summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink')
-rw-r--r--chromium/third_party/blink/API_OWNERS2
-rw-r--r--chromium/third_party/blink/OWNERS3
-rwxr-xr-xchromium/third_party/blink/PRESUBMIT_test.py2
-rw-r--r--chromium/third_party/blink/common/BUILD.gn18
-rw-r--r--chromium/third_party/blink/common/DEPS4
-rw-r--r--chromium/third_party/blink/common/OWNERS1
-rw-r--r--chromium/third_party/blink/common/associated_interfaces/associated_interface_provider.cc38
-rw-r--r--chromium/third_party/blink/common/feature_policy/document_policy.cc126
-rw-r--r--chromium/third_party/blink/common/feature_policy/feature_policy.cc2
-rw-r--r--chromium/third_party/blink/common/feature_policy/feature_policy_mojom_traits.h3
-rw-r--r--chromium/third_party/blink/common/feature_policy/feature_policy_unittest.cc2
-rw-r--r--chromium/third_party/blink/common/feature_policy/policy_value.cc12
-rw-r--r--chromium/third_party/blink/common/features.cc80
-rw-r--r--chromium/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc3
-rw-r--r--chromium/third_party/blink/common/http/structured_header.cc (renamed from chromium/third_party/blink/common/web_package/http_structured_header.cc)6
-rw-r--r--chromium/third_party/blink/common/http/structured_header_corpus/1.txt (renamed from chromium/third_party/blink/common/web_package/http_structured_header_corpus/1.txt)0
-rw-r--r--chromium/third_party/blink/common/http/structured_header_corpus/2.txt (renamed from chromium/third_party/blink/common/web_package/http_structured_header_corpus/2.txt)0
-rw-r--r--chromium/third_party/blink/common/http/structured_header_corpus/3.txt (renamed from chromium/third_party/blink/common/web_package/http_structured_header_corpus/3.txt)0
-rw-r--r--chromium/third_party/blink/common/http/structured_header_corpus/4.txt (renamed from chromium/third_party/blink/common/web_package/http_structured_header_corpus/4.txt)0
-rw-r--r--chromium/third_party/blink/common/http/structured_header_corpus/5.txt (renamed from chromium/third_party/blink/common/web_package/http_structured_header_corpus/5.txt)0
-rw-r--r--chromium/third_party/blink/common/http/structured_header_fuzzer.cc (renamed from chromium/third_party/blink/common/web_package/http_structured_header_fuzzer.cc)2
-rw-r--r--chromium/third_party/blink/common/http/structured_header_unittest.cc (renamed from chromium/third_party/blink/common/web_package/http_structured_header_unittest.cc)2
-rw-r--r--chromium/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/common/indexeddb/indexeddb_key_path.cc6
-rw-r--r--chromium/third_party/blink/common/indexeddb/indexeddb_metadata.cc14
-rw-r--r--chromium/third_party/blink/common/loader/mime_sniffing_throttle.cc66
-rw-r--r--chromium/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc516
-rw-r--r--chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc373
-rw-r--r--chromium/third_party/blink/common/loader/request_destination.cc4
-rw-r--r--chromium/third_party/blink/common/loader/url_loader_factory_bundle.cc28
-rw-r--r--chromium/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc14
-rw-r--r--chromium/third_party/blink/common/loader/url_loader_throttle.cc4
-rw-r--r--chromium/third_party/blink/common/logging/logging_utils.cc2
-rw-r--r--chromium/third_party/blink/common/manifest/manifest.cc4
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_util.cc25
-rw-r--r--chromium/third_party/blink/common/manifest/manifest_util_unittest.cc35
-rw-r--r--chromium/third_party/blink/common/mediastream/media_devices.cc7
-rw-r--r--chromium/third_party/blink/common/messaging/cloneable_message.cc21
-rw-r--r--chromium/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/common/messaging/transferable_message.cc5
-rw-r--r--chromium/third_party/blink/common/notifications/notification_mojom_traits.cc1
-rw-r--r--chromium/third_party/blink/common/notifications/platform_notification_data.cc4
-rw-r--r--chromium/third_party/blink/common/origin_policy/origin_policy_unittest.cc2
-rw-r--r--chromium/third_party/blink/common/page/page_zoom.cc41
-rw-r--r--chromium/third_party/blink/common/peerconnection/webrtc_ip_handling_policy.cc17
-rw-r--r--chromium/third_party/blink/common/privacy_preferences.cc14
-rw-r--r--chromium/third_party/blink/common/scheduler/OWNERS1
-rw-r--r--chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc82
-rw-r--r--chromium/third_party/blink/common/service_worker/service_worker_utils.cc24
-rw-r--r--chromium/third_party/blink/manual_tests/compositing/resources/composited-subframe.html6
-rw-r--r--chromium/third_party/blink/public/BUILD.gn72
-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.gn17
-rw-r--r--chromium/third_party/blink/public/common/DEPS4
-rw-r--r--chromium/third_party/blink/public/common/associated_interfaces/associated_interface_provider.h37
-rw-r--r--chromium/third_party/blink/public/common/associated_interfaces/associated_interface_registry.h23
-rw-r--r--chromium/third_party/blink/public/common/bluetooth/web_bluetooth_device_id_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/css/navigation_controls.h18
-rw-r--r--chromium/third_party/blink/public/common/feature_policy/document_policy.h136
-rw-r--r--chromium/third_party/blink/public/common/feature_policy/feature_policy.h3
-rw-r--r--chromium/third_party/blink/public/common/feature_policy/policy_value.h16
-rw-r--r--chromium/third_party/blink/public/common/features.h25
-rw-r--r--chromium/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h17
-rw-r--r--chromium/third_party/blink/public/common/fetch/fetch_api_request_headers_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/frame/sandbox_flags.h1
-rw-r--r--chromium/third_party/blink/public/common/http/structured_header.h87
-rw-r--r--chromium/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/indexeddb/indexeddb_key_path.h4
-rw-r--r--chromium/third_party/blink/public/common/indexeddb/indexeddb_metadata.h14
-rw-r--r--chromium/third_party/blink/public/common/loader/loading_behavior_flag.h (renamed from chromium/third_party/blink/public/platform/web_loading_behavior_flag.h)26
-rw-r--r--chromium/third_party/blink/public/common/loader/mime_sniffing_throttle.h42
-rw-r--r--chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h159
-rw-r--r--chromium/third_party/blink/public/common/loader/url_loader_factory_bundle.h29
-rw-r--r--chromium/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h9
-rw-r--r--chromium/third_party/blink/public/common/loader/url_loader_throttle.h5
-rw-r--r--chromium/third_party/blink/public/common/logging/logging_utils.h3
-rw-r--r--chromium/third_party/blink/public/common/manifest/display_mode.typemap11
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest.h6
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/manifest/manifest_util.h16
-rw-r--r--chromium/third_party/blink/public/common/manifest/web_display_mode.h28
-rw-r--r--chromium/third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h58
-rw-r--r--chromium/third_party/blink/public/common/mediastream/media_devices.h4
-rw-r--r--chromium/third_party/blink/public/common/mediastream/media_stream_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/messaging/cloneable_message.h5
-rw-r--r--chromium/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h4
-rw-r--r--chromium/third_party/blink/public/common/messaging/transferable_message.h4
-rw-r--r--chromium/third_party/blink/public/common/navigation/triggering_event_info.h (renamed from chromium/third_party/blink/public/web/web_triggering_event_info.h)11
-rw-r--r--chromium/third_party/blink/public/common/notifications/notification_constants.h26
-rw-r--r--chromium/third_party/blink/public/common/notifications/notification_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/public/common/notifications/platform_notification_data.h5
-rw-r--r--chromium/third_party/blink/public/common/page/page_zoom.h26
-rw-r--r--chromium/third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h33
-rw-r--r--chromium/third_party/blink/public/common/plugin/plugin_action.h (renamed from chromium/third_party/blink/public/web/web_plugin_action.h)10
-rw-r--r--chromium/third_party/blink/public/common/presentation/presentation_receiver_flags.h (renamed from chromium/third_party/blink/public/web/web_presentation_receiver_flags.h)8
-rw-r--r--chromium/third_party/blink/public/common/privacy_preferences.h30
-rw-r--r--chromium/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h13
-rw-r--r--chromium/third_party/blink/public/common/security/security_style.h17
-rw-r--r--chromium/third_party/blink/public/common/sudden_termination_disabler_type.h18
-rw-r--r--chromium/third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h31
-rw-r--r--chromium/third_party/blink/public/common/web_package/http_structured_header.h43
-rw-r--r--chromium/third_party/blink/public/common/web_package/signed_exchange_request_matcher.h2
-rw-r--r--chromium/third_party/blink/public/mojom/BUILD.gn7
-rw-r--r--chromium/third_party/blink/public/mojom/appcache/appcache.mojom3
-rw-r--r--chromium/third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/badging/badging.mojom8
-rw-r--r--chromium/third_party/blink/public/mojom/blob/blob.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/blob/blob_url_store.mojom7
-rw-r--r--chromium/third_party/blink/public/mojom/blob/data_element.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/blob/serialized_blob.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom12
-rw-r--r--chromium/third_party/blink/public/mojom/cache_storage/cache_storage.mojom32
-rw-r--r--chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/content_index/content_index.mojom5
-rw-r--r--chromium/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom15
-rw-r--r--chromium/third_party/blink/public/mojom/feature_policy/PRESUBMIT.py2
-rw-r--r--chromium/third_party/blink/public/mojom/feature_policy/feature_policy.mojom162
-rw-r--r--chromium/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom142
-rw-r--r--chromium/third_party/blink/public/mojom/feature_policy/policy_value.mojom28
-rw-r--r--chromium/third_party/blink/public/mojom/fetch/fetch_api_response.mojom13
-rw-r--r--chromium/third_party/blink/public/mojom/filesystem/file_system.mojom25
-rw-r--r--chromium/third_party/blink/public/mojom/frame/document_interface_broker.mojom25
-rw-r--r--chromium/third_party/blink/public/mojom/frame/frame.mojom35
-rw-r--r--chromium/third_party/blink/public/mojom/frame/fullscreen.mojom12
-rw-r--r--chromium/third_party/blink/public/mojom/hid/hid.mojom6
-rw-r--r--chromium/third_party/blink/public/mojom/indexeddb/indexeddb.mojom18
-rw-r--r--chromium/third_party/blink/public/mojom/installedapp/OWNERS3
-rw-r--r--chromium/third_party/blink/public/mojom/installedapp/installed_app_provider.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/installedapp/related_application.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/leak_detector/leak_detector.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/manifest/display_mode.mojom18
-rw-r--r--chromium/third_party/blink/public/mojom/media_controls/touchless/OWNERS5
-rw-r--r--chromium/third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom46
-rw-r--r--chromium/third_party/blink/public/mojom/messaging/cloneable_message.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom7
-rw-r--r--chromium/third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom7
-rw-r--r--chromium/third_party/blink/public/mojom/payments/payment_app.mojom24
-rw-r--r--chromium/third_party/blink/public/mojom/payments/payment_handler_host.mojom36
-rw-r--r--chromium/third_party/blink/public/mojom/portal/portal.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/renderer_preferences.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/serial/serial.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom22
-rw-r--r--chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom32
-rw-r--r--chromium/third_party/blink/public/mojom/service_worker/service_worker_client.mojom11
-rw-r--r--chromium/third_party/blink/public/mojom/service_worker/service_worker_object.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/service_worker/service_worker_state.mojom2
-rw-r--r--chromium/third_party/blink/public/mojom/speech/speech_recognizer.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/use_counter/css_property_id.mojom1
-rw-r--r--chromium/third_party/blink/public/mojom/web_feature/web_feature.mojom40
-rw-r--r--chromium/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom4
-rw-r--r--chromium/third_party/blink/public/mojom/worker/subresource_loader_updater.mojom16
-rw-r--r--chromium/third_party/blink/public/platform/DEPS1
-rw-r--r--chromium/third_party/blink/public/platform/TaskTypes.md118
-rw-r--r--chromium/third_party/blink/public/platform/interface_provider.h6
-rw-r--r--chromium/third_party/blink/public/platform/interface_registry.h37
-rw-r--r--chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_decoding_info.h22
-rw-r--r--chromium/third_party/blink/public/platform/modules/notifications/OWNERS4
-rw-r--r--chromium/third_party/blink/public/platform/modules/notifications/web_notification_constants.h38
-rw-r--r--chromium/third_party/blink/public/platform/modules/peerconnection/DEPS1
-rw-r--r--chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h29
-rw-r--r--chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h29
-rw-r--r--chromium/third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h1
-rw-r--r--chromium/third_party/blink/public/platform/platform.h76
-rw-r--r--chromium/third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h5
-rw-r--r--chromium/third_party/blink/public/platform/scheduler/web_thread_scheduler.h10
-rw-r--r--chromium/third_party/blink/public/platform/web_cache.h21
-rw-r--r--chromium/third_party/blink/public/platform/web_content_decryption_module_exception.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h11
-rw-r--r--chromium/third_party/blink/public/platform/web_fetch_client_settings_object.h53
-rw-r--r--chromium/third_party/blink/public/platform/web_http_body.h14
-rw-r--r--chromium/third_party/blink/public/platform/web_localized_string.h179
-rw-r--r--chromium/third_party/blink/public/platform/web_media_player.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_media_player_client.h23
-rw-r--r--chromium/third_party/blink/public/platform/web_mouse_wheel_event.h24
-rw-r--r--chromium/third_party/blink/public/platform/web_rtc_certificate_generator.h82
-rw-r--r--chromium/third_party/blink/public/platform/web_rtc_rtp_source.h2
-rw-r--r--chromium/third_party/blink/public/platform/web_runtime_features.h21
-rw-r--r--chromium/third_party/blink/public/platform/web_security_style.h17
-rw-r--r--chromium/third_party/blink/public/platform/web_source_buffer_client.h6
-rw-r--r--chromium/third_party/blink/public/platform/web_string.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_sudden_termination_disabler_type.h18
-rw-r--r--chromium/third_party/blink/public/platform/web_theme_engine.h25
-rw-r--r--chromium/third_party/blink/public/platform/web_transmission_encoding_info_handler.h38
-rw-r--r--chromium/third_party/blink/public/platform/web_url_loader.h4
-rw-r--r--chromium/third_party/blink/public/platform/web_url_loader_client.h1
-rw-r--r--chromium/third_party/blink/public/platform/web_url_request.h20
-rw-r--r--chromium/third_party/blink/public/platform/web_url_response.h21
-rw-r--r--chromium/third_party/blink/public/public_features.gni4
-rw-r--r--chromium/third_party/blink/public/public_typemaps.gni1
-rw-r--r--chromium/third_party/blink/public/strings/BUILD.gn66
-rw-r--r--chromium/third_party/blink/public/strings/blink_strings.grd1106
-rw-r--r--chromium/third_party/blink/public/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha11
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb269
-rw-r--r--chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb269
-rw-r--r--chromium/third_party/blink/public/web/DEPS2
-rw-r--r--chromium/third_party/blink/public/web/blink.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h8
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h4
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/DEPS18
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h129
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h2
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h89
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/mock_data_channel_impl.h59
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h177
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h391
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h103
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h191
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h179
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h197
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h195
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h117
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h153
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h155
-rw-r--r--chromium/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h49
-rw-r--r--chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h14
-rw-r--r--chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h2
-rw-r--r--chromium/third_party/blink/public/web/web_ax_enums.h7
-rw-r--r--chromium/third_party/blink/public/web/web_ax_object.h4
-rw-r--r--chromium/third_party/blink/public/web/web_device_emulation_params.h7
-rw-r--r--chromium/third_party/blink/public/web/web_document.h1
-rw-r--r--chromium/third_party/blink/public/web/web_document_loader.h10
-rw-r--r--chromium/third_party/blink/public/web/web_embedded_worker.h28
-rw-r--r--chromium/third_party/blink/public/web/web_embedded_worker_start_data.h12
-rw-r--r--chromium/third_party/blink/public/web/web_frame.h9
-rw-r--r--chromium/third_party/blink/public/web/web_fullscreen_options.h23
-rw-r--r--chromium/third_party/blink/public/web/web_local_frame.h29
-rw-r--r--chromium/third_party/blink/public/web/web_local_frame_client.h73
-rw-r--r--chromium/third_party/blink/public/web/web_navigation_params.h16
-rw-r--r--chromium/third_party/blink/public/web/web_plugin.h2
-rw-r--r--chromium/third_party/blink/public/web/web_print_scaling_option.h4
-rw-r--r--chromium/third_party/blink/public/web/web_render_theme.h2
-rw-r--r--chromium/third_party/blink/public/web/web_settings.h9
-rw-r--r--chromium/third_party/blink/public/web/web_view.h22
-rw-r--r--chromium/third_party/blink/public/web/web_view_client.h8
-rw-r--r--chromium/third_party/blink/public/web/web_widget.h12
-rw-r--r--chromium/third_party/blink/public/web/web_widget_client.h14
-rw-r--r--chromium/third_party/blink/renderer/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/bindings/BUILD.gn28
-rw-r--r--chromium/third_party/blink/renderer/bindings/bindings.gni9
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/boxed_v8_module.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_pop_state_event_custom.cc8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc64
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc64
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.cc180
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h35
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/iterable.h19
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc9
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc16
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/maplike.h5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/module_record.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/module_record.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/profiler_trace_builder.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc12
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc44
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h32
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.cc82
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.h61
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc40
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_value.h113
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc15
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.cc32
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc45
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.cc7
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h23
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc7
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc12
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc19
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc31
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h15
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc19
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc29
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h46
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference_test.cc63
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni14
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.cc8
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc42
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf3
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py53
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py59
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py502
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py118
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/example.py39
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py68
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py11
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/collect_idl_files.py21
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py61
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps59
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/generate_v8_context_snapshot_external_references.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_types.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py9
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py6
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py8
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_types.py14
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py114
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py31
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py26
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/literal_constant.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py108
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl9
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/external_reference_table.cc.tmpl3
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl108
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl3
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl4
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl36
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl3
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/element_lookup_trie.cc.tmpl6
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/feature_policy_helper.cc.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/probe_sink.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_initializer.cc11
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_leak_detector.cc2
-rw-r--r--chromium/third_party/blink/renderer/controller/dev_tools_frontend_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/BUILD.gn24
-rw-r--r--chromium/third_party/blink/renderer/core/DEPS8
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/BUILD.gn11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animatable.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animatable.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animatable.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.cc441
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.h37
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect.h12
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test.cc131
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_time_delta.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.h12
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc274
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h15
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_type.h14
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_length_interpolation_type.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc233
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.h6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_input.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_input_test.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_model.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_model.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc264
-rw-r--r--chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.h33
-rw-r--r--chromium/third_party/blink/renderer/core/animation/get_animations_options.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/animation/inert_effect.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/inert_effect.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_filter.cc245
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_filter.h80
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_length.cc271
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_length.h56
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_shadow.cc202
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_shadow.h94
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h71
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_value.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolable_value.h107
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolation.h3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolation_effect.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/interpolation_value.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.h4
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.h10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pairwise_interpolation_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pending_animations.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/sampled_effect.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.cc195
-rw-r--r--chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.h40
-rw-r--r--chromium/third_party/blink/renderer/core/animation/size_interpolation_functions.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/animation/string_keyframe.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing.h13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_calculations.h113
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_calculations_test.cc282
-rw-r--r--chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/BUILD.gn15
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/README.md3
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc (renamed from chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc)53
-rw-r--r--chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h (renamed from chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h)12
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h2
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object.h2
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object_item.h4
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/sent_nodes.h2
-rw-r--r--chromium/third_party/blink/renderer/core/content_capture/task_session.h4
-rw-r--r--chromium/third_party/blink/renderer/core/context_features/context_feature_settings.h2
-rw-r--r--chromium/third_party/blink/renderer/core/core.gni36
-rw-r--r--chromium/third_party/blink/renderer/core/core_idl_files.gni13
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/BUILD.gn17
-rw-r--r--chromium/third_party/blink/renderer/core/css/binary_data_font_face_source.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css.dict1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_default_style_sheets.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face.h4
-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_source_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.h52
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.idl14
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_global_rule_set.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_generator_value.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_generator_value.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_set_value.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_image_value.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h31
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc209
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node.h66
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_expression_node_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_function_value.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_math_function_value.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_image_generator.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value.cc128
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value.h28
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_paint_value_test.cc227
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h31
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_properties.json516
-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.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_value_set.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_resource_fetch_restriction.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_segmented_font_face.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector_watch.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_id_mappings.h248
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_keywords.json54
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_pair.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_pool.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h12
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_deferred_image.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/css/element_rule_collector.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/element_rule_collector.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_cache.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/fullscreen.css15
-rw-r--r--chromium/third_party/blink/renderer/core/css/fullscreenAndroid.css2
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/layout_tree_rebuild_root.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_overrides.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_overrides.h27
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_feature_overrides_test.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_evaluator_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_exp.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_matcher.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values.h16
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_values_cached.h7
-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.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h56
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc5
-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_lazy_parsing_state.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.h19
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.cc (renamed from chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.cc)68
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h (renamed from chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.h)22
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc (renamed from chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser_test.cc)24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc219
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registration.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/pseudo_style_request.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/font_builder.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/font_builder.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/font_builder_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h15
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_set.cc10
-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.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_checker.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.cc189
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.h39
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine_test.cc231
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_invalidation_root.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_recalc_root.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule.h39
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_import.h2
-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.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_contents.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_traversal_root.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/touchless.css31
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock.dict16
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc333
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h101
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.idl27
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc361
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc107
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities.h8
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc145
-rw-r--r--chromium/third_party/blink/renderer/core/dom/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/aria_attributes.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/context_features.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/context_features_client_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc730
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h74
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_init.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser_timing.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_token_list.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_token_list.h11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc698
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.h31
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_data.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_rare_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/custom_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_path.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_path.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/native_event_listener.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_node_data.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc2
-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/global_event_handlers.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/id_target_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/live_node_list_registry_test.cc4
-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_interest_group.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_notifier.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/node.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.h12
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_rare_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_test.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/dom/presentation_attribute_style.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/qualified_name.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/space_split_string.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/text_link_colors.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_ordered_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/visited_link_state.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/BUILD.gn10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/edit_command.h2
-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/indent_outdent_command.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/undo_step.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/drag_caret.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_utilities.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/element_inner_text.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_task_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.h5
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_caret.h3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.h8
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection.cc124
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_list.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h41
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h38
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h36
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h58
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.h10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h32
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_editor.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/events/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/events/application_cache_error_event.h2
-rw-r--r--chromium/third_party/blink/renderer/core/events/error_event.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/events/event_type_names.json52
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event.h19
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/events/wheel_event.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent.h2
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc119
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h77
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc183
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.h5
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.cc2
-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/window_agent.h13
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h23
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc18
-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.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_element_observer_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_test.cc626
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_layer_test.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_meta_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_option_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h10
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_render_theme.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_searchable_form_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_select_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.h7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc216
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.h26
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_test.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json526
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h2
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc115
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.h3
-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_manager.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h39
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h12
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer_test.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/global_fetch.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/multipart_parser.h2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/multipart_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.h4
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.h12
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.h4
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h8
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.h2
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_registry.h7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive.h3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_source.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_timer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/event_handler_registry.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/find_in_page.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/fragment_directive.h21
-rw-r--r--chromium/third_party/blink/renderer/core/frame/fragment_directive.idl (renamed from chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl)6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_client.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_console.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_overlay.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_overlay.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_owner.h41
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_serializer.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/link_highlights.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/frame/link_highlights.h92
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.cc202
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.h31
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_back_forward_cache_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client.h54
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_test.cc147
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.cc243
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.h41
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h2
-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.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/scheduling.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.json555
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/viewport_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/viewport_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.cc196
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.h33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h293
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h12
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h9
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/html/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h15
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_queue.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_test_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.h18
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/element_internals.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_queue_base.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_step.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_processing_step.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_resource_loader.h9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_client.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_input_type.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_chooser.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_chooser_impl.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h16
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/email_input_type.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser_test.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_chooser.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_controller.cc228
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_controller.h35
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_controller_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_button_element.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_button_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_options_collection.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc118
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/mock_file_chooser.h38
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc15
-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/number_input_type.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/option_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/password_input_type_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/popup_menu.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/range_input_type.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/reset_input_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/.clang-format1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.css2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js863
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/calendar_picker_refresh.css227
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.css90
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/colorSuggestionPicker.js116
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.css36
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js636
-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/listPicker.js115
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js135
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js43
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.css36
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/suggestionPicker.js130
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.css94
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.js538
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/url_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_collection.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_details_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_dialog_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_embed_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h12
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_hr_element.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_html_element.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_html_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_li_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meter_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_or_foreign_element.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_progress_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_progress_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_source_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_style_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import_loader.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc251
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h13
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc258
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_resource.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_audio_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.cc92
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.h20
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_source.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_controls.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_filling_viewport_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/video_wake_lock_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_scheduler.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_stack_item.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/OWNERS6
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/document_portals.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/document_portals.h45
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.cc169
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.h35
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc (renamed from chromium/third_party/blink/renderer/core/events/portal_activate_event.cc)10
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.h (renamed from chromium/third_party/blink/renderer/core/events/portal_activate_event.h)8
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.idl (renamed from chromium/third_party/blink/renderer/core/events/portal_activate_event.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl (renamed from chromium/third_party/blink/renderer/core/events/portal_activate_event_init.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc161
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_contents.h121
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_host.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_host.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css56
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/forced_colors.css79
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/html.css24
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg2
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_off.svg4
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_on.svg2
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/images/time_icon.svg3
-rw-r--r--chromium/third_party/blink/renderer/core/html/resources/win.css2
-rw-r--r--chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/cue_timeline.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/html_track_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.h22
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.h15
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h22
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h9
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.h7
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler_test.cc132
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h4
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc142
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_event_manager.h10
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.h4
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.h8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl130
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/console_message.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_agent.h13
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_session.cc84
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/devtools_session.h28
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_patch_support.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspected_frames.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_base_agent.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc55
-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.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_history.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_container.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_resource_content_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/legacy_dom_snapshot_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.h6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/thread_debugger.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/BUILD.gn31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc)81
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h)28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_cache.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_canvas_result.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc129
-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.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_counter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc)72
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h)29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_embedded_content.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_box.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_item.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_set.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.cc148
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.h30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_progress.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_progress.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_replaced.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_replaced.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_region.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.cc172
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker.h34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.cc121
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.h51
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.h31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mobile.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_win.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_win.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_video.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.h5
-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_text_box.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/list_marker_text.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/document_layout_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h97
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc482
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h148
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc214
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc558
-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_height_metrics.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.cc169
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_break_token.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc940
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h154
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc159
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h80
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_break_appeal.h38
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_break_token.h21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc164
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc1384
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h77
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_early_break.h55
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result.h104
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h45
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_space_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/order_iterator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.h35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_text_layout_engine.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/transform_helper.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/transform_helper.h71
-rw-r--r--chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.cc411
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.h93
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.h23
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.h17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc250
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.h36
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader_state_machine.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/history_item.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_refresh_scheduler.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/importance_attribute.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/importance_attribute.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_load_parameters.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_load_parameters.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/loader/loader_factory_for_worker.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/long_task_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/long_task_detector_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/loader/prefetched_signed_exchange_manager.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/preload_helper.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/loader/preload_helper.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h42
-rw-r--r--chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/multipart_image_resource_parser_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.h15
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_filter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_filter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/text_track_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/text_track_loader.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threaded_icon_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/web_associated_url_loader_impl_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h4
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.h4
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h5
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message.h4
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.h2
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h76
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context.h2
-rw-r--r--chromium/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/page/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.h16
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_provider.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/page/link_highlight.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/page/link_highlight.h72
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.cc123
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.h27
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/plugin_data.h9
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc10
-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/fragment_anchor.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h6
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.h24
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc314
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h36
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc267
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc146
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h18
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h29
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics_test.cc182
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_test.cc451
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h14
-rw-r--r--chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_rects_cache.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc287
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h31
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc211
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.cc (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.cc)123
-rw-r--r--chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.h (renamed from chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h)43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_painter.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_element_timing.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_element_timing.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_element_timing_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc3
-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.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_painter.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/line_box_list_painter.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc271
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc266
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc142
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc112
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h53
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc180
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc323
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h47
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_info.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.h25
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_resource_info.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc293
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h44
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h13
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc488
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_phase.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_detector.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing_test_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_element_timing.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_element_timing.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector_test.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm38
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler_integration_tests/scheduler_affecting_features_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/script/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_write_intervention.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h7
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map.cc430
-rw-r--r--chromium/third_party/blink/renderer/core/script/import_map.h55
-rw-r--r--chromium/third_party/blink/renderer/core/script/js_module_script.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/layered_api.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/script/mock_script_element_base.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.h12
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.h1
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_record_resolver_impl_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/parsed_specifier.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/script/parsed_specifier.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_import_map.h9
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.h14
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs44
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs120
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs27
-rw-r--r--chromium/third_party/blink/renderer/core/script/script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.h9
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.h21
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/xml_parser_script_runner.h2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/programmatic_scroll_animator.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator.h4
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.h10
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_animator_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scroll_types.h2
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area.h16
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollable_area_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar.h11
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc103
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h7
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_test_suite.h7
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc206
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.h75
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h17
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h20
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.mm18
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.h10
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h12
-rw-r--r--chromium/third_party/blink/renderer/core/streams/BUILD.gn10
-rw-r--r--chromium/third_party/blink/renderer/core/streams/ByteLengthQueuingStrategy.js31
-rw-r--r--chromium/third_party/blink/renderer/core/streams/CommonOperations.js624
-rw-r--r--chromium/third_party/blink/renderer/core/streams/CommonStrings.js24
-rw-r--r--chromium/third_party/blink/renderer/core/streams/CountQueuingStrategy.js47
-rw-r--r--chromium/third_party/blink/renderer/core/streams/README.md35
-rw-r--r--chromium/third_party/blink/renderer/core/streams/ReadableStream.js1145
-rw-r--r--chromium/third_party/blink/renderer/core/streams/SimpleQueue.js152
-rw-r--r--chromium/third_party/blink/renderer/core/streams/TransformStream.js498
-rw-r--r--chromium/third_party/blink/renderer/core/streams/WritableStream.js1093
-rw-r--r--chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/queue_with_sizes.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/queue_with_sizes.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc106
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_reader.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc239
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_native.h14
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc392
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h172
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc627
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_test.cc107
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc439
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.h125
-rw-r--r--chromium/third_party/blink/renderer/core/streams/stream_algorithms.h8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/stream_promise_resolver.h4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transferable_streams_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream.h1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h38
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc294
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_native.h8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc226
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_transformer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc222
-rw-r--r--chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h59
-rw-r--r--chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.h10
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h3
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc160
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_native.h22
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc253
-rw-r--r--chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h93
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.h102
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_diff_functions.json512
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_extra_fields.json532
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/style/content_data.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/style/content_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/counter_content.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/filter_operation.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/shape_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image.h6
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_fetched_image_set.h1
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_generated_image.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_generated_image.h3
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/BUILD.gn9
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc127
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h108
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_repeat_count.h63
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time.h229
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc286
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.h55
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc1041
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.h128
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/linear_gradient_attributes.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_property.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/radial_gradient_attributes.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_a_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_element.h14
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_integer_optional_integer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_number_optional_number.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_path.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_point_list.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animation_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_attribute_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_discard_element.h3
-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.cc302
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_element_rare_data.h3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element_test.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_image_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_svg_element.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.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_view_spec.h2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/compositor-worker-basic.html28
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/editable_elements.html7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/fullscreen_style.html2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/fullscreen_video.html8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/rgm_test.html2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight.html10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html20
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/webxr_overlay.html17
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h36
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internal_settings.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internal_settings.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.h2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.h7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/page_test_base.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/testing/page_test_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h19
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/timezone/timezone_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/internals_profiler.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/timing/internals_profiler.h24
-rw-r--r--chromium/third_party/blink/renderer/core/timing/internals_profiler.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/layout_shift.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_entry.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.cc163
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.h10
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.idl23
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_element_timing.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_mark.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_mark.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_measure.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_measure.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h25
-rw-r--r--chromium/third_party/blink/renderer/core/timing/task_attribution_timing.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/README.md90
-rw-r--r--chromium/third_party/blink/renderer/core/workers/abstract_worker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h15
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h10
-rw-r--r--chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.h6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.h53
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl7
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_reporting_proxy.h10
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.h15
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.h3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.h5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.h3
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_expression_node.h2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_step.h2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_value.h2
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h2
-rw-r--r--chromium/third_party/blink/renderer/devtools/.eslintignore6
-rw-r--r--chromium/third_party/blink/renderer/devtools/.eslintrc.js182
-rw-r--r--chromium/third_party/blink/renderer/devtools/BUILD.gn3180
-rw-r--r--chromium/third_party/blink/renderer/devtools/OWNERS9
-rw-r--r--chromium/third_party/blink/renderer/devtools/PRESUBMIT.py34
-rw-r--r--chromium/third_party/blink/renderer/devtools/docs/langpacks/README.md6
-rw-r--r--chromium/third_party/blink/renderer/devtools/docs/langpacks/adding_strings.md116
-rw-r--r--chromium/third_party/blink/renderer/devtools/docs/langpacks/grdp_files.md41
-rw-r--r--chromium/third_party/blink/renderer/devtools/docs/langpacks/localization_apis.md44
-rw-r--r--chromium/third_party/blink/renderer/devtools/docs/langpacks/locked_terms.md25
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg77
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.pngbin12268 -> 12067 bytes
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Runtime.js358
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Tests.js158
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAAttributesView.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAMetadata.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/AXBreadcrumbsPane.js124
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityModel.js53
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js112
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilitySidebarView.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationGroupPreviewUI.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationModel.js83
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationScreenshotPopover.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationTimeline.js119
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationUI.js67
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/AppcacheTestRunner.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/CacheStorageTestRunner.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/IndexedDBTestRunner.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourcesTestRunner.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsController.js36
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsPanel.js35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsProtocolService.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportRenderer.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportSelector.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStartView.js17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStatusView.js75
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/RadioSetting.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp102
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report-generator.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.css14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.js456
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/template.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/templates.html78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_test_runner/AuditsTestRunner.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/AuditsService.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/README.chromium4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js6882
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar-XB.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/bg.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ca.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/cs.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/da.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/de.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/el.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-GB.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-US.json1634
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XA.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XL.json1634
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es-419.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fi.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fil.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fr.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/he.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hi.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hr.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hu.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/id.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/it.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ja.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ko.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lt.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lv.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/nl.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/no.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pl.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt-PT.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ro.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ru.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sk.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sl.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr-Latn.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sv.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ta.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/te.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/th.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/tr.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/uk.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/vi.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-HK.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-TW.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh.json1541
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/axe_core_test_runner/AxeCoreTestRunner.js57
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/BlackboxManager.js106
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/BreakpointManager.js253
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/CSSWorkspaceBinding.js116
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/CompilerScriptMapping.js98
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/ContentProviderBasedProject.js50
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/DebuggerWorkspaceBinding.js131
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/DefaultScriptMapping.js58
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/FileUtils.js77
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/LiveLocation.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js81
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/PresentationConsoleMessageHelper.js94
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceMapping.js183
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceScriptMapping.js139
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceUtils.js76
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/SASSSourceMapping.js42
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/StylesSourceMapping.js82
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/TempFile.js49
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings.js44
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/BindingsTestRunner.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/DOMBreakpointsSidebarPane.js46
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js61
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/ObjectEventListenersSidebarPane.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/XHRBreakpointsSidebarPane.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesHighlighter.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js70
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/cm_modes/DefaultCodeMirrorMimeMode.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastInfo.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastOverlay.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js270
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/App.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/AppProvider.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Color.js354
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Console.js56
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/EventTarget.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js40
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Linkifier.js43
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js152
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Object.js98
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js101
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Progress.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js202
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Revealer.js63
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Runnable.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js198
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/common/OutputStream.js)31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Throttler.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Trie.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/UIString.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Worker.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/common.js63
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/common_strings.grdp51
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/module.json22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/DockController.js80
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js46
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/JSPresentationUtils.js35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/Linkifier.js372
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/Reload.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/TargetDetachedDialog.js22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/components.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/components/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleFilter.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePanel.js11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js48
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js91
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleSidebar.js93
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js145
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js413
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewport.js130
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp111
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console_counters/WarningErrorCounter.js47
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console_counters/console_counters.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console_counters/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js102
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/cookie_table/CookiesTable.js316
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageDecorationManager.js214
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageListView.js70
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js373
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js142
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/coverageListView.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/cpu_profiler_test_runner/ProfilerTestRunner.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewCompletedView.js260
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewController.js25
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewModel.js136
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewPanel.js173
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewProcessingView.js44
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewSidebarPanel.js77
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewStartView.js34
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverview.css9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewCompletedView.css92
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewProcessingView.css33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewSidebarPanel.css33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewStartView.css29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/css_overview_strings.grdp66
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/css_overview/module.json35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/LICENSE (renamed from chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/LICENSE)5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/README.md16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/dagre.js11500
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/module.json8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js556
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid/ShowMoreDataGridNode.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid/SortableDataGrid.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid/ViewportDataGrid.js145
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js118
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_app.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_app.json5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js106
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/diff/Diff.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js214
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/dom_extension/module.json3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ClassesPaneWidget.js57
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ColorSwatchPopoverIcon.js45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleModel.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/DOMPath.js103
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementStatePaneWidget.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsBreadcrumbs.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js230
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsSidebarPane.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js352
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElementHighlighter.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js417
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/EventListenersWidget.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/InspectElementModeController.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/MarkerDecorator.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/MetricsSidebarPane.js79
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/PlatformFontsWidget.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js69
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyHighlighter.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js285
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js519
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/elementsTreeOutline.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp51
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/EditDOMTestRunner.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js220
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp60
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js96
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js94
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeWrapper.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DevicesSettingsTab.js40
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/EmulatedDevices.js84
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/GeolocationsSettingsTab.js79
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/InspectedPagePlaceholder.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/MediaQueryInspector.js90
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js86
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp70
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/geolocationsSettingsTab.css97
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/module.json26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/sensors.css249
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersUtils.js74
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersView.js132
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/event_listeners/eventListenersView.css18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionAPI.js154
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionPanel.js53
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js228
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionTraceProvider.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionView.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/extensions.js16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/externs.js436
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter/ScriptFormatter.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSFormatter.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSRuleParser.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/ESTreeWalker.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormattedContentBuilder.js35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js131
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/HTMLFormatter.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js178
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js41
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/RelaxedJSONParser.js17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js9516
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js2548
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARFormat.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js61
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js84
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js66
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/AllocationProfile.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js369
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js34
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/help/Help.js16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteText.js44
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js120
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js334
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/Platform.js86
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js91
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js55
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/host.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierEditor.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierUI.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowEditor.js54
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowModel.js43
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/ColorSwatch.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inline_editor/SwatchPopoverHelper.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector_main/RenderingOptions.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp37
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector_main/renderingOptions.css26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/js_app.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/js_app.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp637
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerDetailsView.js81
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerTreeOutline.js50
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerViewHost.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/Layers3DView.js132
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/PaintProfilerView.js72
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/TransformController.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp104
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layers/LayerPaintProfilerView.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layers/LayerTreeModel.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layers/LayersPanel.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/layers_test_runner/LayersTestRunner.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/main/ExecutionContextSelector.js45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/main/Main.js197
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/main/module.json16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/EventDisplayTable.js154
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/MainView.js141
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/MediaModel.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/MediaTable.js75
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/PlayerDetailView.js47
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/PlayerListView.js155
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/eventDisplayTable.css14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/mediaView.css26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/media_strings.grdp27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/module.json34
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/media/playerListView.css22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js41
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingSettingsTab.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ndb_app.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js51
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/BlockedURLsPane.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/EventSourceMessagesView.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/HARWriter.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkConfigView.js122
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js147
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkFrameGrouper.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkItemView.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js285
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js102
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkManageCustomHeadersView.js17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkOverview.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js99
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js36
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkTimeCalculator.js41
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js50
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestCookiesView.js250
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestHeadersView.js82
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestInitiatorView.js86
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestTimingView.js40
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/module.json2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/networkLogView.css13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp309
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/requestCookiesView.css42
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/requestInitiatorView.css23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_app.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_app.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/CustomPreviewComponent.js43
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js209
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptREPL.js17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js449
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js54
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectValue.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/ChartViewport.js38
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FilmStripView.js37
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js343
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/GCActionDelegate.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/NetworkPriorities.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js114
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/PieChart.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineGrid.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineOverviewPane.js42
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/flameChart.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js69
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js55
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/Automapping.js210
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/EditFileSystemView.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/FileSystemWorkspaceBinding.js124
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js213
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js137
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/NetworkPersistenceManager.js146
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceImpl.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/persistence/Persistence.js)170
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceUtils.js44
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/PlatformFileSystem.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/WorkspaceSettingsTab.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/module.json6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/platform/module.json3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js289
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/product_registry/BadgePool.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/product_registry/ProductRegistry.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/product_registry/badge.css6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/product_registry_impl/ProductRegistryImpl.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/BottomUpProfileDataGrid.js36
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileFlameChart.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js94
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js102
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js139
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotProxy.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js363
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js44
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileDataGrid.js148
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileHeader.js5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js76
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js113
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/TopDownProfileDataGrid.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js383
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol/NodeURL.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol/protocol.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js79
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/quick_open/FilteredListWidget.js97
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/quick_open/HelpQuickOpen.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/quick_open/QuickOpen.js11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheItemsView.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheModel.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationPanelSidebar.js299
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ClearStorageView.js50
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/CookieItemsView.js99
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageItemsView.js57
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageModel.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseModel.js16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseQueryView.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBModel.js63
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js63
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesPanel.js46
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js86
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/cookieItemsView.css12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/module.json3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp38
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/root.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/screencast/InputModel.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastApp.js17
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js124
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js113
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfilerModel.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js237
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMedia.js96
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js125
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSModel.js289
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSProperty.js85
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSRule.js151
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js75
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleSheetHeader.js65
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js49
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CompilerSourceMappingContentProvider.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/sdk/ContentProviders.js)61
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/Connections.js112
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js268
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieModel.js56
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieParser.js157
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js243
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js481
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js463
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/EmulationModel.js193
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/FilmStripModel.js74
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js124
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js119
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/LayerTreeBase.js163
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/LogModel.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js193
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js459
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js444
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js158
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/PaintProfiler.js71
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/PerformanceMetricsModel.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js34
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js443
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/Resource.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js293
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js281
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/SDKModel.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/Script.js91
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/SecurityOriginManager.js36
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ServerTiming.js47
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerCacheModel.js100
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerManager.js193
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js287
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMapManager.js201
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js162
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js142
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingManager.js136
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js394
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/module.json59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk.js115
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp161
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk_test_runner/PageMockTestRunner.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/search/SearchConfig.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/search/SearchResultsPane.js37
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/search/SearchView.js70
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security/SecurityModel.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js133
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security/mainView.css1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security/originView.css25
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/security_test_runner/SecurityTestRunner.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/services/ServiceManager.js116
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/services/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/services/services.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js60
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/shell.json1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/snippets/SnippetsQuickOpen.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/BinaryResourceViewFactory.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js10
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceCodeDiff.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js168
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourcesTextEditor.js187
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js64
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/CSSPlugin.js85
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js56
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPausedMessage.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js437
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/EditingLocationHistoryManager.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/FilePathScoreFunction.js41
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/FilteredUISourceCodeListProvider.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/GoToLineQuickOpen.js27
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/InplaceFormatterEditorAction.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptCompilerPlugin.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js332
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/OpenFileQuickOpen.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/OutlineQuickOpen.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/ScopeChainSidebarPane.js16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptFormatterEditorAction.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptOriginPlugin.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SearchSourcesView.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SimpleHistoryManager.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourceFormatter.js82
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourceMapNamesResolver.js97
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesNavigator.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js223
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesSearchScope.js58
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesView.js190
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/TabbedEditorContainer.js132
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/ThreadsSidebarPane.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/UISourceCodeFrame.js203
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/sourcesPanel.css6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/DebuggerTestRunner.js104
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js23
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/LiveEditTestRunner.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SearchTestRunner.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SourcesTestRunner.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/module.json1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/TerminalWidget.js149
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/module.json31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal.css37
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/README.chromium7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/fit.js86
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/package.json5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.css2248
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.js4318
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js231
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js310
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js102
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_utils/Text.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextRange.js59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextUtils.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/CountersGraph.js69
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/ExtensionTracingSession.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/PerformanceModel.js37
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineDetailsView.js45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineEventOverview.js236
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js212
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartNetworkDataProvider.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartView.js71
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js42
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLayersView.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLoader.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePaintProfilerView.js20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js200
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js197
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js461
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsController.js (renamed from chromium/third_party/blink/renderer/modules/filesystem/file_system_client.h)57
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsUtils.js143
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/module.json5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp104
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineFrameModel.js94
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineIRModel.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineJSProfile.js64
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js434
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModelFilter.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js146
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TracingLayerTree.js58
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/toolbox.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/toolbox.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/toolbox_bootstrap/Toolbox.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js342
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Action.js165
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ActionDelegate.js25
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js178
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Context.js59
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ContextFlavorListener.js22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js223
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Dialog.js22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/DropTarget.js32
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/EmptyWidget.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js155
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/FilterSuggestionBuilder.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js22
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js153
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Geometry.js450
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/GlassPane.js160
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/HistoryInput.js28
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Icon.js72
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Infobar.js51
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/InplaceEditor.js98
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js99
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/KeyboardShortcut.js108
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ListControl.js149
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ListModel.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ListWidget.js112
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js46
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/PopoverHelper.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/ui/Popover.js)66
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ProgressIndicator.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ReportView.js75
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ResizerWidget.js56
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/RootView.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SearchableView.js183
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SegmentedButton.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SettingsUI.js112
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js96
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js152
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js109
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js65
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js227
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js104
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SyntaxHighlighter.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js346
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TargetCrashedScreen.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js113
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js149
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ThrottledWidget.js24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js355
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js79
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Treeoutline.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js)500
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js1040
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/View.js763
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ViewManager.js713
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Widget.js283
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/XElement.js117
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js48
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/XWidget.js67
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ZoomManager.js25
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/closeButton.css8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/infobar.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/module.json13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/tabbedPane.css21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/textButton.css9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ui.js126
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphManager.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphView.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/NodeView.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_app.html4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_app.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_service/ServiceDispatcher.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js47
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace/UISourceCode.js322
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace/WorkspaceImpl.js (renamed from chromium/third_party/blink/renderer/devtools/front_end/workspace/Workspace.js)184
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace/module.json6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace/workspace.js13
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js78
-rw-r--r--chromium/third_party/blink/renderer/devtools/karma.conf.js80
-rw-r--r--chromium/third_party/blink/renderer/devtools/readme.md28
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/README.md3
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/build/build_release_applications.py16
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/build/copy_devtools_modules.py38
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_extension_api.py2
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.js124
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.py53
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/build/modular_build.py2
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/check_localizability.js5
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js72
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/closure/README.md220
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/build_compiler_runner_jar.py2
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/closure_runner.jarbin9986 -> 9964 bytes
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/closure/compiler.jarbin7543861 -> 8010041 bytes
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/compile_frontend.py25
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/devtools_paths.py73
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes4
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jarbin43674 -> 43735 bytes
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/FileCheckerCallable.java3
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/MethodAnnotationChecker.java7
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/lint_javascript.py7
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/local_node.py29
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js206
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js62
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/migration/package.json11
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/migration/refactor-folder-to-es-modules.sh66
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts176
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/migration/tsconfig.json10
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/run_tests.py73
-rw-r--r--chromium/third_party/blink/renderer/devtools/services/devtools.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/services/dispatcher.js130
-rw-r--r--chromium/third_party/blink/renderer/devtools/services/package.json11
-rw-r--r--chromium/third_party/blink/renderer/devtools/services/terminal.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/tsconfig.json7
-rw-r--r--chromium/third_party/blink/renderer/modules/BUILD.gn69
-rw-r--r--chromium/third_party/blink/renderer/modules/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc68
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list_box.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_media_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc188
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc125
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc232
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc69
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc52
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_effect.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/badge.cc98
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/badge.h58
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/badge_options.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/experimental_badge.idl17
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/navigator_badge.cc65
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/navigator_badge.h40
-rw-r--r--chromium/third_party/blink/renderer/modules/badging/navigator_badge.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.cc243
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc114
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.cc87
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc73
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/DEPS9
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc108
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc57
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context_base.h6
-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.cc136
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/README.md8
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/compression_stream.cc53
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/compression_stream.h36
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/compression_stream.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/decompression_stream.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/decompression_stream.h32
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/decompression_stream.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc121
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h60
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc116
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h56
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.cc49
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/contacts_picker/contacts_select_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_description.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_index.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_index.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/content_index/service_worker_registration_content_index.h2
-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/cookie_store.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/event_target_modules_names.json52
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source_parser_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc306
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h66
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/entry.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.cc105
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_writer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc84
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc (renamed from chromium/third_party/blink/renderer/modules/geolocation/coordinates.cc)10
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h (renamed from chromium/third_party/blink/renderer/modules/geolocation/coordinates.h)30
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.idl (renamed from chromium/third_party/blink/renderer/modules/geolocation/coordinates.idl)5
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_position.idl (renamed from chromium/third_party/blink/renderer/modules/geolocation/position.idl)5
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.h (renamed from chromium/third_party/blink/renderer/modules/geolocation/position_error.h)10
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.idl (renamed from chromium/third_party/blink/renderer/modules/geolocation/position_error.idl)5
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geoposition.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_collection_info.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_collection_info.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_device.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_device.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_report_info.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_report_info.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_report_item.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/hid/hid_report_item.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/idle/idle_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/image_downloader/multi_resolution_image_resource_fetcher.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.cc85
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_any.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_index.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_path.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_names.json56
-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_web_idb_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/mock_web_idb_transaction.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_transaction.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/related_application.h36
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/related_application.idl15
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/dom_window_launch_params.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/launch/launch_params.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest.json1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_1.json15
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_2.json16
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_3.json19
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_4.json18
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_5.json18
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_6.json24
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_listing_related_android_app.json18
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_maskable.json20
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json14
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_1.json12
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_2.json14
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_3.json14
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_4.json15
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_5.json15
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_6.json19
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_7.json20
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_8.json22
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_short_name.json1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_wrong_origin.json1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/play_app_url_manifest.json8
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.dict88
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/manifest_uma_util.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn43
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_base.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/mediaControls.css26
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.cc79
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc81
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h27
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h35
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc98
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h45
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h32
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc541
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h130
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc637
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc144
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h35
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/gradient_bg.pngbin715 -> 0 bytes
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_music_note.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_no_source.svg5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_off.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_on.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css370
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.grd14
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.cc45
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc51
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/blob_event.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc39
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc87
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc92
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_session.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/track_default.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_request.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/input_device_info.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_device_info.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_device_info.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_controller.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.cc79
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_request.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc160
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/modules.gni18
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_idl_files.gni34
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/BUILD.gn20
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc72
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h17
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc216
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/netinfo/testing/internals_net_info.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc149
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/ndef_record_init.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_constants.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_constants.h54
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_proxy_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_push_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_reader.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_scan_options.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_utils.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_utils.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_writer.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_writer.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/p2p/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/modules/p2p/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/modules/p2p/port_allocator.cc60
-rw-r--r--chromium/third_party/blink/renderer/modules/p2p/port_allocator.h62
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_request.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_address_init.idl18
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_handler_response.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_manager.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_manager.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_manager.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_method_change_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_method_change_response.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.cc100
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc216
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc100
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn32
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/DEPS13
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc257
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc234
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc314
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/mock_data_channel_impl.cc98
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc391
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc532
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.cc52
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc652
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc152
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h65
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc386
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc569
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc261
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc384
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc426
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc240
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc388
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter.cc338
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.cc215
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc357
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc271
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/mock_presentation_service.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_provider.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/README.md34
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc (renamed from chromium/third_party/blink/renderer/modules/scheduler/scheduler.cc)43
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h82
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc (renamed from chromium/third_party/blink/renderer/modules/scheduler/task.cc)63
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task.h (renamed from chromium/third_party/blink/renderer/modules/scheduler/task.h)50
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.cc80
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.h86
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/scheduler.h85
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_queue.cc150
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_queue.h83
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/task_queue.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/DEPS8
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/accelerometer.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc152
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/gyroscope.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/magnetometer.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc83
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial.cc44
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port.cc267
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_sink.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc65
-rw-r--r--chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/client.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc303
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h100
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/face_detector.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/shape_detection_type_converter.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/text_detector.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/sms/sms_receiver.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/testing/fake_area_source.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/navigator_vr.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_frame_data.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_frame_data.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_pose.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_pose.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/BUILD.gn10
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/README.md4
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc52
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h39
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.cc196
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.h65
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc234
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h88
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc488
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc81
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h72
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc121
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc174
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc212
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc57
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h41
-rw-r--r--chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_object_proxy.cc6
-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/base_audio_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc66
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/panner_node.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_context.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_thread.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_statement.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h3
-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.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc78
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc111
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc178
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc227
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h5
-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.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl19
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_buffer_descriptor.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_color.idl)6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc169
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl24
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_descriptor.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl)5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc121
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h34
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl20
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h31
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl12
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d_dict.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl)2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d_dict.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl3
-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_pipeline_layout_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_pass_encoder.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.idl (renamed from chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl)2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl31
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl29
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl33
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc60
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_usage.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_access.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_input.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_port.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/mock_websocket_channel.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/web_pepper_socket_channel_client_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc126
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_stream.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_stream_test.cc126
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.cc128
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/navigator_xr.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr.cc478
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr.h59
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_anchor.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_anchor.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc39
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.cc35
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc293
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h52
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_grip_space.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_grip_space.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.h17
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.h26
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.cc87
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.h59
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_object_space.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_plane.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_plane.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_plane.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_reference_space.cc130
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_reference_space.h34
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.cc769
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.h146
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_space.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_space.h59
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc88
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_world_information.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_world_information.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/BUILD.gn75
-rw-r--r--chromium/third_party/blink/renderer/platform/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/animated_layers_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_bus.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_channel.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_delay_dsp_kernel.cc101
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_accumulation_buffer.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc2
-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/custom_wrappable.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h127
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_state.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h74
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h62
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob_url_store.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/content_decryption_module_result.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/crypto_result.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/encrypted_media_request.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/page_zoom_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/platform.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/video_capture/web_video_capture_impl_manager_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_cache.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_http_body.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_mixed_content.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc74
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_string.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_request.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_response.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/file_metadata.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.h10
-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_optical_sizing.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc91
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h56
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h91
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc67
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc265
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc410
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h235
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc19
-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_provider.cc492
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc255
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc375
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc133
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc138
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc18
-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.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc10
-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.h1
-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_classifier.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc126
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc123
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc125
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc116
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/link_highlight.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc60
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BUILD.gn21
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md46
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/DEPS3
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc156
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc115
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/disallow_new_wrapper.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/garbage_collected.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/gc_info.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_allocator.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_allocator.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.cc228
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.h80
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test.cc178
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc71
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.cc85
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.h186
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/process_heap.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.cc475
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.h78
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/trace_traits.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/worklist.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc197
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_notifier.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc53
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc (renamed from chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.h)37
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h46
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h58
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h2
-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.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_resource_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/DEPS10
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/OWNERS (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/OWNERS)0
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_audio_configuration.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h)6
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h)6
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_key_system_configuration.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_key_system_configuration.h)6
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h)10
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_media_decoding_configuration.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_decoding_configuration.h)10
-rw-r--r--chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h (renamed from chromium/third_party/blink/public/platform/modules/media_capabilities/web_video_configuration.h)6
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni7
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/bluetooth_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_headers_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.h46
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc619
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/revocable_binding.h182
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h241
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/revocable_strong_binding.h134
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/security_origin_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/encoded_form_data_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_state_notifier.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/DEPS13
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc224
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h133
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc517
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc62
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/host_address_request.h62
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc199
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc201
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc797
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc69
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h46
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/network_list_manager.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/network_list_observer.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client_delegate.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc175
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h118
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc109
-rw-r--r--chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h111
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc164
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.cc312
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h103
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc191
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h75
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc323
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc204
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source_test.cc98
-rw-r--r--chromium/third_party/blink/renderer/platform/prerender.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5208
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cooperative_scheduling_manager.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/event_loop.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc5
-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.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/compositor_priority_experiments.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc142
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc73
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scoped_virtual_time_pauser.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_unittest.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/scoped_mocked_url.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/video_frame_utils.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/video_frame_utils.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc3
-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.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/timer_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transform_operations.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transform_operations_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/DEPS15
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc247
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc172
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc53
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/url_security_origin_map.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/Allocator.md5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/BUILD.gn23
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/cross_thread_copier.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/deque.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa.cc (renamed from chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.cc)18
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa.h (renamed from chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.h)18
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/COPYING26
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/LICENSE26
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/README11
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc680
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h90
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.cc770
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.h149
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.cc204
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h124
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.cc596
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h382
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/double.h251
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.cc743
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h88
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc412
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.cc447
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/utils.h308
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/functional.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_map.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_set.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_table.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/linked_hash_set.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_to_number.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_pthreads.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/type_traits_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf_test_helper.h8
-rw-r--r--chromium/third_party/blink/tools/BUILD.gn39
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/file_uploader.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py146
-rw-r--r--chromium/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py573
-rwxr-xr-xchromium/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py61
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py6
-rw-r--r--chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py21
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py26
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py66
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py340
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py275
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py105
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder.py59
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_finder_unittest.py76
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py12
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py14
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py418
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures_unittest.py32
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_input.py11
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results.py45
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results_unittest.py15
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py5
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py37
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/base.py7
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py2
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py24
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/port/test.py83
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py13
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/run_web_tests_unittest.py383
-rw-r--r--chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py2
-rw-r--r--chromium/third_party/blink/tools/lldb/lldb_blink.py30
4460 files changed, 223856 insertions, 90793 deletions
diff --git a/chromium/third_party/blink/API_OWNERS b/chromium/third_party/blink/API_OWNERS
index 30b7d7d0084..a5b22d5301c 100644
--- a/chromium/third_party/blink/API_OWNERS
+++ b/chromium/third_party/blink/API_OWNERS
@@ -2,7 +2,7 @@
# expose to the open web.
#
# See https://www.chromium.org/blink#new-features for details.
-bratell@opera.com
+bratell.d@gmail.com
chrishtr@chromium.org
darin@chromium.org
foolip@chromium.org
diff --git a/chromium/third_party/blink/OWNERS b/chromium/third_party/blink/OWNERS
index d398a3dde46..770dfb07fa9 100644
--- a/chromium/third_party/blink/OWNERS
+++ b/chromium/third_party/blink/OWNERS
@@ -1,6 +1,6 @@
# Top-level owners for cases where there's nobody available with
# specific context
-bratell@opera.com
+bratell.d@gmail.com
chrishtr@chromium.org
foolip@chromium.org
jochen@chromium.org
@@ -10,7 +10,6 @@ tkent@chromium.org
yoavweiss@chromium.org
# For *.gn* changes only.
-dpranke@chromium.org
thakis@chromium.org
per-file PRESUBMIT*.py=dcheng@chromium.org
diff --git a/chromium/third_party/blink/PRESUBMIT_test.py b/chromium/third_party/blink/PRESUBMIT_test.py
index e7cf59ca3eb..e28addf4fea 100755
--- a/chromium/third_party/blink/PRESUBMIT_test.py
+++ b/chromium/third_party/blink/PRESUBMIT_test.py
@@ -240,7 +240,7 @@ class CxxDependencyTest(unittest.TestCase):
# External module checks should not affect CSS files.
def testCheckCSSIgnored(self):
- filename = 'third_party/blink/renderer/devtools/front_end/timeline/someFile.css'
+ filename = 'third_party/blink/renderer/someFile.css'
errors = self.runCheck(filename, ['.toolbar::after { color: pink; }\n'])
self.assertEqual([], errors)
diff --git a/chromium/third_party/blink/common/BUILD.gn b/chromium/third_party/blink/common/BUILD.gn
index a5d36cb2341..6b501f924ba 100644
--- a/chromium/third_party/blink/common/BUILD.gn
+++ b/chromium/third_party/blink/common/BUILD.gn
@@ -33,6 +33,7 @@ jumbo_source_set("common") {
"device_memory/approximated_device_memory.cc",
"dom_storage/session_storage_namespace_id.cc",
"experiments/memory_ablation_experiment.cc",
+ "feature_policy/document_policy.cc",
"feature_policy/feature_policy.cc",
"feature_policy/policy_value.cc",
"features.cc",
@@ -40,11 +41,14 @@ jumbo_source_set("common") {
"frame/frame_policy.cc",
"frame/from_ad_state.cc",
"frame/user_activation_state.cc",
+ "http/structured_header.cc",
"indexeddb/indexed_db_default_mojom_traits.cc",
"indexeddb/indexeddb_key.cc",
"indexeddb/indexeddb_key_path.cc",
"indexeddb/indexeddb_key_range.cc",
"indexeddb/indexeddb_metadata.cc",
+ "loader/mime_sniffing_throttle.cc",
+ "loader/mime_sniffing_url_loader.cc",
"loader/request_destination.cc",
"loader/url_loader_factory_bundle.cc",
"loader/url_loader_factory_bundle_mojom_traits.cc",
@@ -75,12 +79,13 @@ jumbo_source_set("common") {
"origin_policy/origin_policy_parser.h",
"origin_trials/trial_token.cc",
"origin_trials/trial_token_validator.cc",
- "privacy_preferences.cc",
+ "page/page_zoom.cc",
+ "peerconnection/webrtc_ip_handling_policy.cc",
+ "scheduler/web_scheduler_tracked_feature.cc",
"service_worker/service_worker_status_code.cc",
"service_worker/service_worker_type_converters.cc",
"service_worker/service_worker_utils.cc",
"thread_safe_browser_interface_broker_proxy.cc",
- "web_package/http_structured_header.cc",
"web_package/signed_exchange_consts.cc",
"web_package/signed_exchange_request_matcher.cc",
]
@@ -95,6 +100,7 @@ jumbo_source_set("common") {
"//net",
"//services/metrics/public/cpp:ukm_builders",
"//services/network/public/cpp:cpp",
+ "//third_party/blink/public/mojom:mojom_platform_blink_headers",
]
# iOS doesn't use and must not depend on //media
@@ -120,13 +126,13 @@ jumbo_source_set("common") {
fuzzer_test("http_structured_header_fuzzer") {
sources = [
- "web_package/http_structured_header_fuzzer.cc",
+ "http/structured_header_fuzzer.cc",
]
deps = [
":common",
"//third_party/blink/renderer/platform:blink_fuzzer_test_support",
]
- seed_corpus = "web_package/http_structured_header_corpus"
+ seed_corpus = "http/structured_header_corpus"
}
test("blink_common_unittests") {
@@ -152,7 +158,9 @@ jumbo_source_set("common_unittests_sources") {
"device_memory/approximated_device_memory_unittest.cc",
"feature_policy/feature_policy_unittest.cc",
"frame/user_activation_state_unittest.cc",
+ "http/structured_header_unittest.cc",
"indexeddb/indexeddb_key_unittest.cc",
+ "loader/mime_sniffing_throttle_unittest.cc",
"manifest/manifest_icon_selector_unittest.cc",
"manifest/manifest_util_unittest.cc",
"mediastream/media_devices_unittest.cc",
@@ -163,7 +171,6 @@ jumbo_source_set("common_unittests_sources") {
"origin_trials/trial_token_unittest.cc",
"origin_trials/trial_token_validator_unittest.cc",
"test/run_all_unittests.cc",
- "web_package/http_structured_header_unittest.cc",
"web_package/signed_exchange_request_matcher_unittest.cc",
]
@@ -172,6 +179,7 @@ jumbo_source_set("common_unittests_sources") {
"//base/test:test_support",
"//mojo/core/embedder",
"//net",
+ "//services/network:test_support",
"//skia/public/mojom",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/third_party/blink/common/DEPS b/chromium/third_party/blink/common/DEPS
index 0a072bb71fb..d0c26816803 100644
--- a/chromium/third_party/blink/common/DEPS
+++ b/chromium/third_party/blink/common/DEPS
@@ -14,6 +14,8 @@ include_rules = [
"+services/metrics/public/cpp",
"+services/network/public/cpp",
"+services/network/public/mojom/url_loader.mojom.h",
+ "+services/network/public/mojom/url_response_head.mojom.h",
+ "+services/network/public/mojom/url_response_head.mojom-forward.h",
"+skia/public/mojom/bitmap_skbitmap_mojom_traits.h",
"+testing/gmock/include/gmock",
"+testing/gtest/include/gtest",
@@ -26,5 +28,5 @@ include_rules = [
"+url",
]
specific_include_rules = {
- '.*unittest.?.cc': [ "+v8" ],
+ '.*unittest.?.cc': [ "+v8", "+services/network/test" ],
}
diff --git a/chromium/third_party/blink/common/OWNERS b/chromium/third_party/blink/common/OWNERS
index cdea22ee510..9b94b90fcad 100644
--- a/chromium/third_party/blink/common/OWNERS
+++ b/chromium/third_party/blink/common/OWNERS
@@ -6,5 +6,6 @@ jbroman@chromium.org
pfeldman@chromium.org
dgozman@chromium.org
dcheng@chromium.org
+falken@chromium.org
# COMPONENT: Blink
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 2a10832aa7f..226a471e8e7 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
@@ -6,7 +6,8 @@
#include <map>
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "base/no_destructor.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
namespace blink {
@@ -17,10 +18,9 @@ class AssociatedInterfaceProvider::LocalProvider
base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>;
explicit LocalProvider(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : associated_interface_provider_binding_(this) {
- associated_interface_provider_binding_.Bind(
- mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr_),
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ associated_interface_provider_receiver_.Bind(
+ remote_.BindNewEndpointAndPassDedicatedReceiverForTesting(),
std::move(task_runner));
}
@@ -36,30 +36,32 @@ class AssociatedInterfaceProvider::LocalProvider
void GetInterface(const std::string& name,
mojo::ScopedInterfaceEndpointHandle handle) {
- return ptr_->GetAssociatedInterface(
- name, mojom::AssociatedInterfaceAssociatedRequest(std::move(handle)));
+ return remote_->GetAssociatedInterface(
+ name, mojo::PendingAssociatedReceiver<mojom::AssociatedInterface>(
+ std::move(handle)));
}
private:
// mojom::AssociatedInterfaceProvider:
void GetAssociatedInterface(
const std::string& name,
- mojom::AssociatedInterfaceAssociatedRequest request) override {
+ mojo::PendingAssociatedReceiver<mojom::AssociatedInterface> receiver)
+ override {
auto it = binders_.find(name);
if (it != binders_.end())
- it->second.Run(request.PassHandle());
+ it->second.Run(receiver.PassHandle());
}
std::map<std::string, Binder> binders_;
- mojo::AssociatedBinding<mojom::AssociatedInterfaceProvider>
- associated_interface_provider_binding_;
- mojom::AssociatedInterfaceProviderAssociatedPtr ptr_;
+ mojo::AssociatedReceiver<mojom::AssociatedInterfaceProvider>
+ associated_interface_provider_receiver_{this};
+ mojo::AssociatedRemote<mojom::AssociatedInterfaceProvider> remote_;
DISALLOW_COPY_AND_ASSIGN(LocalProvider);
};
AssociatedInterfaceProvider::AssociatedInterfaceProvider(
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy,
+ mojo::PendingAssociatedRemote<mojom::AssociatedInterfaceProvider> proxy,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: proxy_(std::move(proxy)), task_runner_(std::move(task_runner)) {
DCHECK(proxy_.is_bound());
@@ -81,7 +83,8 @@ void AssociatedInterfaceProvider::GetInterface(
}
DCHECK(proxy_);
proxy_->GetAssociatedInterface(
- name, mojom::AssociatedInterfaceAssociatedRequest(std::move(handle)));
+ name, mojo::PendingAssociatedReceiver<mojom::AssociatedInterface>(
+ std::move(handle)));
}
void AssociatedInterfaceProvider::OverrideBinderForTesting(
@@ -93,4 +96,11 @@ void AssociatedInterfaceProvider::OverrideBinderForTesting(
local_provider_->SetBinderForName(name, binder);
}
+AssociatedInterfaceProvider*
+AssociatedInterfaceProvider::GetEmptyAssociatedInterfaceProvider() {
+ static base::NoDestructor<AssociatedInterfaceProvider>
+ associated_interface_provider(base::ThreadTaskRunnerHandle::Get());
+ return associated_interface_provider.get();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/common/feature_policy/document_policy.cc b/chromium/third_party/blink/common/feature_policy/document_policy.cc
new file mode 100644
index 00000000000..25b727d27a5
--- /dev/null
+++ b/chromium/third_party/blink/common/feature_policy/document_policy.cc
@@ -0,0 +1,126 @@
+// 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/common/feature_policy/document_policy.h"
+
+#include "base/no_destructor.h"
+
+namespace blink {
+
+// static
+std::unique_ptr<DocumentPolicy> DocumentPolicy::CreateWithRequiredPolicy(
+ const FeatureState& required_policy) {
+ return CreateWithRequiredPolicy(required_policy, GetFeatureDefaults());
+}
+
+bool DocumentPolicy::IsFeatureEnabled(
+ mojom::FeaturePolicyFeature feature) const {
+ mojom::PolicyValueType feature_type = GetFeatureDefaults().at(feature).Type();
+ // TODO(iclelland): Generate this switch block
+ switch (feature) {
+ case mojom::FeaturePolicyFeature::kFontDisplay:
+ return font_display_;
+ case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
+ return PolicyValue(unoptimized_lossless_images_) >=
+ PolicyValue::CreateMaxPolicyValue(feature_type);
+ default:
+ NOTREACHED();
+ return true;
+ }
+}
+
+bool DocumentPolicy::IsFeatureEnabled(
+ mojom::FeaturePolicyFeature feature,
+ const PolicyValue& threshold_value) const {
+ return GetFeatureValue(feature) >= threshold_value;
+}
+
+PolicyValue DocumentPolicy::GetFeatureValue(
+ mojom::FeaturePolicyFeature feature) const {
+ // TODO(iclelland): Generate this switch block
+ switch (feature) {
+ case mojom::FeaturePolicyFeature::kFontDisplay:
+ return PolicyValue(font_display_);
+ case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
+ return PolicyValue(unoptimized_lossless_images_);
+ default:
+ NOTREACHED();
+ return PolicyValue(false);
+ }
+}
+
+void DocumentPolicy::SetHeaderPolicy(
+ const ParsedDocumentPolicy& parsed_header) {
+ for (const ParsedDocumentPolicyDeclaration& parsed_declaration :
+ parsed_header) {
+ mojom::FeaturePolicyFeature feature = parsed_declaration.feature;
+ // TODO(iclelland): Generate this switch block
+ switch (feature) {
+ case mojom::FeaturePolicyFeature::kFontDisplay:
+ font_display_ = parsed_declaration.value.BoolValue();
+ break;
+ case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
+ unoptimized_lossless_images_ = parsed_declaration.value.DoubleValue();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+void DocumentPolicy::UpdateFeatureState(const FeatureState& feature_state) {
+ for (const auto& feature_and_value : feature_state) {
+ // TODO(iclelland): Generate this switch block
+ switch (feature_and_value.first) {
+ case mojom::FeaturePolicyFeature::kFontDisplay:
+ font_display_ = feature_and_value.second.BoolValue();
+ break;
+ case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
+ unoptimized_lossless_images_ = feature_and_value.second.DoubleValue();
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+}
+
+DocumentPolicy::FeatureState DocumentPolicy::GetFeatureState() const {
+ FeatureState feature_state;
+ // TODO(iclelland): Generate this block
+ feature_state[mojom::FeaturePolicyFeature::kFontDisplay] =
+ PolicyValue(font_display_);
+ feature_state[mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages] =
+ PolicyValue(unoptimized_lossless_images_);
+ return feature_state;
+}
+
+DocumentPolicy::DocumentPolicy(const FeatureState& defaults) {
+ UpdateFeatureState(defaults);
+}
+
+DocumentPolicy::~DocumentPolicy() = default;
+
+// static
+std::unique_ptr<DocumentPolicy> DocumentPolicy::CreateWithRequiredPolicy(
+ const FeatureState& required_policy,
+ const DocumentPolicy::FeatureState& defaults) {
+ std::unique_ptr<DocumentPolicy> new_policy =
+ base::WrapUnique(new DocumentPolicy(defaults));
+ new_policy->UpdateFeatureState(required_policy);
+ return new_policy;
+}
+
+// static
+// TODO(iclelland): This list just contains two sample features for use during
+// development. It should be generated from definitions in a feature
+// configuration json5 file.
+const DocumentPolicy::FeatureState& DocumentPolicy::GetFeatureDefaults() {
+ static base::NoDestructor<FeatureState> default_feature_list(
+ {{mojom::FeaturePolicyFeature::kFontDisplay, PolicyValue(false)},
+ {mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages,
+ PolicyValue(2.0f)}});
+ return *default_feature_list;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/feature_policy/feature_policy.cc b/chromium/third_party/blink/common/feature_policy/feature_policy.cc
index c3762aecf00..46f672a23f6 100644
--- a/chromium/third_party/blink/common/feature_policy/feature_policy.cc
+++ b/chromium/third_party/blink/common/feature_policy/feature_policy.cc
@@ -9,6 +9,7 @@
#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
namespace blink {
namespace {
@@ -350,6 +351,7 @@ mojom::FeaturePolicyFeature FeaturePolicy::FeatureForSandboxFlag(
case WebSandboxFlags::kPlugins:
case WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts:
case WebSandboxFlags::kTopNavigationByUserActivation:
+ case WebSandboxFlags::kStorageAccessByUserActivation:
break;
}
return mojom::FeaturePolicyFeature::kNotFound;
diff --git a/chromium/third_party/blink/common/feature_policy/feature_policy_mojom_traits.h b/chromium/third_party/blink/common/feature_policy/feature_policy_mojom_traits.h
index 6c545c89b89..70c3c7a175e 100644
--- a/chromium/third_party/blink/common/feature_policy/feature_policy_mojom_traits.h
+++ b/chromium/third_party/blink/common/feature_policy/feature_policy_mojom_traits.h
@@ -58,6 +58,9 @@ STATIC_ASSERT_ENUM(
::blink::mojom::WebSandboxFlags::kTopNavigationByUserActivation);
STATIC_ASSERT_ENUM(::blink::WebSandboxFlags::kDownloads,
::blink::mojom::WebSandboxFlags::kDownloads);
+STATIC_ASSERT_ENUM(
+ ::blink::WebSandboxFlags::kStorageAccessByUserActivation,
+ ::blink::mojom::WebSandboxFlags::kStorageAccessByUserActivation);
template <>
struct BLINK_COMMON_EXPORT
diff --git a/chromium/third_party/blink/common/feature_policy/feature_policy_unittest.cc b/chromium/third_party/blink/common/feature_policy/feature_policy_unittest.cc
index 213cb940691..7c2af77ab69 100644
--- a/chromium/third_party/blink/common/feature_policy/feature_policy_unittest.cc
+++ b/chromium/third_party/blink/common/feature_policy/feature_policy_unittest.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
#include "url/gurl.h"
namespace blink {
diff --git a/chromium/third_party/blink/common/feature_policy/policy_value.cc b/chromium/third_party/blink/common/feature_policy/policy_value.cc
index f58edea6666..9eb09268223 100644
--- a/chromium/third_party/blink/common/feature_policy/policy_value.cc
+++ b/chromium/third_party/blink/common/feature_policy/policy_value.cc
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/feature_policy/policy_value.h"
+
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
namespace blink {
@@ -17,6 +19,9 @@ PolicyValue::PolicyValue(mojom::PolicyValueType type) : type_(type) {
PolicyValue::PolicyValue(bool bool_value)
: type_(mojom::PolicyValueType::kBool), bool_value_(bool_value) {}
+PolicyValue::PolicyValue(double double_value)
+ : type_(mojom::PolicyValueType::kDecDouble), double_value_(double_value) {}
+
PolicyValue::PolicyValue(double double_value, mojom::PolicyValueType type)
: type_(type), double_value_(double_value) {}
@@ -49,6 +54,11 @@ void PolicyValue::SetBoolValue(bool bool_value) {
bool_value_ = bool_value;
}
+void PolicyValue::SetDoubleValue(double double_value) {
+ DCHECK_EQ(mojom::PolicyValueType::kDecDouble, type_);
+ double_value_ = double_value;
+}
+
void PolicyValue::SetDoubleValue(double double_value,
mojom::PolicyValueType type) {
DCHECK_EQ(type, type_);
diff --git a/chromium/third_party/blink/common/features.cc b/chromium/third_party/blink/common/features.cc
index a7e586dec11..b6869e60e57 100644
--- a/chromium/third_party/blink/common/features.cc
+++ b/chromium/third_party/blink/common/features.cc
@@ -18,9 +18,9 @@ const base::Feature kBlockingDownloadsInAdFrameWithoutUserActivation{
"BlockingDownloadsInAdFrameWithoutUserActivation",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Enable defer commits a bit to avoid flash.
-const base::Feature kAvoidFlashBetweenNavigation{
- "AvoidFlashBetweenNavigation", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enable defer commits to avoid flash of unstyled content.
+const base::Feature kPaintHolding{"PaintHolding",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Enable eagerly setting up a CacheStorage interface pointer and
// passing it to service workers on startup as an optimization.
@@ -28,12 +28,6 @@ const base::Feature kEagerCacheStorageSetupForServiceWorkers{
"EagerCacheStorageSetupForServiceWorkers",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Controls the user-specified viewport restriction for GPU Rasterization on
-// mobile. See https://crbug.com/899399
-const base::Feature kEnableGpuRasterizationViewportRestriction{
- "EnableGpuRasterizationViewportRestriction",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Controls script streaming.
const base::Feature kScriptStreaming{"ScriptStreaming",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -46,10 +40,6 @@ const base::Feature kSmallScriptStreaming{"SmallScriptStreaming",
const base::Feature kUserLevelMemoryPressureSignal{
"UserLevelMemoryPressureSignal", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enable FCP++ by experiment. See https://crbug.com/869924
-const base::Feature kFirstContentfulPaintPlusPlus{
- "FirstContentfulPaintPlusPlus", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Perform memory purges after freezing only if all pages are frozen.
const base::Feature kFreezePurgeMemoryAllPagesFrozen{
"FreezePurgeMemoryAllPagesFrozen", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -70,13 +60,7 @@ const base::Feature kDisplayLocking{"DisplayLocking",
// a mask layer.
const base::Feature kFastBorderRadius {
"FastBorderRadius",
-#if defined(OS_MACOSX)
- // A FastBorderRadiusMac experiment is rolling out separately for that
- // platform, due to complications with CALayer overlay optimizations.
- base::FEATURE_DISABLED_BY_DEFAULT
-#else
base::FEATURE_ENABLED_BY_DEFAULT
-#endif
};
// Enable LayoutNG.
@@ -103,7 +87,7 @@ const base::Feature kNavigationPredictor {
// Start service workers on a background thread.
// https://crbug.com/692909
const base::Feature kOffMainThreadServiceWorkerStartup{
- "OffMainThreadServiceWorkerStartup", base::FEATURE_DISABLED_BY_DEFAULT};
+ "OffMainThreadServiceWorkerStartup", base::FEATURE_ENABLED_BY_DEFAULT};
// Enable browser-initiated dedicated worker script loading
// (PlzDedicatedWorker). https://crbug.com/906991
@@ -145,6 +129,10 @@ const base::Feature kImplicitRootScroller {
#endif
};
+// Enable CSSOM View Scroll Coordinates. https://crbug.com/721759.
+const base::Feature kCSSOMViewScrollCoordinates{
+ "CSSOMViewScrollCoordinates", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables usage of getDisplayMedia() that allows capture of web content, see
// https://crbug.com/865060.
const base::Feature kRTCGetDisplayMedia{"RTCGetDisplayMedia",
@@ -188,21 +176,25 @@ const base::Feature kWebRtcHWVP9Encoding {
const base::Feature kWebRtcHWH264Encoding{"WebRtcHWH264Encoding",
base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables negotiation of experimental multiplex codec in SDP.
+const base::Feature kWebRtcMultiplexCodec{"WebRTC-MultiplexCodec",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Causes WebRTC to replace host ICE candidate IP addresses with generated
+// names ending in ".local" and resolve them using mDNS.
+// http://crbug.com/878465
+const base::Feature kWebRtcHideLocalIpsWithMdns{
+ "WebRtcHideLocalIpsWithMdns", base::FEATURE_ENABLED_BY_DEFAULT};
+
#if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
// Run-time feature for the |rtc_use_h264| encoder/decoder.
const base::Feature kWebRtcH264WithOpenH264FFmpeg{
"WebRTC-H264WithOpenH264FFmpeg", base::FEATURE_ENABLED_BY_DEFAULT};
#endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
-const base::Feature kServiceWorkerIsolateInForeground{
- "ServiceWorkerIsolateInForeground", base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kServiceWorkerImportedScriptUpdateCheck{
"ServiceWorkerImportedScriptUpdateCheck", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kServiceWorkerAggressiveCodeCache{
- "ServiceWorkerAggressiveCodeCache", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Experiment of the delay from navigation to starting an update of a service
// worker's script.
const base::Feature kServiceWorkerUpdateDelay{
@@ -276,12 +268,6 @@ const base::Feature kDecodeJpeg420ImagesToYUV{
const base::Feature kDecodeLossyWebPImagesToYUV{
"DecodeLossyWebPImagesToYUV", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables usage of render frame observer as the receiver of the resource
-// loading hints in the render process.
-// https://crbug.com/891328.
-const base::Feature kSendPreviewsLoadingHintsBeforeCommit{
- "SendPreviewsLoadingHintsBeforeCommit", base::FEATURE_ENABLED_BY_DEFAULT};
-
// Enables cache-aware WebFonts loading. See https://crbug.com/570205.
// The feature is disabled on Android for WebView API issue discussed at
// https://crbug.com/942440.
@@ -304,11 +290,13 @@ const base::Feature kAudioWorkletRealtimeThread{
// A feature to reduce the set of resources fetched by No-State Prefetch.
const base::Feature kLightweightNoStatePrefetch{
- "LightweightNoStatePrefetch", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Use scroll gestures for scrollbar scrolls (see https://crbug.com/954007).
-const base::Feature kScrollbarInjectScrollGestures{
- "ScrollbarInjectScrollGestures", base::FEATURE_ENABLED_BY_DEFAULT};
+ "LightweightNoStatePrefetch",
+#if defined(OS_ANDROID)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
// Automatically convert light-themed pages to use a Blink-generated dark theme
const base::Feature kForceWebContentsDarkMode{
@@ -357,11 +345,6 @@ const base::FeatureParam<int> kForceDarkBackgroundLightnessThresholdParam{
const base::Feature kCanvasAlwaysDeferral{"CanvasAlwaysDeferral",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Use the new C++ implementation of WHATWG Streams. See
-// https://crbug.com/977500.
-const base::Feature kStreamsNative{"StreamsNative",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Blink garbage collection.
// Enables compaction of backing stores on Blink's heap.
const base::Feature kBlinkHeapCompaction{"BlinkHeapCompaction",
@@ -379,10 +362,6 @@ const base::Feature kBlinkHeapIncrementalMarking{
// also adds additional verification passes.
const base::Feature kBlinkHeapIncrementalMarkingStress{
"BlinkHeapIncrementalMarkingStress", base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables unified heap garbage collection scheduling where scheduling is
-// delegated to V8's heap controller.
-const base::Feature kBlinkHeapUnifiedGCScheduling{
- "BlinkHeapUnifiedGCScheduling", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables a delay before BufferingBytesConsumer begins reading from its
// underlying consumer when instantiated with CreateWithDelay().
@@ -423,5 +402,14 @@ const base::Feature kLowerJavaScriptPriorityWhenForceDeferred{
const base::Feature kHtmlImportsRequestInitiatorLock{
"HtmlImportsRequestInitiatorLock", base::FEATURE_DISABLED_BY_DEFAULT};
+// When 'enabled', directly compositing images is turned off.
+const base::Feature kDisableDirectlyCompositedImages{
+ "DisableDirectlyCompositedImages", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// When enabled, beacons (and friends) have ResourceLoadPriority::kLow,
+// not ResourceLoadPriority::kVeryLow.
+const base::Feature kSetLowPriorityForBeacon{"SetLowPriorityForBeacon",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace blink
diff --git a/chromium/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc b/chromium/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
index e744edb56c6..439236ec538 100644
--- a/chromium/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/chromium/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h"
#include "services/network/public/cpp/url_request_mojom_traits.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
namespace mojo {
@@ -38,7 +39,7 @@ bool StructTraits<
out->data_pipe_getter_ =
data.TakeDataPipeGetter<network::mojom::DataPipeGetterPtrInfo>();
out->chunked_data_pipe_getter_ = data.TakeChunkedDataPipeGetter<
- network::mojom::ChunkedDataPipeGetterPtrInfo>();
+ mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
out->offset_ = data.offset();
out->length_ = data.length();
return true;
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header.cc b/chromium/third_party/blink/common/http/structured_header.cc
index 90c1a36b3c4..b814c3c62a9 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header.cc
+++ b/chromium/third_party/blink/common/http/structured_header.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/common/web_package/http_structured_header.h"
+#include "third_party/blink/public/common/http/structured_header.h"
#include <string>
#include <utility>
@@ -79,7 +79,7 @@ class StructuredHeaderParser {
// byte sequences) are supported, and all types are returned as a string
// regardless of the item type. E.g. both 123 (number) and "123" (string) are
// returned as "123".
- // TODO(ksakamoto): Add support for other types, and return a value with type
+ // TODO(1011101): Add support for other types, and return a value with type
// info.
base::Optional<std::string> ReadItem() {
if (input_.empty()) {
@@ -289,6 +289,8 @@ class StructuredHeaderParser {
ParameterisedIdentifier::ParameterisedIdentifier(
const ParameterisedIdentifier&) = default;
+ParameterisedIdentifier& ParameterisedIdentifier::operator=(
+ const ParameterisedIdentifier&) = default;
ParameterisedIdentifier::ParameterisedIdentifier(const std::string& id,
const Parameters& ps)
: identifier(id), params(ps) {}
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/1.txt b/chromium/third_party/blink/common/http/structured_header_corpus/1.txt
index e3e6559db87..e3e6559db87 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/1.txt
+++ b/chromium/third_party/blink/common/http/structured_header_corpus/1.txt
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/2.txt b/chromium/third_party/blink/common/http/structured_header_corpus/2.txt
index 373db578eef..373db578eef 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/2.txt
+++ b/chromium/third_party/blink/common/http/structured_header_corpus/2.txt
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/3.txt b/chromium/third_party/blink/common/http/structured_header_corpus/3.txt
index b8aecd1d635..b8aecd1d635 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/3.txt
+++ b/chromium/third_party/blink/common/http/structured_header_corpus/3.txt
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/4.txt b/chromium/third_party/blink/common/http/structured_header_corpus/4.txt
index 9d0aa4452d5..9d0aa4452d5 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/4.txt
+++ b/chromium/third_party/blink/common/http/structured_header_corpus/4.txt
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/5.txt b/chromium/third_party/blink/common/http/structured_header_corpus/5.txt
index 449a0dfa251..449a0dfa251 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_corpus/5.txt
+++ b/chromium/third_party/blink/common/http/structured_header_corpus/5.txt
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_fuzzer.cc b/chromium/third_party/blink/common/http/structured_header_fuzzer.cc
index f6723f3fc51..1103bfcf0b9 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_fuzzer.cc
+++ b/chromium/third_party/blink/common/http/structured_header_fuzzer.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/common/web_package/http_structured_header.h" // nogncheck
+#include "third_party/blink/public/common/http/structured_header.h" // nogncheck
namespace blink {
namespace http_structured_header {
diff --git a/chromium/third_party/blink/common/web_package/http_structured_header_unittest.cc b/chromium/third_party/blink/common/http/structured_header_unittest.cc
index da212eb3ee2..d175f7217e1 100644
--- a/chromium/third_party/blink/common/web_package/http_structured_header_unittest.cc
+++ b/chromium/third_party/blink/common/http/structured_header_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/public/common/web_package/http_structured_header.h"
+#include "third_party/blink/public/common/http/structured_header.h"
#include <string>
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 8679107a6a5..f981576ff5e 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
@@ -11,6 +11,7 @@
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
namespace mojo {
diff --git a/chromium/third_party/blink/common/indexeddb/indexeddb_key_path.cc b/chromium/third_party/blink/common/indexeddb/indexeddb_key_path.cc
index ec2b618e769..552d54179c5 100644
--- a/chromium/third_party/blink/common/indexeddb/indexeddb_key_path.cc
+++ b/chromium/third_party/blink/common/indexeddb/indexeddb_key_path.cc
@@ -18,12 +18,12 @@ IndexedDBKeyPath::IndexedDBKeyPath(const std::vector<base::string16>& array)
: type_(mojom::IDBKeyPathType::Array), array_(array) {}
IndexedDBKeyPath::IndexedDBKeyPath(const IndexedDBKeyPath& other) = default;
-IndexedDBKeyPath::IndexedDBKeyPath(IndexedDBKeyPath&& other) noexcept = default;
+IndexedDBKeyPath::IndexedDBKeyPath(IndexedDBKeyPath&& other) = default;
IndexedDBKeyPath::~IndexedDBKeyPath() = default;
IndexedDBKeyPath& IndexedDBKeyPath::operator=(const IndexedDBKeyPath& other) =
default;
-IndexedDBKeyPath& IndexedDBKeyPath::operator=(
- IndexedDBKeyPath&& other) noexcept = default;
+IndexedDBKeyPath& IndexedDBKeyPath::operator=(IndexedDBKeyPath&& other) =
+ default;
const std::vector<base::string16>& IndexedDBKeyPath::array() const {
DCHECK(type_ == blink::mojom::IDBKeyPathType::Array);
diff --git a/chromium/third_party/blink/common/indexeddb/indexeddb_metadata.cc b/chromium/third_party/blink/common/indexeddb/indexeddb_metadata.cc
index 50d5845228b..9349732048a 100644
--- a/chromium/third_party/blink/common/indexeddb/indexeddb_metadata.cc
+++ b/chromium/third_party/blink/common/indexeddb/indexeddb_metadata.cc
@@ -23,15 +23,15 @@ IndexedDBIndexMetadata::IndexedDBIndexMetadata(const base::string16& name,
IndexedDBIndexMetadata::IndexedDBIndexMetadata(
const IndexedDBIndexMetadata& other) = default;
-IndexedDBIndexMetadata::IndexedDBIndexMetadata(
- IndexedDBIndexMetadata&& other) noexcept = default;
+IndexedDBIndexMetadata::IndexedDBIndexMetadata(IndexedDBIndexMetadata&& other) =
+ default;
IndexedDBIndexMetadata::~IndexedDBIndexMetadata() = default;
IndexedDBIndexMetadata& IndexedDBIndexMetadata::operator=(
const IndexedDBIndexMetadata& other) = default;
IndexedDBIndexMetadata& IndexedDBIndexMetadata::operator=(
- IndexedDBIndexMetadata&& other) noexcept = default;
+ IndexedDBIndexMetadata&& other) = default;
bool IndexedDBIndexMetadata::operator==(
const IndexedDBIndexMetadata& other) const {
@@ -56,14 +56,14 @@ IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata() = default;
IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
const IndexedDBObjectStoreMetadata& other) = default;
IndexedDBObjectStoreMetadata::IndexedDBObjectStoreMetadata(
- IndexedDBObjectStoreMetadata&& other) noexcept = default;
+ IndexedDBObjectStoreMetadata&& other) = default;
IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() = default;
IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
const IndexedDBObjectStoreMetadata& other) = default;
IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
- IndexedDBObjectStoreMetadata&& other) noexcept = default;
+ IndexedDBObjectStoreMetadata&& other) = default;
bool IndexedDBObjectStoreMetadata::operator==(
const IndexedDBObjectStoreMetadata& other) const {
@@ -87,14 +87,14 @@ IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
const IndexedDBDatabaseMetadata& other) = default;
IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
- IndexedDBDatabaseMetadata&& other) noexcept = default;
+ IndexedDBDatabaseMetadata&& other) = default;
IndexedDBDatabaseMetadata::~IndexedDBDatabaseMetadata() = default;
IndexedDBDatabaseMetadata& IndexedDBDatabaseMetadata::operator=(
const IndexedDBDatabaseMetadata& other) = default;
IndexedDBDatabaseMetadata& IndexedDBDatabaseMetadata::operator=(
- IndexedDBDatabaseMetadata&& other) noexcept = default;
+ IndexedDBDatabaseMetadata&& other) = default;
bool IndexedDBDatabaseMetadata::operator==(
const IndexedDBDatabaseMetadata& other) const {
diff --git a/chromium/third_party/blink/common/loader/mime_sniffing_throttle.cc b/chromium/third_party/blink/common/loader/mime_sniffing_throttle.cc
new file mode 100644
index 00000000000..96ca9af81be
--- /dev/null
+++ b/chromium/third_party/blink/common/loader/mime_sniffing_throttle.cc
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
+
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/mime_sniffer.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "third_party/blink/public/common/loader/mime_sniffing_url_loader.h"
+
+namespace blink {
+
+MimeSniffingThrottle::MimeSniffingThrottle(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)) {}
+
+MimeSniffingThrottle::~MimeSniffingThrottle() = default;
+
+void MimeSniffingThrottle::WillProcessResponse(
+ const GURL& response_url,
+ network::ResourceResponseHead* response_head,
+ bool* defer) {
+ // No need to do mime sniffing again.
+ if (response_head->did_mime_sniff)
+ return;
+
+ bool blocked_sniffing_mime = false;
+ std::string content_type_options;
+ if (response_head->headers &&
+ response_head->headers->GetNormalizedHeader("x-content-type-options",
+ &content_type_options)) {
+ blocked_sniffing_mime =
+ base::LowerCaseEqualsASCII(content_type_options, "nosniff");
+ }
+
+ if (!blocked_sniffing_mime &&
+ net::ShouldSniffMimeType(response_url, response_head->mime_type)) {
+ // Pause the response until the mime type becomes ready.
+ *defer = true;
+
+ mojo::PendingRemote<network::mojom::URLLoader> new_remote;
+ mojo::PendingReceiver<network::mojom::URLLoaderClient> new_receiver;
+ network::mojom::URLLoaderPtr source_loader;
+ network::mojom::URLLoaderClientRequest source_client_request;
+ MimeSniffingURLLoader* mime_sniffing_loader;
+ std::tie(new_remote, new_receiver, mime_sniffing_loader) =
+ MimeSniffingURLLoader::CreateLoader(weak_factory_.GetWeakPtr(),
+ response_url, *response_head,
+ task_runner_);
+ delegate_->InterceptResponse(
+ network::mojom::URLLoaderPtr(std::move(new_remote)),
+ std::move(new_receiver), &source_loader, &source_client_request);
+ mime_sniffing_loader->Start(source_loader.PassInterface(),
+ std::move(source_client_request));
+ }
+}
+
+void MimeSniffingThrottle::ResumeWithNewResponseHead(
+ network::mojom::URLResponseHeadPtr new_response_head) {
+ delegate_->UpdateDeferredResponseHead(std::move(new_response_head));
+ delegate_->Resume();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc b/chromium/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc
new file mode 100644
index 00000000000..0286cce304c
--- /dev/null
+++ b/chromium/third_party/blink/common/loader/mime_sniffing_throttle_unittest.cc
@@ -0,0 +1,516 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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/loader/mime_sniffing_throttle.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/loader/mime_sniffing_url_loader.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+namespace {
+
+class MojoDataPipeSender {
+ public:
+ MojoDataPipeSender(mojo::ScopedDataPipeProducerHandle handle)
+ : handle_(std::move(handle)),
+ watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC) {}
+
+ void Start(std::string data, base::OnceClosure done_callback) {
+ data_ = std::move(data);
+ done_callback_ = std::move(done_callback);
+ watcher_.Watch(handle_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MojoDataPipeSender::OnWritable,
+ base::Unretained(this)));
+ }
+
+ void OnWritable(MojoResult) {
+ uint32_t sending_bytes = data_.size() - sent_bytes_;
+ MojoResult result = handle_->WriteData(
+ data_.c_str() + sent_bytes_, &sending_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // Finished unexpectedly.
+ std::move(done_callback_).Run();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ // Just wait until OnWritable() is called by the watcher.
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ sent_bytes_ += sending_bytes;
+ if (data_.size() == sent_bytes_)
+ std::move(done_callback_).Run();
+ }
+
+ mojo::ScopedDataPipeProducerHandle ReleaseHandle() {
+ return std::move(handle_);
+ }
+
+ bool has_succeeded() const { return data_.size() == sent_bytes_; }
+
+ private:
+ mojo::ScopedDataPipeProducerHandle handle_;
+ mojo::SimpleWatcher watcher_;
+ base::OnceClosure done_callback_;
+ std::string data_;
+ uint32_t sent_bytes_ = 0;
+};
+
+class MockDelegate : public blink::URLLoaderThrottle::Delegate {
+ public:
+ // Implements blink::URLLoaderThrottle::Delegate.
+ void CancelWithError(int error_code,
+ base::StringPiece custom_reason) override {
+ NOTIMPLEMENTED();
+ }
+ void Resume() override {
+ is_resumed_ = true;
+ // Resume from OnReceiveResponse() with a customized response header.
+ destination_loader_client()->OnReceiveResponse(
+ std::move(updated_response_head_));
+ }
+
+ void SetPriority(net::RequestPriority priority) override { NOTIMPLEMENTED(); }
+ void UpdateDeferredResponseHead(
+ network::mojom::URLResponseHeadPtr new_response_head) override {
+ updated_response_head_ = std::move(new_response_head);
+ }
+ void PauseReadingBodyFromNet() override { NOTIMPLEMENTED(); }
+ void ResumeReadingBodyFromNet() override { NOTIMPLEMENTED(); }
+ void InterceptResponse(
+ network::mojom::URLLoaderPtr new_loader,
+ network::mojom::URLLoaderClientRequest new_client_request,
+ network::mojom::URLLoaderPtr* original_loader,
+ network::mojom::URLLoaderClientRequest* original_client_request)
+ override {
+ is_intercepted_ = true;
+
+ destination_loader_ptr_ = std::move(new_loader);
+ ASSERT_TRUE(mojo::FuseInterface(
+ std::move(new_client_request),
+ destination_loader_client_.CreateInterfacePtr().PassInterface()));
+
+ mojo::PendingRemote<network::mojom::URLLoader> pending_remote;
+ pending_receiver_ = pending_remote.InitWithNewPipeAndPassReceiver();
+ original_loader->Bind(std::move(pending_remote));
+
+ *original_client_request =
+ source_loader_client_remote_.BindNewPipeAndPassReceiver();
+ }
+
+ void LoadResponseBody(const std::string& body) {
+ if (!source_body_handle_.is_valid()) {
+ // Send OnStartLoadingResponseBody() if it's the first call.
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ mojo::CreateDataPipe(nullptr, &source_body_handle_, &consumer));
+ source_loader_client_remote()->OnStartLoadingResponseBody(
+ std::move(consumer));
+ }
+
+ MojoDataPipeSender sender(std::move(source_body_handle_));
+ base::RunLoop loop;
+ sender.Start(body, loop.QuitClosure());
+ loop.Run();
+
+ EXPECT_TRUE(sender.has_succeeded());
+ source_body_handle_ = sender.ReleaseHandle();
+ }
+
+ void CompleteResponse() {
+ source_loader_client_remote()->OnComplete(
+ network::URLLoaderCompletionStatus());
+ source_body_handle_.reset();
+ }
+
+ uint32_t ReadResponseBody(uint32_t size) {
+ std::vector<uint8_t> buffer(size);
+ MojoResult result = destination_loader_client_.response_body().ReadData(
+ buffer.data(), &size, MOJO_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ return size;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ return 0;
+ case MOJO_RESULT_SHOULD_WAIT:
+ return 0;
+ default:
+ NOTREACHED();
+ }
+ return 0;
+ }
+
+ bool is_intercepted() const { return is_intercepted_; }
+ bool is_resumed() const { return is_resumed_; }
+
+ network::TestURLLoaderClient* destination_loader_client() {
+ return &destination_loader_client_;
+ }
+
+ mojo::Remote<network::mojom::URLLoaderClient>& source_loader_client_remote() {
+ return source_loader_client_remote_;
+ }
+
+ private:
+ bool is_intercepted_ = false;
+ bool is_resumed_ = false;
+ network::mojom::URLResponseHeadPtr updated_response_head_;
+
+ // A pair of a loader and a loader client for destination of the response.
+ network::mojom::URLLoaderPtr destination_loader_ptr_;
+ network::TestURLLoaderClient destination_loader_client_;
+
+ // A pair of a receiver and a remote for source of the response.
+ mojo::PendingReceiver<network::mojom::URLLoader> pending_receiver_;
+ mojo::Remote<network::mojom::URLLoaderClient> source_loader_client_remote_;
+
+ mojo::ScopedDataPipeProducerHandle source_body_handle_;
+};
+
+} // namespace
+
+class MimeSniffingThrottleTest : public testing::Test {
+ protected:
+ // Be the first member so it is destroyed last.
+ base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(MimeSniffingThrottleTest, NoMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NotSniffableMimeTypeWithSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/javascript";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NoMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NotSniffableMimeTypeWithNotSniffableScheme) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/javascript";
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("wss://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, SniffableButAlreadySniffed) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ network::ResourceResponseHead response_head;
+ response_head.mime_type = "text/plain";
+ response_head.did_mime_sniff = true;
+ bool defer = false;
+ throttle->WillProcessResponse(GURL("https://example.com"), &response_head,
+ &defer);
+ EXPECT_FALSE(defer);
+ EXPECT_FALSE(delegate->is_intercepted());
+}
+
+TEST_F(MimeSniffingThrottleTest, NoBody) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Call OnComplete() without sending body.
+ delegate->source_loader_client_remote()->OnComplete(
+ network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated to the default mime type ("text/plain").
+ EXPECT_TRUE(delegate->destination_loader_client()->has_received_response());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, EmptyBody) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &producer, &consumer));
+ delegate->source_loader_client_remote()->OnStartLoadingResponseBody(
+ std::move(consumer));
+ producer.reset(); // The pipe is empty.
+
+ delegate->source_loader_client_remote()->OnComplete(
+ network::URLLoaderCompletionStatus());
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated to the default mime type ("text/plain").
+ EXPECT_TRUE(delegate->destination_loader_client()->has_received_response());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_PlainText) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("This is a text.");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_Docx) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com/hogehoge.docx");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("application/msword",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_PNG) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com/hogehoge.docx");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body and complete the response.
+ delegate->LoadResponseBody("\x89PNG\x0D\x0A\x1A\x0A");
+ delegate->CompleteResponse();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("image/png",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Body_LongPlainText) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // 64KiB is coming from the default value used in
+ // mojo::core::Core::CreateDataPipe().
+ const uint32_t kDefaultDataPipeBufferSize = 64 * 1024;
+ std::string long_body(kDefaultDataPipeBufferSize * 2, 'x');
+
+ // Send the data to the MimeSniffingURLLoader.
+ // |delegate|'s MojoDataPipeSender sends the first
+ // |kDefaultDataPipeBufferSize| bytes to MimeSniffingURLLoader and
+ // MimeSniffingURLLoader will read the first |kDefaultDataPipeBufferSize|
+ // bytes of the body, so the MojoDataPipeSender can push the rest of
+ // |kDefaultDataPipeBufferSize| of the body soon and finishes sending the
+ // body. After this, MimeSniffingURLLoader is waiting to push the body to the
+ // destination data pipe since the pipe should be full until it's read.
+ delegate->LoadResponseBody(long_body);
+ task_environment_.RunUntilIdle();
+
+ // Send OnComplete() to the MimeSniffingURLLoader.
+ delegate->CompleteResponse();
+ task_environment_.RunUntilIdle();
+ // MimeSniffingURLLoader should not send OnComplete() to the destination
+ // client until it finished writing all the data.
+ EXPECT_FALSE(
+ delegate->destination_loader_client()->has_received_completion());
+
+ // Read the half of the body. This unblocks MimeSniffingURLLoader to push the
+ // rest of the body to the data pipe.
+ uint32_t read_bytes = delegate->ReadResponseBody(long_body.size() / 2);
+ task_environment_.RunUntilIdle();
+
+ // Read the rest of the body.
+ read_bytes += delegate->ReadResponseBody(long_body.size() / 2);
+ task_environment_.RunUntilIdle();
+ delegate->destination_loader_client()->RunUntilComplete();
+
+ // Check if all data has been read.
+ EXPECT_EQ(long_body.size(), read_bytes);
+
+ // The mime type should be updated.
+ EXPECT_TRUE(delegate->is_resumed());
+ EXPECT_EQ("text/plain",
+ delegate->destination_loader_client()->response_head()->mime_type);
+}
+
+TEST_F(MimeSniffingThrottleTest, Abort_NoBodyPipe) {
+ auto throttle = std::make_unique<MimeSniffingThrottle>(
+ task_environment_.GetMainThreadTaskRunner());
+ auto delegate = std::make_unique<MockDelegate>();
+ throttle->set_delegate(delegate.get());
+
+ GURL response_url("https://example.com");
+ network::ResourceResponseHead response_head;
+ bool defer = false;
+ throttle->WillProcessResponse(response_url, &response_head, &defer);
+ EXPECT_TRUE(defer);
+ EXPECT_TRUE(delegate->is_intercepted());
+
+ // Send the body
+ std::string body = "This should be long enough to complete sniffing.";
+ body.resize(1024, 'a');
+ delegate->LoadResponseBody(body);
+ task_environment_.RunUntilIdle();
+
+ // Release a pipe for the body on the receiver side.
+ delegate->destination_loader_client()->response_body_release();
+ task_environment_.RunUntilIdle();
+
+ // Send the body after the pipe is closed. The the loader aborts.
+ delegate->LoadResponseBody("This is a text.");
+
+ // Calling OnComplete should not crash.
+ delegate->CompleteResponse();
+ task_environment_.RunUntilIdle();
+}
+
+} // 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
new file mode 100644
index 00000000000..86b3b10b17f
--- /dev/null
+++ b/chromium/third_party/blink/common/loader/mime_sniffing_url_loader.cc
@@ -0,0 +1,373 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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/loader/mime_sniffing_url_loader.h"
+
+#include "base/bind.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "net/base/mime_sniffer.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
+
+namespace blink {
+
+// static
+const char MimeSniffingURLLoader::kDefaultMimeType[] = "text/plain";
+
+// static
+std::tuple<mojo::PendingRemote<network::mojom::URLLoader>,
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>,
+ MimeSniffingURLLoader*>
+MimeSniffingURLLoader::CreateLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ mojo::PendingRemote<network::mojom::URLLoader> url_loader;
+ mojo::PendingRemote<network::mojom::URLLoaderClient> url_loader_client;
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
+ url_loader_client_receiver =
+ url_loader_client.InitWithNewPipeAndPassReceiver();
+
+ auto loader = base::WrapUnique(new MimeSniffingURLLoader(
+ std::move(throttle), response_url, std::move(response_head),
+ std::move(url_loader_client), std::move(task_runner)));
+ MimeSniffingURLLoader* loader_rawptr = loader.get();
+ mojo::MakeSelfOwnedReceiver(std::move(loader),
+ url_loader.InitWithNewPipeAndPassReceiver());
+ return std::make_tuple(std::move(url_loader),
+ std::move(url_loader_client_receiver), loader_rawptr);
+}
+
+MimeSniffingURLLoader::MimeSniffingURLLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::PendingRemote<network::mojom::URLLoaderClient>
+ destination_url_loader_client,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : throttle_(throttle),
+ destination_url_loader_client_(std::move(destination_url_loader_client)),
+ response_url_(response_url),
+ response_head_(std::move(response_head)),
+ task_runner_(task_runner),
+ body_consumer_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ task_runner),
+ body_producer_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ std::move(task_runner)) {}
+
+MimeSniffingURLLoader::~MimeSniffingURLLoader() = default;
+
+void MimeSniffingURLLoader::Start(
+ mojo::PendingRemote<network::mojom::URLLoader> source_url_loader_remote,
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
+ source_url_client_receiver) {
+ source_url_loader_.Bind(std::move(source_url_loader_remote));
+ source_url_client_receiver_.Bind(std::move(source_url_client_receiver),
+ task_runner_);
+}
+
+void MimeSniffingURLLoader::OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr response_head) {
+ // OnReceiveResponse() shouldn't be called because MimeSniffingURLLoader is
+ // created by MimeSniffingThrottle::WillProcessResponse(), which is equivalent
+ // to OnReceiveResponse().
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr response_head) {
+ // OnReceiveRedirect() shouldn't be called because MimeSniffingURLLoader is
+ // created by MimeSniffingThrottle::WillProcessResponse(), which is equivalent
+ // to OnReceiveResponse().
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback ack_callback) {
+ destination_url_loader_client_->OnUploadProgress(current_position, total_size,
+ std::move(ack_callback));
+}
+
+void MimeSniffingURLLoader::OnReceiveCachedMetadata(mojo_base::BigBuffer data) {
+ destination_url_loader_client_->OnReceiveCachedMetadata(std::move(data));
+}
+
+void MimeSniffingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
+ destination_url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
+}
+
+void MimeSniffingURLLoader::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) {
+ state_ = State::kSniffing;
+ body_consumer_handle_ = std::move(body);
+ body_consumer_watcher_.Watch(
+ body_consumer_handle_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MimeSniffingURLLoader::OnBodyReadable,
+ base::Unretained(this)));
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ DCHECK(!complete_status_.has_value());
+ switch (state_) {
+ case State::kWaitForBody:
+ // An error occured before receiving any data.
+ DCHECK_NE(net::OK, status.error_code);
+ state_ = State::kCompleted;
+ response_head_->mime_type = kDefaultMimeType;
+ if (!throttle_) {
+ Abort();
+ return;
+ }
+ throttle_->ResumeWithNewResponseHead(std::move(response_head_));
+ destination_url_loader_client_->OnComplete(status);
+ return;
+ case State::kSniffing:
+ case State::kSending:
+ // Defer calling OnComplete() until mime sniffing has finished and all
+ // data is sent.
+ complete_status_ = status;
+ return;
+ case State::kCompleted:
+ destination_url_loader_client_->OnComplete(status);
+ return;
+ case State::kAborted:
+ NOTREACHED();
+ return;
+ }
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::FollowRedirect(
+ const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const base::Optional<GURL>& new_url) {
+ // MimeSniffingURLLoader starts handling the request after
+ // OnReceivedResponse(). A redirect response is not expected.
+ NOTREACHED();
+}
+
+void MimeSniffingURLLoader::SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->SetPriority(priority, intra_priority_value);
+}
+
+void MimeSniffingURLLoader::PauseReadingBodyFromNet() {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->PauseReadingBodyFromNet();
+}
+
+void MimeSniffingURLLoader::ResumeReadingBodyFromNet() {
+ if (state_ == State::kAborted)
+ return;
+ source_url_loader_->ResumeReadingBodyFromNet();
+}
+
+void MimeSniffingURLLoader::OnBodyReadable(MojoResult) {
+ if (state_ == State::kSending) {
+ // The pipe becoming readable when kSending means all buffered body has
+ // already been sent.
+ ForwardBodyToClient();
+ return;
+ }
+ DCHECK_EQ(State::kSniffing, state_);
+
+ size_t start_size = buffered_body_.size();
+ uint32_t read_bytes = net::kMaxBytesToSniff;
+ buffered_body_.resize(start_size + read_bytes);
+ MojoResult result =
+ body_consumer_handle_->ReadData(buffered_body_.data() + start_size,
+ &read_bytes, MOJO_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // Finished the body before mime type is completely decided.
+ buffered_body_.resize(start_size);
+ CompleteSniffing();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK_EQ(MOJO_RESULT_OK, result);
+ buffered_body_.resize(start_size + read_bytes);
+ std::string new_type;
+ bool made_final_decision =
+ net::SniffMimeType(buffered_body_.data(), buffered_body_.size(),
+ response_url_, response_head_->mime_type,
+ net::ForceSniffFileUrlsForHtml::kDisabled, &new_type);
+ response_head_->mime_type = new_type;
+ response_head_->did_mime_sniff = true;
+ if (made_final_decision) {
+ CompleteSniffing();
+ return;
+ }
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::OnBodyWritable(MojoResult) {
+ DCHECK_EQ(State::kSending, state_);
+ if (bytes_remaining_in_buffer_ > 0) {
+ SendReceivedBodyToClient();
+ } else {
+ ForwardBodyToClient();
+ }
+}
+
+void MimeSniffingURLLoader::CompleteSniffing() {
+ DCHECK_EQ(State::kSniffing, state_);
+ if (buffered_body_.empty()) {
+ // The URLLoader ended before sending any data. There is not enough
+ // information to determine the MIME type.
+ response_head_->mime_type = kDefaultMimeType;
+ }
+
+ state_ = State::kSending;
+ bytes_remaining_in_buffer_ = buffered_body_.size();
+ if (!throttle_) {
+ Abort();
+ return;
+ }
+ throttle_->ResumeWithNewResponseHead(std::move(response_head_));
+ mojo::ScopedDataPipeConsumerHandle body_to_send;
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &body_producer_handle_, &body_to_send);
+ if (result != MOJO_RESULT_OK) {
+ Abort();
+ return;
+ }
+ // Set up the watcher for the producer handle.
+ body_producer_watcher_.Watch(
+ body_producer_handle_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ base::BindRepeating(&MimeSniffingURLLoader::OnBodyWritable,
+ base::Unretained(this)));
+
+ // Send deferred message.
+ destination_url_loader_client_->OnStartLoadingResponseBody(
+ std::move(body_to_send));
+
+ if (bytes_remaining_in_buffer_) {
+ SendReceivedBodyToClient();
+ return;
+ }
+
+ CompleteSending();
+}
+
+void MimeSniffingURLLoader::CompleteSending() {
+ DCHECK_EQ(State::kSending, state_);
+ state_ = State::kCompleted;
+ // Call client's OnComplete() if |this|'s OnComplete() has already been
+ // called.
+ if (complete_status_.has_value())
+ destination_url_loader_client_->OnComplete(complete_status_.value());
+
+ body_consumer_watcher_.Cancel();
+ body_producer_watcher_.Cancel();
+ body_consumer_handle_.reset();
+ body_producer_handle_.reset();
+}
+
+void MimeSniffingURLLoader::SendReceivedBodyToClient() {
+ DCHECK_EQ(State::kSending, state_);
+ // Send the buffered data first.
+ DCHECK_GT(bytes_remaining_in_buffer_, 0u);
+ size_t start_position = buffered_body_.size() - bytes_remaining_in_buffer_;
+ uint32_t bytes_sent = bytes_remaining_in_buffer_;
+ MojoResult result =
+ body_producer_handle_->WriteData(buffered_body_.data() + start_position,
+ &bytes_sent, MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // The pipe is closed unexpectedly. |this| should be deleted once
+ // URLLoaderPtr on the destination is released.
+ Abort();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_producer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ bytes_remaining_in_buffer_ -= bytes_sent;
+ body_producer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::ForwardBodyToClient() {
+ DCHECK_EQ(0u, bytes_remaining_in_buffer_);
+ // Send the body from the consumer to the producer.
+ const void* buffer;
+ uint32_t buffer_size = 0;
+ MojoResult result = body_consumer_handle_->BeginReadData(
+ &buffer, &buffer_size, MOJO_BEGIN_READ_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_watcher_.ArmOrNotify();
+ return;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // All data has been sent.
+ CompleteSending();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ result = body_producer_handle_->WriteData(buffer, &buffer_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ switch (result) {
+ case MOJO_RESULT_OK:
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ // The pipe is closed unexpectedly. |this| should be deleted once
+ // URLLoaderPtr on the destination is released.
+ Abort();
+ return;
+ case MOJO_RESULT_SHOULD_WAIT:
+ body_consumer_handle_->EndReadData(0);
+ body_producer_watcher_.ArmOrNotify();
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+
+ body_consumer_handle_->EndReadData(buffer_size);
+ body_consumer_watcher_.ArmOrNotify();
+}
+
+void MimeSniffingURLLoader::Abort() {
+ state_ = State::kAborted;
+ body_consumer_watcher_.Cancel();
+ body_producer_watcher_.Cancel();
+ source_url_loader_.reset();
+ source_url_client_receiver_.reset();
+ destination_url_loader_client_.reset();
+ // |this| should be removed since the owner will destroy |this| or the owner
+ // has already been destroyed by some reason.
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/loader/request_destination.cc b/chromium/third_party/blink/common/loader/request_destination.cc
index 3c72936c01a..a41401d96f2 100644
--- a/chromium/third_party/blink/common/loader/request_destination.cc
+++ b/chromium/third_party/blink/common/loader/request_destination.cc
@@ -28,8 +28,10 @@ const char* GetRequestDestinationFromContext(
case mojom::RequestContextType::FONT:
return "font";
case mojom::RequestContextType::FRAME:
- case mojom::RequestContextType::HYPERLINK:
+ return "frame";
case mojom::RequestContextType::IFRAME:
+ return "iframe";
+ case mojom::RequestContextType::HYPERLINK:
case mojom::RequestContextType::LOCATION:
case mojom::RequestContextType::FORM:
return "document";
diff --git a/chromium/third_party/blink/common/loader/url_loader_factory_bundle.cc b/chromium/third_party/blink/common/loader/url_loader_factory_bundle.cc
index d75d273dc5b..d45b4cd88c8 100644
--- a/chromium/third_party/blink/common/loader/url_loader_factory_bundle.cc
+++ b/chromium/third_party/blink/common/loader/url_loader_factory_bundle.cc
@@ -39,13 +39,13 @@ URLLoaderFactoryBundleInfo::URLLoaderFactoryBundleInfo(
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_default_factory,
SchemeMap pending_scheme_specific_factories,
- OriginMap pending_initiator_specific_factories,
+ OriginMap pending_isolated_world_factories,
bool bypass_redirect_checks)
: pending_default_factory_(std::move(pending_default_factory)),
pending_scheme_specific_factories_(
std::move(pending_scheme_specific_factories)),
- pending_initiator_specific_factories_(
- std::move(pending_initiator_specific_factories)),
+ pending_isolated_world_factories_(
+ std::move(pending_isolated_world_factories)),
bypass_redirect_checks_(bypass_redirect_checks) {}
URLLoaderFactoryBundleInfo::~URLLoaderFactoryBundleInfo() = default;
@@ -57,8 +57,8 @@ URLLoaderFactoryBundleInfo::CreateFactory() {
other->pending_appcache_factory_ = std::move(pending_appcache_factory_);
other->pending_scheme_specific_factories_ =
std::move(pending_scheme_specific_factories_);
- other->pending_initiator_specific_factories_ =
- std::move(pending_initiator_specific_factories_);
+ other->pending_isolated_world_factories_ =
+ std::move(pending_isolated_world_factories_);
other->bypass_redirect_checks_ = bypass_redirect_checks_;
return base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(other));
@@ -81,10 +81,10 @@ network::mojom::URLLoaderFactory* URLLoaderFactoryBundle::GetFactory(
if (it != scheme_specific_factories_.end())
return it->second.get();
- if (request.request_initiator.has_value()) {
+ if (request.isolated_world_origin.has_value()) {
auto it2 =
- initiator_specific_factories_.find(request.request_initiator.value());
- if (it2 != initiator_specific_factories_.end())
+ isolated_world_factories_.find(request.isolated_world_origin.value());
+ if (it2 != isolated_world_factories_.end())
return it2->second.get();
}
@@ -92,7 +92,7 @@ network::mojom::URLLoaderFactory* URLLoaderFactoryBundle::GetFactory(
if (appcache_factory_)
return appcache_factory_.get();
- return default_factory_.get();
+ return default_factory_.is_bound() ? default_factory_.get() : nullptr;
}
void URLLoaderFactoryBundle::CreateLoaderAndStart(
@@ -110,7 +110,7 @@ void URLLoaderFactoryBundle::CreateLoaderAndStart(
}
void URLLoaderFactoryBundle::Clone(
- network::mojom::URLLoaderFactoryRequest request) {
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
NOTREACHED();
}
@@ -125,7 +125,7 @@ URLLoaderFactoryBundle::Clone() {
auto pending_factories = std::make_unique<blink::URLLoaderFactoryBundleInfo>(
std::move(pending_default_factory),
CloneRemoteMapToPendingRemoteMap(scheme_specific_factories_),
- CloneRemoteMapToPendingRemoteMap(initiator_specific_factories_),
+ CloneRemoteMapToPendingRemoteMap(isolated_world_factories_),
bypass_redirect_checks_);
if (appcache_factory_) {
@@ -143,10 +143,12 @@ bool URLLoaderFactoryBundle::BypassRedirectChecks() const {
void URLLoaderFactoryBundle::Update(
std::unique_ptr<URLLoaderFactoryBundleInfo> pending_factories) {
if (pending_factories->pending_default_factory()) {
+ default_factory_.reset();
default_factory_.Bind(
std::move(pending_factories->pending_default_factory()));
}
if (pending_factories->pending_appcache_factory()) {
+ appcache_factory_.reset();
appcache_factory_.Bind(
std::move(pending_factories->pending_appcache_factory()));
}
@@ -154,8 +156,8 @@ void URLLoaderFactoryBundle::Update(
&scheme_specific_factories_,
std::move(pending_factories->pending_scheme_specific_factories()));
BindPendingRemoteMapToRemoteMap(
- &initiator_specific_factories_,
- std::move(pending_factories->pending_initiator_specific_factories()));
+ &isolated_world_factories_,
+ std::move(pending_factories->pending_isolated_world_factories()));
bypass_redirect_checks_ = pending_factories->bypass_redirect_checks();
}
diff --git a/chromium/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc b/chromium/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
index f63b571f91b..447a23f99e7 100644
--- a/chromium/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
+++ b/chromium/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
@@ -15,13 +15,13 @@ using Traits = StructTraits<blink::mojom::URLLoaderFactoryBundleDataView,
std::unique_ptr<blink::URLLoaderFactoryBundleInfo>>;
// static
-network::mojom::URLLoaderFactoryPtrInfo Traits::default_factory(
+mojo::PendingRemote<network::mojom::URLLoaderFactory> Traits::default_factory(
BundleInfoType& bundle) {
return std::move(bundle->pending_default_factory());
}
// static
-network::mojom::URLLoaderFactoryPtrInfo Traits::appcache_factory(
+mojo::PendingRemote<network::mojom::URLLoaderFactory> Traits::appcache_factory(
BundleInfoType& bundle) {
return std::move(bundle->pending_appcache_factory());
}
@@ -33,9 +33,9 @@ blink::URLLoaderFactoryBundleInfo::SchemeMap Traits::scheme_specific_factories(
}
// static
-blink::URLLoaderFactoryBundleInfo::OriginMap
-Traits::initiator_specific_factories(BundleInfoType& bundle) {
- return std::move(bundle->pending_initiator_specific_factories());
+blink::URLLoaderFactoryBundleInfo::OriginMap Traits::isolated_world_factories(
+ BundleInfoType& bundle) {
+ return std::move(bundle->pending_isolated_world_factories());
}
// static
@@ -56,8 +56,8 @@ bool Traits::Read(blink::mojom::URLLoaderFactoryBundleDataView data,
&(*out_bundle)->pending_scheme_specific_factories())) {
return false;
}
- if (!data.ReadInitiatorSpecificFactories(
- &(*out_bundle)->pending_initiator_specific_factories())) {
+ if (!data.ReadIsolatedWorldFactories(
+ &(*out_bundle)->pending_isolated_world_factories())) {
return false;
}
diff --git a/chromium/third_party/blink/common/loader/url_loader_throttle.cc b/chromium/third_party/blink/common/loader/url_loader_throttle.cc
index 6f4bf736427..bb691fbf627 100644
--- a/chromium/third_party/blink/common/loader/url_loader_throttle.cc
+++ b/chromium/third_party/blink/common/loader/url_loader_throttle.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "base/logging.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_response_head.mojom.h"
namespace blink {
@@ -13,7 +15,7 @@ void URLLoaderThrottle::Delegate::UpdateDeferredRequestHeaders(
const net::HttpRequestHeaders& modified_request_headers,
const net::HttpRequestHeaders& modified_cors_exempt_request_headers) {}
void URLLoaderThrottle::Delegate::UpdateDeferredResponseHead(
- const network::ResourceResponseHead& new_response_head) {}
+ network::mojom::URLResponseHeadPtr new_response_head) {}
void URLLoaderThrottle::Delegate::PauseReadingBodyFromNet() {}
void URLLoaderThrottle::Delegate::ResumeReadingBodyFromNet() {}
diff --git a/chromium/third_party/blink/common/logging/logging_utils.cc b/chromium/third_party/blink/common/logging/logging_utils.cc
index 1d35e235547..cbe5692bc1e 100644
--- a/chromium/third_party/blink/common/logging/logging_utils.cc
+++ b/chromium/third_party/blink/common/logging/logging_utils.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/public/common/logging/logging_utils.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+
namespace blink {
logging::LogSeverity ConsoleMessageLevelToLogSeverity(
diff --git a/chromium/third_party/blink/common/manifest/manifest.cc b/chromium/third_party/blink/common/manifest/manifest.cc
index e27e2308921..076ef43e723 100644
--- a/chromium/third_party/blink/common/manifest/manifest.cc
+++ b/chromium/third_party/blink/common/manifest/manifest.cc
@@ -30,7 +30,7 @@ Manifest::RelatedApplication::RelatedApplication() = default;
Manifest::RelatedApplication::~RelatedApplication() = default;
Manifest::Manifest()
- : display(blink::kWebDisplayModeUndefined),
+ : display(blink::mojom::DisplayMode::kUndefined),
orientation(blink::kWebScreenOrientationLockDefault),
prefer_related_applications(false) {}
@@ -40,7 +40,7 @@ Manifest::~Manifest() = default;
bool Manifest::IsEmpty() const {
return name.is_null() && short_name.is_null() && start_url.is_empty() &&
- display == blink::kWebDisplayModeUndefined &&
+ display == blink::mojom::DisplayMode::kUndefined &&
orientation == blink::kWebScreenOrientationLockDefault &&
icons.empty() && !share_target.has_value() &&
related_applications.empty() && !prefer_related_applications &&
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 167eb1c4fd1..8b8dcae9472 100644
--- a/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_mojom_traits.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "mojo/public/cpp/base/string16_mojom_traits.h"
-#include "third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h"
#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_mojom_traits.h"
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
diff --git a/chromium/third_party/blink/common/manifest/manifest_util.cc b/chromium/third_party/blink/common/manifest/manifest_util.cc
index 63611e55866..7cf3f038d21 100644
--- a/chromium/third_party/blink/common/manifest/manifest_util.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_util.cc
@@ -5,35 +5,36 @@
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "base/strings/string_util.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
namespace blink {
-std::string WebDisplayModeToString(blink::WebDisplayMode display) {
+std::string DisplayModeToString(blink::mojom::DisplayMode display) {
switch (display) {
- case blink::kWebDisplayModeUndefined:
+ case blink::mojom::DisplayMode::kUndefined:
return "";
- case blink::kWebDisplayModeBrowser:
+ case blink::mojom::DisplayMode::kBrowser:
return "browser";
- case blink::kWebDisplayModeMinimalUi:
+ case blink::mojom::DisplayMode::kMinimalUi:
return "minimal-ui";
- case blink::kWebDisplayModeStandalone:
+ case blink::mojom::DisplayMode::kStandalone:
return "standalone";
- case blink::kWebDisplayModeFullscreen:
+ case blink::mojom::DisplayMode::kFullscreen:
return "fullscreen";
}
return "";
}
-blink::WebDisplayMode WebDisplayModeFromString(const std::string& display) {
+blink::mojom::DisplayMode DisplayModeFromString(const std::string& display) {
if (base::LowerCaseEqualsASCII(display, "browser"))
- return blink::kWebDisplayModeBrowser;
+ return blink::mojom::DisplayMode::kBrowser;
if (base::LowerCaseEqualsASCII(display, "minimal-ui"))
- return blink::kWebDisplayModeMinimalUi;
+ return blink::mojom::DisplayMode::kMinimalUi;
if (base::LowerCaseEqualsASCII(display, "standalone"))
- return blink::kWebDisplayModeStandalone;
+ return blink::mojom::DisplayMode::kStandalone;
if (base::LowerCaseEqualsASCII(display, "fullscreen"))
- return blink::kWebDisplayModeFullscreen;
- return blink::kWebDisplayModeUndefined;
+ return blink::mojom::DisplayMode::kFullscreen;
+ return blink::mojom::DisplayMode::kUndefined;
}
std::string WebScreenOrientationLockTypeToString(
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 b37faa2223a..594c19b1eef 100644
--- a/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc
+++ b/chromium/third_party/blink/common/manifest/manifest_util_unittest.cc
@@ -8,34 +8,33 @@
namespace blink {
-TEST(ManifestUtilTest, WebDisplayModeConversions) {
+TEST(ManifestUtilTest, DisplayModeConversions) {
struct ReversibleConversion {
- blink::WebDisplayMode display_mode;
+ blink::mojom::DisplayMode display_mode;
std::string lowercase_display_mode_string;
} reversible_conversions[] = {
- {blink::kWebDisplayModeUndefined, ""},
- {blink::kWebDisplayModeBrowser, "browser"},
- {blink::kWebDisplayModeMinimalUi, "minimal-ui"},
- {blink::kWebDisplayModeStandalone, "standalone"},
- {blink::kWebDisplayModeFullscreen, "fullscreen"},
+ {blink::mojom::DisplayMode::kUndefined, ""},
+ {blink::mojom::DisplayMode::kBrowser, "browser"},
+ {blink::mojom::DisplayMode::kMinimalUi, "minimal-ui"},
+ {blink::mojom::DisplayMode::kStandalone, "standalone"},
+ {blink::mojom::DisplayMode::kFullscreen, "fullscreen"},
};
for (const ReversibleConversion& conversion : reversible_conversions) {
- EXPECT_EQ(
- conversion.display_mode,
- WebDisplayModeFromString(conversion.lowercase_display_mode_string));
+ EXPECT_EQ(conversion.display_mode,
+ DisplayModeFromString(conversion.lowercase_display_mode_string));
EXPECT_EQ(conversion.lowercase_display_mode_string,
- WebDisplayModeToString(conversion.display_mode));
+ DisplayModeToString(conversion.display_mode));
}
- // WebDisplayModeFromString() should work with non-lowercase strings.
- EXPECT_EQ(blink::kWebDisplayModeFullscreen,
- WebDisplayModeFromString("Fullscreen"));
+ // DisplayModeFromString() should work with non-lowercase strings.
+ EXPECT_EQ(blink::mojom::DisplayMode::kFullscreen,
+ DisplayModeFromString("Fullscreen"));
- // WebDisplayModeFromString() should return
- // blink::WebDisplayModeUndefined if the string isn't known.
- EXPECT_EQ(blink::kWebDisplayModeUndefined,
- WebDisplayModeFromString("random"));
+ // DisplayModeFromString() should return
+ // DisplayMode::kUndefined if the string isn't known.
+ EXPECT_EQ(blink::mojom::DisplayMode::kUndefined,
+ DisplayModeFromString("random"));
}
TEST(ManifestUtilTest, WebScreenOrientationLockTypeConversions) {
diff --git a/chromium/third_party/blink/common/mediastream/media_devices.cc b/chromium/third_party/blink/common/mediastream/media_devices.cc
index 93df20102b9..3661b4b6587 100644
--- a/chromium/third_party/blink/common/mediastream/media_devices.cc
+++ b/chromium/third_party/blink/common/mediastream/media_devices.cc
@@ -13,8 +13,7 @@ WebMediaDeviceInfo::WebMediaDeviceInfo()
WebMediaDeviceInfo::WebMediaDeviceInfo(const WebMediaDeviceInfo& other) =
default;
-WebMediaDeviceInfo::WebMediaDeviceInfo(WebMediaDeviceInfo&& other) noexcept =
- default;
+WebMediaDeviceInfo::WebMediaDeviceInfo(WebMediaDeviceInfo&& other) = default;
WebMediaDeviceInfo::WebMediaDeviceInfo(const std::string& device_id,
const std::string& label,
@@ -36,8 +35,8 @@ WebMediaDeviceInfo::~WebMediaDeviceInfo() = default;
WebMediaDeviceInfo& WebMediaDeviceInfo::operator=(
const WebMediaDeviceInfo& other) = default;
-WebMediaDeviceInfo& WebMediaDeviceInfo::operator=(
- WebMediaDeviceInfo&& other) noexcept = default;
+WebMediaDeviceInfo& WebMediaDeviceInfo::operator=(WebMediaDeviceInfo&& other) =
+ default;
bool operator==(const WebMediaDeviceInfo& first,
const WebMediaDeviceInfo& second) {
diff --git a/chromium/third_party/blink/common/messaging/cloneable_message.cc b/chromium/third_party/blink/common/messaging/cloneable_message.cc
index 75fd2b4ae12..5c3ee7e8dd9 100644
--- a/chromium/third_party/blink/common/messaging/cloneable_message.cc
+++ b/chromium/third_party/blink/common/messaging/cloneable_message.cc
@@ -4,15 +4,16 @@
#include "third_party/blink/public/common/messaging/cloneable_message.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/messaging/cloneable_message.mojom.h"
namespace blink {
CloneableMessage::CloneableMessage() = default;
-CloneableMessage::CloneableMessage(CloneableMessage&&) noexcept = default;
-CloneableMessage& CloneableMessage::operator=(CloneableMessage&&) noexcept =
- default;
+CloneableMessage::CloneableMessage(CloneableMessage&&) = default;
+CloneableMessage& CloneableMessage::operator=(CloneableMessage&&) = default;
CloneableMessage::~CloneableMessage() = default;
CloneableMessage CloneableMessage::ShallowClone() const {
@@ -22,17 +23,17 @@ CloneableMessage CloneableMessage::ShallowClone() const {
// NOTE: We dubiously exercise dual ownership of the blob's pipe handle here
// so that we can temporarily bind and send a message over the pipe without
// mutating the state of this CloneableMessage.
- mojo::ScopedMessagePipeHandle handle(blob->blob.handle().get());
- mojom::BlobPtr blob_proxy(
- mojom::BlobPtrInfo(std::move(handle), blob->blob.version()));
- mojom::BlobPtrInfo blob_clone_info;
- blob_proxy->Clone(MakeRequest(&blob_clone_info));
+ mojo::ScopedMessagePipeHandle handle(blob->blob.Pipe().get());
+ mojo::Remote<mojom::Blob> blob_proxy(mojo::PendingRemote<mojom::Blob>(
+ std::move(handle), blob->blob.version()));
+ mojo::PendingRemote<mojom::Blob> blob_clone_remote;
+ blob_proxy->Clone(blob_clone_remote.InitWithNewPipeAndPassReceiver());
clone.blobs.push_back(
mojom::SerializedBlob::New(blob->uuid, blob->content_type, blob->size,
- std::move(blob_clone_info)));
+ std::move(blob_clone_remote)));
// Not leaked - still owned by |blob->blob|.
- ignore_result(blob_proxy.PassInterface().PassHandle().release());
+ ignore_result(blob_proxy.Unbind().PassPipe().release());
}
return clone;
}
diff --git a/chromium/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc b/chromium/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
index b920c9e13d3..1df77e5e7be 100644
--- a/chromium/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
+++ b/chromium/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
@@ -32,6 +32,7 @@ bool StructTraits<blink::mojom::CloneableMessage::DataView,
out->stack_trace_id = data.stack_trace_id();
out->stack_trace_debugger_id_first = data.stack_trace_debugger_id_first();
out->stack_trace_debugger_id_second = data.stack_trace_debugger_id_second();
+ out->stack_trace_should_pause = data.stack_trace_should_pause();
out->locked_agent_cluster_id = locked_agent_cluster_id;
return true;
}
diff --git a/chromium/third_party/blink/common/messaging/transferable_message.cc b/chromium/third_party/blink/common/messaging/transferable_message.cc
index 07ac9bbce4c..4a69d0aa714 100644
--- a/chromium/third_party/blink/common/messaging/transferable_message.cc
+++ b/chromium/third_party/blink/common/messaging/transferable_message.cc
@@ -9,10 +9,9 @@
namespace blink {
TransferableMessage::TransferableMessage() = default;
-TransferableMessage::TransferableMessage(TransferableMessage&&) noexcept =
+TransferableMessage::TransferableMessage(TransferableMessage&&) = default;
+TransferableMessage& TransferableMessage::operator=(TransferableMessage&&) =
default;
-TransferableMessage& TransferableMessage::operator=(
- TransferableMessage&&) noexcept = default;
TransferableMessage::~TransferableMessage() = default;
} // namespace blink
diff --git a/chromium/third_party/blink/common/notifications/notification_mojom_traits.cc b/chromium/third_party/blink/common/notifications/notification_mojom_traits.cc
index 67d0c4b74f2..140cf774e4a 100644
--- a/chromium/third_party/blink/common/notifications/notification_mojom_traits.cc
+++ b/chromium/third_party/blink/common/notifications/notification_mojom_traits.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/public/common/notifications/notification_mojom_traits.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom.h"
namespace {
diff --git a/chromium/third_party/blink/common/notifications/platform_notification_data.cc b/chromium/third_party/blink/common/notifications/platform_notification_data.cc
index 8de726b5ea9..a67dc2b0322 100644
--- a/chromium/third_party/blink/common/notifications/platform_notification_data.cc
+++ b/chromium/third_party/blink/common/notifications/platform_notification_data.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/public/common/notifications/platform_notification_data.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom.h"
namespace blink {
@@ -13,7 +14,8 @@ PlatformNotificationAction::PlatformNotificationAction(
PlatformNotificationAction::~PlatformNotificationAction() {}
-PlatformNotificationData::PlatformNotificationData() {}
+PlatformNotificationData::PlatformNotificationData()
+ : direction(mojom::NotificationDirection::LEFT_TO_RIGHT) {}
PlatformNotificationData::PlatformNotificationData(
const PlatformNotificationData& other) = default;
diff --git a/chromium/third_party/blink/common/origin_policy/origin_policy_unittest.cc b/chromium/third_party/blink/common/origin_policy/origin_policy_unittest.cc
index a27115a7f0a..dcfc34f0050 100644
--- a/chromium/third_party/blink/common/origin_policy/origin_policy_unittest.cc
+++ b/chromium/third_party/blink/common/origin_policy/origin_policy_unittest.cc
@@ -232,7 +232,7 @@ TEST(OriginPolicy, FirstPartySetMissingScheme) {
ASSERT_EQ(0U, policy->GetFirstPartySet().size());
}
-// Since we use json_parser, and it has the `KEEP_LAST_OF_DUPES` behaviour when
+// Since we use json_parser, and it keeps the last of duplicated elements when
// parsing, the last "first-party-set" is the "true" one.
// TODO(andypaicu): figure out if this is fine, or if it needs to change
TEST(OriginPolicy, FirstPartySetMultipleLists) {
diff --git a/chromium/third_party/blink/common/page/page_zoom.cc b/chromium/third_party/blink/common/page/page_zoom.cc
new file mode 100644
index 00000000000..a372e0ab122
--- /dev/null
+++ b/chromium/third_party/blink/common/page/page_zoom.cc
@@ -0,0 +1,41 @@
+// 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/common/page/page_zoom.h"
+
+#include <cmath>
+
+namespace blink {
+
+// The minimum and maximum amount of page zoom that is possible, independent
+// of other factors such as device scale and page scale (pinch). Historically,
+// these values came from WebKitLegacy/mac/WebView/WebView.mm where they are
+// named MinimumZoomMultiplier and MaximumZoomMultiplier. But chromium has
+// changed to use different limits.
+const double kMinimumPageZoomFactor = 0.25;
+const double kMaximumPageZoomFactor = 5.0;
+
+// Change the zoom factor by 20% for each zoom level increase from the user.
+// Historically, this value came from WebKit in
+// WebKitLegacy/mac/WebView/WebView.mm (named as ZoomMultiplierRatio there).
+static const double kTextSizeMultiplierRatio = 1.2;
+
+double PageZoomLevelToZoomFactor(double zoom_level) {
+ return std::pow(kTextSizeMultiplierRatio, zoom_level);
+}
+
+double PageZoomFactorToZoomLevel(double factor) {
+ return std::log(factor) / std::log(kTextSizeMultiplierRatio);
+}
+
+bool PageZoomValuesEqual(double value_a, double value_b) {
+ // Epsilon value for comparing two floating-point zoom values. We don't use
+ // std::numeric_limits<> because it is too precise for zoom values. Zoom
+ // values lose precision due to factor/level conversions. A value of 0.001
+ // is precise enough for zoom value comparisons.
+ const double kPageZoomEpsilon = 0.001;
+ return (std::fabs(value_a - value_b) <= kPageZoomEpsilon);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/peerconnection/webrtc_ip_handling_policy.cc b/chromium/third_party/blink/common/peerconnection/webrtc_ip_handling_policy.cc
new file mode 100644
index 00000000000..942bc14c6ac
--- /dev/null
+++ b/chromium/third_party/blink/common/peerconnection/webrtc_ip_handling_policy.cc
@@ -0,0 +1,17 @@
+// 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/common/peerconnection/webrtc_ip_handling_policy.h"
+
+namespace blink {
+
+// The set of strings here need to match what's specified in privacy.json.
+const char kWebRTCIPHandlingDefault[] = "default";
+const char kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces[] =
+ "default_public_and_private_interfaces";
+const char kWebRTCIPHandlingDefaultPublicInterfaceOnly[] =
+ "default_public_interface_only";
+const char kWebRTCIPHandlingDisableNonProxiedUdp[] = "disable_non_proxied_udp";
+
+} // namespace blink
diff --git a/chromium/third_party/blink/common/privacy_preferences.cc b/chromium/third_party/blink/common/privacy_preferences.cc
deleted file mode 100644
index 48351fa9c9c..00000000000
--- a/chromium/third_party/blink/common/privacy_preferences.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_preferences.h"
-
-namespace blink {
-
-PrivacyPreferences::PrivacyPreferences(bool enable_do_not_track,
- bool enable_referrers)
- : enable_do_not_track(enable_do_not_track),
- enable_referrers(enable_referrers) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/common/scheduler/OWNERS b/chromium/third_party/blink/common/scheduler/OWNERS
new file mode 100644
index 00000000000..6f83df0f877
--- /dev/null
+++ b/chromium/third_party/blink/common/scheduler/OWNERS
@@ -0,0 +1 @@
+file://third_party/blink/renderer/platform/scheduler/OWNERS
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
new file mode 100644
index 00000000000..0bebb931010
--- /dev/null
+++ b/chromium/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
+
+namespace blink {
+namespace scheduler {
+
+const char* FeatureToString(WebSchedulerTrackedFeature feature) {
+ switch (feature) {
+ case WebSchedulerTrackedFeature::kWebSocket:
+ return "WebSocket";
+ case WebSchedulerTrackedFeature::kWebRTC:
+ return "WebRTC";
+ case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoCache:
+ return "main resource has Cache-Control: No-Cache";
+ case WebSchedulerTrackedFeature::kMainResourceHasCacheControlNoStore:
+ return "main resource has Cache-Control: No-Store";
+ case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoCache:
+ return "subresource has Cache-Control: No-Cache";
+ case WebSchedulerTrackedFeature::kSubresourceHasCacheControlNoStore:
+ return "subresource has Cache-Control: No-Store";
+ case WebSchedulerTrackedFeature::kPageShowEventListener:
+ return "onpageshow() event listener";
+ case WebSchedulerTrackedFeature::kPageHideEventListener:
+ return "onpagehide() event listener";
+ case WebSchedulerTrackedFeature::kBeforeUnloadEventListener:
+ return "onbeforeunload() event listener";
+ case WebSchedulerTrackedFeature::kUnloadEventListener:
+ return "onunload() event listener";
+ case WebSchedulerTrackedFeature::kFreezeEventListener:
+ return "onfreeze() event listener";
+ case WebSchedulerTrackedFeature::kResumeEventListener:
+ return "onresume() event listener";
+ case WebSchedulerTrackedFeature::kContainsPlugins:
+ return "page contains plugins";
+ case WebSchedulerTrackedFeature::kDocumentLoaded:
+ return "document loaded";
+ case WebSchedulerTrackedFeature::kDedicatedWorkerOrWorklet:
+ return "Dedicated worker or worklet present";
+ case WebSchedulerTrackedFeature::kSharedWorker:
+ return "Shared worker present";
+ case WebSchedulerTrackedFeature::kOutstandingNetworkRequest:
+ return "outstanding network request";
+ case WebSchedulerTrackedFeature::kServiceWorkerControlledPage:
+ return "ServiceWorker-controlled page";
+ case WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction:
+ return "outstanding IndexedDB transaction";
+ case WebSchedulerTrackedFeature::kHasScriptableFramesInMultipleTabs:
+ return "has scriptable frames in multiple tabs";
+ case WebSchedulerTrackedFeature::kRequestedGeolocationPermission:
+ return "requested geolocation permission";
+ case WebSchedulerTrackedFeature::kRequestedNotificationsPermission:
+ return "requested notifications permission";
+ case WebSchedulerTrackedFeature::kRequestedMIDIPermission:
+ return "requested midi permission";
+ case WebSchedulerTrackedFeature::kRequestedAudioCapturePermission:
+ return "requested audio capture permission";
+ case WebSchedulerTrackedFeature::kRequestedVideoCapturePermission:
+ return "requested video capture permission";
+ case WebSchedulerTrackedFeature::kRequestedSensorsPermission:
+ return "requested sensors permission";
+ case WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission:
+ return "requested background work permission";
+ case WebSchedulerTrackedFeature::kBroadcastChannel:
+ return "requested broadcast channel permission";
+ case WebSchedulerTrackedFeature::kIndexedDBConnection:
+ return "IndexedDB connection present";
+ case WebSchedulerTrackedFeature::kWebGL:
+ return "WebGL";
+ case WebSchedulerTrackedFeature::kWebVR:
+ return "WebVR";
+ case WebSchedulerTrackedFeature::kWebXR:
+ return "WebXR";
+ case WebSchedulerTrackedFeature::kWebLocks:
+ return "WebLocks";
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/common/service_worker/service_worker_utils.cc b/chromium/third_party/blink/common/service_worker/service_worker_utils.cc
index a8c0702eb8f..a8d0803dc22 100644
--- a/chromium/third_party/blink/common/service_worker/service_worker_utils.cc
+++ b/chromium/third_party/blink/common/service_worker/service_worker_utils.cc
@@ -5,37 +5,13 @@
#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
#include "third_party/blink/public/common/features.h"
namespace blink {
-const char kServiceWorkerEagerCodeCacheStrategy[] = "sw_cache_strategy";
-
-namespace {
-
-constexpr base::FeatureParam<EagerCodeCacheStrategy>::Option
- kEagerCodeCacheStrategyOptions[] = {
- {EagerCodeCacheStrategy::kDontGenerate, "dontgenerate"},
- {EagerCodeCacheStrategy::kDuringInstallEvent, "installevent"},
- {EagerCodeCacheStrategy::kOnIdleTask, "idletask"},
-};
-
-constexpr base::FeatureParam<EagerCodeCacheStrategy>
- kEagerCodeCacheStrategyParam{&features::kServiceWorkerAggressiveCodeCache,
- "sw_cache_strategy",
- EagerCodeCacheStrategy::kDuringInstallEvent,
- &kEagerCodeCacheStrategyOptions};
-
-} // namespace
-
bool ServiceWorkerUtils::IsImportedScriptUpdateCheckEnabled() {
return base::FeatureList::IsEnabled(
blink::features::kServiceWorkerImportedScriptUpdateCheck);
}
-EagerCodeCacheStrategy ServiceWorkerUtils::GetEagerCodeCacheStrategy() {
- return kEagerCodeCacheStrategyParam.Get();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/manual_tests/compositing/resources/composited-subframe.html b/chromium/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
index 92b3b7f4f5b..1e15908f44e 100644
--- a/chromium/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
+++ b/chromium/third_party/blink/manual_tests/compositing/resources/composited-subframe.html
@@ -4,15 +4,15 @@
<head>
<style type="text/css" media="screen">
body { background-color:silver }
-
+
.box {
height: 200px;
width: 200px;
margin: 10px;
padding: 5px;
background-color: blue;
- transform: translateZ(0);
- overflow:hidden;
+ will-change: transform;
+ overflow: hidden;
}
.box:hover {
transform: none;
diff --git a/chromium/third_party/blink/public/BUILD.gn b/chromium/third_party/blink/public/BUILD.gn
index 790ec1254c5..8ced46efafd 100644
--- a/chromium/third_party/blink/public/BUILD.gn
+++ b/chromium/third_party/blink/public/BUILD.gn
@@ -34,6 +34,7 @@ group("test_support") {
":test_headers",
"//third_party/blink/renderer/modules/exported:test_support",
"//third_party/blink/renderer/modules/mediastream:test_support",
+ "//third_party/blink/renderer/modules/peerconnection:test_support",
"//third_party/blink/renderer/platform:test_support",
]
}
@@ -73,7 +74,6 @@ buildflag_header("buildflags") {
if (is_android) {
java_cpp_enum("blink_headers_java_enums_srcjar") {
sources = [
- "./common/manifest/web_display_mode.h",
"./platform/web_focus_type.h",
"./platform/web_input_event.h",
"./platform/web_text_input_mode.h",
@@ -104,12 +104,25 @@ source_set("test_headers") {
"web/modules/mediastream/mock_media_stream_registry.h",
"web/modules/mediastream/mock_media_stream_video_sink.h",
"web/modules/mediastream/mock_media_stream_video_source.h",
+
+ # TODO(crbug.com/787254): Remove the group of mock_.h files
+ # below when content/renderer/media/webrtc Onion souping is
+ # done.
+ "web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h",
+ "web/modules/peerconnection/mock_data_channel_impl.h",
+ "web/modules/peerconnection/mock_peer_connection_dependency_factory.h",
+ "web/modules/peerconnection/mock_peer_connection_impl.h",
+ "web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h",
+ "web/modules/peerconnection/webrtc_stats_report_obtainer.h",
]
deps = [
":blink_headers",
"//base:base",
"//cc:cc",
"//testing/gmock:gmock",
+ "//third_party/webrtc/api:libjingle_peerconnection_api",
+ "//third_party/webrtc/api:media_stream_interface",
+ "//third_party/webrtc/api:rtc_stats_api",
]
}
@@ -134,13 +147,6 @@ source_set("blink_headers") {
"platform/mac/web_scrollbar_theme.h",
"platform/media/webmediaplayer_delegate.h",
"platform/modules/indexeddb/web_idb_database_exception.h",
- "platform/modules/media_capabilities/web_audio_configuration.h",
- "platform/modules/media_capabilities/web_media_capabilities_decoding_info.h",
- "platform/modules/media_capabilities/web_media_capabilities_info.h",
- "platform/modules/media_capabilities/web_media_capabilities_key_system_configuration.h",
- "platform/modules/media_capabilities/web_media_configuration.h",
- "platform/modules/media_capabilities/web_media_decoding_configuration.h",
- "platform/modules/media_capabilities/web_video_configuration.h",
"platform/modules/mediastream/media_stream_audio_deliverer.h",
"platform/modules/mediastream/media_stream_audio_level_calculator.h",
"platform/modules/mediastream/media_stream_audio_processor_options.h",
@@ -159,8 +165,6 @@ source_set("blink_headers") {
"platform/modules/peerconnection/audio_codec_factory.h",
"platform/modules/peerconnection/rtc_event_log_output_sink.h",
"platform/modules/peerconnection/rtc_event_log_output_sink_proxy_util.h",
- "platform/modules/peerconnection/rtc_video_decoder_factory_util.h",
- "platform/modules/peerconnection/rtc_video_encoder_factory_util.h",
"platform/modules/peerconnection/two_keys_adapter_map.h",
"platform/modules/peerconnection/webrtc_audio_sink.h",
"platform/modules/peerconnection/webrtc_util.h",
@@ -235,6 +239,7 @@ source_set("blink_headers") {
"platform/web_encrypted_media_key_information.h",
"platform/web_encrypted_media_request.h",
"platform/web_encrypted_media_types.h",
+ "platform/web_fetch_client_settings_object.h",
"platform/web_file_system_type.h",
"platform/web_float_point.h",
"platform/web_float_point_3d.h",
@@ -265,9 +270,7 @@ source_set("blink_headers") {
"platform/web_isolated_world_ids.h",
"platform/web_isolated_world_info.h",
"platform/web_keyboard_event.h",
- "platform/web_loading_behavior_flag.h",
"platform/web_loading_hints_provider.h",
- "platform/web_localized_string.h",
"platform/web_media_constraints.h",
"platform/web_media_key_system_configuration.h",
"platform/web_media_key_system_media_capability.h",
@@ -301,7 +304,6 @@ source_set("blink_headers") {
"platform/web_resource_timing_info.h",
"platform/web_rtc_answer_options.h",
"platform/web_rtc_api_name.h",
- "platform/web_rtc_certificate_generator.h",
"platform/web_rtc_data_channel_init.h",
"platform/web_rtc_dtmf_sender_handler.h",
"platform/web_rtc_dtmf_sender_handler_client.h",
@@ -330,7 +332,6 @@ source_set("blink_headers") {
"platform/web_scrollbar_buttons_placement.h",
"platform/web_scrollbar_overlay_color_theme.h",
"platform/web_security_origin.h",
- "platform/web_security_style.h",
"platform/web_set_sink_id_callbacks.h",
"platform/web_size.h",
"platform/web_source_buffer.h",
@@ -349,7 +350,6 @@ source_set("blink_headers") {
"platform/web_touch_action.h",
"platform/web_touch_event.h",
"platform/web_touch_point.h",
- "platform/web_transmission_encoding_info_handler.h",
"platform/web_url.h",
"platform/web_url_error.h",
"platform/web_url_load_timing.h",
@@ -384,6 +384,14 @@ source_set("blink_headers") {
"web/modules/mediastream/web_media_stream_utils.h",
"web/modules/mediastream/webmediaplayer_ms.h",
"web/modules/peerconnection/media_stream_remote_video_source.h",
+ "web/modules/peerconnection/media_stream_video_webrtc_sink.h",
+ "web/modules/peerconnection/peer_connection_dependency_factory.h",
+ "web/modules/peerconnection/rtc_rtp_receiver_impl.h",
+ "web/modules/peerconnection/rtc_rtp_sender_impl.h",
+ "web/modules/peerconnection/rtc_rtp_transceiver_impl.h",
+ "web/modules/peerconnection/transceiver_state_surfacer.h",
+ "web/modules/peerconnection/webrtc_media_stream_track_adapter.h",
+ "web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h",
"web/modules/service_worker/web_service_worker_context_client.h",
"web/modules/service_worker/web_service_worker_context_proxy.h",
"web/modules/webrtc/webrtc_audio_device_impl.h",
@@ -467,14 +475,12 @@ source_set("blink_headers") {
"web/web_pepper_socket_client.h",
"web/web_performance.h",
"web/web_plugin.h",
- "web/web_plugin_action.h",
"web/web_plugin_container.h",
"web/web_plugin_document.h",
"web/web_plugin_params.h",
"web/web_plugin_script_forbidden_scope.h",
"web/web_popup_menu_info.h",
"web/web_prerenderer_client.h",
- "web/web_presentation_receiver_flags.h",
"web/web_print_params.h",
"web/web_print_preset_options.h",
"web/web_print_scaling_option.h",
@@ -503,7 +509,6 @@ source_set("blink_headers") {
"web/web_text_decoration_type.h",
"web/web_text_direction.h",
"web/web_tree_scope_type.h",
- "web/web_triggering_event_info.h",
"web/web_user_gesture_indicator.h",
"web/web_user_gesture_token.h",
"web/web_user_media_request.h",
@@ -549,6 +554,8 @@ source_set("blink_headers") {
"//services/network/public/mojom",
"//third_party/blink/renderer/platform/wtf:wtf",
"//third_party/webrtc/api:libjingle_peerconnection_api",
+ "//third_party/webrtc/api:media_stream_interface",
+ "//third_party/webrtc/api:rtc_error",
"//third_party/webrtc/api:rtc_stats_api",
"//third_party/webrtc/api:rtp_parameters",
"//third_party/webrtc/api:scoped_refptr",
@@ -560,30 +567,40 @@ source_set("blink_headers") {
"//third_party/webrtc/modules/audio_device:audio_device_api",
"//third_party/webrtc/modules/audio_processing:api",
"//third_party/webrtc/modules/video_coding:video_codec_interface",
+ "//third_party/webrtc/p2p:libstunprober",
"//third_party/webrtc/pc:peerconnection",
"//third_party/webrtc/rtc_base:rtc_base",
"//third_party/webrtc/rtc_base:rtc_task_queue",
+
+ # TODO(titovartem) remove dependency on WebRTC internals.
+ "//third_party/webrtc/rtc_base/third_party/sigslot:sigslot",
"//third_party/webrtc_overrides:init_webrtc",
"//ui/base:base",
"//v8:v8_headers",
]
}
+if (external_devtools_frontend) {
+ devtools_frontend_path = "//third_party/devtools-frontend"
+} else {
+ devtools_frontend_path = "//third_party/blink/renderer/devtools"
+}
+
group("blink_devtools_frontend_resources") {
public_deps = [
- "//third_party/blink/renderer/devtools:devtools_frontend_resources",
+ "$devtools_frontend_path:devtools_frontend_resources",
]
}
group("blink_devtools_frontend_resources_files") {
data_deps = [
- "//third_party/blink/renderer/devtools:devtools_all_files",
+ "$devtools_frontend_path:devtools_all_files",
]
}
group("blink_generate_devtools_grd") {
public_deps = [
- "//third_party/blink/renderer/devtools:generate_devtools_grd",
+ "$devtools_frontend_path:generate_devtools_grd",
]
}
@@ -596,9 +613,6 @@ grit("resources") {
"grit/blink_resources.h",
"blink_resources.pak",
]
- if (is_android) {
- defines = [ "notouch_build=$notouch_build" ]
- }
html_min_css = "$blink_core_output_dir/html.css"
grit_flags = [
"-E",
@@ -624,10 +638,6 @@ group("scaled_resources") {
":image_resources",
"//third_party/blink/renderer/modules/media_controls:media_controls_resources",
]
-
- if (is_android && notouch_build) {
- public_deps += [ "//third_party/blink/renderer/modules/media_controls:media_controls_touchless_resources" ]
- }
}
repack("scaled_resources_100_percent") {
@@ -636,9 +646,6 @@ repack("scaled_resources_100_percent") {
"$root_gen_dir/third_party/blink/public/resources/blink_image_resources_100_percent.pak",
"$root_gen_dir/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources_100_percent.pak",
]
- if (is_android && notouch_build) {
- sources += [ "$root_gen_dir/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.pak" ]
- }
deps = [
":scaled_resources",
]
@@ -650,9 +657,6 @@ repack("scaled_resources_200_percent") {
"$root_gen_dir/third_party/blink/public/resources/blink_image_resources_200_percent.pak",
"$root_gen_dir/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources_200_percent.pak",
]
- if (is_android && notouch_build) {
- sources += [ "$root_gen_dir/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.pak" ]
- }
deps = [
":scaled_resources",
]
diff --git a/chromium/third_party/blink/public/OWNERS b/chromium/third_party/blink/public/OWNERS
index 29f47187472..f87e5af5343 100644
--- a/chromium/third_party/blink/public/OWNERS
+++ b/chromium/third_party/blink/public/OWNERS
@@ -1,6 +1,7 @@
chrishtr@chromium.org
dcheng@chromium.org
dgozman@chromium.org
+falken@chromium.org
foolip@chromium.org
haraken@chromium.org
japhet@chromium.org
diff --git a/chromium/third_party/blink/public/blink_resources.grd b/chromium/third_party/blink/public/blink_resources.grd
index a1426e71d11..aeabb20d217 100644
--- a/chromium/third_party/blink/public/blink_resources.grd
+++ b/chromium/third_party/blink/public/blink_resources.grd
@@ -18,9 +18,6 @@
<if expr="is_macosx">
<include name="IDR_UASTYLE_THEME_MAC_CSS" file="../renderer/core/html/resources/mac.css" type="BINDATA" compress="gzip"/>
</if>
- <if expr="notouch_build">
- <include name="IDR_UASTYLE_THEME_TOUCHLESS_CSS" file="../renderer/core/css/touchless.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"/>
@@ -50,6 +47,9 @@
<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_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"/>
diff --git a/chromium/third_party/blink/public/common/BUILD.gn b/chromium/third_party/blink/public/common/BUILD.gn
index d8b2d96b9dd..be6da1f9196 100644
--- a/chromium/third_party/blink/public/common/BUILD.gn
+++ b/chromium/third_party/blink/public/common/BUILD.gn
@@ -50,10 +50,12 @@ source_set("headers") {
"client_hints/client_hints.h",
"common_export.h",
"css/forced_colors.h",
+ "css/navigation_controls.h",
"css/preferred_color_scheme.h",
"device_memory/approximated_device_memory.h",
"dom_storage/session_storage_namespace_id.h",
"experiments/memory_ablation_experiment.h",
+ "feature_policy/document_policy.h",
"feature_policy/feature_policy.h",
"feature_policy/policy_value.h",
"features.h",
@@ -69,12 +71,16 @@ source_set("headers") {
"frame/user_activation_state.h",
"frame/user_activation_update_source.h",
"frame/user_activation_update_type.h",
+ "http/structured_header.h",
"indexeddb/indexed_db_default_mojom_traits.h",
"indexeddb/indexeddb_key.h",
"indexeddb/indexeddb_key_path.h",
"indexeddb/indexeddb_key_range.h",
"indexeddb/indexeddb_metadata.h",
"indexeddb/web_idb_types.h",
+ "loader/loading_behavior_flag.h",
+ "loader/mime_sniffing_throttle.h",
+ "loader/mime_sniffing_url_loader.h",
"loader/request_destination.h",
"loader/url_loader_factory_bundle.h",
"loader/url_loader_factory_bundle_mojom_traits.h",
@@ -83,7 +89,6 @@ source_set("headers") {
"manifest/manifest.h",
"manifest/manifest_icon_selector.h",
"manifest/manifest_util.h",
- "manifest/web_display_mode.h",
"media/video_capture.h",
"mediastream/media_devices.h",
"mediastream/media_devices_mojom_traits.h",
@@ -99,6 +104,7 @@ source_set("headers") {
"messaging/transferable_message.h",
"messaging/transferable_message_mojom_traits.h",
"mime_util/mime_util.h",
+ "navigation/triggering_event_info.h",
"notifications/notification_constants.h",
"notifications/notification_mojom_traits.h",
"notifications/notification_resources.h",
@@ -109,18 +115,23 @@ source_set("headers") {
"origin_trials/trial_token.h",
"origin_trials/trial_token_validator.h",
"page/launching_process_state.h",
+ "page/page_zoom.h",
+ "peerconnection/webrtc_ip_handling_policy.h",
+ "plugin/plugin_action.h",
"prerender/prerender_rel_type.h",
- "privacy_preferences.h",
+ "presentation/presentation_receiver_flags.h",
"scheduler/web_scheduler_tracked_feature.h",
"screen_orientation/web_screen_orientation_lock_type.h",
"screen_orientation/web_screen_orientation_type.h",
+ "security/security_style.h",
"service_worker/service_worker_status_code.h",
"service_worker/service_worker_type_converters.h",
"service_worker/service_worker_types.h",
"service_worker/service_worker_utils.h",
"sms/sms_receiver_outcome.h",
+ "sudden_termination_disabler_type.h",
"user_agent/user_agent_metadata.h",
- "web_package/http_structured_header.h",
+ "web_cache/web_cache_resource_type_stats.h",
"web_package/signed_exchange_consts.h",
"web_package/signed_exchange_request_matcher.h",
]
diff --git a/chromium/third_party/blink/public/common/DEPS b/chromium/third_party/blink/public/common/DEPS
index 56d0145d42d..43c0fd6770f 100644
--- a/chromium/third_party/blink/public/common/DEPS
+++ b/chromium/third_party/blink/public/common/DEPS
@@ -12,9 +12,13 @@ include_rules = [
"+media",
"+mojo",
"+services/network/public/cpp/resource_request_body.h",
+ "+services/network/public/cpp/resource_response.h",
"+services/network/public/cpp/shared_url_loader_factory.h",
"+services/network/public/mojom/url_loader.mojom.h",
+ "+services/network/public/mojom/url_loader.mojom-forward.h",
"+services/network/public/mojom/url_loader_factory.mojom.h",
+ "+services/network/public/mojom/url_response_head.mojom.h",
+ "+services/network/public/mojom/url_response_head.mojom-forward.h",
"+skia/public/mojom",
"+third_party/blink/public/common",
"+third_party/blink/public/mojom",
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 a82a430fc42..40049848c2b 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
@@ -11,10 +11,9 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "mojo/public/cpp/bindings/associated_interface_request.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 "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom.h"
@@ -24,13 +23,12 @@ namespace blink {
// A helper interface for connecting to remote Channel-associated interfaces.
//
// This is analogous to service_manager::InterfaceProvider in that it provides a
-// means of
-// binding proxies to remote interfaces, but this is specifically for interfaces
-// which must be associated with an IPC::Channel, i.e. retain FIFO message
-// ordering with respect to legacy IPC messages.
+// means of binding proxies to remote interfaces, but this is specifically for
+// interfaces which must be associated with an IPC::Channel, i.e. retain FIFO
+// message ordering with respect to legacy IPC messages.
//
-// The Channel with which the remote interfaces are associated depends on
-// the configuration of the specific AssociatedInterfaceProvider instance. For
+// The Channel with which the remote interfaces are associated depends on the
+// configuration of the specific AssociatedInterfaceProvider instance. For
// example, RenderFrameHost exposes an instance of this class for which all
// interfaces are associated with the IPC::ChannelProxy to the render process
// which hosts its corresponding RenderFrame.
@@ -41,7 +39,7 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceProvider {
// |task_runner| must belong to the same thread. It will be used to dispatch
// all callbacks and connection error notification.
explicit AssociatedInterfaceProvider(
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy,
+ mojo::PendingAssociatedRemote<mojom::AssociatedInterfaceProvider> proxy,
scoped_refptr<base::SingleThreadTaskRunner> task_runner = nullptr);
// Constructs a local provider with no remote interfaces. This is useful in
@@ -60,21 +58,6 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceProvider {
void GetInterface(const std::string& name,
mojo::ScopedInterfaceEndpointHandle handle);
- // Remove this after done with migration from AssociatedInterfaceRequest to
- // PendingAssociatedReceiver.
- // Templated helpers for GetInterface().
- template <typename Interface>
- void GetInterface(mojo::AssociatedInterfaceRequest<Interface> request) {
- GetInterface(Interface::Name_, request.PassHandle());
- }
-
- // Remove this after done with migration from AssociatedInterfacePtr to
- // AssociatedRemote.
- template <typename Interface>
- void GetInterface(mojo::AssociatedInterfacePtr<Interface>* proxy) {
- GetInterface(mojo::MakeRequest(proxy, task_runner_));
- }
-
template <typename Interface>
void GetInterface(mojo::PendingAssociatedReceiver<Interface> receiver) {
GetInterface(Interface::Name_, receiver.PassHandle());
@@ -90,10 +73,14 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceProvider {
const base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>&
binder);
+ // Returns an instance of AssociatedInterfaceProvider that is safe to use but
+ // is not connected to anything.
+ static AssociatedInterfaceProvider* GetEmptyAssociatedInterfaceProvider();
+
private:
class LocalProvider;
- mojom::AssociatedInterfaceProviderAssociatedPtr proxy_;
+ mojo::AssociatedRemote<mojom::AssociatedInterfaceProvider> proxy_;
std::unique_ptr<LocalProvider> local_provider_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
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 02317fec11e..de98489f69e 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
@@ -52,21 +52,6 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceRegistry {
bool TryBindInterface(const std::string& name,
mojo::ScopedInterfaceEndpointHandle* handle);
- // Remove this after done with migration from AssociatedInterfaceRequest to
- // PendingAssociatedReceiver.
- template <typename Interface>
- using InterfaceBinder = base::RepeatingCallback<void(
- mojo::AssociatedInterfaceRequest<Interface>)>;
-
- // Remove this after done with migration from AssociatedInterfaceRequest to
- // PendingAssociatedReceiver.
- // Templated helper for AddInterface() above.
- template <typename Interface>
- void AddInterface(const InterfaceBinder<Interface>& binder) {
- AddInterface(Interface::Name_,
- base::BindRepeating(&BindInterface<Interface>, binder));
- }
-
template <typename Interface>
using ReceiverBinder =
base::RepeatingCallback<void(mojo::PendingAssociatedReceiver<Interface>)>;
@@ -81,14 +66,6 @@ class BLINK_COMMON_EXPORT AssociatedInterfaceRegistry {
base::WeakPtr<AssociatedInterfaceRegistry> GetWeakPtr();
private:
- // Remove this after done with migration from AssociatedInterfaceRequest to
- // PendingAssociatedReceiver.
- template <typename Interface>
- static void BindInterface(const InterfaceBinder<Interface>& binder,
- mojo::ScopedInterfaceEndpointHandle handle) {
- binder.Run(mojo::AssociatedInterfaceRequest<Interface>(std::move(handle)));
- }
-
template <typename Interface>
static void BindInterfaceReceiver(
const ReceiverBinder<Interface>& binder,
diff --git a/chromium/third_party/blink/public/common/bluetooth/web_bluetooth_device_id_mojom_traits.h b/chromium/third_party/blink/public/common/bluetooth/web_bluetooth_device_id_mojom_traits.h
index 745265ac7be..9ca0c6cf1bc 100644
--- a/chromium/third_party/blink/public/common/bluetooth/web_bluetooth_device_id_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/bluetooth/web_bluetooth_device_id_mojom_traits.h
@@ -8,7 +8,7 @@
#include <string>
#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h"
namespace mojo {
diff --git a/chromium/third_party/blink/public/common/css/navigation_controls.h b/chromium/third_party/blink/public/common/css/navigation_controls.h
new file mode 100644
index 00000000000..a1c789ebac3
--- /dev/null
+++ b/chromium/third_party/blink/public/common/css/navigation_controls.h
@@ -0,0 +1,18 @@
+// 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_CSS_NAVIGATION_CONTROLS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_NAVIGATION_CONTROLS_H_
+
+namespace blink {
+
+// Use for passing navigation controls from the OS to the renderer.
+enum class NavigationControls {
+ kNone,
+ kBackButton,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_NAVIGATION_CONTROLS_H_
diff --git a/chromium/third_party/blink/public/common/feature_policy/document_policy.h b/chromium/third_party/blink/public/common/feature_policy/document_policy.h
new file mode 100644
index 00000000000..106a102a5fa
--- /dev/null
+++ b/chromium/third_party/blink/public/common/feature_policy/document_policy.h
@@ -0,0 +1,136 @@
+// 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_FEATURE_POLICY_DOCUMENT_POLICY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_DOCUMENT_POLICY_H_
+
+#include <limits>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/feature_policy/policy_value.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
+
+namespace blink {
+
+// Document Policy is a mechanism for controlling the behaviour of web platform
+// features in a document, and for requesting such changes in embedded frames.
+// (The specific changes which are made depend on the feature; see the
+// specification for details).
+//
+// Policies can be defined in the HTTP header stream, with the |Document-Policy|
+// HTTP header, or can be set by the |policy| attributes on the iframe element
+// which embeds the document.
+//
+// See
+// https://github.com/w3c/webappsec-feature-policy/blob/master/document-policy-explainer.md
+//
+// Key concepts:
+//
+// Features
+// --------
+// Features which can be controlled by policy are defined by instances of enum
+// mojom::FeaturePolicyFeature, declared in |feature_policy_feature.mojom|.
+// TODO(iclelland): Make a clear distinction between feature policy features
+// and document policy features.
+//
+// Declarations
+// ------------
+// A document policy declaration is a mapping of a feature name to a policy
+// value. A set of such declarations is a declared policy. The declared policy
+// is attached to a document.
+//
+// Required Policy
+// ----------------
+// In addition to the declared policy (which may be empty), every frame has
+// an required policy, which is set by the embedding document (or inherited
+// from its parent). Any document loaded into a frame with a required policy
+// must have a declared policy which is compatible with it. Frames may add new
+// requirements to their own subframes, but cannot relax any existing ones.
+//
+// Advertised Policy
+// -----------------
+// If a frame has a non-empty required policy, the requirements will be
+// advertised on the outgoing HTTP request for any document to be loaded in that
+// frame, in the Sec-Required-Document-Policy HTTP header.
+//
+// Defaults
+// --------
+// Each defined feature has a default policy, which determines the threshold
+// value to use when no policy has been declared.
+
+struct BLINK_COMMON_EXPORT ParsedDocumentPolicyDeclaration {
+ mojom::FeaturePolicyFeature feature;
+ PolicyValue value;
+};
+
+using ParsedDocumentPolicy = std::vector<ParsedDocumentPolicyDeclaration>;
+
+class BLINK_COMMON_EXPORT DocumentPolicy {
+ public:
+ using FeatureState = std::map<mojom::FeaturePolicyFeature, PolicyValue>;
+
+ ~DocumentPolicy();
+
+ static std::unique_ptr<DocumentPolicy> CreateWithRequiredPolicy(
+ const FeatureState& required_policy);
+
+ // Returns true if the feature is unrestricted (has its default value for the
+ // platform)
+ bool IsFeatureEnabled(mojom::FeaturePolicyFeature feature) const;
+
+ // Returns true if the feature is unrestricted, or is not restricted as much
+ // as the given threshold value.
+ bool IsFeatureEnabled(mojom::FeaturePolicyFeature feature,
+ const PolicyValue& threshold_value) const;
+
+ // Returns the value of the given feature on the given origin.
+ PolicyValue GetFeatureValue(mojom::FeaturePolicyFeature feature) const;
+
+ // Sets the declared policy from the parsed Document-Policy HTTP header.
+ // Unrecognized features will be ignored.
+ void SetHeaderPolicy(const ParsedDocumentPolicy& parsed_header);
+
+ // Returns the current threshold values assigned to all document policies.
+ // the declared header policy as well as any unadvertised required policies
+ // (such as sandbox policies).
+ FeatureState GetFeatureState() const;
+
+ // Returns the required policy to advertise for an outgoing HTTP request.
+ ParsedDocumentPolicy RequiredPolicy() const;
+
+ // Returns true if this document policy is compatible with the given required
+ // policy.
+ bool IsPolicyCompatible(const ParsedDocumentPolicy& required_policy);
+
+ // Returns the list of features which can be controlled by Document Policy,
+ // and their default values.
+ static const FeatureState& GetFeatureDefaults();
+
+ private:
+ friend class DocumentPolicyTest;
+
+ DocumentPolicy(const FeatureState& feature_list);
+ static std::unique_ptr<DocumentPolicy> CreateWithRequiredPolicy(
+ const FeatureState& required_policy,
+ const FeatureState& defaults);
+
+ void UpdateFeatureState(const FeatureState& feature_state);
+
+ // Threshold values for each defined feature.
+ // TODO(iclelland): Generate these members; pack booleans in bitfields if
+ // possible.
+ bool font_display_ = true;
+ double unoptimized_lossless_images_ = std::numeric_limits<double>::infinity();
+
+ DISALLOW_COPY_AND_ASSIGN(DocumentPolicy);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_FEATURE_POLICY_DOCUMENT_POLICY_H_
diff --git a/chromium/third_party/blink/public/common/feature_policy/feature_policy.h b/chromium/third_party/blink/public/common/feature_policy/feature_policy.h
index 467dbe61548..17741c4268e 100644
--- a/chromium/third_party/blink/public/common/feature_policy/feature_policy.h
+++ b/chromium/third_party/blink/public/common/feature_policy/feature_policy.h
@@ -15,7 +15,8 @@
#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/feature_policy/policy_value.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-forward.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-forward.h"
#include "url/origin.h"
namespace blink {
diff --git a/chromium/third_party/blink/public/common/feature_policy/policy_value.h b/chromium/third_party/blink/public/common/feature_policy/policy_value.h
index 95f8e79be3a..81bc1799ac2 100644
--- a/chromium/third_party/blink/public/common/feature_policy/policy_value.h
+++ b/chromium/third_party/blink/public/common/feature_policy/policy_value.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom-forward.h"
namespace blink {
@@ -25,9 +25,8 @@ class BLINK_COMMON_EXPORT PolicyValue {
explicit PolicyValue(mojom::PolicyValueType);
explicit PolicyValue(bool bool_value);
- explicit PolicyValue(
- double double_value,
- mojom::PolicyValueType type = mojom::PolicyValueType::kDecDouble);
+ explicit PolicyValue(double double_value);
+ PolicyValue(double double_value, mojom::PolicyValueType type);
// A 'max' PolicyValue is the most permissive value for the policy.
static PolicyValue CreateMaxPolicyValue(mojom::PolicyValueType type);
@@ -45,9 +44,8 @@ class BLINK_COMMON_EXPORT PolicyValue {
// PolicyValue setters.
// Note the getters also DCHECKs that the type is correct.
void SetBoolValue(bool bool_value);
- void SetDoubleValue(
- double double_value,
- mojom::PolicyValueType type = mojom::PolicyValueType::kDecDouble);
+ void SetDoubleValue(double double_value);
+ void SetDoubleValue(double double_value, mojom::PolicyValueType type);
// Operater overrides
PolicyValue& operator=(const PolicyValue& rhs);
@@ -61,8 +59,8 @@ class BLINK_COMMON_EXPORT PolicyValue {
private:
mojom::PolicyValueType type_;
- bool bool_value_;
- double double_value_;
+ bool bool_value_ = false;
+ double double_value_ = 0.0;
};
bool BLINK_COMMON_EXPORT operator==(const PolicyValue& lhs,
diff --git a/chromium/third_party/blink/public/common/features.h b/chromium/third_party/blink/public/common/features.h
index ba239af2d70..59a7415cca2 100644
--- a/chromium/third_party/blink/public/common/features.h
+++ b/chromium/third_party/blink/public/common/features.h
@@ -17,18 +17,16 @@ namespace features {
BLINK_COMMON_EXPORT extern const base::Feature
kBlockingDownloadsInAdFrameWithoutUserActivation;
-BLINK_COMMON_EXPORT extern const base::Feature kAvoidFlashBetweenNavigation;
+BLINK_COMMON_EXPORT extern const base::Feature kPaintHolding;
BLINK_COMMON_EXPORT extern const base::Feature
kEagerCacheStorageSetupForServiceWorkers;
-BLINK_COMMON_EXPORT extern const base::Feature
- kEnableGpuRasterizationViewportRestriction;
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 kFirstContentfulPaintPlusPlus;
BLINK_COMMON_EXPORT extern const base::Feature kFreezePurgeMemoryAllPagesFrozen;
BLINK_COMMON_EXPORT extern const base::Feature kFreezeUserAgent;
BLINK_COMMON_EXPORT extern const base::Feature kImplicitRootScroller;
+BLINK_COMMON_EXPORT extern const base::Feature kCSSOMViewScrollCoordinates;
BLINK_COMMON_EXPORT extern const base::Feature kCSSBackdropFilter;
BLINK_COMMON_EXPORT extern const base::Feature kDisplayLocking;
BLINK_COMMON_EXPORT extern const base::Feature kFastBorderRadius;
@@ -49,6 +47,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed;
BLINK_COMMON_EXPORT extern const base::Feature kWebRtcHWH264Encoding;
BLINK_COMMON_EXPORT extern const base::Feature kWebRtcHWVP8Encoding;
BLINK_COMMON_EXPORT extern const base::Feature kWebRtcHWVP9Encoding;
+BLINK_COMMON_EXPORT extern const base::Feature kWebRtcMultiplexCodec;
+BLINK_COMMON_EXPORT extern const base::Feature kWebRtcHideLocalIpsWithMdns;
#if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
BLINK_COMMON_EXPORT extern const base::Feature kWebRtcH264WithOpenH264FFmpeg;
@@ -56,11 +56,7 @@ BLINK_COMMON_EXPORT extern const base::Feature kWebRtcH264WithOpenH264FFmpeg;
BLINK_COMMON_EXPORT extern const base::Feature kResourceLoadViaDataPipe;
BLINK_COMMON_EXPORT extern const base::Feature
- kServiceWorkerIsolateInForeground;
-BLINK_COMMON_EXPORT extern const base::Feature
kServiceWorkerImportedScriptUpdateCheck;
-BLINK_COMMON_EXPORT extern const base::Feature
- kServiceWorkerAggressiveCodeCache;
BLINK_COMMON_EXPORT extern const base::Feature kServiceWorkerUpdateDelay;
BLINK_COMMON_EXPORT extern const base::Feature kStopInBackground;
BLINK_COMMON_EXPORT extern const base::Feature
@@ -83,13 +79,9 @@ BLINK_COMMON_EXPORT extern const base::Feature kDecodeJpeg420ImagesToYUV;
BLINK_COMMON_EXPORT extern const base::Feature kDecodeLossyWebPImagesToYUV;
BLINK_COMMON_EXPORT extern const base::Feature
- kSendPreviewsLoadingHintsBeforeCommit;
-
-BLINK_COMMON_EXPORT extern const base::Feature
kWebFontsCacheAwareTimeoutAdaption;
BLINK_COMMON_EXPORT extern const base::Feature
kBlockingFocusWithoutUserActivation;
-BLINK_COMMON_EXPORT extern const base::Feature kScrollbarInjectScrollGestures;
BLINK_COMMON_EXPORT extern const base::Feature kAudioWorkletRealtimeThread;
@@ -110,8 +102,6 @@ BLINK_COMMON_EXPORT bool IsPlzDedicatedWorkerEnabled();
BLINK_COMMON_EXPORT extern const base::Feature kCanvasAlwaysDeferral;
-BLINK_COMMON_EXPORT extern const base::Feature kStreamsNative;
-
// Blink garbage collection.
BLINK_COMMON_EXPORT extern const base::Feature kBlinkHeapCompaction;
BLINK_COMMON_EXPORT extern const base::Feature kBlinkHeapConcurrentMarking;
@@ -119,7 +109,6 @@ BLINK_COMMON_EXPORT extern const base::Feature kBlinkHeapConcurrentSweeping;
BLINK_COMMON_EXPORT extern const base::Feature kBlinkHeapIncrementalMarking;
BLINK_COMMON_EXPORT extern const base::Feature
kBlinkHeapIncrementalMarkingStress;
-BLINK_COMMON_EXPORT extern const base::Feature kBlinkHeapUnifiedGCScheduling;
BLINK_COMMON_EXPORT extern const base::Feature kBufferingBytesConsumerDelay;
BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
@@ -137,6 +126,12 @@ BLINK_COMMON_EXPORT extern const base::Feature
BLINK_COMMON_EXPORT extern const base::Feature
kLowerJavaScriptPriorityWhenForceDeferred;
+BLINK_COMMON_EXPORT extern const base::Feature kARIAAnnotationRoles;
+
+BLINK_COMMON_EXPORT extern const base::Feature kDisableDirectlyCompositedImages;
+
+BLINK_COMMON_EXPORT extern const base::Feature kSetLowPriorityForBeacon;
+
} // 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 2a55afeae4e..1ddfc2108f9 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
@@ -8,9 +8,10 @@
#include <utility>
#include "base/memory/scoped_refptr.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "services/network/public/mojom/url_loader.mojom-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-forward.h"
namespace mojo {
@@ -67,16 +68,16 @@ struct StructTraits<blink::mojom::FetchAPIDataElementDataView,
static const std::string& blob_uuid(const network::DataElement& element) {
return element.blob_uuid_;
}
- static network::mojom::DataPipeGetterPtrInfo data_pipe_getter(
+ static mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
const network::DataElement& element) {
if (element.type_ != network::mojom::DataElementType::kDataPipe)
- return nullptr;
- return element.CloneDataPipeGetter().PassInterface();
+ return mojo::NullRemote();
+ return element.CloneDataPipeGetter();
}
- static network::mojom::ChunkedDataPipeGetterPtrInfo chunked_data_pipe_getter(
- const network::DataElement& element) {
+ static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
+ chunked_data_pipe_getter(const network::DataElement& element) {
if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe)
- return nullptr;
+ return mojo::NullRemote();
return const_cast<network::DataElement&>(element)
.ReleaseChunkedDataPipeGetter();
}
diff --git a/chromium/third_party/blink/public/common/fetch/fetch_api_request_headers_mojom_traits.h b/chromium/third_party/blink/public/common/fetch/fetch_api_request_headers_mojom_traits.h
index 9454bd0ab00..3efb9d6d22b 100644
--- a/chromium/third_party/blink/public/common/fetch/fetch_api_request_headers_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/fetch/fetch_api_request_headers_mojom_traits.h
@@ -10,7 +10,7 @@
#include "base/containers/flat_map.h"
#include "base/strings/string_util.h"
#include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-forward.h"
namespace mojo {
diff --git a/chromium/third_party/blink/public/common/frame/sandbox_flags.h b/chromium/third_party/blink/public/common/frame/sandbox_flags.h
index 19925ce6f40..60f88b8dd6a 100644
--- a/chromium/third_party/blink/public/common/frame/sandbox_flags.h
+++ b/chromium/third_party/blink/public/common/frame/sandbox_flags.h
@@ -36,6 +36,7 @@ enum class WebSandboxFlags : int {
kTopNavigationByUserActivation = 1 << 14,
// See https://crbug.com/539938
kDownloads = 1 << 15,
+ kStorageAccessByUserActivation = 1 << 16,
kAll = -1 // Mask with all bits set to 1.
};
diff --git a/chromium/third_party/blink/public/common/http/structured_header.h b/chromium/third_party/blink/public/common/http/structured_header.h
new file mode 100644
index 00000000000..7e8fb9d2326
--- /dev/null
+++ b/chromium/third_party/blink/public/common/http/structured_header.h
@@ -0,0 +1,87 @@
+// 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_HTTP_STRUCTURED_HEADER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_HTTP_STRUCTURED_HEADER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+namespace http_structured_header {
+
+// This file implements parsing of HTTP structured headers, as defined in
+// https://httpwg.org/http-extensions/draft-ietf-httpbis-header-structure.html.
+//
+// Currently supported data types are:
+// Item:
+// integer: 123
+// string: "abc"
+// token: abc
+// byte sequence: *YWJj*
+// Parameterised list: abc_123;a=1;b=2; cdef_456, ghi;q="9";r="w"
+// List-of-lists: "foo";"bar", "baz", "bat"; "one"
+//
+// Functions are provided to parse each of these, which are intended to be
+// called with the complete value of an HTTP header (that is, any
+// sub-structure will be handled internally by the parser; the exported
+// functions are not intended to be called on partial header strings.) Input
+// values should be ASCII byte strings (non-ASCII characters should not be
+// present in Structured Header values, and will cause the entire header to fail
+// to parse.)
+//
+// Note that all values of Item type are currently returned as strings. The
+// string, token and byte sequence examples above would all be returned by the
+// parser as the string "abc". It is not currently possible to determine which
+// type of Item was parsed from a given header.
+// TODO(1011101): Return values with type information attached.
+//
+// TODO(1011101): The current parser implementation is of draft #9
+// (https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-09) from
+// December 2018; this should be brought up to date with the latest changes.
+
+struct BLINK_COMMON_EXPORT ParameterisedIdentifier {
+ using Parameters = std::map<std::string, std::string>;
+
+ std::string identifier;
+ Parameters params;
+
+ ParameterisedIdentifier(const ParameterisedIdentifier&);
+ ParameterisedIdentifier& operator=(const ParameterisedIdentifier&);
+ ParameterisedIdentifier(const std::string&, const Parameters&);
+ ~ParameterisedIdentifier();
+};
+
+using ParameterisedList = std::vector<ParameterisedIdentifier>;
+using ListOfLists = std::vector<std::vector<std::string>>;
+
+// Returns the string representation of the header value, if it can be parsed as
+// an Item, or nullopt if it cannot. Note that the returned string is not
+// guaranteed to have any encoding, as it may have been a Byte Sequence.
+BLINK_COMMON_EXPORT base::Optional<std::string> ParseItem(
+ const base::StringPiece& str);
+
+// Returns the result of parsing the header value as a Parameterised List, if it
+// can be parsed as one, or nullopt if it cannot. Note that list items, as well
+// as parameter values, will be returned as strings, and that those strings are
+// not guaranteed to have any encoding, as they may have been Byte Sequences.
+BLINK_COMMON_EXPORT base::Optional<ParameterisedList> ParseParameterisedList(
+ const base::StringPiece& str);
+
+// Returns the result of parsing the header value as a List of Lists, if it can
+// be parsed as one, or nullopt if it cannot. Note that inner list items will be
+// be returned as strings, and that those strings are not guaranteed to have any
+// encoding, as they may have been Byte Sequences.
+BLINK_COMMON_EXPORT base::Optional<ListOfLists> ParseListOfLists(
+ const base::StringPiece& str);
+
+} // namespace http_structured_header
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_HTTP_STRUCTURED_HEADER_H_
diff --git a/chromium/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h b/chromium/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
index 35ad7e191cc..8a530d4f852 100644
--- a/chromium/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
@@ -8,7 +8,7 @@
#include "base/containers/span.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/indexeddb/indexeddb_key.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h"
namespace mojo {
diff --git a/chromium/third_party/blink/public/common/indexeddb/indexeddb_key_path.h b/chromium/third_party/blink/public/common/indexeddb/indexeddb_key_path.h
index 8ebe10c51d2..9f5422c88eb 100644
--- a/chromium/third_party/blink/public/common/indexeddb/indexeddb_key_path.h
+++ b/chromium/third_party/blink/public/common/indexeddb/indexeddb_key_path.h
@@ -22,10 +22,10 @@ class BLINK_COMMON_EXPORT IndexedDBKeyPath {
explicit IndexedDBKeyPath(const base::string16&);
explicit IndexedDBKeyPath(const std::vector<base::string16>&);
IndexedDBKeyPath(const IndexedDBKeyPath& other);
- IndexedDBKeyPath(IndexedDBKeyPath&& other) noexcept;
+ IndexedDBKeyPath(IndexedDBKeyPath&& other);
~IndexedDBKeyPath();
IndexedDBKeyPath& operator=(const IndexedDBKeyPath& other);
- IndexedDBKeyPath& operator=(IndexedDBKeyPath&& other) noexcept;
+ IndexedDBKeyPath& operator=(IndexedDBKeyPath&& other);
bool IsNull() const { return type_ == blink::mojom::IDBKeyPathType::Null; }
bool operator==(const IndexedDBKeyPath& other) const;
diff --git a/chromium/third_party/blink/public/common/indexeddb/indexeddb_metadata.h b/chromium/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
index 15663f608e9..7bb37c9ecc8 100644
--- a/chromium/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
+++ b/chromium/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
@@ -26,10 +26,10 @@ struct BLINK_COMMON_EXPORT IndexedDBIndexMetadata {
bool unique,
bool multi_entry);
IndexedDBIndexMetadata(const IndexedDBIndexMetadata& other);
- IndexedDBIndexMetadata(IndexedDBIndexMetadata&& other) noexcept;
+ IndexedDBIndexMetadata(IndexedDBIndexMetadata&& other);
~IndexedDBIndexMetadata();
IndexedDBIndexMetadata& operator=(const IndexedDBIndexMetadata& other);
- IndexedDBIndexMetadata& operator=(IndexedDBIndexMetadata&& other) noexcept;
+ IndexedDBIndexMetadata& operator=(IndexedDBIndexMetadata&& other);
bool operator==(const IndexedDBIndexMetadata& other) const;
base::string16 name;
@@ -50,12 +50,11 @@ struct BLINK_COMMON_EXPORT IndexedDBObjectStoreMetadata {
bool auto_increment,
int64_t max_index_id);
IndexedDBObjectStoreMetadata(const IndexedDBObjectStoreMetadata& other);
- IndexedDBObjectStoreMetadata(IndexedDBObjectStoreMetadata&& other) noexcept;
+ IndexedDBObjectStoreMetadata(IndexedDBObjectStoreMetadata&& other);
~IndexedDBObjectStoreMetadata();
IndexedDBObjectStoreMetadata& operator=(
const IndexedDBObjectStoreMetadata& other);
- IndexedDBObjectStoreMetadata& operator=(
- IndexedDBObjectStoreMetadata&& other) noexcept;
+ IndexedDBObjectStoreMetadata& operator=(IndexedDBObjectStoreMetadata&& other);
bool operator==(const IndexedDBObjectStoreMetadata& other) const;
base::string16 name;
@@ -77,11 +76,10 @@ struct BLINK_COMMON_EXPORT IndexedDBDatabaseMetadata {
int64_t version,
int64_t max_object_store_id);
IndexedDBDatabaseMetadata(const IndexedDBDatabaseMetadata& other);
- IndexedDBDatabaseMetadata(IndexedDBDatabaseMetadata&& other) noexcept;
+ IndexedDBDatabaseMetadata(IndexedDBDatabaseMetadata&& other);
~IndexedDBDatabaseMetadata();
IndexedDBDatabaseMetadata& operator=(const IndexedDBDatabaseMetadata& other);
- IndexedDBDatabaseMetadata& operator=(
- IndexedDBDatabaseMetadata&& other) noexcept;
+ IndexedDBDatabaseMetadata& operator=(IndexedDBDatabaseMetadata&& other);
bool operator==(const IndexedDBDatabaseMetadata& other) const;
base::string16 name;
diff --git a/chromium/third_party/blink/public/platform/web_loading_behavior_flag.h b/chromium/third_party/blink/public/common/loader/loading_behavior_flag.h
index b1342dd1bec..dfd67355836 100644
--- a/chromium/third_party/blink/public/platform/web_loading_behavior_flag.h
+++ b/chromium/third_party/blink/public/common/loader/loading_behavior_flag.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_PUBLIC_PLATFORM_WEB_LOADING_BEHAVIOR_FLAG_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOADING_BEHAVIOR_FLAG_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_LOADING_BEHAVIOR_FLAG_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_LOADING_BEHAVIOR_FLAG_H_
namespace blink {
@@ -12,33 +12,33 @@ namespace blink {
// features and potential areas of improvement in the loading stack. The main
// consumer is the page_load_metrics component, which sends bit flags to the
// browser process for histogram splitting.
-enum WebLoadingBehaviorFlag {
- kWebLoadingBehaviorNone = 0,
+enum LoadingBehaviorFlag {
+ kLoadingBehaviorNone = 0,
// Indicates that the page used the document.write evaluator to preload scan
// for resources inserted via document.write.
// DEPRECATED, feature has been turned down.
- kWebLoadingBehaviorDocumentWriteEvaluator = 1 << 0,
+ kLoadingBehaviorDocumentWriteEvaluator = 1 << 0,
// Indicates that the page is controlled by a Service Worker.
- kWebLoadingBehaviorServiceWorkerControlled = 1 << 1,
+ kLoadingBehaviorServiceWorkerControlled = 1 << 1,
// Indicates that the page has a synchronous, cross-origin document.written
// script.
- kWebLoadingBehaviorDocumentWriteBlock = 1 << 2,
+ kLoadingBehaviorDocumentWriteBlock = 1 << 2,
// Indicates that the page is a reload and has a synchronous, cross-origin
// document.written script.
- kWebLoadingBehaviorDocumentWriteBlockReload = 1 << 3,
+ kLoadingBehaviorDocumentWriteBlockReload = 1 << 3,
// The page loaded external CSS that generated a PreloadRequest via the
// CSSPreloaderResourceClient.
- kWebLoadingBehaviorCSSPreloadFound = 1 << 4,
+ kLoadingBehaviorCSSPreloadFound = 1 << 4,
// Indicates that the page has a synchronous, same-origin document.written
// script with different protocol.
- kWebLoadingBehaviorDocumentWriteBlockDifferentScheme = 1 << 5,
+ kLoadingBehaviorDocumentWriteBlockDifferentScheme = 1 << 5,
// Indicates that a subresource on the page matched the subresource filtering
// rules.
- kWebLoadingBehaviorSubresourceFilterMatch = 1 << 6,
+ kLoadingBehaviorSubresourceFilterMatch = 1 << 6,
// Indicates that the page is an AMP document, with <html amp> tag.
- kWebLoadingBehaviorAmpDocumentLoaded = 1 << 7,
+ kLoadingBehaviorAmpDocumentLoaded = 1 << 7,
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOADING_BEHAVIOR_FLAG_H_
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_LOADING_BEHAVIOR_FLAG_H_
diff --git a/chromium/third_party/blink/public/common/loader/mime_sniffing_throttle.h b/chromium/third_party/blink/public/common/loader/mime_sniffing_throttle.h
new file mode 100644
index 00000000000..6d714c822ff
--- /dev/null
+++ b/chromium/third_party/blink/public/common/loader/mime_sniffing_throttle.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_MIME_SNIFFING_THROTTLE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_MIME_SNIFFING_THROTTLE_H_
+
+#include "base/memory/weak_ptr.h"
+#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
+
+namespace blink {
+
+// Throttle for mime type sniffing. This may intercept the request and
+// modify the response's mime type in the response head.
+class BLINK_COMMON_EXPORT MimeSniffingThrottle : public URLLoaderThrottle {
+ public:
+ // |task_runner| is used to bind the right task runner for handling incoming
+ // IPC in MimeSniffingLoader. |task_runner| is supposed to be bound to the
+ // current sequence.
+ explicit MimeSniffingThrottle(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~MimeSniffingThrottle() override;
+
+ // Implements blink::URLLoaderThrottle.
+ void WillProcessResponse(const GURL& response_url,
+ network::ResourceResponseHead* response_head,
+ bool* defer) override;
+
+ // Called from MimeSniffingURLLoader once mime type is ready.
+ void ResumeWithNewResponseHead(
+ network::mojom::URLResponseHeadPtr new_response_head);
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ base::WeakPtrFactory<MimeSniffingThrottle> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_MIME_SNIFFING_THROTTLE_H_
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
new file mode 100644
index 00000000000..e9fb966866b
--- /dev/null
+++ b/chromium/third_party/blink/public/common/loader/mime_sniffing_url_loader.h
@@ -0,0 +1,159 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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_LOADER_MIME_SNIFFING_URL_LOADER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_MIME_SNIFFING_URL_LOADER_H_
+
+#include <tuple>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "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/cpp/shared_url_loader_factory.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-forward.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
+
+namespace blink {
+
+class MimeSniffingThrottle;
+
+// Reads the response body and determines its mime type. This url loader buffers
+// the response body until the mime type is decided. MimeSniffingURLLoader
+// is expected to be created just after receiving OnReceiveResponse(), so this
+// handles only OnStartLoadingResponseBody() and OnComplete() as a
+// network::mojom::URLLoaderClient.
+//
+// This loader has five states:
+// kWaitForBody: The initial state until the body is received (=
+// OnStartLoadingResponseBody() is called) or the response is
+// finished (= OnComplete() is called). When body is provided, the
+// state is changed to kSniffing. Otherwise the state goes to
+// kCompleted.
+// kSniffing: Receives the body from the source loader and estimate the mime
+// type. The received body is kept in this loader until the mime type
+// is decided. When the mime type is decided or all body has been
+// received, this loader will dispatch queued messages like
+// OnStartLoadingResponseBody() to the destination
+// loader client, and then the state is changed to kSending.
+// kSending: Receives the body and sends it to the destination loader client.
+// The state changes to kCompleted after all data is sent.
+// kCompleted: All data has been sent to the destination loader.
+// kAborted: Unexpected behavior happens. Watchers, pipes and the binding from
+// the source loader to |this| are stopped. All incoming messages from
+// the destination (through network::mojom::URLLoader) are ignored in
+// this state.
+class BLINK_COMMON_EXPORT MimeSniffingURLLoader
+ : public network::mojom::URLLoaderClient,
+ public network::mojom::URLLoader {
+ public:
+ ~MimeSniffingURLLoader() override;
+
+ // Start waiting for the body.
+ void Start(
+ mojo::PendingRemote<network::mojom::URLLoader> source_url_loader_remote,
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
+ source_url_client_receiver);
+
+ // mojo::PendingRemote<network::mojom::URLLoader> controls the lifetime of the
+ // loader.
+ static std::tuple<mojo::PendingRemote<network::mojom::URLLoader>,
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>,
+ MimeSniffingURLLoader*>
+ CreateLoader(base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ private:
+ MimeSniffingURLLoader(
+ base::WeakPtr<MimeSniffingThrottle> throttle,
+ const GURL& response_url,
+ network::mojom::URLResponseHeadPtr response_head,
+ mojo::PendingRemote<network::mojom::URLLoaderClient>
+ destination_url_loader_client,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ // network::mojom::URLLoaderClient implementation (called from the source of
+ // the response):
+ 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 ack_callback) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override;
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ // network::mojom::URLLoader implementation (called from the destination of
+ // the response):
+ void FollowRedirect(const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const base::Optional<GURL>& new_url) override;
+ void SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) override;
+ void PauseReadingBodyFromNet() override;
+ void ResumeReadingBodyFromNet() override;
+
+ void OnBodyReadable(MojoResult);
+ void OnBodyWritable(MojoResult);
+ void CompleteSniffing();
+ void CompleteSending();
+ void SendReceivedBodyToClient();
+ void ForwardBodyToClient();
+
+ void Abort();
+
+ static const char kDefaultMimeType[];
+
+ base::WeakPtr<MimeSniffingThrottle> throttle_;
+
+ mojo::Receiver<network::mojom::URLLoaderClient> source_url_client_receiver_{
+ this};
+ mojo::Remote<network::mojom::URLLoader> source_url_loader_;
+ mojo::Remote<network::mojom::URLLoaderClient> destination_url_loader_client_;
+
+ GURL response_url_;
+
+ // Capture the response head to defer to send it to the destination until the
+ // mime type is decided.
+ network::mojom::URLResponseHeadPtr response_head_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ enum class State { kWaitForBody, kSniffing, kSending, kCompleted, kAborted };
+ State state_ = State::kWaitForBody;
+
+ // Set if OnComplete() is called during sniffing.
+ base::Optional<network::URLLoaderCompletionStatus> complete_status_;
+
+ std::vector<char> buffered_body_;
+ size_t bytes_remaining_in_buffer_;
+
+ mojo::ScopedDataPipeConsumerHandle body_consumer_handle_;
+ mojo::ScopedDataPipeProducerHandle body_producer_handle_;
+ mojo::SimpleWatcher body_consumer_watcher_;
+ mojo::SimpleWatcher body_producer_watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(MimeSniffingURLLoader);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_LOADER_MIME_SNIFFING_URL_LOADER_H_
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 c0f1a45a205..738e05e007c 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
@@ -11,6 +11,7 @@
#include <utility>
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -37,9 +38,9 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundleInfo
std::map<std::string,
mojo::PendingRemote<network::mojom::URLLoaderFactory>>;
- // Map from origin of request initiator to PendingRemote<URLLoaderFactory> for
- // handling this initiator's requests (e.g., for relaxing CORB for requests
- // initiated from content scripts).
+ // Map from origin of isolated world to PendingRemote<URLLoaderFactory> for
+ // handling this isolated world's requests (e.g., for relaxing CORB for
+ // requests initiated from content scripts).
using OriginMap =
std::map<url::Origin,
mojo::PendingRemote<network::mojom::URLLoaderFactory>>;
@@ -49,7 +50,7 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundleInfo
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_default_factory,
SchemeMap scheme_specific_factory_infos,
- OriginMap initiator_specific_factory_infos,
+ OriginMap isolated_world_factory_infos,
bool bypass_redirect_checks);
~URLLoaderFactoryBundleInfo() override;
@@ -66,8 +67,8 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundleInfo
SchemeMap& pending_scheme_specific_factories() {
return pending_scheme_specific_factories_;
}
- OriginMap& pending_initiator_specific_factories() {
- return pending_initiator_specific_factories_;
+ OriginMap& pending_isolated_world_factories() {
+ return pending_isolated_world_factories_;
}
bool bypass_redirect_checks() const { return bypass_redirect_checks_; }
@@ -84,7 +85,7 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundleInfo
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_appcache_factory_;
SchemeMap pending_scheme_specific_factories_;
- OriginMap pending_initiator_specific_factories_;
+ OriginMap pending_isolated_world_factories_;
bool bypass_redirect_checks_ = false;
DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryBundleInfo);
@@ -109,7 +110,8 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundle
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
- void Clone(network::mojom::URLLoaderFactoryRequest request) override;
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
+ override;
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override;
bool BypassRedirectChecks() const override;
@@ -141,16 +143,15 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundle
return output;
}
- // TODO(crbug.com/955171): Replace URLLoaderFactoryPtr with Remote below.
// |default_factory_| is the default factory used by the bundle. It usually
// goes to "network", but it's possible it was overriden in case when the
// context should not be given access to the network.
- network::mojom::URLLoaderFactoryPtr default_factory_;
+ mojo::Remote<network::mojom::URLLoaderFactory> default_factory_;
// |appcache_factory_| is a special loader factory that intercepts
// requests when the context has AppCache. See also
// AppCacheSubresourceURLFactory.
- network::mojom::URLLoaderFactoryPtr appcache_factory_;
+ mojo::Remote<network::mojom::URLLoaderFactory> appcache_factory_;
// Map from URL scheme to Remote<URLLoaderFactory> for handling URL requests
// for schemes not handled by the |default_factory_|. See also
@@ -160,12 +161,12 @@ class BLINK_COMMON_EXPORT URLLoaderFactoryBundle
std::map<std::string, mojo::Remote<network::mojom::URLLoaderFactory>>;
SchemeMap scheme_specific_factories_;
- // Map from origin of request initiator to Remote<URLLoaderFactory> for
- // handling this initiator's requests. See also
+ // Map from origin of isolated world to Remote<URLLoaderFactory> for handling
+ // this isolated world's requests. See also
// URLLoaderFactoryBundleInfo::OriginMap.
using OriginMap =
std::map<url::Origin, mojo::Remote<network::mojom::URLLoaderFactory>>;
- OriginMap initiator_specific_factories_;
+ OriginMap isolated_world_factories_;
bool bypass_redirect_checks_ = false;
};
diff --git a/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h b/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
index 4727643fd28..be9179eff1f 100644
--- a/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
+++ b/chromium/third_party/blink/public/common/loader/url_loader_factory_bundle_mojom_traits.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
@@ -24,17 +25,17 @@ struct BLINK_COMMON_EXPORT
static void SetToNull(BundleInfoType* bundle) { bundle->reset(); }
- static network::mojom::URLLoaderFactoryPtrInfo default_factory(
+ static mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory(
BundleInfoType& bundle);
- static network::mojom::URLLoaderFactoryPtrInfo appcache_factory(
+ static mojo::PendingRemote<network::mojom::URLLoaderFactory> appcache_factory(
BundleInfoType& bundle);
static blink::URLLoaderFactoryBundleInfo::SchemeMap scheme_specific_factories(
BundleInfoType& bundle);
- static blink::URLLoaderFactoryBundleInfo::OriginMap
- initiator_specific_factories(BundleInfoType& bundle);
+ static blink::URLLoaderFactoryBundleInfo::OriginMap isolated_world_factories(
+ BundleInfoType& bundle);
static bool bypass_redirect_checks(BundleInfoType& bundle);
diff --git a/chromium/third_party/blink/public/common/loader/url_loader_throttle.h b/chromium/third_party/blink/public/common/loader/url_loader_throttle.h
index 33e95e7bbed..85ef30747d7 100644
--- a/chromium/third_party/blink/public/common/loader/url_loader_throttle.h
+++ b/chromium/third_party/blink/public/common/loader/url_loader_throttle.h
@@ -10,7 +10,8 @@
#include "base/strings/string_piece.h"
#include "net/base/request_priority.h"
-#include "services/network/public/mojom/url_loader.mojom.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/blink/public/common/common_export.h"
class GURL;
@@ -68,7 +69,7 @@ class BLINK_COMMON_EXPORT URLLoaderThrottle {
// URLLoaderThrottle::WillProcessResponse() and before calling
// Delegate::Resume().
virtual void UpdateDeferredResponseHead(
- const network::ResourceResponseHead& new_response_head);
+ network::mojom::URLResponseHeadPtr new_response_head);
// Pauses/resumes reading response body if the resource is fetched from
// network.
diff --git a/chromium/third_party/blink/public/common/logging/logging_utils.h b/chromium/third_party/blink/public/common/logging/logging_utils.h
index e016185216e..fd97b84a237 100644
--- a/chromium/third_party/blink/public/common/logging/logging_utils.h
+++ b/chromium/third_party/blink/public/common/logging/logging_utils.h
@@ -6,7 +6,8 @@
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_LOGGING_LOGGING_UTILS_H_
#include "base/logging.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-forward.h"
namespace blink {
diff --git a/chromium/third_party/blink/public/common/manifest/display_mode.typemap b/chromium/third_party/blink/public/common/manifest/display_mode.typemap
deleted file mode 100644
index df5f721f5a7..00000000000
--- a/chromium/third_party/blink/public/common/manifest/display_mode.typemap
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-mojom = "//third_party/blink/public/mojom/manifest/display_mode.mojom"
-public_headers =
- [ "//third_party/blink/public/common/manifest/web_display_mode.h" ]
-traits_headers = [
- "//third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h",
-]
-type_mappings = [ "blink.mojom.DisplayMode=::blink::WebDisplayMode" ]
diff --git a/chromium/third_party/blink/public/common/manifest/manifest.h b/chromium/third_party/blink/public/common/manifest/manifest.h
index e9cac5d90eb..fffe10b13c3 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest.h
@@ -14,8 +14,8 @@
#include "base/strings/nullable_string16.h"
#include "base/strings/string16.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@@ -149,9 +149,9 @@ struct BLINK_COMMON_EXPORT Manifest {
// Empty if the parsing failed or the field was not present.
GURL start_url;
- // Set to WebDisplayModeUndefined if the parsing failed or the field was not
+ // Set to DisplayMode::kUndefined if the parsing failed or the field was not
// present.
- blink::WebDisplayMode display;
+ blink::mojom::DisplayMode display;
// Set to blink::WebScreenOrientationLockDefault if the parsing failed or the
// field was not present.
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 eb53cc46e3d..450dd6523d8 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
@@ -67,7 +67,7 @@ struct BLINK_COMMON_EXPORT
return manifest.scope;
}
- static blink::WebDisplayMode display(const ::blink::Manifest& manifest) {
+ static blink::mojom::DisplayMode display(const ::blink::Manifest& manifest) {
return manifest.display;
}
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 2a2bd8f8334..d8fd9d0845d 100644
--- a/chromium/third_party/blink/public/common/manifest/manifest_util.h
+++ b/chromium/third_party/blink/public/common/manifest/manifest_util.h
@@ -8,23 +8,23 @@
#include <string>
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_lock_type.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
namespace blink {
-// Converts a blink::WebDisplayMode to a string. Returns one of
+// 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 blink::WebDisplayModeUndefined.
-BLINK_COMMON_EXPORT std::string WebDisplayModeToString(
- blink::WebDisplayMode display);
+// are lowercase. Returns an empty string for DisplayMode::kUndefined.
+BLINK_COMMON_EXPORT std::string DisplayModeToString(
+ blink::mojom::DisplayMode display);
-// Returns the blink::WebDisplayMode which matches |display|.
+// Returns the blink::mojom::DisplayMode which matches |display|.
// |display| should be one of
// https://www.w3.org/TR/appmanifest/#dfn-display-modes-values. |display| is
-// case insensitive. Returns blink::WebDisplayModeUndefined if there is no
+// case insensitive. Returns DisplayMode::kUndefined if there is no
// match.
-BLINK_COMMON_EXPORT blink::WebDisplayMode WebDisplayModeFromString(
+BLINK_COMMON_EXPORT blink::mojom::DisplayMode DisplayModeFromString(
const std::string& display);
// Converts a blink::WebScreenOrientationLockType to a string. Returns one of
diff --git a/chromium/third_party/blink/public/common/manifest/web_display_mode.h b/chromium/third_party/blink/public/common/manifest/web_display_mode.h
deleted file mode 100644
index 9ed8949672c..00000000000
--- a/chromium/third_party/blink/public/common/manifest/web_display_mode.h
+++ /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.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_WEB_DISPLAY_MODE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_WEB_DISPLAY_MODE_H_
-
-namespace blink {
-
-// Enumerates values of the display property of the Web App Manifest.
-//
-// TODO(dgozman): instead of this enum, use blink.mojom.DisplayMode directly.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.platform
-// GENERATED_JAVA_PREFIX_TO_STRIP: WebDisplayMode
-enum WebDisplayMode {
- kWebDisplayModeUndefined, // User for override setting (ie. not set).
- kWebDisplayModeBrowser,
- kWebDisplayModeMinimalUi,
- kWebDisplayModeStandalone,
- kWebDisplayModeFullscreen,
- kWebDisplayModeLast = kWebDisplayModeFullscreen
- // This enum is persisted to logs, and therefore is append-only and should not
- // be reordered.
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_WEB_DISPLAY_MODE_H_
diff --git a/chromium/third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h b/chromium/third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h
deleted file mode 100644
index 6319d540d98..00000000000
--- a/chromium/third_party/blink/public/common/manifest/web_display_mode_mojom_traits.h
+++ /dev/null
@@ -1,58 +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_COMMON_MANIFEST_WEB_DISPLAY_MODE_MOJOM_TRAITS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_WEB_DISPLAY_MODE_MOJOM_TRAITS_H_
-
-#include "mojo/public/cpp/bindings/enum_traits.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
-
-namespace mojo {
-
-template <>
-struct EnumTraits<blink::mojom::DisplayMode, blink::WebDisplayMode> {
- static blink::mojom::DisplayMode ToMojom(blink::WebDisplayMode input) {
- switch (input) {
- case blink::kWebDisplayModeUndefined:
- return blink::mojom::DisplayMode::UNDEFINED;
- case blink::kWebDisplayModeBrowser:
- return blink::mojom::DisplayMode::BROWSER;
- case blink::kWebDisplayModeMinimalUi:
- return blink::mojom::DisplayMode::MINIMAL_UI;
- case blink::kWebDisplayModeStandalone:
- return blink::mojom::DisplayMode::STANDALONE;
- case blink::kWebDisplayModeFullscreen:
- return blink::mojom::DisplayMode::FULLSCREEN;
- }
- NOTREACHED();
- return blink::mojom::DisplayMode::UNDEFINED;
- }
-
- static bool FromMojom(blink::mojom::DisplayMode input,
- blink::WebDisplayMode* output) {
- switch (input) {
- case blink::mojom::DisplayMode::UNDEFINED:
- *output = blink::kWebDisplayModeUndefined;
- return true;
- case blink::mojom::DisplayMode::BROWSER:
- *output = blink::kWebDisplayModeBrowser;
- return true;
- case blink::mojom::DisplayMode::MINIMAL_UI:
- *output = blink::kWebDisplayModeMinimalUi;
- return true;
- case blink::mojom::DisplayMode::STANDALONE:
- *output = blink::kWebDisplayModeStandalone;
- return true;
- case blink::mojom::DisplayMode::FULLSCREEN:
- *output = blink::kWebDisplayModeFullscreen;
- return true;
- }
- return false;
- }
-};
-
-} // namespace mojo
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_WEB_DISPLAY_MODE_MOJOM_TRAITS_H_
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 0d63e575f8a..d87affeb087 100644
--- a/chromium/third_party/blink/public/common/mediastream/media_devices.h
+++ b/chromium/third_party/blink/public/common/mediastream/media_devices.h
@@ -27,7 +27,7 @@ enum MediaDeviceType {
struct BLINK_COMMON_EXPORT WebMediaDeviceInfo {
WebMediaDeviceInfo();
WebMediaDeviceInfo(const WebMediaDeviceInfo& other);
- WebMediaDeviceInfo(WebMediaDeviceInfo&& other) noexcept;
+ WebMediaDeviceInfo(WebMediaDeviceInfo&& other);
WebMediaDeviceInfo(
const std::string& device_id,
const std::string& label,
@@ -37,7 +37,7 @@ struct BLINK_COMMON_EXPORT WebMediaDeviceInfo {
const media::VideoCaptureDeviceDescriptor& descriptor);
~WebMediaDeviceInfo();
WebMediaDeviceInfo& operator=(const WebMediaDeviceInfo& other);
- WebMediaDeviceInfo& operator=(WebMediaDeviceInfo&& other) noexcept;
+ WebMediaDeviceInfo& operator=(WebMediaDeviceInfo&& other);
std::string device_id;
std::string label;
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 e544a0895f4..9e9e3b80338 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
@@ -8,7 +8,7 @@
#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"
-#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
+#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-forward.h"
namespace mojo {
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 7ec0b47d2a3..8dbd9106cce 100644
--- a/chromium/third_party/blink/public/common/messaging/cloneable_message.h
+++ b/chromium/third_party/blink/public/common/messaging/cloneable_message.h
@@ -21,8 +21,8 @@ namespace blink {
// This type can be serialized as a blink::mojom::CloneableMessage struct.
struct BLINK_COMMON_EXPORT CloneableMessage {
CloneableMessage();
- CloneableMessage(CloneableMessage&&) noexcept;
- CloneableMessage& operator=(CloneableMessage&&) noexcept;
+ CloneableMessage(CloneableMessage&&);
+ CloneableMessage& operator=(CloneableMessage&&);
~CloneableMessage();
// Returns a shallow clone of this message. |encoded_message| in the clone
@@ -48,6 +48,7 @@ struct BLINK_COMMON_EXPORT CloneableMessage {
uint64_t stack_trace_id = 0;
int64_t stack_trace_debugger_id_first = 0;
int64_t stack_trace_debugger_id_second = 0;
+ bool stack_trace_should_pause = false;
// If not null, this message is locked to the given agent cluster ID.
// See
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 5ecec0337e7..8ae03d2666e 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
@@ -38,6 +38,10 @@ struct BLINK_COMMON_EXPORT
return input.stack_trace_debugger_id_second;
}
+ static bool stack_trace_should_pause(const blink::CloneableMessage& input) {
+ return input.stack_trace_should_pause;
+ }
+
static const base::Optional<base::UnguessableToken>& locked_agent_cluster_id(
const blink::CloneableMessage& input) {
return input.locked_agent_cluster_id;
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 5eef63c975b..2d87363d3b1 100644
--- a/chromium/third_party/blink/public/common/messaging/transferable_message.h
+++ b/chromium/third_party/blink/public/common/messaging/transferable_message.h
@@ -22,8 +22,8 @@ namespace blink {
// type can be serialized as a blink::mojom::TransferableMessage struct.
struct BLINK_COMMON_EXPORT TransferableMessage : public CloneableMessage {
TransferableMessage();
- TransferableMessage(TransferableMessage&&) noexcept;
- TransferableMessage& operator=(TransferableMessage&&) noexcept;
+ TransferableMessage(TransferableMessage&&);
+ TransferableMessage& operator=(TransferableMessage&&);
~TransferableMessage();
// Any ports being transferred as part of this message.
diff --git a/chromium/third_party/blink/public/web/web_triggering_event_info.h b/chromium/third_party/blink/public/common/navigation/triggering_event_info.h
index da8183ec7ab..9232d7f8a3f 100644
--- a/chromium/third_party/blink/public/web/web_triggering_event_info.h
+++ b/chromium/third_party/blink/public/common/navigation/triggering_event_info.h
@@ -2,14 +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_PUBLIC_WEB_WEB_TRIGGERING_EVENT_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_TRIGGERING_EVENT_INFO_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
namespace blink {
-// Extra info sometimes associated with a navigation. Mirrors
-// theWebTriggeringEventInfoEnum.
-enum class WebTriggeringEventInfo {
+// Extra info sometimes associated with a navigation.
+enum class TriggeringEventInfo {
kUnknown,
// The navigation was not triggered via a JS Event.
@@ -26,4 +25,4 @@ enum class WebTriggeringEventInfo {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_TRIGGERING_EVENT_INFO_H_
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
diff --git a/chromium/third_party/blink/public/common/notifications/notification_constants.h b/chromium/third_party/blink/public/common/notifications/notification_constants.h
index c88e3b7ab85..edda92a56fc 100644
--- a/chromium/third_party/blink/public/common/notifications/notification_constants.h
+++ b/chromium/third_party/blink/public/common/notifications/notification_constants.h
@@ -14,6 +14,32 @@ namespace blink {
constexpr base::TimeDelta kMaxNotificationShowTriggerDelay =
base::TimeDelta::FromDays(367);
+// TODO(johnme): The maximum number of actions is platform-specific and should
+// be indicated by the embedder.
+
+// Maximum number of actions on a Platform Notification.
+constexpr size_t kNotificationMaxActions = 2;
+
+// TODO(mvanouwerkerk): Update the notification resource loader to get the
+// appropriate image sizes from the embedder.
+
+// The maximum reasonable image size, scaled from dip units to pixels using the
+// largest supported scaling factor. TODO(johnme): Check sizes are correct.
+constexpr int kNotificationMaxImageWidthPx = 1800; // 450 dip * 4
+constexpr int kNotificationMaxImageHeightPx = 900; // 225 dip * 4
+
+// The maximum reasonable notification icon size, scaled from dip units to
+// pixels using the largest supported scaling factor.
+constexpr int kNotificationMaxIconSizePx = 320; // 80 dip * 4
+
+// The maximum reasonable badge size, scaled from dip units to pixels using the
+// largest supported scaling factor.
+constexpr int kNotificationMaxBadgeSizePx = 96; // 24 dip * 4
+
+// The maximum reasonable action icon size, scaled from dip units to
+// pixels using the largest supported scaling factor.
+constexpr int kNotificationMaxActionIconSizePx = 128; // 32 dip * 4
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_NOTIFICATIONS_NOTIFICATION_CONSTANTS_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 0cb169d3675..b2677a60ace 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
@@ -13,7 +13,7 @@
#include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h"
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/notifications/platform_notification_data.h"
-#include "third_party/blink/public/mojom/notifications/notification.mojom.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-forward.h"
#include "url/gurl.h"
#include "url/mojom/url_gurl_mojom_traits.h"
diff --git a/chromium/third_party/blink/public/common/notifications/platform_notification_data.h b/chromium/third_party/blink/public/common/notifications/platform_notification_data.h
index b39b0c95767..3d3c8f7a0ec 100644
--- a/chromium/third_party/blink/public/common/notifications/platform_notification_data.h
+++ b/chromium/third_party/blink/public/common/notifications/platform_notification_data.h
@@ -13,7 +13,7 @@
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/mojom/notifications/notification.mojom.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-forward.h"
#include "url/gurl.h"
namespace blink {
@@ -60,8 +60,7 @@ struct BLINK_COMMON_EXPORT PlatformNotificationData {
base::string16 title;
// Hint to determine the directionality of the displayed notification.
- mojom::NotificationDirection direction =
- mojom::NotificationDirection::LEFT_TO_RIGHT;
+ mojom::NotificationDirection direction;
// BCP 47 language tag describing the notification's contents. Optional.
std::string lang;
diff --git a/chromium/third_party/blink/public/common/page/page_zoom.h b/chromium/third_party/blink/public/common/page/page_zoom.h
new file mode 100644
index 00000000000..cc6b49e44d5
--- /dev/null
+++ b/chromium/third_party/blink/public/common/page/page_zoom.h
@@ -0,0 +1,26 @@
+// 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_PAGE_PAGE_ZOOM_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PAGE_PAGE_ZOOM_H_
+
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+
+// The minimum and maximum page zoom factors that are allowed.
+BLINK_COMMON_EXPORT extern const double kMinimumPageZoomFactor;
+BLINK_COMMON_EXPORT extern const double kMaximumPageZoomFactor;
+
+// Convert between page zoom factors and levels.
+BLINK_COMMON_EXPORT double PageZoomLevelToZoomFactor(double zoom_level);
+BLINK_COMMON_EXPORT double PageZoomFactorToZoomLevel(double factor);
+
+// Use this to compare page zoom factors and levels. It accounts for precision
+// loss due to conversions back and forth.
+BLINK_COMMON_EXPORT bool PageZoomValuesEqual(double value_a, double value_b);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PAGE_PAGE_ZOOM_H_
diff --git a/chromium/third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h b/chromium/third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h
new file mode 100644
index 00000000000..7972fc17340
--- /dev/null
+++ b/chromium/third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h
@@ -0,0 +1,33 @@
+// 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_COMMON_PEERCONNECTION_WEBRTC_IP_HANDLING_POLICY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PEERCONNECTION_WEBRTC_IP_HANDLING_POLICY_H_
+
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+
+// This is the default behavior of Chrome. Currently, WebRTC has the right to
+// enumerate all interfaces and bind them to discover public interfaces.
+BLINK_COMMON_EXPORT extern const char kWebRTCIPHandlingDefault[];
+
+// WebRTC should only use the default route used by http. This also exposes the
+// associated default private address. Default route is the route chosen by the
+// OS on a multi-homed endpoint.
+BLINK_COMMON_EXPORT extern const char
+ kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces[];
+
+// WebRTC should only use the default route used by http. This doesn't expose
+// any local addresses.
+BLINK_COMMON_EXPORT extern const char
+ kWebRTCIPHandlingDefaultPublicInterfaceOnly[];
+
+// WebRTC should only use TCP to contact peers or servers unless the proxy
+// server supports UDP. This doesn't expose any local addresses either.
+BLINK_COMMON_EXPORT extern const char kWebRTCIPHandlingDisableNonProxiedUdp[];
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PEERCONNECTION_WEBRTC_IP_HANDLING_POLICY_H_
diff --git a/chromium/third_party/blink/public/web/web_plugin_action.h b/chromium/third_party/blink/public/common/plugin/plugin_action.h
index 106e7e5b6f3..168b39a6365 100644
--- a/chromium/third_party/blink/public/web/web_plugin_action.h
+++ b/chromium/third_party/blink/public/common/plugin/plugin_action.h
@@ -28,12 +28,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PLUGIN_ACTION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PLUGIN_ACTION_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PLUGIN_PLUGIN_ACTION_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PLUGIN_PLUGIN_ACTION_H_
namespace blink {
-struct WebPluginAction {
+struct PluginAction {
enum Type {
kUnknown,
kRotate90Clockwise,
@@ -44,8 +44,8 @@ struct WebPluginAction {
Type type;
bool enable;
- WebPluginAction() : type(kUnknown), enable(false) {}
- WebPluginAction(Type type, bool enable) : type(type), enable(enable) {}
+ PluginAction() : type(kUnknown), enable(false) {}
+ PluginAction(Type type, bool enable) : type(type), enable(enable) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_presentation_receiver_flags.h b/chromium/third_party/blink/public/common/presentation/presentation_receiver_flags.h
index 8b0094b74f6..7059ba2b024 100644
--- a/chromium/third_party/blink/public/web/web_presentation_receiver_flags.h
+++ b/chromium/third_party/blink/public/common/presentation/presentation_receiver_flags.h
@@ -28,8 +28,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRESENTATION_RECEIVER_FLAGS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRESENTATION_RECEIVER_FLAGS_H_
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRESENTATION_PRESENTATION_RECEIVER_FLAGS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRESENTATION_PRESENTATION_RECEIVER_FLAGS_H_
#include "third_party/blink/public/common/frame/sandbox_flags.h"
@@ -38,10 +38,10 @@ namespace blink {
// Disable popups, modals, and top-level navigation for presentation receivers.
// See:
// https://w3c.github.io/presentation-api/#creating-a-receiving-browsing-context
-static constexpr WebSandboxFlags kPresentationReceiverSandboxFlags =
+constexpr WebSandboxFlags kPresentationReceiverSandboxFlags =
WebSandboxFlags::kPopups | WebSandboxFlags::kModals |
WebSandboxFlags::kTopNavigation;
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRESENTATION_RECEIVER_FLAGS_H_
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRESENTATION_PRESENTATION_RECEIVER_FLAGS_H_
diff --git a/chromium/third_party/blink/public/common/privacy_preferences.h b/chromium/third_party/blink/public/common/privacy_preferences.h
deleted file mode 100644
index efcaddee50e..00000000000
--- a/chromium/third_party/blink/public/common/privacy_preferences.h
+++ /dev/null
@@ -1,30 +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_PUBLIC_COMMON_PRIVACY_PREFERENCES_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_PREFERENCES_H_
-
-#include "third_party/blink/public/common/common_export.h"
-
-namespace blink {
-
-// Subset of content::RendererPreferences for passing the security info to
-// blink.
-// TODO(crbug.com/869748): Move this into a mojom struct and use the new struct
-// as a part of RendererPreferences once RendererPreferences becomes a mojom
-// struct.
-struct BLINK_COMMON_EXPORT PrivacyPreferences {
- PrivacyPreferences() = default;
- PrivacyPreferences(bool enable_do_not_track,
- bool enable_referrers);
-
- // These default values are coming from the defaults in
- // content::RendererPreferences.
- bool enable_do_not_track = false;
- bool enable_referrers = true;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_PREFERENCES_H_
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 f83259e2d67..8572a8017c7 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
@@ -5,6 +5,10 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_WEB_SCHEDULER_TRACKED_FEATURE_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_WEB_SCHEDULER_TRACKED_FEATURE_H_
+#include <stdint.h>
+
+#include "third_party/blink/public/common/common_export.h"
+
namespace blink {
namespace scheduler {
@@ -65,14 +69,21 @@ enum class WebSchedulerTrackedFeature {
kWebVR = 30,
kWebXR = 31,
+ kSharedWorker = 32,
+
+ kWebLocks = 33,
+
// NB: This enum is used in a bitmask, so kMaxValue must be less than 64.
- kMaxValue = kWebXR
+ kMaxValue = kWebLocks
};
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");
+BLINK_COMMON_EXPORT const char* FeatureToString(
+ WebSchedulerTrackedFeature feature);
+
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/public/common/security/security_style.h b/chromium/third_party/blink/public/common/security/security_style.h
new file mode 100644
index 00000000000..efcf4c9969c
--- /dev/null
+++ b/chromium/third_party/blink/public/common/security/security_style.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_SECURITY_STYLE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_SECURITY_STYLE_H_
+namespace blink {
+// This enum represents the security state of a resource.
+enum class SecurityStyle {
+ kUnknown,
+ kNeutral,
+ kInsecure,
+ kSecure,
+ kLast = kSecure
+};
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_SECURITY_SECURITY_STYLE_H_"
diff --git a/chromium/third_party/blink/public/common/sudden_termination_disabler_type.h b/chromium/third_party/blink/public/common/sudden_termination_disabler_type.h
new file mode 100644
index 00000000000..a13f0e97e21
--- /dev/null
+++ b/chromium/third_party/blink/public/common/sudden_termination_disabler_type.h
@@ -0,0 +1,18 @@
+// 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_SUDDEN_TERMINATION_DISABLER_TYPE_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SUDDEN_TERMINATION_DISABLER_TYPE_H_
+
+namespace blink {
+
+// Used when elements preventing the sudden termination of the frame become
+// present or become absent.
+using SuddenTerminationDisablerType = uint8_t;
+const SuddenTerminationDisablerType kBeforeUnloadHandler = 1 << 0;
+const SuddenTerminationDisablerType kUnloadHandler = 1 << 1;
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_SUDDEN_TERMINATION_DISABLER_TYPE_H_
diff --git a/chromium/third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h b/chromium/third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h
new file mode 100644
index 00000000000..7eee22c63d3
--- /dev/null
+++ b/chromium/third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h
@@ -0,0 +1,31 @@
+// 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_WEB_CACHE_WEB_CACHE_RESOURCE_TYPE_STATS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_CACHE_WEB_CACHE_RESOURCE_TYPE_STATS_H_
+
+#include <stddef.h>
+
+namespace blink {
+
+// A struct mirroring blink::MemoryCache::TypeStatistic.
+struct WebCacheResourceTypeStat {
+ size_t count;
+ size_t size;
+ size_t decoded_size;
+};
+
+// A struct mirroring blink::MemoryCache::Statistics.
+struct WebCacheResourceTypeStats {
+ WebCacheResourceTypeStat images;
+ WebCacheResourceTypeStat css_style_sheets;
+ WebCacheResourceTypeStat scripts;
+ WebCacheResourceTypeStat xsl_style_sheets;
+ WebCacheResourceTypeStat fonts;
+ WebCacheResourceTypeStat other;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_CACHE_WEB_CACHE_RESOURCE_TYPE_STATS_H_
diff --git a/chromium/third_party/blink/public/common/web_package/http_structured_header.h b/chromium/third_party/blink/public/common/web_package/http_structured_header.h
deleted file mode 100644
index b430307c3fa..00000000000
--- a/chromium/third_party/blink/public/common/web_package/http_structured_header.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_PUBLIC_COMMON_WEB_PACKAGE_HTTP_STRUCTURED_HEADER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_PACKAGE_HTTP_STRUCTURED_HEADER_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/optional.h"
-#include "base/strings/string_piece.h"
-#include "third_party/blink/public/common/common_export.h"
-
-namespace blink {
-namespace http_structured_header {
-
-struct BLINK_COMMON_EXPORT ParameterisedIdentifier {
- using Parameters = std::map<std::string, std::string>;
-
- std::string identifier;
- Parameters params;
-
- ParameterisedIdentifier(const ParameterisedIdentifier&);
- ParameterisedIdentifier(const std::string&, const Parameters&);
- ~ParameterisedIdentifier();
-};
-
-using ParameterisedList = std::vector<ParameterisedIdentifier>;
-using ListOfLists = std::vector<std::vector<std::string>>;
-
-BLINK_COMMON_EXPORT base::Optional<std::string> ParseItem(
- const base::StringPiece& str);
-BLINK_COMMON_EXPORT base::Optional<ParameterisedList> ParseParameterisedList(
- const base::StringPiece& str);
-BLINK_COMMON_EXPORT base::Optional<ListOfLists> ParseListOfLists(
- const base::StringPiece& str);
-
-} // namespace http_structured_header
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_WEB_PACKAGE_HTTP_STRUCTURED_HEADER_H_
diff --git a/chromium/third_party/blink/public/common/web_package/signed_exchange_request_matcher.h b/chromium/third_party/blink/public/common/web_package/signed_exchange_request_matcher.h
index d16ac435098..c6da00f833e 100644
--- a/chromium/third_party/blink/public/common/web_package/signed_exchange_request_matcher.h
+++ b/chromium/third_party/blink/public/common/web_package/signed_exchange_request_matcher.h
@@ -12,7 +12,7 @@
#include "base/gtest_prod_util.h"
#include "net/http/http_request_headers.h"
#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/web_package/http_structured_header.h"
+#include "third_party/blink/public/common/http/structured_header.h"
namespace blink {
diff --git a/chromium/third_party/blink/public/mojom/BUILD.gn b/chromium/third_party/blink/public/mojom/BUILD.gn
index a5a94a8ac50..d4971ab9ab9 100644
--- a/chromium/third_party/blink/public/mojom/BUILD.gn
+++ b/chromium/third_party/blink/public/mojom/BUILD.gn
@@ -44,6 +44,8 @@ mojom("mojom_platform") {
"dom_storage/storage_area.mojom",
"dom_storage/storage_partition_service.mojom",
"feature_policy/feature_policy.mojom",
+ "feature_policy/feature_policy_feature.mojom",
+ "feature_policy/policy_value.mojom",
"fetch/fetch_api_request.mojom",
"fetch/fetch_api_response.mojom",
"file/file_utilities.mojom",
@@ -52,6 +54,7 @@ mojom("mojom_platform") {
"frame/find_in_page.mojom",
"frame/frame.mojom",
"frame/frame_host_test_interface.mojom",
+ "frame/fullscreen.mojom",
"frame/lifecycle.mojom",
"frame/navigation_initiator.mojom",
"geolocation/geolocation_service.mojom",
@@ -141,6 +144,7 @@ mojom("mojom_platform") {
"worker/shared_worker_creation_context_type.mojom",
"worker/shared_worker_host.mojom",
"worker/shared_worker_info.mojom",
+ "worker/subresource_loader_updater.mojom",
"worker/worker_content_settings_proxy.mojom",
"worker/worker_main_script_load_params.mojom",
]
@@ -226,9 +230,6 @@ mojom("android_mojo_bindings") {
"webauthn/internal_authenticator.mojom",
"webshare/webshare.mojom",
]
- if (is_android && notouch_build) {
- sources += [ "media_controls/touchless/media_controls.mojom" ]
- }
public_deps = [
"//components/payments/mojom",
"//mojo/public/mojom/base",
diff --git a/chromium/third_party/blink/public/mojom/appcache/appcache.mojom b/chromium/third_party/blink/public/mojom/appcache/appcache.mojom
index 0e53a935460..b1419ace64f 100644
--- a/chromium/third_party/blink/public/mojom/appcache/appcache.mojom
+++ b/chromium/third_party/blink/public/mojom/appcache/appcache.mojom
@@ -138,5 +138,6 @@ interface AppCacheFrontend {
// In the network service world this message sets the URLLoaderFactory to be
// used for subresources.
- SetSubresourceFactory(network.mojom.URLLoaderFactory url_loader_factory);
+ SetSubresourceFactory(
+ pending_remote<network.mojom.URLLoaderFactory> url_loader_factory);
};
diff --git a/chromium/third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom b/chromium/third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom
index 20ce5b370d2..a588177e6af 100644
--- a/chromium/third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom
+++ b/chromium/third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom
@@ -11,5 +11,7 @@ interface AssociatedInterface {};
// Analogous to the generic InterfaceProvider interface, but for content
// AssociatedInterfaces.
interface AssociatedInterfaceProvider {
- GetAssociatedInterface(string name, associated AssociatedInterface& request);
+ GetAssociatedInterface(
+ string name,
+ pending_associated_receiver<AssociatedInterface> receiver);
};
diff --git a/chromium/third_party/blink/public/mojom/badging/badging.mojom b/chromium/third_party/blink/public/mojom/badging/badging.mojom
index 3b7e10ae8f0..4d0296b9c08 100644
--- a/chromium/third_party/blink/public/mojom/badging/badging.mojom
+++ b/chromium/third_party/blink/public/mojom/badging/badging.mojom
@@ -20,12 +20,8 @@ union BadgeValue {
// Interface for handling badge messages from frames and subframes.
interface BadgeService {
// Asks the browser process to set a badge.
- // |scope| specifies which badges to set. Note: This must be on the same
- // origin as the caller.
- SetBadge(url.mojom.Url scope, BadgeValue value);
+ SetBadge(BadgeValue value);
// Asks the browser to clear a badge.
- // |scope| specifies the badges to clear. Note: This must be on the same
- // origin as the caller.
- ClearBadge(url.mojom.Url scope);
+ ClearBadge();
};
diff --git a/chromium/third_party/blink/public/mojom/blob/blob.mojom b/chromium/third_party/blink/public/mojom/blob/blob.mojom
index 61c10a2a35e..9abc424434f 100644
--- a/chromium/third_party/blink/public/mojom/blob/blob.mojom
+++ b/chromium/third_party/blink/public/mojom/blob/blob.mojom
@@ -33,7 +33,7 @@ interface Blob {
Clone(pending_receiver<Blob> blob);
// Creates a reference to this Blob as a DataPipeGetter.
- AsDataPipeGetter(network.mojom.DataPipeGetter& data_pipe_getter);
+ AsDataPipeGetter(pending_receiver<network.mojom.DataPipeGetter> data_pipe_getter);
// Causes the entire contents of this blob to be written into the given data
// pipe. An optional BlobReaderClient will be informed of the result of the
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 33f4779524f..ca0fa77b394 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
@@ -22,7 +22,7 @@ interface BlobURLStore {
Revoke(url.mojom.Url url);
// Resolves a public Blob URL.
- Resolve(url.mojom.Url url) => (blink.mojom.Blob? blob);
+ Resolve(url.mojom.Url url) => (pending_remote<blink.mojom.Blob>? blob);
// 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
@@ -31,8 +31,9 @@ interface BlobURLStore {
// As long as the resulting URLLoaderFactory is alive the resolved blob will
// 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,
- network.mojom.URLLoaderFactory& factory);
+ ResolveAsURLLoaderFactory(
+ url.mojom.Url url,
+ pending_receiver<network.mojom.URLLoaderFactory> factory);
// 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
diff --git a/chromium/third_party/blink/public/mojom/blob/data_element.mojom b/chromium/third_party/blink/public/mojom/blob/data_element.mojom
index 7afa95ad97f..3767c31c7ae 100644
--- a/chromium/third_party/blink/public/mojom/blob/data_element.mojom
+++ b/chromium/third_party/blink/public/mojom/blob/data_element.mojom
@@ -103,7 +103,7 @@ struct DataElementFilesystemURL {
// A reference to a slice of another blob.
struct DataElementBlob {
// The blob being referenced.
- blink.mojom.Blob blob;
+ pending_remote<blink.mojom.Blob> blob;
// Offset to the beginning of the slice.
uint64 offset;
// Length of the slice.
diff --git a/chromium/third_party/blink/public/mojom/blob/serialized_blob.mojom b/chromium/third_party/blink/public/mojom/blob/serialized_blob.mojom
index f346205fecc..f99f2b10c88 100644
--- a/chromium/third_party/blink/public/mojom/blob/serialized_blob.mojom
+++ b/chromium/third_party/blink/public/mojom/blob/serialized_blob.mojom
@@ -14,5 +14,5 @@ struct SerializedBlob {
string uuid;
string content_type;
uint64 size;
- Blob blob;
+ pending_remote<Blob> blob;
};
diff --git a/chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom b/chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
index 65bf6c8fea2..c798d5e3d49 100644
--- a/chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
+++ b/chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
@@ -191,7 +191,8 @@ interface WebBluetoothService {
// Returns the result of the connection request.
RemoteServerConnect(
WebBluetoothDeviceId device_id,
- associated WebBluetoothServerClient client) => (WebBluetoothResult result);
+ pending_associated_remote<WebBluetoothServerClient> client) => (
+ WebBluetoothResult result);
// If a GATT connection exists for Device identified by |device_id| then
// decreases the ref count for that connection.
@@ -245,7 +246,7 @@ interface WebBluetoothService {
// Returns the result of the connection request.
RemoteCharacteristicStartNotifications(
string characteristic_instance_id,
- associated WebBluetoothCharacteristicClient client) => (
+ pending_associated_remote<WebBluetoothCharacteristicClient> client) => (
WebBluetoothResult result);
// Stops notifications for the characteristic identified by
@@ -285,9 +286,10 @@ interface WebBluetoothService {
array<uint8> value) => (WebBluetoothResult result);
// Starts scanning for low energy devices.
- RequestScanningStart(associated WebBluetoothScanClient client,
- WebBluetoothRequestLEScanOptions options) => (
- RequestScanningStartResult result);
+ RequestScanningStart(
+ pending_associated_remote<WebBluetoothScanClient> client,
+ WebBluetoothRequestLEScanOptions options) => (
+ RequestScanningStartResult result);
};
// Classes that implement this interface will be notified of device events.
diff --git a/chromium/third_party/blink/public/mojom/cache_storage/cache_storage.mojom b/chromium/third_party/blink/public/mojom/cache_storage/cache_storage.mojom
index e08e10308e3..da1c6bdc793 100644
--- a/chromium/third_party/blink/public/mojom/cache_storage/cache_storage.mojom
+++ b/chromium/third_party/blink/public/mojom/cache_storage/cache_storage.mojom
@@ -5,11 +5,10 @@
module blink.mojom;
import "mojo/public/mojom/base/read_only_buffer.mojom";
-import "mojo/public/mojom/base/time.mojom";
+import "third_party/blink/public/mojom/blob/blob.mojom";
import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom";
import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
import "mojo/public/mojom/base/string16.mojom";
-import "url/mojom/url.mojom";
// This enum is used in histograms, so do not change the ordering and always
// append new types to the end.
@@ -75,7 +74,15 @@ struct BatchOperation {
// Result of Open method. |status| is only set if there is a failure.
union OpenResult {
CacheStorageError status;
- associated CacheStorageCache cache;
+ pending_associated_remote<CacheStorageCache> cache;
+};
+
+// EagerResponse: A blob response where the source has eagerly started reading
+// the body into a DataPipe.
+struct EagerResponse {
+ blink.mojom.FetchAPIResponse response;
+ handle<data_pipe_consumer> pipe;
+ pending_receiver<BlobReaderClient> client_receiver;
};
// Result of Match for both interfaces CacheStorage and CacheStorageCache
@@ -83,6 +90,7 @@ union OpenResult {
union MatchResult {
CacheStorageError status;
blink.mojom.FetchAPIResponse response;
+ EagerResponse eager_response;
};
// Result of MatchAll method |status| is only set if there is a failure.
@@ -102,8 +110,11 @@ union CacheKeysResult {
// defined on spec: https://w3c.github.io/ServiceWorker/#cache-interface
interface CacheStorageCache {
// Returns the first cached response that matches |request| according to
- // options specified on |query_options|.
- Match(blink.mojom.FetchAPIRequest request, CacheQueryOptions query_options, int64 trace_id)
+ // options specified on |query_options|. |in_related_fetch_event| will be
+ // true if the operation was initiated within a FetchEvent handler with
+ // a matching request URL.
+ Match(blink.mojom.FetchAPIRequest request, CacheQueryOptions query_options,
+ bool in_related_fetch_event, int64 trace_id)
=> (MatchResult result);
// Returns all cached responses that match |request| according to options
@@ -119,11 +130,6 @@ interface CacheStorageCache {
// Perform a batch of operations, used for PUT and DELETE operations.
Batch(array<BatchOperation> batch_operations, int64 trace_id)
=> (CacheStorageVerboseError result);
-
- // Sets |side_data| if there is an entry of which key is |url| and the entry
- // has the same |response_time|.
- SetSideData(url.mojom.Url url, mojo_base.mojom.Time response_time,
- mojo_base.mojom.ReadOnlyBuffer side_data, int64 trace_id) => (CacheStorageError result);
};
// Handles global CacheStorage methods, directly relates to methods available on
@@ -140,8 +146,10 @@ interface CacheStorage {
// Returns the first cached response that matches |request| and
// |match_options|. It can search on all caches if |cache_name| isn't provided
- // on |match_options|.
- Match(blink.mojom.FetchAPIRequest request, MultiCacheQueryOptions match_options, int64 trace_id)
+ // on |match_options|. |in_related_fetch_event| will be true if the operation
+ // was initiated within a FetchEvent handler with a matching request URL.
+ Match(blink.mojom.FetchAPIRequest request, MultiCacheQueryOptions match_options,
+ bool in_related_fetch_event, int64 trace_id)
=> (MatchResult result);
// Opens and returns a mojo interface to a cache, it creates if doesn't exist.
diff --git a/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom b/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
index f7064c836ce..a1f0d0f2fed 100644
--- a/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
+++ b/chromium/third_party/blink/public/mojom/clipboard/clipboard.mojom
@@ -5,6 +5,7 @@
module blink.mojom;
import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/big_buffer.mojom";
import "skia/public/mojom/bitmap.mojom";
import "url/mojom/url.mojom";
@@ -65,7 +66,11 @@ interface ClipboardHost {
WriteSmartPasteMarker();
+ // Chrome-specific pickled data.
WriteCustomData(map<mojo_base.mojom.String16, mojo_base.mojom.BigString16> data);
+ // Arbitrary unsanitized data from renderer.
+ // NOTE: This has no callers, but will with Raw Clipboard Access.
+ WriteRawData(mojo_base.mojom.String16 format, mojo_base.mojom.BigBuffer data);
// TODO(dcheng): The |url| parameter should really be a GURL, but <canvas>'s
// copy as image tries to set very long data: URLs on the clipboard. Using
diff --git a/chromium/third_party/blink/public/mojom/content_index/content_index.mojom b/chromium/third_party/blink/public/mojom/content_index/content_index.mojom
index 23d7baac5d8..7d3e00ce4dd 100644
--- a/chromium/third_party/blink/public/mojom/content_index/content_index.mojom
+++ b/chromium/third_party/blink/public/mojom/content_index/content_index.mojom
@@ -26,8 +26,11 @@ enum ContentIndexError {
// These values are persisted and recorded, do not change or create gaps.
enum ContentCategory {
+ // ""
+ NONE = 0,
+
// "homepage"
- HOME_PAGE = 1,
+ HOME_PAGE,
// "article"
ARTICLE,
diff --git a/chromium/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom b/chromium/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
index 09534aa956f..a5d5ad16f2a 100644
--- a/chromium/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
+++ b/chromium/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
@@ -20,6 +20,13 @@ struct DWriteFontStyle {
uint8 font_stretch;
};
+struct FallbackFamilyAndStyle {
+ string fallback_family_name;
+ uint16 weight;
+ uint8 width;
+ uint8 slant;
+};
+
struct MapCharactersResult {
uint32 family_index;
mojo_base.mojom.String16 family_name;
@@ -120,8 +127,8 @@ interface DWriteFontProxy {
// Use only on Windows 8.0 and earlier - otherwise better fallback API is
// available through using a proxies IDWriteFontFallback.
[Sync]
- FallbackFamilyNameForCodepoint(string base_family_name,
- string bcp47_language_tag,
- uint32 codepoint)
- => (string fallback_family_name);
+ FallbackFamilyAndStyleForCodepoint(string base_family_name,
+ string bcp47_language_tag,
+ uint32 codepoint)
+ => (FallbackFamilyAndStyle fallback_result);
};
diff --git a/chromium/third_party/blink/public/mojom/feature_policy/PRESUBMIT.py b/chromium/third_party/blink/public/mojom/feature_policy/PRESUBMIT.py
index 3991ea358ae..ff785dec725 100644
--- a/chromium/third_party/blink/public/mojom/feature_policy/PRESUBMIT.py
+++ b/chromium/third_party/blink/public/mojom/feature_policy/PRESUBMIT.py
@@ -22,7 +22,7 @@ def _RunUmaHistogramChecks(input_api, output_api): # pylint: disable=C0103
source_path = ''
for f in input_api.AffectedFiles():
- if f.LocalPath().endswith('feature_policy.mojom'):
+ if f.LocalPath().endswith('feature_policy_feature.mojom'):
source_path = f.LocalPath()
break
else:
diff --git a/chromium/third_party/blink/public/mojom/feature_policy/feature_policy.mojom b/chromium/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
index 8999739e5bb..f01cfdcb5ae 100644
--- a/chromium/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
+++ b/chromium/third_party/blink/public/mojom/feature_policy/feature_policy.mojom
@@ -5,6 +5,8 @@
module blink.mojom;
import "url/mojom/origin.mojom";
+import "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom";
+import "third_party/blink/public/mojom/feature_policy/policy_value.mojom";
// This mirrors blink::WebSandboxFlags enum bitfield.
[Extensible]
@@ -26,143 +28,7 @@ enum WebSandboxFlags {
kPresentationController = 8192, // 1 << 13
kTopNavigationByUserActivation = 16384, // 1 << 14
kDownloads = 32768, // 1 << 15
-};
-
-// These values map to the features which can be controlled by Feature Policy.
-//
-// Features are listed in
-// https://github.com/WICG/feature-policy/blob/master/features.md. Not all
-// listed features are supported in Blink, and many are gated by runtime flags.
-// See renderer/platform/feature_policy/feature_policy.cc for the feature names
-// which will be recognized in policy declarations.
-enum FeaturePolicyFeature {
- kNotFound = 0,
- // Controls access to media autoplay.
- kAutoplay = 1,
- // Controls access to video input devices.
- kCamera = 2,
- // Controls whether navigator.requestMediaKeySystemAccess is allowed.
- kEncryptedMedia = 3,
- // Controls whether Element.requestFullscreen is allowed.
- kFullscreen = 4,
- // Controls access to Geolocation interface.
- kGeolocation = 5,
- // Controls access to audio input devices.
- kMicrophone = 6,
- // Controls access to requestMIDIAccess method.
- kMidiFeature = 7,
- // Controls access to PaymentRequest interface.
- kPayment = 8,
- // Controls access to document.cookie attribute.
- kDocumentCookie = 10,
- // Contols access to document.domain attribute.
- kDocumentDomain = 11,
- // Controls whether synchronous script elements will run.
- kSyncScript = 12,
- // Controls use of synchronous XMLHTTPRequest API.
- kSyncXHR = 13,
- // Controls access to the WebUSB API.
- kUsb = 14,
- // Controls access to AOM event listeners.
- kAccessibilityEvents = 15,
- // Controls use of WebVR API.
- kWebVr = 16,
- // The following features control access to the corresponding sensor classes.
- // Fusion sensor APIs (e.g. LinearAcceleration, OrientationSensor-based
- // classes)require all of the features that are inputs into that API to be
- // enabled for the feature to be allowed.
- kAccelerometer = 17,
- kAmbientLightSensor = 18,
- kGyroscope = 19,
- kMagnetometer = 20,
- // Controls the layout size of intrinsically sized images and videos. When
- // disabled, default size (300 x 150) is used to prevent relayout.
- kUnsizedMedia = 21,
- // When disallowed, restricts source image size to be no more 2x larger than
- // the image's containing block.
- kOversizedImages = 25,
- // Controls access to Picture-in-Picture.
- kPictureInPicture = 26,
- // Controls the ability to block and interfere with vertical scrolling.
- kVerticalScroll = 27,
- // Controls the ability of the document to use several dynamic markup API
- // which interfere with document's input stream (document.write(),
- // document.close(), etc.).
- kDocumentWrite = 28,
- // TODO(ekaramad): kLazyLoad is deprecated; remove.
- // Used to enforce lazyloading for a frame and any nested <iframe> or image.
- kLazyLoad = 29,
- // Restricts the usage of layout-causing animations in a document.
- kLayoutAnimations = 30,
- // Controls access to WakeLock
- kWakeLock = 31,
- // Controls access to font-display attribute in @font-face CSS rule
- kFontDisplay = 32,
-
- // These are the defined sandbox features implemented as policy-controlled
- // features.
- kTopNavigation = 33,
- kFormSubmission = 34,
- kScript = 35,
- kPopups = 36,
- kPointerLock = 37,
- kModals = 38,
- kOrientationLock = 39,
- kPresentation = 40,
- // End of sandbox features.
-
- // Sample Origin Trial enabled feature. This is used only for testing.
- kFrobulate = 41,
- // Controls access to Serial
- kSerial = 42,
- // Controls access to WebHID.
- kHid = 43,
- // Controls access to Idle Detection
- kIdleDetection = 44,
-
- // When disallowed, these policies require images to have a reasonable byte-to-pixel ratio.
- kUnoptimizedLossyImages = 45,
- kUnoptimizedLosslessImages = 46,
- kUnoptimizedLosslessImagesStrict = 47,
-
- // Loading policies.
- kLoadingFrameDefaultEager = 48,
-
- // Implements sandbox flag: allow-downloads-without-user-activation.
- kDownloadsWithoutUserActivation = 49,
-
- // Allow execution while not in the viewport.
- kExecutionWhileOutOfViewport = 50,
- // Allow execution while not rendered.
- kExecutionWhileNotRendered = 51,
-
- // When disallowed, a frame without user activation cannot acquire focus.
- kFocusWithoutUserActivation = 52,
-
- // Client Hints
- kClientHintDPR = 53,
- kClientHintDeviceMemory = 54,
- kClientHintDownlink = 55,
- kClientHintECT = 56,
- kClientHintLang = 57,
- kClientHintRTT = 58,
- kClientHintUA = 59,
- kClientHintUAArch = 60,
- kClientHintUAModel = 61,
- kClientHintUAPlatform = 62,
- kClientHintViewportWidth = 63,
- kClientHintWidth = 64,
-
- // Whether all cross document access to this window object is treated as cross origin.
- kDocumentAccess = 65,
-
- // Controls use of WebXR API.
- kWebXr = 66,
-
- // 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_feature_policy_enum.py in
- // chromium/src/tools/metrics/histograms/ to update the UMA mapping.
+ kStorageAccessByUserActivation = 65536, // 1 << 16
};
// This enum is used to distinguish between report-only directives and enforcing
@@ -172,28 +38,6 @@ enum FeaturePolicyDisposition {
kReport,
};
-// This enum defines the types of parameters used to specify a feature policy.
-// TODO(loonybear): Add the following types: inc/dec int, inc double, enum, set.
-enum PolicyValueType {
- kNull,
- kBool,
- kDecDouble,
-};
-
-// This union includes all the types that can be used to specify a policy's
-// parameter.
-// TODO(loonybear): Add the following types: inc/dec int, inc double, enum, set.
-union PolicyValueData {
- bool null_value;
- bool bool_value;
- double dec_double_value;
-};
-
-// Defined as a structure so that it can be typemapped with StructTraits.
-struct PolicyValue {
- PolicyValueData data;
-};
-
// This struct holds feature policy allowlist data that needs to be replicated
// between a RenderFrame and any of its associated RenderFrameProxies. A list of
// these form a ParsedFeaturePolicy.
diff --git a/chromium/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom b/chromium/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
new file mode 100644
index 00000000000..7271d5988a1
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
@@ -0,0 +1,142 @@
+// 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;
+
+// These values map to the features which can be controlled by Feature Policy.
+//
+// Features are listed in
+// https://github.com/WICG/feature-policy/blob/master/features.md. Not all
+// listed features are supported in Blink, and many are gated by runtime flags.
+// See renderer/platform/feature_policy/feature_policy.cc for the feature names
+// which will be recognized in policy declarations.
+enum FeaturePolicyFeature {
+ kNotFound = 0,
+ // Controls access to media autoplay.
+ kAutoplay = 1,
+ // Controls access to video input devices.
+ kCamera = 2,
+ // Controls whether navigator.requestMediaKeySystemAccess is allowed.
+ kEncryptedMedia = 3,
+ // Controls whether Element.requestFullscreen is allowed.
+ kFullscreen = 4,
+ // Controls access to Geolocation interface.
+ kGeolocation = 5,
+ // Controls access to audio input devices.
+ kMicrophone = 6,
+ // Controls access to requestMIDIAccess method.
+ kMidiFeature = 7,
+ // Controls access to PaymentRequest interface.
+ kPayment = 8,
+ // Controls access to document.cookie attribute.
+ kDocumentCookie = 10,
+ // Controls access to document.domain attribute.
+ kDocumentDomain = 11,
+ // Controls whether synchronous script elements will run.
+ kSyncScript = 12,
+ // Controls use of synchronous XMLHTTPRequest API.
+ kSyncXHR = 13,
+ // Controls access to the WebUSB API.
+ kUsb = 14,
+ // Controls access to AOM event listeners.
+ kAccessibilityEvents = 15,
+ // Controls use of WebVR API.
+ kWebVr = 16,
+ // The following features control access to the corresponding sensor classes.
+ // Fusion sensor APIs (e.g. LinearAcceleration, OrientationSensor-based
+ // classes)require all of the features that are inputs into that API to be
+ // enabled for the feature to be allowed.
+ kAccelerometer = 17,
+ kAmbientLightSensor = 18,
+ kGyroscope = 19,
+ kMagnetometer = 20,
+ // Controls the layout size of intrinsically sized images and videos. When
+ // disabled, default size (300 x 150) is used to prevent relayout.
+ kUnsizedMedia = 21,
+ // When disallowed, restricts source image size to be no more 2x larger than
+ // the image's containing block.
+ kOversizedImages = 25,
+ // Controls access to Picture-in-Picture.
+ kPictureInPicture = 26,
+ // Controls the ability to block and interfere with vertical scrolling.
+ kVerticalScroll = 27,
+ // Controls the ability of the document to use several dynamic markup API
+ // which interfere with document's input stream (document.write(),
+ // document.close(), etc.).
+ kDocumentWrite = 28,
+ // TODO(ekaramad): kLazyLoad is deprecated; remove.
+ // Used to enforce lazyloading for a frame and any nested <iframe> or image.
+ kLazyLoad = 29,
+ // Restricts the usage of layout-causing animations in a document.
+ kLayoutAnimations = 30,
+ // Controls access to WakeLock
+ kWakeLock = 31,
+ // Controls access to font-display attribute in @font-face CSS rule
+ kFontDisplay = 32,
+
+ // These are the defined sandbox features implemented as policy-controlled
+ // features.
+ kTopNavigation = 33,
+ kFormSubmission = 34,
+ kScript = 35,
+ kPopups = 36,
+ kPointerLock = 37,
+ kModals = 38,
+ kOrientationLock = 39,
+ kPresentation = 40,
+ // End of sandbox features.
+
+ // Sample Origin Trial enabled feature. This is used only for testing.
+ kFrobulate = 41,
+ // Controls access to Serial
+ kSerial = 42,
+ // Controls access to WebHID.
+ kHid = 43,
+ // Controls access to Idle Detection
+ kIdleDetection = 44,
+
+ // When disallowed, these policies require images to have a reasonable byte-to-pixel ratio.
+ kUnoptimizedLossyImages = 45,
+ kUnoptimizedLosslessImages = 46,
+ kUnoptimizedLosslessImagesStrict = 47,
+
+ // Loading policies.
+ kLoadingFrameDefaultEager = 48,
+
+ // Implements sandbox flag: allow-downloads-without-user-activation.
+ kDownloadsWithoutUserActivation = 49,
+
+ // Allow execution while not in the viewport.
+ kExecutionWhileOutOfViewport = 50,
+ // Allow execution while not rendered.
+ kExecutionWhileNotRendered = 51,
+
+ // When disallowed, a frame without user activation cannot acquire focus.
+ kFocusWithoutUserActivation = 52,
+
+ // Client Hints
+ kClientHintDPR = 53,
+ kClientHintDeviceMemory = 54,
+ kClientHintDownlink = 55,
+ kClientHintECT = 56,
+ kClientHintLang = 57,
+ kClientHintRTT = 58,
+ kClientHintUA = 59,
+ kClientHintUAArch = 60,
+ kClientHintUAModel = 61,
+ kClientHintUAPlatform = 62,
+ kClientHintViewportWidth = 63,
+ kClientHintWidth = 64,
+
+ // Whether all cross document access to this window object is treated as cross origin.
+ kDocumentAccess = 65,
+
+ // Controls use of WebXR API.
+ kWebXr = 66,
+
+ // 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_feature_policy_enum.py in
+ // chromium/src/tools/metrics/histograms/ to update the UMA mapping.
+};
diff --git a/chromium/third_party/blink/public/mojom/feature_policy/policy_value.mojom b/chromium/third_party/blink/public/mojom/feature_policy/policy_value.mojom
new file mode 100644
index 00000000000..7a8cca0a492
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/feature_policy/policy_value.mojom
@@ -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.
+
+module blink.mojom;
+
+// This enum defines the types of parameters used to specify a feature policy.
+// TODO(loonybear): Add the following types: inc/dec int, inc double, enum, set.
+enum PolicyValueType {
+ kNull,
+ kBool,
+ kDecDouble,
+};
+
+// This union includes all the types that can be used to specify a policy's
+// parameter.
+// TODO(loonybear): Add the following types: inc/dec int, inc double, enum, set.
+union PolicyValueData {
+ bool null_value;
+ bool bool_value;
+ double dec_double_value;
+};
+
+// Defined as a structure so that it can be typemapped with StructTraits.
+struct PolicyValue {
+ PolicyValueData data;
+};
+
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 622e84be563..2d9be3fff71 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
@@ -6,6 +6,7 @@ module blink.mojom;
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/fetch_api.mojom";
+import "services/network/public/mojom/content_security_policy.mojom";
import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom";
import "url/mojom/url.mojom";
@@ -59,6 +60,16 @@ struct FetchAPIResponse {
// set of headers that should be exposed.
array<string> cors_exposed_header_names;
- // Side data is used to pass the metadata of the response (eg. V8 code cache).
+ // Used to pass code cache for responses produced by cache_storage. The code
+ // cache will be stored in the side data stream of the blob.
SerializedBlob? side_data_blob;
+
+ // Used to pass code cache for a response that is being newly stored in
+ // cache_storage. This blob is created from a memory buffer in the renderer
+ // and the code cache is contained in the primary data stream of the blob.
+ SerializedBlob? side_data_blob_for_cache_put;
+
+ // In case this response had a Content-Security-Policy header, this is the
+ // parsed CSP.
+ network.mojom.ContentSecurityPolicy? content_security_policy;
};
diff --git a/chromium/third_party/blink/public/mojom/filesystem/file_system.mojom b/chromium/third_party/blink/public/mojom/filesystem/file_system.mojom
index 800dbd1dac1..cba19ba44a8 100644
--- a/chromium/third_party/blink/public/mojom/filesystem/file_system.mojom
+++ b/chromium/third_party/blink/public/mojom/filesystem/file_system.mojom
@@ -27,8 +27,8 @@ struct FileSystemInfo {
};
// Interface for renderers to cancel running file system operations. A
-// FileSystemCancellableOperationRequest is passed as a parameter for any
-// operation that can be cancelled.
+// pending_receiver<FileSystemCancellableOperation> is passed as a parameter for
+// any operation that can be cancelled.
interface FileSystemCancellableOperation {
// Cancels the associated operation. It may not always be possible to cancel
// an operation, and partial writes are possible. |error_code| indicates if
@@ -38,8 +38,8 @@ interface FileSystemCancellableOperation {
// Operations that need to repeatedly call a particular callback use this
// interface. For example, the Write operation needs to call DidWrite
-// repeatedly, and uses a FileSystemOperationListenerPtr passed from the
-// renderer to call it.
+// repeatedly, and uses a pending_remote<FileSystemOperationListener> passed
+// from the renderer to call it.
// Note: For operations that only need a callback called once, we can directly
// use mojo return value callbacks.
interface FileSystemOperationListener {
@@ -59,7 +59,7 @@ interface FileSystemOperationListener {
};
// Used by the renderer to notify the browser that it has received a snapshot
-// after calling CreateSnapshotFile. The browser sends an interface ptr along
+// after calling CreateSnapshotFile. The browser sends a pending remote along
// with the result of the CreateSnapshotFile call.
interface ReceivedSnapshotListener {
DidReceiveSnapshotFile();
@@ -142,7 +142,8 @@ interface FileSystemManager {
// Reads directory entries of a given directory at |path|. Calls
// ResultsRetrieved on |listener| when results are ready, or ErrorOccurred
// if the operation fails.
- ReadDirectory(url.mojom.Url path, FileSystemOperationListener listener);
+ ReadDirectory(url.mojom.Url path,
+ pending_remote<FileSystemOperationListener> listener);
[Sync]
ReadDirectorySync(url.mojom.Url path) =>
(array<filesystem.mojom.DirectoryEntry> entries,
@@ -151,12 +152,12 @@ interface FileSystemManager {
// Write data (indicated by |blob_uuid|) to the given file at |file_path|,
// at |position|. Calls DidWrite on |listener| to provide progress updates on
// the write, and |ErrorOccurred| if the operation fails. The operation can
- // also be cancelled using the interface ptr associated with |op_request|.
+ // also be cancelled using the remote associated with |op_receiver|.
Write(url.mojom.Url file_path,
string blob_uuid,
int64 position,
- FileSystemCancellableOperation& op_request,
- FileSystemOperationListener listener);
+ pending_receiver<FileSystemCancellableOperation> op_receiver,
+ pending_remote<FileSystemOperationListener> listener);
[Sync]
WriteSync(url.mojom.Url file_path, string blob_uuid, int64 position) =>
(int64 byte_count, mojo_base.mojom.FileError error_code);
@@ -164,10 +165,10 @@ interface FileSystemManager {
// Changes the file length of the file at |file_path| to the |length|
// indicated. Returns |error_code| after completion to indicate if the
// operation succeeded or failed. The operation can also be cancelled using
- // the interface ptr associated with |op_request|.
+ // the remote associated with |op_receiver|.
Truncate(url.mojom.Url file_path,
int64 length,
- FileSystemCancellableOperation& op_request) =>
+ pending_receiver<FileSystemCancellableOperation> op_receiver) =>
(mojo_base.mojom.FileError error_code);
[Sync]
TruncateSync(url.mojom.Url file_path, int64 length) =>
@@ -195,7 +196,7 @@ interface FileSystemManager {
(mojo_base.mojom.FileInfo file_info,
mojo_base.mojom.FilePath platform_path,
mojo_base.mojom.FileError error_code,
- ReceivedSnapshotListener? snapshot_listener);
+ pending_remote<ReceivedSnapshotListener>? snapshot_listener);
// Synchronously gets the platform path for the given |file_path|.
[Sync]
diff --git a/chromium/third_party/blink/public/mojom/frame/document_interface_broker.mojom b/chromium/third_party/blink/public/mojom/frame/document_interface_broker.mojom
index 63d012dfacb..c036ff4f84f 100644
--- a/chromium/third_party/blink/public/mojom/frame/document_interface_broker.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/document_interface_broker.mojom
@@ -4,40 +4,15 @@
module blink.mojom;
-import "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom";
import "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom";
-import "third_party/blink/public/mojom/push_messaging/push_messaging.mojom";
-import "third_party/blink/public/mojom/webauthn/authenticator.mojom";
-import "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom";
// An interface through which the renderer may request document-scoped
// interfaces from the browser.
interface DocumentInterfaceBroker {
- // Binds the blink.mojom.Authenticator pending receiver to its remote
- // implementation in the browser process, to allow directing authenticators to
- // create or use a public key credential.
- GetAuthenticator(pending_receiver<blink.mojom.Authenticator> receiver);
-
- // Binds the blink.mojom.CredentialManager pending receiver to its remote
- // implementation in the browser process, to allow storing, retrieving and
- // handling credentials.
- GetCredentialManager(pending_receiver<blink.mojom.CredentialManager> receiver);
-
// Binds the blink.mojom.FrameHostTestInterface pending receiver to its
// remote implementation in the browser process, to allow using this test
// interface to exercise requesting document-scoped interfaces from the
// RenderFrameHost through the DocumentInterfaceBroker interface.
GetFrameHostTestInterface(
pending_receiver<blink.mojom.FrameHostTestInterface> receiver);
-
- // Binds the blink.mojom.PushMessaging pending receiver to its remote
- // implementation in the browser process, to allow subscribing, unsubscribing
- // and retrieving subscriptions related to push notifications (see Push API).
- GetPushMessaging(pending_receiver<blink.mojom.PushMessaging> receiver);
-
- // Binds the blink.test.mojom.VirtualAuthenticatorManager pending receiver to
- // its remote implementation in the browser process, to manage a virtual
- // environment that allows talking virtual authenticators via the WebAuth API.
- GetVirtualAuthenticatorManager(
- pending_receiver<blink.test.mojom.VirtualAuthenticatorManager> receiver);
};
diff --git a/chromium/third_party/blink/public/mojom/frame/frame.mojom b/chromium/third_party/blink/public/mojom/frame/frame.mojom
index f264c70e61b..7cfb700248c 100644
--- a/chromium/third_party/blink/public/mojom/frame/frame.mojom
+++ b/chromium/third_party/blink/public/mojom/frame/frame.mojom
@@ -5,6 +5,28 @@
module blink.mojom;
import "mojo/public/mojom/base/string16.mojom";
+import "third_party/blink/public/mojom/frame/fullscreen.mojom";
+
+// Implemented in Browser, this interface defines frame-specific methods that will
+// be invoked from the render process (e.g. content::RenderFrameHostImpl).
+//
+// Note that this is different than content/common/frame.mojom in that the
+// methods defined here are called directly in Blink without passing through
+// content. In the future this interface will likely host more methods as the
+// Onion Soup project advances, which can potentially lead to the removal of
+// content/common/frame.mojom if enough code is moved to Blink.
+interface LocalFrameHost {
+
+ // Request to the browser that the frame wishes to enter fullscreen mode.
+ EnterFullscreen(FullscreenOptions options);
+
+ // Request to the browser to exit fullscreen mode.
+ ExitFullscreen();
+
+ // Notifies the browser that the current frame has either become or is no
+ // longer fullscreen.
+ FullscreenStateChanged(bool is_fullscreen);
+};
// Implemented in Blink, this interface defines frame-specific methods that will
// be invoked from the browser process (e.g. content::RenderFrameHostImpl).
@@ -12,12 +34,19 @@ import "mojo/public/mojom/base/string16.mojom";
// Note that this is different than content/common/frame.mojom in that the
// methods defined here are handled directly in Blink without passing through
// content. In the future this interface will likely host more methods as the
-// Onion Soup project advances, which can potentially leading to the removal of
-// content/common/frame.mojom in the future if enough code is moved to Blink.
- interface Frame {
+// Onion Soup project advances, which can potentially lead to the removal of
+// content/common/frame.mojom if enough code is moved to Blink.
+// TODO(dtapuska): Rename to LocalFrame
+interface Frame {
// Retrieves the text surrounding the current selection for the frame up to
// the length specified by |max_length|, along with its start and end offsets.
GetTextSurroundingSelection(uint32 max_length)
=> (mojo_base.mojom.String16 content, uint32 start_offset,
uint32 end_offset);
+
+ // Creates an intervention report in the frame with contents |id| and
+ // |message|, returns once the report has been queued. |id| identifies the
+ // intervention that occurred. |message| is a human-readable string that
+ // can provide additional context to the cause of the intervention.
+ SendInterventionReport(string id, string message);
};
diff --git a/chromium/third_party/blink/public/mojom/frame/fullscreen.mojom b/chromium/third_party/blink/public/mojom/frame/fullscreen.mojom
new file mode 100644
index 00000000000..3a52eab02e8
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/frame/fullscreen.mojom
@@ -0,0 +1,12 @@
+// 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;
+
+struct FullscreenOptions {
+ // Prefer that the bottom navigation bar be shown when in fullscreen
+ // mode on devices with overlay navigation bars.
+ bool prefers_navigation_bar = false;
+};
+
diff --git a/chromium/third_party/blink/public/mojom/hid/hid.mojom b/chromium/third_party/blink/public/mojom/hid/hid.mojom
index fe4d38df62d..7c3f49b8365 100644
--- a/chromium/third_party/blink/public/mojom/hid/hid.mojom
+++ b/chromium/third_party/blink/public/mojom/hid/hid.mojom
@@ -83,8 +83,8 @@ interface HidService {
// Opens a connection to the device with GUID matching |device_guid|. |client|
// will be notified when an input report is received from the device.
- // |connection| contains the opened connection, or nullptr if the device could
- // not be opened.
+ // |connection| contains the opened connection, or a null remote if the
+ // device could not be opened.
Connect(string device_guid, pending_remote<device.mojom.HidConnectionClient> client)
- => (device.mojom.HidConnection? connection);
+ => (pending_remote<device.mojom.HidConnection>? connection);
};
diff --git a/chromium/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/chromium/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
index 60c24c2709c..bc4468199bc 100644
--- a/chromium/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
+++ b/chromium/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -58,6 +58,20 @@ enum IDBKeyType {
Min,
};
+// Durability guarantees during a transaction. This maps to whether or not
+// the writes to disk are explicitly flushed or not.
+enum IDBTransactionDurability {
+ // Unspecified by caller, and so is implementation defined.
+ // May map to either Strict or Relaxed.
+ Default,
+
+ // Always flush to disk after a write.
+ Strict,
+
+ // Do not flush to disk. This is much faster.
+ Relaxed,
+};
+
union IDBKeyData {
array<IDBKey> key_array;
array<uint8> binary;
@@ -176,7 +190,7 @@ struct IDBFileInfo {
};
struct IDBBlobInfo {
- blink.mojom.Blob blob;
+ pending_remote<blink.mojom.Blob> blob;
string uuid;
mojo_base.mojom.String16 mime_type;
int64 size;
@@ -343,7 +357,7 @@ interface IDBDatabase {
int64 transaction_id,
array<int64> object_store_ids,
IDBTransactionMode mode,
- bool relaxed_durability);
+ IDBTransactionDurability durability);
Close();
VersionChangeIgnored();
AddObserver(int64 transaction_id,
diff --git a/chromium/third_party/blink/public/mojom/installedapp/OWNERS b/chromium/third_party/blink/public/mojom/installedapp/OWNERS
index 6137d699f9e..124a0b41de7 100644
--- a/chromium/third_party/blink/public/mojom/installedapp/OWNERS
+++ b/chromium/third_party/blink/public/mojom/installedapp/OWNERS
@@ -1,4 +1,5 @@
-mgiuca@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/installedapp/installed_app_provider.mojom b/chromium/third_party/blink/public/mojom/installedapp/installed_app_provider.mojom
index 2bcfc0d46ac..d3c24e75793 100644
--- a/chromium/third_party/blink/public/mojom/installedapp/installed_app_provider.mojom
+++ b/chromium/third_party/blink/public/mojom/installedapp/installed_app_provider.mojom
@@ -11,6 +11,7 @@ import "third_party/blink/public/mojom/installedapp/related_application.mojom";
interface InstalledAppProvider {
// Filters |related_apps|, keeping only those which are both installed on the
// user's system, and related to the web origin of the requesting page.
+ // Also appends the app version to the filtered apps.
FilterInstalledApps(array<RelatedApplication> related_apps)
=> (array<RelatedApplication> installedApps);
};
diff --git a/chromium/third_party/blink/public/mojom/installedapp/related_application.mojom b/chromium/third_party/blink/public/mojom/installedapp/related_application.mojom
index be3d390356f..b4b02704088 100644
--- a/chromium/third_party/blink/public/mojom/installedapp/related_application.mojom
+++ b/chromium/third_party/blink/public/mojom/installedapp/related_application.mojom
@@ -13,4 +13,5 @@ struct RelatedApplication {
// WebRelatedApplication as well).
string? url;
string? id;
+ string? version;
};
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 1120c12b0e3..bdfb0082b2a 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
@@ -12,7 +12,6 @@ struct LeakDetectionResult {
uint32 number_of_live_layout_objects;
uint32 number_of_live_resources;
uint32 number_of_live_context_lifecycle_state_observers;
- uint32 number_of_live_script_promises;
uint32 number_of_live_frames;
uint32 number_of_live_v8_per_context_data;
uint32 number_of_worker_global_scopes;
diff --git a/chromium/third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom b/chromium/third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom
index 5870e5a7b4b..bedbd7c157a 100644
--- a/chromium/third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom
+++ b/chromium/third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom
@@ -19,6 +19,8 @@ enum InsecureRequestsPolicy {
//
// See comments on blink::FetchClientSettingsObject for details of this struct
// and each member.
+//
+// Also keep this struct consistent with blink::WebFetchClientSettingsObject.
struct FetchClientSettingsObject {
network.mojom.ReferrerPolicy referrer_policy;
url.mojom.Url outgoing_referrer;
diff --git a/chromium/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom b/chromium/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
index 24ac0fcf26b..024a5564095 100644
--- a/chromium/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
+++ b/chromium/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
@@ -25,9 +25,9 @@ struct URLLoaderFactoryBundle {
// A mapping from URL scheme to factory interface.
map<string, network.mojom.URLLoaderFactory> scheme_specific_factories;
- // A mapping from request-initiator-origin to factory interface.
+ // A mapping from isolated world's origin to factory interface.
map<url.mojom.Origin, network.mojom.URLLoaderFactory>
- initiator_specific_factories;
+ isolated_world_factories;
// A special factory that is used for AppCache.
// TODO(https://crbug.com/582750): Drop this when AppCache is deprecated.
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 902b123189e..d5104de0a19 100644
--- a/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom
+++ b/chromium/third_party/blink/public/mojom/manifest/display_mode.mojom
@@ -4,10 +4,18 @@
module blink.mojom;
+// This enum should be synced with
+// chrome/android/java/src/org/chromium/chrome/browser/webapps/WebDisplayMode.java
+// and components/sync/protocol/web_app_specifics.proto
+
enum DisplayMode {
- UNDEFINED, // User for override setting (ie. not set).
- BROWSER,
- MINIMAL_UI,
- STANDALONE,
- FULLSCREEN,
+ kUndefined, // User for override setting (ie. not set).
+ kBrowser,
+ kMinimalUi,
+ kStandalone,
+ kFullscreen,
+
+ /**
+ * 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/media_controls/touchless/OWNERS b/chromium/third_party/blink/public/mojom/media_controls/touchless/OWNERS
deleted file mode 100644
index a15fabe68d4..00000000000
--- a/chromium/third_party/blink/public/mojom/media_controls/touchless/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-mlamouri@chromium.org
-steimel@chromium.org
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom b/chromium/third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom
deleted file mode 100644
index b2442144dfe..00000000000
--- a/chromium/third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom
+++ /dev/null
@@ -1,46 +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.
-
-[JavaPackage="org.chromium.mediacontrols.touchless.mojom"]
-module blink.mojom;
-
-// Represents a Text Track to be shown in the CAPTIONS sub-menu.
-struct TextTrackMetadata {
- int32 track_index;
- string label;
-};
-
-// Represents the current state of the Video showing controls.
-struct VideoState {
- bool is_muted;
- bool is_fullscreen;
-};
-
-// The types of menu items that can be shown.
-enum MenuItem {
- FULLSCREEN,
- CAPTIONS,
- MUTE,
- DOWNLOAD
-};
-
-// Represents the response from the browser for a menu item click.
-struct MenuResponse {
- // |clicked| returns the menu item clicked on, CANCEL if the menu was closed
- // without an item being clicked. |track_index| is only used when |clicked|
- // is CAPTIONS.
- MenuItem clicked;
- int32 track_index;
-};
-
-// Mojo service for the browser-drawn media controls.
-interface MediaControlsMenuHost {
- // Shows the media controls menu with the items specified in |menu_items|.
- // |text_tracks| is only used if the CAPTIONS menu item is present.
- // |response| will be null if the menu was canceled.
- ShowMediaMenu(array<MenuItem> menu_items, VideoState video_state,
- array<TextTrackMetadata>? text_tracks)
- => (MenuResponse? response);
-};
-
diff --git a/chromium/third_party/blink/public/mojom/messaging/cloneable_message.mojom b/chromium/third_party/blink/public/mojom/messaging/cloneable_message.mojom
index 19f1da057fa..2be0f4f7ce8 100644
--- a/chromium/third_party/blink/public/mojom/messaging/cloneable_message.mojom
+++ b/chromium/third_party/blink/public/mojom/messaging/cloneable_message.mojom
@@ -21,6 +21,7 @@ struct CloneableMessage {
uint64 stack_trace_id;
int64 stack_trace_debugger_id_first;
int64 stack_trace_debugger_id_second;
+ bool stack_trace_should_pause;
// If not null, this message is locked to the given agent cluster ID.
// See https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-agent-cluster-formalism
mojo_base.mojom.UnguessableToken? locked_agent_cluster_id;
diff --git a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
index 0ee74d30fe7..9c33fd93056 100644
--- a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
+++ b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom
@@ -13,7 +13,7 @@ import "third_party/blink/public/mojom/permissions/permission_status.mojom";
// can return arbitrary handles.
union NativeFileSystemHandle {
pending_remote<NativeFileSystemFileHandle> file;
- NativeFileSystemDirectoryHandle directory;
+ pending_remote<NativeFileSystemDirectoryHandle> directory;
};
struct NativeFileSystemEntry {
@@ -51,7 +51,8 @@ interface NativeFileSystemDirectoryHandle {
// Returns an error if the operation fails, or a handle to the newly created
// directory if the operation succeeds.
GetDirectory(string basename, bool create) =>
- (NativeFileSystemError result, NativeFileSystemDirectoryHandle? directory);
+ (NativeFileSystemError result,
+ pending_remote<NativeFileSystemDirectoryHandle>? directory);
// Returns all the direct children of this directory.
// TODO(mek): Change this API to stream results in chunks rather than block
@@ -65,5 +66,5 @@ interface NativeFileSystemDirectoryHandle {
// Create a TransferToken for this directory. This token can be used to pass
// a reference to this directory to other methods, for example to copy or move
// the directory, or when transferring the handle over postMessage.
- Transfer(NativeFileSystemTransferToken& token);
+ Transfer(pending_receiver<NativeFileSystemTransferToken> token);
};
diff --git a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom
index badc3b67a01..708b469c5b1 100644
--- a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom
+++ b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom
@@ -31,5 +31,5 @@ interface NativeFileSystemFileHandle {
// Create a TransferToken for this directory. This token can be used to pass
// a reference to this directory to other methods, for example to copy or move
// the file, or when transferring the handle over postMessage.
- Transfer(NativeFileSystemTransferToken& token);
+ Transfer(pending_receiver<NativeFileSystemTransferToken> token);
};
diff --git a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom
index 3bdedf72904..61683ae11f8 100644
--- a/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom
+++ b/chromium/third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom
@@ -33,8 +33,9 @@ struct ChooseFileSystemEntryAcceptsOption {
// tell what operations are being done by which document or worker.
interface NativeFileSystemManager {
// Opens the sandboxed filesystem for the origin of the current document or worker.
- GetSandboxedFileSystem() => (NativeFileSystemError result,
- NativeFileSystemDirectoryHandle? directory);
+ GetSandboxedFileSystem() =>
+ (NativeFileSystemError result,
+ pending_remote<NativeFileSystemDirectoryHandle>? directory);
// Prompts the user to select a file from the native filesystem. Returns an
// error code if something failed, or a list of the selected entries on
@@ -49,6 +50,6 @@ interface NativeFileSystemManager {
array<NativeFileSystemEntry> entries);
// TODO(mek): Add this method when it is needed for transferability of handles.
- // GetHandleFromToken(NativeFileSystemTransferToken token) =>
+ // GetHandleFromToken(pending_remote<NativeFileSystemTransferToken> token) =>
// (NativeFileSystemError result, NativeFileSystemHandle? entry_handle);
};
diff --git a/chromium/third_party/blink/public/mojom/payments/payment_app.mojom b/chromium/third_party/blink/public/mojom/payments/payment_app.mojom
index 4b88899f6b8..238bf57b83d 100644
--- a/chromium/third_party/blink/public/mojom/payments/payment_app.mojom
+++ b/chromium/third_party/blink/public/mojom/payments/payment_app.mojom
@@ -34,6 +34,11 @@ enum PaymentEventResponseType {
PAYMENT_EVENT_BROWSER_ERROR,
PAYMENT_EVENT_TIMEOUT,
PAYMENT_HANDLER_INSECURE_NAVIGATION,
+ PAYER_NAME_EMPTY,
+ PAYER_EMAIL_EMPTY,
+ PAYER_PHONE_EMPTY,
+ SHIPPING_ADDRESS_INVALID,
+ SHIPPING_OPTION_EMPTY,
};
// This struct is provided to hold a payment instrument from render
@@ -50,6 +55,13 @@ struct PaymentInstrument {
array<BasicCardType> supported_types;
};
+enum PaymentDelegation {
+ SHIPPING_ADDRESS,
+ PAYER_NAME,
+ PAYER_PHONE,
+ PAYER_EMAIL,
+};
+
// This interface provides implementation of PaymentInstruments.idl
// and PaymentManager.idl in render side. This interface is implemented
// by payment_manager.cc and runs in browser side.
@@ -72,6 +84,11 @@ interface PaymentManager {
ClearPaymentInstruments()
=> (PaymentHandlerStatus status);
SetUserHint(string user_hint);
+ // A method from PaymentManager.idl which lets payment handlers specify
+ // whether or not they can handle shipping address or contact info (payer's
+ // name/email/phone).
+ EnableDelegations(array<PaymentDelegation> delegations)
+ =>(PaymentHandlerStatus status);
};
// This struct is provided to send payment request data to render side
@@ -93,6 +110,8 @@ struct PaymentRequestEventData {
PaymentCurrencyAmount total;
array<PaymentDetailsModifier> modifiers;
string instrument_key;
+ PaymentOptions? payment_options;
+ array<PaymentShippingOption>? shipping_options;
// Handles events raised by the payment handler, such as "payment method
// changed" event. Null in content_browsertests.
@@ -105,6 +124,11 @@ struct PaymentHandlerResponse {
string method_name;
string stringified_details;
PaymentEventResponseType response_type;
+ string? payer_name;
+ string? payer_email;
+ string? payer_phone;
+ PaymentAddress? shipping_address;
+ string? shipping_option;
};
// This interface is provided to pass a payment handler response from payment
diff --git a/chromium/third_party/blink/public/mojom/payments/payment_handler_host.mojom b/chromium/third_party/blink/public/mojom/payments/payment_handler_host.mojom
index b951796a2f6..665a3c90c56 100644
--- a/chromium/third_party/blink/public/mojom/payments/payment_handler_host.mojom
+++ b/chromium/third_party/blink/public/mojom/payments/payment_handler_host.mojom
@@ -6,6 +6,7 @@
module payments.mojom;
import "components/payments/mojom/payment_request_data.mojom";
+import "third_party/blink/public/mojom/payments/payment_request.mojom";
struct PaymentHandlerMethodData {
// Either a short string (e.g., "basic-string") or URL (e.g.,
@@ -31,9 +32,11 @@ struct PaymentHandlerModifier {
// renderer. The browser sends this to the Payment Handler renderer.
struct PaymentMethodChangeResponse {
PaymentCurrencyAmount? total;
+ array<PaymentShippingOption>? shipping_options;
array<PaymentHandlerModifier>? modifiers;
string error = "";
string? stringified_payment_method_errors;
+ AddressErrors? shipping_address_errors;
};
// The interface for a PaymentRequest object in the browser, so a PaymentHandler
@@ -44,22 +47,35 @@ struct PaymentMethodChangeResponse {
// components/payments/content/payment_request.h
interface PaymentHandlerHost {
// Called by the Payment Handler renderer to let the browser know that the
- // user has selected a different payment instrument.
+ // user has selected a different payment instrument or shipping option, or
+ // when the user has changed the shipping address.
//
- // The browser validates the |method_data| and passes it on to the Merchant
- // renderer via
+ // The browser validates the |method_data|, |shipping address|, or
+ // |shipping option_id| and passes it on to the Merchant renderer via one of
+ // the following methods which are all defined in
+ // third_party/blink/public/mojom/payments/payment_request.mojom:
// PaymentRequestClient.OnPaymentMethodChange(method_name,stringified_data),
- // defined in third_party/blink/public/mojom/payments/payment_request.mojom.
+ // PaymentRequestClient.OnShippingAddressChange(PaymentAddress address),
+ // PaymentRequestClient.OnShippingOptionChange(string shipping_option_id).
//
- // The Merchant renderer than responds to the browser via
- // PaymentRequest.UpdateWith(details) to update the total based on the
- // selected instrument or PaymentRequest.NoUpdatedPaymentDetails() if the
- // total is unchanged. The total can change, for example, based on the
- // billing address of the selected instrument.
+ // The Merchant renderer then responds to the browser via
+ // PaymentRequest.UpdateWith(details) to update the total or other details of
+ // the payment request based on the selected instrument/shipping address/
+ // shipping option or PaymentRequest.NoUpdatedPaymentDetails() if the
+ // total and other details are unchanged. The total can change, for example,
+ // based on the billing address of the selected instrument or the selected
+ // shipping address/option. The list of available shipping options can change
+ // based on the selected shipping address.
//
// The browser validates the |details| from the Merchant renderer and sends
// their subset to the Payment Handler renderer as
- // |PaymentMethodChangeResponse|, so it can show the updated total.
+ // |PaymentMethodChangeResponse|, so it can show the updated details.
+ // Todo(sahel): Rename PaymentMethodChangeResponse to
+ // PaymentRequestDetailsUpdate which is a more generic name. crbug.com/984694
ChangePaymentMethod(PaymentHandlerMethodData method_data) =>
(PaymentMethodChangeResponse response_data);
+ ChangeShippingOption(string shipping_option_id) =>
+ (PaymentMethodChangeResponse response_data);
+ ChangeShippingAddress(PaymentAddress shipping_address) =>
+ (PaymentMethodChangeResponse response_data);
};
diff --git a/chromium/third_party/blink/public/mojom/portal/portal.mojom b/chromium/third_party/blink/public/mojom/portal/portal.mojom
index 3949597e60c..44db21b7ea6 100644
--- a/chromium/third_party/blink/public/mojom/portal/portal.mojom
+++ b/chromium/third_party/blink/public/mojom/portal/portal.mojom
@@ -16,7 +16,7 @@ import "url/mojom/origin.mojom";
// (content::Portal). It is 1:1 with PortalClient (defined below).
interface Portal {
// Navigates the portal to |url|.
- Navigate(url.mojom.Url url, Referrer referrer);
+ Navigate(url.mojom.Url url, Referrer referrer) => ();
// When a portal is activated, it'll replace the current tab with the portal.
Activate(TransferableMessage data) => (bool was_adopted);
diff --git a/chromium/third_party/blink/public/mojom/renderer_preferences.mojom b/chromium/third_party/blink/public/mojom/renderer_preferences.mojom
index 26c3aa13452..6dac97e5d88 100644
--- a/chromium/third_party/blink/public/mojom/renderer_preferences.mojom
+++ b/chromium/third_party/blink/public/mojom/renderer_preferences.mojom
@@ -63,7 +63,6 @@ struct RendererPreferences {
bool use_custom_colors = true;
// Set to false to not send referrers.
- // The default value should be in sync with blink::PrivacyPreferences.
bool enable_referrers = true;
// Set to true to allow third-party sub-content to pop-up HTTP basic auth
@@ -71,7 +70,6 @@ struct RendererPreferences {
bool allow_cross_origin_auth_prompt = false;
// Set to true to indicate that the preference to set DNT to 1 is enabled.
- // The default value should be in sync with blink::PrivacyPreferences.
bool enable_do_not_track = false;
// Whether to allow the use of Encrypted Media Extensions (EME), except for
@@ -89,6 +87,8 @@ struct RendererPreferences {
uint16 webrtc_udp_min_port = 0;
uint16 webrtc_udp_max_port = 0;
+ array<string> webrtc_local_ips_allowed_urls;
+
// The user agent given to WebKit when it requests one and the user agent is
// being overridden for the current navigation.
string user_agent_override;
diff --git a/chromium/third_party/blink/public/mojom/serial/serial.mojom b/chromium/third_party/blink/public/mojom/serial/serial.mojom
index 42f28d4f450..ea610c26002 100644
--- a/chromium/third_party/blink/public/mojom/serial/serial.mojom
+++ b/chromium/third_party/blink/public/mojom/serial/serial.mojom
@@ -36,5 +36,5 @@ interface SerialService {
// Connects an instance of the SerialPort interface attached to the serial
// port identified by |token|.
GetPort(mojo_base.mojom.UnguessableToken token,
- pending_receiver<device.mojom.SerialPort> port_request);
+ pending_receiver<device.mojom.SerialPort> port_receiver);
};
diff --git a/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom b/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom
index d9df450abfa..ad82ce9d4d6 100644
--- a/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom
+++ b/chromium/third_party/blink/public/mojom/service_worker/embedded_worker.mojom
@@ -10,6 +10,8 @@ import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/network/public/mojom/url_loader_factory.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/worker/subresource_loader_updater.mojom";
+import "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom";
import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
import "third_party/blink/public/mojom/renderer_preference_watcher.mojom";
import "third_party/blink/public/mojom/renderer_preferences.mojom";
@@ -20,7 +22,6 @@ import "third_party/blink/public/mojom/service_worker/service_worker_installed_s
import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
-import "third_party/blink/public/mojom/v8_cache_options.mojom";
import "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom";
import "third_party/blink/public/mojom/web_feature/web_feature.mojom";
import "url/mojom/url.mojom";
@@ -44,11 +45,16 @@ struct EmbeddedWorkerStartParams {
// https://w3c.github.io/ServiceWorker/#dfn-type
ScriptType script_type;
+ // The outside fetch client settings object. This is used for top-level script
+ // fetch.
+ FetchClientSettingsObject outside_fetch_client_settings_object;
+
// The string used for "user-agent" HTTP header.
string user_agent;
- // The id to talk with the DevTools agent for the worker.
- int32 worker_devtools_agent_route_id;
+ // The id this service worker uses as render_frame_id in
+ // network::ResourceRequests it makes.
+ int32 service_worker_route_id;
// Unique token identifying this worker for DevTools.
mojo_base.mojom.UnguessableToken devtools_worker_token;
@@ -76,9 +82,6 @@ struct EmbeddedWorkerStartParams {
// True if this service worker has been installed.
bool is_installed;
- // Determines how eagerly V8 creates the code cache.
- V8CacheOptions v8_cache_options;
-
// Used to set up fetch requests.
RendererPreferences renderer_preferences;
@@ -110,11 +113,8 @@ struct EmbeddedWorkerStartParams {
// loader factory can't load.
URLLoaderFactoryBundle subresource_loader_factories;
- // Another interface to talk to the service worker from the browser process
- // to update WorkerFetchContext. See the comment of
- // ServiceWorkerSubresourceLoaderUpdater why there are two interfaces.
- pending_receiver<ServiceWorkerSubresourceLoaderUpdater>
- subresource_loader_updater;
+ // Used for updating subresource loaders after NetworkService crash etc.
+ pending_receiver<SubresourceLoaderUpdater> subresource_loader_updater;
};
// Holds timing information about the start worker sequence for UMA.
diff --git a/chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom b/chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom
index 0e6fe9f3a68..2dd155a959d 100644
--- a/chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom
+++ b/chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom
@@ -12,7 +12,6 @@ import "services/network/public/mojom/url_loader_factory.mojom";
import "third_party/blink/public/mojom/background_fetch/background_fetch.mojom";
import "third_party/blink/public/mojom/devtools/console_message.mojom";
import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom";
-import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
import "third_party/blink/public/mojom/notifications/notification.mojom";
import "third_party/blink/public/mojom/payments/payment_app.mojom";
@@ -168,11 +167,13 @@ interface ServiceWorker {
// ServiceWorker is the first interface available on the
// service worker thread. It establishes the |service_worker_host| connection
// and passes information used to populate
- // ServiceWorkerGlobalScope#registration object. JavaScript execution of the
+ // ServiceWorkerGlobalScope#registration object and
+ // ServiceWorkerGlobalScope#serviceWorker object. JavaScript execution of the
// service worker does not start until this message is received.
InitializeGlobalScope(
pending_associated_remote<ServiceWorkerHost> service_worker_host,
ServiceWorkerRegistrationObjectInfo registration_info,
+ ServiceWorkerObjectInfo service_worker_info,
FetchHandlerExistence fetch_handler_existence);
DispatchInstallEvent()
@@ -202,9 +203,7 @@ interface ServiceWorker {
// https://github.com/WICG/cookie-store/
// The callback is called once the event handler has run and the waitUntil()
// promise has settled.
- DispatchCookieChangeEvent(
- network.mojom.CanonicalCookie cookie,
- network.mojom.CookieChangeCause cause)
+ DispatchCookieChangeEvent(network.mojom.CookieChangeInfo change)
=> (ServiceWorkerEventStatus status);
// The Dispatch*FetchEvent() callback is called once the event finishes,
@@ -268,12 +267,6 @@ interface ServiceWorker {
// Ref: https://github.com/rknoll/content-index
DispatchContentDeleteEvent(string id) => (ServiceWorkerEventStatus status);
- // TODO(crbug.com/869714): Remove this code for long living service workers
- // when Android Messages no longer requires it.
- DispatchExtendableMessageEventWithCustomTimeout(ExtendableMessageEvent event,
- mojo_base.mojom.TimeDelta timeout)
- => (ServiceWorkerEventStatus status);
-
// Pings the service worker to check if it is responsive. If the callback is
// not called within a certain period of time, the browser will terminate the
// worker.
@@ -286,20 +279,3 @@ interface ServiceWorker {
// Adds a message to DevTools console which is associated with this worker.
AddMessageToConsole(ConsoleMessageLevel level, string message);
};
-
-// This is another interface for talking to a running service worker in
-// addition to the ServiceWorker interface defined above. The reason we have two
-// interfaces is that implementations of these two interfaces live in different
-// places (one in blink and the other in content). Ideally these two interfaces
-// should be merged but we separate them to avoid cumbersome type conversions
-// between blink and content.
-interface ServiceWorkerSubresourceLoaderUpdater {
- // Provides the worker an updated |subresource_loader_factories|.
- //
- // Pushes updated set of subresource URL loader factories to the worker
- // (for example, after DevTools network interception has been enabled).
- // Note this does not affect the script loader factory, whose
- // implementation lives in the browser and may be updated there.
- UpdateSubresourceLoaderFactories(
- URLLoaderFactoryBundle subresource_loader_factories);
-};
diff --git a/chromium/third_party/blink/public/mojom/service_worker/service_worker_client.mojom b/chromium/third_party/blink/public/mojom/service_worker/service_worker_client.mojom
index 43c90ba8db1..1e638f10519 100644
--- a/chromium/third_party/blink/public/mojom/service_worker/service_worker_client.mojom
+++ b/chromium/third_party/blink/public/mojom/service_worker/service_worker_client.mojom
@@ -25,14 +25,6 @@ enum ServiceWorkerClientLifecycleState {
kFrozen,
};
-// Indicates the query mode for service worker lifecycle state.
-// https://wicg.github.io/page-lifecycle/#serviceworker-clients-dfn
-enum ServiceWorkerClientLifecycleStateQuery {
- kActive,
- kFrozen,
- kAll,
-};
-
// Indicates the options for the service worker clients matching operation.
// https://w3c.github.io/ServiceWorker/#dictdef-clientqueryoptions.
struct ServiceWorkerClientQueryOptions {
@@ -41,9 +33,6 @@ struct ServiceWorkerClientQueryOptions {
// ClientQueryOptions#type
ServiceWorkerClientType client_type = ServiceWorkerClientType.kWindow;
-
- // ClientQueryOptions#lifecycleState
- ServiceWorkerClientLifecycleStateQuery lifecycle_state = ServiceWorkerClientLifecycleStateQuery.kActive;
};
// Holds the information related to a service worker client.
diff --git a/chromium/third_party/blink/public/mojom/service_worker/service_worker_object.mojom b/chromium/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
index b03ee48ecb0..588bcf1fa15 100644
--- a/chromium/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
+++ b/chromium/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
@@ -18,7 +18,7 @@ struct ServiceWorkerObjectInfo {
int64 version_id = kInvalidServiceWorkerVersionId;
// ServiceWorker#state
- ServiceWorkerState state = ServiceWorkerState.kUnknown;
+ ServiceWorkerState state = ServiceWorkerState.kParsed;
// ServiceWorker#scriptURL
url.mojom.Url url;
diff --git a/chromium/third_party/blink/public/mojom/service_worker/service_worker_state.mojom b/chromium/third_party/blink/public/mojom/service_worker/service_worker_state.mojom
index be9f358d36b..5dd8c095d7a 100644
--- a/chromium/third_party/blink/public/mojom/service_worker/service_worker_state.mojom
+++ b/chromium/third_party/blink/public/mojom/service_worker/service_worker_state.mojom
@@ -7,7 +7,7 @@ module blink.mojom;
// Represents ServiceWorkerState from the Service Workers spec:
// https://w3c.github.io/ServiceWorker/#enumdef-serviceworkerstate
enum ServiceWorkerState {
- kUnknown,
+ kParsed,
kInstalling,
kInstalled,
kActivating,
diff --git a/chromium/third_party/blink/public/mojom/speech/speech_recognizer.mojom b/chromium/third_party/blink/public/mojom/speech/speech_recognizer.mojom
index 0144c94245a..e9fdbe61d1b 100644
--- a/chromium/third_party/blink/public/mojom/speech/speech_recognizer.mojom
+++ b/chromium/third_party/blink/public/mojom/speech/speech_recognizer.mojom
@@ -14,11 +14,11 @@ import "url/mojom/origin.mojom";
struct StartSpeechRecognitionRequestParams {
// Used to create a connection with a SpeechRecognitionSession implementation
// that will be created when the session is created.
- SpeechRecognitionSession& session_request;
+ pending_receiver<SpeechRecognitionSession> session_receiver;
// Used by the browser to communicate with a SpeechRecognitionSessionClient
// implementation created for the new session.
- SpeechRecognitionSessionClient client;
+ pending_remote<SpeechRecognitionSessionClient> client;
// Language to use for speech recognition.
string language;
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 04ffb17ab0a..2d75ffa0d4f 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
@@ -689,6 +689,7 @@ enum CSSSampleId {
kOverscrollBehaviorInline = 644,
kOverscrollBehaviorBlock = 645,
kContentSize = 646,
+ kFontOpticalSizing = 647
// 1. Add new features above this line (don't change the assigned numbers of
// the existing items).
// 2. Run the update_use_counter_css.py script in
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 b73e8518c2b..189db1f2551 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
@@ -2309,8 +2309,8 @@ enum WebFeature {
kV8CallSiteAPIGetThisSloppyCall = 2925,
kBuiltInModuleToast = 2926,
kLargestContentfulPaintExplicitlyRequested = 2927,
- kPageLifecycleTransitionsOptIn = 2928,
- kPageLifecycleTransitionsOptOut = 2929,
+ kPageFreezeOptIn = 2928,
+ kPageFreezeOptOut = 2929,
kPeriodicBackgroundSync = 2930,
kPeriodicBackgroundSyncRegister = 2931,
kLazyLoadFrameLoadingAttributeEager = 2932,
@@ -2360,7 +2360,6 @@ enum WebFeature {
kAutoplayDynamicDelegation = 2977,
kToggleEventHandlerDuringParsing = 2978,
kFragmentDoubleHash = 2979,
- kV8RegExpMatchAllWithNonGlobalRegExp = 2980,
kOBSOLETE_CSSValueOverflowXOverlay = 2981,
kOBSOLETE_CSSValueOverflowYOverlay = 2982,
kContentIndexAdd = 2983,
@@ -2408,13 +2407,44 @@ enum WebFeature {
kDeprecatedFileSystemRead = 3025,
kDeprecatedFileSystemWrite = 3026,
kPointerLockUnadjustedMovement = 3027,
- kQuotaRead = 3029,
- kTextFragmentAnchorTapToDismiss = 3035,
+ // The above items are available in M78 branch.
+
+ kCreateObjectBlob = 3028,
+ kQuotaRead = 3029, // available in M78 branch.
+ kDelegateFocus = 3030,
+ kDelegateFocusNotFirstInFlatTree = 3031,
+ kThirdPartySharedWorker = 3032,
+ kThirdPartyBroadcastChannel = 3033,
+ kMediaSourceGroupEndTimestampDecreaseWithinMediaSegment = 3034,
+ kTextFragmentAnchorTapToDismiss = 3035, // available in M78 branch.
+ kXRIsSessionSupported = 3036,
+ kScrollbarUseScrollbarButtonReversedDirection = 3037,
+ kCSSSelectorPseudoScrollbarButtonReversedDirection = 3038,
kFragmentHasTildeAmpersandTilde = 3039,
kFragmentHasColonTildeColon = 3040,
kFragmentHasTildeAtTilde = 3041,
kFragmentHasAmpersandDelimiterQuestion = 3042,
kInvalidFragmentDirective = 3043,
+ kContactsManagerGetProperties = 3044,
+ kEvaluateScriptMovedBetweenElementDocuments = 3045,
+ kPluginElementLoadedDocument = 3046,
+ kPluginElementLoadedImage = 3047,
+ kPluginElementLoadedExternal = 3048,
+ kRenderSubtreeAttribute = 3049,
+ kARIAAnnotationRoles = 3050,
+ kIntersectionObserverV2 = 3051,
+ kHeavyAdIntervention = 3052,
+ kUserTimingL3 = 3053,
+ kGetGamepadsFromCrossOriginSubframe = 3054,
+ kGetGamepadsFromInsecureContext = 3055,
+ kOriginCleanImageBitmapSerialization = 3056,
+ kNonOriginCleanImageBitmapSerialization = 3057,
+ kOriginCleanImageBitmapTransfer = 3058,
+ kNonOriginCleanImageBitmapTransfer = 3059,
+ kCompressionStreamConstructor = 3060,
+ kDecompressionStreamConstructor = 3061,
+ kV8RTCRtpReceiver_PlayoutDelayHint_AttributeGetter = 3062,
+ kV8RTCRtpReceiver_PlayoutDelayHint_AttributeSetter = 3063,
// 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/worker/dedicated_worker_host_factory.mojom b/chromium/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
index be2a63cc110..379a9c42da9 100644
--- a/chromium/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
+++ b/chromium/third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom
@@ -9,6 +9,7 @@ import "services/service_manager/public/mojom/interface_provider.mojom";
import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
import "third_party/blink/public/mojom/browser_interface_broker.mojom";
import "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom";
+import "third_party/blink/public/mojom/worker/subresource_loader_updater.mojom";
import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
import "third_party/blink/public/mojom/worker/dedicated_worker_host.mojom";
import "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom";
@@ -56,6 +57,9 @@ interface DedicatedWorkerHostFactoryClient {
// chrome-extension:// URLs.
URLLoaderFactoryBundle subresource_loader_factories,
+ // Used for updating subresource loaders after NetworkService crash.
+ pending_receiver<SubresourceLoaderUpdater> subresource_loader_updater,
+
// Used to make fetches from the worker go through the controller service
// worker. This is null when there're no controller service worker.
ControllerServiceWorkerInfo? controller_info);
diff --git a/chromium/third_party/blink/public/mojom/worker/subresource_loader_updater.mojom b/chromium/third_party/blink/public/mojom/worker/subresource_loader_updater.mojom
new file mode 100644
index 00000000000..2bd8738b971
--- /dev/null
+++ b/chromium/third_party/blink/public/mojom/worker/subresource_loader_updater.mojom
@@ -0,0 +1,16 @@
+// 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 "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
+
+// An interface for pushing updated subresource loader factories to workers in
+// renderers, for example, after Network Service crashes or DevTools network
+// interception is enabled/disabled.
+interface SubresourceLoaderUpdater {
+ // Pushes updated set of subresource URL loader factories to a renderer.
+ UpdateSubresourceLoaderFactories(
+ URLLoaderFactoryBundle subresource_loader_factories);
+};
diff --git a/chromium/third_party/blink/public/platform/DEPS b/chromium/third_party/blink/public/platform/DEPS
index 6ed19385cef..72d083d9844 100644
--- a/chromium/third_party/blink/public/platform/DEPS
+++ b/chromium/third_party/blink/public/platform/DEPS
@@ -43,6 +43,7 @@ include_rules = [
"+services/network/public/mojom/referrer_policy.mojom-shared.h",
"+services/service_manager/public/mojom",
+ "+third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h",
"+third_party/blink/public/platform",
"-third_party/blink/public/web",
"-third_party/blink/renderer/bindings",
diff --git a/chromium/third_party/blink/public/platform/TaskTypes.md b/chromium/third_party/blink/public/platform/TaskTypes.md
index ce7ef0ef4ef..76c519a2a93 100644
--- a/chromium/third_party/blink/public/platform/TaskTypes.md
+++ b/chromium/third_party/blink/public/platform/TaskTypes.md
@@ -1,68 +1,58 @@
-# Task Queues
+# Frame Associated Task Types
-Blink uses a series of task queues.
+Blink uses a series of task types defined in
+[task_type.h](https://cs.chromium.org/chromium/src/third_party/blink/public/platform/task_type.h).
+For each task type that can be frame-attributed, the table below indicates
+whether the task queue associated with this task type can be paused, throttled,
+frozen or deferred. All specified (in W3C, HTML, DOM, etc) task types are
+pausable. Some internal task queues are not.
-All specified (in W3C, HTML, DOM, etc) task queues are pausable. Some internal task queues are not.
-
-| Task Queue | Pausable | Throttlable | Frozen | Deferred |
-| -------------------- | -------- | ----------- | ------------ | -------- |
-| DOM Manipulation | Yes | Yes | Android Only | Yes |
-| User Interaction | Yes | Yes | Android Only | No |
-| Networking | Yes | No | Yes | Yes |
-| Networking (URL Ldr) | Yes | No | Yes | Yes |
-| Networking (Ctrl) | Yes | No | Yes | Yes |
-| History Traversal | Yes | Yes | Android Only | Yes |
-| Embed | Yes | Yes | Android Only | Yes |
-| Media Element | Yes | Yes | Android Only | No |
-| Canvas Block Serial. | Yes | Yes | Android Only | Yes |
-| Microtask | Yes | Yes | Android Only | Yes |
-| Javascript Timer | Yes | Yes | Yes | Yes |
-| Remote Event | Yes | Yes | Android Only | Yes |
-| Web Socket | Yes | Yes | Android Only | Yes |
-| Posted Message | Yes | Yes | Android Only | No |
-| Unshipped Port Msg. | Yes | Yes | Android Only | Yes |
-| File Reading | Yes | Yes | Android Only | Yes |
-| Database Access | Yes | Yes | Android Only | No |
-| Presentation | Yes | Yes | Android Only | Yes |
-| Sensor | Yes | Yes | Android Only | Yes |
-| Performance Timeline | Yes | Yes | Android Only | Yes |
-| WebGL | Yes | Yes | Android Only | Yes |
-| Idle Task | Yes | Yes | Android Only | Yes |
-| Misc Platform API | Yes | Yes | Android Only | Yes |
-| Worker Animation | Yes | Yes | Android Only | No |
-| Web Schdlr User Int. | Yes | Yes | Yes | No |
-| Web Schdlr Best Eff. | Yes | Yes | Yes | Yes |
-| Font Loading | Yes | Yes | Android Only | Yes |
-| Application Lifecycle| Yes | Yes | Android Only | Yes |
-| Background Fetch | Yes | Yes | Android Only | Yes |
-| Permission | Yes | Yes | Android Only | Yes |
-| Service Worklet CMsg | Yes | Yes | Android Only | No |
-| Internal Default | No | No | No | No |
-| Internal Loading | No | No | No | No |
-| Internal Test | No | No | No | No |
-| Internal Web Crypto | Yes | Yes | Android Only | No |
-| Internal Media | Yes | Yes | Android Only | No |
-| Internal Media Rt. | Yes | Yes | Android Only | No |
-| Internal IPC | No | No | No | No |
-| Internal User Inter. | Yes | Yes | Android Only | No |
-| Internal Inspector | No | No | No | No |
-| Internal Worker | No | No | No | No |
-| Internal Translation | No | No | No | No |
-| Internal Intersec Obs| Yes | Yes | Android Only | No |
-| Internal Content Cpt | Yes | Yes | Yes | Yes |
-| Internal Nav | No | No | No | No |
-| Main Thread V8 | No | No | No | No |
-| Main Thread Composit.| No | No | No | No |
-| Main Thread Default | No | No | No | No |
-| Main Thread Input | No | No | No | No |
-| Main Thread Idle | No | No | No | No |
-| Main Thread Control | No | No | No | No |
-| Main Thread Cleanup | No | No | No | No |
-| Main Thread Mem Purge| No | No | No | No |
-| Compositor Default | No | No | No | No |
-| Compositor Input | No | No | No | No |
-| Worker Default | No | No | No | No |
-| Worker V8 | No | No | No | No |
-| Worker Compositor | No | No | No | No |
+| Queue Type | Throttlable | Deferrable | Freezable | Pausable | Virtual time |
+|------------------------------|-------------|------------|-----------|----------|--------------|
+| DOMManipulation | No | Yes | Yes | Yes | Yes |
+| UserInteraction | No | No | Yes | Yes | Yes |
+| Networking | No | Yes | Yes | Yes | No |
+| NetworkingWithURLLoaderAnnot | No | Yes | Yes | Yes | No |
+| NetworkingControl | No | Yes | Yes | Yes | No |
+| HistoryTraversal | No | Yes | Yes | Yes | Yes |
+| Embed | No | Yes | Yes | Yes | Yes |
+| MediaElementEvent | No | No | Yes | Yes | Yes |
+| CanvasBlobSerialization | No | Yes | Yes | Yes | Yes |
+| Microtask | No | Yes | Yes | Yes | Yes |
+| JavascriptTimer | Yes | Yes | Yes | Yes | Yes |
+| RemoteEvent | No | Yes | Yes | Yes | Yes |
+| WebSocket | No | Yes | Yes | Yes | Yes |
+| PostedMessage | No | No | Yes | Yes | Yes |
+| UnshippedPortMessage | No | Yes | Yes | Yes | Yes |
+| FileReading | No | Yes | Yes | Yes | Yes |
+| DatabaseAccess | No | No | Yes | Yes | Yes |
+| Presentation | No | Yes | Yes | Yes | Yes |
+| Sensor | No | Yes | Yes | Yes | Yes |
+| PerformanceTimeline | No | Yes | Yes | Yes | Yes |
+| WebGL | No | Yes | Yes | Yes | Yes |
+| IdleTask | No | Yes | Yes | Yes | Yes |
+| MiscPlatformAPI | No | Yes | Yes | Yes | Yes |
+| WorkerAnimation | No | No | Yes | Yes | Yes |
+| FontLoading | No | Yes | Yes | Yes | Yes |
+| ApplicationLifeCycle | No | Yes | Yes | Yes | Yes |
+| BackgroundFetch | No | Yes | Yes | Yes | Yes |
+| Permission | No | Yes | Yes | Yes | Yes |
+| ServiceWorkerClientMessage | No | No | Yes | Yes | Yes |
+| WebLocks | No | No | No | No | Yes |
+| InternalDefault | No | Yes | Yes | Yes | Yes |
+| InternalLoading | No | Yes | Yes | Yes | No |
+| InternalTest | No | No | No | No | Yes |
+| InternalWebCrypto | No | No | Yes | Yes | Yes |
+| InternalMedia | No | No | Yes | Yes | Yes |
+| InternalMediaRealTime | No | No | Yes | Yes | Yes |
+| InternalIPC | No | No | No | No | Yes |
+| InternalUserInteraction | No | No | Yes | Yes | Yes |
+| InternalInspector | No | No | No | No | No |
+| InternalTranslation | Yes | Yes | Yes | Yes | Yes |
+| InternalIntersectionObserver | No | No | Yes | Yes | Yes |
+| InternalContentCapture | Yes | Yes | Yes | Yes | Yes |
+| InternalNavigationAssociated | No | No | No | No | No |
+| InternalFreezableIPC | No | No | Yes | No | No |
+| InternalContinueScriptLoadin | No | No | Yes | 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/interface_provider.h b/chromium/third_party/blink/public/platform/interface_provider.h
index e3f5025a640..ff54cc6542c 100644
--- a/chromium/third_party/blink/public/platform/interface_provider.h
+++ b/chromium/third_party/blink/public/platform/interface_provider.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INTERFACE_PROVIDER_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_INTERFACE_PROVIDER_H_
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -21,11 +20,6 @@ class BLINK_PLATFORM_EXPORT InterfaceProvider {
mojo::ScopedMessagePipeHandle) = 0;
template <typename Interface>
- void GetInterface(mojo::InterfaceRequest<Interface> ptr) {
- GetInterface(Interface::Name_, ptr.PassMessagePipe());
- }
-
- template <typename Interface>
void GetInterface(mojo::PendingReceiver<Interface> receiver) {
GetInterface(Interface::Name_, receiver.PassPipe());
}
diff --git a/chromium/third_party/blink/public/platform/interface_registry.h b/chromium/third_party/blink/public/platform/interface_registry.h
index 3d8777d6554..a31c6078e44 100644
--- a/chromium/third_party/blink/public/platform/interface_registry.h
+++ b/chromium/third_party/blink/public/platform/interface_registry.h
@@ -14,8 +14,6 @@
#include "third_party/blink/public/platform/web_common.h"
#if INSIDE_BLINK
-#include "mojo/public/cpp/bindings/associated_interface_request.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" // nogncheck
@@ -49,17 +47,6 @@ class BLINK_PLATFORM_EXPORT InterfaceRegistry {
#if INSIDE_BLINK
template <typename Interface>
void AddInterface(
- base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>)>
- factory) {
- AddInterface(
- Interface::Name_,
- WTF::BindRepeating(&InterfaceRegistry::ForwardToInterfaceFactory<
- mojo::InterfaceRequest<Interface>>,
- std::move(factory)));
- }
-
- template <typename Interface>
- void AddInterface(
base::RepeatingCallback<void(mojo::PendingReceiver<Interface>)> factory) {
AddInterface(
Interface::Name_,
@@ -70,18 +57,6 @@ class BLINK_PLATFORM_EXPORT InterfaceRegistry {
template <typename Interface>
void AddInterface(WTF::CrossThreadRepeatingFunction<
- void(mojo::InterfaceRequest<Interface>)> factory,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- AddInterface(Interface::Name_,
- ConvertToBaseCallback(CrossThreadBind(
- &InterfaceRegistry::ForwardToCrossThreadInterfaceFactory<
- mojo::InterfaceRequest<Interface>>,
- std::move(factory))),
- std::move(task_runner));
- }
-
- template <typename Interface>
- void AddInterface(WTF::CrossThreadRepeatingFunction<
void(mojo::PendingReceiver<Interface>)> factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
AddInterface(Interface::Name_,
@@ -94,18 +69,6 @@ class BLINK_PLATFORM_EXPORT InterfaceRegistry {
template <typename Interface>
void AddAssociatedInterface(
- base::RepeatingCallback<void(mojo::AssociatedInterfaceRequest<Interface>)>
- factory) {
- AddAssociatedInterface(
- Interface::Name_,
- WTF::BindRepeating(
- &InterfaceRegistry::ForwardToAssociatedInterfaceFactory<
- mojo::AssociatedInterfaceRequest<Interface>>,
- std::move(factory)));
- }
-
- template <typename Interface>
- void AddAssociatedInterface(
base::RepeatingCallback<void(mojo::PendingAssociatedReceiver<Interface>)>
factory) {
AddAssociatedInterface(
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_decoding_info.h b/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_decoding_info.h
deleted file mode 100644
index fb8a97f6212..00000000000
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_decoding_info.h
+++ /dev/null
@@ -1,22 +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_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_DECODING_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_DECODING_INFO_H_
-
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h"
-#include "third_party/blink/public/platform/web_content_decryption_module_access.h"
-
-namespace blink {
-
-// Represents a MediaCapabilitiesDecodingInfo dictionary to be used outside of
-// Blink. This is set by consumers and sent back to Blink.
-struct WebMediaCapabilitiesDecodingInfo : WebMediaCapabilitiesInfo {
- std::unique_ptr<WebContentDecryptionModuleAccess>
- content_decryption_module_access;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_DECODING_INFO_H_
diff --git a/chromium/third_party/blink/public/platform/modules/notifications/OWNERS b/chromium/third_party/blink/public/platform/modules/notifications/OWNERS
deleted file mode 100644
index 2fd0e4bec55..00000000000
--- a/chromium/third_party/blink/public/platform/modules/notifications/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-peter@chromium.org
-
-# TEAM: platform-capabilities@chromium.org
-# COMPONENT: UI>Notifications
diff --git a/chromium/third_party/blink/public/platform/modules/notifications/web_notification_constants.h b/chromium/third_party/blink/public/platform/modules/notifications/web_notification_constants.h
deleted file mode 100644
index 7c7c13768f7..00000000000
--- a/chromium/third_party/blink/public/platform/modules/notifications/web_notification_constants.h
+++ /dev/null
@@ -1,38 +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_PUBLIC_PLATFORM_MODULES_NOTIFICATIONS_WEB_NOTIFICATION_CONSTANTS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_NOTIFICATIONS_WEB_NOTIFICATION_CONSTANTS_H_
-
-namespace blink {
-
-// TODO(johnme): The maximum number of actions is platform-specific and should
-// be indicated by the embedder.
-
-// Maximum number of actions on a Platform Notification.
-static constexpr size_t kWebNotificationMaxActions = 2;
-
-// TODO(mvanouwerkerk): Update the notification resource loader to get the
-// appropriate image sizes from the embedder.
-
-// The maximum reasonable image size, scaled from dip units to pixels using the
-// largest supported scaling factor. TODO(johnme): Check sizes are correct.
-static constexpr int kWebNotificationMaxImageWidthPx = 1800; // 450 dip * 4
-static constexpr int kWebNotificationMaxImageHeightPx = 900; // 225 dip * 4
-
-// The maximum reasonable notification icon size, scaled from dip units to
-// pixels using the largest supported scaling factor.
-static constexpr int kWebNotificationMaxIconSizePx = 320; // 80 dip * 4
-
-// The maximum reasonable badge size, scaled from dip units to pixels using the
-// largest supported scaling factor.
-static constexpr int kWebNotificationMaxBadgeSizePx = 96; // 24 dip * 4
-
-// The maximum reasonable action icon size, scaled from dip units to
-// pixels using the largest supported scaling factor.
-static constexpr int kWebNotificationMaxActionIconSizePx = 128; // 32 dip * 4
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_NOTIFICATIONS_WEB_NOTIFICATION_CONSTANTS_H_
diff --git a/chromium/third_party/blink/public/platform/modules/peerconnection/DEPS b/chromium/third_party/blink/public/platform/modules/peerconnection/DEPS
index 68362d4bf3f..b9fba4789b7 100644
--- a/chromium/third_party/blink/public/platform/modules/peerconnection/DEPS
+++ b/chromium/third_party/blink/public/platform/modules/peerconnection/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+base/timer/timer.h",
"+media/base/audio_parameters.h",
"+media/base/audio_push_fifo.h",
"+media/base/video_codecs.h",
diff --git a/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h b/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h
deleted file mode 100644
index de64ea4d9fd..00000000000
--- a/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h
+++ /dev/null
@@ -1,29 +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_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace webrtc {
-class VideoDecoderFactory;
-}
-
-namespace blink {
-
-// TODO(crbug.com/787254): Remove this API when its clients are Onion souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoderFactory>
-CreateRTCVideoDecoderFactory(
- media::GpuVideoAcceleratorFactories* gpu_factories);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_DECODER_FACTORY_UTIL_H_
diff --git a/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h b/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h
deleted file mode 100644
index 45bafd3f6bd..00000000000
--- a/chromium/third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h
+++ /dev/null
@@ -1,29 +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_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace media {
-class GpuVideoAcceleratorFactories;
-}
-
-namespace webrtc {
-class VideoEncoderFactory;
-}
-
-namespace blink {
-
-// TODO(crbug.com/787254): Remove this API when its clients are Onion souped.
-BLINK_PLATFORM_EXPORT std::unique_ptr<webrtc::VideoEncoderFactory>
-CreateRTCVideoEncoderFactory(
- media::GpuVideoAcceleratorFactories* gpu_factories);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_PEERCONNECTION_RTC_VIDEO_ENCODER_FACTORY_UTIL_H_
diff --git a/chromium/third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h b/chromium/third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h
index b0ea2ffc142..934e1cd4d12 100644
--- a/chromium/third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h
+++ b/chromium/third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h
@@ -78,6 +78,7 @@ class BLINK_PLATFORM_EXPORT WebRtcVideoTrackSource
gfx::Rect accumulated_update_rect_;
base::Optional<int> previous_capture_counter_;
gfx::Rect cropping_rect_of_previous_delivered_frame_;
+ gfx::Size natural_size_of_previous_delivered_frame_;
absl::optional<FrameAdaptationParams>
custom_frame_adaptation_params_for_testing_;
diff --git a/chromium/third_party/blink/public/platform/platform.h b/chromium/third_party/blink/public/platform/platform.h
index 68051e35252..422cddc5b05 100644
--- a/chromium/third_party/blink/public/platform/platform.h
+++ b/chromium/third_party/blink/public/platform/platform.h
@@ -59,7 +59,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_gesture_device.h"
-#include "third_party/blink/public/platform/web_localized_string.h"
#include "third_party/blink/public/platform/web_rtc_api_name.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -84,13 +83,10 @@ class GpuMemoryBufferManager;
namespace media {
struct AudioSinkParameters;
struct AudioSourceParameters;
+class MediaPermission;
class GpuVideoAcceleratorFactories;
}
-namespace rtc {
-class Thread;
-}
-
namespace service_manager {
class InterfaceProvider;
}
@@ -106,7 +102,6 @@ class ContextProvider;
}
namespace webrtc {
-struct RtpCapabilities;
class AsyncResolverFactory;
}
@@ -125,14 +120,11 @@ class WebLocalFrame;
class WebMediaCapabilitiesClient;
class WebPrescientNetworking;
class WebPublicSuffixList;
-class WebRtcAudioDeviceImpl;
-class WebRTCCertificateGenerator;
class WebRTCPeerConnectionHandler;
class WebRTCPeerConnectionHandlerClient;
class WebSandboxSupport;
class WebSecurityOrigin;
class WebThemeEngine;
-class WebTransmissionEncodingInfoHandler;
class WebURLLoaderMockFactory;
class WebURLResponse;
class WebURLResponse;
@@ -577,11 +569,6 @@ class BLINK_PLATFORM_EXPORT Platform {
CreateRTCPeerConnectionHandler(WebRTCPeerConnectionHandlerClient*,
scoped_refptr<base::SingleThreadTaskRunner>);
- // May return null if WebRTC functionality is not available or out of
- // resources.
- virtual std::unique_ptr<WebRTCCertificateGenerator>
- CreateRTCCertificateGenerator();
-
// Returns the SingleThreadTaskRunner suitable for running WebRTC networking.
// An rtc::Thread will have already been created.
// May return null if WebRTC functionality is not implemented.
@@ -589,16 +576,6 @@ class BLINK_PLATFORM_EXPORT Platform {
return nullptr;
}
- // Returns the rtc::Thread instance associated with the WebRTC worker thread.
- // TODO(bugs.webrtc.org/9419): Remove once WebRTC can be built as a component.
- // May return null if WebRTC functionality is not implemented.
- virtual rtc::Thread* GetWebRtcWorkerThreadRtcThread() { return nullptr; }
-
- virtual scoped_refptr<base::SingleThreadTaskRunner>
- GetWebRtcSignalingTaskRunner() {
- return nullptr;
- }
-
// May return null if WebRTC functionality is not implemented.
virtual std::unique_ptr<cricket::PortAllocator> CreateWebRtcPortAllocator(
WebLocalFrame* frame);
@@ -607,15 +584,6 @@ class BLINK_PLATFORM_EXPORT Platform {
virtual std::unique_ptr<webrtc::AsyncResolverFactory>
CreateWebRtcAsyncResolverFactory();
- // Returns the most optimistic view of the capabilities of the system for
- // sending or receiving media of the given kind ("audio" or "video").
- virtual std::unique_ptr<webrtc::RtpCapabilities> GetRtpSenderCapabilities(
- const WebString& kind);
- virtual std::unique_ptr<webrtc::RtpCapabilities> GetRtpReceiverCapabilities(
- const WebString& kind);
-
- virtual void UpdateWebRTCAPICount(WebRTCAPIName api_name) {}
-
// Checks if the default minimum starting volume value for the AGC is
// overridden on the command line.
virtual base::Optional<double> GetWebRtcMaxCaptureFrameRate() {
@@ -633,14 +601,41 @@ class BLINK_PLATFORM_EXPORT Platform {
return media::AudioLatency::LATENCY_PLAYBACK;
}
- virtual blink::WebRtcAudioDeviceImpl* GetWebRtcAudioDevice() {
+ virtual base::Optional<std::string> GetWebRTCAudioProcessingConfiguration() {
+ return base::nullopt;
+ }
+
+ virtual bool ShouldEnforceWebRTCRoutingPreferences() { return true; }
+
+ virtual media::MediaPermission* GetWebRTCMediaPermission(
+ WebLocalFrame* web_frame) {
return nullptr;
}
- virtual base::Optional<std::string> GetWebRTCAudioProcessingConfiguration() {
+ virtual bool UsesFakeCodecForPeerConnection() { return false; }
+
+ virtual bool IsWebRtcEncryptionEnabled() { return true; }
+
+ virtual bool IsWebRtcStunOriginEnabled() { return false; }
+
+ virtual bool IsWebRtcSrtpAesGcmEnabled() { return false; }
+
+ virtual bool IsWebRtcSrtpEncryptedHeadersEnabled() { return false; }
+
+ virtual base::Optional<std::string> WebRtcStunProbeTrialParameter() {
return base::nullopt;
}
+ // TODO(qingsi): Consolidate the legacy |ip_handling_policy| with
+ // |allow_mdns_obfuscation| following the latest spec on IP handling modes
+ // with mDNS introduced
+ // (https://tools.ietf.org/html/draft-ietf-rtcweb-ip-handling-12);
+ virtual void GetWebRTCRendererPreferences(WebLocalFrame* web_frame,
+ WebString* ip_handling_policy,
+ uint16_t* udp_min_port,
+ uint16_t* udp_max_port,
+ bool* allow_mdns_obfuscation) {}
+
virtual base::Optional<int> GetAgcStartupMinimumVolume() {
return base::nullopt;
}
@@ -653,6 +648,12 @@ class BLINK_PLATFORM_EXPORT Platform {
return true;
}
+ virtual bool IsWebRtcHWEncodingEnabled() { return true; }
+
+ virtual bool IsWebRtcHWDecodingEnabled() { return true; }
+
+ virtual bool AllowsLoopbackInPeerConnection() { return false; }
+
// VideoCapture -------------------------------------------------------
virtual WebVideoCaptureImplManager* GetVideoCaptureImplManager() {
@@ -709,11 +710,6 @@ class BLINK_PLATFORM_EXPORT Platform {
return nullptr;
}
- virtual WebTransmissionEncodingInfoHandler*
- TransmissionEncodingInfoHandler() {
- return nullptr;
- }
-
// GpuVideoAcceleratorFactories --------------------------------------
virtual media::GpuVideoAcceleratorFactories* GetGpuFactories() {
diff --git a/chromium/third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h b/chromium/third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h
index 75f3ae16b5d..81edd69946a 100644
--- a/chromium/third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h
+++ b/chromium/third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h
@@ -42,9 +42,8 @@ class BLINK_PLATFORM_EXPORT WebScopedVirtualTimePauser {
WebScopedVirtualTimePauser();
~WebScopedVirtualTimePauser();
- WebScopedVirtualTimePauser(WebScopedVirtualTimePauser&& other) noexcept;
- WebScopedVirtualTimePauser& operator=(
- WebScopedVirtualTimePauser&& other) noexcept;
+ WebScopedVirtualTimePauser(WebScopedVirtualTimePauser&& other);
+ WebScopedVirtualTimePauser& operator=(WebScopedVirtualTimePauser&& other);
WebScopedVirtualTimePauser(const WebScopedVirtualTimePauser&) = delete;
WebScopedVirtualTimePauser& operator=(const WebScopedVirtualTimePauser&) =
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 2ad31899e98..041bf8d9da8 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
@@ -156,6 +156,16 @@ class BLINK_PLATFORM_EXPORT WebThreadScheduler {
// a fling). Called by the compositor (impl) thread.
virtual void DidAnimateForInputOnCompositorThread();
+ // Tells the scheduler that the compositor thread queued up a BeginMainFrame
+ // task to run on the main thread.
+ virtual void DidScheduleBeginMainFrame();
+
+ // Tells the scheduler that the main thread processed a BeginMainFrame task
+ // from its queue. Note that DidRunBeginMainFrame will be called
+ // unconditionally, even if BeginMainFrame early-returns without committing
+ // a frame.
+ virtual void DidRunBeginMainFrame();
+
// Tells the scheduler about the change of renderer visibility status (e.g.
// "all widgets are hidden" condition). Used mostly for metric purposes.
// Must be called on the main thread.
diff --git a/chromium/third_party/blink/public/platform/web_cache.h b/chromium/third_party/blink/public/platform/web_cache.h
index b70a9c79074..ffb8f9f3925 100644
--- a/chromium/third_party/blink/public/platform/web_cache.h
+++ b/chromium/third_party/blink/public/platform/web_cache.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CACHE_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CACHE_H_
+#include "third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h"
#include "third_party/blink/public/platform/web_common.h"
namespace blink {
@@ -43,23 +44,6 @@ class WebCache {
size_t size;
};
- // A struct mirroring blink::MemoryCache::TypeStatistic.
- struct ResourceTypeStat {
- size_t count;
- size_t size;
- size_t decoded_size;
- };
-
- // A struct mirroring blink::MemoryCache::Statistics.
- struct ResourceTypeStats {
- ResourceTypeStat images;
- ResourceTypeStat css_style_sheets;
- ResourceTypeStat scripts;
- ResourceTypeStat xsl_style_sheets;
- ResourceTypeStat fonts;
- ResourceTypeStat other;
- };
-
// Sets the capacities of the resource cache, evicting objects as necessary.
BLINK_PLATFORM_EXPORT static void SetCapacity(size_t);
@@ -72,7 +56,8 @@ class WebCache {
BLINK_PLATFORM_EXPORT static void GetUsageStats(UsageStats*);
// Get usage stats about the resource cache.
- BLINK_PLATFORM_EXPORT static void GetResourceTypeStats(ResourceTypeStats*);
+ BLINK_PLATFORM_EXPORT static void GetResourceTypeStats(
+ WebCacheResourceTypeStats*);
private:
WebCache() = delete; // Not intended to be instanced.
diff --git a/chromium/third_party/blink/public/platform/web_content_decryption_module_exception.h b/chromium/third_party/blink/public/platform/web_content_decryption_module_exception.h
index d8bf9bb0e0a..787ca0c38d1 100644
--- a/chromium/third_party/blink/public/platform/web_content_decryption_module_exception.h
+++ b/chromium/third_party/blink/public/platform/web_content_decryption_module_exception.h
@@ -13,10 +13,6 @@ enum WebContentDecryptionModuleException {
kWebContentDecryptionModuleExceptionNotSupportedError,
kWebContentDecryptionModuleExceptionInvalidStateError,
kWebContentDecryptionModuleExceptionQuotaExceededError,
- // TODO(jrummell): UnknownError is not part of the spec, but CDMs can
- // generate other error codes (in addition to the 4 listed above). Remove
- // UnknownError when the CDMs no longer use other error codes.
- kWebContentDecryptionModuleExceptionUnknownError
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h b/chromium/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
index f0126764ebf..f3a7c6c90b7 100644
--- a/chromium/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
+++ b/chromium/third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h
@@ -10,6 +10,7 @@
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
+#include "third_party/blink/public/platform/web_fetch_client_settings_object.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
namespace base {
@@ -34,17 +35,15 @@ class WebDedicatedWorkerHostFactoryClient {
virtual void CreateWorkerHostDeprecated(
const blink::WebSecurityOrigin& script_origin) = 0;
// For PlzDedicatedWorker.
- // TODO(nhiroki): Pack |fetch_client_*| into some struct like
- // WebFetchClientSettingsObject.
+ // |fetch_client_security_origin| is intentionally separated from
+ // |fetch_client_settings_object| as it shouldn't be passed from renderer
+ // process from the security perspective.
virtual void CreateWorkerHost(
const blink::WebURL& script_url,
const blink::WebSecurityOrigin& script_origin,
network::mojom::CredentialsMode credentials_mode,
const blink::WebSecurityOrigin& fetch_client_security_origin,
- network::mojom::ReferrerPolicy fetch_client_referrer_policy,
- const blink::WebURL& fetch_client_outgoing_referrer,
- const blink::WebInsecureRequestPolicy
- fetch_client_insecure_request_policy,
+ const blink::WebFetchClientSettingsObject& fetch_client_settings_object,
mojo::ScopedMessagePipeHandle blob_url_token) = 0;
// Clones the given WebWorkerFetchContext for nested workers.
diff --git a/chromium/third_party/blink/public/platform/web_fetch_client_settings_object.h b/chromium/third_party/blink/public/platform/web_fetch_client_settings_object.h
new file mode 100644
index 00000000000..ebb8e562c38
--- /dev/null
+++ b/chromium/third_party/blink/public/platform/web_fetch_client_settings_object.h
@@ -0,0 +1,53 @@
+// 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_WEB_FETCH_CLIENT_SETTINGS_OBJECT_H_
+#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_FETCH_CLIENT_SETTINGS_OBJECT_H_
+
+#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom-shared.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_url.h"
+
+#if INSIDE_BLINK
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" // nogncheck
+#include "third_party/blink/renderer/platform/weborigin/kurl.h" // nogncheck
+#endif
+
+namespace blink {
+
+// Yet another variant of FetchClientSettingsObject. Having this is unfortunate
+// but we need this struct for the interaction between blink and content until
+// Onion Soup is done.
+// Keep this struct consistent with mojom::FetchClientSettingsObject.
+struct WebFetchClientSettingsObject {
+ network::mojom::ReferrerPolicy referrer_policy =
+ network::mojom::ReferrerPolicy::kDefault;
+ WebURL outgoing_referrer;
+ mojom::InsecureRequestsPolicy insecure_requests_policy =
+ blink::mojom::InsecureRequestsPolicy::kDoNotUpgrade;
+
+ WebFetchClientSettingsObject(
+ network::mojom::ReferrerPolicy referrer_policy,
+ WebURL outgoing_referrer,
+ mojom::InsecureRequestsPolicy insecure_requests_policy)
+ : referrer_policy(referrer_policy),
+ outgoing_referrer(outgoing_referrer),
+ insecure_requests_policy(insecure_requests_policy) {}
+
+#if INSIDE_BLINK
+ explicit WebFetchClientSettingsObject(
+ const FetchClientSettingsObjectSnapshot& snapshot)
+ : referrer_policy(snapshot.GetReferrerPolicy()),
+ outgoing_referrer(KURL(snapshot.GetOutgoingReferrer())),
+ insecure_requests_policy(
+ snapshot.GetInsecureRequestsPolicy() &
+ blink::kUpgradeInsecureRequests
+ ? blink::mojom::InsecureRequestsPolicy::kUpgrade
+ : blink::mojom::InsecureRequestsPolicy::kDoNotUpgrade) {}
+#endif // INSIDE_BLINK
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_FETCH_CLIENT_SETTINGS_OBJECT_H_
diff --git a/chromium/third_party/blink/public/platform/web_http_body.h b/chromium/third_party/blink/public/platform/web_http_body.h
index d57d602348d..996b49af907 100644
--- a/chromium/third_party/blink/public/platform/web_http_body.h
+++ b/chromium/third_party/blink/public/platform/web_http_body.h
@@ -61,9 +61,10 @@ class WebHTTPBody {
WebString blob_uuid;
uint64_t blob_length;
mojo::ScopedMessagePipeHandle optional_blob_handle;
- // |data_pipe_getter| is a network::mojom::DataPipeGetterPtr. It's declared
- // as a generic ScopedMessagePipeHandle so it can be "cast" between Blink
- // and non-Blink variant types.
+ // |data_pipe_getter| is a
+ // mojo::PendingRemote<network::mojom::DataPipeGetter>. It's declared as a
+ // generic ScopedMessagePipeHandle so it can be "cast" between Blink and
+ // non-Blink variant types.
mojo::ScopedMessagePipeHandle data_pipe_getter;
};
@@ -103,9 +104,10 @@ class WebHTTPBody {
const WebString& uuid,
uint64_t length,
mojo::ScopedMessagePipeHandle blob_handle);
- // |data_pipe_getter| is a network::mojom::DataPipeGetterPtr. It's declared
- // as a generic ScopedMessagePipeHandle so it can be "cast" between Blink
- // and non-Blink variant types.
+ // |data_pipe_getter| is a
+ // mojo::PendingRemote<network::mojom::DataPipeGetter>. It's declared as a
+ // generic ScopedMessagePipeHandle so it can be "cast" between Blink and
+ // non-Blink variant types.
BLINK_PLATFORM_EXPORT void AppendDataPipe(
mojo::ScopedMessagePipeHandle data_pipe_getter);
diff --git a/chromium/third_party/blink/public/platform/web_localized_string.h b/chromium/third_party/blink/public/platform/web_localized_string.h
deleted file mode 100644
index 3da8e473bf5..00000000000
--- a/chromium/third_party/blink/public/platform/web_localized_string.h
+++ /dev/null
@@ -1,179 +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_PLATFORM_WEB_LOCALIZED_STRING_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_LOCALIZED_STRING_H_
-
-namespace blink {
-
-struct WebLocalizedString {
- enum Name {
- kAXAMPMFieldText,
- kAXCalendarShowDatePicker,
- kAXCalendarShowMonthSelector,
- kAXCalendarShowNextMonth,
- kAXCalendarShowPreviousMonth,
- kAXCalendarWeekDescription,
- kAXDayOfMonthFieldText,
- kAXHourFieldText,
- kAXMediaAudioElement,
- kAXMediaAudioElementHelp,
- kAXMediaAudioSliderHelp,
- kAXMediaCastOffButton,
- kAXMediaCastOnButton,
- kAXMediaCurrentTimeDisplay,
- kAXMediaCurrentTimeDisplayHelp,
- kAXMediaDefault,
- kAXMediaDownloadButton,
- kAXMediaEnterFullscreenButton,
- kAXMediaExitFullscreenButton,
- kAXMediaHideClosedCaptionsMenuButton,
- kAXMediaMuteButton,
- kAXMediaDisplayCutoutFullscreenButton,
- kAXMediaLoadingPanel,
- kAXMediaOverflowButton,
- kAXMediaOverflowButtonHelp,
- kAXMediaPauseButton,
- kAXMediaPlayButton,
- kAXMediaPlaybackError,
- kAXMediaShowClosedCaptionsMenuButton,
- kAXMediaTimeRemainingDisplay,
- kAXMediaTimeRemainingDisplayHelp,
- kAXMediaUnMuteButton,
- kAXMediaVideoElement,
- kAXMediaVideoElementHelp,
- kAXMediaVideoSliderHelp,
- kAXMediaVolumeSliderHelp,
- kAXMediaEnterPictureInPictureButton,
- kAXMediaExitPictureInPictureButton,
- kAXMediaTouchLessPlayPauseAction,
- kAXMediaTouchLessSeekAction,
- kAXMediaTouchLessVolumeAction,
- kAXMillisecondFieldText,
- kAXMinuteFieldText,
- kAXMonthFieldText,
- kAXSecondFieldText,
- kAXWeekOfYearFieldText,
- kAXYearFieldText,
- kBlockedPluginText,
- kCalendarClear,
- kCalendarToday,
- kDetailsLabel,
- kFileButtonChooseFileLabel,
- kFileButtonChooseMultipleFilesLabel,
- kFileButtonNoFileSelectedLabel,
- kInputElementAltText,
- kMediaRemotingCastText,
- kMediaRemotingCastToUnknownDeviceText,
- kMediaRemotingStopByErrorText,
- kMediaRemotingStopByPlaybackQualityText,
- kMediaRemotingStopNoText,
- kMediaRemotingStopText,
- kMediaScrubbingMessageText,
- kMissingPluginText,
- kMultipleFileUploadText,
- kOtherColorLabel,
- kOtherDateLabel,
- kOtherMonthLabel,
- kOtherWeekLabel,
- kOverflowMenuCaptions,
- kOverflowMenuCaptionsSubmenuTitle,
- kOverflowMenuCast,
- kOverflowMenuEnterFullscreen,
- kOverflowMenuExitFullscreen,
- kOverflowMenuMute,
- kOverflowMenuUnmute,
- kOverflowMenuPlay,
- kOverflowMenuPause,
- kOverflowMenuDownload,
- kOverflowMenuEnterPictureInPicture,
- kOverflowMenuExitPictureInPicture,
- kPictureInPictureInterstitialText,
- // kPlaceholderForDayOfMonthField is for day placeholder text, e.g.
- // "dd", for date field used in multiple fields "date", "datetime", and
- // "datetime-local" input UI instead of "--".
- kPlaceholderForDayOfMonthField,
- // kPlaceholderForfMonthField is for month placeholder text, e.g.
- // "mm", for month field used in multiple fields "date", "datetime", and
- // "datetime-local" input UI instead of "--".
- kPlaceholderForMonthField,
- // kPlaceholderForYearField is for year placeholder text, e.g. "yyyy",
- // for year field used in multiple fields "date", "datetime", and
- // "datetime-local" input UI instead of "----".
- kPlaceholderForYearField,
- kResetButtonDefaultLabel,
- kSelectMenuListText,
- kSubmitButtonDefaultLabel,
- kTextTracksNoLabel,
- kTextTracksOff,
- kThisMonthButtonLabel,
- kThisWeekButtonLabel,
- kUnitsKibibytes,
- kUnitsMebibytes,
- kUnitsGibibytes,
- kUnitsTebibytes,
- kUnitsPebibytes,
- kValidationBadInputForNumber,
- kValidationBadInputForDateTime,
- kValidationPatternMismatch,
- kValidationRangeOverflow,
- kValidationRangeOverflowDateTime,
- kValidationRangeUnderflow,
- kValidationRangeUnderflowDateTime,
- kValidationStepMismatch,
- kValidationStepMismatchCloseToLimit,
- kValidationTooLong,
- kValidationTooShort,
- kValidationTooShortPlural,
- kValidationTypeMismatch,
- kValidationTypeMismatchForEmail,
- kValidationTypeMismatchForEmailEmpty,
- kValidationTypeMismatchForEmailEmptyDomain,
- kValidationTypeMismatchForEmailEmptyLocal,
- kValidationTypeMismatchForEmailInvalidDomain,
- kValidationTypeMismatchForEmailInvalidDots,
- kValidationTypeMismatchForEmailInvalidLocal,
- kValidationTypeMismatchForEmailNoAtSign,
- kValidationTypeMismatchForMultipleEmail,
- kValidationTypeMismatchForURL,
- kValidationValueMissing,
- kValidationValueMissingForCheckbox,
- kValidationValueMissingForFile,
- kValidationValueMissingForMultipleFile,
- kValidationValueMissingForRadio,
- kValidationValueMissingForSelect,
- kWeekFormatTemplate,
- kWeekNumberLabel,
- };
-};
-
-} // namespace blink
-
-#endif
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 61869a8bf55..c2c3e215e57 100644
--- a/chromium/third_party/blink/public/platform/web_media_player.h
+++ b/chromium/third_party/blink/public/platform/web_media_player.h
@@ -425,6 +425,10 @@ class WebMediaPlayer {
return base::nullopt;
}
+ // Provide the media URL, after any redirects are applied. May return an
+ // empty GURL, which will be interpreted as "use the original URL".
+ virtual GURL GetSrcAfterRedirects() { return GURL(); }
+
virtual base::WeakPtr<WebMediaPlayer> AsWeakPtr() = 0;
};
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 9811f0f5106..850b079948d 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
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_
#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_localized_string.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "ui/gfx/color_space.h"
@@ -68,6 +67,8 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
kAudioTrackKindCommentary
};
+ static const int kMediaRemotingStopNoText = -1;
+
virtual void NetworkStateChanged() = 0;
virtual void ReadyStateChanged() = 0;
virtual void TimeChanged() = 0;
@@ -120,9 +121,10 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
virtual void MediaRemotingStarted(
const WebString& remote_device_friendly_name) = 0;
- // Informs that media stops being rendered remotely. |error_msg| corresponds
+ // Informs that media stops being rendered remotely. |error_code| corresponds
// to a localized string that explains the reason as user-readable text.
- virtual void MediaRemotingStopped(WebLocalizedString::Name error_msg) = 0;
+ // |error_code| should be IDS_FOO or kMediaRemotingStopNoText.
+ virtual void MediaRemotingStopped(int error_code) = 0;
// Returns whether the media element has native controls. It does not mean
// that the controls are currently visible.
@@ -175,6 +177,21 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
// - Natural Size.
virtual void OnPictureInPictureStateChange() = 0;
+ struct Features {
+ WebString id;
+ WebString width;
+ WebString parent_id;
+ WebString alt_text;
+ bool is_page_visible;
+ bool is_in_main_frame;
+ WebString url_host;
+ WebString url_path;
+ };
+
+ // Compute and return features for this media element for the media local
+ // learning experiment.
+ virtual Features GetFeatures() = 0;
+
protected:
~WebMediaPlayerClient() = default;
};
diff --git a/chromium/third_party/blink/public/platform/web_mouse_wheel_event.h b/chromium/third_party/blink/public/platform/web_mouse_wheel_event.h
index 087aef42745..92888e84e27 100644
--- a/chromium/third_party/blink/public/platform/web_mouse_wheel_event.h
+++ b/chromium/third_party/blink/public/platform/web_mouse_wheel_event.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MOUSE_WHEEL_EVENT_H_
#include "third_party/blink/public/platform/web_mouse_event.h"
+#include "ui/events/types/scroll_types.h"
namespace blink {
@@ -72,13 +73,6 @@ class WebMouseWheelEvent : public WebMouseEvent {
Phase phase;
Phase momentum_phase;
- // True when phase information is added in mouse_wheel_phase_handler based
- // on its timer.
- bool has_synthetic_phase = false;
-
- bool scroll_by_page = false;
- bool has_precise_scrolling_deltas = false;
-
RailsMode rails_mode;
// Whether the event is blocking, non-blocking, all event
@@ -88,6 +82,16 @@ class WebMouseWheelEvent : public WebMouseEvent {
// The expected result of this wheel event (if not canceled).
EventAction event_action;
+ // True when phase information is added in mouse_wheel_phase_handler based
+ // on its timer.
+ bool has_synthetic_phase = false;
+
+ // The units of delta_x and delta_y. Currently only supports
+ // kScrollByPrecisePixel, kScrollByPixel, and kScrollByPage, as they are
+ // the only values expected after converting an OS event to a
+ // WebMouseWheelEvent.
+ ui::input_types::ScrollGranularity delta_units;
+
WebMouseWheelEvent(Type type, int modifiers, base::TimeTicks time_stamp)
: WebMouseEvent(sizeof(WebMouseWheelEvent),
type,
@@ -104,7 +108,8 @@ class WebMouseWheelEvent : public WebMouseEvent {
phase(kPhaseNone),
momentum_phase(kPhaseNone),
rails_mode(kRailsModeFree),
- dispatch_type(kBlocking) {}
+ dispatch_type(kBlocking),
+ delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
WebMouseWheelEvent()
: WebMouseEvent(sizeof(WebMouseWheelEvent), kMousePointerId),
@@ -118,7 +123,8 @@ class WebMouseWheelEvent : public WebMouseEvent {
phase(kPhaseNone),
momentum_phase(kPhaseNone),
rails_mode(kRailsModeFree),
- dispatch_type(kBlocking) {}
+ dispatch_type(kBlocking),
+ delta_units(ui::input_types::ScrollGranularity::kScrollByPixel) {}
#if INSIDE_BLINK
BLINK_PLATFORM_EXPORT float DeltaXInRootFrame() const;
diff --git a/chromium/third_party/blink/public/platform/web_rtc_certificate_generator.h b/chromium/third_party/blink/public/platform/web_rtc_certificate_generator.h
deleted file mode 100644
index 198f4b1c958..00000000000
--- a/chromium/third_party/blink/public/platform/web_rtc_certificate_generator.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2015 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_RTC_CERTIFICATE_GENERATOR_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_GENERATOR_H_
-
-#include <memory>
-
-#include "third_party/blink/public/platform/web_rtc_key_params.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/webrtc/api/peer_connection_interface.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace blink {
-
-using WebRTCCertificateCallback =
- base::OnceCallback<void(rtc::scoped_refptr<rtc::RTCCertificate>)>;
-
-// Interface defining a class that can generate WebRTCCertificates
-// asynchronously.
-class WebRTCCertificateGenerator {
- public:
- virtual ~WebRTCCertificateGenerator() = default;
-
- // Start generating a certificate asynchronously. |observer| is invoked on the
- // same thread that called generateCertificate when the operation is
- // completed.
- virtual void GenerateCertificate(
- const WebRTCKeyParams&,
- WebRTCCertificateCallback completion_callback,
- scoped_refptr<base::SingleThreadTaskRunner>) = 0;
- virtual void GenerateCertificateWithExpiration(
- const WebRTCKeyParams&,
- uint64_t expires_ms,
- WebRTCCertificateCallback completion_callback,
- scoped_refptr<base::SingleThreadTaskRunner>) = 0;
-
- // Determines if the parameters are supported by |GenerateCertificate|.
- // For example, if the number of bits of some parameter is too small or too
- // large we may want to reject it for security or performance reasons.
- virtual bool IsSupportedKeyParams(const WebRTCKeyParams&) = 0;
-
- // Creates a certificate from the PEM strings. See also
- // |rtc::RTCCertificate::ToPEM|.
- virtual rtc::scoped_refptr<rtc::RTCCertificate> FromPEM(
- blink::WebString pem_private_key,
- blink::WebString pem_certificate) = 0;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_CERTIFICATE_GENERATOR_H_
diff --git a/chromium/third_party/blink/public/platform/web_rtc_rtp_source.h b/chromium/third_party/blink/public/platform/web_rtc_rtp_source.h
index 959440f7a57..c3fd5421aa6 100644
--- a/chromium/third_party/blink/public/platform/web_rtc_rtp_source.h
+++ b/chromium/third_party/blink/public/platform/web_rtc_rtp_source.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_RTP_SOURCE_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_RTC_RTP_SOURCE_H_
+#include <memory>
+
#include "base/optional.h"
#include "third_party/blink/public/platform/web_common.h"
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 95dd05edb09..d0b1bcb62ed 100644
--- a/chromium/third_party/blink/public/platform/web_runtime_features.h
+++ b/chromium/third_party/blink/public/platform/web_runtime_features.h
@@ -62,6 +62,9 @@ class WebRuntimeFeatures {
const std::string& name,
bool enable);
+ BLINK_PLATFORM_EXPORT static void EnableForcedColors(bool);
+ BLINK_PLATFORM_EXPORT static bool IsForcedColorsEnabled();
+
BLINK_PLATFORM_EXPORT static void EnableFractionalScrollOffsets(bool);
BLINK_PLATFORM_EXPORT static bool IsFractionalScrollOffsetsEnabled();
@@ -71,6 +74,9 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableCompositorTouchAction(bool);
BLINK_PLATFORM_EXPORT static void EnableAccelerated2dCanvas(bool);
+ BLINK_PLATFORM_EXPORT static void EnableAccessibilityExposeARIAAnnotations(
+ bool);
+ BLINK_PLATFORM_EXPORT static void EnableAccessibilityExposeDisplayNone(bool);
BLINK_PLATFORM_EXPORT static void EnableAccessibilityObjectModel(bool);
BLINK_PLATFORM_EXPORT static void EnableAdTagging(bool);
BLINK_PLATFORM_EXPORT static void EnableAllowActivationDelegationAttr(bool);
@@ -86,7 +92,6 @@ class WebRuntimeFeatures {
bool);
BLINK_PLATFORM_EXPORT static void EnableWasmCodeCache(bool);
BLINK_PLATFORM_EXPORT static void EnableCanvas2dImageChromium(bool);
- BLINK_PLATFORM_EXPORT static void EnableCanvas2dSwapChain(bool);
BLINK_PLATFORM_EXPORT static void EnableCooperativeScheduling(bool);
BLINK_PLATFORM_EXPORT static void EnableCSSHexAlphaColor(bool);
BLINK_PLATFORM_EXPORT static void EnableSameSiteByDefaultCookies(bool);
@@ -101,14 +106,13 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableFastMobileScrolling(bool);
BLINK_PLATFORM_EXPORT static void EnableFeaturePolicyForSandbox(bool);
BLINK_PLATFORM_EXPORT static void EnableFileSystem(bool);
- BLINK_PLATFORM_EXPORT static void EnableFirstContentfulPaintPlusPlus(bool);
BLINK_PLATFORM_EXPORT static void EnableForceSynchronousHTMLParsing(bool);
BLINK_PLATFORM_EXPORT static void EnableForceTallerSelectPopup(bool);
BLINK_PLATFORM_EXPORT static void EnableFormControlsRefresh(bool);
BLINK_PLATFORM_EXPORT static void EnableGenericSensorExtraClasses(bool);
BLINK_PLATFORM_EXPORT static void EnableImplicitRootScroller(bool);
+ BLINK_PLATFORM_EXPORT static void EnableCSSOMViewScrollCoordinates(bool);
BLINK_PLATFORM_EXPORT static void EnableInputMultipleFieldsUI(bool);
- BLINK_PLATFORM_EXPORT static void EnableJankTrackingSweepLine(bool);
BLINK_PLATFORM_EXPORT static void EnableBuiltInModuleAll(bool);
BLINK_PLATFORM_EXPORT static void EnableBuiltInModuleInfra(bool);
BLINK_PLATFORM_EXPORT static void EnableBuiltInModuleKvStorage(bool);
@@ -152,10 +156,8 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnablePrintBrowser(bool);
BLINK_PLATFORM_EXPORT static void EnablePresentationAPI(bool);
BLINK_PLATFORM_EXPORT static void EnablePushMessaging(bool);
- BLINK_PLATFORM_EXPORT static void EnableRasterInducingScroll(bool);
BLINK_PLATFORM_EXPORT static void EnableReducedReferrerGranularity(bool);
BLINK_PLATFORM_EXPORT static void EnableRemotePlaybackAPI(bool);
- BLINK_PLATFORM_EXPORT static void EnableResourceLoadScheduler(bool);
BLINK_PLATFORM_EXPORT static void
EnableRestrictAutomaticLazyFrameLoadingToDataSaver(bool);
BLINK_PLATFORM_EXPORT static void
@@ -163,7 +165,6 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableLazyImageLoadingMetadataFetch(bool);
BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechRecognition(bool);
BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechSynthesis(bool);
- BLINK_PLATFORM_EXPORT static void EnableScrollAnchorSerialization(bool);
BLINK_PLATFORM_EXPORT static void EnableFetchMetadata(bool);
BLINK_PLATFORM_EXPORT static void EnableAutoLazyLoadOnReloads(bool);
BLINK_PLATFORM_EXPORT static void EnableFetchMetadataDestination(bool);
@@ -183,7 +184,6 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableWebGL2ComputeContext(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGLDraftExtensions(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGLImageChromium(bool);
- BLINK_PLATFORM_EXPORT static void EnableWebGLSwapChain(bool);
BLINK_PLATFORM_EXPORT static void EnableWebGPU(bool);
BLINK_PLATFORM_EXPORT static void EnableWebNfc(bool);
BLINK_PLATFORM_EXPORT static void EnableWebShare(bool);
@@ -192,7 +192,9 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableWebVR(bool);
BLINK_PLATFORM_EXPORT static void EnableWebXR(bool);
BLINK_PLATFORM_EXPORT static void EnableWebXRARModule(bool);
+ BLINK_PLATFORM_EXPORT static void EnableWebXRARDOMOverlay(bool);
BLINK_PLATFORM_EXPORT static void EnableWebXRAnchors(bool);
+ BLINK_PLATFORM_EXPORT static void EnableWebXrGamepadModule(bool);
BLINK_PLATFORM_EXPORT static void EnableWebXRHitTest(bool);
BLINK_PLATFORM_EXPORT static void EnableWebXRPlaneDetection(bool);
BLINK_PLATFORM_EXPORT static void EnableXSLT(bool);
@@ -214,7 +216,6 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableMediaControlsOverlayPlayButton(bool);
BLINK_PLATFORM_EXPORT static void EnableRemotePlaybackBackend(bool);
BLINK_PLATFORM_EXPORT static void EnableMediaCastOverlayButton(bool);
- BLINK_PLATFORM_EXPORT static void EnableClientPlaceholdersForServerLoFi(bool);
BLINK_PLATFORM_EXPORT static void EnableLazyInitializeMediaControls(bool);
BLINK_PLATFORM_EXPORT static void EnableMediaEngagementBypassAutoplayPolicies(
bool);
@@ -237,13 +238,9 @@ class WebRuntimeFeatures {
bool);
BLINK_PLATFORM_EXPORT static void EnableIdleDetection(bool);
BLINK_PLATFORM_EXPORT static void EnableSkipTouchEventFilter(bool);
- BLINK_PLATFORM_EXPORT static void EnableStaleWhileRevalidate(bool);
BLINK_PLATFORM_EXPORT static void EnableSmsReceiver(bool);
BLINK_PLATFORM_EXPORT static void EnableDisplayLocking(bool);
- BLINK_PLATFORM_EXPORT static void
- EnablePauseExecutionContextOnBackgroundFreeze(bool);
BLINK_PLATFORM_EXPORT static void EnableConsolidatedMovementXY(bool);
- BLINK_PLATFORM_EXPORT static void EnableStreamsNative(bool);
BLINK_PLATFORM_EXPORT static void EnableMouseSubframeNoImplicitCapture(bool);
BLINK_PLATFORM_EXPORT static void EnableBackForwardCache(bool);
diff --git a/chromium/third_party/blink/public/platform/web_security_style.h b/chromium/third_party/blink/public/platform/web_security_style.h
deleted file mode 100644
index 3a60a1ad5dd..00000000000
--- a/chromium/third_party/blink/public/platform/web_security_style.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SECURITY_STYLE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SECURITY_STYLE_H_
-namespace blink {
-// This enum represents the security state of a resource.
-enum WebSecurityStyle {
- kWebSecurityStyleUnknown,
- kWebSecurityStyleNeutral,
- kWebSecurityStyleInsecure,
- kWebSecurityStyleSecure,
- kWebSecurityStyleLast = kWebSecurityStyleSecure
-};
-} // namespace blink
-#endif
diff --git a/chromium/third_party/blink/public/platform/web_source_buffer_client.h b/chromium/third_party/blink/public/platform/web_source_buffer_client.h
index 81cb9462cad..85f342b582d 100644
--- a/chromium/third_party/blink/public/platform/web_source_buffer_client.h
+++ b/chromium/third_party/blink/public/platform/web_source_buffer_client.h
@@ -16,7 +16,11 @@ namespace blink {
class WebSourceBufferClient {
public:
// Parser notification types used to monitor problematic usage.
- enum ParseWarning { kKeyframeTimeGreaterThanDependant, kMuxedSequenceMode };
+ enum ParseWarning {
+ kKeyframeTimeGreaterThanDependant,
+ kMuxedSequenceMode,
+ kGroupEndTimestampDecreaseWithinMediaSegment
+ };
virtual ~WebSourceBufferClient() = default;
diff --git a/chromium/third_party/blink/public/platform/web_string.h b/chromium/third_party/blink/public/platform/web_string.h
index e4fda4f666d..ffd1da0bc8e 100644
--- a/chromium/third_party/blink/public/platform/web_string.h
+++ b/chromium/third_party/blink/public/platform/web_string.h
@@ -102,10 +102,10 @@ class WebString {
BLINK_PLATFORM_EXPORT WebString(const WebUChar* data, size_t len);
BLINK_PLATFORM_EXPORT WebString(const WebString&);
- BLINK_PLATFORM_EXPORT WebString(WebString&&) noexcept;
+ BLINK_PLATFORM_EXPORT WebString(WebString&&);
BLINK_PLATFORM_EXPORT WebString& operator=(const WebString&);
- BLINK_PLATFORM_EXPORT WebString& operator=(WebString&&) noexcept;
+ BLINK_PLATFORM_EXPORT WebString& operator=(WebString&&);
BLINK_PLATFORM_EXPORT void Reset();
diff --git a/chromium/third_party/blink/public/platform/web_sudden_termination_disabler_type.h b/chromium/third_party/blink/public/platform/web_sudden_termination_disabler_type.h
deleted file mode 100644
index 7e4a39ed4e2..00000000000
--- a/chromium/third_party/blink/public/platform/web_sudden_termination_disabler_type.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SUDDEN_TERMINATION_DISABLER_TYPE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SUDDEN_TERMINATION_DISABLER_TYPE_H_
-
-namespace blink {
-
-// Used when elements preventing the sudden termination of the frame become
-// present or become absent.
-using WebSuddenTerminationDisablerType = uint8_t;
-const WebSuddenTerminationDisablerType kBeforeUnloadHandler = 1 << 0;
-const WebSuddenTerminationDisablerType kUnloadHandler = 1 << 1;
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SUDDEN_TERMINATION_DISABLER_TYPE_H_
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 73dbfd8f394..2b55c0b0baf 100644
--- a/chromium/third_party/blink/public/platform/web_theme_engine.h
+++ b/chromium/third_party/blink/public/platform/web_theme_engine.h
@@ -31,7 +31,9 @@
#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_THEME_ENGINE_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_THEME_ENGINE_H_
+#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/platform/web_color_scheme.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_scrollbar_overlay_color_theme.h"
@@ -81,6 +83,21 @@ class WebThemeEngine {
kPartProgressBar
};
+ enum class SystemThemeColor {
+ kNotSupported,
+ kButtonFace,
+ kButtonText,
+ kGrayText,
+ kHighlight,
+ kHighlightText,
+ kHotlight,
+ kMenuHighlight,
+ kScrollbar,
+ kWindow,
+ kWindowText,
+ kMaxValue = kWindowText,
+ };
+
// Extra parameters for drawing the PartScrollbarHorizontalTrack and
// PartScrollbarVerticalTrack.
struct ScrollbarTrackExtraParams {
@@ -203,6 +220,14 @@ class WebThemeEngine {
const WebRect&,
const ExtraParams*,
blink::WebColorScheme) {}
+
+ virtual base::Optional<SkColor> GetSystemColor(
+ SystemThemeColor system_theme) const {
+ return base::nullopt;
+ }
+
+ virtual ForcedColors ForcedColors() const { return ForcedColors::kNone; }
+ virtual void SetForcedColors(const blink::ForcedColors forced_colors) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/platform/web_transmission_encoding_info_handler.h b/chromium/third_party/blink/public/platform/web_transmission_encoding_info_handler.h
deleted file mode 100644
index dfdf15fcfe4..00000000000
--- a/chromium/third_party/blink/public/platform/web_transmission_encoding_info_handler.h
+++ /dev/null
@@ -1,38 +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_PUBLIC_PLATFORM_WEB_TRANSMISSION_ENCODING_INFO_HANDLER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_TRANSMISSION_ENCODING_INFO_HANDLER_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h"
-#include "third_party/blink/public/platform/web_common.h"
-
-namespace blink {
-
-struct WebMediaConfiguration;
-
-// Platform interface of a TransmissionEncodingInfoHandler.
-// It handle MediaCapabilities.encodingInfo() API with
-// "transmission" type.
-class BLINK_PLATFORM_EXPORT WebTransmissionEncodingInfoHandler {
- public:
- virtual ~WebTransmissionEncodingInfoHandler() = default;
-
- // 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>)>;
- virtual void EncodingInfo(const WebMediaConfiguration&,
- OnMediaCapabilitiesEncodingInfoCallback) const = 0;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_TRANSMISSION_ENCODING_INFO_HANDLER_H_
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 7bb0b6bf25d..17d09c8f746 100644
--- a/chromium/third_party/blink/public/platform/web_url_loader.h
+++ b/chromium/third_party/blink/public/platform/web_url_loader.h
@@ -37,6 +37,10 @@
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_url_request.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace blink {
class WebData;
diff --git a/chromium/third_party/blink/public/platform/web_url_loader_client.h b/chromium/third_party/blink/public/platform/web_url_loader_client.h
index b055afd9266..db68c8aa260 100644
--- a/chromium/third_party/blink/public/platform/web_url_loader_client.h
+++ b/chromium/third_party/blink/public/platform/web_url_loader_client.h
@@ -59,7 +59,6 @@ class BLINK_PLATFORM_EXPORT WebURLLoaderClient {
virtual bool WillFollowRedirect(
const WebURL& new_url,
const WebURL& new_site_for_cookies,
- const base::Optional<WebSecurityOrigin>& new_top_frame_origin,
const WebString& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
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 1e261f66c62..b7e32b823ea 100644
--- a/chromium/third_party/blink/public/platform/web_url_request.h
+++ b/chromium/third_party/blink/public/platform/web_url_request.h
@@ -35,16 +35,16 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
-#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/web_common.h"
#include "ui/base/page_transition_types.h"
+// TODO(crbug.com/922875): Need foo.mojom.shared-forward.h.
namespace network {
namespace mojom {
enum class CorsPreflightPolicy : int32_t;
enum class CredentialsMode : int32_t;
enum class RedirectMode : int32_t;
+enum class ReferrerPolicy : int32_t;
enum class RequestMode : int32_t;
enum class RequestContextFrameType : int32_t;
} // namespace mojom
@@ -54,6 +54,7 @@ namespace blink {
namespace mojom {
enum class FetchCacheMode : int32_t;
+enum class RequestContextType : int32_t;
} // namespace mojom
class ResourceRequest;
@@ -153,7 +154,9 @@ class WebURLRequest {
virtual ~ExtraData() = default;
protected:
- int render_frame_id_ = MSG_ROUTING_NONE;
+ BLINK_PLATFORM_EXPORT ExtraData();
+
+ int render_frame_id_;
bool is_main_frame_ = false;
ui::PageTransition transition_type_ = ui::PAGE_TRANSITION_LINK;
bool is_for_no_state_prefetch_ = false;
@@ -184,6 +187,10 @@ class WebURLRequest {
BLINK_PLATFORM_EXPORT WebSecurityOrigin RequestorOrigin() const;
BLINK_PLATFORM_EXPORT void SetRequestorOrigin(const WebSecurityOrigin&);
+ // The origin of the isolated world - set if this is a fetch/XHR initiated by
+ // an isolated world.
+ BLINK_PLATFORM_EXPORT WebSecurityOrigin IsolatedWorldOrigin() const;
+
// Controls whether user name, password, and cookies may be sent with the
// request.
BLINK_PLATFORM_EXPORT bool AllowStoredCredentials() const;
@@ -335,10 +342,6 @@ class WebURLRequest {
// Returns true when the request is for revalidation.
BLINK_PLATFORM_EXPORT bool IsRevalidating() const;
- // Returns true if the CORS module should take into account the origin
- // attached with the URLLoaderFactory.
- BLINK_PLATFORM_EXPORT bool ShouldAlsoUseFactoryBoundOriginForCors() const;
-
// Returns the DevTools ID to throttle the network request.
BLINK_PLATFORM_EXPORT const base::Optional<base::UnguessableToken>&
GetDevToolsToken() const;
@@ -367,6 +370,9 @@ class WebURLRequest {
BLINK_PLATFORM_EXPORT bool IsSignedExchangePrefetchCacheEnabled() const;
+ BLINK_PLATFORM_EXPORT base::Optional<base::UnguessableToken>
+ RecursivePrefetchToken() const;
+
#if INSIDE_BLINK
BLINK_PLATFORM_EXPORT ResourceRequest& ToMutableResourceRequest();
BLINK_PLATFORM_EXPORT const ResourceRequest& ToResourceRequest() const;
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 d0e9c07a107..500fa6ed910 100644
--- a/chromium/third_party/blink/public/platform/web_url_response.h
+++ b/chromium/third_party/blink/public/platform/web_url_response.h
@@ -37,13 +37,17 @@
#include "base/time/time.h"
#include "net/cert/ct_policy_status.h"
#include "net/http/http_response_info.h"
-#include "services/network/public/mojom/fetch_api.mojom-shared.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/public/common/security/security_style.h"
#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_security_style.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
+namespace network {
+namespace mojom {
+enum class FetchResponseType : int32_t;
+}
+} // namespace network
+
namespace blink {
class ResourceResponse;
@@ -213,7 +217,7 @@ class WebURLResponse {
BLINK_PLATFORM_EXPORT void SetCTPolicyCompliance(net::ct::CTPolicyCompliance);
BLINK_PLATFORM_EXPORT void SetIsLegacyTLSVersion(bool);
- BLINK_PLATFORM_EXPORT void SetSecurityStyle(WebSecurityStyle);
+ BLINK_PLATFORM_EXPORT void SetSecurityStyle(SecurityStyle);
BLINK_PLATFORM_EXPORT void SetSecurityDetails(const WebSecurityDetails&);
BLINK_PLATFORM_EXPORT base::Optional<WebSecurityDetails>
@@ -231,6 +235,7 @@ class WebURLResponse {
// Flag whether this request was loaded via the SPDY protocol or not.
// SPDY is an experimental web protocol, see http://dev.chromium.org/spdy
+ BLINK_PLATFORM_EXPORT bool WasFetchedViaSPDY() const;
BLINK_PLATFORM_EXPORT void SetWasFetchedViaSPDY(bool);
// Flag whether this request was loaded via a ServiceWorker. See
@@ -276,9 +281,15 @@ class WebURLResponse {
BLINK_PLATFORM_EXPORT void SetRemotePort(uint16_t);
// ALPN negotiated protocol of the socket which fetched this resource.
+ BLINK_PLATFORM_EXPORT bool WasAlpnNegotiated() const;
+ BLINK_PLATFORM_EXPORT void SetWasAlpnNegotiated(bool);
BLINK_PLATFORM_EXPORT WebString AlpnNegotiatedProtocol() const;
BLINK_PLATFORM_EXPORT void SetAlpnNegotiatedProtocol(const WebString&);
+ // Whether the response could use alternate protocol.
+ BLINK_PLATFORM_EXPORT bool WasAlternateProtocolAvailable() const;
+ BLINK_PLATFORM_EXPORT void SetWasAlternateProtocolAvailable(bool);
+
// Information about the type of connection used to fetch this resource.
BLINK_PLATFORM_EXPORT net::HttpResponseInfo::ConnectionInfo ConnectionInfo()
const;
@@ -294,6 +305,8 @@ class WebURLResponse {
BLINK_PLATFORM_EXPORT void SetIsSignedExchangeInnerResponse(bool);
BLINK_PLATFORM_EXPORT void SetWasInPrefetchCache(bool);
+ BLINK_PLATFORM_EXPORT void SetRecursivePrefetchToken(
+ const base::Optional<base::UnguessableToken>&);
// Whether this resource is from a MHTML archive.
BLINK_PLATFORM_EXPORT bool FromArchive() const;
diff --git a/chromium/third_party/blink/public/public_features.gni b/chromium/third_party/blink/public/public_features.gni
index f977569611d..c4834efc30d 100644
--- a/chromium/third_party/blink/public/public_features.gni
+++ b/chromium/third_party/blink/public/public_features.gni
@@ -10,6 +10,10 @@ declare_args() {
# resources.pak. It is still possible to load JS files from disk by passing
# --debug-devtools cmdline switch.
debug_devtools = false
+
+ # If external_devtools_frontend is set to true, use DevTools frontend that is
+ # pulled as external dependency.
+ external_devtools_frontend = false
}
# Unhandled Tap enable means Contextual Search aka Tap to Search.
diff --git a/chromium/third_party/blink/public/public_typemaps.gni b/chromium/third_party/blink/public/public_typemaps.gni
index 60808309f10..0a428d85b8f 100644
--- a/chromium/third_party/blink/public/public_typemaps.gni
+++ b/chromium/third_party/blink/public/public_typemaps.gni
@@ -8,7 +8,6 @@ typemaps = [
"//third_party/blink/public/common/fetch/fetch_api_request_headers.typemap",
"//third_party/blink/public/common/indexeddb/indexed_db_default.typemap",
"//third_party/blink/public/common/loader/url_loader_factory_bundle.typemap",
- "//third_party/blink/public/common/manifest/display_mode.typemap",
"//third_party/blink/public/common/manifest/manifest.typemap",
"//third_party/blink/public/common/mediastream/media_devices.typemap",
"//third_party/blink/public/common/mediastream/media_stream.typemap",
diff --git a/chromium/third_party/blink/public/strings/BUILD.gn b/chromium/third_party/blink/public/strings/BUILD.gn
new file mode 100644
index 00000000000..83cfe650b7c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/BUILD.gn
@@ -0,0 +1,66 @@
+# 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("//tools/grit/grit_rule.gni")
+
+grit("strings") {
+ source = "blink_strings.grd"
+ outputs = [
+ "grit/blink_strings.h",
+ "blink_strings_am.pak",
+ "blink_strings_ar.pak",
+ "blink_strings_bg.pak",
+ "blink_strings_bn.pak",
+ "blink_strings_ca.pak",
+ "blink_strings_cs.pak",
+ "blink_strings_da.pak",
+ "blink_strings_de.pak",
+ "blink_strings_el.pak",
+ "blink_strings_en-GB.pak",
+ "blink_strings_en-US.pak",
+ "blink_strings_es.pak",
+ "blink_strings_es-419.pak",
+ "blink_strings_et.pak",
+ "blink_strings_fa.pak",
+ "blink_strings_fake-bidi.pak",
+ "blink_strings_fi.pak",
+ "blink_strings_fil.pak",
+ "blink_strings_fr.pak",
+ "blink_strings_gu.pak",
+ "blink_strings_he.pak",
+ "blink_strings_hi.pak",
+ "blink_strings_hr.pak",
+ "blink_strings_hu.pak",
+ "blink_strings_id.pak",
+ "blink_strings_it.pak",
+ "blink_strings_ja.pak",
+ "blink_strings_kn.pak",
+ "blink_strings_ko.pak",
+ "blink_strings_lt.pak",
+ "blink_strings_lv.pak",
+ "blink_strings_ml.pak",
+ "blink_strings_mr.pak",
+ "blink_strings_ms.pak",
+ "blink_strings_nl.pak",
+ "blink_strings_nb.pak",
+ "blink_strings_pl.pak",
+ "blink_strings_pt-BR.pak",
+ "blink_strings_pt-PT.pak",
+ "blink_strings_ro.pak",
+ "blink_strings_ru.pak",
+ "blink_strings_sk.pak",
+ "blink_strings_sl.pak",
+ "blink_strings_sr.pak",
+ "blink_strings_sv.pak",
+ "blink_strings_sw.pak",
+ "blink_strings_ta.pak",
+ "blink_strings_te.pak",
+ "blink_strings_th.pak",
+ "blink_strings_tr.pak",
+ "blink_strings_uk.pak",
+ "blink_strings_vi.pak",
+ "blink_strings_zh-CN.pak",
+ "blink_strings_zh-TW.pak",
+ ]
+}
diff --git a/chromium/third_party/blink/public/strings/blink_strings.grd b/chromium/third_party/blink/public/strings/blink_strings.grd
new file mode 100644
index 00000000000..06d55e16e70
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/blink_strings.grd
@@ -0,0 +1,1106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This file contains definitions of resources that will be translated for
+each locale. Specifically, these are UI strings that are used by content that
+need to be translated for each locale.-->
+
+<!-- Some of these strings and string descriptions were taken from
+WebKit/win/WebCoreLocalizedStrings.cpp so we include the original license
+below:
+
+/*
+ * Copyright (C) 2007 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.
+ */
+-->
+
+<grit base_dir="." latest_public_release="0" current_release="1"
+ output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
+ <outputs>
+ <!-- TODO add each of your output files. Modify the three below, and add
+ your own for your various languages. See the user's guide
+ (https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide)
+ for more details.
+ Note that all output references are relative to the output directory
+ which is specified at build time. -->
+ <output filename="grit/blink_strings.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="blink_strings_am.pak" type="data_package" lang="am" />
+ <output filename="blink_strings_ar.pak" type="data_package" lang="ar" />
+ <output filename="blink_strings_bg.pak" type="data_package" lang="bg" />
+ <output filename="blink_strings_bn.pak" type="data_package" lang="bn" />
+ <output filename="blink_strings_ca.pak" type="data_package" lang="ca" />
+ <output filename="blink_strings_cs.pak" type="data_package" lang="cs" />
+ <output filename="blink_strings_da.pak" type="data_package" lang="da" />
+ <output filename="blink_strings_de.pak" type="data_package" lang="de" />
+ <output filename="blink_strings_el.pak" type="data_package" lang="el" />
+ <output filename="blink_strings_en-GB.pak" type="data_package" lang="en-GB" />
+ <output filename="blink_strings_en-US.pak" type="data_package" lang="en" />
+ <output filename="blink_strings_es.pak" type="data_package" lang="es" />
+ <output filename="blink_strings_es-419.pak" type="data_package" lang="es-419" />
+ <output filename="blink_strings_et.pak" type="data_package" lang="et" />
+ <output filename="blink_strings_fa.pak" type="data_package" lang="fa" />
+ <output filename="blink_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
+ <output filename="blink_strings_fi.pak" type="data_package" lang="fi" />
+ <output filename="blink_strings_fil.pak" type="data_package" lang="fil" />
+ <output filename="blink_strings_fr.pak" type="data_package" lang="fr" />
+ <output filename="blink_strings_gu.pak" type="data_package" lang="gu" />
+ <output filename="blink_strings_he.pak" type="data_package" lang="he" />
+ <output filename="blink_strings_hi.pak" type="data_package" lang="hi" />
+ <output filename="blink_strings_hr.pak" type="data_package" lang="hr" />
+ <output filename="blink_strings_hu.pak" type="data_package" lang="hu" />
+ <output filename="blink_strings_id.pak" type="data_package" lang="id" />
+ <output filename="blink_strings_it.pak" type="data_package" lang="it" />
+ <output filename="blink_strings_ja.pak" type="data_package" lang="ja" />
+ <output filename="blink_strings_kn.pak" type="data_package" lang="kn" />
+ <output filename="blink_strings_ko.pak" type="data_package" lang="ko" />
+ <output filename="blink_strings_lt.pak" type="data_package" lang="lt" />
+ <output filename="blink_strings_lv.pak" type="data_package" lang="lv" />
+ <output filename="blink_strings_ml.pak" type="data_package" lang="ml" />
+ <output filename="blink_strings_mr.pak" type="data_package" lang="mr" />
+ <output filename="blink_strings_ms.pak" type="data_package" lang="ms" />
+ <output filename="blink_strings_nl.pak" type="data_package" lang="nl" />
+ <!-- The translation console uses 'no' for Norwegian Bokmål. It should
+ be 'nb'. -->
+ <output filename="blink_strings_nb.pak" type="data_package" lang="no" />
+ <output filename="blink_strings_pl.pak" type="data_package" lang="pl" />
+ <output filename="blink_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
+ <output filename="blink_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
+ <output filename="blink_strings_ro.pak" type="data_package" lang="ro" />
+ <output filename="blink_strings_ru.pak" type="data_package" lang="ru" />
+ <output filename="blink_strings_sk.pak" type="data_package" lang="sk" />
+ <output filename="blink_strings_sl.pak" type="data_package" lang="sl" />
+ <output filename="blink_strings_sr.pak" type="data_package" lang="sr" />
+ <output filename="blink_strings_sv.pak" type="data_package" lang="sv" />
+ <output filename="blink_strings_sw.pak" type="data_package" lang="sw" />
+ <output filename="blink_strings_ta.pak" type="data_package" lang="ta" />
+ <output filename="blink_strings_te.pak" type="data_package" lang="te" />
+ <output filename="blink_strings_th.pak" type="data_package" lang="th" />
+ <output filename="blink_strings_tr.pak" type="data_package" lang="tr" />
+ <output filename="blink_strings_uk.pak" type="data_package" lang="uk" />
+ <output filename="blink_strings_vi.pak" type="data_package" lang="vi" />
+ <output filename="blink_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
+ <output filename="blink_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
+ </outputs>
+ <translations>
+ <file path="translations/blink_strings_am.xtb" lang="am" />
+ <file path="translations/blink_strings_ar.xtb" lang="ar" />
+ <file path="translations/blink_strings_bg.xtb" lang="bg" />
+ <file path="translations/blink_strings_bn.xtb" lang="bn" />
+ <file path="translations/blink_strings_ca.xtb" lang="ca" />
+ <file path="translations/blink_strings_cs.xtb" lang="cs" />
+ <file path="translations/blink_strings_da.xtb" lang="da" />
+ <file path="translations/blink_strings_de.xtb" lang="de" />
+ <file path="translations/blink_strings_el.xtb" lang="el" />
+ <file path="translations/blink_strings_en-GB.xtb" lang="en-GB" />
+ <file path="translations/blink_strings_es.xtb" lang="es" />
+ <file path="translations/blink_strings_es-419.xtb" lang="es-419" />
+ <file path="translations/blink_strings_et.xtb" lang="et" />
+ <file path="translations/blink_strings_fa.xtb" lang="fa" />
+ <file path="translations/blink_strings_fi.xtb" lang="fi" />
+ <file path="translations/blink_strings_fil.xtb" lang="fil" />
+ <file path="translations/blink_strings_fr.xtb" lang="fr" />
+ <file path="translations/blink_strings_gu.xtb" lang="gu" />
+ <file path="translations/blink_strings_hi.xtb" lang="hi" />
+ <file path="translations/blink_strings_hr.xtb" lang="hr" />
+ <file path="translations/blink_strings_hu.xtb" lang="hu" />
+ <file path="translations/blink_strings_id.xtb" lang="id" />
+ <file path="translations/blink_strings_it.xtb" lang="it" />
+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+ <file path="translations/blink_strings_iw.xtb" lang="he" />
+ <file path="translations/blink_strings_ja.xtb" lang="ja" />
+ <file path="translations/blink_strings_kn.xtb" lang="kn" />
+ <file path="translations/blink_strings_ko.xtb" lang="ko" />
+ <file path="translations/blink_strings_lt.xtb" lang="lt" />
+ <file path="translations/blink_strings_lv.xtb" lang="lv" />
+ <file path="translations/blink_strings_ml.xtb" lang="ml" />
+ <file path="translations/blink_strings_mr.xtb" lang="mr" />
+ <file path="translations/blink_strings_ms.xtb" lang="ms" />
+ <file path="translations/blink_strings_nl.xtb" lang="nl" />
+ <file path="translations/blink_strings_no.xtb" lang="no" />
+ <file path="translations/blink_strings_pl.xtb" lang="pl" />
+ <file path="translations/blink_strings_pt-BR.xtb" lang="pt-BR" />
+ <file path="translations/blink_strings_pt-PT.xtb" lang="pt-PT" />
+ <file path="translations/blink_strings_ro.xtb" lang="ro" />
+ <file path="translations/blink_strings_ru.xtb" lang="ru" />
+ <file path="translations/blink_strings_sk.xtb" lang="sk" />
+ <file path="translations/blink_strings_sl.xtb" lang="sl" />
+ <file path="translations/blink_strings_sr.xtb" lang="sr" />
+ <file path="translations/blink_strings_sv.xtb" lang="sv" />
+ <file path="translations/blink_strings_sw.xtb" lang="sw" />
+ <file path="translations/blink_strings_ta.xtb" lang="ta" />
+ <file path="translations/blink_strings_te.xtb" lang="te" />
+ <file path="translations/blink_strings_th.xtb" lang="th" />
+ <file path="translations/blink_strings_tr.xtb" lang="tr" />
+ <file path="translations/blink_strings_uk.xtb" lang="uk" />
+ <file path="translations/blink_strings_vi.xtb" lang="vi" />
+ <file path="translations/blink_strings_zh-CN.xtb" lang="zh-CN" />
+ <file path="translations/blink_strings_zh-TW.xtb" lang="zh-TW" />
+ </translations>
+ <release seq="1" allow_pseudo="false">
+ <messages fallback_to_english="true">
+ <!-- TODO add all of your "string table" messages here. Remember to
+ change nontranslateable parts of the messages into placeholders (using the
+ <ph> element). You can also use the 'grit add' tool to help you identify
+ nontranslateable parts and create placeholders for them. -->
+
+ <message name="IDS_DETAILS_WITHOUT_SUMMARY_LABEL" desc="Clickable label to show detailed information or to hide the detailed information.">
+ Details
+ </message>
+ <message name="IDS_FORM_CALENDAR_CLEAR" desc="Label for a button which clears a date input field.">
+ Clear
+ </message>
+ <message name="IDS_FORM_CALENDAR_TODAY" desc="Label for a button which sets today to a date input field.">
+ Today
+ </message>
+ <message name="IDS_FORM_SUBMIT_LABEL" desc="Default label for Submit buttons in forms on webpages.">
+ Submit
+ </message>
+ <message name="IDS_FORM_INPUT_ALT" desc="Alt text for &lt;input&gt; elements with no alt, title, or value">
+ Submit
+ </message>
+ <message name="IDS_FORM_RESET_LABEL" desc="default label for Reset buttons in forms on webpages">
+ Reset
+ </message>
+ <message name="IDS_FORM_FILE_BUTTON_LABEL" desc="title for a single file chooser button used in HTML forms">
+ Choose File
+ </message>
+ <message name="IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL" desc="title for a multiple file chooser button used in HTML forms. This title should be as short as possible.">
+ Choose Files
+ </message>
+ <message name="IDS_FORM_FILE_NO_FILE_LABEL" desc="text to display in file button used in HTML forms when no file is selected">
+ No file chosen
+ </message>
+ <message name="IDS_FORM_FILE_MULTIPLE_UPLOAD" desc="text to display next to file buttons in HTML forms when 2 or more files are selected for uploading. This is not used for a case that just 1 file is selected.">
+ <ph name="NUMBER_OF_FILES">$1<ex>3</ex></ph> files
+ </message>
+ <message name="IDS_FORM_OTHER_COLOR_LABEL" desc="Label for button that opens a full color chooser so the user can choose colors other than the ones in the list.">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_DATE_LABEL" desc="Label for button that opens a full calendar picker so the user can choose dates other than the ones in the list." meaning="for date label">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_MONTH_LABEL" desc="Label for button that opens a full month picker so the user can choose dates other than the ones in the list." meaning="for month label">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_WEEK_LABEL" desc="Label for button that opens a full week picker so the user can choose dates other than the ones in the list." meaning="for week label">
+ Other...
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD" desc="Text for denoting day of month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ dd
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD" desc="Text for denoting month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ mm
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD" desc="Text for denoting day of month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ yyyy
+ </message>
+ <message name="IDS_FORM_SELECT_MENU_LIST_TEXT" desc="Text for the menu list rendering of a select element.">
+ <ph name="SELECTED_COUNT">$1<ex>3</ex></ph> selected
+ </message>
+ <message name="IDS_FORM_THIS_MONTH_LABEL" desc="Label for button in month picker to select this month.">
+ This month
+ </message>
+ <message name="IDS_FORM_THIS_WEEK_LABEL" desc="Label for button in week picker to select this week.">
+ This week
+ </message>
+ <message name="IDS_FORM_WEEK_NUMBER_LABEL" desc="Label for week number column in a calendar.">
+ Week
+ </message>
+
+ <message name="IDS_AX_CALENDAR_SHOW_DATE_PICKER" desc="Accessible description of a button to show a calendar from a date input field.">
+ Show date picker
+ </message>
+ <message name="IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR" desc="Accessible description of a button to show month selection panel in a calendar picker.">
+ Show month selection panel
+ </message>
+ <message name="IDS_AX_CALENDAR_SHOW_NEXT_MONTH" desc="Accessible description of a button to show next month in a calendar picker.">
+ Show next month
+ </message>
+ <message name="IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH" desc="Accessible description of a button to show previous month in a calendar picker.">
+ Show previous month
+ </message>
+ <message name="IDS_AX_CALENDAR_WEEK_DESCRIPTION" desc="Accessible description of a button to select a specific week.">
+ <ph name="WEEK">$1<ex>Week 38, 2014</ex></ph>, starting on <ph name="WEEK_START_DATE">$2<ex>September 15, 2014</ex></ph>
+ </message>
+
+ <!-- Localized names for accessibility roles -->
+ <message name="IDS_AX_ROLE_ANNOTATION_ATTRIBUTION" desc="Accessibility role description for attribution, meaning authoring information tied to specific content">
+ authoring info
+ </message>
+ <message name="IDS_AX_ROLE_ANNOTATION_COMMENTARY" desc="Accessibility role description for commentary">
+ comments
+ </message>
+ <message name="IDS_AX_ROLE_ANNOTATION_PRESENCE" desc="Accessibility role description for presence, meaning information about another collaborator who is currently reviewing or editing this content">
+ live presence
+ </message>
+ <message name="IDS_AX_ROLE_ANNOTATION_REVISION" desc="Accessibility role description for revision, meaining historical change info tied to this content">
+ revision
+ </message>
+ <message name="IDS_AX_ROLE_ANNOTATION_SUGGESTION" desc="Accessibility role description for suggestion, meaning a suggested change to some content">
+ suggestion
+ </message>
+ <message name="IDS_AX_ROLE_ARTICLE" desc="Accessibility role description for article">
+ article
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-audio -->
+ <message name="IDS_AX_ROLE_AUDIO" desc="Accessible role description for audio">
+ audio
+ </message>
+ <message name="IDS_AX_ROLE_BANNER" desc="Accessibility role description for banner">
+ banner
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-input-color -->
+ <message name="IDS_AX_ROLE_COLOR_WELL" desc="Accessibility role description for a color picker">
+ color picker
+ </message>
+ <message name="IDS_AX_ROLE_COMPLEMENTARY" desc="Accessibility role description for complementary">
+ complementary
+ </message>
+ <message name="IDS_AX_ROLE_CONTENT_DELETION" desc="Accessibility role description for content deletion, meaning content that is has been or is suggested to be removed from a document, such as in a revision review">
+ deletion
+ </message>
+ <message name="IDS_AX_ROLE_CONTENT_INSERTION" desc="Accessibility role description for content insertion, meaning content that has been marked or is suggested to be inserted into a document, such as in a revision review">
+ insertion
+ </message>
+ <message name="IDS_AX_ROLE_CHECK_BOX" desc="Accessibility role description for a check box">
+ checkbox
+ </message>
+ <message name="IDS_AX_ROLE_CONTENT_INFO" desc="Accessibility role description for credits and information about the content of the page, like copyrights and privacy statements">
+ content information
+ </message>
+ <message name="IDS_AX_ROLE_DATE" desc="Accessibility role description for a date input">
+ date picker
+ </message>
+ <message name="IDS_AX_ROLE_DATE_TIME_LOCAL" desc="Accessibility role description for a datetime-local input">
+ local date and time picker
+ </message>
+ <message name="IDS_AX_ROLE_DEFINITION" desc="Accessibility role description for a definition">
+ definition
+ </message>
+ <message name="IDS_AX_ROLE_DESCRIPTION_LIST" desc="Accessibility role description for a definition list">
+ definition list
+ </message>
+ <message name="IDS_AX_ROLE_DESCRIPTION_TERM" desc="Accessibility role description for description term (as in a description list)">
+ term
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-details -->
+ <message name="IDS_AX_ROLE_DETAILS" desc="Accessibility role description for details">
+ details
+ </message>
+ <message name="IDS_AX_ROLE_DISCLOSURE_TRIANGLE" desc="Accessibility role description for a disclosure triangle, a control shaped like a triangle that expands or collapses to show or hide extra content">
+ disclosure triangle
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ABSTRACT" desc="Accessibility role description for abstract, meaning the summary of the contents of an article or book">
+ abstract
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ACKNOWLEDGMENTS" desc="Accessibility role description for acknowledgments">
+ acknowledgments
+ </message>
+ <message name="IDS_AX_ROLE_DOC_AFTERWORD" desc="Accessibility role description for afterword">
+ afterword
+ </message>
+ <message name="IDS_AX_ROLE_DOC_APPENDIX" desc="Accessibility role description for appendix, meaning the summary of the contents of an article or book">
+ appendix
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BACKLINK" desc="Accessibility role description for back link">
+ back link
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIO_ENTRY" desc="Accessibility role description for bibliography entry">
+ bibliography entry
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIOGRAPHY" desc="Accessibility role description for bibliography">
+ bibliography
+ </message>
+ <message name="IDS_AX_ROLE_DOC_BIBLIO_REF" desc="Accessibility role description for bibliography reference">
+ bibliography reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CHAPTER" desc="Accessibility role description for chapter">
+ chapter
+ </message>
+ <message name="IDS_AX_ROLE_DOC_COLOPHON" desc="Accessibility role description for colophon">
+ colophon
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CONCLUSION" desc="Accessibility role description for conclusion">
+ conclusion
+ </message>
+ <message name="IDS_AX_ROLE_DOC_COVER" desc="Accessibility role description for cover">
+ cover
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CREDIT" desc="Accessibility role description for credit, a public acknowledgement of someone who was responsible for helping with something">
+ credit
+ </message>
+ <message name="IDS_AX_ROLE_DOC_CREDITS" desc="Accessibility role description for credits">
+ credits
+ </message>
+ <message name="IDS_AX_ROLE_DOC_DEDICATION" desc="Accessibility role description for dedication">
+ dedication
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ENDNOTE" desc="Accessibility role description for endnote">
+ endnote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ENDNOTES" desc="Accessibility role description for endnotes">
+ endnotes
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EPIGRAPH" desc="Accessibility role description for epigraph">
+ epigraph
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EPILOGUE" desc="Accessibility role description for epilogue">
+ epilogue
+ </message>
+ <message name="IDS_AX_ROLE_DOC_ERRATA" desc="Accessibility role description for errata">
+ errata
+ </message>
+ <message name="IDS_AX_ROLE_DOC_EXAMPLE" desc="Accessibility role description for example">
+ example
+ </message>
+ <message name="IDS_AX_ROLE_DOC_FOOTNOTE" desc="Accessibility role description for footnote">
+ footnote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_FOREWORD" desc="Accessibility role description for foreword">
+ foreword
+ </message>
+ <message name="IDS_AX_ROLE_DOC_GLOSSARY" desc="Accessibility role description for glossary">
+ glossary
+ </message>
+ <message name="IDS_AX_ROLE_DOC_GLOSS_REF" desc="Accessibility role description for glossary reference">
+ glossary reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_INDEX" desc="Accessibility role description for index">
+ index
+ </message>
+ <message name="IDS_AX_ROLE_DOC_INTRODUCTION" desc="Accessibility role description for introduction">
+ introduction
+ </message>
+ <message name="IDS_AX_ROLE_DOC_NOTE_REF" desc="Accessibility role description for note reference">
+ note reference
+ </message>
+ <message name="IDS_AX_ROLE_DOC_NOTICE" desc="Accessibility role description for notice">
+ notice
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PAGE_BREAK" desc="Accessibility role description for page break">
+ page break
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PAGE_LIST" desc="Accessibility role description for page list">
+ page list
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PART" desc="Accessibility role description for part, as in a part of a book">
+ part
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PREFACE" desc="Accessibility role description for preface">
+ preface
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PROLOGUE" desc="Accessibility role description for prologue">
+ prologue
+ </message>
+ <message name="IDS_AX_ROLE_DOC_PULLQUOTE" desc="Accessibility role description for pullquote">
+ pullquote
+ </message>
+ <message name="IDS_AX_ROLE_DOC_QNA" desc="Accessibility role description for Q+A (questions and answers)">
+ Q&amp;A
+ </message>
+ <message name="IDS_AX_ROLE_DOC_SUBTITLE" desc="Accessibility role description for subtitle">
+ subtitle
+ </message>
+ <message name="IDS_AX_ROLE_DOC_TIP" desc="Accessibility role description for tip, as in a suggestion or idea">
+ tip
+ </message>
+ <message name="IDS_AX_ROLE_DOC_TOC" desc="Accessibility role description for table of contents">
+ table of contents
+ </message>
+ <message name="IDS_AX_ROLE_FEED" desc="Accessibility role description for a scrollable list of articles.">
+ feed
+ </message>
+ <message name="IDS_AX_ROLE_FIGURE" desc="Accessibility role description for figure">
+ figure
+ </message>
+ <message name="IDS_AX_ROLE_FORM" desc="Accessibility role description for form">
+ form
+ </message>
+ <message name="IDS_AX_ROLE_FOOTER" desc="Accessibility role description for footers">
+ footer
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHICS_DOCUMENT" desc="Accessibility role description for graphics document">
+ graphics document
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHICS_OBJECT" desc="Accessibility role description for graphics object">
+ graphics object
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHICS_SYMBOL" desc="Accessibility role description for graphics symbol">
+ graphics symbol
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-input-email -->
+ <message name="IDS_AX_ROLE_EMAIL" desc="Accessibility role description for email input">
+ email
+ </message>
+ <message name="IDS_AX_AUTOFILL_POPUP_ACCESSIBLE_NODE_DATA" desc="The accessibility text to speak when we display an autofill popup">
+ Autofill
+ </message>
+ <if expr="is_macosx">
+ <message name="IDS_AX_ROLE_STEPPER" desc="Accessibility role description for a stepper - a control where you can use up/down arrows to increment or decrement it. The name 'stepper' is how this user interface element is described by VoiceOver on Mac OS X; the translation should be consistent with VoiceOver.">
+ stepper
+ </message>
+ </if>
+ <message name="IDS_AX_ROLE_TOGGLE_BUTTON" desc="Accessibility role description for a toggle button">
+ toggle button
+ </message>
+ <message name="IDS_AX_ROLE_HEADER" desc="Accessibility role description for header">
+ header
+ </message>
+ <message name="IDS_AX_ROLE_HEADING" desc="Accessibility role description for headings">
+ heading
+ </message>
+ <message name="IDS_AX_ROLE_LINK" desc="Accessibility role description for link">
+ link
+ </message>
+ <message name="IDS_AX_ROLE_MAIN_CONTENT" desc="Accessibility role description for main content of the document.">
+ main
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-mark -->
+ <message name="IDS_AX_ROLE_MARK" desc="Accessibility role description for highlighted content.">
+ highlight
+ </message>
+ <message name="IDS_AX_ROLE_MATH" desc="Accessibility role description for math">
+ math
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-meter -->
+ <message name="IDS_AX_ROLE_METER" desc="Accessibility role description for a meter, for example a temperature indicator or progress bar">
+ meter
+ </message>
+ <message name="IDS_AX_ROLE_NAVIGATIONAL_LINK" desc="Accessibility role description for group of navigational links.">
+ navigation
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-output -->
+ <message name="IDS_AX_ROLE_OUTPUT" desc="Accessibility role description for output">
+ output
+ </message>
+ <message name="IDS_AX_ROLE_REGION" desc="Accessibility role description for region">
+ region
+ </message>
+ <!-- https://www.w3.org/TR/core-aam-1.1/#role-map-searchbox -->
+ <if expr="is_win">
+ <message name="IDS_AX_ROLE_SEARCH_BOX" desc="UIA role description for search text field">
+ search box
+ </message>
+ </if>
+ <if expr="not is_win">
+ <message name="IDS_AX_ROLE_SEARCH_BOX" desc="Accessibility role description for search text field">
+ search text field
+ </message>
+ </if>
+ <!-- https://w3c.github.io/html-aam/#el-section -->
+ <message name="IDS_AX_ROLE_SECTION" desc="Accessibility role description for a section of a document, like the main body text, the table of contents, a header, or a footer">
+ section
+ </message>
+ <message name="IDS_AX_ROLE_STATUS" desc="Accessibility role description for status">
+ status
+ </message>
+ <message name="IDS_AX_ROLE_SWITCH" desc="Accessibility role description for switch">
+ switch
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-input-tel -->
+ <message name="IDS_AX_ROLE_TELEPHONE" desc="Accessibility role description for telephone number input">
+ telephone
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-time -->
+ <message name="IDS_AX_ROLE_TIME" desc="Accessibility role description for a time">
+ time
+ </message>
+ <!-- https://w3c.github.io/html-aam/#el-input-url -->
+ <message name="IDS_AX_ROLE_URL" desc="Accessibility role description for URL input">
+ url
+ </message>
+ <message name="IDS_AX_ROLE_WEB_AREA" desc="Accessibility role description for web area">
+ HTML content
+ </message>
+ <message name="IDS_AX_ROLE_WEEK" desc="Accessibility role description for a week input">
+ week picker
+ </message>
+ <if expr="is_android">
+ <message name="IDS_AX_ROLE_ALERT" desc="Accessibility role description for an alert">
+ alert
+ </message>
+ <message name="IDS_AX_ROLE_ALERT_DIALOG" desc="Accessibility role description for an alert dialog">
+ alert_dialog
+ </message>
+ <message name="IDS_AX_ROLE_APPLICATION" desc="Accessibility role description for an application">
+ application
+ </message>
+ <message name="IDS_AX_ROLE_BLOCKQUOTE" desc="Accessibility role description for a blockquote">
+ blockquote
+ </message>
+ <message name="IDS_AX_ROLE_BUTTON" desc="Accessibility role description for a button">
+ button
+ </message>
+ <message name="IDS_AX_ROLE_COLUMN_HEADER" desc="Accessibility role description for a column header">
+ column header
+ </message>
+ <message name="IDS_AX_ROLE_COMBO_BOX" desc="Accessibility role description for a combo box, an editable text control with an associated drop-down list">
+ combo box
+ </message>
+ <message name="IDS_AX_ROLE_DATE_TIME" desc="Accessibility role description for a date / time picker">
+ date and time picker
+ </message>
+ <message name="IDS_AX_ROLE_DIALOG" desc="Accessibility role description for a dialog">
+ dialog
+ </message>
+ <message name="IDS_AX_ROLE_DIRECTORY" desc="Accessibility role description for a directory, for example a table of contents or list of employees">
+ directory
+ </message>
+ <message name="IDS_AX_ROLE_DOCUMENT" desc="Accessibility role description for a document">
+ document
+ </message>
+ <message name="IDS_AX_ROLE_EMBEDDED_OBJECT" desc="Accessibility role description for an embedded object, like a video inside a web page">
+ object
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHIC" desc="Accessibility role description for a graphic or image">
+ graphic
+ </message>
+ <message name="IDS_AX_ROLE_HEADING_WITH_LEVEL" desc="Accessibility role description for a heading with a heading level, for example 'heading 1' is the most important heading and 'heading 3' is less important">
+ heading <ph name="HEADING_LEVEL">$1<ex>1</ex></ph>
+ </message>
+ <message name="IDS_AX_ROLE_INPUT_TIME" desc="Accessibility role description for a time picker control">
+ time picker
+ </message>
+ <message name="IDS_AX_ROLE_LIST_BOX" desc="Accessibility role description for a list box control">
+ list box
+ </message>
+ <message name="IDS_AX_ROLE_LOG" desc="Accessibility role description for an information log, such as a chat log or error log">
+ log
+ </message>
+ <message name="IDS_AX_ROLE_MARQUEE" desc="Accessibility role description for a marquee, such as a stock ticker or ad banner that frequently changes">
+ marquee
+ </message>
+ <message name="IDS_AX_ROLE_MENU" desc="Accessibility role description for a menu">
+ menu
+ </message>
+ <message name="IDS_AX_ROLE_MENU_BAR" desc="Accessibility role description for a menu bar">
+ menu bar
+ </message>
+ <message name="IDS_AX_ROLE_MENU_BUTTON" desc="Accessibility role description for a menu button, a button that opens a menu">
+ menu button
+ </message>
+ <message name="IDS_AX_ROLE_MENU_ITEM" desc="Accessibility role description for a menu item">
+ menu item
+ </message>
+ <message name="IDS_AX_ROLE_NOTE" desc="Accessibility role description for a note">
+ note
+ </message>
+ <message name="IDS_AX_ROLE_POP_UP_BUTTON" desc="Accessibility role description for a pop up button">
+ pop up button
+ </message>
+ <message name="IDS_AX_ROLE_PROGRESS_INDICATOR" desc="Accessibility role description for a progress indicator">
+ progress indicator
+ </message>
+ <message name="IDS_AX_ROLE_RADIO" desc="Accessibility role description for a radio button">
+ radio button
+ </message>
+ <message name="IDS_AX_ROLE_RADIO_GROUP" desc="Accessibility role description for a group of related radio buttons">
+ radio group
+ </message>
+ <message name="IDS_AX_ROLE_ROW_HEADER" desc="Accessibility role description for a row header in a table">
+ row header
+ </message>
+ <message name="IDS_AX_ROLE_SCROLL_BAR" desc="Accessibility role description for a scroll bar">
+ scroll bar
+ </message>
+ <message name="IDS_AX_ROLE_SEARCH" desc="Accessibility role description for the section of a web page containing controls for searching the page or site">
+ search
+ </message>
+ <message name="IDS_AX_ROLE_SLIDER" desc="Accessibility role description for a slider">
+ slider
+ </message>
+ <message name="IDS_AX_ROLE_SPIN_BUTTON" desc="Accessibility role description for a spin button, a control containing a numerical value that can be incremented or decremented by 1">
+ spin button
+ </message>
+ <message name="IDS_AX_ROLE_SPLITTER" desc="Accessibility role description for a splitter, a control that splits the window in two pieces and can usually be dragged">
+ splitter
+ </message>
+ <message name="IDS_AX_ROLE_TAB" desc="Accessibility role description for a tab">
+ tab
+ </message>
+ <message name="IDS_AX_ROLE_TABLE" desc="Accessibility role description for a table">
+ table
+ </message>
+ <message name="IDS_AX_ROLE_TAB_LIST" desc="Accessibility role description for a tab list">
+ tab list
+ </message>
+ <message name="IDS_AX_ROLE_TAB_PANEL" desc="Accessibility role description for a tab panel, the part of the window that changes when selecting a new tab">
+ tab panel
+ </message>
+ <message name="IDS_AX_ROLE_TIMER" desc="Accessibility role description for a timer">
+ timer
+ </message>
+ <message name="IDS_AX_ROLE_TOOLBAR" desc="Accessibility role description for a toolbar">
+ toolbar
+ </message>
+ <message name="IDS_AX_ROLE_TOOLTIP" desc="Accessibility role description for a tooltip">
+ tooltip
+ </message>
+ <message name="IDS_AX_ROLE_TREE" desc="Accessibility role description for a tree">
+ tree
+ </message>
+ <message name="IDS_AX_ROLE_TREE_GRID" desc="Accessibility role description for a tree grid">
+ tree grid
+ </message>
+ <message name="IDS_AX_ROLE_TREE_ITEM" desc="Accessibility role description for a tree item">
+ tree item
+ </message>
+ </if>
+
+ <!-- Automatic image annotations for accessibility -->
+ <if expr="is_win">
+ <then>
+ <message name="IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION" desc="Accessibility role description for a graphic (image) on a web page or PDF that does not have a description for blind users.">
+ Unlabeled graphic
+ </message>
+ </then>
+ <else>
+ <message name="IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION" desc="Accessibility role description for an image on a web page or PDF that does not have a description for blind users.">
+ Unlabeled image
+ </message>
+ </else>
+ </if>
+ <message name="IDS_AX_IMAGE_ELIGIBLE_FOR_ANNOTATION" desc="Accessibility message spoken out loud to screen reader users to inform them that they can get a description of an image by opening the context menu.">
+ To get missing image descriptions, open the context menu.
+ </message>
+ <message name="IDS_AX_IMAGE_ANNOTATION_PENDING" desc="Accessibility message spoken out loud to screen reader users saying that the browser is in the middle of trying to get a description for an image.">
+ Getting description...
+ </message>
+ <message name="IDS_AX_IMAGE_ANNOTATION_ADULT" desc="Accessibility message spoken out loud to screen reader users indicating that an image appears to be something like nudity or pornography or other policy violation that is not appropriate for children.">
+ Appears to contain adult content. No description available.
+ </message>
+ <message name="IDS_AX_IMAGE_ANNOTATION_NO_DESCRIPTION" desc="Accessibility message spoken out loud to screen reader users indicating that the browser was unable to provide a description for an image.">
+ No description available.
+ </message>
+ <message name="IDS_AX_IMAGE_ANNOTATION_OCR_CONTEXT" desc="Accessibility message spoken out loud to screen reader users when reading text that was automatically extracted from an image, for an example the word 'stop' could be extracted from a photo of a stop sign. Because automatic text extraction sometimes contains errors it is important that the language used indicates some uncertainty - it may say 'stop' or it appears to say 'stop', not it definitely says 'stop'.">
+ Appears to say: <ph name="OCR_TEXT">$1<ex>Stop</ex></ph>
+ </message>
+ <message name="IDS_AX_IMAGE_ANNOTATION_DESCRIPTION_CONTEXT" desc="Accessibility message spoken out loud to screen reader users when reading a computer-generated description of an image, for example a photo of the president at a press conference might be described as 'A person at a podium'. Because automatic image description is sometimes incorrect, it is important that the langauge used indicates some uncertainty - it may be a person, it appears to be a person, not it definitely is a person.">
+ Appears to be: <ph name="DESCRIPTION">$1<ex>A person at a podium</ex></ph>
+ </message>
+
+ <message name="IDS_AX_AM_PM_FIELD_TEXT" desc="Accessible description of the AM/PM field in a date/time control">
+ AM/PM
+ </message>
+
+ <message name="IDS_AX_DAY_OF_MONTH_FIELD_TEXT" desc="Accessible description of the day of month field in a date/time control">
+ Day
+ </message>
+
+ <message name="IDS_AX_HOUR_FIELD_TEXT" desc="Accessible description of the hour field in a date/time control">
+ Hours
+ </message>
+
+ <message name="IDS_AX_MEDIA_DEFAULT" desc="Accessible description of a media control.">
+ media control
+ </message>
+
+ <message name="IDS_AX_MEDIA_AUDIO_ELEMENT" desc="Accessible description of audio">
+ audio
+ </message>
+
+ <message name="IDS_AX_MEDIA_VIDEO_ELEMENT" desc="Accessible description of video">
+ video
+ </message>
+
+ <message name="IDS_AX_MEDIA_MUTE_BUTTON" desc="Accessibility role description for mute button">
+ mute
+ </message>
+
+ <message name="IDS_AX_MEDIA_UNMUTE_BUTTON" desc="Accessibility role description for turn mute off button">
+ unmute
+ </message>
+
+ <message name="IDS_AX_MEDIA_PLAY_BUTTON" desc="Accessibility role description for play button">
+ play
+ </message>
+
+ <message name="IDS_AX_MEDIA_PAUSE_BUTTON" desc="Accessibility role description for pause button">
+ pause
+ </message>
+
+ <message name="IDS_AX_MEDIA_CURRENT_TIME_DISPLAY" desc="Accessibility role description for elapsed time display">
+ elapsed time: <ph name="ELAPSED_TIME">$1<ex>0:25</ex></ph>
+ </message>
+
+ <message name="IDS_AX_MEDIA_TIME_REMAINING_DISPLAY" desc="Accessibility role description for time remaining display">
+ remaining time: <ph name="REMAINING_TIME">$1<ex>3:25</ex></ph>
+ </message>
+
+ <message name="IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON" desc="Accessibility role description for enter fullscreen button">
+ enter full screen
+ </message>
+
+ <message name="IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON" desc="Accessibility role description for exit fullscreen button">
+ exit full screen
+ </message>
+
+ <message name="IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON" desc="Accessibility role description for display cutout fullscreen button">
+ toggle display cutout fullscreen
+ </message>
+
+ <message name="IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON" desc="Accessibility role description for enter Picture-in-Picture button">
+ enter picture-in-picture
+ </message>
+
+ <message name="IDS_AX_MEDIA_EXIT_PICTURE_IN_PICTURE_BUTTON" desc="Accessibility role description for exit Picture-in-Picture button">
+ exit picture-in-picture
+ </message>
+
+ <message name="IDS_AX_MEDIA_LOADING_PANEL" desc="Accessibility role description for the loading/buffering panel">
+ buffering
+ </message>
+
+ <message name="IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_MENU_BUTTON" desc="Accessibility role description for show closed captions menu button">
+ show closed captions menu
+ </message>
+
+ <message name="IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_MENU_BUTTON" desc="Accessibility role description for hide closed captions menu button">
+ hide closed captions menu
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_OFF_BUTTON" desc="Accessibility role description for remote playback button">
+ play on remote device
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_ON_BUTTON" desc="Accessibility role description for remote playback control button">
+ control remote playback
+ </message>
+
+ <message name="IDS_AX_MEDIA_DOWNLOAD_BUTTON" desc="Media controls download button.">
+ download media
+ </message>
+
+ <message name="IDS_AX_MEDIA_OVERFLOW_BUTTON" desc="Media controls overflow button.">
+ show more media controls
+ </message>
+
+ <message name="IDS_AX_MEDIA_AUDIO_ELEMENT_HELP" desc="Accessible help of audio controls">
+ audio
+ </message>
+
+ <message name="IDS_AX_MEDIA_VIDEO_ELEMENT_HELP" desc="Accessible help of video">
+ video
+ </message>
+
+ <message name="IDS_AX_MEDIA_AUDIO_SLIDER_HELP" desc="Accessibility help description for audio timeline slider">
+ audio time scrubber
+ </message>
+
+ <message name="IDS_AX_MEDIA_VIDEO_SLIDER_HELP" desc="Accessibility help description for video timeline slider">
+ video time scrubber
+ </message>
+
+ <message name="IDS_AX_MEDIA_VOLUME_SLIDER_HELP" desc="Accessibility help description for volume slider">
+ volume slider
+ </message>
+
+ <message name="IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP" desc="Accessibility help description for elapsed time display">
+ current time in seconds
+ </message>
+
+ <message name="IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP" desc="Accessibility help description for time remaining display">
+ number of seconds of video remaining
+ </message>
+
+ <message name="IDS_AX_MEDIA_OVERFLOW_BUTTON_HELP" desc="Accessibility help description for overflow button.">
+ more options
+ </message>
+
+ <message name="IDS_AX_MILLISECOND_FIELD_TEXT" desc="Accessible description of the millisecond field in a date/time control">
+ Milliseconds
+ </message>
+
+ <message name="IDS_AX_MINUTE_FIELD_TEXT" desc="Accessible description of the minute field in a date/time control">
+ Minutes
+ </message>
+
+ <message name="IDS_AX_MONTH_FIELD_TEXT" desc="Accessible description of the month field in a date/time control">
+ Month
+ </message>
+
+ <message name="IDS_AX_SECOND_FIELD_TEXT" desc="Accessible description of the second field in a date/time control">
+ Seconds
+ </message>
+
+ <message name="IDS_AX_WEEK_OF_YEAR_FIELD_TEXT" desc="Accessible description of the week of year field in a date/time control">
+ Week
+ </message>
+
+ <message name="IDS_AX_YEAR_FIELD_TEXT" desc="Accessible description of the year field in a date/time control">
+ Year
+ </message>
+
+ <message name="IDS_FORM_INPUT_WEEK_TEMPLATE" desc="A specific week (1-53) in a specific year shown in a form control">
+ Week <ph name="WEEKNUMBER">$2<ex>51</ex></ph>, <ph name="YEAR">$1<ex>2012</ex></ph>
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE" desc="Heading or short sentence shown when a file upload control in a webpage requires one or more files selected, but the user didn't specify any files.">
+ Please select one or more files.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH" desc="Heading or short sentence shown when a form control in a webpage requires specific type such as email address or URL, but the specified value does not comform to the type.">
+ Invalid value.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY" desc="Heading or short sentence shown when there is an email field in a form and a user specified an empty value.">
+ Please enter a non-empty email address.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_DOMAIN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'user@'.">
+ Please enter a part following '<ph name="ATSIGN">$1<ex>@</ex></ph>'. '<ph name="INVALIDADDRESS">$2<ex>user@</ex></ph>' is incomplete.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_LOCAL" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like '@example.com'.">
+ Please enter a part followed by '<ph name="ATSIGN">$1<ex>@</ex></ph>'. '<ph name="INVALIDADDRESS">$2<ex>@example.com</ex></ph>' is incomplete.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOMAIN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'user@example,com'.">
+ A part following '<ph name="ATSIGN">$1<ex>@</ex></ph>' should not contain the symbol '<ph name="INVALIDCHARACTER">$2<ex>,</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOTS" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value with wrong dots like 'user@example..com'.">
+ '<ph name="DOT">$1<ex>.</ex></ph>' is used at a wrong position in '<ph name="INVALIDDOMAIN">$2<ex>example..com</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_LOCAL" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'us,er@example.com'.">
+ A part followed by '<ph name="ATSIGN">$1<ex>@</ex></ph>' should not contain the symbol '<ph name="INVALIDCHARACTER">$2<ex>,</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_NO_AT_SIGN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'user'.">
+ Please include an '<ph name="ATSIGN">$1<ex>@</ex></ph>' in the email address. '<ph name="INVALIDADDRESS">$2<ex>user</ex></ph>' is missing an '<ph name="ATSIGN">$1<ex>@</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL" desc="Heading or short sentence shown there is a field which accepts multiple e-mail addresses and a user specified a value which is not a comma-separated e-mail addresses.">
+ Please enter a comma separated list of email addresses.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_UNDERFLOW" desc="Heading or short sentence shown when a form control value in a webpage needs to be larger than or equal to a minimum value specified by the page author, but a user specified a too small value.">
+ Value must be greater than or equal to <ph name="MINIMUM">$1<ex>0</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_UNDERFLOW_DATETIME" desc="Heading or short sentence shown when a form control value in a webpage needs to be later or equal to a minimum date/time value specified by the page author, but a user specified an earlier date/time.">
+ Value must be <ph name="MINIMUM_DATE_OR_TIME">$1<ex>01/04/2013</ex></ph> or later.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_OVERFLOW" desc="Heading or short sentence shown when a form control value in a webpage needs to be smaller than or equal to a maximum value specified by the page author, but a user specified a too large value.">
+ Value must be less than or equal to <ph name="MAXIMUM">$1<ex>100</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_OVERFLOW_DATETIME" desc="Heading or short sentence shown when a form control value in a webpage needs to be earlier than or equal to a maximum date/time value specified by the page author, but a user specified a later date/time.">
+ Value must be <ph name="MAXIMUM_DATE_OR_TIME">$1<ex>12/31/2013</ex></ph> or earlier.
+ </message>
+ <message name="IDS_FORM_VALIDATION_BAD_INPUT_DATETIME" desc="Heading or short sentence shown when a user specified an incomplete value or an invalid date (such as 02/31/2012) to a date/time form control in a webpage.">
+ Please enter a valid value. The field is incomplete or has an invalid date.
+ </message>
+ <message name="IDS_FORM_VALIDATION_BAD_INPUT_NUMBER" desc="Heading or short sentence shown when a user entered a non-number string to a number field in a webpage.">
+ Please enter a number.
+ </message>
+
+<!-- The following IDS_FORM_VALIDATION_* messages were taken from Mozilla's dom.properties file.
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mitch <mstoltz@netscape.com> (original author)
+# Ehsan Akhgari <ehsan.akhgari@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+-->
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING" desc="Heading or short sentence shown when a text form control in a webpage requires a value, but the user didn't specify any value.">
+ Please fill out this field.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX" desc="Heading or short sentence shown when a checkbox control in a webpage must be checked, but the user didn't check it.">
+ Please check this box if you want to proceed.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_FILE" desc="Heading or short sentence shown when a file upload control in a webpage requires a file selected, but the user didn't specify any file.">
+ Please select a file.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_RADIO" desc="Heading or short sentence shown when a radio button of a radio button group in a webpage must be selected, but the user selected nothing.">
+ Please select one of these options.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_SELECT" desc="Heading or short sentence shown when a value of a menu-list control in a webpage must be selected, but the user selected nothing.">
+ Please select an item in the list.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL" desc="Heading or short sentence shown when there is an email field in a form and a user specified a value which doesn't look like an e-mail address.">
+ Please enter an email address.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_URL" desc="Heading or short sentence shown when there is a URL field in a form and a user specified a value which doesn't look like a URL.">
+ Please enter a URL.
+ </message>
+ <message name="IDS_FORM_VALIDATION_PATTERN_MISMATCH" desc="Heading or short sentence shown when a form control value needs to satisfy a pattern specified by the page author, but a user specified unmatched value.">
+ Please match the requested format.
+ </message>
+ <message name="IDS_FORM_VALIDATION_STEP_MISMATCH" desc="Heading or short sentence shown when a form control value in a webpage should be aligned to a step value specified by the page author, but a user speficified non-aligned value. e.g. A number type field, minimum value is 0, and step value is 4. If A user-specified value is not a multiple of 4, this warning message is shown.">
+ Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW">$1<ex>4</ex></ph> and <ph name="VALID_VALUE_HIGHER">$2<ex>8</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT" desc="Heading or short sentence shown when a form control value in a webpage should be aligned to a step value specified by the page author, but a user speficified non-aligned value. e.g. A number type field, minimum value is 0, and step value is 4. If A user-specified value is not a multiple of 4, this warning message is shown.">
+ Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE">$1<ex>0</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TOO_LONG" desc="Heading or short sentence shown when a form control in a webpage needs to be shorter than a length specified by the page author, but a user specified long value.">
+ Please shorten this text to <ph name="MAX_CHARACTERS">$2<ex>100</ex></ph> characters or less (you are currently using <ph name="CURRENT_LENGTH">$1<ex>101</ex></ph> characters).
+ </message>
+ <message name="IDS_FORM_VALIDATION_TOO_SHORT" desc="Heading or short sentence shown when a form control in a webpage needs to be longer than a length specified by the page author, but a user specified a value of 1 character.">
+ Please lengthen this text to <ph name="MIN_CHARACTERS">$2<ex>101</ex></ph> characters or more (you are currently using 1 character).
+ </message>
+ <message name="IDS_FORM_VALIDATION_TOO_SHORT_PLURAL" desc="Heading or short sentence shown when a form control in a webpage needs to be longer than a length specified by the page author, but a user specified short value.">
+ Please lengthen this text to <ph name="MIN_CHARACTERS">$2<ex>101</ex></ph> characters or more (you are currently using <ph name="CURRENT_LENGTH">$1<ex>100</ex></ph> characters).
+ </message>
+
+ <message name="IDS_MEDIA_SESSION_FILE_SOURCE" desc="The name of the media session source if the media is a local file.">
+ Local File
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS" desc="Media controls overflow menu item label for a closed captions button. The text for this overflow menu should be short.">
+ Captions
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS_SUBMENU_TITLE" desc="Media controls overflow menu title for the closed captions submenu. The text for this overflow menu should be short.">
+ Options
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_CAST" desc="Media controls overflow menu item label for a cast button.">
+ Cast
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_ENTER_FULLSCREEN" desc="Media controls overflow menu item label for a button to enter fullscreen.">
+ Fullscreen
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_FULLSCREEN" desc="Media controls overflow menu item label for a button to exit fullscreen.">
+ Exit fullscreen
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_MUTE" desc="Media controls overflow menu item label for a mute button.">
+ Mute
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_UNMUTE" desc="Media controls overflow menu item label for an unmute button.">
+ Unmute
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_PLAY" desc="Media controls overflow menu item label for a play button.">
+ Play
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_PAUSE" desc="Media controls overflow menu item label for a pause button.">
+ Pause
+ </message>
+ <message name="IDS_MEDIA_OVERFLOW_MENU_DOWNLOAD" desc="Media controls overflow menu item label for a download button.">
+ Download
+ </message>
+ <if expr="is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_ENTER_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to enter Picture-in-Picture.">
+ Picture in Picture
+ </message>
+ </if>
+ <if expr="not is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_ENTER_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to enter Picture-in-Picture.">
+ Picture in picture
+ </message>
+ </if>
+ <if expr="is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to exit Picture-in-Picture.">
+ Exit Picture-in-Picture
+ </message>
+ </if>
+ <if expr="not is_macosx">
+ <message name="IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE" desc="Media controls overflow menu item label for a button to exit Picture-in-Picture.">
+ Exit picture-in-picture
+ </message>
+ </if>
+ <message name="IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT" desc="Text message shown to user when in picture in picture mode. When a video is in picture in picture mode, an interstitial with this text appears where the video player is positioned. The video continues to play back in another window that gives the experience that the video is 'popped out'.">
+ Playing in picture-in-picture
+ </message>
+ <message name="IDS_MEDIA_REMOTING_CAST_TEXT" desc="Text message shown to the user when casting a video to a known remote device.">
+ Now casting to <ph name="DEVICE_FRIENDLY_NAME">$1<ex>Living Room TV</ex></ph>
+ </message>
+ <message name="IDS_MEDIA_REMOTING_CAST_TO_UNKNOWN_DEVICE_TEXT" desc="Text message shown to the user when casting a video to an unknown remote device.">
+ Now casting to your TV
+ </message>
+ <message name = "IDS_MEDIA_REMOTING_STOP_TEXT" desc="The transient text shown on top of the video when switching from media remoting to mirroring.">
+ Switched to mirroring
+ </message>
+ <message name = "IDS_MEDIA_REMOTING_STOP_BY_PLAYBACK_QUALITY_TEXT" desc="The transient text shown on top of the video when switching from media remoting to mirroring due to poor playback quality.">
+ Poor playback quality
+ </message>
+ <message name = "IDS_MEDIA_REMOTING_STOP_BY_ERROR_TEXT" desc="The transient text shown on top of the video when switching from media remoting to mirroring due to errors.">
+ Video playback error
+ </message>
+ <message name="IDS_MEDIA_SCRUBBING_MESSAGE_TEXT" desc="Message informing the user that they can double tap to skip ten seconds. This should be no longer than twice the length of the English version.">
+ Double tap left or right to skip 10s
+ </message>
+ <message name="IDS_MEDIA_TRACKS_NO_LABEL" desc="Menu item label for a text track that has no name specified. The number represents the track number in the list of tracks.">
+ Track <ph name="NUMBER">$1<ex>1</ex></ph>
+ </message>
+
+ <message name="IDS_MEDIA_TRACKS_OFF" desc="Menu item label for a text track that represents disabling closed captions">
+ Off
+ </message>
+
+ <message name="IDS_PLUGIN_INITIALIZATION_ERROR" desc="A message displayed when a plugin failed to load">
+ Couldn't load plugin.
+ </message>
+
+ <message name="IDS_MEDIA_PLAYBACK_ERROR" desc="Message informing that the user that there were issues playing back their media.">
+ Unable to play media.
+ </message>
+
+ <!-- Byte size units -->
+ <message name="IDS_UNITS_KIBIBYTES" desc="Units tag indicating a quantity of kilobytes">
+ <ph name="QUANTITY">$1<ex>42.0</ex></ph> KB
+ </message>
+ <message name="IDS_UNITS_MEBIBYTES" desc="Units tag indicating a quantity of megabytes">
+ <ph name="QUANTITY">$1<ex>42.0</ex></ph> MB
+ </message>
+ <message name="IDS_UNITS_GIBIBYTES" desc="Units tag indicating a quantity of gigabytes">
+ <ph name="QUANTITY">$1<ex>42.0</ex></ph> GB
+ </message>
+ <message name="IDS_UNITS_TEBIBYTES" desc="Units tag indicating a quantity of terabytes">
+ <ph name="QUANTITY">$1<ex>42.0</ex></ph> TB
+ </message>
+ <message name="IDS_UNITS_PEBIBYTES" desc="Units tag indicating a quantity of petabytes">
+ <ph name="QUANTITY">$1<ex>42.0</ex></ph> PB
+ </message>
+
+ <message name="CONTENT_INVALID_TRUE" desc="Error message for aria-invalid = true">
+ Invalid entry
+ </message>
+ <message name="CONTENT_INVALID_SPELLING" desc="Error message for aria-invalid = spelling">
+ Invalid spelling
+ </message>
+ <message name="CONTENT_INVALID_GRAMMAR" desc="Error message for aria-invalid = grammar">
+ Invalid grammar
+ </message>
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/third_party/blink/public/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1 b/chromium/third_party/blink/public/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1
new file mode 100644
index 00000000000..7ae1cf665af
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/content_strings_grd/IDS_MEDIA_SESSION_FILE_SOURCE.png.sha1
@@ -0,0 +1 @@
+53ecf240f59804dfdb53d40001e317cee9284305 \ No newline at end of file
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
new file mode 100644
index 00000000000..5d6a3c8c39a
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_am.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="am">
+<translation id="1018939186200882850">የምናሌ ንጥል</translation>
+<translation id="10623998915015855">የማቀያየሪያ አዝራር</translation>
+<translation id="1088086359088493902">ሰኮንዶች</translation>
+<translation id="1171774979989969504">እባክዎ የኢሜይል አድራሻ ያስገቡ።</translation>
+<translation id="1178581264944972037">ለአፍታ አቁም</translation>
+<translation id="1188858454923323853">ማሟያ</translation>
+<translation id="1206619573307042055">መልሶ መልስ</translation>
+<translation id="1206693055195146388">ተንሸራታች</translation>
+<translation id="1211441953136645838">የግርጌ ማስታወሻ</translation>
+<translation id="1281252709823657822">መገናኛ</translation>
+<translation id="1335095011850992622">ክሬዲቶች</translation>
+<translation id="1342835525016946179">ጽሑፍ</translation>
+<translation id="1359897965706325498">ሰንደቅ</translation>
+<translation id="1589122976691792535">ክልል</translation>
+<translation id="1591562245178063882">በዚህ ወር</translation>
+<translation id="1637811476055996098">ፋይሎችን ይምረጡ</translation>
+<translation id="1650423536718072820">ጥቅስ</translation>
+<translation id="1727886345390570319">የተዘጉ የሥዕል መግለጫ ጽሑፎችን ምናሌ ደብቅ</translation>
+<translation id="1729654308190250600">እባክዎ ባዶ ያልሆነ የኢሜይል አድራሻ ያስገቡ።</translation>
+<translation id="1758486001363313524">ሌላ...</translation>
+<translation id="1806710327868736751">የማንቂያ_መገናኛ</translation>
+<translation id="1821985195704844674">የዛፍ ፍርግርግ</translation>
+<translation id="1822429046913737220">ጥዋት/ከሰዓት</translation>
+<translation id="1832974991323546415">በርቀት መሳሪያ ላይ አጫውት</translation>
+<translation id="190587075670221089">ስረዛ</translation>
+<translation id="1907737156431278478">ምሳሌ</translation>
+<translation id="1921819250265091946">ቀቀ</translation>
+<translation id="1930711995431081526">ሁኔታ</translation>
+<translation id="1938124657309484470">ዋጋ <ph name="MAXIMUM_DATE_OR_TIME" /> ወይም ከዚያ በፊት መሆን አለበት።</translation>
+<translation id="1946271899482435442">የቀን መልቀሚያ አሳይ</translation>
+<translation id="1993104285338243655">ወደ ማንጸባረቅ ተቀይሯል</translation>
+<translation id="2060505056492490888">«<ph name="DOT" />» በ«<ph name="INVALIDDOMAIN" />» ውስጥ በተሳሳተ ቦታ ላይ ነው የገባው።</translation>
+<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="2247351761944213033">ሳምንት <ph name="WEEKNUMBER" />፣ <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ትራክ <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">አመልካች ሳጥን</translation>
+<translation id="2311842470354187719">ገጽ ከፋይ</translation>
+<translation id="2335594187091864976">የቀን እና የሰዓት መራጭ</translation>
+<translation id="245932805758469625">የቪዲዮ ቀሪ ሰከንዶች ብዛት</translation>
+<translation id="248395913932153421">ቀን</translation>
+<translation id="2507943997699731163">እባክዎ ይህን መስክ ይሙሉት።</translation>
+<translation id="2508569020611168319">የትር ዝርዝር</translation>
+<translation id="2561842179657104141">ተጨማሪ የማህደረ መረጃ ቁጥጥሮችን አሳይ</translation>
+<translation id="2572483411312390101">አጫውት</translation>
+<translation id="2613802280814924224">እባክዎ የሚሰራ ዋጋ ያስገቡ። የሚቀርበው ዋጋ <ph name="VALID_VALUE" /> ነው።</translation>
+<translation id="2653659639078652383">አስገባ</translation>
+<translation id="2657045182931379222">ግራፊካዊ ነገር</translation>
+<translation id="2674318244760992338">ግርጌ</translation>
+<translation id="2709516037105925701">ራስ-ሙላ</translation>
+<translation id="2723001399770238859">ድምጽ</translation>
+<translation id="2725963129578236554">አስተያየቶች</translation>
+<translation id="2746543609216772311">ዋጋ <ph name="MINIMUM_DATE_OR_TIME" /> ወይም ከዚያ በኋላ መሆን አለበት።</translation>
+<translation id="2759744352195237655">የብቅ-ባይ አዝራር</translation>
+<translation id="2761667185364618470">ለመቀጠል ከፈለጉ እባክዎ ይህ ሳጥን ላይ ምልክት ያድርጉ።</translation>
+<translation id="2844350028562914727">ዝርዝሮች</translation>
+<translation id="2896972712917208084">የሬዲዮ ስብስብ</translation>
+<translation id="2908441821576996758">እባክዎ በኮማ የተለዩ የኢሜይል አድራሻዎች ዝርዝር ያስገቡ።</translation>
+<translation id="2940813599313844715">ነገር</translation>
+<translation id="3040011195152428237">አገናኝ</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> ሜባ</translation>
+<translation id="3075154866155599887">እባክዎ የሚሰራ ዋጋ ያስገቡ። መስኩ ያልተጠናቀቀ ነው ወይም ልክ ያልሆነ ቀን አለው።</translation>
+<translation id="3078740164268491126">ሠንጠረዥ</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">እባክዎ አንድ ዩአርኤል ያስገቡ።</translation>
+<translation id="3175736971608411871">ሰዓት ቆጣሪ</translation>
+<translation id="3199563858620722075">ጥምድ ሳጥን</translation>
+<translation id="3450233048674729344">ዋጋ ከ<ph name="MAXIMUM" /> የሚያንስ ወይም ከእሱ እኩል መሆን አለበት።</translation>
+<translation id="3486220673238053218">ብየና</translation>
+<translation id="3557673793733683882">አርዕስት <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">ሳምንት መራጭ</translation>
+<translation id="3685101356851116974">መሰየሚያ ያልተሰጠው ምስል</translation>
+<translation id="3706100364254443312">ቀይር</translation>
+<translation id="3732799496749320381">ሚሜ</translation>
+<translation id="3754210790023674521">ከሥዕል-ውስጥ-ሥዕል ውጣ</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> ጊባ</translation>
+<translation id="3808586225841795776">የጊዜ ቆይታ</translation>
+<translation id="3822383571486410024">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ቁምፊዎች ወይም ከዚያ በላይ ያራዝሙት (አሁን እየተጠቀሙ ያሉት <ph name="CURRENT_LENGTH" />ቁምፊዎችን ነው)።</translation>
+<translation id="383465348367842624">ከ«<ph name="ATSIGN" />» በፊት የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
+<translation id="3846214748874656680">ከሙሉ ማያገጽ ውጣ</translation>
+<translation id="3889183436948184105">ክለሳ</translation>
+<translation id="3920932319529768807">ድምዳሜ</translation>
+<translation id="3924558731517983934">መተግበሪያ</translation>
+<translation id="3944740393230681990">ቅድመ-ታሪክ</translation>
+<translation id="3960700977367013758">የማሸብለያ አሞሌ</translation>
+<translation id="4103419683916926126">ሚሊሰኮንዶች</translation>
+<translation id="4151657705144244502">ግራፊክ</translation>
+<translation id="4160057747563657758">ስልክ</translation>
+<translation id="4193965531860883258">መቅድም</translation>
+<translation id="4201051445878709314">ቀዳሚውን ወር አሳይ</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">የምናሌ አሞሌ</translation>
+<translation id="4360991593054037559">እባክዎ የሚሰራ ዋጋ ያስገቡ። ሁለቱ የሚቀርቡ ዋጋዎች <ph name="VALID_VALUE_LOW" /> እና <ph name="VALID_VALUE_HIGHER" /> ናቸው።</translation>
+<translation id="4384583879834880242">ጥያቄ እና መልስ</translation>
+<translation id="4413860115965805769">የምናሌ አዝራር</translation>
+<translation id="4444765639179266822">እንዲህ የሚል ይመስላል፦ <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">የሙዳየ ቃላት ዋቢ</translation>
+<translation id="4522570452068850558">ዝርዝሮች</translation>
+<translation id="4542388879936266156">ቀሪ ጊዜ፦ <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ቅጽ</translation>
+<translation id="4661075872484491155">ዛፍ</translation>
+<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
+<translation id="4668956016107839909">ቅጥያዎች</translation>
+<translation id="4718048029184481307">በሥዕል-ውስጥ-ሥዕልን በማጫወት ላይ</translation>
+<translation id="4742539557769756338">ሽፋን</translation>
+<translation id="4748357248530471599">የተቆረጠው የማሳያ ክፍል ሙሉ ማያ ገጽን ይቀያይሩ</translation>
+<translation id="4757246831282535685">የትር ፓነል</translation>
+<translation id="4763480195061959176">ቪዲዮ</translation>
+<translation id="479989351350248267">ፈልግ</translation>
+<translation id="4812940957355064477">እባክዎ ቁጥር ያስገቡ።</translation>
+<translation id="4912536737030637138">የዋቢ መጽሐፍት ግቤት</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ተመርጠዋል</translation>
+<translation id="4992066212339426712">ድምጸ-ከል አንሳ</translation>
+<translation id="49969490063480558">እባክዎ ከ«<ph name="ATSIGN" />» በኋላ አንድ ክፍል ያስገቡ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
+<translation id="5034860022980953847">የሂደት አመልካች</translation>
+<translation id="5090250355906949916">የቪዲዮ ጊዜ አንፏቃቂ</translation>
+<translation id="5093189678851173835">የተቀረጸ ጽሑፍ</translation>
+<translation id="5117590920725113268">ቀጣዩን ወር አሳይ</translation>
+<translation id="512758898067543763">የረድፍ ራስጌ</translation>
+<translation id="5143125788380636750">ድሕረ ታሪክ</translation>
+<translation id="5164977714490026579">ዋጋ ከ<ph name="MINIMUM" /> የሚበልጥ ወይም ከእሱ እኩል መሆን አለበት።</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> ፔታ</translation>
+<translation id="5307600278924710095">እባክዎ አንድ ክፍል ያስገቡና «<ph name="ATSIGN" />»ን ያስከትሉ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
+<translation id="5334352251556557839">ሚዲያን ማጫወት አልተቻለም።</translation>
+<translation id="5406322316791861025">ምስል</translation>
+<translation id="5453733299334684579">የዛፍ ንጥል</translation>
+<translation id="5466621249238537318">እባክዎ አንድ ወይም ተጨማሪ ፋይሎችን ይምረጡ።</translation>
+<translation id="5468998798572797635">ከሙሉ ማያ ገጽ ውጣ</translation>
+<translation id="5516424706154626233">ቀን መራጭ</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">ድምፅ-ከልን አንሳ</translation>
+<translation id="5608153257855394627">አድምቅ</translation>
+<translation id="561939826962581046">ሰዓት</translation>
+<translation id="5630795885300617244">10 ሴ ለመዝለል ወደ ግራ ወይም ቀኝ ሁለቴ መታ ያድርጉ</translation>
+<translation id="5631759159893697722">ረቂቅ</translation>
+<translation id="5643186887447432888">አዝራር</translation>
+<translation id="5677946354068040947">ተጨማሪ አማራጮች</translation>
+<translation id="576709008726043716">መግቢያ</translation>
+<translation id="57838592816432529">ድምጽ ይዝጉ</translation>
+<translation id="5860033963881614850">አጥፋ</translation>
+<translation id="588258955323874662">ሙሉ ገጽ ዕይታ</translation>
+<translation id="5888666972993069672">አሁን ወደ <ph name="DEVICE_FRIENDLY_NAME" /> cast በማድረግ ላይ</translation>
+<translation id="591047860372322273">የፍለጋ ሳጥን</translation>
+<translation id="5939518447894949180">ዳግም አስጀምር</translation>
+<translation id="5966707198760109579">ሳምንት</translation>
+<translation id="5987525920412732405">ማሾሪያ አዝራር</translation>
+<translation id="6011459053400940133">የድምጽ ተንሸራታች</translation>
+<translation id="6015796118275082299">ዓመት</translation>
+<translation id="6023896073578205740">የዝርዝር ሳጥን</translation>
+<translation id="6150588977291308318">ዋቢ መጽሐፍት</translation>
+<translation id="6164829606128959761">ሜትር</translation>
+<translation id="6166809985690652833">ድሕረ ቃል</translation>
+<translation id="6209276755895393898">ይህ ይመስላል፦ <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">ሙዳየ ቃላት</translation>
+<translation id="6281763101136022427">ዩአርኤል</translation>
+<translation id="6310801910862476708">ከስዕል-ውስጥ-ስዕል ውጣ</translation>
+<translation id="6398862346408813489">የወር መምረጫ ፓነል አሳይ</translation>
+<translation id="6404546809543547843">የኦዲዮ ሰዓት አንፏቃቂ</translation>
+<translation id="6443871981718447451">የተዘጉ የመግለጫ ጽሁፎችን ምናሌ አሳይ</translation>
+<translation id="6453774872122745852">ምስጋና</translation>
+<translation id="6475115390776617481">የቀጥታ ተገኝነት</translation>
+<translation id="648732519525291180">ሰዓት መራጭ</translation>
+<translation id="6550675742724504774">አማራጮች</translation>
+<translation id="6572309429103589720">ልክ ያልኾነ ሰዋሰው</translation>
+<translation id="658823671542763450">ወደ ሙሉ ገጽ ዕይታ ግባ</translation>
+<translation id="663493177488814956">ምግብ</translation>
+<translation id="6637586476836377253">የምዝግብ ማስታወሻ</translation>
+<translation id="6643016212128521049">አጽዳ</translation>
+<translation id="668171684555832681">ሌላ…</translation>
+<translation id="6692633176391053278">አስኪያጅ</translation>
+<translation id="6709570249143506788">ደካማ የመልሶ ማጫወት ጥራት</translation>
+<translation id="6755330956360078551">ጠቃሚ የመሣሪያ ምክር</translation>
+<translation id="6790428901817661496">አጫውት</translation>
+<translation id="6820355525329141109">ተሰኪን መጫን አልተቻለም።</translation>
+<translation id="6820615603175220800">የዋቢ መጽሐፍት ማጣቀሻ</translation>
+<translation id="6843725295806269523">ድምጸ-ከል ያድርጉ</translation>
+<translation id="6885760532393684712">ማውጫ</translation>
+<translation id="689129560213475294">ኮሎፎን</translation>
+<translation id="6934078000481955284">የጽሑፍ ጥቅስ</translation>
+<translation id="693476918119313863">ራስጌ</translation>
+<translation id="6941933287844615239">ማህደረ መረጃን አውርድ</translation>
+<translation id="6981594929165378967">ማስገባት</translation>
+<translation id="6989848892321993519">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ወይም ከዚያ በላይ ቁምፊዎች ያራዝሙት (አሁን እየተጠቀሙ ያሉት 1 ቁምፊ ነው)።</translation>
+<translation id="7034405885550056553">የአስተያየት ጥቆማ</translation>
+<translation id="709897737746224366">እባክዎ የተጠየቀውን ቅርጸት ያዛምዱ።</translation>
+<translation id="7118469954320184356">ምንም መግለጫ የለም።</translation>
+<translation id="7139483182332611405">መቅድም</translation>
+<translation id="7214187073215825913">የይዘት መረጃ</translation>
+<translation id="7263440858009898357">እባክዎ በዝርዝሩ ውስጥ አንድ ንጥል ይምረጡ።</translation>
+<translation id="727747134524199931">የአምድ ራስጌ</translation>
+<translation id="7320576522385648310">በማቋት ላይ</translation>
+<translation id="7353453495576941748">ክሬዲት</translation>
+<translation id="7364796246159120393">ፋይል ምረጥ</translation>
+<translation id="739024184232394898">ሌላ...</translation>
+<translation id="7405738980073107433">ግርጌ ማስታወሻዎች</translation>
+<translation id="7410239719251593705">የአዋቂ ይዘት የያዘ ይመስላል። ምንም መግለጫ የለም።</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> ቴባ</translation>
+<translation id="7491962110804786152">TAB</translation>
+<translation id="7514365320538308">አውርድ</translation>
+<translation id="7529102961911894712">የጀርባ አገናኝ</translation>
+<translation id="7533959249147584474">ያልተሰየመ ግራፊክ</translation>
+<translation id="7647456547678091388">ጠቃሚ ምክር</translation>
+<translation id="7661956066982048809">ግራፊካዊ ሰነድ</translation>
+<translation id="7673697353781729403">ሰዓቶች</translation>
+<translation id="7681220483256441252">መረጃ ጠቋሚ</translation>
+<translation id="7740050170769002709">የኤች ቲ ኤም ኤል ይዘት</translation>
+<translation id="7745230546936012372">የጎደሉ የምስል ዝርዝር መግለጫዎችን ለማግኘት፣ የአውድ ምናሌውን ይክፈቱ።</translation>
+<translation id="7750228210027921155">በሥዕል ውስጥ ሥዕል</translation>
+<translation id="775297008183122718">ትክክል ያልሆነ አገባብ </translation>
+<translation id="7789962463072032349">ላፍታ አቁም</translation>
+<translation id="7802800022689234070">ይፋ ማሳወቂያ ሶስት ማዕዘን</translation>
+<translation id="7888071071722539607">እባክዎ በኢሜይል አድራሻው ውስጥ «<ph name="ATSIGN" />» ያካትቱ። «<ph name="INVALIDADDRESS" />» ውስጥ «<ph name="ATSIGN" />» ይጎድላል።</translation>
+<translation id="7891486169920085145">መክፈያ</translation>
+<translation id="795667975304826397">ምንም ፋይል አልተመረጠም</translation>
+<translation id="8053789581856978548">የጽሑፍ መስክ ፈልግ</translation>
+<translation id="8057695513531652401">ማስታወቂያ</translation>
+<translation id="8105797009065549151">ማስታወሻ ማጣቀሻ</translation>
+<translation id="811583516810654505">ዝርዝርን በማግኘት ላይ...</translation>
+<translation id="8117451130807776954">በዚህ ሳምንት</translation>
+<translation id="8199524924445686405">ዓዓዓዓ</translation>
+<translation id="8208673686607688524">አካባቢያዊ ቀን እና ሰዓት መራጭ</translation>
+<translation id="8261464734335370856">ልክ ያልኾነ ሥርዓተ አጻጻፍ</translation>
+<translation id="8284326494547611709">መግለጫ ጽሑፎች</translation>
+<translation id="8346634859695247203">ክፍል</translation>
+<translation id="835897206747267392">ልክ ያልሆነ እሴት።</translation>
+<translation id="8403857369060869934">ያለፈው ጊዜ፦ <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">ክፍለ አካል</translation>
+<translation id="8433900881053900389">የመሣሪያ አሞሌ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ፋይሎች</translation>
+<translation id="8451268428117625855">እባክዎ ፋይል ይምረጡ።</translation>
+<translation id="8461852803063341183">የሬዲዮ አዝራር</translation>
+<translation id="8474886197722836894">መታሰቢያነቱ</translation>
+<translation id="8531739829932800271">እርማት</translation>
+<translation id="8534579021159131403">ደቂቃዎች</translation>
+<translation id="8541249477527128034">የማህደረ መረጃ ቁጥጥር</translation>
+<translation id="8550857728288566671">ሥዕላዊ ምልክት</translation>
+<translation id="8583702881314752957">የብየና ዝርዝር</translation>
+<translation id="8597182159515967513">ርዕስ</translation>
+<translation id="860475260694818407">ማውጫ</translation>
+<translation id="8613126697340063924">በርቀት መልሶ ማጫወትን ተቆጣጠር</translation>
+<translation id="862370744433916922">የግርጌ ጽሑፍ</translation>
+<translation id="8711688047404765493">ውጽዓት</translation>
+<translation id="8750798805984357768">እባክዎ ከእነዚህ አማራጮች ውስጥ አንዱን ይምረጡ።</translation>
+<translation id="8808573423886751634">ምዕራፍ</translation>
+<translation id="8822203815165896261">የደራሲ መረጃ</translation>
+<translation id="8845239796550121995">አሁን ወደ የእርስዎ ቴሌቪዥን cast በማድረግ ላይ</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">የቪዲዮ መልሶ ማጫወት ስህተት</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> ኪባ</translation>
+<translation id="8987927404178983737">ወር</translation>
+<translation id="901493112792887934">የአሁኑ ጊዜ በሰከንዶች</translation>
+<translation id="901834265349196618">ኢሜይል</translation>
+<translation id="9048119486235211610">አሰሳ</translation>
+<translation id="9062295712474918030">ሰነድ</translation>
+<translation id="9093215626363556771">ከስዕል-ውስጥ-ስዕል ውጣ</translation>
+<translation id="9108370397979208512">ሒሳብ</translation>
+<translation id="9132465097189459683">ሌላ...</translation>
+<translation id="9138385573473225930">ማንቂያ</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />፣ የሚጀምረው በ<ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">በሥዕል ላይ ሥዕል</translation>
+<translation id="9168329111483466115">የግርጌ ማስታወሻ</translation>
+<translation id="954003015749068518">ወደ ስዕል-ውስጥ-ስዕል ይግቡ</translation>
+<translation id="966787709310836684">ምናሌ</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..4b081853065
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ar.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ar">
+<translation id="1018939186200882850">عنصر القائمة</translation>
+<translation id="10623998915015855">زر التبديل</translation>
+<translation id="1088086359088493902">ثوانٍ‬‬</translation>
+<translation id="1171774979989969504">يُرجى إدخال عنوان البريد الإلكتروني.</translation>
+<translation id="1178581264944972037">الإيقاف مؤقتًا</translation>
+<translation id="1188858454923323853">تكميلي</translation>
+<translation id="1206619573307042055">صورة بها نص متحرك</translation>
+<translation id="1206693055195146388">شريط تمرير</translation>
+<translation id="1211441953136645838">تعليق ختامي</translation>
+<translation id="1281252709823657822">مربع حوار</translation>
+<translation id="1335095011850992622">إسهامات</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">إعلان بانر</translation>
+<translation id="1589122976691792535">منطقة</translation>
+<translation id="1591562245178063882">هذا الشهر</translation>
+<translation id="1637811476055996098">اختيار الملفات</translation>
+<translation id="1650423536718072820">اقتباس مستمد</translation>
+<translation id="1727886345390570319">إخفاء قائمة مقاطع الترجمة والشرح</translation>
+<translation id="1729654308190250600">يُرجى إدخال عنوان البريد الإلكتروني وعدم ترك الحق فارغًا.</translation>
+<translation id="1758486001363313524">آخر...</translation>
+<translation id="1806710327868736751">مربع حوار_للتنبيه</translation>
+<translation id="1821985195704844674">شبكة متفرعة</translation>
+<translation id="1822429046913737220">صباحًا/مساءً</translation>
+<translation id="1832974991323546415">تشغيل على جهاز بعيد</translation>
+<translation id="190587075670221089">حذف</translation>
+<translation id="1907737156431278478">مثال</translation>
+<translation id="1921819250265091946">يوم</translation>
+<translation id="1930711995431081526">الحالة</translation>
+<translation id="1938124657309484470">يجب أن تكون القيمة <ph name="MAXIMUM_DATE_OR_TIME" /> أو قبل ذلك.</translation>
+<translation id="1946271899482435442">عرض منتقي التاريخ</translation>
+<translation id="1993104285338243655">تم التبديل إلى النسخ المطابق.</translation>
+<translation id="2060505056492490888">تم استخدام "<ph name="DOT" />" في موضع خاطئ في "<ph name="INVALIDDOMAIN" />".</translation>
+<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="2247351761944213033">الأسبوع <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">المقطع الصوتي <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">مربع اختيار</translation>
+<translation id="2311842470354187719">فاصل صفحة</translation>
+<translation id="2335594187091864976">منتقي التاريخ والوقت</translation>
+<translation id="245932805758469625">عدد الثواني المتبقية من الفيديو</translation>
+<translation id="248395913932153421">يوم</translation>
+<translation id="2507943997699731163">يُرجى ملء هذا الحقل.</translation>
+<translation id="2508569020611168319">قائمة علامات التبويب</translation>
+<translation id="2561842179657104141">عرض المزيد من عناصر التحكم في الوسائط</translation>
+<translation id="2572483411312390101">تشغيل</translation>
+<translation id="2613802280814924224">يُرجى إدخال قيمة صالحة. علمًا بأن أقرب قيمة صالحة هي <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">إرسال</translation>
+<translation id="2657045182931379222">كائن رسومي</translation>
+<translation id="2674318244760992338">تذييل</translation>
+<translation id="2709516037105925701">الملء التلقائي</translation>
+<translation id="2723001399770238859">الصوت</translation>
+<translation id="2725963129578236554">التعليقات</translation>
+<translation id="2746543609216772311">يجب أن تكون القيمة <ph name="MINIMUM_DATE_OR_TIME" /> أو بعد ذلك.</translation>
+<translation id="2759744352195237655">زر بقائمة منبثقة</translation>
+<translation id="2761667185364618470">يُرجى تحديد هذا المربع إذا أردت المتابعة.</translation>
+<translation id="2844350028562914727">التفاصيل</translation>
+<translation id="2896972712917208084">مجموعة أزرار الاختيار</translation>
+<translation id="2908441821576996758">يُرجى إدخال قائمة مفصولة بفواصل لعناوين البريد الإلكتروني.</translation>
+<translation id="2940813599313844715">كائن</translation>
+<translation id="3040011195152428237">رابط</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> ميغابايت</translation>
+<translation id="3075154866155599887">يرجى إدخال قيمة صالحة. الحقل غير مكتمل أو أن التاريخ غير صالح.</translation>
+<translation id="3078740164268491126">جدول</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">‏يُرجى إدخال عنوان URL.</translation>
+<translation id="3175736971608411871">الموقّت</translation>
+<translation id="3199563858620722075">مربع تحرير وسرد</translation>
+<translation id="3450233048674729344">يجب أن تكون القيمة أقل من أو تساوي <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">تعريف</translation>
+<translation id="3557673793733683882">عنوان <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">منتقي الأسبوع</translation>
+<translation id="3685101356851116974">صورة غير مُصنَّفة</translation>
+<translation id="3706100364254443312">تبديل</translation>
+<translation id="3732799496749320381">شهر</translation>
+<translation id="3754210790023674521">الخروج من وضع "نافذة ضمن نافذة"</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> غيغابايت</translation>
+<translation id="3808586225841795776">عبارة</translation>
+<translation id="3822383571486410024">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت تستخدم حاليًا <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
+<translation id="383465348367842624">الجزء المتبوع بالعلامة "<ph name="ATSIGN" />" يجب ألا يشتمل على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">خروج من عرض ملء الشاشة</translation>
+<translation id="3889183436948184105">المراجعة</translation>
+<translation id="3920932319529768807">خاتمة</translation>
+<translation id="3924558731517983934">التطبيق</translation>
+<translation id="3944740393230681990">فاتحة</translation>
+<translation id="3960700977367013758">شريط التمرير</translation>
+<translation id="4103419683916926126">مللي ثانية</translation>
+<translation id="4151657705144244502">الرسم</translation>
+<translation id="4160057747563657758">هاتف</translation>
+<translation id="4193965531860883258">مقدمة</translation>
+<translation id="4201051445878709314">عرض الشهر السابق</translation>
+<translation id="421884353938374759">علبة الألوان</translation>
+<translation id="4248100235867064564">شريط قوائم</translation>
+<translation id="4360991593054037559">يُرجى إدخال قيمة صالحة. علمًا بأن القيم الصالحة تتراوح بين <ph name="VALID_VALUE_LOW" /> و<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">سين وجيم</translation>
+<translation id="4413860115965805769">زر القائمة</translation>
+<translation id="4444765639179266822">يبدو أنه يقول: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">مرجع مسرد مصطلحات</translation>
+<translation id="4522570452068850558">التفاصيل</translation>
+<translation id="4542388879936266156">الوقت المتبقي: <ph name="REMAINING_TIME" />ّ</translation>
+<translation id="4597532268155981612">نموذج</translation>
+<translation id="4661075872484491155">متفرع</translation>
+<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">ملحق</translation>
+<translation id="4718048029184481307">تشغيل في وضع "نافذة ضمن النافذة"</translation>
+<translation id="4742539557769756338">غلاف</translation>
+<translation id="4748357248530471599">تبديل صورة مقطوعة للشاشة إلى وضع ملء الشاشة</translation>
+<translation id="4757246831282535685">لوحة علامة التبويب</translation>
+<translation id="4763480195061959176">فيديو</translation>
+<translation id="479989351350248267">بحث</translation>
+<translation id="4812940957355064477">يُرجى إدخال عدد.</translation>
+<translation id="4912536737030637138">إدخال قائمة مراجع</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> محددة</translation>
+<translation id="4992066212339426712">إعادة الصوت</translation>
+<translation id="49969490063480558">يُرجى إدخال الجزء الذي يلي العلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
+<translation id="5034860022980953847">مؤشر التقدم</translation>
+<translation id="5090250355906949916">شريط تمرير وقت الفيديو</translation>
+<translation id="5093189678851173835">عبارة مقتبسة</translation>
+<translation id="5117590920725113268">عرض الشهر التالي</translation>
+<translation id="512758898067543763">عنوان الصف</translation>
+<translation id="5143125788380636750">تتِّمة</translation>
+<translation id="5164977714490026579">يجب أن تكون القيمة أكبر من أو تساوي <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> بيتابايت</translation>
+<translation id="5307600278924710095">يُرجى إدخال جزء متبوع بعلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
+<translation id="5334352251556557839">تعذّر تشغيل الوسائط</translation>
+<translation id="5406322316791861025">شكل</translation>
+<translation id="5453733299334684579">عنصر متفرع</translation>
+<translation id="5466621249238537318">يُرجى تحديد ملف واحد أو أكثر.</translation>
+<translation id="5468998798572797635">إنهاء وضع ملء الشاشة</translation>
+<translation id="5516424706154626233">منتقي التاريخ</translation>
+<translation id="5537725057119320332">إرسال</translation>
+<translation id="5546461542133609677">إعادة الصوت</translation>
+<translation id="5608153257855394627">تمييز</translation>
+<translation id="561939826962581046">الوقت</translation>
+<translation id="5630795885300617244">انقر مرّتين جهة اليمين أو اليسار لتخطي 10 ثوانٍ.</translation>
+<translation id="5631759159893697722">نبذة مختصرة</translation>
+<translation id="5643186887447432888">زر</translation>
+<translation id="5677946354068040947">خيارات إضافية</translation>
+<translation id="576709008726043716">مقدمة</translation>
+<translation id="57838592816432529">كتم الصوت</translation>
+<translation id="5860033963881614850">غير مفعّل</translation>
+<translation id="588258955323874662">ملء الشاشة</translation>
+<translation id="5888666972993069672">يتم الإرسال الآن إلى <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">مربع البحث</translation>
+<translation id="5939518447894949180">إعادة الضبط</translation>
+<translation id="5966707198760109579">الأسبوع</translation>
+<translation id="5987525920412732405">زر الدوران</translation>
+<translation id="6011459053400940133">شريط تمرير مستوى الصوت</translation>
+<translation id="6015796118275082299">عام</translation>
+<translation id="6023896073578205740">مربع القائمة</translation>
+<translation id="6150588977291308318">قائمة مراجع</translation>
+<translation id="6164829606128959761">متر</translation>
+<translation id="6166809985690652833">كلمة ختامية</translation>
+<translation id="6209276755895393898">يبدو أن: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">مسرد مصطلحات</translation>
+<translation id="6281763101136022427">‏عنوان URL</translation>
+<translation id="6310801910862476708">الخروج من وضع "نافذة ضمن نافذة"</translation>
+<translation id="6398862346408813489">عرض لوحة تحديد الشهر</translation>
+<translation id="6404546809543547843">شريط تمرير وقت الصوت</translation>
+<translation id="6443871981718447451">عرض قائمة مقاطع الترجمة والشرح</translation>
+<translation id="6453774872122745852">شكر وتقدير</translation>
+<translation id="6475115390776617481">الحضور المباشر</translation>
+<translation id="648732519525291180">منتقي الوقت</translation>
+<translation id="6550675742724504774">خيارات</translation>
+<translation id="6572309429103589720">قواعد لغوية غير صالحة</translation>
+<translation id="658823671542763450">تشغيل وضع ملء الشاشة</translation>
+<translation id="663493177488814956">البطاقات</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">محو</translation>
+<translation id="668171684555832681">ملف تعريف آخر...</translation>
+<translation id="6692633176391053278">تخطي</translation>
+<translation id="6709570249143506788">جودة التشغيل ضعيفة.</translation>
+<translation id="6755330956360078551">تلميح</translation>
+<translation id="6790428901817661496">التشغيل</translation>
+<translation id="6820355525329141109">تعذر تحميل المكوّن الإضافي.</translation>
+<translation id="6820615603175220800">مرجع قائمة مراجع</translation>
+<translation id="6843725295806269523">كتم الصوت</translation>
+<translation id="6885760532393684712">الدليل</translation>
+<translation id="689129560213475294">إشارة ناشر</translation>
+<translation id="6934078000481955284">علامة اقتباس فقرة</translation>
+<translation id="693476918119313863">عنوان</translation>
+<translation id="6941933287844615239">تنزيل وسائط</translation>
+<translation id="6981594929165378967">إدراج</translation>
+<translation id="6989848892321993519">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت الآن تستخدم حرفًا واحدًا).</translation>
+<translation id="7034405885550056553">اقتراح</translation>
+<translation id="709897737746224366">يُرجى مطابقة التنسيق المطلوب.</translation>
+<translation id="7118469954320184356">لا يتوفر أي وصف.</translation>
+<translation id="7139483182332611405">تمهيد</translation>
+<translation id="7214187073215825913">معلومات المحتوى</translation>
+<translation id="7263440858009898357">يُرجى تحديد عنصر من القائمة.</translation>
+<translation id="727747134524199931">عنوان العمود</translation>
+<translation id="7320576522385648310">التخزين مؤقتًا</translation>
+<translation id="7353453495576941748">إسهام</translation>
+<translation id="7364796246159120393">اختيار ملفّ</translation>
+<translation id="739024184232394898">آخر...</translation>
+<translation id="7405738980073107433">تعليقات ختامية</translation>
+<translation id="7410239719251593705">يبدو أنه يحتوي على محتوى للبالغين. لا يتوفر أي وصف.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> تيرابايت</translation>
+<translation id="7491962110804786152">علامة تبويب</translation>
+<translation id="7514365320538308">تنزيل</translation>
+<translation id="7529102961911894712">رابط رجوع</translation>
+<translation id="7533959249147584474">رسم غير مصنّف</translation>
+<translation id="7647456547678091388">نصيحة</translation>
+<translation id="7661956066982048809">مستند رسومي</translation>
+<translation id="7673697353781729403">ساعات</translation>
+<translation id="7681220483256441252">فهرس</translation>
+<translation id="7740050170769002709">‏محتوى HTML</translation>
+<translation id="7745230546936012372">للحصول على أوصاف الصور غير المتوفّرة، افتح قائمة السياقات.</translation>
+<translation id="7750228210027921155">نافذة ضمن النافذة</translation>
+<translation id="775297008183122718">إدخال غير صالح</translation>
+<translation id="7789962463072032349">إيقاف مؤقت</translation>
+<translation id="7802800022689234070">مثلث الإفصاح</translation>
+<translation id="7888071071722539607">يُرجى تضمين العلامة "<ph name="ATSIGN" />" في عنوان البريد الإلكتروني، حيث يفتقر "<ph name="INVALIDADDRESS" />" إلى العلامة "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">أداة التقسيم</translation>
+<translation id="795667975304826397">ّلم يتمّ اختيار أيّ ملفّ</translation>
+<translation id="8053789581856978548">الحقل النصي للبحث</translation>
+<translation id="8057695513531652401">ملاحظة</translation>
+<translation id="8105797009065549151">ملاحظة مرجعية</translation>
+<translation id="811583516810654505">جارٍ الحصول على وصف...</translation>
+<translation id="8117451130807776954">هذا الأسبوع</translation>
+<translation id="8199524924445686405">سنة</translation>
+<translation id="8208673686607688524">منتقي الوقت والتاريخ المحليان</translation>
+<translation id="8261464734335370856">تدقيق إملائي غير صالح</translation>
+<translation id="8284326494547611709">الترجمة والشرح</translation>
+<translation id="8346634859695247203">القسم</translation>
+<translation id="835897206747267392">قيمة غير صحيحة</translation>
+<translation id="8403857369060869934">الوقت المنقضي: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">جزء</translation>
+<translation id="8433900881053900389">شريط الأدوات</translation>
+<translation id="8444882422881193423">عدد الملفات: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">يُرجى تحديد ملف.</translation>
+<translation id="8461852803063341183">زر الاختيار</translation>
+<translation id="8474886197722836894">إهداء</translation>
+<translation id="8531739829932800271">قائمة بالأخطاء</translation>
+<translation id="8534579021159131403">دقائق</translation>
+<translation id="8541249477527128034">التحكم في الوسائط</translation>
+<translation id="8550857728288566671">رمز رسومي</translation>
+<translation id="8583702881314752957">قائمة تعريف</translation>
+<translation id="8597182159515967513">العنوان</translation>
+<translation id="860475260694818407">جدول المحتويات</translation>
+<translation id="8613126697340063924">التحكم في التشغيل عن بعد</translation>
+<translation id="862370744433916922">ترجمة مصاحِبة</translation>
+<translation id="8711688047404765493">الإخراج</translation>
+<translation id="8750798805984357768">يُرجى اختيار أحد هذه الخيارات.</translation>
+<translation id="8808573423886751634">فصل</translation>
+<translation id="8822203815165896261">إنشاء المعلومات</translation>
+<translation id="8845239796550121995">يتم الآن الإرسال إلى جهاز التلفزيون</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">خطأ في تشغيل الفيديو.</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> كيلوبايت</translation>
+<translation id="8987927404178983737">شهر</translation>
+<translation id="901493112792887934">المدة الحالية بالثواني</translation>
+<translation id="901834265349196618">بريد إلكتروني</translation>
+<translation id="9048119486235211610">تنقل</translation>
+<translation id="9062295712474918030">المستند</translation>
+<translation id="9093215626363556771">الخروج من وضع "نافذة ضمن نافذة"</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">آخر...</translation>
+<translation id="9138385573473225930">تنبيه</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />، ابتداء من <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">نافذة ضمن النافذة</translation>
+<translation id="9168329111483466115">حاشية سُفلية</translation>
+<translation id="954003015749068518">الدخول في وضع "نافذة ضمن نافذة"</translation>
+<translation id="966787709310836684">القائمة</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..5568b78e313
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_bg.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bg">
+<translation id="1018939186200882850">елемент от меню</translation>
+<translation id="10623998915015855">бутон за превключване</translation>
+<translation id="1088086359088493902">Секунди</translation>
+<translation id="1171774979989969504">Моля, въведете имейл адрес.</translation>
+<translation id="1178581264944972037">Пауза</translation>
+<translation id="1188858454923323853">допълнение</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">плъзгач</translation>
+<translation id="1211441953136645838">бележка в края</translation>
+<translation id="1281252709823657822">диалогов прозорец</translation>
+<translation id="1335095011850992622">признания за източника</translation>
+<translation id="1342835525016946179">статия</translation>
+<translation id="1359897965706325498">банер</translation>
+<translation id="1589122976691792535">регион</translation>
+<translation id="1591562245178063882">Този месец</translation>
+<translation id="1637811476055996098">Избор на файлове</translation>
+<translation id="1650423536718072820">изнесен цитат</translation>
+<translation id="1727886345390570319">скриване на менюто за надписи</translation>
+<translation id="1729654308190250600">Моля, въведете имейл адрес.</translation>
+<translation id="1758486001363313524">Други...</translation>
+<translation id="1806710327868736751">диалогов прозорец със сигнал</translation>
+<translation id="1821985195704844674">дървовидна таблица</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">възпроизвеждане на отдалечено устройство</translation>
+<translation id="190587075670221089">изтриване</translation>
+<translation id="1907737156431278478">пример</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="1930711995431081526">състояние</translation>
+<translation id="1938124657309484470">Стойността трябва да е <ph name="MAXIMUM_DATE_OR_TIME" /> или по-рано.</translation>
+<translation id="1946271899482435442">Показване на инструмента за избор на дата</translation>
+<translation id="1993104285338243655">Превключихте към дублиране</translation>
+<translation id="2060505056492490888">„<ph name="DOT" />“ се използва на неправилна позиция в/ъв „<ph name="INVALIDDOMAIN" />“.</translation>
+<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="2247351761944213033">Седмица <ph name="WEEKNUMBER" />, <ph name="YEAR" /> г.</translation>
+<translation id="2277199496770840904">Запис <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">квадратче за отметка</translation>
+<translation id="2311842470354187719">разделител на страници</translation>
+<translation id="2335594187091864976">инструмент за избор на дата и час</translation>
+<translation id="245932805758469625">оставащи секунди до края на видеоклипа</translation>
+<translation id="248395913932153421">Ден</translation>
+<translation id="2507943997699731163">Моля, попълнете това поле.</translation>
+<translation id="2508569020611168319">списък с раздели</translation>
+<translation id="2561842179657104141">показване на още контроли за мултимедия</translation>
+<translation id="2572483411312390101">пускане</translation>
+<translation id="2613802280814924224">Моля, въведете валидна стойност. Най-близката такава е <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Изпращане</translation>
+<translation id="2657045182931379222">графичен обект</translation>
+<translation id="2674318244760992338">долен колонтитул</translation>
+<translation id="2709516037105925701">Автоматично попълване</translation>
+<translation id="2723001399770238859">звук</translation>
+<translation id="2725963129578236554">коментари</translation>
+<translation id="2746543609216772311">Стойността трябва да е <ph name="MINIMUM_DATE_OR_TIME" /> или по-късно.</translation>
+<translation id="2759744352195237655">бутон с изскачащ прозорец</translation>
+<translation id="2761667185364618470">Моля, поставете отметка в това квадратче, ако искате да продължите.</translation>
+<translation id="2844350028562914727">подробности</translation>
+<translation id="2896972712917208084">група бутони за избор</translation>
+<translation id="2908441821576996758">Моля, въведете списък с имейл адреси, разделени със запетаи.</translation>
+<translation id="2940813599313844715">обект</translation>
+<translation id="3040011195152428237">връзка</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> МБ</translation>
+<translation id="3075154866155599887">Моля, въведете валидна стойност. Данните в полето са непълни или датата е невалидна.</translation>
+<translation id="3078740164268491126">таблица</translation>
+<translation id="3086746722712840547">забележка</translation>
+<translation id="310520048233152454">Моля, въведете URL адрес.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">разгъващ се списък</translation>
+<translation id="3450233048674729344">Стойността трябва да е по-малка или равна на <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">дефиниция</translation>
+<translation id="3557673793733683882">заглавие от ниво <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">инструмент за избор на седмица</translation>
+<translation id="3685101356851116974">Изображение без етикет</translation>
+<translation id="3706100364254443312">превключвател</translation>
+<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Изход от „Картина в картината“</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
+<translation id="3808586225841795776">термин</translation>
+<translation id="3822383571486410024">Моля, удължете този текст поне до <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Текстът преди „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3846214748874656680">Изход от цял екран</translation>
+<translation id="3889183436948184105">корекция</translation>
+<translation id="3920932319529768807">заключение</translation>
+<translation id="3924558731517983934">приложение</translation>
+<translation id="3944740393230681990">пролог</translation>
+<translation id="3960700977367013758">лента за превъртане</translation>
+<translation id="4103419683916926126">Милисекунди</translation>
+<translation id="4151657705144244502">графика</translation>
+<translation id="4160057747563657758">телефон</translation>
+<translation id="4193965531860883258">предговор</translation>
+<translation id="4201051445878709314">Показване на предишния месец</translation>
+<translation id="421884353938374759">инструмент за избор на цветове</translation>
+<translation id="4248100235867064564">лента с менюта</translation>
+<translation id="4360991593054037559">Моля, въведете валидна стойност. Двете най-близки такива са <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Въпроси и отговори</translation>
+<translation id="4413860115965805769">бутон за меню</translation>
+<translation id="4444765639179266822">Изглежда, че пише: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">препратка към определение в терминологичния речник</translation>
+<translation id="4522570452068850558">Подробности</translation>
+<translation id="4542388879936266156">оставащо време: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">формуляр</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">приложение</translation>
+<translation id="4718048029184481307">Възпроизвежда се в режим „Картина в картината“</translation>
+<translation id="4742539557769756338">корица</translation>
+<translation id="4748357248530471599">превключване между прорез на екрана и цял екран</translation>
+<translation id="4757246831282535685">панел с раздели</translation>
+<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Моля, въведете номер.</translation>
+<translation id="4912536737030637138">библиографски запис</translation>
+<translation id="4975562563186953947">Избрани: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Включване на звука</translation>
+<translation id="49969490063480558">Моля, въведете текст след „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
+<translation id="5034860022980953847">индикатор за напредък</translation>
+<translation id="5090250355906949916">времеви плъзгач за видеоклипа</translation>
+<translation id="5093189678851173835">епиграф</translation>
+<translation id="5117590920725113268">Показване на следващия месец</translation>
+<translation id="512758898067543763">заглавка на ред</translation>
+<translation id="5143125788380636750">епилог</translation>
+<translation id="5164977714490026579">Стойността трябва да е по-голяма или равна на <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> ПБ</translation>
+<translation id="5307600278924710095">Моля, въведете текст преди „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
+<translation id="5334352251556557839">Мултимедийното съдържание не може да бъде възпроизведено.</translation>
+<translation id="5406322316791861025">фигура</translation>
+<translation id="5453733299334684579">елемент от дърво</translation>
+<translation id="5466621249238537318">Моля, изберете един или повече файлове.</translation>
+<translation id="5468998798572797635">изход от цял екран</translation>
+<translation id="5516424706154626233">инструмент за избор на дата</translation>
+<translation id="5537725057119320332">Предаване</translation>
+<translation id="5546461542133609677">пускане на звука</translation>
+<translation id="5608153257855394627">открояване</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Докоснете два пъти стрелката наляво или надясно, за да пропуснете 10 сек</translation>
+<translation id="5631759159893697722">резюме</translation>
+<translation id="5643186887447432888">бутон</translation>
+<translation id="5677946354068040947">още опции</translation>
+<translation id="576709008726043716">въведение</translation>
+<translation id="57838592816432529">Заглушаване</translation>
+<translation id="5860033963881614850">Изключено</translation>
+<translation id="588258955323874662">Цял екран</translation>
+<translation id="5888666972993069672">В момента се предава към „<ph name="DEVICE_FRIENDLY_NAME" />“</translation>
+<translation id="591047860372322273">поле за търсене</translation>
+<translation id="5939518447894949180">Нулиране</translation>
+<translation id="5966707198760109579">Седмица</translation>
+<translation id="5987525920412732405">брояч</translation>
+<translation id="6011459053400940133">плъзгач за силата на звука</translation>
+<translation id="6015796118275082299">Година</translation>
+<translation id="6023896073578205740">списъчно поле</translation>
+<translation id="6150588977291308318">библиография</translation>
+<translation id="6164829606128959761">индикатор</translation>
+<translation id="6166809985690652833">послеслов</translation>
+<translation id="6209276755895393898">Изглежда, че това е: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">терминологичен речник</translation>
+<translation id="6281763101136022427">url адрес</translation>
+<translation id="6310801910862476708">Изход от „Картина в картината“</translation>
+<translation id="6398862346408813489">Показване на панела за избиране на месец</translation>
+<translation id="6404546809543547843">времеви плъзгач за аудиозаписа</translation>
+<translation id="6443871981718447451">показване на менюто за надписи</translation>
+<translation id="6453774872122745852">признания</translation>
+<translation id="6475115390776617481">текущо присъствие</translation>
+<translation id="648732519525291180">инструмент за избор на час</translation>
+<translation id="6550675742724504774">Опции</translation>
+<translation id="6572309429103589720">Невалидна граматика</translation>
+<translation id="658823671542763450">вход за цял екран</translation>
+<translation id="663493177488814956">емисия</translation>
+<translation id="6637586476836377253">регистрационен файл</translation>
+<translation id="6643016212128521049">Изчистване</translation>
+<translation id="668171684555832681">Друг...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Лошо качество на възпроизвеждането</translation>
+<translation id="6755330956360078551">подсказка</translation>
+<translation id="6790428901817661496">Пускане</translation>
+<translation id="6820355525329141109">Приставката не можа да се зареди.</translation>
+<translation id="6820615603175220800">препратка към библиографски запис</translation>
+<translation id="6843725295806269523">заглушаване</translation>
+<translation id="6885760532393684712">директория</translation>
+<translation id="689129560213475294">колофон</translation>
+<translation id="6934078000481955284">блоков цитат</translation>
+<translation id="693476918119313863">горен колонтитул</translation>
+<translation id="6941933287844615239">изтегляне на мултимедията</translation>
+<translation id="6981594929165378967">вмъкване</translation>
+<translation id="6989848892321993519">Моля, удължете този текст до поне <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате 1 знак).</translation>
+<translation id="7034405885550056553">предложение</translation>
+<translation id="709897737746224366">Моля, спазвайте изисквания формат.</translation>
+<translation id="7118469954320184356">Няма описание.</translation>
+<translation id="7139483182332611405">предисловие</translation>
+<translation id="7214187073215825913">информация за съдържанието</translation>
+<translation id="7263440858009898357">Моля, изберете елемент в списъка.</translation>
+<translation id="727747134524199931">заглавка на колона</translation>
+<translation id="7320576522385648310">буферира се</translation>
+<translation id="7353453495576941748">признание за източника</translation>
+<translation id="7364796246159120393">Избор на файл</translation>
+<translation id="739024184232394898">Други...</translation>
+<translation id="7405738980073107433">бележки в края</translation>
+<translation id="7410239719251593705">Изглежда има съдържание за пълнолетни. Няма описание.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
+<translation id="7491962110804786152">раздел</translation>
+<translation id="7514365320538308">Изтегляне</translation>
+<translation id="7529102961911894712">препратка</translation>
+<translation id="7533959249147584474">Графика без етикет</translation>
+<translation id="7647456547678091388">съвет</translation>
+<translation id="7661956066982048809">графичен документ</translation>
+<translation id="7673697353781729403">Часове</translation>
+<translation id="7681220483256441252">показалец</translation>
+<translation id="7740050170769002709">HTML съдържание</translation>
+<translation id="7745230546936012372">За да изтеглите липсващите описания на изображения, отворете контекстното меню.</translation>
+<translation id="7750228210027921155">Картина в картината</translation>
+<translation id="775297008183122718">Въведеното е невалидно</translation>
+<translation id="7789962463072032349">поставяне на пауза</translation>
+<translation id="7802800022689234070">триъгълник за разкриване на съдържание</translation>
+<translation id="7888071071722539607">Моля, включете „<ph name="ATSIGN" />“ в имейл адреса. В/ъв „<ph name="INVALIDADDRESS" />“ липсва „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">разделител</translation>
+<translation id="795667975304826397">Няма избран файл</translation>
+<translation id="8053789581856978548">текстово поле за търсене</translation>
+<translation id="8057695513531652401">известие</translation>
+<translation id="8105797009065549151">препратка към бележка</translation>
+<translation id="811583516810654505">Описанието се изтегля...</translation>
+<translation id="8117451130807776954">Тази седмица</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="8208673686607688524">инструмент за избор на дата и час според местното време</translation>
+<translation id="8261464734335370856">Невалиден правопис</translation>
+<translation id="8284326494547611709">Надписи</translation>
+<translation id="8346634859695247203">секция</translation>
+<translation id="835897206747267392">Невалидна стойност.</translation>
+<translation id="8403857369060869934">изминало време: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">част</translation>
+<translation id="8433900881053900389">лента с инструменти</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> файла</translation>
+<translation id="8451268428117625855">Моля, изберете файл.</translation>
+<translation id="8461852803063341183">бутон за избор</translation>
+<translation id="8474886197722836894">посвещение</translation>
+<translation id="8531739829932800271">списък с печатните грешки</translation>
+<translation id="8534579021159131403">Минути</translation>
+<translation id="8541249477527128034">медийна контрола</translation>
+<translation id="8550857728288566671">графичен символ</translation>
+<translation id="8583702881314752957">списък с дефиниции</translation>
+<translation id="8597182159515967513">заглавие</translation>
+<translation id="860475260694818407">съдържание</translation>
+<translation id="8613126697340063924">управление на отдалеченото възпроизвеждане</translation>
+<translation id="862370744433916922">подзаглавие</translation>
+<translation id="8711688047404765493">изход</translation>
+<translation id="8750798805984357768">Моля, изберете една от тези опции.</translation>
+<translation id="8808573423886751634">глава</translation>
+<translation id="8822203815165896261">информация за авторството</translation>
+<translation id="8845239796550121995">В момента се предава към телевизора ви</translation>
+<translation id="8851136666856101339">основен елемент</translation>
+<translation id="8875657656876809964">Грешка при възпроизвеждането на видеоклипа</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KБ</translation>
+<translation id="8987927404178983737">Месец</translation>
+<translation id="901493112792887934">текущо време в секунди</translation>
+<translation id="901834265349196618">имейл</translation>
+<translation id="9048119486235211610">навигация</translation>
+<translation id="9062295712474918030">документ</translation>
+<translation id="9093215626363556771">изход от режима „Картина в картината“</translation>
+<translation id="9108370397979208512">математически израз</translation>
+<translation id="9132465097189459683">Други...</translation>
+<translation id="9138385573473225930">сигнал</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> – започва от <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Картина в картината</translation>
+<translation id="9168329111483466115">бележка под линия</translation>
+<translation id="954003015749068518">вход в режима „Картина в картината“</translation>
+<translation id="966787709310836684">меню</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..a4c910c6d05
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_bn.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bn">
+<translation id="1018939186200882850">মেনু আইটেম</translation>
+<translation id="10623998915015855">টগল বোতাম</translation>
+<translation id="1088086359088493902">সেকেন্ড</translation>
+<translation id="1171774979989969504">অনুগ্রহ করে কোন ইমেল আইডি লিখুন:</translation>
+<translation id="1178581264944972037">বিরতি</translation>
+<translation id="1188858454923323853">পরিপূরক</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">স্লাইডার</translation>
+<translation id="1211441953136645838">এন্ডনোট</translation>
+<translation id="1281252709823657822">ডায়ালগ</translation>
+<translation id="1335095011850992622">ক্রেডিট</translation>
+<translation id="1342835525016946179">নিবন্ধ</translation>
+<translation id="1359897965706325498">ব্যানার</translation>
+<translation id="1589122976691792535">অঞ্চল</translation>
+<translation id="1591562245178063882">এই মাস</translation>
+<translation id="1637811476055996098">ফাইল বেছে নিন</translation>
+<translation id="1650423536718072820">পুলকোট</translation>
+<translation id="1727886345390570319">ক্লোজড ক্যাপশনের মেনু লুকান</translation>
+<translation id="1729654308190250600">অনুগ্রহ করে একটি খালি না থাকা ইমেল আইডি লিখুন৷</translation>
+<translation id="1758486001363313524">অন্যান্য...</translation>
+<translation id="1806710327868736751">সতর্কতার_ডায়ালগ</translation>
+<translation id="1821985195704844674">ট্রি গ্রিড</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">রিমোট ডিভাইসে প্লে করুন</translation>
+<translation id="190587075670221089">মোছা হচ্ছে</translation>
+<translation id="1907737156431278478">উদাহরণ</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">স্থিতি</translation>
+<translation id="1938124657309484470">মানকে অবশ্যই <ph name="MAXIMUM_DATE_OR_TIME" /> বা আগের হতে হবে৷</translation>
+<translation id="1946271899482435442">তারিখ বেছে নেওয়ার বিকল্পটি দেখান</translation>
+<translation id="1993104285338243655">মিররিং এ পরিবর্তন করা হয়েছে</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />' এ একটি ভুল অবস্থানে '<ph name="DOT" />' ব্যবহৃত হয়েছে৷</translation>
+<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="2247351761944213033"><ph name="WEEKNUMBER" /> সপ্তাহ, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ট্র্যাক <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">চেকবাক্স</translation>
+<translation id="2311842470354187719">পৃষ্ঠা বিরতি</translation>
+<translation id="2335594187091864976">তারিখ এবং সময় চয়নকারি</translation>
+<translation id="245932805758469625">ভিডিও শেষ হতে এখনও যত সেকেন্ড বাকি আছে</translation>
+<translation id="248395913932153421">দিন</translation>
+<translation id="2507943997699731163">দয়া করে এই ক্ষেত্রটি পূরণ করুন৷</translation>
+<translation id="2508569020611168319">ট্যাব তালিকা</translation>
+<translation id="2561842179657104141">আরও মিডিয়া নিয়ন্ত্রণ দেখান</translation>
+<translation id="2572483411312390101">চালনা করুন</translation>
+<translation id="2613802280814924224">দয়া করে একটি বৈধ মান লিখুন৷ কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE" />৷</translation>
+<translation id="2653659639078652383">জমা দিন</translation>
+<translation id="2657045182931379222">গ্রাফিক্স অবজেক্ট</translation>
+<translation id="2674318244760992338">পাদলেখ</translation>
+<translation id="2709516037105925701">স্বয়ংপূরণ</translation>
+<translation id="2723001399770238859">অডিও</translation>
+<translation id="2725963129578236554">মন্তব্য</translation>
+<translation id="2746543609216772311">মানকে অবশ্যই <ph name="MINIMUM_DATE_OR_TIME" /> বা পরবর্তী হতে হবে৷</translation>
+<translation id="2759744352195237655">পপ আপ বোতাম</translation>
+<translation id="2761667185364618470">আপনি এগিয়ে যেতে চাইলে এই বাক্সটি পরীক্ষা করুন৷</translation>
+<translation id="2844350028562914727">বিবরণ</translation>
+<translation id="2896972712917208084">রেডিও বোতাম গ্রুপ</translation>
+<translation id="2908441821576996758">অনুগ্রহ করে কমা দিয়ে আলাদা করা ইমেল আইডির তালিকা লিখুন৷</translation>
+<translation id="2940813599313844715">অবজেক্ট</translation>
+<translation id="3040011195152428237">লিঙ্ক</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> এমবি</translation>
+<translation id="3075154866155599887">অনুগ্রহ করে একটি সঠিক মান লিখুন৷ ফিল্ডটি অসম্পূর্ণ অথবা একটি ভুল তারিখ আছে৷</translation>
+<translation id="3078740164268491126">সারণী</translation>
+<translation id="3086746722712840547">দ্রষ্টব্য</translation>
+<translation id="310520048233152454">দয়া করে একটি বৈধ URL প্রবেশ করুন৷</translation>
+<translation id="3175736971608411871">টাইমার</translation>
+<translation id="3199563858620722075">কম্বো বাক্স</translation>
+<translation id="3450233048674729344">মানটি অবশ্যই <ph name="MAXIMUM" />এর চেয়ে কম বা সমান হবে৷</translation>
+<translation id="3486220673238053218">সংজ্ঞা</translation>
+<translation id="3557673793733683882">শিরোনাম <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">সপ্তাহ চয়নকারি</translation>
+<translation id="3685101356851116974">লেবেল ছাড়া ছবি</translation>
+<translation id="3706100364254443312">পরিবর্তন করুন</translation>
+<translation id="3732799496749320381">মিমি</translation>
+<translation id="3754210790023674521">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> জিবি</translation>
+<translation id="3808586225841795776">পদ</translation>
+<translation id="3822383571486410024">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করেছেন) দৈর্ঘের করুন।</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="3846214748874656680">পূর্ণস্ক্রীন থেকে প্রস্থান করুন</translation>
+<translation id="3889183436948184105">আবার দেখুন</translation>
+<translation id="3920932319529768807">সিদ্ধান্ত</translation>
+<translation id="3924558731517983934">অ্যাপ্লিকেশান</translation>
+<translation id="3944740393230681990">ভূমিকা</translation>
+<translation id="3960700977367013758">স্ক্রল বার</translation>
+<translation id="4103419683916926126">মিলিসেকেন্ড</translation>
+<translation id="4151657705144244502">গ্রাফিক</translation>
+<translation id="4160057747563657758">টেলিফোন</translation>
+<translation id="4193965531860883258">মুখবন্ধ</translation>
+<translation id="4201051445878709314">পূর্ববর্তী মাস দেখান</translation>
+<translation id="421884353938374759">রঙ চয়নকারী</translation>
+<translation id="4248100235867064564">মেনু বার</translation>
+<translation id="4360991593054037559">দয়া করে একটি বৈধ মান লিখুন৷ দুটি কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE_LOW" /> এবং <ph name="VALID_VALUE_HIGHER" />৷</translation>
+<translation id="4384583879834880242">প্রশ্ন এবং উত্তর</translation>
+<translation id="4413860115965805769">মেনু বোতাম</translation>
+<translation id="4444765639179266822">মনে হচ্ছে বলতে চাইছে: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">শব্দকোষের রেফারেন্স</translation>
+<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4542388879936266156">বাকি সময়: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ফর্ম</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="4668956016107839909">পরিশিষ্ট</translation>
+<translation id="4718048029184481307">ছবির-মধ্যে-ছবি মোডে চলছে</translation>
+<translation id="4742539557769756338">কভার</translation>
+<translation id="4748357248530471599">ডিসপ্লে কাট-আউট ফুল-স্ক্রিনে টগল করুন</translation>
+<translation id="4757246831282535685">ট্যাব প্যানেল</translation>
+<translation id="4763480195061959176">ভিডিও</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">দয়া করে একটি সংখ্যা লিখুন৷</translation>
+<translation id="4912536737030637138">বিবলিওগ্রাফি এন্ট্রি</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />টি নির্বাচিত</translation>
+<translation id="4992066212339426712">সশব্দ করুন</translation>
+<translation id="49969490063480558">দয়া করে '<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
+<translation id="5034860022980953847">অগ্রগতি সূচক</translation>
+<translation id="5090250355906949916">ভিডিওর সময় স্ক্রাবার</translation>
+<translation id="5093189678851173835">এপিগ্রাফ</translation>
+<translation id="5117590920725113268">পরবর্তী মাস দেখান</translation>
+<translation id="512758898067543763">সারি শিরোলেখ</translation>
+<translation id="5143125788380636750">উপসংহার</translation>
+<translation id="5164977714490026579">মানটি অবশ্যই <ph name="MINIMUM" />এর চেয়ে বেশি বা সমান হবে৷</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
+<translation id="5334352251556557839">মিডিয়া চালানো যাচ্ছে না।</translation>
+<translation id="5406322316791861025">আকার</translation>
+<translation id="5453733299334684579">ট্রি আইটেম</translation>
+<translation id="5466621249238537318">অনুগ্রহ করে এক বা একাধিক ফাইল নির্বাচন করুন৷</translation>
+<translation id="5468998798572797635">পূর্ণ স্ক্রিন বন্ধ করুন</translation>
+<translation id="5516424706154626233">তারিখ চয়নকারি</translation>
+<translation id="5537725057119320332">কাস্ট করুন</translation>
+<translation id="5546461542133609677">সশব্দ</translation>
+<translation id="5608153257855394627">হাইলাইট করা</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">১০ সেকেন্ড আগে পরে করার জন্য বাঁ অথবা ডান দিকে ডবল ট্যাপ করুন</translation>
+<translation id="5631759159893697722">বিমূর্ত</translation>
+<translation id="5643186887447432888">বোতাম</translation>
+<translation id="5677946354068040947">আরও বিকল্প</translation>
+<translation id="576709008726043716">পরিচয়</translation>
+<translation id="57838592816432529">মিউট করুন</translation>
+<translation id="5860033963881614850">বন্ধ করুন</translation>
+<translation id="588258955323874662">সম্পূর্নস্ক্রীণ</translation>
+<translation id="5888666972993069672"><ph name="DEVICE_FRIENDLY_NAME" /> এ কাস্ট করা হচ্ছে</translation>
+<translation id="591047860372322273">সার্চ বক্স</translation>
+<translation id="5939518447894949180">রিসেট করুন</translation>
+<translation id="5966707198760109579">সপ্তাহ</translation>
+<translation id="5987525920412732405">ঘোড়ানোর বোতাম</translation>
+<translation id="6011459053400940133">ভলিউম স্লাইডার</translation>
+<translation id="6015796118275082299">বছর</translation>
+<translation id="6023896073578205740">তালিকা বাক্স</translation>
+<translation id="6150588977291308318">বিবলিওগ্রাফি</translation>
+<translation id="6164829606128959761">মিটার</translation>
+<translation id="6166809985690652833">পরিশিষ্ট</translation>
+<translation id="6209276755895393898">মনে হচ্ছে: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">শব্দকোষ</translation>
+<translation id="6281763101136022427">ইউআরএল</translation>
+<translation id="6310801910862476708">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
+<translation id="6398862346408813489">মাস নির্বাচনের প্যানেল দেখান</translation>
+<translation id="6404546809543547843">অডিও সময় স্ক্রাবার</translation>
+<translation id="6443871981718447451">ক্লোজড ক্যাপশনের মেনু দেখান</translation>
+<translation id="6453774872122745852">কৃতজ্ঞতা স্বীকার</translation>
+<translation id="6475115390776617481">কারা এই কন্টেন্টে কাজ করছেন</translation>
+<translation id="648732519525291180">সময় চয়নকারি</translation>
+<translation id="6550675742724504774">বিকল্পসমূহ</translation>
+<translation id="6572309429103589720">ভুল ব্যাকরণ</translation>
+<translation id="658823671542763450">পূর্ণ স্ক্রীনে প্রবেশ করুন</translation>
+<translation id="663493177488814956">ফিড</translation>
+<translation id="6637586476836377253">লগ</translation>
+<translation id="6643016212128521049">সাফ করুন</translation>
+<translation id="668171684555832681">অন্যান্য...</translation>
+<translation id="6692633176391053278">পদক্ষেপকারী</translation>
+<translation id="6709570249143506788">প্লেব্যাকের গুণমান খারাপ</translation>
+<translation id="6755330956360078551">সরঞ্জামটিপ</translation>
+<translation id="6790428901817661496">চালু করুন</translation>
+<translation id="6820355525329141109">প্লাগ-ইন লোড করা যায়নি।</translation>
+<translation id="6820615603175220800">বিবলিওগ্রাফি রেফারেন্স</translation>
+<translation id="6843725295806269523">মিউট</translation>
+<translation id="6885760532393684712">ডিরেক্টরি</translation>
+<translation id="689129560213475294">বইটির সম্পর্কে</translation>
+<translation id="6934078000481955284">ব্লক উদ্ধৃতি</translation>
+<translation id="693476918119313863">হেডার</translation>
+<translation id="6941933287844615239">মিডিয়া ডাউনলোড করুন</translation>
+<translation id="6981594929165378967">যোগ করা হচ্ছে</translation>
+<translation id="6989848892321993519">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি দৈর্ঘ্যের করুন (আপনি বর্তমানে ১টি অক্ষর ব্যবহার করেছেন)।</translation>
+<translation id="7034405885550056553">সাজেশন</translation>
+<translation id="709897737746224366">দয়া করে অনুরোধ হওয়া বিন্যাসটি মেলান৷</translation>
+<translation id="7118469954320184356">কোনও বিবরণ নেই।</translation>
+<translation id="7139483182332611405">মুখবন্ধ</translation>
+<translation id="7214187073215825913">কন্টেন্টের তথ্য</translation>
+<translation id="7263440858009898357">তালিকা থেকে একটি আইটেম নির্বাচন করুন৷ </translation>
+<translation id="727747134524199931">কলাম শিরোলেখ</translation>
+<translation id="7320576522385648310">বাফার হচ্ছে</translation>
+<translation id="7353453495576941748">স্বীকৃতি</translation>
+<translation id="7364796246159120393">ফাইল বেছে নিন</translation>
+<translation id="739024184232394898">অন্যান্য...</translation>
+<translation id="7405738980073107433">এন্ডনোট</translation>
+<translation id="7410239719251593705">প্রাপ্তবয়স্কদের কন্টেন্ট আছে বলে মনে হচ্ছে। কোনও বিবরণ দেওয়া নেই।</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">ট্যাব</translation>
+<translation id="7514365320538308">ডাউনলোড করুন</translation>
+<translation id="7529102961911894712">ফিরে যাওয়ার লিঙ্ক</translation>
+<translation id="7533959249147584474">লেবেল ছাড়া ছবি</translation>
+<translation id="7647456547678091388">পরামর্শ</translation>
+<translation id="7661956066982048809">গ্রাফিক্স ডকুমেন্ট</translation>
+<translation id="7673697353781729403">ঘণ্টা</translation>
+<translation id="7681220483256441252">সূচি</translation>
+<translation id="7740050170769002709">HTML কন্টেন্ট</translation>
+<translation id="7745230546936012372">ছবির বিবরণ অনুপস্থিত থাকলে, সেটি জানতে সংশ্লিষ্ট মেনু খুলুন।</translation>
+<translation id="7750228210027921155">ছবির-মধ্যে-ছবি</translation>
+<translation id="775297008183122718">নির্ভুল নয়</translation>
+<translation id="7789962463072032349">বিরাম</translation>
+<translation id="7802800022689234070">উম্মোচন ত্রিভুজ</translation>
+<translation id="7888071071722539607">ইমেল আইডিতে অনুগ্রহ করে একটি '<ph name="ATSIGN" />' অন্তর্ভুক্ত করুন৷ '<ph name="INVALIDADDRESS" />'-তে একটি '<ph name="ATSIGN" />' অনুপস্থিত৷</translation>
+<translation id="7891486169920085145">স্প্লিটার</translation>
+<translation id="795667975304826397">কোনও ফাইল চয়ন করা হয় নি</translation>
+<translation id="8053789581856978548">সার্চ পাঠ্য ফিল্ড</translation>
+<translation id="8057695513531652401">বিজ্ঞপ্তি</translation>
+<translation id="8105797009065549151">নোটের রেফারেন্স</translation>
+<translation id="811583516810654505">বিবরণ খোঁজা হচ্ছে…</translation>
+<translation id="8117451130807776954">এই সপ্তাহ</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">স্থানীয় তারিখ ও সময় চয়নকারি</translation>
+<translation id="8261464734335370856">ভুল বানান</translation>
+<translation id="8284326494547611709">পরিচয়লিপিগুলি</translation>
+<translation id="8346634859695247203">বিভাগ</translation>
+<translation id="835897206747267392">ভুল মান৷</translation>
+<translation id="8403857369060869934">অতিবাহিত সময়: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">অংশ</translation>
+<translation id="8433900881053900389">টুল দণ্ড</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> টি ফাইল</translation>
+<translation id="8451268428117625855">দয়া করে একটি ফাইল নির্বাচন করুন৷</translation>
+<translation id="8461852803063341183">রেডিও বোতাম</translation>
+<translation id="8474886197722836894">উৎসর্গ</translation>
+<translation id="8531739829932800271">ত্রুটি-বিচ্যুতি</translation>
+<translation id="8534579021159131403">মিনিট</translation>
+<translation id="8541249477527128034">মিডিয়া নিয়ন্ত্রণ</translation>
+<translation id="8550857728288566671">গ্রাফিক্স চিহ্ন</translation>
+<translation id="8583702881314752957">সংজ্ঞার তালিকা</translation>
+<translation id="8597182159515967513">শিরোনাম</translation>
+<translation id="860475260694818407">সূচিপত্র</translation>
+<translation id="8613126697340063924">রিমোট প্লেব্যাক নিয়ন্ত্রণ করুন</translation>
+<translation id="862370744433916922">সাবটাইটেল</translation>
+<translation id="8711688047404765493">আউটপুট</translation>
+<translation id="8750798805984357768">দয়া করে বিকল্পগুলির একটি নির্বাচন করুন৷</translation>
+<translation id="8808573423886751634">অধ্যায়</translation>
+<translation id="8822203815165896261">লেখার তথ্য</translation>
+<translation id="8845239796550121995">এখন আপনার TV তে কাস্ট করা হচ্ছে</translation>
+<translation id="8851136666856101339">প্রধান</translation>
+<translation id="8875657656876809964">ভিডিও প্লেব্যাকে সমস্যা</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> কেবি</translation>
+<translation id="8987927404178983737">মাস</translation>
+<translation id="901493112792887934">সেকেন্ডে বর্তমান সময়</translation>
+<translation id="901834265349196618">ইমেল আইডি</translation>
+<translation id="9048119486235211610">নেভিগেশন</translation>
+<translation id="9062295712474918030">দস্তাবেজ</translation>
+<translation id="9093215626363556771">ছবির-মধ্যে-ছবি মোড থেকে বেরিয়ে আসুন</translation>
+<translation id="9108370397979208512">গণিত</translation>
+<translation id="9132465097189459683">অন্যান্য...</translation>
+<translation id="9138385573473225930">সতর্কতা</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> এ শুরু</translation>
+<translation id="916607977885256133">ছবির-মধ্যে-ছবি</translation>
+<translation id="9168329111483466115">ফুটনোট</translation>
+<translation id="954003015749068518">ছবির-মধ্যে-ছবি মোডে যান</translation>
+<translation id="966787709310836684">মেনু</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..e8a2a5f3195
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ca.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ca">
+<translation id="1018939186200882850">element del menú</translation>
+<translation id="10623998915015855">botó de commutació</translation>
+<translation id="1088086359088493902">Segons</translation>
+<translation id="1171774979989969504">Introduïu una adreça electrònica.</translation>
+<translation id="1178581264944972037">Posa en pausa</translation>
+<translation id="1188858454923323853">complementari</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control lliscant</translation>
+<translation id="1211441953136645838">nota final</translation>
+<translation id="1281252709823657822">quadre de diàleg</translation>
+<translation id="1335095011850992622">crèdits</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">bàner</translation>
+<translation id="1589122976691792535">regió</translation>
+<translation id="1591562245178063882">Aquest mes</translation>
+<translation id="1637811476055996098">Trieu els fitxers</translation>
+<translation id="1650423536718072820">citació extreta</translation>
+<translation id="1727886345390570319">amaga el menú de subtítols</translation>
+<translation id="1729654308190250600">Introduïu una adreça electrònica.</translation>
+<translation id="1758486001363313524">Altres...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">quadrícula d'arbre</translation>
+<translation id="1822429046913737220">a. m./p. m.</translation>
+<translation id="1832974991323546415">reprodueix al dispositiu remot</translation>
+<translation id="190587075670221089">supressió</translation>
+<translation id="1907737156431278478">exemple</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">estat</translation>
+<translation id="1938124657309484470">El valor ha de ser <ph name="MAXIMUM_DATE_OR_TIME" /> o anterior.</translation>
+<translation id="1946271899482435442">Mostra el selector de dates</translation>
+<translation id="1993104285338243655">S'ha canviat a projecció</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />" s'ha utilitzat en una posició incorrecta a "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Avui</translation>
+<translation id="2158401438286456825">llista de pàgines</translation>
+<translation id="2226276347425096477">Escurceu aquest text a un màxim de <ph name="MAX_CHARACTERS" /> caràcters (ara n'esteu utilitzant <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="2246498165605549352">Fitxer local</translation>
+<translation id="2247351761944213033">Setmana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">casella de selecció</translation>
+<translation id="2311842470354187719">salt de pàgina</translation>
+<translation id="2335594187091864976">selector de data i hora</translation>
+<translation id="245932805758469625">nombre de segons restants del vídeo</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="2507943997699731163">Empleneu aquest camp.</translation>
+<translation id="2508569020611168319">llista de pestanyes</translation>
+<translation id="2561842179657104141">mostra més controls multimèdia</translation>
+<translation id="2572483411312390101">reprodueix</translation>
+<translation id="2613802280814924224">Introduïu un valor vàlid. El valor vàlid més proper és <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Envia</translation>
+<translation id="2657045182931379222">objecte gràfic</translation>
+<translation id="2674318244760992338">peu</translation>
+<translation id="2709516037105925701">Emplenament automàtic</translation>
+<translation id="2723001399770238859">àudio</translation>
+<translation id="2725963129578236554">comentaris</translation>
+<translation id="2746543609216772311">El valor ha de ser <ph name="MINIMUM_DATE_OR_TIME" /> o posterior.</translation>
+<translation id="2759744352195237655">botó emergent</translation>
+<translation id="2761667185364618470">Marqueu aquesta casella si voleu continuar.</translation>
+<translation id="2844350028562914727">detalls</translation>
+<translation id="2896972712917208084">grup de botons d'opció</translation>
+<translation id="2908441821576996758">Introduïu una llista d'adreces electròniques separades per comes.</translation>
+<translation id="2940813599313844715">objecte</translation>
+<translation id="3040011195152428237">enllaç</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Introduïu un valor vàlid. El camp està incomplet o conté una data no vàlida.</translation>
+<translation id="3078740164268491126">taula</translation>
+<translation id="3086746722712840547">nota</translation>
+<translation id="310520048233152454">Introduïu un URL.</translation>
+<translation id="3175736971608411871">temporitzador</translation>
+<translation id="3199563858620722075">quadre combinat</translation>
+<translation id="3450233048674729344">El valor ha de ser igual o inferior a <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definició</translation>
+<translation id="3557673793733683882">capçalera <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selector setmanal</translation>
+<translation id="3685101356851116974">Imatge sense etiquetar</translation>
+<translation id="3706100364254443312">commutador</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Surt del mode de pantalla en pantalla</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">terme</translation>
+<translation id="3822383571486410024">Allargueu aquest text fins a un mínim de <ph name="MIN_CHARACTERS" /> caràcters (ara n'utilitzeu <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Un nom d'usuari seguit de "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Surt de la pantalla completa</translation>
+<translation id="3889183436948184105">revisió</translation>
+<translation id="3920932319529768807">conclusió</translation>
+<translation id="3924558731517983934">aplicació</translation>
+<translation id="3944740393230681990">pròleg</translation>
+<translation id="3960700977367013758">barra de desplaçament</translation>
+<translation id="4103419683916926126">Mil·lisegons</translation>
+<translation id="4151657705144244502">gràfic</translation>
+<translation id="4160057747563657758">telèfon</translation>
+<translation id="4193965531860883258">preàmbul</translation>
+<translation id="4201051445878709314">Mostra el mes anterior</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4360991593054037559">Introduïu un valor vàlid. Els valors vàlids més propers són <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntes</translation>
+<translation id="4413860115965805769">botó de menú</translation>
+<translation id="4444765639179266822">Sembla que diu "<ph name="OCR_TEXT" />"</translation>
+<translation id="4446524499724042288">referència del glossari</translation>
+<translation id="4522570452068850558">Detalls</translation>
+<translation id="4542388879936266156">temps restant: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulari</translation>
+<translation id="4661075872484491155">arbre</translation>
+<translation id="4664250907885839816">Un domini precedit per "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apèndix</translation>
+<translation id="4718048029184481307">S'està reproduint en mode de pantalla en pantalla</translation>
+<translation id="4742539557769756338">portada</translation>
+<translation id="4748357248530471599">activa o desactiva la pantalla completa al retall de pantalla</translation>
+<translation id="4757246831282535685">tauler de pestanyes</translation>
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">cerca</translation>
+<translation id="4812940957355064477">Introduïu un número.</translation>
+<translation id="4912536737030637138">entrada bibliogràfica</translation>
+<translation id="4975562563186953947">Elements seleccionats: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Deixa de silenciar</translation>
+<translation id="49969490063480558">Introduïu un domini precedit per "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça electrònica completa.</translation>
+<translation id="5034860022980953847">indicador de progrés</translation>
+<translation id="5090250355906949916">barra de moment del vídeo</translation>
+<translation id="5093189678851173835">epígraf</translation>
+<translation id="5117590920725113268">Mostra el mes següent</translation>
+<translation id="512758898067543763">capçalera de la fila</translation>
+<translation id="5143125788380636750">epíleg</translation>
+<translation id="5164977714490026579">El valor ha de ser més gran o igual que <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Introduïu un nom d'usuari seguit de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça completa.</translation>
+<translation id="5334352251556557839">No s'ha pogut reproduir el contingut multimèdia.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">element de l'arbre</translation>
+<translation id="5466621249238537318">Seleccioneu un o diversos fitxers.</translation>
+<translation id="5468998798572797635">surt de la pantalla completa</translation>
+<translation id="5516424706154626233">selector de data</translation>
+<translation id="5537725057119320332">Emet</translation>
+<translation id="5546461542133609677">deixa de silenciar</translation>
+<translation id="5608153257855394627">ressalta</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Fes doble toc a l'esquerra o a la dreta per saltar 10 s</translation>
+<translation id="5631759159893697722">resum</translation>
+<translation id="5643186887447432888">botó</translation>
+<translation id="5677946354068040947">més opcions</translation>
+<translation id="576709008726043716">introducció</translation>
+<translation id="57838592816432529">Silencia</translation>
+<translation id="5860033963881614850">Desactivat</translation>
+<translation id="588258955323874662">Pantalla completa</translation>
+<translation id="5888666972993069672">S'està emetent a <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">quadre de cerca</translation>
+<translation id="5939518447894949180">Restableix</translation>
+<translation id="5966707198760109579">Setmana</translation>
+<translation id="5987525920412732405">botó de selecció de valors</translation>
+<translation id="6011459053400940133">control lliscant de volum</translation>
+<translation id="6015796118275082299">Any</translation>
+<translation id="6023896073578205740">quadre de llista</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">comptador</translation>
+<translation id="6166809985690652833">cloenda</translation>
+<translation id="6209276755895393898">Sembla el següent: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossari</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Surt del mode de pantalla en pantalla</translation>
+<translation id="6398862346408813489">Mostra el tauler de la selecció de mes</translation>
+<translation id="6404546809543547843">barra de moment de l'àudio</translation>
+<translation id="6443871981718447451">mostra el menú de subtítols</translation>
+<translation id="6453774872122745852">agraïments</translation>
+<translation id="6475115390776617481">presència en directe</translation>
+<translation id="648732519525291180">selector d'hora</translation>
+<translation id="6550675742724504774">Opcions</translation>
+<translation id="6572309429103589720">La gramàtica no és vàlida</translation>
+<translation id="658823671542763450">passa a pantalla completa</translation>
+<translation id="663493177488814956">El meu tauler</translation>
+<translation id="6637586476836377253">registre</translation>
+<translation id="6643016212128521049">Esborra</translation>
+<translation id="668171684555832681">Altres...</translation>
+<translation id="6692633176391053278">desplaçador</translation>
+<translation id="6709570249143506788">Mala qualitat de reproducció</translation>
+<translation id="6755330956360078551">descripció emergent</translation>
+<translation id="6790428901817661496">Reprodueix</translation>
+<translation id="6820355525329141109">El connector no s'ha pogut carregar.</translation>
+<translation id="6820615603175220800">referència bibliogràfica</translation>
+<translation id="6843725295806269523">silencia</translation>
+<translation id="6885760532393684712">directori</translation>
+<translation id="689129560213475294">colofó</translation>
+<translation id="6934078000481955284">cita en bloc</translation>
+<translation id="693476918119313863">capçalera</translation>
+<translation id="6941933287844615239">baixa els fitxers multimèdia</translation>
+<translation id="6981594929165378967">inserció</translation>
+<translation id="6989848892321993519">Allarga aquest text fins a <ph name="MIN_CHARACTERS" /> caràcters o més (ara n'utilitzes 1).</translation>
+<translation id="7034405885550056553">suggeriment</translation>
+<translation id="709897737746224366">Feu servir el format sol·licitat.</translation>
+<translation id="7118469954320184356">No hi ha cap descripció disponible.</translation>
+<translation id="7139483182332611405">prefaci</translation>
+<translation id="7214187073215825913">informació sobre el contingut</translation>
+<translation id="7263440858009898357">Seleccioneu un element de la llista.</translation>
+<translation id="727747134524199931">capçalera de columna</translation>
+<translation id="7320576522385648310">s'estan emmagatzemant dades a la memòria intermèdia</translation>
+<translation id="7353453495576941748">crèdit</translation>
+<translation id="7364796246159120393">Tria un fitxer</translation>
+<translation id="739024184232394898">Altres...</translation>
+<translation id="7405738980073107433">notes finals</translation>
+<translation id="7410239719251593705">Sembla que inclou contingut per a adults. No hi ha cap descripció disponible.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">pestanya</translation>
+<translation id="7514365320538308">Baixa</translation>
+<translation id="7529102961911894712">enllaç d'entrada</translation>
+<translation id="7533959249147584474">Gràfic sense etiqueta</translation>
+<translation id="7647456547678091388">consell</translation>
+<translation id="7661956066982048809">document gràfic</translation>
+<translation id="7673697353781729403">Hores</translation>
+<translation id="7681220483256441252">índex</translation>
+<translation id="7740050170769002709">Contingut HTML</translation>
+<translation id="7745230546936012372">Per obtenir les descripcions que falten de les imatges, obre el menú contextual.</translation>
+<translation id="7750228210027921155">Pantalla en pantalla</translation>
+<translation id="775297008183122718">Entrada no vàlida</translation>
+<translation id="7789962463072032349">posa en pausa</translation>
+<translation id="7802800022689234070">triangle desplegable</translation>
+<translation id="7888071071722539607">Incloeu el símbol "<ph name="ATSIGN" />" a l'adreça electrònica. Al camp "<ph name="INVALIDADDRESS" />" falta el símbol "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
+<translation id="795667975304826397">No s'ha triat cap fitxer</translation>
+<translation id="8053789581856978548">camp de text de la cerca</translation>
+<translation id="8057695513531652401">avís</translation>
+<translation id="8105797009065549151">referència de la nota</translation>
+<translation id="811583516810654505">S'està obtenint la descripció...</translation>
+<translation id="8117451130807776954">Aquesta setmana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selector de data i hora local</translation>
+<translation id="8261464734335370856">L'ortografia no és vàlida</translation>
+<translation id="8284326494547611709">Subtítols</translation>
+<translation id="8346634859695247203">secció</translation>
+<translation id="835897206747267392">Valor no vàlid.</translation>
+<translation id="8403857369060869934">temps transcorregut: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">part</translation>
+<translation id="8433900881053900389">barra d'eines</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fitxers</translation>
+<translation id="8451268428117625855">Seleccioneu un fitxer.</translation>
+<translation id="8461852803063341183">botó d'opció</translation>
+<translation id="8474886197722836894">dedicatòria</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minuts</translation>
+<translation id="8541249477527128034">control de mitjans</translation>
+<translation id="8550857728288566671">símbol gràfic</translation>
+<translation id="8583702881314752957">llista de definicions</translation>
+<translation id="8597182159515967513">capçalera</translation>
+<translation id="860475260694818407">taula de continguts</translation>
+<translation id="8613126697340063924">reproducció amb comandament</translation>
+<translation id="862370744433916922">subtítol</translation>
+<translation id="8711688047404765493">sortida</translation>
+<translation id="8750798805984357768">Seleccioneu una d'aquestes opcions.</translation>
+<translation id="8808573423886751634">capítol</translation>
+<translation id="8822203815165896261">informació sobre l'autoria</translation>
+<translation id="8845239796550121995">S'està emetent al televisor</translation>
+<translation id="8851136666856101339">principal</translation>
+<translation id="8875657656876809964">Error de reproducció del vídeo</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="901493112792887934">temps actual en segons</translation>
+<translation id="901834265349196618">correu electrònic</translation>
+<translation id="9048119486235211610">navegació</translation>
+<translation id="9062295712474918030">document</translation>
+<translation id="9093215626363556771">surt del mode de pantalla en pantalla</translation>
+<translation id="9108370397979208512">matemàtiques</translation>
+<translation id="9132465097189459683">Altres...</translation>
+<translation id="9138385573473225930">alerta</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, a partir del dia <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Pantalla en pantalla</translation>
+<translation id="9168329111483466115">nota al peu</translation>
+<translation id="954003015749068518">ves al mode de pantalla en pantalla</translation>
+<translation id="966787709310836684">menú</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..d8708974d6a
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_cs.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="cs">
+<translation id="1018939186200882850">položka nabídky</translation>
+<translation id="10623998915015855">přepínací tlačítko</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="1171774979989969504">Zadejte prosím e-mailovou adresu.</translation>
+<translation id="1178581264944972037">Pozastavit</translation>
+<translation id="1188858454923323853">doplňkové</translation>
+<translation id="1206619573307042055">běžící text</translation>
+<translation id="1206693055195146388">posuvník</translation>
+<translation id="1211441953136645838">koncová poznámka</translation>
+<translation id="1281252709823657822">dialogové okno</translation>
+<translation id="1335095011850992622">poděkování</translation>
+<translation id="1342835525016946179">čl</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">oblast</translation>
+<translation id="1591562245178063882">Tento měsíc</translation>
+<translation id="1637811476055996098">Zvolit soubory</translation>
+<translation id="1650423536718072820">citace</translation>
+<translation id="1727886345390570319">skrýt nabídku titulků</translation>
+<translation id="1729654308190250600">Vyplňte e-mailovou adresu.</translation>
+<translation id="1758486001363313524">Jiné…</translation>
+<translation id="1806710327868736751">dialog upozornění</translation>
+<translation id="1821985195704844674">stromová mřížka</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">přehrát ve vzdáleném zařízení</translation>
+<translation id="190587075670221089">smazání</translation>
+<translation id="1907737156431278478">příklad</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">stav</translation>
+<translation id="1938124657309484470">Datum musí být <ph name="MAXIMUM_DATE_OR_TIME" /> nebo dříve.</translation>
+<translation id="1946271899482435442">Zobrazit výběr data</translation>
+<translation id="1993104285338243655">Přepnuto na zrcadlení</translation>
+<translation id="2060505056492490888">Znak <ph name="DOT" /> v doméně <ph name="INVALIDDOMAIN" /> není použitý správně.</translation>
+<translation id="2148716181193084225">Dnes</translation>
+<translation id="2158401438286456825">seznam stránek</translation>
+<translation id="2226276347425096477">Zkraťte prosím tento text na <ph name="MAX_CHARACTERS" /> znaků nebo méně. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
+<translation id="2246498165605549352">Místní soubor</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týden, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Stopa <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">zaškrtávací políčko</translation>
+<translation id="2311842470354187719">konec stránky</translation>
+<translation id="2335594187091864976">výběr data a času</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>
+<translation id="2508569020611168319">seznam karet</translation>
+<translation id="2561842179657104141">zobrazit více ovládacích prvků médií</translation>
+<translation id="2572483411312390101">přehrát</translation>
+<translation id="2613802280814924224">Zadejte platnou hodnotu. Nejbližší platná hodnota je <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Odeslat</translation>
+<translation id="2657045182931379222">grafický objekt</translation>
+<translation id="2674318244760992338">zápatí</translation>
+<translation id="2709516037105925701">Automatické vyplňování</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="2725963129578236554">komentáře</translation>
+<translation id="2746543609216772311">Datum musí být <ph name="MINIMUM_DATE_OR_TIME" /> nebo později.</translation>
+<translation id="2759744352195237655">tlačítko s vyskakovacím oknem</translation>
+<translation id="2761667185364618470">Chcete-li pokračovat, zaškrtněte toto políčko.</translation>
+<translation id="2844350028562914727">podrobnosti</translation>
+<translation id="2896972712917208084">skupina přepínačů</translation>
+<translation id="2908441821576996758">Zadejte seznam e-mailových adres oddělených čárkami.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">odkaz</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Zadejte prosím platnou hodnotu. Pole obsahuje neúplnou hodnotu nebo neplatné datum.</translation>
+<translation id="3078740164268491126">tabulka</translation>
+<translation id="3086746722712840547">pozn</translation>
+<translation id="310520048233152454">Zadejte prosím adresu URL.</translation>
+<translation id="3175736971608411871">časovač</translation>
+<translation id="3199563858620722075">rozbalovací seznam</translation>
+<translation id="3450233048674729344">Hodnota musí být menší nebo rovna <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definice</translation>
+<translation id="3557673793733683882">nadpis <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">výběr týdne</translation>
+<translation id="3685101356851116974">Neoznačený obrázek</translation>
+<translation id="3706100364254443312">přepínač</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Ukončit režim obrazu v obraze</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">výraz</translation>
+<translation id="3822383571486410024">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
+<translation id="383465348367842624">Část před znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3846214748874656680">Ukončit režim na celou obrazovku</translation>
+<translation id="3889183436948184105">verze</translation>
+<translation id="3920932319529768807">závěr</translation>
+<translation id="3924558731517983934">aplikace</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">posuvník</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">obrázek</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">předmluva</translation>
+<translation id="4201051445878709314">Zobrazit předchozí měsíc</translation>
+<translation id="421884353938374759">výběr barev</translation>
+<translation id="4248100235867064564">panel nabídky</translation>
+<translation id="4360991593054037559">Zadejte platnou hodnotu. Dvě nejbližší hodnoty jsou <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Dotazy</translation>
+<translation id="4413860115965805769">tlačítko nabídky</translation>
+<translation id="4444765639179266822">Vypadá jako: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">odkaz na glosář</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">zbývající čas: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulář</translation>
+<translation id="4661075872484491155">strom</translation>
+<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">příloha</translation>
+<translation id="4718048029184481307">Video se přehrává v režimu obrazu v obraze</translation>
+<translation id="4742539557769756338">titulní strana</translation>
+<translation id="4748357248530471599">přepnout výřez displeje na celou obrazovku</translation>
+<translation id="4757246831282535685">panel karty</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Zadejte prosím číslo.</translation>
+<translation id="4912536737030637138">bibliografická položka</translation>
+<translation id="4975562563186953947">Vybráno: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Zapnout zvuk</translation>
+<translation id="49969490063480558">Zadejte část za znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
+<translation id="5034860022980953847">indikátor průběhu</translation>
+<translation id="5090250355906949916">posuvník času videa</translation>
+<translation id="5093189678851173835">nápis</translation>
+<translation id="5117590920725113268">Zobrazit další měsíc</translation>
+<translation id="512758898067543763">záhlaví řádku</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Hodnota musí být větší nebo rovna <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Zadejte část před znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
+<translation id="5334352251556557839">Médium nelze přehrát.</translation>
+<translation id="5406322316791861025">číslice</translation>
+<translation id="5453733299334684579">položka stromu</translation>
+<translation id="5466621249238537318">Vyberte prosím jeden nebo více souborů.</translation>
+<translation id="5468998798572797635">ukončit režim celé obrazovky</translation>
+<translation id="5516424706154626233">výběr data</translation>
+<translation id="5537725057119320332">Odeslat</translation>
+<translation id="5546461542133609677">zapnout zvuk</translation>
+<translation id="5608153257855394627">zvýraznění</translation>
+<translation id="561939826962581046">čas</translation>
+<translation id="5630795885300617244">Dvojitým klepnutím na šipku vlevo nebo vpravo přeskočíte o 10 s</translation>
+<translation id="5631759159893697722">abstrakt</translation>
+<translation id="5643186887447432888">tlačítko</translation>
+<translation id="5677946354068040947">další možnosti</translation>
+<translation id="576709008726043716">úvod</translation>
+<translation id="57838592816432529">Ztlumit</translation>
+<translation id="5860033963881614850">Vypnuto</translation>
+<translation id="588258955323874662">Celá obrazovka</translation>
+<translation id="5888666972993069672">Odesílání do zařízení <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">vyhledávací pole</translation>
+<translation id="5939518447894949180">Resetovat</translation>
+<translation id="5966707198760109579">Týden</translation>
+<translation id="5987525920412732405">číselník</translation>
+<translation id="6011459053400940133">posuvník hlasitosti</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">seznam</translation>
+<translation id="6150588977291308318">bibliografie</translation>
+<translation id="6164829606128959761">měřič</translation>
+<translation id="6166809985690652833">doslov</translation>
+<translation id="6209276755895393898">Vypadá jako: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosář</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Ukončit režim obrazu v obraze</translation>
+<translation id="6398862346408813489">Zobrazit panel pro výběr měsíců</translation>
+<translation id="6404546809543547843">posuvník času zvuku</translation>
+<translation id="6443871981718447451">zobrazit nabídku skrytých titulků</translation>
+<translation id="6453774872122745852">poděkování</translation>
+<translation id="6475115390776617481">aktuální přítomnost</translation>
+<translation id="648732519525291180">výběr času</translation>
+<translation id="6550675742724504774">Možnosti</translation>
+<translation id="6572309429103589720">Neplatná gramatika</translation>
+<translation id="658823671542763450">přejít do režimu celé obrazovky</translation>
+<translation id="663493177488814956">zdroj</translation>
+<translation id="6637586476836377253">protokol</translation>
+<translation id="6643016212128521049">Vymazat</translation>
+<translation id="668171684555832681">Další...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Špatná kvalita přehrávání</translation>
+<translation id="6755330956360078551">popisek</translation>
+<translation id="6790428901817661496">Přehrát</translation>
+<translation id="6820355525329141109">Plugin se nepodařilo načíst.</translation>
+<translation id="6820615603175220800">bibliografický odkaz</translation>
+<translation id="6843725295806269523">ztlumit</translation>
+<translation id="6885760532393684712">adresář</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">bloková citace</translation>
+<translation id="693476918119313863">záhlaví</translation>
+<translation id="6941933287844615239">stáhnout média</translation>
+<translation id="6981594929165378967">vložení</translation>
+<translation id="6989848892321993519">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má 1 znak.)</translation>
+<translation id="7034405885550056553">návrh</translation>
+<translation id="709897737746224366">Zadejte hodnotu, která odpovídá požadovanému formátu.</translation>
+<translation id="7118469954320184356">Popis není k dispozici.</translation>
+<translation id="7139483182332611405">předmluva</translation>
+<translation id="7214187073215825913">informace o obsahu</translation>
+<translation id="7263440858009898357">Vyberte prosím v seznamu některou položku.</translation>
+<translation id="727747134524199931">záhlaví sloupce</translation>
+<translation id="7320576522385648310">načítání do vyrovnávací paměti</translation>
+<translation id="7353453495576941748">poděkování</translation>
+<translation id="7364796246159120393">Vybrat soubor</translation>
+<translation id="739024184232394898">Jiné…</translation>
+<translation id="7405738980073107433">koncové poznámky</translation>
+<translation id="7410239719251593705">Zřejmě zahrnuje obsah pro dospělé. Popis není k dispozici.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">karta</translation>
+<translation id="7514365320538308">Stáhnout</translation>
+<translation id="7529102961911894712">zpětný odkaz</translation>
+<translation id="7533959249147584474">Neoznačená grafika</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafický dokument</translation>
+<translation id="7673697353781729403">Hodiny</translation>
+<translation id="7681220483256441252">rejstřík</translation>
+<translation id="7740050170769002709">Obsah ve formátu HTML</translation>
+<translation id="7745230546936012372">Chcete-li získat popisky obrázků, otevřete kontextovou nabídku.</translation>
+<translation id="7750228210027921155">Obraz v obraze</translation>
+<translation id="775297008183122718">Neplatný vstup</translation>
+<translation id="7789962463072032349">pozastavit</translation>
+<translation id="7802800022689234070">tlačítko k zobrazení skrytého obsahu</translation>
+<translation id="7888071071722539607">Do e-mailové adresy zahrňte znak <ph name="ATSIGN" />. V adrese <ph name="INVALIDADDRESS" /> chybí znak <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">rozdělovač</translation>
+<translation id="795667975304826397">Soubor nevybrán</translation>
+<translation id="8053789581856978548">pole pro vyhledání textu</translation>
+<translation id="8057695513531652401">oznámení</translation>
+<translation id="8105797009065549151">odkaz na poznámku</translation>
+<translation id="811583516810654505">Získávání popisu...</translation>
+<translation id="8117451130807776954">Tento týden</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="8208673686607688524">výběr místního data a času</translation>
+<translation id="8261464734335370856">Neplatný pravopis</translation>
+<translation id="8284326494547611709">Titulky</translation>
+<translation id="8346634859695247203">oddíl</translation>
+<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8403857369060869934">uplynulý čas: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">část</translation>
+<translation id="8433900881053900389">lišta</translation>
+<translation id="8444882422881193423">Počet souborů: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Vyberte prosím soubor.</translation>
+<translation id="8461852803063341183">přepínač</translation>
+<translation id="8474886197722836894">věnování</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minuty</translation>
+<translation id="8541249477527128034">ovládání médií</translation>
+<translation id="8550857728288566671">grafický symbol</translation>
+<translation id="8583702881314752957">seznam definic</translation>
+<translation id="8597182159515967513">záhlaví</translation>
+<translation id="860475260694818407">obsah</translation>
+<translation id="8613126697340063924">ovládání vzdáleného přehrávání</translation>
+<translation id="862370744433916922">titulek</translation>
+<translation id="8711688047404765493">výstup</translation>
+<translation id="8750798805984357768">Vyberte jednu z těchto možností.</translation>
+<translation id="8808573423886751634">kapitola</translation>
+<translation id="8822203815165896261">informace o autorech</translation>
+<translation id="8845239796550121995">Odesílání do televize</translation>
+<translation id="8851136666856101339">hlavní</translation>
+<translation id="8875657656876809964">Chyba přehrávání videa</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Měsíc</translation>
+<translation id="901493112792887934">aktuální čas v sekundách</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigace</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">ukončit režim obrazu v obraze</translation>
+<translation id="9108370397979208512">matematika</translation>
+<translation id="9132465097189459683">Jiné…</translation>
+<translation id="9138385573473225930">upozornění</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, začíná <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Obraz v obraze</translation>
+<translation id="9168329111483466115">poznámka pod čarou</translation>
+<translation id="954003015749068518">spustit režim obrazu v obraze</translation>
+<translation id="966787709310836684">nabídka</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..6db27748783
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_da.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="da">
+<translation id="1018939186200882850">menupunkt</translation>
+<translation id="10623998915015855">til/fra-knap</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="1171774979989969504">Angiv en mailadresse.</translation>
+<translation id="1178581264944972037">Pause</translation>
+<translation id="1188858454923323853">supplerende</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">skyder</translation>
+<translation id="1211441953136645838">slutnote</translation>
+<translation id="1281252709823657822">dialogboks</translation>
+<translation id="1335095011850992622">anerkendelser</translation>
+<translation id="1342835525016946179">artikel</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">område</translation>
+<translation id="1591562245178063882">Denne måned</translation>
+<translation id="1637811476055996098">Vælg filer</translation>
+<translation id="1650423536718072820">opmærksomhedsskabende citat</translation>
+<translation id="1727886345390570319">skjul menuen for undertekster</translation>
+<translation id="1729654308190250600">Angiv en mailadresse, der ikke er tom.</translation>
+<translation id="1758486001363313524">Andet...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">trægitter</translation>
+<translation id="1822429046913737220">f.m./e.m.</translation>
+<translation id="1832974991323546415">afspil på en enhed via fjernadgang</translation>
+<translation id="190587075670221089">sletning</translation>
+<translation id="1907737156431278478">eksempel</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Værdien må ikke være senere end <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
+<translation id="1946271899482435442">Vis datovælger</translation>
+<translation id="1993104285338243655">Ændret til spejling</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />" er placeret forkert i "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">I dag</translation>
+<translation id="2158401438286456825">sideliste</translation>
+<translation id="2226276347425096477">Forkort denne tekst til <ph name="MAX_CHARACTERS" /> tegn eller færre (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
+<translation id="2247351761944213033">Uge <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">afkrydsningsfelt</translation>
+<translation id="2311842470354187719">sideskift</translation>
+<translation id="2335594187091864976">dato- og tidsvælger</translation>
+<translation id="245932805758469625">antal sekunder tilbage af videoen</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="2507943997699731163">Udfyld dette felt.</translation>
+<translation id="2508569020611168319">faneliste</translation>
+<translation id="2561842179657104141">vis flere knapper til mediestyring</translation>
+<translation id="2572483411312390101">afspil</translation>
+<translation id="2613802280814924224">Angiv en gyldig værdi. Den nærmeste gyldige værdi er <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Indsend</translation>
+<translation id="2657045182931379222">grafikobjekt</translation>
+<translation id="2674318244760992338">sidefod</translation>
+<translation id="2709516037105925701">AutoFyld</translation>
+<translation id="2723001399770238859">lyd</translation>
+<translation id="2725963129578236554">kommentarer</translation>
+<translation id="2746543609216772311">Værdien må ikke være tidligere end <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">pop op-knap</translation>
+<translation id="2761667185364618470">Markér dette felt, hvis du vil fortsætte.</translation>
+<translation id="2844350028562914727">detaljer</translation>
+<translation id="2896972712917208084">gruppe af alternativknapper</translation>
+<translation id="2908441821576996758">Angiv en kommasepareret liste over mailadresser.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Angiv en gyldig værdi. Feltet er ufuldstændigt eller har en ugyldig dato.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">bmrk</translation>
+<translation id="310520048233152454">Angiv en webadresse.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">kombifelt</translation>
+<translation id="3450233048674729344">Værdien skal være mindre end eller lig med <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">overskrift <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">ugevælger</translation>
+<translation id="3685101356851116974">Billedet har ingen etiket</translation>
+<translation id="3706100364254443312">kontakt</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Afslut integreret billede</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">term</translation>
+<translation id="3822383571486410024">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="383465348367842624">Den del, der kommer før "<ph name="ATSIGN" />", må ikke indeholde "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Afslut fuld skærm</translation>
+<translation id="3889183436948184105">revision</translation>
+<translation id="3920932319529768807">konklusion</translation>
+<translation id="3924558731517983934">applikation</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">rullepanel</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">grafik</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">forord</translation>
+<translation id="4201051445878709314">Vis den foregående måned</translation>
+<translation id="421884353938374759">farvevælger</translation>
+<translation id="4248100235867064564">menulinje</translation>
+<translation id="4360991593054037559">Angiv en gyldig værdi. De to nærmeste gyldige værdier er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Spørgsmål og svar</translation>
+<translation id="4413860115965805769">menuknap</translation>
+<translation id="4444765639179266822">Der lader til at stå: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">reference på ordliste</translation>
+<translation id="4522570452068850558">Detaljer</translation>
+<translation id="4542388879936266156">resterende tid: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formular</translation>
+<translation id="4661075872484491155">træ</translation>
+<translation id="4664250907885839816">Den del, der kommer efter "<ph name="ATSIGN" />", må ikke indeholde symbolet "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">bilag</translation>
+<translation id="4718048029184481307">Afspiller i integreret billede</translation>
+<translation id="4742539557769756338">forside</translation>
+<translation id="4748357248530471599">skift fra skærmhak til fuld skærm</translation>
+<translation id="4757246831282535685">fanepanel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">søg</translation>
+<translation id="4812940957355064477">Angiv et nummer.</translation>
+<translation id="4912536737030637138">bibliografipost</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
+<translation id="4992066212339426712">Slå lyden til</translation>
+<translation id="49969490063480558">Angiv den del, der kommer efter "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
+<translation id="5034860022980953847">statusindikator</translation>
+<translation id="5090250355906949916">afspilningsbjælke for video</translation>
+<translation id="5093189678851173835">motto</translation>
+<translation id="5117590920725113268">Vis næste måned</translation>
+<translation id="512758898067543763">rækkeoverskrift</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Værdien skal være større end eller lig med <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Angiv den del, der kommer før "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
+<translation id="5334352251556557839">Mediet kunne ikke afspilles.</translation>
+<translation id="5406322316791861025">tal</translation>
+<translation id="5453733299334684579">træelement</translation>
+<translation id="5466621249238537318">Vælg en eller flere filer.</translation>
+<translation id="5468998798572797635">afslut fuld skærm</translation>
+<translation id="5516424706154626233">datovælger</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">slå lyden til</translation>
+<translation id="5608153257855394627">fremhævning</translation>
+<translation id="561939826962581046">tidspunkt</translation>
+<translation id="5630795885300617244">Tryk to gange til venstre eller højre for at springe ti sekunder over</translation>
+<translation id="5631759159893697722">abstrakt</translation>
+<translation id="5643186887447432888">knap</translation>
+<translation id="5677946354068040947">flere valgmuligheder</translation>
+<translation id="576709008726043716">indledning</translation>
+<translation id="57838592816432529">Slå lyden fra</translation>
+<translation id="5860033963881614850">Fra</translation>
+<translation id="588258955323874662">Fuld skærm</translation>
+<translation id="5888666972993069672">Caster nu til <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">søgefelt</translation>
+<translation id="5939518447894949180">Nulstil</translation>
+<translation id="5966707198760109579">Uge</translation>
+<translation id="5987525920412732405">skalafelt</translation>
+<translation id="6011459053400940133">lydstyrkeskyder</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listefelt</translation>
+<translation id="6150588977291308318">bibliografi</translation>
+<translation id="6164829606128959761">måler</translation>
+<translation id="6166809985690652833">efterskrift</translation>
+<translation id="6209276755895393898">Det lader til at være: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">ordliste</translation>
+<translation id="6281763101136022427">webadresse</translation>
+<translation id="6310801910862476708">Afslut integreret billede</translation>
+<translation id="6398862346408813489">Vis panel til valg af måned</translation>
+<translation id="6404546809543547843">afspilningsbjælke for lyd</translation>
+<translation id="6443871981718447451">vis menuen for undertekster</translation>
+<translation id="6453774872122745852">tak</translation>
+<translation id="6475115390776617481">aktiv bruger</translation>
+<translation id="648732519525291180">tidsvælger</translation>
+<translation id="6550675742724504774">Valgmuligheder</translation>
+<translation id="6572309429103589720">Ugyldig grammatik</translation>
+<translation id="658823671542763450">åbn fuld skærm</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Ryd</translation>
+<translation id="668171684555832681">Andre...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Dårlig afspilningskvalitet</translation>
+<translation id="6755330956360078551">værktøjstip</translation>
+<translation id="6790428901817661496">Afspil</translation>
+<translation id="6820355525329141109">Pluginnet kunne ikke indlæses.</translation>
+<translation id="6820615603175220800">reference i bibliografi</translation>
+<translation id="6843725295806269523">slå lyden fra</translation>
+<translation id="6885760532393684712">indeks</translation>
+<translation id="689129560213475294">slutskrift</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">header</translation>
+<translation id="6941933287844615239">download medier</translation>
+<translation id="6981594929165378967">indsættelse</translation>
+<translation id="6989848892321993519">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket ét tegn).</translation>
+<translation id="7034405885550056553">forslag</translation>
+<translation id="709897737746224366">Find et match til det anmodede format.</translation>
+<translation id="7118469954320184356">Der er ingen beskrivelse.</translation>
+<translation id="7139483182332611405">forord</translation>
+<translation id="7214187073215825913">oplysninger om indholdet</translation>
+<translation id="7263440858009898357">Vælg et punkt på listen.</translation>
+<translation id="727747134524199931">kolonneoverskrift</translation>
+<translation id="7320576522385648310">gemmer i buffer</translation>
+<translation id="7353453495576941748">anerkendelse</translation>
+<translation id="7364796246159120393">Vælg fil</translation>
+<translation id="739024184232394898">Andet...</translation>
+<translation id="7405738980073107433">slutnoter</translation>
+<translation id="7410239719251593705">Ser ud til at indeholde voksenindhold. Der er ingen tilgængelig beskrivelse.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">fane</translation>
+<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7533959249147584474">Grafikken har ingen etiket</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafikdokument</translation>
+<translation id="7673697353781729403">Timer</translation>
+<translation id="7681220483256441252">indeks</translation>
+<translation id="7740050170769002709">HTML-indhold</translation>
+<translation id="7745230546936012372">Åbn genvejsmenuen for at få beskrivelser til billeder, der mangler en beskrivelse.</translation>
+<translation id="7750228210027921155">Integreret billede</translation>
+<translation id="775297008183122718">Ugyldig indtastning</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">Trekant til at vise eller skjule indhold</translation>
+<translation id="7888071071722539607">Mailadressen skal indeholde et "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" mangler et "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">splitter</translation>
+<translation id="795667975304826397">Der er ikke valgt nogen fil</translation>
+<translation id="8053789581856978548">tekstfelt til søgning</translation>
+<translation id="8057695513531652401">meddelelse</translation>
+<translation id="8105797009065549151">reference i noter</translation>
+<translation id="811583516810654505">Henter beskrivelsen...</translation>
+<translation id="8117451130807776954">Denne uge</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="8208673686607688524">lokal dato- og tidsvælger</translation>
+<translation id="8261464734335370856">Ugyldig stavning</translation>
+<translation id="8284326494547611709">Undertekster</translation>
+<translation id="8346634859695247203">sektion</translation>
+<translation id="835897206747267392">Ugyldig værdi.</translation>
+<translation id="8403857369060869934">forløbet tid: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">del</translation>
+<translation id="8433900881053900389">værktøjslinje</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
+<translation id="8451268428117625855">Vælg en fil.</translation>
+<translation id="8461852803063341183">alternativknap</translation>
+<translation id="8474886197722836894">dedikation</translation>
+<translation id="8531739829932800271">rettelser</translation>
+<translation id="8534579021159131403">Minutter</translation>
+<translation id="8541249477527128034">mediekontrol</translation>
+<translation id="8550857728288566671">grafiksymbol</translation>
+<translation id="8583702881314752957">liste over definitioner</translation>
+<translation id="8597182159515967513">overskrift</translation>
+<translation id="860475260694818407">indholdsfortegnelse</translation>
+<translation id="8613126697340063924">kontrollér afspilning via fjernadgang</translation>
+<translation id="862370744433916922">undertitel</translation>
+<translation id="8711688047404765493">output</translation>
+<translation id="8750798805984357768">Vælg en af disse muligheder.</translation>
+<translation id="8808573423886751634">kapitel</translation>
+<translation id="8822203815165896261">godkendelsesoplysninger</translation>
+<translation id="8845239796550121995">Caster nu til dit fjernsyn</translation>
+<translation id="8851136666856101339">hovd</translation>
+<translation id="8875657656876809964">Fejl under videoafspilning</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Måned</translation>
+<translation id="901493112792887934">aktuel tid i sekunder</translation>
+<translation id="901834265349196618">mail</translation>
+<translation id="9048119486235211610">navigation</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">afslut integreret billede</translation>
+<translation id="9108370397979208512">matematik</translation>
+<translation id="9132465097189459683">Andet...</translation>
+<translation id="9138385573473225930">underretning</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Integreret billede</translation>
+<translation id="9168329111483466115">fodnote</translation>
+<translation id="954003015749068518">start integreret billede</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..bc7e048a2b7
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_de.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="de">
+<translation id="1018939186200882850">Menüpunkt</translation>
+<translation id="10623998915015855">Schaltfläche zum Umschalten</translation>
+<translation id="1088086359088493902">Sekunden</translation>
+<translation id="1171774979989969504">Geben Sie eine E-Mail-Adresse ein.</translation>
+<translation id="1178581264944972037">Anhalten</translation>
+<translation id="1188858454923323853">ergänzend</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">Schieberegler</translation>
+<translation id="1211441953136645838">Endnote</translation>
+<translation id="1281252709823657822">Kleines Fenster</translation>
+<translation id="1335095011850992622">Mitwirkende</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">Banner</translation>
+<translation id="1589122976691792535">Region</translation>
+<translation id="1591562245178063882">Aktueller Monat</translation>
+<translation id="1637811476055996098">Dateien auswählen</translation>
+<translation id="1650423536718072820">Textzitat</translation>
+<translation id="1727886345390570319">Untertitelmenü ausblenden</translation>
+<translation id="1729654308190250600">Geben Sie eine E-Mail-Adresse ein.</translation>
+<translation id="1758486001363313524">Andere...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">Baumraster</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">auf Remote-Gerät wiedergeben</translation>
+<translation id="190587075670221089">Löschen</translation>
+<translation id="1907737156431278478">Beispiel</translation>
+<translation id="1921819250265091946">tt</translation>
+<translation id="1930711995431081526">Status</translation>
+<translation id="1938124657309484470">Verwenden Sie <ph name="MAXIMUM_DATE_OR_TIME" /> oder einen früheren Wert.</translation>
+<translation id="1946271899482435442">Datumsauswahl anzeigen</translation>
+<translation id="1993104285338243655">Zu 1:1-Wiedergabe gewechselt</translation>
+<translation id="2060505056492490888">Das Punktzeichen "<ph name="DOT" />" steht in "<ph name="INVALIDDOMAIN" />" an einer falschen Stelle.</translation>
+<translation id="2148716181193084225">Heute</translation>
+<translation id="2158401438286456825">Seitenliste</translation>
+<translation id="2226276347425096477">Kürzen Sie diesen Text auf max. <ph name="MAX_CHARACTERS" /> Zeichen. Zurzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
+<translation id="2246498165605549352">Lokale Datei</translation>
+<translation id="2247351761944213033">Woche <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Titel <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">Kästchen</translation>
+<translation id="2311842470354187719">Seitenumbruch</translation>
+<translation id="2335594187091864976">Datums- und Uhrzeitauswahl</translation>
+<translation id="245932805758469625">verbleibende Videozeit in Sekunden</translation>
+<translation id="248395913932153421">Tag</translation>
+<translation id="2507943997699731163">Füllen Sie dieses Feld aus.</translation>
+<translation id="2508569020611168319">Tabliste</translation>
+<translation id="2561842179657104141">weitere Mediensteuerelemente anzeigen</translation>
+<translation id="2572483411312390101">Wiedergeben</translation>
+<translation id="2613802280814924224">Geben Sie einen gültigen Wert ein. Der nächstliegende gültige Wert ist <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Senden</translation>
+<translation id="2657045182931379222">Grafikobjekt</translation>
+<translation id="2674318244760992338">Fußzeile</translation>
+<translation id="2709516037105925701">AutoFill</translation>
+<translation id="2723001399770238859">Audio</translation>
+<translation id="2725963129578236554">Kommentare</translation>
+<translation id="2746543609216772311">Verwenden Sie <ph name="MINIMUM_DATE_OR_TIME" /> oder einen späteren Wert.</translation>
+<translation id="2759744352195237655">Pop-up-Schaltfläche</translation>
+<translation id="2761667185364618470">Klicken Sie dieses Kästchen an, wenn Sie fortfahren möchten.</translation>
+<translation id="2844350028562914727">Details</translation>
+<translation id="2896972712917208084">Optionsfeldgruppe</translation>
+<translation id="2908441821576996758">Geben Sie eine durch Kommas getrennte Liste der E-Mail-Adressen ein.</translation>
+<translation id="2940813599313844715">Objekt</translation>
+<translation id="3040011195152428237">Link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Geben Sie einen gültigen Wert ein. Das Feld ist nicht vollständig oder enthält ein ungültiges Datum.</translation>
+<translation id="3078740164268491126">Tabelle</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Geben Sie eine URL ein.</translation>
+<translation id="3175736971608411871">Timer</translation>
+<translation id="3199563858620722075">Kombinationsfeld</translation>
+<translation id="3450233048674729344">Wert muss kleiner als oder gleich <ph name="MAXIMUM" /> sein.</translation>
+<translation id="3486220673238053218">Definition</translation>
+<translation id="3557673793733683882">Überschrift <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">Wochenauswahl</translation>
+<translation id="3685101356851116974">Bild ohne Label</translation>
+<translation id="3706100364254443312">wechseln</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Bild-im-Bild-Modus beenden</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">Begriff</translation>
+<translation id="3822383571486410024">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
+<translation id="383465348367842624">Vor dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
+<translation id="3846214748874656680">Vollbildmodus beenden</translation>
+<translation id="3889183436948184105">Überarbeitung</translation>
+<translation id="3920932319529768807">Fazit</translation>
+<translation id="3924558731517983934">Anwendung</translation>
+<translation id="3944740393230681990">Prolog</translation>
+<translation id="3960700977367013758">Bildlaufleiste</translation>
+<translation id="4103419683916926126">Millisekunden</translation>
+<translation id="4151657705144244502">Grafik</translation>
+<translation id="4160057747563657758">Telefonnummer</translation>
+<translation id="4193965531860883258">Vorwort</translation>
+<translation id="4201051445878709314">Vorherigen Monat anzeigen</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">Menüleiste</translation>
+<translation id="4360991593054037559">Geben Sie einen gültigen Wert ein. Die zwei nächstliegenden gültigen Werte sind <ph name="VALID_VALUE_LOW" /> und <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Fragen und Antworten</translation>
+<translation id="4413860115965805769">Menüschaltfläche</translation>
+<translation id="4444765639179266822">Es sieht aus wie: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">Glossarreferenz</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">verbleibende Zeit: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">Formular</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Nach dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
+<translation id="4668956016107839909">Anhang</translation>
+<translation id="4718048029184481307">Wird im Bild-im-Bild-Modus abgespielt</translation>
+<translation id="4742539557769756338">Titelseite</translation>
+<translation id="4748357248530471599">Vollbildmodus mit Display-Aussparung ein-/ausschalten</translation>
+<translation id="4757246831282535685">Tabsteuerfeld</translation>
+<translation id="4763480195061959176">Video</translation>
+<translation id="479989351350248267">Suchen</translation>
+<translation id="4812940957355064477">Geben Sie eine Nummer ein.</translation>
+<translation id="4912536737030637138">Bibliografieeintrag</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ausgewählt</translation>
+<translation id="4992066212339426712">Stummschaltung aufheben</translation>
+<translation id="49969490063480558">Geben Sie etwas nach dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
+<translation id="5034860022980953847">Fortschrittsanzeige</translation>
+<translation id="5090250355906949916">Video-Zeitachse</translation>
+<translation id="5093189678851173835">Motto</translation>
+<translation id="5117590920725113268">Nächsten Monat anzeigen</translation>
+<translation id="512758898067543763">Zeilenüberschrift</translation>
+<translation id="5143125788380636750">Epilog</translation>
+<translation id="5164977714490026579">Wert muss größer als oder gleich <ph name="MINIMUM" /> sein.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Geben Sie etwas vor dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
+<translation id="5334352251556557839">Medien können nicht abgespielt werden.</translation>
+<translation id="5406322316791861025">Zahl</translation>
+<translation id="5453733299334684579">Baumelement</translation>
+<translation id="5466621249238537318">Wählen Sie eine oder mehrere Dateien aus.</translation>
+<translation id="5468998798572797635">Vollbildmodus beenden</translation>
+<translation id="5516424706154626233">Datumsauswahl</translation>
+<translation id="5537725057119320332">Übertragen</translation>
+<translation id="5546461542133609677">Ton an</translation>
+<translation id="5608153257855394627">markieren</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Tippen Sie links oder rechts doppelt, um 10 s zu überspringen</translation>
+<translation id="5631759159893697722">Zusammenfassung</translation>
+<translation id="5643186887447432888">Schaltfläche</translation>
+<translation id="5677946354068040947">weitere Optionen</translation>
+<translation id="576709008726043716">Einleitung</translation>
+<translation id="57838592816432529">Stummschalten</translation>
+<translation id="5860033963881614850">Aus</translation>
+<translation id="588258955323874662">Vollbild</translation>
+<translation id="5888666972993069672">Wird gerade auf <ph name="DEVICE_FRIENDLY_NAME" /> gestreamt</translation>
+<translation id="591047860372322273">Suchfeld</translation>
+<translation id="5939518447894949180">Zurücksetzen</translation>
+<translation id="5966707198760109579">Woche</translation>
+<translation id="5987525920412732405">Drehfeld</translation>
+<translation id="6011459053400940133">Schieberegler für die Lautstärke</translation>
+<translation id="6015796118275082299">Jahr</translation>
+<translation id="6023896073578205740">Listenfeld</translation>
+<translation id="6150588977291308318">Bibliografie</translation>
+<translation id="6164829606128959761">Messinstrument</translation>
+<translation id="6166809985690652833">Nachwort</translation>
+<translation id="6209276755895393898">Anscheinend ist es: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">Glossar</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Bild-im-Bild-Modus beenden</translation>
+<translation id="6398862346408813489">Auswahlbereich für Monatsanzeige</translation>
+<translation id="6404546809543547843">Audio-Zeitachse</translation>
+<translation id="6443871981718447451">Untertitelmenü einblenden</translation>
+<translation id="6453774872122745852">Danksagung</translation>
+<translation id="6475115390776617481">Live-Personenentdeckung</translation>
+<translation id="648732519525291180">Uhrzeitauswahl</translation>
+<translation id="6550675742724504774">Optionen</translation>
+<translation id="6572309429103589720">Ungültige Grammatik</translation>
+<translation id="658823671542763450">Vollbildmodus aktivieren</translation>
+<translation id="663493177488814956">Feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Löschen</translation>
+<translation id="668171684555832681">Andere...</translation>
+<translation id="6692633176391053278">Stepper</translation>
+<translation id="6709570249143506788">Schlechte Wiedergabequalität</translation>
+<translation id="6755330956360078551">Kurzinfo</translation>
+<translation id="6790428901817661496">Wiedergabe</translation>
+<translation id="6820355525329141109">Plug-in konnte nicht geladen werden.</translation>
+<translation id="6820615603175220800">Bibliografiereferenz</translation>
+<translation id="6843725295806269523">Stumm</translation>
+<translation id="6885760532393684712">Verzeichnis</translation>
+<translation id="689129560213475294">Kolophon</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">Überschrift</translation>
+<translation id="6941933287844615239">Medien herunterladen</translation>
+<translation id="6981594929165378967">Einfügen</translation>
+<translation id="6989848892321993519">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie 1 Zeichen.</translation>
+<translation id="7034405885550056553">Vorschlag</translation>
+<translation id="709897737746224366">Ihre Eingabe muss mit dem geforderten Format übereinstimmen.</translation>
+<translation id="7118469954320184356">Keine Beschreibung verfügbar.</translation>
+<translation id="7139483182332611405">Vorbemerkung</translation>
+<translation id="7214187073215825913">Informationen zum Inhalt</translation>
+<translation id="7263440858009898357">Wählen Sie ein Element in der Liste aus.</translation>
+<translation id="727747134524199931">Spaltenüberschrift</translation>
+<translation id="7320576522385648310">Wird zwischengespeichert</translation>
+<translation id="7353453495576941748">Danksagung</translation>
+<translation id="7364796246159120393">Datei auswählen</translation>
+<translation id="739024184232394898">Andere...</translation>
+<translation id="7405738980073107433">Endnoten</translation>
+<translation id="7410239719251593705">Enthält offenbar Inhalte nur für Erwachsene. Keine Beschreibung verfügbar.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Herunterladen</translation>
+<translation id="7529102961911894712">Rückverweis</translation>
+<translation id="7533959249147584474">Grafik ohne Label</translation>
+<translation id="7647456547678091388">Tipp</translation>
+<translation id="7661956066982048809">Grafikdokument</translation>
+<translation id="7673697353781729403">Stunden</translation>
+<translation id="7681220483256441252">Index</translation>
+<translation id="7740050170769002709">HTML-Inhalte</translation>
+<translation id="7745230546936012372">Wenn Sie fehlende Bildbeschreibungen abrufen möchten, öffnen Sie das Kontextmenü.</translation>
+<translation id="7750228210027921155">Bild-in-Bild</translation>
+<translation id="775297008183122718">Ungültiger Eintrag</translation>
+<translation id="7789962463072032349">Pausieren</translation>
+<translation id="7802800022689234070">Aufklappdreieck</translation>
+<translation id="7888071071722539607">Die E-Mail-Adresse muss ein <ph name="ATSIGN" />-Zeichen enthalten. In der Angabe "<ph name="INVALIDADDRESS" />" fehlt ein <ph name="ATSIGN" />-Zeichen.</translation>
+<translation id="7891486169920085145">Teilungsfunktion</translation>
+<translation id="795667975304826397">Keine ausgewählt</translation>
+<translation id="8053789581856978548">Feld für den Suchtext</translation>
+<translation id="8057695513531652401">Bemerkung</translation>
+<translation id="8105797009065549151">Hinweisreferenz</translation>
+<translation id="811583516810654505">Beschreibung wird abgerufen…</translation>
+<translation id="8117451130807776954">Diese Woche</translation>
+<translation id="8199524924445686405">jjjj</translation>
+<translation id="8208673686607688524">lokale Datums- und Uhrzeitauswahl</translation>
+<translation id="8261464734335370856">Ungültige Schreibweise</translation>
+<translation id="8284326494547611709">Untertitel</translation>
+<translation id="8346634859695247203">Abschnitt</translation>
+<translation id="835897206747267392">Ungültiger Wert.</translation>
+<translation id="8403857369060869934">verstrichene Zeit: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">Teil</translation>
+<translation id="8433900881053900389">Symbolleiste</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> Dateien</translation>
+<translation id="8451268428117625855">Wählen Sie eine Datei aus.</translation>
+<translation id="8461852803063341183">Optionsfeld</translation>
+<translation id="8474886197722836894">Widmung</translation>
+<translation id="8531739829932800271">Druckfehler</translation>
+<translation id="8534579021159131403">Minuten</translation>
+<translation id="8541249477527128034">Mediensteuerung</translation>
+<translation id="8550857728288566671">Grafiksymbol</translation>
+<translation id="8583702881314752957">Definitionsliste</translation>
+<translation id="8597182159515967513">Kopfzeile</translation>
+<translation id="860475260694818407">Inhaltsverzeichnis</translation>
+<translation id="8613126697340063924">Remote-Wiedergabe steuern</translation>
+<translation id="862370744433916922">Untertitel</translation>
+<translation id="8711688047404765493">Ausgang</translation>
+<translation id="8750798805984357768">Wählen Sie eine dieser Optionen aus.</translation>
+<translation id="8808573423886751634">Kapitel</translation>
+<translation id="8822203815165896261">Authoring-Info</translation>
+<translation id="8845239796550121995">Wird gerade auf Ihren Fernseher gestreamt</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Videowiedergabefehler</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Monat</translation>
+<translation id="901493112792887934">Aktuelle Dauer in Sekunden</translation>
+<translation id="901834265349196618">E-Mail</translation>
+<translation id="9048119486235211610">Navigation</translation>
+<translation id="9062295712474918030">Dokument</translation>
+<translation id="9093215626363556771">Bild-im-Bild-Modus beenden</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Andere...</translation>
+<translation id="9138385573473225930">Benachrichtigung</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> ab dem <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Bild-in-Bild</translation>
+<translation id="9168329111483466115">Fußnote</translation>
+<translation id="954003015749068518">Bild-im-Bild-Modus aktivieren</translation>
+<translation id="966787709310836684">Menü</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..4e90df54069
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_el.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="el">
+<translation id="1018939186200882850">στοιχείο μενού</translation>
+<translation id="10623998915015855">κουμπί εναλλαγής</translation>
+<translation id="1088086359088493902">Δευτερόλεπτα</translation>
+<translation id="1171774979989969504">Εισαγάγετε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
+<translation id="1178581264944972037">Παύση</translation>
+<translation id="1188858454923323853">συμπληρωματικό</translation>
+<translation id="1206619573307042055">μαρκίζα</translation>
+<translation id="1206693055195146388">ρυθμιστικό</translation>
+<translation id="1211441953136645838">σημείωση τέλους</translation>
+<translation id="1281252709823657822">παράθυρο διαλόγου</translation>
+<translation id="1335095011850992622">συντελεστές</translation>
+<translation id="1342835525016946179">άρθρο</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">περιοχή</translation>
+<translation id="1591562245178063882">Αυτόν το μήνα</translation>
+<translation id="1637811476055996098">Επιλογή αρχείων</translation>
+<translation id="1650423536718072820">ελκυστική φράση</translation>
+<translation id="1727886345390570319">απόκρυψη μενού υποτίτλων</translation>
+<translation id="1729654308190250600">Καταχωρίστε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
+<translation id="1758486001363313524">Άλλες…</translation>
+<translation id="1806710327868736751">παράθυρο διαλόγου ειδοποιήσεων</translation>
+<translation id="1821985195704844674">πλέγμα δέντρου</translation>
+<translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
+<translation id="1832974991323546415">αναπαραγωγή σε απομακρυσμένη συσκευή</translation>
+<translation id="190587075670221089">διαγραφή</translation>
+<translation id="1907737156431278478">παράδειγμα</translation>
+<translation id="1921819250265091946">ηη</translation>
+<translation id="1930711995431081526">κατάσταση</translation>
+<translation id="1938124657309484470">Η τιμή πρέπει να είναι <ph name="MAXIMUM_DATE_OR_TIME" /> ή προγενέστερη.</translation>
+<translation id="1946271899482435442">Εμφάνιση εργαλείου επιλογής ημερομηνίας</translation>
+<translation id="1993104285338243655">Εναλλαγή σε κατοπτρισμό</translation>
+<translation id="2060505056492490888">Το σύμβολο "<ph name="DOT" />" χρησιμοποιείται σε λάθος θέση στη διεύθυνση "<ph name="INVALIDDOMAIN" />".</translation>
+<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="2247351761944213033">Εβδομάδα <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Κομμάτι <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">πλαίσιο ελέγχου</translation>
+<translation id="2311842470354187719">αλλαγή σελίδας</translation>
+<translation id="2335594187091864976">εργαλείο επιλογής ημερομηνίας και ώρας</translation>
+<translation id="245932805758469625">χρόνος που απομένει από το βίντεο σε δευτερόλεπτα</translation>
+<translation id="248395913932153421">Ημέρα</translation>
+<translation id="2507943997699731163">Συμπληρώστε αυτό το πεδίο.</translation>
+<translation id="2508569020611168319">λίστα καρτελών</translation>
+<translation id="2561842179657104141">εμφάνιση περισσότερων στοιχείων ελέγχου μέσων</translation>
+<translation id="2572483411312390101">αναπαραγωγή</translation>
+<translation id="2613802280814924224">Καταχωρίστε μια έγκυρη τιμή. Η κοντινότερη έγκυρη τιμή είναι <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Υποβολή</translation>
+<translation id="2657045182931379222">αντικείμενο γραφικών</translation>
+<translation id="2674318244760992338">υποσέλιδο</translation>
+<translation id="2709516037105925701">Αυτόματη συμπλήρωση</translation>
+<translation id="2723001399770238859">ήχος</translation>
+<translation id="2725963129578236554">σχόλια</translation>
+<translation id="2746543609216772311">Η τιμή πρέπει να είναι <ph name="MINIMUM_DATE_OR_TIME" /> ή μεταγενέστερη.</translation>
+<translation id="2759744352195237655">αναδυόμενο κουμπί</translation>
+<translation id="2761667185364618470">Αν θέλετε να συνεχίσετε, επιλέξτε αυτό το πλαίσιο.</translation>
+<translation id="2844350028562914727">λεπτομέρειες</translation>
+<translation id="2896972712917208084">ομάδα κουμπιών επιλογής</translation>
+<translation id="2908441821576996758">Εισαγάγετε μια λίστα διευθύνσεων ηλεκτρονικού ταχυδρομείου διαχωρισμένη με κόμματα.</translation>
+<translation id="2940813599313844715">αντικείμενο</translation>
+<translation id="3040011195152428237">σύνδεσμος</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Καταχωρίστε μια έγκυρη τιμή. Το πεδίο είναι ελλιπές ή περιέχει μη έγκυρη ημερομηνία.</translation>
+<translation id="3078740164268491126">πίνακας</translation>
+<translation id="3086746722712840547">σημείωση</translation>
+<translation id="310520048233152454">Εισαγάγετε μια διεύθυνση URL.</translation>
+<translation id="3175736971608411871">χρονόμετρο</translation>
+<translation id="3199563858620722075">σύνθετο πλαίσιο</translation>
+<translation id="3450233048674729344">Η τιμή πρέπει να είναι μικρότερη ή ίση του <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">ορισμός</translation>
+<translation id="3557673793733683882">επικεφαλίδα <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">επιλογέας εβδομάδας</translation>
+<translation id="3685101356851116974">Εικόνα χωρίς ετικέτα</translation>
+<translation id="3706100364254443312">εναλλαγή</translation>
+<translation id="3732799496749320381">μμ</translation>
+<translation id="3754210790023674521">Έξοδος από τη λειτουργία picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">όρος</translation>
+<translation id="3822383571486410024">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
+<translation id="383465348367842624">Το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Έξοδος από πλήρη οθόνη</translation>
+<translation id="3889183436948184105">αναθεώρηση</translation>
+<translation id="3920932319529768807">συμπέρασμα</translation>
+<translation id="3924558731517983934">εφαρμογή</translation>
+<translation id="3944740393230681990">πρόλογος</translation>
+<translation id="3960700977367013758">γραμμή κύλισης</translation>
+<translation id="4103419683916926126">Χιλιοστά του δευτερολέπτου</translation>
+<translation id="4151657705144244502">γραφικό</translation>
+<translation id="4160057747563657758">τηλέφωνο</translation>
+<translation id="4193965531860883258">εισαγωγή</translation>
+<translation id="4201051445878709314">Εμφάνιση προηγούμενου μήνα</translation>
+<translation id="421884353938374759">επιλογέας χρώματος</translation>
+<translation id="4248100235867064564">γραμμή μενού</translation>
+<translation id="4360991593054037559">Καταχωρίστε μια έγκυρη τιμή. Οι δύο πιο κοντινές έγκυρες τιμές είναι <ph name="VALID_VALUE_LOW" /> και <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Ερωτήσεις και απαντήσεις</translation>
+<translation id="4413860115965805769">κουμπί μενού</translation>
+<translation id="4444765639179266822">Φαίνεται πως λέει: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">αναφορά στο γλωσσάρι</translation>
+<translation id="4522570452068850558">Λεπτομέρειες</translation>
+<translation id="4542388879936266156">χρόνος που απομένει: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">φόρμα</translation>
+<translation id="4661075872484491155">δέντρο</translation>
+<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">παράρτημα</translation>
+<translation id="4718048029184481307">Αναπαραγωγή σε λειτουργία picture-in-picture</translation>
+<translation id="4742539557769756338">εξώφυλλο</translation>
+<translation id="4748357248530471599">εναλλαγή πλήρους οθόνης εγκοπής οθόνης</translation>
+<translation id="4757246831282535685">παράθυρο καρτέλας</translation>
+<translation id="4763480195061959176">βίντεο</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Εισαγάγετε έναν αριθμό.</translation>
+<translation id="4912536737030637138">βιβλιογραφική καταχώριση</translation>
+<translation id="4975562563186953947">Επιλέχτηκαν <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Κατάργηση σίγασης</translation>
+<translation id="49969490063480558">Καταχωρίστε το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
+<translation id="5034860022980953847">ένδειξη προόδου</translation>
+<translation id="5090250355906949916">δείκτης χρόνου βίντεο</translation>
+<translation id="5093189678851173835">επιγραφή</translation>
+<translation id="5117590920725113268">Εμφάνιση επόμενου μήνα</translation>
+<translation id="512758898067543763">κεφαλίδα σειράς</translation>
+<translation id="5143125788380636750">επίλογος</translation>
+<translation id="5164977714490026579">Η τιμή πρέπει να είναι μεγαλύτερη ή ίση του <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Καταχωρίστε το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
+<translation id="5334352251556557839">Δεν είναι δυνατή η αναπαραγωγή μέσων.</translation>
+<translation id="5406322316791861025">αριθμός</translation>
+<translation id="5453733299334684579">στοιχείο δέντρου</translation>
+<translation id="5466621249238537318">Επιλέξτε ένα ή περισσότερα αρχεία.</translation>
+<translation id="5468998798572797635">έξοδος από πλήρη οθόνη</translation>
+<translation id="5516424706154626233">εργαλείο επιλογής ημερομηνίας</translation>
+<translation id="5537725057119320332">Μετάδοση</translation>
+<translation id="5546461542133609677">κατάργηση σίγασης</translation>
+<translation id="5608153257855394627">επισήμανση</translation>
+<translation id="561939826962581046">ώρα</translation>
+<translation id="5630795885300617244">Πατήστε δύο φορές αριστερά ή δεξιά, για να παραβλέψετε 10 δευτ.</translation>
+<translation id="5631759159893697722">περίληψη</translation>
+<translation id="5643186887447432888">κουμπί</translation>
+<translation id="5677946354068040947">περισσότερες επιλογές</translation>
+<translation id="576709008726043716">εισαγωγή</translation>
+<translation id="57838592816432529">Σίγαση</translation>
+<translation id="5860033963881614850">Απενεργοποιημένη</translation>
+<translation id="588258955323874662">Πλήρης οθόνη</translation>
+<translation id="5888666972993069672">Μετάδοση τώρα στη συσκευή <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">πλαίσιο αναζήτησης</translation>
+<translation id="5939518447894949180">Επαναφορά</translation>
+<translation id="5966707198760109579">Εβδομάδα</translation>
+<translation id="5987525920412732405">κουμπί αυξομείωσης</translation>
+<translation id="6011459053400940133">ρυθμιστικό έντασης ήχου</translation>
+<translation id="6015796118275082299">Έτος</translation>
+<translation id="6023896073578205740">πλαίσιο λίστας</translation>
+<translation id="6150588977291308318">βιβλιογραφία</translation>
+<translation id="6164829606128959761">μετρητής</translation>
+<translation id="6166809985690652833">επίλογος</translation>
+<translation id="6209276755895393898">Φαίνεται πως είναι: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">γλωσσάρι</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Έξοδος από τη λειτουργία Picture-in-Picture</translation>
+<translation id="6398862346408813489">Εμφάνιση παραθύρου επιλογής μήνα</translation>
+<translation id="6404546809543547843">δείκτης χρόνου ήχου</translation>
+<translation id="6443871981718447451">εμφάνιση μενού υποτίτλων</translation>
+<translation id="6453774872122745852">ευχαριστίες</translation>
+<translation id="6475115390776617481">παρουσία σε πραγματικό χρόνο</translation>
+<translation id="648732519525291180">εργαλείο επιλογής ώρας</translation>
+<translation id="6550675742724504774">Επιλογές</translation>
+<translation id="6572309429103589720">Μη έγκυρη γραμματική</translation>
+<translation id="658823671542763450">ενεργοποίηση πλήρους οθόνης</translation>
+<translation id="663493177488814956">ροή</translation>
+<translation id="6637586476836377253">αρχείο καταγραφής</translation>
+<translation id="6643016212128521049">Διαγραφή</translation>
+<translation id="668171684555832681">Άλλο...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Κακή ποιότητα αναπαραγωγής</translation>
+<translation id="6755330956360078551">επεξήγηση εργαλείου</translation>
+<translation id="6790428901817661496">Αναπαραγωγή</translation>
+<translation id="6820355525329141109">Δεν είναι δυνατή η φόρτωση της προσθήκης.</translation>
+<translation id="6820615603175220800">βιβλιογραφική αναφορά</translation>
+<translation id="6843725295806269523">σίγαση</translation>
+<translation id="6885760532393684712">κατάλογος</translation>
+<translation id="689129560213475294">εκδοτικό σήμα</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">κεφαλίδα</translation>
+<translation id="6941933287844615239">λήψη μέσων</translation>
+<translation id="6981594929165378967">εισαγωγή</translation>
+<translation id="6989848892321993519">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε 1 χαρακτήρα).</translation>
+<translation id="7034405885550056553">πρόταση</translation>
+<translation id="709897737746224366">Αντιστοιχίστε τη ζητούμενη μορφή.</translation>
+<translation id="7118469954320184356">Δεν υπάρχει διαθέσιμη περιγραφή.</translation>
+<translation id="7139483182332611405">πρόλογος</translation>
+<translation id="7214187073215825913">πληροφορίες για το περιεχόμενο</translation>
+<translation id="7263440858009898357">Επιλέξτε ένα στοιχείο από τη λίστα.</translation>
+<translation id="727747134524199931">κεφαλίδα στήλης</translation>
+<translation id="7320576522385648310">αποθήκευση στην προσωρινή μνήμη</translation>
+<translation id="7353453495576941748">εύσημα</translation>
+<translation id="7364796246159120393">Επιλογή αρχείου</translation>
+<translation id="739024184232394898">Άλλες…</translation>
+<translation id="7405738980073107433">σημειώσεις τέλους</translation>
+<translation id="7410239719251593705">Φαίνεται να περιέχει περιεχόμενο για ενηλίκους Δεν υπάρχει διαθέσιμη περιγραφή.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">καρτέλα</translation>
+<translation id="7514365320538308">Λήψη</translation>
+<translation id="7529102961911894712">σύνδεσμος επιστροφής</translation>
+<translation id="7533959249147584474">Γραφικό χωρίς ετικέτα</translation>
+<translation id="7647456547678091388">συμβουλή</translation>
+<translation id="7661956066982048809">έγγραφο γραφικών</translation>
+<translation id="7673697353781729403">Ώρες</translation>
+<translation id="7681220483256441252">ευρετήριο</translation>
+<translation id="7740050170769002709">Περιεχόμενο HTML</translation>
+<translation id="7745230546936012372">Για να λάβετε περιγραφές εικόνων που λείπουν, ανοίξτε το μενού περιβάλλοντος.</translation>
+<translation id="7750228210027921155">Picture in picture</translation>
+<translation id="775297008183122718">Μη έγκυρη καταχώριση</translation>
+<translation id="7789962463072032349">παύση</translation>
+<translation id="7802800022689234070">τρίγωνο εμφάνισης/απόκρυψης</translation>
+<translation id="7888071071722539607">Συμπεριλάβετε το σύμβολο "<ph name="ATSIGN" />" στη διεύθυνση ηλεκτρονικού ταχυδρομείου. Από τη διεύθυνση "<ph name="INVALIDADDRESS" />" λείπει το σύμβολο "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">διαχωριστής</translation>
+<translation id="795667975304826397">Δεν επιλέχθηκε κανένα αρχείο.</translation>
+<translation id="8053789581856978548">αναζήτηση πεδίου κειμένου</translation>
+<translation id="8057695513531652401">ειδοποίηση</translation>
+<translation id="8105797009065549151">παραπομπή</translation>
+<translation id="811583516810654505">Λήψη περιγραφής…</translation>
+<translation id="8117451130807776954">Αυτήν την εβδομάδα</translation>
+<translation id="8199524924445686405">εεεε</translation>
+<translation id="8208673686607688524">επιλογέας τοπικής ώρας και ημερομηνίας</translation>
+<translation id="8261464734335370856">Μη έγκυρη ορθογραφία</translation>
+<translation id="8284326494547611709">Υπότιτλοι</translation>
+<translation id="8346634859695247203">ενότητα</translation>
+<translation id="835897206747267392">Μη έγκυρη τιμή.</translation>
+<translation id="8403857369060869934">χρόνος που παρήλθε: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">τμήμα</translation>
+<translation id="8433900881053900389">γραμμή εργαλείων</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> αρχεία</translation>
+<translation id="8451268428117625855">Επιλέξτε ένα αρχείο.</translation>
+<translation id="8461852803063341183">κουμπί επιλογής</translation>
+<translation id="8474886197722836894">αφιέρωση</translation>
+<translation id="8531739829932800271">τυπογραφικά λάθη</translation>
+<translation id="8534579021159131403">Λεπτά</translation>
+<translation id="8541249477527128034">έλεγχος μέσων</translation>
+<translation id="8550857728288566671">σύμβολο γραφικών</translation>
+<translation id="8583702881314752957">λίστα ορισμών</translation>
+<translation id="8597182159515967513">επικεφαλίδα</translation>
+<translation id="860475260694818407">πίνακας περιεχομένων</translation>
+<translation id="8613126697340063924">έλεγχος απομακρυσμένης αναπαραγωγής</translation>
+<translation id="862370744433916922">υπότιτλος</translation>
+<translation id="8711688047404765493">έξοδος</translation>
+<translation id="8750798805984357768">Ορίστε μία από αυτές τις επιλογές.</translation>
+<translation id="8808573423886751634">κεφάλαιο</translation>
+<translation id="8822203815165896261">πληροφορίες σύνταξης</translation>
+<translation id="8845239796550121995">Γίνεται μετάδοση στην TV</translation>
+<translation id="8851136666856101339">κύριο</translation>
+<translation id="8875657656876809964">Σφάλμα αναπαραγωγής βίντεο</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Μήνας</translation>
+<translation id="901493112792887934">τρέχων χρόνος σε δευτερόλεπτα</translation>
+<translation id="901834265349196618">ηλεκτρονικό ταχυδρομείο</translation>
+<translation id="9048119486235211610">πλοήγηση</translation>
+<translation id="9062295712474918030">έγγραφο</translation>
+<translation id="9093215626363556771">έξοδος από τη λειτουργία picture-in-picture</translation>
+<translation id="9108370397979208512">μαθηματικά</translation>
+<translation id="9132465097189459683">Άλλες…</translation>
+<translation id="9138385573473225930">ειδοποίηση</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, από τις <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Παράθεση εικόνων</translation>
+<translation id="9168329111483466115">υποσημείωση</translation>
+<translation id="954003015749068518">είσοδος στη λειτουργία picture-in-picture</translation>
+<translation id="966787709310836684">μενού</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..5b254e5d654
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_en-GB.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="en-GB">
+<translation id="1018939186200882850">menu item</translation>
+<translation id="10623998915015855">toggle button</translation>
+<translation id="1088086359088493902">Seconds</translation>
+<translation id="1171774979989969504">Please enter an email address.</translation>
+<translation id="1178581264944972037">Pause</translation>
+<translation id="1188858454923323853">complementary</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">slider</translation>
+<translation id="1211441953136645838">endnote</translation>
+<translation id="1281252709823657822">dialogue</translation>
+<translation id="1335095011850992622">credits</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">region</translation>
+<translation id="1591562245178063882">This month</translation>
+<translation id="1637811476055996098">Choose Files</translation>
+<translation id="1650423536718072820">pullquote</translation>
+<translation id="1727886345390570319">hide closed captions menu</translation>
+<translation id="1729654308190250600">Please enter a non-empty email address.</translation>
+<translation id="1758486001363313524">Other...</translation>
+<translation id="1806710327868736751">alert_dialogue</translation>
+<translation id="1821985195704844674">tree grid</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">play on remote device</translation>
+<translation id="190587075670221089">deletion</translation>
+<translation id="1907737156431278478">example</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Value must be <ph name="MAXIMUM_DATE_OR_TIME" /> or earlier.</translation>
+<translation id="1946271899482435442">Show date picker</translation>
+<translation id="1993104285338243655">Switched to mirroring</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' is used at a wrong position in '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Today</translation>
+<translation id="2158401438286456825">page list</translation>
+<translation id="2226276347425096477">Please shorten this text to <ph name="MAX_CHARACTERS" /> characters or less (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
+<translation id="2246498165605549352">Local file</translation>
+<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">Tick box</translation>
+<translation id="2311842470354187719">page break</translation>
+<translation id="2335594187091864976">date and time picker</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>
+<translation id="2508569020611168319">tab list</translation>
+<translation id="2561842179657104141">show more media controls</translation>
+<translation id="2572483411312390101">play</translation>
+<translation id="2613802280814924224">Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Submit</translation>
+<translation id="2657045182931379222">graphics object</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="2709516037105925701">Auto-fill</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">comments</translation>
+<translation id="2746543609216772311">Value must be <ph name="MINIMUM_DATE_OR_TIME" /> or later.</translation>
+<translation id="2759744352195237655">pop-up button</translation>
+<translation id="2761667185364618470">Please tick this box if you want to proceed.</translation>
+<translation id="2844350028562914727">details</translation>
+<translation id="2896972712917208084">radio group</translation>
+<translation id="2908441821576996758">Please enter a comma-separated list of email addresses.</translation>
+<translation id="2940813599313844715">object</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Please enter a valid value. The field is incomplete or has an invalid date.</translation>
+<translation id="3078740164268491126">table</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Please enter a URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">combo box</translation>
+<translation id="3450233048674729344">Value must be less than or equal to <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">heading <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">week picker</translation>
+<translation id="3685101356851116974">Unlabelled image</translation>
+<translation id="3706100364254443312">switch</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Exit picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">term</translation>
+<translation id="3822383571486410024">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
+<translation id="383465348367842624">A part followed by '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">Exit full screen</translation>
+<translation id="3889183436948184105">revision</translation>
+<translation id="3920932319529768807">conclusion</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
+<translation id="3960700977367013758">scroll bar</translation>
+<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="4151657705144244502">graphic</translation>
+<translation id="4160057747563657758">telephone</translation>
+<translation id="4193965531860883258">foreword</translation>
+<translation id="4201051445878709314">Show previous month</translation>
+<translation id="421884353938374759">colour picker</translation>
+<translation id="4248100235867064564">menu bar</translation>
+<translation id="4360991593054037559">Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW" /> and <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
+<translation id="4413860115965805769">menu button</translation>
+<translation id="4444765639179266822">Appears to say: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">glossary reference</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">remaining time: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">A part following '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">appendix</translation>
+<translation id="4718048029184481307">Playing in picture-in-picture</translation>
+<translation id="4742539557769756338">cover</translation>
+<translation id="4748357248530471599">toggle display cutout full screen</translation>
+<translation id="4757246831282535685">tab panel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Please enter a number.</translation>
+<translation id="4912536737030637138">bibliography entry</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selected</translation>
+<translation id="4992066212339426712">Unmute</translation>
+<translation id="49969490063480558">Please enter a part following '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
+<translation id="5034860022980953847">progress indicator</translation>
+<translation id="5090250355906949916">video time scrubber</translation>
+<translation id="5093189678851173835">epigraph</translation>
+<translation id="5117590920725113268">Show next month</translation>
+<translation id="512758898067543763">row header</translation>
+<translation id="5143125788380636750">epilogue</translation>
+<translation id="5164977714490026579">Value must be greater than or equal to <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Please enter a part followed by '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
+<translation id="5334352251556557839">Unable to play media.</translation>
+<translation id="5406322316791861025">figure</translation>
+<translation id="5453733299334684579">tree item</translation>
+<translation id="5466621249238537318">Please select one or more files.</translation>
+<translation id="5468998798572797635">exit full screen</translation>
+<translation id="5516424706154626233">date picker</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">un-mute</translation>
+<translation id="5608153257855394627">highlight</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Double-tap left or right to skip 10s</translation>
+<translation id="5631759159893697722">abstract</translation>
+<translation id="5643186887447432888">button</translation>
+<translation id="5677946354068040947">more options</translation>
+<translation id="576709008726043716">introduction</translation>
+<translation id="57838592816432529">Mute</translation>
+<translation id="5860033963881614850">Off</translation>
+<translation id="588258955323874662">Full screen</translation>
+<translation id="5888666972993069672">Now casting to <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">search box</translation>
+<translation id="5939518447894949180">Reset</translation>
+<translation id="5966707198760109579">Week</translation>
+<translation id="5987525920412732405">spin button</translation>
+<translation id="6011459053400940133">volume slider</translation>
+<translation id="6015796118275082299">Year</translation>
+<translation id="6023896073578205740">list box</translation>
+<translation id="6150588977291308318">bibliography</translation>
+<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">afterword</translation>
+<translation id="6209276755895393898">Appears to be: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossary</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Exit picture-in-picture</translation>
+<translation id="6398862346408813489">Show month selection panel</translation>
+<translation id="6404546809543547843">audio time scrubber</translation>
+<translation id="6443871981718447451">show closed captions menu</translation>
+<translation id="6453774872122745852">acknowledgements</translation>
+<translation id="6475115390776617481">live presence</translation>
+<translation id="648732519525291180">time picker</translation>
+<translation id="6550675742724504774">Options</translation>
+<translation id="6572309429103589720">Invalid grammar</translation>
+<translation id="658823671542763450">enter full screen</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Clear</translation>
+<translation id="668171684555832681">Other...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Poor playback quality</translation>
+<translation id="6755330956360078551">tooltip</translation>
+<translation id="6790428901817661496">Play</translation>
+<translation id="6820355525329141109">Couldn't load plug-in.</translation>
+<translation id="6820615603175220800">bibliography reference</translation>
+<translation id="6843725295806269523">mute</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colophon</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">header</translation>
+<translation id="6941933287844615239">download media</translation>
+<translation id="6981594929165378967">insertion</translation>
+<translation id="6989848892321993519">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using 1 character).</translation>
+<translation id="7034405885550056553">suggestion</translation>
+<translation id="709897737746224366">Please match the format requested.</translation>
+<translation id="7118469954320184356">No description available.</translation>
+<translation id="7139483182332611405">preface</translation>
+<translation id="7214187073215825913">content information</translation>
+<translation id="7263440858009898357">Please select an item in the list.</translation>
+<translation id="727747134524199931">column header</translation>
+<translation id="7320576522385648310">buffering</translation>
+<translation id="7353453495576941748">credit</translation>
+<translation id="7364796246159120393">Choose file</translation>
+<translation id="739024184232394898">Other...</translation>
+<translation id="7405738980073107433">endnotes</translation>
+<translation id="7410239719251593705">Appears to contain adult content. No description available.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7533959249147584474">Unlabelled graphic</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">graphics document</translation>
+<translation id="7673697353781729403">Hours</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">HTML content</translation>
+<translation id="7745230546936012372">To get missing image descriptions, open the context menu.</translation>
+<translation id="7750228210027921155">Picture-in-picture</translation>
+<translation id="775297008183122718">Invalid entry</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">disclosure triangle</translation>
+<translation id="7888071071722539607">Please include an '<ph name="ATSIGN" />' in the email address. '<ph name="INVALIDADDRESS" />' is missing an '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">splitter</translation>
+<translation id="795667975304826397">No file chosen</translation>
+<translation id="8053789581856978548">search text field</translation>
+<translation id="8057695513531652401">notice</translation>
+<translation id="8105797009065549151">note reference</translation>
+<translation id="811583516810654505">Getting description...</translation>
+<translation id="8117451130807776954">This week</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">local date and time picker</translation>
+<translation id="8261464734335370856">Invalid spelling</translation>
+<translation id="8284326494547611709">Captions</translation>
+<translation id="8346634859695247203">section</translation>
+<translation id="835897206747267392">Invalid value.</translation>
+<translation id="8403857369060869934">elapsed time: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">part</translation>
+<translation id="8433900881053900389">toolbar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> files</translation>
+<translation id="8451268428117625855">Please select a file.</translation>
+<translation id="8461852803063341183">radio button</translation>
+<translation id="8474886197722836894">dedication</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutes</translation>
+<translation id="8541249477527128034">media control</translation>
+<translation id="8550857728288566671">graphics symbol</translation>
+<translation id="8583702881314752957">definition list</translation>
+<translation id="8597182159515967513">heading</translation>
+<translation id="860475260694818407">table of contents</translation>
+<translation id="8613126697340063924">control remote playback</translation>
+<translation id="862370744433916922">subtitle</translation>
+<translation id="8711688047404765493">output</translation>
+<translation id="8750798805984357768">Please select one of these options.</translation>
+<translation id="8808573423886751634">chapter</translation>
+<translation id="8822203815165896261">authoring info</translation>
+<translation id="8845239796550121995">Now casting to your TV</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Video playback error</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Month</translation>
+<translation id="901493112792887934">current time in seconds</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">navigation</translation>
+<translation id="9062295712474918030">document</translation>
+<translation id="9093215626363556771">exit picture-in-picture</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Other...</translation>
+<translation id="9138385573473225930">alert</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, starting on <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture in Picture</translation>
+<translation id="9168329111483466115">footnote</translation>
+<translation id="954003015749068518">enter picture-in-picture</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..8a3514f8910
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_es-419.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es-419">
+<translation id="1018939186200882850">elemento del menú</translation>
+<translation id="10623998915015855">botón de activación</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="1171774979989969504">Ingresa una dirección de correo electrónico.</translation>
+<translation id="1178581264944972037">Detener</translation>
+<translation id="1188858454923323853">complementario</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
+<translation id="1281252709823657822">diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
+<translation id="1342835525016946179">artículo</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">región</translation>
+<translation id="1591562245178063882">Este mes</translation>
+<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="1650423536718072820">cita inicial</translation>
+<translation id="1727886345390570319">oculta el menú de subtítulos opcionales</translation>
+<translation id="1729654308190250600">Ingresa una dirección de correo electrónico que no esté vacía.</translation>
+<translation id="1758486001363313524">Otra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">cuadrícula de árbol</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">jugar en el dispositivo remoto</translation>
+<translation id="190587075670221089">contenido borrado</translation>
+<translation id="1907737156431278478">ejemplo</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
+<translation id="1946271899482435442">Mostrar el selector de fechas</translation>
+<translation id="1993104285338243655">Se cambió a duplicación</translation>
+<translation id="2060505056492490888">El signo "<ph name="DOT" />" está colocado en una posición incorrecta en "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Hoy</translation>
+<translation id="2158401438286456825">listado de páginas</translation>
+<translation id="2226276347425096477">Acorta este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente estás usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Archivo local</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2311842470354187719">salto de página</translation>
+<translation id="2335594187091864976">selector de fecha y hora</translation>
+<translation id="245932805758469625">cantidad de segundos restantes del video</translation>
+<translation id="248395913932153421">Día</translation>
+<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="2508569020611168319">lista de pestañas</translation>
+<translation id="2561842179657104141">mostrar más controles de medios</translation>
+<translation id="2572483411312390101">reproducir</translation>
+<translation id="2613802280814924224">Ingresa un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
+<translation id="2674318244760992338">pie de página</translation>
+<translation id="2709516037105925701">Autocompletar</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">comentarios</translation>
+<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">botón con ventana emergente</translation>
+<translation id="2761667185364618470">Controla esta casilla si deseas continuar.</translation>
+<translation id="2844350028562914727">detalles</translation>
+<translation id="2896972712917208084">grupo de botones de selección</translation>
+<translation id="2908441821576996758">Ingresa una lista de direcciones de correo electrónico separadas por coma</translation>
+<translation id="2940813599313844715">objeto</translation>
+<translation id="3040011195152428237">enlace</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Debes ingresar un valor válido. El campo está incompleto o contiene una fecha no válida.</translation>
+<translation id="3078740164268491126">tabla</translation>
+<translation id="3086746722712840547">nota</translation>
+<translation id="310520048233152454">Ingresa una URL.</translation>
+<translation id="3175736971608411871">cronómetro</translation>
+<translation id="3199563858620722075">cuadro combinado</translation>
+<translation id="3450233048674729344">El valor debe ser menor de o igual a <ph name="MAXIMUM" /></translation>
+<translation id="3486220673238053218">definición</translation>
+<translation id="3557673793733683882">encabezado <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selector de semana</translation>
+<translation id="3685101356851116974">Imagen sin etiquetar</translation>
+<translation id="3706100364254443312">cambiar</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Salir del modo de pantalla en pantalla</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">término</translation>
+<translation id="3822383571486410024">Alarga el texto a <ph name="MIN_CHARACTERS" /> o más caracteres (actualmente, usas <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="383465348367842624">El texto antes del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Salir de pantalla completa</translation>
+<translation id="3889183436948184105">revisión</translation>
+<translation id="3920932319529768807">conclusión</translation>
+<translation id="3924558731517983934">aplicación</translation>
+<translation id="3944740393230681990">prólogo</translation>
+<translation id="3960700977367013758">barra de desplazamiento</translation>
+<translation id="4103419683916926126">Milisegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
+<translation id="4160057747563657758">teléfono</translation>
+<translation id="4193965531860883258">prefacio</translation>
+<translation id="4201051445878709314">Mostrar el mes anterior</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4360991593054037559">Ingresa un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntas y respuestas</translation>
+<translation id="4413860115965805769">botón de menú</translation>
+<translation id="4444765639179266822">Parece decir: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referencia de glosario</translation>
+<translation id="4522570452068850558">Detalles</translation>
+<translation id="4542388879936266156">tiempo restante: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulario</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">El texto después del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apéndice</translation>
+<translation id="4718048029184481307">Reproduciendo en modo de pantalla en pantalla</translation>
+<translation id="4742539557769756338">portada</translation>
+<translation id="4748357248530471599">activar o desactivar la pantalla completa en el corte de pantalla</translation>
+<translation id="4757246831282535685">panel de pestañas</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Debes ingresar un número.</translation>
+<translation id="4912536737030637138">entrada de bibliografía</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> elementos seleccionados</translation>
+<translation id="4992066212339426712">Dejar de silenciar</translation>
+<translation id="49969490063480558">Ingresa texto después del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5034860022980953847">indicador de progreso</translation>
+<translation id="5090250355906949916">control deslizante de duración del video</translation>
+<translation id="5093189678851173835">epígrafe</translation>
+<translation id="5117590920725113268">Mostrar el mes siguiente</translation>
+<translation id="512758898067543763">encabezado de fila</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5164977714490026579">El valor debe ser mayor de o igual a <ph name="MINIMUM" /></translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Ingresa texto antes del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5334352251556557839">No es posible reproducir los archivos multimedia.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">elemento de árbol</translation>
+<translation id="5466621249238537318">Selecciona uno o más archivos.</translation>
+<translation id="5468998798572797635">salir de pantalla completa</translation>
+<translation id="5516424706154626233">selector de fecha</translation>
+<translation id="5537725057119320332">Transmitir</translation>
+<translation id="5546461542133609677">desactivar silencio</translation>
+<translation id="5608153257855394627">destacar</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Presiona dos veces a la derecha o izquierda para omitir 10 s</translation>
+<translation id="5631759159893697722">resumen</translation>
+<translation id="5643186887447432888">botón</translation>
+<translation id="5677946354068040947">más opciones</translation>
+<translation id="576709008726043716">introducción</translation>
+<translation id="57838592816432529">Silenciar</translation>
+<translation id="5860033963881614850">No</translation>
+<translation id="588258955323874662">Pantalla completa</translation>
+<translation id="5888666972993069672">Transmitiendo ahora a <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">cuadro de búsqueda</translation>
+<translation id="5939518447894949180">Restablecer</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="5987525920412732405">botón de control numérico</translation>
+<translation id="6011459053400940133">control deslizante del volumen</translation>
+<translation id="6015796118275082299">Año</translation>
+<translation id="6023896073578205740">cuadro de lista</translation>
+<translation id="6150588977291308318">bibliografía</translation>
+<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">posfacio</translation>
+<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosario</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Salir del modo de pantalla en pantalla</translation>
+<translation id="6398862346408813489">Mostrar el panel de selección de meses</translation>
+<translation id="6404546809543547843">control deslizante de duración del audio</translation>
+<translation id="6443871981718447451">muestra el menú de subtítulos opcionales</translation>
+<translation id="6453774872122745852">reconocimientos</translation>
+<translation id="6475115390776617481">presencia en vivo</translation>
+<translation id="648732519525291180">selector de hora</translation>
+<translation id="6550675742724504774">Opciones</translation>
+<translation id="6572309429103589720">Gramática no válida</translation>
+<translation id="658823671542763450">ingresar a pantalla completa</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">rgstr</translation>
+<translation id="6643016212128521049">Borrar</translation>
+<translation id="668171684555832681">Otro...</translation>
+<translation id="6692633176391053278">secuenciador</translation>
+<translation id="6709570249143506788">Baja calidad de reproducción</translation>
+<translation id="6755330956360078551">información sobre la herramienta</translation>
+<translation id="6790428901817661496">Reproducir</translation>
+<translation id="6820355525329141109">No se pudo cargar el complemento.</translation>
+<translation id="6820615603175220800">referencia bibliográfica</translation>
+<translation id="6843725295806269523">silencio</translation>
+<translation id="6885760532393684712">directorio</translation>
+<translation id="689129560213475294">colofón</translation>
+<translation id="6934078000481955284">bloque entrecomillado</translation>
+<translation id="693476918119313863">encabezado</translation>
+<translation id="6941933287844615239">descargar medios</translation>
+<translation id="6981594929165378967">contenido agregado</translation>
+<translation id="6989848892321993519">Extiende este texto para que tenga <ph name="MIN_CHARACTERS" /> caracteres o más (actualmente usas 1 carácter).</translation>
+<translation id="7034405885550056553">sugerencia</translation>
+<translation id="709897737746224366">Haz coincidir el formato solicitado.</translation>
+<translation id="7118469954320184356">No hay una descripción disponible.</translation>
+<translation id="7139483182332611405">prefacio</translation>
+<translation id="7214187073215825913">información de contenido</translation>
+<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="727747134524199931">encabezado de columna</translation>
+<translation id="7320576522385648310">almacenando en búfer</translation>
+<translation id="7353453495576941748">crédito</translation>
+<translation id="7364796246159120393">Seleccionar archivo</translation>
+<translation id="739024184232394898">Otra...</translation>
+<translation id="7405738980073107433">notas finales</translation>
+<translation id="7410239719251593705">Al parecer, tiene contenido para adultos. No hay una descripción disponible.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Descargar</translation>
+<translation id="7529102961911894712">retrovínculo</translation>
+<translation id="7533959249147584474">Gráfico sin etiquetar</translation>
+<translation id="7647456547678091388">sugerencia</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
+<translation id="7740050170769002709">Contenido HTML</translation>
+<translation id="7745230546936012372">Para obtener las descripciones de imágenes faltantes, abre el menú contextual.</translation>
+<translation id="7750228210027921155">Pantalla en pantalla</translation>
+<translation id="775297008183122718">Entrada no válida</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triángulo desplegable</translation>
+<translation id="7888071071722539607">Incluye un signo "<ph name="ATSIGN" />" en la dirección de correo electrónico. La dirección "<ph name="INVALIDADDRESS" />" no incluye el signo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">separador</translation>
+<translation id="795667975304826397">No se eligió archivo</translation>
+<translation id="8053789581856978548">campo de texto de búsqueda</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">nota de referencia</translation>
+<translation id="811583516810654505">Obteniendo la descripción…</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selector de fecha y hora locales</translation>
+<translation id="8261464734335370856">Ortografía no válida</translation>
+<translation id="8284326494547611709">Subtítulos</translation>
+<translation id="8346634859695247203">sección</translation>
+<translation id="835897206747267392">Valor no válido.</translation>
+<translation id="8403857369060869934">tiempo transcurrido: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">barra de herramientas</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
+<translation id="8451268428117625855">Selecciona un archivo.</translation>
+<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8474886197722836894">dedicatoria</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="8541249477527128034">control de medios</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
+<translation id="8583702881314752957">lista de definiciones</translation>
+<translation id="8597182159515967513">cabecera</translation>
+<translation id="860475260694818407">índice</translation>
+<translation id="8613126697340063924">controlar la reproducción remota</translation>
+<translation id="862370744433916922">subtítulo</translation>
+<translation id="8711688047404765493">salida</translation>
+<translation id="8750798805984357768">Selecciona una de estas opciones.</translation>
+<translation id="8808573423886751634">capítulo</translation>
+<translation id="8822203815165896261">información de creación</translation>
+<translation id="8845239796550121995">Transmitiendo a tu TV</translation>
+<translation id="8851136666856101339">ppal</translation>
+<translation id="8875657656876809964">Error de reproducción de video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="901493112792887934">tiempo actual en segundos</translation>
+<translation id="901834265349196618">correo electrónico</translation>
+<translation id="9048119486235211610">navegación</translation>
+<translation id="9062295712474918030">documento</translation>
+<translation id="9093215626363556771">salir del modo de pantalla en pantalla</translation>
+<translation id="9108370397979208512">expr mtmtc</translation>
+<translation id="9132465097189459683">Otra...</translation>
+<translation id="9138385573473225930">alerta</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Pantalla en pantalla</translation>
+<translation id="9168329111483466115">nota a pie de página</translation>
+<translation id="954003015749068518">ingresar al modo de pantalla en pantalla</translation>
+<translation id="966787709310836684">menú</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..f66a0868641
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_es.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es">
+<translation id="1018939186200882850">elemento de menú</translation>
+<translation id="10623998915015855">botón de activación</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="1171774979989969504">Introduce una dirección de correo electrónico</translation>
+<translation id="1178581264944972037">Pausar</translation>
+<translation id="1188858454923323853">complementario</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
+<translation id="1281252709823657822">cuadro de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
+<translation id="1342835525016946179">artículo</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">región</translation>
+<translation id="1591562245178063882">Este mes</translation>
+<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="1650423536718072820">cita</translation>
+<translation id="1727886345390570319">ocultar menú de subtítulos</translation>
+<translation id="1729654308190250600">Introduce una dirección de correo electrónico que no esté vacía.</translation>
+<translation id="1758486001363313524">Otra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">cuadrícula de árbol</translation>
+<translation id="1822429046913737220">A.M./P.M.</translation>
+<translation id="1832974991323546415">reproducir en dispositivo remoto</translation>
+<translation id="190587075670221089">eliminación</translation>
+<translation id="1907737156431278478">ejemplo</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
+<translation id="1946271899482435442">Mostrar selector de fecha</translation>
+<translation id="1993104285338243655">Se ha cambiado a proyección</translation>
+<translation id="2060505056492490888">El signo "<ph name="DOT" />" está colocado en una posición incorrecta en la dirección "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Hoy</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
+<translation id="2226276347425096477">Reduce la longitud de este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres)</translation>
+<translation id="2246498165605549352">Archivo local</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Pista <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2311842470354187719">salto de página</translation>
+<translation id="2335594187091864976">selector de fecha y hora</translation>
+<translation id="245932805758469625">segundos de vídeo restantes</translation>
+<translation id="248395913932153421">Día</translation>
+<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="2508569020611168319">lista de pestañas</translation>
+<translation id="2561842179657104141">mostrar más controles multimedia</translation>
+<translation id="2572483411312390101">reproducir</translation>
+<translation id="2613802280814924224">Introduce un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
+<translation id="2674318244760992338">pie de página</translation>
+<translation id="2709516037105925701">Autocompletar</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">comentarios</translation>
+<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">botón emergente</translation>
+<translation id="2761667185364618470">Selecciona esta casilla de verificación si quieres continuar</translation>
+<translation id="2844350028562914727">detalles</translation>
+<translation id="2896972712917208084">grupo de selección</translation>
+<translation id="2908441821576996758">Introduce una lista de direcciones de correo electrónico separada por comas</translation>
+<translation id="2940813599313844715">objeto</translation>
+<translation id="3040011195152428237">enlace</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Debes introducir un valor válido. El campo está incompleto o incluye una fecha no válida.</translation>
+<translation id="3078740164268491126">tabla</translation>
+<translation id="3086746722712840547">nota</translation>
+<translation id="310520048233152454">Introduce una URL</translation>
+<translation id="3175736971608411871">temporizador</translation>
+<translation id="3199563858620722075">cuadro combinado</translation>
+<translation id="3450233048674729344">El valor debe ser inferior o igual a <ph name="MAXIMUM" /></translation>
+<translation id="3486220673238053218">definición</translation>
+<translation id="3557673793733683882">encabezado <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selector de semana</translation>
+<translation id="3685101356851116974">Imagen sin descripción</translation>
+<translation id="3706100364254443312">interruptor</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Salir del modo imagen en imagen</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">término</translation>
+<translation id="3822383571486410024">Aumenta la longitud del texto a <ph name="MIN_CHARACTERS" /> caracteres como mínimo (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="383465348367842624">El texto seguido del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Salir de pantalla completa</translation>
+<translation id="3889183436948184105">revisión</translation>
+<translation id="3920932319529768807">conclusión</translation>
+<translation id="3924558731517983934">aplicación</translation>
+<translation id="3944740393230681990">prólogo</translation>
+<translation id="3960700977367013758">barra de desplazamiento</translation>
+<translation id="4103419683916926126">Millisegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
+<translation id="4160057747563657758">teléfono</translation>
+<translation id="4193965531860883258">prefacio</translation>
+<translation id="4201051445878709314">Mostrar mes anterior</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4360991593054037559">Introduce un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Preguntas</translation>
+<translation id="4413860115965805769">botón de menú</translation>
+<translation id="4444765639179266822">Parece que pone: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referencia de glosario</translation>
+<translation id="4522570452068850558">Detalles</translation>
+<translation id="4542388879936266156">tiempo restante: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulario</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">El texto detrás del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apéndice</translation>
+<translation id="4718048029184481307">Reproduciendo en modo imagen en imagen</translation>
+<translation id="4742539557769756338">portada</translation>
+<translation id="4748357248530471599">activar pantalla completa en el recorte de la pantalla</translation>
+<translation id="4757246831282535685">panel de pestaña</translation>
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">buscar</translation>
+<translation id="4812940957355064477">Debes introducir un número</translation>
+<translation id="4912536737030637138">entrada bibliográfica</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> seleccionados</translation>
+<translation id="4992066212339426712">Activar sonido</translation>
+<translation id="49969490063480558">Introduce texto detrás del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5034860022980953847">indicador de progreso</translation>
+<translation id="5090250355906949916">control deslizante de duración de vídeo</translation>
+<translation id="5093189678851173835">epígrafe</translation>
+<translation id="5117590920725113268">Mostrar mes siguiente</translation>
+<translation id="512758898067543763">encabezado de fila</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5164977714490026579">El valor debe ser superior o igual a <ph name="MINIMUM" /></translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Introduce texto seguido del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5334352251556557839">No se ha podido reproducir el contenido multimedia.</translation>
+<translation id="5406322316791861025">cifra</translation>
+<translation id="5453733299334684579">elemento del árbol</translation>
+<translation id="5466621249238537318">Selecciona uno o varios archivos</translation>
+<translation id="5468998798572797635">salir de pantalla completa</translation>
+<translation id="5516424706154626233">selector de fecha</translation>
+<translation id="5537725057119320332">Enviar</translation>
+<translation id="5546461542133609677">activar sonido</translation>
+<translation id="5608153257855394627">destacado</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Toca dos veces a la derecha o a la izquierda para saltar 10 segundos</translation>
+<translation id="5631759159893697722">resumen</translation>
+<translation id="5643186887447432888">botón</translation>
+<translation id="5677946354068040947">más opciones</translation>
+<translation id="576709008726043716">introducción</translation>
+<translation id="57838592816432529">Silenciar</translation>
+<translation id="5860033963881614850">Desactivado</translation>
+<translation id="588258955323874662">Pantalla completa</translation>
+<translation id="5888666972993069672">Enviando a <ph name="DEVICE_FRIENDLY_NAME" /> en este momento</translation>
+<translation id="591047860372322273">cuadro de búsqueda</translation>
+<translation id="5939518447894949180">Restablecer</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="5987525920412732405">botón de control numérico</translation>
+<translation id="6011459053400940133">control deslizante de volumen</translation>
+<translation id="6015796118275082299">Año</translation>
+<translation id="6023896073578205740">cuadro de lista</translation>
+<translation id="6150588977291308318">bibliografía</translation>
+<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">epílogo</translation>
+<translation id="6209276755895393898">Parece que es: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosario</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Salir del modo imagen en imagen</translation>
+<translation id="6398862346408813489">Mostrar panel para seleccionar el mes</translation>
+<translation id="6404546809543547843">control deslizante de duración de audio</translation>
+<translation id="6443871981718447451">mostrar menú de subtítulos</translation>
+<translation id="6453774872122745852">agradecimientos</translation>
+<translation id="6475115390776617481">hay otro usuario presente</translation>
+<translation id="648732519525291180">selector de hora</translation>
+<translation id="6550675742724504774">Configuración</translation>
+<translation id="6572309429103589720">La gramática no es válida</translation>
+<translation id="658823671542763450">activar pantalla completa</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">registro</translation>
+<translation id="6643016212128521049">Eliminar</translation>
+<translation id="668171684555832681">Otros...</translation>
+<translation id="6692633176391053278">secuenciador</translation>
+<translation id="6709570249143506788">Calidad de reproducción baja</translation>
+<translation id="6755330956360078551">descripción emergente</translation>
+<translation id="6790428901817661496">Reproducir</translation>
+<translation id="6820355525329141109">No se ha podido cargar el complemento.</translation>
+<translation id="6820615603175220800">referencia bibliográfica</translation>
+<translation id="6843725295806269523">silenciar</translation>
+<translation id="6885760532393684712">directorio</translation>
+<translation id="689129560213475294">colofón</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">encabezado</translation>
+<translation id="6941933287844615239">descargar archivos multimedia</translation>
+<translation id="6981594929165378967">inserción</translation>
+<translation id="6989848892321993519">Aumenta la longitud de este texto a <ph name="MIN_CHARACTERS" /> caracteres o más (actualmente, el texto tiene 1 carácter).</translation>
+<translation id="7034405885550056553">sugerencia</translation>
+<translation id="709897737746224366">Utiliza un formato que coincida con el solicitado</translation>
+<translation id="7118469954320184356">No hay ninguna descripción disponible.</translation>
+<translation id="7139483182332611405">prefacio</translation>
+<translation id="7214187073215825913">información sobre el contenido</translation>
+<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="727747134524199931">encabezado de columna</translation>
+<translation id="7320576522385648310">almacenando en búfer</translation>
+<translation id="7353453495576941748">crédito</translation>
+<translation id="7364796246159120393">Seleccionar archivo</translation>
+<translation id="739024184232394898">Otra...</translation>
+<translation id="7405738980073107433">notas finales</translation>
+<translation id="7410239719251593705">Parece que incluye contenido para adultos. No hay ninguna descripción disponible.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tabulador</translation>
+<translation id="7514365320538308">Descargar</translation>
+<translation id="7529102961911894712">enlace de retroceso</translation>
+<translation id="7533959249147584474">Gráfico sin descripción</translation>
+<translation id="7647456547678091388">consejo</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
+<translation id="7740050170769002709">Contenido HTML</translation>
+<translation id="7745230546936012372">Para obtener las descripciones de las imágenes, abre el menú contextual.</translation>
+<translation id="7750228210027921155">Imagen en imagen</translation>
+<translation id="775297008183122718">Entrada no válida</translation>
+<translation id="7789962463072032349">pausar</translation>
+<translation id="7802800022689234070">triángulo de revelación</translation>
+<translation id="7888071071722539607">Incluye un signo "<ph name="ATSIGN" />" en la dirección de correo electrónico. La dirección "<ph name="INVALIDADDRESS" />" no incluye el signo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
+<translation id="795667975304826397">Ningún archivo seleccionado</translation>
+<translation id="8053789581856978548">campo para buscar texto</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referencia de nota</translation>
+<translation id="811583516810654505">Obteniendo la descripción...</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selector de fecha y hora locales</translation>
+<translation id="8261464734335370856">La ortografía no es válida</translation>
+<translation id="8284326494547611709">Subtítulos</translation>
+<translation id="8346634859695247203">sección</translation>
+<translation id="835897206747267392">Valor no válido</translation>
+<translation id="8403857369060869934">tiempo transcurrido: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">barra de herramientas</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
+<translation id="8451268428117625855">Selecciona un archivo</translation>
+<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8474886197722836894">dedicatoria</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="8541249477527128034">control de medios</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
+<translation id="8583702881314752957">lista de definiciones</translation>
+<translation id="8597182159515967513">cabecera</translation>
+<translation id="860475260694818407">índice</translation>
+<translation id="8613126697340063924">reproducción de control remoto</translation>
+<translation id="862370744433916922">subtítulo</translation>
+<translation id="8711688047404765493">salida</translation>
+<translation id="8750798805984357768">Selecciona una de estas opciones</translation>
+<translation id="8808573423886751634">capítulo</translation>
+<translation id="8822203815165896261">información sobre autoría</translation>
+<translation id="8845239796550121995">Se está enviando contenido a tu TV</translation>
+<translation id="8851136666856101339">principal</translation>
+<translation id="8875657656876809964">No se puede reproducir el vídeo</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="901493112792887934">tiempo actual en segundos</translation>
+<translation id="901834265349196618">correo electrónico</translation>
+<translation id="9048119486235211610">navegación</translation>
+<translation id="9062295712474918030">documento</translation>
+<translation id="9093215626363556771">salir del modo imagen en imagen</translation>
+<translation id="9108370397979208512">expresión matemática</translation>
+<translation id="9132465097189459683">Otra...</translation>
+<translation id="9138385573473225930">alerta</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Imagen en imagen</translation>
+<translation id="9168329111483466115">nota al pie</translation>
+<translation id="954003015749068518">abrir el modo imagen en imagen</translation>
+<translation id="966787709310836684">menú</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..18b50d4ee6d
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_et.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="et">
+<translation id="1018939186200882850">menüü-üksus</translation>
+<translation id="10623998915015855">ümberlülitusnupp</translation>
+<translation id="1088086359088493902">Sekundid</translation>
+<translation id="1171774979989969504">Sisestage meiliaadress.</translation>
+<translation id="1178581264944972037">Peata</translation>
+<translation id="1188858454923323853">täiendav</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">liugur</translation>
+<translation id="1211441953136645838">järelmärkus</translation>
+<translation id="1281252709823657822">dialoog</translation>
+<translation id="1335095011850992622">tiitrid</translation>
+<translation id="1342835525016946179">artikkel</translation>
+<translation id="1359897965706325498">bänner</translation>
+<translation id="1589122976691792535">piirkond</translation>
+<translation id="1591562245178063882">See kuu</translation>
+<translation id="1637811476055996098">Vali failid</translation>
+<translation id="1650423536718072820">tsitaat</translation>
+<translation id="1727886345390570319">peida subtiitrite menüü</translation>
+<translation id="1729654308190250600">Sisestage mittetühi e-posti aadress.</translation>
+<translation id="1758486001363313524">Muu ...</translation>
+<translation id="1806710327868736751">hoiatusdialoog</translation>
+<translation id="1821985195704844674">puuruudustik</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">kaugseadmes esitamine</translation>
+<translation id="190587075670221089">kustutamine</translation>
+<translation id="1907737156431278478">näide</translation>
+<translation id="1921819250265091946">pp</translation>
+<translation id="1930711995431081526">olek</translation>
+<translation id="1938124657309484470">Väärtus peab olema <ph name="MAXIMUM_DATE_OR_TIME" /> või varasem.</translation>
+<translation id="1946271899482435442">Kuupäevavalija kuvamine</translation>
+<translation id="1993104285338243655">Lülitatud peegeldamisele</translation>
+<translation id="2060505056492490888">Tähist „<ph name="DOT" />” on aadressis „<ph name="INVALIDDOMAIN" />” valesti kasutatud.</translation>
+<translation id="2148716181193084225">Täna</translation>
+<translation id="2158401438286456825">lehtede loend</translation>
+<translation id="2226276347425096477">Lühendage seda teksti <ph name="MAX_CHARACTERS" /> tähemärgini või rohkem (praegu kasutate <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
+<translation id="2246498165605549352">Kohalik fail</translation>
+<translation id="2247351761944213033">Nädal <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />. lugu</translation>
+<translation id="2291999235780842123">märkeruut</translation>
+<translation id="2311842470354187719">leheküljepiir</translation>
+<translation id="2335594187091864976">kuupäeva ja kellaaja valija</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>
+<translation id="2508569020611168319">vahelehtede loend</translation>
+<translation id="2561842179657104141">kuva rohkem meedia juhtnuppe</translation>
+<translation id="2572483411312390101">esitus</translation>
+<translation id="2613802280814924224">Sisestage kehtiv väärtus. Lähim kehtiv väärtus on <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Esita</translation>
+<translation id="2657045182931379222">graafika objekt</translation>
+<translation id="2674318244760992338">jalus</translation>
+<translation id="2709516037105925701">Automaatne täitmine</translation>
+<translation id="2723001399770238859">heli</translation>
+<translation id="2725963129578236554">kommentaarid</translation>
+<translation id="2746543609216772311">Väärtus peab olema <ph name="MINIMUM_DATE_OR_TIME" /> või hilisem.</translation>
+<translation id="2759744352195237655">hüpikunupp</translation>
+<translation id="2761667185364618470">Märkige see ruut, kui soovite jätkata.</translation>
+<translation id="2844350028562914727">üksikasjad</translation>
+<translation id="2896972712917208084">raadionuppude grupp</translation>
+<translation id="2908441821576996758">Sisestage meiliaadresside loend komadega eraldatult.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Sisestage kehtiv väärtus. Väli on täitmata või sisaldab sobimatut kuupäeva.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">märge</translation>
+<translation id="310520048233152454">Sisestage URL.</translation>
+<translation id="3175736971608411871">taimer</translation>
+<translation id="3199563858620722075">liitkast</translation>
+<translation id="3450233048674729344">Väärtus peab olema väiksem või võrdne <ph name="MAXIMUM" />-ga.</translation>
+<translation id="3486220673238053218">definitsioon</translation>
+<translation id="3557673793733683882">päis <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">nädala valija</translation>
+<translation id="3685101356851116974">Sildita pilt</translation>
+<translation id="3706100364254443312">lüliti</translation>
+<translation id="3732799496749320381">kk</translation>
+<translation id="3754210790023674521">Välju režiimist Pilt pildis</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termin</translation>
+<translation id="3822383571486410024">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
+<translation id="383465348367842624">Märgile „<ph name="ATSIGN" />” eelnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3846214748874656680">Täisekraanilt väljumine</translation>
+<translation id="3889183436948184105">redaktsioon</translation>
+<translation id="3920932319529768807">kokkuvõte</translation>
+<translation id="3924558731517983934">rakendus</translation>
+<translation id="3944740393230681990">proloog</translation>
+<translation id="3960700977367013758">kerimisriba</translation>
+<translation id="4103419683916926126">Millisekundid</translation>
+<translation id="4151657705144244502">graafika</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">eessõna</translation>
+<translation id="4201051445878709314">Eelmise kuu kuvamine</translation>
+<translation id="421884353938374759">värvivalija</translation>
+<translation id="4248100235867064564">menüüriba</translation>
+<translation id="4360991593054037559">Sisestage kehtiv väärtus. Kaks lähimat kehtivat väärtust on <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Küsimused ja vastused</translation>
+<translation id="4413860115965805769">menüünupp</translation>
+<translation id="4444765639179266822">Näib ütlevat: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">sõnastiku viide</translation>
+<translation id="4522570452068850558">Üksikasjad</translation>
+<translation id="4542388879936266156">järelejäänud aeg: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">vorm</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Märgile „<ph name="ATSIGN" />” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">lisa</translation>
+<translation id="4718048029184481307">Režiimis Pilt pildis mängimine</translation>
+<translation id="4742539557769756338">kaas</translation>
+<translation id="4748357248530471599">ekraani väljalõike täisekraanrežiimi sisse-/väljalülitamine</translation>
+<translation id="4757246831282535685">vahelehepaneel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">otsing</translation>
+<translation id="4812940957355064477">Sisestage arv.</translation>
+<translation id="4912536737030637138">bibliograafia kirje</translation>
+<translation id="4975562563186953947">Valitud on <ph name="SELECTED_COUNT" /> üksust</translation>
+<translation id="4992066212339426712">Tühista vaigistus</translation>
+<translation id="49969490063480558">Sisestage märgile „<ph name="ATSIGN" />” järgnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
+<translation id="5034860022980953847">edenemise näidik</translation>
+<translation id="5090250355906949916">video ajakursor</translation>
+<translation id="5093189678851173835">epigraaf</translation>
+<translation id="5117590920725113268">Järgmise kuu kuvamine</translation>
+<translation id="512758898067543763">rea päis</translation>
+<translation id="5143125788380636750">epiloog</translation>
+<translation id="5164977714490026579">Väärtus peab olema suurem või võrdne <ph name="MINIMUM" />-ga.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Sisestage märgile „<ph name="ATSIGN" />” eelnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
+<translation id="5334352251556557839">Meediasisu ei saa esitada.</translation>
+<translation id="5406322316791861025">joonis</translation>
+<translation id="5453733299334684579">puuüksus</translation>
+<translation id="5466621249238537318">Valige üks või mitu faili.</translation>
+<translation id="5468998798572797635">täisekraanilt väljumine</translation>
+<translation id="5516424706154626233">kuupäeva valija</translation>
+<translation id="5537725057119320332">Ülekanne</translation>
+<translation id="5546461542133609677">vaigistuse tühistamine</translation>
+<translation id="5608153257855394627">esiletõstmine</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">10 sekundi võrra kerimiseks topeltpuudutage vasakul või paremal</translation>
+<translation id="5631759159893697722">abstraktne</translation>
+<translation id="5643186887447432888">nupp</translation>
+<translation id="5677946354068040947">rohkem valikuid</translation>
+<translation id="576709008726043716">sissejuhatus</translation>
+<translation id="57838592816432529">Vaigista</translation>
+<translation id="5860033963881614850">Väljas</translation>
+<translation id="588258955323874662">Täisekraan</translation>
+<translation id="5888666972993069672">Nüüd kantakse üle seadmesse <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">otsingukast</translation>
+<translation id="5939518447894949180">Lähtesta</translation>
+<translation id="5966707198760109579">Nädal</translation>
+<translation id="5987525920412732405">pöördnupp</translation>
+<translation id="6011459053400940133">helitugevuse liugur</translation>
+<translation id="6015796118275082299">Aasta</translation>
+<translation id="6023896073578205740">loendikast</translation>
+<translation id="6150588977291308318">bibliograafia</translation>
+<translation id="6164829606128959761">mõõdik</translation>
+<translation id="6166809985690652833">järelsõna</translation>
+<translation id="6209276755895393898">Näib olevat: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">sõnastik</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Välju režiimist Pilt pildis</translation>
+<translation id="6398862346408813489">Kuu valikupaneeli kuvamine</translation>
+<translation id="6404546809543547843">heli ajamõõdik</translation>
+<translation id="6443871981718447451">kuva subtiitrite menüü</translation>
+<translation id="6453774872122745852">tunnustused</translation>
+<translation id="6475115390776617481">reaalajas kohalolek</translation>
+<translation id="648732519525291180">kellaaja valija</translation>
+<translation id="6550675742724504774">Valikud</translation>
+<translation id="6572309429103589720">Grammatikavead</translation>
+<translation id="658823671542763450">kuvamine täisekraanil</translation>
+<translation id="663493177488814956">voog</translation>
+<translation id="6637586476836377253">logi</translation>
+<translation id="6643016212128521049">Tühjenda</translation>
+<translation id="668171684555832681">Muu...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Kehv esituskvaliteet</translation>
+<translation id="6755330956360078551">tööriistavihje</translation>
+<translation id="6790428901817661496">Esita</translation>
+<translation id="6820355525329141109">Pistikprogrammi ei saanud laadida.</translation>
+<translation id="6820615603175220800">kasutatud kirjandus</translation>
+<translation id="6843725295806269523">vaigista</translation>
+<translation id="6885760532393684712">kataloog</translation>
+<translation id="689129560213475294">kolofoon</translation>
+<translation id="6934078000481955284">plokktsitaat</translation>
+<translation id="693476918119313863">päis</translation>
+<translation id="6941933287844615239">laadi meedia alla</translation>
+<translation id="6981594929165378967">lisamine</translation>
+<translation id="6989848892321993519">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu ühte tähemärki).</translation>
+<translation id="7034405885550056553">soovitus</translation>
+<translation id="709897737746224366">Vastendage nõutav vorming.</translation>
+<translation id="7118469954320184356">Kirjeldust pole.</translation>
+<translation id="7139483182332611405">eessõna</translation>
+<translation id="7214187073215825913">sisu teave</translation>
+<translation id="7263440858009898357">Valige loendist element.</translation>
+<translation id="727747134524199931">veeru päis</translation>
+<translation id="7320576522385648310">puhverdamine</translation>
+<translation id="7353453495576941748">autor(id)</translation>
+<translation id="7364796246159120393">Vali fail</translation>
+<translation id="739024184232394898">Muu ...</translation>
+<translation id="7405738980073107433">järelmärkused</translation>
+<translation id="7410239719251593705">Näib sisaldavat täiskasvanutele mõeldud sisu. Kirjeldust pole.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">Tabulaator</translation>
+<translation id="7514365320538308">Laadi alla</translation>
+<translation id="7529102961911894712">tagasilink</translation>
+<translation id="7533959249147584474">Sildita graafika</translation>
+<translation id="7647456547678091388">nõuanne</translation>
+<translation id="7661956066982048809">graafika dokument</translation>
+<translation id="7673697353781729403">Tunnid</translation>
+<translation id="7681220483256441252">register</translation>
+<translation id="7740050170769002709">HTML-sisu</translation>
+<translation id="7745230546936012372">Puuduvate pildikirjelduste hankimiseks avage kontekstimenüü.</translation>
+<translation id="7750228210027921155">Pilt pildis</translation>
+<translation id="775297008183122718">Kehtetu kirje</translation>
+<translation id="7789962463072032349">peata</translation>
+<translation id="7802800022689234070">avalikustamise kolmnurk</translation>
+<translation id="7888071071722539607">Lisage e-posti aadressile märk „<ph name="ATSIGN" />”. Aadressist „<ph name="INVALIDADDRESS" />” puudub märk „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">jagaja</translation>
+<translation id="795667975304826397">Pole valitud</translation>
+<translation id="8053789581856978548">otsinguteksti väli</translation>
+<translation id="8057695513531652401">teatis</translation>
+<translation id="8105797009065549151">märkuse viide</translation>
+<translation id="811583516810654505">Kirjelduse hankimine …</translation>
+<translation id="8117451130807776954">See nädal</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">kohaliku kuupäeva ja kellaaja valija</translation>
+<translation id="8261464734335370856">Õigekirjavead</translation>
+<translation id="8284326494547611709">Subtiitrid</translation>
+<translation id="8346634859695247203">jaotis</translation>
+<translation id="835897206747267392">Kehtetu väärtus.</translation>
+<translation id="8403857369060869934">möödunud aeg: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">osa</translation>
+<translation id="8433900881053900389">tööriistariba</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
+<translation id="8451268428117625855">Valige üks fail.</translation>
+<translation id="8461852803063341183">raadionupp</translation>
+<translation id="8474886197722836894">pühendus</translation>
+<translation id="8531739829932800271">veaparandused</translation>
+<translation id="8534579021159131403">Minutid</translation>
+<translation id="8541249477527128034">meedia juhtimine</translation>
+<translation id="8550857728288566671">graafika sümbol</translation>
+<translation id="8583702881314752957">definitsioonide loend</translation>
+<translation id="8597182159515967513">pealkiri</translation>
+<translation id="860475260694818407">sisukord</translation>
+<translation id="8613126697340063924">kaugesituse juhtimine</translation>
+<translation id="862370744433916922">alapealkiri</translation>
+<translation id="8711688047404765493">väljund</translation>
+<translation id="8750798805984357768">Tehke üks nendest valikutest.</translation>
+<translation id="8808573423886751634">peatükk</translation>
+<translation id="8822203815165896261">volitamisteave</translation>
+<translation id="8845239796550121995">Kantakse nüüd üle telerisse</translation>
+<translation id="8851136666856101339">pea</translation>
+<translation id="8875657656876809964">Video taasesituse viga</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">kuu</translation>
+<translation id="901493112792887934">praegune aeg sekundites</translation>
+<translation id="901834265349196618">meil:</translation>
+<translation id="9048119486235211610">navigeerimine</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">välju režiimist Pilt pildis</translation>
+<translation id="9108370397979208512">matemaatika</translation>
+<translation id="9132465097189459683">Muu ...</translation>
+<translation id="9138385573473225930">hoiatus</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> alates kuupäevast <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Pilt pildis</translation>
+<translation id="9168329111483466115">allmärkus</translation>
+<translation id="954003015749068518">aktiveeri režiim Pilt pildis</translation>
+<translation id="966787709310836684">menüü</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..c37828ce3cd
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fa.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fa">
+<translation id="1018939186200882850">مورد منو</translation>
+<translation id="10623998915015855">دکمه تغییر حالت</translation>
+<translation id="1088086359088493902">ثانیه</translation>
+<translation id="1171774979989969504">لطفاً یک نشانی ایمیل وارد کنید.</translation>
+<translation id="1178581264944972037">مکث</translation>
+<translation id="1188858454923323853">تکمیلی</translation>
+<translation id="1206619573307042055">نوشتار متحرک روی صفحه</translation>
+<translation id="1206693055195146388">لغزنده</translation>
+<translation id="1211441953136645838">ته‌نویس</translation>
+<translation id="1281252709823657822">کادر گفتگو</translation>
+<translation id="1335095011850992622">دست‌اندرکاران</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">برنما</translation>
+<translation id="1589122976691792535">منطقه</translation>
+<translation id="1591562245178063882">این ماه</translation>
+<translation id="1637811476055996098">انتخاب فایل‌ها</translation>
+<translation id="1650423536718072820">نقل‌قول</translation>
+<translation id="1727886345390570319">پنهان کردن منوی زیرنویس ناشنوایان</translation>
+<translation id="1729654308190250600">لطفاً یک نشانی ایمیل غیرخالی وارد کنید.</translation>
+<translation id="1758486001363313524">موارد دیگر...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">شبکه درختی</translation>
+<translation id="1822429046913737220">ق.ظ/ب.ظ</translation>
+<translation id="1832974991323546415">پخش در دستگاه راه دور</translation>
+<translation id="190587075670221089">حذف</translation>
+<translation id="1907737156431278478">مثال</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">وضعیت</translation>
+<translation id="1938124657309484470">مقدار باید <ph name="MAXIMUM_DATE_OR_TIME" /> یا قبل از آن باشد.</translation>
+<translation id="1946271899482435442">نمایش انتخابگر تاریخ</translation>
+<translation id="1993104285338243655">به نمایش صفحه‌نمایش روی دستگاه دیگر تغییر یافت</translation>
+<translation id="2060505056492490888">«<ph name="DOT" />» در «<ph name="INVALIDDOMAIN" />» در محل اشتباهی قرار دارد.</translation>
+<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="2247351761944213033">هفته <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">آهنگ <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">کادر تأیید</translation>
+<translation id="2311842470354187719">جداساز صفحه</translation>
+<translation id="2335594187091864976">انتخابگر تاریخ و زمان</translation>
+<translation id="245932805758469625">ثانیه‌های باقی‌مانده از ویدیو</translation>
+<translation id="248395913932153421">روز</translation>
+<translation id="2507943997699731163">لطفاً این قسمت را تکمیل کنید.</translation>
+<translation id="2508569020611168319">فهرست برگه</translation>
+<translation id="2561842179657104141">نمایش کنترل‌های رسانه بیشتر</translation>
+<translation id="2572483411312390101">پخش</translation>
+<translation id="2613802280814924224">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقدار معتبر <ph name="VALID_VALUE" /> است.</translation>
+<translation id="2653659639078652383">ارائه</translation>
+<translation id="2657045182931379222">شیء گرافیکی</translation>
+<translation id="2674318244760992338">پانویس</translation>
+<translation id="2709516037105925701">تکمیل خودکار</translation>
+<translation id="2723001399770238859">صدا</translation>
+<translation id="2725963129578236554">نظرها</translation>
+<translation id="2746543609216772311">مقدار باید <ph name="MINIMUM_DATE_OR_TIME" /> یا بعد از آن باشد.</translation>
+<translation id="2759744352195237655">دکمه بازشو</translation>
+<translation id="2761667185364618470">درصورتی‌که می‌خواهید ادامه دهید، این کادر را انتخاب کنید.</translation>
+<translation id="2844350028562914727">جزئیات</translation>
+<translation id="2896972712917208084">گروه رادیویی</translation>
+<translation id="2908441821576996758">لطفاً لیستی از آدرس‌های ایمیل که با کاما از هم جدا شده‌اند را وارد کنید.</translation>
+<translation id="2940813599313844715">شیء</translation>
+<translation id="3040011195152428237">پیوند</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> مگابایت</translation>
+<translation id="3075154866155599887">لطفاً یک مقدار معتبر وارد کنید. این قسمت کامل نیست و یا تاریخ نامعتبر است.</translation>
+<translation id="3078740164268491126">جدول</translation>
+<translation id="3086746722712840547">نت</translation>
+<translation id="310520048233152454">لطفاً یک نشانی وب وارد کنید.</translation>
+<translation id="3175736971608411871">تایمر</translation>
+<translation id="3199563858620722075">کادر ترکیبی</translation>
+<translation id="3450233048674729344">مقدار باید کمتر یا برابر با <ph name="MAXIMUM" /> باشد.</translation>
+<translation id="3486220673238053218">معنی</translation>
+<translation id="3557673793733683882">عنوان <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">انتخاب‌گر هفته</translation>
+<translation id="3685101356851116974">تصویر بدون برچسب</translation>
+<translation id="3706100364254443312">تعویض</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">خروج از تصویردرتصویر</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> گیگابایت</translation>
+<translation id="3808586225841795776">اصطلاح</translation>
+<translation id="3822383571486410024">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
+<translation id="383465348367842624">قسمت قبل از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
+<translation id="3846214748874656680">خروج از حالت تمام صفحه</translation>
+<translation id="3889183436948184105">بازبینی</translation>
+<translation id="3920932319529768807">نتیجه‌گیری</translation>
+<translation id="3924558731517983934">برنامه</translation>
+<translation id="3944740393230681990">گفتار آغازین</translation>
+<translation id="3960700977367013758">نوار پیمایش</translation>
+<translation id="4103419683916926126">میلی‌ ثانیه</translation>
+<translation id="4151657705144244502">گرافیک</translation>
+<translation id="4160057747563657758">تلفن</translation>
+<translation id="4193965531860883258">پیش‌گفتار</translation>
+<translation id="4201051445878709314">نمایش ماه قبلی</translation>
+<translation id="421884353938374759">انتخابگر رنگ</translation>
+<translation id="4248100235867064564">نوار منو</translation>
+<translation id="4360991593054037559">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقادیر معتبر <ph name="VALID_VALUE_LOW" /> و <ph name="VALID_VALUE_HIGHER" /> هستند.</translation>
+<translation id="4384583879834880242">پرسش و پاسخ</translation>
+<translation id="4413860115965805769">دکمه منو</translation>
+<translation id="4444765639179266822">ظاهراً <ph name="OCR_TEXT" /> را نشان می‌دهد</translation>
+<translation id="4446524499724042288">مرجع واژه‌نامه</translation>
+<translation id="4522570452068850558">جزئیات</translation>
+<translation id="4542388879936266156">زمان باقی‌مانده: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">فرم</translation>
+<translation id="4661075872484491155">درخت</translation>
+<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
+<translation id="4668956016107839909">ضمیمه</translation>
+<translation id="4718048029184481307">درحال پخش در حالت تصویردرتصویر</translation>
+<translation id="4742539557769756338">جلد</translation>
+<translation id="4748357248530471599">جابجایی برش نمایشگر تمام‌صفحه</translation>
+<translation id="4757246831282535685">پانل برگه</translation>
+<translation id="4763480195061959176">ویدئو</translation>
+<translation id="479989351350248267">جستجو</translation>
+<translation id="4812940957355064477">لطفاً شماره‌ای را وارد کنید.</translation>
+<translation id="4912536737030637138">ورودی فهرست منابع</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> انتخاب شد</translation>
+<translation id="4992066212339426712">باصدا کردن</translation>
+<translation id="49969490063480558">لطفاً قسمت بعد از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
+<translation id="5034860022980953847">نشانگر پیشرفت</translation>
+<translation id="5090250355906949916">انتخابگر زمان ویدیو</translation>
+<translation id="5093189678851173835">نقل‌قول آغازین</translation>
+<translation id="5117590920725113268">نمایش ماه بعدی</translation>
+<translation id="512758898067543763">عنوان ردیف</translation>
+<translation id="5143125788380636750">گفتار پایانی</translation>
+<translation id="5164977714490026579">مقدار باید بیشتر یا مساوی با <ph name="MINIMUM" /> باشد.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> پتابایت</translation>
+<translation id="5307600278924710095">لطفاً قسمت قبل از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
+<translation id="5334352251556557839">رسانه پخش نشد.</translation>
+<translation id="5406322316791861025">شکل</translation>
+<translation id="5453733299334684579">مورد درختی</translation>
+<translation id="5466621249238537318">لطفاً یک یا چند فایل را انتخاب کنید.</translation>
+<translation id="5468998798572797635">خروج از حالت تمام صفحه</translation>
+<translation id="5516424706154626233">انتخابگر تاریخ</translation>
+<translation id="5537725057119320332">فرستادن</translation>
+<translation id="5546461542133609677">صدادارکردن</translation>
+<translation id="5608153257855394627">برجسته</translation>
+<translation id="561939826962581046">زمان</translation>
+<translation id="5630795885300617244">روی سمت راست یا چپ دو ضربه سریع بزنید تا ۱۰ ثانیه رد شود</translation>
+<translation id="5631759159893697722">انتزاعی</translation>
+<translation id="5643186887447432888">دکمه</translation>
+<translation id="5677946354068040947">گزینه‌های بیشتر</translation>
+<translation id="576709008726043716">مقدمه</translation>
+<translation id="57838592816432529">بی‌صدا کردن</translation>
+<translation id="5860033963881614850">خاموش</translation>
+<translation id="588258955323874662">تمام صفحه</translation>
+<translation id="5888666972993069672">درحال ارسال محتوا به <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">جعبه جستجو</translation>
+<translation id="5939518447894949180">بازنشانی</translation>
+<translation id="5966707198760109579">هفته</translation>
+<translation id="5987525920412732405">دکمه چرخش</translation>
+<translation id="6011459053400940133">لغزنده میزان صدا</translation>
+<translation id="6015796118275082299">سال</translation>
+<translation id="6023896073578205740">کادر فهرست</translation>
+<translation id="6150588977291308318">فهرست منابع</translation>
+<translation id="6164829606128959761">متر</translation>
+<translation id="6166809985690652833">سخن پایانی</translation>
+<translation id="6209276755895393898">به‌نظر می‌رسد <ph name="DESCRIPTION" /> باشد</translation>
+<translation id="6213469881011901533">واژه‌نامه</translation>
+<translation id="6281763101136022427">نشانی وب</translation>
+<translation id="6310801910862476708">خروج از تصویر در تصویر</translation>
+<translation id="6398862346408813489">نمایش پانل انتخاب ماه</translation>
+<translation id="6404546809543547843">انتخابگر زمان صدا</translation>
+<translation id="6443871981718447451">نمایش منوی زیرنویس ناشنوایان</translation>
+<translation id="6453774872122745852">قدردانی</translation>
+<translation id="6475115390776617481">حضور زنده</translation>
+<translation id="648732519525291180">انتخابگر زمان</translation>
+<translation id="6550675742724504774">گزینه‌ها</translation>
+<translation id="6572309429103589720">دستور زبان نامعتبر</translation>
+<translation id="658823671542763450">رفتن به حالت تمام صفحه</translation>
+<translation id="663493177488814956">خبرمایه</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">پاک کردن</translation>
+<translation id="668171684555832681">دیگر...</translation>
+<translation id="6692633176391053278">گام به گام</translation>
+<translation id="6709570249143506788">کیفیت پخش ضعیف</translation>
+<translation id="6755330956360078551">نکته ابزار</translation>
+<translation id="6790428901817661496">پخش</translation>
+<translation id="6820355525329141109">افزایه بارگیری نشد.</translation>
+<translation id="6820615603175220800">مرجع فهرست منابع</translation>
+<translation id="6843725295806269523">بیصداکردن</translation>
+<translation id="6885760532393684712">فهرست راهنما</translation>
+<translation id="689129560213475294">انجامه</translation>
+<translation id="6934078000481955284">نقل‌قول</translation>
+<translation id="693476918119313863">سرصفحه</translation>
+<translation id="6941933287844615239">بارگیری رسانه</translation>
+<translation id="6981594929165378967">درج</translation>
+<translation id="6989848892321993519">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال‌حاضر از ۱ نویسه استفاده می‌کنید).</translation>
+<translation id="7034405885550056553">پیشنهاد</translation>
+<translation id="709897737746224366">لطفاً با قالب درخواستی مطابقت دهید.</translation>
+<translation id="7118469954320184356">توضیحی دردسترس نیست.</translation>
+<translation id="7139483182332611405">پیش‌گفتار</translation>
+<translation id="7214187073215825913">اطلاعات محتوا</translation>
+<translation id="7263440858009898357">لطفاً یک مورد را در فهرست انتخاب کنید.</translation>
+<translation id="727747134524199931">عنوان ستون</translation>
+<translation id="7320576522385648310">درحال بافر کردن</translation>
+<translation id="7353453495576941748">تأیید اعتبار</translation>
+<translation id="7364796246159120393">انتخاب فایل</translation>
+<translation id="739024184232394898">موارد دیگر...</translation>
+<translation id="7405738980073107433">ته‌نویس‌ها</translation>
+<translation id="7410239719251593705">ظاهراً حاوی محتوای بزرگسالان است. توضیحی در دسترس نیست.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> ترابایت</translation>
+<translation id="7491962110804786152">برگه</translation>
+<translation id="7514365320538308">بارگیری</translation>
+<translation id="7529102961911894712">پیوند برگشت</translation>
+<translation id="7533959249147584474">گرافیک بدون برچسب</translation>
+<translation id="7647456547678091388">نکته</translation>
+<translation id="7661956066982048809">سند گرافیکی</translation>
+<translation id="7673697353781729403">ساعت</translation>
+<translation id="7681220483256441252">فهرست موضوعی</translation>
+<translation id="7740050170769002709">‏محتوای HTML</translation>
+<translation id="7745230546936012372">برای دریافت توضیحات تصویر جاافتاده، منوی بافت را باز کنید.</translation>
+<translation id="7750228210027921155">تصویردرتصویر</translation>
+<translation id="775297008183122718">ورودی نامعتبر</translation>
+<translation id="7789962463072032349">مکث</translation>
+<translation id="7802800022689234070">مثلث افشا</translation>
+<translation id="7888071071722539607">لطفاً نماد «<ph name="ATSIGN" />» را به نشانی ایمیل اضافه کنید. «<ph name="INVALIDADDRESS" />» در «<ph name="ATSIGN" />» موجود نیست.</translation>
+<translation id="7891486169920085145">تقسیم‌کننده</translation>
+<translation id="795667975304826397">فایلی انتخاب نشده است</translation>
+<translation id="8053789581856978548">فیلد نوشتاری جستجو</translation>
+<translation id="8057695513531652401">اطلاعیه</translation>
+<translation id="8105797009065549151">مرجع یادداشت</translation>
+<translation id="811583516810654505">درحال دریافت توضیح…</translation>
+<translation id="8117451130807776954">این هفته</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">انتخابگر تاریخ و زمان محلی</translation>
+<translation id="8261464734335370856">املای نامعتبر</translation>
+<translation id="8284326494547611709">زیرنویس‌ها</translation>
+<translation id="8346634859695247203">بخش</translation>
+<translation id="835897206747267392">مقدار نامعتبر.</translation>
+<translation id="8403857369060869934">زمان سپری‌شده: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">بخش</translation>
+<translation id="8433900881053900389">نوار ابزار</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> فایل</translation>
+<translation id="8451268428117625855">لطفاً یک فایل انتخاب کنید.</translation>
+<translation id="8461852803063341183">دکمه رادیو</translation>
+<translation id="8474886197722836894">تقدیم‌نامه</translation>
+<translation id="8531739829932800271">فهرست اشتباهات</translation>
+<translation id="8534579021159131403">دقیقه</translation>
+<translation id="8541249477527128034">کنترل رسانه</translation>
+<translation id="8550857728288566671">نماد گرافیکی</translation>
+<translation id="8583702881314752957">فهرست معنی‌ها</translation>
+<translation id="8597182159515967513">عنوان</translation>
+<translation id="860475260694818407">فهرست مطالب</translation>
+<translation id="8613126697340063924">کنترل بازپخش راه دور</translation>
+<translation id="862370744433916922">زیرنویس</translation>
+<translation id="8711688047404765493">خروجی</translation>
+<translation id="8750798805984357768">لطفاً یکی از این گزینه‌ها را انتخاب کنید.</translation>
+<translation id="8808573423886751634">فصل</translation>
+<translation id="8822203815165896261">اطلاعات تألیف</translation>
+<translation id="8845239796550121995">درحال ارسال محتوا به تلویزیون</translation>
+<translation id="8851136666856101339">اصلی</translation>
+<translation id="8875657656876809964">خطا در بازپخش ویدئو</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> کیلوبایت</translation>
+<translation id="8987927404178983737">ماه</translation>
+<translation id="901493112792887934">زمان کنونی به ثانیه</translation>
+<translation id="901834265349196618">ایمیل</translation>
+<translation id="9048119486235211610">پیمایش</translation>
+<translation id="9062295712474918030">سند</translation>
+<translation id="9093215626363556771">خروج از تصویر در تصویر</translation>
+<translation id="9108370397979208512">حساب</translation>
+<translation id="9132465097189459683">موارد دیگر...</translation>
+<translation id="9138385573473225930">هشدار</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />، شروع از <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">تصویر در تصویر</translation>
+<translation id="9168329111483466115">پانویس</translation>
+<translation id="954003015749068518">ورود به تصویر در تصویر</translation>
+<translation id="966787709310836684">منو</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..c8bbb0d20d3
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fi.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fi">
+<translation id="1018939186200882850">valikkokohde</translation>
+<translation id="10623998915015855">vaihtopainike</translation>
+<translation id="1088086359088493902">Sekuntia</translation>
+<translation id="1171774979989969504">Anna sähköpostiosoite.</translation>
+<translation id="1178581264944972037">Tauko</translation>
+<translation id="1188858454923323853">täydentävä</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">liukusäädin</translation>
+<translation id="1211441953136645838">loppuhuomautus</translation>
+<translation id="1281252709823657822">valintaikkuna</translation>
+<translation id="1335095011850992622">tunnustukset</translation>
+<translation id="1342835525016946179">artikkeli</translation>
+<translation id="1359897965706325498">banneri</translation>
+<translation id="1589122976691792535">alue</translation>
+<translation id="1591562245178063882">Tässä kuussa</translation>
+<translation id="1637811476055996098">Valitse tiedostot</translation>
+<translation id="1650423536718072820">erotettu lainaus</translation>
+<translation id="1727886345390570319">sulje tekstitysvalikko</translation>
+<translation id="1729654308190250600">Kirjoita ei-tyhjä sähköpostiosoite.</translation>
+<translation id="1758486001363313524">Muu...</translation>
+<translation id="1806710327868736751">ilmoitusvalintaikkuna</translation>
+<translation id="1821985195704844674">puuruudukko</translation>
+<translation id="1822429046913737220">AP/IP</translation>
+<translation id="1832974991323546415">toista etälaitteella</translation>
+<translation id="190587075670221089">poisto</translation>
+<translation id="1907737156431278478">esimerkki</translation>
+<translation id="1921819250265091946">pp</translation>
+<translation id="1930711995431081526">tila</translation>
+<translation id="1938124657309484470">Arvon on oltava <ph name="MAXIMUM_DATE_OR_TIME" /> tai aiempi.</translation>
+<translation id="1946271899482435442">Näytä päivämäärävalitsin</translation>
+<translation id="1993104285338243655">Peilaus käynnissä</translation>
+<translation id="2060505056492490888"><ph name="DOT" />-merkkiä on käytetty väärässä kohdassa osoitteessa <ph name="INVALIDDOMAIN" />.</translation>
+<translation id="2148716181193084225">Tänään</translation>
+<translation id="2158401438286456825">sivuluettelo</translation>
+<translation id="2226276347425096477">Lyhennä tämä teksti alle <ph name="MAX_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
+<translation id="2246498165605549352">Paikallinen tiedosto</translation>
+<translation id="2247351761944213033">Viikko <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Kappale <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">valintaruutu</translation>
+<translation id="2311842470354187719">sivunvaihto</translation>
+<translation id="2335594187091864976">päivämäärän ja ajan valitsin</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>
+<translation id="2508569020611168319">välilehtiluettelo</translation>
+<translation id="2561842179657104141">näytä lisää mediaohjaimia</translation>
+<translation id="2572483411312390101">toista</translation>
+<translation id="2613802280814924224">Syötä kelvollinen arvo. Lähin kelvollinen arvo on <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Lähetä</translation>
+<translation id="2657045182931379222">grafiikkaobjekti</translation>
+<translation id="2674318244760992338">alaviite</translation>
+<translation id="2709516037105925701">Automaattinen täyttö</translation>
+<translation id="2723001399770238859">ääni</translation>
+<translation id="2725963129578236554">kommentit</translation>
+<translation id="2746543609216772311">Arvon on oltava <ph name="MINIMUM_DATE_OR_TIME" /> tai myöhempi.</translation>
+<translation id="2759744352195237655">ponnahduspainike</translation>
+<translation id="2761667185364618470">Valitse tämä ruutu jatkaaksesi.</translation>
+<translation id="2844350028562914727">tiedot</translation>
+<translation id="2896972712917208084">valintapainikeryhmä</translation>
+<translation id="2908441821576996758">Anna pilkuilla erotettu sähköpostiosoitteiden luettelo.</translation>
+<translation id="2940813599313844715">kohde</translation>
+<translation id="3040011195152428237">linkki</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> Mt</translation>
+<translation id="3075154866155599887">Anna kelvollinen arvo. Kentän arvo on puutteellinen tai annettu päivä on virheellinen.</translation>
+<translation id="3078740164268491126">taulukko</translation>
+<translation id="3086746722712840547">huom.</translation>
+<translation id="310520048233152454">Anna URL-osoite.</translation>
+<translation id="3175736971608411871">ajastin</translation>
+<translation id="3199563858620722075">yhdistelmäruutu</translation>
+<translation id="3450233048674729344">Arvon tulee olla pienempi tai yhtä suuri kuin <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">määritelmä</translation>
+<translation id="3557673793733683882">otsikko <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">viikon valitsin</translation>
+<translation id="3685101356851116974">Tunnisteeton kuva</translation>
+<translation id="3706100364254443312">vaihto</translation>
+<translation id="3732799496749320381">kk</translation>
+<translation id="3754210790023674521">Sulje kuva kuvassa ‑tila</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> Gt</translation>
+<translation id="3808586225841795776">termi</translation>
+<translation id="3822383571486410024">Pidennä tämä teksti yli <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
+<translation id="383465348367842624"><ph name="ATSIGN" />-osaa ennen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3846214748874656680">Sulje koko näytön tila.</translation>
+<translation id="3889183436948184105">muutostiedot</translation>
+<translation id="3920932319529768807">johtopäätös</translation>
+<translation id="3924558731517983934">sovellus</translation>
+<translation id="3944740393230681990">prologi</translation>
+<translation id="3960700977367013758">vierityspalkki</translation>
+<translation id="4103419683916926126">Millisekuntia</translation>
+<translation id="4151657705144244502">kuva</translation>
+<translation id="4160057747563657758">puhelin</translation>
+<translation id="4193965531860883258">esipuhe</translation>
+<translation id="4201051445878709314">Näytä edellinen kuukausi</translation>
+<translation id="421884353938374759">värinvalitsin</translation>
+<translation id="4248100235867064564">valikkopalkki</translation>
+<translation id="4360991593054037559">Syötä kelvollinen arvo. Kaksi lähintä kelvollista arvoa ovat <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">K &amp; V</translation>
+<translation id="4413860115965805769">valikkopainike</translation>
+<translation id="4444765639179266822">Kuuluu sanovan: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">sanastoviittaus</translation>
+<translation id="4522570452068850558">Tiedot</translation>
+<translation id="4542388879936266156">jäljellä oleva aika: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">lomake</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816"><ph name="ATSIGN" />-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">liite</translation>
+<translation id="4718048029184481307">Toistetaan kuva kuvassa ‑tilassa</translation>
+<translation id="4742539557769756338">kansi</translation>
+<translation id="4748357248530471599">näyttölovi osana koko näytön tilaa päälle/pois</translation>
+<translation id="4757246831282535685">välilehtipaneeli</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">haku</translation>
+<translation id="4812940957355064477">Anna numero.</translation>
+<translation id="4912536737030637138">lähdeluettelomerkintä</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valittu</translation>
+<translation id="4992066212339426712">Poista mykistys</translation>
+<translation id="49969490063480558">Kirjoita loppuun asti osoite, joka alkaa <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> on vielä kesken.</translation>
+<translation id="5034860022980953847">etenemisen osoitin</translation>
+<translation id="5090250355906949916">videon ajan liukusäädin</translation>
+<translation id="5093189678851173835">epigrafi</translation>
+<translation id="5117590920725113268">Näytä seuraava kuukausi</translation>
+<translation id="512758898067543763">rivin otsikko</translation>
+<translation id="5143125788380636750">epilogi</translation>
+<translation id="5164977714490026579">Arvon tulee olla suurempi tai yhtä suuri kuin <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> Pt</translation>
+<translation id="5307600278924710095">Lisää <ph name="ATSIGN" />-osaa ennen tuleva osa. <ph name="INVALIDADDRESS" /> on puutteellinen.</translation>
+<translation id="5334352251556557839">Mediaa ei voi toistaa.</translation>
+<translation id="5406322316791861025">kuva</translation>
+<translation id="5453733299334684579">puukohde</translation>
+<translation id="5466621249238537318">Valitse vähintään yksi tiedosto.</translation>
+<translation id="5468998798572797635">poistu koko näytön tilasta</translation>
+<translation id="5516424706154626233">päivämäärän valitsin</translation>
+<translation id="5537725057119320332">Lähetä</translation>
+<translation id="5546461542133609677">peruuta mykistys</translation>
+<translation id="5608153257855394627">korosta</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Ohita 10 sekuntia kaksoisnapauttamalla vasemmalle tai oikealle.</translation>
+<translation id="5631759159893697722">tiivistelmä</translation>
+<translation id="5643186887447432888">painike</translation>
+<translation id="5677946354068040947">lisäasetukset</translation>
+<translation id="576709008726043716">johdanto</translation>
+<translation id="57838592816432529">Mykistä</translation>
+<translation id="5860033963881614850">Pois käytöstä</translation>
+<translation id="588258955323874662">Koko ruutu</translation>
+<translation id="5888666972993069672">Katsotaan TV:stä <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">hakukenttä</translation>
+<translation id="5939518447894949180">Tyhjennä</translation>
+<translation id="5966707198760109579">Viikko</translation>
+<translation id="5987525920412732405">pyöräytyspainike</translation>
+<translation id="6011459053400940133">äänenvoimakkuuden liukusäädin</translation>
+<translation id="6015796118275082299">Vuosi</translation>
+<translation id="6023896073578205740">luetteloruutu</translation>
+<translation id="6150588977291308318">lähdeluettelo</translation>
+<translation id="6164829606128959761">mittari</translation>
+<translation id="6166809985690652833">jälkipuhe</translation>
+<translation id="6209276755895393898">Näkyy olevan: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">sanasto</translation>
+<translation id="6281763101136022427">url-osoite</translation>
+<translation id="6310801910862476708">Sulje kuva kuvassa ‑tila</translation>
+<translation id="6398862346408813489">Näytä kuukaudenvalintapaneeli</translation>
+<translation id="6404546809543547843">äänen ajan liukusäädin</translation>
+<translation id="6443871981718447451">näytä tekstitysvalikko</translation>
+<translation id="6453774872122745852">kiitokset</translation>
+<translation id="6475115390776617481">paikallaolo</translation>
+<translation id="648732519525291180">ajan valitsin</translation>
+<translation id="6550675742724504774">Asetukset</translation>
+<translation id="6572309429103589720">Kielioppivirhe</translation>
+<translation id="658823671542763450">siirry koko näytön tilaan</translation>
+<translation id="663493177488814956">fiidi</translation>
+<translation id="6637586476836377253">loki</translation>
+<translation id="6643016212128521049">Tyhjennä</translation>
+<translation id="668171684555832681">Joku muu profiili...</translation>
+<translation id="6692633176391053278">askellin</translation>
+<translation id="6709570249143506788">Heikko toiston laatu</translation>
+<translation id="6755330956360078551">työkaluvinkki</translation>
+<translation id="6790428901817661496">Toista</translation>
+<translation id="6820355525329141109">Laajennuksen lataaminen epäonnistui.</translation>
+<translation id="6820615603175220800">lähdeluetteloviittaus</translation>
+<translation id="6843725295806269523">äänetön</translation>
+<translation id="6885760532393684712">hakemisto</translation>
+<translation id="689129560213475294">kolofoni</translation>
+<translation id="6934078000481955284">muotoiltu lainaus</translation>
+<translation id="693476918119313863">otsikko</translation>
+<translation id="6941933287844615239">lataa media</translation>
+<translation id="6981594929165378967">lisäys</translation>
+<translation id="6989848892321993519">Pidennä tämä teksti vähintään <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä 1 merkki).</translation>
+<translation id="7034405885550056553">ehdotus</translation>
+<translation id="709897737746224366">Käytä pyydettyä muotoilua.</translation>
+<translation id="7118469954320184356">Ei kuvausta saatavilla</translation>
+<translation id="7139483182332611405">johdanto</translation>
+<translation id="7214187073215825913">sisältötiedot</translation>
+<translation id="7263440858009898357">Valitse kohde luettelosta.</translation>
+<translation id="727747134524199931">sarakkeen otsikko</translation>
+<translation id="7320576522385648310">puskuroidaan</translation>
+<translation id="7353453495576941748">tunnustus</translation>
+<translation id="7364796246159120393">Valitse tiedosto</translation>
+<translation id="739024184232394898">Muu...</translation>
+<translation id="7405738980073107433">loppuhuomautukset</translation>
+<translation id="7410239719251593705">Vaikuttaa sisältävän aikuisille suunnattua sisältöä Ei kuvausta saatavilla</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> Tt</translation>
+<translation id="7491962110804786152">sarkain</translation>
+<translation id="7514365320538308">Lataa</translation>
+<translation id="7529102961911894712">viittaajan linkki</translation>
+<translation id="7533959249147584474">Grafiikka, jolla ei ole tunnistetta</translation>
+<translation id="7647456547678091388">vinkki</translation>
+<translation id="7661956066982048809">grafiikkadokumentti</translation>
+<translation id="7673697353781729403">Tuntia</translation>
+<translation id="7681220483256441252">hakemisto</translation>
+<translation id="7740050170769002709">HTML-sisältö</translation>
+<translation id="7745230546936012372">Avaa kontekstivalikko, niin näet puuttuvia kuvien selityksiä</translation>
+<translation id="7750228210027921155">Kuva kuvassa</translation>
+<translation id="775297008183122718">Virheellinen arvo</translation>
+<translation id="7789962463072032349">tauko</translation>
+<translation id="7802800022689234070">näyttämiskolmio</translation>
+<translation id="7888071071722539607">Sähköpostiosoitteeseen kuuluu <ph name="ATSIGN" />-osa. Osoitteesta <ph name="INVALIDADDRESS" /> puuttuu <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">jakaja</translation>
+<translation id="795667975304826397">Ei valittua tiedostoa</translation>
+<translation id="8053789581856978548">hakutekstikenttä</translation>
+<translation id="8057695513531652401">ilmoitus</translation>
+<translation id="8105797009065549151">muistiinpanoviittaus</translation>
+<translation id="811583516810654505">Haetaan kuvausta…</translation>
+<translation id="8117451130807776954">Tällä viikolla</translation>
+<translation id="8199524924445686405">vvvv</translation>
+<translation id="8208673686607688524">paikallisen päivämäärän ja ajan valitsin</translation>
+<translation id="8261464734335370856">Kirjoitusvirhe</translation>
+<translation id="8284326494547611709">Tekstitykset</translation>
+<translation id="8346634859695247203">osio</translation>
+<translation id="835897206747267392">Virheellinen arvo.</translation>
+<translation id="8403857369060869934">kulunut aika: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">osa</translation>
+<translation id="8433900881053900389">työkalupalkki</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tiedostoa</translation>
+<translation id="8451268428117625855">Valitse tiedosto.</translation>
+<translation id="8461852803063341183">valintapainike</translation>
+<translation id="8474886197722836894">omistuskirjoitus</translation>
+<translation id="8531739829932800271">oikaisut</translation>
+<translation id="8534579021159131403">Minuuttia</translation>
+<translation id="8541249477527128034">median hallinta</translation>
+<translation id="8550857728288566671">grafiikkasymboli</translation>
+<translation id="8583702881314752957">määritelmäluettelo</translation>
+<translation id="8597182159515967513">otsikko</translation>
+<translation id="860475260694818407">sisällysluettelo</translation>
+<translation id="8613126697340063924">hallinnoi etätoistoa</translation>
+<translation id="862370744433916922">alaotsikko</translation>
+<translation id="8711688047404765493">syöte</translation>
+<translation id="8750798805984357768">Valitse yksi vaihtoehdoista.</translation>
+<translation id="8808573423886751634">luku</translation>
+<translation id="8822203815165896261">tekijätiedot</translation>
+<translation id="8845239796550121995">Suoratoistetaan televisioosi</translation>
+<translation id="8851136666856101339">pää</translation>
+<translation id="8875657656876809964">Videon toistovirhe</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kt</translation>
+<translation id="8987927404178983737">Kuukausi</translation>
+<translation id="901493112792887934">nykyinen toistoaika sekunteina</translation>
+<translation id="901834265349196618">sähköposti</translation>
+<translation id="9048119486235211610">navigointi</translation>
+<translation id="9062295712474918030">dokumentti</translation>
+<translation id="9093215626363556771">sulje kuva kuvassa ‑tila</translation>
+<translation id="9108370397979208512">matematiikka</translation>
+<translation id="9132465097189459683">Muu...</translation>
+<translation id="9138385573473225930">ilmoitus</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, alkupäivä: <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Kuva kuvassa</translation>
+<translation id="9168329111483466115">alaviite</translation>
+<translation id="954003015749068518">avaa kuva kuvassa ‑tila</translation>
+<translation id="966787709310836684">valikko</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..2bccd4cf97e
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fil.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fil">
+<translation id="1018939186200882850">item sa menu</translation>
+<translation id="10623998915015855">button sa pag-toggle</translation>
+<translation id="1088086359088493902">Segundo</translation>
+<translation id="1171774979989969504">Mangyaring magpasok ng email address.</translation>
+<translation id="1178581264944972037">I-pause</translation>
+<translation id="1188858454923323853">complementary</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">slider</translation>
+<translation id="1211441953136645838">endnote</translation>
+<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">mga credit</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">rehiyon</translation>
+<translation id="1591562245178063882">Buwang ito</translation>
+<translation id="1637811476055996098">Pumili ng Mga File</translation>
+<translation id="1650423536718072820">pullquote</translation>
+<translation id="1727886345390570319">itago ang menu ng mga nakasarang caption</translation>
+<translation id="1729654308190250600">Mangyaring maglagay ng isang non-empty na email address.</translation>
+<translation id="1758486001363313524">Iba pa...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">tree grid</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">i-play sa malayuang device</translation>
+<translation id="190587075670221089">pag-delete</translation>
+<translation id="1907737156431278478">halimbawa</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">katayuan</translation>
+<translation id="1938124657309484470">Dapat <ph name="MAXIMUM_DATE_OR_TIME" /> o mas nauna ang value.</translation>
+<translation id="1946271899482435442">Ipakita ang picker ng petsa</translation>
+<translation id="1993104285338243655">Lumipat sa pag-mirror</translation>
+<translation id="2060505056492490888">Ginamit ang '<ph name="DOT" />' sa maling posisyon sa '<ph name="INVALIDDOMAIN" />.'</translation>
+<translation id="2148716181193084225">Ngayon</translation>
+<translation id="2158401438286456825">listahan ng page</translation>
+<translation id="2226276347425096477">Mangyaring paikliin ang tekstong ito ng <ph name="MAX_CHARACTERS" /> (na) character o mas mababa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
+<translation id="2246498165605549352">Lokal na File</translation>
+<translation id="2247351761944213033">Linggo <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">checkbox</translation>
+<translation id="2311842470354187719">page break</translation>
+<translation id="2335594187091864976">picker ng petsa at oras</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>
+<translation id="2508569020611168319">listahan ng tab</translation>
+<translation id="2561842179657104141">magpakita ng higit pang kontrol sa media</translation>
+<translation id="2572483411312390101">i-play</translation>
+<translation id="2613802280814924224">Mangyaring maglagay ng isang wastong value. Ang pinakamalapit na wastong value ay <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Isumite</translation>
+<translation id="2657045182931379222">object ng graphics</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="2709516037105925701">AutoFill</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">mga komento</translation>
+<translation id="2746543609216772311">Dapat <ph name="MINIMUM_DATE_OR_TIME" /> o mas bago ang value.</translation>
+<translation id="2759744352195237655">pop up na button</translation>
+<translation id="2761667185364618470">Pakitingnan ang kahon na ito kung gusto mong magpatuloy.</translation>
+<translation id="2844350028562914727">mga detalye</translation>
+<translation id="2896972712917208084">pangkat ng radyo</translation>
+<translation id="2908441821576996758">Mangyaring magpasok ng listahan ng email address na pinaghihiwalay ng kuwit.</translation>
+<translation id="2940813599313844715">object</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> (na) MB</translation>
+<translation id="3075154866155599887">Mangyaring maglagay ng wastong halaga. Hindi kumpleto ang field o may isang di-wastong petsa.</translation>
+<translation id="3078740164268491126">talahanayan</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Mangyaring magpasok ng URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">combo box</translation>
+<translation id="3450233048674729344">Dapat mas mababa kaysa sa o katumbas ng <ph name="MAXIMUM" /> ang halaga.</translation>
+<translation id="3486220673238053218">kahulugan</translation>
+<translation id="3557673793733683882">heading <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">picker ng linggo</translation>
+<translation id="3685101356851116974">Walang label na larawan</translation>
+<translation id="3706100364254443312">lumipat</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Lumabas sa picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> (na) GB</translation>
+<translation id="3808586225841795776">termino</translation>
+<translation id="3822383571486410024">Pakihabaan ang text na ito hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
+<translation id="383465348367842624">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi bago ang '<ph name="ATSIGN" />.'</translation>
+<translation id="3846214748874656680">Lumabas sa fullscreen</translation>
+<translation id="3889183436948184105">rebisyon</translation>
+<translation id="3920932319529768807">konklusyon</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
+<translation id="3960700977367013758">scroll bar</translation>
+<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="4151657705144244502">graphic</translation>
+<translation id="4160057747563657758">telepono</translation>
+<translation id="4193965531860883258">foreword</translation>
+<translation id="4201051445878709314">Ipakita ang nakaraang buwan</translation>
+<translation id="421884353938374759">tagapili ng kulay</translation>
+<translation id="4248100235867064564">menu bar</translation>
+<translation id="4360991593054037559">Mangyaring maglagay ng isang wastong value. Ang dalawang pinakamalapit na wastong value ay <ph name="VALID_VALUE_LOW" /> at <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
+<translation id="4413860115965805769">button ng menu</translation>
+<translation id="4444765639179266822">Mukhang ang sabi ay: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">sanggunian sa glosaryo</translation>
+<translation id="4522570452068850558">Mga Detalye</translation>
+<translation id="4542388879936266156">natitirang oras: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi pagkatapos ng '<ph name="ATSIGN" />.'</translation>
+<translation id="4668956016107839909">appendix</translation>
+<translation id="4718048029184481307">Nagpe-play sa picture-in-picture</translation>
+<translation id="4742539557769756338">cover</translation>
+<translation id="4748357248530471599">i-toggle ang fullscreen ng cutout ng display</translation>
+<translation id="4757246831282535685">panel ng tab</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Mangyaring maglagay ng numero.</translation>
+<translation id="4912536737030637138">entry sa bibliograpiya</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ang napili</translation>
+<translation id="4992066212339426712">I-unmute</translation>
+<translation id="49969490063480558">Mangyaring maglagay ng isang bahagi pagkatapos ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="5034860022980953847">indicator ng pag-usad</translation>
+<translation id="5090250355906949916">scrubber ng tagal ng video</translation>
+<translation id="5093189678851173835">epigraph</translation>
+<translation id="5117590920725113268">Ipakita ang susunod na buwan</translation>
+<translation id="512758898067543763">header ng row</translation>
+<translation id="5143125788380636750">epilogue</translation>
+<translation id="5164977714490026579">Dapat mas mataas kaysa sa o katumbas ng <ph name="MINIMUM" /> ang halaga.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> (na) PB</translation>
+<translation id="5307600278924710095">Mangyaring maglagay ng isang bahagi na sinusundan ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="5334352251556557839">Hindi ma-play ang media.</translation>
+<translation id="5406322316791861025">anyo</translation>
+<translation id="5453733299334684579">item sa tree</translation>
+<translation id="5466621249238537318">Mangyaring pumili ng isa o higit pang mga file.</translation>
+<translation id="5468998798572797635">lumabas sa full screen</translation>
+<translation id="5516424706154626233">picker ng petsa</translation>
+<translation id="5537725057119320332">I-cast</translation>
+<translation id="5546461542133609677">i-unmute</translation>
+<translation id="5608153257855394627">i-highlight</translation>
+<translation id="561939826962581046">oras</translation>
+<translation id="5630795885300617244">Mag-double tap sa kaliwa o kanan upang lumaktaw nang 10s</translation>
+<translation id="5631759159893697722">abstract</translation>
+<translation id="5643186887447432888">button</translation>
+<translation id="5677946354068040947">higit pang opsyon</translation>
+<translation id="576709008726043716">panimula</translation>
+<translation id="57838592816432529">I-mute</translation>
+<translation id="5860033963881614850">Naka-off</translation>
+<translation id="588258955323874662">Fullscreen</translation>
+<translation id="5888666972993069672">Nagka-cast na sa <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">box para sa paghahanap</translation>
+<translation id="5939518447894949180">I-reset</translation>
+<translation id="5966707198760109579">Linggo</translation>
+<translation id="5987525920412732405">button ng pag-spin</translation>
+<translation id="6011459053400940133">slider ng volume</translation>
+<translation id="6015796118275082299">Taon</translation>
+<translation id="6023896073578205740">kahon ng listahan</translation>
+<translation id="6150588977291308318">bibliograpiya</translation>
+<translation id="6164829606128959761">metro</translation>
+<translation id="6166809985690652833">afterword</translation>
+<translation id="6209276755895393898">Mukhang: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosaryo</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Lumabas sa Picture-in-Picture</translation>
+<translation id="6398862346408813489">Ipakita ang panel ng pagpipilian ng buwan</translation>
+<translation id="6404546809543547843">scrubber ng oras ng audio</translation>
+<translation id="6443871981718447451">Ipakita ang menu ng mga nakasarang caption</translation>
+<translation id="6453774872122745852">mga pagkilala</translation>
+<translation id="6475115390776617481">presensya sa live</translation>
+<translation id="648732519525291180">picker ng petsa</translation>
+<translation id="6550675742724504774">Mga Pagpipilian</translation>
+<translation id="6572309429103589720">Invalid na grammar</translation>
+<translation id="658823671542763450">mag-full screen</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">I-clear</translation>
+<translation id="668171684555832681">Iba pa...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Hindi magandang playback quality</translation>
+<translation id="6755330956360078551">tooltip</translation>
+<translation id="6790428901817661496">I-play</translation>
+<translation id="6820355525329141109">Hindi ma-load ang plugin.</translation>
+<translation id="6820615603175220800">sanggunian sa bibliograpiya</translation>
+<translation id="6843725295806269523">i-mute</translation>
+<translation id="6885760532393684712">direktoryo</translation>
+<translation id="689129560213475294">colophon</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">header</translation>
+<translation id="6941933287844615239">i-download ang media</translation>
+<translation id="6981594929165378967">paglagay</translation>
+<translation id="6989848892321993519">Pakidagdagan ang text na ito nang hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng 1 character).</translation>
+<translation id="7034405885550056553">suhestyon</translation>
+<translation id="709897737746224366">Pakitugma ang hiniling na format.</translation>
+<translation id="7118469954320184356">Walang available na paglalarawan.</translation>
+<translation id="7139483182332611405">preface</translation>
+<translation id="7214187073215825913">impormasyon ng content</translation>
+<translation id="7263440858009898357">Mangyaring pumili ng item sa listahan.</translation>
+<translation id="727747134524199931">header ng column</translation>
+<translation id="7320576522385648310">nagba-buffer</translation>
+<translation id="7353453495576941748">credit</translation>
+<translation id="7364796246159120393">Pumili ng File</translation>
+<translation id="739024184232394898">Iba pa...</translation>
+<translation id="7405738980073107433">mga endnote</translation>
+<translation id="7410239719251593705">Mukhang may lamang pang-adult na content. Walang available na paglalarawan.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> (na) TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">I-download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7533959249147584474">Walang label na graphic</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">dokumento ng graphics</translation>
+<translation id="7673697353781729403">Oras</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">HTML na nilalaman</translation>
+<translation id="7745230546936012372">Para kunin ang mga paglalarawan ng larawan, buksan ang menu ng konteksto.</translation>
+<translation id="7750228210027921155">Picture in picture</translation>
+<translation id="775297008183122718">Di-wastong entry</translation>
+<translation id="7789962463072032349">i-pause</translation>
+<translation id="7802800022689234070">disclosure triangle</translation>
+<translation id="7888071071722539607">Mangyaring magsama ng '<ph name="ATSIGN" />' sa email address. Kulang ng '<ph name="ATSIGN" />' ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="7891486169920085145">splitter</translation>
+<translation id="795667975304826397">Walang napiling file</translation>
+<translation id="8053789581856978548">text field ng paghahanap</translation>
+<translation id="8057695513531652401">paunawa</translation>
+<translation id="8105797009065549151">sanggunian sa tala</translation>
+<translation id="811583516810654505">Kinukuha ang paglalarawan...</translation>
+<translation id="8117451130807776954">Linggong ito</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">picker ng lokal na petsa at oras</translation>
+<translation id="8261464734335370856">Invalid na spelling</translation>
+<translation id="8284326494547611709">Mga Caption</translation>
+<translation id="8346634859695247203">seksyon</translation>
+<translation id="835897206747267392">Di-wastong halaga.</translation>
+<translation id="8403857369060869934">lumipas na oras: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">bahagi</translation>
+<translation id="8433900881053900389">toolbar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> mga file</translation>
+<translation id="8451268428117625855">Mangyaring pumili ng file.</translation>
+<translation id="8461852803063341183">radio button</translation>
+<translation id="8474886197722836894">dedikasyon</translation>
+<translation id="8531739829932800271">mga erratum</translation>
+<translation id="8534579021159131403">Minuto</translation>
+<translation id="8541249477527128034">kontrol sa media</translation>
+<translation id="8550857728288566671">simbolo ng graphics</translation>
+<translation id="8583702881314752957">listahan ng kahulugan</translation>
+<translation id="8597182159515967513">heading</translation>
+<translation id="860475260694818407">talaan ng nilalaman</translation>
+<translation id="8613126697340063924">kontrolin ang malayuang pag-playback</translation>
+<translation id="862370744433916922">subtitle</translation>
+<translation id="8711688047404765493">output</translation>
+<translation id="8750798805984357768">Mangyaring pumili ng isa sa mga opsyong ito.</translation>
+<translation id="8808573423886751634">kabanata</translation>
+<translation id="8822203815165896261">impormasyon ng pag-author</translation>
+<translation id="8845239796550121995">Ikina-cast ngayon sa iyong TV</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Error sa pag-playback ng video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Buwan</translation>
+<translation id="901493112792887934">kasalukuyang oras ayon sa segundo</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">navigation</translation>
+<translation id="9062295712474918030">dokumento</translation>
+<translation id="9093215626363556771">lumabas sa picture-in-picture</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Iba pa...</translation>
+<translation id="9138385573473225930">alerto</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, na magsisimula sa <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture in Picture</translation>
+<translation id="9168329111483466115">footnote</translation>
+<translation id="954003015749068518">pumasok sa picture-in-picture</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..e16446aadc4
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_fr.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr">
+<translation id="1018939186200882850">élément de menu</translation>
+<translation id="10623998915015855">bouton d'activation/de désactivation</translation>
+<translation id="1088086359088493902">Secondes</translation>
+<translation id="1171774979989969504">Veuillez saisir une adresse e-mail.</translation>
+<translation id="1178581264944972037">Suspendre</translation>
+<translation id="1188858454923323853">complémentaire</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">curseur</translation>
+<translation id="1211441953136645838">note de fin</translation>
+<translation id="1281252709823657822">boîte de dialogue</translation>
+<translation id="1335095011850992622">crédits</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">bannière</translation>
+<translation id="1589122976691792535">région</translation>
+<translation id="1591562245178063882">Ce mois</translation>
+<translation id="1637811476055996098">Sélect. fichiers</translation>
+<translation id="1650423536718072820">témoignage</translation>
+<translation id="1727886345390570319">masquer le menu des sous-titres</translation>
+<translation id="1729654308190250600">Veuillez saisir une adresse e-mail dans le champ correspondant.</translation>
+<translation id="1758486001363313524">Autre…</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">arborescence</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">lire sur un appareil à distance</translation>
+<translation id="190587075670221089">suppression</translation>
+<translation id="1907737156431278478">exemple</translation>
+<translation id="1921819250265091946">jj</translation>
+<translation id="1930711995431081526">état</translation>
+<translation id="1938124657309484470">La date ou l'heure doit être égale ou antérieure à "<ph name="MAXIMUM_DATE_OR_TIME" />".</translation>
+<translation id="1946271899482435442">Afficher le sélecteur de date</translation>
+<translation id="1993104285338243655">Passage à la duplication d'écran</translation>
+<translation id="2060505056492490888">L'emplacement du caractère "<ph name="DOT" />" est incorrect dans "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Aujourd'hui</translation>
+<translation id="2158401438286456825">liste des pages</translation>
+<translation id="2226276347425096477">Veuillez réduire ce texte à <ph name="MAX_CHARACTERS" /> caractères maximum (il compte actuellement <ph name="CURRENT_LENGTH" /> caractères).</translation>
+<translation id="2246498165605549352">Fichier local</translation>
+<translation id="2247351761944213033">Semaine <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Piste <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">case à cocher</translation>
+<translation id="2311842470354187719">saut de page</translation>
+<translation id="2335594187091864976">outil de sélection de la date et de l'heure</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>
+<translation id="2508569020611168319">liste d'onglets</translation>
+<translation id="2561842179657104141">afficher plus de commandes multimédias</translation>
+<translation id="2572483411312390101">lire</translation>
+<translation id="2613802280814924224">Veuillez saisir une valeur valide. La valeur valide la plus proche est "<ph name="VALID_VALUE" />".</translation>
+<translation id="2653659639078652383">Valider</translation>
+<translation id="2657045182931379222">objet graphique</translation>
+<translation id="2674318244760992338">pied de page</translation>
+<translation id="2709516037105925701">Saisie automatique</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">commentaires</translation>
+<translation id="2746543609216772311">La date ou l'heure doit être égale ou postérieure à "<ph name="MINIMUM_DATE_OR_TIME" />".</translation>
+<translation id="2759744352195237655">bouton pop-up</translation>
+<translation id="2761667185364618470">Veuillez cocher cette case si vous souhaitez continuer.</translation>
+<translation id="2844350028562914727">détails</translation>
+<translation id="2896972712917208084">groupe de cases d'option</translation>
+<translation id="2908441821576996758">Veuillez saisir une liste d'adresses e-mail séparées par une virgule.</translation>
+<translation id="2940813599313844715">objet</translation>
+<translation id="3040011195152428237">Lien</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> Mo</translation>
+<translation id="3075154866155599887">Veuillez saisir une valeur valide. Le champ n'est pas complet ou contient une date non valide.</translation>
+<translation id="3078740164268491126">tableau</translation>
+<translation id="3086746722712840547">remarque</translation>
+<translation id="310520048233152454">Veuillez saisir une URL.</translation>
+<translation id="3175736971608411871">minuteur</translation>
+<translation id="3199563858620722075">boîte combinée</translation>
+<translation id="3450233048674729344">Cette valeur doit être inférieure ou égale à <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">définition</translation>
+<translation id="3557673793733683882">titre <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">outil de sélection de semaine</translation>
+<translation id="3685101356851116974">Image sans libellé</translation>
+<translation id="3706100364254443312">interrupteur</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Quitter le mode PIP (Picture-in-picture)</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> Go</translation>
+<translation id="3808586225841795776">terme</translation>
+<translation id="3822383571486410024">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement <ph name="CURRENT_LENGTH" />.</translation>
+<translation id="383465348367842624">La partie suivie du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Quitter le mode plein écran</translation>
+<translation id="3889183436948184105">révision</translation>
+<translation id="3920932319529768807">conclusion</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3944740393230681990">prologue</translation>
+<translation id="3960700977367013758">barre de défilement</translation>
+<translation id="4103419683916926126">Millisecondes</translation>
+<translation id="4151657705144244502">élément graphique</translation>
+<translation id="4160057747563657758">téléphone</translation>
+<translation id="4193965531860883258">avant-propos</translation>
+<translation id="4201051445878709314">Afficher le mois précédent</translation>
+<translation id="421884353938374759">palette couleurs</translation>
+<translation id="4248100235867064564">barre de menu</translation>
+<translation id="4360991593054037559">Veuillez saisir une valeur valide. Les deux valeurs valides les plus proches sont "<ph name="VALID_VALUE_LOW" />" et "<ph name="VALID_VALUE_HIGHER" />".</translation>
+<translation id="4384583879834880242">Questions/Réponses</translation>
+<translation id="4413860115965805769">bouton de menu</translation>
+<translation id="4444765639179266822">Voici la mention que contient probablement l'image : <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">référence de glossaire</translation>
+<translation id="4522570452068850558">Détails</translation>
+<translation id="4542388879936266156">temps restant : <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulaire</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">La partie précédée du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">annexe</translation>
+<translation id="4718048029184481307">Lecture en mode Picture-in-picture</translation>
+<translation id="4742539557769756338">couverture</translation>
+<translation id="4748357248530471599">activer/désactiver plein écran en encoche</translation>
+<translation id="4757246831282535685">panneau des onglets</translation>
+<translation id="4763480195061959176">vidéo</translation>
+<translation id="479989351350248267">rechercher</translation>
+<translation id="4812940957355064477">Veuillez saisir un nombre.</translation>
+<translation id="4912536737030637138">entrée bibliographique</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> élément(s) sélectionné(s)</translation>
+<translation id="4992066212339426712">Réactiver le son</translation>
+<translation id="49969490063480558">Veuillez saisir la partie manquante après le symbole "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
+<translation id="5034860022980953847">indicateur de progression</translation>
+<translation id="5090250355906949916">barre de défilement de la durée de la vidéo</translation>
+<translation id="5093189678851173835">épigraphe</translation>
+<translation id="5117590920725113268">Afficher le mois suivant</translation>
+<translation id="512758898067543763">en-tête de ligne</translation>
+<translation id="5143125788380636750">épilogue</translation>
+<translation id="5164977714490026579">Cette valeur doit être supérieure ou égale à <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> Po</translation>
+<translation id="5307600278924710095">Veuillez saisir la partie manquante avant le caractère "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
+<translation id="5334352251556557839">Impossible de lire les contenus multimédias.</translation>
+<translation id="5406322316791861025">nombre</translation>
+<translation id="5453733299334684579">élément d'arborescence</translation>
+<translation id="5466621249238537318">Veuillez sélectionner un ou plusieurs fichiers.</translation>
+<translation id="5468998798572797635">quitter le mode plein écran</translation>
+<translation id="5516424706154626233">outil de sélection de la date</translation>
+<translation id="5537725057119320332">Caster</translation>
+<translation id="5546461542133609677">réactiver le son</translation>
+<translation id="5608153257855394627">mettre en surbrillance</translation>
+<translation id="561939826962581046">horodatage</translation>
+<translation id="5630795885300617244">Appuyez deux fois à gauche/droite pour reculer/avancer de 10 s</translation>
+<translation id="5631759159893697722">résumé</translation>
+<translation id="5643186887447432888">bouton</translation>
+<translation id="5677946354068040947">plus d'options</translation>
+<translation id="576709008726043716">introduction</translation>
+<translation id="57838592816432529">Couper le son</translation>
+<translation id="5860033963881614850">Désactivé</translation>
+<translation id="588258955323874662">Plein écran</translation>
+<translation id="5888666972993069672">Diffusion en cours sur l'appareil "<ph name="DEVICE_FRIENDLY_NAME" />"</translation>
+<translation id="591047860372322273">champ de recherche</translation>
+<translation id="5939518447894949180">Réinitialiser</translation>
+<translation id="5966707198760109579">Semaine</translation>
+<translation id="5987525920412732405">bouton toupie</translation>
+<translation id="6011459053400940133">curseur de volume</translation>
+<translation id="6015796118275082299">Année</translation>
+<translation id="6023896073578205740">zone de liste</translation>
+<translation id="6150588977291308318">bibliographie</translation>
+<translation id="6164829606128959761">outil de mesure</translation>
+<translation id="6166809985690652833">postface</translation>
+<translation id="6209276755895393898">L'image représente probablement : <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossaire</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Quitter le mode PIP (Picture-in-picture)</translation>
+<translation id="6398862346408813489">Afficher le panneau de sélection du mois</translation>
+<translation id="6404546809543547843">curseur durée audio</translation>
+<translation id="6443871981718447451">afficher le menu des sous-titres</translation>
+<translation id="6453774872122745852">remerciements</translation>
+<translation id="6475115390776617481">actuellement présent</translation>
+<translation id="648732519525291180">outil de sélection de l'heure</translation>
+<translation id="6550675742724504774">Options</translation>
+<translation id="6572309429103589720">Grammaire non valide</translation>
+<translation id="658823671542763450">activer le mode plein écran</translation>
+<translation id="663493177488814956">flux</translation>
+<translation id="6637586476836377253">journal</translation>
+<translation id="6643016212128521049">Effacer</translation>
+<translation id="668171684555832681">Autre...</translation>
+<translation id="6692633176391053278">curseur</translation>
+<translation id="6709570249143506788">Mauvaise qualité de lecture</translation>
+<translation id="6755330956360078551">info-bulle</translation>
+<translation id="6790428901817661496">Lire</translation>
+<translation id="6820355525329141109">Impossible de charger le plug-in.</translation>
+<translation id="6820615603175220800">référence bibliographique</translation>
+<translation id="6843725295806269523">muet</translation>
+<translation id="6885760532393684712">annuaire</translation>
+<translation id="689129560213475294">achevé d'imprimer</translation>
+<translation id="6934078000481955284">bloc de citation</translation>
+<translation id="693476918119313863">en-tête</translation>
+<translation id="6941933287844615239">télécharger des contenus multimédias</translation>
+<translation id="6981594929165378967">insertion</translation>
+<translation id="6989848892321993519">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement un seul.</translation>
+<translation id="7034405885550056553">suggestion</translation>
+<translation id="709897737746224366">Veuillez respecter le format requis.</translation>
+<translation id="7118469954320184356">Aucune description disponible.</translation>
+<translation id="7139483182332611405">préface</translation>
+<translation id="7214187073215825913">informations sur le contenu</translation>
+<translation id="7263440858009898357">Sélectionnez un élément dans la liste.</translation>
+<translation id="727747134524199931">en-tête de colonne</translation>
+<translation id="7320576522385648310">mise en mémoire tampon</translation>
+<translation id="7353453495576941748">crédit</translation>
+<translation id="7364796246159120393">Choisir un fichier</translation>
+<translation id="739024184232394898">Autre…</translation>
+<translation id="7405738980073107433">notes de fin</translation>
+<translation id="7410239719251593705">Semble être du contenu réservé aux adultes. Aucune description disponible.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> To</translation>
+<translation id="7491962110804786152">tabulation</translation>
+<translation id="7514365320538308">Télécharger</translation>
+<translation id="7529102961911894712">lien entrant</translation>
+<translation id="7533959249147584474">Image sans libellé</translation>
+<translation id="7647456547678091388">conseil</translation>
+<translation id="7661956066982048809">document graphique</translation>
+<translation id="7673697353781729403">Heures</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">Contenu HTML</translation>
+<translation id="7745230546936012372">Pour obtenir les descriptions d'image manquantes, ouvrez le menu contextuel.</translation>
+<translation id="7750228210027921155">Mode PIP (Picture-in-Picture)</translation>
+<translation id="775297008183122718">Saisie incorrecte</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">triangle d'expansion</translation>
+<translation id="7888071071722539607">Veuillez inclure "<ph name="ATSIGN" />" dans l'adresse e-mail. Il manque un symbole "<ph name="ATSIGN" />" dans "<ph name="INVALIDADDRESS" />".</translation>
+<translation id="7891486169920085145">séparateur</translation>
+<translation id="795667975304826397">Aucun fichier choisi</translation>
+<translation id="8053789581856978548">champ de recherche de texte</translation>
+<translation id="8057695513531652401">notification</translation>
+<translation id="8105797009065549151">référence de note</translation>
+<translation id="811583516810654505">Récupération de la description…</translation>
+<translation id="8117451130807776954">Cette semaine</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">outil de sélection de la date et de l'heure locales</translation>
+<translation id="8261464734335370856">Orthographe non valide</translation>
+<translation id="8284326494547611709">Sous-titres</translation>
+<translation id="8346634859695247203">section</translation>
+<translation id="835897206747267392">Valeur incorrecte</translation>
+<translation id="8403857369060869934">temps écoulé : <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">partie</translation>
+<translation id="8433900881053900389">barre d'outils</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fichiers</translation>
+<translation id="8451268428117625855">Veuillez sélectionner un fichier.</translation>
+<translation id="8461852803063341183">case d'option</translation>
+<translation id="8474886197722836894">dédicace</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutes</translation>
+<translation id="8541249477527128034">commande multimédia</translation>
+<translation id="8550857728288566671">symbole graphique</translation>
+<translation id="8583702881314752957">liste de définitions</translation>
+<translation id="8597182159515967513">en-tête</translation>
+<translation id="860475260694818407">sommaire</translation>
+<translation id="8613126697340063924">contrôler la lecture à distance</translation>
+<translation id="862370744433916922">sous-titre</translation>
+<translation id="8711688047404765493">sortie</translation>
+<translation id="8750798805984357768">Veuillez sélectionner l'une de ces options.</translation>
+<translation id="8808573423886751634">chapitre</translation>
+<translation id="8822203815165896261">informations de création</translation>
+<translation id="8845239796550121995">En cours de diffusion sur votre téléviseur</translation>
+<translation id="8851136666856101339">principal</translation>
+<translation id="8875657656876809964">Erreur lors de la lecture de la vidéo</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> Ko</translation>
+<translation id="8987927404178983737">Mois</translation>
+<translation id="901493112792887934">durée actuelle en secondes</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigation</translation>
+<translation id="9062295712474918030">document</translation>
+<translation id="9093215626363556771">quitter le mode PIP</translation>
+<translation id="9108370397979208512">math.</translation>
+<translation id="9132465097189459683">Autre…</translation>
+<translation id="9138385573473225930">alerte</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> (premier jour de la semaine : <ph name="WEEK_START_DATE" />)</translation>
+<translation id="916607977885256133">Picture-in-picture</translation>
+<translation id="9168329111483466115">note de bas de page</translation>
+<translation id="954003015749068518">utiliser le mode PIP</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..514a4de71c7
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_gu.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="gu">
+<translation id="1018939186200882850">મેનૂ આઇટમ</translation>
+<translation id="10623998915015855">ટોગલ બટન</translation>
+<translation id="1088086359088493902">સેકંડ</translation>
+<translation id="1171774979989969504">કૃપા કરી કોઈ ઇમેઇલ ઍડ્રેસ દાખલ કરો.</translation>
+<translation id="1178581264944972037">થોભો</translation>
+<translation id="1188858454923323853">પૂરક</translation>
+<translation id="1206619573307042055">માર્કી</translation>
+<translation id="1206693055195146388">સ્લાઇડર</translation>
+<translation id="1211441953136645838">અંતિમ નોંધ</translation>
+<translation id="1281252709823657822">સંવાદ</translation>
+<translation id="1335095011850992622">ક્રેડિટ</translation>
+<translation id="1342835525016946179">લેખ</translation>
+<translation id="1359897965706325498">બેનર</translation>
+<translation id="1589122976691792535">પ્રદેશ</translation>
+<translation id="1591562245178063882">આ મહિને</translation>
+<translation id="1637811476055996098">ફાઇલો પસંદ કરો</translation>
+<translation id="1650423536718072820">પુલક્વોટ</translation>
+<translation id="1727886345390570319">બંધ કરેલું ઉપશીર્ષક મેનૂ છુપાવો</translation>
+<translation id="1729654308190250600">કૃપા કરીને ખાલી ન હોય એવું ઇમેઇલ ઍડ્રેસ દાખલ કરો.</translation>
+<translation id="1758486001363313524">અન્ય...</translation>
+<translation id="1806710327868736751">ચેતવણી_સંવાદ</translation>
+<translation id="1821985195704844674">ટ્રી ગ્રિડ</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">રિમોટ ઉપકરણ પર ચલાવો</translation>
+<translation id="190587075670221089">ડિલીટ કરો</translation>
+<translation id="1907737156431278478">ઉદાહરણ</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">સ્થિતિ</translation>
+<translation id="1938124657309484470">મૂલ્ય <ph name="MAXIMUM_DATE_OR_TIME" /> અથવા પહેલાંનું હોવું આવશ્યક છે.</translation>
+<translation id="1946271899482435442">તારીખ પીકર બતાવો</translation>
+<translation id="1993104285338243655">મીરરીંગ પર સ્વિચ કર્યુંં</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' નો ઉપયોગ '<ph name="INVALIDDOMAIN" />' માં ખોટી જગ્યાએ થયો છે.</translation>
+<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="2247351761944213033">અઠવાડિયું <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ટ્રૅક <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">ચેકબોક્સ</translation>
+<translation id="2311842470354187719">પેજ વિભાજન</translation>
+<translation id="2335594187091864976">તારીખ અને સમય પીકર</translation>
+<translation id="245932805758469625">વીડિયોની બાકી સેકન્ડ</translation>
+<translation id="248395913932153421">દિવસ</translation>
+<translation id="2507943997699731163">કૃપા કરીને આ ફીલ્ડ ભરો.</translation>
+<translation id="2508569020611168319">ટેબ સૂચિ</translation>
+<translation id="2561842179657104141">વધુ મીડિયા નિયંત્રણો બતાવો</translation>
+<translation id="2572483411312390101">ચલાવો</translation>
+<translation id="2613802280814924224">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. નિકટતમ માન્ય મૂલ્ય <ph name="VALID_VALUE" /> છે.</translation>
+<translation id="2653659639078652383">સબમિટ કરો</translation>
+<translation id="2657045182931379222">ગ્રાફિક્સ ઑબ્જેક્ટ</translation>
+<translation id="2674318244760992338">ફૂટર</translation>
+<translation id="2709516037105925701">સ્વતઃભરો</translation>
+<translation id="2723001399770238859">ઑડિઓ</translation>
+<translation id="2725963129578236554">કૉમેન્ટ</translation>
+<translation id="2746543609216772311">મૂલ્ય <ph name="MINIMUM_DATE_OR_TIME" /> અથવા પછીનું હોવું આવશ્યક છે.</translation>
+<translation id="2759744352195237655">પૉપ-અપ બટન</translation>
+<translation id="2761667185364618470">જો તમે આગળ વધવા માંગતા હો તો કૃપા કરીને આ બૉક્સને ચેક કરો.</translation>
+<translation id="2844350028562914727">વિગતો</translation>
+<translation id="2896972712917208084">રેડિઓ જૂથ</translation>
+<translation id="2908441821576996758">કૃપા કરીને અલ્પવિરામથી વિભાજિત ઇમેઇલ સરનામાંઓની સૂચિ દાખલ કરો.</translation>
+<translation id="2940813599313844715">ઑબ્જેક્ટ</translation>
+<translation id="3040011195152428237">લિંક</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" />MB</translation>
+<translation id="3075154866155599887">કૃપા કરીને માન્ય કિંમત દાખલ કરો. ફીલ્ડ અપૂર્ણ છે અથવા અમાન્ય તારીખ ધરાવે છે.</translation>
+<translation id="3078740164268491126">કોષ્ટક</translation>
+<translation id="3086746722712840547">નોંધ</translation>
+<translation id="310520048233152454">કૃપા કરી કોઈ URL દાખલ કરો.</translation>
+<translation id="3175736971608411871">ટાઇમર</translation>
+<translation id="3199563858620722075">કૉમ્બો બૉક્સ</translation>
+<translation id="3450233048674729344">મૂલ્ય <ph name="MAXIMUM" /> જેટલું અથવા આનાથી ઓછું હોવું આવશ્યક છે.</translation>
+<translation id="3486220673238053218">વિવરણ</translation>
+<translation id="3557673793733683882">મથાળું <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">અઠવાડિયાનું પિકર</translation>
+<translation id="3685101356851116974">લેબલ વિનાની છબી</translation>
+<translation id="3706100364254443312">સ્વિચ</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">ચિત્રમાં ચિત્રમાંથી બહાર નીકળો</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">ટર્મ</translation>
+<translation id="3822383571486410024">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અક્ષર અથવા તેથી વધુ સુધી લંબાવો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યાં છો).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' દ્વારા અનુસરાઈ રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="3846214748874656680">પૂર્ણસ્ક્રીનથી બહાર નીકળો</translation>
+<translation id="3889183436948184105">પુનરાવર્તન</translation>
+<translation id="3920932319529768807">સારાંશ</translation>
+<translation id="3924558731517983934">ઍપ્લિકેશન</translation>
+<translation id="3944740393230681990">પ્રસ્તાવના</translation>
+<translation id="3960700977367013758">સ્ક્રોલ બાર</translation>
+<translation id="4103419683916926126">મીલીસેકન્ડ</translation>
+<translation id="4151657705144244502">ગ્રાફિક</translation>
+<translation id="4160057747563657758">ટેલિફોન</translation>
+<translation id="4193965531860883258">આમુખ</translation>
+<translation id="4201051445878709314">પાછળનો મહિનો બતાવો</translation>
+<translation id="421884353938374759">રંગ ચૂંટનાર</translation>
+<translation id="4248100235867064564">મેનૂ બાર</translation>
+<translation id="4360991593054037559">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. બે નિકટતમ માન્ય મૂલ્યો <ph name="VALID_VALUE_LOW" /> અને <ph name="VALID_VALUE_HIGHER" /> છે.</translation>
+<translation id="4384583879834880242">પ્રશ્ન અને જવાબ</translation>
+<translation id="4413860115965805769">મેનૂ બટન</translation>
+<translation id="4444765639179266822">આવું બોલતા જણાય છે: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">શબ્દાવલીનો સંદર્ભ</translation>
+<translation id="4522570452068850558">વિગતો</translation>
+<translation id="4542388879936266156">બાકીનો સમય: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ફોર્મ</translation>
+<translation id="4661075872484491155">ટ્રી</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="4668956016107839909">જોડાણ</translation>
+<translation id="4718048029184481307">ચિત્રમાં ચિત્રમાંથી ચલાવી રહ્યાં છીએ</translation>
+<translation id="4742539557769756338">કવર</translation>
+<translation id="4748357248530471599">ડિસ્પ્લેમાં જ સામેલ પૂર્ણસ્ક્રીન ટૉગલ કરો</translation>
+<translation id="4757246831282535685">ટેબ પેનલ</translation>
+<translation id="4763480195061959176">વીડિયો</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">કૃપા કરીને એક નંબર દાખલ કરો.</translation>
+<translation id="4912536737030637138">ગ્રંથસૂચિની એન્ટ્રી</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> પસંદ કર્યા</translation>
+<translation id="4992066212339426712">અનમ્યૂટ કરો</translation>
+<translation id="49969490063480558">કૃપા કરીને '<ph name="ATSIGN" />' ને અનુસરી રહેલો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
+<translation id="5034860022980953847">પ્રગતિ સૂચક</translation>
+<translation id="5090250355906949916">વીડિયો ટાઇમ સ્ક્રબર</translation>
+<translation id="5093189678851173835">શિલાલેખ</translation>
+<translation id="5117590920725113268">આગલો મહિનો દર્શાવો</translation>
+<translation id="512758898067543763">પંક્તિ હેડર</translation>
+<translation id="5143125788380636750">ઉપસંહાર</translation>
+<translation id="5164977714490026579">મૂલ્ય <ph name="MINIMUM" /> જેટલું અથવા આનાથી વધુ હોવું આવશ્યક છે.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">કૃપા કરીને '<ph name="ATSIGN" />' ની આગળનો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
+<translation id="5334352251556557839">મીડિયા ચલાવવામાં નિષ્ફળ રહ્યાં.</translation>
+<translation id="5406322316791861025">આકૃતિ</translation>
+<translation id="5453733299334684579">ટ્રી આઇટમ</translation>
+<translation id="5466621249238537318">કૃપા કરીને એક અથવા વધુ ફાઇલ પસંદ કરો. </translation>
+<translation id="5468998798572797635">પૂર્ણ સ્ક્રીનથી બહાર નીકળો</translation>
+<translation id="5516424706154626233">તારીખ પીકર</translation>
+<translation id="5537725057119320332">કાસ્ટ કરો</translation>
+<translation id="5546461542133609677">અનમ્યૂટ કરો</translation>
+<translation id="5608153257855394627">હાઇલાઇટ કરેલું કન્ટેન્ટ</translation>
+<translation id="561939826962581046">સમય</translation>
+<translation id="5630795885300617244">10 સેકન્ડ છોડવા માટે ડાબે અથવા જમણે બે વાર ટૅપ કરો</translation>
+<translation id="5631759159893697722">અમૂર્ત</translation>
+<translation id="5643186887447432888">બટન</translation>
+<translation id="5677946354068040947">વધુ વિકલ્પો</translation>
+<translation id="576709008726043716">પ્રસ્તાવના</translation>
+<translation id="57838592816432529">અવાજ બંધ કરો</translation>
+<translation id="5860033963881614850">બંધ</translation>
+<translation id="588258955323874662">પૂર્ણસ્ક્રીન</translation>
+<translation id="5888666972993069672">હવે <ph name="DEVICE_FRIENDLY_NAME" /> પર કાસ્ટ કરી રહ્યાં છીએ</translation>
+<translation id="591047860372322273">શોધ બૉક્સ</translation>
+<translation id="5939518447894949180">રીસેટ કરો</translation>
+<translation id="5966707198760109579">અઠવાડિયું</translation>
+<translation id="5987525920412732405">સ્પિન બટન</translation>
+<translation id="6011459053400940133">વોલ્યુમ સ્લાઇડર</translation>
+<translation id="6015796118275082299">વર્ષ</translation>
+<translation id="6023896073578205740">સૂચિ બૉક્સ</translation>
+<translation id="6150588977291308318">ગ્રંથસૂચિ</translation>
+<translation id="6164829606128959761">મીટર</translation>
+<translation id="6166809985690652833">સમાપન ભાષણ</translation>
+<translation id="6209276755895393898">આના જેવું જણાય છે: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">શબ્દાવલી</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">ચિત્ર-માં-ચિત્રમાંથી બહાર નીકળો</translation>
+<translation id="6398862346408813489">મહિના પસંદગી પેનલ દર્શાવો</translation>
+<translation id="6404546809543547843">ઑડિઓ સમય સ્ક્રબર</translation>
+<translation id="6443871981718447451">બંધ કરેલું ઉપશીર્ષક મેનૂ દર્શાવો</translation>
+<translation id="6453774872122745852">સ્વીકૃતિઓ</translation>
+<translation id="6475115390776617481">લાઇવ ઉપસ્થિતિ</translation>
+<translation id="648732519525291180">સમય પીકર</translation>
+<translation id="6550675742724504774">વિકલ્પો</translation>
+<translation id="6572309429103589720">અમાન્ય વ્યાકરણ</translation>
+<translation id="658823671542763450">પૂર્ણ સ્ક્રીનમાં દાખલ થાઓ</translation>
+<translation id="663493177488814956">ફીડ</translation>
+<translation id="6637586476836377253">લૉગ</translation>
+<translation id="6643016212128521049">સાફ કરો</translation>
+<translation id="668171684555832681">અન્ય...</translation>
+<translation id="6692633176391053278">સ્ટેપર</translation>
+<translation id="6709570249143506788">ખરાબ પ્લેબૅક ક્વૉલિટી</translation>
+<translation id="6755330956360078551">ટૂલટીપ</translation>
+<translation id="6790428901817661496">ચલાવો</translation>
+<translation id="6820355525329141109">પ્લગિન લોડ કરી શક્યાં નથી.</translation>
+<translation id="6820615603175220800">ગ્રંથસૂચિનો સંદર્ભ</translation>
+<translation id="6843725295806269523">બંધ કરો</translation>
+<translation id="6885760532393684712">ડિરેક્ટરી</translation>
+<translation id="689129560213475294">પ્રકાશકની માહિતી</translation>
+<translation id="6934078000481955284">બ્લૉકક્વોટ</translation>
+<translation id="693476918119313863">હેડર</translation>
+<translation id="6941933287844615239">મીડિયા ડાઉનલોડ કરો</translation>
+<translation id="6981594929165378967">ઉમેરો</translation>
+<translation id="6989848892321993519">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અથવા તેથી વધુ અક્ષર સુધી લંબાવો (તમે હાલમાં 1 અક્ષરનો ઉપયોગ કરી રહ્યાં છો).</translation>
+<translation id="7034405885550056553">સૂચન</translation>
+<translation id="709897737746224366">કૃપા કરીને વિનંતી કરેલા ફોર્મેટ સાથે મેળ કરો.</translation>
+<translation id="7118469954320184356">કોઈ વર્ણન ઉપલબ્ધ નથી.</translation>
+<translation id="7139483182332611405">પ્રસ્તાવના</translation>
+<translation id="7214187073215825913">કન્ટેન્ટ વિશેની માહિતી</translation>
+<translation id="7263440858009898357">કૃપા કરીને સૂચિમાંથી એક આઇટમ પસંદ કરો.</translation>
+<translation id="727747134524199931">કૉલમ હેડર</translation>
+<translation id="7320576522385648310">બફર થઈ રહ્યું છે</translation>
+<translation id="7353453495576941748">ક્રેડિટ</translation>
+<translation id="7364796246159120393">ફાઇલ પસંદ કરો</translation>
+<translation id="739024184232394898">અન્ય...</translation>
+<translation id="7405738980073107433">અંતિમ નોંધ</translation>
+<translation id="7410239719251593705">પુખ્ત લોકો માટેનું કન્ટેન્ટ સમાવતી હોવાનું જણાય છે. કોઈ વર્ણન ઉપલબ્ધ નથી.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">ટેબ</translation>
+<translation id="7514365320538308">ડાઉનલોડ કરો</translation>
+<translation id="7529102961911894712">પાછળ લઈ જતી લિંક</translation>
+<translation id="7533959249147584474">લેબલ વિનાનું ગ્રાફિક</translation>
+<translation id="7647456547678091388">ટિપ</translation>
+<translation id="7661956066982048809">ગ્રાફિક્સ દસ્તાવેજ</translation>
+<translation id="7673697353781729403">કલાક</translation>
+<translation id="7681220483256441252">અનુક્રમણિકા</translation>
+<translation id="7740050170769002709">HTML માહિતી</translation>
+<translation id="7745230546936012372">છબીઓના ખૂટતા વર્ણનો માટે, સંદર્ભ મેનૂ ખોલો.</translation>
+<translation id="7750228210027921155">ચિત્રમાં ચિત્ર</translation>
+<translation id="775297008183122718">અમાન્ય એન્ટ્રી</translation>
+<translation id="7789962463072032349">થોભો</translation>
+<translation id="7802800022689234070">પ્રકટીકરણ ત્રિકોણ</translation>
+<translation id="7888071071722539607">કૃપા કરીને ઇમેઇલ સરનામાંમાં '<ph name="ATSIGN" />' શામેલ કરો. '<ph name="INVALIDADDRESS" />'માં '<ph name="ATSIGN" />' ખૂટે છે.</translation>
+<translation id="7891486169920085145">વિભાજનકર્તા</translation>
+<translation id="795667975304826397">કોઈ ફાઇલ પસંદ કરેલી નથી</translation>
+<translation id="8053789581856978548">ટેક્સ્ટ ફીલ્ડ શોધો</translation>
+<translation id="8057695513531652401">સૂચના</translation>
+<translation id="8105797009065549151">નોંધ સંદર્ભ</translation>
+<translation id="811583516810654505">વર્ણન મેળવી રહ્યાં છીએ…</translation>
+<translation id="8117451130807776954">આ અઠવાડિયે</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">સ્થાનિક તારીખ અને સમય પિકર</translation>
+<translation id="8261464734335370856">અમાન્ય જોડણી</translation>
+<translation id="8284326494547611709">કૅપ્શન્સ</translation>
+<translation id="8346634859695247203">વિભાગ</translation>
+<translation id="835897206747267392">અમાન્ય મૂલ્ય.</translation>
+<translation id="8403857369060869934">વીતેલો સમય: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">ભાગ</translation>
+<translation id="8433900881053900389">ટુલબાર</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ફાઇલો</translation>
+<translation id="8451268428117625855">કૃપા કરીને કોઈ ફાઇલ પસંદ કરો.</translation>
+<translation id="8461852803063341183">રેડિઓ બટન</translation>
+<translation id="8474886197722836894">સમર્પણ</translation>
+<translation id="8531739829932800271">ભૂલ સુધારાની સૂચિ</translation>
+<translation id="8534579021159131403">મિનિટ</translation>
+<translation id="8541249477527128034">મીડિયાનું નિયંત્રણ</translation>
+<translation id="8550857728288566671">ગ્રાફિક્સ પ્રતીક</translation>
+<translation id="8583702881314752957">વિવરણ સૂચિ</translation>
+<translation id="8597182159515967513">મથાળું</translation>
+<translation id="860475260694818407">અનુક્રમણિકા</translation>
+<translation id="8613126697340063924">રિમોટ પ્લેબેકનું નિયંત્રણ કરો</translation>
+<translation id="862370744433916922">(સબટાઇટલ)</translation>
+<translation id="8711688047404765493">આઉટપુટ</translation>
+<translation id="8750798805984357768">કૃપા કરીને આ વિકલ્પોમાંથી કોઈ એક પસંદ કરો.</translation>
+<translation id="8808573423886751634">પ્રકરણ</translation>
+<translation id="8822203815165896261">ચોક્કસ કન્ટેન્ટ વિશેની માહિતી</translation>
+<translation id="8845239796550121995">હમણાં તમારા TV પર કાસ્ટ કરી રહ્યાં છીએ</translation>
+<translation id="8851136666856101339">મુખ્ય</translation>
+<translation id="8875657656876809964">વીડિયો પ્લેબૅક ભૂલ</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">મહિનો</translation>
+<translation id="901493112792887934">સેકન્ડ્સમાં વર્તમાન સમય</translation>
+<translation id="901834265349196618">ઇમેઇલ</translation>
+<translation id="9048119486235211610">નેવિગેશન</translation>
+<translation id="9062295712474918030">દસ્તાવેજ</translation>
+<translation id="9093215626363556771">ચિત્ર-માં-ચિત્રમાંથી બહાર નીકળો</translation>
+<translation id="9108370397979208512">ગણિત</translation>
+<translation id="9132465097189459683">અન્ય...</translation>
+<translation id="9138385573473225930">ચેતવણી</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> થી શરૂ કરીને</translation>
+<translation id="916607977885256133">ચિત્ર-માં-ચિત્ર</translation>
+<translation id="9168329111483466115">ફૂટનોટ</translation>
+<translation id="954003015749068518">ચિત્ર-માં-ચિત્રમાં પ્રવેશ કરો</translation>
+<translation id="966787709310836684">મેનૂ</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..fdd004cbee4
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hi.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hi">
+<translation id="1018939186200882850">मेन्यू आइटम</translation>
+<translation id="10623998915015855">टॉगल बटन</translation>
+<translation id="1088086359088493902">सेकंड</translation>
+<translation id="1171774979989969504">कृपया ई-मेल पता दर्ज करें.</translation>
+<translation id="1178581264944972037">रोकें</translation>
+<translation id="1188858454923323853">पूरक</translation>
+<translation id="1206619573307042055">मार्की</translation>
+<translation id="1206693055195146388">स्लाइडर</translation>
+<translation id="1211441953136645838">एंड नोट</translation>
+<translation id="1281252709823657822">संवाद</translation>
+<translation id="1335095011850992622">क्रेडिट</translation>
+<translation id="1342835525016946179">लेख</translation>
+<translation id="1359897965706325498">बैनर</translation>
+<translation id="1589122976691792535">क्षेत्र</translation>
+<translation id="1591562245178063882">इस माह</translation>
+<translation id="1637811476055996098">फ़ाइलें चुनें</translation>
+<translation id="1650423536718072820">पुलकोट</translation>
+<translation id="1727886345390570319">बंद कैप्शन मेन्यू छिपाएं</translation>
+<translation id="1729654308190250600">कृपया गैर-खाली ईमेल पता डालें.</translation>
+<translation id="1758486001363313524">अन्य...</translation>
+<translation id="1806710327868736751">सूचना संवाद</translation>
+<translation id="1821985195704844674">ट्री ग्रिड</translation>
+<translation id="1822429046913737220">पूर्वाह्न/अपराह्न</translation>
+<translation id="1832974991323546415">दूरस्थ डिवाइस पर चलाएं</translation>
+<translation id="190587075670221089">मिटाना</translation>
+<translation id="1907737156431278478">उदाहरण</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">स्थिति</translation>
+<translation id="1938124657309484470">मान <ph name="MAXIMUM_DATE_OR_TIME" /> या पहले का होना चाहिए.</translation>
+<translation id="1946271899482435442">तारीख पिकर दिखाएं</translation>
+<translation id="1993104285338243655">'स्क्रीन शेयर करने' पर स्विच किया गया</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' का '<ph name="INVALIDDOMAIN" />' में गलत स्थान पर उपयोग किया गया है.</translation>
+<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="2247351761944213033">हफ़्ता <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ट्रैक <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">चेकबॉक्स</translation>
+<translation id="2311842470354187719">नया पेज</translation>
+<translation id="2335594187091864976">तारीख और समय पिकर</translation>
+<translation id="245932805758469625">बचे हुए वीडियो का कुल समय सेकंड में</translation>
+<translation id="248395913932153421">दिन</translation>
+<translation id="2507943997699731163">कृपया इस फ़ील्ड को भरें.</translation>
+<translation id="2508569020611168319">टैब सूची</translation>
+<translation id="2561842179657104141">ज़्यादा मीडिया नियंत्रण दिखाएं</translation>
+<translation id="2572483411312390101">चलाएं</translation>
+<translation id="2613802280814924224">कृपया कोई मान्य मान डालें. निकटतम मान्य मान <ph name="VALID_VALUE" /> है.</translation>
+<translation id="2653659639078652383">सबमिट करें</translation>
+<translation id="2657045182931379222">ग्राफ़िक्स ऑब्जेक्ट</translation>
+<translation id="2674318244760992338">पाद लेख</translation>
+<translation id="2709516037105925701">ऑटोमैटिक भरना</translation>
+<translation id="2723001399770238859">ऑडियो</translation>
+<translation id="2725963129578236554">टिप्पणियां</translation>
+<translation id="2746543609216772311">मान <ph name="MINIMUM_DATE_OR_TIME" /> या बाद का होना चाहिए.</translation>
+<translation id="2759744352195237655">पॉप अप बटन</translation>
+<translation id="2761667185364618470">अगर आप आगे बढ़ना चाहते हैं तो इस बॉक्‍स को सही का निशान लगाकर चुनें.</translation>
+<translation id="2844350028562914727">जानकारी</translation>
+<translation id="2896972712917208084">रेडियो समूह</translation>
+<translation id="2908441821576996758">कृपया ईमेल पतों की अल्पविराम द्वारा विभाजित सूची दर्ज करें.</translation>
+<translation id="2940813599313844715">ऑब्जेक्ट</translation>
+<translation id="3040011195152428237">संपर्क</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> एमबी</translation>
+<translation id="3075154866155599887">कृपया सही मान डालें. फ़ील्ड अधूरी है या उसमें डाली गई तारीख गलत है.</translation>
+<translation id="3078740164268491126">टेबल</translation>
+<translation id="3086746722712840547">नोट</translation>
+<translation id="310520048233152454">कृपया यूआरएल डालें.</translation>
+<translation id="3175736971608411871">टाइमर</translation>
+<translation id="3199563858620722075">कॉम्बो बॉक्स</translation>
+<translation id="3450233048674729344">मान <ph name="MAXIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
+<translation id="3486220673238053218">परिभाषा</translation>
+<translation id="3557673793733683882">शीर्षक <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">हफ़्ता पिकर (हफ़्ता चुनने की सुविधा)</translation>
+<translation id="3685101356851116974">लेबल न की गई इमेज</translation>
+<translation id="3706100364254443312">स्विच करें</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">'पिक्चर में पिक्चर' सुविधा से बाहर निकलें</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> जीबी</translation>
+<translation id="3808586225841795776">शब्द</translation>
+<translation id="3822383571486410024">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> वर्णों या ज़्यादा तक बढ़ाएं (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="3846214748874656680">पूर्णस्क्रीन से बाहर निकलें</translation>
+<translation id="3889183436948184105">बदलाव</translation>
+<translation id="3920932319529768807">निष्कर्ष</translation>
+<translation id="3924558731517983934">ऐप्लिकेशन</translation>
+<translation id="3944740393230681990">प्रस्तावना</translation>
+<translation id="3960700977367013758">स्क्रोल बार</translation>
+<translation id="4103419683916926126">मिलीसेकंड</translation>
+<translation id="4151657705144244502">ग्राफ़‍िक</translation>
+<translation id="4160057747563657758">टेलीफ़ोन</translation>
+<translation id="4193965531860883258">भूमिका</translation>
+<translation id="4201051445878709314">पिछला महीना दिखाएं</translation>
+<translation id="421884353938374759">रंग पिकर</translation>
+<translation id="4248100235867064564">मेन्यू बार</translation>
+<translation id="4360991593054037559">कृपया कोई मान्य मान डालें. दो निकटतम मान्य मान <ph name="VALID_VALUE_LOW" /> और <ph name="VALID_VALUE_HIGHER" /> हैं.</translation>
+<translation id="4384583879834880242">सवाल और जवाब</translation>
+<translation id="4413860115965805769">मेन्यू बटन</translation>
+<translation id="4444765639179266822">यह जानकारी इस बारे में लगती है: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">संदर्भ के लिए शब्दावली</translation>
+<translation id="4522570452068850558">विवरण</translation>
+<translation id="4542388879936266156">बचा हुआ समय: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">फ़ॉर्म</translation>
+<translation id="4661075872484491155">ट्री</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4718048029184481307">वीडियो को 'पिक्चर में पिक्चर' सुविधा में चलाया जा रहा है</translation>
+<translation id="4742539557769756338">कवर</translation>
+<translation id="4748357248530471599">डिसप्ले कटआउट फ़ुलस्क्रीन टॉगल करें</translation>
+<translation id="4757246831282535685">टैब पैनल</translation>
+<translation id="4763480195061959176">वीडियो</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">कृपया कोई संख्या डालें.</translation>
+<translation id="4912536737030637138">संदर्भ सूची प्रविष्टि</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> चुने गए</translation>
+<translation id="4992066212339426712">अनम्यूट करें</translation>
+<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' के बाद आने वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
+<translation id="5034860022980953847">प्रगति संकेतक</translation>
+<translation id="5090250355906949916">वीडियो टाइम स्क्रबर</translation>
+<translation id="5093189678851173835">इपिग्राफ़</translation>
+<translation id="5117590920725113268">अगला महीना दिखाएं</translation>
+<translation id="512758898067543763">पंक्ति शीर्षलेख</translation>
+<translation id="5143125788380636750">उपसंहार</translation>
+<translation id="5164977714490026579">मान <ph name="MINIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' के पहले वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
+<translation id="5334352251556557839">मीडिया नहीं चला पा रहे हैं.</translation>
+<translation id="5406322316791861025">आकृति</translation>
+<translation id="5453733299334684579">ट्री आइटम</translation>
+<translation id="5466621249238537318">कृपया एक या ज़्यादा फ़ाइल को चुनें.</translation>
+<translation id="5468998798572797635">फ़ुल स्क्रीन से बाहर निकलें</translation>
+<translation id="5516424706154626233">तारीख पिकर</translation>
+<translation id="5537725057119320332">कास्‍ट करें</translation>
+<translation id="5546461542133609677">अनम्यूट करें</translation>
+<translation id="5608153257855394627">हाइलाइट</translation>
+<translation id="561939826962581046">समय</translation>
+<translation id="5630795885300617244">10 सेकंड के लिए 'स्किप' करने के लिए बाएं या दाएं पर दो बार टैप करें</translation>
+<translation id="5631759159893697722">संक्षेप</translation>
+<translation id="5643186887447432888">बटन</translation>
+<translation id="5677946354068040947">ज़्यादा विकल्प</translation>
+<translation id="576709008726043716">परिचय</translation>
+<translation id="57838592816432529">म्यूट करें</translation>
+<translation id="5860033963881614850">बंद</translation>
+<translation id="588258955323874662">पूर्णस्‍क्रीन</translation>
+<translation id="5888666972993069672">अब <ph name="DEVICE_FRIENDLY_NAME" /> पर कास्ट किया जा रहा है</translation>
+<translation id="591047860372322273">खोज बॉक्स</translation>
+<translation id="5939518447894949180">रीसेट करें</translation>
+<translation id="5966707198760109579">हफ़्ता</translation>
+<translation id="5987525920412732405">स्पिन बटन</translation>
+<translation id="6011459053400940133">वॉल्यूम स्लाइडर</translation>
+<translation id="6015796118275082299">वर्ष</translation>
+<translation id="6023896073578205740">सूची बॉक्स</translation>
+<translation id="6150588977291308318">संदर्भ सूची</translation>
+<translation id="6164829606128959761">मीटर</translation>
+<translation id="6166809985690652833">उपसंहार</translation>
+<translation id="6209276755895393898">यह इमेज इस बारे में लगती है: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">शब्दावली</translation>
+<translation id="6281763101136022427">यूआरएल</translation>
+<translation id="6310801910862476708">'पिक्चर में पिक्चर से बाहर निकलें'</translation>
+<translation id="6398862346408813489">महीना चुनने का पैनल दिखाएं</translation>
+<translation id="6404546809543547843">ऑडियो समय स्क्रबर</translation>
+<translation id="6443871981718447451">बंद कैप्‍शन मेन्यू दिखाएं</translation>
+<translation id="6453774872122745852">धन्यवाद</translation>
+<translation id="6475115390776617481">लाइव मौजूदगी</translation>
+<translation id="648732519525291180">समय पिकर</translation>
+<translation id="6550675742724504774">विकल्प</translation>
+<translation id="6572309429103589720">गलत व्याकरण</translation>
+<translation id="658823671542763450">फ़ुल स्क्रीन में प्रवेश करें</translation>
+<translation id="663493177488814956">फ़ीड</translation>
+<translation id="6637586476836377253">लॉग</translation>
+<translation id="6643016212128521049">साफ़ करें</translation>
+<translation id="668171684555832681">अन्य...</translation>
+<translation id="6692633176391053278">स्टेपर</translation>
+<translation id="6709570249143506788">खराब वीडियो क्वालिटी</translation>
+<translation id="6755330956360078551">टूलटिप</translation>
+<translation id="6790428901817661496">चलाएं</translation>
+<translation id="6820355525329141109">प्लग इन लोड नहीं किया जा सका.</translation>
+<translation id="6820615603175220800">संदर्भ सूची का संदर्भ</translation>
+<translation id="6843725295806269523">म्यूट करें</translation>
+<translation id="6885760532393684712">निर्देशिका</translation>
+<translation id="689129560213475294">कॉलफ़न</translation>
+<translation id="6934078000481955284">ब्लॉककोट</translation>
+<translation id="693476918119313863">हेडर</translation>
+<translation id="6941933287844615239">मीडिया डाउनलोड करें</translation>
+<translation id="6981594929165378967">डालना</translation>
+<translation id="6989848892321993519">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> या उससे ज़्यादा वर्णों तक बढ़ाएं (आप इस समय 1 वर्ण का उपयोग कर रहे हैं).</translation>
+<translation id="7034405885550056553">सुझाव</translation>
+<translation id="709897737746224366">कृपया अनुरोधित प्रारूप का मिलान करें.</translation>
+<translation id="7118469954320184356">कोई जानकारी मौजूद नहीं है.</translation>
+<translation id="7139483182332611405">आमुख</translation>
+<translation id="7214187073215825913">सामग्री की जानकारी</translation>
+<translation id="7263440858009898357">कृपया सूची में किसी आइटम को चुनें.</translation>
+<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
+<translation id="7320576522385648310">बफ़र हो रहा है</translation>
+<translation id="7353453495576941748">क्रेडिट</translation>
+<translation id="7364796246159120393">फ़ाइल चुनें</translation>
+<translation id="739024184232394898">अन्य...</translation>
+<translation id="7405738980073107433">एंडनोट</translation>
+<translation id="7410239719251593705">लगता है कि वयस्क सामग्री मौजूद है. कोई जानकारी मौजूद नहीं है.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">टैब</translation>
+<translation id="7514365320538308">डाउनलोड करें</translation>
+<translation id="7529102961911894712">बैक लिंक</translation>
+<translation id="7533959249147584474">बिना लेबल वाले ग्राफ़िक</translation>
+<translation id="7647456547678091388">सलाह</translation>
+<translation id="7661956066982048809">ग्राफ़िक्स दस्तावेज़</translation>
+<translation id="7673697353781729403">घंटे</translation>
+<translation id="7681220483256441252">इंडेक्स</translation>
+<translation id="7740050170769002709">HTML सामग्री</translation>
+<translation id="7745230546936012372">ऐसी इमेज जो मौजूद नहीं हैं उनके बारे में जानकारी पाने के लिए, संदर्भ मेन्यू खोलें.</translation>
+<translation id="7750228210027921155">पिक्चर में पिक्चर</translation>
+<translation id="775297008183122718">अमान्य प्रविष्टि</translation>
+<translation id="7789962463072032349">रोकें</translation>
+<translation id="7802800022689234070">प्रकटीकरण त्रिकोण</translation>
+<translation id="7888071071722539607">कृपया ईमेल पते में '<ph name="ATSIGN" />' शामिल करें. '<ph name="INVALIDADDRESS" />' में '<ph name="ATSIGN" />' नहीं है.</translation>
+<translation id="7891486169920085145">विभाजक</translation>
+<translation id="795667975304826397">कोई फाइल नहीं चुनी गई</translation>
+<translation id="8053789581856978548">लेख फ़ील्ड खोजें</translation>
+<translation id="8057695513531652401">सूचना</translation>
+<translation id="8105797009065549151">नोट संदर्भ</translation>
+<translation id="811583516810654505">इमेज की जानकारी ढूंढी जा रही है</translation>
+<translation id="8117451130807776954">इस हफ़्ते</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">स्थानीय तारीख और समय पिकर (स्थानीय तारीख और समय चुनने की सुविधा)</translation>
+<translation id="8261464734335370856">गलत स्पेलिंग</translation>
+<translation id="8284326494547611709">कैप्शन</translation>
+<translation id="8346634859695247203">सेक्शन</translation>
+<translation id="835897206747267392">अमान्य मान.</translation>
+<translation id="8403857369060869934">बीता हुआ समय: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">भाग</translation>
+<translation id="8433900881053900389">टूलबार</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फ़ाइल</translation>
+<translation id="8451268428117625855">कृपया किसी फ़ाइल को चुनें.</translation>
+<translation id="8461852803063341183">रेडियो बटन</translation>
+<translation id="8474886197722836894">लगन</translation>
+<translation id="8531739829932800271">गलतियां</translation>
+<translation id="8534579021159131403">मिनट</translation>
+<translation id="8541249477527128034">मीडिया नियंत्रण</translation>
+<translation id="8550857728288566671">ग्राफ़िक्स चिह्न</translation>
+<translation id="8583702881314752957">परिभाषा सूची</translation>
+<translation id="8597182159515967513">हेडिंग</translation>
+<translation id="860475260694818407">विषय सूची</translation>
+<translation id="8613126697340063924">दूरस्थ प्लेबैक नियंत्रित करें</translation>
+<translation id="862370744433916922">सबटाइटल</translation>
+<translation id="8711688047404765493">आउटपुट</translation>
+<translation id="8750798805984357768">कृपया इनमें से कोई विकल्प चुनें.</translation>
+<translation id="8808573423886751634">पाठ</translation>
+<translation id="8822203815165896261">लेखन से जुड़ी जानकारी</translation>
+<translation id="8845239796550121995">अब आपके टीवी पर कास्ट हो रहा है</translation>
+<translation id="8851136666856101339">मुख्य</translation>
+<translation id="8875657656876809964">वीडियो चलाने में गड़बड़ी</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> केबी</translation>
+<translation id="8987927404178983737">माह</translation>
+<translation id="901493112792887934">वर्तमान समय, सेकंड में</translation>
+<translation id="901834265349196618">ईमेल</translation>
+<translation id="9048119486235211610">मार्गदर्शक</translation>
+<translation id="9062295712474918030">दस्तावेज़</translation>
+<translation id="9093215626363556771">पिक्चर में पिक्चर से बाहर निकलें</translation>
+<translation id="9108370397979208512">गणित</translation>
+<translation id="9132465097189459683">अन्य...</translation>
+<translation id="9138385573473225930">सूचना</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> से प्रारंभ हो रहा है</translation>
+<translation id="916607977885256133">पिक्चर में पिक्चर</translation>
+<translation id="9168329111483466115">फ़ुटनोट</translation>
+<translation id="954003015749068518">पिक्चर में पिक्चर चालू करें</translation>
+<translation id="966787709310836684">मेन्यू</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..f593b987913
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hr.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hr">
+<translation id="1018939186200882850">stavka izbornika</translation>
+<translation id="10623998915015855">preklopni gumb</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="1171774979989969504">Unesite e-adresu.</translation>
+<translation id="1178581264944972037">Pauziraj</translation>
+<translation id="1188858454923323853">dopunski</translation>
+<translation id="1206619573307042055">pomični tekst</translation>
+<translation id="1206693055195146388">klizač</translation>
+<translation id="1211441953136645838">završna napomena</translation>
+<translation id="1281252709823657822">dijalog</translation>
+<translation id="1335095011850992622">zasluge</translation>
+<translation id="1342835525016946179">članak</translation>
+<translation id="1359897965706325498">natpis</translation>
+<translation id="1589122976691792535">regija</translation>
+<translation id="1591562245178063882">Ovaj mjesec</translation>
+<translation id="1637811476055996098">Odabir datoteka</translation>
+<translation id="1650423536718072820">izdvojeno</translation>
+<translation id="1727886345390570319">sakrij izbornik titlova</translation>
+<translation id="1729654308190250600">Unesite e-adresu koja nije prazna vrijednost.</translation>
+<translation id="1758486001363313524">Drugo...</translation>
+<translation id="1806710327868736751">dijaloški okvir upozorenja</translation>
+<translation id="1821985195704844674">rešetka u obliku stabla</translation>
+<translation id="1822429046913737220">prijepodne/poslijepodne</translation>
+<translation id="1832974991323546415">reproduciraj na udaljenom uređaju</translation>
+<translation id="190587075670221089">brisanje</translation>
+<translation id="1907737156431278478">primjer</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Vrijednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ili prije toga.</translation>
+<translation id="1946271899482435442">Prikaz alata za odabir datuma</translation>
+<translation id="1993104285338243655">Prebačeno na zrcaljenje</translation>
+<translation id="2060505056492490888">Znak "<ph name="DOT" />" upotrebljava se na pogrešnom položaju u domeni "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Danas</translation>
+<translation id="2158401438286456825">popis stranica</translation>
+<translation id="2226276347425096477">Skratite taj tekst na <ph name="MAX_CHARACTERS" /> znakova ili manje (trenutačno upotrebljavate <ph name="CURRENT_LENGTH" /> znakova).</translation>
+<translation id="2246498165605549352">Lokalna datoteka</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. tjedan, <ph name="YEAR" />. godina</translation>
+<translation id="2277199496770840904">Zapis <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">potvrdni okvir</translation>
+<translation id="2311842470354187719">prijelom stranice</translation>
+<translation id="2335594187091864976">alat za odabir datuma i vremena</translation>
+<translation id="245932805758469625">preostali broj sekundi videozapisa</translation>
+<translation id="248395913932153421">Dan</translation>
+<translation id="2507943997699731163">Ispunite ovo polje.</translation>
+<translation id="2508569020611168319">popis kartica</translation>
+<translation id="2561842179657104141">prikaži više kontrola za medije</translation>
+<translation id="2572483411312390101">reprodukcija</translation>
+<translation id="2613802280814924224">Unesite važeću vrijednost. Najbliža je važeća vrijednost <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Pošalji</translation>
+<translation id="2657045182931379222">grafički objekt</translation>
+<translation id="2674318244760992338">podnožje</translation>
+<translation id="2709516037105925701">Automatsko popunjavanje</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="2725963129578236554">komentari</translation>
+<translation id="2746543609216772311">Vrijednost mora biti <ph name="MINIMUM_DATE_OR_TIME" /> ili nakon toga.</translation>
+<translation id="2759744352195237655">gumb skočnog prozora</translation>
+<translation id="2761667185364618470">Označite taj okvir ako želite ići dalje.</translation>
+<translation id="2844350028562914727">pojedinosti</translation>
+<translation id="2896972712917208084">grupa izbornih gumba</translation>
+<translation id="2908441821576996758">Unesite popis adresa e-pošte odijeljen zarezima.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">veza</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Unesite važeću vrijednost. Ovo je polje nepotpuno ili sadrži nevažeći datum.</translation>
+<translation id="3078740164268491126">tablica</translation>
+<translation id="3086746722712840547">napom</translation>
+<translation id="310520048233152454">Unesite URL.</translation>
+<translation id="3175736971608411871">odbrojavanje</translation>
+<translation id="3199563858620722075">kombinirani okvir</translation>
+<translation id="3450233048674729344">Vrijednost mora biti <ph name="MAXIMUM" /> ili manja.</translation>
+<translation id="3486220673238053218">definicija</translation>
+<translation id="3557673793733683882">naslov <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">alat za odabir tjedna</translation>
+<translation id="3685101356851116974">Neoznačena slika</translation>
+<translation id="3706100364254443312">prebaci</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Zatvori sliku u slici</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">pojam</translation>
+<translation id="3822383571486410024">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" />. Trenutačno imate premalo znakova (<ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Dio adrese ispred znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Izlaz iz punog zaslona</translation>
+<translation id="3889183436948184105">izmjena</translation>
+<translation id="3920932319529768807">zaključak</translation>
+<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">klizač</translation>
+<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="4151657705144244502">slika</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">predgovor</translation>
+<translation id="4201051445878709314">Prikaži prethodni mjesec</translation>
+<translation id="421884353938374759">odabir boja</translation>
+<translation id="4248100235867064564">traka izbornika</translation>
+<translation id="4360991593054037559">Unesite važeću vrijednost. Dvije su najbliže važeće vrijednosti <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Pitanja i odgovori</translation>
+<translation id="4413860115965805769">gumb izbornika</translation>
+<translation id="4444765639179266822">Čini se da piše: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referenca iz pojmovnika</translation>
+<translation id="4522570452068850558">Detalji</translation>
+<translation id="4542388879936266156">preostalo vrijeme: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">obrazac</translation>
+<translation id="4661075872484491155">stablo</translation>
+<translation id="4664250907885839816">Dio adrese iza znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">dodatak</translation>
+<translation id="4718048029184481307">Reproducira se u načinu slika u slici</translation>
+<translation id="4742539557769756338">naslovnica</translation>
+<translation id="4748357248530471599">prebacite urez na zaslonu u cijeli zaslon</translation>
+<translation id="4757246831282535685">ploča kartice</translation>
+<translation id="4763480195061959176">videozapis</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Unesite broj.</translation>
+<translation id="4912536737030637138">bibliografski unos</translation>
+<translation id="4975562563186953947">Odabrano: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Uključi zvuk</translation>
+<translation id="49969490063480558">Unesite dio adrese iza znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
+<translation id="5034860022980953847">pokazivač napretka</translation>
+<translation id="5090250355906949916">klizač vremena videozapisa</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Prikaži sljedeći mjesec</translation>
+<translation id="512758898067543763">zaglavlje retka</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Vrijednost mora biti <ph name="MINIMUM" /> ili veća.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Unesite dio adrese ispred znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
+<translation id="5334352251556557839">Reprodukcija medija nije uspjela.</translation>
+<translation id="5406322316791861025">lik</translation>
+<translation id="5453733299334684579">stavka stabla</translation>
+<translation id="5466621249238537318">Izaberite jednu ili više datoteka.</translation>
+<translation id="5468998798572797635">izlazak iz cijelog zaslona</translation>
+<translation id="5516424706154626233">alat za odabir datuma</translation>
+<translation id="5537725057119320332">Emitiraj</translation>
+<translation id="5546461542133609677">uključivanje zvuka</translation>
+<translation id="5608153257855394627">istaknuto</translation>
+<translation id="561939826962581046">vrijeme</translation>
+<translation id="5630795885300617244">Dvaput dodirnite lijevo ili desno za preskakanje od 10 s</translation>
+<translation id="5631759159893697722">sažetak</translation>
+<translation id="5643186887447432888">gumb</translation>
+<translation id="5677946354068040947">više opcija</translation>
+<translation id="576709008726043716">uvod</translation>
+<translation id="57838592816432529">Isključi zvuk</translation>
+<translation id="5860033963881614850">Isključeno</translation>
+<translation id="588258955323874662">Puni zaslon</translation>
+<translation id="5888666972993069672">Trenutačno se emitira na uređaju <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">okvir za pretraživanje</translation>
+<translation id="5939518447894949180">Ponovno postavi</translation>
+<translation id="5966707198760109579">Tjedan</translation>
+<translation id="5987525920412732405">okretni gumb</translation>
+<translation id="6011459053400940133">Klizač za glasnoću</translation>
+<translation id="6015796118275082299">Godina</translation>
+<translation id="6023896073578205740">okvir s popisom</translation>
+<translation id="6150588977291308318">bibliografija</translation>
+<translation id="6164829606128959761">mjerač</translation>
+<translation id="6166809985690652833">pogovor</translation>
+<translation id="6209276755895393898">Čini se da je to: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">pojmovnik</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Izlaz iz načina slika u slici</translation>
+<translation id="6398862346408813489">Prikaži ploču za odabir mjeseca</translation>
+<translation id="6404546809543547843">klizač vremena audiozapisa</translation>
+<translation id="6443871981718447451">prikaži izbornik titlova</translation>
+<translation id="6453774872122745852">zahvale</translation>
+<translation id="6475115390776617481">trenutačno prisutni suradnik</translation>
+<translation id="648732519525291180">alat za odabir vremena</translation>
+<translation id="6550675742724504774">Opcije</translation>
+<translation id="6572309429103589720">Netočna gramatika</translation>
+<translation id="658823671542763450">otvaranje na cijelom zaslonu</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">zap</translation>
+<translation id="6643016212128521049">Izbriši</translation>
+<translation id="668171684555832681">Ostalo...</translation>
+<translation id="6692633176391053278">povećanje/smanjenje strelicama gore/dolje (stepper)</translation>
+<translation id="6709570249143506788">Loša kvaliteta reprodukcije</translation>
+<translation id="6755330956360078551">opis</translation>
+<translation id="6790428901817661496">Reproduciraj</translation>
+<translation id="6820355525329141109">Nije bilo moguće učitati dodatak.</translation>
+<translation id="6820615603175220800">bibliografska referenca</translation>
+<translation id="6843725295806269523">isključi ton</translation>
+<translation id="6885760532393684712">direktorij</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">uvučeni citat</translation>
+<translation id="693476918119313863">zaglavlje</translation>
+<translation id="6941933287844615239">preuzmi medij</translation>
+<translation id="6981594929165378967">umetanje</translation>
+<translation id="6989848892321993519">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" /> (trenutačno imate 1 znak).</translation>
+<translation id="7034405885550056553">prijedlog</translation>
+<translation id="709897737746224366">Udovoljite zadanom formatu.</translation>
+<translation id="7118469954320184356">Opis nije dostupan.</translation>
+<translation id="7139483182332611405">predgovor</translation>
+<translation id="7214187073215825913">informacije o sadržaju</translation>
+<translation id="7263440858009898357">Odaberite stavku s popisa.</translation>
+<translation id="727747134524199931">zaglavlje stupca</translation>
+<translation id="7320576522385648310">pohranjivanje u međuspremnik</translation>
+<translation id="7353453495576941748">zasluga</translation>
+<translation id="7364796246159120393">Odaberi datoteku</translation>
+<translation id="739024184232394898">Drugo...</translation>
+<translation id="7405738980073107433">završne napomene</translation>
+<translation id="7410239719251593705">Čini se da sadrži sadržaj za odrasle. Opis nije dostupan.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">kart</translation>
+<translation id="7514365320538308">Preuzmi</translation>
+<translation id="7529102961911894712">povratna veza</translation>
+<translation id="7533959249147584474">Neoznačena grafika</translation>
+<translation id="7647456547678091388">savjet</translation>
+<translation id="7661956066982048809">grafički dokument</translation>
+<translation id="7673697353781729403">Sati</translation>
+<translation id="7681220483256441252">indeks</translation>
+<translation id="7740050170769002709">HTML sadržaj</translation>
+<translation id="7745230546936012372">Da biste dohvatili opise slika koji nedostaju, otvorite kontekstni izbornik.</translation>
+<translation id="7750228210027921155">Slika u slici</translation>
+<translation id="775297008183122718">Nevažeći unos</translation>
+<translation id="7789962463072032349">pauziraj</translation>
+<translation id="7802800022689234070">trokut za otkrivanje</translation>
+<translation id="7888071071722539607">Uključite znak "<ph name="ATSIGN" />" u e-adresu. U adresi "<ph name="INVALIDADDRESS" />" nedostaje znak "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">razdjelnik</translation>
+<translation id="795667975304826397">Nije odabrana niti jedna datoteka.</translation>
+<translation id="8053789581856978548">pretraži tekstno polje</translation>
+<translation id="8057695513531652401">obavijest</translation>
+<translation id="8105797009065549151">referenca bilješke</translation>
+<translation id="811583516810654505">U tijeku je dohvaćanje opisa...</translation>
+<translation id="8117451130807776954">Ovaj tjedan</translation>
+<translation id="8199524924445686405">gggg</translation>
+<translation id="8208673686607688524">alat za odabir lokalnog datuma i vremena</translation>
+<translation id="8261464734335370856">Netočan pravopis</translation>
+<translation id="8284326494547611709">Titlovi</translation>
+<translation id="8346634859695247203">odjeljak</translation>
+<translation id="835897206747267392">Nevažeća vrijednost.</translation>
+<translation id="8403857369060869934">proteklo vrijeme: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">dio</translation>
+<translation id="8433900881053900389">alatna traka</translation>
+<translation id="8444882422881193423">Broj datoteka: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Odaberite datoteku.</translation>
+<translation id="8461852803063341183">izborni gumb</translation>
+<translation id="8474886197722836894">posveta</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="8541249477527128034">kontrola medija</translation>
+<translation id="8550857728288566671">grafički simbol</translation>
+<translation id="8583702881314752957">popis definicija</translation>
+<translation id="8597182159515967513">naslov</translation>
+<translation id="860475260694818407">sadržaj</translation>
+<translation id="8613126697340063924">upravljaj daljinskom reprodukcijom</translation>
+<translation id="862370744433916922">titl</translation>
+<translation id="8711688047404765493">izlaz</translation>
+<translation id="8750798805984357768">Izaberite jednu od tih opcija.</translation>
+<translation id="8808573423886751634">poglavlje</translation>
+<translation id="8822203815165896261">informacije o autorstvu</translation>
+<translation id="8845239796550121995">Emitira se na televizoru</translation>
+<translation id="8851136666856101339">glav</translation>
+<translation id="8875657656876809964">Pogreška pri reprodukciji videozapisa</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mjesec</translation>
+<translation id="901493112792887934">trenutačno vrijeme u sekundama</translation>
+<translation id="901834265349196618">e-pošta</translation>
+<translation id="9048119486235211610">navigacija</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">izlaz iz načina slika u slici</translation>
+<translation id="9108370397979208512">mat</translation>
+<translation id="9132465097189459683">Drugo...</translation>
+<translation id="9138385573473225930">upozorenje</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, počevši od <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Slika u slici</translation>
+<translation id="9168329111483466115">fusnota</translation>
+<translation id="954003015749068518">pokretanje načina slika u slici</translation>
+<translation id="966787709310836684">izbornik</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..25f46aa4b43
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_hu.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hu">
+<translation id="1018939186200882850">menüelem</translation>
+<translation id="10623998915015855">átkapcsológomb</translation>
+<translation id="1088086359088493902">Másodperc</translation>
+<translation id="1171774979989969504">Kérjük, adjon meg egy e-mail címet.</translation>
+<translation id="1178581264944972037">Szünet</translation>
+<translation id="1188858454923323853">kiegészítő</translation>
+<translation id="1206619573307042055">fényújság</translation>
+<translation id="1206693055195146388">csúszka</translation>
+<translation id="1211441953136645838">záró jegyzet</translation>
+<translation id="1281252709823657822">párbeszédpanel</translation>
+<translation id="1335095011850992622">készítők</translation>
+<translation id="1342835525016946179">cikk</translation>
+<translation id="1359897965706325498">szalaghirdetés</translation>
+<translation id="1589122976691792535">régió</translation>
+<translation id="1591562245178063882">Ebben a hónapban</translation>
+<translation id="1637811476055996098">Fájlok kiválasztása</translation>
+<translation id="1650423536718072820">kiemelt idézet</translation>
+<translation id="1727886345390570319">a feliratok menü elrejtése</translation>
+<translation id="1729654308190250600">Kérjük, ne hagyja üresen az e-mail-cím mezőjét.</translation>
+<translation id="1758486001363313524">Más...</translation>
+<translation id="1806710327868736751">értesítő párbeszédpanel</translation>
+<translation id="1821985195704844674">farács</translation>
+<translation id="1822429046913737220">de./du.</translation>
+<translation id="1832974991323546415">lejátszás távoli eszközön</translation>
+<translation id="190587075670221089">törlés</translation>
+<translation id="1907737156431278478">példa</translation>
+<translation id="1921819250265091946">nn</translation>
+<translation id="1930711995431081526">állapot</translation>
+<translation id="1938124657309484470">Az érték <ph name="MAXIMUM_DATE_OR_TIME" /> vagy azt megelőző kell, hogy legyen.</translation>
+<translation id="1946271899482435442">Dátumválasztó megjelenítése</translation>
+<translation id="1993104285338243655">Átváltott tükrözésre</translation>
+<translation id="2060505056492490888">A „<ph name="DOT" />” rossz helyen van a(z) „<ph name="INVALIDDOMAIN" />” címben.</translation>
+<translation id="2148716181193084225">Ma</translation>
+<translation id="2158401438286456825">oldallista</translation>
+<translation id="2226276347425096477">Kérjük, rövidítse le a szöveget legfeljebb <ph name="MAX_CHARACTERS" /> karakterre (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
+<translation id="2246498165605549352">Helyi fájl</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hét, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />. szám</translation>
+<translation id="2291999235780842123">jelölőnégyzet</translation>
+<translation id="2311842470354187719">oldaltörés</translation>
+<translation id="2335594187091864976">dátum- és időválasztó</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>
+<translation id="2508569020611168319">laplista</translation>
+<translation id="2561842179657104141">további médiavezérlők megjelenítése</translation>
+<translation id="2572483411312390101">lejátszás</translation>
+<translation id="2613802280814924224">Kérjük, érvényes értéket adjon meg. A legközelebbi érvényes érték <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Elküldés</translation>
+<translation id="2657045182931379222">grafikus objektum</translation>
+<translation id="2674318244760992338">lábléc</translation>
+<translation id="2709516037105925701">Automatikus kitöltés</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">megjegyzések</translation>
+<translation id="2746543609216772311">Az érték <ph name="MINIMUM_DATE_OR_TIME" /> vagy azt követő kell, hogy legyen.</translation>
+<translation id="2759744352195237655">előugró gomb</translation>
+<translation id="2761667185364618470">Kérjük, jelölje be ezt a jelölőnégyzetet, ha tovább kíván haladni.</translation>
+<translation id="2844350028562914727">részletek</translation>
+<translation id="2896972712917208084">választógombcsoport</translation>
+<translation id="2908441821576996758">Kérjük, adjon meg egy vesszőkkel elválasztott e-mail címlistát.</translation>
+<translation id="2940813599313844715">objektum</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Kérjük, adjon meg érvényes értéket. A mező hiányos, vagy érvénytelen dátum van megadva.</translation>
+<translation id="3078740164268491126">táblázat</translation>
+<translation id="3086746722712840547">jegyzet</translation>
+<translation id="310520048233152454">Adjon meg egy URL-t.</translation>
+<translation id="3175736971608411871">időzítő</translation>
+<translation id="3199563858620722075">legördülő lista</translation>
+<translation id="3450233048674729344">Az érték legyen kisebb vagy egyenlő, mint <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definíció</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" />. címsor</translation>
+<translation id="3670698553867754311">hétválasztó</translation>
+<translation id="3685101356851116974">Címke nélküli kép</translation>
+<translation id="3706100364254443312">váltás</translation>
+<translation id="3732799496749320381">hh</translation>
+<translation id="3754210790023674521">Kilépés a kép a képben módból</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">kifejezés</translation>
+<translation id="3822383571486410024">Kérjük, <ph name="MIN_CHARACTERS" /> karakter hosszú vagy annál hosszabb szöveget adjon meg (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
+<translation id="383465348367842624">A „<ph name="ATSIGN" />” előtti rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
+<translation id="3846214748874656680">Teljes képernyő – ki</translation>
+<translation id="3889183436948184105">változat</translation>
+<translation id="3920932319529768807">összefoglalás</translation>
+<translation id="3924558731517983934">alkalmazás</translation>
+<translation id="3944740393230681990">prológus</translation>
+<translation id="3960700977367013758">görgetősáv</translation>
+<translation id="4103419683916926126">Ezredmásodperc</translation>
+<translation id="4151657705144244502">grafika</translation>
+<translation id="4160057747563657758">telefonszám</translation>
+<translation id="4193965531860883258">előszó</translation>
+<translation id="4201051445878709314">Az előző hónap megjelenítése</translation>
+<translation id="421884353938374759">színválasztó</translation>
+<translation id="4248100235867064564">menüsor</translation>
+<translation id="4360991593054037559">Kérjük, érvényes értéket adjon meg. A két legközelebbi érvényes érték <ph name="VALID_VALUE_LOW" /> és <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Kérdések és válaszok</translation>
+<translation id="4413860115965805769">menügomb</translation>
+<translation id="4444765639179266822">Úgy tűnik, hogy a következő látható rajta: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">szószedet-hivatkozás</translation>
+<translation id="4522570452068850558">Részletek</translation>
+<translation id="4542388879936266156">hátralévő idő: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">űrlap</translation>
+<translation id="4661075872484491155">fa</translation>
+<translation id="4664250907885839816">A „<ph name="ATSIGN" />” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
+<translation id="4668956016107839909">függelék</translation>
+<translation id="4718048029184481307">Lejátszás kép a képben módban</translation>
+<translation id="4742539557769756338">borító</translation>
+<translation id="4748357248530471599">képernyőkivágás váltása teljes képernyőn</translation>
+<translation id="4757246831282535685">lappanel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Kérjük, adjon meg egy számot.</translation>
+<translation id="4912536737030637138">bibliográfiai bejegyzés</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> kiválasztva</translation>
+<translation id="4992066212339426712">Némítás feloldása</translation>
+<translation id="49969490063480558">Kérjük, adja meg a „<ph name="ATSIGN" />” utáni részt is. A(z) „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
+<translation id="5034860022980953847">folyamatjelző</translation>
+<translation id="5090250355906949916">a videóidő vezérlője</translation>
+<translation id="5093189678851173835">mottó</translation>
+<translation id="5117590920725113268">A következő hónap megjelenítése</translation>
+<translation id="512758898067543763">sorfejléc</translation>
+<translation id="5143125788380636750">végszó</translation>
+<translation id="5164977714490026579">Az érték legyen nagyobb vagy egyenlő, mint <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Kérjük, adja meg a „<ph name="ATSIGN" />” előtti részt is. A „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
+<translation id="5334352251556557839">Nem sikerült a médiafájl lejátszása.</translation>
+<translation id="5406322316791861025">alak</translation>
+<translation id="5453733299334684579">faelem</translation>
+<translation id="5466621249238537318">Kérjük, válasszon ki egy vagy több fájlt.</translation>
+<translation id="5468998798572797635">kilépés a teljes képernyős nézetből</translation>
+<translation id="5516424706154626233">dátumválasztó</translation>
+<translation id="5537725057119320332">Küldés</translation>
+<translation id="5546461542133609677">némítás feloldása</translation>
+<translation id="5608153257855394627">kiemelés</translation>
+<translation id="561939826962581046">idő</translation>
+<translation id="5630795885300617244">A jobb/bal oldalon duplán koppintva ugorhat előre/vissza 10 másodpercet</translation>
+<translation id="5631759159893697722">absztrakt</translation>
+<translation id="5643186887447432888">gomb</translation>
+<translation id="5677946354068040947">további beállítások</translation>
+<translation id="576709008726043716">bevezetés</translation>
+<translation id="57838592816432529">Némítás</translation>
+<translation id="5860033963881614850">Kikapcsolva</translation>
+<translation id="588258955323874662">Teljes képernyő</translation>
+<translation id="5888666972993069672">Átküldés ide: <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">keresőmező</translation>
+<translation id="5939518447894949180">Visszaállítás</translation>
+<translation id="5966707198760109579">Hét</translation>
+<translation id="5987525920412732405">léptetőnyíl</translation>
+<translation id="6011459053400940133">hangerőcsúszka</translation>
+<translation id="6015796118275082299">Év</translation>
+<translation id="6023896073578205740">listamező</translation>
+<translation id="6150588977291308318">bibliográfia</translation>
+<translation id="6164829606128959761">mérő</translation>
+<translation id="6166809985690652833">utószó</translation>
+<translation id="6209276755895393898">Úgy tűnik, hogy a következőről van szó: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">szószedet</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Kilépés a kép a képben funkcióból</translation>
+<translation id="6398862346408813489">A hónapválasztási panel megjelenítése</translation>
+<translation id="6404546809543547843">hang idővonalának vezérlője</translation>
+<translation id="6443871981718447451">a feliratok menü mutatása</translation>
+<translation id="6453774872122745852">köszönetnyilvánítás</translation>
+<translation id="6475115390776617481">élő közreműködés</translation>
+<translation id="648732519525291180">időválasztó</translation>
+<translation id="6550675742724504774">Beállítások</translation>
+<translation id="6572309429103589720">Nyelvtani hiba</translation>
+<translation id="658823671542763450">teljes képernyős nézet</translation>
+<translation id="663493177488814956">hírcsatorna</translation>
+<translation id="6637586476836377253">napló</translation>
+<translation id="6643016212128521049">Törlés</translation>
+<translation id="668171684555832681">Egyéb...</translation>
+<translation id="6692633176391053278">léptető</translation>
+<translation id="6709570249143506788">Gyenge lejátszási minőség</translation>
+<translation id="6755330956360078551">elemleírás</translation>
+<translation id="6790428901817661496">Játék</translation>
+<translation id="6820355525329141109">Nem sikerült betölteni a beépülő modult.</translation>
+<translation id="6820615603175220800">bibliográfiai hivatkozás</translation>
+<translation id="6843725295806269523">némítás</translation>
+<translation id="6885760532393684712">címtár</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">bekezdésszintű idézet</translation>
+<translation id="693476918119313863">fejléc</translation>
+<translation id="6941933287844615239">médiafájlok letöltése</translation>
+<translation id="6981594929165378967">beszúrás</translation>
+<translation id="6989848892321993519">Legalább <ph name="MIN_CHARACTERS" /> karakter hosszú szöveget adjon meg (jelenleg 1 karaktert használ).</translation>
+<translation id="7034405885550056553">javaslat</translation>
+<translation id="709897737746224366">Kérjük, tartsa magát a kívánt formátumhoz.</translation>
+<translation id="7118469954320184356">Nincs leírás.</translation>
+<translation id="7139483182332611405">bevezető</translation>
+<translation id="7214187073215825913">tartalom adatai</translation>
+<translation id="7263440858009898357">Kérjük, válasszon egyet a lista elemei közül.</translation>
+<translation id="727747134524199931">oszlopfejléc</translation>
+<translation id="7320576522385648310">pufferelés</translation>
+<translation id="7353453495576941748">elismerés</translation>
+<translation id="7364796246159120393">Fájl kiválasztása</translation>
+<translation id="739024184232394898">Más...</translation>
+<translation id="7405738980073107433">záró jegyzetek</translation>
+<translation id="7410239719251593705">Úgy tűnik, felnőtt tartalom van benne. Leírás nincs.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Letöltés</translation>
+<translation id="7529102961911894712">visszamutató link</translation>
+<translation id="7533959249147584474">Címke nélküli ábra</translation>
+<translation id="7647456547678091388">tipp</translation>
+<translation id="7661956066982048809">grafikus dokumentum</translation>
+<translation id="7673697353781729403">Óra</translation>
+<translation id="7681220483256441252">tárgymutató</translation>
+<translation id="7740050170769002709">HTML-tartalom</translation>
+<translation id="7745230546936012372">Ha hiányzó képleírásokat szeretne lekérni, nyissa meg a helyi menüt.</translation>
+<translation id="7750228210027921155">Kép a képben</translation>
+<translation id="775297008183122718">Érvénytelen bevitel</translation>
+<translation id="7789962463072032349">szüneteltetés</translation>
+<translation id="7802800022689234070">plusz tartalom kibontására szolgáló háromszög</translation>
+<translation id="7888071071722539607">Kérjük, írjon egy „<ph name="ATSIGN" />” karaktert az e-mail címbe. A(z) „<ph name="INVALIDADDRESS" />” címből hiányzik a „<ph name="ATSIGN" />” jel.</translation>
+<translation id="7891486169920085145">felosztó</translation>
+<translation id="795667975304826397">Nincs fájl kiválasztva</translation>
+<translation id="8053789581856978548">keresés a szövegmezőben</translation>
+<translation id="8057695513531652401">közlés</translation>
+<translation id="8105797009065549151">jegyzethivatkozás</translation>
+<translation id="811583516810654505">A leírás lekérdezése folyamatban van</translation>
+<translation id="8117451130807776954">Ezen a héten</translation>
+<translation id="8199524924445686405">éééé</translation>
+<translation id="8208673686607688524">helyi dátum- és időválasztó</translation>
+<translation id="8261464734335370856">Helyesírási hiba</translation>
+<translation id="8284326494547611709">Feliratok</translation>
+<translation id="8346634859695247203">szakasz</translation>
+<translation id="835897206747267392">Érvénytelen érték.</translation>
+<translation id="8403857369060869934">eltelt idő: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">rész</translation>
+<translation id="8433900881053900389">eszköztár</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fájl</translation>
+<translation id="8451268428117625855">Válasszon egy fájlt.</translation>
+<translation id="8461852803063341183">választógomb</translation>
+<translation id="8474886197722836894">ajánlás</translation>
+<translation id="8531739829932800271">hibajegyzék</translation>
+<translation id="8534579021159131403">Perc</translation>
+<translation id="8541249477527128034">médiavezérlő</translation>
+<translation id="8550857728288566671">grafikus szimbólum</translation>
+<translation id="8583702881314752957">definíciós lista</translation>
+<translation id="8597182159515967513">fejléc</translation>
+<translation id="860475260694818407">tartalomjegyzék</translation>
+<translation id="8613126697340063924">távoli lejátszás kezelése</translation>
+<translation id="862370744433916922">felirat</translation>
+<translation id="8711688047404765493">kimenet</translation>
+<translation id="8750798805984357768">Kérjük, válassza ki az egyik opciót.</translation>
+<translation id="8808573423886751634">fejezet</translation>
+<translation id="8822203815165896261">szerzői adatok</translation>
+<translation id="8845239796550121995">Átküldés a tévére folyamatban</translation>
+<translation id="8851136666856101339">fő</translation>
+<translation id="8875657656876809964">Videólejátszási hiba</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">hónap</translation>
+<translation id="901493112792887934">jelenlegi idő másodpercben</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigáció</translation>
+<translation id="9062295712474918030">dokumentum</translation>
+<translation id="9093215626363556771">kilépés a kép a képben funkcióból</translation>
+<translation id="9108370397979208512">matematika</translation>
+<translation id="9132465097189459683">Más...</translation>
+<translation id="9138385573473225930">értesítés</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />. hét (<ph name="WEEK_START_DATE" />-i dátummal kezdődik)</translation>
+<translation id="916607977885256133">Kép a képben</translation>
+<translation id="9168329111483466115">lábjegyzet</translation>
+<translation id="954003015749068518">belépés a kép a képben funkcióba</translation>
+<translation id="966787709310836684">menü</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..ab5b11e8f24
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_id.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="id">
+<translation id="1018939186200882850">item menu</translation>
+<translation id="10623998915015855">tombol</translation>
+<translation id="1088086359088493902">Detik</translation>
+<translation id="1171774979989969504">Masukkan alamat email.</translation>
+<translation id="1178581264944972037">Jeda</translation>
+<translation id="1188858454923323853">komplementer</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">penggeser</translation>
+<translation id="1211441953136645838">catatan akhir</translation>
+<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">daftar penghargaan</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">spanduk</translation>
+<translation id="1589122976691792535">wilayah</translation>
+<translation id="1591562245178063882">Bulan ini</translation>
+<translation id="1637811476055996098">Pilih File</translation>
+<translation id="1650423536718072820">pullquote</translation>
+<translation id="1727886345390570319">sembunyikan menu subtitel</translation>
+<translation id="1729654308190250600">Jangan mengosongkan bidang alamat email.</translation>
+<translation id="1758486001363313524">Lainnya...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">kisi pohon</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">putar di perangkat jarak jauh</translation>
+<translation id="190587075670221089">penghapusan</translation>
+<translation id="1907737156431278478">contoh</translation>
+<translation id="1921819250265091946">hh</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Tanggal harus <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
+<translation id="1946271899482435442">Tampilkan alat pilih tanggal</translation>
+<translation id="1993104285338243655">Dialihkan ke pencerminan</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' digunakan pada posisi yang salah di '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2158401438286456825">daftar halaman</translation>
+<translation id="2226276347425096477">Pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> karakter atau kurang (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
+<translation id="2246498165605549352">File Lokal</translation>
+<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">kotak centang</translation>
+<translation id="2311842470354187719">batas halaman</translation>
+<translation id="2335594187091864976">pemilih tanggal dan waktu</translation>
+<translation id="245932805758469625">sisa durasi video dalam detik</translation>
+<translation id="248395913932153421">Hari</translation>
+<translation id="2507943997699731163">Harap isi bidang ini.</translation>
+<translation id="2508569020611168319">daftar tab</translation>
+<translation id="2561842179657104141">tampilkan kontrol media lainnya</translation>
+<translation id="2572483411312390101">main</translation>
+<translation id="2613802280814924224">Masukkan nilai yang valid. Nilai valid terdekatnya adalah <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Kirim</translation>
+<translation id="2657045182931379222">objek grafis</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="2709516037105925701">Isi-Otomatis</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">komentar</translation>
+<translation id="2746543609216772311">Tanggal harus <ph name="MINIMUM_DATE_OR_TIME" /> atau setelahnya.</translation>
+<translation id="2759744352195237655">tombol pop-up</translation>
+<translation id="2761667185364618470">Centang kotak ini jika Anda ingin melanjutkan.</translation>
+<translation id="2844350028562914727">detail</translation>
+<translation id="2896972712917208084">grup radio</translation>
+<translation id="2908441821576996758">Masukkan daftar alamat email yang dipisahkan dengan koma.</translation>
+<translation id="2940813599313844715">objek</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Masukkan nilai yang valid. Bidang tersebut tidak lengkap atau memiliki tanggal yang tidak valid.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Masukkan URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">kotak kombo</translation>
+<translation id="3450233048674729344">Nilai harus lebih kecil atau sama dengan <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definisi</translation>
+<translation id="3557673793733683882">judul <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">pemilih minggu</translation>
+<translation id="3685101356851116974">Gambar tidak berlabel</translation>
+<translation id="3706100364254443312">saklar</translation>
+<translation id="3732799496749320381">bb</translation>
+<translation id="3754210790023674521">Keluar dari mode picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">istilah</translation>
+<translation id="3822383571486410024">Perpanjang teks ini hingga <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
+<translation id="383465348367842624">Bagian sebelum '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">Keluar dari layar penuh</translation>
+<translation id="3889183436948184105">revisi</translation>
+<translation id="3920932319529768807">kesimpulan</translation>
+<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">bilah gulir</translation>
+<translation id="4103419683916926126">Milidetik</translation>
+<translation id="4151657705144244502">grafis</translation>
+<translation id="4160057747563657758">telepon</translation>
+<translation id="4193965531860883258">kata pengantar</translation>
+<translation id="4201051445878709314">Tampilkan bulan sebelumnya</translation>
+<translation id="421884353938374759">pemilih warna</translation>
+<translation id="4248100235867064564">bilah menu</translation>
+<translation id="4360991593054037559">Masukkan nilai yang valid. Dua nilai valid terdekat adalah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Tanya Jawab</translation>
+<translation id="4413860115965805769">tombol menu</translation>
+<translation id="4444765639179266822">Muncul dengan menyatakan: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referensi glosarium</translation>
+<translation id="4522570452068850558">Detail</translation>
+<translation id="4542388879936266156">sisa waktu: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulir</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">lampiran</translation>
+<translation id="4718048029184481307">Diputar dalam mode picture-in-picture</translation>
+<translation id="4742539557769756338">sampul</translation>
+<translation id="4748357248530471599">mengalihkan ke layar penuh potongan layar</translation>
+<translation id="4757246831282535685">panel tab</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Masukkan nomor.</translation>
+<translation id="4912536737030637138">entri bibliografi</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
+<translation id="4992066212339426712">Bunyikan</translation>
+<translation id="49969490063480558">Masukkan bagian setelah '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5034860022980953847">indikator kemajuan</translation>
+<translation id="5090250355906949916">pengatur waktu video</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Tampilkan bulan berikutnya</translation>
+<translation id="512758898067543763">judul baris</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Nilai harus lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Masukkan bagian yang diikuti dengan '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5334352251556557839">Tidak dapat memutar media.</translation>
+<translation id="5406322316791861025">sosok</translation>
+<translation id="5453733299334684579">item pohon</translation>
+<translation id="5466621249238537318">Pilih salah satu atau beberapa file.</translation>
+<translation id="5468998798572797635">keluar dari tampilan layar penuh</translation>
+<translation id="5516424706154626233">pemilih tanggal</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">suarakan</translation>
+<translation id="5608153257855394627">sorotan</translation>
+<translation id="561939826962581046">waktu</translation>
+<translation id="5630795885300617244">Ketuk dua kali ke kiri atau kanan untuk melewati 10 detik</translation>
+<translation id="5631759159893697722">abstrak</translation>
+<translation id="5643186887447432888">tombol</translation>
+<translation id="5677946354068040947">opsi lainnya</translation>
+<translation id="576709008726043716">pendahuluan</translation>
+<translation id="57838592816432529">Bisukan</translation>
+<translation id="5860033963881614850">Nonaktif</translation>
+<translation id="588258955323874662">Layar Penuh</translation>
+<translation id="5888666972993069672">Sedang melakukan cast ke <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">kotak penelusuran</translation>
+<translation id="5939518447894949180">Setel ulang</translation>
+<translation id="5966707198760109579">Minggu</translation>
+<translation id="5987525920412732405">tombol putar</translation>
+<translation id="6011459053400940133">Pengatur volume</translation>
+<translation id="6015796118275082299">Tahun</translation>
+<translation id="6023896073578205740">kotak daftar</translation>
+<translation id="6150588977291308318">bibliografi</translation>
+<translation id="6164829606128959761">pengukur</translation>
+<translation id="6166809985690652833">penutup</translation>
+<translation id="6209276755895393898">Muncul sebagai: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosarium</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Keluar dari Mode Picture-in-Picture</translation>
+<translation id="6398862346408813489">Tampilkan panel pilihan bulan</translation>
+<translation id="6404546809543547843">scrubber waktu audio</translation>
+<translation id="6443871981718447451">tampilkan menu subtitel</translation>
+<translation id="6453774872122745852">ucapan terima kasih</translation>
+<translation id="6475115390776617481">kehadiran langsung</translation>
+<translation id="648732519525291180">pemilih waktu</translation>
+<translation id="6550675742724504774">Opsi</translation>
+<translation id="6572309429103589720">Tata bahasa tidak valid</translation>
+<translation id="658823671542763450">masuk layar penuh</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Hapus</translation>
+<translation id="668171684555832681">Lainnya...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Kualitas pemutaran buruk</translation>
+<translation id="6755330956360078551">keterangan alat</translation>
+<translation id="6790428901817661496">Putar</translation>
+<translation id="6820355525329141109">Tidak dapat memuat plugin.</translation>
+<translation id="6820615603175220800">referensi bibliografi</translation>
+<translation id="6843725295806269523">bisukan</translation>
+<translation id="6885760532393684712">direktori</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">header</translation>
+<translation id="6941933287844615239">download media</translation>
+<translation id="6981594929165378967">penyisipan</translation>
+<translation id="6989848892321993519">Perpanjang teks ini menjadi <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan 1 karakter).</translation>
+<translation id="7034405885550056553">saran</translation>
+<translation id="709897737746224366">Sesuaikan dengan format yang diminta.</translation>
+<translation id="7118469954320184356">Deskripsi tidak tersedia.</translation>
+<translation id="7139483182332611405">kata pengantar</translation>
+<translation id="7214187073215825913">informasi konten</translation>
+<translation id="7263440858009898357">Pilih item pada daftar.</translation>
+<translation id="727747134524199931">judul kolom</translation>
+<translation id="7320576522385648310">buffering</translation>
+<translation id="7353453495576941748">daftar penghargaan</translation>
+<translation id="7364796246159120393">Pilih File</translation>
+<translation id="739024184232394898">Lainnya...</translation>
+<translation id="7405738980073107433">catatan akhir</translation>
+<translation id="7410239719251593705">Tampaknya berisi konten khusus dewasa. Deskripsi tidak tersedia.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Download</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7533959249147584474">Grafik tidak berlabel</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">dokumen grafis</translation>
+<translation id="7673697353781729403">Jam</translation>
+<translation id="7681220483256441252">indeks</translation>
+<translation id="7740050170769002709">Konten HTML</translation>
+<translation id="7745230546936012372">Untuk mendapatkan deskripsi gambar yang tidak ada, buka menu konteks.</translation>
+<translation id="7750228210027921155">Picture-in-picture</translation>
+<translation id="775297008183122718">Entri tidak valid</translation>
+<translation id="7789962463072032349">jeda</translation>
+<translation id="7802800022689234070">segitiga pengungkapan</translation>
+<translation id="7888071071722539607">Sertakan '<ph name="ATSIGN" />' pada alamat email. '<ph name="INVALIDADDRESS" />' tidak memiliki '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">pemisah</translation>
+<translation id="795667975304826397">Tidak ada file yang dipilih</translation>
+<translation id="8053789581856978548">bidang teks penelusuran</translation>
+<translation id="8057695513531652401">pemberitahuan</translation>
+<translation id="8105797009065549151">referensi catatan</translation>
+<translation id="811583516810654505">Mendapatkan deskripsi...</translation>
+<translation id="8117451130807776954">Minggu ini</translation>
+<translation id="8199524924445686405">tttt</translation>
+<translation id="8208673686607688524">pemilih tanggal dan waktu lokal</translation>
+<translation id="8261464734335370856">Ejaan tidak valid</translation>
+<translation id="8284326494547611709">Teks</translation>
+<translation id="8346634859695247203">bagian</translation>
+<translation id="835897206747267392">Nilai tidak valid.</translation>
+<translation id="8403857369060869934">waktu berlalu: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">bagian</translation>
+<translation id="8433900881053900389">bilah alat</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
+<translation id="8451268428117625855">Pilih file.</translation>
+<translation id="8461852803063341183">tombol radio</translation>
+<translation id="8474886197722836894">persembahan</translation>
+<translation id="8531739829932800271">erratum</translation>
+<translation id="8534579021159131403">Menit</translation>
+<translation id="8541249477527128034">kontrol media</translation>
+<translation id="8550857728288566671">simbol grafis</translation>
+<translation id="8583702881314752957">daftar definisi</translation>
+<translation id="8597182159515967513">kepala</translation>
+<translation id="860475260694818407">daftar isi</translation>
+<translation id="8613126697340063924">kontrol pemutaran jarak jauh</translation>
+<translation id="862370744433916922">subjudul</translation>
+<translation id="8711688047404765493">keluaran</translation>
+<translation id="8750798805984357768">Pilih salah satu opsi berikut.</translation>
+<translation id="8808573423886751634">bab</translation>
+<translation id="8822203815165896261">info pembuatan</translation>
+<translation id="8845239796550121995">Sekarang sedang mentransmisi ke TV Anda</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Error pemutaran video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Bulan</translation>
+<translation id="901493112792887934">waktu saat ini dalam detik</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">navigasi</translation>
+<translation id="9062295712474918030">dokumen</translation>
+<translation id="9093215626363556771">keluar dari mode picture-in-picture</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Lainnya...</translation>
+<translation id="9138385573473225930">notifikasi</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, dimulai pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture-in-Picture</translation>
+<translation id="9168329111483466115">catatan kaki</translation>
+<translation id="954003015749068518">masuk mode picture-in-picture</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..18c81222c29
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_it.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="it">
+<translation id="1018939186200882850">voce di menu</translation>
+<translation id="10623998915015855">pulsante di attivazione/disattivazione</translation>
+<translation id="1088086359088493902">Secondi</translation>
+<translation id="1171774979989969504">Inserisci un indirizzo email.</translation>
+<translation id="1178581264944972037">Pausa</translation>
+<translation id="1188858454923323853">elementi complementari</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">dispositivo di scorrimento</translation>
+<translation id="1211441953136645838">nota finale</translation>
+<translation id="1281252709823657822">finestra di dialogo</translation>
+<translation id="1335095011850992622">ringraziamenti</translation>
+<translation id="1342835525016946179">articolo</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">regione</translation>
+<translation id="1591562245178063882">Questo mese</translation>
+<translation id="1637811476055996098">Scegli file</translation>
+<translation id="1650423536718072820">citazione</translation>
+<translation id="1727886345390570319">nascondi menu sottotitoli</translation>
+<translation id="1729654308190250600">Inserisci un indirizzo email valido.</translation>
+<translation id="1758486001363313524">Altro...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">griglia ad albero</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">riproduci su dispositivo remoto</translation>
+<translation id="190587075670221089">eliminazione</translation>
+<translation id="1907737156431278478">esempio</translation>
+<translation id="1921819250265091946">gg</translation>
+<translation id="1930711995431081526">stato</translation>
+<translation id="1938124657309484470">Il valore deve essere <ph name="MAXIMUM_DATE_OR_TIME" /> o precedente.</translation>
+<translation id="1946271899482435442">Mostra selettore date</translation>
+<translation id="1993104285338243655">Sei passato a mirroring</translation>
+<translation id="2060505056492490888">Il segno "<ph name="DOT" />" è utilizzato in una posizione errata in "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Oggi</translation>
+<translation id="2158401438286456825">elenco pagine</translation>
+<translation id="2226276347425096477">Riduci questo testo a <ph name="MAX_CHARACTERS" /> caratteri o meno (attualmente stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
+<translation id="2246498165605549352">File locale</translation>
+<translation id="2247351761944213033">Settimana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Traccia <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">casella di controllo</translation>
+<translation id="2311842470354187719">interruzione di pagina</translation>
+<translation id="2335594187091864976">selettore di data e ora</translation>
+<translation id="245932805758469625">numero di secondi di video rimanenti</translation>
+<translation id="248395913932153421">Giorno</translation>
+<translation id="2507943997699731163">Compila questo campo.</translation>
+<translation id="2508569020611168319">elenco schede</translation>
+<translation id="2561842179657104141">mostra altri controlli multimediali</translation>
+<translation id="2572483411312390101">riproduci</translation>
+<translation id="2613802280814924224">Inserisci un valore valido. Il valore valido più vicino è <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Invia</translation>
+<translation id="2657045182931379222">oggetto grafico</translation>
+<translation id="2674318244760992338">piè di pagina</translation>
+<translation id="2709516037105925701">Compilazione automatica</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">commenti</translation>
+<translation id="2746543609216772311">Il valore deve essere <ph name="MINIMUM_DATE_OR_TIME" /> o successivo.</translation>
+<translation id="2759744352195237655">pulsante popup</translation>
+<translation id="2761667185364618470">Seleziona questa casella se intendi procedere.</translation>
+<translation id="2844350028562914727">dettagli</translation>
+<translation id="2896972712917208084">gruppo pulsanti di opzione</translation>
+<translation id="2908441821576996758">Inserisci un elenco di indirizzi email separati da virgola.</translation>
+<translation id="2940813599313844715">oggetto</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Inserisci un valore valido. Il campo è incompleto o presenta una data non valida.</translation>
+<translation id="3078740164268491126">tabella</translation>
+<translation id="3086746722712840547">nota</translation>
+<translation id="310520048233152454">Inserisci un URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">casella combinata</translation>
+<translation id="3450233048674729344">Il valore deve essere inferiore o uguale a <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definizione</translation>
+<translation id="3557673793733683882">intestazione <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selettore della settimana</translation>
+<translation id="3685101356851116974">immagine senza etichetta</translation>
+<translation id="3706100364254443312">strumento per il passaggio ad altri elementi</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Esci da Picture in picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termine</translation>
+<translation id="3822383571486410024">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
+<translation id="383465348367842624">Una parte seguita da "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Esci da schermo intero</translation>
+<translation id="3889183436948184105">revisione</translation>
+<translation id="3920932319529768807">conclusioni</translation>
+<translation id="3924558731517983934">applicazione</translation>
+<translation id="3944740393230681990">prologo</translation>
+<translation id="3960700977367013758">barra di scorrimento</translation>
+<translation id="4103419683916926126">Millisecondi</translation>
+<translation id="4151657705144244502">immagine</translation>
+<translation id="4160057747563657758">telefono</translation>
+<translation id="4193965531860883258">premessa</translation>
+<translation id="4201051445878709314">Mostra mese precedente</translation>
+<translation id="421884353938374759">selettore colori</translation>
+<translation id="4248100235867064564">barra dei menu</translation>
+<translation id="4360991593054037559">Inserisci un valore valido. I due valori validi più vicini sono <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Domande e risposte</translation>
+<translation id="4413860115965805769">pulsante di menu</translation>
+<translation id="4444765639179266822">Sembra che dica: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">riferimento glossario</translation>
+<translation id="4522570452068850558">Dettagli</translation>
+<translation id="4542388879936266156">Tempo rimanente: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">modulo</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Una parte che segue "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">appendice</translation>
+<translation id="4718048029184481307">Riproduzione in modalità Picture in picture</translation>
+<translation id="4742539557769756338">copertina</translation>
+<translation id="4748357248530471599">attiva/disattiva lo schermo intero tagliato dalla visualizzazione</translation>
+<translation id="4757246831282535685">riquadro a schede</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">ricerca</translation>
+<translation id="4812940957355064477">Inserisci un numero.</translation>
+<translation id="4912536737030637138">voce bibliografica</translation>
+<translation id="4975562563186953947">Elementi selezionati: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Riattiva audio</translation>
+<translation id="49969490063480558">Inserisci una parte dopo "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
+<translation id="5034860022980953847">indicatore di avanzamento</translation>
+<translation id="5090250355906949916">dispositivo di scorrimento durata video</translation>
+<translation id="5093189678851173835">epigrafe</translation>
+<translation id="5117590920725113268">Mostra mese successivo</translation>
+<translation id="512758898067543763">intestazione di riga</translation>
+<translation id="5143125788380636750">epilogo</translation>
+<translation id="5164977714490026579">Il valore deve essere superiore o uguale a <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Inserisci una parte seguita da "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
+<translation id="5334352251556557839">Impossibile riprodurre i contenuti multimediali.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">elemento albero</translation>
+<translation id="5466621249238537318">Seleziona uno o più file.</translation>
+<translation id="5468998798572797635">esci da schermo intero</translation>
+<translation id="5516424706154626233">selettore di data</translation>
+<translation id="5537725057119320332">Trasmetti</translation>
+<translation id="5546461542133609677">riattiva audio</translation>
+<translation id="5608153257855394627">evidenzia</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Tocca due volte a sinistra o destra per saltare di 10 secondi</translation>
+<translation id="5631759159893697722">abstract</translation>
+<translation id="5643186887447432888">pulsante</translation>
+<translation id="5677946354068040947">altre opzioni</translation>
+<translation id="576709008726043716">introduzione</translation>
+<translation id="57838592816432529">Disattiva audio</translation>
+<translation id="5860033963881614850">OFF</translation>
+<translation id="588258955323874662">Schermo intero</translation>
+<translation id="5888666972993069672">Trasmissione in corso a <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">casella di ricerca</translation>
+<translation id="5939518447894949180">Reimposta</translation>
+<translation id="5966707198760109579">Settimana</translation>
+<translation id="5987525920412732405">pulsante di selezione</translation>
+<translation id="6011459053400940133">dispositivo di scorrimento del volume</translation>
+<translation id="6015796118275082299">Anno</translation>
+<translation id="6023896073578205740">casella di riepilogo</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">indicatore</translation>
+<translation id="6166809985690652833">postfazione</translation>
+<translation id="6209276755895393898">Sembra che sia: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossario</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Esci da Picture in picture</translation>
+<translation id="6398862346408813489">Mostra il riquadro di selezione del mese</translation>
+<translation id="6404546809543547843">dispositivo di scorrimento durata audio</translation>
+<translation id="6443871981718447451">mostra menu sottotitoli</translation>
+<translation id="6453774872122745852">riconoscimenti</translation>
+<translation id="6475115390776617481">presenza dal vivo</translation>
+<translation id="648732519525291180">selettore di ora</translation>
+<translation id="6550675742724504774">Opzioni</translation>
+<translation id="6572309429103589720">Grammatica non valida</translation>
+<translation id="658823671542763450">passa a schermo intero</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Cancella</translation>
+<translation id="668171684555832681">Altro...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Scarsa qualità di riproduzione</translation>
+<translation id="6755330956360078551">descrizione comando</translation>
+<translation id="6790428901817661496">Play</translation>
+<translation id="6820355525329141109">Impossibile caricare il plug-in</translation>
+<translation id="6820615603175220800">riferimento bibliografico</translation>
+<translation id="6843725295806269523">disattiva audio</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colophon</translation>
+<translation id="6934078000481955284">citazione lunga</translation>
+<translation id="693476918119313863">intestazione</translation>
+<translation id="6941933287844615239">scarica contenuti multimediali</translation>
+<translation id="6981594929165378967">inserimento</translation>
+<translation id="6989848892321993519">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando 1 carattere).</translation>
+<translation id="7034405885550056553">suggerimento</translation>
+<translation id="709897737746224366">Rispetta il formato richiesto.</translation>
+<translation id="7118469954320184356">Descrizione non disponibile.</translation>
+<translation id="7139483182332611405">prefazione</translation>
+<translation id="7214187073215825913">informazioni sui contenuti</translation>
+<translation id="7263440858009898357">Seleziona un elemento nell'elenco.</translation>
+<translation id="727747134524199931">intestazione di colonna</translation>
+<translation id="7320576522385648310">Buffering</translation>
+<translation id="7353453495576941748">ringraziamento</translation>
+<translation id="7364796246159120393">Scegli file</translation>
+<translation id="739024184232394898">Altro...</translation>
+<translation id="7405738980073107433">note finali</translation>
+<translation id="7410239719251593705">Sembra essere contenuto per adulti. Descrizione non disponibile.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">Tab</translation>
+<translation id="7514365320538308">Scarica</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7533959249147584474">Immagine senza etichetta</translation>
+<translation id="7647456547678091388">suggerimento</translation>
+<translation id="7661956066982048809">documento grafico</translation>
+<translation id="7673697353781729403">Orario</translation>
+<translation id="7681220483256441252">indice</translation>
+<translation id="7740050170769002709">Contenuti HTML</translation>
+<translation id="7745230546936012372">Per accedere alle descrizioni mancanti delle immagini, apri il menu contestuale.</translation>
+<translation id="7750228210027921155">Picture in picture</translation>
+<translation id="775297008183122718">Valore non valido</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triangolo descrittivo</translation>
+<translation id="7888071071722539607">Aggiungi un simbolo "<ph name="ATSIGN" />" nell'indirizzo email. In "<ph name="INVALIDADDRESS" />" manca un simbolo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">barra di divisione</translation>
+<translation id="795667975304826397">Nessun file selezionato</translation>
+<translation id="8053789581856978548">campo di testo della ricerca</translation>
+<translation id="8057695513531652401">informativa</translation>
+<translation id="8105797009065549151">riferimento note</translation>
+<translation id="811583516810654505">Recupero descrizione…</translation>
+<translation id="8117451130807776954">Questa settimana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selettore di data e ora locali</translation>
+<translation id="8261464734335370856">Ortografia non valida</translation>
+<translation id="8284326494547611709">Sottotitoli</translation>
+<translation id="8346634859695247203">sezione</translation>
+<translation id="835897206747267392">Valore non valido.</translation>
+<translation id="8403857369060869934">Tempo trascorso: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">barra degli strumenti</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
+<translation id="8451268428117625855">Seleziona un file.</translation>
+<translation id="8461852803063341183">pulsante di opzione</translation>
+<translation id="8474886197722836894">dedica</translation>
+<translation id="8531739829932800271">errata corrige</translation>
+<translation id="8534579021159131403">Minuti</translation>
+<translation id="8541249477527128034">controllo contenuti multimediali</translation>
+<translation id="8550857728288566671">simbolo grafico</translation>
+<translation id="8583702881314752957">elenco di definizioni</translation>
+<translation id="8597182159515967513">intestazione</translation>
+<translation id="860475260694818407">sommario</translation>
+<translation id="8613126697340063924">gestisci riproduzione remota</translation>
+<translation id="862370744433916922">sottotitolo</translation>
+<translation id="8711688047404765493">uscita</translation>
+<translation id="8750798805984357768">Seleziona una di queste opzioni.</translation>
+<translation id="8808573423886751634">capitolo</translation>
+<translation id="8822203815165896261">informazioni creazione</translation>
+<translation id="8845239796550121995">Ora in fase di trasmissione alla TV</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Errore di riproduzione video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Mese</translation>
+<translation id="901493112792887934">tempo attuale in secondi</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">navigazione</translation>
+<translation id="9062295712474918030">documento</translation>
+<translation id="9093215626363556771">esci da picture in picture</translation>
+<translation id="9108370397979208512">elemento matematico</translation>
+<translation id="9132465097189459683">Altro...</translation>
+<translation id="9138385573473225930">avviso</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, a partire dal giorno <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture in picture</translation>
+<translation id="9168329111483466115">piè di pagina</translation>
+<translation id="954003015749068518">attiva picture in picture</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..7ea1bd339b8
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_iw.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="iw">
+<translation id="1018939186200882850">פריט בתפריט</translation>
+<translation id="10623998915015855">לחצן החלפה</translation>
+<translation id="1088086359088493902">שניות</translation>
+<translation id="1171774979989969504">הזן כתובת אימייל.</translation>
+<translation id="1178581264944972037">השהה</translation>
+<translation id="1188858454923323853">משלים</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">מחוון</translation>
+<translation id="1211441953136645838">הערת סיום</translation>
+<translation id="1281252709823657822">דו-שיח</translation>
+<translation id="1335095011850992622">קרדיטים</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">מודעת באנר</translation>
+<translation id="1589122976691792535">אזור</translation>
+<translation id="1591562245178063882">החודש</translation>
+<translation id="1637811476055996098">בחר קבצים</translation>
+<translation id="1650423536718072820">ציטוט</translation>
+<translation id="1727886345390570319">הסתרה של תפריט הכתוביות</translation>
+<translation id="1729654308190250600">הזן ערך נדרש בשדה של כתובת האימייל.</translation>
+<translation id="1758486001363313524">אחר...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">רשת של עץ</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">הפעלה במכשיר מרוחק</translation>
+<translation id="190587075670221089">מחיקה</translation>
+<translation id="1907737156431278478">דוגמה</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">מצב</translation>
+<translation id="1938124657309484470">על הערך להיות <ph name="MAXIMUM_DATE_OR_TIME" /> או מוקדם יותר.</translation>
+<translation id="1946271899482435442">הצגת בוחר התאריכים</translation>
+<translation id="1993104285338243655">הועבר לשיקוף מסך</translation>
+<translation id="2060505056492490888">נעשה שימוש ב-'<ph name="DOT" />' במיקום שגוי ב-'<ph name="INVALIDDOMAIN" />'.</translation>
+<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="2247351761944213033">שבוע <ph name="WEEKNUMBER" />‏, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">רצועה <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">תיבת סימון</translation>
+<translation id="2311842470354187719">מעבר דף</translation>
+<translation id="2335594187091864976">בוחר תאריך ושעה</translation>
+<translation id="245932805758469625">מספר השניות שנותרו עד לסיום הסרטון</translation>
+<translation id="248395913932153421">יום</translation>
+<translation id="2507943997699731163">זהו שדה חובה.</translation>
+<translation id="2508569020611168319">רשימת כרטיסיות</translation>
+<translation id="2561842179657104141">הצג עוד פקדי מדיה</translation>
+<translation id="2572483411312390101">הפעל</translation>
+<translation id="2613802280814924224">הזן ערך חוקי. הערך החוקי הקרוב ביותר הוא <ph name="VALID_VALUE" /></translation>
+<translation id="2653659639078652383">שלח</translation>
+<translation id="2657045182931379222">אובייקט גרפי</translation>
+<translation id="2674318244760992338">כותרת תחתונה</translation>
+<translation id="2709516037105925701">מילוי אוטומטי</translation>
+<translation id="2723001399770238859">אודיו</translation>
+<translation id="2725963129578236554">תגובות</translation>
+<translation id="2746543609216772311">על הערך להיות <ph name="MINIMUM_DATE_OR_TIME" /> ומעלה.</translation>
+<translation id="2759744352195237655">לחצן קופץ</translation>
+<translation id="2761667185364618470">סמן תיבה זו אם אתה רוצה להמשיך.</translation>
+<translation id="2844350028562914727">פרטים</translation>
+<translation id="2896972712917208084">קבוצת לחצני בחירה</translation>
+<translation id="2908441821576996758">הזן רשימה של כתובות אימייל המופרדות באמצעות פסיקים.</translation>
+<translation id="2940813599313844715">אובייקט</translation>
+<translation id="3040011195152428237">קישור</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">הזן ערך חוקי. השדה ריק או שהוא מכיל תאריך לא חוקי.</translation>
+<translation id="3078740164268491126">טבלה</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">הזן כתובת אתר.</translation>
+<translation id="3175736971608411871">טיימר</translation>
+<translation id="3199563858620722075">תיבה משולבת</translation>
+<translation id="3450233048674729344">הערך חייב להיות קטן מ-<ph name="MAXIMUM" /> או שווה לו.</translation>
+<translation id="3486220673238053218">הגדרה</translation>
+<translation id="3557673793733683882">כותרת <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">בורר השבועות</translation>
+<translation id="3685101356851116974">תמונה ללא תיאור</translation>
+<translation id="3706100364254443312">מעבר</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">יציאה ממצב תמונה בתוך תמונה</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">מונח</translation>
+<translation id="3822383571486410024">הארך טקסט זה ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
+<translation id="383465348367842624">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">צא ממסך מלא</translation>
+<translation id="3889183436948184105">תיקון</translation>
+<translation id="3920932319529768807">סיכום</translation>
+<translation id="3924558731517983934">יישום</translation>
+<translation id="3944740393230681990">פרולוג</translation>
+<translation id="3960700977367013758">סרגל גלילה</translation>
+<translation id="4103419683916926126">אלפיות שנייה</translation>
+<translation id="4151657705144244502">פריט גרפי</translation>
+<translation id="4160057747563657758">טלפון</translation>
+<translation id="4193965531860883258">פתח דבר</translation>
+<translation id="4201051445878709314">הצג חודש קודם</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">שורת תפריטים</translation>
+<translation id="4360991593054037559">הזן ערך חוקי. שני הערכים החוקיים הקרובים ביותר הם <ph name="VALID_VALUE_LOW" /> ו-<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">שאלות ותשובות</translation>
+<translation id="4413860115965805769">לחצן תפריט</translation>
+<translation id="4444765639179266822">נראה שכתובים כאן הדברים הבאים: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">הפניה למילון מונחים</translation>
+<translation id="4522570452068850558">פרטים</translation>
+<translation id="4542388879936266156">הזמן שנותר: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">טופס</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">נספח</translation>
+<translation id="4718048029184481307">הפעלה במצב תמונה בתוך תמונה</translation>
+<translation id="4742539557769756338">שער</translation>
+<translation id="4748357248530471599">מעבר מתצוגה באזור המגרעת של המסך למסך מלא</translation>
+<translation id="4757246831282535685">חלונית כרטיסיות</translation>
+<translation id="4763480195061959176">סרטוני וידאו</translation>
+<translation id="479989351350248267">Search</translation>
+<translation id="4812940957355064477">יש להזין מספר.</translation>
+<translation id="4912536737030637138">ערך ביבליוגרפי</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> נבחרו</translation>
+<translation id="4992066212339426712">בטל השתקה</translation>
+<translation id="49969490063480558">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
+<translation id="5034860022980953847">סימן ויזואלי להתקדמות</translation>
+<translation id="5090250355906949916">מחוון זמן הסרטון</translation>
+<translation id="5093189678851173835">ציטוט בראש ספר</translation>
+<translation id="5117590920725113268">הצג את החודש הבא</translation>
+<translation id="512758898067543763">כותרת שורה</translation>
+<translation id="5143125788380636750">אפילוג</translation>
+<translation id="5164977714490026579">הערך חייב להיות גדול מ-<ph name="MINIMUM" /> או שווה לו.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
+<translation id="5334352251556557839">לא ניתן להפעיל את המדיה.</translation>
+<translation id="5406322316791861025">ספרה</translation>
+<translation id="5453733299334684579">פריט בעץ</translation>
+<translation id="5466621249238537318">בחר קובץ אחד או יותר.</translation>
+<translation id="5468998798572797635">צא ממסך מלא</translation>
+<translation id="5516424706154626233">בוחר תאריכים</translation>
+<translation id="5537725057119320332">העברה</translation>
+<translation id="5546461542133609677">בטל השתקה</translation>
+<translation id="5608153257855394627">הדגשה</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">הקשה כפולה בצד ימין או שמאל מדלגת על 10 שניות</translation>
+<translation id="5631759159893697722">תקציר</translation>
+<translation id="5643186887447432888">לחצן</translation>
+<translation id="5677946354068040947">אפשרויות נוספות</translation>
+<translation id="576709008726043716">מבוא</translation>
+<translation id="57838592816432529">השתקה</translation>
+<translation id="5860033963881614850">כבוי</translation>
+<translation id="588258955323874662">מסך מלא</translation>
+<translation id="5888666972993069672">מתבצעת העברה אל <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">תיבת חיפוש</translation>
+<translation id="5939518447894949180">אפס</translation>
+<translation id="5966707198760109579">שבוע</translation>
+<translation id="5987525920412732405">לחצן קביעת ערך</translation>
+<translation id="6011459053400940133">מחוון עוצמת קול</translation>
+<translation id="6015796118275082299">שנה</translation>
+<translation id="6023896073578205740">תיבת רשימה</translation>
+<translation id="6150588977291308318">ביבליוגרפיה</translation>
+<translation id="6164829606128959761">מד</translation>
+<translation id="6166809985690652833">אחרית דבר</translation>
+<translation id="6209276755895393898">נראה כמו: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">מילון מונחים</translation>
+<translation id="6281763101136022427">‏כתובת URL</translation>
+<translation id="6310801910862476708">יציאה ממצב 'תמונה בתוך תמונה'</translation>
+<translation id="6398862346408813489">הצג חלונית לבחירת חודש</translation>
+<translation id="6404546809543547843">מסתיר משך אודיו</translation>
+<translation id="6443871981718447451">הצגת תפריט כתוביות</translation>
+<translation id="6453774872122745852">תודות</translation>
+<translation id="6475115390776617481">עובד/ת על התוכן הזה</translation>
+<translation id="648732519525291180">בוחר שעות</translation>
+<translation id="6550675742724504774">אפשרויות</translation>
+<translation id="6572309429103589720">דקדוק שגוי</translation>
+<translation id="658823671542763450">היכנס למסך מלא</translation>
+<translation id="663493177488814956">פיד</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">ניקוי</translation>
+<translation id="668171684555832681">אחר...</translation>
+<translation id="6692633176391053278">פקד חצים</translation>
+<translation id="6709570249143506788">איכות הפעלה נמוכה</translation>
+<translation id="6755330956360078551">הסבר קצר</translation>
+<translation id="6790428901817661496">הפעל</translation>
+<translation id="6820355525329141109">לא ניתן היה לטעון את הפלאגין.</translation>
+<translation id="6820615603175220800">הפניה לביבליוגרפיה</translation>
+<translation id="6843725295806269523">השתקה</translation>
+<translation id="6885760532393684712">ספריה</translation>
+<translation id="689129560213475294">קולופון</translation>
+<translation id="6934078000481955284">‏רכיב blockquote</translation>
+<translation id="693476918119313863">כותרת</translation>
+<translation id="6941933287844615239">הורד מדיה</translation>
+<translation id="6981594929165378967">הוספה</translation>
+<translation id="6989848892321993519">עליך להאריך את הטקסט ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע בתו אחד).</translation>
+<translation id="7034405885550056553">הצעה</translation>
+<translation id="709897737746224366">התאם את הפורמט המבוקש.</translation>
+<translation id="7118469954320184356">אין תיאור זמין.</translation>
+<translation id="7139483182332611405">הקדמה</translation>
+<translation id="7214187073215825913">פרטי תוכן</translation>
+<translation id="7263440858009898357">בחר פריט מהרשימה.</translation>
+<translation id="727747134524199931">כותרת עמודה</translation>
+<translation id="7320576522385648310">אגירה</translation>
+<translation id="7353453495576941748">קרדיט</translation>
+<translation id="7364796246159120393">בחירת קובץ</translation>
+<translation id="739024184232394898">אחר...</translation>
+<translation id="7405738980073107433">הערות סיום</translation>
+<translation id="7410239719251593705">נראה שהתמונה כוללת תוכן למבוגרים בלבד. אין תיאור זמין.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">הורדה</translation>
+<translation id="7529102961911894712">קישור לאחור</translation>
+<translation id="7533959249147584474">גרפיקה ללא תיאור</translation>
+<translation id="7647456547678091388">טיפ</translation>
+<translation id="7661956066982048809">מסמך גרפי</translation>
+<translation id="7673697353781729403">שעות</translation>
+<translation id="7681220483256441252">אינדקס</translation>
+<translation id="7740050170769002709">‏תוכן HTML</translation>
+<translation id="7745230546936012372">כדי לקבל תיאורים חסרים של תמונות, יש לפתוח את תפריט ההקשר.</translation>
+<translation id="7750228210027921155">תמונה בתוך תמונה</translation>
+<translation id="775297008183122718">ערך לא חוקי</translation>
+<translation id="7789962463072032349">השהה</translation>
+<translation id="7802800022689234070">משולש הצגה/הסתרה</translation>
+<translation id="7888071071722539607">כלול '<ph name="ATSIGN" />' בכתובת האימייל. ב-'<ph name="INVALIDADDRESS" />' חסר '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">מפצל</translation>
+<translation id="795667975304826397">לא נבחר קובץ</translation>
+<translation id="8053789581856978548">שדה טקסט לחיפוש</translation>
+<translation id="8057695513531652401">הודעה</translation>
+<translation id="8105797009065549151">הפניה להערה</translation>
+<translation id="811583516810654505">התיאור עוד מעט מוכן…</translation>
+<translation id="8117451130807776954">השבוע</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">בורר תאריך ושעה מקומיים</translation>
+<translation id="8261464734335370856">איות שגוי</translation>
+<translation id="8284326494547611709">כתוביות</translation>
+<translation id="8346634859695247203">קטע</translation>
+<translation id="835897206747267392">ערך לא חוקי.</translation>
+<translation id="8403857369060869934">הזמן שחלף: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">חלק</translation>
+<translation id="8433900881053900389">סרגל כלים</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> קבצים</translation>
+<translation id="8451268428117625855">בחר קובץ.</translation>
+<translation id="8461852803063341183">לחצן בחירה</translation>
+<translation id="8474886197722836894">הקדשה</translation>
+<translation id="8531739829932800271">שגיאת דפוס</translation>
+<translation id="8534579021159131403">דקות</translation>
+<translation id="8541249477527128034">שליטה במדיה</translation>
+<translation id="8550857728288566671">סמל גרפי</translation>
+<translation id="8583702881314752957">רשימת הגדרות</translation>
+<translation id="8597182159515967513">כותרת</translation>
+<translation id="860475260694818407">תוכן העניינים</translation>
+<translation id="8613126697340063924">שליטה בהפעלה מרחוק</translation>
+<translation id="862370744433916922">כותרת משנה</translation>
+<translation id="8711688047404765493">פלט</translation>
+<translation id="8750798805984357768">בחר אחת מהאפשרויות הבאות.</translation>
+<translation id="8808573423886751634">פרק</translation>
+<translation id="8822203815165896261">פרטי המחבר</translation>
+<translation id="8845239796550121995">מעביר תוכן לטלוויזיה</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">שגיאה בהפעלת הסרטון</translation>
+<translation id="8901569739625249689">‏<ph name="QUANTITY" /> KB‏</translation>
+<translation id="8987927404178983737">חודש</translation>
+<translation id="901493112792887934">זמן נוכחי בשניות</translation>
+<translation id="901834265349196618">אימייל</translation>
+<translation id="9048119486235211610">ניווט</translation>
+<translation id="9062295712474918030">מסמך</translation>
+<translation id="9093215626363556771">יציאה ממצב 'תמונה בתוך תמונה'</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">אחר...</translation>
+<translation id="9138385573473225930">התראה</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, שמתחיל בתאריך <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">תמונה בתוך תמונה</translation>
+<translation id="9168329111483466115">הערת שוליים</translation>
+<translation id="954003015749068518">מעבר אל מצב 'תמונה בתוך תמונה'</translation>
+<translation id="966787709310836684">תפריט</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..6c7ec9def07
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ja.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ja">
+<translation id="1018939186200882850">メニュー項目</translation>
+<translation id="10623998915015855">切り替えボタン</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="1171774979989969504">メール アドレスを入力してください。</translation>
+<translation id="1178581264944972037">一時停止</translation>
+<translation id="1188858454923323853">捕捉</translation>
+<translation id="1206619573307042055">マーキー</translation>
+<translation id="1206693055195146388">スライダ</translation>
+<translation id="1211441953136645838">巻末注</translation>
+<translation id="1281252709823657822">ダイアログ</translation>
+<translation id="1335095011850992622">クレジット</translation>
+<translation id="1342835525016946179">記事</translation>
+<translation id="1359897965706325498">バナー</translation>
+<translation id="1589122976691792535">地域</translation>
+<translation id="1591562245178063882">今月</translation>
+<translation id="1637811476055996098">ファイル選択</translation>
+<translation id="1650423536718072820">引用</translation>
+<translation id="1727886345390570319">字幕メニューを表示しない</translation>
+<translation id="1729654308190250600">メール アドレスを入力してください。</translation>
+<translation id="1758486001363313524">その他...</translation>
+<translation id="1806710327868736751">アラート ダイアログ</translation>
+<translation id="1821985195704844674">ツリーグリッド</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">リモート デバイスで再生</translation>
+<translation id="190587075670221089">削除</translation>
+<translation id="1907737156431278478">例</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="1930711995431081526">ステータス</translation>
+<translation id="1938124657309484470"><ph name="MAXIMUM_DATE_OR_TIME" /> 以前の値を指定する必要があります。</translation>
+<translation id="1946271899482435442">日付選択ツールを表示</translation>
+<translation id="1993104285338243655">ミラーリングに切り替わりました</translation>
+<translation id="2060505056492490888">「<ph name="INVALIDDOMAIN" />」内の「<ph name="DOT" />」の位置が間違っています。</translation>
+<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="2247351761944213033"><ph name="YEAR" />年第<ph name="WEEKNUMBER" />週</translation>
+<translation id="2277199496770840904">トラック <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">チェックボックス</translation>
+<translation id="2311842470354187719">改ページ</translation>
+<translation id="2335594187091864976">日時選択ツール</translation>
+<translation id="245932805758469625">残りの再生時間(秒)</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="2507943997699731163">このフィールドを入力してください。</translation>
+<translation id="2508569020611168319">タブリスト</translation>
+<translation id="2561842179657104141">その他のメディア コントロールを表示</translation>
+<translation id="2572483411312390101">再生</translation>
+<translation id="2613802280814924224">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE" /> です。</translation>
+<translation id="2653659639078652383">送信</translation>
+<translation id="2657045182931379222">図形オブジェクト</translation>
+<translation id="2674318244760992338">フッター</translation>
+<translation id="2709516037105925701">自動入力</translation>
+<translation id="2723001399770238859">音声</translation>
+<translation id="2725963129578236554">コメント</translation>
+<translation id="2746543609216772311"><ph name="MINIMUM_DATE_OR_TIME" /> 以降の値を指定する必要があります。</translation>
+<translation id="2759744352195237655">ポップアップ ボタン</translation>
+<translation id="2761667185364618470">次に進むにはこのチェックボックスをオンにしてください。</translation>
+<translation id="2844350028562914727">詳細</translation>
+<translation id="2896972712917208084">ラジオボタン グループ</translation>
+<translation id="2908441821576996758">メール アドレスのカンマ区切りリストを入力してください。</translation>
+<translation id="2940813599313844715">オブジェクト</translation>
+<translation id="3040011195152428237">リンク</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">有効な値を入力してください。フィールドの入力が不完全か、日付が無効です。</translation>
+<translation id="3078740164268491126">表</translation>
+<translation id="3086746722712840547">注記</translation>
+<translation id="310520048233152454">URL を入力してください。</translation>
+<translation id="3175736971608411871">タイマー</translation>
+<translation id="3199563858620722075">コンボボックス</translation>
+<translation id="3450233048674729344">値は <ph name="MAXIMUM" /> 以下にする必要があります。</translation>
+<translation id="3486220673238053218">定義</translation>
+<translation id="3557673793733683882">見出し <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">週選択ツール</translation>
+<translation id="3685101356851116974">ラベルのない画像</translation>
+<translation id="3706100364254443312">切り替え</translation>
+<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">ピクチャー イン ピクチャーを終了</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">用語</translation>
+<translation id="3822383571486410024">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在は <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
+<translation id="383465348367842624">「<ph name="ATSIGN" />」の前の文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
+<translation id="3846214748874656680">全画面表示を終了</translation>
+<translation id="3889183436948184105">変更履歴</translation>
+<translation id="3920932319529768807">まとめ</translation>
+<translation id="3924558731517983934">アプリケーション</translation>
+<translation id="3944740393230681990">プロローグ</translation>
+<translation id="3960700977367013758">スクロールバー</translation>
+<translation id="4103419683916926126">ミリ秒</translation>
+<translation id="4151657705144244502">グラフィック</translation>
+<translation id="4160057747563657758">電話</translation>
+<translation id="4193965531860883258">前書き</translation>
+<translation id="4201051445878709314">前の月を表示</translation>
+<translation id="421884353938374759">カラー選択ツール</translation>
+<translation id="4248100235867064564">メニューバー</translation>
+<translation id="4360991593054037559">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE_LOW" /> と <ph name="VALID_VALUE_HIGHER" /> です。</translation>
+<translation id="4384583879834880242">Q&A</translation>
+<translation id="4413860115965805769">メニューボタン</translation>
+<translation id="4444765639179266822"><ph name="OCR_TEXT" /> というテキストのようです</translation>
+<translation id="4446524499724042288">用語参照</translation>
+<translation id="4522570452068850558">詳細</translation>
+<translation id="4542388879936266156">残り時間: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">フォーム</translation>
+<translation id="4661075872484491155">ツリー</translation>
+<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
+<translation id="4668956016107839909">付録</translation>
+<translation id="4718048029184481307">ピクチャー イン ピクチャーを再生しています</translation>
+<translation id="4742539557769756338">表紙</translation>
+<translation id="4748357248530471599">ディスプレイ カットアウトに合わせた全画面表示に切り替えます</translation>
+<translation id="4757246831282535685">タブパネル</translation>
+<translation id="4763480195061959176">動画</translation>
+<translation id="479989351350248267">検索</translation>
+<translation id="4812940957355064477">数字を入力してください。</translation>
+<translation id="4912536737030637138">文献情報</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> 件選択</translation>
+<translation id="4992066212339426712">ミュートを解除</translation>
+<translation id="49969490063480558">「<ph name="INVALIDADDRESS" />」は完全なメールアドレスではありません。「<ph name="ATSIGN" />」に続く文字列を入力してください。</translation>
+<translation id="5034860022980953847">プログレスバー</translation>
+<translation id="5090250355906949916">動画シークバー</translation>
+<translation id="5093189678851173835">題辞</translation>
+<translation id="5117590920725113268">次の月を表示</translation>
+<translation id="512758898067543763">行見出し</translation>
+<translation id="5143125788380636750">エピローグ</translation>
+<translation id="5164977714490026579">値は <ph name="MINIMUM" /> 以上にする必要があります。</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">「<ph name="ATSIGN" />」の前の文字列を入力してください。「<ph name="INVALIDADDRESS" />」は完全なメール アドレスではありません。</translation>
+<translation id="5334352251556557839">メディアを再生できません。</translation>
+<translation id="5406322316791861025">図</translation>
+<translation id="5453733299334684579">ツリー項目</translation>
+<translation id="5466621249238537318">1 つ以上のファイルを選択してください。</translation>
+<translation id="5468998798572797635">全画面表示を終了</translation>
+<translation id="5516424706154626233">日付選択ツール</translation>
+<translation id="5537725057119320332">キャスト</translation>
+<translation id="5546461542133609677">ミュートを解除</translation>
+<translation id="5608153257855394627">ハイライト</translation>
+<translation id="561939826962581046">日時</translation>
+<translation id="5630795885300617244">左または右をダブルタップして 10 秒スキップします</translation>
+<translation id="5631759159893697722">概要</translation>
+<translation id="5643186887447432888">ボタン</translation>
+<translation id="5677946354068040947">その他のオプション</translation>
+<translation id="576709008726043716">序論</translation>
+<translation id="57838592816432529">ミュート</translation>
+<translation id="5860033963881614850">オフ</translation>
+<translation id="588258955323874662">全画面表示</translation>
+<translation id="5888666972993069672">現在 <ph name="DEVICE_FRIENDLY_NAME" /> にキャストしています</translation>
+<translation id="591047860372322273">検索ボックス</translation>
+<translation id="5939518447894949180">リセット</translation>
+<translation id="5966707198760109579">週</translation>
+<translation id="5987525920412732405">スピンボタン</translation>
+<translation id="6011459053400940133">音量スライダー</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">リストボックス</translation>
+<translation id="6150588977291308318">参考文献</translation>
+<translation id="6164829606128959761">メーター</translation>
+<translation id="6166809985690652833">後書き</translation>
+<translation id="6209276755895393898"><ph name="DESCRIPTION" /> の画像のようです</translation>
+<translation id="6213469881011901533">用語集</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">ピクチャー イン ピクチャーを終了</translation>
+<translation id="6398862346408813489">月選択パネルを表示</translation>
+<translation id="6404546809543547843">オーディオ再生バー</translation>
+<translation id="6443871981718447451">字幕メニューを表示</translation>
+<translation id="6453774872122745852">謝辞</translation>
+<translation id="6475115390776617481">アクセス中のユーザー</translation>
+<translation id="648732519525291180">時間選択ツール</translation>
+<translation id="6550675742724504774">オプション</translation>
+<translation id="6572309429103589720">文法が無効です</translation>
+<translation id="658823671542763450">全画面表示</translation>
+<translation id="663493177488814956">フィード</translation>
+<translation id="6637586476836377253">ログ</translation>
+<translation id="6643016212128521049">削除</translation>
+<translation id="668171684555832681">その他...</translation>
+<translation id="6692633176391053278">ステッパー</translation>
+<translation id="6709570249143506788">低再生画質</translation>
+<translation id="6755330956360078551">ツールチップ</translation>
+<translation id="6790428901817661496">再生</translation>
+<translation id="6820355525329141109">プラグインを読み込むことができませんでした。</translation>
+<translation id="6820615603175220800">文献参照</translation>
+<translation id="6843725295806269523">ミュート</translation>
+<translation id="6885760532393684712">ディレクトリ</translation>
+<translation id="689129560213475294">奥付</translation>
+<translation id="6934078000481955284">引用</translation>
+<translation id="693476918119313863">ヘッダー</translation>
+<translation id="6941933287844615239">メディアをダウンロード</translation>
+<translation id="6981594929165378967">挿入</translation>
+<translation id="6989848892321993519">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在 1 文字で指定されています)。</translation>
+<translation id="7034405885550056553">提案</translation>
+<translation id="709897737746224366">指定されている形式で入力してください。</translation>
+<translation id="7118469954320184356">説明はありません。</translation>
+<translation id="7139483182332611405">序文</translation>
+<translation id="7214187073215825913">コンテンツの情報</translation>
+<translation id="7263440858009898357">リスト内の項目を選択してください。</translation>
+<translation id="727747134524199931">列見出し</translation>
+<translation id="7320576522385648310">バッファリング</translation>
+<translation id="7353453495576941748">クレジット</translation>
+<translation id="7364796246159120393">ファイルを選択</translation>
+<translation id="739024184232394898">その他...</translation>
+<translation id="7405738980073107433">巻末注</translation>
+<translation id="7410239719251593705">アダルト コンテンツが含まれているようです。説明はありません。</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">タブ</translation>
+<translation id="7514365320538308">ダウンロード</translation>
+<translation id="7529102961911894712">言及リンク</translation>
+<translation id="7533959249147584474">ラベルのない画像</translation>
+<translation id="7647456547678091388">ヒント</translation>
+<translation id="7661956066982048809">図形ドキュメント</translation>
+<translation id="7673697353781729403">時間</translation>
+<translation id="7681220483256441252">索引</translation>
+<translation id="7740050170769002709">HTML コンテンツ</translation>
+<translation id="7745230546936012372">画像の説明がない場合に取得するには、コンテキスト メニューを開きます。</translation>
+<translation id="7750228210027921155">ピクチャー イン ピクチャー</translation>
+<translation id="775297008183122718">入力した値が無効です</translation>
+<translation id="7789962463072032349">一時停止</translation>
+<translation id="7802800022689234070">三角形の展開ボタン</translation>
+<translation id="7888071071722539607">メール アドレスに「<ph name="ATSIGN" />」を挿入してください。「<ph name="INVALIDADDRESS" />」内に「<ph name="ATSIGN" />」がありません。</translation>
+<translation id="7891486169920085145">分割バー</translation>
+<translation id="795667975304826397">選択されていません</translation>
+<translation id="8053789581856978548">検索テキスト欄</translation>
+<translation id="8057695513531652401">注記</translation>
+<translation id="8105797009065549151">備考</translation>
+<translation id="811583516810654505">説明を取得しています...</translation>
+<translation id="8117451130807776954">今週</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="8208673686607688524">ローカル日時選択ツール</translation>
+<translation id="8261464734335370856">スペルが無効です</translation>
+<translation id="8284326494547611709">字幕</translation>
+<translation id="8346634859695247203">セクション</translation>
+<translation id="835897206747267392">値が無効です。</translation>
+<translation id="8403857369060869934">経過時間: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">部</translation>
+<translation id="8433900881053900389">ツールバー</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ファイル</translation>
+<translation id="8451268428117625855">ファイルを選択してください。</translation>
+<translation id="8461852803063341183">ラジオボタン</translation>
+<translation id="8474886197722836894">献辞</translation>
+<translation id="8531739829932800271">正誤表</translation>
+<translation id="8534579021159131403">分</translation>
+<translation id="8541249477527128034">メディア管理</translation>
+<translation id="8550857728288566671">図形記号</translation>
+<translation id="8583702881314752957">定義リスト</translation>
+<translation id="8597182159515967513">見出し</translation>
+<translation id="860475260694818407">目次</translation>
+<translation id="8613126697340063924">リモート再生をコントロール</translation>
+<translation id="862370744433916922">副題</translation>
+<translation id="8711688047404765493">出力</translation>
+<translation id="8750798805984357768">これらのオプションから 1 つ選択してください。</translation>
+<translation id="8808573423886751634">章</translation>
+<translation id="8822203815165896261">作成情報</translation>
+<translation id="8845239796550121995">テレビにキャストしています</translation>
+<translation id="8851136666856101339">本文</translation>
+<translation id="8875657656876809964">動画再生エラー</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="901493112792887934">現在の時間(秒単位)</translation>
+<translation id="901834265349196618">メール</translation>
+<translation id="9048119486235211610">ナビゲーション</translation>
+<translation id="9062295712474918030">ドキュメント</translation>
+<translation id="9093215626363556771">ピクチャー イン ピクチャーを終了します</translation>
+<translation id="9108370397979208512">数式</translation>
+<translation id="9132465097189459683">その他...</translation>
+<translation id="9138385573473225930">アラート</translation>
+<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> から始まる <ph name="WEEK" /></translation>
+<translation id="916607977885256133">ピクチャー イン ピクチャー</translation>
+<translation id="9168329111483466115">脚注</translation>
+<translation id="954003015749068518">ピクチャー イン ピクチャーを開始します</translation>
+<translation id="966787709310836684">メニュー</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..11949db622c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_kn.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="kn">
+<translation id="1018939186200882850">ಮೆನು ಐಟಂ</translation>
+<translation id="10623998915015855">ಟಾಗಲ್ ಬಟನ್</translation>
+<translation id="1088086359088493902">ಸೆಕೆಂಡುಗಳು</translation>
+<translation id="1171774979989969504">ದಯವಿಟ್ಟು ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="1178581264944972037">ವಿರಾಮ</translation>
+<translation id="1188858454923323853">ಪೂರಕವಾಗಿ</translation>
+<translation id="1206619573307042055">ಮಾರ್ಕ್ಯೂ</translation>
+<translation id="1206693055195146388">ಸ್ಲೈಡರ್</translation>
+<translation id="1211441953136645838">ಮುಕ್ತಾಯ ಟಿಪ್ಪಣಿ</translation>
+<translation id="1281252709823657822">ಸಂವಾದ</translation>
+<translation id="1335095011850992622">ಕ್ರೆಡಿಟ್‌ಗಳು</translation>
+<translation id="1342835525016946179">ಲೇಖನ</translation>
+<translation id="1359897965706325498">ಬ್ಯಾನರ್</translation>
+<translation id="1589122976691792535">ಪ್ರದೇಶ</translation>
+<translation id="1591562245178063882">ಈ ತಿಂಗಳು</translation>
+<translation id="1637811476055996098">ಫೈಲ್‌ಗಳನ್ನು ಆರಿಸಿ</translation>
+<translation id="1650423536718072820">ಪ್ರಮುಖ ಉಲ್ಲೇಖ</translation>
+<translation id="1727886345390570319">ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳ ಮೆನುವನ್ನು ಮರೆಮಾಡಿ</translation>
+<translation id="1729654308190250600">ಖಾಲಿ-ಅಲ್ಲದ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="1758486001363313524">ಇತರೆ...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">ಟ್ರೀ ಗ್ರಿಡ್</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">ರಿಮೋಟ್ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="190587075670221089">ಅಳಿಸುವಿಕೆ</translation>
+<translation id="1907737156431278478">ಉದಾಹರಣೆ</translation>
+<translation id="1921819250265091946">ದಿದಿ</translation>
+<translation id="1930711995431081526">ಸ್ಥಿತಿ</translation>
+<translation id="1938124657309484470">ಮೌಲ್ಯವು <ph name="MAXIMUM_DATE_OR_TIME" /> ಅಥವಾ ಹಿಂದಿನದ್ದಾಗಿರಬೇಕು.</translation>
+<translation id="1946271899482435442">ದಿನಾಂಕದ ಆಯ್ಕೆಯನ್ನು ತೋರಿಸಿ</translation>
+<translation id="1993104285338243655">ಪ್ರತಿಬಿಂಬಿಸುವಿಕೆಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' ಅನ್ನು '<ph name="INVALIDDOMAIN" />' ನಲ್ಲಿ ತಪ್ಪಾದ ಸ್ಥಾನದಲ್ಲಿ ಬಳಸಲಾಗಿದೆ.</translation>
+<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="2247351761944213033">ವಾರ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ಟ್ರ್ಯಾಕ್ <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">ಚೆಕ್‌ಬಾಕ್ಸ್</translation>
+<translation id="2311842470354187719">ಪುಟ ವಿಭಜನೆ</translation>
+<translation id="2335594187091864976">ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಪಿಕರ್</translation>
+<translation id="245932805758469625">ಇಷ್ಟು ಸೆಕೆಂಡಿನ ವೀಡಿಯೊ ಬಾಕಿ ಉಳಿದಿದೆ</translation>
+<translation id="248395913932153421">ದಿನ</translation>
+<translation id="2507943997699731163">ದಯವಿಟ್ಟು ಈ ಕ್ಷೇತ್ರವನ್ನು ಭರ್ತಿ ಮಾಡಿ.</translation>
+<translation id="2508569020611168319">ಟ್ಯಾಬ್ ಪಟ್ಟಿ</translation>
+<translation id="2561842179657104141">ಇನ್ನಷ್ಟು ಮಾಧ್ಯಮ ನಿಯಂತ್ರಣಗಳನ್ನು ತೋರಿಸು</translation>
+<translation id="2572483411312390101">ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="2613802280814924224">ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯವು <ph name="VALID_VALUE" /> ಆಗಿದೆ.</translation>
+<translation id="2653659639078652383">ಸಲ್ಲಿಸು</translation>
+<translation id="2657045182931379222">ಗ್ರಾಫಿಕ್ಸ್ ವಸ್ತು</translation>
+<translation id="2674318244760992338">ಅಡಿಟಿಪ್ಪಣಿ</translation>
+<translation id="2709516037105925701">ಸ್ವಯಂತುಂಬುವಿಕೆ</translation>
+<translation id="2723001399770238859">ಆಡಿಯೋ</translation>
+<translation id="2725963129578236554">ಕಾಮೆಂಟ್‌ಗಳು</translation>
+<translation id="2746543609216772311">ಮೌಲ್ಯವು <ph name="MINIMUM_DATE_OR_TIME" /> ಅಥವಾ ನಂತರದ್ದಾಗಿರಬೇಕು.</translation>
+<translation id="2759744352195237655">ಪಾಪ್ ಅಪ್ ಬಟನ್</translation>
+<translation id="2761667185364618470">ನೀವು ಮುಂದುವರೆಯಬೇಕಾದರೆ ದಯವಿಟ್ಟು ಈ ಬಾಕ್ಸ್ ಅನ್ನು ಪರೀಕ್ಷಿಸಿ.</translation>
+<translation id="2844350028562914727">ವಿವರಗಳು</translation>
+<translation id="2896972712917208084">ರೇಡಿಯೋ ಗುಂಪು</translation>
+<translation id="2908441821576996758">ದಯವಿಟ್ಟು ಅಲ್ಪ ವಿರಾಮದಿಂದ ಬೇರ್ಪಡಿಸಿದ ಇಮೇಲ್ ವಿಳಾಸಗಳ ಪಟ್ಟಿಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="2940813599313844715">ವಸ್ತು</translation>
+<translation id="3040011195152428237">ಲಿಂಕ್</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">ದಯವಿಟ್ಟು ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಕ್ಷೇತ್ರವು ಅಪೂರ್ಣವಾಗಿದೆ ಅಥವಾ ಅಮಾನ್ಯ ದಿನಾಂಕವನ್ನು ಹೊಂದಿದೆ.</translation>
+<translation id="3078740164268491126">ಕೋಷ್ಟಕ</translation>
+<translation id="3086746722712840547">ಟಿಪ್ಪಣಿ</translation>
+<translation id="310520048233152454">ದಯವಿಟ್ಟು URL ಅನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="3175736971608411871">ಟೈಮರ್</translation>
+<translation id="3199563858620722075">ಕಾಂಬೊ ಬಾಕ್ಸ್</translation>
+<translation id="3450233048674729344">ಮೌಲ್ಯವು <ph name="MAXIMUM" /> ಕ್ಕೆ ಸಮನಾಗಿರಬಹುದು ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆ ಆಗಿರಬಹುದು.</translation>
+<translation id="3486220673238053218">ವಿವರಣೆ</translation>
+<translation id="3557673793733683882">ಶಿರೋನಾಮೆ <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">ವಾರದ ಆಯ್ಕೆ</translation>
+<translation id="3685101356851116974">ಲೇಬಲ್ ಮಾಡಿಲ್ಲದ ಚಿತ್ರ</translation>
+<translation id="3706100364254443312">ಸ್ವಿಚ್</translation>
+<translation id="3732799496749320381">ಮಿಮೀ</translation>
+<translation id="3754210790023674521">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">ನಿಯಮ</translation>
+<translation id="3822383571486410024">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತವಾಗಿ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="3846214748874656680">ಪೂರ್ಣಪರದೆಯಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="3889183436948184105">ಪರಿಷ್ಕರಣೆ</translation>
+<translation id="3920932319529768807">ತೀರ್ಮಾನ</translation>
+<translation id="3924558731517983934">ಅಪ್ಲಿಕೇಶನ್</translation>
+<translation id="3944740393230681990">ಪೀಠಿಕೆ</translation>
+<translation id="3960700977367013758">ಸ್ಕ್ರಾಲ್ ಪಟ್ಟಿ</translation>
+<translation id="4103419683916926126">ಮಿಲಿಸೆಕೆಂಡುಗಳು</translation>
+<translation id="4151657705144244502">ಗ್ರಾಫಿಕ್</translation>
+<translation id="4160057747563657758">ಫೋನ್</translation>
+<translation id="4193965531860883258">ಮುನ್ನುಡಿ</translation>
+<translation id="4201051445878709314">ಹಿಂದಿನ ತಿಂಗಳು ತೋರಿಸು</translation>
+<translation id="421884353938374759">ಬಣ್ಣದ ಆಯ್ಕೆಮಾಡುವಿಕೆ</translation>
+<translation id="4248100235867064564">ಮೆನು ಬಾರ್‌</translation>
+<translation id="4360991593054037559">ಮಾನ್ಯವಾದ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. <ph name="VALID_VALUE_LOW" /> ಮತ್ತು <ph name="VALID_VALUE_HIGHER" /> ಎರಡು ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯಗಳಾಗಿವೆ.</translation>
+<translation id="4384583879834880242">ಪ್ರಶ್ನೋತ್ತರ</translation>
+<translation id="4413860115965805769">ಮೆನು ಬಟನ್</translation>
+<translation id="4444765639179266822">ಹೀಗೆ ಹೇಳುತ್ತಿರಬಹುದು: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">ಪದಕೋಶ ಉಲ್ಲೇಖ</translation>
+<translation id="4522570452068850558">ವಿವರಗಳು</translation>
+<translation id="4542388879936266156">ಬಾಕಿ ಉಳಿದಿರುವ ಸಮಯ: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ಫಾರ್ಮ್</translation>
+<translation id="4661075872484491155">ಮರ</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="4668956016107839909">ಅನುಬಂಧ</translation>
+<translation id="4718048029184481307">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ ಮೋಡ್‌ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ</translation>
+<translation id="4742539557769756338">ಕವರ್</translation>
+<translation id="4748357248530471599">ಡಿಸ್‌ಪ್ಲೇ ಕಟ್‌ಔಟ್ ಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಟಾಗಲ್ ಮಾಡಿ</translation>
+<translation id="4757246831282535685">ಟ್ಯಾಬ್ ಫಲಕ</translation>
+<translation id="4763480195061959176">ವೀಡಿಯೊ</translation>
+<translation id="479989351350248267">ಹುಡುಕಾಡಿ</translation>
+<translation id="4812940957355064477">ದಯವಿಟ್ಟು ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="4912536737030637138">ಗ್ರಂಥಸೂಚಿ ನಮೂದು</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ</translation>
+<translation id="4992066212339426712">ಅನ್‌ಮ್ಯೂಟ್</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN" />' ನಂತರದ ಒಂದು ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="5034860022980953847">ಪ್ರಗತಿ ಸೂಚಕ</translation>
+<translation id="5090250355906949916">ವೀಡಿಯೊ ಸಮಯದ ಸ್ಕ್ರಬ್ಬರ್</translation>
+<translation id="5093189678851173835">ಶಿಲಾಶಾಸನ</translation>
+<translation id="5117590920725113268">ಮುಂದಿನ ತಿಂಗಳು ತೋರಿಸಿ</translation>
+<translation id="512758898067543763">ಸಾಲಿನ ಶಿರೋನಾಮೆ</translation>
+<translation id="5143125788380636750">ಹಿನ್ನುಡಿ</translation>
+<translation id="5164977714490026579">ಮೌಲ್ಯವು <ph name="MINIMUM" /> ಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಾಗಿರಬೇಕು ಅಥವಾ ಸಮನಾಗಿರಬೇಕು.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="5334352251556557839">ಮೀಡಿಯಾ ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.</translation>
+<translation id="5406322316791861025">ಆಕೃತಿ</translation>
+<translation id="5453733299334684579">ಟ್ರೀ ಐಟಂ</translation>
+<translation id="5466621249238537318">ದಯವಿಟ್ಟು ಒಂದು ಅಥವಾ ಹೆಚ್ಚು ಫೈಲ್‌ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ.</translation>
+<translation id="5468998798572797635">ಪೂರ್ಣಪರದೆಯಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="5516424706154626233">ದಿನಾಂಕದ ಪಿಕರ್</translation>
+<translation id="5537725057119320332">ಪಾತ್ರವರ್ಗ</translation>
+<translation id="5546461542133609677">ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="5608153257855394627">ಹೈಲೈಟ್</translation>
+<translation id="561939826962581046">ಸಮಯ</translation>
+<translation id="5630795885300617244">10ಸೆ ಸ್ಕಿಪ್ ಮಾಡಲು ಎಡಕ್ಕೆ ಅಥವಾ ಬಲಕ್ಕೆ ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ</translation>
+<translation id="5631759159893697722">ಸಾರಾಂಶ</translation>
+<translation id="5643186887447432888">ಬಟನ್</translation>
+<translation id="5677946354068040947">ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು</translation>
+<translation id="576709008726043716">ಪರಿಚಯ</translation>
+<translation id="57838592816432529">ಮ್ಯೂಟ್</translation>
+<translation id="5860033963881614850">ಆಫ್</translation>
+<translation id="588258955323874662">ಪೂರ್ಣಪರದೆ</translation>
+<translation id="5888666972993069672">ಈಗ <ph name="DEVICE_FRIENDLY_NAME" /> ಗೆ ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ</translation>
+<translation id="591047860372322273">ಹುಡುಕಾಟ ಬಾಕ್ಸ್</translation>
+<translation id="5939518447894949180">ಮರುಹೊಂದಿಸು</translation>
+<translation id="5966707198760109579">ವಾರ</translation>
+<translation id="5987525920412732405">ಸ್ಪಿನ್ ಬಟನ್</translation>
+<translation id="6011459053400940133">ವಾಲ್ಯೂಮ್ ಸ್ಲೈಡರ್</translation>
+<translation id="6015796118275082299">ವರ್ಷ</translation>
+<translation id="6023896073578205740">ಪಟ್ಟಿಯ ಬಾಕ್ಸ್</translation>
+<translation id="6150588977291308318">ಗ್ರಂಥಸೂಚಿ</translation>
+<translation id="6164829606128959761">ಮೀಟರ್</translation>
+<translation id="6166809985690652833">ನಂತರದ</translation>
+<translation id="6209276755895393898">ಹೀಗೆ ಕಾಣಿಸುತ್ತಿದೆ: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">ಪದಕೋಶ</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="6398862346408813489">ತಿಂಗಳ ಆಯ್ಕೆ ಪ್ಯಾನಲ್ ತೋರಿಸಿ</translation>
+<translation id="6404546809543547843">ಆಡಿಯೊ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್</translation>
+<translation id="6443871981718447451">ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳ ಮೆನುವನ್ನು ತೋರಿಸಿ</translation>
+<translation id="6453774872122745852">ಅಂಗೀಕಾರಗಳು</translation>
+<translation id="6475115390776617481">ಪ್ರಸ್ತುತವಾಗಿ ಈ ವಿಷಯವನ್ನು ಪರಿಶೀಲಿಸುತ್ತಿರುವವರು ಅಥವಾ ಎಡಿಟ್ ಮಾಡುತ್ತಿರುವವರು</translation>
+<translation id="648732519525291180">ಸಮಯ ಪಿಕರ್</translation>
+<translation id="6550675742724504774">ಆಯ್ಕೆಗಳು</translation>
+<translation id="6572309429103589720">ಅಮಾನ್ಯ ವ್ಯಾಕರಣ</translation>
+<translation id="658823671542763450">ಪೂರ್ಣ ಪರದೆ ನಮೂದಿಸು</translation>
+<translation id="663493177488814956">ಫೀಡ್‌</translation>
+<translation id="6637586476836377253">ಲಾಗ್</translation>
+<translation id="6643016212128521049">ತೆರವುಗೊಳಿಸಿ</translation>
+<translation id="668171684555832681">ಇತರೆ...</translation>
+<translation id="6692633176391053278">ಸ್ಟೀಪರ್</translation>
+<translation id="6709570249143506788">ಪ್ಲೇಬ್ಯಾಕ್ ಗುಣಮಟ್ಟ ಕಳಪೆಯಾಗಿದೆ</translation>
+<translation id="6755330956360078551">ಟೂಲ್‌ ಟಿಪ್‌</translation>
+<translation id="6790428901817661496">ಪ್ಲೇ ಮಾಡು</translation>
+<translation id="6820355525329141109">ಪ್ಲಗ್-ಇನ್ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.</translation>
+<translation id="6820615603175220800">ಗ್ರಂಥಸೂಚಿ ಉಲ್ಲೇಖ</translation>
+<translation id="6843725295806269523">ಮ್ಯೂಟ್</translation>
+<translation id="6885760532393684712">ಡೈರೆಕ್ಟರಿ</translation>
+<translation id="689129560213475294">ಕೊಲೊಫೋನ್</translation>
+<translation id="6934078000481955284">ಬ್ಲಾಕ್‌ಕೋಟ್</translation>
+<translation id="693476918119313863">ಶಿರೋಲೇಖ</translation>
+<translation id="6941933287844615239">ಮಾಧ್ಯಮ ಡೌನ್‌ಲೋಡ್</translation>
+<translation id="6981594929165378967">ಅಳವಡಿಕೆ</translation>
+<translation id="6989848892321993519">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಥವಾ ಇದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿನ ಅಕ್ಷರಗಳಿಗೆ ಉದ್ದಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತ 1 ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
+<translation id="7034405885550056553">ಸಲಹೆ</translation>
+<translation id="709897737746224366">ದಯವಿಟ್ಟು ವಿನಂತಿಸಿದ ಸ್ವರೂಪವನ್ನು ಹೊಂದಿಸಿ.</translation>
+<translation id="7118469954320184356">ಯಾವುದೇ ವಿವರಣೆ ಲಭ್ಯವಿಲ್ಲ.</translation>
+<translation id="7139483182332611405">ಮುನ್ನುಡಿ</translation>
+<translation id="7214187073215825913">ವಿಷಯದ ಮಾಹಿತಿ</translation>
+<translation id="7263440858009898357">ಪಟ್ಟಿಯಲ್ಲಿನ ಐಟಂ ಅನ್ನು ದಯವಿಟ್ಟು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
+<translation id="727747134524199931">ಕಾಲಮ್ ಶಿರೋನಾಮೆ</translation>
+<translation id="7320576522385648310">ಬಫರ್ ಆಗುತ್ತಿದೆ</translation>
+<translation id="7353453495576941748">ಗೌರವ</translation>
+<translation id="7364796246159120393">ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ</translation>
+<translation id="739024184232394898">ಇತರೆ...</translation>
+<translation id="7405738980073107433">ಅಂತಿಮ ಟಿಪ್ಪಣಿಗಳು</translation>
+<translation id="7410239719251593705">ವಯಸ್ಕರ ವಿಷಯವನ್ನು ಒಳಗೊಂಡಿರುವಂತೆ ತೋರುತ್ತಿದೆ. ಯಾವುದೇ ವಿವರಣೆ ಲಭ್ಯವಿಲ್ಲ.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">ಟ್ಯಾಬ್</translation>
+<translation id="7514365320538308">ಡೌನ್‌ಲೋಡ್</translation>
+<translation id="7529102961911894712">ಬ್ಯಾಕ್‌ಲಿಂಕ್</translation>
+<translation id="7533959249147584474">ಲೇಬಲ್ ಮಾಡಿಲ್ಲದ ಗ್ರಾಫಿಕ್</translation>
+<translation id="7647456547678091388">ಸಲಹೆ</translation>
+<translation id="7661956066982048809">ಗ್ರಾಫಿಕ್ಸ್ ಡಾಕ್ಯುಮೆಂಟ್</translation>
+<translation id="7673697353781729403">ಗಂಟೆಗಳು</translation>
+<translation id="7681220483256441252">ಸೂಚಿಕೆ</translation>
+<translation id="7740050170769002709">HTML ವಿಷಯ</translation>
+<translation id="7745230546936012372">ಕಾಣೆಯಾಗಿರುವ ಚಿತ್ರದ ವಿವರಣೆಗಳನ್ನು ಪಡೆಯಲು, ಸಂದರ್ಭದ ಮೆನು ತೆರೆಯಿರಿ.</translation>
+<translation id="7750228210027921155">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ</translation>
+<translation id="775297008183122718">ಅಮಾನ್ಯ ನಮೂದು</translation>
+<translation id="7789962463072032349">ವಿರಾಮ</translation>
+<translation id="7802800022689234070">ತ್ರಿಕೋನ ಪ್ರಕಟಣೆ</translation>
+<translation id="7888071071722539607">ಇಮೇಲ್ ವಿಳಾಸದಲ್ಲಿ ಒಂದು '<ph name="ATSIGN" />' ಅನ್ನು ಸೇರಿಸಿ. '<ph name="ATSIGN" />' ನಲ್ಲಿ '<ph name="INVALIDADDRESS" />' ಕಾಣೆಯಾಗಿದೆ.</translation>
+<translation id="7891486169920085145">ಛೇದಕ</translation>
+<translation id="795667975304826397">ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ</translation>
+<translation id="8053789581856978548">ಪಠ್ಯ ಹುಡುಕಾಟದ ಫೀಲ್ಡ್</translation>
+<translation id="8057695513531652401">ಸೂಚನೆ</translation>
+<translation id="8105797009065549151">ಸೂಚನೆ ಉಲ್ಲೇಖ</translation>
+<translation id="811583516810654505">ವಿವರಣೆಯನ್ನು ಪಡೆಯಲಾಗುತ್ತಿದೆ...</translation>
+<translation id="8117451130807776954">ಈ ವಾರ</translation>
+<translation id="8199524924445686405">ವವವವ</translation>
+<translation id="8208673686607688524">ಸ್ಥಳೀಯ ದಿನಾಂಕ ಮತ್ತು ಸಮಯದ ಆಯ್ಕೆ</translation>
+<translation id="8261464734335370856">ಅಮಾನ್ಯ ಕಾಗುಣಿತ</translation>
+<translation id="8284326494547611709">ಶೀರ್ಷಿಕೆಗಳು</translation>
+<translation id="8346634859695247203">ವಿಭಾಗ</translation>
+<translation id="835897206747267392">ಅಮಾನ್ಯ ಮೌಲ್ಯ.</translation>
+<translation id="8403857369060869934">ಕಳೆದುಹೋದ ಸಮಯ: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">ಭಾಗ</translation>
+<translation id="8433900881053900389">ಟೂಲ್‌ಬಾರ್</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ಫೈಲ್‌ಗಳು</translation>
+<translation id="8451268428117625855">ದಯವಿಟ್ಟು ಫೈಲ್ ಆಯ್ಕೆಮಾಡಿ.</translation>
+<translation id="8461852803063341183">ರೇಡಿಯೋ ಬಟನ್</translation>
+<translation id="8474886197722836894">ಸಮರ್ಪಣೆ</translation>
+<translation id="8531739829932800271">ಎರ್ರಾಟಾ</translation>
+<translation id="8534579021159131403">ನಿಮಿಷಗಳು</translation>
+<translation id="8541249477527128034">ಮಾಧ್ಯಮ ನಿಯಂತ್ರಣ</translation>
+<translation id="8550857728288566671">ಗ್ರಾಫಿಕ್ಸ್ ಚಿಹ್ನೆ</translation>
+<translation id="8583702881314752957">ವಿವರಣೆ ಪಟ್ಟಿ</translation>
+<translation id="8597182159515967513">ಶೀರ್ಷಿಕೆ</translation>
+<translation id="860475260694818407">ಪರಿವಿಡಿ</translation>
+<translation id="8613126697340063924">ರಿಮೋಟ್ ಪ್ಲೇಬ್ಯಾಕ್ ನಿಯಂತ್ರಿಸಿ</translation>
+<translation id="862370744433916922">ಉಪಶೀರ್ಷಿಕೆ</translation>
+<translation id="8711688047404765493">ಔಟ್‌ಪುಟ್</translation>
+<translation id="8750798805984357768">ದಯವಿಟ್ಟು ಈ ಕೆಳಗಿನ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಆರಿಸಿ.</translation>
+<translation id="8808573423886751634">ಅಧ್ಯಾಯ</translation>
+<translation id="8822203815165896261">ಲೇಖಕರ ಮಾಹಿತಿ</translation>
+<translation id="8845239796550121995">ಈಗ ನಿಮ್ಮ ಟಿವಿಯನ್ನು ಬಿತ್ತರಿಸಲಾಗುತ್ತಿದೆ</translation>
+<translation id="8851136666856101339">ಮುಖ್ಯ</translation>
+<translation id="8875657656876809964">ವೀಡಿಯೊ ಪ್ಲೇಬ್ಯಾಕ್ ದೋಷ</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">ತಿಂಗಳು</translation>
+<translation id="901493112792887934">ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತ ಸಮಯ</translation>
+<translation id="901834265349196618">ಇಮೇಲ್</translation>
+<translation id="9048119486235211610">ನ್ಯಾವಿಗೇಷನ್</translation>
+<translation id="9062295712474918030">ಡಾಕ್ಯುಮೆಂಟ್</translation>
+<translation id="9093215626363556771">ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರದಿಂದ ನಿರ್ಗಮಿಸಿ</translation>
+<translation id="9108370397979208512">ಮ್ಯಾಥ್</translation>
+<translation id="9132465097189459683">ಇತರೆ...</translation>
+<translation id="9138385573473225930">ಎಚ್ಚರಿಕೆ</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> ರಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ</translation>
+<translation id="916607977885256133">ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರ</translation>
+<translation id="9168329111483466115">ಅಡಿಟಿಪ್ಪಣಿ</translation>
+<translation id="954003015749068518">ಚಿತ್ರದಲ್ಲಿನ ಚಿತ್ರವನ್ನು ಪ್ರವೇಶಿಸಿ</translation>
+<translation id="966787709310836684">ಮೆನು</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..8f92ca41f75
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ko.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ko">
+<translation id="1018939186200882850">메뉴 항목</translation>
+<translation id="10623998915015855">전환 버튼</translation>
+<translation id="1088086359088493902">초</translation>
+<translation id="1171774979989969504">이메일 주소를 입력하세요.</translation>
+<translation id="1178581264944972037">일시중지</translation>
+<translation id="1188858454923323853">상호 보완</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">슬라이더</translation>
+<translation id="1211441953136645838">미주</translation>
+<translation id="1281252709823657822">대화상자</translation>
+<translation id="1335095011850992622">저작권 표시</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">배너</translation>
+<translation id="1589122976691792535">지역</translation>
+<translation id="1591562245178063882">이번 달</translation>
+<translation id="1637811476055996098">파일 선택</translation>
+<translation id="1650423536718072820">인용문</translation>
+<translation id="1727886345390570319">자막 메뉴 숨기기</translation>
+<translation id="1729654308190250600">비어 있지 않은 이메일 주소를 입력해 주세요.</translation>
+<translation id="1758486001363313524">다른 일자...</translation>
+<translation id="1806710327868736751">알림 대화상자</translation>
+<translation id="1821985195704844674">트리 격자</translation>
+<translation id="1822429046913737220">오전/오후</translation>
+<translation id="1832974991323546415">원격 기기에서 재생</translation>
+<translation id="190587075670221089">삭제</translation>
+<translation id="1907737156431278478">예시</translation>
+<translation id="1921819250265091946">일</translation>
+<translation id="1930711995431081526">상태</translation>
+<translation id="1938124657309484470">값은 <ph name="MAXIMUM_DATE_OR_TIME" /> 이전이어야 합니다.</translation>
+<translation id="1946271899482435442">날짜 선택도구 표시</translation>
+<translation id="1993104285338243655">미러링으로 전환됨</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />'에서 '<ph name="DOT" />'의 위치가 잘못되었습니다.</translation>
+<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="2247351761944213033"><ph name="YEAR" />, <ph name="WEEKNUMBER" />번째 주</translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />번 트랙</translation>
+<translation id="2291999235780842123">체크박스</translation>
+<translation id="2311842470354187719">페이지 나누기</translation>
+<translation id="2335594187091864976">날짜 및 시간 선택기</translation>
+<translation id="245932805758469625">동영상 남은 시간</translation>
+<translation id="248395913932153421">일</translation>
+<translation id="2507943997699731163">이 입력란을 작성하세요.</translation>
+<translation id="2508569020611168319">탭 목록</translation>
+<translation id="2561842179657104141">미디어 컨트롤 더보기</translation>
+<translation id="2572483411312390101">재생</translation>
+<translation id="2613802280814924224">유효한 값을 입력해 주세요. 가장 근접한 유효 값은 <ph name="VALID_VALUE" />입니다.</translation>
+<translation id="2653659639078652383">제출</translation>
+<translation id="2657045182931379222">그래픽 객체</translation>
+<translation id="2674318244760992338">바닥글</translation>
+<translation id="2709516037105925701">자동 완성</translation>
+<translation id="2723001399770238859">오디오</translation>
+<translation id="2725963129578236554">댓글</translation>
+<translation id="2746543609216772311">값은 <ph name="MINIMUM_DATE_OR_TIME" /> 이후여야 합니다.</translation>
+<translation id="2759744352195237655">팝업 버튼</translation>
+<translation id="2761667185364618470">계속하려면 이 확인란을 선택하세요.</translation>
+<translation id="2844350028562914727">세부정보</translation>
+<translation id="2896972712917208084">라디오 그룹</translation>
+<translation id="2908441821576996758">이메일 주소를 쉼표로 구분하여 입력하세요.</translation>
+<translation id="2940813599313844715">객체</translation>
+<translation id="3040011195152428237">링크</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" />MB</translation>
+<translation id="3075154866155599887">유효한 값을 입력하세요. 입력을 완료하지 않았거나 날짜가 잘못되었습니다.</translation>
+<translation id="3078740164268491126">표</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">URL을 입력하세요.</translation>
+<translation id="3175736971608411871">타이머</translation>
+<translation id="3199563858620722075">콤보 상자</translation>
+<translation id="3450233048674729344">값은 <ph name="MAXIMUM" /> 이하여야 합니다.</translation>
+<translation id="3486220673238053218">정의</translation>
+<translation id="3557673793733683882">제목 <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">주 선택도구</translation>
+<translation id="3685101356851116974">라벨이 없는 이미지</translation>
+<translation id="3706100364254443312">전환</translation>
+<translation id="3732799496749320381">월</translation>
+<translation id="3754210790023674521">PIP 모드 종료</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" />GB</translation>
+<translation id="3808586225841795776">용어</translation>
+<translation id="3822383571486410024">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' 앞 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
+<translation id="3846214748874656680">전체화면 종료</translation>
+<translation id="3889183436948184105">개정</translation>
+<translation id="3920932319529768807">결론</translation>
+<translation id="3924558731517983934">애플리케이션</translation>
+<translation id="3944740393230681990">프롤로그</translation>
+<translation id="3960700977367013758">스크롤바</translation>
+<translation id="4103419683916926126">밀리초</translation>
+<translation id="4151657705144244502">그래픽</translation>
+<translation id="4160057747563657758">전화번호</translation>
+<translation id="4193965531860883258">서문</translation>
+<translation id="4201051445878709314">이전 달 표시</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">메뉴 표시줄</translation>
+<translation id="4360991593054037559">유효한 값을 입력해 주세요. 가장 근접한 유효 값 2개는 <ph name="VALID_VALUE_LOW" /> 및 <ph name="VALID_VALUE_HIGHER" />입니다.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
+<translation id="4413860115965805769">메뉴 버튼</translation>
+<translation id="4444765639179266822">텍스트가 <ph name="OCR_TEXT" />인 것으로 보입니다</translation>
+<translation id="4446524499724042288">용어 참조</translation>
+<translation id="4522570452068850558">세부정보</translation>
+<translation id="4542388879936266156">남은 시간: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">양식</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
+<translation id="4668956016107839909">부록</translation>
+<translation id="4718048029184481307">PIP 모드에서 재생</translation>
+<translation id="4742539557769756338">표지</translation>
+<translation id="4748357248530471599">디스플레이 컷아웃을 전체화면으로 전환</translation>
+<translation id="4757246831282535685">탭 패널</translation>
+<translation id="4763480195061959176">동영상</translation>
+<translation id="479989351350248267">검색</translation>
+<translation id="4812940957355064477">숫자를 입력하세요.</translation>
+<translation id="4912536737030637138">참고문헌 항목</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />개 선택됨</translation>
+<translation id="4992066212339426712">음소거 해제</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN" />' 뒷 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
+<translation id="5034860022980953847">진행률 표시기</translation>
+<translation id="5090250355906949916">동영상 시간 스크러버</translation>
+<translation id="5093189678851173835">제명</translation>
+<translation id="5117590920725113268">다음 달 표시</translation>
+<translation id="512758898067543763">행 헤더</translation>
+<translation id="5143125788380636750">에필로그</translation>
+<translation id="5164977714490026579">값은 <ph name="MINIMUM" /> 이상이어야 합니다.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" />PB</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN" />' 앞 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
+<translation id="5334352251556557839">미디어를 재생할 수 없습니다.</translation>
+<translation id="5406322316791861025">그림</translation>
+<translation id="5453733299334684579">트리 항목</translation>
+<translation id="5466621249238537318">파일을 한 개 이상 선택하세요.</translation>
+<translation id="5468998798572797635">전체화면 닫기</translation>
+<translation id="5516424706154626233">날짜 선택기</translation>
+<translation id="5537725057119320332">전송</translation>
+<translation id="5546461542133609677">음소거 해제</translation>
+<translation id="5608153257855394627">강조표시</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">10초를 건너뛰려면 왼쪽이나 오른쪽을 두 번 탭하세요.</translation>
+<translation id="5631759159893697722">초록</translation>
+<translation id="5643186887447432888">버튼</translation>
+<translation id="5677946354068040947">옵션 더보기</translation>
+<translation id="576709008726043716">소개</translation>
+<translation id="57838592816432529">음소거</translation>
+<translation id="5860033963881614850">사용 안함</translation>
+<translation id="588258955323874662">전체화면</translation>
+<translation id="5888666972993069672">현재 <ph name="DEVICE_FRIENDLY_NAME" />(으)로 전송 중</translation>
+<translation id="591047860372322273">검색창</translation>
+<translation id="5939518447894949180">초기화</translation>
+<translation id="5966707198760109579">주</translation>
+<translation id="5987525920412732405">스핀 버튼</translation>
+<translation id="6011459053400940133">볼륨 슬라이더</translation>
+<translation id="6015796118275082299">연도</translation>
+<translation id="6023896073578205740">목록 상자</translation>
+<translation id="6150588977291308318">참고문헌</translation>
+<translation id="6164829606128959761">미터</translation>
+<translation id="6166809985690652833">후기</translation>
+<translation id="6209276755895393898"><ph name="DESCRIPTION" /> 같습니다</translation>
+<translation id="6213469881011901533">용어설명</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">PIP 모드 종료</translation>
+<translation id="6398862346408813489">월 선택 패널 표시</translation>
+<translation id="6404546809543547843">오디오 시간 스크러버</translation>
+<translation id="6443871981718447451">자막 메뉴 표시</translation>
+<translation id="6453774872122745852">감사의 말</translation>
+<translation id="6475115390776617481">실시간 공동작업자</translation>
+<translation id="648732519525291180">시간 선택기</translation>
+<translation id="6550675742724504774">옵션</translation>
+<translation id="6572309429103589720">문법이 잘못되었습니다.</translation>
+<translation id="658823671542763450">전체화면 열기</translation>
+<translation id="663493177488814956">피드</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">삭제</translation>
+<translation id="668171684555832681">기타...</translation>
+<translation id="6692633176391053278">증감자</translation>
+<translation id="6709570249143506788">재생 품질 나쁨</translation>
+<translation id="6755330956360078551">도움말</translation>
+<translation id="6790428901817661496">재생</translation>
+<translation id="6820355525329141109">플러그인을 로드할 수 없습니다.</translation>
+<translation id="6820615603175220800">참고문헌 참조</translation>
+<translation id="6843725295806269523">음소거</translation>
+<translation id="6885760532393684712">디렉터리</translation>
+<translation id="689129560213475294">출판사 이름</translation>
+<translation id="6934078000481955284">인용구</translation>
+<translation id="693476918119313863">머리글</translation>
+<translation id="6941933287844615239">미디어 다운로드</translation>
+<translation id="6981594929165378967">삽입</translation>
+<translation id="6989848892321993519">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 1자 사용 중).</translation>
+<translation id="7034405885550056553">추천</translation>
+<translation id="709897737746224366">요청한 형식과 일치시키세요.</translation>
+<translation id="7118469954320184356">설명이 없습니다.</translation>
+<translation id="7139483182332611405">머리말</translation>
+<translation id="7214187073215825913">콘텐츠 정보</translation>
+<translation id="7263440858009898357">목록에서 항목을 선택하세요.</translation>
+<translation id="727747134524199931">열 헤더</translation>
+<translation id="7320576522385648310">버퍼링</translation>
+<translation id="7353453495576941748">크레딧</translation>
+<translation id="7364796246159120393">파일 선택</translation>
+<translation id="739024184232394898">다른 주...</translation>
+<translation id="7405738980073107433">미주</translation>
+<translation id="7410239719251593705">성인용 콘텐츠가 포함된 것으로 보입니다. 설명이 없습니다.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" />TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">다운로드</translation>
+<translation id="7529102961911894712">뒤로 링크</translation>
+<translation id="7533959249147584474">라벨이 없는 그래픽</translation>
+<translation id="7647456547678091388">도움말</translation>
+<translation id="7661956066982048809">그래픽 문서</translation>
+<translation id="7673697353781729403">시간</translation>
+<translation id="7681220483256441252">색인</translation>
+<translation id="7740050170769002709">HTML 콘텐츠</translation>
+<translation id="7745230546936012372">누락된 이미지 설명을 확인하려면 컨텍스트 메뉴를 여세요.</translation>
+<translation id="7750228210027921155">PIP 모드</translation>
+<translation id="775297008183122718">입력값이 잘못되었습니다.</translation>
+<translation id="7789962463072032349">일시중지</translation>
+<translation id="7802800022689234070">펼치기/접기 삼각형</translation>
+<translation id="7888071071722539607">이메일 주소에 '<ph name="ATSIGN" />'를 포함해 주세요. '<ph name="INVALIDADDRESS" />'에 '<ph name="ATSIGN" />'가 없습니다.</translation>
+<translation id="7891486169920085145">분할선</translation>
+<translation id="795667975304826397">선택된 파일 없음</translation>
+<translation id="8053789581856978548">검색어 입력란</translation>
+<translation id="8057695513531652401">안내문</translation>
+<translation id="8105797009065549151">참고 자료</translation>
+<translation id="811583516810654505">설명 가져오는 중...</translation>
+<translation id="8117451130807776954">이번 주</translation>
+<translation id="8199524924445686405">연도</translation>
+<translation id="8208673686607688524">로컬 날짜 및 시간 선택도구</translation>
+<translation id="8261464734335370856">맞춤법이 잘못되었습니다.</translation>
+<translation id="8284326494547611709">자막</translation>
+<translation id="8346634859695247203">섹션</translation>
+<translation id="835897206747267392">값이 잘못되었습니다.</translation>
+<translation id="8403857369060869934">경과 시간: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">부</translation>
+<translation id="8433900881053900389">툴바</translation>
+<translation id="8444882422881193423">파일 <ph name="NUMBER_OF_FILES" />개</translation>
+<translation id="8451268428117625855">파일을 선택하세요.</translation>
+<translation id="8461852803063341183">라디오 버튼</translation>
+<translation id="8474886197722836894">헌정사</translation>
+<translation id="8531739829932800271">정오표</translation>
+<translation id="8534579021159131403">분</translation>
+<translation id="8541249477527128034">미디어 컨트롤</translation>
+<translation id="8550857728288566671">그래픽 기호</translation>
+<translation id="8583702881314752957">정의 목록</translation>
+<translation id="8597182159515967513">항목</translation>
+<translation id="860475260694818407">목차</translation>
+<translation id="8613126697340063924">원격 재생 제어</translation>
+<translation id="862370744433916922">부제</translation>
+<translation id="8711688047404765493">출력</translation>
+<translation id="8750798805984357768">다음 옵션 중 하나를 선택하세요.</translation>
+<translation id="8808573423886751634">장</translation>
+<translation id="8822203815165896261">저자 정보</translation>
+<translation id="8845239796550121995">TV로 전송 중</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">동영상 재생 오류</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" />KB</translation>
+<translation id="8987927404178983737">월</translation>
+<translation id="901493112792887934">현재 시간(초)</translation>
+<translation id="901834265349196618">이메일</translation>
+<translation id="9048119486235211610">탐색</translation>
+<translation id="9062295712474918030">문서</translation>
+<translation id="9093215626363556771">PIP 모드 종료</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">다른 달...</translation>
+<translation id="9138385573473225930">알림</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />(<ph name="WEEK_START_DATE" />에 시작)</translation>
+<translation id="916607977885256133">PIP 모드</translation>
+<translation id="9168329111483466115">각주</translation>
+<translation id="954003015749068518">PIP 모드 시작</translation>
+<translation id="966787709310836684">메뉴</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..dd3b231a827
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_lt.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lt">
+<translation id="1018939186200882850">meniu elementas</translation>
+<translation id="10623998915015855">perjungimo mygtukas</translation>
+<translation id="1088086359088493902">Sekundės</translation>
+<translation id="1171774979989969504">Įveskite el. pašto adresą.</translation>
+<translation id="1178581264944972037">Pristabdyti</translation>
+<translation id="1188858454923323853">papildomas</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">šliaužiklis</translation>
+<translation id="1211441953136645838">išnaša</translation>
+<translation id="1281252709823657822">dialogo langas</translation>
+<translation id="1335095011850992622">titrai</translation>
+<translation id="1342835525016946179">artikelis</translation>
+<translation id="1359897965706325498">reklamjuostė</translation>
+<translation id="1589122976691792535">regionas</translation>
+<translation id="1591562245178063882">Šis mėnuo</translation>
+<translation id="1637811476055996098">Pasirinkti failus</translation>
+<translation id="1650423536718072820">citata</translation>
+<translation id="1727886345390570319">slėpti subtitrų meniu</translation>
+<translation id="1729654308190250600">Įveskite el. pašto adresą (nepalikite lauko tuščio).</translation>
+<translation id="1758486001363313524">Kita...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">medžio tinklelis</translation>
+<translation id="1822429046913737220">iki pietų / po pietų</translation>
+<translation id="1832974991323546415">leisti naudojant nuotolinį įrenginį</translation>
+<translation id="190587075670221089">trynimas</translation>
+<translation id="1907737156431278478">pavyzdys</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">būsena</translation>
+<translation id="1938124657309484470">Vertė turi būti <ph name="MAXIMUM_DATE_OR_TIME" /> ar ankstesnė data.</translation>
+<translation id="1946271899482435442">Rodyti datos rinkiklį</translation>
+<translation id="1993104285338243655">Perjungta į ekrano vaizdo bendrinimą</translation>
+<translation id="2060505056492490888">„<ph name="DOT" />“ naudojamas netinkamoje „<ph name="INVALIDDOMAIN" />“ vietoje.</translation>
+<translation id="2148716181193084225">Šiandien</translation>
+<translation id="2158401438286456825">puslapių sąrašas</translation>
+<translation id="2226276347425096477">Sutrumpinkite šį tekstą iki <ph name="MAX_CHARACTERS" /> simb. ar mažiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
+<translation id="2246498165605549352">Vietos failas</translation>
+<translation id="2247351761944213033"><ph name="YEAR" /> m. <ph name="WEEKNUMBER" /> sav.</translation>
+<translation id="2277199496770840904"><ph name="NUMBER" /> takelis</translation>
+<translation id="2291999235780842123">žymimasis laukelis</translation>
+<translation id="2311842470354187719">puslapio lūžis</translation>
+<translation id="2335594187091864976">datos ir laiko rinkiklis</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>
+<translation id="2508569020611168319">skirtukų sąrašas</translation>
+<translation id="2561842179657104141">rodyti daugiau medijos valdiklių</translation>
+<translation id="2572483411312390101">paleisti</translation>
+<translation id="2613802280814924224">Įveskite tinkamą vertę. Artimiausia tinkama vertė yra <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Pateikti</translation>
+<translation id="2657045182931379222">grafikos objektas</translation>
+<translation id="2674318244760992338">poraštė</translation>
+<translation id="2709516037105925701">Automatinis pildymas</translation>
+<translation id="2723001399770238859">garso įrašas</translation>
+<translation id="2725963129578236554">komentarai</translation>
+<translation id="2746543609216772311">Vertė turi būti <ph name="MINIMUM_DATE_OR_TIME" /> ar vėlesnė data.</translation>
+<translation id="2759744352195237655">Iššokantysis mygtukas</translation>
+<translation id="2761667185364618470">Jei norite tęsti, pažymėkite šį laukelį.</translation>
+<translation id="2844350028562914727">išsami informacija</translation>
+<translation id="2896972712917208084">akučių grupė</translation>
+<translation id="2908441821576996758">Įveskite kableliais atskirtą el. pašto adresų sąrašą.</translation>
+<translation id="2940813599313844715">objektas</translation>
+<translation id="3040011195152428237">nuoroda</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Įveskite tinkamą vertę. Laukas užpildytas nevisiškai arba įvesta netinkama data.</translation>
+<translation id="3078740164268491126">lentelė</translation>
+<translation id="3086746722712840547">pastaba</translation>
+<translation id="310520048233152454">Įveskite URL.</translation>
+<translation id="3175736971608411871">laikmatis</translation>
+<translation id="3199563858620722075">jungtinis laukelis</translation>
+<translation id="3450233048674729344">Vertė turi būti <ph name="MAXIMUM" /> arba mažesnė.</translation>
+<translation id="3486220673238053218">apibrėžimas</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" /> antraštė</translation>
+<translation id="3670698553867754311">savaitės rinkiklis</translation>
+<translation id="3685101356851116974">Nepažymėtas vaizdas</translation>
+<translation id="3706100364254443312">jungiklis</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Išeiti iš vaizdo vaizde režimo</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">terminas</translation>
+<translation id="3822383571486410024">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
+<translation id="383465348367842624">Prieš „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3846214748874656680">Išjungti viso ekrano režimą</translation>
+<translation id="3889183436948184105">taisymas</translation>
+<translation id="3920932319529768807">išvada</translation>
+<translation id="3924558731517983934">programa</translation>
+<translation id="3944740393230681990">prologas</translation>
+<translation id="3960700977367013758">slinkties juosta</translation>
+<translation id="4103419683916926126">Milisekundės</translation>
+<translation id="4151657705144244502">grafinis elementas</translation>
+<translation id="4160057747563657758">telefonas</translation>
+<translation id="4193965531860883258">pratarmė</translation>
+<translation id="4201051445878709314">Rodyti ankstesnį mėnesį</translation>
+<translation id="421884353938374759">spalvos parinkiklis</translation>
+<translation id="4248100235867064564">meniu juosta</translation>
+<translation id="4360991593054037559">Įveskite galiojančią vertę. Dvi artimiausios vertės yra <ph name="VALID_VALUE_LOW" /> ir <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Klausimai ir atsakymai</translation>
+<translation id="4413860115965805769">meniu mygtukas</translation>
+<translation id="4444765639179266822">Tai tikriausiai reiškia: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">aiškinamojo terminų žodyno nuoroda</translation>
+<translation id="4522570452068850558">Išsami informacija</translation>
+<translation id="4542388879936266156">likęs laikas: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">forma</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Po „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">priedas</translation>
+<translation id="4718048029184481307">Leidžiama vaizdo vaizde režimu</translation>
+<translation id="4742539557769756338">viršelis</translation>
+<translation id="4748357248530471599">perjungti ekrano išpjovą į visą ekraną</translation>
+<translation id="4757246831282535685">skirtuko skydelis</translation>
+<translation id="4763480195061959176">vaizdo įrašas</translation>
+<translation id="479989351350248267">ieškoti</translation>
+<translation id="4812940957355064477">Įveskite skaičių.</translation>
+<translation id="4912536737030637138">bibliografijos įrašas</translation>
+<translation id="4975562563186953947">Pasirinkta: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Įjungti garsą</translation>
+<translation id="49969490063480558">Įveskite dalį po „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
+<translation id="5034860022980953847">eigos indikatorius</translation>
+<translation id="5090250355906949916">vaizdo įrašo laiko valdiklis</translation>
+<translation id="5093189678851173835">epigrafas</translation>
+<translation id="5117590920725113268">Rodyti kitą mėnesį</translation>
+<translation id="512758898067543763">eilutės antraštė</translation>
+<translation id="5143125788380636750">epilogas</translation>
+<translation id="5164977714490026579">Vertė turi būti <ph name="MINIMUM" /> arba didesnė.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Įveskite el. pašto adreso dalį iki „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
+<translation id="5334352251556557839">Nepavyko paleisti medijos.</translation>
+<translation id="5406322316791861025">iliustracija</translation>
+<translation id="5453733299334684579">medžio elementas</translation>
+<translation id="5466621249238537318">Pasirinkite bent vieną failą.</translation>
+<translation id="5468998798572797635">išeiti iš viso ekrano režimo</translation>
+<translation id="5516424706154626233">datos rinkiklis</translation>
+<translation id="5537725057119320332">Perduoti</translation>
+<translation id="5546461542133609677">įjungti garsą</translation>
+<translation id="5608153257855394627">paryškinti</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Dukart palieskite kairėn arba dešinėn, kad praleistumėte 10 sek.</translation>
+<translation id="5631759159893697722">santrauka</translation>
+<translation id="5643186887447432888">mygtukas</translation>
+<translation id="5677946354068040947">daugiau parinkčių</translation>
+<translation id="576709008726043716">įžanga</translation>
+<translation id="57838592816432529">Nutildyti</translation>
+<translation id="5860033963881614850">Išjungta</translation>
+<translation id="588258955323874662">Visas ekranas</translation>
+<translation id="5888666972993069672">Dabar perduodama į „<ph name="DEVICE_FRIENDLY_NAME" />“</translation>
+<translation id="591047860372322273">paieškos laukelis</translation>
+<translation id="5939518447894949180">Nustatyti iš naujo</translation>
+<translation id="5966707198760109579">Savaitė</translation>
+<translation id="5987525920412732405">sukimo mygtukas</translation>
+<translation id="6011459053400940133">garsumo šliaužiklis</translation>
+<translation id="6015796118275082299">Metai</translation>
+<translation id="6023896073578205740">sąrašo laukelis</translation>
+<translation id="6150588977291308318">bibliografija</translation>
+<translation id="6164829606128959761">matuoklis</translation>
+<translation id="6166809985690652833">baigiamasis žodis</translation>
+<translation id="6209276755895393898">Tai tikriausiai yra: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">aiškinamasis terminų žodynas</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Išeiti iš vaizdo vaizde</translation>
+<translation id="6398862346408813489">Rodyti mėnesio pasirinkimo skydelį</translation>
+<translation id="6404546809543547843">garso laiko valdiklis</translation>
+<translation id="6443871981718447451">rodyti subtitrų meniu</translation>
+<translation id="6453774872122745852">padėka</translation>
+<translation id="6475115390776617481">tiesioginė veikla</translation>
+<translation id="648732519525291180">laiko rinkiklis</translation>
+<translation id="6550675742724504774">Parinktys</translation>
+<translation id="6572309429103589720">Netinkama gramatika</translation>
+<translation id="658823671542763450">įjungti viso ekrano režimą</translation>
+<translation id="663493177488814956">sklaidos kanalas</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Išvalyti</translation>
+<translation id="668171684555832681">Kita...</translation>
+<translation id="6692633176391053278">ėjimo aukštyn / žemyn valdiklis</translation>
+<translation id="6709570249143506788">Prasta atkūrimo kokybė</translation>
+<translation id="6755330956360078551">patarimas</translation>
+<translation id="6790428901817661496">Žaisti</translation>
+<translation id="6820355525329141109">Nepavyko įkelti papildinio.</translation>
+<translation id="6820615603175220800">bibliografijos nuoroda</translation>
+<translation id="6843725295806269523">nutildyti</translation>
+<translation id="6885760532393684712">katalogas</translation>
+<translation id="689129560213475294">informacija apie leidimą</translation>
+<translation id="6934078000481955284">citata</translation>
+<translation id="693476918119313863">antraštė</translation>
+<translation id="6941933287844615239">atsisiųsti mediją</translation>
+<translation id="6981594929165378967">įterpimas</translation>
+<translation id="6989848892321993519">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate 1 simbolį).</translation>
+<translation id="7034405885550056553">pasiūlymas</translation>
+<translation id="709897737746224366">Priderinkite reikalaujamą formatą.</translation>
+<translation id="7118469954320184356">Nepasiekiamas joks aprašas.</translation>
+<translation id="7139483182332611405">įvadas</translation>
+<translation id="7214187073215825913">turinio informacija</translation>
+<translation id="7263440858009898357">Pasirinkite sąraše pateiktą elementą.</translation>
+<translation id="727747134524199931">stulpelio antraštė</translation>
+<translation id="7320576522385648310">rašoma į buferį</translation>
+<translation id="7353453495576941748">padėka</translation>
+<translation id="7364796246159120393">Pasirinkti failą</translation>
+<translation id="739024184232394898">Kita...</translation>
+<translation id="7405738980073107433">išnašos</translation>
+<translation id="7410239719251593705">Panašu, kad yra turinio suaugusiesiems. Nepasiekiamas joks aprašas.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">Tabuliavimo klavišas</translation>
+<translation id="7514365320538308">Atsisiųsti</translation>
+<translation id="7529102961911894712">atgalinė nuoroda</translation>
+<translation id="7533959249147584474">Nepažymėtas grafinis elementas</translation>
+<translation id="7647456547678091388">patarimas</translation>
+<translation id="7661956066982048809">grafikos dokumentas</translation>
+<translation id="7673697353781729403">Valandos</translation>
+<translation id="7681220483256441252">rodyklė</translation>
+<translation id="7740050170769002709">HTML turinys</translation>
+<translation id="7745230546936012372">Jei norite gauti trūkstamus vaizdų aprašus, atidarykite kontekstinį meniu.</translation>
+<translation id="7750228210027921155">Vaizdas vaizde</translation>
+<translation id="775297008183122718">Neteisingas įrašas</translation>
+<translation id="7789962463072032349">pristabdyti</translation>
+<translation id="7802800022689234070">paskelbimo trikampis</translation>
+<translation id="7888071071722539607">Į el. pašto adresą įtraukite „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ trūksta „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">skaidiklis</translation>
+<translation id="795667975304826397">Nepasirinktas joks failas</translation>
+<translation id="8053789581856978548">paieškos teksto laukas</translation>
+<translation id="8057695513531652401">pranešimas</translation>
+<translation id="8105797009065549151">pastabos nuoroda</translation>
+<translation id="811583516810654505">Gaunamas aprašas...</translation>
+<translation id="8117451130807776954">Ši savaitė</translation>
+<translation id="8199524924445686405">mmmm</translation>
+<translation id="8208673686607688524">vietos datos ir laiko rinkiklis</translation>
+<translation id="8261464734335370856">Netinkama rašyba</translation>
+<translation id="8284326494547611709">Subtitrai</translation>
+<translation id="8346634859695247203">skiltis</translation>
+<translation id="835897206747267392">Neteisinga vertė.</translation>
+<translation id="8403857369060869934">praėjęs laikas: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">dalis</translation>
+<translation id="8433900881053900389">įrankių juosta</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> failai (-ų)</translation>
+<translation id="8451268428117625855">Pasirinkite failą.</translation>
+<translation id="8461852803063341183">akutė</translation>
+<translation id="8474886197722836894">dedikacija</translation>
+<translation id="8531739829932800271">spaudos klaidų sąrašas</translation>
+<translation id="8534579021159131403">Minutės</translation>
+<translation id="8541249477527128034">medijos valdiklis</translation>
+<translation id="8550857728288566671">grafikos simbolis</translation>
+<translation id="8583702881314752957">apibrėžimų sąrašas</translation>
+<translation id="8597182159515967513">antraštė</translation>
+<translation id="860475260694818407">turinys</translation>
+<translation id="8613126697340063924">valdyti nuotolinį atkūrimą</translation>
+<translation id="862370744433916922">paantraštė</translation>
+<translation id="8711688047404765493">išvestis</translation>
+<translation id="8750798805984357768">Pasirinkite vieną iš šių parinkčių.</translation>
+<translation id="8808573423886751634">skyrius</translation>
+<translation id="8822203815165896261">kūrimo informacija</translation>
+<translation id="8845239796550121995">Dabar perduodama į TV</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Vaizdo įrašo atkūrimo klaida</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mėnuo</translation>
+<translation id="901493112792887934">dabartinis laikas sekundėmis</translation>
+<translation id="901834265349196618">El. paštas</translation>
+<translation id="9048119486235211610">naršymas</translation>
+<translation id="9062295712474918030">dokumentas</translation>
+<translation id="9093215626363556771">išeiti iš vaizdo vaizde</translation>
+<translation id="9108370397979208512">matematika</translation>
+<translation id="9132465097189459683">Kita...</translation>
+<translation id="9138385573473225930">įspėjimas</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, nuo <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Vaizdas vaizde</translation>
+<translation id="9168329111483466115">išnaša</translation>
+<translation id="954003015749068518">įeiti į vaizdą vaizde</translation>
+<translation id="966787709310836684">meniu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..bd7c1b3d103
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_lv.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lv">
+<translation id="1018939186200882850">izvēlnes vienums</translation>
+<translation id="10623998915015855">pārslēgšanas poga</translation>
+<translation id="1088086359088493902">Sekundes</translation>
+<translation id="1171774979989969504">Ievadiet e-pasta adresi.</translation>
+<translation id="1178581264944972037">Pauzēt</translation>
+<translation id="1188858454923323853">papildu</translation>
+<translation id="1206619573307042055">slīdošais teksts</translation>
+<translation id="1206693055195146388">slīdnis</translation>
+<translation id="1211441953136645838">beigu vēre</translation>
+<translation id="1281252709823657822">dialoglodziņš</translation>
+<translation id="1335095011850992622">pateicības</translation>
+<translation id="1342835525016946179">raksts</translation>
+<translation id="1359897965706325498">reklāmkarogs</translation>
+<translation id="1589122976691792535">reģions</translation>
+<translation id="1591562245178063882">Šis mēnesis</translation>
+<translation id="1637811476055996098">Izvēlēties failus</translation>
+<translation id="1650423536718072820">izvilkuma citāts</translation>
+<translation id="1727886345390570319">paslēpt slēgto parakstu izvēlni</translation>
+<translation id="1729654308190250600">Lūdzu, ievadiet e-pasta adresi.</translation>
+<translation id="1758486001363313524">Cits...</translation>
+<translation id="1806710327868736751">brīdinājuma dialoglodziņš</translation>
+<translation id="1821985195704844674">koka režģis</translation>
+<translation id="1822429046913737220">priekšpusdienā/pēcpusdienā</translation>
+<translation id="1832974991323546415">atskaņot attālinātā ierīcē</translation>
+<translation id="190587075670221089">dzēšana</translation>
+<translation id="1907737156431278478">piemērs</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">statuss</translation>
+<translation id="1938124657309484470">Vērtībai ir jābūt “<ph name="MAXIMUM_DATE_OR_TIME" />” vai agrākam datumam vai laikam.</translation>
+<translation id="1946271899482435442">Rādīt datumu atlasītāju</translation>
+<translation id="1993104285338243655">Mainīts uz spoguļošanu</translation>
+<translation id="2060505056492490888">Punkts (<ph name="DOT" />) atrodas nepareizā vietā (<ph name="INVALIDDOMAIN" />).</translation>
+<translation id="2148716181193084225">Šodien</translation>
+<translation id="2158401438286456825">lapu saraksts</translation>
+<translation id="2226276347425096477">Lūdzu, saīsiniet šo tekstu līdz <ph name="MAX_CHARACTERS" /> vai mazāk zīmēm (pašreiz tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
+<translation id="2246498165605549352">Lokāls fails</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. nedēļa, <ph name="YEAR" />. gads</translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />. ieraksts</translation>
+<translation id="2291999235780842123">izvēles rūtiņa</translation>
+<translation id="2311842470354187719">lappuses pārtraukums</translation>
+<translation id="2335594187091864976">datuma un laika atlasītājs</translation>
+<translation id="245932805758469625">atlikušais video laiks sekundēs</translation>
+<translation id="248395913932153421">Diena</translation>
+<translation id="2507943997699731163">Aizpildiet šo lauku.</translation>
+<translation id="2508569020611168319">ciļņu saraksts</translation>
+<translation id="2561842179657104141">rādīt citas multivides vadīklas</translation>
+<translation id="2572483411312390101">atskaņot</translation>
+<translation id="2613802280814924224">Lūdzu, ievadiet derīgu vērtību. Tuvākā derīgā vērtība ir <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Iesniegt</translation>
+<translation id="2657045182931379222">grafiskais objekts</translation>
+<translation id="2674318244760992338">kājene</translation>
+<translation id="2709516037105925701">Automātiskā aizpilde</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">komentāri</translation>
+<translation id="2746543609216772311">Vērtībai ir jābūt “<ph name="MINIMUM_DATE_OR_TIME" />” vai vēlākam datumam vai laikam.</translation>
+<translation id="2759744352195237655">uznirstoša poga</translation>
+<translation id="2761667185364618470">Lai turpinātu, atzīmējiet šo izvēles rūtiņu.</translation>
+<translation id="2844350028562914727">detalizēta informācija</translation>
+<translation id="2896972712917208084">radiopogu grupa</translation>
+<translation id="2908441821576996758">Lūdzu, ievadiet ar komatu atdalītu e-pasta adrešu sarakstu.</translation>
+<translation id="2940813599313844715">objekts</translation>
+<translation id="3040011195152428237">saite</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Lūdzu, ievadiet derīgu vērtību. Šis lauks nav pabeigts, vai tajā ir norādīts nederīgs datums.</translation>
+<translation id="3078740164268491126">tabula</translation>
+<translation id="3086746722712840547">piezīme</translation>
+<translation id="310520048233152454">Ievadiet URL.</translation>
+<translation id="3175736971608411871">taimeris</translation>
+<translation id="3199563858620722075">kombinētais lodziņš</translation>
+<translation id="3450233048674729344">Vērtībai ir jābūt mazākai vai vienādai ar <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definīcija</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" />. virsraksts</translation>
+<translation id="3670698553867754311">nedēļas atlasītājs</translation>
+<translation id="3685101356851116974">Attēls bez iezīmes</translation>
+<translation id="3706100364254443312">slēdzis</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Iziet no režīma “Attēls attēlā”</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">vārds</translation>
+<translation id="3822383571486410024">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
+<translation id="383465348367842624">Daļā, kas atrodas pirms zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3846214748874656680">Aizvērt pilnekrāna režīmu</translation>
+<translation id="3889183436948184105">pārskatīšana</translation>
+<translation id="3920932319529768807">nobeigums</translation>
+<translation id="3924558731517983934">lietojumprogramma</translation>
+<translation id="3944740393230681990">prologs</translation>
+<translation id="3960700977367013758">ritjosla</translation>
+<translation id="4103419683916926126">Milisekundes</translation>
+<translation id="4151657705144244502">grafiskais elements</translation>
+<translation id="4160057747563657758">tālrunis</translation>
+<translation id="4193965531860883258">priekšvārds</translation>
+<translation id="4201051445878709314">Rādīt iepriekšējo mēnesi</translation>
+<translation id="421884353938374759">krāsu izvēle</translation>
+<translation id="4248100235867064564">izvēļņu josla</translation>
+<translation id="4360991593054037559">Lūdzu, ievadiet derīgu vērtību. Divas tuvākās derīgās vērtības ir <ph name="VALID_VALUE_LOW" /> un <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Jautājumi un atbildes</translation>
+<translation id="4413860115965805769">izvēlnes poga</translation>
+<translation id="4444765639179266822">Izklausās: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">atsauce uz glosāriju</translation>
+<translation id="4522570452068850558">Informācija</translation>
+<translation id="4542388879936266156">atlikušais laiks: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">veidlapa</translation>
+<translation id="4661075872484491155">koks</translation>
+<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">pielikums</translation>
+<translation id="4718048029184481307">Tiek atskaņots režīmā “Attēls attēlā”</translation>
+<translation id="4742539557769756338">vāks</translation>
+<translation id="4748357248530471599">pārslēdz displeja izgriezuma apgabalu pilnekrāna režīmā</translation>
+<translation id="4757246831282535685">ciļņu panelis</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">meklēt</translation>
+<translation id="4812940957355064477">Lūdzu, ievadiet skaitli.</translation>
+<translation id="4912536737030637138">bibliogrāfijas ieraksts</translation>
+<translation id="4975562563186953947">Atlasīti <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Ieslēgt skaņu</translation>
+<translation id="49969490063480558">Lūdzu, ievadiet daļu, kas atrodas aiz zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
+<translation id="5034860022980953847">norises indikators</translation>
+<translation id="5090250355906949916">video laika skalas slīdnis</translation>
+<translation id="5093189678851173835">epigrāfs</translation>
+<translation id="5117590920725113268">Rādīt nākamo mēnesi</translation>
+<translation id="512758898067543763">rindas virsraksts</translation>
+<translation id="5143125788380636750">epilogs</translation>
+<translation id="5164977714490026579">Vērtībai ir jābūt lielākai vai vienādai ar <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Lūdzu, ievadiet daļu, kas atrodas pirms zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
+<translation id="5334352251556557839">Nevar atskaņot multividi.</translation>
+<translation id="5406322316791861025">cipars</translation>
+<translation id="5453733299334684579">koka vienums</translation>
+<translation id="5466621249238537318">Lūdzu, atlasiet vienu vai vairākus failus.</translation>
+<translation id="5468998798572797635">iziet no pilnekrāna režīma</translation>
+<translation id="5516424706154626233">datuma atlasītājs</translation>
+<translation id="5537725057119320332">Apraidīt</translation>
+<translation id="5546461542133609677">rādīt</translation>
+<translation id="5608153257855394627">izcēlums</translation>
+<translation id="561939826962581046">laiks</translation>
+<translation id="5630795885300617244">Veiciet dubultskārienu pa labi vai pa kreisi, lai izlaistu 10 s.</translation>
+<translation id="5631759159893697722">kopsavilkums</translation>
+<translation id="5643186887447432888">poga</translation>
+<translation id="5677946354068040947">citas opcijas</translation>
+<translation id="576709008726043716">ievads</translation>
+<translation id="57838592816432529">Izslēgt skaņu</translation>
+<translation id="5860033963881614850">Izsl.</translation>
+<translation id="588258955323874662">Pilnekrāna</translation>
+<translation id="5888666972993069672">Notiek apraide šajā ierīcē: <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">meklēšanas lodziņš</translation>
+<translation id="5939518447894949180">Atiestatīt</translation>
+<translation id="5966707198760109579">Nedēļa</translation>
+<translation id="5987525920412732405">skaitītājpoga</translation>
+<translation id="6011459053400940133">skaļuma slīdnis</translation>
+<translation id="6015796118275082299">Gads</translation>
+<translation id="6023896073578205740">sarakstlodziņš</translation>
+<translation id="6150588977291308318">bibliogrāfija</translation>
+<translation id="6164829606128959761">mērītājs</translation>
+<translation id="6166809985690652833">pēcvārds</translation>
+<translation id="6209276755895393898">Šķiet, ka tas ir: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosārijs</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Aizvērt režīmu “Attēls attēlā”</translation>
+<translation id="6398862346408813489">Rādīt mēneša atlases paneli</translation>
+<translation id="6404546809543547843">audio laika skalas slīdnis</translation>
+<translation id="6443871981718447451">rādīt slēgto parakstu izvēlni</translation>
+<translation id="6453774872122745852">pateicības</translation>
+<translation id="6475115390776617481">tiešsaistes klātbūtne</translation>
+<translation id="648732519525291180">laika atlasītājs</translation>
+<translation id="6550675742724504774">Opcijas</translation>
+<translation id="6572309429103589720">Nederīga gramatika</translation>
+<translation id="658823671542763450">atvērt pilnekrāna režīmā</translation>
+<translation id="663493177488814956">plūsma</translation>
+<translation id="6637586476836377253">žurnāls</translation>
+<translation id="6643016212128521049">Notīrīt</translation>
+<translation id="668171684555832681">Cits</translation>
+<translation id="6692633176391053278">pārslēdzējs</translation>
+<translation id="6709570249143506788">Slikta atskaņošanas kvalitāte</translation>
+<translation id="6755330956360078551">rīka padoms</translation>
+<translation id="6790428901817661496">Atskaņot</translation>
+<translation id="6820355525329141109">Nevarēja ielādēt spraudni.</translation>
+<translation id="6820615603175220800">bibliogrāfiskā atsauce</translation>
+<translation id="6843725295806269523">izslēgt skaņu</translation>
+<translation id="6885760532393684712">katalogs</translation>
+<translation id="689129560213475294">izdošanas ziņas</translation>
+<translation id="6934078000481955284">citāta bloks</translation>
+<translation id="693476918119313863">galvene</translation>
+<translation id="6941933287844615239">lejupielādēt multivides failus</translation>
+<translation id="6981594929165378967">ievietošana</translation>
+<translation id="6989848892321993519">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver 1 rakstzīmi).</translation>
+<translation id="7034405885550056553">ieteikums</translation>
+<translation id="709897737746224366">Pieskaņojiet vērtību prasītajam formātam.</translation>
+<translation id="7118469954320184356">Nav apraksta.</translation>
+<translation id="7139483182332611405">ievadraksts</translation>
+<translation id="7214187073215825913">informācija par saturu</translation>
+<translation id="7263440858009898357">Atlasiet vienumu sarakstā.</translation>
+<translation id="727747134524199931">slejas virsraksts</translation>
+<translation id="7320576522385648310">notiek ievietošana buferī</translation>
+<translation id="7353453495576941748">pateicība</translation>
+<translation id="7364796246159120393">Izvēlēties failu</translation>
+<translation id="739024184232394898">Cits...</translation>
+<translation id="7405738980073107433">beigu vēres</translation>
+<translation id="7410239719251593705">Šķiet, ka šis ir pieaugušajiem paredzēts saturs. Nav apraksta</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">cilne</translation>
+<translation id="7514365320538308">Lejupielādēt</translation>
+<translation id="7529102961911894712">atpakaļsaite</translation>
+<translation id="7533959249147584474">Grafika bez atzīmes</translation>
+<translation id="7647456547678091388">padoms</translation>
+<translation id="7661956066982048809">grafikas dokuments</translation>
+<translation id="7673697353781729403">Stundas</translation>
+<translation id="7681220483256441252">rādītājs</translation>
+<translation id="7740050170769002709">HTML saturs</translation>
+<translation id="7745230546936012372">Lai iegūtu trūkstošos attēlu aprakstus, atveriet kontekstizvēlni.</translation>
+<translation id="7750228210027921155">Attēls attēlā</translation>
+<translation id="775297008183122718">Nederīgs ieraksts</translation>
+<translation id="7789962463072032349">pauzēt</translation>
+<translation id="7802800022689234070">satura atklāšanas trijstūris</translation>
+<translation id="7888071071722539607">E-pasta adresē ietveriet zīmi <ph name="ATSIGN" />. Adresē “<ph name="INVALIDADDRESS" />” trūkst zīmes <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">sadalītājs</translation>
+<translation id="795667975304826397">Nav izvēlēts neviens fails</translation>
+<translation id="8053789581856978548">meklēšanas teksta lauks</translation>
+<translation id="8057695513531652401">paziņojums</translation>
+<translation id="8105797009065549151">vēres atsauce</translation>
+<translation id="811583516810654505">Notiek apraksta iegūšana...</translation>
+<translation id="8117451130807776954">Šī nedēļa</translation>
+<translation id="8199524924445686405">gggg</translation>
+<translation id="8208673686607688524">vietējā datuma un laika atlasītājs</translation>
+<translation id="8261464734335370856">Nederīga pareizrakstība</translation>
+<translation id="8284326494547611709">Paraksti</translation>
+<translation id="8346634859695247203">sadaļa</translation>
+<translation id="835897206747267392">Nederīga vērtība.</translation>
+<translation id="8403857369060869934">pagājušais laiks: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">daļa</translation>
+<translation id="8433900881053900389">rīkjosla</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
+<translation id="8451268428117625855">Lūdzu, atlasiet failu.</translation>
+<translation id="8461852803063341183">radiopoga</translation>
+<translation id="8474886197722836894">veltījums</translation>
+<translation id="8531739829932800271">iespiedkļūdu saraksts</translation>
+<translation id="8534579021159131403">Minūtes</translation>
+<translation id="8541249477527128034">multivides vadība</translation>
+<translation id="8550857728288566671">grafiskais simbols</translation>
+<translation id="8583702881314752957">definīciju saraksts</translation>
+<translation id="8597182159515967513">Virsraksts</translation>
+<translation id="860475260694818407">satura rādītājs</translation>
+<translation id="8613126697340063924">kontrolēt attālināto atskaņošanu</translation>
+<translation id="862370744433916922">apakšvirsraksts</translation>
+<translation id="8711688047404765493">izvade</translation>
+<translation id="8750798805984357768">Lūdzu, atlasiet vienu no šīm opcijām.</translation>
+<translation id="8808573423886751634">nodaļa</translation>
+<translation id="8822203815165896261">satura izveides informācija</translation>
+<translation id="8845239796550121995">Pašlaik notiek apraide uz jūsu TV</translation>
+<translation id="8851136666856101339">galvenais</translation>
+<translation id="8875657656876809964">Videoklipa atskaņošanas kļūda</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mēnesis</translation>
+<translation id="901493112792887934">pašreizējais laiks sekundēs</translation>
+<translation id="901834265349196618">e-pasts</translation>
+<translation id="9048119486235211610">navigācija</translation>
+<translation id="9062295712474918030">dokuments</translation>
+<translation id="9093215626363556771">aizvērt režīmu “attēls attēlā”</translation>
+<translation id="9108370397979208512">matemātiska izteiksme</translation>
+<translation id="9132465097189459683">Cits...</translation>
+<translation id="9138385573473225930">brīdinājums</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, sākot no: <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Attēls attēlā</translation>
+<translation id="9168329111483466115">vēre</translation>
+<translation id="954003015749068518">atvērt režīmu “attēls attēlā”</translation>
+<translation id="966787709310836684">izvēlne</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..0004021cc8c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ml.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ml">
+<translation id="1018939186200882850">മെനു ഇനം</translation>
+<translation id="10623998915015855">ടോഗിൾ ബട്ടൺ</translation>
+<translation id="1088086359088493902">സെക്കൻഡ്</translation>
+<translation id="1171774979989969504">ദയവായി ഒരു ഇമെയില്‍ വിലാസം നല്‍കുക.</translation>
+<translation id="1178581264944972037">അല്പംനിര്‍ത്തൂ</translation>
+<translation id="1188858454923323853">കോംപ്ലിമെന്ററി</translation>
+<translation id="1206619573307042055">മാർക്യൂ</translation>
+<translation id="1206693055195146388">സ്ലൈഡർ</translation>
+<translation id="1211441953136645838">അന്തിമ കുറിപ്പ്</translation>
+<translation id="1281252709823657822">ഡയലോഗ്</translation>
+<translation id="1335095011850992622">ക്രെഡിറ്റുകൾ</translation>
+<translation id="1342835525016946179">ലേഖനം</translation>
+<translation id="1359897965706325498">ബാനർ</translation>
+<translation id="1589122976691792535">പ്രദേശം</translation>
+<translation id="1591562245178063882">ഈ മാസം</translation>
+<translation id="1637811476055996098">ഫയലുകൾ തിരഞ്ഞെടുക്കുക</translation>
+<translation id="1650423536718072820">പുൾക്വോട്ട്</translation>
+<translation id="1727886345390570319">സബ്‌ടൈറ്റിൽ മെനു മറയ്ക്കുക</translation>
+<translation id="1729654308190250600">ശൂന്യമായിടാതെ, ഇമെയിൽ വിലാസം നൽകുക.</translation>
+<translation id="1758486001363313524">മറ്റുള്ളവ...</translation>
+<translation id="1806710327868736751">അലേർട്ട്_ഡയലോഗ്</translation>
+<translation id="1821985195704844674">ട്രീ ഗ്രിഡ്</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">റിമോട്ട് ഉപകരണത്തിൽ പ്ലേ ചെയ്യുക</translation>
+<translation id="190587075670221089">ഇല്ലാതാക്കൽ</translation>
+<translation id="1907737156431278478">ഉദാഹരണം</translation>
+<translation id="1921819250265091946">തീയതി</translation>
+<translation id="1930711995431081526">നില</translation>
+<translation id="1938124657309484470">മൂല്യം <ph name="MAXIMUM_DATE_OR_TIME" /> എന്നതോ അതിനുമുമ്പുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
+<translation id="1946271899482435442">തീയതി തിരഞ്ഞെടുക്കൽ കാണിക്കുക</translation>
+<translation id="1993104285338243655">മിററിംഗിലേക്ക് മാറി</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />', '<ph name="INVALIDDOMAIN" />' എന്നതിൽ തെറ്റായ സ്ഥാനത്താണ് ഉപയോഗിച്ചിരിക്കുന്നത്.</translation>
+<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="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ട്രാക്ക് <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">ചെക്ക്‌ ബോക്‌സ്</translation>
+<translation id="2311842470354187719">പേജ് ബ്രേക്ക്</translation>
+<translation id="2335594187091864976">തീയതിയും സമയ പിക്കറും</translation>
+<translation id="245932805758469625">വീഡിയോയുടെ അവശേഷിക്കുന്ന സമയം സെക്കൻഡിൽ</translation>
+<translation id="248395913932153421">ദിവസം</translation>
+<translation id="2507943997699731163">ദയവായി ഈ ഫീല്‍ഡ് പൂരിപ്പിക്കുക.</translation>
+<translation id="2508569020611168319">ടാബ് ലിസ്റ്റ്</translation>
+<translation id="2561842179657104141">കൂടുതൽ മീഡിയ നിയന്ത്രണങ്ങൾ കാണിക്കുക</translation>
+<translation id="2572483411312390101">പ്ലേ ചെയ്യുക</translation>
+<translation id="2613802280814924224">സാധുവായ ഒരു മൂല്യം നൽകുക. ഏറ്റവുമടുത്ത സാധുവായ മൂല്യം <ph name="VALID_VALUE" /> ആണ്.</translation>
+<translation id="2653659639078652383">സമര്‍പ്പിക്കൂ</translation>
+<translation id="2657045182931379222">ഗ്രാഫിക്‌സ് ഒബ്‌ജക്‌റ്റ്</translation>
+<translation id="2674318244760992338">അടിക്കുറിപ്പ്</translation>
+<translation id="2709516037105925701">സ്വയമേവ പൂരിപ്പിക്കൽ</translation>
+<translation id="2723001399770238859">ഓഡിയോ</translation>
+<translation id="2725963129578236554">കമന്റുകൾ</translation>
+<translation id="2746543609216772311">മൂല്യം <ph name="MINIMUM_DATE_OR_TIME" /> എന്നതോ അതിനുശേഷമുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
+<translation id="2759744352195237655">പോപ്പ് അപ്പ് ബട്ടൺ</translation>
+<translation id="2761667185364618470">നിങ്ങള്‍ തുടരാന്‍ താല്‍പ്പര്യപ്പെടുന്നെങ്കില്‍ ഈ ബോക്സ് ദയവായി പരിശോധിക്കുക.</translation>
+<translation id="2844350028562914727">വിശദാംശങ്ങൾ</translation>
+<translation id="2896972712917208084">റേഡിയോ ഗ്രൂപ്പ്</translation>
+<translation id="2908441821576996758">ഇമെയില്‍ വിലാസങ്ങളുടെ കോമയാല്‍ വേര്‍തിരിച്ച ഒരു പട്ടിക ദയവായി നല്‍കുക.</translation>
+<translation id="2940813599313844715">ഒബ്‌ജക്‌റ്റ്</translation>
+<translation id="3040011195152428237">ലിങ്ക്</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">ഒരു സാധുതയുള്ള മൂല്യം നൽകുക. ഫീൽഡ് പൂർണ്ണമല്ല അല്ലെങ്കിൽ അസാധുവായ തീയതിയിലുള്ളതാണ്.</translation>
+<translation id="3078740164268491126">പട്ടിക</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">ദയവായി ഒരു URL നല്‍കുക.</translation>
+<translation id="3175736971608411871">ടൈമർ</translation>
+<translation id="3199563858620722075">കോമ്പോ ബോക്‌സ്</translation>
+<translation id="3450233048674729344">മൂല്യം <ph name="MAXIMUM" /> എന്നതില്‍ കുറവോ സമമോ ആയിരിക്കണം.</translation>
+<translation id="3486220673238053218">നിർവചനം</translation>
+<translation id="3557673793733683882">തലക്കെട്ട് <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">ആഴ്‌ച പിക്കർ</translation>
+<translation id="3685101356851116974">ലേബൽ ചെയ്യാത്ത ചിത്രം</translation>
+<translation id="3706100364254443312">സ്വിച്ച്</translation>
+<translation id="3732799496749320381">മാസം</translation>
+<translation id="3754210790023674521">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിന് പുറത്ത് കടക്കുക</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">പദം</translation>
+<translation id="3822383571486410024">ഈ ടെക്‌സ്റ്റിന്‍റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> അല്ലെങ്കിൽ അതിൽക്കൂടുതൽ പ്രതീകങ്ങൾ നൽകി കൂട്ടുക. (നിങ്ങൾ നിലവിൽ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങളാണ് ഉപയോഗിക്കുന്നത്).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഒരു ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="3846214748874656680">പൂർണ്ണ സ്‌ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക</translation>
+<translation id="3889183436948184105">പുനഃപരിശോധന</translation>
+<translation id="3920932319529768807">ഉപസംഹാരം</translation>
+<translation id="3924558731517983934">ആപ്പ്</translation>
+<translation id="3944740393230681990">ആമുഖം</translation>
+<translation id="3960700977367013758">സ്‌ക്രോൾ ബാർ</translation>
+<translation id="4103419683916926126">മില്ലിസെക്കൻഡ്</translation>
+<translation id="4151657705144244502">ഗ്രാഫിക്</translation>
+<translation id="4160057747563657758">ടെലിഫോൺ</translation>
+<translation id="4193965531860883258">മുഖവുര</translation>
+<translation id="4201051445878709314">മുമ്പത്തെ മാസം കാണിക്കുക</translation>
+<translation id="421884353938374759">വർണ്ണ പിക്കർ</translation>
+<translation id="4248100235867064564">മെനു ബാർ</translation>
+<translation id="4360991593054037559">സാധുവായ മൂല്യം നൽകുക. സാധുവായ ഏറ്റവുമടുത്ത രണ്ട് മൂല്യങ്ങൾ <ph name="VALID_VALUE_LOW" />, <ph name="VALID_VALUE_HIGHER" /> എന്നിവയാണ്.</translation>
+<translation id="4384583879834880242">ചോദ്യോത്തരം</translation>
+<translation id="4413860115965805769">മെനു ബട്ടൺ</translation>
+<translation id="4444765639179266822">പറയാൻ ദൃശ്യമാകുന്നത്: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">പദസഞ്ചയ റെഫറൻസ്</translation>
+<translation id="4522570452068850558">വിശദാംശങ്ങൾ‌</translation>
+<translation id="4542388879936266156">അവശേഷിക്കുന്ന സമയം: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ഫോം</translation>
+<translation id="4661075872484491155">ട്രീ</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="4668956016107839909">അനുബന്ധം</translation>
+<translation id="4718048029184481307">ചിത്രത്തിനുള്ളിൽ ചിത്രത്തിൽ പ്ലേ ചെയ്യുന്നു</translation>
+<translation id="4742539557769756338">കവർ</translation>
+<translation id="4748357248530471599">ഡിസ്‌പ്ലേ കട്ടൗട്ട് പൂർണ്ണ സ്ക്രീൻ മാറ്റുക</translation>
+<translation id="4757246831282535685">ടാബ് പാനൽ</translation>
+<translation id="4763480195061959176">വീഡിയോ</translation>
+<translation id="479989351350248267">തിരയുക</translation>
+<translation id="4812940957355064477">ഒരു നമ്പർ നൽകുക.</translation>
+<translation id="4912536737030637138">ഗ്രന്ഥസൂചി എൻട്രി</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> തിരഞ്ഞെടുത്തു</translation>
+<translation id="4992066212339426712">അൺമ്യൂട്ടുചെയ്യുക</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
+<translation id="5034860022980953847">'പ്രോഗ്രസ്' ഇൻഡിക്കേറ്റർ</translation>
+<translation id="5090250355906949916">വീഡിയോ ടൈം സ്‌ക്രബർ</translation>
+<translation id="5093189678851173835">ശിലാലേഖ</translation>
+<translation id="5117590920725113268">അടുത്ത മാസം കാണിക്കുക</translation>
+<translation id="512758898067543763">വരി ശീർഷകം</translation>
+<translation id="5143125788380636750">ഉപസംഹാരം</translation>
+<translation id="5164977714490026579">മൂല്യം <ph name="MINIMUM" /> എന്നതില്‍ കൂടുതലോ സമമോ ആയിരിക്കണം.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
+<translation id="5334352251556557839">മീഡിയ പ്ലേ ചെയ്യാനായില്ല.</translation>
+<translation id="5406322316791861025">ആകാരം</translation>
+<translation id="5453733299334684579">ട്രീ ഇനം</translation>
+<translation id="5466621249238537318">ഒന്നോ അതില്‍ക്കൂടുതലോ ഫയലുകള്‍ ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="5468998798572797635">പൂർണ്ണ സ്‌ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക</translation>
+<translation id="5516424706154626233">തീയതി പിക്കർ</translation>
+<translation id="5537725057119320332">കാസ്‌റ്റ് ചെയ്യുക</translation>
+<translation id="5546461542133609677">ശബ്‌ദമുള്ളതാക്കുക</translation>
+<translation id="5608153257855394627">ഹൈലൈറ്റ് ചെയ്‌തത്</translation>
+<translation id="561939826962581046">സമയം</translation>
+<translation id="5630795885300617244">10 സെക്കൻഡ് ഒഴിവാക്കാൻ ഇടത്തോ വലത്തോ ഡബിൾ ടാപ്പ് ചെയ്യുക</translation>
+<translation id="5631759159893697722">സംക്ഷേപം</translation>
+<translation id="5643186887447432888">ബട്ടൺ</translation>
+<translation id="5677946354068040947">കൂടുതൽ ഓപ്‌ഷനുകൾ</translation>
+<translation id="576709008726043716">ആമുഖം</translation>
+<translation id="57838592816432529">മ്യൂട്ട് ചെയ്യുക</translation>
+<translation id="5860033963881614850">ഓഫാക്കുക</translation>
+<translation id="588258955323874662">പൂര്‍‌ണ്ണസ്‌ക്രീന്‍</translation>
+<translation id="5888666972993069672"><ph name="DEVICE_FRIENDLY_NAME" /> എന്ന ഉപകരണത്തിലേക്ക് കാസ്‌റ്റുചെയ്യുന്നു</translation>
+<translation id="591047860372322273">സെർച്ച് ബോക്‌സ്</translation>
+<translation id="5939518447894949180">റീസെറ്റ് ചെയ്യുക</translation>
+<translation id="5966707198760109579">ആഴ്‌ച</translation>
+<translation id="5987525920412732405">സ്‌പിൻ ബട്ടൺ</translation>
+<translation id="6011459053400940133">വോളിയം സ്ലൈഡർ</translation>
+<translation id="6015796118275082299">വര്‍ഷം</translation>
+<translation id="6023896073578205740">ലിസ്റ്റ് ബോക്‌സ്</translation>
+<translation id="6150588977291308318">ഗ്രന്ഥസൂചി</translation>
+<translation id="6164829606128959761">മീറ്റർ</translation>
+<translation id="6166809985690652833">പിൻ കുറിപ്പ്</translation>
+<translation id="6209276755895393898">ഇങ്ങനെ ദൃശ്യമാകും: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">പദസഞ്ചയം</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിന് പുറത്ത് കടക്കുക</translation>
+<translation id="6398862346408813489">മാസം തിരഞ്ഞെടുക്കുന്ന പാനൽ കാണിക്കുക</translation>
+<translation id="6404546809543547843">ഓഡിയോ സമയ സ്‌ക്രബർ</translation>
+<translation id="6443871981718447451">സബ്‌ടൈറ്റിൽ മെനു കാണിക്കുക</translation>
+<translation id="6453774872122745852">കടപ്പാട്</translation>
+<translation id="6475115390776617481">തത്സമയ സാന്നിധ്യം</translation>
+<translation id="648732519525291180">സമയ പിക്കർ</translation>
+<translation id="6550675742724504774">ഓപ്ഷനുകൾ</translation>
+<translation id="6572309429103589720">അസാധുവായ വ്യാകരണം</translation>
+<translation id="658823671542763450">പൂർണ്ണ സ്‌ക്രീനിലേക്ക് പോവുക</translation>
+<translation id="663493177488814956">ഫീഡ്</translation>
+<translation id="6637586476836377253">ലോഗ്</translation>
+<translation id="6643016212128521049">മായ്‌ക്കുക</translation>
+<translation id="668171684555832681">മറ്റുള്ളവ...</translation>
+<translation id="6692633176391053278">സ്റ്റെപ്പർ</translation>
+<translation id="6709570249143506788">മോശം പ്ലേബാക്ക് നിലവാരം</translation>
+<translation id="6755330956360078551">ടൂൾടിപ്പ്</translation>
+<translation id="6790428901817661496">പ്ലേചെയ്യുക</translation>
+<translation id="6820355525329141109">പ്ലഗിൻ ലോഡ് ചെയ്യാനായില്ല.</translation>
+<translation id="6820615603175220800">ഗ്രന്ഥസൂചി റെഫറൻസ്</translation>
+<translation id="6843725295806269523">നിശബ്‌ദമാക്കുക</translation>
+<translation id="6885760532393684712">ഡയറക്‌റ്ററി</translation>
+<translation id="689129560213475294">അച്ചടിമുദ്ര</translation>
+<translation id="6934078000481955284">ബ്ലോക്ക്‌കോട്ട്</translation>
+<translation id="693476918119313863">തലക്കെട്ട്</translation>
+<translation id="6941933287844615239">മീഡിയ ഡൗൺലോഡ് ചെയ്യുക</translation>
+<translation id="6981594929165378967">ചേർക്കൽ</translation>
+<translation id="6989848892321993519">ഈ ടെക്‌സ്റ്റിന്‍റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> പ്രതീകങ്ങളോ അതിൽ കൂടുതലോ ആയി വർദ്ധിപ്പിക്കുക (നിങ്ങൾ നിലവിൽ ഒരു പ്രതീകം മാത്രമേ ഉപയോഗിക്കുന്നുള്ളൂ).</translation>
+<translation id="7034405885550056553">നിർദ്ദേശം</translation>
+<translation id="709897737746224366">അഭ്യര്‍ത്ഥി ച്ചഫോര്‍മാറ്റ് ദയവായി പൊരുത്തപ്പെടുത്തുക.</translation>
+<translation id="7118469954320184356">വിവരണം ലഭ്യമല്ല.</translation>
+<translation id="7139483182332611405">പീഠിക</translation>
+<translation id="7214187073215825913">ഉള്ളടക്ക വിവരങ്ങൾ</translation>
+<translation id="7263440858009898357">പട്ടികയിലെ ഒരു ഇനം ദയവായി തിരഞ്ഞെടുക്കുക</translation>
+<translation id="727747134524199931">കോളം പേര്</translation>
+<translation id="7320576522385648310">ബഫർ ചെയ്യൽ</translation>
+<translation id="7353453495576941748">ക്രെഡിറ്റ്</translation>
+<translation id="7364796246159120393">ഫയല്‍ തിരഞ്ഞെടുക്കൂ</translation>
+<translation id="739024184232394898">മറ്റുള്ളവ...</translation>
+<translation id="7405738980073107433">അന്തിമ കുറിപ്പുകൾ</translation>
+<translation id="7410239719251593705">മുതിർന്നവർക്കുള്ള ഉള്ളടക്കം അടങ്ങിയിരിക്കുന്നുണ്ടെന്ന് തോന്നുന്നു. വിവരണം ലഭ്യമല്ല.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">ടാബ്</translation>
+<translation id="7514365320538308">ഡൗൺലോഡ് ചെയ്യുക</translation>
+<translation id="7529102961911894712">ബാക്ക്‌ ലിങ്ക്</translation>
+<translation id="7533959249147584474">ലേബൽ ചെയ്യാത്ത ഗ്രാഫിക്</translation>
+<translation id="7647456547678091388">നുറുങ്ങ്</translation>
+<translation id="7661956066982048809">ഗ്രാഫിക്‌സ് ഡോക്യുമെന്റ്</translation>
+<translation id="7673697353781729403">മണിക്കൂര്‍‌</translation>
+<translation id="7681220483256441252">സൂചിക</translation>
+<translation id="7740050170769002709">HTML ഉള്ളടക്കം</translation>
+<translation id="7745230546936012372">വിട്ടുപോയ ചിത്ര വിവരണങ്ങൾ ലഭിക്കാൻ സന്ദർഭ മെനു തുറക്കുക.</translation>
+<translation id="7750228210027921155">ചിത്രത്തിനുള്ളിലെ ചിത്രം</translation>
+<translation id="775297008183122718">എൻട്രി അസാധുവാണ്</translation>
+<translation id="7789962463072032349">താല്‍‌ക്കാലികമായി നിര്‍‌ത്തുക</translation>
+<translation id="7802800022689234070">ഡിസ്‌ക്ലോഷർ ത്രികോണം</translation>
+<translation id="7888071071722539607">ഇമെയിൽ വിലാസത്തിൽ '<ph name="ATSIGN" />' ഉൾപ്പെടുത്തുക. '<ph name="INVALIDADDRESS" />' എന്നതിൽ ഒരു '<ph name="ATSIGN" />' കാണുന്നില്ല.</translation>
+<translation id="7891486169920085145">സ്‌പ്ലിറ്റർ</translation>
+<translation id="795667975304826397">ഒരു ഫയലും തിരഞ്ഞെടുത്തിട്ടില്ല</translation>
+<translation id="8053789581856978548">തിരയൽ ടെക്‌സ്റ്റ് ഫീൽഡ്</translation>
+<translation id="8057695513531652401">അറിയിപ്പ്</translation>
+<translation id="8105797009065549151">കുറിപ്പ് റെഫറൻസ്</translation>
+<translation id="811583516810654505">വിവരണം ലഭ്യമാക്കുന്നു...</translation>
+<translation id="8117451130807776954">ഈ ആഴ്‌ച</translation>
+<translation id="8199524924445686405">വർഷം</translation>
+<translation id="8208673686607688524">പ്രാദേശിക തീയതിയും സമയ പിക്കറും</translation>
+<translation id="8261464734335370856">അക്ഷരത്തെറ്റ്</translation>
+<translation id="8284326494547611709">അടിക്കുറിപ്പുകൾ</translation>
+<translation id="8346634859695247203">വിഭാഗം</translation>
+<translation id="835897206747267392">അസാധുവായ മൂല്യം.</translation>
+<translation id="8403857369060869934">കഴിഞ്ഞ സമയം: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">ഭാഗം</translation>
+<translation id="8433900881053900389">ടൂൾബാർ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ഫയലുകള്‍</translation>
+<translation id="8451268428117625855">ദയവായി ഒരു ഫയല്‍ തരം തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="8461852803063341183">റേഡിയോ ബട്ടൺ</translation>
+<translation id="8474886197722836894">സമർപ്പണം</translation>
+<translation id="8531739829932800271">സംശോധന പട്ടിക</translation>
+<translation id="8534579021159131403">മിനിറ്റ്</translation>
+<translation id="8541249477527128034">മീഡിയ നിയന്ത്രണം</translation>
+<translation id="8550857728288566671">ഗ്രാഫിക്സ് ചിഹ്നം</translation>
+<translation id="8583702881314752957">നിർവചന ലിസ്റ്റ്</translation>
+<translation id="8597182159515967513">തലക്കെട്ട്</translation>
+<translation id="860475260694818407">ഉള്ളടക്ക പട്ടിക</translation>
+<translation id="8613126697340063924">വിദൂര പ്ലേബാക്ക് നിയന്ത്രിക്കുക</translation>
+<translation id="862370744433916922">ഉപശീർഷകം</translation>
+<translation id="8711688047404765493">ഔട്ട്‌പുട്ട്</translation>
+<translation id="8750798805984357768">ഈ ഓപ്ഷനുകളിലൊന്ന് ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="8808573423886751634">അധ്യായം</translation>
+<translation id="8822203815165896261">രചനയുമായി ബന്ധപ്പെട്ട വിവരം</translation>
+<translation id="8845239796550121995">ഇപ്പോൾ നിങ്ങളുടെ ടിവിയിൽ കാസ്‌റ്റുചെയ്യുന്നു</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">വീഡിയോ പ്ലേബാക്ക് പിശക്</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">മാസം</translation>
+<translation id="901493112792887934">നിലവിലെ സമയം നിമിഷങ്ങളിൽ</translation>
+<translation id="901834265349196618">ഇമെയില്‍</translation>
+<translation id="9048119486235211610">നാവിഗേഷൻ</translation>
+<translation id="9062295712474918030">പ്രമാണം</translation>
+<translation id="9093215626363556771">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിന് പുറത്ത് കടക്കുക</translation>
+<translation id="9108370397979208512">മാത്ത്</translation>
+<translation id="9132465097189459683">മറ്റുള്ളവ...</translation>
+<translation id="9138385573473225930">അലേർട്ട്</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" />-ന് ആരംഭിക്കുന്നു</translation>
+<translation id="916607977885256133">ചിത്രത്തിനുള്ളിൽ ചിത്രം</translation>
+<translation id="9168329111483466115">അടിക്കുറിപ്പ്</translation>
+<translation id="954003015749068518">ചിത്രത്തിനുള്ളിലെ ചിത്രത്തിലേക്ക് പ്രവേശിക്കുക</translation>
+<translation id="966787709310836684">മെനു</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..874ad64d5ce
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_mr.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="mr">
+<translation id="1018939186200882850">मेनू आयटम</translation>
+<translation id="10623998915015855">टॉगल बटण</translation>
+<translation id="1088086359088493902">सेकंद</translation>
+<translation id="1171774979989969504">कृपया एक ईमेल ॲड्रेस एंटर करा.</translation>
+<translation id="1178581264944972037">विराम द्या</translation>
+<translation id="1188858454923323853">पूरक</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">स्लायडर</translation>
+<translation id="1211441953136645838">तळटीप</translation>
+<translation id="1281252709823657822">डायलॉग</translation>
+<translation id="1335095011850992622">श्रेय</translation>
+<translation id="1342835525016946179">लेख</translation>
+<translation id="1359897965706325498">बॅनर</translation>
+<translation id="1589122976691792535">प्रदेश</translation>
+<translation id="1591562245178063882">या महिन्यात</translation>
+<translation id="1637811476055996098">फायली निवडा</translation>
+<translation id="1650423536718072820">पुलकोट</translation>
+<translation id="1727886345390570319">सबटायटल मेनू लपवा</translation>
+<translation id="1729654308190250600">कृपया एक रिक्त नसलेला ईमेल ॲड्रेस एंटर करा.</translation>
+<translation id="1758486001363313524">अन्य...</translation>
+<translation id="1806710327868736751">सूचना_संवाद</translation>
+<translation id="1821985195704844674">ट्री ग्रीड</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">दूरस्थ डिव्हाइसवर प्ले करा</translation>
+<translation id="190587075670221089">हटवणे</translation>
+<translation id="1907737156431278478">उदाहरण</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">स्थिती</translation>
+<translation id="1938124657309484470">मूल्य <ph name="MAXIMUM_DATE_OR_TIME" /> किंवा आधीचे असणे आवश्यक आहे.</translation>
+<translation id="1946271899482435442">तारीख निवडक दाखवा</translation>
+<translation id="1993104285338243655">मिररिंगवर स्विच केले</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' '<ph name="INVALIDDOMAIN" />' मध्ये चुकीच्या स्थितीवर वापरले आहे.</translation>
+<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="2247351761944213033">आठवडा <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ट्रॅक <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">चेकबॉक्‍स</translation>
+<translation id="2311842470354187719">पेज ब्रेक</translation>
+<translation id="2335594187091864976">तारीख आणि वेळ निवडक</translation>
+<translation id="245932805758469625">व्हिडिओच्या शिल्लक सेकंदांची संख्या</translation>
+<translation id="248395913932153421">दिवस</translation>
+<translation id="2507943997699731163">कृपया हे फील्ड भरा.</translation>
+<translation id="2508569020611168319">टॅब सूची</translation>
+<translation id="2561842179657104141">आणखी मीडिया नियंत्रणे दर्शवा</translation>
+<translation id="2572483411312390101">प्ले करा</translation>
+<translation id="2613802280814924224">कृपया एक वैध मूल्य एंटर करा. जवळील वैध मूल्य <ph name="VALID_VALUE" /> आहे.</translation>
+<translation id="2653659639078652383">सबमिट करा</translation>
+<translation id="2657045182931379222">ग्राफिक्स ऑब्जेक्ट</translation>
+<translation id="2674318244760992338">अधोलेख</translation>
+<translation id="2709516037105925701">ऑटोफिल</translation>
+<translation id="2723001399770238859">ऑडिओ</translation>
+<translation id="2725963129578236554">टिप्पण्या</translation>
+<translation id="2746543609216772311">मूल्य <ph name="MINIMUM_DATE_OR_TIME" /> किंवा नंतरचे असणे आवश्यक आहे.</translation>
+<translation id="2759744352195237655">पॉप अप बटण</translation>
+<translation id="2761667185364618470">कृपया तुम्ही पुढे चालू ठेवू इच्छित असल्यास हा बॉक्स पहा.</translation>
+<translation id="2844350028562914727">तपशील</translation>
+<translation id="2896972712917208084">रेडिओ गट</translation>
+<translation id="2908441821576996758">कृपया ईमेल पत्त्यांची स्वल्पविरामाद्वारे विभक्त सूची एंटर करा.</translation>
+<translation id="2940813599313844715">ऑब्जेक्ट</translation>
+<translation id="3040011195152428237">लिंक</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">कृपया एक वैध मूल्य एंटर करा. फील्ड अपूर्ण आहे किंवा चुकीची तारीख आहे.</translation>
+<translation id="3078740164268491126">सारणी</translation>
+<translation id="3086746722712840547">टीप</translation>
+<translation id="310520048233152454">कृपया एखादी URL एंटर करा.</translation>
+<translation id="3175736971608411871">टायमर</translation>
+<translation id="3199563858620722075">काँबो बॉक्स</translation>
+<translation id="3450233048674729344">मूल्य <ph name="MAXIMUM" /> पेक्षा कमी किंवा समान असावे.</translation>
+<translation id="3486220673238053218">परिभाषा</translation>
+<translation id="3557673793733683882">शीर्षक <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">आठवडा पिकर</translation>
+<translation id="3685101356851116974">लेबल न केलेली इमेज</translation>
+<translation id="3706100364254443312">स्विच करा</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">चित्रात-चित्र मधून बाहेर पडा</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">संज्ञा</translation>
+<translation id="3822383571486410024">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (तुम्ही सध्‍या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' मागुन येणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
+<translation id="3846214748874656680">क्षेत्रेमधून बाहेर पडा</translation>
+<translation id="3889183436948184105">पुनरावृत्ती</translation>
+<translation id="3920932319529768807">निष्कर्ष</translation>
+<translation id="3924558731517983934">ॲप्लिकेशन</translation>
+<translation id="3944740393230681990">उपोद्घात</translation>
+<translation id="3960700977367013758">स्क्रोल बार</translation>
+<translation id="4103419683916926126">मिलिसेकंद</translation>
+<translation id="4151657705144244502">ग्राफिक</translation>
+<translation id="4160057747563657758">टेलिफोन</translation>
+<translation id="4193965531860883258">प्रस्तावना</translation>
+<translation id="4201051445878709314">मागील महिना दर्शवा</translation>
+<translation id="421884353938374759">रंग निवडक</translation>
+<translation id="4248100235867064564">मेनू बार</translation>
+<translation id="4360991593054037559">कृपया एक वैध मूल्य एंटर करा. दोन जवळील वैध मूल्ये <ph name="VALID_VALUE_LOW" /> आणि <ph name="VALID_VALUE_HIGHER" /> आहेत.</translation>
+<translation id="4384583879834880242">प्रश्नोत्तरे</translation>
+<translation id="4413860115965805769">मेनू बटण</translation>
+<translation id="4444765639179266822">असे म्हणत असल्याचे दिसत आहे: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">शब्दावली संदर्भ</translation>
+<translation id="4522570452068850558">तपशील</translation>
+<translation id="4542388879936266156">शिल्लक वेळ: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">फॉर्म</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे फॉलो करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
+<translation id="4668956016107839909">परिशिष्ट</translation>
+<translation id="4718048029184481307">चित्रात-चित्र मध्ये प्ले करत आहे</translation>
+<translation id="4742539557769756338">कव्हर</translation>
+<translation id="4748357248530471599">डिस्प्ले कटआउट फुलस्क्रीन टॉगल करा</translation>
+<translation id="4757246831282535685">टॅब पॅनेल</translation>
+<translation id="4763480195061959176">व्हिडिओ</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">कृपया एक नंबर एंटर करा.</translation>
+<translation id="4912536737030637138">ग्रंथसूची नोंद</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> निवडले</translation>
+<translation id="4992066212339426712">सशब्द करा</translation>
+<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' चे फॉलो करणारा भाग एंटर करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
+<translation id="5034860022980953847">प्रगती सूचक</translation>
+<translation id="5090250355906949916">व्हिडिओ वेळ स्क्रबर</translation>
+<translation id="5093189678851173835">बोधवाक्य</translation>
+<translation id="5117590920725113268">पुढील महिना दर्शवा</translation>
+<translation id="512758898067543763">पंक्ती शीर्षलेख</translation>
+<translation id="5143125788380636750">उपसंहार</translation>
+<translation id="5164977714490026579">मूल्य <ph name="MINIMUM" /> पेक्षा मोठे किंवा समान असावे.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' मागुन येणारा भाग एंटर करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
+<translation id="5334352251556557839">मीडिया प्ले करता आला नाही.</translation>
+<translation id="5406322316791861025">आकृती</translation>
+<translation id="5453733299334684579">ट्री आयटम</translation>
+<translation id="5466621249238537318">कृपया एक किंवा अधिक फायली निवडा.</translation>
+<translation id="5468998798572797635">पूर्ण स्क्रीनमधून निर्गमन करा</translation>
+<translation id="5516424706154626233">तारीख निवडक</translation>
+<translation id="5537725057119320332">कास्ट करा</translation>
+<translation id="5546461542133609677">सशब्द करा</translation>
+<translation id="5608153257855394627">हायलाइट</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">10 सेकंद वगळण्यासाठी डावीकडे किंवा उजवीकडे दोनदा टॅप करा</translation>
+<translation id="5631759159893697722">अमूर्त</translation>
+<translation id="5643186887447432888">बटण</translation>
+<translation id="5677946354068040947">अधिक पर्याय</translation>
+<translation id="576709008726043716">परिचय</translation>
+<translation id="57838592816432529">म्यूट करा</translation>
+<translation id="5860033963881614850">बंद</translation>
+<translation id="588258955323874662">क्षेत्रे</translation>
+<translation id="5888666972993069672">आता <ph name="DEVICE_FRIENDLY_NAME" /> वर कास्ट करत आहे</translation>
+<translation id="591047860372322273">सर्च बॉक्स</translation>
+<translation id="5939518447894949180">रीसेट करा</translation>
+<translation id="5966707198760109579">आठवडा</translation>
+<translation id="5987525920412732405">स्पिन बटण</translation>
+<translation id="6011459053400940133">व्हॉल्यूम स्लायडर</translation>
+<translation id="6015796118275082299">वर्ष</translation>
+<translation id="6023896073578205740">सूची बॉक्स</translation>
+<translation id="6150588977291308318">ग्रंथसूची</translation>
+<translation id="6164829606128959761">मीटर</translation>
+<translation id="6166809985690652833">अंतिम शब्द</translation>
+<translation id="6209276755895393898">असे असल्याचे दिसत आहे: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">शब्दावली</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">चित्रात-चित्र मधून बाहेर पडा</translation>
+<translation id="6398862346408813489">महिना निवड पॅनेल दाखवा</translation>
+<translation id="6404546809543547843">ऑडिओ वेळ स्क्रबर</translation>
+<translation id="6443871981718447451">सबटायटल मेनू दाखवा</translation>
+<translation id="6453774872122745852">श्रेयनिर्देश</translation>
+<translation id="6475115390776617481">लाइव्ह उपस्थिती</translation>
+<translation id="648732519525291180">वेळ निवडक</translation>
+<translation id="6550675742724504774">पर्याय</translation>
+<translation id="6572309429103589720">चुकीचे व्याकरण</translation>
+<translation id="658823671542763450">फुल स्क्रीन एंटर करा</translation>
+<translation id="663493177488814956">फीड</translation>
+<translation id="6637586476836377253">लॉग</translation>
+<translation id="6643016212128521049">साफ करा</translation>
+<translation id="668171684555832681">अन्य...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">खराब प्लेबॅक गुणवत्ता</translation>
+<translation id="6755330956360078551">टूलटिप</translation>
+<translation id="6790428901817661496">प्ले करा</translation>
+<translation id="6820355525329141109">प्लग-इन लोड करणे शक्य झाले नाही.</translation>
+<translation id="6820615603175220800">ग्रंथसूची संदर्भ</translation>
+<translation id="6843725295806269523">म्यूट करा</translation>
+<translation id="6885760532393684712">डिरेक्टरी</translation>
+<translation id="689129560213475294">बोधचिन्ह</translation>
+<translation id="6934078000481955284">ब्लॉककोट</translation>
+<translation id="693476918119313863">हेडर</translation>
+<translation id="6941933287844615239">मीडिया डाउनलोड करा</translation>
+<translation id="6981594929165378967">घालणे</translation>
+<translation id="6989848892321993519">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (तुम्ही सध्‍या 1 वर्ण वापरत आहात).</translation>
+<translation id="7034405885550056553">सूचना</translation>
+<translation id="709897737746224366">कृपया विनंती केलेले स्वरूपन जुळवा.</translation>
+<translation id="7118469954320184356">कोणतेही वर्णन उपलब्ध नाही.</translation>
+<translation id="7139483182332611405">प्रस्तावना</translation>
+<translation id="7214187073215825913">आशयाची माहिती</translation>
+<translation id="7263440858009898357">कृपया सूचीमधील आयटम निवडा.</translation>
+<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
+<translation id="7320576522385648310">बफर होत आहे</translation>
+<translation id="7353453495576941748">श्रेय</translation>
+<translation id="7364796246159120393">फाइल निवडा</translation>
+<translation id="739024184232394898">अन्य...</translation>
+<translation id="7405738980073107433">अंतिम नोंदी</translation>
+<translation id="7410239719251593705">प्रौढांसाठी असलेला आशय असल्याचे वाटत आहे. कोणतेही वर्णन उपलब्ध नाही.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">टॅब</translation>
+<translation id="7514365320538308">डाउनलोड करा</translation>
+<translation id="7529102961911894712">मागील लिंक</translation>
+<translation id="7533959249147584474">लेबल न केलेले ग्राफिक</translation>
+<translation id="7647456547678091388">टीप</translation>
+<translation id="7661956066982048809">ग्राफिक्स दस्तऐवज</translation>
+<translation id="7673697353781729403">तास</translation>
+<translation id="7681220483256441252">अनुक्रमणिका</translation>
+<translation id="7740050170769002709">HTML सामुग्री</translation>
+<translation id="7745230546936012372">नसलेले इमेज वर्णन मिळवण्यासाठी, संदर्भ मेनू उघडा.</translation>
+<translation id="7750228210027921155">चित्रात-चित्र</translation>
+<translation id="775297008183122718">अवैध प्रविष्टी</translation>
+<translation id="7789962463072032349">विराम द्या</translation>
+<translation id="7802800022689234070">त्रिकोण प्रकटन</translation>
+<translation id="7888071071722539607">कृपया ईमेल पत्त्यामध्ये '<ph name="ATSIGN" />' समाविष्ट करा. '<ph name="INVALIDADDRESS" />' '<ph name="ATSIGN" />' गमावत आहे.</translation>
+<translation id="7891486169920085145">विभाजक</translation>
+<translation id="795667975304826397">कोणतीही फाइल निवडलेली नाही</translation>
+<translation id="8053789581856978548">मजकूर फील्ड दर्शवा</translation>
+<translation id="8057695513531652401">सूचना</translation>
+<translation id="8105797009065549151">टीप संदर्भ</translation>
+<translation id="811583516810654505">वर्णन मिळवत आहे...</translation>
+<translation id="8117451130807776954">या आठवड्यात</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">स्थानिक तारीख आणि वेळ पिकर</translation>
+<translation id="8261464734335370856">चुकीचे शब्दलेखन</translation>
+<translation id="8284326494547611709">मथळे</translation>
+<translation id="8346634859695247203">विभाग</translation>
+<translation id="835897206747267392">चुकीचे मूल्य.</translation>
+<translation id="8403857369060869934">गेलेला वेळ: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">भाग</translation>
+<translation id="8433900881053900389">टूलबार</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फायली</translation>
+<translation id="8451268428117625855">कृपया एखादी फाइल निवडा.</translation>
+<translation id="8461852803063341183">रेडिओ बटण</translation>
+<translation id="8474886197722836894">अर्पणपत्रिका</translation>
+<translation id="8531739829932800271">शुद्धिपत्रक</translation>
+<translation id="8534579021159131403">मिनिटे</translation>
+<translation id="8541249477527128034">माध्यम नियंत्रण</translation>
+<translation id="8550857728288566671">ग्राफिक्स चिन्ह</translation>
+<translation id="8583702881314752957">परिभाषा सूची</translation>
+<translation id="8597182159515967513">शीर्षलेख</translation>
+<translation id="860475260694818407">अनुक्रमणिका</translation>
+<translation id="8613126697340063924">दूरस्थ प्लेबॅक नियंत्रित करा</translation>
+<translation id="862370744433916922">उपशीर्षक</translation>
+<translation id="8711688047404765493">आउटपुट</translation>
+<translation id="8750798805984357768">कृपया या पर्यायांपैकी एक निवडा.</translation>
+<translation id="8808573423886751634">प्रकरण</translation>
+<translation id="8822203815165896261">लेखकासंबंधित माहिती</translation>
+<translation id="8845239796550121995">आता तुमच्या टिव्हीवर कास्ट करत आहे</translation>
+<translation id="8851136666856101339">मुख्य</translation>
+<translation id="8875657656876809964">व्हिडिओ प्लेबॅक एरर</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">महिना</translation>
+<translation id="901493112792887934">वर्तमान वेळ सेकंदांमध्ये</translation>
+<translation id="901834265349196618">ईमेल</translation>
+<translation id="9048119486235211610">नेव्हिगेशन</translation>
+<translation id="9062295712474918030">दस्तऐवज</translation>
+<translation id="9093215626363556771">चित्रात-चित्र मधून बाहेर पडा</translation>
+<translation id="9108370397979208512">गणित</translation>
+<translation id="9132465097189459683">अन्य...</translation>
+<translation id="9138385573473225930">सूचना</translation>
+<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> रोजी प्रारंभ होणारा, <ph name="WEEK" /></translation>
+<translation id="916607977885256133">चित्रात-चित्र</translation>
+<translation id="9168329111483466115">तळटीप</translation>
+<translation id="954003015749068518">चित्रात-चित्र एंटर करा</translation>
+<translation id="966787709310836684">मेनू</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..af549a720fa
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ms.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ms">
+<translation id="1018939186200882850">item menu</translation>
+<translation id="10623998915015855">butang togol</translation>
+<translation id="1088086359088493902">Saat</translation>
+<translation id="1171774979989969504">Sila masukkan alamat e-mel.</translation>
+<translation id="1178581264944972037">Jeda</translation>
+<translation id="1188858454923323853">pelengkap</translation>
+<translation id="1206619573307042055">marki</translation>
+<translation id="1206693055195146388">peluncur</translation>
+<translation id="1211441953136645838">nota hujung</translation>
+<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">kredit</translation>
+<translation id="1342835525016946179">artikel</translation>
+<translation id="1359897965706325498">sepanduk</translation>
+<translation id="1589122976691792535">wilayah</translation>
+<translation id="1591562245178063882">Bulan ini</translation>
+<translation id="1637811476055996098">Pilih Fail</translation>
+<translation id="1650423536718072820">petikan tarik keluar</translation>
+<translation id="1727886345390570319">sembunyikan menu sari kata</translation>
+<translation id="1729654308190250600">Sila masukkan alamat e-mel bukan kosong.</translation>
+<translation id="1758486001363313524">Lain-lain...</translation>
+<translation id="1806710327868736751">dialog_makluman</translation>
+<translation id="1821985195704844674">grid pohon</translation>
+<translation id="1822429046913737220">PG / P/M</translation>
+<translation id="1832974991323546415">main pada peranti jauh</translation>
+<translation id="190587075670221089">pemadaman</translation>
+<translation id="1907737156431278478">contoh</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Nilai mestilah <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
+<translation id="1946271899482435442">Tunjukkan pemilih tarikh</translation>
+<translation id="1993104285338243655">Beralih kepada pencerminan</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' digunakan pada kedudukan yang salah dalam '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2158401438286456825">senarai halaman</translation>
+<translation id="2226276347425096477">Sila pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> aksara atau kurang (anda kini menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
+<translation id="2246498165605549352">Fail Setempat</translation>
+<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Lagu <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">kotak pilihan</translation>
+<translation id="2311842470354187719">pemisah halaman</translation>
+<translation id="2335594187091864976">pemilih tarikh dan masa</translation>
+<translation id="245932805758469625">bilangan saat baki video</translation>
+<translation id="248395913932153421">Hari</translation>
+<translation id="2507943997699731163">Sila isikan medan ini.</translation>
+<translation id="2508569020611168319">senarai tab</translation>
+<translation id="2561842179657104141">tunjukkan lagi kawalan media</translation>
+<translation id="2572483411312390101">main</translation>
+<translation id="2613802280814924224">Sila masukkan nilai yang sah. Nilai sah yang terdekat ialah <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Serah</translation>
+<translation id="2657045182931379222">objek grafik</translation>
+<translation id="2674318244760992338">pembawah</translation>
+<translation id="2709516037105925701">Autoisi</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">ulasan</translation>
+<translation id="2746543609216772311">Nilai mestilah <ph name="MINIMUM_DATE_OR_TIME" /> atau kemudian.</translation>
+<translation id="2759744352195237655">butang timbul</translation>
+<translation id="2761667185364618470">Sila tandakan kotak ini jika anda mahu teruskan.</translation>
+<translation id="2844350028562914727">butiran</translation>
+<translation id="2896972712917208084">kumpulan radio</translation>
+<translation id="2908441821576996758">Sila masukkan senarai alamat e-mel yang dipisahkan dengan koma.</translation>
+<translation id="2940813599313844715">objek</translation>
+<translation id="3040011195152428237">pautan</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Sila masukkan nilai yang sah. Medan tidak lengkap atau mengandungi tarikh yang tidak sah.</translation>
+<translation id="3078740164268491126">jadual</translation>
+<translation id="3086746722712840547">nota</translation>
+<translation id="310520048233152454">Sila masukkan URL.</translation>
+<translation id="3175736971608411871">pemasa</translation>
+<translation id="3199563858620722075">kotak kombo</translation>
+<translation id="3450233048674729344">Nilai mestilah kurang daripada atau sama dengan <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">takrif</translation>
+<translation id="3557673793733683882">pengepala <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">pemilih minggu</translation>
+<translation id="3685101356851116974">Imej tidak berlabel</translation>
+<translation id="3706100364254443312">tukar</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Keluar daripada gambar dalam gambar</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">istilah</translation>
+<translation id="3822383571486410024">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
+<translation id="383465348367842624">Bahagian yang diikuti oleh '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">Keluar dari skrin penuh</translation>
+<translation id="3889183436948184105">semakan</translation>
+<translation id="3920932319529768807">kesimpulan</translation>
+<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">bar tatal</translation>
+<translation id="4103419683916926126">Milisaat</translation>
+<translation id="4151657705144244502">grafik</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">kata pengantar</translation>
+<translation id="4201051445878709314">Tunjukkan bulan sebelumnya</translation>
+<translation id="421884353938374759">pemilih warna</translation>
+<translation id="4248100235867064564">bar menu</translation>
+<translation id="4360991593054037559">Sila masukkan nilai yang sah. Dua nilai sah yang terdekat ialah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Soal Jawab</translation>
+<translation id="4413860115965805769">butang menu</translation>
+<translation id="4444765639179266822">Nampaknya menyatakan: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">rujukan glosari</translation>
+<translation id="4522570452068850558">Butiran</translation>
+<translation id="4542388879936266156">masa yang tinggal: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">borang</translation>
+<translation id="4661075872484491155">pohon</translation>
+<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">lampiran</translation>
+<translation id="4718048029184481307">Memainkan video dalam gambar dalam gambar</translation>
+<translation id="4742539557769756338">muka depan</translation>
+<translation id="4748357248530471599">togol skrin penuh potongan paparan</translation>
+<translation id="4757246831282535685">panel tab</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Sila masukkan nombor.</translation>
+<translation id="4912536737030637138">masukan bibliografi</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
+<translation id="4992066212339426712">Nyahredam</translation>
+<translation id="49969490063480558">Sila masukkan bahagian selepas '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5034860022980953847">penunjuk kemajuan</translation>
+<translation id="5090250355906949916">pembersih masa video</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Tunjukkan bulan seterusnya</translation>
+<translation id="512758898067543763">pengepala baris</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Nilai mesti lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Sila masukkan bahagian diikuti oleh '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5334352251556557839">Tidak dapat memainkan media.</translation>
+<translation id="5406322316791861025">angka</translation>
+<translation id="5453733299334684579">item pohon</translation>
+<translation id="5466621249238537318">Sila pilih satu fail atau lebih.</translation>
+<translation id="5468998798572797635">keluar daripada skrin penuh</translation>
+<translation id="5516424706154626233">pemilih tarikh</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">nyahredam</translation>
+<translation id="5608153257855394627">sorotan</translation>
+<translation id="561939826962581046">masa</translation>
+<translation id="5630795885300617244">Ketik dua kali ke kiri atau kanan untuk melangkau 10s</translation>
+<translation id="5631759159893697722">abstrak</translation>
+<translation id="5643186887447432888">butang</translation>
+<translation id="5677946354068040947">lagi pilihan</translation>
+<translation id="576709008726043716">pengenalan</translation>
+<translation id="57838592816432529">Redam</translation>
+<translation id="5860033963881614850">Dimatikan</translation>
+<translation id="588258955323874662">Skrin penuh</translation>
+<translation id="5888666972993069672">Sekarang menghantar ke <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">kotak carian</translation>
+<translation id="5939518447894949180">Tetapkan semula</translation>
+<translation id="5966707198760109579">Minggu</translation>
+<translation id="5987525920412732405">butang putar</translation>
+<translation id="6011459053400940133">peluncur kelantangan</translation>
+<translation id="6015796118275082299">Tahun</translation>
+<translation id="6023896073578205740">kotak senarai</translation>
+<translation id="6150588977291308318">bibliografi</translation>
+<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">kata hujungan</translation>
+<translation id="6209276755895393898">Nampak seperti: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosari</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Keluar daripada Gambar dalam Gambar</translation>
+<translation id="6398862346408813489">Tunjukkan panel pilihan bulan</translation>
+<translation id="6404546809543547843">pembersih masa audio</translation>
+<translation id="6443871981718447451">tunjukkan menu sari kata</translation>
+<translation id="6453774872122745852">perakuan</translation>
+<translation id="6475115390776617481">kehadiran langsung</translation>
+<translation id="648732519525291180">pemilih masa</translation>
+<translation id="6550675742724504774">Pilihan</translation>
+<translation id="6572309429103589720">Tatabahasa tidak sah</translation>
+<translation id="658823671542763450">memasuki skrin penuh</translation>
+<translation id="663493177488814956">suapan</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Kosongkan</translation>
+<translation id="668171684555832681">Lain-lain...</translation>
+<translation id="6692633176391053278">pelangkah</translation>
+<translation id="6709570249143506788">Mutu main balik teruk</translation>
+<translation id="6755330956360078551">tip alat</translation>
+<translation id="6790428901817661496">Mainkan</translation>
+<translation id="6820355525329141109">Tidak dapat memuatkan pemalam.</translation>
+<translation id="6820615603175220800">rujukan bibliografi</translation>
+<translation id="6843725295806269523">redam</translation>
+<translation id="6885760532393684712">direktori</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">petikan blok</translation>
+<translation id="693476918119313863">pengepala</translation>
+<translation id="6941933287844615239">muat turun media</translation>
+<translation id="6981594929165378967">penyisipan</translation>
+<translation id="6989848892321993519">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan 1 aksara).</translation>
+<translation id="7034405885550056553">cadangan</translation>
+<translation id="709897737746224366">Sila padankan dengan format yang diminta.</translation>
+<translation id="7118469954320184356">Perihalan tidak tersedia.</translation>
+<translation id="7139483182332611405">kata penghantar</translation>
+<translation id="7214187073215825913">maklumat kandungan</translation>
+<translation id="7263440858009898357">Sila pilih item dalam senarai.</translation>
+<translation id="727747134524199931">pengepala lajur</translation>
+<translation id="7320576522385648310">menimbal</translation>
+<translation id="7353453495576941748">kredit</translation>
+<translation id="7364796246159120393">Pilih Fail</translation>
+<translation id="739024184232394898">Lain-lain...</translation>
+<translation id="7405738980073107433">nota hujung</translation>
+<translation id="7410239719251593705">Nampaknya mengandungi kandungan dewasa. Perihalan tidak tersedia.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Muat Turun</translation>
+<translation id="7529102961911894712">pautan balik</translation>
+<translation id="7533959249147584474">Grafik tidak berlabel</translation>
+<translation id="7647456547678091388">petua</translation>
+<translation id="7661956066982048809">dokumen grafik</translation>
+<translation id="7673697353781729403">Jam</translation>
+<translation id="7681220483256441252">indeks</translation>
+<translation id="7740050170769002709">Kandungan HTML</translation>
+<translation id="7745230546936012372">Untuk mendapatkan perihalan imej yang tiada, buka menu konteks.</translation>
+<translation id="7750228210027921155">Gambar dalam gambar</translation>
+<translation id="775297008183122718">Entri tidak sah</translation>
+<translation id="7789962463072032349">jeda</translation>
+<translation id="7802800022689234070">segi tiga pendedahan</translation>
+<translation id="7888071071722539607">Sila masukkan '<ph name="ATSIGN" />' dalam alamat e-mel. '<ph name="INVALIDADDRESS" />' tiada '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">pemisah</translation>
+<translation id="795667975304826397">Tiada fail dipilih</translation>
+<translation id="8053789581856978548">medan teks carian</translation>
+<translation id="8057695513531652401">notis</translation>
+<translation id="8105797009065549151">rujukan nota</translation>
+<translation id="811583516810654505">Mendapatkan perihalan...</translation>
+<translation id="8117451130807776954">Minggu ini</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">pemilih tarikh dan masa setempat</translation>
+<translation id="8261464734335370856">Ejaan tidak sah</translation>
+<translation id="8284326494547611709">Kapsyen</translation>
+<translation id="8346634859695247203">bahagian</translation>
+<translation id="835897206747267392">Nilai tidak sah.</translation>
+<translation id="8403857369060869934">masa berlalu: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">bahagian</translation>
+<translation id="8433900881053900389">bar alat</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fail</translation>
+<translation id="8451268428117625855">Sila pilih fail.</translation>
+<translation id="8461852803063341183">butang radio</translation>
+<translation id="8474886197722836894">dedikasi</translation>
+<translation id="8531739829932800271">ralat</translation>
+<translation id="8534579021159131403">Minit</translation>
+<translation id="8541249477527128034">kawalan media</translation>
+<translation id="8550857728288566671">simbol grafik</translation>
+<translation id="8583702881314752957">senarai takrif</translation>
+<translation id="8597182159515967513">tajuk</translation>
+<translation id="860475260694818407">isi kandungan</translation>
+<translation id="8613126697340063924">kawal main balik jauh</translation>
+<translation id="862370744433916922">sari kata</translation>
+<translation id="8711688047404765493">output</translation>
+<translation id="8750798805984357768">Sila pilih salah satu pilihan ini.</translation>
+<translation id="8808573423886751634">bab</translation>
+<translation id="8822203815165896261">maklumat pengarangan</translation>
+<translation id="8845239796550121995">Menghantar ke TV anda sekarang</translation>
+<translation id="8851136666856101339">utama</translation>
+<translation id="8875657656876809964">Ralat main balik video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Bulan</translation>
+<translation id="901493112792887934">masa semasa dalam saat</translation>
+<translation id="901834265349196618">e-mel</translation>
+<translation id="9048119486235211610">navigasi</translation>
+<translation id="9062295712474918030">dokumen</translation>
+<translation id="9093215626363556771">keluar daripada gambar dalam gambar</translation>
+<translation id="9108370397979208512">matematik</translation>
+<translation id="9132465097189459683">Lain-lain...</translation>
+<translation id="9138385573473225930">makluman</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, bermula pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Gambar dalam Gambar</translation>
+<translation id="9168329111483466115">nota kaki</translation>
+<translation id="954003015749068518">masuk ke gambar dalam gambar</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..d5821c882cc
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_nl.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="nl">
+<translation id="1018939186200882850">menu-item</translation>
+<translation id="10623998915015855">schakelknop</translation>
+<translation id="1088086359088493902">Seconden</translation>
+<translation id="1171774979989969504">Geef een e-mailadres op.</translation>
+<translation id="1178581264944972037">Onderbreken</translation>
+<translation id="1188858454923323853">aanvullend</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">schuifregelaar</translation>
+<translation id="1211441953136645838">eindnoot</translation>
+<translation id="1281252709823657822">dialoogvenster</translation>
+<translation id="1335095011850992622">bronvermelding</translation>
+<translation id="1342835525016946179">artikel</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">regio</translation>
+<translation id="1591562245178063882">Deze maand</translation>
+<translation id="1637811476055996098">Bestanden kiezen</translation>
+<translation id="1650423536718072820">pullquote</translation>
+<translation id="1727886345390570319">ondertitelingsmenu verbergen</translation>
+<translation id="1729654308190250600">Geef een e-mailadres op.</translation>
+<translation id="1758486001363313524">Anders...</translation>
+<translation id="1806710327868736751">dialoogvenster voor meldingen</translation>
+<translation id="1821985195704844674">boomstructuur</translation>
+<translation id="1822429046913737220">a.m./p.m.</translation>
+<translation id="1832974991323546415">afspelen op extern apparaat</translation>
+<translation id="190587075670221089">verwijdering</translation>
+<translation id="1907737156431278478">voorbeeld</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Waarde moet <ph name="MAXIMUM_DATE_OR_TIME" /> of eerder zijn.</translation>
+<translation id="1946271899482435442">Datumkiezer weergeven</translation>
+<translation id="1993104285338243655">Overgeschakeld naar mirroring</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' wordt op een verkeerde positie gebruikt in '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Vandaag</translation>
+<translation id="2158401438286456825">paginalijst</translation>
+<translation id="2226276347425096477">Kort deze tekst in tot <ph name="MAX_CHARACTERS" /> tekens of minder (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
+<translation id="2246498165605549352">Lokaal bestand</translation>
+<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Track <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">selectievakje</translation>
+<translation id="2311842470354187719">pagina-einde</translation>
+<translation id="2335594187091864976">datum- en tijdkiezer</translation>
+<translation id="245932805758469625">aantal seconden van resterende video</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="2507943997699731163">Vul dit veld in.</translation>
+<translation id="2508569020611168319">tabbladlijst</translation>
+<translation id="2561842179657104141">meer mediabedieningselementen weergeven</translation>
+<translation id="2572483411312390101">afspelen</translation>
+<translation id="2613802280814924224">Geef een geldige waarde op. De dichtstbijzijnde geldige waarde is <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Verzenden</translation>
+<translation id="2657045182931379222">grafisch object</translation>
+<translation id="2674318244760992338">voettekst</translation>
+<translation id="2709516037105925701">Automatisch aanvullen</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">reacties</translation>
+<translation id="2746543609216772311">Waarde moet <ph name="MINIMUM_DATE_OR_TIME" /> of later zijn.</translation>
+<translation id="2759744352195237655">pop-upknop</translation>
+<translation id="2761667185364618470">Vink dit selectievakje aan als je wilt doorgaan.</translation>
+<translation id="2844350028562914727">details</translation>
+<translation id="2896972712917208084">groep met keuzerondjes</translation>
+<translation id="2908441821576996758">Voer een door komma's gescheiden lijst met e-mailadressen in.</translation>
+<translation id="2940813599313844715">object</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Voer een geldige waarde in. Het veld is onvolledig of bevat een ongeldige datum.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">opmerking</translation>
+<translation id="310520048233152454">Geef een URL op.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">keuzelijst met invoervak</translation>
+<translation id="3450233048674729344">Waarde moet kleiner dan of gelijk zijn aan <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definitie</translation>
+<translation id="3557673793733683882">koptekst <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">weekkiezer</translation>
+<translation id="3685101356851116974">Ongelabelde afbeelding</translation>
+<translation id="3706100364254443312">schakelaar</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Scherm-in-scherm afsluiten</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">term</translation>
+<translation id="3822383571486410024">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
+<translation id="383465348367842624">Het naamgedeelte vóór '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
+<translation id="3846214748874656680">Volledig scherm sluiten</translation>
+<translation id="3889183436948184105">revisie</translation>
+<translation id="3920932319529768807">conclusie</translation>
+<translation id="3924558731517983934">app</translation>
+<translation id="3944740393230681990">proloog</translation>
+<translation id="3960700977367013758">scrollbar</translation>
+<translation id="4103419683916926126">Milliseconden</translation>
+<translation id="4151657705144244502">afbeelding</translation>
+<translation id="4160057747563657758">telefoon</translation>
+<translation id="4193965531860883258">voorwoord</translation>
+<translation id="4201051445878709314">Vorige maand weergeven</translation>
+<translation id="421884353938374759">kleurkiezer</translation>
+<translation id="4248100235867064564">menubalk</translation>
+<translation id="4360991593054037559">Geef een geldige waarde op. De twee dichtstbijzijnde geldige waarden zijn <ph name="VALID_VALUE_LOW" /> en <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
+<translation id="4413860115965805769">menuknop</translation>
+<translation id="4444765639179266822">Lijkt het volgende te zeggen: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">woordenlijstreferentie</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">resterende tijd: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulier</translation>
+<translation id="4661075872484491155">structuur</translation>
+<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
+<translation id="4668956016107839909">bijlage</translation>
+<translation id="4718048029184481307">Beeld-in-beeld afspelen</translation>
+<translation id="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">volledig scherm met display-cutout schakelen</translation>
+<translation id="4757246831282535685">deelvenster met tabblad</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">zoeken</translation>
+<translation id="4812940957355064477">Voer een getal in.</translation>
+<translation id="4912536737030637138">bibliografievermelding</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> geselecteerd</translation>
+<translation id="4992066212339426712">Dempen opheffen</translation>
+<translation id="49969490063480558">Geef een adresgedeelte op na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
+<translation id="5034860022980953847">voortgangsindicator</translation>
+<translation id="5090250355906949916">scrollbar met tijd van de video</translation>
+<translation id="5093189678851173835">epigraaf</translation>
+<translation id="5117590920725113268">Volgende maand weergeven</translation>
+<translation id="512758898067543763">rijkop</translation>
+<translation id="5143125788380636750">epiloog</translation>
+<translation id="5164977714490026579">Waarde moet groter dan of gelijk zijn aan <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Geef een naamgedeelte op, gevolgd door '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
+<translation id="5334352251556557839">Kan media niet afspelen.</translation>
+<translation id="5406322316791861025">figuur</translation>
+<translation id="5453733299334684579">item in boomstructuur</translation>
+<translation id="5466621249238537318">Selecteer een of meer bestanden.</translation>
+<translation id="5468998798572797635">volledig scherm sluiten</translation>
+<translation id="5516424706154626233">datumkiezer</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">dempen opheffen</translation>
+<translation id="5608153257855394627">markeren</translation>
+<translation id="561939826962581046">tijd</translation>
+<translation id="5630795885300617244">Dubbeltik links of rechts om 10 seconden over te slaan</translation>
+<translation id="5631759159893697722">uittreksel</translation>
+<translation id="5643186887447432888">knop</translation>
+<translation id="5677946354068040947">meer opties</translation>
+<translation id="576709008726043716">inleiding</translation>
+<translation id="57838592816432529">Dempen</translation>
+<translation id="5860033963881614850">Uit</translation>
+<translation id="588258955323874662">Volledig scherm</translation>
+<translation id="5888666972993069672">Wordt nu gecast naar <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">zoekvak</translation>
+<translation id="5939518447894949180">Resetten</translation>
+<translation id="5966707198760109579">Week</translation>
+<translation id="5987525920412732405">draaiknop</translation>
+<translation id="6011459053400940133">volumeregelaar</translation>
+<translation id="6015796118275082299">Jaar</translation>
+<translation id="6023896073578205740">keuzelijst</translation>
+<translation id="6150588977291308318">bibliografie</translation>
+<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">nawoord</translation>
+<translation id="6209276755895393898">Lijkt het volgende te zijn: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">woordenlijst</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Scherm-in-scherm afsluiten</translation>
+<translation id="6398862346408813489">Deelvenster voor maandselectie weergeven</translation>
+<translation id="6404546809543547843">scrollbar met audiotijd</translation>
+<translation id="6443871981718447451">ondertitelingsmenu weergeven</translation>
+<translation id="6453774872122745852">dankwoord</translation>
+<translation id="6475115390776617481">live aanwezigheid</translation>
+<translation id="648732519525291180">tijdkiezer</translation>
+<translation id="6550675742724504774">Opties</translation>
+<translation id="6572309429103589720">Ongeldige grammatica</translation>
+<translation id="658823671542763450">volledig scherm openen</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">logboek</translation>
+<translation id="6643016212128521049">Wissen</translation>
+<translation id="668171684555832681">Anders...</translation>
+<translation id="6692633176391053278">stappenregelaar</translation>
+<translation id="6709570249143506788">Slechte afspeelkwaliteit</translation>
+<translation id="6755330956360078551">knopinfo</translation>
+<translation id="6790428901817661496">Spelen</translation>
+<translation id="6820355525329141109">Kan plug-in niet laden.</translation>
+<translation id="6820615603175220800">bibliografiereferentie</translation>
+<translation id="6843725295806269523">dempen</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="689129560213475294">colofon</translation>
+<translation id="6934078000481955284">blok met geciteerde tekst</translation>
+<translation id="693476918119313863">koptekst</translation>
+<translation id="6941933287844615239">media downloaden</translation>
+<translation id="6981594929165378967">invoeging</translation>
+<translation id="6989848892321993519">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel één teken).</translation>
+<translation id="7034405885550056553">suggestie</translation>
+<translation id="709897737746224366">Zorg dat de indeling voldoet aan de gevraagde indeling.</translation>
+<translation id="7118469954320184356">Geen beschrijving beschikbaar.</translation>
+<translation id="7139483182332611405">voorwoord</translation>
+<translation id="7214187073215825913">Gegevens over de content</translation>
+<translation id="7263440858009898357">Selecteer een item in de lijst.</translation>
+<translation id="727747134524199931">kolomkop</translation>
+<translation id="7320576522385648310">bufferen</translation>
+<translation id="7353453495576941748">bronvermelding</translation>
+<translation id="7364796246159120393">Bestand kiezen</translation>
+<translation id="739024184232394898">Anders...</translation>
+<translation id="7405738980073107433">eindnoten</translation>
+<translation id="7410239719251593705">Lijkt content voor volwassenen te bevatten. Geen beschrijving beschikbaar.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Downloaden</translation>
+<translation id="7529102961911894712">back link</translation>
+<translation id="7533959249147584474">Ongelabelde afbeelding</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafisch document</translation>
+<translation id="7673697353781729403">Uur</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">HTML-content</translation>
+<translation id="7745230546936012372">Als je ontbrekende afbeeldingsbeschrijvingen wilt ophalen, open je het contextmenu.</translation>
+<translation id="7750228210027921155">Scherm-in-scherm</translation>
+<translation id="775297008183122718">Ongeldige invoer</translation>
+<translation id="7789962463072032349">onderbreken</translation>
+<translation id="7802800022689234070">driehoek voor samen-/uitvouwen</translation>
+<translation id="7888071071722539607">Gebruik een '<ph name="ATSIGN" />' in het e-mailadres. In '<ph name="INVALIDADDRESS" />' ontbreekt een '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">splitser</translation>
+<translation id="795667975304826397">Geen bestand gekozen</translation>
+<translation id="8053789581856978548">zoektekstveld</translation>
+<translation id="8057695513531652401">kennisgeving</translation>
+<translation id="8105797009065549151">opmerkingsreferentie</translation>
+<translation id="811583516810654505">Beschrijving ophalen…</translation>
+<translation id="8117451130807776954">Deze week</translation>
+<translation id="8199524924445686405">jjjj</translation>
+<translation id="8208673686607688524">lokale datum- en tijdkiezer</translation>
+<translation id="8261464734335370856">Ongeldige spelling</translation>
+<translation id="8284326494547611709">Ondertiteling</translation>
+<translation id="8346634859695247203">sectie</translation>
+<translation id="835897206747267392">Ongeldige waarde.</translation>
+<translation id="8403857369060869934">verstreken tijd: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">deel</translation>
+<translation id="8433900881053900389">werkbalk</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> bestanden</translation>
+<translation id="8451268428117625855">Selecteer een bestand.</translation>
+<translation id="8461852803063341183">keuzerondje</translation>
+<translation id="8474886197722836894">opgedragen aan</translation>
+<translation id="8531739829932800271">drukfouten</translation>
+<translation id="8534579021159131403">Minuten</translation>
+<translation id="8541249477527128034">mediacontrole</translation>
+<translation id="8550857728288566671">grafisch symbool</translation>
+<translation id="8583702881314752957">definitielijst</translation>
+<translation id="8597182159515967513">kop</translation>
+<translation id="860475260694818407">inhoudsopgave</translation>
+<translation id="8613126697340063924">afspelen bedienen op afstand</translation>
+<translation id="862370744433916922">ondertitel</translation>
+<translation id="8711688047404765493">uitvoer</translation>
+<translation id="8750798805984357768">Selecteer een van deze opties.</translation>
+<translation id="8808573423886751634">hoofdstuk</translation>
+<translation id="8822203815165896261">informatie over auteur</translation>
+<translation id="8845239796550121995">Wordt nu gecast naar je tv</translation>
+<translation id="8851136666856101339">hoofd</translation>
+<translation id="8875657656876809964">Fout bij afspelen video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Maand</translation>
+<translation id="901493112792887934">huidige tijd in seconden</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigatie</translation>
+<translation id="9062295712474918030">document</translation>
+<translation id="9093215626363556771">scherm-in-scherm afsluiten</translation>
+<translation id="9108370397979208512">wiskunde</translation>
+<translation id="9132465097189459683">Anders...</translation>
+<translation id="9138385573473225930">melding</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, die begint op <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Scherm-in-scherm</translation>
+<translation id="9168329111483466115">voetnoot</translation>
+<translation id="954003015749068518">scherm-in-scherm openen</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..9e42991a07c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_no.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="no">
+<translation id="1018939186200882850">menyelement</translation>
+<translation id="10623998915015855">av/på-knapp</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="1171774979989969504">Skriv inn en e-postadresse.</translation>
+<translation id="1178581264944972037">Stans midlertidig</translation>
+<translation id="1188858454923323853">komplementær</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">glidebryter</translation>
+<translation id="1211441953136645838">sluttnote</translation>
+<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">anerkjennelser</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">område</translation>
+<translation id="1591562245178063882">Denne måneden</translation>
+<translation id="1637811476055996098">Velg filer</translation>
+<translation id="1650423536718072820">sitat</translation>
+<translation id="1727886345390570319">skjul menyen for teksting for hørselshemmede</translation>
+<translation id="1729654308190250600">Skriv inn en ikke-tom e-postadresse.</translation>
+<translation id="1758486001363313524">Andre</translation>
+<translation id="1806710327868736751">varseldialog</translation>
+<translation id="1821985195704844674">trerutenett</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">spill på ekstern enhet</translation>
+<translation id="190587075670221089">sletting</translation>
+<translation id="1907737156431278478">eksempel</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Verdien må være <ph name="MAXIMUM_DATE_OR_TIME" /> eller før.</translation>
+<translation id="1946271899482435442">Vis datovelgeren</translation>
+<translation id="1993104285338243655">Byttet til speiling</translation>
+<translation id="2060505056492490888">«<ph name="DOT" />» er brukt på feil sted i «<ph name="INVALIDDOMAIN" />».</translation>
+<translation id="2148716181193084225">I dag</translation>
+<translation id="2158401438286456825">sideliste</translation>
+<translation id="2226276347425096477">Forkort denne teksten til <ph name="MAX_CHARACTERS" /> tegn eller færre (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
+<translation id="2247351761944213033">Uke <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Spor <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">avmerkingsboks</translation>
+<translation id="2311842470354187719">sideskift</translation>
+<translation id="2335594187091864976">dato- og klokkeslettvelger</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>
+<translation id="2508569020611168319">faneliste</translation>
+<translation id="2561842179657104141">vis flere mediakontroller</translation>
+<translation id="2572483411312390101">spill av</translation>
+<translation id="2613802280814924224">Skriv inn en gyldig verdi. Den nærmeste, gyldige verdien er <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Send</translation>
+<translation id="2657045182931379222">grafikkobjekt</translation>
+<translation id="2674318244760992338">fotnote</translation>
+<translation id="2709516037105925701">Autofyll</translation>
+<translation id="2723001399770238859">lyd</translation>
+<translation id="2725963129578236554">kommentarer</translation>
+<translation id="2746543609216772311">Verdien må være <ph name="MINIMUM_DATE_OR_TIME" /> eller senere.</translation>
+<translation id="2759744352195237655">forgrunnsknapp</translation>
+<translation id="2761667185364618470">Kryss av denne boksen hvis du vil fortsette.</translation>
+<translation id="2844350028562914727">detaljer</translation>
+<translation id="2896972712917208084">gruppe med alternativknapper</translation>
+<translation id="2908441821576996758">Skriv inn en liste over e-postadresser atskilt med komma.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Skriv inn en gyldig verdi. Feltet er ufullstendig, eller har en ugyldig dato.</translation>
+<translation id="3078740164268491126">tabell</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Skriv inn en nettadresse.</translation>
+<translation id="3175736971608411871">nedtelling</translation>
+<translation id="3199563858620722075">kombinasjonsfelt</translation>
+<translation id="3450233048674729344">Verdien må være mindre enn eller lik <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definisjon</translation>
+<translation id="3557673793733683882">overskrift <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">ukevelger</translation>
+<translation id="3685101356851116974">Umerket bilde</translation>
+<translation id="3706100364254443312">bryter</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Avslutt bilde-i-bilde</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">term</translation>
+<translation id="3822383571486410024">Du må forlenge denne teksten til <ph name="MIN_CHARACTERS" /> tegn eller mer (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
+<translation id="383465348367842624">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
+<translation id="3846214748874656680">Avslutt fullskjermmodus</translation>
+<translation id="3889183436948184105">versjon</translation>
+<translation id="3920932319529768807">konklusjon</translation>
+<translation id="3924558731517983934">program</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">rullefelt</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">grafikk</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">forord</translation>
+<translation id="4201051445878709314">Se forrige måned</translation>
+<translation id="421884353938374759">fargevelger</translation>
+<translation id="4248100235867064564">menyrad</translation>
+<translation id="4360991593054037559">Skriv inn en gyldig verdi. De to nærmeste, gyldige verdiene er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Spørsmål og svar</translation>
+<translation id="4413860115965805769">menyknapp</translation>
+<translation id="4444765639179266822">Det ser ut til at det står <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">ordlistereferanse</translation>
+<translation id="4522570452068850558">Detaljer</translation>
+<translation id="4542388879936266156">tid som gjenstår: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">skjema</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
+<translation id="4668956016107839909">vedlegg</translation>
+<translation id="4718048029184481307">Spiller av i bilde-i-bilde</translation>
+<translation id="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">slå av/på fullskjermsvisning av skjermutklipp</translation>
+<translation id="4757246831282535685">fanepanel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">søk</translation>
+<translation id="4812940957355064477">Skriv inn et tall.</translation>
+<translation id="4912536737030637138">bibliografioppføring</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
+<translation id="4992066212339426712">Slå på lyden</translation>
+<translation id="49969490063480558">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
+<translation id="5034860022980953847">fremdriftsindikator</translation>
+<translation id="5090250355906949916">videotidslinje</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Se neste måned</translation>
+<translation id="512758898067543763">radoverskrift</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Verdien må være større enn eller lik <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
+<translation id="5334352251556557839">Kunne ikke spille innholdet.</translation>
+<translation id="5406322316791861025">figur</translation>
+<translation id="5453733299334684579">treelement</translation>
+<translation id="5466621249238537318">Velg én eller flere filer.</translation>
+<translation id="5468998798572797635">avslutt fullskjerm</translation>
+<translation id="5516424706154626233">datovelger</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">slå på lyden</translation>
+<translation id="5608153257855394627">fremheving</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Dobbelttrykk på venstre eller høyre side for å hoppe 10 sekunder</translation>
+<translation id="5631759159893697722">abstrakt</translation>
+<translation id="5643186887447432888">knapp</translation>
+<translation id="5677946354068040947">flere alternativer</translation>
+<translation id="576709008726043716">innledning</translation>
+<translation id="57838592816432529">Kutt lyden</translation>
+<translation id="5860033963881614850">Av</translation>
+<translation id="588258955323874662">Fullskjerm</translation>
+<translation id="5888666972993069672">Caster nå til <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">søkefelt</translation>
+<translation id="5939518447894949180">Tilbakestill</translation>
+<translation id="5966707198760109579">Uke</translation>
+<translation id="5987525920412732405">verdisettingsknapp</translation>
+<translation id="6011459053400940133">glidebryter for volum</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listefelt</translation>
+<translation id="6150588977291308318">bibliografi</translation>
+<translation id="6164829606128959761">måler</translation>
+<translation id="6166809985690652833">etterord</translation>
+<translation id="6209276755895393898">Dette ser ut til å være <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">ordliste</translation>
+<translation id="6281763101136022427">nettadresse</translation>
+<translation id="6310801910862476708">Avslutt bilde-i-bilde</translation>
+<translation id="6398862346408813489">Se panelet for valg av måned</translation>
+<translation id="6404546809543547843">lydtidslinje</translation>
+<translation id="6443871981718447451">vis menyen for teksting for hørselshemmede</translation>
+<translation id="6453774872122745852">omtale</translation>
+<translation id="6475115390776617481">direkte tilstedeværelse</translation>
+<translation id="648732519525291180">klokkeslettvelger</translation>
+<translation id="6550675742724504774">Alternativer</translation>
+<translation id="6572309429103589720">Grammatikkfeil</translation>
+<translation id="658823671542763450">gå til fullskjermmodus</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">logg</translation>
+<translation id="6643016212128521049">Tøm</translation>
+<translation id="668171684555832681">Annen</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Dårlig avspillingskvalitet</translation>
+<translation id="6755330956360078551">verktøytips</translation>
+<translation id="6790428901817661496">Spill av</translation>
+<translation id="6820355525329141109">Kunne ikke laste inn programtillegget.</translation>
+<translation id="6820615603175220800">bibliografireferanse</translation>
+<translation id="6843725295806269523">kutt lyd</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">blokksitat</translation>
+<translation id="693476918119313863">topptekst</translation>
+<translation id="6941933287844615239">last ned medier</translation>
+<translation id="6981594929165378967">innsetting</translation>
+<translation id="6989848892321993519">Øk lengden på denne teksten med minst <ph name="MIN_CHARACTERS" /> tegn (du bruker for øyeblikket 1 tegn).</translation>
+<translation id="7034405885550056553">forslag</translation>
+<translation id="709897737746224366">Sørg for samsvar med det forespurte formatet.</translation>
+<translation id="7118469954320184356">Ingen beskrivelse er tilgjengelig.</translation>
+<translation id="7139483182332611405">forord</translation>
+<translation id="7214187073215825913">innholdsinformasjon</translation>
+<translation id="7263440858009898357">Velg en artikkel i listen.</translation>
+<translation id="727747134524199931">kolonneoverskrift</translation>
+<translation id="7320576522385648310">bufring</translation>
+<translation id="7353453495576941748">anerkjennelse</translation>
+<translation id="7364796246159120393">Velg fil</translation>
+<translation id="739024184232394898">Andre</translation>
+<translation id="7405738980073107433">sluttnoter</translation>
+<translation id="7410239719251593705">Ser ut til å inneholde seksuelt innhold. Ingen beskrivelse er tilgjengelig.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Last ned</translation>
+<translation id="7529102961911894712">tilbakelink</translation>
+<translation id="7533959249147584474">Umerket grafikk</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">grafikkdokument</translation>
+<translation id="7673697353781729403">Timer</translation>
+<translation id="7681220483256441252">stikkordregister</translation>
+<translation id="7740050170769002709">HTML-innhold</translation>
+<translation id="7745230546936012372">For å hente manglende bildebeskrivelser, åpne den kontekstuelle menyen.</translation>
+<translation id="7750228210027921155">Bilde i bilde</translation>
+<translation id="775297008183122718">Ugyldig oppføring</translation>
+<translation id="7789962463072032349">stans midlertidig</translation>
+<translation id="7802800022689234070">trekant for ekstra innhold</translation>
+<translation id="7888071071722539607">Inkluder en «<ph name="ATSIGN" />» i e-postadressen. «<ph name="INVALIDADDRESS" />» mangler en «<ph name="ATSIGN" />».</translation>
+<translation id="7891486169920085145">vindusdeler</translation>
+<translation id="795667975304826397">Ingen fil valgt</translation>
+<translation id="8053789581856978548">søketekstfelt</translation>
+<translation id="8057695513531652401">merknad</translation>
+<translation id="8105797009065549151">kommentarreferanse</translation>
+<translation id="811583516810654505">Henter beskrivelse …</translation>
+<translation id="8117451130807776954">Denne uken</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="8208673686607688524">lokaldato- og -klokkeslettvelger</translation>
+<translation id="8261464734335370856">Stavefeil</translation>
+<translation id="8284326494547611709">Teksting</translation>
+<translation id="8346634859695247203">del</translation>
+<translation id="835897206747267392">Ugyldig verdi</translation>
+<translation id="8403857369060869934">medgått tid: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">del</translation>
+<translation id="8433900881053900389">verktøyrad</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
+<translation id="8451268428117625855">Velg en fil.</translation>
+<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8474886197722836894">dedikasjon</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutter</translation>
+<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="8550857728288566671">grafikksymbol</translation>
+<translation id="8583702881314752957">definisjonsliste</translation>
+<translation id="8597182159515967513">overskrift</translation>
+<translation id="860475260694818407">innholdsfortegnelse</translation>
+<translation id="8613126697340063924">kontrollér ekstern avspilling</translation>
+<translation id="862370744433916922">undertittel</translation>
+<translation id="8711688047404765493">utdata</translation>
+<translation id="8750798805984357768">Velg ett av følgende alternativer.</translation>
+<translation id="8808573423886751634">kapittel</translation>
+<translation id="8822203815165896261">forfatterinfo</translation>
+<translation id="8845239796550121995">Caster til TV-en nå</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Feil ved videoavspilling</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Måned</translation>
+<translation id="901493112792887934">gjeldende tid i sekunder</translation>
+<translation id="901834265349196618">e-post</translation>
+<translation id="9048119486235211610">navigasjon</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">avslutt bilde-i-bilde</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Andre</translation>
+<translation id="9138385573473225930">varsel</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Bilde i bilde</translation>
+<translation id="9168329111483466115">fotnote</translation>
+<translation id="954003015749068518">start bilde-i-bilde</translation>
+<translation id="966787709310836684">meny</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..2c2f80b5127
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pl.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pl">
+<translation id="1018939186200882850">element menu</translation>
+<translation id="10623998915015855">przycisk przełączania</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="1171774979989969504">Wprowadź adres e-mail.</translation>
+<translation id="1178581264944972037">Wstrzymaj</translation>
+<translation id="1188858454923323853">pomocniczy</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">suwak</translation>
+<translation id="1211441953136645838">przypis końcowy</translation>
+<translation id="1281252709823657822">okno dialogowe</translation>
+<translation id="1335095011850992622">autorzy</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">baner</translation>
+<translation id="1589122976691792535">region</translation>
+<translation id="1591562245178063882">W tym miesiącu</translation>
+<translation id="1637811476055996098">Wybierz pliki</translation>
+<translation id="1650423536718072820">cytat</translation>
+<translation id="1727886345390570319">ukrywanie menu napisów</translation>
+<translation id="1729654308190250600">Podaj adres e-mail.</translation>
+<translation id="1758486001363313524">Inny...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">siatka drzewa</translation>
+<translation id="1822429046913737220">rano/po południu</translation>
+<translation id="1832974991323546415">odtwarzanie na urządzeniu zdalnym</translation>
+<translation id="190587075670221089">usunięcie</translation>
+<translation id="1907737156431278478">przykład</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">stan</translation>
+<translation id="1938124657309484470">Musisz podać wartość <ph name="MAXIMUM_DATE_OR_TIME" /> lub wcześniejszą.</translation>
+<translation id="1946271899482435442">Pokaż selektor dat</translation>
+<translation id="1993104285338243655">Przełączono na odbicie lustrzane</translation>
+<translation id="2060505056492490888">„<ph name="DOT" />” występuje w niewłaściwym miejscu w „<ph name="INVALIDDOMAIN" />”.</translation>
+<translation id="2148716181193084225">Dzisiaj</translation>
+<translation id="2158401438286456825">lista stron</translation>
+<translation id="2226276347425096477">Skróć ten tekst do maksymalnie <ph name="MAX_CHARACTERS" /> znaków (w tej chwili korzystasz z <ph name="CURRENT_LENGTH" /> znaków).</translation>
+<translation id="2246498165605549352">Plik lokalny</translation>
+<translation id="2247351761944213033">Tydzień <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Utwór <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">pole wyboru</translation>
+<translation id="2311842470354187719">podział strony</translation>
+<translation id="2335594187091864976">selektor daty i godziny</translation>
+<translation id="245932805758469625">pozostały czas filmu w sekundach</translation>
+<translation id="248395913932153421">Dzień</translation>
+<translation id="2507943997699731163">Wypełnij to pole.</translation>
+<translation id="2508569020611168319">lista kart</translation>
+<translation id="2561842179657104141">pokaż więcej opcji sterowania multimediami</translation>
+<translation id="2572483411312390101">odtwórz</translation>
+<translation id="2613802280814924224">Podaj prawidłową wartość. Najbliższa prawidłowa wartość to <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Prześlij</translation>
+<translation id="2657045182931379222">obiekt graficzny</translation>
+<translation id="2674318244760992338">stopka</translation>
+<translation id="2709516037105925701">Autouzupełnianie</translation>
+<translation id="2723001399770238859">dźwięk</translation>
+<translation id="2725963129578236554">komentarze</translation>
+<translation id="2746543609216772311">Musisz podać wartość <ph name="MINIMUM_DATE_OR_TIME" /> lub późniejszą.</translation>
+<translation id="2759744352195237655">przycisk wyskakującego okienka</translation>
+<translation id="2761667185364618470">Zaznacz to pole, jeśli chcesz kontynuować.</translation>
+<translation id="2844350028562914727">szczegóły</translation>
+<translation id="2896972712917208084">grupa przycisków opcji</translation>
+<translation id="2908441821576996758">Podaj listę adresów e-mail rozdzielonych przecinkami.</translation>
+<translation id="2940813599313844715">obiekt</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Wpisz prawidłową wartość. Pole jest niekompletne lub zawiera nieprawidłową datę.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Wprowadź adres URL.</translation>
+<translation id="3175736971608411871">licznik czasu</translation>
+<translation id="3199563858620722075">pole złożone</translation>
+<translation id="3450233048674729344">Wartość nie może być większa niż <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definicja</translation>
+<translation id="3557673793733683882">nagłówek <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selektor tygodnia</translation>
+<translation id="3685101356851116974">Obraz bez etykiety</translation>
+<translation id="3706100364254443312">przełącznik</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Wyłącz tryb obrazu w obrazie</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termin</translation>
+<translation id="3822383571486410024">Wydłuż ten tekst przynajmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz <ph name="CURRENT_LENGTH" /> znaków).</translation>
+<translation id="383465348367842624">Część przed znakiem „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3846214748874656680">Zamknij pełny ekran</translation>
+<translation id="3889183436948184105">wersja</translation>
+<translation id="3920932319529768807">podsumowanie</translation>
+<translation id="3924558731517983934">aplikacja</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">pasek przewijania</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">grafika</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">przedmowa</translation>
+<translation id="4201051445878709314">Pokaż poprzedni miesiąc</translation>
+<translation id="421884353938374759">selektor kolorów</translation>
+<translation id="4248100235867064564">pasek menu</translation>
+<translation id="4360991593054037559">Podaj prawidłową wartość. Dwie najbliższe prawidłowe wartości to <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Pytania i odpowiedzi</translation>
+<translation id="4413860115965805769">przycisk menu</translation>
+<translation id="4444765639179266822">Wygląda jak napis: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">odniesienie do słownika</translation>
+<translation id="4522570452068850558">Szczegóły</translation>
+<translation id="4542388879936266156">pozostało: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formularz</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">dodatek</translation>
+<translation id="4718048029184481307">Odtwarzam w trybie obrazu w obrazie</translation>
+<translation id="4742539557769756338">okładka</translation>
+<translation id="4748357248530471599">przełącz z wycięcia w ekranie na tryb pełnoekranowy</translation>
+<translation id="4757246831282535685">panel karty</translation>
+<translation id="4763480195061959176">film</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Wpisz liczbę.</translation>
+<translation id="4912536737030637138">pozycja bibliograficzna</translation>
+<translation id="4975562563186953947">Wybrano: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Wyłącz wyciszenie</translation>
+<translation id="49969490063480558">Podaj część po znaku „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
+<translation id="5034860022980953847">wskaźnik postępu</translation>
+<translation id="5090250355906949916">pasek czasu odtwarzania filmu</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Pokaż przyszły miesiąc</translation>
+<translation id="512758898067543763">nagłówek wiersza</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Wartość nie może być mniejsza niż <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Podaj część przed znakiem „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
+<translation id="5334352251556557839">Nie można odtworzyć multimediów.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">element drzewa</translation>
+<translation id="5466621249238537318">Wybierz jeden lub kilka plików.</translation>
+<translation id="5468998798572797635">zamknij pełny ekran</translation>
+<translation id="5516424706154626233">selektor daty</translation>
+<translation id="5537725057119320332">Przesyłaj</translation>
+<translation id="5546461542133609677">wyłącz wyciszenie</translation>
+<translation id="5608153257855394627">podświetlenie</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Kliknij dwukrotnie z lewej lub prawej, by przewinąć o 10 s</translation>
+<translation id="5631759159893697722">streszczenie</translation>
+<translation id="5643186887447432888">przycisk</translation>
+<translation id="5677946354068040947">więcej opcji</translation>
+<translation id="576709008726043716">wprowadzenie</translation>
+<translation id="57838592816432529">Wycisz</translation>
+<translation id="5860033963881614850">Wyłączone</translation>
+<translation id="588258955323874662">Pełny ekran</translation>
+<translation id="5888666972993069672">Przesyłam na urządzenie <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">pole wyszukiwania</translation>
+<translation id="5939518447894949180">Resetuj</translation>
+<translation id="5966707198760109579">Tydzień</translation>
+<translation id="5987525920412732405">przycisk przewijany</translation>
+<translation id="6011459053400940133">suwak głośności</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">pole listy</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">miernik</translation>
+<translation id="6166809985690652833">posłowie</translation>
+<translation id="6209276755895393898">Wygląda jak: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">słownik</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Wyłącz tryb obrazu w obrazie</translation>
+<translation id="6398862346408813489">Pokaż panel wyboru miesiąca</translation>
+<translation id="6404546809543547843">pasek czasu odtwarzania dźwięku</translation>
+<translation id="6443871981718447451">wyświetlanie menu napisów</translation>
+<translation id="6453774872122745852">podziękowania</translation>
+<translation id="6475115390776617481">obecność na żywo</translation>
+<translation id="648732519525291180">selektor godziny</translation>
+<translation id="6550675742724504774">Opcje</translation>
+<translation id="6572309429103589720">Nieprawidłowa gramatyka</translation>
+<translation id="658823671542763450">przejdź do pełnego ekranu</translation>
+<translation id="663493177488814956">kanał</translation>
+<translation id="6637586476836377253">dziennik</translation>
+<translation id="6643016212128521049">Wyczyść</translation>
+<translation id="668171684555832681">Inny...</translation>
+<translation id="6692633176391053278">element kroczący</translation>
+<translation id="6709570249143506788">Niska jakość odtwarzania</translation>
+<translation id="6755330956360078551">etykietka</translation>
+<translation id="6790428901817661496">Odtwórz</translation>
+<translation id="6820355525329141109">Nie można załadować wtyczki.</translation>
+<translation id="6820615603175220800">odniesienie bibliograficzne</translation>
+<translation id="6843725295806269523">wyciszenie</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">cytat blokowy</translation>
+<translation id="693476918119313863">nagłówek</translation>
+<translation id="6941933287844615239">pobierz multimedia</translation>
+<translation id="6981594929165378967">wstawienie</translation>
+<translation id="6989848892321993519">Wydłuż ten tekst co najmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz jednego znaku).</translation>
+<translation id="7034405885550056553">sugestia</translation>
+<translation id="709897737746224366">Podaj wartość w wymaganym formacie.</translation>
+<translation id="7118469954320184356">Brak opisu.</translation>
+<translation id="7139483182332611405">wstęp</translation>
+<translation id="7214187073215825913">informacje o treści</translation>
+<translation id="7263440858009898357">Wybierz element z listy.</translation>
+<translation id="727747134524199931">nagłówek kolumny</translation>
+<translation id="7320576522385648310">buforowanie</translation>
+<translation id="7353453495576941748">twórcy</translation>
+<translation id="7364796246159120393">Wybierz plik</translation>
+<translation id="739024184232394898">Inny...</translation>
+<translation id="7405738980073107433">przypisy końcowe</translation>
+<translation id="7410239719251593705">To wygląda na przeznaczone tylko dla dorosłych. Brak opisu.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Pobierz</translation>
+<translation id="7529102961911894712">link zwrotny</translation>
+<translation id="7533959249147584474">Grafika bez etykiety</translation>
+<translation id="7647456547678091388">Wskazówka</translation>
+<translation id="7661956066982048809">dokument graficzny</translation>
+<translation id="7673697353781729403">Godziny</translation>
+<translation id="7681220483256441252">indeks</translation>
+<translation id="7740050170769002709">Treść HTML</translation>
+<translation id="7745230546936012372">Aby uzyskać brakujące opisy obrazów, otwórz menu kontekstowe.</translation>
+<translation id="7750228210027921155">Obraz w obrazie</translation>
+<translation id="775297008183122718">Nieprawidłowy wpis</translation>
+<translation id="7789962463072032349">wstrzymaj</translation>
+<translation id="7802800022689234070">trójkąt rozwinięcia</translation>
+<translation id="7888071071722539607">Uwzględnij znak „<ph name="ATSIGN" />” w adresie e-mail. W adresie „<ph name="INVALIDADDRESS" />” brakuje znaku „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">podział</translation>
+<translation id="795667975304826397">Nie wybrano pliku</translation>
+<translation id="8053789581856978548">pole tekstowe wyszukiwania</translation>
+<translation id="8057695513531652401">uwaga</translation>
+<translation id="8105797009065549151">odsyłacz</translation>
+<translation id="811583516810654505">Pobieram opis...</translation>
+<translation id="8117451130807776954">W tym tygodniu</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="8208673686607688524">selektor lokalnej daty i godziny</translation>
+<translation id="8261464734335370856">Nieprawidłowa pisownia</translation>
+<translation id="8284326494547611709">Napisy</translation>
+<translation id="8346634859695247203">sekcja</translation>
+<translation id="835897206747267392">Nieprawidłowa wartość.</translation>
+<translation id="8403857369060869934">upłynęło: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">część</translation>
+<translation id="8433900881053900389">pasek narzędzi</translation>
+<translation id="8444882422881193423">Liczba plików: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Wybierz plik.</translation>
+<translation id="8461852803063341183">przycisk opcji</translation>
+<translation id="8474886197722836894">dedykacja</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minuty</translation>
+<translation id="8541249477527128034">sterowanie multimediami</translation>
+<translation id="8550857728288566671">symbol graficzny</translation>
+<translation id="8583702881314752957">lista definicji</translation>
+<translation id="8597182159515967513">nagłówek</translation>
+<translation id="860475260694818407">spis treści</translation>
+<translation id="8613126697340063924">sterowanie zdalnym odtwarzaniem</translation>
+<translation id="862370744433916922">podtytuł</translation>
+<translation id="8711688047404765493">dane wyjściowe</translation>
+<translation id="8750798805984357768">Wybierz jedną z opcji.</translation>
+<translation id="8808573423886751634">rozdział</translation>
+<translation id="8822203815165896261">informacje o autorze</translation>
+<translation id="8845239796550121995">Przesyłam na telewizor</translation>
+<translation id="8851136666856101339">główny</translation>
+<translation id="8875657656876809964">Błąd odtwarzania filmu</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Miesiąc</translation>
+<translation id="901493112792887934">bieżący czas w sekundach</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">nawigacja</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">wyłącz tryb obrazu w obrazie</translation>
+<translation id="9108370397979208512">matematyczny</translation>
+<translation id="9132465097189459683">Inny...</translation>
+<translation id="9138385573473225930">alert</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, początek <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Obraz w obrazie</translation>
+<translation id="9168329111483466115">przypis</translation>
+<translation id="954003015749068518">włącz tryb obrazu w obrazie</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..92e93935a1d
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-BR.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-BR">
+<translation id="1018939186200882850">item de menu</translation>
+<translation id="10623998915015855">botão "alternar"</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="1171774979989969504">Insira um endereço de e-mail.</translation>
+<translation id="1178581264944972037">Pausar</translation>
+<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">controle deslizante</translation>
+<translation id="1211441953136645838">nota final</translation>
+<translation id="1281252709823657822">caixa de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">região</translation>
+<translation id="1591562245178063882">Este mês</translation>
+<translation id="1637811476055996098">Escolher arquivos</translation>
+<translation id="1650423536718072820">citação</translation>
+<translation id="1727886345390570319">ocultar menu de closed captions</translation>
+<translation id="1729654308190250600">Insira um endereço de e-mail que não esteja vazio.</translation>
+<translation id="1758486001363313524">Outras...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">grade de árvore</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">reproduzir em dispositivo remoto</translation>
+<translation id="190587075670221089">exclusão</translation>
+<translation id="1907737156431278478">exemplo</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">O valor deve ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
+<translation id="1946271899482435442">Mostrar seletor de datas</translation>
+<translation id="1993104285338243655">Alterado para espelhamento</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />" está sendo usado em uma posição incorreta em "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Hoje</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
+<translation id="2226276347425096477">Reduza este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Arquivo local</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">caixa de seleção</translation>
+<translation id="2311842470354187719">quebra de página</translation>
+<translation id="2335594187091864976">seletor de data e hora</translation>
+<translation id="245932805758469625">segundos restantes do vídeo</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="2508569020611168319">lista de guias</translation>
+<translation id="2561842179657104141">mostrar mais controles de mídia</translation>
+<translation id="2572483411312390101">reproduzir</translation>
+<translation id="2613802280814924224">Insira um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="2657045182931379222">objeto gráfico</translation>
+<translation id="2674318244760992338">rodapé</translation>
+<translation id="2709516037105925701">Preenchimento automático</translation>
+<translation id="2723001399770238859">áudio</translation>
+<translation id="2725963129578236554">comentários</translation>
+<translation id="2746543609216772311">O valor deve ser <ph name="MINIMUM_DATE_OR_TIME" /> ou posterior.</translation>
+<translation id="2759744352195237655">botão pop-up</translation>
+<translation id="2761667185364618470">Marque esta caixa se deseja continuar.</translation>
+<translation id="2844350028562914727">detalhes</translation>
+<translation id="2896972712917208084">grupo de rádio</translation>
+<translation id="2908441821576996758">Insira uma lista de endereços de e-mail separados por vírgula.</translation>
+<translation id="2940813599313844715">objeto</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Insira um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Insira um URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">caixa de combinação</translation>
+<translation id="3450233048674729344">O valor deve ser menor ou igual a <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definição</translation>
+<translation id="3557673793733683882">cabeçalho <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">seletor de semana</translation>
+<translation id="3685101356851116974">Imagem sem etiqueta</translation>
+<translation id="3706100364254443312">alternar</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Sair do modo picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termo</translation>
+<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="383465348367842624">Uma parte seguida por "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Sair da tela cheia</translation>
+<translation id="3889183436948184105">revisão</translation>
+<translation id="3920932319529768807">conclusão</translation>
+<translation id="3924558731517983934">app</translation>
+<translation id="3944740393230681990">prólogo</translation>
+<translation id="3960700977367013758">barra de rolagem</translation>
+<translation id="4103419683916926126">Milésimos de segundo</translation>
+<translation id="4151657705144244502">gráfico</translation>
+<translation id="4160057747563657758">telefone</translation>
+<translation id="4193965531860883258">prefácio</translation>
+<translation id="4201051445878709314">Mostrar mês anterior</translation>
+<translation id="421884353938374759">Seletor de cores</translation>
+<translation id="4248100235867064564">barra de menu</translation>
+<translation id="4360991593054037559">Insira um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Perguntas e respostas</translation>
+<translation id="4413860115965805769">botão de menu</translation>
+<translation id="4444765639179266822">Parece dizer: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referência de glossário</translation>
+<translation id="4522570452068850558">Saiba mais</translation>
+<translation id="4542388879936266156">tempo restante: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulário</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">A parte depois de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apêndice</translation>
+<translation id="4718048029184481307">Vídeo no modo picture-in-picture</translation>
+<translation id="4742539557769756338">capa</translation>
+<translation id="4748357248530471599">ativa tela cheia com corte de tela</translation>
+<translation id="4757246831282535685">painel da guia</translation>
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">pesquisar</translation>
+<translation id="4812940957355064477">Insira um número.</translation>
+<translation id="4912536737030637138">entrada bibliográfica</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
+<translation id="4992066212339426712">Ativar som</translation>
+<translation id="49969490063480558">Insira uma parte depois de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5034860022980953847">indicador de progresso</translation>
+<translation id="5090250355906949916">barra de progressão de vídeo</translation>
+<translation id="5093189678851173835">epígrafe</translation>
+<translation id="5117590920725113268">Mostrar próximo mês</translation>
+<translation id="512758898067543763">cabeçalho de linha</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5164977714490026579">O valor deve ser maior ou igual a <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Insira uma parte seguida por "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5334352251556557839">Não foi possível abrir a mídia.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">item de árvore</translation>
+<translation id="5466621249238537318">Selecione um ou mais arquivos.</translation>
+<translation id="5468998798572797635">sair do modo tela cheia</translation>
+<translation id="5516424706154626233">seletor de data</translation>
+<translation id="5537725057119320332">Transmitir</translation>
+<translation id="5546461542133609677">ativar som</translation>
+<translation id="5608153257855394627">destaque</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Toque duas vezes na esquerda ou direita para pular 10 s</translation>
+<translation id="5631759159893697722">resumo</translation>
+<translation id="5643186887447432888">botão</translation>
+<translation id="5677946354068040947">mais opções</translation>
+<translation id="576709008726043716">introdução</translation>
+<translation id="57838592816432529">Desativar som</translation>
+<translation id="5860033963881614850">Desativado</translation>
+<translation id="588258955323874662">Tela inteira</translation>
+<translation id="5888666972993069672">Transmitindo agora para <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">caixa de pesquisa</translation>
+<translation id="5939518447894949180">Redefinir</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="5987525920412732405">botão de rotação</translation>
+<translation id="6011459053400940133">controle deslizante de volume</translation>
+<translation id="6015796118275082299">Ano</translation>
+<translation id="6023896073578205740">caixa de listagem</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">medidor</translation>
+<translation id="6166809985690652833">posfácio</translation>
+<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossário</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Sair de picture-in-picture</translation>
+<translation id="6398862346408813489">Mostrar painel de seleção de mês</translation>
+<translation id="6404546809543547843">barra de progressão do áudio</translation>
+<translation id="6443871981718447451">mostrar menu de closed captions</translation>
+<translation id="6453774872122745852">agradecimentos</translation>
+<translation id="6475115390776617481">há mais alguém aqui</translation>
+<translation id="648732519525291180">seletor de hora</translation>
+<translation id="6550675742724504774">Opções</translation>
+<translation id="6572309429103589720">Gramática inválida</translation>
+<translation id="658823671542763450">entrar no modo tela cheia</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Limpar</translation>
+<translation id="668171684555832681">Outro...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Baixa qualidade de reprodução</translation>
+<translation id="6755330956360078551">dica</translation>
+<translation id="6790428901817661496">Reproduzir</translation>
+<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
+<translation id="6820615603175220800">referência bibliográfica</translation>
+<translation id="6843725295806269523">sem som</translation>
+<translation id="6885760532393684712">diretório</translation>
+<translation id="689129560213475294">colofão</translation>
+<translation id="6934078000481955284">bloco de texto</translation>
+<translation id="693476918119313863">cabeçalho</translation>
+<translation id="6941933287844615239">fazer o download da mídia</translation>
+<translation id="6981594929165378967">inserção</translation>
+<translation id="6989848892321993519">Aumente esse texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando 1 caractere.</translation>
+<translation id="7034405885550056553">sugestão</translation>
+<translation id="709897737746224366">É preciso que o formato corresponda ao exigido.</translation>
+<translation id="7118469954320184356">Nenhuma descrição disponível.</translation>
+<translation id="7139483182332611405">prefácio</translation>
+<translation id="7214187073215825913">informações do conteúdo</translation>
+<translation id="7263440858009898357">Selecione um item da lista.</translation>
+<translation id="727747134524199931">cabeçalho da coluna</translation>
+<translation id="7320576522385648310">armazenando em buffer</translation>
+<translation id="7353453495576941748">crédito</translation>
+<translation id="7364796246159120393">Escolher arquivo</translation>
+<translation id="739024184232394898">Outras...</translation>
+<translation id="7405738980073107433">notas finais</translation>
+<translation id="7410239719251593705">Parece apresentar conteúdo adulto. Nenhuma descrição disponível.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Fazer o download</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7533959249147584474">Elemento gráfico sem etiqueta</translation>
+<translation id="7647456547678091388">dica</translation>
+<translation id="7661956066982048809">documento gráfico</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
+<translation id="7740050170769002709">Conteúdo HTML</translation>
+<translation id="7745230546936012372">Para ver descrições ausentes de imagens, abra o menu de contexto.</translation>
+<translation id="7750228210027921155">Picture-in-picture</translation>
+<translation id="775297008183122718">Entrada inválida</translation>
+<translation id="7789962463072032349">pausar</translation>
+<translation id="7802800022689234070">triângulo de divulgação</translation>
+<translation id="7888071071722539607">Inclua um "<ph name="ATSIGN" />" no endereço de e-mail. "<ph name="INVALIDADDRESS" />" está com um "<ph name="ATSIGN" />" faltando.</translation>
+<translation id="7891486169920085145">divisor</translation>
+<translation id="795667975304826397">Nenhum arquivo selecionado</translation>
+<translation id="8053789581856978548">campo de texto da pesquisa</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referência de nota</translation>
+<translation id="811583516810654505">Buscando descrição...</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">seletor de data e hora local</translation>
+<translation id="8261464734335370856">Ortografia inválida</translation>
+<translation id="8284326494547611709">Legendas</translation>
+<translation id="8346634859695247203">seção</translation>
+<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8403857369060869934">tempo decorrido: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">barra de ferramentas</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> arquivos</translation>
+<translation id="8451268428117625855">Selecione um arquivo.</translation>
+<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8474886197722836894">dedicatória</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="8541249477527128034">controle de mídia</translation>
+<translation id="8550857728288566671">símbolo gráfico</translation>
+<translation id="8583702881314752957">lista de definições</translation>
+<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="860475260694818407">sumário</translation>
+<translation id="8613126697340063924">controlar reprodução remota</translation>
+<translation id="862370744433916922">subtítulo</translation>
+<translation id="8711688047404765493">saída</translation>
+<translation id="8750798805984357768">Selecione uma das opções.</translation>
+<translation id="8808573423886751634">capítulo</translation>
+<translation id="8822203815165896261">informações de autoria</translation>
+<translation id="8845239796550121995">Reproduzindo agora na sua TV</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Erro na reprodução do vídeo</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mês</translation>
+<translation id="901493112792887934">tempo atual em segundos</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navegação</translation>
+<translation id="9062295712474918030">documento</translation>
+<translation id="9093215626363556771">sair de picture-in-picture</translation>
+<translation id="9108370397979208512">matemática</translation>
+<translation id="9132465097189459683">Outras...</translation>
+<translation id="9138385573473225930">alerta</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, que começa em <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture-in-picture</translation>
+<translation id="9168329111483466115">nota de rodapé</translation>
+<translation id="954003015749068518">entrar no modo picture-in-picture</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..9b8d7015784
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_pt-PT.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-PT">
+<translation id="1018939186200882850">item de menu</translation>
+<translation id="10623998915015855">botão alternar</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="1171774979989969504">Introduza um endereço de email.</translation>
+<translation id="1178581264944972037">Pausa</translation>
+<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">painel rolante</translation>
+<translation id="1206693055195146388">controlo de deslize</translation>
+<translation id="1211441953136645838">nota final</translation>
+<translation id="1281252709823657822">caixa de diálogo</translation>
+<translation id="1335095011850992622">créditos</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">região</translation>
+<translation id="1591562245178063882">Este mês</translation>
+<translation id="1637811476055996098">Escolher Ficheiros</translation>
+<translation id="1650423536718072820">trecho em destaque</translation>
+<translation id="1727886345390570319">ocultar menu de legendas ocultas</translation>
+<translation id="1729654308190250600">Introduza um endereço de email que não esteja vazio.</translation>
+<translation id="1758486001363313524">Outra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">grelha de árvore</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">reproduzir no dispositivo remoto</translation>
+<translation id="190587075670221089">eliminação</translation>
+<translation id="1907737156431278478">exemplo</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="1938124657309484470">O valor tem de ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
+<translation id="1946271899482435442">Mostrar selecionador de data</translation>
+<translation id="1993104285338243655">Alterado para espelhamento.</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />" está a ser utilizado numa posição errada em "<ph name="INVALIDDOMAIN" />".</translation>
+<translation id="2148716181193084225">Hoje</translation>
+<translation id="2158401438286456825">lista de páginas</translation>
+<translation id="2226276347425096477">Encurte este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> caracteres).</translation>
+<translation id="2246498165605549352">Ficheiro local</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, de <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Faixa <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">caixa de verificação</translation>
+<translation id="2311842470354187719">quebra de página</translation>
+<translation id="2335594187091864976">selecionador de data e hora</translation>
+<translation id="245932805758469625">segundos restantes do vídeo</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="2508569020611168319">lista de separadores</translation>
+<translation id="2561842179657104141">mostrar mais controlos de multimédia</translation>
+<translation id="2572483411312390101">reproduzir</translation>
+<translation id="2613802280814924224">Introduza um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Submeter</translation>
+<translation id="2657045182931379222">objeto de gráficos</translation>
+<translation id="2674318244760992338">rodapé</translation>
+<translation id="2709516037105925701">Preenchimento automático</translation>
+<translation id="2723001399770238859">áudio</translation>
+<translation id="2725963129578236554">comentários</translation>
+<translation id="2746543609216772311">O valor tem de ser <ph name="MINIMUM_DATE_OR_TIME" /> ou posterior.</translation>
+<translation id="2759744352195237655">botão pop-up</translation>
+<translation id="2761667185364618470">Selecione esta caixa se pretender continuar.</translation>
+<translation id="2844350028562914727">detalhes</translation>
+<translation id="2896972712917208084">grupo de botões de opção</translation>
+<translation id="2908441821576996758">Introduza uma lista de endereços de email separados por vírgula.</translation>
+<translation id="2940813599313844715">objeto</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Introduza um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Introduza um URL.</translation>
+<translation id="3175736971608411871">temporizador</translation>
+<translation id="3199563858620722075">caixa de combinação</translation>
+<translation id="3450233048674729344">O valor tem de ser inferior ou igual a <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definição</translation>
+<translation id="3557673793733683882">título <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selecionador de semanas</translation>
+<translation id="3685101356851116974">Imagem sem etiqueta</translation>
+<translation id="3706100364254443312">alternar</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Sair de ecrã no ecrã</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termo</translation>
+<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> carateres ou mais (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> carateres).</translation>
+<translation id="383465348367842624">Uma parte seguida de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Sair do modo de ecrã inteiro</translation>
+<translation id="3889183436948184105">revisão</translation>
+<translation id="3920932319529768807">conclusão</translation>
+<translation id="3924558731517983934">aplicação</translation>
+<translation id="3944740393230681990">prólogo</translation>
+<translation id="3960700977367013758">barra de deslocamento</translation>
+<translation id="4103419683916926126">Milissegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
+<translation id="4160057747563657758">telefone</translation>
+<translation id="4193965531860883258">prefácio</translation>
+<translation id="4201051445878709314">Mostrar mês anterior</translation>
+<translation id="421884353938374759">seletor de cores</translation>
+<translation id="4248100235867064564">barra de menu</translation>
+<translation id="4360991593054037559">Introduza um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Perg e Resp</translation>
+<translation id="4413860115965805769">botão de menu</translation>
+<translation id="4444765639179266822">Parece indicar: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">referência do glossário</translation>
+<translation id="4522570452068850558">Detalhes</translation>
+<translation id="4542388879936266156">tempo restante: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulário</translation>
+<translation id="4661075872484491155">árvore</translation>
+<translation id="4664250907885839816">Uma parte a seguir a "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">apêndice</translation>
+<translation id="4718048029184481307">A reproduzir em ecrã no ecrã…</translation>
+<translation id="4742539557769756338">capa</translation>
+<translation id="4748357248530471599">ativar/desativar o ecrã inteiro de recorte no ecrã</translation>
+<translation id="4757246831282535685">painel de separadores</translation>
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Introduza um número.</translation>
+<translation id="4912536737030637138">entrada da bibliografia</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
+<translation id="4992066212339426712">Reativar o som</translation>
+<translation id="49969490063480558">Introduza uma parte a seguir a "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5034860022980953847">indicador de progresso</translation>
+<translation id="5090250355906949916">controlo de arrasto do tempo do vídeo</translation>
+<translation id="5093189678851173835">epígrafe</translation>
+<translation id="5117590920725113268">Mostrar mês seguinte</translation>
+<translation id="512758898067543763">cabeçalho da linha</translation>
+<translation id="5143125788380636750">epílogo</translation>
+<translation id="5164977714490026579">O valor tem de ser superior ou igual a <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Introduza uma parte seguida de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5334352251556557839">Não é possível reproduzir multimédia.</translation>
+<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">item de árvore</translation>
+<translation id="5466621249238537318">Selecione um ou mais ficheiros.</translation>
+<translation id="5468998798572797635">sair do modo de ecrã inteiro</translation>
+<translation id="5516424706154626233">selecionador de data</translation>
+<translation id="5537725057119320332">Transmitir</translation>
+<translation id="5546461542133609677">reativar som</translation>
+<translation id="5608153257855394627">realçar</translation>
+<translation id="561939826962581046">hora</translation>
+<translation id="5630795885300617244">Toque duas vezes à esquerda ou à direita para avançar 10 seg.</translation>
+<translation id="5631759159893697722">resumo</translation>
+<translation id="5643186887447432888">botão</translation>
+<translation id="5677946354068040947">mais opções</translation>
+<translation id="576709008726043716">introdução</translation>
+<translation id="57838592816432529">Desativar som</translation>
+<translation id="5860033963881614850">Desativado</translation>
+<translation id="588258955323874662">Ecrã inteiro</translation>
+<translation id="5888666972993069672">A transmitir agora para <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">caixa de pesquisa</translation>
+<translation id="5939518447894949180">Repor</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="5987525920412732405">botão giratório</translation>
+<translation id="6011459053400940133">controlo de deslize do volume</translation>
+<translation id="6015796118275082299">Ano</translation>
+<translation id="6023896073578205740">caixa de lista</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">contador</translation>
+<translation id="6166809985690652833">posfácio</translation>
+<translation id="6209276755895393898">Parece ser: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glossário</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Sair do modo ecrã no ecrã</translation>
+<translation id="6398862346408813489">Mostrar painel de seleção do mês</translation>
+<translation id="6404546809543547843">controlo de arrasto do tempo do áudio</translation>
+<translation id="6443871981718447451">mostrar menu de legendas ocultas</translation>
+<translation id="6453774872122745852">agradecimentos</translation>
+<translation id="6475115390776617481">presença em direto</translation>
+<translation id="648732519525291180">selecionador de hora</translation>
+<translation id="6550675742724504774">Opções</translation>
+<translation id="6572309429103589720">Gramática inválida.</translation>
+<translation id="658823671542763450">entrar no modo de ecrã inteiro</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Limpar</translation>
+<translation id="668171684555832681">Outros...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Má qualidade de reprodução.</translation>
+<translation id="6755330956360078551">sugestão</translation>
+<translation id="6790428901817661496">Reproduzir</translation>
+<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
+<translation id="6820615603175220800">referência bibliográfica</translation>
+<translation id="6843725295806269523">desativar som</translation>
+<translation id="6885760532393684712">diretório</translation>
+<translation id="689129560213475294">colofão</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">cabeçalho</translation>
+<translation id="6941933287844615239">transferir multimédia</translation>
+<translation id="6981594929165378967">inserção</translation>
+<translation id="6989848892321993519">Aumente este texto para <ph name="MIN_CHARACTERS" /> ou mais carateres (atualmente, está a utilizar 1 caráter).</translation>
+<translation id="7034405885550056553">sugestão</translation>
+<translation id="709897737746224366">Faça corresponder o formato pedido.</translation>
+<translation id="7118469954320184356">Nenhuma descrição disponível.</translation>
+<translation id="7139483182332611405">prefácio</translation>
+<translation id="7214187073215825913">informações sobre o conteúdo</translation>
+<translation id="7263440858009898357">Selecione um item na lista.</translation>
+<translation id="727747134524199931">cabeçalho da coluna</translation>
+<translation id="7320576522385648310">colocação no buffer</translation>
+<translation id="7353453495576941748">crédito</translation>
+<translation id="7364796246159120393">Escolher ficheiro</translation>
+<translation id="739024184232394898">Outra...</translation>
+<translation id="7405738980073107433">notas finais</translation>
+<translation id="7410239719251593705">Parece ser conteúdo para adultos. Nenhuma descrição disponível.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Transferir</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7533959249147584474">Gráfico sem etiqueta</translation>
+<translation id="7647456547678091388">sugestão</translation>
+<translation id="7661956066982048809">documento de gráficos</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="7681220483256441252">índice</translation>
+<translation id="7740050170769002709">Conteúdo HTML</translation>
+<translation id="7745230546936012372">Para obter descrições de imagens em falta, abra o menu de contexto.</translation>
+<translation id="7750228210027921155">Ecrã no ecrã</translation>
+<translation id="775297008183122718">Entrada inválida</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triângulo de divulgação</translation>
+<translation id="7888071071722539607">Inclua um "<ph name="ATSIGN" />" no endereço de email. Falta um "<ph name="ATSIGN" />" em "<ph name="INVALIDADDRESS" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
+<translation id="795667975304826397">Nenhum ficheiro selecionado</translation>
+<translation id="8053789581856978548">campo de texto de pesquisa</translation>
+<translation id="8057695513531652401">aviso</translation>
+<translation id="8105797009065549151">referência de nota</translation>
+<translation id="811583516810654505">A obter descrição…</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selecionador de data e hora locais</translation>
+<translation id="8261464734335370856">Ortografia inválida.</translation>
+<translation id="8284326494547611709">Legendas</translation>
+<translation id="8346634859695247203">secção</translation>
+<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8403857369060869934">tempo decorrido: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">barra de ferramentas</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ficheiros</translation>
+<translation id="8451268428117625855">Selecione um ficheiro.</translation>
+<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8474886197722836894">dedicatória</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="8541249477527128034">controlo multimédia</translation>
+<translation id="8550857728288566671">símbolo de gráficos</translation>
+<translation id="8583702881314752957">lista de definições</translation>
+<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="860475260694818407">índice</translation>
+<translation id="8613126697340063924">controlar a reprodução remota</translation>
+<translation id="862370744433916922">legenda</translation>
+<translation id="8711688047404765493">saída</translation>
+<translation id="8750798805984357768">Selecione uma destas opções.</translation>
+<translation id="8808573423886751634">capítulo</translation>
+<translation id="8822203815165896261">informações sobre a criação</translation>
+<translation id="8845239796550121995">A transmitir na sua TV…</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Erro de reprodução de vídeo.</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mês</translation>
+<translation id="901493112792887934">tempo atual em segundos</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">navegação</translation>
+<translation id="9062295712474918030">documento</translation>
+<translation id="9093215626363556771">sair do modo ecrã no ecrã</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Outra...</translation>
+<translation id="9138385573473225930">alerta</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, a partir de <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Ecrã no ecrã</translation>
+<translation id="9168329111483466115">nota de rodapé</translation>
+<translation id="954003015749068518">entrar no modo ecrã no ecrã</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..dd4c886b016
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ro.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ro">
+<translation id="1018939186200882850">element de meniu</translation>
+<translation id="10623998915015855">buton de comutare</translation>
+<translation id="1088086359088493902">Secunde</translation>
+<translation id="1171774979989969504">Introdu o adresă de e-mail.</translation>
+<translation id="1178581264944972037">Întrerupe</translation>
+<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">text derulant</translation>
+<translation id="1206693055195146388">glisor</translation>
+<translation id="1211441953136645838">notă de final</translation>
+<translation id="1281252709823657822">dialog</translation>
+<translation id="1335095011850992622">mulțumiri</translation>
+<translation id="1342835525016946179">articol</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">regiune</translation>
+<translation id="1591562245178063882">Luna aceasta</translation>
+<translation id="1637811476055996098">Alege fișierele</translation>
+<translation id="1650423536718072820">citat</translation>
+<translation id="1727886345390570319">ascunde meniul de subtitrări</translation>
+<translation id="1729654308190250600">Introduceți o adresă de e-mail concretă.</translation>
+<translation id="1758486001363313524">Altele...</translation>
+<translation id="1806710327868736751">dialog de alertă</translation>
+<translation id="1821985195704844674">grilă arbore</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">redă pe dispozitiv la distanță</translation>
+<translation id="190587075670221089">ștergere</translation>
+<translation id="1907737156431278478">exemplu</translation>
+<translation id="1921819250265091946">zz</translation>
+<translation id="1930711995431081526">stare</translation>
+<translation id="1938124657309484470">Valoarea pentru dată/oră trebuie să fie <ph name="MAXIMUM_DATE_OR_TIME" /> sau una anterioară.</translation>
+<translation id="1946271899482435442">Afișează selectorul de date</translation>
+<translation id="1993104285338243655">S-a comutat la oglindire</translation>
+<translation id="2060505056492490888">Semnul „<ph name="DOT" />” apare poziționat greșit în „<ph name="INVALIDDOMAIN" />”.</translation>
+<translation id="2148716181193084225">Astăzi</translation>
+<translation id="2158401438286456825">listă de pagini</translation>
+<translation id="2226276347425096477">Micșorează acest text la cel mult <ph name="MAX_CHARACTERS" /> caractere (în prezent utilizezi <ph name="CURRENT_LENGTH" /> caractere).</translation>
+<translation id="2246498165605549352">Fișier local</translation>
+<translation id="2247351761944213033">Săptămâna <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Melodia <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">casetă de selectare</translation>
+<translation id="2311842470354187719">sfârșit de pagină</translation>
+<translation id="2335594187091864976">selector pentru dată și oră</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>
+<translation id="2508569020611168319">listă de file</translation>
+<translation id="2561842179657104141">afișează mai multe comenzi media</translation>
+<translation id="2572483411312390101">redați</translation>
+<translation id="2613802280814924224">Introduceți o valoare validă. Cea mai apropiată valoare validă este <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Trimite</translation>
+<translation id="2657045182931379222">obiect grafic</translation>
+<translation id="2674318244760992338">notă de subsol</translation>
+<translation id="2709516037105925701">Completare automată</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="2725963129578236554">comentarii</translation>
+<translation id="2746543609216772311">Valoarea pentru dată/oră trebuie să fie <ph name="MINIMUM_DATE_OR_TIME" /> sau una ulterioară.</translation>
+<translation id="2759744352195237655">buton pop-up</translation>
+<translation id="2761667185364618470">Bifeză caseta dacă vrei să continui.</translation>
+<translation id="2844350028562914727">detalii</translation>
+<translation id="2896972712917208084">grup butoane radio</translation>
+<translation id="2908441821576996758">Introdu o listă de adrese de e-mail separate prin virgulă.</translation>
+<translation id="2940813599313844715">obiect</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Introduceți o valoare validă. Câmpul este incomplet sau conține o dată nevalidă.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">notă</translation>
+<translation id="310520048233152454">Introdu o adresă URL.</translation>
+<translation id="3175736971608411871">temporizator</translation>
+<translation id="3199563858620722075">casetă combo</translation>
+<translation id="3450233048674729344">Valoarea trebuie să fie mai mică sau egală cu <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definiție</translation>
+<translation id="3557673793733683882">titlu <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">selector pentru săptămână</translation>
+<translation id="3685101356851116974">Imagine neetichetată</translation>
+<translation id="3706100364254443312">comutator</translation>
+<translation id="3732799496749320381">ll</translation>
+<translation id="3754210790023674521">Ieși din modul picture-in-picture</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">termen</translation>
+<translation id="3822383571486410024">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> caractere (în prezent folosești <ph name="CURRENT_LENGTH" /> caractere).</translation>
+<translation id="383465348367842624">Valoarea urmată de semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3846214748874656680">Ieși din ecranul complet</translation>
+<translation id="3889183436948184105">versiune</translation>
+<translation id="3920932319529768807">concluzie</translation>
+<translation id="3924558731517983934">aplicație</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">bară de derulare</translation>
+<translation id="4103419683916926126">Milisecunde</translation>
+<translation id="4151657705144244502">element grafic</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">cuvânt înainte</translation>
+<translation id="4201051445878709314">Afișează luna anterioară</translation>
+<translation id="421884353938374759">selector de culoare</translation>
+<translation id="4248100235867064564">bară de meniu</translation>
+<translation id="4360991593054037559">Introduceți o valoare validă. Cele mai apropiate valori valide sunt <ph name="VALID_VALUE_LOW" /> și <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Întrebări și răspunsuri</translation>
+<translation id="4413860115965805769">buton de meniu</translation>
+<translation id="4444765639179266822">Se pare că spune: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">trimitere la glosar</translation>
+<translation id="4522570452068850558">Detalii</translation>
+<translation id="4542388879936266156">timp rămas: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formular</translation>
+<translation id="4661075872484491155">arbore</translation>
+<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4668956016107839909">anexă</translation>
+<translation id="4718048029184481307">Se redă în modul picture-in-picture</translation>
+<translation id="4742539557769756338">copertă</translation>
+<translation id="4748357248530471599">decupaj inclus în ecranul complet</translation>
+<translation id="4757246831282535685">panou de file</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">căutați</translation>
+<translation id="4812940957355064477">Introduceți un număr.</translation>
+<translation id="4912536737030637138">intrare bibliografică</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selectate</translation>
+<translation id="4992066212339426712">Activează sunetul</translation>
+<translation id="49969490063480558">Introduceți o valoare după semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
+<translation id="5034860022980953847">indicator de progres</translation>
+<translation id="5090250355906949916">glisor pentru redare video</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Afișează luna următoare</translation>
+<translation id="512758898067543763">antet rând</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Valoarea trebuie să fie mai mare sau egală cu <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Introduceți o valoare urmată de semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
+<translation id="5334352251556557839">Nu se pot reda fișiere media.</translation>
+<translation id="5406322316791861025">cifră</translation>
+<translation id="5453733299334684579">element arbore</translation>
+<translation id="5466621249238537318">Selectează unul sau mai multe fișiere.</translation>
+<translation id="5468998798572797635">ieșiți din ecranul complet</translation>
+<translation id="5516424706154626233">selector dată</translation>
+<translation id="5537725057119320332">Proiectează</translation>
+<translation id="5546461542133609677">activați sunetul</translation>
+<translation id="5608153257855394627">evidențiază</translation>
+<translation id="561939826962581046">oră</translation>
+<translation id="5630795885300617244">Atinge de două ori spre stânga sau spre dreapta pentru a derula cu 10 secunde</translation>
+<translation id="5631759159893697722">rezumat</translation>
+<translation id="5643186887447432888">buton</translation>
+<translation id="5677946354068040947">mai multe opțiuni</translation>
+<translation id="576709008726043716">introducere</translation>
+<translation id="57838592816432529">Dezactivează sunetul</translation>
+<translation id="5860033963881614850">Dezactivat</translation>
+<translation id="588258955323874662">Ecran complet</translation>
+<translation id="5888666972993069672">Se proiectează acum pe <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">casetă de căutare</translation>
+<translation id="5939518447894949180">Resetează</translation>
+<translation id="5966707198760109579">Săptămână</translation>
+<translation id="5987525920412732405">buton incrementare/decrementare</translation>
+<translation id="6011459053400940133">glisor de volum</translation>
+<translation id="6015796118275082299">An</translation>
+<translation id="6023896073578205740">casetă listă</translation>
+<translation id="6150588977291308318">bibliografie</translation>
+<translation id="6164829606128959761">instrument de măsurare</translation>
+<translation id="6166809985690652833">postfață</translation>
+<translation id="6209276755895393898">Pare a fi: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosar</translation>
+<translation id="6281763101136022427">adresă URL</translation>
+<translation id="6310801910862476708">Ieși din modul Picture-in-Picture</translation>
+<translation id="6398862346408813489">Afișează panoul de selectare a lunii</translation>
+<translation id="6404546809543547843">glisor redare audio</translation>
+<translation id="6443871981718447451">afișează meniul de subtitrări</translation>
+<translation id="6453774872122745852">lista colaboratorilor</translation>
+<translation id="6475115390776617481">prezență live</translation>
+<translation id="648732519525291180">selector oră</translation>
+<translation id="6550675742724504774">Opțiuni</translation>
+<translation id="6572309429103589720">Gramatică nevalidă</translation>
+<translation id="658823671542763450">deschideți în ecran complet</translation>
+<translation id="663493177488814956">feed</translation>
+<translation id="6637586476836377253">jurnal</translation>
+<translation id="6643016212128521049">Șterge</translation>
+<translation id="668171684555832681">Altele...</translation>
+<translation id="6692633176391053278">control numeric cu incrementare/decrementare</translation>
+<translation id="6709570249143506788">Calitate slabă a redării</translation>
+<translation id="6755330956360078551">balon explicativ</translation>
+<translation id="6790428901817661496">Redă</translation>
+<translation id="6820355525329141109">Nu s-a putut încărca pluginul.</translation>
+<translation id="6820615603175220800">referință bibliografică</translation>
+<translation id="6843725295806269523">dezactivați sunetul</translation>
+<translation id="6885760532393684712">director</translation>
+<translation id="689129560213475294">colofon</translation>
+<translation id="6934078000481955284">blockquote</translation>
+<translation id="693476918119313863">antet</translation>
+<translation id="6941933287844615239">descarcă conținut media</translation>
+<translation id="6981594929165378967">inserare</translation>
+<translation id="6989848892321993519">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> caractere (în prezent folosești 1 caracter).</translation>
+<translation id="7034405885550056553">sugestie</translation>
+<translation id="709897737746224366">Respectă formatul solicitat.</translation>
+<translation id="7118469954320184356">Nu există nicio descriere disponibilă.</translation>
+<translation id="7139483182332611405">prefață</translation>
+<translation id="7214187073215825913">informații despre conținut</translation>
+<translation id="7263440858009898357">Selectează un articol din listă.</translation>
+<translation id="727747134524199931">antet coloană</translation>
+<translation id="7320576522385648310">Se încarcă în memoria temporară</translation>
+<translation id="7353453495576941748">mulțumire</translation>
+<translation id="7364796246159120393">Alege fișierul</translation>
+<translation id="739024184232394898">Altele...</translation>
+<translation id="7405738980073107433">note de final</translation>
+<translation id="7410239719251593705">Pare a avea conținut pentru adulți. Nu există nicio descriere disponibilă.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">filă</translation>
+<translation id="7514365320538308">Descarcă</translation>
+<translation id="7529102961911894712">backlink</translation>
+<translation id="7533959249147584474">Imagine neetichetată</translation>
+<translation id="7647456547678091388">sfat</translation>
+<translation id="7661956066982048809">document grafic</translation>
+<translation id="7673697353781729403">Ore</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">Conținut HTML</translation>
+<translation id="7745230546936012372">Pentru a obține descrierile lipsă ale imaginilor, deschide meniul contextual.</translation>
+<translation id="7750228210027921155">Picture-in-picture</translation>
+<translation id="775297008183122718">Intrare nevalidă</translation>
+<translation id="7789962463072032349">întrerupe</translation>
+<translation id="7802800022689234070">triunghi pentru afișare</translation>
+<translation id="7888071071722539607">Includeți semnul „<ph name="ATSIGN" />” în adresa de e-mail. Din adresa „<ph name="INVALIDADDRESS" />” lipsește semnul „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">element de divizare</translation>
+<translation id="795667975304826397">Nu ai ales niciun fișier</translation>
+<translation id="8053789581856978548">câmp pentru căutarea textului</translation>
+<translation id="8057695513531652401">anunț</translation>
+<translation id="8105797009065549151">trimitere la notă</translation>
+<translation id="811583516810654505">Se așteaptă descrierea…</translation>
+<translation id="8117451130807776954">Săptămâna aceasta</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="8208673686607688524">selector pentru data și ora locală</translation>
+<translation id="8261464734335370856">Ortografie nevalidă</translation>
+<translation id="8284326494547611709">Subtitrări</translation>
+<translation id="8346634859695247203">secțiune</translation>
+<translation id="835897206747267392">Valoare nevalidă.</translation>
+<translation id="8403857369060869934">timp scurs: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">parte</translation>
+<translation id="8433900881053900389">bară de instrumente</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fișiere</translation>
+<translation id="8451268428117625855">Selectează un fișier.</translation>
+<translation id="8461852803063341183">buton radio</translation>
+<translation id="8474886197722836894">dedicație</translation>
+<translation id="8531739829932800271">erată</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="8541249477527128034">comandă media</translation>
+<translation id="8550857728288566671">simbol grafic</translation>
+<translation id="8583702881314752957">listă de definiții</translation>
+<translation id="8597182159515967513">antet</translation>
+<translation id="860475260694818407">cuprins</translation>
+<translation id="8613126697340063924">controlează redarea la distanță</translation>
+<translation id="862370744433916922">subtitlu</translation>
+<translation id="8711688047404765493">ieșire</translation>
+<translation id="8750798805984357768">Selectează una dintre aceste opțiuni.</translation>
+<translation id="8808573423886751634">capitol</translation>
+<translation id="8822203815165896261">informații despre crearea de conținut</translation>
+<translation id="8845239796550121995">Acum se proiectează pe televizor</translation>
+<translation id="8851136666856101339">principal</translation>
+<translation id="8875657656876809964">Eroare de redare video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KO</translation>
+<translation id="8987927404178983737">Lună</translation>
+<translation id="901493112792887934">timp actual în secunde</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigare</translation>
+<translation id="9062295712474918030">document</translation>
+<translation id="9093215626363556771">ieși din modul picture-in-picture</translation>
+<translation id="9108370397979208512">matematică</translation>
+<translation id="9132465097189459683">Altele...</translation>
+<translation id="9138385573473225930">alertă</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, începând de pe <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picture-in-Picture</translation>
+<translation id="9168329111483466115">notă de subsol</translation>
+<translation id="954003015749068518">intră în modul picture-in-picture</translation>
+<translation id="966787709310836684">meniu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..2021635728c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ru.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ru">
+<translation id="1018939186200882850">элемент меню</translation>
+<translation id="10623998915015855">кнопка-переключатель</translation>
+<translation id="1088086359088493902">Секунды</translation>
+<translation id="1171774979989969504">Введите адрес электронной почты.</translation>
+<translation id="1178581264944972037">Пауза</translation>
+<translation id="1188858454923323853">дополнительно</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">ползунок</translation>
+<translation id="1211441953136645838">концевая сноска</translation>
+<translation id="1281252709823657822">диалоговое окно</translation>
+<translation id="1335095011850992622">выходные сведения</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">баннер</translation>
+<translation id="1589122976691792535">регион</translation>
+<translation id="1591562245178063882">В этом месяце</translation>
+<translation id="1637811476055996098">Выбрать файлы</translation>
+<translation id="1650423536718072820">цитата в виде врезки</translation>
+<translation id="1727886345390570319">скрыть меню субтитров</translation>
+<translation id="1729654308190250600">Введите адрес электронной почты.</translation>
+<translation id="1758486001363313524">Другое…</translation>
+<translation id="1806710327868736751">диалоговое окно оповещения</translation>
+<translation id="1821985195704844674">сетка в виде дерева</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">воспроизвести на удаленном устройстве</translation>
+<translation id="190587075670221089">удаление</translation>
+<translation id="1907737156431278478">пример</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="1938124657309484470">Максимальное значение должно быть <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
+<translation id="1946271899482435442">Показать окно выбора даты</translation>
+<translation id="1993104285338243655">Включено дублирование экрана</translation>
+<translation id="2060505056492490888">Недопустимое положение символа "<ph name="DOT" />" в адресе "<ph name="INVALIDDOMAIN" />".</translation>
+<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="2247351761944213033">Неделя <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Трек <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">флажок</translation>
+<translation id="2311842470354187719">разрыв страницы</translation>
+<translation id="2335594187091864976">окно выбора даты и времени</translation>
+<translation id="245932805758469625">оставшееся время до конца видео в секундах</translation>
+<translation id="248395913932153421">День</translation>
+<translation id="2507943997699731163">Заполните это поле.</translation>
+<translation id="2508569020611168319">список вкладок</translation>
+<translation id="2561842179657104141">ещё элементы управления</translation>
+<translation id="2572483411312390101">воспроизведение</translation>
+<translation id="2613802280814924224">Введите допустимое значение. Ближайшее допустимое значение: <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Отправить</translation>
+<translation id="2657045182931379222">графический объект</translation>
+<translation id="2674318244760992338">нижний колонтитул</translation>
+<translation id="2709516037105925701">Автозаполнение</translation>
+<translation id="2723001399770238859">аудио</translation>
+<translation id="2725963129578236554">комментарии</translation>
+<translation id="2746543609216772311">Минимальное значение должно быть <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">всплывающая кнопка</translation>
+<translation id="2761667185364618470">Чтобы продолжить, установите этот флажок.</translation>
+<translation id="2844350028562914727">подробные сведения</translation>
+<translation id="2896972712917208084">группа переключателей</translation>
+<translation id="2908441821576996758">Введите адреса электронной почты через запятую.</translation>
+<translation id="2940813599313844715">объект</translation>
+<translation id="3040011195152428237">ссылка</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> МБ</translation>
+<translation id="3075154866155599887">Введите верное значение. Поле не заполнено или введена недействительная дата.</translation>
+<translation id="3078740164268491126">таблица</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Введите URL.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">поле со списком</translation>
+<translation id="3450233048674729344">Значение должно быть меньше или равно <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">описание</translation>
+<translation id="3557673793733683882">заголовок <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">выбор недели</translation>
+<translation id="3685101356851116974">Изображение без описания</translation>
+<translation id="3706100364254443312">переключить</translation>
+<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Выйти из режима "Картинка в картинке"</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
+<translation id="3808586225841795776">запрос</translation>
+<translation id="3822383571486410024">Минимально допустимое количество символов: <ph name="MIN_CHARACTERS" />. Длина текста сейчас: <ph name="CURRENT_LENGTH" />.</translation>
+<translation id="383465348367842624">Часть адреса до символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Обычный режим</translation>
+<translation id="3889183436948184105">версия</translation>
+<translation id="3920932319529768807">заключение</translation>
+<translation id="3924558731517983934">приложение</translation>
+<translation id="3944740393230681990">пролог</translation>
+<translation id="3960700977367013758">полоса прокрутки</translation>
+<translation id="4103419683916926126">Миллисекунды</translation>
+<translation id="4151657705144244502">изображение</translation>
+<translation id="4160057747563657758">телефон</translation>
+<translation id="4193965531860883258">предисловие</translation>
+<translation id="4201051445878709314">Показать предыдущий месяц</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">панель меню</translation>
+<translation id="4360991593054037559">Введите допустимое значение. Ближайшие допустимые значения: <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Вопросы и ответы</translation>
+<translation id="4413860115965805769">кнопка меню</translation>
+<translation id="4444765639179266822">Похоже, тут написано "<ph name="OCR_TEXT" />"</translation>
+<translation id="4446524499724042288">ссылка на словарную статью</translation>
+<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4542388879936266156">осталось времени: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">форма</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">приложение</translation>
+<translation id="4718048029184481307">Воспроизведение в режиме "Картинка в картинке"</translation>
+<translation id="4742539557769756338">обложка</translation>
+<translation id="4748357248530471599">Переключить вырезанную область на полный экран</translation>
+<translation id="4757246831282535685">панель вкладок</translation>
+<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">поиск</translation>
+<translation id="4812940957355064477">Введите число.</translation>
+<translation id="4912536737030637138">запись в библиографии</translation>
+<translation id="4975562563186953947">Выбрано: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Включить звук</translation>
+<translation id="49969490063480558">Введите часть адреса после символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
+<translation id="5034860022980953847">индикатор хода выполнения</translation>
+<translation id="5090250355906949916">полоса воспроизведения видео</translation>
+<translation id="5093189678851173835">эпиграф</translation>
+<translation id="5117590920725113268">Показать следующий месяц</translation>
+<translation id="512758898067543763">заголовок строки</translation>
+<translation id="5143125788380636750">эпилог</translation>
+<translation id="5164977714490026579">Значение должно быть больше или равно <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> ПБ</translation>
+<translation id="5307600278924710095">Введите часть адреса до символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
+<translation id="5334352251556557839">Не удалось воспроизвести медиафайл.</translation>
+<translation id="5406322316791861025">фигура</translation>
+<translation id="5453733299334684579">элемент дерева</translation>
+<translation id="5466621249238537318">Выберите один или несколько файлов.</translation>
+<translation id="5468998798572797635">выход из полноэкранного режима</translation>
+<translation id="5516424706154626233">окно выбора даты</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">включение звука</translation>
+<translation id="5608153257855394627">выделение</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">Чтобы пропустить 10 секунд, нажмите дважды слева или справа.</translation>
+<translation id="5631759159893697722">аннотация</translation>
+<translation id="5643186887447432888">кнопка</translation>
+<translation id="5677946354068040947">дополнительные параметры</translation>
+<translation id="576709008726043716">введение</translation>
+<translation id="57838592816432529">Отключить звук</translation>
+<translation id="5860033963881614850">ВЫКЛ</translation>
+<translation id="588258955323874662">Полноэкранный режим</translation>
+<translation id="5888666972993069672">Транслируется на устройство "<ph name="DEVICE_FRIENDLY_NAME" />"</translation>
+<translation id="591047860372322273">Окно поиска</translation>
+<translation id="5939518447894949180">Сбросить</translation>
+<translation id="5966707198760109579">Неделя</translation>
+<translation id="5987525920412732405">кнопка счетчика</translation>
+<translation id="6011459053400940133">регулятор громкости</translation>
+<translation id="6015796118275082299">Год</translation>
+<translation id="6023896073578205740">список</translation>
+<translation id="6150588977291308318">библиография</translation>
+<translation id="6164829606128959761">счетчик</translation>
+<translation id="6166809985690652833">послесловие</translation>
+<translation id="6209276755895393898">Кажется, это "<ph name="DESCRIPTION" />"</translation>
+<translation id="6213469881011901533">словарь</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Выйти из режима "Картинка в картинке"</translation>
+<translation id="6398862346408813489">Показать панель выбора месяца</translation>
+<translation id="6404546809543547843">полоса воспроизведения</translation>
+<translation id="6443871981718447451">показать меню субтитров</translation>
+<translation id="6453774872122745852">благодарности</translation>
+<translation id="6475115390776617481">информация о соавторах, которые сейчас работают над этим документом</translation>
+<translation id="648732519525291180">окно выбора даты</translation>
+<translation id="6550675742724504774">Параметры</translation>
+<translation id="6572309429103589720">Грамматическая ошибка</translation>
+<translation id="658823671542763450">полноэкранный режим</translation>
+<translation id="663493177488814956">лента</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Удалить</translation>
+<translation id="668171684555832681">Другой...</translation>
+<translation id="6692633176391053278">счетчик</translation>
+<translation id="6709570249143506788">Плохое качество воспроизведения</translation>
+<translation id="6755330956360078551">подсказка</translation>
+<translation id="6790428901817661496">Воспроизвести</translation>
+<translation id="6820355525329141109">Не удалось загрузить плагин</translation>
+<translation id="6820615603175220800">ссылка на библиографию</translation>
+<translation id="6843725295806269523">отключить звук</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">выпускные данные</translation>
+<translation id="6934078000481955284">цитата</translation>
+<translation id="693476918119313863">Заголовок</translation>
+<translation id="6941933287844615239">скачать файл</translation>
+<translation id="6981594929165378967">вставка</translation>
+<translation id="6989848892321993519">Текст должен быть не короче <ph name="MIN_CHARACTERS" /> симв. Длина текста сейчас: 1 символ.</translation>
+<translation id="7034405885550056553">рекомендация</translation>
+<translation id="709897737746224366">Введите данные в указанном формате.</translation>
+<translation id="7118469954320184356">Нет описания.</translation>
+<translation id="7139483182332611405">вступление</translation>
+<translation id="7214187073215825913">информация о содержании</translation>
+<translation id="7263440858009898357">Выберите один из пунктов списка.</translation>
+<translation id="727747134524199931">заголовок столбца</translation>
+<translation id="7320576522385648310">Буферизация…</translation>
+<translation id="7353453495576941748">упоминание</translation>
+<translation id="7364796246159120393">Выберите файл</translation>
+<translation id="739024184232394898">Другое…</translation>
+<translation id="7405738980073107433">концевые сноски</translation>
+<translation id="7410239719251593705">Похоже, это контент для взрослых. Описания нет.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Скачать</translation>
+<translation id="7529102961911894712">обратная ссылка</translation>
+<translation id="7533959249147584474">Графическое изображение без описания</translation>
+<translation id="7647456547678091388">совет</translation>
+<translation id="7661956066982048809">графический документ</translation>
+<translation id="7673697353781729403">Часы</translation>
+<translation id="7681220483256441252">указатель</translation>
+<translation id="7740050170769002709">HTML-содержание</translation>
+<translation id="7745230546936012372">Чтобы получить недостающие описания изображений, откройте контекстное меню.</translation>
+<translation id="7750228210027921155">Картинка в картинке</translation>
+<translation id="775297008183122718">Неверная запись</translation>
+<translation id="7789962463072032349">Пауза</translation>
+<translation id="7802800022689234070">треугольник развертывания</translation>
+<translation id="7888071071722539607">Адрес электронной почты должен содержать символ "<ph name="ATSIGN" />". В адресе "<ph name="INVALIDADDRESS" />" отсутствует символ "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">разделитель</translation>
+<translation id="795667975304826397">Файл не выбран</translation>
+<translation id="8053789581856978548">поле поиска</translation>
+<translation id="8057695513531652401">примечание</translation>
+<translation id="8105797009065549151">ссылка на примечание</translation>
+<translation id="811583516810654505">Загружается описание...</translation>
+<translation id="8117451130807776954">На этой неделе</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="8208673686607688524">выбор местного времени и даты</translation>
+<translation id="8261464734335370856">Орфографическая ошибка</translation>
+<translation id="8284326494547611709">Титры</translation>
+<translation id="8346634859695247203">раздел</translation>
+<translation id="835897206747267392">Недопустимые данные.</translation>
+<translation id="8403857369060869934">прошло времени: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">часть</translation>
+<translation id="8433900881053900389">панель инструментов</translation>
+<translation id="8444882422881193423">Число файлов: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Выберите файл.</translation>
+<translation id="8461852803063341183">переключатель</translation>
+<translation id="8474886197722836894">посвящение</translation>
+<translation id="8531739829932800271">список опечаток</translation>
+<translation id="8534579021159131403">Минуты</translation>
+<translation id="8541249477527128034">управление мультимедиа</translation>
+<translation id="8550857728288566671">графический символ</translation>
+<translation id="8583702881314752957">список описаний</translation>
+<translation id="8597182159515967513">заголовок</translation>
+<translation id="860475260694818407">оглавление</translation>
+<translation id="8613126697340063924">управлять воспроизведением на удаленных устройствах</translation>
+<translation id="862370744433916922">подзаголовок</translation>
+<translation id="8711688047404765493">выход</translation>
+<translation id="8750798805984357768">Выберите один из вариантов.</translation>
+<translation id="8808573423886751634">глава</translation>
+<translation id="8822203815165896261">информация об авторах</translation>
+<translation id="8845239796550121995">Транслируется на телевизор</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Ошибка при воспроизведении видео</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> КБ</translation>
+<translation id="8987927404178983737">Месяц</translation>
+<translation id="901493112792887934">текущее время в секундах</translation>
+<translation id="901834265349196618">электронная почта</translation>
+<translation id="9048119486235211610">навигация</translation>
+<translation id="9062295712474918030">документ</translation>
+<translation id="9093215626363556771">выйти из режима "Картинка в картинке"</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Другое…</translation>
+<translation id="9138385573473225930">оповещение</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, начинается <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Картинка в картинке</translation>
+<translation id="9168329111483466115">сноска</translation>
+<translation id="954003015749068518">включить режим "Картинка в картинке"</translation>
+<translation id="966787709310836684">меню</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..9bf9e7e7d14
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sk.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sk">
+<translation id="1018939186200882850">položka ponuky</translation>
+<translation id="10623998915015855">tlačidlo prepínania</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="1171774979989969504">Zadajte e-mailovú adresu.</translation>
+<translation id="1178581264944972037">Pozastaviť</translation>
+<translation id="1188858454923323853">doplnkové</translation>
+<translation id="1206619573307042055">pohyblivý prvok</translation>
+<translation id="1206693055195146388">posúvač</translation>
+<translation id="1211441953136645838">vysvetlivka</translation>
+<translation id="1281252709823657822">dialóg</translation>
+<translation id="1335095011850992622">titulky</translation>
+<translation id="1342835525016946179">článok</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">oblasť</translation>
+<translation id="1591562245178063882">Tento mesiac</translation>
+<translation id="1637811476055996098">Vybrať súbory</translation>
+<translation id="1650423536718072820">obsiahnutý citát</translation>
+<translation id="1727886345390570319">skryť ponuku skrytých titulkov</translation>
+<translation id="1729654308190250600">Zadajte e-mailovú adresu, ktorá nie je prázdna hodnota.</translation>
+<translation id="1758486001363313524">Iné...</translation>
+<translation id="1806710327868736751">dialóg_upozornenia</translation>
+<translation id="1821985195704844674">stromová mriežka</translation>
+<translation id="1822429046913737220">AM / PM</translation>
+<translation id="1832974991323546415">prehrať na vzdialenom zariadení</translation>
+<translation id="190587075670221089">odstránenie</translation>
+<translation id="1907737156431278478">príklad</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">stav</translation>
+<translation id="1938124657309484470">Hodnota musí byť <ph name="MAXIMUM_DATE_OR_TIME" /> alebo skôr.</translation>
+<translation id="1946271899482435442">Zobraziť výber dátumu</translation>
+<translation id="1993104285338243655">Prepnuté na zrkadlenie</translation>
+<translation id="2060505056492490888">Znak <ph name="DOT" /> je v doméne <ph name="INVALIDDOMAIN" /> použitý na nesprávnej pozícii.</translation>
+<translation id="2148716181193084225">Dnes</translation>
+<translation id="2158401438286456825">zoznam strán</translation>
+<translation id="2226276347425096477">Tento text musíte skrátiť na <ph name="MAX_CHARACTERS" /> znakov alebo menej (súčasný počet znakov: <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="2246498165605549352">Miestny súbor</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týždeň, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Skladba <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">začiarkavacie políčko</translation>
+<translation id="2311842470354187719">zlom strany</translation>
+<translation id="2335594187091864976">výber dátumu a času</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>
+<translation id="2508569020611168319">zoznam kariet</translation>
+<translation id="2561842179657104141">zobraziť ďalšie ovládacie prvky médií</translation>
+<translation id="2572483411312390101">prehrať</translation>
+<translation id="2613802280814924224">Zadajte platnú hodnotu. Najbližšia platná hodnota je <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Odoslať</translation>
+<translation id="2657045182931379222">grafický objekt</translation>
+<translation id="2674318244760992338">päta</translation>
+<translation id="2709516037105925701">Automatické dopĺňanie</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="2725963129578236554">komentáre</translation>
+<translation id="2746543609216772311">Hodnota musí byť <ph name="MINIMUM_DATE_OR_TIME" /> alebo neskôr.</translation>
+<translation id="2759744352195237655">kontextové tlačidlo</translation>
+<translation id="2761667185364618470">Ak chcete pokračovať, začiarknite toto políčko.</translation>
+<translation id="2844350028562914727">podrobnosti</translation>
+<translation id="2896972712917208084">skupina prepínačov</translation>
+<translation id="2908441821576996758">Zadajte zoznam e-mailových adries oddelených čiarkou.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">odkaz</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Zadajte platnú hodnotu. Pole obsahuje neúplnú hodnotu alebo neplatný dátum.</translation>
+<translation id="3078740164268491126">tabuľka</translation>
+<translation id="3086746722712840547">poznámka</translation>
+<translation id="310520048233152454">Zadajte webovú adresu.</translation>
+<translation id="3175736971608411871">časovač</translation>
+<translation id="3199563858620722075">pole s výberom</translation>
+<translation id="3450233048674729344">Hodnota musí byť menšia alebo rovná hodnote <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definícia</translation>
+<translation id="3557673793733683882">nadpis <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">výber týždňa</translation>
+<translation id="3685101356851116974">Neoznačený obrázok</translation>
+<translation id="3706100364254443312">prepínač</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Ukončiť obraz v obraze</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">výraz</translation>
+<translation id="3822383571486410024">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálny počet znakov je <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Časť pred znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3846214748874656680">Ukončiť režim celej obrazovky</translation>
+<translation id="3889183436948184105">verzia</translation>
+<translation id="3920932319529768807">záver</translation>
+<translation id="3924558731517983934">aplikácia</translation>
+<translation id="3944740393230681990">prológ</translation>
+<translation id="3960700977367013758">posúvač</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">grafika</translation>
+<translation id="4160057747563657758">telefón</translation>
+<translation id="4193965531860883258">predhovor</translation>
+<translation id="4201051445878709314">Zobraziť predchádzajúci mesiac</translation>
+<translation id="421884353938374759">výber farieb</translation>
+<translation id="4248100235867064564">panel s ponukami</translation>
+<translation id="4360991593054037559">Zadajte platnú hodnotu. Najbližšie platné hodnoty sú <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Otázky a odpovede</translation>
+<translation id="4413860115965805769">tlačidlo ponuky</translation>
+<translation id="4444765639179266822">Zrejme znamená: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">glosárový termín</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">zostávajúci čas: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulár</translation>
+<translation id="4661075872484491155">strom</translation>
+<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">príloha</translation>
+<translation id="4718048029184481307">Prehráva sa v režime obrazu v obraze</translation>
+<translation id="4742539557769756338">titulná strana</translation>
+<translation id="4748357248530471599">prepnúť výrez obrazovky na celú obrazovku</translation>
+<translation id="4757246831282535685">panel karty</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Zadajte číslo.</translation>
+<translation id="4912536737030637138">bibliografický záznam</translation>
+<translation id="4975562563186953947">Počet vybraných položiek: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Zapnúť zvuk</translation>
+<translation id="49969490063480558">Zadajte časť za znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
+<translation id="5034860022980953847">indikátor priebehu</translation>
+<translation id="5090250355906949916">posúvač časovej osi videa</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Zobraziť ďalší mesiac</translation>
+<translation id="512758898067543763">hlavička riadka</translation>
+<translation id="5143125788380636750">epilóg</translation>
+<translation id="5164977714490026579">Hodnota musí byť väčšia alebo rovná hodnote <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Zadajte časť pred znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
+<translation id="5334352251556557839">Nepodarilo sa prehrať médiá.</translation>
+<translation id="5406322316791861025">hodnota</translation>
+<translation id="5453733299334684579">položka stromu</translation>
+<translation id="5466621249238537318">Vyberte jeden alebo viac súborov.</translation>
+<translation id="5468998798572797635">ukončiť režim celej obrazovky</translation>
+<translation id="5516424706154626233">výber dátumu</translation>
+<translation id="5537725057119320332">Prenášať</translation>
+<translation id="5546461542133609677">obnoviť zvuk</translation>
+<translation id="5608153257855394627">zvýraznenie</translation>
+<translation id="561939826962581046">čas</translation>
+<translation id="5630795885300617244">Dvojitým klepnutím doľava alebo doprava preskočíte o 10 s</translation>
+<translation id="5631759159893697722">abstrakt</translation>
+<translation id="5643186887447432888">tlačidlo</translation>
+<translation id="5677946354068040947">ďalšie možnosti</translation>
+<translation id="576709008726043716">úvod</translation>
+<translation id="57838592816432529">Vypnúť zvuk</translation>
+<translation id="5860033963881614850">Vypnuté</translation>
+<translation id="588258955323874662">Celá obrazovka</translation>
+<translation id="5888666972993069672">Prenáša sa do zariadenia <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">vyhľadávacie pole</translation>
+<translation id="5939518447894949180">Resetovať</translation>
+<translation id="5966707198760109579">Týždeň</translation>
+<translation id="5987525920412732405">tlačidlo otáčania</translation>
+<translation id="6011459053400940133">posúvač hlasitosti</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">zoznamové pole</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">meter</translation>
+<translation id="6166809985690652833">doslov</translation>
+<translation id="6209276755895393898">Zrejme to bude: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosár</translation>
+<translation id="6281763101136022427">Webová adresa</translation>
+<translation id="6310801910862476708">Ukončiť obraz v obraze</translation>
+<translation id="6398862346408813489">Zobraziť panel na výber mesiaca</translation>
+<translation id="6404546809543547843">posúvač časovej osi zvuku</translation>
+<translation id="6443871981718447451">zobraziť ponuku skrytých titulkov</translation>
+<translation id="6453774872122745852">poďakovanie</translation>
+<translation id="6475115390776617481">aktuálny spolupracujúci</translation>
+<translation id="648732519525291180">výber času</translation>
+<translation id="6550675742724504774">Možnosti</translation>
+<translation id="6572309429103589720">Neplatná gramatika</translation>
+<translation id="658823671542763450">prejsť do režimu celej obrazovky</translation>
+<translation id="663493177488814956">informačný kanál</translation>
+<translation id="6637586476836377253">denník</translation>
+<translation id="6643016212128521049">Vymazať</translation>
+<translation id="668171684555832681">Iný...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Nízka kvalita prehrávania</translation>
+<translation id="6755330956360078551">popis</translation>
+<translation id="6790428901817661496">Prehrať</translation>
+<translation id="6820355525329141109">Doplnok sa nepodarilo načítať.</translation>
+<translation id="6820615603175220800">bibliografický odkaz</translation>
+<translation id="6843725295806269523">stlmiť</translation>
+<translation id="6885760532393684712">adresár</translation>
+<translation id="689129560213475294">kolofón</translation>
+<translation id="6934078000481955284">značka blockquote</translation>
+<translation id="693476918119313863">hlavička</translation>
+<translation id="6941933287844615239">stiahnuť médiá</translation>
+<translation id="6981594929165378967">vloženie</translation>
+<translation id="6989848892321993519">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálne používate jeden znak).</translation>
+<translation id="7034405885550056553">návrh</translation>
+<translation id="709897737746224366">Zadajte hodnotu zodpovedajúcu požadovanému formátu.</translation>
+<translation id="7118469954320184356">Nie je k dispozícii žiadny popis.</translation>
+<translation id="7139483182332611405">predslov</translation>
+<translation id="7214187073215825913">informácie o obsahu</translation>
+<translation id="7263440858009898357">Vyberte položku zo zoznamu.</translation>
+<translation id="727747134524199931">hlavička stĺpca</translation>
+<translation id="7320576522385648310">ukladá sa do vyrovnávacej pamäte</translation>
+<translation id="7353453495576941748">poďakovanie</translation>
+<translation id="7364796246159120393">Vybrať súbor</translation>
+<translation id="739024184232394898">Iné...</translation>
+<translation id="7405738980073107433">vysvetlivky</translation>
+<translation id="7410239719251593705">Zrejme zahŕňa obsah pre dospelých. Nie je k dispozícii žiadny popis.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">karta</translation>
+<translation id="7514365320538308">Stiahnuť</translation>
+<translation id="7529102961911894712">spätný odkaz</translation>
+<translation id="7533959249147584474">Neoznačený obrázok</translation>
+<translation id="7647456547678091388">tip</translation>
+<translation id="7661956066982048809">grafický dokument</translation>
+<translation id="7673697353781729403">Hodiny</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">Obsah HTML</translation>
+<translation id="7745230546936012372">Ak chcete získať chýbajúce popisy obrázka, otvorte kontextovú ponuku.</translation>
+<translation id="7750228210027921155">Obraz v obraze</translation>
+<translation id="775297008183122718">Neplatný vstup</translation>
+<translation id="7789962463072032349">pozastaviť</translation>
+<translation id="7802800022689234070">trojuholníkové tlačidlo na zobrazenie skrytého obsahu</translation>
+<translation id="7888071071722539607">Uveďte v e-mailovej adrese znak <ph name="ATSIGN" />. V adrese <ph name="INVALIDADDRESS" /> znak <ph name="ATSIGN" /> chýba.</translation>
+<translation id="7891486169920085145">rozdeľovač</translation>
+<translation id="795667975304826397">Nie je vybratý žiadny súbor</translation>
+<translation id="8053789581856978548">textové pole pre vyhľadávanie</translation>
+<translation id="8057695513531652401">upozornenie</translation>
+<translation id="8105797009065549151">odkaz na poznámku</translation>
+<translation id="811583516810654505">Načítava sa popis…</translation>
+<translation id="8117451130807776954">Tento týždeň</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="8208673686607688524">výber miestneho dátumu a času</translation>
+<translation id="8261464734335370856">Neplatný pravopis</translation>
+<translation id="8284326494547611709">Titulky</translation>
+<translation id="8346634859695247203">sekcia</translation>
+<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8403857369060869934">uplynutý čas: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">časť</translation>
+<translation id="8433900881053900389">panel s nástrojmi</translation>
+<translation id="8444882422881193423">Počet súborov: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Vyberte súbor.</translation>
+<translation id="8461852803063341183">prepínač</translation>
+<translation id="8474886197722836894">venovanie</translation>
+<translation id="8531739829932800271">erráta</translation>
+<translation id="8534579021159131403">Minúty</translation>
+<translation id="8541249477527128034">ovládanie médií</translation>
+<translation id="8550857728288566671">grafický symbol</translation>
+<translation id="8583702881314752957">zoznam definícií</translation>
+<translation id="8597182159515967513">nadpis</translation>
+<translation id="860475260694818407">obsah</translation>
+<translation id="8613126697340063924">ovládať vzdialené prehrávanie</translation>
+<translation id="862370744433916922">podnadpis</translation>
+<translation id="8711688047404765493">výstup</translation>
+<translation id="8750798805984357768">Vyberte jednu z týchto možností.</translation>
+<translation id="8808573423886751634">kapitola</translation>
+<translation id="8822203815165896261">informácie o autorovi</translation>
+<translation id="8845239796550121995">Prenáša sa do televízora</translation>
+<translation id="8851136666856101339">hlavné</translation>
+<translation id="8875657656876809964">Chyba prehrávania videa</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Mesiac</translation>
+<translation id="901493112792887934">aktuálny čas v sekundách</translation>
+<translation id="901834265349196618">e-mail</translation>
+<translation id="9048119486235211610">navigácia</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">ukončiť obraz v obraze</translation>
+<translation id="9108370397979208512">matematika</translation>
+<translation id="9132465097189459683">Iné...</translation>
+<translation id="9138385573473225930">upozornenie</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> začínajúci <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Obraz v obraze</translation>
+<translation id="9168329111483466115">poznámka pod čiarou</translation>
+<translation id="954003015749068518">zapnúť obraz v obraze</translation>
+<translation id="966787709310836684">ponuka</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..1c7b534f315
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sl.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sl">
+<translation id="1018939186200882850">menijski element</translation>
+<translation id="10623998915015855">preklopni gumb</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="1171774979989969504">Vnesite e-poštni naslov</translation>
+<translation id="1178581264944972037">Prekini</translation>
+<translation id="1188858454923323853">dopolnilno</translation>
+<translation id="1206619573307042055">potujoči napis</translation>
+<translation id="1206693055195146388">drsnik</translation>
+<translation id="1211441953136645838">končna opomba</translation>
+<translation id="1281252709823657822">pogovorno okno</translation>
+<translation id="1335095011850992622">seznam sodelujočih</translation>
+<translation id="1342835525016946179">člnk</translation>
+<translation id="1359897965706325498">pasica</translation>
+<translation id="1589122976691792535">območje</translation>
+<translation id="1591562245178063882">Ta mesec</translation>
+<translation id="1637811476055996098">Izberi datoteke</translation>
+<translation id="1650423536718072820">pojavni citat</translation>
+<translation id="1727886345390570319">skrij meni s podnapisi</translation>
+<translation id="1729654308190250600">Vnesite e-poštni naslov (polje ne sme biti prazno).</translation>
+<translation id="1758486001363313524">Drugo ...</translation>
+<translation id="1806710327868736751">pogovorno okno z opozorilom</translation>
+<translation id="1821985195704844674">drevesna mreža</translation>
+<translation id="1822429046913737220">Dopoldne/popoldne</translation>
+<translation id="1832974991323546415">predvajanje v oddaljeni napravi</translation>
+<translation id="190587075670221089">brisanje</translation>
+<translation id="1907737156431278478">primer</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">stanje</translation>
+<translation id="1938124657309484470">Vrednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ali prej.</translation>
+<translation id="1946271899482435442">Pokaži izbirnik datuma</translation>
+<translation id="1993104285338243655">Preklopljeno na zrcaljenje</translation>
+<translation id="2060505056492490888">»<ph name="DOT" />« je na napačnem mestu v »<ph name="INVALIDDOMAIN" />«.</translation>
+<translation id="2148716181193084225">Danes</translation>
+<translation id="2158401438286456825">seznam strani</translation>
+<translation id="2226276347425096477">Skrajšajte to besedilo na <ph name="MAX_CHARACTERS" /> znakov ali manj (trenutno uporabljate <ph name="CURRENT_LENGTH" /> znakov).</translation>
+<translation id="2246498165605549352">Lokalna datoteka</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. teden, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Besedilni posnetek <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">potrditveno polje</translation>
+<translation id="2311842470354187719">prelom strani</translation>
+<translation id="2335594187091864976">izbirnik datuma in ure</translation>
+<translation id="245932805758469625">preostale sekunde videoposnetka</translation>
+<translation id="248395913932153421">Dan</translation>
+<translation id="2507943997699731163">Izpolnite to polje</translation>
+<translation id="2508569020611168319">seznam zavihkov</translation>
+<translation id="2561842179657104141">prikaz več kontrolnikov za predstavnost</translation>
+<translation id="2572483411312390101">predvajanje</translation>
+<translation id="2613802280814924224">Vnesite veljavno vrednost. Najbližja veljavna vrednost je <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Pošlji</translation>
+<translation id="2657045182931379222">grafični predmet</translation>
+<translation id="2674318244760992338">noga</translation>
+<translation id="2709516037105925701">Samodejno izpolnjevanje</translation>
+<translation id="2723001399770238859">zvok</translation>
+<translation id="2725963129578236554">komentarji</translation>
+<translation id="2746543609216772311">Vrednost mora biti <ph name="MINIMUM_DATE_OR_TIME" /> ali pozneje.</translation>
+<translation id="2759744352195237655">pojavni gumb</translation>
+<translation id="2761667185364618470">Potrdite to polje, če želite nadaljevati.</translation>
+<translation id="2844350028562914727">podrobnosti</translation>
+<translation id="2896972712917208084">skupina izbirnih gumbov</translation>
+<translation id="2908441821576996758">Vnesite seznam e-poštnih naslovov, ločenih z vejicami</translation>
+<translation id="2940813599313844715">predmet</translation>
+<translation id="3040011195152428237">povezava</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Vnesite veljavno vrednost. Vnos v polje je nepopoln ali vsebuje neveljaven datum.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">opmb</translation>
+<translation id="310520048233152454">Vnesite URL.</translation>
+<translation id="3175736971608411871">merilnik časa</translation>
+<translation id="3199563858620722075">kombinirano polje</translation>
+<translation id="3450233048674729344">Vrednost mora biti manjša od <ph name="MAXIMUM" /> ali enaka.</translation>
+<translation id="3486220673238053218">opredelitev</translation>
+<translation id="3557673793733683882">naslov <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">izbirnik tedna</translation>
+<translation id="3685101356851116974">Neoznačena slika</translation>
+<translation id="3706100364254443312">preklop</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Zapri način slike v sliki</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">izraz</translation>
+<translation id="3822383571486410024">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate toliko znakov: <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Del pred »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
+<translation id="3846214748874656680">Zapri celozaslonski način</translation>
+<translation id="3889183436948184105">različica</translation>
+<translation id="3920932319529768807">sklep</translation>
+<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3944740393230681990">uvod</translation>
+<translation id="3960700977367013758">drsni trak</translation>
+<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="4151657705144244502">grafični element</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">predgovor</translation>
+<translation id="4201051445878709314">Prikaz prejšnjega meseca</translation>
+<translation id="421884353938374759">izbirnik barve</translation>
+<translation id="4248100235867064564">menijska vrstica</translation>
+<translation id="4360991593054037559">Vnesite veljavno vrednost. Najbližji veljavni vrednosti sta <ph name="VALID_VALUE_LOW" /> in <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Vprašanja</translation>
+<translation id="4413860115965805769">menijski gumb</translation>
+<translation id="4444765639179266822">Videti je, da piše: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">vnos v glosarju</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">preostali čas: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">obrazec</translation>
+<translation id="4661075872484491155">drevo</translation>
+<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
+<translation id="4668956016107839909">dodatek</translation>
+<translation id="4718048029184481307">Predvajanje v načinu slike v sliki</translation>
+<translation id="4742539557769756338">naslovnica</translation>
+<translation id="4748357248530471599">preklop celozaslonskega načina na zarezo zaslona</translation>
+<translation id="4757246831282535685">podokno z zavihki</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Vnesite številko.</translation>
+<translation id="4912536737030637138">bibliografski vnos</translation>
+<translation id="4975562563186953947">Št. izbranih: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Vklopi zvok</translation>
+<translation id="49969490063480558">Vnesite nekaj po znaku »<ph name="ATSIGN" />«. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
+<translation id="5034860022980953847">kazalnik poteka</translation>
+<translation id="5090250355906949916">časovni krmilnik za predvajanje videoposnetka</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Prikaz naslednjega meseca</translation>
+<translation id="512758898067543763">glava vrstice</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Vrednost mora biti večja od <ph name="MINIMUM" /> ali enaka.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Vnesite nekaj in nato <ph name="ATSIGN" />. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
+<translation id="5334352251556557839">Predstavnosti ni mogoče predvajati.</translation>
+<translation id="5406322316791861025">številka</translation>
+<translation id="5453733299334684579">element drevesa</translation>
+<translation id="5466621249238537318">Izberite eno ali več datotek.</translation>
+<translation id="5468998798572797635">izhod iz celozaslonskega načina</translation>
+<translation id="5516424706154626233">izbirnik datuma</translation>
+<translation id="5537725057119320332">Predvajanje</translation>
+<translation id="5546461542133609677">vklop zvoka</translation>
+<translation id="5608153257855394627">označeno</translation>
+<translation id="561939826962581046">čas</translation>
+<translation id="5630795885300617244">Dvakrat se dotaknite levo ali desno, da preskočite 10 s</translation>
+<translation id="5631759159893697722">izvleček</translation>
+<translation id="5643186887447432888">gumb</translation>
+<translation id="5677946354068040947">več možnosti</translation>
+<translation id="576709008726043716">uvod</translation>
+<translation id="57838592816432529">Izklopi zvok</translation>
+<translation id="5860033963881614850">Izklopljeno</translation>
+<translation id="588258955323874662">Celozaslonsko</translation>
+<translation id="5888666972993069672">Predvajanje v napravi <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">iskalno polje</translation>
+<translation id="5939518447894949180">Ponastavi</translation>
+<translation id="5966707198760109579">Teden</translation>
+<translation id="5987525920412732405">pomikalnik</translation>
+<translation id="6011459053400940133">drsnik za glasnost</translation>
+<translation id="6015796118275082299">Leto</translation>
+<translation id="6023896073578205740">polje s seznamom</translation>
+<translation id="6150588977291308318">bibliografija</translation>
+<translation id="6164829606128959761">merilnik</translation>
+<translation id="6166809985690652833">spremna beseda</translation>
+<translation id="6209276755895393898">Videti je kot: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">glosar</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Zapri način slike v sliki</translation>
+<translation id="6398862346408813489">Prikaz podokna za izbiro meseca</translation>
+<translation id="6404546809543547843">časovni krmilnik za predvajanje zvoka</translation>
+<translation id="6443871981718447451">pokaži meni s podnapisi</translation>
+<translation id="6453774872122745852">zahvala</translation>
+<translation id="6475115390776617481">prisotnost v živo</translation>
+<translation id="648732519525291180">izbirnik ure</translation>
+<translation id="6550675742724504774">Možnosti</translation>
+<translation id="6572309429103589720">Neveljavna slovnica</translation>
+<translation id="658823671542763450">prehod v celozaslonski način</translation>
+<translation id="663493177488814956">vir</translation>
+<translation id="6637586476836377253">dnevn</translation>
+<translation id="6643016212128521049">Izbriši</translation>
+<translation id="668171684555832681">Drugo ...</translation>
+<translation id="6692633176391053278">kontrolnik</translation>
+<translation id="6709570249143506788">Slaba kakovost predvajanja</translation>
+<translation id="6755330956360078551">opis orodja</translation>
+<translation id="6790428901817661496">Predvajanje</translation>
+<translation id="6820355525329141109">Vtičnika ni bilo mogoče naložiti.</translation>
+<translation id="6820615603175220800">bibliografski viri</translation>
+<translation id="6843725295806269523">nemo</translation>
+<translation id="6885760532393684712">imenik</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">daljši citat</translation>
+<translation id="693476918119313863">glava</translation>
+<translation id="6941933287844615239">prenos predstavnosti</translation>
+<translation id="6981594929165378967">vstavljanje</translation>
+<translation id="6989848892321993519">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate en znak).</translation>
+<translation id="7034405885550056553">predlog</translation>
+<translation id="709897737746224366">Poskrbite za ujemanje z zahtevano obliko.</translation>
+<translation id="7118469954320184356">Ni opisa.</translation>
+<translation id="7139483182332611405">predgovor</translation>
+<translation id="7214187073215825913">podatki o vsebini</translation>
+<translation id="7263440858009898357">Izberite element s seznama.</translation>
+<translation id="727747134524199931">glava stolpca</translation>
+<translation id="7320576522385648310">medpomnjenje</translation>
+<translation id="7353453495576941748">zasluga</translation>
+<translation id="7364796246159120393">Izberite datoteko</translation>
+<translation id="739024184232394898">Drugo ...</translation>
+<translation id="7405738980073107433">končne opombe</translation>
+<translation id="7410239719251593705">Videti je, da vsebuje vsebino za odrasle. Ni opisa.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tabulatorka</translation>
+<translation id="7514365320538308">Prenos</translation>
+<translation id="7529102961911894712">povratna povezava</translation>
+<translation id="7533959249147584474">Neoznačena grafika</translation>
+<translation id="7647456547678091388">namig</translation>
+<translation id="7661956066982048809">grafični dokument</translation>
+<translation id="7673697353781729403">Ure</translation>
+<translation id="7681220483256441252">kazalo</translation>
+<translation id="7740050170769002709">Vsebina HTML</translation>
+<translation id="7745230546936012372">Če želite prejeti manjkajoče opise slike, odprite kontekstni meni.</translation>
+<translation id="7750228210027921155">Slika v sliki</translation>
+<translation id="775297008183122718">Neveljaven vnos</translation>
+<translation id="7789962463072032349">premor</translation>
+<translation id="7802800022689234070">trikotnik z dodatno vsebino</translation>
+<translation id="7888071071722539607">V e-poštnem naslovu mora biti znak »<ph name="ATSIGN" />«. V naslovu »<ph name="INVALIDADDRESS" />« manjka »<ph name="ATSIGN" />«.</translation>
+<translation id="7891486169920085145">razdelilnik</translation>
+<translation id="795667975304826397">Nobena datoteka ni izbrana</translation>
+<translation id="8053789581856978548">besedilno polje za iskanje</translation>
+<translation id="8057695513531652401">kritika</translation>
+<translation id="8105797009065549151">sklicevanje na opombo</translation>
+<translation id="811583516810654505">Pridobivanje opisa …</translation>
+<translation id="8117451130807776954">Ta teden</translation>
+<translation id="8199524924445686405">llll</translation>
+<translation id="8208673686607688524">izbirnik lokalnega datuma in ure</translation>
+<translation id="8261464734335370856">Neveljavno črkovanje</translation>
+<translation id="8284326494547611709">Napisi</translation>
+<translation id="8346634859695247203">razdelek</translation>
+<translation id="835897206747267392">Neveljavna vrednost.</translation>
+<translation id="8403857369060869934">pretečeni čas: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">del</translation>
+<translation id="8433900881053900389">orodna vrstica</translation>
+<translation id="8444882422881193423">Število datotek: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Izberite datoteko.</translation>
+<translation id="8461852803063341183">izbirni gumb</translation>
+<translation id="8474886197722836894">posvetilo</translation>
+<translation id="8531739829932800271">popravki</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="8541249477527128034">nadziranje predstavnosti</translation>
+<translation id="8550857728288566671">grafični simbol</translation>
+<translation id="8583702881314752957">seznam opredelitev</translation>
+<translation id="8597182159515967513">naslov</translation>
+<translation id="860475260694818407">kazalo</translation>
+<translation id="8613126697340063924">upravljanje oddaljenega predvajanja</translation>
+<translation id="862370744433916922">podnaslov</translation>
+<translation id="8711688047404765493">izhod</translation>
+<translation id="8750798805984357768">Izberite eno od teh možnosti.</translation>
+<translation id="8808573423886751634">poglavje</translation>
+<translation id="8822203815165896261">podatki o avtorstvu</translation>
+<translation id="8845239796550121995">Predvajanje na televizorju</translation>
+<translation id="8851136666856101339">glavn</translation>
+<translation id="8875657656876809964">Napaka pri predvajanju videoposnetka</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Mesec</translation>
+<translation id="901493112792887934">trenutni čas v sekundah</translation>
+<translation id="901834265349196618">e-pošta</translation>
+<translation id="9048119486235211610">krmarjenje</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">zapiranje načina slike v sliki</translation>
+<translation id="9108370397979208512">matematika</translation>
+<translation id="9132465097189459683">Drugo ...</translation>
+<translation id="9138385573473225930">opozorilo</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, začne se <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Slika v sliki</translation>
+<translation id="9168329111483466115">sprotna opomba</translation>
+<translation id="954003015749068518">odpiranje načina slike v sliki</translation>
+<translation id="966787709310836684">meni</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..a31a9f3d09e
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sr.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sr">
+<translation id="1018939186200882850">ставка менија</translation>
+<translation id="10623998915015855">дугме за укључивање/искључивање</translation>
+<translation id="1088086359088493902">Секунде</translation>
+<translation id="1171774979989969504">Унесите имејл адресу.</translation>
+<translation id="1178581264944972037">Паузирај</translation>
+<translation id="1188858454923323853">комплементарно</translation>
+<translation id="1206619573307042055">покретни текст</translation>
+<translation id="1206693055195146388">клизач</translation>
+<translation id="1211441953136645838">завршна напомена</translation>
+<translation id="1281252709823657822">дијалог</translation>
+<translation id="1335095011850992622">заслуге</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">банер</translation>
+<translation id="1589122976691792535">регион</translation>
+<translation id="1591562245178063882">Овај месец</translation>
+<translation id="1637811476055996098">Избор датотека</translation>
+<translation id="1650423536718072820">кратки цитат</translation>
+<translation id="1727886345390570319">сакријте мени опционалног титла</translation>
+<translation id="1729654308190250600">Унесите имејл адресу која није празна.</translation>
+<translation id="1758486001363313524">Друго...</translation>
+<translation id="1806710327868736751">дијалог обавештења</translation>
+<translation id="1821985195704844674">мрежа стабла</translation>
+<translation id="1822429046913737220">пре подне/по подне</translation>
+<translation id="1832974991323546415">пуштајте на удаљеном уређају</translation>
+<translation id="190587075670221089">брисање</translation>
+<translation id="1907737156431278478">пример</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="1938124657309484470">Вредност мора да буде <ph name="MAXIMUM_DATE_OR_TIME" /> или старија.</translation>
+<translation id="1946271899482435442">Прикажи бирач датума</translation>
+<translation id="1993104285338243655">Пребачено је на пресликавање</translation>
+<translation id="2060505056492490888">„<ph name="DOT" />“ је стављено на погрешно место у „<ph name="INVALIDDOMAIN" />“.</translation>
+<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="2247351761944213033"><ph name="WEEKNUMBER" />. недеља, <ph name="YEAR" />.</translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />. песма</translation>
+<translation id="2291999235780842123">поље за потврду</translation>
+<translation id="2311842470354187719">прелом странице</translation>
+<translation id="2335594187091864976">бирач датума и времена</translation>
+<translation id="245932805758469625">број преосталих секунди видео снимка</translation>
+<translation id="248395913932153421">Дан</translation>
+<translation id="2507943997699731163">Попуните ово поље.</translation>
+<translation id="2508569020611168319">листа картица</translation>
+<translation id="2561842179657104141">прикажи више контрола за медије</translation>
+<translation id="2572483411312390101">пустите</translation>
+<translation id="2613802280814924224">Унесите важећу вредност. Најближа важећа вредност је <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Пошаљи</translation>
+<translation id="2657045182931379222">графички објекат</translation>
+<translation id="2674318244760992338">подножје</translation>
+<translation id="2709516037105925701">Аутоматско попуњавање</translation>
+<translation id="2723001399770238859">аудио</translation>
+<translation id="2725963129578236554">коментари</translation>
+<translation id="2746543609216772311">Вредност мора да буде <ph name="MINIMUM_DATE_OR_TIME" /> или новија.</translation>
+<translation id="2759744352195237655">искачуће дугме</translation>
+<translation id="2761667185364618470">Потврдите избор у овом пољу за потврду уколико желите да наставите.</translation>
+<translation id="2844350028562914727">детаљи</translation>
+<translation id="2896972712917208084">група дугмади за избор</translation>
+<translation id="2908441821576996758">Унесите листу имејл адреса раздвојених зарезима.</translation>
+<translation id="2940813599313844715">објекат</translation>
+<translation id="3040011195152428237">веза</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Унесите важећу вредност. Поље није попуњено или садржи неважећи датум.</translation>
+<translation id="3078740164268491126">табела</translation>
+<translation id="3086746722712840547">белешка</translation>
+<translation id="310520048233152454">Унесите URL адресу.</translation>
+<translation id="3175736971608411871">тајмер</translation>
+<translation id="3199563858620722075">комбиновани оквир</translation>
+<translation id="3450233048674729344">Вредност сме да буде највише <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">дефиниција</translation>
+<translation id="3557673793733683882">заглавље <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">бирач недеља</translation>
+<translation id="3685101356851116974">Неозначена слика</translation>
+<translation id="3706100364254443312">прекидач</translation>
+<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Изађи из режима слике у слици</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">термин</translation>
+<translation id="3822383571486410024">Продужите овај текст на <ph name="MIN_CHARACTERS" /> знак(ов)а или више (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
+<translation id="383465348367842624">Део пре „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3846214748874656680">Изађи из целог екрана</translation>
+<translation id="3889183436948184105">ревизија</translation>
+<translation id="3920932319529768807">закључак</translation>
+<translation id="3924558731517983934">апликација</translation>
+<translation id="3944740393230681990">пролог</translation>
+<translation id="3960700977367013758">трака за померање</translation>
+<translation id="4103419683916926126">Милисекунде</translation>
+<translation id="4151657705144244502">графички елемент</translation>
+<translation id="4160057747563657758">број телефона</translation>
+<translation id="4193965531860883258">предговор</translation>
+<translation id="4201051445878709314">Прикажи претходни месец</translation>
+<translation id="421884353938374759">бирач боја</translation>
+<translation id="4248100235867064564">трака са менијима</translation>
+<translation id="4360991593054037559">Унесите важећу вредност. Две најближе важеће вредности су <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Питања и одговори</translation>
+<translation id="4413860115965805769">дугме менија</translation>
+<translation id="4444765639179266822">Изгледа да пише: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">референца речника термина</translation>
+<translation id="4522570452068850558">Детаљи</translation>
+<translation id="4542388879936266156">преостало време: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">образац</translation>
+<translation id="4661075872484491155">стабло</translation>
+<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4668956016107839909">додатак</translation>
+<translation id="4718048029184481307">Репродукује се у режиму слике у слици</translation>
+<translation id="4742539557769756338">корицe</translation>
+<translation id="4748357248530471599">укључи/искључи цео екран без области изрезаног приказа</translation>
+<translation id="4757246831282535685">табла са картицама</translation>
+<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Унесите број.</translation>
+<translation id="4912536737030637138">библиографска ставка</translation>
+<translation id="4975562563186953947">Изабрано: <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Укључи звук</translation>
+<translation id="49969490063480558">Унесите неки део после „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
+<translation id="5034860022980953847">индикатор напретка</translation>
+<translation id="5090250355906949916">клизач за трајање видео снимка</translation>
+<translation id="5093189678851173835">натпис</translation>
+<translation id="5117590920725113268">Прикажи следећи месец</translation>
+<translation id="512758898067543763">заглавље реда</translation>
+<translation id="5143125788380636750">епилог</translation>
+<translation id="5164977714490026579">Вредност сме да буде најмање <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Унесите неки део пре „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
+<translation id="5334352251556557839">Пуштање медија није успело.</translation>
+<translation id="5406322316791861025">цифра</translation>
+<translation id="5453733299334684579">ставка стабла</translation>
+<translation id="5466621249238537318">Изаберите једну или више датотека.</translation>
+<translation id="5468998798572797635">изађите из режима целог екрана</translation>
+<translation id="5516424706154626233">бирач датума</translation>
+<translation id="5537725057119320332">Пребацуј</translation>
+<translation id="5546461542133609677">укључите звук</translation>
+<translation id="5608153257855394627">истакнуто</translation>
+<translation id="561939826962581046">време</translation>
+<translation id="5630795885300617244">Двапут додирните лево или десно да бисте прескочили 10 сек</translation>
+<translation id="5631759159893697722">сажетак</translation>
+<translation id="5643186887447432888">дугме</translation>
+<translation id="5677946354068040947">још опција</translation>
+<translation id="576709008726043716">увод</translation>
+<translation id="57838592816432529">Искључи звук</translation>
+<translation id="5860033963881614850">Искључено</translation>
+<translation id="588258955323874662">Цеo екран</translation>
+<translation id="5888666972993069672">Тренутно се пребацује на <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">оквир за претрагу</translation>
+<translation id="5939518447894949180">Ресетуј</translation>
+<translation id="5966707198760109579">Недеља</translation>
+<translation id="5987525920412732405">дугме за промену вредности</translation>
+<translation id="6011459053400940133">клизач за јачину звука</translation>
+<translation id="6015796118275082299">Година</translation>
+<translation id="6023896073578205740">оквир са листом</translation>
+<translation id="6150588977291308318">библиографија</translation>
+<translation id="6164829606128959761">мерач</translation>
+<translation id="6166809985690652833">поговор</translation>
+<translation id="6209276755895393898">Изгледа да је ово: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">речник термина</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Изађи из режима слике у слици</translation>
+<translation id="6398862346408813489">Прикажи таблу за избор месеца</translation>
+<translation id="6404546809543547843">клизач за трајање аудио-садржаја</translation>
+<translation id="6443871981718447451">прикажите мени опционалног титла</translation>
+<translation id="6453774872122745852">признања</translation>
+<translation id="6475115390776617481">присуство уживо</translation>
+<translation id="648732519525291180">бирач времена</translation>
+<translation id="6550675742724504774">Опције</translation>
+<translation id="6572309429103589720">Нетачна граматика</translation>
+<translation id="658823671542763450">пређите на режим целог екрана</translation>
+<translation id="663493177488814956">фид</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Обриши</translation>
+<translation id="668171684555832681">Друго...</translation>
+<translation id="6692633176391053278">контрола за промене у корацима</translation>
+<translation id="6709570249143506788">Лош квалитет снимка</translation>
+<translation id="6755330956360078551">објашњење</translation>
+<translation id="6790428901817661496">Пусти</translation>
+<translation id="6820355525329141109">Учитавање додатне компоненте није успело.</translation>
+<translation id="6820615603175220800">референца библиографије</translation>
+<translation id="6843725295806269523">искључи звук</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">знак издавача</translation>
+<translation id="6934078000481955284">издвојени цитат</translation>
+<translation id="693476918119313863">заглавље</translation>
+<translation id="6941933287844615239">преузми медије</translation>
+<translation id="6981594929165378967">уметање</translation>
+<translation id="6989848892321993519">Продужите овај текст на бар <ph name="MIN_CHARACTERS" /> знак(ов)а (тренутно користите 1 знак).</translation>
+<translation id="7034405885550056553">предлог</translation>
+<translation id="709897737746224366">Изаберите захтевани формат.</translation>
+<translation id="7118469954320184356">Опис није доступан.</translation>
+<translation id="7139483182332611405">предговор</translation>
+<translation id="7214187073215825913">информације о садржају</translation>
+<translation id="7263440858009898357">Изаберите ставку са листе.</translation>
+<translation id="727747134524199931">заглавље колоне</translation>
+<translation id="7320576522385648310">баферовање</translation>
+<translation id="7353453495576941748">заслуга</translation>
+<translation id="7364796246159120393">Одабери датотеку</translation>
+<translation id="739024184232394898">Друго...</translation>
+<translation id="7405738980073107433">завршне напомене</translation>
+<translation id="7410239719251593705">Изгледа да има садржај за одрасле. Опис није доступан.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Преузми</translation>
+<translation id="7529102961911894712">повратни линк</translation>
+<translation id="7533959249147584474">Неозначена слика</translation>
+<translation id="7647456547678091388">савет</translation>
+<translation id="7661956066982048809">графички документ</translation>
+<translation id="7673697353781729403">Сати</translation>
+<translation id="7681220483256441252">индекс</translation>
+<translation id="7740050170769002709">HTML садржај</translation>
+<translation id="7745230546936012372">Да бисте добили описе слика који недостају, отворите контекстуални мени.</translation>
+<translation id="7750228210027921155">Слика у слици</translation>
+<translation id="775297008183122718">Неважећи унос</translation>
+<translation id="7789962463072032349">паузирај</translation>
+<translation id="7802800022689234070">троугао за откривање</translation>
+<translation id="7888071071722539607">Уврстите „<ph name="ATSIGN" />“ у имејл адресу. У адреси е-поште „<ph name="INVALIDADDRESS" />“ недостаје „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">разделник</translation>
+<translation id="795667975304826397">Није одабрано</translation>
+<translation id="8053789581856978548">поље за текст претраге</translation>
+<translation id="8057695513531652401">обавештење</translation>
+<translation id="8105797009065549151">референца напомене</translation>
+<translation id="811583516810654505">Преузима се опис...</translation>
+<translation id="8117451130807776954">Ова недеља</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="8208673686607688524">бирач локалног датума и времена</translation>
+<translation id="8261464734335370856">Нетачан правопис</translation>
+<translation id="8284326494547611709">Титл</translation>
+<translation id="8346634859695247203">одељак</translation>
+<translation id="835897206747267392">Неважећа вредност.</translation>
+<translation id="8403857369060869934">протекло време: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">део</translation>
+<translation id="8433900881053900389">трака с алаткама</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> датотеке(а)</translation>
+<translation id="8451268428117625855">Изаберите датотеку.</translation>
+<translation id="8461852803063341183">дугме за избор</translation>
+<translation id="8474886197722836894">посвета</translation>
+<translation id="8531739829932800271">исправке и допуне</translation>
+<translation id="8534579021159131403">Минути</translation>
+<translation id="8541249477527128034">контрола за медије</translation>
+<translation id="8550857728288566671">графички симбол</translation>
+<translation id="8583702881314752957">листа дефиниција</translation>
+<translation id="8597182159515967513">наслов</translation>
+<translation id="860475260694818407">садржај</translation>
+<translation id="8613126697340063924">контролишите репродукцију на удаљеном уређају</translation>
+<translation id="862370744433916922">титл</translation>
+<translation id="8711688047404765493">излаз</translation>
+<translation id="8750798805984357768">Изаберите неку од ових опција.</translation>
+<translation id="8808573423886751634">поглавље</translation>
+<translation id="8822203815165896261">информације о ауторству</translation>
+<translation id="8845239796550121995">Тренутно се пребацује на ТВ</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Грешка при пуштању видео снимка</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Месец</translation>
+<translation id="901493112792887934">актуелно време у секундама</translation>
+<translation id="901834265349196618">имејл</translation>
+<translation id="9048119486235211610">навигација</translation>
+<translation id="9062295712474918030">документ</translation>
+<translation id="9093215626363556771">изађи из режима слике у слици</translation>
+<translation id="9108370397979208512">математички</translation>
+<translation id="9132465097189459683">Друго...</translation>
+<translation id="9138385573473225930">обавештење</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, од <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Слика у слици</translation>
+<translation id="9168329111483466115">фуснота</translation>
+<translation id="954003015749068518">уђи у режим слике у слици</translation>
+<translation id="966787709310836684">мени</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..69feea51fd0
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sv.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sv">
+<translation id="1018939186200882850">menyalternativ</translation>
+<translation id="10623998915015855">växlingsknapp</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="1171774979989969504">Ange en e-postadress.</translation>
+<translation id="1178581264944972037">Paus</translation>
+<translation id="1188858454923323853">kompletterande</translation>
+<translation id="1206619573307042055">markör</translation>
+<translation id="1206693055195146388">skjutreglage</translation>
+<translation id="1211441953136645838">slutnot</translation>
+<translation id="1281252709823657822">dialogruta</translation>
+<translation id="1335095011850992622">medverkande</translation>
+<translation id="1342835525016946179">artikel</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">område</translation>
+<translation id="1591562245178063882">Den här månaden</translation>
+<translation id="1637811476055996098">Välj filer</translation>
+<translation id="1650423536718072820">utvalt citat</translation>
+<translation id="1727886345390570319">dölj textningsmenyn</translation>
+<translation id="1729654308190250600">Ange en e-postadress som inte är tom.</translation>
+<translation id="1758486001363313524">Annat ...</translation>
+<translation id="1806710327868736751">varningsdialogruta</translation>
+<translation id="1821985195704844674">träddiagram</translation>
+<translation id="1822429046913737220">FM/EM</translation>
+<translation id="1832974991323546415">spela på en fjärrenhet</translation>
+<translation id="190587075670221089">borttagning</translation>
+<translation id="1907737156431278478">exempel</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="1938124657309484470">Värdet måste vara <ph name="MAXIMUM_DATE_OR_TIME" /> eller tidigare.</translation>
+<translation id="1946271899482435442">Visa datumväljaren</translation>
+<translation id="1993104285338243655">Bytte till spegling</translation>
+<translation id="2060505056492490888"><ph name="DOT" /> används på fel plats i <ph name="INVALIDDOMAIN" />.</translation>
+<translation id="2148716181193084225">Idag</translation>
+<translation id="2158401438286456825">sidlista</translation>
+<translation id="2226276347425096477">Förkorta texten till <ph name="MAX_CHARACTERS" /> tecken eller mindre (nu är texten <ph name="CURRENT_LENGTH" /> tecken).</translation>
+<translation id="2246498165605549352">Lokal fil</translation>
+<translation id="2247351761944213033">Vecka <ph name="WEEKNUMBER" /> <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Spår <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">kryssruta</translation>
+<translation id="2311842470354187719">sidbrytning</translation>
+<translation id="2335594187091864976">datum- och tidsväljare</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>
+<translation id="2508569020611168319">fliklista</translation>
+<translation id="2561842179657104141">visa fler mediereglage</translation>
+<translation id="2572483411312390101">spela upp</translation>
+<translation id="2613802280814924224">Ange ett giltigt värde. Det närmast giltiga värdet är <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Skicka</translation>
+<translation id="2657045182931379222">grafiskt objekt</translation>
+<translation id="2674318244760992338">sidfot</translation>
+<translation id="2709516037105925701">Autofyll</translation>
+<translation id="2723001399770238859">ljud</translation>
+<translation id="2725963129578236554">kommentarer</translation>
+<translation id="2746543609216772311">Värdet måste vara <ph name="MINIMUM_DATE_OR_TIME" /> eller senare.</translation>
+<translation id="2759744352195237655">popup-knapp</translation>
+<translation id="2761667185364618470">Markera den här kryssrutan om du vill fortsätta.</translation>
+<translation id="2844350028562914727">detaljer</translation>
+<translation id="2896972712917208084">alternativknappsgrupp</translation>
+<translation id="2908441821576996758">Ange en kommaavgränsad lista med e-postadresser.</translation>
+<translation id="2940813599313844715">objekt</translation>
+<translation id="3040011195152428237">länk</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Ange ett giltigt värde. Fältet är ofullständigt eller innehåller ett ogiltigt datum.</translation>
+<translation id="3078740164268491126">tabell</translation>
+<translation id="3086746722712840547">anm</translation>
+<translation id="310520048233152454">Ange en webbadress.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">kombinationsruta</translation>
+<translation id="3450233048674729344">Värdet måste vara mindre än eller lika med <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">rubrik <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">veckoväljare</translation>
+<translation id="3685101356851116974">Bild utan etikett</translation>
+<translation id="3706100364254443312">växel</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Avsluta bild-i-bild-läge</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">term</translation>
+<translation id="3822383571486410024">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett <ph name="CURRENT_LENGTH" /> tecken).</translation>
+<translation id="383465348367842624">En del följt av <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3846214748874656680">Avsluta helskärmsläge</translation>
+<translation id="3889183436948184105">version</translation>
+<translation id="3920932319529768807">resultat</translation>
+<translation id="3924558731517983934">program</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">rullningslist</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">bild</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">förord</translation>
+<translation id="4201051445878709314">Visa föregående månad</translation>
+<translation id="421884353938374759">färgval</translation>
+<translation id="4248100235867064564">menyfält</translation>
+<translation id="4360991593054037559">Ange ett giltigt värde. De två närmaste giltiga värdena är <ph name="VALID_VALUE_LOW" /> och <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Frågor och svar</translation>
+<translation id="4413860115965805769">menyknapp</translation>
+<translation id="4444765639179266822">Säger troligen: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">hänvisning till ordlista</translation>
+<translation id="4522570452068850558">Info</translation>
+<translation id="4542388879936266156">tid som återstår: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">formulär</translation>
+<translation id="4661075872484491155">träd</translation>
+<translation id="4664250907885839816">En del efter <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4668956016107839909">bilaga</translation>
+<translation id="4718048029184481307">Spelas upp i bild-i-bild-läge</translation>
+<translation id="4742539557769756338">omslag</translation>
+<translation id="4748357248530471599">aktivera och inaktivera skärmutskärning i helskärm</translation>
+<translation id="4757246831282535685">flikpanel</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">sök</translation>
+<translation id="4812940957355064477">Ange ett nummer.</translation>
+<translation id="4912536737030637138">bibliografipost</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valda</translation>
+<translation id="4992066212339426712">Slå på ljudet</translation>
+<translation id="49969490063480558">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
+<translation id="5034860022980953847">förloppsindikator</translation>
+<translation id="5090250355906949916">tidsreglage för video</translation>
+<translation id="5093189678851173835">epigraf</translation>
+<translation id="5117590920725113268">Visa nästa månad</translation>
+<translation id="512758898067543763">radrubrik</translation>
+<translation id="5143125788380636750">epilog</translation>
+<translation id="5164977714490026579">Värdet måste vara större än eller lika med <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
+<translation id="5334352251556557839">Det går inte att spela upp media.</translation>
+<translation id="5406322316791861025">figur</translation>
+<translation id="5453733299334684579">trädobjekt</translation>
+<translation id="5466621249238537318">Välj en eller flera filer.</translation>
+<translation id="5468998798572797635">avsluta helskärmsläge</translation>
+<translation id="5516424706154626233">datumväljare</translation>
+<translation id="5537725057119320332">Casta</translation>
+<translation id="5546461542133609677">slå på ljudet</translation>
+<translation id="5608153257855394627">markerat</translation>
+<translation id="561939826962581046">tid</translation>
+<translation id="5630795885300617244">Hoppa över 10 s genom att trycka två gånger till vänster/höger</translation>
+<translation id="5631759159893697722">abstract</translation>
+<translation id="5643186887447432888">knapp</translation>
+<translation id="5677946354068040947">fler alternativ</translation>
+<translation id="576709008726043716">inledning</translation>
+<translation id="57838592816432529">Stäng av ljudet</translation>
+<translation id="5860033963881614850">Av</translation>
+<translation id="588258955323874662">Helskärm</translation>
+<translation id="5888666972993069672">Castar till <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">sökruta</translation>
+<translation id="5939518447894949180">Återställ</translation>
+<translation id="5966707198760109579">Vecka</translation>
+<translation id="5987525920412732405">snurrknapp</translation>
+<translation id="6011459053400940133">volymreglage</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listruta</translation>
+<translation id="6150588977291308318">bibliografi</translation>
+<translation id="6164829606128959761">mätare</translation>
+<translation id="6166809985690652833">efterord</translation>
+<translation id="6209276755895393898">Det verkar vara: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">ordlista</translation>
+<translation id="6281763101136022427">webbadress</translation>
+<translation id="6310801910862476708">Avsluta bild-i-bild-läge</translation>
+<translation id="6398862346408813489">Visa panelen för val av månad</translation>
+<translation id="6404546809543547843">tidsreglage för ljud</translation>
+<translation id="6443871981718447451">visa textningsmenyn</translation>
+<translation id="6453774872122745852">författarens tack</translation>
+<translation id="6475115390776617481">närvarande just nu</translation>
+<translation id="648732519525291180">tidsväljare</translation>
+<translation id="6550675742724504774">Alternativ</translation>
+<translation id="6572309429103589720">Grammatikfel</translation>
+<translation id="658823671542763450">visa i helskärm</translation>
+<translation id="663493177488814956">flöde</translation>
+<translation id="6637586476836377253">logg</translation>
+<translation id="6643016212128521049">Rensa</translation>
+<translation id="668171684555832681">Annan...</translation>
+<translation id="6692633176391053278">knappreglage</translation>
+<translation id="6709570249143506788">Låg uppspelningskvalitet</translation>
+<translation id="6755330956360078551">beskrivning</translation>
+<translation id="6790428901817661496">Spela</translation>
+<translation id="6820355525329141109">Det gick inte att läsa in plugin-programmet.</translation>
+<translation id="6820615603175220800">bibliografisk referens</translation>
+<translation id="6843725295806269523">ljud av</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="689129560213475294">kolofon</translation>
+<translation id="6934078000481955284">citatblock</translation>
+<translation id="693476918119313863">rubrik</translation>
+<translation id="6941933287844615239">ladda ned media</translation>
+<translation id="6981594929165378967">infogning</translation>
+<translation id="6989848892321993519">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett 1 tecken).</translation>
+<translation id="7034405885550056553">förslag</translation>
+<translation id="709897737746224366">Matcha det format som anges.</translation>
+<translation id="7118469954320184356">Det finns ingen tillgänglig beskrivning.</translation>
+<translation id="7139483182332611405">företal</translation>
+<translation id="7214187073215825913">innehållsinformation</translation>
+<translation id="7263440858009898357">Välj ett alternativ i listan.</translation>
+<translation id="727747134524199931">kolumnrubrik</translation>
+<translation id="7320576522385648310">buffrar</translation>
+<translation id="7353453495576941748">erkännande</translation>
+<translation id="7364796246159120393">Välj fil</translation>
+<translation id="739024184232394898">Annat ...</translation>
+<translation id="7405738980073107433">slutnoter</translation>
+<translation id="7410239719251593705">Verkar innehålla barnförbjudet innehåll. Det finns ingen tillgänglig beskrivning.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tabb</translation>
+<translation id="7514365320538308">Ladda ned</translation>
+<translation id="7529102961911894712">bakåtlänk</translation>
+<translation id="7533959249147584474">Bild utan etikett</translation>
+<translation id="7647456547678091388">tips</translation>
+<translation id="7661956066982048809">grafiskt dokument</translation>
+<translation id="7673697353781729403">Timmar</translation>
+<translation id="7681220483256441252">index</translation>
+<translation id="7740050170769002709">HTML-innehåll</translation>
+<translation id="7745230546936012372">Öppna snabbmenyn om du vill hämta en bildbeskrivning när en sådan saknas.</translation>
+<translation id="7750228210027921155">Bild-i-bild</translation>
+<translation id="775297008183122718">Ogiltig inmatning</translation>
+<translation id="7789962463072032349">paus</translation>
+<translation id="7802800022689234070">expanderingstriangel</translation>
+<translation id="7888071071722539607">Inkludera ett <ph name="ATSIGN" /> i e-postadressen. <ph name="INVALIDADDRESS" /> saknar ett <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">delare</translation>
+<translation id="795667975304826397">Ingen fil har valts</translation>
+<translation id="8053789581856978548">fält för söktext</translation>
+<translation id="8057695513531652401">anmärkning</translation>
+<translation id="8105797009065549151">referensnot</translation>
+<translation id="811583516810654505">Beskrivningen hämtas …</translation>
+<translation id="8117451130807776954">Den här veckan</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="8208673686607688524">datum- och tidsväljare för lokal tid</translation>
+<translation id="8261464734335370856">Stavfel</translation>
+<translation id="8284326494547611709">Textning</translation>
+<translation id="8346634859695247203">avsnitt</translation>
+<translation id="835897206747267392">Ogiltigt värde.</translation>
+<translation id="8403857369060869934">tid som gått: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">del</translation>
+<translation id="8433900881053900389">verktygsfält</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
+<translation id="8451268428117625855">Välj en fil.</translation>
+<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8474886197722836894">tillägnan</translation>
+<translation id="8531739829932800271">errata</translation>
+<translation id="8534579021159131403">Minuter</translation>
+<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="8550857728288566671">grafisk symbol</translation>
+<translation id="8583702881314752957">definitionslista</translation>
+<translation id="8597182159515967513">rubrik</translation>
+<translation id="860475260694818407">innehållsförteckning</translation>
+<translation id="8613126697340063924">styra fjärruppspelning</translation>
+<translation id="862370744433916922">undertext</translation>
+<translation id="8711688047404765493">utdata</translation>
+<translation id="8750798805984357768">Välj ett av följande alternativ.</translation>
+<translation id="8808573423886751634">kapitel</translation>
+<translation id="8822203815165896261">författaruppgift</translation>
+<translation id="8845239796550121995">Castar nu till TV:n</translation>
+<translation id="8851136666856101339">huvud</translation>
+<translation id="8875657656876809964">Videouppspelningsfel</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
+<translation id="8987927404178983737">Månad</translation>
+<translation id="901493112792887934">aktuell tid i sekunder</translation>
+<translation id="901834265349196618">e-post</translation>
+<translation id="9048119486235211610">navigering</translation>
+<translation id="9062295712474918030">dokument</translation>
+<translation id="9093215626363556771">avsluta bild-i-bild-läge</translation>
+<translation id="9108370397979208512">matte</translation>
+<translation id="9132465097189459683">Annat ...</translation>
+<translation id="9138385573473225930">varning</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> som börjar den <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Bild-i-bild</translation>
+<translation id="9168329111483466115">fotnot</translation>
+<translation id="954003015749068518">öppna bild-i-bild-läge</translation>
+<translation id="966787709310836684">meny</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..923a4cda2a7
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_sw.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sw">
+<translation id="1018939186200882850">kipengee cha menyu</translation>
+<translation id="10623998915015855">kitufe cha kugeuza</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="1171774979989969504">Tafadhali weka anwani ya barua pepe.</translation>
+<translation id="1178581264944972037">Sitisha</translation>
+<translation id="1188858454923323853">nyongeza</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">kitelezi</translation>
+<translation id="1211441953136645838">maelezo ya mwisho wa kitabu</translation>
+<translation id="1281252709823657822">kidirisha</translation>
+<translation id="1335095011850992622">walioshiriki</translation>
+<translation id="1342835525016946179">makala</translation>
+<translation id="1359897965706325498">bango</translation>
+<translation id="1589122976691792535">eneo</translation>
+<translation id="1591562245178063882">Mwezi huu</translation>
+<translation id="1637811476055996098">Chagua Faili</translation>
+<translation id="1650423536718072820">nukuu muhimu</translation>
+<translation id="1727886345390570319">kuficha menyu ya manukuu</translation>
+<translation id="1729654308190250600">Tafadhali jaza sehemu ya anwani ya barua pepe.</translation>
+<translation id="1758486001363313524">Nyingine...</translation>
+<translation id="1806710327868736751">kidirisha cha arifa</translation>
+<translation id="1821985195704844674">gridi ya mti</translation>
+<translation id="1822429046913737220">AM / PM</translation>
+<translation id="1832974991323546415">cheza kwenye kifaa cha mbali</translation>
+<translation id="190587075670221089">ufutaji</translation>
+<translation id="1907737156431278478">mfano</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">hali</translation>
+<translation id="1938124657309484470">Thamani lazima iwe <ph name="MAXIMUM_DATE_OR_TIME" /> au mapema.</translation>
+<translation id="1946271899482435442">Onyesha kiteua tarehe</translation>
+<translation id="1993104285338243655">Inatumia hali ya kuakisi</translation>
+<translation id="2060505056492490888">' <ph name="DOT" /> 'imetumika kwenye nafasi isiyostahili katika '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Leo</translation>
+<translation id="2158401438286456825">orodha ya kurasa</translation>
+<translation id="2226276347425096477">Tafadhali fupisha maandishi haya hadi vibambo <ph name="MAX_CHARACTERS" /> au chini (kwa sasa unatumia vibambo <ph name="CURRENT_LENGTH" /> ).</translation>
+<translation id="2246498165605549352">Faili ya Ndani</translation>
+<translation id="2247351761944213033">Wiki <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Wimbo wa <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">kisanduku cha kuteua</translation>
+<translation id="2311842470354187719">nafasi ya kugawa kurasa</translation>
+<translation id="2335594187091864976">mchumaji tarehe na wakati</translation>
+<translation id="245932805758469625">idadi ya sekunde za video zilizosalia</translation>
+<translation id="248395913932153421">Siku</translation>
+<translation id="2507943997699731163">Tafadhali jaza sehemu hii.</translation>
+<translation id="2508569020611168319">orodha ya vichupo</translation>
+<translation id="2561842179657104141">onyesha vidhibiti zaidi vya maudhui</translation>
+<translation id="2572483411312390101">cheza</translation>
+<translation id="2613802280814924224">Tafadhali ingiza thamani halali.Thamani halali ya karibu ni <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Wasilisha</translation>
+<translation id="2657045182931379222">kipengee cha michoro</translation>
+<translation id="2674318244760992338">kijachini</translation>
+<translation id="2709516037105925701">Kujaza Kiotomatiki</translation>
+<translation id="2723001399770238859">sauti</translation>
+<translation id="2725963129578236554">maoni</translation>
+<translation id="2746543609216772311">Thamani lazima iwe <ph name="MINIMUM_DATE_OR_TIME" /> au baadaye.</translation>
+<translation id="2759744352195237655">kitufe cha dirisha ibukizi</translation>
+<translation id="2761667185364618470">Tafadhali angalia kikasha hiki iwapo unataka kuendelea.</translation>
+<translation id="2844350028562914727">maelezo</translation>
+<translation id="2896972712917208084">kikundi cha vitufe</translation>
+<translation id="2908441821576996758">Tafadhali weka orodha ya anwani za barua pepe zilizotenganishwa kwa vikomo.</translation>
+<translation id="2940813599313844715">kitu</translation>
+<translation id="3040011195152428237">kiungo</translation>
+<translation id="3049748772180311791">MB <ph name="QUANTITY" /></translation>
+<translation id="3075154866155599887">Tafadhali ingiza thamani halali. Uga umekamilika au una tarehe batili.</translation>
+<translation id="3078740164268491126">jedwali</translation>
+<translation id="3086746722712840547">dokezo</translation>
+<translation id="310520048233152454">Tafadhali ingiza URL.</translation>
+<translation id="3175736971608411871">kipima muda</translation>
+<translation id="3199563858620722075">kisanduku mseto</translation>
+<translation id="3450233048674729344">Lazima thamani iwe chache kuliko au sawa na <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">ufafanuzi</translation>
+<translation id="3557673793733683882">kichwa cha <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">kiteua wiki</translation>
+<translation id="3685101356851116974">Picha isiyo na lebo</translation>
+<translation id="3706100364254443312">badilisha</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Funga hali ya picha ndani ya picha</translation>
+<translation id="3757388668994797779">GB <ph name="QUANTITY" /></translation>
+<translation id="3808586225841795776">neno</translation>
+<translation id="3822383571486410024">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi <ph name="CURRENT_LENGTH" />).</translation>
+<translation id="383465348367842624">Sehemu inayofuatwa na '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">Ondoka kwenye skrini nzima</translation>
+<translation id="3889183436948184105">marekebisho</translation>
+<translation id="3920932319529768807">hitimisho</translation>
+<translation id="3924558731517983934">programu</translation>
+<translation id="3944740393230681990">shairi la utangulizi</translation>
+<translation id="3960700977367013758">sehemu ya kusogeza</translation>
+<translation id="4103419683916926126">nukta</translation>
+<translation id="4151657705144244502">mchoro</translation>
+<translation id="4160057747563657758">simu</translation>
+<translation id="4193965531860883258">dibaji</translation>
+<translation id="4201051445878709314">Onyesha mwezi uliotangulia</translation>
+<translation id="421884353938374759">kiteua rangi</translation>
+<translation id="4248100235867064564">upau wa menyu</translation>
+<translation id="4360991593054037559">Tafadhali ingiza thamani halali. Thamani mbili halali za karibu ni <ph name="VALID_VALUE_LOW" /> na <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Maswali na Majibu</translation>
+<translation id="4413860115965805769">kitufe cha menyu</translation>
+<translation id="4444765639179266822">Inaonekana kusema: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">marejeleo ya farahasa</translation>
+<translation id="4522570452068850558">Maelezo</translation>
+<translation id="4542388879936266156">muda uliosalia: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">fomu</translation>
+<translation id="4661075872484491155">mti</translation>
+<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">kiambatisho</translation>
+<translation id="4718048029184481307">Inacheza katika hali ya picha ndani ya picha</translation>
+<translation id="4742539557769756338">jalada</translation>
+<translation id="4748357248530471599">tumia mkato kwenye skrini nzima</translation>
+<translation id="4757246831282535685">kisanduku cha kichupo</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">tafuta</translation>
+<translation id="4812940957355064477">Tafadhali ingiza nambari.</translation>
+<translation id="4912536737030637138">maelezo ya bibliografia</translation>
+<translation id="4975562563186953947">Vipengee <ph name="SELECTED_COUNT" /> vimechaguliwa</translation>
+<translation id="4992066212339426712">Rejesha sauti</translation>
+<translation id="49969490063480558">Tafadhali ingiza sehemu inayofuatia '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
+<translation id="5034860022980953847">kiashiria cha maendeleo</translation>
+<translation id="5090250355906949916">kitelezi cha muda wa video</translation>
+<translation id="5093189678851173835">epigrafu</translation>
+<translation id="5117590920725113268">Onyesha mwezi unaofuata</translation>
+<translation id="512758898067543763">kichwa cha safu mlalo</translation>
+<translation id="5143125788380636750">hitimisho</translation>
+<translation id="5164977714490026579">Lazima thamani iwe kubwa kuliko au sawa na <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650">PB <ph name="QUANTITY" /></translation>
+<translation id="5307600278924710095">Tafadhali ingiza sehemu ikifuatiwa na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
+<translation id="5334352251556557839">Imeshindwa kucheza maudhui.</translation>
+<translation id="5406322316791861025">umbo</translation>
+<translation id="5453733299334684579">kipengee cha mti</translation>
+<translation id="5466621249238537318">Tafadhali chagua faili moja au zaidi.</translation>
+<translation id="5468998798572797635">Ondoka kwenye Skrini nzima</translation>
+<translation id="5516424706154626233">kichagua tarehe</translation>
+<translation id="5537725057119320332">Tuma</translation>
+<translation id="5546461542133609677">washa sauti</translation>
+<translation id="5608153257855394627">yaliyoangaziwa</translation>
+<translation id="561939826962581046">wakati</translation>
+<translation id="5630795885300617244">Gusa mara mbili kushoto au kulia ili uruke kwa sekunde 10</translation>
+<translation id="5631759159893697722">ikisiri</translation>
+<translation id="5643186887447432888">kitufe</translation>
+<translation id="5677946354068040947">chaguo zaidi</translation>
+<translation id="576709008726043716">utangulizi</translation>
+<translation id="57838592816432529">Zima sauti</translation>
+<translation id="5860033963881614850">Kimezimwa</translation>
+<translation id="588258955323874662">Skrini nzima</translation>
+<translation id="5888666972993069672">Sasa inatuma kwenye <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">kisanduku cha kutafutia</translation>
+<translation id="5939518447894949180">Weka upya</translation>
+<translation id="5966707198760109579">Juma</translation>
+<translation id="5987525920412732405">kitufe cha kubadilishia</translation>
+<translation id="6011459053400940133">kitelezi cha sauti</translation>
+<translation id="6015796118275082299">Mwaka</translation>
+<translation id="6023896073578205740">kikasha cha orodha</translation>
+<translation id="6150588977291308318">bibliografia</translation>
+<translation id="6164829606128959761">mita</translation>
+<translation id="6166809985690652833">maelezo kuhusu kitabu</translation>
+<translation id="6209276755895393898">Inaonekana kuwa: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">faharasa</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Funga hali ya Picha ndani ya Picha</translation>
+<translation id="6398862346408813489">Onyesha kisanduku cha uchaguzi wa mwezi</translation>
+<translation id="6404546809543547843">kitelezi cha muda cha sauti</translation>
+<translation id="6443871981718447451">kuonyesha menyu ya manukuu</translation>
+<translation id="6453774872122745852">shukrani</translation>
+<translation id="6475115390776617481">yuko mtandaoni hivi sasa</translation>
+<translation id="648732519525291180">Kiteua wakati</translation>
+<translation id="6550675742724504774">Chaguo</translation>
+<translation id="6572309429103589720">Sarufi si sahihi</translation>
+<translation id="658823671542763450">ingia skrini kamili</translation>
+<translation id="663493177488814956">mipasho</translation>
+<translation id="6637586476836377253">kumbukumbu</translation>
+<translation id="6643016212128521049">Futa</translation>
+<translation id="668171684555832681">Mengine...</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="6709570249143506788">Ubora wa chini wa kucheza video</translation>
+<translation id="6755330956360078551">kidirisha cha vidokezo</translation>
+<translation id="6790428901817661496">Cheza</translation>
+<translation id="6820355525329141109">Haikuweza kupakia programu jalizi.</translation>
+<translation id="6820615603175220800">marejeleo ya bibliografia</translation>
+<translation id="6843725295806269523">nyamazisha</translation>
+<translation id="6885760532393684712">saraka</translation>
+<translation id="689129560213475294">kolofoni</translation>
+<translation id="6934078000481955284">nukuu la msingi</translation>
+<translation id="693476918119313863">kichwa</translation>
+<translation id="6941933287844615239">pakua maudhui</translation>
+<translation id="6981594929165378967">uwekaji</translation>
+<translation id="6989848892321993519">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi 1).</translation>
+<translation id="7034405885550056553">pendekezo</translation>
+<translation id="709897737746224366">Tafadhali linganisha umbizo lililoombwa.</translation>
+<translation id="7118469954320184356">Hakuna maelezo yanayopatikana.</translation>
+<translation id="7139483182332611405">dibaji</translation>
+<translation id="7214187073215825913">maelezo ya maudhui</translation>
+<translation id="7263440858009898357">Tafadhali chagua kipengee katika orodha.</translation>
+<translation id="727747134524199931">kijajuu cha safu wima</translation>
+<translation id="7320576522385648310">inaakibisha</translation>
+<translation id="7353453495576941748">aliyeshiriki</translation>
+<translation id="7364796246159120393">Chagua Faili</translation>
+<translation id="739024184232394898">Nyingine...</translation>
+<translation id="7405738980073107433">maelezo ya mwisho wa kitabu</translation>
+<translation id="7410239719251593705">Inaonekana kuwa na maudhui ya watu wazima. Hakuna maelezo yanayopatikana.</translation>
+<translation id="7460907917090416791">TB <ph name="QUANTITY" /></translation>
+<translation id="7491962110804786152">kichupo</translation>
+<translation id="7514365320538308">Pakua</translation>
+<translation id="7529102961911894712">kiungo rejeshi</translation>
+<translation id="7533959249147584474">Mchoro usiokuwa na lebo</translation>
+<translation id="7647456547678091388">kidokezo</translation>
+<translation id="7661956066982048809">hati ya picha</translation>
+<translation id="7673697353781729403">Saa</translation>
+<translation id="7681220483256441252">faharasa</translation>
+<translation id="7740050170769002709">Maudhui ya HTML</translation>
+<translation id="7745230546936012372">Ili upate ufafanuzi wa picha unaokosekana, fungua menyu.</translation>
+<translation id="7750228210027921155">Picha ndani ya picha</translation>
+<translation id="775297008183122718">Ingizo batili</translation>
+<translation id="7789962463072032349">Sitisha</translation>
+<translation id="7802800022689234070">pembe tatu ya ufafanuzi</translation>
+<translation id="7888071071722539607">Tafadhali jumuisha '<ph name="ATSIGN" />' katika anwani ya barua pepe. '<ph name="INVALIDADDRESS" />' inakosa '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">kitenganishi</translation>
+<translation id="795667975304826397">Hakuna faili iliyochaguliwa</translation>
+<translation id="8053789581856978548">sehemu ya maandishi ya utafutaji</translation>
+<translation id="8057695513531652401">ilani</translation>
+<translation id="8105797009065549151">marejeleo ya dokezo</translation>
+<translation id="811583516810654505">Inaleta ufafanuzi...</translation>
+<translation id="8117451130807776954">Wiki hii</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">kiteuzi cha saa na tarehe ya mahali ulipo</translation>
+<translation id="8261464734335370856">Maendelezo si sahihi</translation>
+<translation id="8284326494547611709">Manukuu</translation>
+<translation id="8346634859695247203">sehemu</translation>
+<translation id="835897206747267392">Thamani batili.</translation>
+<translation id="8403857369060869934">muda uliopita: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">sehemu</translation>
+<translation id="8433900881053900389">upau wa vidhibiti</translation>
+<translation id="8444882422881193423">faili <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Tafadhali chagua faili.</translation>
+<translation id="8461852803063341183">kitufe cha mviringo</translation>
+<translation id="8474886197722836894">tabaruku</translation>
+<translation id="8531739829932800271">hitilafu katika uchapishaji</translation>
+<translation id="8534579021159131403">Dakika</translation>
+<translation id="8541249477527128034">udhibiti wa vyombo vya habari</translation>
+<translation id="8550857728288566671">ishara ya picha</translation>
+<translation id="8583702881314752957">orodha ya ufafanuzi</translation>
+<translation id="8597182159515967513">kichwa</translation>
+<translation id="860475260694818407">jedwali la yaliyomo</translation>
+<translation id="8613126697340063924">dhibiti kucheza kwa mbali</translation>
+<translation id="862370744433916922">kichwa kidogo</translation>
+<translation id="8711688047404765493">vifaa vya kutoa maudhui</translation>
+<translation id="8750798805984357768">Tafadhali chagua moja wapo ya chaguo hizi.</translation>
+<translation id="8808573423886751634">sura</translation>
+<translation id="8822203815165896261">maelezo ya usanidi</translation>
+<translation id="8845239796550121995">Sasa inatuma kwenye TV yako</translation>
+<translation id="8851136666856101339">kuu</translation>
+<translation id="8875657656876809964">Hitilafu ya kucheza video</translation>
+<translation id="8901569739625249689">KB <ph name="QUANTITY" /></translation>
+<translation id="8987927404178983737">Mwezi</translation>
+<translation id="901493112792887934">muda wa sasa kwa sekunde</translation>
+<translation id="901834265349196618">Barua pepe</translation>
+<translation id="9048119486235211610">kuvinjari</translation>
+<translation id="9062295712474918030">hati</translation>
+<translation id="9093215626363556771">funga hali ya picha ndani ya picha</translation>
+<translation id="9108370397979208512">hisabati</translation>
+<translation id="9132465097189459683">Nyingine...</translation>
+<translation id="9138385573473225930">arifa</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, itaanza tarehe <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Picha ndani ya Picha</translation>
+<translation id="9168329111483466115">tanbihi</translation>
+<translation id="954003015749068518">washa hali ya picha ndani ya picha</translation>
+<translation id="966787709310836684">menyu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..045bfc1c1a9
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_ta.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ta">
+<translation id="1018939186200882850">மெனு உருப்படி</translation>
+<translation id="10623998915015855">நிலைமாற்றுவதற்கான பொத்தான்</translation>
+<translation id="1088086359088493902">வினாடிகள்</translation>
+<translation id="1171774979989969504">ஒரு மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
+<translation id="1178581264944972037">இடைநிறுத்து</translation>
+<translation id="1188858454923323853">ஈடுசெய்யக்கூடியது</translation>
+<translation id="1206619573307042055">மார்கியூ</translation>
+<translation id="1206693055195146388">ஸ்லைடர்</translation>
+<translation id="1211441953136645838">முடிவுக்குறிப்பு</translation>
+<translation id="1281252709823657822">உரையாடல்</translation>
+<translation id="1335095011850992622">பங்களித்தவர்கள்</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">பேனர்</translation>
+<translation id="1589122976691792535">மண்டலம்</translation>
+<translation id="1591562245178063882">இந்த மாதம்</translation>
+<translation id="1637811476055996098">கோப்புகளைத் தேர்வுசெய்க</translation>
+<translation id="1650423536718072820">pullquote</translation>
+<translation id="1727886345390570319">விரிவான வசனங்கள் மெனுவை மறைக்கும்</translation>
+<translation id="1729654308190250600">காலி அல்லாத மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
+<translation id="1758486001363313524">மற்றவை…</translation>
+<translation id="1806710327868736751">விழிப்பூட்டல்_உரையாடல்</translation>
+<translation id="1821985195704844674">ட்ரீ கிரிட்</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">தொலைநிலைச் சாதனத்தில் இயக்கு</translation>
+<translation id="190587075670221089">நீக்கும்</translation>
+<translation id="1907737156431278478">உதாரணம்</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">நிலை</translation>
+<translation id="1938124657309484470">மதிப்பு <ph name="MAXIMUM_DATE_OR_TIME" /> அல்லது அதற்கு முன்பு இருக்க வேண்டும்.</translation>
+<translation id="1946271899482435442">தேதித் தேர்ந்தெடுப்பானைக் காட்டும்</translation>
+<translation id="1993104285338243655">பிரதிபலித்தலுக்கு மாற்றியது</translation>
+<translation id="2060505056492490888"><ph name="INVALIDDOMAIN" /> இல் தவறான இடத்தில் '<ph name="DOT" />' பயன்படுத்தபட்டுள்ளது.</translation>
+<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="2247351761944213033">வாரம் <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ட்ராக் <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">செக்பாக்ஸ்</translation>
+<translation id="2311842470354187719">பக்க முறிப்பு</translation>
+<translation id="2335594187091864976">தேதி மற்றும் நேரம் தேர்ந்தெடுப்பான்</translation>
+<translation id="245932805758469625">மீதமுள்ள வீடியோவின் வினாடிகள்</translation>
+<translation id="248395913932153421">நாள்</translation>
+<translation id="2507943997699731163">இந்தப் புலத்தை நிரப்புக.</translation>
+<translation id="2508569020611168319">தாவல் பட்டியல்</translation>
+<translation id="2561842179657104141">மேலும் மீடியா கட்டுப்பாடுகளைக் காட்டு</translation>
+<translation id="2572483411312390101">இயக்கு</translation>
+<translation id="2613802280814924224">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE" /> என்பது நெருக்கமாக உள்ள சரியான மதிப்பாகும்.</translation>
+<translation id="2653659639078652383">சமர்ப்பி</translation>
+<translation id="2657045182931379222">கிராஃபிக்ஸ் பொருள்</translation>
+<translation id="2674318244760992338">அடிக்குறிப்பு</translation>
+<translation id="2709516037105925701">தானாகநிரப்பு</translation>
+<translation id="2723001399770238859">ஆடியோ</translation>
+<translation id="2725963129578236554">கருத்துகள்</translation>
+<translation id="2746543609216772311">மதிப்பானது <ph name="MINIMUM_DATE_OR_TIME" /> அல்லது அதற்குப் பின்பு இருக்க வேண்டும்.</translation>
+<translation id="2759744352195237655">பாப் அப் பொத்தான்</translation>
+<translation id="2761667185364618470">தொடர விரும்பினால், இந்தப் பெட்டியைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="2844350028562914727">விவரங்கள்</translation>
+<translation id="2896972712917208084">ரேடியோ குழு</translation>
+<translation id="2908441821576996758">காற்புள்ளியால் பிரிக்கப்பட்ட மின்னஞ்சல் முகவரிகளின் பட்டியலை உள்ளிடுக.</translation>
+<translation id="2940813599313844715">பொருள்</translation>
+<translation id="3040011195152428237">இணைப்பு</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> மெ.பை</translation>
+<translation id="3075154866155599887">சரியான மதிப்பை உள்ளிடவும். இந்தப் புலம் முழுமையற்றதாக உள்ளது அல்லது தவறான தேதியைக் கொண்டுள்ளது.</translation>
+<translation id="3078740164268491126">அட்டவணை</translation>
+<translation id="3086746722712840547">குறிப்பு</translation>
+<translation id="310520048233152454">URL ஐ உள்ளிடுக.</translation>
+<translation id="3175736971608411871">டைமர்</translation>
+<translation id="3199563858620722075">சேர்க்கைப் பெட்டி</translation>
+<translation id="3450233048674729344">மதிப்பானது கண்டிப்பாக <ph name="MAXIMUM" /> ஐ விடக்குறைவாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
+<translation id="3486220673238053218">விளக்கம்</translation>
+<translation id="3557673793733683882">தலைப்பு <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">வாரத் தேர்வி</translation>
+<translation id="3685101356851116974">லேபிளிடப்படாத படம்</translation>
+<translation id="3706100364254443312">ஸ்விட்ச்</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">’பிக்ச்சர்-இன்-பிக்ச்சரில்' இருந்து வெளியேறு</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">சொல்</translation>
+<translation id="3822383571486410024">இந்த உரையை <ph name="MIN_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் அதிகமாக (தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்) நீட்டிக்கவும்.</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து வரும் பகுதியில் '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="3846214748874656680">முழுத்திரை வேண்டாம்</translation>
+<translation id="3889183436948184105">மீள்திருத்தம்</translation>
+<translation id="3920932319529768807">முடிவு</translation>
+<translation id="3924558731517983934">ஆப்ஸ்</translation>
+<translation id="3944740393230681990">முன்னுரை</translation>
+<translation id="3960700977367013758">உருட்டல் பட்டி</translation>
+<translation id="4103419683916926126">மில்லிவினாடிகள்</translation>
+<translation id="4151657705144244502">கிராஃபிக்</translation>
+<translation id="4160057747563657758">தொலைபேசி</translation>
+<translation id="4193965531860883258">அறிமுகம்</translation>
+<translation id="4201051445878709314">முந்தைய மாதத்தைக் காட்டு</translation>
+<translation id="421884353938374759">வண்ணத் தேர்வி</translation>
+<translation id="4248100235867064564">மெனுப் பட்டி</translation>
+<translation id="4360991593054037559">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE_LOW" /> மற்றும் <ph name="VALID_VALUE_HIGHER" /> ஆகியவை மிக நெருக்கமான சரியான இரண்டு மதிப்புகளாகும்.</translation>
+<translation id="4384583879834880242">கேள்வி-பதில்</translation>
+<translation id="4413860115965805769">மெனு பொத்தான்</translation>
+<translation id="4444765639179266822"><ph name="OCR_TEXT" /> என்று சொல்வதாகத் தோன்றுகிறது</translation>
+<translation id="4446524499724042288">அருஞ்சொல் திரட்டு மேற்கோள்</translation>
+<translation id="4522570452068850558">விவரங்கள்</translation>
+<translation id="4542388879936266156">மீதமுள்ள நேரம்: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">படிவம்</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="4668956016107839909">பிற்சேர்க்கை</translation>
+<translation id="4718048029184481307">’பிக்ச்சர்-இன்-பிக்ச்சர்' பயன்முறையில் பிளே ஆகிறது</translation>
+<translation id="4742539557769756338">அட்டை</translation>
+<translation id="4748357248530471599">டிஸ்ப்ளே கட்அவுட் முழுத்திரை நிலைமாற்ற பட்டன்</translation>
+<translation id="4757246831282535685">தாவல் பலகம்</translation>
+<translation id="4763480195061959176">வீடியோ</translation>
+<translation id="479989351350248267">தேடல்</translation>
+<translation id="4812940957355064477">எண்ணை உள்ளிடுக.</translation>
+<translation id="4912536737030637138">நூல்விவர அட்டவணை உள்ளீடு</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> தேர்ந்தெடுக்கப்பட்டன</translation>
+<translation id="4992066212339426712">ஒலி இயக்கு</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப்பெறாமல் உள்ளது.</translation>
+<translation id="5034860022980953847">செயல்நிலை காட்டி</translation>
+<translation id="5090250355906949916">வீடியோ நேர ஸ்க்ரப்பர்</translation>
+<translation id="5093189678851173835">கல்வெட்டு</translation>
+<translation id="5117590920725113268">அடுத்த மாதத்தைக் காட்டு</translation>
+<translation id="512758898067543763">வரிசை மேற்தலைப்பு</translation>
+<translation id="5143125788380636750">முடிவுரை</translation>
+<translation id="5164977714490026579">மதிப்பானது, கண்டிப்பாக <ph name="MINIMUM" /> ஐ விட அதிகமாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> பெ.பை</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப் பெறாமல் உள்ளது.</translation>
+<translation id="5334352251556557839">மீடியாவை இயக்க முடியவில்லை.</translation>
+<translation id="5406322316791861025">உருவம்</translation>
+<translation id="5453733299334684579">ட்ரீ உருப்படி</translation>
+<translation id="5466621249238537318">ஒன்று அல்லது அதற்குமேற்பட்ட கோப்புகளைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="5468998798572797635">முழுத்திரையிலிருந்து வெளியேறு</translation>
+<translation id="5516424706154626233">தேதி தேர்ந்தெடுப்பான்</translation>
+<translation id="5537725057119320332">அலைபரப்பு</translation>
+<translation id="5546461542133609677">ஒலி இயக்கு</translation>
+<translation id="5608153257855394627">தனிப்படுத்தும்</translation>
+<translation id="561939826962581046">நேரம்</translation>
+<translation id="5630795885300617244">10வி தவிர்க்க, இடது அல்லது வலதுபுறம் இருமுறை தட்டவும்</translation>
+<translation id="5631759159893697722">சுருக்கம்</translation>
+<translation id="5643186887447432888">பொத்தான்</translation>
+<translation id="5677946354068040947">கூடுதல் விருப்பங்கள் பட்டன்</translation>
+<translation id="576709008726043716">அறிமுகம்</translation>
+<translation id="57838592816432529">ஒலியடக்கு</translation>
+<translation id="5860033963881614850">ஆஃப்</translation>
+<translation id="588258955323874662">முழுத்திரை</translation>
+<translation id="5888666972993069672">இப்போது <ph name="DEVICE_FRIENDLY_NAME" />க்கு அனுப்புகிறது</translation>
+<translation id="591047860372322273">தேடல் பெட்டி</translation>
+<translation id="5939518447894949180">மீட்டமை</translation>
+<translation id="5966707198760109579">வாரம்</translation>
+<translation id="5987525920412732405">சுழல் பொத்தான்</translation>
+<translation id="6011459053400940133">ஒலியளவு ஸ்லைடர்</translation>
+<translation id="6015796118275082299">ஆண்டு</translation>
+<translation id="6023896073578205740">பட்டியல் பெட்டி</translation>
+<translation id="6150588977291308318">நூல்விவர அட்டவணை</translation>
+<translation id="6164829606128959761">மீட்டர்</translation>
+<translation id="6166809985690652833">பின்னுரை</translation>
+<translation id="6209276755895393898"><ph name="DESCRIPTION" /> போலத் தோன்றுகிறது.</translation>
+<translation id="6213469881011901533">அருஞ்சொல் திரட்டு</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையிலிருந்து வெளியேறு</translation>
+<translation id="6398862346408813489">மாதம் தேர்ந்தெடுப்புப் பலகத்தைக் காட்டு</translation>
+<translation id="6404546809543547843">ஆடியோ நேர ஸ்கிரப்பர்</translation>
+<translation id="6443871981718447451">விரிவான வசனங்கள் மெனுவைக் காட்டும்</translation>
+<translation id="6453774872122745852">அங்கீகாரங்கள்</translation>
+<translation id="6475115390776617481">தற்சமயம் இன்னொருவர் பயன்படுத்துகிறார்</translation>
+<translation id="648732519525291180">நேரம் தேர்ந்தெடுப்பான்</translation>
+<translation id="6550675742724504774">விருப்பத்தேர்வுகள்</translation>
+<translation id="6572309429103589720">இலக்கணப்பிழை</translation>
+<translation id="658823671542763450">முழுத்திரைக்குச் செல்</translation>
+<translation id="663493177488814956">ஊட்டம்</translation>
+<translation id="6637586476836377253">பதிவு</translation>
+<translation id="6643016212128521049">அழி</translation>
+<translation id="668171684555832681">மற்றவை…</translation>
+<translation id="6692633176391053278">ஸ்டெப்பர்</translation>
+<translation id="6709570249143506788">மோசமான வீடியோவின் தரம்</translation>
+<translation id="6755330956360078551">உதவிக்குறிப்பு</translation>
+<translation id="6790428901817661496">இயக்கு</translation>
+<translation id="6820355525329141109">செருகுநிரல் ஏற்றப்படவில்லை.</translation>
+<translation id="6820615603175220800">நூல்விவர அட்டவணை மேற்கோள்</translation>
+<translation id="6843725295806269523">ஒலியடக்கு</translation>
+<translation id="6885760532393684712">கோப்பகம்</translation>
+<translation id="689129560213475294">முத்திரை</translation>
+<translation id="6934078000481955284">பிளாக்கோட்</translation>
+<translation id="693476918119313863">மேற்குறிப்பு</translation>
+<translation id="6941933287844615239">மீடியாவைப் பதிவிறக்கு</translation>
+<translation id="6981594929165378967">செருகும்</translation>
+<translation id="6989848892321993519">இந்த உரையில் <ph name="MIN_CHARACTERS" /> அல்லது அதற்கு மேற்பட்ட எழுத்துக்குறிகளைப் பயன்படுத்தவும் (தற்போது 1 எழுத்துக்குறியைப் பயன்படுத்துகிறீர்கள்).</translation>
+<translation id="7034405885550056553">பரிந்துரை</translation>
+<translation id="709897737746224366">கோரிய வடிவமைப்பில் தருக.</translation>
+<translation id="7118469954320184356">விவரம் எதுவுமில்லை.</translation>
+<translation id="7139483182332611405">முன்னுரை</translation>
+<translation id="7214187073215825913">உள்ளடக்கத் தகவல்</translation>
+<translation id="7263440858009898357">பட்டியலிலிருந்து ஒரு உருப்படியைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="727747134524199931">நெடுவரிசை மேற்தலைப்பு</translation>
+<translation id="7320576522385648310">ஏற்றுகிறது</translation>
+<translation id="7353453495576941748">பங்களித்தவர்</translation>
+<translation id="7364796246159120393">கோப்பைத் தேர்வு செய்க</translation>
+<translation id="739024184232394898">மற்றவை…</translation>
+<translation id="7405738980073107433">முடிவுக்குறிப்புகள்</translation>
+<translation id="7410239719251593705">வயதுவந்தோருக்கான உள்ளடக்கம் இருக்கலாம். விவரம் இல்லை.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> டெ.பை</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">பதிவிறக்கு</translation>
+<translation id="7529102961911894712">பின்னிணைப்பு</translation>
+<translation id="7533959249147584474">லேபிளிடப்படாத கிராஃபிக்</translation>
+<translation id="7647456547678091388">உதவிக்குறிப்பு</translation>
+<translation id="7661956066982048809">கிராஃபிக்ஸ் ஆவணம்</translation>
+<translation id="7673697353781729403">மணிநேரம்</translation>
+<translation id="7681220483256441252">பொருளடக்கம்</translation>
+<translation id="7740050170769002709">HTML உள்ளடக்கம்</translation>
+<translation id="7745230546936012372">சூழல் மெனுவைத் திறந்தால் மறைந்துள்ள படங்களின் விவரங்களைப் பெறலாம்.</translation>
+<translation id="7750228210027921155">பிக்ச்சர்-இன்-பிக்ச்சர்</translation>
+<translation id="775297008183122718">தவறான உள்ளீடு</translation>
+<translation id="7789962463072032349">இடைநிறுத்து</translation>
+<translation id="7802800022689234070">கூடுதல் உள்ளடக்க முக்கோணம்</translation>
+<translation id="7888071071722539607">மின்னஞ்சல் முகவரியில் '<ph name="ATSIGN" />' ஐச் சேர்க்கவும். '<ph name="ATSIGN" />' இல் '<ph name="INVALIDADDRESS" />' இல்லை.</translation>
+<translation id="7891486169920085145">பிரிப்பான்</translation>
+<translation id="795667975304826397">எந்த கோப்பும் தேர்ந்தெடுக்கப்படவில்லை</translation>
+<translation id="8053789581856978548">தேடல் உரைப் புலம்</translation>
+<translation id="8057695513531652401">அறிவிப்பு</translation>
+<translation id="8105797009065549151">குறிப்பு மேற்கோள்</translation>
+<translation id="811583516810654505">விளக்கத்தைப் பெறுகிறது...</translation>
+<translation id="8117451130807776954">இந்த வாரம்</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">உள்ளூர் தேதி &amp; நேரத் தேர்வி</translation>
+<translation id="8261464734335370856">எழுத்துப்பிழை</translation>
+<translation id="8284326494547611709">வசனங்கள்</translation>
+<translation id="8346634859695247203">பிரிவு</translation>
+<translation id="835897206747267392">செல்லாத மதிப்பு.</translation>
+<translation id="8403857369060869934">முடிவடைந்த நேரம்: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">பகுதி</translation>
+<translation id="8433900881053900389">கருவிப்பட்டி</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> கோப்புகள்</translation>
+<translation id="8451268428117625855">ஒரு கோப்பை தேர்ந்தெடுக்கவும்.</translation>
+<translation id="8461852803063341183">ரேடியோ பட்டன்</translation>
+<translation id="8474886197722836894">அர்ப்பணம்</translation>
+<translation id="8531739829932800271">பிழைகள்</translation>
+<translation id="8534579021159131403">நிமிடங்கள்</translation>
+<translation id="8541249477527128034">மீடியா கட்டுப்பாடு</translation>
+<translation id="8550857728288566671">கிராஃபிக்ஸ் சின்னம்</translation>
+<translation id="8583702881314752957">விளக்கப் பட்டியல்</translation>
+<translation id="8597182159515967513">தலைப்பு</translation>
+<translation id="860475260694818407">உள்ளடக்க அட்டவணை</translation>
+<translation id="8613126697340063924">தொலைநிலை இயக்கத்தைக் கட்டுப்படுத்தவும்</translation>
+<translation id="862370744433916922">துணை தலைப்பு</translation>
+<translation id="8711688047404765493">வெளியீடு</translation>
+<translation id="8750798805984357768">தயவுசெய்து இந்த விருப்பங்களில் ஒன்றைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="8808573423886751634">அத்தியாயம்</translation>
+<translation id="8822203815165896261">அனுமதி வழங்குவது தொடர்பான தகவல்</translation>
+<translation id="8845239796550121995">டிவிக்கு அனுப்புகிறது</translation>
+<translation id="8851136666856101339">முதன்மை</translation>
+<translation id="8875657656876809964">வீடியோ இயக்கப் பிழை</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> கி.பை.</translation>
+<translation id="8987927404178983737">மாதம்</translation>
+<translation id="901493112792887934">நடப்பு நேரம் வினாடிகளில்</translation>
+<translation id="901834265349196618">மின்னஞ்சல்</translation>
+<translation id="9048119486235211610">வழிசெலுத்தல்</translation>
+<translation id="9062295712474918030">ஆவணம்</translation>
+<translation id="9093215626363556771">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறையிலிருந்து வெளியேறும்</translation>
+<translation id="9108370397979208512">கணிதம்</translation>
+<translation id="9132465097189459683">மற்றவை…</translation>
+<translation id="9138385573473225930">விழிப்பூட்டல்</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> அன்று தொடங்குவது</translation>
+<translation id="916607977885256133">பிக்ச்சர்-இன்-பிக்ச்சர்</translation>
+<translation id="9168329111483466115">அடிக்குறிப்பு</translation>
+<translation id="954003015749068518">பிக்ச்சர்-இன்-பிக்ச்சர் பயன்முறைக்குச் செல்லும்</translation>
+<translation id="966787709310836684">மெனு</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..37217302268
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_te.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="te">
+<translation id="1018939186200882850">మెను అంశం</translation>
+<translation id="10623998915015855">టోగుల్ బటన్</translation>
+<translation id="1088086359088493902">సెకన్లు</translation>
+<translation id="1171774979989969504">దయచేసి ఇమెయిల్ చిరునామాను ఎంటర్ చెయ్యండి.</translation>
+<translation id="1178581264944972037">పాజ్ చేయి</translation>
+<translation id="1188858454923323853">బహుమానపూర్వకం</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">స్లయిడర్</translation>
+<translation id="1211441953136645838">ఎండ్‌నోట్</translation>
+<translation id="1281252709823657822">డైలాగ్</translation>
+<translation id="1335095011850992622">సహకారులు</translation>
+<translation id="1342835525016946179">కథనం</translation>
+<translation id="1359897965706325498">బ్యానర్</translation>
+<translation id="1589122976691792535">ప్రాంతం</translation>
+<translation id="1591562245178063882">ఈ నెల</translation>
+<translation id="1637811476055996098">ఫైల్‌లను ఎంచుకోండి</translation>
+<translation id="1650423536718072820">పుల్‌కోట్</translation>
+<translation id="1727886345390570319">ఉపశీర్షికల మెనూని దాచు</translation>
+<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఇమెయిల్ చిరునామాను నమోదు చేయండి.</translation>
+<translation id="1758486001363313524">ఇతర...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">వృక్షాంశ గ్రిడ్</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">రిమోట్ పరికరంలో ప్లే చేస్తుంది</translation>
+<translation id="190587075670221089">తొలగింపు</translation>
+<translation id="1907737156431278478">ఉదాహరణ</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">స్థితి</translation>
+<translation id="1938124657309484470">విలువ తప్పనిసరిగా <ph name="MAXIMUM_DATE_OR_TIME" /> లేదా అంతకంటే మునుపటిది అయి ఉండాలి.</translation>
+<translation id="1946271899482435442">తేదీ ఎంపికను చూపుతుంది</translation>
+<translation id="1993104285338243655">మిర్రరింగ్‌కు మార్చబడింది</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN" />'లో '<ph name="DOT" />' తప్పు స్థానంలో ఉపయోగించబడింది.</translation>
+<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="2247351761944213033"><ph name="WEEKNUMBER" />వ వారం, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">ట్రాక్ <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">చెక్‌బాక్స్</translation>
+<translation id="2311842470354187719">పేజీ విభజన</translation>
+<translation id="2335594187091864976">తేదీ మరియు సమయం ఎంపిక</translation>
+<translation id="245932805758469625">వీడియోలో మిగిలి ఉన్న సెకన్లు</translation>
+<translation id="248395913932153421">రోజు</translation>
+<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ను పూర్తి చేయండి.</translation>
+<translation id="2508569020611168319">ట్యాబ్ జాబితా</translation>
+<translation id="2561842179657104141">మరిన్ని మీడియా నియంత్రణలను చూపు</translation>
+<translation id="2572483411312390101">ప్లే చేయి</translation>
+<translation id="2613802280814924224">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE" /> అనేది సమీప చెల్లుబాటు విలువ.</translation>
+<translation id="2653659639078652383">సమర్పించు</translation>
+<translation id="2657045182931379222">గ్రాఫిక్స్ ఆబ్జెక్ట్</translation>
+<translation id="2674318244760992338">ఫుటర్</translation>
+<translation id="2709516037105925701">స్వయంపూర్తి</translation>
+<translation id="2723001399770238859">ఆడియో</translation>
+<translation id="2725963129578236554">వ్యాఖ్యలు</translation>
+<translation id="2746543609216772311">విలువ తప్పనిసరిగా <ph name="MINIMUM_DATE_OR_TIME" /> లేదా అంతకంటే తదుపరిది అయి ఉండాలి.</translation>
+<translation id="2759744352195237655">పాప్ అప్ బటన్</translation>
+<translation id="2761667185364618470">మీరు కొనసాగాలనుకుంటే దయచేసి ఈ బాక్స్‌కి టిక్కు పెట్టండి.</translation>
+<translation id="2844350028562914727">వివరాలు</translation>
+<translation id="2896972712917208084">రేడియో సమూహం</translation>
+<translation id="2908441821576996758">దయచేసి కామాతో వేరు చేసిన ఇమెయిల్ చిరునామాల జాబితాను నమోదు చేయండి.</translation>
+<translation id="2940813599313844715">ఆబ్జెక్ట్</translation>
+<translation id="3040011195152428237">లింక్</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. ఫీల్డ్ అసంపూర్ణంగా ఉంది లేదా ఇందులోని తేదీ చెల్లదు.</translation>
+<translation id="3078740164268491126">పట్టిక</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">దయచేసి ఒక URLని ఎంటర్ చేయండి.</translation>
+<translation id="3175736971608411871">టైమర్</translation>
+<translation id="3199563858620722075">కాంబో పెట్టె</translation>
+<translation id="3450233048674729344">విలువ ఖచ్చితంగా <ph name="MAXIMUM" /> కంటే తగ్గువగా లేదా సమానంగా ఉండాలి.</translation>
+<translation id="3486220673238053218">నిర్వచనం</translation>
+<translation id="3557673793733683882">ముఖ్య శీర్షిక <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">వారం ఎంపిక</translation>
+<translation id="3685101356851116974">లేబుల్ లేని చిత్రం</translation>
+<translation id="3706100364254443312">మార్పు</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమింపజేయి</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">పదం</translation>
+<translation id="3822383571486410024">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN" />'కి ముందు ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
+<translation id="3846214748874656680">పూర్తి స్క్రీన్ నుండి నిష్క్రమించు</translation>
+<translation id="3889183436948184105">పునర్విమర్శ</translation>
+<translation id="3920932319529768807">ముగింపు</translation>
+<translation id="3924558731517983934">అప్లికేషన్‌</translation>
+<translation id="3944740393230681990">ప్రారంభం</translation>
+<translation id="3960700977367013758">స్క్రోల్ బార్</translation>
+<translation id="4103419683916926126">మిల్లీసెకన్లు</translation>
+<translation id="4151657705144244502">గ్రాఫిక్</translation>
+<translation id="4160057747563657758">టెలిఫోన్</translation>
+<translation id="4193965531860883258">ముందుమాట</translation>
+<translation id="4201051445878709314">మునుపటి నెలను చూపుతుంది</translation>
+<translation id="421884353938374759">రంగు ఎంపిక</translation>
+<translation id="4248100235867064564">మెనూ బార్</translation>
+<translation id="4360991593054037559">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE_LOW" /> మరియు <ph name="VALID_VALUE_HIGHER" /> అనేవి రెండు సమీప చెల్లుబాటు విలువలు.</translation>
+<translation id="4384583879834880242">Q&amp;A</translation>
+<translation id="4413860115965805769">మెను బటన్</translation>
+<translation id="4444765639179266822">ఇది చెబుతున్నట్లుగా ఉంది: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">పదకోశ సూచన</translation>
+<translation id="4522570452068850558">వివరాలు</translation>
+<translation id="4542388879936266156">మిగిలి ఉన్న సమయం: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ఫారమ్</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
+<translation id="4668956016107839909">అనుబంధం</translation>
+<translation id="4718048029184481307">చిత్రంలో చిత్రం మోడ్‌లో ప్లే అవుతోంది</translation>
+<translation id="4742539557769756338">ముఖచిత్రం</translation>
+<translation id="4748357248530471599">డిస్‌ప్లే కత్తిరింపు పూర్తి స్క్రీన్‌ని సక్రియం చేస్తుంది</translation>
+<translation id="4757246831282535685">ట్యాబ్ ప్యానెల్</translation>
+<translation id="4763480195061959176">వీడియో</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">దయచేసి సంఖ్యను నమోదు చేయండి.</translation>
+<translation id="4912536737030637138">వివరణపట్టి నమోదు</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ఎంచుకోబడ్డాయి</translation>
+<translation id="4992066212339426712">అన్‌మ్యూట్ చేయి</translation>
+<translation id="49969490063480558">దయచేసి '<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="5034860022980953847">ప్రోగ్రెస్ సూచిక</translation>
+<translation id="5090250355906949916">వీడియో సమయ స్క్రబ్బర్</translation>
+<translation id="5093189678851173835">పరిచయ వాక్యం</translation>
+<translation id="5117590920725113268">తరువాత నెలను చూపుతుంది</translation>
+<translation id="512758898067543763">అడ్డు వరుస శీర్షిక</translation>
+<translation id="5143125788380636750">ఉపసంహారం</translation>
+<translation id="5164977714490026579">విలువ ఖచ్చితంగా <ph name="MINIMUM" /> కంటే ఎక్కువగా లేదా సమానంగా ఉండాలి.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">దయచేసి '<ph name="ATSIGN" />'కి ముందు ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="5334352251556557839">మీడియాను ప్లే చేయడం సాధ్యపడలేదు.</translation>
+<translation id="5406322316791861025">రూపం</translation>
+<translation id="5453733299334684579">వృక్షాంశం</translation>
+<translation id="5466621249238537318">దయచేసి ఒకటి లేదా మరిన్ని ఫైళ్ళను ఎంచుకోండి.</translation>
+<translation id="5468998798572797635">పూర్తి స్క్రీన్ నుండి నిష్క్రమించు</translation>
+<translation id="5516424706154626233">తేదీ ఎంపిక</translation>
+<translation id="5537725057119320332">Cast</translation>
+<translation id="5546461542133609677">అన్‌మ్యూట్ చేయి</translation>
+<translation id="5608153257855394627">హైలైట్ చేసినది</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">10సె దాటవేయడానికి రెండుసార్లు ఎడమ లేదా కుడివైపుకి నొక్కండి</translation>
+<translation id="5631759159893697722">సంక్షేపం</translation>
+<translation id="5643186887447432888">బటన్</translation>
+<translation id="5677946354068040947">మరిన్ని ఎంపికలు</translation>
+<translation id="576709008726043716">పరిచయం</translation>
+<translation id="57838592816432529">మ్యూట్ చేయి</translation>
+<translation id="5860033963881614850">ఆఫ్ అయ్యింది</translation>
+<translation id="588258955323874662">పూర్తితెర</translation>
+<translation id="5888666972993069672">ఇప్పుడు <ph name="DEVICE_FRIENDLY_NAME" />కి ప్రసారం చేస్తోంది</translation>
+<translation id="591047860372322273">శోధన పెట్టె</translation>
+<translation id="5939518447894949180">రీసెట్ చేయి</translation>
+<translation id="5966707198760109579">వారం</translation>
+<translation id="5987525920412732405">స్పిన్ బటన్</translation>
+<translation id="6011459053400940133">వాల్యూమ్ స్లయిడర్</translation>
+<translation id="6015796118275082299">సంవత్సరం</translation>
+<translation id="6023896073578205740">జాబితా పెట్టె</translation>
+<translation id="6150588977291308318">వివరణపట్టి</translation>
+<translation id="6164829606128959761">మీటర్</translation>
+<translation id="6166809985690652833">చివరిమాట</translation>
+<translation id="6209276755895393898">వీరిలా కనిపిస్తున్నారు: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">పదకోశం</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమించు</translation>
+<translation id="6398862346408813489">నెల ఎంపిక ప్యానెల్‌ను చూపుతుంది</translation>
+<translation id="6404546809543547843">ఆడియో సమయ స్క్రబ్బర్</translation>
+<translation id="6443871981718447451">ఉపశీర్షికల మెనూని చూపు</translation>
+<translation id="6453774872122745852">గుర్తింపులు</translation>
+<translation id="6475115390776617481">లైవ్ ప్రెజెన్స్</translation>
+<translation id="648732519525291180">సమయం ఎంపిక</translation>
+<translation id="6550675742724504774">ఎంపికలు</translation>
+<translation id="6572309429103589720">చెల్లని వ్యాకరణం</translation>
+<translation id="658823671542763450">పూర్తి స్క్రీన్‌లోకి ప్రవేశించు</translation>
+<translation id="663493177488814956">ఫీడ్</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">క్లియర్ చేయి</translation>
+<translation id="668171684555832681">ఇతర...</translation>
+<translation id="6692633176391053278">స్టెప్పర్</translation>
+<translation id="6709570249143506788">ప్లేబ్యాక్ నాణ్యత బాగాలేదు</translation>
+<translation id="6755330956360078551">సాధన చిట్కా</translation>
+<translation id="6790428901817661496">ప్లే చేయి</translation>
+<translation id="6820355525329141109">ప్లగ్ఇన్‌‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
+<translation id="6820615603175220800">వివరణపట్టి సూచన</translation>
+<translation id="6843725295806269523">మ్యూట్ చేయి</translation>
+<translation id="6885760532393684712">డైరెక్టరీ</translation>
+<translation id="689129560213475294">ఆఖరిమాట</translation>
+<translation id="6934078000481955284">బ్లాక్‌కోట్</translation>
+<translation id="693476918119313863">ముఖ్య శీర్షిక</translation>
+<translation id="6941933287844615239">మీడియా అంశం డౌన్‌లోడ్ చేయి</translation>
+<translation id="6981594929165378967">చొప్పించడం</translation>
+<translation id="6989848892321993519">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు 1 అక్షరాన్ని ఉపయోగిస్తున్నారు).</translation>
+<translation id="7034405885550056553">సూచన</translation>
+<translation id="709897737746224366">దయచేసి అభ్యర్థించిన ఆకృతీకరణను సరిపోల్చండి.</translation>
+<translation id="7118469954320184356">వివరణ అందుబాటులో లేదు.</translation>
+<translation id="7139483182332611405">ముందుమాట</translation>
+<translation id="7214187073215825913">కంటెంట్ సమాచారం</translation>
+<translation id="7263440858009898357">దయచేసి జాబితాలోని ఒక అంశాన్ని ఎంచుకోండి.</translation>
+<translation id="727747134524199931">నిలువు వరుస శీర్షిక</translation>
+<translation id="7320576522385648310">బఫర్ చేయడం</translation>
+<translation id="7353453495576941748">సహకారి</translation>
+<translation id="7364796246159120393">ఫైల్‌ను ఎంచుకోండి</translation>
+<translation id="739024184232394898">ఇతర...</translation>
+<translation id="7405738980073107433">ఎండ్‌నోట్‌లు</translation>
+<translation id="7410239719251593705">పెద్దలకు మాత్రమే విషయాలను కలిగి ఉండవచ్చు. వివరణ అందుబాటులో లేదు.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">డౌన్‌లోడ్ చేయి</translation>
+<translation id="7529102961911894712">వెనుకకు తీసుకువెళ్లే లింక్‌</translation>
+<translation id="7533959249147584474">లేబుల్ లేని గ్రాఫిక్</translation>
+<translation id="7647456547678091388">చిట్కా</translation>
+<translation id="7661956066982048809">గ్రాఫిక్స్ పత్రం</translation>
+<translation id="7673697353781729403">గంటలు</translation>
+<translation id="7681220483256441252">సూచిక</translation>
+<translation id="7740050170769002709">HTML కంటెంట్</translation>
+<translation id="7745230546936012372">అందించలేకపోయిన చిత్ర వివరణలను పొందడానికి, సందర్భ మెనూని తెరవండి.</translation>
+<translation id="7750228210027921155">చిత్రంలో చిత్రం</translation>
+<translation id="775297008183122718">నమోదు చెల్లదు</translation>
+<translation id="7789962463072032349">నిలిపివేయి</translation>
+<translation id="7802800022689234070">కంటెంట్‌ను విస్తరింపజేసే లేదా కుదించే త్రిభుజం</translation>
+<translation id="7888071071722539607">దయచేసి ఇమెయిల్ చిరునామాలో '<ph name="ATSIGN" />'ని చేర్చండి. '<ph name="INVALIDADDRESS" />'లో '<ph name="ATSIGN" />' లేదు.</translation>
+<translation id="7891486169920085145">విభజన</translation>
+<translation id="795667975304826397">ఫైల్ ఏదీ ఎంచుకోలేదు</translation>
+<translation id="8053789581856978548">శోధన వచనం ఫీల్డ్</translation>
+<translation id="8057695513531652401">గమనిక</translation>
+<translation id="8105797009065549151">గమనిక సూచన</translation>
+<translation id="811583516810654505">వివరణను పొందుతోంది...</translation>
+<translation id="8117451130807776954">ఈ వారం</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">స్థానిక తేదీ మరియు సమయం ఎంపిక</translation>
+<translation id="8261464734335370856">చెల్లని అక్షరక్రమం</translation>
+<translation id="8284326494547611709">ఉపశీర్షికలు</translation>
+<translation id="8346634859695247203">విభాగం</translation>
+<translation id="835897206747267392">చెల్లని విలువ.</translation>
+<translation id="8403857369060869934">గడిచిన సమయం: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">భాగం</translation>
+<translation id="8433900881053900389">సాధన పట్టీ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ఫైళ్ళు</translation>
+<translation id="8451268428117625855">దయచేసి ఒక ఫైల్‌ని ఎంచుకోండి.</translation>
+<translation id="8461852803063341183">రేడియో బటన్</translation>
+<translation id="8474886197722836894">అంకితం</translation>
+<translation id="8531739829932800271">తప్పొప్పుల పట్టిక</translation>
+<translation id="8534579021159131403">నిమిషాలు</translation>
+<translation id="8541249477527128034">మీడియా నియంత్రణ</translation>
+<translation id="8550857728288566671">గ్రాఫిక్స్ చిహ్నం</translation>
+<translation id="8583702881314752957">నిర్వచన జాబితా</translation>
+<translation id="8597182159515967513">శీర్షిక</translation>
+<translation id="860475260694818407">కంటెంట్‌ల‌ పట్టిక</translation>
+<translation id="8613126697340063924">రిమోట్ ప్లేబ్యాక్‌ను నియంత్రిస్తుంది</translation>
+<translation id="862370744433916922">ఉపశీర్షిక</translation>
+<translation id="8711688047404765493">అవుట్‌పుట్</translation>
+<translation id="8750798805984357768">దయచేసి ఈ ఎంపికలలో ఒకదాన్ని ఎంచుకోండి.</translation>
+<translation id="8808573423886751634">అధ్యాయం</translation>
+<translation id="8822203815165896261">ఆథరింగ్ సమాచారం</translation>
+<translation id="8845239796550121995">ఇప్పుడు మీ టీవీలో ప్రసారం చేస్తోంది</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">వీడియో ప్లేబ్యాక్ ఎర్రర్</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">నెల</translation>
+<translation id="901493112792887934">సెకన్లలో ప్రస్తుత సమయం</translation>
+<translation id="901834265349196618">ఇమెయిల్</translation>
+<translation id="9048119486235211610">నావిగేషన్</translation>
+<translation id="9062295712474918030">పత్రం</translation>
+<translation id="9093215626363556771">చిత్రంలో చిత్రం మోడ్ నుండి నిష్క్రమింపజేస్తుంది</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">ఇతర...</translation>
+<translation id="9138385573473225930">హెచ్చరిక</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> నుండి ప్రారంభమవుతుంది</translation>
+<translation id="916607977885256133">చిత్రంలో చిత్రం</translation>
+<translation id="9168329111483466115">ఫుట్‌నోట్</translation>
+<translation id="954003015749068518">చిత్రంలో చిత్రం మోడ్‌లోకి ప్రవేశిస్తుంది</translation>
+<translation id="966787709310836684">మెను</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..385e590bd2f
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_th.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="th">
+<translation id="1018939186200882850">รายการเมนู</translation>
+<translation id="10623998915015855">ปุ่มสลับ</translation>
+<translation id="1088086359088493902">วินาที</translation>
+<translation id="1171774979989969504">โปรดป้อนที่อยู่อีเมล</translation>
+<translation id="1178581264944972037">หยุดชั่วคราว</translation>
+<translation id="1188858454923323853">ส่วนเสริม</translation>
+<translation id="1206619573307042055">ตัวอักษรวิ่ง</translation>
+<translation id="1206693055195146388">แถบเลื่อน</translation>
+<translation id="1211441953136645838">อ้างอิงท้ายเรื่อง</translation>
+<translation id="1281252709823657822">กล่องโต้ตอบ</translation>
+<translation id="1335095011850992622">เครดิต</translation>
+<translation id="1342835525016946179">บทความ</translation>
+<translation id="1359897965706325498">แบนเนอร์</translation>
+<translation id="1589122976691792535">ภูมิภาค</translation>
+<translation id="1591562245178063882">เดือนนี้</translation>
+<translation id="1637811476055996098">เลือกไฟล์</translation>
+<translation id="1650423536718072820">การเน้นข้อความ</translation>
+<translation id="1727886345390570319">ซ่อนเมนูคำอธิบายภาพ</translation>
+<translation id="1729654308190250600">โปรดป้อนที่อยู่อีเมลที่ไม่ว่างเปล่า</translation>
+<translation id="1758486001363313524">อื่นๆ...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">แผนผังต้นไม้</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">เล่นในอุปกรณ์ระยะไกล</translation>
+<translation id="190587075670221089">การลบ</translation>
+<translation id="1907737156431278478">ตัวอย่าง</translation>
+<translation id="1921819250265091946">วว</translation>
+<translation id="1930711995431081526">สถานะ</translation>
+<translation id="1938124657309484470">ค่าต้องเป็น <ph name="MAXIMUM_DATE_OR_TIME" /> หรือก่อนหน้านั้น</translation>
+<translation id="1946271899482435442">แสดงเครื่องมือเลือกวันที่</translation>
+<translation id="1993104285338243655">เปลี่ยนเป็นการมิเรอร์</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />" ถูกใช้งานในตำแหน่งที่ไม่ถูกต้องใน "<ph name="INVALIDDOMAIN" />"</translation>
+<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="2247351761944213033">สัปดาห์ที่ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">แทร็ก <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">ช่องทำเครื่องหมาย</translation>
+<translation id="2311842470354187719">ตัวแบ่งหน้า</translation>
+<translation id="2335594187091864976">เครื่องมือเลือกวันที่และเวลา</translation>
+<translation id="245932805758469625">จำนวนวินาทีที่เหลือของวิดีโอ</translation>
+<translation id="248395913932153421">วัน</translation>
+<translation id="2507943997699731163">โปรดกรอกฟิลด์นี้</translation>
+<translation id="2508569020611168319">รายการแท็บ</translation>
+<translation id="2561842179657104141">แสดงส่วนควบคุมสื่อเพิ่มเติม</translation>
+<translation id="2572483411312390101">เล่น</translation>
+<translation id="2613802280814924224">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องคือ <ph name="VALID_VALUE" /></translation>
+<translation id="2653659639078652383">ส่ง</translation>
+<translation id="2657045182931379222">ออบเจ็กต์กราฟิก</translation>
+<translation id="2674318244760992338">ส่วนท้าย</translation>
+<translation id="2709516037105925701">ป้อนอัตโนมัติ</translation>
+<translation id="2723001399770238859">เสียง</translation>
+<translation id="2725963129578236554">ความคิดเห็น</translation>
+<translation id="2746543609216772311">ค่าต้องเป็น <ph name="MINIMUM_DATE_OR_TIME" /> หรือหลังจากนั้น</translation>
+<translation id="2759744352195237655">ปุ่มป๊อปอัป</translation>
+<translation id="2761667185364618470">โปรดเลือกช่องนี้หากคุณต้องการดำเนินการต่อ</translation>
+<translation id="2844350028562914727">รายละเอียด</translation>
+<translation id="2896972712917208084">กลุ่มตัวเลือก</translation>
+<translation id="2908441821576996758">โปรดป้อนรายการที่อยู่อีเมลโดยคั่นด้วยเครื่องหมายจุลภาค</translation>
+<translation id="2940813599313844715">ออบเจ็กต์</translation>
+<translation id="3040011195152428237">ลิงก์</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">โปรดป้อนค่าที่ถูกต้อง ฟิลด์นี้ไม่สมบูรณ์หรือมีวันที่ที่ไม่ถูกต้อง</translation>
+<translation id="3078740164268491126">ตาราง</translation>
+<translation id="3086746722712840547">หมายเหตุ</translation>
+<translation id="310520048233152454">โปรดป้อน URL</translation>
+<translation id="3175736971608411871">ตัวจับเวลา</translation>
+<translation id="3199563858620722075">ช่องตัวเลือกรวม</translation>
+<translation id="3450233048674729344">ค่าต้องน้อยกว่าหรือเท่ากับ <ph name="MAXIMUM" /></translation>
+<translation id="3486220673238053218">คำจำกัดความ</translation>
+<translation id="3557673793733683882">ส่วนหัว <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">เครื่องมือเลือกสัปดาห์</translation>
+<translation id="3685101356851116974">รูปภาพที่ไม่มีป้ายกำกับ</translation>
+<translation id="3706100364254443312">สวิตช์</translation>
+<translation id="3732799496749320381">ดด</translation>
+<translation id="3754210790023674521">ออกจากการแสดงภาพซ้อนภาพ</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">คีย์เวิร์ด</translation>
+<translation id="3822383571486410024">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี <ph name="CURRENT_LENGTH" /> ตัว)</translation>
+<translation id="383465348367842624">ส่วนที่ตามด้วย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
+<translation id="3846214748874656680">ออกจากการแสดงเต็มหน้าจอ</translation>
+<translation id="3889183436948184105">การแก้ไข</translation>
+<translation id="3920932319529768807">บทสรุป</translation>
+<translation id="3924558731517983934">แอปพลิเคชัน</translation>
+<translation id="3944740393230681990">อารัมภบท</translation>
+<translation id="3960700977367013758">แถบเลื่อน</translation>
+<translation id="4103419683916926126">มิลลิวินาที</translation>
+<translation id="4151657705144244502">กราฟิก</translation>
+<translation id="4160057747563657758">โทรศัพท์</translation>
+<translation id="4193965531860883258">คำนำ</translation>
+<translation id="4201051445878709314">แสดงเดือนที่ผ่านมา</translation>
+<translation id="421884353938374759">ตัวเลือกสี</translation>
+<translation id="4248100235867064564">แถบเมนู</translation>
+<translation id="4360991593054037559">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องสองรายการคือ <ph name="VALID_VALUE_LOW" /> และ <ph name="VALID_VALUE_HIGHER" /></translation>
+<translation id="4384583879834880242">ถามและตอบ</translation>
+<translation id="4413860115965805769">ปุ่มเมนู</translation>
+<translation id="4444765639179266822">ดูเหมือนจะพูดว่า <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">ข้อมูลอ้างอิงอภิธานศัพท์</translation>
+<translation id="4522570452068850558">รายละเอียด</translation>
+<translation id="4542388879936266156">เวลาที่เหลือ: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">ฟอร์ม</translation>
+<translation id="4661075872484491155">แผนผัง</translation>
+<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
+<translation id="4668956016107839909">ภาคผนวก</translation>
+<translation id="4718048029184481307">กำลังเล่นแบบการแสดงภาพซ้อนภาพ</translation>
+<translation id="4742539557769756338">หน้าปก</translation>
+<translation id="4748357248530471599">สลับเป็นแบบเต็มหน้าจอสำหรับหน้าจอรอยบาก</translation>
+<translation id="4757246831282535685">แผงแท็บ</translation>
+<translation id="4763480195061959176">วิดีโอ</translation>
+<translation id="479989351350248267">ค้นหา</translation>
+<translation id="4812940957355064477">โปรดป้อนตัวเลข</translation>
+<translation id="4912536737030637138">รายการบรรณานุกรม</translation>
+<translation id="4975562563186953947">เลือกไว้ <ph name="SELECTED_COUNT" /> รายการ</translation>
+<translation id="4992066212339426712">เปิดเสียง</translation>
+<translation id="49969490063480558">โปรดป้อนส่วนที่ต่อท้าย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
+<translation id="5034860022980953847">ตัวบอกสถานะความคืบหน้า</translation>
+<translation id="5090250355906949916">ตัวควบคุมเวลาของวิดีโอ</translation>
+<translation id="5093189678851173835">คำจารึก</translation>
+<translation id="5117590920725113268">แสดงเดือนถัดไป</translation>
+<translation id="512758898067543763">ส่วนหัวของแถว</translation>
+<translation id="5143125788380636750">ปัจฉิมบท</translation>
+<translation id="5164977714490026579">ค่าต้องมากกว่าหรือเท่ากับ <ph name="MINIMUM" /></translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">โปรดป้อนส่วนหนึ่งโดยตามด้วย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
+<translation id="5334352251556557839">เล่นสื่อไม่ได้</translation>
+<translation id="5406322316791861025">ตัวเลข</translation>
+<translation id="5453733299334684579">รายการแบบต้นไม้</translation>
+<translation id="5466621249238537318">โปรดเลือกอย่างน้อยหนึ่งไฟล์</translation>
+<translation id="5468998798572797635">ออกจากการแสดงแบบเต็มหน้าจอ</translation>
+<translation id="5516424706154626233">เครื่องมือเลือกวันที่</translation>
+<translation id="5537725057119320332">ส่ง</translation>
+<translation id="5546461542133609677">เปิดเสียง</translation>
+<translation id="5608153257855394627">ไฮไลต์</translation>
+<translation id="561939826962581046">เวลา</translation>
+<translation id="5630795885300617244">แตะ 2 ครั้งที่ด้านขวาหรือซ้ายเพื่อข้ามทีละ 10 วินาที</translation>
+<translation id="5631759159893697722">บทคัดย่อ</translation>
+<translation id="5643186887447432888">ปุ่ม</translation>
+<translation id="5677946354068040947">ตัวเลือกเพิ่มเติม</translation>
+<translation id="576709008726043716">บทนำ</translation>
+<translation id="57838592816432529">ปิดเสียง</translation>
+<translation id="5860033963881614850">ปิด</translation>
+<translation id="588258955323874662">เต็มหน้าจอ</translation>
+<translation id="5888666972993069672">ขณะนี้กำลังแคสต์ไปที่ <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">ช่องค้นหา</translation>
+<translation id="5939518447894949180">รีเซ็ต</translation>
+<translation id="5966707198760109579">สัปดาห์</translation>
+<translation id="5987525920412732405">ปุ่มหมุน</translation>
+<translation id="6011459053400940133">แถบเลื่อนปรับระดับเสียง</translation>
+<translation id="6015796118275082299">ปี</translation>
+<translation id="6023896073578205740">ช่องรายการ</translation>
+<translation id="6150588977291308318">บรรณานุกรม</translation>
+<translation id="6164829606128959761">เมตร</translation>
+<translation id="6166809985690652833">คำแถลงท้ายเล่ม</translation>
+<translation id="6209276755895393898">ดูเหมือนเป็น<ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">อภิธานศัพท์</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">ออกจากการแสดงภาพซ้อนภาพ</translation>
+<translation id="6398862346408813489">แสดงแผงการเลือกเดือน</translation>
+<translation id="6404546809543547843">ตัวควบคุมเวลาของเสียง</translation>
+<translation id="6443871981718447451">แสดงเมนูคำอธิบายภาพ</translation>
+<translation id="6453774872122745852">กิตติกรรมประกาศ</translation>
+<translation id="6475115390776617481">ผู้ทำงานร่วมกันที่ดูเนื้อหานี้อยู่</translation>
+<translation id="648732519525291180">เครื่องมือเลือกเวลา</translation>
+<translation id="6550675742724504774">ตัวเลือก</translation>
+<translation id="6572309429103589720">ไวยากรณ์ไม่ถูกต้อง</translation>
+<translation id="658823671542763450">เข้าสู่โหมดเต็มหน้าจอ</translation>
+<translation id="663493177488814956">ฟีด</translation>
+<translation id="6637586476836377253">บันทึก</translation>
+<translation id="6643016212128521049">ล้าง</translation>
+<translation id="668171684555832681">อื่นๆ...</translation>
+<translation id="6692633176391053278">ตัวเพิ่ม/ลดระดับเสียง</translation>
+<translation id="6709570249143506788">คุณภาพการเล่นต่ำ</translation>
+<translation id="6755330956360078551">เคล็ดลับเครื่องมือ</translation>
+<translation id="6790428901817661496">เล่น</translation>
+<translation id="6820355525329141109">ไม่สามารถโหลดปลั๊กอิน</translation>
+<translation id="6820615603175220800">ข้อมูลอ้างอิงทางบรรณานุกรม</translation>
+<translation id="6843725295806269523">ปิดเสียง</translation>
+<translation id="6885760532393684712">ไดเรกทอรี</translation>
+<translation id="689129560213475294">ข้อมูลทางบรรณานุกรม</translation>
+<translation id="6934078000481955284">ข้อความที่ยกมา</translation>
+<translation id="693476918119313863">ส่วนหัว</translation>
+<translation id="6941933287844615239">ดาวน์โหลดสื่อ</translation>
+<translation id="6981594929165378967">การแทรก</translation>
+<translation id="6989848892321993519">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี 1 ตัว)</translation>
+<translation id="7034405885550056553">คำแนะนำ</translation>
+<translation id="709897737746224366">โปรดจับคู่รูปแบบที่ร้องขอ</translation>
+<translation id="7118469954320184356">ไม่มีคำอธิบาย</translation>
+<translation id="7139483182332611405">ส่วนนำ</translation>
+<translation id="7214187073215825913">ข้อมูลเกี่ยวกับเนื้อหา</translation>
+<translation id="7263440858009898357">โปรดเลือกรายการจากหน้ารายการ</translation>
+<translation id="727747134524199931">ส่วนหัวคอลัมน์</translation>
+<translation id="7320576522385648310">กำลังบัฟเฟอร์</translation>
+<translation id="7353453495576941748">เครดิต</translation>
+<translation id="7364796246159120393">เลือกไฟล์</translation>
+<translation id="739024184232394898">อื่นๆ...</translation>
+<translation id="7405738980073107433">อ้างอิงท้ายเรื่อง</translation>
+<translation id="7410239719251593705">ดูเหมือนจะมีเนื้อหาสำหรับผู้ใหญ่ ไม่มีคำอธิบาย</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">แท็บ</translation>
+<translation id="7514365320538308">ดาวน์โหลด</translation>
+<translation id="7529102961911894712">ลิงก์กลับมาที่หน้า</translation>
+<translation id="7533959249147584474">กราฟิกที่ไม่มีป้ายกำกับ</translation>
+<translation id="7647456547678091388">เคล็ดลับ</translation>
+<translation id="7661956066982048809">เอกสารกราฟิก</translation>
+<translation id="7673697353781729403">ชั่วโมง</translation>
+<translation id="7681220483256441252">ดัชนี</translation>
+<translation id="7740050170769002709">เนื้อหา HTML</translation>
+<translation id="7745230546936012372">เปิดเมนูตามบริบทเพื่อดูคำอธิบายรูปภาพที่หายไป</translation>
+<translation id="7750228210027921155">การแสดงภาพซ้อนภาพ</translation>
+<translation id="775297008183122718">ป้อนข้อมูลไม่ถูกต้อง</translation>
+<translation id="7789962463072032349">หยุดชั่วคราว</translation>
+<translation id="7802800022689234070">สามเหลี่ยมซ่อนเนื้อหา</translation>
+<translation id="7888071071722539607">โปรดใส่ "<ph name="ATSIGN" />" ในที่อยู่อีเมล "<ph name="INVALIDADDRESS" />" ขาด "<ph name="ATSIGN" />"</translation>
+<translation id="7891486169920085145">ตัวแยก</translation>
+<translation id="795667975304826397">ไม่ได้เลือกไฟล์ใด</translation>
+<translation id="8053789581856978548">ช่องข้อความค้นหา</translation>
+<translation id="8057695513531652401">ประกาศ</translation>
+<translation id="8105797009065549151">ข้อมูลอ้างอิงหมายเหตุ</translation>
+<translation id="811583516810654505">กำลังโหลดคำอธิบาย...</translation>
+<translation id="8117451130807776954">สัปดาห์นี้</translation>
+<translation id="8199524924445686405">ปปปป</translation>
+<translation id="8208673686607688524">เครื่องมือเลือกวันที่และเวลาในท้องถิ่น</translation>
+<translation id="8261464734335370856">มีการสะกดผิด</translation>
+<translation id="8284326494547611709">คำบรรยาย</translation>
+<translation id="8346634859695247203">ส่วน</translation>
+<translation id="835897206747267392">ค่าไม่ถูกต้อง</translation>
+<translation id="8403857369060869934">เวลาที่ผ่านไป: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">ภาค</translation>
+<translation id="8433900881053900389">แถบเครื่องมือ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ไฟล์</translation>
+<translation id="8451268428117625855">โปรดเลือกไฟล์</translation>
+<translation id="8461852803063341183">ปุ่มตัวเลือก</translation>
+<translation id="8474886197722836894">คำอุทิศ</translation>
+<translation id="8531739829932800271">ข้อผิดพลาด</translation>
+<translation id="8534579021159131403">นาที</translation>
+<translation id="8541249477527128034">การควบคุมสื่อ</translation>
+<translation id="8550857728288566671">สัญลักษณ์กราฟิก</translation>
+<translation id="8583702881314752957">รายการคำจำกัดความ</translation>
+<translation id="8597182159515967513">ส่วนหัว</translation>
+<translation id="860475260694818407">สารบัญ</translation>
+<translation id="8613126697340063924">ควบคุมการเล่นระยะไกล</translation>
+<translation id="862370744433916922">คำบรรยาย</translation>
+<translation id="8711688047404765493">เอาต์พุต</translation>
+<translation id="8750798805984357768">โปรดเลือกตัวเลือกอย่างหนึ่งอย่างใดเหล่านี้</translation>
+<translation id="8808573423886751634">บท</translation>
+<translation id="8822203815165896261">ข้อมูลการเขียนโปรแกรม</translation>
+<translation id="8845239796550121995">ตอนนี้กำลังแคสต์ไปยัง TV</translation>
+<translation id="8851136666856101339">หลัก</translation>
+<translation id="8875657656876809964">ข้อผิดพลาดในการเล่นวิดีโอ</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">เดือน</translation>
+<translation id="901493112792887934">เวลาปัจจุบันเป็นวินาที</translation>
+<translation id="901834265349196618">อีเมล</translation>
+<translation id="9048119486235211610">การนำทาง</translation>
+<translation id="9062295712474918030">เอกสาร</translation>
+<translation id="9093215626363556771">ออกจากการแสดงภาพซ้อนภาพ</translation>
+<translation id="9108370397979208512">คณิตศาสตร์</translation>
+<translation id="9132465097189459683">อื่นๆ...</translation>
+<translation id="9138385573473225930">การแจ้งเตือน</translation>
+<translation id="9155987714137265666"><ph name="WEEK" /> เริ่มวันที่ <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">การแสดงภาพซ้อนภาพ</translation>
+<translation id="9168329111483466115">เชิงอรรถ</translation>
+<translation id="954003015749068518">เข้าสู่การแสดงภาพซ้อนภาพ</translation>
+<translation id="966787709310836684">เมนู</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..6ead6891fa2
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_tr.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="tr">
+<translation id="1018939186200882850">menü öğesi</translation>
+<translation id="10623998915015855">geçiş düğmesi</translation>
+<translation id="1088086359088493902">Saniye</translation>
+<translation id="1171774979989969504">Lütfen e-posta adresi girin.</translation>
+<translation id="1178581264944972037">Duraklat</translation>
+<translation id="1188858454923323853">tamamlayıcı</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">kaydırma çubuğu</translation>
+<translation id="1211441953136645838">son not</translation>
+<translation id="1281252709823657822">iletişim kutusu</translation>
+<translation id="1335095011850992622">katkıda bulunanlar</translation>
+<translation id="1342835525016946179">article</translation>
+<translation id="1359897965706325498">banner</translation>
+<translation id="1589122976691792535">bölge</translation>
+<translation id="1591562245178063882">Bu ay</translation>
+<translation id="1637811476055996098">Dosyaları Seç</translation>
+<translation id="1650423536718072820">alıntı</translation>
+<translation id="1727886345390570319">altyazı menüsünü gizle</translation>
+<translation id="1729654308190250600">Lütfen e-posta adresini boş bırakmayın.</translation>
+<translation id="1758486001363313524">Diğer...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">ağaç tablo</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">uzaktan cihazda oynat</translation>
+<translation id="190587075670221089">silme</translation>
+<translation id="1907737156431278478">örnek</translation>
+<translation id="1921819250265091946">gg</translation>
+<translation id="1930711995431081526">durum</translation>
+<translation id="1938124657309484470">Değer <ph name="MAXIMUM_DATE_OR_TIME" /> veya daha geri olmalıdır.</translation>
+<translation id="1946271899482435442">Tarih seçiciyi göster</translation>
+<translation id="1993104285338243655">Yansıtmaya geçildi</translation>
+<translation id="2060505056492490888">"<ph name="DOT" />", "<ph name="INVALIDDOMAIN" />" adı içinde yanlış bir konumda kullanılmış.</translation>
+<translation id="2148716181193084225">Bugün</translation>
+<translation id="2158401438286456825">sayfa listesi</translation>
+<translation id="2226276347425096477">Lütfen bu metni <ph name="MAX_CHARACTERS" /> veya daha az karakter olacak şekilde kısaltın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
+<translation id="2246498165605549352">Yerel Dosya</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hafta, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904"><ph name="NUMBER" />. parça</translation>
+<translation id="2291999235780842123">onay kutusu</translation>
+<translation id="2311842470354187719">sayfa sonu</translation>
+<translation id="2335594187091864976">tarih ve saat seçici</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>
+<translation id="2508569020611168319">sekme listesi</translation>
+<translation id="2561842179657104141">diğer medya kontrollerini göster</translation>
+<translation id="2572483411312390101">oynat</translation>
+<translation id="2613802280814924224">Lütfen geçerli bir değer girin. En yakın geçerli değer şudur: <ph name="VALID_VALUE" /></translation>
+<translation id="2653659639078652383">Gönder</translation>
+<translation id="2657045182931379222">grafik nesnesi</translation>
+<translation id="2674318244760992338">altbilgi</translation>
+<translation id="2709516037105925701">Otomatik doldurma</translation>
+<translation id="2723001399770238859">ses</translation>
+<translation id="2725963129578236554">yorumlar</translation>
+<translation id="2746543609216772311">Değer <ph name="MINIMUM_DATE_OR_TIME" /> veya daha ileri olmalıdır.</translation>
+<translation id="2759744352195237655">pop-up düğmesi</translation>
+<translation id="2761667185364618470">İlerlemek istiyorsanız lütfen bu kutuyu işaretleyin.</translation>
+<translation id="2844350028562914727">ayrıntılar</translation>
+<translation id="2896972712917208084">radyo düğmesi grubu</translation>
+<translation id="2908441821576996758">Lütfen e-posta adreslerinin virgülle ayrılmış listesini girin.</translation>
+<translation id="2940813599313844715">nesne</translation>
+<translation id="3040011195152428237">bağlantı</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Lütfen geçerli bir tarih girin. Alan tam doldurulmamış veya geçersiz bir tarih var.</translation>
+<translation id="3078740164268491126">tablo</translation>
+<translation id="3086746722712840547">note</translation>
+<translation id="310520048233152454">Lütfen bir URL girin.</translation>
+<translation id="3175736971608411871">zamanlayıcı</translation>
+<translation id="3199563858620722075">birleşik kutu</translation>
+<translation id="3450233048674729344">Değer <ph name="MAXIMUM" /> veya daha küçük olmalıdır.</translation>
+<translation id="3486220673238053218">tanım</translation>
+<translation id="3557673793733683882">başlık <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">hafta seçici</translation>
+<translation id="3685101356851116974">Etiketsiz resim</translation>
+<translation id="3706100364254443312">anahtar</translation>
+<translation id="3732799496749320381">aa</translation>
+<translation id="3754210790023674521">Pencere içinde pencere modundan çık</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">terim</translation>
+<translation id="3822383571486410024">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
+<translation id="383465348367842624">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
+<translation id="3846214748874656680">Tam ekran modundan çık</translation>
+<translation id="3889183436948184105">düzeltme</translation>
+<translation id="3920932319529768807">sonuç</translation>
+<translation id="3924558731517983934">uygulama</translation>
+<translation id="3944740393230681990">prolog</translation>
+<translation id="3960700977367013758">kaydırma çubuğu</translation>
+<translation id="4103419683916926126">Milisaniye</translation>
+<translation id="4151657705144244502">grafik</translation>
+<translation id="4160057747563657758">telefon</translation>
+<translation id="4193965531860883258">önsöz</translation>
+<translation id="4201051445878709314">Önceki ayı göster</translation>
+<translation id="421884353938374759">renk seçici</translation>
+<translation id="4248100235867064564">menü çubuğu</translation>
+<translation id="4360991593054037559">Lütfen geçerli bir değer girin. En yakın iki geçerli değer şunlardır: <ph name="VALID_VALUE_LOW" /> ve <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Soru-Cevap</translation>
+<translation id="4413860115965805769">menü düğmesi</translation>
+<translation id="4444765639179266822">Şöyle diyor olabilir: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">terimler sözlüğü referansı</translation>
+<translation id="4522570452068850558">Ayrıntılar</translation>
+<translation id="4542388879936266156">kalan süre: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
+<translation id="4668956016107839909">ek</translation>
+<translation id="4718048029184481307">Pencere içinde pencere modunda oynatılıyor</translation>
+<translation id="4742539557769756338">kapak</translation>
+<translation id="4748357248530471599">ekran kesimi alanını tam ekran olarak değiştirin</translation>
+<translation id="4757246831282535685">sekme paneli</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">ara</translation>
+<translation id="4812940957355064477">Lütfen bir sayı girin.</translation>
+<translation id="4912536737030637138">kaynakça girişi</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> öğe seçildi</translation>
+<translation id="4992066212339426712">Sesi aç</translation>
+<translation id="49969490063480558">Lütfen "<ph name="ATSIGN" />" işaretinden sonra gelen kısmı ekleyin. "<ph name="INVALIDADDRESS" />", tam bir adres değil.</translation>
+<translation id="5034860022980953847">ilerleme durumu göstergesi</translation>
+<translation id="5090250355906949916">video süresi göstergesi</translation>
+<translation id="5093189678851173835">yazıt</translation>
+<translation id="5117590920725113268">Sonraki ayı göster</translation>
+<translation id="512758898067543763">satır başlığı</translation>
+<translation id="5143125788380636750">son söz</translation>
+<translation id="5164977714490026579">Değer <ph name="MINIMUM" /> veya daha büyük olmalıdır.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Lütfen başına "<ph name="ATSIGN" />" ekleyin. "<ph name="INVALIDADDRESS" />" adresi eksik.</translation>
+<translation id="5334352251556557839">Medya oynatılamıyor.</translation>
+<translation id="5406322316791861025">figür</translation>
+<translation id="5453733299334684579">ağaç öğesi</translation>
+<translation id="5466621249238537318">Lütfen bir veya daha fazla dosya seçin.</translation>
+<translation id="5468998798572797635">tam ekrandan çık</translation>
+<translation id="5516424706154626233">tarih seçici</translation>
+<translation id="5537725057119320332">Yayınla</translation>
+<translation id="5546461542133609677">sesi aç</translation>
+<translation id="5608153257855394627">vurgula</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">10 sn. atlamak için sola veya sağa iki kez dokunun</translation>
+<translation id="5631759159893697722">özet</translation>
+<translation id="5643186887447432888">düğme</translation>
+<translation id="5677946354068040947">diğer seçenekler</translation>
+<translation id="576709008726043716">giriş</translation>
+<translation id="57838592816432529">Sesi kapat</translation>
+<translation id="5860033963881614850">Kapalı</translation>
+<translation id="588258955323874662">Tam ekran</translation>
+<translation id="5888666972993069672">Şimdi <ph name="DEVICE_FRIENDLY_NAME" /> adlı cihaza yayınlanıyor</translation>
+<translation id="591047860372322273">arama kutusu</translation>
+<translation id="5939518447894949180">Sıfırla</translation>
+<translation id="5966707198760109579">Hafta</translation>
+<translation id="5987525920412732405">dönme düğmesi</translation>
+<translation id="6011459053400940133">ses kaydırma çubuğu</translation>
+<translation id="6015796118275082299">Yıl</translation>
+<translation id="6023896073578205740">liste kutusu</translation>
+<translation id="6150588977291308318">kaynakça</translation>
+<translation id="6164829606128959761">ölçüm aracı</translation>
+<translation id="6166809985690652833">sonsöz</translation>
+<translation id="6209276755895393898">Resimdeki şu olabilir: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">terimler sözlüğü</translation>
+<translation id="6281763101136022427">URL</translation>
+<translation id="6310801910862476708">Pencere İçinde Pencereden Çık</translation>
+<translation id="6398862346408813489">Ay seçim panelini göster</translation>
+<translation id="6404546809543547843">ses zaman çizelgesi temizleyici</translation>
+<translation id="6443871981718447451">altyazı menüsünü göster</translation>
+<translation id="6453774872122745852">teşekkür</translation>
+<translation id="6475115390776617481">aktif ortak çalışan</translation>
+<translation id="648732519525291180">zaman seçici</translation>
+<translation id="6550675742724504774">Seçenekler</translation>
+<translation id="6572309429103589720">Geçersiz dil bilgisi</translation>
+<translation id="658823671542763450">tam ekrana geç</translation>
+<translation id="663493177488814956">kartlar</translation>
+<translation id="6637586476836377253">log</translation>
+<translation id="6643016212128521049">Temizle</translation>
+<translation id="668171684555832681">Diğer...</translation>
+<translation id="6692633176391053278">stepper (adımlayıcı)</translation>
+<translation id="6709570249143506788">Oynatma kalitesi kötü</translation>
+<translation id="6755330956360078551">ipucu</translation>
+<translation id="6790428901817661496">Oynat</translation>
+<translation id="6820355525329141109">Eklenti yüklenemedi.</translation>
+<translation id="6820615603175220800">kaynakça referansı</translation>
+<translation id="6843725295806269523">sesi kapat</translation>
+<translation id="6885760532393684712">dizin</translation>
+<translation id="689129560213475294">künye</translation>
+<translation id="6934078000481955284">blok alıntı</translation>
+<translation id="693476918119313863">üst bilgi</translation>
+<translation id="6941933287844615239">medyayı indir</translation>
+<translation id="6981594929165378967">ekleme</translation>
+<translation id="6989848892321993519">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda 1 karakter kullanıyorsunuz).</translation>
+<translation id="7034405885550056553">öneri</translation>
+<translation id="709897737746224366">Lütfen istenen biçimi eşleştirin.</translation>
+<translation id="7118469954320184356">Açıklama yok.</translation>
+<translation id="7139483182332611405">önsöz</translation>
+<translation id="7214187073215825913">içerik bilgisi</translation>
+<translation id="7263440858009898357">Lütfen listeden bir öğe seçin.</translation>
+<translation id="727747134524199931">sütun başlığı</translation>
+<translation id="7320576522385648310">arabelleğe alınıyor</translation>
+<translation id="7353453495576941748">katkıda bulunan</translation>
+<translation id="7364796246159120393">Dosya Seç</translation>
+<translation id="739024184232394898">Diğer...</translation>
+<translation id="7405738980073107433">son notlar</translation>
+<translation id="7410239719251593705">Yetişkinlere uygun içerik barındırdığı anlaşılıyor. Açıklama yok.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">İndir</translation>
+<translation id="7529102961911894712">geri bağlantı</translation>
+<translation id="7533959249147584474">Etiketlenmemiş grafik</translation>
+<translation id="7647456547678091388">ipucu</translation>
+<translation id="7661956066982048809">grafik dokümanı</translation>
+<translation id="7673697353781729403">Saat</translation>
+<translation id="7681220483256441252">dizin</translation>
+<translation id="7740050170769002709">HTML içeriği</translation>
+<translation id="7745230546936012372">Eksik resim açıklamalarını almak için içerik menüsünü açın.</translation>
+<translation id="7750228210027921155">Pencere içinde pencere</translation>
+<translation id="775297008183122718">Geçersiz giriş</translation>
+<translation id="7789962463072032349">duraklat</translation>
+<translation id="7802800022689234070">açıklama üçgeni</translation>
+<translation id="7888071071722539607">Lütfen e-posta adresine bir "<ph name="ATSIGN" />" işareti ekleyin. "<ph name="INVALIDADDRESS" />" adresinde "<ph name="ATSIGN" />" eksik.</translation>
+<translation id="7891486169920085145">ayırıcı</translation>
+<translation id="795667975304826397">Dosya seçilmedi</translation>
+<translation id="8053789581856978548">arama metni alanı</translation>
+<translation id="8057695513531652401">bildirim</translation>
+<translation id="8105797009065549151">not referansı</translation>
+<translation id="811583516810654505">Açıklama alınıyor...</translation>
+<translation id="8117451130807776954">Bu hafta</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">yerel tarih ve zaman seçici</translation>
+<translation id="8261464734335370856">Geçersiz yazım</translation>
+<translation id="8284326494547611709">Altyazılar</translation>
+<translation id="8346634859695247203">bölüm</translation>
+<translation id="835897206747267392">Geçersiz değer.</translation>
+<translation id="8403857369060869934">geçen süre: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">bölüm</translation>
+<translation id="8433900881053900389">araç çubuğu</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> dosya</translation>
+<translation id="8451268428117625855">Lütfen bir dosya seçin.</translation>
+<translation id="8461852803063341183">radyo düğmesi</translation>
+<translation id="8474886197722836894">ithaf</translation>
+<translation id="8531739829932800271">yazım hataları</translation>
+<translation id="8534579021159131403">Dakika</translation>
+<translation id="8541249477527128034">medya kontrolü</translation>
+<translation id="8550857728288566671">grafik sembolü</translation>
+<translation id="8583702881314752957">tanım listesi</translation>
+<translation id="8597182159515967513">başlık</translation>
+<translation id="860475260694818407">içindekiler</translation>
+<translation id="8613126697340063924">uzaktan oynatmayı kontrol et</translation>
+<translation id="862370744433916922">alt başlık</translation>
+<translation id="8711688047404765493">çıkış</translation>
+<translation id="8750798805984357768">Lütfen bu seçeneklerden birini belirleyin.</translation>
+<translation id="8808573423886751634">bölüm</translation>
+<translation id="8822203815165896261">yazma bilgileri</translation>
+<translation id="8845239796550121995">Şimdi TV'nize yayınlanıyor</translation>
+<translation id="8851136666856101339">main</translation>
+<translation id="8875657656876809964">Video oynatma hatası</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Ay</translation>
+<translation id="901493112792887934">saniye olarak geçerli süre</translation>
+<translation id="901834265349196618">e-posta</translation>
+<translation id="9048119486235211610">gezinme</translation>
+<translation id="9062295712474918030">doküman</translation>
+<translation id="9093215626363556771">pencere içinde pencere modundan çıkın</translation>
+<translation id="9108370397979208512">math</translation>
+<translation id="9132465097189459683">Diğer...</translation>
+<translation id="9138385573473225930">uyarı</translation>
+<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> tarihinde başlayan <ph name="WEEK" /></translation>
+<translation id="916607977885256133">Pencere içinde Pencere</translation>
+<translation id="9168329111483466115">dipnot</translation>
+<translation id="954003015749068518">pencere içinde pencere moduna gir</translation>
+<translation id="966787709310836684">menü</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..76191ac49b2
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_uk.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="uk">
+<translation id="1018939186200882850">пункт меню</translation>
+<translation id="10623998915015855">перемикач</translation>
+<translation id="1088086359088493902">Секунди</translation>
+<translation id="1171774979989969504">Введіть електронну адресу.</translation>
+<translation id="1178581264944972037">Пауза</translation>
+<translation id="1188858454923323853">додатково</translation>
+<translation id="1206619573307042055">область виділення</translation>
+<translation id="1206693055195146388">повзунок</translation>
+<translation id="1211441953136645838">кінцева виноска</translation>
+<translation id="1281252709823657822">діалогове вікно</translation>
+<translation id="1335095011850992622">подяки</translation>
+<translation id="1342835525016946179">стаття</translation>
+<translation id="1359897965706325498">банер</translation>
+<translation id="1589122976691792535">регіон</translation>
+<translation id="1591562245178063882">Цей місяць</translation>
+<translation id="1637811476055996098">Вибрати файли</translation>
+<translation id="1650423536718072820">цитата</translation>
+<translation id="1727886345390570319">сховати меню субтитрів</translation>
+<translation id="1729654308190250600">Введіть електронну адресу.</translation>
+<translation id="1758486001363313524">Інші...</translation>
+<translation id="1806710327868736751">вікно сповіщення</translation>
+<translation id="1821985195704844674">сітка дерева</translation>
+<translation id="1822429046913737220">д.п./п.п.</translation>
+<translation id="1832974991323546415">відтворити на віддаленому пристрої</translation>
+<translation id="190587075670221089">видалення</translation>
+<translation id="1907737156431278478">приклад</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="1938124657309484470">Має бути <ph name="MAXIMUM_DATE_OR_TIME" /> або раніша дата.</translation>
+<translation id="1946271899482435442">Показує засіб вибору дати</translation>
+<translation id="1993104285338243655">Змінено на дзеркалювання</translation>
+<translation id="2060505056492490888">Символ "<ph name="DOT" />" у "<ph name="INVALIDDOMAIN" />" використано неправильно.</translation>
+<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="2247351761944213033">Тиждень <ph name="WEEKNUMBER" />, <ph name="YEAR" /> р.</translation>
+<translation id="2277199496770840904">Композиція <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">прапорець</translation>
+<translation id="2311842470354187719">розрив сторінки</translation>
+<translation id="2335594187091864976">засіб вибору дати й часу</translation>
+<translation id="245932805758469625">кількість секунд до кінця відео</translation>
+<translation id="248395913932153421">День</translation>
+<translation id="2507943997699731163">Заповніть це поле.</translation>
+<translation id="2508569020611168319">cписок вкладок</translation>
+<translation id="2561842179657104141">показати більше елементів керування мультимедійним вмістом</translation>
+<translation id="2572483411312390101">відтворити</translation>
+<translation id="2613802280814924224">Введіть дійсне значення. Найближче дійсне значення: <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Надіслати</translation>
+<translation id="2657045182931379222">графічний об’єкт</translation>
+<translation id="2674318244760992338">нижній колонтитул</translation>
+<translation id="2709516037105925701">Автозаповнення</translation>
+<translation id="2723001399770238859">аудіо</translation>
+<translation id="2725963129578236554">коментарі</translation>
+<translation id="2746543609216772311">Має бути <ph name="MINIMUM_DATE_OR_TIME" /> або пізніша дата.</translation>
+<translation id="2759744352195237655">кнопка спливаючої підказки</translation>
+<translation id="2761667185364618470">Поставте тут прапорець, якщо хочете продовжити.</translation>
+<translation id="2844350028562914727">деталі</translation>
+<translation id="2896972712917208084">група перемикачів</translation>
+<translation id="2908441821576996758">Введіть список електронних адрес, розділених комою.</translation>
+<translation id="2940813599313844715">об’єкт</translation>
+<translation id="3040011195152428237">посилання</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> МБ</translation>
+<translation id="3075154866155599887">Введіть дійсне значення. Поле не заповнено або введено недійсну дату.</translation>
+<translation id="3078740164268491126">таблиця</translation>
+<translation id="3086746722712840547">примітка</translation>
+<translation id="310520048233152454">Введіть URL-адресу.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">поле зі списком</translation>
+<translation id="3450233048674729344">Значення має бути меншим або дорівнювати <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">визначення</translation>
+<translation id="3557673793733683882">заголовок <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">засіб вибору тижня</translation>
+<translation id="3685101356851116974">Зображення без мітки</translation>
+<translation id="3706100364254443312">перемикач</translation>
+<translation id="3732799496749320381">мм</translation>
+<translation id="3754210790023674521">Вийти з режиму "Картинка в картинці"</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> ГБ</translation>
+<translation id="3808586225841795776">термін</translation>
+<translation id="3822383571486410024">У тексті має бути на менше <ph name="MIN_CHARACTERS" /> символів (ви ввели <ph name="CURRENT_LENGTH" /> символів).</translation>
+<translation id="383465348367842624">Частина перед знаком "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3846214748874656680">Вийти з повноекранного режиму</translation>
+<translation id="3889183436948184105">редакція</translation>
+<translation id="3920932319529768807">висновок</translation>
+<translation id="3924558731517983934">додаток</translation>
+<translation id="3944740393230681990">пролог</translation>
+<translation id="3960700977367013758">смуга прокрутки</translation>
+<translation id="4103419683916926126">Мілісекунди</translation>
+<translation id="4151657705144244502">зображення</translation>
+<translation id="4160057747563657758">номер телефону</translation>
+<translation id="4193965531860883258">передмова</translation>
+<translation id="4201051445878709314">Показати попередній місяць</translation>
+<translation id="421884353938374759">вибір кольору</translation>
+<translation id="4248100235867064564">панель меню</translation>
+<translation id="4360991593054037559">Введіть дійсне значення. Два найближчі дійсні значення: <ph name="VALID_VALUE_LOW" /> і <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Запитання</translation>
+<translation id="4413860115965805769">кнопка меню</translation>
+<translation id="4444765639179266822">Схоже, на зображенні написано "<ph name="OCR_TEXT" />"</translation>
+<translation id="4446524499724042288">посилання на глосарій</translation>
+<translation id="4522570452068850558">Деталі</translation>
+<translation id="4542388879936266156">залишилося часу: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">форма</translation>
+<translation id="4661075872484491155">дерево</translation>
+<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4668956016107839909">додаток</translation>
+<translation id="4718048029184481307">Відтворюється в режимі "Картинка в картинці"</translation>
+<translation id="4742539557769756338">обкладинка</translation>
+<translation id="4748357248530471599">перемкнути виріз у повноекранному режимі</translation>
+<translation id="4757246831282535685">панель вкладок</translation>
+<translation id="4763480195061959176">відео</translation>
+<translation id="479989351350248267">пошук</translation>
+<translation id="4812940957355064477">Введіть число.</translation>
+<translation id="4912536737030637138">бібліографічний запис</translation>
+<translation id="4975562563186953947">Вибрано <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Увімкнути звук</translation>
+<translation id="49969490063480558">Введіть частину електронної адреси після знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
+<translation id="5034860022980953847">індикатор перебігу</translation>
+<translation id="5090250355906949916">повзунок часу відтворення відео</translation>
+<translation id="5093189678851173835">епіграф</translation>
+<translation id="5117590920725113268">Показати наступний місяць</translation>
+<translation id="512758898067543763">заголовок рядка</translation>
+<translation id="5143125788380636750">епілог</translation>
+<translation id="5164977714490026579">Значення має бути більшим або дорівнювати <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> Пб</translation>
+<translation id="5307600278924710095">Введіть частину електронної адреси до знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
+<translation id="5334352251556557839">Не вдалося відтворити медіавміст.</translation>
+<translation id="5406322316791861025">фігура</translation>
+<translation id="5453733299334684579">елемент дерева</translation>
+<translation id="5466621249238537318">Виберіть один або декілька файлів.</translation>
+<translation id="5468998798572797635">вийти з повноекранного режиму</translation>
+<translation id="5516424706154626233">засіб вибору дати</translation>
+<translation id="5537725057119320332">Трансляція екрана</translation>
+<translation id="5546461542133609677">увімкнути звук</translation>
+<translation id="5608153257855394627">виділити</translation>
+<translation id="561939826962581046">час</translation>
+<translation id="5630795885300617244">Двічі торкніться ліворуч або праворуч, щоб пропустити 10 с</translation>
+<translation id="5631759159893697722">автореферат</translation>
+<translation id="5643186887447432888">кнопка</translation>
+<translation id="5677946354068040947">більше опцій</translation>
+<translation id="576709008726043716">вступ</translation>
+<translation id="57838592816432529">Вимкнути звук</translation>
+<translation id="5860033963881614850">Вимк.</translation>
+<translation id="588258955323874662">Повноекранний режим</translation>
+<translation id="5888666972993069672">Транслюється на пристрій <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">вікно пошуку</translation>
+<translation id="5939518447894949180">Скинути</translation>
+<translation id="5966707198760109579">Тиждень</translation>
+<translation id="5987525920412732405">лічильник</translation>
+<translation id="6011459053400940133">повзунок гучності</translation>
+<translation id="6015796118275082299">Рік</translation>
+<translation id="6023896073578205740">вікно списку</translation>
+<translation id="6150588977291308318">бібліографія</translation>
+<translation id="6164829606128959761">вимірювач</translation>
+<translation id="6166809985690652833">післямова</translation>
+<translation id="6209276755895393898">Схоже, на цьому зображенні <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">глосарій</translation>
+<translation id="6281763101136022427">URL-адреса</translation>
+<translation id="6310801910862476708">Вийти з режиму "Картинка в картинці"</translation>
+<translation id="6398862346408813489">Показати панель вибору місяців</translation>
+<translation id="6404546809543547843">повзунок часу відтворення аудіо</translation>
+<translation id="6443871981718447451">показати меню субтитрів</translation>
+<translation id="6453774872122745852">слова подяки</translation>
+<translation id="6475115390776617481">дані про присутність у реальному часі</translation>
+<translation id="648732519525291180">засіб вибору часу</translation>
+<translation id="6550675742724504774">Параметри</translation>
+<translation id="6572309429103589720">Граматична помилка</translation>
+<translation id="658823671542763450">увійти в повноекранний режим</translation>
+<translation id="663493177488814956">стрічка</translation>
+<translation id="6637586476836377253">журнал</translation>
+<translation id="6643016212128521049">Очистити</translation>
+<translation id="668171684555832681">Інший...</translation>
+<translation id="6692633176391053278">повторювач stepper</translation>
+<translation id="6709570249143506788">Низька якість відтворення</translation>
+<translation id="6755330956360078551">підказка</translation>
+<translation id="6790428901817661496">Відтворити</translation>
+<translation id="6820355525329141109">Не вдалося завантажити плагін.</translation>
+<translation id="6820615603175220800">посилання на бібліографію</translation>
+<translation id="6843725295806269523">вимкнути звук</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="689129560213475294">емблема видавництва</translation>
+<translation id="6934078000481955284">цитата</translation>
+<translation id="693476918119313863">заголовок</translation>
+<translation id="6941933287844615239">завантажити медіафайл</translation>
+<translation id="6981594929165378967">вставлення</translation>
+<translation id="6989848892321993519">У тексті має бути не менше стількох символів: <ph name="MIN_CHARACTERS" />. Наразі ви ввели 1 символ.</translation>
+<translation id="7034405885550056553">пропозиція</translation>
+<translation id="709897737746224366">Виберіть потрібний формат.</translation>
+<translation id="7118469954320184356">Немає опису.</translation>
+<translation id="7139483182332611405">передмова</translation>
+<translation id="7214187073215825913">інформація про контент</translation>
+<translation id="7263440858009898357">Виберіть елемент зі списку.</translation>
+<translation id="727747134524199931">заголовок стовпця</translation>
+<translation id="7320576522385648310">буферизація</translation>
+<translation id="7353453495576941748">подяка</translation>
+<translation id="7364796246159120393">Вибрати файл</translation>
+<translation id="739024184232394898">Інші...</translation>
+<translation id="7405738980073107433">кінцеві виноски</translation>
+<translation id="7410239719251593705">Схоже, це вміст для дорослих. Немає опису.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> ТБ</translation>
+<translation id="7491962110804786152">вкладка</translation>
+<translation id="7514365320538308">Завантажити</translation>
+<translation id="7529102961911894712">зворотне посилання</translation>
+<translation id="7533959249147584474">Графічний об’єкт без мітки</translation>
+<translation id="7647456547678091388">порада</translation>
+<translation id="7661956066982048809">графічний документ</translation>
+<translation id="7673697353781729403">Години</translation>
+<translation id="7681220483256441252">покажчик</translation>
+<translation id="7740050170769002709">Вміст HTML</translation>
+<translation id="7745230546936012372">Щоб відсутні описи зображення з’явилися, відкрийте контекстне меню.</translation>
+<translation id="7750228210027921155">Картинка в картинці</translation>
+<translation id="775297008183122718">Недійсне введене значення</translation>
+<translation id="7789962463072032349">призупинити</translation>
+<translation id="7802800022689234070">трикутник відкривання</translation>
+<translation id="7888071071722539607">Електронна адреса має містити знак "<ph name="ATSIGN" />". В електронній адресі "<ph name="INVALIDADDRESS" />" знака "<ph name="ATSIGN" />" немає.</translation>
+<translation id="7891486169920085145">розділювач</translation>
+<translation id="795667975304826397">Файл не вибрано</translation>
+<translation id="8053789581856978548">текстове поле пошуку</translation>
+<translation id="8057695513531652401">примітка</translation>
+<translation id="8105797009065549151">посилання на примітку</translation>
+<translation id="811583516810654505">Завантажується опис…</translation>
+<translation id="8117451130807776954">Цей тиждень</translation>
+<translation id="8199524924445686405">рррр</translation>
+<translation id="8208673686607688524">засіб вибору місцевих дати й часу</translation>
+<translation id="8261464734335370856">Орфографічна помилка</translation>
+<translation id="8284326494547611709">Субтитри</translation>
+<translation id="8346634859695247203">розділ</translation>
+<translation id="835897206747267392">Недійсне значення</translation>
+<translation id="8403857369060869934">минуло часу: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">частина</translation>
+<translation id="8433900881053900389">панель інструментів</translation>
+<translation id="8444882422881193423">файлів: <ph name="NUMBER_OF_FILES" /></translation>
+<translation id="8451268428117625855">Виберіть файл.</translation>
+<translation id="8461852803063341183">перемикач</translation>
+<translation id="8474886197722836894">присвята</translation>
+<translation id="8531739829932800271">перелік описок</translation>
+<translation id="8534579021159131403">Хвилини</translation>
+<translation id="8541249477527128034">елемент керування мультимедіа</translation>
+<translation id="8550857728288566671">графічний символ</translation>
+<translation id="8583702881314752957">список визначень</translation>
+<translation id="8597182159515967513">заголовок</translation>
+<translation id="860475260694818407">зміст</translation>
+<translation id="8613126697340063924">керувати віддаленим відтворенням</translation>
+<translation id="862370744433916922">підзаголовок</translation>
+<translation id="8711688047404765493">вихід</translation>
+<translation id="8750798805984357768">Виберіть один із запропонованих варіантів.</translation>
+<translation id="8808573423886751634">розділ</translation>
+<translation id="8822203815165896261">інформація про автора</translation>
+<translation id="8845239796550121995">Транслюється на телевізор</translation>
+<translation id="8851136666856101339">головний</translation>
+<translation id="8875657656876809964">Помилка відтворення відео</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> КБ</translation>
+<translation id="8987927404178983737">Місяць</translation>
+<translation id="901493112792887934">поточний час у секундах</translation>
+<translation id="901834265349196618">електронна адреса</translation>
+<translation id="9048119486235211610">навігація</translation>
+<translation id="9062295712474918030">документ</translation>
+<translation id="9093215626363556771">вийти з режиму "Картинка в картинці"</translation>
+<translation id="9108370397979208512">математика</translation>
+<translation id="9132465097189459683">Інші...</translation>
+<translation id="9138385573473225930">сповіщення</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, починається <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Картинка в картинці</translation>
+<translation id="9168329111483466115">виноска</translation>
+<translation id="954003015749068518">увімкнути режим "Картинка в картинці"</translation>
+<translation id="966787709310836684">меню</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..87e7948c55c
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_vi.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="vi">
+<translation id="1018939186200882850">mục menu</translation>
+<translation id="10623998915015855">nút chuyển đổi</translation>
+<translation id="1088086359088493902">Giây</translation>
+<translation id="1171774979989969504">Vui lòng nhập địa chỉ email.</translation>
+<translation id="1178581264944972037">Tạm dừng</translation>
+<translation id="1188858454923323853">bổ sung</translation>
+<translation id="1206619573307042055">bảng chữ chạy</translation>
+<translation id="1206693055195146388">thanh trượt</translation>
+<translation id="1211441953136645838">chú thích cuối</translation>
+<translation id="1281252709823657822">hộp thoại</translation>
+<translation id="1335095011850992622">ghi nhận tác giả</translation>
+<translation id="1342835525016946179">bài viết</translation>
+<translation id="1359897965706325498">biểu ngữ</translation>
+<translation id="1589122976691792535">khu vực</translation>
+<translation id="1591562245178063882">Tháng này</translation>
+<translation id="1637811476055996098">Chọn tệp</translation>
+<translation id="1650423536718072820">đoạn trích dẫn</translation>
+<translation id="1727886345390570319">ẩn menu phụ đề chi tiết</translation>
+<translation id="1729654308190250600">Vui lòng nhập địa chỉ email không trống.</translation>
+<translation id="1758486001363313524">Khác...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">lưới dạng cây</translation>
+<translation id="1822429046913737220">SA/CH</translation>
+<translation id="1832974991323546415">phát trên thiết bị từ xa</translation>
+<translation id="190587075670221089">xóa</translation>
+<translation id="1907737156431278478">ví dụ</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="1930711995431081526">trạng thái</translation>
+<translation id="1938124657309484470">Giá trị phải là <ph name="MAXIMUM_DATE_OR_TIME" /> hoặc sớm hơn.</translation>
+<translation id="1946271899482435442">Hiển thị bộ chọn ngày</translation>
+<translation id="1993104285338243655">Đã chuyển sang chế độ phản chiếu</translation>
+<translation id="2060505056492490888">'<ph name="DOT" />' bị sử dụng sai vị trí trong '<ph name="INVALIDDOMAIN" />'.</translation>
+<translation id="2148716181193084225">Hôm nay</translation>
+<translation id="2158401438286456825">danh sách trang</translation>
+<translation id="2226276347425096477">Hãy cắt ngắn văn bản này thành <ph name="MAX_CHARACTERS" /> ký tự hoặc ít hơn (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
+<translation id="2246498165605549352">Tệp trên máy</translation>
+<translation id="2247351761944213033">Tuần <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
+<translation id="2277199496770840904">Bản nhạc <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">hộp kiểm</translation>
+<translation id="2311842470354187719">ngắt trang</translation>
+<translation id="2335594187091864976">bộ chọn ngày và giờ</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>
+<translation id="2508569020611168319">danh sách tab</translation>
+<translation id="2561842179657104141">hiển thị các kiểm soát phương tiện khác</translation>
+<translation id="2572483411312390101">phát</translation>
+<translation id="2613802280814924224">Vui lòng nhập giá trị hợp lệ. Giá trị hợp lệ gần nhất là <ph name="VALID_VALUE" />.</translation>
+<translation id="2653659639078652383">Gửi</translation>
+<translation id="2657045182931379222">đối tượng đồ họa</translation>
+<translation id="2674318244760992338">chân trang</translation>
+<translation id="2709516037105925701">Tự động điền</translation>
+<translation id="2723001399770238859">âm thanh</translation>
+<translation id="2725963129578236554">nhận xét</translation>
+<translation id="2746543609216772311">Giá trị phải là <ph name="MINIMUM_DATE_OR_TIME" /> hoặc muộn hơn.</translation>
+<translation id="2759744352195237655">nút cửa sổ bật lên</translation>
+<translation id="2761667185364618470">Vui lòng chọn hộp kiểm này nếu bạn muốn tiếp tục.</translation>
+<translation id="2844350028562914727">chi tiết</translation>
+<translation id="2896972712917208084">nhóm radio</translation>
+<translation id="2908441821576996758">Vui lòng nhập danh sách địa chỉ email được phân cách bằng dấu phẩy.</translation>
+<translation id="2940813599313844715">đối tượng</translation>
+<translation id="3040011195152428237">liên kết</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">Vui lòng nhập một giá trị hợp lệ. Trường không hoàn chỉnh hoặc có giá trị không hợp lệ.</translation>
+<translation id="3078740164268491126">bảng</translation>
+<translation id="3086746722712840547">ghi chú</translation>
+<translation id="310520048233152454">Vui lòng nhập URL.</translation>
+<translation id="3175736971608411871">bộ tính giờ</translation>
+<translation id="3199563858620722075">hộp kết hợp</translation>
+<translation id="3450233048674729344">Giá trị phải nhỏ hơn hoặc bằng <ph name="MAXIMUM" />.</translation>
+<translation id="3486220673238053218">định nghĩa</translation>
+<translation id="3557673793733683882">tiêu đề <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">bộ chọn tuần</translation>
+<translation id="3685101356851116974">Hình ảnh không có nhãn</translation>
+<translation id="3706100364254443312">chuyển</translation>
+<translation id="3732799496749320381">mm</translation>
+<translation id="3754210790023674521">Thoát chế độ hình trong hình</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">cụm từ</translation>
+<translation id="3822383571486410024">Hãy kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
+<translation id="383465348367842624">Phần đứng trước '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3846214748874656680">Thoát chế độ toàn màn hình</translation>
+<translation id="3889183436948184105">bản sửa đổi</translation>
+<translation id="3920932319529768807">kết luận</translation>
+<translation id="3924558731517983934">ứng dụng</translation>
+<translation id="3944740393230681990">phần mở đầu</translation>
+<translation id="3960700977367013758">thanh cuộn</translation>
+<translation id="4103419683916926126">Mili giây</translation>
+<translation id="4151657705144244502">hình ảnh</translation>
+<translation id="4160057747563657758">điện thoại</translation>
+<translation id="4193965531860883258">lời tựa</translation>
+<translation id="4201051445878709314">Hiển thị tháng trước</translation>
+<translation id="421884353938374759">công cụ chọn màu</translation>
+<translation id="4248100235867064564">thanh menu</translation>
+<translation id="4360991593054037559">Vui lòng nhập giá trị hợp lệ. Hai giá trị hợp lệ gần nhất là <ph name="VALID_VALUE_LOW" /> và <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4384583879834880242">Giải đáp</translation>
+<translation id="4413860115965805769">nút menu</translation>
+<translation id="4444765639179266822">Có vẻ như nội dung là: <ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">tham chiếu bảng thuật ngữ</translation>
+<translation id="4522570452068850558">Chi tiết</translation>
+<translation id="4542388879936266156">thời gian còn lại: <ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">biểu mẫu</translation>
+<translation id="4661075872484491155">cây</translation>
+<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4668956016107839909">phụ lục</translation>
+<translation id="4718048029184481307">Đang phát ở chế độ hình trong hình</translation>
+<translation id="4742539557769756338">trang bìa</translation>
+<translation id="4748357248530471599">bật/tắt chế độ toàn màn hình có vết cắt</translation>
+<translation id="4757246831282535685">bảng điều khiển tab</translation>
+<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">Vui lòng nhập một số.</translation>
+<translation id="4912536737030637138">mục nhập danh mục</translation>
+<translation id="4975562563186953947">Đã chọn <ph name="SELECTED_COUNT" /></translation>
+<translation id="4992066212339426712">Bật âm thanh</translation>
+<translation id="49969490063480558">Vui lòng nhập phần đứng sau '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
+<translation id="5034860022980953847">chỉ báo tiến trình</translation>
+<translation id="5090250355906949916">thanh trượt thời gian trên video</translation>
+<translation id="5093189678851173835">lời đề từ</translation>
+<translation id="5117590920725113268">Hiển thị tháng tiếp theo</translation>
+<translation id="512758898067543763">tiêu đề hàng</translation>
+<translation id="5143125788380636750">lời kết</translation>
+<translation id="5164977714490026579">Giá trị phải lớn hơn hoặc bằng <ph name="MINIMUM" />.</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">Vui lòng nhập phần đứng trước '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
+<translation id="5334352251556557839">Không thể phát nội dung đa phương tiện.</translation>
+<translation id="5406322316791861025">hình dáng</translation>
+<translation id="5453733299334684579">mục dạng cây</translation>
+<translation id="5466621249238537318">Vui lòng chọn một hoặc nhiều tệp.</translation>
+<translation id="5468998798572797635">thoát khỏi chế độ toàn màn hình</translation>
+<translation id="5516424706154626233">bộ chọn ngày</translation>
+<translation id="5537725057119320332">Truyền</translation>
+<translation id="5546461542133609677">bật tiếng</translation>
+<translation id="5608153257855394627">nội dung nổi bật</translation>
+<translation id="561939826962581046">thời gian</translation>
+<translation id="5630795885300617244">Nhấn đúp vào bên trái hoặc phải để bỏ qua sau 10 giây</translation>
+<translation id="5631759159893697722">bản tóm tắt</translation>
+<translation id="5643186887447432888">nút</translation>
+<translation id="5677946354068040947">tùy chọn khác</translation>
+<translation id="576709008726043716">giới thiệu</translation>
+<translation id="57838592816432529">Tắt tiếng</translation>
+<translation id="5860033963881614850">Tắt</translation>
+<translation id="588258955323874662">Toàn màn hình</translation>
+<translation id="5888666972993069672">Hiện đang truyền tới <ph name="DEVICE_FRIENDLY_NAME" /></translation>
+<translation id="591047860372322273">hộp tìm kiếm</translation>
+<translation id="5939518447894949180">Đặt lại</translation>
+<translation id="5966707198760109579">Tuần</translation>
+<translation id="5987525920412732405">nút quay tròn</translation>
+<translation id="6011459053400940133">thanh trượt âm lượng</translation>
+<translation id="6015796118275082299">Năm</translation>
+<translation id="6023896073578205740">hộp danh sách</translation>
+<translation id="6150588977291308318">danh mục</translation>
+<translation id="6164829606128959761">thước đo</translation>
+<translation id="6166809985690652833">lời bạt</translation>
+<translation id="6209276755895393898">Có vẻ như là: <ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">bảng thuật ngữ</translation>
+<translation id="6281763101136022427">url</translation>
+<translation id="6310801910862476708">Thoát chế độ hình trong hình</translation>
+<translation id="6398862346408813489">Hiển thị bảng lựa chọn tháng</translation>
+<translation id="6404546809543547843">trình kiểm soát thời gian âm thanh</translation>
+<translation id="6443871981718447451">hiển thị menu phụ đề chi tiết</translation>
+<translation id="6453774872122745852">lời cảm ơn</translation>
+<translation id="6475115390776617481">cộng tác viên đang hiện diện</translation>
+<translation id="648732519525291180">bộ chọn giờ</translation>
+<translation id="6550675742724504774">Tùy chọn</translation>
+<translation id="6572309429103589720">Ngữ pháp không hợp lệ</translation>
+<translation id="658823671542763450">vào chế độ toàn màn hình</translation>
+<translation id="663493177488814956">nguồn cấp dữ liệu</translation>
+<translation id="6637586476836377253">nhật ký</translation>
+<translation id="6643016212128521049">Xóa</translation>
+<translation id="668171684555832681">Khác...</translation>
+<translation id="6692633176391053278">điều khiển tăng/giảm</translation>
+<translation id="6709570249143506788">Chất lượng phát lại kém</translation>
+<translation id="6755330956360078551">chú giải công cụ</translation>
+<translation id="6790428901817661496">Phát</translation>
+<translation id="6820355525329141109">Không thể tải plugin.</translation>
+<translation id="6820615603175220800">tham chiếu danh mục</translation>
+<translation id="6843725295806269523">tắt tiếng</translation>
+<translation id="6885760532393684712">thư mục</translation>
+<translation id="689129560213475294">lời ghi cuối sách</translation>
+<translation id="6934078000481955284">khung trích dẫn</translation>
+<translation id="693476918119313863">tiêu đề</translation>
+<translation id="6941933287844615239">tải xuống phương tiện</translation>
+<translation id="6981594929165378967">chèn</translation>
+<translation id="6989848892321993519">Vui lòng kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng 1 ký tự).</translation>
+<translation id="7034405885550056553">đề xuất</translation>
+<translation id="709897737746224366">Vui lòng khớp với định dạng được yêu cầu.</translation>
+<translation id="7118469954320184356">Không có nội dung mô tả.</translation>
+<translation id="7139483182332611405">lời nói đầu</translation>
+<translation id="7214187073215825913">thông tin về nội dung</translation>
+<translation id="7263440858009898357">Vui lòng chọn một mục trong danh sách.</translation>
+<translation id="727747134524199931">tiêu đề cột</translation>
+<translation id="7320576522385648310">lưu vào bộ đệm</translation>
+<translation id="7353453495576941748">ghi nhận tác giả</translation>
+<translation id="7364796246159120393">Chọn tệp</translation>
+<translation id="739024184232394898">Khác...</translation>
+<translation id="7405738980073107433">chú thích cuối</translation>
+<translation id="7410239719251593705">Có vẻ chứa nội dung người lớn. Không có nội dung mô tả.</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">tab</translation>
+<translation id="7514365320538308">Tải xuống</translation>
+<translation id="7529102961911894712">liên kết ngược</translation>
+<translation id="7533959249147584474">Hình ảnh không có nhãn</translation>
+<translation id="7647456547678091388">mẹo</translation>
+<translation id="7661956066982048809">tài liệu đồ họa</translation>
+<translation id="7673697353781729403">Giờ</translation>
+<translation id="7681220483256441252">chú dẫn</translation>
+<translation id="7740050170769002709">Nội dung HTML</translation>
+<translation id="7745230546936012372">Để tải nội dung mô tả hình ảnh bị thiếu, hãy mở menu ngữ cảnh.</translation>
+<translation id="7750228210027921155">Hình trong hình</translation>
+<translation id="775297008183122718">Mục nhập không hợp lệ</translation>
+<translation id="7789962463072032349">tạm dừng</translation>
+<translation id="7802800022689234070">tam giác hiển thị</translation>
+<translation id="7888071071722539607">Vui lòng bao gồm '<ph name="ATSIGN" />' trong địa chỉ email. '<ph name="INVALIDADDRESS" />' bị thiếu '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">bộ chia</translation>
+<translation id="795667975304826397">Không có tệp nào được chọn</translation>
+<translation id="8053789581856978548">trường văn bản tìm kiếm</translation>
+<translation id="8057695513531652401">lưu ý</translation>
+<translation id="8105797009065549151">tham chiếu chú thích</translation>
+<translation id="811583516810654505">Đang tải nội dung mô tả...</translation>
+<translation id="8117451130807776954">Tuần này</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="8208673686607688524">bộ chọn ngày và giờ địa phương</translation>
+<translation id="8261464734335370856">Chính tả không hợp lệ</translation>
+<translation id="8284326494547611709">Phụ đề</translation>
+<translation id="8346634859695247203">phần mục</translation>
+<translation id="835897206747267392">Giá trị không hợp lệ.</translation>
+<translation id="8403857369060869934">thời gian trôi qua: <ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">phần</translation>
+<translation id="8433900881053900389">thanh công cụ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tệp</translation>
+<translation id="8451268428117625855">Vui lòng chọn một tệp.</translation>
+<translation id="8461852803063341183">nút radio</translation>
+<translation id="8474886197722836894">lời đề tặng</translation>
+<translation id="8531739829932800271">bản đính chính</translation>
+<translation id="8534579021159131403">Phút</translation>
+<translation id="8541249477527128034">kiểm soát phương tiện</translation>
+<translation id="8550857728288566671">biểu tượng đồ họa</translation>
+<translation id="8583702881314752957">danh sách định nghĩa</translation>
+<translation id="8597182159515967513">đầu đề</translation>
+<translation id="860475260694818407">mục lục</translation>
+<translation id="8613126697340063924">điều khiển phát lại từ xa</translation>
+<translation id="862370744433916922">phụ đề</translation>
+<translation id="8711688047404765493">thiết bị ra</translation>
+<translation id="8750798805984357768">Vui lòng chọn một trong các tùy chọn sau.</translation>
+<translation id="8808573423886751634">chương</translation>
+<translation id="8822203815165896261">thông tin về tác giả</translation>
+<translation id="8845239796550121995">Hiện đang truyền tới TV của bạn</translation>
+<translation id="8851136666856101339">chính</translation>
+<translation id="8875657656876809964">Lỗi phát lại video</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">Tháng</translation>
+<translation id="901493112792887934">thời gian hiện tại bằng giây</translation>
+<translation id="901834265349196618">email</translation>
+<translation id="9048119486235211610">điều hướng</translation>
+<translation id="9062295712474918030">tài liệu</translation>
+<translation id="9093215626363556771">thoát chế độ hình trong hình</translation>
+<translation id="9108370397979208512">toán học</translation>
+<translation id="9132465097189459683">Khác...</translation>
+<translation id="9138385573473225930">thông báo</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />, bắt đầu vào <ph name="WEEK_START_DATE" /></translation>
+<translation id="916607977885256133">Ảnh trong ảnh</translation>
+<translation id="9168329111483466115">chú thích cuối trang</translation>
+<translation id="954003015749068518">vào chế độ hình trong hình</translation>
+<translation id="966787709310836684">menu</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..31821a25a1d
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-CN.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-CN">
+<translation id="1018939186200882850">菜单项</translation>
+<translation id="10623998915015855">切换按钮</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="1171774979989969504">请输入电子邮件地址。</translation>
+<translation id="1178581264944972037">暂停</translation>
+<translation id="1188858454923323853">补充内容</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">滑块</translation>
+<translation id="1211441953136645838">尾注</translation>
+<translation id="1281252709823657822">对话框</translation>
+<translation id="1335095011850992622">参与者名单</translation>
+<translation id="1342835525016946179">文章标记</translation>
+<translation id="1359897965706325498">横幅</translation>
+<translation id="1589122976691792535">区域</translation>
+<translation id="1591562245178063882">本月</translation>
+<translation id="1637811476055996098">选择文件</translation>
+<translation id="1650423536718072820">重要引述</translation>
+<translation id="1727886345390570319">隐藏字幕菜单</translation>
+<translation id="1729654308190250600">请输入有效的电子邮件地址。</translation>
+<translation id="1758486001363313524">其他...</translation>
+<translation id="1806710327868736751">提醒对话框</translation>
+<translation id="1821985195704844674">树状网格</translation>
+<translation id="1822429046913737220">上午/下午</translation>
+<translation id="1832974991323546415">在远程设备上播放</translation>
+<translation id="190587075670221089">删除</translation>
+<translation id="1907737156431278478">示例</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="1930711995431081526">状态</translation>
+<translation id="1938124657309484470">指定的值不得晚于<ph name="MAXIMUM_DATE_OR_TIME" />。</translation>
+<translation id="1946271899482435442">显示日期选择器</translation>
+<translation id="1993104285338243655">已切换到镜像</translation>
+<translation id="2060505056492490888">“<ph name="INVALIDDOMAIN" />”中“<ph name="DOT" />”的位置不正确。</translation>
+<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="2247351761944213033"><ph name="YEAR" /> 年第 <ph name="WEEKNUMBER" /> 周</translation>
+<translation id="2277199496770840904">字幕轨 <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">复选框</translation>
+<translation id="2311842470354187719">分页符</translation>
+<translation id="2335594187091864976">日期和时间选择器</translation>
+<translation id="245932805758469625">视频剩余时间(以秒为单位)</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="2507943997699731163">请填写此字段。</translation>
+<translation id="2508569020611168319">标签列表</translation>
+<translation id="2561842179657104141">显示更多媒体控件</translation>
+<translation id="2572483411312390101">播放</translation>
+<translation id="2613802280814924224">请输入有效值。最接近的有效值为<ph name="VALID_VALUE" />。</translation>
+<translation id="2653659639078652383">提交</translation>
+<translation id="2657045182931379222">图形对象</translation>
+<translation id="2674318244760992338">页脚</translation>
+<translation id="2709516037105925701">自动填充</translation>
+<translation id="2723001399770238859">音频</translation>
+<translation id="2725963129578236554">评注</translation>
+<translation id="2746543609216772311">指定的值不得早于<ph name="MINIMUM_DATE_OR_TIME" />。</translation>
+<translation id="2759744352195237655">弹出式按钮</translation>
+<translation id="2761667185364618470">如果要继续,请选中此框。</translation>
+<translation id="2844350028562914727">详细信息</translation>
+<translation id="2896972712917208084">单选按钮组</translation>
+<translation id="2908441821576996758">请输入用逗号分隔的电子邮件地址的列表。</translation>
+<translation id="2940813599313844715">对象</translation>
+<translation id="3040011195152428237">链接</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">请输入一个有效值。该字段不完整或存在无效日期。</translation>
+<translation id="3078740164268491126">表格</translation>
+<translation id="3086746722712840547">备注</translation>
+<translation id="310520048233152454">请输入网址。</translation>
+<translation id="3175736971608411871">定时器</translation>
+<translation id="3199563858620722075">组合框</translation>
+<translation id="3450233048674729344">值必须小于或等于 <ph name="MAXIMUM" />。</translation>
+<translation id="3486220673238053218">定义</translation>
+<translation id="3557673793733683882">标题 <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">星期选择器</translation>
+<translation id="3685101356851116974">未加标签的图片</translation>
+<translation id="3706100364254443312">切换</translation>
+<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">退出“画中画”模式</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">字词</translation>
+<translation id="3822383571486410024">请将该文本增加为 <ph name="MIN_CHARACTERS" /> 个字符或更多(您当前使用的是 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
+<translation id="383465348367842624">“<ph name="ATSIGN" />”前面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
+<translation id="3846214748874656680">退出全屏模式</translation>
+<translation id="3889183436948184105">修订历史</translation>
+<translation id="3920932319529768807">总结</translation>
+<translation id="3924558731517983934">应用</translation>
+<translation id="3944740393230681990">序言</translation>
+<translation id="3960700977367013758">滚动条</translation>
+<translation id="4103419683916926126">毫秒</translation>
+<translation id="4151657705144244502">图形</translation>
+<translation id="4160057747563657758">电话号码</translation>
+<translation id="4193965531860883258">前言</translation>
+<translation id="4201051445878709314">显示上一个月</translation>
+<translation id="421884353938374759">颜色选择器</translation>
+<translation id="4248100235867064564">菜单栏</translation>
+<translation id="4360991593054037559">请输入有效值。两个最接近的有效值分别为<ph name="VALID_VALUE_LOW" />和<ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4384583879834880242">问答</translation>
+<translation id="4413860115965805769">菜单按钮</translation>
+<translation id="4444765639179266822">似乎是说:<ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">词汇表参考资料</translation>
+<translation id="4522570452068850558">详细信息</translation>
+<translation id="4542388879936266156">剩余时间:<ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">表单</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
+<translation id="4668956016107839909">附录</translation>
+<translation id="4718048029184481307">以“画中画”模式播放</translation>
+<translation id="4742539557769756338">封面</translation>
+<translation id="4748357248530471599">开启/关闭全屏模式中的刘海屏</translation>
+<translation id="4757246831282535685">标签面板</translation>
+<translation id="4763480195061959176">视频</translation>
+<translation id="479989351350248267">搜索</translation>
+<translation id="4812940957355064477">请输入一个数字。</translation>
+<translation id="4912536737030637138">参考书目</translation>
+<translation id="4975562563186953947">选择了<ph name="SELECTED_COUNT" />项</translation>
+<translation id="4992066212339426712">取消静音</translation>
+<translation id="49969490063480558">请在“<ph name="ATSIGN" />”后面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
+<translation id="5034860022980953847">进度指示器</translation>
+<translation id="5090250355906949916">视频时间进度条</translation>
+<translation id="5093189678851173835">题词</translation>
+<translation id="5117590920725113268">显示下一个月</translation>
+<translation id="512758898067543763">行标题</translation>
+<translation id="5143125788380636750">结语</translation>
+<translation id="5164977714490026579">值必须大于或等于 <ph name="MINIMUM" />。</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">请在“<ph name="ATSIGN" />”前面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
+<translation id="5334352251556557839">无法播放媒体。</translation>
+<translation id="5406322316791861025">图表</translation>
+<translation id="5453733299334684579">树状目录项</translation>
+<translation id="5466621249238537318">请选择一个或多个文件。</translation>
+<translation id="5468998798572797635">退出全屏模式</translation>
+<translation id="5516424706154626233">日期选择器</translation>
+<translation id="5537725057119320332">投射</translation>
+<translation id="5546461542133609677">取消静音</translation>
+<translation id="5608153257855394627">突出显示</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">在左侧或右侧点按两次即可跳过 10 秒</translation>
+<translation id="5631759159893697722">摘要</translation>
+<translation id="5643186887447432888">按钮</translation>
+<translation id="5677946354068040947">更多选项</translation>
+<translation id="576709008726043716">简介</translation>
+<translation id="57838592816432529">静音</translation>
+<translation id="5860033963881614850">关闭</translation>
+<translation id="588258955323874662">全屏</translation>
+<translation id="5888666972993069672">现正投射至“<ph name="DEVICE_FRIENDLY_NAME" />”</translation>
+<translation id="591047860372322273">搜索框</translation>
+<translation id="5939518447894949180">重置</translation>
+<translation id="5966707198760109579">周</translation>
+<translation id="5987525920412732405">微调按钮</translation>
+<translation id="6011459053400940133">音量滑块</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">列表框</translation>
+<translation id="6150588977291308318">参考书目</translation>
+<translation id="6164829606128959761">计量条</translation>
+<translation id="6166809985690652833">后记</translation>
+<translation id="6209276755895393898">似乎是:<ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">词汇表</translation>
+<translation id="6281763101136022427">网址</translation>
+<translation id="6310801910862476708">退出“画中画”模式</translation>
+<translation id="6398862346408813489">显示月份选择面板</translation>
+<translation id="6404546809543547843">音频时间进度条</translation>
+<translation id="6443871981718447451">显示字幕菜单</translation>
+<translation id="6453774872122745852">致谢</translation>
+<translation id="6475115390776617481">实时协作状态</translation>
+<translation id="648732519525291180">时间选择器</translation>
+<translation id="6550675742724504774">选项</translation>
+<translation id="6572309429103589720">语法无效</translation>
+<translation id="658823671542763450">进入全屏模式</translation>
+<translation id="663493177488814956">Feed</translation>
+<translation id="6637586476836377253">日志</translation>
+<translation id="6643016212128521049">清除</translation>
+<translation id="668171684555832681">其他...</translation>
+<translation id="6692633176391053278">步进器</translation>
+<translation id="6709570249143506788">播放质量不佳</translation>
+<translation id="6755330956360078551">提示</translation>
+<translation id="6790428901817661496">播放</translation>
+<translation id="6820355525329141109">无法加载插件。</translation>
+<translation id="6820615603175220800">参考书目</translation>
+<translation id="6843725295806269523">静音</translation>
+<translation id="6885760532393684712">目录</translation>
+<translation id="689129560213475294">版权页</translation>
+<translation id="6934078000481955284">引用标记</translation>
+<translation id="693476918119313863">标题</translation>
+<translation id="6941933287844615239">下载媒体</translation>
+<translation id="6981594929165378967">插入</translation>
+<translation id="6989848892321993519">请将该内容增加到 <ph name="MIN_CHARACTERS" /> 个或更多字符(目前您使用了 1 个字符)。</translation>
+<translation id="7034405885550056553">建议</translation>
+<translation id="709897737746224366">请与所请求的格式保持一致。</translation>
+<translation id="7118469954320184356">尚无说明。</translation>
+<translation id="7139483182332611405">序言</translation>
+<translation id="7214187073215825913">内容信息</translation>
+<translation id="7263440858009898357">请在列表中选择一项。</translation>
+<translation id="727747134524199931">列标题</translation>
+<translation id="7320576522385648310">正在缓冲</translation>
+<translation id="7353453495576941748">感谢</translation>
+<translation id="7364796246159120393">选择文件</translation>
+<translation id="739024184232394898">其他...</translation>
+<translation id="7405738980073107433">尾注</translation>
+<translation id="7410239719251593705">似乎包含成人内容。尚无说明。</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">标签</translation>
+<translation id="7514365320538308">下载</translation>
+<translation id="7529102961911894712">返回链接</translation>
+<translation id="7533959249147584474">未加标签的图片</translation>
+<translation id="7647456547678091388">提示</translation>
+<translation id="7661956066982048809">图形文档</translation>
+<translation id="7673697353781729403">小时</translation>
+<translation id="7681220483256441252">索引</translation>
+<translation id="7740050170769002709">HTML 内容</translation>
+<translation id="7745230546936012372">要获取缺失的图片说明,请打开上下文菜单。</translation>
+<translation id="7750228210027921155">画中画</translation>
+<translation id="775297008183122718">输入内容无效</translation>
+<translation id="7789962463072032349">暂停</translation>
+<translation id="7802800022689234070">开合三角标记</translation>
+<translation id="7888071071722539607">请在电子邮件地址中包括“<ph name="ATSIGN" />”。“<ph name="INVALIDADDRESS" />”中缺少“<ph name="ATSIGN" />”。</translation>
+<translation id="7891486169920085145">分离器</translation>
+<translation id="795667975304826397">未选择任何文件</translation>
+<translation id="8053789581856978548">搜索文本字段</translation>
+<translation id="8057695513531652401">通知</translation>
+<translation id="8105797009065549151">备注参考资料</translation>
+<translation id="811583516810654505">正在获取说明…</translation>
+<translation id="8117451130807776954">本周</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="8208673686607688524">当地日期和时间选择器</translation>
+<translation id="8261464734335370856">拼写无效</translation>
+<translation id="8284326494547611709">字幕</translation>
+<translation id="8346634859695247203">部分</translation>
+<translation id="835897206747267392">值无效。</translation>
+<translation id="8403857369060869934">已播放时间:<ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">部分</translation>
+<translation id="8433900881053900389">工具栏</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 个文件</translation>
+<translation id="8451268428117625855">请选择一个文件。</translation>
+<translation id="8461852803063341183">单选按钮</translation>
+<translation id="8474886197722836894">献辞</translation>
+<translation id="8531739829932800271">勘误表</translation>
+<translation id="8534579021159131403">分钟</translation>
+<translation id="8541249477527128034">媒体控件</translation>
+<translation id="8550857728288566671">图形符号</translation>
+<translation id="8583702881314752957">定义列表</translation>
+<translation id="8597182159515967513">标题</translation>
+<translation id="860475260694818407">目录</translation>
+<translation id="8613126697340063924">控制远程播放</translation>
+<translation id="862370744433916922">副标题</translation>
+<translation id="8711688047404765493">输出</translation>
+<translation id="8750798805984357768">请从这些选项中选择一个。</translation>
+<translation id="8808573423886751634">章节</translation>
+<translation id="8822203815165896261">创作信息</translation>
+<translation id="8845239796550121995">现在正投射到您的电视上</translation>
+<translation id="8851136666856101339">主体内容</translation>
+<translation id="8875657656876809964">视频播放出错</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="901493112792887934">目前时间(以秒为单位)</translation>
+<translation id="901834265349196618">电子邮件</translation>
+<translation id="9048119486235211610">导航</translation>
+<translation id="9062295712474918030">文档</translation>
+<translation id="9093215626363556771">退出“画中画”模式</translation>
+<translation id="9108370397979208512">数学</translation>
+<translation id="9132465097189459683">其他...</translation>
+<translation id="9138385573473225930">提醒</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />,从 <ph name="WEEK_START_DATE" />开始</translation>
+<translation id="916607977885256133">画中画</translation>
+<translation id="9168329111483466115">脚注</translation>
+<translation id="954003015749068518">进入“画中画”模式</translation>
+<translation id="966787709310836684">菜单</translation>
+</translationbundle> \ No newline at end of file
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
new file mode 100644
index 00000000000..c462fead329
--- /dev/null
+++ b/chromium/third_party/blink/public/strings/translations/blink_strings_zh-TW.xtb
@@ -0,0 +1,269 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-TW">
+<translation id="1018939186200882850">選單項目</translation>
+<translation id="10623998915015855">切換按鈕</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="1171774979989969504">請輸入電子郵件地址。</translation>
+<translation id="1178581264944972037">暫停</translation>
+<translation id="1188858454923323853">補充</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">滑桿</translation>
+<translation id="1211441953136645838">章節附註</translation>
+<translation id="1281252709823657822">對話方塊</translation>
+<translation id="1335095011850992622">參與名單</translation>
+<translation id="1342835525016946179">文章</translation>
+<translation id="1359897965706325498">橫幅</translation>
+<translation id="1589122976691792535">區域</translation>
+<translation id="1591562245178063882">本月</translation>
+<translation id="1637811476055996098">選擇檔案</translation>
+<translation id="1650423536718072820">重要引述</translation>
+<translation id="1727886345390570319">不要顯示隱藏式輔助字幕選單</translation>
+<translation id="1729654308190250600">請輸入電子郵件地址。</translation>
+<translation id="1758486001363313524">其他...</translation>
+<translation id="1806710327868736751">警示對話方塊</translation>
+<translation id="1821985195704844674">樹狀目錄網格</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1832974991323546415">在遠端裝置上播放</translation>
+<translation id="190587075670221089">刪除</translation>
+<translation id="1907737156431278478">範例</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="1930711995431081526">狀態</translation>
+<translation id="1938124657309484470">必須輸入 <ph name="MAXIMUM_DATE_OR_TIME" /> 或之前的值。</translation>
+<translation id="1946271899482435442">顯示日期選擇器</translation>
+<translation id="1993104285338243655">已切換至鏡像模式</translation>
+<translation id="2060505056492490888">「<ph name="DOT" />」未放在「<ph name="INVALIDDOMAIN" />」的正確位置。</translation>
+<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="2247351761944213033"><ph name="YEAR" /> 年,第 <ph name="WEEKNUMBER" /> 週</translation>
+<translation id="2277199496770840904">曲目 <ph name="NUMBER" /></translation>
+<translation id="2291999235780842123">核取方塊</translation>
+<translation id="2311842470354187719">分頁符號</translation>
+<translation id="2335594187091864976">日期和時間選擇器</translation>
+<translation id="245932805758469625">影片剩餘秒數</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="2507943997699731163">請填寫這個欄位。</translation>
+<translation id="2508569020611168319">分頁清單</translation>
+<translation id="2561842179657104141">顯示更多媒體控制項</translation>
+<translation id="2572483411312390101">播放</translation>
+<translation id="2613802280814924224">請輸入有效值。最接近的有效值是 <ph name="VALID_VALUE" />。</translation>
+<translation id="2653659639078652383">提交</translation>
+<translation id="2657045182931379222">圖形物件</translation>
+<translation id="2674318244760992338">頁尾</translation>
+<translation id="2709516037105925701">自動填入</translation>
+<translation id="2723001399770238859">音訊</translation>
+<translation id="2725963129578236554">留言</translation>
+<translation id="2746543609216772311">必須輸入 <ph name="MINIMUM_DATE_OR_TIME" /> 或之後的值。</translation>
+<translation id="2759744352195237655">彈出式按鈕</translation>
+<translation id="2761667185364618470">如果你要繼續執行,請勾選這個核取方塊。</translation>
+<translation id="2844350028562914727">詳細資料</translation>
+<translation id="2896972712917208084">圓形按鈕群組</translation>
+<translation id="2908441821576996758">請輸入以逗號分隔的電子郵件地址清單。</translation>
+<translation id="2940813599313844715">物件</translation>
+<translation id="3040011195152428237">連結</translation>
+<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
+<translation id="3075154866155599887">欄位內容不完整或日期無效,請輸入有效的值。</translation>
+<translation id="3078740164268491126">表格</translation>
+<translation id="3086746722712840547">附註</translation>
+<translation id="310520048233152454">請輸入網址。</translation>
+<translation id="3175736971608411871">計時器</translation>
+<translation id="3199563858620722075">下拉式方塊</translation>
+<translation id="3450233048674729344">值必須小於或等於 <ph name="MAXIMUM" />。</translation>
+<translation id="3486220673238053218">定義</translation>
+<translation id="3557673793733683882">標題 <ph name="HEADING_LEVEL" /></translation>
+<translation id="3670698553867754311">週挑選器</translation>
+<translation id="3685101356851116974">未標示的圖片</translation>
+<translation id="3706100364254443312">切換</translation>
+<translation id="3732799496749320381">月</translation>
+<translation id="3754210790023674521">離開子母畫面</translation>
+<translation id="3757388668994797779"><ph name="QUANTITY" /> GB</translation>
+<translation id="3808586225841795776">字詞</translation>
+<translation id="3822383571486410024">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前使用字元數:<ph name="CURRENT_LENGTH" />)。</translation>
+<translation id="383465348367842624">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
+<translation id="3846214748874656680">結束全螢幕</translation>
+<translation id="3889183436948184105">修訂版本</translation>
+<translation id="3920932319529768807">結論</translation>
+<translation id="3924558731517983934">應用程式</translation>
+<translation id="3944740393230681990">序言</translation>
+<translation id="3960700977367013758">捲軸</translation>
+<translation id="4103419683916926126">毫秒</translation>
+<translation id="4151657705144244502">圖形</translation>
+<translation id="4160057747563657758">電話</translation>
+<translation id="4193965531860883258">前言</translation>
+<translation id="4201051445878709314">顯示上一個月</translation>
+<translation id="421884353938374759">顏色選擇器</translation>
+<translation id="4248100235867064564">選單列</translation>
+<translation id="4360991593054037559">請輸入有效值。最接近的兩個有效值分別是 <ph name="VALID_VALUE_LOW" /> 和 <ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4384583879834880242">問與答</translation>
+<translation id="4413860115965805769">選單按鈕</translation>
+<translation id="4444765639179266822">圖片上的文字似乎是:<ph name="OCR_TEXT" /></translation>
+<translation id="4446524499724042288">詞彙解釋參考資料</translation>
+<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4542388879936266156">剩餘時間:<ph name="REMAINING_TIME" /></translation>
+<translation id="4597532268155981612">表單</translation>
+<translation id="4661075872484491155">tree</translation>
+<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
+<translation id="4668956016107839909">附錄</translation>
+<translation id="4718048029184481307">在子母畫面中播放</translation>
+<translation id="4742539557769756338">封面</translation>
+<translation id="4748357248530471599">切換螢幕凹口全螢幕模式</translation>
+<translation id="4757246831282535685">分頁面板</translation>
+<translation id="4763480195061959176">影片</translation>
+<translation id="479989351350248267">search</translation>
+<translation id="4812940957355064477">請輸入一個數字。</translation>
+<translation id="4912536737030637138">參考書目</translation>
+<translation id="4975562563186953947">已選取 <ph name="SELECTED_COUNT" /> 個項目</translation>
+<translation id="4992066212339426712">取消靜音</translation>
+<translation id="49969490063480558">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
+<translation id="5034860022980953847">進度指標</translation>
+<translation id="5090250355906949916">影片時間拖曳工具</translation>
+<translation id="5093189678851173835">題詞</translation>
+<translation id="5117590920725113268">顯示下一個月</translation>
+<translation id="512758898067543763">列標題</translation>
+<translation id="5143125788380636750">結尾</translation>
+<translation id="5164977714490026579">值必須大於或等於 <ph name="MINIMUM" />。</translation>
+<translation id="520299402983819650"><ph name="QUANTITY" /> PB</translation>
+<translation id="5307600278924710095">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
+<translation id="5334352251556557839">無法播放媒體。</translation>
+<translation id="5406322316791861025">圖表</translation>
+<translation id="5453733299334684579">樹狀目錄項目</translation>
+<translation id="5466621249238537318">請選取一或多個檔案。</translation>
+<translation id="5468998798572797635">退出全螢幕</translation>
+<translation id="5516424706154626233">日期選擇器</translation>
+<translation id="5537725057119320332">投放</translation>
+<translation id="5546461542133609677">取消靜音</translation>
+<translation id="5608153257855394627">醒目顯示</translation>
+<translation id="561939826962581046">time</translation>
+<translation id="5630795885300617244">輕觸兩下左側或右側可跳過 10 秒</translation>
+<translation id="5631759159893697722">摘要</translation>
+<translation id="5643186887447432888">按鈕</translation>
+<translation id="5677946354068040947">更多選項</translation>
+<translation id="576709008726043716">簡介</translation>
+<translation id="57838592816432529">靜音</translation>
+<translation id="5860033963881614850">關閉</translation>
+<translation id="588258955323874662">全螢幕</translation>
+<translation id="5888666972993069672">正在投放到「<ph name="DEVICE_FRIENDLY_NAME" />」</translation>
+<translation id="591047860372322273">搜尋框</translation>
+<translation id="5939518447894949180">重設</translation>
+<translation id="5966707198760109579">週</translation>
+<translation id="5987525920412732405">微調按鈕</translation>
+<translation id="6011459053400940133">音量滑桿</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">清單方塊</translation>
+<translation id="6150588977291308318">參考書目</translation>
+<translation id="6164829606128959761">計量器</translation>
+<translation id="6166809985690652833">後記</translation>
+<translation id="6209276755895393898">圖片內容似乎是:<ph name="DESCRIPTION" /></translation>
+<translation id="6213469881011901533">詞彙解釋</translation>
+<translation id="6281763101136022427">網址</translation>
+<translation id="6310801910862476708">離開子母畫面</translation>
+<translation id="6398862346408813489">顯示月份選取面板</translation>
+<translation id="6404546809543547843">音訊時間點拖曳工具</translation>
+<translation id="6443871981718447451">顯示隱藏式輔助字幕選單</translation>
+<translation id="6453774872122745852">鳴謝</translation>
+<translation id="6475115390776617481">即時狀態</translation>
+<translation id="648732519525291180">時間選擇器</translation>
+<translation id="6550675742724504774">選項</translation>
+<translation id="6572309429103589720">文法錯誤</translation>
+<translation id="658823671542763450">進入全螢幕</translation>
+<translation id="663493177488814956">資訊提供</translation>
+<translation id="6637586476836377253">記錄</translation>
+<translation id="6643016212128521049">清除</translation>
+<translation id="668171684555832681">其他...</translation>
+<translation id="6692633176391053278">步進器</translation>
+<translation id="6709570249143506788">播放品質不佳</translation>
+<translation id="6755330956360078551">工具提示</translation>
+<translation id="6790428901817661496">播放</translation>
+<translation id="6820355525329141109">無法載入外掛程式。</translation>
+<translation id="6820615603175220800">參考書目資料</translation>
+<translation id="6843725295806269523">靜音</translation>
+<translation id="6885760532393684712">目錄</translation>
+<translation id="689129560213475294">版權頁標記</translation>
+<translation id="6934078000481955284">引用標記</translation>
+<translation id="693476918119313863">頁首</translation>
+<translation id="6941933287844615239">下載媒體</translation>
+<translation id="6981594929165378967">插入</translation>
+<translation id="6989848892321993519">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前已有 1 個字元)。</translation>
+<translation id="7034405885550056553">建議</translation>
+<translation id="709897737746224366">請符合要求的格式。</translation>
+<translation id="7118469954320184356">目前沒有說明。</translation>
+<translation id="7139483182332611405">前言</translation>
+<translation id="7214187073215825913">內容資訊</translation>
+<translation id="7263440858009898357">請選取一個清單中的項目。</translation>
+<translation id="727747134524199931">欄標題</translation>
+<translation id="7320576522385648310">緩衝處理中</translation>
+<translation id="7353453495576941748">參與名單</translation>
+<translation id="7364796246159120393">選擇檔案</translation>
+<translation id="739024184232394898">其他...</translation>
+<translation id="7405738980073107433">章節附註</translation>
+<translation id="7410239719251593705">圖片似乎含有成人內容。目前沒有說明。</translation>
+<translation id="7460907917090416791"><ph name="QUANTITY" /> TB</translation>
+<translation id="7491962110804786152">分頁</translation>
+<translation id="7514365320538308">下載</translation>
+<translation id="7529102961911894712">反向連結</translation>
+<translation id="7533959249147584474">未標示的圖片</translation>
+<translation id="7647456547678091388">提示</translation>
+<translation id="7661956066982048809">圖形文件</translation>
+<translation id="7673697353781729403">小時</translation>
+<translation id="7681220483256441252">索引</translation>
+<translation id="7740050170769002709">HTML 內容</translation>
+<translation id="7745230546936012372">如要為缺少說明的圖片取得說明,請開啟內容選單。</translation>
+<translation id="7750228210027921155">子母畫面</translation>
+<translation id="775297008183122718">無效的輸入值</translation>
+<translation id="7789962463072032349">暫停</translation>
+<translation id="7802800022689234070">顯示/隱藏三角標記</translation>
+<translation id="7888071071722539607">請在電子郵件地址中包含「<ph name="ATSIGN" />」。「<ph name="INVALIDADDRESS" />」未包含「<ph name="ATSIGN" />」。</translation>
+<translation id="7891486169920085145">分割器</translation>
+<translation id="795667975304826397">未選擇任何檔案</translation>
+<translation id="8053789581856978548">搜尋文字欄位</translation>
+<translation id="8057695513531652401">聲明</translation>
+<translation id="8105797009065549151">附註參考資料</translation>
+<translation id="811583516810654505">正在取得說明...</translation>
+<translation id="8117451130807776954">本週</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="8208673686607688524">當地日期和時間挑選器</translation>
+<translation id="8261464734335370856">拼字錯誤</translation>
+<translation id="8284326494547611709">字幕</translation>
+<translation id="8346634859695247203">部分</translation>
+<translation id="835897206747267392">無效的值。</translation>
+<translation id="8403857369060869934">經過時間:<ph name="ELAPSED_TIME" /></translation>
+<translation id="8415319359811155763">分輯</translation>
+<translation id="8433900881053900389">工具列</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 個檔案</translation>
+<translation id="8451268428117625855">請選取檔案。</translation>
+<translation id="8461852803063341183">圓形按鈕</translation>
+<translation id="8474886197722836894">獻辭</translation>
+<translation id="8531739829932800271">勘誤表</translation>
+<translation id="8534579021159131403">分鐘</translation>
+<translation id="8541249477527128034">媒體控制</translation>
+<translation id="8550857728288566671">圖形符號</translation>
+<translation id="8583702881314752957">定義清單</translation>
+<translation id="8597182159515967513">標題</translation>
+<translation id="860475260694818407">目錄</translation>
+<translation id="8613126697340063924">控制遠端播放</translation>
+<translation id="862370744433916922">副標題</translation>
+<translation id="8711688047404765493">輸出</translation>
+<translation id="8750798805984357768">請選取其中一個選項。</translation>
+<translation id="8808573423886751634">章節</translation>
+<translation id="8822203815165896261">作者資訊</translation>
+<translation id="8845239796550121995">正在投放到電視上</translation>
+<translation id="8851136666856101339">主要元素</translation>
+<translation id="8875657656876809964">影片播放錯誤</translation>
+<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="901493112792887934">目前時間 (以秒為單位)</translation>
+<translation id="901834265349196618">電子郵件</translation>
+<translation id="9048119486235211610">導覽</translation>
+<translation id="9062295712474918030">文件</translation>
+<translation id="9093215626363556771">離開子母畫面</translation>
+<translation id="9108370397979208512">數學</translation>
+<translation id="9132465097189459683">其他...</translation>
+<translation id="9138385573473225930">警示</translation>
+<translation id="9155987714137265666"><ph name="WEEK" />,從 <ph name="WEEK_START_DATE" />開始</translation>
+<translation id="916607977885256133">子母畫面</translation>
+<translation id="9168329111483466115">註腳</translation>
+<translation id="954003015749068518">進入子母畫面</translation>
+<translation id="966787709310836684">選單</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/third_party/blink/public/web/DEPS b/chromium/third_party/blink/public/web/DEPS
index 58f3066d3ea..5ab26450f8e 100644
--- a/chromium/third_party/blink/public/web/DEPS
+++ b/chromium/third_party/blink/public/web/DEPS
@@ -14,6 +14,7 @@ include_rules = [
"+cc/input/overscroll_behavior.h",
"+cc/input/layer_selection_bound.h",
"+cc/layers/layer.h",
+ "+cc/metrics/begin_main_frame_metrics.h",
"+cc/paint/element_id.h",
"+cc/paint/paint_canvas.h",
"+cc/paint/paint_flags.h",
@@ -26,6 +27,7 @@ include_rules = [
"+services/metrics/public/cpp/ukm_source_id.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/ip_address_space.mojom-shared.h",
"+services/network/public/mojom/referrer_policy.mojom-shared.h",
"+services/service_manager/public",
diff --git a/chromium/third_party/blink/public/web/blink.h b/chromium/third_party/blink/public/web/blink.h
index a15ea060fce..7ec87b5a64a 100644
--- a/chromium/third_party/blink/public/web/blink.h
+++ b/chromium/third_party/blink/public/web/blink.h
@@ -68,10 +68,6 @@ BLINK_EXPORT v8::Isolate* MainThreadIsolate();
BLINK_EXPORT void SetWebTestMode(bool);
BLINK_EXPORT bool WebTestMode();
-// Enables or disables the use of the mock theme for web tests. This function
-// must be called only if SetWebTestMode(true).
-BLINK_EXPORT void SetMockThemeEnabledForTest(bool);
-
// Alters the rendering of fonts for web tests.
BLINK_EXPORT void SetFontAntialiasingEnabledForTest(bool);
BLINK_EXPORT bool FontAntialiasingEnabledForTest();
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h
index 99f47f56b2f..8451b86539b 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h
@@ -73,8 +73,8 @@ class BLINK_MODULES_EXPORT VideoCaptureSettings {
VideoCaptureSettings(const VideoCaptureSettings& other);
VideoCaptureSettings& operator=(const VideoCaptureSettings& other);
- VideoCaptureSettings(VideoCaptureSettings&& other) noexcept;
- VideoCaptureSettings& operator=(VideoCaptureSettings&& other) noexcept;
+ VideoCaptureSettings(VideoCaptureSettings&& other);
+ VideoCaptureSettings& operator=(VideoCaptureSettings&& other);
~VideoCaptureSettings();
bool HasValue() const { return !failed_constraint_name_; }
@@ -193,8 +193,8 @@ class BLINK_MODULES_EXPORT AudioCaptureSettings {
const AudioProcessingProperties& audio_processing_properties);
AudioCaptureSettings(const AudioCaptureSettings& other);
AudioCaptureSettings& operator=(const AudioCaptureSettings& other);
- AudioCaptureSettings(AudioCaptureSettings&& other) noexcept;
- AudioCaptureSettings& operator=(AudioCaptureSettings&& other) noexcept;
+ AudioCaptureSettings(AudioCaptureSettings&& other);
+ AudioCaptureSettings& operator=(AudioCaptureSettings&& other);
bool HasValue() const { return !failed_constraint_name_; }
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h
index 199bdeb22a6..c89e6e91bb9 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_sets.h
@@ -159,8 +159,8 @@ class DiscreteSet {
DiscreteSet(const DiscreteSet& other) = default;
DiscreteSet& operator=(const DiscreteSet& other) = default;
- DiscreteSet(DiscreteSet&& other) noexcept = default;
- DiscreteSet& operator=(DiscreteSet&& other) noexcept = default;
+ DiscreteSet(DiscreteSet&& other) = default;
+ DiscreteSet& operator=(DiscreteSet&& other) = default;
~DiscreteSet() = default;
bool Contains(const T& value) const {
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 5e50d1be156..ed5967f8a27 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
@@ -285,8 +285,8 @@ class BLINK_MODULES_EXPORT MediaStreamVideoSource
const VideoTrackFormatCallback& format_callback,
std::unique_ptr<VideoTrackAdapterSettings> adapter_settings,
const ConstraintsCallback& callback);
- PendingTrackInfo(PendingTrackInfo&& other) noexcept;
- PendingTrackInfo& operator=(PendingTrackInfo&& other) noexcept;
+ PendingTrackInfo(PendingTrackInfo&& other);
+ PendingTrackInfo& operator=(PendingTrackInfo&& other);
~PendingTrackInfo();
MediaStreamVideoTrack* track;
diff --git a/chromium/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h b/chromium/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
index 504a94711f2..fff774fcaf9 100644
--- a/chromium/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
+++ b/chromium/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
@@ -26,11 +26,9 @@ class AudioProcessorControls;
namespace blink {
-// TODO(crbug.com/704136): Move this class and method out of the Blink exposed
+// TODO(crbug.com/704136): Move this class out of the Blink exposed
// API when all users of it have been Onion souped.
-BLINK_MODULES_EXPORT bool IsApmInAudioServiceEnabled();
-
class AudioServiceAudioProcessorProxy;
class MediaStreamAudioProcessor;
class MediaStreamInternalFrameWrapper;
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/DEPS b/chromium/third_party/blink/public/web/modules/peerconnection/DEPS
new file mode 100644
index 00000000000..45e1ae23933
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/DEPS
@@ -0,0 +1,18 @@
+include_rules = [
+ "+base/memory/weak_ptr.h",
+ # TODO(crbug.com/787254): Remove the use of base::MessageLoopCurrent.
+ "+base/message_loop/message_loop_current.h",
+
+ # TODO(crbug.com/787254): Replace base::SequenceChecker by base::ThreadChecker.
+ "+base/sequence_checker.h",
+ "+base/single_thread_task_runner.h",
+ "+base/synchronization/waitable_event.h",
+ "+base/threading/thread.h",
+]
+
+specific_include_rules = {
+ ".*obtainer\.h|mock.*\.h": [
+ "+base/run_loop.h",
+ "+testing/gmock/include/gmock/gmock.h",
+ ],
+}
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
new file mode 100644
index 00000000000..186522410d2
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
@@ -0,0 +1,129 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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_MODULES_PEERCONNECTION_FAKE_RTC_RTP_TRANSCEIVER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_FAKE_RTC_RTP_TRANSCEIVER_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/web_media_constraints.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_sender.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_source.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+
+namespace blink {
+
+// TODO(https://crbug.com/868868): Similar methods to this exist in many blink
+// unittests. Move to a separate file and reuse it in all of them.
+blink::WebMediaStreamTrack CreateWebMediaStreamTrack(
+ const std::string& id,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+class FakeRTCRtpSenderImpl : public blink::WebRTCRtpSender {
+ public:
+ FakeRTCRtpSenderImpl(base::Optional<std::string> track_id,
+ std::vector<std::string> stream_ids,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ FakeRTCRtpSenderImpl(const FakeRTCRtpSenderImpl&);
+ ~FakeRTCRtpSenderImpl() override;
+ FakeRTCRtpSenderImpl& operator=(const FakeRTCRtpSenderImpl&);
+
+ std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override;
+ uintptr_t Id() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override;
+ webrtc::DtlsTransportInformation DtlsTransportInformation() override;
+ blink::WebMediaStreamTrack Track() const override;
+ blink::WebVector<blink::WebString> StreamIds() const override;
+ void ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ blink::WebRTCVoidRequest request) override;
+ std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender()
+ const override;
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() const override;
+ void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>,
+ webrtc::DegradationPreference,
+ blink::WebRTCVoidRequest) override;
+ void GetStats(blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) override;
+ void SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) override;
+
+ private:
+ base::Optional<std::string> track_id_;
+ std::vector<std::string> stream_ids_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+class FakeRTCRtpReceiverImpl : public blink::WebRTCRtpReceiver {
+ public:
+ FakeRTCRtpReceiverImpl(
+ const std::string& track_id,
+ std::vector<std::string> stream_ids,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ FakeRTCRtpReceiverImpl(const FakeRTCRtpReceiverImpl&);
+ ~FakeRTCRtpReceiverImpl() override;
+ FakeRTCRtpReceiverImpl& operator=(const FakeRTCRtpReceiverImpl&);
+
+ std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override;
+ uintptr_t Id() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override;
+ webrtc::DtlsTransportInformation DtlsTransportInformation() override;
+ const blink::WebMediaStreamTrack& Track() const override;
+ blink::WebVector<blink::WebString> StreamIds() const override;
+ blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> GetSources()
+ override;
+ void GetStats(blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) override;
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() const override;
+ void SetJitterBufferMinimumDelay(
+ base::Optional<double> delay_seconds) override;
+
+ private:
+ blink::WebMediaStreamTrack track_;
+ std::vector<std::string> stream_ids_;
+};
+
+class FakeRTCRtpTransceiverImpl : public blink::WebRTCRtpTransceiver {
+ public:
+ FakeRTCRtpTransceiverImpl(
+ base::Optional<std::string> mid,
+ FakeRTCRtpSenderImpl sender,
+ FakeRTCRtpReceiverImpl receiver,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction);
+ ~FakeRTCRtpTransceiverImpl() override;
+
+ blink::WebRTCRtpTransceiverImplementationType ImplementationType()
+ const override;
+ uintptr_t Id() const override;
+ blink::WebString Mid() const override;
+ std::unique_ptr<blink::WebRTCRtpSender> Sender() const override;
+ std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override;
+ bool Stopped() const override;
+ webrtc::RtpTransceiverDirection Direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection direction) override;
+ base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection()
+ const override;
+ base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
+ const override;
+
+ private:
+ base::Optional<std::string> mid_;
+ FakeRTCRtpSenderImpl sender_;
+ FakeRTCRtpReceiverImpl receiver_;
+ bool stopped_;
+ webrtc::RtpTransceiverDirection direction_;
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_FAKE_RTC_RTP_TRANSCEIVER_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h b/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h
index b9085cf6ae8..a0ee73b114e 100644
--- a/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h
@@ -23,7 +23,7 @@ class TrackObserver;
// source is a local source and a video track where the source is a remote video
// track.
//
-// TODO(crbug.com/704136): Move the classes below out of the Blink exposed
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed
// API when all users of it have been Onion souped.
class BLINK_MODULES_EXPORT MediaStreamRemoteVideoSource
: public MediaStreamVideoSource {
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h b/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h
new file mode 100644
index 00000000000..019e8fd591b
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h
@@ -0,0 +1,89 @@
+// 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_WEB_MODULES_PEERCONNECTION_MEDIA_STREAM_VIDEO_WEBRTC_SINK_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MEDIA_STREAM_VIDEO_WEBRTC_SINK_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+class MediaStreamVideoTrack;
+class PeerConnectionDependencyFactory;
+class WebRtcVideoTrackSource;
+
+// MediaStreamVideoWebRtcSink is an adapter between a
+// MediaStreamVideoTrack object and a webrtc VideoTrack that is
+// currently sent on a PeerConnection.
+// The responsibility of the class is to create and own a representation of a
+// webrtc VideoTrack that can be added and removed from a RTCPeerConnection. An
+// instance of MediaStreamVideoWebRtcSink is created when a VideoTrack is added
+// to an RTCPeerConnection object.
+// Instances of this class is owned by the WebRtcMediaStreamAdapter object that
+// created it.
+//
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed
+// API when all users of it have been Onion souped.
+class BLINK_MODULES_EXPORT MediaStreamVideoWebRtcSink
+ : public MediaStreamVideoSink {
+ public:
+ MediaStreamVideoWebRtcSink(
+ const WebMediaStreamTrack& track,
+ PeerConnectionDependencyFactory* factory,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~MediaStreamVideoWebRtcSink() override;
+
+ webrtc::VideoTrackInterface* webrtc_video_track() {
+ return video_track_.get();
+ }
+
+ absl::optional<bool> SourceNeedsDenoisingForTesting() const;
+
+ protected:
+ // Implementation of MediaStreamSink.
+ void OnEnabledChanged(bool enabled) override;
+ void OnContentHintChanged(
+ WebMediaStreamTrack::ContentHintType content_hint) override;
+
+ private:
+ // Helper to request a refresh frame from the source. Called via the callback
+ // passed to WebRtcVideoSourceAdapter.
+ void RequestRefreshFrame();
+
+ // Used to DCHECK that we are called on the correct thread.
+ THREAD_CHECKER(thread_checker_);
+
+ // |video_source_| and |video_source_proxy_| are held as
+ // references to outlive |video_track_| since the interfaces between them
+ // don't use reference counting.
+ scoped_refptr<WebRtcVideoTrackSource> video_source_;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> video_source_proxy_;
+ scoped_refptr<webrtc::VideoTrackInterface> video_track_;
+
+ class WebRtcVideoSourceAdapter;
+ scoped_refptr<WebRtcVideoSourceAdapter> source_adapter_;
+
+ // Provides WebRtcVideoSourceAdapter a weak reference to
+ // MediaStreamVideoWebRtcSink in order to allow it to request refresh frames.
+ // See comments in media_stream_video_webrtc_sink.cc.
+ //
+ // TODO(crbug.com/787254): Make this object Oilpan-able, and get
+ // rid of this weak prt factory use.
+ base::WeakPtrFactory<MediaStreamVideoWebRtcSink> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoWebRtcSink);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MEDIA_STREAM_VIDEO_WEBRTC_SINK_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/mock_data_channel_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/mock_data_channel_impl.h
new file mode 100644
index 00000000000..9dd63111b6a
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/mock_data_channel_impl.h
@@ -0,0 +1,59 @@
+// 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_WEB_MODULES_PEERCONNECTION_MOCK_DATA_CHANNEL_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_DATA_CHANNEL_IMPL_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/macros.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+
+namespace blink {
+
+// TODO(crbug.com/787254): Move this class out of the Blink API
+// when all its clients get Onion souped.
+class MockDataChannel : public webrtc::DataChannelInterface {
+ public:
+ MockDataChannel(const std::string& label,
+ const webrtc::DataChannelInit* config);
+
+ void RegisterObserver(webrtc::DataChannelObserver* observer) override;
+ void UnregisterObserver() override;
+ std::string label() const override;
+ bool reliable() const override;
+ bool ordered() const override;
+ std::string protocol() const override;
+ bool negotiated() const override;
+ int id() const override;
+ DataState state() const override;
+ uint32_t messages_sent() const override;
+ uint64_t bytes_sent() const override;
+ uint32_t messages_received() const override;
+ uint64_t bytes_received() const override;
+ uint64_t buffered_amount() const override;
+ void Close() override;
+ bool Send(const webrtc::DataBuffer& buffer) override;
+
+ // For testing.
+ void changeState(DataState state);
+
+ protected:
+ ~MockDataChannel() override;
+
+ private:
+ std::string label_;
+ bool reliable_;
+ webrtc::DataChannelInterface::DataState state_;
+ webrtc::DataChannelInit config_;
+ webrtc::DataChannelObserver* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDataChannel);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_DATA_CHANNEL_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h b/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h
new file mode 100644
index 00000000000..a53758e9611
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.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_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+
+typedef std::set<webrtc::ObserverInterface*> ObserverSet;
+
+class MockWebRtcAudioSource : public webrtc::AudioSourceInterface {
+ public:
+ MockWebRtcAudioSource(bool is_remote);
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+
+ SourceState state() const override;
+ bool remote() const override;
+
+ private:
+ const bool is_remote_;
+};
+
+class MockWebRtcAudioTrack : public webrtc::AudioTrackInterface {
+ public:
+ static scoped_refptr<MockWebRtcAudioTrack> Create(const std::string& id);
+
+ void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
+ void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
+ webrtc::AudioSourceInterface* GetSource() const override;
+
+ std::string kind() const override;
+ std::string id() const override;
+ bool enabled() const override;
+ webrtc::MediaStreamTrackInterface::TrackState state() const override;
+ bool set_enabled(bool enable) override;
+
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+
+ void SetEnded();
+
+ protected:
+ MockWebRtcAudioTrack(const std::string& id);
+ ~MockWebRtcAudioTrack() override;
+
+ private:
+ std::string id_;
+ scoped_refptr<webrtc::AudioSourceInterface> source_;
+ bool enabled_;
+ TrackState state_;
+ ObserverSet observers_;
+};
+
+class MockWebRtcVideoTrack : public webrtc::VideoTrackInterface {
+ public:
+ static scoped_refptr<MockWebRtcVideoTrack> Create(const std::string& id);
+ MockWebRtcVideoTrack(const std::string& id,
+ webrtc::VideoTrackSourceInterface* source);
+ void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+ void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override;
+ webrtc::VideoTrackSourceInterface* GetSource() const override;
+
+ std::string kind() const override;
+ std::string id() const override;
+ bool enabled() const override;
+ webrtc::MediaStreamTrackInterface::TrackState state() const override;
+ bool set_enabled(bool enable) override;
+
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+
+ void SetEnded();
+
+ protected:
+ ~MockWebRtcVideoTrack() override;
+
+ private:
+ std::string id_;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> source_;
+ bool enabled_;
+ TrackState state_;
+ ObserverSet observers_;
+ rtc::VideoSinkInterface<webrtc::VideoFrame>* sink_;
+};
+
+class MockMediaStream : public webrtc::MediaStreamInterface {
+ public:
+ explicit MockMediaStream(const std::string& id);
+
+ bool AddTrack(webrtc::AudioTrackInterface* track) override;
+ bool AddTrack(webrtc::VideoTrackInterface* track) override;
+ bool RemoveTrack(webrtc::AudioTrackInterface* track) override;
+ bool RemoveTrack(webrtc::VideoTrackInterface* track) override;
+ std::string id() const override;
+ webrtc::AudioTrackVector GetAudioTracks() override;
+ webrtc::VideoTrackVector GetVideoTracks() override;
+ rtc::scoped_refptr<webrtc::AudioTrackInterface> FindAudioTrack(
+ const std::string& track_id) override;
+ rtc::scoped_refptr<webrtc::VideoTrackInterface> FindVideoTrack(
+ const std::string& track_id) override;
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+
+ protected:
+ ~MockMediaStream() override;
+
+ private:
+ void NotifyObservers();
+
+ std::string id_;
+ webrtc::AudioTrackVector audio_track_vector_;
+ webrtc::VideoTrackVector video_track_vector_;
+
+ ObserverSet observers_;
+};
+
+// A mock factory for creating different objects for
+// RTC PeerConnections.
+class MockPeerConnectionDependencyFactory
+ : public blink::PeerConnectionDependencyFactory {
+ public:
+ MockPeerConnectionDependencyFactory();
+ ~MockPeerConnectionDependencyFactory() override;
+
+ scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
+ blink::WebLocalFrame* frame,
+ webrtc::PeerConnectionObserver* observer) override;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> CreateVideoTrackSourceProxy(
+ webrtc::VideoTrackSourceInterface* source) override;
+ scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
+ const std::string& label) override;
+ scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source) override;
+ webrtc::SessionDescriptionInterface* CreateSessionDescription(
+ const std::string& type,
+ const std::string& sdp,
+ webrtc::SdpParseError* error) override;
+ webrtc::IceCandidateInterface* CreateIceCandidate(
+ const std::string& sdp_mid,
+ int sdp_mline_index,
+ const std::string& sdp) override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcSignalingTaskRunner()
+ override;
+
+ // If |fail| is true, subsequent calls to CreateSessionDescription will
+ // return nullptr. This can be used to fake a blob of SDP that fails to be
+ // parsed.
+ void SetFailToCreateSessionDescription(bool fail);
+
+ private:
+ base::Thread signaling_thread_;
+ bool fail_to_create_session_description_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionDependencyFactory);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h
new file mode 100644
index 00000000000..72a64fd6663
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h
@@ -0,0 +1,391 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_IMPL_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/webrtc/api/dtls_transport_interface.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/sctp_transport_interface.h"
+#include "third_party/webrtc/api/stats/rtc_stats_report.h"
+#include "third_party/webrtc/api/test/dummy_peer_connection.h"
+
+namespace blink {
+
+class MockPeerConnectionDependencyFactory;
+class MockStreamCollection;
+
+class FakeRtpSender : public webrtc::RtpSenderInterface {
+ public:
+ FakeRtpSender(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ std::vector<std::string> stream_ids);
+ ~FakeRtpSender() override;
+
+ bool SetTrack(webrtc::MediaStreamTrackInterface* track) override;
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> dtls_transport()
+ const override;
+ uint32_t ssrc() const override;
+ cricket::MediaType media_type() const override;
+ std::string id() const override;
+ std::vector<std::string> stream_ids() const override;
+ std::vector<webrtc::RtpEncodingParameters> init_send_encodings()
+ const override;
+ webrtc::RtpParameters GetParameters() const override;
+ webrtc::RTCError SetParameters(
+ const webrtc::RtpParameters& parameters) override;
+ rtc::scoped_refptr<webrtc::DtmfSenderInterface> GetDtmfSender()
+ const override;
+ void SetTransport(
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
+ transport_ = transport;
+ }
+
+ private:
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport_;
+ std::vector<std::string> stream_ids_;
+};
+
+class FakeRtpReceiver : public webrtc::RtpReceiverInterface {
+ public:
+ FakeRtpReceiver(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>
+ streams = {});
+ ~FakeRtpReceiver() override;
+
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> dtls_transport()
+ const override;
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams()
+ const override;
+ std::vector<std::string> stream_ids() const override;
+ cricket::MediaType media_type() const override;
+ std::string id() const override;
+ webrtc::RtpParameters GetParameters() const override;
+ bool SetParameters(const webrtc::RtpParameters& parameters) override;
+ void SetObserver(webrtc::RtpReceiverObserverInterface* observer) override;
+ void SetJitterBufferMinimumDelay(
+ absl::optional<double> delay_seconds) override;
+ std::vector<webrtc::RtpSource> GetSources() const override;
+ void SetTransport(
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
+ transport_ = transport;
+ }
+
+ private:
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport_;
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams_;
+};
+
+class FakeRtpTransceiver : public webrtc::RtpTransceiverInterface {
+ public:
+ FakeRtpTransceiver(
+ cricket::MediaType media_type,
+ rtc::scoped_refptr<FakeRtpSender> sender,
+ rtc::scoped_refptr<FakeRtpReceiver> receiver,
+ base::Optional<std::string> mid,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction);
+ ~FakeRtpTransceiver() override;
+
+ FakeRtpTransceiver& operator=(const FakeRtpTransceiver& other) = default;
+
+ cricket::MediaType media_type() const override;
+ absl::optional<std::string> mid() const override;
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override;
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override;
+ bool stopped() const override;
+ webrtc::RtpTransceiverDirection direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection new_direction) override;
+ absl::optional<webrtc::RtpTransceiverDirection> current_direction()
+ const override;
+ void Stop() override;
+ void SetTransport(
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport);
+
+ private:
+ cricket::MediaType media_type_;
+ rtc::scoped_refptr<FakeRtpSender> sender_;
+ rtc::scoped_refptr<FakeRtpReceiver> receiver_;
+ absl::optional<std::string> mid_;
+ bool stopped_;
+ webrtc::RtpTransceiverDirection direction_;
+ absl::optional<webrtc::RtpTransceiverDirection> current_direction_;
+};
+
+class FakeDtlsTransport : public webrtc::DtlsTransportInterface {
+ public:
+ FakeDtlsTransport();
+ rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport() override;
+ webrtc::DtlsTransportInformation Information() override;
+ void RegisterObserver(
+ webrtc::DtlsTransportObserverInterface* observer) override {}
+ void UnregisterObserver() override {}
+};
+
+// TODO(hbos): The use of fakes and mocks is the wrong approach for testing of
+// this. It introduces complexity, is error prone (not testing the right thing
+// and bugs in the mocks). This class is a maintenance burden and should be
+// removed. https://crbug.com/788659
+class MockPeerConnectionImpl : public webrtc::DummyPeerConnection {
+ public:
+ explicit MockPeerConnectionImpl(MockPeerConnectionDependencyFactory* factory,
+ webrtc::PeerConnectionObserver* observer);
+
+ // PeerConnectionInterface implementation.
+ rtc::scoped_refptr<webrtc::StreamCollectionInterface> local_streams()
+ override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ rtc::scoped_refptr<webrtc::StreamCollectionInterface> remote_streams()
+ override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ bool AddStream(webrtc::MediaStreamInterface* local_stream) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+ void RemoveStream(webrtc::MediaStreamInterface* local_stream) override {
+ NOTIMPLEMENTED();
+ }
+ webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ AddTransceiver(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track) override {
+ NOTIMPLEMENTED();
+ return webrtc::RTCErrorOr<
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>();
+ }
+ webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ AddTransceiver(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const webrtc::RtpTransceiverInit& init) override {
+ NOTIMPLEMENTED();
+ return webrtc::RTCErrorOr<
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>();
+ }
+
+ webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ AddTransceiver(cricket::MediaType media_type) override {
+ NOTIMPLEMENTED();
+ return webrtc::RTCErrorOr<
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>();
+ }
+ webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ AddTransceiver(cricket::MediaType media_type,
+ const webrtc::RtpTransceiverInit& init) override {
+ NOTIMPLEMENTED();
+ return webrtc::RTCErrorOr<
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>();
+ }
+
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> CreateSender(
+ const std::string& kind,
+ const std::string& stream_id) override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> AddTrack(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::vector<std::string>& stream_ids) override;
+ bool RemoveTrack(webrtc::RtpSenderInterface* sender) override;
+ std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> GetSenders()
+ const override;
+ std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> GetReceivers()
+ const override;
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ GetTransceivers() const override {
+ return {};
+ }
+ MOCK_CONST_METHOD0(GetSctpTransport,
+ rtc::scoped_refptr<webrtc::SctpTransportInterface>());
+ rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
+ const std::string& label,
+ const webrtc::DataChannelInit* config) override;
+
+ bool GetStats(webrtc::StatsObserver* observer,
+ webrtc::MediaStreamTrackInterface* track,
+ StatsOutputLevel level) override;
+ void GetStats(webrtc::RTCStatsCollectorCallback* callback) override;
+ void GetStats(
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> selector,
+ rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback> callback) override;
+ void GetStats(
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> selector,
+ rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback> callback) override;
+
+ // Call this function to make sure next call to legacy GetStats fail.
+ void SetGetStatsResult(bool result) { getstats_result_ = result; }
+ // Set the report that |GetStats(RTCStatsCollectorCallback*)| returns.
+ void SetGetStatsReport(webrtc::RTCStatsReport* report);
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> LookupDtlsTransportByMid(
+ const std::string& mid) override {
+ return nullptr;
+ }
+
+ SignalingState signaling_state() override {
+ NOTIMPLEMENTED();
+ return PeerConnectionInterface::kStable;
+ }
+ IceConnectionState ice_connection_state() override {
+ NOTIMPLEMENTED();
+ return PeerConnectionInterface::kIceConnectionNew;
+ }
+ IceConnectionState standardized_ice_connection_state() override {
+ NOTIMPLEMENTED();
+ return PeerConnectionInterface::kIceConnectionNew;
+ }
+
+ PeerConnectionState peer_connection_state() override {
+ NOTIMPLEMENTED();
+ return PeerConnectionState::kNew;
+ }
+
+ IceGatheringState ice_gathering_state() override {
+ NOTIMPLEMENTED();
+ return PeerConnectionInterface::kIceGatheringNew;
+ }
+
+ bool StartRtcEventLog(std::unique_ptr<webrtc::RtcEventLogOutput> output,
+ int64_t output_period_ms) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+ bool StartRtcEventLog(
+ std::unique_ptr<webrtc::RtcEventLogOutput> output) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+ void StopRtcEventLog() override { NOTIMPLEMENTED(); }
+
+ MOCK_METHOD0(Close, void());
+
+ const webrtc::SessionDescriptionInterface* local_description() const override;
+ const webrtc::SessionDescriptionInterface* remote_description()
+ const override;
+ const webrtc::SessionDescriptionInterface* current_local_description()
+ const override {
+ return nullptr;
+ }
+ const webrtc::SessionDescriptionInterface* current_remote_description()
+ const override {
+ return nullptr;
+ }
+ const webrtc::SessionDescriptionInterface* pending_local_description()
+ const override {
+ return nullptr;
+ }
+ const webrtc::SessionDescriptionInterface* pending_remote_description()
+ const override {
+ return nullptr;
+ }
+
+ // JSEP01 APIs
+ void CreateOffer(webrtc::CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) override;
+ void CreateAnswer(webrtc::CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) override;
+ MOCK_METHOD2(SetLocalDescription,
+ void(webrtc::SetSessionDescriptionObserver* observer,
+ webrtc::SessionDescriptionInterface* desc));
+ void SetLocalDescriptionWorker(
+ webrtc::SetSessionDescriptionObserver* observer,
+ webrtc::SessionDescriptionInterface* desc);
+ // TODO(hbos): Remove once no longer mandatory to implement.
+ MOCK_METHOD2(SetRemoteDescription,
+ void(webrtc::SetSessionDescriptionObserver* observer,
+ webrtc::SessionDescriptionInterface* desc));
+ void SetRemoteDescription(
+ std::unique_ptr<webrtc::SessionDescriptionInterface> desc,
+ rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>
+ observer) override {
+ SetRemoteDescriptionForMock(&desc, &observer);
+ }
+ // Work-around due to MOCK_METHOD being unable to handle move-only arguments.
+ MOCK_METHOD2(
+ SetRemoteDescriptionForMock,
+ void(std::unique_ptr<webrtc::SessionDescriptionInterface>* desc,
+ rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>*
+ observer));
+ void SetRemoteDescriptionWorker(
+ webrtc::SetSessionDescriptionObserver* observer,
+ webrtc::SessionDescriptionInterface* desc);
+ webrtc::PeerConnectionInterface::RTCConfiguration GetConfiguration() {
+ NOTIMPLEMENTED();
+ return webrtc::PeerConnectionInterface::RTCConfiguration();
+ }
+ webrtc::RTCError SetConfiguration(
+ const RTCConfiguration& configuration) override;
+
+ bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
+ bool RemoveIceCandidates(
+ const std::vector<cricket::Candidate>& candidates) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ webrtc::RTCError SetBitrate(const webrtc::BitrateSettings& bitrate) override;
+
+ void AddRemoteStream(webrtc::MediaStreamInterface* stream);
+
+ const std::string& stream_label() const { return stream_label_; }
+ bool hint_audio() const { return hint_audio_; }
+ bool hint_video() const { return hint_video_; }
+ const std::string& description_sdp() const { return description_sdp_; }
+ const std::string& sdp_mid() const { return sdp_mid_; }
+ int sdp_mline_index() const { return sdp_mline_index_; }
+ const std::string& ice_sdp() const { return ice_sdp_; }
+ webrtc::SessionDescriptionInterface* created_session_description() const {
+ return created_sessiondescription_.get();
+ }
+ webrtc::PeerConnectionObserver* observer() { return observer_; }
+ void set_setconfiguration_error_type(webrtc::RTCErrorType error_type) {
+ setconfiguration_error_type_ = error_type;
+ }
+ static const char kDummyOffer[];
+ static const char kDummyAnswer[];
+
+ protected:
+ ~MockPeerConnectionImpl() override;
+
+ private:
+ // Used for creating MockSessionDescription.
+ MockPeerConnectionDependencyFactory* dependency_factory_;
+
+ std::string stream_label_;
+ std::vector<std::string> local_stream_ids_;
+ rtc::scoped_refptr<MockStreamCollection> remote_streams_;
+ std::vector<rtc::scoped_refptr<FakeRtpSender>> senders_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> local_desc_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> remote_desc_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface>
+ created_sessiondescription_;
+ bool hint_audio_;
+ bool hint_video_;
+ bool getstats_result_;
+ std::string description_sdp_;
+ std::string sdp_mid_;
+ int sdp_mline_index_;
+ std::string ice_sdp_;
+ webrtc::PeerConnectionObserver* observer_;
+ webrtc::RTCErrorType setconfiguration_error_type_ =
+ webrtc::RTCErrorType::NONE;
+ rtc::scoped_refptr<webrtc::RTCStatsReport> stats_report_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionImpl);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_PEER_CONNECTION_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h b/chromium/third_party/blink/public/web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h
new file mode 100644
index 00000000000..f6fdf04922e
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_WEB_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_WEB_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_rtc_ice_candidate.h"
+#include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+
+namespace blink {
+
+class MockWebRTCPeerConnectionHandlerClient
+ : public blink::WebRTCPeerConnectionHandlerClient {
+ public:
+ MockWebRTCPeerConnectionHandlerClient();
+ ~MockWebRTCPeerConnectionHandlerClient() override;
+
+ // WebRTCPeerConnectionHandlerClient implementation.
+ MOCK_METHOD0(NegotiationNeeded, void());
+ MOCK_METHOD1(DidGenerateICECandidate,
+ void(scoped_refptr<blink::WebRTCICECandidate> candidate));
+ MOCK_METHOD4(DidFailICECandidate,
+ void(const blink::WebString& host_candidate,
+ const blink::WebString& url,
+ int error_code,
+ const blink::WebString& error_text));
+ MOCK_METHOD1(DidChangeSignalingState,
+ void(webrtc::PeerConnectionInterface::SignalingState state));
+ MOCK_METHOD1(DidChangeIceGatheringState,
+ void(webrtc::PeerConnectionInterface::IceGatheringState state));
+ MOCK_METHOD1(DidChangeIceConnectionState,
+ void(webrtc::PeerConnectionInterface::IceConnectionState state));
+ MOCK_METHOD1(
+ DidChangePeerConnectionState,
+ void(webrtc::PeerConnectionInterface::PeerConnectionState state));
+ void DidAddReceiverPlanB(
+ std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override {
+ DidAddReceiverPlanBForMock(&web_rtp_receiver);
+ }
+ void DidRemoveReceiverPlanB(
+ std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override {
+ DidRemoveReceiverPlanBForMock(&web_rtp_receiver);
+ }
+ MOCK_METHOD1(DidModifySctpTransport,
+ void(blink::WebRTCSctpTransportSnapshot snapshot));
+ void DidModifyTransceivers(
+ blink::WebVector<std::unique_ptr<blink::WebRTCRtpTransceiver>>
+ web_transceivers,
+ bool is_remote_description) override {
+ DidModifyTransceiversForMock(&web_transceivers, is_remote_description);
+ }
+ MOCK_METHOD1(DidAddRemoteDataChannel,
+ void(scoped_refptr<webrtc::DataChannelInterface>));
+ MOCK_METHOD1(DidNoteInterestingUsage, void(int));
+ MOCK_METHOD0(ReleasePeerConnectionHandler, void());
+
+ // Move-only arguments do not play nicely with MOCK, the workaround is to
+ // EXPECT_CALL with these instead.
+ MOCK_METHOD1(DidAddReceiverPlanBForMock,
+ void(std::unique_ptr<blink::WebRTCRtpReceiver>*));
+ MOCK_METHOD1(DidRemoveReceiverPlanBForMock,
+ void(std::unique_ptr<blink::WebRTCRtpReceiver>*));
+ MOCK_METHOD2(
+ DidModifyTransceiversForMock,
+ void(blink::WebVector<std::unique_ptr<blink::WebRTCRtpTransceiver>>*,
+ bool));
+
+ void didGenerateICECandidateWorker(
+ scoped_refptr<blink::WebRTCICECandidate> candidate);
+ void didAddReceiverWorker(
+ std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers);
+ void didRemoveReceiverWorker(
+ std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers);
+
+ const std::string& candidate_sdp() const { return candidate_sdp_; }
+ const base::Optional<uint16_t>& candidate_mlineindex() const {
+ return candidate_mline_index_;
+ }
+ const std::string& candidate_mid() const { return candidate_mid_; }
+ const blink::WebString& remote_stream_id() const { return remote_stream_id_; }
+
+ private:
+ blink::WebString remote_stream_id_;
+ std::string candidate_sdp_;
+ base::Optional<uint16_t> candidate_mline_index_;
+ std::string candidate_mid_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockWebRTCPeerConnectionHandlerClient);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_MOCK_WEB_RTC_PEER_CONNECTION_HANDLER_CLIENT_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h b/chromium/third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h
new file mode 100644
index 00000000000..851ddd9a8b1
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h
@@ -0,0 +1,191 @@
+// 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_WEB_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/p2p/stunprober/stun_prober.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace cricket {
+class PortAllocator;
+}
+
+namespace media {
+class GpuVideoAcceleratorFactories;
+}
+
+namespace rtc {
+class Thread;
+}
+
+namespace blink {
+
+class IpcNetworkManager;
+class IpcPacketSocketFactory;
+class MdnsResponderAdapter;
+class P2PSocketDispatcher;
+class StunProberTrial;
+class WebLocalFrame;
+class WebRTCPeerConnectionHandler;
+class WebRTCPeerConnectionHandlerClient;
+class WebRtcAudioDeviceImpl;
+
+// Object factory for RTC PeerConnections.
+class BLINK_MODULES_EXPORT PeerConnectionDependencyFactory
+ : base::MessageLoopCurrent::DestructionObserver {
+ public:
+ // TODO(crbug.com/787254): Make this constructor private, when
+ // MockPeerConnectionDependencyFactory gets moved to blink.
+ // (friend class declaration will be needed).
+ PeerConnectionDependencyFactory(bool create_p2p_socket_dispatcher);
+ ~PeerConnectionDependencyFactory() override;
+
+ static PeerConnectionDependencyFactory* GetInstance();
+
+ // Create a RTCPeerConnectionHandler object that implements the
+ // WebKit WebRTCPeerConnectionHandler interface.
+ std::unique_ptr<blink::WebRTCPeerConnectionHandler>
+ CreateRTCPeerConnectionHandler(
+ blink::WebRTCPeerConnectionHandlerClient* client,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ // Create a proxy object for a VideoTrackSource that makes sure it's called on
+ // the correct threads.
+ virtual scoped_refptr<webrtc::VideoTrackSourceInterface>
+ CreateVideoTrackSourceProxy(webrtc::VideoTrackSourceInterface* source);
+
+ // Asks the PeerConnection factory to create a Local MediaStream object.
+ virtual scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
+ const std::string& label);
+
+ // Asks the PeerConnection factory to create a Local VideoTrack object.
+ virtual scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source);
+
+ // Asks the libjingle PeerConnection factory to create a libjingle
+ // PeerConnection object.
+ // The PeerConnection object is owned by PeerConnectionHandler.
+ virtual scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
+ blink::WebLocalFrame* web_frame,
+ webrtc::PeerConnectionObserver* observer);
+
+ // Creates a PortAllocator that uses Chrome IPC sockets and enforces privacy
+ // controls according to the permissions granted on the page.
+ virtual std::unique_ptr<cricket::PortAllocator> CreatePortAllocator(
+ blink::WebLocalFrame* web_frame);
+
+ // Creates an AsyncResolverFactory that uses the networking Mojo service.
+ virtual std::unique_ptr<webrtc::AsyncResolverFactory>
+ CreateAsyncResolverFactory();
+
+ // Creates a libjingle representation of a Session description. Used by a
+ // RTCPeerConnectionHandler instance.
+ virtual webrtc::SessionDescriptionInterface* CreateSessionDescription(
+ const std::string& type,
+ const std::string& sdp,
+ webrtc::SdpParseError* error);
+
+ // Creates a libjingle representation of an ice candidate.
+ virtual webrtc::IceCandidateInterface* CreateIceCandidate(
+ const std::string& sdp_mid,
+ int sdp_mline_index,
+ const std::string& sdp);
+
+ // Returns the most optimistic view of the capabilities of the system for
+ // sending or receiving media of the given kind ("audio" or "video").
+ virtual std::unique_ptr<webrtc::RtpCapabilities> GetSenderCapabilities(
+ const std::string& kind);
+ virtual std::unique_ptr<webrtc::RtpCapabilities> GetReceiverCapabilities(
+ const std::string& kind);
+
+ blink::WebRtcAudioDeviceImpl* GetWebRtcAudioDevice();
+
+ void EnsureInitialized();
+ scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcWorkerThread() const;
+
+ // Returns the rtc::Thread instance associated with the WebRTC worker thread.
+ // TODO(bugs.webrtc.org/9419): Remove once WebRTC can be built as a component.
+ rtc::Thread* GetWebRtcWorkerThreadRtcThread();
+ virtual scoped_refptr<base::SingleThreadTaskRunner>
+ GetWebRtcSignalingTaskRunner();
+
+ protected:
+ virtual const scoped_refptr<webrtc::PeerConnectionFactoryInterface>&
+ GetPcFactory();
+ virtual bool PeerConnectionFactoryCreated();
+
+ // Helper method to create a WebRtcAudioDeviceImpl.
+ void EnsureWebRtcAudioDeviceImpl();
+
+ private:
+ // Implement base::MessageLoopCurrent::DestructionObserver.
+ // This makes sure the libjingle PeerConnectionFactory is released before
+ // the renderer message loop is destroyed.
+ void WillDestroyCurrentMessageLoop() override;
+
+ // Functions related to Stun probing trial to determine how fast we could send
+ // Stun request without being dropped by NAT.
+ void TryScheduleStunProbeTrial();
+ void StartStunProbeTrialOnWorkerThread(const std::string& params);
+
+ // Creates |pc_factory_|, which in turn is used for
+ // creating PeerConnection objects.
+ void CreatePeerConnectionFactory();
+
+ void InitializeSignalingThread(
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ base::WaitableEvent* event);
+
+ void InitializeWorkerThread(rtc::Thread** thread, base::WaitableEvent* event);
+
+ void CreateIpcNetworkManagerOnWorkerThread(
+ base::WaitableEvent* event,
+ std::unique_ptr<MdnsResponderAdapter> mdns_responder);
+ void DeleteIpcNetworkManager();
+ void CleanupPeerConnectionFactory();
+
+ // network_manager_ must be deleted on the worker thread. The network manager
+ // uses |p2p_socket_dispatcher_|.
+ std::unique_ptr<blink::IpcNetworkManager> network_manager_;
+ std::unique_ptr<IpcPacketSocketFactory> socket_factory_;
+
+ scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
+
+ // Dispatches all P2P sockets.
+ scoped_refptr<P2PSocketDispatcher> p2p_socket_dispatcher_;
+
+ scoped_refptr<blink::WebRtcAudioDeviceImpl> audio_device_;
+
+ std::unique_ptr<blink::StunProberTrial> stun_trial_;
+
+ // PeerConnection threads. signaling_thread_ is created from the
+ // "current" chrome thread.
+ rtc::Thread* signaling_thread_;
+ rtc::Thread* worker_thread_;
+ base::Thread chrome_signaling_thread_;
+ base::Thread chrome_worker_thread_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(PeerConnectionDependencyFactory);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_PEER_CONNECTION_DEPENDENCY_FACTORY_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h
new file mode 100644
index 00000000000..a96694f763f
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h
@@ -0,0 +1,179 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_RECEIVER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_RECEIVER_IMPL_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/rtp_receiver_interface.h"
+#include "third_party/webrtc/api/stats/rtc_stats.h"
+
+namespace blink {
+
+// This class represents the state of a receiver; a snapshot of what a
+// webrtc-layer receiver looked like when it was inspected on the signaling
+// thread such that this information can be moved to the main thread in a single
+// PostTask. It is used to surface state changes to make the blink-layer
+// receiver up-to-date.
+//
+// Blink objects live on the main thread and webrtc objects live on the
+// signaling thread. If multiple asynchronous operations begin execution on the
+// main thread they are posted and executed in order on the signaling thread.
+// For example, operation A and operation B are called in JavaScript. When A is
+// done on the signaling thread, webrtc object states will be updated. A
+// callback is posted to the main thread so that blink objects can be updated to
+// match the result of operation A. But if callback A tries to inspect the
+// webrtc objects from the main thread this requires posting back to the
+// signaling thread and waiting, which also includes waiting for the previously
+// posted task: operation B. Inspecting the webrtc object like this does not
+// guarantee you to get the state of operation A.
+//
+// As such, all state changes associated with an operation have to be surfaced
+// in the same callback. This includes copying any states into a separate object
+// so that it can be inspected on the main thread without any additional thread
+// hops.
+//
+// The RtpReceiverState is a snapshot of what the webrtc::RtpReceiverInterface
+// looked like when the RtpReceiverState was created on the signaling thread. It
+// also takes care of initializing track adapters, such that we have access to a
+// blink track corresponding to the webrtc track of the receiver.
+//
+// Except for initialization logic and operator=(), the RtpReceiverState is
+// immutable and only accessible on the main thread.
+//
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed API.
+// Also, consider merging RTCRtpReceiverImpl and RTCRtpReceiver, and removing
+// WebRTCRtpReceiver when all its clients are Onion soup'ed.
+//
+// Last, move away from using std::vector.
+class BLINK_MODULES_EXPORT RtpReceiverState {
+ public:
+ RtpReceiverState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ std::vector<std::string> stream_ids);
+ RtpReceiverState(RtpReceiverState&&);
+ RtpReceiverState(const RtpReceiverState&) = delete;
+ ~RtpReceiverState();
+
+ // This is intended to be used for moving the object from the signaling thread
+ // to the main thread and as such has no thread checks. Once moved to the main
+ // this should only be invoked on the main thread.
+ RtpReceiverState& operator=(RtpReceiverState&&);
+ RtpReceiverState& operator=(const RtpReceiverState&) = delete;
+
+ bool is_initialized() const;
+ void Initialize();
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const;
+ scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver() const;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport()
+ const;
+ webrtc::DtlsTransportInformation webrtc_dtls_transport_information() const;
+
+ const std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>&
+ track_ref() const;
+ const std::vector<std::string>& stream_ids() const;
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport_;
+ webrtc::DtlsTransportInformation webrtc_dtls_transport_information_;
+ bool is_initialized_;
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref_;
+ std::vector<std::string> stream_ids_;
+};
+
+// Used to surface |webrtc::RtpReceiverInterface| to blink. Multiple
+// |RTCRtpReceiverImpl|s could reference the same webrtc receiver; |id| is the
+// value of the pointer to the webrtc receiver.
+class BLINK_MODULES_EXPORT RTCRtpReceiverImpl
+ : public blink::WebRTCRtpReceiver {
+ public:
+ static uintptr_t getId(
+ const webrtc::RtpReceiverInterface* webrtc_rtp_receiver);
+
+ RTCRtpReceiverImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ RtpReceiverState state);
+ RTCRtpReceiverImpl(const RTCRtpReceiverImpl& other);
+ ~RTCRtpReceiverImpl() override;
+
+ RTCRtpReceiverImpl& operator=(const RTCRtpReceiverImpl& other);
+
+ const RtpReceiverState& state() const;
+ void set_state(RtpReceiverState state);
+
+ std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override;
+ uintptr_t Id() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override;
+ webrtc::DtlsTransportInformation DtlsTransportInformation() override;
+
+ const blink::WebMediaStreamTrack& Track() const override;
+ blink::WebVector<blink::WebString> StreamIds() const override;
+ blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> GetSources()
+ override;
+ void GetStats(blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) override;
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() const override;
+ void SetJitterBufferMinimumDelay(
+ base::Optional<double> delay_seconds) override;
+
+ private:
+ class RTCRtpReceiverInternal;
+ struct RTCRtpReceiverInternalTraits;
+
+ scoped_refptr<RTCRtpReceiverInternal> internal_;
+};
+
+class BLINK_MODULES_EXPORT RTCRtpReceiverOnlyTransceiver
+ : public blink::WebRTCRtpTransceiver {
+ public:
+ RTCRtpReceiverOnlyTransceiver(
+ std::unique_ptr<blink::WebRTCRtpReceiver> receiver);
+ ~RTCRtpReceiverOnlyTransceiver() override;
+
+ blink::WebRTCRtpTransceiverImplementationType ImplementationType()
+ const override;
+ uintptr_t Id() const override;
+ blink::WebString Mid() const override;
+ std::unique_ptr<blink::WebRTCRtpSender> Sender() const override;
+ std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override;
+ bool Stopped() const override;
+ webrtc::RtpTransceiverDirection Direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection direction) override;
+ base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection()
+ const override;
+ base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
+ const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
+
+ private:
+ std::unique_ptr<blink::WebRTCRtpReceiver> receiver_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_RECEIVER_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h
new file mode 100644
index 00000000000..dc3c78472b6
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h
@@ -0,0 +1,197 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_SENDER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_SENDER_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_sender.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+#include "third_party/webrtc/api/rtp_sender_interface.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace blink {
+
+// This class represents the state of a sender; a snapshot of what a
+// webrtc-layer sender looked like when it was inspected on the signaling thread
+// such that this information can be moved to the main thread in a single
+// PostTask. It is used to surface state changes to make the blink-layer sender
+// up-to-date.
+//
+// Blink objects live on the main thread and webrtc objects live on the
+// signaling thread. If multiple asynchronous operations begin execution on the
+// main thread they are posted and executed in order on the signaling thread.
+// For example, operation A and operation B are called in JavaScript. When A is
+// done on the signaling thread, webrtc object states will be updated. A
+// callback is posted to the main thread so that blink objects can be updated to
+// match the result of operation A. But if callback A tries to inspect the
+// webrtc objects from the main thread this requires posting back to the
+// signaling thread and waiting, which also includes waiting for the previously
+// posted task: operation B. Inspecting the webrtc object like this does not
+// guarantee you to get the state of operation A.
+//
+// As such, all state changes associated with an operation have to be surfaced
+// in the same callback. This includes copying any states into a separate object
+// so that it can be inspected on the main thread without any additional thread
+// hops.
+//
+// The RtpSenderState is a snapshot of what the webrtc::RtpSenderInterface
+// looked like when the RtpSenderState was created on the signaling thread. It
+// also takes care of initializing track adapters, such that we have access to a
+// blink track corresponding to the webrtc track of the sender.
+//
+// Except for initialization logic and operator=(), the RtpSenderState is
+// immutable and only accessible on the main thread.
+//
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed API.
+// Also, consider merging RTCRtpSenderImpl and RTCRtpReceiver, and removing
+// WebRTCRtpSender when all its clients are Onion soup'ed.
+//
+// Last, move away from using std::vector.
+class BLINK_MODULES_EXPORT RtpSenderState {
+ public:
+ RtpSenderState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ std::vector<std::string> stream_ids);
+ RtpSenderState(RtpSenderState&&);
+ RtpSenderState(const RtpSenderState&) = delete;
+ ~RtpSenderState();
+
+ // This is intended to be used for moving the object from the signaling thread
+ // to the main thread and as such has no thread checks. Once moved to the main
+ // this should only be invoked on the main thread.
+ RtpSenderState& operator=(RtpSenderState&&);
+ RtpSenderState& operator=(const RtpSenderState&) = delete;
+
+ bool is_initialized() const;
+ void Initialize();
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const;
+ scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender() const;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport()
+ const;
+ webrtc::DtlsTransportInformation webrtc_dtls_transport_information() const;
+ const std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>&
+ track_ref() const;
+ void set_track_ref(
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref);
+ std::vector<std::string> stream_ids() const;
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> webrtc_dtls_transport_;
+ webrtc::DtlsTransportInformation webrtc_dtls_transport_information_;
+ bool is_initialized_;
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref_;
+ std::vector<std::string> stream_ids_;
+};
+
+// Used to surface |webrtc::RtpSenderInterface| to blink. Multiple
+// |RTCRtpSenderImpl|s could reference the same webrtc sender; |id| is the value
+// of the pointer to the webrtc sender.
+// TODO(hbos): [Onion Soup] Move all of the implementation inside the blink
+// object and remove this class and interface. The blink object is reference
+// counted and we can get rid of this "Web"-copyable with "internal" nonsense,
+// all the blink object will need is the RtpSenderState. Requires coordination
+// with transceivers and receivers since these are tightly coupled.
+// https://crbug.com/787254
+class BLINK_MODULES_EXPORT RTCRtpSenderImpl : public blink::WebRTCRtpSender {
+ public:
+ static uintptr_t getId(const webrtc::RtpSenderInterface* webrtc_sender);
+
+ RTCRtpSenderImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpSenderState state);
+ RTCRtpSenderImpl(const RTCRtpSenderImpl& other);
+ ~RTCRtpSenderImpl() override;
+ RTCRtpSenderImpl& operator=(const RTCRtpSenderImpl& other);
+
+ const RtpSenderState& state() const;
+ void set_state(RtpSenderState state);
+
+ // blink::WebRTCRtpSender.
+ std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override;
+ uintptr_t Id() const override;
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> DtlsTransport() override;
+ webrtc::DtlsTransportInformation DtlsTransportInformation() override;
+ blink::WebMediaStreamTrack Track() const override;
+ blink::WebVector<blink::WebString> StreamIds() const override;
+ void ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ blink::WebRTCVoidRequest request) override;
+ std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender()
+ const override;
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() const override;
+ void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>,
+ webrtc::DegradationPreference,
+ blink::WebRTCVoidRequest) override;
+ void GetStats(blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) override;
+ void SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) override;
+
+ // The ReplaceTrack() that takes a blink::WebRTCVoidRequest is implemented on
+ // top of this, which returns the result in a callback instead. Allows doing
+ // ReplaceTrack() without having a blink::WebRTCVoidRequest, which can only be
+ // constructed inside of blink.
+ void ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ base::OnceCallback<void(bool)> callback);
+ bool RemoveFromPeerConnection(webrtc::PeerConnectionInterface* pc);
+
+ private:
+ class RTCRtpSenderInternal;
+ struct RTCRtpSenderInternalTraits;
+
+ scoped_refptr<RTCRtpSenderInternal> internal_;
+};
+
+class BLINK_MODULES_EXPORT RTCRtpSenderOnlyTransceiver
+ : public blink::WebRTCRtpTransceiver {
+ public:
+ explicit RTCRtpSenderOnlyTransceiver(
+ std::unique_ptr<blink::WebRTCRtpSender> sender);
+ ~RTCRtpSenderOnlyTransceiver() override;
+
+ blink::WebRTCRtpTransceiverImplementationType ImplementationType()
+ const override;
+ uintptr_t Id() const override;
+ blink::WebString Mid() const override;
+ std::unique_ptr<blink::WebRTCRtpSender> Sender() const override;
+ std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override;
+ bool Stopped() const override;
+ webrtc::RtpTransceiverDirection Direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection direction) override;
+ base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection()
+ const override;
+ base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
+ const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
+
+ private:
+ std::unique_ptr<blink::WebRTCRtpSender> sender_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_SENDER_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h
new file mode 100644
index 00000000000..57a951131a7
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h
@@ -0,0 +1,195 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_IMPL_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_IMPL_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/webrtc/api/rtp_transceiver_interface.h"
+
+namespace blink {
+
+// This class represents the state of a transceiver; a snapshot of what a
+// webrtc-layer transceiver looked like when it was inspected on the signaling
+// thread such that this information can be moved to the main thread in a single
+// PostTask. It is used to surface state changes to make the blink-layer
+// transceiver up-to-date.
+//
+// Blink objects live on the main thread and webrtc objects live on the
+// signaling thread. If multiple asynchronous operations begin execution on the
+// main thread they are posted and executed in order on the signaling thread.
+// For example, operation A and operation B are called in JavaScript. When A is
+// done on the signaling thread, webrtc object states will be updated. A
+// callback is posted to the main thread so that blink objects can be updated to
+// match the result of operation A. But if callback A tries to inspect the
+// webrtc objects from the main thread this requires posting back to the
+// signaling thread and waiting, which also includes waiting for the previously
+// posted task: operation B. Inspecting the webrtc object like this does not
+// guarantee you to get the state of operation A.
+//
+// As such, all state changes associated with an operation have to be surfaced
+// in the same callback. This includes copying any states into a separate object
+// so that it can be inspected on the main thread without any additional thread
+// hops.
+//
+// The RtpTransceiverState is a snapshot of what the
+// webrtc::RtpTransceiverInterface looked like when the RtpTransceiverState was
+// created on the signaling thread. It also takes care of initializing sender
+// and receiver states, including their track adapters such that we have access
+// to a blink track corresponding to the webrtc tracks of the sender and
+// receiver.
+//
+// Except for initialization logic and operator=(), the RtpTransceiverState is
+// immutable and only accessible on the main thread.
+//
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed API.
+// Also, consider merging RTCRtpTransceiverImpl and RTCRtpTransceiver
+// (requires coordination with senders and receivers) and
+// removing WebRTCRtpTransceiver when all its clients are Onion soup'ed.
+//
+// Last, move away from using std::vector.
+class BLINK_MODULES_EXPORT RtpTransceiverState {
+ public:
+ RtpTransceiverState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver,
+ base::Optional<blink::RtpSenderState> sender_state,
+ base::Optional<blink::RtpReceiverState> receiver_state,
+ base::Optional<std::string> mid,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction,
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction);
+ RtpTransceiverState(RtpTransceiverState&&);
+ RtpTransceiverState(const RtpTransceiverState&) = delete;
+ ~RtpTransceiverState();
+
+ // This is intended to be used for moving the object from the signaling thread
+ // to the main thread and as such has no thread checks. Once moved to the main
+ // this should only be invoked on the main thread.
+ RtpTransceiverState& operator=(RtpTransceiverState&&);
+ RtpTransceiverState& operator=(const RtpTransceiverState&) = delete;
+
+ bool is_initialized() const;
+ void Initialize();
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const;
+ scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver() const;
+ const base::Optional<blink::RtpSenderState>& sender_state() const;
+ blink::RtpSenderState MoveSenderState();
+ const base::Optional<blink::RtpReceiverState>& receiver_state() const;
+ blink::RtpReceiverState MoveReceiverState();
+ base::Optional<std::string> mid() const;
+ bool stopped() const;
+ webrtc::RtpTransceiverDirection direction() const;
+ void set_direction(webrtc::RtpTransceiverDirection);
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction() const;
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction() const;
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_;
+ bool is_initialized_;
+ base::Optional<blink::RtpSenderState> sender_state_;
+ base::Optional<blink::RtpReceiverState> receiver_state_;
+ base::Optional<std::string> mid_;
+ bool stopped_;
+ webrtc::RtpTransceiverDirection direction_;
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction_;
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction_;
+};
+
+// RTCRtpTransceiverImpl::set_state() performs differently depending on the
+// update mode. The update mode exists to get around problems with the webrtc
+// threading model: https://crbug.com/webrtc/8692.
+//
+// Transceiver state information can be surfaced as a result of invoking a
+// number of different JavaScript APIs. The way states are surfaced from webrtc
+// to blink fall into two categories:
+// Blocking operations and callback-based operations.
+//
+// When a blocking operation is invoked, the main thread is blocked on the
+// webrtc signaling thread, and the state information is surfaced immediately
+// - guaranteed to be up-to-date. An example of this is addTrack().
+// Callback-based operations on the other hand will post a task from the
+// signaling thread to the main thread, placing the task to update the state
+// information in queue. There is no guarantee that something - such as
+// addTrack() - doesn't happen in-between the posting of the task and the
+// execution of it. In such cases, the state information surfaced might not be
+// up-to-date (in edge cases). Examples of callback-based operations include
+// setLocalDescripti.on() and setRemoteDescription().
+enum class TransceiverStateUpdateMode {
+ // In this mode, all state information is updated. Use this enum unless
+ // a different update mode applies.
+ kAll,
+ // Use this enum when surfacing state information as a result of
+ // setLocalDescription() or setRemoteDescription().
+ // Behaves like "kAll" except "transceiver.sender.track" and
+ // "transceiver.direction" are not updated.
+ kSetDescription,
+};
+
+// Used to surface |webrtc::RtpTransceiverInterface| to blink. Multiple
+// |RTCRtpTransceiverImpl|s could reference the same webrtc transceiver; |id| is
+// unique per webrtc transceiver.
+// Its methods are accessed on the main thread, internally also performs
+// operations on the signaling thread.
+class BLINK_MODULES_EXPORT RTCRtpTransceiverImpl
+ : public blink::WebRTCRtpTransceiver {
+ public:
+ static uintptr_t GetId(
+ const webrtc::RtpTransceiverInterface* webrtc_transceiver);
+
+ RTCRtpTransceiverImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpTransceiverState state);
+ RTCRtpTransceiverImpl(const RTCRtpTransceiverImpl& other);
+ ~RTCRtpTransceiverImpl() override;
+
+ RTCRtpTransceiverImpl& operator=(const RTCRtpTransceiverImpl& other);
+ std::unique_ptr<RTCRtpTransceiverImpl> ShallowCopy() const;
+
+ const RtpTransceiverState& state() const;
+ void set_state(RtpTransceiverState state,
+ TransceiverStateUpdateMode update_mode);
+ blink::RTCRtpSenderImpl* content_sender();
+ blink::RTCRtpReceiverImpl* content_receiver();
+
+ blink::WebRTCRtpTransceiverImplementationType ImplementationType()
+ const override;
+ uintptr_t Id() const override;
+ blink::WebString Mid() const override;
+ std::unique_ptr<blink::WebRTCRtpSender> Sender() const override;
+ std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override;
+ bool Stopped() const override;
+ webrtc::RtpTransceiverDirection Direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection direction) override;
+ base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection()
+ const override;
+ base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
+ const override;
+ webrtc::RTCError SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) override;
+
+ private:
+ class RTCRtpTransceiverInternal;
+ struct RTCRtpTransceiverInternalTraits;
+
+ scoped_refptr<RTCRtpTransceiverInternal> internal_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_IMPL_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h b/chromium/third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h
new file mode 100644
index 00000000000..1668faa1621
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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_MODULES_PEERCONNECTION_TRANSCEIVER_STATE_SURFACER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_TRANSCEIVER_STATE_SURFACER_H_
+
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h"
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/webrtc/api/rtp_transceiver_interface.h"
+#include "third_party/webrtc/api/sctp_transport_interface.h"
+#include "third_party/webrtc/rtc_base/ref_count.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+namespace blink {
+
+// Takes care of creating and initializing transceiver states (including sender
+// and receiver states). This is usable for both blocking and non-blocking calls
+// to the webrtc signaling thread.
+//
+// The surfacer is initialized on the signaling thread and states are obtained
+// on the main thread. It is designed to be initialized and handed off; it is
+// not thread safe for concurrent thread usage.
+//
+// TODO(crbug.com/787254): Move this class out of the Blink API when all its
+// client get moved to Blink. Also move it away from using std::vector.
+class BLINK_MODULES_EXPORT TransceiverStateSurfacer {
+ public:
+ TransceiverStateSurfacer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner);
+ TransceiverStateSurfacer(TransceiverStateSurfacer&&);
+ TransceiverStateSurfacer(const TransceiverStateSurfacer&) = delete;
+ ~TransceiverStateSurfacer();
+
+ // This is intended to be used for moving the object from the signaling thread
+ // to the main thread and as such has no thread checks. Once moved to the main
+ // this should only be invoked on the main thread.
+ TransceiverStateSurfacer& operator=(TransceiverStateSurfacer&&);
+ TransceiverStateSurfacer& operator=(const TransceiverStateSurfacer&) = delete;
+
+ bool is_initialized() const { return is_initialized_; }
+
+ // Must be invoked on the signaling thread.
+ void Initialize(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers);
+
+ // Must be invoked on the main thread.
+ blink::WebRTCSctpTransportSnapshot SctpTransportSnapshot();
+ std::vector<blink::RtpTransceiverState> ObtainStates();
+
+ protected:
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ bool is_initialized_;
+ bool states_obtained_;
+ blink::WebRTCSctpTransportSnapshot sctp_transport_snapshot_;
+ std::vector<blink::RtpTransceiverState> transceiver_states_;
+};
+
+// A dummy implementation of a transceiver used to surface sender state
+// information only. It is not thread safe, only designed to be passed on to
+// TransceiverStateSurfacer::Initialize().
+class BLINK_MODULES_EXPORT SurfaceSenderStateOnly
+ : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> {
+ public:
+ SurfaceSenderStateOnly(rtc::scoped_refptr<webrtc::RtpSenderInterface> sender);
+ ~SurfaceSenderStateOnly() override;
+
+ cricket::MediaType media_type() const override;
+ absl::optional<std::string> mid() const override;
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override;
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override;
+ bool stopped() const override;
+ webrtc::RtpTransceiverDirection direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection new_direction) override;
+ absl::optional<webrtc::RtpTransceiverDirection> current_direction()
+ const override;
+ void Stop() override;
+
+ private:
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_;
+};
+
+// A dummy implementation of a transceiver used to surface receiver state
+// information only. It is not thread safe, only designed to be passed on to
+// TransceiverStateSurfacer::Initialize().
+class BLINK_MODULES_EXPORT SurfaceReceiverStateOnly
+ : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> {
+ public:
+ SurfaceReceiverStateOnly(
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver);
+ ~SurfaceReceiverStateOnly() override;
+
+ cricket::MediaType media_type() const override;
+ absl::optional<std::string> mid() const override;
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override;
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override;
+ bool stopped() const override;
+ webrtc::RtpTransceiverDirection direction() const override;
+ void SetDirection(webrtc::RtpTransceiverDirection new_direction) override;
+ absl::optional<webrtc::RtpTransceiverDirection> current_direction()
+ const override;
+ void Stop() override;
+
+ private:
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_TRANSCEIVER_STATE_SURFACER_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h
new file mode 100644
index 00000000000..21cc8af7e6a
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h
@@ -0,0 +1,153 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_H_
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/waitable_event.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_audio_sink.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/web/modules/mediastream/remote_media_stream_track_adapter.h"
+#include "third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+
+namespace blink {
+
+class PeerConnectionDependencyFactory;
+struct WebRtcMediaStreamTrackAdapterTraits;
+
+// This is a mapping between a webrtc and blink media stream track. It takes
+// care of creation, initialization and disposing of tracks independently of
+// media streams.
+// There are different sinks/adapters used whether the track is local or remote
+// and whether it is an audio or video track; this adapter hides that fact and
+// lets you use a single class for any type of track.
+//
+// TODO(crbug.com/787254): Move the classes below out of the Blink exposed
+// API when all users of it have been Onion souped.
+class BLINK_MODULES_EXPORT WebRtcMediaStreamTrackAdapter
+ : public base::RefCountedThreadSafe<WebRtcMediaStreamTrackAdapter,
+ WebRtcMediaStreamTrackAdapterTraits> {
+ public:
+ // Invoke on the main thread. The returned adapter is fully initialized, see
+ // |is_initialized|. The adapter will keep a reference to the |main_thread|.
+ static scoped_refptr<WebRtcMediaStreamTrackAdapter> CreateLocalTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ const blink::WebMediaStreamTrack& web_track);
+ // Invoke on the webrtc signaling thread. Initialization finishes on the main
+ // thread in a post, meaning returned adapters are ensured to be initialized
+ // in posts to the main thread, see |is_initialized|. The adapter will keep
+ // references to the |main_thread| and |webrtc_track|.
+ static scoped_refptr<WebRtcMediaStreamTrackAdapter> CreateRemoteTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ const scoped_refptr<webrtc::MediaStreamTrackInterface>& webrtc_track);
+ // Must be called before all external references are released (i.e. before
+ // destruction). Invoke on the main thread. Disposing may finish
+ // asynchronously using the webrtc signaling thread and the main thread. After
+ // calling this method it is safe to release all external references to the
+ // adapter.
+ void Dispose();
+
+ bool is_initialized() const;
+ void InitializeOnMainThread();
+ // These methods must be called on the main thread.
+ // TODO(hbos): Allow these methods to be called on any thread and make them
+ // const. https://crbug.com/756436
+ const blink::WebMediaStreamTrack& web_track();
+ webrtc::MediaStreamTrackInterface* webrtc_track();
+ bool IsEqual(const blink::WebMediaStreamTrack& web_track);
+
+ // For testing.
+ blink::WebRtcAudioSink* GetLocalTrackAudioSinkForTesting() {
+ return local_track_audio_sink_.get();
+ }
+ blink::MediaStreamVideoWebRtcSink* GetLocalTrackVideoSinkForTesting() {
+ return local_track_video_sink_.get();
+ }
+ blink::RemoteAudioTrackAdapter* GetRemoteAudioTrackAdapterForTesting() {
+ return remote_audio_track_adapter_.get();
+ }
+ blink::RemoteVideoTrackAdapter* GetRemoteVideoTrackAdapterForTesting() {
+ return remote_video_track_adapter_.get();
+ }
+
+ protected:
+ friend class base::RefCountedThreadSafe<WebRtcMediaStreamTrackAdapter,
+ WebRtcMediaStreamTrackAdapterTraits>;
+ friend struct WebRtcMediaStreamTrackAdapterTraits;
+
+ WebRtcMediaStreamTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread);
+ virtual ~WebRtcMediaStreamTrackAdapter();
+
+ private:
+ // Initialization of local tracks occurs on the main thread.
+ void InitializeLocalAudioTrack(const blink::WebMediaStreamTrack& web_track);
+ void InitializeLocalVideoTrack(const blink::WebMediaStreamTrack& web_track);
+ // Initialization of remote tracks starts on the webrtc signaling thread and
+ // finishes on the main thread.
+ void InitializeRemoteAudioTrack(
+ const scoped_refptr<webrtc::AudioTrackInterface>& webrtc_audio_track);
+ void InitializeRemoteVideoTrack(
+ const scoped_refptr<webrtc::VideoTrackInterface>& webrtc_video_track);
+ void FinalizeRemoteTrackInitializationOnMainThread();
+ void EnsureTrackIsInitialized();
+
+ // Disposing starts and finishes on the main thread. Local tracks and remote
+ // video tracks are disposed synchronously. Remote audio tracks are disposed
+ // asynchronously with a jump to the webrtc signaling thread and back.
+ void DisposeLocalAudioTrack();
+ void DisposeLocalVideoTrack();
+ void DisposeRemoteAudioTrack();
+ void DisposeRemoteVideoTrack();
+ void UnregisterRemoteAudioTrackAdapterOnSignalingThread();
+ void FinalizeRemoteTrackDisposingOnMainThread();
+
+ // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|.
+ // It's valid for the lifetime of |RenderThread|.
+ blink::PeerConnectionDependencyFactory* const factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+
+ // Part of the initialization of remote tracks occurs on the signaling thread.
+ // |remote_track_can_complete_initialization_| allows waiting until that part
+ // of the process is finished, so that full initialization of the track can be
+ // completed on the main thread.
+ base::WaitableEvent remote_track_can_complete_initialization_;
+ bool is_initialized_;
+ bool is_disposed_;
+ blink::WebMediaStreamTrack web_track_;
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
+ // If the track is local, a sink is added to the local webrtc track that is
+ // owned by us.
+ std::unique_ptr<blink::WebRtcAudioSink> local_track_audio_sink_;
+ std::unique_ptr<blink::MediaStreamVideoWebRtcSink> local_track_video_sink_;
+ // If the track is remote, an adapter is used that listens to notifications on
+ // the remote webrtc track and notifies Blink.
+ scoped_refptr<blink::RemoteAudioTrackAdapter> remote_audio_track_adapter_;
+ scoped_refptr<blink::RemoteVideoTrackAdapter> remote_video_track_adapter_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamTrackAdapter);
+};
+
+struct BLINK_MODULES_EXPORT WebRtcMediaStreamTrackAdapterTraits {
+ private:
+ friend class base::RefCountedThreadSafe<WebRtcMediaStreamTrackAdapter,
+ WebRtcMediaStreamTrackAdapterTraits>;
+
+ // Ensure destruction occurs on main thread so that "Web" and other resources
+ // are destroyed on the correct thread.
+ static void Destruct(const WebRtcMediaStreamTrackAdapter* adapter);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h
new file mode 100644
index 00000000000..edcb224b345
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_MAP_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_MAP_H_
+
+#include "base/memory/ref_counted.h"
+#include "third_party/blink/public/platform/modules/peerconnection/two_keys_adapter_map.h"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+class PeerConnectionDependencyFactory;
+
+// A map and owner of |WebRtcMediaStreamTrackAdapter|s. It takes care of
+// creating, initializing and disposing track adapters independently of media
+// streams. Adapters are accessed via |AdapterRef|s, when all references to an
+// adapter are destroyed it is disposed and removed from the map.
+//
+// TODO(crbug.com/787254): Move the class below out of the Blink exposed
+// API when all users of it have been Onion souped.
+class BLINK_MODULES_EXPORT WebRtcMediaStreamTrackAdapterMap
+ : public base::RefCountedThreadSafe<WebRtcMediaStreamTrackAdapterMap> {
+ public:
+ // Acts as an accessor to adapter members without leaking a reference to the
+ // adapter. When the last |AdapterRef| is destroyed, the corresponding adapter
+ // is |Dispose|d and removed from the map.
+ class BLINK_MODULES_EXPORT AdapterRef {
+ public:
+ // Must be invoked on the main thread. If this was the last reference to the
+ // adapter it will be disposed and removed from the map.
+ ~AdapterRef();
+
+ std::unique_ptr<AdapterRef> Copy() const;
+ bool is_initialized() const { return adapter_->is_initialized(); }
+ void InitializeOnMainThread();
+ const blink::WebMediaStreamTrack& web_track() const {
+ return adapter_->web_track();
+ }
+ webrtc::MediaStreamTrackInterface* webrtc_track() const {
+ return adapter_->webrtc_track();
+ }
+
+ // Warning: Holding an external reference to the adapter will prevent
+ // |~AdapterRef| from disposing the adapter.
+ blink::WebRtcMediaStreamTrackAdapter* GetAdapterForTesting() const {
+ return adapter_.get();
+ }
+
+ private:
+ friend class WebRtcMediaStreamTrackAdapterMap;
+
+ enum class Type { kLocal, kRemote };
+
+ // Assumes map's |lock_| is held.
+ AdapterRef(scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map,
+ Type type,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> adapter);
+
+ scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map_;
+ Type type_;
+ // A reference to the entry's adapter, ensures that |HasOneRef()| is false
+ // as long as the |AdapterRef| is kept alive (the map entry has one
+ // reference to it too).
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> adapter_;
+ };
+
+ // Must be invoked on the main thread.
+ WebRtcMediaStreamTrackAdapterMap(
+ blink::PeerConnectionDependencyFactory* const factory,
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread);
+
+ // Gets a new reference to the local track adapter, or null if no such adapter
+ // was found. When all references are destroyed the adapter is disposed and
+ // removed from the map. This method can be called from any thread, but
+ // references must be destroyed on the main thread.
+ // The adapter is a associated with a blink and webrtc track, lookup works by
+ // either track.
+ std::unique_ptr<AdapterRef> GetLocalTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track);
+ std::unique_ptr<AdapterRef> GetLocalTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track);
+ // Invoke on the main thread. Gets a new reference to the local track adapter
+ // for the web track. If no adapter exists for the track one is created and
+ // initialized. When all references are destroyed the adapter is disposed and
+ // removed from the map. References must be destroyed on the main thread.
+ std::unique_ptr<AdapterRef> GetOrCreateLocalTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track);
+ size_t GetLocalTrackCount() const;
+
+ // Gets a new reference to the remote track adapter. When all references are
+ // destroyed the adapter is disposed and removed from the map. This method can
+ // be called from any thread, but references must be destroyed on the main
+ // thread. The adapter is a associated with a blink and webrtc track, lookup
+ // works by either track.
+ // First variety: If an adapter exists it will already be initialized, if one
+ // does not exist null is returned.
+ std::unique_ptr<AdapterRef> GetRemoteTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track);
+ // Second variety: If an adapter exists it may or may not be initialized, see
+ // |AdapterRef::is_initialized|. If an adapter does not exist null is
+ // returned.
+ std::unique_ptr<AdapterRef> GetRemoteTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track);
+ // Invoke on the webrtc signaling thread. Gets a new reference to the remote
+ // track adapter for the webrtc track. If no adapter exists for the track one
+ // is created and initialization completes on the main thread in a post. When
+ // all references are destroyed the adapter is disposed and removed from the
+ // map. References must be destroyed on the main thread.
+ std::unique_ptr<AdapterRef> GetOrCreateRemoteTrackAdapter(
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track);
+ size_t GetRemoteTrackCount() const;
+
+ private:
+ friend class base::RefCountedThreadSafe<WebRtcMediaStreamTrackAdapterMap>;
+
+ // "(blink::WebMediaStreamTrack, webrtc::MediaStreamTrackInterface) ->
+ // WebRtcMediaStreamTrackAdapter" maps. The primary key is based on the object
+ // used to create the adapter. Local tracks are created from
+ // |blink::WebMediaStreamTrack|s, remote tracks are created from
+ // |webrtc::MediaStreamTrackInterface|s.
+ // The adapter keeps the |webrtc::MediaStreamTrackInterface| alive with ref
+ // counting making it safe to use a raw pointer for key.
+ using LocalTrackAdapterMap = blink::TwoKeysAdapterMap<
+ int, // blink::WebMediaStreamTrack::UniqueId()
+ webrtc::MediaStreamTrackInterface*,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>>;
+ using RemoteTrackAdapterMap = blink::TwoKeysAdapterMap<
+ webrtc::MediaStreamTrackInterface*,
+ int, // blink::WebMediaStreamTrack::UniqueId()
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>>;
+
+ // Invoke on the main thread.
+ virtual ~WebRtcMediaStreamTrackAdapterMap();
+
+ // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|.
+ // It's valid for the lifetime of |RenderThread|.
+ blink::PeerConnectionDependencyFactory* const factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+
+ mutable base::Lock lock_;
+ LocalTrackAdapterMap local_track_adapters_;
+ RemoteTrackAdapterMap remote_track_adapters_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_MEDIA_STREAM_TRACK_ADAPTER_MAP_H_
diff --git a/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h
new file mode 100644
index 00000000000..db74237665a
--- /dev/null
+++ b/chromium/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_
+#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+
+namespace blink {
+
+// The obtainer is a test-only helper class capable of waiting for a GetStats()
+// callback to be called. It takes ownership of and exposes the resulting
+// blink::WebRTCStatsReport.
+// While WaitForReport() is waiting for the report, tasks posted on the current
+// thread are executed (see base::RunLoop::Run()) making it safe to wait on the
+// same thread that the stats report callback occurs on without blocking the
+// callback.
+//
+// TODO(crbug.com/787254): Move this class out of the Blink API
+// when all its clients get Onion souped.
+class WebRTCStatsReportObtainer
+ : public base::RefCountedThreadSafe<WebRTCStatsReportObtainer> {
+ public:
+ WebRTCStatsReportObtainer();
+
+ blink::WebRTCStatsReportCallback GetStatsCallbackWrapper();
+
+ blink::WebRTCStatsReport* report() const;
+ blink::WebRTCStatsReport* WaitForReport();
+
+ private:
+ friend class base::RefCountedThreadSafe<WebRTCStatsReportObtainer>;
+ friend class CallbackWrapper;
+ virtual ~WebRTCStatsReportObtainer();
+
+ void OnStatsDelivered(std::unique_ptr<blink::WebRTCStatsReport> report);
+
+ base::RunLoop run_loop_;
+ std::unique_ptr<blink::WebRTCStatsReport> report_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_
diff --git a/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h b/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
index 98de58420df..324a3da58f5 100644
--- a/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
+++ b/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
@@ -81,18 +81,12 @@ class WebServiceWorkerContextClient {
mojo::ScopedMessagePipeHandle devtools_agent_ptr_info,
mojo::ScopedMessagePipeHandle devtools_agent_host_request) {}
- // Starting the worker failed. This could happen when loading the worker
- // script failed, or the worker was asked to terminate before startup
- // completed. Called on the initiator thread.
- virtual void WorkerContextFailedToStartOnInitiatorThread() {}
-
- // The worker started but it could not execute because loading the classic
- // script failed on the worker thread. This is called only for installed
- // scripts fetch or off-the-main-thread classic worker script fetch.
- virtual void FailedToLoadClassicScript() {}
+ // The worker started but it could not execute because fetching the classic
+ // script failed on the worker thread.
+ virtual void FailedToFetchClassicScript() {}
// The worker started but it could not execute because fetching module script
- // failed.
+ // failed on the worker thread.
virtual void FailedToFetchModuleScript() {}
// The worker script was successfully loaded on the worker thread.
diff --git a/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h b/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h
index f9a4ed9eb0b..baa7d088d9f 100644
--- a/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h
+++ b/chromium/third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h
@@ -69,6 +69,8 @@ class WebServiceWorkerContextProxy {
int64_t decoded_body_length) = 0;
virtual bool IsWindowInteractionAllowed() = 0;
+ virtual void PauseEvaluation() = 0;
+ virtual void ResumeEvaluation() = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_ax_enums.h b/chromium/third_party/blink/public/web/web_ax_enums.h
index 043848278bb..42e333c37f6 100644
--- a/chromium/third_party/blink/public/web/web_ax_enums.h
+++ b/chromium/third_party/blink/public/web/web_ax_enums.h
@@ -73,6 +73,13 @@ enum WebAXRestriction {
kWebAXRestrictionDisabled,
};
+// Autofill state.
+enum WebAXAutofillState {
+ kNoSuggestions = 0,
+ kAutofillAvailable,
+ kAutocompleteAvailable,
+};
+
//
// Sparse accessibility attributes
//
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 7d946aedffe..8e83e466d90 100644
--- a/chromium/third_party/blink/public/web/web_ax_object.h
+++ b/chromium/third_party/blink/public/web/web_ax_object.h
@@ -158,7 +158,7 @@ class WebAXObject {
BLINK_EXPORT void ColorValue(int& r, int& g, int& b) const;
BLINK_EXPORT unsigned ColorValue() const;
BLINK_EXPORT WebAXObject AriaActiveDescendant() const;
- BLINK_EXPORT WebString AriaAutoComplete() const;
+ BLINK_EXPORT WebString AutoComplete() const;
BLINK_EXPORT ax::mojom::AriaCurrentState AriaCurrentState() const;
BLINK_EXPORT ax::mojom::HasPopup HasPopup() const;
BLINK_EXPORT bool IsEditableRoot() const;
@@ -383,7 +383,7 @@ class WebAXObject {
BLINK_EXPORT WebString ToString() const;
BLINK_EXPORT void HandleAutofillStateChanged(
- bool suggestions_available) const;
+ const WebAXAutofillState state) const;
#if INSIDE_BLINK
BLINK_EXPORT WebAXObject(AXObject*);
diff --git a/chromium/third_party/blink/public/web/web_device_emulation_params.h b/chromium/third_party/blink/public/web/web_device_emulation_params.h
index c11b505d5e3..a9d6de84c48 100644
--- a/chromium/third_party/blink/public/web/web_device_emulation_params.h
+++ b/chromium/third_party/blink/public/web/web_device_emulation_params.h
@@ -29,13 +29,16 @@ struct WebDeviceEmulationParams {
// original one for kDesktop screen position, (0, 0) for kMobile.
base::Optional<WebPoint> view_position;
- // Emulated view size. Empty size means no override.
+ // Emulated view size. A width or height of 0 means no override in that
+ // dimension, but the other can still be applied. When both are 0, then the
+ // |scale| will be applied to the view instead.
WebSize view_size;
// If zero, the original device scale factor is preserved.
float device_scale_factor;
- // Scale of emulated view inside available space, not in fit to view mode.
+ // Scale the contents of the main frame. The view's size will be scaled by
+ // this number when they are not specified in |view_size|.
float scale;
// Forced viewport offset for screenshots during emulation, (-1, -1) for
diff --git a/chromium/third_party/blink/public/web/web_document.h b/chromium/third_party/blink/public/web/web_document.h
index 10a20028df8..230a855dbfe 100644
--- a/chromium/third_party/blink/public/web/web_document.h
+++ b/chromium/third_party/blink/public/web/web_document.h
@@ -70,7 +70,6 @@ class WebDocument : public WebNode {
// Note: Security checks should use the getSecurityOrigin(), not url().
BLINK_EXPORT WebSecurityOrigin GetSecurityOrigin() const;
BLINK_EXPORT bool IsSecureContext() const;
- BLINK_EXPORT void GrantLoadLocalResources();
BLINK_EXPORT WebString Encoding() const;
BLINK_EXPORT WebString ContentLanguage() const;
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 408709b35cf..a6e5e250321 100644
--- a/chromium/third_party/blink/public/web/web_document_loader.h
+++ b/chromium/third_party/blink/public/web/web_document_loader.h
@@ -39,6 +39,7 @@
#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"
+#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_text_direction.h"
@@ -95,12 +96,6 @@ class BLINK_EXPORT WebDocumentLoader {
virtual bool HasUnreachableURL() const = 0;
virtual WebURL UnreachableURL() const = 0;
- // The error code for loading an error page.
- virtual int ErrorCode() const = 0;
-
- // The IPAddressSpace associated with this loader.
- virtual network::mojom::IPAddressSpace GetIPAddressSpace() 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
@@ -158,6 +153,9 @@ class BLINK_EXPORT WebDocumentLoader {
// can return true even if archive loading ended up failing.
virtual bool HasBeenLoadedAsWebArchive() const = 0;
+ // Returns the previews state for the document.
+ virtual WebURLRequest::PreviewsState GetPreviewsState() const = 0;
+
// Returns archive info for the archive.
virtual WebArchiveInfo GetArchiveInfo() const = 0;
diff --git a/chromium/third_party/blink/public/web/web_embedded_worker.h b/chromium/third_party/blink/public/web/web_embedded_worker.h
index 724e63c0699..aa3128ca01d 100644
--- a/chromium/third_party/blink/public/web/web_embedded_worker.h
+++ b/chromium/third_party/blink/public/web/web_embedded_worker.h
@@ -45,7 +45,14 @@ struct WebEmbeddedWorkerStartData;
// As we're on the border line between non-Blink and Blink variants, we need
// to use mojo::ScopedMessagePipeHandle to pass Mojo types.
-struct WebServiceWorkerInstalledScriptsManagerParams {
+struct BLINK_EXPORT WebServiceWorkerInstalledScriptsManagerParams {
+ WebServiceWorkerInstalledScriptsManagerParams() = delete;
+ WebServiceWorkerInstalledScriptsManagerParams(
+ WebVector<WebURL> installed_scripts_urls,
+ mojo::ScopedMessagePipeHandle manager_receiver,
+ mojo::ScopedMessagePipeHandle manager_host_remote);
+ ~WebServiceWorkerInstalledScriptsManagerParams() = default;
+
WebVector<WebURL> installed_scripts_urls;
// A handle for
// mojo::PendingReceiver<mojom::blink::ServiceWorkerInstalledScriptsManager>.
@@ -63,19 +70,20 @@ class BLINK_EXPORT WebEmbeddedWorker {
// WebServiceWorkerContextClient is owned by caller and must survive the
// instance of WebEmbeddedWorker.
static std::unique_ptr<WebEmbeddedWorker> Create(
- WebServiceWorkerContextClient*,
- std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
- mojo::ScopedMessagePipeHandle content_settings_handle,
- mojo::ScopedMessagePipeHandle cache_storage,
- mojo::ScopedMessagePipeHandle interface_provider,
- mojo::ScopedMessagePipeHandle browser_interface_broker);
+ WebServiceWorkerContextClient*);
virtual ~WebEmbeddedWorker() = default;
// Starts and terminates WorkerThread and WorkerGlobalScope.
- virtual void StartWorkerContext(const WebEmbeddedWorkerStartData&,
- scoped_refptr<base::SingleThreadTaskRunner>
- initiator_thread_task_runner) = 0;
+ virtual void StartWorkerContext(
+ std::unique_ptr<WebEmbeddedWorkerStartData>,
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
+ mojo::ScopedMessagePipeHandle content_settings_handle,
+ mojo::ScopedMessagePipeHandle cache_storage,
+ mojo::ScopedMessagePipeHandle interface_provider,
+ mojo::ScopedMessagePipeHandle browser_interface_broker,
+ scoped_refptr<base::SingleThreadTaskRunner>
+ initiator_thread_task_runner) = 0;
virtual void TerminateWorkerContext() = 0;
// Resumes starting a worker startup that was paused via
diff --git a/chromium/third_party/blink/public/web/web_embedded_worker_start_data.h b/chromium/third_party/blink/public/web/web_embedded_worker_start_data.h
index c4e3d069881..d475bda3012 100644
--- a/chromium/third_party/blink/public/web/web_embedded_worker_start_data.h
+++ b/chromium/third_party/blink/public/web/web_embedded_worker_start_data.h
@@ -33,12 +33,11 @@
#include "base/unguessable_token.h"
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
-#include "third_party/blink/public/common/privacy_preferences.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-shared.h"
#include "third_party/blink/public/platform/web_content_security_policy.h"
+#include "third_party/blink/public/platform/web_fetch_client_settings_object.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"
namespace blink {
@@ -54,15 +53,16 @@ struct WebEmbeddedWorkerStartData {
// Unique worker token used by DevTools to attribute different instrumentation
// to the same worker.
base::UnguessableToken devtools_worker_token;
- WebSettings::V8CacheOptions v8_cache_options;
network::mojom::IPAddressSpace address_space;
- PrivacyPreferences privacy_preferences;
+ WebFetchClientSettingsObject outside_fetch_client_settings_object;
- WebEmbeddedWorkerStartData()
+ explicit WebEmbeddedWorkerStartData(
+ WebFetchClientSettingsObject outside_fetch_client_settings_object)
: wait_for_debugger_mode(kDontWaitForDebugger),
- v8_cache_options(WebSettings::V8CacheOptions::kDefault) {}
+ outside_fetch_client_settings_object(
+ std::move(outside_fetch_client_settings_object)) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_frame.h b/chromium/third_party/blink/public/web/web_frame.h
index 12966c848fc..4dc7a53e777 100644
--- a/chromium/third_party/blink/public/web/web_frame.h
+++ b/chromium/third_party/blink/public/web/web_frame.h
@@ -53,7 +53,6 @@ class WebView;
enum class WebSandboxFlags;
struct FramePolicy;
struct WebFrameOwnerProperties;
-struct WebRect;
// Frames may be rendered in process ('local') or out of process ('remote').
// A remote frame is always cross-site; a local frame may be either same-site or
@@ -119,14 +118,6 @@ class BLINK_EXPORT WebFrame {
// navigation. This matches the in-process frame behavior.
void SetFrameOwnerProperties(const WebFrameOwnerProperties&);
- // Geometry -----------------------------------------------------------
-
- // NOTE: These routines do not force page layout so their results may
- // not be accurate if the page layout is out-of-date.
-
- // Returns the visible content rect (minus scrollbars, in absolute coordinate)
- virtual WebRect VisibleContentRect() const = 0;
-
// Whether to collapse the frame's owner element in the embedder document,
// that is, to remove it from the layout as if it did not exist. Only works
// for <iframe> owner elements.
diff --git a/chromium/third_party/blink/public/web/web_fullscreen_options.h b/chromium/third_party/blink/public/web/web_fullscreen_options.h
deleted file mode 100644
index ae7648bb586..00000000000
--- a/chromium/third_party/blink/public/web/web_fullscreen_options.h
+++ /dev/null
@@ -1,23 +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_PUBLIC_WEB_WEB_FULLSCREEN_OPTIONS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_FULLSCREEN_OPTIONS_H_
-
-namespace blink {
-
-// Options used when requesting fullscreen.
-struct WebFullscreenOptions {
- // Prefer that the bottom navigation bar be shown when in fullscreen
- // mode on devices with overlay navigation bars.
- bool prefers_navigation_bar = false;
-
- bool operator==(const WebFullscreenOptions& rhs) {
- return prefers_navigation_bar == rhs.prefers_navigation_bar;
- }
-};
-
-} // namespace blink
-
-#endif
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 a781a44399a..023e01533b6 100644
--- a/chromium/third_party/blink/public/web/web_local_frame.h
+++ b/chromium/third_party/blink/public/web/web_local_frame.h
@@ -9,7 +9,7 @@
#include <set>
#include "base/callback.h"
-#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
@@ -236,9 +236,6 @@ class WebLocalFrame : public WebFrame {
// Navigation State -------------------------------------------------------
- // Returns true if the current frame's load event has not completed.
- bool IsLoading() const override = 0;
-
// Returns true if there is a pending redirect or location change
// within specified interval. This could be caused by:
// * an HTTP Refresh header
@@ -272,13 +269,6 @@ class WebLocalFrame : public WebFrame {
// Notify the frame that the screen orientation has changed.
virtual void SendOrientationChangeEvent() = 0;
- // Printing ------------------------------------------------------------
-
- // Returns true on success and sets the out parameter to the print preset
- // options for the document.
- virtual bool GetPrintPresetOptionsForPlugin(const WebNode&,
- WebPrintPresetOptions*) = 0;
-
// CSS3 Paged Media ----------------------------------------------------
// Returns true if page box (margin boxes and page borders) is visible.
@@ -539,13 +529,9 @@ class WebLocalFrame : public WebFrame {
// Image reload -----------------------------------------------------------
- // If the provided node is an image, reload the image disabling Lo-Fi.
+ // If the provided node is an image that failed to load, reload it.
virtual void ReloadImage(const WebNode&) = 0;
- // Reloads all the Lo-Fi images in this WebLocalFrame. Ignores the cache and
- // reloads from the network.
- virtual void ReloadLoFiImages() = 0;
-
// Feature usage logging --------------------------------------------------
virtual void DidCallAddSearchProvider() = 0;
@@ -678,6 +664,9 @@ class WebLocalFrame : public WebFrame {
// Returns true if the contents (minus scrollbars) has non-zero area.
virtual bool HasVisibleContent() const = 0;
+ // Returns the visible content rect (minus scrollbars, in absolute coordinate)
+ virtual WebRect VisibleContentRect() const = 0;
+
// Printing ------------------------------------------------------------
// Dispatch |beforeprint| event, and execute event handlers. They might detach
@@ -713,6 +702,11 @@ class WebLocalFrame : public WebFrame {
// This function should be called after pairs of PrintBegin() and PrintEnd().
virtual void DispatchAfterPrintEvent() = 0;
+ // Returns true on success and sets the out parameter to the print preset
+ // options for the document.
+ virtual bool GetPrintPresetOptionsForPlugin(const WebNode&,
+ WebPrintPresetOptions*) = 0;
+
// Focus --------------------------------------------------------------
// Advance the focus of the WebView to next text input element from current
@@ -777,13 +771,12 @@ class WebLocalFrame : public WebFrame {
explicit WebLocalFrame(WebTreeScopeType scope) : WebFrame(scope) {}
// Inherited from WebFrame, but intentionally hidden: it never makes sense
- // to call these on a WebLocalFrame.
+ // to directly call these on a WebLocalFrame.
bool IsWebLocalFrame() const override = 0;
WebLocalFrame* ToWebLocalFrame() override = 0;
bool IsWebRemoteFrame() const override = 0;
WebRemoteFrame* ToWebRemoteFrame() override = 0;
- private:
virtual void AddMessageToConsoleImpl(const WebConsoleMessage&,
bool discard_duplicates) = 0;
};
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 8f62613797f..dc80421a389 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
@@ -34,12 +34,16 @@
#include <memory>
#include "base/unguessable_token.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/frame/blocked_navigation_types.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
+#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/common/sudden_termination_disabler_type.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-shared.h"
#include "third_party/blink/public/platform/blame_context.h"
@@ -51,11 +55,9 @@
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_file_system_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
#include "third_party/blink/public/platform/web_scroll_types.h"
#include "third_party/blink/public/platform/web_set_sink_id_callbacks.h"
#include "third_party/blink/public/platform/web_source_location.h"
-#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -75,7 +77,6 @@
#include "third_party/blink/public/web/web_navigation_policy.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_text_direction.h"
-#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "ui/accessibility/ax_enums.mojom-shared.h"
#include "ui/events/types/scroll_types.h"
#include "v8/include/v8.h"
@@ -118,7 +119,6 @@ class WebURLResponse;
struct FramePolicy;
struct WebConsoleMessage;
struct WebContextMenuData;
-struct WebFullscreenOptions;
struct WebPluginParams;
struct WebPopupMenuInfo;
struct WebRect;
@@ -207,9 +207,7 @@ class BLINK_EXPORT WebLocalFrameClient {
// navigation-associated interfaces from the browser. See also
// LocalFrame::GetRemoteNavigationAssociatedInterfaces().
virtual AssociatedInterfaceProvider*
- GetRemoteNavigationAssociatedInterfaces() {
- return nullptr;
- }
+ GetRemoteNavigationAssociatedInterfaces();
// General notifications -----------------------------------------------
@@ -348,13 +346,10 @@ class BLINK_EXPORT WebLocalFrameClient {
// The client should handle the request as a download.
// If the request is for a blob: URL, a BlobURLToken should be provided
// as |blob_url_token| to ensure the correct blob gets downloaded.
- enum class CrossOriginRedirects { kFollow, kNavigate };
- virtual void DownloadURL(const WebURLRequest&,
- CrossOriginRedirects cross_origin_redirect_behavior,
- mojo::ScopedMessagePipeHandle blob_url_token) {}
-
- // The client should load an error page in the current frame.
- virtual void LoadErrorPage(int reason) {}
+ virtual void DownloadURL(
+ const WebURLRequest&,
+ network::mojom::RedirectMode cross_origin_redirect_behavior,
+ mojo::ScopedMessagePipeHandle blob_url_token) {}
// Navigational queries ------------------------------------------------
@@ -408,11 +403,6 @@ class BLINK_EXPORT WebLocalFrameClient {
// A new provisional load has been started.
virtual void DidStartProvisionalLoad(WebDocumentLoader* document_loader) {}
- // The provisional load failed, which used |http_method| to load the main
- // resource.
- virtual void DidFailProvisionalLoad(const WebURLError&,
- const WebString& http_method) {}
-
// The provisional datasource is now committed. The first part of the
// response body has been received, and the encoding of the response
// body is known.
@@ -508,10 +498,6 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void SetEffectiveConnectionTypeForTesting(
WebEffectiveConnectionType) {}
- virtual WebURLRequest::PreviewsState GetPreviewsStateForFrame() const {
- return WebURLRequest::kPreviewsUnspecified;
- }
-
// This frame tried to perform a navigation from |initiator_url| to
// |blocked_url| but was blocked because of |reason|.
virtual void DidBlockNavigation(const WebURL& blocked_url,
@@ -521,11 +507,8 @@ class BLINK_EXPORT WebLocalFrameClient {
// Tells the embedder to navigate back or forward in session history by
// the given offset (relative to the current position in session
// history). |has_user_gesture| tells whether or not this is the consequence
- // of a user action. |from_script| tells whether the action was initiated from
- // the execution of a script.
- virtual void NavigateBackForwardSoon(int offset,
- bool has_user_gesture,
- bool from_script) {}
+ // of a user action.
+ virtual void NavigateBackForwardSoon(int offset, bool has_user_gesture) {}
// Returns token to be used as a frame id in the devtools protocol.
// It is derived from the content's devtools_frame_token, is
@@ -638,10 +621,6 @@ class BLINK_EXPORT WebLocalFrameClient {
// connection with certificate errors.
virtual void DidRunContentWithCertificateErrors() {}
- // The frame loaded a resource with a legacy TLS version that will be removed
- // in the future. Prints a console message to warn about this.
- virtual void ReportLegacyTLSVersion(const WebURL&) {}
-
// A performance timing event (e.g. first paint) occurred
virtual void DidChangePerformanceTiming() {}
@@ -658,7 +637,7 @@ class BLINK_EXPORT WebLocalFrameClient {
// UseCounter ----------------------------------------------------------
// Blink exhibited a certain loading behavior that the browser process will
// use for segregated histograms.
- virtual void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) {}
+ virtual void DidObserveLoadingBehavior(LoadingBehaviorFlag) {}
// Blink UseCounter should only track feature usage for non NTP activities.
// ShouldTrackUseCounter checks the url of a page's main frame is not a new
// tab page url.
@@ -790,26 +769,14 @@ class BLINK_EXPORT WebLocalFrameClient {
// in page operation.
virtual void HandleAccessibilityFindInPageTermination() {}
- // Fullscreen ----------------------------------------------------------
-
- // Called to enter/exit fullscreen mode.
- // After calling enterFullscreen or exitFullscreen,
- // WebWidget::didEnterFullscreen or WebWidget::didExitFullscreen
- // respectively will be called once the fullscreen mode has changed.
- virtual void EnterFullscreen(const blink::WebFullscreenOptions& options) {}
- virtual void ExitFullscreen() {}
-
- // Called when this frame changes fullscreen state.
- virtual void FullscreenStateChanged(bool is_fullscreen) {}
-
// Sudden termination --------------------------------------------------
// Called when elements preventing the sudden termination of the frame
// become present or stop being present. |type| is the type of element
// (BeforeUnload handler, Unload handler).
- virtual void SuddenTerminationDisablerChanged(
- bool present,
- WebSuddenTerminationDisablerType) {}
+ virtual void SuddenTerminationDisablerChanged(bool present,
+ SuddenTerminationDisablerType) {
+ }
// Navigator Content Utils --------------------------------------------
@@ -859,6 +826,12 @@ class BLINK_EXPORT WebLocalFrameClient {
return nullptr;
}
+ // AppCache ------------------------------------------------------------
+ virtual void UpdateSubresourceFactory(
+ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) {}
+
+ // Misc ----------------------------------------------------------------
+
// Returns true when the contents of plugin are handled externally. This means
// the plugin element will own a content frame but the frame is than used
// externally to load the required handlers.
@@ -879,10 +852,6 @@ class BLINK_EXPORT WebLocalFrameClient {
// Transfers user activation state from |source_frame| to the current frame.
virtual void TransferUserActivationFrom(WebLocalFrame* source_frame) {}
- // AppCache ------------------------------------------------------------
- virtual void UpdateSubresourceFactory(
- std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) {}
-
// Evicts the page from the back forward cache due to e.g., JavaScript
// execution.
virtual void EvictFromBackForwardCache() {}
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 72e4a1d4cf2..d3e8c0b2e26 100644
--- a/chromium/third_party/blink/public/web/web_navigation_params.h
+++ b/chromium/third_party/blink/public/web/web_navigation_params.h
@@ -14,6 +14,7 @@
#include "mojo/public/cpp/system/message_pipe.h"
#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/navigation/triggering_event_info.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -35,7 +36,6 @@
#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_origin_policy.h"
-#include "third_party/blink/public/web/web_triggering_event_info.h"
#if INSIDE_BLINK
#include "base/memory/scoped_refptr.h"
@@ -99,9 +99,8 @@ struct BLINK_EXPORT WebNavigationInfo {
// |BlockingDownloadsInSandboxWithoutUserActivation| is enabled.
bool blocking_downloads_in_sandbox_without_user_activation_enabled = false;
- // Event information. See WebTriggeringEventInfo.
- WebTriggeringEventInfo triggering_event_info =
- WebTriggeringEventInfo::kUnknown;
+ // Event information. See TriggeringEventInfo.
+ TriggeringEventInfo triggering_event_info = TriggeringEventInfo::kUnknown;
// If the navigation is a result of form submit, the form element is provided.
WebFormElement form;
@@ -282,6 +281,9 @@ struct BLINK_EXPORT WebNavigationParams {
WebHistoryItem history_item;
// Whether this navigation is a result of client redirect.
bool is_client_redirect = false;
+ // Cache mode to be used for subresources, instead of the one determined
+ // by |frame_load_type|.
+ base::Optional<blink::mojom::FetchCacheMode> force_fetch_cache_mode;
// Miscellaneous parameters.
@@ -306,6 +308,8 @@ struct BLINK_EXPORT WebNavigationParams {
bool is_user_activated = false;
// Whether this navigation was browser initiated.
bool is_browser_initiated = 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.
WebURLRequest::PreviewsState previews_state =
WebURLRequest::kPreviewsUnspecified;
@@ -344,6 +348,10 @@ struct BLINK_EXPORT WebNavigationParams {
WebVector<int> initiator_origin_trial_features;
base::Optional<WebOriginPolicy> origin_policy;
+
+ // The base URL which will be set for the document to support relative path
+ // subresource loading in unsigned bundled exchanges file.
+ WebURL base_url_override_for_bundled_exchanges;
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_plugin.h b/chromium/third_party/blink/public/web/web_plugin.h
index 1088264556e..3f4d2d6014b 100644
--- a/chromium/third_party/blink/public/web/web_plugin.h
+++ b/chromium/third_party/blink/public/web/web_plugin.h
@@ -143,6 +143,8 @@ 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.
diff --git a/chromium/third_party/blink/public/web/web_print_scaling_option.h b/chromium/third_party/blink/public/web/web_print_scaling_option.h
index 379a60a392b..044bde7bb86 100644
--- a/chromium/third_party/blink/public/web/web_print_scaling_option.h
+++ b/chromium/third_party/blink/public/web/web_print_scaling_option.h
@@ -43,7 +43,9 @@ enum WebPrintScalingOption {
kWebPrintScalingOptionSourceSize, // Print output page size is same as the
// actual source page size. Do not
// scale/center/fit to printable area.
- kWebPrintScalingOptionLast = kWebPrintScalingOptionSourceSize
+ kWebPrintScalingOptionFitToPaper, // Reduces or enlarges each page to fit the
+ // selected printer paper size.
+ kWebPrintScalingOptionLast = kWebPrintScalingOptionFitToPaper
};
} // namespace blink
diff --git a/chromium/third_party/blink/public/web/web_render_theme.h b/chromium/third_party/blink/public/web/web_render_theme.h
index 347b342d9e4..6f8ce807d59 100644
--- a/chromium/third_party/blink/public/web/web_render_theme.h
+++ b/chromium/third_party/blink/public/web/web_render_theme.h
@@ -47,6 +47,8 @@ BLINK_EXPORT void SetSelectionColors(unsigned active_background_color,
unsigned inactive_background_color,
unsigned inactive_foreground_color);
+BLINK_EXPORT void SystemColorsChanged();
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/public/web/web_settings.h b/chromium/third_party/blink/public/web/web_settings.h
index 91622c67a65..eda372798bc 100644
--- a/chromium/third_party/blink/public/web/web_settings.h
+++ b/chromium/third_party/blink/public/web/web_settings.h
@@ -33,7 +33,7 @@
#include <unicode/uscript.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/common/css/preferred_color_scheme.h"
#include "third_party/blink/public/platform/pointer_properties.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -290,9 +290,14 @@ class WebSettings {
virtual void SetLazyImageLoadingDistanceThresholdPx2G(int) = 0;
virtual void SetLazyImageLoadingDistanceThresholdPx3G(int) = 0;
virtual void SetLazyImageLoadingDistanceThresholdPx4G(int) = 0;
+ virtual void SetLazyImageFirstKFullyLoadUnknown(int) = 0;
+ virtual void SetLazyImageFirstKFullyLoadSlow2G(int) = 0;
+ virtual void SetLazyImageFirstKFullyLoad2G(int) = 0;
+ virtual void SetLazyImageFirstKFullyLoad3G(int) = 0;
+ virtual void SetLazyImageFirstKFullyLoad4G(int) = 0;
virtual void SetForceDarkModeEnabled(bool) = 0;
virtual void SetPreferredColorScheme(PreferredColorScheme) = 0;
- virtual void SetForcedColors(ForcedColors) = 0;
+ virtual void SetNavigationControls(NavigationControls) = 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 db7d7c87686..bd279e31c8b 100644
--- a/chromium/third_party/blink/public/web/web_view.h
+++ b/chromium/third_party/blink/public/web/web_view.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_VIEW_H_
#include "base/time/time.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -60,10 +60,10 @@ class WebSettings;
class WebString;
class WebViewClient;
class WebWidget;
+struct PluginAction;
struct WebDeviceEmulationParams;
struct WebFloatPoint;
struct WebFloatSize;
-struct WebPluginAction;
struct WebRect;
struct WebSize;
struct WebTextAutosizerPageInfo;
@@ -201,15 +201,6 @@ class WebView {
// change.
virtual double SetZoomLevel(double) = 0;
- // Updates the zoom limits for this view.
- virtual void ZoomLimitsChanged(double minimum_zoom_level,
- double maximum_zoom_level) = 0;
-
- // Helper functions to convert between zoom level and zoom factor. zoom
- // factor is zoom percent / 100, so 300% = 3.0.
- BLINK_EXPORT static double ZoomLevelToZoomFactor(double zoom_level);
- BLINK_EXPORT static double ZoomFactorToZoomLevel(double factor);
-
// Returns the current text zoom factor, where 1.0 is the normal size, > 1.0
// is scaled up and < 1.0 is scaled down.
virtual float TextZoomFactor() = 0;
@@ -278,6 +269,9 @@ class WebView {
// mode (does not have <!doctype html>), the height will stretch to fill the
// viewport. The returned size has the page zoom factor applied. The lifecycle
// must be updated to at least layout before calling (see: |UpdateLifecycle|).
+ //
+ // This may only be called when there is a local main frame attached to this
+ // WebView.
virtual WebSize ContentsPreferredMinimumSize() = 0;
// Requests a page-scale animation based on the specified point/rect.
@@ -287,7 +281,7 @@ class WebView {
virtual void ZoomToFindInPageRect(const WebRect&) = 0;
// Sets the display mode of the web app.
- virtual void SetDisplayMode(WebDisplayMode) = 0;
+ virtual void SetDisplayMode(blink::mojom::DisplayMode) = 0;
// Sets the ratio as computed by computePageScaleConstraints.
// TODO(oshima): Remove this once the device scale factor implementation is
@@ -314,6 +308,8 @@ class WebView {
// settings.
virtual void Resize(const WebSize&) = 0;
+ virtual WebSize GetSize() = 0;
+
// Auto-Resize -----------------------------------------------------------
// In auto-resize mode, the view is automatically adjusted to fit the html
@@ -327,7 +323,7 @@ class WebView {
// Media ---------------------------------------------------------------
// Performs the specified plugin action on the node at the given location.
- virtual void PerformPluginAction(const WebPluginAction&,
+ virtual void PerformPluginAction(const PluginAction&,
const gfx::Point& location) = 0;
// Notifies WebView when audio is started or stopped.
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 8ef050d6d6b..233bd478865 100644
--- a/chromium/third_party/blink/public/web/web_view_client.h
+++ b/chromium/third_party/blink/public/web/web_view_client.h
@@ -156,10 +156,6 @@ class WebViewClient {
// Called when the View acquires focus.
virtual void DidFocus(WebLocalFrame* calling_frame) {}
- // Returns information about the screen where this view's widgets are being
- // displayed.
- virtual WebScreenInfo GetScreenInfo() = 0;
-
// Session history -----------------------------------------------------
// Returns the number of history items before/after the current
@@ -178,10 +174,6 @@ class WebViewClient {
// Zoom ----------------------------------------------------------------
- // Informs the browser that the zoom levels for this frame have changed from
- // the default values.
- virtual void ZoomLimitsChanged(double minimum_level, double maximum_level) {}
-
// Informs the browser that the page scale has changed and/or a pinch gesture
// has started or ended.
virtual void PageScaleFactorChanged(float page_scale_factor) {}
diff --git a/chromium/third_party/blink/public/web/web_widget.h b/chromium/third_party/blink/public/web/web_widget.h
index bc31142504e..700d7448f51 100644
--- a/chromium/third_party/blink/public/web/web_widget.h
+++ b/chromium/third_party/blink/public/web/web_widget.h
@@ -34,6 +34,7 @@
#include "base/callback.h"
#include "base/time/time.h"
#include "cc/input/browser_controls_state.h"
+#include "cc/metrics/begin_main_frame_metrics.h"
#include "cc/paint/element_id.h"
#include "cc/trees/layer_tree_host_client.h"
#include "third_party/blink/public/platform/web_common.h"
@@ -103,6 +104,17 @@ class WebWidget {
// any metrics that depend upon the main frame total time.
virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) {}
+ // Return metrics information for the stages of BeginMainFrame. This is
+ // ultimately implemented by Blink's LocalFrameUKMAggregator. It must be a
+ // distinct call from the FrameMetrics above because the BeginMainFrameMetrics
+ // for compositor latency must be gathered before the layer tree is
+ // committed to the compositor, which is before the call to
+ // RecordEndOfFrameMetrics.
+ virtual std::unique_ptr<cc::BeginMainFrameMetrics>
+ GetBeginMainFrameMetrics() {
+ return nullptr;
+ }
+
// Methods called to mark the beginning and end of input processing work
// before rAF scripts are executed. Only called when gathering main frame
// UMA and UKM. That is, when RecordStartOfFrameMetrics has been called, and
diff --git a/chromium/third_party/blink/public/web/web_widget_client.h b/chromium/third_party/blink/public/web/web_widget_client.h
index 87f660f8554..b315756ff5a 100644
--- a/chromium/third_party/blink/public/web/web_widget_client.h
+++ b/chromium/third_party/blink/public/web/web_widget_client.h
@@ -60,7 +60,6 @@ struct ElementId;
class LayerTreeMutator;
class ScopedDeferMainFrameUpdate;
class PaintImage;
-struct ViewportLayers;
}
namespace gfx {
@@ -135,6 +134,10 @@ class WebWidgetClient {
// Called to show the widget according to the given policy.
virtual void Show(WebNavigationPolicy) {}
+ // Returns information about the screen where this view's widgets are being
+ // displayed.
+ virtual WebScreenInfo GetScreenInfo() { return {}; }
+
// Called to get/set the position of the widget's window in screen
// coordinates. Note, the window includes any decorations such as borders,
// scrollbars, URL bar, tab strip, etc. if they exist.
@@ -257,11 +260,6 @@ class WebWidgetClient {
// Find in page zooms a rect in the main-frame renderer.
virtual void ZoomToFindInPageRectInMainFrame(const blink::WebRect& rect) {}
- // Identify key viewport layers to the compositor. Pass a default-constructed
- // ViewportLayers to clear them.
- virtual void RegisterViewportLayers(
- const cc::ViewportLayers& viewport_layers) {}
-
// Used to update the active selection bounds. Pass a default-constructed
// LayerSelection to clear it.
virtual void RegisterSelection(const cc::LayerSelection&) {}
@@ -273,10 +271,6 @@ class WebWidgetClient {
bool down) {}
virtual void FallbackCursorModeSetCursorVisibility(bool visible) {}
- // Informs the compositor if gpu raster will be allowed, or it is blocked
- // based on heuristics from the content of the page.
- virtual void SetAllowGpuRasterization(bool) {}
-
// Sets the current page scale factor and minimum / maximum limits. Both
// limits are initially 1 (no page scale allowed).
virtual void SetPageScaleStateAndLimits(float page_scale_factor,
diff --git a/chromium/third_party/blink/renderer/BUILD.gn b/chromium/third_party/blink/renderer/BUILD.gn
index b8718cabbd1..0d02c49b449 100644
--- a/chromium/third_party/blink/renderer/BUILD.gn
+++ b/chromium/third_party/blink/renderer/BUILD.gn
@@ -112,6 +112,14 @@ config("config") {
"blink-gc-plugin",
]
+ # Don't perform checks for GarbageCollectedFinalized.
+ cflags += [
+ "-Xclang",
+ "-plugin-arg-blink-gc-plugin",
+ "-Xclang",
+ "no-gc-finalized",
+ ]
+
# Add arguments for enabled GC plugin options:
if (blink_gc_plugin_option_do_dump_graph) {
cflags += [
diff --git a/chromium/third_party/blink/renderer/bindings/BUILD.gn b/chromium/third_party/blink/renderer/bindings/BUILD.gn
index b994e1cb6fb..65761237348 100644
--- a/chromium/third_party/blink/renderer/bindings/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/BUILD.gn
@@ -125,3 +125,31 @@ action_with_pydeps("web_idl_database") {
":web_idl_in_modules",
]
}
+
+action_with_pydeps("generate_bindings_example") {
+ script = "${bindings_scripts_dir}/generate_bindings.py"
+
+ web_idl_database_outputs = get_target_outputs(":web_idl_database")
+ web_idl_database = web_idl_database_outputs[0]
+
+ inputs = [
+ web_idl_database,
+ ]
+ outputs = [
+ "${bindings_output_dir}/core/v8/v8_example.cc",
+ ]
+
+ args = [
+ "example",
+ "--web_idl_database",
+ rebase_path(web_idl_database, root_build_dir),
+ "--output_dir_core",
+ rebase_path("${bindings_output_dir}/core/v8/", root_build_dir),
+ "--output_dir_modules",
+ rebase_path("${bindings_output_dir}/modules/v8/", root_build_dir),
+ ]
+
+ deps = [
+ ":web_idl_database",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/bindings/bindings.gni b/chromium/third_party/blink/renderer/bindings/bindings.gni
index f5f73eeaf11..7b70a23fa20 100644
--- a/chromium/third_party/blink/renderer/bindings/bindings.gni
+++ b/chromium/third_party/blink/renderer/bindings/bindings.gni
@@ -26,8 +26,6 @@ bindings_core_v8_files =
"core/v8/custom/v8_message_channel_custom.cc",
"core/v8/custom/v8_pop_state_event_custom.cc",
"core/v8/custom/v8_promise_rejection_event_custom.cc",
- "core/v8/custom/v8_readable_stream_custom.cc",
- "core/v8/custom/v8_writable_stream_custom.cc",
"core/v8/custom/v8_shadow_root_custom.cc",
"core/v8/custom/v8_window_custom.cc",
"core/v8/custom/v8_xml_http_request_custom.cc",
@@ -42,8 +40,6 @@ bindings_core_v8_files =
"core/v8/idl_dictionary_base.h",
"core/v8/idl_types.h",
"core/v8/idl_types_base.h",
- "core/v8/initialize_v8_extras_binding.cc",
- "core/v8/initialize_v8_extras_binding.h",
"core/v8/iterable.h",
"core/v8/js_based_event_listener.cc",
"core/v8/js_based_event_listener.h",
@@ -113,6 +109,7 @@ bindings_core_v8_files =
"core/v8/serialization/serialized_script_value.h",
"core/v8/serialization/serialized_script_value_factory.cc",
"core/v8/serialization/serialized_script_value_factory.h",
+ "core/v8/serialization/transferables.cc",
"core/v8/serialization/transferables.h",
"core/v8/serialization/unpacked_serialized_script_value.cc",
"core/v8/serialization/unpacked_serialized_script_value.h",
@@ -192,7 +189,6 @@ bindings_unittest_files =
"core/v8/binding_security_test.cc",
"core/v8/dictionary_test.cc",
"core/v8/dom_wrapper_world_test.cc",
- "core/v8/initialize_v8_extras_binding_test.cc",
"core/v8/idl_types_test.cc",
"core/v8/module_record_test.cc",
"core/v8/boxed_v8_module_test.cc",
@@ -209,6 +205,7 @@ bindings_unittest_files =
"core/v8/v8_binding_for_testing.cc",
"core/v8/v8_binding_for_testing.h",
"core/v8/window_proxy_test.cc",
+ "core/v8/world_safe_v8_reference_test.cc",
"core/v8/v8_object_builder_test.cc",
"core/v8/v8_script_runner_test.cc",
"core/v8/serialization/serialized_script_value_test.cc",
@@ -216,6 +213,8 @@ bindings_unittest_files =
"core/v8/serialization/v8_script_value_serializer_test.cc",
"core/v8/v8_extras_test_utils.cc",
"core/v8/v8_extras_test_utils.h",
+ "core/v8/script_promise_tester.cc",
+ "core/v8/script_promise_tester.h",
],
"abspath")
bindings_unittest_files += bindings_modules_v8_unittest_files
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/DEPS b/chromium/third_party/blink/renderer/bindings/core/v8/DEPS
new file mode 100644
index 00000000000..c386e5e6f34
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "script_promise_resolver_test.cc": [
+ "+base/run_loop.h",
+ ]
+} \ No newline at end of file
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 29ab49d8a63..f2c6c2ed25f 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.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_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
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 2daa9ac0eb0..e5d11a33924 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
@@ -18,8 +18,7 @@ namespace blink {
// Hash of Member<BoxedV8Module> overrides HashTraits.
// Therefore, BoxedV8Module can be a key/value type of WTF::HashMap,
// HashSet,HashTable by using BoxedV8ModuleHash.
-class CORE_EXPORT BoxedV8Module
- : public GarbageCollectedFinalized<BoxedV8Module> {
+class CORE_EXPORT BoxedV8Module final : public GarbageCollected<BoxedV8Module> {
public:
BoxedV8Module(v8::Isolate* isolate, v8::Local<v8::Module> module)
: record_(isolate, module),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_pop_state_event_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_pop_state_event_custom.cc
index 28c17d96664..5ac764eb377 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_pop_state_event_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_pop_state_event_custom.cc
@@ -37,12 +37,6 @@
namespace blink {
-namespace {
-// |kHistoryStateSymbolKey| is a key for a cached attribute for History.state.
-// TODO(peria): Do not use this cached attribute directly.
-constexpr char kHistoryStateSymbolKey[] = "History#State";
-}
-
// Save the state value to a hidden attribute in the V8PopStateEvent, and return
// it, for convenience.
static v8::Local<v8::Value> CacheState(ScriptState* script_state,
@@ -94,7 +88,7 @@ void V8PopStateEvent::StateAttributeGetterCustom(
bool is_same_state = history->IsSameAsCurrentState(event->SerializedState());
if (is_same_state) {
V8PrivateProperty::Symbol history_state =
- V8PrivateProperty::GetSymbol(isolate, kHistoryStateSymbolKey);
+ V8PrivateProperty::GetHistoryStateSymbol(info.GetIsolate());
v8::Local<v8::Value> v8_history_value =
ToV8(history, info.Holder(), isolate);
if (v8_history_value.IsEmpty())
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc
deleted file mode 100644
index d0e9fe48b4c..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_readable_stream_custom.cc
+++ /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.
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-void V8ReadableStream::ConstructorCustom(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
- RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(
- info.GetIsolate(), "Blink_ReadableStream_ConstructorCallback");
-
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kConstructionContext,
- "ReadableStream");
- ScriptState* script_state =
- ScriptState::From(info.NewTarget().As<v8::Object>()->CreationContext());
-
- ScriptValue underlying_source =
- ScriptValue(ScriptState::Current(info.GetIsolate()),
- v8::Undefined(info.GetIsolate()));
- ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()),
- v8::Undefined(info.GetIsolate()));
- int num_args = info.Length();
- if (num_args >= 1) {
- underlying_source =
- ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
- }
- if (num_args >= 2)
- strategy = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
-
- v8::Local<v8::Object> wrapper = info.Holder();
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- auto* impl = MakeGarbageCollected<ReadableStreamNative>(
- script_state, underlying_source, strategy, false, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- wrapper = impl->AssociateWithWrapper(
- info.GetIsolate(), V8ReadableStream::GetWrapperTypeInfo(), wrapper);
- } else {
- auto* impl = MakeGarbageCollected<ReadableStreamWrapper>();
- wrapper = impl->AssociateWithWrapper(
- info.GetIsolate(), V8ReadableStream::GetWrapperTypeInfo(), wrapper);
-
- impl->Init(script_state, underlying_source, strategy, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- }
- V8SetReturnValue(info, wrapper);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc
deleted file mode 100644
index 2f67ed55f98..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_writable_stream_custom.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2018 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/bindings/core/v8/v8_writable_stream.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-void V8WritableStream::ConstructorCustom(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
- RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT(
- info.GetIsolate(), "Blink_WritableStream_ConstructorCallback");
-
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kConstructionContext,
- "WritableStream");
- ScriptState* script_state =
- ScriptState::From(info.NewTarget().As<v8::Object>()->CreationContext());
-
- ScriptValue underlying_sink =
- ScriptValue(ScriptState::Current(info.GetIsolate()),
- v8::Undefined(info.GetIsolate()));
- ScriptValue strategy = ScriptValue(ScriptState::Current(info.GetIsolate()),
- v8::Undefined(info.GetIsolate()));
- int num_args = info.Length();
- if (num_args >= 1) {
- underlying_sink =
- ScriptValue(ScriptState::Current(info.GetIsolate()), info[0]);
- }
- if (num_args >= 2)
- strategy = ScriptValue(ScriptState::Current(info.GetIsolate()), info[1]);
- v8::Local<v8::Object> wrapper = info.Holder();
-
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- auto* impl = MakeGarbageCollected<WritableStreamNative>(
- script_state, underlying_sink, strategy, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- wrapper = impl->AssociateWithWrapper(
- info.GetIsolate(), V8WritableStream::GetWrapperTypeInfo(), wrapper);
- } else {
- auto* impl = MakeGarbageCollected<WritableStreamWrapper>();
- wrapper = impl->AssociateWithWrapper(
- info.GetIsolate(), V8WritableStream::GetWrapperTypeInfo(), wrapper);
- impl->Init(script_state, underlying_sink, strategy, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- }
-
- V8SetReturnValue(info, wrapper);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h b/chromium/third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h
index a6bbfaf20dc..5e20c3cff75 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h
@@ -16,7 +16,7 @@ namespace blink {
// by auto-generated IDL dictionary impl classes. toV8Impl() is used
// in ToV8.h to provide a consistent API of ToV8().
class CORE_EXPORT IDLDictionaryBase
- : public GarbageCollectedFinalized<IDLDictionaryBase> {
+ : public GarbageCollected<IDLDictionaryBase> {
public:
virtual ~IDLDictionaryBase() = default;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.cc b/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.cc
deleted file mode 100644
index fe15e880fe2..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.cc
+++ /dev/null
@@ -1,180 +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/bindings/core/v8/initialize_v8_extras_binding.h"
-
-#include <algorithm>
-#include <iterator>
-
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/platform/bindings/to_v8.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.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/runtime_enabled_features.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-// This macro avoids duplicating the name and hence prevents typos.
-#define WEB_FEATURE_ID_NAME_LOOKUP_ENTRY(id) \
- { #id, WebFeature::k##id }
-
-struct WebFeatureIdNameLookupEntry {
- const char* const name;
- const WebFeature id;
-};
-
-// TODO(ricea): Replace with a more efficient data structure if the
-// number of entries increases.
-constexpr WebFeatureIdNameLookupEntry web_feature_id_name_lookup_table[] = {
- WEB_FEATURE_ID_NAME_LOOKUP_ENTRY(ReadableStreamConstructor),
- WEB_FEATURE_ID_NAME_LOOKUP_ENTRY(WritableStreamConstructor),
- WEB_FEATURE_ID_NAME_LOOKUP_ENTRY(TransformStreamConstructor),
-};
-
-#undef WEB_FEATURE_ID_NAME_LOOKUP_ENTRY
-
-class CountUseForBindings : public ScriptFunction {
- public:
- static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
- auto* self = MakeGarbageCollected<CountUseForBindings>(script_state);
- return self->BindToV8Function();
- }
-
- explicit CountUseForBindings(ScriptState* script_state)
- : ScriptFunction(script_state) {}
-
- private:
- ScriptValue Call(ScriptValue value) override {
- String string_id;
- if (!value.ToString(string_id)) {
- V8ThrowException::ThrowTypeError(GetScriptState()->GetIsolate(),
- "countUse requires a string argument");
- return ScriptValue();
- }
-
- auto* const it =
- std::find_if(std::begin(web_feature_id_name_lookup_table),
- std::end(web_feature_id_name_lookup_table),
- [&string_id](const WebFeatureIdNameLookupEntry& entry) {
- return string_id == entry.name;
- });
-
- if (it == std::end(web_feature_id_name_lookup_table)) {
- V8ThrowException::ThrowTypeError(GetScriptState()->GetIsolate(),
- "unknown use counter");
- return ScriptValue();
- }
-
- UseCounter::Count(ExecutionContext::From(GetScriptState()), it->id);
-
- return ScriptValue::From(GetScriptState(), ToV8UndefinedGenerator());
- }
-};
-
-void AddCountUse(ScriptState* script_state, v8::Local<v8::Object> binding) {
- v8::Local<v8::Function> fn =
- CountUseForBindings::CreateFunction(script_state);
- v8::Local<v8::String> name =
- V8AtomicString(script_state->GetIsolate(), "countUse");
- binding->Set(script_state->GetContext(), name, fn).ToChecked();
-}
-
-void AddOriginals(ScriptState* script_state, v8::Local<v8::Object> binding) {
- // These values are only used when serialization is enabled.
- if (!RuntimeEnabledFeatures::TransferableStreamsEnabled())
- return;
-
- v8::Local<v8::Object> global = script_state->GetContext()->Global();
- v8::Local<v8::Context> context = script_state->GetContext();
- v8::Isolate* isolate = script_state->GetIsolate();
-
- const auto ObjectGet = [&context, &isolate](v8::Local<v8::Value> object,
- const char* property) {
- DCHECK(object->IsObject());
- return object.As<v8::Object>()
- ->Get(context, V8AtomicString(isolate, property))
- .ToLocalChecked();
- };
-
- const auto GetPrototype = [&ObjectGet](v8::Local<v8::Value> object) {
- return ObjectGet(object, "prototype");
- };
-
- const auto GetOwnPD = [&context, &isolate](v8::Local<v8::Value> object,
- const char* property) {
- DCHECK(object->IsObject());
- return object.As<v8::Object>()
- ->GetOwnPropertyDescriptor(context, V8AtomicString(isolate, property))
- .ToLocalChecked();
- };
-
- const auto GetOwnPDGet = [&ObjectGet, &GetOwnPD](v8::Local<v8::Value> object,
- const char* property) {
- return ObjectGet(GetOwnPD(object, property), "get");
- };
-
- const auto Bind = [&context, &isolate, &binding](const char* name,
- v8::Local<v8::Value> value) {
- bool result =
- binding
- ->CreateDataProperty(context, V8AtomicString(isolate, name), value)
- .ToChecked();
- DCHECK(result);
- };
-
- v8::Local<v8::Value> message_port = ObjectGet(global, "MessagePort");
- v8::Local<v8::Value> dom_exception = ObjectGet(global, "DOMException");
-
- // Most Worklets don't have MessagePort. In this case, serialization will
- // fail. AudioWorklet has MessagePort but no DOMException, so it can't use
- // serialization for now.
- if (message_port->IsUndefined() || dom_exception->IsUndefined()) {
- // Allow V8 Extras JavaScript to safely detect that MessagePort is not
- // available. Without this, lookups of MessagePort_postMessage will follow
- // the prototype chain.
- Bind("MessagePort_postMessage", v8::Undefined(isolate));
- return;
- }
-
- v8::Local<v8::Value> event_target_prototype =
- GetPrototype(ObjectGet(global, "EventTarget"));
- Bind("EventTarget_addEventListener",
- ObjectGet(event_target_prototype, "addEventListener"));
-
- v8::Local<v8::Value> message_port_prototype = GetPrototype(message_port);
- Bind("MessagePort_postMessage",
- ObjectGet(message_port_prototype, "postMessage"));
- Bind("MessagePort_close", ObjectGet(message_port_prototype, "close"));
- Bind("MessagePort_start", ObjectGet(message_port_prototype, "start"));
-
- v8::Local<v8::Value> message_event_prototype =
- GetPrototype(ObjectGet(global, "MessageEvent"));
-
- Bind("MessageEvent_data_get", GetOwnPDGet(message_event_prototype, "data"));
-
- Bind("DOMException", dom_exception);
-
- v8::Local<v8::Value> dom_exception_prototype = GetPrototype(dom_exception);
- Bind("DOMException_message_get",
- GetOwnPDGet(dom_exception_prototype, "message"));
- Bind("DOMException_name_get", GetOwnPDGet(dom_exception_prototype, "name"));
-}
-
-} // namespace
-
-void InitializeV8ExtrasBinding(ScriptState* script_state) {
- v8::Local<v8::Object> binding =
- script_state->GetContext()->GetExtrasBindingObject();
- AddCountUse(script_state, binding);
- AddOriginals(script_state, binding);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h b/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h
deleted file mode 100644
index a0f066de265..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h
+++ /dev/null
@@ -1,35 +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_BINDINGS_CORE_V8_INITIALIZE_V8_EXTRAS_BINDING_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_INITIALIZE_V8_EXTRAS_BINDING_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-
-namespace blink {
-
-class ScriptState;
-
-// Add the JavaScript function countUse() to the "binding" object that is
-// exposed to the JavaScript streams implementations.
-//
-// binding.countUse() takes a string and calls UseCounter::Count() on the
-// matching ID. It only does anything the first time it is called in a
-// particular execution context. The use of a string argument avoids duplicating
-// the IDs in the JS files, but means that JS code should avoid calling it more
-// than once to avoid unnecessary overhead. Only string IDs that this code
-// specifically knows about will work.
-//
-// Also copy the original values of MessageChannel, MessagePort and MessageEvent
-// methods and accessors to the binding object where they can be used for
-// serialization by the streams code.
-//
-// This function must be called during initialisation of the V8 context.
-//
-// countUse() is not available during snapshot creation.
-void CORE_EXPORT InitializeV8ExtrasBinding(ScriptState*);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_INITIALIZE_V8_EXTRAS_BINDING_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc
deleted file mode 100644
index c3a402f66d9..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-// Add "binding" to the global object. Production code should never do this;
-// it would be a huge security hole.
-void AddExtrasBindingToGlobal(V8TestingScope* scope) {
- auto context = scope->GetContext();
- v8::Local<v8::Object> global = context->Global();
- v8::Local<v8::Object> binding = context->GetExtrasBindingObject();
- v8::Local<v8::String> key = V8AtomicString(scope->GetIsolate(), "binding");
- global->Set(context, key, binding).FromJust();
-}
-
-TEST(InitializeV8ExtrasBindingTest, SupportedId) {
- V8TestingScope scope;
- InitializeV8ExtrasBinding(scope.GetScriptState());
- AddExtrasBindingToGlobal(&scope);
- Page::InsertOrdinaryPageForTesting(&scope.GetPage());
-
- ScriptValue rv = EvalWithPrintingError(
- &scope, "binding.countUse('TransformStreamConstructor');");
- EXPECT_TRUE(rv.IsUndefined());
- EXPECT_TRUE(scope.GetDocument().IsUseCounted(
- WebFeature::kTransformStreamConstructor));
-}
-
-TEST(InitializeV8ExtrasBindingTest, UnsupportedId) {
- V8TestingScope scope;
- InitializeV8ExtrasBinding(scope.GetScriptState());
- AddExtrasBindingToGlobal(&scope);
-
- ScriptValue rv = EvalWithPrintingError(&scope,
- "let result;"
- "try {"
- " binding.countUse('WindowEvent');"
- " result = 'FAIL';"
- "} catch (e) {"
- " result = e.name;"
- "}"
- "result");
- String result;
- EXPECT_TRUE(rv.ToString(result));
- EXPECT_EQ("TypeError", result);
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc b/chromium/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc
index 91827731a70..efa7fbcdd02 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/isolated_world_csp.cc
@@ -25,7 +25,7 @@ namespace blink {
namespace {
class IsolatedWorldCSPDelegate final
- : public GarbageCollectedFinalized<IsolatedWorldCSPDelegate>,
+ : public GarbageCollected<IsolatedWorldCSPDelegate>,
public ContentSecurityPolicyDelegate {
USING_GARBAGE_COLLECTED_MIXIN(IsolatedWorldCSPDelegate);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h b/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
index 0d89cfa5e2e..8cf18c135ad 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
@@ -79,8 +79,9 @@ class Iterable {
if (callback
->Invoke(v8_callback_this_value,
- ScriptValue(script_state, v8_value),
- ScriptValue(script_state, v8_key), this_value)
+ ScriptValue(script_state->GetIsolate(), v8_value),
+ ScriptValue(script_state->GetIsolate(), v8_key),
+ this_value)
.IsNothing()) {
exception_state.RethrowV8Exception(try_catch.Exception());
return;
@@ -88,7 +89,7 @@ class Iterable {
}
}
- class IterationSource : public GarbageCollectedFinalized<IterationSource> {
+ class IterationSource : public GarbageCollected<IterationSource> {
public:
virtual ~IterationSource() = default;
@@ -120,18 +121,18 @@ class Iterable {
};
struct EntrySelector {
STATIC_ONLY(EntrySelector);
- static Vector<ScriptValue, 2> Select(ScriptState* script_state,
- const KeyType& key,
- const ValueType& value) {
+ static HeapVector<ScriptValue, 2> Select(ScriptState* script_state,
+ const KeyType& key,
+ const ValueType& value) {
v8::Local<v8::Object> creation_context =
script_state->GetContext()->Global();
v8::Isolate* isolate = script_state->GetIsolate();
- Vector<ScriptValue, 2> entry;
+ HeapVector<ScriptValue, 2> entry;
entry.push_back(
- ScriptValue(script_state, ToV8(key, creation_context, isolate)));
+ ScriptValue(isolate, ToV8(key, creation_context, isolate)));
entry.push_back(
- ScriptValue(script_state, ToV8(value, creation_context, isolate)));
+ ScriptValue(isolate, ToV8(value, creation_context, isolate)));
return entry;
}
};
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 6d8b70d607a..b5062cc0327 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
@@ -88,7 +88,7 @@ void JSEventHandler::InvokeInternal(EventTarget& event_target,
// If an exception gets thrown by the callback, end these steps and allow
// the exception to propagate. (It will propagate to the DOM event dispatch
// logic, which will then report the exception.)
- Vector<ScriptValue> arguments;
+ HeapVector<ScriptValue> arguments;
ScriptState* script_state_of_listener =
event_handler_->CallbackRelevantScriptState();
@@ -99,9 +99,10 @@ void JSEventHandler::InvokeInternal(EventTarget& event_target,
// https://html.spec.whatwg.org/C/#runtime-script-errors-2
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);
-
+ error_event->target()->InterfaceName() == event_target_names::kWorker) {
+ error_attribute =
+ ScriptValue::CreateNull(script_state_of_listener->GetIsolate());
+ }
arguments = {
ScriptValue::From(script_state_of_listener, error_event->message()),
ScriptValue::From(script_state_of_listener, error_event->filename()),
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 c0ec993ca6d..4eb7d11483b 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
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/bindings/core/v8/local_window_proxy.h"
-#include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.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/to_v8_for_core.h"
@@ -182,9 +181,15 @@ void LocalWindowProxy::Initialize() {
if (evaluate_csp_for_eval) {
ContentSecurityPolicy* csp =
GetFrame()->GetDocument()->GetContentSecurityPolicyForWorld();
- context->AllowCodeGenerationFromStrings(csp->AllowEval(
- nullptr, SecurityViolationReportingPolicy::kSuppressReporting,
- ContentSecurityPolicy::kWillNotThrowException, g_empty_string));
+ // CSP has two mechanisms for controlling eval, script-src and Trusted
+ // Types, and we need to check both.
+ // TODO(vogelheim): Provide a simple(e) API for this use case.
+ bool allow_code_generation =
+ csp->AllowEval(SecurityViolationReportingPolicy::kSuppressReporting,
+ ContentSecurityPolicy::kWillNotThrowException,
+ g_empty_string) &&
+ !csp->IsRequireTrustedTypes();
+ context->AllowCodeGenerationFromStrings(allow_code_generation);
context->SetErrorMessageForCodeGenerationFromStrings(
V8String(GetIsolate(), csp->EvalDisabledErrorMessage()));
}
@@ -210,9 +215,6 @@ void LocalWindowProxy::Initialize() {
InstallConditionalFeatures();
- // This needs to go after everything else since it accesses the window object.
- InitializeV8ExtrasBinding(script_state_);
-
if (World().IsMainWorld()) {
GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/maplike.h b/chromium/third_party/blink/renderer/bindings/core/v8/maplike.h
index a7ca7bfb287..f22fa7559dc 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/maplike.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/maplike.h
@@ -26,10 +26,11 @@ class Maplike : public PairIterable<KeyType, ValueType> {
ExceptionState& exception_state) {
ValueType value;
if (GetMapEntry(script_state, key, value, exception_state))
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
ToV8(value, script_state->GetContext()->Global(),
script_state->GetIsolate()));
- return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+ return ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate()));
}
private:
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 b1278954fb2..31f20815c6a 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
@@ -107,7 +107,7 @@ ScriptValue ModuleRecord::Instantiate(ScriptState* script_state,
.To(&success) ||
!success) {
DCHECK(try_catch.HasCaught());
- return ScriptValue(script_state, try_catch.Exception());
+ return ScriptValue(isolate, try_catch.Exception());
}
DCHECK(!try_catch.HasCaught());
return ScriptValue();
@@ -133,7 +133,7 @@ ScriptValue ModuleRecord::Evaluate(ScriptState* script_state,
script_state->GetContext())
.ToLocal(&result)) {
DCHECK(try_catch.HasCaught());
- return ScriptValue(script_state, try_catch.Exception());
+ return ScriptValue(isolate, try_catch.Exception());
}
return ScriptValue();
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 83d9e8894fc..fac8fdacfd1 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
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.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/platform/bindings/shared_persistent.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/wtf/allocator/allocator.h"
@@ -28,7 +27,7 @@ class ScriptValue;
// ModuleRecordProduceCacheData is a parameter object for
// ModuleRecord::ProduceCache().
class CORE_EXPORT ModuleRecordProduceCacheData final
- : public GarbageCollectedFinalized<ModuleRecordProduceCacheData> {
+ : public GarbageCollected<ModuleRecordProduceCacheData> {
public:
ModuleRecordProduceCacheData(v8::Isolate*,
SingleCachedMetadataHandler*,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
index 4004a722cbe..7ea955c253d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
@@ -259,7 +259,7 @@ TEST(NativeValueTraitsImplTest, IDLSequence) {
EvaluateScriptForArray(scope, "['Vini, vidi, vici.', 65535, 0.125]");
NonThrowableExceptionState exception_state;
- Vector<ScriptValue> script_value_vector =
+ HeapVector<ScriptValue> script_value_vector =
NativeValueTraits<IDLSequence<ScriptValue>>::NativeValue(
scope.GetIsolate(), v8_array, exception_state);
EXPECT_EQ(3U, script_value_vector.size());
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 48ccf8594e2..ca5975ade93 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
@@ -68,8 +68,8 @@ struct ProfilerNodeFrameHash {
//
// The trace format is described at:
// https://wicg.github.io/js-self-profiling/#the-profilertrace-dictionary
-class ProfilerTraceBuilder
- : public GarbageCollectedFinalized<ProfilerTraceBuilder> {
+class ProfilerTraceBuilder final
+ : public GarbageCollected<ProfilerTraceBuilder> {
public:
static ProfilerTrace* FromProfile(ScriptState*,
const v8::CpuProfile* profile,
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 4875efec8a8..0dce491aec2 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
+#include "mojo/public/cpp/bindings/enum_utils.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "v8/include/v8.h"
@@ -58,9 +59,12 @@ ReferrerScriptInfo ReferrerScriptInfo::FromV8HostDefinedOptions(
v8::Local<v8::Primitive> referrer_policy_value =
host_defined_options->Get(isolate, kReferrerPolicy);
SECURITY_CHECK(referrer_policy_value->IsUint32());
+ int32_t referrer_policy_int32 = base::saturated_cast<int32_t>(
+ referrer_policy_value->IntegerValue(context).ToChecked());
network::mojom::ReferrerPolicy referrer_policy =
- static_cast<network::mojom::ReferrerPolicy>(
- referrer_policy_value->IntegerValue(context).ToChecked());
+ mojo::ConvertIntToMojoEnum<network::mojom::ReferrerPolicy>(
+ referrer_policy_int32)
+ .value_or(network::mojom::ReferrerPolicy::kDefault);
return ReferrerScriptInfo(base_url, credentials_mode, nonce, parser_state,
referrer_policy);
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 cb6ba97fcb1..9f459d22d1c 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
@@ -75,7 +75,7 @@ class RejectedPromises::Message final {
sanitize_script_errors_ == SanitizeScriptErrors::kDoNotSanitize) {
PromiseRejectionEventInit* init = PromiseRejectionEventInit::Create();
init->setPromise(ScriptPromise(script_state_, value));
- init->setReason(ScriptValue(script_state_, reason));
+ init->setReason(ScriptValue(script_state_->GetIsolate(), reason));
init->setCancelable(true);
PromiseRejectionEvent* event = PromiseRejectionEvent::Create(
script_state_, event_type_names::kUnhandledrejection, init);
@@ -115,7 +115,7 @@ class RejectedPromises::Message final {
sanitize_script_errors_ == SanitizeScriptErrors::kDoNotSanitize) {
PromiseRejectionEventInit* init = PromiseRejectionEventInit::Create();
init->setPromise(ScriptPromise(script_state_, value));
- init->setReason(ScriptValue(script_state_, reason));
+ init->setReason(ScriptValue(script_state_->GetIsolate(), reason));
PromiseRejectionEvent* event = PromiseRejectionEvent::Create(
script_state_, event_type_names::kRejectionhandled, init);
target->DispatchEvent(*event);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
index cb096bd269e..843cb14c3c2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -51,10 +51,11 @@
namespace blink {
-ScheduledAction* ScheduledAction::Create(ScriptState* script_state,
- ExecutionContext* target,
- V8Function* handler,
- const Vector<ScriptValue>& arguments) {
+ScheduledAction* ScheduledAction::Create(
+ ScriptState* script_state,
+ ExecutionContext* target,
+ V8Function* handler,
+ const HeapVector<ScriptValue>& arguments) {
if (!script_state->World().IsWorkerWorld()) {
if (!BindingSecurity::ShouldAllowAccessToFrame(
EnteredDOMWindow(script_state->GetIsolate()),
@@ -85,7 +86,7 @@ ScheduledAction* ScheduledAction::Create(ScriptState* script_state,
ScheduledAction::ScheduledAction(ScriptState* script_state,
V8Function* function,
- const Vector<ScriptValue>& arguments)
+ const HeapVector<ScriptValue>& arguments)
: script_state_(
MakeGarbageCollected<ScriptStateProtectingContext>(script_state)),
function_(function),
@@ -157,6 +158,7 @@ void ScheduledAction::Execute(ExecutionContext* context) {
void ScheduledAction::Trace(blink::Visitor* visitor) {
visitor->Trace(script_state_);
visitor->Trace(function_);
+ visitor->Trace(arguments_);
}
void ScheduledAction::Execute(LocalFrame* frame) {
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 5c6de14a14c..888c1c91ed0 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
@@ -47,7 +47,7 @@ class ScriptValue;
class V8Function;
class WorkerGlobalScope;
-class ScheduledAction final : public GarbageCollectedFinalized<ScheduledAction>,
+class ScheduledAction final : public GarbageCollected<ScheduledAction>,
public NameClient {
DISALLOW_COPY_AND_ASSIGN(ScheduledAction);
@@ -55,14 +55,14 @@ class ScheduledAction final : public GarbageCollectedFinalized<ScheduledAction>,
static ScheduledAction* Create(ScriptState*,
ExecutionContext* target,
V8Function* handler,
- const Vector<ScriptValue>& arguments);
+ const HeapVector<ScriptValue>& arguments);
static ScheduledAction* Create(ScriptState*,
ExecutionContext* target,
const String& handler);
explicit ScheduledAction(ScriptState*,
V8Function* handler,
- const Vector<ScriptValue>& arguments);
+ const HeapVector<ScriptValue>& arguments);
explicit ScheduledAction(ScriptState*, const String& handler);
// Creates an empty ScheduledAction.
explicit ScheduledAction(ScriptState*);
@@ -83,7 +83,7 @@ class ScheduledAction final : public GarbageCollectedFinalized<ScheduledAction>,
Member<ScriptStateProtectingContext> script_state_;
Member<V8Function> function_;
- Vector<ScriptValue> arguments_;
+ HeapVector<ScriptValue> arguments_;
String code_;
};
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
index 53dac106484..e2cc2813646 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
@@ -39,7 +39,6 @@
#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/platform/bindings/shared_persistent.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
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 dfbfed1ca13..aae5dbeba44 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
@@ -262,7 +262,7 @@ v8::Local<v8::Object> ScriptCustomElementDefinition::Constructor() const {
// CustomElementDefinition
ScriptValue ScriptCustomElementDefinition::GetConstructorForScript() {
- return ScriptValue(script_state_, Constructor());
+ return ScriptValue(script_state_->GetIsolate(), Constructor());
}
bool ScriptCustomElementDefinition::HasConnectedCallback() const {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
index 3657116ff81..849ba6405ae 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
@@ -34,7 +34,8 @@ ScriptValue ScriptFunction::Call(ScriptValue) {
}
void ScriptFunction::CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) {
- ScriptValue result = Call(ScriptValue(GetScriptState(), args[0]));
+ ScriptValue result =
+ Call(ScriptValue(GetScriptState()->GetIsolate(), args[0]));
V8SetReturnValue(args, result.V8Value());
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
index b031ff084e5..25ec59b272e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
@@ -36,18 +36,16 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "v8/include/v8.h"
namespace blink {
namespace {
-class PromiseAllHandler final
- : public GarbageCollectedFinalized<PromiseAllHandler> {
+class PromiseAllHandler final : public GarbageCollected<PromiseAllHandler> {
public:
static ScriptPromise All(ScriptState* script_state,
- const Vector<ScriptPromise>& promises) {
+ const HeapVector<ScriptPromise>& promises) {
if (promises.IsEmpty())
return ScriptPromise::Cast(script_state,
v8::Array::New(script_state->GetIsolate()));
@@ -55,7 +53,8 @@ class PromiseAllHandler final
->resolver_.Promise();
}
- PromiseAllHandler(ScriptState* script_state, Vector<ScriptPromise> promises)
+ PromiseAllHandler(ScriptState* script_state,
+ HeapVector<ScriptPromise> promises)
: number_of_pending_promises_(promises.size()), resolver_(script_state) {
DCHECK(!promises.IsEmpty());
values_.resize(promises.size());
@@ -65,7 +64,10 @@ class PromiseAllHandler final
}
}
- virtual void Trace(blink::Visitor* visitor) { visitor->Trace(resolver_); }
+ virtual void Trace(blink::Visitor* visitor) {
+ visitor->Trace(resolver_);
+ visitor->Trace(values_);
+ }
private:
class AdapterFunction : public ScriptFunction {
@@ -157,7 +159,7 @@ class PromiseAllHandler final
// This is cleared when owners of this handler, that is, given promises are
// settled.
- Vector<ScriptValue> values_;
+ HeapVector<ScriptValue> values_;
DISALLOW_COPY_AND_ASSIGN(PromiseAllHandler);
};
@@ -166,7 +168,7 @@ class PromiseAllHandler final
ScriptPromise::InternalResolver::InternalResolver(ScriptState* script_state)
: script_state_(script_state),
- resolver_(script_state,
+ resolver_(script_state->GetIsolate(),
v8::Promise::Resolver::New(script_state->GetContext())) {
// |resolver| can be empty when the thread is being terminated. We ignore such
// errors.
@@ -210,38 +212,26 @@ void ScriptPromise::InternalResolver::Reject(v8::Local<v8::Value> value) {
Clear();
}
-ScriptPromise::ScriptPromise() {
- IncreaseInstanceCount();
-}
-
ScriptPromise::ScriptPromise(ScriptState* script_state,
v8::Local<v8::Value> value)
: script_state_(script_state) {
- IncreaseInstanceCount();
-
if (value.IsEmpty())
return;
if (!value->IsPromise()) {
- promise_ = ScriptValue(script_state, v8::Local<v8::Value>());
+ promise_ = ScriptValue();
V8ThrowException::ThrowTypeError(script_state->GetIsolate(),
"the given value is not a Promise");
return;
}
- promise_ = ScriptValue(script_state, value);
+ promise_ = ScriptValue(script_state->GetIsolate(), value);
}
ScriptPromise::ScriptPromise(const ScriptPromise& other) {
- IncreaseInstanceCount();
-
this->script_state_ = other.script_state_;
this->promise_ = other.promise_;
}
-ScriptPromise::~ScriptPromise() {
- DecreaseInstanceCount();
-}
-
ScriptPromise ScriptPromise::Then(v8::Local<v8::Function> on_fulfilled,
v8::Local<v8::Function> on_rejected) {
if (promise_.IsEmpty())
@@ -350,16 +340,8 @@ void ScriptPromise::MarkAsHandled() {
}
ScriptPromise ScriptPromise::All(ScriptState* script_state,
- const Vector<ScriptPromise>& promises) {
+ const HeapVector<ScriptPromise>& promises) {
return PromiseAllHandler::All(script_state, promises);
}
-void ScriptPromise::IncreaseInstanceCount() {
- InstanceCounters::IncrementCounter(InstanceCounters::kScriptPromiseCounter);
-}
-
-void ScriptPromise::DecreaseInstanceCount() {
- InstanceCounters::DecrementCounter(InstanceCounters::kScriptPromiseCounter);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
index 555de6a7c09..fde92c9aeb2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
@@ -57,7 +57,7 @@ class CORE_EXPORT ScriptPromise final {
public:
// Constructs an empty promise.
- ScriptPromise();
+ ScriptPromise() = default;
// Constructs a ScriptPromise from |promise|.
// If |promise| is not a Promise object, throws a v8 TypeError.
@@ -65,7 +65,7 @@ class CORE_EXPORT ScriptPromise final {
ScriptPromise(const ScriptPromise&);
- ~ScriptPromise();
+ ~ScriptPromise() = default;
ScriptPromise Then(v8::Local<v8::Function> on_fulfilled,
v8::Local<v8::Function> on_rejected = {});
@@ -121,7 +121,13 @@ class CORE_EXPORT ScriptPromise final {
// Constructs and returns a ScriptPromise to be resolved when all |promises|
// are resolved. If one of |promises| is rejected, the returned
// ScriptPromise is rejected.
- static ScriptPromise All(ScriptState*, const Vector<ScriptPromise>& promises);
+ static ScriptPromise All(ScriptState*,
+ const HeapVector<ScriptPromise>& promises);
+
+ void Trace(Visitor* visitor) {
+ visitor->Trace(promise_);
+ visitor->Trace(script_state_);
+ }
// This is a utility class intended to be used internally.
// ScriptPromiseResolver is for general purpose.
@@ -136,7 +142,10 @@ class CORE_EXPORT ScriptPromise final {
void Reject(v8::Local<v8::Value>);
void Clear() { resolver_.Clear(); }
ScriptState* GetScriptState() const { return script_state_; }
- void Trace(blink::Visitor* visitor) { visitor->Trace(script_state_); }
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
+ visitor->Trace(resolver_);
+ }
private:
Member<ScriptState> script_state_;
@@ -147,12 +156,21 @@ class CORE_EXPORT ScriptPromise final {
static void IncreaseInstanceCount();
static void DecreaseInstanceCount();
- // TODO(peria): Move ScriptPromise to Oilpan heap.
- GC_PLUGIN_IGNORE("813731")
- Persistent<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
ScriptValue promise_;
};
} // namespace blink
+namespace WTF {
+
+template <>
+struct VectorTraits<blink::ScriptPromise>
+ : VectorTraitsBase<blink::ScriptPromise> {
+ STATIC_ONLY(VectorTraits);
+ static constexpr bool kCanClearUnusedSlotsWithMemset = true;
+};
+
+} // namespace WTF
+
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_PROMISE_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
index cf1785b4cce..11cb4eef85d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
@@ -25,7 +25,7 @@ class ScriptState;
// TODO(yhirano): Remove NOINLINE once we find the cause of crashes.
class CORE_EXPORT ScriptPromisePropertyBase
- : public GarbageCollectedFinalized<ScriptPromisePropertyBase>,
+ : public GarbageCollected<ScriptPromisePropertyBase>,
public ContextClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptPromisePropertyBase);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index 5ab7eba37e6..a64d5000304 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -154,7 +154,7 @@ class ScriptPromisePropertyTestBase {
ScriptState::From(ToV8Context(&GetDocument(), world));
ScriptState::Scope scope(script_state);
return ScriptValue(
- script_state,
+ GetIsolate(),
ToV8(value, script_state->GetContext()->Global(), GetIsolate()));
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
index 8b8ff3a6472..835b86b9c93 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
@@ -121,6 +121,7 @@ void ScriptPromiseResolver::ResolveOrRejectDeferred() {
void ScriptPromiseResolver::Trace(blink::Visitor* visitor) {
visitor->Trace(script_state_);
visitor->Trace(resolver_);
+ visitor->Trace(value_);
ContextLifecycleObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
index 934967b1c01..929535af650 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
@@ -36,7 +36,7 @@ namespace blink {
// There are cases where promises cannot work (e.g., where the thread is being
// terminated). In such cases operations will silently fail.
class CORE_EXPORT ScriptPromiseResolver
- : public GarbageCollectedFinalized<ScriptPromiseResolver>,
+ : public GarbageCollected<ScriptPromiseResolver>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(ScriptPromiseResolver);
USING_PRE_FINALIZER(ScriptPromiseResolver, Dispose);
@@ -148,7 +148,7 @@ class CORE_EXPORT ScriptPromiseResolver
const Member<ScriptState> script_state_;
TaskHandle deferred_resolve_task_;
Resolver resolver_;
- ScopedPersistent<v8::Value> value_;
+ TraceWrapperV8Reference<v8::Value> value_;
// To support keepAliveWhilePending(), this object needs to keep itself
// alive while in that state.
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
index 0243503c357..7d92626c7d8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
index 49e6343f0bf..0e4aa4195a8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
@@ -283,8 +283,8 @@ TEST(ScriptPromiseTest, CastNonPromise) {
V8TestingScope scope;
ScriptValue on_fulfilled1, on_fulfilled2, on_rejected1, on_rejected2;
- ScriptValue value = ScriptValue(scope.GetScriptState(),
- V8String(scope.GetIsolate(), "hello"));
+ ScriptValue value =
+ ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello"));
ScriptPromise promise1 =
ScriptPromise::Cast(scope.GetScriptState(), ScriptValue(value));
ScriptPromise promise2 =
@@ -322,8 +322,8 @@ TEST(ScriptPromiseTest, Reject) {
V8TestingScope scope;
ScriptValue on_fulfilled, on_rejected;
- ScriptValue value = ScriptValue(scope.GetScriptState(),
- V8String(scope.GetIsolate(), "hello"));
+ ScriptValue value =
+ ScriptValue(scope.GetIsolate(), V8String(scope.GetIsolate(), "hello"));
ScriptPromise promise =
ScriptPromise::Reject(scope.GetScriptState(), ScriptValue(value));
promise.Then(FunctionForScriptPromiseTest::CreateFunction(
@@ -371,7 +371,7 @@ TEST(ScriptPromiseTest, AllWithEmptyPromises) {
ScriptValue on_fulfilled, on_rejected;
ScriptPromise promise =
- ScriptPromise::All(scope.GetScriptState(), Vector<ScriptPromise>());
+ ScriptPromise::All(scope.GetScriptState(), HeapVector<ScriptPromise>());
ASSERT_FALSE(promise.IsEmpty());
promise.Then(FunctionForScriptPromiseTest::CreateFunction(
@@ -393,7 +393,7 @@ TEST(ScriptPromiseTest, AllWithResolvedPromises) {
V8TestingScope scope;
ScriptValue on_fulfilled, on_rejected;
- Vector<ScriptPromise> promises;
+ HeapVector<ScriptPromise> promises;
promises.push_back(ScriptPromise::Cast(
scope.GetScriptState(), V8String(scope.GetIsolate(), "hello")));
promises.push_back(ScriptPromise::Cast(
@@ -423,7 +423,7 @@ TEST(ScriptPromiseTest, AllWithRejectedPromise) {
V8TestingScope scope;
ScriptValue on_fulfilled, on_rejected;
- Vector<ScriptPromise> promises;
+ HeapVector<ScriptPromise> promises;
promises.push_back(ScriptPromise::Cast(
scope.GetScriptState(), V8String(scope.GetIsolate(), "hello")));
promises.push_back(ScriptPromise::Reject(
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.cc
new file mode 100644
index 00000000000..c9f005bd171
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.cc
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
+
+#include <utility>
+
+#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/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class ScriptPromiseTester::ThenFunction : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> CreateFunction(
+ ScriptState* script_state,
+ base::WeakPtr<ScriptPromiseTester> owner,
+ ScriptPromiseTester::State target_state) {
+ ThenFunction* self = MakeGarbageCollected<ThenFunction>(
+ script_state, std::move(owner), target_state);
+ return self->BindToV8Function();
+ }
+
+ ThenFunction(ScriptState* script_state,
+ base::WeakPtr<ScriptPromiseTester> owner,
+ ScriptPromiseTester::State target_state)
+ : ScriptFunction(script_state),
+ owner_(std::move(owner)),
+ target_state_(target_state) {}
+
+ ScriptValue Call(ScriptValue value) override {
+ if (!owner_)
+ return value;
+
+ DCHECK_EQ(owner_->state_, State::kNotSettled);
+ owner_->state_ = target_state_;
+
+ DCHECK(owner_->value_.IsEmpty());
+ owner_->value_ = value;
+ return value;
+ }
+
+ private:
+ base::WeakPtr<ScriptPromiseTester> owner_;
+ State target_state_;
+};
+
+ScriptPromiseTester::ScriptPromiseTester(ScriptState* script_state,
+ ScriptPromise script_promise)
+ : script_state_(script_state) {
+ DCHECK(script_state);
+ script_promise.Then(
+ ThenFunction::CreateFunction(script_state, weak_factory_.GetWeakPtr(),
+ State::kFulfilled),
+ ThenFunction::CreateFunction(script_state, weak_factory_.GetWeakPtr(),
+ State::kRejected));
+}
+
+void ScriptPromiseTester::WaitUntilSettled() {
+ auto* isolate = script_state_->GetIsolate();
+ while (state_ == State::kNotSettled) {
+ v8::MicrotasksScope::PerformCheckpoint(isolate);
+ test::RunPendingTasks();
+ }
+}
+
+ScriptValue ScriptPromiseTester::Value() const {
+ return value_;
+}
+
+void ScriptPromiseTester::Trace(Visitor* visitor) {
+ visitor->Trace(script_state_);
+ visitor->Trace(value_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.h
new file mode 100644
index 00000000000..63a52f1673e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_tester.h
@@ -0,0 +1,61 @@
+// 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_BINDINGS_CORE_V8_SCRIPT_PROMISE_TESTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_PROMISE_TESTER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class ScriptState;
+class ScriptPromise;
+class Visitor;
+
+// Utility for writing unit tests involving promises.
+// Typical usage:
+// ScriptPromiseTester tester(script_state, script_promise);
+// tester.WaitUntilSettled(); // Runs a nested event loop.
+// EXPECT_TRUE(tester.IsFulfilled());
+// EXPECT_TRUE(tester.Value().IsUndefined());
+class ScriptPromiseTester final {
+ DISALLOW_NEW();
+
+ public:
+ ScriptPromiseTester(ScriptState*, ScriptPromise);
+
+ // Run microtasks and tasks until the promise is either fulfilled or rejected.
+ // If the promise never settles this will busy loop until the test times out.
+ void WaitUntilSettled();
+
+ // Did the promise fulfill?
+ bool IsFulfilled() const { return state_ == State::kFulfilled; }
+
+ // Did the promise reject?
+ bool IsRejected() const { return state_ == State::kRejected; }
+
+ // The value the promise fulfilled or rejected with.
+ ScriptValue Value() const;
+
+ void Trace(Visitor*);
+
+ private:
+ class ThenFunction;
+
+ enum class State { kNotSettled, kFulfilled, kRejected };
+
+ Member<ScriptState> script_state_;
+ State state_ = State::kNotSettled;
+ ScriptValue value_;
+
+ base::WeakPtrFactory<ScriptPromiseTester> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(ScriptPromiseTester);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_PROMISE_TESTER_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 2993ffb7c08..afd83f83ae7 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
index 43f3998a6ba..685112d599d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -29,7 +29,7 @@ class ResponseBodyLoaderClient;
// ClassicPendingScript are destroyed while the streaming is in progress, and
// ScriptStreamer handles it gracefully.
class CORE_EXPORT ScriptStreamer final
- : public GarbageCollectedFinalized<ScriptStreamer> {
+ : public GarbageCollected<ScriptStreamer> {
USING_PRE_FINALIZER(ScriptStreamer, Prefinalize);
public:
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 1cd0bdcc1c1..93db3b70169 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
@@ -43,9 +43,8 @@ namespace blink {
namespace {
-class TestResourceClient final
- : public GarbageCollectedFinalized<TestResourceClient>,
- public ResourceClient {
+class TestResourceClient final : public GarbageCollected<TestResourceClient>,
+ public ResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(TestResourceClient);
public:
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
index 4df0baeb46e..ed52b29b0f2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
@@ -35,43 +35,13 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
-namespace {
-
-v8::Local<v8::Value> ToWorldSafeValue(ScriptState* target_script_state,
- v8::Local<v8::Value> value) {
- if (value.IsEmpty() || !value->IsObject())
- return value;
-
- v8::Local<v8::Context> creation_context =
- value.As<v8::Object>()->CreationContext();
- v8::Isolate* isolate = target_script_state->GetIsolate();
- if (&ScriptState::From(creation_context)->World() ==
- &target_script_state->World()) {
- return value;
- }
-
- v8::Context::Scope target_context_scope(target_script_state->GetContext());
- scoped_refptr<SerializedScriptValue> serialized =
- SerializedScriptValue::SerializeAndSwallowExceptions(isolate, value);
- return serialized->Deserialize(isolate);
-}
-
-} // namespace
v8::Local<v8::Value> ScriptValue::V8Value() const {
if (IsEmpty())
return v8::Local<v8::Value>();
DCHECK(GetIsolate()->InContext());
-
- // This is a check to validate that you don't return a ScriptValue to a world
- // different from the world that created the ScriptValue.
- // Probably this could be:
- // if (&script_state_->world() == &DOMWrapperWorld::current(isolate()))
- // return v8::Local<v8::Value>();
- // instead of triggering CHECK.
- CHECK_EQ(&script_state_->World(), &DOMWrapperWorld::Current(GetIsolate()));
- return value_->NewLocal(GetIsolate());
+ return value_->Get(ScriptState::From(isolate_->GetCurrentContext()));
}
v8::Local<v8::Value> ScriptValue::V8ValueFor(
@@ -79,15 +49,13 @@ v8::Local<v8::Value> ScriptValue::V8ValueFor(
if (IsEmpty())
return v8::Local<v8::Value>();
- return ToWorldSafeValue(target_script_state,
- value_->NewLocal(target_script_state->GetIsolate()));
+ return value_->GetAcrossWorld(target_script_state);
}
bool ScriptValue::ToString(String& result) const {
if (IsEmpty())
return false;
- ScriptState::Scope scope(script_state_);
v8::Local<v8::Value> string = V8Value();
if (string.IsEmpty() || !string->IsString())
return false;
@@ -95,8 +63,8 @@ bool ScriptValue::ToString(String& result) const {
return true;
}
-ScriptValue ScriptValue::CreateNull(ScriptState* script_state) {
- return ScriptValue(script_state, v8::Null(script_state->GetIsolate()));
+ScriptValue ScriptValue::CreateNull(v8::Isolate* isolate) {
+ return ScriptValue(isolate, v8::Null(isolate));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
index 3027b1c9877..791d6556280 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
@@ -33,9 +33,10 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
+#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/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/shared_persistent.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.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"
@@ -69,44 +70,34 @@ class CORE_EXPORT ScriptValue final {
ScriptValue() = default;
- ScriptValue(ScriptState* script_state, v8::Local<v8::Value> value)
- : script_state_(script_state),
- value_(value.IsEmpty() ? nullptr
- : SharedPersistent<v8::Value>::Create(
- value,
- script_state->GetIsolate())) {
- DCHECK(IsEmpty() || script_state_);
+ ScriptValue(v8::Isolate* isolate, v8::Local<v8::Value> value)
+ : isolate_(isolate),
+ value_(
+ MakeGarbageCollected<WorldSafeV8ReferenceWrapper>(isolate, value)) {
+ DCHECK(isolate_);
}
template <typename T>
- ScriptValue(ScriptState* script_state, v8::MaybeLocal<T> value)
- : script_state_(script_state),
- value_(value.IsEmpty() ? nullptr
- : SharedPersistent<v8::Value>::Create(
- value.ToLocalChecked(),
- script_state->GetIsolate())) {
- DCHECK(IsEmpty() || script_state_);
+ ScriptValue(v8::Isolate* isolate, v8::MaybeLocal<T> value)
+ : isolate_(isolate),
+ value_(value.IsEmpty()
+ ? MakeGarbageCollected<WorldSafeV8ReferenceWrapper>()
+ : MakeGarbageCollected<WorldSafeV8ReferenceWrapper>(
+ isolate,
+ value.ToLocalChecked())) {
+ DCHECK(isolate_);
}
- ScriptValue(const ScriptValue& value)
- : script_state_(value.script_state_), value_(value.value_) {
- DCHECK(IsEmpty() || script_state_);
- }
-
- ScriptState* GetScriptState() const { return script_state_; }
+ ScriptValue(const ScriptValue& value) = default;
+ // TODO(riakf): Use this GetIsolate() only when doing DCHECK inside
+ // ScriptValue.
v8::Isolate* GetIsolate() const {
- return script_state_ ? script_state_->GetIsolate()
- : v8::Isolate::GetCurrent();
+ DCHECK(isolate_);
+ return isolate_;
}
- ScriptValue& operator=(const ScriptValue& value) {
- if (this != &value) {
- script_state_ = value.script_state_;
- value_ = value.value_;
- }
- return *this;
- }
+ ScriptValue& operator=(const ScriptValue& value) = default;
bool operator==(const ScriptValue& value) const {
if (IsEmpty())
@@ -150,9 +141,12 @@ class CORE_EXPORT ScriptValue final {
return !value.IsEmpty() && value->IsObject();
}
- bool IsEmpty() const { return !value_.get() || value_->IsEmpty(); }
+ bool IsEmpty() const { return !value_ || value_->IsEmpty(); }
- void Clear() { value_ = nullptr; }
+ void Clear() {
+ isolate_ = nullptr;
+ value_.Clear();
+ }
v8::Local<v8::Value> V8Value() const;
// Returns v8Value() if a given ScriptState is the same as the
@@ -162,13 +156,46 @@ class CORE_EXPORT ScriptValue final {
bool ToString(String&) const;
- static ScriptValue CreateNull(ScriptState*);
+ static ScriptValue CreateNull(v8::Isolate*);
+
+ void Trace(Visitor* visitor) { visitor->Trace(value_); }
private:
- // TODO(peria): Move ScriptValue to Oilpan heap.
- GC_PLUGIN_IGNORE("813731")
- Persistent<ScriptState> script_state_;
- scoped_refptr<SharedPersistent<v8::Value>> value_;
+ // WorldSafeV8ReferenceWrapper wraps a WorldSafeV8Reference so that it can be
+ // used on both the stack and heaps. WorldSafeV8Reference cannot be used on
+ // the stack because the conservative scanning does not know how to trace
+ // TraceWrapperV8Reference.
+ class CORE_EXPORT WorldSafeV8ReferenceWrapper
+ : public GarbageCollected<WorldSafeV8ReferenceWrapper> {
+ public:
+ WorldSafeV8ReferenceWrapper() = default;
+ WorldSafeV8ReferenceWrapper(v8::Isolate* isolate,
+ v8::Local<v8::Value> value)
+ : value_(isolate, value) {}
+
+ virtual ~WorldSafeV8ReferenceWrapper() = default;
+ void Trace(blink::Visitor* visitor) { visitor->Trace(value_); }
+
+ v8::Local<v8::Value> Get(ScriptState* script_state) const {
+ return value_.Get(script_state);
+ }
+
+ v8::Local<v8::Value> GetAcrossWorld(ScriptState* script_state) const {
+ return value_.GetAcrossWorld(script_state);
+ }
+
+ bool IsEmpty() const { return value_.IsEmpty(); }
+
+ bool operator==(const WorldSafeV8ReferenceWrapper& other) const {
+ return value_ == other.value_;
+ }
+
+ private:
+ WorldSafeV8Reference<v8::Value> value_;
+ };
+
+ v8::Isolate* isolate_ = nullptr;
+ Member<WorldSafeV8ReferenceWrapper> value_;
};
template <>
@@ -177,10 +204,20 @@ struct NativeValueTraits<ScriptValue>
static inline ScriptValue NativeValue(v8::Isolate* isolate,
v8::Local<v8::Value> value,
ExceptionState& exception_state) {
- return ScriptValue(ScriptState::Current(isolate), value);
+ return ScriptValue(isolate, value);
}
};
} // namespace blink
+namespace WTF {
+
+template <>
+struct VectorTraits<blink::ScriptValue> : VectorTraitsBase<blink::ScriptValue> {
+ STATIC_ONLY(VectorTraits);
+ static constexpr bool kCanClearUnusedSlotsWithMemset = true;
+};
+
+} // namespace WTF
+
#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_VALUE_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
index 33320193204..0bad9aae85c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
+#include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h
index 2edf1d69a5f..0dce019e0c6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SERIALIZATION_POST_MESSAGE_HELPER_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom-blink.h"
+#include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "v8/include/v8.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
index 6a926077a78..f4e1d24b263 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -67,7 +67,6 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
@@ -518,7 +517,7 @@ bool SerializedScriptValue::ExtractTransferables(
if (value.IsEmpty() || value->IsUndefined())
return true;
- const Vector<ScriptValue>& transferable_array =
+ const HeapVector<ScriptValue>& transferable_array =
NativeValueTraits<IDLSequence<ScriptValue>>::NativeValue(isolate, value,
exception_state);
if (exception_state.HadException())
@@ -530,7 +529,7 @@ bool SerializedScriptValue::ExtractTransferables(
bool SerializedScriptValue::ExtractTransferables(
v8::Isolate* isolate,
- const Vector<ScriptValue>& object_sequence,
+ const HeapVector<ScriptValue>& object_sequence,
Transferables& transferables,
ExceptionState& exception_state) {
// Validate the passed array of transferables.
@@ -705,6 +704,16 @@ SerializedScriptValue::TransferArrayBufferContents(
contents.Grow(array_buffers.size());
HeapHashSet<Member<DOMArrayBufferBase>> visited;
+ // The scope object to promptly free the backing store to avoid memory
+ // regressions.
+ // TODO(bikineev): Revisit after young generation is there.
+ struct PromptlyFreeSet {
+ // The void* is to avoid blink-gc-plugin error.
+ void* buffer;
+ ~PromptlyFreeSet() {
+ static_cast<HeapHashSet<Member<DOMArrayBufferBase>>*>(buffer)->clear();
+ }
+ } promptly_free_array_buffers{&visited};
for (auto* it = array_buffers.begin(); it != array_buffers.end(); ++it) {
DOMArrayBufferBase* array_buffer_base = *it;
if (visited.Contains(array_buffer_base))
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 d1edfe780db..52d1f2aea4e 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
@@ -74,8 +74,7 @@ class CORE_EXPORT SerializedScriptValue
using ArrayBufferContentsArray = Vector<WTF::ArrayBufferContents, 1>;
using SharedArrayBufferContentsArray = Vector<WTF::ArrayBufferContents, 1>;
using ImageBitmapContentsArray = Vector<scoped_refptr<StaticBitmapImage>, 1>;
- using TransferredWasmModulesArray =
- WTF::Vector<v8::WasmModuleObject::TransferrableModule>;
+ using TransferredWasmModulesArray = WTF::Vector<v8::CompiledWasmModule>;
using MessagePortChannelArray = Vector<MessagePortChannel>;
// Increment this for each incompatible change to the wire format.
@@ -205,7 +204,7 @@ class CORE_EXPORT SerializedScriptValue
Transferables&,
ExceptionState&);
static bool ExtractTransferables(v8::Isolate*,
- const Vector<ScriptValue>&,
+ const HeapVector<ScriptValue>&,
Transferables&,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.cc
new file mode 100644
index 00000000000..f3929db0f1f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.cc
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/bindings/core/v8/serialization/transferables.h"
+
+#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/mojo/mojo_handle.h"
+#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
+#include "third_party/blink/renderer/core/streams/readable_stream.h"
+#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"
+
+namespace blink {
+
+Transferables::~Transferables() {
+ // Explicitly free all backing stores for containers to avoid memory
+ // regressions.
+ // TODO(bikineev): Revisit after young generation is there.
+ array_buffers.clear();
+ image_bitmaps.clear();
+ offscreen_canvases.clear();
+ message_ports.clear();
+ mojo_handles.clear();
+ readable_streams.clear();
+ writable_streams.clear();
+ transform_streams.clear();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h
index 4883b80b8be..e813ef37d87 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h
@@ -35,6 +35,7 @@ class CORE_EXPORT Transferables final {
public:
Transferables() = default;
+ ~Transferables();
ArrayBufferArray array_buffers;
ImageBitmapArray image_bitmaps;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h
index 6d93d2feac9..cb97edb5ea9 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h
@@ -35,8 +35,8 @@ class ImageBitmap;
// but (for security reasons) separate JavaScript wrappers must exist. For this
// reason, a SerializedScriptValue can only be unpacked once, but thereafter it
// can be deserialized multiple times.
-class CORE_EXPORT UnpackedSerializedScriptValue
- : public GarbageCollectedFinalized<UnpackedSerializedScriptValue> {
+class CORE_EXPORT UnpackedSerializedScriptValue final
+ : public GarbageCollected<UnpackedSerializedScriptValue> {
public:
// Callers should use SerializedScriptValue::Unpack.
explicit UnpackedSerializedScriptValue(scoped_refptr<SerializedScriptValue>);
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 0b0da0ca5bf..042a35881ed 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
@@ -325,8 +325,9 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
if (!ReadUint32(&is_premultiplied) || is_premultiplied > 1)
return nullptr;
break;
- default:
- NOTREACHED();
+ case ImageSerializationTag::kImageDataStorageFormatTag:
+ // Does not apply to ImageBitmap.
+ return nullptr;
}
} while (!is_done);
} else if (!ReadUint32(&origin_clean) || origin_clean > 1 ||
@@ -384,8 +385,12 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
&image_data_storage_format))
return nullptr;
break;
- default:
- NOTREACHED();
+ case ImageSerializationTag::kCanvasPixelFormatTag:
+ case ImageSerializationTag::kOriginCleanTag:
+ case ImageSerializationTag::kIsPremultipliedTag:
+ case ImageSerializationTag::kCanvasOpacityModeTag:
+ // Does not apply to ImageData.
+ return nullptr;
}
} while (!is_done);
}
@@ -509,7 +514,8 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
!ReadUint32(&canvas_id) || !ReadUint32(&client_id) ||
!ReadUint32(&sink_id))
return nullptr;
- OffscreenCanvas* canvas = OffscreenCanvas::Create(width, height);
+ OffscreenCanvas* canvas = OffscreenCanvas::Create(
+ ExecutionContext::From(GetScriptState()), width, height);
canvas->SetPlaceholderCanvasId(canvas_id);
canvas->SetFrameSinkId(client_id, sink_id);
return canvas;
@@ -692,7 +698,7 @@ v8::MaybeLocal<v8::WasmModuleObject>
V8ScriptValueDeserializer::GetWasmModuleFromId(v8::Isolate* isolate,
uint32_t id) {
if (id < serialized_script_value_->WasmModules().size()) {
- return v8::WasmModuleObject::FromTransferrableModule(
+ return v8::WasmModuleObject::FromCompiledModule(
isolate, serialized_script_value_->WasmModules()[id]);
}
CHECK(serialized_script_value_->WasmModules().IsEmpty());
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 90821da650b..5c6173a1cae 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h"
#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/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
@@ -28,6 +29,7 @@
#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"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_read_only.h"
#include "third_party/blink/renderer/core/geometry/dom_point.h"
@@ -42,6 +44,7 @@
#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/file_metadata.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/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
@@ -151,6 +154,16 @@ void V8ScriptValueSerializer::FinalizeTransfer(
v8::Isolate* isolate = script_state_->GetIsolate();
ArrayBufferArray array_buffers;
+ // The scope object to promptly free the backing store to avoid memory
+ // regressions.
+ // TODO(bikineev): Revisit after young generation is there.
+ struct PromptlyFreeArrayBuffers {
+ // The void* is to avoid blink-gc-plugin error.
+ void* buffer;
+ ~PromptlyFreeArrayBuffers() {
+ static_cast<ArrayBufferArray*>(buffer)->clear();
+ }
+ } promptly_free_array_buffers{&array_buffers};
if (transferables_)
array_buffers.AppendVector(transferables_->array_buffers);
@@ -248,11 +261,20 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
return false;
}
+ auto* execution_context = ExecutionContext::From(script_state_.Get());
// If this ImageBitmap was transferred, it can be serialized by index.
size_t index = kNotFound;
if (transferables_)
index = transferables_->image_bitmaps.Find(image_bitmap);
if (index != kNotFound) {
+ if (image_bitmap->OriginClean()) {
+ execution_context->CountUse(
+ mojom::WebFeature::kOriginCleanImageBitmapTransfer);
+ } else {
+ execution_context->CountUse(
+ mojom::WebFeature::kNonOriginCleanImageBitmapTransfer);
+ }
+
DCHECK_LE(index, std::numeric_limits<uint32_t>::max());
WriteTag(kImageBitmapTransferTag);
WriteUint32(static_cast<uint32_t>(index));
@@ -260,6 +282,13 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
}
// Otherwise, it must be fully serialized.
+ if (image_bitmap->OriginClean()) {
+ execution_context->CountUse(
+ mojom::WebFeature::kOriginCleanImageBitmapSerialization);
+ } else {
+ execution_context->CountUse(
+ mojom::WebFeature::kNonOriginCleanImageBitmapSerialization);
+ }
WriteTag(kImageBitmapTag);
SerializedColorParams color_params(image_bitmap->GetCanvasColorParams());
WriteUint32Enum(ImageSerializationTag::kCanvasColorSpaceTag);
@@ -275,9 +304,17 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
WriteUint32Enum(ImageSerializationTag::kEndTag);
WriteUint32(image_bitmap->width());
WriteUint32(image_bitmap->height());
- scoped_refptr<Uint8Array> pixels = image_bitmap->CopyBitmapData();
- WriteUint32(pixels->length());
- WriteRawBytes(pixels->Data(), pixels->length());
+ Vector<uint8_t> pixels = image_bitmap->CopyBitmapData();
+ // Check if we succeeded to copy the BitmapData.
+ if (image_bitmap->width() != 0 && image_bitmap->height() != 0 &&
+ pixels.size() == 0) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kDataCloneError,
+ "An ImageBitmap could not be read successfully.");
+ return false;
+ }
+ WriteUint32(pixels.size());
+ WriteRawBytes(pixels.data(), pixels.size());
return true;
}
if (wrapper_type_info == V8ImageData::GetWrapperTypeInfo()) {
@@ -725,7 +762,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetWasmModuleTransferId(
// around. Most likely, we'll have one module. The vector approach is
// simple and should perform sufficiently well under these expectations.
serialized_script_value_->WasmModules().push_back(
- module->GetTransferrableModule());
+ module->GetCompiledModule());
uint32_t size =
static_cast<uint32_t>(serialized_script_value_->WasmModules().size());
DCHECK_GE(size, 1u);
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 de2d7f680ec..981efb4bf1e 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
@@ -855,6 +855,19 @@ TEST(V8ScriptValueSerializerTest, DecodeImageDataV18) {
new_image_data->BufferBase()->Data())[0]);
}
+TEST(V8ScriptValueSerializerTest, InvalidImageDataDecodeV18) {
+ V8TestingScope scope;
+ ScriptState* script_state = scope.GetScriptState();
+ {
+ // Nonsense image serialization tag (kOriginCleanTag).
+ scoped_refptr<SerializedScriptValue> input =
+ SerializedValue({0xff, 0x12, 0xff, 0x0d, 0x5c, 0x23, 0x02, 0x00, 0x00,
+ 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00});
+ EXPECT_TRUE(
+ V8ScriptValueDeserializer(script_state, input).Deserialize()->IsNull());
+ }
+}
+
MessagePort* MakeMessagePort(ExecutionContext* execution_context,
::MojoHandle* unowned_handle_out = nullptr) {
auto* port = MakeGarbageCollected<MessagePort>(*execution_context);
@@ -1252,6 +1265,14 @@ TEST(V8ScriptValueSerializerTest, InvalidImageBitmapDecodeV18) {
EXPECT_TRUE(
V8ScriptValueDeserializer(script_state, input).Deserialize()->IsNull());
}
+ {
+ // Nonsense image serialization tag (kImageDataStorageFormatTag).
+ scoped_refptr<SerializedScriptValue> input =
+ SerializedValue({0xff, 0x12, 0xff, 0x0d, 0x5c, 0x67, 0x03, 0x00, 0x00,
+ 0x01, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00});
+ EXPECT_TRUE(
+ V8ScriptValueDeserializer(script_state, input).Deserialize()->IsNull());
+ }
}
TEST(V8ScriptValueSerializerTest, TransferImageBitmap) {
@@ -1293,7 +1314,8 @@ TEST(V8ScriptValueSerializerTest, TransferImageBitmap) {
TEST(V8ScriptValueSerializerTest, TransferOffscreenCanvas) {
// More exhaustive tests in web_tests/. This is a sanity check.
V8TestingScope scope;
- OffscreenCanvas* canvas = OffscreenCanvas::Create(10, 7);
+ OffscreenCanvas* canvas =
+ OffscreenCanvas::Create(scope.GetExecutionContext(), 10, 7);
canvas->SetPlaceholderCanvasId(519);
v8::Local<v8::Value> wrapper = ToV8(canvas, scope.GetScriptState());
Transferables transferables;
@@ -1850,7 +1872,7 @@ TEST(V8ScriptValueSerializerTest, RoundTripReadableStream) {
auto* rs = ReadableStream::Create(script_state, ASSERT_NO_EXCEPTION);
v8::Local<v8::Value> wrapper = ToV8(rs, script_state);
- Vector<ScriptValue> transferable_array = {ScriptValue(script_state, wrapper)};
+ HeapVector<ScriptValue> transferable_array = {ScriptValue(isolate, wrapper)};
Transferables transferables;
ASSERT_TRUE(SerializedScriptValue::ExtractTransferables(
isolate, transferable_array, transferables, ASSERT_NO_EXCEPTION));
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.cc b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.cc
index 51ba025d2a3..5e5ec0d9b34 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/frame/dom_window.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
@@ -49,4 +50,10 @@ v8::Local<v8::Value> ToV8(EventTarget* impl,
return ToV8(static_cast<ScriptWrappable*>(impl), creation_context, isolate);
}
+v8::Local<v8::Value> ToV8(Node* node,
+ v8::Local<v8::Object> creation_context,
+ v8::Isolate* isolate) {
+ return ToV8(static_cast<ScriptWrappable*>(node), creation_context, isolate);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
index d27e786867d..544815c302a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h
@@ -10,9 +10,9 @@
#include "third_party/blink/renderer/bindings/core/v8/idl_dictionary_base.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h"
+#include "third_party/blink/renderer/platform/heap/disallow_new_wrapper.h"
#include "v8/include/v8.h"
namespace blink {
@@ -27,11 +27,9 @@ CORE_EXPORT v8::Local<v8::Value> ToV8(DOMWindow*,
CORE_EXPORT v8::Local<v8::Value> ToV8(EventTarget*,
v8::Local<v8::Object> creation_context,
v8::Isolate*);
-inline v8::Local<v8::Value> ToV8(Node* node,
- v8::Local<v8::Object> creation_context,
- v8::Isolate* isolate) {
- return ToV8(static_cast<ScriptWrappable*>(node), creation_context, isolate);
-}
+CORE_EXPORT v8::Local<v8::Value> ToV8(Node* node,
+ v8::Local<v8::Object> creation_context,
+ v8::Isolate* isolate);
inline v8::Local<v8::Value> ToV8(const Dictionary& value,
v8::Local<v8::Object> creation_context,
@@ -67,11 +65,22 @@ inline v8::Local<v8::Value> ToV8(const ScriptValue& value,
return value.V8Value();
}
+inline v8::Local<v8::Value> ToV8(const DisallowNewWrapper<ScriptValue>* value,
+ v8::Local<v8::Object> creation_context,
+ v8::Isolate* isolate) {
+ if (value->Value().IsEmpty())
+ return v8::Undefined(isolate);
+ return value->Value().V8Value();
+}
+
// Cannot define in ScriptValue because of the circular dependency between toV8
// and ScriptValue
template <typename T>
inline ScriptValue ScriptValue::From(ScriptState* script_state, T&& value) {
- return ScriptValue(script_state, ToV8(std::forward<T>(value), script_state));
+ v8::Local<v8::Value> v8_value = ToV8(std::forward<T>(value), script_state);
+ if (v8_value.IsEmpty())
+ return ScriptValue();
+ return ScriptValue(script_state->GetIsolate(), v8_value);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
index b71fa3f818a..ed09cf5afbe 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_test.cc
@@ -152,7 +152,7 @@ TEST(ToV8Test, undefinedType) {
TEST(ToV8Test, scriptValue) {
V8TestingScope scope;
- ScriptValue value(scope.GetScriptState(),
+ ScriptValue value(scope.GetIsolate(),
v8::Number::New(scope.GetIsolate(), 1234));
TEST_TOV8("1234", value);
@@ -300,7 +300,7 @@ TEST(ToV8Test, heapVector) {
TEST(ToV8Test, withScriptState) {
V8TestingScope scope;
- ScriptValue value(scope.GetScriptState(),
+ ScriptValue value(scope.GetIsolate(),
v8::Number::New(scope.GetIsolate(), 1234.0));
v8::Local<v8::Value> actual = ToV8(value, scope.GetScriptState());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
index fd91a6bee39..d8425c4a58b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/trace_wrapper_v8_reference_test.cc
@@ -14,7 +14,7 @@ namespace {
using TraceWrapperV8ReferenceTest = BindingTestSupportingGC;
-class TraceWrapperV8ReferenceHolder
+class TraceWrapperV8ReferenceHolder final
: public GarbageCollected<TraceWrapperV8ReferenceHolder> {
public:
TraceWrapperV8ReferenceHolder() = default;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc b/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
index a381af0a56d..46acbdc2541 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
@@ -234,9 +234,6 @@ void UseCounterCallback(v8::Isolate* isolate,
case v8::Isolate::kCallSiteAPIGetThisSloppyCall:
blink_feature = WebFeature::kV8CallSiteAPIGetThisSloppyCall;
break;
- case v8::Isolate::kRegExpMatchAllWithNonGlobalRegExp:
- blink_feature = WebFeature::kV8RegExpMatchAllWithNonGlobalRegExp;
- break;
default:
// This can happen if V8 has added counters that this version of Blink
// does not know about. It's harmless.
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
index e07a189ccb7..b8f95c90ea6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
@@ -318,7 +318,7 @@ bool V0CustomElementConstructorBuilder::DidRegisterDefinition() const {
}
ScriptValue V0CustomElementConstructorBuilder::BindingsReturnValue() const {
- return ScriptValue(script_state_, constructor_);
+ return ScriptValue(script_state_->GetIsolate(), constructor_);
}
bool V0CustomElementConstructorBuilder::HasValidPrototypeChainFor(
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 647f70e18f2..22f10d19ee7 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
@@ -783,7 +783,7 @@ ScriptState* ToScriptStateForMainWorld(LocalFrame* frame) {
}
bool IsValidEnum(const String& value,
- const char** valid_values,
+ const char* const* valid_values,
size_t length,
const String& enum_name,
ExceptionState& exception_state) {
@@ -799,7 +799,7 @@ bool IsValidEnum(const String& value,
}
bool IsValidEnum(const Vector<String>& values,
- const char** valid_values,
+ const char* const* valid_values,
size_t length,
const String& enum_name,
ExceptionState& exception_state) {
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 a03407398c6..c69e169d739 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
@@ -502,12 +502,12 @@ CORE_EXPORT void ToFlexibleArrayBufferView(v8::Isolate*,
void* storage = nullptr);
CORE_EXPORT bool IsValidEnum(const String& value,
- const char** valid_values,
+ const char* const* valid_values,
size_t length,
const String& enum_name,
ExceptionState&);
CORE_EXPORT bool IsValidEnum(const Vector<String>& values,
- const char** valid_values,
+ const char* const* valid_values,
size_t length,
const String& enum_name,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
index 0f2accba4e3..8d3b1b24c3a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
@@ -12,9 +12,8 @@
namespace blink {
-namespace {
-
-std::unique_ptr<DummyPageHolder> CreateDummyPageHolder(const KURL& url) {
+std::unique_ptr<DummyPageHolder> V8TestingScope::CreateDummyPageHolder(
+ const KURL& url) {
std::unique_ptr<DummyPageHolder> holder = std::make_unique<DummyPageHolder>();
if (url.IsValid()) {
holder->GetFrame().Loader().CommitNavigation(
@@ -25,8 +24,6 @@ std::unique_ptr<DummyPageHolder> CreateDummyPageHolder(const KURL& url) {
return holder;
}
-} // namespace
-
V8TestingScope::V8TestingScope(const KURL& url)
: holder_(CreateDummyPageHolder(url)),
handle_scope_(GetIsolate()),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
index d22214d67fc..ba8125b9159 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
@@ -27,6 +27,9 @@ class V8TestingScope {
STACK_ALLOCATED();
public:
+ // TODO(keishi): Define CreateDummyPageHolder in DummyPageHolder.
+ static std::unique_ptr<DummyPageHolder> CreateDummyPageHolder(
+ const KURL& url);
explicit V8TestingScope(const KURL& url = KURL());
ScriptState* GetScriptState() const;
ExecutionContext* GetExecutionContext() const;
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 794d58df642..4187057454c 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
@@ -173,8 +173,9 @@ class GC_PLUGIN_IGNORE(
uint16_t class_id) override;
// v8::EmbedderHeapTracer::TracedGlobalHandleVisitor override.
- void VisitTracedGlobalHandle(
- const v8::TracedGlobal<v8::Value>& value) override;
+ void VisitTracedReference(
+ const v8::TracedReference<v8::Value>& value) override;
+ void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) override;
// Visitor overrides.
void VisitRoot(void*, TraceDescriptor, const base::Location&) final;
@@ -508,8 +509,8 @@ void V8EmbedderGraphBuilder::VisitPersistentHandleInternal(
}
}
-void V8EmbedderGraphBuilder::VisitTracedGlobalHandle(
- const v8::TracedGlobal<v8::Value>& value) {
+void V8EmbedderGraphBuilder::VisitTracedReference(
+ const v8::TracedReference<v8::Value>& value) {
const uint16_t class_id = value.WrapperClassId();
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
@@ -517,6 +518,11 @@ void V8EmbedderGraphBuilder::VisitTracedGlobalHandle(
VisitPersistentHandleInternal(value.As<v8::Object>().Get(isolate_), class_id);
}
+void V8EmbedderGraphBuilder::VisitTracedGlobalHandle(
+ const v8::TracedGlobal<v8::Value>&) {
+ CHECK(false) << "Blink does not use v8::TracedGlobal.";
+}
+
void V8EmbedderGraphBuilder::VisitPersistentHandle(
v8::Persistent<v8::Value>* value,
uint16_t class_id) {
@@ -637,7 +643,7 @@ void V8EmbedderGraphBuilder::VisitBlinkRoots() {
std::unique_ptr<Graph::Node>(new EmbedderRootNode("Blink roots"))));
EnsureRootState(root);
ParentScope parent(this, root);
- ThreadState::Current()->GetPersistentRegion()->TracePersistentNodes(this);
+ ThreadState::Current()->GetPersistentRegion()->TraceNodes(this);
}
{
EmbedderNode* root =
@@ -646,7 +652,7 @@ void V8EmbedderGraphBuilder::VisitBlinkRoots() {
EnsureRootState(root);
ParentScope parent(this, root);
MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
- ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(this);
+ ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(this);
}
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.cc
index 7623ed70b80..16a021bdf2a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.cc
@@ -33,7 +33,7 @@ ScriptValue Eval(V8TestingScope* scope, const char* script_as_string) {
ADD_FAILURE() << "Compilation fails";
return ScriptValue();
}
- return ScriptValue(scope->GetScriptState(), script->Run(scope->GetContext()));
+ return ScriptValue(scope->GetIsolate(), script->Run(scope->GetContext()));
}
ScriptValue EvalWithPrintingError(V8TestingScope* scope, const char* script) {
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 bf045ffc632..de328132d2f 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
@@ -176,18 +176,10 @@ void V8GCController::GcEpilogue(v8::Isolate* isolate,
case v8::kGCTypeScavenge:
TRACE_EVENT_END1("devtools.timeline,v8", "MinorGC", "usedHeapSizeAfter",
UsedHeapSize(isolate));
- // Scavenger might have dropped nodes.
- if (ThreadState::Current()) {
- ThreadState::Current()->ScheduleV8FollowupGCIfNeeded(
- BlinkGC::kV8MinorGC);
- }
break;
case v8::kGCTypeMarkSweepCompact:
TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter",
UsedHeapSize(isolate));
- if (ThreadState::Current())
- ThreadState::Current()->ScheduleV8FollowupGCIfNeeded(
- BlinkGC::kV8MajorGC);
break;
case v8::kGCTypeIncrementalMarking:
TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter",
@@ -260,7 +252,11 @@ class DOMWrapperForwardingVisitor final
VisitHandle(value, class_id);
}
- void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>& value) final {
+ void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) final {
+ CHECK(false) << "Blink does not use v8::TracedGlobal.";
+ }
+
+ void VisitTracedReference(const v8::TracedReference<v8::Value>& value) final {
VisitHandle(&value, value.WrapperClassId());
}
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 3eeafca490b..3b1ced15de4 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
@@ -374,9 +374,9 @@ static bool ContentSecurityPolicyCodeGenerationCheck(
static_cast<size_t>(source_str.length()));
memcpy(snippet, *source_str, len * sizeof(UChar));
snippet[len] = 0;
- return policy->AllowEval(
- ScriptState::From(context), SecurityViolationReportingPolicy::kReport,
- ContentSecurityPolicy::kWillThrowException, snippet);
+ return policy->AllowEval(SecurityViolationReportingPolicy::kReport,
+ ContentSecurityPolicy::kWillThrowException,
+ snippet);
}
}
return false;
@@ -450,12 +450,10 @@ static bool WasmCodeGenerationCheckCallbackInMainThread(
// Wasm code generation is allowed if we have either the wasm-eval
// directive or the unsafe-eval directive. However, we only recognize
// wasm-eval for certain schemes
- return policy->AllowWasmEval(ScriptState::From(context),
- SecurityViolationReportingPolicy::kReport,
+ return policy->AllowWasmEval(SecurityViolationReportingPolicy::kReport,
ContentSecurityPolicy::kWillThrowException,
snippet) ||
- policy->AllowEval(ScriptState::From(context),
- SecurityViolationReportingPolicy::kReport,
+ policy->AllowEval(SecurityViolationReportingPolicy::kReport,
ContentSecurityPolicy::kWillThrowException,
snippet);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
index 6d37648968d..0af30777d9b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h
@@ -27,7 +27,7 @@ V8UnpackIteratorResult(ScriptState*, v8::Local<v8::Object> result, bool* done);
template <typename T>
inline ScriptValue V8IteratorResult(ScriptState* script_state, const T& value) {
return ScriptValue(
- script_state,
+ script_state->GetIsolate(),
V8IteratorResultValue(script_state, false,
ToV8(value, script_state->GetContext()->Global(),
script_state->GetIsolate())));
@@ -35,7 +35,7 @@ inline ScriptValue V8IteratorResult(ScriptState* script_state, const T& value) {
inline ScriptValue V8IteratorResultDone(ScriptState* script_state) {
return ScriptValue(
- script_state,
+ script_state->GetIsolate(),
V8IteratorResultValue(script_state, true,
v8::Undefined(script_state->GetIsolate())));
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
index c448406ca4b..6abb611983a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
@@ -53,7 +53,7 @@ V8ObjectBuilder& V8ObjectBuilder::AddStringOrNull(const StringView& name,
}
ScriptValue V8ObjectBuilder::GetScriptValue() const {
- return ScriptValue(script_state_, object_);
+ return ScriptValue(script_state_->GetIsolate(), object_);
}
void V8ObjectBuilder::AddInternal(const StringView& name,
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 4aca5e28650..94ce5a11791 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
@@ -44,6 +44,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/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -524,22 +525,4 @@ void V8ScriptRunner::ReportException(v8::Isolate* isolate,
V8Initializer::MessageHandlerInWorker(message, exception);
}
-v8::MaybeLocal<v8::Value> V8ScriptRunner::CallExtraHelper(
- ScriptState* script_state,
- const char* name,
- uint32_t num_args,
- v8::Local<v8::Value>* args) {
- v8::Isolate* isolate = script_state->GetIsolate();
- v8::Local<v8::Value> function_value;
- v8::Local<v8::Context> context = script_state->GetContext();
- if (!context->GetExtrasBindingObject()
- ->Get(context, V8AtomicString(isolate, name))
- .ToLocal(&function_value))
- return v8::MaybeLocal<v8::Value>();
- v8::Local<v8::Function> function = function_value.As<v8::Function>();
- return V8ScriptRunner::CallInternalFunction(
- isolate, ToMicrotaskQueue(script_state), function, v8::Undefined(isolate),
- num_args, args);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
index 002f4ce7c30..fb0ad51edf9 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
@@ -103,26 +103,12 @@ class CORE_EXPORT V8ScriptRunner final {
const String& file_name,
const WTF::TextPosition&);
- // Calls a function on the V8 extras binding object.
- template <uint32_t N>
- static v8::MaybeLocal<v8::Value> CallExtra(ScriptState* script_state,
- const char* name,
- v8::Local<v8::Value> (&args)[N]) {
- return CallExtraHelper(script_state, name, N, args);
- }
-
// Reports an exception to the message handler, as if it were an uncaught
// exception. Can only be called on the main thread.
//
// TODO(adamk): This should live on V8ThrowException, but it depends on
// V8Initializer and so can't trivially move to platform/bindings.
static void ReportException(v8::Isolate*, v8::Local<v8::Value> exception);
-
- private:
- static v8::MaybeLocal<v8::Value> CallExtraHelper(ScriptState*,
- const char* name,
- uint32_t num_args,
- v8::Local<v8::Value>* args);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
index fe0426952bc..00a872a9953 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
@@ -106,19 +106,15 @@ V8V0CustomElementLifecycleCallbacks::V8V0CustomElementLifecycleCallbacks(
: V0CustomElementLifecycleCallbacks(
FlagSet(attached, detached, attribute_changed)),
script_state_(script_state),
- prototype_(script_state->GetIsolate(), prototype),
- created_(script_state->GetIsolate(), created),
- attached_(script_state->GetIsolate(), attached),
- detached_(script_state->GetIsolate(), detached),
- attribute_changed_(script_state->GetIsolate(), attribute_changed) {
- prototype_.SetPhantom();
-
-#define MAKE_WEAK(Var, Ignored) \
- if (!Var##_.IsEmpty()) \
- Var##_.SetPhantom();
-
- CALLBACK_LIST(MAKE_WEAK)
-#undef MAKE_WEAK
+ prototype_(script_state->GetIsolate(), prototype){
+ v8::Isolate* isolate = script_state->GetIsolate();
+ v8::Local<v8::Function> function;
+#define SET_FIELD(maybe, ignored) \
+ if (maybe.ToLocal(&function)) \
+ maybe##_.Set(isolate, function);
+
+ CALLBACK_LIST(SET_FIELD)
+#undef SET_FIELD
}
V8PerContextData* V8V0CustomElementLifecycleCallbacks::CreationContextData() {
@@ -228,7 +224,7 @@ void V8V0CustomElementLifecycleCallbacks::AttributeChanged(
}
void V8V0CustomElementLifecycleCallbacks::Call(
- const ScopedPersistent<v8::Function>& weak_callback,
+ const TraceWrapperV8Reference<v8::Function>& callback_reference,
Element* element) {
// FIXME: callbacks while paused should be queued up for execution to
// continue then be delivered in order rather than delivered immediately.
@@ -238,7 +234,7 @@ void V8V0CustomElementLifecycleCallbacks::Call(
ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Context> context = script_state_->GetContext();
- v8::Local<v8::Function> callback = weak_callback.NewLocal(isolate);
+ v8::Local<v8::Function> callback = callback_reference.NewLocal(isolate);
if (callback.IsEmpty())
return;
@@ -254,6 +250,11 @@ void V8V0CustomElementLifecycleCallbacks::Call(
void V8V0CustomElementLifecycleCallbacks::Trace(blink::Visitor* visitor) {
visitor->Trace(script_state_);
+ visitor->Trace(prototype_);
+ visitor->Trace(created_);
+ visitor->Trace(attached_);
+ visitor->Trace(detached_);
+ visitor->Trace(attribute_changed_);
V0CustomElementLifecycleCallbacks::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
index c37f7880552..f295bfbb236 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
@@ -35,8 +35,8 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.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/trace_wrapper_v8_reference.h"
#include "v8/include/v8.h"
namespace blink {
@@ -79,16 +79,17 @@ class V8V0CustomElementLifecycleCallbacks final
const AtomicString& old_value,
const AtomicString& new_value) override;
- void Call(const ScopedPersistent<v8::Function>& weak_callback, Element*);
+ void Call(const TraceWrapperV8Reference<v8::Function>& callback_reference,
+ Element*);
V8PerContextData* CreationContextData();
Member<ScriptState> script_state_;
- ScopedPersistent<v8::Object> prototype_;
- ScopedPersistent<v8::Function> created_;
- ScopedPersistent<v8::Function> attached_;
- ScopedPersistent<v8::Function> detached_;
- ScopedPersistent<v8::Function> attribute_changed_;
+ TraceWrapperV8Reference<v8::Object> prototype_;
+ TraceWrapperV8Reference<v8::Function> created_;
+ TraceWrapperV8Reference<v8::Function> attached_;
+ TraceWrapperV8Reference<v8::Function> detached_;
+ TraceWrapperV8Reference<v8::Function> attribute_changed_;
};
} // 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 8bf3935efb2..1be10f4d468 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
@@ -159,7 +159,7 @@ class FetchDataLoaderForWasmStreaming final : public FetchDataLoader,
// argument to BodyStreamBuffer::startLoading, however, it fulfills
// a very small role. Consider refactoring to avoid it.
class WasmDataLoaderClient final
- : public GarbageCollectedFinalized<WasmDataLoaderClient>,
+ : public GarbageCollected<WasmDataLoaderClient>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(WasmDataLoaderClient);
@@ -234,24 +234,15 @@ RawResource* GetRawResource(ScriptState* script_state,
class WasmStreamingClient : public v8::WasmStreaming::Client {
public:
WasmStreamingClient(const String& response_url,
- const base::Time& response_time,
- v8::Isolate* isolate,
- v8::Local<v8::Context> context)
+ const base::Time& response_time)
: response_url_(response_url.IsolatedCopy()),
- response_time_(response_time),
- context_(isolate, context) {
- context_.SetWeak();
- }
+ response_time_(response_time) {}
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());
- // Don't cache if Context has been destroyed.
- if (context_.IsEmpty())
- return;
-
// Our heuristic for whether it's worthwhile to cache is that the module
// was fully compiled and it is "large". Wire bytes size is likely to be
// highly correlated with compiled module size so we use it to avoid the
@@ -292,7 +283,6 @@ class WasmStreamingClient : public v8::WasmStreaming::Client {
private:
String response_url_;
base::Time response_time_;
- v8::Global<v8::Context> context_;
scoped_refptr<CachedMetadata> cached_module_;
DISALLOW_COPY_AND_ASSIGN(WasmStreamingClient);
@@ -365,8 +355,7 @@ void StreamFromResponseCallback(
raw_resource->ScriptCacheHandler();
if (cache_handler) {
auto client = std::make_shared<WasmStreamingClient>(
- url, raw_resource->GetResponse().ResponseTime(), args.GetIsolate(),
- script_state->GetContext());
+ url, raw_resource->GetResponse().ResponseTime());
streaming->SetClient(client);
scoped_refptr<CachedMetadata> cached_module =
cache_handler->GetCachedMetadata(kWasmModuleTag);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h b/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
index 44a70bdf501..060b4a3b6b6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
@@ -141,7 +141,7 @@ struct WrapperTypeInfo;
// ====== References ======
// https://wiki.mozilla.org/Gecko:SplitWindow
// https://whatwg.org/C/browsers.html#the-windowproxy-exotic-object
-class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
+class WindowProxy : public GarbageCollected<WindowProxy> {
public:
virtual ~WindowProxy();
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 7a2c63f5439..1463b2baaf9 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
@@ -33,7 +33,6 @@
#include <memory>
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
@@ -115,9 +114,8 @@ void WorkerOrWorkletScriptController::Dispose() {
rejected_promises_->Dispose();
rejected_promises_ = nullptr;
- world_->Dispose();
-
DisposeContextIfNeeded();
+ world_->Dispose();
}
void WorkerOrWorkletScriptController::DisposeContextIfNeeded() {
@@ -133,9 +131,23 @@ void WorkerOrWorkletScriptController::DisposeContextIfNeeded() {
{
ScriptState::Scope scope(script_state_);
+ v8::Local<v8::Context> context = script_state_->GetContext();
+ // After disposing the world, all Blink->V8 references are gone. Blink
+ // stand-alone GCs may collect the WorkerOrWorkletGlobalScope because there
+ // are no more roots (V8->Blink references that are actually found by
+ // iterating Blink->V8 references). Clear the back pointers to avoid
+ // referring to cleared memory on the next GC in case the JS wrapper objects
+ // survived.
+ v8::Local<v8::Object> global_proxy_object = context->Global();
+ v8::Local<v8::Object> global_object =
+ global_proxy_object->GetPrototype().As<v8::Object>();
+ DCHECK(!global_object.IsEmpty());
+ V8DOMWrapper::ClearNativeInfo(isolate_, global_object);
+ V8DOMWrapper::ClearNativeInfo(isolate_, global_proxy_object);
+
// This detaches v8::MicrotaskQueue pointer from v8::Context, so that we can
// destroy EventLoop safely.
- script_state_->GetContext()->DetachGlobal();
+ context->DetachGlobal();
}
script_state_->DisposePerContextData();
@@ -308,10 +320,6 @@ void WorkerOrWorkletScriptController::PrepareForEvaluation() {
wrapper_type_info->InstallConditionalFeatures(
context, *world_, global_object, v8::Local<v8::Object>(),
v8::Local<v8::Function>(), global_interface_template);
-
- // This can only be called after the global object is fully initialised, as it
- // reads values from it.
- InitializeV8ExtrasBinding(script_state_);
}
void WorkerOrWorkletScriptController::DisableEvalInternal(
@@ -372,7 +380,8 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
execution_state_->error_message = ToCoreString(message->Get());
execution_state_->location_ = SourceLocation::FromMessage(
isolate_, message, ExecutionContext::From(script_state_));
- execution_state_->exception = ScriptValue(script_state_, block.Exception());
+ execution_state_->exception =
+ ScriptValue(script_state_->GetIsolate(), block.Exception());
block.Reset();
} else {
execution_state_->had_exception = false;
@@ -382,7 +391,7 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
if (!maybe_result.ToLocal(&result) || result->IsUndefined())
return ScriptValue();
- return ScriptValue(script_state_, result);
+ return ScriptValue(script_state_->GetIsolate(), result);
}
bool WorkerOrWorkletScriptController::Evaluate(
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
index 3b9faadbe69..b4d37783935 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
@@ -50,7 +50,7 @@ class ScriptSourceCode;
class WorkerOrWorkletGlobalScope;
class CORE_EXPORT WorkerOrWorkletScriptController final
- : public GarbageCollectedFinalized<WorkerOrWorkletScriptController> {
+ : public GarbageCollected<WorkerOrWorkletScriptController> {
public:
WorkerOrWorkletScriptController(WorkerOrWorkletGlobalScope*, v8::Isolate*);
virtual ~WorkerOrWorkletScriptController();
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc
index 7ee67ac88a7..8ee18890b38 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc
@@ -41,8 +41,12 @@ void WorldSafeV8ReferenceInternal::MaybeCheckCreationContextWorld(
if (!value->IsObject())
return;
- ScriptState* script_state =
- ScriptState::From(value.As<v8::Object>()->CreationContext());
+ v8::Local<v8::Context> context = value.As<v8::Object>()->CreationContext();
+ // Creation context is null if the value is a remote object.
+ if (context.IsEmpty())
+ return;
+
+ ScriptState* script_state = ScriptState::From(context);
CHECK_EQ(&world, &script_state->World());
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h
index 85b3e322567..20b5677af71 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h
@@ -47,40 +47,58 @@ class CORE_EXPORT WorldSafeV8ReferenceInternal final {
// provides accessors that check whether the value is accessed in the same world
// or not, also provides an accessor that clones the value when accessed across
// worlds.
+//
+// TODO(crbug.com/1008765): Allow WorldSafeV8Reference created/set not in
+// context.
template <typename V8Type>
class WorldSafeV8Reference final {
DISALLOW_NEW();
public:
WorldSafeV8Reference() = default;
+
explicit WorldSafeV8Reference(v8::Isolate* isolate, v8::Local<V8Type> value)
- : v8_reference_(isolate, value),
- world_(&DOMWrapperWorld::Current(isolate)) {
- WorldSafeV8ReferenceInternal::MaybeCheckCreationContextWorld(*world_.get(),
- value);
+ : v8_reference_(isolate, value) {
+ DCHECK(!value.IsEmpty());
+ // Basically, |world_| is a world when this V8 reference is created.
+ // However, when this V8 reference isn't created in context and value is
+ // object, we set |world_| to a value's creation cotext's world.
+ if (isolate->InContext()) {
+ world_ = &DOMWrapperWorld::Current(isolate);
+ WorldSafeV8ReferenceInternal::MaybeCheckCreationContextWorld(
+ *world_.get(), value);
+ } else if (value->IsObject()) {
+ ScriptState* script_state =
+ ScriptState::From(value.template As<v8::Object>()->CreationContext());
+ world_ = &script_state->World();
+ }
}
~WorldSafeV8Reference() = default;
- // Returns the V8 reference. Crashes if |target_script_state|'s world is
- // different from this V8 reference's world.
+ // Returns the V8 reference. Crashes if |world_| is set and it is
+ // different from |target_script_state|'s world.
v8::Local<V8Type> Get(ScriptState* target_script_state) const {
DCHECK(!v8_reference_.IsEmpty());
- CHECK_EQ(world_.get(), &target_script_state->World());
+ if (world_) {
+ CHECK_EQ(world_.get(), &target_script_state->World());
+ }
return v8_reference_.NewLocal(target_script_state->GetIsolate());
}
// Returns a V8 reference that is safe to access in |target_script_state|.
// The return value may be a cloned object.
v8::Local<V8Type> GetAcrossWorld(ScriptState* target_script_state) const {
+ CHECK(world_);
return WorldSafeV8ReferenceInternal::ToWorldSafeValue(
target_script_state, v8_reference_, *world_.get())
.template As<V8Type>();
}
- // Sets a new V8 reference. Crashes if |new_value|'s world is different from
- // this V8 reference's world.
+ // Sets a new V8 reference. Crashes if |world_| is set and it is
+ // different from |new_value|'s world.
void Set(v8::Isolate* isolate, v8::Local<V8Type> new_value) {
DCHECK(!new_value.IsEmpty());
+ CHECK(isolate->InContext());
const DOMWrapperWorld& new_world = DOMWrapperWorld::Current(isolate);
WorldSafeV8ReferenceInternal::MaybeCheckCreationContextWorld(new_world,
new_value);
@@ -93,6 +111,7 @@ class WorldSafeV8Reference final {
// world of this V8 reference will be |new_value|'s world.
void SetAcrossWorld(v8::Isolate* isolate, v8::Local<V8Type> new_value) {
DCHECK(!new_value.IsEmpty());
+ CHECK(isolate->InContext());
const DOMWrapperWorld& new_world = DOMWrapperWorld::Current(isolate);
v8_reference_.Set(isolate, new_value);
world_ = WrapRefCounted(&new_world);
@@ -107,14 +126,19 @@ class WorldSafeV8Reference final {
void Trace(blink::Visitor* visitor) { visitor->Trace(v8_reference_); }
+ WorldSafeV8Reference& operator=(const WorldSafeV8Reference<V8Type>& other) =
+ default;
+
+ bool operator==(const WorldSafeV8Reference<V8Type>& other) const {
+ return v8_reference_ == other.v8_reference_;
+ }
+
private:
TraceWrapperV8Reference<V8Type> v8_reference_;
// The world of the current context at the time when |v8_reference_| was set.
// It's guaranteed that, if |v8_reference_| is a v8::Object, the world of the
// creation context of |v8_reference_| is the same as |world_|.
scoped_refptr<const DOMWrapperWorld> world_;
-
- DISALLOW_COPY_AND_ASSIGN(WorldSafeV8Reference);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference_test.cc
new file mode 100644
index 00000000000..8f166748c69
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference_test.cc
@@ -0,0 +1,63 @@
+// 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/bindings/core/v8/world_safe_v8_reference.h"
+
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gtest/include/gtest/gtest.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/frame/settings.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class DummyPageHolder;
+class KURL;
+
+namespace {
+
+class IsolateOnlyV8TestingScope {
+ STACK_ALLOCATED();
+
+ public:
+ IsolateOnlyV8TestingScope(const KURL& url = KURL())
+ : holder_(V8TestingScope::CreateDummyPageHolder(url)),
+ handle_scope_(GetIsolate()) {}
+
+ v8::Isolate* GetIsolate() const {
+ return ToScriptStateForMainWorld(holder_->GetDocument().GetFrame())
+ ->GetIsolate();
+ }
+
+ private:
+ std::unique_ptr<DummyPageHolder> holder_;
+ v8::HandleScope handle_scope_;
+};
+
+// http://crbug.com/1007504, http://crbug.com/1008425
+TEST(WorldSafeV8ReferenceTest, CreatedWhenNotInContext) {
+ WorldSafeV8Reference<v8::Value> v8_reference;
+ v8::Local<v8::Value> value;
+ {
+ IsolateOnlyV8TestingScope scope1;
+ v8::Isolate* isolate = scope1.GetIsolate();
+ CHECK(isolate);
+ CHECK(!isolate->InContext());
+
+ value = v8::Null(isolate);
+ v8_reference = WorldSafeV8Reference<v8::Value>(isolate, value);
+ EXPECT_FALSE(v8_reference.IsEmpty());
+ }
+ V8TestingScope scope2;
+ ScriptState* script_state = scope2.GetScriptState();
+ EXPECT_EQ(v8_reference.Get(script_state), value);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn b/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
index 0f17d1fb20f..3e852619f4f 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -69,6 +69,7 @@ generate_event_interfaces("modules_bindings_generated_event_interfaces") {
"//third_party/blink/renderer/modules/speech/speech_synthesis_event.idl",
"//third_party/blink/renderer/modules/storage/storage_event.idl",
"//third_party/blink/renderer/modules/vr/vr_display_event.idl",
+ "//third_party/blink/renderer/modules/wake_lock/wake_lock_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",
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 4adf793e28d..7f20ac335de 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/BUILD.gn
@@ -128,13 +128,6 @@ blink_modules_sources("bindings_modules_impl") {
"//third_party/blink/renderer/modules/mediarecorder:buildflags",
"//third_party/dawn/src/dawn:dawn_headers",
]
-
- if (!is_component_build && is_win) {
- # This target as a static library (for non-component builds) is >4GB on
- # Windows, this causes linking to fail. As a workaround, split it into
- # multiple shards.
- split_count = 5
- }
}
action("generate_v8_context_snapshot_external_references") {
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni b/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
index 88ea668865f..ee03000278b 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -42,18 +42,20 @@ bindings_modules_generated_union_type_files = [
"$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/worklet_animation_effect_or_worklet_group_effect.cc",
"$bindings_modules_v8_output_dir/worklet_animation_effect_or_worklet_group_effect.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_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_load_op_or_gpu_color.cc",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_gpu_color.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_long.cc",
- "$bindings_modules_v8_output_dir/gpu_load_op_or_long.h",
+ "$bindings_modules_v8_output_dir/gpu_load_op_or_unsigned_long.cc",
+ "$bindings_modules_v8_output_dir/gpu_load_op_or_unsigned_long.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",
@@ -92,6 +94,10 @@ bindings_modules_generated_union_type_files = [
"$bindings_modules_v8_output_dir/string_or_unsigned_long.h",
"$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_sequence_or_gpu_extent_3d_dict.cc",
+ "$bindings_modules_v8_output_dir/unsigned_long_sequence_or_gpu_extent_3d_dict.h",
+ "$bindings_modules_v8_output_dir/unsigned_long_sequence_or_gpu_origin_3d_dict.cc",
+ "$bindings_modules_v8_output_dir/unsigned_long_sequence_or_gpu_origin_3d_dict.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",
]
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 f4f489e5cf9..cf6f28c8322 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
@@ -8,13 +8,13 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
-#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/crypto/crypto_key.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/imagecapture/point_2d.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/shapedetection/detected_barcode.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_face.h"
#include "third_party/blink/renderer/modules/shapedetection/detected_text.h"
@@ -53,8 +53,8 @@ ScriptWrappable* V8ScriptValueDeserializerForModules::ReadDOMObject(
if (!ReadUTF8String(&pem_private_key) ||
!ReadUTF8String(&pem_certificate))
return nullptr;
- std::unique_ptr<WebRTCCertificateGenerator> certificate_generator(
- Platform::Current()->CreateRTCCertificateGenerator());
+ std::unique_ptr<RTCCertificateGenerator> certificate_generator =
+ std::make_unique<RTCCertificateGenerator>();
if (!certificate_generator)
return nullptr;
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
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 58e9887c0d3..c6fa496e76c 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
@@ -7,10 +7,10 @@
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#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/public/platform/web_rtc_certificate_generator.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"
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/imagecapture/point_2d.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/shapedetection/landmark.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -155,8 +156,8 @@ static const uint8_t kEcdsaCertificateEncoded[] = {
TEST(V8ScriptValueSerializerForModulesTest, RoundTripRTCCertificate) {
// If WebRTC is not supported in this build, this test is meaningless.
- std::unique_ptr<WebRTCCertificateGenerator> certificate_generator(
- Platform::Current()->CreateRTCCertificateGenerator());
+ std::unique_ptr<RTCCertificateGenerator> certificate_generator =
+ std::make_unique<RTCCertificateGenerator>();
if (!certificate_generator)
return;
@@ -185,8 +186,8 @@ TEST(V8ScriptValueSerializerForModulesTest, RoundTripRTCCertificate) {
TEST(V8ScriptValueSerializerForModulesTest, DecodeRTCCertificate) {
// If WebRTC is not supported in this build, this test is meaningless.
- std::unique_ptr<WebRTCCertificateGenerator> certificate_generator(
- Platform::Current()->CreateRTCCertificateGenerator());
+ std::unique_ptr<RTCCertificateGenerator> certificate_generator =
+ std::make_unique<RTCCertificateGenerator>();
if (!certificate_generator)
return;
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 965f6ec208d..c6eb591f1bd 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
@@ -724,13 +724,12 @@ ScriptValue DeserializeScriptValue(ScriptState* script_state,
v8::Isolate* isolate = script_state->GetIsolate();
v8::HandleScope handle_scope(isolate);
if (!serialized_value)
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
SerializedScriptValue::DeserializeOptions options;
options.blob_info = blob_info;
options.read_wasm_from_stream = read_wasm_from_stream;
- return ScriptValue(script_state,
- serialized_value->Deserialize(isolate, options));
+ return ScriptValue(isolate, serialized_value->Deserialize(isolate, options));
}
SQLValue NativeValueTraits<SQLValue>::NativeValue(
@@ -792,8 +791,7 @@ void AssertPrimaryKeyValidOrInjectable(ScriptState* script_state,
ScriptState::Scope scope(script_state);
v8::Isolate* isolate = script_state->GetIsolate();
ScriptValue key_value = ScriptValue::From(script_state, value->PrimaryKey());
- ScriptValue script_value(script_state,
- DeserializeIDBValueData(isolate, value));
+ ScriptValue script_value(isolate, DeserializeIDBValueData(isolate, value));
DummyExceptionStateForTesting exception_state;
std::unique_ptr<IDBKey> expected_key = CreateIDBKeyFromValueAndKeyPath(
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
index f7125da9f2a..df48fafd533 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -255,7 +255,7 @@ TEST(IDBKeyFromValue, Exceptions) {
{
// Value is an array with a getter that throws.
ScriptValue script_value(
- scope.GetScriptState(),
+ scope.GetIsolate(),
EvaluateScriptAsObject(
scope,
"(()=>{"
@@ -273,7 +273,7 @@ TEST(IDBKeyFromValue, Exceptions) {
{
// Value is an array containing an array with a getter that throws.
ScriptValue script_value(
- scope.GetScriptState(),
+ scope.GetIsolate(),
EvaluateScriptAsObject(
scope,
"(()=>{"
@@ -293,7 +293,7 @@ TEST(IDBKeyFromValue, Exceptions) {
TEST(IDBKeyFromValueAndKeyPathTest, Exceptions) {
V8TestingScope scope;
ScriptValue script_value(
- scope.GetScriptState(),
+ scope.GetIsolate(),
EvaluateScriptAsObject(scope,
"({id:1, get throws() { throw Error(); }})"));
{
@@ -380,14 +380,14 @@ TEST(InjectIDBKeyTest, ImplicitValues) {
v8::Isolate* isolate = scope.GetIsolate();
{
v8::Local<v8::String> string = V8String(isolate, "string");
- ScriptValue value = ScriptValue(scope.GetScriptState(), string);
+ ScriptValue value = ScriptValue(scope.GetIsolate(), string);
std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(123);
CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
"length");
}
{
v8::Local<v8::Array> array = v8::Array::New(isolate);
- ScriptValue value = ScriptValue(scope.GetScriptState(), array);
+ ScriptValue value = ScriptValue(scope.GetIsolate(), array);
std::unique_ptr<IDBKey> idb_key = IDBKey::CreateNumber(456);
CheckInjectionIgnored(scope.GetScriptState(), idb_key.get(), value,
"length");
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
index 2933abb7dc1..271f0f5d082 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/webgl_any.cc
@@ -12,7 +12,7 @@
namespace blink {
ScriptValue WebGLAny(ScriptState* script_state, bool value) {
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
v8::Boolean::New(script_state->GetIsolate(), value));
}
@@ -20,69 +20,73 @@ ScriptValue WebGLAny(ScriptState* script_state,
const bool* value,
uint32_t size) {
auto span = base::make_span(value, size);
- return ScriptValue(script_state, ToV8(span, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(span, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, const Vector<bool>& value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, const Vector<unsigned>& value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, const Vector<int>& value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, int value) {
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
v8::Integer::New(script_state->GetIsolate(), value));
}
ScriptValue WebGLAny(ScriptState* script_state, unsigned value) {
return ScriptValue(
- script_state, v8::Integer::NewFromUnsigned(script_state->GetIsolate(),
- static_cast<unsigned>(value)));
+ script_state->GetIsolate(),
+ v8::Integer::NewFromUnsigned(script_state->GetIsolate(),
+ static_cast<unsigned>(value)));
}
ScriptValue WebGLAny(ScriptState* script_state, int64_t value) {
- return ScriptValue(script_state, v8::Number::New(script_state->GetIsolate(),
- static_cast<double>(value)));
+ return ScriptValue(
+ script_state->GetIsolate(),
+ v8::Number::New(script_state->GetIsolate(), static_cast<double>(value)));
}
ScriptValue WebGLAny(ScriptState* script_state, uint64_t value) {
- return ScriptValue(script_state, v8::Number::New(script_state->GetIsolate(),
- static_cast<double>(value)));
+ return ScriptValue(
+ script_state->GetIsolate(),
+ v8::Number::New(script_state->GetIsolate(), static_cast<double>(value)));
}
ScriptValue WebGLAny(ScriptState* script_state, float value) {
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
v8::Number::New(script_state->GetIsolate(), value));
}
ScriptValue WebGLAny(ScriptState* script_state, String value) {
- return ScriptValue(script_state, V8String(script_state->GetIsolate(), value));
+ return ScriptValue(script_state->GetIsolate(),
+ V8String(script_state->GetIsolate(), value));
}
ScriptValue WebGLAny(ScriptState* script_state, WebGLObject* value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, DOMFloat32Array* value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, DOMInt32Array* value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, DOMUint8Array* value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
ScriptValue WebGLAny(ScriptState* script_state, DOMUint32Array* value) {
- return ScriptValue(script_state, ToV8(value, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(value, script_state));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf
new file mode 100644
index 00000000000..0169b9a6487
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/.style.yapf
@@ -0,0 +1,3 @@
+[style]
+# https://www.chromium.org/blink/coding-style
+based_on_style = pep8
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
new file mode 100644
index 00000000000..32103feb06b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/__init__.py
@@ -0,0 +1,53 @@
+# 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 os.path
+import platform
+import sys
+
+
+# Set up |sys.path| so that this module works without user-side setup of
+# PYTHONPATH assuming Chromium's directory tree structure.
+def _setup_sys_path():
+ expected_path = 'third_party/blink/renderer/bindings/scripts/bind_gen/'
+
+ this_dir = os.path.dirname(__file__)
+ root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/')))
+
+ sys.path = [
+ # //third_party/blink/renderer/build/scripts/blinkbuild
+ os.path.join(root_dir, 'third_party', 'blink', 'renderer', 'build',
+ 'scripts'),
+ # //third_party/mako/mako
+ os.path.join(root_dir, 'third_party', 'mako'),
+ ] + sys.path
+
+
+_setup_sys_path()
+
+from .clang_format import init_clang_format
+
+
+def _setup_clang_format():
+ expected_path = 'third_party/blink/renderer/bindings/scripts/bind_gen/'
+
+ this_dir = os.path.dirname(__file__)
+ root_dir = os.path.join(this_dir, *(['..'] * expected_path.count('/')))
+
+ # //third_party/depot_tools/clang-format
+ command_name = ('clang-format.bat'
+ if platform.system() == 'Windows' else 'clang-format')
+ command_path = os.path.abspath(
+ os.path.join(root_dir, 'third_party', 'depot_tools', command_name))
+
+ init_clang_format(command_path=command_path)
+
+
+_setup_clang_format()
+
+from .example import run_example
+
+__all__ = [
+ "run_example",
+]
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py
new file mode 100644
index 00000000000..3f41f659435
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/clang_format.py
@@ -0,0 +1,59 @@
+# 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 os.path
+import subprocess
+
+_clang_format_command_path = None
+
+
+def init_clang_format(command_path):
+ assert isinstance(command_path, str)
+ assert os.path.exists(command_path)
+
+ global _clang_format_command_path
+ assert _clang_format_command_path is None
+ _clang_format_command_path = command_path
+
+
+def clang_format(contents, filename=None):
+ command_line = [_clang_format_command_path]
+ if filename is not None:
+ command_line.append('-assume-filename={}'.format(filename))
+
+ proc = subprocess.Popen(
+ command_line, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout_output, stderr_output = proc.communicate(input=contents)
+ exit_code = proc.wait()
+
+ return ClangFormatResult(
+ stdout_output=stdout_output,
+ stderr_output=stderr_output,
+ exit_code=exit_code,
+ filename=filename)
+
+
+class ClangFormatResult(object):
+ def __init__(self, stdout_output, stderr_output, exit_code, filename):
+ self._stdout_output = stdout_output
+ self._stderr_output = stderr_output
+ self._exit_code = exit_code
+ self._filename = filename
+
+ @property
+ def did_succeed(self):
+ return self._exit_code == 0
+
+ @property
+ def contents(self):
+ assert self.did_succeed
+ return self._stdout_output
+
+ @property
+ def error_message(self):
+ return self._stderr_output
+
+ @property
+ def filename(self):
+ return self._filename
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
new file mode 100644
index 00000000000..68bacee8dd3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -0,0 +1,502 @@
+# 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.
+"""
+The code generator generates code based on a graph of code fragments. Each node
+of the graph is represented with CodeNode and its subclasses. This module
+provides a collection of the classes that represent code nodes independent from
+specific bindings, such as ECMAScript bindings.
+"""
+
+import copy
+import string
+
+from .mako_renderer import MakoRenderer
+
+
+class CodeNode(object):
+ """
+ This is the base class of all code fragment nodes.
+
+ - Graph structure
+ CodeNode can be nested and |outer| points to the nesting CodeNode. Also
+ CodeNode can make a sequence and |prev| points to the previous CodeNode.
+ See also |SequenceNode|.
+
+ - Template rendering
+ CodeNode has template text and template variable bindings. Either of
+ |__str__| or |render| returns a text of generated code. However, these
+ methods have side effects on rendering states, and repeated calls may return
+ different results.
+ """
+
+ class _RenderState(object):
+ """
+ Represents a set of per-render states. Every call to CodeNode.render
+ resets all the per-render states.
+ """
+
+ def __init__(self):
+ # Symbols used in generated code, but not yet defined. See also
+ # SymbolNode.
+ self.code_symbols_used = {}
+
+ class _LooseFormatter(string.Formatter):
+ def get_value(self, key, args, kwargs):
+ if key in kwargs:
+ return kwargs[key]
+ else:
+ return "{" + key + "}"
+
+ _template_formatter = _LooseFormatter()
+ _gensym_seq_id = 0
+
+ @classmethod
+ def format_template(cls, format_string, *args, **kwargs):
+ """
+ Formats a string like the built-in |format| allowing unbound keys.
+
+ format_template("${template_var} {format_var}", format_var=42)
+ will produce
+ "${template_var} 42"
+ without raising an exception that |template_var| is unbound.
+ """
+ return cls._template_formatter.format(format_string, *args, **kwargs)
+
+ @classmethod
+ def gensym(cls):
+ """
+ Creates a new template variable that never conflicts with anything.
+
+ The name 'gensym' came from 'gensym' (generated symbol) in Lisp that
+ exists for exactly the same purpose.
+
+ Note that |gensym| is used to produce a new Mako template variable while
+ SymbolNode is used to represent a code symbol (such as a local variable)
+ in generated code.
+
+ Bad example:
+ template_text = "abc ${tmp} xyz"
+ a = CodeNodeA(template_text='123')
+ b = CodeNodeB(template_text=template_text, {'tmp': a})
+ |b| expects "abc 123 xyz" but what if 'tmp' were already bound to
+ something else?
+
+ Good example:
+ sym = CodeNode.gensym()
+ template_text = CodeNode.format_template(
+ "abc ${{{node_a}}} xyz", node_a=sym)
+ a = CodeNodeA(template_text='123')
+ b = CodeNodeB(template_text=template_text, {sym: a})
+ "{{" and "}}" are literal of "{" and "}" themselves, and the innermost
+ "{node_a}" will be replaced with |sym|. The resulting template text
+ will be "abc ${gensym1} xyz" when |sym| is 'gensym1'.
+ """
+ cls._gensym_seq_id += 1
+ return "gensym{}".format(cls._gensym_seq_id)
+
+ def __init__(self,
+ outer=None,
+ prev=None,
+ template_text=None,
+ template_vars=None,
+ renderer=None):
+ assert outer is None or isinstance(outer, CodeNode)
+ assert prev is None or isinstance(prev, CodeNode)
+ assert template_text is None or isinstance(template_text, str)
+ assert template_vars is None or isinstance(template_vars, dict)
+ assert renderer is None or isinstance(renderer, MakoRenderer)
+
+ # The outer CodeNode or None iff this is a top-level node
+ self._outer = outer
+ # The previous CodeNode if this is a Sequence or None
+ self._prev = prev
+
+ # Mako's template text, bindings dict, and the renderer object
+ self._template_text = template_text
+ self._template_vars = {}
+ self._renderer = renderer
+
+ self._render_state = CodeNode._RenderState()
+ self._is_rendering = False
+
+ if template_vars:
+ self.add_template_vars(template_vars)
+
+ def __str__(self):
+ """
+ Renders this CodeNode object into a Mako template. This is supposed to
+ be used in a Mako template as ${code_node}.
+ """
+ return self.render()
+
+ def render(self):
+ """
+ Renders this CodeNode object as a text string and also propagates
+ updates to related CodeNode objects. As this method has side-effects
+ not only to this object but also other related objects, the resulting
+ text may change on each invocation.
+ """
+ assert self.renderer
+
+ last_render_state = self._render_state
+ self._render_state = CodeNode._RenderState()
+ self._is_rendering = True
+
+ try:
+ text = self._render(
+ renderer=self.renderer, last_render_state=last_render_state)
+ finally:
+ self._is_rendering = False
+
+ return text
+
+ def _render(self, renderer, last_render_state):
+ """
+ Renders this CodeNode object as a text string and also propagates
+ updates to related CodeNode objects.
+
+ Only limited subclasses may override this method.
+ """
+ assert self._template_text is not None
+ return renderer.render(
+ caller=self,
+ template_text=self._template_text,
+ template_vars=self.template_vars)
+
+ @property
+ def outer(self):
+ """Returns the outer CodeNode or None iff this is a top-level node."""
+ return self._outer
+
+ def set_outer(self, outer):
+ assert isinstance(outer, CodeNode)
+ assert self._outer is None
+ self._outer = outer
+
+ @property
+ def prev(self):
+ """Returns the previous CodeNode if this is a Sequence or None."""
+ return self._prev
+
+ def set_prev(self, prev):
+ assert isinstance(prev, CodeNode)
+ assert self._prev is None
+ self._prev = prev
+
+ def reset_prev(self, prev):
+ assert isinstance(prev, CodeNode)
+ self._prev = prev
+
+ @property
+ def upstream(self):
+ """
+ Returns the upstream CodeNode in terms of code flow.
+
+ The upstream CodeNode is defined as:
+ 1. the previous CodeNode, or
+ 2. the outer CodeNode, or
+ 3. None (as this is a top-level node)
+ """
+ return self.prev or self.outer
+
+ @property
+ def template_vars(self):
+ """
+ Returns the template variable bindings available at this point, i.e.
+ bound at this node or outer nodes.
+
+ CAUTION: Do not modify the returned dict. This method may return the
+ original dict in a CodeNode.
+ """
+ if not self.outer:
+ return self._template_vars
+
+ if not self._template_vars:
+ return self.outer.template_vars
+
+ binds = copy.copy(self.outer.template_vars)
+ for name, value in self._template_vars.iteritems():
+ assert name not in binds, (
+ "Duplicated template variable binding: {}".format(name))
+ binds[name] = value
+ return binds
+
+ def add_template_var(self, name, value):
+ assert name not in self._template_vars
+ if isinstance(value, CodeNode):
+ value.set_outer(self)
+ self._template_vars[name] = value
+
+ def add_template_vars(self, template_vars):
+ assert isinstance(template_vars, dict)
+ for name, value in template_vars.iteritems():
+ self.add_template_var(name, value)
+
+ @property
+ def renderer(self):
+ return self._renderer or self.outer.renderer
+
+ @property
+ def current_render_state(self):
+ assert self._is_rendering
+ return self._render_state
+
+ @property
+ def last_render_state(self):
+ assert not self._is_rendering
+ return self._render_state
+
+ def is_code_symbol_defined(self, symbol_node):
+ """
+ Returns True if |symbol_node| is defined at this point or upstream.
+ """
+ if self.upstream:
+ return self.upstream.is_code_symbol_defined(symbol_node)
+ return False
+
+ def on_code_symbol_used(self, symbol_node):
+ """Receives a report of use of an undefined symbol node."""
+ assert isinstance(symbol_node, SymbolNode)
+ state = self.current_render_state
+ state.code_symbols_used[symbol_node.name] = symbol_node
+
+
+class LiteralNode(CodeNode):
+ """
+ Represents a literal text, which will be rendered as is without any template
+ magic applied.
+ """
+
+ def __init__(self, literal_text, renderer=None):
+ assert isinstance(literal_text, str)
+
+ literal_text_gensym = CodeNode.gensym()
+ template_text = CodeNode.format_template(
+ "${{{literal_text}}}", literal_text=literal_text_gensym)
+ template_vars = {literal_text_gensym: literal_text}
+
+ CodeNode.__init__(
+ self,
+ template_text=template_text,
+ template_vars=template_vars,
+ renderer=renderer)
+
+
+class TextNode(CodeNode):
+ """
+ Represents a template text node.
+
+ TextNode is designed to be a leaf node of a code node tree. TextNode
+ represents a template text while LiteralNode represents a literal text.
+ All template magics will be applied to |template_text|.
+ """
+
+ def __init__(self, template_text, renderer=None):
+ CodeNode.__init__(self, template_text=template_text, renderer=renderer)
+
+
+class SequenceNode(CodeNode):
+ """
+ Represents a sequence of nodes.
+ """
+
+ def __init__(self, code_nodes=None, separator="\n", renderer=None):
+ assert isinstance(separator, str)
+
+ element_nodes_gensym = CodeNode.gensym()
+ element_nodes = []
+ template_text = CodeNode.format_template(
+ """\
+% for node in {element_nodes}:
+${node}\\
+% if not loop.last:
+{separator}\\
+% endif
+% endfor
+""",
+ element_nodes=element_nodes_gensym,
+ separator=separator)
+ template_vars = {element_nodes_gensym: element_nodes}
+
+ CodeNode.__init__(
+ self,
+ template_text=template_text,
+ template_vars=template_vars,
+ renderer=renderer)
+
+ self._element_nodes = element_nodes
+
+ if code_nodes is not None:
+ self.extend(code_nodes)
+
+ def __getitem__(self, index):
+ return self._element_nodes[index]
+
+ def __iter__(self):
+ return iter(self._element_nodes)
+
+ def __len__(self):
+ return len(self._element_nodes)
+
+ def append(self, node):
+ assert isinstance(node, CodeNode)
+ assert node.outer is None and node.prev is None
+
+ if len(self._element_nodes) == 0:
+ self._element_nodes.append(node)
+ else:
+ node.set_prev(self._element_nodes[-1])
+ self._element_nodes.append(node)
+ node.set_outer(self)
+
+ def extend(self, nodes):
+ for node in nodes:
+ self.append(node)
+
+ def insert(self, index, node):
+ assert isinstance(index, (int, long))
+ assert isinstance(node, CodeNode)
+ assert node.outer is None and node.prev is None
+
+ if index < 0:
+ index += len(self._element_nodes)
+ index = max(0, min(index, len(self._element_nodes)))
+
+ if (len(self._element_nodes) == 0
+ or index == len(self._element_nodes)):
+ return self.append(node)
+
+ next_node = self._element_nodes[index]
+ if next_node.prev:
+ node.set_prev(next_node.prev)
+ next_node.reset_prev(node)
+ node.set_outer(self)
+ self._element_nodes.insert(index, node)
+
+
+class SymbolNode(CodeNode):
+ """
+ Represents a code symbol such as a local variable of generated code.
+
+ Using a SymbolNode combined with SymbolScopeNode, SymbolDefinitionNode(s)
+ will be automatically inserted iff this symbol is referenced.
+ """
+
+ def __init__(self,
+ name,
+ template_text=None,
+ definition_node_constructor=None):
+ """
+ Args:
+ name: The name of this code symbol.
+ template_text: Template text to be used to define the code symbol.
+ definition_node_constructor: A callable that creates and returns a
+ new definition node. This SymbolNode will be passed as the
+ argument.
+ Either of |template_text| or |definition_node_constructor| must
+ be given.
+ """
+ assert isinstance(name, str) and name
+ assert (template_text is not None
+ or definition_node_constructor is not None)
+ assert template_text is None or definition_node_constructor is None
+ if template_text is not None:
+ assert isinstance(template_text, str)
+ if definition_node_constructor is not None:
+ assert callable(definition_node_constructor)
+
+ CodeNode.__init__(self)
+
+ self._name = name
+
+ if template_text is not None:
+
+ def constructor(symbol_node):
+ return SymbolDefinitionNode(
+ symbol_node, template_text=template_text)
+
+ self._definition_node_constructor = constructor
+ else:
+ self._definition_node_constructor = definition_node_constructor
+
+ def _render(self, renderer, last_render_state):
+ if not renderer.last_caller.is_code_symbol_defined(self):
+ for caller in renderer.callers:
+ assert isinstance(caller, CodeNode)
+ caller.on_code_symbol_used(self)
+
+ return self.name
+
+ @property
+ def name(self):
+ return self._name
+
+ def create_definition_node(self):
+ """Creates a new definition node."""
+ node = self._definition_node_constructor(self)
+ assert isinstance(node, SymbolDefinitionNode)
+ return node
+
+
+class SymbolDefinitionNode(CodeNode):
+ """
+ Represents a definition of a code symbol.
+
+ It's allowed to define the same code symbol multiple times, and most
+ upstream definition(s) are effective.
+ """
+
+ def __init__(self, symbol_node, template_text, template_vars=None):
+ assert isinstance(symbol_node, SymbolNode)
+
+ CodeNode.__init__(
+ self, template_text=template_text, template_vars=template_vars)
+
+ self._symbol_node = symbol_node
+
+ def _render(self, renderer, last_render_state):
+ if (self.upstream
+ and self.upstream.is_code_symbol_defined(self._symbol_node)):
+ return ""
+
+ return super(SymbolDefinitionNode, self)._render(
+ renderer=renderer, last_render_state=last_render_state)
+
+ def is_code_symbol_defined(self, symbol_node):
+ if symbol_node is self._symbol_node:
+ return True
+ return super(SymbolDefinitionNode,
+ self).is_code_symbol_defined(symbol_node)
+
+
+class SymbolScopeNode(SequenceNode):
+ """
+ Represents a sequence of nodes.
+
+ If SymbolNodes are rendered inside this node, this node will attempt to
+ insert corresponding SymbolDefinitionNodes appropriately.
+ """
+
+ def _render(self, renderer, last_render_state):
+ # Sort nodes in order to render reproducible results.
+ symbol_nodes = sorted(
+ last_render_state.code_symbols_used.itervalues(),
+ key=lambda symbol_node: symbol_node.name)
+ for symbol_node in symbol_nodes:
+ self._insert_symbol_definition(symbol_node)
+
+ return super(SymbolScopeNode, self)._render(
+ renderer=renderer, last_render_state=last_render_state)
+
+ def _insert_symbol_definition(self, symbol_node):
+ self.insert(0, symbol_node.create_definition_node())
+
+ def register_code_symbol(self, symbol_node):
+ """Registers a SymbolNode and makes it available in this scope."""
+ assert isinstance(symbol_node, SymbolNode)
+ self.add_template_var(symbol_node.name, symbol_node)
+
+ def register_code_symbols(self, symbol_nodes):
+ for symbol_node in symbol_nodes:
+ self.register_code_symbol(symbol_node)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
new file mode 100644
index 00000000000..831213ee776
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
@@ -0,0 +1,118 @@
+# 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 unittest
+
+from .code_node import LiteralNode
+from .code_node import SequenceNode
+from .code_node import SymbolNode
+from .code_node import SymbolScopeNode
+from .code_node import TextNode
+from .mako_renderer import MakoRenderer
+
+
+class CodeNodeTest(unittest.TestCase):
+ def render(self, node):
+ prev = ""
+ current = str(node)
+ while current != prev:
+ prev = current
+ current = str(node)
+ return current
+
+ def assertRenderResult(self, node, expected):
+ def simplify(s):
+ return " ".join(s.split())
+
+ actual = simplify(self.render(node))
+ expected = simplify(expected)
+
+ self.assertEqual(actual, expected)
+
+ def test_literal_node(self):
+ """
+ Tests that, in LiteralNode, the special characters of template (%, ${},
+ etc) are not processed.
+ """
+ renderer = MakoRenderer()
+ root = LiteralNode("<% x = 42 %>${x}", renderer=renderer)
+ self.assertRenderResult(root, "<% x = 42 %>${x}")
+
+ def test_empty_literal_node(self):
+ renderer = MakoRenderer()
+ root = LiteralNode("", renderer=renderer)
+ self.assertRenderResult(root, "")
+
+ def test_text_node(self):
+ """Tests that the template language works in TextNode."""
+ renderer = MakoRenderer()
+ root = TextNode("<% x = 42 %>${x}", renderer=renderer)
+ self.assertRenderResult(root, "42")
+
+ def test_empty_text_node(self):
+ renderer = MakoRenderer()
+ root = TextNode("", renderer=renderer)
+ self.assertRenderResult(root, "")
+
+ def test_list_operations_of_sequence_node(self):
+ """
+ Tests that list operations (insert, append, and extend) of SequenceNode
+ work just same as Python built-in list.
+ """
+ renderer = MakoRenderer()
+ root = SequenceNode(renderer=renderer)
+ root.extend([
+ LiteralNode("2"),
+ LiteralNode("4"),
+ ])
+ root.insert(1, LiteralNode("3"))
+ root.insert(0, LiteralNode("1"))
+ root.insert(100, LiteralNode("5"))
+ root.append(LiteralNode("6"))
+ self.assertRenderResult(root, "1 2 3 4 5 6")
+
+ def test_nested_sequence(self):
+ """Tests nested SequenceNodes."""
+ renderer = MakoRenderer()
+ root = SequenceNode(renderer=renderer)
+ nested = SequenceNode()
+ nested.extend([
+ LiteralNode("2"),
+ LiteralNode("3"),
+ LiteralNode("4"),
+ ])
+ root.extend([
+ LiteralNode("1"),
+ nested,
+ LiteralNode("5"),
+ ])
+ self.assertRenderResult(root, "1 2 3 4 5")
+
+ def test_symbol_definition_chains(self):
+ """
+ Tests that use of SymbolNode inserts necessary SymbolDefinitionNode
+ appropriately.
+ """
+ renderer = MakoRenderer()
+ root = SymbolScopeNode(renderer=renderer)
+
+ root.register_code_symbols([
+ SymbolNode("var1", "int ${var1} = ${var2} + ${var3};"),
+ SymbolNode("var2", "int ${var2} = ${var5};"),
+ SymbolNode("var3", "int ${var3} = ${var4};"),
+ SymbolNode("var4", "int ${var4} = 1;"),
+ SymbolNode("var5", "int ${var5} = 2;"),
+ ])
+
+ root.append(TextNode("(void)${var1};"))
+
+ self.assertRenderResult(
+ root, """
+int var5 = 2;
+int var4 = 1;
+int var3 = var4;
+int var2 = var5;
+int var1 = var2 + var3;
+(void)var1;
+ """)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/example.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/example.py
new file mode 100644
index 00000000000..b1bf4f3525e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/example.py
@@ -0,0 +1,39 @@
+# 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 os.path
+
+from . import code_node
+from .clang_format import clang_format
+from .mako_renderer import MakoRenderer
+
+
+def run_example(web_idl_database, output_dirs):
+ renderer = MakoRenderer()
+
+ filename = 'v8_example.cc'
+ filepath = os.path.join(output_dirs['core'], filename)
+
+ root_node = code_node.SymbolScopeNode(renderer=renderer)
+ root_node.extend([
+ code_node.TextNode("${z} = ${x} + ${y};"),
+ code_node.TextNode("print ${z};"),
+ ])
+
+ root_node.register_code_symbols([
+ code_node.SymbolNode('x', "int ${x} = 1;"),
+ code_node.SymbolNode('y', "int ${y} = 2;"),
+ code_node.SymbolNode('z', "int ${z};"),
+ ])
+
+ prev = ''
+ current = str(root_node)
+ while current != prev:
+ prev = current
+ current = str(root_node)
+ rendered_text = current
+
+ format_result = clang_format(rendered_text, filename=filename)
+ with open(filepath, 'w') as output_file:
+ output_file.write(format_result.contents)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
new file mode 100644
index 00000000000..a9f6b058702
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
@@ -0,0 +1,68 @@
+# 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 mako.lookup
+import mako.template
+
+
+class MakoRenderer(object):
+ """Represents a renderer object implemented with Mako templates."""
+
+ def __init__(self, template_dirs=None):
+ template_dirs = template_dirs or []
+ self._template_lookup = mako.lookup.TemplateLookup(
+ directories=template_dirs)
+
+ self._caller_stack = []
+
+ def render(self,
+ caller,
+ template_path=None,
+ template_text=None,
+ template_vars=None):
+ """
+ Renders the template with variable bindings.
+
+ It's okay to invoke |render| method recursively and |caller| is pushed
+ onto the call stack, which is accessible via |callers| and |last_caller|
+ methods.
+
+ Args:
+ template_path: A filepath to a template file.
+ template_text: A text content to be used as a template. Either of
+ |template_path| or |template_text| must be specified.
+ template_vars: Template variable bindings.
+ caller: An object to be pushed onto the call stack.
+ """
+
+ assert template_path is not None or template_text is not None
+ assert template_path is None or template_text is None
+ assert isinstance(template_vars, dict)
+ assert caller is not None
+
+ self._caller_stack.append(caller)
+
+ try:
+ if template_path is not None:
+ template = self._template_lookup.get_template(template_path)
+ elif template_text is not None:
+ template = mako.template.Template(text=template_text)
+ text = template.render(**template_vars)
+ finally:
+ self._caller_stack.pop()
+
+ return text
+
+ @property
+ def callers(self):
+ """
+ Returns the callers of this renderer in the order from the last caller
+ to the first caller.
+ """
+ return reversed(self._caller_stack)
+
+ @property
+ def last_caller(self):
+ """Returns the last caller in the call stack of this renderer."""
+ return self._caller_stack[-1]
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py b/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
index f2dd305a300..1706754e5e5 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
@@ -18,11 +18,14 @@ import web_idl
def parse_options():
parser = optparse.OptionParser()
parser.add_option('--output', type='string',
- help='filepath of the resulting database')
+ help="filepath of the resulting database")
options, args = parser.parse_args()
if options.output is None:
- parser.error('Specify a filepath of the database with --output.')
+ parser.error("Specify a filepath of the database with --output.")
+
+ if not args:
+ parser.error("No argument specified.")
return options, args
@@ -34,13 +37,13 @@ def main():
def report_error(message):
was_error_reported[0] = True
- sys.stderr.writelines([message, '\n'])
+ sys.stderr.writelines([message, "\n"])
database = web_idl.build_database(filepaths=filepaths,
report_error=report_error)
if was_error_reported[0]:
- sys.exit('Aborted due to error.')
+ sys.exit("Aborted due to error.")
database.write_to_file(options.output)
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 4189985bf15..c6922e536fc 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
@@ -17,33 +17,34 @@ import utilities
import web_idl
-_VALID_COMPONENTS = ("core", "modules")
+_VALID_COMPONENTS = ('core', 'modules')
def parse_options():
parser = optparse.OptionParser()
parser.add_option('--idl-list-file', type='string',
- help='a file path which lists IDL file paths to process')
+ help="a file path which lists IDL file paths to process")
parser.add_option('--component', type='choice', choices=_VALID_COMPONENTS,
- help='specify a component name')
+ help="specify a component name")
parser.add_option('--output', type='string',
- help='the output file path')
+ help="the output file path")
options, args = parser.parse_args()
if options.idl_list_file is None:
- parser.error('Specify a file listing IDL files with --idl-list-file.')
+ parser.error("Specify a file listing IDL files with --idl-list-file.")
if options.output is None:
- parser.error('Specify the output file path with --output.')
+ parser.error("Specify the output file path with --output.")
if options.component is None:
- parser.error('Specify a component with --component.')
+ parser.error("Specify a component with --component.")
+
+ if args:
+ parser.error("Unknown arguments {}".format(args))
return options, args
def main():
- options, args = parse_options()
- if args:
- raise RuntimeError('unknown arguments {}'.format(args))
+ options, _ = parse_options()
filepaths = utilities.read_idl_files_list_from_file(options.idl_list_file)
parser = blink_idl_parser.BlinkIDLParser()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
new file mode 100644
index 00000000000..119b1476ff9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.py
@@ -0,0 +1,61 @@
+# 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.
+
+"""
+Runs the bindings code generator for the given tasks.
+"""
+
+import optparse
+import sys
+
+import bind_gen
+import web_idl
+
+
+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('--output_dir_core', type='string',
+ help="outout directory for 'core' component")
+ parser.add_option('--output_dir_modules', type='string',
+ help="outout directory for 'modules' component")
+ options, args = parser.parse_args()
+
+ required_option_names = (
+ 'web_idl_database', 'output_dir_core', 'output_dir_modules')
+ for opt_name in required_option_names:
+ if getattr(options, opt_name) is None:
+ parser.error("--{} is a required option.".format(opt_name))
+
+ if not args:
+ parser.error("No argument specified.")
+
+ return options, args
+
+
+def main():
+ options, tasks = parse_options()
+
+ dispatch_table = {
+ 'example': bind_gen.run_example,
+ }
+
+ for task in tasks:
+ if task not in dispatch_table:
+ sys.exit("Unknown task: {}".format(task))
+
+ web_idl_database = web_idl.Database.read_from_file(options.web_idl_database)
+ output_dirs = {
+ web_idl.Component('core'): options.output_dir_core,
+ web_idl.Component('modules'): options.output_dir_modules,
+ }
+
+ for task in tasks:
+ dispatch_table[task](web_idl_database=web_idl_database,
+ output_dirs=output_dirs)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
new file mode 100644
index 00000000000..28c6e59e7aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
@@ -0,0 +1,59 @@
+# Generated by running:
+# build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps third_party/blink/renderer/bindings/scripts/generate_bindings.py
+../../../../mako/mako/__init__.py
+../../../../mako/mako/_ast_util.py
+../../../../mako/mako/ast.py
+../../../../mako/mako/cache.py
+../../../../mako/mako/codegen.py
+../../../../mako/mako/compat.py
+../../../../mako/mako/exceptions.py
+../../../../mako/mako/ext/__init__.py
+../../../../mako/mako/filters.py
+../../../../mako/mako/lexer.py
+../../../../mako/mako/lookup.py
+../../../../mako/mako/parsetree.py
+../../../../mako/mako/pygen.py
+../../../../mako/mako/pyparser.py
+../../../../mako/mako/runtime.py
+../../../../mako/mako/template.py
+../../../../mako/mako/util.py
+../../build/scripts/blinkbuild/__init__.py
+../../build/scripts/blinkbuild/name_style_converter.py
+bind_gen/__init__.py
+bind_gen/clang_format.py
+bind_gen/code_node.py
+bind_gen/example.py
+bind_gen/mako_renderer.py
+generate_bindings.py
+web_idl/__init__.py
+web_idl/argument.py
+web_idl/ast_group.py
+web_idl/attribute.py
+web_idl/callback_function.py
+web_idl/callback_interface.py
+web_idl/code_generator_info.py
+web_idl/composition_parts.py
+web_idl/constant.py
+web_idl/database.py
+web_idl/database_builder.py
+web_idl/dictionary.py
+web_idl/enumeration.py
+web_idl/exposure.py
+web_idl/extended_attribute.py
+web_idl/file_io.py
+web_idl/function_like.py
+web_idl/idl_compiler.py
+web_idl/idl_type.py
+web_idl/includes.py
+web_idl/interface.py
+web_idl/ir_builder.py
+web_idl/ir_map.py
+web_idl/literal_constant.py
+web_idl/make_copy.py
+web_idl/namespace.py
+web_idl/operation.py
+web_idl/overload_group.py
+web_idl/reference.py
+web_idl/typedef.py
+web_idl/union.py
+web_idl/user_defined_type.py
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
index c380c9308f7..3fc8a81a152 100644
--- 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
@@ -80,7 +80,6 @@ class InterfaceTemplateContextBuilder(object):
has_cross_origin_named_enum = False
has_cross_origin_named_getter = False
has_cross_origin_named_setter = False
- has_origin_safe_method_setter = False
has_security_check = False
indexed_property_getter = None
is_global = False
@@ -98,9 +97,6 @@ class InterfaceTemplateContextBuilder(object):
interface.indexed_property_getter, ['index'])
if not interface.is_partial:
- has_origin_safe_method_setter = is_global and any(
- method['is_check_security_for_receiver'] and not method['is_unforgeable']
- for method in methods)
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
@@ -114,7 +110,6 @@ class InterfaceTemplateContextBuilder(object):
return {
'attributes': attributes,
'component': component,
- 'has_origin_safe_method_setter': has_origin_safe_method_setter,
'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,
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
index 58d091b0824..27c6b032902 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -509,6 +509,8 @@ class IdlLiteral(object):
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)
@@ -537,6 +539,8 @@ def default_node_to_idl_literal(node):
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)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
index 9931a138ae3..6e1bce98c16 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_types.py
@@ -365,6 +365,11 @@ class IdlUnionType(IdlTypeBase):
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
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py b/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
index e75099ee2fe..85de1cc1d83 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/idl_validator.py
@@ -60,6 +60,15 @@ class IDLExtendedAttributeValidator(object):
self.validate_extended_attributes_node(operation)
for argument in operation.arguments:
self.validate_extended_attributes_node(argument)
+ for dictionary in definitions.dictionaries.itervalues():
+ self.validate_extended_attributes_node(dictionary)
+ for member in dictionary.members:
+ self.validate_extended_attributes_node(member)
+ for callback_function in definitions.callback_functions.itervalues():
+ 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.iteritems():
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
index 9754671433f..8a5c5dc4b36 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
@@ -402,6 +402,9 @@ def getter_base_name(interface, attribute, arguments):
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'
@@ -570,6 +573,9 @@ def setter_base_name(interface, attribute, arguments):
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'
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
index fee066fc61f..bdd5965ca9d 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
@@ -91,7 +91,10 @@ def arguments_context(arguments):
def argument_cpp_type(argument):
cpp_type = argument.idl_type.callback_cpp_type
if argument.is_variadic:
- return 'const Vector<%s>&' % cpp_type
+ if argument.idl_type.is_traceable:
+ return 'const HeapVector<%s>&' % cpp_type
+ else:
+ return 'const Vector<%s>&' % cpp_type
else:
return cpp_type
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
index 68105822562..39ab8717569 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
@@ -434,10 +434,6 @@ def interface_context(interface, interfaces, component_info):
# Methods
context.update(methods_context(interface, component_info))
methods = context['methods']
- context.update({
- 'has_origin_safe_method_setter': any(method['is_cross_origin'] and not method['is_unforgeable']
- for method in methods),
- })
# Conditionally enabled methods
conditional_methods = v8_methods.filter_conditionally_enabled(methods, interface.is_partial)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
index c170e7ee36f..07fcc8d0f8e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -474,9 +474,11 @@ def argument_set_default_value(argument):
if not default_value:
return None
if idl_type.is_dictionary:
- if not argument.default_value.is_null:
- raise Exception('invalid default value for dictionary type')
- return None
+ 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)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
index 3226f36e524..6264576d548 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
@@ -209,7 +209,7 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
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_gc_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
@@ -217,7 +217,7 @@ def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_
# Record types.
if idl_type.is_record_type:
- vector_type = cpp_ptr_type('Vector', 'HeapVector', idl_type.value_type.is_gc_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)
@@ -382,7 +382,7 @@ 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
+ 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)
@@ -570,7 +570,7 @@ V8_VALUE_TO_CPP_VALUE = {
# Interface types
'FlexibleArrayBufferView': 'ToFlexibleArrayBufferView({isolate}, {v8_value}, {variable_name}, allocateFlexibleArrayBufferViewStorage({v8_value}))',
'Promise': 'ScriptPromise::Cast(ScriptState::Current({isolate}), {v8_value})',
- 'ScriptValue': 'ScriptValue(ScriptState::Current({isolate}), {v8_value})',
+ 'ScriptValue': 'ScriptValue({isolate}, {v8_value})',
'Window': 'ToDOMWindow({isolate}, {v8_value})',
'XPathNSResolver': 'ToXPathNSResolver(ScriptState::Current({isolate}), {v8_value})',
}
@@ -1051,10 +1051,12 @@ 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)'
+ 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
@@ -1069,6 +1071,8 @@ def union_literal_cpp_value(idl_type, idl_literal):
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)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
index bbadf6240e0..ec31d27da23 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -210,7 +210,7 @@ CALL_WITH_ARGUMENTS = {
'ScriptState': 'script_state',
'ExecutionContext': 'execution_context',
'Document': 'document',
- 'ThisValue': 'ScriptValue(script_state, info.Holder())',
+ 'ThisValue': 'ScriptValue(info.GetIsolate(), info.Holder())',
}
# List because key order matters, as we want arguments in deterministic order
CALL_WITH_VALUES = [
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
index a2a9aae1b0b..9c71fc2fa66 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/dictionary.py
@@ -51,7 +51,7 @@ class Dictionary(UserDefinedType, WithExtendedAttributes,
self.is_partial = is_partial
self.inherited = inherited
- self.own_members = own_members
+ self.own_members = list(own_members)
def iter_all_members(self):
return iter(self.own_members)
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 7e4f15477fd..6f864784048 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
@@ -16,6 +16,7 @@ from .ir_map import IRMap
from .idl_type import IdlTypeFactory
from .interface import Interface
from .make_copy import make_copy
+from .namespace import Namespace
from .operation import OperationGroup
from .reference import RefByIdFactory
from .typedef import Typedef
@@ -79,16 +80,17 @@ class IdlCompiler(object):
# Merge partial definitions.
self._propagate_extattrs_per_idl_fragment()
- self._merge_partial_interfaces()
+ self._merge_partial_interface_likes()
self._merge_partial_dictionaries()
# Merge mixins.
self._merge_interface_mixins()
- self._group_overloaded_functions()
-
# Process inheritances.
self._process_interface_inheritances()
+ # Make groups of overloaded functions including inherited ones.
+ self._group_overloaded_functions()
+
# Updates on IRs are finished. Create API objects.
self._create_public_objects()
@@ -182,18 +184,22 @@ class IdlCompiler(object):
map(process_interface_like, old_irs)
- def _merge_partial_interfaces(self):
- old_interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE)
- partial_interfaces = self._ir_map.find_by_kind(
- IRMap.IR.Kind.PARTIAL_INTERFACE)
- old_mixins = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE_MIXIN)
- partial_mixins = self._ir_map.find_by_kind(
- IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN)
+ def _merge_partial_interface_likes(self):
+ irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
+ IRMap.IR.Kind.INTERFACE_MIXIN,
+ IRMap.IR.Kind.NAMESPACE)
+ partial_irs = self._ir_map.irs_of_kinds(
+ IRMap.IR.Kind.PARTIAL_INTERFACE,
+ IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN,
+ IRMap.IR.Kind.PARTIAL_NAMESPACE)
self._ir_map.move_to_new_phase()
- self._merge_interfaces(old_interfaces, partial_interfaces)
- self._merge_interfaces(old_mixins, partial_mixins)
+ ir_sets_to_merge = [(ir, [
+ partial_ir for partial_ir in partial_irs
+ if partial_ir.identifier == ir.identifier
+ ]) for ir in irs]
+ self._merge_interface_like_irs(ir_sets_to_merge)
def _merge_partial_dictionaries(self):
old_dictionaries = self._ir_map.find_by_kind(IRMap.IR.Kind.DICTIONARY)
@@ -215,59 +221,34 @@ class IdlCompiler(object):
def _merge_interface_mixins(self):
interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE)
- interface_mixins = self._ir_map.find_by_kind(
- IRMap.IR.Kind.INTERFACE_MIXIN)
+ mixins = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE_MIXIN)
+ includes = self._ir_map.find_by_kind(IRMap.IR.Kind.INCLUDES)
- identifier_to_mixin_map = {
- identifier: [
- interface_mixins[include.mixin_identifier]
- for include in includes
- ]
- for identifier, includes in self._ir_map.find_by_kind(
- IRMap.IR.Kind.INCLUDES).iteritems()
- }
+ ir_sets_to_merge = [(interface, [
+ mixins[include.mixin_identifier]
+ for include in includes.get(identifier, [])
+ ]) for identifier, interface in interfaces.iteritems()]
self._ir_map.move_to_new_phase()
- self._merge_interfaces(interfaces, identifier_to_mixin_map)
+ self._merge_interface_like_irs(ir_sets_to_merge)
- def _merge_interfaces(self, old_interfaces, interfaces_to_be_merged):
- for identifier, old_interface in old_interfaces.iteritems():
- new_interface = make_copy(old_interface)
- for to_be_merged in interfaces_to_be_merged.get(identifier, []):
- new_interface.add_components(to_be_merged.components)
- new_interface.debug_info.add_locations(
+ def _merge_interface_like_irs(self, old_irs_to_merge):
+ for old_ir, irs_to_be_merged in old_irs_to_merge:
+ new_ir = make_copy(old_ir)
+ for ir in irs_to_be_merged:
+ to_be_merged = make_copy(ir)
+ new_ir.add_components(to_be_merged.components)
+ new_ir.debug_info.add_locations(
to_be_merged.debug_info.all_locations)
- new_interface.attributes.extend(
- make_copy(to_be_merged.attributes))
- new_interface.constants.extend(
- make_copy(to_be_merged.constants))
- new_interface.operations.extend(
- make_copy(to_be_merged.operations))
- self._ir_map.add(new_interface)
-
- def _group_overloaded_functions(self):
- old_interfaces = self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE)
-
- self._ir_map.move_to_new_phase()
-
- for old_interface in old_interfaces:
- assert not old_interface.operation_groups
- new_interface = make_copy(old_interface)
-
- sort_key = lambda x: x.identifier
- sorted_operations = sorted(new_interface.operations, key=sort_key)
- new_interface.operation_groups = [
- OperationGroup.IR(operations=list(operations))
- for identifier, operations in itertools.groupby(
- sorted_operations, key=sort_key) if identifier
- ]
-
- self._ir_map.add(new_interface)
+ new_ir.attributes.extend(to_be_merged.attributes)
+ new_ir.constants.extend(to_be_merged.constants)
+ new_ir.operations.extend(to_be_merged.operations)
+ self._ir_map.add(new_ir)
def _process_interface_inheritances(self):
def is_own_member(member):
- return 'Unfogeable' in member.extended_attributes
+ return 'Unforgeable' in member.extended_attributes
def create_inheritance_stack(obj, table):
if obj.inherited is None:
@@ -294,6 +275,24 @@ class IdlCompiler(object):
])
self._ir_map.add(new_interface)
+ def _group_overloaded_functions(self):
+ old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
+ IRMap.IR.Kind.NAMESPACE)
+
+ self._ir_map.move_to_new_phase()
+
+ for old_ir in old_irs:
+ assert not old_ir.operation_groups
+ new_ir = make_copy(old_ir)
+ sort_key = lambda x: x.identifier
+ new_ir.operation_groups = [
+ OperationGroup.IR(operations=list(operations))
+ for identifier, operations in itertools.groupby(
+ sorted(old_ir.operations, key=sort_key), key=sort_key)
+ if identifier
+ ]
+ self._ir_map.add(new_ir)
+
def _create_public_objects(self):
"""Creates public representations of compiled objects."""
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE):
@@ -302,6 +301,9 @@ class IdlCompiler(object):
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE_MIXIN):
self._db.register(DatabaseBody.Kind.INTERFACE_MIXIN, Interface(ir))
+ for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.NAMESPACE):
+ self._db.register(DatabaseBody.Kind.NAMESPACE, Namespace(ir))
+
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.DICTIONARY):
self._db.register(DatabaseBody.Kind.DICTIONARY, Dictionary(ir))
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
index 5ef3c3ce24c..a1ba38154db 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
@@ -174,20 +174,31 @@ class Interface(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
return self._attributes
@property
- def operation_groups(self):
- """
- Returns groups of operations, including [Unforgeable] operations in
- ancestors. Operation groups are sorted by their identifier.
+ def constants(self):
+ """Returns constants."""
+ return self._constants
- All operations are grouped by their identifier in OperationGroup's,
- even when there exists a single operation with that identifier.
+ @property
+ def operations(self):
"""
- assert False, "Not implemented yet."
+ Returns all operations, including special operations without an
+ identifier, as well as [Unforgeable] operations in ancestors.
+ """
+ return self._operations
@property
- def constants(self):
- """Returns constants."""
- return self._constants
+ def operation_groups(self):
+ """
+ Returns groups of overloaded operations, including [Unforgeable]
+ operations in ancestors.
+
+ All operations that have an identifier are grouped by identifier, thus
+ it's possible that there is a single operation in a certain operation
+ group. If an operation doesn't have an identifier, i.e. if it's a
+ merely special operation, then the operation doesn't appear in any
+ operation group.
+ """
+ return self._operation_groups
@property
def constructors(self):
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 e8c2c24bde2..370262ae3c7 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
@@ -150,10 +150,32 @@ class _IRBuilder(object):
debug_info=self._build_debug_info(node))
def _build_namespace(self, node):
- # TODO(peria): Build members and register them in |namespace|
+ child_nodes = list(node.GetChildren())
+ extended_attributes = self._take_extended_attributes(child_nodes)
+
+ members = map(self._build_interface_or_namespace_member, child_nodes)
+ attributes = []
+ constants = []
+ operations = []
+ for member in members:
+ if isinstance(member, Attribute.IR):
+ member.is_static = True
+ attributes.append(member)
+ elif isinstance(member, Constant.IR):
+ constants.append(member)
+ elif isinstance(member, Operation.IR):
+ member.is_static = True
+ operations.append(member)
+ else:
+ assert False
+
return Namespace.IR(
identifier=Identifier(node.GetName()),
is_partial=bool(node.GetProperty('PARTIAL')),
+ attributes=attributes,
+ constants=constants,
+ operations=operations,
+ extended_attributes=extended_attributes,
component=self._component,
debug_info=self._build_debug_info(node))
@@ -462,7 +484,7 @@ class _IRBuilder(object):
idl_type = factory.simple_type(
name='object', debug_info=debug_info)
assert value_token == '{}'
- value = object()
+ value = dict()
literal = '{}'
else:
assert False, 'Unknown literal type: {}'.format(type_token)
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/literal_constant.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/literal_constant.py
index d83cc94e25e..d3d948a4ff2 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/literal_constant.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/literal_constant.py
@@ -47,7 +47,7 @@ class LiteralConstant(object):
The values of the following literals are represented as follows.
- null: None
- []: list()
- - {}: object()
+ - {}: dict()
- true / false: True / False
- INTEGER_NUMERICS: an instance of long
- FLOATING_POINTS: an instance of float
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
index b49d52be044..947c325287a 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/web_idl/namespace.py
@@ -2,58 +2,112 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import exceptions
-
+from .attribute import Attribute
+from .code_generator_info import CodeGeneratorInfo
from .composition_parts import WithCodeGeneratorInfo
from .composition_parts import WithComponent
from .composition_parts import WithDebugInfo
+from .composition_parts import WithExposure
from .composition_parts import WithExtendedAttributes
-from .composition_parts import WithIdentifier
+from .constant import Constant
+from .exposure import Exposure
from .ir_map import IRMap
+from .make_copy import make_copy
+from .operation import Operation
+from .operation import OperationGroup
+from .user_defined_type import UserDefinedType
-class Namespace(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo,
- WithComponent, WithDebugInfo):
+class Namespace(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
+ WithExposure, WithComponent, WithDebugInfo):
"""https://heycam.github.io/webidl/#idl-namespaces"""
class IR(IRMap.IR, WithExtendedAttributes, WithCodeGeneratorInfo,
- WithComponent, WithDebugInfo):
+ WithExposure, WithComponent, WithDebugInfo):
def __init__(self,
identifier,
is_partial,
+ attributes=None,
+ constants=None,
+ operations=None,
extended_attributes=None,
- code_generator_info=None,
component=None,
debug_info=None):
+ assert isinstance(is_partial, bool)
+ assert attributes is None or isinstance(attributes, (list, tuple))
+ assert constants is None or isinstance(constants, (list, tuple))
+ assert operations is None or isinstance(operations, (list, tuple))
+
+ attributes = attributes or []
+ constants = constants or []
+ operations = operations or []
+ assert all(
+ isinstance(attribute, Attribute.IR) and attribute.is_readonly
+ and attribute.is_static for attribute in attributes)
+ assert all(
+ isinstance(constant, Constant.IR) for constant in constants)
+ assert all(
+ isinstance(operation, Operation.IR) and operation.identifier
+ and operation.is_static for operation in operations)
+
kind = (IRMap.IR.Kind.PARTIAL_NAMESPACE
if is_partial else IRMap.IR.Kind.NAMESPACE)
IRMap.IR.__init__(self, identifier=identifier, kind=kind)
WithExtendedAttributes.__init__(self, extended_attributes)
- WithCodeGeneratorInfo.__init__(self, code_generator_info)
- WithComponent.__init__(self, component)
+ WithCodeGeneratorInfo.__init__(self)
+ WithExposure.__init__(self)
+ WithComponent.__init__(self, component=component)
WithDebugInfo.__init__(self, debug_info)
+ self.is_partial = is_partial
+ self.attributes = list(attributes)
+ self.constants = list(constants)
+ self.operations = list(operations)
+ self.operation_groups = []
+
+ def __init__(self, ir):
+ assert isinstance(ir, Namespace.IR)
+ assert not ir.is_partial
+
+ ir = make_copy(ir)
+ UserDefinedType.__init__(self, ir.identifier)
+ WithExtendedAttributes.__init__(self, ir.extended_attributes)
+ WithCodeGeneratorInfo.__init__(
+ self, CodeGeneratorInfo(ir.code_generator_info))
+ WithExposure.__init__(self, Exposure(ir.exposure))
+ WithComponent.__init__(self, components=ir.components)
+ WithDebugInfo.__init__(self, ir.debug_info)
+
+ self._attributes = tuple([
+ Attribute(attribute_ir, owner=self)
+ for attribute_ir in ir.attributes
+ ])
+ self._constants = tuple([
+ Constant(constant_ir, owner=self) for constant_ir in ir.constants
+ ])
+ self._operations = tuple([
+ Operation(operation_ir, owner=self)
+ for operation_ir in ir.operations
+ ])
+ self._operation_groups = tuple([
+ OperationGroup(
+ operation_group_ir,
+ filter(lambda x: x.identifier == operation_group_ir.identifier,
+ self._operations),
+ owner=self) for operation_group_ir in ir.operation_groups
+ ])
+
@property
def attributes(self):
- """
- Returns a list of attributes.
- @return tuple(Attribute)
- """
- raise exceptions.NotImplementedError()
+ """Returns attributes."""
+ return self._attributes
@property
- def operation_groups(self):
- """
- Returns a list of OperationGroup. Each OperationGroup may have an operation
- or a set of overloaded operations.
- @return tuple(OperationGroup)
- """
- raise exceptions.NotImplementedError()
+ def operations(self):
+ """Returns operations."""
+ return self._operations
@property
- def constants(self):
- """
- Returns a list of constants.
- @return tuple(Constant)
- """
- raise exceptions.NotImplementedError()
+ def operation_groups(self):
+ """Returns a list of OperationGroups."""
+ return self._operation_groups
diff --git a/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
index b6314416f63..17a6000d881 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -75,9 +75,14 @@ const v8::FunctionCallbackInfo<v8::Value>& info
{% if attribute.cached_attribute_validation_method %}
// [CachedAttribute]
+ {% if cpp_class == 'History' and attribute.camel_case_name == 'State' %}
+ V8PrivateProperty::Symbol property_symbol =
+ V8PrivateProperty::GetHistoryStateSymbol(info.GetIsolate());
+ {% else %}
V8PrivateProperty::Symbol property_symbol =
V8PrivateProperty::GetSymbol(info.GetIsolate(),
"{{cpp_class}}#{{attribute.camel_case_name}}");
+ {% endif %}
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()) {
@@ -177,8 +182,10 @@ const v8::FunctionCallbackInfo<v8::Value>& info
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()));
+ // This key is used for uniquely identifying v8::Private.
+ static int private_property_key;
V8PrivateProperty::GetSymbol(
- info.GetIsolate(), "KeepAlive#{{interface_name}}#{{attribute.name}}")
+ info.GetIsolate(), &private_property_key, "KeepAlive#{{interface_name}}#{{attribute.name}}")
.Set(holder, v8_value);
{% endif %}
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
index 4f44253b784..3097b0d3cbc 100644
--- 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
@@ -58,9 +58,6 @@ const intptr_t* {{class}}::GetTable() {
{% endif%}
{% endfor %}
{% endfor %}{# method #}
- {% if interface.has_origin_safe_method_setter %}
- reinterpret_cast<intptr_t>({{v8_class}}::{{interface.name}}OriginSafeMethodSetterCallback),
- {% endif %}
{% if interface.has_cross_origin_named_getter %}
reinterpret_cast<intptr_t>({{v8_class}}::CrossOriginNamedGetter),
{% endif %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
index c58e9a81ceb..733475988ec 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface.cc.tmpl
@@ -722,58 +722,6 @@ void {{v8_class_or_partial}}::NamedPropertyEnumeratorCallback(
{##############################################################################}
-{# TODO(dcheng): Currently, bindings must create a function object for each
- realm as a hack to support the incumbent realm. Remove this when Blink
- properly supports the incumbent realm. #}
-{% block origin_safe_method_setter %}
-{% if has_origin_safe_method_setter %}
-static void {{cpp_class}}OriginSafeMethodSetter(
- v8::Local<v8::Name> name,
- v8::Local<v8::Value> v8_value,
- const v8::PropertyCallbackInfo<void>& info) {
- if (!name->IsString())
- return;
- v8::Local<v8::Object> holder =
- {{v8_class}}::FindInstanceInPrototypeChain(info.Holder(), info.GetIsolate());
- if (holder.IsEmpty())
- return;
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(holder);
- v8::String::Utf8Value name_in_utf8(info.GetIsolate(), name);
- ExceptionState exception_state(
- info.GetIsolate(),
- ExceptionState::kSetterContext,
- "{{interface_name}}",
- *name_in_utf8);
- if (!BindingSecurity::ShouldAllowAccessTo(
- CurrentDOMWindow(info.GetIsolate()), impl, exception_state)) {
- return;
- }
-
- {# The findInstanceInPrototypeChain() call above only returns a non-empty handle if info.Holder() is an Object. #}
- {% raw %}
- // |methodName| must be same with {{method.name}} in
- // {{method.name}}OriginSafeMethodGetter{{world_suffix}} defined in
- // methods.cc.tmpl
- {% endraw %}
- V8PrivateProperty::GetSymbol(info.GetIsolate(), *name_in_utf8)
- .Set(v8::Local<v8::Object>::Cast(info.Holder()), v8_value);
-}
-{% endif %}
-{% endblock %}
-
-{% block origin_safe_method_setter_callback %}
-{% if has_origin_safe_method_setter %}
-void {{v8_class_or_partial}}::{{cpp_class}}OriginSafeMethodSetterCallback(
- v8::Local<v8::Name> name,
- v8::Local<v8::Value> v8_value,
- const v8::PropertyCallbackInfo<void>& info) {
- {{internal_namespace}}::{{cpp_class}}OriginSafeMethodSetter(name, v8_value, info);
-}
-{% endif %}
-{% endblock %}
-
-
-{##############################################################################}
{% block named_constructor %}
{% from 'methods.cc.tmpl' import generate_constructor with context %}
{% if named_constructor %}
@@ -954,34 +902,58 @@ static void Constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {
{##############################################################################}
-{% macro install_origin_safe_method(method, instance_template, prototype_template) %}
+{% 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 getter_callback =
- '%s::%sOriginSafeMethodGetterCallback' %
- (v8_class_or_partial, method.camel_case_name) %}
-{% set setter_callback =
- '%s::%sOriginSafeMethodSetterCallback' % (v8_class_or_partial, cpp_class)
- if not method.is_unforgeable else 'nullptr' %}
+{% 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::AttributeConfiguration {{method.name}}OriginSafeAttributeConfiguration[] = {
+static const V8DOMConfiguration::MethodConfiguration k{{method.camel_case_name}}OriginSafeMethodConfiguration[] = {
{% if method.is_per_world_bindings %}
-{% set getter_callback_for_main_world = '%sForMainWorld' % getter_callback %}
-{% set setter_callback_for_main_world = '%sForMainWorld' % setter_callback
- if not method.is_unforgeable else 'nullptr' %}
- {"{{method.name}}", {{getter_callback_for_main_world}}, {{setter_callback_for_main_world}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::MainWorld},
- {"{{method.name}}", {{getter_callback}}, {{setter_callback}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::NonMainWorlds}}
+{% 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}}", {{getter_callback}}, {{setter_callback}}, {{property_attribute}}, {{property_location(method)}}, {{holder_check}}, V8DOMConfiguration::kHasSideEffect, V8DOMConfiguration::kAlwaysCallGetter, V8DOMConfiguration::kAllWorlds}
+ {
+ "{{method.name}}",
+ {{function_callback}},
+ {{method.length}},
+ {{property_attribute}},
+ {{property_location(method)}},
+ {{holder_check}},
+ V8DOMConfiguration::kCheckAccess,
+ V8DOMConfiguration::kHasSideEffect,
+ V8DOMConfiguration::kAllWorlds,
+ }
{% endif %}
};
- for (const auto& attributeConfig : {{method.name}}OriginSafeAttributeConfiguration)
- V8DOMConfiguration::InstallAttribute(isolate, world, {{instance_template}}, {{prototype_template}}, attributeConfig);
+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 %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
index c124e53e940..f84c11618b2 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
@@ -220,9 +220,6 @@ class {{v8_class}} {
{% if iterator_method %}
{{exported}}static void {{iterator_method.camel_case_name}}MethodCallback(const v8::FunctionCallbackInfo<v8::Value>&);
{% endif %}
- {% if has_origin_safe_method_setter %}
- {{exported}}static void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&);
- {% 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>);
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
index 303e0160b63..5702a474bb3 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface_base.cc.tmpl
@@ -128,7 +128,6 @@ static void (*{{method.name}}MethodForPartialInterface)(const v8::FunctionCallba
{% if iterator_method %}
{{generate_method(iterator_method)}}
{% endif %}
-{% block origin_safe_method_setter %}{% endblock %}
{# Constructors #}
{% for constructor in constructors %}
{{generate_constructor(constructor)}}
@@ -235,7 +234,6 @@ static const struct {
{% if iterator_method %}
{{method_callback(iterator_method)}}
{% endif %}
-{% block origin_safe_method_setter_callback %}{% endblock %}
{# Special operations (methods) #}
{% block named_property_getter_callback %}{% endblock %}
{% block named_property_setter_callback %}{% endblock %}
@@ -616,7 +614,7 @@ static void Install{{v8_class}}Template(
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') | trim | indent(2)}}
+ {{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 %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
index 15cd677dd0d..955155c6c25 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
@@ -206,10 +206,10 @@ if (info[{{argument.index}}]->IsObject()) {
{{v8_value_to_local_cpp_value(argument)}}
{% if argument.is_nullable %}
} else if (info[{{argument.index}}]->IsNullOrUndefined()) {
- {{argument.local_cpp_variable}} = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Null(info.GetIsolate()));
+ {{argument.local_cpp_variable}} = ScriptValue(info.GetIsolate(), v8::Null(info.GetIsolate()));
{% elif argument.is_optional %}
} else if (info[{{argument.index}}]->IsUndefined()) {
- {{argument.local_cpp_variable}} = ScriptValue(ScriptState::Current(info.GetIsolate()), v8::Undefined(info.GetIsolate()));
+ {{argument.local_cpp_variable}} = ScriptValue(info.GetIsolate(), v8::Undefined(info.GetIsolate()));
{% endif %}
} else {
{{throw_argument_error(method, argument, "parameter %(index)d ('%(name)s') is not an object.")}}
@@ -507,7 +507,6 @@ void {{v8_class_or_partial}}::{{method.camel_case_name}}MethodCallback{{world_su
{##############################################################################}
{% macro origin_safe_method_getter(method, world_suffix) %}
static void {{method.camel_case_name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info) {
- static int dom_template_key; // This address is used for a key to look up the dom template.
v8::Isolate* isolate = info.GetIsolate();
V8PerIsolateData* data = V8PerIsolateData::From(isolate);
const DOMWrapperWorld& world =
@@ -517,6 +516,7 @@ static void {{method.camel_case_name}}OriginSafeMethodGetter{{world_suffix}}(con
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,
@@ -526,32 +526,10 @@ static void {{method.camel_case_name}}OriginSafeMethodGetter{{world_suffix}}(con
signature,
{{method.length}});
- {{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
- if (!BindingSecurity::ShouldAllowAccessTo(
- CurrentDOMWindow(isolate), impl,
- BindingSecurity::ErrorReportOption::kDoNotReport)) {
- V8SetReturnValue(
- info,
- method_template->GetFunction(
- isolate->GetCurrentContext()).ToLocalChecked());
- return;
- }
-
- // When the web author overwrote the property, return the overwriting value.
- //
- // "{{method.name}}" must be the same as |name_in_utf8| (=name) in
- // {{cpp_class}}OriginSafeMethodSetter defined in interface.cc.tmpl.
- V8PrivateProperty::Symbol property_symbol =
- V8PrivateProperty::GetSymbol(isolate, "{{method.name}}");
- v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast(info.Holder());
- if (property_symbol.HasValue(holder)) {
- V8SetReturnValue(info, property_symbol.GetOrUndefined(holder));
- } else {
- V8SetReturnValue(
- info,
- method_template->GetFunction(
- holder->CreationContext()).ToLocalChecked());
- }
+ V8SetReturnValue(
+ info,
+ method_template->GetFunction(
+ isolate->GetCurrentContext()).ToLocalChecked());
}
{% endmacro %}
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
index 9a3e8cd882e..41b235f6dc3 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/partial_interface.h.tmpl
@@ -100,9 +100,6 @@ class {{v8_class_or_partial}} {
{% if iterator_method %}
{{exported}}static void {{iterator_method.camel_case_name}}MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
{% endif %}
- {% if has_origin_safe_method_setter %}
- {{exported}}static void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::Name> name, v8::Local<v8::Value> v8_value, const v8::PropertyCallbackInfo<void>& info);
- {% endif %}
private:
{% if needs_runtime_enabled_installer %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
index b4cdea716f3..035dbf2cd80 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/utilities.cc.tmpl
@@ -32,7 +32,7 @@ if ({{item.check_expression}})
{% macro declare_enum_validation_variable(enum_values, enum_variable='kValidValues') %}
-const char* {{enum_variable}}[] = {
+const char* const {{enum_variable}}[] = {
{% for enum_value in enum_values %}
{% if enum_value is none %}
nullptr,
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 0b632ab8fb0..9c9142d93f4 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
@@ -324,6 +324,7 @@ To<Longhand>(resolved_property).{{apply_call}};
{% endcall %}
{% call(property) apply_inherit(property) %}
+ state.Style()->Clear{{action}}Directives();
const CounterDirectiveMap* parent_map = state.ParentStyle()->GetCounterDirectives();
if (!parent_map)
return;
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
index 52ad7d9d853..f33388f4f95 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
@@ -64,7 +64,7 @@ const StylePropertyShorthand& animationShorthandForParsing();
const StylePropertyShorthand& transitionShorthandForParsing();
// Returns an empty list if the property is not a shorthand.
-const StylePropertyShorthand& shorthandForProperty(CSSPropertyID);
+CORE_EXPORT const StylePropertyShorthand& shorthandForProperty(CSSPropertyID);
// Return the list of shorthands for a given longhand.
// The client must pass in an empty result vector.
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/element_lookup_trie.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/element_lookup_trie.cc.tmpl
index 2eab64f679e..0b7e7c9d404 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/element_lookup_trie.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/element_lookup_trie.cc.tmpl
@@ -11,12 +11,12 @@
namespace blink {
-using namespace {{namespace|lower}}_names;
-
const AtomicString& lookup{{namespace}}Tag(const UChar* data, unsigned length) {
DCHECK(data);
DCHECK(length);
- {% macro trie_return_statement(tag) %}{{tag|symbol}}Tag.LocalName(){% endmacro %}
+ {% macro trie_return_statement(tag) -%}
+ {{namespace|lower}}_names::{{tag|symbol}}Tag.LocalName()
+ {%- endmacro %}
{{ trie_length_switch(length_tries, trie_return_statement, false) | indent(4) }}
return g_null_atom;
}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/feature_policy_helper.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/feature_policy_helper.cc.tmpl
index b9e140da981..4d4284df0ae 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/feature_policy_helper.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/feature_policy_helper.cc.tmpl
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/feature_policy/feature_policy_helper.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/probe_sink.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/probe_sink.h.tmpl
index 19a4466066f..163e9e1e23d 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/probe_sink.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/probe_sink.h.tmpl
@@ -23,7 +23,7 @@ namespace blink {
class {{ agent | agent_name_to_class }};
{% endfor %}
-class {{export_symbol}} {{sink_class}} : public GarbageCollectedFinalized<{{sink_class}}> {
+class {{export_symbol}} {{sink_class}} final : public GarbageCollected<{{sink_class}}> {
public:
enum AgentType : unsigned {
diff --git a/chromium/third_party/blink/renderer/controller/blink_initializer.cc b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
index c75973878e9..bf1baaf0f4b 100644
--- a/chromium/third_party/blink/renderer/controller/blink_initializer.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
@@ -185,8 +185,9 @@ void BlinkInitializer::RegisterInterfaces(
void BlinkInitializer::InitLocalFrame(LocalFrame& frame) const {
if (RuntimeEnabledFeatures::DisplayCutoutAPIEnabled()) {
- frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
- &DisplayCutoutClientImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
+ frame.GetInterfaceRegistry()->AddAssociatedInterface(
+ WTF::BindRepeating(&DisplayCutoutClientImpl::BindMojoReceiver,
+ WrapWeakPersistent(&frame)));
}
frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
&DevToolsFrontendImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
@@ -195,12 +196,6 @@ void BlinkInitializer::InitLocalFrame(LocalFrame& frame) const {
frame.GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
&LocalFrame::PauseSubresourceLoading, WrapWeakPersistent(&frame)));
- if (!base::FeatureList::IsEnabled(
- blink::features::kSendPreviewsLoadingHintsBeforeCommit)) {
- frame.GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
- &LocalFrame::BindPreviewsResourceLoadingHintsReceiver,
- WrapWeakPersistent(&frame)));
- }
ModulesInitializer::InitLocalFrame(frame);
}
diff --git a/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc b/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
index 16d7fdfb1f3..d35880b6946 100644
--- a/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
@@ -127,8 +127,6 @@ void BlinkLeakDetector::ReportResult() {
result->number_of_live_context_lifecycle_state_observers =
InstanceCounters::CounterValue(
InstanceCounters::kContextLifecycleStateObserverCounter);
- result->number_of_live_script_promises =
- InstanceCounters::CounterValue(InstanceCounters::kScriptPromiseCounter);
result->number_of_live_frames =
InstanceCounters::CounterValue(InstanceCounters::kFrameCounter);
result->number_of_live_v8_per_context_data = InstanceCounters::CounterValue(
diff --git a/chromium/third_party/blink/renderer/controller/dev_tools_frontend_impl.h b/chromium/third_party/blink/renderer/controller/dev_tools_frontend_impl.h
index 731f960c750..ce7c49f2cbb 100644
--- a/chromium/third_party/blink/renderer/controller/dev_tools_frontend_impl.h
+++ b/chromium/third_party/blink/renderer/controller/dev_tools_frontend_impl.h
@@ -49,7 +49,7 @@ class LocalFrame;
// This class lives as long as a frame (being a supplement), or until
// it's host (mojom.DevToolsFrontendHost) is destroyed.
class DevToolsFrontendImpl final
- : public GarbageCollectedFinalized<DevToolsFrontendImpl>,
+ : public GarbageCollected<DevToolsFrontendImpl>,
public Supplement<LocalFrame>,
public mojom::blink::DevToolsFrontend,
public InspectorFrontendClient {
diff --git a/chromium/third_party/blink/renderer/core/BUILD.gn b/chromium/third_party/blink/renderer/core/BUILD.gn
index dd6b0e83b2d..211ffc068bc 100644
--- a/chromium/third_party/blink/renderer/core/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/BUILD.gn
@@ -6,7 +6,6 @@ import("//build/config/chromecast_build.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/dcheck_always_on.gni")
import("//build/config/ui.gni")
-import("//build/split_static_library.gni")
import("//build/toolchain/toolchain.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/blink/renderer/bindings/bindings.gni")
@@ -29,9 +28,6 @@ rel_blink_core_gen_dir = rebase_path(blink_core_output_dir, root_build_dir)
# Config for code that builds as part of core.
config("config") {
defines = [ "BLINK_CORE_IMPLEMENTATION=1" ]
- if (is_android && notouch_build) {
- defines += [ "ENABLE_TOUCHLESS_UASTYLE_THEME" ]
- }
}
config("core_include_dirs") {
@@ -164,6 +160,7 @@ component("core") {
"//third_party/blink/public/mojom:mojom_broadcastchannel_bindings_blink",
"//third_party/blink/renderer/core/accessibility",
"//third_party/blink/renderer/core/animation",
+ "//third_party/blink/renderer/core/animation_frame",
"//third_party/blink/renderer/core/aom",
"//third_party/blink/renderer/core/clipboard",
"//third_party/blink/renderer/core/content_capture",
@@ -276,6 +273,8 @@ jumbo_source_set("testing") {
"testing/dummy_modulator.h",
"testing/dummy_page_holder.cc",
"testing/dummy_page_holder.h",
+ "testing/fake_local_frame_host.cc",
+ "testing/fake_local_frame_host.h",
"testing/garbage_collected_script_wrappable.cc",
"testing/garbage_collected_script_wrappable.h",
"testing/gc_object_liveness_observer.h",
@@ -313,6 +312,8 @@ jumbo_source_set("testing") {
"testing/wait_for_event.h",
"testing/worker_internals.cc",
"testing/worker_internals.h",
+ "timing/internals_profiler.cc",
+ "timing/internals_profiler.h",
]
# Compile the sources produced by these IDL file lists.
@@ -1017,7 +1018,15 @@ group("all_generators") {
}
# Compiles the code generated by the targets above.
-target("jumbo_" + core_link_small_target_type, "core_generated") {
+if (is_component_build) {
+ # To get exported symbols correct in component builds, the files must be in
+ # source sets.
+ core_generated_target_type = "source_set"
+} else {
+ core_generated_target_type = "static_library"
+}
+
+target("jumbo_" + core_generated_target_type, "core_generated") {
sources = bindings_core_v8_files
# Add all sources generated by the targets above.
@@ -1103,6 +1112,7 @@ jumbo_source_set("unit_tests") {
"css/css_test_helpers.h",
"css/css_uri_value_test.cc",
"css/css_value_test_helper.h",
+ "css/mock_css_paint_image_generator.h",
"display_lock/display_lock_budget_test.cc",
"display_lock/display_lock_context_test.cc",
"display_lock/display_lock_utilities_test.cc",
@@ -1144,6 +1154,7 @@ jumbo_source_set("unit_tests") {
"events/pointer_event_factory_test.cc",
"events/touch_event_test.cc",
"events/web_input_event_conversion_test.cc",
+ "execution_context/agent_metrics_collector_test.cc",
"execution_context/context_lifecycle_state_observer_test.cc",
"exported/local_frame_client_impl_test.cc",
"exported/prerendering_test.cc",
@@ -1219,6 +1230,7 @@ jumbo_source_set("unit_tests") {
"html/anchor_element_metrics_test.cc",
"html/canvas/canvas_async_blob_creator_test.cc",
"html/canvas/canvas_font_cache_test.cc",
+ "html/canvas/html_canvas_element_test.cc",
"html/canvas/image_data_test.cc",
"html/custom/custom_element_definition_test.cc",
"html/custom/custom_element_descriptor_test.cc",
@@ -1528,7 +1540,6 @@ jumbo_source_set("unit_tests") {
"scroll/scrollbar_theme_overlay_test.cc",
"streams/miscellaneous_operations_test.cc",
"streams/queue_with_sizes_test.cc",
- "streams/readable_stream_operations_test.cc",
"streams/readable_stream_test.cc",
"streams/stream_promise_resolver_test.cc",
"streams/test_underlying_source.h",
@@ -1542,6 +1553,7 @@ jumbo_source_set("unit_tests") {
"style/style_variables_test.cc",
"style/svg_computed_style_test.cc",
"svg/graphics/svg_image_test.cc",
+ "svg/svg_foreign_object_element_test.cc",
"svg/svg_path_parser_test.cc",
"svg/svg_text_content_element_test.cc",
"svg/svg_use_element_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/DEPS b/chromium/third_party/blink/renderer/core/DEPS
index 2783c536345..1629785933f 100644
--- a/chromium/third_party/blink/renderer/core/DEPS
+++ b/chromium/third_party/blink/renderer/core/DEPS
@@ -42,13 +42,15 @@ include_rules = [
"+cc/layers/layer_position_constraint.h",
"+cc/layers/layer_sticky_position_constraint.h",
"+cc/layers/picture_layer.h",
- "+cc/layers/scrollbar_layer_interface.h",
+ "+cc/layers/scrollbar_layer_base.h",
"+cc/layers/surface_layer.h",
+ "+cc/metrics/begin_main_frame_metrics.h",
"+cc/paint/display_item_list.h",
"+cc/paint/paint_canvas.h",
"+cc/paint/paint_flags.h",
"+cc/paint/paint_worklet_input.h",
"+cc/trees/paint_holding_commit_trigger.h",
+ "+components/performance_manager/public/mojom/coordination_unit.mojom-blink.h",
"+gpu/config/gpu_feature_info.h",
"-inspector/v8",
"+inspector/v8/public",
@@ -76,6 +78,7 @@ include_rules = [
"-third_party/blink/renderer/modules",
"+third_party/skia/include",
"+ui/base/ime/mojom/ime_types.mojom-blink.h",
+ "+ui/base/ime/mojom/ime_types.mojom-blink-forward.h",
"+ui/base/resource/scale_factor.h",
"+ui/gfx/geometry",
"+ui/gfx/skia_util.h",
@@ -120,5 +123,8 @@ specific_include_rules = {
],
"element_test.cc": [
"+third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
+ ],
+ "html_canvas_painter_test.cc": [
+ "+components/viz/test/test_context_provider.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc b/chromium/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
index ccdd9658198..269edc4b716 100644
--- a/chromium/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
+++ b/chromium/third_party/blink/renderer/core/accessibility/apply_dark_mode.cc
@@ -39,16 +39,23 @@ bool HasLightBackground(const LayoutView& root) {
kBrightnessThreshold;
}
-DarkMode GetMode(const Settings& frame_settings) {
+bool IsDarkModeEnabled(const Settings& frame_settings) {
+ static bool isDarkModeEnabledByFeatureFlag =
+ features::kForceDarkInversionMethodParam.Get() !=
+ ForceDarkInversionMethod::kUseBlinkSettings;
+ return isDarkModeEnabledByFeatureFlag || frame_settings.GetDarkModeEnabled();
+}
+
+DarkModeInversionAlgorithm GetMode(const Settings& frame_settings) {
switch (features::kForceDarkInversionMethodParam.Get()) {
case ForceDarkInversionMethod::kUseBlinkSettings:
- return frame_settings.GetDarkMode();
+ return frame_settings.GetDarkModeInversionAlgorithm();
case ForceDarkInversionMethod::kCielabBased:
- return DarkMode::kInvertLightnessLAB;
+ return DarkModeInversionAlgorithm::kInvertLightnessLAB;
case ForceDarkInversionMethod::kHslBased:
- return DarkMode::kInvertLightness;
+ return DarkModeInversionAlgorithm::kInvertLightness;
case ForceDarkInversionMethod::kRgbBased:
- return DarkMode::kInvertBrightness;
+ return DarkModeInversionAlgorithm::kInvertBrightness;
}
}
@@ -80,39 +87,46 @@ int GetBackgroundBrightnessThreshold(const Settings& frame_settings) {
: frame_settings.GetDarkModeBackgroundBrightnessThreshold();
}
+DarkModeSettings GetEnabledSettings(const Settings& frame_settings) {
+ DarkModeSettings settings;
+ settings.mode = GetMode(frame_settings);
+ settings.image_policy = GetImagePolicy(frame_settings);
+ settings.text_brightness_threshold =
+ GetTextBrightnessThreshold(frame_settings);
+ settings.background_brightness_threshold =
+ GetBackgroundBrightnessThreshold(frame_settings);
+
+ settings.grayscale = frame_settings.GetDarkModeGrayscale();
+ settings.contrast = frame_settings.GetDarkModeContrast();
+ settings.image_grayscale_percent = frame_settings.GetDarkModeImageGrayscale();
+ return settings;
+}
+
+// In theory it should be sufficient for the disabled settings to set mode to
+// kOff (or to just return the default struct) without also setting
+// image_policy. However, this causes images to be inverted unexpectedly in
+// some cases (such as when toggling between the site's light and dark theme
+// on arstechnica.com).
+//
+// TODO(gilmanmh): Investigate unexpected image inversion behavior when
+// image_policy not set to kFilterNone.
+DarkModeSettings GetDisabledSettings() {
+ DarkModeSettings settings;
+ settings.mode = DarkModeInversionAlgorithm::kOff;
+ settings.image_policy = DarkModeImagePolicy::kFilterNone;
+ return settings;
+}
+
} // namespace
DarkModeSettings BuildDarkModeSettings(const Settings& frame_settings,
const LayoutView& root) {
- DarkModeSettings dark_mode_settings;
-
- if (!ShouldApplyDarkModeFilterToPage(frame_settings.GetDarkModePagePolicy(),
- root)) {
- // In theory it should be sufficient to set mode to
- // kOff (or to just return the default struct) without also setting
- // image_policy. However, this causes images to be inverted unexpectedly in
- // some cases (such as when toggling between the site's light and dark theme
- // on arstechnica.com).
- //
- // TODO(gilmanmh): Investigate unexpected image inversion behavior when
- // image_policy not set to kFilterNone.
- dark_mode_settings.mode = DarkMode::kOff;
- dark_mode_settings.image_policy = DarkModeImagePolicy::kFilterNone;
- return dark_mode_settings;
+ if (IsDarkModeEnabled(frame_settings) &&
+ ShouldApplyDarkModeFilterToPage(frame_settings.GetDarkModePagePolicy(),
+ root)) {
+ return GetEnabledSettings(frame_settings);
}
-
- dark_mode_settings.mode = GetMode(frame_settings);
- dark_mode_settings.image_policy = GetImagePolicy(frame_settings);
- dark_mode_settings.text_brightness_threshold =
- GetTextBrightnessThreshold(frame_settings);
- dark_mode_settings.background_brightness_threshold =
- GetBackgroundBrightnessThreshold(frame_settings);
-
- dark_mode_settings.grayscale = frame_settings.GetDarkModeGrayscale();
- dark_mode_settings.contrast = frame_settings.GetDarkModeContrast();
- dark_mode_settings.image_grayscale_percent =
- frame_settings.GetDarkModeImageGrayscale();
- return dark_mode_settings;
+ return GetDisabledSettings();
}
bool ShouldApplyDarkModeFilterToPage(DarkModePagePolicy policy,
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 04660530ad0..750d20f69fb 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
@@ -47,9 +47,8 @@ class LayoutRect;
class LineLayoutItem;
class LocalFrameView;
-class CORE_EXPORT AXObjectCache
- : public GarbageCollectedFinalized<AXObjectCache>,
- public ContextLifecycleObserver {
+class CORE_EXPORT AXObjectCache : public GarbageCollected<AXObjectCache>,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(AXObjectCache);
public:
diff --git a/chromium/third_party/blink/renderer/core/animation/BUILD.gn b/chromium/third_party/blink/renderer/core/animation/BUILD.gn
index a048dcf56a1..9ac82738a44 100644
--- a/chromium/third_party/blink/renderer/core/animation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/animation/BUILD.gn
@@ -19,7 +19,6 @@ buildflag_header("buildflags") {
}
blink_core_sources("animation") {
- split_count = 5
sources = [
"animatable.cc",
"animatable.h",
@@ -152,14 +151,18 @@ blink_core_sources("animation") {
"effect_stack.h",
"element_animations.cc",
"element_animations.h",
- "filter_interpolation_functions.cc",
- "filter_interpolation_functions.h",
"image_list_property_functions.h",
"image_slice_property_functions.h",
"inert_effect.cc",
"inert_effect.h",
+ "interpolable_filter.cc",
+ "interpolable_filter.h",
"interpolable_length.cc",
"interpolable_length.h",
+ "interpolable_shadow.cc",
+ "interpolable_shadow.h",
+ "interpolable_transform_list.cc",
+ "interpolable_transform_list.h",
"interpolable_value.cc",
"interpolable_value.h",
"interpolated_svg_path_source.h",
@@ -202,8 +205,6 @@ blink_core_sources("animation") {
"scroll_timeline.h",
"scroll_timeline_util.cc",
"scroll_timeline_util.h",
- "shadow_interpolation_functions.cc",
- "shadow_interpolation_functions.h",
"side_index.h",
"size_interpolation_functions.cc",
"size_interpolation_functions.h",
diff --git a/chromium/third_party/blink/renderer/core/animation/animatable.cc b/chromium/third_party/blink/renderer/core/animation/animatable.cc
index f9dda660f16..88fc2ef60e7 100644
--- a/chromium/third_party/blink/renderer/core/animation/animatable.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animatable.cc
@@ -83,20 +83,30 @@ Animation* Animatable::animate(ScriptState* script_state,
return animateInternal(*element, effect, Timing());
}
-HeapVector<Member<Animation>> Animatable::getAnimations() {
+HeapVector<Member<Animation>> Animatable::getAnimations(
+ GetAnimationsOptions* options) {
+ bool use_subtree = options && options->subtree();
Element* element = GetAnimationTarget();
- element->GetDocument().UpdateStyleAndLayoutTreeForNode(element);
+ if (use_subtree)
+ element->GetDocument().UpdateStyleAndLayoutTreeForSubtree(element);
+ else
+ element->GetDocument().UpdateStyleAndLayoutTreeForNode(element);
HeapVector<Member<Animation>> animations;
- if (!element->HasAnimations())
+ if (!use_subtree && !element->HasAnimations())
return animations;
for (const auto& animation :
element->GetDocument().Timeline().getAnimations()) {
DCHECK(animation->effect());
- if (ToKeyframeEffect(animation->effect())->target() == element &&
- (animation->effect()->IsCurrent() || animation->effect()->IsInEffect()))
+ Element* target = ToKeyframeEffect(animation->effect())->target();
+ if (element == target || (use_subtree && element->contains(target))) {
+ // DocumentTimeline::getAnimations should only give us animations that are
+ // either current or in effect.
+ DCHECK(animation->effect()->IsCurrent() ||
+ animation->effect()->IsInEffect());
animations.push_back(animation);
+ }
}
return animations;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/animatable.h b/chromium/third_party/blink/renderer/core/animation/animatable.h
index f930d370531..3b568266aef 100644
--- a/chromium/third_party/blink/renderer/core/animation/animatable.h
+++ b/chromium/third_party/blink/renderer/core/animation/animatable.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATABLE_H_
+#include "third_party/blink/renderer/core/animation/get_animations_options.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/heap/member.h"
@@ -60,7 +61,8 @@ class CORE_EXPORT Animatable {
Animation* animate(ScriptState*, const ScriptValue&, ExceptionState&);
- HeapVector<Member<Animation>> getAnimations();
+ HeapVector<Member<Animation>> getAnimations(
+ GetAnimationsOptions* options = nullptr);
private:
FRIEND_TEST_ALL_PREFIXES(AnimationSimTest, CustomPropertyBaseComputedStyle);
diff --git a/chromium/third_party/blink/renderer/core/animation/animatable.idl b/chromium/third_party/blink/renderer/core/animation/animatable.idl
index 4862ea48a8d..9d4327680d0 100644
--- a/chromium/third_party/blink/renderer/core/animation/animatable.idl
+++ b/chromium/third_party/blink/renderer/core/animation/animatable.idl
@@ -31,7 +31,7 @@
// https://drafts.csswg.org/web-animations/#the-animatable-interface-mixin
interface mixin Animatable {
[CallWith=ScriptState, Measure, RaisesException] Animation animate(object? keyframes, optional (unrestricted double or KeyframeAnimationOptions) options);
- [RuntimeEnabled=WebAnimationsAPI] sequence<Animation> getAnimations();
+ [RuntimeEnabled=WebAnimationsAPI] sequence<Animation> getAnimations(optional GetAnimationsOptions options);
};
// https://drafts.csswg.org/web-animations-1/#extensions-to-the-element-interface
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.cc b/chromium/third_party/blink/renderer/core/animation/animation.cc
index 419c030ab6e..b2d03baa08f 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation.cc
@@ -52,6 +52,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
@@ -68,10 +69,14 @@ unsigned NextSequenceNumber() {
return ++next;
}
-double ToMilliseconds(double seconds) {
+double SecondsToMilliseconds(double seconds) {
return seconds * 1000;
}
+double MillisecondsToSeconds(double milliseconds) {
+ return milliseconds / 1000;
+}
+
bool AreEqualOrNull(double a, double b) {
// Null values are represented as NaNs, which have the property NaN != NaN.
if (IsNull(a) && IsNull(b))
@@ -86,6 +91,18 @@ base::Optional<double> ValueOrUnresolved(double a) {
return value;
}
+double Max(base::Optional<double> a, double b) {
+ if (a.has_value())
+ return std::max(a.value(), b);
+ return b;
+}
+
+double Min(base::Optional<double> a, double b) {
+ if (a.has_value())
+ return std::min(a.value(), b);
+ return b;
+}
+
void RecordCompositorAnimationFailureReasons(
CompositorAnimations::FailureReasons failure_reasons) {
// UMA_HISTOGRAM_ENUMERATION requires that the enum_max must be strictly
@@ -154,6 +171,7 @@ Animation::Animation(ExecutionContext* execution_context,
AnimationEffect* content)
: ContextLifecycleObserver(execution_context),
internal_play_state_(kIdle),
+ reported_play_state_(kIdle),
animation_play_state_(kIdle),
playback_rate_(1),
start_time_(),
@@ -166,6 +184,8 @@ Animation::Animation(ExecutionContext* execution_context,
is_composited_animation_disabled_for_testing_(false),
pending_pause_(false),
pending_play_(false),
+ pending_finish_notification_(false),
+ has_queued_microtask_(false),
outdated_(false),
finished_(true),
compositor_state_(nullptr),
@@ -233,6 +253,7 @@ DocumentTimeline& Animation::TickingTimeline() {
return document_->Timeline();
}
+// https://drafts.csswg.org/web-animations/#setting-the-current-time-of-an-animation.
void Animation::setCurrentTime(double new_current_time,
bool is_null,
ExceptionState& exception_state) {
@@ -246,10 +267,6 @@ void Animation::setCurrentTime(double new_current_time,
return;
}
- PlayStateUpdateScope update_scope(*this, kTimingUpdateOnDemand);
-
- // Step 1. of the procedure to silently set the current time of an
- // animation states that we abort if the new time is null.
if (is_null) {
// If the current time is resolved, then throw a TypeError.
if (!IsNull(CurrentTimeInternal())) {
@@ -259,17 +276,62 @@ void Animation::setCurrentTime(double new_current_time,
return;
}
+ SetCurrentTimeInternal(MillisecondsToSeconds(new_current_time));
+
+ // Synchronously resolve pending pause task.
+ if (pending_pause_) {
+ hold_time_ = MillisecondsToSeconds(new_current_time);
+ ApplyPendingPlaybackRate();
+ start_time_ = base::nullopt;
+ pending_pause_ = false;
+ if (ready_promise_)
+ ResolvePromiseMaybeAsync(ready_promise_.Get());
+ }
+
+ // TODO(crbug.com/960944): Deprecate use of legacy flags.
if (PlayStateInternal() == kIdle)
paused_ = true;
-
current_time_pending_ = false;
internal_play_state_ = kUnset;
- SetCurrentTimeInternal(new_current_time / 1000, kTimingUpdateOnDemand);
- if (CalculatePlayState() == kFinished)
+ // Update the finished state.
+ UpdateFinishedState(UpdateType::kDiscontinuous, NotificationType::kAsync);
+
+ SetCompositorPending(/*effect_changed=*/false);
+ animation_play_state_ = CalculateAnimationPlayState();
+ internal_play_state_ = CalculatePlayState();
+}
+
+// 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.
+void Animation::SetCurrentTimeInternal(double new_current_time) {
+ DCHECK(std::isfinite(new_current_time));
+
+ base::Optional<double> previous_start_time = start_time_;
+ base::Optional<double> previous_hold_time = hold_time_;
+
+ // Update either the hold time or the start time.
+ if (hold_time_ || !start_time_ || !timeline_ || !timeline_->IsActive() ||
+ playback_rate_ == 0)
+ hold_time_ = new_current_time;
+ else
start_time_ = CalculateStartTime(new_current_time);
+
+ // Preserve invariant that we can only set a start time or a hold time in the
+ // absence of an active timeline.
+ if (!timeline_ || !timeline_->IsActive())
+ start_time_ = base::nullopt;
+
+ // Reset the previous current time.
+ previous_current_time_ = base::nullopt;
+
+ if (previous_start_time != start_time_ || previous_hold_time != hold_time_)
+ SetOutdated();
}
+// TODO(crbug.com/960944): Deprecate. This method is only called by methods that
+// are pending refactoring to align with the web-animation spec.
void Animation::SetCurrentTimeInternal(double new_current_time,
TimingUpdateReason reason) {
DCHECK(std::isfinite(new_current_time));
@@ -295,6 +357,8 @@ void Animation::SetCurrentTimeInternal(double new_current_time,
outdated = true;
}
+ previous_current_time_ = base::nullopt;
+
if (outdated) {
SetOutdated();
}
@@ -349,7 +413,7 @@ double Animation::currentTime() {
// 1. If the animation’s hold time is resolved,
// The current time is the animation’s hold time.
if (hold_time_.has_value())
- return ToMilliseconds(hold_time_.value());
+ return SecondsToMilliseconds(hold_time_.value());
// 2. If any of the following are true:
// * the animation has no associated timeline, or
@@ -371,7 +435,7 @@ double Animation::currentTime() {
}
double current_time =
(timeline_time.value() - start_time_.value()) * playback_rate_;
- return ToMilliseconds(current_time);
+ return SecondsToMilliseconds(current_time);
}
double Animation::CurrentTimeInternal() const {
@@ -452,7 +516,6 @@ bool Animation::PreCommit(
}
}
}
-
return true;
}
@@ -797,6 +860,7 @@ void Animation::pause(ExceptionState& exception_state) {
// (https://drafts.csswg.org/web-animations/#play-states).
paused_ = true;
pending_pause_ = true;
+ pending_play_ = false;
current_time_pending_ = true;
SetCurrentTimeInternal(new_current_time, kTimingUpdateOnDemand);
@@ -842,6 +906,7 @@ void Animation::play(ExceptionState& exception_state) {
internal_play_state_ = kUnset;
pending_play_ = true;
+ pending_pause_ = false;
finished_ = false;
UnpauseInternal();
@@ -882,43 +947,168 @@ void Animation::reverse(ExceptionState& exception_state) {
}
}
+// ----------------------------------------------
+// Finish methods.
+// ----------------------------------------------
+
// https://drafts.csswg.org/web-animations/#finishing-an-animation-section
void Animation::finish(ExceptionState& exception_state) {
- // Force resolution of PlayStateUpdateScope to enable immediate queuing of
- // the finished event.
- {
- PlayStateUpdateScope update_scope(*this, kTimingUpdateOnDemand);
+ if (!EffectivePlaybackRate()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Cannot finish Animation with a playbackRate of 0.");
+ return;
+ }
+ if (EffectivePlaybackRate() > 0 &&
+ EffectEnd() == std::numeric_limits<double>::infinity()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Cannot finish Animation with an infinite target effect end.");
+ return;
+ }
- if (!playback_rate_) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "Cannot finish Animation with a playbackRate of 0.");
- return;
+ ApplyPendingPlaybackRate();
+
+ double new_current_time = playback_rate_ < 0 ? 0 : EffectEnd();
+ SetCurrentTimeInternal(new_current_time);
+
+ if (!start_time_ && timeline_ && timeline_->IsActive())
+ start_time_ = CalculateStartTime(new_current_time);
+
+ if (pending_pause_ && start_time_) {
+ hold_time_ = base::nullopt;
+ pending_pause_ = false;
+ if (ready_promise_)
+ ResolvePromiseMaybeAsync(ready_promise_.Get());
+ }
+ if (pending_play_ && start_time_) {
+ pending_play_ = false;
+ if (ready_promise_)
+ ResolvePromiseMaybeAsync(ready_promise_.Get());
+ }
+
+ // TODO(crbug.com/960944): Cleanup use of legacy flags.
+ paused_ = false;
+ current_time_pending_ = false;
+ internal_play_state_ = kUnset;
+ ResetPendingTasks();
+
+ SetOutdated();
+ UpdateFinishedState(UpdateType::kDiscontinuous, NotificationType::kSync);
+ animation_play_state_ = internal_play_state_ = kFinished;
+}
+
+void Animation::UpdateFinishedState(UpdateType update_type,
+ NotificationType notification_type) {
+ bool did_seek = update_type == UpdateType::kDiscontinuous;
+ // 1. Calculate the unconstrained current time. The dependency on did_seek is
+ // required to accommodate timelines that may change direction. Without this
+ // distinction, a once-finished animation would remain finished even when its
+ // timeline progresses in the opposite direction.
+ double unconstrained_current_time =
+ did_seek ? CurrentTimeInternal() : CalculateCurrentTime();
+
+ // 2. Conditionally update the hold time.
+ if (!IsNull(unconstrained_current_time) && start_time_ && !pending_play_ &&
+ !pending_pause_) {
+ // Can seek outside the bounds of the active effect. Set the hold time to
+ // the unconstrained value of the current time in the even that this update
+ // this the result of explicitly setting the current time and the new time
+ // is out of bounds. An update due to a time tick should not snap the hold
+ // value back to the boundary if previously set outside the normal effect
+ // boundary. The value of previous current time is used to retain this
+ // value.
+ double playback_rate = EffectivePlaybackRate();
+ if (playback_rate > 0 && unconstrained_current_time >= EffectEnd()) {
+ hold_time_ = did_seek ? unconstrained_current_time
+ : Max(previous_current_time_, EffectEnd());
+ } else if (playback_rate < 0 && unconstrained_current_time <= 0) {
+ hold_time_ = did_seek ? unconstrained_current_time
+ : Min(previous_current_time_, 0);
+ // Hack for resolving precision issue at zero.
+ if (hold_time_.value() == -0)
+ hold_time_ = 0;
+ } else if (playback_rate != 0) {
+ // Update start time and reset hold time.
+ if (did_seek && hold_time_)
+ start_time_ = CalculateStartTime(hold_time_.value());
+ hold_time_ = base::nullopt;
}
- if (playback_rate_ > 0 &&
- EffectEnd() == std::numeric_limits<double>::infinity()) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "Cannot finish Animation with an infinite target effect end.");
- return;
+ }
+
+ // 3. Set the previous current time.
+ previous_current_time_ = ValueOrUnresolved(CurrentTimeInternal());
+
+ // 4. Set the current finished state.
+ AnimationPlayState play_state = CalculateAnimationPlayState();
+ if (play_state == kFinished) {
+ // 5. Setup finished notification.
+ if (notification_type == NotificationType::kSync)
+ CommitFinishNotification();
+ else
+ ScheduleAsyncFinish();
+ } else {
+ // 6. If not finished but the current finished promise is already resolved,
+ // create a new promise.
+ finished_ = pending_finish_notification_ = false;
+ if (finished_promise_ &&
+ finished_promise_->GetState() == AnimationPromise::kResolved) {
+ finished_promise_->Reset();
}
+ }
+ NotifyProbe();
+}
- // Avoid updating start time when already finished.
- if (CalculatePlayState() == kFinished)
- return;
+void Animation::ScheduleAsyncFinish() {
+ // Run a task to handle the finished promise and event as a microtask. With
+ // the exception of an explicit call to Animation::finish, it is important to
+ // apply these updates asynchronously as it is possible to enter the finished
+ // state temporarily.
+ pending_finish_notification_ = true;
+ if (!has_queued_microtask_) {
+ Microtask::EnqueueMicrotask(
+ WTF::Bind(&Animation::AsyncFinishMicrotask, WrapWeakPersistent(this)));
+ has_queued_microtask_ = true;
+ }
+}
- double new_current_time = playback_rate_ < 0 ? 0 : EffectEnd();
- SetCurrentTimeInternal(new_current_time, kTimingUpdateOnDemand);
- paused_ = false;
- current_time_pending_ = false;
- start_time_ = CalculateStartTime(new_current_time);
- internal_play_state_ = kFinished;
- ResetPendingTasks();
+void Animation::AsyncFinishMicrotask() {
+ // Resolve the finished promise and queue the finished event only if the
+ // animation is still in a pending finished state. It is possible that the
+ // transition was only temporary.
+ if (pending_finish_notification_)
+ CommitFinishNotification();
+
+ // This is a once callback and needs to be re-armed.
+ has_queued_microtask_ = false;
+}
+
+void Animation::CommitFinishNotification() {
+ pending_finish_notification_ = false;
+ pending_play_ = pending_pause_ = false;
+ animation_play_state_ = kFinished;
+
+ // TODO(crbug.com/960944) Deprecate following flags.
+ current_time_pending_ = false;
+ internal_play_state_ = kFinished;
+
+ // If start_time_ is not set, then CalculatePlayState will return pending
+ // rather than finished. Force synchronous resolution of the start time.
+ if (!start_time_ && hold_time_ && timeline_ && timeline_->IsActive())
+ start_time_ = CalculateStartTime(hold_time_.value());
+
+ if (finished_promise_ &&
+ finished_promise_->GetState() == AnimationPromise::kPending) {
+ ResolvePromiseMaybeAsync(finished_promise_.Get());
}
- // Resolve finished event immediately.
QueueFinishedEvent();
}
+void Animation::CommitAllUpdatesForTesting() {
+ if (pending_finish_notification_)
+ CommitFinishNotification();
+}
+
// https://drafts.csswg.org/web-animations/#setting-the-playback-rate-of-an-animation
void Animation::updatePlaybackRate(double playback_rate,
ExceptionState& exception_state) {
@@ -1007,6 +1197,17 @@ double Animation::playbackRate() const {
return active_playback_rate_.value_or(playback_rate_);
}
+double Animation::EffectivePlaybackRate() const {
+ // TODO(crbug.com/960944): Use pending playback rate.
+ return playback_rate_;
+}
+
+void Animation::ApplyPendingPlaybackRate() {
+ // TODO(crbug.com/960944): If pending playback rate is set, then update the
+ // playback rate accordingly.
+ active_playback_rate_ = base::nullopt;
+}
+
void Animation::setPlaybackRate(double playback_rate,
ExceptionState& exception_state) {
// TODO(crbug.com/916117): Implement setting playback rate for scroll-linked
@@ -1267,22 +1468,8 @@ bool Animation::Update(TimingUpdateReason reason) {
if ((idle || Limited()) && !finished_) {
if (reason == kTimingUpdateForAnimationFrame && (idle || start_time_)) {
- if (idle) {
- const AtomicString& event_type = event_type_names::kCancel;
- if (GetExecutionContext() && HasEventListeners(event_type)) {
- double event_current_time = NullValue();
- // TODO(crbug.com/916117): Handle NaN values for scroll-linked
- // animations.
- pending_cancelled_event_ =
- MakeGarbageCollected<AnimationPlaybackEvent>(
- event_type, event_current_time, TimelineTime());
- pending_cancelled_event_->SetTarget(this);
- pending_cancelled_event_->SetCurrentTarget(this);
- document_->EnqueueAnimationFrameEvent(pending_cancelled_event_);
- }
- } else {
+ if (!idle)
QueueFinishedEvent();
- }
finished_ = true;
}
}
@@ -1334,9 +1521,11 @@ base::Optional<AnimationTimeDelta> Animation::TimeToEffectChange() {
playback_rate_);
}
- double result = playback_rate_ > 0
- ? content_->TimeToForwardsEffectChange() / playback_rate_
- : content_->TimeToReverseEffectChange() / -playback_rate_;
+ double result =
+ playback_rate_ > 0
+ ? content_->TimeToForwardsEffectChange().InSecondsF() / playback_rate_
+ : content_->TimeToReverseEffectChange().InSecondsF() /
+ -playback_rate_;
return !HasActiveAnimationsOnCompositor() &&
content_->GetPhase() == Timing::kPhaseActive
@@ -1345,17 +1534,61 @@ base::Optional<AnimationTimeDelta> Animation::TimeToEffectChange() {
}
void Animation::cancel() {
- PlayStateUpdateScope update_scope(*this, kTimingUpdateOnDemand);
+ // TODO(crbug.com/916117): Get rid of internal_play_state_.
+ internal_play_state_ = kUnset;
+ AnimationPlayState initial_play_state = CalculateAnimationPlayState();
+ if (initial_play_state != kIdle) {
+ if (pending()) {
+ // TODO(crbug.com/916117): Rejecting the ready promise should be performed
+ // inside reset pending tasks once aligned with the spec.
+ // TODO(crbug.com/1013351): Add test for rejection and reset of cancel
+ // promise. Requires further cleanup of PlayStateUpdateScope.
+ if (ready_promise_)
+ RejectAndResetPromiseMaybeAsync(ready_promise_.Get());
+ }
+ ResetPendingTasks();
- if (PlayStateInternal() == kIdle)
- return;
+ if (finished_promise_) {
+ if (finished_promise_->GetState() == AnimationPromise::kPending)
+ RejectAndResetPromiseMaybeAsync(finished_promise_.Get());
+ else
+ finished_promise_->Reset();
+ }
+
+ const AtomicString& event_type = event_type_names::kCancel;
+ if (GetExecutionContext() && HasEventListeners(event_type)) {
+ double event_current_time = NullValue();
+ // TODO(crbug.com/916117): Handle NaN values for scroll-linked
+ // animations.
+ pending_cancelled_event_ = MakeGarbageCollected<AnimationPlaybackEvent>(
+ event_type, event_current_time, TimelineTime());
+ pending_cancelled_event_->SetTarget(this);
+ pending_cancelled_event_->SetCurrentTarget(this);
+ document_->EnqueueAnimationFrameEvent(pending_cancelled_event_);
+ }
+ } else {
+ // Quietly reset without rejecting promises.
+ active_playback_rate_ = base::nullopt;
+ pending_pause_ = pending_play_ = false;
+ }
hold_time_ = base::nullopt;
+ start_time_ = base::nullopt;
+
+ // TODO(crbug.com/958433): Phase out the use of these variables, which are not
+ // in the spec.
paused_ = false;
internal_play_state_ = kIdle;
- start_time_ = base::nullopt;
current_time_pending_ = false;
- ResetPendingTasks();
+
+ animation_play_state_ = kIdle;
+
+ // Apply changes synchronously.
+ SetCompositorPending(/*effect_changed=*/false);
+ NotifyProbe();
+ SetOutdated();
+
+ // Force dispatch of canceled event.
ForceServiceOnNextFrame();
}
@@ -1447,65 +1680,28 @@ Animation::PlayStateUpdateScope::PlayStateUpdateScope(
Animation::PlayStateUpdateScope::~PlayStateUpdateScope() {
AnimationPlayState old_play_state = initial_play_state_;
AnimationPlayState new_play_state = animation_->CalculatePlayState();
-
- // TODO(crbug.com/958433): Phase out internal_play_state_ in favor of the spec
- // compliant version. At present, both are needed as the web exposed play
- // state cannot simply be inferred from the internal play state.
animation_->internal_play_state_ = new_play_state;
animation_->animation_play_state_ = animation_->CalculateAnimationPlayState();
- if (old_play_state != new_play_state) {
- bool was_active = old_play_state == kPending || old_play_state == kRunning;
- bool is_active = new_play_state == kPending || new_play_state == kRunning;
- if (!was_active && is_active) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
- "blink.animations,devtools.timeline,benchmark,rail", "Animation",
- animation_, "data", inspector_animation_event::Data(*animation_));
- } else if (was_active && !is_active) {
- TRACE_EVENT_NESTABLE_ASYNC_END1(
- "blink.animations,devtools.timeline,benchmark,rail", "Animation",
- animation_, "endData",
- inspector_animation_state_event::Data(*animation_));
- } else {
- TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
- "blink.animations,devtools.timeline,benchmark,rail", "Animation",
- animation_, "data",
- inspector_animation_state_event::Data(*animation_));
- }
- }
// Ordering is important, the ready promise should resolve/reject before
// the finished promise.
if (animation_->ready_promise_ && new_play_state != old_play_state) {
- if (new_play_state == kIdle) {
- if (animation_->ready_promise_->GetState() ==
- AnimationPromise::kPending) {
- animation_->RejectAndResetPromiseMaybeAsync(
- animation_->ready_promise_.Get());
- } else {
- animation_->ready_promise_->Reset();
- }
- animation_->ResetPendingTasks();
- animation_->ResolvePromiseMaybeAsync(animation_->ready_promise_.Get());
- } else if (old_play_state == kPending) {
+ // Transitioning to an idle state is handled in cancel().
+ DCHECK(new_play_state != kIdle);
+
+ if (old_play_state == kPending) {
animation_->ResetPendingTasks();
animation_->ResolvePromiseMaybeAsync(animation_->ready_promise_.Get());
} else if (new_play_state == kPending) {
- DCHECK_NE(animation_->ready_promise_->GetState(),
- AnimationPromise::kPending);
animation_->ready_promise_->Reset();
}
}
if (animation_->finished_promise_ && new_play_state != old_play_state) {
- if (new_play_state == kIdle) {
- if (animation_->finished_promise_->GetState() ==
- AnimationPromise::kPending) {
- animation_->RejectAndResetPromiseMaybeAsync(
- animation_->finished_promise_.Get());
- } else {
- animation_->finished_promise_->Reset();
- }
- } else if (new_play_state == kFinished) {
+ // Transitioning to an idle state is handled in cancel().
+ DCHECK(new_play_state != kIdle);
+
+ if (new_play_state == kFinished) {
animation_->ResetPendingTasks();
animation_->ResolvePromiseMaybeAsync(animation_->finished_promise_.Get());
} else if (old_play_state == kFinished) {
@@ -1537,11 +1733,7 @@ Animation::PlayStateUpdateScope::~PlayStateUpdateScope() {
break;
}
animation_->EndUpdatingState();
-
- if (old_play_state != new_play_state) {
- probe::AnimationPlayStateChanged(animation_->document_, animation_,
- old_play_state, new_play_state);
- }
+ animation_->NotifyProbe();
}
void Animation::AddedEventListener(
@@ -1622,6 +1814,35 @@ void Animation::RejectAndResetPromiseMaybeAsync(AnimationPromise* promise) {
}
}
+void Animation::NotifyProbe() {
+ AnimationPlayState old_play_state = reported_play_state_;
+ AnimationPlayState new_play_state =
+ pending() ? kPending : CalculateAnimationPlayState();
+
+ if (old_play_state != new_play_state) {
+ probe::AnimationPlayStateChanged(document_, this, old_play_state,
+ new_play_state);
+ reported_play_state_ = new_play_state;
+
+ bool was_active = old_play_state == kPending || old_play_state == kRunning;
+ bool is_active = new_play_state == kPending || new_play_state == kRunning;
+
+ if (!was_active && is_active) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "blink.animations,devtools.timeline,benchmark,rail", "Animation",
+ this, "data", inspector_animation_event::Data(*this));
+ } else if (was_active && !is_active) {
+ TRACE_EVENT_NESTABLE_ASYNC_END1(
+ "blink.animations,devtools.timeline,benchmark,rail", "Animation",
+ this, "endData", inspector_animation_state_event::Data(*this));
+ } else {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
+ "blink.animations,devtools.timeline,benchmark,rail", "Animation",
+ this, "data", inspector_animation_state_event::Data(*this));
+ }
+ }
+}
+
void Animation::Trace(blink::Visitor* visitor) {
visitor->Trace(content_);
visitor->Trace(document_);
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.h b/chromium/third_party/blink/renderer/core/animation/animation.h
index f8597104186..ea510e45114 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation.h
@@ -244,6 +244,7 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
void Trace(blink::Visitor*) override;
bool CompositorPendingForTesting() const { return compositor_pending_; }
+ void CommitAllUpdatesForTesting();
protected:
DispatchEventResult DispatchEventInternal(Event&) override;
@@ -257,8 +258,8 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
AnimationPlayState PlayStateInternal() const;
double CurrentTimeInternal() const;
- void SetCurrentTimeInternal(double new_current_time,
- TimingUpdateReason = kTimingUpdateOnDemand);
+ void SetCurrentTimeInternal(double new_current_time);
+ void SetCurrentTimeInternal(double new_current_time, TimingUpdateReason);
void ClearOutdated();
void ForceServiceOnNextFrame();
@@ -270,6 +271,7 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
// If there are no pending tasks, then the effective playback rate equals the
// active playback rate.
double EffectivePlaybackRate() const;
+ void ApplyPendingPlaybackRate();
void ResolvePendingPlaybackRate();
// https://drafts.csswg.org/web-animations/#play-states
@@ -316,17 +318,39 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
void RejectAndResetPromise(AnimationPromise*);
void RejectAndResetPromiseMaybeAsync(AnimationPromise*);
+ // Updates the finished state of the animation. If the update is the result of
+ // a discontinuous time change then the value for current time is not bound by
+ // the limits of the animation. The finished notification may be synchronous
+ // or asynchronous. A synchronous notification is used in the case of
+ // explicitly calling finish on an animation.
+ enum class UpdateType { kContinuous, kDiscontinuous };
+ enum class NotificationType { kAsync, kSync };
+ void UpdateFinishedState(UpdateType update_context,
+ NotificationType notification_type);
void QueueFinishedEvent();
void ResetPendingTasks();
double TimelineTime() const;
DocumentTimeline& TickingTimeline();
+ void ScheduleAsyncFinish();
+ void AsyncFinishMicrotask();
+ void CommitFinishNotification();
+
+ // Tracking the state of animations in dev tools.
+ void NotifyProbe();
+
String id_;
// Extended play state with additional pending state for managing timing of
// micro-tasks.
+ // TODO(crbug.com/958433): Phase out this version of the play state. Should
+ // just need the reported play state.
AnimationPlayState internal_play_state_;
+ // Extended play state reported to dev tools. This play state has an
+ // additional pending state that is not part of the spec by expected by dev
+ // tools.
+ AnimationPlayState reported_play_state_;
// Web exposed play state, which does not have pending state.
AnimationPlayState animation_play_state_;
double playback_rate_;
@@ -340,6 +364,7 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
base::Optional<double> active_playback_rate_;
base::Optional<double> start_time_;
base::Optional<double> hold_time_;
+ base::Optional<double> previous_current_time_;
unsigned sequence_number_;
@@ -362,6 +387,8 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
// control.
bool pending_pause_;
bool pending_play_;
+ bool pending_finish_notification_;
+ bool has_queued_microtask_;
// This indicates timing information relevant to the animation's effect
// has changed by means other than the ordinary progression of time
@@ -421,8 +448,8 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
// CompositorAnimation objects need to eagerly sever their connection to their
// Animation delegate; use a separate 'holder' on-heap object to accomplish
// that.
- class CompositorAnimationHolder
- : public GarbageCollectedFinalized<CompositorAnimationHolder> {
+ class CompositorAnimationHolder final
+ : public GarbageCollected<CompositorAnimationHolder> {
USING_PRE_FINALIZER(CompositorAnimationHolder, Dispose);
public:
@@ -461,6 +488,8 @@ class CORE_EXPORT Animation : public EventTargetWithInlineData,
FRIEND_TEST_ALL_PREFIXES(AnimationAnimationTestCompositeAfterPaint,
NoCompositeWithoutCompositedElementId);
+ FRIEND_TEST_ALL_PREFIXES(AnimationAnimationTestNoCompositing,
+ PendingActivityWithFinishedEventListener);
};
} // 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 238faebdf9a..1f75362599a 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.cc
@@ -76,8 +76,11 @@ void AnimationEffect::updateTiming(OptionalEffectTiming* optional_timing,
void AnimationEffect::UpdateInheritedTime(double inherited_time,
TimingUpdateReason reason) const {
+ base::Optional<double> playback_rate = base::nullopt;
+ if (GetAnimation())
+ playback_rate = GetAnimation()->playbackRate();
const Timing::AnimationDirection direction =
- (GetAnimation() && GetAnimation()->playbackRate() < 0)
+ (playback_rate && playback_rate.value() < 0)
? Timing::AnimationDirection::kBackwards
: Timing::AnimationDirection::kForwards;
bool needs_update =
@@ -91,22 +94,16 @@ void AnimationEffect::UpdateInheritedTime(double inherited_time,
const double local_time = inherited_time;
if (needs_update) {
Timing::CalculatedTiming calculated = SpecifiedTiming().CalculateTimings(
- local_time, direction, IsKeyframeEffect());
+ local_time, direction, IsKeyframeEffect(), playback_rate);
const bool was_canceled = calculated.phase != calculated_.phase &&
calculated.phase == Timing::kPhaseNone;
// If the animation was canceled, we need to fire the event condition before
- // updating the timing so that the cancelation time can be determined.
+ // updating the calculated timing so that the cancellation time can be
+ // determined.
if (was_canceled && event_delegate_) {
- // TODO(jortaylo): OnEventCondition uses the new phase but the old current
- // iterations. That is why we partially update *calculated_* here with the
- // new phase. This pseudo state can be very confusing. It may be either a
- // bug or required but at the very least instead of partially updating
- // *calculated_* we should pass in current phase and the old "current
- // iterations" more explicitly. https://crbug.com/994850
- calculated_.phase = calculated.phase;
- event_delegate_->OnEventCondition(*this);
+ event_delegate_->OnEventCondition(*this, calculated.phase);
}
calculated_ = calculated;
@@ -119,7 +116,7 @@ void AnimationEffect::UpdateInheritedTime(double inherited_time,
if (reason == kTimingUpdateForAnimationFrame &&
(!owner_ || owner_->IsEventDispatchAllowed())) {
if (event_delegate_)
- event_delegate_->OnEventCondition(*this);
+ event_delegate_->OnEventCondition(*this, calculated_.phase);
}
if (needs_update) {
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 746d085e5f2..01f5dbe2069 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.h
@@ -67,11 +67,11 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
friend class EffectStack;
public:
- class EventDelegate : public GarbageCollectedFinalized<EventDelegate> {
+ class EventDelegate : public GarbageCollected<EventDelegate> {
public:
virtual ~EventDelegate() = default;
virtual bool RequiresIterationEvents(const AnimationEffect&) = 0;
- virtual void OnEventCondition(const AnimationEffect&) = 0;
+ virtual void OnEventCondition(const AnimationEffect&, Timing::Phase) = 0;
virtual void Trace(blink::Visitor* visitor) {}
};
@@ -84,16 +84,16 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
bool IsCurrent() const { return EnsureCalculated().is_current; }
bool IsInEffect() const { return EnsureCalculated().is_in_effect; }
bool IsInPlay() const { return EnsureCalculated().is_in_play; }
- double CurrentIteration() const {
+ base::Optional<double> CurrentIteration() const {
return EnsureCalculated().current_iteration;
}
base::Optional<double> Progress() const {
return EnsureCalculated().progress;
}
- double TimeToForwardsEffectChange() const {
+ AnimationTimeDelta TimeToForwardsEffectChange() const {
return EnsureCalculated().time_to_forwards_effect_change;
}
- double TimeToReverseEffectChange() const {
+ AnimationTimeDelta TimeToReverseEffectChange() const {
return EnsureCalculated().time_to_reverse_effect_change;
}
double LocalTime() const { return EnsureCalculated().local_time; }
@@ -142,7 +142,7 @@ class CORE_EXPORT AnimationEffect : public ScriptWrappable {
return AnimationTimeDelta();
}
- virtual double CalculateTimeToEffectChange(
+ virtual AnimationTimeDelta CalculateTimeToEffectChange(
bool forwards,
double local_time,
double time_to_next_iteration) const = 0;
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 d29b93837d7..807239ec8f5 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
@@ -40,7 +40,7 @@
namespace blink {
class MockAnimationEffectOwner
- : public GarbageCollectedFinalized<MockAnimationEffectOwner>,
+ : public GarbageCollected<MockAnimationEffectOwner>,
public AnimationEffectOwner {
USING_GARBAGE_COLLECTED_MIXIN(MockAnimationEffectOwner);
@@ -56,7 +56,8 @@ class MockAnimationEffectOwner
class TestAnimationEffectEventDelegate : public AnimationEffect::EventDelegate {
public:
- void OnEventCondition(const AnimationEffect& animation_node) override {
+ void OnEventCondition(const AnimationEffect& animation_node,
+ Timing::Phase current_phase) override {
event_triggered_ = true;
}
bool RequiresIterationEvents(const AnimationEffect& animation_node) override {
@@ -92,13 +93,13 @@ class TestAnimationEffect : public AnimationEffect {
TestAnimationEffectEventDelegate* EventDelegate() {
return event_delegate_.Get();
}
- double CalculateTimeToEffectChange(
+ AnimationTimeDelta CalculateTimeToEffectChange(
bool forwards,
double local_time,
double time_to_next_iteration) const override {
local_time_ = local_time;
time_to_next_iteration_ = time_to_next_iteration;
- return -1;
+ return AnimationTimeDelta::FromSecondsD(-1);
}
double TakeLocalTime() {
const double result = local_time_;
@@ -246,7 +247,7 @@ TEST(AnimationAnimationEffectTest, ZeroIteration) {
animation_node->UpdateInheritedTime(-1);
EXPECT_EQ(0, animation_node->SpecifiedTiming().ActiveDuration());
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
@@ -263,7 +264,7 @@ TEST(AnimationAnimationEffectTest, InfiniteIteration) {
auto* animation_node = MakeGarbageCollected<TestAnimationEffect>(timing);
animation_node->UpdateInheritedTime(-1);
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
EXPECT_EQ(std::numeric_limits<double>::infinity(),
@@ -475,7 +476,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationInfiniteIteration) {
animation_node->UpdateInheritedTime(-1);
EXPECT_EQ(0, animation_node->SpecifiedTiming().ActiveDuration());
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
@@ -492,7 +493,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationIteration) {
auto* animation_node = MakeGarbageCollected<TestAnimationEffect>(timing);
animation_node->UpdateInheritedTime(-1);
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
@@ -532,7 +533,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationIterationAlternate) {
auto* animation_node = MakeGarbageCollected<TestAnimationEffect>(timing);
animation_node->UpdateInheritedTime(-1);
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
@@ -552,7 +553,7 @@ TEST(AnimationAnimationEffectTest, ZeroDurationIterationAlternateReverse) {
auto* animation_node = MakeGarbageCollected<TestAnimationEffect>(timing);
animation_node->UpdateInheritedTime(-1);
- EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+ EXPECT_FALSE(animation_node->CurrentIteration());
EXPECT_FALSE(animation_node->Progress());
animation_node->UpdateInheritedTime(0);
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 98853f0555a..eeefe3f87e7 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test.cc
@@ -33,6 +33,7 @@
#include <memory>
#include "base/bits.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
#include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h"
@@ -45,6 +46,8 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.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"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -177,11 +180,15 @@ class AnimationAnimationTestNoCompositing : public RenderingTest {
}
void SimulateAwaitReady() {
+ animation->CommitAllUpdatesForTesting();
+
// TOOD(crbug/958433): This should trigger a call to the microtask for
// applying updates.
SimulateFrame(last_frame_time);
}
+ void SimulateMicrotask() { animation->CommitAllUpdatesForTesting(); }
+
Persistent<DocumentTimeline> timeline;
Persistent<Animation> animation;
@@ -620,11 +627,11 @@ TEST_F(AnimationAnimationTestNoCompositing, Finish) {
TEST_F(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
NonThrowableExceptionState exception_state;
+ // OK to set current time out of bounds.
animation->setCurrentTime(40000, false);
animation->finish(exception_state);
- // TODO(crbug/958433): This is not to spec. Finish should trigger a snap to
- // the upper boundary.
- EXPECT_EQ(40000, animation->currentTime());
+ // The finish method triggers a snap to the upper boundary.
+ EXPECT_EQ(30000, animation->currentTime());
}
TEST_F(AnimationAnimationTestNoCompositing, FinishBeforeStart) {
@@ -1349,4 +1356,122 @@ TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
EXPECT_FALSE(is_null);
}
+TEST_F(AnimationAnimationTestNoCompositing,
+ RemoveCanceledAnimationFromActiveSet) {
+ EXPECT_EQ("running", animation->playState());
+ EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
+ SimulateFrame(1000);
+ EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
+ animation->cancel();
+ EXPECT_EQ("idle", animation->playState());
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+}
+
+TEST_F(AnimationAnimationTestNoCompositing,
+ RemoveFinishedAnimationFromActiveSet) {
+ EXPECT_EQ("running", animation->playState());
+ EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
+ SimulateFrame(1000);
+ EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
+
+ // Synchronous completion.
+ animation->finish();
+ EXPECT_EQ("finished", animation->playState());
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+
+ // Play creates a new pending finished promise.
+ animation->play();
+ EXPECT_EQ("running", animation->playState());
+ EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
+
+ // Asynchronous completion.
+ animation->setCurrentTime(50000, false);
+ EXPECT_EQ("finished", animation->playState());
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+}
+
+TEST_F(AnimationAnimationTestNoCompositing,
+ PendingActivityWithFinishedPromise) {
+ // No pending activity even when running if there is no finished promise
+ // or event listener.
+ EXPECT_EQ("running", animation->playState());
+ SimulateFrame(1000);
+ EXPECT_FALSE(animation->HasPendingActivity());
+
+ // An unresolved finished promise indicates pending activity.
+ ScriptState* script_state =
+ ToScriptStateForMainWorld(GetDocument().GetFrame());
+ animation->finished(script_state);
+ EXPECT_TRUE(animation->HasPendingActivity());
+
+ // Resolving the finished promise clears the pending activity.
+ animation->setCurrentTime(50000, false);
+ EXPECT_EQ("finished", animation->playState());
+ SimulateMicrotask();
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+ EXPECT_FALSE(animation->HasPendingActivity());
+
+ // Playing an already finished animation creates a new pending finished
+ // promise.
+ animation->play();
+ EXPECT_EQ("running", animation->playState());
+ SimulateFrame(2000);
+ EXPECT_TRUE(animation->HasPendingActivity());
+ // Cancel rejects the finished promise and creates a new pending finished
+ // promise.
+ // TODO(crbug.com/960944): Investigate if this should return false to prevent
+ // holding onto the animation indefinitely.
+ animation->cancel();
+ EXPECT_TRUE(animation->HasPendingActivity());
+}
+
+class MockEventListener final : public NativeEventListener {
+ public:
+ MOCK_METHOD2(Invoke, void(ExecutionContext*, Event*));
+};
+
+TEST_F(AnimationAnimationTestNoCompositing,
+ PendingActivityWithFinishedEventListener) {
+ EXPECT_EQ("running", animation->playState());
+ EXPECT_FALSE(animation->HasPendingActivity());
+
+ // Attaching a listener for the finished event indicates pending activity.
+ Persistent<MockEventListener> event_listener =
+ MakeGarbageCollected<MockEventListener>();
+ animation->addEventListener(event_type_names::kFinish, event_listener);
+ EXPECT_TRUE(animation->HasPendingActivity());
+
+ // Synchronous finish clears pending activity.
+ animation->finish();
+ EXPECT_EQ("finished", animation->playState());
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+ EXPECT_TRUE(animation->HasPendingActivity());
+ animation->pending_finished_event_ = nullptr;
+ EXPECT_FALSE(animation->HasPendingActivity());
+
+ // Playing an already finished animation resets the finished state.
+ animation->play();
+ EXPECT_EQ("running", animation->playState());
+ SimulateFrame(2000);
+ EXPECT_TRUE(animation->HasPendingActivity());
+
+ // Finishing the animation asynchronously clears the pending activity.
+ animation->setCurrentTime(50000, false);
+ EXPECT_EQ("finished", animation->playState());
+ SimulateMicrotask();
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+ EXPECT_TRUE(animation->HasPendingActivity());
+ animation->pending_finished_event_ = nullptr;
+ EXPECT_FALSE(animation->HasPendingActivity());
+
+ // Canceling an animation clears the pending activity.
+ animation->play();
+ EXPECT_EQ("running", animation->playState());
+ SimulateFrame(2000);
+ animation->cancel();
+ EXPECT_EQ("idle", animation->playState());
+ EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
+ EXPECT_FALSE(animation->HasPendingActivity());
+}
+
} // 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 157fda29f8a..b1af4e69a8e 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
@@ -6,6 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_TIME_DELTA_H_
#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/compositor_animations.cc b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
index a3f55f18541..ac49e123869 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -267,6 +267,12 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
if (keyframe_value) {
DCHECK(RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled());
DCHECK(keyframe_value->IsDouble() || keyframe_value->IsColor());
+ // If a custom property is not used by CSS Paint, then we should not
+ // support that on the compositor thread.
+ if (!layout_object->Style()->HasCSSPaintImagesUsingCustomProperty(
+ property.CustomPropertyName(),
+ layout_object->GetDocument()))
+ reasons |= kUnsupportedCSSProperty;
// TODO: Add support for keyframes containing different types
if (keyframes.front()->GetCompositorKeyframeValue()->GetType() !=
keyframe_value->GetType()) {
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 74916876bf7..af5cd935325 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
@@ -47,7 +47,11 @@
#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/css/css_custom_ident_value.h"
+#include "third_party/blink/renderer/core/css/css_paint_value.h"
+#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/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"
@@ -58,6 +62,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/filter_operations.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/animation/compositor_color_animation_curve.h"
@@ -77,8 +82,27 @@
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
#include "third_party/skia/include/core/SkColor.h"
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+using testing::ReturnRef;
+using testing::Values;
+
namespace blink {
+namespace {
+// CSSPaintImageGenerator requires that CSSPaintImageGeneratorCreateFunction be
+// a static method. As such, it cannot access a class member and so instead we
+// store a pointer to the overriding generator globally.
+MockCSSPaintImageGenerator* g_override_generator = nullptr;
+CSSPaintImageGenerator* ProvideOverrideGenerator(
+ const String&,
+ const Document&,
+ CSSPaintImageGenerator::Observer*) {
+ return g_override_generator;
+}
+} // namespace
+
using namespace css_test_helpers;
class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
@@ -588,9 +612,11 @@ TEST_P(AnimationCompositorAnimationsTest,
RegisterProperty(GetDocument(), "--foo", "<number>", "0", false);
RegisterProperty(GetDocument(), "--bar", "<length>", "10px", false);
RegisterProperty(GetDocument(), "--loo", "<color>", "rgb(0, 0, 0)", false);
+ RegisterProperty(GetDocument(), "--x", "<number>", "0", false);
SetCustomProperty("--foo", "10");
SetCustomProperty("--bar", "10px");
SetCustomProperty("--loo", "rgb(0, 255, 0)");
+ SetCustomProperty("--x", "5");
auto style = GetDocument().EnsureStyleResolver().StyleForElement(element_);
EXPECT_TRUE(style->NonInheritedVariables());
@@ -603,7 +629,41 @@ TEST_P(AnimationCompositorAnimationsTest,
EXPECT_TRUE(style->NonInheritedVariables()
->GetData(AtomicString("--loo"))
.value_or(nullptr));
+ EXPECT_TRUE(style->NonInheritedVariables()
+ ->GetData(AtomicString("--x"))
+ .value_or(nullptr));
+ NiceMock<MockCSSPaintImageGenerator>* mock_generator =
+ MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
+ base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
+ &g_override_generator, mock_generator);
+ base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
+ scoped_create_function(
+ CSSPaintImageGenerator::GetCreateFunctionForTesting(),
+ ProvideOverrideGenerator);
+
+ mock_generator->AddCustomProperty("--foo");
+ mock_generator->AddCustomProperty("--bar");
+ mock_generator->AddCustomProperty("--loo");
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("foopainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+ paint_value->CreateGeneratorForTesting(GetDocument());
+ StyleGeneratedImage* style_image =
+ MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
+ style->AddPaintImage(style_image);
+ element_->GetLayoutObject()->SetStyle(style);
+ // The image is added for testing off-thread paint worklet supporting
+ // custom property animation case. The style doesn't have a real
+ // PaintImage, so we cannot call UpdateAllLifecyclePhasesForTest. But the
+ // PaintArtifactCompositor requires NeedsUpdate to be false.
+ // In the real world when a PaintImage does exist in the style, the life
+ // cycle will be updated automatically and we don't have to worry about
+ // this.
+ auto* paint_artifact_compositor =
+ GetDocument().View()->GetPaintArtifactCompositor();
+ paint_artifact_compositor->ClearNeedsUpdateForTesting();
+
+ ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
StringKeyframe* keyframe = CreateReplaceOpKeyframe("--foo", "10");
EXPECT_EQ(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe),
CompositorAnimations::kNoFailure);
@@ -625,6 +685,12 @@ TEST_P(AnimationCompositorAnimationsTest,
SetCustomProperty("opacity", "var(--foo)");
EXPECT_TRUE(DuplicateSingleKeyframeAndTestIsCandidateOnResult(keyframe) &
CompositorAnimations::kUnsupportedCSSProperty);
+
+ // Cannot composite because "--x" is not used by the paint worklet.
+ StringKeyframe* non_used_keyframe = CreateReplaceOpKeyframe("--x", "5");
+ EXPECT_EQ(
+ DuplicateSingleKeyframeAndTestIsCandidateOnResult(non_used_keyframe),
+ CompositorAnimations::kUnsupportedCSSProperty);
}
TEST_P(AnimationCompositorAnimationsTest,
diff --git a/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h b/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h
index 26bef21a63e..6823c1515e7 100644
--- a/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h
+++ b/chromium/third_party/blink/renderer/core/animation/css/compositor_keyframe_value.h
@@ -12,7 +12,7 @@
namespace blink {
class CORE_EXPORT CompositorKeyframeValue
- : public GarbageCollectedFinalized<CompositorKeyframeValue> {
+ : public GarbageCollected<CompositorKeyframeValue> {
public:
virtual ~CompositorKeyframeValue() = default;
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 ab7e1dd44b0..4ee0fa68df0 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
@@ -1121,9 +1121,10 @@ bool CSSAnimations::AnimationEventDelegate::RequiresIterationEvents(
}
void CSSAnimations::AnimationEventDelegate::OnEventCondition(
- const AnimationEffect& animation_node) {
- const Timing::Phase current_phase = animation_node.GetPhase();
- const double current_iteration = animation_node.CurrentIteration();
+ const AnimationEffect& animation_node,
+ Timing::Phase current_phase) {
+ const base::Optional<double> current_iteration =
+ animation_node.CurrentIteration();
if (previous_phase_ != current_phase &&
(current_phase == Timing::kPhaseActive ||
@@ -1143,9 +1144,10 @@ void CSSAnimations::AnimationEventDelegate::OnEventCondition(
// between a single pair of samples. See http://crbug.com/275263. For
// compatibility with the existing implementation, this event uses
// the elapsedTime for the first iteration in question.
+ DCHECK(previous_iteration_);
const AnimationTimeDelta elapsed_time =
animation_node.SpecifiedTiming().iteration_duration.value() *
- (previous_iteration_ + 1);
+ (previous_iteration_.value() + 1);
MaybeDispatch(Document::kAnimationIterationListener,
event_type_names::kAnimationiteration,
elapsed_time.InSecondsF());
@@ -1172,8 +1174,8 @@ EventTarget* CSSAnimations::TransitionEventDelegate::GetEventTarget() const {
}
void CSSAnimations::TransitionEventDelegate::OnEventCondition(
- const AnimationEffect& animation_node) {
- const Timing::Phase current_phase = animation_node.GetPhase();
+ const AnimationEffect& animation_node,
+ Timing::Phase current_phase) {
if (current_phase == previous_phase_)
return;
@@ -1228,11 +1230,18 @@ void CSSAnimations::TransitionEventDelegate::OnEventCondition(
// Per the css-transitions-2 spec, transitioncancel is fired with the
// "active time of the animation at the moment it was cancelled,
// calculated using a fill mode of both".
- double cancel_active_time = CalculateActiveTime(
- animation_node.SpecifiedTiming().ActiveDuration(),
- Timing::FillMode::BOTH, animation_node.LocalTime(), previous_phase_,
- animation_node.SpecifiedTiming());
- EnqueueEvent(event_type_names::kTransitioncancel, cancel_active_time);
+ base::Optional<AnimationTimeDelta> cancel_active_time =
+ CalculateActiveTime(animation_node.SpecifiedTiming().ActiveDuration(),
+ Timing::FillMode::BOTH,
+ animation_node.LocalTime(), previous_phase_,
+ animation_node.SpecifiedTiming());
+ // 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
+ // current_phase != previous_phase_ (see early return at the beginning).
+ DCHECK(cancel_active_time);
+ EnqueueEvent(event_type_names::kTransitioncancel,
+ cancel_active_time->InSecondsF());
}
}
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 38a535c08ec..f64a4001811 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
@@ -102,8 +102,7 @@ class CORE_EXPORT CSSAnimations final {
void Trace(blink::Visitor*);
private:
- class RunningAnimation final
- : public GarbageCollectedFinalized<RunningAnimation> {
+ class RunningAnimation final : public GarbageCollected<RunningAnimation> {
public:
RunningAnimation(Animation* animation, NewCSSAnimation new_animation)
: animation(animation),
@@ -202,10 +201,9 @@ class CORE_EXPORT CSSAnimations final {
AnimationEventDelegate(Element* animation_target, const AtomicString& name)
: animation_target_(animation_target),
name_(name),
- previous_phase_(Timing::kPhaseNone),
- previous_iteration_(NullValue()) {}
+ previous_phase_(Timing::kPhaseNone) {}
bool RequiresIterationEvents(const AnimationEffect&) override;
- void OnEventCondition(const AnimationEffect&) override;
+ void OnEventCondition(const AnimationEffect&, Timing::Phase) override;
void Trace(blink::Visitor*) override;
private:
@@ -219,7 +217,7 @@ class CORE_EXPORT CSSAnimations final {
Member<Element> animation_target_;
const AtomicString name_;
Timing::Phase previous_phase_;
- double previous_iteration_;
+ base::Optional<double> previous_iteration_;
};
class TransitionEventDelegate final : public AnimationEffect::EventDelegate {
@@ -232,7 +230,7 @@ class CORE_EXPORT CSSAnimations final {
bool RequiresIterationEvents(const AnimationEffect&) override {
return false;
}
- void OnEventCondition(const AnimationEffect&) override;
+ void OnEventCondition(const AnimationEffect&, Timing::Phase) override;
void Trace(blink::Visitor*) override;
private:
diff --git a/chromium/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
index fa454ddd14e..fb5cbf71cc1 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
@@ -365,6 +365,8 @@ void CSSBorderImageLengthBoxInterpolationType::Composite(
ListInterpolationFunctions::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
WTF::BindRepeating(NonInterpolableSidesAreCompatible),
WTF::BindRepeating(CompositeSide));
}
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 86b713ad36e..1a787a8f962 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
@@ -127,6 +127,8 @@ void CSSCustomListInterpolationType::Composite(
ListInterpolationFunctions::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
GetNonInterpolableValuesAreCompatibleCallback(),
WTF::BindRepeating(composite_callback,
WTF::Unretained(inner_interpolation_type_.get()),
diff --git a/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
index 4b8b02b0b17..1c8e68fa394 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.cc
@@ -8,7 +8,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/renderer/core/animation/filter_interpolation_functions.h"
+#include "third_party/blink/renderer/core/animation/interpolable_filter.h"
#include "third_party/blink/renderer/core/animation/list_interpolation_functions.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -52,28 +52,32 @@ void SetFilterList(const CSSProperty& property,
class UnderlyingFilterListChecker
: public CSSInterpolationType::CSSConversionChecker {
public:
- UnderlyingFilterListChecker(
- scoped_refptr<const NonInterpolableList> non_interpolable_list)
- : non_interpolable_list_(std::move(non_interpolable_list)) {}
+ UnderlyingFilterListChecker(const InterpolableList* interpolable_list) {
+ wtf_size_t length = interpolable_list->length();
+ types_.ReserveInitialCapacity(length);
+ for (wtf_size_t i = 0; i < length; i++) {
+ types_.push_back(
+ To<InterpolableFilter>(interpolable_list->Get(i))->GetType());
+ }
+ }
bool IsValid(const StyleResolverState&,
const InterpolationValue& underlying) const final {
- const NonInterpolableList& underlying_non_interpolable_list =
- ToNonInterpolableList(*underlying.non_interpolable_value);
- if (non_interpolable_list_->length() !=
- underlying_non_interpolable_list.length())
+ const InterpolableList& underlying_list =
+ ToInterpolableList(*underlying.interpolable_value);
+ if (underlying_list.length() != types_.size())
return false;
- for (wtf_size_t i = 0; i < non_interpolable_list_->length(); i++) {
- if (!filter_interpolation_functions::FiltersAreCompatible(
- *non_interpolable_list_->Get(i),
- *underlying_non_interpolable_list.Get(i)))
+ for (wtf_size_t i = 0; i < types_.size(); i++) {
+ FilterOperation::OperationType other_type =
+ To<InterpolableFilter>(underlying_list.Get(i))->GetType();
+ if (types_[i] != other_type)
return false;
}
return true;
}
private:
- scoped_refptr<const NonInterpolableList> non_interpolable_list_;
+ Vector<FilterOperation::OperationType> types_;
};
class InheritedFilterListChecker
@@ -101,35 +105,38 @@ InterpolationValue ConvertFilterList(const FilterOperations& filter_operations,
double zoom) {
wtf_size_t length = filter_operations.size();
auto interpolable_list = std::make_unique<InterpolableList>(length);
- Vector<scoped_refptr<const NonInterpolableValue>> non_interpolable_values(
- length);
for (wtf_size_t i = 0; i < length; i++) {
- InterpolationValue filter_result =
- filter_interpolation_functions::MaybeConvertFilter(
- *filter_operations.Operations()[i], zoom);
- if (!filter_result)
+ std::unique_ptr<InterpolableFilter> result =
+ InterpolableFilter::MaybeCreate(*filter_operations.Operations()[i],
+ zoom);
+ if (!result)
return nullptr;
- interpolable_list->Set(i, std::move(filter_result.interpolable_value));
- non_interpolable_values[i] =
- std::move(filter_result.non_interpolable_value);
+ interpolable_list->Set(i, std::move(result));
}
- return InterpolationValue(
- std::move(interpolable_list),
- NonInterpolableList::Create(std::move(non_interpolable_values)));
+ return InterpolationValue(std::move(interpolable_list));
}
+class AlwaysInvalidateChecker
+ : public CSSInterpolationType::CSSConversionChecker {
+ public:
+ bool IsValid(const StyleResolverState& state,
+ const InterpolationValue& underlying) const final {
+ return false;
+ }
+};
} // namespace
InterpolationValue CSSFilterListInterpolationType::MaybeConvertNeutral(
const InterpolationValue& underlying,
ConversionCheckers& conversion_checkers) const {
- // const_cast for taking refs.
- NonInterpolableList& non_interpolable_list = const_cast<NonInterpolableList&>(
- ToNonInterpolableList(*underlying.non_interpolable_value));
+ const InterpolableList* interpolable_list =
+ ToInterpolableList(underlying.interpolable_value.get());
conversion_checkers.push_back(
- std::make_unique<UnderlyingFilterListChecker>(&non_interpolable_list));
- return InterpolationValue(underlying.interpolable_value->CloneAndZero(),
- &non_interpolable_list);
+ std::make_unique<UnderlyingFilterListChecker>(interpolable_list));
+ // The neutral value for composition for a filter list is the empty list, as
+ // the additive operator is concatenation, so concat(underlying, []) ==
+ // underlying.
+ return InterpolationValue(std::make_unique<InterpolableList>(0));
}
InterpolationValue CSSFilterListInterpolationType::MaybeConvertInitial(
@@ -156,8 +163,7 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertValue(
ConversionCheckers&) const {
auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
if (identifier_value && identifier_value->GetValueID() == CSSValueID::kNone)
- return InterpolationValue(std::make_unique<InterpolableList>(0),
- NonInterpolableList::Create());
+ return InterpolationValue(std::make_unique<InterpolableList>(0));
if (!value.IsBaseValueList())
return nullptr;
@@ -165,19 +171,14 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertValue(
const auto& list = To<CSSValueList>(value);
wtf_size_t length = list.length();
auto interpolable_list = std::make_unique<InterpolableList>(length);
- Vector<scoped_refptr<const NonInterpolableValue>> non_interpolable_values(
- length);
for (wtf_size_t i = 0; i < length; i++) {
- InterpolationValue item_result =
- filter_interpolation_functions::MaybeConvertCSSFilter(list.Item(i));
- if (!item_result)
+ std::unique_ptr<InterpolableFilter> result =
+ InterpolableFilter::MaybeConvertCSSValue(list.Item(i));
+ if (!result)
return nullptr;
- interpolable_list->Set(i, std::move(item_result.interpolable_value));
- non_interpolable_values[i] = std::move(item_result.non_interpolable_value);
+ interpolable_list->Set(i, std::move(result));
}
- return InterpolationValue(
- std::move(interpolable_list),
- NonInterpolableList::Create(std::move(non_interpolable_values)));
+ return InterpolationValue(std::move(interpolable_list));
}
InterpolationValue
@@ -190,38 +191,35 @@ CSSFilterListInterpolationType::MaybeConvertStandardPropertyUnderlyingValue(
PairwiseInterpolationValue CSSFilterListInterpolationType::MaybeMergeSingles(
InterpolationValue&& start,
InterpolationValue&& end) const {
- const NonInterpolableList& start_non_interpolable_list =
- ToNonInterpolableList(*start.non_interpolable_value);
- const NonInterpolableList& end_non_interpolable_list =
- ToNonInterpolableList(*end.non_interpolable_value);
- wtf_size_t start_length = start_non_interpolable_list.length();
- wtf_size_t end_length = end_non_interpolable_list.length();
+ InterpolableList& start_interpolable_list =
+ ToInterpolableList(*start.interpolable_value);
+ InterpolableList& end_interpolable_list =
+ ToInterpolableList(*end.interpolable_value);
+ wtf_size_t start_length = start_interpolable_list.length();
+ wtf_size_t end_length = end_interpolable_list.length();
for (wtf_size_t i = 0; i < start_length && i < end_length; i++) {
- if (!filter_interpolation_functions::FiltersAreCompatible(
- *start_non_interpolable_list.Get(i),
- *end_non_interpolable_list.Get(i)))
+ if (To<InterpolableFilter>(start_interpolable_list.Get(i))->GetType() !=
+ To<InterpolableFilter>(end_interpolable_list.Get(i))->GetType())
return nullptr;
}
if (start_length == end_length) {
return PairwiseInterpolationValue(std::move(start.interpolable_value),
- std::move(end.interpolable_value),
- std::move(start.non_interpolable_value));
+ std::move(end.interpolable_value));
}
// Extend the shorter InterpolableList with neutral values that are compatible
// with corresponding filters in the longer list.
InterpolationValue& shorter = start_length < end_length ? start : end;
- InterpolationValue& longer = start_length < end_length ? end : start;
- wtf_size_t shorter_length =
- ToNonInterpolableList(*shorter.non_interpolable_value).length();
- wtf_size_t longer_length =
- ToNonInterpolableList(*longer.non_interpolable_value).length();
- InterpolableList& shorter_interpolable_list =
- ToInterpolableList(*shorter.interpolable_value);
- const NonInterpolableList& longer_non_interpolable_list =
- ToNonInterpolableList(*longer.non_interpolable_value);
+ wtf_size_t shorter_length = std::min(start_length, end_length);
+ wtf_size_t longer_length = std::max(start_length, end_length);
+ InterpolableList& shorter_interpolable_list = start_length < end_length
+ ? start_interpolable_list
+ : end_interpolable_list;
+ const InterpolableList& longer_interpolable_list =
+ start_length < end_length ? end_interpolable_list
+ : start_interpolable_list;
auto extended_interpolable_list =
std::make_unique<InterpolableList>(longer_length);
for (wtf_size_t i = 0; i < longer_length; i++) {
@@ -230,14 +228,14 @@ PairwiseInterpolationValue CSSFilterListInterpolationType::MaybeMergeSingles(
i, std::move(shorter_interpolable_list.GetMutable(i)));
else
extended_interpolable_list->Set(
- i, filter_interpolation_functions::CreateNoneValue(
- *longer_non_interpolable_list.Get(i)));
+ i, InterpolableFilter::CreateInitialValue(
+ To<InterpolableFilter>(longer_interpolable_list.Get(i))
+ ->GetType()));
}
shorter.interpolable_value = std::move(extended_interpolable_list);
return PairwiseInterpolationValue(std::move(start.interpolable_value),
- std::move(end.interpolable_value),
- std::move(longer.non_interpolable_value));
+ std::move(end.interpolable_value));
}
void CSSFilterListInterpolationType::Composite(
@@ -245,49 +243,9 @@ void CSSFilterListInterpolationType::Composite(
double underlying_fraction,
const InterpolationValue& value,
double interpolation_fraction) const {
- const NonInterpolableList& underlying_non_interpolable_list =
- ToNonInterpolableList(
- *underlying_value_owner.Value().non_interpolable_value);
- const NonInterpolableList& non_interpolable_list =
- ToNonInterpolableList(*value.non_interpolable_value);
- wtf_size_t underlying_length = underlying_non_interpolable_list.length();
- wtf_size_t length = non_interpolable_list.length();
-
- for (wtf_size_t i = 0; i < underlying_length && i < length; i++) {
- if (!filter_interpolation_functions::FiltersAreCompatible(
- *underlying_non_interpolable_list.Get(i),
- *non_interpolable_list.Get(i))) {
- underlying_value_owner.Set(*this, value);
- return;
- }
- }
-
- InterpolableList& underlying_interpolable_list = ToInterpolableList(
- *underlying_value_owner.MutableValue().interpolable_value);
- const InterpolableList& interpolable_list =
- ToInterpolableList(*value.interpolable_value);
- DCHECK_EQ(underlying_length, underlying_interpolable_list.length());
- DCHECK_EQ(length, interpolable_list.length());
-
- for (wtf_size_t i = 0; i < length && i < underlying_length; i++)
- underlying_interpolable_list.GetMutable(i)->ScaleAndAdd(
- underlying_fraction, *interpolable_list.Get(i));
-
- if (length <= underlying_length)
- return;
-
- auto extended_interpolable_list = std::make_unique<InterpolableList>(length);
- for (wtf_size_t i = 0; i < length; i++) {
- if (i < underlying_length)
- extended_interpolable_list->Set(
- i, std::move(underlying_interpolable_list.GetMutable(i)));
- else
- extended_interpolable_list->Set(i, interpolable_list.Get(i)->Clone());
- }
- underlying_value_owner.MutableValue().interpolable_value =
- std::move(extended_interpolable_list);
- underlying_value_owner.MutableValue().non_interpolable_value =
- value.non_interpolable_value;
+ // We do our compositing behavior in |PreInterpolationCompositeIfNeeded|; see
+ // the documentation on that method.
+ underlying_value_owner.Set(*this, value);
}
void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
@@ -296,19 +254,105 @@ void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
StyleResolverState& state) const {
const InterpolableList& interpolable_list =
ToInterpolableList(interpolable_value);
- const NonInterpolableList& non_interpolable_list =
- ToNonInterpolableList(*non_interpolable_value);
wtf_size_t length = interpolable_list.length();
- DCHECK_EQ(length, non_interpolable_list.length());
FilterOperations filter_operations;
filter_operations.Operations().ReserveCapacity(length);
for (wtf_size_t i = 0; i < length; i++) {
filter_operations.Operations().push_back(
- filter_interpolation_functions::CreateFilter(
- *interpolable_list.Get(i), *non_interpolable_list.Get(i), state));
+ To<InterpolableFilter>(interpolable_list.Get(i))
+ ->CreateFilterOperation(state));
}
SetFilterList(CssProperty(), *state.Style(), std::move(filter_operations));
}
+InterpolationValue
+CSSFilterListInterpolationType::PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation composite,
+ ConversionCheckers& conversion_checkers) const {
+ DCHECK(!value.non_interpolable_value);
+ DCHECK(!underlying.non_interpolable_value);
+
+ // Due to the post-interpolation composite optimization, the interpolation
+ // stack aggressively caches interpolated values. When we are doing
+ // pre-interpolation compositing, this can cause us to bake-in the composited
+ // result even when the underlying value is changing. This checker is a hack
+ // to disable that caching in this case.
+ // TODO(crbug.com/1009230): Remove this once our interpolation code isn't
+ // caching composited values.
+ conversion_checkers.push_back(std::make_unique<AlwaysInvalidateChecker>());
+
+ // The underlying value can be nullptr, most commonly if it contains a url().
+ // TODO(crbug.com/1009229): Properly handle url() in filter composite.
+ if (!underlying.interpolable_value)
+ return nullptr;
+
+ auto interpolable_list = std::unique_ptr<InterpolableList>(
+ ToInterpolableList(value.interpolable_value.release()));
+ const InterpolableList& underlying_list =
+ ToInterpolableList(*underlying.interpolable_value);
+
+ if (composite == EffectModel::CompositeOperation::kCompositeAdd) {
+ return PerformAdditiveComposition(std::move(interpolable_list),
+ underlying_list);
+ }
+ DCHECK_EQ(composite, EffectModel::CompositeOperation::kCompositeAccumulate);
+ return PerformAccumulativeComposition(std::move(interpolable_list),
+ underlying_list);
+}
+
+InterpolationValue CSSFilterListInterpolationType::PerformAdditiveComposition(
+ std::unique_ptr<InterpolableList> interpolable_list,
+ const InterpolableList& underlying_list) const {
+ // Per the spec, addition of filter lists is defined as concatenation.
+ // https://drafts.fxtf.org/filter-effects-1/#addition
+ auto composited_list = std::make_unique<InterpolableList>(
+ underlying_list.length() + interpolable_list->length());
+ for (wtf_size_t i = 0; i < composited_list->length(); i++) {
+ if (i < underlying_list.length()) {
+ composited_list->Set(i, underlying_list.Get(i)->Clone());
+ } else {
+ composited_list->Set(
+ i, interpolable_list->Get(i - underlying_list.length())->Clone());
+ }
+ }
+ return InterpolationValue(std::move(composited_list));
+}
+
+InterpolationValue
+CSSFilterListInterpolationType::PerformAccumulativeComposition(
+ std::unique_ptr<InterpolableList> interpolable_list,
+ const InterpolableList& underlying_list) const {
+ // Per the spec, accumulation of filter lists operates on pairwise addition of
+ // the underlying components.
+ // https://drafts.fxtf.org/filter-effects-1/#accumulation
+ wtf_size_t length = interpolable_list->length();
+ wtf_size_t underlying_length = underlying_list.length();
+
+ // If any of the types don't match, fallback to replace behavior.
+ for (wtf_size_t i = 0; i < underlying_length && i < length; i++) {
+ if (To<InterpolableFilter>(underlying_list.Get(i))->GetType() !=
+ To<InterpolableFilter>(interpolable_list->Get(i))->GetType())
+ return InterpolationValue(std::move(interpolable_list));
+ }
+
+ // Otherwise, arithmetically combine the matching prefix of the lists then
+ // concatenate the remainder of the longer one.
+ wtf_size_t max_length = std::max(length, underlying_length);
+ auto composited_list = std::make_unique<InterpolableList>(max_length);
+ for (wtf_size_t i = 0; i < max_length; i++) {
+ if (i < underlying_length) {
+ composited_list->Set(i, underlying_list.Get(i)->Clone());
+ if (i < length)
+ composited_list->GetMutable(i)->Add(*interpolable_list->Get(i));
+ } else {
+ composited_list->Set(i, interpolable_list->Get(i)->Clone());
+ }
+ }
+
+ return InterpolationValue(std::move(composited_list));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h
index 8fac1a73794..5b01268a653 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h
@@ -26,6 +26,11 @@ class CSSFilterListInterpolationType : public CSSInterpolationType {
void ApplyStandardPropertyValue(const InterpolableValue&,
const NonInterpolableValue*,
StyleResolverState&) const final;
+ InterpolationValue PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const final;
private:
InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying,
@@ -37,6 +42,16 @@ class CSSFilterListInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*,
ConversionCheckers&) const final;
+
+ // Helper methods to perform either additive or accumulative composition, as
+ // defined in https://drafts.fxtf.org/filter-effects-1/#addition and
+ // https://drafts.fxtf.org/filter-effects-1/#accumulation
+ InterpolationValue PerformAdditiveComposition(
+ std::unique_ptr<InterpolableList> interpolable_list,
+ const InterpolableList& underlying_list) const;
+ InterpolationValue PerformAccumulativeComposition(
+ std::unique_ptr<InterpolableList> interpolable_list,
+ const InterpolableList& underlying_list) const;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc
index 3893bf8b295..5cde658ee51 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
@@ -141,7 +141,9 @@ InterpolationValue CSSInterpolationType::MaybeConvertSingle(
keyframe, environment, underlying, conversion_checkers);
if (result && keyframe.Composite() !=
EffectModel::CompositeOperation::kCompositeReplace) {
- return MakeAdditive(std::move(result));
+ return PreInterpolationCompositeIfNeeded(std::move(result), underlying,
+ keyframe.Composite(),
+ conversion_checkers);
}
return result;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.h
index 0c84cded9d4..f829d118286 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_interpolation_type.h
@@ -63,7 +63,19 @@ class CORE_EXPORT CSSInterpolationType : public InterpolationType {
const InterpolationValue& underlying,
ConversionCheckers&) const final;
- virtual InterpolationValue MakeAdditive(InterpolationValue value) const {
+ // The interpolation stack has an optimization where we perform compositing
+ // after interpolation. This is against spec, but it works for simple addition
+ // cases and halves the amount of computation needed. Some types require
+ // compositing before interpolation (e.g. if their composition operator is a
+ // concatenation), however, and for those we define this method that is called
+ // pre-interpolation.
+ // TODO(crbug.com/1009230): Revisit the post-interpolation composite
+ // optimization.
+ virtual InterpolationValue PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const {
return value;
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
index 17b67ec7842..dd06b170d99 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/animation/css_angle_interpolation_type.h"
#include "third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.h"
#include "third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/css_length_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_length_interpolation_type.cc
index 7c6c05dd557..93b6a9206a9 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_length_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_length_interpolation_type.cc
@@ -150,9 +150,14 @@ void CSSLengthInterpolationType::ApplyStandardPropertyValue(
DCHECK(LengthPropertyFunctions::GetLength(CssProperty(), style, after));
DCHECK(before.IsSpecified());
DCHECK(after.IsSpecified());
- const float kSlack = 0.1;
- float delta =
- FloatValueForLength(after, 100) - FloatValueForLength(before, 100);
+ const float kSlack = 1e-6;
+ const float before_length = FloatValueForLength(before, 100);
+ const float after_length = FloatValueForLength(after, 100);
+ // Test relative difference for large values to avoid floating point
+ // inaccuracies tripping the check.
+ const float delta = std::abs(before_length) < kSlack
+ ? after_length - before_length
+ : (after_length - before_length) / before_length;
DCHECK_LT(std::abs(delta), kSlack);
#endif
return;
diff --git a/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
index f26a25a2554..07864c91aa4 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_length_list_interpolation_type.cc
@@ -148,6 +148,8 @@ void CSSLengthListInterpolationType::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple,
WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
+ WTF::BindRepeating(
ListInterpolationFunctions::VerifyNoNonInterpolableValues),
WTF::BindRepeating([](UnderlyingValue& underlying_value,
double underlying_fraction,
diff --git a/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc
index cd0c029f961..cf28f051802 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc
@@ -212,8 +212,12 @@ InterpolationValue CSSRotateInterpolationType::MaybeConvertValue(
OptionalRotation(StyleBuilderConverter::ConvertRotation(value)));
}
-InterpolationValue CSSRotateInterpolationType::MakeAdditive(
- InterpolationValue value) const {
+InterpolationValue
+CSSRotateInterpolationType::PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const {
value.non_interpolable_value = CSSRotateNonInterpolableValue::CreateAdditive(
ToCSSRotateNonInterpolableValue(*value.non_interpolable_value));
return value;
diff --git a/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.h
index 16096fcc94c..818377df8ba 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.h
@@ -39,7 +39,11 @@ class CSSRotateInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*,
ConversionCheckers&) const final;
- InterpolationValue MakeAdditive(InterpolationValue) const final;
+ InterpolationValue PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
index 1efebb67155..3efeb2bc6b0 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
@@ -193,8 +193,11 @@ InterpolationValue CSSScaleInterpolationType::MaybeConvertValue(
}
}
-InterpolationValue CSSScaleInterpolationType::MakeAdditive(
- InterpolationValue value) const {
+InterpolationValue CSSScaleInterpolationType::PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const {
value.non_interpolable_value = CSSScaleNonInterpolableValue::CreateAdditive(
ToCSSScaleNonInterpolableValue(*value.non_interpolable_value));
return value;
diff --git a/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.h
index c570dd16c46..1d365713a71 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_scale_interpolation_type.h
@@ -36,7 +36,11 @@ class CSSScaleInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*,
ConversionCheckers&) const final;
- InterpolationValue MakeAdditive(InterpolationValue) const final;
+ InterpolationValue PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const final;
PairwiseInterpolationValue MaybeMergeSingles(
InterpolationValue&&,
diff --git a/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
index 463cf6f643d..32e5a119674 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_shadow_list_interpolation_type.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/animation/interpolable_shadow.h"
#include "third_party/blink/renderer/core/animation/list_interpolation_functions.h"
-#include "third_party/blink/renderer/core/animation/shadow_interpolation_functions.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
@@ -44,8 +44,8 @@ InterpolationValue CSSShadowListInterpolationType::ConvertShadowList(
const ShadowDataVector& shadows = shadow_list->Shadows();
return ListInterpolationFunctions::CreateList(
shadows.size(), [&shadows, zoom](wtf_size_t index) {
- return ShadowInterpolationFunctions::ConvertShadowData(shadows[index],
- zoom);
+ return InterpolationValue(
+ InterpolableShadow::Create(shadows[index], zoom));
});
}
@@ -116,8 +116,8 @@ InterpolationValue CSSShadowListInterpolationType::MaybeConvertValue(
const auto& value_list = To<CSSValueList>(value);
return ListInterpolationFunctions::CreateList(
value_list.length(), [&value_list](wtf_size_t index) {
- return ShadowInterpolationFunctions::MaybeConvertCSSValue(
- value_list.Item(index));
+ return InterpolationValue(
+ InterpolableShadow::MaybeConvertCSSValue(value_list.Item(index)));
});
}
@@ -127,7 +127,12 @@ PairwiseInterpolationValue CSSShadowListInterpolationType::MaybeMergeSingles(
return ListInterpolationFunctions::MaybeMergeSingles(
std::move(start), std::move(end),
ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest,
- WTF::BindRepeating(ShadowInterpolationFunctions::MaybeMergeSingles));
+ WTF::BindRepeating(
+ [](InterpolationValue&& start_item, InterpolationValue&& end_item) {
+ return InterpolableShadow::MaybeMergeSingles(
+ std::move(start_item.interpolable_value),
+ std::move(end_item.interpolable_value));
+ }));
}
InterpolationValue
@@ -145,9 +150,10 @@ void CSSShadowListInterpolationType::Composite(
ListInterpolationFunctions::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest,
+ WTF::BindRepeating(InterpolableShadow::CompatibleForCompositing),
WTF::BindRepeating(
- ShadowInterpolationFunctions::NonInterpolableValuesAreCompatible),
- WTF::BindRepeating(ShadowInterpolationFunctions::Composite));
+ ListInterpolationFunctions::VerifyNoNonInterpolableValues),
+ WTF::BindRepeating(InterpolableShadow::Composite));
}
static scoped_refptr<ShadowList> CreateShadowList(
@@ -159,12 +165,11 @@ static scoped_refptr<ShadowList> CreateShadowList(
wtf_size_t length = interpolable_list.length();
if (length == 0)
return nullptr;
- const NonInterpolableList& non_interpolable_list =
- ToNonInterpolableList(*non_interpolable_value);
ShadowDataVector shadows;
- for (wtf_size_t i = 0; i < length; i++)
- shadows.push_back(ShadowInterpolationFunctions::CreateShadowData(
- *interpolable_list.Get(i), non_interpolable_list.Get(i), state));
+ for (wtf_size_t i = 0; i < length; i++) {
+ shadows.push_back(To<InterpolableShadow>(interpolable_list.Get(i))
+ ->CreateShadowData(state));
+ }
return ShadowList::Adopt(shadows);
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
index 181f65efd3c..7ae4e5109b0 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_size_list_interpolation_type.cc
@@ -165,6 +165,8 @@ void CSSSizeListInterpolationType::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kLowestCommonMultiple,
WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
+ WTF::BindRepeating(
SizeInterpolationFunctions::NonInterpolableValuesAreCompatible),
WTF::BindRepeating(SizeInterpolationFunctions::Composite));
}
diff --git a/chromium/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
index e2b28ddcd1d..05174e233ec 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_text_indent_interpolation_type.cc
@@ -67,53 +67,6 @@ class CSSTextIndentNonInterpolableValue : public NonInterpolableValue {
DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSTextIndentNonInterpolableValue);
DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSTextIndentNonInterpolableValue);
-// TODO(xiaochengh): Clean up. With |InterpolableLength| introduced and
-// |LengthNonInterpolableValue| removed, the following no longer makes sense.
-//
-// A wrapper for the UnderlyingValue passed to
-// CSSTextIndentInterpolationType::Composite which can be forwarded to
-// LengthInterpolationFunctions::Composite.
-//
-// If LengthInterpolationFunctions::Composite calls SetNonInterpolableValue with
-// a new NonInterpolableValue, this class wraps it in a new
-// CSSTextIndentNonInterpolableValue before being set on the inner
-// UnderlyingValue.
-class UnderlyingTextIndentAsLengthValue : public UnderlyingValue {
- STACK_ALLOCATED();
-
- public:
- UnderlyingTextIndentAsLengthValue(UnderlyingValue& inner_underlying_value,
- IndentMode mode)
- : inner_underlying_value_(inner_underlying_value), mode_(mode) {}
-
- InterpolableValue& MutableInterpolableValue() final {
- return inner_underlying_value_.MutableInterpolableValue();
- }
-
- void SetInterpolableValue(
- std::unique_ptr<InterpolableValue> interpolable_value) final {
- inner_underlying_value_.SetInterpolableValue(std::move(interpolable_value));
- }
-
- const NonInterpolableValue* GetNonInterpolableValue() const final {
- const auto& text_indent_non_interpolable_value =
- ToCSSTextIndentNonInterpolableValue(
- *inner_underlying_value_.GetNonInterpolableValue());
- return text_indent_non_interpolable_value.LengthNonInterpolableValue();
- }
-
- void SetNonInterpolableValue(
- scoped_refptr<const NonInterpolableValue> non_interpolable_value) final {
- inner_underlying_value_.SetNonInterpolableValue(
- CSSTextIndentNonInterpolableValue::Create(
- std::move(non_interpolable_value), mode_));
- }
-
- private:
- UnderlyingValue& inner_underlying_value_;
- const IndentMode mode_;
-};
-
namespace {
class UnderlyingIndentModeChecker
@@ -266,9 +219,7 @@ void CSSTextIndentInterpolationType::Composite(
return;
}
- UnderlyingTextIndentAsLengthValue underlying_text_indent_as_length(
- underlying_value_owner, mode);
- underlying_text_indent_as_length.MutableInterpolableValue().ScaleAndAdd(
+ underlying_value_owner.MutableInterpolableValue().ScaleAndAdd(
underlying_fraction, *value.interpolable_value);
}
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 a46ed6cbc32..986db9d9acc 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
@@ -8,6 +8,7 @@
#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"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -19,130 +20,10 @@
#include "third_party/blink/renderer/platform/transforms/translate_transform_operation.h"
namespace blink {
-
-class CSSTransformNonInterpolableValue : public NonInterpolableValue {
- public:
- static scoped_refptr<CSSTransformNonInterpolableValue> Create(
- TransformOperations&& transform) {
- const bool is_single = true;
- const bool is_additive = false;
- return base::AdoptRef(new CSSTransformNonInterpolableValue(
- is_single, std::move(transform), EmptyTransformOperations(),
- is_additive, is_additive));
- }
-
- static scoped_refptr<CSSTransformNonInterpolableValue> CreateAdditive(
- const CSSTransformNonInterpolableValue& other) {
- DCHECK(other.is_single_);
- const bool is_single = true;
- const bool is_additive = true;
- return base::AdoptRef(new CSSTransformNonInterpolableValue(
- is_single, TransformOperations(other.start_),
- TransformOperations(other.end_), is_additive, is_additive));
- }
-
- static scoped_refptr<CSSTransformNonInterpolableValue> Create(
- const CSSTransformNonInterpolableValue& start,
- double start_fraction,
- const CSSTransformNonInterpolableValue& end,
- double end_fraction) {
- return base::AdoptRef(new CSSTransformNonInterpolableValue(
- false, start.GetInterpolatedTransform(start_fraction),
- end.GetInterpolatedTransform(end_fraction), start.IsAdditive(),
- end.IsAdditive()));
- }
-
- scoped_refptr<CSSTransformNonInterpolableValue> Composite(
- const CSSTransformNonInterpolableValue& other,
- double other_progress) const {
- DCHECK(is_single_);
- DCHECK(!IsAdditive());
-
- // This is the case where we have no B, so the equation is U + A.
- if (other.is_single_) {
- DCHECK_EQ(other_progress, 0);
- DCHECK(other.IsAdditive());
- TransformOperations result;
- result.Operations() = Concat(Transform(), other.Transform());
- return Create(std::move(result));
- }
-
- // Otherwise, we must compute (U + A)(1 - f) + (U + B)f - where U is only
- // included if the keyframe is additive. This requires pre-pending the
- // underlying ops to the necessary sides and then performing the
- // interpolation.
- DCHECK(other.is_start_additive_ || other.is_end_additive_);
- TransformOperations start;
- start.Operations() = other.is_start_additive_
- ? Concat(Transform(), other.start_)
- : other.start_.Operations();
- TransformOperations end;
- end.Operations() = other.is_end_additive_ ? Concat(Transform(), other.end_)
- : other.end_.Operations();
- return Create(end.Blend(start, other_progress));
- }
-
- TransformOperations GetInterpolatedTransform(double progress) const {
- if (progress == 0)
- return start_;
- if (progress == 1)
- return end_;
- DCHECK(!IsAdditive());
- return end_.Blend(start_, progress);
- }
-
- bool IsSingle() const { return is_single_; }
-
- DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
-
- private:
- CSSTransformNonInterpolableValue(bool is_single,
- TransformOperations&& start,
- TransformOperations&& end,
- bool is_start_additive,
- bool is_end_additive)
- : is_single_(is_single),
- start_(std::move(start)),
- end_(std::move(end)),
- is_start_additive_(is_start_additive),
- is_end_additive_(is_end_additive) {}
-
- const TransformOperations& Transform() const {
- DCHECK(is_single_);
- return start_;
- }
- bool IsAdditive() const {
- bool result = is_start_additive_ || is_end_additive_;
- DCHECK(!result || is_single_);
- return result;
- }
-
- Vector<scoped_refptr<TransformOperation>> Concat(
- const TransformOperations& a,
- const TransformOperations& b) const {
- Vector<scoped_refptr<TransformOperation>> result;
- result.ReserveCapacity(a.size() + b.size());
- result.AppendVector(a.Operations());
- result.AppendVector(b.Operations());
- return result;
- }
-
- bool is_single_;
- TransformOperations start_;
- TransformOperations end_;
- bool is_start_additive_;
- bool is_end_additive_;
-};
-
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSTransformNonInterpolableValue);
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSTransformNonInterpolableValue);
-
namespace {
-
InterpolationValue ConvertTransform(TransformOperations&& transform) {
return InterpolationValue(
- std::make_unique<InterpolableNumber>(0),
- CSSTransformNonInterpolableValue::Create(std::move(transform)));
+ InterpolableTransformList::Create(std::move(transform)));
}
InterpolationValue ConvertTransform(const TransformOperations& transform) {
@@ -164,34 +45,14 @@ class InheritedTransformChecker
const TransformOperations inherited_transform_;
};
-// Performs interpolation for the UnderlyingValueOwner, if necessary. This
-// requires us to:
-//
-// i. Compute the interpolation for the CSSTransformNonInterpolableValue.
-// ii. Reset the underlying_value_owner's interpolable_value (which is the
-// progress) to 0. This is necessary to avoid double-interpolating in
-// ApplyStandardPropertyValue.
-void InterpolateUnderlyingValueOwnerIfNecessary(
- UnderlyingValueOwner& underlying_value_owner) {
- const CSSTransformNonInterpolableValue& underlying_non_interpolable_value =
- ToCSSTransformNonInterpolableValue(
- *underlying_value_owner.Value().non_interpolable_value);
- // If the UnderlyingValueOwner is already single, it is either based on the
- // underlying CSS style itself, or has already been interpolated.
- if (underlying_non_interpolable_value.IsSingle())
- return;
-
- double underlying_progress =
- ToInterpolableNumber(*underlying_value_owner.Value().interpolable_value)
- .Value();
- underlying_value_owner.SetInterpolableValue(
- std::make_unique<InterpolableNumber>(0));
- underlying_value_owner.SetNonInterpolableValue(
- CSSTransformNonInterpolableValue::Create(
- underlying_non_interpolable_value.GetInterpolatedTransform(
- underlying_progress)));
-}
-
+class AlwaysInvalidateChecker
+ : public CSSInterpolationType::CSSConversionChecker {
+ public:
+ bool IsValid(const StyleResolverState& state,
+ const InterpolationValue& underlying) const final {
+ return false;
+ }
+};
} // namespace
InterpolationValue CSSTransformInterpolationType::MaybeConvertNeutral(
@@ -232,8 +93,10 @@ InterpolationValue CSSTransformInterpolationType::MaybeConvertValue(
}
for (const CSSValue* argument : transform_function) {
const auto& primitive_value = To<CSSPrimitiveValue>(*argument);
- if (!primitive_value.IsLength())
+ if (!primitive_value.IsLength() &&
+ !primitive_value.IsCalculatedPercentageWithLength()) {
continue;
+ }
primitive_value.AccumulateLengthUnitTypes(types);
}
}
@@ -244,36 +107,37 @@ InterpolationValue CSSTransformInterpolationType::MaybeConvertValue(
conversion_checkers.push_back(std::move(length_units_checker));
}
- DCHECK(state);
- TransformOperations transform = TransformBuilder::CreateTransformOperations(
- value, state->CssToLengthConversionData());
- return ConvertTransform(std::move(transform));
+ return InterpolationValue(
+ InterpolableTransformList::ConvertCSSValue(value, state));
}
-InterpolationValue CSSTransformInterpolationType::MakeAdditive(
- InterpolationValue value) const {
- value.non_interpolable_value =
- CSSTransformNonInterpolableValue::CreateAdditive(
- ToCSSTransformNonInterpolableValue(*value.non_interpolable_value));
+InterpolationValue
+CSSTransformInterpolationType::PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers& conversion_checkers) const {
+ // Due to the post-interpolation composite optimization, the interpolation
+ // stack aggressively caches interpolated values. When we are doing
+ // pre-interpolation compositing, this can cause us to bake-in the composited
+ // result even when the underlying value is changing. This checker is a hack
+ // to disable that caching in this case.
+ // TODO(crbug.com/1009230): Remove this once our interpolation code isn't
+ // caching composited values.
+ conversion_checkers.push_back(std::make_unique<AlwaysInvalidateChecker>());
+
+ To<InterpolableTransformList>(*value.interpolable_value)
+ .PreConcat(To<InterpolableTransformList>(*underlying.interpolable_value));
return value;
}
PairwiseInterpolationValue CSSTransformInterpolationType::MaybeMergeSingles(
InterpolationValue&& start,
InterpolationValue&& end) const {
- double start_fraction =
- ToInterpolableNumber(*start.interpolable_value).Value();
- double end_fraction = ToInterpolableNumber(*end.interpolable_value).Value();
- return PairwiseInterpolationValue(
- std::make_unique<InterpolableNumber>(0),
- std::make_unique<InterpolableNumber>(1),
- CSSTransformNonInterpolableValue::Create(
- std::move(ToCSSTransformNonInterpolableValue(
- *start.non_interpolable_value)),
- start_fraction,
- std::move(
- ToCSSTransformNonInterpolableValue(*end.non_interpolable_value)),
- end_fraction));
+ // We don't do any checking here; InterpolableTransformList::Interpolate will
+ // handle discrete animation for us if needed.
+ return PairwiseInterpolationValue(std::move(start.interpolable_value),
+ std::move(end.interpolable_value));
}
InterpolationValue
@@ -287,34 +151,17 @@ void CSSTransformInterpolationType::Composite(
double underlying_fraction,
const InterpolationValue& value,
double interpolation_fraction) const {
- // If the first InvalidatableInterpolation in the stack doesn't depend on an
- // underlying value, it becomes the underlying value, U. However at this point
- // U has not yet been interpolated (as interpolation for
- // CSSTransformInterpolationType only happens in either Composite or
- // ApplyStandardPropertyValue), and so we have to do it here.
- InterpolateUnderlyingValueOwnerIfNecessary(underlying_value_owner);
-
- // Now that U has been resolved, do the actual compositing.
- const CSSTransformNonInterpolableValue& underlying_non_interpolable_value =
- ToCSSTransformNonInterpolableValue(
- *underlying_value_owner.GetNonInterpolableValue());
- const CSSTransformNonInterpolableValue& non_interpolable_value =
- ToCSSTransformNonInterpolableValue(*value.non_interpolable_value);
- double progress = ToInterpolableNumber(*value.interpolable_value).Value();
- underlying_value_owner.SetNonInterpolableValue(
- underlying_non_interpolable_value.Composite(non_interpolable_value,
- progress));
+ // We do our compositing behavior in |PreInterpolationCompositeIfNeeded|; see
+ // the documentation on that method.
+ underlying_value_owner.Set(*this, value);
}
void CSSTransformInterpolationType::ApplyStandardPropertyValue(
const InterpolableValue& interpolable_value,
const NonInterpolableValue* untyped_non_interpolable_value,
StyleResolverState& state) const {
- double progress = ToInterpolableNumber(interpolable_value).Value();
- const CSSTransformNonInterpolableValue& non_interpolable_value =
- ToCSSTransformNonInterpolableValue(*untyped_non_interpolable_value);
state.Style()->SetTransform(
- non_interpolable_value.GetInterpolatedTransform(progress));
+ To<InterpolableTransformList>(interpolable_value).operations());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.h b/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.h
index b2ec860801a..0ad909424c6 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.h
+++ b/chromium/third_party/blink/renderer/core/animation/css_transform_interpolation_type.h
@@ -39,7 +39,11 @@ class CSSTransformInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*,
ConversionCheckers&) const final;
- InterpolationValue MakeAdditive(InterpolationValue) const final;
+ InterpolationValue PreInterpolationCompositeIfNeeded(
+ InterpolationValue value,
+ const InterpolationValue& underlying,
+ EffectModel::CompositeOperation,
+ ConversionCheckers&) const final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/document_timeline.cc b/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
index 86c48d0927d..40615bd8e31 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
@@ -182,6 +182,9 @@ void DocumentTimeline::ServiceAnimations(TimingUpdateReason reason) {
for (const auto& animation : animations_needing_update_)
DCHECK(!animation->Outdated());
#endif
+ // Explicitly free the backing store to avoid memory regressions.
+ // TODO(bikineev): Revisit when young generation is done.
+ animations.clear();
}
void DocumentTimeline::ScheduleNextService() {
diff --git a/chromium/third_party/blink/renderer/core/animation/document_timeline.h b/chromium/third_party/blink/renderer/core/animation/document_timeline.h
index d14d5cb21da..4774bd79c6e 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.h
@@ -59,7 +59,7 @@ class CORE_EXPORT DocumentTimeline : public AnimationTimeline {
DEFINE_WRAPPERTYPEINFO();
public:
- class PlatformTiming : public GarbageCollectedFinalized<PlatformTiming> {
+ class PlatformTiming : public GarbageCollected<PlatformTiming> {
public:
// Calls DocumentTimeline's wake() method after duration seconds.
virtual void WakeAfter(base::TimeDelta duration) = 0;
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 fc0b9127d56..50bdcf344c6 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_input.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_input.cc
@@ -180,8 +180,10 @@ bool ValidatePartialKeyframes(const StringKeyframeVector& keyframes) {
EffectModel::CompositeOperation ResolveCompositeOperationForKeyframe(
EffectModel::CompositeOperation composite,
StringKeyframe* keyframe) {
+ bool additive_composite = composite == EffectModel::kCompositeAdd ||
+ composite == EffectModel::kCompositeAccumulate;
if (!RuntimeEnabledFeatures::CSSAdditiveAnimationsEnabled() &&
- keyframe->HasCssProperty() && composite == EffectModel::kCompositeAdd) {
+ keyframe->HasCssProperty() && additive_composite) {
return EffectModel::kCompositeReplace;
}
return composite;
@@ -226,8 +228,8 @@ void AddPropertyValuePairsForKeyframe(
v8::TryCatch try_catch(isolate);
for (const auto& property : keyframe_properties) {
- if (property == "offset" || property == "composite" ||
- property == "easing") {
+ if (property == "offset" || property == "float" ||
+ property == "composite" || property == "easing") {
continue;
}
@@ -488,8 +490,8 @@ StringKeyframeVector ConvertObjectForm(Element* element,
WTF::CodeUnitCompareLessThan);
for (const auto& property : keyframe_properties) {
- if (property == "offset" || property == "composite" ||
- property == "easing") {
+ if (property == "offset" || property == "float" ||
+ property == "composite" || property == "easing") {
continue;
}
@@ -642,8 +644,10 @@ bool HasAdditiveCompositeCSSKeyframe(
if (!property.IsCSSProperty())
continue;
for (const auto& keyframe : keyframe_group.value->Keyframes()) {
- if (keyframe->Composite() == EffectModel::kCompositeAdd)
+ if (keyframe->Composite() == EffectModel::kCompositeAdd ||
+ keyframe->Composite() == EffectModel::kCompositeAccumulate) {
return true;
+ }
}
}
return false;
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc b/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
index 3ca4bd2fc3b..88ebc78152b 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
@@ -28,17 +28,17 @@ TEST(AnimationEffectInputTest, SortedOffsets) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- Vector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
- .AddString("width", "100px")
- .AddString("offset", "0")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "0px")
- .AddString("offset", "1")
- .GetScriptValue()};
+ HeapVector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
+ .AddString("width", "100px")
+ .AddString("offset", "0")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "0px")
+ .AddString("offset", "1")
+ .GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
Element* element = AppendElement(scope.GetDocument());
@@ -53,17 +53,17 @@ TEST(AnimationEffectInputTest, UnsortedOffsets) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- Vector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
- .AddString("width", "0px")
- .AddString("offset", "1")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "100px")
- .AddString("offset", "0")
- .GetScriptValue()};
+ HeapVector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
+ .AddString("width", "0px")
+ .AddString("offset", "1")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "100px")
+ .AddString("offset", "0")
+ .GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
Element* element = AppendElement(scope.GetDocument());
@@ -78,20 +78,20 @@ TEST(AnimationEffectInputTest, LooslySorted) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- Vector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
- .AddString("width", "100px")
- .AddString("offset", "0")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "200px")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "0px")
- .AddString("offset", "1")
- .GetScriptValue()};
+ HeapVector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
+ .AddString("width", "100px")
+ .AddString("offset", "0")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "200px")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "0px")
+ .AddString("offset", "1")
+ .GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
Element* element = AppendElement(scope.GetDocument());
@@ -106,24 +106,24 @@ TEST(AnimationEffectInputTest, OutOfOrderWithNullOffsets) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- Vector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
- .AddString("height", "100px")
- .AddString("offset", "0.5")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("height", "150px")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("height", "200px")
- .AddString("offset", "0")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("height", "300px")
- .AddString("offset", "1")
- .GetScriptValue()};
+ HeapVector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
+ .AddString("height", "100px")
+ .AddString("offset", "0.5")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("height", "150px")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("height", "200px")
+ .AddString("offset", "0")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("height", "300px")
+ .AddString("offset", "1")
+ .GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
Element* element = AppendElement(scope.GetDocument());
@@ -137,20 +137,20 @@ TEST(AnimationEffectInputTest, Invalid) {
ScriptState* script_state = scope.GetScriptState();
// Not loosely sorted by offset, and there exists a keyframe with null offset.
- Vector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
- .AddString("width", "0px")
- .AddString("offset", "1")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "200px")
- .GetScriptValue(),
- V8ObjectBuilder(script_state)
- .AddString("width", "200px")
- .AddString("offset", "0")
- .GetScriptValue()};
+ HeapVector<ScriptValue> blink_keyframes = {V8ObjectBuilder(script_state)
+ .AddString("width", "0px")
+ .AddString("offset", "1")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "200px")
+ .GetScriptValue(),
+ V8ObjectBuilder(script_state)
+ .AddString("width", "200px")
+ .AddString("offset", "0")
+ .GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
Element* element = AppendElement(scope.GetDocument());
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_model.cc b/chromium/third_party/blink/renderer/core/animation/effect_model.cc
index ed3a9025193..4504d18f645 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_model.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_model.cc
@@ -17,7 +17,8 @@ EffectModel::StringToCompositeOperation(const String& composite_string) {
return base::nullopt;
if (composite_string == "add")
return kCompositeAdd;
- // TODO(crbug.com/788440): Support accumulate.
+ if (composite_string == "accumulate")
+ return kCompositeAccumulate;
return kCompositeReplace;
}
@@ -26,6 +27,8 @@ String EffectModel::CompositeOperationToString(
if (!composite)
return "auto";
switch (composite.value()) {
+ case EffectModel::kCompositeAccumulate:
+ return "accumulate";
case EffectModel::kCompositeAdd:
return "add";
case EffectModel::kCompositeReplace:
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 bec992ba60e..5b6941783b1 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_model.h
+++ b/chromium/third_party/blink/renderer/core/animation/effect_model.h
@@ -45,11 +45,12 @@ class Interpolation;
// Time independent representation of an Animation's content.
// Can be sampled for the active pairs of Keyframes (represented by
// Interpolations) at a given time fraction.
-class CORE_EXPORT EffectModel : public GarbageCollectedFinalized<EffectModel> {
+class CORE_EXPORT EffectModel : public GarbageCollected<EffectModel> {
public:
enum CompositeOperation {
kCompositeReplace,
kCompositeAdd,
+ kCompositeAccumulate,
};
static base::Optional<CompositeOperation> StringToCompositeOperation(
const String&);
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 4a69003a9a5..acefc4ee920 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.h
@@ -46,8 +46,8 @@ class CSSAnimations;
using AnimationCountedSet = HeapHashCountedSet<WeakMember<Animation>>;
using WorkletAnimationSet = HeapHashSet<WeakMember<WorkletAnimationBase>>;
-class CORE_EXPORT ElementAnimations
- : public GarbageCollectedFinalized<ElementAnimations> {
+class CORE_EXPORT ElementAnimations final
+ : public GarbageCollected<ElementAnimations> {
public:
ElementAnimations();
~ElementAnimations();
diff --git a/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc b/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
deleted file mode 100644
index dd4a2b43d43..00000000000
--- a/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.cc
+++ /dev/null
@@ -1,264 +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/animation/filter_interpolation_functions.h"
-
-#include <memory>
-#include "third_party/blink/renderer/core/animation/interpolable_length.h"
-#include "third_party/blink/renderer/core/animation/shadow_interpolation_functions.h"
-#include "third_party/blink/renderer/core/css/css_function_value.h"
-#include "third_party/blink/renderer/core/css/css_primitive_value.h"
-#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
-#include "third_party/blink/renderer/core/style/filter_operations.h"
-#include "third_party/blink/renderer/core/style/shadow_data.h"
-
-namespace blink {
-
-class FilterNonInterpolableValue : public NonInterpolableValue {
- public:
- static scoped_refptr<FilterNonInterpolableValue> Create(
- FilterOperation::OperationType type,
- scoped_refptr<const NonInterpolableValue> type_non_interpolable_value) {
- return base::AdoptRef(new FilterNonInterpolableValue(
- type, std::move(type_non_interpolable_value)));
- }
-
- FilterOperation::OperationType GetOperationType() const { return type_; }
- const NonInterpolableValue* TypeNonInterpolableValue() const {
- return type_non_interpolable_value_.get();
- }
-
- DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
-
- private:
- FilterNonInterpolableValue(
- FilterOperation::OperationType type,
- scoped_refptr<const NonInterpolableValue> type_non_interpolable_value)
- : type_(type),
- type_non_interpolable_value_(std::move(type_non_interpolable_value)) {}
-
- const FilterOperation::OperationType type_;
- scoped_refptr<const NonInterpolableValue> type_non_interpolable_value_;
-};
-
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE(FilterNonInterpolableValue);
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(FilterNonInterpolableValue);
-
-namespace {
-
-double ClampParameter(double value, FilterOperation::OperationType type) {
- switch (type) {
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::SATURATE:
- return clampTo<double>(value, 0);
-
- case FilterOperation::GRAYSCALE:
- case FilterOperation::INVERT:
- case FilterOperation::OPACITY:
- case FilterOperation::SEPIA:
- return clampTo<double>(value, 0, 1);
-
- case FilterOperation::HUE_ROTATE:
- return value;
-
- default:
- NOTREACHED();
- return 0;
- }
-}
-
-} // namespace
-
-InterpolationValue filter_interpolation_functions::MaybeConvertCSSFilter(
- const CSSValue& value) {
- if (value.IsURIValue())
- return nullptr;
-
- const auto& filter = To<CSSFunctionValue>(value);
- DCHECK_LE(filter.length(), 1u);
- FilterOperation::OperationType type =
- FilterOperationResolver::FilterOperationForType(filter.FunctionType());
- InterpolationValue result = nullptr;
-
- switch (type) {
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::GRAYSCALE:
- case FilterOperation::INVERT:
- case FilterOperation::OPACITY:
- case FilterOperation::SATURATE:
- case FilterOperation::SEPIA:
- case FilterOperation::HUE_ROTATE:
- result.interpolable_value = std::make_unique<InterpolableNumber>(
- FilterOperationResolver::ResolveNumericArgumentForFunction(filter));
- break;
-
- case FilterOperation::BLUR: {
- if (filter.length() == 0) {
- result.interpolable_value = InterpolableLength::CreateNeutral();
- } else {
- result = InterpolationValue(
- InterpolableLength::MaybeConvertCSSValue(filter.Item(0)));
- }
- break;
- }
-
- case FilterOperation::DROP_SHADOW: {
- result =
- ShadowInterpolationFunctions::MaybeConvertCSSValue(filter.Item(0));
- break;
- }
-
- default:
- NOTREACHED();
- return nullptr;
- }
-
- if (!result)
- return nullptr;
-
- result.non_interpolable_value = FilterNonInterpolableValue::Create(
- type, std::move(result.non_interpolable_value));
- return result;
-}
-
-InterpolationValue filter_interpolation_functions::MaybeConvertFilter(
- const FilterOperation& filter,
- double zoom) {
- InterpolationValue result = nullptr;
-
- switch (filter.GetType()) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::SATURATE:
- case FilterOperation::SEPIA:
- result.interpolable_value = std::make_unique<InterpolableNumber>(
- To<BasicColorMatrixFilterOperation>(filter).Amount());
- break;
-
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::INVERT:
- case FilterOperation::OPACITY:
- result.interpolable_value = std::make_unique<InterpolableNumber>(
- To<BasicComponentTransferFilterOperation>(filter).Amount());
- break;
-
- case FilterOperation::BLUR:
- result = InterpolationValue(InterpolableLength::MaybeConvertLength(
- To<BlurFilterOperation>(filter).StdDeviation(), zoom));
- break;
-
- case FilterOperation::DROP_SHADOW: {
- result = ShadowInterpolationFunctions::ConvertShadowData(
- To<DropShadowFilterOperation>(filter).Shadow(), zoom);
- break;
- }
-
- case FilterOperation::REFERENCE:
- return nullptr;
-
- default:
- NOTREACHED();
- return nullptr;
- }
-
- if (!result)
- return nullptr;
-
- result.non_interpolable_value = FilterNonInterpolableValue::Create(
- filter.GetType(), std::move(result.non_interpolable_value));
- return result;
-}
-
-std::unique_ptr<InterpolableValue>
-filter_interpolation_functions::CreateNoneValue(
- const NonInterpolableValue& untyped_value) {
- switch (ToFilterNonInterpolableValue(untyped_value).GetOperationType()) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::INVERT:
- case FilterOperation::SEPIA:
- case FilterOperation::HUE_ROTATE:
- return std::make_unique<InterpolableNumber>(0);
-
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- case FilterOperation::SATURATE:
- return std::make_unique<InterpolableNumber>(1);
-
- case FilterOperation::BLUR:
- return InterpolableLength::CreateNeutral();
-
- case FilterOperation::DROP_SHADOW:
- return ShadowInterpolationFunctions::CreateNeutralInterpolableValue();
-
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-bool filter_interpolation_functions::FiltersAreCompatible(
- const NonInterpolableValue& a,
- const NonInterpolableValue& b) {
- return ToFilterNonInterpolableValue(a).GetOperationType() ==
- ToFilterNonInterpolableValue(b).GetOperationType();
-}
-
-FilterOperation* filter_interpolation_functions::CreateFilter(
- const InterpolableValue& interpolable_value,
- const NonInterpolableValue& untyped_non_interpolable_value,
- const StyleResolverState& state) {
- const FilterNonInterpolableValue& non_interpolable_value =
- ToFilterNonInterpolableValue(untyped_non_interpolable_value);
- FilterOperation::OperationType type =
- non_interpolable_value.GetOperationType();
-
- switch (type) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::SATURATE:
- case FilterOperation::SEPIA: {
- double value = ClampParameter(
- ToInterpolableNumber(interpolable_value).Value(), type);
- return MakeGarbageCollected<BasicColorMatrixFilterOperation>(value, type);
- }
-
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::INVERT:
- case FilterOperation::OPACITY: {
- double value = ClampParameter(
- ToInterpolableNumber(interpolable_value).Value(), type);
- return MakeGarbageCollected<BasicComponentTransferFilterOperation>(value,
- type);
- }
-
- case FilterOperation::BLUR: {
- Length std_deviation =
- To<InterpolableLength>(interpolable_value)
- .CreateLength(state.CssToLengthConversionData(),
- kValueRangeNonNegative);
- return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
- }
-
- case FilterOperation::DROP_SHADOW: {
- ShadowData shadow_data = ShadowInterpolationFunctions::CreateShadowData(
- interpolable_value, non_interpolable_value.TypeNonInterpolableValue(),
- state);
- if (shadow_data.GetColor().IsCurrentColor())
- shadow_data.OverrideColor(Color::kBlack);
- return DropShadowFilterOperation::Create(shadow_data);
- }
-
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.h b/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.h
deleted file mode 100644
index 799a8bd49e1..00000000000
--- a/chromium/third_party/blink/renderer/core/animation/filter_interpolation_functions.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/animation/interpolation_value.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class FilterOperation;
-class CSSValue;
-class StyleResolverState;
-
-namespace filter_interpolation_functions {
-
-InterpolationValue MaybeConvertCSSFilter(const CSSValue&);
-InterpolationValue MaybeConvertFilter(const FilterOperation&, double zoom);
-std::unique_ptr<InterpolableValue> CreateNoneValue(const NonInterpolableValue&);
-bool FiltersAreCompatible(const NonInterpolableValue&,
- const NonInterpolableValue&);
-FilterOperation* CreateFilter(const InterpolableValue&,
- const NonInterpolableValue&,
- const StyleResolverState&);
-
-} // namespace filter_interpolation_functions
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/get_animations_options.idl b/chromium/third_party/blink/renderer/core/animation/get_animations_options.idl
new file mode 100644
index 00000000000..7c90f1841a9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/get_animations_options.idl
@@ -0,0 +1,9 @@
+// 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://drafts.csswg.org/web-animations-1/#the-animatable-interface-mixin
+
+dictionary GetAnimationsOptions {
+ boolean subtree = false;
+};
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 7331c601471..b8cdb53e7ce 100644
--- a/chromium/third_party/blink/renderer/core/animation/inert_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/inert_effect.cc
@@ -50,14 +50,17 @@ void InertEffect::Sample(HeapVector<Member<Interpolation>>& result) const {
return;
}
- double iteration = CurrentIteration();
- DCHECK_GE(iteration, 0);
- model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
+ base::Optional<double> iteration = CurrentIteration();
+ DCHECK(iteration);
+ DCHECK_GE(iteration.value(), 0);
+ model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
SpecifiedTiming().IterationDuration(), result);
}
-double InertEffect::CalculateTimeToEffectChange(bool, double, double) const {
- return std::numeric_limits<double>::infinity();
+AnimationTimeDelta InertEffect::CalculateTimeToEffectChange(bool,
+ double,
+ double) const {
+ return AnimationTimeDelta::Max();
}
void InertEffect::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/animation/inert_effect.h b/chromium/third_party/blink/renderer/core/animation/inert_effect.h
index c3d1526bf60..a0df75aacf6 100644
--- a/chromium/third_party/blink/renderer/core/animation/inert_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/inert_effect.h
@@ -57,7 +57,7 @@ class CORE_EXPORT InertEffect final : public AnimationEffect {
protected:
void UpdateChildrenAndEffects() const override {}
- double CalculateTimeToEffectChange(
+ AnimationTimeDelta CalculateTimeToEffectChange(
bool forwards,
double inherited_time,
double time_to_next_iteration) const override;
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_filter.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_filter.cc
new file mode 100644
index 00000000000..7c3c084be2b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_filter.cc
@@ -0,0 +1,245 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/animation/interpolable_filter.h"
+#include "third_party/blink/renderer/core/animation/interpolable_length.h"
+#include "third_party/blink/renderer/core/animation/interpolable_shadow.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_shadow_value.h"
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+
+namespace blink {
+namespace {
+double ClampParameter(double value, FilterOperation::OperationType type) {
+ switch (type) {
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::SATURATE:
+ return clampTo<double>(value, 0);
+
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::INVERT:
+ case FilterOperation::OPACITY:
+ case FilterOperation::SEPIA:
+ return clampTo<double>(value, 0, 1);
+
+ case FilterOperation::HUE_ROTATE:
+ return value;
+
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+} // namespace
+
+// static
+std::unique_ptr<InterpolableFilter> InterpolableFilter::MaybeCreate(
+ const FilterOperation& filter,
+ double zoom) {
+ std::unique_ptr<InterpolableValue> value = nullptr;
+ FilterOperation::OperationType type = filter.GetType();
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::SATURATE:
+ case FilterOperation::SEPIA:
+ value = std::make_unique<InterpolableNumber>(
+ To<BasicColorMatrixFilterOperation>(filter).Amount());
+ break;
+
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::INVERT:
+ case FilterOperation::OPACITY:
+ value = std::make_unique<InterpolableNumber>(
+ To<BasicComponentTransferFilterOperation>(filter).Amount());
+ break;
+
+ case FilterOperation::BLUR:
+ value = InterpolableLength::MaybeConvertLength(
+ To<BlurFilterOperation>(filter).StdDeviation(), zoom);
+ break;
+
+ case FilterOperation::DROP_SHADOW:
+ value = InterpolableShadow::Create(
+ To<DropShadowFilterOperation>(filter).Shadow(), zoom);
+ break;
+
+ case FilterOperation::REFERENCE:
+ return nullptr;
+
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+
+ if (!value)
+ return nullptr;
+ return std::make_unique<InterpolableFilter>(std::move(value), type);
+}
+
+// static
+std::unique_ptr<InterpolableFilter> InterpolableFilter::MaybeConvertCSSValue(
+ const CSSValue& css_value) {
+ if (css_value.IsURIValue())
+ return nullptr;
+
+ const auto& filter = To<CSSFunctionValue>(css_value);
+ DCHECK_LE(filter.length(), 1u);
+
+ std::unique_ptr<InterpolableValue> value = nullptr;
+ FilterOperation::OperationType type =
+ FilterOperationResolver::FilterOperationForType(filter.FunctionType());
+ switch (type) {
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::INVERT:
+ case FilterOperation::OPACITY:
+ case FilterOperation::SATURATE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::HUE_ROTATE:
+ value = std::make_unique<InterpolableNumber>(
+ FilterOperationResolver::ResolveNumericArgumentForFunction(filter));
+ break;
+
+ case FilterOperation::BLUR:
+ value = filter.length() > 0
+ ? InterpolableLength::MaybeConvertCSSValue(filter.Item(0))
+ : InterpolableLength::CreateNeutral();
+ break;
+
+ case FilterOperation::DROP_SHADOW:
+ value = InterpolableShadow::MaybeConvertCSSValue(filter.Item(0));
+ break;
+
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+
+ if (!value)
+ return nullptr;
+ return std::make_unique<InterpolableFilter>(std::move(value), type);
+}
+
+// static
+std::unique_ptr<InterpolableFilter> InterpolableFilter::CreateInitialValue(
+ FilterOperation::OperationType type) {
+ // See https://drafts.fxtf.org/filter-effects-1/#filter-functions for the
+ // mapping of OperationType to initial value.
+ std::unique_ptr<InterpolableValue> value = nullptr;
+ switch (type) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::INVERT:
+ case FilterOperation::SEPIA:
+ case FilterOperation::HUE_ROTATE:
+ value = std::make_unique<InterpolableNumber>(0);
+ break;
+
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ case FilterOperation::SATURATE:
+ value = std::make_unique<InterpolableNumber>(1);
+ break;
+
+ case FilterOperation::BLUR:
+ value = InterpolableLength::CreateNeutral();
+ break;
+
+ case FilterOperation::DROP_SHADOW:
+ value = InterpolableShadow::CreateNeutral();
+ break;
+
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+
+ return std::make_unique<InterpolableFilter>(std::move(value), type);
+}
+
+FilterOperation* InterpolableFilter::CreateFilterOperation(
+ const StyleResolverState& state) const {
+ switch (type_) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::SATURATE:
+ case FilterOperation::SEPIA: {
+ double value =
+ ClampParameter(ToInterpolableNumber(*value_).Value(), type_);
+ return MakeGarbageCollected<BasicColorMatrixFilterOperation>(value,
+ type_);
+ }
+
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::INVERT:
+ case FilterOperation::OPACITY: {
+ double value =
+ ClampParameter(ToInterpolableNumber(*value_).Value(), type_);
+ return MakeGarbageCollected<BasicComponentTransferFilterOperation>(value,
+ type_);
+ }
+
+ case FilterOperation::BLUR: {
+ Length std_deviation = To<InterpolableLength>(*value_).CreateLength(
+ state.CssToLengthConversionData(), kValueRangeNonNegative);
+ return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
+ }
+
+ case FilterOperation::DROP_SHADOW: {
+ ShadowData shadow_data =
+ To<InterpolableShadow>(*value_).CreateShadowData(state);
+ if (shadow_data.GetColor().IsCurrentColor())
+ shadow_data.OverrideColor(Color::kBlack);
+ return DropShadowFilterOperation::Create(shadow_data);
+ }
+
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
+void InterpolableFilter::Add(const InterpolableValue& other) {
+ value_->Add(*To<InterpolableFilter>(other).value_);
+ // The following types have an initial value of 1, so addition for them is
+ // one-based: result = value_ + other.value_ - 1
+ switch (type_) {
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::INVERT:
+ case FilterOperation::OPACITY:
+ case FilterOperation::SATURATE:
+ case FilterOperation::SEPIA:
+ value_->Add(*std::make_unique<InterpolableNumber>(-1));
+ break;
+ default:
+ break;
+ }
+}
+
+void InterpolableFilter::AssertCanInterpolateWith(
+ const InterpolableValue& other) const {
+ const InterpolableFilter& other_filter = To<InterpolableFilter>(other);
+ value_->AssertCanInterpolateWith(*other_filter.value_);
+ DCHECK_EQ(type_, other_filter.type_);
+}
+
+void InterpolableFilter::Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const {
+ const InterpolableFilter& filter_to = To<InterpolableFilter>(to);
+ InterpolableFilter& filter_result = To<InterpolableFilter>(result);
+ value_->Interpolate(*filter_to.value_, progress, *filter_result.value_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_filter.h b/chromium/third_party/blink/renderer/core/animation/interpolable_filter.h
new file mode 100644
index 00000000000..07b20a5eb20
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_filter.h
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
+
+#include <memory>
+#include "third_party/blink/renderer/core/animation/interpolable_value.h"
+#include "third_party/blink/renderer/core/style/filter_operation.h"
+
+namespace blink {
+
+class CSSValue;
+class StyleResolverState;
+
+// Represents a blink::FilterOperation, converted into a form that can be
+// interpolated from/to.
+class CORE_EXPORT InterpolableFilter final : public InterpolableValue {
+ public:
+ InterpolableFilter(std::unique_ptr<InterpolableValue> value,
+ FilterOperation::OperationType type)
+ : value_(std::move(value)), type_(type) {
+ DCHECK(value_);
+ }
+
+ static std::unique_ptr<InterpolableFilter> MaybeCreate(const FilterOperation&,
+ double zoom);
+ static std::unique_ptr<InterpolableFilter> MaybeConvertCSSValue(
+ const CSSValue&);
+
+ // Create an InterpolableFilter representing the 'initial value for
+ // interpolation' for the given OperationType.
+ static std::unique_ptr<InterpolableFilter> CreateInitialValue(
+ FilterOperation::OperationType);
+
+ FilterOperation::OperationType GetType() const { return type_; }
+
+ // Convert this InterpolableFilter back into a FilterOperation class, usually
+ // to be applied to the style after interpolating |this|.
+ FilterOperation* CreateFilterOperation(const StyleResolverState&) const;
+
+ // InterpolableValue implementation:
+ void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const final;
+ bool IsFilter() const final { return true; }
+ bool Equals(const InterpolableValue& other) const final {
+ NOTREACHED();
+ return false;
+ }
+ void Scale(double scale) final { NOTREACHED(); }
+ void Add(const InterpolableValue& other) final;
+ void AssertCanInterpolateWith(const InterpolableValue& other) const final;
+
+ private:
+ InterpolableFilter* RawClone() const final {
+ return new InterpolableFilter(value_->Clone(), type_);
+ }
+ InterpolableFilter* RawCloneAndZero() const final {
+ return new InterpolableFilter(value_->CloneAndZero(), type_);
+ }
+
+ // Stores the interpolable data for the filter. The form varies depending on
+ // the |type_|; see the implementation file for details of the mapping.
+ std::unique_ptr<InterpolableValue> value_;
+
+ FilterOperation::OperationType type_;
+};
+
+template <>
+struct DowncastTraits<InterpolableFilter> {
+ static bool AllowFrom(const InterpolableValue& interpolable_value) {
+ return interpolable_value.IsFilter();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_length.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_length.cc
index 9f6a511fa27..08e6cc60d5a 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_length.cc
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_length.cc
@@ -14,6 +14,22 @@
namespace blink {
+using UnitType = CSSPrimitiveValue::UnitType;
+
+namespace {
+
+CSSMathExpressionNode* NumberNode(double number) {
+ return CSSMathExpressionNumericLiteral::Create(
+ CSSNumericLiteralValue::Create(number, UnitType::kNumber));
+}
+
+CSSMathExpressionNode* PercentageNode(double number) {
+ return CSSMathExpressionNumericLiteral::Create(
+ CSSNumericLiteralValue::Create(number, UnitType::kPercentage));
+}
+
+} // namespace
+
// static
std::unique_ptr<InterpolableLength> InterpolableLength::CreatePixels(
double pixels) {
@@ -49,13 +65,12 @@ std::unique_ptr<InterpolableLength> InterpolableLength::MaybeConvertCSSValue(
return nullptr;
CSSLengthArray length_array;
- if (!primitive_value->AccumulateLengthArray(length_array)) {
- // TODO(crbug.com/991672): Implement interpolation when CSS comparison
- // functions min/max are involved.
- return nullptr;
- }
+ if (primitive_value->AccumulateLengthArray(length_array))
+ return std::make_unique<InterpolableLength>(std::move(length_array));
- return std::make_unique<InterpolableLength>(std::move(length_array));
+ DCHECK(primitive_value->IsMathFunctionValue());
+ return std::make_unique<InterpolableLength>(
+ *To<CSSMathFunctionValue>(primitive_value)->ExpressionNode());
}
// static
@@ -66,8 +81,9 @@ std::unique_ptr<InterpolableLength> InterpolableLength::MaybeConvertLength(
return nullptr;
if (length.IsCalculated() && length.GetCalculationValue().IsExpression()) {
- // TODO(crbug.com/991672): Support interpolation on min/max results.
- return nullptr;
+ auto unzoomed_calc = length.GetCalculationValue().Zoom(1.0 / zoom);
+ return std::make_unique<InterpolableLength>(
+ *CSSMathExpressionNode::Create(*unzoomed_calc));
}
PixelsAndPercent pixels_and_percent = length.GetPixelsAndPercent();
@@ -90,27 +106,97 @@ PairwiseInterpolationValue InterpolableLength::MergeSingles(
std::unique_ptr<InterpolableValue> start,
std::unique_ptr<InterpolableValue> end) {
// TODO(crbug.com/991672): We currently have a lot of "fast paths" that do not
- // go through here, and hence, do not merge the type flags of two lengths. We
- // should stop doing that.
+ // go through here, and hence, do not merge the percentage info of two
+ // lengths. We should stop doing that.
auto& start_length = To<InterpolableLength>(*start);
auto& end_length = To<InterpolableLength>(*end);
- start_length.length_array_.type_flags |= end_length.length_array_.type_flags;
- end_length.length_array_.type_flags = start_length.length_array_.type_flags;
+ if (start_length.HasPercentage() || end_length.HasPercentage()) {
+ start_length.SetHasPercentage();
+ end_length.SetHasPercentage();
+ }
+ if (start_length.IsExpression() || end_length.IsExpression()) {
+ start_length.SetExpression(start_length.AsExpression());
+ end_length.SetExpression(end_length.AsExpression());
+ }
return PairwiseInterpolationValue(std::move(start), std::move(end));
}
+InterpolableLength::InterpolableLength(CSSLengthArray&& length_array) {
+ SetLengthArray(std::move(length_array));
+}
+
+void InterpolableLength::SetLengthArray(CSSLengthArray&& length_array) {
+ type_ = Type::kLengthArray;
+ length_array_ = std::move(length_array);
+ expression_.Clear();
+}
+
+InterpolableLength::InterpolableLength(
+ const CSSMathExpressionNode& expression) {
+ SetExpression(expression);
+}
+
+void InterpolableLength::SetExpression(
+ const CSSMathExpressionNode& expression) {
+ type_ = Type::kExpression;
+ expression_ = &expression;
+}
+
+InterpolableLength* InterpolableLength::RawClone() const {
+ return new InterpolableLength(*this);
+}
+
+bool InterpolableLength::HasPercentage() const {
+ if (IsLengthArray()) {
+ return length_array_.type_flags.test(
+ CSSPrimitiveValue::kUnitTypePercentage);
+ }
+ return expression_->HasPercentage();
+}
+
+void InterpolableLength::SetHasPercentage() {
+ if (HasPercentage())
+ return;
+
+ if (IsLengthArray()) {
+ length_array_.type_flags.set(CSSPrimitiveValue::kUnitTypePercentage);
+ return;
+ }
+
+ DEFINE_STATIC_LOCAL(Persistent<CSSMathExpressionNode>, zero_percent,
+ {PercentageNode(0)});
+ SetExpression(*CSSMathExpressionBinaryOperation::Create(
+ expression_, zero_percent, CSSMathOperator::kAdd));
+}
+
void InterpolableLength::SubtractFromOneHundredPercent() {
- for (double& value : length_array_.values)
- value *= -1;
- length_array_.values[CSSPrimitiveValue::kUnitTypePercentage] += 100;
- length_array_.type_flags.set(CSSPrimitiveValue::kUnitTypePercentage);
+ if (IsLengthArray()) {
+ for (double& value : length_array_.values)
+ value *= -1;
+ length_array_.values[CSSPrimitiveValue::kUnitTypePercentage] += 100;
+ length_array_.type_flags.set(CSSPrimitiveValue::kUnitTypePercentage);
+ return;
+ }
+
+ DEFINE_STATIC_LOCAL(Persistent<CSSMathExpressionNode>, hundred_percent,
+ {PercentageNode(100)});
+ SetExpression(*CSSMathExpressionBinaryOperation::CreateSimplified(
+ hundred_percent, expression_, CSSMathOperator::kSubtract));
}
static double ClampToRange(double x, ValueRange range) {
return (range == kValueRangeNonNegative && x < 0) ? 0 : x;
}
-static CSSPrimitiveValue::UnitType IndexToUnitType(wtf_size_t index) {
+static const CSSNumericLiteralValue& ClampNumericLiteralValueToRange(
+ const CSSNumericLiteralValue& value,
+ ValueRange range) {
+ if (range == kValueRangeAll || value.DoubleValue() >= 0)
+ return value;
+ return *CSSNumericLiteralValue::Create(0, value.GetType());
+}
+
+static UnitType IndexToUnitType(wtf_size_t index) {
return CSSPrimitiveValue::LengthUnitTypeToUnitType(
static_cast<CSSPrimitiveValue::LengthUnitType>(index));
}
@@ -118,6 +204,9 @@ static CSSPrimitiveValue::UnitType IndexToUnitType(wtf_size_t index) {
Length InterpolableLength::CreateLength(
const CSSToLengthConversionData& conversion_data,
ValueRange range) const {
+ if (IsExpression())
+ return Length(expression_->ToCalcValue(conversion_data, range));
+
bool has_percentage = HasPercentage();
double pixels = 0;
double percentage = 0;
@@ -147,11 +236,40 @@ Length InterpolableLength::CreateLength(
const CSSPrimitiveValue* InterpolableLength::CreateCSSValue(
ValueRange range) const {
+ if (IsExpression())
+ return CSSMathFunctionValue::Create(expression_, range);
+
+ DCHECK(IsLengthArray());
+ if (length_array_.type_flags.count() > 1u) {
+ const CSSMathExpressionNode& expression = AsExpression();
+ if (!expression.IsNumericLiteral())
+ return CSSMathFunctionValue::Create(&AsExpression(), range);
+
+ // This creates a temporary CSSMathExpressionNode. Eliminate it if this
+ // results in significant performance regression.
+ return &ClampNumericLiteralValueToRange(
+ To<CSSMathExpressionNumericLiteral>(expression).GetValue(), range);
+ }
+
+ for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
+ if (length_array_.type_flags.test(i)) {
+ double value = ClampToRange(length_array_.values[i], range);
+ UnitType unit_type = IndexToUnitType(i);
+ return CSSNumericLiteralValue::Create(value, unit_type);
+ }
+ }
+
+ return CSSNumericLiteralValue::Create(0, UnitType::kPixels);
+}
+
+const CSSMathExpressionNode& InterpolableLength::AsExpression() const {
+ if (IsExpression())
+ return *expression_;
+
+ DCHECK(IsLengthArray());
bool has_percentage = HasPercentage();
CSSMathExpressionNode* root_node = nullptr;
- CSSNumericLiteralValue* first_value = nullptr;
-
for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
double value = length_array_.values[i];
if (value == 0 &&
@@ -160,41 +278,70 @@ const CSSPrimitiveValue* InterpolableLength::CreateCSSValue(
}
CSSNumericLiteralValue* current_value =
CSSNumericLiteralValue::Create(value, IndexToUnitType(i));
-
- if (!first_value) {
- DCHECK(!root_node);
- first_value = current_value;
- continue;
- }
CSSMathExpressionNode* current_node =
CSSMathExpressionNumericLiteral::Create(current_value);
if (!root_node) {
- root_node = CSSMathExpressionNumericLiteral::Create(first_value);
+ root_node = current_node;
+ } else {
+ root_node = CSSMathExpressionBinaryOperation::Create(
+ root_node, current_node, CSSMathOperator::kAdd);
}
- root_node = CSSMathExpressionBinaryOperation::Create(
- root_node, current_node, CSSMathOperator::kAdd);
}
- if (root_node) {
- return CSSMathFunctionValue::Create(root_node, range);
+ if (root_node)
+ return *root_node;
+ return *CSSMathExpressionNumericLiteral::Create(
+ CSSNumericLiteralValue::Create(0, UnitType::kPixels));
+}
+
+void InterpolableLength::Scale(double scale) {
+ if (IsLengthArray()) {
+ for (auto& value : length_array_.values)
+ value *= scale;
+ return;
}
- if (first_value) {
- if (range == kValueRangeNonNegative && first_value->DoubleValue() < 0)
- return CSSNumericLiteralValue::Create(0, first_value->GetType());
- return first_value;
+
+ DCHECK(IsExpression());
+ SetExpression(*CSSMathExpressionBinaryOperation::CreateSimplified(
+ expression_, NumberNode(scale), CSSMathOperator::kMultiply));
+}
+
+void InterpolableLength::Add(const InterpolableValue& other) {
+ const InterpolableLength& other_length = To<InterpolableLength>(other);
+ if (IsLengthArray() && other_length.IsLengthArray()) {
+ for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
+ length_array_.values[i] =
+ length_array_.values[i] + other_length.length_array_.values[i];
+ }
+ length_array_.type_flags |= other_length.length_array_.type_flags;
+ return;
}
- return CSSNumericLiteralValue::Create(0,
- CSSPrimitiveValue::UnitType::kPixels);
+
+ CSSMathExpressionNode* result =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ &AsExpression(), &other_length.AsExpression(), CSSMathOperator::kAdd);
+ SetExpression(*result);
}
void InterpolableLength::ScaleAndAdd(double scale,
const InterpolableValue& other) {
const InterpolableLength& other_length = To<InterpolableLength>(other);
- for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
- length_array_.values[i] =
- length_array_.values[i] * scale + other_length.length_array_.values[i];
+ if (IsLengthArray() && other_length.IsLengthArray()) {
+ for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
+ length_array_.values[i] = length_array_.values[i] * scale +
+ other_length.length_array_.values[i];
+ }
+ length_array_.type_flags |= other_length.length_array_.type_flags;
+ return;
}
- length_array_.type_flags |= other_length.length_array_.type_flags;
+
+ CSSMathExpressionNode* scaled =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ &AsExpression(), NumberNode(scale), CSSMathOperator::kMultiply);
+ CSSMathExpressionNode* result =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ scaled, &other_length.AsExpression(), CSSMathOperator::kAdd);
+ SetExpression(*result);
}
void InterpolableLength::AssertCanInterpolateWith(
@@ -204,23 +351,45 @@ void InterpolableLength::AssertCanInterpolateWith(
// two |InterpolableLength| objects should also assign them the same shape
// (i.e. type flags) after merging into a |PairwiseInterpolationValue|. We
// currently fail to do that, and hit the following DCHECK:
- // DCHECK_EQ(length_array_.type_flags,
- // To<InterpolableLength>(other).length_array_.type_flags);
+ // DCHECK_EQ(HasPercentage(),
+ // To<InterpolableLength>(other).HasPercentage());
}
void InterpolableLength::Interpolate(const InterpolableValue& to,
const double progress,
InterpolableValue& result) const {
- const CSSLengthArray& to_length_array =
- To<InterpolableLength>(to).length_array_;
- CSSLengthArray& result_length_array =
- To<InterpolableLength>(result).length_array_;
- for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
- result_length_array.values[i] =
- Blend(length_array_.values[i], to_length_array.values[i], progress);
+ const auto& to_length = To<InterpolableLength>(to);
+ auto& result_length = To<InterpolableLength>(result);
+ if (IsLengthArray() && to_length.IsLengthArray()) {
+ if (!result_length.IsLengthArray())
+ result_length.SetLengthArray(CSSLengthArray());
+ const CSSLengthArray& to_length_array = to_length.length_array_;
+ CSSLengthArray& result_length_array =
+ To<InterpolableLength>(result).length_array_;
+ for (wtf_size_t i = 0; i < length_array_.values.size(); ++i) {
+ result_length_array.values[i] =
+ Blend(length_array_.values[i], to_length_array.values[i], progress);
+ }
+ result_length_array.type_flags =
+ length_array_.type_flags | to_length_array.type_flags;
+ return;
}
- result_length_array.type_flags =
- length_array_.type_flags | to_length_array.type_flags;
+
+ CSSMathExpressionNode* blended_from =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ &AsExpression(), NumberNode(1 - progress),
+ CSSMathOperator::kMultiply);
+ CSSMathExpressionNode* blended_to =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ &to_length.AsExpression(), NumberNode(progress),
+ CSSMathOperator::kMultiply);
+ CSSMathExpressionNode* result_expression =
+ CSSMathExpressionBinaryOperation::CreateSimplified(
+ blended_from, blended_to, CSSMathOperator::kAdd);
+ result_length.SetExpression(*result_expression);
+
+ DCHECK_EQ(result_length.HasPercentage(),
+ HasPercentage() || to_length.HasPercentage());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_length.h b/chromium/third_party/blink/renderer/core/animation/interpolable_length.h
index bd06bcfe62e..02ce93022dc 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_length.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_length.h
@@ -10,19 +10,19 @@
#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/platform/geometry/length.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class CSSToLengthConversionData;
+class CSSMathExpressionNode;
class CORE_EXPORT InterpolableLength final : public InterpolableValue {
public:
~InterpolableLength() final {}
- InterpolableLength(const CSSLengthArray& length_array)
- : length_array_(length_array) {}
- InterpolableLength(CSSLengthArray&& length_array)
- : length_array_(std::move(length_array)) {}
+ InterpolableLength(CSSLengthArray&& length_array);
+ explicit InterpolableLength(const CSSMathExpressionNode& expression);
static std::unique_ptr<InterpolableLength> CreatePixels(double pixels);
static std::unique_ptr<InterpolableLength> CreatePercent(double pixels);
@@ -45,39 +45,49 @@ class CORE_EXPORT InterpolableLength final : public InterpolableValue {
// expressions.
const CSSPrimitiveValue* CreateCSSValue(ValueRange range) const;
- bool HasPercentage() const {
- return length_array_.type_flags.test(
- CSSPrimitiveValue::kUnitTypePercentage);
- }
+ void SetHasPercentage();
+ bool HasPercentage() const;
void SubtractFromOneHundredPercent();
+ std::unique_ptr<InterpolableLength> Clone() const {
+ return std::unique_ptr<InterpolableLength>(RawClone());
+ }
+ std::unique_ptr<InterpolableLength> CloneAndZero() const {
+ return std::unique_ptr<InterpolableLength>(RawCloneAndZero());
+ }
+
// InterpolableValue:
+ void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const final;
bool IsLength() const final { return true; }
bool Equals(const InterpolableValue& other) const final {
NOTREACHED();
return false;
}
- std::unique_ptr<InterpolableValue> Clone() const final {
- return std::make_unique<InterpolableLength>(length_array_);
- }
- std::unique_ptr<InterpolableValue> CloneAndZero() const final {
- return std::make_unique<InterpolableLength>(CSSLengthArray());
- }
- void Scale(double scale) final {
- for (double& value : length_array_.values) {
- value *= scale;
- }
- }
+ void Scale(double scale) final;
+ void Add(const InterpolableValue& other) final;
+ // We override this to avoid two passes in the case of LengthArrays.
void ScaleAndAdd(double scale, const InterpolableValue& other) final;
void AssertCanInterpolateWith(const InterpolableValue& other) const final;
private:
- // InterpolableValue:
- void Interpolate(const InterpolableValue& to,
- const double progress,
- InterpolableValue& result) const final;
+ InterpolableLength* RawClone() const final;
+ InterpolableLength* RawCloneAndZero() const final {
+ return new InterpolableLength(CSSLengthArray());
+ }
+
+ bool IsLengthArray() const { return type_ == Type::kLengthArray; }
+ bool IsExpression() const { return type_ == Type::kExpression; }
+
+ void SetLengthArray(CSSLengthArray&& length_array);
+ void SetExpression(const CSSMathExpressionNode& expression);
+ const CSSMathExpressionNode& AsExpression() const;
+ enum class Type { kLengthArray, kExpression };
+ Type type_;
CSSLengthArray length_array_;
+ Persistent<const CSSMathExpressionNode> expression_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.cc
new file mode 100644
index 00000000000..37e48c4a4a9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.cc
@@ -0,0 +1,202 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/animation/interpolable_shadow.h"
+
+#include <memory>
+#include "third_party/blink/renderer/core/animation/css_color_interpolation_type.h"
+#include "third_party/blink/renderer/core/animation/underlying_value.h"
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
+#include "third_party/blink/renderer/core/css/css_shadow_value.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/platform/geometry/float_point.h"
+
+namespace blink {
+namespace {
+std::unique_ptr<InterpolableLength> MaybeConvertLength(
+ const CSSPrimitiveValue* value) {
+ if (value)
+ return InterpolableLength::MaybeConvertCSSValue(*value);
+ return InterpolableLength::CreatePixels(0);
+}
+
+std::unique_ptr<InterpolableValue> MaybeConvertColor(const CSSValue* value) {
+ if (value)
+ return CSSColorInterpolationType::MaybeCreateInterpolableColor(*value);
+ return CSSColorInterpolationType::CreateInterpolableColor(
+ StyleColor::CurrentColor());
+}
+} // namespace
+
+InterpolableShadow::InterpolableShadow(
+ std::unique_ptr<InterpolableLength> x,
+ std::unique_ptr<InterpolableLength> y,
+ std::unique_ptr<InterpolableLength> blur,
+ std::unique_ptr<InterpolableLength> spread,
+ std::unique_ptr<InterpolableValue> color,
+ ShadowStyle shadow_style)
+ : x_(std::move(x)),
+ y_(std::move(y)),
+ blur_(std::move(blur)),
+ spread_(std::move(spread)),
+ color_(std::move(color)),
+ shadow_style_(shadow_style) {
+ DCHECK(x_);
+ DCHECK(y_);
+ DCHECK(blur_);
+ DCHECK(spread_);
+ DCHECK(color_);
+}
+
+// static
+std::unique_ptr<InterpolableShadow> InterpolableShadow::Create(
+ const ShadowData& shadow_data,
+ double zoom) {
+ return std::make_unique<InterpolableShadow>(
+ InterpolableLength::CreatePixels(shadow_data.X() / zoom),
+ InterpolableLength::CreatePixels(shadow_data.Y() / zoom),
+ InterpolableLength::CreatePixels(shadow_data.Blur() / zoom),
+ InterpolableLength::CreatePixels(shadow_data.Spread() / zoom),
+ CSSColorInterpolationType::CreateInterpolableColor(
+ shadow_data.GetColor()),
+ shadow_data.Style());
+}
+
+// static
+std::unique_ptr<InterpolableShadow> InterpolableShadow::CreateNeutral() {
+ return Create(ShadowData::NeutralValue(), 1);
+}
+
+// static
+std::unique_ptr<InterpolableShadow> InterpolableShadow::MaybeConvertCSSValue(
+ const CSSValue& value) {
+ const auto* shadow = DynamicTo<CSSShadowValue>(value);
+ if (!shadow)
+ return nullptr;
+
+ ShadowStyle shadow_style = kNormal;
+ if (shadow->style) {
+ if (shadow->style->GetValueID() != CSSValueID::kInset)
+ return nullptr;
+ shadow_style = kInset;
+ }
+
+ std::unique_ptr<InterpolableLength> x = MaybeConvertLength(shadow->x.Get());
+ std::unique_ptr<InterpolableLength> y = MaybeConvertLength(shadow->y.Get());
+ std::unique_ptr<InterpolableLength> blur =
+ MaybeConvertLength(shadow->blur.Get());
+ std::unique_ptr<InterpolableLength> spread =
+ MaybeConvertLength(shadow->spread.Get());
+ std::unique_ptr<InterpolableValue> color = MaybeConvertColor(shadow->color);
+
+ // If any of the conversations failed, we can't represent this CSSValue.
+ if (!x || !y || !blur || !spread || !color)
+ return nullptr;
+
+ return std::make_unique<InterpolableShadow>(
+ std::move(x), std::move(y), std::move(blur), std::move(spread),
+ std::move(color), shadow_style);
+}
+
+// static
+PairwiseInterpolationValue InterpolableShadow::MaybeMergeSingles(
+ std::unique_ptr<InterpolableValue> start,
+ std::unique_ptr<InterpolableValue> end) {
+ if (To<InterpolableShadow>(start.get())->shadow_style_ !=
+ To<InterpolableShadow>(end.get())->shadow_style_)
+ return nullptr;
+ return PairwiseInterpolationValue(std::move(start), std::move(end));
+}
+
+// static
+bool InterpolableShadow::CompatibleForCompositing(const InterpolableValue* from,
+ const InterpolableValue* to) {
+ return To<InterpolableShadow>(from)->shadow_style_ ==
+ To<InterpolableShadow>(to)->shadow_style_;
+}
+
+// static
+void InterpolableShadow::Composite(UnderlyingValue& underlying_value,
+ double underlying_fraction,
+ const InterpolableValue& interpolable_value,
+ const NonInterpolableValue*) {
+ InterpolableShadow& underlying_shadow =
+ To<InterpolableShadow>(underlying_value.MutableInterpolableValue());
+ const InterpolableShadow& interpolable_shadow =
+ To<InterpolableShadow>(interpolable_value);
+ DCHECK_EQ(underlying_shadow.shadow_style_, interpolable_shadow.shadow_style_);
+ underlying_shadow.ScaleAndAdd(underlying_fraction, interpolable_shadow);
+}
+
+ShadowData InterpolableShadow::CreateShadowData(
+ const StyleResolverState& state) const {
+ const CSSToLengthConversionData& conversion_data =
+ state.CssToLengthConversionData();
+ Length shadow_x = x_->CreateLength(conversion_data, kValueRangeAll);
+ Length shadow_y = y_->CreateLength(conversion_data, kValueRangeAll);
+ Length shadow_blur =
+ blur_->CreateLength(conversion_data, kValueRangeNonNegative);
+ Length shadow_spread = spread_->CreateLength(conversion_data, kValueRangeAll);
+ DCHECK(shadow_x.IsFixed() && shadow_y.IsFixed() && shadow_blur.IsFixed() &&
+ shadow_spread.IsFixed());
+ return ShadowData(
+ FloatPoint(shadow_x.Value(), shadow_y.Value()), shadow_blur.Value(),
+ shadow_spread.Value(), shadow_style_,
+ CSSColorInterpolationType::ResolveInterpolableColor(*color_, state));
+}
+
+InterpolableShadow* InterpolableShadow::RawClone() const {
+ return new InterpolableShadow(x_->Clone(), y_->Clone(), blur_->Clone(),
+ spread_->Clone(), color_->Clone(),
+ shadow_style_);
+}
+
+InterpolableShadow* InterpolableShadow::RawCloneAndZero() const {
+ return new InterpolableShadow(x_->CloneAndZero(), y_->CloneAndZero(),
+ blur_->CloneAndZero(), spread_->CloneAndZero(),
+ color_->CloneAndZero(), shadow_style_);
+}
+
+void InterpolableShadow::Scale(double scale) {
+ x_->Scale(scale);
+ y_->Scale(scale);
+ blur_->Scale(scale);
+ spread_->Scale(scale);
+ color_->Scale(scale);
+}
+
+void InterpolableShadow::Add(const InterpolableValue& other) {
+ const InterpolableShadow& other_shadow = To<InterpolableShadow>(other);
+ x_->Add(*other_shadow.x_);
+ y_->Add(*other_shadow.y_);
+ blur_->Add(*other_shadow.blur_);
+ spread_->Add(*other_shadow.spread_);
+ color_->Add(*other_shadow.color_);
+}
+
+void InterpolableShadow::AssertCanInterpolateWith(
+ const InterpolableValue& other) const {
+ const InterpolableShadow& other_shadow = To<InterpolableShadow>(other);
+ DCHECK_EQ(shadow_style_, other_shadow.shadow_style_);
+ x_->AssertCanInterpolateWith(*other_shadow.x_);
+ y_->AssertCanInterpolateWith(*other_shadow.y_);
+ blur_->AssertCanInterpolateWith(*other_shadow.blur_);
+ spread_->AssertCanInterpolateWith(*other_shadow.spread_);
+ color_->AssertCanInterpolateWith(*other_shadow.color_);
+}
+
+void InterpolableShadow::Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const {
+ const InterpolableShadow& to_shadow = To<InterpolableShadow>(to);
+ InterpolableShadow& result_shadow = To<InterpolableShadow>(result);
+
+ x_->Interpolate(*to_shadow.x_, progress, *result_shadow.x_);
+ y_->Interpolate(*to_shadow.y_, progress, *result_shadow.y_);
+ blur_->Interpolate(*to_shadow.blur_, progress, *result_shadow.blur_);
+ spread_->Interpolate(*to_shadow.spread_, progress, *result_shadow.spread_);
+ color_->Interpolate(*to_shadow.color_, progress, *result_shadow.color_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.h b/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.h
new file mode 100644
index 00000000000..bdc200f4ce8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_shadow.h
@@ -0,0 +1,94 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_SHADOW_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_SHADOW_H_
+
+#include <memory>
+#include "third_party/blink/renderer/core/animation/interpolable_length.h"
+#include "third_party/blink/renderer/core/animation/interpolable_value.h"
+#include "third_party/blink/renderer/core/animation/interpolation_value.h"
+#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
+#include "third_party/blink/renderer/core/style/shadow_data.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class CSSValue;
+class StyleResolverState;
+class UnderlyingValue;
+
+// Represents a CSS shadow value (such as [0] or [1]), converted into a form
+// that can be interpolated from/to.
+//
+// [0]: https://drafts.csswg.org/css-backgrounds-3/#typedef-shadow
+// [1]: https://drafts.fxtf.org/filter-effects/#funcdef-filter-drop-shadow
+class InterpolableShadow : public InterpolableValue {
+ public:
+ InterpolableShadow(std::unique_ptr<InterpolableLength> x,
+ std::unique_ptr<InterpolableLength> y,
+ std::unique_ptr<InterpolableLength> blur,
+ std::unique_ptr<InterpolableLength> spread,
+ std::unique_ptr<InterpolableValue> color,
+ ShadowStyle);
+
+ static std::unique_ptr<InterpolableShadow> Create(const ShadowData&,
+ double zoom);
+ static std::unique_ptr<InterpolableShadow> CreateNeutral();
+
+ static std::unique_ptr<InterpolableShadow> MaybeConvertCSSValue(
+ const CSSValue&);
+
+ // Helpers for CSSListInterpolationFunctions.
+ static PairwiseInterpolationValue MaybeMergeSingles(
+ std::unique_ptr<InterpolableValue> start,
+ std::unique_ptr<InterpolableValue> end);
+ static bool CompatibleForCompositing(const InterpolableValue*,
+ const InterpolableValue*);
+ static void Composite(UnderlyingValue&,
+ double underlying_fraction,
+ const InterpolableValue&,
+ const NonInterpolableValue*);
+
+ // Convert this InterpolableShadow back into a ShadowData class, usually to be
+ // applied to the style after interpolating it.
+ ShadowData CreateShadowData(const StyleResolverState&) const;
+
+ // InterpolableValue implementation:
+ void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const final;
+ bool IsShadow() const final { return true; }
+ bool Equals(const InterpolableValue& other) const final {
+ NOTREACHED();
+ return false;
+ }
+ void Scale(double scale) final;
+ void Add(const InterpolableValue& other) final;
+ void AssertCanInterpolateWith(const InterpolableValue& other) const final;
+
+ private:
+ InterpolableShadow* RawClone() const final;
+ InterpolableShadow* RawCloneAndZero() const final;
+
+ // The interpolable components of a shadow. These should all be non-null.
+ std::unique_ptr<InterpolableLength> x_;
+ std::unique_ptr<InterpolableLength> y_;
+ std::unique_ptr<InterpolableLength> blur_;
+ std::unique_ptr<InterpolableLength> spread_;
+ std::unique_ptr<InterpolableValue> color_;
+
+ ShadowStyle shadow_style_;
+};
+
+template <>
+struct DowncastTraits<InterpolableShadow> {
+ static bool AllowFrom(const InterpolableValue& interpolable_value) {
+ return interpolable_value.IsShadow();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_SHADOW_H_
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
new file mode 100644
index 00000000000..948ea14d091
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/animation/interpolable_transform_list.h"
+#include "third_party/blink/renderer/core/css/css_value.h"
+#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
+#include "third_party/blink/renderer/core/css/resolver/transform_builder.h"
+
+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) {
+ TransformOperations transform = TransformBuilder::CreateTransformOperations(
+ css_value, state->CssToLengthConversionData());
+ return std::make_unique<InterpolableTransformList>(std::move(transform));
+}
+
+void InterpolableTransformList::PreConcat(
+ const InterpolableTransformList& other) {
+ Vector<scoped_refptr<TransformOperation>> result;
+ result.ReserveCapacity(other.operations_.size() + operations_.size());
+ result.AppendVector(other.operations_.Operations());
+ result.AppendVector(operations_.Operations());
+ operations_.Operations() = result;
+}
+
+void InterpolableTransformList::Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const {
+ To<InterpolableTransformList>(result).operations_ =
+ To<InterpolableTransformList>(to).operations_.Blend(operations_,
+ progress);
+}
+
+void InterpolableTransformList::AssertCanInterpolateWith(
+ const InterpolableValue& other) const {
+ // We don't have to check the underlying TransformOperations, as Blend will
+ // take care of that and fall-back to discrete animation if needed.
+ DCHECK(other.IsTransformList());
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..d0ab3303223
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_transform_list.h
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_TRANSFORM_LIST_H_
+#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"
+
+namespace blink {
+
+class CSSValue;
+class StyleResolverState;
+
+// Represents a blink::TransformOperations, converted into a form that can be
+// interpolated from/to.
+class CORE_EXPORT InterpolableTransformList final : public InterpolableValue {
+ public:
+ InterpolableTransformList(TransformOperations&& operations)
+ : operations_(std::move(operations)) {}
+
+ static std::unique_ptr<InterpolableTransformList> Create(
+ TransformOperations&&);
+ static std::unique_ptr<InterpolableTransformList> ConvertCSSValue(
+ const CSSValue&,
+ const StyleResolverState*);
+
+ // Return the underlying TransformOperations. Usually called after composition
+ // and interpolation, to apply the results back to the style.
+ TransformOperations operations() const { return operations_; }
+
+ void PreConcat(const InterpolableTransformList&);
+
+ // InterpolableValue implementation:
+ void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const final;
+ bool IsTransformList() const final { return true; }
+ bool Equals(const InterpolableValue& other) const final {
+ NOTREACHED();
+ return false;
+ }
+ void Scale(double scale) final { NOTREACHED(); }
+ void Add(const InterpolableValue& other) final { NOTREACHED(); }
+ void AssertCanInterpolateWith(const InterpolableValue& other) const final;
+
+ private:
+ InterpolableTransformList* RawClone() const final {
+ return new InterpolableTransformList(TransformOperations(operations_));
+ }
+ InterpolableTransformList* RawCloneAndZero() const final {
+ NOTREACHED();
+ return nullptr;
+ }
+
+ TransformOperations operations_;
+};
+
+template <>
+struct DowncastTraits<InterpolableTransformList> {
+ static bool AllowFrom(const InterpolableValue& interpolable_value) {
+ return interpolable_value.IsTransformList();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_TRANSFORM_LIST_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolable_value.cc b/chromium/third_party/blink/renderer/core/animation/interpolable_value.cc
index 1f3c0ebce94..272c70dad4f 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_value.cc
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_value.cc
@@ -63,11 +63,11 @@ void InterpolableList::Interpolate(const InterpolableValue& to,
}
}
-std::unique_ptr<InterpolableValue> InterpolableList::CloneAndZero() const {
- auto result = std::make_unique<InterpolableList>(length());
+InterpolableList* InterpolableList::RawCloneAndZero() const {
+ auto* result = new InterpolableList(length());
for (wtf_size_t i = 0; i < length(); i++)
result->Set(i, values_[i]->CloneAndZero());
- return std::move(result);
+ return result;
}
void InterpolableNumber::Scale(double scale) {
@@ -79,9 +79,15 @@ void InterpolableList::Scale(double scale) {
values_[i]->Scale(scale);
}
-void InterpolableNumber::ScaleAndAdd(double scale,
- const InterpolableValue& other) {
- value_ = value_ * scale + ToInterpolableNumber(other).value_;
+void InterpolableNumber::Add(const InterpolableValue& other) {
+ value_ += ToInterpolableNumber(other).value_;
+}
+
+void InterpolableList::Add(const InterpolableValue& other) {
+ const InterpolableList& other_list = ToInterpolableList(other);
+ DCHECK_EQ(other_list.length(), length());
+ for (wtf_size_t i = 0; i < length(); i++)
+ values_[i]->Add(*other_list.values_[i]);
}
void InterpolableList::ScaleAndAdd(double scale,
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 8531e99d49f..2301fd0174f 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolable_value.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolable_value.h
@@ -23,59 +23,82 @@ class CORE_EXPORT InterpolableValue {
public:
virtual ~InterpolableValue() = default;
+ // Interpolates from |this| InterpolableValue towards |to| at the given
+ // |progress|, placing the output in |result|. That is:
+ //
+ // result = this * (1 - progress) + to * progress
+ //
+ // Callers must make sure that |this|, |to|, and |result| are all of the same
+ // concrete subclass.
+ virtual void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const = 0;
+
virtual bool IsNumber() const { return false; }
virtual bool IsBool() const { return false; }
virtual bool IsList() const { return false; }
virtual bool IsLength() const { return false; }
+ virtual bool IsShadow() const { return false; }
+ virtual bool IsFilter() const { return false; }
+ virtual bool IsTransformList() const { return false; }
// TODO(alancutter): Remove Equals().
virtual bool Equals(const InterpolableValue&) const = 0;
- virtual std::unique_ptr<InterpolableValue> Clone() const = 0;
- virtual std::unique_ptr<InterpolableValue> CloneAndZero() const = 0;
virtual void Scale(double scale) = 0;
- virtual void ScaleAndAdd(double scale, const InterpolableValue& other) = 0;
+ virtual void Add(const InterpolableValue& other) = 0;
+ // The default implementation should be sufficient for most types, but
+ // subclasses can override this to be more efficient if they chose.
+ virtual void ScaleAndAdd(double scale, const InterpolableValue& other) {
+ Scale(scale);
+ Add(other);
+ }
virtual void AssertCanInterpolateWith(
const InterpolableValue& other) const = 0;
- private:
- virtual void Interpolate(const InterpolableValue& to,
- const double progress,
- InterpolableValue& result) const = 0;
-
- friend class LegacyStyleInterpolation;
- friend class TransitionInterpolation;
- friend class PairwisePrimitiveInterpolation;
-
- // Keep interpolate private, but allow calls within the hierarchy without
- // knowledge of type.
- friend class InterpolableNumber;
- friend class InterpolableList;
+ // Clone this value, optionally zeroing out the components at the same time.
+ // These are not virtual to allow for covariant return types; see
+ // documentation on RawClone/RawCloneAndZero.
+ std::unique_ptr<InterpolableValue> Clone() const {
+ return std::unique_ptr<InterpolableValue>(RawClone());
+ }
+ std::unique_ptr<InterpolableValue> CloneAndZero() const {
+ return std::unique_ptr<InterpolableValue>(RawCloneAndZero());
+ }
- friend class AnimationInterpolableValueTest;
+ private:
+ // Helper methods to allow covariant Clone/CloneAndZero methods. Concrete
+ // subclasses should not expose these methods publically, but instead should
+ // declare their own version of Clone/CloneAndZero with a concrete return type
+ // if it is useful for their clients.
+ virtual InterpolableValue* RawClone() const = 0;
+ virtual InterpolableValue* RawCloneAndZero() const = 0;
};
class CORE_EXPORT InterpolableNumber final : public InterpolableValue {
public:
explicit InterpolableNumber(double value) : value_(value) {}
- bool IsNumber() const final { return true; }
double Value() const { return value_; }
- bool Equals(const InterpolableValue& other) const final;
- std::unique_ptr<InterpolableValue> Clone() const final {
- return std::make_unique<InterpolableNumber>(value_);
- }
- std::unique_ptr<InterpolableValue> CloneAndZero() const final {
- return std::make_unique<InterpolableNumber>(0);
- }
- void Scale(double scale) final;
- void ScaleAndAdd(double scale, const InterpolableValue& other) final;
void Set(double value) { value_ = value; }
- void AssertCanInterpolateWith(const InterpolableValue& other) const final;
- private:
+ // InterpolableValue
void Interpolate(const InterpolableValue& to,
const double progress,
InterpolableValue& result) const final;
+ bool IsNumber() const final { return true; }
+ bool Equals(const InterpolableValue& other) const final;
+ void Scale(double scale) final;
+ void Add(const InterpolableValue& other) final;
+ void AssertCanInterpolateWith(const InterpolableValue& other) const final;
+
+ private:
+ InterpolableNumber* RawClone() const final {
+ return new InterpolableNumber(value_);
+ }
+ InterpolableNumber* RawCloneAndZero() const final {
+ return new InterpolableNumber(0);
+ }
+
double value_;
};
@@ -96,10 +119,6 @@ class CORE_EXPORT InterpolableList : public InterpolableValue {
Set(i, other.values_[i]->Clone());
}
- bool IsList() const final { return true; }
- void Set(wtf_size_t position, std::unique_ptr<InterpolableValue> value) {
- values_[position] = std::move(value);
- }
const InterpolableValue* Get(wtf_size_t position) const {
return values_[position].get();
}
@@ -107,19 +126,27 @@ class CORE_EXPORT InterpolableList : public InterpolableValue {
return values_[position];
}
wtf_size_t length() const { return values_.size(); }
- bool Equals(const InterpolableValue& other) const final;
- std::unique_ptr<InterpolableValue> Clone() const final {
- return std::make_unique<InterpolableList>(*this);
+ void Set(wtf_size_t position, std::unique_ptr<InterpolableValue> value) {
+ values_[position] = std::move(value);
}
- std::unique_ptr<InterpolableValue> CloneAndZero() const final;
+
+ // InterpolableValue
+ void Interpolate(const InterpolableValue& to,
+ const double progress,
+ InterpolableValue& result) const final;
+ bool IsList() const final { return true; }
+ bool Equals(const InterpolableValue& other) const final;
void Scale(double scale) final;
+ void Add(const InterpolableValue& other) final;
+ // We override this to avoid two passes on the list from the base version.
void ScaleAndAdd(double scale, const InterpolableValue& other) final;
void AssertCanInterpolateWith(const InterpolableValue& other) const final;
private:
- void Interpolate(const InterpolableValue& to,
- const double progress,
- InterpolableValue& result) const final;
+ InterpolableList* RawClone() const final {
+ return new InterpolableList(*this);
+ }
+ InterpolableList* RawCloneAndZero() const final;
Vector<std::unique_ptr<InterpolableValue>> values_;
};
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation.h b/chromium/third_party/blink/renderer/core/animation/interpolation.h
index 2db04b42eea..32690db1cc1 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolation.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolation.h
@@ -57,8 +57,7 @@ namespace blink {
// The interpolation's effect at its current timing state is applied to the
// element. How this is done depends on the subclass of Interpolation. See
// the subclass documentation for more.
-class CORE_EXPORT Interpolation
- : public GarbageCollectedFinalized<Interpolation> {
+class CORE_EXPORT Interpolation : public GarbageCollected<Interpolation> {
public:
virtual ~Interpolation() {}
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h b/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h
index b8d5dfe79ca..d8e0e3ac450 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolation_effect.h
@@ -52,8 +52,8 @@ class CORE_EXPORT InterpolationEffect
void Trace(Visitor*);
private:
- class InterpolationRecord
- : public GarbageCollectedFinalized<InterpolationRecord> {
+ class InterpolationRecord final
+ : public GarbageCollected<InterpolationRecord> {
public:
InterpolationRecord(Interpolation* interpolation,
scoped_refptr<TimingFunction> easing,
diff --git a/chromium/third_party/blink/renderer/core/animation/interpolation_value.h b/chromium/third_party/blink/renderer/core/animation/interpolation_value.h
index 75c5d35488c..17ccf0242d0 100644
--- a/chromium/third_party/blink/renderer/core/animation/interpolation_value.h
+++ b/chromium/third_party/blink/renderer/core/animation/interpolation_value.h
@@ -27,11 +27,11 @@ struct InterpolationValue {
InterpolationValue(std::nullptr_t) {}
- InterpolationValue(InterpolationValue&& other) noexcept
+ InterpolationValue(InterpolationValue&& other)
: interpolable_value(std::move(other.interpolable_value)),
non_interpolable_value(std::move(other.non_interpolable_value)) {}
- void operator=(InterpolationValue&& other) noexcept {
+ void operator=(InterpolationValue&& other) {
interpolable_value = std::move(other.interpolable_value);
non_interpolable_value = std::move(other.non_interpolable_value);
}
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.h b/chromium/third_party/blink/renderer/core/animation/keyframe.h
index 928ac7410e2..9a084a56fe0 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe.h
@@ -60,7 +60,7 @@ class V8ObjectBuilder;
// from the keyframe effect. See KeyframeEffectModelBase::EnsureKeyframeGroups.
//
// FIXME: Make Keyframe immutable
-class CORE_EXPORT Keyframe : public GarbageCollectedFinalized<Keyframe> {
+class CORE_EXPORT Keyframe : public GarbageCollected<Keyframe> {
public:
virtual ~Keyframe() = default;
@@ -118,7 +118,7 @@ class CORE_EXPORT Keyframe : public GarbageCollectedFinalized<Keyframe> {
// Represents a property-specific keyframe as defined in the spec. Refer to
// the Keyframe class-level documentation for more details.
class CORE_EXPORT PropertySpecificKeyframe
- : public GarbageCollectedFinalized<PropertySpecificKeyframe> {
+ : public GarbageCollected<PropertySpecificKeyframe> {
public:
PropertySpecificKeyframe(double offset,
scoped_refptr<TimingFunction> easing,
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 aeae27bb70f..36c2d0c6aa4 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -140,10 +140,14 @@ String KeyframeEffect::composite() const {
void KeyframeEffect::setComposite(String composite_string) {
Model()->SetComposite(
EffectModel::StringToCompositeOperation(composite_string).value());
+
+ ClearEffects();
+ InvalidateAndNotifyOwner();
}
-Vector<ScriptValue> KeyframeEffect::getKeyframes(ScriptState* script_state) {
- Vector<ScriptValue> computed_keyframes;
+HeapVector<ScriptValue> KeyframeEffect::getKeyframes(
+ ScriptState* script_state) {
+ HeapVector<ScriptValue> computed_keyframes;
if (!model_->HasFrames())
return computed_keyframes;
@@ -384,16 +388,18 @@ void KeyframeEffect::ApplyEffects() {
GetAnimation()->CancelAnimationOnCompositor();
}
- double iteration = CurrentIteration();
- DCHECK_GE(iteration, 0);
+ base::Optional<double> iteration = CurrentIteration();
+ DCHECK(iteration);
+ DCHECK_GE(iteration.value(), 0);
bool changed = false;
if (sampled_effect_) {
- changed = model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
- SpecifiedTiming().IterationDuration(),
- sampled_effect_->MutableInterpolations());
+ changed =
+ model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
+ SpecifiedTiming().IterationDuration(),
+ sampled_effect_->MutableInterpolations());
} else {
HeapVector<Member<Interpolation>> interpolations;
- model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
+ model_->Sample(clampTo<int>(iteration.value(), 0), Progress().value(),
SpecifiedTiming().IterationDuration(), interpolations);
if (!interpolations.IsEmpty()) {
auto* sampled_effect =
@@ -469,7 +475,7 @@ void KeyframeEffect::DetachTarget(Animation* animation) {
ClearEffects();
}
-double KeyframeEffect::CalculateTimeToEffectChange(
+AnimationTimeDelta KeyframeEffect::CalculateTimeToEffectChange(
bool forwards,
double local_time,
double time_to_next_iteration) const {
@@ -482,34 +488,37 @@ double KeyframeEffect::CalculateTimeToEffectChange(
switch (GetPhase()) {
case Timing::kPhaseNone:
- return std::numeric_limits<double>::infinity();
+ return AnimationTimeDelta::Max();
case Timing::kPhaseBefore:
DCHECK_GE(start_time, local_time);
- return forwards ? start_time - local_time
- : std::numeric_limits<double>::infinity();
+ return forwards
+ ? AnimationTimeDelta::FromSecondsD(start_time - local_time)
+ : AnimationTimeDelta::Max();
case Timing::kPhaseActive:
if (forwards) {
// Need service to apply fill / fire events.
const double time_to_end = after_time - local_time;
if (RequiresIterationEvents()) {
- return std::min(time_to_end, time_to_next_iteration);
+ return AnimationTimeDelta::FromSecondsD(
+ std::min(time_to_end, time_to_next_iteration));
}
- return time_to_end;
+ return AnimationTimeDelta::FromSecondsD(time_to_end);
}
- return 0;
+ return {};
case Timing::kPhaseAfter:
DCHECK_GE(local_time, after_time);
if (forwards) {
// If an animation has a positive-valued end delay, we need an
// additional tick at the end time to ensure that the finished event is
// delivered.
- return end_time > local_time ? end_time - local_time
- : std::numeric_limits<double>::infinity();
+ return end_time > local_time
+ ? AnimationTimeDelta::FromSecondsD(end_time - local_time)
+ : AnimationTimeDelta::Max();
}
- return local_time - after_time;
+ return AnimationTimeDelta::FromSecondsD(local_time - after_time);
default:
NOTREACHED();
- return std::numeric_limits<double>::infinity();
+ return AnimationTimeDelta::Max();
}
}
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 5d43efc2fb5..595da68639f 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
@@ -81,7 +81,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void setTarget(Element*);
String composite() const;
void setComposite(String);
- Vector<ScriptValue> getKeyframes(ScriptState*);
+ HeapVector<ScriptValue> getKeyframes(ScriptState*);
void setKeyframes(ScriptState*,
const ScriptValue& keyframes,
ExceptionState&);
@@ -135,7 +135,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void Detach() override;
void AttachTarget(Animation*);
void DetachTarget(Animation*);
- double CalculateTimeToEffectChange(
+ AnimationTimeDelta CalculateTimeToEffectChange(
bool forwards,
double inherited_time,
double time_to_next_iteration) const override;
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 5c4d32e38a5..ef9b74ee02d 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
@@ -62,11 +62,8 @@ template <class K>
void KeyframeEffectModelBase::SetFrames(HeapVector<K>& keyframes) {
// TODO(samli): Should also notify/invalidate the animation
keyframes_.clear();
- keyframe_groups_ = nullptr;
- interpolation_effect_->Clear();
- last_fraction_ = std::numeric_limits<double>::quiet_NaN();
keyframes_.AppendVector(keyframes);
- needs_compositor_keyframes_snapshot_ = true;
+ ClearCachedData();
}
template CORE_EXPORT void KeyframeEffectModelBase::SetFrames(
@@ -74,6 +71,11 @@ template CORE_EXPORT void KeyframeEffectModelBase::SetFrames(
template CORE_EXPORT void KeyframeEffectModelBase::SetFrames(
HeapVector<Member<StringKeyframe>>& keyframes);
+void KeyframeEffectModelBase::SetComposite(CompositeOperation composite) {
+ composite_ = composite;
+ ClearCachedData();
+}
+
bool KeyframeEffectModelBase::Sample(
int iteration,
double fraction,
@@ -391,6 +393,13 @@ void KeyframeEffectModelBase::EnsureInterpolationEffectPopulated() const {
interpolation_effect_->SetPopulated();
}
+void KeyframeEffectModelBase::ClearCachedData() {
+ keyframe_groups_ = nullptr;
+ interpolation_effect_->Clear();
+ last_fraction_ = std::numeric_limits<double>::quiet_NaN();
+ needs_compositor_keyframes_snapshot_ = true;
+}
+
bool KeyframeEffectModelBase::IsReplaceOnly() const {
EnsureKeyframeGroups();
for (const auto& entry : *keyframe_groups_) {
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
index 2d2a2e60255..54224d18644 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.h
@@ -91,7 +91,7 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
void SetFrames(HeapVector<K>& keyframes);
CompositeOperation Composite() const { return composite_; }
- void SetComposite(CompositeOperation composite) { composite_ = composite; }
+ void SetComposite(CompositeOperation composite);
const PropertySpecificKeyframeVector* GetPropertySpecificKeyframes(
const PropertyHandle& property) const {
@@ -170,6 +170,9 @@ class CORE_EXPORT KeyframeEffectModelBase : public EffectModel {
void EnsureKeyframeGroups() const;
void EnsureInterpolationEffectPopulated() const;
+ // Clears the various bits of cached data that this class has.
+ void ClearCachedData();
+
using ShouldSnapshotPropertyCallback =
std::function<bool(const PropertyHandle&)>;
using ShouldSnapshotKeyframeCallback =
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
index c71c458d5bc..9cb0caa9cd9 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/core/css/property_registry.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/html/html_element.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -56,7 +57,9 @@ class AnimationKeyframeEffectModel : public PageTestBase {
protected:
void SetUp() override {
PageTestBase::SetUp(IntSize());
+ GetDocument().UpdateStyleAndLayoutTree();
element = GetDocument().CreateElementForBinding("foo");
+ GetDocument().body()->appendChild(element);
}
void ExpectLengthValue(double expected_value,
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 fbefcf795cb..2223f1590a2 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
@@ -110,7 +110,7 @@ TEST_F(AnimationKeyframeEffectV8Test, CanCreateAnAnimation) {
ScriptState* script_state = scope.GetScriptState();
NonThrowableExceptionState exception_state;
- Vector<ScriptValue> blink_keyframes = {
+ HeapVector<ScriptValue> blink_keyframes = {
V8ObjectBuilder(script_state)
.AddString("width", "100px")
.AddString("offset", "0")
@@ -123,7 +123,7 @@ TEST_F(AnimationKeyframeEffectV8Test, CanCreateAnAnimation) {
.GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
KeyframeEffect* animation =
@@ -168,7 +168,7 @@ TEST_F(AnimationKeyframeEffectV8Test, SetAndRetrieveEffectComposite) {
effect_options_dictionary, exception_state);
EXPECT_FALSE(exception_state.HadException());
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
KeyframeEffect* effect = CreateAnimationFromOption(
script_state, element.Get(), js_keyframes, effect_options_dictionary);
EXPECT_EQ("add", effect->composite());
@@ -176,10 +176,8 @@ TEST_F(AnimationKeyframeEffectV8Test, SetAndRetrieveEffectComposite) {
effect->setComposite("replace");
EXPECT_EQ("replace", effect->composite());
- // TODO(crbug.com/788440): Once accumulate is supported as a composite
- // property, setting it here should work.
effect->setComposite("accumulate");
- EXPECT_EQ("replace", effect->composite());
+ EXPECT_EQ("accumulate", effect->composite());
}
TEST_F(AnimationKeyframeEffectV8Test, KeyframeCompositeOverridesEffect) {
@@ -196,7 +194,7 @@ TEST_F(AnimationKeyframeEffectV8Test, KeyframeCompositeOverridesEffect) {
effect_options_dictionary, exception_state);
EXPECT_FALSE(exception_state.HadException());
- Vector<ScriptValue> blink_keyframes = {
+ HeapVector<ScriptValue> blink_keyframes = {
V8ObjectBuilder(script_state)
.AddString("width", "100px")
.AddString("composite", "replace")
@@ -204,7 +202,7 @@ TEST_F(AnimationKeyframeEffectV8Test, KeyframeCompositeOverridesEffect) {
V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};
ScriptValue js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
KeyframeEffect* effect = CreateAnimationFromOption(
@@ -222,7 +220,7 @@ TEST_F(AnimationKeyframeEffectV8Test, KeyframeCompositeOverridesEffect) {
TEST_F(AnimationKeyframeEffectV8Test, CanSetDuration) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
double duration = 2000;
KeyframeEffect* animation = CreateAnimationFromTiming(
@@ -235,7 +233,7 @@ TEST_F(AnimationKeyframeEffectV8Test, CanSetDuration) {
TEST_F(AnimationKeyframeEffectV8Test, CanOmitSpecifiedDuration) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
KeyframeEffect* animation =
CreateAnimation(script_state, element.Get(), js_keyframes);
EXPECT_FALSE(animation->SpecifiedTiming().iteration_duration);
@@ -244,7 +242,7 @@ TEST_F(AnimationKeyframeEffectV8Test, CanOmitSpecifiedDuration) {
TEST_F(AnimationKeyframeEffectV8Test, SpecifiedGetters) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
v8::Local<v8::Object> timing_input = v8::Object::New(scope.GetIsolate());
SetV8ObjectPropertyAsNumber(scope.GetIsolate(), timing_input, "delay", 2);
@@ -283,7 +281,7 @@ TEST_F(AnimationKeyframeEffectV8Test, SpecifiedGetters) {
TEST_F(AnimationKeyframeEffectV8Test, SpecifiedDurationGetter) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
v8::Local<v8::Object> timing_input_with_duration =
v8::Object::New(scope.GetIsolate());
@@ -331,7 +329,7 @@ TEST_F(AnimationKeyframeEffectV8Test, SetKeyframesAdditiveCompositeOperation) {
ScopedCSSAdditiveAnimationsForTest css_additive_animation(false);
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
- ScriptValue js_keyframes = ScriptValue::CreateNull(script_state);
+ ScriptValue js_keyframes = ScriptValue::CreateNull(scope.GetIsolate());
v8::Local<v8::Object> timing_input = v8::Object::New(scope.GetIsolate());
KeyframeEffectOptions* timing_input_dictionary =
KeyframeEffectOptions::Create();
@@ -349,11 +347,11 @@ TEST_F(AnimationKeyframeEffectV8Test, SetKeyframesAdditiveCompositeOperation) {
// But if we then setKeyframes with CSS-targeting keyframes, the composite
// should fallback to 'replace'.
- Vector<ScriptValue> blink_keyframes = {
+ HeapVector<ScriptValue> blink_keyframes = {
V8ObjectBuilder(script_state).AddString("width", "10px").GetScriptValue(),
V8ObjectBuilder(script_state).AddString("width", "0px").GetScriptValue()};
ScriptValue new_js_keyframes(
- script_state,
+ scope.GetIsolate(),
ToV8(blink_keyframes, scope.GetContext()->Global(), scope.GetIsolate()));
effect->setKeyframes(script_state, new_js_keyframes, exception_state);
ASSERT_FALSE(exception_state.HadException());
@@ -369,31 +367,37 @@ TEST_F(KeyframeEffectTest, TimeToEffectChange) {
auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
nullptr, CreateEmptyEffectModel(), timing);
Animation* animation = GetDocument().Timeline().Play(keyframe_effect);
- double inf = std::numeric_limits<double>::infinity();
// Beginning of the animation.
- EXPECT_EQ(100, keyframe_effect->TimeToForwardsEffectChange());
- EXPECT_EQ(inf, keyframe_effect->TimeToReverseEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
+ keyframe_effect->TimeToForwardsEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::Max(),
+ keyframe_effect->TimeToReverseEffectChange());
// End of the before phase.
animation->setCurrentTime(100000, false);
- EXPECT_EQ(100, keyframe_effect->TimeToForwardsEffectChange());
- EXPECT_EQ(0, keyframe_effect->TimeToReverseEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
+ keyframe_effect->TimeToForwardsEffectChange());
+ EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// Nearing the end of the active phase.
animation->setCurrentTime(199000, false);
- EXPECT_EQ(1, keyframe_effect->TimeToForwardsEffectChange());
- EXPECT_EQ(0, keyframe_effect->TimeToReverseEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
+ keyframe_effect->TimeToForwardsEffectChange());
+ EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// End of the active phase.
animation->setCurrentTime(200000, false);
- EXPECT_EQ(100, keyframe_effect->TimeToForwardsEffectChange());
- EXPECT_EQ(0, keyframe_effect->TimeToReverseEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
+ keyframe_effect->TimeToForwardsEffectChange());
+ EXPECT_EQ(AnimationTimeDelta(), keyframe_effect->TimeToReverseEffectChange());
// End of the animation.
animation->setCurrentTime(300000, false);
- EXPECT_EQ(inf, keyframe_effect->TimeToForwardsEffectChange());
- EXPECT_EQ(100, keyframe_effect->TimeToReverseEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::Max(),
+ keyframe_effect->TimeToForwardsEffectChange());
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(100),
+ keyframe_effect->TimeToReverseEffectChange());
}
TEST_F(KeyframeEffectTest, CheckCanStartAnimationOnCompositorNoKeyframes) {
diff --git a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.cc b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
index c23539d82b8..146f840c0e8 100644
--- a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
+++ b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
@@ -281,6 +281,27 @@ static void PadToSameLength(InterpolationValue& value,
NonInterpolableList::Create(std::move(new_non_interpolable_values));
}
+static bool InterpolableListsAreCompatible(
+ const InterpolableList& a,
+ const InterpolableList& b,
+ wtf_size_t length,
+ ListInterpolationFunctions::LengthMatchingStrategy length_matching_strategy,
+ ListInterpolationFunctions::InterpolableValuesAreCompatibleCallback
+ interpolable_values_are_compatible) {
+ for (wtf_size_t i = 0; i < length; i++) {
+ if (length_matching_strategy ==
+ ListInterpolationFunctions::LengthMatchingStrategy::
+ kLowestCommonMultiple ||
+ (i < a.length() && i < b.length())) {
+ if (!interpolable_values_are_compatible.Run(a.Get(i % a.length()),
+ b.Get(i % b.length()))) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
static bool NonInterpolableListsAreCompatible(
const NonInterpolableList& a,
const NonInterpolableList& b,
@@ -315,6 +336,7 @@ void ListInterpolationFunctions::Composite(
const InterpolationType& type,
const InterpolationValue& value,
LengthMatchingStrategy length_matching_strategy,
+ InterpolableValuesAreCompatibleCallback interpolable_values_are_compatible,
NonInterpolableValuesAreCompatibleCallback
non_interpolable_values_are_compatible,
CompositeItemCallback composite_item) {
@@ -346,10 +368,20 @@ void ListInterpolationFunctions::Composite(
return;
}
- const NonInterpolableList& non_interpolable_list =
- ToNonInterpolableList(*value.non_interpolable_value);
const wtf_size_t final_length =
MatchLengths(underlying_length, value_length, length_matching_strategy);
+
+ if (!InterpolableListsAreCompatible(
+ ToInterpolableList(
+ *underlying_value_owner.Value().interpolable_value),
+ interpolable_list, final_length, length_matching_strategy,
+ interpolable_values_are_compatible)) {
+ underlying_value_owner.Set(type, value);
+ return;
+ }
+
+ const NonInterpolableList& non_interpolable_list =
+ ToNonInterpolableList(*value.non_interpolable_value);
if (!NonInterpolableListsAreCompatible(
ToNonInterpolableList(
*underlying_value_owner.Value().non_interpolable_value),
diff --git a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.h b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.h
index a254bc415ca..1cd58ff70ef 100644
--- a/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.h
+++ b/chromium/third_party/blink/renderer/core/animation/list_interpolation_functions.h
@@ -49,6 +49,9 @@ class CORE_EXPORT ListInterpolationFunctions {
const InterpolationValue&,
EqualNonInterpolableValuesCallback);
+ using InterpolableValuesAreCompatibleCallback =
+ base::RepeatingCallback<bool(const InterpolableValue*,
+ const InterpolableValue*)>;
using NonInterpolableValuesAreCompatibleCallback =
base::RepeatingCallback<bool(const NonInterpolableValue*,
const NonInterpolableValue*)>;
@@ -62,9 +65,16 @@ class CORE_EXPORT ListInterpolationFunctions {
const InterpolationType&,
const InterpolationValue&,
LengthMatchingStrategy,
+ InterpolableValuesAreCompatibleCallback,
NonInterpolableValuesAreCompatibleCallback,
CompositeItemCallback);
+ // Used when the interpolable values are known to always be compatible.
+ static bool InterpolableValuesKnownCompatible(const InterpolableValue* a,
+ const InterpolableValue* b) {
+ return true;
+ }
+
// We are moving towards elimination of |NonInterpolableValue|, and expect
// more clients to assert no more usage with this function.
static bool VerifyNoNonInterpolableValues(const NonInterpolableValue* a,
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 01929f8f16a..23ac9fa3caa 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
@@ -105,6 +105,27 @@ InterpolationValue CreateNonInterpolableList(const Vector<int>& values) {
});
}
+// A simple helper to specify which InterpolableValues in an InterpolableList
+// should be considered compatible.
+class InterpolableValuesCompatibilityHelper {
+ public:
+ // The input |answers| vector must be at least as large as the
+ // InterpolableList being tested, or |AreCompatible| will DCHECK.
+ InterpolableValuesCompatibilityHelper(Vector<bool> answers)
+ : answers_(answers), current_index_(0) {}
+
+ // Callers should pass a reference to this function to
+ // ListInterpolationFunctions::Composite.
+ bool AreCompatible(const InterpolableValue*, const InterpolableValue*) {
+ DCHECK(current_index_ < answers_.size());
+ return answers_.at(current_index_++);
+ }
+
+ private:
+ Vector<bool> answers_;
+ wtf_size_t current_index_;
+};
+
bool NonInterpolableValuesAreCompatible(const NonInterpolableValue* a,
const NonInterpolableValue* b) {
return (a ? ToTestNonInterpolableValue(*a).GetValue() : 0) ==
@@ -193,6 +214,8 @@ TEST(ListInterpolationFunctionsTest, EqualCompositeSameLengths) {
ListInterpolationFunctions::Composite(
owner, 1.0, interpolation_type, list2,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
WTF::BindRepeating(NonInterpolableValuesAreCompatible),
WTF::BindRepeating(Composite));
@@ -218,6 +241,8 @@ TEST(ListInterpolationFunctionsTest, EqualCompositeDifferentLengths) {
ListInterpolationFunctions::Composite(
owner, 1.0, interpolation_type, list2,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
WTF::BindRepeating(NonInterpolableValuesAreCompatible),
WTF::BindRepeating(Composite));
@@ -230,7 +255,39 @@ TEST(ListInterpolationFunctionsTest, EqualCompositeDifferentLengths) {
// If one (or more) of the element pairs are incompatible, the list as a whole
// is non-interpolable. We expect the underlying value to be replaced.
-TEST(ListInterpolationFunctionsTest, EqualCompositeIncompatibleValues) {
+TEST(ListInterpolationFunctionsTest,
+ EqualCompositeIncompatibleInterpolableValues) {
+ auto list1 = CreateInterpolableList({1.0, 2.0, 3.0});
+ auto list2 = CreateInterpolableList({4.0, 5.0, 6.0});
+
+ InterpolableValuesCompatibilityHelper compatibility_helper(
+ {true, false, true});
+
+ PropertyHandle property_handle(GetCSSPropertyZIndex());
+ CSSNumberInterpolationType interpolation_type(property_handle);
+ UnderlyingValueOwner owner;
+ owner.Set(interpolation_type, std::move(list1));
+
+ ListInterpolationFunctions::Composite(
+ owner, 1.0, interpolation_type, list2,
+ ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(&InterpolableValuesCompatibilityHelper::AreCompatible,
+ WTF::Unretained(&compatibility_helper)),
+ WTF::BindRepeating(NonInterpolableValuesAreCompatible),
+ WTF::BindRepeating(Composite));
+
+ const auto& result = ToInterpolableList(*owner.Value().interpolable_value);
+
+ ASSERT_EQ(result.length(), 3u);
+ EXPECT_EQ(ToInterpolableNumber(result.Get(0))->Value(), 4.0);
+ EXPECT_EQ(ToInterpolableNumber(result.Get(1))->Value(), 5.0);
+ EXPECT_EQ(ToInterpolableNumber(result.Get(2))->Value(), 6.0);
+}
+
+// If one (or more) of the element pairs are incompatible, the list as a whole
+// is non-interpolable. We expect the underlying value to be replaced.
+TEST(ListInterpolationFunctionsTest,
+ EqualCompositeIncompatibleNonInterpolableValues) {
auto list1 = CreateInterpolableList({{1.0, 1}, {2.0, 2}, {3.0, 3}});
auto list2 = CreateInterpolableList({{4.0, 1}, {5.0, 4}, {6.0, 3}});
@@ -242,6 +299,8 @@ TEST(ListInterpolationFunctionsTest, EqualCompositeIncompatibleValues) {
ListInterpolationFunctions::Composite(
owner, 1.0, interpolation_type, list2,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
+ WTF::BindRepeating(
+ ListInterpolationFunctions::InterpolableValuesKnownCompatible),
WTF::BindRepeating(NonInterpolableValuesAreCompatible),
WTF::BindRepeating(Composite));
diff --git a/chromium/third_party/blink/renderer/core/animation/pairwise_interpolation_value.h b/chromium/third_party/blink/renderer/core/animation/pairwise_interpolation_value.h
index 39e6c57ebe8..87bb431032a 100644
--- a/chromium/third_party/blink/renderer/core/animation/pairwise_interpolation_value.h
+++ b/chromium/third_party/blink/renderer/core/animation/pairwise_interpolation_value.h
@@ -28,7 +28,7 @@ struct PairwiseInterpolationValue {
PairwiseInterpolationValue(std::nullptr_t) {}
- PairwiseInterpolationValue(PairwiseInterpolationValue&& other) noexcept
+ PairwiseInterpolationValue(PairwiseInterpolationValue&& other)
: start_interpolable_value(std::move(other.start_interpolable_value)),
end_interpolable_value(std::move(other.end_interpolable_value)),
non_interpolable_value(std::move(other.non_interpolable_value)) {}
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 86afd946a62..b3fd5373d25 100644
--- a/chromium/third_party/blink/renderer/core/animation/pending_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/pending_animations.h
@@ -59,7 +59,7 @@ class PaintArtifactCompositor;
// with compositor animations when both classes of CSS Animations are triggered
// by the same recalc.
class CORE_EXPORT PendingAnimations final
- : public GarbageCollectedFinalized<PendingAnimations> {
+ : public GarbageCollected<PendingAnimations> {
public:
explicit PendingAnimations(Document& document)
: timer_(document.GetTaskRunner(TaskType::kInternalDefault),
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 b35a6952194..48ac6f9b144 100644
--- a/chromium/third_party/blink/renderer/core/animation/sampled_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/sampled_effect.h
@@ -16,7 +16,7 @@ namespace blink {
// Associates the results of sampling an EffectModel with metadata used for
// effect ordering and managing composited animations.
-class SampledEffect : public GarbageCollectedFinalized<SampledEffect> {
+class SampledEffect final : public GarbageCollected<SampledEffect> {
public:
SampledEffect(KeyframeEffect*, unsigned sequence_number);
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 1c91e9f713b..90be56d6e6b 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -315,17 +315,6 @@ void ScrollTimeline::AnimationAttached(Animation*) {
return;
GetActiveScrollTimelineSet().insert(resolved_scroll_source_);
- if (auto* element = DynamicTo<Element>(resolved_scroll_source_.Get()))
- element->SetNeedsCompositingUpdate();
- resolved_scroll_source_->GetDocument()
- .GetLayoutView()
- ->Compositor()
- ->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
- LayoutBoxModelObject* object = scroll_source_->GetLayoutBoxModelObject();
- if (object && object->HasLayer())
- object->Layer()->SetNeedsCompositingInputsUpdate();
- if (object)
- object->SetNeedsPaintPropertyUpdate();
}
void ScrollTimeline::AnimationDetached(Animation*) {
@@ -333,19 +322,6 @@ void ScrollTimeline::AnimationDetached(Animation*) {
return;
GetActiveScrollTimelineSet().erase(resolved_scroll_source_);
- if (auto* element = DynamicTo<Element>(resolved_scroll_source_.Get()))
- element->SetNeedsCompositingUpdate();
- auto* layout_view = resolved_scroll_source_->GetDocument().GetLayoutView();
- if (layout_view && layout_view->Compositor()) {
- layout_view->Compositor()->SetNeedsCompositingUpdate(
- kCompositingUpdateRebuildTree);
-
- LayoutBoxModelObject* object = scroll_source_->GetLayoutBoxModelObject();
- if (object && object->HasLayer())
- object->Layer()->SetNeedsCompositingInputsUpdate();
- if (object)
- object->SetNeedsPaintPropertyUpdate();
- }
}
void ScrollTimeline::Trace(blink::Visitor* visitor) {
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 bbfc2fa6424..dec86d777b3 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -89,11 +89,6 @@ class CORE_EXPORT ScrollTimeline final : public AnimationTimeline {
void Trace(blink::Visitor*) override;
- // For the AnimationWorklet origin trial, we need to automatically composite
- // elements that are targets of ScrollTimelines (http://crbug.com/776533). We
- // expose a static lookup method to enable this.
- //
- // TODO(crbug.com/839341): Remove once WorkletAnimations can run on main.
static bool HasActiveScrollTimeline(Node* node);
private:
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 6e5bbe92422..beef1184689 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
@@ -20,49 +20,6 @@ class ScrollTimelineTest : public RenderingTest {
}
};
-TEST_F(ScrollTimelineTest,
- AttachingAndDetachingAnimationCausesCompositingUpdate) {
-
- SetBodyInnerHTML(R"HTML(
- <style>#scroller { overflow: scroll; width: 100px; height: 100px; }</style>
- <div id='scroller'></div>
- )HTML");
-
- LayoutBoxModelObject* scroller =
- ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"));
- ASSERT_TRUE(scroller);
-
- // Invariant: the scroller is not composited by default.
- EXPECT_EQ(DocumentLifecycle::kPaintClean,
- GetDocument().Lifecycle().GetState());
- EXPECT_EQ(kNotComposited, scroller->Layer()->GetCompositingState());
-
- // Create the ScrollTimeline. This shouldn't cause the scrollSource to need
- // compositing, as it isn't attached to any animation yet.
- ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
- DoubleOrScrollTimelineAutoKeyword time_range =
- DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
- options->setTimeRange(time_range);
- options->setScrollSource(GetElementById("scroller"));
- ScrollTimeline* scroll_timeline =
- ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
- EXPECT_EQ(DocumentLifecycle::kPaintClean,
- GetDocument().Lifecycle().GetState());
- EXPECT_EQ(kNotComposited, scroller->Layer()->GetCompositingState());
-
- // Now attach an animation. This should require a compositing update.
- scroll_timeline->AnimationAttached(nullptr);
-
- UpdateAllLifecyclePhasesForTest();
- EXPECT_NE(scroller->Layer()->GetCompositingState(), kNotComposited);
-
- // Now detach an animation. This should again require a compositing update.
- scroll_timeline->AnimationDetached(nullptr);
-
- UpdateAllLifecyclePhasesForTest();
- EXPECT_EQ(scroller->Layer()->GetCompositingState(), kNotComposited);
-}
-
TEST_F(ScrollTimelineTest, CurrentTimeIsNullIfScrollSourceIsNotScrollable) {
SetBodyInnerHTML(R"HTML(
<style>#scroller { width: 100px; height: 100px; }</style>
diff --git a/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.cc b/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.cc
deleted file mode 100644
index 5274b9f002f..00000000000
--- a/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/animation/shadow_interpolation_functions.h"
-
-#include <memory>
-#include "third_party/blink/renderer/core/animation/css_color_interpolation_type.h"
-#include "third_party/blink/renderer/core/animation/interpolable_length.h"
-#include "third_party/blink/renderer/core/animation/interpolation_value.h"
-#include "third_party/blink/renderer/core/animation/non_interpolable_value.h"
-#include "third_party/blink/renderer/core/animation/underlying_value.h"
-#include "third_party/blink/renderer/core/css/css_identifier_value.h"
-#include "third_party/blink/renderer/core/css/css_shadow_value.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
-#include "third_party/blink/renderer/core/style/shadow_data.h"
-#include "third_party/blink/renderer/platform/geometry/float_point.h"
-
-namespace blink {
-
-enum ShadowComponentIndex : unsigned {
- kShadowX,
- kShadowY,
- kShadowBlur,
- kShadowSpread,
- kShadowColor,
- kShadowComponentIndexCount,
-};
-
-class ShadowNonInterpolableValue : public NonInterpolableValue {
- public:
- ~ShadowNonInterpolableValue() final = default;
-
- static scoped_refptr<ShadowNonInterpolableValue> Create(
- ShadowStyle shadow_style) {
- return base::AdoptRef(new ShadowNonInterpolableValue(shadow_style));
- }
-
- ShadowStyle Style() const { return style_; }
-
- DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
-
- private:
- ShadowNonInterpolableValue(ShadowStyle shadow_style) : style_(shadow_style) {}
-
- ShadowStyle style_;
-};
-
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE(ShadowNonInterpolableValue);
-DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(ShadowNonInterpolableValue);
-
-bool ShadowInterpolationFunctions::NonInterpolableValuesAreCompatible(
- const NonInterpolableValue* a,
- const NonInterpolableValue* b) {
- return ToShadowNonInterpolableValue(*a).Style() ==
- ToShadowNonInterpolableValue(*b).Style();
-}
-
-PairwiseInterpolationValue ShadowInterpolationFunctions::MaybeMergeSingles(
- InterpolationValue&& start,
- InterpolationValue&& end) {
- if (!NonInterpolableValuesAreCompatible(start.non_interpolable_value.get(),
- end.non_interpolable_value.get()))
- return nullptr;
- return PairwiseInterpolationValue(std::move(start.interpolable_value),
- std::move(end.interpolable_value),
- std::move(start.non_interpolable_value));
-}
-
-InterpolationValue ShadowInterpolationFunctions::ConvertShadowData(
- const ShadowData& shadow_data,
- double zoom) {
- auto interpolable_list =
- std::make_unique<InterpolableList>(kShadowComponentIndexCount);
- interpolable_list->Set(
- kShadowX, InterpolableLength::CreatePixels(shadow_data.X() / zoom));
- interpolable_list->Set(
- kShadowY, InterpolableLength::CreatePixels(shadow_data.Y() / zoom));
- interpolable_list->Set(
- kShadowBlur, InterpolableLength::CreatePixels(shadow_data.Blur() / zoom));
- interpolable_list->Set(kShadowSpread, InterpolableLength::CreatePixels(
- shadow_data.Spread() / zoom));
- interpolable_list->Set(kShadowColor,
- CSSColorInterpolationType::CreateInterpolableColor(
- shadow_data.GetColor()));
- return InterpolationValue(
- std::move(interpolable_list),
- ShadowNonInterpolableValue::Create(shadow_data.Style()));
-}
-
-InterpolationValue ShadowInterpolationFunctions::MaybeConvertCSSValue(
- const CSSValue& value) {
- const auto* shadow = DynamicTo<CSSShadowValue>(value);
- if (!shadow)
- return nullptr;
-
- ShadowStyle style = kNormal;
- if (shadow->style) {
- if (shadow->style->GetValueID() == CSSValueID::kInset)
- style = kInset;
- else
- return nullptr;
- }
-
- auto interpolable_list =
- std::make_unique<InterpolableList>(kShadowComponentIndexCount);
- static_assert(kShadowX == 0, "Enum ordering check.");
- static_assert(kShadowY == 1, "Enum ordering check.");
- static_assert(kShadowBlur == 2, "Enum ordering check.");
- static_assert(kShadowSpread == 3, "Enum ordering check.");
- const CSSPrimitiveValue* lengths[] = {
- shadow->x.Get(),
- shadow->y.Get(),
- shadow->blur.Get(),
- shadow->spread.Get(),
- };
- for (wtf_size_t i = 0; i < base::size(lengths); i++) {
- if (lengths[i]) {
- InterpolationValue length_field(
- InterpolableLength::MaybeConvertCSSValue(*lengths[i]));
- if (!length_field)
- return nullptr;
- DCHECK(!length_field.non_interpolable_value);
- interpolable_list->Set(i, std::move(length_field.interpolable_value));
- } else {
- interpolable_list->Set(i, InterpolableLength::CreatePixels(0));
- }
- }
-
- if (shadow->color) {
- std::unique_ptr<InterpolableValue> interpolable_color =
- CSSColorInterpolationType::MaybeCreateInterpolableColor(*shadow->color);
- if (!interpolable_color)
- return nullptr;
- interpolable_list->Set(kShadowColor, std::move(interpolable_color));
- } else {
- interpolable_list->Set(kShadowColor,
- CSSColorInterpolationType::CreateInterpolableColor(
- StyleColor::CurrentColor()));
- }
-
- return InterpolationValue(std::move(interpolable_list),
- ShadowNonInterpolableValue::Create(style));
-}
-
-std::unique_ptr<InterpolableValue>
-ShadowInterpolationFunctions::CreateNeutralInterpolableValue() {
- return ConvertShadowData(ShadowData::NeutralValue(), 1).interpolable_value;
-}
-
-void ShadowInterpolationFunctions::Composite(
- UnderlyingValue& underlying_value,
- double underlying_fraction,
- const InterpolableValue& interpolable_value,
- const NonInterpolableValue* non_interpolable_value) {
- DCHECK(NonInterpolableValuesAreCompatible(
- underlying_value.GetNonInterpolableValue(), non_interpolable_value));
- InterpolableList& underlying_interpolable_list =
- ToInterpolableList(underlying_value.MutableInterpolableValue());
- const InterpolableList& interpolable_list =
- ToInterpolableList(interpolable_value);
- underlying_interpolable_list.ScaleAndAdd(underlying_fraction,
- interpolable_list);
-}
-
-ShadowData ShadowInterpolationFunctions::CreateShadowData(
- const InterpolableValue& interpolable_value,
- const NonInterpolableValue* non_interpolable_value,
- const StyleResolverState& state) {
- const InterpolableList& interpolable_list =
- ToInterpolableList(interpolable_value);
- const ShadowNonInterpolableValue& shadow_non_interpolable_value =
- ToShadowNonInterpolableValue(*non_interpolable_value);
- const CSSToLengthConversionData& conversion_data =
- state.CssToLengthConversionData();
- Length shadow_x = To<InterpolableLength>(*interpolable_list.Get(kShadowX))
- .CreateLength(conversion_data, kValueRangeAll);
- Length shadow_y = To<InterpolableLength>(*interpolable_list.Get(kShadowY))
- .CreateLength(conversion_data, kValueRangeAll);
- Length shadow_blur =
- To<InterpolableLength>(*interpolable_list.Get(kShadowBlur))
- .CreateLength(conversion_data, kValueRangeNonNegative);
- Length shadow_spread =
- To<InterpolableLength>(*interpolable_list.Get(kShadowSpread))
- .CreateLength(conversion_data, kValueRangeAll);
- DCHECK(shadow_x.IsFixed() && shadow_y.IsFixed() && shadow_blur.IsFixed() &&
- shadow_spread.IsFixed());
- return ShadowData(FloatPoint(shadow_x.Value(), shadow_y.Value()),
- shadow_blur.Value(), shadow_spread.Value(),
- shadow_non_interpolable_value.Style(),
- CSSColorInterpolationType::ResolveInterpolableColor(
- *interpolable_list.Get(kShadowColor), state));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.h b/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.h
deleted file mode 100644
index 7745390059e..00000000000
--- a/chromium/third_party/blink/renderer/core/animation/shadow_interpolation_functions.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SHADOW_INTERPOLATION_FUNCTIONS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SHADOW_INTERPOLATION_FUNCTIONS_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/animation/interpolation_value.h"
-#include "third_party/blink/renderer/core/animation/pairwise_interpolation_value.h"
-
-namespace blink {
-
-class ShadowData;
-class CSSValue;
-class StyleResolverState;
-class UnderlyingValue;
-
-class ShadowInterpolationFunctions {
- public:
- static InterpolationValue ConvertShadowData(const ShadowData&, double zoom);
- static InterpolationValue MaybeConvertCSSValue(const CSSValue&);
- static std::unique_ptr<InterpolableValue> CreateNeutralInterpolableValue();
- static bool NonInterpolableValuesAreCompatible(const NonInterpolableValue*,
- const NonInterpolableValue*);
- static PairwiseInterpolationValue MaybeMergeSingles(
- InterpolationValue&& start,
- InterpolationValue&& end);
- static void Composite(UnderlyingValue&,
- double underlying_fraction,
- const InterpolableValue&,
- const NonInterpolableValue*);
- static ShadowData CreateShadowData(const InterpolableValue&,
- const NonInterpolableValue*,
- const StyleResolverState&);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_SHADOW_INTERPOLATION_FUNCTIONS_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/size_interpolation_functions.cc b/chromium/third_party/blink/renderer/core/animation/size_interpolation_functions.cc
index b2b2ed6e3e5..a2fca4909be 100644
--- a/chromium/third_party/blink/renderer/core/animation/size_interpolation_functions.cc
+++ b/chromium/third_party/blink/renderer/core/animation/size_interpolation_functions.cc
@@ -56,48 +56,6 @@ class CSSSizeNonInterpolableValue : public NonInterpolableValue {
DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSSizeNonInterpolableValue);
DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(CSSSizeNonInterpolableValue);
-// TODO(xiaochengh): Clean up. With |InterpolableLength| introduced and
-// |LengthNonInterpolableValue| removed, the following no longer makes sense.
-//
-// A wrapper for the UnderlyingValue passed to
-// SizeInterpolationFunctions::Composite which can be forwarded to
-// LengthInterpolationFunctions::Composite.
-//
-// If LengthInterpolationFunctions::Composite calls SetNonInterpolableValue with
-// a new NonInterpolableValue, this class wraps it in a new
-// CSSSizeNonInterpolableValue before being set on the inner UnderlyingValue.
-class UnderlyingSizeAsLengthValue : public UnderlyingValue {
- STACK_ALLOCATED();
-
- public:
- UnderlyingSizeAsLengthValue(UnderlyingValue& inner_underlying_value)
- : inner_underlying_value_(inner_underlying_value) {}
-
- InterpolableValue& MutableInterpolableValue() final {
- return inner_underlying_value_.MutableInterpolableValue();
- }
-
- void SetInterpolableValue(
- std::unique_ptr<InterpolableValue> interpolable_value) final {
- inner_underlying_value_.SetInterpolableValue(std::move(interpolable_value));
- }
-
- const NonInterpolableValue* GetNonInterpolableValue() const final {
- const auto& size_non_interpolable_value = ToCSSSizeNonInterpolableValue(
- *inner_underlying_value_.GetNonInterpolableValue());
- return size_non_interpolable_value.LengthNonInterpolableValue();
- }
-
- void SetNonInterpolableValue(
- scoped_refptr<const NonInterpolableValue> non_interpolable_value) final {
- inner_underlying_value_.SetNonInterpolableValue(
- CSSSizeNonInterpolableValue::Create(std::move(non_interpolable_value)));
- }
-
- private:
- UnderlyingValue& inner_underlying_value_;
-};
-
static InterpolationValue ConvertKeyword(CSSValueID keyword) {
return InterpolationValue(std::make_unique<InterpolableList>(0),
CSSSizeNonInterpolableValue::Create(keyword));
@@ -204,9 +162,8 @@ void SizeInterpolationFunctions::Composite(
ToCSSSizeNonInterpolableValue(*non_interpolable_value);
if (size_non_interpolable_value.IsKeyword())
return;
- UnderlyingSizeAsLengthValue underlying_size_as_length(underlying_value);
- underlying_size_as_length.MutableInterpolableValue().ScaleAndAdd(
- underlying_fraction, interpolable_value);
+ underlying_value.MutableInterpolableValue().ScaleAndAdd(underlying_fraction,
+ interpolable_value);
}
static Length CreateLength(
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 6439f736f37..7d3be39bde9 100644
--- a/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/string_keyframe.cc
@@ -42,7 +42,7 @@ const CSSValue* GetOrCreateCSSValueFrom(
// which can be used to correctly serialize it given longhands that are
// present in this set.
return MakeGarbageCollected<CSSKeyframeShorthandValue>(
- property_value_set.ImmutableCopyIfNeeded());
+ property.PropertyID(), property_value_set.ImmutableCopyIfNeeded());
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/animation/timing.cc b/chromium/third_party/blink/renderer/core/animation/timing.cc
index ecbed772e00..ade75c7e56e 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing.cc
@@ -121,8 +121,11 @@ ComputedEffectTiming* Timing::getComputedTiming(
}
if (calculated_timing.is_in_effect) {
+ DCHECK(calculated_timing.current_iteration);
+ DCHECK(calculated_timing.progress);
computed_timing->setProgress(calculated_timing.progress.value());
- computed_timing->setCurrentIteration(calculated_timing.current_iteration);
+ computed_timing->setCurrentIteration(
+ calculated_timing.current_iteration.value());
} else {
computed_timing->setProgressToNull();
computed_timing->setCurrentIterationToNull();
@@ -152,12 +155,13 @@ ComputedEffectTiming* Timing::getComputedTiming(
Timing::CalculatedTiming Timing::CalculateTimings(
double local_time,
AnimationDirection animation_direction,
- bool is_keyframe_effect) const {
+ bool is_keyframe_effect,
+ base::Optional<double> playback_rate) const {
const double active_duration = ActiveDuration();
const Timing::Phase current_phase =
CalculatePhase(active_duration, local_time, animation_direction, *this);
- const double active_time =
+ const base::Optional<AnimationTimeDelta> active_time =
CalculateActiveTime(active_duration, ResolvedFillMode(is_keyframe_effect),
local_time, current_phase, *this);
@@ -171,7 +175,7 @@ Timing::CalculatedTiming Timing::CalculateTimings(
CalculateSimpleIterationProgress(current_phase, overall_progress,
iteration_start, active_time,
active_duration, iteration_count);
- const double current_iteration =
+ const base::Optional<double> current_iteration =
CalculateCurrentIteration(current_phase, active_time, iteration_count,
overall_progress, simple_iteration_progress);
const bool current_direction_is_forwards =
@@ -179,9 +183,9 @@ Timing::CalculatedTiming Timing::CalculateTimings(
const base::Optional<double> directed_progress = CalculateDirectedProgress(
simple_iteration_progress, current_iteration, direction);
- progress = CalculateTransformedProgress(
- current_phase, directed_progress, iteration_duration,
- current_direction_is_forwards, timing_function);
+ progress = CalculateTransformedProgress(current_phase, directed_progress,
+ current_direction_is_forwards,
+ timing_function);
double time_to_next_iteration = std::numeric_limits<double>::infinity();
// Conditionally compute the time to next iteration, which is only
@@ -190,14 +194,18 @@ Timing::CalculatedTiming Timing::CalculateTimings(
const double start_offset =
MultiplyZeroAlwaysGivesZero(iteration_start, iteration_duration);
DCHECK_GE(start_offset, 0);
- const base::Optional<double> offset_active_time =
+ const base::Optional<AnimationTimeDelta> offset_active_time =
CalculateOffsetActiveTime(active_duration, active_time, start_offset);
- const base::Optional<double> iteration_time = CalculateIterationTime(
- iteration_duration, active_duration, offset_active_time, start_offset,
- current_phase, *this);
+ const base::Optional<AnimationTimeDelta> iteration_time =
+ CalculateIterationTime(iteration_duration, active_duration,
+ offset_active_time, start_offset, current_phase,
+ *this);
if (iteration_time) {
- time_to_next_iteration = iteration_duration - iteration_time.value();
- if (active_duration - active_time < time_to_next_iteration)
+ // active_time cannot be null if iteration_time is not null.
+ DCHECK(active_time);
+ time_to_next_iteration =
+ iteration_duration - iteration_time->InSecondsF();
+ if (active_duration - active_time->InSecondsF() < time_to_next_iteration)
time_to_next_iteration = std::numeric_limits<double>::infinity();
}
}
@@ -206,10 +214,18 @@ Timing::CalculatedTiming Timing::CalculateTimings(
calculated.phase = current_phase;
calculated.current_iteration = current_iteration;
calculated.progress = progress;
- calculated.is_in_effect = !IsNull(active_time);
+ calculated.is_in_effect = active_time.has_value();
+ // If active_time is not null then current_iteration and (transformed)
+ // progress are also non-null).
+ DCHECK(!calculated.is_in_effect ||
+ (current_iteration.has_value() && progress.has_value()));
calculated.is_in_play = calculated.phase == Timing::kPhaseActive;
- calculated.is_current =
- calculated.phase == Timing::kPhaseBefore || calculated.is_in_play;
+ // https://drafts.csswg.org/web-animations-1/#current
+ calculated.is_current = calculated.is_in_play ||
+ (playback_rate.has_value() && playback_rate > 0 &&
+ calculated.phase == Timing::kPhaseBefore) ||
+ (playback_rate.has_value() && playback_rate < 0 &&
+ calculated.phase == Timing::kPhaseAfter);
calculated.local_time = local_time;
calculated.time_to_next_iteration = time_to_next_iteration;
diff --git a/chromium/third_party/blink/renderer/core/animation/timing.h b/chromium/third_party/blink/renderer/core/animation/timing.h
index 0a01bb55e74..0dafc87b92c 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing.h
@@ -135,22 +135,23 @@ struct CORE_EXPORT Timing {
struct CalculatedTiming {
DISALLOW_NEW();
Phase phase = Phase::kPhaseNone;
- double current_iteration = 0;
+ base::Optional<double> current_iteration = 0;
base::Optional<double> progress = 0;
bool is_current = false;
bool is_in_effect = false;
bool is_in_play = false;
double local_time = NullValue();
- double time_to_forwards_effect_change =
- std::numeric_limits<double>::infinity();
- double time_to_reverse_effect_change =
- std::numeric_limits<double>::infinity();
+ AnimationTimeDelta time_to_forwards_effect_change =
+ AnimationTimeDelta::Max();
+ AnimationTimeDelta time_to_reverse_effect_change =
+ AnimationTimeDelta::Max();
double time_to_next_iteration = std::numeric_limits<double>::infinity();
};
CalculatedTiming CalculateTimings(double local_time,
AnimationDirection animation_direction,
- bool is_keyframe_effect) const;
+ bool is_keyframe_effect,
+ base::Optional<double> playback_rate) const;
ComputedEffectTiming* getComputedTiming(const CalculatedTiming& calculated,
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 1ab2e77d282..d43104da761 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
+++ b/chromium/third_party/blink/renderer/core/animation/timing_calculations.h
@@ -94,34 +94,39 @@ static inline Timing::Phase CalculatePhase(double active_duration,
}
// https://drafts.csswg.org/web-animations/#calculating-the-active-time
-static inline double CalculateActiveTime(double active_duration,
- Timing::FillMode fill_mode,
- double local_time,
- Timing::Phase phase,
- const Timing& specified) {
+static inline base::Optional<AnimationTimeDelta> CalculateActiveTime(
+ double active_duration,
+ Timing::FillMode fill_mode,
+ double local_time,
+ Timing::Phase phase,
+ const Timing& specified) {
DCHECK_GE(active_duration, 0);
switch (phase) {
case Timing::kPhaseBefore:
if (fill_mode == Timing::FillMode::BACKWARDS ||
- fill_mode == Timing::FillMode::BOTH)
- return std::max(local_time - specified.start_delay, 0.0);
- return NullValue();
+ fill_mode == Timing::FillMode::BOTH) {
+ return AnimationTimeDelta::FromSecondsD(
+ std::max(local_time - specified.start_delay, 0.0));
+ }
+ return base::nullopt;
case Timing::kPhaseActive:
- return local_time - specified.start_delay;
+ return AnimationTimeDelta::FromSecondsD(local_time -
+ specified.start_delay);
case Timing::kPhaseAfter:
if (fill_mode == Timing::FillMode::FORWARDS ||
fill_mode == Timing::FillMode::BOTH) {
- return std::max(
- 0.0, std::min(active_duration, local_time - specified.start_delay));
+ return AnimationTimeDelta::FromSecondsD(std::max(
+ 0.0,
+ std::min(active_duration, local_time - specified.start_delay)));
}
- return NullValue();
+ return base::nullopt;
case Timing::kPhaseNone:
DCHECK(IsNull(local_time));
- return NullValue();
+ return base::nullopt;
default:
NOTREACHED();
- return NullValue();
+ return base::nullopt;
}
}
@@ -130,12 +135,12 @@ static inline double CalculateActiveTime(double active_duration,
// https://drafts.csswg.org/web-animations/#calculating-the-overall-progress
static inline base::Optional<double> CalculateOverallProgress(
Timing::Phase phase,
- double active_time,
+ base::Optional<AnimationTimeDelta> active_time,
double iteration_duration,
double iteration_count,
double iteration_start) {
// 1. If the active time is unresolved, return unresolved.
- if (IsNull(active_time))
+ if (!active_time)
return base::nullopt;
// 2. Calculate an initial value for overall progress.
@@ -144,7 +149,7 @@ static inline base::Optional<double> CalculateOverallProgress(
if (phase != Timing::kPhaseBefore)
overall_progress = iteration_count;
} else {
- overall_progress = active_time / iteration_duration;
+ overall_progress = active_time->InSecondsF() / iteration_duration;
}
return overall_progress + iteration_start;
@@ -160,7 +165,7 @@ static inline base::Optional<double> CalculateSimpleIterationProgress(
Timing::Phase phase,
base::Optional<double> overall_progress,
double iteration_start,
- double active_time,
+ base::Optional<AnimationTimeDelta> active_time,
double active_duration,
double iteration_count) {
// 1. If the overall progress is unresolved, return unresolved.
@@ -174,6 +179,10 @@ static inline base::Optional<double> CalculateSimpleIterationProgress(
? fmod(iteration_start, 1.0)
: fmod(overall_progress.value(), 1.0);
+ // active_time is not null is because overall_progress != null and
+ // CalculateOverallProgress() only returns null when active_time is null.
+ DCHECK(active_time);
+
// 3. If all of the following conditions are true,
// * the simple iteration progress calculated above is zero, and
// * the animation effect is in the active phase or the after phase, and
@@ -182,7 +191,7 @@ static inline base::Optional<double> CalculateSimpleIterationProgress(
// let the simple iteration progress be 1.0.
if (IsWithinEpsilon(simple_iteration_progress, 0.0) &&
(phase == Timing::kPhaseActive || phase == Timing::kPhaseAfter) &&
- IsWithinEpsilon(active_time, active_duration) &&
+ IsWithinEpsilon(active_time->InSecondsF(), active_duration) &&
!IsWithinEpsilon(iteration_count, 0.0)) {
simple_iteration_progress = 1.0;
}
@@ -192,15 +201,15 @@ static inline base::Optional<double> CalculateSimpleIterationProgress(
}
// https://drafts.csswg.org/web-animations/#calculating-the-current-iteration
-static inline double CalculateCurrentIteration(
+static inline base::Optional<double> CalculateCurrentIteration(
Timing::Phase phase,
- double active_time,
+ base::Optional<AnimationTimeDelta> active_time,
double iteration_count,
base::Optional<double> overall_progress,
base::Optional<double> simple_iteration_progress) {
// 1. If the active time is unresolved, return unresolved.
- if (IsNull(active_time))
- return NullValue();
+ if (!active_time)
+ return base::nullopt;
// 2. If the animation effect is in the after phase and the iteration count
// is infinity, return infinity.
@@ -209,7 +218,7 @@ static inline double CalculateCurrentIteration(
}
if (!overall_progress)
- return NullValue();
+ return base::nullopt;
// simple iteration progress can only be null if overall progress is null.
DCHECK(simple_iteration_progress);
@@ -227,12 +236,14 @@ static inline double CalculateCurrentIteration(
// https://drafts.csswg.org/web-animations/#calculating-the-directed-progress
static inline bool IsCurrentDirectionForwards(
- double current_iteration,
+ base::Optional<double> current_iteration,
Timing::PlaybackDirection direction) {
const bool current_iteration_is_even =
- std::isinf(current_iteration)
- ? true
- : IsWithinEpsilon(fmod(current_iteration, 2), 0);
+ !current_iteration
+ ? false
+ : (std::isinf(current_iteration.value())
+ ? true
+ : IsWithinEpsilon(fmod(current_iteration.value(), 2), 0));
switch (direction) {
case Timing::PlaybackDirection::NORMAL:
@@ -252,7 +263,7 @@ static inline bool IsCurrentDirectionForwards(
// https://drafts.csswg.org/web-animations/#calculating-the-directed-progress
static inline base::Optional<double> CalculateDirectedProgress(
base::Optional<double> simple_iteration_progress,
- double current_iteration,
+ base::Optional<double> current_iteration,
Timing::PlaybackDirection direction) {
// 1. If the simple progress is unresolved, return unresolved.
if (!simple_iteration_progress)
@@ -272,7 +283,6 @@ static inline base::Optional<double> CalculateDirectedProgress(
static inline base::Optional<double> CalculateTransformedProgress(
Timing::Phase phase,
base::Optional<double> directed_progress,
- double iteration_duration,
bool is_current_direction_forward,
scoped_refptr<TimingFunction> timing_function) {
if (!directed_progress)
@@ -308,23 +318,24 @@ static inline base::Optional<double> CalculateTransformedProgress(
// product of the iteration start and iteration duration). This is not part of
// the Web Animations spec; it is used for calculating the time until the next
// iteration to optimize scheduling.
-static inline base::Optional<double> CalculateOffsetActiveTime(
+static inline base::Optional<AnimationTimeDelta> CalculateOffsetActiveTime(
double active_duration,
- double active_time,
+ base::Optional<AnimationTimeDelta> active_time,
double start_offset) {
DCHECK_GE(active_duration, 0);
DCHECK_GE(start_offset, 0);
- if (IsNull(active_time))
+ if (!active_time)
return base::nullopt;
- DCHECK(active_time >= 0 &&
- LessThanOrEqualToWithinEpsilon(active_time, active_duration));
+ DCHECK(active_time.value() >= AnimationTimeDelta() &&
+ LessThanOrEqualToWithinEpsilon(active_time->InSecondsF(),
+ active_duration));
- if (!std::isfinite(active_time))
- return std::numeric_limits<double>::infinity();
+ if (active_time->is_max())
+ return AnimationTimeDelta::Max();
- return active_time + start_offset;
+ return active_time.value() + AnimationTimeDelta::FromSecondsD(start_offset);
}
// Maps the offset active time into 'iteration time space'[0], aka the offset
@@ -333,10 +344,10 @@ static inline base::Optional<double> CalculateOffsetActiveTime(
// the time until the next iteration to optimize scheduling.
//
// [0] https://drafts.csswg.org/web-animations-1/#iteration-time-space
-static inline base::Optional<double> CalculateIterationTime(
+static inline base::Optional<AnimationTimeDelta> CalculateIterationTime(
double iteration_duration,
double active_duration,
- base::Optional<double> offset_active_time,
+ base::Optional<AnimationTimeDelta> offset_active_time,
double start_offset,
Timing::Phase phase,
const Timing& specified) {
@@ -348,27 +359,29 @@ static inline base::Optional<double> CalculateIterationTime(
if (!offset_active_time)
return base::nullopt;
- DCHECK_GE(offset_active_time.value(), 0);
- DCHECK(LessThanOrEqualToWithinEpsilon(offset_active_time.value(),
+ DCHECK_GE(offset_active_time.value(), AnimationTimeDelta());
+ DCHECK(LessThanOrEqualToWithinEpsilon(offset_active_time->InSecondsF(),
active_duration + start_offset));
- if (!std::isfinite(offset_active_time.value()) ||
- (offset_active_time.value() - start_offset == active_duration &&
+ if (offset_active_time->is_max() ||
+ (offset_active_time->InSecondsF() - start_offset == active_duration &&
specified.iteration_count &&
EndsOnIterationBoundary(specified.iteration_count,
specified.iteration_start)))
- return iteration_duration;
+ return AnimationTimeDelta::FromSecondsD(iteration_duration);
- DCHECK(std::isfinite(offset_active_time.value()));
- double iteration_time = fmod(offset_active_time.value(), iteration_duration);
+ DCHECK(!offset_active_time->is_max());
+ double iteration_time =
+ fmod(offset_active_time->InSecondsF(), iteration_duration);
// This implements step 3 of
// https://drafts.csswg.org/web-animations/#calculating-the-simple-iteration-progress
if (iteration_time == 0 && phase == Timing::kPhaseAfter &&
- active_duration != 0 && offset_active_time != 0)
- return iteration_duration;
+ active_duration != 0 &&
+ offset_active_time.value() != AnimationTimeDelta())
+ return AnimationTimeDelta::FromSecondsD(iteration_duration);
- return iteration_time;
+ return AnimationTimeDelta::FromSecondsD(iteration_time);
}
} // namespace blink
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 3ff590d3f4e..71657a06d67 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
@@ -43,55 +43,62 @@ TEST(AnimationTimingCalculationsTest, ActiveTime) {
// Before Phase
timing.start_delay = 10;
- EXPECT_TRUE(IsNull(CalculateActiveTime(20, Timing::FillMode::FORWARDS, 0,
- Timing::kPhaseBefore, timing)));
- EXPECT_TRUE(IsNull(CalculateActiveTime(20, Timing::FillMode::NONE, 0,
- Timing::kPhaseBefore, timing)));
- EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
+ EXPECT_FALSE(CalculateActiveTime(20, Timing::FillMode::FORWARDS, 0,
Timing::kPhaseBefore, timing));
- EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
+ EXPECT_FALSE(CalculateActiveTime(20, Timing::FillMode::NONE, 0,
Timing::kPhaseBefore, timing));
+ EXPECT_EQ(AnimationTimeDelta(),
+ CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
+ Timing::kPhaseBefore, timing));
+ EXPECT_EQ(AnimationTimeDelta(),
+ CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
+ Timing::kPhaseBefore, timing));
timing.start_delay = -10;
- EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5,
- Timing::kPhaseBefore, timing));
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
+ CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5,
+ Timing::kPhaseBefore, timing));
// Active Phase
timing.start_delay = 10;
- EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
- Timing::kPhaseActive, timing));
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5),
+ CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
+ Timing::kPhaseActive, timing));
// After Phase
timing.start_delay = 10;
- EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
- Timing::kPhaseAfter, timing));
- EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
- Timing::kPhaseAfter, timing));
- EXPECT_TRUE(IsNull(CalculateActiveTime(21, Timing::FillMode::BACKWARDS, 45,
- Timing::kPhaseAfter, timing)));
- EXPECT_TRUE(IsNull(CalculateActiveTime(21, Timing::FillMode::NONE, 45,
- Timing::kPhaseAfter, timing)));
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
+ CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
+ Timing::kPhaseAfter, timing));
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21),
+ CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
+ Timing::kPhaseAfter, timing));
+ EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::BACKWARDS, 45,
+ Timing::kPhaseAfter, timing));
+ EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::NONE, 45,
+ Timing::kPhaseAfter, timing));
// None
- EXPECT_TRUE(IsNull(CalculateActiveTime(
- 32, Timing::FillMode::NONE, NullValue(), Timing::kPhaseNone, timing)));
+ EXPECT_FALSE(CalculateActiveTime(32, Timing::FillMode::NONE, NullValue(),
+ Timing::kPhaseNone, timing));
}
TEST(AnimationTimingCalculationsTest, OffsetActiveTime) {
// if the active time is null
- EXPECT_FALSE(CalculateOffsetActiveTime(4, NullValue(), 5));
+ EXPECT_FALSE(CalculateOffsetActiveTime(4, base::nullopt, 5));
// normal case
- EXPECT_EQ(15, CalculateOffsetActiveTime(40, 10, 5));
-
- // infinte activeTime
EXPECT_EQ(
- std::numeric_limits<double>::infinity(),
- CalculateOffsetActiveTime(std::numeric_limits<double>::infinity(),
- std::numeric_limits<double>::infinity(), 0));
+ AnimationTimeDelta::FromSecondsD(15),
+ CalculateOffsetActiveTime(40, AnimationTimeDelta::FromSecondsD(10), 5));
+
+ // infinite activeTime
+ EXPECT_TRUE(CalculateOffsetActiveTime(std::numeric_limits<double>::infinity(),
+ AnimationTimeDelta::Max(), 0)
+ ->is_max());
// Edge case for active_time being within epsilon of active_duration.
// https://crbug.com/962138
- const double active_time = 1.3435713716800004;
+ auto active_time = AnimationTimeDelta::FromSecondsD(1.3435713716800004);
const double active_duration = 1.3435713716800002;
EXPECT_EQ(active_time,
CalculateOffsetActiveTime(active_duration, active_time, 0));
@@ -109,18 +116,25 @@ TEST(AnimationTimingCalculationsTest, IterationTime) {
Timing::kPhaseActive, timing));
// if (complex-conditions)...
- EXPECT_EQ(
- 12, CalculateIterationTime(12, 12, 12, 0, Timing::kPhaseActive, timing));
+ EXPECT_EQ(AnimationTimeDelta::FromSecondsD(12),
+ CalculateIterationTime(12, 12, AnimationTimeDelta::FromSecondsD(12),
+ 0, Timing::kPhaseActive, timing));
// otherwise
timing.iteration_count = 10;
EXPECT_EQ(
- 5, CalculateIterationTime(10, 100, 25, 4, Timing::kPhaseActive, timing));
+ AnimationTimeDelta::FromSecondsD(5),
+ CalculateIterationTime(10, 100, AnimationTimeDelta::FromSecondsD(25), 4,
+ Timing::kPhaseActive, timing));
EXPECT_EQ(
- 7, CalculateIterationTime(11, 110, 29, 1, Timing::kPhaseActive, timing));
+ AnimationTimeDelta::FromSecondsD(7),
+ CalculateIterationTime(11, 110, AnimationTimeDelta::FromSecondsD(29), 1,
+ Timing::kPhaseActive, timing));
timing.iteration_start = 1.1;
EXPECT_EQ(
- 8, CalculateIterationTime(12, 120, 20, 7, Timing::kPhaseActive, timing));
+ AnimationTimeDelta::FromSecondsD(8),
+ CalculateIterationTime(12, 120, AnimationTimeDelta::FromSecondsD(20), 7,
+ Timing::kPhaseActive, timing));
// Edge case for offset_active_time being within epsilon of (active_duration
// + start_offset). https://crbug.com/962138
@@ -129,47 +143,52 @@ TEST(AnimationTimingCalculationsTest, IterationTime) {
const double iteration_duration = 1.3435713716800002;
const double active_duration = 1.3435713716800002;
EXPECT_NEAR(2.22045e-16,
- CalculateIterationTime(iteration_duration, active_duration,
- offset_active_time, 0,
- Timing::kPhaseActive, timing)
- .value(),
+ CalculateIterationTime(
+ iteration_duration, active_duration,
+ AnimationTimeDelta::FromSecondsD(offset_active_time), 0,
+ Timing::kPhaseActive, timing)
+ ->InSecondsF(),
std::numeric_limits<float>::epsilon());
}
TEST(AnimationTimingCalculationsTest, OverallProgress) {
// If the active time is null.
EXPECT_FALSE(CalculateOverallProgress(Timing::kPhaseAfter,
- /*active_time=*/NullValue(),
+ /*active_time=*/base::nullopt,
/*iteration_duration=*/1.0,
/*iteration_count=*/1.0,
/*iteration_start=*/1.0));
// If iteration duration is zero, calculate progress based on iteration count.
- EXPECT_EQ(3, CalculateOverallProgress(Timing::kPhaseActive,
- /*active_time=*/3.0,
- /*iteration_duration=*/0.0,
- /*iteration_count=*/3.0,
- /*iteration_start=*/0.0));
+ EXPECT_EQ(3, CalculateOverallProgress(
+ Timing::kPhaseActive,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+ /*iteration_duration=*/0.0,
+ /*iteration_count=*/3.0,
+ /*iteration_start=*/0.0));
// ...unless in before phase, in which case progress is zero.
- EXPECT_EQ(0, CalculateOverallProgress(Timing::kPhaseBefore,
- /*active_time=*/3.0,
- /*iteration_duration=*/0.0,
- /*iteration_count=*/3.0,
- /*iteration_start=*/0.0));
+ EXPECT_EQ(0, CalculateOverallProgress(
+ Timing::kPhaseBefore,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+ /*iteration_duration=*/0.0,
+ /*iteration_count=*/3.0,
+ /*iteration_start=*/0.0));
// Edge case for duration being within Epsilon of zero.
// crbug.com/954558
- EXPECT_EQ(1, CalculateOverallProgress(Timing::kPhaseActive,
- /*active_time=*/3.0,
- /*iteration_duration=*/1e-18,
- /*iteration_count=*/1.0,
- /*iteration_start=*/0.0));
+ EXPECT_EQ(1, CalculateOverallProgress(
+ Timing::kPhaseActive,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+ /*iteration_duration=*/1e-18,
+ /*iteration_count=*/1.0,
+ /*iteration_start=*/0.0));
// Otherwise.
- EXPECT_EQ(3.0, CalculateOverallProgress(Timing::kPhaseAfter,
- /*active_time=*/2.5,
- /*iteration_duration=*/1.0,
- /*iteration_count=*/0.0,
- /*iteration_start=*/0.5));
+ EXPECT_EQ(3.0, CalculateOverallProgress(
+ Timing::kPhaseAfter,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+ /*iteration_duration=*/1.0,
+ /*iteration_count=*/0.0,
+ /*iteration_start=*/0.5));
}
TEST(AnimationTimingCalculationsTest, CalculateSimpleIterationProgress) {
@@ -178,75 +197,80 @@ TEST(AnimationTimingCalculationsTest, CalculateSimpleIterationProgress) {
CalculateSimpleIterationProgress(Timing::kPhaseAfter,
/*overall_progress=*/base::nullopt,
/*iteration_start=*/1.0,
- /*active_time=*/NullValue(),
+ /*active_time=*/base::nullopt,
/*active_duration=*/1.0,
/*iteration_count=*/1.0));
// If the overall progress is infinite.
const double inf = std::numeric_limits<double>::infinity();
- EXPECT_EQ(0.5, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
- /*overall_progress=*/inf,
- /*iteration_start=*/1.5,
- /*active_time=*/0.0,
- /*active_duration=*/0.0,
- /*iteration_count=*/inf));
+ EXPECT_EQ(0.5, CalculateSimpleIterationProgress(
+ Timing::kPhaseAfter,
+ /*overall_progress=*/inf,
+ /*iteration_start=*/1.5,
+ /*active_time=*/AnimationTimeDelta(),
+ /*active_duration=*/0.0,
+ /*iteration_count=*/inf));
// Precisely on an iteration boundary.
- EXPECT_EQ(1.0, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
- /*overall_progress=*/3.0,
- /*iteration_start=*/0.0,
- /*active_time=*/3.0,
- /*active_duration=*/3.0,
- /*iteration_count=*/3.0));
+ EXPECT_EQ(1.0, CalculateSimpleIterationProgress(
+ Timing::kPhaseAfter,
+ /*overall_progress=*/3.0,
+ /*iteration_start=*/0.0,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+ /*active_duration=*/3.0,
+ /*iteration_count=*/3.0));
// Otherwise.
- EXPECT_EQ(0.5, CalculateSimpleIterationProgress(Timing::kPhaseAfter,
- /*overall_progress=*/2.5,
- /*iteration_start=*/0.0,
- /*active_time=*/2.5,
- /*active_duration=*/0.0,
- /*iteration_count=*/0.0));
+ EXPECT_EQ(0.5, CalculateSimpleIterationProgress(
+ Timing::kPhaseAfter,
+ /*overall_progress=*/2.5,
+ /*iteration_start=*/0.0,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+ /*active_duration=*/0.0,
+ /*iteration_count=*/0.0));
}
TEST(AnimationTimingCalculationsTest, CurrentIteration) {
// If the active time is null.
- EXPECT_TRUE(
- IsNull(CalculateCurrentIteration(Timing::kPhaseAfter,
- /*active_time=*/NullValue(),
- /*iteration_count=*/1.0,
- /*overall_progress=*/base::nullopt,
- /*simple_iteration_progress=*/0)));
+ EXPECT_FALSE(CalculateCurrentIteration(Timing::kPhaseAfter,
+ /*active_time=*/base::nullopt,
+ /*iteration_count=*/1.0,
+ /*overall_progress=*/base::nullopt,
+ /*simple_iteration_progress=*/0));
// If the iteration count is infinite.
const double inf = std::numeric_limits<double>::infinity();
- EXPECT_EQ(inf, CalculateCurrentIteration(Timing::kPhaseAfter,
- /*active_time=*/1.0,
- /*iteration_count=*/inf,
- /*overall_progress=*/inf,
- /*simple_iteration_progress=*/0.0));
+ EXPECT_EQ(inf, CalculateCurrentIteration(
+ Timing::kPhaseAfter,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(1.0),
+ /*iteration_count=*/inf,
+ /*overall_progress=*/inf,
+ /*simple_iteration_progress=*/0.0));
// Hold the endpoint of the final iteration of ending precisely on an
// iteration boundary.
- EXPECT_EQ(2, CalculateCurrentIteration(Timing::kPhaseAfter,
- /*active_time=*/3.0,
- /*iteration_count=*/3.0,
- /*overall_progress=*/3.0,
- /*simple_iteration_progress=*/1.0));
+ EXPECT_EQ(2, CalculateCurrentIteration(
+ Timing::kPhaseAfter,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0),
+ /*iteration_count=*/3.0,
+ /*overall_progress=*/3.0,
+ /*simple_iteration_progress=*/1.0));
// Edge case for zero-duration animation.
// crbug.com/954558
EXPECT_EQ(0, CalculateCurrentIteration(Timing::kPhaseAfter,
- /*active_time=*/0.0,
+ /*active_time=*/AnimationTimeDelta(),
/*iteration_count=*/1.0,
/*overall_progress=*/0.0,
/*simple_iteration_progress=*/1.0));
// Otherwise.
- EXPECT_EQ(2, CalculateCurrentIteration(Timing::kPhaseAfter,
- /*active_time=*/2.5,
- /*iteration_count=*/0.0,
- /*overall_progress=*/2.5,
- /*simple_iteration_progress=*/0.5));
+ EXPECT_EQ(2, CalculateCurrentIteration(
+ Timing::kPhaseAfter,
+ /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5),
+ /*iteration_count=*/0.0,
+ /*overall_progress=*/2.5,
+ /*simple_iteration_progress=*/0.5));
}
TEST(AnimationTimingCalculationsTest, IsCurrentDirectionForwards) {
@@ -276,7 +300,7 @@ TEST(AnimationTimingCalculationsTest, CalculateDirectedProgress) {
// direction);
// if the simple iteration progress is null
- EXPECT_FALSE(CalculateDirectedProgress(base::nullopt, NullValue(),
+ EXPECT_FALSE(CalculateDirectedProgress(base::nullopt, base::nullopt,
Timing::PlaybackDirection::NORMAL));
// forwards
@@ -318,7 +342,7 @@ TEST(AnimationTimingCalculationsTest, CalculateDirectedProgress) {
TEST(AnimationTimingCalculationsTest, TransformedProgress) {
// CalculateTransformedProgress(
- // phase, directed_progress, iteration_duraction,
+ // phase, directed_progress,
// is_current_direction_forward, timing_function)
scoped_refptr<TimingFunction> timing_function =
@@ -326,53 +350,53 @@ TEST(AnimationTimingCalculationsTest, TransformedProgress) {
// directed_progress is null.
EXPECT_FALSE(CalculateTransformedProgress(Timing::kPhaseActive, base::nullopt,
- 1, true, timing_function));
+ true, timing_function));
// At step boundaries.
// Forward direction.
- EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0, 1, true,
+ EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0, true,
timing_function));
- EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25, 1, true,
+ EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25, true,
timing_function));
- EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, 1,
- true, timing_function));
- EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, 1,
- true, timing_function));
- EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, 1, true,
+ EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, true,
+ timing_function));
+ EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, true,
+ timing_function));
+ EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, true,
timing_function));
- EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75, 1,
- true, timing_function));
- EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, 1,
- true, timing_function));
- EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 1, 1, true,
+ EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75, true,
+ timing_function));
+ EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, true,
+ timing_function));
+ EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 1, true,
timing_function));
- EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1, 1, true,
+ EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1, true,
timing_function));
// Reverse direction.
- EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseBefore, 1, 1, false,
+ EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseBefore, 1, false,
timing_function));
- EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 1, 1, false,
+ EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 1, false,
timing_function));
- EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75, 1,
+ EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75,
false, timing_function));
- EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, 1,
- false, timing_function));
- EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, 1,
- false, timing_function));
- EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, 1,
- false, timing_function));
- EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25, 1,
+ EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, false,
+ timing_function));
+ EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, false,
+ timing_function));
+ EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, false,
+ timing_function));
+ EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25,
false, timing_function));
- EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, 1, false,
+ EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, false,
timing_function));
// Edges cases
- EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1 - 1e-16, 1,
+ EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1 - 1e-16,
true, timing_function));
scoped_refptr<TimingFunction> step_start_timing_function =
StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::START);
- EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 1e-16, 1,
- false, step_start_timing_function));
+ EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 1e-16, false,
+ step_start_timing_function));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
index 0acfb2fb95b..8e49013398d 100644
--- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
+++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
@@ -33,7 +33,7 @@ class WorkletAnimationBase;
// For more details on AnimationWorklet, see the spec:
// https://wicg.github.io/animation-worklet
class CORE_EXPORT WorkletAnimationController
- : public GarbageCollectedFinalized<WorkletAnimationController>,
+ : public GarbageCollected<WorkletAnimationController>,
public MutatorClient {
public:
WorkletAnimationController(Document*);
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/BUILD.gn b/chromium/third_party/blink/renderer/core/animation_frame/BUILD.gn
new file mode 100644
index 00000000000..5d6265cbaec
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation_frame/BUILD.gn
@@ -0,0 +1,15 @@
+# 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/core/core.gni")
+
+blink_core_sources("animation_frame") {
+ sources = [
+ "worker_animation_frame_provider.cc",
+ "worker_animation_frame_provider.h",
+ ]
+ deps = [
+ "//mojo/public/cpp/bindings:bindings",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/OWNERS b/chromium/third_party/blink/renderer/core/animation_frame/OWNERS
new file mode 100644
index 00000000000..5ef87b1aa3f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation_frame/OWNERS
@@ -0,0 +1,4 @@
+fserb@chromium.org
+
+# TEAM: paint-dev@chromium.org
+# COMPONENT: Blink>Canvas
diff --git a/chromium/third_party/blink/renderer/core/animation_frame/README.md b/chromium/third_party/blink/renderer/core/animation_frame/README.md
new file mode 100644
index 00000000000..b47c5e0a87d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation_frame/README.md
@@ -0,0 +1,3 @@
+# animation frame
+
+This directory contains the implementation of the [animation frames](https://html.spec.whatwg.org/C/#animation-frames)
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
index eb9565e620c..6152182b7c0 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.cc
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
+#include "third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
namespace blink {
@@ -35,29 +36,37 @@ void WorkerAnimationFrameProvider::CancelCallback(int id) {
callback_collection_.CancelFrameCallback(id);
}
-void WorkerAnimationFrameProvider::BeginFrame() {
- // TODO(fserb): Remove this once the Mojo changes for scheduling are in.
- context_->GetTaskRunner(TaskType::kWorkerAnimation)
- ->PostTask(
- FROM_HERE,
- WTF::Bind(
- [](base::WeakPtr<WorkerAnimationFrameProvider> provider) {
- ExecutionContext* context = provider->context_;
- Performance* performance =
- WorkerGlobalScopePerformance::performance(
- *To<WorkerGlobalScope>(context));
- double time = performance->now();
- // We don't want to expose microseconds residues to users.
- time = round(time * 60) / 60;
+void WorkerAnimationFrameProvider::BeginFrame(const viz::BeginFrameArgs& args) {
+ TRACE_EVENT_WITH_FLOW0("blink", "WorkerAnimationFrameProvider::BeginFrame",
+ TRACE_ID_GLOBAL(args.trace_id),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
- provider->callback_collection_.ExecuteFrameCallbacks(time,
- time);
+ Microtask::EnqueueMicrotask(WTF::Bind(
+ [](base::WeakPtr<WorkerAnimationFrameProvider> provider,
+ const viz::BeginFrameArgs& args) {
+ if (!provider)
+ return;
+ TRACE_EVENT_WITH_FLOW0(
+ "blink", "WorkerAnimationFrameProvider::RequestAnimationFrame",
+ TRACE_ID_GLOBAL(args.trace_id), TRACE_EVENT_FLAG_FLOW_IN);
+ {
+ OffscreenCanvas::ScopedInsideWorkerRAF inside_raf_scope(args);
+ for (auto& offscreen_canvas : provider->offscreen_canvases_) {
+ // If one of the OffscreenCanvas has too many pending frames,
+ // we abort the whole process.
+ if (!inside_raf_scope.AddOffscreenCanvas(offscreen_canvas)) {
+ provider->begin_frame_provider_->FinishBeginFrame(args);
+ provider->begin_frame_provider_->RequestBeginFrame();
+ return;
+ }
+ }
- for (auto& offscreen_canvas : provider->offscreen_canvases_) {
- offscreen_canvas->PushFrameIfNeeded();
- }
- },
- weak_factory_.GetWeakPtr()));
+ double time = (args.frame_time - base::TimeTicks()).InMillisecondsF();
+ provider->callback_collection_.ExecuteFrameCallbacks(time, time);
+ }
+ provider->begin_frame_provider_->FinishBeginFrame(args);
+ },
+ weak_factory_.GetWeakPtr(), args));
}
void WorkerAnimationFrameProvider::RegisterOffscreenCanvas(
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
index b075b804f84..fdb656bd702 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
+++ b/chromium/third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_ANIMATION_FRAME_PROVIDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_ANIMATION_FRAME_PROVIDER_H_
+#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"
@@ -26,7 +26,7 @@ class OffscreenCanvas;
// OffscreenCanvas that is connected to a Canvas, and this class signals
// OffscreenCanvases when it's time to dispatch frames.
class CORE_EXPORT WorkerAnimationFrameProvider
- : public GarbageCollectedFinalized<WorkerAnimationFrameProvider>,
+ : public GarbageCollected<WorkerAnimationFrameProvider>,
public BeginFrameProviderClient {
public:
WorkerAnimationFrameProvider(
@@ -39,8 +39,7 @@ class CORE_EXPORT WorkerAnimationFrameProvider
void Trace(blink::Visitor* visitor);
// BeginFrameProviderClient
- void BeginFrame() override;
- bool InBeginFrame() const;
+ void BeginFrame(const viz::BeginFrameArgs&) override;
void RegisterOffscreenCanvas(OffscreenCanvas*);
void DeregisterOffscreenCanvas(OffscreenCanvas*);
@@ -55,7 +54,6 @@ class CORE_EXPORT WorkerAnimationFrameProvider
// To avoid leaking OffscreenCanvas objects, the following vector must
// not hold strong references.
Vector<UntracedMember<OffscreenCanvas>> offscreen_canvases_;
- bool in_begin_frame_;
Member<ExecutionContext> context_;
@@ -64,4 +62,4 @@ class CORE_EXPORT WorkerAnimationFrameProvider
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_ANIMATION_FRAME_PROVIDER_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FRAME_WORKER_ANIMATION_FRAME_PROVIDER_H_
diff --git a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
index 5a4ab9917a9..ef81643b71e 100644
--- a/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
@@ -22,7 +22,7 @@ class Document;
class ScriptState;
class ComputedAccessibleNodePromiseResolver final
- : public GarbageCollectedFinalized<ComputedAccessibleNodePromiseResolver> {
+ : public GarbageCollected<ComputedAccessibleNodePromiseResolver> {
public:
ComputedAccessibleNodePromiseResolver(ScriptState*, Element&);
~ComputedAccessibleNodePromiseResolver() {}
diff --git a/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn b/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
index 7c0e8dd8de7..ac9cff9c19a 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
@@ -31,10 +31,6 @@ blink_core_sources("clipboard") {
if (is_win) {
sources += [ "clipboard_utilities_win.cc" ]
}
-
- deps = [
- "//ui/gfx/codec",
- ]
}
blink_core_tests("unit_tests") {
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_object.h b/chromium/third_party/blink/renderer/core/clipboard/data_object.h
index f1fdcd3b6a0..3e666e2eee1 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_object.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_object.h
@@ -50,7 +50,7 @@ enum class PasteMode;
// A data object for holding data that would be in a clipboard or moved
// during a drag-n-drop operation. This is the data that WebCore is aware
// of and is not specific to a platform.
-class CORE_EXPORT DataObject : public GarbageCollectedFinalized<DataObject>,
+class CORE_EXPORT DataObject : public GarbageCollected<DataObject>,
public Supplementable<DataObject> {
USING_GARBAGE_COLLECTED_MIXIN(DataObject);
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 0b4a308f9b5..74fc71918cc 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
@@ -34,8 +34,8 @@
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
-#include "ui/gfx/codec/png_codec.h"
namespace blink {
@@ -135,18 +135,28 @@ File* DataObjectItem::GetAsFile() const {
DCHECK_EQ(source_, kClipboardSource);
if (GetType() == kMimeTypeImagePng) {
- SkBitmap image = SystemClipboard::GetInstance().ReadImage(
+ SkBitmap bitmap = SystemClipboard::GetInstance().ReadImage(
mojom::ClipboardBuffer::kStandard);
- std::vector<unsigned char> png_data;
- if (gfx::PNGCodec::FastEncodeBGRASkBitmap(image, false, &png_data)) {
- 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 File::Create("image.png", base::Time::Now().ToDoubleT() * 1000.0,
- std::move(blob));
- }
+
+ 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;
+
+ 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 File::Create("image.png", base::Time::Now().ToDoubleT() * 1000.0,
+ std::move(blob));
}
return nullptr;
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 82a11c42be5..07f92814f06 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
@@ -40,8 +40,8 @@
namespace blink {
-class CORE_EXPORT DataObjectItem
- : public GarbageCollectedFinalized<DataObjectItem> {
+class CORE_EXPORT DataObjectItem final
+ : public GarbageCollected<DataObjectItem> {
public:
enum ItemKind { kStringKind, kFileKind };
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 b7160ec51b2..d8874555064 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -67,7 +67,7 @@ class DraggedNodeImageBuilder {
STACK_ALLOCATED();
public:
- DraggedNodeImageBuilder(const LocalFrame& local_frame, Node& node)
+ DraggedNodeImageBuilder(LocalFrame& local_frame, Node& node)
: local_frame_(&local_frame),
node_(&node)
#if DCHECK_IS_ON()
@@ -148,7 +148,7 @@ class DraggedNodeImageBuilder {
}
private:
- const Member<const LocalFrame> local_frame_;
+ const Member<LocalFrame> local_frame_;
const Member<Node> node_;
#if DCHECK_IS_ON()
const uint64_t dom_tree_version_;
@@ -383,7 +383,7 @@ FloatSize DataTransfer::DeviceSpaceSize(const FloatSize& css_size,
// Returns a DragImage whose bitmap contains |contents|, positioned and scaled
// in device space.
std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
- const LocalFrame& frame,
+ LocalFrame& frame,
float opacity,
RespectImageOrientationEnum image_orientation,
const FloatSize& css_size,
@@ -414,8 +414,9 @@ std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
scoped_refptr<Image> image =
StaticBitmapImage::Create(surface->makeImageSnapshot());
+ ChromeClient& chrome_client = frame.GetPage()->GetChromeClient();
float screen_device_scale_factor =
- frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+ chrome_client.GetScreenInfo(frame).device_scale_factor;
return DragImage::Create(image.get(), image_orientation,
screen_device_scale_factor, kInterpolationDefault,
@@ -423,7 +424,7 @@ std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
}
// static
-std::unique_ptr<DragImage> DataTransfer::NodeImage(const LocalFrame& frame,
+std::unique_ptr<DragImage> DataTransfer::NodeImage(LocalFrame& frame,
Node& node) {
DraggedNodeImageBuilder image_node(frame, node);
return image_node.CreateImage();
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.h b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.h
index 08ef14c9612..67d3be7239a 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.h
@@ -149,14 +149,14 @@ class CORE_EXPORT DataTransfer final : public ScriptWrappable,
// |paint_offset| is the offset from the origin of the dragged
// object of the PaintRecordBuilder.
static std::unique_ptr<DragImage> CreateDragImageForFrame(
- const LocalFrame&,
+ LocalFrame&,
float,
RespectImageOrientationEnum,
const FloatSize& css_size,
const FloatPoint& paint_offset,
PaintRecordBuilder&,
const PropertyTreeState&);
- static std::unique_ptr<DragImage> NodeImage(const LocalFrame&, Node&);
+ static std::unique_ptr<DragImage> NodeImage(LocalFrame&, Node&);
void Trace(blink::Visitor*) override;
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 432ccc8307b..601ec0d8971 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
-#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_manager.h b/chromium/third_party/blink/renderer/core/content_capture/content_capture_manager.h
index d38c5a0544c..9d374aa9777 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_manager.h
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_manager.h
@@ -19,7 +19,7 @@ class SentNodes;
// This class is used to create the NodeHolder, and start the ContentCaptureTask
// when necessary. The ContentCaptureManager is owned by main frame.
class CORE_EXPORT ContentCaptureManager
- : public GarbageCollectedFinalized<ContentCaptureManager> {
+ : public GarbageCollected<ContentCaptureManager> {
public:
explicit ContentCaptureManager(LocalFrame& local_frame_root);
virtual ~ContentCaptureManager();
diff --git a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
index a6d0a07a93e..f8b7517a6c1 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
+++ b/chromium/third_party/blink/renderer/core/content_capture/content_capture_task.cc
@@ -196,7 +196,7 @@ bool ContentCaptureTask::RunInternal() {
}
void ContentCaptureTask::Run(TimerBase*) {
- TRACE_EVENT0("blink", "CaptureContentTask::Run");
+ TRACE_EVENT0("content_capture", "RunTask");
is_scheduled_ = false;
if (!RunInternal()) {
ScheduleInternal(ScheduleReason::kRetryTask);
@@ -229,6 +229,8 @@ void ContentCaptureTask::ScheduleInternal(ScheduleReason reason) {
delay_task_->StartOneShot(delay, FROM_HERE);
is_scheduled_ = true;
+ TRACE_EVENT_INSTANT1("content_capture", "ScheduleTask",
+ TRACE_EVENT_SCOPE_THREAD, "reason", reason);
}
void ContentCaptureTask::Schedule(ScheduleReason reason) {
diff --git a/chromium/third_party/blink/renderer/core/content_capture/sent_nodes.h b/chromium/third_party/blink/renderer/core/content_capture/sent_nodes.h
index 194b29a8569..17ea8e54e15 100644
--- a/chromium/third_party/blink/renderer/core/content_capture/sent_nodes.h
+++ b/chromium/third_party/blink/renderer/core/content_capture/sent_nodes.h
@@ -15,7 +15,7 @@ class Node;
// The class manages a list of nodes that have been sent, is only used when
// kNodeID is used, see WebContentCaptureClient::GetNodeType().
-class SentNodes : public GarbageCollectedFinalized<SentNodes> {
+class SentNodes final : public GarbageCollected<SentNodes> {
public:
bool HasSent(const Node& node);
void OnSent(const Node& node);
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 e648a52f396..80c2864c079 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
@@ -37,13 +37,13 @@ class SentNodes;
// ContentCaptureTask gets the data per document by using
// GetUnsentDocumentSession() and GetNextUnsentNode(), and must send
// all data out before capturing on-screen content again.
-class TaskSession : public GarbageCollectedFinalized<TaskSession> {
+class TaskSession final : public GarbageCollected<TaskSession> {
public:
// This class manages the captured content and the detached nodes per
// document, the data is moved to the ContentCaptureTask while required. This
// class has an instance per document, will be released while the associated
// document is GC-ed, see TaskSession::to_document_session_.
- class DocumentSession : public GarbageCollectedFinalized<DocumentSession> {
+ class DocumentSession final : public GarbageCollected<DocumentSession> {
public:
// The callback for total_sent_nodes_ metrics.
using SentNodeCountCallback = base::RepeatingCallback<void(size_t)>;
diff --git a/chromium/third_party/blink/renderer/core/context_features/context_feature_settings.h b/chromium/third_party/blink/renderer/core/context_features/context_feature_settings.h
index 8ef606eac10..7e4ab3ad257 100644
--- a/chromium/third_party/blink/renderer/core/context_features/context_feature_settings.h
+++ b/chromium/third_party/blink/renderer/core/context_features/context_feature_settings.h
@@ -17,7 +17,7 @@ class ExecutionContext;
// pertaining to the enabled/disabled state of any platform API features which
// are gated behind a ContextEnabled extended attribute in IDL.
class CORE_EXPORT ContextFeatureSettings final
- : public GarbageCollectedFinalized<ContextFeatureSettings>,
+ : public GarbageCollected<ContextFeatureSettings>,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(ContextFeatureSettings);
diff --git a/chromium/third_party/blink/renderer/core/core.gni b/chromium/third_party/blink/renderer/core/core.gni
index 97f02c4c967..b7df7c9e685 100644
--- a/chromium/third_party/blink/renderer/core/core.gni
+++ b/chromium/third_party/blink/renderer/core/core.gni
@@ -4,7 +4,6 @@
import("//build/config/chrome_build.gni")
import("//build/config/jumbo.gni")
-import("//build/split_static_library.gni")
import("//third_party/blink/renderer/config.gni")
blink_core_output_dir = "$root_gen_dir/third_party/blink/renderer/core"
@@ -33,22 +32,9 @@ if (is_win && is_official_build) {
core_config_remove += [ "//build/config/compiler:default_symbols" ]
core_config_add += blink_symbols_config
-# Use this target type to link core targets.
-if (is_component_build) {
- # To get exported symbols correct in component builds, the files must be in
- # source sets.
- core_link_large_target_type = "source_set"
- core_link_small_target_type = "source_set"
-} else {
- # In static builds some of the libraries can get >2GB on Windows so we need
- # to split the targets for the larger ones.
- core_link_large_target_type = "split_static_library"
- core_link_small_target_type = "static_library"
-}
-
# Use this to generate a static library or source set that gets linked into
-# "core". This will either be a source_set (component build), a static library
-# (split_count undefined) or a split static library (split_count defined).
+# "core". This will either be a source_set (component build), or a static
+# library.
#
# Special values (all unlisted values are forwarded to the underlying library):
#
@@ -59,12 +45,6 @@ if (is_component_build) {
# into account: just modify the configs as normal for target-specific
# overrides (or don't touch it).
#
-# split_count
-# If defined, non-component builds will generate this number of static
-# libraries by splitting the sources. This is for use on Windows where the
-# maximum static library size is 2GB, and 64-bit builds with full symbols
-# can exceed this if there are many sources.
-#
# deps
# Normal meaning but "core:prerequisites" target is always added. Callers
# shouldn't list prerequisites as a dependency.
@@ -74,23 +54,14 @@ if (is_component_build) {
template("blink_core_sources") {
if (is_component_build) {
target_type = "jumbo_source_set"
-
- # This assert avoids an unused variable warning.
- assert(!defined(invoker.split_count) || invoker.split_count != 0)
- } else if (!defined(invoker.split_count)) {
- target_type = "jumbo_static_library"
} else {
- target_type = "jumbo_split_static_library"
+ target_type = "jumbo_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/core/*" ]
- if (target_type == "jumbo_split_static_library") {
- split_count = invoker.split_count
- }
-
deps = [
"//third_party/blink/renderer/core:prerequisites",
]
@@ -111,7 +82,6 @@ template("blink_core_sources") {
[
"deps",
"public_deps",
- "split_count",
])
}
}
diff --git a/chromium/third_party/blink/renderer/core/core_idl_files.gni b/chromium/third_party/blink/renderer/core/core_idl_files.gni
index 1411e9e2fa1..c2180f4a342 100644
--- a/chromium/third_party/blink/renderer/core/core_idl_files.gni
+++ b/chromium/third_party/blink/renderer/core/core_idl_files.gni
@@ -51,7 +51,6 @@ core_idl_files =
"clipboard/data_transfer_item_list.idl",
"css/css_condition_rule.idl",
"css/css_font_face_rule.idl",
- "css/css_font_feature_values_rule.idl",
"css/css_grouping_rule.idl",
"css/css_import_rule.idl",
"css/css_keyframe_rule.idl",
@@ -105,7 +104,6 @@ core_idl_files =
"css/cssom/style_property_map.idl",
"css/cssom/style_property_map_read_only.idl",
"display_lock/before_activate_event.idl",
- "display_lock/display_lock_context.idl",
"dom/abort_controller.idl",
"dom/abort_signal.idl",
"dom/attr.idl",
@@ -165,7 +163,6 @@ core_idl_files =
"events/page_transition_event.idl",
"events/pointer_event.idl",
"events/pop_state_event.idl",
- "events/portal_activate_event.idl",
"events/progress_event.idl",
"events/promise_rejection_event.idl",
"events/resource_progress_event.idl",
@@ -190,6 +187,7 @@ core_idl_files =
"frame/deprecation_report_body.idl",
"frame/external.idl",
"frame/feature_policy_violation_report_body.idl",
+ "frame/fragment_directive.idl",
"frame/history.idl",
"frame/intervention_report_body.idl",
"frame/location.idl",
@@ -291,6 +289,7 @@ core_idl_files =
"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/track/audio_track_list.idl",
"html/track/html_track_element.idl",
@@ -600,6 +599,7 @@ core_dictionary_idl_files =
"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",
@@ -624,7 +624,6 @@ core_dictionary_idl_files =
"dom/events/event_init.idl",
"dom/events/event_listener_options.idl",
"dom/events/event_modifier_init.idl",
- "display_lock/display_lock_options.idl",
"events/animation_event_init.idl",
"events/animation_playback_event_init.idl",
"events/application_cache_error_event_init.idl",
@@ -642,7 +641,6 @@ core_dictionary_idl_files =
"events/page_transition_event_init.idl",
"events/pointer_event_init.idl",
"events/pop_state_event_init.idl",
- "events/portal_activate_event_init.idl",
"events/progress_event_init.idl",
"events/promise_rejection_event_init.idl",
"events/security_policy_violation_event_init.idl",
@@ -673,6 +671,7 @@ core_dictionary_idl_files =
"html/canvas/image_encode_options.idl",
"html/custom/validity_state_flags.idl",
"html/forms/form_data_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",
@@ -699,6 +698,9 @@ core_dictionary_idl_files =
"mojo/test/mojo_interface_request_event_init.idl",
"page/scrolling/scroll_state_init.idl",
"streams/queuing_strategy_init.idl",
+ "timing/measure_memory/measure_memory.idl",
+ "timing/measure_memory/measure_memory_entry.idl",
+ "timing/measure_memory/measure_memory_options.idl",
"timing/performance_mark_options.idl",
"timing/performance_measure_options.idl",
"timing/performance_observer_init.idl",
@@ -751,6 +753,7 @@ webcore_testing_dependency_idl_files =
"fetch/testing/internals_fetch.idl",
"fetch/testing/worker_internals_fetch.idl",
"testing/origin_trials_test_partial.idl",
+ "timing/internals_profiler.idl",
],
"abspath")
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.h b/chromium/third_party/blink/renderer/core/core_initializer.h
index 21c5a704abd..f8ac79931cb 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.h
+++ b/chromium/third_party/blink/renderer/core/core_initializer.h
@@ -56,7 +56,7 @@ class WebMediaPlayerClient;
class WebMediaPlayerSource;
class WebRemotePlaybackClient;
class WebViewClient;
-class WorkerClients;
+class WorkerGlobalScope;
class CORE_EXPORT CoreInitializer {
USING_FAST_MALLOC(CoreInitializer);
@@ -83,7 +83,7 @@ class CORE_EXPORT CoreInitializer {
virtual void InitLocalFrame(LocalFrame&) const = 0;
// Supplements installed on a frame using ChromeClient
virtual void InstallSupplements(LocalFrame&) const = 0;
- virtual void ProvideLocalFileSystemToWorker(WorkerClients&) const = 0;
+ virtual void ProvideLocalFileSystemToWorker(WorkerGlobalScope&) const = 0;
virtual MediaControls* CreateMediaControls(HTMLMediaElement&,
ShadowRoot&) const = 0;
virtual PictureInPictureController* CreatePictureInPictureController(
diff --git a/chromium/third_party/blink/renderer/core/css/BUILD.gn b/chromium/third_party/blink/renderer/core/css/BUILD.gn
index 39740647572..bda1f9c8be2 100644
--- a/chromium/third_party/blink/renderer/core/css/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/css/BUILD.gn
@@ -5,7 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("css") {
- split_count = 10
sources = [
"abstract_property_set_css_style_declaration.cc",
"abstract_property_set_css_style_declaration.h",
@@ -58,8 +57,6 @@ blink_core_sources("css") {
"css_font_family_value.h",
"css_font_feature_value.cc",
"css_font_feature_value.h",
- "css_font_feature_values_rule.cc",
- "css_font_feature_values_rule.h",
"css_font_selector.cc",
"css_font_selector.h",
"css_font_style_range_value.cc",
@@ -106,6 +103,8 @@ blink_core_sources("css") {
"css_keyframes_rule.h",
"css_layout_function_value.cc",
"css_layout_function_value.h",
+ "css_light_dark_color_pair.cc",
+ "css_light_dark_color_pair.h",
"css_markup.cc",
"css_markup.h",
"css_math_expression_node.cc",
@@ -157,6 +156,7 @@ blink_core_sources("css") {
"css_reflect_value.h",
"css_reflection_direction.h",
"css_resolution_units.h",
+ "css_resource_fetch_restriction.h",
"css_rule.cc",
"css_rule.h",
"css_rule_list.h",
@@ -351,6 +351,8 @@ blink_core_sources("css") {
"layout_tree_rebuild_root.h",
"local_font_face_source.cc",
"local_font_face_source.h",
+ "media_feature_overrides.cc",
+ "media_feature_overrides.h",
"media_list.cc",
"media_list.h",
"media_query.cc",
@@ -431,8 +433,8 @@ blink_core_sources("css") {
"parser/media_query_parser.h",
"parser/sizes_attribute_parser.cc",
"parser/sizes_attribute_parser.h",
- "parser/sizes_calc_parser.cc",
- "parser/sizes_calc_parser.h",
+ "parser/sizes_math_function_parser.cc",
+ "parser/sizes_math_function_parser.h",
"part_names.cc",
"part_names.h",
"properties/computed_style_utils.cc",
@@ -590,6 +592,7 @@ blink_core_tests("unit_tests") {
"css_font_face_source_test.cc",
"css_gradient_value_test.cc",
"css_invalid_variable_value_test.cc",
+ "css_light_dark_color_pair_test.cc",
"css_math_expression_node_test.cc",
"css_page_rule_test.cc",
"css_paint_value_test.cc",
@@ -611,6 +614,7 @@ blink_core_tests("unit_tests") {
"cssom/css_unit_value_test.cc",
"cssom/css_unparsed_value_test.cc",
"cssom/css_unsupported_color_value_test.cc",
+ "cssom/inline_style_property_map_test.cc",
"cssom/paint_worklet_style_property_map_test.cc",
"cssom/prepopulated_computed_style_property_map_test.cc",
"drag_update_test.cc",
@@ -618,6 +622,7 @@ blink_core_tests("unit_tests") {
"invalidation/invalidation_set_test.cc",
"invalidation/pending_invalidations_test.cc",
"invalidation/style_invalidator_test.cc",
+ "media_feature_overrides_test.cc",
"media_query_evaluator_test.cc",
"media_query_list_test.cc",
"media_query_matcher_test.cc",
@@ -634,7 +639,7 @@ blink_core_tests("unit_tests") {
"parser/css_tokenizer_test.cc",
"parser/media_condition_test.cc",
"parser/sizes_attribute_parser_test.cc",
- "parser/sizes_calc_parser_test.cc",
+ "parser/sizes_math_function_parser_test.cc",
"properties/css_exposure_test.cc",
"properties/css_parsing_utils_test.cc",
"properties/css_property_ref_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/css/binary_data_font_face_source.cc b/chromium/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
index f73ca24032f..025157de69d 100644
--- a/chromium/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
+++ b/chromium/third_party/blink/renderer/core/css/binary_data_font_face_source.cc
@@ -31,8 +31,8 @@ scoped_refptr<SimpleFontData> BinaryDataFontFaceSource::CreateFontData(
font_description.IsSyntheticBold(),
font_description.IsSyntheticItalic(),
font_description.GetFontSelectionRequest(),
- font_selection_capabilities, font_description.Orientation(),
- font_description.VariationSettings()),
+ font_selection_capabilities, font_description.FontOpticalSizing(),
+ font_description.Orientation(), font_description.VariationSettings()),
CustomFontData::Create());
}
diff --git a/chromium/third_party/blink/renderer/core/css/css.dict b/chromium/third_party/blink/renderer/core/css/css.dict
index ec5c79aff9d..c80456647a1 100644
--- a/chromium/third_party/blink/renderer/core/css/css.dict
+++ b/chromium/third_party/blink/renderer/core/css/css.dict
@@ -915,6 +915,7 @@
"active"
"linktext"
"visitedtext"
+"back-button"
# 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 9a26f1e4015..b700d457fc6 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
@@ -85,34 +85,35 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyID::kDirection, CSSPropertyID::kDisplay,
CSSPropertyID::kEmptyCells, CSSPropertyID::kFloat,
CSSPropertyID::kFontFamily, CSSPropertyID::kFontKerning,
- CSSPropertyID::kFontSize, CSSPropertyID::kFontSizeAdjust,
- CSSPropertyID::kFontStretch, CSSPropertyID::kFontStyle,
- CSSPropertyID::kFontVariant, CSSPropertyID::kFontVariantLigatures,
- CSSPropertyID::kFontVariantCaps, CSSPropertyID::kFontVariantNumeric,
- CSSPropertyID::kFontVariantEastAsian, CSSPropertyID::kFontWeight,
- CSSPropertyID::kHeight, CSSPropertyID::kImageOrientation,
- CSSPropertyID::kImageRendering, CSSPropertyID::kIsolation,
- CSSPropertyID::kJustifyItems, CSSPropertyID::kJustifySelf,
- CSSPropertyID::kLeft, CSSPropertyID::kLetterSpacing,
- CSSPropertyID::kLineHeight, CSSPropertyID::kLineHeightStep,
- CSSPropertyID::kListStyleImage, CSSPropertyID::kListStylePosition,
- CSSPropertyID::kListStyleType, CSSPropertyID::kMarginBottom,
- CSSPropertyID::kMarginLeft, CSSPropertyID::kMarginRight,
- CSSPropertyID::kMarginTop, CSSPropertyID::kMaxHeight,
- CSSPropertyID::kMaxWidth, CSSPropertyID::kMinHeight,
- CSSPropertyID::kMinWidth, CSSPropertyID::kMixBlendMode,
- CSSPropertyID::kObjectFit, CSSPropertyID::kObjectPosition,
- CSSPropertyID::kOffsetAnchor, CSSPropertyID::kOffsetDistance,
- CSSPropertyID::kOffsetPath, CSSPropertyID::kOffsetPosition,
- CSSPropertyID::kOffsetRotate, CSSPropertyID::kOpacity,
- CSSPropertyID::kOrphans, CSSPropertyID::kOutlineColor,
- CSSPropertyID::kOutlineOffset, CSSPropertyID::kOutlineStyle,
- CSSPropertyID::kOutlineWidth, CSSPropertyID::kOverflowAnchor,
- CSSPropertyID::kOverflowWrap, CSSPropertyID::kOverflowX,
- CSSPropertyID::kOverflowY, CSSPropertyID::kPaddingBottom,
- CSSPropertyID::kPaddingLeft, CSSPropertyID::kPaddingRight,
- CSSPropertyID::kPaddingTop, CSSPropertyID::kPointerEvents,
- CSSPropertyID::kPosition, CSSPropertyID::kResize, CSSPropertyID::kRight,
+ CSSPropertyID::kFontOpticalSizing, CSSPropertyID::kFontSize,
+ CSSPropertyID::kFontSizeAdjust, CSSPropertyID::kFontStretch,
+ CSSPropertyID::kFontStyle, CSSPropertyID::kFontVariant,
+ CSSPropertyID::kFontVariantLigatures, CSSPropertyID::kFontVariantCaps,
+ CSSPropertyID::kFontVariantNumeric, CSSPropertyID::kFontVariantEastAsian,
+ CSSPropertyID::kFontWeight, CSSPropertyID::kHeight,
+ CSSPropertyID::kImageOrientation, CSSPropertyID::kImageRendering,
+ CSSPropertyID::kIsolation, CSSPropertyID::kJustifyItems,
+ CSSPropertyID::kJustifySelf, CSSPropertyID::kLeft,
+ CSSPropertyID::kLetterSpacing, CSSPropertyID::kLineHeight,
+ CSSPropertyID::kLineHeightStep, CSSPropertyID::kListStyleImage,
+ CSSPropertyID::kListStylePosition, CSSPropertyID::kListStyleType,
+ CSSPropertyID::kMarginBottom, CSSPropertyID::kMarginLeft,
+ CSSPropertyID::kMarginRight, CSSPropertyID::kMarginTop,
+ CSSPropertyID::kMaxHeight, CSSPropertyID::kMaxWidth,
+ CSSPropertyID::kMinHeight, CSSPropertyID::kMinWidth,
+ CSSPropertyID::kMixBlendMode, CSSPropertyID::kObjectFit,
+ CSSPropertyID::kObjectPosition, CSSPropertyID::kOffsetAnchor,
+ CSSPropertyID::kOffsetDistance, CSSPropertyID::kOffsetPath,
+ CSSPropertyID::kOffsetPosition, CSSPropertyID::kOffsetRotate,
+ CSSPropertyID::kOpacity, CSSPropertyID::kOrphans,
+ CSSPropertyID::kOutlineColor, CSSPropertyID::kOutlineOffset,
+ CSSPropertyID::kOutlineStyle, CSSPropertyID::kOutlineWidth,
+ CSSPropertyID::kOverflowAnchor, CSSPropertyID::kOverflowWrap,
+ CSSPropertyID::kOverflowX, CSSPropertyID::kOverflowY,
+ CSSPropertyID::kPaddingBottom, CSSPropertyID::kPaddingLeft,
+ CSSPropertyID::kPaddingRight, CSSPropertyID::kPaddingTop,
+ CSSPropertyID::kPointerEvents, CSSPropertyID::kPosition,
+ CSSPropertyID::kResize, CSSPropertyID::kRight,
CSSPropertyID::kScrollBehavior, CSSPropertyID::kScrollCustomization,
CSSPropertyID::kSpeak, CSSPropertyID::kTableLayout, CSSPropertyID::kTabSize,
CSSPropertyID::kTextAlign, CSSPropertyID::kTextAlignLast,
diff --git a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
index 363015e35de..31e4f24b328 100644
--- a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration_test.cc
@@ -82,10 +82,11 @@ TEST_F(CSSComputedStyleDeclarationTest, NeedsAdjacentStyleRecalc) {
Element* container = GetDocument().getElementById("container");
Element* c_span = GetDocument().getElementById("c");
Element* d_span = GetDocument().getElementById("d");
+
d_span->setAttribute("style", "color:pink");
- EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
- EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdateForNode(*d_span));
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdateForNode(*d_span));
EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdateForNode(*c_span));
EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdateForNode(*c_span, true));
EXPECT_FALSE(container->NeedsAdjacentStyleRecalc());
@@ -95,6 +96,8 @@ TEST_F(CSSComputedStyleDeclarationTest, NeedsAdjacentStyleRecalc) {
EXPECT_EQ("rgb(0, 128, 0)",
computed->GetPropertyValue(CSSPropertyID::kColor));
+ d_span->setAttribute("style", "color:green");
+
EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdateForNode(*d_span));
EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdateForNode(*c_span));
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 a8a705deb8b..7efd4b60cda 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
@@ -36,9 +36,8 @@ class Element;
class RuleSet;
class StyleSheetContents;
-class CSSDefaultStyleSheets
- : public GarbageCollectedFinalized<CSSDefaultStyleSheets> {
-
+class CSSDefaultStyleSheets final
+ : public GarbageCollected<CSSDefaultStyleSheets> {
public:
CORE_EXPORT static CSSDefaultStyleSheets& Instance();
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face.h b/chromium/third_party/blink/renderer/core/css/css_font_face.h
index e76d47b0404..9f7f7bd14c6 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face.h
@@ -45,9 +45,7 @@ class FontDescription;
class RemoteFontFaceSource;
class SimpleFontData;
-class CORE_EXPORT CSSFontFace final
- : public GarbageCollectedFinalized<CSSFontFace> {
-
+class CORE_EXPORT CSSFontFace final : public GarbageCollected<CSSFontFace> {
public:
CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges)
: ranges_(base::AdoptRef(new UnicodeRangeSet(ranges))),
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 6f93e387355..7c898d8426c 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
@@ -42,7 +42,7 @@ class FontDescription;
class SimpleFontData;
class CORE_EXPORT CSSFontFaceSource
- : public GarbageCollectedFinalized<CSSFontFaceSource> {
+ : public GarbageCollected<CSSFontFaceSource> {
public:
virtual ~CSSFontFaceSource();
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc b/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
index 9ef1fca2bb8..029b8ff9985 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
@@ -51,10 +51,10 @@ unsigned SimulateHashCalculation(float size) {
TEST(CSSFontFaceSourceTest, HashCollision) {
DummyFontFaceSource font_face_source;
// Even if the hash value collide, fontface cache should return different
- // value for different fonts.
- EXPECT_EQ(SimulateHashCalculation(6009), SimulateHashCalculation(8634));
- EXPECT_NE(font_face_source.GetFontDataForSize(6009),
- font_face_source.GetFontDataForSize(8634));
+ // value for different fonts, values determined experimentally.
+ EXPECT_EQ(SimulateHashCalculation(10280), SimulateHashCalculation(9875));
+ EXPECT_NE(font_face_source.GetFontDataForSize(10280),
+ font_face_source.GetFontDataForSize(9875));
}
// Exercises the size font_data_table_ assertions in CSSFontFaceSource.
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
index b2cf3037717..437e88d7fd7 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_src_value.h
@@ -107,9 +107,8 @@ class CORE_EXPORT CSSFontFaceSrcValue : public CSSValue {
const ContentSecurityPolicyDisposition should_check_content_security_policy_;
const OriginClean origin_clean_;
- class FontResourceHelper
- : public GarbageCollectedFinalized<FontResourceHelper>,
- public FontResourceClient {
+ class FontResourceHelper : public GarbageCollected<FontResourceHelper>,
+ public FontResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(FontResourceHelper);
public:
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.cc b/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.cc
deleted file mode 100644
index e4b8ae90aeb..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/css_font_feature_values_rule.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_rule.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-CSSFontFeatureValuesRule::CSSFontFeatureValuesRule(
- StyleRuleFontFeatureValues* font_feature_values_rule,
- CSSStyleSheet* parent)
- : CSSRule(parent), font_feature_values_rule_(font_feature_values_rule) {}
-
-CSSFontFeatureValuesRule::~CSSFontFeatureValuesRule() = default;
-
-void CSSFontFeatureValuesRule::setFontFamily(const String& font_family) {}
-
-String CSSFontFeatureValuesRule::fontFamily() {
- return font_feature_values_rule_->FontFamily().CssText();
-}
-
-void CSSFontFeatureValuesRule::setFontDisplay(const String& font_display) {}
-
-String CSSFontFeatureValuesRule::fontDisplay() {
- if (font_feature_values_rule_->FontDisplay())
- return font_feature_values_rule_->FontDisplay()->CssText();
- return "";
-}
-
-String CSSFontFeatureValuesRule::cssText() const {
- StringBuilder result;
- result.Append("@font-feature-values ");
- DCHECK(font_feature_values_rule_);
- result.Append(font_feature_values_rule_->FontFamily().CssText());
- result.Append(" { ");
- if (const CSSIdentifierValue* display =
- font_feature_values_rule_->FontDisplay()) {
- result.Append("{ font-display: ");
- result.Append(display->CssText());
- result.Append("; } ");
- }
- result.Append("}");
- return result.ToString();
-}
-
-void CSSFontFeatureValuesRule::Reattach(StyleRuleBase* rule) {
- DCHECK(rule);
- font_feature_values_rule_ = To<StyleRuleFontFeatureValues>(rule);
-}
-
-void CSSFontFeatureValuesRule::Trace(blink::Visitor* visitor) {
- visitor->Trace(font_feature_values_rule_);
- CSSRule::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.h b/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.h
deleted file mode 100644
index 5fac19ddb68..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_FONT_FEATURE_VALUES_RULE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_FONT_FEATURE_VALUES_RULE_H_
-
-#include "third_party/blink/renderer/core/css/css_rule.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/casting.h"
-
-namespace blink {
-
-class StyleRuleFontFeatureValues;
-
-class CSSFontFeatureValuesRule final : public CSSRule {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- CSSFontFeatureValuesRule(StyleRuleFontFeatureValues*, CSSStyleSheet* parent);
- ~CSSFontFeatureValuesRule() override;
-
- void setFontFamily(const String& font_family);
- String fontFamily();
- void setFontDisplay(const String& font_display);
- String fontDisplay();
-
- String cssText() const override;
- void Reattach(StyleRuleBase*) override;
-
- StyleRuleFontFeatureValues* StyleRule() const {
- return font_feature_values_rule_.Get();
- }
-
- void Trace(blink::Visitor*) override;
-
- private:
- CSSRule::Type type() const override { return kFontFeatureValuesRule; }
-
- Member<StyleRuleFontFeatureValues> font_feature_values_rule_;
-};
-
-template <>
-struct DowncastTraits<CSSFontFeatureValuesRule> {
- static bool AllowFrom(const CSSRule& rule) {
- return rule.type() == CSSRule::kFontFeatureValuesRule;
- }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_FONT_FEATURE_VALUES_RULE_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.idl b/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.idl
deleted file mode 100644
index 882239c5b16..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_font_feature_values_rule.idl
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://drafts.csswg.org/css-fonts-4/#om-fontfeaturevalues
-
-[
- RuntimeEnabled=CSSFontFeatureValues
-] interface CSSFontFeatureValuesRule : CSSRule {
- attribute CSSOMString fontFamily;
-
- // fontDisplay is not reflected in CSSOM according to the current draft.
- attribute CSSOMString fontDisplay;
-};
diff --git a/chromium/third_party/blink/renderer/core/css/css_global_rule_set.h b/chromium/third_party/blink/renderer/core/css/css_global_rule_set.h
index 0fb3a072cf3..c45dc4075ca 100644
--- a/chromium/third_party/blink/renderer/core/css/css_global_rule_set.h
+++ b/chromium/third_party/blink/renderer/core/css/css_global_rule_set.h
@@ -22,7 +22,7 @@ class RuleSet;
// possible to the ScopedStyleResolver as possible to avoid full reconstruction
// of these rulesets on shadow tree changes. See https://crbug.com/401359
-class CSSGlobalRuleSet : public GarbageCollectedFinalized<CSSGlobalRuleSet> {
+class CSSGlobalRuleSet final : public GarbageCollected<CSSGlobalRuleSet> {
public:
CSSGlobalRuleSet() = default;
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 f8764608de3..db328c5a651 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
@@ -159,6 +159,16 @@ scoped_refptr<Image> CSSImageGeneratorValue::GetImage(
return nullptr;
}
+bool CSSImageGeneratorValue::IsUsingCustomProperty(
+ const AtomicString& custom_property_name,
+ const Document& document) const {
+ if (GetClassType() == kPaintClass) {
+ return To<CSSPaintValue>(this)->IsUsingCustomProperty(custom_property_name,
+ document);
+ }
+ return false;
+}
+
bool CSSImageGeneratorValue::IsFixedSize() const {
switch (GetClassType()) {
case kCrossfadeClass:
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 ca7d805b6b3..94180496d71 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
@@ -105,6 +105,9 @@ class CORE_EXPORT CSSImageGeneratorValue : public CSSValue {
CSSImageGeneratorValue* ComputedCSSValue(const ComputedStyle&,
bool allow_visited_style);
+ bool IsUsingCustomProperty(const AtomicString& custom_property_name,
+ const Document&) const;
+
void TraceAfterDispatch(blink::Visitor* visitor) {
CSSValue::TraceAfterDispatch(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc b/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
index bbb39a7f768..5e1fd09a024 100644
--- a/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_image_set_value.cc
@@ -127,12 +127,6 @@ StyleImage* CSSImageSetValue::CacheImage(
cross_origin);
}
- if (document.GetFrame() &&
- image_request_optimization == FetchParameters::kAllowPlaceholder &&
- document.GetFrame()->IsClientLoFiAllowed(params.GetResourceRequest())) {
- params.SetClientLoFiPlaceholder();
- }
-
cached_image_ = MakeGarbageCollected<StyleFetchedImageSet>(
ImageResourceContent::Fetch(params, document.Fetcher()),
image.scale_factor, this, params.Url());
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 f623e1f4ba9..06f072c9188 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
@@ -80,11 +80,6 @@ StyleImage* CSSImageValue::CacheImage(
cross_origin);
}
- if (document.GetFrame() &&
- image_request_optimization == FetchParameters::kAllowPlaceholder &&
- document.GetFrame()->IsClientLoFiAllowed(params.GetResourceRequest())) {
- params.SetClientLoFiPlaceholder();
- }
bool is_lazily_loaded =
image_request_optimization == FetchParameters::kDeferImageLoad &&
// Only http/https images are eligible to be lazily loaded.
diff --git a/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.cc b/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.cc
index a5d33566389..7311cb6aa55 100644
--- a/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.cc
@@ -3,25 +3,44 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
namespace blink {
+#if DCHECK_IS_ON()
+namespace {
+bool ShorthandMatches(CSSPropertyID expected_shorthand,
+ CSSPropertyID longhand) {
+ Vector<StylePropertyShorthand, 4> shorthands;
+ getMatchingShorthandsForLonghand(longhand, &shorthands);
+ for (unsigned i = 0; i < shorthands.size(); ++i) {
+ if (shorthands.at(i).id() == expected_shorthand)
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+#endif
+
CSSKeyframeShorthandValue::CSSKeyframeShorthandValue(
+ CSSPropertyID shorthand,
ImmutableCSSPropertyValueSet* properties)
- : CSSValue(kKeyframeShorthandClass), properties_(properties) {}
+ : CSSValue(kKeyframeShorthandClass),
+ shorthand_(shorthand),
+ properties_(properties) {}
String CSSKeyframeShorthandValue::CustomCSSText() const {
- // All property/value pairs belong to the same shorthand so we grab the id
- // from the first one.
- CSSPropertyID my_shorthand = properties_->PropertyAt(0).ShorthandID();
#if DCHECK_IS_ON()
+ // Check that all property/value pairs belong to the same shorthand.
for (unsigned i = 0; i < properties_->PropertyCount(); i++) {
- DCHECK_EQ(my_shorthand, properties_->PropertyAt(i).ShorthandID())
+ DCHECK(ShorthandMatches(shorthand_, properties_->PropertyAt(i).Id()))
<< "These are not the longhands you're looking for.";
}
#endif
- return properties_->GetPropertyValue(my_shorthand);
+ return properties_->GetPropertyValue(shorthand_);
}
void CSSKeyframeShorthandValue::TraceAfterDispatch(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h b/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h
index bcc149c4ffa..43f849f4553 100644
--- a/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h
@@ -36,17 +36,24 @@ class CSSKeyframeShorthandValue : public CSSValue {
public:
// Assumes that all property/value pairs that are present in the input set are
// longhands for the same shorthand property/value pair.
- CSSKeyframeShorthandValue(ImmutableCSSPropertyValueSet*);
+ CSSKeyframeShorthandValue(CSSPropertyID shorthand,
+ ImmutableCSSPropertyValueSet*);
String CustomCSSText() const;
bool Equals(const CSSKeyframeShorthandValue& other) const {
- return properties_ == other.properties_;
+ return shorthand_ == other.shorthand_ && properties_ == other.properties_;
}
void TraceAfterDispatch(blink::Visitor*);
private:
+ // The shorthand property that these longhands belonged to.
+ // Note that a single longhand property may belong to multiple shorthands
+ // (e.g., border-left-style belongs to border-style and border) so we keep
+ // this value instead of trying to calculate the common shorthand given the
+ // longhands.
+ CSSPropertyID shorthand_;
Member<ImmutableCSSPropertyValueSet> properties_;
};
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc
new file mode 100644
index 00000000000..201654e4264
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.cc
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
+
+namespace blink {
+
+String CSSLightDarkColorPair::CustomCSSText() const {
+ String first = First().CssText();
+ String second = Second().CssText();
+ return "-internal-light-dark-color(" + first + ", " + second + ")";
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h
new file mode 100644
index 00000000000..84737f5e29c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
+
+#include "third_party/blink/renderer/core/css/css_value_pair.h"
+
+namespace blink {
+
+class CORE_EXPORT CSSLightDarkColorPair : public CSSValuePair {
+ public:
+ CSSLightDarkColorPair(const CSSValue* first, const CSSValue* second)
+ : CSSValuePair(kLightDarkColorPairClass, first, second) {}
+ String CustomCSSText() const;
+ void TraceAfterDispatch(blink::Visitor* visitor) {
+ CSSValuePair::TraceAfterDispatch(visitor);
+ }
+};
+
+template <>
+struct DowncastTraits<CSSLightDarkColorPair> {
+ static bool AllowFrom(const CSSValue& value) {
+ return value.IsLightDarkColorPair();
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LIGHT_DARK_COLOR_PAIR_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc
new file mode 100644
index 00000000000..e3523d7c609
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_light_dark_color_pair_test.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+
+namespace blink {
+
+namespace {
+
+const CSSValue* CreateLightDarkColorPair(const char* value) {
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+ return CSSParser::ParseSingleValue(CSSPropertyID::kColor, value, ua_context);
+}
+
+TEST(CSSLightDarkColorPairTest, Equals) {
+ const auto* value1 =
+ CreateLightDarkColorPair("-internal-light-dark-color(red, green)");
+ const auto* value2 =
+ CreateLightDarkColorPair("-internal-light-dark-color(red, green)");
+ const auto* value3 =
+ CreateLightDarkColorPair("-internal-light-dark-color(#000, #fff)");
+ const auto* value4 = CreateLightDarkColorPair(
+ "-internal-light-dark-color(rgb(0, 0, 0), rgb(255, 255, 255))");
+ ASSERT_TRUE(value1);
+ ASSERT_TRUE(value2);
+ ASSERT_TRUE(value3);
+ ASSERT_TRUE(value4);
+ EXPECT_TRUE(*value1 == *value1);
+ EXPECT_TRUE(*value1 == *value2);
+ EXPECT_TRUE(*value3 == *value3);
+ EXPECT_TRUE(*value4 == *value4);
+ EXPECT_TRUE(*value3 == *value4);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc b/chromium/third_party/blink/renderer/core/css/css_math_expression_node.cc
index 3a325efbb56..4e6fa5e20e4 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
@@ -127,7 +127,7 @@ static bool HasDoubleValue(CSSPrimitiveValue::UnitType type) {
// static
CSSMathExpressionNumericLiteral* CSSMathExpressionNumericLiteral::Create(
- CSSNumericLiteralValue* value,
+ const CSSNumericLiteralValue* value,
bool is_integer) {
return MakeGarbageCollected<CSSMathExpressionNumericLiteral>(value,
is_integer);
@@ -145,7 +145,7 @@ CSSMathExpressionNumericLiteral* CSSMathExpressionNumericLiteral::Create(
}
CSSMathExpressionNumericLiteral::CSSMathExpressionNumericLiteral(
- CSSNumericLiteralValue* value,
+ const CSSNumericLiteralValue* value,
bool is_integer)
: CSSMathExpressionNode(UnitCategory(value->GetType()), is_integer),
value_(value) {}
@@ -158,8 +158,8 @@ String CSSMathExpressionNumericLiteral::CustomCSSText() const {
return value_->CssText();
}
-scoped_refptr<const CalculationExpressionNode>
-CSSMathExpressionNumericLiteral::ToCalculationExpression(
+base::Optional<PixelsAndPercent>
+CSSMathExpressionNumericLiteral::ToPixelsAndPercent(
const CSSToLengthConversionData& conversion_data) const {
PixelsAndPercent value(0, 0);
switch (category_) {
@@ -179,7 +179,14 @@ CSSMathExpressionNumericLiteral::ToCalculationExpression(
default:
NOTREACHED();
}
- return base::MakeRefCounted<CalculationExpressionLeafNode>(value);
+ return value;
+}
+
+scoped_refptr<const CalculationExpressionNode>
+CSSMathExpressionNumericLiteral::ToCalculationExpression(
+ const CSSToLengthConversionData& conversion_data) const {
+ return base::MakeRefCounted<CalculationExpressionLeafNode>(
+ *ToPixelsAndPercent(conversion_data));
}
double CSSMathExpressionNumericLiteral::DoubleValue() const {
@@ -358,8 +365,8 @@ static bool IsIntegerResult(const CSSMathExpressionNode* left_side,
// static
CSSMathExpressionNode* CSSMathExpressionBinaryOperation::Create(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op) {
DCHECK_NE(left_side->Category(), kCalcOther);
DCHECK_NE(right_side->Category(), kCalcOther);
@@ -375,9 +382,12 @@ CSSMathExpressionNode* CSSMathExpressionBinaryOperation::Create(
// static
CSSMathExpressionNode* CSSMathExpressionBinaryOperation::CreateSimplified(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op) {
+ if (left_side->IsMathFunction() || right_side->IsMathFunction())
+ return Create(left_side, right_side, op);
+
CalculationCategory left_category = left_side->Category();
CalculationCategory right_category = right_side->Category();
DCHECK_NE(left_category, kCalcOther);
@@ -432,12 +442,13 @@ CSSMathExpressionNode* CSSMathExpressionBinaryOperation::CreateSimplified(
} else {
// Simplify multiplying or dividing by a number for simplifiable types.
DCHECK(op == CSSMathOperator::kMultiply || op == CSSMathOperator::kDivide);
- CSSMathExpressionNode* number_side = GetNumberSide(left_side, right_side);
+ const CSSMathExpressionNode* number_side =
+ GetNumberSide(left_side, right_side);
if (!number_side)
return Create(left_side, right_side, op);
if (number_side == left_side && op == CSSMathOperator::kDivide)
return nullptr;
- CSSMathExpressionNode* other_side =
+ const CSSMathExpressionNode* other_side =
left_side == number_side ? right_side : left_side;
double number = number_side->DoubleValue();
@@ -458,8 +469,8 @@ CSSMathExpressionNode* CSSMathExpressionBinaryOperation::CreateSimplified(
}
CSSMathExpressionBinaryOperation::CSSMathExpressionBinaryOperation(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op,
CalculationCategory category)
: CSSMathExpressionNode(category,
@@ -472,6 +483,52 @@ bool CSSMathExpressionBinaryOperation::IsZero() const {
return !DoubleValue();
}
+base::Optional<PixelsAndPercent>
+CSSMathExpressionBinaryOperation::ToPixelsAndPercent(
+ const CSSToLengthConversionData& conversion_data) const {
+ base::Optional<PixelsAndPercent> result;
+ switch (operator_) {
+ case CSSMathOperator::kAdd:
+ case CSSMathOperator::kSubtract: {
+ result = left_side_->ToPixelsAndPercent(conversion_data);
+ if (!result)
+ return base::nullopt;
+
+ base::Optional<PixelsAndPercent> other_side =
+ right_side_->ToPixelsAndPercent(conversion_data);
+ if (!other_side)
+ return base::nullopt;
+ if (operator_ == CSSMathOperator::kAdd) {
+ result->pixels += other_side->pixels;
+ result->percent += other_side->percent;
+ } else {
+ result->pixels -= other_side->pixels;
+ result->percent -= other_side->percent;
+ }
+ break;
+ }
+ case CSSMathOperator::kMultiply:
+ case CSSMathOperator::kDivide: {
+ const CSSMathExpressionNode* number_side =
+ GetNumberSide(left_side_, right_side_);
+ const CSSMathExpressionNode* other_side =
+ left_side_ == number_side ? right_side_ : left_side_;
+ result = other_side->ToPixelsAndPercent(conversion_data);
+ if (!result)
+ return base::nullopt;
+ float number = number_side->DoubleValue();
+ if (operator_ == CSSMathOperator::kDivide)
+ number = 1.0 / number;
+ result->pixels *= number;
+ result->percent *= number;
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ return result;
+}
+
scoped_refptr<const CalculationExpressionNode>
CSSMathExpressionBinaryOperation::ToCalculationExpression(
const CSSToLengthConversionData& conversion_data) const {
@@ -605,26 +662,30 @@ bool CSSMathExpressionBinaryOperation::IsComputationallyIndependent() const {
right_side_->IsComputationallyIndependent();
}
-// static
-String CSSMathExpressionBinaryOperation::BuildCSSText(
- const String& left_expression,
- const String& right_expression,
- CSSMathOperator op) {
+String CSSMathExpressionBinaryOperation::CustomCSSText() const {
StringBuilder result;
- result.Append('(');
- result.Append(left_expression);
+
+ const bool left_side_needs_parentheses =
+ left_side_->IsBinaryOperation() && operator_ != CSSMathOperator::kAdd;
+ if (left_side_needs_parentheses)
+ result.Append('(');
+ result.Append(left_side_->CustomCSSText());
+ if (left_side_needs_parentheses)
+ result.Append(')');
+
result.Append(' ');
- result.Append(ToString(op));
+ result.Append(ToString(operator_));
result.Append(' ');
- result.Append(right_expression);
- result.Append(')');
- return result.ToString();
-}
+ const bool right_side_needs_parentheses =
+ right_side_->IsBinaryOperation() && operator_ != CSSMathOperator::kAdd;
+ if (right_side_needs_parentheses)
+ result.Append('(');
+ result.Append(right_side_->CustomCSSText());
+ if (right_side_needs_parentheses)
+ result.Append(')');
-String CSSMathExpressionBinaryOperation::CustomCSSText() const {
- return BuildCSSText(left_side_->CustomCSSText(), right_side_->CustomCSSText(),
- operator_);
+ return result.ToString();
}
bool CSSMathExpressionBinaryOperation::operator==(
@@ -681,9 +742,9 @@ void CSSMathExpressionBinaryOperation::Trace(blink::Visitor* visitor) {
}
// static
-CSSMathExpressionNode* CSSMathExpressionBinaryOperation::GetNumberSide(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side) {
+const CSSMathExpressionNode* CSSMathExpressionBinaryOperation::GetNumberSide(
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side) {
if (left_side->Category() == kCalcNumber)
return left_side;
if (right_side->Category() == kCalcNumber)
@@ -816,7 +877,31 @@ double CSSMathExpressionVariadicOperation::ComputeLengthPx(
return result;
}
+String CSSMathExpressionVariadicOperation::CSSTextAsClamp() const {
+ DCHECK(is_clamp_);
+ DCHECK_EQ(CSSMathOperator::kMax, operator_);
+ DCHECK_EQ(2u, operands_.size());
+ DCHECK(operands_[1]->IsVariadicOperation());
+ const auto& nested = To<CSSMathExpressionVariadicOperation>(*operands_[1]);
+ DCHECK(!nested.is_clamp_);
+ DCHECK_EQ(CSSMathOperator::kMin, nested.operator_);
+ DCHECK_EQ(2u, nested.operands_.size());
+
+ StringBuilder result;
+ result.Append("clamp(");
+ result.Append(operands_[0]->CustomCSSText());
+ result.Append(", ");
+ result.Append(nested.operands_[0]->CustomCSSText());
+ result.Append(", ");
+ result.Append(nested.operands_[1]->CustomCSSText());
+ result.Append(")");
+ return result.ToString();
+}
+
String CSSMathExpressionVariadicOperation::CustomCSSText() const {
+ if (is_clamp_)
+ return CSSTextAsClamp();
+
StringBuilder result;
result.Append(ToString(operator_));
result.Append('(');
@@ -830,6 +915,12 @@ String CSSMathExpressionVariadicOperation::CustomCSSText() const {
return result.ToString();
}
+base::Optional<PixelsAndPercent>
+CSSMathExpressionVariadicOperation::ToPixelsAndPercent(
+ const CSSToLengthConversionData& conversion_data) const {
+ return base::nullopt;
+}
+
scoped_refptr<const CalculationExpressionNode>
CSSMathExpressionVariadicOperation::ToCalculationExpression(
const CSSToLengthConversionData& data) const {
@@ -963,6 +1054,41 @@ class CSSMathExpressionNodeParser {
return CSSMathExpressionVariadicOperation::Create(std::move(operands), op);
}
+ CSSMathExpressionNode* ParseClamp(CSSParserTokenRange tokens, int depth) {
+ if (CheckDepthAndIndex(&depth, tokens) != OK)
+ return nullptr;
+
+ CSSMathExpressionNode* min_operand = ParseValueExpression(tokens, depth);
+ if (!min_operand)
+ return nullptr;
+
+ if (!css_property_parser_helpers::ConsumeCommaIncludingWhitespace(tokens))
+ return nullptr;
+
+ CSSMathExpressionNode* val_operand = ParseValueExpression(tokens, depth);
+ if (!val_operand)
+ return nullptr;
+
+ if (!css_property_parser_helpers::ConsumeCommaIncludingWhitespace(tokens))
+ return nullptr;
+
+ CSSMathExpressionNode* max_operand = ParseValueExpression(tokens, depth);
+ if (!max_operand)
+ return nullptr;
+
+ if (!tokens.AtEnd())
+ return nullptr;
+
+ // clamp(MIN, VAL, MAX) is identical to max(MIN, min(VAL, MAX))
+
+ auto* nested = CSSMathExpressionVariadicOperation::Create(
+ {val_operand, max_operand}, CSSMathOperator::kMin);
+ auto* result = CSSMathExpressionVariadicOperation::Create(
+ {min_operand, nested}, CSSMathOperator::kMax);
+ result->SetIsClamp();
+ return result;
+ }
+
private:
CSSMathExpressionNode* ParseValue(CSSParserTokenRange& tokens) {
CSSParserToken token = tokens.ConsumeIncludingWhitespace();
@@ -1008,8 +1134,9 @@ class CSSMathExpressionNodeParser {
return ParseMinOrMax(inner_range, CSSMathOperator::kMin, depth);
case CSSValueID::kMax:
return ParseMinOrMax(inner_range, CSSMathOperator::kMax, depth);
+ case CSSValueID::kClamp:
+ return ParseClamp(inner_range, depth);
default:
- // TODO(crbug.com/825895): Support clamp when min/max are done.
break;
}
}
@@ -1093,6 +1220,15 @@ class CSSMathExpressionNodeParser {
}
};
+scoped_refptr<CalculationValue> CSSMathExpressionNode::ToCalcValue(
+ const CSSToLengthConversionData& conversion_data,
+ ValueRange range) const {
+ if (auto maybe_pixels_and_percent = ToPixelsAndPercent(conversion_data))
+ return CalculationValue::Create(*maybe_pixels_and_percent, range);
+ return CalculationValue::CreateSimplified(
+ ToCalculationExpression(conversion_data), range);
+}
+
// static
CSSMathExpressionNode* CSSMathExpressionNode::Create(
const CalculationValue& calc) {
@@ -1154,7 +1290,7 @@ CSSMathExpressionNode* CSSMathExpressionNode::Create(
DCHECK(node.IsComparison());
const auto& comparison = To<CalculationExpressionComparisonNode>(node);
- HeapVector<Member<CSSMathExpressionNode>> operands;
+ CSSMathExpressionVariadicOperation::Operands operands;
for (const auto& operand : comparison.GetOperands())
operands.push_back(Create(*operand));
CSSMathOperator op =
@@ -1183,4 +1319,11 @@ CSSMathExpressionNode* CSSMathExpressionNode::ParseMax(
return parser.ParseMinOrMax(tokens, CSSMathOperator::kMax, 0);
}
+// static
+CSSMathExpressionNode* CSSMathExpressionNode::ParseClamp(
+ const CSSParserTokenRange& tokens) {
+ CSSMathExpressionNodeParser parser;
+ return parser.ParseClamp(tokens, 0);
+}
+
} // namespace blink
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 d9ce4f6d6f6..ce486ec1732 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
@@ -46,7 +46,6 @@ class CSSNumericLiteralValue;
// The order of this enum should not change since its elements are used as
// indices in the addSubtractResult matrix.
-// TODO(crbug.com/825895): Change it to |enum class CSSMathExpressionCategory|.
enum CalculationCategory {
kCalcNumber = 0,
kCalcLength,
@@ -71,6 +70,7 @@ class CORE_EXPORT CSSMathExpressionNode
static CSSMathExpressionNode* ParseCalc(const CSSParserTokenRange& tokens);
static CSSMathExpressionNode* ParseMin(const CSSParserTokenRange& tokens);
static CSSMathExpressionNode* ParseMax(const CSSParserTokenRange& tokens);
+ static CSSMathExpressionNode* ParseClamp(const CSSParserTokenRange& tokens);
virtual bool IsNumericLiteral() const { return false; }
virtual bool IsBinaryOperation() const { return false; }
@@ -93,6 +93,12 @@ class CORE_EXPORT CSSMathExpressionNode
CSSPrimitiveValue::LengthTypeFlags& types) const = 0;
virtual scoped_refptr<const CalculationExpressionNode>
ToCalculationExpression(const CSSToLengthConversionData&) const = 0;
+ virtual base::Optional<PixelsAndPercent> ToPixelsAndPercent(
+ const CSSToLengthConversionData&) const = 0;
+
+ scoped_refptr<CalculationValue> ToCalcValue(
+ const CSSToLengthConversionData& conversion_data,
+ ValueRange range) const;
// Evaluates the expression with type conversion (e.g., cm -> px) handled, and
// returns the result value in the canonical unit of the corresponding
@@ -114,6 +120,11 @@ class CORE_EXPORT CSSMathExpressionNode
virtual bool IsComputationallyIndependent() const = 0;
CalculationCategory Category() const { return category_; }
+ bool HasPercentage() const {
+ return category_ == kCalcPercent || category_ == kCalcPercentNumber ||
+ category_ == kCalcPercentLength ||
+ category_ == kCalcPercentLengthNumber;
+ }
// Returns the unit type of the math expression *without doing any type
// conversion* (e.g., 1px + 1em needs type conversion to resolve).
@@ -149,20 +160,25 @@ class CORE_EXPORT CSSMathExpressionNode
class CORE_EXPORT CSSMathExpressionNumericLiteral final
: public CSSMathExpressionNode {
public:
- static CSSMathExpressionNumericLiteral* Create(CSSNumericLiteralValue* value,
- bool is_integer = false);
+ static CSSMathExpressionNumericLiteral* Create(
+ const CSSNumericLiteralValue* value,
+ bool is_integer = false);
static CSSMathExpressionNumericLiteral*
Create(double value, CSSPrimitiveValue::UnitType type, bool is_integer);
- CSSMathExpressionNumericLiteral(CSSNumericLiteralValue* value,
+ CSSMathExpressionNumericLiteral(const CSSNumericLiteralValue* value,
bool is_integer);
+ const CSSNumericLiteralValue& GetValue() const { return *value_; }
+
bool IsNumericLiteral() const final { return true; }
bool IsZero() const final;
String CustomCSSText() const final;
scoped_refptr<const CalculationExpressionNode> ToCalculationExpression(
const CSSToLengthConversionData&) const final;
+ base::Optional<PixelsAndPercent> ToPixelsAndPercent(
+ const CSSToLengthConversionData&) const final;
double DoubleValue() const final;
base::Optional<double> ComputeValueInCanonicalUnit() const final;
double ComputeLengthPx(
@@ -181,7 +197,7 @@ class CORE_EXPORT CSSMathExpressionNumericLiteral final
#endif
private:
- Member<CSSNumericLiteralValue> value_;
+ Member<const CSSNumericLiteralValue> value_;
};
template <>
@@ -194,16 +210,16 @@ struct DowncastTraits<CSSMathExpressionNumericLiteral> {
class CORE_EXPORT CSSMathExpressionBinaryOperation final
: public CSSMathExpressionNode {
public:
- static CSSMathExpressionNode* Create(CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ static CSSMathExpressionNode* Create(const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op);
static CSSMathExpressionNode* CreateSimplified(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op);
- CSSMathExpressionBinaryOperation(CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side,
+ CSSMathExpressionBinaryOperation(const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side,
CSSMathOperator op,
CalculationCategory category);
@@ -218,6 +234,8 @@ class CORE_EXPORT CSSMathExpressionBinaryOperation final
bool IsZero() const final;
scoped_refptr<const CalculationExpressionNode> ToCalculationExpression(
const CSSToLengthConversionData&) const final;
+ base::Optional<PixelsAndPercent> ToPixelsAndPercent(
+ const CSSToLengthConversionData&) const final;
double DoubleValue() const final;
base::Optional<double> ComputeValueInCanonicalUnit() const final;
double ComputeLengthPx(
@@ -237,13 +255,9 @@ class CORE_EXPORT CSSMathExpressionBinaryOperation final
#endif
private:
- static CSSMathExpressionNode* GetNumberSide(
- CSSMathExpressionNode* left_side,
- CSSMathExpressionNode* right_side);
-
- static String BuildCSSText(const String& left_expression,
- const String& right_expression,
- CSSMathOperator op);
+ static const CSSMathExpressionNode* GetNumberSide(
+ const CSSMathExpressionNode* left_side,
+ const CSSMathExpressionNode* right_side);
double Evaluate(double left_side, double right_side) const {
return EvaluateOperator(left_side, right_side, operator_);
@@ -253,8 +267,8 @@ class CORE_EXPORT CSSMathExpressionBinaryOperation final
double right_value,
CSSMathOperator op);
- const Member<CSSMathExpressionNode> left_side_;
- const Member<CSSMathExpressionNode> right_side_;
+ const Member<const CSSMathExpressionNode> left_side_;
+ const Member<const CSSMathExpressionNode> right_side_;
const CSSMathOperator operator_;
};
@@ -267,7 +281,7 @@ struct DowncastTraits<CSSMathExpressionBinaryOperation> {
class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode {
public:
- using Operands = HeapVector<Member<CSSMathExpressionNode>>;
+ using Operands = HeapVector<Member<const CSSMathExpressionNode>>;
static CSSMathExpressionVariadicOperation* Create(Operands&& operands,
CSSMathOperator op);
@@ -282,10 +296,15 @@ class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode {
bool IsVariadicOperation() const final { return true; }
+ void SetIsClamp() { is_clamp_ = true; }
+ String CSSTextAsClamp() const;
+
bool IsZero() const final;
String CustomCSSText() const final;
scoped_refptr<const CalculationExpressionNode> ToCalculationExpression(
const CSSToLengthConversionData&) const final;
+ base::Optional<PixelsAndPercent> ToPixelsAndPercent(
+ const CSSToLengthConversionData&) const final;
double DoubleValue() const final;
double ComputeLengthPx(
const CSSToLengthConversionData& conversion_data) const final;
@@ -305,8 +324,8 @@ class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode {
private:
// Helper for iterating from the 2nd to the last operands
- // TODO: Is this Oilpan-safe?
- base::span<const Member<CSSMathExpressionNode>> SecondToLastOperands() const {
+ base::span<const Member<const CSSMathExpressionNode>> SecondToLastOperands()
+ const {
return base::make_span(std::next(operands_.begin()), operands_.end());
}
@@ -314,6 +333,7 @@ class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode {
Operands operands_;
const CSSMathOperator operator_;
+ bool is_clamp_ = false;
};
template <>
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 2569e8e7bb6..36cc3dd829f 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
@@ -60,6 +60,12 @@ void TestAccumulatePixelsAndPercent(
To<CalculationExpressionLeafNode>(*value).Pixels());
EXPECT_EQ(expected_percent,
To<CalculationExpressionLeafNode>(*value).Percent());
+
+ base::Optional<PixelsAndPercent> pixels_and_percent =
+ expression->ToPixelsAndPercent(conversion_data);
+ EXPECT_TRUE(pixels_and_percent.has_value());
+ EXPECT_EQ(expected_pixels, pixels_and_percent->pixels);
+ EXPECT_EQ(expected_percent, pixels_and_percent->percent);
}
CSSLengthArray& SetLengthArray(CSSLengthArray& length_array, String text) {
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_function_value.cc b/chromium/third_party/blink/renderer/core/css/css_math_function_value.cc
index 91887e718cd..49986ea7099 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_function_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_math_function_value.cc
@@ -22,15 +22,16 @@ void CSSMathFunctionValue::TraceAfterDispatch(blink::Visitor* visitor) {
CSSPrimitiveValue::TraceAfterDispatch(visitor);
}
-CSSMathFunctionValue::CSSMathFunctionValue(CSSMathExpressionNode* expression,
- ValueRange range)
+CSSMathFunctionValue::CSSMathFunctionValue(
+ const CSSMathExpressionNode* expression,
+ ValueRange range)
: CSSPrimitiveValue(kMathFunctionClass), expression_(expression) {
is_non_negative_math_function_ = range == kValueRangeNonNegative;
}
// static
CSSMathFunctionValue* CSSMathFunctionValue::Create(
- CSSMathExpressionNode* expression,
+ const CSSMathExpressionNode* expression,
ValueRange range) {
if (!expression)
return nullptr;
@@ -96,12 +97,9 @@ Length CSSMathFunctionValue::ConvertToLength(
static String BuildCSSText(const String& expression) {
StringBuilder result;
result.Append("calc");
- bool expression_has_single_term = expression[0] != '(';
- if (expression_has_single_term)
- result.Append('(');
+ result.Append('(');
result.Append(expression);
- if (expression_has_single_term)
- result.Append(')');
+ result.Append(')');
return result.ToString();
}
@@ -141,9 +139,7 @@ bool CSSMathFunctionValue::IsComputationallyIndependent() const {
scoped_refptr<CalculationValue> CSSMathFunctionValue::ToCalcValue(
const CSSToLengthConversionData& conversion_data) const {
- return CalculationValue::CreateSimplified(
- expression_->ToCalculationExpression(conversion_data),
- PermittedValueRange());
+ return expression_->ToCalcValue(conversion_data, PermittedValueRange());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_math_function_value.h b/chromium/third_party/blink/renderer/core/css/css_math_function_value.h
index 4436f74d994..73316aa2244 100644
--- a/chromium/third_party/blink/renderer/core/css/css_math_function_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_math_function_value.h
@@ -16,12 +16,13 @@ namespace blink {
class CORE_EXPORT CSSMathFunctionValue : public CSSPrimitiveValue {
public:
static CSSMathFunctionValue* Create(const Length&, float zoom);
- static CSSMathFunctionValue* Create(CSSMathExpressionNode*,
+ static CSSMathFunctionValue* Create(const CSSMathExpressionNode*,
ValueRange = kValueRangeAll);
- CSSMathFunctionValue(CSSMathExpressionNode* expression, ValueRange range);
+ CSSMathFunctionValue(const CSSMathExpressionNode* expression,
+ ValueRange range);
- CSSMathExpressionNode* ExpressionNode() const { return expression_; }
+ const CSSMathExpressionNode* ExpressionNode() const { return expression_; }
scoped_refptr<CalculationValue> ToCalcValue(
const CSSToLengthConversionData& conversion_data) const;
@@ -94,7 +95,7 @@ class CORE_EXPORT CSSMathFunctionValue : public CSSPrimitiveValue {
double ClampToPermittedRange(double) const;
- Member<CSSMathExpressionNode> expression_;
+ Member<const CSSMathExpressionNode> expression_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/css/css_paint_image_generator.h b/chromium/third_party/blink/renderer/core/css/css_paint_image_generator.h
index 6dadca545e6..e3449d7b945 100644
--- a/chromium/third_party/blink/renderer/core/css/css_paint_image_generator.h
+++ b/chromium/third_party/blink/renderer/core/css/css_paint_image_generator.h
@@ -21,13 +21,13 @@ class ImageResourceObserver;
// Produces a PaintGeneratedImage from a CSS Paint API callback.
// https://drafts.css-houdini.org/css-paint-api/
class CORE_EXPORT CSSPaintImageGenerator
- : public GarbageCollectedFinalized<CSSPaintImageGenerator> {
+ : public GarbageCollected<CSSPaintImageGenerator> {
public:
// This observer is used if the paint worklet doesn't have a javascript
// class registered with the correct name yet.
// paintImageGeneratorReady is called when the javascript class is
// registered and ready to use.
- class Observer : public GarbageCollectedFinalized<Observer> {
+ class Observer : public GarbageCollected<Observer> {
public:
virtual ~Observer() = default;
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 e01b860b3cd..e2571f0dc67 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/css/css_paint_value.h"
+#include "base/metrics/histogram_macros.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_paint_image_generator.h"
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
@@ -24,7 +25,10 @@ CSSPaintValue::CSSPaintValue(CSSCustomIdentValue* name)
: CSSImageGeneratorValue(kPaintClass),
name_(name),
paint_image_generator_observer_(MakeGarbageCollected<Observer>(this)),
- paint_off_thread_(true) {}
+ off_thread_paint_state_(
+ RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()
+ ? OffThreadPaintState::kUnknown
+ : OffThreadPaintState::kMainThread) {}
CSSPaintValue::CSSPaintValue(
CSSCustomIdentValue* name,
@@ -51,6 +55,38 @@ String CSSPaintValue::GetName() const {
return name_->Value();
}
+const Vector<CSSPropertyID>* CSSPaintValue::NativeInvalidationProperties(
+ const Document& document) const {
+ if (!generators_.Contains(&document))
+ return nullptr;
+ return &(generators_.at(&document)->NativeInvalidationProperties());
+}
+
+const Vector<AtomicString>* CSSPaintValue::CustomInvalidationProperties(
+ const Document& document) const {
+ if (!generators_.Contains(&document))
+ return nullptr;
+ return &(generators_.at(&document)->CustomInvalidationProperties());
+}
+
+bool CSSPaintValue::IsUsingCustomProperty(
+ const AtomicString& custom_property_name,
+ const Document& document) const {
+ if (!generators_.Contains(&document) ||
+ !generators_.at(&document)->IsImageGeneratorReady())
+ return false;
+ return generators_.at(&document)->CustomInvalidationProperties().Contains(
+ custom_property_name);
+}
+
+void CSSPaintValue::CreateGeneratorForTesting(const Document& document) {
+ if (!generators_.Contains(&document)) {
+ generators_.insert(
+ &document, CSSPaintImageGenerator::Create(
+ GetName(), document, paint_image_generator_observer_));
+ }
+}
+
scoped_refptr<Image> CSSPaintValue::GetImage(
const ImageResourceObserver& client,
const Document& document,
@@ -61,15 +97,16 @@ scoped_refptr<Image> CSSPaintValue::GetImage(
if (style.InsideLink() != EInsideLink::kNotInsideLink)
return nullptr;
- if (!generator_) {
- generator_ = CSSPaintImageGenerator::Create(
- GetName(), document, paint_image_generator_observer_);
+ if (!generators_.Contains(&document)) {
+ generators_.insert(
+ &document, CSSPaintImageGenerator::Create(
+ GetName(), document, paint_image_generator_observer_));
}
// If the generator isn't ready yet, we have nothing to paint. Our
// |paint_image_generator_observer_| will cause us to be called again once the
// generator is ready.
- if (!generator_->IsImageGeneratorReady())
+ if (!generators_.at(&document)->IsImageGeneratorReady())
return nullptr;
if (!ParseInputArguments(document))
@@ -91,40 +128,49 @@ scoped_refptr<Image> CSSPaintValue::GetImage(
// For Off-Thread PaintWorklet, we just collect the necessary inputs together
// and defer the actual JavaScript call until much later (during cc Raster).
- if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
- if (paint_off_thread_) {
- // It is not necessary for a LayoutObject to always have RareData which
- // contains the ElementId. If this |layout_object| doesn't have an
- // ElementId, then create one for it.
- layout_object.GetMutableForPainting().EnsureId();
-
- Vector<CSSPropertyID> native_properties =
- generator_->NativeInvalidationProperties();
- Vector<AtomicString> custom_properties =
- generator_->CustomInvalidationProperties();
- float zoom = layout_object.StyleRef().EffectiveZoom();
- CompositorPaintWorkletInput::PropertyKeys input_property_keys;
- auto style_data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
- document, layout_object.UniqueId(), style, native_properties,
- custom_properties, input_property_keys);
- paint_off_thread_ = style_data.has_value();
- if (paint_off_thread_) {
- Vector<std::unique_ptr<CrossThreadStyleValue>>
- cross_thread_input_arguments;
- BuildInputArgumentValues(cross_thread_input_arguments);
- scoped_refptr<PaintWorkletInput> input =
- base::MakeRefCounted<PaintWorkletInput>(
- GetName(), target_size, zoom, device_scale_factor,
- generator_->WorkletId(), std::move(style_data.value()),
- std::move(cross_thread_input_arguments),
- std::move(input_property_keys));
- return PaintWorkletDeferredImage::Create(std::move(input), target_size);
- }
+ //
+ // Generating print-previews happens entirely on the main thread, so we have
+ // to fall-back to main in that case.
+ if (off_thread_paint_state_ != OffThreadPaintState::kMainThread &&
+ !document.Printing()) {
+ // It is not necessary for a LayoutObject to always have RareData which
+ // contains the ElementId. If this |layout_object| doesn't have an
+ // ElementId, then create one for it.
+ layout_object.GetMutableForPainting().EnsureId();
+
+ Vector<CSSPropertyID> native_properties =
+ generators_.at(&document)->NativeInvalidationProperties();
+ Vector<AtomicString> custom_properties =
+ generators_.at(&document)->CustomInvalidationProperties();
+ float zoom = layout_object.StyleRef().EffectiveZoom();
+ CompositorPaintWorkletInput::PropertyKeys input_property_keys;
+ auto style_data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
+ document, layout_object.UniqueId(), style, native_properties,
+ custom_properties, input_property_keys);
+ if (off_thread_paint_state_ == OffThreadPaintState::kUnknown) {
+ UMA_HISTOGRAM_BOOLEAN("Blink.CSSPaintValue.PaintOffThread",
+ style_data.has_value());
+ }
+ off_thread_paint_state_ = style_data.has_value()
+ ? OffThreadPaintState::kOffThread
+ : OffThreadPaintState::kMainThread;
+ if (off_thread_paint_state_ == OffThreadPaintState::kOffThread) {
+ Vector<std::unique_ptr<CrossThreadStyleValue>>
+ cross_thread_input_arguments;
+ BuildInputArgumentValues(cross_thread_input_arguments);
+ scoped_refptr<PaintWorkletInput> input =
+ base::MakeRefCounted<PaintWorkletInput>(
+ GetName(), target_size, zoom, device_scale_factor,
+ generators_.at(&document)->WorkletId(),
+ std::move(style_data.value()),
+ std::move(cross_thread_input_arguments),
+ std::move(input_property_keys));
+ return PaintWorkletDeferredImage::Create(std::move(input), target_size);
}
}
- return generator_->Paint(client, target_size, parsed_input_arguments_,
- device_scale_factor);
+ return generators_.at(&document)->Paint(
+ client, target_size, parsed_input_arguments_, device_scale_factor);
}
void CSSPaintValue::BuildInputArgumentValues(
@@ -147,9 +193,9 @@ bool CSSPaintValue::ParseInputArguments(const Document& document) {
!RuntimeEnabledFeatures::CSSPaintAPIArgumentsEnabled())
return true;
- DCHECK(generator_->IsImageGeneratorReady());
+ DCHECK(generators_.at(&document)->IsImageGeneratorReady());
const Vector<CSSSyntaxDefinition>& input_argument_types =
- generator_->InputArgumentTypes();
+ generators_.at(&document)->InputArgumentTypes();
if (argument_variable_data_.size() != input_argument_types.size()) {
input_arguments_invalid_ = true;
return false;
@@ -188,9 +234,9 @@ void CSSPaintValue::PaintImageGeneratorReady() {
}
}
-bool CSSPaintValue::KnownToBeOpaque(const Document&,
+bool CSSPaintValue::KnownToBeOpaque(const Document& document,
const ComputedStyle&) const {
- return generator_ && !generator_->HasAlpha();
+ return generators_.at(&document) && !generators_.at(&document)->HasAlpha();
}
bool CSSPaintValue::Equals(const CSSPaintValue& other) const {
@@ -200,7 +246,7 @@ bool CSSPaintValue::Equals(const CSSPaintValue& other) const {
void CSSPaintValue::TraceAfterDispatch(blink::Visitor* visitor) {
visitor->Trace(name_);
- visitor->Trace(generator_);
+ visitor->Trace(generators_);
visitor->Trace(paint_image_generator_observer_);
visitor->Trace(parsed_input_arguments_);
CSSImageGeneratorValue::TraceAfterDispatch(visitor);
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 7b384a0834b..fcf98c8a0ed 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
@@ -44,12 +44,10 @@ class CORE_EXPORT CSSPaintValue : public CSSImageGeneratorValue {
bool Equals(const CSSPaintValue&) const;
- const Vector<CSSPropertyID>* NativeInvalidationProperties() const {
- return generator_ ? &generator_->NativeInvalidationProperties() : nullptr;
- }
- const Vector<AtomicString>* CustomInvalidationProperties() const {
- return generator_ ? &generator_->CustomInvalidationProperties() : nullptr;
- }
+ const Vector<CSSPropertyID>* NativeInvalidationProperties(
+ const Document&) const;
+ const Vector<AtomicString>* CustomInvalidationProperties(
+ const Document&) const;
const CSSStyleValueVector* GetParsedInputArgumentsForTesting() {
return parsed_input_arguments_;
@@ -64,6 +62,12 @@ class CORE_EXPORT CSSPaintValue : public CSSImageGeneratorValue {
return this;
}
+ bool IsUsingCustomProperty(const AtomicString& custom_property_name,
+ const Document&) const;
+
+ void CreateGeneratorForTesting(const Document& document);
+ unsigned NumberOfGeneratorsForTesting() const { return generators_.size(); }
+
void TraceAfterDispatch(blink::Visitor*);
private:
@@ -94,13 +98,21 @@ class CORE_EXPORT CSSPaintValue : public CSSImageGeneratorValue {
bool input_arguments_invalid_ = false;
Member<CSSCustomIdentValue> name_;
- Member<CSSPaintImageGenerator> generator_;
+ // CSSValues may be shared between Documents. This map stores the
+ // CSSPaintImageGenerator for each Document using this CSSPaintValue. We use a
+ // WeakMember to ensure that entries are removed when Documents are destroyed
+ // (since the CSSValue may outlive any given Document).
+ HeapHashMap<WeakMember<const Document>, Member<CSSPaintImageGenerator>>
+ generators_;
Member<Observer> paint_image_generator_observer_;
Member<CSSStyleValueVector> parsed_input_arguments_;
Vector<scoped_refptr<CSSVariableData>> argument_variable_data_;
+ enum class OffThreadPaintState { kUnknown, kOffThread, kMainThread };
+ // Indicates whether this paint worklet is composited or not. kUnknown
+ // indicates that it has not been decided yet.
// TODO(crbug.com/987974): Make this variable reset when there is a style
// change.
- bool paint_off_thread_;
+ OffThreadPaintState off_thread_paint_state_;
};
template <>
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 e1d9340ff08..03fe77e1be1 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
@@ -10,13 +10,16 @@
#include "testing/gtest/include/gtest/gtest.h"
#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/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"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/paint_generated_image.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"
@@ -43,6 +46,9 @@ class CSSPaintValueTest : public RenderingTest,
: ScopedCSSPaintAPIArgumentsForTest(GetParam() & kCSSPaintAPIArguments),
ScopedOffMainThreadCSSPaintForTest(GetParam() &
kOffMainThreadCSSPaint) {}
+
+ // TODO(xidachen): a mock_generator is used in many tests in this file, put
+ // that in a Setup method.
};
INSTANTIATE_TEST_SUITE_P(,
@@ -53,37 +59,6 @@ INSTANTIATE_TEST_SUITE_P(,
kCSSPaintAPIArguments |
kOffMainThreadCSSPaint));
-class MockCSSPaintImageGenerator : public CSSPaintImageGenerator {
- public:
- MockCSSPaintImageGenerator() {
- // These methods return references, so setup a default ON_CALL to make them
- // easier to use. They can be overridden by a specific test if desired.
- ON_CALL(*this, NativeInvalidationProperties())
- .WillByDefault(ReturnRef(native_properties_));
- ON_CALL(*this, CustomInvalidationProperties())
- .WillByDefault(ReturnRef(custom_properties_));
- ON_CALL(*this, InputArgumentTypes())
- .WillByDefault(ReturnRef(input_argument_types_));
- }
-
- MOCK_METHOD4(Paint,
- scoped_refptr<Image>(const ImageResourceObserver&,
- const FloatSize& container_size,
- const CSSStyleValueVector*,
- float device_scale_factor));
- MOCK_CONST_METHOD0(NativeInvalidationProperties, Vector<CSSPropertyID>&());
- MOCK_CONST_METHOD0(CustomInvalidationProperties, Vector<AtomicString>&());
- MOCK_CONST_METHOD0(HasAlpha, bool());
- MOCK_CONST_METHOD0(InputArgumentTypes, Vector<CSSSyntaxDefinition>&());
- MOCK_CONST_METHOD0(IsImageGeneratorReady, bool());
- MOCK_CONST_METHOD0(WorkletId, int());
-
- private:
- Vector<CSSPropertyID> native_properties_;
- Vector<AtomicString> custom_properties_;
- Vector<CSSSyntaxDefinition> input_argument_types_;
-};
-
// CSSPaintImageGenerator requires that CSSPaintImageGeneratorCreateFunction be
// a static method. As such, it cannot access a class member and so instead we
// store a pointer to the overriding generator globally.
@@ -96,6 +71,103 @@ CSSPaintImageGenerator* ProvideOverrideGenerator(
}
} // namespace
+TEST_P(CSSPaintValueTest, ReportingCompositedUMA) {
+ HistogramTester histogram_tester;
+ NiceMock<MockCSSPaintImageGenerator>* mock_generator =
+ MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
+ base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
+ &g_override_generator, mock_generator);
+ base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
+ scoped_create_function(
+ CSSPaintImageGenerator::GetCreateFunctionForTesting(),
+ ProvideOverrideGenerator);
+
+ const FloatSize target_size(100, 100);
+
+ SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML");
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ const ComputedStyle& style = *target->Style();
+
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+ // Mark the generator as ready - GetImage should succeed when
+ // OffMainThreadCSSPaint is enabled.
+ ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
+ ON_CALL(*mock_generator, Paint(_, _, _, _))
+ .WillByDefault(Return(PaintGeneratedImage::Create(nullptr, target_size)));
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), style, target_size));
+ if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u);
+ histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread",
+ true, 1u);
+ } else {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u);
+ }
+
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), style, target_size));
+ if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
+ // Repaint, should not report histogram again.
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u);
+ histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread",
+ true, 1u);
+ } else {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u);
+ }
+}
+
+TEST_P(CSSPaintValueTest, ReportingNonCompositedUMA) {
+ HistogramTester histogram_tester;
+ NiceMock<MockCSSPaintImageGenerator>* mock_generator =
+ MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
+ mock_generator->AddNativeProperty();
+ base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
+ &g_override_generator, mock_generator);
+ base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
+ scoped_create_function(
+ CSSPaintImageGenerator::GetCreateFunctionForTesting(),
+ ProvideOverrideGenerator);
+
+ const FloatSize target_size(100, 100);
+
+ SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML");
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ auto style = ComputedStyle::Create();
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+ StyleGeneratedImage* style_image =
+ MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
+ style->SetBorderImageSource(style_image);
+
+ ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
+ EXPECT_CALL(*mock_generator, Paint(_, _, _, _))
+ .WillRepeatedly(
+ Return(PaintGeneratedImage::Create(nullptr, target_size)));
+ // The paint worklet is not composited, and falls back to the main thread
+ // paint.
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), *style, target_size));
+ if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u);
+ histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread",
+ false, 1u);
+ } else {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u);
+ }
+
+ // Repaint, should not report histogram again.
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), *style, target_size));
+ if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u);
+ histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread",
+ false, 1u);
+ } else {
+ histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u);
+ }
+}
+
TEST_P(CSSPaintValueTest, DelayPaintUntilGeneratorReady) {
NiceMock<MockCSSPaintImageGenerator>* mock_generator =
MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
@@ -137,6 +209,99 @@ TEST_P(CSSPaintValueTest, DelayPaintUntilGeneratorReady) {
paint_value->GetImage(*target, GetDocument(), style, target_size));
}
+// Regression test for crbug.com/998439. The problem is that GetImage is called
+// on a new document. This test simulates the situation by having two different
+// documents and call GetImage on different ones.
+TEST_P(CSSPaintValueTest, GetImageCalledOnMultipleDocuments) {
+ const FloatSize target_size(100, 100);
+
+ SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML");
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ const ComputedStyle& style = *target->Style();
+
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+
+ EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 0u);
+ paint_value->GetImage(*target, GetDocument(), style, target_size);
+ // A new generator should be created if there is no generator exists.
+ EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 1u);
+
+ auto new_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
+ // Call GetImage on a new Document should not crash.
+ paint_value->GetImage(*target, new_page_holder->GetDocument(), style,
+ target_size);
+ EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 2u);
+}
+
+TEST_P(CSSPaintValueTest, NativeInvalidationPropertiesWithNoGenerator) {
+ SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML");
+
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+
+ EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 0u);
+ // There is no generator, so returning a nullptr.
+ EXPECT_EQ(paint_value->NativeInvalidationProperties(GetDocument()), nullptr);
+}
+
+TEST_P(CSSPaintValueTest, CustomInvalidationPropertiesWithNoGenerator) {
+ SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML");
+
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+
+ EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 0u);
+ // There is no generator, so returning a nullptr.
+ EXPECT_EQ(paint_value->CustomInvalidationProperties(GetDocument()), nullptr);
+}
+
+TEST_P(CSSPaintValueTest, PrintingMustFallbackToMainThread) {
+ if (!RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled())
+ return;
+
+ NiceMock<MockCSSPaintImageGenerator>* mock_generator =
+ MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
+ base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator(
+ &g_override_generator, mock_generator);
+ base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction>
+ scoped_create_function(
+ CSSPaintImageGenerator::GetCreateFunctionForTesting(),
+ ProvideOverrideGenerator);
+
+ const FloatSize target_size(100, 100);
+
+ SetBodyInnerHTML(R"HTML(
+ <div id="target"></div>
+ )HTML");
+ LayoutObject* target = GetLayoutObjectByElementId("target");
+ const ComputedStyle& style = *target->Style();
+
+ auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter");
+ CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident);
+
+ ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
+ // This PW can be composited, so we should only fall back to main once, in
+ // the case where we are printing.
+ EXPECT_CALL(*mock_generator, Paint(_, _, _, _))
+ .Times(1)
+ .WillOnce(Return(PaintGeneratedImage::Create(nullptr, target_size)));
+
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), style, target_size));
+
+ // Start printing; our paint should run on the main thread (and thus call
+ // Paint).
+ GetDocument().SetPrinting(Document::kPrinting);
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), style, target_size));
+
+ // Stop printing; we should return to the compositor.
+ GetDocument().SetPrinting(Document::kNotPrinting);
+ ASSERT_TRUE(
+ paint_value->GetImage(*target, GetDocument(), style, target_size));
+}
+
// Regression test for https://crbug.com/835589.
TEST_P(CSSPaintValueTest, DoNotPaintForLink) {
SetBodyInnerHTML(R"HTML(
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 755063b48f9..e49b90bfff3 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
@@ -754,6 +754,37 @@ inline FontDescription::Kerning CSSIdentifierValue::ConvertTo() const {
}
template <>
+inline CSSIdentifierValue::CSSIdentifierValue(OpticalSizing optical_sizing)
+ : CSSValue(kIdentifierClass) {
+ switch (optical_sizing) {
+ case kAutoOpticalSizing:
+ value_id_ = CSSValueID::kAuto;
+ return;
+ case kNoneOpticalSizing:
+ value_id_ = CSSValueID::kNone;
+ return;
+ }
+
+ NOTREACHED();
+ value_id_ = CSSValueID::kAuto;
+}
+
+template <>
+inline OpticalSizing CSSIdentifierValue::ConvertTo() const {
+ switch (value_id_) {
+ case CSSValueID::kAuto:
+ return kAutoOpticalSizing;
+ case CSSValueID::kNone:
+ return kNoneOpticalSizing;
+ default:
+ break;
+ }
+
+ NOTREACHED();
+ return kAutoOpticalSizing;
+}
+
+template <>
inline CSSIdentifierValue::CSSIdentifierValue(EFillSizeType fill_size)
: CSSValue(kIdentifierClass) {
switch (fill_size) {
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 937dcec119b..4924191a8a5 100644
--- a/chromium/third_party/blink/renderer/core/css/css_properties.json5
+++ b/chromium/third_party/blink/renderer/core/css/css_properties.json5
@@ -636,6 +636,17 @@
typedom_types: ["Keyword"],
},
{
+ name: "font-optical-sizing",
+ property_methods: ["CSSValueFromComputedStyleInternal"],
+ inherited: true,
+ font: true,
+ name_for_methods: "FontOpticalSizing",
+ type_name: "OpticalSizing",
+ priority: "High",
+ keywords: ["auto", "none"],
+ typedom_types: ["Keyword"]
+ },
+ {
name: "font-size",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
@@ -2093,9 +2104,8 @@
},
{
name: "list-style-type",
- property_methods: ["CSSValueFromComputedStyleInternal"],
+ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
- field_template: "keyword",
keywords: [
"disc", "circle", "square", "decimal", "decimal-leading-zero",
"arabic-indic", "bengali", "cambodian", "khmer", "devanagari",
@@ -2111,7 +2121,7 @@
"simp-chinese-informal", "trad-chinese-formal", "trad-chinese-informal",
"hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none"
],
- default_value: "disc",
+ style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
name: "margin-bottom",
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 fb283eb8e82..f7dac058925 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
@@ -83,7 +83,7 @@ WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::CSSPropertySourceData)
namespace blink {
-class CSSRuleSourceData : public GarbageCollectedFinalized<CSSRuleSourceData> {
+class CSSRuleSourceData final : public GarbageCollected<CSSRuleSourceData> {
public:
explicit CSSRuleSourceData(StyleRule::RuleType type) : type(type) {}
void Trace(blink::Visitor* visitor) { visitor->Trace(child_rules); }
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 50ae3d7403e..2b5940ed826 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
@@ -652,8 +652,8 @@ unsigned CSSPropertyValueSet::AverageSizeInBytes() {
}
// See the function above if you need to update this.
-struct SameSizeAsCSSPropertyValueSet
- : public GarbageCollectedFinalized<SameSizeAsCSSPropertyValueSet> {
+struct SameSizeAsCSSPropertyValueSet final
+ : public GarbageCollected<SameSizeAsCSSPropertyValueSet> {
unsigned bitfield;
};
static_assert(sizeof(CSSPropertyValueSet) ==
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 7ac228e89e7..a16b05b588f 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
@@ -44,7 +44,7 @@ enum class CSSValueID;
enum class SecureContextMode;
class CORE_EXPORT CSSPropertyValueSet
- : public GarbageCollectedFinalized<CSSPropertyValueSet> {
+ : public GarbageCollected<CSSPropertyValueSet> {
friend class PropertyReference;
public:
@@ -166,8 +166,7 @@ class CORE_EXPORT CSSPropertyValueSet
};
// Used for lazily parsing properties.
-class CSSLazyPropertyParser
- : public GarbageCollectedFinalized<CSSLazyPropertyParser> {
+class CSSLazyPropertyParser : public GarbageCollected<CSSLazyPropertyParser> {
public:
CSSLazyPropertyParser() = default;
virtual ~CSSLazyPropertyParser() = default;
diff --git a/chromium/third_party/blink/renderer/core/css/css_resource_fetch_restriction.h b/chromium/third_party/blink/renderer/core/css/css_resource_fetch_restriction.h
new file mode 100644
index 00000000000..c55a92a914d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/css_resource_fetch_restriction.h
@@ -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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_RESOURCE_FETCH_RESTRICTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_RESOURCE_FETCH_RESTRICTION_H_
+
+namespace blink {
+
+enum class ResourceFetchRestriction { kNone, kOnlyDataUrls };
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_RESOURCE_FETCH_RESTRICTION_H_
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 ccbe58bfb05..15d3d4da2a2 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.cc
@@ -27,7 +27,7 @@
namespace blink {
-struct SameSizeAsCSSRule : public GarbageCollectedFinalized<SameSizeAsCSSRule>,
+struct SameSizeAsCSSRule : public GarbageCollected<SameSizeAsCSSRule>,
public ScriptWrappable {
~SameSizeAsCSSRule() override;
unsigned char bitfields;
diff --git a/chromium/third_party/blink/renderer/core/css/css_rule.h b/chromium/third_party/blink/renderer/core/css/css_rule.h
index 3036f6ea9b7..4dbd80e8815 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.h
@@ -55,7 +55,6 @@ class CORE_EXPORT CSSRule : public ScriptWrappable {
kKeyframeRule = 8,
kNamespaceRule = 10,
kSupportsRule = 12,
- kFontFeatureValuesRule = 14,
kViewportRule = 15,
// Experimental features below. Such features must be greater than 1000:
// the 0-1000 range is reserved by the CSS Working Group.
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 d63735b882f..96679da64ad 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.idl
@@ -46,10 +46,6 @@
// https://drafts.csswg.org/css-conditional/#extentions-to-cssrule-interface
const unsigned short SUPPORTS_RULE = 12;
- // CSS Fonts Level 4
- // https://drafts.csswg.org/css-fonts-4/#font-feature-values
- [RuntimeEnabled=CSSFontFeatureValues] const unsigned short FONT_FEATURE_VALUES_RULE = 14;
-
// CSS Device Adaptation
// https://drafts.csswg.org/css-device-adapt/#css-rule-interface
[RuntimeEnabled=CSSViewport] const unsigned short VIEWPORT_RULE = 15;
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 4326210e933..fad468a96b4 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
@@ -43,7 +43,7 @@ class FontFace;
class SegmentedFontData;
class CSSSegmentedFontFace final
- : public GarbageCollectedFinalized<CSSSegmentedFontFace> {
+ : public GarbageCollected<CSSSegmentedFontFace> {
public:
CSSSegmentedFontFace(FontSelectionCapabilities);
~CSSSegmentedFontFace();
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 e441087e457..66db83fef26 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.cc
@@ -278,6 +278,7 @@ PseudoId CSSSelector::GetPseudoId(PseudoType type) {
case kPseudoHost:
case kPseudoHostContext:
case kPseudoPart:
+ case kPseudoState:
case kPseudoShadow:
case kPseudoFullScreen:
case kPseudoFullScreenAncestor:
@@ -291,6 +292,7 @@ PseudoId CSSSelector::GetPseudoId(PseudoType type) {
case kPseudoSlotted:
case kPseudoVideoPersistent:
case kPseudoVideoPersistentAncestor:
+ case kPseudoXrImmersiveDomOverlay:
return kPseudoIdNone;
}
@@ -323,6 +325,8 @@ const static NameToPseudoStruct kPseudoTypeWithoutArgumentsMap[] = {
{"-internal-video-persistent", CSSSelector::kPseudoVideoPersistent},
{"-internal-video-persistent-ancestor",
CSSSelector::kPseudoVideoPersistentAncestor},
+ {"-internal-xr-immersive-dom-overlay",
+ CSSSelector::kPseudoXrImmersiveDomOverlay},
{"-webkit-any-link", CSSSelector::kPseudoWebkitAnyLink},
{"-webkit-autofill", CSSSelector::kPseudoAutofill},
{"-webkit-drag", CSSSelector::kPseudoDrag},
@@ -415,6 +419,7 @@ const static NameToPseudoStruct kPseudoTypeWithArgumentsMap[] = {
{"nth-of-type", CSSSelector::kPseudoNthOfType},
{"part", CSSSelector::kPseudoPart},
{"slotted", CSSSelector::kPseudoSlotted},
+ {"state", CSSSelector::kPseudoState},
{"where", CSSSelector::kPseudoWhere},
};
@@ -456,6 +461,11 @@ static CSSSelector::PseudoType NameToPseudoType(const AtomicString& name,
!RuntimeEnabledFeatures::CSSPictureInPictureEnabled())
return CSSSelector::kPseudoUnknown;
+ if (match->type == CSSSelector::kPseudoState &&
+ !RuntimeEnabledFeatures::CustomStatePseudoClassEnabled()) {
+ return CSSSelector::kPseudoUnknown;
+ }
+
return static_cast<CSSSelector::PseudoType>(match->type);
}
@@ -578,6 +588,7 @@ void CSSSelector::UpdatePseudoType(const AtomicString& value,
case kPseudoSpatialNavigationInterest:
case kPseudoVideoPersistent:
case kPseudoVideoPersistentAncestor:
+ case kPseudoXrImmersiveDomOverlay:
if (mode != kUASheetMode) {
pseudo_type_ = kPseudoUnknown;
break;
@@ -645,6 +656,7 @@ void CSSSelector::UpdatePseudoType(const AtomicString& value,
case kPseudoScope:
case kPseudoSingleButton:
case kPseudoStart:
+ case kPseudoState:
case kPseudoTarget:
case kPseudoUnknown:
case kPseudoValid:
@@ -764,6 +776,7 @@ const CSSSelector* CSSSelector::SerializeCompound(
break;
}
case kPseudoLang:
+ case kPseudoState:
builder.Append('(');
builder.Append(simple_selector->Argument());
builder.Append(')');
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 7729ab802f6..e6b66610efc 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.h
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.h
@@ -160,6 +160,7 @@ class CORE_EXPORT CSSSelector {
kPseudoNthLastChild,
kPseudoNthLastOfType,
kPseudoPart,
+ kPseudoState,
kPseudoLink,
kPseudoVisited,
kPseudoAny,
@@ -250,6 +251,7 @@ class CORE_EXPORT CSSSelector {
kPseudoSlotted,
kPseudoVideoPersistent,
kPseudoVideoPersistentAncestor,
+ kPseudoXrImmersiveDomOverlay,
};
enum AttributeMatchType {
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector_list.h b/chromium/third_party/blink/renderer/core/css/css_selector_list.h
index 4d38b0942e9..51f354b6bf4 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector_list.h
+++ b/chromium/third_party/blink/renderer/core/css/css_selector_list.h
@@ -67,8 +67,7 @@ class CORE_EXPORT CSSSelectorList {
public:
CSSSelectorList() : selector_array_(nullptr) {}
- CSSSelectorList(CSSSelectorList&& o) noexcept
- : selector_array_(o.selector_array_) {
+ CSSSelectorList(CSSSelectorList&& o) : selector_array_(o.selector_array_) {
o.selector_array_ = nullptr;
}
@@ -82,7 +81,7 @@ class CORE_EXPORT CSSSelectorList {
bool HasPseudoWhere() const;
bool RequiresExpansion() const;
- CSSSelectorList& operator=(CSSSelectorList&& o) noexcept {
+ CSSSelectorList& operator=(CSSSelectorList&& o) {
DCHECK(this != &o);
DeleteSelectorsIfNeeded();
selector_array_ = o.selector_array_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector_watch.h b/chromium/third_party/blink/renderer/core/css/css_selector_watch.h
index 7791ba78f91..16df789b574 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector_watch.h
+++ b/chromium/third_party/blink/renderer/core/css/css_selector_watch.h
@@ -43,7 +43,7 @@
namespace blink {
class CORE_EXPORT CSSSelectorWatch final
- : public GarbageCollectedFinalized<CSSSelectorWatch>,
+ : public GarbageCollected<CSSSelectorWatch>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(CSSSelectorWatch);
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 233df4a404f..5cd917af122 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
@@ -47,8 +47,8 @@ CSSToLengthConversionData::FontSizes::FontSizes(float em,
CSSToLengthConversionData::FontSizes::FontSizes(const ComputedStyle* style,
const ComputedStyle* root_style)
- : FontSizes(style->ComputedFontSize(),
- root_style ? root_style->ComputedFontSize() : 1.0f,
+ : FontSizes(style->SpecifiedFontSize(),
+ root_style ? root_style->SpecifiedFontSize() : 1.0f,
&style->GetFont(),
style->EffectiveZoom()) {}
@@ -175,13 +175,13 @@ double CSSToLengthConversionData::ZoomedComputedPixels(
// as well as enforcing the implicit "smart minimum."
case CSSPrimitiveValue::UnitType::kEms:
case CSSPrimitiveValue::UnitType::kQuirkyEms:
- return value * EmFontSize();
+ return value * EmFontSize() * Zoom();
case CSSPrimitiveValue::UnitType::kExs:
return value * ExFontSize();
case CSSPrimitiveValue::UnitType::kRems:
- return value * RemFontSize();
+ return value * RemFontSize() * Zoom();
case CSSPrimitiveValue::UnitType::kChs:
return value * ChFontSize();
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 1c0a54ad5d7..604562a5a46 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_value.cc
@@ -55,6 +55,7 @@
#include "third_party/blink/renderer/core/css/css_invalid_variable_value.h"
#include "third_party/blink/renderer/core/css/css_keyframe_shorthand_value.h"
#include "third_party/blink/renderer/core/css/css_layout_function_value.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_paint_value.h"
@@ -81,8 +82,7 @@ namespace blink {
using namespace cssvalue;
-struct SameSizeAsCSSValue
- : public GarbageCollectedFinalized<SameSizeAsCSSValue> {
+struct SameSizeAsCSSValue final : public GarbageCollected<SameSizeAsCSSValue> {
uint32_t bitfields;
};
ASSERT_SIZE(CSSValue, SameSizeAsCSSValue);
@@ -263,6 +263,8 @@ bool CSSValue::operator==(const CSSValue& other) const {
return CompareCSSValues<CSSPendingSubstitutionValue>(*this, other);
case kInvalidVariableValueClass:
return CompareCSSValues<CSSInvalidVariableValue>(*this, other);
+ case kLightDarkColorPairClass:
+ return CompareCSSValues<CSSLightDarkColorPair>(*this, other);
}
NOTREACHED();
return false;
@@ -378,6 +380,8 @@ String CSSValue::CssText() const {
return To<CSSPendingSubstitutionValue>(this)->CustomCSSText();
case kInvalidVariableValueClass:
return To<CSSInvalidVariableValue>(this)->CustomCSSText();
+ case kLightDarkColorPairClass:
+ return To<CSSLightDarkColorPair>(this)->CustomCSSText();
}
NOTREACHED();
return String();
@@ -545,6 +549,9 @@ void CSSValue::FinalizeGarbageCollectedObject() {
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->~CSSInvalidVariableValue();
return;
+ case kLightDarkColorPairClass:
+ To<CSSLightDarkColorPair>(this)->~CSSLightDarkColorPair();
+ return;
}
NOTREACHED();
}
@@ -710,6 +717,9 @@ void CSSValue::Trace(blink::Visitor* visitor) {
case kInvalidVariableValueClass:
To<CSSInvalidVariableValue>(this)->TraceAfterDispatch(visitor);
return;
+ case kLightDarkColorPairClass:
+ To<CSSLightDarkColorPair>(this)->TraceAfterDispatch(visitor);
+ return;
}
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_value.h b/chromium/third_party/blink/renderer/core/css/css_value.h
index 0673a4a3085..8b24591556a 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value.h
@@ -31,7 +31,7 @@ namespace blink {
class Document;
class Length;
-class CORE_EXPORT CSSValue : public GarbageCollectedFinalized<CSSValue> {
+class CORE_EXPORT CSSValue : public GarbageCollected<CSSValue> {
public:
static void* AllocateObject(size_t size) {
ThreadState* state =
@@ -171,6 +171,9 @@ class CORE_EXPORT CSSValue : public GarbageCollectedFinalized<CSSValue> {
bool IsShorthandWrapperValue() const {
return class_type_ == kKeyframeShorthandClass;
}
+ bool IsLightDarkColorPair() const {
+ return class_type_ == kLightDarkColorPairClass;
+ }
bool HasFailedOrCanceledSubresources() const;
bool MayContainUrl() const;
@@ -201,6 +204,7 @@ class CORE_EXPORT CSSValue : public GarbageCollectedFinalized<CSSValue> {
kStringClass,
kURIClass,
kValuePairClass,
+ kLightDarkColorPairClass,
// Basic shape classes.
// TODO(sashab): Represent these as a single subclass, BasicShapeClass.
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 ffa22b63c70..c6490c88d49 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
@@ -174,6 +174,130 @@ 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::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:
+ NOTREACHED();
+ break;
+ }
+
+ NOTREACHED();
+ return EListStyleType::kDisc;
+}
+
+template <>
inline EUserSelect CssValueIDToPlatformEnum(CSSValueID v) {
if (v == CSSValueID::kAuto)
return EUserSelect::kAuto;
@@ -233,6 +357,130 @@ inline CSSValueID PlatformEnumToCSSValueID(EDisplay v) {
return CSSValueID::kInline;
}
+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::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;
+}
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5 b/chromium/third_party/blink/renderer/core/css/css_value_keywords.json5
index 205af759b97..1010ca9287d 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
@@ -1205,5 +1205,9 @@
// (forced-colors:) media feature
// none
"active",
+
+ // (navigation-controls) media feature
+ // none
+ "back-button",
],
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_pair.h b/chromium/third_party/blink/renderer/core/css/css_value_pair.h
index d36680d0f4e..2cd6b476e46 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_pair.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_pair.h
@@ -66,6 +66,18 @@ class CORE_EXPORT CSSValuePair : public CSSValue {
void TraceAfterDispatch(blink::Visitor*);
+ protected:
+ CSSValuePair(ClassType class_type,
+ const CSSValue* first,
+ const CSSValue* second)
+ : CSSValue(class_type),
+ first_(first),
+ second_(second),
+ identical_values_policy_(kKeepIdenticalValues) {
+ DCHECK(first_);
+ DCHECK(second_);
+ }
+
private:
Member<const CSSValue> first_;
Member<const CSSValue> second_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_pool.h b/chromium/third_party/blink/renderer/core/css/css_value_pool.h
index ce42ae5e3b4..10d55b77ac1 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_pool.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_pool.h
@@ -48,9 +48,7 @@
namespace blink {
-class CORE_EXPORT CSSValuePool
- : public GarbageCollectedFinalized<CSSValuePool> {
-
+class CORE_EXPORT CSSValuePool final : public GarbageCollected<CSSValuePool> {
public:
using PassKey = util::PassKey<CSSValuePool>;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
index b1c7810b602..b3971d317ab 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
@@ -148,7 +148,7 @@ TEST_F(CrossThreadStyleValueTest, CrossThreadUnparsedValueToCSSStyleValue) {
CSSStyleValue* style_value = value->ToCSSStyleValue();
EXPECT_EQ(style_value->GetType(),
CSSStyleValue::StyleValueType::kUnparsedType);
- EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToStringForTesting(),
+ EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToString(),
"Unparsed");
}
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 b4aed733c2e..80f6e206f99 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
@@ -74,12 +74,12 @@ CSSMathExpressionNode* CSSMathMax::ToCalcExpressionNode() const {
if (!RuntimeEnabledFeatures::CSSComparisonFunctionsEnabled())
return nullptr;
- HeapVector<Member<CSSMathExpressionNode>> operands;
+ CSSMathExpressionVariadicOperation::Operands operands;
operands.ReserveCapacity(NumericValues().size());
for (const auto& value : NumericValues()) {
CSSMathExpressionNode* operand = value->ToCalcExpressionNode();
if (!operand) {
- // TODO(crbug.com/825895): Remove this when all ToCalcExpressionNode()
+ // TODO(crbug.com/983784): Remove this when all ToCalcExpressionNode()
// overrides are implemented.
NOTREACHED();
continue;
@@ -87,7 +87,7 @@ CSSMathExpressionNode* CSSMathMax::ToCalcExpressionNode() const {
operands.push_back(value->ToCalcExpressionNode());
}
if (!operands.size()) {
- // TODO(crbug.com/825895): Remove this when all ToCalcExpressionNode()
+ // TODO(crbug.com/983784): Remove this when all ToCalcExpressionNode()
// overrides are implemented.
NOTREACHED();
return nullptr;
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 e65b9bf1e70..7b8d0f8666f 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
@@ -73,12 +73,12 @@ CSSMathExpressionNode* CSSMathMin::ToCalcExpressionNode() const {
if (!RuntimeEnabledFeatures::CSSComparisonFunctionsEnabled())
return nullptr;
- HeapVector<Member<CSSMathExpressionNode>> operands;
+ CSSMathExpressionVariadicOperation::Operands operands;
operands.ReserveCapacity(NumericValues().size());
for (const auto& value : NumericValues()) {
CSSMathExpressionNode* operand = value->ToCalcExpressionNode();
if (!operand) {
- // TODO(crbug.com/825895): Remove this when all ToCalcExpressionNode()
+ // TODO(crbug.com/983784): Remove this when all ToCalcExpressionNode()
// overrides are implemented.
NOTREACHED();
continue;
@@ -86,7 +86,7 @@ CSSMathExpressionNode* CSSMathMin::ToCalcExpressionNode() const {
operands.push_back(value->ToCalcExpressionNode());
}
if (!operands.size()) {
- // TODO(crbug.com/825895): Remove this when all ToCalcExpressionNode()
+ // TODO(crbug.com/983784): Remove this when all ToCalcExpressionNode()
// overrides are implemented.
NOTREACHED();
return nullptr;
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 a25f4b38238..2b0c4e3f499 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
@@ -253,8 +253,8 @@ CSSNumericValue* CSSNumericValue::parse(const String& css_text,
range.Peek().FunctionId() == CSSValueID::kWebkitCalc ||
(RuntimeEnabledFeatures::CSSComparisonFunctionsEnabled() &&
(range.Peek().FunctionId() == CSSValueID::kMin ||
- range.Peek().FunctionId() == CSSValueID::kMax))) {
- // TODO(crbug.com/825895): Support clamp() after min()/max() are done.
+ range.Peek().FunctionId() == CSSValueID::kMax ||
+ range.Peek().FunctionId() == CSSValueID::kClamp))) {
CSSMathExpressionNode* expression =
CSSMathExpressionNode::ParseCalc(range);
if (expression)
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
index cff142e0ba6..552b4082192 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
@@ -95,10 +95,11 @@ CSSPositionValue* CSSPositionValue::Create(CSSNumericValue* x,
}
CSSPositionValue* CSSPositionValue::FromCSSValue(const CSSValue& value) {
- const auto& pair = To<CSSValuePair>(value);
-
- CSSNumericValue* x = FromSingleValue(pair.First());
- CSSNumericValue* y = FromSingleValue(pair.Second());
+ const auto* pair = DynamicTo<CSSValuePair>(&value);
+ if (!pair)
+ return nullptr;
+ CSSNumericValue* x = FromSingleValue(pair->First());
+ CSSNumericValue* y = FromSingleValue(pair->Second());
DCHECK(x);
DCHECK(y);
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 03545ced05b..7c87b475f86 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
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -58,17 +59,22 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
CSSStyleValue::Trace(visitor);
}
- String ToStringForTesting() const { return ToString(); }
-
- private:
String ToString() const;
+ private:
FRIEND_TEST_ALL_PREFIXES(CSSVariableReferenceValueTest, MixedList);
HeapVector<CSSUnparsedSegment> tokens_;
DISALLOW_COPY_AND_ASSIGN(CSSUnparsedValue);
};
+template <>
+struct DowncastTraits<CSSUnparsedValue> {
+ static bool AllowFrom(const CSSStyleValue& value) {
+ return value.GetType() == CSSStyleValue::StyleValueType::kUnparsedType;
+ }
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_UNPARSED_VALUE_H_
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
new file mode 100644
index 00000000000..87412c21f99
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map_test.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.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/style_property_shorthand.h"
+
+namespace blink {
+
+TEST(InlineStylePropertyMapTest, PendingSubstitutionValueCrash) {
+ // Test that trying to reify any longhands with a CSSPendingSubstitutionValue
+ // does not cause a crash.
+
+ Document* document = MakeGarbageCollected<Document>();
+ Element* div = document->CreateRawElement(html_names::kDivTag);
+ InlineStylePropertyMap map(div);
+
+ // For each shorthand, create a declaration with a var() reference and try
+ // reifying all longhands.
+ for (CSSPropertyID property_id : CSSPropertyIDList()) {
+ const CSSProperty& shorthand = CSSProperty::Get(property_id);
+ if (!shorthand.IsShorthand())
+ continue;
+ div->SetInlineStyleProperty(property_id, "var(--dummy)");
+ const StylePropertyShorthand& longhands = shorthandForProperty(property_id);
+ for (unsigned i = 0; i < longhands.length(); i++) {
+ map.get(document,
+ longhands.properties()[i]->GetCSSPropertyName().ToAtomicString(),
+ ASSERT_NO_EXCEPTION);
+ }
+ }
+}
+
+} // namespace blink
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 9828aa23706..f37d073af4f 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
@@ -20,12 +20,8 @@ void DrawInternal(cc::PaintCanvas* canvas,
const FloatRect& src_rect,
const PaintFlags& flags,
Image::ImageClampingMode clamping_mode,
- scoped_refptr<PaintWorkletInput> input) {
- canvas->drawImageRect(PaintImageBuilder::WithDefault()
- .set_paint_worklet_input(std::move(input))
- .set_id(PaintImage::GetNextId())
- .TakePaintImage(),
- src_rect, dest_rect, &flags,
+ const PaintImage& image) {
+ canvas->drawImageRect(image, src_rect, dest_rect, &flags,
WebCoreClampingModeToSkiaRectConstraint(clamping_mode));
}
} // namespace
@@ -37,28 +33,23 @@ void PaintWorkletDeferredImage::Draw(cc::PaintCanvas* canvas,
RespectImageOrientationEnum,
ImageClampingMode clamping_mode,
ImageDecodingMode) {
- DrawInternal(canvas, dest_rect, src_rect, flags, clamping_mode, input_);
+ DrawInternal(canvas, dest_rect, src_rect, flags, clamping_mode, image_);
}
void PaintWorkletDeferredImage::DrawTile(GraphicsContext& context,
const FloatRect& src_rect) {
DrawInternal(context.Canvas(), FloatRect(), src_rect, context.FillFlags(),
- kClampImageToSourceRect, input_);
+ kClampImageToSourceRect, image_);
}
sk_sp<PaintShader> PaintWorkletDeferredImage::CreateShader(
const FloatRect& tile_rect,
const SkMatrix* pattern_matrix,
const FloatRect& src_rect) {
- PaintImage image = PaintImageBuilder::WithDefault()
- .set_paint_worklet_input(std::move(input_))
- .set_id(PaintImage::GetNextId())
- .TakePaintImage();
-
SkRect tile = SkRect::MakeXYWH(tile_rect.X(), tile_rect.Y(),
tile_rect.Width(), tile_rect.Height());
sk_sp<PaintShader> shader = PaintShader::MakeImage(
- image, SkTileMode::kRepeat, SkTileMode::kRepeat, pattern_matrix, &tile);
+ image_, SkTileMode::kRepeat, SkTileMode::kRepeat, pattern_matrix, &tile);
return shader;
}
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 9ef8f716d82..11429a243ba 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
@@ -46,9 +46,14 @@ class CORE_EXPORT PaintWorkletDeferredImage : public GeneratedImage {
private:
PaintWorkletDeferredImage(scoped_refptr<PaintWorkletInput> input,
const FloatSize& size)
- : GeneratedImage(size), input_(input) {}
+ : GeneratedImage(size) {
+ image_ = PaintImageBuilder::WithDefault()
+ .set_paint_worklet_input(std::move(input))
+ .set_id(PaintImage::GetNextId())
+ .TakePaintImage();
+ }
- scoped_refptr<PaintWorkletInput> input_;
+ PaintImage image_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
index 78afb586182..67349970ad4 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
@@ -16,6 +16,8 @@
namespace blink {
+class ComputedStyle;
+
// This class is designed for CSS Paint such that it can be safely passed cross
// threads.
//
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
index a6f8e156a92..1ec9a507e94 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -12,8 +12,10 @@
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color_value.h"
#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h"
+#include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -47,55 +49,25 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
waitable_event.Wait();
}
- void CheckCustomProperties(const PaintWorkletStylePropertyMap* map,
- DummyExceptionStateForTesting& exception_state) {
- const CSSStyleValue* foo = map->get(nullptr, "--foo", exception_state);
- ASSERT_NE(nullptr, foo);
- ASSERT_EQ(CSSStyleValue::kUnknownType, foo->GetType());
- EXPECT_FALSE(exception_state.HadException());
+ void CheckUnregisteredProperty(base::WaitableEvent* waitable_event,
+ scoped_refptr<PaintWorkletInput> input) {
+ ASSERT_TRUE(!IsMainThread());
- EXPECT_EQ(true, map->has(nullptr, "--foo", exception_state));
- EXPECT_FALSE(exception_state.HadException());
-
- CSSStyleValueVector fooAll = map->getAll(nullptr, "--foo", exception_state);
- EXPECT_EQ(1U, fooAll.size());
- ASSERT_NE(nullptr, fooAll[0]);
- ASSERT_EQ(CSSStyleValue::kUnknownType, fooAll[0]->GetType());
- EXPECT_FALSE(exception_state.HadException());
-
- EXPECT_EQ(nullptr, map->get(nullptr, "--quix", exception_state));
- EXPECT_FALSE(exception_state.HadException());
-
- EXPECT_EQ(false, map->has(nullptr, "--quix", exception_state));
- EXPECT_FALSE(exception_state.HadException());
-
- EXPECT_EQ(CSSStyleValueVector(),
- map->getAll(nullptr, "--quix", exception_state));
- EXPECT_FALSE(exception_state.HadException());
- }
-
- void CheckNativeProperties(const PaintWorkletStylePropertyMap* map,
- DummyExceptionStateForTesting& exception_state) {
- map->get(nullptr, "color", exception_state);
- EXPECT_FALSE(exception_state.HadException());
-
- map->has(nullptr, "color", exception_state);
- EXPECT_FALSE(exception_state.HadException());
-
- map->getAll(nullptr, "color", exception_state);
- EXPECT_FALSE(exception_state.HadException());
-
- map->get(nullptr, "align-contents", exception_state);
- EXPECT_TRUE(exception_state.HadException());
- exception_state.ClearException();
-
- map->has(nullptr, "align-contents", exception_state);
- EXPECT_TRUE(exception_state.HadException());
- exception_state.ClearException();
+ PaintWorkletStylePropertyMap* map =
+ MakeGarbageCollected<PaintWorkletStylePropertyMap>(
+ input->StyleMapData());
+ ASSERT_TRUE(map);
- map->getAll(nullptr, "align-contents", exception_state);
- EXPECT_TRUE(exception_state.HadException());
- exception_state.ClearException();
+ const PaintWorkletStylePropertyMap::CrossThreadData& data =
+ map->StyleMapDataForTest();
+ EXPECT_EQ(data.size(), 1u);
+ EXPECT_EQ(data.at("--x")->GetType(),
+ CrossThreadStyleValue::StyleValueType::kUnparsedType);
+ CSSStyleValue* style_value = data.at("--x")->ToCSSStyleValue();
+ EXPECT_EQ(style_value->GetType(),
+ CSSStyleValue::StyleValueType::kUnparsedType);
+ EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToString(), "50");
+ waitable_event->Signal();
}
void CheckCrossThreadData(base::WaitableEvent* waitable_event,
@@ -113,13 +85,13 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
EXPECT_EQ(data.at("--foo")->ToCSSStyleValue()->GetType(),
CSSStyleValue::StyleValueType::kUnitType);
EXPECT_EQ(To<CSSUnitValue>(data.at("--foo")->ToCSSStyleValue())->value(),
- 134);
+ 10);
EXPECT_EQ(To<CSSUnitValue>(data.at("--foo")->ToCSSStyleValue())->unit(),
"px");
EXPECT_EQ(data.at("--bar")->ToCSSStyleValue()->GetType(),
CSSStyleValue::StyleValueType::kUnitType);
EXPECT_EQ(To<CSSUnitValue>(data.at("--bar")->ToCSSStyleValue())->value(),
- 42);
+ 15);
EXPECT_EQ(data.at("--loo")->ToCSSStyleValue()->GetType(),
CSSStyleValue::StyleValueType::kKeywordType);
EXPECT_EQ(To<CSSKeywordValue>(data.at("--loo")->ToCSSStyleValue())->value(),
@@ -128,7 +100,7 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
CSSStyleValue::StyleValueType::kUnsupportedColorType);
EXPECT_EQ(To<CSSUnsupportedColorValue>(data.at("--gar")->ToCSSStyleValue())
->Value(),
- Color(0, 255, 0));
+ Color(255, 0, 0));
EXPECT_EQ(data.at("display")->ToCSSStyleValue()->GetType(),
CSSStyleValue::StyleValueType::kKeywordType);
waitable_event->Signal();
@@ -138,7 +110,47 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
std::unique_ptr<blink::Thread> thread_;
};
-TEST_F(PaintWorkletStylePropertyMapTest, CreateSupportedCrossThreadData) {
+TEST_F(PaintWorkletStylePropertyMapTest, UnregisteredCustomProperty) {
+ CustomProperty property("--x", GetDocument());
+ Vector<CSSPropertyID> native_properties;
+ Vector<AtomicString> custom_properties({"--x"});
+
+ GetDocument().documentElement()->SetInnerHTMLFromString(
+ "<div id='target' style='--x:50'></div>");
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* node = GetDocument().getElementById("target");
+ node->GetLayoutObject()->GetMutableForPainting().EnsureId();
+ CompositorPaintWorkletInput::PropertyKeys input_property_keys;
+ auto data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
+ GetDocument(), node->GetLayoutObject()->UniqueId(),
+ node->ComputedStyleRef(), native_properties, custom_properties,
+ input_property_keys);
+ EXPECT_TRUE(data.has_value());
+
+ Vector<std::unique_ptr<CrossThreadStyleValue>> input_arguments;
+ std::vector<cc::PaintWorkletInput::PropertyKey> property_keys;
+ scoped_refptr<PaintWorkletInput> input =
+ base::MakeRefCounted<PaintWorkletInput>(
+ "test", FloatSize(100, 100), 1.0f, 1.0f, 1, std::move(data.value()),
+ std::move(input_arguments), std::move(property_keys));
+ ASSERT_TRUE(input);
+
+ thread_ = blink::Thread::CreateThread(
+ ThreadCreationParams(WebThreadType::kTestThread).SetSupportsGC(true));
+ base::WaitableEvent waitable_event;
+ PostCrossThreadTask(
+ *thread_->GetTaskRunner(), FROM_HERE,
+ CrossThreadBindOnce(
+ &PaintWorkletStylePropertyMapTest::CheckUnregisteredProperty,
+ CrossThreadUnretained(this), CrossThreadUnretained(&waitable_event),
+ std::move(input)));
+ waitable_event.Wait();
+
+ ShutDownThread();
+}
+
+TEST_F(PaintWorkletStylePropertyMapTest, SupportedCrossThreadData) {
Vector<CSSPropertyID> native_properties({CSSPropertyID::kDisplay});
Vector<AtomicString> custom_properties({"--foo", "--bar", "--loo", "--gar"});
css_test_helpers::RegisterProperty(GetDocument(), "--foo", "<length>",
@@ -150,9 +162,13 @@ TEST_F(PaintWorkletStylePropertyMapTest, CreateSupportedCrossThreadData) {
css_test_helpers::RegisterProperty(GetDocument(), "--gar", "<color>",
"rgb(0, 255, 0)", false);
+ GetDocument().documentElement()->SetInnerHTMLFromString(
+ "<div id='target' style='--foo:10px; --bar:15; --gar:rgb(255, 0, "
+ "0)'></div>");
UpdateAllLifecyclePhasesForTest();
- Node* node = PageNode();
+ Element* node = GetDocument().getElementById("target");
+ node->GetLayoutObject()->GetMutableForPainting().EnsureId();
Vector<std::unique_ptr<CrossThreadStyleValue>> input_arguments;
CompositorPaintWorkletInput::PropertyKeys input_property_keys;
auto data = PaintWorkletStylePropertyMap::BuildCrossThreadData(
@@ -192,8 +208,13 @@ TEST_F(PaintWorkletStylePropertyMapTest, UnsupportedCrossThreadData) {
css_test_helpers::RegisterProperty(GetDocument(), "--loo", "test", "test",
false);
+ GetDocument().documentElement()->SetInnerHTMLFromString(
+ "<div id='target' style='--foo:url(https://crbug.com/); "
+ "--bar:15;'></div>");
UpdateAllLifecyclePhasesForTest();
- Node* node = PageNode();
+
+ Element* node = GetDocument().getElementById("target");
+ node->GetLayoutObject()->GetMutableForPainting().EnsureId();
Vector<std::unique_ptr<CrossThreadStyleValue>> input_arguments;
CompositorPaintWorkletInput::PropertyKeys input_property_keys;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
index 5d821bd63ae..88b52b13f2e 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/css/css_property_id_templates.h"
#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
namespace blink {
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 56a30afdb27..f9c43847b3b 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
@@ -131,10 +131,11 @@ CSSStyleValue* CreateStyleValueWithPropertyInternal(CSSPropertyID property_id,
return CreateStyleValue(value);
}
case CSSPropertyID::kGridAutoFlow: {
- const auto& value_list = To<CSSValueList>(value);
- // Only single keywords are supported in level 1.
- if (value_list.length() == 1U)
- return CreateStyleValue(value_list.Item(0));
+ if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
+ // Only single keywords are supported in level 1.
+ if (value_list->length() == 1U)
+ return CreateStyleValue(value_list->Item(0));
+ }
return nullptr;
}
case CSSPropertyID::kTransform:
@@ -150,10 +151,11 @@ CSSStyleValue* CreateStyleValueWithPropertyInternal(CSSPropertyID property_id,
case CSSPropertyID::kTransformOrigin:
return CSSPositionValue::FromCSSValue(value);
case CSSPropertyID::kOffsetRotate: {
- const auto& value_list = To<CSSValueList>(value);
- // Only single keywords are supported in level 1.
- if (value_list.length() == 1U)
- return CreateStyleValue(value_list.Item(0));
+ if (const auto* value_list = DynamicTo<CSSValueList>(&value)) {
+ // Only single keywords are supported in level 1.
+ if (value_list->length() == 1U)
+ return CreateStyleValue(value_list->Item(0));
+ }
return nullptr;
}
case CSSPropertyID::kAlignItems: {
@@ -171,10 +173,11 @@ CSSStyleValue* CreateStyleValueWithPropertyInternal(CSSPropertyID property_id,
if (value.IsIdentifierValue())
return CreateStyleValue(value);
- const auto& value_list = To<CSSValueList>(value);
- // Only single keywords are supported in level 1.
- if (value_list.length() == 1U)
- return CreateStyleValue(value_list.Item(0));
+ if (const auto* value_list = DynamicTo<CSSValueList>(&value)) {
+ // Only single keywords are supported in level 1.
+ if (value_list->length() == 1U)
+ return CreateStyleValue(value_list->Item(0));
+ }
return nullptr;
}
case CSSPropertyID::kTextIndent: {
@@ -189,10 +192,11 @@ CSSStyleValue* CreateStyleValueWithPropertyInternal(CSSPropertyID property_id,
}
case CSSPropertyID::kTransitionProperty:
case CSSPropertyID::kTouchAction: {
- const auto& value_list = To<CSSValueList>(value);
- // Only single values are supported in level 1.
- if (value_list.length() == 1U)
- return CreateStyleValue(value_list.Item(0));
+ if (const auto* value_list = DynamicTo<CSSValueList>(value)) {
+ // Only single values are supported in level 1.
+ if (value_list->length() == 1U)
+ return CreateStyleValue(value_list->Item(0));
+ }
return nullptr;
}
case CSSPropertyID::kWillChange: {
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 f204eddfc6c..83b90e0a78e 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
@@ -350,7 +350,7 @@ void ElementRuleCollector::DidMatchRule(
dynamic_pseudo == kPseudoIdAfter) &&
!rule_data->Rule()->Properties().HasProperty(CSSPropertyID::kContent))
return;
- style_->SetHasPseudoStyle(dynamic_pseudo);
+ style_->SetHasPseudoElementStyle(dynamic_pseudo);
} else {
matched_rules_.push_back(MatchedRule(
rule_data, result.specificity, cascade_order,
diff --git a/chromium/third_party/blink/renderer/core/css/element_rule_collector.h b/chromium/third_party/blink/renderer/core/css/element_rule_collector.h
index 6562ed0d6ff..31444ad2754 100644
--- a/chromium/third_party/blink/renderer/core/css/element_rule_collector.h
+++ b/chromium/third_party/blink/renderer/core/css/element_rule_collector.h
@@ -113,7 +113,7 @@ class ElementRuleCollector {
~ElementRuleCollector();
void SetMode(SelectorChecker::Mode mode) { mode_ = mode; }
- void SetPseudoStyleRequest(const PseudoStyleRequest& request) {
+ void SetPseudoElementStyleRequest(const PseudoElementStyleRequest& request) {
pseudo_style_request_ = request;
}
void SetSameOriginOnly(bool f) { same_origin_only_ = f; }
@@ -182,7 +182,7 @@ class ElementRuleCollector {
scoped_refptr<ComputedStyle>
style_; // FIXME: This can be mutated during matching!
- PseudoStyleRequest pseudo_style_request_;
+ PseudoElementStyleRequest pseudo_style_request_;
SelectorChecker::Mode mode_;
bool can_use_fast_reject_;
bool same_origin_only_;
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 a090bc77e63..12914055281 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face.cc
@@ -780,13 +780,8 @@ bool FontFace::HasPendingActivity() const {
return status_ == kLoading && GetExecutionContext();
}
-FontDisplay FontFace::GetFontDisplayWithFallback() const {
- if (display_)
- return CSSValueToFontDisplay(display_.Get());
- ExecutionContext* context = GetExecutionContext();
- if (!context || !context->IsDocument())
- return kFontDisplayAuto;
- return To<Document>(context)->GetStyleEngine().GetDefaultFontDisplay(family_);
+FontDisplay FontFace::GetFontDisplay() const {
+ return CSSValueToFontDisplay(display_.Get());
}
} // namespace blink
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 7c8a121528b..b6ac8235889 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.h
+++ b/chromium/third_party/blink/renderer/core/css/font_face.h
@@ -113,9 +113,7 @@ class CORE_EXPORT FontFace : public ScriptWrappable,
FontSelectionCapabilities GetFontSelectionCapabilities() const;
CSSFontFace* CssFontFace() { return css_font_face_.Get(); }
size_t ApproximateBlankCharacterCount() const;
- // Return FontDisplay using the default from @font-feature-values if not
- // specified on this FontFace.
- FontDisplay GetFontDisplayWithFallback() const;
+ FontDisplay GetFontDisplay() const;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_cache.cc b/chromium/third_party/blink/renderer/core/css/font_face_cache.cc
index 93d56d23b60..09ace644e6d 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_cache.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face_cache.cc
@@ -154,6 +154,11 @@ CSSSegmentedFontFace* FontFaceCache::Get(
segmented_faces_for_family->value->IsEmpty())
return nullptr;
+ // TODO(crbug.com/1021568): Prevent `system-ui` from matching. Per spec,
+ // generic family names should not match web fonts unless they are quoted.
+ if (family == font_family_names::kSystemUi)
+ return nullptr;
+
auto family_faces = segmented_faces_for_family->value;
// Either add or retrieve a cache entry in the selection query cache for the
diff --git a/chromium/third_party/blink/renderer/core/css/font_face_set.h b/chromium/third_party/blink/renderer/core/css/font_face_set.h
index 6235034481e..f71d240add9 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face_set.h
+++ b/chromium/third_party/blink/renderer/core/css/font_face_set.h
@@ -126,7 +126,7 @@ class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
};
class LoadFontPromiseResolver final
- : public GarbageCollectedFinalized<LoadFontPromiseResolver>,
+ : public GarbageCollected<LoadFontPromiseResolver>,
public FontFace::LoadFontCallback {
USING_GARBAGE_COLLECTED_MIXIN(LoadFontPromiseResolver);
diff --git a/chromium/third_party/blink/renderer/core/css/fullscreen.css b/chromium/third_party/blink/renderer/core/css/fullscreen.css
index 8023bdb8e26..7ed4f7704cc 100644
--- a/chromium/third_party/blink/renderer/core/css/fullscreen.css
+++ b/chromium/third_party/blink/renderer/core/css/fullscreen.css
@@ -1,4 +1,4 @@
-:not(:root):-webkit-full-screen {
+:not(:root):fullscreen {
position: fixed !important;
top: 0 !important;
right: 0 !important;
@@ -18,14 +18,14 @@
object-fit: contain;
}
-iframe:-webkit-full-screen {
+iframe:fullscreen {
border: none !important;
padding: 0 !important;
}
/* TODO(foolip): In the spec, there's a ::backdrop block with the properties
shared with dialog::backdrop (see html.css). */
-:not(:root):-webkit-full-screen::backdrop {
+:not(:root):fullscreen::backdrop {
position: fixed;
top: 0;
right: 0;
@@ -45,7 +45,7 @@ iframe:-webkit-full-screen {
overflow: hidden !important;
}
-:-webkit-full-screen:-internal-video-persistent-ancestor :not(:-internal-video-persistent-ancestor) {
+:fullscreen:-internal-video-persistent-ancestor :not(:-internal-video-persistent-ancestor) {
display: none !important;
}
@@ -65,3 +65,10 @@ iframe:-webkit-full-screen {
background-color: black !important;
z-index: 2147483647 !important;
}
+
+/* WebXR DOM Overlay for handheld AR needs a transparent background for both the
+ fullscreened element and its backdrop. */
+:-internal-xr-immersive-dom-overlay :fullscreen,
+:-internal-xr-immersive-dom-overlay :fullscreen::backdrop {
+ background-color: rgba(0,0,0,0) !important;
+}
diff --git a/chromium/third_party/blink/renderer/core/css/fullscreenAndroid.css b/chromium/third_party/blink/renderer/core/css/fullscreenAndroid.css
index 2466f350551..526736d6510 100644
--- a/chromium/third_party/blink/renderer/core/css/fullscreenAndroid.css
+++ b/chromium/third_party/blink/renderer/core/css/fullscreenAndroid.css
@@ -1,4 +1,4 @@
-video:-webkit-full-screen {
+video:fullscreen {
/* Fullscreen video on Android does not synchronize correctly when the <video>
* element is not rendered in the root render pass. Disable properties that
* cause this. (http://crbug.com/618753) */
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 5120207b88e..678a929e4a3 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
@@ -31,14 +31,19 @@ void PendingInvalidations::ScheduleInvalidationSetsForNode(
if (node.GetStyleChangeType() < kSubtreeStyleChange) {
for (auto& invalidation_set : invalidation_lists.descendants) {
if (invalidation_set->WholeSubtreeInvalid()) {
- node.SetNeedsStyleRecalc(kSubtreeStyleChange,
- StyleChangeReasonForTracing::Create(
+ ContainerNode* subtree_root = &node;
+ if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
+ if (auto* shadow_root = DynamicTo<ShadowRoot>(node))
+ subtree_root = &shadow_root->host();
+ }
+ subtree_root->SetNeedsStyleRecalc(
+ kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kStyleInvalidator));
requires_descendant_invalidation = false;
break;
}
- if (invalidation_set->InvalidatesSelf()) {
+ if (invalidation_set->InvalidatesSelf() && node.IsElementNode()) {
node.SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::Create(
style_change_reason::kStyleInvalidator));
@@ -103,28 +108,32 @@ void PendingInvalidations::ScheduleSiblingInvalidationsAsDescendants(
scheduling_parent.SetNeedsStyleInvalidation();
+ ContainerNode* subtree_root = &scheduling_parent;
+ if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
+ subtree_root = DynamicTo<Element>(scheduling_parent);
+ if (!subtree_root)
+ subtree_root = &To<ShadowRoot>(scheduling_parent).host();
+ }
+
for (auto& invalidation_set : invalidation_lists.siblings) {
- if (invalidation_set->WholeSubtreeInvalid()) {
- scheduling_parent.SetNeedsStyleRecalc(
+ DescendantInvalidationSet* descendants =
+ To<SiblingInvalidationSet>(*invalidation_set).SiblingDescendants();
+ if (invalidation_set->WholeSubtreeInvalid() ||
+ (descendants && descendants->WholeSubtreeInvalid())) {
+ subtree_root->SetNeedsStyleRecalc(
kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kStyleInvalidator));
return;
}
+
if (invalidation_set->InvalidatesSelf() &&
- !pending_invalidations.Descendants().Contains(invalidation_set))
+ !pending_invalidations.Descendants().Contains(invalidation_set)) {
pending_invalidations.Descendants().push_back(invalidation_set);
+ }
- if (DescendantInvalidationSet* descendants =
- To<SiblingInvalidationSet>(*invalidation_set)
- .SiblingDescendants()) {
- if (descendants->WholeSubtreeInvalid()) {
- scheduling_parent.SetNeedsStyleRecalc(
- kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
- style_change_reason::kStyleInvalidator));
- return;
- }
- if (!pending_invalidations.Descendants().Contains(descendants))
- pending_invalidations.Descendants().push_back(descendants);
+ if (descendants &&
+ !pending_invalidations.Descendants().Contains(descendants)) {
+ pending_invalidations.Descendants().push_back(descendants);
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations_test.cc b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations_test.cc
index 94535cfecc0..fe8dbcfccfb 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations_test.cc
@@ -56,7 +56,7 @@ TEST_F(PendingInvalidationsTest, ScheduleOnDocumentNode) {
EXPECT_FALSE(GetDocument().NeedsStyleInvalidation());
EXPECT_FALSE(GetDocument().ChildNeedsStyleInvalidation());
EXPECT_FALSE(GetDocument().NeedsStyleRecalc());
- EXPECT_TRUE(GetDocument().ChildNeedsStyleRecalc());
+ EXPECT_TRUE(GetStyleEngine().NeedsStyleRecalc());
GetDocument().View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
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 ef7d8514b82..e98cef63978 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
@@ -303,8 +303,9 @@ void StyleInvalidator::Invalidate(Element& element, SiblingData& sibling_data) {
// styles but we do it. If we ever stop doing that then this code and the
// PushInvalidationSetsForContainerNode above need to move out of the
// if-block.
- if (InvalidatesSlotted() && IsHTMLSlotElement(element))
- InvalidateSlotDistributedElements(ToHTMLSlotElement(element));
+ auto* html_slot_element = DynamicTo<HTMLSlotElement>(element);
+ if (html_slot_element && InvalidatesSlotted())
+ InvalidateSlotDistributedElements(*html_slot_element);
if (InsertionPointCrossing() && element.IsV0InsertionPoint()) {
element.SetNeedsStyleRecalc(kSubtreeStyleChange,
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator_test.cc b/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator_test.cc
index 7940afd71d6..ed8c8d7df20 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
#include "testing/gtest/include/gtest/gtest.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/html/html_element.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -49,7 +50,7 @@ TEST_F(StyleInvalidatorTest, SkipDisplayNone) {
StyleInvalidator invalidator(pending.GetPendingInvalidationMap());
invalidator.Invalidate(GetDocument(), GetDocument().body());
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_FALSE(GetDocument().GetStyleEngine().NeedsStyleRecalc());
}
TEST_F(StyleInvalidatorTest, SkipDisplayNoneClearPendingNth) {
diff --git a/chromium/third_party/blink/renderer/core/css/layout_tree_rebuild_root.cc b/chromium/third_party/blink/renderer/core/css/layout_tree_rebuild_root.cc
index 1511c69ec3b..6299085d9c2 100644
--- a/chromium/third_party/blink/renderer/core/css/layout_tree_rebuild_root.cc
+++ b/chromium/third_party/blink/renderer/core/css/layout_tree_rebuild_root.cc
@@ -50,10 +50,13 @@ bool LayoutTreeRebuildRoot::IsDirty(const Node& node) const {
void LayoutTreeRebuildRoot::ClearChildDirtyForAncestors(
ContainerNode& parent) const {
- for (ContainerNode* ancestor = &parent; ancestor;
- ancestor = ancestor->GetReattachParent()) {
- ancestor->ClearChildNeedsReattachLayoutTree();
+ Element* ancestor = DynamicTo<Element>(parent);
+ if (!ancestor)
+ ancestor = parent.ParentOrShadowHostElement();
+ for (; ancestor; ancestor = ancestor->GetReattachParent()) {
+ DCHECK(ancestor->ChildNeedsReattachLayoutTree());
DCHECK(!ancestor->NeedsReattachLayoutTree());
+ ancestor->ClearChildNeedsReattachLayoutTree();
}
}
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 ad3352a2bc5..b78aa49241e 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
@@ -48,6 +48,7 @@
"min-monochrome",
"min-width",
"min-resolution",
+ "navigation-controls",
"pointer",
"prefers-color-scheme",
"prefers-reduced-motion",
diff --git a/chromium/third_party/blink/renderer/core/css/media_feature_overrides.cc b/chromium/third_party/blink/renderer/core/css/media_feature_overrides.cc
new file mode 100644
index 00000000000..c6a0850d57b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_overrides.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/media_feature_overrides.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"
+
+namespace blink {
+
+void MediaFeatureOverrides::SetOverride(const AtomicString& feature,
+ const String& value_string) {
+ CSSTokenizer tokenizer(value_string);
+ const auto tokens = tokenizer.TokenizeToEOF();
+ CSSParserTokenRange range(tokens);
+ auto value = MediaQueryExp::Create(feature, range).ExpValue();
+
+ if (value.IsValid())
+ overrides_.Set(feature, value);
+ else
+ overrides_.erase(feature);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..96e2e1da8ed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_overrides.h
@@ -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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_FEATURE_OVERRIDES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_FEATURE_OVERRIDES_H_
+
+#include "third_party/blink/renderer/core/css/media_query_exp.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+
+namespace blink {
+
+class CORE_EXPORT MediaFeatureOverrides {
+ public:
+ void SetOverride(const AtomicString& feature, const String& value_string);
+ MediaQueryExpValue GetOverride(const AtomicString& feature) const {
+ return overrides_.at(feature);
+ }
+
+ private:
+ HashMap<AtomicString, MediaQueryExpValue> overrides_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_FEATURE_OVERRIDES_H_
diff --git a/chromium/third_party/blink/renderer/core/css/media_feature_overrides_test.cc b/chromium/third_party/blink/renderer/core/css/media_feature_overrides_test.cc
new file mode 100644
index 00000000000..573d6f0cf48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/media_feature_overrides_test.cc
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(MediaFeatureOverrides, GetOverrideInitial) {
+ MediaFeatureOverrides overrides;
+
+ EXPECT_FALSE(overrides.GetOverride("unknown").IsValid());
+ EXPECT_FALSE(overrides.GetOverride("prefers-color-scheme").IsValid());
+ EXPECT_FALSE(overrides.GetOverride("display-mode").IsValid());
+}
+
+TEST(MediaFeatureOverrides, SetOverrideInvalid) {
+ MediaFeatureOverrides overrides;
+
+ overrides.SetOverride("prefers-color-scheme", "1px");
+ EXPECT_FALSE(overrides.GetOverride("prefers-color-scheme").IsValid());
+
+ overrides.SetOverride("prefers-color-scheme", "orange");
+ EXPECT_FALSE(overrides.GetOverride("prefers-color-scheme").IsValid());
+}
+
+TEST(MediaFeatureOverrides, SetOverrideValid) {
+ MediaFeatureOverrides overrides;
+
+ overrides.SetOverride("prefers-color-scheme", "light");
+ auto light_override = overrides.GetOverride("prefers-color-scheme");
+ EXPECT_TRUE(light_override.IsValid());
+ EXPECT_TRUE(light_override.is_id);
+ EXPECT_EQ(CSSValueID::kLight, light_override.id);
+
+ overrides.SetOverride("prefers-color-scheme", "dark");
+ auto dark_override = overrides.GetOverride("prefers-color-scheme");
+ EXPECT_TRUE(dark_override.IsValid());
+ EXPECT_TRUE(dark_override.is_id);
+ EXPECT_EQ(CSSValueID::kDark, dark_override.id);
+}
+
+TEST(MediaFeatureOverrides, ResetOverride) {
+ MediaFeatureOverrides overrides;
+
+ overrides.SetOverride("prefers-color-scheme", "light");
+ EXPECT_TRUE(overrides.GetOverride("prefers-color-scheme").IsValid());
+ overrides.SetOverride("prefers-color-scheme", "");
+ EXPECT_FALSE(overrides.GetOverride("prefers-color-scheme").IsValid());
+
+ overrides.SetOverride("prefers-color-scheme", "light");
+ EXPECT_TRUE(overrides.GetOverride("prefers-color-scheme").IsValid());
+ overrides.SetOverride("prefers-color-scheme", "invalid");
+ EXPECT_FALSE(overrides.GetOverride("prefers-color-scheme").IsValid());
+}
+
+} // namespace blink
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 9c90b9db2d0..2e73dacd324 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
@@ -30,8 +30,9 @@
#include "third_party/blink/renderer/core/css/media_query_evaluator.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/common/css/preferred_color_scheme.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/pointer_properties.h"
#include "third_party/blink/public/platform/shape_properties.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -256,16 +257,16 @@ static bool DisplayModeMediaFeatureEval(const MediaQueryExpValue& value,
if (!value.is_id)
return false;
- WebDisplayMode mode = media_values.DisplayMode();
+ blink::mojom::DisplayMode mode = media_values.DisplayMode();
switch (value.id) {
case CSSValueID::kFullscreen:
- return mode == kWebDisplayModeFullscreen;
+ return mode == blink::mojom::DisplayMode::kFullscreen;
case CSSValueID::kStandalone:
- return mode == kWebDisplayModeStandalone;
+ return mode == blink::mojom::DisplayMode::kStandalone;
case CSSValueID::kMinimalUi:
- return mode == kWebDisplayModeMinimalUi;
+ return mode == blink::mojom::DisplayMode::kMinimalUi;
case CSSValueID::kBrowser:
- return mode == kWebDisplayModeBrowser;
+ return mode == blink::mojom::DisplayMode::kBrowser;
default:
NOTREACHED();
return false;
@@ -867,6 +868,25 @@ static bool ForcedColorsMediaFeatureEval(const MediaQueryExpValue& value,
value.id == CSSValueID::kActive);
}
+static bool NavigationControlsMediaFeatureEval(
+ const MediaQueryExpValue& value,
+ MediaFeaturePrefix,
+ const MediaValues& media_values) {
+ NavigationControls navigation_controls = media_values.GetNavigationControls();
+
+ if (!value.IsValid())
+ return navigation_controls != NavigationControls::kNone;
+
+ if (!value.is_id)
+ return false;
+
+ // Check the navigation controls against value.id.
+ return (navigation_controls == NavigationControls::kNone &&
+ value.id == CSSValueID::kNone) ||
+ (navigation_controls == NavigationControls::kBackButton &&
+ value.id == CSSValueID::kBackButton);
+}
+
void MediaQueryEvaluator::Init() {
// Create the table.
g_function_map = new FunctionMap;
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.h b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.h
index d9888d9733d..570e0ff096b 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_evaluator.h
+++ b/chromium/third_party/blink/renderer/core/css/media_query_evaluator.h
@@ -56,8 +56,7 @@ using MediaQueryResultList = Vector<MediaQueryResult>;
// loading of stylesheets to only those which are probable to match.
class CORE_EXPORT MediaQueryEvaluator final
- : public GarbageCollectedFinalized<MediaQueryEvaluator> {
-
+ : public GarbageCollected<MediaQueryEvaluator> {
public:
static void Init();
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 1a00fa9667c..e7bfdefb089 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
@@ -6,6 +6,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
#include "third_party/blink/renderer/core/css/media_values_initial_viewport.h"
@@ -186,6 +187,18 @@ MediaQueryEvaluatorTestCase g_forcedcolors_none_cases[] = {
{nullptr, 0} // 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.
+};
+
+MediaQueryEvaluatorTestCase g_navigationcontrols_none_cases[] = {
+ {"(navigation-controls: back-button)", 0},
+ {"(navigation-controls: none)", 1},
+ {nullptr, 0} // Do not remove the terminator line.
+};
+
void TestMQEvaluator(MediaQueryEvaluatorTestCase* test_cases,
const MediaQueryEvaluator& media_query_evaluator,
CSSParserMode mode) {
@@ -224,7 +237,7 @@ TEST(MediaQueryEvaluatorTest, Cached) {
data.three_d_enabled = true;
data.media_type = media_type_names::kScreen;
data.strict_mode = true;
- data.display_mode = kWebDisplayModeBrowser;
+ data.display_mode = blink::mojom::DisplayMode::kBrowser;
data.display_shape = kDisplayShapeRect;
data.immersive_mode = false;
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 07350e9b590..07cea4a6c44 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
@@ -94,6 +94,12 @@ static inline bool FeatureWithValidIdent(const String& media_feature,
}
}
+ if (RuntimeEnabledFeatures::MediaQueryNavigationControlsEnabled()) {
+ if (media_feature == kNavigationControlsMediaFeature) {
+ return ident == CSSValueID::kNone || ident == CSSValueID::kBackButton;
+ }
+ }
+
return false;
}
@@ -205,7 +211,8 @@ static inline bool FeatureWithoutValue(const String& media_feature) {
media_feature == kImmersiveMediaFeature ||
media_feature == kPrefersColorSchemeMediaFeature ||
media_feature == kPrefersReducedMotionMediaFeature ||
- media_feature == kForcedColorsMediaFeature;
+ media_feature == kForcedColorsMediaFeature ||
+ media_feature == kNavigationControlsMediaFeature;
}
bool MediaQueryExp::IsViewportDependent() const {
diff --git a/chromium/third_party/blink/renderer/core/css/media_query_matcher.h b/chromium/third_party/blink/renderer/core/css/media_query_matcher.h
index 6a2b90ff3ca..818119762de 100644
--- a/chromium/third_party/blink/renderer/core/css/media_query_matcher.h
+++ b/chromium/third_party/blink/renderer/core/css/media_query_matcher.h
@@ -40,8 +40,7 @@ class MediaQuerySet;
// which they have been added.
class CORE_EXPORT MediaQueryMatcher final
- : public GarbageCollectedFinalized<MediaQueryMatcher> {
-
+ : public GarbageCollected<MediaQueryMatcher> {
public:
static MediaQueryMatcher* Create(Document&);
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 c31ccf36536..045d7937d14 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_values.cc
@@ -4,8 +4,11 @@
#include "third_party/blink/renderer/core/css/media_values.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_screen_info.h"
+#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
+#include "third_party/blink/renderer/core/css/media_feature_overrides.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/dom/document.h"
@@ -22,6 +25,20 @@
namespace blink {
+PreferredColorScheme CSSValueIDToPreferredColorScheme(CSSValueID id) {
+ switch (id) {
+ case CSSValueID::kNoPreference:
+ return PreferredColorScheme::kNoPreference;
+ case CSSValueID::kLight:
+ return PreferredColorScheme::kLight;
+ case CSSValueID::kDark:
+ return PreferredColorScheme::kDark;
+ default:
+ NOTREACHED();
+ return PreferredColorScheme::kNoPreference;
+ }
+}
+
MediaValues* MediaValues::CreateDynamicIfFrameExists(LocalFrame* frame) {
if (frame)
return MediaValuesDynamic::Create(frame);
@@ -45,7 +62,7 @@ double MediaValues::CalculateViewportHeight(LocalFrame* frame) {
int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
blink::WebScreenInfo screen_info =
- frame->GetPage()->GetChromeClient().GetScreenInfo();
+ frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_width = screen_info.rect.width;
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
device_width = static_cast<int>(
@@ -57,7 +74,7 @@ int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
blink::WebScreenInfo screen_info =
- frame->GetPage()->GetChromeClient().GetScreenInfo();
+ frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
int device_height = screen_info.rect.height;
if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
device_height = static_cast<int>(
@@ -79,23 +96,21 @@ float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) {
int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
- if (frame->GetPage()->GetChromeClient().GetScreenInfo().is_monochrome)
+ WebScreenInfo screen_info =
+ frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
+ if (screen_info.is_monochrome)
return 0;
- return frame->GetPage()
- ->GetChromeClient()
- .GetScreenInfo()
- .depth_per_component;
+ return screen_info.depth_per_component;
}
int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
- if (!frame->GetPage()->GetChromeClient().GetScreenInfo().is_monochrome)
+ WebScreenInfo screen_info =
+ frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
+ if (!screen_info.is_monochrome)
return 0;
- return frame->GetPage()
- ->GetChromeClient()
- .GetScreenInfo()
- .depth_per_component;
+ return screen_info.depth_per_component;
}
int MediaValues::CalculateDefaultFontSize(LocalFrame* frame) {
@@ -109,16 +124,16 @@ const String MediaValues::CalculateMediaType(LocalFrame* frame) {
return frame->View()->MediaType();
}
-WebDisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
+blink::mojom::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) {
DCHECK(frame);
- WebDisplayMode mode =
+ blink::mojom::DisplayMode mode =
frame->GetPage()->GetSettings().GetDisplayModeOverride();
- if (mode != kWebDisplayModeUndefined)
+ if (mode != blink::mojom::DisplayMode::kUndefined)
return mode;
if (!frame->View())
- return kWebDisplayModeBrowser;
+ return blink::mojom::DisplayMode::kBrowser;
return frame->View()->DisplayMode();
}
@@ -166,14 +181,17 @@ int MediaValues::CalculateAvailableHoverTypes(LocalFrame* frame) {
DisplayShape MediaValues::CalculateDisplayShape(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
- return frame->GetPage()->GetChromeClient().GetScreenInfo().display_shape;
+ return frame->GetPage()
+ ->GetChromeClient()
+ .GetScreenInfo(*frame)
+ .display_shape;
}
ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetPage());
return color_space_utilities::GetColorSpaceGamut(
- frame->GetPage()->GetChromeClient().GetScreenInfo());
+ frame->GetPage()->GetChromeClient().GetScreenInfo(*frame));
}
PreferredColorScheme MediaValues::CalculatePreferredColorScheme(
@@ -181,20 +199,37 @@ PreferredColorScheme MediaValues::CalculatePreferredColorScheme(
DCHECK(frame);
DCHECK(frame->GetSettings());
DCHECK(frame->GetDocument());
+ DCHECK(frame->GetPage());
+ if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
+ MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme");
+ if (value.IsValid())
+ return CSSValueIDToPreferredColorScheme(value.id);
+ }
return frame->GetDocument()->GetStyleEngine().GetPreferredColorScheme();
}
bool MediaValues::CalculatePrefersReducedMotion(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
+ if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) {
+ MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-motion");
+ if (value.IsValid())
+ return value.id == CSSValueID::kReduce;
+ }
return frame->GetSettings()->GetPrefersReducedMotion();
}
-ForcedColors MediaValues::CalculateForcedColors(LocalFrame* frame) {
+ForcedColors MediaValues::CalculateForcedColors() {
+ if (Platform::Current() && Platform::Current()->ThemeEngine())
+ return Platform::Current()->ThemeEngine()->ForcedColors();
+ else
+ return ForcedColors::kNone;
+}
+
+NavigationControls MediaValues::CalculateNavigationControls(LocalFrame* frame) {
DCHECK(frame);
DCHECK(frame->GetSettings());
- DCHECK(frame->GetDocument());
- return frame->GetDocument()->GetStyleEngine().GetForcedColors();
+ return frame->GetSettings()->GetNavigationControls();
}
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 445c19b47e0..22d46d54110 100644
--- a/chromium/third_party/blink/renderer/core/css/media_values.h
+++ b/chromium/third_party/blink/renderer/core/css/media_values.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MEDIA_VALUES_H_
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/pointer_properties.h"
#include "third_party/blink/public/platform/shape_properties.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -17,11 +17,15 @@ namespace blink {
class Document;
class CSSPrimitiveValue;
class LocalFrame;
+enum class CSSValueID;
enum class ColorSpaceGamut;
enum class PreferredColorScheme;
enum class ForcedColors;
+enum class NavigationControls;
-class CORE_EXPORT MediaValues : public GarbageCollectedFinalized<MediaValues> {
+PreferredColorScheme CSSValueIDToPreferredColorScheme(CSSValueID id);
+
+class CORE_EXPORT MediaValues : public GarbageCollected<MediaValues> {
public:
virtual ~MediaValues() = default;
virtual void Trace(blink::Visitor* visitor) {}
@@ -70,7 +74,7 @@ class CORE_EXPORT MediaValues : public GarbageCollectedFinalized<MediaValues> {
virtual bool ThreeDEnabled() const = 0;
virtual bool InImmersiveMode() const = 0;
virtual const String MediaType() const = 0;
- virtual WebDisplayMode DisplayMode() const = 0;
+ virtual blink::mojom::DisplayMode DisplayMode() const = 0;
virtual bool StrictMode() const = 0;
virtual Document* GetDocument() const = 0;
virtual bool HasValues() const = 0;
@@ -81,6 +85,7 @@ class CORE_EXPORT MediaValues : public GarbageCollectedFinalized<MediaValues> {
virtual PreferredColorScheme GetPreferredColorScheme() const = 0;
virtual bool PrefersReducedMotion() const = 0;
virtual ForcedColors GetForcedColors() const = 0;
+ virtual NavigationControls GetNavigationControls() const = 0;
protected:
static double CalculateViewportWidth(LocalFrame*);
@@ -93,7 +98,7 @@ class CORE_EXPORT MediaValues : public GarbageCollectedFinalized<MediaValues> {
static int CalculateMonochromeBitsPerComponent(LocalFrame*);
static int CalculateDefaultFontSize(LocalFrame*);
static const String CalculateMediaType(LocalFrame*);
- static WebDisplayMode CalculateDisplayMode(LocalFrame*);
+ static blink::mojom::DisplayMode CalculateDisplayMode(LocalFrame*);
static bool CalculateThreeDEnabled(LocalFrame*);
static bool CalculateInImmersiveMode(LocalFrame*);
static PointerType CalculatePrimaryPointerType(LocalFrame*);
@@ -104,7 +109,8 @@ class CORE_EXPORT MediaValues : public GarbageCollectedFinalized<MediaValues> {
static ColorSpaceGamut CalculateColorGamut(LocalFrame*);
static PreferredColorScheme CalculatePreferredColorScheme(LocalFrame*);
static bool CalculatePrefersReducedMotion(LocalFrame*);
- static ForcedColors CalculateForcedColors(LocalFrame*);
+ static ForcedColors CalculateForcedColors();
+ static NavigationControls CalculateNavigationControls(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 7da0eaf41bf..0f9c299e69f 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
@@ -5,6 +5,7 @@
#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/common/css/preferred_color_scheme.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -30,12 +31,13 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData()
three_d_enabled(false),
immersive_mode(false),
strict_mode(true),
- display_mode(kWebDisplayModeBrowser),
+ display_mode(blink::mojom::DisplayMode::kBrowser),
display_shape(kDisplayShapeRect),
color_gamut(ColorSpaceGamut::kUnknown),
preferred_color_scheme(PreferredColorScheme::kNoPreference),
prefers_reduced_motion(false),
- forced_colors(ForcedColors::kNone) {}
+ forced_colors(ForcedColors::kNone),
+ navigation_controls(NavigationControls::kNone) {}
MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
Document& document)
@@ -76,7 +78,8 @@ MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
color_gamut = MediaValues::CalculateColorGamut(frame);
preferred_color_scheme = MediaValues::CalculatePreferredColorScheme(frame);
prefers_reduced_motion = MediaValues::CalculatePrefersReducedMotion(frame);
- forced_colors = MediaValues::CalculateForcedColors(frame);
+ forced_colors = MediaValues::CalculateForcedColors();
+ navigation_controls = MediaValues::CalculateNavigationControls(frame);
}
}
@@ -165,7 +168,7 @@ const String MediaValuesCached::MediaType() const {
return data_.media_type;
}
-WebDisplayMode MediaValuesCached::DisplayMode() const {
+blink::mojom::DisplayMode MediaValuesCached::DisplayMode() const {
return data_.display_mode;
}
@@ -203,4 +206,8 @@ ForcedColors MediaValuesCached::GetForcedColors() const {
return data_.forced_colors;
}
+NavigationControls MediaValuesCached::GetNavigationControls() const {
+ return data_.navigation_controls;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/media_values_cached.h b/chromium/third_party/blink/renderer/core/css/media_values_cached.h
index 3d123a79841..4a82b2aa96e 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
@@ -33,12 +33,13 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
bool immersive_mode;
bool strict_mode;
String media_type;
- WebDisplayMode display_mode;
+ blink::mojom::DisplayMode display_mode;
DisplayShape display_shape;
ColorSpaceGamut color_gamut;
PreferredColorScheme preferred_color_scheme;
bool prefers_reduced_motion;
ForcedColors forced_colors;
+ NavigationControls navigation_controls;
MediaValuesCachedData();
explicit MediaValuesCachedData(Document&);
@@ -67,6 +68,7 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
data.preferred_color_scheme = preferred_color_scheme;
data.prefers_reduced_motion = prefers_reduced_motion;
data.forced_colors = forced_colors;
+ data.navigation_controls = navigation_controls;
return data;
}
};
@@ -100,12 +102,13 @@ class CORE_EXPORT MediaValuesCached final : public MediaValues {
Document* GetDocument() const override;
bool HasValues() const override;
const String MediaType() const override;
- WebDisplayMode DisplayMode() const override;
+ blink::mojom::DisplayMode DisplayMode() const override;
DisplayShape GetDisplayShape() const override;
ColorSpaceGamut ColorGamut() const override;
PreferredColorScheme GetPreferredColorScheme() const override;
bool PrefersReducedMotion() const override;
ForcedColors GetForcedColors() const override;
+ NavigationControls GetNavigationControls() 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 59488e77e1f..6a1035ea3a5 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/media_values_dynamic.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/common/css/preferred_color_scheme.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
@@ -127,7 +128,7 @@ const String MediaValuesDynamic::MediaType() const {
return CalculateMediaType(frame_);
}
-WebDisplayMode MediaValuesDynamic::DisplayMode() const {
+blink::mojom::DisplayMode MediaValuesDynamic::DisplayMode() const {
return CalculateDisplayMode(frame_);
}
@@ -152,7 +153,11 @@ bool MediaValuesDynamic::PrefersReducedMotion() const {
}
ForcedColors MediaValuesDynamic::GetForcedColors() const {
- return CalculateForcedColors(frame_);
+ return CalculateForcedColors();
+}
+
+NavigationControls MediaValuesDynamic::GetNavigationControls() const {
+ return CalculateNavigationControls(frame_);
}
Document* MediaValuesDynamic::GetDocument() const {
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 95c454e1fac..8b73c573a91 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
@@ -45,12 +45,13 @@ class CORE_EXPORT MediaValuesDynamic : public MediaValues {
bool InImmersiveMode() const override;
bool StrictMode() const override;
const String MediaType() const override;
- WebDisplayMode DisplayMode() const override;
+ blink::mojom::DisplayMode DisplayMode() const override;
DisplayShape GetDisplayShape() const override;
ColorSpaceGamut ColorGamut() const override;
PreferredColorScheme GetPreferredColorScheme() const override;
bool PrefersReducedMotion() const override;
ForcedColors GetForcedColors() const override;
+ NavigationControls GetNavigationControls() 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/mock_css_paint_image_generator.h b/chromium/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h
new file mode 100644
index 00000000000..c0c16ad4ea1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/mock_css_paint_image_generator.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_paint_image_generator.h"
+
+using testing::ReturnRef;
+
+namespace blink {
+
+class MockCSSPaintImageGenerator : public CSSPaintImageGenerator {
+ public:
+ MockCSSPaintImageGenerator() {
+ // These methods return references, so setup a default ON_CALL to make them
+ // easier to use. They can be overridden by a specific test if desired.
+ ON_CALL(*this, NativeInvalidationProperties())
+ .WillByDefault(ReturnRef(native_properties_));
+ ON_CALL(*this, CustomInvalidationProperties())
+ .WillByDefault(ReturnRef(custom_properties_));
+ ON_CALL(*this, InputArgumentTypes())
+ .WillByDefault(ReturnRef(input_argument_types_));
+ }
+
+ MOCK_METHOD4(Paint,
+ scoped_refptr<Image>(const ImageResourceObserver&,
+ const FloatSize& container_size,
+ const CSSStyleValueVector*,
+ float device_scale_factor));
+ MOCK_CONST_METHOD0(NativeInvalidationProperties, Vector<CSSPropertyID>&());
+ MOCK_CONST_METHOD0(CustomInvalidationProperties, Vector<AtomicString>&());
+ MOCK_CONST_METHOD0(HasAlpha, bool());
+ MOCK_CONST_METHOD0(InputArgumentTypes, Vector<CSSSyntaxDefinition>&());
+ MOCK_CONST_METHOD0(IsImageGeneratorReady, bool());
+ MOCK_CONST_METHOD0(WorkletId, int());
+
+ void AddCustomProperty(const AtomicString& custom_property) {
+ custom_properties_.push_back(custom_property);
+ }
+ void AddNativeProperty() {
+ native_properties_.push_back(CSSPropertyID::kBorderImageSource);
+ }
+
+ private:
+ Vector<CSSPropertyID> native_properties_;
+ Vector<AtomicString> custom_properties_;
+ Vector<CSSSyntaxDefinition> input_argument_types_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_MOCK_CSS_PAINT_IMAGE_GENERATOR_H_
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 9dc8287b1ae..e9ed122eff4 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
@@ -15,8 +15,6 @@ CSSAtRuleID CssAtRuleID(StringView name) {
return kCSSAtRuleCharset;
if (EqualIgnoringASCIICase(name, "font-face"))
return kCSSAtRuleFontFace;
- if (EqualIgnoringASCIICase(name, "font-feature-values"))
- return kCSSAtRuleFontFeatureValues;
if (EqualIgnoringASCIICase(name, "import"))
return kCSSAtRuleImport;
if (EqualIgnoringASCIICase(name, "keyframes"))
@@ -48,9 +46,6 @@ void CountAtRule(const CSSParserContext* context, CSSAtRuleID rule_id) {
case kCSSAtRuleFontFace:
feature = WebFeature::kCSSAtRuleFontFace;
break;
- case kCSSAtRuleFontFeatureValues:
- feature = WebFeature::kCSSAtRuleFontFeatureValues;
- break;
case kCSSAtRuleImport:
feature = WebFeature::kCSSAtRuleImport;
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 73fa0fdaaca..f15629e7dbb 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
@@ -15,7 +15,6 @@ enum CSSAtRuleID {
kCSSAtRuleInvalid,
kCSSAtRuleCharset,
kCSSAtRuleFontFace,
- kCSSAtRuleFontFeatureValues,
kCSSAtRuleImport,
kCSSAtRuleKeyframes,
kCSSAtRuleMedia,
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h b/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
index 6b7ad897bc1..19f486bb983 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_state.h
@@ -21,8 +21,7 @@ namespace blink {
// Currently, the only strong references to this class are from individual lazy
// properties, so after an entire lazy sheet is parsed, the extra memory should
// be released.
-class CSSLazyParsingState
- : public GarbageCollectedFinalized<CSSLazyParsingState> {
+class CSSLazyParsingState final : public GarbageCollected<CSSLazyParsingState> {
public:
CSSLazyParsingState(const CSSParserContext*,
const String& sheet_text,
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 b802a2dd6a7..2c9766dd5a4 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
@@ -46,7 +46,8 @@ CSSParserContext::CSSParserContext(const CSSParserContext* other,
other->use_legacy_background_size_shorthand_behavior_,
other->secure_context_mode_,
other->should_check_content_security_policy_,
- use_counter_document) {}
+ use_counter_document,
+ other->resource_fetch_restriction_) {}
CSSParserContext::CSSParserContext(
const CSSParserContext* other,
@@ -67,7 +68,8 @@ CSSParserContext::CSSParserContext(
other->use_legacy_background_size_shorthand_behavior_,
other->secure_context_mode_,
other->should_check_content_security_policy_,
- use_counter_document) {}
+ use_counter_document,
+ other->resource_fetch_restriction_) {}
CSSParserContext::CSSParserContext(CSSParserMode mode,
SecureContextMode secure_context_mode,
@@ -84,7 +86,8 @@ CSSParserContext::CSSParserContext(CSSParserMode mode,
false,
secure_context_mode,
kDoNotCheckContentSecurityPolicy,
- use_counter_document) {}
+ use_counter_document,
+ ResourceFetchRestriction::kNone) {}
CSSParserContext::CSSParserContext(const Document& document)
: CSSParserContext(document,
@@ -100,7 +103,8 @@ CSSParserContext::CSSParserContext(
bool origin_clean,
network::mojom::ReferrerPolicy referrer_policy_override,
const WTF::TextEncoding& charset,
- SelectorProfile profile)
+ SelectorProfile profile,
+ enum ResourceFetchRestriction resource_fetch_restriction)
: CSSParserContext(
base_url_override,
origin_clean,
@@ -123,7 +127,8 @@ CSSParserContext::CSSParserContext(
ContentSecurityPolicy::ShouldBypassMainWorld(&document)
? kDoNotCheckContentSecurityPolicy
: kCheckContentSecurityPolicy,
- &document) {}
+ &document,
+ resource_fetch_restriction) {}
CSSParserContext::CSSParserContext(const ExecutionContext& context)
: CSSParserContext(context.Url(),
@@ -140,7 +145,8 @@ CSSParserContext::CSSParserContext(const ExecutionContext& context)
ContentSecurityPolicy::ShouldBypassMainWorld(&context)
? kDoNotCheckContentSecurityPolicy
: kCheckContentSecurityPolicy,
- DynamicTo<Document>(context)) {}
+ DynamicTo<Document>(context),
+ ResourceFetchRestriction::kNone) {}
CSSParserContext::CSSParserContext(
const KURL& base_url,
@@ -154,7 +160,8 @@ CSSParserContext::CSSParserContext(
bool use_legacy_background_size_shorthand_behavior,
SecureContextMode secure_context_mode,
ContentSecurityPolicyDisposition policy_disposition,
- const Document* use_counter_document)
+ const Document* use_counter_document,
+ enum ResourceFetchRestriction resource_fetch_restriction)
: base_url_(base_url),
should_check_content_security_policy_(policy_disposition),
origin_clean_(origin_clean),
@@ -167,7 +174,8 @@ CSSParserContext::CSSParserContext(
use_legacy_background_size_shorthand_behavior),
secure_context_mode_(secure_context_mode),
charset_(charset),
- document_(use_counter_document) {}
+ document_(use_counter_document),
+ resource_fetch_restriction_(resource_fetch_restriction) {}
bool CSSParserContext::operator==(const CSSParserContext& other) const {
return base_url_ == other.base_url_ && origin_clean_ == other.origin_clean_ &&
@@ -176,7 +184,8 @@ bool CSSParserContext::operator==(const CSSParserContext& other) const {
is_html_document_ == other.is_html_document_ &&
use_legacy_background_size_shorthand_behavior_ ==
other.use_legacy_background_size_shorthand_behavior_ &&
- secure_context_mode_ == other.secure_context_mode_;
+ secure_context_mode_ == other.secure_context_mode_ &&
+ resource_fetch_restriction_ == other.resource_fetch_restriction_;
}
const CSSParserContext* StrictCSSParserContext(
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 c7435d8330f..17f30d7bcf5 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
@@ -7,6 +7,7 @@
#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_resource_fetch_restriction.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
@@ -23,8 +24,8 @@ class Document;
class StyleRuleKeyframe;
class StyleSheetContents;
-class CORE_EXPORT CSSParserContext
- : public GarbageCollectedFinalized<CSSParserContext> {
+class CORE_EXPORT CSSParserContext final
+ : public GarbageCollected<CSSParserContext> {
public:
// https://drafts.csswg.org/selectors/#profiles
enum SelectorProfile : uint8_t { kLiveProfile, kSnapshotProfile };
@@ -55,7 +56,9 @@ class CORE_EXPORT CSSParserContext
bool origin_clean,
network::mojom::ReferrerPolicy referrer_policy_override,
const WTF::TextEncoding& charset = WTF::TextEncoding(),
- SelectorProfile = kLiveProfile);
+ SelectorProfile = kLiveProfile,
+ ResourceFetchRestriction resource_fetch_restriction =
+ ResourceFetchRestriction::kNone);
// This is used for workers, where we don't have a document.
CSSParserContext(const ExecutionContext& context);
@@ -71,7 +74,8 @@ class CORE_EXPORT CSSParserContext
bool use_legacy_background_size_shorthand_behavior,
SecureContextMode,
ContentSecurityPolicyDisposition,
- const Document* use_counter_document);
+ const Document* use_counter_document,
+ ResourceFetchRestriction resource_fetch_restriction);
bool operator==(const CSSParserContext&) const;
bool operator!=(const CSSParserContext& other) const {
@@ -84,6 +88,9 @@ class CORE_EXPORT CSSParserContext
const WTF::TextEncoding& Charset() const { return charset_; }
const Referrer& GetReferrer() const { return referrer_; }
bool IsHTMLDocument() const { return is_html_document_; }
+ enum ResourceFetchRestriction ResourceFetchRestriction() const {
+ return resource_fetch_restriction_;
+ }
bool IsLiveProfile() const { return profile_ == kLiveProfile; }
bool IsOriginClean() const;
@@ -148,6 +155,10 @@ class CORE_EXPORT CSSParserContext
WTF::TextEncoding charset_;
WeakMember<const Document> document_;
+
+ // Flag indicating whether images with a URL scheme other than "data" are
+ // allowed.
+ const enum ResourceFetchRestriction resource_fetch_restriction_;
};
CORE_EXPORT const CSSParserContext* StrictCSSParserContext(SecureContextMode);
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 5578a01ce92..63a966880f4 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
@@ -886,6 +886,8 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
case CSSPropertyID::kFontKerning:
return value_id == CSSValueID::kAuto || value_id == CSSValueID::kNormal ||
value_id == CSSValueID::kNone;
+ case CSSPropertyID::kFontOpticalSizing:
+ return value_id == CSSValueID::kAuto || value_id == CSSValueID::kNone;
case CSSPropertyID::kWebkitFontSmoothing:
return value_id == CSSValueID::kAuto || value_id == CSSValueID::kNone ||
value_id == CSSValueID::kAntialiased ||
@@ -1061,6 +1063,7 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyID::kFlexDirection:
case CSSPropertyID::kFlexWrap:
case CSSPropertyID::kFontKerning:
+ case CSSPropertyID::kFontOpticalSizing:
case CSSPropertyID::kWebkitFontSmoothing:
case CSSPropertyID::kLineBreak:
case CSSPropertyID::kWebkitLineBreak:
@@ -1092,6 +1095,7 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
bool CSSParserFastPaths::IsPartialKeywordPropertyID(CSSPropertyID property_id) {
switch (property_id) {
case CSSPropertyID::kDisplay:
+ case CSSPropertyID::kListStyleType:
return true;
default:
return false;
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 dd681c46f74..08bf277c485 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
@@ -525,8 +525,6 @@ StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenStream& stream,
return ConsumeViewportRule(prelude, prelude_offset, stream);
case kCSSAtRuleFontFace:
return ConsumeFontFaceRule(prelude, prelude_offset, stream);
- case kCSSAtRuleFontFeatureValues:
- return ConsumeFontFeatureValuesRule(prelude, prelude_offset, stream);
case kCSSAtRuleWebkitKeyframes:
return ConsumeKeyframesRule(true, prelude, prelude_offset, stream);
case kCSSAtRuleKeyframes:
@@ -756,44 +754,6 @@ StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
CreateCSSPropertyValueSet(parsed_properties_, kCSSFontFaceRuleMode));
}
-StyleRuleFontFeatureValues* CSSParserImpl::ConsumeFontFeatureValuesRule(
- CSSParserTokenRange prelude,
- const RangeOffset& prelude_offset,
- CSSParserTokenStream& block) {
- if (!RuntimeEnabledFeatures::CSSFontFeatureValuesEnabled())
- return nullptr;
-
- const CSSValueList* font_family =
- css_parsing_utils::ConsumeFontFamily(prelude);
- if (!font_family || !prelude.AtEnd())
- return nullptr;
-
- if (observer_) {
- observer_->StartRuleHeader(StyleRule::kFontFeatureValues,
- prelude_offset.start);
- observer_->EndRuleHeader(prelude_offset.end);
- observer_->StartRuleBody(block.Offset());
- }
-
- const CSSIdentifierValue* font_display = nullptr;
- ConsumeRuleList(
- block, kFontFeatureRuleList, [&font_display](StyleRuleBase* rule) {
- const CSSValue* value =
- To<StyleRuleFontFace>(rule)->Properties().GetPropertyCSSValue(
- CSSPropertyID::kFontDisplay);
- if (value)
- font_display = To<CSSIdentifierValue>(value);
- });
-
- if (observer_)
- observer_->EndRuleBody(block.Offset());
-
- if (!block.AtEnd())
- return nullptr;
- return MakeGarbageCollected<StyleRuleFontFeatureValues>(font_family,
- font_display);
-}
-
StyleRuleKeyframes* CSSParserImpl::ConsumeKeyframesRule(
bool webkit_prefixed,
CSSParserTokenRange prelude,
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 7da6c307d80..6f1fa33bb69 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
@@ -26,7 +26,6 @@ class CSSParserTokenStream;
class StyleRule;
class StyleRuleBase;
class StyleRuleCharset;
-class StyleRuleFontFeatureValues;
class StyleRuleFontFace;
class StyleRuleImport;
class StyleRuleKeyframe;
@@ -163,10 +162,6 @@ class CSSParserImpl {
StyleRuleFontFace* ConsumeFontFaceRule(CSSParserTokenRange prelude,
const RangeOffset& prelude_offset,
CSSParserTokenStream& block);
- StyleRuleFontFeatureValues* ConsumeFontFeatureValuesRule(
- CSSParserTokenRange prelude,
- const RangeOffset& prelude_offset,
- CSSParserTokenStream& block);
StyleRuleKeyframes* ConsumeKeyframesRule(bool webkit_prefixed,
CSSParserTokenRange prelude,
const RangeOffset& prelude_offset,
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
index eec141a0686..79e47494477 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/css/css_image_set_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
#include "third_party/blink/renderer/core/css/css_initial_value.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
#include "third_party/blink/renderer/core/css/css_math_expression_node.h"
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
@@ -185,14 +186,13 @@ CSSParserTokenRange ConsumeFunction(CSSParserTokenRange& range) {
}
// TODO(rwlbuis): consider pulling in the parsing logic from
-// CSSCalculationValue.cpp.
-// TODO(xiaochengh): Rename to |MathFunctionParser|.
-class CalcParser {
+// css_math_expression_node.cc.
+class MathFunctionParser {
STACK_ALLOCATED();
public:
- explicit CalcParser(CSSParserTokenRange& range,
- ValueRange value_range = kValueRangeAll)
+ explicit MathFunctionParser(CSSParserTokenRange& range,
+ ValueRange value_range = kValueRangeAll)
: source_range_(range), range_(range) {
const CSSParserToken& token = range.Peek();
if (token.FunctionId() == CSSValueID::kCalc ||
@@ -215,8 +215,12 @@ class CalcParser {
CSSMathExpressionNode::ParseMax(ConsumeFunction(range_)),
value_range);
return;
+ case CSSValueID::kClamp:
+ calc_value_ = CSSMathFunctionValue::Create(
+ CSSMathExpressionNode::ParseClamp(ConsumeFunction(range_)),
+ value_range);
+ return;
default:
- // TODO(crbug.com/825895): Support clamp() when min()/max() are done.
break;
}
}
@@ -276,20 +280,20 @@ CSSPrimitiveValue* ConsumeInteger(CSSParserTokenRange& range,
range.ConsumeIncludingWhitespace().NumericValue(),
CSSPrimitiveValue::UnitType::kInteger);
}
- CalcParser calc_parser(range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
- if (!RuntimeEnabledFeatures::CSSCalcAsIntEnabled() && !calculation->IsInt())
+ MathFunctionParser math_parser(range);
+ if (const CSSMathFunctionValue* math_value = math_parser.Value()) {
+ if (!RuntimeEnabledFeatures::CSSCalcAsIntEnabled() && !math_value->IsInt())
return nullptr;
- if (calculation->Category() != kCalcNumber)
+ if (math_value->Category() != kCalcNumber)
return nullptr;
- double value = calculation->GetDoubleValue();
- if (value < minimum_value)
+ double double_value = math_value->GetDoubleValue();
+ if (double_value < minimum_value)
return nullptr;
if (!RuntimeEnabledFeatures::CSSCalcAsIntEnabled())
- return calc_parser.ConsumeNumber();
- if (calculation->IsInt())
- return calc_parser.ConsumeNumber();
- return calc_parser.ConsumeRoundedInt();
+ return math_parser.ConsumeNumber();
+ if (math_value->IsInt())
+ return math_parser.ConsumeNumber();
+ return math_parser.ConsumeRoundedInt();
}
return nullptr;
}
@@ -309,11 +313,11 @@ CSSPrimitiveValue* ConsumeIntegerOrNumberCalc(CSSParserTokenRange& range) {
range = int_range;
return value;
}
- CalcParser calc_parser(range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
if (calculation->Category() != kCalcNumber)
return nullptr;
- return calc_parser.ConsumeValue();
+ return math_parser.ConsumeValue();
}
return nullptr;
}
@@ -327,8 +331,8 @@ bool ConsumeNumberRaw(CSSParserTokenRange& range, double& result) {
result = range.ConsumeIncludingWhitespace().NumericValue();
return true;
}
- CalcParser calc_parser(range, kValueRangeAll);
- return calc_parser.ConsumeNumberRaw(result);
+ MathFunctionParser math_parser(range, kValueRangeAll);
+ return math_parser.ConsumeNumberRaw(result);
}
// TODO(timloh): Work out if this can just call consumeNumberRaw
@@ -341,14 +345,14 @@ CSSPrimitiveValue* ConsumeNumber(CSSParserTokenRange& range,
return CSSNumericLiteralValue::Create(
range.ConsumeIncludingWhitespace().NumericValue(), token.GetUnitType());
}
- CalcParser calc_parser(range, kValueRangeAll);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, kValueRangeAll);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
// TODO(rwlbuis) Calcs should not be subject to parse time range checks.
// spec: https://drafts.csswg.org/css-values-3/#calc-range
if (calculation->Category() != kCalcNumber ||
(value_range == kValueRangeNonNegative && calculation->IsNegative()))
return nullptr;
- return calc_parser.ConsumeNumber();
+ return math_parser.ConsumeNumber();
}
return nullptr;
}
@@ -411,9 +415,9 @@ CSSPrimitiveValue* ConsumeLength(CSSParserTokenRange& range,
}
if (css_parser_mode == kSVGAttributeMode)
return nullptr;
- CalcParser calc_parser(range, value_range);
- if (calc_parser.Value() && calc_parser.Value()->Category() == kCalcLength)
- return calc_parser.ConsumeValue();
+ MathFunctionParser math_parser(range, value_range);
+ if (math_parser.Value() && math_parser.Value()->Category() == kCalcLength)
+ return math_parser.ConsumeValue();
return nullptr;
}
@@ -427,10 +431,10 @@ CSSPrimitiveValue* ConsumePercent(CSSParserTokenRange& range,
range.ConsumeIncludingWhitespace().NumericValue(),
CSSPrimitiveValue::UnitType::kPercentage);
}
- CalcParser calc_parser(range, value_range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, value_range);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
if (calculation->Category() == kCalcPercent)
- return calc_parser.ConsumeValue();
+ return math_parser.ConsumeValue();
}
return nullptr;
}
@@ -471,10 +475,10 @@ CSSPrimitiveValue* ConsumeLengthOrPercent(CSSParserTokenRange& range,
return ConsumeLength(range, css_parser_mode, value_range, unitless);
if (token.GetType() == kPercentageToken)
return ConsumePercent(range, value_range);
- CalcParser calc_parser(range, value_range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, value_range);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
if (CanConsumeCalcValue(calculation->Category(), css_parser_mode))
- return calc_parser.ConsumeValue();
+ return math_parser.ConsumeValue();
}
return nullptr;
}
@@ -553,11 +557,11 @@ CSSPrimitiveValue* ConsumeAngle(
return CSSNumericLiteralValue::Create(
0, CSSPrimitiveValue::UnitType::kDegrees);
}
- CalcParser calc_parser(range, kValueRangeAll);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, kValueRangeAll);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
if (calculation->Category() != kCalcAngle)
return nullptr;
- if (CSSMathFunctionValue* result = calc_parser.ConsumeValue()) {
+ if (CSSMathFunctionValue* result = math_parser.ConsumeValue()) {
if (result->ComputeDegrees() < minimum_value) {
return CSSNumericLiteralValue::Create(
minimum_value, CSSPrimitiveValue::UnitType::kDegrees);
@@ -595,10 +599,10 @@ CSSPrimitiveValue* ConsumeTime(CSSParserTokenRange& range,
token.GetUnitType());
return nullptr;
}
- CalcParser calc_parser(range, value_range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, value_range);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
if (calculation->Category() == kCalcTime)
- return calc_parser.ConsumeValue();
+ return math_parser.ConsumeValue();
}
return nullptr;
}
@@ -859,8 +863,8 @@ static bool ParseColorFunction(CSSParserTokenRange& range, RGBA32& result) {
return true;
}
-static CSSValuePair* ParseLightDarkColor(CSSParserTokenRange& range,
- CSSParserMode mode) {
+static CSSLightDarkColorPair* ParseLightDarkColor(CSSParserTokenRange& range,
+ CSSParserMode mode) {
if (range.Peek().FunctionId() != CSSValueID::kInternalLightDarkColor)
return nullptr;
if (!isValueAllowedInMode(CSSValueID::kInternalLightDarkColor, mode))
@@ -872,8 +876,7 @@ static CSSValuePair* ParseLightDarkColor(CSSParserTokenRange& range,
CSSValue* dark_color = ConsumeColor(args, kUASheetMode);
if (!dark_color || !args.AtEnd())
return nullptr;
- return MakeGarbageCollected<CSSValuePair>(light_color, dark_color,
- CSSValuePair::kKeepIdenticalValues);
+ return MakeGarbageCollected<CSSLightDarkColorPair>(light_color, dark_color);
}
CSSValue* ConsumeColor(CSSParserTokenRange& range,
@@ -1269,7 +1272,7 @@ static CSSValue* ConsumeDeprecatedGradient(CSSParserTokenRange& args,
// For radial gradients only, we now expect a numeric radius.
const CSSPrimitiveValue* first_radius = nullptr;
if (id == CSSValueID::kRadial) {
- first_radius = ConsumeNumber(args, kValueRangeAll);
+ first_radius = ConsumeNumber(args, kValueRangeNonNegative);
if (!first_radius || !ConsumeCommaIncludingWhitespace(args))
return nullptr;
}
@@ -1288,7 +1291,7 @@ static CSSValue* ConsumeDeprecatedGradient(CSSParserTokenRange& args,
if (id == CSSValueID::kRadial) {
if (!ConsumeCommaIncludingWhitespace(args))
return nullptr;
- second_radius = ConsumeNumber(args, kValueRangeAll);
+ second_radius = ConsumeNumber(args, kValueRangeNonNegative);
if (!second_radius)
return nullptr;
}
@@ -1323,12 +1326,12 @@ static CSSPrimitiveValue* ConsumeGradientAngleOrPercent(
}
if (token.GetType() == kPercentageToken)
return ConsumePercent(range, value_range);
- CalcParser calc_parser(range, value_range);
- if (const CSSMathFunctionValue* calculation = calc_parser.Value()) {
+ MathFunctionParser math_parser(range, value_range);
+ if (const CSSMathFunctionValue* calculation = math_parser.Value()) {
CalculationCategory category = calculation->Category();
// TODO(fs): Add and support kCalcPercentAngle?
if (category == kCalcAngle || category == kCalcPercent)
- return calc_parser.ConsumeValue();
+ return math_parser.ConsumeValue();
}
return nullptr;
}
@@ -1404,10 +1407,10 @@ static CSSValue* ConsumeDeprecatedRadialGradient(
const CSSPrimitiveValue* vertical_size = nullptr;
if (!shape && !size_keyword) {
horizontal_size =
- ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll);
+ ConsumeLengthOrPercent(args, context.Mode(), kValueRangeNonNegative);
if (horizontal_size) {
vertical_size =
- ConsumeLengthOrPercent(args, context.Mode(), kValueRangeAll);
+ ConsumeLengthOrPercent(args, context.Mode(), kValueRangeNonNegative);
if (!vertical_size)
return nullptr;
ConsumeCommaIncludingWhitespace(args);
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 011f495b840..83e602857dd 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
@@ -714,4 +714,15 @@ TEST(CSSPropertyParserTest, UAInternalLightDarkColor) {
}
}
+TEST(CSSPropertyParserTest, UAInternalLightDarkColorSerialization) {
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+ const CSSValue* value = CSSParser::ParseSingleValue(
+ CSSPropertyID::kColor, "-internal-light-dark-color(red,#aaa)",
+ ua_context);
+ ASSERT_TRUE(value);
+ EXPECT_EQ("-internal-light-dark-color(red, rgb(170, 170, 170))",
+ value->CssText());
+}
+
} // namespace blink
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 6936279fbfd..68a9bbdea0c 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
@@ -37,6 +37,7 @@ const std::string Converter::kPseudoLookupTable[] = {
"-internal-spatial-navigation-focus",
"-internal-video-persistent",
"-internal-video-persistent-ancestor",
+ "-internal-xr-immersive-dom-overlay",
"-webkit-any-link",
"-webkit-autofill",
"-webkit-drag",
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 3a5aec71736..d2e02292994 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
@@ -252,6 +252,8 @@ bool IsPseudoClassValidAfterPseudoElement(
case CSSSelector::kPseudoSelection:
return pseudo_class == CSSSelector::kPseudoWindowInactive;
case CSSSelector::kPseudoPart:
+ return IsUserActionPseudoClass(pseudo_class) ||
+ pseudo_class == CSSSelector::kPseudoState;
case CSSSelector::kPseudoWebKitCustomElement:
case CSSSelector::kPseudoBlinkInternalElement:
return IsUserActionPseudoClass(pseudo_class);
@@ -599,6 +601,7 @@ std::unique_ptr<CSSParserSelector> CSSSelectorParser::ConsumePseudo(
selector->AdoptSelectorVector(selector_vector);
return selector;
}
+ case CSSSelector::kPseudoState:
case CSSSelector::kPseudoPart: {
const CSSParserToken& ident = block.ConsumeIncludingWhitespace();
if (ident.GetType() != kIdentToken || !block.AtEnd())
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc
index 28fc2f67b1c..7a59eb34018 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc
@@ -6,7 +6,7 @@
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
-#include "third_party/blink/renderer/core/css/parser/sizes_calc_parser.h"
+#include "third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h"
#include "third_party/blink/renderer/core/media_type_names.h"
namespace blink {
@@ -40,7 +40,7 @@ bool SizesAttributeParser::CalculateLengthInPixels(CSSParserTokenRange range,
return true;
}
} else if (type == kFunctionToken) {
- SizesCalcParser calc_parser(range, media_values_);
+ SizesMathFunctionParser calc_parser(range, media_values_);
if (!calc_parser.IsValid())
return false;
result = calc_parser.Result();
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser_test.cc
index 23c134e22e6..bcb5bcd9e49 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_attribute_parser_test.cc
@@ -87,7 +87,7 @@ TEST(SizesAttributeParserTest, Basic) {
data.three_d_enabled = true;
data.media_type = media_type_names::kScreen;
data.strict_mode = true;
- data.display_mode = kWebDisplayModeBrowser;
+ data.display_mode = blink::mojom::DisplayMode::kBrowser;
auto* media_values = MakeGarbageCollected<MediaValuesCached>(data);
for (unsigned i = 0; test_cases[i].input; ++i) {
@@ -168,7 +168,7 @@ TEST(SizesAttributeParserTest, FloatViewportWidth) {
data.three_d_enabled = true;
data.media_type = media_type_names::kScreen;
data.strict_mode = true;
- data.display_mode = kWebDisplayModeBrowser;
+ data.display_mode = blink::mojom::DisplayMode::kBrowser;
auto* media_values = MakeGarbageCollected<MediaValuesCached>(data);
for (unsigned i = 0; test_cases[i].input; ++i) {
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.cc
index ab825e8e790..6daa4598c3c 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/css/parser/sizes_calc_parser.h"
+#include "third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h"
#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token.h"
@@ -11,13 +11,13 @@
namespace blink {
-SizesCalcParser::SizesCalcParser(CSSParserTokenRange range,
- MediaValues* media_values)
+SizesMathFunctionParser::SizesMathFunctionParser(CSSParserTokenRange range,
+ MediaValues* media_values)
: media_values_(media_values), result_(0) {
is_valid_ = CalcToReversePolishNotation(range) && Calculate();
}
-float SizesCalcParser::Result() const {
+float SizesMathFunctionParser::Result() const {
DCHECK(is_valid_);
return result_;
}
@@ -32,8 +32,8 @@ static bool OperatorPriority(CSSMathOperator cc, bool& high_priority) {
return true;
}
-bool SizesCalcParser::HandleOperator(Vector<CSSParserToken>& stack,
- const CSSParserToken& token) {
+bool SizesMathFunctionParser::HandleOperator(Vector<CSSParserToken>& stack,
+ const CSSParserToken& token) {
// If the token is not an operator, then return. Else determine the
// precedence of the new operator (op1).
bool incoming_operator_priority;
@@ -65,7 +65,8 @@ bool SizesCalcParser::HandleOperator(Vector<CSSParserToken>& stack,
return true;
}
-bool SizesCalcParser::HandleRightParenthesis(Vector<CSSParserToken>& stack) {
+bool SizesMathFunctionParser::HandleRightParenthesis(
+ Vector<CSSParserToken>& stack) {
// If the token is a right parenthesis:
// Until the token at the top of the stack is a left parenthesis or a
// function, pop operators off the stack onto the output queue.
@@ -94,6 +95,16 @@ bool SizesCalcParser::HandleRightParenthesis(Vector<CSSParserToken>& stack) {
return !comma_count;
}
+ if (left_side.FunctionId() == CSSValueID::kClamp) {
+ if (comma_count != 2)
+ return false;
+ // Convert clamp(MIN, VAL, MAX) into max(MIN, min(VAL, MAX))
+ // https://www.w3.org/TR/css-values-4/#calc-notation
+ value_list_.emplace_back(CSSMathOperator::kMin);
+ value_list_.emplace_back(CSSMathOperator::kMax);
+ return true;
+ }
+
// Break variadic min/max() into binary operations to fit in the reverse
// polish notation.
CSSMathOperator op = left_side.FunctionId() == CSSValueID::kMin
@@ -104,8 +115,8 @@ bool SizesCalcParser::HandleRightParenthesis(Vector<CSSParserToken>& stack) {
return true;
}
-bool SizesCalcParser::HandleComma(Vector<CSSParserToken>& stack,
- const CSSParserToken& token) {
+bool SizesMathFunctionParser::HandleComma(Vector<CSSParserToken>& stack,
+ const CSSParserToken& token) {
if (!RuntimeEnabledFeatures::CSSComparisonFunctionsEnabled())
return false;
// Treat comma as a binary right-associative operation for now, so that
@@ -124,14 +135,14 @@ bool SizesCalcParser::HandleComma(Vector<CSSParserToken>& stack,
return true;
}
-void SizesCalcParser::AppendNumber(const CSSParserToken& token) {
- SizesCalcValue value;
+void SizesMathFunctionParser::AppendNumber(const CSSParserToken& token) {
+ SizesMathValue value;
value.value = token.NumericValue();
value_list_.push_back(value);
}
-bool SizesCalcParser::AppendLength(const CSSParserToken& token) {
- SizesCalcValue value;
+bool SizesMathFunctionParser::AppendLength(const CSSParserToken& token) {
+ SizesMathValue value;
double result = 0;
if (!media_values_->ComputeLength(token.NumericValue(), token.GetUnitType(),
result))
@@ -142,11 +153,12 @@ bool SizesCalcParser::AppendLength(const CSSParserToken& token) {
return true;
}
-void SizesCalcParser::AppendOperator(const CSSParserToken& token) {
+void SizesMathFunctionParser::AppendOperator(const CSSParserToken& token) {
value_list_.emplace_back(ParseCSSArithmeticOperator(token));
}
-bool SizesCalcParser::CalcToReversePolishNotation(CSSParserTokenRange range) {
+bool SizesMathFunctionParser::CalcToReversePolishNotation(
+ CSSParserTokenRange range) {
// This method implements the shunting yard algorithm, to turn the calc syntax
// into a reverse polish notation.
// http://en.wikipedia.org/wiki/Shunting-yard_algorithm
@@ -170,8 +182,8 @@ bool SizesCalcParser::CalcToReversePolishNotation(CSSParserTokenRange range) {
case kFunctionToken:
if (RuntimeEnabledFeatures::CSSComparisonFunctionsEnabled()) {
if (token.FunctionId() == CSSValueID::kMin ||
- token.FunctionId() == CSSValueID::kMax) {
- // TODO(crbug.com/825895): Add clamp() when min/max are done.
+ token.FunctionId() == CSSValueID::kMax ||
+ token.FunctionId() == CSSValueID::kClamp) {
stack.push_back(token);
break;
}
@@ -240,13 +252,13 @@ bool SizesCalcParser::CalcToReversePolishNotation(CSSParserTokenRange range) {
return true;
}
-static bool OperateOnStack(Vector<SizesCalcValue>& stack,
+static bool OperateOnStack(Vector<SizesMathValue>& stack,
CSSMathOperator operation) {
if (stack.size() < 2)
return false;
- SizesCalcValue right_operand = stack.back();
+ SizesMathValue right_operand = stack.back();
stack.pop_back();
- SizesCalcValue left_operand = stack.back();
+ SizesMathValue left_operand = stack.back();
stack.pop_back();
bool is_length;
switch (operation) {
@@ -255,40 +267,40 @@ static bool OperateOnStack(Vector<SizesCalcValue>& stack,
return false;
is_length = (right_operand.is_length && left_operand.is_length);
stack.push_back(
- SizesCalcValue(left_operand.value + right_operand.value, is_length));
+ SizesMathValue(left_operand.value + right_operand.value, is_length));
break;
case CSSMathOperator::kSubtract:
if (right_operand.is_length != left_operand.is_length)
return false;
is_length = (right_operand.is_length && left_operand.is_length);
stack.push_back(
- SizesCalcValue(left_operand.value - right_operand.value, is_length));
+ SizesMathValue(left_operand.value - right_operand.value, is_length));
break;
case CSSMathOperator::kMultiply:
if (right_operand.is_length && left_operand.is_length)
return false;
is_length = (right_operand.is_length || left_operand.is_length);
stack.push_back(
- SizesCalcValue(left_operand.value * right_operand.value, is_length));
+ SizesMathValue(left_operand.value * right_operand.value, is_length));
break;
case CSSMathOperator::kDivide:
if (right_operand.is_length || right_operand.value == 0)
return false;
- stack.push_back(SizesCalcValue(left_operand.value / right_operand.value,
+ stack.push_back(SizesMathValue(left_operand.value / right_operand.value,
left_operand.is_length));
break;
case CSSMathOperator::kMin:
if (right_operand.is_length != left_operand.is_length)
return false;
is_length = (right_operand.is_length && left_operand.is_length);
- stack.push_back(SizesCalcValue(
+ stack.push_back(SizesMathValue(
std::min(left_operand.value, right_operand.value), is_length));
break;
case CSSMathOperator::kMax:
if (right_operand.is_length != left_operand.is_length)
return false;
is_length = (right_operand.is_length && left_operand.is_length);
- stack.push_back(SizesCalcValue(
+ stack.push_back(SizesMathValue(
std::max(left_operand.value, right_operand.value), is_length));
break;
default:
@@ -297,8 +309,8 @@ static bool OperateOnStack(Vector<SizesCalcValue>& stack,
return true;
}
-bool SizesCalcParser::Calculate() {
- Vector<SizesCalcValue> stack;
+bool SizesMathFunctionParser::Calculate() {
+ Vector<SizesMathValue> stack;
for (const auto& value : value_list_) {
if (value.operation == CSSMathOperator::kInvalid) {
stack.push_back(value);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.h b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h
index b5ca9602b6f..de8b146de0c 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_CALC_PARSER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_CALC_PARSER_H_
-
-// TODO(crbug.com/825895): Rename the file and classes from "calc" to "math"
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_MATH_FUNCTION_PARSER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_MATH_FUNCTION_PARSER_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/css_math_operator.h"
@@ -16,25 +14,25 @@
namespace blink {
-struct SizesCalcValue {
+struct SizesMathValue {
DISALLOW_NEW();
double value = 0;
bool is_length = false;
CSSMathOperator operation = CSSMathOperator::kInvalid;
- SizesCalcValue() = default;
+ SizesMathValue() = default;
- SizesCalcValue(double numeric_value, bool length)
+ SizesMathValue(double numeric_value, bool length)
: value(numeric_value), is_length(length) {}
- explicit SizesCalcValue(CSSMathOperator op) : operation(op) {}
+ explicit SizesMathValue(CSSMathOperator op) : operation(op) {}
};
-class CORE_EXPORT SizesCalcParser {
+class CORE_EXPORT SizesMathFunctionParser {
STACK_ALLOCATED();
public:
- SizesCalcParser(CSSParserTokenRange, MediaValues*);
+ SizesMathFunctionParser(CSSParserTokenRange, MediaValues*);
float Result() const;
bool IsValid() const { return is_valid_; }
@@ -49,7 +47,7 @@ class CORE_EXPORT SizesCalcParser {
bool HandleOperator(Vector<CSSParserToken>& stack, const CSSParserToken&);
void AppendOperator(const CSSParserToken&);
- Vector<SizesCalcValue> value_list_;
+ Vector<SizesMathValue> value_list_;
Member<MediaValues> media_values_;
bool is_valid_;
float result_;
@@ -57,4 +55,4 @@ class CORE_EXPORT SizesCalcParser {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_CALC_PARSER_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PARSER_SIZES_MATH_FUNCTION_PARSER_H_
diff --git a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc
index c36015115e3..f6b07c22960 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/sizes_calc_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/sizes_math_function_parser_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/renderer/core/css/parser/sizes_calc_parser.h"
+#include "third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_math_function_value.h"
@@ -62,7 +62,7 @@ static void VerifyCSSCalc(String text,
EXPECT_APPROX_EQ(value, math_value->ComputeLength<float>(conversion_data));
}
-TEST(SizesCalcParserTest, Basic) {
+TEST(SizesMathFunctionParserTest, Basic) {
ScopedCSSComparisonFunctionsForTest scope(true);
SizesCalcTestCase test_cases[] = {
@@ -151,6 +151,22 @@ TEST(SizesCalcParserTest, Basic) {
{"calc(min(100px, 200px) / max(3, 4, 5))", 20, true, false},
{"max(10px, min(20px, 1em))", 16, true, false},
{"min(20px, max(10px, 1em))", 16, true, false},
+ {"clamp(10px, 20px, 30px)", 20, true, false},
+ {"clamp(10px, 5px, 30px)", 10, true, false},
+ {"clamp(10px, 35px, 30px)", 30, true, false},
+ {"clamp(30px, 20px, 10px)", 30, true, false},
+ {"clamp(10px, 20px, clamp(20px, 30px, 40px))", 20, true, false},
+ {"clamp()", 0, false, false},
+ {"clamp( )", 0, false, false},
+ {"clamp(,)", 0, false, false},
+ {"clamp(1px, )", 0, false, false},
+ {"clamp(, 1px)", 0, false, false},
+ {"clamp(1px, 1px)", 0, false, false},
+ {"clamp(1px, , 1px)", 0, false, false},
+ {"clamp(, 1px, 1px)", 0, false, false},
+ {"clamp(1px, 1px, )", 0, false, false},
+ {"clamp(1px, 1px, 1px, )", 0, false, false},
+ {"clamp(1px 1px 1px)", 0, false, false},
{nullptr, 0, true, false} // Do not remove the terminator line.
};
@@ -167,11 +183,11 @@ TEST(SizesCalcParserTest, Basic) {
data.three_d_enabled = true;
data.media_type = media_type_names::kScreen;
data.strict_mode = true;
- data.display_mode = kWebDisplayModeBrowser;
+ data.display_mode = blink::mojom::DisplayMode::kBrowser;
auto* media_values = MakeGarbageCollected<MediaValuesCached>(data);
for (unsigned i = 0; test_cases[i].input; ++i) {
- SizesCalcParser calc_parser(
+ SizesMathFunctionParser calc_parser(
CSSParserTokenRange(CSSTokenizer(test_cases[i].input).TokenizeToEOF()),
media_values);
ASSERT_EQ(test_cases[i].valid, calc_parser.IsValid());
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 39b7cffcec6..ca3b3f18291 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
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/css/css_font_family_value.h"
#include "third_party/blink/renderer/core/css/css_font_style_range_value.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
+#include "third_party/blink/renderer/core/css/css_grid_auto_repeat_value.h"
#include "third_party/blink/renderer/core/css/css_grid_line_names_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"
@@ -29,18 +30,21 @@
#include "third_party/blink/renderer/core/css/cssom/cross_thread_color_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/cross_thread_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/cross_thread_unsupported_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
+#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color_value.h"
#include "third_party/blink/renderer/core/css/style_color.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
-#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/core/svg_element_type_helpers.h"
namespace blink {
@@ -801,7 +805,7 @@ CSSValue* ComputedStyleUtils::ValueForFontStyle(const ComputedStyle& style) {
*CSSIdentifierValue::Create(CSSValueID::kOblique), *oblique_values);
}
-CSSPrimitiveValue* ComputedStyleUtils::ValueForFontWeight(
+CSSNumericLiteralValue* ComputedStyleUtils::ValueForFontWeight(
const ComputedStyle& style) {
return CSSNumericLiteralValue::Create(style.GetFontDescription().Weight(),
CSSPrimitiveValue::UnitType::kNumber);
@@ -1003,13 +1007,18 @@ CSSValue* ComputedStyleUtils::ValueForFontVariantEastAsian(
}
CSSValue* ComputedStyleUtils::ValueForFont(const ComputedStyle& style) {
- // Add a slash between size and line-height.
- CSSValueList* size_and_line_height = CSSValueList::CreateSlashSeparated();
- size_and_line_height->Append(*ValueForFontSize(style));
- size_and_line_height->Append(*ValueForLineHeight(style));
+ auto AppendIfNotNormal = [](CSSValueList* list, const CSSValue& value) {
+ auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
+ if (identifier_value &&
+ identifier_value->GetValueID() == CSSValueID::kNormal) {
+ return;
+ }
+
+ list->Append(value);
+ };
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- list->Append(*ValueForFontStyle(style));
+ AppendIfNotNormal(list, *ValueForFontStyle(style));
// Check that non-initial font-variant subproperties are not conflicting with
// this serialization.
@@ -1036,11 +1045,32 @@ CSSValue* ComputedStyleUtils::ValueForFont(const ComputedStyle& style) {
if (caps_value->GetValueID() != CSSValueID::kNormal &&
caps_value->GetValueID() != CSSValueID::kSmallCaps)
return nullptr;
- list->Append(*caps_value);
+ AppendIfNotNormal(list, *caps_value);
+
+ {
+ CSSNumericLiteralValue* font_weight = ValueForFontWeight(style);
+ if (font_weight->DoubleValue() != NormalWeightValue())
+ list->Append(*font_weight);
+ }
+
+ AppendIfNotNormal(list, *ValueForFontStretchAsKeyword(style));
+
+ {
+ CSSValue* line_height = ValueForLineHeight(style);
+ auto* identifier_line_height = DynamicTo<CSSIdentifierValue>(line_height);
+ if (identifier_line_height &&
+ identifier_line_height->GetValueID() == CSSValueID::kNormal) {
+ list->Append(*ValueForFontSize(style));
+ } else {
+ // Add a slash between size and line-height.
+ CSSValueList* size_and_line_height = CSSValueList::CreateSlashSeparated();
+ size_and_line_height->Append(*ValueForFontSize(style));
+ size_and_line_height->Append(*line_height);
+
+ list->Append(*size_and_line_height);
+ }
+ }
- list->Append(*ValueForFontWeight(style));
- list->Append(*ValueForFontStretchAsKeyword(style));
- list->Append(*size_and_line_height);
list->Append(*ValueForFontFamily(style));
return list;
@@ -1099,39 +1129,62 @@ class OrderedNamedLinesCollector {
STACK_ALLOCATED();
public:
- OrderedNamedLinesCollector(const ComputedStyle& style,
- bool is_row_axis,
- size_t auto_repeat_tracks_count)
+ OrderedNamedLinesCollector(const ComputedStyle& style, bool is_row_axis)
: ordered_named_grid_lines_(is_row_axis
? style.OrderedNamedGridColumnLines()
: style.OrderedNamedGridRowLines()),
ordered_named_auto_repeat_grid_lines_(
is_row_axis ? style.AutoRepeatOrderedNamedGridColumnLines()
- : style.AutoRepeatOrderedNamedGridRowLines()),
- insertion_point_(is_row_axis
- ? style.GridAutoRepeatColumnsInsertionPoint()
- : style.GridAutoRepeatRowsInsertionPoint()),
- auto_repeat_total_tracks_(auto_repeat_tracks_count),
- auto_repeat_track_list_length_(
- is_row_axis ? style.GridAutoRepeatColumns().size()
- : style.GridAutoRepeatRows().size()) {}
+ : style.AutoRepeatOrderedNamedGridRowLines()) {}
+ virtual ~OrderedNamedLinesCollector() = default;
bool IsEmpty() const {
return ordered_named_grid_lines_.IsEmpty() &&
ordered_named_auto_repeat_grid_lines_.IsEmpty();
}
- void CollectLineNamesForIndex(CSSGridLineNamesValue&, size_t index) const;
+ virtual void CollectLineNamesForIndex(CSSGridLineNamesValue&,
+ size_t index) const;
- private:
+ protected:
enum NamedLinesType { kNamedLines, kAutoRepeatNamedLines };
void AppendLines(CSSGridLineNamesValue&, size_t index, NamedLinesType) const;
const OrderedNamedGridLines& ordered_named_grid_lines_;
const OrderedNamedGridLines& ordered_named_auto_repeat_grid_lines_;
+ DISALLOW_COPY_AND_ASSIGN(OrderedNamedLinesCollector);
+};
+
+class OrderedNamedLinesCollectorInsideRepeat
+ : public OrderedNamedLinesCollector {
+ public:
+ OrderedNamedLinesCollectorInsideRepeat(const ComputedStyle& style,
+ bool is_row_axis)
+ : OrderedNamedLinesCollector(style, is_row_axis) {}
+ void CollectLineNamesForIndex(CSSGridLineNamesValue&,
+ size_t index) const override;
+};
+
+class OrderedNamedLinesCollectorInGridLayout
+ : public OrderedNamedLinesCollector {
+ public:
+ OrderedNamedLinesCollectorInGridLayout(const ComputedStyle& style,
+ bool is_row_axis,
+ size_t auto_repeat_tracks_count)
+ : OrderedNamedLinesCollector(style, is_row_axis),
+ insertion_point_(is_row_axis
+ ? style.GridAutoRepeatColumnsInsertionPoint()
+ : style.GridAutoRepeatRowsInsertionPoint()),
+ auto_repeat_total_tracks_(auto_repeat_tracks_count),
+ auto_repeat_track_list_length_(
+ is_row_axis ? style.GridAutoRepeatColumns().size()
+ : style.GridAutoRepeatRows().size()) {}
+ void CollectLineNamesForIndex(CSSGridLineNamesValue&,
+ size_t index) const override;
+
+ private:
size_t insertion_point_;
size_t auto_repeat_total_tracks_;
size_t auto_repeat_track_list_length_;
- DISALLOW_COPY_AND_ASSIGN(OrderedNamedLinesCollector);
};
// RJW
@@ -1154,11 +1207,25 @@ void OrderedNamedLinesCollector::AppendLines(
}
}
-// RJW
void OrderedNamedLinesCollector::CollectLineNamesForIndex(
CSSGridLineNamesValue& line_names_value,
size_t i) const {
DCHECK(!IsEmpty());
+ AppendLines(line_names_value, i, kNamedLines);
+}
+
+void OrderedNamedLinesCollectorInsideRepeat::CollectLineNamesForIndex(
+ CSSGridLineNamesValue& line_names_value,
+ size_t i) const {
+ DCHECK(!IsEmpty());
+ AppendLines(line_names_value, i, kAutoRepeatNamedLines);
+}
+
+// RJW
+void OrderedNamedLinesCollectorInGridLayout::CollectLineNamesForIndex(
+ CSSGridLineNamesValue& line_names_value,
+ size_t i) const {
+ DCHECK(!IsEmpty());
if (ordered_named_auto_repeat_grid_lines_.IsEmpty() || i < insertion_point_) {
AppendLines(line_names_value, i, kNamedLines);
return;
@@ -1220,6 +1287,31 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackSizeList(
return list;
}
+template <typename T, typename F>
+void PopulateGridTrackList(CSSValueList* list,
+ OrderedNamedLinesCollector& collector,
+ const Vector<T>& tracks,
+ F getTrackSize,
+ wtf_size_t start,
+ wtf_size_t end,
+ size_t offset = 0) {
+ DCHECK_LE(end, tracks.size());
+ for (wtf_size_t i = start; i < end; ++i) {
+ AddValuesForNamedGridLinesAtIndex(collector, i + offset, *list);
+ list->Append(*getTrackSize(tracks[i]));
+ }
+ AddValuesForNamedGridLinesAtIndex(collector, end + offset, *list);
+}
+
+template <typename T, typename F>
+void PopulateGridTrackList(CSSValueList* list,
+ OrderedNamedLinesCollector& collector,
+ const Vector<T>& tracks,
+ F getTrackSize) {
+ PopulateGridTrackList<T>(list, collector, tracks, getTrackSize, 0,
+ tracks.size());
+}
+
CSSValue* ComputedStyleUtils::ValueForGridTrackList(
GridTrackSizingDirection direction,
const LayoutObject* layout_object,
@@ -1246,36 +1338,54 @@ CSSValue* ComputedStyleUtils::ValueForGridTrackList(
if (track_list_is_empty)
return CSSIdentifierValue::Create(CSSValueID::kNone);
- size_t auto_repeat_total_tracks =
- is_layout_grid
- ? ToLayoutGrid(layout_object)->AutoRepeatCountForDirection(direction)
- : 0;
- OrderedNamedLinesCollector collector(style, is_row_axis,
- auto_repeat_total_tracks);
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
- wtf_size_t insertion_index;
+
+ // If the element is a grid container, the resolved value is the used value,
+ // specifying track sizes in pixels and expanding the repeat() notation.
if (is_layout_grid) {
const auto* grid = ToLayoutGrid(layout_object);
- Vector<LayoutUnit> computed_track_sizes =
- grid->TrackSizesForComputedStyle(direction);
- wtf_size_t num_tracks = computed_track_sizes.size();
-
- for (wtf_size_t i = 0; i < num_tracks; ++i) {
- AddValuesForNamedGridLinesAtIndex(collector, i, *list);
- list->Append(*ZoomAdjustedPixelValue(computed_track_sizes[i], style));
- }
- AddValuesForNamedGridLinesAtIndex(collector, num_tracks + 1, *list);
+ OrderedNamedLinesCollectorInGridLayout collector(
+ style, is_row_axis, grid->AutoRepeatCountForDirection(direction));
+ PopulateGridTrackList(
+ list, collector, grid->TrackSizesForComputedStyle(direction),
+ [&](const LayoutUnit& v) { return ZoomAdjustedPixelValue(v, style); });
+ return list;
+ }
+
+ // Otherwise, the resolved value is the computed value, preserving repeat().
+ OrderedNamedLinesCollector collector(style, is_row_axis);
+ auto getTrackSize = [&](const GridTrackSize& v) {
+ return SpecifiedValueForGridTrackSize(v, style);
+ };
- insertion_index = num_tracks;
- } else {
- for (wtf_size_t i = 0; i < track_sizes.size(); ++i) {
- AddValuesForNamedGridLinesAtIndex(collector, i, *list);
- list->Append(*SpecifiedValueForGridTrackSize(track_sizes[i], style));
- }
- insertion_index = track_sizes.size();
- }
- // Those are the trailing <string>* allowed in the syntax.
- AddValuesForNamedGridLinesAtIndex(collector, insertion_index, *list);
+ if (auto_repeat_track_sizes.IsEmpty()) {
+ // If there's no auto repeat(), just add all the line names and track sizes.
+ PopulateGridTrackList(list, collector, track_sizes, getTrackSize);
+ return list;
+ }
+
+ // Add the line names and track sizes that precede the auto repeat().
+ size_t auto_repeat_insertion_point =
+ is_row_axis ? style.GridAutoRepeatColumnsInsertionPoint()
+ : style.GridAutoRepeatRowsInsertionPoint();
+ PopulateGridTrackList(list, collector, track_sizes, getTrackSize, 0,
+ auto_repeat_insertion_point);
+
+ // Add a CSSGridAutoRepeatValue with the contents of the auto repeat().
+ AutoRepeatType auto_repeat_type = is_row_axis
+ ? style.GridAutoRepeatColumnsType()
+ : style.GridAutoRepeatRowsType();
+ CSSValueList* repeated_values = MakeGarbageCollected<CSSGridAutoRepeatValue>(
+ auto_repeat_type == AutoRepeatType::kAutoFill ? CSSValueID::kAutoFill
+ : CSSValueID::kAutoFit);
+ OrderedNamedLinesCollectorInsideRepeat repeat_collector(style, is_row_axis);
+ PopulateGridTrackList(repeated_values, repeat_collector,
+ auto_repeat_track_sizes, getTrackSize);
+ list->Append(*repeated_values);
+
+ // Add the line names and track sizes that follow the auto repeat().
+ PopulateGridTrackList(list, collector, track_sizes, getTrackSize,
+ auto_repeat_insertion_point, track_sizes.size(), 1);
return list;
}
@@ -1669,7 +1779,7 @@ FloatRect ComputedStyleUtils::ReferenceBoxForTransform(
const LayoutObject& layout_object,
UsePixelSnappedBox pixel_snap_box) {
if (layout_object.IsSVGChild())
- return ComputeSVGTransformReferenceBox(layout_object);
+ return TransformHelper::ComputeReferenceBox(layout_object);
if (layout_object.IsBox()) {
const auto& layout_box = ToLayoutBox(layout_object);
if (pixel_snap_box == kUsePixelSnappedBox)
@@ -2454,6 +2564,9 @@ ComputedStyleUtils::CrossThreadStyleValueFromCSSStyleValue(
case CSSStyleValue::StyleValueType::kUnsupportedColorType:
return std::make_unique<CrossThreadColorValue>(
To<CSSUnsupportedColorValue>(style_value)->Value());
+ case CSSStyleValue::StyleValueType::kUnparsedType:
+ return std::make_unique<CrossThreadUnparsedValue>(
+ To<CSSUnparsedValue>(style_value)->ToString().IsolatedCopy());
default:
// Make an isolated copy to ensure that it is safe to pass cross thread.
return std::make_unique<CrossThreadUnsupportedValue>(
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 9cda1029785..6ac44dc9de4 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
@@ -19,9 +19,10 @@ namespace blink {
using namespace cssvalue;
-class ComputedStyle;
+class CSSNumericLiteralValue;
class CSSStyleValue;
class CSSValue;
+class ComputedStyle;
class StyleColor;
class StylePropertyShorthand;
@@ -104,7 +105,7 @@ class ComputedStyleUtils {
static CSSPrimitiveValue* ValueForFontSize(const ComputedStyle&);
static CSSPrimitiveValue* ValueForFontStretch(const ComputedStyle&);
static CSSValue* ValueForFontStyle(const ComputedStyle&);
- static CSSPrimitiveValue* ValueForFontWeight(const ComputedStyle&);
+ static CSSNumericLiteralValue* ValueForFontWeight(const ComputedStyle&);
static CSSIdentifierValue* ValueForFontVariantCaps(const ComputedStyle&);
static CSSValue* ValueForFontVariantLigatures(const ComputedStyle&);
static CSSValue* ValueForFontVariantNumeric(const ComputedStyle&);
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 f6dc21ef4e7..b90e0e3b86f 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
@@ -849,6 +849,7 @@ bool ParseBackgroundOrMask(bool important,
CSSValue* origin_value = nullptr;
do {
bool found_property = false;
+ bool bg_position_parsed_in_current_layer = false;
for (unsigned i = 0; i < longhand_count; ++i) {
if (parsed_longhand[i])
continue;
@@ -866,6 +867,8 @@ bool ParseBackgroundOrMask(bool important,
css_property_parser_helpers::UnitlessQuirk::kForbid,
WebFeature::kThreeValuedPositionBackground, value, value_y))
continue;
+ if (value)
+ bg_position_parsed_in_current_layer = true;
} else if (property.IDEquals(CSSPropertyID::kBackgroundSize) ||
property.IDEquals(CSSPropertyID::kWebkitMaskSize)) {
if (!css_property_parser_helpers::ConsumeSlashIncludingWhitespace(
@@ -877,12 +880,8 @@ bool ParseBackgroundOrMask(bool important,
? WebFeature::kNegativeBackgroundSize
: WebFeature::kNegativeMaskSize,
ParsingStyle::kNotLegacy);
- if (!value ||
- !parsed_longhand[i - 1]) // Position must have been
- // parsed in the current layer.
- {
+ if (!value || !bg_position_parsed_in_current_layer)
return false;
- }
} else if (property.IDEquals(CSSPropertyID::kBackgroundPositionY) ||
property.IDEquals(CSSPropertyID::kBackgroundRepeatY) ||
property.IDEquals(CSSPropertyID::kWebkitMaskPositionY) ||
@@ -1723,7 +1722,7 @@ CSSCustomIdentValue* ConsumeCustomIdentForGridLine(
}
// Appends to the passed in CSSGridLineNamesValue if any, otherwise creates a
-// new one.
+// new one. Returns nullptr if an empty list is consumed.
CSSGridLineNamesValue* ConsumeGridLineNames(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -1739,6 +1738,8 @@ CSSGridLineNamesValue* ConsumeGridLineNames(
if (range_copy.ConsumeIncludingWhitespace().GetType() != kRightBracketToken)
return nullptr;
range = range_copy;
+ if (line_names->length() == 0U)
+ return nullptr;
return line_names;
}
@@ -1939,12 +1940,11 @@ CSSValue* ConsumeGridTrackList(CSSParserTokenRange& range,
TrackListType track_list_type) {
bool allow_grid_line_names = track_list_type != TrackListType::kGridAuto;
CSSValueList* values = CSSValueList::CreateSpaceSeparated();
+ if (!allow_grid_line_names && range.Peek().GetType() == kLeftBracketToken)
+ return nullptr;
CSSGridLineNamesValue* line_names = ConsumeGridLineNames(range, context);
- if (line_names) {
- if (!allow_grid_line_names)
- return nullptr;
+ if (line_names)
values->Append(*line_names);
- }
bool allow_repeat = track_list_type == TrackListType::kGridTemplate;
bool seen_auto_repeat = false;
@@ -1970,12 +1970,11 @@ CSSValue* ConsumeGridTrackList(CSSParserTokenRange& range,
}
if (seen_auto_repeat && !all_tracks_are_fixed_sized)
return nullptr;
+ if (!allow_grid_line_names && range.Peek().GetType() == kLeftBracketToken)
+ return nullptr;
line_names = ConsumeGridLineNames(range, context);
- if (line_names) {
- if (!allow_grid_line_names)
- return nullptr;
+ if (line_names)
values->Append(*line_names);
- }
} while (!range.AtEnd() && range.Peek().GetType() != kDelimiterToken);
return values;
}
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 6dc426bbece..68a697521d4 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
@@ -1899,8 +1899,7 @@ const CSSValue* Content::ParseSingleValue(CSSParserTokenRange& range,
}
}
if (!parsed_value) {
- if (RuntimeEnabledFeatures::CSSAltTextEnabled() &&
- css_property_parser_helpers::ConsumeSlashIncludingWhitespace(range)) {
+ if (css_property_parser_helpers::ConsumeSlashIncludingWhitespace(range)) {
// No values were parsed before the slash, so nothing to apply the
// alternative text to.
if (!values->length())
@@ -2560,6 +2559,15 @@ const CSSValue* FontKerning::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetFontDescription().GetKerning());
}
+const CSSValue* FontOpticalSizing::CSSValueFromComputedStyleInternal(
+ const ComputedStyle& style,
+ const SVGComputedStyle&,
+ const LayoutObject*,
+ bool allow_visited_style) const {
+ return CSSIdentifierValue::Create(
+ style.GetFontDescription().FontOpticalSizing());
+}
+
const CSSValue* FontSizeAdjust::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
@@ -3769,14 +3777,53 @@ const CSSValue* ListStylePosition::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.ListStylePosition());
}
+const CSSValue* ListStyleType::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ // NOTE: All the keyword values for the list-style-type property are handled
+ // by the CSSParserFastPaths.
+ return css_property_parser_helpers::ConsumeString(range);
+}
+
const CSSValue* ListStyleType::CSSValueFromComputedStyleInternal(
const ComputedStyle& style,
const SVGComputedStyle&,
const LayoutObject*,
bool allow_visited_style) const {
+ if (style.ListStyleType() == EListStyleType::kString)
+ return MakeGarbageCollected<CSSStringValue>(style.ListStyleStringValue());
return CSSIdentifierValue::Create(style.ListStyleType());
}
+void ListStyleType::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetListStyleType(
+ ComputedStyleInitialValues::InitialListStyleType());
+ state.Style()->SetListStyleStringValue(
+ ComputedStyleInitialValues::InitialListStyleStringValue());
+}
+
+void ListStyleType::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetListStyleType(state.ParentStyle()->ListStyleType());
+ state.Style()->SetListStyleStringValue(
+ state.ParentStyle()->ListStyleStringValue());
+}
+
+void ListStyleType::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+ state.Style()->SetListStyleType(
+ identifier_value->ConvertTo<EListStyleType>());
+ state.Style()->SetListStyleStringValue(
+ ComputedStyleInitialValues::InitialListStyleStringValue());
+ return;
+ }
+
+ state.Style()->SetListStyleType(EListStyleType::kString);
+ state.Style()->SetListStyleStringValue(
+ AtomicString(To<CSSStringValue>(value).Value()));
+}
+
bool MarginBlockEnd::IsLayoutDependent(const ComputedStyle* style,
LayoutObject* layout_object) const {
return layout_object && layout_object->IsBox();
@@ -5004,12 +5051,9 @@ const CSSValue* Rotate::CSSValueFromComputedStyleInternal(
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
if (style.Rotate()->X() != 0 || style.Rotate()->Y() != 0 ||
style.Rotate()->Z() != 1) {
- list->Append(*CSSNumericLiteralValue::Create(
- style.Rotate()->X(), CSSPrimitiveValue::UnitType::kNumber));
- list->Append(*CSSNumericLiteralValue::Create(
- style.Rotate()->Y(), CSSPrimitiveValue::UnitType::kNumber));
- list->Append(*CSSNumericLiteralValue::Create(
- style.Rotate()->Z(), CSSPrimitiveValue::UnitType::kNumber));
+ const CSSAxisValue* axis = MakeGarbageCollected<CSSAxisValue>(
+ style.Rotate()->X(), style.Rotate()->Y(), style.Rotate()->Z());
+ list->Append(*axis);
}
list->Append(*CSSNumericLiteralValue::Create(
style.Rotate()->Angle(), CSSPrimitiveValue::UnitType::kDegrees));
diff --git a/chromium/third_party/blink/renderer/core/css/property_registration.h b/chromium/third_party/blink/renderer/core/css/property_registration.h
index 25eed14ea32..4562c64397b 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registration.h
+++ b/chromium/third_party/blink/renderer/core/css/property_registration.h
@@ -23,8 +23,8 @@ class StyleRuleProperty;
using CSSInterpolationTypes = Vector<std::unique_ptr<CSSInterpolationType>>;
-class CORE_EXPORT PropertyRegistration
- : public GarbageCollectedFinalized<PropertyRegistration> {
+class CORE_EXPORT PropertyRegistration final
+ : public GarbageCollected<PropertyRegistration> {
public:
static PropertyRegistration* MaybeCreate(Document&,
const AtomicString& name,
diff --git a/chromium/third_party/blink/renderer/core/css/pseudo_style_request.h b/chromium/third_party/blink/renderer/core/css/pseudo_style_request.h
index b61f395529b..29c77e87961 100644
--- a/chromium/third_party/blink/renderer/core/css/pseudo_style_request.h
+++ b/chromium/third_party/blink/renderer/core/css/pseudo_style_request.h
@@ -23,7 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PSEUDO_STYLE_REQUEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PSEUDO_STYLE_REQUEST_H_
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
+#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"
@@ -31,21 +31,21 @@ namespace blink {
class ComputedStyle;
-class PseudoStyleRequest {
+class PseudoElementStyleRequest {
DISALLOW_NEW();
public:
enum RequestType { kForRenderer, kForComputedStyle };
- PseudoStyleRequest(PseudoId pseudo_id,
- LayoutScrollbar* scrollbar = nullptr,
- ScrollbarPart scrollbar_part = kNoPart)
+ PseudoElementStyleRequest(PseudoId pseudo_id,
+ CustomScrollbar* scrollbar = nullptr,
+ ScrollbarPart scrollbar_part = kNoPart)
: pseudo_id(pseudo_id),
type(kForRenderer),
scrollbar_part(scrollbar_part),
scrollbar(scrollbar) {}
- PseudoStyleRequest(PseudoId pseudo_id, RequestType request_type)
+ PseudoElementStyleRequest(PseudoId pseudo_id, RequestType request_type)
: pseudo_id(pseudo_id),
type(request_type),
scrollbar_part(kNoPart),
@@ -61,7 +61,7 @@ class PseudoStyleRequest {
PseudoId pseudo_id;
RequestType type;
ScrollbarPart scrollbar_part;
- Member<LayoutScrollbar> scrollbar;
+ Member<CustomScrollbar> scrollbar;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc b/chromium/third_party/blink/renderer/core/css/remote_font_face_source.cc
index b747901744e..475ea4d21bc 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/css/remote_font_face_source.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/css/css_custom_font_data.h"
@@ -221,7 +222,7 @@ bool RemoteFontFaceSource::ShouldTriggerWebFontsIntervention() {
return false;
WebEffectiveConnectionType connection_type =
- document->GetFrame()->Client()->GetEffectiveConnectionType();
+ GetNetworkStateNotifier().EffectiveType();
bool network_is_slow =
WebEffectiveConnectionType::kTypeOffline <= connection_type &&
@@ -251,8 +252,8 @@ scoped_refptr<SimpleFontData> RemoteFontFaceSource::CreateFontData(
font_description.IsSyntheticBold(),
font_description.IsSyntheticItalic(),
font_description.GetFontSelectionRequest(),
- font_selection_capabilities, font_description.Orientation(),
- font_description.VariationSettings()),
+ font_selection_capabilities, font_description.FontOpticalSizing(),
+ font_description.Orientation(), font_description.VariationSettings()),
CustomFontData::Create());
}
@@ -279,7 +280,7 @@ void RemoteFontFaceSource::BeginLoadIfNeeded() {
return;
DCHECK(GetResource());
- SetDisplay(face_->GetFontFace()->GetFontDisplayWithFallback());
+ SetDisplay(face_->GetFontFace()->GetFontDisplay());
FontResource* font = ToFontResource(GetResource());
if (font->StillNeedsLoad()) {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h b/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
index 9664c0f77ec..a77173acd07 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_property_priority.h
@@ -87,7 +87,7 @@ inline CSSPropertyID CSSPropertyPriorityData<kHighPropertyPriority>::First() {
template <>
inline CSSPropertyID CSSPropertyPriorityData<kHighPropertyPriority>::Last() {
static_assert(static_cast<int>(CSSPropertyID::kZoom) ==
- static_cast<int>(CSSPropertyID::kColor) + 26,
+ static_cast<int>(CSSPropertyID::kColor) + 27,
"CSSPropertyID::kZoom should be the end of the high priority "
"property range");
static_assert(static_cast<int>(CSSPropertyID::kWritingMode) ==
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index eeaca59e931..8325036ac1e 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
@@ -314,7 +314,8 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
mask_layer->GetImage()->IsPendingImage()) {
mask_layer->SetImage(LoadPendingImage(
style, To<StylePendingImage>(mask_layer->GetImage()),
- FetchParameters::kAllowPlaceholder));
+ FetchParameters::kAllowPlaceholder,
+ kCrossOriginAttributeAnonymous));
}
}
break;
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 e46dfec3c15..f71b93bbf59 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
@@ -182,6 +182,12 @@ void FontBuilder::SetKerning(FontDescription::Kerning kerning) {
font_description_.SetKerning(kerning);
}
+void FontBuilder::SetFontOpticalSizing(OpticalSizing font_optical_sizing) {
+ Set(PropertySetFlag::kFontOpticalSizing);
+
+ font_description_.SetFontOpticalSizing(font_optical_sizing);
+}
+
void FontBuilder::SetFontSmoothing(FontSmoothingMode foont_smoothing_mode) {
Set(PropertySetFlag::kFontSmoothing);
@@ -238,7 +244,8 @@ float FontBuilder::GetComputedSizeFromSpecifiedSize(
float specified_size) {
DCHECK(document_);
float zoom_factor = effective_zoom;
- // FIXME: Why is this here!!!!?!
+ // Apply the text zoom factor preference. The preference is exposed in
+ // accessibility settings in Chrome for Android to improve readability.
if (LocalFrame* frame = document_->GetFrame())
zoom_factor *= frame->TextZoomFactor();
@@ -379,6 +386,8 @@ void FontBuilder::UpdateFontDescription(FontDescription& description,
description.SetTextRendering(font_description_.TextRendering());
if (IsSet(PropertySetFlag::kKerning))
description.SetKerning(font_description_.GetKerning());
+ if (IsSet(PropertySetFlag::kFontOpticalSizing))
+ description.SetFontOpticalSizing(font_description_.FontOpticalSizing());
if (IsSet(PropertySetFlag::kFontSmoothing))
description.SetFontSmoothing(font_description_.FontSmoothing());
if (IsSet(PropertySetFlag::kTextOrientation) ||
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/font_builder.h b/chromium/third_party/blink/renderer/core/css/resolver/font_builder.h
index ddb0bb87b02..2021eb1672f 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/font_builder.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/font_builder.h
@@ -72,6 +72,7 @@ class CORE_EXPORT FontBuilder {
void SetVariantNumeric(const FontVariantNumeric&);
void SetTextRendering(TextRenderingMode);
void SetKerning(FontDescription::Kerning);
+ void SetFontOpticalSizing(OpticalSizing);
void SetFontSmoothing(FontSmoothingMode);
void SetVariationSettings(scoped_refptr<FontVariationSettings>);
@@ -114,6 +115,7 @@ class CORE_EXPORT FontBuilder {
static FontDescription::Kerning InitialKerning() {
return FontDescription::kAutoKerning;
}
+ static OpticalSizing InitialFontOpticalSizing() { return kAutoOpticalSizing; }
static FontSmoothingMode InitialFontSmoothing() { return kAutoSmoothing; }
static FontSelectionValue InitialStretch() { return NormalWidthValue(); }
@@ -156,6 +158,7 @@ class CORE_EXPORT FontBuilder {
kVariationSettings,
kTextRendering,
kKerning,
+ kFontOpticalSizing,
kFontSmoothing,
kEffectiveZoom,
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/font_builder_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/font_builder_test.cc
index a5fc0b5ecfa..076628b2578 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/font_builder_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/font_builder_test.cc
@@ -167,6 +167,13 @@ static void FontKerningValue(FontBuilder& b) {
b.SetKerning(FontDescription::kNoneKerning);
}
+static void FontOpticalSizingBase(FontDescription& d) {
+ d.SetFontOpticalSizing(kAutoOpticalSizing);
+}
+static void FontOpticalSizingValue(FontBuilder& b) {
+ b.SetFontOpticalSizing(kNoneOpticalSizing);
+}
+
static void FontFontSmoothingBase(FontDescription& d) {
d.SetFontSmoothing(kAntialiased);
}
@@ -207,6 +214,7 @@ INSTANTIATE_TEST_SUITE_P(
FunctionPair(FontKerningBase, FontKerningValue),
FunctionPair(FontFontSmoothingBase, FontFontSmoothingValue),
FunctionPair(FontSizeBase, FontSizeValue),
- FunctionPair(FontScriptBase, FontScriptValue)));
+ FunctionPair(FontScriptBase, FontScriptValue),
+ FunctionPair(FontOpticalSizingBase, FontOpticalSizingValue)));
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
index 2ee36999abf..a4bff51083e 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
@@ -37,7 +37,7 @@ class ComputedStyle;
class StyleResolverState;
class CachedMatchedProperties final
- : public GarbageCollectedFinalized<CachedMatchedProperties> {
+ : public GarbageCollected<CachedMatchedProperties> {
public:
HeapVector<MatchedProperties> matched_properties;
scoped_refptr<ComputedStyle> computed_style;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
index f953969825d..f27c2171e2c 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -81,9 +81,6 @@ void ScopedStyleResolver::AddFontFaceRules(const RuleSet& rule_set) {
}
if (font_face_rules.size() && document.GetStyleResolver())
document.GetStyleResolver()->InvalidateMatchedPropertiesCache();
-
- for (const auto& rule : rule_set.FontFeatureValuesRules())
- document.GetStyleEngine().AddDefaultFontDisplay(rule);
}
void ScopedStyleResolver::AppendActiveStyleSheets(
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
index 2171a419c8e..51ed87c6892 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
@@ -48,7 +48,7 @@ class StyleSheetContents;
// broken down by what kind of scope they apply to (e.g. shadow host,
// tree-boundary-crossing, etc).
class CORE_EXPORT ScopedStyleResolver final
- : public GarbageCollectedFinalized<ScopedStyleResolver> {
+ : public GarbageCollected<ScopedStyleResolver> {
public:
explicit ScopedStyleResolver(TreeScope& scope) : scope_(scope) {}
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 98a8b47c39b..cac490fef9e 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
@@ -305,10 +305,10 @@ static void AdjustStyleForHTMLElement(ComputedStyle& style,
// See https://drafts.csswg.org/css-display/#unbox-html
// Some of these elements are handled with other adjustments above.
if (IsA<HTMLBRElement>(element) || IsHTMLWBRElement(element) ||
- IsHTMLMeterElement(element) || IsHTMLProgressElement(element) ||
+ IsA<HTMLMeterElement>(element) || IsA<HTMLProgressElement>(element) ||
IsA<HTMLCanvasElement>(element) || IsHTMLMediaElement(element) ||
IsHTMLInputElement(element) || IsHTMLTextAreaElement(element) ||
- IsHTMLSelectElement(element)) {
+ IsA<HTMLSelectElement>(element)) {
style.SetDisplay(EDisplay::kNone);
}
}
@@ -417,8 +417,7 @@ static void AdjustStyleForDisplay(ComputedStyle& style,
// setting of block-flow to anything other than TopToBottomWritingMode.
// https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
if (style.GetWritingMode() != WritingMode::kHorizontalTb &&
- (style.Display() == EDisplay::kWebkitBox ||
- style.Display() == EDisplay::kWebkitInlineBox)) {
+ style.IsDeprecatedWebkitBox()) {
style.SetWritingMode(WritingMode::kHorizontalTb);
style.UpdateFontOrientation();
}
@@ -567,7 +566,9 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
AdjustStyleForFirstLetter(style);
}
- if (element && RuntimeEnabledFeatures::DisplayLockingEnabled() &&
+ if (element &&
+ RuntimeEnabledFeatures::DisplayLockingEnabled(
+ element->GetExecutionContext()) &&
element->hasAttribute(html_names::kRendersubtreeAttr)) {
// The element has the rendersubtree attr, so we should add style and
// layout containment. If the attribute contains "invisible" we should
@@ -584,7 +585,7 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
}
if (style.IsColorInternalText()) {
- style.SetColor(
+ style.ResolveInternalTextColor(
LayoutTheme::GetTheme().RootElementColor(style.UsedColorScheme()));
}
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 07ed34f59d6..9eeed1dd6f6 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
@@ -751,6 +751,14 @@ scoped_refptr<ComputedStyle> StyleResolver::StyleForElement(
: ComputedStyle::kNotAtShadowBoundary);
state.SetStyle(std::move(style));
} else {
+ // Strictly, we should only allow the root element to inherit from initial
+ // styles, but we allow getComputedStyle() for connected elements outside
+ // the flat tree rooted at an unassigned shadow host child, or Shadow DOM
+ // V0 insertion points.
+ DCHECK(element == GetDocument().documentElement() ||
+ element->IsV0InsertionPoint() ||
+ (IsShadowHost(element->parentNode()) &&
+ !LayoutTreeBuilderTraversal::ParentElement(*element)));
state.SetStyle(InitialStyleForElement(GetDocument()));
state.SetParentStyle(ComputedStyle::Clone(*state.Style()));
state.SetLayoutParentStyle(state.ParentStyle());
@@ -894,7 +902,7 @@ CompositorKeyframeValue* StyleResolver::CreateCompositorKeyframeValueSnapshot(
bool StyleResolver::PseudoStyleForElementInternal(
Element& element,
- const PseudoStyleRequest& pseudo_style_request,
+ const PseudoElementStyleRequest& pseudo_style_request,
StyleResolverState& state) {
DCHECK(GetDocument().GetFrame());
DCHECK(GetDocument().GetSettings());
@@ -913,6 +921,10 @@ bool StyleResolver::PseudoStyleForElementInternal(
style->InheritFrom(*state.ParentStyle());
state.SetStyle(std::move(style));
} else {
+ // ::backdrop inherits from initial styles. All other pseudo elements
+ // inherit from their originating element (::before/::after), or originating
+ // element descendants (::first-line/::first-letter).
+ DCHECK(pseudo_style_request.pseudo_id == kPseudoIdBackdrop);
state.SetStyle(InitialStyleForElement(GetDocument()));
state.SetParentStyle(ComputedStyle::Clone(*state.Style()));
}
@@ -926,7 +938,7 @@ bool StyleResolver::PseudoStyleForElementInternal(
// Check UA, user and author rules.
ElementRuleCollector collector(state.ElementContext(), selector_filter_,
state.Style());
- collector.SetPseudoStyleRequest(pseudo_style_request);
+ collector.SetPseudoElementStyleRequest(pseudo_style_request);
MatchUARules(collector);
MatchUserRules(collector);
@@ -971,7 +983,7 @@ bool StyleResolver::PseudoStyleForElementInternal(
scoped_refptr<ComputedStyle> StyleResolver::PseudoStyleForElement(
Element* element,
- const PseudoStyleRequest& pseudo_style_request,
+ const PseudoElementStyleRequest& pseudo_style_request,
const ComputedStyle* parent_style,
const ComputedStyle* parent_layout_object_style) {
DCHECK(parent_style);
@@ -982,7 +994,7 @@ scoped_refptr<ComputedStyle> StyleResolver::PseudoStyleForElement(
pseudo_style_request.pseudo_id, parent_style,
parent_layout_object_style);
if (!PseudoStyleForElementInternal(*element, pseudo_style_request, state)) {
- if (pseudo_style_request.type == PseudoStyleRequest::kForRenderer)
+ if (pseudo_style_request.type == PseudoElementStyleRequest::kForRenderer)
return nullptr;
return state.TakeStyle();
}
@@ -1136,7 +1148,7 @@ void StyleResolver::CollectPseudoRulesForElement(
ElementRuleCollector& collector,
PseudoId pseudo_id,
unsigned rules_to_include) {
- collector.SetPseudoStyleRequest(PseudoStyleRequest(pseudo_id));
+ collector.SetPseudoElementStyleRequest(PseudoElementStyleRequest(pseudo_id));
if (rules_to_include & kUAAndUserCSSRules) {
MatchUARules(collector);
@@ -1390,6 +1402,7 @@ static inline bool IsValidFirstLetterStyleProperty(CSSPropertyID id) {
case CSSPropertyID::kFontFamily:
case CSSPropertyID::kFontFeatureSettings:
case CSSPropertyID::kFontKerning:
+ case CSSPropertyID::kFontOpticalSizing:
case CSSPropertyID::kFontSize:
case CSSPropertyID::kFontSizeAdjust:
case CSSPropertyID::kFontStretch:
@@ -1687,6 +1700,8 @@ void StyleResolver::ApplyForcedColors(StyleResolverState& state,
// https://drafts.csswg.org/css-color-adjust-1/#forced-colors-properties
if (priority == kHighPropertyPriority) {
ApplyProperty(GetCSSPropertyColor(), state, *unset, apply_mask);
+ ApplyUaForcedColors<priority>(state, match_result, apply_inherited_only,
+ needs_apply_pass);
} else {
DCHECK(priority == kLowPropertyPriority);
ApplyProperty(GetCSSPropertyBorderBottomColor(), state, *unset, apply_mask);
@@ -1708,18 +1723,31 @@ void StyleResolver::ApplyForcedColors(StyleResolverState& state,
// Background colors compute to the Window system color for all values
// except for the alpha channel.
+ RGBA32 prev_bg_color = state.Style()->BackgroundColor().GetColor().Rgb();
RGBA32 sys_bg_color =
LayoutTheme::GetTheme()
.SystemColor(CSSValueID::kWindow, WebColorScheme::kLight)
.Rgb();
+ ApplyProperty(GetCSSPropertyBackgroundColor(), state,
+ *cssvalue::CSSColorValue::Create(sys_bg_color), apply_mask);
+
+ ApplyUaForcedColors<priority>(state, match_result, apply_inherited_only,
+ needs_apply_pass);
+
RGBA32 current_bg_color = state.Style()->BackgroundColor().GetColor().Rgb();
RGBA32 bg_color =
- MakeRGBA(RedChannel(sys_bg_color), GreenChannel(sys_bg_color),
- BlueChannel(sys_bg_color), AlphaChannel(current_bg_color));
+ MakeRGBA(RedChannel(current_bg_color), GreenChannel(current_bg_color),
+ BlueChannel(current_bg_color), AlphaChannel(prev_bg_color));
ApplyProperty(GetCSSPropertyBackgroundColor(), state,
*cssvalue::CSSColorValue::Create(bg_color), apply_mask);
}
+}
+template <CSSPropertyPriority priority>
+void StyleResolver::ApplyUaForcedColors(StyleResolverState& state,
+ const MatchResult& match_result,
+ bool apply_inherited_only,
+ NeedsApplyPass& needs_apply_pass) {
auto force_colors = ForcedColorFilter::kEnabled;
ApplyMatchedProperties<priority, kCheckNeedsApplyPass>(
state, match_result.UaRules(), false, apply_inherited_only,
@@ -2327,6 +2355,9 @@ void StyleResolver::ApplyCascadedColorValue(StyleResolverState& state) {
case CSSValueID::kInitial:
state.Style()->SetColor(ComputedStyleInitialValues::InitialColor());
break;
+ case CSSValueID::kInternalRootColor:
+ state.Style()->SetIsColorInternalText(true);
+ break;
default:
identifier_value = nullptr;
break;
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 d07981e46dc..452b8a7568b 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
@@ -60,9 +60,7 @@ enum ApplyMask { kApplyMaskRegular = 1 << 0, kApplyMaskVisited = 1 << 1 };
// This class selects a ComputedStyle for a given element in a document based on
// the document's collection of stylesheets (user styles, author styles, UA
// style). There is a 1-1 relationship of StyleResolver and Document.
-class CORE_EXPORT StyleResolver final
- : public GarbageCollectedFinalized<StyleResolver> {
-
+class CORE_EXPORT StyleResolver final : public GarbageCollected<StyleResolver> {
public:
explicit StyleResolver(Document&);
~StyleResolver();
@@ -85,7 +83,7 @@ class CORE_EXPORT StyleResolver final
scoped_refptr<ComputedStyle> PseudoStyleForElement(
Element*,
- const PseudoStyleRequest&,
+ const PseudoElementStyleRequest&,
const ComputedStyle* parent_style,
const ComputedStyle* layout_parent_style);
@@ -247,6 +245,11 @@ class CORE_EXPORT StyleResolver final
const MatchResult& match_result,
bool apply_inherited_only,
NeedsApplyPass& needs_apply_pass);
+ template <CSSPropertyPriority priority>
+ void ApplyUaForcedColors(StyleResolverState& state,
+ const MatchResult& match_result,
+ bool apply_inherited_only,
+ NeedsApplyPass& needs_apply_pass);
void CascadeAndApplyMatchedProperties(StyleResolverState&,
const MatchResult&);
@@ -300,7 +303,7 @@ class CORE_EXPORT StyleResolver final
void ApplyCascadedColorValue(StyleResolverState&);
bool PseudoStyleForElementInternal(Element&,
- const PseudoStyleRequest&,
+ const PseudoElementStyleRequest&,
StyleResolverState&);
bool HasAuthorBorder(const StyleResolverState&);
@@ -318,6 +321,8 @@ class CORE_EXPORT StyleResolver final
bool print_media_type_ = false;
bool was_viewport_resized_ = false;
DISALLOW_COPY_AND_ASSIGN(StyleResolver);
+
+ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, ApplyInternalLightDarkColor);
};
} // namespace blink
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 e5dea3bc890..a79ba7df190 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
@@ -320,7 +320,7 @@ Length ViewportStyleResolver::ViewportLengthValue(CSSPropertyID id) {
if (result.IsFixed() && document_->GetPage()) {
float scaled_value =
document_->GetPage()->GetChromeClient().WindowToViewportScalar(
- result.GetFloatValue());
+ document_->GetFrame(), result.GetFloatValue());
result = Length::Fixed(scaled_value);
}
return result;
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
index db90ffdf990..f4c771b1058 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
@@ -44,8 +44,8 @@ class DocumentStyleSheetCollection;
class MutableCSSPropertyValueSet;
class StyleRuleViewport;
-class CORE_EXPORT ViewportStyleResolver
- : public GarbageCollectedFinalized<ViewportStyleResolver> {
+class CORE_EXPORT ViewportStyleResolver final
+ : public GarbageCollected<ViewportStyleResolver> {
public:
explicit ViewportStyleResolver(Document&);
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 0de92743f9a..38bd45be530 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
@@ -89,6 +89,7 @@ bool SupportsInvalidation(CSSSelector::PseudoType type) {
case CSSSelector::kPseudoNthLastChild:
case CSSSelector::kPseudoNthLastOfType:
case CSSSelector::kPseudoPart:
+ case CSSSelector::kPseudoState:
case CSSSelector::kPseudoLink:
case CSSSelector::kPseudoVisited:
case CSSSelector::kPseudoAny:
@@ -168,6 +169,7 @@ bool SupportsInvalidation(CSSSelector::PseudoType type) {
case CSSSelector::kPseudoSlotted:
case CSSSelector::kPseudoVideoPersistent:
case CSSSelector::kPseudoVideoPersistentAncestor:
+ case CSSSelector::kPseudoXrImmersiveDomOverlay:
return true;
case CSSSelector::kPseudoIs:
case CSSSelector::kPseudoWhere:
@@ -533,6 +535,7 @@ InvalidationSet* RuleFeatureSet::InvalidationSetForSimpleSelector(
case CSSSelector::kPseudoRequired:
case CSSSelector::kPseudoReadOnly:
case CSSSelector::kPseudoReadWrite:
+ case CSSSelector::kPseudoState:
case CSSSelector::kPseudoValid:
case CSSSelector::kPseudoInvalid:
case CSSSelector::kPseudoIndeterminate:
@@ -548,6 +551,7 @@ InvalidationSet* RuleFeatureSet::InvalidationSetForSimpleSelector(
case CSSSelector::kPseudoDefined:
case CSSSelector::kPseudoVideoPersistent:
case CSSSelector::kPseudoVideoPersistentAncestor:
+ case CSSSelector::kPseudoXrImmersiveDomOverlay:
case CSSSelector::kPseudoSpatialNavigationInterest:
return &EnsurePseudoInvalidationSet(selector.GetPseudoType(), type,
position);
diff --git a/chromium/third_party/blink/renderer/core/css/rule_set.cc b/chromium/third_party/blink/renderer/core/css/rule_set.cc
index b619bd7dfdc..6224f84bf0b 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_set.cc
+++ b/chromium/third_party/blink/renderer/core/css/rule_set.cc
@@ -275,11 +275,6 @@ void RuleSet::AddFontFaceRule(StyleRuleFontFace* rule) {
font_face_rules_.push_back(rule);
}
-void RuleSet::AddFontFeatureValuesRule(StyleRuleFontFeatureValues* rule) {
- EnsurePendingRules();
- font_feature_values_rules_.push_back(rule);
-}
-
void RuleSet::AddKeyframesRule(StyleRuleKeyframes* rule) {
EnsurePendingRules(); // So that keyframes_rules_.ShrinkToFit() gets called.
keyframes_rules_.push_back(rule);
@@ -324,9 +319,6 @@ void RuleSet::AddChildRules(const HeapVector<Member<StyleRuleBase>>& rules,
AddChildRules(media_rule->ChildRules(), medium, add_rule_flags);
} else if (auto* font_face_rule = DynamicTo<StyleRuleFontFace>(rule)) {
AddFontFaceRule(font_face_rule);
- } else if (auto* font_feature_values_rule =
- DynamicTo<StyleRuleFontFeatureValues>(rule)) {
- AddFontFeatureValuesRule(font_feature_values_rule);
} else if (auto* keyframes_rule = DynamicTo<StyleRuleKeyframes>(rule)) {
AddKeyframesRule(keyframes_rule);
} else if (auto* property_rule = DynamicTo<StyleRuleProperty>(rule)) {
@@ -405,7 +397,6 @@ void RuleSet::CompactRules() {
shadow_host_rules_.ShrinkToFit();
page_rules_.ShrinkToFit();
font_face_rules_.ShrinkToFit();
- font_feature_values_rules_.ShrinkToFit();
keyframes_rules_.ShrinkToFit();
property_rules_.ShrinkToFit();
deep_combinator_or_shadow_pseudo_rules_.ShrinkToFit();
@@ -442,7 +433,6 @@ void RuleSet::Trace(blink::Visitor* visitor) {
visitor->Trace(shadow_host_rules_);
visitor->Trace(page_rules_);
visitor->Trace(font_face_rules_);
- visitor->Trace(font_feature_values_rules_);
visitor->Trace(keyframes_rules_);
visitor->Trace(property_rules_);
visitor->Trace(deep_combinator_or_shadow_pseudo_rules_);
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 6776c98aca8..ab1531ecb7c 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_set.h
+++ b/chromium/third_party/blink/renderer/core/css/rule_set.h
@@ -175,7 +175,7 @@ static_assert(sizeof(RuleData) == sizeof(SameSizeAsRuleData),
// specific group are appended to the "universal" rules. The grouping is done to
// optimize finding what rules apply to an element under consideration by
// ElementRuleCollector::CollectMatchingRules.
-class CORE_EXPORT RuleSet : public GarbageCollectedFinalized<RuleSet> {
+class CORE_EXPORT RuleSet final : public GarbageCollected<RuleSet> {
public:
RuleSet() : rule_count_(0) {}
@@ -243,10 +243,6 @@ class CORE_EXPORT RuleSet : public GarbageCollectedFinalized<RuleSet> {
const HeapVector<Member<StyleRuleFontFace>>& FontFaceRules() const {
return font_face_rules_;
}
- const HeapVector<Member<StyleRuleFontFeatureValues>>& FontFeatureValuesRules()
- const {
- return font_feature_values_rules_;
- }
const HeapVector<Member<StyleRuleKeyframes>>& KeyframesRules() const {
return keyframes_rules_;
}
@@ -302,7 +298,6 @@ class CORE_EXPORT RuleSet : public GarbageCollectedFinalized<RuleSet> {
void AddPageRule(StyleRulePage*);
void AddViewportRule(StyleRuleViewport*);
void AddFontFaceRule(StyleRuleFontFace*);
- void AddFontFeatureValuesRule(StyleRuleFontFeatureValues*);
void AddKeyframesRule(StyleRuleKeyframes*);
void AddPropertyRule(StyleRuleProperty*);
@@ -346,7 +341,6 @@ class CORE_EXPORT RuleSet : public GarbageCollectedFinalized<RuleSet> {
RuleFeatureSet features_;
HeapVector<Member<StyleRulePage>> page_rules_;
HeapVector<Member<StyleRuleFontFace>> font_face_rules_;
- HeapVector<Member<StyleRuleFontFeatureValues>> font_feature_values_rules_;
HeapVector<Member<StyleRuleKeyframes>> keyframes_rules_;
HeapVector<Member<StyleRuleProperty>> property_rules_;
HeapVector<MinimalRuleData> deep_combinator_or_shadow_pseudo_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 f2cac1495f1..5e2ec4ba562 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.cc
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
@@ -77,14 +78,14 @@ static bool IsFrameFocused(const Element& element) {
}
static bool MatchesSpatialNavigationFocusPseudoClass(const Element& element) {
- return IsHTMLOptionElement(element) &&
- ToHTMLOptionElement(element).SpatialNavigationFocused() &&
+ auto* option_element = DynamicTo<HTMLOptionElement>(element);
+ return option_element && option_element->SpatialNavigationFocused() &&
IsFrameFocused(element);
}
static bool MatchesListBoxPseudoClass(const Element& element) {
- return IsHTMLSelectElement(element) &&
- !ToHTMLSelectElement(element).UsesMenuList();
+ auto* html_select_element = DynamicTo<HTMLSelectElement>(element);
+ return html_select_element && !html_select_element->UsesMenuList();
}
static bool MatchesTagName(const Element& element,
@@ -1007,9 +1008,10 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
if (input_element->ShouldAppearChecked() &&
!input_element->ShouldAppearIndeterminate())
return true;
- } else if (IsHTMLOptionElement(element) &&
- ToHTMLOptionElement(element).Selected()) {
- return true;
+ } else if (auto* option_element = DynamicTo<HTMLOptionElement>(element)) {
+ if (option_element->Selected()) {
+ return true;
+ }
}
break;
}
@@ -1045,6 +1047,11 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
case CSSSelector::kPseudoVideoPersistentAncestor:
DCHECK(is_ua_rule_);
return element.ContainsPersistentVideo();
+ case CSSSelector::kPseudoXrImmersiveDomOverlay:
+ DCHECK(is_ua_rule_);
+ // In immersive AR overlay mode, apply a pseudostyle to the root element.
+ return element.GetDocument().IsImmersiveArOverlay() &&
+ element == element.GetDocument().documentElement();
case CSSSelector::kPseudoInRange:
return element.IsInRange();
case CSSSelector::kPseudoOutOfRange:
@@ -1103,6 +1110,10 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
if (!context.has_selection_pseudo)
return false;
return !element.GetDocument().GetPage()->GetFocusController().IsActive();
+ case CSSSelector::kPseudoState: {
+ return element.DidAttachInternals() &&
+ element.EnsureElementInternals().HasState(selector.Argument());
+ }
case CSSSelector::kPseudoHorizontal:
case CSSSelector::kPseudoVertical:
case CSSSelector::kPseudoDecrement:
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 9137fe524e8..e89b0fc2437 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.h
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.h
@@ -39,9 +39,9 @@ namespace blink {
class CSSSelector;
class ContainerNode;
-class Element;
-class LayoutScrollbar;
+class CustomScrollbar;
class ComputedStyle;
+class Element;
class PartNames;
class SelectorChecker {
@@ -83,7 +83,7 @@ class SelectorChecker {
Mode mode = kResolvingStyle;
bool is_ua_rule = false;
ComputedStyle* element_style = nullptr;
- Member<LayoutScrollbar> scrollbar = nullptr;
+ Member<CustomScrollbar> scrollbar = nullptr;
ScrollbarPart scrollbar_part = kNoPart;
PartNames* part_names = nullptr;
};
@@ -206,7 +206,7 @@ class SelectorChecker {
Mode mode_;
bool is_ua_rule_;
ComputedStyle* element_style_;
- Member<LayoutScrollbar> scrollbar_;
+ Member<CustomScrollbar> scrollbar_;
ScrollbarPart scrollbar_part_;
PartNames* part_names_;
DISALLOW_COPY_AND_ASSIGN(SelectorChecker);
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 e31b232f659..19fd2ee27bd 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.cc
@@ -39,6 +39,8 @@
#include "third_party/blink/renderer/core/css/document_style_sheet_collector.h"
#include "third_party/blink/renderer/core/css/font_face_cache.h"
#include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
+#include "third_party/blink/renderer/core/css/media_feature_overrides.h"
+#include "third_party/blink/renderer/core/css/media_values.h"
#include "third_party/blink/renderer/core/css/property_registration.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h"
@@ -55,10 +57,13 @@
#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/dom/nth_index_cache.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.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/frame/settings.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_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
@@ -67,6 +72,7 @@
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/style_initial_data.h"
@@ -74,6 +80,7 @@
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -94,12 +101,8 @@ StyleEngine::StyleEngine(Document& document)
viewport_resolver_ = MakeGarbageCollected<ViewportStyleResolver>(document);
if (IsMaster())
global_rule_set_ = MakeGarbageCollected<CSSGlobalRuleSet>();
- // Document is initially style dirty.
- style_recalc_root_.Update(nullptr, &document);
- if (auto* settings = GetDocument().GetSettings()) {
+ if (auto* settings = GetDocument().GetSettings())
preferred_color_scheme_ = settings->GetPreferredColorScheme();
- forced_colors_ = settings->GetForcedColors();
- }
}
StyleEngine::~StyleEngine() = default;
@@ -389,12 +392,48 @@ void StyleEngine::MediaQueryAffectingValueChanged(
}
}
+void StyleEngine::AddTextTrack(TextTrack* text_track) {
+ text_tracks_.insert(text_track);
+}
+
+void StyleEngine::RemoveTextTrack(TextTrack* text_track) {
+ text_tracks_.erase(text_track);
+}
+
+void StyleEngine::MediaQueryAffectingValueChanged(
+ HeapHashSet<Member<TextTrack>>& text_tracks) {
+ if (text_tracks.IsEmpty())
+ return;
+
+ for (auto text_track : text_tracks) {
+ bool style_needs_recalc = false;
+ auto style_sheets = text_track->GetCSSStyleSheets();
+ for (const auto& sheet : style_sheets) {
+ StyleSheetContents* contents = sheet->Contents();
+ if (contents->HasMediaQueries()) {
+ style_needs_recalc = true;
+ contents->ClearRuleSet();
+ }
+ }
+
+ if (style_needs_recalc) {
+ // Use kSubtreeTreeStyleChange instead of RuleSet style invalidation
+ // because it won't be expensive for tracks and we won't have dynamic
+ // changes.
+ text_track->Owner()->SetNeedsStyleRecalc(
+ kSubtreeStyleChange,
+ StyleChangeReasonForTracing::Create(style_change_reason::kShadow));
+ }
+ }
+}
+
void StyleEngine::MediaQueryAffectingValueChanged() {
if (ClearMediaQueryDependentRuleSets(active_user_style_sheets_))
MarkUserStyleDirty();
if (GetDocumentStyleSheetCollection().MediaQueryAffectingValueChanged())
SetNeedsActiveStyleUpdate(GetDocument());
MediaQueryAffectingValueChanged(active_tree_scopes_);
+ MediaQueryAffectingValueChanged(text_tracks_);
if (resolver_)
resolver_->UpdateMediaType();
}
@@ -634,39 +673,13 @@ void StyleEngine::ClearFontCacheAndAddUserFonts() {
resolver_->InvalidateMatchedPropertiesCache();
}
- default_font_display_map_.clear();
// Rebuild the font cache with @font-face rules from user style sheets.
for (unsigned i = 0; i < active_user_style_sheets_.size(); ++i) {
DCHECK(active_user_style_sheets_[i].second);
AddUserFontFaceRules(*active_user_style_sheets_[i].second);
- for (const auto& rule :
- active_user_style_sheets_[i].second->FontFeatureValuesRules()) {
- AddDefaultFontDisplay(rule);
- }
}
}
-void StyleEngine::AddDefaultFontDisplay(
- const StyleRuleFontFeatureValues* rule) {
- if (!rule->FontDisplay())
- return;
- for (const auto& family_value : rule->FontFamily()) {
- if (auto* font_family_value =
- DynamicTo<CSSFontFamilyValue>(family_value.Get())) {
- default_font_display_map_.Set(AtomicString(font_family_value->Value()),
- CSSValueToFontDisplay(rule->FontDisplay()));
- }
- }
-}
-
-FontDisplay StyleEngine::GetDefaultFontDisplay(
- const AtomicString& family) const {
- auto it = default_font_display_map_.find(family);
- if (it == default_font_display_map_.end())
- return kFontDisplayAuto;
- return it->value;
-}
-
void StyleEngine::UpdateGenericFontFamilySettings() {
// FIXME: we should not update generic font family settings when
// document is inactive.
@@ -1219,8 +1232,9 @@ void StyleEngine::ScheduleInvalidationsForRuleSets(
Element* element = ElementTraversal::FirstChild(*stay_within);
while (element) {
ScheduleRuleSetInvalidationsForElement(*element, rule_sets);
- if (invalidate_slotted && IsHTMLSlotElement(element))
- InvalidateSlottedElements(ToHTMLSlotElement(*element));
+ auto* html_slot_element = DynamicTo<HTMLSlotElement>(element);
+ if (html_slot_element && invalidate_slotted)
+ InvalidateSlottedElements(*html_slot_element);
if (invalidation_scope == kInvalidateAllScopes) {
if (ShadowRoot* shadow_root = element->GetShadowRoot()) {
@@ -1348,9 +1362,7 @@ enum RuleSetFlags {
kFontFaceRules = 1 << 0,
kKeyframesRules = 1 << 1,
kFullRecalcRules = 1 << 2,
- kFontFeatureValuesRules = 1 << 3,
- kFontRules = kFontFaceRules | kFontFeatureValuesRules,
- kPropertyRules = 1 << 4
+ kPropertyRules = 1 << 3,
};
unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
@@ -1363,8 +1375,6 @@ unsigned GetRuleSetFlags(const HeapHashSet<Member<RuleSet>> rule_sets) {
flags |= kFontFaceRules;
if (rule_set->NeedsFullRecalcForRuleSetInvalidation())
flags |= kFullRecalcRules;
- if (!rule_set->FontFeatureValuesRules().IsEmpty())
- flags |= kFontFeatureValuesRules;
if (!rule_set->PropertyRules().IsEmpty())
flags |= kPropertyRules;
}
@@ -1425,7 +1435,7 @@ void StyleEngine::ApplyUserRuleSetChanges(
global_rule_set_->MarkDirty();
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
- if (changed_rule_flags & kFontRules) {
+ if (changed_rule_flags & kFontFaceRules) {
if (ScopedStyleResolver* scoped_resolver =
GetDocument().GetScopedStyleResolver()) {
// User style and document scope author style shares the font cache. If
@@ -1469,7 +1479,7 @@ void StyleEngine::ApplyRuleSetChanges(
unsigned changed_rule_flags = GetRuleSetFlags(changed_rule_sets);
bool rebuild_font_cache = change == kActiveSheetsChanged &&
- (changed_rule_flags & kFontRules) &&
+ (changed_rule_flags & kFontFaceRules) &&
tree_scope.RootNode().IsDocumentNode();
ScopedStyleResolver* scoped_resolver = tree_scope.GetScopedStyleResolver();
if (scoped_resolver && scoped_resolver->NeedsAppendAllSheets()) {
@@ -1609,8 +1619,8 @@ void StyleEngine::MarkForWhitespaceReattachment() {
*element);
continue;
}
- DCHECK(!element->NeedsStyleRecalc());
- DCHECK(!element->ChildNeedsStyleRecalc());
+ DCHECK(!element->NeedsStyleRecalc());
+ DCHECK(!element->ChildNeedsStyleRecalc());
if (Node* first_child = LayoutTreeBuilderTraversal::FirstChild(*element))
first_child->MarkAncestorsWithChildNeedsReattachLayoutTree();
}
@@ -1774,13 +1784,14 @@ void StyleEngine::RecalcStyle() {
SelectorFilterRootScope filter_scope(parent);
root_element->RecalcStyle({});
- for (ContainerNode* ancestor = root_element->ParentOrShadowHostNode();
- ancestor; ancestor = ancestor->ParentOrShadowHostNode()) {
+ for (ContainerNode* ancestor = root_element->GetStyleRecalcParent(); ancestor;
+ ancestor = ancestor->GetStyleRecalcParent()) {
if (auto* ancestor_element = DynamicTo<Element>(ancestor))
ancestor_element->RecalcStyleForTraversalRootAncestor();
ancestor->ClearChildNeedsStyleRecalc();
}
style_recalc_root_.Clear();
+ PropagateWritingModeAndDirectionToHTMLRoot();
}
void StyleEngine::RebuildLayoutTree() {
@@ -1809,6 +1820,67 @@ void StyleEngine::RebuildLayoutTree() {
in_layout_tree_rebuild_ = false;
}
+void StyleEngine::UpdateStyleAndLayoutTree() {
+ // All of layout tree dirtiness and rebuilding needs to happen on a stable
+ // flat tree. We have an invariant that all of that happens in this method
+ // as a result of style recalc and the following layout tree rebuild.
+ //
+ // NeedsReattachLayoutTree() marks dirty up the flat tree ancestors. Re-
+ // slotting on a dirty tree could break ancestor chains and fail to update the
+ // tree properly.
+ DCHECK(!NeedsLayoutTreeRebuild());
+
+ UpdateViewportStyle();
+
+ if (Element* document_element = GetDocument().documentElement()) {
+ NthIndexCache nth_index_cache(GetDocument());
+ if (NeedsStyleRecalc()) {
+ TRACE_EVENT0("blink,blink_style", "Document::recalcStyle");
+ SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RecalcTime");
+ Element* viewport_defining = GetDocument().ViewportDefiningElement();
+ RecalcStyle();
+ if (viewport_defining != GetDocument().ViewportDefiningElement())
+ ViewportDefiningElementDidChange();
+ }
+ MarkForWhitespaceReattachment();
+ if (NeedsLayoutTreeRebuild()) {
+ TRACE_EVENT0("blink,blink_style", "Document::rebuildLayoutTree");
+ SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RebuildLayoutTreeTime");
+ RebuildLayoutTree();
+ }
+ } else {
+ style_recalc_root_.Clear();
+ }
+ ClearWhitespaceReattachSet();
+ UpdateColorSchemeBackground();
+}
+
+void StyleEngine::ViewportDefiningElementDidChange() {
+ HTMLBodyElement* body = GetDocument().FirstBodyElement();
+ if (!body || body->NeedsReattachLayoutTree())
+ return;
+ LayoutObject* layout_object = body->GetLayoutObject();
+ if (layout_object && layout_object->IsLayoutBlock()) {
+ // When the overflow style for documentElement changes to or from visible,
+ // it changes whether the body element's box should have scrollable overflow
+ // on its own box or propagated to the viewport. If the body style did not
+ // need a recalc, this will not be updated as its done as part of setting
+ // ComputedStyle on the LayoutObject. Force a SetStyle for body when the
+ // ViewportDefiningElement changes in order to trigger an update of
+ // HasOverflowClip() and the PaintLayer in StyleDidChange().
+ layout_object->SetStyle(ComputedStyle::Clone(*layout_object->Style()));
+ // CompositingReason::kClipsCompositingDescendants depends on the root
+ // element having a clip-related style. Since style update due to changes of
+ // viewport-defining element don't end up as a StyleDifference, we need a
+ // special dirty bit for this situation.
+ if (layout_object->HasLayer()) {
+ ToLayoutBoxModelObject(layout_object)
+ ->Layer()
+ ->SetNeedsCompositingReasonsUpdate();
+ }
+ }
+}
+
void StyleEngine::UpdateStyleInvalidationRoot(ContainerNode* ancestor,
Node* dirty_node) {
DCHECK(IsMaster());
@@ -1856,13 +1928,17 @@ bool StyleEngine::SupportsDarkColorScheme() {
void StyleEngine::UpdateColorScheme() {
auto* settings = GetDocument().GetSettings();
- DCHECK(settings);
-
- ForcedColors old_forced_colors = forced_colors_;
- forced_colors_ = settings->GetForcedColors();
+ if (!settings)
+ return;
PreferredColorScheme old_preferred_color_scheme = preferred_color_scheme_;
preferred_color_scheme_ = settings->GetPreferredColorScheme();
+ if (const auto* overrides =
+ GetDocument().GetPage()->GetMediaFeatureOverrides()) {
+ MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme");
+ if (value.IsValid())
+ preferred_color_scheme_ = CSSValueIDToPreferredColorScheme(value.id);
+ }
bool use_dark_scheme =
preferred_color_scheme_ == PreferredColorScheme::kDark &&
SupportsDarkColorScheme();
@@ -1872,8 +1948,7 @@ void StyleEngine::UpdateColorScheme() {
preferred_color_scheme_ = PreferredColorScheme::kNoPreference;
}
- if (forced_colors_ != old_forced_colors ||
- preferred_color_scheme_ != old_preferred_color_scheme)
+ if (preferred_color_scheme_ != old_preferred_color_scheme)
PlatformColorsChanged();
UpdateColorSchemeBackground();
}
@@ -1899,7 +1974,7 @@ void StyleEngine::UpdateColorSchemeBackground() {
bool use_dark_background = false;
if (preferred_color_scheme_ == PreferredColorScheme::kDark &&
- forced_colors_ != ForcedColors::kActive) {
+ !GetDocument().InForcedColorsMode()) {
const ComputedStyle* style = nullptr;
if (auto* root_element = GetDocument().documentElement())
style = root_element->GetComputedStyle();
@@ -1941,6 +2016,17 @@ void StyleEngine::UpdateViewportStyle() {
}
}
+bool StyleEngine::NeedsFullStyleUpdate() const {
+ return NeedsActiveStyleUpdate() || NeedsWhitespaceReattachment() ||
+ IsViewportStyleDirty();
+}
+
+void StyleEngine::PropagateWritingModeAndDirectionToHTMLRoot() {
+ if (HTMLHtmlElement* root_element =
+ DynamicTo<HTMLHtmlElement>(GetDocument().documentElement()))
+ root_element->PropagateWritingModeAndDirectionFromBody();
+}
+
void StyleEngine::Trace(blink::Visitor* visitor) {
visitor->Trace(document_);
visitor->Trace(injected_user_style_sheets_);
@@ -1968,6 +2054,7 @@ void StyleEngine::Trace(blink::Visitor* visitor) {
visitor->Trace(sheet_to_text_cache_);
visitor->Trace(tracker_);
visitor->Trace(meta_color_scheme_);
+ visitor->Trace(text_tracks_);
FontSelectorClient::Trace(visitor);
}
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 ba452844b2a..bbca1d35770 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.h
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.h
@@ -33,14 +33,12 @@
#include <memory>
#include <utility>
#include "base/auto_reset.h"
-#include "third_party/blink/public/common/css/forced_colors.h"
#include "third_party/blink/public/common/css/preferred_color_scheme.h"
#include "third_party/blink/public/web/web_document.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"
#include "third_party/blink/renderer/core/css/document_style_sheet_collection.h"
-#include "third_party/blink/renderer/core/css/font_display.h"
#include "third_party/blink/renderer/core/css/invalidation/pending_invalidations.h"
#include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
#include "third_party/blink/renderer/core/css/layout_tree_rebuild_root.h"
@@ -51,6 +49,7 @@
#include "third_party/blink/renderer/core/css/style_recalc_root.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/tree_ordered_list.h"
+#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -81,10 +80,9 @@ using StyleSheetKey = AtomicString;
// The StyleEngine class manages style-related state for the document. There is
// a 1-1 relationship of Document to StyleEngine. The document calls the
// StyleEngine when the the document is updated in a way that impacts styles.
-class CORE_EXPORT StyleEngine final
- : public GarbageCollectedFinalized<StyleEngine>,
- public FontSelectorClient,
- public NameClient {
+class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
+ public FontSelectorClient,
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(StyleEngine);
public:
@@ -113,6 +111,9 @@ class CORE_EXPORT StyleEngine final
CSSStyleSheet* InspectorStyleSheet() const { return inspector_style_sheet_; }
+ void AddTextTrack(TextTrack*);
+ void RemoveTextTrack(TextTrack*);
+
const ActiveStyleSheetVector ActiveStyleSheetsForInspector();
bool NeedsActiveStyleUpdate() const;
@@ -343,12 +344,20 @@ class CORE_EXPORT StyleEngine final
const AtomicString& animation_name);
DocumentStyleEnvironmentVariables& EnsureEnvironmentVariables();
- void AddDefaultFontDisplay(const StyleRuleFontFeatureValues*);
- FontDisplay GetDefaultFontDisplay(const AtomicString& family) const;
scoped_refptr<StyleInitialData> MaybeCreateAndGetInitialData();
+ bool NeedsStyleInvalidation() const {
+ return style_invalidation_root_.GetRootNode();
+ }
+ bool NeedsStyleRecalc() const { return style_recalc_root_.GetRootNode(); }
+ bool NeedsLayoutTreeRebuild() const {
+ return layout_tree_rebuild_root_.GetRootNode();
+ }
+ bool NeedsFullStyleUpdate() const;
+
void UpdateViewportStyle();
+ void UpdateStyleAndLayoutTree();
void RecalcStyle();
void RebuildLayoutTree();
bool InRebuildLayoutTree() const { return in_layout_tree_rebuild_; }
@@ -358,7 +367,6 @@ class CORE_EXPORT StyleEngine final
PreferredColorScheme GetPreferredColorScheme() const {
return preferred_color_scheme_;
}
- ForcedColors GetForcedColors() const { return forced_colors_; }
void UpdateColorSchemeBackground();
void Trace(blink::Visitor*) override;
@@ -391,6 +399,7 @@ class CORE_EXPORT StyleEngine final
typedef HeapHashSet<Member<TreeScope>> UnorderedTreeScopeSet;
void MediaQueryAffectingValueChanged(UnorderedTreeScopeSet&);
+ void MediaQueryAffectingValueChanged(HeapHashSet<Member<TextTrack>>&);
const RuleFeatureSet& GetRuleFeatureSet() const {
DCHECK(IsMaster());
DCHECK(global_rule_set_);
@@ -458,6 +467,9 @@ class CORE_EXPORT StyleEngine final
void UpdateColorScheme();
bool SupportsDarkColorScheme();
+ void ViewportDefiningElementDidChange();
+ void PropagateWritingModeAndDirectionToHTMLRoot();
+
Member<Document> document_;
bool is_master_;
@@ -554,10 +566,6 @@ class CORE_EXPORT StyleEngine final
scoped_refptr<StyleInitialData> initial_data_;
- // Default font-display collected from @font-feature-values rules. The key is
- // font-family.
- HashMap<AtomicString, FontDisplay> default_font_display_map_;
-
// Color schemes explicitly supported by the author through the viewport meta
// tag. E.g. <meta name="color-scheme" content="light dark">. A dark color-
// scheme is used to opt-out of forced darkening.
@@ -569,12 +577,11 @@ class CORE_EXPORT StyleEngine final
PreferredColorScheme preferred_color_scheme_ =
PreferredColorScheme::kNoPreference;
- // Forced colors is set in settings.
- ForcedColors forced_colors_ = ForcedColors::kNone;
-
friend class NodeTest;
friend class StyleEngineTest;
friend class WhitespaceAttacherTest;
+
+ HeapHashSet<Member<TextTrack>> text_tracks_;
};
} // namespace blink
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 3722659c3cd..637c3d366be 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
@@ -8,8 +8,10 @@
#include "testing/gtest/include/gtest/gtest.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/common/css/preferred_color_scheme.h"
#include "third_party/blink/public/platform/web_float_rect.h"
+#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
@@ -67,6 +69,10 @@ class StyleEngineTest : public testing::Test {
DocumentLifecycle::LifecycleUpdateReason::kTest);
}
+ Node* GetStyleRecalcRoot() {
+ return GetStyleEngine().style_recalc_root_.GetRootNode();
+ }
+
private:
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
};
@@ -1582,11 +1588,13 @@ TEST_F(StyleEngineTest, MediaQueriesChangeForcedColors) {
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
- GetDocument().GetSettings()->SetForcedColors(ForcedColors::kActive);
+ Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kActive);
+ GetDocument().PlatformColorsChanged();
UpdateAllLifecyclePhases();
EXPECT_EQ(MakeRGB(0, 128, 0),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
+ Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone);
}
TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) {
@@ -1616,7 +1624,7 @@ TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) {
)HTML");
// ForcedColors = kNone, PreferredColorScheme = kLight
- GetDocument().GetSettings()->SetForcedColors(ForcedColors::kNone);
+ Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone);
GetDocument().GetSettings()->SetPreferredColorScheme(
PreferredColorScheme::kLight);
UpdateAllLifecyclePhases();
@@ -1633,7 +1641,8 @@ TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) {
GetCSSPropertyColor()));
// ForcedColors = kActive, PreferredColorScheme = kDark
- GetDocument().GetSettings()->SetForcedColors(ForcedColors::kActive);
+ Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kActive);
+ GetDocument().PlatformColorsChanged();
UpdateAllLifecyclePhases();
EXPECT_EQ(MakeRGB(255, 165, 0),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
@@ -1654,6 +1663,101 @@ TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) {
EXPECT_EQ(MakeRGB(0, 0, 255),
GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
GetCSSPropertyColor()));
+ Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone);
+}
+
+TEST_F(StyleEngineTest, MediaQueriesColorSchemeOverride) {
+ ScopedMediaQueryPrefersColorSchemeForTest feature_scope(true);
+
+ EXPECT_EQ(PreferredColorScheme::kNoPreference,
+ GetDocument().GetSettings()->GetPreferredColorScheme());
+
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ body { color: red }
+ @media (prefers-color-scheme: dark) {
+ body { color: green }
+ }
+ </style>
+ <body></body>
+ )HTML");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-color-scheme",
+ "dark");
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(0, 128, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->ClearMediaFeatureOverrides();
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+}
+
+TEST_F(StyleEngineTest, MediaQueriesReducedMotionOverride) {
+ EXPECT_FALSE(GetDocument().GetSettings()->GetPrefersReducedMotion());
+
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ body { color: red }
+ @media (prefers-reduced-motion: reduce) {
+ body { color: green }
+ }
+ </style>
+ <body></body>
+ )HTML");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-reduced-motion",
+ "reduce");
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(0, 128, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetPage()->ClearMediaFeatureOverrides();
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+}
+
+TEST_F(StyleEngineTest, MediaQueriesChangeNavigationControls) {
+ ScopedMediaQueryNavigationControlsForTest scoped_feature(true);
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ @media (navigation-controls: none) {
+ body { color: red }
+ }
+ @media (navigation-controls: back-button) {
+ body { color: green }
+ }
+ </style>
+ <body></body>
+ )HTML");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(255, 0, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+
+ GetDocument().GetSettings()->SetNavigationControls(
+ NavigationControls::kBackButton);
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(MakeRGB(0, 128, 0),
+ GetDocument().body()->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
}
TEST_F(StyleEngineTest, ShadowRootStyleRecalcCrash) {
@@ -1740,10 +1844,10 @@ TEST_F(StyleEngineTest, MarkForWhitespaceReattachment) {
EXPECT_TRUE(GetStyleEngine().NeedsWhitespaceReattachment(d1));
EXPECT_FALSE(GetDocument().ChildNeedsStyleInvalidation());
EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
GetStyleEngine().MarkForWhitespaceReattachment();
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
UpdateAllLifecyclePhases();
@@ -1752,10 +1856,10 @@ TEST_F(StyleEngineTest, MarkForWhitespaceReattachment) {
EXPECT_TRUE(GetStyleEngine().NeedsWhitespaceReattachment(d2));
EXPECT_FALSE(GetDocument().ChildNeedsStyleInvalidation());
EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
GetStyleEngine().MarkForWhitespaceReattachment();
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
UpdateAllLifecyclePhases();
@@ -1763,10 +1867,10 @@ TEST_F(StyleEngineTest, MarkForWhitespaceReattachment) {
EXPECT_TRUE(GetStyleEngine().NeedsWhitespaceReattachment(d3));
EXPECT_FALSE(GetDocument().ChildNeedsStyleInvalidation());
EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
GetStyleEngine().MarkForWhitespaceReattachment();
- EXPECT_TRUE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_TRUE(GetStyleEngine().NeedsLayoutTreeRebuild());
}
TEST_F(StyleEngineTest, FirstLetterRemoved) {
@@ -2035,6 +2139,71 @@ TEST_F(StyleEngineTest, ColorSchemeBaseBackgroundChange) {
EXPECT_EQ(Color::kBlack, GetDocument().View()->BaseBackgroundColor());
}
+TEST_F(StyleEngineTest, ColorSchemeOverride) {
+ ScopedCSSColorSchemeForTest enable_color_scheme(true);
+
+ GetDocument().documentElement()->SetInlineStyleProperty(
+ CSSPropertyID::kColorScheme, "light dark");
+ UpdateAllLifecyclePhases();
+
+ EXPECT_EQ(
+ WebColorScheme::kLight,
+ GetDocument().documentElement()->GetComputedStyle()->UsedColorScheme());
+
+ GetDocument().GetPage()->SetMediaFeatureOverride("prefers-color-scheme",
+ "dark");
+
+ UpdateAllLifecyclePhases();
+ EXPECT_EQ(
+ WebColorScheme::kDark,
+ GetDocument().documentElement()->GetComputedStyle()->UsedColorScheme());
+}
+
+TEST_F(StyleEngineTest, InternalRootColor) {
+ ScopedCSSColorSchemeForTest enable_color_scheme(true);
+ GetDocument().GetSettings()->SetPreferredColorScheme(
+ PreferredColorScheme::kDark);
+
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ #container { color-scheme: dark }
+ #light { color-scheme: light }
+ </style>
+ <div id="container">
+ <span id="dark">Text</span>
+ <span id="light">Text</span>
+ </div>
+ )HTML");
+
+ UpdateAllLifecyclePhases();
+
+ auto* container = GetDocument().getElementById("container");
+ auto* light = GetDocument().getElementById("light");
+ auto* dark = GetDocument().getElementById("dark");
+
+ // Initial value of color-scheme is 'light'.
+ EXPECT_EQ(
+ WebColorScheme::kLight,
+ GetDocument().documentElement()->GetComputedStyle()->UsedColorScheme());
+ EXPECT_EQ(WebColorScheme::kDark,
+ container->GetComputedStyle()->UsedColorScheme());
+ // color-scheme:dark inherited from #container.
+ EXPECT_EQ(WebColorScheme::kDark, dark->GetComputedStyle()->UsedColorScheme());
+ EXPECT_EQ(WebColorScheme::kLight,
+ light->GetComputedStyle()->UsedColorScheme());
+
+ EXPECT_EQ(Color::kBlack, GetDocument()
+ .documentElement()
+ ->GetComputedStyle()
+ ->VisitedDependentColor(GetCSSPropertyColor()));
+ EXPECT_EQ(Color::kWhite, container->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+ EXPECT_EQ(Color::kWhite, dark->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+ EXPECT_EQ(Color::kBlack, light->GetComputedStyle()->VisitedDependentColor(
+ GetCSSPropertyColor()));
+}
+
TEST_F(StyleEngineTest, PseudoElementBaseComputedStyle) {
GetDocument().body()->SetInnerHTMLFromString(R"HTML(
<style>
@@ -2080,16 +2249,54 @@ TEST_F(StyleEngineTest, NeedsLayoutTreeRebuild) {
UpdateAllLifecyclePhases();
EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
- EXPECT_FALSE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
GetDocument().documentElement()->SetInlineStyleProperty(
CSSPropertyID::kDisplay, "none");
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+
GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
GetDocument().GetStyleEngine().RecalcStyle();
- EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
- EXPECT_TRUE(GetDocument().NeedsLayoutTreeRebuild());
+ EXPECT_TRUE(GetStyleEngine().NeedsLayoutTreeRebuild());
+}
+
+TEST_F(StyleEngineTest, ForceReattachLayoutTreeStyleRecalcRoot) {
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <div id="outer">
+ <div id="inner"></div>
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhases();
+
+ Element* outer = GetDocument().getElementById("outer");
+ Element* inner = GetDocument().getElementById("inner");
+
+ outer->SetForceReattachLayoutTree();
+ inner->SetInlineStyleProperty(CSSPropertyID::kColor, "blue");
+
+ EXPECT_EQ(outer, GetStyleRecalcRoot());
+}
+
+TEST_F(StyleEngineTest, RecalcPropagatedWritingMode) {
+ GetDocument().body()->SetInlineStyleProperty(CSSPropertyID::kWritingMode,
+ "vertical-lr");
+
+ UpdateAllLifecyclePhases();
+
+ // Make sure that recalculating style for the root element does not trigger a
+ // visual diff that requires layout. That is, we take the body -> root
+ // propagation of writing-mode into account before setting ComputedStyle on
+ // the root LayoutObject.
+ GetDocument().documentElement()->SetInlineStyleProperty(
+ CSSPropertyID::kWritingMode, "horizontal-tb");
+
+ GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
+ GetDocument().GetStyleEngine().RecalcStyle();
+
+ EXPECT_FALSE(GetStyleEngine().NeedsLayoutTreeRebuild());
+ EXPECT_FALSE(GetDocument().View()->NeedsLayout());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_invalidation_root.cc b/chromium/third_party/blink/renderer/core/css/style_invalidation_root.cc
index bb29306e757..a317c66bc2a 100644
--- a/chromium/third_party/blink/renderer/core/css/style_invalidation_root.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_invalidation_root.cc
@@ -37,8 +37,9 @@ void StyleInvalidationRoot::ClearChildDirtyForAncestors(
ContainerNode& parent) const {
for (Node* ancestor = &parent; ancestor;
ancestor = ancestor->ParentOrShadowHostNode()) {
- ancestor->ClearChildNeedsStyleInvalidation();
+ DCHECK(ancestor->ChildNeedsStyleInvalidation());
DCHECK(!ancestor->NeedsStyleInvalidation());
+ ancestor->ClearChildNeedsStyleInvalidation();
}
}
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 70b8bb6d9c3..5d59848c6e1 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
@@ -30,6 +30,7 @@
#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_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"
#include "third_party/blink/renderer/core/css_value_keywords.h"
@@ -560,7 +561,7 @@ String StylePropertySerializer::SerializeShorthand(
return String();
}
case CSSPropertyID::kBorderRadius:
- return Get4Values(borderRadiusShorthand());
+ return BorderRadiusValue();
case CSSPropertyID::kScrollPadding:
return Get4Values(scrollPaddingShorthand());
case CSSPropertyID::kScrollPaddingBlock:
@@ -633,29 +634,27 @@ bool StylePropertySerializer::AppendFontLonghandValueIfNotNormal(
if (identifier_value && identifier_value->GetValueID() == CSSValueID::kNormal)
return true;
- char prefix = '\0';
- switch (property.PropertyID()) {
- case CSSPropertyID::kFontStyle:
- break; // No prefix.
- case CSSPropertyID::kFontFamily:
- case CSSPropertyID::kFontStretch:
- case CSSPropertyID::kFontVariantCaps:
- case CSSPropertyID::kFontVariantLigatures:
- case CSSPropertyID::kFontVariantNumeric:
- case CSSPropertyID::kFontVariantEastAsian:
- case CSSPropertyID::kFontWeight:
- prefix = ' ';
- break;
- case CSSPropertyID::kLineHeight:
- prefix = '/';
- break;
- default:
- NOTREACHED();
+ if (!result.IsEmpty()) {
+ switch (property.PropertyID()) {
+ case CSSPropertyID::kFontStyle:
+ break; // No prefix.
+ case CSSPropertyID::kFontFamily:
+ case CSSPropertyID::kFontStretch:
+ case CSSPropertyID::kFontVariantCaps:
+ case CSSPropertyID::kFontVariantLigatures:
+ case CSSPropertyID::kFontVariantNumeric:
+ case CSSPropertyID::kFontVariantEastAsian:
+ case CSSPropertyID::kFontWeight:
+ result.Append(' ');
+ break;
+ case CSSPropertyID::kLineHeight:
+ result.Append(" / ");
+ break;
+ default:
+ NOTREACHED();
+ }
}
- if (prefix && !result.IsEmpty())
- result.Append(prefix);
-
String value;
// In the font-variant shorthand a "none" ligatures value needs to be
// expanded.
@@ -1096,6 +1095,58 @@ String StylePropertySerializer::BorderImagePropertyValue() const {
return result.ToString();
}
+String StylePropertySerializer::BorderRadiusValue() const {
+ auto serialize = [](const CSSValue& top_left, const CSSValue& top_right,
+ const CSSValue& bottom_right,
+ const CSSValue& bottom_left) -> String {
+ bool show_bottom_left = !(top_right == bottom_left);
+ bool show_bottom_right = !(top_left == bottom_right) || show_bottom_left;
+ bool show_top_right = !(top_left == top_right) || show_bottom_right;
+
+ StringBuilder result;
+ result.Append(top_left.CssText());
+ if (show_top_right) {
+ result.Append(' ');
+ result.Append(top_right.CssText());
+ }
+ if (show_bottom_right) {
+ result.Append(' ');
+ result.Append(bottom_right.CssText());
+ }
+ if (show_bottom_left) {
+ result.Append(' ');
+ result.Append(bottom_left.CssText());
+ }
+ return result.ToString();
+ };
+
+ const CSSValuePair& top_left = To<CSSValuePair>(
+ *property_set_.GetPropertyCSSValue(GetCSSPropertyBorderTopLeftRadius()));
+ const CSSValuePair& top_right = To<CSSValuePair>(
+ *property_set_.GetPropertyCSSValue(GetCSSPropertyBorderTopRightRadius()));
+ const CSSValuePair& bottom_right =
+ To<CSSValuePair>(*property_set_.GetPropertyCSSValue(
+ GetCSSPropertyBorderBottomRightRadius()));
+ const CSSValuePair& bottom_left =
+ To<CSSValuePair>(*property_set_.GetPropertyCSSValue(
+ GetCSSPropertyBorderBottomLeftRadius()));
+
+ StringBuilder builder;
+ builder.Append(serialize(top_left.First(), top_right.First(),
+ bottom_right.First(), bottom_left.First()));
+
+ if (!(top_left.First() == top_left.Second()) ||
+ !(top_right.First() == top_right.Second()) ||
+ !(bottom_right.First() == bottom_right.Second()) ||
+ !(bottom_left.First() == bottom_left.Second())) {
+ builder.Append(" / ");
+ builder.Append(serialize(top_left.Second(), top_right.Second(),
+ bottom_right.Second(), bottom_left.Second()));
+ }
+
+ return builder.ToString();
+}
+
static void AppendBackgroundRepeatValue(StringBuilder& builder,
const CSSValue& repeat_xcss_value,
const CSSValue& repeat_ycss_value) {
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 59329fd8b3f..4205dabebbd 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
@@ -48,6 +48,7 @@ class StylePropertySerializer {
const StylePropertyShorthand&,
const StylePropertyShorthand&) const;
String BorderImagePropertyValue() const;
+ String BorderRadiusValue() const;
String GetLayeredShorthandValue(const StylePropertyShorthand&) const;
String Get2Values(const StylePropertyShorthand&) const;
String Get4Values(const StylePropertyShorthand&) const;
diff --git a/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc b/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
index 0a251fbd4f0..c94c76e8dbd 100644
--- a/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_recalc_root.cc
@@ -36,7 +36,7 @@ Element& StyleRecalcRoot::RootElement() const {
#if DCHECK_IS_ON()
ContainerNode* StyleRecalcRoot::Parent(const Node& node) const {
- return node.ParentOrShadowHostNode();
+ return node.GetStyleRecalcParent();
}
bool StyleRecalcRoot::IsChildDirty(const ContainerNode& node) const {
@@ -45,14 +45,19 @@ bool StyleRecalcRoot::IsChildDirty(const ContainerNode& node) const {
#endif // DCHECK_IS_ON()
bool StyleRecalcRoot::IsDirty(const Node& node) const {
- return node.NeedsStyleRecalc();
+ return node.IsDirtyForStyleRecalc();
}
void StyleRecalcRoot::ClearChildDirtyForAncestors(ContainerNode& parent) const {
- for (ContainerNode* ancestor = &parent; ancestor;
- ancestor = ancestor->ParentOrShadowHostNode()) {
- ancestor->ClearChildNeedsStyleRecalc();
+ ContainerNode* ancestor = &parent;
+ if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled() &&
+ !parent.IsElementNode()) {
+ ancestor = parent.ParentOrShadowHostElement();
+ }
+ for (; ancestor; ancestor = ancestor->GetStyleRecalcParent()) {
+ DCHECK(ancestor->ChildNeedsStyleRecalc());
DCHECK(!ancestor->NeedsStyleRecalc());
+ ancestor->ClearChildNeedsStyleRecalc();
}
}
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 fc4f7801d15..4a99e20558e 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.cc
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/css_font_face_rule.h"
-#include "third_party/blink/renderer/core/css/css_font_feature_values_rule.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
@@ -40,8 +39,8 @@
namespace blink {
-struct SameSizeAsStyleRuleBase
- : public GarbageCollectedFinalized<SameSizeAsStyleRuleBase> {
+struct SameSizeAsStyleRuleBase final
+ : public GarbageCollected<SameSizeAsStyleRuleBase> {
unsigned bitfields;
};
@@ -94,9 +93,6 @@ void StyleRuleBase::Trace(blink::Visitor* visitor) {
case kViewport:
To<StyleRuleViewport>(this)->TraceAfterDispatch(visitor);
return;
- case kFontFeatureValues:
- To<StyleRuleFontFeatureValues>(this)->TraceAfterDispatch(visitor);
- return;
}
NOTREACHED();
}
@@ -139,9 +135,6 @@ void StyleRuleBase::FinalizeGarbageCollectedObject() {
case kViewport:
To<StyleRuleViewport>(this)->~StyleRuleViewport();
return;
- case kFontFeatureValues:
- To<StyleRuleFontFeatureValues>(this)->~StyleRuleFontFeatureValues();
- return;
}
NOTREACHED();
}
@@ -170,8 +163,6 @@ StyleRuleBase* StyleRuleBase::Copy() const {
return To<StyleRuleViewport>(this)->Copy();
case kNamespace:
return To<StyleRuleNamespace>(this)->Copy();
- case kFontFeatureValues:
- return To<StyleRuleFontFeatureValues>(this)->Copy();
case kCharset:
case kKeyframe:
NOTREACHED();
@@ -226,10 +217,6 @@ CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet,
rule = MakeGarbageCollected<CSSViewportRule>(To<StyleRuleViewport>(self),
parent_sheet);
break;
- case kFontFeatureValues:
- rule = MakeGarbageCollected<CSSFontFeatureValuesRule>(
- To<StyleRuleFontFeatureValues>(self), parent_sheet);
- break;
case kKeyframe:
case kCharset:
NOTREACHED();
@@ -455,17 +442,4 @@ void StyleRuleViewport::TraceAfterDispatch(blink::Visitor* visitor) {
StyleRuleBase::TraceAfterDispatch(visitor);
}
-StyleRuleFontFeatureValues::StyleRuleFontFeatureValues(
- const CSSValueList* font_family,
- const CSSIdentifierValue* font_display)
- : StyleRuleBase(kFontFeatureValues),
- font_family_(font_family),
- font_display_(font_display) {}
-
-void StyleRuleFontFeatureValues::TraceAfterDispatch(blink::Visitor* visitor) {
- visitor->Trace(font_family_);
- visitor->Trace(font_display_);
- StyleRuleBase::TraceAfterDispatch(visitor);
-}
-
} // namespace blink
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 d465b100cda..feaac3a2c00 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/style_rule.h
@@ -32,13 +32,10 @@
namespace blink {
-class CSSIdentifierValue;
class CSSRule;
class CSSStyleSheet;
-class CSSValueList;
-class CORE_EXPORT StyleRuleBase
- : public GarbageCollectedFinalized<StyleRuleBase> {
+class CORE_EXPORT StyleRuleBase : public GarbageCollected<StyleRuleBase> {
public:
enum RuleType {
kCharset,
@@ -53,7 +50,6 @@ class CORE_EXPORT StyleRuleBase
kNamespace,
kSupports,
kViewport,
- kFontFeatureValues,
};
RuleType GetType() const { return static_cast<RuleType>(type_); }
@@ -70,9 +66,6 @@ class CORE_EXPORT StyleRuleBase
bool IsSupportsRule() const { return GetType() == kSupports; }
bool IsViewportRule() const { return GetType() == kViewport; }
bool IsImportRule() const { return GetType() == kImport; }
- bool IsFontFeatureValuesRule() const {
- return GetType() == kFontFeatureValues;
- }
StyleRuleBase* Copy() const;
@@ -325,29 +318,6 @@ class StyleRuleCharset : public StyleRuleBase {
private:
};
-class CORE_EXPORT StyleRuleFontFeatureValues : public StyleRuleBase {
- public:
- StyleRuleFontFeatureValues(const CSSValueList* font_family,
- const CSSIdentifierValue* font_display);
- StyleRuleFontFeatureValues(const StyleRuleFontFeatureValues&) = default;
-
- StyleRuleFontFeatureValues* Copy() const {
- return MakeGarbageCollected<StyleRuleFontFeatureValues>(*this);
- }
-
- const CSSValueList& FontFamily() const {
- DCHECK(font_family_);
- return *font_family_;
- }
- const CSSIdentifierValue* FontDisplay() const { return font_display_; }
-
- void TraceAfterDispatch(blink::Visitor*);
-
- private:
- Member<const CSSValueList> font_family_;
- Member<const CSSIdentifierValue> font_display_;
-};
-
template <>
struct DowncastTraits<StyleRule> {
static bool AllowFrom(const StyleRuleBase& rule) {
@@ -402,13 +372,6 @@ struct DowncastTraits<StyleRuleCharset> {
}
};
-template <>
-struct DowncastTraits<StyleRuleFontFeatureValues> {
- static bool AllowFrom(const StyleRuleBase& rule) {
- return rule.IsFontFeatureValuesRule();
- }
-};
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_RULE_H_
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 cdfd0ef7bba..3d9d022e23c 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
@@ -65,7 +65,7 @@ class StyleRuleImport : public StyleRuleBase {
// NOTE: We put the ResourceClient in a member instead of inheriting
// from it to avoid adding a vptr to StyleRuleImport.
class ImportedStyleSheetClient final
- : public GarbageCollectedFinalized<ImportedStyleSheetClient>,
+ : public GarbageCollected<ImportedStyleSheetClient>,
public ResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(ImportedStyleSheetClient);
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 efdf51cfd33..57951be3103 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
@@ -43,7 +43,7 @@ namespace blink {
class StyleSheet;
class CORE_EXPORT StyleSheetCollection
- : public GarbageCollectedFinalized<StyleSheetCollection>,
+ : public GarbageCollected<StyleSheetCollection>,
public NameClient {
public:
friend class ActiveDocumentStyleSheetCollector;
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 31140d7094a..000e05e1de7 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
@@ -515,7 +515,6 @@ static bool ChildRulesHaveFailedOrCanceledSubresources(
case StyleRuleBase::kKeyframe:
case StyleRuleBase::kSupports:
case StyleRuleBase::kViewport:
- case StyleRuleBase::kFontFeatureValues:
break;
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_contents.h b/chromium/third_party/blink/renderer/core/css/style_sheet_contents.h
index 80e49b2d4c4..c92b55bd7b4 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_contents.h
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_contents.h
@@ -47,8 +47,8 @@ class StyleRuleImport;
class StyleRuleNamespace;
enum class ParseSheetResult;
-class CORE_EXPORT StyleSheetContents
- : public GarbageCollectedFinalized<StyleSheetContents> {
+class CORE_EXPORT StyleSheetContents final
+ : public GarbageCollected<StyleSheetContents> {
public:
static const Document* SingleOwnerDocument(const StyleSheetContents*);
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 98f32dde0ef..afcebcba7e6 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
@@ -55,10 +55,6 @@ void StyleTraversalRoot::Update(ContainerNode* common_ancestor,
void StyleTraversalRoot::ChildrenRemoved(ContainerNode& parent) {
if (!root_node_ || root_node_->isConnected())
return;
-#if DCHECK_IS_ON()
- DCHECK(IsChildDirty(parent));
- DCHECK(!IsDirty(parent));
-#endif // DCHECK_IS_ON()
ClearChildDirtyForAncestors(parent);
Clear();
}
diff --git a/chromium/third_party/blink/renderer/core/css/touchless.css b/chromium/third_party/blink/renderer/core/css/touchless.css
deleted file mode 100644
index a0013b0378b..00000000000
--- a/chromium/third_party/blink/renderer/core/css/touchless.css
+++ /dev/null
@@ -1,31 +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. */
-
-video:focus {
- outline: none !important;
- box-shadow: none !important
-}
-
-input[type = text],
-input[type = email],
-input[type = date],
-input[type = datetime],
-input[type = datetime-local],
-input[type = month],
-input[type = number],
-input[type = password],
-input[type = search],
-input[type = time],
-video:-internal-spatial-navigation-interest {
- outline-offset: -4px
-}
-
-:-internal-spatial-navigation-interest {
- outline: auto 4px #185ABC !important;
- box-shadow: none !important
-}
-
-body {
- user-select: none !important;
-}
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock.dict b/chromium/third_party/blink/renderer/core/display_lock/display_lock.dict
index e8d53579c69..02c0f17d8f2 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock.dict
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock.dict
@@ -1,11 +1,5 @@
-"displayLock.acquire"
-"displayLock.commit()"
-"displayLock.update()"
-"displayLock.updateAndCommit()"
-"activatable: true"
-"activatable: false"
-"timeout: Infinity"
-"timeout: 0"
-"timeout: 17"
-"size: [100, 100]"
-"contain: style layout"
+"rendersubtree=''"
+"rendersubtree='invisible'"
+"rendersubtree='invisible activatable'"
+"updateRendering()"
+"content-size"
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
index 45601b5f3b5..513da9c01ad 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -44,6 +44,18 @@ class DisplayLockBudgetTest : public RenderingTest,
context->update_budget_ = std::move(budget);
}
+ void LockElement(Element& element, bool update_lifecycle = true) {
+ element.setAttribute(html_names::kRendersubtreeAttr, "invisible");
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ void CommitElement(Element& element, bool update_lifecycle = true) {
+ element.setAttribute(html_names::kRendersubtreeAttr, "");
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
+ }
+
protected:
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
@@ -65,11 +77,7 @@ TEST_F(DisplayLockBudgetTest, UnyieldingBudget) {
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*element, false);
ASSERT_TRUE(element->GetDisplayLockContext());
UnyieldingDisplayLockBudget budget(element->GetDisplayLockContext());
@@ -112,11 +120,7 @@ TEST_F(DisplayLockBudgetTest, StrictYieldingBudget) {
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*element, false);
ASSERT_TRUE(element->GetDisplayLockContext());
StrictYieldingDisplayLockBudget budget(element->GetDisplayLockContext());
@@ -287,11 +291,7 @@ TEST_F(DisplayLockBudgetTest,
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*element, false);
ASSERT_TRUE(element->GetDisplayLockContext());
StrictYieldingDisplayLockBudget budget(element->GetDisplayLockContext());
@@ -334,11 +334,7 @@ TEST_F(DisplayLockBudgetTest, YieldingBudget) {
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*element, false);
ASSERT_TRUE(element->GetDisplayLockContext());
YieldingDisplayLockBudget budget(element->GetDisplayLockContext());
@@ -468,12 +464,7 @@ TEST_F(DisplayLockBudgetTest, YieldingBudgetMarksNextPhase) {
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element);
ASSERT_TRUE(element->GetDisplayLockContext());
ASSERT_TRUE(element->GetDisplayLockContext()->IsLocked());
@@ -485,7 +476,7 @@ TEST_F(DisplayLockBudgetTest, YieldingBudgetMarksNextPhase) {
{
auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->update(script_state);
+ element->GetDisplayLockContext()->UpdateRendering(script_state);
ResetBudget(std::move(budget_owned), element->GetDisplayLockContext());
}
@@ -563,12 +554,7 @@ TEST_F(DisplayLockBudgetTest, UpdateHappensInLifecycleOnly) {
)HTML");
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element);
ASSERT_TRUE(element->GetDisplayLockContext());
ASSERT_TRUE(element->GetDisplayLockContext()->IsLocked());
@@ -579,7 +565,7 @@ TEST_F(DisplayLockBudgetTest, UpdateHappensInLifecycleOnly) {
{
auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->update(script_state);
+ element->GetDisplayLockContext()->UpdateRendering(script_state);
ResetBudget(std::move(budget_owned), element->GetDisplayLockContext());
}
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 0e6b6cb3f9c..ca1c90a47b7 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
@@ -9,7 +9,7 @@
#include "base/memory/ptr_util.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/display_lock/display_lock_options.h"
+#include "third_party/blink/renderer/core/display_lock/before_activate_event.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h"
#include "third_party/blink/renderer/core/display_lock/unyielding_display_lock_budget.h"
@@ -31,20 +31,13 @@
namespace blink {
namespace {
-// The default timeout for the lock if a timeout is not specified. Defaults to 1
-// sec.
-double kDefaultLockTimeoutMs = 1000.;
-
namespace rejection_names {
-const char* kElementIsUnlocked = "Element is unlocked.";
const char* kExecutionContextDestroyed = "Execution context destroyed.";
const char* kContainmentNotSatisfied =
"Containment requirement is not satisfied.";
const char* kUnsupportedDisplay =
"Element has unsupported display type (display: contents).";
const char* kElementIsDisconnected = "Element is disconnected.";
-const char* kLockCommitted = "Lock commit was requested.";
-const char* kInvalidOptions = "Invalid options.";
const char* kElementIsNested = "Element is nested under a locked element.";
} // namespace rejection_names
@@ -82,12 +75,6 @@ ScriptPromise GetResolvedPromise(ScriptState* script_state) {
return promise;
}
-base::Optional<LayoutSize> ParseAndVerifySize(const Vector<double>& size) {
- if (size.size() != 2 || size[0] < 0 || size[1] < 0)
- return {};
- return LayoutSize(static_cast<float>(size[0]), static_cast<float>(size[1]));
-}
-
} // namespace
DisplayLockContext::DisplayLockContext(Element* element,
@@ -103,13 +90,9 @@ DisplayLockContext::~DisplayLockContext() {
void DisplayLockContext::Trace(blink::Visitor* visitor) {
visitor->Trace(update_resolver_);
- visitor->Trace(commit_resolver_);
- visitor->Trace(acquire_resolver_);
visitor->Trace(element_);
visitor->Trace(document_);
visitor->Trace(whitespace_reattach_set_);
- ScriptWrappable::Trace(visitor);
- ActiveScriptWrappable::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
}
@@ -121,104 +104,42 @@ void DisplayLockContext::Dispose() {
// TODO(vmpstr): See if there is another earlier time we can detect that we're
// going to be disposed.
FinishUpdateResolver(kDetach);
- FinishCommitResolver(kDetach);
- FinishAcquireResolver(kDetach);
- CancelTimeoutTask();
state_ = kUnlocked;
}
void DisplayLockContext::ContextDestroyed(ExecutionContext*) {
FinishUpdateResolver(kReject, rejection_names::kExecutionContextDestroyed);
- FinishCommitResolver(kReject, rejection_names::kExecutionContextDestroyed);
- FinishAcquireResolver(kReject, rejection_names::kExecutionContextDestroyed);
- CancelTimeoutTask();
state_ = kUnlocked;
}
-bool DisplayLockContext::HasPendingActivity() const {
- // If we're locked or doing any work and have an element, then we should stay
- // alive. If the element is gone, then there is no reason for the context to
- // remain. Also, if we're unlocked we're essentially "idle" so GC can clean us
- // up. If the script needs the context, the element would create a new one.
- return element_ && state_ != kUnlocked;
-}
-
-ScriptPromise DisplayLockContext::acquire(ScriptState* script_state,
- DisplayLockOptions* options) {
- TRACE_EVENT0("blink", "DisplayLockContext::acquire()");
- if (!GetExecutionContext()) {
- return GetRejectedPromise(script_state,
- rejection_names::kExecutionContextDestroyed);
- }
-
- double timeout_ms = (options && options->hasTimeout())
- ? options->timeout()
- : kDefaultLockTimeoutMs;
-
- // We always reschedule a timeout task even if we're not starting a new
- // acquire. The reason for this is that the last acquire dictates the timeout
- // interval. Note that the following call cancels any existing timeout tasks.
- RescheduleTimeoutTask(timeout_ms);
-
- // We need to recalc if the locked size has changed.
- bool should_recalc_layout_size = false;
- if (options && options->hasSize()) {
- auto parsed_size = ParseAndVerifySize(options->size());
- if (!parsed_size)
- return GetRejectedPromise(script_state, rejection_names::kInvalidOptions);
- if (locked_content_logical_size_ != *parsed_size)
- should_recalc_layout_size = true;
- locked_content_logical_size_ = *parsed_size;
-
- } else {
- if (locked_content_logical_size_ != LayoutSize())
- should_recalc_layout_size = true;
- locked_content_logical_size_ = LayoutSize();
+void DisplayLockContext::UpdateActivationObservationIfNeeded() {
+ if (!document_) {
+ is_observed_ = false;
+ return;
}
- if (should_recalc_layout_size && ConnectedToView()) {
- if (auto* layout_object = element_->GetLayoutObject()) {
- layout_object->SetNeedsLayoutAndPrefWidthsRecalc(
- layout_invalidation_reason::kDisplayLock);
- }
- ScheduleAnimation();
+ bool should_observe = IsLocked() &&
+ IsActivatable(DisplayLockActivationReason::kViewport) &&
+ ConnectedToView();
+ if (should_observe && !is_observed_) {
+ document_->RegisterDisplayLockActivationObservation(element_);
+ } else if (!should_observe && is_observed_) {
+ document_->UnregisterDisplayLockActivationObservation(element_);
}
-
- SetActivatable(options && options->activatable());
-
- if (acquire_resolver_)
- return acquire_resolver_->Promise();
-
- // At this point, we updated state based on the options so if we're locked,
- // resolve.
- if (IsLocked())
- return GetResolvedPromise(script_state);
-
- // We might be committing (which means we're already unlocked for the purposes
- // of the above check. We resolve the commit, since rejecting it seems wrong.
- // TODO(vmpstr): We could also reject this, but then script would have no way
- // to avoid this rejection (since at the time acquire is called, locked
- // property is false).
- FinishCommitResolver(kResolve);
-
- StartAcquire();
-
- // If we're not connected, resolve immediately.
- if (!ConnectedToView())
- return GetResolvedPromise(script_state);
-
- MakeResolver(script_state, &acquire_resolver_);
- return acquire_resolver_->Promise();
+ is_observed_ = should_observe;
}
-void DisplayLockContext::SetActivatable(bool activatable) {
+void DisplayLockContext::SetActivatable(unsigned char activatable_mask) {
if (IsLocked()) {
- // If we're locked, the activatable flag might change the activation
+ // If we're locked, the activatable mask might change the activation
// blocking lock count. If we're not locked, the activation blocking lock
// count will be updated when we changed the state.
- state_.UpdateActivationBlockingCount(activatable_, activatable);
+ // Note that we record this only if we're blocking all activation. That is,
+ // the lock is considered activatable if any bit is set.
+ state_.UpdateActivationBlockingCount(activatable_mask_, activatable_mask);
}
- activatable_ = activatable;
+ activatable_mask_ = activatable_mask;
+ UpdateActivationObservationIfNeeded();
}
void DisplayLockContext::StartAcquire() {
@@ -258,17 +179,16 @@ void DisplayLockContext::StartAcquire() {
// we might use the cached result instead. In order to ensure we skip the
// newly locked layers, we need to set |need_graphics_layer_collection_|
// before marking the layer for repaint.
- needs_graphics_layer_collection_ = true;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ needs_graphics_layer_collection_ = true;
MarkPaintLayerNeedsRepaint();
}
-ScriptPromise DisplayLockContext::update(ScriptState* script_state) {
- TRACE_EVENT0("blink", "DisplayLockContext::update()");
- // Reject if we're unlocked or disconnected.
- if (state_ == kUnlocked || !ConnectedToView()) {
- return GetRejectedPromise(script_state,
- rejection_names::kElementIsUnlocked);
- }
+ScriptPromise DisplayLockContext::UpdateRendering(ScriptState* script_state) {
+ TRACE_EVENT0("blink", "DisplayLockContext::UpdateRendering");
+ // Immediately resolve if we're unlocked or disconnected.
+ if (state_ == kUnlocked || !ConnectedToView())
+ return GetResolvedPromise(script_state);
// If we have a resolver, then we're at least updating already, just return
// the same promise.
@@ -296,44 +216,9 @@ bool DisplayLockContext::CleanupAndRejectCommitIfNotConnected() {
update_budget_.reset();
// Note that we reject the update, but resolve the commit.
FinishUpdateResolver(kReject, rejection_names::kElementIsDisconnected);
- FinishCommitResolver(kResolve);
return true;
}
-ScriptPromise DisplayLockContext::commit(ScriptState* script_state) {
- TRACE_EVENT0("blink", "DisplayLockContext::commit()");
- // Resolve if we're already unlocked.
- if (state_ == kUnlocked)
- return GetResolvedPromise(script_state);
-
- // If we're already committing and it's not because of activation,
- // we would already have the commit promise and should just return it.
- if (commit_resolver_) {
- // When we perform an updateAndCommit(), we schedule a StartCommit() via a
- // task. While that task is in flight, our state could still be locked. It,
- // of course, can also be updating or committing if that's what we are
- // currently doing. So the only state we can't be in is kUnlocked.
- DCHECK(state_ != kUnlocked);
- return commit_resolver_->Promise();
- }
-
- if (CleanupAndRejectCommitIfNotConnected())
- return GetResolvedPromise(script_state);
-
- // Note that we don't resolve the update promise here, since it should still
- // finish updating before resolution. That is, calling update() and commit()
- // together will still wait until the lifecycle is clean before resolving any
- // of the promises.
-
- MakeResolver(script_state, &commit_resolver_);
- auto promise = commit_resolver_->Promise();
- // It's possible we are already committing due to activation. If not, we
- // should start the commit.
- if (state_ != kCommitting)
- StartCommit();
- return promise;
-}
-
void DisplayLockContext::MakeResolver(ScriptState* script_state,
Member<ScriptPromiseResolver>* resolver) {
DCHECK(ConnectedToView());
@@ -342,36 +227,7 @@ void DisplayLockContext::MakeResolver(ScriptState* script_state,
}
bool DisplayLockContext::HasResolver() {
- return acquire_resolver_ || update_resolver_ || commit_resolver_;
-}
-
-ScriptPromise DisplayLockContext::updateAndCommit(ScriptState* script_state) {
- TRACE_EVENT0("blink", "DisplayLockContext::updateAndCommit()");
-
- // Resolve if we're already unlocked.
- if (state_ == kUnlocked)
- return GetResolvedPromise(script_state);
-
- // If we're in a state where a co-operative update doesn't make sense (e.g. we
- // haven't acquired the lock, or we're already sync committing, or we're under
- // a nested lock), then do whatever commit() would do.
- if (state_ == kCommitting || !ConnectedToView() ||
- DisplayLockUtilities::NearestLockedExclusiveAncestor(*element_)) {
- return commit(script_state);
- }
-
- // If we have a commit resolver already, return it.
- if (commit_resolver_) {
- // We must be in a second call to updateAndCommit(), meaning that we're in
- // the kUpdating state with a commit_resolver_.
- DCHECK_EQ(state_, kUpdating);
- return commit_resolver_->Promise();
- }
-
- CancelTimeoutTask();
- MakeResolver(script_state, &commit_resolver_);
- StartUpdateIfNeeded();
- return commit_resolver_->Promise();
+ return update_resolver_;
}
void DisplayLockContext::FinishUpdateResolver(ResolverState state,
@@ -379,16 +235,6 @@ void DisplayLockContext::FinishUpdateResolver(ResolverState state,
FinishResolver(&update_resolver_, state, rejection_reason);
}
-void DisplayLockContext::FinishCommitResolver(ResolverState state,
- const char* rejection_reason) {
- FinishResolver(&commit_resolver_, state, rejection_reason);
-}
-
-void DisplayLockContext::FinishAcquireResolver(ResolverState state,
- const char* rejection_reason) {
- FinishResolver(&acquire_resolver_, state, rejection_reason);
-}
-
void DisplayLockContext::FinishResolver(Member<ScriptPromiseResolver>* resolver,
ResolverState state,
const char* rejection_reason) {
@@ -526,11 +372,18 @@ void DisplayLockContext::DidPaint(DisplayLockLifecycleTarget) {
// This is here for symmetry, but could be removed if necessary.
}
-bool DisplayLockContext::IsActivatable() const {
- return activatable_ || !IsLocked();
+bool DisplayLockContext::IsActivatable(
+ DisplayLockActivationReason reason) const {
+ return !IsLocked() ||
+ (activatable_mask_ & static_cast<unsigned char>(reason));
}
-void DisplayLockContext::CommitForActivation() {
+void DisplayLockContext::CommitForActivationWithSignal(
+ Element* activated_element) {
+ DCHECK(activated_element);
+ element_->DispatchEvent(
+ *MakeGarbageCollected<BeforeActivateEvent>(*activated_element));
+
// The beforeactivate signal may have committed this lock already, in which
// case we have nothing to do.
if (!IsLocked())
@@ -538,16 +391,17 @@ void DisplayLockContext::CommitForActivation() {
DCHECK(element_);
DCHECK(ConnectedToView());
- DCHECK(ShouldCommitForActivation());
+ DCHECK(ShouldCommitForActivation(DisplayLockActivationReason::kAny));
StartCommit();
// Since setting the attribute might trigger a commit if we are still locked,
// we set it after we start the commit.
if (element_->hasAttribute(html_names::kRendersubtreeAttr))
- element_->setAttribute(html_names::kRendersubtreeAttr, "visible");
+ element_->setAttribute(html_names::kRendersubtreeAttr, "");
}
-bool DisplayLockContext::ShouldCommitForActivation() const {
- return IsActivatable() && IsLocked();
+bool DisplayLockContext::ShouldCommitForActivation(
+ DisplayLockActivationReason reason) const {
+ return IsActivatable(reason) && IsLocked();
}
void DisplayLockContext::DidAttachLayoutTree() {
@@ -583,22 +437,11 @@ void DisplayLockContext::NotifyForcedUpdateScopeEnded() {
void DisplayLockContext::StartCommit() {
DCHECK(IsLocked());
- // Since we are starting a commit, cancel the timeout task.
- CancelTimeoutTask();
if (CleanupAndRejectCommitIfNotConnected())
return;
- // If we have an acquire resolver, it means that we haven't had a chance to
- // run the lifecycle yet to clear the painted output. However, we're being
- // requested to commit. So, we can commit immediately and reject the acquire
- // callback at the same time.
- if (acquire_resolver_) {
- FinishAcquireResolver(kReject, rejection_names::kLockCommitted);
- FinishCommitResolver(kResolve);
- state_ = kUnlocked;
- } else if (state_ != kUpdating) {
+ if (state_ != kUpdating)
ScheduleAnimation();
- }
// We might already be unlocked due to above, but we should still mark
// ancestor chains for updates below.
@@ -628,6 +471,9 @@ void DisplayLockContext::StartCommit() {
layout_object->SetNeedsLayoutAndPrefWidthsRecalc(
layout_invalidation_reason::kDisplayLock);
+
+ if (auto* view = layout_object->GetFrameView())
+ view->SetNeedsForcedResizeObservations();
}
void DisplayLockContext::StartUpdateIfNeeded() {
@@ -764,8 +610,9 @@ bool DisplayLockContext::MarkPaintLayerNeedsRepaint() {
DCHECK(ConnectedToView());
if (auto* layout_object = element_->GetLayoutObject()) {
layout_object->PaintingLayer()->SetNeedsRepaint();
- if (needs_graphics_layer_collection_) {
- document_->View()->GraphicsLayersDidChange();
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ needs_graphics_layer_collection_) {
+ document_->View()->SetForeignLayerListNeedsUpdate();
needs_graphics_layer_collection_ = false;
}
return true;
@@ -806,6 +653,11 @@ void DisplayLockContext::DidMoveToNewDocument(Document& old_document) {
DCHECK(element_);
document_ = &element_->GetDocument();
+ if (is_observed_) {
+ old_document.UnregisterDisplayLockActivationObservation(element_);
+ document_->RegisterDisplayLockActivationObservation(element_);
+ }
+
// Since we're observing the lifecycle updates, ensure that we listen to the
// right document's view.
if (HasResolver()) {
@@ -815,7 +667,7 @@ void DisplayLockContext::DidMoveToNewDocument(Document& old_document) {
document_->View()->RegisterForLifecycleNotifications(this);
}
- if (!IsActivatable()) {
+ if (!IsActivatable(DisplayLockActivationReason::kAny)) {
old_document.RemoveActivationBlockingDisplayLock();
document_->AddActivationBlockingDisplayLock();
}
@@ -831,17 +683,8 @@ void DisplayLockContext::WillStartLifecycleUpdate(const LocalFrameView& view) {
}
void DisplayLockContext::DidFinishLifecycleUpdate(const LocalFrameView& view) {
- if (acquire_resolver_) {
- FinishAcquireResolver(kResolve);
- // TODO(vmpstr): When size: auto is supported, we need to get the size from
- // the layout object here.
- // Fallthrough here in case we're already updating.
- }
-
if (state_ == kCommitting) {
FinishUpdateResolver(kResolve);
- FinishCommitResolver(kResolve);
- CancelTimeoutTask();
state_ = kUnlocked;
return;
}
@@ -855,10 +698,7 @@ void DisplayLockContext::DidFinishLifecycleUpdate(const LocalFrameView& view) {
FinishUpdateResolver(kReject, rejection_names::kElementIsDisconnected);
update_budget_.reset();
- if (commit_resolver_) {
- // We resolve the commit if we're not connected.
- FinishCommitResolver(kResolve);
- CancelTimeoutTask();
+ if (state_ == kCommitting) {
state_ = kUnlocked;
} else {
state_ = kLocked;
@@ -879,17 +719,6 @@ void DisplayLockContext::DidFinishLifecycleUpdate(const LocalFrameView& view) {
FinishUpdateResolver(kResolve);
update_budget_.reset();
state_ = kLocked;
-
- if (commit_resolver_) {
- // Schedule a commit to run. Note that we can't call StartCommit directly
- // here, since we're in the lifecycle updates right now and the code that
- // runs after may depend on having clean layout state, which StartCommit
- // might dirty.
- GetExecutionContext()
- ->GetTaskRunner(TaskType::kMiscPlatformAPI)
- ->PostTask(FROM_HERE, WTF::Bind(&DisplayLockContext::StartCommit,
- WrapWeakPersistent(this)));
- }
}
void DisplayLockContext::NotifyWillDisconnect() {
@@ -904,6 +733,14 @@ void DisplayLockContext::NotifyWillDisconnect() {
parent->SetNeedsLayout(layout_invalidation_reason::kDisplayLock);
}
+void DisplayLockContext::ElementDisconnected() {
+ UpdateActivationObservationIfNeeded();
+}
+
+void DisplayLockContext::ElementConnected() {
+ UpdateActivationObservationIfNeeded();
+}
+
void DisplayLockContext::ScheduleAnimation() {
DCHECK(element_);
// We could have posted a task to run ScheduleAnimation if we're updating.
@@ -921,33 +758,6 @@ void DisplayLockContext::ScheduleAnimation() {
document_->GetPage()->Animator().ScheduleVisualUpdate(document_->GetFrame());
}
-void DisplayLockContext::RescheduleTimeoutTask(double delay) {
- CancelTimeoutTask();
-
- if (!std::isfinite(delay))
- return;
-
- // Make sure the delay is at least 1ms.
- delay = std::max(delay, 1.);
- timeout_task_handle_ = PostDelayedCancellableTask(
- *GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI),
- FROM_HERE,
- WTF::Bind(&DisplayLockContext::TriggerTimeout, WrapWeakPersistent(this)),
- base::TimeDelta::FromMillisecondsD(delay));
-}
-
-void DisplayLockContext::CancelTimeoutTask() {
- timeout_task_handle_.Cancel();
-}
-
-void DisplayLockContext::TriggerTimeout() {
- // We might have started destroyed the element or started to shut down while
- // we're triggering a timeout. In that case, do nothing.
- if (!element_ || !document_ || !document_->Lifecycle().IsActive())
- return;
- StartCommit();
-}
-
const char* DisplayLockContext::ShouldForceUnlock() const {
DCHECK(element_);
// This function is only called after style, layout tree, or lifecycle
@@ -1011,10 +821,7 @@ bool DisplayLockContext::ForceUnlockIfNeeded() {
// commit() isn't in progress, the web author won't know that the element
// got unlocked. Figure out how to notify the author.
if (auto* reason = ShouldForceUnlock()) {
- FinishAcquireResolver(kReject, reason);
FinishUpdateResolver(kReject, reason);
- FinishCommitResolver(kReject, reason);
- CancelTimeoutTask();
state_ = kUnlocked;
return true;
}
@@ -1033,7 +840,7 @@ DisplayLockContext::ScopedForcedUpdate::ScopedForcedUpdate(
: context_(context) {}
DisplayLockContext::ScopedForcedUpdate::ScopedForcedUpdate(
- ScopedForcedUpdate&& other) noexcept
+ ScopedForcedUpdate&& other)
: context_(other.context_) {
other.context_ = nullptr;
}
@@ -1064,7 +871,8 @@ operator=(State new_state) {
"LockedDisplayLock", this);
}
- bool was_activatable = context_->IsActivatable();
+ bool was_activatable =
+ context_->IsActivatable(DisplayLockActivationReason::kAny);
bool was_locked = context_->IsLocked();
state_ = new_state;
@@ -1077,7 +885,9 @@ operator=(State new_state) {
if (!context_->document_)
return *this;
- UpdateActivationBlockingCount(was_activatable, context_->IsActivatable());
+ UpdateActivationBlockingCount(
+ was_activatable,
+ context_->IsActivatable(DisplayLockActivationReason::kAny));
// Adjust the total number of locked display locks.
auto& document = *context_->document_;
@@ -1088,6 +898,7 @@ operator=(State new_state) {
document.AddLockedDisplayLock();
}
+ context_->UpdateActivationObservationIfNeeded();
return *this;
}
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 518b162089d..0484345cceb 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
@@ -18,18 +18,33 @@ namespace blink {
class DisplayLockSuspendedHandle;
class Element;
-class DisplayLockOptions;
class DisplayLockScopedLogger;
-class TaskHandle;
enum class DisplayLockLifecycleTarget { kSelf, kChildren };
+enum class DisplayLockActivationReason {
+ // This represents activations triggered by intersection observer when the
+ // element intersects the viewport.
+ kViewport = 1 << 0,
+ // This represents activations triggered by script or user actions, such as
+ // find-in-page or scrollIntoView().
+ kUser = 1 << 1,
+ // This represents any activation, and should be result of all other flags
+ // combined.
+ kAny =
+ static_cast<unsigned char>(kViewport) | static_cast<unsigned char>(kUser)
+};
+
+// Instead of specifying an underlying type, which would propagate throughout
+// forward declarations, we static assert that the activation reasons enum is
+// small.
+static_assert(static_cast<int>(DisplayLockActivationReason::kAny) <
+ std::numeric_limits<unsigned char>::max(),
+ "DisplayLockActivationReason is too large");
class CORE_EXPORT DisplayLockContext final
- : public ScriptWrappable,
- public ActiveScriptWrappable<DisplayLockContext>,
+ : public GarbageCollected<DisplayLockContext>,
public ContextLifecycleObserver,
public LocalFrameView::LifecycleNotificationObserver {
- DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(DisplayLockContext);
USING_PRE_FINALIZER(DisplayLockContext, Dispose);
@@ -66,6 +81,7 @@ class CORE_EXPORT DisplayLockContext final
enum StyleType {
kStyleUpdateNotRequired,
kStyleUpdateSelf,
+ kStyleUpdatePseudoElements,
kStyleUpdateChildren,
kStyleUpdateDescendants
};
@@ -75,7 +91,7 @@ class CORE_EXPORT DisplayLockContext final
DISALLOW_NEW();
public:
- ScopedForcedUpdate(ScopedForcedUpdate&&) noexcept;
+ ScopedForcedUpdate(ScopedForcedUpdate&&);
~ScopedForcedUpdate();
private:
@@ -87,7 +103,7 @@ class CORE_EXPORT DisplayLockContext final
};
DisplayLockContext(Element*, ExecutionContext*);
- ~DisplayLockContext() override;
+ ~DisplayLockContext();
// GC functions.
void Trace(blink::Visitor*) override;
@@ -95,23 +111,16 @@ class CORE_EXPORT DisplayLockContext final
// ContextLifecycleObserver overrides.
void ContextDestroyed(ExecutionContext*) override;
- // ActiveScriptWrappable overrides. This keeps the context alive as long as we
- // have an element and we're not unlocked.
- bool HasPendingActivity() const final;
-
- // JavaScript interface implementation. See display_lock_context.idl for
- // description.
- ScriptPromise acquire(ScriptState*, DisplayLockOptions*);
- ScriptPromise update(ScriptState*);
- ScriptPromise commit(ScriptState*);
- ScriptPromise updateAndCommit(ScriptState*);
- void SetActivatable(bool activatable);
+ // Set which reasons activate, as a mask of DisplayLockActivationReason enums.
+ void SetActivatable(unsigned char activatable_mask);
// Acquire the lock, should only be called when unlocked.
void StartAcquire();
// Initiate a commit.
void StartCommit();
+ // Update rendering of the subtree.
+ ScriptPromise UpdateRendering(ScriptState*);
// Lifecycle observation / state functions.
bool ShouldStyle(DisplayLockLifecycleTarget) const;
@@ -130,14 +139,18 @@ class CORE_EXPORT DisplayLockContext final
}
// Returns true if the contents of the associated element should be visible
- // from and activatable by find-in-page, tab order, anchor links, etc.
- bool IsActivatable() const;
+ // from and activatable by a specified reason. Note that passing
+ // kAny will return true if the lock is activatable for any
+ // reason.
+ bool IsActivatable(DisplayLockActivationReason reason) const;
// Trigger commit because of activation from tab order, url fragment,
- // find-in-page, etc.
- void CommitForActivation();
+ // find-in-page, scrolling, etc.
+ // This issues a before activate signal with the given element as the
+ // activated element.
+ void CommitForActivationWithSignal(Element* activated_element);
- bool ShouldCommitForActivation() const;
+ bool ShouldCommitForActivation(DisplayLockActivationReason reason) const;
// Returns true if this lock is locked. Note from the outside perspective, the
// lock is locked any time the state is not kUnlocked or kCommitting.
@@ -189,6 +202,10 @@ class CORE_EXPORT DisplayLockContext final
// Notify this element will be disconnected.
void NotifyWillDisconnect();
+ // Called when the element disconnects or connects.
+ void ElementDisconnected();
+ void ElementConnected();
+
void SetNeedsPrePaintSubtreeWalk(
bool needs_effective_allowed_touch_action_update) {
needs_effective_allowed_touch_action_update_ =
@@ -196,15 +213,6 @@ class CORE_EXPORT DisplayLockContext final
needs_prepaint_subtree_walk_ = true;
}
- LayoutUnit GetLockedContentLogicalWidth() const {
- return is_horizontal_writing_mode_ ? locked_content_logical_size_.Width()
- : locked_content_logical_size_.Height();
- }
- LayoutUnit GetLockedContentLogicalHeight() const {
- return is_horizontal_writing_mode_ ? locked_content_logical_size_.Height()
- : locked_content_logical_size_.Width();
- }
-
private:
friend class DisplayLockContextTest;
friend class DisplayLockBudgetTest;
@@ -262,22 +270,11 @@ class CORE_EXPORT DisplayLockContext final
// frame.
void ScheduleAnimation();
- // Timeout implementation. When the lock is acquired, we kick off a timeout
- // task that will trigger a commit (which can be canceled by other calls to
- // schedule or by a call to commit). Note that calling RescheduleTimeoutTask()
- // will cancel any previously scheduled task.
- void RescheduleTimeoutTask(double delay);
- void CancelTimeoutTask();
- void TriggerTimeout();
-
// Helper functions to resolve the update/commit promises.
enum ResolverState { kResolve, kReject, kDetach };
void MakeResolver(ScriptState*, Member<ScriptPromiseResolver>*);
bool HasResolver();
void FinishUpdateResolver(ResolverState, const char* reject_reason = nullptr);
- void FinishCommitResolver(ResolverState, const char* reject_reason = nullptr);
- void FinishAcquireResolver(ResolverState,
- const char* reject_reason = nullptr);
void FinishResolver(Member<ScriptPromiseResolver>*,
ResolverState,
const char* reject_reason);
@@ -305,11 +302,15 @@ class CORE_EXPORT DisplayLockContext final
// promises if the lock is not connected to the tree.
bool CleanupAndRejectCommitIfNotConnected();
+ // Registers or unregisters the element for intersection observations in the
+ // document. This is used to activate on visibily changes. This can be safely
+ // called even if changes are not required, since it will only act if a
+ // register/unregister is required.
+ void UpdateActivationObservationIfNeeded();
+
std::unique_ptr<DisplayLockBudget> update_budget_;
- Member<ScriptPromiseResolver> commit_resolver_;
Member<ScriptPromiseResolver> update_resolver_;
- Member<ScriptPromiseResolver> acquire_resolver_;
WeakMember<Element> element_;
WeakMember<Document> document_;
@@ -323,12 +324,9 @@ class CORE_EXPORT DisplayLockContext final
HeapHashSet<Member<Element>> whitespace_reattach_set_;
StateChangeHelper state_;
- LayoutSize locked_content_logical_size_;
bool update_forced_ = false;
- bool activatable_ = false;
- bool is_locked_after_connect_ = false;
StyleType blocked_style_traversal_type_ = kStyleUpdateNotRequired;
// Signifies whether we've blocked a layout tree reattachment on |element_|'s
// descendants or not, so that we can mark |element_| for reattachment when
@@ -345,7 +343,12 @@ class CORE_EXPORT DisplayLockContext final
// traversed into, we will traverse to the children of the locked element.
bool child_layout_was_blocked_ = false;
- TaskHandle timeout_task_handle_;
+ // Tracks whether the element associated with this lock is being tracked by a
+ // document level intersection observer.
+ bool is_observed_ = false;
+
+ unsigned char activatable_mask_ =
+ static_cast<unsigned char>(DisplayLockActivationReason::kAny);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.idl b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.idl
deleted file mode 100644
index 00e9cebb513..00000000000
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.idl
+++ /dev/null
@@ -1,27 +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.
-
-[RuntimeEnabled=DisplayLocking, ActiveScriptWrappable]
-interface DisplayLockContext {
- // Acquires a display lock (possibly asynchronously) with the given options.
- // Returns a promise that resolves when the lock is acquired.
- [CallWith=ScriptState] Promise<any> acquire(optional DisplayLockOptions options);
-
- // Causes co-operative updates to happen on the locked subtree.
- // Returns a promise that resolves when the update is finished.
- [CallWith=ScriptState] Promise<any> update();
-
- // Commits the locked subtree, which releases the lock and updates any
- // necessary lifecycle phases.
- // Returns a promise that resolves when the commit is finished.
- [CallWith=ScriptState] Promise<any> commit();
-
- // Causes co-operative updates to happen, followed by a commit.
- // Returns a promise that resolves when the commit is finished.
- [CallWith=ScriptState] Promise<any> updateAndCommit();
-
- // Returns true if this context is locked. In other words, if true, then any
- // changes to the subtree of this element would not be reflected visually on screen.
- [ImplementedAs=IsLocked] readonly attribute boolean locked;
-};
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 2f8c5566ee7..e14278aecc4 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
@@ -11,7 +11,6 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
-#include "third_party/blink/renderer/core/display_lock/display_lock_options.h"
#include "third_party/blink/renderer/core/display_lock/strict_yielding_display_lock_budget.h"
#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -127,20 +126,23 @@ class DisplayLockContextTest : public testing::Test,
test::RunPendingTasks();
}
- void LockElement(Element& element, bool activatable) {
- DisplayLockOptions options;
- options.setActivatable(activatable);
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element.getDisplayLockForBindings()->acquire(script_state, &options);
- UpdateAllLifecyclePhasesForTest();
+ void LockElement(Element& element,
+ bool activatable,
+ bool update_lifecycle = true) {
+ StringBuilder value;
+ value.Append("invisible");
+ if (!activatable)
+ value.Append(" skip-activation");
+ element.setAttribute(html_names::kRendersubtreeAttr,
+ value.ToAtomicString());
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
}
- void CommitElement(Element& element) {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element.getDisplayLockForBindings()->commit(script_state);
- UpdateAllLifecyclePhasesForTest();
+ void CommitElement(Element& element, bool update_lifecycle = true) {
+ element.setAttribute(html_names::kRendersubtreeAttr, "");
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
}
bool GraphicsLayerNeedsCollection(DisplayLockContext* context) const {
@@ -188,11 +190,7 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
)HTML");
auto* element = GetDocument().getElementById("container");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*element, false, false);
// Finished acquiring the lock.
// Note that because the element is locked after append, the "self" phase for
@@ -220,10 +218,7 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
EXPECT_EQ(
element->GetComputedStyle()->VisitedDependentColor(GetCSSPropertyColor()),
MakeRGB(255, 0, 0));
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->commit(script_state);
- }
+ CommitElement(*element, false);
auto* child = GetDocument().getElementById("child");
EXPECT_TRUE(GetDocument().body()->ChildNeedsStyleRecalc());
EXPECT_TRUE(element->NeedsStyleRecalc());
@@ -237,11 +232,7 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
EXPECT_FALSE(child->NeedsStyleRecalc());
// Re-acquire.
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element, false);
// If a child is dirty, it will still be dirty.
child->setAttribute("style", "color: blue;");
@@ -261,12 +252,11 @@ TEST_F(DisplayLockContextTest, LockAfterAppendStyleDirtyBits) {
child->GetComputedStyle()->VisitedDependentColor(GetCSSPropertyColor()),
MakeRGB(0, 0, 255));
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->commit(script_state);
- }
+ CommitElement(*element, false);
EXPECT_TRUE(GetDocument().body()->ChildNeedsStyleRecalc());
- EXPECT_FALSE(element->NeedsStyleRecalc());
+ // Since the rendersubtree attribute changes, it will force self style to put
+ // in proper containment in place.
+ EXPECT_TRUE(element->NeedsStyleRecalc());
EXPECT_TRUE(element->ChildNeedsStyleRecalc());
EXPECT_TRUE(child->NeedsStyleRecalc());
UpdateAllLifecyclePhasesForTest();
@@ -517,27 +507,29 @@ TEST_F(DisplayLockContextTest,
auto* div_two = GetDocument().getElementById("two");
auto* div_three = GetDocument().getElementById("three");
// Lock three divs, make #div_two non-activatable.
- LockElement(*div_one, true /* activatable */);
- LockElement(*div_two, false /* activatable */);
+ LockElement(*div_one, true /* activatable */, false /* update_lifecycle */);
+ LockElement(*div_two, false /* activatable */, false /* update_lifecycle */);
LockElement(*div_three, true /* activatable */);
DisplayLockTestFindInPageClient client;
client.SetFrame(LocalMainFrame());
WebString search_text(String("result"));
+ auto text_rect = [](Element* element) {
+ return ComputeTextRect(EphemeralRange::RangeOfContents(*element));
+ };
+
// Find result in #one.
Find(search_text, client);
EXPECT_EQ(2, client.Count());
EXPECT_EQ(1, client.ActiveIndex());
- EphemeralRange range_one = EphemeralRange::RangeOfContents(*div_one);
- EXPECT_EQ(ComputeTextRect(range_one), client.ActiveMatchRect());
+ EXPECT_EQ(text_rect(div_one), client.ActiveMatchRect());
// Going forward from #one would go to #three.
Find(search_text, client, true /* find_next */);
EXPECT_EQ(2, client.Count());
EXPECT_EQ(2, client.ActiveIndex());
- EphemeralRange range_three = EphemeralRange::RangeOfContents(*div_three);
- EXPECT_EQ(ComputeTextRect(range_three), client.ActiveMatchRect());
+ EXPECT_EQ(text_rect(div_three), client.ActiveMatchRect());
// Going backwards from #three would go to #one.
client.Reset();
@@ -547,7 +539,7 @@ TEST_F(DisplayLockContextTest,
test::RunPendingTasks();
EXPECT_EQ(2, client.Count());
EXPECT_EQ(1, client.ActiveIndex());
- EXPECT_EQ(ComputeTextRect(range_one), client.ActiveMatchRect());
+ EXPECT_EQ(text_rect(div_one), client.ActiveMatchRect());
}
TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChange) {
@@ -563,12 +555,7 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChange) {
<body><div id="container"><b>t</b>esting</div></body>
)HTML");
auto* element = GetDocument().getElementById("container");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element, false);
// Sanity checks to ensure the element is locked.
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
@@ -615,12 +602,9 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChange) {
EXPECT_FALSE(element->NeedsReattachLayoutTree());
EXPECT_FALSE(element->ChildNeedsReattachLayoutTree());
- {
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->commit(script_state);
- }
-
- EXPECT_FALSE(element->NeedsStyleRecalc());
+ CommitElement(*element, false);
+ // Since containment may change, we need self style recalc.
+ EXPECT_TRUE(element->NeedsStyleRecalc());
EXPECT_TRUE(element->ChildNeedsStyleRecalc());
EXPECT_FALSE(element->NeedsReattachLayoutTree());
EXPECT_FALSE(element->ChildNeedsReattachLayoutTree());
@@ -631,7 +615,8 @@ TEST_F(DisplayLockContextTest, CallUpdateStyleAndLayoutAfterChange) {
element->GetDisplayLockContext()->DidStyle(
DisplayLockLifecycleTarget::kChildren);
- EXPECT_FALSE(element->NeedsStyleRecalc());
+ // Self style still needs updating.
+ EXPECT_TRUE(element->NeedsStyleRecalc());
EXPECT_FALSE(element->ChildNeedsStyleRecalc());
EXPECT_FALSE(element->NeedsReattachLayoutTree());
EXPECT_TRUE(element->ChildNeedsReattachLayoutTree());
@@ -662,13 +647,7 @@ TEST_F(DisplayLockContextTest, LockedElementAndDescendantsAreNotFocusable) {
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
auto* element = GetDocument().getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element, false);
// Sanity checks to ensure the element is locked.
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
@@ -691,11 +670,7 @@ TEST_F(DisplayLockContextTest, LockedElementAndDescendantsAreNotFocusable) {
EXPECT_FALSE(GetDocument().FocusedElement());
// Now commit the lock and ensure we can focus the input
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->commit(script_state);
- }
+ CommitElement(*element, false);
EXPECT_TRUE(element->GetDisplayLockContext()->ShouldStyle(
DisplayLockLifecycleTarget::kChildren));
@@ -731,8 +706,10 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
auto* host = GetDocument().getElementById("shadowHost");
auto* slotted = GetDocument().getElementById("slotted");
- ASSERT_FALSE(host->DisplayLockPreventsActivation());
- ASSERT_FALSE(slotted->DisplayLockPreventsActivation());
+ ASSERT_FALSE(
+ host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
+ ASSERT_FALSE(slotted->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
ShadowRoot& shadow_root =
host->AttachShadowRootInternal(ShadowRootType::kOpen);
@@ -742,44 +719,49 @@ TEST_F(DisplayLockContextTest, DisplayLockPreventsActivation) {
UpdateAllLifecyclePhasesForTest();
auto* container = shadow_root.getElementById("container");
- EXPECT_FALSE(host->DisplayLockPreventsActivation());
- EXPECT_FALSE(container->DisplayLockPreventsActivation());
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation());
+ EXPECT_FALSE(
+ host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(container->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- container->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ LockElement(*container, false, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
- EXPECT_FALSE(host->DisplayLockPreventsActivation());
- EXPECT_TRUE(container->DisplayLockPreventsActivation());
- EXPECT_TRUE(slotted->DisplayLockPreventsActivation());
+ EXPECT_FALSE(
+ host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
+ EXPECT_TRUE(container->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
+ EXPECT_TRUE(slotted->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
// Ensure that we resolve the acquire callback, thus finishing the acquire
// step.
UpdateAllLifecyclePhasesForTest();
- {
- ScriptState::Scope scope(script_state);
- container->getDisplayLockForBindings()->commit(script_state);
- }
+ CommitElement(*container, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_FALSE(host->DisplayLockPreventsActivation());
- EXPECT_FALSE(container->DisplayLockPreventsActivation());
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation());
+ EXPECT_FALSE(
+ host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(container->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
UpdateAllLifecyclePhasesForTest();
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_FALSE(host->DisplayLockPreventsActivation());
- EXPECT_FALSE(container->DisplayLockPreventsActivation());
- EXPECT_FALSE(slotted->DisplayLockPreventsActivation());
+ EXPECT_FALSE(
+ host->DisplayLockPreventsActivation(DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(container->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
+ EXPECT_FALSE(slotted->DisplayLockPreventsActivation(
+ DisplayLockActivationReason::kAny));
}
TEST_F(DisplayLockContextTest,
@@ -807,13 +789,7 @@ TEST_F(DisplayLockContextTest,
ASSERT_TRUE(text_field->IsFocusable());
auto* element = shadow_root.getElementById("container");
- {
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*element, false);
// Sanity checks to ensure the element is locked.
EXPECT_FALSE(element->GetDisplayLockContext()->ShouldStyle(
@@ -860,67 +836,36 @@ TEST_F(DisplayLockContextTest, LockedCountsWithMultipleLocks) {
auto* two = GetDocument().getElementById("two");
auto* three = GetDocument().getElementById("three");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- one->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*one, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
- {
- ScriptState::Scope scope(script_state);
- two->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*two, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 2);
- {
- ScriptState::Scope scope(script_state);
- three->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*three, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 3);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 3);
// Now commit the inner lock.
- {
- ScriptState::Scope scope(script_state);
- two->getDisplayLockForBindings()->commit(script_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*two);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 2);
// Commit the outer lock.
- {
- ScriptState::Scope scope(script_state);
- one->getDisplayLockForBindings()->commit(script_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*one);
// Both inner and outer locks should have committed.
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
// Commit the sibling lock.
- {
- ScriptState::Scope scope(script_state);
- three->getDisplayLockForBindings()->commit(script_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*three);
// Both inner and outer locks should have committed.
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
@@ -949,71 +894,45 @@ TEST_F(DisplayLockContextTest, ActivatableNotCountedAsBlocking) {
auto* activatable = GetDocument().getElementById("activatable");
auto* non_activatable = GetDocument().getElementById("nonActivatable");
- DisplayLockOptions activatable_options;
- activatable_options.setActivatable(true);
-
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- activatable->getDisplayLockForBindings()->acquire(script_state,
- &activatable_options);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*activatable, true);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable());
-
- {
- ScriptState::Scope scope(script_state);
- non_activatable->getDisplayLockForBindings()->acquire(script_state,
- nullptr);
- }
+ EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*non_activatable, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
- EXPECT_FALSE(non_activatable->GetDisplayLockContext()->IsActivatable());
+ EXPECT_FALSE(non_activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
// Now commit the lock for |non_ctivatable|.
- {
- ScriptState::Scope scope(script_state);
- non_activatable->getDisplayLockForBindings()->commit(script_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*non_activatable);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable());
- EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable());
+ EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
+ EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
// Re-acquire the lock for |activatable|, but without the activatable flag.
- {
- ScriptState::Scope scope(script_state);
- activatable->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*activatable, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
- EXPECT_FALSE(activatable->GetDisplayLockContext()->IsActivatable());
+ EXPECT_FALSE(activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
// Re-acquire the lock for |activatable| again with the activatable flag.
- {
- ScriptState::Scope scope(script_state);
- activatable->getDisplayLockForBindings()->acquire(script_state,
- &activatable_options);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*activatable, true);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable());
+ EXPECT_TRUE(activatable->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny));
}
TEST_F(DisplayLockContextTest, ElementInTemplate) {
@@ -1045,63 +964,43 @@ TEST_F(DisplayLockContextTest, ElementInTemplate) {
ToHTMLTemplateElement(GetDocument().getElementById("template"));
auto* child = To<Element>(template_el->content()->firstChild());
EXPECT_FALSE(child->isConnected());
- ASSERT_TRUE(child->getDisplayLockForBindings());
// Try to lock an element in a template.
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- child->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*child, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_TRUE(child->getDisplayLockForBindings()->IsLocked());
+ EXPECT_TRUE(child->GetDisplayLockContext()->IsLocked());
// commit() will unlock the element.
- {
- ScriptState::Scope scope(script_state);
- child->getDisplayLockForBindings()->commit(script_state);
- }
- UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(child->getDisplayLockForBindings()->IsLocked());
+ CommitElement(*child);
+ EXPECT_FALSE(child->GetDisplayLockContext()->IsLocked());
// Try to lock an element that was moved from a template to a document.
auto* document_child =
To<Element>(GetDocument().adoptNode(child, ASSERT_NO_EXCEPTION));
- GetDocument().getElementById("container")->appendChild(document_child);
-
- {
- ScriptState::Scope scope(script_state);
- document_child->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
+ auto* container = GetDocument().getElementById("container");
+ container->appendChild(document_child);
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*document_child, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 1);
- EXPECT_TRUE(document_child->getDisplayLockForBindings()->IsLocked());
+ EXPECT_TRUE(document_child->GetDisplayLockContext()->IsLocked());
- GetDocument()
- .getElementById("container")
- ->setAttribute("style", "display: block;");
+ container->setAttribute("style", "display: block;");
document_child->setAttribute("style", "color: red;");
- EXPECT_TRUE(document_child->NeedsStyleRecalc());
+ EXPECT_TRUE(container->NeedsStyleRecalc());
+ EXPECT_FALSE(document_child->NeedsStyleRecalc());
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(document_child->NeedsStyleRecalc());
// commit() will unlock the element and update the style.
- {
- ScriptState::Scope scope(script_state);
- document_child->getDisplayLockForBindings()->commit(script_state);
- }
- UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(document_child->getDisplayLockForBindings()->IsLocked());
+ CommitElement(*document_child);
+ EXPECT_FALSE(document_child->GetDisplayLockContext()->IsLocked());
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
@@ -1147,13 +1046,7 @@ TEST_F(DisplayLockContextTest, AncestorAllowedTouchAction) {
auto* locked_element = GetDocument().getElementById("locked");
auto* lockedchild_element = GetDocument().getElementById("lockedchild");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- locked_element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*locked_element, false);
EXPECT_TRUE(locked_element->GetDisplayLockContext()->IsLocked());
auto* ancestor_object = ancestor_element->GetLayoutObject();
@@ -1220,10 +1113,7 @@ TEST_F(DisplayLockContextTest, AncestorAllowedTouchAction) {
EXPECT_TRUE(locked_object->InsideBlockingTouchEventHandler());
EXPECT_FALSE(lockedchild_object->InsideBlockingTouchEventHandler());
- {
- ScriptState::Scope scope(script_state);
- locked_element->GetDisplayLockContext()->commit(script_state);
- }
+ CommitElement(*locked_element, false);
EXPECT_FALSE(ancestor_object->EffectiveAllowedTouchActionChanged());
EXPECT_FALSE(handler_object->EffectiveAllowedTouchActionChanged());
@@ -1290,13 +1180,7 @@ TEST_F(DisplayLockContextTest, DescendantAllowedTouchAction) {
auto* locked_element = GetDocument().getElementById("locked");
auto* handler_element = GetDocument().getElementById("handler");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- locked_element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*locked_element, false);
EXPECT_TRUE(locked_element->GetDisplayLockContext()->IsLocked());
auto* ancestor_object = ancestor_element->GetLayoutObject();
@@ -1370,10 +1254,7 @@ TEST_F(DisplayLockContextTest, DescendantAllowedTouchAction) {
EXPECT_FALSE(locked_object->InsideBlockingTouchEventHandler());
EXPECT_FALSE(handler_object->InsideBlockingTouchEventHandler());
- {
- ScriptState::Scope scope(script_state);
- locked_element->GetDisplayLockContext()->commit(script_state);
- }
+ CommitElement(*locked_element, false);
EXPECT_FALSE(ancestor_object->EffectiveAllowedTouchActionChanged());
EXPECT_FALSE(descendant_object->EffectiveAllowedTouchActionChanged());
@@ -1434,7 +1315,7 @@ TEST_F(DisplayLockContextTest,
auto* container = GetDocument().getElementById("container");
// Ensure that we will gather graphics layer on the next update (after lock).
- GetDocument().View()->GraphicsLayersDidChange();
+ GetDocument().View()->SetForeignLayerListNeedsUpdate();
LockElement(*container, false /* activatable */);
EXPECT_TRUE(container->GetDisplayLockContext()->IsLocked());
@@ -1468,13 +1349,7 @@ TEST_F(DisplayLockContextTest, DescendantNeedsPaintPropertyUpdateBlocked) {
auto* locked_element = GetDocument().getElementById("locked");
auto* handler_element = GetDocument().getElementById("handler");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- {
- ScriptState::Scope scope(script_state);
- locked_element->getDisplayLockForBindings()->acquire(script_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*locked_element, false);
EXPECT_TRUE(locked_element->GetDisplayLockContext()->IsLocked());
auto* ancestor_object = ancestor_element->GetLayoutObject();
@@ -1529,10 +1404,7 @@ TEST_F(DisplayLockContextTest, DescendantNeedsPaintPropertyUpdateBlocked) {
EXPECT_TRUE(locked_object->DescendantNeedsPaintPropertyUpdate());
EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
- {
- ScriptState::Scope scope(script_state);
- locked_element->GetDisplayLockContext()->commit(script_state);
- }
+ CommitElement(*locked_element, false);
EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
@@ -1581,7 +1453,7 @@ TEST_F(DisplayLockContextTest, DisconnectedWhileUpdating) {
auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
{
ScriptState::Scope scope(script_state);
- container->GetDisplayLockContext()->update(script_state);
+ container->GetDisplayLockContext()->UpdateRendering(script_state);
}
auto budget = base::WrapUnique(
new StrictYieldingDisplayLockBudget(container->GetDisplayLockContext()));
@@ -1637,10 +1509,7 @@ TEST_F(DisplayLockContextRenderingTest, FrameDocumentRemovedWhileAcquire) {
auto* target = ChildDocument().getElementById("target");
GetDocument().getElementById("frame")->remove();
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
- ScriptState::Scope scope(script_state);
- DisplayLockOptions options;
- target->getDisplayLockForBindings()->acquire(script_state, &options);
+ target->EnsureDisplayLockContext().StartAcquire();
}
TEST_F(DisplayLockContextRenderingTest,
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_options.idl b/chromium/third_party/blink/renderer/core/display_lock/display_lock_options.idl
deleted file mode 100644
index 098d2b66618..00000000000
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_options.idl
+++ /dev/null
@@ -1,10 +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.
-
-dictionary DisplayLockOptions {
- unrestricted double timeout;
- boolean activatable = false;
- sequence<double> size;
-};
-
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 47c69cb5c33..7de9a7d4fa7 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
@@ -28,11 +28,38 @@ const Node* GetFrameOwnerNode(const Node* child) {
return child->GetDocument().GetFrame()->OwnerLayoutObject()->GetNode();
}
+bool UpdateStyleAndLayoutForRangeIfNeeded(const EphemeralRangeInFlatTree& range,
+ DisplayLockActivationReason reason) {
+ if (range.IsNull() || range.IsCollapsed())
+ return false;
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()) ||
+ range.GetDocument().LockedDisplayLockCount() ==
+ range.GetDocument().ActivationBlockingDisplayLockCount())
+ return false;
+ Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_;
+ for (Node& node : range.Nodes()) {
+ for (Element* locked_activatable_ancestor :
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(node,
+ reason)) {
+ DCHECK(locked_activatable_ancestor->GetDisplayLockContext());
+ DCHECK(locked_activatable_ancestor->GetDisplayLockContext()->IsLocked());
+ if (locked_activatable_ancestor->GetDisplayLockContext()->UpdateForced())
+ break;
+ scoped_forced_update_list_.push_back(
+ locked_activatable_ancestor->GetDisplayLockContext()
+ ->GetScopedForcedUpdate());
+ }
+ }
+ if (!scoped_forced_update_list_.IsEmpty())
+ range.GetDocument().UpdateStyleAndLayout();
+ return !scoped_forced_update_list_.IsEmpty();
+}
+
} // namespace
bool DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()))
return false;
DCHECK(!range.IsNull());
DCHECK(!range.IsCollapsed());
@@ -49,18 +76,20 @@ bool DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(
DCHECK(enclosing_block);
DCHECK_EQ(enclosing_block,
EnclosingBlock(range.EndPosition(), kCannotCrossEditingBoundary));
- return enclosing_block->ActivateDisplayLockIfNeeded();
+ return enclosing_block->ActivateDisplayLockIfNeeded(
+ DisplayLockActivationReason::kUser);
}
bool DisplayLockUtilities::ActivateSelectionRangeIfNeeded(
const EphemeralRangeInFlatTree& range) {
if (range.IsNull() || range.IsCollapsed())
return false;
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&range.GetDocument()) ||
range.GetDocument().LockedDisplayLockCount() ==
range.GetDocument().ActivationBlockingDisplayLockCount())
return false;
- UpdateStyleAndLayoutForRangeIfNeeded(range);
+ UpdateStyleAndLayoutForRangeIfNeeded(range,
+ DisplayLockActivationReason::kUser);
HeapHashSet<Member<Element>> elements_to_activate;
for (Node& node : range.Nodes()) {
DCHECK(!node.GetDocument().NeedsLayoutTreeUpdateForNode(node));
@@ -70,42 +99,21 @@ bool DisplayLockUtilities::ActivateSelectionRangeIfNeeded(
if (auto* nearest_locked_ancestor = NearestLockedExclusiveAncestor(node))
elements_to_activate.insert(nearest_locked_ancestor);
}
- for (Element* element : elements_to_activate)
- element->ActivateDisplayLockIfNeeded();
- return !elements_to_activate.IsEmpty();
-}
-
-bool DisplayLockUtilities::UpdateStyleAndLayoutForRangeIfNeeded(
- const EphemeralRangeInFlatTree& range) {
- if (range.IsNull() || range.IsCollapsed())
- return false;
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
- range.GetDocument().LockedDisplayLockCount() ==
- range.GetDocument().ActivationBlockingDisplayLockCount())
- return false;
- Vector<DisplayLockContext::ScopedForcedUpdate> scoped_forced_update_list_;
- for (Node& node : range.Nodes()) {
- for (Element* locked_activatable_ancestor :
- ActivatableLockedInclusiveAncestors(node)) {
- DCHECK(locked_activatable_ancestor->GetDisplayLockContext());
- DCHECK(locked_activatable_ancestor->GetDisplayLockContext()->IsLocked());
- if (locked_activatable_ancestor->GetDisplayLockContext()->UpdateForced())
- break;
- scoped_forced_update_list_.push_back(
- locked_activatable_ancestor->GetDisplayLockContext()
- ->GetScopedForcedUpdate());
- }
+ for (Element* element : elements_to_activate) {
+ element->ActivateDisplayLockIfNeeded(
+ DisplayLockActivationReason::kViewport);
}
- if (!scoped_forced_update_list_.IsEmpty())
- range.GetDocument().UpdateStyleAndLayout();
- return !scoped_forced_update_list_.IsEmpty();
+ return !elements_to_activate.IsEmpty();
}
const HeapVector<Member<Element>>
-DisplayLockUtilities::ActivatableLockedInclusiveAncestors(const Node& node) {
+DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ const Node& node,
+ DisplayLockActivationReason reason) {
HeapVector<Member<Element>> elements_to_activate;
const_cast<Node*>(&node)->UpdateDistributionForFlatTreeTraversal();
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
node.GetDocument().LockedDisplayLockCount() ==
node.GetDocument().ActivationBlockingDisplayLockCount())
return elements_to_activate;
@@ -117,7 +125,7 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(const Node& node) {
if (auto* context = ancestor_element->GetDisplayLockContext()) {
if (!context->IsLocked())
continue;
- if (!context->IsActivatable()) {
+ if (!context->IsActivatable(reason)) {
// If we find a non-activatable locked ancestor, then we shouldn't
// activate anything.
elements_to_activate.clear();
@@ -132,7 +140,8 @@ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(const Node& node) {
DisplayLockUtilities::ScopedChainForcedUpdate::ScopedChainForcedUpdate(
const Node* node,
bool include_self) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node->GetExecutionContext()))
return;
CreateParentFrameScopeIfNeeded(node);
@@ -188,8 +197,9 @@ const Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(
auto* element = DynamicTo<Element>(node);
if (!element)
return NearestLockedExclusiveAncestor(node);
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || !node.isConnected() ||
- node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
+ !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -207,8 +217,9 @@ Element* DisplayLockUtilities::NearestLockedInclusiveAncestor(Node& node) {
Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() || !node.isConnected() ||
- node.GetDocument().LockedDisplayLockCount() == 0 ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
+ !node.isConnected() || node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
}
@@ -229,7 +240,8 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -250,7 +262,8 @@ Element* DisplayLockUtilities::HighestLockedInclusiveAncestor(
Element* DisplayLockUtilities::HighestLockedExclusiveAncestor(
const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
return nullptr;
@@ -284,7 +297,8 @@ Element* DisplayLockUtilities::NearestLockedExclusiveAncestor(
}
bool DisplayLockUtilities::IsInNonActivatableLockedSubtree(const Node& node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ node.GetExecutionContext()) ||
node.GetDocument().LockedDisplayLockCount() == 0 ||
node.GetDocument().ActivationBlockingDisplayLockCount() == 0 ||
!node.CanParticipateInFlatTree()) {
@@ -293,15 +307,18 @@ bool DisplayLockUtilities::IsInNonActivatableLockedSubtree(const Node& node) {
for (auto* element = NearestLockedExclusiveAncestor(node); element;
element = NearestLockedExclusiveAncestor(*element)) {
- if (!element->GetDisplayLockContext()->IsActivatable())
+ if (!element->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kAny)) {
return true;
+ }
}
return false;
}
bool DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(
const Node& source_node) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ source_node.GetExecutionContext()))
return false;
const Node* node = &source_node;
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 ca23fa3fea7..b9b4bf33c23 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
@@ -44,17 +44,13 @@ class CORE_EXPORT DisplayLockUtilities {
static bool ActivateSelectionRangeIfNeeded(
const EphemeralRangeInFlatTree& range);
- // Updates style for all locked nodes in |range|. Returns true if there's at
- // least one locked node encountered.
- static bool UpdateStyleAndLayoutForRangeIfNeeded(
- const EphemeralRangeInFlatTree& range);
-
// Returns activatable-locked inclusive ancestors of |node|.
// Note that this function will return an empty list if |node| is inside a
// non-activatable locked subtree (e.g. at least one ancestor is not
// activatable-locked).
static const HeapVector<Member<Element>> ActivatableLockedInclusiveAncestors(
- const Node& node);
+ const Node& node,
+ DisplayLockActivationReason reason);
// Returns the nearest inclusive ancestor of |node| that is display locked.
static const Element* NearestLockedInclusiveAncestor(const Node& node);
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
index e34792f2787..154a07eb585 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_utilities_test.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
-#include "third_party/blink/renderer/core/display_lock/display_lock_options.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -20,6 +19,25 @@ class DisplayLockUtilitiesTest : public RenderingTest,
DisplayLockUtilitiesTest()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
ScopedDisplayLockingForTest(true) {}
+
+ void LockElement(Element& element,
+ bool activatable,
+ bool update_lifecycle = true) {
+ StringBuilder value;
+ value.Append("invisible");
+ if (!activatable)
+ value.Append(" skip-activation");
+ element.setAttribute(html_names::kRendersubtreeAttr,
+ value.ToAtomicString());
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ void CommitElement(Element& element, bool update_lifecycle = true) {
+ element.setAttribute(html_names::kRendersubtreeAttr, "");
+ if (update_lifecycle)
+ UpdateAllLifecyclePhasesForTest();
+ }
};
TEST_F(DisplayLockUtilitiesTest, ActivatableLockedInclusiveAncestors) {
@@ -50,108 +68,101 @@ TEST_F(DisplayLockUtilitiesTest, ActivatableLockedInclusiveAncestors) {
shadow_root.SetInnerHTMLFromString("<div id='shadowDiv'>shadow!</div>");
Element& shadow_div = *shadow_root.getElementById("shadowDiv");
- auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
-
- DisplayLockOptions options;
- options.setActivatable(true);
- // Lock outer with activatable flag.
- {
- ScriptState::Scope scope(script_state);
- outer.getDisplayLockForBindings()->acquire(script_state, &options);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(outer, true);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 1);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
// Querying from every element gives |outer|.
HeapVector<Member<Element>> result_for_outer =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(outer);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ outer, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_outer.size(), 1u);
EXPECT_EQ(result_for_outer.at(0), outer);
HeapVector<Member<Element>> result_for_inner_a =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_a);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_a, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_inner_a.size(), 1u);
EXPECT_EQ(result_for_inner_a.at(0), outer);
HeapVector<Member<Element>> result_for_innermost =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(innermost);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ innermost, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_innermost.size(), 1u);
EXPECT_EQ(result_for_innermost.at(0), outer);
HeapVector<Member<Element>> result_for_inner_b =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_b);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_b, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_inner_b.size(), 1u);
EXPECT_EQ(result_for_inner_b.at(0), outer);
HeapVector<Member<Element>> result_for_shadow_div =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(shadow_div);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ shadow_div, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_shadow_div.size(), 1u);
EXPECT_EQ(result_for_shadow_div.at(0), outer);
// Lock innermost with activatable flag.
- {
- ScriptState::Scope scope(script_state);
- innermost.getDisplayLockForBindings()->acquire(script_state, &options);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(innermost, true);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 2);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- result_for_outer =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(outer);
+ result_for_outer = DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ outer, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_outer.size(), 1u);
EXPECT_EQ(result_for_outer.at(0), outer);
result_for_inner_a =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_a);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_a, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_inner_a.size(), 1u);
EXPECT_EQ(result_for_inner_a.at(0), outer);
result_for_innermost =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(innermost);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ innermost, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_innermost.size(), 2u);
EXPECT_EQ(result_for_innermost.at(0), innermost);
EXPECT_EQ(result_for_innermost.at(1), outer);
result_for_inner_b =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_b);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_b, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_inner_b.size(), 1u);
EXPECT_EQ(result_for_inner_b.at(0), outer);
result_for_shadow_div =
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(shadow_div);
+ DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ shadow_div, DisplayLockActivationReason::kAny);
EXPECT_EQ(result_for_shadow_div.size(), 1u);
EXPECT_EQ(result_for_shadow_div.at(0), outer);
// Unlock everything.
- {
- ScriptState::Scope scope(script_state);
- innermost.getDisplayLockForBindings()->commit(script_state);
- outer.getDisplayLockForBindings()->commit(script_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(innermost, false);
+ CommitElement(outer);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(GetDocument().ActivationBlockingDisplayLockCount(), 0);
- EXPECT_EQ(
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(outer).size(),
- 0u);
- EXPECT_EQ(
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_a).size(),
- 0u);
- EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(innermost)
+ EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ outer, DisplayLockActivationReason::kAny)
+ .size(),
+ 0u);
+ EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_a, DisplayLockActivationReason::kAny)
+ .size(),
+ 0u);
+ EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ innermost, DisplayLockActivationReason::kAny)
+ .size(),
+ 0u);
+ EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ inner_b, DisplayLockActivationReason::kAny)
+ .size(),
+ 0u);
+ EXPECT_EQ(DisplayLockUtilities::ActivatableLockedInclusiveAncestors(
+ shadow_div, DisplayLockActivationReason::kAny)
.size(),
0u);
- EXPECT_EQ(
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(inner_b).size(),
- 0u);
- EXPECT_EQ(
- DisplayLockUtilities::ActivatableLockedInclusiveAncestors(shadow_div)
- .size(),
- 0u);
}
TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
@@ -187,18 +198,8 @@ TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
ASSERT_TRUE(parent);
ASSERT_TRUE(child);
- auto* child_frame_state =
- ToScriptStateForMainWorld(ChildDocument().GetFrame());
- auto* parent_frame_state =
- ToScriptStateForMainWorld(GetDocument().GetFrame());
-
// Lock parent.
- {
- ScriptState::Scope scope(child_frame_state);
- parent->getDisplayLockForBindings()->acquire(child_frame_state, nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*parent, false);
EXPECT_EQ(GetDocument().LockedDisplayLockCount(), 0);
EXPECT_EQ(ChildDocument().LockedDisplayLockCount(), 1);
@@ -209,13 +210,7 @@ TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
EXPECT_TRUE(DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*child));
// Lock grandparent.
- {
- ScriptState::Scope scope(parent_frame_state);
- grandparent->getDisplayLockForBindings()->acquire(parent_frame_state,
- nullptr);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ LockElement(*grandparent, false);
EXPECT_FALSE(
DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*grandparent));
@@ -223,12 +218,7 @@ TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
EXPECT_TRUE(DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*child));
// Unlock parent.
- {
- ScriptState::Scope scope(child_frame_state);
- parent->getDisplayLockForBindings()->commit(child_frame_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*parent);
EXPECT_FALSE(
DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*grandparent));
@@ -236,12 +226,7 @@ TEST_F(DisplayLockUtilitiesTest, LockedSubtreeCrossingFrames) {
EXPECT_TRUE(DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*child));
// Unlock grandparent.
- {
- ScriptState::Scope scope(parent_frame_state);
- grandparent->getDisplayLockForBindings()->commit(parent_frame_state);
- }
-
- UpdateAllLifecyclePhasesForTest();
+ CommitElement(*grandparent);
EXPECT_FALSE(
DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*grandparent));
diff --git a/chromium/third_party/blink/renderer/core/dom/BUILD.gn b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
index 394115bfa0f..76061e82074 100644
--- a/chromium/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
@@ -5,8 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("dom") {
- split_count = 5
-
sources = [
"abort_controller.cc",
"abort_controller.h",
diff --git a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
index 4cf3cdcbaaa..59db0f1c100 100644
--- a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
+++ b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
@@ -17,8 +17,10 @@
[CEReactions, Reflect=aria_colindex] attribute DOMString? ariaColIndex;
[CEReactions, Reflect=aria_colspan] attribute DOMString? ariaColSpan;
[CEReactions, Reflect=aria_controls] attribute DOMString? ariaControls;
+ [CEReactions, Reflect=aria_controls] attribute FrozenArray<Element>? ariaControlsElements;
[CEReactions, Reflect=aria_current] attribute DOMString? ariaCurrent;
[CEReactions, Reflect=aria_describedby] attribute DOMString? ariaDescribedBy;
+ [CEReactions, Reflect=aria_describedby] attribute FrozenArray<Element>? ariaDescribedByElements;
[CEReactions, Reflect=aria_details] attribute DOMString? ariaDetails;
[CEReactions, Reflect=aria_details] attribute Element? ariaDetailsElement;
[CEReactions, Reflect=aria_disabled] attribute DOMString? ariaDisabled;
@@ -26,11 +28,13 @@
[CEReactions, Reflect=aria_errormessage] attribute Element? ariaErrorMessageElement;
[CEReactions, Reflect=aria_expanded] attribute DOMString? ariaExpanded;
[CEReactions, Reflect=aria_flowto] attribute DOMString? ariaFlowTo;
+ [CEReactions, Reflect=aria_flowto] attribute FrozenArray<Element>? ariaFlowToElements;
[CEReactions, Reflect=aria_haspopup] attribute DOMString? ariaHasPopup;
[CEReactions, Reflect=aria_hidden] attribute DOMString? ariaHidden;
[CEReactions, Reflect=aria_keyshortcuts] attribute DOMString? ariaKeyShortcuts;
[CEReactions, Reflect=aria_label] attribute DOMString? ariaLabel;
[CEReactions, Reflect=aria_labelledby] attribute DOMString? ariaLabelledBy;
+ [CEReactions, Reflect=aria_labelledby] attribute FrozenArray<Element>? ariaLabelledByElements;
[CEReactions, Reflect=aria_level] attribute DOMString? ariaLevel;
[CEReactions, Reflect=aria_live] attribute DOMString? ariaLive;
[CEReactions, Reflect=aria_modal] attribute DOMString? ariaModal;
@@ -38,6 +42,7 @@
[CEReactions, Reflect=aria_multiselectable] attribute DOMString? ariaMultiSelectable;
[CEReactions, Reflect=aria_orientation] attribute DOMString? ariaOrientation;
[CEReactions, Reflect=aria_owns] attribute DOMString? ariaOwns;
+ [CEReactions, Reflect=aria_owns] attribute FrozenArray<Element>? ariaOwnsElements;
[CEReactions, Reflect=aria_placeholder] attribute DOMString? ariaPlaceholder;
[CEReactions, Reflect=aria_posinset] attribute DOMString? ariaPosInSet;
[CEReactions, Reflect=aria_pressed] attribute DOMString? ariaPressed;
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 c74e482557b..6a7a98f13ff 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -1049,7 +1049,7 @@ void ContainerNode::FocusStateChanged() {
return;
StyleChangeType change_type =
- GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
+ GetComputedStyle()->HasPseudoElementStyle(kPseudoIdFirstLetter)
? kSubtreeStyleChange
: kLocalStyleChange;
SetNeedsStyleRecalc(
@@ -1070,7 +1070,7 @@ void ContainerNode::FocusVisibleStateChanged() {
if (!RuntimeEnabledFeatures::CSSFocusVisibleEnabled())
return;
StyleChangeType change_type =
- GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
+ GetComputedStyle()->HasPseudoElementStyle(kPseudoIdFirstLetter)
? kSubtreeStyleChange
: kLocalStyleChange;
SetNeedsStyleRecalc(change_type,
@@ -1086,7 +1086,7 @@ void ContainerNode::FocusVisibleStateChanged() {
void ContainerNode::FocusWithinStateChanged() {
if (GetComputedStyle() && GetComputedStyle()->AffectedByFocusWithin()) {
StyleChangeType change_type =
- GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
+ GetComputedStyle()->HasPseudoElementStyle(kPseudoIdFirstLetter)
? kSubtreeStyleChange
: kLocalStyleChange;
SetNeedsStyleRecalc(change_type,
@@ -1195,7 +1195,7 @@ void ContainerNode::SetDragged(bool new_value) {
if (GetComputedStyle()->AffectedByDrag()) {
StyleChangeType change_type =
- GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
+ GetComputedStyle()->HasPseudoElementStyle(kPseudoIdFirstLetter)
? kSubtreeStyleChange
: kLocalStyleChange;
SetNeedsStyleRecalc(change_type,
@@ -1392,7 +1392,7 @@ void ContainerNode::RebuildChildrenLayoutTrees(
DCHECK(!NeedsReattachLayoutTree());
if (IsActiveSlotOrActiveV0InsertionPoint()) {
- if (auto* slot = ToHTMLSlotElementOrNull(this)) {
+ if (auto* slot = DynamicTo<HTMLSlotElement>(this)) {
slot->RebuildDistributedChildrenLayoutTrees(whitespace_attacher);
} else {
To<V0InsertionPoint>(this)->RebuildDistributedChildrenLayoutTrees(
diff --git a/chromium/third_party/blink/renderer/core/dom/context_features.h b/chromium/third_party/blink/renderer/core/dom/context_features.h
index 788c789f147..b7312f6f4e7 100644
--- a/chromium/third_party/blink/renderer/core/dom/context_features.h
+++ b/chromium/third_party/blink/renderer/core/dom/context_features.h
@@ -38,7 +38,7 @@ class ContextFeaturesClient;
class Document;
class Page;
-class ContextFeatures final : public GarbageCollectedFinalized<ContextFeatures>,
+class ContextFeatures final : public GarbageCollected<ContextFeatures>,
public Supplement<Page> {
USING_GARBAGE_COLLECTED_MIXIN(ContextFeatures);
diff --git a/chromium/third_party/blink/renderer/core/dom/context_features_client_impl.cc b/chromium/third_party/blink/renderer/core/dom/context_features_client_impl.cc
index a4d9bb3c278..390c594ff0c 100644
--- a/chromium/third_party/blink/renderer/core/dom/context_features_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/dom/context_features_client_impl.cc
@@ -39,7 +39,7 @@
namespace blink {
class ContextFeaturesCache final
- : public GarbageCollectedFinalized<ContextFeaturesCache>,
+ : public GarbageCollected<ContextFeaturesCache>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(ContextFeaturesCache);
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index 9265249b5e4..fe3647ab426 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -38,6 +38,7 @@
#include "base/time/time.h"
#include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_snap_data.h"
+#include "components/performance_manager/public/mojom/coordination_unit.mojom-blink.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
@@ -45,12 +46,11 @@
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/metrics/public/mojom/ukm_interface.mojom-blink.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
-#include "services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.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/features.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
#include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
#include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h"
@@ -59,9 +59,11 @@
#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_prerendering_support.h"
+#include "third_party/blink/public/platform/web_theme_engine.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"
@@ -128,7 +130,6 @@
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/node_with_index.h"
-#include "third_party/blink/renderer/core/dom/nth_index_cache.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/dom/scripted_animation_controller.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -152,6 +153,7 @@
#include "third_party/blink/renderer/core/events/page_transition_event.h"
#include "third_party/blink/renderer/core/events/visual_viewport_resize_event.h"
#include "third_party/blink/renderer/core/events/visual_viewport_scroll_event.h"
+#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
#include "third_party/blink/renderer/core/execution_context/window_agent.h"
#include "third_party/blink/renderer/core/execution_context/window_agent_factory.h"
#include "third_party/blink/renderer/core/feature_policy/document_policy.h"
@@ -201,6 +203,7 @@
#include "third_party/blink/renderer/core/html/html_html_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_meta_element.h"
+#include "third_party/blink/renderer/core/html/html_object_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
#include "third_party/blink/renderer/core/html/html_script_element.h"
#include "third_party/blink/renderer/core/html/html_title_element.h"
@@ -214,7 +217,7 @@
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
-#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
#include "third_party/blink/renderer/core/html/window_name_collection.h"
#include "third_party/blink/renderer/core/html_element_factory.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
@@ -260,7 +263,6 @@
#include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
@@ -326,6 +328,25 @@ static WeakDocumentSet& liveDocumentSet();
namespace blink {
+namespace {
+
+// Returns true if any of <object> ancestors don't start loading or are loading
+// plugins/frames/images. If there are no <object> ancestors, this function
+// returns false.
+bool IsInIndeterminateObjectAncestor(const Element* element) {
+ if (!element->isConnected())
+ return false;
+ for (; element; element = element->ParentOrShadowHostElement()) {
+ if (const auto* object = DynamicTo<HTMLObjectElement>(element)) {
+ if (!object->DidFinishLoading())
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
using namespace html_names;
class DocumentOutliveTimeReporter : public BlinkGCObserver {
@@ -551,21 +572,8 @@ uint64_t Document::global_tree_version_ = 0;
static bool g_threaded_parsing_enabled_for_testing = true;
-// This doesn't work with non-Document ExecutionContext.
-static void RunAutofocusTask(ExecutionContext* context) {
- // Document lifecycle check is done in Element::focus()
- if (!context)
- return;
-
- Document* document = To<Document>(context);
- if (Element* element = document->AutofocusElement()) {
- document->SetAutofocusElement(nullptr);
- element->focus();
- }
-}
-
class Document::NetworkStateObserver final
- : public GarbageCollectedFinalized<Document::NetworkStateObserver>,
+ : public GarbageCollected<Document::NetworkStateObserver>,
public NetworkStateNotifier::NetworkStateObserver,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(Document::NetworkStateObserver);
@@ -690,71 +698,68 @@ class Document::SecurityContextInit : public FeaturePolicyParserDelegate {
frame ? frame->Loader().GetLastOriginDocumentCSP() : nullptr;
KURL url;
- if (initializer.ShouldSetURL()) {
- url = initializer.Url();
- if (url.IsEmpty())
- url = BlankURL();
- }
+ if (initializer.ShouldSetURL())
+ url = initializer.Url().IsEmpty() ? BlankURL() : initializer.Url();
- if (initializer.HasSecurityContext() && !initializer.OriginToCommit() &&
- initializer.OwnerDocument()) {
- // Alias certain security properties from |owner_document|. Used for
- // the case of about:blank pages inheriting the security properties of
- // their requestor context.
- // Note that this is currently somewhat broken; Blink always inherits
- // from the parent or opener, even though it should actually be
- // inherited from the request initiator.
- if (url.IsEmpty()) {
- last_origin_document_csp =
- initializer.OwnerDocument()->GetContentSecurityPolicy();
- }
+ // Alias certain security properties from |owner_document|. Used for the
+ // case of about:blank pages inheriting the security properties of their
+ // requestor context.
+ //
+ // Note that this is currently somewhat broken; Blink always inherits from
+ // the parent or opener, even though it should actually be inherited from
+ // the request initiator.
+ if (url.IsEmpty() && initializer.HasSecurityContext() &&
+ !initializer.OriginToCommit() && initializer.OwnerDocument()) {
+ last_origin_document_csp =
+ initializer.OwnerDocument()->GetContentSecurityPolicy();
}
csp_ = initializer.GetContentSecurityPolicy();
- if (!csp_ && initializer.ImportsController()) {
- // If this document is an HTML import, grab a reference to its master
- // document's Content Security Policy. We don't bind the CSP's delegate
- // in 'InitSecurityPolicy' in this case, as we can't rebind the
- // master document's policy object: The Content Security Policy's delegate
- // needs to remain set to the master document.
- csp_ =
- initializer.ImportsController()->Master()->GetContentSecurityPolicy();
- } else {
- if (!csp_) {
- csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
- bind_csp_immediately_ = true;
+ if (!csp_) {
+ if (initializer.ImportsController()) {
+ // If this document is an HTML import, grab a reference to its master
+ // document's Content Security Policy. We don't bind the CSP's delegate
+ // in 'InitSecurityPolicy' in this case, as we can't rebind the master
+ // document's policy object: The Content Security Policy's delegate
+ // needs to remain set to the master document.
+ csp_ = initializer.ImportsController()
+ ->Master()
+ ->GetContentSecurityPolicy();
+ return;
}
- // We should inherit the navigation initiator CSP if the document is
- // loaded using a local-scheme url.
- //
- // Note: about:srcdoc inherits CSP from its parent, not from its
- // initiator. In this case, the initializer.GetContentSecurityPolicy() is
- // used.
- if (last_origin_document_csp && !url.IsAboutSrcdocURL() &&
- (url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() ||
- url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) {
- csp_->CopyStateFrom(last_origin_document_csp);
+ csp_ = MakeGarbageCollected<ContentSecurityPolicy>();
+ bind_csp_immediately_ = true;
+ }
+
+ // We should inherit the navigation initiator CSP if the document is loaded
+ // using a local-scheme url.
+ //
+ // Note: about:srcdoc inherits CSP from its parent, not from its initiator.
+ // In this case, the initializer.GetContentSecurityPolicy() is used.
+ if (last_origin_document_csp && !url.IsAboutSrcdocURL() &&
+ (url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() ||
+ url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) {
+ csp_->CopyStateFrom(last_origin_document_csp);
+ }
+
+ if (document_classes & kPluginDocumentClass) {
+ if (last_origin_document_csp) {
+ csp_->CopyPluginTypesFrom(last_origin_document_csp);
+ return;
}
- if (document_classes & kPluginDocumentClass) {
- // TODO(andypaicu): This should inherit the origin document's plugin
- // types but because this could be a OOPIF document it might not have
- // access. In this situation we fallback on using the parent/opener.
- if (last_origin_document_csp) {
- csp_->CopyPluginTypesFrom(last_origin_document_csp);
- } else if (frame) {
- Frame* inherit_from = frame->Tree().Parent()
- ? frame->Tree().Parent()
- : frame->Client()->Opener();
- if (inherit_from && frame != inherit_from) {
- DCHECK(
- inherit_from->GetSecurityContext() &&
- inherit_from->GetSecurityContext()->GetContentSecurityPolicy());
- csp_->CopyPluginTypesFrom(
- inherit_from->GetSecurityContext()->GetContentSecurityPolicy());
- }
+ // TODO(andypaicu): This should inherit the origin document's plugin types
+ // but because this could be a OOPIF document it might not have access. In
+ // this situation we fallback on using the parent/opener:
+ if (frame) {
+ Frame* inherit_from = frame->Tree().Parent()
+ ? frame->Tree().Parent()
+ : frame->Client()->Opener();
+ if (inherit_from && frame != inherit_from) {
+ csp_->CopyPluginTypesFrom(
+ inherit_from->GetSecurityContext()->GetContentSecurityPolicy());
}
}
}
@@ -838,6 +843,9 @@ class Document::SecurityContextInit : public FeaturePolicyParserDelegate {
}
}
}
+
+ if (initializer.GrantLoadLocalResources())
+ security_origin_->GrantLoadLocalResources();
}
void InitializeFeaturePolicy(const DocumentInit& initializer,
@@ -987,15 +995,17 @@ class Document::SecurityContextInit : public FeaturePolicyParserDelegate {
bool bind_csp_immediately_ = false;
};
-ExplicitlySetAttrElementMap* Document::GetExplicitlySetAttrElementMap(
+ExplicitlySetAttrElementsMap* Document::GetExplicitlySetAttrElementsMap(
Element* element) {
DCHECK(element);
DCHECK(element->GetDocument() == this);
- if (!element_explicitly_set_attr_element_map_.Contains(element)) {
- element_explicitly_set_attr_element_map_.insert(
- element, MakeGarbageCollected<ExplicitlySetAttrElementMap>());
+ auto add_result =
+ element_explicitly_set_attr_elements_map_.insert(element, nullptr);
+ if (add_result.is_new_entry) {
+ add_result.stored_value->value =
+ MakeGarbageCollected<ExplicitlySetAttrElementsMap>();
}
- return element_explicitly_set_attr_element_map_.at(element);
+ return add_result.stored_value->value;
}
Document* Document::Create(Document& document) {
@@ -1041,7 +1051,6 @@ Document::Document(const DocumentInit& initializer,
printing_(kNotPrinting),
compatibility_mode_(kNoQuirksMode),
compatibility_mode_locked_(false),
- has_autofocused_(false),
last_focus_type_(kWebFocusTypeNone),
had_keyboard_event_(false),
clear_focused_element_timer_(
@@ -1142,7 +1151,7 @@ Document::Document(const DocumentInit& initializer,
// We disable fetches for frame-less Documents, including HTML-imported
// Documents (if kHtmlImportsRequestInitiatorLock is enabled). Subresources
// of HTML-imported Documents are fetched via the context document's
- // ResourceFetcher.
+ // ResourceFetcher. See https://crbug.com/961614 for details.
auto& properties =
*MakeGarbageCollected<DetachableResourceFetcherProperties>(
*MakeGarbageCollected<NullResourceFetcherProperties>());
@@ -1196,6 +1205,9 @@ Document::Document(const DocumentInit& initializer,
#ifndef NDEBUG
liveDocumentSet().insert(this);
#endif
+
+ if (frame_ && frame_->GetPage()->GetAgentMetricsCollector())
+ frame_->GetPage()->GetAgentMetricsCollector()->DidAttachDocument(*this);
}
Document::~Document() {
@@ -1619,6 +1631,8 @@ ScriptValue Document::registerElement(ScriptState* script_state,
V0CustomElementConstructorBuilder constructor_builder(script_state, options);
RegistrationContext()->RegisterElement(this, &constructor_builder, name,
exception_state);
+ if (exception_state.HadException())
+ return ScriptValue();
return constructor_builder.BindingsReturnValue();
}
@@ -2258,21 +2272,21 @@ FormController& Document::GetFormController() {
form_controller_ = MakeGarbageCollected<FormController>(*this);
HistoryItem* history_item = Loader() ? Loader()->GetHistoryItem() : nullptr;
if (history_item)
- history_item->SetDocumentState(form_controller_->FormElementsState());
+ history_item->SetDocumentState(form_controller_->ControlStates());
}
return *form_controller_;
}
-DocumentState* Document::FormElementsState() const {
+DocumentState* Document::GetDocumentState() const {
if (!form_controller_)
return nullptr;
- return form_controller_->FormElementsState();
+ return form_controller_->ControlStates();
}
-void Document::SetStateForNewFormElements(const Vector<String>& state_vector) {
+void Document::SetStateForNewControls(const Vector<String>& state_vector) {
if (!state_vector.size() && !form_controller_)
return;
- GetFormController().SetStateForNewFormElements(state_vector);
+ GetFormController().SetStateForNewControls(state_vector);
}
LocalFrameView* Document::View() const {
@@ -2318,36 +2332,39 @@ bool Document::NeedsLayoutTreeUpdate() const {
return false;
if (NeedsFullLayoutTreeUpdate())
return true;
- if (ChildNeedsStyleRecalc())
+ if (style_engine_->NeedsStyleRecalc())
return true;
- if (ChildNeedsStyleInvalidation())
+ if (style_engine_->NeedsStyleInvalidation())
return true;
if (GetLayoutView() && GetLayoutView()->WasNotifiedOfSubtreeChange())
return true;
- if (NeedsLayoutTreeRebuild()) {
+ if (style_engine_->NeedsLayoutTreeRebuild()) {
+ // TODO(futhark): there a couple of places where call back into the top
+ // frame while recursively doing a lifecycle update. One of them are for the
+ // RootScrollerController. These should probably be post layout tasks and
+ // make this test unnecessary since the layout tree rebuild dirtiness is
+ // internal to StyleEngine::UpdateStyleAndLayoutTree().
DCHECK(InStyleRecalc());
return true;
}
return false;
}
-bool Document::NeedsLayoutTreeRebuild() const {
- return documentElement() &&
- (documentElement()->NeedsReattachLayoutTree() ||
- documentElement()->ChildNeedsReattachLayoutTree());
-}
-
bool Document::NeedsFullLayoutTreeUpdate() 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
+ // chain to decide if we can let getComputedStyle() use the current
+ // ComputedStyle without doing the lifecycle update (implemented in
+ // Document::NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked()).
if (!IsActive() || !View())
return false;
- if (style_engine_->NeedsActiveStyleUpdate())
- return true;
- if (style_engine_->NeedsWhitespaceReattachment())
+ if (style_engine_->NeedsFullStyleUpdate())
return true;
if (!use_elements_needing_update_.IsEmpty())
return true;
- if (style_engine_->IsViewportStyleDirty())
- return true;
+ // We have scheduled an invalidation set on the document node which means any
+ // element may need a style recalc.
if (NeedsStyleInvalidation())
return true;
if (IsSlotAssignmentOrLegacyDistributionDirty())
@@ -2396,7 +2413,7 @@ void Document::UpdateStyleInvalidationIfNeeded() {
DCHECK(IsActive());
ScriptForbiddenScope forbid_script;
- if (!ChildNeedsStyleInvalidation() && !NeedsStyleInvalidation())
+ if (!GetStyleEngine().NeedsStyleInvalidation())
return;
TRACE_EVENT0("blink", "Document::updateStyleInvalidationIfNeeded");
SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.InvalidationTime");
@@ -2437,8 +2454,8 @@ bool PropagateScrollSnapStyleToViewport(
SetScrollPaddingLeft, Length());
if (changed) {
- document.GetSnapCoordinator()->SnapContainerDidChange(
- *document.GetLayoutView(), false /* is_removed */);
+ document.GetSnapCoordinator().SnapContainerDidChange(
+ *document.GetLayoutView());
}
return changed;
@@ -2604,7 +2621,7 @@ void Document::PropagateStyleToViewport() {
overflow_style->OverscrollBehaviorY())));
}
- if (overflow_style->HasPseudoStyle(kPseudoIdScrollbar))
+ if (overflow_style->HasPseudoElementStyle(kPseudoIdScrollbar))
update_scrollbar_style = true;
}
@@ -2652,7 +2669,9 @@ static void AssertLayoutTreeUpdated(Node& root) {
Node* node = &root;
while (node) {
auto* element = DynamicTo<Element>(node);
- if (element && RuntimeEnabledFeatures::DisplayLockingEnabled() &&
+ if (element &&
+ RuntimeEnabledFeatures::DisplayLockingEnabled(
+ root.GetExecutionContext()) &&
element->StyleRecalcBlockedByDisplayLock(
DisplayLockLifecycleTarget::kChildren)) {
node = FlatTreeTraversal::NextSkippingChildren(*node);
@@ -2753,17 +2772,6 @@ void Document::UpdateStyleAndLayoutTree() {
UpdateActiveStyle();
UpdateStyleInvalidationIfNeeded();
-
- // FIXME: We should update style on our ancestor chain before proceeding
- // however doing so currently causes several tests to crash, as
- // LocalFrame::setDocument calls Document::attach before setting the
- // LocalDOMWindow on the LocalFrame, or the SecurityOrigin on the
- // document. The attach, in turn resolves style (here) and then when we
- // resolve style on the parent chain, we may end up re-attaching our
- // containing iframe, which when asked HTMLFrameElementBase::isURLAllowed hits
- // a null-dereference due to security code always assuming the document has a
- // SecurityOrigin.
-
UpdateStyle();
NotifyLayoutTreeOfSubtreeChanges();
@@ -2802,47 +2810,20 @@ void Document::UpdateStyle() {
lifecycle_.AdvanceTo(DocumentLifecycle::kInStyleRecalc);
- // All of layout tree dirtiness and rebuilding needs to happen on a stable
- // flat tree. We have an invariant that all of that happens in this method
- // as a result of style recalc and the following layout tree rebuild.
- //
- // NeedsReattachLayoutTree() marks dirty up the flat tree ancestors. Re-
- // slotting on a dirty tree could break ancestor chains and fail to update the
- // tree properly.
- DCHECK(!NeedsLayoutTreeRebuild());
-
// SetNeedsStyleRecalc should only happen on Element and Text nodes.
DCHECK(!NeedsStyleRecalc());
- GetStyleEngine().UpdateViewportStyle();
-
StyleResolver& resolver = EnsureStyleResolver();
bool should_record_stats;
TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink,blink_style", &should_record_stats);
GetStyleEngine().SetStatsEnabled(should_record_stats);
- if (Element* document_element = documentElement()) {
- NthIndexCache nth_index_cache(*this);
- if (StyleRecalcChange().TraverseChild(*document_element)) {
- TRACE_EVENT0("blink,blink_style", "Document::recalcStyle");
- SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RecalcTime");
- Element* viewport_defining = ViewportDefiningElement();
- GetStyleEngine().RecalcStyle();
- if (viewport_defining != ViewportDefiningElement())
- ViewportDefiningElementDidChange();
- }
- GetStyleEngine().MarkForWhitespaceReattachment();
- if (NeedsLayoutTreeRebuild()) {
- TRACE_EVENT0("blink,blink_style", "Document::rebuildLayoutTree");
- SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RebuildLayoutTreeTime");
- GetStyleEngine().RebuildLayoutTree();
- }
- }
- GetStyleEngine().ClearWhitespaceReattachSet();
+ GetStyleEngine().UpdateStyleAndLayoutTree();
+
ClearChildNeedsStyleRecalc();
PropagateStyleToViewport();
- GetStyleEngine().UpdateColorSchemeBackground();
+
View()->UpdateCountersAfterStyleChange();
GetLayoutView()->RecalcLayoutOverflow();
@@ -2865,34 +2846,6 @@ void Document::UpdateStyle() {
}
}
-void Document::ViewportDefiningElementDidChange() {
- HTMLBodyElement* body = FirstBodyElement();
- if (!body)
- return;
- if (body->NeedsReattachLayoutTree())
- return;
- LayoutObject* layout_object = body->GetLayoutObject();
- if (layout_object && layout_object->IsLayoutBlock()) {
- // When the overflow style for documentElement changes to or from visible,
- // it changes whether the body element's box should have scrollable overflow
- // on its own box or propagated to the viewport. If the body style did not
- // need a recalc, this will not be updated as its done as part of setting
- // ComputedStyle on the LayoutObject. Force a SetStyle for body when the
- // ViewportDefiningElement changes in order to trigger an update of
- // HasOverflowClip() and the PaintLayer in StyleDidChange().
- layout_object->SetStyle(ComputedStyle::Clone(*layout_object->Style()));
- // CompositingReason::kClipsCompositingDescendants depends on the root
- // element having a clip-related style. Since style update due to changes of
- // viewport-defining element don't end up as a StyleDifference, we need a
- // special dirty bit for this situation.
- if (layout_object->HasLayer()) {
- ToLayoutBoxModelObject(layout_object)
- ->Layer()
- ->SetNeedsCompositingReasonsUpdate();
- }
- }
-}
-
void Document::NotifyLayoutTreeOfSubtreeChanges() {
if (!GetLayoutView()->WasNotifiedOfSubtreeChange())
return;
@@ -2974,6 +2927,22 @@ void Document::UpdateStyleAndLayoutTreeForNode(const Node* node) {
UpdateStyleAndLayoutTree();
}
+void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node) {
+ DCHECK(node);
+ if (!node->InActiveDocument()) {
+ DCHECK_EQ(node->ownerDocument(), this);
+ return;
+ }
+ DCHECK(!InStyleRecalc())
+ << "UpdateStyleAndLayoutTreeForSubtree called from within style recalc";
+
+ if (NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node) ||
+ node->ChildNeedsStyleRecalc() || node->ChildNeedsStyleInvalidation()) {
+ DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
+ UpdateStyleAndLayoutTree();
+ }
+}
+
void Document::UpdateStyleAndLayoutForNode(const Node* node) {
DCHECK(node);
if (!node->InActiveDocument())
@@ -3165,6 +3134,30 @@ void Document::SetIsViewSource(bool is_view_source) {
return;
}
+void Document::SetIsImmersiveArOverlay(bool val) {
+ if (!documentElement())
+ return;
+
+ if (val != is_immersive_ar_overlay_) {
+ DCHECK(RuntimeEnabledFeatures::WebXRARDOMOverlayEnabled(this));
+ is_immersive_ar_overlay_ = val;
+
+ // If the property has changed, apply the pseudo-style change to the root
+ // element. This will cascade further UA stylesheet changes such as setting
+ // the fullscreened element and its backdrop transparent.
+ documentElement()->PseudoStateChanged(
+ CSSSelector::kPseudoXrImmersiveDomOverlay);
+
+ // Ensure that the graphics layer tree gets fully rebuilt on changes,
+ // similar to HTMLVideoElement::DidEnterFullscreen(). This may not be
+ // strictly necessary if the compositing changes are based on visibility
+ // settings, but helps ensure consistency in case it's changed to
+ // detaching layers or re-rooting the graphics layer tree.
+ GetLayoutView()->Compositor()->SetNeedsCompositingUpdate(
+ kCompositingUpdateRebuildTree);
+ }
+}
+
void Document::ScheduleUseShadowTreeUpdate(SVGUseElement& element) {
use_elements_needing_update_.insert(&element);
ScheduleLayoutTreeUpdateIfNeeded();
@@ -3320,7 +3313,7 @@ void Document::Shutdown() {
hover_element_ = nullptr;
active_element_ = nullptr;
- autofocus_element_ = nullptr;
+ autofocus_candidates_.clear();
if (focused_element_.Get()) {
Element* old_focused_element = focused_element_;
@@ -3379,6 +3372,8 @@ void Document::Shutdown() {
// Check for frame_ so we only detach execution contexts with its own
// scheduler.
+ // TODO(bokan): Can this happen? |frame_| is dereferenced above and CHECKed
+ // at top.
if (frame_)
GetAgent()->DetachExecutionContext(this);
@@ -4012,9 +4007,9 @@ static bool AllDescendantsAreComplete(Document* document) {
if (child->IsLoading())
return false;
}
- for (HTMLPortalElement* portal :
- DocumentPortals::From(*document).GetPortals()) {
- if (portal->ContentFrame() && portal->ContentFrame()->IsLoading())
+ for (PortalContents* portal : DocumentPortals::From(*document).GetPortals()) {
+ auto* frame = portal->GetFrame();
+ if (frame && frame->IsLoading())
return false;
}
return true;
@@ -4200,7 +4195,9 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient* chrome_client,
return false;
}
-void Document::DispatchUnloadEvents(DocumentLoadTiming* timing) {
+void Document::DispatchUnloadEvents(
+ SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>* unload_timing) {
PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
if (parser_)
parser_->StopParsing();
@@ -4258,21 +4255,25 @@ void Document::DispatchUnloadEvents(DocumentLoadTiming* timing) {
load_event_progress_ = kUnloadEventInProgress;
Event& unload_event = *Event::Create(event_type_names::kUnload);
- if (timing && timing->UnloadEventStart().is_null() &&
- timing->UnloadEventEnd().is_null()) {
- DCHECK(!timing->NavigationStart().is_null());
- const base::TimeTicks unload_event_start = base::TimeTicks::Now();
- timing->MarkUnloadEventStart(unload_event_start);
- frame_->DomWindow()->DispatchEvent(unload_event, this);
- const base::TimeTicks unload_event_end = base::TimeTicks::Now();
+ const base::TimeTicks unload_event_start = base::TimeTicks::Now();
+ frame_->DomWindow()->DispatchEvent(unload_event, this);
+ const base::TimeTicks unload_event_end = base::TimeTicks::Now();
+
+ if (unload_timing) {
+ // Record unload event timing when navigating cross-document.
DEFINE_STATIC_LOCAL(
CustomCountHistogram, unload_histogram,
("DocumentEventTiming.UnloadDuration", 0, 10000000, 50));
unload_histogram.CountMicroseconds(unload_event_end -
unload_event_start);
- timing->MarkUnloadEventEnd(unload_event_end);
- } else {
- frame_->DomWindow()->DispatchEvent(unload_event, frame_->GetDocument());
+
+ // Fill in the unload timing if the new document origin has access to
+ // them.
+ if (committing_origin->CanRequest(Url())) {
+ auto& timing = unload_timing->emplace();
+ timing.unload_event_start = unload_event_start;
+ timing.unload_event_end = unload_event_end;
+ }
}
}
load_event_progress_ = kUnloadEventHandled;
@@ -4315,10 +4316,16 @@ Document::PageDismissalType Document::PageDismissalEventBeingDispatched()
}
void Document::SetParsingState(ParsingState parsing_state) {
+ ParsingState previous_state = parsing_state_;
parsing_state_ = parsing_state;
if (Parsing() && !element_data_cache_)
element_data_cache_ = MakeGarbageCollected<ElementDataCache>();
+ if (previous_state != kFinishedParsing &&
+ parsing_state_ == kFinishedParsing) {
+ if (form_controller_ && form_controller_->HasControlStates())
+ form_controller_->ScheduleRestore();
+ }
}
bool Document::ShouldScheduleLayout() const {
@@ -4518,41 +4525,18 @@ void Document::SetURL(const KURL& url) {
// If text fragment identifiers are enabled, we strip the fragment directive
// from the URL fragment.
- // E.g. "#id:~:targetText=a" --> "#id"
+ // E.g. "#id:~:text=a" --> "#id"
if (RuntimeEnabledFeatures::TextFragmentIdentifiersEnabled(this)) {
String fragment = new_url.FragmentIdentifier();
- wtf_size_t start_pos = fragment.Find(kFragmentDirectiveNewPrefix);
+ wtf_size_t start_pos = fragment.Find(kFragmentDirectivePrefix);
if (start_pos != kNotFound) {
- fragment_directive_ = fragment.Substring(
- start_pos + kFragmentDirectiveNewPrefixStringLength);
+ fragment_directive_ =
+ fragment.Substring(start_pos + kFragmentDirectivePrefixStringLength);
if (start_pos == 0)
new_url.RemoveFragmentIdentifier();
else
new_url.SetFragmentIdentifier(fragment.Substring(0, start_pos));
- } else {
- // TODO(crbug/1007016): Remove support for the old prefix, we currently
- // fall back to checking ## if we did not find the new delimiter :~:.
-
- // Add a hash to the beginning of the fragment as it is part of parsing
- // the ## fragment directive prefix but is not included in
- // FragmentIdentifier().
- fragment = "#" + fragment;
- wtf_size_t start_pos = fragment.Find(kFragmentDirectivePrefix);
- if (start_pos != kNotFound) {
- fragment_directive_ = fragment.Substring(
- start_pos + kFragmentDirectivePrefixStringLength);
-
- if (start_pos == 0) {
- // Remove the URL fragment if it is entirely a fragment directive.
- new_url.RemoveFragmentIdentifier();
- } else {
- // The stripped fragment starts at position 1 and has length
- // start_pos-1 due to the added hash.
- String stripped_fragment = fragment.Substring(1, start_pos - 1);
- new_url.SetFragmentIdentifier(stripped_fragment);
- }
- }
}
}
@@ -5716,7 +5700,7 @@ void Document::SendDidEditFieldInInsecureContext() {
return;
mojo::Remote<mojom::blink::InsecureInputService> insecure_input_service;
- GetFrame()->GetInterfaceProvider().GetInterface(
+ GetFrame()->GetBrowserInterfaceBroker().GetInterface(
insecure_input_service.BindNewPipeAndPassReceiver());
insecure_input_service->DidEditFieldInInsecureContext();
@@ -6058,53 +6042,22 @@ const KURL Document::SiteForCookies() const {
if (!GetFrame())
return NullURL();
- // TODO(mkwst): This doesn't correctly handle sandboxed documents; we want to
- // look at their URL, but we can't because we don't know what it is.
Frame& top = GetFrame()->Tree().Top();
- KURL top_document_url;
- auto* top_local_frame = DynamicTo<LocalFrame>(&top);
- if (top_local_frame) {
- top_document_url = top_local_frame->GetDocument()->Url();
- } else {
- const SecurityOrigin* origin =
- top.GetSecurityContext()->GetSecurityOrigin();
- // TODO(yhirano): Ideally |origin| should not be null here.
- if (origin)
- top_document_url = KURL(NullURL(), origin->ToString());
- else
- top_document_url = NullURL();
- }
+ const SecurityOrigin* origin = top.GetSecurityContext()->GetSecurityOrigin();
+ // TODO(yhirano): Ideally |origin| should not be null here.
+ if (!origin)
+ return NullURL();
if (SchemeRegistry::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
- top_document_url.Protocol()))
- return top_document_url;
-
- // We're intentionally using the URL of each document rather than the
- // document's SecurityOrigin. A sandboxed document has a unique opaque
- // origin, but that shouldn't affect first-/third-party status for cookies
- // and site data.
- base::Optional<OriginAccessEntry> remote_entry;
- if (!top_local_frame) {
- remote_entry.emplace(
- top_document_url,
- network::mojom::CorsDomainMatchMode::kAllowRegistrableDomains);
- }
- const OriginAccessEntry& access_entry =
- remote_entry ? *remote_entry
- : top_local_frame->GetDocument()->AccessEntryFromURL();
+ origin->Protocol())) {
+ return origin->IsOpaque() ? NullURL() : KURL(origin->ToString());
+ }
+
+ OriginAccessEntry access_entry(
+ *origin, network::mojom::CorsDomainMatchMode::kAllowRegistrableDomains);
const Frame* current_frame = GetFrame();
while (current_frame) {
- // Skip over srcdoc documents, as they are always same-origin with their
- // closest non-srcdoc parent.
- auto is_srcdoc = [](const Frame* frame) {
- const auto* local_frame = DynamicTo<LocalFrame>(frame);
- return local_frame && local_frame->GetDocument()->IsSrcdocDocument();
- };
- while (is_srcdoc(current_frame))
- current_frame = current_frame->Tree().Parent();
- DCHECK(current_frame);
-
// We use 'matchesDomain' here, as it turns out that some folks embed HTTPS
// login forms into HTTP pages; we should allow this kind of upgrade.
if (access_entry.MatchesDomain(
@@ -6116,7 +6069,32 @@ const KURL Document::SiteForCookies() const {
current_frame = current_frame->Tree().Parent();
}
- return top_document_url;
+ return origin->IsOpaque() ? NullURL() : KURL(origin->ToString());
+}
+
+ScriptPromise Document::hasStorageAccess(ScriptState* script_state) const {
+ const bool has_access =
+ TopFrameOrigin() &&
+ GetSecurityOrigin()->IsSameSchemeHostPort(TopFrameOrigin().get());
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+
+ // TODO (http://crbug.com/989663)
+ // Hookup actual logic to Resolve/Reject this request properly.
+ ScriptPromise promise = resolver->Promise();
+ resolver->Resolve(has_access);
+ return promise;
+}
+
+ScriptPromise Document::requestStorageAccess(ScriptState* script_state) const {
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+
+ // TODO (http://crbug.com/989663)
+ // Hookup actual logic to Resolve/Reject this request properly.
+ ScriptPromise promise = resolver->Promise();
+ resolver->Reject();
+ return promise;
}
static bool IsValidNameNonASCII(const LChar* characters, unsigned length) {
@@ -6589,21 +6567,20 @@ LocalDOMWindow* Document::defaultView() const {
namespace {
-using resource_coordinator::mojom::InterventionPolicy;
+using performance_manager::mojom::InterventionPolicy;
-// A helper function for setting intervention policy values on a frame.
-void SetInitialInterventionPolicies(
+// A helper function to set the origin trial freeze policy of a document.
+void SetOriginTrialFreezePolicy(
DocumentResourceCoordinator* document_resource_coordinator,
ExecutionContext* context) {
// An explicit opt-out overrides an explicit opt-in if both are present.
InterventionPolicy policy = InterventionPolicy::kDefault;
- if (RuntimeEnabledFeatures::PageLifecycleTransitionsOptOutEnabled(context)) {
+ if (RuntimeEnabledFeatures::PageFreezeOptOutEnabled(context)) {
policy = InterventionPolicy::kOptOut;
- UseCounter::Count(context, WebFeature::kPageLifecycleTransitionsOptOut);
- } else if (RuntimeEnabledFeatures::PageLifecycleTransitionsOptInEnabled(
- context)) {
+ UseCounter::Count(context, WebFeature::kPageFreezeOptOut);
+ } else if (RuntimeEnabledFeatures::PageFreezeOptInEnabled(context)) {
policy = InterventionPolicy::kOptIn;
- UseCounter::Count(context, WebFeature::kPageLifecycleTransitionsOptIn);
+ UseCounter::Count(context, WebFeature::kPageFreezeOptIn);
}
document_resource_coordinator->SetOriginTrialFreezePolicy(policy);
@@ -6669,11 +6646,10 @@ void Document::FinishedParsing() {
probe::DomContentLoadedEventFired(frame);
frame->GetIdlenessDetector()->DomContentLoadedEventFired();
- // Forward intervention policy state to the corresponding frame object
- // in the resource coordinator.
- // TODO(chrisha): Plumb in dynamic policy changes driven from Javascript.
+ // Forward origin trial freeze policy to the corresponding frame object in
+ // the resource coordinator.
if (auto* document_resource_coordinator = GetResourceCoordinator())
- SetInitialInterventionPolicies(document_resource_coordinator, this);
+ SetOriginTrialFreezePolicy(document_resource_coordinator, this);
}
// Schedule dropping of the ElementDataCache. We keep it alive for a while
@@ -6997,11 +6973,13 @@ void Document::InitSecurityContext(
AddInsecureNavigationUpgrade(to_upgrade);
}
- cookie_url_ = url_;
+ bool inherit_cookie_url_from_owner = initializer.IsSrcdocDocument() ||
+ url_.IsAboutBlankURL() ||
+ !initializer.OriginToCommit();
- if (!initializer.OriginToCommit() && initializer.OwnerDocument()) {
- cookie_url_ = initializer.OwnerDocument()->CookieURL();
- }
+ cookie_url_ = inherit_cookie_url_from_owner && initializer.OwnerDocument()
+ ? initializer.OwnerDocument()->CookieURL()
+ : url_;
SetAddressSpace(initializer.GetIPAddressSpace());
@@ -7131,7 +7109,6 @@ bool Document::IsContextThread() const {
}
void Document::UpdateFocusAppearanceAfterLayout() {
- DCHECK_LT(Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
update_focus_appearance_after_layout_ = true;
}
@@ -7437,6 +7414,8 @@ void Document::CancelPostAnimationFrame(int id) {
}
void Document::RunPostAnimationFrameCallbacks() {
+ FlushAutofocusCandidates();
+
bool was_throttled = current_frame_is_throttled_;
current_frame_is_throttled_ = false;
if (was_throttled || !scripted_animation_controller_)
@@ -7526,11 +7505,11 @@ bool Document::ThreadedParsingEnabledForTesting() {
return g_threaded_parsing_enabled_for_testing;
}
-SnapCoordinator* Document::GetSnapCoordinator() {
+SnapCoordinator& Document::GetSnapCoordinator() {
if (!snap_coordinator_)
snap_coordinator_ = MakeGarbageCollected<SnapCoordinator>();
- return snap_coordinator_.Get();
+ return *snap_coordinator_;
}
void Document::SetContextFeatures(ContextFeatures& features) {
@@ -7772,19 +7751,140 @@ bool Document::SetPseudoStateForTesting(Element& element,
return true;
}
-void Document::SetAutofocusElement(Element* element) {
- if (!element) {
- autofocus_element_ = nullptr;
+void Document::EnqueueAutofocusCandidate(Element& element) {
+ // https://html.spec.whatwg.org/C#the-autofocus-attribute
+ // 7. If topDocument's autofocus processed flag is false, then remove the
+ // element from topDocument's autofocus candidates, and append the element
+ // to topDocument's autofocus candidates.
+ if (autofocus_processed_flag_)
+ return;
+ wtf_size_t index = autofocus_candidates_.Find(&element);
+ if (index != WTF::kNotFound)
+ autofocus_candidates_.EraseAt(index);
+ autofocus_candidates_.push_back(element);
+}
+
+bool Document::HasAutofocusCandidates() const {
+ return autofocus_candidates_.size() > 0;
+}
+
+// https://html.spec.whatwg.org/C/#flush-autofocus-candidates
+void Document::FlushAutofocusCandidates() {
+ // 1. If topDocument's autofocus processed flag is true, then return.
+ if (autofocus_processed_flag_)
+ return;
+
+ // 3. If candidates is empty, then return.
+ if (autofocus_candidates_.IsEmpty())
+ return;
+
+ // 4. If topDocument's focused area is not topDocument itself, or
+ // topDocument's URL's fragment is not empty, then:
+ // 1. Empty candidates.
+ // 2. Set topDocument's autofocus processed flag to true.
+ // 3. Return.
+ if (AdjustedFocusedElement()) {
+ autofocus_candidates_.clear();
+ autofocus_processed_flag_ = true;
+ AddConsoleMessage(
+ ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kInfo,
+ "Autofocus processing was blocked because a "
+ "document already has a focused element."));
return;
}
- if (has_autofocused_)
+ if (HasNonEmptyFragment()) {
+ autofocus_candidates_.clear();
+ autofocus_processed_flag_ = true;
+ AddConsoleMessage(
+ ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kInfo,
+ "Autofocus processing was blocked because a "
+ "document's URL has a fragment '#" +
+ Url().FragmentIdentifier() + "'."));
return;
- has_autofocused_ = true;
- DCHECK(!autofocus_element_);
- autofocus_element_ = element;
- GetTaskRunner(TaskType::kUserInteraction)
- ->PostTask(FROM_HERE,
- WTF::Bind(&RunAutofocusTask, WrapWeakPersistent(this)));
+ }
+
+ // 5. While candidates is not empty:
+ while (!autofocus_candidates_.IsEmpty()) {
+ // 5.1. Let element be candidates[0].
+ Element& element = *autofocus_candidates_[0];
+
+ // 5.2. Let doc be element's node document.
+ Document* doc = &element.GetDocument();
+
+ // 5.3. If doc is not fully active, then remove element from candidates,
+ // and continue.
+ // 5.4. If doc's browsing context's top-level browsing context is not same
+ // as topDocument's browsing context, then remove element from candidates,
+ // and continue.
+ if (&doc->TopDocument() != this) {
+ autofocus_candidates_.EraseAt(0);
+ continue;
+ }
+
+ // The element is in the fallback content of an OBJECT of which
+ // fallback state is not fixed yet.
+ // TODO(tkent): Standardize this behavior.
+ if (IsInIndeterminateObjectAncestor(&element)) {
+ GetPage()->Animator().ScheduleVisualUpdate(GetFrame());
+ return;
+ }
+
+ // 5.5. If doc's script-blocking style sheet counter is greater than 0,
+ // then return.
+ // TODO(tkent): Is this necessary? WPT spin-by-blocking-style-sheet.html
+ // doesn't hit this condition, and FlushAutofocusCandidates() is not called
+ // until the stylesheet is loaded.
+ StyleEngine& engine = GetStyleEngine();
+ if (engine.HasPendingScriptBlockingSheets() ||
+ engine.HasPendingRenderBlockingSheets()) {
+ return;
+ }
+
+ // 5.6. Remove element from candidates.
+ autofocus_candidates_.EraseAt(0);
+
+ // 5.7. Let inclusiveAncestorDocuments be a list consisting of doc, plus
+ // the active documents of each of doc's browsing context's ancestor
+ // browsing contexts.
+ // 5.8. If URL's fragment of any Document in inclusiveAncestorDocuments
+ // is not empty, then continue.
+ if (doc != this) {
+ for (HTMLFrameOwnerElement* frameOwner = doc->LocalOwner();
+ !doc->HasNonEmptyFragment() && frameOwner;
+ frameOwner = doc->LocalOwner()) {
+ doc = &frameOwner->GetDocument();
+ }
+ if (doc->HasNonEmptyFragment()) {
+ AddConsoleMessage(
+ ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kInfo,
+ "Autofocus processing was blocked because a "
+ "document's URL has a fragment '#" +
+ doc->Url().FragmentIdentifier() + "'."));
+ continue;
+ }
+ DCHECK_EQ(doc, this);
+ }
+
+ // 9. If element is a focusable area, then:
+ if (element.IsFocusable()) {
+ // 9.1. Empty candidates.
+ autofocus_candidates_.clear();
+ // 9.2. Set topDocument's autofocus processed flag to true.
+ autofocus_processed_flag_ = true;
+ // 9.3. Run the focusing steps for element.
+ element.focus();
+ } else {
+ // TODO(tkent): Show a console message, and fix LocalNTP*Test.*
+ // in browser_tests.
+ }
+ }
+}
+
+bool Document::HasNonEmptyFragment() const {
+ return !Url().FragmentIdentifier().IsEmpty();
}
Element* Document::ActiveElement() const {
@@ -7902,6 +8002,7 @@ void Document::PlatformColorsChanged() {
return;
GetStyleEngine().PlatformColorsChanged();
+ MediaQueryAffectingValueChanged();
}
bool Document::IsSecureContext(String& error_message) const {
@@ -8127,7 +8228,7 @@ void Document::Trace(Visitor* visitor) {
visitor->Trace(imports_controller_);
visitor->Trace(doc_type_);
visitor->Trace(implementation_);
- visitor->Trace(autofocus_element_);
+ visitor->Trace(autofocus_candidates_);
visitor->Trace(focused_element_);
visitor->Trace(sequential_focus_navigation_starting_point_);
visitor->Trace(hover_element_);
@@ -8190,7 +8291,8 @@ void Document::Trace(Visitor* visitor) {
visitor->Trace(find_in_page_root_);
visitor->Trace(computed_node_mapping_);
visitor->Trace(mime_handler_view_before_unload_event_listener_);
- visitor->Trace(element_explicitly_set_attr_element_map_);
+ visitor->Trace(element_explicitly_set_attr_elements_map_);
+ visitor->Trace(display_lock_activation_observer_);
Supplementable<Document>::Trace(visitor);
TreeScope::Trace(visitor);
ContainerNode::Trace(visitor);
@@ -8296,8 +8398,10 @@ NavigationInitiatorImpl& Document::NavigationInitiator() {
}
LazyLoadImageObserver& Document::EnsureLazyLoadImageObserver() {
- if (!lazy_load_image_observer_)
- lazy_load_image_observer_ = MakeGarbageCollected<LazyLoadImageObserver>();
+ if (!lazy_load_image_observer_) {
+ lazy_load_image_observer_ =
+ MakeGarbageCollected<LazyLoadImageObserver>(*this);
+ }
return *lazy_load_image_observer_;
}
@@ -8391,6 +8495,40 @@ int Document::LockedDisplayLockCount() const {
return locked_display_lock_count_;
}
+void Document::RegisterDisplayLockActivationObservation(Element* element) {
+ EnsureDisplayLockActivationObserver().observe(element);
+}
+
+void Document::UnregisterDisplayLockActivationObservation(Element* element) {
+ EnsureDisplayLockActivationObserver().unobserve(element);
+}
+
+IntersectionObserver& Document::EnsureDisplayLockActivationObserver() {
+ if (!display_lock_activation_observer_) {
+ // Use kPostTaskToDeliver method, since a commit can dirty layout, and we
+ // want to avoid dirtying layout during post-lifecycle steps.
+ display_lock_activation_observer_ = IntersectionObserver::Create(
+ {}, {std::numeric_limits<float>::min()}, this,
+ WTF::BindRepeating(&Document::ProcessDisplayLockActivationObservation,
+ WrapWeakPersistent(this)),
+ IntersectionObserver::kPostTaskToDeliver);
+ }
+ return *display_lock_activation_observer_;
+}
+
+void Document::ProcessDisplayLockActivationObservation(
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ for (auto& entry : entries) {
+ if (entry->isIntersecting()) {
+ auto* context = entry->target()->GetDisplayLockContext();
+ DCHECK(context);
+ DCHECK(context->ShouldCommitForActivation(
+ DisplayLockActivationReason::kViewport));
+ context->CommitForActivationWithSignal(entry->target());
+ }
+ }
+}
+
void Document::ExecuteJavaScriptUrls() {
DCHECK(frame_);
Vector<PendingJavascriptUrl> urls_to_execute;
@@ -8484,8 +8622,10 @@ void Document::ColorSchemeChanged() {
}
bool Document::InForcedColorsMode() const {
- return RuntimeEnabledFeatures::ForcedColorsEnabled() &&
- GetSettings()->GetForcedColors() != ForcedColors::kNone;
+ return RuntimeEnabledFeatures::ForcedColorsEnabled() && Platform::Current() &&
+ Platform::Current()->ThemeEngine() &&
+ Platform::Current()->ThemeEngine()->ForcedColors() !=
+ ForcedColors::kNone;
}
void Document::CountUse(mojom::WebFeature feature) const {
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index 4e935717449..ee2f8012b78 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -104,7 +104,6 @@ class DOMWindow;
class DocumentFragment;
class DocumentInit;
class DocumentLoader;
-class DocumentLoadTiming;
class DocumentMarkerController;
class DocumentNameCollection;
class DocumentOutliveTimeReporter;
@@ -140,7 +139,9 @@ class HTMLScriptElementOrSVGScriptElement;
class HitTestRequest;
class HttpRefreshScheduler;
class IdleRequestOptions;
+class IntersectionObserver;
class IntersectionObserverController;
+class IntersectionObserverEntry;
class LayoutView;
class LazyLoadImageObserver;
class LiveNodeListBase;
@@ -170,6 +171,7 @@ class SVGUseElement;
class Text;
class TrustedHTML;
class ScriptElementBase;
+class ScriptPromise;
class ScriptRunner;
class ScriptableDocumentParser;
class ScriptedAnimationController;
@@ -245,8 +247,12 @@ using DocumentClassFlags = unsigned char;
// ("ariaActiveDescendant", el2)
// This represents 'explicitly set attr-element' in the HTML specification.
// https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:element-2
-using ExplicitlySetAttrElementMap =
- HeapHashMap<QualifiedName, WeakMember<Element>>;
+// Note that in the interest of simplicitly, attributes that reflect a single
+// element reference are implemented using the same ExplicitlySetAttrElementsMap
+// storage, but only store a single element vector which is DCHECKED at the
+// calling site.
+using ExplicitlySetAttrElementsMap =
+ HeapHashMap<QualifiedName, Member<HeapVector<Member<Element>>>>;
// A document (https://dom.spec.whatwg.org/#concept-document) is the root node
// of a tree of DOM nodes, generally resulting from the parsing of an markup
@@ -468,6 +474,9 @@ class CORE_EXPORT Document : public ContainerNode,
bool IsViewSource() const { return is_view_source_; }
void SetIsViewSource(bool);
+ bool IsImmersiveArOverlay() const { return is_immersive_ar_overlay_; }
+ void SetIsImmersiveArOverlay(bool);
+
bool SawElementsInKnownNamespaces() const {
return saw_elements_in_known_namespaces_;
}
@@ -497,8 +506,8 @@ class CORE_EXPORT Document : public ContainerNode,
void EvaluateMediaQueryList();
FormController& GetFormController();
- DocumentState* FormElementsState() const;
- void SetStateForNewFormElements(const Vector<String>&);
+ DocumentState* GetDocumentState() const;
+ void SetStateForNewControls(const Vector<String>&);
LocalFrameView* View() const; // can be null
LocalFrame* GetFrame() const { return frame_; } // can be null
@@ -540,6 +549,7 @@ class CORE_EXPORT Document : public ContainerNode,
// lay out.
void UpdateStyleAndLayoutTree();
void UpdateStyleAndLayoutTreeForNode(const Node*);
+ void UpdateStyleAndLayoutTreeForSubtree(const Node*);
enum ForcedLayoutStatus { IsForcedLayout, IsNotForcedLayout };
void UpdateStyleAndLayout(ForcedLayoutStatus = IsForcedLayout);
@@ -657,10 +667,15 @@ class CORE_EXPORT Document : public ContainerNode,
bool is_reload,
bool& did_allow_navigation);
+ struct UnloadEventTiming {
+ base::TimeTicks unload_event_start;
+ base::TimeTicks unload_event_end;
+ };
// Dispatches "pagehide", "visibilitychange" and "unload" events, if not
- // dispatched already. Fills unload timing in the next document's load timing
- // if present.
- void DispatchUnloadEvents(DocumentLoadTiming*);
+ // dispatched already. Fills unload timing if present and |committing_origin|
+ // has access to the unload timing of the document.
+ void DispatchUnloadEvents(SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>*);
void DispatchFreezeEvent();
@@ -811,14 +826,14 @@ class CORE_EXPORT Document : public ContainerNode,
return user_action_elements_;
}
- ExplicitlySetAttrElementMap* GetExplicitlySetAttrElementMap(Element* index);
+ ExplicitlySetAttrElementsMap* GetExplicitlySetAttrElementsMap(Element*);
// Returns false if the function fails. e.g. |pseudo| is not supported.
bool SetPseudoStateForTesting(Element& element,
const String& pseudo,
bool matches);
- void SetAutofocusElement(Element*);
- Element* AutofocusElement() const { return autofocus_element_.Get(); }
+ void EnqueueAutofocusCandidate(Element&);
+ bool HasAutofocusCandidates() const;
void SetSequentialFocusNavigationStartingPoint(Node*);
Element* SequentialFocusNavigationStartingPoint(WebFocusType) const;
@@ -992,6 +1007,11 @@ class CORE_EXPORT Document : public ContainerNode,
const KURL SiteForCookies() const;
+ // Storage Access API methods to check for or request access to storage that
+ // may otherwise be blocked.
+ ScriptPromise hasStorageAccess(ScriptState* script_state) const;
+ ScriptPromise requestStorageAccess(ScriptState* script_state) const;
+
// The following implements the rule from HTML 4 for what valid names are.
// To get this right for all the XML cases, we probably have to improve this
// or move it and make it sensitive to the type of document.
@@ -1358,7 +1378,7 @@ class CORE_EXPORT Document : public ContainerNode,
}
int NodeCount() const { return node_count_; }
- SnapCoordinator* GetSnapCoordinator();
+ SnapCoordinator& GetSnapCoordinator();
void DidEnforceInsecureRequestPolicy();
void DidEnforceInsecureNavigationsSet();
@@ -1526,6 +1546,10 @@ class CORE_EXPORT Document : public ContainerNode,
void RemoveLockedDisplayLock();
int LockedDisplayLockCount() const;
+ // Manage the element's observation for display lock activation.
+ void RegisterDisplayLockActivationObservation(Element*);
+ void UnregisterDisplayLockActivationObservation(Element*);
+
// Deferred compositor commits are disallowed by default, and are only allowed
// for same-origin navigations to an html document fetched with http.
bool DeferredCompositorCommitIsAllowed() {
@@ -1601,8 +1625,6 @@ class CORE_EXPORT Document : public ContainerNode,
return !pending_javascript_urls_.IsEmpty();
}
- bool NeedsLayoutTreeRebuild() const;
-
String GetFragmentDirective() const { return fragment_directive_; }
bool UseCountFragmentDirective() const {
return use_count_fragment_directive_;
@@ -1719,6 +1741,8 @@ class CORE_EXPORT Document : public ContainerNode,
void ClearFocusedElementSoon();
void ClearFocusedElementTimerFired(TimerBase*);
+ void FlushAutofocusCandidates();
+ bool HasNonEmptyFragment() const;
bool HaveScriptBlockingStylesheetsLoaded() const;
@@ -1737,7 +1761,6 @@ class CORE_EXPORT Document : public ContainerNode,
void SendDidEditFieldInInsecureContext();
bool HaveImportsLoaded() const;
- void ViewportDefiningElementDidChange();
void UpdateActiveState(bool is_active, bool update_active_chain, Element*);
void UpdateHoverState(Element*);
@@ -1761,6 +1784,11 @@ class CORE_EXPORT Document : public ContainerNode,
Element* new_focused_element);
void DisplayNoneChangedForFrame();
+ IntersectionObserver& EnsureDisplayLockActivationObserver();
+
+ void ProcessDisplayLockActivationObservation(
+ const HeapVector<Member<IntersectionObserverEntry>>&);
+
DocumentLifecycle lifecycle_;
bool evaluate_media_queries_on_style_recalc_;
@@ -1827,11 +1855,14 @@ class CORE_EXPORT Document : public ContainerNode,
};
Vector<PendingJavascriptUrl> pending_javascript_urls_;
- bool has_autofocused_;
+ // https://html.spec.whatwg.org/C/#autofocus-processed-flag
+ bool autofocus_processed_flag_ = false;
WebFocusType last_focus_type_;
bool had_keyboard_event_;
TaskRunnerTimer<Document> clear_focused_element_timer_;
- Member<Element> autofocus_element_;
+ // https://html.spec.whatwg.org/C/#autofocus-candidates
+ // We implement this as a Vector because its maximum size is typically 1.
+ HeapVector<Member<Element>> autofocus_candidates_;
Member<Element> focused_element_;
Member<Range> sequential_focus_navigation_starting_point_;
Member<Element> hover_element_;
@@ -1944,6 +1975,7 @@ class CORE_EXPORT Document : public ContainerNode,
DocumentClassFlags document_classes_;
bool is_view_source_;
+ bool is_immersive_ar_overlay_;
bool saw_elements_in_known_namespaces_;
bool is_srcdoc_document_;
bool is_mobile_document_;
@@ -2112,12 +2144,14 @@ class CORE_EXPORT Document : public ContainerNode,
bool toggle_during_parsing_ = false;
- HeapHashMap<WeakMember<Element>, Member<ExplicitlySetAttrElementMap>>
- element_explicitly_set_attr_element_map_;
-
String fragment_directive_;
bool use_count_fragment_directive_ = false;
+
+ HeapHashMap<WeakMember<Element>, Member<ExplicitlySetAttrElementsMap>>
+ element_explicitly_set_attr_elements_map_;
+
+ Member<IntersectionObserver> display_lock_activation_observer_;
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl
index 69af8b4520b..f49890f9c32 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document.idl
@@ -188,6 +188,9 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// Non-standard APIs
[MeasureAs=DocumentCaretRangeFromPoint] Range caretRangeFromPoint([DefaultValue=Undefined] optional long x, [DefaultValue=Undefined] optional long y);
+ // Storage Access API
+ [CallWith=ScriptState, NewObject, RuntimeEnabled=StorageAccessAPI] Promise<boolean> hasStorageAccess();
+ [CallWith=ScriptState, NewObject, RuntimeEnabled=StorageAccessAPI] Promise<void> requestStorageAccess();
// https://w3c.github.io/webappsec-feature-policy/#the-policy-object
[RuntimeEnabled=FeaturePolicyJavaScriptInterface] readonly attribute FeaturePolicy featurePolicy;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.cc b/chromium/third_party/blink/renderer/core/dom/document_init.cc
index 6cd86383a57..bc4df38ace2 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.cc
@@ -94,19 +94,15 @@ DocumentLoader* DocumentInit::MasterDocumentLoader() const {
}
WebSandboxFlags DocumentInit::GetSandboxFlags() const {
- DocumentLoader* loader = MasterDocumentLoader();
WebSandboxFlags flags = sandbox_flags_;
- if (loader) {
+ if (DocumentLoader* loader = MasterDocumentLoader())
flags |= loader->GetFrame()->Loader().EffectiveSandboxFlags();
-
- // If the load was blocked by CSP, force the Document's origin to be unique,
- // so that the blocked document appears to be a normal cross-origin
- // document's load per CSP spec:
- // https://www.w3.org/TR/CSP3/#directive-frame-ancestors.
- if (loader->WasBlockedAfterCSP()) {
- flags |= WebSandboxFlags::kOrigin;
- }
- }
+ // If the load was blocked by CSP, force the Document's origin to be unique,
+ // so that the blocked document appears to be a normal cross-origin
+ // document's load per CSP spec:
+ // https://www.w3.org/TR/CSP3/#directive-frame-ancestors.
+ if (blocked_by_csp_)
+ flags |= WebSandboxFlags::kOrigin;
return flags;
}
@@ -214,6 +210,17 @@ DocumentInit& DocumentInit::WithSrcdocDocument(bool is_srcdoc_document) {
return *this;
}
+DocumentInit& DocumentInit::WithBlockedByCSP(bool blocked_by_csp) {
+ blocked_by_csp_ = blocked_by_csp;
+ return *this;
+}
+
+DocumentInit& DocumentInit::WithGrantLoadLocalResources(
+ bool grant_load_local_resources) {
+ grant_load_local_resources_ = grant_load_local_resources;
+ return *this;
+}
+
DocumentInit& DocumentInit::WithRegistrationContext(
V0CustomElementRegistrationContext* registration_context) {
DCHECK(!create_new_registration_context_);
diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.h b/chromium/third_party/blink/renderer/core/dom/document_init.h
index e68384c4607..21d95304518 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_init.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_init.h
@@ -80,6 +80,7 @@ class CORE_EXPORT DocumentInit final {
WebInsecureRequestPolicy GetInsecureRequestPolicy() const;
const SecurityContext::InsecureNavigationsSet* InsecureNavigationsToUpgrade()
const;
+ bool GrantLoadLocalResources() const { return grant_load_local_resources_; }
Settings* GetSettings() const;
@@ -118,6 +119,8 @@ class CORE_EXPORT DocumentInit final {
network::mojom::IPAddressSpace GetIPAddressSpace() const;
DocumentInit& WithSrcdocDocument(bool is_srcdoc_document);
+ DocumentInit& WithBlockedByCSP(bool blocked_by_csp);
+ DocumentInit& WithGrantLoadLocalResources(bool grant_load_local_resources);
DocumentInit& WithRegistrationContext(V0CustomElementRegistrationContext*);
V0CustomElementRegistrationContext* RegistrationContext(Document*) const;
@@ -178,6 +181,13 @@ class CORE_EXPORT DocumentInit final {
// the parent document, not from loading a URL.
bool is_srcdoc_document_ = false;
+ // Whether the actual document was blocked by csp and we are creating a dummy
+ // empty document instead.
+ bool blocked_by_csp_ = false;
+
+ // Whether the document should be able to access local file:// resources.
+ bool grant_load_local_resources_ = false;
+
Member<V0CustomElementRegistrationContext> registration_context_;
bool create_new_registration_context_;
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 16860fde376..fffbc14c425 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser.h
@@ -37,9 +37,8 @@ class DocumentParserClient;
class ScriptableDocumentParser;
class TextResourceDecoder;
-class CORE_EXPORT DocumentParser
- : public GarbageCollectedFinalized<DocumentParser>,
- public NameClient {
+class CORE_EXPORT DocumentParser : public GarbageCollected<DocumentParser>,
+ public NameClient {
public:
virtual ~DocumentParser();
virtual void Trace(Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
index 323029be01e..96484aeb313 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
@@ -15,7 +15,7 @@ namespace blink {
// DocumentParserTiming is responsible for tracking parser-related timings for a
// given document.
class DocumentParserTiming final
- : public GarbageCollectedFinalized<DocumentParserTiming>,
+ : public GarbageCollected<DocumentParserTiming>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(DocumentParserTiming);
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 c7675d16ceb..12538a28caa 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
@@ -164,13 +164,13 @@ bool HasOpenGraphArticle(const Element& head) {
DEFINE_STATIC_LOCAL(AtomicString, property_attr, ("property"));
for (const Element* child = ElementTraversal::FirstChild(head); child;
child = ElementTraversal::NextSibling(*child)) {
- if (!IsHTMLMetaElement(*child))
+ auto* meta = DynamicTo<HTMLMetaElement>(child);
+ if (!meta)
continue;
- const HTMLMetaElement& meta = ToHTMLMetaElement(*child);
- if (meta.GetName() == og_type ||
- meta.getAttribute(property_attr) == og_type) {
- if (DeprecatedEqualIgnoringCase(meta.Content(), "article")) {
+ if (meta->GetName() == og_type ||
+ meta->getAttribute(property_attr) == og_type) {
+ if (DeprecatedEqualIgnoringCase(meta->Content(), "article")) {
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document_test.cc b/chromium/third_party/blink/renderer/core/dom/document_test.cc
index d71b363daf7..99eebc46873 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_test.cc
@@ -63,7 +63,6 @@
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.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"
@@ -92,7 +91,7 @@ void DocumentTest::SetHtmlInnerHTML(const char* html_content) {
namespace {
class TestSynchronousMutationObserver
- : public GarbageCollectedFinalized<TestSynchronousMutationObserver>,
+ : public GarbageCollected<TestSynchronousMutationObserver>,
public SynchronousMutationObserver {
USING_GARBAGE_COLLECTED_MIXIN(TestSynchronousMutationObserver);
@@ -262,7 +261,7 @@ void TestSynchronousMutationObserver::Trace(Visitor* visitor) {
}
class TestDocumentShutdownObserver
- : public GarbageCollectedFinalized<TestDocumentShutdownObserver>,
+ : public GarbageCollected<TestDocumentShutdownObserver>,
public DocumentShutdownObserver {
USING_GARBAGE_COLLECTED_MIXIN(TestDocumentShutdownObserver);
@@ -298,7 +297,7 @@ void TestDocumentShutdownObserver::Trace(Visitor* visitor) {
}
class MockDocumentValidationMessageClient
- : public GarbageCollectedFinalized<MockDocumentValidationMessageClient>,
+ : public GarbageCollected<MockDocumentValidationMessageClient>,
public ValidationMessageClient {
USING_GARBAGE_COLLECTED_MIXIN(MockDocumentValidationMessageClient);
@@ -338,7 +337,8 @@ class MockApplicationCacheHost final : public ApplicationCacheHostForFrame {
explicit MockApplicationCacheHost(DocumentLoader* loader)
: ApplicationCacheHostForFrame(loader,
GetEmptyBrowserInterfaceBroker(),
- /*task_runner=*/nullptr) {}
+ /*task_runner=*/nullptr,
+ base::UnguessableToken()) {}
~MockApplicationCacheHost() override = default;
void SelectCacheWithoutManifest() override {
@@ -973,27 +973,6 @@ TEST_F(DocumentTest, ViewportPropagationNoRecalc) {
EXPECT_EQ(1, new_element_count - old_element_count);
}
-class InvalidatorObserver : public InterfaceInvalidator::Observer {
- public:
- void OnInvalidate() override { ++invalidate_called_counter_; }
-
- int CountInvalidateCalled() const { return invalidate_called_counter_; }
-
- private:
- int invalidate_called_counter_ = 0;
-};
-
-TEST_F(DocumentTest, InterfaceInvalidatorDestruction) {
- InvalidatorObserver obs;
- InterfaceInvalidator* invalidator = GetDocument().GetInterfaceInvalidator();
- invalidator->AddObserver(&obs);
- EXPECT_EQ(obs.CountInvalidateCalled(), 0);
-
- GetDocument().Shutdown();
- EXPECT_FALSE(GetDocument().GetInterfaceInvalidator());
- EXPECT_EQ(1, obs.CountInvalidateCalled());
-}
-
// Test fixture parameterized on whether the "IsolatedWorldCSP" feature is
// enabled.
class IsolatedWorldCSPTest : public DocumentTest,
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc b/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
index b20d2b259d8..14897c38a18 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
@@ -254,13 +254,21 @@ void DOMTokenList::UpdateWithTokenSet(const SpaceSplitString& token_set) {
setValue(token_set.SerializeToString());
}
+AtomicString DOMTokenList::value() const {
+ DCHECK_NE(attribute_name_, g_null_name)
+ << "The subclass of DOMTokenList should override value().";
+ return element_->getAttribute(attribute_name_);
+}
+
void DOMTokenList::setValue(const AtomicString& value) {
+ DCHECK_NE(attribute_name_, g_null_name)
+ << "The subclass of DOMTokenList should override setValue().";
element_->setAttribute(attribute_name_, value);
+ // setAttribute() will call DidUpdateAttributeValue().
}
void DOMTokenList::DidUpdateAttributeValue(const AtomicString& old_value,
const AtomicString& new_value) {
- value_ = new_value;
if (is_in_update_step_)
return;
if (old_value != new_value)
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_token_list.h b/chromium/third_party/blink/renderer/core/dom/dom_token_list.h
index 900be185ee4..713f4d1b5c3 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_token_list.h
+++ b/chromium/third_party/blink/renderer/core/dom/dom_token_list.h
@@ -59,9 +59,9 @@ class CORE_EXPORT DOMTokenList : public ScriptWrappable {
const AtomicString& new_token,
ExceptionState&);
bool supports(const AtomicString&, ExceptionState&);
- const AtomicString& value() const { return value_; }
- void setValue(const AtomicString&);
- const AtomicString& toString() const { return value(); }
+ virtual AtomicString value() const;
+ virtual void setValue(const AtomicString&);
+ AtomicString toString() const { return value(); }
// This function should be called when the associated attribute value was
// updated.
@@ -84,8 +84,11 @@ class CORE_EXPORT DOMTokenList : public ScriptWrappable {
void UpdateWithTokenSet(const SpaceSplitString&);
SpaceSplitString token_set_;
- AtomicString value_;
const Member<Element> element_;
+ // Normal DOMTokenList instances is associated to an attribute name.
+ // So |attribute_name_| is typically an html_names::kFooAttr.
+ // CustomStateTokenList is associated to no attribute name.
+ // |attribute_name_| is |g_null_name| in that case.
const QualifiedName attribute_name_;
bool is_in_update_step_ = false;
DISALLOW_COPY_AND_ASSIGN(DOMTokenList);
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc
index 90fe5cb095f..22ee7dab60c 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element.cc
@@ -32,13 +32,13 @@
#include "cc/input/snap_selection_strategy.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
+#include "third_party/blink/renderer/bindings/core/v8/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.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url_or_trusted_url.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script_url.h"
#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_display_lock_options.h"
#include "third_party/blink/renderer/core/accessibility/ax_context.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
@@ -115,11 +115,13 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
#include "third_party/blink/renderer/core/html/forms/html_form_controls_collection.h"
#include "third_party/blink/renderer/core/html/forms/html_options_collection.h"
+#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+#include "third_party/blink/renderer/core/html/html_html_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/html_table_rows_collection.h"
@@ -127,6 +129,7 @@
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
#include "third_party/blink/renderer/core/invisible_dom/activate_invisible_event.h"
@@ -323,8 +326,7 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
return true;
}
- if (style.Display() == EDisplay::kWebkitBox ||
- style.Display() == EDisplay::kWebkitInlineBox)
+ if (style.IsDeprecatedWebkitBox())
return true;
if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
@@ -334,6 +336,16 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element,
return true;
if (document.Printing() && element == document.documentElement())
return true;
+
+ // Fall back to legacy layout for frameset documents. The frameset itself
+ // (and the frames) can only create legacy layout objects anyway (no NG
+ // counterpart for them yet). However, the layout object for the HTML root
+ // element would be an NG one. If we'd then print the document, we'd fall
+ // back to legacy layout (because of the above check), which would re-attach
+ // all layout objects, which would cause the frameset to lose state of some
+ // sort, leaving everything blank when printed.
+ if (document.IsFrameSet())
+ return true;
}
// 'text-combine-upright' property is not supported yet.
@@ -385,13 +397,31 @@ bool HasUpwardDirection(const Element& element) {
bool IsElementReflectionAttribute(const QualifiedName& name) {
if (name == html_names::kAriaActivedescendantAttr)
return true;
- if (name == html_names::kAriaErrormessageAttr)
+ if (name == html_names::kAriaControlsAttr)
+ return true;
+ if (name == html_names::kAriaDescribedbyAttr)
return true;
if (name == html_names::kAriaDetailsAttr)
return true;
+ if (name == html_names::kAriaErrormessageAttr)
+ return true;
+ if (name == html_names::kAriaFlowtoAttr)
+ return true;
+ if (name == html_names::kAriaLabelledbyAttr)
+ return true;
+ if (name == html_names::kAriaOwnsAttr)
+ return true;
return false;
}
+HeapVector<Member<Element>>* GetExplicitlySetElementsForAttr(
+ Element* element,
+ QualifiedName name) {
+ ExplicitlySetAttrElementsMap* element_attribute_map =
+ element->GetDocument().GetExplicitlySetAttrElementsMap(element);
+ return element_attribute_map->at(name);
+}
+
// Checks that the given element |candidate| is a descendant of
// |attribute_element|'s shadow including ancestors.
bool ElementIsDescendantOfShadowIncludingAncestor(
@@ -410,6 +440,55 @@ bool ElementIsDescendantOfShadowIncludingAncestor(
return candidate.IsDescendantOf(document_element);
}
+// The first algorithm in
+// https://html.spec.whatwg.org/C/#the-autofocus-attribute
+void EnqueueAutofocus(Element& element) {
+ // When an element with the autofocus attribute specified is inserted into a
+ // document, run the following steps:
+ DCHECK(element.isConnected());
+ if (!element.IsAutofocusable())
+ return;
+
+ // 1. If the user has indicated (for example, by starting to type in a form
+ // control) that they do not wish focus to be changed, then optionally return.
+
+ // We don't implement this optional step. If other browsers have such
+ // behavior, we should follow it or standardize it.
+
+ // 2. Let target be the element's node document.
+ Document& doc = element.GetDocument();
+
+ // 3. If target's browsing context is null, then return.
+ if (!doc.GetFrame())
+ return;
+
+ // 4. If target's active sandboxing flag set has the sandboxed automatic
+ // features browsing context flag, then return.
+ if (doc.IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) {
+ doc.AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kSecurity,
+ mojom::ConsoleMessageLevel::kError,
+ "Blocked autofocusing on a form control because the form's frame is "
+ "sandboxed and the 'allow-scripts' permission is not set."));
+ return;
+ }
+
+ // 5. Let topDocument be the active document of target's browsing context's
+ // top-level browsing context.
+ // 6. If target's origin is not the same as the origin of topDocument,
+ // then return.
+ if (!doc.IsInMainFrame() &&
+ !doc.TopFrameOrigin()->CanAccess(doc.GetSecurityOrigin())) {
+ doc.AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kSecurity,
+ mojom::ConsoleMessageLevel::kError,
+ "Blocked autofocusing on a form control in a cross-origin subframe."));
+ return;
+ }
+
+ element.GetDocument().TopDocument().EnqueueAutofocusCandidate(element);
+}
+
} // namespace
Element* Element::Create(const QualifiedName& tag_name, Document* document) {
@@ -481,17 +560,11 @@ bool Element::IsFocusableStyle() const {
EVisibility::kVisible;
}
- // Get the style from |StyleResolver::StyleForElement()| if we're in a
- // display-locked subtree, because it isn't included in the normal style
- // updates. This will calculate the style without causing other side effects,
- // unlike triggering a forced style.layout recalc..
- if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) {
- scoped_refptr<ComputedStyle> style =
- GetDocument().EnsureStyleResolver().StyleForElement(
- const_cast<Element*>(this));
- return style->Display() != EDisplay::kNone &&
- style->Visibility() == EVisibility::kVisible;
- }
+ // Update style if we're in a display-locked subtree, because it isn't
+ // included in the normal style updates. We also need to update the layout
+ // here because some callers expect the layout stays clean.
+ if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this))
+ GetDocument().UpdateStyleAndLayoutForNode(this);
if (IsInsideInvisibleSubtree()) {
const ComputedStyle* style =
@@ -585,14 +658,14 @@ void Element::SetBooleanAttribute(const QualifiedName& name, bool value) {
void Element::SynchronizeContentAttributeAndElementReference(
const QualifiedName& name) {
- ExplicitlySetAttrElementMap* element_attribute_data =
- GetDocument().GetExplicitlySetAttrElementMap(this);
- element_attribute_data->erase(name);
+ ExplicitlySetAttrElementsMap* element_attribute_map =
+ GetDocument().GetExplicitlySetAttrElementsMap(this);
+ element_attribute_map->erase(name);
}
void Element::SetElementAttribute(const QualifiedName& name, Element* element) {
- ExplicitlySetAttrElementMap* element_attribute_data =
- GetDocument().GetExplicitlySetAttrElementMap(this);
+ ExplicitlySetAttrElementsMap* explicitly_set_attr_elements_map_ =
+ GetDocument().GetExplicitlySetAttrElementsMap(this);
// If the reflected element is explicitly null, or is not a member of this
// elements shadow including ancestor tree, then we remove the content
@@ -602,7 +675,7 @@ void Element::SetElementAttribute(const QualifiedName& name, Element* element) {
// https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:concept-shadow-including-ancestor
if (!element ||
!ElementIsDescendantOfShadowIncludingAncestor(*this, *element)) {
- element_attribute_data->erase(name);
+ explicitly_set_attr_elements_map_->erase(name);
removeAttribute(name);
return;
}
@@ -622,18 +695,27 @@ void Element::SetElementAttribute(const QualifiedName& name, Element* element) {
else
setAttribute(name, id);
- element_attribute_data->Set(name, element);
+ auto result = explicitly_set_attr_elements_map_->insert(name, nullptr);
+ if (result.is_new_entry) {
+ result.stored_value->value =
+ MakeGarbageCollected<HeapVector<Member<Element>>>();
+ } else {
+ result.stored_value->value->clear();
+ }
+ result.stored_value->value->push_back(element);
}
Element* Element::GetElementAttribute(const QualifiedName& name) {
- ExplicitlySetAttrElementMap* element_attribute_data =
- GetDocument().GetExplicitlySetAttrElementMap(this);
-
- Element* explicitly_set_element = element_attribute_data->at(name);
- // Only return the explicit element if it still exists in the same scope.
- if (explicitly_set_element && ElementIsDescendantOfShadowIncludingAncestor(
- *this, *explicitly_set_element))
- return explicitly_set_element;
+ HeapVector<Member<Element>>* element_attribute_vector =
+ GetExplicitlySetElementsForAttr(this, name);
+ if (element_attribute_vector) {
+ DCHECK_EQ(element_attribute_vector->size(), 1u);
+ Element* explicitly_set_element = element_attribute_vector->at(0);
+ // Only return the explicit element if it still exists in the same scope.
+ if (explicitly_set_element && ElementIsDescendantOfShadowIncludingAncestor(
+ *this, *explicitly_set_element))
+ return explicitly_set_element;
+ }
// Compute the attr-associated element, this can be null.
AtomicString id = getAttribute(name);
@@ -644,6 +726,84 @@ Element* Element::GetElementAttribute(const QualifiedName& name) {
return GetTreeScope().getElementById(id);
}
+void Element::SetElementArrayAttribute(
+ const QualifiedName& name,
+ HeapVector<Member<Element>> given_elements,
+ bool is_null) {
+ ExplicitlySetAttrElementsMap* element_attribute_map =
+ GetDocument().GetExplicitlySetAttrElementsMap(this);
+
+ if (is_null) {
+ element_attribute_map->erase(name);
+ removeAttribute(name);
+ return;
+ }
+
+ // Get or create element array, and remove any pre-existing elements.
+ // Note that this performs two look ups on |name| within the map, as
+ // modifying the content attribute will cause the synchronization steps to
+ // be run which with modifies the hash map, and can cause a rehash.
+ HeapVector<Member<Element>>* elements = element_attribute_map->at(name);
+ if (!elements)
+ elements = MakeGarbageCollected<HeapVector<Member<Element>>>();
+ else
+ elements->clear();
+ SpaceSplitString value;
+
+ for (auto element : given_elements) {
+ if (!ElementIsDescendantOfShadowIncludingAncestor(*this, *element))
+ continue;
+ if (value.IsNull() && !elements->IsEmpty()) {
+ elements->push_back(element);
+ continue;
+ }
+ elements->push_back(element);
+ const AtomicString given_element_id = element->GetIdAttribute();
+ if (given_element_id.IsNull() ||
+ GetTreeScope() != element->GetTreeScope() ||
+ GetTreeScope().getElementById(given_element_id) != element) {
+ value.Clear();
+ continue;
+ }
+ value.Add(given_element_id);
+ }
+
+ setAttribute(name, value.SerializeToString());
+ element_attribute_map->Set(name, elements);
+}
+
+HeapVector<Member<Element>> Element::GetElementArrayAttribute(
+ const QualifiedName& name,
+ bool& is_null) {
+ HeapVector<Member<Element>>* explicitly_set_elements =
+ GetExplicitlySetElementsForAttr(this, name);
+ is_null = false;
+ if (explicitly_set_elements) {
+ HeapVector<Member<Element>> return_elements;
+ for (auto element : *explicitly_set_elements) {
+ if (ElementIsDescendantOfShadowIncludingAncestor(*this, *element))
+ return_elements.push_back(element);
+ }
+ return return_elements;
+ }
+
+ String attribute_value = getAttribute(name).GetString();
+ HeapVector<Member<Element>> content_elements;
+
+ Vector<String> tokens;
+ attribute_value = attribute_value.SimplifyWhiteSpace();
+ attribute_value.Split(' ', tokens);
+
+ for (auto token : tokens) {
+ Element* candidate = GetTreeScope().getElementById(AtomicString(token));
+ if (candidate)
+ content_elements.push_back(candidate);
+ }
+ if (content_elements.IsEmpty())
+ is_null = true;
+ return content_elements;
+}
+
NamedNodeMap* Element::attributesForBindings() const {
ElementRareData& rare_data =
const_cast<Element*>(this)->EnsureElementRareData();
@@ -905,7 +1065,7 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options,
}
void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions* options) {
- ActivateDisplayLockIfNeeded();
+ ActivateDisplayLockIfNeeded(DisplayLockActivationReason::kUser);
GetDocument().EnsurePaintLocationDataValidForNode(this);
ScrollIntoViewNoVisualUpdate(options);
}
@@ -915,7 +1075,7 @@ void Element::ScrollIntoViewNoVisualUpdate(
if (!GetLayoutObject() || !GetDocument().GetPage())
return;
- if (DisplayLockPreventsActivation())
+ if (DisplayLockPreventsActivation(DisplayLockActivationReason::kUser))
return;
ScrollBehavior behavior = (options->behavior() == "smooth")
@@ -1054,7 +1214,9 @@ int Element::clientWidth() {
if (LayoutBox* layout_object = GetLayoutBox())
return AdjustForAbsoluteZoom::AdjustLayoutUnit(
- LayoutUnit(layout_object->PixelSnappedClientWidth()),
+ LayoutUnit(
+ layout_object
+ ->PixelSnappedClientWidthWithTableSpecialBehavior()),
layout_object->StyleRef())
.Round();
return 0;
@@ -1090,7 +1252,9 @@ int Element::clientHeight() {
if (LayoutBox* layout_object = GetLayoutBox())
return AdjustForAbsoluteZoom::AdjustLayoutUnit(
- LayoutUnit(layout_object->PixelSnappedClientHeight()),
+ LayoutUnit(
+ layout_object
+ ->PixelSnappedClientHeightWithTableSpecialBehavior()),
layout_object->StyleRef())
.Round();
return 0;
@@ -1125,8 +1289,16 @@ double Element::scrollLeft() {
kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
}
- return AdjustForAbsoluteZoom::AdjustScroll(
- scrollable_area->ScrollPosition().X(), *GetLayoutBox());
+ // In order to keep the behavior of element scroll consistent with document
+ // scroll, and consistent with the behavior of other vendors, the scrollLeft
+ // of a box is changed to the offset from |ScrollOrigin()|.
+ if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) {
+ return AdjustForAbsoluteZoom::AdjustScroll(
+ scrollable_area->GetScrollOffset().Width(), *GetLayoutBox());
+ } else {
+ return AdjustForAbsoluteZoom::AdjustScroll(
+ scrollable_area->ScrollPosition().X(), *GetLayoutBox());
+ }
}
return 0;
@@ -1154,8 +1326,16 @@ double Element::scrollTop() {
kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
}
- return AdjustForAbsoluteZoom::AdjustScroll(
- scrollable_area->ScrollPosition().Y(), *GetLayoutBox());
+ // In order to keep the behavior of element scroll consistent with document
+ // scroll, and consistent with the behavior of other vendors, the scrollTop
+ // of a box is changed to the offset from |ScrollOrigin()|.
+ if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) {
+ return AdjustForAbsoluteZoom::AdjustScroll(
+ scrollable_area->GetScrollOffset().Height(), *GetLayoutBox());
+ } else {
+ return AdjustForAbsoluteZoom::AdjustScroll(
+ scrollable_area->ScrollPosition().Y(), *GetLayoutBox());
+ }
}
return 0;
@@ -1192,20 +1372,38 @@ void Element::setScrollLeft(double new_left) {
}
}
- FloatPoint end_point(new_left * box->Style()->EffectiveZoom(),
- scrollable_area->ScrollPosition().Y());
- std::unique_ptr<cc::SnapSelectionStrategy> strategy =
- cc::SnapSelectionStrategy::CreateForEndPosition(
- gfx::ScrollOffset(end_point), true, false);
- end_point = GetDocument()
- .GetSnapCoordinator()
- ->GetSnapPosition(*box, *strategy)
- .value_or(end_point);
-
- FloatPoint new_position(end_point.X(),
- scrollable_area->ScrollPosition().Y());
- scrollable_area->ScrollToAbsolutePosition(new_position,
- kScrollBehaviorAuto);
+ if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) {
+ ScrollOffset end_offset(new_left * box->Style()->EffectiveZoom(),
+ scrollable_area->GetScrollOffset().Height());
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(
+ scrollable_area->ScrollOffsetToPosition(end_offset)),
+ true, false);
+ base::Optional<FloatPoint> snap_point =
+ GetDocument().GetSnapCoordinator().GetSnapPosition(*box, *strategy);
+ if (snap_point.has_value()) {
+ end_offset =
+ scrollable_area->ScrollPositionToOffset(snap_point.value());
+ }
+ scrollable_area->SetScrollOffset(end_offset, kProgrammaticScroll,
+ kScrollBehaviorAuto);
+ } else {
+ FloatPoint end_point(new_left * box->Style()->EffectiveZoom(),
+ scrollable_area->ScrollPosition().Y());
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(end_point), true, false);
+ end_point = GetDocument()
+ .GetSnapCoordinator()
+ .GetSnapPosition(*box, *strategy)
+ .value_or(end_point);
+
+ FloatPoint new_position(end_point.X(),
+ scrollable_area->ScrollPosition().Y());
+ scrollable_area->ScrollToAbsolutePosition(new_position,
+ kScrollBehaviorAuto);
+ }
}
}
@@ -1240,19 +1438,38 @@ void Element::setScrollTop(double new_top) {
}
}
- FloatPoint end_point(scrollable_area->ScrollPosition().X(),
- new_top * box->Style()->EffectiveZoom());
- std::unique_ptr<cc::SnapSelectionStrategy> strategy =
- cc::SnapSelectionStrategy::CreateForEndPosition(
- gfx::ScrollOffset(end_point), false, true);
- end_point = GetDocument()
- .GetSnapCoordinator()
- ->GetSnapPosition(*box, *strategy)
- .value_or(end_point);
- FloatPoint new_position(scrollable_area->ScrollPosition().X(),
- end_point.Y());
- scrollable_area->ScrollToAbsolutePosition(new_position,
- kScrollBehaviorAuto);
+ if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) {
+ ScrollOffset end_offset(scrollable_area->GetScrollOffset().Width(),
+ new_top * box->Style()->EffectiveZoom());
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(
+ scrollable_area->ScrollOffsetToPosition(end_offset)),
+ false, true);
+ base::Optional<FloatPoint> snap_point =
+ GetDocument().GetSnapCoordinator().GetSnapPosition(*box, *strategy);
+ if (snap_point.has_value()) {
+ end_offset =
+ scrollable_area->ScrollPositionToOffset(snap_point.value());
+ }
+
+ scrollable_area->SetScrollOffset(end_offset, kProgrammaticScroll,
+ kScrollBehaviorAuto);
+ } else {
+ FloatPoint end_point(scrollable_area->ScrollPosition().X(),
+ new_top * box->Style()->EffectiveZoom());
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(end_point), false, true);
+ end_point = GetDocument()
+ .GetSnapCoordinator()
+ .GetSnapPosition(*box, *strategy)
+ .value_or(end_point);
+ FloatPoint new_position(scrollable_area->ScrollPosition().X(),
+ end_point.Y());
+ scrollable_area->ScrollToAbsolutePosition(new_position,
+ kScrollBehaviorAuto);
+ }
}
}
@@ -1372,7 +1589,7 @@ void Element::ScrollLayoutBoxBy(const ScrollToOptions* scroll_to_options) {
displacement);
new_position = GetDocument()
.GetSnapCoordinator()
- ->GetSnapPosition(*box, *strategy)
+ .GetSnapPosition(*box, *strategy)
.value_or(new_position);
scrollable_area->ScrollToAbsolutePosition(new_position, scroll_behavior);
}
@@ -1386,54 +1603,86 @@ void Element::ScrollLayoutBoxTo(const ScrollToOptions* scroll_to_options) {
if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) {
LayoutBox* box = GetLayoutBox();
DCHECK(box);
- FloatPoint new_position(scrollable_area->ScrollPosition().X(),
- scrollable_area->ScrollPosition().Y());
- if (scroll_to_options->hasLeft()) {
- if (HasLeftwardDirection(*this)) {
+ if (scroll_to_options->hasLeft() && HasLeftwardDirection(*this)) {
+ UseCounter::Count(
+ GetDocument(),
+ WebFeature::
+ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
+ if (scroll_to_options->left() > 0) {
UseCounter::Count(
GetDocument(),
WebFeature::
- kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
- if (scroll_to_options->left() > 0) {
- UseCounter::Count(
- GetDocument(),
- WebFeature::
- kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTopSetPositive);
- }
+ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTopSetPositive);
}
-
- new_position.SetX(
- ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->left()) *
- box->Style()->EffectiveZoom());
}
- if (scroll_to_options->hasTop()) {
- if (HasUpwardDirection(*this)) {
+ if (scroll_to_options->hasTop() && HasUpwardDirection(*this)) {
+ UseCounter::Count(
+ GetDocument(),
+ WebFeature::
+ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
+ if (scroll_to_options->top() > 0) {
UseCounter::Count(
GetDocument(),
WebFeature::
- kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop);
- if (scroll_to_options->top() > 0) {
- UseCounter::Count(
- GetDocument(),
- WebFeature::
- kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTopSetPositive);
- }
+ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTopSetPositive);
}
-
- new_position.SetY(
- ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) *
- box->Style()->EffectiveZoom());
}
- std::unique_ptr<cc::SnapSelectionStrategy> strategy =
- cc::SnapSelectionStrategy::CreateForEndPosition(
- gfx::ScrollOffset(new_position), scroll_to_options->hasLeft(),
- scroll_to_options->hasTop());
- new_position = GetDocument()
- .GetSnapCoordinator()
- ->GetSnapPosition(*box, *strategy)
- .value_or(new_position);
- scrollable_area->ScrollToAbsolutePosition(new_position, scroll_behavior);
+ // In order to keep the behavior of element scroll consistent with document
+ // scroll, and consistent with the behavior of other vendors, the
+ // offsets in |scroll_to_options| are treated as the offset from
+ // |ScrollOrigin()|.
+ if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) {
+ ScrollOffset new_offset = scrollable_area->GetScrollOffset();
+ if (scroll_to_options->hasLeft()) {
+ new_offset.SetWidth(ScrollableArea::NormalizeNonFiniteScroll(
+ scroll_to_options->left()) *
+ box->Style()->EffectiveZoom());
+ }
+ if (scroll_to_options->hasTop()) {
+ new_offset.SetHeight(
+ ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) *
+ box->Style()->EffectiveZoom());
+ }
+
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(
+ scrollable_area->ScrollOffsetToPosition(new_offset)),
+ scroll_to_options->hasLeft(), scroll_to_options->hasTop());
+ base::Optional<FloatPoint> snap_point =
+ GetDocument().GetSnapCoordinator().GetSnapPosition(*box, *strategy);
+ if (snap_point.has_value()) {
+ new_offset =
+ scrollable_area->ScrollPositionToOffset(snap_point.value());
+ }
+
+ scrollable_area->SetScrollOffset(new_offset, kProgrammaticScroll,
+ scroll_behavior);
+ } else {
+ FloatPoint new_position(scrollable_area->ScrollPosition().X(),
+ scrollable_area->ScrollPosition().Y());
+ if (scroll_to_options->hasLeft()) {
+ new_position.SetX(ScrollableArea::NormalizeNonFiniteScroll(
+ scroll_to_options->left()) *
+ box->Style()->EffectiveZoom());
+ }
+ if (scroll_to_options->hasTop()) {
+ new_position.SetY(
+ ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) *
+ box->Style()->EffectiveZoom());
+ }
+
+ std::unique_ptr<cc::SnapSelectionStrategy> strategy =
+ cc::SnapSelectionStrategy::CreateForEndPosition(
+ gfx::ScrollOffset(new_position), scroll_to_options->hasLeft(),
+ scroll_to_options->hasTop());
+ new_position = GetDocument()
+ .GetSnapCoordinator()
+ .GetSnapPosition(*box, *strategy)
+ .value_or(new_position);
+ scrollable_area->ScrollToAbsolutePosition(new_position, scroll_behavior);
+ }
}
}
@@ -1467,11 +1716,10 @@ void Element::ScrollFrameBy(const ScrollToOptions* scroll_to_options) {
std::unique_ptr<cc::SnapSelectionStrategy> strategy =
cc::SnapSelectionStrategy::CreateForEndAndDirection(current_position,
displacement);
- new_position =
- GetDocument()
- .GetSnapCoordinator()
- ->GetSnapPosition(*GetDocument().GetLayoutView(), *strategy)
- .value_or(new_position);
+ new_position = GetDocument()
+ .GetSnapCoordinator()
+ .GetSnapPosition(*GetDocument().GetLayoutView(), *strategy)
+ .value_or(new_position);
viewport->SetScrollOffset(viewport->ScrollPositionToOffset(new_position),
kProgrammaticScroll, scroll_behavior);
}
@@ -1505,11 +1753,10 @@ void Element::ScrollFrameTo(const ScrollToOptions* scroll_to_options) {
cc::SnapSelectionStrategy::CreateForEndPosition(
gfx::ScrollOffset(new_position), scroll_to_options->hasLeft(),
scroll_to_options->hasTop());
- new_position =
- GetDocument()
- .GetSnapCoordinator()
- ->GetSnapPosition(*GetDocument().GetLayoutView(), *strategy)
- .value_or(new_position);
+ new_position = GetDocument()
+ .GetSnapCoordinator()
+ .GetSnapPosition(*GetDocument().GetLayoutView(), *strategy)
+ .value_or(new_position);
new_offset = viewport->ScrollPositionToOffset(new_position);
viewport->SetScrollOffset(new_offset, kProgrammaticScroll, scroll_behavior);
}
@@ -2116,14 +2363,28 @@ void Element::AttributeChanged(const AttributeModificationParams& params) {
GetElementData()->presentation_attribute_style_is_dirty_ = true;
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::FromAttribute(name));
- } else if (RuntimeEnabledFeatures::DisplayLockingEnabled() &&
+ } else if (RuntimeEnabledFeatures::DisplayLockingEnabled(
+ GetExecutionContext()) &&
name == html_names::kRendersubtreeAttr &&
params.old_value != params.new_value) {
+ UseCounter::Count(GetDocument(), WebFeature::kRenderSubtreeAttribute);
+
+ // This is needed to ensure that proper containment is put in place.
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::FromAttribute(name));
SpaceSplitString tokens(params.new_value.LowerASCII());
- const bool should_be_activatable = tokens.Contains("activatable");
- EnsureDisplayLockContext().SetActivatable(should_be_activatable);
+ unsigned char activation_mask =
+ static_cast<unsigned char>(DisplayLockActivationReason::kAny);
+
+ // Figure out the activation mask.
+ if (tokens.Contains("skip-activation"))
+ activation_mask = 0;
+ if (tokens.Contains("skip-viewport-activation")) {
+ activation_mask &=
+ ~static_cast<unsigned char>(DisplayLockActivationReason::kViewport);
+ }
+
+ EnsureDisplayLockContext().SetActivatable(activation_mask);
const bool should_be_invisible = tokens.Contains("invisible");
if (should_be_invisible) {
if (!GetDisplayLockContext()->IsLocked())
@@ -2412,9 +2673,16 @@ Node::InsertionNotificationRequest Element::InsertedInto(
}
}
}
+
+ if (isConnected()) {
+ if (auto* context = rare_data->GetDisplayLockContext())
+ context->ElementConnected();
+ }
}
if (isConnected()) {
+ EnqueueAutofocus(*this);
+
if (GetCustomElementState() == CustomElementState::kCustom)
CustomElement::EnqueueConnectedCallback(*this);
else if (IsUpgradedV0CustomElement())
@@ -2499,13 +2767,18 @@ void Element::RemovedFrom(ContainerNode& insertion_point) {
if (ElementAnimations* element_animations = data->GetElementAnimations())
element_animations->CssAnimations().Cancel();
- if (data->IntersectionObserverData()) {
+ if (was_in_document && data->IntersectionObserverData()) {
data->IntersectionObserverData()->ComputeIntersectionsForTarget(
IntersectionObservation::kExplicitRootObserversNeedUpdate |
- IntersectionObservation::kImplicitRootObserversNeedUpdate);
+ IntersectionObservation::kImplicitRootObserversNeedUpdate |
+ IntersectionObservation::kIgnoreDelay);
GetDocument().EnsureIntersectionObserverController().RemoveTrackedElement(
*this);
}
+
+ if (auto* context = data->GetDisplayLockContext())
+ context->ElementDisconnected();
+
DCHECK(!data->HasPseudoElements());
}
@@ -2737,19 +3010,46 @@ void Element::RecalcStyle(const StyleRecalcChange change) {
// display locking can happen..
display_lock_style_scope.DidUpdateSelfStyle();
+ if (!display_lock_style_scope.ShouldUpdateChildStyle()) {
+ if (child_change.RecalcChildren()) {
+ // If we should've calculated the style for children but was blocked,
+ // notify so that we'd come back.
+ // Note that the if-clause wouldn't catch cases where
+ // ChildNeedsStyleRecalc() is true but child_change.RecalcChildren() is
+ // false. Since we are retaining the child dirty bit, that case is
+ // automatically handled without needing to notify it here.
+ display_lock_style_scope.NotifyUpdateWasBlocked(
+ DisplayLockContext::kStyleUpdateDescendants);
+
+ } else if (child_change.TraversePseudoElements(*this)) {
+ display_lock_style_scope.NotifyUpdateWasBlocked(
+ DisplayLockContext::kStyleUpdatePseudoElements);
+ }
+ if (HasCustomStyleCallbacks())
+ DidRecalcStyle(child_change);
+ return;
+ }
+
if (child_change.TraversePseudoElements(*this)) {
UpdatePseudoElement(kPseudoIdBackdrop, child_change);
UpdatePseudoElement(kPseudoIdBefore, child_change);
}
- const bool should_update_child_style =
- display_lock_style_scope.ShouldUpdateChildStyle();
- if (child_change.TraverseChildren(*this) && should_update_child_style) {
+ if (child_change.TraverseChildren(*this)) {
SelectorFilterParentScope filter_scope(*this);
if (ShadowRoot* root = GetShadowRoot()) {
- if (child_change.TraverseChild(*root))
- root->RecalcStyle(child_change);
- RecalcDescendantStyles(StyleRecalcChange::kClearEnsured);
+ if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
+ root->RecalcDescendantStyles(child_change);
+ } else {
+ if (child_change.TraverseChild(*root))
+ root->RecalcStyle(child_change);
+ RecalcDescendantStyles(StyleRecalcChange::kClearEnsured);
+ }
+ } else if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(this)) {
+ slot->RecalcStyleForSlotChildren(child_change);
+ } else if (IsActiveV0InsertionPoint(*this)) {
+ To<V0InsertionPoint>(this)->RecalcStyleForInsertionPointChildren(
+ child_change);
} else {
RecalcDescendantStyles(child_change);
}
@@ -2765,20 +3065,9 @@ void Element::RecalcStyle(const StyleRecalcChange change) {
UpdateFirstLetterPseudoElement(StyleUpdatePhase::kRecalc);
}
- if (should_update_child_style) {
ClearChildNeedsStyleRecalc();
// We've updated all the children that needs an update (might be 0).
display_lock_style_scope.DidUpdateChildStyle();
- } else if (child_change.RecalcChildren()) {
- // If we should've calculated the style for children but was blocked,
- // notify so that we'd come back.
- // Note that the if-clause wouldn't catch cases where
- // ChildNeedsStyleRecalc() is true but child_change.RecalcChildren() is
- // false. Since we are retaining the child dirty bit, that case is
- // automatically handled without needing to notify it here.
- display_lock_style_scope.NotifyUpdateWasBlocked(
- DisplayLockContext::kStyleUpdateDescendants);
- }
if (HasCustomStyleCallbacks())
DidRecalcStyle(child_change);
@@ -2807,7 +3096,7 @@ static const StyleRecalcChange ApplyComputedStyleDiff(
const StyleRecalcChange change,
ComputedStyle::Difference diff) {
if (change.RecalcDescendants() ||
- diff < ComputedStyle::Difference::kPseudoStyle)
+ diff < ComputedStyle::Difference::kPseudoElementStyle)
return change;
if (diff == ComputedStyle::Difference::kDisplayAffectingDescendantStyles)
return change.ForceRecalcDescendants();
@@ -2815,7 +3104,7 @@ static const StyleRecalcChange ApplyComputedStyleDiff(
return change.EnsureAtLeast(StyleRecalcChange::kRecalcChildren);
if (diff == ComputedStyle::Difference::kIndependentInherited)
return change.EnsureAtLeast(StyleRecalcChange::kIndependentInherit);
- DCHECK(diff == ComputedStyle::Difference::kPseudoStyle);
+ DCHECK(diff == ComputedStyle::Difference::kPseudoElementStyle);
return change.EnsureAtLeast(StyleRecalcChange::kUpdatePseudoElements);
}
@@ -2938,9 +3227,14 @@ StyleRecalcChange Element::RecalcOwnStyle(const StyleRecalcChange change) {
if (LayoutObject* layout_object = GetLayoutObject()) {
DCHECK(new_style);
- auto* this_element = DynamicTo<PseudoElement>(this);
- if (this_element && new_style->Display() == EDisplay::kContents) {
- new_style = this_element->LayoutStyleForDisplayContents(*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) {
+ layout_style =
+ pseudo_element->LayoutStyleForDisplayContents(*layout_style);
+ }
+ } else if (auto* html_element = DynamicTo<HTMLHtmlElement>(this)) {
+ 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,
@@ -2951,7 +3245,7 @@ StyleRecalcChange Element::RecalcOwnStyle(const StyleRecalcChange change) {
diff == ComputedStyle::Difference::kEqual
? LayoutObject::ApplyStyleChanges::kNo
: LayoutObject::ApplyStyleChanges::kYes;
- layout_object->SetStyle(new_style.get(), apply_changes);
+ layout_object->SetStyle(layout_style.get(), apply_changes);
}
return child_change;
}
@@ -3097,7 +3391,7 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
}
shadow_root->InsertedInto(*this);
- if (InActiveDocument())
+ if (InActiveDocument() && GetComputedStyle())
SetChildNeedsStyleRecalc();
SetNeedsStyleRecalc(kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kShadow));
@@ -3131,14 +3425,6 @@ void Element::SetAnimationStyleChange(bool animation_style_change) {
element_animations->SetAnimationStyleChange(animation_style_change);
}
-void Element::ClearAnimationStyleChange() {
- if (!HasRareData())
- return;
- if (ElementAnimations* element_animations =
- GetElementRareData()->GetElementAnimations())
- element_animations->SetAnimationStyleChange(false);
-}
-
void Element::SetNeedsAnimationStyleRecalc() {
if (GetDocument().InStyleRecalc())
return;
@@ -3147,7 +3433,8 @@ void Element::SetNeedsAnimationStyleRecalc() {
SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kAnimation));
- SetAnimationStyleChange(true);
+ if (NeedsStyleRecalc())
+ SetAnimationStyleChange(true);
}
void Element::SetNeedsCompositingUpdate() {
@@ -3747,6 +4034,7 @@ void Element::focus(const FocusParams& params) {
return;
if (AuthorShadowRoot() && AuthorShadowRoot()->delegatesFocus()) {
+ UseCounter::Count(GetDocument(), WebFeature::kDelegateFocus);
Element* focused_element = GetDocument().FocusedElement();
if (focused_element &&
IsShadowIncludingInclusiveAncestorOf(*focused_element))
@@ -3763,7 +4051,12 @@ void Element::focus(const FocusParams& params) {
return;
}
}
- ActivateDisplayLockIfNeeded();
+ // If script called focus(), then the type would be none. This means we are
+ // activating because of a script action (kUser). Otherwise, this is a
+ // viewport activation (kViewport).
+ ActivateDisplayLockIfNeeded(params.type == kWebFocusTypeNone
+ ? DisplayLockActivationReason::kUser
+ : DisplayLockActivationReason::kViewport);
DispatchActivateInvisibleEventIfNeeded();
if (IsInsideInvisibleSubtree()) {
// The element stays invisible because the default event action is
@@ -3917,7 +4210,7 @@ bool Element::IsKeyboardFocusable() const {
((SupportsFocus() && tabIndex() >= 0) ||
(RuntimeEnabledFeatures::KeyboardFocusableScrollersEnabled() &&
IsScrollableNode(this))) &&
- !DisplayLockPreventsActivation();
+ !DisplayLockPreventsActivation(DisplayLockActivationReason::kViewport);
}
bool Element::IsMouseFocusable() const {
@@ -3926,11 +4219,18 @@ bool Element::IsMouseFocusable() const {
DCHECK(!GetDocument().IsActive() ||
!GetDocument().NeedsLayoutTreeUpdateForNode(*this));
return isConnected() && !IsInert() && IsFocusableStyle() && SupportsFocus() &&
- !DisplayLockPreventsActivation();
+ !DisplayLockPreventsActivation(DisplayLockActivationReason::kViewport);
}
-bool Element::ActivateDisplayLockIfNeeded() {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled() ||
+bool Element::IsAutofocusable() const {
+ // https://html.spec.whatwg.org/C/#global-attributes
+ // https://svgwg.org/svg2-draft/struct.html#autofocusattribute
+ return (IsHTMLElement() || IsSVGElement()) &&
+ FastHasAttribute(html_names::kAutofocusAttr);
+}
+
+bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) {
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()) ||
GetDocument().LockedDisplayLockCount() ==
GetDocument().ActivationBlockingDisplayLockCount())
return false;
@@ -3942,8 +4242,9 @@ bool Element::ActivateDisplayLockIfNeeded() {
if (!ancestor_element)
continue;
if (auto* context = ancestor_element->GetDisplayLockContext()) {
- // If any of the ancestors is not activatable, we can't activate.
- if (!context->IsActivatable())
+ // If any of the ancestors is not activatable for the given reason, we
+ // can't activate.
+ if (!context->IsActivatable(reason))
return false;
activatable_targets.push_back(std::make_pair(
ancestor_element, &ancestor.GetTreeScope().Retarget(*this)));
@@ -3955,19 +4256,18 @@ bool Element::ActivateDisplayLockIfNeeded() {
// Dispatch event on activatable ancestor (target.first), with
// the retargeted element (target.second) as the |activatedElement|.
if (auto* context = target.first->GetDisplayLockContext()) {
- if (context->ShouldCommitForActivation()) {
+ if (context->ShouldCommitForActivation(reason)) {
activated = true;
- target.first->DispatchEvent(
- *MakeGarbageCollected<BeforeActivateEvent>(*target.second));
- context->CommitForActivation();
+ context->CommitForActivationWithSignal(target.second);
}
}
}
return activated;
}
-bool Element::DisplayLockPreventsActivation() const {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+bool Element::DisplayLockPreventsActivation(
+ DisplayLockActivationReason reason) const {
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()))
return false;
if (GetDocument().ActivationBlockingDisplayLockCount() == 0)
@@ -3985,7 +4285,7 @@ bool Element::DisplayLockPreventsActivation() const {
if (!current_element)
continue;
if (auto* context = current_element->GetDisplayLockContext()) {
- if (!context->IsActivatable())
+ if (!context->IsActivatable(reason))
return true;
}
}
@@ -4264,6 +4564,7 @@ void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html,
}
}
+// Step 4 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
Node* Element::InsertAdjacent(const String& where,
Node* new_child,
ExceptionState& exception_state) {
@@ -4344,13 +4645,8 @@ void Element::SetNeedsResizeObserverUpdate() {
}
}
-DisplayLockContext* Element::getDisplayLockForBindings() {
- return EnsureElementRareData().EnsureDisplayLockContext(
- this, GetExecutionContext());
-}
-
DisplayLockContext* Element::GetDisplayLockContext() const {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()))
return nullptr;
return HasRareData() ? GetElementRareData()->GetDisplayLockContext()
: nullptr;
@@ -4361,14 +4657,24 @@ DisplayLockContext& Element::EnsureDisplayLockContext() {
this, GetExecutionContext());
}
+ScriptPromise Element::updateRendering(ScriptState* script_state) {
+ auto* context = GetDisplayLockContext();
+ if (context)
+ return context->UpdateRendering(script_state);
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ auto promise = resolver->Promise();
+ resolver->Resolve();
+ return promise;
+}
+
// Step 1 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
-static Element* ContextElementForInsertion(const String& where,
- Element* element,
- ExceptionState& exception_state) {
+static Node* ContextNodeForInsertion(const String& where,
+ Element* element,
+ ExceptionState& exception_state) {
if (DeprecatedEqualIgnoringCase(where, "beforeBegin") ||
DeprecatedEqualIgnoringCase(where, "afterEnd")) {
- Element* parent = element->parentElement();
- if (!parent) {
+ Node* parent = element->parentNode();
+ if (!parent || IsA<Document>(parent)) {
exception_state.ThrowDOMException(
DOMExceptionCode::kNoModificationAllowedError,
"The element has no parent.");
@@ -4403,11 +4709,22 @@ void Element::insertAdjacentText(const String& where,
void Element::insertAdjacentHTML(const String& where,
const String& markup,
ExceptionState& exception_state) {
- Element* context_element =
- ContextElementForInsertion(where, this, exception_state);
- if (!context_element)
+ Node* context_node = ContextNodeForInsertion(where, this, exception_state);
+ if (!context_node)
return;
+ // Step 2 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
+ Element* context_element;
+ if (!IsA<Element>(context_node) ||
+ (context_node->GetDocument().IsHTMLDocument() &&
+ IsA<HTMLHtmlElement>(context_node))) {
+ context_element =
+ MakeGarbageCollected<HTMLBodyElement>(context_node->GetDocument());
+ } else {
+ context_element = To<Element>(context_node);
+ }
+
+ // Step 3 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
DocumentFragment* fragment = CreateFragmentForInnerOuterHTML(
markup, context_element, kAllowScriptingContent, "insertAdjacentHTML",
exception_state);
@@ -4598,7 +4915,7 @@ const ComputedStyle* Element::EnsureComputedStyle(
return element_style;
if (const ComputedStyle* pseudo_element_style =
- element_style->GetCachedPseudoStyle(pseudo_element_specifier))
+ element_style->GetCachedPseudoElementStyle(pseudo_element_specifier))
return pseudo_element_style;
const ComputedStyle* layout_parent_style = element_style;
@@ -4612,12 +4929,13 @@ const ComputedStyle* Element::EnsureComputedStyle(
scoped_refptr<ComputedStyle> result =
GetDocument().EnsureStyleResolver().PseudoStyleForElement(
this,
- PseudoStyleRequest(pseudo_element_specifier,
- PseudoStyleRequest::kForComputedStyle),
+ PseudoElementStyleRequest(
+ pseudo_element_specifier,
+ PseudoElementStyleRequest::kForComputedStyle),
element_style, layout_parent_style);
DCHECK(result);
result->SetIsEnsuredInDisplayNone();
- return element_style->AddCachedPseudoStyle(std::move(result));
+ return element_style->AddCachedPseudoElementStyle(std::move(result));
}
bool Element::HasDisplayContentsStyle() const {
@@ -4847,26 +5165,26 @@ LayoutObject* Element::PseudoElementLayoutObject(PseudoId pseudo_id) const {
}
const ComputedStyle* Element::CachedStyleForPseudoElement(
- const PseudoStyleRequest& request) {
+ const PseudoElementStyleRequest& request) {
const ComputedStyle* style = GetComputedStyle();
if (!style || (request.pseudo_id < kFirstInternalPseudoId &&
- !style->HasPseudoStyle(request.pseudo_id))) {
+ !style->HasPseudoElementStyle(request.pseudo_id))) {
return nullptr;
}
if (const ComputedStyle* cached =
- style->GetCachedPseudoStyle(request.pseudo_id))
+ style->GetCachedPseudoElementStyle(request.pseudo_id))
return cached;
scoped_refptr<ComputedStyle> result = StyleForPseudoElement(request, style);
if (result)
- return style->AddCachedPseudoStyle(std::move(result));
+ return style->AddCachedPseudoElementStyle(std::move(result));
return nullptr;
}
scoped_refptr<ComputedStyle> Element::StyleForPseudoElement(
- const PseudoStyleRequest& request,
+ const PseudoElementStyleRequest& request,
const ComputedStyle* parent_style) {
const ComputedStyle* style = GetComputedStyle();
const bool is_before_or_after = request.pseudo_id == kPseudoIdBefore ||
@@ -5919,7 +6237,7 @@ void Element::SetHovered(bool hovered) {
const ComputedStyle* style = GetComputedStyle();
if (!style || style->AffectedByHover()) {
StyleChangeType change_type = kLocalStyleChange;
- if (style && style->HasPseudoStyle(kPseudoIdFirstLetter))
+ if (style && style->HasPseudoElementStyle(kPseudoIdFirstLetter))
change_type = kSubtreeStyleChange;
SetNeedsStyleRecalc(change_type,
StyleChangeReasonForTracing::CreateWithExtraData(
@@ -5953,7 +6271,7 @@ void Element::SetActive(bool active) {
if (GetComputedStyle()->AffectedByActive()) {
StyleChangeType change_type =
- GetComputedStyle()->HasPseudoStyle(kPseudoIdFirstLetter)
+ GetComputedStyle()->HasPseudoElementStyle(kPseudoIdFirstLetter)
? kSubtreeStyleChange
: kLocalStyleChange;
SetNeedsStyleRecalc(change_type,
diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h
index 81149af8088..fc0f084edb0 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.h
+++ b/chromium/third_party/blink/renderer/core/dom/element.h
@@ -74,9 +74,10 @@ class NamedNodeMap;
class PaintLayerScrollableArea;
class PointerLockOptions;
class PseudoElement;
-class PseudoStyleRequest;
+class PseudoElementStyleRequest;
class ResizeObservation;
class ResizeObserver;
+class ScriptPromise;
class ScrollIntoViewOptions;
class ScrollIntoViewOptionsOrBoolean;
class ScrollToOptions;
@@ -94,6 +95,7 @@ class V0CustomElementDefinition;
enum class CSSPropertyID;
enum class CSSValueID;
+enum class DisplayLockActivationReason;
enum class DisplayLockLifecycleTarget;
using ScrollOffset = FloatSize;
@@ -203,6 +205,12 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
Element* GetElementAttribute(const QualifiedName& name);
void SetElementAttribute(const QualifiedName&, Element*);
+ HeapVector<Member<Element>> GetElementArrayAttribute(
+ const QualifiedName& name,
+ bool& is_null);
+ void SetElementArrayAttribute(const QualifiedName&,
+ HeapVector<Member<Element>>,
+ bool is_null);
// Call this to get the value of an attribute that is known not to be the
// style attribute or one of the SVG animatable attributes.
@@ -547,7 +555,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void RebuildLayoutTree(WhitespaceAttacher&);
void PseudoStateChanged(CSSSelector::PseudoType);
void SetAnimationStyleChange(bool);
- void ClearAnimationStyleChange();
void SetNeedsAnimationStyleRecalc();
void SetNeedsCompositingUpdate();
@@ -667,6 +674,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
virtual bool IsMouseFocusable() const;
bool IsFocusedElementInDocument() const;
Element* AdjustedFocusedElementInTreeScope() const;
+ bool IsAutofocusable() const;
virtual void DispatchFocusEvent(
Element* old_focused_element,
@@ -749,9 +757,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
PseudoElement* GetPseudoElement(PseudoId) const;
LayoutObject* PseudoElementLayoutObject(PseudoId) const;
- const ComputedStyle* CachedStyleForPseudoElement(const PseudoStyleRequest&);
+ const ComputedStyle* CachedStyleForPseudoElement(
+ const PseudoElementStyleRequest&);
scoped_refptr<ComputedStyle> StyleForPseudoElement(
- const PseudoStyleRequest&,
+ const PseudoElementStyleRequest&,
const ComputedStyle* parent_style = nullptr);
bool CanGeneratePseudoElement(PseudoId) const;
@@ -793,6 +802,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
virtual bool IsOutOfRange() const { return false; }
virtual bool IsClearButtonElement() const { return false; }
virtual bool IsScriptElement() const { return false; }
+ virtual bool IsVTTCueBackgroundBox() const { return false; }
// Elements that may have an insertion mode other than "in body" should
// override this and return true.
@@ -920,15 +930,17 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
EnsureResizeObserverData();
void SetNeedsResizeObserverUpdate();
- DisplayLockContext* getDisplayLockForBindings();
DisplayLockContext* GetDisplayLockContext() const;
DisplayLockContext& EnsureDisplayLockContext();
+ ScriptPromise updateRendering(ScriptState*);
+
bool StyleRecalcBlockedByDisplayLock(DisplayLockLifecycleTarget) const;
- // Activates all activatable locked ancestors for this element. Return true if
- // we activated at least one previously locked element.
- bool ActivateDisplayLockIfNeeded();
+ // Activates all activatable (for a given reason) locked ancestors for this
+ // element. Return true if we activated at least one previously locked
+ // element.
+ bool ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason);
virtual void SetActive(bool active);
virtual void SetHovered(bool hovered);
@@ -984,6 +996,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
scoped_refptr<ComputedStyle> OriginalStyleForLayoutObject();
+ // Step 4 of http://domparsing.spec.whatwg.org/#insertadjacenthtml()
Node* InsertAdjacent(const String& where, Node* new_child, ExceptionState&);
virtual void ParserDidSetAttributes() {}
@@ -1139,7 +1152,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable {
void DetachAttrNodeFromElementWithValue(Attr*, const AtomicString& value);
void DetachAttrNodeAtIndex(Attr*, wtf_size_t index);
- bool DisplayLockPreventsActivation() const;
+ bool DisplayLockPreventsActivation(DisplayLockActivationReason reason) const;
FRIEND_TEST_ALL_PREFIXES(DisplayLockContextTest,
DisplayLockPreventsActivation);
diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl
index fae536b7c3b..3dc254fdf11 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.idl
+++ b/chromium/third_party/blink/renderer/core/dom/element.idl
@@ -142,13 +142,12 @@ callback ScrollStateCallback = void (ScrollState scrollState);
attribute EventHandler onbeforepaste;
attribute EventHandler onsearch;
- // Display locking. Returns a display lock context.
- [RuntimeEnabled=DisplayLocking, ImplementedAs=getDisplayLockForBindings] readonly attribute DisplayLockContext displayLock;
// Declarative display locking.
[RuntimeEnabled=DisplayLocking, CEReactions, CustomElementCallbacks, Reflect] attribute DOMString renderSubtree;
+ [RuntimeEnabled=DisplayLocking, CallWith=ScriptState] Promise<any> updateRendering();
// Element Timing
- [RuntimeEnabled=ElementTiming, Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
+ [Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
};
Element includes ParentNode;
diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.cc b/chromium/third_party/blink/renderer/core/dom/element_data.cc
index 92e725d0567..890989ea8f6 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element_data.cc
@@ -36,8 +36,8 @@
namespace blink {
-struct SameSizeAsElementData
- : public GarbageCollectedFinalized<SameSizeAsElementData> {
+struct SameSizeAsElementData final
+ : public GarbageCollected<SameSizeAsElementData> {
unsigned bitfield;
Member<void*> willbe_member;
void* pointers[2];
diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.h b/chromium/third_party/blink/renderer/core/dom/element_data.h
index 72aacbcdf89..a3b87797d0b 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/element_data.h
@@ -48,9 +48,9 @@ class UniqueElementData;
// ElementData represents very common, but not necessarily unique to an element,
// data such as attributes, inline style, and parsed class names and ids.
-class ElementData : public GarbageCollectedFinalized<ElementData> {
+class ElementData : public GarbageCollected<ElementData> {
public:
- // Override GarbageCollectedFinalized's finalizeGarbageCollectedObject to
+ // Override GarbageCollected's finalizeGarbageCollectedObject to
// dispatch to the correct subclass destructor.
void FinalizeGarbageCollectedObject();
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 cf180109fd4..c105ed22f15 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
@@ -236,7 +236,7 @@ class ElementRareData : public NodeRareData {
Member<AccessibleNode> accessible_node_;
- WeakMember<DisplayLockContext> display_lock_context_;
+ Member<DisplayLockContext> display_lock_context_;
bool did_attach_internals_ = false;
bool should_force_legacy_layout_for_child_ = false;
bool style_should_force_legacy_layout_ = false;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
index be37dfd339e..447a53e79f4 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc
@@ -56,8 +56,8 @@ void CustomEvent::initCustomEvent(ScriptState* script_state,
ScriptValue CustomEvent::detail(ScriptState* script_state) const {
v8::Isolate* isolate = script_state->GetIsolate();
if (detail_.IsEmpty())
- return ScriptValue(script_state, v8::Null(isolate));
- return ScriptValue(script_state, detail_.GetAcrossWorld(script_state));
+ return ScriptValue(isolate, v8::Null(isolate));
+ return ScriptValue(isolate, detail_.GetAcrossWorld(script_state));
}
const AtomicString& CustomEvent::InterfaceName() const {
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.cc b/chromium/third_party/blink/renderer/core/dom/events/event.cc
index 543ae51c3e7..89fa3036082 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event.cc
@@ -301,7 +301,7 @@ void Event::InitEventPath(Node& node) {
ScriptValue Event::path(ScriptState* script_state) const {
return ScriptValue(
- script_state,
+ script_state->GetIsolate(),
ToV8(PathInternal(script_state, kNonEmptyAfterDispatch), script_state));
}
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 2274c0d6a9b..f84e0f72194 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
@@ -337,7 +337,7 @@ inline void EventDispatcher::DispatchEventPostProcess(
// TODO(dtapuska): Change this to a target SDK quirk crbug.com/643705
if (!is_trusted_or_click && event_->IsMouseEvent() &&
event_->type() == event_type_names::kMousedown &&
- IsHTMLSelectElement(*node_)) {
+ IsA<HTMLSelectElement>(*node_)) {
if (Settings* settings = node_->GetDocument().GetSettings()) {
is_trusted_or_click = settings->GetWideViewportQuirkEnabled();
}
@@ -346,8 +346,10 @@ inline void EventDispatcher::DispatchEventPostProcess(
// Call default event handlers. While the DOM does have a concept of
// preventing default handling, the detail of which handlers are called is an
// internal implementation detail and not part of the DOM.
- if (!event_->defaultPrevented() && !event_->DefaultHandled() &&
- is_trusted_or_click) {
+ if (event_->defaultPrevented()) {
+ if (activation_target)
+ activation_target->DidPreventDefault(*event_);
+ } else if (!event_->DefaultHandled() && is_trusted_or_click) {
// Non-bubbling events call only one default event handler, the one for the
// target.
node_->WillCallDefaultEventHandler(*event_);
@@ -382,7 +384,7 @@ inline void EventDispatcher::DispatchEventPostProcess(
// events to open select boxes.
if (!event_->isTrusted() && event_->IsMouseEvent() &&
event_->type() == event_type_names::kMousedown &&
- IsHTMLSelectElement(*node_)) {
+ IsA<HTMLSelectElement>(*node_)) {
UseCounter::Count(node_->GetDocument(),
WebFeature::kUntrustedMouseDownEventDispatchedToSelect);
}
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 0787c6f76a8..9faaae7f295 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
@@ -44,9 +44,8 @@ class ExecutionContext;
// - once
// - removed
// EventListener represents 'callback' part.
-class CORE_EXPORT EventListener
- : public GarbageCollectedFinalized<EventListener>,
- public NameClient {
+class CORE_EXPORT EventListener : public GarbageCollected<EventListener>,
+ public NameClient {
public:
virtual ~EventListener() = default;
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 f199fc35392..fc934283780 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
@@ -275,6 +275,10 @@ void EventPath::RetargetRelatedTarget(const Node& related_target_node) {
DCHECK(adjusted_related_target);
tree_scope_event_context.Get()->SetRelatedTarget(*adjusted_related_target);
}
+ // Explicitly clear the heap container to avoid memory regressions in the hot
+ // path.
+ // TODO(bikineev): Revisit after young generation is there.
+ related_node_map.clear();
}
namespace {
@@ -372,6 +376,10 @@ void EventPath::AdjustTouchList(
adjusted_touch_list[j]->Append(touch.CloneWithNewTarget(
FindRelatedNode(*tree_scopes[j], related_node_map)));
}
+ // Explicitly clear the heap container to avoid memory regressions in the
+ // hot path.
+ // TODO(bikineev): Revisit after young generation is there.
+ related_node_map.clear();
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_path.h b/chromium/third_party/blink/renderer/core/dom/events/event_path.h
index 07102f25af7..b2e6efc9acd 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_path.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_path.h
@@ -43,8 +43,7 @@ class TouchList;
class TreeScope;
class WindowEventContext;
-class CORE_EXPORT EventPath final
- : public GarbageCollectedFinalized<EventPath> {
+class CORE_EXPORT EventPath final : public GarbageCollected<EventPath> {
public:
explicit EventPath(Node&, Event* = nullptr);
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 7d9e69a4ead..c0d12674570 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
@@ -36,9 +36,8 @@ namespace blink {
class Event;
class ExecutionContext;
-class CORE_EXPORT EventQueue final
- : public GarbageCollectedFinalized<EventQueue>,
- public ContextLifecycleObserver {
+class CORE_EXPORT EventQueue final : public GarbageCollected<EventQueue>,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(EventQueue);
public:
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 ca8bd99fefc..d60e5ddd68d 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
@@ -77,7 +77,7 @@ struct FiringEventIterator {
using FiringEventIteratorVector = Vector<FiringEventIterator, 1>;
class CORE_EXPORT EventTargetData final
- : public GarbageCollectedFinalized<EventTargetData> {
+ : public GarbageCollected<EventTargetData> {
public:
EventTargetData();
~EventTargetData();
diff --git a/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc b/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
index bf97de00785..d2d8e5dcef2 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/listener_leak_test.cc
@@ -106,9 +106,7 @@ class ListenerLeakTest : public testing::Test {
}
void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
+ url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
}
protected:
diff --git a/chromium/third_party/blink/renderer/core/dom/events/native_event_listener.h b/chromium/third_party/blink/renderer/core/dom/events/native_event_listener.h
index 7e5b67417c6..31ae554d2b6 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/native_event_listener.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/native_event_listener.h
@@ -23,7 +23,6 @@ class CORE_EXPORT NativeEventListener : public EventListener {
// Helper functions for DowncastTraits.
bool IsNativeEventListener() const override { return true; }
- virtual bool IsConditionEventListener() const { return false; }
virtual bool IsImageEventListener() const { return false; }
protected:
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 6753d0af29b..50fef4d2c33 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
@@ -110,7 +110,8 @@ LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
}
if (!parent_layout_object ||
- !parent_layout_object->Style()->HasPseudoStyle(kPseudoIdFirstLetter) ||
+ !parent_layout_object->Style()->HasPseudoElementStyle(
+ kPseudoIdFirstLetter) ||
!CanHaveGeneratedChildren(*parent_layout_object) ||
!parent_layout_object->BehavesLikeBlockContainer())
return nullptr;
@@ -177,7 +178,7 @@ LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject(
first_letter_text_layout_object =
first_letter_text_layout_object->NextSibling();
} else if (!first_letter_text_layout_object->IsInline() &&
- first_letter_text_layout_object->Style()->HasPseudoStyle(
+ first_letter_text_layout_object->Style()->HasPseudoElementStyle(
kPseudoIdFirstLetter) &&
CanHaveGeneratedChildren(*first_letter_text_layout_object)) {
// There is a layoutObject further down the tree which has
@@ -313,7 +314,7 @@ FirstLetterPseudoElement::CustomStyleForLayoutObject() {
return nullptr;
DCHECK(first_letter_text->Parent());
return ParentOrShadowHostElement()->StyleForPseudoElement(
- PseudoStyleRequest(GetPseudoId()),
+ PseudoElementStyleRequest(GetPseudoId()),
first_letter_text->Parent()->FirstLineStyle());
}
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_node_data.h b/chromium/third_party/blink/renderer/core/dom/flat_tree_node_data.h
index 1c95ad2f451..a9913495596 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_node_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_node_data.h
@@ -47,6 +47,7 @@ class FlatTreeNodeData final : public GarbageCollected<FlatTreeNodeData> {
friend class FlatTreeTraversal;
friend class HTMLSlotElement;
friend HTMLSlotElement* Node::AssignedSlot() const;
+ friend Element* Node::FlatTreeParentForChildDirty() const;
WeakMember<HTMLSlotElement> assigned_slot_;
WeakMember<Node> previous_in_assigned_nodes_;
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
index 18d31accdcc..bb95f1b0cd4 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.cc
@@ -138,7 +138,7 @@ Node* FlatTreeTraversal::V0ResolveDistributionStartingAt(
? insertion_point.FirstDistributedNode()
: insertion_point.LastDistributedNode()))
return found;
- DCHECK(IsHTMLShadowElement(insertion_point) ||
+ DCHECK(IsA<HTMLShadowElement>(insertion_point) ||
(IsA<HTMLContentElement>(insertion_point) &&
!insertion_point.HasChildren()));
}
diff --git a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
index 7b1c989da99..094fef963e3 100644
--- a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
+++ b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
@@ -83,6 +83,8 @@ void FrameRequestCallbackCollection::CancelCallbackInternal(
void FrameRequestCallbackCollection::ExecuteFrameCallbacks(
double high_res_now_ms,
double high_res_now_ms_legacy) {
+ TRACE_EVENT0("blink",
+ "FrameRequestCallbackCollection::ExecuteFrameCallbacks");
ExecuteCallbacksInternal(frame_callbacks_, "FireAnimationFrame",
"requestAnimationFrame", high_res_now_ms,
high_res_now_ms_legacy);
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 daf9d357a1a..74a2fc35e7f 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
@@ -27,9 +27,8 @@ class GC_PLUGIN_IGNORE("crbug.com/841830")
// |FrameCallback| is an interface type which generalizes callbacks which are
// invoked when a script-based animation needs to be resampled.
- class CORE_EXPORT FrameCallback
- : public GarbageCollectedFinalized<FrameCallback>,
- public NameClient {
+ class CORE_EXPORT FrameCallback : public GarbageCollected<FrameCallback>,
+ public NameClient {
public:
virtual void Trace(Visitor* visitor) {}
const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
index 0d7d82f9389..13c7cf669cd 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h
@@ -40,6 +40,10 @@ class GlobalEventHandlers {
public:
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(abort, kAbort)
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(animationend, kAnimationend)
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(animationiteration,
+ kAnimationiteration)
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(animationstart, kAnimationstart)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(activateinvisible, kActivateinvisible)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(auxclick, kAuxclick)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(blur, kBlur)
@@ -113,6 +117,7 @@ class GlobalEventHandlers {
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(stalled, kStalled)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(submit, kSubmit)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(suspend, kSuspend)
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(transitionend, kTransitionend)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(timeupdate, kTimeupdate)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(toggle, kToggle)
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(touchcancel, kTouchcancel)
diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
index a0604580efa..05630ca88dc 100644
--- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
+++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl
@@ -129,4 +129,14 @@
// https://w3c.github.io/selection-api/#extensions-to-globaleventhandlers
attribute EventHandler onselectstart;
attribute EventHandler onselectionchange;
+
+ // CSS Animations
+ // https://drafts.csswg.org/css-animations/#interface-globaleventhandlers-idl
+ attribute EventHandler onanimationend;
+ attribute EventHandler onanimationiteration;
+ attribute EventHandler onanimationstart;
+
+ // CSS Transitions
+ // https://drafts.csswg.org/css-transitions/#interface-globaleventhandlers-idl
+ attribute EventHandler ontransitionend;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/id_target_observer.h b/chromium/third_party/blink/renderer/core/dom/id_target_observer.h
index 13bce1cf590..e240e1ad670 100644
--- a/chromium/third_party/blink/renderer/core/dom/id_target_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/id_target_observer.h
@@ -33,7 +33,7 @@ namespace blink {
class IdTargetObserverRegistry;
-class IdTargetObserver : public GarbageCollectedFinalized<IdTargetObserver> {
+class IdTargetObserver : public GarbageCollected<IdTargetObserver> {
public:
virtual ~IdTargetObserver();
virtual void Trace(Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry_test.cc b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry_test.cc
index 102f56e7dea..70a22ee0f9d 100644
--- a/chromium/third_party/blink/renderer/core/dom/live_node_list_registry_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/live_node_list_registry_test.cc
@@ -100,8 +100,8 @@ TEST_F(LiveNodeListRegistryTest, ExplicitRemove) {
// This is a hack for test purposes. The test below forces a GC to happen and
// claims that there are no GC pointers on the stack. For this to be valid, the
// tracker itself must live on the heap, not on the stack.
-struct LiveNodeListRegistryWrapper
- : public GarbageCollectedFinalized<LiveNodeListRegistryWrapper> {
+struct LiveNodeListRegistryWrapper final
+ : public GarbageCollected<LiveNodeListRegistryWrapper> {
LiveNodeListRegistry registry;
void Trace(Visitor* visitor) { visitor->Trace(registry); }
};
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 48a0ac5613e..02dc9ddd661 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
@@ -77,7 +77,7 @@ class CORE_EXPORT MutationObserver final
kCharacterDataOldValue = 1 << 6,
};
- class CORE_EXPORT Delegate : public GarbageCollectedFinalized<Delegate>,
+ class CORE_EXPORT Delegate : public GarbageCollected<Delegate>,
public NameClient {
public:
virtual ~Delegate() = default;
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
index 899ff635d7c..42c73cfa883 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
@@ -71,6 +71,11 @@ bool MutationObserverInterestGroup::IsOldValueRequested() {
void MutationObserverInterestGroup::EnqueueMutationRecord(
MutationRecord* mutation) {
MutationRecord* mutation_with_null_old_value = nullptr;
+
+ // For investigation of crbug.com/1003733.
+ // If the crashes stop it means there is a GC related issue.
+ ThreadState::GCForbiddenScope gc_forbidden(ThreadState::Current());
+
for (auto& iter : observers_) {
MutationObserver* observer = iter.key.Get();
if (HasOldValue(iter.value)) {
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_notifier.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer_notifier.h
index 85911759153..497245e75a1 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_notifier.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_notifier.h
@@ -16,7 +16,7 @@ class HTMLSlotElement;
// In charge of mutation observer related state that should be managed per
// WindowAgent.
class MutationObserverNotifier final
- : public GarbageCollectedFinalized<MutationObserverNotifier> {
+ : public GarbageCollected<MutationObserverNotifier> {
public:
MutationObserverNotifier();
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 a535ac48a6c..baec26baa2b 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
@@ -44,7 +44,7 @@ namespace blink {
class QualifiedName;
class CORE_EXPORT MutationObserverRegistration final
- : public GarbageCollectedFinalized<MutationObserverRegistration>,
+ : public GarbageCollected<MutationObserverRegistration>,
public NameClient {
public:
static MutationObserverRegistration* Create(
diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc
index ce83236d529..f3319f60d48 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node.cc
@@ -54,6 +54,7 @@
#include "third_party/blink/renderer/core/dom/get_root_node_options.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_registration.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/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
@@ -102,7 +103,6 @@
#include "third_party/blink/renderer/core/mathml_names.h"
#include "third_party/blink/renderer/core/page/context_menu_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_customization_callbacks.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h"
@@ -641,6 +641,7 @@ void Node::CallApplyScroll(ScrollState& scroll_state) {
if (!GetDocument().GetPage()) {
// We should always have a Page if we're scrolling. See
// crbug.com/689074 for details.
+ NOTREACHED();
return;
}
@@ -1234,18 +1235,18 @@ void Node::MarkAncestorsWithChildNeedsDistributionRecalc() {
}
void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
- ContainerNode* ancestor = ParentOrShadowHostNode();
- bool parent_dirty = ancestor && ancestor->NeedsStyleRecalc();
+ ContainerNode* ancestor = GetStyleRecalcParent();
+ bool parent_dirty = ancestor && ancestor->IsDirtyForStyleRecalc();
for (; ancestor && !ancestor->ChildNeedsStyleRecalc();
- ancestor = ancestor->ParentOrShadowHostNode()) {
+ ancestor = ancestor->GetStyleRecalcParent()) {
if (!ancestor->isConnected())
return;
ancestor->SetChildNeedsStyleRecalc();
- if (ancestor->NeedsStyleRecalc())
+ if (ancestor->IsDirtyForStyleRecalc())
break;
// If we reach a locked ancestor, we should abort since the ancestor marking
// will be done when the lock is committed.
- if (RuntimeEnabledFeatures::DisplayLockingEnabled()) {
+ if (RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext())) {
auto* ancestor_element = DynamicTo<Element>(ancestor);
if (ancestor_element && ancestor_element->StyleRecalcBlockedByDisplayLock(
DisplayLockLifecycleTarget::kChildren)) {
@@ -1264,10 +1265,10 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
// roots. These would be updated when we commit the lock. If we have locked
// display locks somewhere in the document, we iterate up the ancestor chain
// to check if we're in one such subtree.
- if (RuntimeEnabledFeatures::DisplayLockingEnabled() &&
+ if (RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()) &&
GetDocument().LockedDisplayLockCount() > 0) {
for (auto* ancestor_copy = ancestor; ancestor_copy;
- ancestor_copy = ancestor_copy->ParentOrShadowHostNode()) {
+ ancestor_copy = ancestor_copy->GetStyleRecalcParent()) {
auto* ancestor_copy_element = DynamicTo<Element>(ancestor_copy);
if (ancestor_copy_element &&
ancestor_copy_element->StyleRecalcBlockedByDisplayLock(
@@ -1281,12 +1282,12 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() {
GetDocument().ScheduleLayoutTreeUpdateIfNeeded();
}
-Element* Node::GetReattachParent() const {
+Element* Node::FlatTreeParentForChildDirty() const {
if (IsPseudoElement())
return ParentOrShadowHostElement();
if (IsChildOfV1ShadowHost()) {
- if (HTMLSlotElement* slot = AssignedSlot())
- return slot;
+ if (auto* data = GetFlatTreeNodeData())
+ return data->AssignedSlot();
}
if (IsInV0ShadowTree() || IsChildOfV0ShadowHost()) {
if (ShadowRootWhereNodeCanBeDistributedForV0(*this)) {
@@ -1299,6 +1300,12 @@ Element* Node::GetReattachParent() const {
return ParentOrShadowHostElement();
}
+ContainerNode* Node::GetStyleRecalcParent() const {
+ if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
+ return FlatTreeParentForChildDirty();
+ return ParentOrShadowHostNode();
+}
+
void Node::MarkAncestorsWithChildNeedsReattachLayoutTree() {
DCHECK(isConnected());
Element* ancestor = GetReattachParent();
@@ -1333,12 +1340,30 @@ void Node::SetNeedsStyleRecalc(StyleChangeType change_type,
// RescheduleSiblingInvalidationsAsDescendants() for WholeSubtreeInvalid(). We
// should instead mark the shadow host for subtree recalc when we traverse the
// flat tree (and skip non-slotted host children).
- DCHECK(IsElementNode() || IsTextNode() || IsShadowRoot());
+ DCHECK(IsElementNode() || IsTextNode() ||
+ (IsShadowRoot() &&
+ !RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()));
if (!InActiveDocument())
return;
- if (!IsContainerNode() && !IsTextNode())
- return;
+ if (!GetComputedStyle()) {
+ // If we don't have a computed style, and our parent element does not have a
+ // computed style it's not necessary to mark this node for style recalc.
+ if (auto* parent = GetStyleRecalcParent()) {
+ while (parent && !parent->CanParticipateInFlatTree())
+ parent = parent->GetStyleRecalcParent();
+ DCHECK(parent);
+ if (!parent->GetComputedStyle())
+ return;
+ } else if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled() &&
+ GetDocument().documentElement() != this) {
+ // If this is the root element, and it does not have a computed style, we
+ // still need to mark it for style recalc since it may change from
+ // display:none. Otherwise, the node is not in the flat tree, and we can
+ // return here.
+ return;
+ }
+ }
TRACE_EVENT_INSTANT1(
TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
@@ -1447,7 +1472,7 @@ void Node::ClearFlatTreeNodeData() {
bool Node::IsDescendantOf(const Node* other) const {
// Return true if other is an ancestor of this, otherwise false
- if (!other || !other->hasChildren() || isConnected() != other->isConnected())
+ if (!other || isConnected() != other->isConnected())
return false;
if (other->GetTreeScope() != GetTreeScope())
return false;
@@ -2785,7 +2810,7 @@ void Node::DispatchSimulatedClick(Event* underlying_event,
SimulatedClickMouseEventOptions event_options,
SimulatedClickCreationScope scope) {
if (auto* element = IsElementNode() ? ToElement(this) : parentElement())
- element->ActivateDisplayLockIfNeeded();
+ element->ActivateDisplayLockIfNeeded(DisplayLockActivationReason::kUser);
EventDispatcher::DispatchSimulatedClick(*this, underlying_event,
event_options, scope);
}
@@ -2860,21 +2885,6 @@ void Node::DefaultEventHandler(Event& event) {
frame->GetEventHandler().StartMiddleClickAutoscroll(layout_object);
}
}
- } else if (event_type == event_type_names::kMouseup && event.IsMouseEvent()) {
- auto& mouse_event = ToMouseEvent(event);
- if (mouse_event.button() ==
- static_cast<int16_t>(WebPointerProperties::Button::kBack)) {
- if (LocalFrame* frame = GetDocument().GetFrame()) {
- if (frame->Client()->NavigateBackForward(-1, false))
- event.SetDefaultHandled();
- }
- } else if (mouse_event.button() ==
- static_cast<int16_t>(WebPointerProperties::Button::kForward)) {
- if (LocalFrame* frame = GetDocument().GetFrame()) {
- if (frame->Client()->NavigateBackForward(1, false))
- event.SetDefaultHandled();
- }
- }
}
}
@@ -3136,7 +3146,7 @@ void Node::CheckSlotChange(SlotChangeType slot_change_type) {
slot->DidSlotChange(slot_change_type);
} else if (IsInV1ShadowTree()) {
// Checking for fallback content if the node is in a v1 shadow tree.
- if (auto* parent_slot = ToHTMLSlotElementOrNull(parentElement())) {
+ if (auto* parent_slot = DynamicTo<HTMLSlotElement>(parentElement())) {
DCHECK(parent_slot->SupportsAssignment());
// The parent_slot's assigned nodes might not be calculated because they
// are lazy evaluated later at UpdateDistribution() so we have to check it
diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h
index cfb63a5e543..d1c1b97b06b 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.h
+++ b/chromium/third_party/blink/renderer/core/dom/node.h
@@ -497,6 +497,10 @@ class CORE_EXPORT Node : public EventTarget {
return GetFlag(kForceReattachLayoutTree);
}
+ bool IsDirtyForStyleRecalc() const {
+ return NeedsStyleRecalc() || GetForceReattachLayoutTree();
+ }
+
bool NeedsDistributionRecalc() const;
bool ChildNeedsDistributionRecalc() const {
@@ -627,7 +631,9 @@ class CORE_EXPORT Node : public EventTarget {
bool IsChildOfV1ShadowHost() const;
bool IsChildOfV0ShadowHost() const;
ShadowRoot* V1ShadowRootOfParent() const;
- Element* GetReattachParent() const;
+ Element* FlatTreeParentForChildDirty() const;
+ ContainerNode* GetStyleRecalcParent() const;
+ Element* GetReattachParent() const { return FlatTreeParentForChildDirty(); }
bool IsDocumentTypeNode() const { return getNodeType() == kDocumentTypeNode; }
virtual bool ChildTypeAllowed(NodeType) const { return false; }
@@ -813,6 +819,10 @@ class CORE_EXPORT Node : public EventTarget {
}
virtual void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) {}
+ // TODO(crbug.com/1013385): Remove DidPreventDefault. It is here as a
+ // temporary fix for form double-submit.
+ virtual void DidPreventDefault(const Event&) {}
+
void DispatchScopedEvent(Event&);
virtual void HandleLocalEvents(Event&);
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 2d22fa4a219..6daa78adc8b 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
@@ -111,7 +111,7 @@ class NodeRareDataBase {
NodeRenderingData* node_layout_data_;
};
-class NodeRareData : public GarbageCollectedFinalized<NodeRareData>,
+class NodeRareData : public GarbageCollected<NodeRareData>,
public NodeRareDataBase {
public:
explicit NodeRareData(NodeRenderingData* node_layout_data)
diff --git a/chromium/third_party/blink/renderer/core/dom/node_test.cc b/chromium/third_party/blink/renderer/core/dom/node_test.cc
index a8fb8772d82..7ba7099511d 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_test.cc
@@ -12,11 +12,13 @@
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_init.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -328,4 +330,59 @@ TEST_F(NodeTest, appendChildCommentNoStyleRecalc) {
EXPECT_FALSE(GetDocument().ChildNeedsStyleRecalc());
}
+TEST_F(NodeTest, MutationOutsideFlatTreeStyleDirty) {
+ SetBodyContent("<div id=host><span id=nonslotted></span></div>");
+ GetDocument().getElementById("host")->AttachShadowRootInternal(
+ ShadowRootType::kOpen);
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument()
+ .getElementById("nonslotted")
+ ->setAttribute("style", "color:green");
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+}
+
+TEST_F(NodeTest, SkipStyleDirtyHostChild) {
+ ScopedFlatTreeStyleRecalcForTest scope(true);
+
+ SetBodyContent("<div id=host><span></span></div>");
+ Element* host = GetDocument().getElementById("host");
+ ShadowRoot& shadow_root =
+ host->AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.SetInnerHTMLFromString(
+ "<div style='display:none'><slot></slot></div>");
+ UpdateAllLifecyclePhasesForTest();
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+
+ // Check that we do not mark an element for style recalc when the element and
+ // its flat tree parent are display:none.
+ To<Element>(host->firstChild())->setAttribute("style", "color:green");
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+}
+
+TEST_F(NodeTest, ContainsChild) {
+ SetBodyContent("<div id=a><div id=b></div></div>");
+ Element* a = GetDocument().getElementById("a");
+ Element* b = GetDocument().getElementById("b");
+ EXPECT_TRUE(a->contains(b));
+}
+
+TEST_F(NodeTest, ContainsNoSibling) {
+ SetBodyContent("<div id=a></div><div id=b></div>");
+ Element* a = GetDocument().getElementById("a");
+ Element* b = GetDocument().getElementById("b");
+ EXPECT_FALSE(a->contains(b));
+}
+
+TEST_F(NodeTest, ContainsPseudo) {
+ SetBodyContent(
+ "<style>#a::before{content:'aaa';}</style>"
+ "<div id=a></div>");
+ Element* a = GetDocument().getElementById("a");
+ PseudoElement* pseudo = a->GetPseudoElement(kPseudoIdBefore);
+ ASSERT_TRUE(pseudo);
+ EXPECT_TRUE(a->contains(pseudo));
+}
+
} // namespace blink
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 0d77d764fd6..8a8ea306f59 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
@@ -62,7 +62,7 @@ static bool operator!=(const PresentationAttributeCacheKey& a,
}
struct PresentationAttributeCacheEntry final
- : public GarbageCollectedFinalized<PresentationAttributeCacheEntry> {
+ : public GarbageCollected<PresentationAttributeCacheEntry> {
public:
void Trace(Visitor* visitor) { visitor->Trace(value); }
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 bbab2128d7b..248de8e4f1a 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -109,7 +109,7 @@ PseudoElement::PseudoElement(Element* parent, PseudoId pseudo_id)
scoped_refptr<ComputedStyle> PseudoElement::CustomStyleForLayoutObject() {
return ParentOrShadowHostElement()->StyleForPseudoElement(
- PseudoStyleRequest(pseudo_id_));
+ PseudoElementStyleRequest(pseudo_id_));
}
scoped_refptr<ComputedStyle> PseudoElement::LayoutStyleForDisplayContents(
diff --git a/chromium/third_party/blink/renderer/core/dom/qualified_name.h b/chromium/third_party/blink/renderer/core/dom/qualified_name.h
index 2223714cd21..23a12cb9101 100644
--- a/chromium/third_party/blink/renderer/core/dom/qualified_name.h
+++ b/chromium/third_party/blink/renderer/core/dom/qualified_name.h
@@ -236,6 +236,10 @@ template <>
struct HashTraits<blink::QualifiedName>
: SimpleClassHashTraits<blink::QualifiedName> {
static const bool kEmptyValueIsZero = false;
+ static const bool kHasIsEmptyValueFunction = true;
+ static bool IsEmptyValue(const blink::QualifiedName& value) {
+ return value == EmptyValue();
+ }
static const blink::QualifiedName& EmptyValue() {
return blink::QualifiedName::Null();
}
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 073226aec36..430fe011dac 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
@@ -42,7 +42,7 @@ class EventTarget;
class MediaQueryListListener;
class CORE_EXPORT ScriptedAnimationController
- : public GarbageCollectedFinalized<ScriptedAnimationController>,
+ : public GarbageCollected<ScriptedAnimationController>,
public NameClient {
public:
explicit ScriptedAnimationController(Document*);
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 65edd7554fd..6bcc6b19bbc 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
@@ -24,7 +24,7 @@ class IdleRequestOptions;
class ThreadScheduler;
class CORE_EXPORT ScriptedIdleTaskController
- : public GarbageCollectedFinalized<ScriptedIdleTaskController>,
+ : public GarbageCollected<ScriptedIdleTaskController>,
public ContextLifecycleStateObserver,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptedIdleTaskController);
@@ -49,8 +49,7 @@ class CORE_EXPORT ScriptedIdleTaskController
// |IdleTask| is an interface type which generalizes tasks which are invoked
// on idle. The tasks need to define what to do on idle in |invoke|.
- class IdleTask : public GarbageCollectedFinalized<IdleTask>,
- public NameClient {
+ class IdleTask : public GarbageCollected<IdleTask>, public NameClient {
public:
virtual void Trace(Visitor* visitor) {}
const char* NameInHeapSnapshot() const override { return "IdleTask"; }
@@ -92,7 +91,7 @@ class CORE_EXPORT ScriptedIdleTaskController
IdleDeadline::CallbackType);
private:
- class QueuedIdleTask : public GarbageCollectedFinalized<QueuedIdleTask> {
+ class QueuedIdleTask : public GarbageCollected<QueuedIdleTask> {
public:
QueuedIdleTask(IdleTask*,
base::TimeTicks queue_timestamp,
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 15cb42c4d69..8d4cb756f04 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -141,6 +141,7 @@ void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml,
void ShadowRoot::RecalcStyle(const StyleRecalcChange change) {
// ShadowRoot doesn't support custom callbacks.
DCHECK(!HasCustomStyleCallbacks());
+ DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
StyleRecalcChange child_change = change;
if (GetStyleChangeType() == kSubtreeStyleChange)
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
index b9f05811df1..55c50953e14 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.cc
@@ -65,7 +65,7 @@ inline void DistributionPool::PopulateChildren(const ContainerNode& parent) {
Clear();
for (Node* child = parent.firstChild(); child; child = child->nextSibling()) {
// Re-distribution across v0 and v1 shadow trees is not supported
- if (IsHTMLSlotElement(child))
+ if (IsA<HTMLSlotElement>(child))
continue;
if (IsActiveV0InsertionPoint(*child)) {
@@ -168,7 +168,7 @@ void ShadowRootV0::Distribute() {
for (const auto& point : DescendantInsertionPoints()) {
if (!point->IsActive())
continue;
- if (auto* shadow = ToHTMLShadowElementOrNull(*point)) {
+ if (auto* shadow = DynamicTo<HTMLShadowElement>(*point)) {
DCHECK(!shadow_insertion_point);
shadow_insertion_point = shadow;
} else {
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
index 47df34fbca6..974294b2ed8 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
@@ -37,8 +37,7 @@
namespace blink {
-class CORE_EXPORT ShadowRootV0 final
- : public GarbageCollectedFinalized<ShadowRootV0> {
+class CORE_EXPORT ShadowRootV0 final : public GarbageCollected<ShadowRootV0> {
public:
using NodeToDestinationInsertionPoints =
HeapHashMap<Member<const Node>, Member<DestinationInsertionPoints>>;
@@ -104,7 +103,7 @@ class CORE_EXPORT ShadowRootV0 final
inline void ShadowRootV0::DidAddInsertionPoint(V0InsertionPoint* point) {
DCHECK(point);
- if (IsHTMLShadowElement(*point))
+ if (IsA<HTMLShadowElement>(*point))
++descendant_shadow_element_count_;
else if (IsA<HTMLContentElement>(*point))
++descendant_content_element_count_;
@@ -115,7 +114,7 @@ inline void ShadowRootV0::DidAddInsertionPoint(V0InsertionPoint* point) {
inline void ShadowRootV0::DidRemoveInsertionPoint(V0InsertionPoint* point) {
DCHECK(point);
- if (IsHTMLShadowElement(*point)) {
+ if (IsA<HTMLShadowElement>(*point)) {
DCHECK_GT(descendant_shadow_element_count_, 0u);
--descendant_shadow_element_count_;
} else if (IsA<HTMLContentElement>(*point)) {
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 e2cb16f98da..d8dbcc1b5a2 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -24,9 +24,9 @@ namespace {
bool ShouldAssignToCustomSlot(const Node& node) {
if (IsA<HTMLDetailsElement>(node.parentElement()))
return HTMLDetailsElement::IsFirstSummary(node);
- if (IsHTMLSelectElement(node.parentElement()))
+ if (IsA<HTMLSelectElement>(node.parentElement()))
return HTMLSelectElement::CanAssignToSelectSlot(node);
- if (IsHTMLOptGroupElement(node.parentElement()))
+ if (IsA<HTMLOptGroupElement>(node.parentElement()))
return HTMLOptGroupElement::CanAssignToOptGroupSlot(node);
return false;
}
@@ -358,7 +358,7 @@ HTMLSlotElement* SlotAssignment::GetCachedFirstSlotWithoutAccessingNodeTree(
const AtomicString& slot_name) {
if (Element* slot =
slot_map_->GetCachedFirstElementWithoutAccessingNodeTree(slot_name)) {
- return ToHTMLSlotElement(slot);
+ return To<HTMLSlotElement>(slot);
}
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc
index 39054a0e03f..db21a594ec7 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc
@@ -155,8 +155,7 @@ TEST_F(SlotAssignmentTest, AssignedNodesAreSet) {
Element* host = GetDocument().QuerySelector("#host");
Element* host_child = GetDocument().QuerySelector("#host-child");
ShadowRoot* shadow_root = host->OpenShadowRoot();
- HTMLSlotElement* slot =
- ToHTMLSlotElementOrNull(shadow_root->QuerySelector("slot"));
+ auto* slot = DynamicTo<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
ASSERT_NE(nullptr, slot);
EXPECT_EQ(slot, host_child->AssignedSlot());
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 21ac9d79269..103cf9ebb31 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
@@ -74,12 +74,8 @@ class CORE_EXPORT SpaceSplitString {
~Data();
- bool Contains(const AtomicString& string) {
- for (const auto& item : vector_) {
- if (item == string)
- return true;
- }
- return false;
+ bool Contains(const AtomicString& string) const {
+ return vector_.Contains(string);
}
bool ContainsAll(Data&);
diff --git a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
index 39bceb8d894..24357812026 100644
--- a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
+++ b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
-#include "third_party/blink/renderer/core/css/css_value_pair.h"
+#include "third_party/blink/renderer/core/css/css_light_dark_color_pair.h"
#include "third_party/blink/renderer/core/css/style_color.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -65,10 +65,11 @@ Color TextLinkColors::ColorFromCSSValue(const CSSValue& value,
if (auto* color_value = DynamicTo<CSSColorValue>(value))
return color_value->Value();
- if (auto* pair = DynamicTo<CSSValuePair>(value)) {
- const CSSColorValue& color_value = To<CSSColorValue>(
- WebColorScheme::kLight ? pair->First() : pair->Second());
- return color_value.Value();
+ if (auto* pair = DynamicTo<CSSLightDarkColorPair>(value)) {
+ const CSSValue& color_value =
+ color_scheme == WebColorScheme::kLight ? pair->First() : pair->Second();
+ return ColorFromCSSValue(color_value, current_color, color_scheme,
+ for_visited_link);
}
CSSValueID value_id = To<CSSIdentifierValue>(value).GetValueID();
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 d01c5b44861..0c426cfba52 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
@@ -67,8 +67,8 @@ inline bool KeyMatchesMapName(const AtomicString& key, const Element& element) {
inline bool KeyMatchesSlotName(const AtomicString& key,
const Element& element) {
- return IsHTMLSlotElement(element) &&
- ToHTMLSlotElement(element).GetName() == key;
+ auto* html_slot_element = DynamicTo<HTMLSlotElement>(element);
+ return html_slot_element && html_slot_element->GetName() == key;
}
void TreeOrderedMap::Add(const AtomicString& key, Element& element) {
@@ -188,7 +188,7 @@ Element* TreeOrderedMap::GetElementByMapName(const AtomicString& key,
HTMLSlotElement* TreeOrderedMap::GetSlotByName(const AtomicString& key,
const TreeScope& scope) const {
if (Element* slot = Get<KeyMatchesSlotName>(key, scope))
- return ToHTMLSlotElement(slot);
+ return To<HTMLSlotElement>(slot);
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
index 1ca3b2be093..dfd9b4f5cf5 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -279,7 +279,7 @@ static bool ShouldAcceptNonElementNode(const Node& node) {
return false;
// In some cases the hit test doesn't return slot elements, so we can only
// get it through its child and can't skip it.
- if (IsHTMLSlotElement(*parent))
+ if (IsA<HTMLSlotElement>(*parent))
return true;
// SVG text content elements has no background, and are thus not
// hit during the background phase of hit-testing. Because of that
@@ -289,7 +289,6 @@ static bool ShouldAcceptNonElementNode(const Node& node) {
HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult(
HitTestResult& result) const {
- DCHECK(RootNode().isConnected());
HeapVector<Member<Element>> elements;
Node* last_node = nullptr;
for (const auto rect_based_node : result.ListBasedTestResult()) {
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
index f0e3f990460..0aff714f64b 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc
@@ -46,7 +46,8 @@ V0InsertionPoint::V0InsertionPoint(const QualifiedName& tag_name,
Document& document)
: HTMLElement(tag_name, document, kCreateV0InsertionPoint),
registered_with_shadow_root_(false) {
- SetHasCustomStyleCallbacks();
+ if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
+ SetHasCustomStyleCallbacks();
}
V0InsertionPoint::~V0InsertionPoint() = default;
@@ -143,6 +144,7 @@ void V0InsertionPoint::RebuildDistributedChildrenLayoutTrees(
}
void V0InsertionPoint::DidRecalcStyle(const StyleRecalcChange change) {
+ DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
if (DistributedNodesAreFallback()) {
// Fallback children have already been recalculated in
// ContainerNode::RecalcDescendantStyles().
@@ -160,6 +162,23 @@ void V0InsertionPoint::DidRecalcStyle(const StyleRecalcChange change) {
}
}
+void V0InsertionPoint::RecalcStyleForInsertionPointChildren(
+ const StyleRecalcChange change) {
+ if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
+ RecalcDescendantStyles(change);
+ return;
+ }
+ for (wtf_size_t i = 0; i < distributed_nodes_.size(); ++i) {
+ Node* node = distributed_nodes_.at(i);
+ if (!change.TraverseChild(*node))
+ continue;
+ if (auto* this_element = DynamicTo<Element>(node))
+ this_element->RecalcStyle(change);
+ else if (auto* text_node = DynamicTo<Text>(node))
+ text_node->RecalcTextStyle(change);
+ }
+}
+
bool V0InsertionPoint::CanBeActive() const {
ShadowRoot* shadow_root = ContainingShadowRoot();
if (!shadow_root)
@@ -174,14 +193,14 @@ bool V0InsertionPoint::IsActive() const {
return false;
ShadowRoot* shadow_root = ContainingShadowRoot();
DCHECK(shadow_root);
- if (!IsHTMLShadowElement(*this) ||
+ if (!IsA<HTMLShadowElement>(*this) ||
shadow_root->V0().DescendantShadowElementCount() <= 1)
return true;
// Slow path only when there are more than one shadow elements in a shadow
// tree. That should be a rare case.
for (const auto& point : shadow_root->V0().DescendantInsertionPoints()) {
- if (IsHTMLShadowElement(*point))
+ if (IsA<HTMLShadowElement>(*point))
return point == this;
}
return true;
diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
index 327aa3817f3..a4883c2a65e 100644
--- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
+++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.h
@@ -81,6 +81,8 @@ class CORE_EXPORT V0InsertionPoint : public HTMLElement {
return !HasDistribution() || DistributedNodeAt(0)->parentNode() == this;
}
+ void RecalcStyleForInsertionPointChildren(const StyleRecalcChange);
+
void Trace(Visitor*) override;
protected:
diff --git a/chromium/third_party/blink/renderer/core/dom/visited_link_state.h b/chromium/third_party/blink/renderer/core/dom/visited_link_state.h
index 1f207eea39e..1f5f33108ce 100644
--- a/chromium/third_party/blink/renderer/core/dom/visited_link_state.h
+++ b/chromium/third_party/blink/renderer/core/dom/visited_link_state.h
@@ -40,7 +40,7 @@ namespace blink {
class Document;
-class VisitedLinkState : public GarbageCollectedFinalized<VisitedLinkState> {
+class VisitedLinkState final : public GarbageCollected<VisitedLinkState> {
public:
explicit VisitedLinkState(const Document&);
diff --git a/chromium/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc b/chromium/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
index 6d712d07839..46c8725a88c 100644
--- a/chromium/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
@@ -11,7 +11,7 @@ namespace blink {
class WeakIdentifierMapTest : public ::testing::Test {
public:
- class TestClass final : public GarbageCollectedFinalized<TestClass> {
+ class TestClass final : public GarbageCollected<TestClass> {
public:
virtual void Trace(Visitor*) {}
};
diff --git a/chromium/third_party/blink/renderer/core/editing/BUILD.gn b/chromium/third_party/blink/renderer/core/editing/BUILD.gn
index 0e4f2edd13c..0e738f219c6 100644
--- a/chromium/third_party/blink/renderer/core/editing/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/editing/BUILD.gn
@@ -5,7 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("editing") {
- split_count = 5
sources = [
"caret_display_item_client.cc",
"caret_display_item_client.h",
@@ -218,6 +217,14 @@ blink_core_sources("editing") {
"markers/suggestion_marker_properties.h",
"markers/suggestion_marker_replacement_scope.cc",
"markers/suggestion_marker_replacement_scope.h",
+ "markers/text_fragment_marker.cc",
+ "markers/text_fragment_marker.h",
+ "markers/text_fragment_marker_list_impl.cc",
+ "markers/text_fragment_marker_list_impl.h",
+ "markers/text_marker_base.cc",
+ "markers/text_marker_base.h",
+ "markers/text_marker_base_list_impl.cc",
+ "markers/text_marker_base_list_impl.h",
"markers/text_match_marker.cc",
"markers/text_match_marker.h",
"markers/text_match_marker_list_impl.cc",
@@ -386,6 +393,7 @@ jumbo_source_set("unit_tests") {
"markers/spelling_marker_test.cc",
"markers/suggestion_marker_list_impl_test.cc",
"markers/suggestion_marker_test.cc",
+ "markers/text_fragment_marker_list_impl_test.cc",
"markers/text_match_marker_list_impl_test.cc",
"markers/unsorted_document_marker_list_editor_test.cc",
"plain_text_range_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
index 6632afef10f..141e536d0f8 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/break_blockquote_command.cc
@@ -230,7 +230,7 @@ void BreakBlockquoteCommand::DoApply(EditingState* editing_state) {
for (wtf_size_t i = ancestors.size(); i != 0; --i) {
Element& cloned_child = ancestors[i - 1]->CloneWithoutChildren();
// Preserve list item numbering in cloned lists.
- if (IsHTMLOListElement(cloned_child)) {
+ if (IsA<HTMLOListElement>(cloned_child)) {
Node* list_child_node = i > 1 ? ancestors[i - 2].Get() : start_node;
// The first child of the cloned list might not be a list item element,
// find the first one so that we know where to start numbering.
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 c63bfb9cc93..c7d74ca6e0a 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
@@ -1503,7 +1503,7 @@ void CompositeEditCommand::MoveParagraphs(
kDoNotAnnotateForInterchange,
ConvertBlocksToInlines::kConvert,
kDoNotResolveURLs, constraining_ancestor),
- "")
+ "", kDisallowScriptingAndPluginContent)
: nullptr;
// A non-empty paragraph's style is moved when we copy and move it. We don't
@@ -1661,7 +1661,7 @@ bool CompositeEditCommand::BreakOutOfEmptyListItem(
// FIXME: Can't we do something better when the immediate parent wasn't a list
// node?
if (!list_node ||
- (!IsHTMLUListElement(*list_node) && !IsHTMLOListElement(*list_node)) ||
+ (!IsHTMLUListElement(*list_node) && !IsA<HTMLOListElement>(*list_node)) ||
!HasEditableStyle(*list_node) ||
list_node == RootEditableElement(*empty_list_item))
return false;
@@ -1695,7 +1695,7 @@ bool CompositeEditCommand::BreakOutOfEmptyListItem(
}
// If listNode does NOT appear at the end of the outer list item, then
// behave as if in a regular paragraph.
- } else if (IsHTMLOListElement(*block_enclosing_list) ||
+ } else if (IsA<HTMLOListElement>(*block_enclosing_list) ||
IsHTMLUListElement(*block_enclosing_list)) {
new_block = MakeGarbageCollected<HTMLLIElement>(GetDocument());
}
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 f4ebf84dc5b..400dec873c3 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
@@ -1036,6 +1036,8 @@ void DeleteSelectionCommand::ClearTransientState() {
void DeleteSelectionCommand::RemoveRedundantBlocks(
EditingState* editing_state) {
Node* node = ending_position_.ComputeContainerNode();
+ if (!node)
+ return;
Element* root_element = RootEditableElement(*node);
while (node != root_element) {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/edit_command.h b/chromium/third_party/blink/renderer/core/editing/commands/edit_command.h
index aec819edf60..be659a9bbcd 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/edit_command.h
+++ b/chromium/third_party/blink/renderer/core/editing/commands/edit_command.h
@@ -37,7 +37,7 @@ class CompositeEditCommand;
class Document;
class EditingState;
-class CORE_EXPORT EditCommand : public GarbageCollectedFinalized<EditCommand> {
+class CORE_EXPORT EditCommand : public GarbageCollected<EditCommand> {
public:
virtual ~EditCommand();
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 574fa2db5f6..f9007014f27 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
@@ -366,7 +366,7 @@ HTMLElement* EnclosingList(const Node* node) {
ContainerNode* root = HighestEditableRoot(FirstPositionInOrBeforeNode(*node));
for (Node& runner : NodeTraversal::AncestorsOf(*node)) {
- if (IsHTMLUListElement(runner) || IsHTMLOListElement(runner))
+ if (IsHTMLUListElement(runner) || IsA<HTMLOListElement>(runner))
return To<HTMLElement>(&runner);
if (runner == root)
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
index 7e9b7124a9e..8aa3caee970 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
@@ -55,7 +55,7 @@ static bool IsHTMLListOrBlockquoteElement(const Node* node) {
return false;
// TODO(yosin): We should check OL/UL element has "list-style-type" CSS
// property to make sure they layout contents as list.
- return IsHTMLUListElement(*element) || IsHTMLOListElement(*element) ||
+ return IsHTMLUListElement(*element) || IsA<HTMLOListElement>(*element) ||
element->HasTagName(kBlockquoteTag);
}
@@ -218,7 +218,7 @@ void IndentOutdentCommand::OutdentParagraph(EditingState* editing_state) {
return;
// Use InsertListCommand to remove the selection from the list
- if (IsHTMLOListElement(*enclosing_element)) {
+ if (IsA<HTMLOListElement>(*enclosing_element)) {
ApplyCommandToComposite(MakeGarbageCollected<InsertListCommand>(
GetDocument(), InsertListCommand::kOrderedList),
editing_state);
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 fd599f543fc..8784b1cf265 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
@@ -807,7 +807,7 @@ VisiblePosition ReplaceSelectionCommand::PositionAtEndOfInsertedContent()
// TODO(yosin): We should set |end_of_inserted_content_| not in SELECT
// element, since contents of SELECT elements, e.g. OPTION, OPTGROUP, are
// not editable, or SELECT element is an atomic on editing.
- HTMLSelectElement* enclosing_select = ToHTMLSelectElement(
+ auto* enclosing_select = To<HTMLSelectElement>(
EnclosingElementWithTag(end_of_inserted_content_, kSelectTag));
if (enclosing_select) {
return CreateVisiblePosition(LastPositionInOrAfterNode(*enclosing_select));
@@ -830,7 +830,7 @@ static void RemoveHeadContents(ReplacementFragment& fragment) {
Node* next = nullptr;
for (Node* node = fragment.FirstChild(); node; node = next) {
if (IsA<HTMLBaseElement>(*node) || IsHTMLLinkElement(*node) ||
- IsHTMLMetaElement(*node) || IsHTMLTitleElement(*node)) {
+ IsA<HTMLMetaElement>(*node) || IsHTMLTitleElement(*node)) {
next = NodeTraversal::NextSkippingChildren(*node);
fragment.RemoveNode(node);
} else {
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 688b3b806c2..e609a4b8d4d 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
@@ -39,7 +39,7 @@ namespace blink {
class SimpleEditCommand;
-class UndoStep : public GarbageCollectedFinalized<UndoStep> {
+class UndoStep final : public GarbageCollected<UndoStep> {
public:
UndoStep(Document*,
const SelectionForUndoStep& starting_selection,
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 f49b2428e13..ca85fa1e99b 100644
--- a/chromium/third_party/blink/renderer/core/editing/drag_caret.h
+++ b/chromium/third_party/blink/renderer/core/editing/drag_caret.h
@@ -40,7 +40,7 @@ namespace blink {
class LayoutBlock;
struct PaintInvalidatorContext;
-class DragCaret final : public GarbageCollectedFinalized<DragCaret>,
+class DragCaret final : public GarbageCollected<DragCaret>,
public SynchronousMutationObserver {
USING_GARBAGE_COLLECTED_MIXIN(DragCaret);
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 8aef31ca0a6..cfa485cf73a 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -343,7 +343,7 @@ bool IsNodeFullyContained(const EphemeralRange& range, const Node& node) {
// instead of |isSelectionBondary()|.
bool IsUserSelectContain(const Node& node) {
return IsHTMLTextAreaElement(node) || IsHTMLInputElement(node) ||
- IsHTMLSelectElement(node);
+ IsA<HTMLSelectElement>(node);
}
enum EditableLevel { kEditable, kRichlyEditable };
@@ -1109,7 +1109,7 @@ Position PositionAfterNode(const Node& node) {
}
bool IsHTMLListElement(const Node* n) {
- return (n && (IsHTMLUListElement(*n) || IsHTMLOListElement(*n) ||
+ return (n && (IsHTMLUListElement(*n) || IsA<HTMLOListElement>(*n) ||
IsA<HTMLDListElement>(*n)));
}
diff --git a/chromium/third_party/blink/renderer/core/editing/editor.h b/chromium/third_party/blink/renderer/core/editing/editor.h
index 6289ad8b2b0..eebbd98c3b6 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor.h
+++ b/chromium/third_party/blink/renderer/core/editing/editor.h
@@ -61,7 +61,7 @@ enum class EditorParagraphSeparator { kIsDiv, kIsP };
enum class EditorCommandSource { kMenuOrKeyBinding, kDOM };
enum class WritingDirection;
-class CORE_EXPORT Editor final : public GarbageCollectedFinalized<Editor> {
+class CORE_EXPORT Editor final : public GarbageCollected<Editor> {
public:
explicit Editor(LocalFrame&);
~Editor();
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 a55f934e57d..2fe5c49d329 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
@@ -123,10 +123,10 @@ String ElementInnerTextCollector::RunOn(const Element& element) {
// Note: Handles <select> and <option> here since they are implemented as
// UA shadow DOM, e.g. Text nodes in <option> don't have layout object.
// See also: https://github.com/whatwg/html/issues/3797
- if (IsHTMLSelectElement(element))
- ProcessSelectElement(ToHTMLSelectElement(element));
- else if (IsHTMLOptionElement(element))
- ProcessOptionElement(ToHTMLOptionElement(element));
+ if (auto* html_select_element = DynamicTo<HTMLSelectElement>(element))
+ ProcessSelectElement(*html_select_element);
+ else if (auto* option_element = DynamicTo<HTMLOptionElement>(element))
+ ProcessOptionElement(*option_element);
else
ProcessChildren(element);
return result_.Finish();
@@ -309,13 +309,13 @@ void ElementInnerTextCollector::ProcessNode(const Node& node) {
// whose child boxes include only those of option element child nodes; and
// * option element have an associated non-replaced block-level CSS box whose
// child boxes are as normal for non-replaced block-level CSS boxes.
- if (IsHTMLSelectElement(node))
- return ProcessSelectElement(ToHTMLSelectElement(node));
- if (IsHTMLOptionElement(node)) {
+ if (auto* html_select_element = DynamicTo<HTMLSelectElement>(node))
+ return ProcessSelectElement(*html_select_element);
+ if (auto* option_element = DynamicTo<HTMLOptionElement>(node)) {
// Since child nodes of OPTION are not rendered, we use dedicated function.
// e.g. <div>ab<option>12</div>cd</div>innerText == "ab\n12\ncd"
// Note: "label" attribute doesn't affect value of innerText.
- return ProcessOptionElement(ToHTMLOptionElement(node));
+ return ProcessOptionElement(*option_element);
}
// 5. If node is a Text node, then for each CSS text box produced by node.
@@ -360,7 +360,7 @@ void ElementInnerTextCollector::ProcessNode(const Node& node) {
// 9. If node is a p element, then append 2 (a required line break count) at
// the beginning and end of items.
- if (IsHTMLParagraphElement(node)) {
+ if (IsA<HTMLParagraphElement>(node)) {
// Note: <p style="display:contents>foo</p> doesn't generate layout object
// for P.
ProcessChildrenWithRequiredLineBreaks(node, 2);
@@ -386,18 +386,18 @@ void ElementInnerTextCollector::ProcessOptionElement(
void ElementInnerTextCollector::ProcessSelectElement(
const HTMLSelectElement& select_element) {
for (const Node& child : NodeTraversal::ChildrenOf(select_element)) {
- if (IsHTMLOptionElement(child)) {
- ProcessOptionElement(ToHTMLOptionElement(child));
+ if (auto* option_element = DynamicTo<HTMLOptionElement>(child)) {
+ ProcessOptionElement(*option_element);
continue;
}
- if (!IsHTMLOptGroupElement(child))
+ if (!IsA<HTMLOptGroupElement>(child))
continue;
// Note: We should emit newline for OPTGROUP even if it has no OPTION.
// e.g. <div>a<select><optgroup></select>b</div>.innerText == "a\nb"
result_.EmitRequiredLineBreak(1);
for (const Node& maybe_option : NodeTraversal::ChildrenOf(child)) {
- if (IsHTMLOptionElement(maybe_option))
- ProcessOptionElement(ToHTMLOptionElement(maybe_option));
+ if (auto* option_element = DynamicTo<HTMLOptionElement>(maybe_option))
+ ProcessOptionElement(*option_element);
}
result_.EmitRequiredLineBreak(1);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
index 8ef026b3d29..7c9dbdc4a0e 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
@@ -103,14 +103,15 @@ bool ShouldIgnoreContents(const Node& node) {
return false;
return (!element->ShouldSerializeEndTag() && !IsHTMLInputElement(*element)) ||
IsA<HTMLIFrameElement>(*element) || IsHTMLImageElement(*element) ||
- IsA<HTMLLegendElement>(*element) || IsHTMLMeterElement(*element) ||
- IsHTMLObjectElement(*element) || IsHTMLProgressElement(*element) ||
- (IsHTMLSelectElement(*element) &&
- ToHTMLSelectElement(*element).UsesMenuList()) ||
+ IsA<HTMLLegendElement>(*element) || IsA<HTMLMeterElement>(*element) ||
+ IsHTMLObjectElement(*element) || IsA<HTMLProgressElement>(*element) ||
+ (IsA<HTMLSelectElement>(*element) &&
+ To<HTMLSelectElement>(*element).UsesMenuList()) ||
IsHTMLStyleElement(*element) || IsHTMLScriptElement(*element) ||
IsHTMLVideoElement(*element) || IsA<HTMLAudioElement>(*element) ||
(element->GetDisplayLockContext() &&
- !element->GetDisplayLockContext()->IsActivatable());
+ !element->GetDisplayLockContext()->IsActivatable(
+ DisplayLockActivationReason::kUser));
}
Node* GetNonSearchableAncestor(const Node& node) {
@@ -234,7 +235,7 @@ std::unique_ptr<FindBuffer::Results> FindBuffer::FindMatches(
bool FindBuffer::PushScopedForcedUpdateIfNeeded(const Element& element) {
if (auto* context = element.GetDisplayLockContext()) {
- DCHECK(context->IsActivatable());
+ DCHECK(context->IsActivatable(DisplayLockActivationReason::kUser));
scoped_forced_update_list_.push_back(context->GetScopedForcedUpdate());
return true;
}
@@ -244,7 +245,8 @@ bool FindBuffer::PushScopedForcedUpdateIfNeeded(const Element& element) {
void FindBuffer::CollectScopedForcedUpdates(Node& start_node,
const Node* search_range_end_node,
const Node* node_after_block) {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(
+ start_node.GetExecutionContext()))
return;
if (start_node.GetDocument().LockedDisplayLockCount() ==
start_node.GetDocument().ActivationBlockingDisplayLockCount())
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 a67f6e0924a..ce853a58796 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/editing/finder/find_task_controller.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/idle_request_options.h"
#include "third_party/blink/renderer/core/dom/range.h"
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 3f9b4844f8a..58e6c8394b4 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_TASK_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_TASK_CONTROLLER_H_
-#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink-forward.h"
#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"
@@ -20,7 +20,7 @@ class WebString;
class WebLocalFrameImpl;
class CORE_EXPORT FindTaskController final
- : public GarbageCollectedFinalized<FindTaskController> {
+ : public GarbageCollected<FindTaskController> {
public:
FindTaskController(WebLocalFrameImpl& owner_frame, TextFinder& text_finder);
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 4882a6cdfe8..a81b9b3c396 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
@@ -75,7 +75,8 @@ void TextFinder::FindMatch::Trace(Visitor* visitor) {
static void ScrollToVisible(Range* match) {
const Node& first_node = *match->FirstNode();
if (RuntimeEnabledFeatures::InvisibleDOMEnabled() ||
- RuntimeEnabledFeatures::DisplayLockingEnabled()) {
+ RuntimeEnabledFeatures::DisplayLockingEnabled(
+ first_node.GetExecutionContext())) {
const EphemeralRangeInFlatTree range(match);
if (InvisibleDOM::ActivateRangeIfNeeded(range) ||
DisplayLockUtilities::ActivateFindInPageMatchRangeIfNeeded(range))
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 63b260b33a7..c025a326699 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,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_TEXT_FINDER_H_
#include "base/macros.h"
-#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
@@ -51,8 +51,7 @@ struct WebFloatPoint;
struct WebFloatRect;
struct WebRect;
-class CORE_EXPORT TextFinder final
- : public GarbageCollectedFinalized<TextFinder> {
+class CORE_EXPORT TextFinder final : public GarbageCollected<TextFinder> {
public:
bool Find(int identifier,
const WebString& search_text,
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
index f56e897421e..f45477f6d9b 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/web/web_document.h"
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 c7ee700aa90..2f65e692d18 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_caret.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_caret.h
@@ -50,8 +50,7 @@ struct PhysicalOffset;
enum class CaretVisibility { kVisible, kHidden };
-class CORE_EXPORT FrameCaret final
- : public GarbageCollectedFinalized<FrameCaret> {
+class CORE_EXPORT FrameCaret final : public GarbageCollected<FrameCaret> {
public:
FrameCaret(LocalFrame&, const SelectionEditor&);
~FrameCaret();
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 d299253d851..fbd580252fd 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -337,9 +337,6 @@ void FrameSelection::NodeWillBeRemoved(Node& node) {
}
void FrameSelection::DidChangeFocus() {
- // Hits in
- // virtual/gpu/compositedscrolling/scrollbars/scrollbar-miss-mousemove-disabled.html
- DisableCompositingQueryAsserts disabler;
UpdateAppearance();
}
@@ -694,7 +691,7 @@ static Node* NonBoundaryShadowTreeRootNode(const Position& position) {
void FrameSelection::SelectAll(SetSelectionBy set_selection_by) {
if (auto* select_element =
- ToHTMLSelectElementOrNull(GetDocument().FocusedElement())) {
+ DynamicTo<HTMLSelectElement>(GetDocument().FocusedElement())) {
if (select_element->CanSelectAll()) {
select_element->SelectAll();
return;
@@ -1246,8 +1243,8 @@ void FrameSelection::ClearDocumentCachedRange() {
}
LayoutSelectionStatus FrameSelection::ComputeLayoutSelectionStatus(
- const NGPaintFragment& text_fragment) const {
- return layout_selection_->ComputeSelectionStatus(text_fragment);
+ const NGInlineCursor& cursor) const {
+ return layout_selection_->ComputeSelectionStatus(cursor);
}
bool FrameSelection::IsDirectional() const {
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 2478f729188..0567aabe8bf 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h
@@ -50,7 +50,7 @@ class LocalFrame;
class FrameCaret;
class GranularityStrategy;
class GraphicsContext;
-class NGPaintFragment;
+class NGInlineCursor;
class Range;
class SelectionEditor;
class LayoutSelection;
@@ -69,7 +69,7 @@ enum class CaretVisibility;
enum class HandleVisibility { kNotVisible, kVisible };
enum class SelectSoftLineBreak { kNotSelected, kSelected };
-// This is return type of ComputeLayoutSelectionStatus(paintfragment).
+// This is return type of ComputeLayoutSelectionStatus(cursor).
// This structure represents how the fragment is selected.
// |start|, |end| : Selection start/end offset. This offset is based on
// the text of NGInlineNode of a parent block thus
@@ -121,7 +121,7 @@ struct LayoutTextSelectionStatus {
};
class CORE_EXPORT FrameSelection final
- : public GarbageCollectedFinalized<FrameSelection>,
+ : public GarbageCollected<FrameSelection>,
public SynchronousMutationObserver {
USING_GARBAGE_COLLECTED_MIXIN(FrameSelection);
@@ -281,7 +281,7 @@ class CORE_EXPORT FrameSelection final
LayoutTextSelectionStatus ComputeLayoutSelectionStatus(
const LayoutText& text) const;
LayoutSelectionStatus ComputeLayoutSelectionStatus(
- const NGPaintFragment&) const;
+ const NGInlineCursor& cursor) const;
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h
index af67466d0b5..40fcf98a41a 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h
+++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span.h
@@ -31,7 +31,7 @@
#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"
-#include "ui/base/ime/mojom/ime_types.mojom-blink.h"
+#include "ui/base/ime/mojom/ime_types.mojom-blink-forward.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc
index 6118240220a..23131ca7f06 100644
--- a/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/ime/ime_text_span_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/ime/ime_text_span.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ime/mojom/ime_types.mojom-blink.h"
namespace blink {
namespace {
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 37cde8df034..3b744378b41 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
@@ -47,7 +47,7 @@ class Range;
enum class TypingContinuation;
class CORE_EXPORT InputMethodController final
- : public GarbageCollectedFinalized<InputMethodController>,
+ : public GarbageCollected<InputMethodController>,
public DocumentShutdownObserver {
USING_GARBAGE_COLLECTED_MIXIN(InputMethodController);
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 31fd9b8029a..490c9fd2959 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
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include <unicode/utf16.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/shadow_root.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
@@ -178,8 +179,9 @@ bool ShouldHandleChildren(const Node& node,
return false;
if (auto* element = DynamicTo<Element>(node)) {
- if (auto* context = element->GetDisplayLockContext())
- return context->IsActivatable();
+ if (auto* context = element->GetDisplayLockContext()) {
+ return context->IsActivatable(DisplayLockActivationReason::kUser);
+ }
}
return true;
}
@@ -310,10 +312,13 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
node_ = nullptr;
return;
}
+ const bool locked =
+ DisplayLockUtilities::NearestLockedInclusiveAncestor(*node_);
LayoutObject* layout_object = node_->GetLayoutObject();
- if (!layout_object) {
- if (IsA<ShadowRoot>(node_.Get()) || HasDisplayContents(*node_)) {
+ if (!layout_object || locked) {
+ if (!locked &&
+ (IsA<ShadowRoot>(node_.Get()) || HasDisplayContents(*node_))) {
// Shadow roots or display: contents elements don't have LayoutObjects,
// but we want to visit children anyway.
iteration_progress_ = iteration_progress_ < kHandledNode
@@ -374,8 +379,8 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
(IsHTMLFormControlElement(html_element) ||
IsA<HTMLLegendElement>(html_element) ||
IsHTMLImageElement(html_element) ||
- IsHTMLMeterElement(html_element) ||
- IsHTMLProgressElement(html_element))))) {
+ IsA<HTMLMeterElement>(html_element) ||
+ IsA<HTMLProgressElement>(html_element))))) {
HandleReplacedElement();
} else {
HandleNonTextNode();
@@ -612,7 +617,7 @@ static bool ShouldEmitNewlinesBeforeAndAfterNode(const Node& node) {
// Need to make an exception for option and optgroup, because we want to
// keep the legacy behavior before we added layoutObjects to them.
- if (IsHTMLOptionElement(node) || IsHTMLOptGroupElement(node))
+ if (IsA<HTMLOptionElement>(node) || IsA<HTMLOptGroupElement>(node))
return false;
// Need to make an exception for table cells, because they are blocks, but we
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
index 004aeee0331..1bfddc2cf6f 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -1030,5 +1031,16 @@ TEST_P(TextIteratorTest, EmitsSpaceForNbsp) {
EXPECT_EQ("[foo bar]", Iterate<DOMTree>(EmitsSpaceForNbspBehavior()));
}
+TEST_P(TextIteratorTest, IterateWithLockedSubtree) {
+ SetBodyContent("<div id='parent'>foo<div id='locked'>text</div>bar</div>");
+ auto* locked = GetDocument().getElementById("locked");
+ locked->setAttribute("rendersubtree", "invisible activatable");
+ GetDocument().UpdateStyleAndLayout();
+ auto* parent = GetDocument().getElementById("parent");
+ const Position start_position = Position::FirstPositionInNode(*parent);
+ const Position end_position = Position::LastPositionInNode(*parent);
+ EXPECT_EQ(6, TextIterator::RangeLength(start_position, end_position));
+}
+
} // namespace text_iterator_test
} // 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 00040d2ea36..3f130f7c1ec 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -33,11 +33,12 @@
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/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_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
-#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
@@ -118,6 +119,13 @@ enum class SelectionMode {
kBlockCursor,
};
+void LayoutSelection::AssertIsValid() const {
+ const Document& document = frame_selection_->GetDocument();
+ DCHECK_GE(document.Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
+ DCHECK(!document.IsSlotAssignmentOrLegacyDistributionDirty());
+ DCHECK(!has_pending_selection_);
+}
+
static SelectionMode ComputeSelectionMode(
const FrameSelection& frame_selection) {
const SelectionInDOMTree& selection_in_dom =
@@ -178,7 +186,7 @@ struct OldSelectedNodes {
public:
OldSelectedNodes()
: paint_range(MakeGarbageCollected<SelectionPaintRange>()) {}
- OldSelectedNodes(OldSelectedNodes&& other) noexcept {
+ OldSelectedNodes(OldSelectedNodes&& other) {
paint_range = other.paint_range;
selected_map = std::move(other.selected_map);
}
@@ -205,8 +213,7 @@ struct NewPaintRangeAndSelectedNodes {
HeapHashSet<Member<const Node>>&& passed_selected_objects)
: paint_range(passed_paint_range),
selected_objects(std::move(passed_selected_objects)) {}
- NewPaintRangeAndSelectedNodes(
- NewPaintRangeAndSelectedNodes&& other) noexcept {
+ NewPaintRangeAndSelectedNodes(NewPaintRangeAndSelectedNodes&& other) {
paint_range = other.paint_range;
selected_objects = std::move(other.selected_objects);
}
@@ -550,49 +557,11 @@ static SelectionPaintRange* ComputeNewPaintRange(
*paint_range.start_node, start_offset, *paint_range.end_node, end_offset);
}
-// ClampOffset modifies |offset| fixed in a range of |text_fragment| start/end
-// offsets.
static unsigned ClampOffset(unsigned offset,
- const NGPhysicalTextFragment& text_fragment) {
- return std::min(std::max(offset, text_fragment.StartOffset()),
- text_fragment.EndOffset());
-}
-
-// We don't paint a line break the end of inline-block
-// because if an inline-block is at the middle of line, we should not paint
-// a line break.
-// Old layout paints line break if the inline-block is at the end of line, but
-// since its complex to determine if the inline-block is at the end of line on NG,
-// we just cancels block-end line break painting for any inline-block.
-static bool IsLastLineInInlineBlock(const NGPaintFragment& line) {
- DCHECK(line.PhysicalFragment().IsLineBox());
- NGPaintFragment* parent = line.Parent();
- if (!parent->PhysicalFragment().IsAtomicInline())
- return false;
- return &parent->Children().back() == &line;
-}
-
-static bool IsBeforeSoftLineBreak(const NGPaintFragment& fragment) {
- if (To<NGPhysicalTextFragment>(fragment.PhysicalFragment()).IsLineBreak())
- return false;
-
- // TODO(yoichio): InlineBlock should not be container line box.
- // See paint/selection/text-selection-inline-block.html.
- const NGPaintFragment* container_line_box = fragment.ContainerLineBox();
- DCHECK(container_line_box);
- if (IsLastLineInInlineBlock(*container_line_box))
- return false;
- const auto& physical_line_box =
- To<NGPhysicalLineBoxFragment>(container_line_box->PhysicalFragment());
- const NGPhysicalFragment* last_leaf = physical_line_box.LastLogicalLeaf();
- DCHECK(last_leaf);
- if (&fragment.PhysicalFragment() != last_leaf)
- return false;
- // Even If |fragment| is before linebreak, if its direction differs to line
- // direction, we don't paint line break. See
- // paint/selection/text-selection-newline-mixed-ltr-rtl.html.
- return physical_line_box.BaseDirection() ==
- fragment.PhysicalFragment().ResolvedDirection();
+ unsigned start_offset,
+ unsigned end_offset) {
+ DCHECK_LE(start_offset, end_offset);
+ return std::min(std::max(offset, start_offset), end_offset);
}
static Text* AssociatedTextNode(const LayoutText& text) {
@@ -614,6 +583,12 @@ static SelectionState GetSelectionStateFor(const LayoutText& layout_text) {
return layout_text.GetSelectionState();
}
+static SelectionState GetSelectionStateFor(const NGInlineCursor& cursor) {
+ DCHECK(cursor.CurrentLayoutObject() &&
+ cursor.CurrentLayoutObject()->IsText());
+ return GetSelectionStateFor(ToLayoutText(*cursor.CurrentLayoutObject()));
+}
+
bool LayoutSelection::IsSelected(const LayoutObject& layout_object) {
if (const LayoutText* layout_text = ToLayoutTextOrNull(layout_object))
return GetSelectionStateFor(*layout_text) != SelectionState::kNone;
@@ -651,10 +626,7 @@ static LayoutTextSelectionStatus ComputeSelectionStatusForNode(
LayoutTextSelectionStatus LayoutSelection::ComputeSelectionStatus(
const LayoutText& layout_text) const {
- Document& document = frame_selection_->GetDocument();
- DCHECK_GE(document.Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
- DCHECK(!document.IsSlotAssignmentOrLegacyDistributionDirty());
- DCHECK(!has_pending_selection_);
+ AssertIsValid();
const SelectionState selection_state = GetSelectionStateFor(layout_text);
if (selection_state == SelectionState::kNone)
return {0, 0, SelectionIncludeEnd::kNotInclude};
@@ -684,54 +656,50 @@ LayoutTextSelectionStatus FrameSelection::ComputeLayoutSelectionStatus(
// FrameSelection holds selection offsets in layout block flow at
// LayoutSelection::Commit() if selection starts/ends within Text that
// each LayoutObject::SelectionState indicates.
-// These offset can be out of |text_fragment| because SelectionState is of each
-// LayoutText and not of each NGPhysicalTextFragment for it.
+// These offset can be out of fragment because SelectionState is of each
+// LayoutText and not of each fragment for it.
LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
- const NGPaintFragment& fragment) const {
- Document& document = frame_selection_->GetDocument();
- DCHECK_GE(document.Lifecycle().GetState(), DocumentLifecycle::kLayoutClean);
- DCHECK(!document.IsSlotAssignmentOrLegacyDistributionDirty());
- const auto& text_fragment =
- To<NGPhysicalTextFragment>(fragment.PhysicalFragment());
+ const NGInlineCursor& cursor) const {
// We don't paint selection on ellipsis.
- if (text_fragment.StyleVariant() == NGStyleVariant::kEllipsis)
+ if (cursor.IsEllipsis())
return {0, 0, SelectSoftLineBreak::kNotSelected};
- // Needs GetSelectionStateFor
- DCHECK(text_fragment.GetLayoutObject());
- switch (
- GetSelectionStateFor(ToLayoutText(*text_fragment.GetLayoutObject()))) {
+ const unsigned start_offset = cursor.CurrentTextStartOffset();
+ const unsigned end_offset = cursor.CurrentTextEndOffset();
+ switch (GetSelectionStateFor(cursor)) {
case SelectionState::kStart: {
const unsigned start_in_block = paint_range_->start_offset.value();
- const bool is_continuous = start_in_block <= text_fragment.EndOffset();
- return {ClampOffset(start_in_block, text_fragment),
- text_fragment.EndOffset(),
- (is_continuous && IsBeforeSoftLineBreak(fragment))
+ const bool is_continuous = start_in_block <= end_offset;
+ return {ClampOffset(start_in_block, start_offset, end_offset), end_offset,
+ (is_continuous && cursor.IsBeforeSoftLineBreak())
? SelectSoftLineBreak::kSelected
: SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kEnd: {
const unsigned end_in_block = paint_range_->end_offset.value();
- const unsigned end_in_fragment = ClampOffset(end_in_block, text_fragment);
- const bool is_continuous = text_fragment.EndOffset() < end_in_block;
- return {text_fragment.StartOffset(), end_in_fragment,
- (is_continuous && IsBeforeSoftLineBreak(fragment))
+ const unsigned end_in_fragment =
+ ClampOffset(end_in_block, start_offset, end_offset);
+ const bool is_continuous = end_offset < end_in_block;
+ return {start_offset, end_in_fragment,
+ (is_continuous && cursor.IsBeforeSoftLineBreak())
? SelectSoftLineBreak::kSelected
: SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kStartAndEnd: {
const unsigned start_in_block = paint_range_->start_offset.value();
const unsigned end_in_block = paint_range_->end_offset.value();
- const unsigned end_in_fragment = ClampOffset(end_in_block, text_fragment);
- const bool is_continuous = start_in_block <= text_fragment.EndOffset() &&
- text_fragment.EndOffset() < end_in_block;
- return {ClampOffset(start_in_block, text_fragment), end_in_fragment,
- (is_continuous && IsBeforeSoftLineBreak(fragment))
+ const unsigned end_in_fragment =
+ ClampOffset(end_in_block, start_offset, end_offset);
+ const bool is_continuous =
+ start_in_block <= end_offset && end_offset < end_in_block;
+ return {ClampOffset(start_in_block, start_offset, end_offset),
+ end_in_fragment,
+ (is_continuous && cursor.IsBeforeSoftLineBreak())
? SelectSoftLineBreak::kSelected
: SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kInside: {
- return {text_fragment.StartOffset(), text_fragment.EndOffset(),
- IsBeforeSoftLineBreak(fragment)
+ return {start_offset, end_offset,
+ cursor.IsBeforeSoftLineBreak()
? SelectSoftLineBreak::kSelected
: SelectSoftLineBreak::kNotSelected};
}
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 e75e45b8de9..c7c218ca402 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.h
@@ -32,7 +32,7 @@ namespace blink {
class IntRect;
class LayoutObject;
class LayoutText;
-class NGPaintFragment;
+class NGInlineCursor;
class FrameSelection;
struct LayoutSelectionStatus;
struct LayoutTextSelectionStatus;
@@ -49,7 +49,7 @@ class LayoutSelection final : public GarbageCollected<LayoutSelection> {
void InvalidatePaintForSelection();
LayoutTextSelectionStatus ComputeSelectionStatus(const LayoutText&) const;
- LayoutSelectionStatus ComputeSelectionStatus(const NGPaintFragment&) const;
+ LayoutSelectionStatus ComputeSelectionStatus(const NGInlineCursor&) const;
static bool IsSelected(const LayoutObject&);
void OnDocumentShutdown();
@@ -57,6 +57,8 @@ class LayoutSelection final : public GarbageCollected<LayoutSelection> {
void Trace(Visitor*);
private:
+ void AssertIsValid() const;
+
Member<FrameSelection> frame_selection_;
bool has_pending_selection_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
index d24c62f105e..1796f3ba63a 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
@@ -12,9 +12,7 @@
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
-#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -40,14 +38,15 @@ class LayoutSelectionTestBase : public EditingTestBase {
std::ostream& ostream,
const LayoutText& layout_text,
SelectionState state) {
- const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_text);
- if (fragments.IsInLayoutNGInlineFormattingContext()) {
- const unsigned text_start =
- To<NGPhysicalTextFragment>(fragments.begin()->PhysicalFragment())
- .StartOffset();
- for (const NGPaintFragment* fragment : fragments) {
+ if (layout_text.IsInLayoutNGInlineFormattingContext()) {
+ NGInlineCursor cursor(*layout_text.RootInlineFormattingContext());
+ cursor.MoveTo(layout_text);
+ if (!cursor)
+ return;
+ const unsigned text_start = cursor.CurrentTextStartOffset();
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
const LayoutSelectionStatus status =
- selection.ComputeLayoutSelectionStatus(*fragment);
+ selection.ComputeLayoutSelectionStatus(cursor);
if (state == SelectionState::kNone && status.start == status.end)
continue;
ostream << "(" << status.start - text_start << ","
@@ -944,32 +943,6 @@ TEST_P(LayoutSelectionTest, InvalidateSlot) {
DumpSelectionInfo());
}
-static const NGPaintFragment* FindNGPaintFragmentInternal(
- const NGPaintFragment* paint,
- const LayoutObject* layout_object) {
- if (paint->GetLayoutObject() == layout_object)
- return paint;
- for (const NGPaintFragment* child : paint->Children()) {
- if (const NGPaintFragment* child_fragment =
- FindNGPaintFragmentInternal(child, layout_object))
- return child_fragment;
- }
- return nullptr;
-}
-
-static const NGPaintFragment& GetNGPaintFragment(
- const LayoutObject* layout_object) {
- DCHECK(layout_object->IsText());
- LayoutBlockFlow* block_flow = layout_object->ContainingNGBlockFlow();
- DCHECK(block_flow);
- DCHECK(block_flow->IsLayoutNGMixin());
- LayoutNGBlockFlow* layout_ng = ToLayoutNGBlockFlow(block_flow);
- const NGPaintFragment* paint_fragment =
- FindNGPaintFragmentInternal(layout_ng->PaintFragment(), layout_object);
- DCHECK(paint_fragment);
- return *paint_fragment;
-}
-
class NGLayoutSelectionTest
: public LayoutSelectionTestBase,
private ScopedLayoutNGForTest,
@@ -979,6 +952,7 @@ class NGLayoutSelectionTest
: ScopedLayoutNGForTest(true),
ScopedPaintUnderInvalidationCheckingForTest(true) {}
+ protected:
const Text* GetFirstTextNode() {
for (const Node& runner : NodeTraversal::StartsAt(*GetDocument().body())) {
if (auto* text_node = DynamicTo<Text>(runner))
@@ -990,17 +964,22 @@ class NGLayoutSelectionTest
bool IsFirstTextLineBreak(const std::string& selection_text) {
SetSelectionAndUpdateLayoutSelection(selection_text);
- const Text* const first_text = GetFirstTextNode();
- const NGPaintFragment& fragment =
- GetNGPaintFragment(first_text->GetLayoutObject());
+ const LayoutText& first_text = *GetFirstTextNode()->GetLayoutObject();
const LayoutSelectionStatus& status =
- Selection().ComputeLayoutSelectionStatus(fragment);
+ ComputeLayoutSelectionStatus(first_text);
return status.line_break == SelectSoftLineBreak::kSelected;
}
LayoutSelectionStatus ComputeLayoutSelectionStatus(const Node& node) {
- return Selection().ComputeLayoutSelectionStatus(
- GetNGPaintFragment(node.GetLayoutObject()));
+ return ComputeLayoutSelectionStatus(*node.GetLayoutObject());
+ }
+
+ LayoutSelectionStatus ComputeLayoutSelectionStatus(
+ const LayoutObject& layout_object) const {
+ DCHECK(layout_object.IsText());
+ NGInlineCursor cursor(*layout_object.RootInlineFormattingContext());
+ cursor.MoveTo(layout_object);
+ return Selection().ComputeLayoutSelectionStatus(cursor);
}
void SetSelectionAndUpdateLayoutSelection(const std::string& selection_text) {
@@ -1053,7 +1032,7 @@ TEST_F(NGLayoutSelectionTest, TwoNGBlockFlows) {
LayoutObject* const foo =
GetDocument().body()->firstChild()->firstChild()->GetLayoutObject();
EXPECT_EQ(LayoutSelectionStatus(1u, 3u, SelectSoftLineBreak::kSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo)));
+ ComputeLayoutSelectionStatus(*foo));
LayoutObject* const bar = GetDocument()
.body()
->firstChild()
@@ -1061,7 +1040,7 @@ TEST_F(NGLayoutSelectionTest, TwoNGBlockFlows) {
->firstChild()
->GetLayoutObject();
EXPECT_EQ(LayoutSelectionStatus(0u, 2u, SelectSoftLineBreak::kNotSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(bar)));
+ ComputeLayoutSelectionStatus(*bar));
}
// TODO(editing-dev): Once LayoutNG supports editing, we should change this
@@ -1123,15 +1102,14 @@ TEST_F(NGLayoutSelectionTest, LineBreakBasic) {
EXPECT_FALSE(IsFirstTextLineBreak("<div>f^oo|</div>"));
EXPECT_FALSE(IsFirstTextLineBreak("<div>f^oo<!--|--></div>"));
EXPECT_FALSE(IsFirstTextLineBreak("<div>f^oo</div>|"));
- // TODO(yoichio): Fix the test. See LayoutSelection::IsLineBreak.
- // EXPECT_FALSE(IsFirstTextLineBreak(
- // "<div style='display:inline-block'>f^oo</div>bar|"));
}
TEST_F(NGLayoutSelectionTest, LineBreakInlineBlock) {
LoadAhem();
EXPECT_FALSE(
IsFirstTextLineBreak("<div style='display:inline-block'>^x</div>y|"));
+ EXPECT_FALSE(
+ IsFirstTextLineBreak("<div style='display:inline-block'>f^oo</div>bar|"));
}
TEST_F(NGLayoutSelectionTest, LineBreakImage) {
@@ -1155,9 +1133,8 @@ TEST_F(NGLayoutSelectionTest, BRStatus) {
LayoutObject* const layout_br =
GetDocument().QuerySelector("br")->GetLayoutObject();
CHECK(layout_br->IsBR());
- EXPECT_EQ(
- LayoutSelectionStatus(3u, 4u, SelectSoftLineBreak::kNotSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(layout_br)));
+ EXPECT_EQ(LayoutSelectionStatus(3u, 4u, SelectSoftLineBreak::kNotSelected),
+ ComputeLayoutSelectionStatus(*layout_br));
}
// https://crbug.com/907186
@@ -1166,9 +1143,8 @@ TEST_F(NGLayoutSelectionTest, WBRStatus) {
"<div style=\"width:0\">^foo<wbr>bar|</div>");
const LayoutObject* layout_wbr =
GetDocument().QuerySelector("wbr")->GetLayoutObject();
- EXPECT_EQ(
- LayoutSelectionStatus(3u, 4u, SelectSoftLineBreak::kSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(layout_wbr)));
+ EXPECT_EQ(LayoutSelectionStatus(3u, 4u, SelectSoftLineBreak::kSelected),
+ ComputeLayoutSelectionStatus(*layout_wbr));
}
} // 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 7124abe6223..42389c3d168 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
@@ -36,8 +36,7 @@ namespace blink {
// A range of a node within a document that is "marked", such as the range of a
// misspelled word. It optionally includes a description that could be displayed
// in the user interface.
-class CORE_EXPORT DocumentMarker
- : public GarbageCollectedFinalized<DocumentMarker> {
+class CORE_EXPORT DocumentMarker : public GarbageCollected<DocumentMarker> {
public:
enum MarkerTypeIndex {
kSpellingMarkerIndex = 0,
@@ -46,6 +45,7 @@ class CORE_EXPORT DocumentMarker
kCompositionMarkerIndex,
kActiveSuggestionMarkerIndex,
kSuggestionMarkerIndex,
+ kTextFragmentMarkerIndex,
kMarkerTypeIndexesCount
};
@@ -56,6 +56,7 @@ class CORE_EXPORT DocumentMarker
kComposition = 1 << kCompositionMarkerIndex,
kActiveSuggestion = 1 << kActiveSuggestionMarkerIndex,
kSuggestion = 1 << kSuggestionMarkerIndex,
+ kTextFragment = 1 << kTextFragmentMarkerIndex,
};
class MarkerTypesIterator
@@ -123,6 +124,7 @@ class CORE_EXPORT DocumentMarker
static MarkerTypes Spelling() { return MarkerTypes(kSpelling); }
static MarkerTypes TextMatch() { return MarkerTypes(kTextMatch); }
static MarkerTypes Suggestion() { return MarkerTypes(kSuggestion); }
+ static MarkerTypes TextFragment() { return MarkerTypes(kTextFragment); }
bool Contains(MarkerType type) const { return mask_ & type; }
bool Intersects(const MarkerTypes& types) const {
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 023cfc51c4b..ca645099da2 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
@@ -46,6 +46,8 @@
#include "third_party/blink/renderer/core/editing/markers/spelling_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker_list_impl.h"
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker.h"
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.h"
#include "third_party/blink/renderer/core/editing/position.h"
@@ -74,6 +76,8 @@ DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(
return DocumentMarker::kActiveSuggestionMarkerIndex;
case DocumentMarker::kSuggestion:
return DocumentMarker::kSuggestionMarkerIndex;
+ case DocumentMarker::kTextFragment:
+ return DocumentMarker::kTextFragmentMarkerIndex;
}
NOTREACHED();
@@ -94,6 +98,8 @@ DocumentMarkerList* CreateListForType(DocumentMarker::MarkerType type) {
return MakeGarbageCollected<SuggestionMarkerListImpl>();
case DocumentMarker::kTextMatch:
return MakeGarbageCollected<TextMatchMarkerListImpl>();
+ case DocumentMarker::kTextFragment:
+ return MakeGarbageCollected<TextFragmentMarkerListImpl>();
}
NOTREACHED();
@@ -211,6 +217,14 @@ void DocumentMarkerController::AddSuggestionMarker(
});
}
+void DocumentMarkerController::AddTextFragmentMarker(
+ const EphemeralRange& range) {
+ DCHECK(!document_->NeedsLayoutTreeUpdate());
+ AddMarkerInternal(range, [](int start_offset, int end_offset) {
+ return MakeGarbageCollected<TextFragmentMarker>(start_offset, end_offset);
+ });
+}
+
void DocumentMarkerController::PrepareForDestruction() {
Clear();
}
@@ -679,6 +693,10 @@ DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
return markers_to_paint;
}
+bool DocumentMarkerController::PossiblyHasTextMatchMarkers() const {
+ return PossiblyHasMarkers(DocumentMarker::kTextMatch);
+}
+
Vector<IntRect> DocumentMarkerController::LayoutRectsForTextMatchMarkers() {
DCHECK(!document_->View()->NeedsLayout());
DCHECK(!document_->NeedsLayoutTreeUpdate());
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 20d0a08ef5d..db46c4699ad 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
@@ -74,6 +74,7 @@ class CORE_EXPORT DocumentMarkerController final
Color background_color);
void AddSuggestionMarker(const EphemeralRange&,
const SuggestionMarkerProperties&);
+ void AddTextFragmentMarker(const EphemeralRange&);
void MoveMarkers(const Text& src_node, int length, const Text& dst_node);
@@ -143,6 +144,7 @@ class CORE_EXPORT DocumentMarkerController final
DocumentMarkerVector Markers() const;
DocumentMarkerVector ComputeMarkersToPaint(const Text&) const;
+ bool PossiblyHasTextMatchMarkers() const;
Vector<IntRect> LayoutRectsForTextMatchMarkers();
void InvalidateRectsForAllTextMatchMarkers();
void InvalidateRectsForTextMatchMarkersInNode(const Text&);
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 1d93cac5a15..bc9852f432a 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
@@ -19,7 +19,7 @@ class DocumentMarker;
// MarkerTypes with different insertion/retrieval patterns, or to provide
// different behavior for certain MarkerTypes).
class CORE_EXPORT DocumentMarkerList
- : public GarbageCollectedFinalized<DocumentMarkerList> {
+ : public GarbageCollected<DocumentMarkerList> {
public:
virtual ~DocumentMarkerList();
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.cc
new file mode 100644
index 00000000000..ce8314318a3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.cc
@@ -0,0 +1,24 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker.h"
+
+namespace blink {
+
+TextFragmentMarker::TextFragmentMarker(unsigned start_offset,
+ unsigned end_offset)
+ : TextMarkerBase(start_offset, end_offset) {
+ DCHECK_LT(start_offset, end_offset);
+}
+
+DocumentMarker::MarkerType TextFragmentMarker::GetType() const {
+ return DocumentMarker::kTextFragment;
+}
+
+bool TextFragmentMarker::IsActiveMatch() const {
+ // The TextFragmentMarker is painted as an inactive text match marker.
+ return false;
+}
+
+} // 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
new file mode 100644
index 00000000000..0e4e3631813
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker.h
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_H_
+
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+// A subclass of TextMarkerBase used for indicating a text fragment on the
+// page. See blink/renderer/core/page/scrolling/text_fragment_anchor.h.
+class CORE_EXPORT TextFragmentMarker final : public TextMarkerBase {
+ public:
+ TextFragmentMarker(unsigned start_offset, unsigned end_offset);
+
+ // DocumentMarker implementations
+ MarkerType GetType() const final;
+
+ // TextMarkerBase implementations
+ bool IsActiveMatch() const final;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextFragmentMarker);
+};
+
+template <>
+struct DowncastTraits<TextFragmentMarker> {
+ static bool AllowFrom(const DocumentMarker& marker) {
+ return marker.GetType() == DocumentMarker::kTextFragment;
+ }
+ static bool AllowFrom(const TextMarkerBase& marker) {
+ return marker.GetType() == DocumentMarker::kTextFragment;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.cc
new file mode 100644
index 00000000000..bc46f6d8115
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h"
+
+namespace blink {
+
+DocumentMarker::MarkerType TextFragmentMarkerListImpl::MarkerType() const {
+ return DocumentMarker::kTextFragment;
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..33f8058c381
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_LIST_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_LIST_IMPL_H_
+
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+// Implementation of TextMarkerBaseListImpl for TextFragment markers.
+class CORE_EXPORT TextFragmentMarkerListImpl final
+ : public TextMarkerBaseListImpl {
+ public:
+ TextFragmentMarkerListImpl() = default;
+
+ // DocumentMarkerList implementations
+ DocumentMarker::MarkerType MarkerType() const final;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextFragmentMarkerListImpl);
+};
+
+template <>
+struct DowncastTraits<TextFragmentMarkerListImpl> {
+ static bool AllowFrom(const DocumentMarkerList& list) {
+ return list.MarkerType() == DocumentMarker::kTextFragment;
+ }
+ static bool AllowFrom(const TextMarkerBaseListImpl& list) {
+ return list.MarkerType() == DocumentMarker::kTextFragment;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_FRAGMENT_MARKER_LIST_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl_test.cc
new file mode 100644
index 00000000000..c8f297384e0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker_list_impl.h"
+
+#include "third_party/blink/renderer/core/editing/markers/text_fragment_marker.h"
+#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
+
+namespace blink {
+
+class TextFragmentMarkerListImplTest : public EditingTestBase {
+ protected:
+ TextFragmentMarkerListImplTest()
+ : marker_list_(MakeGarbageCollected<TextFragmentMarkerListImpl>()) {}
+
+ DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) {
+ return MakeGarbageCollected<TextFragmentMarker>(start_offset, end_offset);
+ }
+
+ Persistent<TextFragmentMarkerListImpl> marker_list_;
+};
+
+TEST_F(TextFragmentMarkerListImplTest, MarkerType) {
+ EXPECT_EQ(DocumentMarker::kTextFragment, marker_list_->MarkerType());
+}
+
+TEST_F(TextFragmentMarkerListImplTest, Add) {
+ EXPECT_EQ(0u, marker_list_->GetMarkers().size());
+
+ marker_list_->Add(CreateMarker(0, 1));
+ marker_list_->Add(CreateMarker(1, 2));
+
+ EXPECT_EQ(2u, marker_list_->GetMarkers().size());
+
+ EXPECT_EQ(0u, marker_list_->GetMarkers()[0]->StartOffset());
+ EXPECT_EQ(1u, marker_list_->GetMarkers()[0]->EndOffset());
+
+ EXPECT_EQ(1u, marker_list_->GetMarkers()[1]->StartOffset());
+ EXPECT_EQ(2u, marker_list_->GetMarkers()[1]->EndOffset());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.cc
new file mode 100644
index 00000000000..8057c462bc1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.cc
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base.h"
+
+namespace blink {
+
+TextMarkerBase::TextMarkerBase(unsigned start_offset, unsigned end_offset)
+ : DocumentMarker(start_offset, end_offset) {}
+
+bool IsTextMarker(const DocumentMarker& marker) {
+ return marker.GetType() == DocumentMarker::kTextMatch ||
+ marker.GetType() == DocumentMarker::kTextFragment;
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..4e0b3558277
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base.h
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_H_
+
+#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+// A subclass of DocumentMarker used to implement functionality shared between
+// text match and text fragment markers, which share painting logic.
+class CORE_EXPORT TextMarkerBase : public DocumentMarker {
+ public:
+ TextMarkerBase(unsigned start_offset, unsigned end_offset);
+
+ virtual bool IsActiveMatch() const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextMarkerBase);
+};
+
+bool CORE_EXPORT IsTextMarker(const DocumentMarker&);
+
+template <>
+struct DowncastTraits<TextMarkerBase> {
+ static bool AllowFrom(const DocumentMarker& marker) {
+ return IsTextMarker(marker);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.cc
new file mode 100644
index 00000000000..d12dec87ad4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h"
+#include "third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h"
+
+namespace blink {
+
+bool TextMarkerBaseListImpl::IsEmpty() const {
+ return markers_.IsEmpty();
+}
+
+void TextMarkerBaseListImpl::Add(DocumentMarker* marker) {
+ DCHECK_EQ(marker->GetType(), MarkerType());
+ SortedDocumentMarkerListEditor::AddMarkerWithoutMergingOverlapping(&markers_,
+ marker);
+}
+
+void TextMarkerBaseListImpl::Clear() {
+ markers_.clear();
+}
+
+const HeapVector<Member<DocumentMarker>>& TextMarkerBaseListImpl::GetMarkers()
+ const {
+ return markers_;
+}
+
+DocumentMarker* TextMarkerBaseListImpl::FirstMarkerIntersectingRange(
+ unsigned start_offset,
+ unsigned end_offset) const {
+ return SortedDocumentMarkerListEditor::FirstMarkerIntersectingRange(
+ markers_, start_offset, end_offset);
+}
+
+HeapVector<Member<DocumentMarker>>
+TextMarkerBaseListImpl::MarkersIntersectingRange(unsigned start_offset,
+ unsigned end_offset) const {
+ return SortedDocumentMarkerListEditor::MarkersIntersectingRange(
+ markers_, start_offset, end_offset);
+}
+
+bool TextMarkerBaseListImpl::MoveMarkers(int length,
+ DocumentMarkerList* dst_list) {
+ return SortedDocumentMarkerListEditor::MoveMarkers(&markers_, length,
+ dst_list);
+}
+
+bool TextMarkerBaseListImpl::RemoveMarkers(unsigned start_offset, int length) {
+ return SortedDocumentMarkerListEditor::RemoveMarkers(&markers_, start_offset,
+ length);
+}
+
+bool TextMarkerBaseListImpl::ShiftMarkers(const String&,
+ unsigned offset,
+ unsigned old_length,
+ unsigned new_length) {
+ return SortedDocumentMarkerListEditor::ShiftMarkersContentDependent(
+ &markers_, offset, old_length, new_length);
+}
+
+void TextMarkerBaseListImpl::Trace(Visitor* visitor) {
+ visitor->Trace(markers_);
+ DocumentMarkerList::Trace(visitor);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..b68fe968a40
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h
@@ -0,0 +1,58 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_LIST_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_LIST_IMPL_H_
+
+#include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+// Nearly-complete implementation of DocumentMarkerList for text match or text
+// fragment markers (subclassed by TextMatchMarkerListImpl and
+// TextFragmentMarkerListImpl to implement the MarkerType() method).
+class CORE_EXPORT TextMarkerBaseListImpl : public DocumentMarkerList {
+ public:
+ // DocumentMarkerList implementations
+ 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(Visitor*) override;
+
+ protected:
+ TextMarkerBaseListImpl() = default;
+ HeapVector<Member<DocumentMarker>> markers_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextMarkerBaseListImpl);
+};
+
+template <>
+struct DowncastTraits<TextMarkerBaseListImpl> {
+ static bool AllowFrom(const DocumentMarkerList& list) {
+ return list.MarkerType() == DocumentMarker::kTextMatch ||
+ list.MarkerType() == DocumentMarker::kTextFragment;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MARKER_BASE_LIST_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.cc
index 276a5f1fd46..f4418198394 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker.cc
@@ -9,7 +9,7 @@ namespace blink {
TextMatchMarker::TextMatchMarker(unsigned start_offset,
unsigned end_offset,
MatchStatus status)
- : DocumentMarker(start_offset, end_offset), match_status_(status) {}
+ : TextMarkerBase(start_offset, end_offset), match_status_(status) {}
DocumentMarker::MarkerType TextMatchMarker::GetType() const {
return DocumentMarker::kTextMatch;
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 5920fac69ed..177ebebffe1 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
@@ -28,6 +28,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MATCH_MARKER_H_
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -37,7 +38,7 @@ namespace blink {
// markers. We store whether or not the match is active, a LayoutRect used for
// rendering the marker, and whether or not the LayoutRect is currently
// up-to-date.
-class CORE_EXPORT TextMatchMarker final : public DocumentMarker {
+class CORE_EXPORT TextMatchMarker final : public TextMarkerBase {
private:
enum class LayoutStatus { kInvalid, kValidNull, kValidNotNull };
@@ -49,8 +50,10 @@ class CORE_EXPORT TextMatchMarker final : public DocumentMarker {
// DocumentMarker implementations
MarkerType GetType() const final;
+ // TextMarkerBase implementations
+ bool IsActiveMatch() const final;
+
// TextMatchMarker-specific
- bool IsActiveMatch() const;
void SetIsActiveMatch(bool active);
bool IsRendered() const;
@@ -75,6 +78,9 @@ struct DowncastTraits<TextMatchMarker> {
static bool AllowFrom(const DocumentMarker& marker) {
return marker.GetType() == DocumentMarker::kTextMatch;
}
+ static bool AllowFrom(const TextMarkerBase& marker) {
+ return marker.GetType() == DocumentMarker::kTextMatch;
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
index c1b3d44267b..767ba9fe1a9 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
-#include "third_party/blink/renderer/core/editing/markers/sorted_document_marker_list_editor.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -19,63 +18,6 @@ DocumentMarker::MarkerType TextMatchMarkerListImpl::MarkerType() const {
return DocumentMarker::kTextMatch;
}
-bool TextMatchMarkerListImpl::IsEmpty() const {
- return markers_.IsEmpty();
-}
-
-void TextMatchMarkerListImpl::Add(DocumentMarker* marker) {
- DCHECK_EQ(DocumentMarker::kTextMatch, marker->GetType());
- SortedDocumentMarkerListEditor::AddMarkerWithoutMergingOverlapping(&markers_,
- marker);
-}
-
-void TextMatchMarkerListImpl::Clear() {
- markers_.clear();
-}
-
-const HeapVector<Member<DocumentMarker>>& TextMatchMarkerListImpl::GetMarkers()
- const {
- return markers_;
-}
-
-DocumentMarker* TextMatchMarkerListImpl::FirstMarkerIntersectingRange(
- unsigned start_offset,
- unsigned end_offset) const {
- return SortedDocumentMarkerListEditor::FirstMarkerIntersectingRange(
- markers_, start_offset, end_offset);
-}
-
-HeapVector<Member<DocumentMarker>>
-TextMatchMarkerListImpl::MarkersIntersectingRange(unsigned start_offset,
- unsigned end_offset) const {
- return SortedDocumentMarkerListEditor::MarkersIntersectingRange(
- markers_, start_offset, end_offset);
-}
-
-bool TextMatchMarkerListImpl::MoveMarkers(int length,
- DocumentMarkerList* dst_list) {
- return SortedDocumentMarkerListEditor::MoveMarkers(&markers_, length,
- dst_list);
-}
-
-bool TextMatchMarkerListImpl::RemoveMarkers(unsigned start_offset, int length) {
- return SortedDocumentMarkerListEditor::RemoveMarkers(&markers_, start_offset,
- length);
-}
-
-bool TextMatchMarkerListImpl::ShiftMarkers(const String&,
- unsigned offset,
- unsigned old_length,
- unsigned new_length) {
- return SortedDocumentMarkerListEditor::ShiftMarkersContentDependent(
- &markers_, offset, old_length, new_length);
-}
-
-void TextMatchMarkerListImpl::Trace(Visitor* visitor) {
- visitor->Trace(markers_);
- DocumentMarkerList::Trace(visitor);
-}
-
static void UpdateMarkerLayoutRect(const Node& node, TextMatchMarker& marker) {
const Position start_position(node, marker.StartOffset());
const Position end_position(node, marker.EndOffset());
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 770ce026d55..3484dbb3800 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
@@ -5,43 +5,24 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MATCH_MARKER_LIST_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_TEXT_MATCH_MARKER_LIST_IMPL_H_
-#include "third_party/blink/renderer/core/editing/markers/document_marker_list.h"
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base_list_impl.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class IntRect;
-// Implementation of DocumentMarkerList for TextMatch markers.
+// Implementation of TextMarkerBaseListImpl for TextMatch markers.
// Markers are kept sorted by start offset, under the assumption that
// TextMatch markers are typically inserted in an order.
-class CORE_EXPORT TextMatchMarkerListImpl final : public DocumentMarkerList {
+class CORE_EXPORT TextMatchMarkerListImpl final
+ : public TextMarkerBaseListImpl {
public:
TextMatchMarkerListImpl() = default;
// DocumentMarkerList implementations
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(Visitor*) override;
-
// TextMatchMarkerListImpl-specific
Vector<IntRect> LayoutRects(const Node&) const;
// Returns true if markers within a range defined by |startOffset| and
@@ -51,8 +32,6 @@ class CORE_EXPORT TextMatchMarkerListImpl final : public DocumentMarkerList {
bool);
private:
- HeapVector<Member<DocumentMarker>> markers_;
-
DISALLOW_COPY_AND_ASSIGN(TextMatchMarkerListImpl);
};
@@ -61,6 +40,9 @@ struct DowncastTraits<TextMatchMarkerListImpl> {
static bool AllowFrom(const DocumentMarkerList& list) {
return list.MarkerType() == DocumentMarker::kTextMatch;
}
+ static bool AllowFrom(const TextMarkerBaseListImpl& list) {
+ return list.MarkerType() == DocumentMarker::kTextMatch;
+ }
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc b/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
index 2a8858ee1c6..230645e2673 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -409,7 +409,7 @@ class ShadowBoundaryAdjuster final {
static bool IsSelectionBoundary(const Node& node) {
return IsHTMLTextAreaElement(node) || IsHTMLInputElement(node) ||
- IsHTMLSelectElement(node);
+ IsA<HTMLSelectElement>(node);
}
static Node* EnclosingShadowHostForStart(const PositionInFlatTree& position) {
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 a92a5b1b16e..20fb1033163 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.h
@@ -43,7 +43,7 @@ class HitTestResult;
class LocalFrame;
class CORE_EXPORT SelectionController final
- : public GarbageCollectedFinalized<SelectionController>,
+ : public GarbageCollected<SelectionController>,
public DocumentShutdownObserver {
USING_GARBAGE_COLLECTED_MIXIN(SelectionController);
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 ea58ab0c791..9b17e52bcec 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_editor.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_editor.h
@@ -39,7 +39,7 @@ namespace blink {
// TODO(yosin): We will rename |SelectionEditor| to appropriate name since
// it is no longer have a changing selection functionality, it was moved to
// |SelectionModifier| class.
-class SelectionEditor final : public GarbageCollectedFinalized<SelectionEditor>,
+class SelectionEditor final : public GarbageCollected<SelectionEditor>,
public SynchronousMutationObserver {
USING_GARBAGE_COLLECTED_MIXIN(SelectionEditor);
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 0ff17a2c9ec..86131233c86 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
@@ -28,7 +28,7 @@ class SpellCheckRequester;
// Main class for the implementation of idle time spell checker.
// See design doc for details: https://goo.gl/zONC3v
class CORE_EXPORT IdleSpellCheckController final
- : public GarbageCollectedFinalized<IdleSpellCheckController>,
+ : public GarbageCollected<IdleSpellCheckController>,
public DocumentShutdownObserver {
DISALLOW_COPY_AND_ASSIGN(IdleSpellCheckController);
USING_GARBAGE_COLLECTED_MIXIN(IdleSpellCheckController);
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 c1c350854e3..02c197d2943 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
@@ -43,8 +43,8 @@ class LocalFrame;
class SpellCheckRequester;
class WebTextCheckClient;
-class CORE_EXPORT SpellCheckRequest
- : public GarbageCollectedFinalized<SpellCheckRequest> {
+class CORE_EXPORT SpellCheckRequest final
+ : public GarbageCollected<SpellCheckRequest> {
public:
static const int kUnrequestedTextCheckingSequence = -1;
@@ -80,7 +80,7 @@ class CORE_EXPORT SpellCheckRequest
};
class CORE_EXPORT SpellCheckRequester final
- : public GarbageCollectedFinalized<SpellCheckRequester> {
+ : public GarbageCollected<SpellCheckRequester> {
public:
explicit SpellCheckRequester(LocalFrame&);
~SpellCheckRequester();
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 e3d249f495f..61702afe3e0 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
@@ -26,7 +26,7 @@ struct TextSuggestionInfo;
// suggestions (e.g. from spellcheck), and performing actions relating to those
// suggestions. Android is currently the only platform that has such a menu.
class CORE_EXPORT TextSuggestionController final
- : public GarbageCollectedFinalized<TextSuggestionController>,
+ : public GarbageCollected<TextSuggestionController>,
public DocumentShutdownObserver {
USING_GARBAGE_COLLECTED_MIXIN(TextSuggestionController);
diff --git a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc
index 941df98e852..b66976cf71d 100644
--- a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc
+++ b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.cc
@@ -12,40 +12,15 @@
#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/frame/local_frame_view.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/testing/dummy_page_holder.h"
namespace blink {
-namespace {
-
-Element* GetOrCreateElement(ContainerNode* parent,
- const HTMLQualifiedName& tag_name) {
- HTMLCollection* elements = parent->getElementsByTagNameNS(
- tag_name.NamespaceURI(), tag_name.LocalName());
- if (!elements->IsEmpty())
- return elements->item(0);
- return parent->ownerDocument()->CreateRawElement(
- tag_name, CreateElementFlags::ByCreateElement());
-}
-
-} // namespace
-
EditingTestBase::EditingTestBase() = default;
EditingTestBase::~EditingTestBase() = default;
-void EditingTestBase::InsertStyleElement(const std::string& style_rules) {
- Element* const head =
- GetOrCreateElement(&GetDocument(), html_names::kHeadTag);
- DCHECK_EQ(head, GetOrCreateElement(&GetDocument(), html_names::kHeadTag));
- Element* const style = GetDocument().CreateRawElement(
- html_names::kStyleTag, CreateElementFlags::ByCreateElement());
- style->setTextContent(String(style_rules.data(), style_rules.size()));
- head->appendChild(style);
-}
-
Position EditingTestBase::SetCaretTextToBody(
const std::string& selection_text) {
const SelectionInDOMTree selection = SetSelectionTextToBody(selection_text);
diff --git a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.h b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.h
index bd810b72533..091d4a2be2f 100644
--- a/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.h
+++ b/chromium/third_party/blink/renderer/core/editing/testing/editing_test_base.h
@@ -29,10 +29,6 @@ class EditingTestBase : public PageTestBase {
EditingTestBase();
~EditingTestBase() override;
- // Insert STYLE element with |style_rules|, no need to have "<style>", into
- // HEAD.
- void InsertStyleElement(const std::string& style_rules);
-
// Returns |Position| for specified |caret_text|, which is HTML markup with
// caret marker "|".
Position SetCaretTextToBody(const std::string& caret_text);
diff --git a/chromium/third_party/blink/renderer/core/events/BUILD.gn b/chromium/third_party/blink/renderer/core/events/BUILD.gn
index c831eb37534..65e808ffc06 100644
--- a/chromium/third_party/blink/renderer/core/events/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/events/BUILD.gn
@@ -58,8 +58,6 @@ blink_core_sources("events") {
"pointer_event_factory.h",
"pop_state_event.cc",
"pop_state_event.h",
- "portal_activate_event.cc",
- "portal_activate_event.h",
"progress_event.cc",
"progress_event.h",
"promise_rejection_event.cc",
diff --git a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.h b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.h
index e7dd93818a8..1be99be242a 100644
--- a/chromium/third_party/blink/renderer/core/events/application_cache_error_event.h
+++ b/chromium/third_party/blink/renderer/core/events/application_cache_error_event.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_APPLICATION_CACHE_ERROR_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_APPLICATION_CACHE_ERROR_EVENT_H_
-#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
+#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/event_interface_names.h"
#include "third_party/blink/renderer/core/events/application_cache_error_event_init.h"
diff --git a/chromium/third_party/blink/renderer/core/events/error_event.cc b/chromium/third_party/blink/renderer/core/events/error_event.cc
index 2a9f4bc6eb8..a1f165358b4 100644
--- a/chromium/third_party/blink/renderer/core/events/error_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/error_event.cc
@@ -44,7 +44,8 @@ ErrorEvent* ErrorEvent::CreateSanitizedError(ScriptState* script_state) {
return MakeGarbageCollected<ErrorEvent>(
"Script error.",
std::make_unique<SourceLocation>(String(), 0, 0, nullptr),
- ScriptValue::CreateNull(script_state), &script_state->World());
+ ScriptValue::CreateNull(script_state->GetIsolate()),
+ &script_state->World());
}
ErrorEvent::ErrorEvent()
@@ -108,8 +109,8 @@ ScriptValue ErrorEvent::error(ScriptState* script_state) const {
// thus passing it around would cause leakage.
// 2) Errors cannot be cloned (or serialized):
if (World() != &script_state->World() || error_.IsEmpty())
- return ScriptValue::CreateNull(script_state);
- return ScriptValue(script_state, error_.Get(script_state));
+ return ScriptValue::CreateNull(script_state->GetIsolate());
+ return ScriptValue(script_state->GetIsolate(), error_.Get(script_state));
}
void ErrorEvent::Trace(blink::Visitor* visitor) {
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 3a1712dac5a..9d6138853e7 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
@@ -229,6 +229,7 @@
"reading",
"readystatechange",
"rejectionhandled",
+ "release",
"removesourcebuffer",
"removestream",
"removetrack",
@@ -287,6 +288,7 @@
"transitionrun",
"transitionstart",
"typechange",
+ "uncapturederror",
"unhandledrejection",
"unload",
"unmute",
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 f941210803b..782ff96e17d 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/message_event.cc
@@ -41,7 +41,7 @@ namespace blink {
static inline bool IsValidSource(EventTarget* source) {
return !source || source->ToLocalDOMWindow() || source->ToMessagePort() ||
source->ToServiceWorker() || source->ToPortalHost() ||
- ToHTMLPortalElementOrNull(source->ToNode());
+ IsA<HTMLPortalElement>(source->ToNode());
}
MessageEvent::V8GCAwareString::V8GCAwareString(const String& value)
@@ -303,7 +303,7 @@ ScriptValue MessageEvent::data(ScriptState* script_state) {
break;
}
- return ScriptValue(script_state, value);
+ return ScriptValue(isolate, value);
}
const AtomicString& MessageEvent::InterfaceName() const {
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event.cc b/chromium/third_party/blink/renderer/core/events/pointer_event.cc
index 7cd8a9856fd..9a44299252a 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event.cc
@@ -12,8 +12,14 @@ namespace blink {
PointerEvent::PointerEvent(const AtomicString& type,
const PointerEventInit* initializer,
- base::TimeTicks platform_time_stamp)
- : MouseEvent(type, initializer, platform_time_stamp),
+ base::TimeTicks platform_time_stamp,
+ MouseEvent::SyntheticEventType synthetic_event_type,
+ WebMenuSourceType menu_source_type)
+ : MouseEvent(type,
+ initializer,
+ platform_time_stamp,
+ synthetic_event_type,
+ menu_source_type),
pointer_id_(0),
width_(0),
height_(0),
@@ -56,6 +62,13 @@ PointerEvent::PointerEvent(const AtomicString& type,
}
bool PointerEvent::IsMouseEvent() const {
+ if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
+ (type() == event_type_names::kClick ||
+ type() == event_type_names::kAuxclick ||
+ type() == event_type_names::kContextmenu)) {
+ return true;
+ }
+
return false;
}
@@ -129,6 +142,13 @@ DispatchEventResult PointerEvent::DispatchEvent(EventDispatcher& dispatcher) {
if (type().IsEmpty())
return DispatchEventResult::kNotCanceled; // Shouldn't happen.
+ if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
+ type() == event_type_names::kClick) {
+ // The MouseEvent::DispatchEvent will take care of sending dblclick event if
+ // needed.
+ return MouseEvent::DispatchEvent(dispatcher);
+ }
+
DCHECK(!target() || target() != relatedTarget());
GetEventPath().AdjustForRelatedTarget(dispatcher.GetNode(), relatedTarget());
diff --git a/chromium/third_party/blink/renderer/core/events/pointer_event.h b/chromium/third_party/blink/renderer/core/events/pointer_event.h
index ec3a1adb136..b8b7bfe1f87 100644
--- a/chromium/third_party/blink/renderer/core/events/pointer_event.h
+++ b/chromium/third_party/blink/renderer/core/events/pointer_event.h
@@ -14,11 +14,16 @@ class CORE_EXPORT PointerEvent final : public MouseEvent {
DEFINE_WRAPPERTYPEINFO();
public:
- static PointerEvent* Create(const AtomicString& type,
- const PointerEventInit* initializer,
- base::TimeTicks platform_time_stamp) {
- return MakeGarbageCollected<PointerEvent>(type, initializer,
- platform_time_stamp);
+ static PointerEvent* Create(
+ const AtomicString& type,
+ const PointerEventInit* initializer,
+ base::TimeTicks platform_time_stamp,
+ MouseEvent::SyntheticEventType synthetic_event_type =
+ kRealOrIndistinguishable,
+ WebMenuSourceType menu_source_type = kMenuSourceNone) {
+ return MakeGarbageCollected<PointerEvent>(
+ type, initializer, platform_time_stamp, synthetic_event_type,
+ menu_source_type);
}
static PointerEvent* Create(const AtomicString& type,
const PointerEventInit* initializer) {
@@ -27,7 +32,9 @@ class CORE_EXPORT PointerEvent final : public MouseEvent {
PointerEvent(const AtomicString&,
const PointerEventInit*,
- base::TimeTicks platform_time_stamp);
+ base::TimeTicks platform_time_stamp,
+ MouseEvent::SyntheticEventType synthetic_event_type,
+ WebMenuSourceType menu_source_type);
PointerId pointerId() const { return pointer_id_; }
double width() const { return width_; }
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 259b52ed2b4..4e80447f5a8 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
@@ -108,10 +108,9 @@ void UpdateCommonPointerEventInit(const WebPointerEvent& web_pointer_event,
if (dom_window && dom_window->GetFrame()) {
LocalFrame* frame = dom_window->GetFrame();
if (frame->GetPage()->DeviceScaleFactorDeprecated() == 1) {
- device_scale_factor = frame->GetPage()
- ->GetChromeClient()
- .GetScreenInfo()
- .device_scale_factor;
+ ChromeClient& chrome_client = frame->GetPage()->GetChromeClient();
+ device_scale_factor =
+ chrome_client.GetScreenInfo(*frame).device_scale_factor;
}
}
diff --git a/chromium/third_party/blink/renderer/core/events/pop_state_event.cc b/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
index 1db86c707d1..7e917d71d11 100644
--- a/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/pop_state_event.cc
@@ -64,9 +64,9 @@ ScriptValue PopStateEvent::state(ScriptState* script_state) const {
v8::Local<v8::Value> value = state_.NewLocal(isolate);
scoped_refptr<SerializedScriptValue> serialized =
SerializedScriptValue::SerializeAndSwallowExceptions(isolate, value);
- return ScriptValue(script_state, serialized->Deserialize(isolate));
+ return ScriptValue(isolate, serialized->Deserialize(isolate));
}
- return ScriptValue(script_state, state_.NewLocal(isolate));
+ return ScriptValue(isolate, state_.NewLocal(isolate));
}
PopStateEvent* PopStateEvent::Create() {
diff --git a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
index d74b3c62c99..44f1173090f 100644
--- a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
@@ -36,9 +36,11 @@ ScriptPromise PromiseRejectionEvent::promise(ScriptState* script_state) const {
ScriptValue PromiseRejectionEvent::reason(ScriptState* script_state) const {
// Return undefined when the value is accessed by a different world than the
// world that created the value.
- if (reason_.IsEmpty() || !CanBeDispatchedInWorld(script_state->World()))
- return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
- return ScriptValue(script_state,
+ if (reason_.IsEmpty() || !CanBeDispatchedInWorld(script_state->World())) {
+ return ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate()));
+ }
+ return ScriptValue(script_state->GetIsolate(),
reason_.NewLocal(script_state->GetIsolate()));
}
diff --git a/chromium/third_party/blink/renderer/core/events/touch_event_test.cc b/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
index 71d5b0ee26d..ef62cd7ebb8 100644
--- a/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
+++ b/chromium/third_party/blink/renderer/core/events/touch_event_test.cc
@@ -7,6 +7,7 @@
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.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/loader/empty_clients.h"
diff --git a/chromium/third_party/blink/renderer/core/events/wheel_event.cc b/chromium/third_party/blink/renderer/core/events/wheel_event.cc
index 7a6be3072b2..bdd390e7103 100644
--- a/chromium/third_party/blink/renderer/core/events/wheel_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/wheel_event.cc
@@ -36,8 +36,15 @@ namespace blink {
namespace {
unsigned ConvertDeltaMode(const WebMouseWheelEvent& event) {
- return event.scroll_by_page ? WheelEvent::kDomDeltaPage
- : WheelEvent::kDomDeltaPixel;
+ // WebMouseWheelEvent only supports these units for the delta.
+ DCHECK(
+ event.delta_units == ui::input_types::ScrollGranularity::kScrollByPage ||
+ event.delta_units == ui::input_types::ScrollGranularity::kScrollByPixel ||
+ event.delta_units ==
+ ui::input_types::ScrollGranularity::kScrollByPrecisePixel);
+ return event.delta_units == ui::input_types::ScrollGranularity::kScrollByPage
+ ? WheelEvent::kDomDeltaPage
+ : WheelEvent::kDomDeltaPixel;
}
// Negate a long value without integer overflow.
diff --git a/chromium/third_party/blink/renderer/core/execution_context/BUILD.gn b/chromium/third_party/blink/renderer/core/execution_context/BUILD.gn
index d588e2caca1..504e53734ca 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/execution_context/BUILD.gn
@@ -8,6 +8,8 @@ blink_core_sources("execution_context") {
sources = [
"agent.cc",
"agent.h",
+ "agent_metrics_collector.cc",
+ "agent_metrics_collector.h",
"context_lifecycle_notifier.cc",
"context_lifecycle_notifier.h",
"context_lifecycle_observer.cc",
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent.h b/chromium/third_party/blink/renderer/core/execution_context/agent.h
index 360f841a4ea..5874d96961b 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/agent.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent.h
@@ -29,7 +29,7 @@ class ExecutionContext;
// Worklets have their own agent.
// While an WindowAgentFactory is shared across a group of reachable frames,
// Agent is shared across a group of reachable and same-site frames.
-class CORE_EXPORT Agent : public GarbageCollectedFinalized<Agent> {
+class CORE_EXPORT Agent : public GarbageCollected<Agent> {
public:
static Agent* CreateForWorkerOrWorklet(
v8::Isolate* isolate,
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
new file mode 100644
index 00000000000..01dc83ae773
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.cc
@@ -0,0 +1,119 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/default_tick_clock.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/window_agent.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
+
+namespace blink {
+
+namespace {
+
+const char kAgentsPerRendererByTimeHistogram[] =
+ "PerformanceManager.AgentsPerRendererByTime";
+
+base::TimeDelta kReportingInterval = base::TimeDelta::FromMinutes(5);
+
+} // namespace
+
+AgentMetricsCollector::AgentMetricsCollector()
+ : reporting_timer_(std::make_unique<TaskRunnerTimer<AgentMetricsCollector>>(
+ // Some tests might not have a MainThreadScheduler.
+ scheduler::WebThreadScheduler::MainThreadScheduler()
+ ? scheduler::WebThreadScheduler::MainThreadScheduler()
+ ->DefaultTaskRunner()
+ : nullptr,
+ this,
+ &AgentMetricsCollector::ReportingTimerFired)),
+ clock_(base::DefaultTickClock::GetInstance()) {
+ // From now until we call CreatedNewAgent will be reported as having 0
+ // agents.
+ time_last_reported_ = clock_->NowTicks();
+}
+
+AgentMetricsCollector::~AgentMetricsCollector() {
+ // Note: This won't be called during a fast-shutdown (i.e. tab closed). We
+ // manually call it from Page::WillBeDestroyed().
+ ReportMetrics();
+}
+
+void AgentMetricsCollector::DidAttachDocument(const Document& doc) {
+ ReportMetrics();
+
+ AgentToDocumentsMap::AddResult result =
+ agent_to_documents_map_.insert(doc.GetAgent(), nullptr);
+ if (result.is_new_entry)
+ result.stored_value->value = MakeGarbageCollected<DocumentSet>();
+
+ result.stored_value->value->insert(&doc);
+}
+
+void AgentMetricsCollector::DidDetachDocument(const Document& doc) {
+ ReportMetrics();
+
+ auto agent_itr = agent_to_documents_map_.find(doc.GetAgent());
+ DCHECK(agent_itr != agent_to_documents_map_.end());
+
+ DocumentSet& documents = *agent_itr->value.Get();
+ auto document_itr = documents.find(&doc);
+ DCHECK(document_itr != documents.end());
+
+ documents.erase(document_itr);
+
+ if (documents.IsEmpty())
+ agent_to_documents_map_.erase(agent_itr);
+}
+
+void AgentMetricsCollector::ReportMetrics() {
+ DCHECK(!time_last_reported_.is_null());
+
+ // Don't run the timer in tests. Doing so causes tests that RunUntilIdle to
+ // never exit.
+ if (!reporting_timer_->IsActive() && !WebTestSupport::IsRunningWebTest()) {
+ reporting_timer_->StartRepeating(kReportingInterval, FROM_HERE);
+ }
+
+ // This computation and reporting is based on the one in
+ // chrome/browser/performance_manager/observers/isolation_context_metrics.cc.
+ base::TimeTicks now = clock_->NowTicks();
+
+ base::TimeDelta elapsed = now - time_last_reported_;
+ time_last_reported_ = now;
+
+ // Account for edge cases like hibernate/sleep. See
+ // GetSecondsSinceLastReportAndUpdate in isolation_context_metrics.cc
+ if (elapsed >= 2 * kReportingInterval)
+ elapsed = base::TimeDelta();
+
+ int to_add = static_cast<int>(std::round(elapsed.InSecondsF()));
+
+ // Time can be negative in tests when we replace the clock_.
+ if (to_add <= 0)
+ return;
+
+ AddTimeToTotalAgents(to_add);
+}
+
+void AgentMetricsCollector::AddTimeToTotalAgents(int time_delta_to_add) {
+ DEFINE_STATIC_LOCAL(LinearHistogram, agents_per_renderer_histogram,
+ (kAgentsPerRendererByTimeHistogram, 1, 100, 101));
+ agents_per_renderer_histogram.CountMany(agent_to_documents_map_.size(),
+ time_delta_to_add);
+}
+
+void AgentMetricsCollector::ReportingTimerFired(TimerBase*) {
+ ReportMetrics();
+}
+
+void AgentMetricsCollector::Trace(blink::Visitor* visitor) {
+ visitor->Trace(agent_to_documents_map_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
new file mode 100644
index 00000000000..9fe93a91a17
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector.h
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
+
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/timer.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace blink {
+
+class Agent;
+class Document;
+class TimerBase;
+
+// This class tracks agent-related metrics for reporting in TRACE and UMA
+// metrics. It listens for documents being attached/detached to an execution
+// context and tracks which agent these documents are associated with.
+//
+// We report metrics periodically to track how long we spent in any given state.
+// For example, suppose that for 10 seconds a page had just one agent, then an
+// ad frame loads causing a document to load with a second agent. After 5
+// seconds, the user closes the browser. In this case, we report:
+//
+// Histogram
+// 1 ----------O 10
+// 2 -----O 5
+//
+// We therefore keep track of how much time has elapsed since the previous
+// report. Metrics are reported whenever a document is added or removed, as
+// well as at a regular interval.
+//
+// This class is based on the metrics tracked in:
+// chrome/browser/performance_manager/observers/isolation_context_metrics.cc
+// It should eventually be migrated to that place.
+class AgentMetricsCollector final
+ : public GarbageCollected<AgentMetricsCollector> {
+ public:
+ AgentMetricsCollector();
+ ~AgentMetricsCollector();
+
+ void DidAttachDocument(const Document&);
+ void DidDetachDocument(const Document&);
+
+ void ReportMetrics();
+
+ void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; }
+
+ void Trace(blink::Visitor*);
+
+ private:
+ void AddTimeToTotalAgents(int time_delta_to_add);
+
+ void ReportingTimerFired(TimerBase*);
+
+ std::unique_ptr<TaskRunnerTimer<AgentMetricsCollector>> reporting_timer_;
+ base::TimeTicks time_last_reported_;
+
+ // Keep a map from each agent to all the documents associated with that
+ // agent. When the last document from the set is removed, we delete the key
+ // from the map.
+ using DocumentSet = HeapHashSet<WeakMember<const Document>>;
+ using AgentToDocumentsMap =
+ HeapHashMap<WeakMember<Agent>, Member<DocumentSet>>;
+ AgentToDocumentsMap agent_to_documents_map_;
+
+ const base::TickClock* clock_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EXECUTION_CONTEXT_AGENT_METRICS_COLLECTOR_H_
diff --git a/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc
new file mode 100644
index 00000000000..bbe63d46e26
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/execution_context/agent_metrics_collector_test.cc
@@ -0,0 +1,183 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/time/default_tick_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/location.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.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/core/trustedtypes/trusted_url.h"
+#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+class AgentMetricsCollectorUnitTest : public SimTest {
+ public:
+ AgentMetricsCollectorUnitTest() = default;
+
+ void SetUp() override {
+ SimTest::SetUp();
+
+ tick_clock_.SetNowTicks(base::TimeTicks::Now());
+
+ // Tests turn this on but it would force all frames into a single agent.
+ // Turn it off so we get an agent per-origin.
+ WebView().GetPage()->GetSettings().SetAllowUniversalAccessFromFileURLs(
+ false);
+
+ WebView().GetPage()->GetAgentMetricsCollector()->SetTickClockForTesting(
+ &tick_clock_);
+ WebView().MainFrameWidget()->Resize(WebSize(800, 600));
+ }
+
+ void TearDown() override {
+ if (!torn_down_) {
+ // Avoid UAF when tick_clock_ is destroyed.
+ auto* collector = WebView().GetPage()->GetAgentMetricsCollector();
+
+ SimTest::TearDown();
+ torn_down_ = true;
+
+ collector->SetTickClockForTesting(base::DefaultTickClock::GetInstance());
+ }
+ }
+
+ bool torn_down_ = false;
+
+ HistogramTester tester_;
+ const char* kHistogramName = "PerformanceManager.AgentsPerRendererByTime";
+
+ base::SimpleTestTickClock tick_clock_;
+};
+
+// Tests that we record samples across a navigation.
+TEST_F(AgentMetricsCollectorUnitTest, AgentsPerRendererRecordOnDocumentChange) {
+ SimRequest request_a("https://example.com/a.html", "text/html");
+ SimRequest request_b("https://example.com/b.html", "text/html");
+
+ // Load the first page. The histogram won't yet have any data because it
+ // records samples by time and only when documents are created/destroyed.
+ // Immediately after we load a.html, no time has passed yet.
+ LoadURL("https://example.com/a.html");
+ request_a.Complete(R"HTML(
+ <!DOCTYPE html>
+ )HTML");
+ Compositor().BeginFrame();
+
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
+
+ // Load the second page. Since 10 seconds have now elapsed, as the documents
+ // are swapped we should see 10 samples recorded in the 1 agent bucket.
+ LoadURL("https://example.com/b.html");
+ request_b.Complete(R"HTML(
+ <!DOCTYPE html>
+ )HTML");
+ Compositor().BeginFrame();
+
+ tester_.ExpectUniqueSample(kHistogramName, 1, 10);
+}
+
+// Test that we correctly record the case where a second agent is added to the
+// page.
+TEST_F(AgentMetricsCollectorUnitTest, MultipleAgents) {
+ SimRequest request_a("https://foo.com/a.html", "text/html");
+ SimRequest request_b("https://bar.com/b.html", "text/html");
+
+ // Load the first page. The histogram won't yet have any data because it
+ // records samples by time and only when documents are created/destroyed.
+ // Immediately after we load a.html, no time has passed yet.
+ LoadURL("https://foo.com/a.html");
+ request_a.Complete(R"HTML(
+ <!DOCTYPE html>
+ <iframe src="about:blank"></iframe>
+ )HTML");
+ Compositor().BeginFrame();
+
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
+
+ // Navigate to a cross-origin page, this should create a second agent.
+ frame_test_helpers::LoadFrameDontWait(
+ MainFrame().FirstChild()->ToWebLocalFrame(),
+ KURL("https://bar.com/b.html"));
+ request_b.Complete(R"HTML(
+ <!DOCTYPE html>
+ )HTML");
+ tester_.ExpectBucketCount(kHistogramName, 1, 10);
+
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(20));
+
+ // Simulate closing the page. This should cause us to report the metrics.
+ TearDown();
+
+ // The final 20 seconds had 2 agents.
+ tester_.ExpectBucketCount(kHistogramName, 1, 10);
+ tester_.ExpectBucketCount(kHistogramName, 2, 20);
+}
+
+// Ensure that multiple Pages in the same Agent are reported as only one agent.
+TEST_F(AgentMetricsCollectorUnitTest, WindowOpenSameAgents) {
+ SimRequest request_a("https://example.com/a.html", "text/html");
+ SimRequest request_b("https://example.com/b.html", "text/html");
+
+ LoadURL("https://example.com/a.html");
+ request_a.Complete(R"HTML(
+ <!DOCTYPE html>
+ <script>
+ window.open('https://example.com/b.html');
+ </script>
+ )HTML");
+ request_b.Complete(R"HTML(
+ <!DOCTYPE html>
+ )HTML");
+ Compositor().BeginFrame();
+
+ ASSERT_EQ(2u, Page::OrdinaryPages().size());
+
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
+
+ // Simulate closing the page. This should cause us to report the metrics.
+ TearDown();
+
+ // Both documents should end up in the same Agent, despite having separate
+ // WebViews/Page.
+ tester_.ExpectUniqueSample(kHistogramName, 1, 10);
+}
+
+// Ensure that multiple Pages in different Agents are reported as multiple
+// agents.
+TEST_F(AgentMetricsCollectorUnitTest, WindowOpenDifferentAgents) {
+ SimRequest request_a("https://example.com/a.html", "text/html");
+ SimRequest request_b("https://different.com/a.html", "text/html");
+
+ LoadURL("https://example.com/a.html");
+ request_a.Complete(R"HTML(
+ <!DOCTYPE html>
+ <script>
+ window.open('https://different.com/a.html');
+ </script>
+ )HTML");
+ request_b.Complete(R"HTML(
+ <!DOCTYPE html>
+ )HTML");
+ Compositor().BeginFrame();
+
+ ASSERT_EQ(2u, Page::OrdinaryPages().size());
+
+ tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
+
+ // Simulate closing the page. This should cause us to report the metrics.
+ TearDown();
+
+ // Each document should have its own Agent.
+ tester_.ExpectUniqueSample(kHistogramName, 2, 10);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer_test.cc b/chromium/third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer_test.cc
index 371360e1296..03e217d0de7 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer_test.cc
@@ -39,7 +39,7 @@
namespace blink {
class MockContextLifecycleStateObserver final
- : public GarbageCollectedFinalized<MockContextLifecycleStateObserver>,
+ : public GarbageCollected<MockContextLifecycleStateObserver>,
public ContextLifecycleStateObserver {
USING_GARBAGE_COLLECTED_MIXIN(MockContextLifecycleStateObserver);
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 c4265f46de9..ab17eb1089e 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
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.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"
@@ -45,7 +46,6 @@
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
-#include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -63,8 +63,7 @@ ExecutionContext::ExecutionContext(v8::Isolate* isolate,
agent_(agent),
origin_trial_context_(origin_trial_context),
window_interaction_tokens_(0),
- referrer_policy_(network::mojom::ReferrerPolicy::kDefault),
- invalidator_(std::make_unique<InterfaceInvalidator>()) {
+ referrer_policy_(network::mojom::ReferrerPolicy::kDefault) {
if (origin_trial_context_)
origin_trial_context_->BindExecutionContext(this);
}
@@ -106,7 +105,6 @@ void ExecutionContext::SetLifecycleState(mojom::FrameLifecycleState state) {
void ExecutionContext::NotifyContextDestroyed() {
is_context_destroyed_ = true;
- invalidator_.reset();
ContextLifecycleNotifier::NotifyContextDestroyed();
}
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 5e25addcd2c..727817f75f6 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
@@ -71,7 +71,6 @@ class DOMTimerCoordinator;
class ErrorEvent;
class EventTarget;
class FrameOrWorkerScheduler;
-class InterfaceInvalidator;
class KURL;
class LocalDOMWindow;
class OriginTrialContext;
@@ -287,8 +286,6 @@ class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier,
virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
TaskType) = 0;
- InterfaceInvalidator* GetInterfaceInvalidator() { return invalidator_.get(); }
-
v8::Isolate* GetIsolate() const { return isolate_; }
Agent* GetAgent() const { return agent_; }
@@ -352,8 +349,6 @@ class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier,
network::mojom::ReferrerPolicy referrer_policy_;
- std::unique_ptr<InterfaceInvalidator> invalidator_;
-
// Tracks which feature policies have already been parsed, so as not to count
// them multiple times.
// The size of this vector is 0 until FeaturePolicyFeatureObserved is called.
diff --git a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
index c70651037ae..854b508c9d4 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/remote_security_context.h
@@ -13,7 +13,7 @@
namespace blink {
class CORE_EXPORT RemoteSecurityContext
- : public GarbageCollectedFinalized<RemoteSecurityContext>,
+ : public GarbageCollected<RemoteSecurityContext>,
public SecurityContext {
USING_GARBAGE_COLLECTED_MIXIN(RemoteSecurityContext);
diff --git a/chromium/third_party/blink/renderer/core/execution_context/security_context.cc b/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
index dff94500f3a..081a3d2d005 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
+++ b/chromium/third_party/blink/renderer/core/execution_context/security_context.cc
@@ -27,7 +27,9 @@
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "base/metrics/histogram_macros.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
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 e3f4ac21df3..acfa25a5b14 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
@@ -34,6 +34,7 @@
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/core/core_export.h"
diff --git a/chromium/third_party/blink/renderer/core/execution_context/window_agent.h b/chromium/third_party/blink/renderer/core/execution_context/window_agent.h
index df47d5d393e..332b4ab47c7 100644
--- a/chromium/third_party/blink/renderer/core/execution_context/window_agent.h
+++ b/chromium/third_party/blink/renderer/core/execution_context/window_agent.h
@@ -23,9 +23,18 @@ class MutationObserverNotifier;
// shared by associated Documents.
class WindowAgent final : public Agent {
public:
- // Do not create the instance directly. Use
- // WindowAgentFactory::GetAgentForOrigin() instead.
+ // Normally you don't want to call this constructor; instead, use
+ // WindowAgentFactory::GetAgentForOrigin() so you can get the agent shared
+ // on the same-site frames.
+ //
+ // This constructor creates a unique agent that won't be shared with any
+ // other frames. Use this constructor only if:
+ // - You want your agent NOT shared with other (possibly same-site) frames
+ // (i.e. document-access feature policy is disabled), or
+ // - An appropriate instance of WindowAgentFactory is not available
+ // (this should only happen in tests).
explicit WindowAgent(v8::Isolate* isolate);
+
~WindowAgent() override;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 3a0e018b097..d65002cf818 100644
--- a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -469,12 +469,6 @@ void LocalFrameClientImpl::DispatchDidCommitLoad(
CoreInitializer::GetInstance().DidCommitLoad(*web_frame_->GetFrame());
}
-void LocalFrameClientImpl::DispatchDidFailProvisionalLoad(
- const ResourceError& error,
- const AtomicString& http_method) {
- web_frame_->DidFailProvisionalLoad(error, http_method);
-}
-
void LocalFrameClientImpl::DispatchDidFailLoad(
const ResourceError& error,
WebHistoryCommitType commit_type) {
@@ -500,7 +494,7 @@ void LocalFrameClientImpl::BeginNavigation(
bool has_transient_activation,
WebFrameLoadType frame_load_type,
bool is_client_redirect,
- WebTriggeringEventInfo triggering_event_info,
+ TriggeringEventInfo triggering_event_info,
HTMLFormElement* form,
ContentSecurityPolicyDisposition
should_check_main_world_content_security_policy,
@@ -647,7 +641,7 @@ void LocalFrameClientImpl::ForwardResourceTimingToParent(
void LocalFrameClientImpl::DownloadURL(
const ResourceRequest& request,
- DownloadCrossOriginRedirects cross_origin_redirect_behavior) {
+ network::mojom::RedirectMode cross_origin_redirect_behavior) {
if (!web_frame_->Client())
return;
DCHECK(web_frame_->GetFrame()->GetDocument());
@@ -656,20 +650,12 @@ void LocalFrameClientImpl::DownloadURL(
web_frame_->GetFrame()->GetDocument()->GetPublicURLManager().Resolve(
request.Url(), blob_url_token.InitWithNewPipeAndPassReceiver());
}
- web_frame_->Client()->DownloadURL(
- WrappedResourceRequest(request),
- static_cast<WebLocalFrameClient::CrossOriginRedirects>(
- cross_origin_redirect_behavior),
- blob_url_token.PassPipe());
-}
-
-void LocalFrameClientImpl::LoadErrorPage(int reason) {
- if (web_frame_->Client())
- web_frame_->Client()->LoadErrorPage(reason);
+ web_frame_->Client()->DownloadURL(WrappedResourceRequest(request),
+ cross_origin_redirect_behavior,
+ blob_url_token.PassPipe());
}
-bool LocalFrameClientImpl::NavigateBackForward(int offset,
- bool from_script) const {
+bool LocalFrameClientImpl::NavigateBackForward(int offset) const {
WebViewImpl* webview = web_frame_->ViewImpl();
DCHECK(webview->Client());
DCHECK(web_frame_->Client());
@@ -682,8 +668,7 @@ bool LocalFrameClientImpl::NavigateBackForward(int offset,
bool has_user_gesture =
LocalFrame::HasTransientUserActivation(web_frame_->GetFrame());
- web_frame_->Client()->NavigateBackForwardSoon(offset, has_user_gesture,
- from_script);
+ web_frame_->Client()->NavigateBackForwardSoon(offset, has_user_gesture);
return true;
}
@@ -725,11 +710,6 @@ void LocalFrameClientImpl::DidRunContentWithCertificateErrors() {
web_frame_->Client()->DidRunContentWithCertificateErrors();
}
-void LocalFrameClientImpl::ReportLegacyTLSVersion(const KURL& url) {
- if (web_frame_->Client())
- web_frame_->Client()->ReportLegacyTLSVersion(url);
-}
-
void LocalFrameClientImpl::DidChangePerformanceTiming() {
if (web_frame_->Client())
web_frame_->Client()->DidChangePerformanceTiming();
@@ -749,7 +729,7 @@ void LocalFrameClientImpl::DidChangeActiveSchedulerTrackedFeatures(
}
void LocalFrameClientImpl::DidObserveLoadingBehavior(
- WebLoadingBehaviorFlag behavior) {
+ LoadingBehaviorFlag behavior) {
if (web_frame_->Client())
web_frame_->Client()->DidObserveLoadingBehavior(behavior);
}
@@ -1027,7 +1007,7 @@ unsigned LocalFrameClientImpl::BackForwardLength() {
void LocalFrameClientImpl::SuddenTerminationDisablerChanged(
bool present,
- WebSuddenTerminationDisablerType type) {
+ SuddenTerminationDisablerType type) {
if (web_frame_->Client()) {
web_frame_->Client()->SuddenTerminationDisablerChanged(present, type);
}
@@ -1039,25 +1019,6 @@ BlameContext* LocalFrameClientImpl::GetFrameBlameContext() {
return nullptr;
}
-WebEffectiveConnectionType LocalFrameClientImpl::GetEffectiveConnectionType() {
- if (web_frame_->Client())
- return web_frame_->Client()->GetEffectiveConnectionType();
- return WebEffectiveConnectionType::kTypeUnknown;
-}
-
-void LocalFrameClientImpl::SetEffectiveConnectionTypeForTesting(
- WebEffectiveConnectionType type) {
- if (web_frame_->Client())
- return web_frame_->Client()->SetEffectiveConnectionTypeForTesting(type);
-}
-
-WebURLRequest::PreviewsState LocalFrameClientImpl::GetPreviewsStateForFrame()
- const {
- if (web_frame_->Client())
- return web_frame_->Client()->GetPreviewsStateForFrame();
- return WebURLRequest::kPreviewsUnspecified;
-}
-
WebDevToolsAgentImpl* LocalFrameClientImpl::DevToolsAgent() {
return WebLocalFrameImpl::FromFrame(web_frame_->GetFrame()->LocalFrameRoot())
->DevToolsAgentImpl();
@@ -1283,9 +1244,4 @@ void LocalFrameClientImpl::EvictFromBackForwardCache() {
return web_frame_->Client()->EvictFromBackForwardCache();
}
-STATIC_ASSERT_ENUM(DownloadCrossOriginRedirects::kFollow,
- WebLocalFrameClient::CrossOriginRedirects::kFollow);
-STATIC_ASSERT_ENUM(DownloadCrossOriginRedirects::kNavigate,
- WebLocalFrameClient::CrossOriginRedirects::kNavigate);
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index 1a06ac7063b..eca82e3154b 100644
--- a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -109,8 +109,6 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DispatchDidCommitLoad(HistoryItem*,
WebHistoryCommitType,
GlobalObjectReusePolicy) override;
- void DispatchDidFailProvisionalLoad(const ResourceError&,
- const AtomicString& http_method) override;
void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override;
void DispatchDidFinishDocumentLoad() override;
void DispatchDidFinishLoad() override;
@@ -126,7 +124,7 @@ class LocalFrameClientImpl final : public LocalFrameClient {
bool has_transient_activation,
WebFrameLoadType,
bool is_client_redirect,
- WebTriggeringEventInfo,
+ TriggeringEventInfo,
HTMLFormElement*,
ContentSecurityPolicyDisposition should_bypass_main_world_csp,
mojo::PendingRemote<mojom::blink::BlobURLToken>,
@@ -141,9 +139,8 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void ProgressEstimateChanged(double progress_estimate) override;
void ForwardResourceTimingToParent(const WebResourceTimingInfo&) override;
void DownloadURL(const ResourceRequest&,
- DownloadCrossOriginRedirects) override;
- void LoadErrorPage(int reason) override;
- bool NavigateBackForward(int offset, bool from_script) const override;
+ network::mojom::RedirectMode) override;
+ bool NavigateBackForward(int offset) const override;
void DidAccessInitialDocument() override;
void DidDisplayInsecureContent() override;
void DidContainInsecureFormAction() override;
@@ -152,11 +149,10 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DidDispatchPingLoader(const KURL&) override;
void DidDisplayContentWithCertificateErrors() override;
void DidRunContentWithCertificateErrors() override;
- void ReportLegacyTLSVersion(const KURL&) override;
void DidChangePerformanceTiming() override;
void DidChangeCpuTiming(base::TimeDelta) override;
void DidChangeActiveSchedulerTrackedFeatures(uint64_t features_mask) override;
- void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) override;
+ void DidObserveLoadingBehavior(LoadingBehaviorFlag) override;
void DidObserveNewFeatureUsage(mojom::WebFeature) override;
void DidObserveNewCssPropertyUsage(mojom::CSSSampleId, bool) override;
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
@@ -235,18 +231,11 @@ class LocalFrameClientImpl final : public LocalFrameClient {
unsigned BackForwardLength() override;
- void SuddenTerminationDisablerChanged(
- bool present,
- WebSuddenTerminationDisablerType) override;
+ void SuddenTerminationDisablerChanged(bool present,
+ SuddenTerminationDisablerType) override;
BlameContext* GetFrameBlameContext() override;
- WebEffectiveConnectionType GetEffectiveConnectionType() override;
- void SetEffectiveConnectionTypeForTesting(
- WebEffectiveConnectionType) override;
-
- WebURLRequest::PreviewsState GetPreviewsStateForFrame() const override;
-
KURL OverrideFlashEmbedWithHTML(const KURL&) override;
void NotifyUserActivation(bool need_browser_verification) override;
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 0ee5948103d..115f6007341 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
@@ -34,7 +34,6 @@
#include <memory>
#include <utility>
-#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_rect.h"
@@ -364,11 +363,11 @@ void WebDevToolsAgentImpl::WillBeDestroyed() {
resource_content_loader_->Dispose();
}
-void WebDevToolsAgentImpl::BindRequest(
- mojom::blink::DevToolsAgentHostAssociatedPtrInfo host_ptr_info,
- mojom::blink::DevToolsAgentAssociatedRequest request) {
- agent_->BindRequest(
- std::move(host_ptr_info), std::move(request),
+void WebDevToolsAgentImpl::BindReceiver(
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host_remote,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver) {
+ agent_->BindReceiver(
+ std::move(host_remote), std::move(receiver),
web_local_frame_impl_->GetTaskRunner(TaskType::kInternalInspector));
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h b/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
index 947811c8b1e..f00e10cb912 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
@@ -33,6 +33,8 @@
#include <memory>
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -56,7 +58,7 @@ class LocalFrame;
class WebLocalFrameImpl;
class CORE_EXPORT WebDevToolsAgentImpl final
- : public GarbageCollectedFinalized<WebDevToolsAgentImpl>,
+ : public GarbageCollected<WebDevToolsAgentImpl>,
public DevToolsAgent::Client,
public InspectorPageAgent::Client,
public InspectorLayerTreeAgent::Client,
@@ -79,8 +81,9 @@ class CORE_EXPORT WebDevToolsAgentImpl final
WebInputEventResult HandleInputEvent(const WebInputEvent&);
void DispatchBufferedTouchEvents();
- void BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo,
- mojom::blink::DevToolsAgentAssociatedRequest);
+ void BindReceiver(
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost>,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent>);
// Instrumentation from web/ layer.
void DidCommitLoadForLocalFrame(LocalFrame*);
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 f90d5653d42..f159f0c5d9b 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document.cc
@@ -84,11 +84,6 @@ WebSecurityOrigin WebDocument::GetSecurityOrigin() const {
return WebSecurityOrigin(ConstUnwrap<Document>()->GetSecurityOrigin());
}
-void WebDocument::GrantLoadLocalResources() {
- if (Document* document = Unwrap<Document>())
- document->GetMutableSecurityOrigin()->GrantLoadLocalResources();
-}
-
bool WebDocument::IsSecureContext() const {
const Document* document = ConstUnwrap<Document>();
return document && document->IsSecureContext();
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 e151b554af8..c0e5af9d524 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,15 +93,6 @@ WebURL WebDocumentLoaderImpl::UnreachableURL() const {
return DocumentLoader::UnreachableURL();
}
-int WebDocumentLoaderImpl::ErrorCode() const {
- return DocumentLoader::ErrorCode();
-}
-
-network::mojom::IPAddressSpace WebDocumentLoaderImpl::GetIPAddressSpace()
- const {
- return DocumentLoader::GetIPAddressSpace();
-}
-
void WebDocumentLoaderImpl::RedirectChain(WebVector<WebURL>& result) const {
result.Assign(redirect_chain_);
}
@@ -152,11 +143,6 @@ void WebDocumentLoaderImpl::SetSubresourceFilter(
void WebDocumentLoaderImpl::SetLoadingHintsProvider(
std::unique_ptr<blink::WebLoadingHintsProvider> loading_hints_provider) {
- if (!base::FeatureList::IsEnabled(
- blink::features::kSendPreviewsLoadingHintsBeforeCommit)) {
- return;
- }
-
DocumentLoader::SetPreviewsResourceLoadingHints(
PreviewsResourceLoadingHints::CreateFromLoadingHintsProvider(
*GetFrame()->GetDocument(), std::move(loading_hints_provider)));
@@ -184,6 +170,10 @@ bool WebDocumentLoaderImpl::HasBeenLoadedAsWebArchive() const {
return archive_ || (archive_load_result_ != mojom::MHTMLLoadResult::kSuccess);
}
+WebURLRequest::PreviewsState WebDocumentLoaderImpl::GetPreviewsState() const {
+ return DocumentLoader::GetPreviewsState();
+}
+
WebArchiveInfo WebDocumentLoaderImpl::GetArchiveInfo() const {
if (archive_) {
DCHECK(archive_->MainResource());
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 a7491de027b..86bc91d729c 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
@@ -67,8 +67,6 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
const WebURLResponse& GetResponse() const override;
bool HasUnreachableURL() const override;
WebURL UnreachableURL() const override;
- int ErrorCode() const override;
- network::mojom::IPAddressSpace GetIPAddressSpace() const override;
void RedirectChain(WebVector<WebURL>&) const override;
bool IsClientRedirect() const override;
bool ReplacesCurrentHistoryItem() const override;
@@ -84,6 +82,7 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
void BlockParser() override;
void ResumeParser() override;
bool HasBeenLoadedAsWebArchive() const override;
+ WebURLRequest::PreviewsState GetPreviewsState() const override;
WebArchiveInfo GetArchiveInfo() const override;
bool HadUserGesture() const override;
bool IsListingFtpDirectory() 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 85973ba4c9b..ebeb44a4ff6 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
@@ -190,6 +190,7 @@ namespace {
const char* g_base_url_origin_a = "http://example.test:0/";
const char* g_base_url_origin_sub_a = "http://subdomain.example.test:0/";
const char* g_base_url_origin_secure_a = "https://example.test:0/";
+const char* g_base_url_sandbox_origin_a = "http://sandbox.example.test:0/";
const char* g_base_url_origin_b = "http://not-example.test:0/";
const char* g_empty_file = "first_party/empty.html";
const char* g_nested_data = "first_party/nested-data.html";
@@ -219,6 +220,10 @@ KURL ToOriginSecureA(const char* file) {
return ToKURL(std::string(g_base_url_origin_secure_a) + file);
}
+KURL ToOriginSandboxA(const char* file) {
+ return ToKURL(std::string(g_base_url_sandbox_origin_a) + file);
+}
+
KURL ToOriginB(const char* file) {
return ToKURL(std::string(g_base_url_origin_b) + file);
}
@@ -261,6 +266,17 @@ void WebDocumentFirstPartyTest::SetUpTestCase() {
RegisterMockedURLLoad(ToOriginSubA(g_empty_file), g_empty_file);
RegisterMockedURLLoad(ToOriginSecureA(g_empty_file), g_empty_file);
+ WebURLResponse response(ToOriginSandboxA(g_empty_file));
+ response.SetMimeType(WebString::FromUTF8("text/html"));
+ response.SetHttpHeaderField(http_names::kContentType,
+ WebString::FromUTF8("text/html"));
+ response.SetHttpHeaderField(http_names::kContentSecurityPolicy,
+ WebString::FromUTF8("sandbox"));
+ response.SetHttpStatusCode(200);
+ url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+ ToOriginSandboxA(g_empty_file), test::CoreTestDataPath(g_empty_file),
+ response);
+
RegisterMockedURLLoad(ToOriginB(g_empty_file), g_empty_file);
RegisterMockedURLLoad(ToOriginB(g_nested_origin_a), g_nested_origin_a);
RegisterMockedURLLoad(ToOriginB(g_nested_origin_b), g_nested_origin_b);
@@ -299,15 +315,29 @@ bool OriginsEqual(const char* path,
TEST_F(WebDocumentFirstPartyTest, Empty) {
Load(g_empty_file);
- ASSERT_EQ(ToOriginA(g_empty_file), TopDocument()->SiteForCookies());
+ ASSERT_TRUE(OriginsEqual(
+ g_empty_file, SecurityOrigin::Create(TopDocument()->SiteForCookies())));
ASSERT_TRUE(OriginsEqual(g_empty_file, TopDocument()->TopFrameOrigin()));
}
+TEST_F(WebDocumentFirstPartyTest, EmptySandbox) {
+ web_view_helper_.InitializeAndLoad(std::string(g_base_url_sandbox_origin_a) +
+ g_empty_file);
+
+ ASSERT_TRUE(TopDocument()->TopFrameOrigin()->IsOpaque())
+ << TopDocument()->TopFrameOrigin()->ToUrlOrigin().GetDebugString();
+ ASSERT_EQ(NullURL(), TopDocument()->SiteForCookies());
+}
+
TEST_F(WebDocumentFirstPartyTest, NestedOriginA) {
Load(g_nested_origin_a);
- ASSERT_EQ(ToOriginA(g_nested_origin_a), TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_a), NestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
ASSERT_TRUE(OriginsEqual(g_nested_origin_a, TopDocument()->TopFrameOrigin()));
ASSERT_TRUE(
@@ -317,9 +347,12 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginA) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginSubA) {
Load(g_nested_origin_sub_a);
- ASSERT_EQ(ToOriginA(g_nested_origin_sub_a), TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_sub_a),
- NestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_sub_a,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_sub_a,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
ASSERT_TRUE(
OriginsEqual(g_nested_origin_sub_a, TopDocument()->TopFrameOrigin()));
@@ -330,10 +363,12 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginSubA) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginSecureA) {
Load(g_nested_origin_secure_a);
- ASSERT_EQ(ToOriginA(g_nested_origin_secure_a),
- TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_secure_a),
- NestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_secure_a,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_secure_a,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
ASSERT_TRUE(
OriginsEqual(g_nested_origin_secure_a, TopDocument()->TopFrameOrigin()));
@@ -344,12 +379,15 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginSecureA) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginA) {
Load(g_nested_origin_a_in_origin_a);
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_a),
- TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_a),
- NestedDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_a),
- NestedNestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a_in_origin_a,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a_in_origin_a,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
+ ASSERT_TRUE(OriginsEqual(
+ g_nested_origin_a_in_origin_a,
+ SecurityOrigin::Create(NestedNestedDocument()->SiteForCookies())));
ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_a,
TopDocument()->TopFrameOrigin()));
@@ -360,8 +398,9 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginA) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginB) {
Load(g_nested_origin_a_in_origin_b);
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_b),
- TopDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a_in_origin_b,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies());
ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies());
@@ -376,7 +415,9 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginB) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginB) {
Load(g_nested_origin_b);
- ASSERT_EQ(ToOriginA(g_nested_origin_b), TopDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_b,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies());
ASSERT_TRUE(OriginsEqual(g_nested_origin_b, TopDocument()->TopFrameOrigin()));
@@ -387,10 +428,12 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginB) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginA) {
Load(g_nested_origin_b_in_origin_a);
- ASSERT_EQ(ToOriginA(g_nested_origin_b_in_origin_a),
- TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_b_in_origin_a),
- NestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_b_in_origin_a,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_b_in_origin_a,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies());
ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_a,
@@ -404,8 +447,9 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginA) {
TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginB) {
Load(g_nested_origin_b_in_origin_b);
- ASSERT_EQ(ToOriginA(g_nested_origin_b_in_origin_b),
- TopDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_b_in_origin_b,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies());
ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies());
@@ -420,8 +464,12 @@ TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginB) {
TEST_F(WebDocumentFirstPartyTest, NestedSrcdoc) {
Load(g_nested_src_doc);
- ASSERT_EQ(ToOriginA(g_nested_src_doc), TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_src_doc), NestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_src_doc,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_src_doc,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
ASSERT_TRUE(OriginsEqual(g_nested_src_doc, TopDocument()->TopFrameOrigin()));
ASSERT_TRUE(
@@ -431,7 +479,8 @@ TEST_F(WebDocumentFirstPartyTest, NestedSrcdoc) {
TEST_F(WebDocumentFirstPartyTest, NestedData) {
Load(g_nested_data);
- ASSERT_EQ(ToOriginA(g_nested_data), TopDocument()->SiteForCookies());
+ ASSERT_TRUE(OriginsEqual(
+ g_nested_data, SecurityOrigin::Create(TopDocument()->SiteForCookies())));
ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies());
ASSERT_TRUE(OriginsEqual(g_nested_data, TopDocument()->TopFrameOrigin()));
@@ -444,12 +493,15 @@ TEST_F(WebDocumentFirstPartyTest,
SchemeRegistry::RegisterURLSchemeAsFirstPartyWhenTopLevel("http");
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_b),
- TopDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_b),
- NestedDocument()->SiteForCookies());
- ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_b),
- NestedNestedDocument()->SiteForCookies());
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a_in_origin_b,
+ SecurityOrigin::Create(TopDocument()->SiteForCookies())));
+ ASSERT_TRUE(
+ OriginsEqual(g_nested_origin_a_in_origin_b,
+ SecurityOrigin::Create(NestedDocument()->SiteForCookies())));
+ ASSERT_TRUE(OriginsEqual(
+ g_nested_origin_a_in_origin_b,
+ SecurityOrigin::Create(NestedNestedDocument()->SiteForCookies())));
ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b,
TopDocument()->TopFrameOrigin()));
diff --git a/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc b/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
index 9c623dc2bc0..4529881a288 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc
@@ -79,7 +79,7 @@ bool WebFormControlElement::IsAutofilled() const {
bool WebFormControlElement::UserHasEditedTheField() const {
if (auto* input = ToHTMLInputElementOrNull(*private_))
return input->UserHasEditedTheField();
- if (auto* select_element = ToHTMLSelectElementOrNull(*private_))
+ if (auto* select_element = DynamicTo<HTMLSelectElement>(*private_))
return select_element->UserHasEditedTheField();
return true;
}
@@ -110,7 +110,7 @@ bool WebFormControlElement::AutoComplete() const {
return input->ShouldAutocomplete();
if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
return textarea->ShouldAutocomplete();
- if (auto* select = ToHTMLSelectElementOrNull(*private_))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*private_))
return select->ShouldAutocomplete();
return false;
}
@@ -126,7 +126,7 @@ void WebFormControlElement::SetValue(const WebString& value, bool send_events) {
value, send_events
? TextFieldEventBehavior::kDispatchInputAndChangeEvent
: TextFieldEventBehavior::kDispatchNoEvent);
- } else if (auto* select = ToHTMLSelectElementOrNull(*private_)) {
+ } else if (auto* select = DynamicTo<HTMLSelectElement>(*private_)) {
select->setValue(value, send_events);
}
}
@@ -147,7 +147,7 @@ void WebFormControlElement::SetAutofillValue(const WebString& value) {
Unwrap<Element>()->DispatchBlurEvent(nullptr, kWebFocusTypeForward,
nullptr);
}
- } else if (auto* select = ToHTMLSelectElementOrNull(*private_)) {
+ } else if (auto* select = DynamicTo<HTMLSelectElement>(*private_)) {
if (!Focused()) {
Unwrap<Element>()->DispatchFocusEvent(nullptr, kWebFocusTypeForward,
nullptr);
@@ -165,7 +165,7 @@ WebString WebFormControlElement::Value() const {
return input->value();
if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
return textarea->value();
- if (auto* select = ToHTMLSelectElementOrNull(*private_))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*private_))
return select->value();
return WebString();
}
@@ -175,7 +175,7 @@ void WebFormControlElement::SetSuggestedValue(const WebString& value) {
input->SetSuggestedValue(value);
} else if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_)) {
textarea->SetSuggestedValue(value);
- } else if (auto* select = ToHTMLSelectElementOrNull(*private_))
+ } else if (auto* select = DynamicTo<HTMLSelectElement>(*private_))
select->SetSuggestedValue(value);
}
@@ -184,7 +184,7 @@ WebString WebFormControlElement::SuggestedValue() const {
return input->SuggestedValue();
if (auto* textarea = ToHTMLTextAreaElementOrNull(*private_))
return textarea->SuggestedValue();
- if (auto* select = ToHTMLSelectElementOrNull(*private_))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*private_))
return select->SuggestedValue();
return WebString();
}
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 034a9e4989f..50f348a3b19 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
@@ -17,7 +17,7 @@ namespace blink {
class HTMLElement;
class CORE_EXPORT WebFormElementObserverImpl final
- : public GarbageCollectedFinalized<WebFormElementObserverImpl>,
+ : public GarbageCollected<WebFormElementObserverImpl>,
public WebFormElementObserver {
public:
WebFormElementObserverImpl(HTMLElement&, base::OnceClosure);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame.cc b/chromium/third_party/blink/renderer/core/exported/web_frame.cc
index 2c5f20ab07b..ae81b3f59ff 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame.cc
@@ -34,6 +34,8 @@ bool WebFrame::Swap(WebFrame* frame) {
Frame* old_frame = ToCoreFrame(*this);
if (!old_frame->IsAttached())
return false;
+ FrameOwner* owner = old_frame->Owner();
+ FrameSwapScope frame_swap_scope(owner);
// Unload the current Document in this frame: this calls unload handlers,
// detaches child frames, etc. Since this runs script, make sure this frame
@@ -89,7 +91,6 @@ bool WebFrame::Swap(WebFrame* frame) {
Page* page = old_frame->GetPage();
AtomicString name = old_frame->Tree().GetName();
- FrameOwner* owner = old_frame->Owner();
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
WindowProxyManager::GlobalProxyVector global_proxies;
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 ddf240f82b9..cdc460ef992 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
@@ -181,7 +181,7 @@ bool MHTMLFrameSerializerDelegate::ShouldIgnoreMetaElement(
// the saved MHTML page, there is no need to carry the directives. If they
// are still kept in the MHTML, child frames that are referred to using cid:
// scheme could be prevented from loading.
- if (!IsHTMLMetaElement(element))
+ if (!IsA<HTMLMetaElement>(element))
return false;
if (!element.FastHasAttribute(html_names::kContentAttr))
return false;
@@ -204,8 +204,10 @@ bool MHTMLFrameSerializerDelegate::ShouldIgnorePopupOverlayElement(
int center_x = window->innerWidth() / 2;
int center_y = window->innerHeight() / 2;
if (Page* page = element.GetDocument().GetPage()) {
- center_x = page->GetChromeClient().WindowToViewportScalar(center_x);
- center_y = page->GetChromeClient().WindowToViewportScalar(center_y);
+ center_x = page->GetChromeClient().WindowToViewportScalar(
+ window->GetFrame(), center_x);
+ center_y = page->GetChromeClient().WindowToViewportScalar(
+ window->GetFrame(), center_y);
}
LayoutPoint center_point(center_x, center_y);
if (!box->FrameRect().Contains(center_point))
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
index 64a1cdc73cc..4c25b5735ea 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -187,6 +187,20 @@ namespace blink {
return os << "WebFloatPoint: [" << point.x << ", " << point.y << "]";
}
+namespace {
+
+template <typename Function>
+void ForAllGraphicsLayers(GraphicsLayer& layer, const Function& function) {
+ bool recurse = function(layer);
+ if (!recurse)
+ return;
+ for (auto* child : layer.Children()) {
+ ForAllGraphicsLayers(*child, function);
+ }
+}
+
+} // namespace
+
const int kTouchPointPadding = 32;
class WebFrameTest : public testing::Test {
@@ -1147,20 +1161,18 @@ TEST_F(WebFrameTest, PostMessageThenDetach) {
namespace {
-class FixedLayoutTestWebViewClient
- : public frame_test_helpers::TestWebViewClient {
+class FixedLayoutTestWebWidgetClient
+ : public frame_test_helpers::TestWebWidgetClient {
public:
- FixedLayoutTestWebViewClient() = default;
- ~FixedLayoutTestWebViewClient() override = default;
+ FixedLayoutTestWebWidgetClient() = default;
+ ~FixedLayoutTestWebWidgetClient() override = default;
- // frame_test_helpers::TestWebViewClient:
+ // frame_test_helpers::TestWebWidgetClient:
WebScreenInfo GetScreenInfo() override { return screen_info_; }
WebScreenInfo screen_info_;
};
-class FakeCompositingWebViewClient : public FixedLayoutTestWebViewClient {};
-
// Helper function to set autosizing multipliers on a document.
bool SetTextAutosizingMultiplier(Document* document, float multiplier) {
bool multiplier_set = false;
@@ -1197,13 +1209,13 @@ bool CheckTextAutosizingMultiplier(Document* document, float multiplier) {
TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
Document* document =
To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1230,11 +1242,11 @@ TEST_F(WebFrameTest, WorkingTextAutosizingMultipliers_VirtualViewport) {
const std::string html_file = "fixed_layout.html";
RegisterMockedHttpURLLoad(html_file);
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client,
- nullptr, ConfigureAndroid);
+ web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, nullptr,
+ &client, ConfigureAndroid);
Document* document =
To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1253,13 +1265,13 @@ TEST_F(WebFrameTest,
RegisterMockedHttpURLLoad("iframe_reload.html");
RegisterMockedHttpURLLoad("visible_iframe.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "iframe_reload.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
auto* main_frame =
To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
@@ -1298,13 +1310,13 @@ TEST_F(WebFrameTest,
}
TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored) {
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 1280;
int viewport_height = 0;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
@@ -1325,12 +1337,12 @@ TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag) {
int viewport_width = 640;
int viewport_height = 480;
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 2;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1351,7 +1363,7 @@ TEST_F(WebFrameTest, DeviceScaleFactorUsesDefaultWithoutViewportTag) {
TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -1359,7 +1371,7 @@ TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale) {
// Make sure we initialize to minimum scale, even if the window size
// only becomes available after the load begins.
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "fixed_layout.html");
@@ -1394,7 +1406,7 @@ TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale) {
TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale) {
RegisterMockedHttpURLLoad("wide_document.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -1402,7 +1414,7 @@ TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale) {
// Make sure we initialize to minimum scale, even if the window size
// only becomes available after the load begins.
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "wide_document.html");
@@ -1436,14 +1448,14 @@ TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale) {
TEST_F(WebFrameTest, DelayedViewportInitialScale) {
RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1463,14 +1475,14 @@ TEST_F(WebFrameTest, DelayedViewportInitialScale) {
TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse) {
RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1484,14 +1496,14 @@ TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse) {
TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport) {
RegisterMockedHttpURLLoad("large-div.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1506,14 +1518,14 @@ TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport) {
TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth) {
RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1537,15 +1549,15 @@ TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth) {
TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale) {
RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
@@ -1569,14 +1581,14 @@ TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale) {
TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag) {
RegisterMockedHttpURLLoad("no_viewport_tag.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1600,13 +1612,13 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag) {
TEST_F(WebFrameTest, WideViewportSetsTo980WithXhtmlMp) {
RegisterMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1630,14 +1642,14 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithXhtmlMp) {
TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta) {
RegisterMockedHttpURLLoad("viewport-height-1000.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "viewport-height-1000.html",
- nullptr, &client, nullptr,
+ nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1654,14 +1666,14 @@ TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta) {
TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth) {
RegisterMockedHttpURLLoad("viewport-2x-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-2x-initial-scale.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-2x-initial-scale.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1684,15 +1696,15 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth) {
TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode) {
RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1704,13 +1716,13 @@ TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode) {
TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
float enforced_page_scale_factor = 2.0f;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
@@ -1737,7 +1749,7 @@ TEST_F(WebFrameTest,
PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode) {
RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -1745,7 +1757,7 @@ TEST_F(WebFrameTest,
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
web_view_helper.GetWebView()->SetInitialPageScaleOverride(
@@ -1760,7 +1772,7 @@ TEST_F(WebFrameTest,
PermanentInitialPageScaleFactorOverridesPageViewportInitialScale) {
RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -1768,8 +1780,8 @@ TEST_F(WebFrameTest,
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetInitialPageScaleOverride(
enforced_page_scale_factor);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1791,7 +1803,7 @@ TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered) {
for (size_t i = 0; i < base::size(pages); ++i)
RegisterMockedHttpURLLoad(pages[i]);
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 400;
int viewport_height = 300;
@@ -1800,8 +1812,8 @@ TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered) {
for (size_t i = 0; i < base::size(pages); ++i) {
for (int quirk_enabled = 0; quirk_enabled <= 1; ++quirk_enabled) {
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + pages[i], nullptr, &client,
- nullptr, ConfigureAndroid);
+ web_view_helper.InitializeAndLoad(base_url_ + pages[i], nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetClobberUserAgentInitialScaleQuirk(quirk_enabled);
@@ -1820,14 +1832,14 @@ TEST_F(WebFrameTest, SmallPermanentInitialPageScaleFactorIsClobbered) {
}
TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth) {
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
float enforced_page_scale_factor = 0.5;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+ web_view_helper.InitializeAndLoad("about:blank", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -1850,15 +1862,15 @@ TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth) {
TEST_F(WebFrameTest, DocumentElementClientHeightWorksWithWrapContentMode) {
RegisterMockedHttpURLLoad("0-by-0.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1871,15 +1883,15 @@ TEST_F(WebFrameTest, DocumentElementClientHeightWorksWithWrapContentMode) {
TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksWithWrapContentMode) {
RegisterMockedHttpURLLoad("0-by-0.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
UpdateAllLifecyclePhases(web_view_helper.GetWebView());
@@ -1937,15 +1949,18 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksWithWrapContentMode) {
LocalFrame* frame = web_view_helper.LocalMainFrame()->GetFrame();
VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport();
- EXPECT_EQ(viewport_height, visual_viewport.ContainerLayer()->Size().height());
- EXPECT_TRUE(visual_viewport.ContainerLayer()->CcLayer()->masks_to_bounds());
+ auto* scroll_node = visual_viewport.GetScrollTranslationNode()->ScrollNode();
+ EXPECT_EQ(IntRect(0, 0, viewport_width, viewport_height),
+ scroll_node->ContainerRect());
+ EXPECT_EQ(IntSize(viewport_width, viewport_height),
+ scroll_node->ContentsSize());
EXPECT_FALSE(scroll_container->CcLayer()->masks_to_bounds());
}
TEST_F(WebFrameTest, SetForceZeroLayoutHeight) {
RegisterMockedHttpURLLoad("200-by-300.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -1953,7 +1968,7 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeight) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
EXPECT_LE(viewport_height, web_view_helper.GetWebView()
@@ -2002,14 +2017,14 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeight) {
TEST_F(WebFrameTest, ToggleViewportMetaOnOff) {
RegisterMockedHttpURLLoad("viewport-device-width.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "viewport-device-width.html",
- nullptr, &client);
+ nullptr, nullptr, &client);
WebSettings* settings = web_view_helper.GetWebView()->GetSettings();
settings->SetViewportMetaEnabled(false);
settings->SetViewportEnabled(true);
@@ -2040,15 +2055,15 @@ TEST_F(WebFrameTest,
// because the layout is only updated if either width or height is changed
RegisterMockedHttpURLLoad("button.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "button.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ web_view_helper.InitializeAndLoad(base_url_ + "button.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
// set view height to zero so that if the height of the view is not
// successfully updated during later resizes touch events will fail
// (as in not hit content included in the view)
@@ -2144,7 +2159,7 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations) {
RegisterMockedHttpURLLoad("200-by-300.html");
RegisterMockedHttpURLLoad("large-div.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -2152,7 +2167,7 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2170,7 +2185,7 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations) {
TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk) {
RegisterMockedHttpURLLoad("200-by-300.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
@@ -2178,7 +2193,7 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -2195,13 +2210,13 @@ TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk) {
TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight) {
RegisterMockedHttpURLLoad("viewport-height-1000.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 600;
int viewport_height = 800;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+ web_view_helper.InitializeAndLoad("about:blank", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -2223,13 +2238,13 @@ TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight) {
TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling) {
RegisterMockedHttpURLLoad("body-overflow-hidden.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client);
+ web_view_helper.Initialize(nullptr, nullptr, &client);
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "body-overflow-hidden.html");
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2243,13 +2258,13 @@ TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling) {
TEST_F(WebFrameTest, OverflowHiddenDisablesScrollingWithSetCanHaveScrollbars) {
RegisterMockedHttpURLLoad("body-overflow-hidden-short.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client);
+ web_view_helper.Initialize(nullptr, nullptr, &client);
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "body-overflow-hidden-short.html");
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2268,13 +2283,13 @@ TEST_F(WebFrameTest, OverflowHiddenDisablesScrollingWithSetCanHaveScrollbars) {
TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) {
RegisterMockedHttpURLLoad("body-overflow-hidden.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client);
+ web_view_helper.Initialize(nullptr, nullptr, &client);
web_view_helper.GetWebView()
->GetSettings()
->SetIgnoreMainFrameOverflowHiddenQuirk(true);
@@ -2289,14 +2304,14 @@ TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) {
TEST_F(WebFrameTest, NonZeroValuesNoQuirk) {
RegisterMockedHttpURLLoad("viewport-nonzero-values.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
float expected_page_scale_factor = 0.5f;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetViewportMetaZeroValuesQuirk(
true);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -2329,7 +2344,7 @@ TEST_F(WebFrameTest, NonZeroValuesNoQuirk) {
TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
// Small viewport to ensure there are always scrollbars.
int viewport_width = 64;
@@ -2337,7 +2352,7 @@ TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
unsigned prev_layout_count =
@@ -2356,14 +2371,14 @@ TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout) {
TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
unsigned prev_layout_count =
@@ -2382,14 +2397,14 @@ TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout) {
TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
web_view_helper.GetWebView()->SetPageScaleFactor(3);
@@ -2405,13 +2420,13 @@ TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem) {
TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "fixed_layout.html");
@@ -2432,7 +2447,7 @@ TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem) {
TEST_F(WebFrameTest, pageScaleFactorDoesntShrinkFrameView) {
RegisterMockedHttpURLLoad("large-div.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
// Small viewport to ensure there are always scrollbars.
int viewport_width = 64;
@@ -2440,7 +2455,7 @@ TEST_F(WebFrameTest, pageScaleFactorDoesntShrinkFrameView) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -2475,14 +2490,14 @@ TEST_F(WebFrameTest, pageScaleFactorDoesntShrinkFrameView) {
TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
web_view_helper.GetWebView()->SetPageScaleFactor(2);
@@ -2503,7 +2518,7 @@ TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform) {
TEST_F(WebFrameTest, targetDensityDpiHigh) {
RegisterMockedHttpURLLoad("viewport-target-densitydpi-high.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
// high-dpi = 240
float target_dpi = 240.0f;
float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
@@ -2517,8 +2532,8 @@ TEST_F(WebFrameTest, targetDensityDpiHigh) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-target-densitydpi-high.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-target-densitydpi-high.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()
@@ -2554,7 +2569,7 @@ TEST_F(WebFrameTest, targetDensityDpiDevice) {
float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
@@ -2563,8 +2578,8 @@ TEST_F(WebFrameTest, targetDensityDpiDevice) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-target-densitydpi-device.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-target-densitydpi-device.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()
@@ -2597,7 +2612,7 @@ TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth) {
float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
@@ -2607,7 +2622,7 @@ TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-target-densitydpi-device-and-fixed-width.html",
- nullptr, &client, nullptr, ConfigureAndroid);
+ nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
web_view_helper.GetWebView()
@@ -2637,15 +2652,15 @@ TEST_F(WebFrameTest, targetDensityDpiDeviceAndFixedWidth) {
TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) {
RegisterMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1.33f;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, &client,
- nullptr, ConfigureAndroid);
+ base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, nullptr,
+ &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2676,7 +2691,7 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
RegisterMockedHttpURLLoad(
"viewport-initial-scale-less-than-1-device-width.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1.33f;
int viewport_width = 640;
int viewport_height = 480;
@@ -2684,7 +2699,7 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-less-than-1-device-width.html",
- nullptr, &client, nullptr, ConfigureAndroid);
+ nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2717,14 +2732,14 @@ TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) {
RegisterMockedHttpURLLoad("large-div.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
float enforced_page_scale_factor = 5.0f;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -2754,14 +2769,14 @@ TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) {
TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale) {
RegisterMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetViewportMetaNonUserScalableQuirk(true);
@@ -2788,7 +2803,7 @@ TEST_F(WebFrameTest,
NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport) {
RegisterMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1.33f;
int viewport_width = 640;
int viewport_height = 480;
@@ -2796,7 +2811,7 @@ TEST_F(WebFrameTest,
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2829,14 +2844,14 @@ TEST_F(WebFrameTest,
TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) {
RegisterMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(
base_url_ + "viewport-2x-initial-scale-non-user-scalable.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()
->GetSettings()
->SetViewportMetaNonUserScalableQuirk(true);
@@ -2865,13 +2880,13 @@ TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) {
TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff) {
RegisterMockedHttpURLLoad("no_viewport_tag.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
true);
@@ -2888,10 +2903,10 @@ TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff) {
TEST_F(WebFrameTest, AtViewportInsideAtMediaInitialViewport) {
RegisterMockedHttpURLLoad("viewport-inside-media.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "viewport-inside-media.html",
- nullptr, &client, nullptr,
+ nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.Resize(WebSize(640, 480));
@@ -2913,9 +2928,9 @@ TEST_F(WebFrameTest, AtViewportInsideAtMediaInitialViewport) {
TEST_F(WebFrameTest, AtViewportAffectingAtMediaRecalcCount) {
RegisterMockedHttpURLLoad("viewport-and-media.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(640, 480));
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "viewport-and-media.html");
@@ -2939,9 +2954,9 @@ TEST_F(WebFrameTest, AtViewportAffectingAtMediaRecalcCount) {
TEST_F(WebFrameTest, AtViewportWithViewportLengths) {
RegisterMockedHttpURLLoad("viewport-lengths.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+ web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(800, 600));
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
base_url_ + "viewport-lengths.html");
@@ -3091,14 +3106,14 @@ TEST_F(WebFrameResizeTest, ResizeYieldsCorrectScrollAndScaleForFixedLayout) {
TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars) {
RegisterMockedHttpURLLoad("fixed_layout.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -3119,14 +3134,14 @@ TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars) {
TEST_F(WebFrameTest, CanOverrideScaleLimits) {
RegisterMockedHttpURLLoad("no_scale_for_you.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "no_scale_for_you.html",
- nullptr, &client, nullptr,
+ nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -3159,10 +3174,10 @@ TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
int view_width = 500;
int view_height = 500;
- FakeCompositingWebViewClient fake_compositing_web_view_client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, &fake_compositing_web_view_client,
- nullptr, &ConfigureCompositingWebView);
+ web_view_helper.Initialize(nullptr, nullptr, &client,
+ &ConfigureCompositingWebView);
web_view_helper.Resize(WebSize(view_width, view_height));
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -5203,8 +5218,7 @@ TEST_F(WebFrameTest, SetTickmarks) {
// Get the tickmarks for the original find request.
LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
ScrollableArea* layout_viewport = frame_view->LayoutViewport();
- Vector<IntRect> original_tickmarks;
- layout_viewport->GetTickmarks(original_tickmarks);
+ Vector<IntRect> original_tickmarks = layout_viewport->GetTickmarks();
EXPECT_EQ(4u, original_tickmarks.size());
// Override the tickmarks.
@@ -5215,8 +5229,7 @@ TEST_F(WebFrameTest, SetTickmarks) {
main_frame->SetTickmarks(overriding_tickmarks_expected);
// Check the tickmarks are overriden correctly.
- Vector<IntRect> overriding_tickmarks_actual;
- layout_viewport->GetTickmarks(overriding_tickmarks_actual);
+ Vector<IntRect> overriding_tickmarks_actual = layout_viewport->GetTickmarks();
EXPECT_EQ(overriding_tickmarks_expected, overriding_tickmarks_actual);
// Reset the tickmark behavior.
@@ -5224,8 +5237,8 @@ TEST_F(WebFrameTest, SetTickmarks) {
main_frame->SetTickmarks(reset_tickmarks);
// Check that the original tickmarks are returned
- Vector<IntRect> original_tickmarks_after_reset;
- layout_viewport->GetTickmarks(original_tickmarks_after_reset);
+ Vector<IntRect> original_tickmarks_after_reset =
+ layout_viewport->GetTickmarks();
EXPECT_EQ(original_tickmarks, original_tickmarks_after_reset);
}
@@ -6132,8 +6145,7 @@ class CompositedSelectionBoundsTest
web_view_helper_.GetWebView()->MainFrameImpl(), base_url_ + test_file);
UpdateAllLifecyclePhases(web_view_helper_.GetWebView());
- cc::LayerTreeHost* layer_tree_host =
- web_widget_client_.layer_tree_view()->layer_tree_host();
+ cc::LayerTreeHost* layer_tree_host = web_widget_client_.layer_tree_host();
const cc::LayerSelection& selection = layer_tree_host->selection();
ASSERT_EQ(selection, cc::LayerSelection());
@@ -6232,8 +6244,7 @@ class CompositedSelectionBoundsTest
->GetEventHandler()
.HandleGestureEvent(gesture_event);
- cc::LayerTreeHost* layer_tree_host =
- web_widget_client_.layer_tree_view()->layer_tree_host();
+ cc::LayerTreeHost* layer_tree_host = web_widget_client_.layer_tree_host();
const cc::LayerSelection& selection = layer_tree_host->selection();
ASSERT_NE(selection, cc::LayerSelection());
@@ -7024,10 +7035,12 @@ TEST_F(WebFrameTest, SiteForCookiesForRedirect) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "first_party_redirect.html");
- EXPECT_TRUE(web_view_helper.GetWebView()
- ->MainFrameImpl()
- ->GetDocument()
- .SiteForCookies() == redirect_url);
+ EXPECT_TRUE(
+ SecurityOrigin::AreSameSchemeHostPort(web_view_helper.GetWebView()
+ ->MainFrameImpl()
+ ->GetDocument()
+ .SiteForCookies(),
+ redirect_url));
}
class TestNewWindowWebViewClient
@@ -7099,8 +7112,7 @@ TEST_F(WebFrameTest, ModifiedClickNewWindow) {
MouseEvent::Create(nullptr, event_type_names::kClick, mouse_initializer);
FrameLoadRequest frame_request(document, ResourceRequest(destination));
frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(event));
- frame_request.SetTriggeringEventInfo(
- WebTriggeringEventInfo::kFromTrustedEvent);
+ frame_request.SetTriggeringEventInfo(TriggeringEventInfo::kFromTrustedEvent);
std::unique_ptr<UserGestureIndicator> gesture =
LocalFrame::NotifyUserActivation(frame);
web_frame_client.IgnoreNavigations();
@@ -7453,6 +7465,35 @@ TEST_F(WebFrameTest, PushStateStartsAndStops) {
EXPECT_EQ(client.StopLoadingCount(), 2);
}
+TEST_F(WebFrameTest, IPAddressSpace) {
+ frame_test_helpers::WebViewHelper web_view_helper;
+ WebViewImpl* web_view =
+ web_view_helper.InitializeAndLoad("data:text/html,ip_address_space");
+
+ network::mojom::IPAddressSpace values[] = {
+ network::mojom::IPAddressSpace::kUnknown,
+ network::mojom::IPAddressSpace::kLocal,
+ network::mojom::IPAddressSpace::kPrivate,
+ network::mojom::IPAddressSpace::kPublic};
+
+ for (auto value : values) {
+ 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;
+ params->ip_address_space = value;
+ web_view_helper.LocalMainFrame()->CommitNavigation(
+ std::move(params), nullptr, base::DoNothing::Once());
+ frame_test_helpers::PumpPendingRequestsForFrameToLoad(
+ web_view_helper.LocalMainFrame());
+
+ ExecutionContext* context =
+ web_view->MainFrameImpl()->GetFrame()->GetDocument();
+ EXPECT_EQ(value, context->GetSecurityContext().AddressSpace());
+ }
+}
+
class TestDidNavigateCommitTypeWebFrameClient
: public frame_test_helpers::TestWebFrameClient {
public:
@@ -7593,12 +7634,10 @@ TEST_F(WebFrameTest, FirstNonBlankSubframeNavigation) {
// Test verifies that layout will change a layer's scrollable attibutes
TEST_F(WebFrameTest, overflowHiddenRewrite) {
RegisterMockedHttpURLLoad("non-scrollable.html");
- std::unique_ptr<FakeCompositingWebViewClient>
- fake_compositing_web_view_client =
- std::make_unique<FakeCompositingWebViewClient>();
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
- web_view_helper.Initialize(nullptr, fake_compositing_web_view_client.get(),
- nullptr, &ConfigureCompositingWebView);
+ web_view_helper.Initialize(nullptr, nullptr, &client,
+ &ConfigureCompositingWebView);
web_view_helper.Resize(WebSize(100, 100));
frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -7729,11 +7768,11 @@ TEST_F(WebFrameTest, FrameViewMoveWithSetFrameRect) {
}
TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("long_scroll.html");
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html", nullptr,
- &client, nullptr, ConfigureAndroid);
+ nullptr, &client, ConfigureAndroid);
WebViewImpl* web_view = web_view_helper.GetWebView();
LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -7820,14 +7859,14 @@ TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
TEST_F(WebFrameTest, MaximumScrollPositionCanBeNegative) {
RegisterMockedHttpURLLoad("rtl-overview-mode.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.device_scale_factor = 1;
int viewport_width = 640;
int viewport_height = 480;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "rtl-overview-mode.html",
- nullptr, &client, nullptr,
+ nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.GetWebView()->SetInitialPageScaleOverride(-1);
web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -7843,7 +7882,7 @@ TEST_F(WebFrameTest, MaximumScrollPositionCanBeNegative) {
}
TEST_F(WebFrameTest, FullscreenLayerSize) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("fullscreen_div.html");
frame_test_helpers::WebViewHelper web_view_helper;
int viewport_width = 640;
@@ -7851,7 +7890,7 @@ TEST_F(WebFrameTest, FullscreenLayerSize) {
client.screen_info_.rect.width = viewport_width;
client.screen_info_.rect.height = viewport_height;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+ base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
UpdateAllLifecyclePhases(web_view_impl);
@@ -7884,13 +7923,13 @@ TEST_F(WebFrameTest, FullscreenLayerSize) {
}
TEST_F(WebFrameTest, FullscreenLayerNonScrollable) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("fullscreen_div.html");
frame_test_helpers::WebViewHelper web_view_helper;
int viewport_width = 640;
int viewport_height = 480;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+ base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
UpdateAllLifecyclePhases(web_view_impl);
@@ -7944,13 +7983,13 @@ TEST_F(WebFrameTest, FullscreenLayerNonScrollable) {
}
TEST_F(WebFrameTest, FullscreenMainFrame) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("fullscreen_div.html");
frame_test_helpers::WebViewHelper web_view_helper;
int viewport_width = 640;
int viewport_height = 480;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+ base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
ConfigureAndroid);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
UpdateAllLifecyclePhases(web_view_impl);
@@ -7998,12 +8037,12 @@ TEST_F(WebFrameTest, FullscreenMainFrame) {
}
TEST_F(WebFrameTest, FullscreenSubframe) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("fullscreen_iframe.html");
RegisterMockedHttpURLLoad("fullscreen_div.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "fullscreen_iframe.html", nullptr, &client, nullptr,
+ base_url_ + "fullscreen_iframe.html", nullptr, nullptr, &client,
ConfigureAndroid);
int viewport_width = 640;
int viewport_height = 480;
@@ -8088,11 +8127,11 @@ TEST_F(WebFrameTest, FullscreenNestedExit) {
}
TEST_F(WebFrameTest, FullscreenWithTinyViewport) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("viewport-tiny.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-tiny.html", nullptr, nullptr, &client,
ConfigureAndroid);
int viewport_width = 384;
int viewport_height = 640;
@@ -8133,11 +8172,11 @@ TEST_F(WebFrameTest, FullscreenWithTinyViewport) {
}
TEST_F(WebFrameTest, FullscreenResizeWithTinyViewport) {
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("viewport-tiny.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
+ base_url_ + "viewport-tiny.html", nullptr, nullptr, &client,
ConfigureAndroid);
int viewport_width = 384;
int viewport_height = 640;
@@ -8192,12 +8231,12 @@ TEST_F(WebFrameTest, FullscreenRestoreScaleFactorUponExiting) {
WebSize screen_size_minus_status_bars(598, 359);
WebSize screen_size(640, 384);
- FakeCompositingWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
RegisterMockedHttpURLLoad("fullscreen_restore_scale_factor.html");
frame_test_helpers::WebViewHelper web_view_helper;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
- base_url_ + "fullscreen_restore_scale_factor.html", nullptr, &client,
- nullptr, &ConfigureAndroid);
+ base_url_ + "fullscreen_restore_scale_factor.html", nullptr, nullptr,
+ &client, &ConfigureAndroid);
client.screen_info_.rect.width =
screen_size_minus_status_bars_minus_url_bar.width;
client.screen_info_.rect.height =
@@ -8321,8 +8360,13 @@ TEST_F(WebFrameTest, OverlayFullscreenVideo) {
web_view_helper.InitializeAndLoad(base_url_ + "fullscreen_video.html",
nullptr, nullptr, &web_widget_client);
+ // Ensure that the local frame view has a paint artifact compositor. It's
+ // created lazily, and doing so after entering fullscreen would undo the
+ // overlay video layer modification.
+ UpdateAllLifecyclePhases(web_view_impl);
+
const cc::LayerTreeHost* layer_tree_host =
- web_widget_client.layer_tree_view()->layer_tree_host();
+ web_widget_client.layer_tree_host();
LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
std::unique_ptr<UserGestureIndicator> gesture =
@@ -8340,6 +8384,52 @@ TEST_F(WebFrameTest, OverlayFullscreenVideo) {
EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()),
SK_AlphaTRANSPARENT);
+ // Check that the sibling div layer is invalidated. It should have its own
+ // graphics layer since it has a transform.
+ GraphicsLayer* div_layer =
+ ToLayoutBoxModelObject(
+ frame->GetDocument()->getElementById("other")->GetLayoutObject())
+ ->Layer()
+ ->GetCompositedLayerMapping()
+ ->MainGraphicsLayer();
+ EXPECT_TRUE(div_layer->GetPaintController().CacheIsAllInvalid());
+
+ // Verify that the video layer is present in the painted graphics layer tree
+ // and that the non-video graphics layers (if any) don't paint anything. The
+ // goal is that the body text and sibling div content should not be visible.
+ // This test should be independent of the mechanism used to accomplish this,
+ // i.e. it could be done by deleting layers, marking them as not drawing, or
+ // by overriding the paint root.
+ GraphicsLayer* video_layer = ToLayoutBoxModelObject(video->GetLayoutObject())
+ ->Layer()
+ ->GetCompositedLayerMapping()
+ ->MainGraphicsLayer();
+ EXPECT_TRUE(video_layer);
+ GraphicsLayer* root_layer =
+ frame->View()->GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
+ EXPECT_TRUE(root_layer);
+ int actively_painting_layers = 0;
+ bool found_video_layer = false;
+ ForAllGraphicsLayers(*root_layer, [&](GraphicsLayer& layer) -> bool {
+ // The video layer is expected to be present, but don't recurse into it.
+ if (&layer == video_layer) {
+ found_video_layer = true;
+ return false;
+ }
+ if (!layer.PaintsContentOrHitTest() || !layer.HasLayerState() ||
+ !layer.DrawsContent()) {
+ // Recurse into non-drawing layers, but don't check if they paint.
+ return true;
+ }
+ layer.CapturePaintRecord();
+ if (layer.GetPaintController().GetDisplayItemList().size() > 0 ||
+ layer.GetPaintController().PaintChunks().size() > 0)
+ ++actively_painting_layers;
+ return true;
+ });
+ EXPECT_EQ(actively_painting_layers, 0);
+ EXPECT_TRUE(found_video_layer);
+
web_view_impl->MainFrameWidget()->DidExitFullscreen();
UpdateAllLifecyclePhases(web_view_impl);
EXPECT_FALSE(video->IsFullscreen());
@@ -8357,7 +8447,7 @@ TEST_F(WebFrameTest, OverlayFullscreenVideoInIframe) {
&web_widget_client);
const cc::LayerTreeHost* layer_tree_host =
- web_widget_client.layer_tree_view()->layer_tree_host();
+ web_widget_client.layer_tree_host();
LocalFrame* iframe =
To<WebLocalFrameImpl>(
web_view_helper.GetWebView()->MainFrame()->FirstChild())
@@ -8383,6 +8473,113 @@ TEST_F(WebFrameTest, OverlayFullscreenVideoInIframe) {
EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
}
+TEST_F(WebFrameTest, WebXrImmersiveOverlay) {
+ RegisterMockedHttpURLLoad("webxr_overlay.html");
+ frame_test_helpers::TestWebWidgetClient web_widget_client;
+ frame_test_helpers::WebViewHelper web_view_helper;
+ WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
+ base_url_ + "webxr_overlay.html", nullptr, nullptr, &web_widget_client);
+ web_view_helper.Resize(WebSize(640, 480));
+
+ // Ensure that the local frame view has a paint artifact compositor. It's
+ // created lazily, and doing so after entering fullscreen would undo the
+ // overlay layer modification.
+ UpdateAllLifecyclePhases(web_view_impl);
+
+ const cc::LayerTreeHost* layer_tree_host =
+ web_widget_client.layer_tree_host();
+
+ LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
+
+ Document* document = frame->GetDocument();
+ EXPECT_FALSE(document->IsImmersiveArOverlay());
+ document->SetIsImmersiveArOverlay(true);
+ EXPECT_TRUE(document->IsImmersiveArOverlay());
+
+ Element* overlay = document->getElementById("overlay");
+ EXPECT_FALSE(Fullscreen::IsFullscreenElement(*overlay));
+ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
+
+ // Fullscreen should work without separate user activation while in ArOverlay
+ // mode.
+ Fullscreen::RequestFullscreen(*overlay);
+ web_view_impl->MainFrameWidget()->DidEnterFullscreen();
+ UpdateAllLifecyclePhases(web_view_impl);
+ EXPECT_TRUE(Fullscreen::IsFullscreenElement(*overlay));
+ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()),
+ SK_AlphaTRANSPARENT);
+
+ GraphicsLayer* inner_layer =
+ ToLayoutBoxModelObject(
+ frame->GetDocument()->getElementById("inner")->GetLayoutObject())
+ ->Layer()
+ ->GetCompositedLayerMapping()
+ ->MainGraphicsLayer();
+ EXPECT_TRUE(inner_layer);
+
+ // Verify that the overlay layer and inner layers are present in the painted
+ // graphics layer tree and that the non-overlay graphics layers (if any) don't
+ // paint anything. The goal is that the body text and sibling div content
+ // should not be visible. This test should be independent of the mechanism
+ // used to accomplish this, i.e. it could be done by deleting layers, marking
+ // them as not drawing, or by overriding the paint root.
+ GraphicsLayer* overlay_layer =
+ ToLayoutBoxModelObject(overlay->GetLayoutObject())
+ ->Layer()
+ ->GetCompositedLayerMapping()
+ ->MainGraphicsLayer();
+ EXPECT_TRUE(overlay_layer);
+ GraphicsLayer* root_layer =
+ frame->View()->GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
+ EXPECT_TRUE(root_layer);
+ int actively_painting_layers = 0;
+ bool found_overlay_layer = false;
+ bool found_inner_layer = false;
+ ForAllGraphicsLayers(*root_layer, [&](GraphicsLayer& layer) -> bool {
+ // The overlay layers is expected to be present, but don't recurse into it.
+ // (This also skips the inner layer which is a child of the overlay layer.)
+ if (&layer == overlay_layer) {
+ found_overlay_layer = true;
+ return false;
+ }
+ if (&layer == inner_layer) {
+ // This shouldn't happen, the inner layer must remain inside the overlay
+ // layer.
+ found_inner_layer = true;
+ }
+ if (!layer.PaintsContentOrHitTest() || !layer.HasLayerState() ||
+ !layer.DrawsContent()) {
+ // Recurse into non-drawing layers, but don't check if they paint.
+ return true;
+ }
+ layer.CapturePaintRecord();
+ if (layer.GetPaintController().GetDisplayItemList().size() > 0 ||
+ layer.GetPaintController().PaintChunks().size() > 0)
+ ++actively_painting_layers;
+ return true;
+ });
+ EXPECT_EQ(actively_painting_layers, 0);
+ EXPECT_TRUE(found_overlay_layer);
+
+ // Check for the inner layer separately, the previous recursion was supposed
+ // to skip it due to being a child of the overlay layer.
+ EXPECT_FALSE(found_inner_layer);
+ ForAllGraphicsLayers(*root_layer, [&](GraphicsLayer& layer) -> bool {
+ if (&layer == inner_layer) {
+ found_inner_layer = true;
+ return false;
+ }
+ return true;
+ });
+ EXPECT_TRUE(found_inner_layer);
+
+ web_view_impl->MainFrameWidget()->DidExitFullscreen();
+ UpdateAllLifecyclePhases(web_view_impl);
+ EXPECT_FALSE(Fullscreen::IsFullscreenElement(*overlay));
+ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
+ document->SetIsImmersiveArOverlay(false);
+}
+
TEST_F(WebFrameTest, LayoutBlockPercentHeightDescendants) {
RegisterMockedHttpURLLoad("percent-height-descendants.html");
frame_test_helpers::WebViewHelper web_view_helper;
@@ -8689,6 +8886,35 @@ TEST_F(WebFrameTest, EmbedderTriggeredDetachWithRemoteMainFrame) {
child_core_frame.Clear();
}
+class WebFrameSwapTestClient : public frame_test_helpers::TestWebFrameClient {
+ public:
+ WebFrameSwapTestClient() {}
+
+ WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
+ WebTreeScopeType scope,
+ const WebString& name,
+ const WebString& fallback_name,
+ const FramePolicy&,
+ const WebFrameOwnerProperties&,
+ FrameOwnerElementType) override {
+ return CreateLocalChild(*parent, scope,
+ std::make_unique<WebFrameSwapTestClient>());
+ }
+
+ void DidChangeFrameOwnerProperties(
+ WebFrame* child_frame,
+ const WebFrameOwnerProperties& properties) override {
+ did_propagate_display_none_ |= properties.is_display_none;
+ }
+
+ bool DidPropagateDisplayNoneProperty() const {
+ return did_propagate_display_none_;
+ }
+
+ private:
+ bool did_propagate_display_none_ = false;
+};
+
class WebFrameSwapTest : public WebFrameTest {
protected:
WebFrameSwapTest() {
@@ -8698,7 +8924,8 @@ class WebFrameSwapTest : public WebFrameTest {
RegisterMockedHttpURLLoad("subframe-c.html");
RegisterMockedHttpURLLoad("subframe-hello.html");
- web_view_helper_.InitializeAndLoad(base_url_ + "frame-a-b-c.html");
+ web_view_helper_.InitializeAndLoad(base_url_ + "frame-a-b-c.html",
+ &main_frame_client_);
}
void Reset() { web_view_helper_.Reset(); }
@@ -8707,6 +8934,7 @@ class WebFrameSwapTest : public WebFrameTest {
private:
frame_test_helpers::WebViewHelper web_view_helper_;
+ WebFrameSwapTestClient main_frame_client_;
};
TEST_F(WebFrameSwapTest, SwapMainFrame) {
@@ -8850,6 +9078,26 @@ TEST_F(WebFrameSwapTest, SwapFirstChild) {
EXPECT_EQ(" \n\nhello\n\nb \n\na\n\nc", content);
}
+TEST_F(WebFrameSwapTest, DoNotPropagateDisplayNonePropertyOnSwap) {
+ WebFrameSwapTestClient* main_frame_client =
+ static_cast<WebFrameSwapTestClient*>(MainFrame()->Client());
+ EXPECT_FALSE(main_frame_client->DidPropagateDisplayNoneProperty());
+
+ WebLocalFrame* child_frame = MainFrame()->FirstChild()->ToWebLocalFrame();
+ frame_test_helpers::LoadFrame(child_frame, "subframe-hello.html");
+ EXPECT_FALSE(main_frame_client->DidPropagateDisplayNoneProperty());
+
+ WebRemoteFrame* remote_frame = frame_test_helpers::CreateRemote();
+ child_frame->Swap(remote_frame);
+ EXPECT_FALSE(main_frame_client->DidPropagateDisplayNoneProperty());
+
+ WebLocalFrame* local_frame =
+ frame_test_helpers::CreateProvisional(*remote_frame);
+ remote_frame->Swap(local_frame);
+ EXPECT_FALSE(main_frame_client->DidPropagateDisplayNoneProperty());
+ Reset();
+}
+
void WebFrameTest::SwapAndVerifyMiddleChildConsistency(
const char* const message,
WebFrame* parent,
@@ -9614,10 +9862,10 @@ TEST_F(WebFrameTest, CrossDomainAccessErrorsUseCallingWindow) {
TEST_F(WebFrameTest, ResizeInvalidatesDeviceMediaQueries) {
RegisterMockedHttpURLLoad("device_media_queries.html");
- FixedLayoutTestWebViewClient client;
+ FixedLayoutTestWebWidgetClient client;
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "device_media_queries.html",
- nullptr, &client, nullptr,
+ nullptr, nullptr, &client,
ConfigureAndroid);
auto* frame =
To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
@@ -9667,7 +9915,7 @@ class DeviceEmulationTest : public WebFrameTest {
RegisterMockedHttpURLLoad("device_emulation.html");
client_.screen_info_.device_scale_factor = 1;
web_view_helper_.InitializeAndLoad(base_url_ + "device_emulation.html",
- nullptr, &client_);
+ nullptr, nullptr, &client_);
}
void TestResize(const WebSize size, const String& expected_size) {
@@ -9691,7 +9939,7 @@ class DeviceEmulationTest : public WebFrameTest {
return callback_helper.StringValue();
}
- FixedLayoutTestWebViewClient client_;
+ FixedLayoutTestWebWidgetClient client_;
frame_test_helpers::WebViewHelper web_view_helper_;
};
@@ -11260,8 +11508,8 @@ TEST_F(WebFrameSimTest, TickmarksDocumentRelative) {
search_text, *options);
// Get the tickmarks for the original find request.
- Vector<IntRect> original_tickmarks;
- frame_view->LayoutViewport()->GetTickmarks(original_tickmarks);
+ Vector<IntRect> original_tickmarks =
+ frame_view->LayoutViewport()->GetTickmarks();
EXPECT_EQ(1u, original_tickmarks.size());
EXPECT_EQ(IntPoint(800, 2000), original_tickmarks[0].Location());
@@ -12082,10 +12330,6 @@ TEST_F(WebFrameTest, NoLoadingCompletionCallbacksInDetach) {
TestWebFrameClient::DidStopLoading();
}
- void DidFailProvisionalLoad(const WebURLError&, const WebString&) override {
- EXPECT_TRUE(false) << "The load should not have failed.";
- }
-
void DidFinishDocumentLoad() override {
// TODO(dcheng): Investigate not calling this as well during frame detach.
did_call_did_finish_document_load_ = true;
@@ -12747,13 +12991,15 @@ TEST_F(WebFrameSimTest, EnterFullscreenResetScrollAndScaleState) {
TEST_F(WebFrameTest, MediaQueriesInLocalFrameInsideRemote) {
frame_test_helpers::WebViewHelper helper;
- FixedLayoutTestWebViewClient client;
+ helper.InitializeRemote();
+
+ FixedLayoutTestWebWidgetClient client;
client.screen_info_.is_monochrome = false;
client.screen_info_.depth_per_component = 8;
- helper.InitializeRemote(nullptr, nullptr, &client);
- WebLocalFrameImpl* local_frame =
- frame_test_helpers::CreateLocalChild(*helper.RemoteMainFrame());
+ WebLocalFrameImpl* local_frame = frame_test_helpers::CreateLocalChild(
+ *helper.RemoteMainFrame(), WebString(), WebFrameOwnerProperties(),
+ nullptr, nullptr, &client);
ASSERT_TRUE(local_frame->GetFrame());
MediaValues* media_values =
diff --git a/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc b/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
index 12f681b3c84..6a61243bfaf 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_hit_test_result.cc
@@ -37,8 +37,8 @@
namespace blink {
-class WebHitTestResultPrivate
- : public GarbageCollectedFinalized<WebHitTestResultPrivate> {
+class WebHitTestResultPrivate final
+ : public GarbageCollected<WebHitTestResultPrivate> {
public:
WebHitTestResultPrivate(const HitTestResult&);
WebHitTestResultPrivate(const WebHitTestResultPrivate&);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_layer_test.cc b/chromium/third_party/blink/renderer/core/exported/web_layer_test.cc
index 20a44c78638..d0229445163 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_layer_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -85,7 +85,7 @@ class WebLayerListTest : public PaintTestConfigurations, public testing::Test {
}
cc::LayerTreeHost* LayerTreeHost() {
- return web_widget_client_.layer_tree_view()->layer_tree_host();
+ return web_widget_client_.layer_tree_host();
}
Element* GetElementById(const AtomicString& id) {
@@ -262,7 +262,7 @@ class WebLayerListSimTest : public PaintTestConfigurations, public SimTest {
}
cc::PropertyTrees* GetPropertyTrees() {
- return Compositor().layer_tree_view().layer_tree_host()->property_trees();
+ return Compositor().layer_tree_host().property_trees();
}
cc::TransformNode* GetTransformNode(const cc::Layer* layer) {
@@ -316,20 +316,20 @@ TEST_P(WebLayerListSimTest, LayerUpdatesDoNotInvalidateEarlierLayers) {
CompositorElementIdNamespace::kPrimary));
// Initially, neither a nor b should have a layer that should push properties.
- auto* host = Compositor().layer_tree_view().layer_tree_host();
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(b_layer));
+ cc::LayerTreeHost& host = Compositor().layer_tree_host();
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
// Modifying b should only cause the b layer to need to push properties.
b_element->setAttribute(html_names::kStyleAttr, "opacity: 0.2");
UpdateAllLifecyclePhases();
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_TRUE(host->LayersThatShouldPushProperties().count(b_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_TRUE(host.LayersThatShouldPushProperties().count(b_layer));
// After a frame, no layers should need to push properties again.
Compositor().BeginFrame();
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(b_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
}
TEST_P(WebLayerListSimTest, LayerUpdatesDoNotInvalidateLaterLayers) {
@@ -373,25 +373,25 @@ TEST_P(WebLayerListSimTest, LayerUpdatesDoNotInvalidateLaterLayers) {
CompositorElementIdNamespace::kPrimary));
// Initially, no layer should need to push properties.
- auto* host = Compositor().layer_tree_view().layer_tree_host();
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(b_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(c_layer));
+ cc::LayerTreeHost& host = Compositor().layer_tree_host();
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
// Modifying a and b (adding opacity to a and removing opacity from b) should
// not cause the c layer to push properties.
a_element->setAttribute(html_names::kStyleAttr, "opacity: 0.3");
b_element->setAttribute(html_names::kStyleAttr, "");
UpdateAllLifecyclePhases();
- EXPECT_TRUE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_TRUE(host->LayersThatShouldPushProperties().count(b_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(c_layer));
+ EXPECT_TRUE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_TRUE(host.LayersThatShouldPushProperties().count(b_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
// After a frame, no layers should need to push properties again.
Compositor().BeginFrame();
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(a_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(b_layer));
- EXPECT_FALSE(host->LayersThatShouldPushProperties().count(c_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
+ EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
}
TEST_P(WebLayerListSimTest,
@@ -411,14 +411,14 @@ TEST_P(WebLayerListSimTest,
Compositor().BeginFrame();
// Initially the host should not need to sync.
- auto* layer_tree_host = Compositor().layer_tree_view().layer_tree_host();
- EXPECT_FALSE(layer_tree_host->needs_full_tree_sync());
+ cc::LayerTreeHost& layer_tree_host = Compositor().layer_tree_host();
+ EXPECT_FALSE(layer_tree_host.needs_full_tree_sync());
int sequence_number = GetPropertyTrees()->sequence_number;
EXPECT_GT(sequence_number, 0);
// A no-op update should not cause the host to need a full tree sync.
UpdateAllLifecyclePhases();
- EXPECT_FALSE(layer_tree_host->needs_full_tree_sync());
+ EXPECT_FALSE(layer_tree_host.needs_full_tree_sync());
// It should also not cause a property tree update - the sequence number
// should not change.
EXPECT_EQ(sequence_number, GetPropertyTrees()->sequence_number);
@@ -947,7 +947,10 @@ TEST_P(WebLayerListSimTest, LayerSubtreeOverflowClipPropertyChanged) {
// both layers.
outer_element->setAttribute(html_names::kStyleAttr, "width: 200px;");
UpdateAllLifecyclePhases();
- EXPECT_TRUE(outer_element_layer->subtree_property_changed());
+ // The overflow clip does not affect |outer_element_layer|, so
+ // subtree_property_changed should be false for it. It does affect
+ // |inner_element_layer| though.
+ EXPECT_FALSE(outer_element_layer->subtree_property_changed());
EXPECT_TRUE(inner_element_layer->subtree_property_changed());
// After a frame the |subtree_property_changed| value should be reset.
diff --git a/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc b/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc
index 2f8894a541e..3b4ed476607 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
namespace blink {
@@ -23,6 +24,18 @@ WebLocalFrameClient::GetInterfaceProvider() {
}
BrowserInterfaceBrokerProxy* WebLocalFrameClient::GetBrowserInterfaceBroker() {
+ // TODO(dtapuska): We should make this interface a pure virtual so we don't
+ // have this implementation in the base class.
return &GetEmptyBrowserInterfaceBroker();
}
+
+AssociatedInterfaceProvider*
+WebLocalFrameClient::GetRemoteNavigationAssociatedInterfaces() {
+ // Embedders will typically override this, but provide a base implementation
+ // so it never returns null. That way we don't need to add a bunch of null
+ // checks for consumers of this API.
+ // TODO(dtapuska): We should make this interface a pure virtual so we don't
+ // have this implementation in the base class.
+ return AssociatedInterfaceProvider::GetEmptyAssociatedInterfaceProvider();
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_meta_element.cc b/chromium/third_party/blink/renderer/core/exported/web_meta_element.cc
index 213df2a4cbf..eb2be518d4c 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_meta_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_meta_element.cc
@@ -18,7 +18,7 @@ WebMetaElement::WebMetaElement(HTMLMetaElement* element)
: WebElement(element) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebMetaElement,
- IsHTMLMetaElement(ConstUnwrap<Node>()))
+ IsA<HTMLMetaElement>(ConstUnwrap<Node>()))
WebMetaElement& WebMetaElement::operator=(HTMLMetaElement* element) {
private_ = element;
@@ -26,7 +26,7 @@ WebMetaElement& WebMetaElement::operator=(HTMLMetaElement* element) {
}
WebMetaElement::operator HTMLMetaElement*() const {
- return ToHTMLMetaElement(private_.Get());
+ return blink::To<HTMLMetaElement>(private_.Get());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_option_element.cc b/chromium/third_party/blink/renderer/core/exported/web_option_element.cc
index 07d4fe36e28..b7ddf46148c 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_option_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_option_element.cc
@@ -52,7 +52,7 @@ WebOptionElement::WebOptionElement(HTMLOptionElement* elem)
: WebElement(elem) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebOptionElement,
- IsHTMLOptionElement(ConstUnwrap<Node>()))
+ IsA<HTMLOptionElement>(ConstUnwrap<Node>()))
WebOptionElement& WebOptionElement::operator=(HTMLOptionElement* elem) {
private_ = elem;
@@ -60,7 +60,7 @@ WebOptionElement& WebOptionElement::operator=(HTMLOptionElement* elem) {
}
WebOptionElement::operator HTMLOptionElement*() const {
- return ToHTMLOptionElement(private_.Get());
+ return blink::To<HTMLOptionElement>(private_.Get());
}
} // 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 218e04aabdd..f76cf8550e0 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
@@ -38,6 +38,7 @@
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
#include "third_party/blink/renderer/core/dom/context_features.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
@@ -66,6 +67,7 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/web_test_support.h"
namespace blink {
@@ -103,7 +105,8 @@ class PagePopupChromeClient final : public EmptyChromeClient {
return rect_in_screen;
}
- float WindowToViewportScalar(const float scalar_value) const override {
+ float WindowToViewportScalar(LocalFrame*,
+ const float scalar_value) const override {
WebFloatRect viewport_rect(0, 0, scalar_value, 0);
popup_->WidgetClient()->ConvertWindowToViewport(&viewport_rect);
return viewport_rect.width;
@@ -122,7 +125,8 @@ class PagePopupChromeClient final : public EmptyChromeClient {
#endif
}
- void ScheduleAnimation(const LocalFrameView*) override {
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) override {
if (WebTestSupport::IsRunningWebTest()) {
// In single threaded web tests, the main frame's WebWidgetClient
// (provided by WebViewTestProxy or WebWidgetTestProxy) runs the composite
@@ -148,8 +152,9 @@ class PagePopupChromeClient final : public EmptyChromeClient {
timeline->GetAnimationTimeline());
}
- WebScreenInfo GetScreenInfo() const override {
- return popup_->web_view_->Client()->GetScreenInfo();
+ WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+ // LocalFrame is ignored since there is only 1 frame in a popup.
+ return popup_->WidgetClient()->GetScreenInfo();
}
WebViewImpl* GetWebView() const override { return popup_->web_view_; }
@@ -405,11 +410,25 @@ WebInputEventResult WebPagePopupImpl::HandleKeyEvent(
const WebKeyboardEvent& event) {
if (closing_)
return WebInputEventResult::kNotHandled;
+
+ if (WebInputEvent::kRawKeyDown == event.GetType()) {
+ Element* focused_element = FocusedElement();
+ if (event.windows_key_code == VKEY_TAB && focused_element &&
+ focused_element->IsKeyboardFocusable()) {
+ // If the tab key is pressed while a keyboard focusable element is
+ // focused, we should not send a corresponding keypress event.
+ suppress_next_keypress_event_ = true;
+ }
+ }
return MainFrame().GetEventHandler().KeyEvent(event);
}
WebInputEventResult WebPagePopupImpl::HandleCharEvent(
const WebKeyboardEvent& event) {
+ if (suppress_next_keypress_event_) {
+ suppress_next_keypress_event_ = false;
+ return WebInputEventResult::kHandledSuppressed;
+ }
return HandleKeyEvent(event);
}
@@ -454,6 +473,21 @@ LocalFrame& WebPagePopupImpl::MainFrame() const {
return *To<LocalFrame>(page_->MainFrame());
}
+Element* WebPagePopupImpl::FocusedElement() const {
+ if (!page_)
+ return nullptr;
+
+ LocalFrame* frame = page_->GetFocusController().FocusedFrame();
+ if (!frame)
+ return nullptr;
+
+ Document* document = frame->GetDocument();
+ if (!document)
+ return nullptr;
+
+ return document->FocusedElement();
+}
+
bool WebPagePopupImpl::IsViewportPointInWindow(int x, int y) {
WebRect point_in_window(x, y, 0, 0);
WidgetClient()->ConvertViewportToWindow(&point_in_window);
@@ -485,6 +519,8 @@ void WebPagePopupImpl::SetFocus(bool enable) {
}
WebURL WebPagePopupImpl::GetURLForDebugTrace() {
+ if (!page_)
+ return {};
WebFrame* main_frame = web_view_->MainFrame();
if (main_frame->IsWebLocalFrame())
return main_frame->ToWebLocalFrame()->GetDocument().Url();
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 6f80f5608ec..8fea472cedb 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
@@ -44,6 +44,7 @@ class Layer;
}
namespace blink {
+class Element;
class Page;
class PagePopupChromeClient;
class PagePopupClient;
@@ -107,6 +108,11 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
private:
// WebWidget implementation.
+ // NOTE: The WebWidget may still be used after requesting the popup to be
+ // closed and destroyed. But the Page and the MainFrame are destroyed
+ // immediately. So all methods (outside of initialization) that are part
+ // of the WebWidget need to check if close has already been initiated (they
+ // can do so by checking |page_|) and not crash! https://crbug.com/906340
void SetAnimationHost(cc::AnimationHost*) override;
void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
void BeginFrame(base::TimeTicks last_frame_time,
@@ -133,6 +139,8 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
// This may only be called if page_ is non-null.
LocalFrame& MainFrame() const;
+ Element* FocusedElement() const;
+
bool IsViewportPointInWindow(int x, int y);
// PagePopup function
@@ -162,6 +170,8 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
base::TimeTicks raf_aligned_input_start_time_;
bool is_accelerated_compositing_active_ = false;
+ bool suppress_next_keypress_event_ = false;
+
friend class WebPagePopup;
friend class PagePopupChromeClient;
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 0c0f9090bdc..3ce77415aa8 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
@@ -150,13 +150,10 @@ void WebPluginContainerImpl::Paint(GraphicsContext& context,
if (!cull_rect.Intersects(FrameRect()))
return;
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- if (WantsWheelEvents()) {
- ScrollHitTestDisplayItem::Record(
- context, *GetLayoutEmbeddedContent(),
- DisplayItem::kPluginScrollHitTest, nullptr,
- GetLayoutEmbeddedContent()->FirstFragment().VisualRect());
- }
+ if (WantsWheelEvents()) {
+ ScrollHitTestDisplayItem::Record(
+ context, *GetLayoutEmbeddedContent(), DisplayItem::kPluginScrollHitTest,
+ nullptr, GetLayoutEmbeddedContent()->FirstFragment().VisualRect());
}
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && layer_) {
@@ -650,11 +647,9 @@ void WebPluginContainerImpl::SetWantsWheelEvents(bool wants_wheel_events) {
LocalFrameView* frame_view = element_->GetDocument().GetFrame()->View();
scrolling_coordinator->NotifyGeometryChanged(frame_view);
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // Scroll hit test display items depend on wheel events. The scroll
- // hit test display items paint in the background phase.
- GetLayoutEmbeddedContent()->SetBackgroundNeedsFullPaintInvalidation();
- }
+ // Scroll hit test display items depend on wheel events. The scroll
+ // hit test display items paint in the background phase.
+ GetLayoutEmbeddedContent()->SetBackgroundNeedsFullPaintInvalidation();
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
index d90c20882ca..242fd3e1d97 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
@@ -67,7 +67,7 @@ struct WebPrintParams;
struct WebPrintPresetOptions;
class CORE_EXPORT WebPluginContainerImpl final
- : public GarbageCollectedFinalized<WebPluginContainerImpl>,
+ : public GarbageCollected<WebPluginContainerImpl>,
public EmbeddedContentView,
public WebPluginContainer,
public ContextClient {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
index 66680b7bb06..fb9ebfd7d3c 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -153,11 +153,6 @@ void WebRemoteFrameImpl::Close() {
self_keep_alive_.Clear();
}
-WebRect WebRemoteFrameImpl::VisibleContentRect() const {
- NOTREACHED();
- return WebRect();
-}
-
WebView* WebRemoteFrameImpl::View() const {
if (!GetFrame()) {
return nullptr;
@@ -391,7 +386,7 @@ void WebRemoteFrameImpl::WillEnterFullscreen() {
// PrefixedForCrossProcessDescendant is necessary because:
// - The fullscreen element ready check and other checks should be bypassed.
// - |ownerElement| will need :-webkit-full-screen-ancestor style in addition
- // to :-webkit-full-screen.
+ // to :fullscreen.
//
// TODO(alexmos): currently, this assumes prefixed requests, but in the
// future, this should plumb in information about which request type
diff --git a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
index 9b2bafddd2f..c908607cb7f 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -28,7 +28,7 @@ struct WebScrollIntoViewParams;
class WindowAgentFactory;
class CORE_EXPORT WebRemoteFrameImpl final
- : public GarbageCollectedFinalized<WebRemoteFrameImpl>,
+ : public GarbageCollected<WebRemoteFrameImpl>,
public WebRemoteFrame {
public:
static WebRemoteFrameImpl* Create(WebTreeScopeType, WebRemoteFrameClient*);
@@ -44,7 +44,6 @@ class CORE_EXPORT WebRemoteFrameImpl final
// WebFrame methods:
void Close() override;
- WebRect VisibleContentRect() const override;
WebView* View() const override;
void StopLoading() override;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_render_theme.cc b/chromium/third_party/blink/renderer/core/exported/web_render_theme.cc
index 997727d3a0d..f9c5e804710 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_render_theme.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_render_theme.cc
@@ -53,4 +53,8 @@ void SetSelectionColors(unsigned active_background_color,
inactive_background_color, inactive_foreground_color);
}
+void SystemColorsChanged() {
+ LayoutTheme::GetTheme().PlatformColorsDidChange();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data.cc b/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data.cc
index e04441e2425..db51e31116a 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_searchable_form_data.cc
@@ -123,7 +123,7 @@ bool IsInDefaultState(const HTMLFormControlElement& form_element) {
if (input->type() == input_type_names::kCheckbox ||
input->type() == input_type_names::kRadio)
return input->checked() == input->FastHasAttribute(kCheckedAttr);
- } else if (auto* select = ToHTMLSelectElementOrNull(form_element)) {
+ } else if (auto* select = DynamicTo<HTMLSelectElement>(form_element)) {
return IsSelectInDefaultState(*select);
}
return true;
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 08765c9c29f..36ef39dc614 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
@@ -51,7 +51,7 @@ WebSelectElement::WebSelectElement(HTMLSelectElement* element)
: WebFormControlElement(element) {}
DEFINE_WEB_NODE_TYPE_CASTS(WebSelectElement,
- IsHTMLSelectElement(ConstUnwrap<Node>()))
+ IsA<HTMLSelectElement>(ConstUnwrap<Node>()))
WebSelectElement& WebSelectElement::operator=(HTMLSelectElement* element) {
private_ = element;
@@ -59,7 +59,7 @@ WebSelectElement& WebSelectElement::operator=(HTMLSelectElement* element) {
}
WebSelectElement::operator HTMLSelectElement*() const {
- return ToHTMLSelectElement(private_.Get());
+ return blink::To<HTMLSelectElement>(private_.Get());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc
index 4a96c866181..61697b65fa6 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
@@ -754,6 +754,26 @@ void WebSettingsImpl::SetLazyImageLoadingDistanceThresholdPx4G(
settings_->SetLazyImageLoadingDistanceThresholdPx4G(distance_px);
}
+void WebSettingsImpl::SetLazyImageFirstKFullyLoadUnknown(int num_images) {
+ settings_->SetLazyImageFirstKFullyLoadUnknown(num_images);
+}
+
+void WebSettingsImpl::SetLazyImageFirstKFullyLoadSlow2G(int num_images) {
+ settings_->SetLazyImageFirstKFullyLoadSlow2G(num_images);
+}
+
+void WebSettingsImpl::SetLazyImageFirstKFullyLoad2G(int num_images) {
+ settings_->SetLazyImageFirstKFullyLoad2G(num_images);
+}
+
+void WebSettingsImpl::SetLazyImageFirstKFullyLoad3G(int num_images) {
+ settings_->SetLazyImageFirstKFullyLoad3G(num_images);
+}
+
+void WebSettingsImpl::SetLazyImageFirstKFullyLoad4G(int num_images) {
+ settings_->SetLazyImageFirstKFullyLoad4G(num_images);
+}
+
void WebSettingsImpl::SetForceDarkModeEnabled(bool enabled) {
settings_->SetForceDarkModeEnabled(enabled);
}
@@ -763,8 +783,9 @@ void WebSettingsImpl::SetPreferredColorScheme(
settings_->SetPreferredColorScheme(color_scheme);
}
-void WebSettingsImpl::SetForcedColors(ForcedColors forced_colors) {
- settings_->SetForcedColors(forced_colors);
+void WebSettingsImpl::SetNavigationControls(
+ NavigationControls navigation_controls) {
+ settings_->SetNavigationControls(navigation_controls);
}
STATIC_ASSERT_ENUM(WebSettings::ImageAnimationPolicy::kAllowed,
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 6bde4b5336b..f902029be3b 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
@@ -215,10 +215,15 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
void SetLazyImageLoadingDistanceThresholdPx2G(int) override;
void SetLazyImageLoadingDistanceThresholdPx3G(int) override;
void SetLazyImageLoadingDistanceThresholdPx4G(int) override;
+ void SetLazyImageFirstKFullyLoadUnknown(int) override;
+ void SetLazyImageFirstKFullyLoadSlow2G(int) override;
+ void SetLazyImageFirstKFullyLoad2G(int) override;
+ void SetLazyImageFirstKFullyLoad3G(int) override;
+ void SetLazyImageFirstKFullyLoad4G(int) override;
void SetForceDarkModeEnabled(bool) override;
void SetPreferredColorScheme(PreferredColorScheme) override;
- void SetForcedColors(ForcedColors) override;
+ void SetNavigationControls(NavigationControls) override;
bool RenderVSyncNotificationEnabled() const {
return render_v_sync_notification_enabled_;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
index de484693a3d..6b313da14c6 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -46,7 +46,6 @@
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.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/events/message_event.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -215,7 +214,8 @@ void WebSharedWorkerImpl::StartWorkerContext(
std::move(web_worker_fetch_context), Vector<CSPHeaderAndType>(),
outside_settings_object->GetReferrerPolicy(),
outside_settings_object->GetSecurityOrigin(), starter_secure_context,
- outside_settings_object->GetHttpsState(), CreateWorkerClients(),
+ outside_settings_object->GetHttpsState(),
+ MakeGarbageCollected<WorkerClients>(),
std::make_unique<SharedWorkerContentSettingsProxy>(
mojo::PendingRemote<mojom::blink::WorkerContentSettingsProxy>(
std::move(content_settings_handle), 0u)),
@@ -262,13 +262,6 @@ void WebSharedWorkerImpl::StartWorkerContext(
devtools_agent_host_receiver.PassPipe());
}
-WorkerClients* WebSharedWorkerImpl::CreateWorkerClients() {
- auto* worker_clients = MakeGarbageCollected<WorkerClients>();
- CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
- *worker_clients);
- return worker_clients;
-}
-
void WebSharedWorkerImpl::TerminateWorkerContext() {
DCHECK(IsMainThread());
TerminateWorkerThread();
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 d42c2199f84..0d9bdd561d7 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,8 +37,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
-#include "third_party/blink/public/mojom/csp/content_security_policy.mojom-blink.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/csp/content_security_policy.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_shared_worker_client.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h"
@@ -96,8 +96,6 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker {
// Shuts down the worker thread. This may synchronously destroy |this|.
void TerminateWorkerThread();
- WorkerClients* CreateWorkerClients();
-
void ConnectTaskOnWorkerThread(MessagePortChannel);
Persistent<SharedWorkerReportingProxy> reporting_proxy_;
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 b286951e399..16a8951a293 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
@@ -39,6 +39,8 @@
#include "build/build_config.h"
#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
+#include "third_party/blink/public/common/plugin/plugin_action.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/public/platform/web_image.h"
#include "third_party/blink/public/platform/web_input_event.h"
@@ -59,7 +61,6 @@
#include "third_party/blink/public/web/web_media_player_action.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_plugin.h"
-#include "third_party/blink/public/web/web_plugin_action.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_scoped_user_gesture.h"
#include "third_party/blink/public/web/web_view_client.h"
@@ -95,7 +96,6 @@
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/fullscreen_controller.h"
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -133,6 +133,7 @@
#include "third_party/blink/renderer/core/page/context_menu_provider.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
@@ -199,11 +200,9 @@ static const int caretPadding = 10;
namespace blink {
-// Change the text zoom level by kTextSizeMultiplierRatio each time the user
-// zooms text in or out (ie., change by 20%). The min and max values limit
-// text zoom to half and 3x the original text size. These three values match
-// those in Apple's port in WebKit/WebKit/WebView/WebView.mm
-const double WebView::kTextSizeMultiplierRatio = 1.2;
+// Historically, these values came from Webkit in
+// WebKitLegacy/mac/WebView/WebView.mm (named MinimumZoomMultiplier and
+// MaximumZoomMultiplier there).
const double WebView::kMinTextSizeMultiplier = 0.5;
const double WebView::kMaxTextSizeMultiplier = 3.0;
@@ -276,8 +275,8 @@ WebViewImpl::WebViewImpl(WebViewClient* client,
WebViewImpl* opener)
: as_view_(client),
chrome_client_(MakeGarbageCollected<ChromeClientImpl>(this)),
- minimum_zoom_level_(ZoomFactorToZoomLevel(kMinTextSizeMultiplier)),
- maximum_zoom_level_(ZoomFactorToZoomLevel(kMaxTextSizeMultiplier)),
+ minimum_zoom_level_(PageZoomFactorToZoomLevel(kMinimumPageZoomFactor)),
+ maximum_zoom_level_(PageZoomFactorToZoomLevel(kMaximumPageZoomFactor)),
does_composite_(does_composite),
fullscreen_controller_(std::make_unique<FullscreenController>(this)) {
if (!AsView().client) {
@@ -399,7 +398,7 @@ void WebViewImpl::HandleMouseDown(LocalFrame& main_frame,
}
}
-void WebViewImpl::SetDisplayMode(WebDisplayMode mode) {
+void WebViewImpl::SetDisplayMode(blink::mojom::DisplayMode mode) {
display_mode_ = mode;
if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView())
return;
@@ -440,9 +439,10 @@ void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) {
// implementation...
}
-void WebViewImpl::HandleMouseUp(LocalFrame& main_frame,
- const WebMouseEvent& event) {
- PageWidgetEventHandler::HandleMouseUp(main_frame, event);
+WebInputEventResult WebViewImpl::HandleMouseUp(LocalFrame& main_frame,
+ const WebMouseEvent& event) {
+ WebInputEventResult result =
+ PageWidgetEventHandler::HandleMouseUp(main_frame, event);
if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
// Dispatch the contextmenu event regardless of if the click was swallowed.
@@ -450,6 +450,7 @@ void WebViewImpl::HandleMouseUp(LocalFrame& main_frame,
if (event.button == WebMouseEvent::Button::kRight)
MouseContextMenu(event);
}
+ return result;
}
WebInputEventResult WebViewImpl::HandleMouseWheel(
@@ -531,7 +532,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
case WebInputEvent::kGestureTapCancel:
case WebInputEvent::kGestureTap:
case WebInputEvent::kGestureLongPress:
- GetPage()->GetLinkHighlights().StartHighlightAnimationIfNeeded();
+ GetPage()->GetLinkHighlight().StartHighlightAnimationIfNeeded();
break;
default:
break;
@@ -563,6 +564,13 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView())
break;
+ if (event.GetType() == WebInputEvent::kGestureLongTap &&
+ !MainFrameImpl()
+ ->GetFrame()
+ ->GetEventHandler()
+ .LongTapShouldInvokeContextMenu())
+ break;
+
AsView().page->GetContextMenuController().ClearContextMenu();
{
ContextMenuAllowedScope scope;
@@ -1004,16 +1012,7 @@ Node* WebViewImpl::BestTapNode(
void WebViewImpl::EnableTapHighlightAtPoint(
const GestureEventWithHitTestResults& targeted_tap_event) {
Node* touch_node = BestTapNode(targeted_tap_event);
-
- HeapVector<Member<Node>> highlight_nodes;
- highlight_nodes.push_back(touch_node);
-
- EnableTapHighlights(highlight_nodes);
-}
-
-void WebViewImpl::EnableTapHighlights(
- HeapVector<Member<Node>>& highlight_nodes) {
- GetPage()->GetLinkHighlights().SetTapHighlights(highlight_nodes);
+ GetPage()->GetLinkHighlight().SetTapHighlight(touch_node);
UpdateLifecycle(WebWidget::LifecycleUpdate::kAll,
WebWidget::LifecycleUpdateReason::kOther);
}
@@ -1219,24 +1218,27 @@ void WebViewImpl::Close() {
DCHECK(AllInstances().Contains(this));
AllInstances().erase(this);
+ if (does_composite_) {
+ // This must occur before WillBeDestroyed, since detaching the main frame
+ // will also destroy the WebWidgetClient and the AnimationHost.
+ // TODO(danakj): Since the AnimationHost will be destroyed anyways, there
+ // is probably no good reason to do this at all.
+ GetPage()->WillCloseAnimationHost(nullptr);
+ }
+
// Initiate shutdown for the entire frameset. This will cause a lot of
// notifications to be sent. This will detach all frames in this WebView's
// frame tree.
AsView().page->WillBeDestroyed();
- // The WebWidget should be closed in response to the main frame being detached
+ // The main frame being detached in WillBeDestroyed() will make use of this
// which happens in Page::WillBeDestroyed(). But since the RenderWidget lives
+ // |animation_host_| through its WebFrameWidget, before causing the
// forever (https://crbug.com/419087), the WebWidget is not closed elsewhere.
+ // WebWidgetClient and the AnimationHost to be destroyed. So this is nulled
// So we close it here but try to simulate the same ordering by closing it
- // after the main frame is detached but before the Page is destroyed. This
- // means the main frame's WebWidget remains valid while the main frame is
- // being detached (and in particular while its unload handlers run).
- {
- if (does_composite_)
- GetPage()->WillCloseAnimationHost(nullptr);
-
- animation_host_ = nullptr;
- }
+ // out after detaching the main frame.
+ animation_host_ = nullptr;
// TODO(bokan): Temporary debugging added to diagnose
// https://crbug.com/992315. Somehow we're synchronously calling
@@ -1451,6 +1453,10 @@ void WebViewImpl::Resize(const WebSize& new_size) {
GetBrowserControls().ShrinkViewport());
}
+WebSize WebViewImpl::GetSize() {
+ return size_;
+}
+
void WebViewImpl::DidEnterFullscreen() {
fullscreen_controller_->DidEnterFullscreen();
}
@@ -1579,6 +1585,18 @@ void WebViewImpl::RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) {
.RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now());
}
+std::unique_ptr<cc::BeginMainFrameMetrics>
+WebViewImpl::GetBeginMainFrameMetrics() {
+ if (!MainFrameImpl())
+ return nullptr;
+
+ return MainFrameImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .GetBeginMainFrameMetrics();
+}
+
void WebViewImpl::UpdateLifecycle(WebWidget::LifecycleUpdate requested_update,
WebWidget::LifecycleUpdateReason reason) {
TRACE_EVENT0("blink", "WebViewImpl::updateAllLifecyclePhases");
@@ -1772,15 +1790,11 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
// notified as input is only handled by the focused frame.
Frame* frame = FocusedCoreFrame();
if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- local_frame->GetDocument())) {
- if (local_frame->View() && local_frame->View()
- ->GetPaintTimingDetector()
- .NeedToNotifyInputOrScroll()) {
- local_frame->View()->GetPaintTimingDetector().NotifyInputEvent(
- input_event.GetType());
- }
+ if (local_frame->View() && local_frame->View()
+ ->GetPaintTimingDetector()
+ .NeedToNotifyInputOrScroll()) {
+ local_frame->View()->GetPaintTimingDetector().NotifyInputEvent(
+ input_event.GetType());
}
}
@@ -2379,7 +2393,7 @@ double WebViewImpl::SetZoomLevel(double zoom_level) {
float zoom_factor =
zoom_factor_override_
? zoom_factor_override_
- : static_cast<float>(ZoomLevelToZoomFactor(zoom_level_));
+ : static_cast<float>(PageZoomLevelToZoomFactor(zoom_level_));
if (zoom_factor_for_device_scale_factor_) {
if (compositor_device_scale_factor_override_) {
// Adjust the page's DSF so that DevicePixelRatio becomes
@@ -2398,13 +2412,6 @@ double WebViewImpl::SetZoomLevel(double zoom_level) {
return zoom_level_;
}
-void WebViewImpl::ZoomLimitsChanged(double minimum_zoom_level,
- double maximum_zoom_level) {
- minimum_zoom_level_ = minimum_zoom_level;
- maximum_zoom_level_ = maximum_zoom_level;
- AsView().client->ZoomLimitsChanged(minimum_zoom_level_, maximum_zoom_level_);
-}
-
float WebViewImpl::TextZoomFactor() {
return MainFrameImpl()->GetFrame()->TextZoomFactor();
}
@@ -2419,15 +2426,6 @@ float WebViewImpl::SetTextZoomFactor(float text_zoom_factor) {
return text_zoom_factor;
}
-double WebView::ZoomLevelToZoomFactor(double zoom_level) {
- return pow(kTextSizeMultiplierRatio, zoom_level);
-}
-
-double WebView::ZoomFactorToZoomLevel(double factor) {
- // Since factor = 1.2^level, level = log(factor) / log(1.2)
- return log(factor) / log(kTextSizeMultiplierRatio);
-}
-
float WebViewImpl::PageScaleFactor() const {
if (!GetPage())
return 1;
@@ -2605,33 +2603,7 @@ void WebViewImpl::UpdatePageDefinedViewportConstraints(
if (!GetPage()->MainFrame()->IsLocalFrame())
return;
- // When viewport is disabled (non-mobile), we always use gpu rasterization.
- // Otherwise, on platforms that do support viewport tags, we only enable it
- // when they are present. But Why? Historically this was used to gate usage of
- // gpu rasterization to a smaller set of less complex cases to avoid driver
- // bugs dealing with websites designed for desktop. The concern is that on
- // older android devices (<L according to https://crbug.com/419521#c9),
- // drivers are more likely to encounter bugs with gpu raster when encountering
- // the full possibility of desktop web content. Further, Adreno devices <=L
- // have encountered problems that look like driver bugs when enabling
- // OOP-Raster which is gpu-based. Thus likely a blacklist would be required
- // for non-viewport-specified pages in order to avoid crashes or other
- // problems on mobile devices with gpu rasterization.
- bool viewport_enabled = GetSettings()->ViewportEnabled();
-
- if (does_composite_) {
- bool gpu_rasterization_allowed = true;
- if (viewport_enabled) {
- static bool viewport_disables_gpu_raster = base::FeatureList::IsEnabled(
- features::kEnableGpuRasterizationViewportRestriction);
- if (viewport_disables_gpu_raster && !description.IsSpecifiedByAuthor())
- gpu_rasterization_allowed = false;
- }
- MainFrameImpl()->FrameWidgetImpl()->Client()->SetAllowGpuRasterization(
- gpu_rasterization_allowed);
- }
-
- if (!viewport_enabled) {
+ if (!GetSettings()->ViewportEnabled()) {
GetPageScaleConstraintsSet().ClearPageDefinedConstraints();
UpdateMainFrameLayoutSize();
return;
@@ -2717,13 +2689,13 @@ IntSize WebViewImpl::ContentsSize() const {
GetPage()->DeprecatedLocalMainFrame()->ContentLayoutObject();
if (!layout_view)
return IntSize();
- return layout_view->DocumentRect().Size();
+ return PixelSnappedIntRect(layout_view->DocumentRect()).Size();
}
WebSize WebViewImpl::ContentsPreferredMinimumSize() {
+ DCHECK(AsView().page->MainFrame()->IsLocalFrame());
+
auto* main_local_frame = DynamicTo<LocalFrame>(AsView().page->MainFrame());
- if (!main_local_frame)
- return WebSize();
Document* document = main_local_frame->GetDocument();
if (!document || !document->GetLayoutView() || !document->documentElement() ||
!document->documentElement()->GetLayoutBox())
@@ -2787,7 +2759,7 @@ void WebViewImpl::ResetScrollAndScaleState() {
GetPageScaleConstraintsSet().SetNeedsReset(true);
}
-void WebViewImpl::PerformPluginAction(const WebPluginAction& action,
+void WebViewImpl::PerformPluginAction(const PluginAction& action,
const gfx::Point& location) {
// FIXME: Location is probably in viewport coordinates
HitTestResult result =
@@ -2802,11 +2774,11 @@ void WebViewImpl::PerformPluginAction(const WebPluginAction& action,
ToLayoutEmbeddedContent(object)->Plugin();
if (plugin_view) {
switch (action.type) {
- case WebPluginAction::kRotate90Clockwise:
+ case PluginAction::kRotate90Clockwise:
plugin_view->Plugin()->RotateView(
WebPlugin::kRotationType90Clockwise);
break;
- case WebPluginAction::kRotate90Counterclockwise:
+ case PluginAction::kRotate90Counterclockwise:
plugin_view->Plugin()->RotateView(
WebPlugin::kRotationType90Counterclockwise);
break;
@@ -3246,47 +3218,6 @@ bool WebViewImpl::TabsToLinks() const {
return tabs_to_links_;
}
-void WebViewImpl::RegisterViewportLayersWithCompositor() {
- DCHECK(does_composite_);
-
- if (!GetPage()->MainFrame() || !GetPage()->MainFrame()->IsLocalFrame())
- return;
-
- Document* document = GetPage()->DeprecatedLocalMainFrame()->GetDocument();
-
- DCHECK(document);
-
- // Get the outer viewport scroll layers.
- GraphicsLayer* layout_viewport_container_layer =
- GetPage()->GlobalRootScrollerController().RootContainerLayer();
- cc::Layer* layout_viewport_container_cc_layer =
- layout_viewport_container_layer
- ? layout_viewport_container_layer->CcLayer()
- : nullptr;
-
- GraphicsLayer* layout_viewport_scroll_layer =
- GetPage()->GlobalRootScrollerController().RootScrollerLayer();
- cc::Layer* layout_viewport_scroll_cc_layer =
- layout_viewport_scroll_layer ? layout_viewport_scroll_layer->CcLayer()
- : nullptr;
-
- VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
-
- cc::ViewportLayers viewport_layers;
- viewport_layers.overscroll_elasticity_element_id =
- visual_viewport.GetCompositorOverscrollElasticityElementId();
- viewport_layers.page_scale = visual_viewport.PageScaleLayer()->CcLayer();
- viewport_layers.inner_viewport_container =
- visual_viewport.ContainerLayer()->CcLayer();
- viewport_layers.outer_viewport_container = layout_viewport_container_cc_layer;
- viewport_layers.inner_viewport_scroll =
- visual_viewport.ScrollLayer()->CcLayer();
- viewport_layers.outer_viewport_scroll = layout_viewport_scroll_cc_layer;
-
- MainFrameImpl()->FrameWidgetImpl()->Client()->RegisterViewportLayers(
- viewport_layers);
-}
-
void WebViewImpl::SetRootGraphicsLayer(GraphicsLayer* graphics_layer) {
DCHECK(MainFrameImpl());
@@ -3297,21 +3228,15 @@ void WebViewImpl::SetRootGraphicsLayer(GraphicsLayer* graphics_layer) {
visual_viewport.AttachLayerTree(graphics_layer);
if (graphics_layer) {
root_graphics_layer_ = visual_viewport.RootGraphicsLayer();
- visual_viewport_container_layer_ = visual_viewport.ContainerLayer();
root_layer_ = root_graphics_layer_->CcLayer();
UpdateDeviceEmulationTransform();
MainFrameImpl()->FrameWidgetImpl()->Client()->SetRootLayer(root_layer_);
- // We register viewport layers here since there may not be a layer
- // tree view prior to this point.
- RegisterViewportLayersWithCompositor();
} else {
root_graphics_layer_ = nullptr;
- visual_viewport_container_layer_ = nullptr;
root_layer_ = nullptr;
WebWidgetClient* widget_client =
MainFrameImpl()->FrameWidgetImpl()->Client();
widget_client->SetRootLayer(nullptr);
- widget_client->RegisterViewportLayers(cc::ViewportLayers());
// When the document in an already-attached main frame is being replaced by
// a navigation then SetRootGraphicsLayer(nullptr) will be called. Since we
@@ -3469,17 +3394,6 @@ void WebViewImpl::SendScrollEndEventFromImplSide(
}
void WebViewImpl::UpdateDeviceEmulationTransform() {
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // This method may be called before a document lifecycle update runs, and
- // attaches the |visual_viewport_container_layer_|. In that case, we will
- // save the new transform and apply it when the container layer is attached.
- // This is also null when CompositeAfterPaint is enabled.
- if (visual_viewport_container_layer_) {
- visual_viewport_container_layer_->SetTransform(
- device_emulation_transform_);
- }
- }
-
GetPage()->GetVisualViewport().SetNeedsPaintPropertyUpdate();
if (MainFrameImpl()) {
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 61d54c30b50..e3f37ec7c3d 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
@@ -35,7 +35,7 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/web_float_size.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_input_event.h"
@@ -69,6 +69,7 @@
namespace cc {
class Layer;
+struct BeginMainFrameMetrics;
class ScopedDeferMainFrameUpdate;
}
@@ -153,8 +154,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebLocalFrame* to) override;
double ZoomLevel() override;
double SetZoomLevel(double) override;
- void ZoomLimitsChanged(double minimum_zoom_level,
- double maximum_zoom_level) override;
float TextZoomFactor() override;
float SetTextZoomFactor(float) override;
float PageScaleFactor() const override;
@@ -169,10 +168,11 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebFloatSize VisualViewportSize() const override;
void ResizeVisualViewport(const WebSize&) override;
void Resize(const WebSize&) override;
+ WebSize GetSize() override;
void ResetScrollAndScaleState() override;
void SetIgnoreViewportTagScaleLimits(bool) override;
WebSize ContentsPreferredMinimumSize() override;
- void SetDisplayMode(WebDisplayMode) override;
+ void SetDisplayMode(blink::mojom::DisplayMode) override;
void AnimateDoubleTapZoom(const gfx::Point&,
const WebRect& block_bounds) override;
void ZoomToFindInPageRect(const WebRect&) override;
@@ -184,7 +184,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void EnableAutoResizeMode(const WebSize& min_size,
const WebSize& max_size) override;
void DisableAutoResizeMode() override;
- void PerformPluginAction(const WebPluginAction&, const gfx::Point&) override;
+ void PerformPluginAction(const PluginAction&, const gfx::Point&) override;
void AudioStateChanged(bool is_audio_playing) override;
WebHitTestResult HitTestResultAt(const gfx::Point&);
WebHitTestResult HitTestResultForTap(const gfx::Point&,
@@ -310,7 +310,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
LocalDOMWindow* PagePopupWindow() const;
GraphicsLayer* RootGraphicsLayer();
- void RegisterViewportLayersWithCompositor();
PaintLayerCompositor* Compositor() const;
PageScheduler* Scheduler() const override;
@@ -333,7 +332,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
Node* BestTapNode(const GestureEventWithHitTestResults& targeted_tap_event);
void EnableTapHighlightAtPoint(
const GestureEventWithHitTestResults& targeted_tap_event);
- void EnableTapHighlights(HeapVector<Member<Node>>&);
void EnableFakePageScaleAnimationForTesting(bool);
bool FakeDoubleTapAnimationPendingForTesting() const {
@@ -379,7 +377,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebSize Size();
IntSize MainFrameSize();
- WebDisplayMode DisplayMode() const { return display_mode_; }
+ blink::mojom::DisplayMode DisplayMode() const { return display_mode_; }
PageScaleConstraintsSet& GetPageScaleConstraintsSet() const;
@@ -426,6 +424,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
FRIEND_TEST_ALL_PREFIXES(WebFrameTest,
DivScrollIntoEditableTestWithDeviceScaleFactor);
FRIEND_TEST_ALL_PREFIXES(WebViewTest, SetBaseBackgroundColorBeforeMainFrame);
+ FRIEND_TEST_ALL_PREFIXES(WebViewTest, LongPressImage);
+ FRIEND_TEST_ALL_PREFIXES(WebViewTest, LongPressImageAndThenLongTapImage);
friend class frame_test_helpers::WebViewHelper;
friend class SimCompositor;
friend class WebView; // So WebView::Create can call our constructor
@@ -456,6 +456,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void EndCommitCompositorFrame();
void RecordStartOfFrameMetrics();
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time);
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics();
void UpdateLifecycle(WebWidget::LifecycleUpdate requested_update,
WebWidget::LifecycleUpdateReason reason);
void ThemeChanged();
@@ -523,7 +524,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// PageWidgetEventHandler functions
void HandleMouseLeave(LocalFrame&, const WebMouseEvent&) override;
void HandleMouseDown(LocalFrame&, const WebMouseEvent&) override;
- void HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
+ WebInputEventResult HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
WebInputEventResult HandleMouseWheel(LocalFrame&,
const WebMouseWheelEvent&) override;
WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
@@ -595,9 +596,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
// mean zoom in, negative numbers mean zoom out.
double zoom_level_ = 0.;
- double minimum_zoom_level_;
-
- double maximum_zoom_level_;
+ const double minimum_zoom_level_;
+ const double maximum_zoom_level_;
// Additional zoom factor used to scale the content by device scale factor.
double zoom_factor_for_device_scale_factor_ = 0.;
@@ -683,7 +683,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
bool should_dispatch_first_visually_non_empty_layout_ = false;
bool should_dispatch_first_layout_after_finished_parsing_ = false;
bool should_dispatch_first_layout_after_finished_loading_ = false;
- WebDisplayMode display_mode_ = kWebDisplayModeBrowser;
+ blink::mojom::DisplayMode display_mode_ = blink::mojom::DisplayMode::kBrowser;
// TODO(bokan): Temporary debugging added to diagnose
// https://crbug.com/992315. Somehow we're synchronously calling
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 cd5ebee39fc..3359f8644cf 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
@@ -47,8 +47,9 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "third_party/blink/public/platform/web_drag_data.h"
@@ -107,6 +108,7 @@
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/interactive_detector.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/context_menu_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/page_hidden_state.h"
@@ -251,12 +253,10 @@ class WebViewTest : public testing::Test {
protected:
void SetViewportSize(const WebSize& size) {
- content::LayerTreeView* layer_tree_view =
- web_view_helper_.GetLayerTreeView();
- layer_tree_view->SetViewportRectAndScale(
+ cc::LayerTreeHost* layer_tree_host = web_view_helper_.GetLayerTreeHost();
+ layer_tree_host->SetViewportRectAndScale(
gfx::Rect(static_cast<gfx::Size>(size)), /*device_scale_factor=*/1.f,
- layer_tree_view->layer_tree_host()
- ->local_surface_id_allocation_from_parent());
+ layer_tree_host->local_surface_id_allocation_from_parent());
}
std::string RegisterMockedHttpURLLoad(const std::string& file_name) {
@@ -2776,6 +2776,10 @@ TEST_F(WebViewTest, LongPressImage) {
EXPECT_EQ(WebInputEventResult::kHandledSystem,
web_view->MainFrameWidget()->HandleInputEvent(
WebCoalescedInputEvent(event)));
+ EXPECT_TRUE(
+ web_view->AsView()
+ .page->GetContextMenuController()
+ .ContextMenuNodeForFrame(web_view->MainFrameImpl()->GetFrame()));
}
TEST_F(WebViewTest, LongPressVideo) {
@@ -3841,7 +3845,7 @@ TEST_F(WebViewTest, ChangeDisplayMode) {
WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8();
EXPECT_EQ("regular-ui", content);
- web_view->SetDisplayMode(kWebDisplayModeMinimalUi);
+ web_view->SetDisplayMode(blink::mojom::DisplayMode::kMinimalUi);
content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8();
EXPECT_EQ("minimal-ui", content);
web_view_helper_.Reset();
@@ -4252,19 +4256,19 @@ TEST_F(WebViewTest, PreferredSize) {
EXPECT_EQ(100, size.width);
EXPECT_EQ(100, size.height);
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(2.0));
size = web_view->ContentsPreferredMinimumSize();
EXPECT_EQ(200, size.width);
EXPECT_EQ(200, size.height);
// Verify that both width and height are rounded (in this case up)
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(0.9995));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(0.9995));
size = web_view->ContentsPreferredMinimumSize();
EXPECT_EQ(100, size.width);
EXPECT_EQ(100, size.height);
// Verify that both width and height are rounded (in this case down)
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(1.0005));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(1.0005));
size = web_view->ContentsPreferredMinimumSize();
EXPECT_EQ(100, size.width);
EXPECT_EQ(100, size.height);
@@ -4274,7 +4278,7 @@ TEST_F(WebViewTest, PreferredSize) {
ToKURL(url), test::CoreTestDataPath("specify_size.html"));
web_view = web_view_helper_.InitializeAndLoad(url);
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(1));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(1));
size = web_view->ContentsPreferredMinimumSize();
EXPECT_EQ(2, size.width);
EXPECT_EQ(2, size.height);
@@ -4840,8 +4844,6 @@ TEST_F(WebViewTest, ForceAndResetViewport) {
web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html");
web_view_impl->MainFrameWidget()->Resize(WebSize(100, 150));
SetViewportSize(WebSize(100, 150));
- VisualViewport* visual_viewport =
- &web_view_impl->GetPage()->GetVisualViewport();
DevToolsEmulator* dev_tools_emulator = web_view_impl->GetDevToolsEmulator();
TransformationMatrix expected_matrix;
@@ -4852,7 +4854,6 @@ TEST_F(WebViewTest, ForceAndResetViewport) {
dev_tools_emulator->OverrideVisibleRect(IntSize(), &visible_rect);
EXPECT_EQ(IntRect(1, 2, 3, 4), visible_rect); // Was modified.
}
- EXPECT_TRUE(visual_viewport->ContainerLayer()->MasksToBounds());
// Override applies transform, sets visible rect, and disables
// visual viewport clipping.
@@ -4865,7 +4866,6 @@ TEST_F(WebViewTest, ForceAndResetViewport) {
dev_tools_emulator->OverrideVisibleRect(IntSize(100, 150), &visible_rect);
EXPECT_EQ(IntRect(50, 55, 50, 75), visible_rect);
}
- EXPECT_FALSE(visual_viewport->ContainerLayer()->MasksToBounds());
// Setting new override discards previous one.
matrix = dev_tools_emulator->ForceViewportForTesting(
@@ -4877,7 +4877,6 @@ TEST_F(WebViewTest, ForceAndResetViewport) {
dev_tools_emulator->OverrideVisibleRect(IntSize(100, 150), &visible_rect);
EXPECT_EQ(IntRect(5, 10, 68, 101), visible_rect); // Was modified.
}
- EXPECT_FALSE(visual_viewport->ContainerLayer()->MasksToBounds());
// Clearing override restores original transform, visible rect and
// visual viewport clipping.
@@ -4889,7 +4888,6 @@ TEST_F(WebViewTest, ForceAndResetViewport) {
dev_tools_emulator->OverrideVisibleRect(IntSize(), &visible_rect);
EXPECT_EQ(IntRect(1, 2, 3, 4), visible_rect); // Not modified.
}
- EXPECT_TRUE(visual_viewport->ContainerLayer()->MasksToBounds());
}
TEST_F(WebViewTest, ViewportOverrideIntegratesDeviceMetricsOffsetAndScale) {
@@ -5034,7 +5032,7 @@ TEST_F(WebViewTest, ResizeForPrintingViewportUnits) {
TEST_F(WebViewTest, WidthMediaQueryWithPageZoomAfterPrinting) {
WebViewImpl* web_view = web_view_helper_.Initialize();
web_view->MainFrameWidget()->Resize(WebSize(800, 600));
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(2.0));
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
@@ -5069,7 +5067,7 @@ TEST_F(WebViewTest, WidthMediaQueryWithPageZoomAfterPrinting) {
TEST_F(WebViewTest, ViewportUnitsPrintingWithPageZoom) {
WebViewImpl* web_view = web_view_helper_.Initialize();
web_view->MainFrameWidget()->Resize(WebSize(800, 600));
- web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0));
+ web_view->SetZoomLevel(PageZoomFactorToZoomLevel(2.0));
WebURL base_url = url_test_helpers::ToKURL("http://example.com/");
frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(),
@@ -5729,14 +5727,14 @@ TEST_F(WebViewTest, RootLayerAttachment) {
// Layers (including the root layer) should not be attached until the paint
// lifecycle phase.
- auto* layer_tree_view = web_view_helper_.GetLayerTreeView();
- EXPECT_FALSE(layer_tree_view->GetRootLayer());
+ cc::LayerTreeHost* layer_tree_host = web_view_helper_.GetLayerTreeHost();
+ EXPECT_FALSE(layer_tree_host->root_layer());
// Do a full lifecycle update and ensure that the root layer has been added.
web_view->MainFrameWidget()->UpdateLifecycle(
WebFrameWidget::LifecycleUpdate::kAll,
WebWidget::LifecycleUpdateReason::kTest);
- EXPECT_TRUE(layer_tree_view->GetRootLayer());
+ EXPECT_TRUE(layer_tree_host->root_layer());
}
// Verifies that we emit Blink.UseCounter.FeaturePolicy.PotentialAnimation for
@@ -5788,4 +5786,44 @@ TEST_F(WebViewTest, ForceDarkModeInvalidatesPaint) {
EXPECT_TRUE(document->GetLayoutView()->ShouldDoFullPaintInvalidation());
}
+// Regression test for https://crbug.com/1012068
+TEST_F(WebViewTest, LongPressImageAndThenLongTapImage) {
+ RegisterMockedHttpURLLoad("long_press_image.html");
+
+ WebViewImpl* web_view =
+ web_view_helper_.InitializeAndLoad(base_url_ + "long_press_image.html");
+ web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false);
+ web_view->MainFrameWidget()->Resize(WebSize(500, 300));
+ UpdateAllLifecyclePhases();
+ RunPendingTasks();
+
+ WebGestureEvent event(WebInputEvent::kGestureLongPress,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests(),
+ WebGestureDevice::kTouchscreen);
+ event.SetPositionInWidget(WebFloatPoint(10, 10));
+
+ EXPECT_EQ(WebInputEventResult::kHandledSystem,
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(event)));
+ EXPECT_TRUE(
+ web_view->AsView()
+ .page->GetContextMenuController()
+ .ContextMenuNodeForFrame(web_view->MainFrameImpl()->GetFrame()));
+
+ WebGestureEvent tap_event(WebInputEvent::kGestureLongTap,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests(),
+ WebGestureDevice::kTouchscreen);
+ tap_event.SetPositionInWidget(WebFloatPoint(10, 10));
+
+ EXPECT_EQ(WebInputEventResult::kNotHandled,
+ web_view->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(tap_event)));
+ EXPECT_TRUE(
+ web_view->AsView()
+ .page->GetContextMenuController()
+ .ContextMenuNodeForFrame(web_view->MainFrameImpl()->GetFrame()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc b/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
index 568d0fc699d..ba83bbfe77a 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/dom_feature_policy.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/feature_policy/dom_feature_policy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
index 299b6a94920..9454fdef28a 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
@@ -45,62 +45,62 @@
{
name: "ClientHintDPR",
feature_policy_name: "ch-dpr",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintDeviceMemory",
feature_policy_name: "ch-device-memory",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintDownlink",
feature_policy_name: "ch-downlink",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintECT",
feature_policy_name: "ch-ect",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintLang",
feature_policy_name: "ch-lang",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintRTT",
feature_policy_name: "ch-rtt",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintUA",
feature_policy_name: "ch-ua",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintUAArch",
feature_policy_name: "ch-ua-arch",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintUAPlatform",
feature_policy_name: "ch-ua-platform",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintUAModel",
feature_policy_name: "ch-ua-model",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintViewportWidth",
feature_policy_name: "ch-viewport-width",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "ClientHintWidth",
feature_policy_name: "ch-width",
- depends_on: ["ClientHintsFeaturePolicy"],
+ depends_on: ["FeaturePolicyForClientHints"],
},
{
name: "DocumentAccess",
@@ -305,7 +305,7 @@
},
{
name: "WebXr",
- feature_policy_name: "xr",
+ feature_policy_name: "xr-spatial-tracking",
depends_on: ["WebXR"],
},
// TODO(crbug.com/960132): WebVR added manually in feature_policy_helper.cc.
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h
index f7542617e95..c1796b27d37 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_helper.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_HELPER_H_
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
index c07c60681fa..2c0cb2e96b3 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
@@ -9,6 +9,7 @@
#include <bitset>
#include "base/metrics/histogram_macros.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h
index 50fb406e88a..96323722eef 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_PARSER_DELEGATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_PARSER_DELEGATE_H_
-#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
index d53943ef363..2748fc7fa39 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -8,6 +8,7 @@
#include <string>
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc
index 1455636e495..dbb180443b5 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/feature_policy_value_fuzzer.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
#include <memory>
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
diff --git a/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc b/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
index 53c870bd734..d6740e81f01 100644
--- a/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
+++ b/chromium/third_party/blink/renderer/core/feature_policy/layout_animations_policy.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/feature_policy/layout_animations_policy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/DEPS b/chromium/third_party/blink/renderer/core/fetch/DEPS
index 15b3d088781..5eb781fa298 100644
--- a/chromium/third_party/blink/renderer/core/fetch/DEPS
+++ b/chromium/third_party/blink/renderer/core/fetch/DEPS
@@ -5,4 +5,5 @@ include_rules = [
"+mojo/public/cpp/system/data_pipe.h",
"+mojo/public/cpp/system/simple_watcher.h",
"+net/base/request_priority.h",
+ "+services/network/public/cpp/content_security_policy.h",
]
diff --git a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
index 21c35e3a014..f1b1b1f5c08 100644
--- a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
@@ -26,7 +27,7 @@ using PublicState = BytesConsumer::PublicState;
using Result = BytesConsumer::Result;
class BlobBytesConsumerTestClient final
- : public GarbageCollectedFinalized<BlobBytesConsumerTestClient>,
+ : public GarbageCollected<BlobBytesConsumerTestClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(BlobBytesConsumerTestClient);
@@ -43,10 +44,10 @@ class BlobBytesConsumerTest : public PageTestBase {
public:
void SetUp() override { PageTestBase::SetUp(IntSize(1, 1)); }
scoped_refptr<BlobDataHandle> CreateBlob(const String& body) {
- mojom::blink::BlobPtrInfo mojo_blob;
- mojo::MakeStrongBinding(
+ mojo::PendingRemote<mojom::blink::Blob> mojo_blob;
+ mojo::MakeSelfOwnedReceiver(
std::make_unique<FakeBlob>(kBlobUUID, body, &blob_state_),
- MakeRequest(&mojo_blob));
+ mojo_blob.InitWithNewPipeAndPassReceiver());
return BlobDataHandle::Create(kBlobUUID, "", body.length(),
std::move(mojo_blob));
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.cc b/chromium/third_party/blink/renderer/core/fetch/body.cc
index fe14d5ac1d9..162d2d5dece 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body.cc
@@ -22,6 +22,7 @@
#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/disallow_new_wrapper.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -30,7 +31,7 @@ namespace blink {
namespace {
-class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>,
+class BodyConsumerBase : public GarbageCollected<BodyConsumerBase>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(BodyConsumerBase);
@@ -145,9 +146,10 @@ class BodyJsonConsumer final : public BodyConsumerBase {
v8::Local<v8::Value> parsed;
if (v8::JSON::Parse(Resolver()->GetScriptState()->GetContext(),
input_string)
- .ToLocal(&parsed))
- ResolveLater(ScriptValue(Resolver()->GetScriptState(), parsed));
- else
+ .ToLocal(&parsed)) {
+ ResolveLater(WrapPersistent(WrapDisallowNew(
+ ScriptValue(Resolver()->GetScriptState()->GetIsolate(), parsed))));
+ } else
Resolver()->Reject(trycatch.Exception());
}
DISALLOW_COPY_AND_ASSIGN(BodyJsonConsumer);
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 d4ae6f19f74..911f1524502 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
@@ -28,7 +28,7 @@
namespace blink {
class BodyStreamBuffer::LoaderClient final
- : public GarbageCollectedFinalized<LoaderClient>,
+ : public GarbageCollected<LoaderClient>,
public ContextLifecycleObserver,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(LoaderClient);
@@ -107,10 +107,20 @@ BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state,
consumer_(consumer),
signal_(signal),
made_from_readable_stream_(false) {
+ // This CHECK is temporary to track down the cause of
+ // https://crbug.com/1007162.
+ // TODO(ricea): Remove it once we know whether it crashes or not.
+ CHECK(consumer_);
+
stream_ =
ReadableStream::CreateWithCountQueueingStrategy(script_state_, this, 0);
stream_broken_ = !stream_;
+ // This CHECK is temporary to track down the cause of
+ // https://crbug.com/1007162.
+ // TODO(ricea): Remove it once we know whether it crashes or not.
+ CHECK(consumer_);
+
consumer_->SetClient(this);
if (signal) {
if (signal->aborted()) {
diff --git a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
index 4c79523854a..0157f5583d8 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
@@ -59,7 +59,8 @@ class BodyStreamBufferTest : public testing::Test {
ADD_FAILURE() << "Compilation fails";
return ScriptValue();
}
- return ScriptValue(script_state, script->Run(script_state->GetContext()));
+ return ScriptValue(script_state->GetIsolate(),
+ script->Run(script_state->GetContext()));
}
ScriptValue EvalWithPrintingError(ScriptState* script_state, const char* s) {
v8::TryCatch block(script_state->GetIsolate());
@@ -154,10 +155,10 @@ TEST_F(BodyStreamBufferTest, TeeFromHandleMadeFromStream) {
scope.GetScriptState(), underlying_source, 0);
ASSERT_TRUE(stream);
- underlying_source->Enqueue(ScriptValue(scope.GetScriptState(),
- ToV8(chunk1, scope.GetScriptState())));
- underlying_source->Enqueue(ScriptValue(scope.GetScriptState(),
- ToV8(chunk2, scope.GetScriptState())));
+ underlying_source->Enqueue(
+ ScriptValue(scope.GetIsolate(), ToV8(chunk1, scope.GetScriptState())));
+ underlying_source->Enqueue(
+ ScriptValue(scope.GetIsolate(), ToV8(chunk2, scope.GetScriptState())));
underlying_source->Close();
Checkpoint checkpoint;
@@ -547,8 +548,8 @@ TEST_F(BodyStreamBufferTest, SourceShouldBeCanceledWhenCanceled) {
BodyStreamBuffer* buffer = MakeGarbageCollected<BodyStreamBuffer>(
scope.GetScriptState(), consumer, nullptr);
- ScriptValue reason(scope.GetScriptState(),
- V8String(scope.GetScriptState()->GetIsolate(), "reason"));
+ ScriptValue reason(scope.GetIsolate(),
+ V8String(scope.GetIsolate(), "reason"));
EXPECT_FALSE(consumer->IsCancelled());
buffer->Cancel(scope.GetScriptState(), reason);
EXPECT_TRUE(consumer->IsCancelled());
diff --git a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
index 74a77e95fdc..7250ffd1b29 100644
--- a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee.cc
@@ -22,7 +22,7 @@ namespace blink {
namespace {
-class NoopClient final : public GarbageCollectedFinalized<NoopClient>,
+class NoopClient final : public GarbageCollected<NoopClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(NoopClient);
@@ -31,7 +31,7 @@ class NoopClient final : public GarbageCollectedFinalized<NoopClient>,
String DebugName() const override { return "NoopClient"; }
};
-class TeeHelper final : public GarbageCollectedFinalized<TeeHelper>,
+class TeeHelper final : public GarbageCollected<TeeHelper>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(TeeHelper);
@@ -122,7 +122,7 @@ class TeeHelper final : public GarbageCollectedFinalized<TeeHelper>,
private:
using Result = BytesConsumer::Result;
- class Chunk final : public GarbageCollectedFinalized<Chunk> {
+ class Chunk final : public GarbageCollected<Chunk> {
public:
Chunk(const char* data, wtf_size_t size) {
buffer_.ReserveInitialCapacity(size);
diff --git a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
index eee1df3e79b..c62fa37dba4 100644
--- a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_tee_test.cc
@@ -21,7 +21,7 @@ namespace {
using Result = BytesConsumer::Result;
class BytesConsumerTestClient final
- : public GarbageCollectedFinalized<BytesConsumerTestClient>,
+ : public GarbageCollected<BytesConsumerTestClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(BytesConsumerTestClient);
diff --git a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h
index 38d7ce1095a..f7a206d6cc3 100644
--- a/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h
+++ b/chromium/third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h
@@ -37,7 +37,7 @@ class BytesConsumerTestUtil {
};
class MockFetchDataLoaderClient
- : public GarbageCollectedFinalized<MockFetchDataLoaderClient>,
+ : public GarbageCollected<MockFetchDataLoaderClient>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(MockFetchDataLoaderClient);
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index 6a04dd9799a..257aca10524 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/parsed_content_disposition.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
@@ -28,8 +29,6 @@ namespace blink {
namespace {
-static const int kDefaultBufferCapacity = 32768;
-
class FetchDataLoaderAsBlobHandle final : public FetchDataLoader,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsBlobHandle);
@@ -127,12 +126,11 @@ class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader,
void Start(BytesConsumer* consumer,
FetchDataLoader::Client* client) override {
DCHECK(!client_);
- DCHECK(!IsValid());
DCHECK(!consumer_);
+ DCHECK(!buffer_);
client_ = client;
- buffer_ = ArrayBuffer::Create(kDefaultBufferCapacity, 1);
- bytes_used_ = 0;
consumer_ = consumer;
+ buffer_ = WTF::SharedBuffer::Create();
consumer_->SetClient(this);
OnStateChange();
}
@@ -148,16 +146,14 @@ class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader,
return;
if (result == BytesConsumer::Result::kOk) {
if (available > 0) {
- unsigned bytes_appended =
- Append(buffer, SafeCast<wtf_size_t>(available));
- if (!bytes_appended) {
+ bool ok = Append(buffer, SafeCast<wtf_size_t>(available));
+ if (!ok) {
auto unused = consumer_->EndRead(0);
ALLOW_UNUSED_LOCAL(unused);
consumer_->Cancel();
client_->DidFetchDataLoadFailed();
return;
}
- DCHECK_EQ(bytes_appended, available);
}
result = consumer_->EndRead(available);
}
@@ -167,10 +163,15 @@ class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader,
case BytesConsumer::Result::kShouldWait:
NOTREACHED();
return;
- case BytesConsumer::Result::kDone:
- client_->DidFetchDataLoadedArrayBuffer(
- DOMArrayBuffer::Create(PassArrayBuffer()));
+ case BytesConsumer::Result::kDone: {
+ DOMArrayBuffer* result = BuildArrayBuffer();
+ if (!result) {
+ client_->DidFetchDataLoadFailed();
+ return;
+ }
+ client_->DidFetchDataLoadedArrayBuffer(result);
return;
+ }
case BytesConsumer::Result::kError:
client_->DidFetchDataLoadFailed();
return;
@@ -187,81 +188,39 @@ class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader,
BytesConsumer::Client::Trace(visitor);
}
- bool IsValid() const { return buffer_.get(); }
-
- // Appending empty data is not allowed.
- unsigned Append(const char* data, unsigned length) {
- DCHECK_GT(length, 0u);
-
- size_t current_buffer_size = buffer_->ByteLength();
-
- DCHECK_LE(bytes_used_, current_buffer_size);
-
- size_t remaining_buffer_space = current_buffer_size - bytes_used_;
-
- if (length > remaining_buffer_space && !ExpandCapacity(length))
- return 0;
-
- memcpy(static_cast<char*>(buffer_->Data()) + bytes_used_, data, length);
- bytes_used_ += length;
-
- return length;
- }
-
- // Number of bytes currently accumulated.
- unsigned ByteLength() const { return bytes_used_; }
-
- // Returns the accumulated data as an ArrayBuffer instance. This transfers
- // ownership of the internal buffer, making this ArrayBufferBuilder invalid
- // for future use.
- scoped_refptr<ArrayBuffer> PassArrayBuffer() {
- DCHECK_LE(bytes_used_, buffer_->ByteLength());
-
- if (buffer_->ByteLength() > bytes_used_)
- buffer_ = buffer_->Slice(0, bytes_used_);
- return std::move(buffer_);
- }
-
private:
- // Expands the size of m_buffer to size + m_bytesUsed bytes. Returns true
- // iff successful. If reallocation is needed, copies only data in
- // [0, m_bytesUsed) range.
- bool ExpandCapacity(unsigned size_to_increase) {
- size_t current_buffer_size = buffer_->ByteLength();
-
- // If the size of the buffer exceeds max of unsigned, it can't be grown any
- // more.
- if (size_to_increase > std::numeric_limits<unsigned>::max() - bytes_used_)
+ // Appending empty data is not allowed. Returns false upon buffer overlow.
+ bool Append(const char* data, wtf_size_t length) {
+ DCHECK_GT(length, 0u);
+ buffer_->Append(data, length);
+ if (buffer_->size() >
+ static_cast<size_t>(std::numeric_limits<uint32_t>::max())) {
return false;
-
- unsigned new_buffer_size = bytes_used_ + size_to_increase;
-
- // Grow exponentially if possible.
- unsigned exponential_growth_new_buffer_size =
- std::numeric_limits<unsigned>::max();
- if (current_buffer_size <= std::numeric_limits<unsigned>::max() / 2) {
- exponential_growth_new_buffer_size =
- static_cast<unsigned>(current_buffer_size * 2);
}
- if (exponential_growth_new_buffer_size > new_buffer_size)
- new_buffer_size = exponential_growth_new_buffer_size;
-
- // Copy existing data in current buffer to new buffer.
- scoped_refptr<ArrayBuffer> new_buffer =
- ArrayBuffer::Create(new_buffer_size, 1);
- if (!new_buffer)
- return false;
-
- memcpy(new_buffer->Data(), buffer_->Data(), bytes_used_);
- buffer_ = new_buffer;
return true;
}
+ // Builds a DOMArrayBuffer from the received bytes.
+ DOMArrayBuffer* BuildArrayBuffer() {
+ DOMArrayBuffer* result = DOMArrayBuffer::CreateUninitializedOrNull(
+ SafeCast<unsigned>(buffer_->size()), 1);
+ // Handle a failed allocation.
+ if (!result) {
+ return result;
+ }
+ char* data = reinterpret_cast<char*>(result->Data());
+ for (const auto& span : *buffer_) {
+ memcpy(data, span.data(), span.size());
+ data += span.size();
+ }
+ buffer_->Clear();
+ return result;
+ }
+
Member<BytesConsumer> consumer_;
Member<FetchDataLoader::Client> client_;
- unsigned bytes_used_;
- scoped_refptr<ArrayBuffer> buffer_;
+ scoped_refptr<SharedBuffer> buffer_;
};
class FetchDataLoaderAsFailure final : public FetchDataLoader,
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.h b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.h
index 220ab82e1d6..9ce57b2ad2e 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.h
@@ -28,8 +28,7 @@ class FormData;
// - Client's methods can be called synchronously in Start().
// - If FetchDataLoader::Cancel() is called, Client's methods will not be
// called anymore.
-class CORE_EXPORT FetchDataLoader
- : public GarbageCollectedFinalized<FetchDataLoader> {
+class CORE_EXPORT FetchDataLoader : public GarbageCollected<FetchDataLoader> {
public:
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
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 620d420d03f..df40205c679 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
@@ -65,7 +65,7 @@ constexpr size_t kQuickBrownFoxFormDataLength =
class FetchDataLoaderTest : public testing::Test {
protected:
- struct PipingClient : public GarbageCollectedFinalized<PipingClient>,
+ struct PipingClient : public GarbageCollected<PipingClient>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(PipingClient);
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 123a2764a4d..9be817069cd 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
@@ -15,7 +15,7 @@ namespace blink {
// http://fetch.spec.whatwg.org/#terminology-headers
class CORE_EXPORT FetchHeaderList final
- : public GarbageCollectedFinalized<FetchHeaderList> {
+ : public GarbageCollected<FetchHeaderList> {
public:
struct ByteCaseInsensitiveCompare {
bool operator()(const String& lhs, const String& rhs) const {
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 21f45f6ae63..67b8ac59d9e 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -8,9 +8,11 @@
#include "base/feature_list.h"
#include "base/single_thread_task_runner.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 "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
@@ -82,7 +84,7 @@ bool HasNonEmptyLocationHeader(const FetchHeaderList* headers) {
} // namespace
class FetchManager::Loader final
- : public GarbageCollectedFinalized<FetchManager::Loader>,
+ : public GarbageCollected<FetchManager::Loader>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(Loader);
@@ -108,7 +110,7 @@ class FetchManager::Loader final
void Dispose();
void Abort();
- class SRIVerifier final : public GarbageCollectedFinalized<SRIVerifier>,
+ class SRIVerifier final : public GarbageCollected<SRIVerifier>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(SRIVerifier);
@@ -349,8 +351,8 @@ void FetchManager::Loader::DidReceiveResponse(
return;
}
}
- } else if (!SecurityOrigin::Create(response.CurrentRequestUrl())
- ->IsSameSchemeHostPort(fetch_request_data_->Origin().get())) {
+ } else if (!fetch_request_data_->Origin()->CanReadContent(
+ response.CurrentRequestUrl())) {
// Recompute the tainting if the request was redirected to a different
// origin.
switch (fetch_request_data_->Mode()) {
@@ -561,17 +563,16 @@ void FetchManager::Loader::Start(ExceptionState& exception_state) {
return;
}
- // "- |request|'s url's origin is |request|'s origin and the |CORS flag| is
- // unset"
- // "- |request|'s url's scheme is 'data' and |request|'s same-origin data
- // URL flag is set"
- // "- |request|'s url's scheme is 'about'"
+ const KURL& url = fetch_request_data_->Url();
+ // "- |request|'s url's origin is same origin with |request|'s origin,
+ // |request|'s tainted origin flag is unset, and the CORS flag is unset"
+ // Note tainted origin flag is always unset here.
// Note we don't support to call this method with |CORS flag|
- // "- |request|'s mode is |navigate|".
- if ((SecurityOrigin::Create(fetch_request_data_->Url())
- ->IsSameSchemeHostPort(fetch_request_data_->Origin().get())) ||
- (fetch_request_data_->Url().ProtocolIsData() &&
- fetch_request_data_->SameOriginDataURLFlag()) ||
+ // "- |request|'s current URL's scheme is |data|"
+ // "- |request|'s mode is |navigate| or |websocket|".
+ if (fetch_request_data_->Origin()->CanReadContent(url) ||
+ (fetch_request_data_->IsolatedWorldOrigin() &&
+ fetch_request_data_->IsolatedWorldOrigin()->CanReadContent(url)) ||
network::IsNavigationRequestMode(fetch_request_data_->Mode())) {
// "The result of performing a scheme fetch using request."
PerformSchemeFetch(exception_state);
@@ -695,11 +696,10 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
// FIXME: Support body.
ResourceRequest request(fetch_request_data_->Url());
request.SetRequestorOrigin(fetch_request_data_->Origin());
+ request.SetIsolatedWorldOrigin(fetch_request_data_->IsolatedWorldOrigin());
request.SetRequestContext(fetch_request_data_->Context());
request.SetHttpMethod(fetch_request_data_->Method());
request.SetFetchWindowId(fetch_request_data_->WindowId());
- request.SetShouldAlsoUseFactoryBoundOriginForCors(
- fetch_request_data_->ShouldAlsoUseFactoryBoundOriginForCors());
switch (fetch_request_data_->Mode()) {
case RequestMode::kSameOrigin:
@@ -783,11 +783,13 @@ void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
fetch_initiator_type_names::kFetch;
resource_loader_options.data_buffering_policy = kDoNotBufferData;
if (fetch_request_data_->URLLoaderFactory()) {
- network::mojom::blink::URLLoaderFactoryPtr factory_clone;
- fetch_request_data_->URLLoaderFactory()->Clone(MakeRequest(&factory_clone));
- resource_loader_options.url_loader_factory = base::MakeRefCounted<
- base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>(
- std::move(factory_clone));
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory> factory_clone;
+ fetch_request_data_->URLLoaderFactory()->Clone(
+ factory_clone.InitWithNewPipeAndPassReceiver());
+ resource_loader_options.url_loader_factory =
+ base::MakeRefCounted<base::RefCountedData<
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>>>(
+ std::move(factory_clone));
}
threadable_loader_ = MakeGarbageCollected<ThreadableLoader>(
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
index 24fa093cd74..71f5b96824b 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/fetch/fetch_request_data.h"
#include "net/base/request_priority.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/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -132,7 +133,7 @@ FetchRequestData* FetchRequestData::CloneExceptBody() {
request->method_ = method_;
request->header_list_ = header_list_->Clone();
request->origin_ = origin_;
- request->same_origin_data_url_flag_ = same_origin_data_url_flag_;
+ request->isolated_world_origin_ = isolated_world_origin_;
request->context_ = context_;
request->referrer_string_ = referrer_string_;
request->referrer_policy_ = referrer_policy_;
@@ -148,8 +149,6 @@ FetchRequestData* FetchRequestData::CloneExceptBody() {
request->keepalive_ = keepalive_;
request->is_history_navigation_ = is_history_navigation_;
request->window_id_ = window_id_;
- request->should_also_use_factory_bound_origin_for_cors_ =
- should_also_use_factory_bound_origin_for_cors_;
return request;
}
@@ -166,7 +165,8 @@ FetchRequestData* FetchRequestData::Clone(ScriptState* script_state,
request->buffer_ = new2;
}
if (url_loader_factory_) {
- url_loader_factory_->Clone(MakeRequest(&request->url_loader_factory_));
+ url_loader_factory_->Clone(
+ request->url_loader_factory_.BindNewPipeAndPassReceiver());
}
return request;
}
@@ -192,7 +192,6 @@ FetchRequestData::FetchRequestData()
: method_(http_names::kGET),
header_list_(MakeGarbageCollected<FetchHeaderList>()),
context_(mojom::RequestContextType::UNSPECIFIED),
- same_origin_data_url_flag_(false),
referrer_string_(Referrer::ClientReferrerString()),
referrer_policy_(network::mojom::ReferrerPolicy::kDefault),
mode_(network::mojom::RequestMode::kNoCors),
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 86b6f85feb3..f8f7ebf29fb 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
@@ -8,10 +8,12 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/unguessable_token.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.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_request.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -30,7 +32,7 @@ class SecurityOrigin;
class ScriptState;
class CORE_EXPORT FetchRequestData final
- : public GarbageCollectedFinalized<FetchRequestData> {
+ : public GarbageCollected<FetchRequestData> {
public:
enum Tainting { kBasicTainting, kCorsTainting, kOpaqueTainting };
enum class ForServiceWorkerFetchEvent { kFalse, kTrue };
@@ -51,13 +53,16 @@ class CORE_EXPORT FetchRequestData final
const KURL& Url() const { return url_; }
mojom::RequestContextType Context() const { return context_; }
void SetContext(mojom::RequestContextType context) { context_ = context; }
- scoped_refptr<const SecurityOrigin> Origin() { return origin_; }
+ scoped_refptr<const SecurityOrigin> Origin() const { return origin_; }
void SetOrigin(scoped_refptr<const SecurityOrigin> origin) {
origin_ = std::move(origin);
}
- bool SameOriginDataURLFlag() { return same_origin_data_url_flag_; }
- void SetSameOriginDataURLFlag(bool flag) {
- same_origin_data_url_flag_ = flag;
+ scoped_refptr<const SecurityOrigin> IsolatedWorldOrigin() const {
+ return isolated_world_origin_;
+ }
+ void SetIsolatedWorldOrigin(
+ scoped_refptr<const SecurityOrigin> isolated_world_origin) {
+ isolated_world_origin_ = std::move(isolated_world_origin);
}
const AtomicString& ReferrerString() const { return referrer_string_; }
void SetReferrerString(const AtomicString& s) { referrer_string_ = s; }
@@ -105,19 +110,14 @@ class CORE_EXPORT FetchRequestData final
void SetIsHistoryNavigation(bool b) { is_history_navigation_ = b; }
network::mojom::blink::URLLoaderFactory* URLLoaderFactory() const {
- return url_loader_factory_.get();
+ return url_loader_factory_.is_bound() ? url_loader_factory_.get() : nullptr;
}
- void SetURLLoaderFactory(network::mojom::blink::URLLoaderFactoryPtr factory) {
- url_loader_factory_ = std::move(factory);
+ void SetURLLoaderFactory(
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory> factory) {
+ url_loader_factory_.Bind(std::move(factory));
}
const base::UnguessableToken& WindowId() const { return window_id_; }
void SetWindowId(const base::UnguessableToken& id) { window_id_ = id; }
- bool ShouldAlsoUseFactoryBoundOriginForCors() const {
- return should_also_use_factory_bound_origin_for_cors_;
- }
- void SetShouldAlsoUseFactoryBoundOriginForCors(bool value) {
- should_also_use_factory_bound_origin_for_cors_ = value;
- }
void Trace(blink::Visitor*);
@@ -130,8 +130,8 @@ class CORE_EXPORT FetchRequestData final
// FIXME: Support m_skipServiceWorkerFlag;
mojom::RequestContextType context_;
scoped_refptr<const SecurityOrigin> origin_;
+ scoped_refptr<const SecurityOrigin> isolated_world_origin_;
// FIXME: Support m_forceOriginHeaderFlag;
- bool same_origin_data_url_flag_;
AtomicString referrer_string_;
network::mojom::ReferrerPolicy referrer_policy_;
// FIXME: Support m_authenticationFlag;
@@ -157,9 +157,8 @@ class CORE_EXPORT FetchRequestData final
// the system would otherwise decide to use to load this request.
// Currently used for blob: URLs, to ensure they can still be loaded even if
// the URL got revoked after creating the request.
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory_;
+ mojo::Remote<network::mojom::blink::URLLoaderFactory> url_loader_factory_;
base::UnguessableToken window_id_;
- bool should_also_use_factory_bound_origin_for_cors_ = false;
DISALLOW_COPY_AND_ASSIGN(FetchRequestData);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
index 983ab9ef46b..57ab1b71c1b 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_request_data_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/fetch/fetch_request_data.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/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
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 53c95f8e245..18dbcd3b0e6 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc
@@ -4,6 +4,10 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
+#include "services/network/public/cpp/content_security_policy.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -12,6 +16,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
using Type = network::mojom::FetchResponseType;
using ResponseSource = network::mojom::FetchResponseSource;
@@ -251,8 +256,43 @@ FetchResponseData::PopulateFetchAPIResponse() {
response->cache_storage_cache_name = cache_storage_cache_name_;
response->cors_exposed_header_names =
HeaderSetToVector(cors_exposed_header_names_);
+ response->side_data_blob = side_data_blob_;
for (const auto& header : HeaderList()->List())
response->headers.insert(header.first, header.second);
+
+ // Check if there's a Content-Security-Policy header and parse it if
+ // necessary.
+ if (base::FeatureList::IsEnabled(
+ network::features::kOutOfBlinkFrameAncestors)) {
+ String content_security_policy_header;
+ if (HeaderList()->Get("content-security-policy",
+ content_security_policy_header)) {
+ network::ContentSecurityPolicy policy;
+ if (policy.Parse(StringUTF8Adaptor(content_security_policy_header)
+ .AsStringPiece())) {
+ const network::mojom::CSPSourceListPtr& frame_ancestors_directive =
+ policy.content_security_policy_ptr()->frame_ancestors;
+ if (frame_ancestors_directive) {
+ // Convert network::mojom::ContentSecurityPolicy to
+ // network::mojom::blink::ContentSecurityPolicy.
+ auto blink_frame_ancestors =
+ network::mojom::blink::CSPSourceList::New();
+ for (auto& csp_source : frame_ancestors_directive->sources) {
+ blink_frame_ancestors->sources.push_back(
+ network::mojom::blink::CSPSource::New(
+ String::FromUTF8(csp_source->scheme),
+ String::FromUTF8(csp_source->host), csp_source->port,
+ String::FromUTF8(csp_source->path),
+ csp_source->is_host_wildcard, csp_source->is_port_wildcard,
+ csp_source->allow_self));
+ }
+ response->content_security_policy =
+ network::mojom::blink::ContentSecurityPolicy::New(
+ std::move(blink_frame_ancestors));
+ }
+ }
+ }
+ }
return 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 09064037542..67b11dbe6b7 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
@@ -9,9 +9,9 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_http_header_set.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
@@ -28,7 +28,7 @@ class FetchHeaderList;
class ScriptState;
class CORE_EXPORT FetchResponseData final
- : public GarbageCollectedFinalized<FetchResponseData> {
+ : public GarbageCollected<FetchResponseData> {
public:
// "A response can have an associated termination reason which is one of
// end-user abort, fatal, and timeout."
@@ -101,6 +101,9 @@ class CORE_EXPORT FetchResponseData final
void SetCorsExposedHeaderNames(const WebHTTPHeaderSet& header_names) {
cors_exposed_header_names_ = header_names;
}
+ void SetSideDataBlob(scoped_refptr<BlobDataHandle> blob) {
+ side_data_blob_ = std::move(blob);
+ }
// If the type is Default, replaces |buffer_|.
// If the type is Basic or CORS, replaces |buffer_| and
@@ -127,6 +130,7 @@ class CORE_EXPORT FetchResponseData final
base::Time response_time_;
String cache_storage_cache_name_;
WebHTTPHeaderSet cors_exposed_header_names_;
+ scoped_refptr<BlobDataHandle> side_data_blob_;
DISALLOW_COPY_AND_ASSIGN(FetchResponseData);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
index 1639df2865c..c03855ab000 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_response_data_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
index 47256d603a6..b150ffce5c5 100644
--- a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
@@ -185,8 +185,8 @@ class DataPipeAndDataBytesConsumer final : public BytesConsumer {
if (iter_->type_ == FormDataElement::kDataPipe) {
// Create the data pipe consumer if there isn't one yet.
if (!data_pipe_consumer_) {
- network::mojom::blink::DataPipeGetterPtr* data_pipe_getter =
- iter_->data_pipe_getter_->GetPtr();
+ network::mojom::blink::DataPipeGetter* data_pipe_getter =
+ iter_->data_pipe_getter_->GetDataPipeGetter();
mojo::ScopedDataPipeProducerHandle pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle pipe_consumer_handle;
@@ -196,11 +196,10 @@ class DataPipeAndDataBytesConsumer final : public BytesConsumer {
return Result::kError;
}
- (*data_pipe_getter)
- ->Read(
- std::move(pipe_producer_handle),
- WTF::Bind(&DataPipeAndDataBytesConsumer::DataPipeGetterCallback,
- WrapWeakPersistent(this)));
+ data_pipe_getter->Read(
+ std::move(pipe_producer_handle),
+ WTF::Bind(&DataPipeAndDataBytesConsumer::DataPipeGetterCallback,
+ WrapWeakPersistent(this)));
DataPipeBytesConsumer::CompletionNotifier* completion_notifier =
nullptr;
data_pipe_consumer_ = MakeGarbageCollected<DataPipeBytesConsumer>(
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 512ad7b6943..a6bd75df3c7 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
@@ -6,7 +6,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/stl_util.h"
-#include "mojo/public/cpp/bindings/binding_set.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"
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -37,12 +38,13 @@ using MockBytesConsumer = BytesConsumerTestUtil::MockBytesConsumer;
class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
public:
- SimpleDataPipeGetter(const String& str,
- network::mojom::blink::DataPipeGetterRequest request)
+ SimpleDataPipeGetter(
+ const String& str,
+ mojo::PendingReceiver<network::mojom::blink::DataPipeGetter> receiver)
: str_(str) {
- bindings_.set_connection_error_handler(WTF::BindRepeating(
- &SimpleDataPipeGetter::OnConnectionError, WTF::Unretained(this)));
- bindings_.AddBinding(this, std::move(request));
+ receivers_.set_disconnect_handler(WTF::BindRepeating(
+ &SimpleDataPipeGetter::OnMojoDisconnect, WTF::Unretained(this)));
+ receivers_.Add(this, std::move(receiver));
}
~SimpleDataPipeGetter() override = default;
@@ -54,18 +56,18 @@ class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
std::move(callback).Run(0 /* OK */, str_.length());
}
- void Clone(network::mojom::blink::DataPipeGetterRequest request) override {
- bindings_.AddBinding(this, std::move(request));
+ void Clone(mojo::PendingReceiver<network::mojom::blink::DataPipeGetter> receiver) override {
+ receivers_.Add(this, std::move(receiver));
}
- void OnConnectionError() {
- if (bindings_.empty())
+ void OnMojoDisconnect() {
+ if (receivers_.empty())
delete this;
}
private:
String str_;
- mojo::BindingSet<network::mojom::blink::DataPipeGetter> bindings_;
+ mojo::ReceiverSet<network::mojom::blink::DataPipeGetter> receivers_;
DISALLOW_COPY_AND_ASSIGN(SimpleDataPipeGetter);
};
@@ -94,18 +96,22 @@ scoped_refptr<EncodedFormData> DataPipeFormData() {
body.AppendData(WebData("foo", 3));
// Add data pipe.
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr;
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter_remote;
// Object deletes itself.
- new SimpleDataPipeGetter(String(" hello world"),
- mojo::MakeRequest(&data_pipe_getter_ptr));
- body.AppendDataPipe(data_pipe_getter_ptr.PassInterface().PassHandle());
+ new SimpleDataPipeGetter(
+ String(" hello world"),
+ data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
+ body.AppendDataPipe(data_pipe_getter_remote.PassPipe());
// Add another data pipe.
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr2;
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter_remote2;
// Object deletes itself.
- new SimpleDataPipeGetter(String(" here's another data pipe "),
- mojo::MakeRequest(&data_pipe_getter_ptr2));
- body.AppendDataPipe(data_pipe_getter_ptr2.PassInterface().PassHandle());
+ new SimpleDataPipeGetter(
+ String(" here's another data pipe "),
+ data_pipe_getter_remote2.InitWithNewPipeAndPassReceiver());
+ body.AppendDataPipe(data_pipe_getter_remote2.PassPipe());
// Add some more data.
body.AppendData(WebData("bar baz", 7));
@@ -114,7 +120,7 @@ scoped_refptr<EncodedFormData> DataPipeFormData() {
return body;
}
-class NoopClient final : public GarbageCollectedFinalized<NoopClient>,
+class NoopClient final : public GarbageCollected<NoopClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(NoopClient);
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 3e446ed3b1b..b016b5fd648 100644
--- a/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
@@ -33,10 +33,9 @@ void MeasureFetchProperties(ExecutionContext* execution_context,
}
template <typename T>
-class GlobalFetchImpl final
- : public GarbageCollectedFinalized<GlobalFetchImpl<T>>,
- public GlobalFetch::ScopedFetcher,
- public Supplement<T> {
+class GlobalFetchImpl final : public GarbageCollected<GlobalFetchImpl<T>>,
+ public GlobalFetch::ScopedFetcher,
+ public Supplement<T> {
USING_GARBAGE_COLLECTED_MIXIN(GlobalFetchImpl);
public:
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 cedf5e53319..009d060efb7 100644
--- a/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h
+++ b/chromium/third_party/blink/renderer/core/fetch/multipart_parser.h
@@ -25,7 +25,7 @@ namespace blink {
// - If MultipartParser::cancel() is called, Client's methods will not be
// called anymore.
class CORE_EXPORT MultipartParser final
- : public GarbageCollectedFinalized<MultipartParser> {
+ : public GarbageCollected<MultipartParser> {
public:
// Client recieves parsed part header fields and data.
class CORE_EXPORT Client : public GarbageCollectedMixin {
diff --git a/chromium/third_party/blink/renderer/core/fetch/multipart_parser_test.cc b/chromium/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
index ec7d5e73eaf..7d23256ffe8 100644
--- a/chromium/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/multipart_parser_test.cc
@@ -22,7 +22,7 @@ String toString(const Vector<char>& data) {
}
class MockMultipartParserClient final
- : public GarbageCollectedFinalized<MockMultipartParserClient>,
+ : public GarbageCollected<MockMultipartParserClient>,
public MultipartParser::Client {
USING_GARBAGE_COLLECTED_MIXIN(MockMultipartParserClient);
diff --git a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
index e25410fc347..1999d6956d1 100644
--- a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
@@ -29,7 +29,7 @@ using Checkpoint = StrictMock<testing::MockFunction<void(int)>>;
using Result = BytesConsumer::Result;
using PublicState = BytesConsumer::PublicState;
-class MockClient : public GarbageCollectedFinalized<MockClient>,
+class MockClient : public GarbageCollected<MockClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(MockClient);
@@ -105,8 +105,8 @@ TEST(ReadableStreamBytesConsumerTest, ErroredStream) {
MakeGarbageCollected<TestUnderlyingSource>(script_state);
auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
script_state, underlying_source, 0);
- underlying_source->Error(
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ underlying_source->Error(ScriptValue(
+ script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())));
Persistent<BytesConsumer> consumer =
MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream,
@@ -157,11 +157,11 @@ TEST(ReadableStreamBytesConsumerTest, TwoPhaseRead) {
chunk3->Data()[2] = 0x49;
chunk3->Data()[3] = 0x4a;
underlying_source->Enqueue(
- ScriptValue(script_state, ToV8(chunk1, script_state)));
+ ScriptValue(script_state->GetIsolate(), ToV8(chunk1, script_state)));
underlying_source->Enqueue(
- ScriptValue(script_state, ToV8(chunk2, script_state)));
+ ScriptValue(script_state->GetIsolate(), ToV8(chunk2, script_state)));
underlying_source->Enqueue(
- ScriptValue(script_state, ToV8(chunk3, script_state)));
+ ScriptValue(script_state->GetIsolate(), ToV8(chunk3, script_state)));
underlying_source->Close();
}
@@ -253,8 +253,8 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueUndefined) {
MakeGarbageCollected<TestUnderlyingSource>(script_state);
auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
script_state, underlying_source, 0);
- underlying_source->Enqueue(
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ underlying_source->Enqueue(ScriptValue(
+ script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())));
underlying_source->Close();
Persistent<BytesConsumer> consumer =
@@ -293,8 +293,8 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueNull) {
MakeGarbageCollected<TestUnderlyingSource>(script_state);
auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
script_state, underlying_source, 0);
- underlying_source->Enqueue(
- ScriptValue(script_state, v8::Null(script_state->GetIsolate())));
+ underlying_source->Enqueue(ScriptValue(script_state->GetIsolate(),
+ v8::Null(script_state->GetIsolate())));
underlying_source->Close();
Persistent<BytesConsumer> consumer =
@@ -334,7 +334,8 @@ TEST(ReadableStreamBytesConsumerTest, EnqueueString) {
auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
script_state, underlying_source, 0);
underlying_source->Enqueue(
- ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
+ ScriptValue(script_state->GetIsolate(),
+ V8String(script_state->GetIsolate(), "hello")));
underlying_source->Close();
Persistent<BytesConsumer> consumer =
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.cc b/chromium/third_party/blink/renderer/core/fetch/request.cc
index e96e23c4352..14923a5b693 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request.cc
@@ -4,9 +4,11 @@
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/cpp/request_mode.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/loader/request_destination.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
@@ -54,17 +56,12 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
request->SetURL(original->Url());
request->SetMethod(original->Method());
request->SetHeaderList(original->HeaderList()->Clone());
+ request->SetOrigin(ExecutionContext::From(script_state)->GetSecurityOrigin());
// FIXME: Set client.
DOMWrapperWorld& world = script_state->World();
- if (world.IsIsolatedWorld()) {
- request->SetOrigin(world.IsolatedWorldSecurityOrigin());
- request->SetShouldAlsoUseFactoryBoundOriginForCors(true);
- } else {
- request->SetOrigin(
- ExecutionContext::From(script_state)->GetSecurityOrigin());
- }
+ if (world.IsIsolatedWorld())
+ request->SetIsolatedWorldOrigin(world.IsolatedWorldSecurityOrigin());
// FIXME: Set ForceOriginHeaderFlag.
- request->SetSameOriginDataURLFlag(true);
request->SetReferrerString(original->ReferrerString());
request->SetReferrerPolicy(original->GetReferrerPolicy());
request->SetMode(original->Mode());
@@ -77,8 +74,9 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
request->SetKeepalive(original->Keepalive());
request->SetIsHistoryNavigation(original->IsHistoryNavigation());
if (original->URLLoaderFactory()) {
- network::mojom::blink::URLLoaderFactoryPtr factory_clone;
- original->URLLoaderFactory()->Clone(MakeRequest(&factory_clone));
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory> factory_clone;
+ original->URLLoaderFactory()->Clone(
+ factory_clone.InitWithNewPipeAndPassReceiver());
request->SetURLLoaderFactory(std::move(factory_clone));
}
request->SetWindowId(original->WindowId());
@@ -267,10 +265,12 @@ Request* Request::CreateRequestWithRequestOrString(
// fetching of a blob URL should work even after the URL is revoked as long
// as the request was created while the URL was still valid.
if (parsed_url.ProtocolIs("blob")) {
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory;
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory;
ExecutionContext::From(script_state)
->GetPublicURLManager()
- .Resolve(parsed_url, MakeRequest(&url_loader_factory));
+ .Resolve(parsed_url,
+ url_loader_factory.InitWithNewPipeAndPassReceiver());
request->SetURLLoaderFactory(std::move(url_loader_factory));
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.h b/chromium/third_party/blink/renderer/core/fetch/request.h
index 0f1cf26349e..d0f6f6ea4e1 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.h
+++ b/chromium/third_party/blink/renderer/core/fetch/request.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_REQUEST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_REQUEST_H_
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_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"
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_test.cc b/chromium/third_party/blink/renderer/core/fetch/request_test.cc
index 59cd95d8a33..9ec15264b7e 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "services/network/public/mojom/fetch_api.mojom-blink.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/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.cc b/chromium/third_party/blink/renderer/core/fetch/response.cc
index e7606bad8a8..55fd745134b 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/response.cc
@@ -8,7 +8,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
@@ -45,7 +45,7 @@ namespace blink {
namespace {
template <typename CorsHeadersContainer>
-FetchResponseData* FilterResponseData(
+FetchResponseData* FilterResponseDataInternal(
network::mojom::FetchResponseType response_type,
FetchResponseData* response,
CorsHeadersContainer& headers) {
@@ -80,30 +80,9 @@ FetchResponseData* FilterResponseData(
FetchResponseData* CreateFetchResponseDataFromFetchAPIResponse(
ScriptState* script_state,
mojom::blink::FetchAPIResponse& fetch_api_response) {
- FetchResponseData* response = nullptr;
- if (fetch_api_response.status_code > 0)
- response = FetchResponseData::Create();
- else
- response = FetchResponseData::CreateNetworkErrorResponse();
-
- response->SetResponseSource(fetch_api_response.response_source);
- response->SetURLList(fetch_api_response.url_list);
- response->SetStatus(fetch_api_response.status_code);
- response->SetStatusMessage(WTF::AtomicString(fetch_api_response.status_text));
- response->SetResponseTime(fetch_api_response.response_time);
- response->SetCacheStorageCacheName(
- fetch_api_response.cache_storage_cache_name);
-
- for (const auto& header : fetch_api_response.headers)
- response->HeaderList()->Append(header.key, header.value);
-
- // TODO(wanderview): This sets the mime type of the Response based on the
- // current headers. This should be correct for most cases, but technically
- // the mime type should really be frozen at the initial Response
- // construction. We should plumb the value through the cache_storage
- // persistence layer and include the explicit mime type in FetchAPIResponse
- // to set here. See: crbug.com/938939
- response->SetMimeType(response->HeaderList()->ExtractMIMEType());
+ FetchResponseData* response =
+ Response::CreateUnfilteredFetchResponseDataWithoutBody(
+ script_state, fetch_api_response);
if (fetch_api_response.blob) {
response->ReplaceBodyStreamBuffer(MakeGarbageCollected<BodyStreamBuffer>(
@@ -114,8 +93,9 @@ FetchResponseData* CreateFetchResponseDataFromFetchAPIResponse(
}
// Filter the response according to |fetch_api_response|'s ResponseType.
- response = FilterResponseData(fetch_api_response.response_type, response,
- fetch_api_response.cors_exposed_header_names);
+ response =
+ FilterResponseDataInternal(fetch_api_response.response_type, response,
+ fetch_api_response.cors_exposed_header_names);
return response;
}
@@ -374,6 +354,45 @@ Response* Response::redirect(ScriptState* script_state,
return r;
}
+FetchResponseData* Response::CreateUnfilteredFetchResponseDataWithoutBody(
+ ScriptState* script_state,
+ mojom::blink::FetchAPIResponse& fetch_api_response) {
+ FetchResponseData* response = nullptr;
+ if (fetch_api_response.status_code > 0)
+ response = FetchResponseData::Create();
+ else
+ response = FetchResponseData::CreateNetworkErrorResponse();
+
+ response->SetResponseSource(fetch_api_response.response_source);
+ response->SetURLList(fetch_api_response.url_list);
+ response->SetStatus(fetch_api_response.status_code);
+ response->SetStatusMessage(WTF::AtomicString(fetch_api_response.status_text));
+ response->SetResponseTime(fetch_api_response.response_time);
+ response->SetCacheStorageCacheName(
+ fetch_api_response.cache_storage_cache_name);
+ response->SetSideDataBlob(fetch_api_response.side_data_blob);
+
+ for (const auto& header : fetch_api_response.headers)
+ response->HeaderList()->Append(header.key, header.value);
+
+ // TODO(wanderview): This sets the mime type of the Response based on the
+ // current headers. This should be correct for most cases, but technically
+ // the mime type should really be frozen at the initial Response
+ // construction. We should plumb the value through the cache_storage
+ // persistence layer and include the explicit mime type in FetchAPIResponse
+ // to set here. See: crbug.com/938939
+ response->SetMimeType(response->HeaderList()->ExtractMIMEType());
+
+ return response;
+}
+
+FetchResponseData* Response::FilterResponseData(
+ network::mojom::FetchResponseType response_type,
+ FetchResponseData* response,
+ WTF::Vector<WTF::String>& headers) {
+ return FilterResponseDataInternal(response_type, response, headers);
+}
+
String Response::type() const {
// "The type attribute's getter must return response's type."
switch (response_->GetType()) {
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.h b/chromium/third_party/blink/renderer/core/fetch/response.h
index b9c824b08d0..3d389ec1749 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.h
+++ b/chromium/third_party/blink/renderer/core/fetch/response.h
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_RESPONSE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_RESPONSE_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -54,6 +55,15 @@ class CORE_EXPORT Response final : public Body {
uint16_t status,
ExceptionState&);
+ static FetchResponseData* CreateUnfilteredFetchResponseDataWithoutBody(
+ ScriptState*,
+ mojom::blink::FetchAPIResponse&);
+
+ static FetchResponseData* FilterResponseData(
+ network::mojom::FetchResponseType response_type,
+ FetchResponseData* response,
+ WTF::Vector<WTF::String>& headers);
+
explicit Response(ExecutionContext*);
Response(ExecutionContext*, FetchResponseData*);
Response(ExecutionContext*, FetchResponseData*, Headers*);
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.cc b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
index f53d7c4e365..e3701368f06 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/blob.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
@@ -40,8 +40,6 @@
#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/web_feature.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
#include "third_party/blink/renderer/core/url/dom_url.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -124,6 +122,7 @@ Blob* Blob::Create(
bool normalize_line_endings_to_native = (options->endings() == "native");
if (normalize_line_endings_to_native)
UseCounter::Count(context, WebFeature::kFileAPINativeLineEndings);
+ UseCounter::Count(context, WebFeature::kCreateObjectBlob);
auto blob_data = std::make_unique<BlobData>();
blob_data->SetContentType(NormalizeType(options->type()));
@@ -258,6 +257,14 @@ URLRegistry& Blob::Registry() const {
return instance;
}
+bool Blob::IsMojoBlob() {
+ return true;
+}
+
+void Blob::CloneMojoBlob(mojo::PendingReceiver<mojom::blink::Blob> receiver) {
+ blob_data_handle_->CloneBlobRemote(std::move(receiver));
+}
+
mojo::PendingRemote<mojom::blink::Blob> Blob::AsMojoBlob() {
return blob_data_handle_->CloneBlobRemote();
}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.h b/chromium/third_party/blink/renderer/core/fileapi/blob.h
index f481cebc895..241ec41e72b 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/blob.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.h
@@ -118,7 +118,9 @@ class CORE_EXPORT Blob : public ScriptWrappable,
// URLRegistrable to support PublicURLs.
URLRegistry& Registry() const final;
- mojo::PendingRemote<mojom::blink::Blob> AsMojoBlob() final;
+ bool IsMojoBlob() final;
+ void CloneMojoBlob(mojo::PendingReceiver<mojom::blink::Blob>) final;
+ mojo::PendingRemote<mojom::blink::Blob> AsMojoBlob();
// ImageBitmapSource implementation
bool IsBlob() const override { return true; }
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
index 5027d138d77..a7cd502b2dc 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -283,9 +283,10 @@ void FileReaderLoader::OnReceivedData(const char* data, unsigned data_length) {
// Receiving more data than expected would indicate a bug in the
// implementation of the mojom Blob interface. However there is no guarantee
- // that the BlobPtr is actually backed by a "real" blob, so to defend against
- // compromised renderer processes we still need to carefully validate anything
- // received. So return an error if we received too much data.
+ // that the Blob is actually backed by a "real" blob, so to
+ // defend against compromised renderer processes we still need to carefully
+ // validate anything received. So return an error if we received too much
+ // data.
if (bytes_loaded_ + data_length > raw_data_.DataLength()) {
raw_data_.reset();
bytes_loaded_ = 0;
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 13b215070a4..1165b72a79f 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
@@ -46,56 +46,64 @@ namespace blink {
namespace {
-// When a blob URL is created in a unique origin the origin is serialized into
-// the URL as "null". Since that makes it impossible to parse the origin back
-// out and compare it against a context's origin (to check if a context is
+// When a blob URL is created in an opaque origin or something whose
+// SecurityOrigin::SerializesAsNull() returns true, the origin is serialized
+// into the URL as "null". Since that makes it impossible to parse the origin
+// back out and compare it against a context's origin (to check if a context is
// allowed to dereference the URL) we store a map of blob URL to SecurityOrigin
-// instance for blob URLs with unique origins.
+// instance for blob URLs with such the origins.
-class BlobOriginMap : public URLSecurityOriginMap {
+class BlobURLNullOriginMap final : public URLSecurityOriginMap {
public:
- BlobOriginMap();
- SecurityOrigin* GetOrigin(const KURL&) override;
+ BlobURLNullOriginMap();
+
+ // If the given blob URL has a "null" origin, returns SecurityOrigin that
+ // represents the "null" origin. Otherwise, returns nullptr.
+ SecurityOrigin* GetOrigin(const KURL& blob_url) override;
};
typedef HashMap<String, scoped_refptr<SecurityOrigin>> BlobURLOriginMap;
static ThreadSpecific<BlobURLOriginMap>& OriginMap() {
- // We want to create the BlobOriginMap exactly once because it is shared by
- // all the threads.
- DEFINE_THREAD_SAFE_STATIC_LOCAL(BlobOriginMap, cache, ());
- (void)cache; // BlobOriginMap's constructor does the interesting work.
+ // We want to create the BlobURLNullOriginMap exactly once because it is
+ // shared by all the threads.
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(BlobURLNullOriginMap, cache, ());
+ // BlobURLNullOriginMap's constructor does the interesting work.
+ (void)cache;
DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<BlobURLOriginMap>, map, ());
return map;
}
-static void SaveToOriginMap(SecurityOrigin* origin, const KURL& url) {
- // If the blob URL contains null origin, as in the context with unique
+static void SaveToOriginMap(SecurityOrigin* origin, const KURL& blob_url) {
+ DCHECK(blob_url.ProtocolIs("blob"));
+ DCHECK(!blob_url.HasFragmentIdentifier());
+
+ // If the blob URL contains "null" origin, as in the context with opaque
// security origin or file URL, save the mapping between url and origin so
// that the origin can be retrieved when doing security origin check.
//
// See the definition of the origin of a Blob URL in the File API spec.
- DCHECK(!url.HasFragmentIdentifier());
- if (origin && BlobURL::GetOrigin(url) == "null")
- OriginMap()->insert(url.GetString(), origin);
+ if (origin && origin->SerializesAsNull()) {
+ DCHECK_EQ(BlobURL::GetOrigin(blob_url), "null");
+ OriginMap()->insert(blob_url.GetString(), origin);
+ }
}
-static void RemoveFromOriginMap(const KURL& url) {
- if (BlobURL::GetOrigin(url) == "null")
- OriginMap()->erase(url.GetString());
+static void RemoveFromOriginMap(const KURL& blob_url) {
+ DCHECK(blob_url.ProtocolIs("blob"));
+ if (BlobURL::GetOrigin(blob_url) == "null")
+ OriginMap()->erase(blob_url.GetString());
}
-BlobOriginMap::BlobOriginMap() {
- SecurityOrigin::SetMap(this);
+BlobURLNullOriginMap::BlobURLNullOriginMap() {
+ SecurityOrigin::SetBlobURLNullOriginMap(this);
}
-SecurityOrigin* BlobOriginMap::GetOrigin(const KURL& url) {
- if (url.ProtocolIs("blob")) {
- KURL url_without_fragment = url;
- url_without_fragment.RemoveFragmentIdentifier();
- return OriginMap()->at(url_without_fragment.GetString());
- }
- return nullptr;
+SecurityOrigin* BlobURLNullOriginMap::GetOrigin(const KURL& blob_url) {
+ DCHECK(blob_url.ProtocolIs("blob"));
+ KURL blob_url_without_fragment = blob_url;
+ blob_url_without_fragment.RemoveFragmentIdentifier();
+ return OriginMap()->at(blob_url_without_fragment.GetString());
}
} // namespace
@@ -112,16 +120,19 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
DCHECK(!url.IsEmpty());
const String& url_string = url.GetString();
- mojo::PendingRemote<mojom::blink::Blob> blob = registrable->AsMojoBlob();
- if (blob) {
+ if (registrable->IsMojoBlob()) {
// Measure how much jank the following synchronous IPC introduces.
SCOPED_UMA_HISTOGRAM_TIMER("Storage.Blob.RegisterPublicURLTime");
if (!url_store_) {
BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
origin, url_store_.BindNewEndpointAndPassReceiver());
}
- url_store_->Register(std::move(blob), url);
+ 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);
mojo_urls_.insert(url_string);
+ registrable->CloneMojoBlob(std::move(blob_receiver));
} else {
URLRegistry* registry = &registrable->Registry();
registry->RegisterURL(origin, url, registrable);
@@ -161,7 +172,8 @@ void PublicURLManager::Revoke(const KURL& url) {
void PublicURLManager::Resolve(
const KURL& url,
- network::mojom::blink::URLLoaderFactoryRequest factory_request) {
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>
+ factory_receiver) {
if (is_stopped_)
return;
@@ -171,7 +183,7 @@ void PublicURLManager::Resolve(
GetExecutionContext()->GetSecurityOrigin(),
url_store_.BindNewEndpointAndPassReceiver());
}
- url_store_->ResolveAsURLLoaderFactory(url, std::move(factory_request));
+ url_store_->ResolveAsURLLoaderFactory(url, std::move(factory_receiver));
}
void PublicURLManager::Resolve(
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
index c70d2aafeb9..ed87d4567b7 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager.h
@@ -27,7 +27,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_PUBLIC_URL_MANAGER_H_
#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
@@ -44,7 +45,7 @@ class URLRegistry;
class URLRegistrable;
class CORE_EXPORT PublicURLManager final
- : public GarbageCollectedFinalized<PublicURLManager>,
+ : public GarbageCollected<PublicURLManager>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(PublicURLManager);
@@ -59,7 +60,8 @@ class CORE_EXPORT PublicURLManager final
void Revoke(const KURL&);
// When mojo Blob URLs are enabled this resolves the provided URL to a
// factory capable of creating loaders for the specific URL.
- void Resolve(const KURL&, network::mojom::blink::URLLoaderFactoryRequest);
+ void Resolve(const KURL&,
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>);
// When mojo Blob URLs are enabled this resolves the provided URL to a mojom
// BlobURLToken. This token can be used by the browser process to securely
// lookup what blob a URL used to refer to, even after the URL is revoked.
diff --git a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
index fcc95bbd09b..4947144e33c 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
@@ -32,12 +32,13 @@ class TestURLRegistrable : public URLRegistrable {
URLRegistry& Registry() const override { return *registry_; }
- mojo::PendingRemote<mojom::blink::Blob> AsMojoBlob() override {
+ bool IsMojoBlob() override { return bool{blob_}; }
+
+ void CloneMojoBlob(
+ mojo::PendingReceiver<mojom::blink::Blob> receiver) override {
if (!blob_)
- return mojo::NullRemote();
- mojo::PendingRemote<mojom::blink::Blob> result;
- blob_->Clone(result.InitWithNewPipeAndPassReceiver());
- return result;
+ return;
+ blob_->Clone(std::move(receiver));
}
private:
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
index 89db9a2298c..415f7238e09 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
@@ -33,6 +33,14 @@ void URLFileAPI::revokeObjectURL(ScriptState* script_state,
ExecutionContext* execution_context = ExecutionContext::From(script_state);
DCHECK(execution_context);
+ revokeObjectURL(execution_context, url_string);
+}
+
+// static
+void URLFileAPI::revokeObjectURL(ExecutionContext* execution_context,
+ const String& url_string) {
+ DCHECK(execution_context);
+
KURL url(NullURL(), url_string);
execution_context->RemoveURLFromMemoryCache(url);
execution_context->GetPublicURLManager().Revoke(url);
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h
index c9b47ad1dda..692a648fbf0 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.h
@@ -11,6 +11,7 @@
namespace blink {
class ExceptionState;
+class ExecutionContext;
class ScriptState;
class Blob;
@@ -20,6 +21,7 @@ class URLFileAPI {
public:
static String createObjectURL(ScriptState*, Blob*, ExceptionState&);
static void revokeObjectURL(ScriptState*, const String&);
+ static void revokeObjectURL(ExecutionContext*, const String&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_registry.h b/chromium/third_party/blink/renderer/core/fileapi/url_registry.h
index e89d0054c5e..2d68c29aa3e 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/url_registry.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_registry.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_URL_REGISTRY_H_
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -46,9 +46,8 @@ class CORE_EXPORT URLRegistrable {
public:
virtual ~URLRegistrable() = default;
virtual URLRegistry& Registry() const = 0;
- virtual mojo::PendingRemote<mojom::blink::Blob> AsMojoBlob() {
- return mojo::NullRemote();
- }
+ virtual bool IsMojoBlob() { return false; }
+ virtual void CloneMojoBlob(mojo::PendingReceiver<mojom::blink::Blob>) {}
};
class CORE_EXPORT URLRegistry {
diff --git a/chromium/third_party/blink/renderer/core/frame/BUILD.gn b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
index 28961259cf6..882c5152c32 100644
--- a/chromium/third_party/blink/renderer/core/frame/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
@@ -57,6 +57,7 @@ blink_core_sources("frame") {
"feature_policy_violation_report_body.h",
"find_in_page.cc",
"find_in_page.h",
+ "fragment_directive.h",
"frame.cc",
"frame.h",
"frame_client.h",
@@ -87,8 +88,6 @@ blink_core_sources("frame") {
"intervention_report_body.h",
"layout_subtree_root_list.cc",
"layout_subtree_root_list.h",
- "link_highlights.cc",
- "link_highlights.h",
"local_dom_window.cc",
"local_dom_window.h",
"local_frame.cc",
diff --git a/chromium/third_party/blink/renderer/core/frame/DEPS b/chromium/third_party/blink/renderer/core/frame/DEPS
new file mode 100644
index 00000000000..974ea722cb2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "local_frame_back_forward_cache_test.cc": [
+ "+base/run_loop.h",
+ ]
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc b/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
index 89700963d1b..da2592a0738 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
@@ -38,6 +38,11 @@ namespace features {
// the currently running stack is ad related.
const base::Feature kAsyncStackAdTagging{"AsyncStackAdTagging",
base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether the AdTracker analyzes the whole pseudo-stack or just the
+// top of the stack when detecting ads.
+const base::Feature kTopOfStackAdTagging{"TopOfStackAdTagging",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
// static
@@ -57,7 +62,9 @@ AdTracker* AdTracker::FromExecutionContext(
AdTracker::AdTracker(LocalFrame* local_root)
: local_root_(local_root),
async_stack_enabled_(
- base::FeatureList::IsEnabled(features::kAsyncStackAdTagging)) {
+ base::FeatureList::IsEnabled(features::kAsyncStackAdTagging)),
+ top_of_stack_only_(
+ base::FeatureList::IsEnabled(features::kTopOfStackAdTagging)) {
local_root_->GetProbeSink()->AddAdTracker(this);
}
@@ -88,6 +95,9 @@ ExecutionContext* AdTracker::GetCurrentExecutionContext() {
void AdTracker::WillExecuteScript(ExecutionContext* execution_context,
const String& script_url) {
+ if (top_of_stack_only_)
+ return;
+
bool is_ad = script_url.IsEmpty()
? false
: IsKnownAdScript(execution_context, script_url);
@@ -97,6 +107,9 @@ void AdTracker::WillExecuteScript(ExecutionContext* execution_context,
}
void AdTracker::DidExecuteScript() {
+ if (top_of_stack_only_)
+ return;
+
if (stack_frame_is_ad_.back()) {
DCHECK_LT(0u, num_ads_in_stack_);
num_ads_in_stack_ -= 1;
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 2543296c398..562d4330aae 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -28,11 +28,12 @@ class ExecuteScript;
namespace features {
CORE_EXPORT extern const base::Feature kAsyncStackAdTagging;
+CORE_EXPORT extern const base::Feature kTopOfStackAdTagging;
}
// Tracker for tagging resources as ads based on the call stack scripts.
// The tracker is maintained per local root.
-class CORE_EXPORT AdTracker : public GarbageCollectedFinalized<AdTracker> {
+class CORE_EXPORT AdTracker : public GarbageCollected<AdTracker> {
public:
// Finds an AdTracker for a given ExecutionContext.
static AdTracker* FromExecutionContext(ExecutionContext*);
@@ -107,6 +108,7 @@ class CORE_EXPORT AdTracker : public GarbageCollectedFinalized<AdTracker> {
uint32_t running_ad_async_tasks_ = 0;
const bool async_stack_enabled_;
+ const bool top_of_stack_only_;
DISALLOW_COPY_AND_ASSIGN(AdTracker);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc
index b5f92e2669f..4e810c814f5 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
@@ -136,6 +136,36 @@ TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource) {
EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
}
+TEST_F(AdTrackerTest, TopOfStackOnly_NoAdsOnTop) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kTopOfStackAdTagging);
+ CreateAdTracker();
+
+ String ad_script_url("https://example.com/bar.js");
+ AppendToKnownAdScripts(ad_script_url);
+
+ WillExecuteScript(ad_script_url);
+ WillExecuteScript("https://example.com/foo.js");
+ ad_tracker_->SetScriptAtTopOfStack("https://www.example.com/baz.js");
+
+ EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
+}
+
+TEST_F(AdTrackerTest, TopOfStackOnly_AdsOnTop) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kTopOfStackAdTagging);
+ CreateAdTracker();
+
+ String ad_script_url("https://example.com/bar.js");
+ AppendToKnownAdScripts(ad_script_url);
+
+ WillExecuteScript(ad_script_url);
+ WillExecuteScript("https://example.com/foo.js");
+ ad_tracker_->SetScriptAtTopOfStack(ad_script_url);
+
+ EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
+}
+
// Tests that if neither script in the stack is an ad,
// AnyExecutingScriptsTaggedAsAdResource should return false.
TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource_False) {
diff --git a/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc b/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
index ebd1284c806..c21448d1216 100644
--- a/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc
@@ -167,11 +167,9 @@ class BrowserControlsSimTest : public SimTest {
WebView().GetSettings()->SetMainFrameResizesAreOrientationChanges(true);
WebView().GetSettings()->SetShrinksViewportContentToFit(true);
WebView().SetDefaultPageScaleLimits(0.25f, 5);
- Compositor()
- .layer_tree_view()
- .layer_tree_host()
- ->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
- cc::BrowserControlsState::kShown, false);
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
+ cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown,
+ false);
WebView().ResizeWithBrowserControls(WebSize(412, 604), 56.f, 0, true);
}
@@ -745,7 +743,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(StateConstraints)) {
ScrollOffset(0, 100), kProgrammaticScroll);
// Setting permitted state should change the content offset to match the
// constraint.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kShown, cc::BrowserControlsState::kShown,
false);
Compositor().BeginFrame();
@@ -759,7 +757,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(StateConstraints)) {
// Setting permitted state should change content offset to match the
// constraint.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kHidden,
false);
Compositor().BeginFrame();
@@ -772,7 +770,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(StateConstraints)) {
GetDocument().View()->LayoutViewport()->GetScrollOffset());
// Setting permitted state to "both" should not change content offset.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kBoth, false);
Compositor().BeginFrame();
EXPECT_FLOAT_EQ(0, WebView().GetBrowserControls().ContentOffset());
@@ -791,19 +789,19 @@ TEST_F(BrowserControlsSimTest, MAYBE(StateConstraints)) {
// Setting permitted state to "both" should not change an in-flight offset.
VerticalScroll(20.f);
EXPECT_FLOAT_EQ(20, WebView().GetBrowserControls().ContentOffset());
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kBoth, false);
Compositor().BeginFrame();
EXPECT_FLOAT_EQ(20, WebView().GetBrowserControls().ContentOffset());
// Setting just the constraint should affect the content offset.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kBoth,
false);
Compositor().BeginFrame();
EXPECT_FLOAT_EQ(0, WebView().GetBrowserControls().ContentOffset());
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kShown, cc::BrowserControlsState::kBoth, false);
Compositor().BeginFrame();
EXPECT_FLOAT_EQ(50, WebView().GetBrowserControls().ContentOffset());
@@ -887,7 +885,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
Compositor().BeginFrame();
WebView().ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown, false);
Compositor().BeginFrame();
@@ -905,7 +903,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
// Now lock the controls in a hidden state. The layout and elements should
// resize without a WebView::resize.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kBoth,
false);
Compositor().BeginFrame();
@@ -917,7 +915,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
// Unlock the controls, the sizes should change even though the controls are
// still hidden.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kBoth, false);
Compositor().BeginFrame();
@@ -927,7 +925,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
EXPECT_EQ(300, GetDocument().GetFrame()->View()->GetLayoutSize().Height());
// Now lock the controls in a shown state.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kShown, cc::BrowserControlsState::kBoth, false);
WebView().ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
Compositor().BeginFrame();
@@ -939,7 +937,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
// Shown -> Hidden
WebView().ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kBoth,
false);
Compositor().BeginFrame();
@@ -951,14 +949,14 @@ TEST_F(BrowserControlsSimTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
// Go from Unlocked and showing, to locked and hidden but issue the resize
// before the constraint update to check for race issues.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown, false);
WebView().ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
Compositor().BeginFrame();
ASSERT_EQ(300, GetDocument().GetFrame()->View()->GetLayoutSize().Height());
WebView().ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kHidden,
false);
Compositor().BeginFrame();
@@ -1214,7 +1212,7 @@ TEST_F(BrowserControlsSimTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
<div id="spacer"></div>
)HTML");
WebView().ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown, false);
Compositor().BeginFrame();
@@ -1227,11 +1225,9 @@ TEST_F(BrowserControlsSimTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
// Lock the browser controls to hidden.
{
- Compositor()
- .layer_tree_view()
- .layer_tree_host()
- ->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
- cc::BrowserControlsState::kHidden, false);
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
+ cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kHidden,
+ false);
WebView().ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
Compositor().BeginFrame();
@@ -1250,11 +1246,9 @@ TEST_F(BrowserControlsSimTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
// Lock the browser controls to shown. This should cause the vh units to
// behave as usual by including the browser controls region in 100vh.
{
- Compositor()
- .layer_tree_view()
- .layer_tree_host()
- ->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
- cc::BrowserControlsState::kShown, false);
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
+ cc::BrowserControlsState::kShown, cc::BrowserControlsState::kShown,
+ false);
WebView().ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
Compositor().BeginFrame();
@@ -1384,12 +1378,12 @@ TEST_F(BrowserControlsSimTest, MixAnimatedAndNonAnimatedUpdateState) {
ASSERT_EQ(1.f, WebView().GetBrowserControls().ShownRatio());
// Kick off a non-animated clamp to hide the top controls.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kBoth,
false /* animated */);
// Now kick off an animated one to do the same thing.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kBoth,
true /* animated */);
@@ -1431,7 +1425,7 @@ TEST_F(BrowserControlsSimTest, HideAnimated) {
ASSERT_EQ(1.f, WebView().GetBrowserControls().ShownRatio());
// Kick off an animated hide.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kHidden,
true /* animated */);
@@ -1462,7 +1456,7 @@ TEST_F(BrowserControlsSimTest, ShowAnimated) {
)HTML");
Compositor().BeginFrame();
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kHidden,
false);
WebView().ResizeWithBrowserControls(WebSize(412, 660), 56.f, 0, false);
@@ -1472,7 +1466,7 @@ TEST_F(BrowserControlsSimTest, ShowAnimated) {
ASSERT_EQ(0.f, WebView().GetBrowserControls().ShownRatio());
// Kick off an animated show.
- Compositor().layer_tree_view().layer_tree_host()->UpdateBrowserControlsState(
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown,
true /* animated */);
@@ -1522,12 +1516,9 @@ TEST_F(BrowserControlsSimTest, ConstraintDoesntClampRatioInBlink) {
// Constrain the controls to hidden from the compositor. This should
// actually cause the controls to hide when we commit.
- Compositor()
- .layer_tree_view()
- .layer_tree_host()
- ->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
- cc::BrowserControlsState::kHidden,
- false /* animated */);
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
+ cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kHidden,
+ false /* animated */);
Compositor().BeginFrame();
EXPECT_EQ(0.f, WebView().GetBrowserControls().ShownRatio());
@@ -1547,12 +1538,9 @@ TEST_F(BrowserControlsSimTest, ConstraintDoesntClampRatioInBlink) {
// Constrain the controls to hidden from the compositor. This should
// actually cause the controls to hide when we commit.
- Compositor()
- .layer_tree_view()
- .layer_tree_host()
- ->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
- cc::BrowserControlsState::kShown,
- false /* animated */);
+ Compositor().layer_tree_host().UpdateBrowserControlsState(
+ cc::BrowserControlsState::kBoth, cc::BrowserControlsState::kShown,
+ false /* animated */);
Compositor().BeginFrame();
EXPECT_EQ(1.f, WebView().GetBrowserControls().ShownRatio());
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 a8ea9d5d95c..da7cd640ea6 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
@@ -217,8 +217,7 @@ void ContentSecurityPolicy::ApplyPolicySideEffectsToDelegate() {
Count(WebFeature::kCSPWithStrictDynamic);
}
- if (policy->AllowEval(nullptr,
- SecurityViolationReportingPolicy::kSuppressReporting,
+ if (policy->AllowEval(SecurityViolationReportingPolicy::kSuppressReporting,
kWillNotThrowException, g_empty_string)) {
Count(WebFeature::kCSPWithUnsafeEval);
}
@@ -527,27 +526,25 @@ bool ContentSecurityPolicy::IsScriptInlineType(InlineType inline_type) {
}
bool ContentSecurityPolicy::AllowEval(
- ScriptState* script_state,
SecurityViolationReportingPolicy reporting_policy,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& script_content) const {
bool is_allowed = true;
for (const auto& policy : policies_) {
- is_allowed &= policy->AllowEval(script_state, reporting_policy,
- exception_status, script_content);
+ is_allowed &=
+ policy->AllowEval(reporting_policy, exception_status, script_content);
}
return is_allowed;
}
bool ContentSecurityPolicy::AllowWasmEval(
- ScriptState* script_state,
SecurityViolationReportingPolicy reporting_policy,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& script_content) const {
bool is_allowed = true;
for (const auto& policy : policies_) {
- is_allowed &= policy->AllowWasmEval(script_state, reporting_policy,
- exception_status, script_content);
+ is_allowed &= policy->AllowWasmEval(reporting_policy, exception_status,
+ script_content);
}
return is_allowed;
}
@@ -950,8 +947,11 @@ static void GatherSecurityPolicyViolationEventData(
StripURLForUseInReport(delegate->GetSecurityOrigin(), blocked_url,
redirect_status, effective_type));
break;
- case ContentSecurityPolicy::kTrustedTypesViolation:
- init->setBlockedURI("trusted-types");
+ case ContentSecurityPolicy::kTrustedTypesSinkViolation:
+ init->setBlockedURI("trusted-types-sink");
+ break;
+ case ContentSecurityPolicy::kTrustedTypesPolicyViolation:
+ init->setBlockedURI("trusted-types-policy");
break;
}
}
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 3d4e153c2f3..600d83f222e 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
@@ -128,8 +128,8 @@ class CORE_EXPORT ContentSecurityPolicyDelegate : public GarbageCollectedMixin {
const blink::WebVector<WebContentSecurityPolicy>&) = 0;
};
-class CORE_EXPORT ContentSecurityPolicy
- : public GarbageCollectedFinalized<ContentSecurityPolicy> {
+class CORE_EXPORT ContentSecurityPolicy final
+ : public GarbageCollected<ContentSecurityPolicy> {
public:
enum ExceptionStatus { kWillThrowException, kWillNotThrowException };
@@ -137,11 +137,15 @@ class CORE_EXPORT ContentSecurityPolicy
// https://w3c.github.io/webappsec-csp/#violation-resource. By the time we
// generate a report, we're guaranteed that the value isn't 'null', so we
// don't need that state in this enum.
+ //
+ // Trusted Types violation's 'resource' values are defined in
+ // https://wicg.github.io/trusted-types/dist/spec/#csp-violation-object-hdr.
enum ViolationType {
kInlineViolation,
kEvalViolation,
kURLViolation,
- kTrustedTypesViolation
+ kTrustedTypesSinkViolation,
+ kTrustedTypesPolicyViolation
};
// The |type| argument given to inline checks, e.g.:
@@ -232,12 +236,10 @@ class CORE_EXPORT ContentSecurityPolicy
// exception in the event of a violation. When the caller will throw
// an exception, ContentSecurityPolicy does not log a violation
// message to the console because it would be redundant.
- bool AllowEval(ScriptState*,
- SecurityViolationReportingPolicy,
+ bool AllowEval(SecurityViolationReportingPolicy,
ExceptionStatus,
const String& script_content) const;
- bool AllowWasmEval(ScriptState*,
- SecurityViolationReportingPolicy,
+ bool AllowWasmEval(SecurityViolationReportingPolicy,
ExceptionStatus,
const String& script_content) const;
bool AllowPluginType(const String& type,
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 1675b87be16..450e42fce5e 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
@@ -1510,12 +1510,12 @@ TEST_F(ContentSecurityPolicyTest, EmptyCSPIsNoOp) {
EXPECT_TRUE(csp->AllowInline(
ContentSecurityPolicy::InlineType::kScriptAttribute, element, source,
String() /* nonce */, context_url, ordinal_number));
- EXPECT_TRUE(csp->AllowEval(nullptr, SecurityViolationReportingPolicy::kReport,
+ EXPECT_TRUE(csp->AllowEval(SecurityViolationReportingPolicy::kReport,
ContentSecurityPolicy::kWillNotThrowException,
g_empty_string));
- EXPECT_TRUE(csp->AllowWasmEval(
- nullptr, SecurityViolationReportingPolicy::kReport,
- ContentSecurityPolicy::kWillNotThrowException, g_empty_string));
+ EXPECT_TRUE(csp->AllowWasmEval(SecurityViolationReportingPolicy::kReport,
+ ContentSecurityPolicy::kWillNotThrowException,
+ g_empty_string));
EXPECT_TRUE(csp->AllowPluginType("application/x-type-1",
"application/x-type-1", example_url));
EXPECT_TRUE(csp->AllowPluginTypeForDocument(
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive.h b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive.h
index 4a32cdcf483..3bdaebfe99f 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive.h
@@ -14,8 +14,7 @@ namespace blink {
class ContentSecurityPolicy;
-class CORE_EXPORT CSPDirective
- : public GarbageCollectedFinalized<CSPDirective> {
+class CORE_EXPORT CSPDirective : public GarbageCollected<CSPDirective> {
public:
CSPDirective(const String& name,
const String& value,
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 a6b03bcc031..9bb9570a7e1 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
@@ -246,7 +246,6 @@ void CSPDirectiveList::ReportEvalViolation(
const ContentSecurityPolicy::DirectiveType effective_type,
const String& message,
const KURL& blocked_url,
- ScriptState* script_state,
const ContentSecurityPolicy::ExceptionStatus exception_status,
const String& content) const {
String report_message = IsReportOnly() ? "[Report Only] " + message : message;
@@ -338,7 +337,7 @@ bool CSPDirectiveList::AllowTrustedTypeAssignmentFailure(
ContentSecurityPolicy::DirectiveType::kTrustedTypes),
ContentSecurityPolicy::DirectiveType::kTrustedTypes, message,
KURL(), RedirectStatus::kFollowedRedirect,
- ContentSecurityPolicy::kTrustedTypesViolation, sample);
+ ContentSecurityPolicy::kTrustedTypesSinkViolation, sample);
return IsReportOnly();
}
@@ -462,7 +461,6 @@ bool CSPDirectiveList::CheckMediaType(MediaListDirective* directive,
bool CSPDirectiveList::CheckEvalAndReportViolation(
SourceListDirective* directive,
const String& console_message,
- ScriptState* script_state,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& content) const {
if (CheckEval(directive))
@@ -477,7 +475,7 @@ bool CSPDirectiveList::CheckEvalAndReportViolation(
ReportEvalViolation(
directive->GetText(), ContentSecurityPolicy::DirectiveType::kScriptSrc,
console_message + "\"" + directive->GetText() + "\"." + suffix + "\n",
- KURL(), script_state, exception_status,
+ KURL(), exception_status,
directive->AllowReportSample() ? content : g_empty_string);
if (!IsReportOnly()) {
policy_->ReportBlockedScriptExecutionToInspector(directive->GetText());
@@ -489,7 +487,6 @@ bool CSPDirectiveList::CheckEvalAndReportViolation(
bool CSPDirectiveList::CheckWasmEvalAndReportViolation(
SourceListDirective* directive,
const String& console_message,
- ScriptState* script_state,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& content) const {
if (CheckWasmEval(directive))
@@ -505,7 +502,7 @@ bool CSPDirectiveList::CheckWasmEvalAndReportViolation(
ReportEvalViolation(
directive->GetText(), ContentSecurityPolicy::DirectiveType::kScriptSrc,
console_message + "\"" + directive->GetText() + "\"." + suffix + "\n",
- KURL(), script_state, exception_status,
+ KURL(), exception_status,
directive->AllowReportSample() ? content : g_empty_string);
if (!IsReportOnly()) {
policy_->ReportBlockedScriptExecutionToInspector(directive->GetText());
@@ -744,7 +741,6 @@ bool CSPDirectiveList::AllowInline(
}
bool CSPDirectiveList::AllowEval(
- ScriptState* script_state,
SecurityViolationReportingPolicy reporting_policy,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& content) const {
@@ -754,7 +750,7 @@ bool CSPDirectiveList::AllowEval(
"Refused to evaluate a string as JavaScript because 'unsafe-eval' is "
"not an allowed source of script in the following Content Security "
"Policy directive: ",
- script_state, exception_status, content);
+ exception_status, content);
}
return IsReportOnly() ||
CheckEval(OperativeDirective(
@@ -762,7 +758,6 @@ bool CSPDirectiveList::AllowEval(
}
bool CSPDirectiveList::AllowWasmEval(
- ScriptState* script_state,
SecurityViolationReportingPolicy reporting_policy,
ContentSecurityPolicy::ExceptionStatus exception_status,
const String& content) const {
@@ -772,7 +767,7 @@ bool CSPDirectiveList::AllowWasmEval(
"Refused to compile or instantiate WebAssembly module because "
"'wasm-eval' is not an allowed source of script in the following "
"Content Security Policy directive: ",
- script_state, exception_status, content);
+ exception_status, content);
}
return IsReportOnly() ||
CheckWasmEval(OperativeDirective(
@@ -780,9 +775,9 @@ bool CSPDirectiveList::AllowWasmEval(
}
bool CSPDirectiveList::ShouldDisableEvalBecauseScriptSrc() const {
- return !AllowEval(
- nullptr, SecurityViolationReportingPolicy::kSuppressReporting,
- ContentSecurityPolicy::kWillNotThrowException, g_empty_string);
+ return !AllowEval(SecurityViolationReportingPolicy::kSuppressReporting,
+ ContentSecurityPolicy::kWillNotThrowException,
+ g_empty_string);
}
bool CSPDirectiveList::ShouldDisableEvalBecauseTrustedTypes() const {
@@ -877,7 +872,8 @@ bool CSPDirectiveList::AllowTrustedTypePolicy(const String& policy_name) const {
"\"%s\".",
policy_name.Utf8().c_str(),
trusted_types_.Get()->GetText().Utf8().c_str()),
- KURL(), RedirectStatus::kNoRedirect);
+ KURL(), RedirectStatus::kNoRedirect,
+ ContentSecurityPolicy::kTrustedTypesPolicyViolation, policy_name);
return DenyIfEnforcingPolicy();
}
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 07a24d7c2cc..937cd384703 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
@@ -28,8 +28,8 @@ enum class ResourceType : uint8_t;
typedef HeapVector<Member<SourceListDirective>> SourceListDirectiveVector;
-class CORE_EXPORT CSPDirectiveList
- : public GarbageCollectedFinalized<CSPDirectiveList> {
+class CORE_EXPORT CSPDirectiveList final
+ : public GarbageCollected<CSPDirectiveList> {
public:
static CSPDirectiveList* Create(ContentSecurityPolicy*,
const UChar* begin,
@@ -60,12 +60,10 @@ class CORE_EXPORT CSPDirectiveList
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy) const;
- bool AllowEval(ScriptState*,
- SecurityViolationReportingPolicy,
+ bool AllowEval(SecurityViolationReportingPolicy,
ContentSecurityPolicy::ExceptionStatus,
const String& script_content) const;
- bool AllowWasmEval(ScriptState*,
- SecurityViolationReportingPolicy,
+ bool AllowWasmEval(SecurityViolationReportingPolicy,
ContentSecurityPolicy::ExceptionStatus,
const String& script_content) const;
bool AllowPluginType(const String& type,
@@ -219,7 +217,6 @@ class CORE_EXPORT CSPDirectiveList
const ContentSecurityPolicy::DirectiveType,
const String& message,
const KURL& blocked_url,
- ScriptState*,
const ContentSecurityPolicy::ExceptionStatus,
const String& content) const;
@@ -246,12 +243,10 @@ class CORE_EXPORT CSPDirectiveList
bool CheckEvalAndReportViolation(SourceListDirective*,
const String& console_message,
- ScriptState*,
ContentSecurityPolicy::ExceptionStatus,
const String& script_content) const;
bool CheckWasmEvalAndReportViolation(SourceListDirective*,
const String& console_message,
- ScriptState*,
ContentSecurityPolicy::ExceptionStatus,
const String& script_content) const;
bool CheckInlineAndReportViolation(
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
index c9d152575b5..2cc39ba3de8 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc
@@ -10,6 +10,7 @@
#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/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/csp/source_list_directive.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/csp_source.h b/chromium/third_party/blink/renderer/core/frame/csp/csp_source.h
index 23c02f720d7..5c3bd9e9ffc 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/csp_source.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/csp_source.h
@@ -18,7 +18,7 @@ namespace blink {
class ContentSecurityPolicy;
class KURL;
-class CORE_EXPORT CSPSource : public GarbageCollectedFinalized<CSPSource> {
+class CORE_EXPORT CSPSource final : public GarbageCollected<CSPSource> {
public:
enum WildcardDisposition { kNoWildcard, kHasWildcard };
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
index 621b0a5d4da..836878e917b 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h
@@ -14,7 +14,7 @@ namespace blink {
class Document;
class NavigationInitiatorImpl
- : public GarbageCollectedFinalized<NavigationInitiatorImpl>,
+ : public GarbageCollected<NavigationInitiatorImpl>,
public mojom::blink::NavigationInitiator {
USING_PRE_FINALIZER(NavigationInitiatorImpl, Dispose);
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.cc b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
index 9e53da36640..04ceac8cd1f 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
@@ -56,6 +56,8 @@ enum Milestone {
kM78,
kM79,
kM80,
+ kM81,
+ kM82,
};
// Returns estimated milestone dates as human-readable strings.
@@ -92,6 +94,10 @@ const char* MilestoneString(Milestone milestone) {
return "M79, around December 2019";
case kM80:
return "M80, around February 2020";
+ case kM81:
+ return "M81, around March 2020";
+ case kM82:
+ return "M82, around April 2020";
}
NOTREACHED();
@@ -132,7 +138,11 @@ double MilestoneDate(Milestone milestone) {
case kM79:
return 1575950400000; // December 10, 2019.
case kM80:
- return 1580529600000; // February 1, 2020. (This is a guess!)
+ return 1580788800000; // February 4, 2020.
+ case kM81:
+ return 1584417600000; // March 17, 2020.
+ case kM82:
+ return 1588046400000; // April 28, 2020.
}
NOTREACHED();
@@ -304,13 +314,23 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"https://www.chromestatus.com/features/6107495151960064 for more "
"details."};
- case WebFeature::kApplicationCacheManifestSelectInsecureOrigin:
case WebFeature::kApplicationCacheAPIInsecureOrigin:
+ case WebFeature::kApplicationCacheManifestSelectInsecureOrigin:
return {"ApplicationCacheAPIInsecureOrigin", kM70,
- "Application Cache is restricted to secure contexts. Please "
- "consider migrating your application to HTTPS, and eventually "
- "shifting over to Service Workers. See https://goo.gl/rStTGz for "
- "more details."};
+ "Application Cache was previously restricted to secure origins "
+ "only from M70 on but now secure origin use is deprecated and "
+ "will be removed in M82. Please shift your use case over to "
+ "Service Workers."};
+
+ case WebFeature::kApplicationCacheAPISecureOrigin:
+ return {
+ "ApplicationCacheAPISecureOrigin", kM82,
+ WillBeRemoved("Application Cache API use", kM82, "6192449487634432")};
+
+ case WebFeature::kApplicationCacheManifestSelectSecureOrigin:
+ return {"ApplicationCacheAPISecureOrigin", kM82,
+ WillBeRemoved("Application Cache API manifest selection", kM82,
+ "6192449487634432")};
case WebFeature::kNotificationInsecureOrigin:
case WebFeature::kNotificationAPIInsecureOriginIframe:
@@ -338,7 +358,8 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
case WebFeature::kCSSDeepCombinator:
return {"CSSDeepCombinator", kM65,
- "/deep/ combinator is no longer supported in CSS dynamic profile."
+ "/deep/ combinator is no longer supported in CSS dynamic "
+ "profile. "
"It is now effectively no-op, acting as if it were a descendant "
"combinator. /deep/ combinator will be removed, and will be "
"invalid at M65. You should remove it. See "
@@ -472,16 +493,6 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"Creating a MediaStreamAudioSourceNode on an OfflineAudioContext",
kM71, "5258622686724096")};
- case WebFeature::kGridRowTrackPercentIndefiniteHeight:
- return {"GridRowTrackPercentIndefiniteHeight", kM70,
- String::Format("Percentages row tracks and gutters for "
- "indefinite height grid containers will be "
- "resolved against the intrinsic height instead of "
- "being treated as auto and zero respectively. "
- "This change will happen in %s. See "
- "https://www.chromestatus.com/feature/"
- "6708326821789696 for more details.",
- MilestoneString(kM70))};
case WebFeature::kTextToSpeech_SpeakDisallowedByAutoplay:
return {
"TextToSpeech_DisallowedByAutoplay", kM71,
@@ -674,6 +685,25 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
WillBeRemoved("'-webkit-appearance: textarea' for "
"elements other than textarea",
kM79, "5070237827334144")};
+ case WebFeature::kARIAHelpAttribute:
+ return {"ARIAHelpAttribute", kM80,
+ WillBeRemoved("'aria-help'", kM80, "5645050857914368")};
+
+ case WebFeature::kXRSupportsSession:
+ return {"XRSupportsSession", kM80,
+ ReplacedBy(
+ "supportsSession()",
+ "isSessionSupported() and check the resolved boolean value")};
+
+ case WebFeature::kCSSValueAppearanceButtonForBootstrapLooseSelectorRendered:
+ case WebFeature::kCSSValueAppearanceButtonForOthers2Rendered:
+ // The below DeprecationInfo::id doesn't match to WebFeature enums
+ // intentionally.
+ return {"CSSValueAppearanceButtonForOthersRendered", kM80,
+ WillBeRemoved("'-webkit-appearance: button' for "
+ "elements other than <button> and <input "
+ "type=button/color/reset/submit>",
+ kM80, "4867142128238592")};
// Features that aren't deprecated don't have a deprecation message.
default:
diff --git a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
index 2c5b38645d2..e66045abeb7 100644
--- a/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
+++ b/chromium/third_party/blink/renderer/core/frame/device_single_window_event_controller.h
@@ -16,7 +16,7 @@ class Document;
class Event;
class CORE_EXPORT DeviceSingleWindowEventController
- : public GarbageCollectedFinalized<DeviceSingleWindowEventController>,
+ : public GarbageCollected<DeviceSingleWindowEventController>,
public PlatformEventController,
public LocalDOMWindow::EventListenerObserver {
public:
diff --git a/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
index ddddffce44f..1ce3fd755a7 100644
--- a/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
@@ -25,15 +25,16 @@ String GetPx(int value) {
DisplayCutoutClientImpl::DisplayCutoutClientImpl(
LocalFrame* frame,
- mojom::blink::DisplayCutoutClientAssociatedRequest request)
- : frame_(frame), binding_(this, std::move(request)) {}
+ mojo::PendingAssociatedReceiver<mojom::blink::DisplayCutoutClient> receiver)
+ : frame_(frame), receiver_(this, std::move(receiver)) {}
-void DisplayCutoutClientImpl::BindMojoRequest(
+void DisplayCutoutClientImpl::BindMojoReceiver(
LocalFrame* frame,
- mojom::blink::DisplayCutoutClientAssociatedRequest request) {
+ mojo::PendingAssociatedReceiver<mojom::blink::DisplayCutoutClient>
+ receiver) {
if (!frame)
return;
- MakeGarbageCollected<DisplayCutoutClientImpl>(frame, std::move(request));
+ MakeGarbageCollected<DisplayCutoutClientImpl>(frame, std::move(receiver));
}
void DisplayCutoutClientImpl::SetSafeArea(
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 b547e26f590..868a6d2a286 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
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -17,15 +18,16 @@ class LocalFrame;
// Mojo interface to set CSS environment variables for display cutout.
class CORE_EXPORT DisplayCutoutClientImpl final
- : public GarbageCollectedFinalized<DisplayCutoutClientImpl>,
+ : public GarbageCollected<DisplayCutoutClientImpl>,
public mojom::blink::DisplayCutoutClient {
public:
- static void BindMojoRequest(
+ static void BindMojoReceiver(
LocalFrame*,
- mojom::blink::DisplayCutoutClientAssociatedRequest);
+ mojo::PendingAssociatedReceiver<mojom::blink::DisplayCutoutClient>);
- DisplayCutoutClientImpl(LocalFrame*,
- mojom::blink::DisplayCutoutClientAssociatedRequest);
+ DisplayCutoutClientImpl(
+ LocalFrame*,
+ mojo::PendingAssociatedReceiver<mojom::blink::DisplayCutoutClient>);
// Notify the renderer that the safe areas have changed.
void SetSafeArea(mojom::blink::DisplayCutoutSafeAreaPtr safe_area) override;
@@ -35,7 +37,7 @@ class CORE_EXPORT DisplayCutoutClientImpl final
private:
Member<LocalFrame> frame_;
- mojo::AssociatedBinding<mojom::blink::DisplayCutoutClient> binding_;
+ mojo::AssociatedReceiver<mojom::blink::DisplayCutoutClient> receiver_;
DISALLOW_COPY_AND_ASSIGN(DisplayCutoutClientImpl);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_timer.h b/chromium/third_party/blink/renderer/core/frame/dom_timer.h
index 6907a4c7c2d..dbd4d64fc76 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_timer.h
+++ b/chromium/third_party/blink/renderer/core/frame/dom_timer.h
@@ -41,7 +41,7 @@ namespace blink {
class ExecutionContext;
class ScheduledAction;
-class CORE_EXPORT DOMTimer final : public GarbageCollectedFinalized<DOMTimer>,
+class CORE_EXPORT DOMTimer final : public GarbageCollected<DOMTimer>,
public ContextLifecycleObserver,
public TimerBase,
public NameClient {
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 82753c7f5dd..ecc5d4ecaa9 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.cc
@@ -118,7 +118,7 @@ DOMWindow* DOMWindow::top() const {
void DOMWindow::postMessage(v8::Isolate* isolate,
const ScriptValue& message,
const String& target_origin,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
WindowPostMessageOptions* options = WindowPostMessageOptions::Create();
options->setTargetOrigin(target_origin);
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 76237d7c85f..a5ed8ab5f55 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.h
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.h
@@ -57,7 +57,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
return frame_;
}
- // GarbageCollectedFinalized overrides:
+ // GarbageCollected overrides:
void Trace(blink::Visitor*) override;
virtual bool IsLocalDOMWindow() const = 0;
@@ -98,7 +98,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
void postMessage(v8::Isolate*,
const ScriptValue& message,
const String& target_origin,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(v8::Isolate*,
@@ -123,8 +123,6 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
// See https://bugs.webkit.org/show_bug.cgi?id=62054
bool IsCurrentlyDisplayedInFrame() const;
- bool isSecureContext() const;
-
InputDeviceCapabilitiesConstants* GetInputDeviceCapabilities();
void PostMessageForTesting(scoped_refptr<SerializedScriptValue> message,
diff --git a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
index 91890f05a6c..3c119318f46 100644
--- a/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
+++ b/chromium/third_party/blink/renderer/core/frame/event_handler_registry.h
@@ -24,7 +24,7 @@ typedef HashCountedSet<UntracedMember<EventTarget>> EventTargetSet;
// event targets for a frame may only be registered with the
// EventHandlerRegistry of its corresponding local root.
class CORE_EXPORT EventHandlerRegistry final
- : public GarbageCollectedFinalized<EventHandlerRegistry> {
+ : public GarbageCollected<EventHandlerRegistry> {
public:
explicit EventHandlerRegistry(LocalFrame&);
virtual ~EventHandlerRegistry();
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 d1cac5d9c93..1f835bfdec9 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
@@ -26,10 +26,8 @@ class WebLocalFrameImpl;
class WebString;
struct WebFloatRect;
-class CORE_EXPORT FindInPage final
- : public GarbageCollectedFinalized<FindInPage>,
- public mojom::blink::FindInPage {
-
+class CORE_EXPORT FindInPage final : public GarbageCollected<FindInPage>,
+ public mojom::blink::FindInPage {
public:
FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry);
diff --git a/chromium/third_party/blink/renderer/core/frame/fragment_directive.h b/chromium/third_party/blink/renderer/core/frame/fragment_directive.h
new file mode 100644
index 00000000000..dd3a604fa95
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/fragment_directive.h
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAGMENT_DIRECTIVE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAGMENT_DIRECTIVE_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+// TODO(crbug/1000308): Implement the FragmentDirective type. This member
+// currently serves as a feature detectable API for the Text Fragment
+// Identifiers feature.
+class FragmentDirective : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAGMENT_DIRECTIVE_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl b/chromium/third_party/blink/renderer/core/frame/fragment_directive.idl
index 074fe3c7a10..3f91db948fd 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.idl
+++ b/chromium/third_party/blink/renderer/core/frame/fragment_directive.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://w3c.github.io/wake-lock/#the-wakelockrequestoptions-dictionary
-dictionary WakeLockRequestOptions {
- AbortSignal signal;
+// https://github.com/WICG/ScrollToTextFragment
+[RuntimeEnabled=TextFragmentIdentifiers]
+interface FragmentDirective {
};
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.cc b/chromium/third_party/blink/renderer/core/frame/frame.cc
index 82a0b0cfbe6..3a4dcf33e8e 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame.cc
@@ -261,6 +261,27 @@ void Frame::UpdateInheritedEffectiveTouchActionIfPossible() {
}
}
+void Frame::UpdateVisibleToHitTesting() {
+ bool parent_visible_to_hit_testing = true;
+ if (auto* parent = Tree().Parent())
+ parent_visible_to_hit_testing = parent->GetVisibleToHitTesting();
+
+ bool self_visible_to_hit_testing = true;
+ if (auto* local_owner = DynamicTo<HTMLFrameOwnerElement>(owner_.Get())) {
+ self_visible_to_hit_testing =
+ local_owner->GetLayoutObject()
+ ? local_owner->GetLayoutObject()->Style()->VisibleToHitTesting()
+ : true;
+ }
+
+ bool visible_to_hit_testing =
+ parent_visible_to_hit_testing && self_visible_to_hit_testing;
+ bool changed = visible_to_hit_testing_ != visible_to_hit_testing;
+ visible_to_hit_testing_ = visible_to_hit_testing;
+ if (changed)
+ DidChangeVisibleToHitTesting();
+}
+
const std::string& Frame::ToTraceValue() {
// token's ToString() is latin1.
if (!trace_value_)
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.h b/chromium/third_party/blink/renderer/core/frame/frame.h
index 1e516668836..6437f572996 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame.h
@@ -74,7 +74,7 @@ enum class UserGestureStatus { kActive, kNone };
// Frame is the base class of LocalFrame and RemoteFrame and should only contain
// functionality shared between both. In particular, any method related to
// input, layout, or painting probably belongs on LocalFrame.
-class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
+class CORE_EXPORT Frame : public GarbageCollected<Frame> {
public:
virtual ~Frame();
@@ -88,8 +88,6 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
void Detach(FrameDetachType);
void DisconnectOwnerElement();
virtual bool ShouldClose() = 0;
- virtual void DidFreeze() = 0;
- virtual void DidResume() = 0;
virtual void HookBackForwardCacheEviction() = 0;
virtual void RemoveBackForwardCacheEviction() = 0;
@@ -236,6 +234,9 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
return *window_agent_factory_;
}
+ bool GetVisibleToHitTesting() const { return visible_to_hit_testing_; }
+ void UpdateVisibleToHitTesting();
+
protected:
// |inheriting_agent_factory| should basically be set to the parent frame or
// opener's WindowAgentFactory. Pass nullptr if the frame is isolated from
@@ -262,6 +263,8 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
return lifecycle_.GetState() == FrameLifecycle::kDetached;
}
+ virtual void DidChangeVisibleToHitTesting() = 0;
+
mutable FrameTree tree_node_;
Member<Page> page_;
@@ -281,6 +284,8 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
TouchAction inherited_effective_touch_action_ = TouchAction::kTouchActionAuto;
+ bool visible_to_hit_testing_ = true;
+
private:
Member<FrameClient> client_;
const Member<WindowProxyManager> window_proxy_manager_;
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_client.h b/chromium/third_party/blink/renderer/core/frame/frame_client.h
index 92973e9e60b..9cb7d272683 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_client.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_client.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_CLIENT_H_
#include "base/unguessable_token.h"
-#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -17,7 +17,7 @@ namespace blink {
class Frame;
enum class FrameDetachType;
-class CORE_EXPORT FrameClient : public GarbageCollectedFinalized<FrameClient> {
+class CORE_EXPORT FrameClient : public GarbageCollected<FrameClient> {
public:
virtual bool InShadowTree() const = 0;
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_console.h b/chromium/third_party/blink/renderer/core/frame/frame_console.h
index 720cd843285..e1e9114b494 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_console.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_console.h
@@ -29,7 +29,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_CONSOLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_CONSOLE_H_
-#include "third_party/blink/public/mojom/devtools/console_message.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"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -48,8 +48,7 @@ class SourceLocation;
// Page to the ChromeClient and Inspector. It's meant as an abstraction
// around ChromeClient calls and the way that Blink core/ can add messages to
// the console.
-class CORE_EXPORT FrameConsole final
- : public GarbageCollectedFinalized<FrameConsole> {
+class CORE_EXPORT FrameConsole final : public GarbageCollected<FrameConsole> {
public:
explicit FrameConsole(LocalFrame&);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/frame_impl.cc
index ae4d25d87ea..e69469f371a 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_impl.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/editing/surrounding_text.h"
+#include "third_party/blink/renderer/core/frame/intervention.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -48,6 +49,13 @@ FrameImpl::~FrameImpl() = default;
void FrameImpl::GetTextSurroundingSelection(
uint32_t max_length,
GetTextSurroundingSelectionCallback callback) {
+ // Early return on detached frames to avoid crashing if a request for
+ // surrounding text gets received at this point.
+ if (!GetSupplementable()->IsAttached()) {
+ std::move(callback).Run(g_empty_string, 0, 0);
+ return;
+ }
+
blink::SurroundingText surrounding_text(GetSupplementable(), max_length);
// |surrounding_text| might not be correctly initialized, for example if
@@ -65,4 +73,9 @@ void FrameImpl::GetTextSurroundingSelection(
surrounding_text.EndOffsetInTextContent());
}
+void FrameImpl::SendInterventionReport(const String& id,
+ const String& message) {
+ Intervention::GenerateReport(GetSupplementable(), id, message);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_impl.h b/chromium/third_party/blink/renderer/core/frame/frame_impl.h
index 7abb3b8d114..8b8ab639fc7 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_impl.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_impl.h
@@ -18,7 +18,7 @@ namespace blink {
class LocalFrame;
// Implementation of mojom::blink::Frame
-class CORE_EXPORT FrameImpl final : public GarbageCollectedFinalized<FrameImpl>,
+class CORE_EXPORT FrameImpl final : public GarbageCollected<FrameImpl>,
public Supplement<LocalFrame>,
public mojom::blink::Frame {
USING_GARBAGE_COLLECTED_MIXIN(FrameImpl);
@@ -41,6 +41,8 @@ class CORE_EXPORT FrameImpl final : public GarbageCollectedFinalized<FrameImpl>,
uint32_t max_length,
GetTextSurroundingSelectionCallback callback) final;
+ void SendInterventionReport(const String& id, const String& message) final;
+
private:
mojo::AssociatedReceiver<mojom::blink::Frame> receiver_{this};
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc b/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
index 784ec829a29..058f16d4b5c 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_overlay.cc
@@ -109,6 +109,10 @@ void FrameOverlay::PaintContents(const GraphicsLayer* graphics_layer,
Paint(context);
}
+void FrameOverlay::GraphicsLayersDidChange() {
+ frame_->View()->SetForeignLayerListNeedsUpdate();
+}
+
void FrameOverlay::ServiceScriptedAnimations(
base::TimeTicks monotonic_frame_begin_time) {
delegate_->ServiceScriptedAnimations(monotonic_frame_begin_time);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_overlay.h b/chromium/third_party/blink/renderer/core/frame/frame_overlay.h
index ae0df9d1353..c3747409ad2 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_overlay.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_overlay.h
@@ -95,6 +95,7 @@ class CORE_EXPORT FrameOverlay : public GraphicsLayerClient,
GraphicsContext&,
GraphicsLayerPaintingPhase,
const IntRect& interest_rect) const override;
+ void GraphicsLayersDidChange() override;
String DebugName(const GraphicsLayer*) const override;
PropertyTreeState DefaultPropertyTreeState() const;
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 a1a2a5d817c..178e3b30087 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_owner.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_owner.h
@@ -14,12 +14,15 @@
namespace blink {
class Frame;
+class FrameSwapScope;
class ResourceTimingInfo;
// Oilpan: all FrameOwner instances are GCed objects. FrameOwner additionally
// derives from GarbageCollectedMixin so that Member<FrameOwner> references can
// be kept (e.g., Frame::m_owner.)
class CORE_EXPORT FrameOwner : public GarbageCollectedMixin {
+ friend class FrameSwapScope;
+
public:
virtual ~FrameOwner() = default;
@@ -73,13 +76,49 @@ class CORE_EXPORT FrameOwner : public GarbageCollectedMixin {
// Returns whether or not children of the owned frame should be lazily loaded.
virtual bool ShouldLazyLoadChildren() const = 0;
+
+ protected:
+ virtual void FrameOwnerPropertiesChanged() {}
+
+ private:
+ virtual void SetIsSwappingFrames(bool) {}
+};
+
+// The purpose of this class is to suppress the propagation of frame owner
+// properties while a frame is being replaced. In particular, it prevents the
+// erroneous propagation of is_display_none=true, which would otherwise happen
+// when the old frame is detached prior to attaching the new frame. This class
+// will postpone the propagation until the properties are in their new stable
+// state.
+//
+// It is only intended to handle cases where one frame is detached and a new
+// frame immediately attached. For normal frame unload/teardown, we don't need
+// to suppress the propagation.
+class FrameSwapScope {
+ STACK_ALLOCATED();
+
+ public:
+ FrameSwapScope(FrameOwner* frame_owner) : frame_owner_(frame_owner) {
+ if (frame_owner)
+ frame_owner->SetIsSwappingFrames(true);
+ }
+
+ ~FrameSwapScope() {
+ if (frame_owner_) {
+ frame_owner_->SetIsSwappingFrames(false);
+ frame_owner_->FrameOwnerPropertiesChanged();
+ }
+ }
+
+ private:
+ Member<FrameOwner> frame_owner_;
};
// TODO(dcheng): This class is an internal implementation detail of provisional
// frames. Move this into WebLocalFrameImpl.cpp and remove existing dependencies
// on it.
class CORE_EXPORT DummyFrameOwner final
- : public GarbageCollectedFinalized<DummyFrameOwner>,
+ : public GarbageCollected<DummyFrameOwner>,
public FrameOwner {
USING_GARBAGE_COLLECTED_MIXIN(DummyFrameOwner);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc b/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
index a9abd9e5a75..29e96a79a26 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -30,6 +30,8 @@
#include "third_party/blink/renderer/core/frame/frame_serializer.h"
+#include "base/feature_list.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/css/css_font_face_rule.h"
#include "third_party/blink/renderer/core/css/css_font_face_src_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
@@ -149,8 +151,8 @@ bool SerializerMarkupAccumulator::ShouldIgnoreElement(
return true;
if (IsHTMLNoScriptElement(element))
return true;
- if (IsHTMLMetaElement(element) &&
- ToHTMLMetaElement(element).ComputeEncoding().IsValid()) {
+ auto* meta = DynamicTo<HTMLMetaElement>(element);
+ if (meta && meta->ComputeEncoding().IsValid()) {
return true;
}
// This is done in serializing document.StyleSheets.
@@ -384,7 +386,7 @@ void FrameSerializer::AddResourceForElement(Document& document,
if (const auto* image = ToHTMLImageElementOrNull(element)) {
AtomicString image_url_value;
const Element* parent = element.parentElement();
- if (parent && IsHTMLPictureElement(parent)) {
+ if (parent && IsA<HTMLPictureElement>(parent)) {
// If parent element is <picture>, use ImageSourceURL() to get best fit
// image URL from sibling source.
image_url_value = image->ImageSourceURL();
@@ -534,7 +536,6 @@ void FrameSerializer::SerializeCSSRule(CSSRule* rule) {
case CSSRule::kKeyframeRule:
case CSSRule::kNamespaceRule:
case CSSRule::kViewportRule:
- case CSSRule::kFontFeatureValuesRule:
break;
}
}
@@ -631,7 +632,19 @@ void FrameSerializer::RetrieveResourcesForCSSValue(const CSSValue& css_value,
if (font_face_src_value->IsLocal())
return;
- AddFontToResources(font_face_src_value->Fetch(&document, nullptr));
+ if (base::FeatureList::IsEnabled(
+ features::kHtmlImportsRequestInitiatorLock)) {
+ if (Document* context_document = document.ContextDocument()) {
+ // For @imports from HTML imported Documents, we use the
+ // context document for getting origin and ResourceFetcher to use the
+ // main Document's origin, while using the element document for
+ // CompleteURL() to use imported Documents' base URLs.
+ AddFontToResources(
+ font_face_src_value->Fetch(context_document, nullptr));
+ }
+ } else {
+ AddFontToResources(font_face_src_value->Fetch(&document, nullptr));
+ }
} else if (const auto* css_value_list = DynamicTo<CSSValueList>(css_value)) {
for (unsigned i = 0; i < css_value_list->length(); i++)
RetrieveResourcesForCSSValue(css_value_list->Item(i), document);
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index a1f2e2abad4..47eb0f6926d 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
@@ -370,6 +370,9 @@ WebViewImpl* WebViewHelper::InitializeWithOpener(
// the case by this point).
web_view_->DidAttachLocalMainFrame();
+ web_view_->SetDeviceScaleFactor(
+ test_web_widget_client_->GetScreenInfo().device_scale_factor);
+
// Set an initial size for subframes.
if (frame->Parent())
frame->FrameWidget()->Resize(WebSize());
@@ -488,8 +491,15 @@ void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
// Consequently, all external image resources must be mocked.
web_view_->GetSettings()->SetLoadsImagesAutomatically(true);
- web_view_->SetDeviceScaleFactor(
- test_web_view_client_->GetScreenInfo().device_scale_factor);
+ // If a test turned off this settings, opened WebViews should propagate that.
+ if (opener) {
+ web_view_->GetSettings()->SetAllowUniversalAccessFromFileURLs(
+ static_cast<WebViewImpl*>(opener)
+ ->GetPage()
+ ->GetSettings()
+ .GetAllowUniversalAccessFromFileURLs());
+ }
+
web_view_->SetDefaultPageScaleLimits(1, 4);
}
@@ -647,10 +657,6 @@ void TestWebWidgetClient::SetBackgroundColor(SkColor color) {
layer_tree_host()->set_background_color(color);
}
-void TestWebWidgetClient::SetAllowGpuRasterization(bool allow) {
- layer_tree_host()->SetHasGpuRasterizationTrigger(allow);
-}
-
void TestWebWidgetClient::SetPageScaleStateAndLimits(
float page_scale_factor,
bool is_pinch_gesture_active,
@@ -700,11 +706,6 @@ void TestWebWidgetClient::StopDeferringCommits(
layer_tree_host()->StopDeferringCommits(trigger);
}
-void TestWebWidgetClient::RegisterViewportLayers(
- const cc::ViewportLayers& layers) {
- layer_tree_host()->RegisterViewportLayers(layers);
-}
-
void TestWebWidgetClient::RegisterSelection(
const cc::LayerSelection& selection) {
layer_tree_host()->RegisterSelection(selection);
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 2050e73c784..9b89b5e9c0e 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
@@ -39,11 +39,12 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/layer_tree_host.h"
#include "content/renderer/compositor/layer_tree_view.h"
#include "content/test/stub_layer_tree_view_delegate.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/test/web_fake_thread_scheduler.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
@@ -213,10 +214,8 @@ class TestWebWidgetClient : public WebWidgetClient {
// WebWidgetClient implementation.
void ScheduleAnimation() override { animation_scheduled_ = true; }
void SetRootLayer(scoped_refptr<cc::Layer> layer) override;
- void RegisterViewportLayers(const cc::ViewportLayers& layOAers) override;
void RegisterSelection(const cc::LayerSelection& selection) override;
void SetBackgroundColor(SkColor color) override;
- void SetAllowGpuRasterization(bool allow) override;
void SetPageScaleStateAndLimits(float page_scale_factor,
bool is_pinch_gesture_active,
float minimum,
@@ -243,7 +242,6 @@ class TestWebWidgetClient : public WebWidgetClient {
bool shrink_viewport) override;
viz::FrameSinkId GetFrameSinkId() override;
- content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
cc::LayerTreeHost* layer_tree_host() {
return layer_tree_view_->layer_tree_host();
}
@@ -294,7 +292,6 @@ class TestWebViewClient : public WebViewClient {
// WebViewClient overrides.
bool CanHandleGestureEvent() override { return true; }
bool CanUpdateLayout() override { return true; }
- blink::WebScreenInfo GetScreenInfo() override { return {}; }
WebView* CreateView(WebLocalFrame* opener,
const WebURLRequest&,
const WebWindowFeatures&,
@@ -371,8 +368,8 @@ class WebViewHelper {
void Reset();
WebViewImpl* GetWebView() const { return web_view_; }
- content::LayerTreeView* GetLayerTreeView() const {
- return test_web_widget_client_->layer_tree_view();
+ cc::LayerTreeHost* GetLayerTreeHost() const {
+ return test_web_widget_client_->layer_tree_host();
}
TestWebWidgetClient* GetWebWidgetClient() const {
return test_web_widget_client_;
diff --git a/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
index 13d190ce0b6..410fd82e42a 100644
--- a/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
+++ b/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/frame/fullscreen_controller.h"
#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
@@ -48,17 +48,6 @@
namespace blink {
-namespace {
-
-WebLocalFrameClient& GetWebFrameClient(LocalFrame& frame) {
- WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
- DCHECK(web_frame);
- DCHECK(web_frame->Client());
- return *web_frame->Client();
-}
-
-} // anonymous namespace
-
FullscreenController::FullscreenController(WebViewImpl* web_view_base)
: web_view_base_(web_view_base),
pending_frames_(MakeGarbageCollected<PendingFullscreenSet>()) {}
@@ -168,10 +157,8 @@ void FullscreenController::EnterFullscreen(LocalFrame& frame,
return;
DCHECK(state_ == State::kInitial);
- blink::WebFullscreenOptions blink_options;
- // Only clone options if the feature is enabled.
- blink_options.prefers_navigation_bar = options->navigationUI() != "hide";
- GetWebFrameClient(frame).EnterFullscreen(blink_options);
+ frame.GetLocalFrameHostRemote().EnterFullscreen(
+ mojom::blink::FullscreenOptions::New(options->navigationUI() != "hide"));
state_ = State::kEnteringFullscreen;
}
@@ -184,7 +171,7 @@ void FullscreenController::ExitFullscreen(LocalFrame& frame) {
if (state_ != State::kFullscreen)
return;
- GetWebFrameClient(frame).ExitFullscreen();
+ frame.GetLocalFrameHostRemote().ExitFullscreen();
state_ = State::kExitingFullscreen;
}
@@ -222,7 +209,7 @@ void FullscreenController::FullscreenElementChanged(Element* old_element,
if (Element* owner = new_element ? new_element : old_element) {
Document& doc = owner->GetDocument();
if (LocalFrame* frame = doc.GetFrame()) {
- GetWebFrameClient(*frame).FullscreenStateChanged(!!new_element);
+ frame->GetLocalFrameHostRemote().FullscreenStateChanged(!!new_element);
if (IsSpatialNavigationEnabled(frame)) {
doc.GetPage()->GetSpatialNavigationController().FullscreenStateChanged(
new_element);
diff --git a/chromium/third_party/blink/renderer/core/frame/history.cc b/chromium/third_party/blink/renderer/core/frame/history.cc
index db65bba1cf6..0eef974112d 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history.cc
@@ -89,7 +89,7 @@ SerializedScriptValue* History::state(ExceptionState& exception_state) {
}
SerializedScriptValue* History::StateInternal() const {
- if (!GetFrame())
+ if (!GetFrame() || !GetFrame()->Loader().GetDocumentLoader())
return nullptr;
if (HistoryItem* history_item =
@@ -195,7 +195,7 @@ void History::go(ScriptState* script_state,
return;
if (delta) {
- GetFrame()->Client()->NavigateBackForward(delta, true);
+ GetFrame()->Client()->NavigateBackForward(delta);
} else {
// We intentionally call reload() for the current frame if delta is zero.
// Otherwise, navigation happens on the root frame.
diff --git a/chromium/third_party/blink/renderer/core/frame/link_highlights.cc b/chromium/third_party/blink/renderer/core/frame/link_highlights.cc
deleted file mode 100644
index 8e962f496a9..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/link_highlights.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
-
-#include <memory>
-
-#include "cc/animation/animation_host.h"
-#include "cc/layers/picture_layer.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/paint/link_highlight_impl.h"
-#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
-
-namespace blink {
-
-LinkHighlights::LinkHighlights(Page& owner) : page_(&owner) {}
-
-LinkHighlights::~LinkHighlights() {
- RemoveAllHighlights();
-}
-
-void LinkHighlights::Trace(blink::Visitor* visitor) {
- visitor->Trace(page_);
-}
-
-void LinkHighlights::RemoveAllHighlights() {
- for (auto& highlight : link_highlights_) {
- if (timeline_)
- timeline_->AnimationDestroyed(*highlight);
- if (auto* node = highlight->GetNode()) {
- if (auto* layout_object = node->GetLayoutObject())
- layout_object->SetNeedsPaintPropertyUpdate();
- }
- }
- link_highlights_.clear();
-}
-
-void LinkHighlights::ResetForPageNavigation() {
- RemoveAllHighlights();
-}
-
-void LinkHighlights::SetTapHighlights(
- HeapVector<Member<Node>>& highlight_nodes) {
- // Always clear any existing highlight when this is invoked, even if we
- // don't get a new target to highlight.
- RemoveAllHighlights();
-
- for (wtf_size_t i = 0; i < highlight_nodes.size(); ++i) {
- Node* node = highlight_nodes[i];
-
- if (!node || !node->GetLayoutObject())
- continue;
-
- Color highlight_color =
- node->GetLayoutObject()->StyleRef().TapHighlightColor();
- // Safari documentation for -webkit-tap-highlight-color says if the
- // specified color has 0 alpha, then tap highlighting is disabled.
- // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
- if (!highlight_color.Alpha())
- continue;
-
- link_highlights_.push_back(std::make_unique<LinkHighlightImpl>(node));
- if (timeline_)
- timeline_->AnimationAttached(*link_highlights_.back());
- node->GetLayoutObject()->SetNeedsPaintPropertyUpdate();
- }
-}
-
-void LinkHighlights::UpdateGeometry() {
- for (auto& highlight : link_highlights_)
- highlight->UpdateGeometry();
-}
-
-LocalFrame* LinkHighlights::MainFrame() const {
- return GetPage().MainFrame() && GetPage().MainFrame()->IsLocalFrame()
- ? GetPage().DeprecatedLocalMainFrame()
- : nullptr;
-}
-
-void LinkHighlights::StartHighlightAnimationIfNeeded() {
- for (auto& highlight : link_highlights_)
- highlight->StartHighlightAnimationIfNeeded();
-
- if (auto* local_frame = MainFrame())
- GetPage().GetChromeClient().ScheduleAnimation(local_frame->View());
-}
-
-void LinkHighlights::AnimationHostInitialized(
- cc::AnimationHost& animation_host) {
- animation_host_ = &animation_host;
- if (Platform::Current()->IsThreadedAnimationEnabled()) {
- timeline_ = std::make_unique<CompositorAnimationTimeline>();
- animation_host_->AddAnimationTimeline(timeline_->GetAnimationTimeline());
- }
-}
-
-void LinkHighlights::WillCloseAnimationHost() {
- RemoveAllHighlights();
- if (timeline_) {
- animation_host_->RemoveAnimationTimeline(timeline_->GetAnimationTimeline());
- timeline_.reset();
- }
- animation_host_ = nullptr;
-}
-
-bool LinkHighlights::NeedsHighlightEffectInternal(
- const LayoutObject& object) const {
- for (auto& highlight : link_highlights_) {
- if (auto* node = highlight->GetNode()) {
- if (node->GetLayoutObject() == &object)
- return true;
- }
- }
- return false;
-}
-
-void LinkHighlights::Paint(GraphicsContext& context) const {
- DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- for (const auto& highlight : link_highlights_)
- highlight->Paint(context);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/link_highlights.h b/chromium/third_party/blink/renderer/core/frame/link_highlights.h
deleted file mode 100644
index e613f1eca68..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/link_highlights.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LINK_HIGHLIGHTS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LINK_HIGHLIGHTS_H_
-
-#include <memory>
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace cc {
-class AnimationHost;
-}
-
-namespace blink {
-class GraphicsContext;
-class Page;
-class LinkHighlightImpl;
-class CompositorAnimationTimeline;
-class LocalFrame;
-class LayoutObject;
-
-// TODO(wangxianzhu): Since the tap disambiguation feature was removed,
-// (http://crrev.com/c/579263), LinkHighlights no longer needs to manage
-// multiple link highlights. Rename this class to LinkHighlight and move
-// it under core/page, and rename LinkHighlightImpl (core/paint) to
-// LinkHighlightPainter. This will be convenient to do when we remove
-// GraphicsLayer for CompositeAfterPaint.
-class CORE_EXPORT LinkHighlights final
- : public GarbageCollectedFinalized<LinkHighlights> {
- public:
- explicit LinkHighlights(Page&);
- virtual ~LinkHighlights();
-
- virtual void Trace(blink::Visitor*);
-
- void ResetForPageNavigation();
-
- void SetTapHighlights(HeapVector<Member<Node>>&);
-
- // Updates geometry on all highlights. See: LinkHighlightImpl::UpdateGeometry.
- void UpdateGeometry();
-
- void StartHighlightAnimationIfNeeded();
-
- void AnimationHostInitialized(cc::AnimationHost&);
- void WillCloseAnimationHost();
-
- bool IsEmpty() const { return link_highlights_.IsEmpty(); }
-
- bool NeedsHighlightEffect(const LayoutObject& object) const {
- if (link_highlights_.IsEmpty())
- return false;
- return NeedsHighlightEffectInternal(object);
- }
-
- // For CompositeAfterPaint.
- void Paint(GraphicsContext&) const;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, verifyWebViewImplIntegration);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetDuringNodeRemoval);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetLayerTreeView);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, HighlightInvalidation);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, multipleHighlights);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, HighlightLayerEffectNode);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, MultiColumn);
- FRIEND_TEST_ALL_PREFIXES(LinkHighlightSquashingImplTest, SquashingLayer);
-
- void RemoveAllHighlights();
-
- LocalFrame* MainFrame() const;
-
- Page& GetPage() const {
- DCHECK(page_);
- return *page_;
- }
-
- bool NeedsHighlightEffectInternal(const LayoutObject& object) const;
-
- Member<Page> page_;
- Vector<std::unique_ptr<LinkHighlightImpl>> link_highlights_;
- cc::AnimationHost* animation_host_ = nullptr;
- std::unique_ptr<CompositorAnimationTimeline> timeline_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LINK_HIGHLIGHTS_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc b/chromium/third_party/blink/renderer/core/frame/local_dom_window.cc
index ed6afc878e7..9cd3e5220a8 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
@@ -119,7 +119,7 @@ static constexpr base::TimeDelta kUnusedPreloadTimeout =
static void UpdateSuddenTerminationStatus(
LocalDOMWindow* dom_window,
bool added_listener,
- WebSuddenTerminationDisablerType disabler_type) {
+ SuddenTerminationDisablerType disabler_type) {
Platform::Current()->SuddenTerminationChanged(!added_listener);
if (dom_window->GetFrame() && dom_window->GetFrame()->Client())
dom_window->GetFrame()->Client()->SuddenTerminationDisablerChanged(
@@ -454,14 +454,12 @@ void LocalDOMWindow::SendOrientationChangeEvent() {
int LocalDOMWindow::orientation() const {
DCHECK(RuntimeEnabledFeatures::OrientationEventEnabled());
- if (!GetFrame() || !GetFrame()->GetPage())
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
- int orientation = GetFrame()
- ->GetPage()
- ->GetChromeClient()
- .GetScreenInfo()
- .orientation_angle;
+ ChromeClient& chrome_client = frame->GetChromeClient();
+ int orientation = chrome_client.GetScreenInfo(*frame).orientation_angle;
// For backward compatibility, we want to return a value in the range of
// [-90; 180] instead of [0; 360[ because window.orientation used to behave
// like that in WebKit (this is a WebKit proprietary API).
@@ -796,7 +794,7 @@ int LocalDOMWindow::outerHeight() const {
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(chrome_client.RootWindowRect(*frame).Height() *
- chrome_client.GetScreenInfo().device_scale_factor));
+ chrome_client.GetScreenInfo(*frame).device_scale_factor));
}
return chrome_client.RootWindowRect(*frame).Height();
}
@@ -814,7 +812,7 @@ int LocalDOMWindow::outerWidth() const {
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(chrome_client.RootWindowRect(*frame).Width() *
- chrome_client.GetScreenInfo().device_scale_factor));
+ chrome_client.GetScreenInfo(*frame).device_scale_factor));
}
return chrome_client.RootWindowRect(*frame).Width();
}
@@ -874,7 +872,7 @@ int LocalDOMWindow::screenX() const {
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(chrome_client.RootWindowRect(*frame).X() *
- chrome_client.GetScreenInfo().device_scale_factor));
+ chrome_client.GetScreenInfo(*frame).device_scale_factor));
}
return chrome_client.RootWindowRect(*frame).X();
}
@@ -892,7 +890,7 @@ int LocalDOMWindow::screenY() const {
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
return static_cast<int>(
lroundf(chrome_client.RootWindowRect(*frame).Y() *
- chrome_client.GetScreenInfo().device_scale_factor));
+ chrome_client.GetScreenInfo(*frame).device_scale_factor));
}
return chrome_client.RootWindowRect(*frame).Y();
}
@@ -1041,7 +1039,7 @@ void LocalDOMWindow::scrollBy(const ScrollToOptions* scroll_to_options) const {
new_scaled_position =
document()
->GetSnapCoordinator()
- ->GetSnapPosition(*document()->GetLayoutView(), *strategy)
+ .GetSnapPosition(*document()->GetLayoutView(), *strategy)
.value_or(new_scaled_position);
ScrollBehavior scroll_behavior = kScrollBehaviorAuto;
@@ -1108,7 +1106,7 @@ void LocalDOMWindow::scrollTo(const ScrollToOptions* scroll_to_options) const {
new_scaled_position =
document()
->GetSnapCoordinator()
- ->GetSnapPosition(*document()->GetLayoutView(), *strategy)
+ .GetSnapPosition(*document()->GetLayoutView(), *strategy)
.value_or(new_scaled_position);
ScrollBehavior scroll_behavior = kScrollBehaviorAuto;
ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(),
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 b93579ccb06..96a00921af4 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
@@ -247,11 +247,7 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
bool isSecureContext() const;
- DEFINE_ATTRIBUTE_EVENT_LISTENER(animationend, kAnimationend)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(animationiteration, kAnimationiteration)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(animationstart, kAnimationstart)
DEFINE_ATTRIBUTE_EVENT_LISTENER(search, kSearch)
- DEFINE_ATTRIBUTE_EVENT_LISTENER(transitionend, kTransitionend)
DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitanimationstart, kWebkitAnimationStart)
DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitanimationiteration,
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 6e2fc4a7dd2..a9397ac1671 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc
@@ -36,6 +36,7 @@
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/interface_provider.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/frame/blocked_navigation_types.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
@@ -95,7 +96,6 @@
#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/previews_resource_loading_hints_receiver_impl.h"
#include "third_party/blink/renderer/core/page/drag_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/plugin_data.h"
@@ -141,18 +141,6 @@ inline float ParentTextZoomFactor(LocalFrame* frame) {
return parent_local_frame ? parent_local_frame->TextZoomFactor() : 1;
}
-bool ShouldUseClientLoFiForRequest(
- const ResourceRequest& request,
- WebURLRequest::PreviewsState frame_previews_state) {
- if (request.GetPreviewsState() != WebURLRequest::kPreviewsUnspecified)
- return request.GetPreviewsState() & WebURLRequest::kClientLoFiOn;
-
- if (!(frame_previews_state & WebURLRequest::kClientLoFiOn))
- return false;
-
- return true;
-}
-
} // namespace
template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
@@ -160,6 +148,9 @@ template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
void LocalFrame::Init() {
CoreInitializer::GetInstance().InitLocalFrame(*this);
+ GetRemoteNavigationAssociatedInterfaces()->GetInterface(
+ local_frame_host_remote_.BindNewEndpointAndPassReceiver());
+
loader_.Init();
}
@@ -308,7 +299,7 @@ void LocalFrame::DetachImpl(FrameDetachType type) {
// both when unloading itself and when unloading its descendants.
IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
GetDocument());
- loader_.DispatchUnloadEvent();
+ loader_.DispatchUnloadEvent(nullptr, nullptr);
DetachChildren();
// All done if detaching the subframes brought about a detach of this frame
@@ -376,7 +367,7 @@ void LocalFrame::DetachImpl(FrameDetachType type) {
}
bool LocalFrame::DetachDocument() {
- return Loader().DetachDocument();
+ return Loader().DetachDocument(nullptr, nullptr);
}
void LocalFrame::CheckCompleted() {
@@ -442,7 +433,6 @@ void LocalFrame::DidAttachDocument() {
GetInputMethodController().DidAttachDocument(document);
GetSpellChecker().DidAttachDocument(document);
GetTextSuggestionController().DidAttachDocument(document);
- previews_resource_loading_hints_receiver_.reset();
}
void LocalFrame::Reload(WebFrameLoadType load_type) {
@@ -496,59 +486,6 @@ void LocalFrame::DidChangeVisibilityState() {
Frame::DidChangeVisibilityState();
}
-void LocalFrame::DidFreeze() {
- if (GetDocument()) {
- if (GetDocument()->GetResourceCoordinator() &&
- !RuntimeEnabledFeatures::BackForwardCacheEnabled()) {
- // TODO(yuzus): Skip this block if DidFreeze is triggered by bfcache.
-
- // Determine if there is a beforeunload handler by dispatching a
- // beforeunload that will *not* launch a user dialog. If
- // |proceed| is false then there is a non-empty beforeunload
- // handler indicating potentially unsaved user state.
- bool unused_did_allow_navigation = false;
- bool proceed = GetDocument()->DispatchBeforeUnloadEvent(
- nullptr, false /* is_reload */, unused_did_allow_navigation);
- // Running the beforeunload event may invalidate the
- // DocumentResourceCoordinator. Because of that, it can't be stored in a
- // local variable that is reused throughout the method.
- // https://crbug.com/991380.
- auto* document_resource_coordinator =
- GetDocument()->GetResourceCoordinator();
- if (document_resource_coordinator)
- document_resource_coordinator->SetHasNonEmptyBeforeUnload(!proceed);
- }
-
- GetDocument()->DispatchFreezeEvent();
- // TODO(fmeawad): Move the following logic to the page once we have a
- // PageResourceCoordinator in Blink. http://crbug.com/838415
- if (auto* document_resource_coordinator =
- GetDocument()->GetResourceCoordinator()) {
- document_resource_coordinator->SetLifecycleState(
- resource_coordinator::mojom::LifecycleState::kFrozen);
- }
- }
-}
-
-void LocalFrame::DidResume() {
- if (GetDocument()) {
- const base::TimeTicks resume_event_start = base::TimeTicks::Now();
- GetDocument()->DispatchEvent(*Event::Create(event_type_names::kResume));
- const base::TimeTicks resume_event_end = base::TimeTicks::Now();
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, resume_histogram,
- ("DocumentEventTiming.ResumeDuration", 0, 10000000, 50));
- resume_histogram.CountMicroseconds(resume_event_end - resume_event_start);
- // TODO(fmeawad): Move the following logic to the page once we have a
- // PageResourceCoordinator in Blink
- if (auto* document_resource_coordinator =
- GetDocument()->GetResourceCoordinator()) {
- document_resource_coordinator->SetLifecycleState(
- resource_coordinator::mojom::LifecycleState::kRunning);
- }
- }
-}
-
void LocalFrame::HookBackForwardCacheEviction() {
// Register a callback dispatched when JavaScript is executed on the frame.
// The callback evicts the frame. If a frame is frozen by BackForwardCache,
@@ -915,9 +852,7 @@ LocalFrame::LocalFrame(LocalFrameClient* client,
interface_registry_(interface_registry
? interface_registry
: InterfaceRegistry::GetEmptyInterfaceRegistry()),
- is_save_data_enabled_(
- !(GetSettings() && GetSettings()->GetDataSaverHoldbackWebApi()) &&
- GetNetworkStateNotifier().SaveDataEnabled()),
+ is_save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled()),
lifecycle_state_(mojom::FrameLifecycleState::kRunning) {
if (IsLocalRoot()) {
probe_sink_ = MakeGarbageCollected<CoreProbeSink>();
@@ -1287,11 +1222,6 @@ void ScopedFrameBlamer::LeaveContext() {
context->Leave();
}
-bool LocalFrame::IsClientLoFiAllowed(const ResourceRequest& request) const {
- return Client() && ShouldUseClientLoFiForRequest(
- request, Client()->GetPreviewsStateForFrame());
-}
-
LocalFrame::LazyLoadImageSetting LocalFrame::GetLazyLoadImageSetting() const {
DCHECK(GetSettings());
if (!RuntimeEnabledFeatures::LazyImageLoadingEnabled() ||
@@ -1328,8 +1258,9 @@ bool LocalFrame::ShouldForceDeferScript() const {
// Check if enabled by runtime feature (for testing/evaluation) or if enabled
// by PreviewsState (for live intervention).
return RuntimeEnabledFeatures::ForceDeferScriptInterventionEnabled() ||
- (Client() && Client()->GetPreviewsStateForFrame() ==
- WebURLRequest::kDeferAllScriptOn);
+ (Loader().GetDocumentLoader() &&
+ Loader().GetDocumentLoader()->GetPreviewsState() ==
+ WebURLRequest::kDeferAllScriptOn);
}
WebURLLoaderFactory* LocalFrame::GetURLLoaderFactory() {
@@ -1447,17 +1378,6 @@ bool LocalFrame::IsProvisional() const {
return Owner()->ContentFrame() != this;
}
-bool LocalFrame::IsUsingDataSavingPreview() const {
- if (!Client())
- return false;
-
- WebURLRequest::PreviewsState previews_state =
- Client()->GetPreviewsStateForFrame();
- // Check for any data saving type of preview.
- return previews_state &
- (WebURLRequest::kClientLoFiOn | WebURLRequest::kNoScriptOn);
-}
-
bool LocalFrame::IsAdSubframe() const {
return ad_frame_type_ != blink::mojom::AdFrameType::kNonAd;
}
@@ -1518,15 +1438,6 @@ void LocalFrame::AnimateSnapFling(base::TimeTicks monotonic_time) {
GetEventHandler().AnimateSnapFling(monotonic_time);
}
-void LocalFrame::BindPreviewsResourceLoadingHintsReceiver(
- mojo::PendingReceiver<
- blink::mojom::blink::PreviewsResourceLoadingHintsReceiver> receiver) {
- DCHECK(!previews_resource_loading_hints_receiver_);
- previews_resource_loading_hints_receiver_ =
- std::make_unique<PreviewsResourceLoadingHintsReceiverImpl>(
- std::move(receiver), GetDocument());
-}
-
SmoothScrollSequencer& LocalFrame::GetSmoothScrollSequencer() {
if (!IsLocalRoot())
return LocalFrameRoot().GetSmoothScrollSequencer();
@@ -1699,20 +1610,70 @@ void LocalFrame::ForciblyPurgeV8Memory() {
Loader().StopAllLoaders();
}
-void LocalFrame::PauseContext() {
- if (Document* document = GetDocument()) {
- document->Fetcher()->SetDefersLoading(true);
- document->SetLifecycleState(lifecycle_state_);
+void LocalFrame::DispatchBeforeUnloadEventForFreeze() {
+ auto* document_resource_coordinator = GetDocument()->GetResourceCoordinator();
+ if (document_resource_coordinator &&
+ lifecycle_state_ == mojom::FrameLifecycleState::kRunning &&
+ !RuntimeEnabledFeatures::BackForwardCacheEnabled()) {
+ // TODO(yuzus): Skip this block if DidFreeze is triggered by bfcache.
+
+ // Determine if there is a beforeunload handler by dispatching a
+ // beforeunload that will *not* launch a user dialog. If
+ // |proceed| is false then there is a non-empty beforeunload
+ // handler indicating potentially unsaved user state.
+ bool unused_did_allow_navigation = false;
+ bool proceed = GetDocument()->DispatchBeforeUnloadEvent(
+ nullptr, false /* is_reload */, unused_did_allow_navigation);
+
+ // DispatchBeforeUnloadEvent dispatches JS events, which may detach |this|.
+ if (!IsAttached())
+ return;
+ document_resource_coordinator->SetHasNonEmptyBeforeUnload(!proceed);
+ }
+}
+
+void LocalFrame::DidFreeze() {
+ DCHECK(IsAttached());
+ GetDocument()->DispatchFreezeEvent();
+ // DispatchFreezeEvent dispatches JS events, which may detach |this|.
+ if (!IsAttached())
+ return;
+ // TODO(fmeawad): Move the following logic to the page once we have a
+ // PageResourceCoordinator in Blink. http://crbug.com/838415
+ if (auto* document_resource_coordinator =
+ GetDocument()->GetResourceCoordinator()) {
+ document_resource_coordinator->SetLifecycleState(
+ performance_manager::mojom::LifecycleState::kFrozen);
}
+}
+
+void LocalFrame::DidResume() {
+ DCHECK(IsAttached());
+ const base::TimeTicks resume_event_start = base::TimeTicks::Now();
+ GetDocument()->DispatchEvent(*Event::Create(event_type_names::kResume));
+ const base::TimeTicks resume_event_end = base::TimeTicks::Now();
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, resume_histogram,
+ ("DocumentEventTiming.ResumeDuration", 0, 10000000, 50));
+ resume_histogram.CountMicroseconds(resume_event_end - resume_event_start);
+ // TODO(fmeawad): Move the following logic to the page once we have a
+ // PageResourceCoordinator in Blink
+ if (auto* document_resource_coordinator =
+ GetDocument()->GetResourceCoordinator()) {
+ document_resource_coordinator->SetLifecycleState(
+ performance_manager::mojom::LifecycleState::kRunning);
+ }
+}
+
+void LocalFrame::PauseContext() {
+ GetDocument()->Fetcher()->SetDefersLoading(true);
+ GetDocument()->SetLifecycleState(lifecycle_state_);
Loader().SetDefersLoading(true);
GetFrameScheduler()->SetPaused(true);
}
void LocalFrame::UnpauseContext() {
- if (Document* document = GetDocument()) {
- document->Fetcher()->SetDefersLoading(false);
- document->SetLifecycleState(mojom::FrameLifecycleState::kRunning);
- }
+ GetDocument()->Fetcher()->SetDefersLoading(false);
+ GetDocument()->SetLifecycleState(mojom::FrameLifecycleState::kRunning);
Loader().SetDefersLoading(false);
GetFrameScheduler()->SetPaused(false);
}
@@ -1725,7 +1686,12 @@ void LocalFrame::SetLifecycleState(mojom::FrameLifecycleState state) {
// load event has fired.
if ((state == mojom::FrameLifecycleState::kFrozen ||
state == mojom::FrameLifecycleState::kFrozenAutoResumeMedia) &&
- IsLoading()) {
+ IsLoading() && !RuntimeEnabledFeatures::BackForwardCacheEnabled()) {
+ // TODO(yuzus): We violate the spec and when bfcache is enabled,
+ // |pending_lifecycle_state_| is not set.
+ // With bfcache, the decision as to whether the frame gets frozen or not is
+ // already made on the browser side and should not be overridden here.
+ // https://wicg.github.io/page-lifecycle/#update-document-frozenness-steps
pending_lifecycle_state_ = state;
return;
}
@@ -1750,7 +1716,7 @@ void LocalFrame::SetLifecycleState(mojom::FrameLifecycleState state) {
if (freeze) {
if (lifecycle_state_ != mojom::FrameLifecycleState::kPaused) {
DidFreeze();
- // DidFreeze can dispatch JS events, causing |this| to be detached.
+ // DidFreeze can dispatch JS events, which may detach |this|.
if (!IsAttached())
return;
}
@@ -1759,13 +1725,12 @@ void LocalFrame::SetLifecycleState(mojom::FrameLifecycleState state) {
UnpauseContext();
if (old_state != mojom::FrameLifecycleState::kPaused) {
DidResume();
- // DidResume can dispatch JS events, causing |this| to be detached.
+ // DidResume can dispatch JS events, which may detach |this|.
if (!IsAttached())
return;
}
}
- if (Client())
- Client()->LifecycleStateChanged(state);
+ Client()->LifecycleStateChanged(state);
}
void LocalFrame::MaybeLogAdClickNavigation() {
@@ -1824,4 +1789,17 @@ void LocalFrame::EvictFromBackForwardCache() {
Client()->EvictFromBackForwardCache();
}
+void LocalFrame::DidChangeVisibleToHitTesting() {
+ // LayoutEmbeddedContent does not propagate style updates to descendants.
+ // Need to update the field manually.
+ for (Frame* child = Tree().FirstChild(); child;
+ child = child->Tree().NextSibling()) {
+ child->UpdateVisibleToHitTesting();
+ }
+}
+
+mojom::blink::LocalFrameHost& LocalFrame::GetLocalFrameHostRemote() {
+ return *local_frame_host_remote_.get();
+}
+
} // 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 3ae0936a186..808e39876b2 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.h
@@ -33,15 +33,15 @@
#include "base/macros.h"
#include "base/time/default_tick_clock.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "third_party/blink/public/common/frame/occlusion_state.h"
#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/lifecycle.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/loader/previews_resource_loading_hints.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink-forward.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -100,7 +100,6 @@ class Node;
class NodeTraversal;
class PerformanceMonitor;
class PluginData;
-class ResourceRequest;
class ScriptController;
class SmoothScrollSequencer;
class SpellChecker;
@@ -142,8 +141,6 @@ class CORE_EXPORT LocalFrame final : public Frame,
bool DetachDocument() override;
void CheckCompleted() override;
void DidChangeVisibilityState() override;
- void DidFreeze() override;
- void DidResume() override;
void HookBackForwardCacheEviction() override;
void RemoveBackForwardCacheEviction() override;
// This sets the is_inert_ flag and also recurses through this frame's
@@ -274,6 +271,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
void RemoveSpellingMarkersUnderWords(const Vector<String>& words);
bool ShouldThrottleRendering() const;
+ void DispatchBeforeUnloadEventForFreeze();
// Returns frame scheduler for this frame.
// FrameScheduler is destroyed during frame detach and nullptr will be
@@ -323,9 +321,6 @@ class CORE_EXPORT LocalFrame final : public Frame,
AdTracker* GetAdTracker() { return ad_tracker_; }
void SetAdTrackerForTesting(AdTracker* ad_tracker);
- // Returns true if Client Lo-Fi should be used for this request.
- bool IsClientLoFiAllowed(const ResourceRequest&) const;
-
enum class LazyLoadImageSetting {
kDisabled,
kEnabledExplicit,
@@ -378,10 +373,6 @@ class CORE_EXPORT LocalFrame final : public Frame,
// be removed.
bool IsProvisional() const;
- // Returns whether the frame is trying to save network data by showing a
- // preview.
- bool IsUsingDataSavingPreview() const;
-
// True if AdTracker heuristics have determined that this frame is an ad.
// Calculated in the constructor but LocalFrames created on behalf of OOPIF
// aren't set until just before commit (ReadyToCommitNavigation time) by the
@@ -407,15 +398,14 @@ class CORE_EXPORT LocalFrame final : public Frame,
return client_hints_preferences_;
}
- void BindPreviewsResourceLoadingHintsReceiver(
- mojo::PendingReceiver<
- blink::mojom::blink::PreviewsResourceLoadingHintsReceiver> receiver);
-
SmoothScrollSequencer& GetSmoothScrollSequencer();
const mojo::Remote<mojom::blink::ReportingServiceProxy>& GetReportingService()
const;
+ // Returns the frame host ptr.
+ mojom::blink::LocalFrameHost& GetLocalFrameHostRemote();
+
// Overlays a color on top of this LocalFrameView if it is associated with
// the main frame. Should not have multiple consumers.
void SetMainFrameColorOverlay(SkColor color);
@@ -461,6 +451,8 @@ class CORE_EXPORT LocalFrame final : public Frame,
void SetIsCapturingMediaCallback(IsCapturingMediaCallback callback);
bool IsCapturingMedia() const;
+ void DidChangeVisibleToHitTesting() override;
+
private:
friend class FrameNavigationDisabler;
@@ -506,6 +498,8 @@ class CORE_EXPORT LocalFrame final : public Frame,
void SetFrameColorOverlay(SkColor color);
+ void DidFreeze();
+ void DidResume();
void PauseContext();
void UnpauseContext();
@@ -575,9 +569,6 @@ class CORE_EXPORT LocalFrame final : public Frame,
// Per-frame URLLoader factory.
std::unique_ptr<WebURLLoaderFactory> url_loader_factory_;
- std::unique_ptr<mojom::blink::PreviewsResourceLoadingHintsReceiver>
- previews_resource_loading_hints_receiver_;
-
ClientHintsPreferences client_hints_preferences_;
// The value of |is_save_data_enabled_| is read once per frame from
@@ -596,6 +587,8 @@ class CORE_EXPORT LocalFrame final : public Frame,
mojom::FrameLifecycleState lifecycle_state_;
base::Optional<mojom::FrameLifecycleState> pending_lifecycle_state_;
+
+ mojo::AssociatedRemote<mojom::blink::LocalFrameHost> local_frame_host_remote_;
};
inline FrameLoader& LocalFrame::Loader() const {
diff --git a/chromium/third_party/blink/renderer/core/frame/local_frame_back_forward_cache_test.cc b/chromium/third_party/blink/renderer/core/frame/local_frame_back_forward_cache_test.cc
index ab5e3cff45b..53e94edbb63 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame_back_forward_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame_back_forward_cache_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "base/run_loop.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/script_controller.h"
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 9134ca8de3e..0fa9c50f4d8 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
@@ -38,25 +38,24 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
+#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/common/sudden_termination_disabler_type.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h"
-#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
-#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
-#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
-#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/public/web/web_history_commit_type.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_manifest_manager.h"
#include "third_party/blink/public/web/web_navigation_params.h"
-#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/icon_url.h"
@@ -120,10 +119,6 @@ class WebSpellCheckPanelHostClient;
struct WebScrollIntoViewParams;
class WebTextCheckClient;
-// Whether to follow cross origin redirects when downloading, or treating
-// the download as a navigation instead.
-enum class DownloadCrossOriginRedirects { kFollow, kNavigate };
-
class CORE_EXPORT LocalFrameClient : public FrameClient {
public:
~LocalFrameClient() override = default;
@@ -152,9 +147,6 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DispatchDidCommitLoad(HistoryItem*,
WebHistoryCommitType,
GlobalObjectReusePolicy) = 0;
- virtual void DispatchDidFailProvisionalLoad(
- const ResourceError&,
- const AtomicString& http_method) = 0;
virtual void DispatchDidFailLoad(const ResourceError&,
WebHistoryCommitType) = 0;
virtual void DispatchDidFinishDocumentLoad() = 0;
@@ -171,7 +163,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
bool has_transient_activation,
WebFrameLoadType,
bool is_client_redirect,
- WebTriggeringEventInfo,
+ TriggeringEventInfo,
HTMLFormElement*,
ContentSecurityPolicyDisposition
should_check_main_world_content_security_policy,
@@ -191,10 +183,9 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void ForwardResourceTimingToParent(const WebResourceTimingInfo&) = 0;
virtual void DownloadURL(const ResourceRequest&,
- DownloadCrossOriginRedirects) = 0;
- virtual void LoadErrorPage(int reason) = 0;
+ network::mojom::RedirectMode) = 0;
- virtual bool NavigateBackForward(int offset, bool from_script) const = 0;
+ virtual bool NavigateBackForward(int offset) const = 0;
// Another page has accessed the initial empty document of this frame. It is
// no longer safe to display a provisional URL, since a URL spoof is now
@@ -219,10 +210,6 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
// The frame ran content with certificate errors with the given URL.
virtual void DidRunContentWithCertificateErrors() = 0;
- // The frame loaded a resource with a legacy TLS version that will be removed
- // in the future. Prints a console message to warn about this.
- virtual void ReportLegacyTLSVersion(const KURL&) {}
-
// Will be called when |PerformanceTiming| events are updated
virtual void DidChangePerformanceTiming() {}
@@ -236,7 +223,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
// Will be called when a particular loading code path has been used. This
// propogates renderer loading behavior to the browser process for histograms.
- virtual void DidObserveLoadingBehavior(WebLoadingBehaviorFlag) {}
+ virtual void DidObserveLoadingBehavior(LoadingBehaviorFlag) {}
// Will be called when a new UseCounter feature has been observed in a frame.
// This propogates feature usage to the browser process for histograms.
@@ -382,21 +369,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual bool IsLocalFrameClientImpl() const { return false; }
- virtual void SuddenTerminationDisablerChanged(
- bool present,
- WebSuddenTerminationDisablerType) {}
-
- // Effective connection type when this frame was loaded.
- virtual WebEffectiveConnectionType GetEffectiveConnectionType() {
- return WebEffectiveConnectionType::kTypeUnknown;
- }
- // Overrides the effective connection type for testing.
- virtual void SetEffectiveConnectionTypeForTesting(
- WebEffectiveConnectionType) {}
-
- // Returns the PreviewsState active for the frame.
- virtual WebURLRequest::PreviewsState GetPreviewsStateForFrame() const {
- return WebURLRequest::kPreviewsUnspecified;
+ virtual void SuddenTerminationDisablerChanged(bool present,
+ SuddenTerminationDisablerType) {
}
// Overwrites the given URL to use an HTML5 embed if possible. An empty URL is
@@ -432,9 +406,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
}
virtual AssociatedInterfaceProvider*
- GetRemoteNavigationAssociatedInterfaces() {
- return nullptr;
- }
+ GetRemoteNavigationAssociatedInterfaces() = 0;
// Notify the embedder that the associated frame has user activation so that
// the replicated states in the browser and other renderers can be updated.
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 2d631832cbe..a417e92455d 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
@@ -17,42 +17,15 @@ namespace blink {
namespace {
-void MaybeAllowImagePlaceholder(DummyPageHolder* page_holder,
- FetchParameters& params) {
- if (page_holder->GetFrame().IsClientLoFiAllowed(params.GetResourceRequest()))
- params.SetClientLoFiPlaceholder();
-}
-
-void DisableLazyLoadAndDisableDataSaverHoldbackInSettings(Settings& settings) {
+void DisableLazyLoadInSettings(Settings& settings) {
settings.SetLazyLoadEnabled(false);
- settings.SetDataSaverHoldbackWebApi(false);
}
-void EnableLazyLoadAndDisableDataSaverHoldbackInSettings(Settings& settings) {
+void EnableLazyLoadInSettings(Settings& settings) {
settings.SetLazyLoadEnabled(true);
- settings.SetDataSaverHoldbackWebApi(false);
-}
-void EnableLazyLoadAndEnableDataSaverHoldbackInSettings(Settings& settings) {
- settings.SetLazyLoadEnabled(true);
- settings.SetDataSaverHoldbackWebApi(true);
}
} // namespace
-class TestLocalFrameClient : public EmptyLocalFrameClient {
- public:
- explicit TestLocalFrameClient(
- WebURLRequest::PreviewsState frame_previews_state)
- : frame_previews_state_(frame_previews_state) {}
- ~TestLocalFrameClient() override = default;
-
- WebURLRequest::PreviewsState GetPreviewsStateForFrame() const override {
- return frame_previews_state_;
- }
-
- private:
- const WebURLRequest::PreviewsState frame_previews_state_;
-};
-
class LocalFrameTest : public testing::Test {
public:
void TearDown() override {
@@ -61,100 +34,11 @@ class LocalFrameTest : public testing::Test {
}
};
-TEST_F(LocalFrameTest, MaybeAllowPlaceholderImageUsesSpecifiedRequestValue) {
- ResourceRequest request1;
- request1.SetUrl(KURL("http://insecure.com"));
- request1.SetPreviewsState(WebURLRequest::kClientLoFiOn);
- FetchParameters params1(request1);
- auto page_holder = std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kPreviewsOff));
- MaybeAllowImagePlaceholder(page_holder.get(), params1);
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params1.GetImageRequestOptimization());
-
- ResourceRequest request2;
- request2.SetUrl(KURL("https://secure.com"));
- request2.SetPreviewsState(WebURLRequest::kPreviewsOff);
- FetchParameters params2(request2);
- auto page_holder2 = std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kClientLoFiOn));
- MaybeAllowImagePlaceholder(page_holder2.get(), params2);
- EXPECT_EQ(FetchParameters::kNone, params2.GetImageRequestOptimization());
-}
-
-TEST_F(LocalFrameTest, MaybeAllowPlaceholderImageUsesFramePreviewsState) {
- ResourceRequest request1;
- request1.SetUrl(KURL("http://insecure.com"));
- request1.SetPreviewsState(WebURLRequest::kPreviewsUnspecified);
- FetchParameters params1(request1);
- auto page_holder = std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(WebURLRequest::kClientLoFiOn));
- MaybeAllowImagePlaceholder(page_holder.get(), params1);
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params1.GetImageRequestOptimization());
- EXPECT_TRUE(page_holder->GetFrame().IsUsingDataSavingPreview());
-
- ResourceRequest request2;
- request2.SetUrl(KURL("http://insecure.com"));
- request2.SetPreviewsState(WebURLRequest::kPreviewsUnspecified);
- FetchParameters params2(request2);
- auto page_holder2 = std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kServerLitePageOn));
- MaybeAllowImagePlaceholder(page_holder2.get(), params2);
- EXPECT_EQ(FetchParameters::kNone, params2.GetImageRequestOptimization());
- EXPECT_FALSE(page_holder2->GetFrame().IsUsingDataSavingPreview());
-}
-
-TEST_F(LocalFrameTest, IsUsingDataSavingPreview) {
- EXPECT_TRUE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kClientLoFiOn))
- ->GetFrame()
- .IsUsingDataSavingPreview());
- EXPECT_TRUE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kNoScriptOn))
- ->GetFrame()
- .IsUsingDataSavingPreview());
-
- EXPECT_FALSE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kPreviewsUnspecified))
- ->GetFrame()
- .IsUsingDataSavingPreview());
- EXPECT_FALSE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kPreviewsOff))
- ->GetFrame()
- .IsUsingDataSavingPreview());
- EXPECT_FALSE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kPreviewsNoTransform))
- ->GetFrame()
- .IsUsingDataSavingPreview());
- EXPECT_FALSE(std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr,
- MakeGarbageCollected<TestLocalFrameClient>(
- WebURLRequest::kServerLitePageOn))
- ->GetFrame()
- .IsUsingDataSavingPreview());
-}
-
TEST_F(LocalFrameTest, IsLazyLoadingImageAllowedWithFeatureDisabled) {
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(false);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndDisableDataSaverHoldbackInSettings));
+ base::BindOnce(&EnableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kDisabled,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
@@ -163,7 +47,7 @@ TEST_F(LocalFrameTest, IsLazyLoadingImageAllowedWithSettingDisabled) {
ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(false);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&DisableLazyLoadAndDisableDataSaverHoldbackInSettings));
+ base::BindOnce(&DisableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kDisabled,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
@@ -174,7 +58,7 @@ TEST_F(LocalFrameTest, IsLazyLoadingImageAllowedWithAutomaticDisabled) {
scoped_automatic_lazy_image_loading_for_test(false);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndDisableDataSaverHoldbackInSettings));
+ base::BindOnce(&EnableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kEnabledExplicit,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
@@ -188,7 +72,7 @@ TEST_F(LocalFrameTest, IsLazyLoadingImageAllowedWhenNotRestricted) {
false);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndDisableDataSaverHoldbackInSettings));
+ base::BindOnce(&EnableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kEnabledAutomatic,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
@@ -203,22 +87,7 @@ TEST_F(LocalFrameTest,
GetNetworkStateNotifier().SetSaveDataEnabled(false);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndDisableDataSaverHoldbackInSettings));
- EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kEnabledExplicit,
- page_holder->GetFrame().GetLazyLoadImageSetting());
-}
-
-TEST_F(LocalFrameTest,
- IsLazyLoadingImageAllowedWhenRestrictedWithDataSaverEnabledHoldback) {
- ScopedLazyImageLoadingForTest scoped_lazy_image_loading_for_test(true);
- ScopedAutomaticLazyImageLoadingForTest
- scoped_automatic_lazy_image_loading_for_test(true);
- ScopedRestrictAutomaticLazyImageLoadingToDataSaverForTest
- scoped_restrict_automatic_lazy_image_loading_to_data_saver_for_test(true);
- GetNetworkStateNotifier().SetSaveDataEnabled(true);
- auto page_holder = std::make_unique<DummyPageHolder>(
- IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndEnableDataSaverHoldbackInSettings));
+ base::BindOnce(&EnableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kEnabledExplicit,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
@@ -233,7 +102,7 @@ TEST_F(LocalFrameTest,
GetNetworkStateNotifier().SetSaveDataEnabled(true);
auto page_holder = std::make_unique<DummyPageHolder>(
IntSize(800, 600), nullptr, nullptr,
- base::BindOnce(&EnableLazyLoadAndDisableDataSaverHoldbackInSettings));
+ base::BindOnce(&EnableLazyLoadInSettings));
EXPECT_EQ(LocalFrame::LazyLoadImageSetting::kEnabledAutomatic,
page_holder->GetFrame().GetLazyLoadImageSetting());
}
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 f0ac3c4af6d..b90e9d648e1 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
@@ -7,6 +7,7 @@
#include "base/format_macros.h"
#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/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -24,7 +25,7 @@ LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
start_time_(clock_->NowTicks()) {}
LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
- ScopedUkmHierarchicalTimer&& other) noexcept
+ ScopedUkmHierarchicalTimer&& other)
: aggregator_(other.aggregator_),
metric_index_(other.metric_index_),
clock_(other.clock_),
@@ -124,6 +125,48 @@ void LocalFrameUkmAggregator::BeginMainFrame() {
in_main_frame_update_ = true;
}
+std::unique_ptr<cc::BeginMainFrameMetrics>
+LocalFrameUkmAggregator::GetBeginMainFrameMetrics() {
+ DCHECK(InMainFrame());
+
+ // Use the main_frame_percentage_records_ because they are the ones that
+ // only count time between the Begin and End of a main frame update.
+ std::unique_ptr<cc::BeginMainFrameMetrics> metrics_data =
+ std::make_unique<cc::BeginMainFrameMetrics>();
+ metrics_data->handle_input_events =
+ main_frame_percentage_records_[static_cast<unsigned>(
+ MetricId::kHandleInputEvents)]
+ .interval_duration;
+ metrics_data->animate =
+ main_frame_percentage_records_[static_cast<unsigned>(MetricId::kAnimate)]
+ .interval_duration;
+ metrics_data->style_update =
+ main_frame_percentage_records_[static_cast<unsigned>(MetricId::kStyle)]
+ .interval_duration;
+ metrics_data->layout_update =
+ main_frame_percentage_records_[static_cast<unsigned>(MetricId::kLayout)]
+ .interval_duration;
+ metrics_data->prepaint =
+ main_frame_percentage_records_[static_cast<unsigned>(MetricId::kPrePaint)]
+ .interval_duration;
+ metrics_data->composite =
+ main_frame_percentage_records_[static_cast<unsigned>(
+ MetricId::kCompositing)]
+ .interval_duration;
+ metrics_data->paint =
+ main_frame_percentage_records_[static_cast<unsigned>(MetricId::kPaint)]
+ .interval_duration;
+ metrics_data->scrolling_coordinator =
+ main_frame_percentage_records_[static_cast<unsigned>(
+ MetricId::kScrollingCoordinator)]
+ .interval_duration;
+ metrics_data->composite_commit =
+ main_frame_percentage_records_[static_cast<unsigned>(
+ MetricId::kCompositingCommit)]
+ .interval_duration;
+ return metrics_data;
+}
+
void LocalFrameUkmAggregator::SetTickClockForTesting(
const base::TickClock* clock) {
clock_ = clock;
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 44c3f87ac4a..e34212257d7 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
@@ -14,6 +14,10 @@ namespace base {
class TickClock;
}
+namespace cc {
+struct BeginMainFrameMetrics;
+}
+
namespace ukm {
class UkmRecorder;
}
@@ -195,7 +199,7 @@ class CORE_EXPORT LocalFrameUkmAggregator
STACK_ALLOCATED();
public:
- ScopedUkmHierarchicalTimer(ScopedUkmHierarchicalTimer&&) noexcept;
+ ScopedUkmHierarchicalTimer(ScopedUkmHierarchicalTimer&&);
~ScopedUkmHierarchicalTimer();
private:
@@ -238,6 +242,12 @@ class CORE_EXPORT LocalFrameUkmAggregator
bool InMainFrame() { return in_main_frame_update_; }
+ // Populate a BeginMainFrameMetrics structure with the latency numbers for
+ // the most recent frame. Must be called when within a main frame update.
+ // That is, after calling BeginMainFrame and before calling
+ // RecordEndOfFrameMetrics.
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics();
+
// The caller is the owner of the |clock|. The |clock| must outlive the
// LocalFrameUkmAggregator.
void SetTickClockForTesting(const base::TickClock* clock);
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 a9bef6dfc77..458fa838f4e 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.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"
@@ -246,4 +247,43 @@ TEST_F(LocalFrameUkmAggregatorTest, EventsRecordedAtIntervals) {
expected_percentage);
}
+TEST_F(LocalFrameUkmAggregatorTest, LatencyDataIsPopulated) {
+ // Although the tests use a mock clock, the UKM aggregator 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.
+ if (!base::TimeTicks::IsHighResolution())
+ return;
+
+ // The initial interval is always zero, so we should see one set of metrics
+ // for the initial frame, regardless of the initial interval.
+ FramesToNextEventForTest(1);
+ unsigned millisecond_for_step = 1;
+ aggregator().BeginMainFrame();
+ for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) {
+ auto timer =
+ aggregator().GetScopedTimer(i % LocalFrameUkmAggregator::kCount);
+ test_task_runner_->FastForwardBy(
+ base::TimeDelta::FromMilliseconds(millisecond_for_step));
+ }
+
+ // Need to populate before the end of the frame.
+ std::unique_ptr<cc::BeginMainFrameMetrics> metrics_data =
+ aggregator().GetBeginMainFrameMetrics();
+ EXPECT_EQ(metrics_data->handle_input_events.InMillisecondsF(),
+ millisecond_for_step);
+ EXPECT_EQ(metrics_data->animate.InMillisecondsF(), millisecond_for_step);
+ EXPECT_EQ(metrics_data->style_update.InMillisecondsF(), millisecond_for_step);
+ EXPECT_EQ(metrics_data->layout_update.InMillisecondsF(),
+ millisecond_for_step);
+ EXPECT_EQ(metrics_data->prepaint.InMillisecondsF(), millisecond_for_step);
+ EXPECT_EQ(metrics_data->composite.InMillisecondsF(), millisecond_for_step);
+ EXPECT_EQ(metrics_data->paint.InMillisecondsF(), millisecond_for_step);
+ EXPECT_EQ(metrics_data->scrolling_coordinator.InMillisecondsF(),
+ millisecond_for_step);
+ EXPECT_EQ(metrics_data->composite_commit.InMillisecondsF(),
+ millisecond_for_step);
+ // Do not check the value in metrics_data.update_layers because it
+ // is not set by the aggregator.
+}
+
} // 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 ef9b6d01aa4..b48fd035e1e 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
@@ -56,7 +56,6 @@
#include "third_party/blink/renderer/core/frame/find_in_page.h"
#include "third_party/blink/renderer/core/frame/frame_overlay.h"
#include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.h"
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
@@ -76,6 +75,7 @@
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
#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/inspector/inspector_trace_events.h"
@@ -101,10 +101,10 @@
#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/frame_tree.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/print_context.h"
#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
@@ -138,7 +138,6 @@
#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/link_highlight.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -198,18 +197,16 @@ void LogCursorSizeCounter(LocalFrame* frame, const Cursor& cursor) {
// flash between navigations. The delay should be small enough so that it won't
// confuse users expecting a new page to appear after navigation and the omnibar
// has updated the url display.
-constexpr int kAvoidFlashCommitDelayDefaultInMs = 500; // 30 frames @ 60hz
-constexpr char kAvoidFlashCommitDelayParameterName[] = "commit_delay";
+constexpr int kPaintHoldingCommitDelayDefaultInMs = 500; // 30 frames @ 60hz
+constexpr char kPaintHoldingCommitDelayParameterName[] = "commit_delay";
-// Get the field trial parameter value for AvoidFlashBetweenNavigation.
-base::TimeDelta GetCommitDelayForAvoidFlashBetweenNavigation() {
- DCHECK(base::FeatureList::IsEnabled(
- blink::features::kAvoidFlashBetweenNavigation));
+// Get the field trial parameter value for Paint Holding.
+base::TimeDelta GetCommitDelayForPaintHolding() {
+ DCHECK(base::FeatureList::IsEnabled(blink::features::kPaintHolding));
return base::TimeDelta::FromMilliseconds(
base::GetFieldTrialParamByFeatureAsInt(
- blink::features::kAvoidFlashBetweenNavigation,
- kAvoidFlashCommitDelayParameterName,
- kAvoidFlashCommitDelayDefaultInMs));
+ blink::features::kPaintHolding, kPaintHoldingCommitDelayParameterName,
+ kPaintHoldingCommitDelayDefaultInMs));
}
} // namespace
@@ -234,14 +231,15 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, const IntSize& initial_size)
LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
: FrameView(frame_rect),
frame_(frame),
- display_mode_(kWebDisplayModeBrowser),
+ display_mode_(blink::mojom::DisplayMode::kBrowser),
can_have_scrollbars_(true),
has_pending_layout_(false),
layout_scheduling_enabled_(true),
layout_count_for_testing_(0),
lifecycle_update_count_for_testing_(0),
nested_layout_count_(0),
- update_plugins_timer_(frame.GetTaskRunner(TaskType::kInternalDefault),
+ // We want plugin updates to happen in FIFO order with loading tasks.
+ update_plugins_timer_(frame.GetTaskRunner(TaskType::kInternalLoading),
this,
&LocalFrameView::UpdatePluginsTimerFired),
first_layout_(true),
@@ -325,9 +323,9 @@ void LocalFrameView::ForAllChildViewsAndPlugins(const Function& function) {
}
if (Document* document = frame_->GetDocument()) {
- for (HTMLPortalElement* portal :
+ for (PortalContents* portal :
DocumentPortals::From(*document).GetPortals()) {
- if (Frame* frame = portal->ContentFrame())
+ if (Frame* frame = portal->GetFrame())
function(*frame->View());
}
}
@@ -531,7 +529,8 @@ void LocalFrameView::AdjustViewSize() {
return;
DCHECK_EQ(frame_->View(), this);
- SetLayoutOverflowSize(layout_view->DocumentRect().Size());
+ SetLayoutOverflowSize(
+ PixelSnappedIntRect(layout_view->DocumentRect()).Size());
}
void LocalFrameView::AdjustViewSizeAndLayout() {
@@ -543,11 +542,6 @@ void LocalFrameView::AdjustViewSizeAndLayout() {
}
}
-void LocalFrameView::UpdateAcceleratedCompositingSettings() {
- if (auto* layout_view = GetLayoutView())
- layout_view->Compositor()->UpdateAcceleratedCompositingSettings();
-}
-
void LocalFrameView::UpdateCountersAfterStyleChange() {
auto* layout_view = GetLayoutView();
DCHECK(layout_view);
@@ -639,8 +633,9 @@ std::unique_ptr<TracedValue> LocalFrameView::AnalyzerCounters() {
value->SetString(
"frame",
String::Format("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(frame_.Get())));
- value->SetInteger("contentsHeightAfterLayout",
- GetLayoutView()->DocumentRect().Height());
+ value->SetInteger(
+ "contentsHeightAfterLayout",
+ PixelSnappedIntRect(GetLayoutView()->DocumentRect()).Height());
value->SetInteger("visibleHeight", Height());
value->SetInteger("approximateBlankCharacterCount",
base::saturated_cast<int>(
@@ -655,7 +650,8 @@ std::unique_ptr<TracedValue> LocalFrameView::AnalyzerCounters() {
void LocalFrameView::PerformLayout(bool in_subtree_layout) {
DCHECK(in_subtree_layout || layout_subtree_root_list_.IsEmpty());
- int contents_height_before_layout = GetLayoutView()->DocumentRect().Height();
+ double contents_height_before_layout =
+ GetLayoutView()->DocumentRect().Height();
TRACE_EVENT_BEGIN1(
PERFORM_LAYOUT_TRACE_CATEGORIES, "LocalFrameView::performLayout",
"contentsHeightBeforeLayout", contents_height_before_layout);
@@ -1114,7 +1110,7 @@ void LocalFrameView::AddPartToUpdate(LayoutEmbeddedObject& object) {
part_update_set_.insert(&object);
}
-void LocalFrameView::SetDisplayMode(WebDisplayMode mode) {
+void LocalFrameView::SetDisplayMode(blink::mojom::DisplayMode mode) {
if (mode == display_mode_)
return;
@@ -1366,10 +1362,10 @@ void LocalFrameView::ProcessUrlFragment(const KURL& url,
bool should_scroll) {
// We want to create the anchor even if we don't need to scroll. This ensures
// all the side effects like setting CSS :target are correctly set.
- FragmentAnchor* anchor =
- FragmentAnchor::TryCreate(url, *frame_, same_document_navigation);
+ FragmentAnchor* anchor = FragmentAnchor::TryCreate(
+ url, *frame_, same_document_navigation, should_scroll);
- if (anchor && should_scroll) {
+ if (anchor) {
fragment_anchor_ = anchor;
fragment_anchor_->Installed();
@@ -1476,7 +1472,7 @@ void LocalFrameView::ClearLayoutSubtreeRootsAndMarkContainingBlocks() {
}
void LocalFrameView::AddOrthogonalWritingModeRoot(LayoutBox& root) {
- DCHECK(!root.IsLayoutScrollbarPart());
+ DCHECK(!root.IsLayoutCustomScrollbarPart());
orthogonal_writing_mode_root_list_.Add(root);
}
@@ -1836,10 +1832,7 @@ void LocalFrameView::PerformPostLayoutTasks() {
this->GetScrollingCoordinator()) {
scrolling_coordinator->NotifyGeometryChanged(this);
}
-
- if (SnapCoordinator* snap_coordinator =
- frame_->GetDocument()->GetSnapCoordinator())
- snap_coordinator->UpdateAllSnapContainerData();
+ frame_->GetDocument()->GetSnapCoordinator().UpdateAllSnapContainerData();
SendResizeEventIfNeeded();
}
@@ -1944,6 +1937,17 @@ Color LocalFrameView::DocumentBackgroundColor() const {
// backdrop.
if (Document* doc = frame_->GetDocument()) {
if (Element* element = Fullscreen::FullscreenElementFrom(*doc)) {
+ if (doc->IsImmersiveArOverlay()) {
+ // Use the fullscreened element's background directly. Don't bother
+ // blending with the backdrop since that's transparent.
+ if (LayoutObject* layout_object = element->GetLayoutObject()) {
+ return layout_object->ResolveColor(GetCSSPropertyBackgroundColor());
+ }
+ if (LayoutObject* layout_object =
+ element->PseudoElementLayoutObject(kPseudoIdBackdrop)) {
+ return layout_object->ResolveColor(GetCSSPropertyBackgroundColor());
+ }
+ }
if (LayoutObject* layout_object =
element->PseudoElementLayoutObject(kPseudoIdBackdrop)) {
return result.Blend(
@@ -2008,6 +2012,9 @@ void LocalFrameView::UpdateGeometriesIfNeeded() {
view->UpdateGeometry();
}
+ // Explicitly free the backing store to avoid memory regressions.
+ // TODO(bikineev): Revisit after young generation is there.
+ views.clear();
}
void LocalFrameView::UpdateAllLifecyclePhases(
@@ -2086,6 +2093,12 @@ void LocalFrameView::ScheduleVisualUpdateForPaintInvalidationIfNeeded() {
// phase of this cycle.
}
+void LocalFrameView::SetNeedsForcedResizeObservations() {
+ if (auto* controller =
+ GetFrame().GetDocument()->GetResizeObserverController())
+ controller->SetNeedsForcedResizeObservations();
+}
+
void LocalFrameView::NotifyResizeObservers() {
TRACE_EVENT0("blink,benchmark", "LocalFrameView::NotifyResizeObservers");
// Controller exists only if ResizeObserver was created.
@@ -2394,13 +2407,6 @@ bool LocalFrameView::RunCompositingLifecyclePhase(
#endif
}
- // We may be in kCompositingInputsClean clean, which does not need to notify
- // the global root scroller controller.
- if (target_state >= DocumentLifecycle::kCompositingClean) {
- frame_->GetPage()->GlobalRootScrollerController().DidUpdateCompositing(
- *this);
- }
-
return target_state > DocumentLifecycle::kCompositingClean;
}
@@ -2417,7 +2423,8 @@ bool LocalFrameView::RunPrePaintLifecyclePhase(
// PrePaintTreeWalk can reach this frame.
frame_view.SetNeedsPaintPropertyUpdate();
// We may record more foreign layers under the frame.
- frame_view.GraphicsLayersDidChange();
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ frame_view.SetForeignLayerListNeedsUpdate();
if (auto* owner = frame_view.GetLayoutEmbeddedContent())
owner->SetShouldCheckForPaintInvalidation();
}
@@ -2427,7 +2434,9 @@ bool LocalFrameView::RunPrePaintLifecyclePhase(
SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
LocalFrameUkmAggregator::kPrePaint);
+ GetPage()->GetLinkHighlight().UpdateBeforePrePaint();
PrePaintTreeWalk().WalkTree(*this);
+ GetPage()->GetLinkHighlight().UpdateAfterPrePaint();
}
UpdateCompositedSelectionIfNeeded();
@@ -2569,13 +2578,6 @@ static void RecordGraphicsLayerAsForeignLayer(
graphics_layer->GetPropertyTreeState());
}
-static void CollectViewportLayersForLayerList(GraphicsContext& context,
- VisualViewport& visual_viewport) {
- RecordGraphicsLayerAsForeignLayer(context, visual_viewport.ContainerLayer());
- RecordGraphicsLayerAsForeignLayer(context, visual_viewport.PageScaleLayer());
- RecordGraphicsLayerAsForeignLayer(context, visual_viewport.ScrollLayer());
-}
-
static void CollectDrawableLayersForLayerListRecursively(
GraphicsContext& context,
const GraphicsLayer* layer) {
@@ -2611,30 +2613,12 @@ static void CollectDrawableLayersForLayerListRecursively(
CollectDrawableLayersForLayerListRecursively(context, layer->MaskLayer());
}
-static void CollectLinkHighlightLayersForLayerListRecursively(
- GraphicsContext& context,
- const GraphicsLayer* layer) {
- if (!layer || layer->Client().ShouldThrottleRendering())
- return;
-
- for (auto* highlight : layer->GetLinkHighlights()) {
- auto property_tree_state = layer->GetPropertyTreeState();
- property_tree_state.SetEffect(highlight->Effect());
- RecordForeignLayer(
- context, DisplayItem::kForeignLayerLinkHighlight, highlight->Layer(),
- highlight->GetOffsetFromTransformNode(), property_tree_state);
- }
-
- for (const auto* child : layer->Children())
- CollectLinkHighlightLayersForLayerListRecursively(context, child);
-}
-
-static void PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
- layer->PaintRecursively();
-
+static bool PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
+ bool painted = layer->PaintRecursively();
#if DCHECK_IS_ON()
VerboseLogGraphicsLayerTree(layer);
#endif
+ return painted;
}
void LocalFrameView::PaintTree() {
@@ -2674,10 +2658,9 @@ void LocalFrameView::PaintTree() {
PaintInternal(graphics_context, kGlobalPaintNormalPhase,
CullRect::Infinite());
- frame_->GetPage()->GetLinkHighlights().Paint(graphics_context);
+ GetPage()->GetLinkHighlight().Paint(graphics_context);
- frame_->GetPage()->GetValidationMessageClient().PaintOverlay(
- graphics_context);
+ GetPage()->GetValidationMessageClient().PaintOverlay(graphics_context);
ForAllNonThrottledLocalFrameViews(
[&graphics_context](LocalFrameView& view) {
view.frame_->PaintFrameColorOverlay(graphics_context);
@@ -2697,25 +2680,21 @@ void LocalFrameView::PaintTree() {
// the host page and will be painted during painting of the host page.
if (GraphicsLayer* root_graphics_layer =
layout_view->Compositor()->PaintRootGraphicsLayer()) {
- PaintGraphicsLayerRecursively(root_graphics_layer);
+ bool painted = PaintGraphicsLayerRecursively(root_graphics_layer);
+ if (painted) {
+ // If the painted result changed, the painted hit test display items may
+ // have changed which will affect the mapped hit test geometry.
+ if (GetScrollingCoordinator())
+ GetScrollingCoordinator()->NotifyGeometryChanged(this);
+ }
}
-
- // This uses an invalidation approach based on graphics layer raster
- // invalidation so it must be after paint. This adds/removes link highlight
- // layers so it must be before
- // |CollectDrawableLayersForLayerListRecursively|.
- frame_->GetPage()->GetLinkHighlights().UpdateGeometry();
}
ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
if (auto* layout_view = frame_view.GetLayoutView())
layout_view->Layer()->ClearNeedsRepaintRecursively();
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- frame_view.GetFrame().GetDocument())) {
- frame_view.GetPaintTimingDetector().NotifyPaintFinished();
- }
+ frame_view.GetPaintTimingDetector().NotifyPaintFinished();
});
PaintController::ReportUMACounts();
@@ -2760,9 +2739,25 @@ void LocalFrameView::PushPaintArtifactToCompositor() {
PaintArtifactCompositor::ViewportProperties viewport_properties;
if (GetFrame().IsMainFrame()) {
const auto& viewport = page->GetVisualViewport();
+ viewport_properties.overscroll_elasticity_transform =
+ viewport.GetOverscrollElasticityTransformNode();
viewport_properties.page_scale = viewport.GetPageScaleNode();
viewport_properties.inner_scroll_translation =
viewport.GetScrollTranslationNode();
+
+ if (const auto* root_scroller =
+ GetPage()->GlobalRootScrollerController().GlobalRootScroller()) {
+ if (const auto* layout_object = root_scroller->GetLayoutObject()) {
+ if (const auto* paint_properties =
+ layout_object->FirstFragment().PaintProperties()) {
+ if (paint_properties->Scroll()) {
+ viewport_properties.outer_clip = paint_properties->OverflowClip();
+ viewport_properties.outer_scroll_translation =
+ paint_properties->ScrollTranslation();
+ }
+ }
+ }
+ }
}
PaintArtifactCompositor::Settings settings;
@@ -2775,30 +2770,28 @@ void LocalFrameView::PushPaintArtifactToCompositor() {
// collect the foreign layers, and this doesn't need caching. This shouldn't
// affect caching status of DisplayItemClients because FinishCycle() is
// not synchronized with other PaintControllers. This may live across frame
- // updates until GraphicsLayersDidChange() is called.
+ // updates until SetForeignLayerListNeedsUpdate() is called.
paint_controller_ =
std::make_unique<PaintController>(PaintController::kTransient);
GraphicsContext context(*paint_controller_);
- // Note: Some blink unit tests run without turning on compositing which
- // means we don't create viewport layers. OOPIFs also don't have their own
- // viewport layers.
- if (GetLayoutView()->Compositor()->InCompositingMode() &&
- GetFrame() == GetPage()->MainFrame()) {
- // TODO(bokan): We should eventually stop creating layers for the visual
- // viewport. At that point, we can remove this. However, for now, CC
- // still has some dependencies on the viewport scale and scroll layers.
- CollectViewportLayersForLayerList(context,
- frame_->GetPage()->GetVisualViewport());
+ // The inner viewport scroll layer is not drawable, but we still need to
+ // collect it in order to coordinate viewport scrolls.
+ if (frame_->IsMainFrame()) {
+ if (const auto* inner_scroll_layer =
+ frame_->GetPage()->GetVisualViewport().ScrollLayer()) {
+ DCHECK(!inner_scroll_layer->DrawsContent());
+ RecordGraphicsLayerAsForeignLayer(context, inner_scroll_layer);
+ }
}
// Before CompositeAfterPaint, |PaintRootGraphicsLayer| is the ancestor of
// all drawable layers (see: PaintLayerCompositor::PaintRootGraphicsLayer)
// so we do not need to collect scrollbars separately.
auto* root = GetLayoutView()->Compositor()->PaintRootGraphicsLayer();
CollectDrawableLayersForLayerListRecursively(context, root);
+
// Link highlights paint after all other layers.
- if (!frame_->GetPage()->GetLinkHighlights().IsEmpty())
- CollectLinkHighlightLayersForLayerListRecursively(context, root);
+ page->GetLinkHighlight().Paint(context);
paint_controller_->CommitNewDisplayItems();
}
@@ -2899,8 +2892,6 @@ void LocalFrameView::UpdateStyleAndLayoutIfNeededRecursive() {
frame_->GetDocument()->GetLayoutView()->AssertLaidOut();
#endif
- UpdateGeometriesIfNeeded();
-
if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
@@ -3335,26 +3326,9 @@ void LocalFrameView::TrackObjectPaintInvalidation(
tracked_object_paint_invalidations_->push_back(invalidation);
}
-void LocalFrameView::AddResizerArea(LayoutBox& resizer_box) {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
- if (!resizer_areas_)
- resizer_areas_ = std::make_unique<ResizerAreaSet>();
- resizer_areas_->insert(&resizer_box);
-}
-
-void LocalFrameView::RemoveResizerArea(LayoutBox& resizer_box) {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
- if (!resizer_areas_)
- return;
-
- ResizerAreaSet::iterator it = resizer_areas_->find(&resizer_box);
- if (it != resizer_areas_->end())
- resizer_areas_->erase(it);
-}
-
-void LocalFrameView::ScheduleAnimation() {
+void LocalFrameView::ScheduleAnimation(base::TimeDelta delay) {
if (auto* client = GetChromeClient())
- client->ScheduleAnimation(this);
+ client->ScheduleAnimation(this, delay);
}
bool LocalFrameView::FrameIsScrollableDidChange() {
@@ -3941,12 +3915,11 @@ bool LocalFrameView::UpdateViewportIntersectionsForSubtree(
child->View()->UpdateViewportIntersectionsForSubtree(flags);
}
- for (HTMLPortalElement* portal :
+ for (PortalContents* portal :
DocumentPortals::From(*frame_->GetDocument()).GetPortals()) {
- if (portal->ContentFrame()) {
+ if (Frame* frame = portal->GetFrame()) {
needs_occlusion_tracking |=
- portal->ContentFrame()->View()->UpdateViewportIntersectionsForSubtree(
- flags);
+ frame->View()->UpdateViewportIntersectionsForSubtree(flags);
}
}
@@ -3995,7 +3968,8 @@ void LocalFrameView::RenderThrottlingStatusChanged() {
DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->InStyleRecalc());
// We may record more/less foreign layers under the frame.
- GraphicsLayersDidChange();
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ SetForeignLayerListNeedsUpdate();
if (!CanThrottleRendering())
InvalidateForThrottlingChange();
@@ -4056,10 +4030,12 @@ void LocalFrameView::SetPaintArtifactCompositorNeedsUpdate() {
root->paint_artifact_compositor_->SetNeedsUpdate();
}
-void LocalFrameView::GraphicsLayersDidChange() {
- LocalFrameView* root = GetFrame().LocalFrameRoot().View();
- if (root) {
- // We will re-collect GraphicsLayers in PushPaintArtifactsToCompositor().
+void LocalFrameView::SetForeignLayerListNeedsUpdate() {
+ DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
+ DCHECK_NE(Lifecycle().GetState(), DocumentLifecycle::kInPaint);
+
+ if (LocalFrameView* root = GetFrame().LocalFrameRoot().View()) {
+ // We will re-collect foreign layers in PushPaintArtifactsToCompositor().
root->paint_controller_ = nullptr;
if (root->paint_artifact_compositor_)
root->paint_artifact_compositor_->SetNeedsUpdate();
@@ -4181,12 +4157,11 @@ void LocalFrameView::BeginLifecycleUpdates() {
// and we do not want to defer a second time if we have already done
// so once and resumed commits already.
if (document &&
- base::FeatureList::IsEnabled(
- blink::features::kAvoidFlashBetweenNavigation) &&
+ base::FeatureList::IsEnabled(blink::features::kPaintHolding) &&
document->DeferredCompositorCommitIsAllowed() &&
!have_deferred_commits_) {
- chrome_client.StartDeferringCommits(
- GetFrame(), GetCommitDelayForAvoidFlashBetweenNavigation());
+ chrome_client.StartDeferringCommits(GetFrame(),
+ GetCommitDelayForPaintHolding());
have_deferred_commits_ = true;
}
@@ -4316,8 +4291,8 @@ void LocalFrameView::ApplyTransformForTopFrameSpace(
}
LayoutUnit LocalFrameView::CaretWidth() const {
- return LayoutUnit(
- std::max<float>(1.0, GetChromeClient()->WindowToViewportScalar(1)));
+ return LayoutUnit(std::max<float>(
+ 1.0f, GetChromeClient()->WindowToViewportScalar(&GetFrame(), 1.0f)));
}
LocalFrameUkmAggregator& LocalFrameView::EnsureUkmAggregator() {
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 f321bda41db..638ba2a3b9e 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
@@ -28,8 +28,8 @@
#include <memory>
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
-#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/shape_properties.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
@@ -114,7 +114,7 @@ struct LifecycleData {
};
class CORE_EXPORT LocalFrameView final
- : public GarbageCollectedFinalized<LocalFrameView>,
+ : public GarbageCollected<LocalFrameView>,
public FrameView {
USING_GARBAGE_COLLECTED_MIXIN(LocalFrameView);
@@ -215,7 +215,7 @@ class CORE_EXPORT LocalFrameView final
void ForceUpdateViewportIntersections();
void SetPaintArtifactCompositorNeedsUpdate();
- void GraphicsLayersDidChange();
+ void SetForeignLayerListNeedsUpdate();
// Marks this frame, and ancestor frames, as needing a mandatory compositing
// update. This overrides throttling for one frame, up to kCompositingClean.
@@ -273,8 +273,8 @@ class CORE_EXPORT LocalFrameView final
void SetMediaType(const AtomicString&);
void AdjustMediaTypeForPrinting(bool printing);
- WebDisplayMode DisplayMode() { return display_mode_; }
- void SetDisplayMode(WebDisplayMode);
+ blink::mojom::DisplayMode DisplayMode() { return display_mode_; }
+ void SetDisplayMode(blink::mojom::DisplayMode);
DisplayShape GetDisplayShape() { return display_shape_; }
void SetDisplayShape(DisplayShape);
@@ -460,21 +460,7 @@ class CORE_EXPORT LocalFrameView final
return animating_scrollable_areas_.Get();
}
- // With CSS style "resize:" enabled, a little resizer handle will appear at
- // the bottom right of the object. We keep track of these resizer areas for
- // checking if touches (implemented using Scroll gesture) are targeting the
- // resizer.
- // TODO(pdr): The resizers do not need to be tracked with
- // PaintNonFastScrollableRegions and can be removed once that ships.
- typedef HashSet<LayoutBox*> ResizerAreaSet;
- void AddResizerArea(LayoutBox&);
- void RemoveResizerArea(LayoutBox&);
- const ResizerAreaSet* ResizerAreas() const {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
- return resizer_areas_.get();
- }
-
- void ScheduleAnimation();
+ void ScheduleAnimation(base::TimeDelta = base::TimeDelta());
// FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter
// passed around the LocalFrameView layout methods can be true while this
@@ -700,6 +686,10 @@ class CORE_EXPORT LocalFrameView final
void RegisterForLifecycleNotifications(LifecycleNotificationObserver*);
void UnregisterFromLifecycleNotifications(LifecycleNotificationObserver*);
+ // Sets whether all ResizeObservers should check all their ResizeObservations
+ // for a resize. This is needed when exiting a display lock.
+ void SetNeedsForcedResizeObservations();
+
protected:
void FrameRectsChanged(const IntRect&) override;
void SelfVisibleChanged() override;
@@ -848,7 +838,7 @@ class CORE_EXPORT LocalFrameView final
Member<LocalFrame> frame_;
- WebDisplayMode display_mode_;
+ blink::mojom::DisplayMode display_mode_;
DisplayShape display_shape_;
@@ -884,7 +874,6 @@ class CORE_EXPORT LocalFrameView final
Member<ScrollableAreaSet> scrollable_areas_;
Member<ScrollableAreaSet> animating_scrollable_areas_;
- std::unique_ptr<ResizerAreaSet> resizer_areas_;
std::unique_ptr<ObjectSet> viewport_constrained_objects_;
unsigned sticky_position_object_count_;
ObjectSet background_attachment_fixed_objects_;
@@ -961,9 +950,9 @@ class CORE_EXPORT LocalFrameView final
std::unique_ptr<Vector<ObjectPaintInvalidation>>
tracked_object_paint_invalidations_;
- // Currently used in PushPaintArtifactToCompositor() to collect GraphicsLayers
- // as foreign layers. It's transient, but may live across frame updates until
- // GraphicsLayersDidChange() is called.
+ // Currently used in PushPaintArtifactToCompositor() to collect composited
+ // layers as foreign layers. It's transient, but may live across frame updates
+ // until SetForeignLayerListNeedsUpdate() is called.
// For CompositeAfterPaint, we use it in PaintTree() for all paintings of the
// frame tree in PaintTree(). It caches display items and subsequences across
// frame updates and repaints.
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 ca2e05bc266..0c9c6049567 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
@@ -42,7 +42,8 @@ class AnimationMockChromeClient : public RenderingTestChromeClient {
MockSetToolTip(&frame, tooltip_text, dir);
}
- void ScheduleAnimation(const LocalFrameView*) override {
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) override {
has_scheduled_animation_ = true;
}
bool has_scheduled_animation_;
diff --git a/chromium/third_party/blink/renderer/core/frame/location.cc b/chromium/third_party/blink/renderer/core/frame/location.cc
index 2eb0735cfdc..3acc96e03fb 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.cc
+++ b/chromium/third_party/blink/renderer/core/frame/location.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/dom_window.h"
+#include "third_party/blink/renderer/core/frame/fragment_directive.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
@@ -45,10 +46,13 @@
namespace blink {
-Location::Location(DOMWindow* dom_window) : dom_window_(dom_window) {}
+Location::Location(DOMWindow* dom_window)
+ : dom_window_(dom_window),
+ fragment_directive_(MakeGarbageCollected<FragmentDirective>()) {}
void Location::Trace(blink::Visitor* visitor) {
visitor->Trace(dom_window_);
+ visitor->Trace(fragment_directive_);
ScriptWrappable::Trace(visitor);
}
@@ -95,6 +99,10 @@ String Location::origin() const {
return DOMURLUtilsReadOnly::origin(Url());
}
+FragmentDirective* Location::fragmentDirective() const {
+ return fragment_directive_;
+}
+
DOMStringList* Location::ancestorOrigins() const {
auto* origins = MakeGarbageCollected<DOMStringList>();
if (!IsAttached())
diff --git a/chromium/third_party/blink/renderer/core/frame/location.h b/chromium/third_party/blink/renderer/core/frame/location.h
index 2b8601a2411..12b6870b0d3 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.h
+++ b/chromium/third_party/blink/renderer/core/frame/location.h
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/frame/dom_window.h"
+#include "third_party/blink/renderer/core/frame/fragment_directive.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -82,6 +83,8 @@ class CORE_EXPORT Location final : public ScriptWrappable {
DOMStringList* ancestorOrigins() const;
+ FragmentDirective* fragmentDirective() const;
+
// Just return the |this| object the way the normal valueOf function on the
// Object prototype would. The valueOf function is only added to make sure
// that it cannot be overwritten on location objects, since that would provide
@@ -112,6 +115,8 @@ class CORE_EXPORT Location final : public ScriptWrappable {
const KURL& Url() const;
const Member<DOMWindow> dom_window_;
+
+ Member<FragmentDirective> fragment_directive_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/location.idl b/chromium/third_party/blink/renderer/core/frame/location.idl
index ea47333ddb7..bfcda81941f 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.idl
+++ b/chromium/third_party/blink/renderer/core/frame/location.idl
@@ -59,6 +59,8 @@
[SetterCallWith=Isolate, RaisesException=Setter, Unforgeable] attribute USVString search;
[SetterCallWith=Isolate, RaisesException=Setter, Unforgeable] attribute USVString hash;
+ [RuntimeEnabled=TextFragmentIdentifiers] readonly attribute FragmentDirective fragmentDirective;
+
// TODO(foolip): Location does not have a valueOf() override in the spec.
// See the comment in Location.h for the purpose of this.
[NotEnumerable, CallWith=ThisValue, Unforgeable] any valueOf();
diff --git a/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc b/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
index 2ad126cc3d5..87d5b91b6d6 100644
--- a/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
@@ -28,10 +28,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
+
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
+#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_parser.h"
#include "third_party/blink/renderer/platform/mhtml/serialized_resource.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc
index 0ff6b8de2fb..bf27a5e20fc 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
@@ -87,9 +87,11 @@ class V8FunctionExecutor : public PausableScriptExecutor::Executor {
Vector<v8::Local<v8::Value>> Execute(LocalFrame*) override;
+ void Trace(Visitor*) override;
+
private:
- ScopedPersistent<v8::Function> function_;
- ScopedPersistent<v8::Value> receiver_;
+ TraceWrapperV8Reference<v8::Function> function_;
+ TraceWrapperV8Reference<v8::Value> receiver_;
V8PersistentValueVector<v8::Value> args_;
};
@@ -126,6 +128,12 @@ Vector<v8::Local<v8::Value>> V8FunctionExecutor::Execute(LocalFrame* frame) {
return results;
}
+void V8FunctionExecutor::Trace(Visitor* visitor) {
+ visitor->Trace(function_);
+ visitor->Trace(receiver_);
+ PausableScriptExecutor::Executor::Trace(visitor);
+}
+
} // namespace
void PausableScriptExecutor::CreateAndRun(
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
index fd4a7af318b..59374a677fd 100644
--- a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
+++ b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
@@ -22,7 +22,7 @@ class ScriptState;
class WebScriptExecutionCallback;
class CORE_EXPORT PausableScriptExecutor final
- : public GarbageCollectedFinalized<PausableScriptExecutor>,
+ : public GarbageCollected<PausableScriptExecutor>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(PausableScriptExecutor);
@@ -38,7 +38,7 @@ class CORE_EXPORT PausableScriptExecutor final
v8::Local<v8::Value> argv[],
WebScriptExecutionCallback*);
- class Executor : public GarbageCollectedFinalized<Executor> {
+ class Executor : public GarbageCollected<Executor> {
public:
virtual ~Executor() = default;
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 7f1e3a172c4..0fe1294cde8 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
@@ -39,7 +39,7 @@ class SourceLocation;
// Long task notifications are delivered to observing WindowPerformance*
// instances (in the local frame tree) in m_webPerformanceObservers.
class CORE_EXPORT PerformanceMonitor final
- : public GarbageCollectedFinalized<PerformanceMonitor>,
+ : public GarbageCollected<PerformanceMonitor>,
public base::sequence_manager::TaskTimeObserver {
public:
enum Violation : size_t {
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 0f08617bce5..ff0e9a50e02 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
@@ -20,7 +20,7 @@ class ScriptPromiseResolver;
// for a video element in Blink outside of modules/ module. It
// is an interface that the module will implement and add a provider for.
class CORE_EXPORT PictureInPictureController
- : public GarbageCollectedFinalized<PictureInPictureController>,
+ : public GarbageCollected<PictureInPictureController>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(PictureInPictureController);
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 209e34eb913..c8f00ab5c8a 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -46,6 +46,7 @@ RemoteFrame::RemoteFrame(RemoteFrameClient* client,
dom_window_ = MakeGarbageCollected<RemoteDOMWindow>(*this);
UpdateInertIfPossible();
UpdateInheritedEffectiveTouchActionIfPossible();
+ UpdateVisibleToHitTesting();
Initialize();
}
@@ -71,12 +72,13 @@ void RemoteFrame::Navigate(const FrameLoadRequest& passed_request,
: network::mojom::RequestContextFrameType::kNested);
const KURL& url = frame_request.GetResourceRequest().Url();
- if (frame_request.OriginDocument() &&
- !frame_request.OriginDocument()->GetSecurityOrigin()->CanDisplay(url)) {
- frame_request.OriginDocument()->AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kSecurity,
- mojom::ConsoleMessageLevel::kError,
- "Not allowed to load local resource: " + url.ElidedString()));
+ if (!frame_request.CanDisplay(url)) {
+ if (frame_request.OriginDocument()) {
+ frame_request.OriginDocument()->AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kSecurity,
+ mojom::ConsoleMessageLevel::kError,
+ "Not allowed to load local resource: " + url.ElidedString()));
+ }
return;
}
@@ -167,14 +169,6 @@ bool RemoteFrame::ShouldClose() {
return true;
}
-void RemoteFrame::DidFreeze() {
- // TODO(fmeawad): Add support for remote frames.
-}
-
-void RemoteFrame::DidResume() {
- // TODO(fmeawad): Add support for remote frames.
-}
-
void RemoteFrame::SetIsInert(bool inert) {
if (inert != is_inert_)
Client()->SetIsInert(inert);
@@ -221,7 +215,7 @@ RemoteFrameClient* RemoteFrame::Client() const {
return static_cast<RemoteFrameClient*>(Frame::Client());
}
-void RemoteFrame::PointerEventsChanged() {
+void RemoteFrame::DidChangeVisibleToHitTesting() {
if (!cc_layer_ || !is_surface_layer_)
return;
@@ -233,9 +227,9 @@ bool RemoteFrame::IsIgnoredForHitTest() const {
HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
if (!owner || !owner->GetLayoutObject())
return false;
+
return owner->OwnerType() == FrameOwnerElementType::kPortal ||
- (owner->GetLayoutObject()->Style()->PointerEvents() ==
- EPointerEvents::kNone);
+ !visible_to_hit_testing_;
}
void RemoteFrame::SetCcLayer(cc::Layer* cc_layer,
@@ -250,7 +244,10 @@ void RemoteFrame::SetCcLayer(cc::Layer* cc_layer,
is_surface_layer_ = is_surface_layer;
if (cc_layer_) {
GraphicsLayer::RegisterContentsLayer(cc_layer_);
- PointerEventsChanged();
+ if (is_surface_layer) {
+ static_cast<cc::SurfaceLayer*>(cc_layer_)->SetHasPointerEventsNone(
+ IsIgnoredForHitTest());
+ }
}
To<HTMLFrameOwnerElement>(Owner())->SetNeedsCompositingUpdate();
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 c124278baf0..300b422db50 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.h
@@ -39,8 +39,6 @@ class CORE_EXPORT RemoteFrame final : public Frame {
bool DetachDocument() override;
void CheckCompleted() override;
bool ShouldClose() override;
- void DidFreeze() override;
- void DidResume() override;
void HookBackForwardCacheEviction() override {}
void RemoveBackForwardCacheEviction() override {}
void SetIsInert(bool) override;
@@ -66,9 +64,10 @@ class CORE_EXPORT RemoteFrame final : public Frame {
RemoteFrameClient* Client() const;
- void PointerEventsChanged();
bool IsIgnoredForHitTest() const;
+ void DidChangeVisibleToHitTesting() override;
+
private:
// Frame protected overrides:
void DetachImpl(FrameDetachType) override;
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h
index ebde84ea840..0e54fb21e07 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
@@ -7,7 +7,7 @@
#include "cc/paint/paint_canvas.h"
#include "third_party/blink/public/common/frame/occlusion_state.h"
-#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
index 31afc440ffc..5e5e7f351e3 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_owner.h
@@ -21,7 +21,7 @@ namespace blink {
// its owner element in another process.
// 2. Trigger a load event on its owner element once it finishes a load.
class CORE_EXPORT RemoteFrameOwner final
- : public GarbageCollectedFinalized<RemoteFrameOwner>,
+ : public GarbageCollected<RemoteFrameOwner>,
public FrameOwner {
USING_GARBAGE_COLLECTED_MIXIN(RemoteFrameOwner);
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 020896fe22d..39a5e08349a 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
@@ -7,7 +7,7 @@
#include "cc/paint/paint_canvas.h"
#include "third_party/blink/public/common/frame/occlusion_state.h"
-#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
@@ -24,7 +24,7 @@ class GraphicsContext;
class LocalFrameView;
class RemoteFrame;
-class RemoteFrameView final : public GarbageCollectedFinalized<RemoteFrameView>,
+class RemoteFrameView final : public GarbageCollected<RemoteFrameView>,
public FrameView {
USING_GARBAGE_COLLECTED_MIXIN(RemoteFrameView);
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 c463cb5af0b..ab5ca79012e 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.h
@@ -21,7 +21,7 @@ class ReportingObserver;
// ReportingContext processes all reports for an ExecutionContext, and serves as
// a container for all active ReportingObservers on that ExecutionContext.
class CORE_EXPORT ReportingContext final
- : public GarbageCollectedFinalized<ReportingContext>,
+ : public GarbageCollected<ReportingContext>,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(ReportingContext);
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 032ce3bffdf..20c0849668e 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
@@ -311,7 +311,7 @@ PhysicalRect RootFrameViewport::ScrollIntoView(
end_point = GetLayoutBox()
->GetDocument()
.GetSnapCoordinator()
- ->GetSnapPosition(*GetLayoutBox(), *strategy)
+ .GetSnapPosition(*GetLayoutBox(), *strategy)
.value_or(end_point);
new_scroll_offset = ScrollPositionToOffset(end_point);
}
@@ -445,10 +445,6 @@ bool RootFrameViewport::ScrollbarsCanBeActive() const {
return LayoutViewport().ScrollbarsCanBeActive();
}
-IntRect RootFrameViewport::ScrollableAreaBoundingBox() const {
- return LayoutViewport().ScrollableAreaBoundingBox();
-}
-
bool RootFrameViewport::UserInputScrollable(
ScrollbarOrientation orientation) const {
return VisualViewport().UserInputScrollable(orientation) ||
@@ -463,10 +459,6 @@ void RootFrameViewport::ScrollControlWasSetNeedsPaintInvalidation() {
LayoutViewport().ScrollControlWasSetNeedsPaintInvalidation();
}
-GraphicsLayer* RootFrameViewport::LayerForContainer() const {
- return LayoutViewport().LayerForContainer();
-}
-
GraphicsLayer* RootFrameViewport::LayerForScrolling() const {
return LayoutViewport().LayerForScrolling();
}
@@ -614,6 +606,15 @@ ScrollbarTheme& RootFrameViewport::GetPageScrollbarTheme() const {
return LayoutViewport().GetPageScrollbarTheme();
}
+const cc::SnapContainerData* RootFrameViewport::GetSnapContainerData() const {
+ return LayoutViewport().GetSnapContainerData();
+}
+
+void RootFrameViewport::SetSnapContainerData(
+ base::Optional<cc::SnapContainerData> data) {
+ LayoutViewport().SetSnapContainerData(data);
+}
+
void RootFrameViewport::Trace(blink::Visitor* visitor) {
visitor->Trace(visual_viewport_);
visitor->Trace(layout_viewport_);
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 4b49885071a..9622a32ddf3 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
@@ -27,7 +27,7 @@ struct WebScrollIntoViewParams;
// the layout viewport. Thus, we could say this class is a decorator on the
// LocalFrameView scrollable area that adds pinch-zoom semantics to scrolling.
class CORE_EXPORT RootFrameViewport final
- : public GarbageCollectedFinalized<RootFrameViewport>,
+ : public GarbageCollected<RootFrameViewport>,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(RootFrameViewport);
@@ -87,11 +87,9 @@ class CORE_EXPORT RootFrameViewport final
ScrollOffset ClampScrollOffset(const ScrollOffset&) const override;
IntSize ContentsSize() const override;
bool ScrollbarsCanBeActive() const override;
- IntRect ScrollableAreaBoundingBox() const override;
bool UserInputScrollable(ScrollbarOrientation) const override;
bool ShouldPlaceVerticalScrollbarOnLeft() const override;
void ScrollControlWasSetNeedsPaintInvalidation() override;
- GraphicsLayer* LayerForContainer() const override;
GraphicsLayer* LayerForScrolling() const override;
GraphicsLayer* LayerForHorizontalScrollbar() const override;
GraphicsLayer* LayerForVerticalScrollbar() const override;
@@ -123,6 +121,8 @@ class CORE_EXPORT RootFrameViewport final
unsigned = 0) const final;
scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final;
ScrollbarTheme& GetPageScrollbarTheme() const override;
+ const cc::SnapContainerData* GetSnapContainerData() const override;
+ void SetSnapContainerData(base::Optional<cc::SnapContainerData>) override;
private:
FRIEND_TEST_ALL_PREFIXES(RootFrameViewportTest, DistributeScrollOrder);
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
index 7b160673f98..e49230efb2e 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
@@ -25,7 +25,7 @@ blink::ScrollbarThemeMock scrollbar_theme_;
namespace blink {
-class ScrollableAreaStub : public GarbageCollectedFinalized<ScrollableAreaStub>,
+class ScrollableAreaStub : public GarbageCollected<ScrollableAreaStub>,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(ScrollableAreaStub);
@@ -103,10 +103,8 @@ class ScrollableAreaStub : public GarbageCollectedFinalized<ScrollableAreaStub>,
bool IsScrollCornerVisible() const override { return true; }
IntRect ScrollCornerRect() const override { return IntRect(); }
bool ScrollbarsCanBeActive() const override { return true; }
- IntRect ScrollableAreaBoundingBox() const override { return IntRect(); }
bool ShouldPlaceVerticalScrollbarOnLeft() const override { return true; }
void ScrollControlWasSetNeedsPaintInvalidation() override {}
- GraphicsLayer* LayerForContainer() const override { return nullptr; }
GraphicsLayer* LayerForScrolling() const override { return nullptr; }
GraphicsLayer* LayerForHorizontalScrollbar() const override {
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
index 7425a5eb34f..bed022e676f 100644
--- a/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
+++ b/chromium/third_party/blink/renderer/core/frame/sandbox_flags.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/public/common/frame/sandbox_flags.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
@@ -111,6 +112,10 @@ WebSandboxFlags ParseSandboxPolicy(const SpaceSplitString& policy,
} else if (EqualIgnoringASCIICase(
sandbox_token, "allow-downloads-without-user-activation")) {
flags = flags & ~WebSandboxFlags::kDownloads;
+ } else if (RuntimeEnabledFeatures::StorageAccessAPIEnabled() &&
+ EqualIgnoringASCIICase(
+ sandbox_token, "allow-storage-access-by-user-activation")) {
+ flags = flags & ~WebSandboxFlags::kStorageAccessByUserActivation;
} else {
token_errors.Append(token_errors.IsEmpty() ? "'" : ", '");
token_errors.Append(sandbox_token);
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.cc b/chromium/third_party/blink/renderer/core/frame/scheduling.cc
index 817fee12159..c9ca978675e 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.cc
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.cc
@@ -61,4 +61,9 @@ bool Scheduling::isInputPending(ScriptState* script_state,
return has_pending_input;
}
+bool Scheduling::isFramePending() const {
+ auto* scheduler = ThreadScheduler::Current();
+ return scheduler->IsBeginMainFrameScheduled();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.h b/chromium/third_party/blink/renderer/core/frame/scheduling.h
index ebd1564b48e..55df6f89981 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.h
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.h
@@ -18,6 +18,7 @@ class Scheduling : public ScriptWrappable {
public:
bool isInputPending(ScriptState*, const Vector<String>& input_types) const;
+ bool isFramePending() const;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/scheduling.idl b/chromium/third_party/blink/renderer/core/frame/scheduling.idl
index 61441a9a740..c1ae6538e09 100644
--- a/chromium/third_party/blink/renderer/core/frame/scheduling.idl
+++ b/chromium/third_party/blink/renderer/core/frame/scheduling.idl
@@ -5,5 +5,6 @@
// https://github.com/tdresser/is-input-pending
[RuntimeEnabled=ExperimentalIsInputPending]
interface Scheduling {
+ [RuntimeEnabled=ExperimentalIsInputPending] boolean isFramePending();
[CallWith=ScriptState, MeasureAs=SchedulingIsInputPending, RuntimeEnabled=ExperimentalIsInputPending] boolean isInputPending(optional sequence<DOMString> inputTypes = []);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/screen.cc b/chromium/third_party/blink/renderer/core/frame/screen.cc
index f31ab99b2c4..5d9629ceaa1 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen.cc
+++ b/chromium/third_party/blink/renderer/core/frame/screen.cc
@@ -38,106 +38,106 @@
namespace blink {
+namespace {
+
+WebScreenInfo GetScreenInfo(LocalFrame& frame) {
+ return frame.GetChromeClient().GetScreenInfo(frame);
+}
+
+} // namespace
+
Screen::Screen(LocalFrame* frame) : DOMWindowClient(frame) {}
int Screen::height() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(
lroundf(screen_info.rect.height * screen_info.device_scale_factor));
}
- return page->GetChromeClient().GetScreenInfo().rect.height;
+ return GetScreenInfo(*frame).rect.height;
}
int Screen::width() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(
lroundf(screen_info.rect.width * screen_info.device_scale_factor));
}
- return page->GetChromeClient().GetScreenInfo().rect.width;
+ return GetScreenInfo(*frame).rect.width;
}
unsigned Screen::colorDepth() const {
- if (!GetFrame() || !GetFrame()->GetPage())
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
- return static_cast<unsigned>(
- GetFrame()->GetPage()->GetChromeClient().GetScreenInfo().depth);
+ return static_cast<unsigned>(GetScreenInfo(*frame).depth);
}
unsigned Screen::pixelDepth() const {
- if (!GetFrame())
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
- return static_cast<unsigned>(
- GetFrame()->GetPage()->GetChromeClient().GetScreenInfo().depth);
+ return static_cast<unsigned>(GetScreenInfo(*frame).depth);
}
int Screen::availLeft() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(lroundf(screen_info.available_rect.x *
screen_info.device_scale_factor));
}
- return static_cast<int>(
- page->GetChromeClient().GetScreenInfo().available_rect.x);
+ return static_cast<int>(GetScreenInfo(*frame).available_rect.x);
}
int Screen::availTop() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(lroundf(screen_info.available_rect.y *
screen_info.device_scale_factor));
}
- return static_cast<int>(
- page->GetChromeClient().GetScreenInfo().available_rect.y);
+ return static_cast<int>(GetScreenInfo(*frame).available_rect.y);
}
int Screen::availHeight() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(lroundf(screen_info.available_rect.height *
screen_info.device_scale_factor));
}
- return page->GetChromeClient().GetScreenInfo().available_rect.height;
+ return GetScreenInfo(*frame).available_rect.height;
}
int Screen::availWidth() const {
- if (!GetFrame())
- return 0;
- Page* page = GetFrame()->GetPage();
- if (!page)
+ LocalFrame* frame = GetFrame();
+ if (!frame)
return 0;
+ Page* page = frame->GetPage();
if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
- WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+ WebScreenInfo screen_info = GetScreenInfo(*frame);
return static_cast<int>(lroundf(screen_info.available_rect.width *
screen_info.device_scale_factor));
}
- return page->GetChromeClient().GetScreenInfo().available_rect.width;
+ return GetScreenInfo(*frame).available_rect.width;
}
void Screen::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h b/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h
index 72d44952932..4fe5279e0b1 100644
--- a/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h
+++ b/chromium/third_party/blink/renderer/core/frame/screen_orientation_controller.h
@@ -20,7 +20,7 @@ class WebLockOrientationCallback;
// Callers of ScreenOrientationController::from() should always assume the
// returned pointer can be nullptr.
class CORE_EXPORT ScreenOrientationController
- : public GarbageCollectedFinalized<ScreenOrientationController>,
+ : public GarbageCollected<ScreenOrientationController>,
public Supplement<LocalFrame> {
USING_GARBAGE_COLLECTED_MIXIN(ScreenOrientationController);
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.cc b/chromium/third_party/blink/renderer/core/frame/settings.cc
index 875f17ebef7..a5781d544b3 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.cc
+++ b/chromium/third_party/blink/renderer/core/frame/settings.cc
@@ -107,13 +107,7 @@ void Settings::SetForceDarkModeEnabled(bool enabled) {
if (force_dark_mode_ == enabled)
return;
force_dark_mode_ = enabled;
-
- if (force_dark_mode_) {
- SetDarkMode(DarkMode::kInvertLightnessLAB);
- SetDarkModeImagePolicy(DarkModeImagePolicy::kFilterSmart);
- } else {
- SetDarkMode(DarkMode::kOff);
- }
+ SetDarkModeEnabled(force_dark_mode_);
Invalidate(SettingsDelegate::kColorSchemeChange);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.h b/chromium/third_party/blink/renderer/core/frame/settings.h
index 5c4091123f8..fc30f6b2724 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.h
+++ b/chromium/third_party/blink/renderer/core/frame/settings.h
@@ -31,9 +31,9 @@
#include <memory>
#include "base/macros.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/common/css/preferred_color_scheme.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/public/platform/pointer_properties.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_viewport_style.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.json5 b/chromium/third_party/blink/renderer/core/frame/settings.json5
index 5c0ba774e7c..4f8a89ef7be 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.json5
+++ b/chromium/third_party/blink/renderer/core/frame/settings.json5
@@ -489,9 +489,9 @@
},
{
name: "displayModeOverride",
- initial: "kWebDisplayModeUndefined",
+ initial: "blink::mojom::DisplayMode::kUndefined",
invalidate: "MediaQuery",
- type: "WebDisplayMode",
+ type: "blink::mojom::DisplayMode",
},
// loadsImagesAutomatically only suppresses the network load of
@@ -884,9 +884,14 @@
// Dark mode
//
{
- name: "darkMode",
- initial: "DarkMode::kOff",
- type: "DarkMode",
+ name: "darkModeEnabled",
+ initial: false,
+ invalidate: "Paint",
+ },
+ {
+ name: "darkModeInversionAlgorithm",
+ initial: "DarkModeInversionAlgorithm::kInvertLightnessLAB",
+ type: "DarkModeInversionAlgorithm",
invalidate: "Paint",
},
{
@@ -1021,6 +1026,34 @@
initial: 3000,
type: "int",
},
+ //
+ // Count of the images to fully load for different effective connection types.
+ //
+ {
+ name: "lazyImageFirstKFullyLoadUnknown",
+ initial: 0,
+ type: "int",
+ },
+ {
+ name: "lazyImageFirstKFullyLoadSlow2G",
+ initial: 12,
+ type: "int",
+ },
+ {
+ name: "lazyImageFirstKFullyLoad2G",
+ initial: 10,
+ type: "int",
+ },
+ {
+ name: "lazyImageFirstKFullyLoad3G",
+ initial: 8,
+ type: "int",
+ },
+ {
+ name: "lazyImageFirstKFullyLoad4G",
+ initial: 6,
+ type: "int",
+ },
// Preferred color scheme from the OS/application passed to the renderer for
// evaluating the prefers-color-scheme media query.
@@ -1042,13 +1075,13 @@
name: "DontSendKeyEventsToJavascript",
initial: false,
},
- // Forced colors from the OS/application passed to the renderer for
- // evaluating the forced-colors media query.
+ // Navigation controls from the application passed to the renderer for
+ // evaluating the navigation-controls media query.
{
- name: "forcedColors",
- initial: "ForcedColors::kNone",
- invalidate: "ColorScheme",
- type: "ForcedColors",
+ name: "navigationControls",
+ initial: "NavigationControls::kNone",
+ invalidate: "MediaQuery",
+ type: "NavigationControls",
},
],
}
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter_helper.h b/chromium/third_party/blink/renderer/core/frame/use_counter_helper.h
index 6c12e3e908b..5b3a64628d1 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter_helper.h
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter_helper.h
@@ -28,7 +28,7 @@
#include <bitset>
#include "base/macros.h"
-#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
+#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink-forward.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/parser/css_parser_mode.h"
diff --git a/chromium/third_party/blink/renderer/core/frame/viewport_data.cc b/chromium/third_party/blink/renderer/core/frame/viewport_data.cc
index edec6c1fd77..043605a27b8 100644
--- a/chromium/third_party/blink/renderer/core/frame/viewport_data.cc
+++ b/chromium/third_party/blink/renderer/core/frame/viewport_data.cc
@@ -21,8 +21,6 @@ void ViewportData::Trace(Visitor* visitor) {
}
void ViewportData::Shutdown() {
- // TODO(https://crbug.com/800641): Use InterfaceInvalidator once it works with
- // associated interfaces.
display_cutout_host_.reset();
}
diff --git a/chromium/third_party/blink/renderer/core/frame/viewport_data.h b/chromium/third_party/blink/renderer/core/frame/viewport_data.h
index 439b0a22330..050c4c5ec34 100644
--- a/chromium/third_party/blink/renderer/core/frame/viewport_data.h
+++ b/chromium/third_party/blink/renderer/core/frame/viewport_data.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_VIEWPORT_DATA_H_
#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -15,7 +15,7 @@ namespace blink {
class Document;
-class ViewportData : public GarbageCollectedFinalized<ViewportData> {
+class ViewportData final : public GarbageCollected<ViewportData> {
public:
ViewportData(Document& document);
void Trace(Visitor* visitor);
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 b87ef4293ed..1b4e8c96869 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -34,7 +34,7 @@
#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/layers/picture_layer.h"
-#include "cc/layers/scrollbar_layer_interface.h"
+#include "cc/layers/scrollbar_layer_base.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -87,8 +87,6 @@ VisualViewport::VisualViewport(Page& owner)
unique_id, CompositorElementIdNamespace::kPrimary);
scroll_element_id_ = CompositorElementIdFromUniqueObjectId(
unique_id, CompositorElementIdNamespace::kScroll);
- overscroll_elasticity_element_id_ = CompositorElementIdFromUniqueObjectId(
- unique_id, CompositorElementIdNamespace::kOverscrollElasticity);
Reset();
}
@@ -103,7 +101,7 @@ VisualViewport::GetOverscrollElasticityTransformNode() const {
}
TransformPaintPropertyNode* VisualViewport::GetPageScaleNode() const {
- return page_scale_node__.get();
+ return page_scale_node_.get();
}
TransformPaintPropertyNode* VisualViewport::GetScrollTranslationNode() const {
@@ -153,18 +151,11 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
}
}
- if (container_layer_) {
- container_layer_->SetLayerState(
- PropertyTreeState(*transform_parent, *clip_parent, *effect_parent),
- IntPoint());
- }
-
{
DCHECK(!transform_parent->IsInSubtreeOfPageScale());
TransformPaintPropertyNode::State state;
state.flags.in_subtree_of_page_scale = false;
- state.compositor_element_id = GetCompositorOverscrollElasticityElementId();
// TODO(crbug.com/877794) Should create overscroll elasticity transform node
// based on settings.
if (!overscroll_elasticity_transform_node_) {
@@ -182,14 +173,15 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
TransformPaintPropertyNode::State state{
TransformationMatrix().Scale(Scale())};
state.flags.in_subtree_of_page_scale = false;
+ state.direct_compositing_reasons = CompositingReason::kWillChangeTransform;
state.compositor_element_id = GetCompositorElementId();
- if (!page_scale_node__) {
- page_scale_node__ = TransformPaintPropertyNode::Create(
+ if (!page_scale_node_) {
+ page_scale_node_ = TransformPaintPropertyNode::Create(
*overscroll_elasticity_transform_node_.get(), std::move(state));
change = PaintPropertyChangeType::kNodeAddedOrRemoved;
} else {
- auto effective_change_type = page_scale_node__->Update(
+ auto effective_change_type = page_scale_node_->Update(
*overscroll_elasticity_transform_node_.get(), std::move(state));
// As an optimization, attempt to directly update the compositor
// scale translation node and return kChangedOnlyCompositedValues which
@@ -202,11 +194,11 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
if (auto* paint_artifact_compositor = GetPaintArtifactCompositor()) {
bool updated =
paint_artifact_compositor->DirectlyUpdatePageScaleTransform(
- *page_scale_node__);
+ *page_scale_node_);
if (updated) {
effective_change_type =
PaintPropertyChangeType::kChangedOnlyCompositedValues;
- page_scale_node__->CompositorSimpleValuesUpdated();
+ page_scale_node_->CompositorSimpleValuesUpdated();
}
}
}
@@ -214,12 +206,6 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
}
}
- if (page_scale_layer_) {
- page_scale_layer_->SetLayerState(
- PropertyTreeState(*page_scale_node__, *clip_parent, *effect_parent),
- IntPoint());
- }
-
{
ScrollPaintPropertyNode::State state;
state.container_rect = IntRect(IntPoint(), size_);
@@ -272,13 +258,14 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
TransformPaintPropertyNode::State state{
FloatSize(-scroll_position.Width(), -scroll_position.Height())};
state.scroll = scroll_node_;
+ state.direct_compositing_reasons = CompositingReason::kWillChangeTransform;
if (!scroll_translation_node_) {
scroll_translation_node_ = TransformPaintPropertyNode::Create(
- *page_scale_node__, std::move(state));
+ *page_scale_node_, std::move(state));
change = PaintPropertyChangeType::kNodeAddedOrRemoved;
} else {
- auto effective_change_type = scroll_translation_node_->Update(
- *page_scale_node__, std::move(state));
+ auto effective_change_type =
+ scroll_translation_node_->Update(*page_scale_node_, std::move(state));
// As an optimization, attempt to directly update the compositor
// translation node and return kChangedOnlyCompositedValues which avoids
// an expensive PaintArtifactCompositor update.
@@ -308,7 +295,7 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
IntPoint());
}
- if (overlay_scrollbar_horizontal_) {
+ if (scrollbar_graphics_layer_horizontal_) {
EffectPaintPropertyNode::State state;
state.local_transform_space = transform_parent;
state.direct_compositing_reasons =
@@ -325,13 +312,13 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
*effect_parent, std::move(state)));
}
- overlay_scrollbar_horizontal_->SetLayerState(
+ scrollbar_graphics_layer_horizontal_->SetLayerState(
PropertyTreeState(*transform_parent, *context.current.clip,
*horizontal_scrollbar_effect_node_),
ScrollbarOffset(ScrollbarOrientation::kHorizontalScrollbar));
}
- if (overlay_scrollbar_vertical_) {
+ if (scrollbar_graphics_layer_vertical_) {
EffectPaintPropertyNode::State state;
state.local_transform_space = transform_parent;
state.direct_compositing_reasons =
@@ -348,7 +335,7 @@ PaintPropertyChangeType VisualViewport::UpdatePaintPropertyNodesIfNeeded(
*effect_parent, std::move(state)));
}
- overlay_scrollbar_vertical_->SetLayerState(
+ scrollbar_graphics_layer_vertical_->SetLayerState(
PropertyTreeState(*transform_parent, *context.current.clip,
*vertical_scrollbar_effect_node_),
ScrollbarOffset(ScrollbarOrientation::kVerticalScrollbar));
@@ -396,16 +383,11 @@ void VisualViewport::SetSize(const IntSize& size) {
TRACE_EVENT_INSTANT1("loading", "viewport", TRACE_EVENT_SCOPE_THREAD, "data",
ViewportToTracedValue());
- if (container_layer_) {
- container_layer_->SetSize(gfx::Size(size_));
- scroll_layer_->CcLayer()->SetScrollable(static_cast<gfx::Size>(size_));
-
- // Need to re-compute sizes for the overlay scrollbars.
- if (overlay_scrollbar_horizontal_) {
- DCHECK(overlay_scrollbar_vertical_);
- SetupScrollbar(kHorizontalScrollbar);
- SetupScrollbar(kVerticalScrollbar);
- }
+ // Need to re-compute sizes for the overlay scrollbars.
+ if (scrollbar_graphics_layer_horizontal_) {
+ DCHECK(scrollbar_graphics_layer_vertical_);
+ SetupScrollbar(kHorizontalScrollbar);
+ SetupScrollbar(kVerticalScrollbar);
}
if (!MainFrame())
@@ -602,34 +584,23 @@ void VisualViewport::CreateLayerTree() {
if (scroll_layer_)
return;
- DCHECK(!overlay_scrollbar_horizontal_ && !overlay_scrollbar_vertical_ &&
- !page_scale_layer_ && !container_layer_);
+ DCHECK(!scrollbar_graphics_layer_horizontal_ &&
+ !scrollbar_graphics_layer_vertical_);
needs_paint_property_update_ = true;
root_transform_layer_ = std::make_unique<GraphicsLayer>(*this);
- container_layer_ = std::make_unique<GraphicsLayer>(*this);
- page_scale_layer_ = std::make_unique<GraphicsLayer>(*this);
scroll_layer_ = std::make_unique<GraphicsLayer>(*this);
ScrollingCoordinator* coordinator = GetPage().GetScrollingCoordinator();
DCHECK(coordinator);
- // Set masks to bounds so the compositor doesn't clobber a manually
- // set inner viewport container layer size.
- container_layer_->SetMasksToBounds(
- GetPage().GetSettings().GetMainFrameClipsContent());
- container_layer_->SetSize(gfx::Size(size_));
-
scroll_layer_->CcLayer()->SetScrollable(static_cast<gfx::Size>(size_));
DCHECK(MainFrame());
DCHECK(MainFrame()->GetDocument());
scroll_layer_->SetElementId(GetCompositorScrollElementId());
- page_scale_layer_->SetElementId(GetCompositorElementId());
- root_transform_layer_->AddChild(container_layer_.get());
- container_layer_->AddChild(page_scale_layer_.get());
- page_scale_layer_->AddChild(scroll_layer_.get());
+ root_transform_layer_->AddChild(scroll_layer_.get());
// Ensure this class is set as the scroll layer's ScrollableArea.
coordinator->ScrollableAreaScrollLayerDidChange(this);
@@ -657,22 +628,23 @@ void VisualViewport::AttachLayerTree(GraphicsLayer* current_layer_tree_root) {
void VisualViewport::InitializeScrollbars() {
// Do nothing if not attached to layer tree yet - will initialize upon attach.
- if (!container_layer_)
+ if (!root_transform_layer_)
return;
needs_paint_property_update_ = true;
if (VisualViewportSuppliesScrollbars() &&
!GetPage().GetSettings().GetHideScrollbars()) {
- DCHECK(!overlay_scrollbar_horizontal_);
- DCHECK(!overlay_scrollbar_vertical_);
- overlay_scrollbar_horizontal_ = std::make_unique<GraphicsLayer>(*this);
- overlay_scrollbar_vertical_ = std::make_unique<GraphicsLayer>(*this);
+ DCHECK(!scrollbar_graphics_layer_horizontal_);
+ DCHECK(!scrollbar_graphics_layer_vertical_);
+ scrollbar_graphics_layer_horizontal_ =
+ std::make_unique<GraphicsLayer>(*this);
+ scrollbar_graphics_layer_vertical_ = std::make_unique<GraphicsLayer>(*this);
SetupScrollbar(kHorizontalScrollbar);
SetupScrollbar(kVerticalScrollbar);
} else {
- overlay_scrollbar_horizontal_ = nullptr;
- overlay_scrollbar_vertical_ = nullptr;
+ scrollbar_graphics_layer_horizontal_ = nullptr;
+ scrollbar_graphics_layer_vertical_ = nullptr;
}
// Ensure existing LocalFrameView scrollbars are removed if the visual
@@ -686,65 +658,55 @@ void VisualViewport::InitializeScrollbars() {
int VisualViewport::ScrollbarThickness() const {
ScrollbarThemeOverlay& theme = ScrollbarThemeOverlay::MobileTheme();
int thickness = theme.ScrollbarThickness(kRegularScrollbar);
- return clampTo<int>(std::floor(
- GetPage().GetChromeClient().WindowToViewportScalar(thickness)));
+ return clampTo<int>(
+ std::floor(GetPage().GetChromeClient().WindowToViewportScalar(
+ MainFrame(), thickness)));
}
IntSize VisualViewport::ScrollbarSize(ScrollbarOrientation orientation) const {
- if (orientation == kHorizontalScrollbar) {
- int viewport_width = container_layer_->Size().width();
- return IntSize(viewport_width - ScrollbarThickness(), ScrollbarThickness());
- }
- int viewport_height = container_layer_->Size().height();
- return IntSize(ScrollbarThickness(), viewport_height - ScrollbarThickness());
+ if (orientation == kHorizontalScrollbar)
+ return IntSize(size_.Width() - ScrollbarThickness(), ScrollbarThickness());
+ return IntSize(ScrollbarThickness(), size_.Height() - ScrollbarThickness());
}
IntPoint VisualViewport::ScrollbarOffset(
ScrollbarOrientation orientation) const {
- if (orientation == kHorizontalScrollbar) {
- int viewport_height = container_layer_->Size().height();
- return IntPoint(0, viewport_height - ScrollbarThickness());
- }
- int viewport_width = container_layer_->Size().width();
- return IntPoint(viewport_width - ScrollbarThickness(), 0);
+ if (orientation == kHorizontalScrollbar)
+ return IntPoint(0, size_.Height() - ScrollbarThickness());
+ return IntPoint(size_.Width() - ScrollbarThickness(), 0);
}
void VisualViewport::SetupScrollbar(ScrollbarOrientation orientation) {
bool is_horizontal = orientation == kHorizontalScrollbar;
GraphicsLayer* scrollbar_graphics_layer =
- is_horizontal ? overlay_scrollbar_horizontal_.get()
- : overlay_scrollbar_vertical_.get();
- std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>&
- scrollbar_layer_group = is_horizontal ? scrollbar_layer_group_horizontal_
- : scrollbar_layer_group_vertical_;
+ is_horizontal ? scrollbar_graphics_layer_horizontal_.get()
+ : scrollbar_graphics_layer_vertical_.get();
+ scoped_refptr<cc::ScrollbarLayerBase>& scrollbar_layer =
+ is_horizontal ? scrollbar_layer_horizontal_ : scrollbar_layer_vertical_;
if (!scrollbar_graphics_layer->Parent())
- container_layer_->AddChild(scrollbar_graphics_layer);
+ root_transform_layer_->AddChild(scrollbar_graphics_layer);
- if (!scrollbar_layer_group) {
+ if (!scrollbar_layer) {
ScrollingCoordinator* coordinator = GetPage().GetScrollingCoordinator();
DCHECK(coordinator);
ScrollbarThemeOverlay& theme = ScrollbarThemeOverlay::MobileTheme();
int thumb_thickness = clampTo<int>(
std::floor(GetPage().GetChromeClient().WindowToViewportScalar(
- theme.ThumbThickness())));
+ MainFrame(), theme.ThumbThickness())));
int scrollbar_margin = clampTo<int>(
std::floor(GetPage().GetChromeClient().WindowToViewportScalar(
- theme.ScrollbarMargin())));
- scrollbar_layer_group = coordinator->CreateSolidColorScrollbarLayer(
+ MainFrame(), theme.ScrollbarMargin())));
+ scrollbar_layer = coordinator->CreateSolidColorScrollbarLayer(
orientation, thumb_thickness, scrollbar_margin, false,
GetScrollbarElementId(orientation));
- // The compositor will control the scrollbar's visibility. Set to invisible
- // by default so scrollbars don't show up in web tests.
- scrollbar_layer_group->layer->SetOpacity(0.f);
scrollbar_graphics_layer->SetContentsToCcLayer(
- scrollbar_layer_group->layer.get(),
+ scrollbar_layer.get(),
/*prevent_contents_opaque_changes=*/false);
scrollbar_graphics_layer->SetDrawsContent(false);
scrollbar_graphics_layer->SetHitTestable(false);
- scrollbar_layer_group->scrollbar_layer->SetScrollElementId(
- scroll_layer_->CcLayer()->element_id());
+ scrollbar_layer->SetScrollElementId(scroll_layer_->CcLayer()->element_id());
}
// Use the GraphicsLayer to position the scrollbars.
@@ -774,11 +736,6 @@ CompositorElementId VisualViewport::GetCompositorScrollElementId() const {
return scroll_element_id_;
}
-CompositorElementId VisualViewport::GetCompositorOverscrollElasticityElementId()
- const {
- return overscroll_elasticity_element_id_;
-}
-
bool VisualViewport::ScrollAnimatorEnabled() const {
return GetPage().GetSettings().GetScrollAnimatorEnabled();
}
@@ -913,19 +870,6 @@ float VisualViewport::BrowserControlsAdjustment() const {
return browser_controls_adjustment_;
}
-IntRect VisualViewport::ScrollableAreaBoundingBox() const {
- // This method should return the bounding box in the top-level
- // LocalFrameView's coordinate space; however, VisualViewport technically
- // isn't a child of any Frames. Nonetheless, the VisualViewport always
- // occupies the entire main frame so just return that.
- LocalFrame* frame = MainFrame();
-
- if (!frame || !frame->View())
- return IntRect();
-
- return frame->View()->FrameRect();
-}
-
bool VisualViewport::UserInputScrollable(ScrollbarOrientation) const {
// If there is a non-root fullscreen element, prevent the viewport from
// scrolling.
@@ -978,20 +922,16 @@ void VisualViewport::UpdateScrollOffset(const ScrollOffset& position,
}
}
-GraphicsLayer* VisualViewport::LayerForContainer() const {
- return container_layer_.get();
-}
-
GraphicsLayer* VisualViewport::LayerForScrolling() const {
return scroll_layer_.get();
}
GraphicsLayer* VisualViewport::LayerForHorizontalScrollbar() const {
- return overlay_scrollbar_horizontal_.get();
+ return scrollbar_graphics_layer_horizontal_.get();
}
GraphicsLayer* VisualViewport::LayerForVerticalScrollbar() const {
- return overlay_scrollbar_vertical_.get();
+ return scrollbar_graphics_layer_vertical_.get();
}
IntRect VisualViewport::ComputeInterestRect(const GraphicsLayer*,
@@ -1188,7 +1128,7 @@ void VisualViewport::SetOverlayScrollbarsHidden(bool hidden) {
void VisualViewport::GraphicsLayersDidChange() {
if (MainFrame() && MainFrame()->View())
- MainFrame()->View()->GraphicsLayersDidChange();
+ MainFrame()->View()->SetForeignLayerListNeedsUpdate();
}
PaintArtifactCompositor* VisualViewport::GetPaintArtifactCompositor() const {
@@ -1199,15 +1139,11 @@ PaintArtifactCompositor* VisualViewport::GetPaintArtifactCompositor() const {
String VisualViewport::DebugName(const GraphicsLayer* graphics_layer) const {
String name;
- if (graphics_layer == container_layer_.get()) {
- name = "Inner Viewport Container Layer";
- } else if (graphics_layer == page_scale_layer_.get()) {
- name = "Page Scale Layer";
- } else if (graphics_layer == scroll_layer_.get()) {
+ if (graphics_layer == scroll_layer_.get()) {
name = "Inner Viewport Scroll Layer";
- } else if (graphics_layer == overlay_scrollbar_horizontal_.get()) {
+ } else if (graphics_layer == scrollbar_graphics_layer_horizontal_.get()) {
name = "Overlay Scrollbar Horizontal Layer";
- } else if (graphics_layer == overlay_scrollbar_vertical_.get()) {
+ } else if (graphics_layer == scrollbar_graphics_layer_vertical_.get()) {
name = "Overlay Scrollbar Vertical Layer";
} else if (graphics_layer == root_transform_layer_.get()) {
name = "Root Transform Layer";
@@ -1239,18 +1175,16 @@ std::unique_ptr<TracedValue> VisualViewport::ViewportToTracedValue() const {
void VisualViewport::DisposeImpl() {
root_transform_layer_.reset();
- container_layer_.reset();
- page_scale_layer_.reset();
scroll_layer_.reset();
- // scrollbar_layer_group_* are referenced from overlay_scrollbar_*, thus
- // overlay_scrollbar_* must be destroyed before scrollbar_layer_group_*.
- overlay_scrollbar_horizontal_.reset();
- overlay_scrollbar_vertical_.reset();
- scrollbar_layer_group_horizontal_.reset();
- scrollbar_layer_group_vertical_.reset();
+ // scrollbar_layer_* are referenced from scrollbar_graphics_layer_*, thus
+ // scrollbar_graphics_layer_* must be destroyed before scrollbar_layer_*.
+ scrollbar_graphics_layer_horizontal_.reset();
+ scrollbar_graphics_layer_vertical_.reset();
+ scrollbar_layer_horizontal_.reset();
+ scrollbar_layer_vertical_.reset();
device_emulation_transform_node_.reset();
overscroll_elasticity_transform_node_.reset();
- page_scale_node__.reset();
+ page_scale_node_.reset();
scroll_translation_node_.reset();
scroll_node_.reset();
horizontal_scrollbar_effect_node_.reset();
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 3c92f0d7665..b675a62d691 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -77,12 +77,10 @@ struct PaintPropertyTreeBuilderFragmentContext;
// (pre-CompositeAfterPaint only)
//
// root_transform_layer_
-// +- container_layer_ (transform: DET_or_parent)
-// +- page_scale_layer_ (transform: page_scale_node_)
-// | +- scroll_layer_ (transform: scroll_translation_node_)
-// | +- LayoutView CompositedLayerMapping layers
-// +- overlay_scrollbar_horizontal_ (optional, transform: DET_or_parent)
-// +- overlay_scrollbar_vertical_ (optional, transform: DET_or_parent)
+// +- scroll_layer_ (transform: scroll_translation_node_)
+// | +- LayoutView CompositedLayerMapping layers
+// +- scrollbar_graphics_layer_horizontal_ (optional, transform: DET_or_parent)
+// +- scrollbar_graphics_layer_vertical_ (optional, transform: DET_or_parent)
// (DET_or_parent: device_emulation_transform_node_ if exists,
// or the parent transform state)
//
@@ -100,7 +98,7 @@ struct PaintPropertyTreeBuilderFragmentContext;
// +- vertical_scrollbar_effect_node_
//
class CORE_EXPORT VisualViewport final
- : public GarbageCollectedFinalized<VisualViewport>,
+ : public GarbageCollected<VisualViewport>,
public GraphicsLayerClient,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(VisualViewport);
@@ -115,9 +113,7 @@ class CORE_EXPORT VisualViewport final
void AttachLayerTree(GraphicsLayer*);
GraphicsLayer* RootGraphicsLayer() { return root_transform_layer_.get(); }
- GraphicsLayer* ContainerLayer() { return container_layer_.get(); }
GraphicsLayer* ScrollLayer() { return scroll_layer_.get(); }
- GraphicsLayer* PageScaleLayer() { return page_scale_layer_.get(); }
void InitializeScrollbars();
@@ -215,14 +211,12 @@ class CORE_EXPORT VisualViewport final
// correct cc Layer sizing.
IntSize ContentsSize() const override;
bool ScrollbarsCanBeActive() const override { return false; }
- IntRect ScrollableAreaBoundingBox() const override;
bool UserInputScrollable(ScrollbarOrientation) const override;
bool ShouldPlaceVerticalScrollbarOnLeft() const override { return false; }
CompositorElementId GetCompositorElementId() const override;
bool ScrollAnimatorEnabled() const override;
void ScrollControlWasSetNeedsPaintInvalidation() override {}
void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
- GraphicsLayer* LayerForContainer() const override;
GraphicsLayer* LayerForScrolling() const override;
GraphicsLayer* LayerForHorizontalScrollbar() const override;
GraphicsLayer* LayerForVerticalScrollbar() const override;
@@ -278,8 +272,6 @@ class CORE_EXPORT VisualViewport final
PaintPropertyChangeType UpdatePaintPropertyNodesIfNeeded(
PaintPropertyTreeBuilderFragmentContext& context);
- CompositorElementId GetCompositorOverscrollElasticityElementId() const;
-
void SetNeedsPaintPropertyUpdate() { needs_paint_property_update_ = true; }
bool NeedsPaintPropertyUpdate() const { return needs_paint_property_update_; }
@@ -341,24 +333,20 @@ class CORE_EXPORT VisualViewport final
Member<Page> page_;
std::unique_ptr<GraphicsLayer> root_transform_layer_;
- std::unique_ptr<GraphicsLayer> container_layer_;
- std::unique_ptr<GraphicsLayer> page_scale_layer_;
std::unique_ptr<GraphicsLayer> scroll_layer_;
// The layers of the ScrollbarLayerGroups are referenced from the
// GraphicsLayers, so the GraphicsLayers must be destructed first (declared
// after).
- std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
- scrollbar_layer_group_horizontal_;
- std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
- scrollbar_layer_group_vertical_;
- std::unique_ptr<GraphicsLayer> overlay_scrollbar_horizontal_;
- std::unique_ptr<GraphicsLayer> overlay_scrollbar_vertical_;
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer_horizontal_;
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer_vertical_;
+ std::unique_ptr<GraphicsLayer> scrollbar_graphics_layer_horizontal_;
+ std::unique_ptr<GraphicsLayer> scrollbar_graphics_layer_vertical_;
scoped_refptr<TransformPaintPropertyNode> device_emulation_transform_node_;
scoped_refptr<TransformPaintPropertyNode>
overscroll_elasticity_transform_node_;
- scoped_refptr<TransformPaintPropertyNode> page_scale_node__;
+ scoped_refptr<TransformPaintPropertyNode> page_scale_node_;
scoped_refptr<TransformPaintPropertyNode> scroll_translation_node_;
scoped_refptr<ScrollPaintPropertyNode> scroll_node_;
scoped_refptr<EffectPaintPropertyNode> horizontal_scrollbar_effect_node_;
@@ -390,7 +378,6 @@ class CORE_EXPORT VisualViewport final
bool track_pinch_zoom_stats_for_page_;
CompositorElementId element_id_;
CompositorElementId scroll_element_id_;
- CompositorElementId overscroll_elasticity_element_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 8995d11204f..51647015884 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
@@ -533,8 +533,6 @@ TEST_P(VisualViewportTest, TestWebViewResizedBeforeAttachment) {
frame_view.GetLayoutView()->Compositor()->RootGraphicsLayer());
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
- EXPECT_FLOAT_SIZE_EQ(IntSize(320, 240),
- IntSize(visual_viewport.ContainerLayer()->Size()));
EXPECT_EQ(IntSize(320, 240),
visual_viewport.GetScrollNode()->ContainerRect().Size());
}
@@ -2407,11 +2405,7 @@ TEST_P(VisualViewportTest, EnsureOverscrollElasticityTransformNode) {
UpdateAllLifecyclePhases();
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
- auto* node = visual_viewport.GetOverscrollElasticityTransformNode();
- CompositorElementId element_id =
- visual_viewport.GetCompositorOverscrollElasticityElementId();
- EXPECT_TRUE(node);
- EXPECT_EQ(element_id, node->GetCompositorElementId());
+ EXPECT_TRUE(visual_viewport.GetOverscrollElasticityTransformNode());
}
// Ensure we create effect node for scrollbar properly.
@@ -2438,7 +2432,7 @@ TEST_P(VisualViewportTest, EnsureEffectNodeForScrollbars) {
ScrollbarThemeOverlay& theme = ScrollbarThemeOverlay::MobileTheme();
int scrollbar_thickness = clampTo<int>(std::floor(
GetFrame()->GetPage()->GetChromeClient().WindowToViewportScalar(
- theme.ScrollbarThickness(kRegularScrollbar))));
+ GetFrame(), theme.ScrollbarThickness(kRegularScrollbar))));
EXPECT_EQ(vertical_scrollbar_state.Effect().GetCompositorElementId(),
visual_viewport.GetScrollbarElementId(
@@ -2514,9 +2508,6 @@ TEST_F(VisualViewportSimTest, ScrollingContentsSmallerThanContainer) {
ASSERT_EQ(1.25f, WebView().MinimumPageScaleFactor());
VisualViewport& visual_viewport = WebView().GetPage()->GetVisualViewport();
- EXPECT_EQ(gfx::Size(400, 600), visual_viewport.ContainerLayer()->Size());
- EXPECT_EQ(gfx::Size(400, 600),
- visual_viewport.ContainerLayer()->CcLayer()->bounds());
EXPECT_EQ(gfx::Size(320, 480), visual_viewport.ScrollLayer()->Size());
EXPECT_EQ(gfx::Size(320, 480),
visual_viewport.ScrollLayer()->CcLayer()->bounds());
@@ -2528,9 +2519,6 @@ TEST_F(VisualViewportSimTest, ScrollingContentsSmallerThanContainer) {
WebView().MainFrameWidget()->ApplyViewportChanges(
{gfx::ScrollOffset(1, 1), gfx::Vector2dF(), 2, false, 1,
cc::BrowserControlsState::kBoth});
- EXPECT_EQ(gfx::Size(400, 600), visual_viewport.ContainerLayer()->Size());
- EXPECT_EQ(gfx::Size(400, 600),
- visual_viewport.ContainerLayer()->CcLayer()->bounds());
EXPECT_EQ(gfx::Size(320, 480), visual_viewport.ScrollLayer()->Size());
EXPECT_EQ(gfx::Size(320, 480),
visual_viewport.ScrollLayer()->CcLayer()->bounds());
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 143c242d4e7..ed21e87c13c 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
@@ -142,8 +142,8 @@ String WebFrameSerializerImpl::PreActionBeforeSerializeOpenTag(
// have overrided the META which have correct charset declaration after
// serializing open tag of HEAD element.
DCHECK(element);
- if (IsHTMLMetaElement(element) &&
- ToHTMLMetaElement(element)->ComputeEncoding().IsValid()) {
+ auto* meta = DynamicTo<HTMLMetaElement>(element);
+ if (meta && meta->ComputeEncoding().IsValid()) {
// Found META tag declared charset, we need to skip it when
// serializing DOM.
param->skip_meta_element = element;
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index eee1f2f90e7..cda90106353 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -60,6 +60,10 @@ WebFrameWidgetBase::~WebFrameWidgetBase() = default;
void WebFrameWidgetBase::BindLocalRoot(WebLocalFrame& local_root) {
local_root_ = To<WebLocalFrameImpl>(local_root);
local_root_->SetFrameWidget(this);
+ request_animation_after_delay_timer_.reset(
+ new TaskRunnerTimer<WebFrameWidgetBase>(
+ local_root.GetTaskRunner(TaskType::kInternalDefault), this,
+ &WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired));
}
void WebFrameWidgetBase::Close() {
@@ -67,6 +71,7 @@ void WebFrameWidgetBase::Close() {
local_root_->SetFrameWidget(nullptr);
local_root_ = nullptr;
client_ = nullptr;
+ request_animation_after_delay_timer_.reset();
}
WebLocalFrame* WebFrameWidgetBase::LocalRoot() const {
@@ -433,6 +438,23 @@ WebLocalFrame* WebFrameWidgetBase::FocusedWebLocalFrameInWidget() const {
return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
}
+void WebFrameWidgetBase::RequestAnimationAfterDelay(
+ const base::TimeDelta& delay) {
+ DCHECK(request_animation_after_delay_timer_.get());
+ if (request_animation_after_delay_timer_->IsActive() &&
+ request_animation_after_delay_timer_->NextFireInterval() > delay) {
+ request_animation_after_delay_timer_->Stop();
+ }
+ if (!request_animation_after_delay_timer_->IsActive()) {
+ request_animation_after_delay_timer_->StartOneShot(delay, FROM_HERE);
+ }
+}
+
+void WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired(TimerBase*) {
+ if (client_)
+ client_->ScheduleAnimation();
+}
+
base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
WebFrameWidgetBase::EnsureCompositorMutatorDispatcher(
scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner) {
diff --git a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index ff862b8560e..98796c1f961 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_BASE_H_
#include "base/single_thread_task_runner.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/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/platform/web_gesture_device.h"
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace cc {
@@ -40,7 +41,7 @@ struct IntrinsicSizingInfo;
struct WebFloatPoint;
class CORE_EXPORT WebFrameWidgetBase
- : public GarbageCollectedFinalized<WebFrameWidgetBase>,
+ : public GarbageCollected<WebFrameWidgetBase>,
public WebFrameWidget {
public:
explicit WebFrameWidgetBase(WebWidgetClient&);
@@ -142,6 +143,8 @@ class CORE_EXPORT WebFrameWidgetBase
// focused frame has a different local root.
LocalFrame* FocusedLocalFrameInWidget() const;
+ void RequestAnimationAfterDelay(const base::TimeDelta&);
+
virtual void Trace(blink::Visitor*);
protected:
@@ -186,6 +189,7 @@ class CORE_EXPORT WebFrameWidgetBase
private:
void CancelDrag();
+ void RequestAnimationAfterDelayTimerFired(TimerBase*);
WebWidgetClient* client_;
@@ -211,6 +215,9 @@ class CORE_EXPORT WebFrameWidgetBase
base::WeakPtr<PaintWorkletPaintDispatcher> paint_dispatcher_;
scoped_refptr<base::SingleThreadTaskRunner> paint_task_runner_;
+ std::unique_ptr<TaskRunnerTimer<WebFrameWidgetBase>>
+ request_animation_after_delay_timer_;
+
friend class WebViewImpl;
};
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 f15903c710b..e4f78f3047d 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
@@ -350,6 +350,18 @@ void WebFrameWidgetImpl::RecordEndOfFrameMetrics(
.RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now());
}
+std::unique_ptr<cc::BeginMainFrameMetrics>
+WebFrameWidgetImpl::GetBeginMainFrameMetrics() {
+ if (!LocalRootImpl())
+ return nullptr;
+
+ return LocalRootImpl()
+ ->GetFrame()
+ ->View()
+ ->EnsureUkmAggregator()
+ .GetBeginMainFrameMetrics();
+}
+
void WebFrameWidgetImpl::UpdateLifecycle(LifecycleUpdate requested_update,
LifecycleUpdateReason reason) {
TRACE_EVENT0("blink", "WebFrameWidgetImpl::updateAllLifecyclePhases");
@@ -756,9 +768,11 @@ void WebFrameWidgetImpl::MouseContextMenu(const WebMouseEvent& event) {
// implementation...
}
-void WebFrameWidgetImpl::HandleMouseUp(LocalFrame& main_frame,
- const WebMouseEvent& event) {
- PageWidgetEventHandler::HandleMouseUp(main_frame, event);
+WebInputEventResult WebFrameWidgetImpl::HandleMouseUp(
+ LocalFrame& main_frame,
+ const WebMouseEvent& event) {
+ WebInputEventResult result =
+ PageWidgetEventHandler::HandleMouseUp(main_frame, event);
if (GetPage()->GetSettings().GetShowContextMenuOnMouseUp()) {
// Dispatch the contextmenu event regardless of if the click was swallowed.
@@ -766,6 +780,7 @@ void WebFrameWidgetImpl::HandleMouseUp(LocalFrame& main_frame,
if (event.button == WebMouseEvent::Button::kRight)
MouseContextMenu(event);
}
+ return result;
}
WebInputEventResult WebFrameWidgetImpl::HandleMouseWheel(
@@ -1006,14 +1021,6 @@ void WebFrameWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
View()->MinimumPageScaleFactor(),
View()->MaximumPageScaleFactor());
- // TODO(kenrb): Currently GPU rasterization is always enabled for OOPIFs.
- // This is okay because it is only necessarily to set the trigger to false
- // for certain cases that affect the top-level frame, but it would be better
- // to be consistent with the top-level frame. Ideally the logic should
- // be moved from WebViewImpl into WebFrameWidget and used for all local
- // frame roots. https://crbug.com/712794
- Client()->SetAllowGpuRasterization(true);
-
// TODO(danakj): SetIsAcceleratedCompositingActive() also sets the root layer
// if it's not null..
Client()->SetRootLayer(root_layer_);
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 3ac90b55d04..43da8465ec2 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
@@ -52,6 +52,7 @@
namespace cc {
class Layer;
+struct BeginMainFrameMetrics;
}
namespace blink {
@@ -89,6 +90,8 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
void EndCommitCompositorFrame() override;
void RecordStartOfFrameMetrics() override;
void RecordEndOfFrameMetrics(base::TimeTicks) override;
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
+ override;
void UpdateLifecycle(LifecycleUpdate requested_update,
LifecycleUpdateReason reason) override;
void ThemeChanged() override;
@@ -158,7 +161,7 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
// PageWidgetEventHandler functions
void HandleMouseLeave(LocalFrame&, const WebMouseEvent&) override;
void HandleMouseDown(LocalFrame&, const WebMouseEvent&) override;
- void HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
+ WebInputEventResult HandleMouseUp(LocalFrame&, const WebMouseEvent&) override;
WebInputEventResult HandleMouseWheel(LocalFrame&,
const WebMouseWheelEvent&) override;
WebInputEventResult HandleGestureEvent(const WebGestureEvent&) override;
diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index d1f07949b20..247152ace23 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
@@ -94,7 +94,10 @@
#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"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_double_size.h"
@@ -171,7 +174,6 @@
#include "third_party/blink/renderer/core/editing/writing_direction.h"
#include "third_party/blink/renderer/core/events/after_print_event.h"
#include "third_party/blink/renderer/core/events/before_print_event.h"
-#include "third_party/blink/renderer/core/events/portal_activate_event.h"
#include "third_party/blink/renderer/core/exported/local_frame_client_impl.h"
#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
#include "third_party/blink/renderer/core/exported/web_document_loader_impl.h"
@@ -212,6 +214,7 @@
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
#include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
#include "third_party/blink/renderer/core/html/portal/html_portal_element.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/html_names.h"
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
@@ -416,7 +419,7 @@ class ChromePrintContext : public PrintContext {
frame_view->PaintContentsOutsideOfLifecycle(
builder.Context(),
kGlobalPaintNormalPhase | kGlobalPaintFlattenCompositingLayers |
- kGlobalPaintPrinting,
+ kGlobalPaintPrinting | kGlobalPaintAddUrlMetadata,
CullRect(page_rect));
{
ScopedPaintChunkProperties scoped_paint_chunk_properties(
@@ -628,7 +631,8 @@ WebSize WebLocalFrameImpl::DocumentSize() const {
if (!GetFrameView() || !GetFrameView()->GetLayoutView())
return WebSize();
- return GetFrameView()->GetLayoutView()->DocumentRect().Size();
+ return PixelSnappedIntRect(GetFrameView()->GetLayoutView()->DocumentRect())
+ .Size();
}
bool WebLocalFrameImpl::HasVisibleContent() const {
@@ -686,7 +690,7 @@ void WebLocalFrameImpl::DispatchUnloadEvent() {
// when unloading itself.
IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
GetFrame()->GetDocument());
- GetFrame()->Loader().DispatchUnloadEvent();
+ GetFrame()->Loader().DispatchUnloadEvent(nullptr, nullptr);
}
void WebLocalFrameImpl::ExecuteScript(const WebScriptSource& source) {
@@ -910,10 +914,6 @@ void WebLocalFrameImpl::ReloadImage(const WebNode& web_node) {
image_element->ForceReload();
}
-void WebLocalFrameImpl::ReloadLoFiImages() {
- GetFrame()->GetDocument()->Fetcher()->ReloadLoFiImages();
-}
-
void WebLocalFrameImpl::StartNavigation(const WebURLRequest& request) {
// TODO(clamy): Remove this function once RenderFrame calls CommitNavigation
// for all requests.
@@ -1932,17 +1932,6 @@ void WebLocalFrameImpl::DidFailLoad(const ResourceError& error,
Client()->DidFailLoad(web_error, web_commit_type);
}
-void WebLocalFrameImpl::DidFailProvisionalLoad(
- const ResourceError& error,
- const AtomicString& http_method) {
- if (!Client())
- return;
- WebURLError web_error = error;
- if (WebPluginContainerImpl* plugin = GetFrame()->GetWebPluginContainer())
- plugin->DidFailLoading(error);
- Client()->DidFailProvisionalLoad(web_error, http_method);
-}
-
void WebLocalFrameImpl::DidFinish() {
if (!Client())
return;
@@ -2651,16 +2640,17 @@ WebDevToolsAgentImpl* WebLocalFrameImpl::DevToolsAgentImpl() {
}
void WebLocalFrameImpl::BindDevToolsAgent(
- mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
- mojo::ScopedInterfaceEndpointHandle devtools_agent_request) {
+ mojo::ScopedInterfaceEndpointHandle devtools_agent_host_remote,
+ mojo::ScopedInterfaceEndpointHandle devtools_agent_receiver) {
WebDevToolsAgentImpl* agent = DevToolsAgentImpl();
if (!agent)
return;
- agent->BindRequest(mojom::blink::DevToolsAgentHostAssociatedPtrInfo(
- std::move(devtools_agent_host_ptr_info),
- mojom::blink::DevToolsAgentHost::Version_),
- mojom::blink::DevToolsAgentAssociatedRequest(
- std::move(devtools_agent_request)));
+ agent->BindReceiver(
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost>(
+ std::move(devtools_agent_host_remote),
+ mojom::blink::DevToolsAgentHost::Version_),
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent>(
+ std::move(devtools_agent_receiver)));
}
void WebLocalFrameImpl::SetLifecycleState(mojom::FrameLifecycleState state) {
diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 9fbb94efc82..c9dbed953b4 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
@@ -38,11 +38,11 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
-#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
-#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h"
-#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
-#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
-#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
+#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_file_system_type.h"
#include "third_party/blink/public/web/web_history_commit_type.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -90,27 +90,70 @@ class WebVector;
// Implementation of WebFrame, note that this is a reference counted object.
class CORE_EXPORT WebLocalFrameImpl final
- : public GarbageCollectedFinalized<WebLocalFrameImpl>,
+ : public GarbageCollected<WebLocalFrameImpl>,
public WebNavigationControl {
public:
- // WebFrame methods:
- // TODO(dcheng): Fix sorting here; a number of method have been moved to
- // WebLocalFrame but not correctly updated here.
+ // WebFrame overrides:
void Close() override;
- WebString AssignedName() const override;
- void SetName(const WebString&) override;
- WebVector<WebIconURL> IconURLs(int icon_types_mask) const override;
- WebSize GetScrollOffset() const override;
- void SetScrollOffset(const WebSize&) override;
- WebSize DocumentSize() const override;
- bool HasVisibleContent() const override;
- WebRect VisibleContentRect() const override;
WebView* View() const override;
- WebDocument GetDocument() const override;
- WebPerformance Performance() const override;
- bool IsAdSubframe() const override;
- void SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) override;
+ v8::Local<v8::Object> GlobalProxy() const override;
+ void StopLoading() override;
+ bool IsLoading() const override;
+
+ // WebLocalFrame overrides:
+ WebLocalFrameImpl* CreateLocalChild(WebTreeScopeType,
+ WebLocalFrameClient*,
+ blink::InterfaceRegistry*,
+ mojo::ScopedMessagePipeHandle) override;
+ WebLocalFrameClient* Client() const override { return client_; }
+ void SetAutofillClient(WebAutofillClient*) override;
+ WebAutofillClient* AutofillClient() override;
+ void SetContentCaptureClient(WebContentCaptureClient*) override;
+ WebContentCaptureClient* ContentCaptureClient() const override;
void DispatchUnloadEvent() override;
+ WebVector<WebIconURL> IconURLs(int icon_types_mask) const override;
+ WebDocument GetDocument() const override;
+ WebString AssignedName() const override;
+ void SetName(const WebString&) override;
+ void NotifyUserActivation() override;
+ bool IsLocalRoot() const override;
+ bool IsProvisional() const override;
+ WebLocalFrameImpl* LocalRoot() override;
+ WebFrameWidget* FrameWidget() const override;
+ WebFrame* FindFrameByName(const WebString& name) override;
+ bool ScrollTo(const gfx::Point& scrollPosition,
+ bool animate,
+ base::OnceClosure on_finish) override;
+ void SendPings(const WebURL& destination_url) override;
+ void StartReload(WebFrameLoadType) override;
+ void StartNavigation(const WebURLRequest&) override;
+ void EnableViewSourceMode(bool enable) override;
+ bool IsViewSourceModeEnabled() const override;
+ WebDocumentLoader* GetDocumentLoader() const override;
+ void ReportContentSecurityPolicyViolation(
+ const blink::WebContentSecurityPolicyViolation&) override;
+ void SetReferrerForRequest(WebURLRequest&, const WebURL& referrer) override;
+ bool IsNavigationScheduledWithin(base::TimeDelta interval) const override;
+ void BlinkFeatureUsageReport(
+ const std::set<blink::mojom::WebFeature>& features) override;
+ void BlinkFeatureUsageReport(blink::mojom::WebFeature feature) override;
+ void MixedContentFound(const WebURL& main_resource_url,
+ const WebURL& mixed_content_url,
+ mojom::RequestContextType,
+ bool was_allowed,
+ bool had_redirect,
+ const WebSourceLocation&) override;
+ void SendOrientationChangeEvent() override;
+ bool IsPageBoxVisible(int page_index) override;
+ bool HasCustomPageSizeStyle(int page_index) override;
+ void PageSizeAndMarginsInPixels(int page_index,
+ WebDoubleSize& page_size,
+ int& margin_top,
+ int& margin_right,
+ int& margin_bottom,
+ int& margin_left) override;
+ WebString PageProperty(const WebString& property_name,
+ int page_index) override;
void ExecuteScript(const WebScriptSource&) override;
void ExecuteScriptInIsolatedWorld(int32_t world_id,
const WebScriptSource&) override;
@@ -120,14 +163,14 @@ class CORE_EXPORT WebLocalFrameImpl final
void ClearIsolatedWorldCSPForTesting(int32_t world_id) override;
void SetIsolatedWorldInfo(int32_t world_id,
const WebIsolatedWorldInfo&) override;
- void Alert(const WebString& message) override;
- bool Confirm(const WebString& message) override;
- WebString Prompt(const WebString& message,
- const WebString& default_value) override;
-
- void CollectGarbageForTesting();
v8::Local<v8::Value> ExecuteScriptAndReturnValue(
const WebScriptSource&) override;
+ v8::MaybeLocal<v8::Value> CallFunctionEvenIfScriptDisabled(
+ v8::Local<v8::Function>,
+ v8::Local<v8::Value>,
+ int argc,
+ v8::Local<v8::Value> argv[]) override;
+ v8::Local<v8::Context> MainWorldScriptContext() const override;
void RequestExecuteScriptAndReturnValue(const WebScriptSource&,
bool user_gesture,
WebScriptExecutionCallback*) override;
@@ -144,25 +187,10 @@ class CORE_EXPORT WebLocalFrameImpl final
bool user_gesture,
ScriptExecutionType,
WebScriptExecutionCallback*) override;
- v8::MaybeLocal<v8::Value> CallFunctionEvenIfScriptDisabled(
- v8::Local<v8::Function>,
- v8::Local<v8::Value>,
- int argc,
- v8::Local<v8::Value> argv[]) override;
- v8::Local<v8::Context> MainWorldScriptContext() const override;
- v8::Local<v8::Object> GlobalProxy() const override;
- void StartReload(WebFrameLoadType) override;
- void ReloadImage(const WebNode&) override;
- void ReloadLoFiImages() override;
- void StartNavigation(const WebURLRequest&) override;
- void CheckCompleted() override;
- void StopLoading() override;
- WebDocumentLoader* GetDocumentLoader() const override;
- void EnableViewSourceMode(bool enable) override;
- bool IsViewSourceModeEnabled() const override;
- void SetReferrerForRequest(WebURLRequest&, const WebURL& referrer) override;
- WebAssociatedURLLoader* CreateAssociatedURLLoader(
- const WebAssociatedURLLoaderOptions&) override;
+ void Alert(const WebString& message) override;
+ bool Confirm(const WebString& message) override;
+ WebString Prompt(const WebString& message,
+ const WebString& default_value) override;
void BindDevToolsAgent(
mojo::ScopedInterfaceEndpointHandle devtools_agent_host_ptr_info,
mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
@@ -183,13 +211,6 @@ class CORE_EXPORT WebLocalFrameImpl final
WebTextDirection& end) const override;
bool IsSelectionAnchorFirst() const override;
void SetTextDirection(WebTextDirection) override;
- void SetTextCheckClient(WebTextCheckClient*) override;
- void SetSpellCheckPanelHostClient(WebSpellCheckPanelHostClient*) override;
- void ReplaceMisspelledRange(const WebString&) override;
- void RemoveSpellingMarkers() override;
- void RemoveSpellingMarkersUnderWords(
- const WebVector<WebString>& words) override;
- void SetContentSettingsClient(WebContentSettingsClient*) override;
bool HasSelection() const override;
WebRange SelectionRange() const override;
WebString SelectionAsText() const override;
@@ -200,7 +221,6 @@ class CORE_EXPORT WebLocalFrameImpl final
HandleVisibilityBehavior,
blink::mojom::SelectionMenuBehavior) override;
WebString RangeAsText(const WebRange&) override;
- void MoveRangeSelectionExtent(const WebPoint&) override;
void MoveRangeSelection(
const WebPoint& base,
const WebPoint& extent,
@@ -212,78 +232,30 @@ class CORE_EXPORT WebLocalFrameImpl final
int composition_end,
const WebVector<WebImeTextSpan>& ime_text_spans) override;
void ExtendSelectionAndDelete(int before, int after) override;
+ void SetCaretVisible(bool) override;
+ void MoveRangeSelectionExtent(const WebPoint&) override;
+ void ReplaceSelection(const WebString&) override;
void DeleteSurroundingText(int before, int after) override;
void DeleteSurroundingTextInCodePoints(int before, int after) override;
- void SetCaretVisible(bool) override;
- void DispatchBeforePrintEvent() override;
- int PrintBegin(const WebPrintParams&,
- const WebNode& constrain_to_node) override;
- float PrintPage(int page_to_print, cc::PaintCanvas*) override;
- float GetPrintPageShrink(int page) override;
- void PrintEnd() override;
- void DispatchAfterPrintEvent() override;
- bool GetPrintPresetOptionsForPlugin(const WebNode&,
- WebPrintPresetOptions*) override;
- bool HasCustomPageSizeStyle(int page_index) override;
- bool IsPageBoxVisible(int page_index) override;
- void PageSizeAndMarginsInPixels(int page_index,
- WebDoubleSize& page_size,
- int& margin_top,
- int& margin_right,
- int& margin_bottom,
- int& margin_left) override;
- WebString PageProperty(const WebString& property_name,
- int page_index) override;
- void PrintPagesForTesting(cc::PaintCanvas*, const WebSize&) override;
-
- void DispatchMessageEventWithOriginCheck(
- const WebSecurityOrigin& intended_target_origin,
- const WebDOMMessageEvent&) override;
-
- WebRect GetSelectionBoundsRectForTesting() const override;
-
- WebString GetLayerTreeAsTextForTesting(
- bool show_debug_info = false) const override;
-
- WebLocalFrameClient* Client() const override { return client_; }
-
- // WebLocalFrame methods:
- WebLocalFrameImpl* CreateLocalChild(WebTreeScopeType,
- WebLocalFrameClient*,
- blink::InterfaceRegistry*,
- mojo::ScopedMessagePipeHandle) override;
- void SetAutofillClient(WebAutofillClient*) override;
- WebAutofillClient* AutofillClient() override;
- void SetContentCaptureClient(WebContentCaptureClient*) override;
- WebContentCaptureClient* ContentCaptureClient() const override;
- bool IsLocalRoot() const override;
- bool IsProvisional() const override;
- WebLocalFrameImpl* LocalRoot() override;
- WebFrame* FindFrameByName(const WebString& name) override;
- bool ScrollTo(const gfx::Point& scrollPosition,
- bool animate,
- base::OnceClosure on_finish) override;
- void SendPings(const WebURL& destination_url) override;
- void ReportContentSecurityPolicyViolation(
- const blink::WebContentSecurityPolicyViolation&) override;
- bool IsLoading() const override;
- bool IsNavigationScheduledWithin(base::TimeDelta interval) const override;
- void NotifyUserActivation() override;
- void BlinkFeatureUsageReport(
- const std::set<blink::mojom::WebFeature>& features) override;
- void BlinkFeatureUsageReport(blink::mojom::WebFeature feature) override;
- void MixedContentFound(const WebURL& main_resource_url,
- const WebURL& mixed_content_url,
- mojom::RequestContextType,
- bool was_allowed,
- bool had_redirect,
- const WebSourceLocation&) override;
- void SendOrientationChangeEvent() override;
- WebSandboxFlags EffectiveSandboxFlagsForTesting() const override;
- bool IsAllowedToDownloadWithoutUserActivation() const override;
+ void ExtractSmartClipData(WebRect rect_in_viewport,
+ WebString& clip_text,
+ WebString& clip_html,
+ WebRect& clip_rect) override;
+ void SetTextCheckClient(WebTextCheckClient*) override;
+ void SetSpellCheckPanelHostClient(WebSpellCheckPanelHostClient*) override;
+ WebSpellCheckPanelHostClient* SpellCheckPanelHostClient() const override {
+ return spell_check_panel_host_client_;
+ }
+ void ReplaceMisspelledRange(const WebString&) override;
+ void RemoveSpellingMarkers() override;
+ void RemoveSpellingMarkersUnderWords(
+ const WebVector<WebString>& words) override;
+ void SetContentSettingsClient(WebContentSettingsClient*) override;
+ void ReloadImage(const WebNode&) override;
void DidCallAddSearchProvider() override;
void DidCallIsSearchProviderInstalled() override;
- void ReplaceSelection(const WebString&) override;
+ WebSandboxFlags EffectiveSandboxFlagsForTesting() const override;
+ bool IsAllowedToDownloadWithoutUserActivation() const override;
bool FindForTesting(int identifier,
const WebString& search_text,
bool match_case,
@@ -293,21 +265,12 @@ class CORE_EXPORT WebLocalFrameImpl final
bool wrap_within_frame) override;
void SetTickmarks(const WebVector<WebRect>&) override;
WebNode ContextMenuNode() const override;
- WebFrameWidget* FrameWidget() const override;
void CopyImageAt(const WebPoint&) override;
void SaveImageAt(const WebPoint&) override;
+ void DispatchMessageEventWithOriginCheck(
+ const WebSecurityOrigin& intended_target_origin,
+ const WebDOMMessageEvent&) override;
void UsageCountChromeLoadTimes(const WebString& metric) override;
- FrameScheduler* Scheduler() const override;
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
- WebInputMethodController* GetInputMethodController() override;
- void ExtractSmartClipData(WebRect rect_in_viewport,
- WebString& clip_text,
- WebString& clip_html,
- WebRect& clip_rect) override;
- void AdvanceFocusInForm(WebFocusType) override;
- bool ShouldSuppressKeyboardForFocusedElement() override;
- void PerformMediaPlayerAction(const WebPoint&,
- const WebMediaPlayerAction&) override;
void OnPortalActivated(const base::UnguessableToken& portal_token,
mojo::ScopedInterfaceEndpointHandle portal_pipe,
mojo::ScopedInterfaceEndpointHandle portal_client_pipe,
@@ -317,10 +280,45 @@ class CORE_EXPORT WebLocalFrameImpl final
TransferableMessage message,
const WebSecurityOrigin& source_origin,
const base::Optional<WebSecurityOrigin>& target_origin) override;
- void AddMessageToConsoleImpl(const WebConsoleMessage&,
- bool discard_duplicates) override;
+ FrameScheduler* Scheduler() const override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
+ WebInputMethodController* GetInputMethodController() override;
+ WebAssociatedURLLoader* CreateAssociatedURLLoader(
+ const WebAssociatedURLLoaderOptions&) override;
+ void CheckCompleted() override;
+ WebSize GetScrollOffset() const override;
+ void SetScrollOffset(const WebSize&) override;
+ WebSize DocumentSize() const override;
+ bool HasVisibleContent() const override;
+ WebRect VisibleContentRect() const override;
+ void DispatchBeforePrintEvent() override;
+ int PrintBegin(const WebPrintParams&,
+ const WebNode& constrain_to_node) override;
+ float GetPrintPageShrink(int page) override;
+ float PrintPage(int page_to_print, cc::PaintCanvas*) override;
+ void PrintEnd() override;
+ void DispatchAfterPrintEvent() override;
+ bool GetPrintPresetOptionsForPlugin(const WebNode&,
+ WebPrintPresetOptions*) override;
+ void AdvanceFocusInForm(WebFocusType) override;
+ bool ShouldSuppressKeyboardForFocusedElement() override;
+ WebPerformance Performance() const override;
+ bool IsAdSubframe() const override;
+ void SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) override;
+ WebString GetLayerTreeAsTextForTesting(
+ bool show_debug_info = false) const override;
+ void PrintPagesForTesting(cc::PaintCanvas*, const WebSize&) override;
+ WebRect GetSelectionBoundsRectForTesting() const override;
+ void PerformMediaPlayerAction(const WebPoint&,
+ const WebMediaPlayerAction&) override;
+ void SetLifecycleState(mojom::FrameLifecycleState state) override;
+ void WasHidden() override;
+ void WasShown() override;
+ void SetAllowsCrossBrowsingInstanceFrameLookup() override;
+
+ void CollectGarbageForTesting();
- // WebNavigationControl methods:
+ // WebNavigationControl overrides:
bool DispatchBeforeUnloadEvent(bool) override;
void CommitNavigation(
std::unique_ptr<WebNavigationParams> navigation_params,
@@ -338,16 +336,12 @@ class CORE_EXPORT WebLocalFrameImpl final
void RenderFallbackContent() const override;
void SetCommittedFirstRealLoad() override;
bool HasCommittedFirstRealLoad() override;
- void DidDropNavigation() override;
- void MarkAsLoading() override;
- bool IsClientNavigationInitialHistoryLoad() override;
bool WillStartNavigation(
const WebNavigationInfo&,
bool is_history_navigation_in_new_child_frame) override;
-
- void SetLifecycleState(mojom::FrameLifecycleState state) override;
- void WasHidden() override;
- void WasShown() override;
+ void DidDropNavigation() override;
+ void MarkAsLoading() override;
+ bool IsClientNavigationInitialHistoryLoad() override;
void InitializeCoreFrame(
Page&,
@@ -420,8 +414,6 @@ class CORE_EXPORT WebLocalFrameImpl final
void SetFindEndstateFocusAndSelection();
void DidFailLoad(const ResourceError&, WebHistoryCommitType);
- void DidFailProvisionalLoad(const ResourceError&,
- const AtomicString& http_method);
void DidFinish();
void SetClient(WebLocalFrameClient* client) { client_ = client; }
@@ -436,10 +428,6 @@ class CORE_EXPORT WebLocalFrameImpl final
return text_check_client_;
}
- WebSpellCheckPanelHostClient* SpellCheckPanelHostClient() const override {
- return spell_check_panel_host_client_;
- }
-
FindInPage* GetFindInPage() const { return find_in_page_; }
TextFinder* GetTextFinder() const;
@@ -461,7 +449,10 @@ class CORE_EXPORT WebLocalFrameImpl final
virtual void Trace(blink::Visitor*);
- void SetAllowsCrossBrowsingInstanceFrameLookup() override;
+ protected:
+ // WebLocalFrame protected overrides:
+ void AddMessageToConsoleImpl(const WebConsoleMessage&,
+ bool discard_duplicates) override;
private:
friend LocalFrameClientImpl;
diff --git a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 95052961433..7d1b83eb5d9 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -91,6 +91,11 @@ void WebViewFrameWidget::RecordEndOfFrameMetrics(
web_view_->RecordEndOfFrameMetrics(frame_begin_time);
}
+std::unique_ptr<cc::BeginMainFrameMetrics>
+WebViewFrameWidget::GetBeginMainFrameMetrics() {
+ return web_view_->GetBeginMainFrameMetrics();
+}
+
void WebViewFrameWidget::UpdateLifecycle(LifecycleUpdate requested_update,
LifecycleUpdateReason reason) {
web_view_->UpdateLifecycle(requested_update, reason);
diff --git a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 5024fa08814..4b58d5d814b 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -58,6 +58,8 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
void EndCommitCompositorFrame() override;
void RecordStartOfFrameMetrics() override;
void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
+ std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics()
+ override;
void UpdateLifecycle(LifecycleUpdate requested_update,
LifecycleUpdateReason reason) override;
void ThemeChanged() override;
diff --git a/chromium/third_party/blink/renderer/core/frame/window.idl b/chromium/third_party/blink/renderer/core/frame/window.idl
index b5c9a7b6d37..0e43da8f8dd 100644
--- a/chromium/third_party/blink/renderer/core/frame/window.idl
+++ b/chromium/third_party/blink/renderer/core/frame/window.idl
@@ -199,11 +199,9 @@
[MeasureAs=PrefixedMutationObserverConstructor] attribute MutationObserverConstructor WebKitMutationObserver;
// Event handler attributes
- attribute EventHandler onanimationend;
- attribute EventHandler onanimationiteration;
- attribute EventHandler onanimationstart;
attribute EventHandler onsearch;
- attribute EventHandler ontransitionend;
+
+ // TODO(crbug.com/999895): Move to global_event_handlers.idl
attribute EventHandler onwebkitanimationend;
attribute EventHandler onwebkitanimationiteration;
attribute EventHandler onwebkitanimationstart;
@@ -215,7 +213,7 @@
attribute DOMMatrixConstructor WebKitCSSMatrix;
// TrustedTypes API: http://github.com/wicg/trusted-types
- [RuntimeEnabled=TrustedDOMTypes, Unforgeable] readonly attribute TrustedTypePolicyFactory TrustedTypes;
+ [RuntimeEnabled=TrustedDOMTypes, Unforgeable] readonly attribute TrustedTypePolicyFactory trustedTypes;
};
Window includes GlobalEventHandlers;
diff --git a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
index 51e3b0f07f5..2211ab079df 100644
--- a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
@@ -52,8 +52,7 @@
namespace blink {
-static bool IsAllowed(ScriptState* script_state,
- ExecutionContext* execution_context,
+static bool IsAllowed(ExecutionContext* execution_context,
bool is_eval,
const String& source) {
if (execution_context->IsDocument()) {
@@ -61,7 +60,7 @@ static bool IsAllowed(ScriptState* script_state,
if (!document->GetFrame())
return false;
if (is_eval && !document->GetContentSecurityPolicy()->AllowEval(
- script_state, SecurityViolationReportingPolicy::kReport,
+ SecurityViolationReportingPolicy::kReport,
ContentSecurityPolicy::kWillNotThrowException, source)) {
return false;
}
@@ -75,9 +74,9 @@ static bool IsAllowed(ScriptState* script_state,
ContentSecurityPolicy* policy =
worker_global_scope->GetContentSecurityPolicy();
if (is_eval && policy &&
- !policy->AllowEval(
- script_state, SecurityViolationReportingPolicy::kReport,
- ContentSecurityPolicy::kWillNotThrowException, source)) {
+ !policy->AllowEval(SecurityViolationReportingPolicy::kReport,
+ ContentSecurityPolicy::kWillNotThrowException,
+ source)) {
return false;
}
return true;
@@ -134,9 +133,9 @@ int WindowOrWorkerGlobalScope::setTimeout(
EventTarget& event_target,
V8Function* handler,
int timeout,
- const Vector<ScriptValue>& arguments) {
+ const HeapVector<ScriptValue>& arguments) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
- if (!IsAllowed(script_state, execution_context, false, g_empty_string))
+ if (!IsAllowed(execution_context, false, g_empty_string))
return 0;
if (timeout >= 0 && execution_context->IsDocument()) {
// FIXME: Crude hack that attempts to pass idle time to V8. This should
@@ -154,7 +153,7 @@ int WindowOrWorkerGlobalScope::setTimeout(
EventTarget& event_target,
const StringOrTrustedScript& string_or_trusted_script,
int timeout,
- const Vector<ScriptValue>& arguments,
+ const HeapVector<ScriptValue>& arguments,
ExceptionState& exception_state) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
Document* document = execution_context->IsDocument()
@@ -173,9 +172,9 @@ int WindowOrWorkerGlobalScope::setTimeoutFromString(
EventTarget& event_target,
const String& handler,
int timeout,
- const Vector<ScriptValue>&) {
+ const HeapVector<ScriptValue>&) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
- if (!IsAllowed(script_state, execution_context, true, handler))
+ if (!IsAllowed(execution_context, true, handler))
return 0;
// Don't allow setting timeouts to run empty functions. Was historically a
// performance issue.
@@ -197,9 +196,9 @@ int WindowOrWorkerGlobalScope::setInterval(
EventTarget& event_target,
V8Function* handler,
int timeout,
- const Vector<ScriptValue>& arguments) {
+ const HeapVector<ScriptValue>& arguments) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
- if (!IsAllowed(script_state, execution_context, false, g_empty_string))
+ if (!IsAllowed(execution_context, false, g_empty_string))
return 0;
ScheduledAction* action = ScheduledAction::Create(
script_state, execution_context, handler, arguments);
@@ -212,7 +211,7 @@ int WindowOrWorkerGlobalScope::setInterval(
EventTarget& event_target,
const StringOrTrustedScript& string_or_trusted_script,
int timeout,
- const Vector<ScriptValue>& arguments,
+ const HeapVector<ScriptValue>& arguments,
ExceptionState& exception_state) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
Document* document = execution_context->IsDocument()
@@ -231,9 +230,9 @@ int WindowOrWorkerGlobalScope::setIntervalFromString(
EventTarget& event_target,
const String& handler,
int timeout,
- const Vector<ScriptValue>&) {
+ const HeapVector<ScriptValue>&) {
ExecutionContext* execution_context = event_target.GetExecutionContext();
- if (!IsAllowed(script_state, execution_context, true, handler))
+ if (!IsAllowed(execution_context, true, handler))
return 0;
// Don't allow setting timeouts to run empty functions. Was historically a
// performance issue.
diff --git a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
index e3e7a41adaf..b378abf505d 100644
--- a/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
@@ -67,34 +67,34 @@ class WindowOrWorkerGlobalScope {
EventTarget&,
V8Function* handler,
int timeout,
- const Vector<ScriptValue>& arguments);
+ const HeapVector<ScriptValue>& arguments);
static int setTimeout(ScriptState*,
EventTarget&,
const StringOrTrustedScript&,
int timeout,
- const Vector<ScriptValue>&,
+ const HeapVector<ScriptValue>&,
ExceptionState&);
static int setTimeoutFromString(ScriptState*,
EventTarget&,
const String& handler,
int timeout,
- const Vector<ScriptValue>&);
+ const HeapVector<ScriptValue>&);
static int setInterval(ScriptState*,
EventTarget&,
V8Function* handler,
int timeout,
- const Vector<ScriptValue>&);
+ const HeapVector<ScriptValue>&);
static int setInterval(ScriptState*,
EventTarget&,
const StringOrTrustedScript&,
int timeout,
- const Vector<ScriptValue>&,
+ const HeapVector<ScriptValue>&,
ExceptionState&);
static int setIntervalFromString(ScriptState*,
EventTarget&,
const String& handler,
int timeout,
- const Vector<ScriptValue>&);
+ const HeapVector<ScriptValue>&);
static void clearTimeout(EventTarget&, int timeout_id);
static void clearInterval(EventTarget&, int timeout_id);
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 1ad5cbc2690..d15f87076fe 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen_options.h"
#include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.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_element_type_helpers.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
@@ -238,6 +239,19 @@ bool AllowedToRequestFullscreen(Document& document) {
return true;
}
+ if (document.IsImmersiveArOverlay()) {
+ // This is a workaround for lack of a user activation when an immersive-ar
+ // session is starting. If the app sets an element fullscreen in the "Enter
+ // AR" button click, that gets unfullscreened when the browser shows its AR
+ // session consent prompt. By the time the session starts, the 5-second
+ // timer for the initial user activation is likely to have expired. This
+ // also allows switching the active fullscreen element during the session.
+ // Note that exiting the immersive-ar session does FullyExitFullscreen to
+ // ensure a consistent post-session state.
+ DVLOG(1) << __func__ << ": allowing fullscreen immersive-ar DOM overlay";
+ return true;
+ }
+
String message = ExceptionMessages::FailedToExecute(
"requestFullscreen", "Element",
"API can only be initiated by a user gesture.");
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
index 7060ad321aa..87f1dd66759 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
@@ -50,10 +50,9 @@ class ScriptPromiseResolver;
// https://fullscreen.spec.whatwg.org/, especially its algorithms. It is a
// Document supplement as each document has some fullscreen state, and to
// actually enter and exit fullscreen it (indirectly) uses FullscreenController.
-class CORE_EXPORT Fullscreen final
- : public GarbageCollectedFinalized<Fullscreen>,
- public Supplement<Document>,
- public ContextLifecycleObserver {
+class CORE_EXPORT Fullscreen final : public GarbageCollected<Fullscreen>,
+ public Supplement<Document>,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(Fullscreen);
public:
@@ -127,7 +126,7 @@ class CORE_EXPORT Fullscreen final
// Stores the pending request, promise and the type for executing
// the asynchronous portion of the request.
- class PendingRequest : public GarbageCollectedFinalized<PendingRequest> {
+ class PendingRequest : public GarbageCollected<PendingRequest> {
public:
PendingRequest(Element* element,
RequestType type,
diff --git a/chromium/third_party/blink/renderer/core/geometry/BUILD.gn b/chromium/third_party/blink/renderer/core/geometry/BUILD.gn
index e9970e290a6..7f26639be1d 100644
--- a/chromium/third_party/blink/renderer/core/geometry/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/geometry/BUILD.gn
@@ -5,8 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("geometry") {
- split_count = 5
-
sources = [
"dom_matrix.cc",
"dom_matrix.h",
diff --git a/chromium/third_party/blink/renderer/core/html/BUILD.gn b/chromium/third_party/blink/renderer/core/html/BUILD.gn
index 4fb850c62b8..1becb65989e 100644
--- a/chromium/third_party/blink/renderer/core/html/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/html/BUILD.gn
@@ -2,12 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/split_static_library.gni")
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("html") {
- split_count = 4
-
sources = [
"anchor_element_metrics.cc",
"anchor_element_metrics.h",
@@ -505,6 +502,10 @@ blink_core_sources("html") {
"portal/dom_window_portal_host.h",
"portal/html_portal_element.cc",
"portal/html_portal_element.h",
+ "portal/portal_activate_event.cc",
+ "portal/portal_activate_event.h",
+ "portal/portal_contents.cc",
+ "portal/portal_contents.h",
"portal/portal_host.cc",
"portal/portal_host.h",
"portal/portal_post_message_helper.cc",
@@ -580,6 +581,7 @@ blink_core_sources("html") {
deps = [
"//services/metrics/public/cpp:metrics_cpp",
"//skia:skcms",
+ "//third_party/blink/public/strings",
"//third_party/blink/renderer/core/html/parser:parser",
]
}
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
index 44b251a16ee..cc6fd74fa51 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -283,10 +283,15 @@ void AnchorElementMetrics::MaybeReportViewportMetricsOnLoad(
if (!anchor_element.Href().ProtocolIsInHTTPFamily())
continue;
- if (anchor_element.VisibleBoundsInVisualViewport().IsEmpty() &&
- (!anchor_element.GetDocument().GetFrame() ||
- !GetRootDocument(anchor_element) ||
- !IsUrlIncrementedByOne(anchor_element))) {
+ // If the anchor doesn't have a valid frame/root document, skip it.
+ if (!anchor_element.GetDocument().GetFrame() ||
+ !GetRootDocument(anchor_element)) {
+ continue;
+ }
+
+ // Only anchors with width/height should be evaluated.
+ if (!anchor_element.GetLayoutObject() ||
+ anchor_element.GetLayoutObject()->AbsoluteBoundingBoxRect().IsEmpty()) {
continue;
}
@@ -297,9 +302,9 @@ void AnchorElementMetrics::MaybeReportViewportMetricsOnLoad(
anchor_elements_metrics.push_back(anchor_metric.value().CreateMetricsPtr());
- // Webpages with more than 40 anchors will stop processing at the 40th
+ // Webpages with more than 100 anchors will stop processing at the 100th
// anchor element.
- if (anchor_elements_metrics.size() >= 40)
+ if (anchor_elements_metrics.size() >= 100)
break;
}
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
index 778f218a497..44585d1242c 100644
--- a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_METRICS_H_
#include "base/optional.h"
-#include "third_party/blink/public/mojom/loader/navigation_predictor.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/navigation_predictor.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.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 00aa4df7f03..c08cce6006b 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
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/html/anchor_element_metrics_sender.h"
#include "base/metrics/histogram_macros.h"
-#include "services/service_manager/public/cpp/interface_provider.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"
@@ -113,7 +113,7 @@ bool AnchorElementMetricsSender::AssociateInterface() {
if (!document->GetFrame())
return false;
- document->GetFrame()->GetInterfaceProvider().GetInterface(
+ document->GetBrowserInterfaceBroker().GetInterface(
metrics_host_.BindNewPipeAndPassReceiver());
return true;
}
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 27e43cccec1..0e5b24774b3 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
@@ -24,7 +24,7 @@ class HTMLAnchorElement;
// AnchorElementMetricsSender is responsible to send anchor element metrics to
// the browser process for a given document.
class CORE_EXPORT AnchorElementMetricsSender final
- : public GarbageCollectedFinalized<AnchorElementMetricsSender>,
+ : public GarbageCollected<AnchorElementMetricsSender>,
public LocalFrameView::LifecycleNotificationObserver,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(AnchorElementMetricsSender);
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
index e90ba9abe82..fe400b9bc00 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
@@ -34,7 +34,7 @@ constexpr const char* kRGBA8ImagePixelFormatName = "uint8";
constexpr const char* kRGBA16ImagePixelFormatName = "uint16";
class CORE_EXPORT CanvasAsyncBlobCreator
- : public GarbageCollectedFinalized<CanvasAsyncBlobCreator> {
+ : public GarbageCollected<CanvasAsyncBlobCreator> {
public:
// This enum is used to back an UMA histogram, and should therefore be treated
// as append-only. Idle tasks are not implemented for some image types.
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
index c74201898b1..1976e144ea7 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache.h
@@ -23,7 +23,7 @@ class FontCachePurgePreventer;
class HTMLCanvasElement;
class CORE_EXPORT CanvasFontCache final
- : public GarbageCollectedFinalized<CanvasFontCache>,
+ : public GarbageCollected<CanvasFontCache>,
public Thread::TaskObserver {
USING_PRE_FINALIZER(CanvasFontCache, Dispose);
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
index 0ddd7b096b4..f8fa995ee93 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_font_cache_test.cc
@@ -23,7 +23,7 @@ class CanvasFontCacheTest : public PageTestBase {
void SetUp() override;
HTMLCanvasElement& CanvasElement() const { return *canvas_element_; }
- CanvasRenderingContext* Context2d() const;
+ CanvasRenderingContext* Context2D() const;
CanvasFontCache* Cache() { return GetDocument().GetCanvasFontCache(); }
private:
@@ -32,7 +32,7 @@ class CanvasFontCacheTest : public PageTestBase {
CanvasFontCacheTest::CanvasFontCacheTest() = default;
-CanvasRenderingContext* CanvasFontCacheTest::Context2d() const {
+CanvasRenderingContext* CanvasFontCacheTest::Context2D() const {
// If the following check fails, perhaps you forgot to call createContext
// in your test?
EXPECT_NE(nullptr, CanvasElement().RenderingContext());
@@ -50,7 +50,7 @@ void CanvasFontCacheTest::SetUp() {
CanvasContextCreationAttributesCore attributes;
attributes.alpha = true;
canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
- Context2d(); // Calling this for the checks
+ Context2D(); // Calling this for the checks
}
TEST_F(CanvasFontCacheTest, CacheHardLimit) {
@@ -58,7 +58,7 @@ TEST_F(CanvasFontCacheTest, CacheHardLimit) {
unsigned i;
for (i = 0; i < Cache()->HardMaxFonts() + 1; i++) {
font_string = String::Number(i + 1) + "px sans-serif";
- Context2d()->setFont(font_string);
+ Context2D()->setFont(font_string);
if (i < Cache()->HardMaxFonts()) {
EXPECT_TRUE(Cache()->IsInCache("1px sans-serif"));
} else {
@@ -69,22 +69,22 @@ TEST_F(CanvasFontCacheTest, CacheHardLimit) {
}
TEST_F(CanvasFontCacheTest, PageVisibilityChange) {
- Context2d()->setFont("10px sans-serif");
+ Context2D()->setFont("10px sans-serif");
EXPECT_TRUE(Cache()->IsInCache("10px sans-serif"));
GetPage().SetIsHidden(/*is_hidden=*/true, /*initial_state=*/false);
EXPECT_FALSE(Cache()->IsInCache("10px sans-serif"));
- Context2d()->setFont("15px sans-serif");
+ Context2D()->setFont("15px sans-serif");
EXPECT_FALSE(Cache()->IsInCache("10px sans-serif"));
EXPECT_TRUE(Cache()->IsInCache("15px sans-serif"));
- Context2d()->setFont("10px sans-serif");
+ Context2D()->setFont("10px sans-serif");
EXPECT_TRUE(Cache()->IsInCache("10px sans-serif"));
EXPECT_FALSE(Cache()->IsInCache("15px sans-serif"));
GetPage().SetIsHidden(/*is_hidden=*/false, /*initial_state=*/false);
- Context2d()->setFont("15px sans-serif");
- Context2d()->setFont("10px sans-serif");
+ Context2D()->setFont("15px sans-serif");
+ Context2D()->setFont("10px sans-serif");
EXPECT_TRUE(Cache()->IsInCache("10px sans-serif"));
EXPECT_TRUE(Cache()->IsInCache("15px sans-serif"));
}
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 df0f5e49065..4923001942f 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
@@ -26,9 +26,9 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
-#include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -116,27 +116,23 @@ void CanvasRenderingContext::DidDraw() {
StartListeningForDidProcessTask();
}
-void CanvasRenderingContext::NeedsFinalizeFrame() {
- StartListeningForDidProcessTask();
-}
-
void CanvasRenderingContext::DidProcessTask(
const base::PendingTask& /* pending_task */) {
StopListeningForDidProcessTask();
- // Call FinalizeFrame() on self first before informing host so that we can
- // present swap chain before exporting it.
- FinalizeFrame();
// The end of a script task that drew content to the canvas is the point
// at which the current frame may be considered complete.
if (Host())
- Host()->FinalizeFrame();
+ Host()->PreFinalizeFrame();
+ FinalizeFrame();
+ if (Host())
+ Host()->PostFinalizeFrame();
}
CanvasRenderingContext::ContextType CanvasRenderingContext::ContextTypeFromId(
const String& id) {
if (id == "2d")
- return kContext2d;
+ return kContext2D;
if (id == "experimental-webgl")
return kContextExperimentalWebgl;
if (id == "webgl")
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 35c2af842af..addd52d1cc2 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
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/skia/include/core/SkColorSpace.h"
+#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkImageInfo.h"
namespace blink {
@@ -64,7 +65,7 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
enum ContextType {
// Do not change assigned numbers of existing items: add new features to the
// end of the list.
- kContext2d = 0,
+ kContext2D = 0,
kContextExperimentalWebgl = 2,
kContextWebgl = 3,
kContextWebgl2 = 4,
@@ -86,14 +87,14 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
const CanvasColorParams& ColorParams() const { return color_params_; }
- virtual scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const = 0;
+ virtual scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) = 0;
virtual ContextType GetContextType() const = 0;
virtual bool IsComposited() const = 0;
virtual bool IsAccelerated() const = 0;
virtual bool IsOriginTopLeft() const {
// Canvas contexts have the origin of coordinates on the top left corner.
// Accelerated resources (e.g. GPU textures) have their origin of
- // coordinates in the uppper left corner.
+ // coordinates in the upper left corner.
return !IsAccelerated();
}
virtual bool ShouldAntialias() const { return false; }
@@ -134,8 +135,6 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
// of a presentable frame.
virtual void FinalizeFrame() {}
- void NeedsFinalizeFrame();
-
// Thread::TaskObserver implementation
void DidProcessTask(const base::PendingTask&) override;
void WillProcessTask(const base::PendingTask&) final {}
@@ -165,8 +164,7 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
virtual void SetFilterQuality(SkFilterQuality) { NOTREACHED(); }
virtual void Reshape(int width, int height) { NOTREACHED(); }
virtual void MarkLayerComposited() { NOTREACHED(); }
- virtual scoped_refptr<Uint8Array> PaintRenderingResultsToDataArray(
- SourceDrawingBuffer) {
+ virtual sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer) {
NOTREACHED();
return nullptr;
}
@@ -181,7 +179,8 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
}
// OffscreenCanvas-specific methods
- virtual void PushFrame() {}
+ virtual bool PushFrame() { return false; }
+ virtual bool IsDeferralEnabled() const { return false; }
virtual ImageBitmap* TransferToImageBitmap(ScriptState*) { return nullptr; }
bool WouldTaintOrigin(CanvasImageSource*);
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 a173b89318c..8b51ddf5ac6 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
+#include "base/feature_list.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
@@ -16,6 +17,10 @@
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
+namespace {
+const base::Feature kLowLatencyCanvas2dSwapChain{
+ "LowLatencyCanvas2dSwapChain", base::FEATURE_DISABLED_BY_DEFAULT};
+} // namespace
CanvasRenderingContextHost::CanvasRenderingContextHost(HostType host_type)
: host_type_(host_type) {}
@@ -161,7 +166,7 @@ CanvasRenderingContextHost::GetOrCreateCanvasResourceProviderImpl(
}
// Allow swap chains only if the runtime feature is enabled and we're
// in low latency mode too.
- if (RuntimeEnabledFeatures::Canvas2dSwapChainEnabled() &&
+ if (base::FeatureList::IsEnabled(kLowLatencyCanvas2dSwapChain) &&
LowLatencyEnabled() && want_acceleration) {
presentation_mode |=
CanvasResourceProvider::kAllowSwapChainPresentationMode;
@@ -203,7 +208,7 @@ CanvasColorParams CanvasRenderingContextHost::ColorParams() const {
ScriptPromise CanvasRenderingContextHost::convertToBlob(
ScriptState* script_state,
const ImageEncodeOptions* options,
- ExceptionState& exception_state) const {
+ ExceptionState& exception_state) {
WTF::String object_name = "Canvas";
if (this->IsOffscreenCanvas())
object_name = "OffscreenCanvas";
@@ -221,6 +226,12 @@ ScriptPromise CanvasRenderingContextHost::convertToBlob(
return ScriptPromise();
}
+ // It's possible that there are recorded commands that have not been resolved
+ // Finalize frame will be called in GetImage, but if there's no
+ // resourceProvider yet then the IsPaintable check will fail
+ if (RenderingContext())
+ RenderingContext()->FinalizeFrame();
+
if (!this->IsPaintable() || Size().IsEmpty()) {
error_msg << "The size of " << object_name << " is zero.";
exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
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 d90f1979efa..467b6298919 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,9 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual void DidDraw(const FloatRect& rect) = 0;
virtual void DidDraw() = 0;
- virtual void FinalizeFrame() = 0;
- virtual void PushFrame(scoped_refptr<CanvasResource> frame,
+ virtual void PreFinalizeFrame() = 0;
+ virtual void PostFinalizeFrame() = 0;
+ virtual bool PushFrame(scoped_refptr<CanvasResource> frame,
const SkIRect& damage_rect) = 0;
virtual bool OriginClean() const = 0;
virtual void SetOriginTainted() = 0;
@@ -77,6 +78,7 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual void Commit(scoped_refptr<CanvasResource> canvas_resource,
const SkIRect& damage_rect);
+ virtual void SetNeedsMatrixClipRestore() {}
bool IsPaintable() const;
@@ -95,9 +97,11 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
bool Is2d() const;
CanvasColorParams ColorParams() const;
+ // For deferred canvases this will have the side effect of drawing recorded
+ // commands in order to finalize the frame.
ScriptPromise convertToBlob(ScriptState*,
const ImageEncodeOptions*,
- ExceptionState&) const;
+ ExceptionState&);
// blink::CanvasImageSource
bool IsOffscreenCanvas() const override;
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 b57e5c02dfb..587e024ad80 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
@@ -290,7 +290,13 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContextInternal(
return nullptr;
}
- context_ = factory->Create(this, attributes);
+ // If this context is cross-origin, it should prefer to use the low-power GPU
+ LocalFrame* frame = GetDocument().GetFrame();
+ CanvasContextCreationAttributesCore recomputed_attributes = attributes;
+ if (frame && frame->IsCrossOriginSubframe())
+ recomputed_attributes.power_preference = "low-power";
+
+ context_ = factory->Create(this, recomputed_attributes);
if (!context_)
return nullptr;
@@ -387,41 +393,35 @@ void HTMLCanvasElement::DidDraw() {
DidDraw(FloatRect(0, 0, Size().Width(), Size().Height()));
}
-void HTMLCanvasElement::FinalizeFrame() {
- TRACE_EVENT0("blink", "HTMLCanvasElement::FinalizeFrame");
+void HTMLCanvasElement::PreFinalizeFrame() {
RecordCanvasSizeToUMA(size_);
- // FinalizeFrame indicates the end of a script task that may have rendered
+ // PreFinalizeFrame indicates the end of a script task that may have rendered
// into the canvas, now is a good time to unlock cache entries.
auto* resource_provider = ResourceProvider();
if (resource_provider)
resource_provider->ReleaseLockedImages();
- if (canvas2d_bridge_) {
- if (!LowLatencyEnabled())
- canvas2d_bridge_->FinalizeFrame();
- }
-
+ // Low-latency 2d canvases produce their frames after the resource gets
+ // single buffered.
if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
if (GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
const bool webgl_overlay_enabled =
RuntimeEnabledFeatures::WebGLImageChromiumEnabled() ||
context_->UsingSwapChain();
- // TryEnableSingleBuffering() the first time we FinalizeFrame().
+ // TryEnableSingleBuffering() the first time we finalize a frame.
if (!ResourceProvider()->IsSingleBuffered()) {
ResourceProvider()->TryEnableSingleBuffering();
if (Is3d() && webgl_overlay_enabled)
context_->ProvideBackBufferToResourceProvider();
}
+ }
+ }
+}
- if (canvas2d_bridge_) {
- canvas2d_bridge_->FlushRecording();
- } else {
- DCHECK(Is3d());
- if (!webgl_overlay_enabled)
- context_->PaintRenderingResultsToCanvas(kBackBuffer);
- }
-
+void HTMLCanvasElement::PostFinalizeFrame() {
+ if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
+ if (GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
const base::TimeTicks start_time = base::TimeTicks::Now();
const scoped_refptr<CanvasResource> canvas_resource =
ResourceProvider()->ProduceCanvasResource();
@@ -733,6 +733,7 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
context_->PaintRenderingResultsToCanvas(kFrontBuffer);
if (HasResourceProvider()) {
if (!context.ContextDisabled()) {
+ const ComputedStyle* style = GetComputedStyle();
// For 2D Canvas, there are two ways of render Canvas for printing:
// display list or image snapshot. Display list allows better PDF printing
// and we prefer this method.
@@ -746,7 +747,6 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
if (IsPrinting() && !Is3d() && canvas2d_bridge_) {
canvas2d_bridge_->FlushRecording();
if (canvas2d_bridge_->getLastRecord()) {
- const ComputedStyle* style = GetComputedStyle();
if (style && style->ImageRendering() != EImageRendering::kPixelated) {
context.Canvas()->save();
context.Canvas()->translate(r.X(), r.Y());
@@ -776,6 +776,7 @@ void HTMLCanvasElement::PaintInternal(GraphicsContext& context,
DCHECK(!snapshot->IsTextureBacked());
context.DrawImage(snapshot.get(), Image::kSyncDecode,
FloatRect(PixelSnappedIntRect(r)), &src_rect,
+ style && style->HasFilterInducingProperty(),
composite_operator);
}
}
@@ -824,9 +825,9 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::Snapshot(
if (ResourceProvider())
image_bitmap = ResourceProvider()->Snapshot();
} else {
- scoped_refptr<Uint8Array> data_array =
+ sk_sp<SkData> pixel_data =
context_->PaintRenderingResultsToDataArray(source_buffer);
- if (data_array) {
+ if (pixel_data) {
// If the accelerated canvas is too big, there is a logic in WebGL code
// path that scales down the drawing buffer to the maximum supported
// size. Hence, we need to query the adjusted size of DrawingBuffer.
@@ -837,7 +838,7 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::Snapshot(
info = info.makeColorSpace(ColorParams().GetSkColorSpace());
if (ColorParams().GetSkColorType() != kN32_SkColorType)
info = info.makeColorType(kRGBA_F16_SkColorType);
- image_bitmap = StaticBitmapImage::Create(std::move(data_array), info);
+ image_bitmap = StaticBitmapImage::Create(std::move(pixel_data), info);
}
}
} else if (canvas2d_bridge_) { // 2D Canvas
@@ -1004,9 +1005,10 @@ CanvasResourceDispatcher* HTMLCanvasElement::GetOrCreateResourceDispatcher() {
return frame_dispatcher_.get();
}
-void HTMLCanvasElement::PushFrame(scoped_refptr<CanvasResource> image,
+bool HTMLCanvasElement::PushFrame(scoped_refptr<CanvasResource> image,
const SkIRect& damage_rect) {
NOTIMPLEMENTED();
+ return false;
}
bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
@@ -1331,20 +1333,21 @@ bool HTMLCanvasElement::IsSupportedInteractiveCanvasFallback(
// A select element with a "multiple" attribute or with a display size greater
// than 1.
- if (auto* select_element = ToHTMLSelectElementOrNull(element)) {
+ if (auto* select_element = DynamicTo<HTMLSelectElement>(element)) {
if (select_element->IsMultiple() || select_element->size() > 1)
return true;
}
// An option element that is in a list of options of a select element with a
// "multiple" attribute or with a display size greater than 1.
- if (IsHTMLOptionElement(element) && element.parentNode() &&
- IsHTMLSelectElement(*element.parentNode())) {
- const HTMLSelectElement& select_element =
- ToHTMLSelectElement(*element.parentNode());
- if (select_element.IsMultiple() || select_element.size() > 1)
- return true;
- }
+ const auto* parent_select =
+ IsA<HTMLOptionElement>(element)
+ ? DynamicTo<HTMLSelectElement>(element.parentNode())
+ : nullptr;
+
+ if (parent_select &&
+ (parent_select->IsMultiple() || parent_select->size() > 1))
+ return true;
// An element that would not be interactive content except for having the
// tabindex attribute specified.
@@ -1389,6 +1392,8 @@ void HTMLCanvasElement::CreateLayer() {
base::DoNothing());
// Creates a placeholder layer first before Surface is created.
surface_layer_bridge_->CreateSolidColorLayer();
+ // This may cause the canvas to be composited.
+ SetNeedsCompositingUpdate();
}
}
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 dcbd75025d9..978e4fdd364 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
@@ -185,11 +185,12 @@ class CORE_EXPORT HTMLCanvasElement final
void DoDeferredPaintInvalidation();
- void FinalizeFrame() override;
+ void PreFinalizeFrame() override;
+ void PostFinalizeFrame() override;
CanvasResourceDispatcher* GetOrCreateResourceDispatcher() override;
- void PushFrame(scoped_refptr<CanvasResource> image,
+ bool PushFrame(scoped_refptr<CanvasResource> image,
const SkIRect& damage_rect) override;
// ContextLifecycleObserver and PageVisibilityObserver implementation
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
new file mode 100644
index 00000000000..a1ec4fef9bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
+
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+using HTMLCanvasElementTest = RenderingTest;
+
+TEST_F(HTMLCanvasElementTest, CreateLayerUpdatesCompositing) {
+ // Enable script so that the canvas will create a LayoutHTMLCanvas.
+ GetDocument().GetSettings()->SetScriptEnabled(true);
+
+ SetBodyInnerHTML("<canvas id='canvas'></canvas>");
+ auto* canvas = ToHTMLCanvasElement(GetDocument().getElementById("canvas"));
+ auto* layer = ToLayoutBoxModelObject(canvas->GetLayoutObject())->Layer();
+ ASSERT_TRUE(layer);
+ EXPECT_EQ(CompositingReason::kNone, layer->DirectCompositingReasons());
+
+ EXPECT_FALSE(layer->NeedsCompositingInputsUpdate());
+ canvas->CreateLayer();
+ EXPECT_TRUE(layer->NeedsCompositingInputsUpdate());
+ UpdateAllLifecyclePhasesForTest();
+ ASSERT_EQ(layer, ToLayoutBoxModelObject(canvas->GetLayoutObject())->Layer());
+ EXPECT_EQ(CompositingReason::kCanvas, layer->DirectCompositingReasons());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
index 2bec5d0bbf9..89509c0c592 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
@@ -298,23 +298,14 @@ TEST_F(ImageDataTest, TestCreateImageDataFromStaticBitmapImage) {
prepareSourcePixels(expected_f32_pixels_premul, true,
skcms_PixelFormat_RGBA_ffff);
- // Preparing ArrayBufferContents objects
- auto createBufferContent = [](auto& array, unsigned size) {
- WTF::ArrayBufferContents contents(
- size, 1, WTF::ArrayBufferContents::kNotShared,
- WTF::ArrayBufferContents::kDontInitialize);
- std::memcpy(contents.Data(), array, size);
- return contents;
- };
-
auto contents_u8_premul =
- createBufferContent(expected_u8_pixels_premul, kNumColorComponents);
+ SkData::MakeWithoutCopy(expected_u8_pixels_premul, kNumColorComponents);
auto contents_u8_unpremul =
- createBufferContent(expected_u8_pixels_unpremul, kNumColorComponents);
- auto contents_f16_premul =
- createBufferContent(expected_f16_pixels_premul, kNumColorComponents * 2);
- auto contents_f16_unpremul = createBufferContent(expected_f16_pixels_unpremul,
- kNumColorComponents * 2);
+ SkData::MakeWithoutCopy(expected_u8_pixels_unpremul, kNumColorComponents);
+ auto contents_f16_premul = SkData::MakeWithoutCopy(expected_f16_pixels_premul,
+ kNumColorComponents * 2);
+ auto contents_f16_unpremul = SkData::MakeWithoutCopy(
+ expected_f16_pixels_unpremul, kNumColorComponents * 2);
// Preparing StaticBitmapImage objects
auto info_u8_premul = SkImageInfo::Make(
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 a996c82b351..e2c73857658 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
@@ -33,7 +33,7 @@ enum class FormAssociationFlag {
};
class CORE_EXPORT CustomElementDefinition
- : public GarbageCollectedFinalized<CustomElementDefinition>,
+ : public GarbageCollected<CustomElementDefinition>,
public NameClient {
public:
// Each definition has an ID that is unique within the
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 d83fecfd726..d3f60588e0c 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
@@ -15,7 +15,7 @@ class CustomElementDefinition;
class Element;
class CORE_EXPORT CustomElementReaction
- : public GarbageCollectedFinalized<CustomElementReaction> {
+ : public GarbageCollected<CustomElementReaction> {
public:
CustomElementReaction(CustomElementDefinition&);
virtual ~CustomElementReaction() = default;
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 04910fae5cb..34dfc38337b 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
@@ -15,7 +15,7 @@ class CustomElementReaction;
class Element;
class CORE_EXPORT CustomElementReactionQueue final
- : public GarbageCollectedFinalized<CustomElementReactionQueue> {
+ : public GarbageCollected<CustomElementReactionQueue> {
public:
CustomElementReactionQueue();
~CustomElementReactionQueue();
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 b240c4d2503..d2f544c3fb2 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
@@ -22,7 +22,7 @@ namespace blink {
class Element;
-class Command : public GarbageCollectedFinalized<Command> {
+class Command : public GarbageCollected<Command> {
public:
Command() = default;
virtual ~Command() = default;
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 26c6ff4a7dc..946528c5dbd 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/custom/element_internals.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
@@ -31,6 +32,20 @@ bool IsValidityStateFlagsValid(const ValidityStateFlags* flags) {
}
} // anonymous namespace
+class CustomStatesTokenList : public DOMTokenList {
+ public:
+ CustomStatesTokenList(Element& element)
+ : DOMTokenList(element, g_null_name) {}
+
+ AtomicString value() const override { return TokenSet().SerializeToString(); }
+
+ void setValue(const AtomicString& new_value) override {
+ DidUpdateAttributeValue(value(), new_value);
+ // Should we have invalidation set for each of state tokens?
+ GetElement().PseudoStateChanged(CSSSelector::kPseudoState);
+ }
+};
+
ElementInternals::ElementInternals(HTMLElement& target) : target_(target) {
value_.SetUSVString(String());
}
@@ -41,7 +56,8 @@ void ElementInternals::Trace(Visitor* visitor) {
visitor->Trace(state_);
visitor->Trace(validity_flags_);
visitor->Trace(validation_anchor_);
- visitor->Trace(explicitly_set_attr_element_map);
+ visitor->Trace(custom_states_);
+ visitor->Trace(explicitly_set_attr_elements_map_);
ListedElement::Trace(visitor);
ScriptWrappable::Trace(visitor);
}
@@ -213,6 +229,16 @@ LabelsNodeList* ElementInternals::labels(ExceptionState& exception_state) {
return Target().labels();
}
+DOMTokenList* ElementInternals::states() {
+ if (!custom_states_)
+ custom_states_ = MakeGarbageCollected<CustomStatesTokenList>(Target());
+ return custom_states_;
+}
+
+bool ElementInternals::HasState(const AtomicString& state) const {
+ return custom_states_ && custom_states_->contains(state);
+}
+
const AtomicString& ElementInternals::FastGetAttribute(
const QualifiedName& attribute) const {
return accessibility_semantics_map_.at(attribute);
@@ -256,11 +282,47 @@ void ElementInternals::DidUpgrade() {
void ElementInternals::SetElementAttribute(const QualifiedName& name,
Element* element) {
- explicitly_set_attr_element_map.Set(name, element);
+ auto result = explicitly_set_attr_elements_map_.insert(name, nullptr);
+ if (result.is_new_entry) {
+ result.stored_value->value =
+ MakeGarbageCollected<HeapVector<Member<Element>>>();
+ } else {
+ result.stored_value->value->clear();
+ }
+ result.stored_value->value->push_back(element);
}
Element* ElementInternals::GetElementAttribute(const QualifiedName& name) {
- return explicitly_set_attr_element_map.at(name);
+ HeapVector<Member<Element>>* element_vector =
+ explicitly_set_attr_elements_map_.at(name);
+ if (!element_vector)
+ return nullptr;
+ DCHECK_EQ(element_vector->size(), 1u);
+ return element_vector->at(0);
+}
+
+HeapVector<Member<Element>> ElementInternals::GetElementArrayAttribute(
+ const QualifiedName& name,
+ bool is_null) {
+ is_null = true;
+ auto iter = explicitly_set_attr_elements_map_.find(name);
+ if (iter != explicitly_set_attr_elements_map_.end()) {
+ is_null = false;
+ return *(iter->value);
+ }
+ return HeapVector<Member<Element>>();
+}
+
+void ElementInternals::SetElementArrayAttribute(
+ const QualifiedName& name,
+ HeapVector<Member<Element>> elements,
+ bool is_null) {
+ if (is_null) {
+ explicitly_set_attr_elements_map_.erase(name);
+ return;
+ }
+ explicitly_set_attr_elements_map_.Set(
+ name, MakeGarbageCollected<HeapVector<Member<Element>>>(elements));
}
bool ElementInternals::IsTargetFormAssociated() const {
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 e324bf51b36..1b5185eb781 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
@@ -13,6 +13,7 @@
namespace blink {
+class DOMTokenList;
class HTMLElement;
class LabelsNodeList;
class ValidityStateFlags;
@@ -50,15 +51,23 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
bool checkValidity(ExceptionState& exception_state);
bool reportValidity(ExceptionState& exception_state);
LabelsNodeList* labels(ExceptionState& exception_state);
+ DOMTokenList* states();
+
+ bool HasState(const AtomicString& state) const;
// We need these functions because we are reflecting ARIA attributes.
// See dom/aria_attributes.idl.
const AtomicString& FastGetAttribute(const QualifiedName&) const;
void setAttribute(const QualifiedName& attribute, const AtomicString& value);
- // TODO(meredithl): Fill these in.
void SetElementAttribute(const QualifiedName& name, Element* element);
Element* GetElementAttribute(const QualifiedName& name);
+ HeapVector<Member<Element>> GetElementArrayAttribute(
+ const QualifiedName& name,
+ bool is_null);
+ void SetElementArrayAttribute(const QualifiedName&,
+ HeapVector<Member<Element>>,
+ bool is_null);
bool HasAttribute(const QualifiedName& attribute) const;
const HashMap<QualifiedName, AtomicString>& GetAttributes() const;
@@ -97,12 +106,15 @@ class CORE_EXPORT ElementInternals : public ScriptWrappable,
bool is_disabled_ = false;
Member<ValidityStateFlags> validity_flags_;
Member<Element> validation_anchor_;
+
+ Member<DOMTokenList> custom_states_;
+
HashMap<QualifiedName, AtomicString> accessibility_semantics_map_;
// See
// https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:element
- HeapHashMap<QualifiedName, WeakMember<Element>>
- explicitly_set_attr_element_map;
+ HeapHashMap<QualifiedName, Member<HeapVector<Member<Element>>>>
+ explicitly_set_attr_elements_map_;
DISALLOW_COPY_AND_ASSIGN(ElementInternals);
};
diff --git a/chromium/third_party/blink/renderer/core/html/custom/element_internals.idl b/chromium/third_party/blink/renderer/core/html/custom/element_internals.idl
index 438c7ad4122..ace4cd3d5d5 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/element_internals.idl
+++ b/chromium/third_party/blink/renderer/core/html/custom/element_internals.idl
@@ -24,5 +24,9 @@ interface ElementInternals {
[RaisesException] boolean reportValidity();
[RaisesException] readonly attribute NodeList labels;
+
+ // Custom state
+ // https://github.com/w3c/webcomponents/blob/gh-pages/proposals/custom-states-and-state-pseudo-class.md
+ [RuntimeEnabled=CustomStatePseudoClass] readonly attribute DOMTokenList states;
};
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_definition.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_definition.h
index e3403107072..79b5530aac3 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_definition.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_definition.h
@@ -37,7 +37,7 @@
namespace blink {
class V0CustomElementDefinition final
- : public GarbageCollectedFinalized<V0CustomElementDefinition> {
+ : public GarbageCollected<V0CustomElementDefinition> {
public:
V0CustomElementDefinition(const V0CustomElementDescriptor&,
V0CustomElementLifecycleCallbacks*);
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.h
index 6e3ed3839a5..ea4407a710e 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_lifecycle_callbacks.h
@@ -39,7 +39,7 @@ namespace blink {
class Element;
class V0CustomElementLifecycleCallbacks
- : public GarbageCollectedFinalized<V0CustomElementLifecycleCallbacks> {
+ : public GarbageCollected<V0CustomElementLifecycleCallbacks> {
public:
virtual ~V0CustomElementLifecycleCallbacks() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_queue_base.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_queue_base.h
index 81efcc35576..8855eee71d8 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_queue_base.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_queue_base.h
@@ -13,7 +13,7 @@
namespace blink {
class V0CustomElementMicrotaskQueueBase
- : public GarbageCollectedFinalized<V0CustomElementMicrotaskQueueBase> {
+ : public GarbageCollected<V0CustomElementMicrotaskQueueBase> {
public:
virtual ~V0CustomElementMicrotaskQueueBase() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_step.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_step.h
index c9f1cfc2a7b..27f49c78ef0 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_step.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_step.h
@@ -37,7 +37,7 @@
namespace blink {
class V0CustomElementMicrotaskStep
- : public GarbageCollectedFinalized<V0CustomElementMicrotaskStep> {
+ : public GarbageCollected<V0CustomElementMicrotaskStep> {
public:
V0CustomElementMicrotaskStep() = default;
virtual ~V0CustomElementMicrotaskStep() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_observer.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_observer.h
index 31888035245..1c95d5febcd 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_observer.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_observer.h
@@ -39,7 +39,7 @@ namespace blink {
class Element;
class V0CustomElementObserver
- : public GarbageCollectedFinalized<V0CustomElementObserver> {
+ : public GarbageCollected<V0CustomElementObserver> {
public:
virtual ~V0CustomElementObserver() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_processing_step.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_processing_step.h
index 145b69bb3b9..64e2314be3e 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_processing_step.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_processing_step.h
@@ -37,8 +37,7 @@
namespace blink {
class V0CustomElementProcessingStep
- : public GarbageCollectedFinalized<V0CustomElementProcessingStep> {
-
+ : public GarbageCollected<V0CustomElementProcessingStep> {
public:
V0CustomElementProcessingStep() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h
index 83c4f53646e..b810d5c081a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h
@@ -43,7 +43,7 @@ namespace blink {
class CustomElementRegistry;
class V0CustomElementRegistrationContext final
- : public GarbageCollectedFinalized<V0CustomElementRegistrationContext> {
+ : public GarbageCollected<V0CustomElementRegistrationContext> {
public:
V0CustomElementRegistrationContext();
~V0CustomElementRegistrationContext() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/DEPS b/chromium/third_party/blink/renderer/core/html/forms/DEPS
new file mode 100644
index 00000000000..4a90b3a5a0b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "file_input_type_test.cc": [
+ "+base/run_loop.h",
+ ]
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
index c852e492962..9d115cef3cd 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html/forms/base_temporal_input_type.h"
#include <limits>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.h"
@@ -41,14 +42,11 @@
namespace blink {
-using blink::WebLocalizedString;
-
static const int kMsecPerMinute = 60 * 1000;
static const int kMsecPerSecond = 1000;
String BaseTemporalInputType::BadInputText() const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationBadInputForDateTime);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_BAD_INPUT_DATETIME);
}
InputTypeView* BaseTemporalInputType::CreateView() {
@@ -96,15 +94,13 @@ bool BaseTemporalInputType::TypeMismatch() const {
}
String BaseTemporalInputType::RangeOverflowText(const Decimal& maximum) const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationRangeOverflowDateTime,
- LocalizeValue(Serialize(maximum)));
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_RANGE_OVERFLOW_DATETIME,
+ LocalizeValue(Serialize(maximum)));
}
String BaseTemporalInputType::RangeUnderflowText(const Decimal& minimum) const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationRangeUnderflowDateTime,
- LocalizeValue(Serialize(minimum)));
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_RANGE_UNDERFLOW_DATETIME,
+ LocalizeValue(Serialize(minimum)));
}
Decimal BaseTemporalInputType::DefaultValueForStepUp() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc
index 05bbb9dbc28..8e67cb196ca 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html/forms/checkbox_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -54,8 +55,7 @@ bool CheckboxInputType::ValueMissing(const String&) const {
}
String CheckboxInputType::ValueMissingText() const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationValueMissingForCheckbox);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX);
}
void CheckboxInputType::HandleKeyupEvent(KeyboardEvent& event) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
index 1d92adca3fc..d7eab0be39e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
@@ -151,4 +151,8 @@ void ChooserOnlyTemporalInputTypeView::CloseDateTimeChooser() {
date_time_chooser_->EndChooser();
}
+void ChooserOnlyTemporalInputTypeView::Blur() {
+ ClosePopupView();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h
index 78e4b1e4f52..5e6f0b64d04 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h
@@ -35,7 +35,7 @@
namespace blink {
class ChooserOnlyTemporalInputTypeView final
- : public GarbageCollectedFinalized<ChooserOnlyTemporalInputTypeView>,
+ : public GarbageCollected<ChooserOnlyTemporalInputTypeView>,
public KeyboardClickableInputTypeView,
public DateTimeChooserClient {
USING_GARBAGE_COLLECTED_MIXIN(ChooserOnlyTemporalInputTypeView);
@@ -50,6 +50,7 @@ class ChooserOnlyTemporalInputTypeView final
void CloseDateTimeChooser();
// InputTypeView functions:
+ void Blur() final;
void CreateShadowSubtree() override;
void ClosePopupView() override;
void ValueAttributeChanged() override;
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 f2343ba061a..5fa60c4aad8 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
@@ -73,6 +73,33 @@ Vector<char> ChooserResourceLoader::GetCalendarPickerJS() {
#endif
}
+Vector<char> ChooserResourceLoader::GetMonthPickerJS() {
+#if !defined(OS_ANDROID)
+ return UncompressResourceAsBinary(IDR_MONTH_PICKER_JS);
+#else
+ NOTREACHED();
+ return Vector<char>();
+#endif
+}
+
+Vector<char> ChooserResourceLoader::GetTimePickerStyleSheet() {
+#if !defined(OS_ANDROID)
+ return UncompressResourceAsBinary(IDR_TIME_PICKER_CSS);
+#else
+ NOTREACHED();
+ return Vector<char>();
+#endif
+}
+
+Vector<char> ChooserResourceLoader::GetTimePickerJS() {
+#if !defined(OS_ANDROID)
+ return UncompressResourceAsBinary(IDR_TIME_PICKER_JS);
+#else
+ NOTREACHED();
+ return Vector<char>();
+#endif
+}
+
Vector<char> ChooserResourceLoader::GetColorSuggestionPickerStyleSheet() {
#if !defined(OS_ANDROID)
return UncompressResourceAsBinary(IDR_COLOR_SUGGESTION_PICKER_CSS);
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 ac68494446e..7d6ec50931a 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
@@ -38,6 +38,15 @@ class ChooserResourceLoader {
// Returns the suggestion picker javascript as a string.
static Vector<char> GetCalendarPickerJS();
+ // Returns the month picker javascript as a string.
+ static Vector<char> GetMonthPickerJS();
+
+ // Returns the time picker stylesheet as a string.
+ static Vector<char> GetTimePickerStyleSheet();
+
+ // Returns the time picker javascript as a string.
+ static Vector<char> GetTimePickerJS();
+
// Returns the color suggestion picker stylesheet as a string.
static Vector<char> GetColorSuggestionPickerStyleSheet();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_client.h b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_client.h
index afaa77acfd0..828b2cfba30 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_client.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_client.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_COLOR_CHOOSER_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_COLOR_CHOOSER_CLIENT_H_
-#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink.h"
+#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
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 71c2174c9da..48a04b2297b 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/chooser_resource_loader.h"
@@ -143,8 +144,8 @@ void ColorChooserPopupUIController::WriteColorSuggestionPickerDocument(
data);
PagePopupClient::AddProperty("values", suggestion_values, data);
PagePopupClient::AddProperty(
- "otherColorLabel",
- GetLocale().QueryString(WebLocalizedString::kOtherColorLabel), data);
+ "otherColorLabel", GetLocale().QueryString(IDS_FORM_OTHER_COLOR_LABEL),
+ data);
if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
PagePopupClient::AddProperty("selectedColor",
client_->CurrentColor().Serialized(), data);
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 7cca96cd63b..6d0012ac143 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
@@ -41,7 +41,7 @@ class ColorChooserClient;
class LocalFrame;
class CORE_EXPORT ColorChooserUIController
- : public GarbageCollectedFinalized<ColorChooserUIController>,
+ : public GarbageCollected<ColorChooserUIController>,
public mojom::blink::ColorChooserClient,
public ColorChooser {
USING_GARBAGE_COLLECTED_MIXIN(ColorChooserUIController);
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 e750e7387d6..9b488c5ce0d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/color_input_type.h"
+#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
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 6f22f11f4ad..90a411ff92b 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
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/date_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/date_time_fields_state.h"
@@ -41,7 +42,6 @@
namespace blink {
-using blink::WebLocalizedString;
using namespace html_names;
static const int kDateDefaultStep = 1;
@@ -115,12 +115,12 @@ void DateInputType::SetupLayoutParameters(
if (!ParseToDateComponents(GetElement().FastGetAttribute(kMaxAttr),
&layout_parameters.maximum))
layout_parameters.maximum = DateComponents();
- layout_parameters.placeholder_for_day = GetLocale().QueryString(
- WebLocalizedString::kPlaceholderForDayOfMonthField);
+ layout_parameters.placeholder_for_day =
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD);
layout_parameters.placeholder_for_month =
- GetLocale().QueryString(WebLocalizedString::kPlaceholderForMonthField);
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD);
layout_parameters.placeholder_for_year =
- GetLocale().QueryString(WebLocalizedString::kPlaceholderForYearField);
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD);
}
bool DateInputType::IsValidFormat(bool has_year,
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 c6c5e749c1b..07cbacb625f 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
@@ -62,6 +62,13 @@ struct DateTimeChooserParameters {
double step_base;
bool required;
bool is_anchor_element_rtl;
+ // The fields below are used for type="time".
+ // For some locales the am/pm is the first field, so is_ampm_first informs
+ // the time popup when the am/pm column should be the first one.
+ bool is_ampm_first;
+ bool has_ampm;
+ bool has_second;
+ bool has_millisecond;
private:
// DateTimeSuggestionPtr is not copyable.
@@ -69,8 +76,7 @@ struct DateTimeChooserParameters {
};
// For pickers like color pickers and date pickers.
-class CORE_EXPORT DateTimeChooser
- : public GarbageCollectedFinalized<DateTimeChooser> {
+class CORE_EXPORT DateTimeChooser : public GarbageCollected<DateTimeChooser> {
public:
virtual ~DateTimeChooser();
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 16900991084..d06ef511d04 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
@@ -32,6 +32,9 @@
#include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
+#include "third_party/blink/renderer/core/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/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/chooser_resource_loader.h"
@@ -105,20 +108,17 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
String today_label_string;
String other_date_label_string;
if (parameters_->type == input_type_names::kMonth) {
- today_label_string =
- GetLocale().QueryString(WebLocalizedString::kThisMonthButtonLabel);
+ today_label_string = GetLocale().QueryString(IDS_FORM_THIS_MONTH_LABEL);
other_date_label_string =
- GetLocale().QueryString(WebLocalizedString::kOtherMonthLabel);
+ GetLocale().QueryString(IDS_FORM_OTHER_MONTH_LABEL);
} else if (parameters_->type == input_type_names::kWeek) {
- today_label_string =
- GetLocale().QueryString(WebLocalizedString::kThisWeekButtonLabel);
+ today_label_string = GetLocale().QueryString(IDS_FORM_THIS_WEEK_LABEL);
other_date_label_string =
- GetLocale().QueryString(WebLocalizedString::kOtherWeekLabel);
+ GetLocale().QueryString(IDS_FORM_OTHER_WEEK_LABEL);
} else {
- today_label_string =
- GetLocale().QueryString(WebLocalizedString::kCalendarToday);
+ today_label_string = GetLocale().QueryString(IDS_FORM_CALENDAR_TODAY);
other_date_label_string =
- GetLocale().QueryString(WebLocalizedString::kOtherDateLabel);
+ GetLocale().QueryString(IDS_FORM_OTHER_DATE_LABEL);
}
AddString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
@@ -130,6 +130,9 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data->Append(ChooserResourceLoader::GetCalendarPickerStyleSheet());
if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
data->Append(ChooserResourceLoader::GetCalendarPickerRefreshStyleSheet());
+ if (parameters_->type == input_type_names::kTime) {
+ data->Append(ChooserResourceLoader::GetTimePickerStyleSheet());
+ }
}
AddString(
"</style></head><body><div id=main>Loading...</div><script>\n"
@@ -154,32 +157,31 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data);
AddProperty("locale", parameters_->locale.GetString(), data);
AddProperty("todayLabel", today_label_string, data);
- AddProperty("clearLabel",
- GetLocale().QueryString(WebLocalizedString::kCalendarClear),
+ AddProperty("clearLabel", GetLocale().QueryString(IDS_FORM_CALENDAR_CLEAR),
data);
- AddProperty("weekLabel",
- GetLocale().QueryString(WebLocalizedString::kWeekNumberLabel),
+ AddProperty("weekLabel", GetLocale().QueryString(IDS_FORM_WEEK_NUMBER_LABEL),
+ data);
+ AddProperty("axShowMonthSelector",
+ GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR),
+ data);
+ AddProperty("axShowNextMonth",
+ GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_NEXT_MONTH), data);
+ AddProperty("axShowPreviousMonth",
+ GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH),
data);
- AddProperty(
- "axShowMonthSelector",
- GetLocale().QueryString(WebLocalizedString::kAXCalendarShowMonthSelector),
- data);
- AddProperty(
- "axShowNextMonth",
- GetLocale().QueryString(WebLocalizedString::kAXCalendarShowNextMonth),
- data);
- AddProperty(
- "axShowPreviousMonth",
- GetLocale().QueryString(WebLocalizedString::kAXCalendarShowPreviousMonth),
- data);
AddProperty("weekStartDay", locale_->FirstDayOfWeek(), data);
AddProperty("shortMonthLabels", locale_->ShortMonthLabels(), data);
AddProperty("dayLabels", locale_->WeekDayShortLabels(), data);
+ AddProperty("ampmLabels", locale_->TimeAMPMLabels(), data);
AddProperty("isLocaleRTL", locale_->IsRTL(), data);
AddProperty("isRTL", parameters_->is_anchor_element_rtl, data);
AddProperty("isFormControlsRefreshEnabled",
RuntimeEnabledFeatures::FormControlsRefreshEnabled(), data);
AddProperty("mode", parameters_->type.GetString(), data);
+ AddProperty("isAMPMFirst", parameters_->is_ampm_first, data);
+ AddProperty("hasAMPM", parameters_->has_ampm, data);
+ AddProperty("hasSecond", parameters_->has_second, data);
+ AddProperty("hasMillisecond", parameters_->has_millisecond, data);
if (parameters_->suggestions.size()) {
Vector<String> suggestion_values;
Vector<String> localized_suggestion_values;
@@ -203,14 +205,19 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
LayoutTheme::GetTheme().SupportsCalendarPicker(parameters_->type),
data);
AddProperty("otherDateLabel", other_date_label_string, data);
+
+ DCHECK(OwnerElement().GetComputedStyle());
+ WebColorScheme color_scheme =
+ OwnerElement().GetComputedStyle()->UsedColorScheme();
+
AddProperty("suggestionHighlightColor",
LayoutTheme::GetTheme()
- .ActiveListBoxSelectionBackgroundColor()
+ .ActiveListBoxSelectionBackgroundColor(color_scheme)
.Serialized(),
data);
AddProperty("suggestionHighlightTextColor",
LayoutTheme::GetTheme()
- .ActiveListBoxSelectionForegroundColor()
+ .ActiveListBoxSelectionForegroundColor(color_scheme)
.Serialized(),
data);
}
@@ -218,6 +225,12 @@ void DateTimeChooserImpl::WriteDocument(SharedBuffer* data) {
data->Append(ChooserResourceLoader::GetPickerCommonJS());
data->Append(ChooserResourceLoader::GetSuggestionPickerJS());
+ if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+ data->Append(ChooserResourceLoader::GetMonthPickerJS());
+ if (parameters_->type == input_type_names::kTime) {
+ data->Append(ChooserResourceLoader::GetTimePickerJS());
+ }
+ }
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 1183906349e..6b53778ceac 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
@@ -832,6 +832,20 @@ void DateTimeEditElement::SetEmptyValue(
field->SetEmptyValue(DateTimeFieldElement::kDispatchNoEvent);
}
+bool DateTimeEditElement::HasField(DateTimeField type) const {
+ for (const auto& field : fields_) {
+ if (field->Type() == type)
+ return true;
+ }
+
+ return false;
+}
+
+bool DateTimeEditElement::IsFirstFieldAMPM() const {
+ const auto* first_field = FieldAt(0);
+ return first_field && first_field->Type() == DateTimeField::kAMPM;
+}
+
bool DateTimeEditElement::HasFocusedField() {
return FocusedFieldIndex() != kInvalidFieldIndex;
}
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 4cf46d4a15f..02e0cee483a 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
@@ -38,6 +38,7 @@ namespace blink {
class DateTimeFieldsState;
class Locale;
class StepRange;
+enum class DateTimeField;
// DateTimeEditElement class contains numberic field and symbolc field for
// representing date and time, such as
@@ -109,6 +110,8 @@ class DateTimeEditElement final : public HTMLDivElement,
void StepUp();
String Value() const;
DateTimeFieldsState ValueAsDateTimeFieldsState() const;
+ bool HasField(DateTimeField) const;
+ bool IsFirstFieldAMPM() const;
private:
static const wtf_size_t kInvalidFieldIndex = UINT_MAX;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
index 289147f6274..73036e4b6a9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc
@@ -42,8 +42,9 @@ using namespace html_names;
DateTimeFieldElement::FieldOwner::~FieldOwner() = default;
DateTimeFieldElement::DateTimeFieldElement(Document& document,
- FieldOwner& field_owner)
- : HTMLSpanElement(document), field_owner_(&field_owner) {}
+ FieldOwner& field_owner,
+ DateTimeField type)
+ : HTMLSpanElement(document), field_owner_(&field_owner), type_(type) {}
void DateTimeFieldElement::Trace(Visitor* visitor) {
visitor->Trace(field_owner_);
@@ -232,4 +233,8 @@ int DateTimeFieldElement::ValueForARIAValueNow() const {
return ValueAsInteger();
}
+DateTimeField DateTimeFieldElement::Type() const {
+ return type_;
+}
+
} // namespace blink
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 da9a87ca553..ca56250f6d2 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
@@ -36,6 +36,18 @@ namespace blink {
class DateComponents;
class DateTimeFieldsState;
+enum class DateTimeField {
+ kYear,
+ kMonth,
+ kWeek,
+ kDay,
+ kHour,
+ kMinute,
+ kSecond,
+ kMillisecond,
+ kAMPM,
+};
+
// DateTimeFieldElement is base class of date time field element.
class DateTimeFieldElement : public HTMLSpanElement {
public:
@@ -77,11 +89,12 @@ class DateTimeFieldElement : public HTMLSpanElement {
virtual String Value() const = 0;
virtual String VisibleValue() const = 0;
void Trace(Visitor*) override;
+ DateTimeField Type() const;
static float ComputeTextWidth(const ComputedStyle&, const String&);
protected:
- DateTimeFieldElement(Document&, FieldOwner&);
+ DateTimeFieldElement(Document&, FieldOwner&, DateTimeField);
void FocusOnNextField();
virtual void HandleKeyboardEvent(KeyboardEvent&) = 0;
void Initialize(const AtomicString& pseudo,
@@ -105,6 +118,7 @@ class DateTimeFieldElement : public HTMLSpanElement {
bool SupportsFocus() const final;
Member<FieldOwner> field_owner_;
+ DateTimeField type_;
DISALLOW_COPY_AND_ASSIGN(DateTimeFieldElement);
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.cc
index 7774c78f02a..42222138ce7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_elements.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/html/forms/date_time_field_elements.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/forms/date_time_fields_state.h"
#include "third_party/blink/renderer/platform/text/date_components.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -32,20 +33,23 @@
namespace blink {
-using blink::WebLocalizedString;
-
-static String QueryString(WebLocalizedString::Name name) {
- return Locale::DefaultLocale().QueryString(name);
+static String QueryString(int resource_id) {
+ return Locale::DefaultLocale().QueryString(resource_id);
}
DateTimeAMPMFieldElement::DateTimeAMPMFieldElement(
Document& document,
FieldOwner& field_owner,
const Vector<String>& ampm_labels)
- : DateTimeSymbolicFieldElement(document, field_owner, ampm_labels, 0, 1) {
+ : DateTimeSymbolicFieldElement(document,
+ field_owner,
+ DateTimeField::kAMPM,
+ ampm_labels,
+ 0,
+ 1) {
DEFINE_STATIC_LOCAL(AtomicString, ampm_pseudo_id,
("-webkit-datetime-edit-ampm-field"));
- Initialize(ampm_pseudo_id, QueryString(WebLocalizedString::kAXAMPMFieldText));
+ Initialize(ampm_pseudo_id, QueryString(IDS_AX_AM_PM_FIELD_TEXT));
}
void DateTimeAMPMFieldElement::PopulateDateTimeFieldsState(
@@ -78,13 +82,13 @@ DateTimeDayFieldElement::DateTimeDayFieldElement(Document& document,
const Range& range)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kDay,
range,
Range(1, 31),
placeholder.IsEmpty() ? "--" : placeholder) {
DEFINE_STATIC_LOCAL(AtomicString, day_pseudo_id,
("-webkit-datetime-edit-day-field"));
- Initialize(day_pseudo_id,
- QueryString(WebLocalizedString::kAXDayOfMonthFieldText));
+ Initialize(day_pseudo_id, QueryString(IDS_AX_DAY_OF_MONTH_FIELD_TEXT));
}
void DateTimeDayFieldElement::PopulateDateTimeFieldsState(
@@ -123,6 +127,7 @@ DateTimeHourFieldElementBase::DateTimeHourFieldElementBase(
const Step& step)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kHour,
range,
hard_limits,
"--",
@@ -131,8 +136,8 @@ DateTimeHourFieldElementBase::DateTimeHourFieldElementBase(
void DateTimeHourFieldElementBase::Initialize() {
DEFINE_STATIC_LOCAL(AtomicString, hour_pseudo_id,
("-webkit-datetime-edit-hour-field"));
- DateTimeNumericFieldElement::Initialize(
- hour_pseudo_id, QueryString(WebLocalizedString::kAXHourFieldText));
+ DateTimeNumericFieldElement::Initialize(hour_pseudo_id,
+ QueryString(IDS_AX_HOUR_FIELD_TEXT));
}
void DateTimeHourFieldElementBase::SetValueAsDate(const DateComponents& date) {
@@ -380,14 +385,14 @@ DateTimeMillisecondFieldElement::DateTimeMillisecondFieldElement(
const Step& step)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kMillisecond,
range,
Range(0, 999),
"---",
step) {
DEFINE_STATIC_LOCAL(AtomicString, millisecond_pseudo_id,
("-webkit-datetime-edit-millisecond-field"));
- Initialize(millisecond_pseudo_id,
- QueryString(WebLocalizedString::kAXMillisecondFieldText));
+ Initialize(millisecond_pseudo_id, QueryString(IDS_AX_MILLISECOND_FIELD_TEXT));
}
void DateTimeMillisecondFieldElement::PopulateDateTimeFieldsState(
@@ -425,14 +430,14 @@ DateTimeMinuteFieldElement::DateTimeMinuteFieldElement(Document& document,
const Step& step)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kMinute,
range,
Range(0, 59),
"--",
step) {
DEFINE_STATIC_LOCAL(AtomicString, minute_pseudo_id,
("-webkit-datetime-edit-minute-field"));
- Initialize(minute_pseudo_id,
- QueryString(WebLocalizedString::kAXMinuteFieldText));
+ Initialize(minute_pseudo_id, QueryString(IDS_AX_MINUTE_FIELD_TEXT));
}
void DateTimeMinuteFieldElement::PopulateDateTimeFieldsState(
@@ -469,13 +474,13 @@ DateTimeMonthFieldElement::DateTimeMonthFieldElement(Document& document,
const Range& range)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kMonth,
range,
Range(1, 12),
placeholder.IsEmpty() ? "--" : placeholder) {
DEFINE_STATIC_LOCAL(AtomicString, month_pseudo_id,
("-webkit-datetime-edit-month-field"));
- Initialize(month_pseudo_id,
- QueryString(WebLocalizedString::kAXMonthFieldText));
+ Initialize(month_pseudo_id, QueryString(IDS_AX_MONTH_FIELD_TEXT));
}
void DateTimeMonthFieldElement::PopulateDateTimeFieldsState(
@@ -512,14 +517,14 @@ DateTimeSecondFieldElement::DateTimeSecondFieldElement(Document& document,
const Step& step)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kSecond,
range,
Range(0, 59),
"--",
step) {
DEFINE_STATIC_LOCAL(AtomicString, second_pseudo_id,
("-webkit-datetime-edit-second-field"));
- Initialize(second_pseudo_id,
- QueryString(WebLocalizedString::kAXSecondFieldText));
+ Initialize(second_pseudo_id, QueryString(IDS_AX_SECOND_FIELD_TEXT));
}
void DateTimeSecondFieldElement::PopulateDateTimeFieldsState(
@@ -558,13 +563,13 @@ DateTimeSymbolicMonthFieldElement::DateTimeSymbolicMonthFieldElement(
int maximum)
: DateTimeSymbolicFieldElement(document,
field_owner,
+ DateTimeField::kMonth,
labels,
minimum,
maximum) {
DEFINE_STATIC_LOCAL(AtomicString, month_pseudo_id,
("-webkit-datetime-edit-month-field"));
- Initialize(month_pseudo_id,
- QueryString(WebLocalizedString::kAXMonthFieldText));
+ Initialize(month_pseudo_id, QueryString(IDS_AX_MONTH_FIELD_TEXT));
}
void DateTimeSymbolicMonthFieldElement::PopulateDateTimeFieldsState(
@@ -603,14 +608,14 @@ DateTimeWeekFieldElement::DateTimeWeekFieldElement(Document& document,
const Range& range)
: DateTimeNumericFieldElement(document,
field_owner,
+ DateTimeField::kWeek,
range,
Range(DateComponents::kMinimumWeekNumber,
DateComponents::kMaximumWeekNumber),
"--") {
DEFINE_STATIC_LOCAL(AtomicString, week_pseudo_id,
("-webkit-datetime-edit-week-field"));
- Initialize(week_pseudo_id,
- QueryString(WebLocalizedString::kAXWeekOfYearFieldText));
+ Initialize(week_pseudo_id, QueryString(IDS_AX_WEEK_OF_YEAR_FIELD_TEXT));
}
void DateTimeWeekFieldElement::PopulateDateTimeFieldsState(
@@ -648,6 +653,7 @@ DateTimeYearFieldElement::DateTimeYearFieldElement(
: DateTimeNumericFieldElement(
document,
field_owner,
+ DateTimeField::kYear,
Range(parameters.minimum_year, parameters.maximum_year),
Range(DateComponents::MinimumYear(), DateComponents::MaximumYear()),
parameters.placeholder.IsEmpty() ? "----" : parameters.placeholder),
@@ -658,7 +664,7 @@ DateTimeYearFieldElement::DateTimeYearFieldElement(
DEFINE_STATIC_LOCAL(AtomicString, year_pseudo_id,
("-webkit-datetime-edit-year-field"));
- Initialize(year_pseudo_id, QueryString(WebLocalizedString::kAXYearFieldText));
+ Initialize(year_pseudo_id, QueryString(IDS_AX_YEAR_FIELD_TEXT));
}
static int CurrentFullYear() {
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 b0bcc91e08d..bb6b7b29c0a 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/date_time_local_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/date_time_fields_state.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
@@ -42,7 +43,6 @@
namespace blink {
-using blink::WebLocalizedString;
using namespace html_names;
static const int kDateTimeLocalDefaultStep = 60;
@@ -172,12 +172,12 @@ void DateTimeLocalInputType::SetupLayoutParameters(
if (!ParseToDateComponents(GetElement().FastGetAttribute(kMaxAttr),
&layout_parameters.maximum))
layout_parameters.maximum = DateComponents();
- layout_parameters.placeholder_for_day = GetLocale().QueryString(
- WebLocalizedString::kPlaceholderForDayOfMonthField);
+ layout_parameters.placeholder_for_day =
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD);
layout_parameters.placeholder_for_month =
- GetLocale().QueryString(WebLocalizedString::kPlaceholderForMonthField);
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD);
layout_parameters.placeholder_for_year =
- GetLocale().QueryString(WebLocalizedString::kPlaceholderForYearField);
+ GetLocale().QueryString(IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD);
}
bool DateTimeLocalInputType::IsValidFormat(bool has_year,
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 ea571884d05..3d15ec0fdce 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
@@ -47,11 +47,12 @@ bool DateTimeNumericFieldElement::Range::IsInRange(int value) const {
DateTimeNumericFieldElement::DateTimeNumericFieldElement(
Document& document,
FieldOwner& field_owner,
+ DateTimeField type,
const Range& range,
const Range& hard_limits,
const String& placeholder,
const DateTimeNumericFieldElement::Step& step)
- : DateTimeFieldElement(document, field_owner),
+ : DateTimeFieldElement(document, field_owner, type),
placeholder_(placeholder),
range_(range),
hard_limits_(hard_limits),
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 83edb4e3147..1f7dd54292e 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
@@ -65,6 +65,7 @@ class DateTimeNumericFieldElement : public DateTimeFieldElement {
protected:
DateTimeNumericFieldElement(Document&,
FieldOwner&,
+ DateTimeField,
const Range&,
const Range& hard_limits,
const String& placeholder,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
index 35276798a10..8efc4961024 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
@@ -49,10 +49,11 @@ static AtomicString MakeVisibleEmptyValue(const Vector<String>& symbols) {
DateTimeSymbolicFieldElement::DateTimeSymbolicFieldElement(
Document& document,
FieldOwner& field_owner,
+ DateTimeField type,
const Vector<String>& symbols,
int minimum,
int maximum)
- : DateTimeFieldElement(document, field_owner),
+ : DateTimeFieldElement(document, field_owner, type),
symbols_(symbols),
visible_empty_value_(MakeVisibleEmptyValue(symbols)),
selected_index_(-1),
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 c2e18f02005..7acc5122bfb 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
@@ -39,6 +39,7 @@ class DateTimeSymbolicFieldElement : public DateTimeFieldElement,
protected:
DateTimeSymbolicFieldElement(Document&,
FieldOwner&,
+ DateTimeField,
const Vector<String>&,
int minimum,
int maximum);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/email_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/email_input_type.cc
index fd9a06fcb95..6061d61571c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/email_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/email_input_type.cc
@@ -27,6 +27,7 @@
#include <unicode/unistr.h>
#include <unicode/uvernum.h>
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
@@ -42,8 +43,6 @@
namespace blink {
-using blink::WebLocalizedString;
-
// http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
static const char kLocalPartCharacters[] =
"abcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+/=?^_`{|}~.-";
@@ -212,14 +211,15 @@ bool EmailInputType::TypeMismatch() const {
String EmailInputType::TypeMismatchText() const {
String invalid_address = FindInvalidAddress(GetElement().value());
DCHECK(!invalid_address.IsNull());
- if (invalid_address.IsEmpty())
+ if (invalid_address.IsEmpty()) {
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailEmpty);
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY);
+ }
String at_sign = String("@");
wtf_size_t at_index = invalid_address.find('@');
if (at_index == kNotFound)
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailNoAtSign, at_sign,
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_NO_AT_SIGN, at_sign,
invalid_address);
// We check validity against an ASCII value because of difficulty to check
// invalid characters. However we should show Unicode value.
@@ -228,38 +228,38 @@ String EmailInputType::TypeMismatchText() const {
String domain = invalid_address.Substring(at_index + 1);
if (local_part.IsEmpty())
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailEmptyLocal, at_sign,
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_LOCAL, at_sign,
unicode_address);
if (domain.IsEmpty())
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailEmptyDomain, at_sign,
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_DOMAIN, at_sign,
unicode_address);
wtf_size_t invalid_char_index = local_part.Find(IsInvalidLocalPartCharacter);
if (invalid_char_index != kNotFound) {
unsigned char_length = U_IS_LEAD(local_part[invalid_char_index]) ? 2 : 1;
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailInvalidLocal,
- at_sign, local_part.Substring(invalid_char_index, char_length));
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_LOCAL, at_sign,
+ local_part.Substring(invalid_char_index, char_length));
}
invalid_char_index = domain.Find(IsInvalidDomainCharacter);
if (invalid_char_index != kNotFound) {
unsigned char_length = U_IS_LEAD(domain[invalid_char_index]) ? 2 : 1;
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailInvalidDomain,
- at_sign, domain.Substring(invalid_char_index, char_length));
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOMAIN, at_sign,
+ domain.Substring(invalid_char_index, char_length));
}
if (!CheckValidDotUsage(domain)) {
wtf_size_t at_index_in_unicode = unicode_address.find('@');
DCHECK_NE(at_index_in_unicode, kNotFound);
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmailInvalidDots,
- String("."), unicode_address.Substring(at_index_in_unicode + 1));
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOTS, String("."),
+ unicode_address.Substring(at_index_in_unicode + 1));
}
- if (GetElement().Multiple())
+ if (GetElement().Multiple()) {
return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForMultipleEmail);
- return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForEmail);
+ IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL);
+ }
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL);
}
bool EmailInputType::SupportsSelectionAPI() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc b/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc
index ae3bf862a59..b8096f302c8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h"
#include "services/service_manager/public/cpp/interface_provider.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/html/forms/date_time_chooser_client.h"
#include "third_party/blink/renderer/core/input_type_names.h"
@@ -117,9 +118,20 @@ mojom::blink::DateTimeChooser& ExternalDateTimeChooser::GetDateTimeChooser(
}
void ExternalDateTimeChooser::DidChooseValue(double value) {
+ // Cache the owner element first, because DidChooseValue might run
+ // JavaScript code and destroy |client|.
+ Element* element = client_ ? &client_->OwnerElement() : nullptr;
if (client_)
client_->DidChooseValue(value);
- // didChooseValue might run JavaScript code, and endChooser() might be
+
+ // Post an accessibility event on the owner element to indicate the
+ // value changed.
+ if (element) {
+ if (AXObjectCache* cache = element->GetDocument().ExistingAXObjectCache())
+ cache->HandleValueChanged(element);
+ }
+
+ // DidChooseValue might run JavaScript code, and endChooser() might be
// called. However DateTimeChooserCompletionImpl still has one reference to
// this object.
if (client_)
diff --git a/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser_test.cc b/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser_test.cc
index fce4e71a016..0593860f7f0 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/external_date_time_chooser_test.cc
@@ -8,14 +8,24 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/forms/date_time_chooser_client.h"
#include "third_party/blink/renderer/core/html/forms/html_input_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"
namespace blink {
-class ExternalDateTimeChooserTest : public testing::Test {};
+class ExternalDateTimeChooserTest : public testing::Test {
+ protected:
+ void SetUp() final {
+ dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
+ }
+ Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
+
+ private:
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+};
class TestDateTimeChooserClient final
- : public GarbageCollectedFinalized<TestDateTimeChooserClient>,
+ : public GarbageCollected<TestDateTimeChooserClient>,
public DateTimeChooserClient {
USING_GARBAGE_COLLECTED_MIXIN(TestDateTimeChooserClient);
@@ -59,4 +69,41 @@ TEST_F(ExternalDateTimeChooserTest, EndChooserShouldNotCrash) {
external_date_time_chooser->ResponseHandler(true, 0);
}
+// This is a regression test for crbug.com/1022302. When the label and the value
+// are the same in an option element,
+// HTMLInputElement::SetupDateTimeChooserParameters had set a null value. This
+// caused a crash because Mojo message pipe couldn't get a null pointer at the
+// receiving side.
+TEST_F(ExternalDateTimeChooserTest,
+ OpenDateTimeChooserShouldNotCrashWhenLabelAndValueIsTheSame) {
+ ScopedInputMultipleFieldsUIForTest input_multiple_fields_ui(false);
+ GetDocument().documentElement()->SetInnerHTMLFromString(R"HTML(
+ <input id=test type="date" list="src" />
+ <datalist id="src">
+ <option value='2019-12-31'>Hint</option>
+ <option value='2019-12-30'/>
+ <option>2019-12-29</option> // This has the same value in label and
+ // value attribute.
+ </datalist>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases(
+ DocumentLifecycle::LifecycleUpdateReason::kTest);
+ GetDocument().View()->RunPostLifecycleSteps();
+ HTMLInputElement* input =
+ ToHTMLInputElement(GetDocument().getElementById("test"));
+ ASSERT_TRUE(input);
+
+ DateTimeChooserParameters params;
+ bool success = input->SetupDateTimeChooserParameters(params);
+ EXPECT_TRUE(success);
+
+ auto* client = MakeGarbageCollected<TestDateTimeChooserClient>(
+ GetDocument().documentElement());
+ auto* external_date_time_chooser = ExternalDateTimeChooser::Create(client);
+ client->SetDateTimeChooser(external_date_time_chooser);
+ external_date_time_chooser->OpenDateTimeChooser(GetDocument().GetFrame(),
+ params);
+ // Crash should not happen after calling OpenDateTimeChooser().
+}
+
} // 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 c640df483ad..b86f742cbd4 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
@@ -254,11 +254,11 @@ void ExternalPopupMenu::GetPopupMenuInfo(WebPopupMenuInfo& info,
popup_item.checked = false;
if (IsA<HTMLHRElement>(item_element)) {
popup_item.type = WebMenuItemInfo::kSeparator;
- } else if (IsHTMLOptGroupElement(item_element)) {
+ } else if (IsA<HTMLOptGroupElement>(item_element)) {
popup_item.type = WebMenuItemInfo::kGroup;
} else {
popup_item.type = WebMenuItemInfo::kOption;
- popup_item.checked = ToHTMLOptionElement(item_element).Selected();
+ popup_item.checked = To<HTMLOptionElement>(item_element).Selected();
}
popup_item.enabled = !item_element.IsDisabledFormControl();
const ComputedStyle& style = *owner_element.ItemComputedStyle(item_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 5e05a5b9258..383f6a853c8 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
@@ -140,7 +140,7 @@ TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportTransform) {
WebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
WebWidget::LifecycleUpdateReason::kTest);
- HTMLSelectElement* select = ToHTMLSelectElement(
+ auto* select = To<HTMLSelectElement>(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
@@ -169,7 +169,7 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndex) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
- HTMLSelectElement* select = ToHTMLSelectElement(
+ auto* select = To<HTMLSelectElement>(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
@@ -189,7 +189,7 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndices) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
- HTMLSelectElement* select = ToHTMLSelectElement(
+ auto* select = To<HTMLSelectElement>(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
@@ -211,7 +211,7 @@ TEST_F(ExternalPopupMenuTest, DidAcceptIndicesClearSelect) {
RegisterMockedURLLoad("select.html");
LoadFrame("select.html");
- HTMLSelectElement* select = ToHTMLSelectElement(
+ auto* select = To<HTMLSelectElement>(
MainFrame()->GetFrame()->GetDocument()->getElementById("select"));
LayoutMenuList* menu_list = ToLayoutMenuList(select->GetLayoutObject());
ASSERT_TRUE(menu_list);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
index 834ba4ec068..60dbf7f1b8d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
@@ -28,8 +28,12 @@
#include "third_party/blink/renderer/core/html/forms/file_chooser.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include <utility>
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/file_path_conversion.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/page/chrome_client_impl.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -73,9 +77,10 @@ bool FileChooser::OpenFileChooser(ChromeClientImpl& chrome_client_impl) {
if (!frame)
return false;
chrome_client_impl_ = chrome_client_impl;
- frame->GetInterfaceProvider().GetInterface(
- &file_chooser_, frame->GetTaskRunner(TaskType::kInternalDefault));
- file_chooser_.set_connection_error_handler(
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ file_chooser_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kInternalDefault)));
+ file_chooser_.set_disconnect_handler(
WTF::Bind(&FileChooser::DidCloseChooser, WTF::Unretained(this)));
file_chooser_->OpenFileChooser(
params_.Clone(),
@@ -93,9 +98,10 @@ void FileChooser::EnumerateChosenDirectory() {
if (!frame)
return;
DCHECK(!chrome_client_impl_);
- frame->GetInterfaceProvider().GetInterface(
- &file_chooser_, frame->GetTaskRunner(TaskType::kInternalDefault));
- file_chooser_.set_connection_error_handler(
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ file_chooser_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kInternalDefault)));
+ file_chooser_.set_disconnect_handler(
WTF::Bind(&FileChooser::DidCloseChooser, WTF::Unretained(this)));
file_chooser_->EnumerateChosenDirectory(
std::move(params_->selected_files[0]),
@@ -143,8 +149,8 @@ void FileChooser::DidChooseFiles(mojom::blink::FileChooserResultPtr result) {
}
void FileChooser::DidCloseChooser() {
- // Close the binding explicitly to avoid this function is called again as a
- // connection error handler.
+ // Close the remote explicitly to avoid this function to be called again as a
+ // disconnect handler.
file_chooser_.reset();
// Some cleanup for OpenFileChooser() path.
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
index fc4d926f749..a98154be563 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
@@ -30,7 +30,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FILE_CHOOSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_FILE_CHOOSER_H_
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom-blink.h"
#include "third_party/blink/renderer/core/page/popup_opening_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -99,7 +99,7 @@ class FileChooser : public RefCounted<FileChooser> {
WeakPersistent<FileChooserClient> client_;
mojom::blink::FileChooserParamsPtr params_;
Persistent<ChromeClientImpl> chrome_client_impl_;
- mojom::blink::FileChooserPtr file_chooser_;
+ mojo::Remote<mojom::blink::FileChooser> file_chooser_;
};
CORE_EXPORT mojom::blink::FileChooserFileInfoPtr
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 538454bf84d..e34249b74a7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/html/forms/file_input_type.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -50,7 +51,6 @@
namespace blink {
-using blink::WebLocalizedString;
using mojom::blink::FileChooserParams;
using namespace html_names;
@@ -147,9 +147,8 @@ bool FileInputType::ValueMissing(const String& value) const {
String FileInputType::ValueMissingText() const {
return GetLocale().QueryString(
- GetElement().Multiple()
- ? WebLocalizedString::kValidationValueMissingForMultipleFile
- : WebLocalizedString::kValidationValueMissingForFile);
+ GetElement().Multiple() ? IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE
+ : IDS_FORM_VALIDATION_VALUE_MISSING_FILE);
}
void FileInputType::HandleDOMActivateEvent(Event& event) {
@@ -315,9 +314,8 @@ void FileInputType::CreateShadowSubtree() {
button->setAttribute(
kValueAttr,
AtomicString(GetLocale().QueryString(
- GetElement().Multiple()
- ? WebLocalizedString::kFileButtonChooseMultipleFilesLabel
- : WebLocalizedString::kFileButtonChooseFileLabel)));
+ GetElement().Multiple() ? IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL
+ : IDS_FORM_FILE_BUTTON_LABEL)));
button->SetShadowPseudoId(AtomicString("-webkit-file-upload-button"));
GetElement().UserAgentShadowRoot()->AppendChild(button);
}
@@ -337,13 +335,13 @@ void FileInputType::MultipleAttributeChanged() {
CHECK(!GetElement().UserAgentShadowRoot()->firstChild() ||
IsA<Element>(GetElement().UserAgentShadowRoot()->firstChild()));
if (Element* button =
- To<Element>(GetElement().UserAgentShadowRoot()->firstChild()))
+ To<Element>(GetElement().UserAgentShadowRoot()->firstChild())) {
button->setAttribute(
kValueAttr,
AtomicString(GetLocale().QueryString(
- GetElement().Multiple()
- ? WebLocalizedString::kFileButtonChooseMultipleFilesLabel
- : WebLocalizedString::kFileButtonChooseFileLabel)));
+ GetElement().Multiple() ? IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL
+ : IDS_FORM_FILE_BUTTON_LABEL)));
+ }
}
bool FileInputType::SetFiles(FileList* files) {
@@ -458,8 +456,7 @@ String FileInputType::DefaultToolTip(const InputTypeView&) const {
FileList* file_list = file_list_.Get();
unsigned list_size = file_list->length();
if (!list_size) {
- return GetLocale().QueryString(
- WebLocalizedString::kFileButtonNoFileSelectedLabel);
+ return GetLocale().QueryString(IDS_FORM_FILE_NO_FILE_LABEL);
}
StringBuilder names;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc b/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
index 3e63afe7702..76fc73e1966 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/html/forms/file_input_type.h"
+#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -140,7 +141,7 @@ TEST(FileInputTypeTest, DropTouchesNoPopupOpeningObserver) {
auto& input = *ToHTMLInputElement(doc.body()->firstChild());
base::RunLoop run_loop;
- MockFileChooser chooser(&doc.GetFrame()->GetInterfaceProvider(),
+ MockFileChooser chooser(doc.GetFrame()->GetBrowserInterfaceBroker(),
run_loop.QuitClosure());
DragData drag_data(DataObject::Create(), FloatPoint(), FloatPoint(),
kDragOperationCopy);
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 82907076088..3108eadb156 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
@@ -44,6 +44,10 @@ using namespace html_names;
namespace {
+// TODO(crbug.com/1008708): Remove this flag when we're sure the new behavior
+// is better than the previous one.
+constexpr bool kRestoreOnLoad = true;
+
inline HTMLFormElement* OwnerFormForState(const ListedElement& control) {
// Assume controls with form attribute have no owners because we restore
// state during parsing and form owners of such controls might be
@@ -58,6 +62,20 @@ const AtomicString& ControlType(const ListedElement& control) {
return To<ElementInternals>(control).Target().localName();
}
+bool IsDirtyControl(const ListedElement& control) {
+ if (control.IsFormControlElementWithState())
+ return ToHTMLFormControlElementWithState(control).UserHasEditedTheField();
+ if (control.IsElementInternals()) {
+ // We have no ways to know the dirtiness of a form-associated custom
+ // element. Assume it is dirty if it has focus.
+ // TODO(tkent): If this approach is not enough, we should check existence
+ // of past user-input events such as 'mousedown', 'keydown', 'touchstart'.
+ return control.ToHTMLElement().HasFocusWithin();
+ }
+ DCHECK(!control.ClassSupportsStateRestore());
+ return false;
+}
+
} // namespace
// ----------------------------------------------------------------------------
@@ -100,20 +118,19 @@ FormControlState FormControlState::Deserialize(
// ----------------------------------------------------------------------------
-class FormElementKey {
+class ControlKey {
public:
- FormElementKey(StringImpl* = nullptr, StringImpl* = nullptr);
- ~FormElementKey();
- FormElementKey(const FormElementKey&);
- FormElementKey& operator=(const FormElementKey&);
+ ControlKey(StringImpl* = nullptr, StringImpl* = nullptr);
+ ~ControlKey();
+ ControlKey(const ControlKey&);
+ ControlKey& operator=(const ControlKey&);
StringImpl* GetName() const { return name_; }
StringImpl* GetType() const { return type_; }
// Hash table deleted values, which are only constructed and never copied or
// destroyed.
- FormElementKey(WTF::HashTableDeletedValueType)
- : name_(HashTableDeletedValue()) {}
+ ControlKey(WTF::HashTableDeletedValueType) : name_(HashTableDeletedValue()) {}
bool IsHashTableDeletedValue() const {
return name_ == HashTableDeletedValue();
}
@@ -130,21 +147,21 @@ class FormElementKey {
StringImpl* type_;
};
-FormElementKey::FormElementKey(StringImpl* name, StringImpl* type)
+ControlKey::ControlKey(StringImpl* name, StringImpl* type)
: name_(name), type_(type) {
Ref();
}
-FormElementKey::~FormElementKey() {
+ControlKey::~ControlKey() {
Deref();
}
-FormElementKey::FormElementKey(const FormElementKey& other)
+ControlKey::ControlKey(const ControlKey& other)
: name_(other.GetName()), type_(other.GetType()) {
Ref();
}
-FormElementKey& FormElementKey::operator=(const FormElementKey& other) {
+ControlKey& ControlKey::operator=(const ControlKey& other) {
other.Ref();
Deref();
name_ = other.GetName();
@@ -152,47 +169,48 @@ FormElementKey& FormElementKey::operator=(const FormElementKey& other) {
return *this;
}
-void FormElementKey::Ref() const {
+void ControlKey::Ref() const {
if (GetName())
GetName()->AddRef();
if (GetType())
GetType()->AddRef();
}
-void FormElementKey::Deref() const {
+void ControlKey::Deref() const {
if (GetName())
GetName()->Release();
if (GetType())
GetType()->Release();
}
-inline bool operator==(const FormElementKey& a, const FormElementKey& b) {
+inline bool operator==(const ControlKey& a, const ControlKey& b) {
return a.GetName() == b.GetName() && a.GetType() == b.GetType();
}
-struct FormElementKeyHash {
- static unsigned GetHash(const FormElementKey&);
- static bool Equal(const FormElementKey& a, const FormElementKey& b) {
- return a == b;
- }
+struct ControlKeyHash {
+ static unsigned GetHash(const ControlKey&);
+ static bool Equal(const ControlKey& a, const ControlKey& b) { return a == b; }
static const bool safe_to_compare_to_empty_or_deleted = true;
};
-unsigned FormElementKeyHash::GetHash(const FormElementKey& key) {
- return StringHasher::HashMemory<sizeof(FormElementKey)>(&key);
+unsigned ControlKeyHash::GetHash(const ControlKey& key) {
+ return StringHasher::HashMemory<sizeof(ControlKey)>(&key);
}
-struct FormElementKeyHashTraits : WTF::GenericHashTraits<FormElementKey> {
- static void ConstructDeletedValue(FormElementKey& slot, bool) {
- new (NotNull, &slot) FormElementKey(WTF::kHashTableDeletedValue);
+struct ControlKeyHashTraits : WTF::GenericHashTraits<ControlKey> {
+ static void ConstructDeletedValue(ControlKey& slot, bool) {
+ new (NotNull, &slot) ControlKey(WTF::kHashTableDeletedValue);
}
- static bool IsDeletedValue(const FormElementKey& value) {
+ static bool IsDeletedValue(const ControlKey& value) {
return value.IsHashTableDeletedValue();
}
};
// ----------------------------------------------------------------------------
+// SavedFormState represents a set of FormControlState.
+// It typically manages controls associated to a single <form>. Controls
+// without owner forms are managed by a dedicated SavedFormState.
class SavedFormState {
USING_FAST_MALLOC(SavedFormState);
@@ -202,7 +220,7 @@ class SavedFormState {
static std::unique_ptr<SavedFormState> Deserialize(const Vector<String>&,
wtf_size_t& index);
void SerializeTo(Vector<String>&) const;
- bool IsEmpty() const { return state_for_new_form_elements_.IsEmpty(); }
+ bool IsEmpty() const { return state_for_new_controls_.IsEmpty(); }
void AppendControlState(const AtomicString& name,
const AtomicString& type,
const FormControlState&);
@@ -212,11 +230,11 @@ class SavedFormState {
Vector<String> GetReferencedFilePaths() const;
private:
- using FormElementStateMap = HashMap<FormElementKey,
- Deque<FormControlState>,
- FormElementKeyHash,
- FormElementKeyHashTraits>;
- FormElementStateMap state_for_new_form_elements_;
+ using ControlStateMap = HashMap<ControlKey,
+ Deque<FormControlState>,
+ ControlKeyHash,
+ ControlKeyHashTraits>;
+ ControlStateMap state_for_new_controls_;
wtf_size_t control_state_count_;
DISALLOW_COPY_AND_ASSIGN(SavedFormState);
@@ -256,8 +274,8 @@ std::unique_ptr<SavedFormState> SavedFormState::Deserialize(
void SavedFormState::SerializeTo(Vector<String>& state_vector) const {
state_vector.push_back(String::Number(control_state_count_));
- for (const auto& form_control : state_for_new_form_elements_) {
- const FormElementKey& key = form_control.key;
+ for (const auto& form_control : state_for_new_controls_) {
+ const ControlKey& key = form_control.key;
const Deque<FormControlState>& queue = form_control.value;
for (const FormControlState& form_control_state : queue) {
state_vector.push_back(key.GetName());
@@ -270,38 +288,38 @@ void SavedFormState::SerializeTo(Vector<String>& state_vector) const {
void SavedFormState::AppendControlState(const AtomicString& name,
const AtomicString& type,
const FormControlState& state) {
- FormElementKey key(name.Impl(), type.Impl());
- FormElementStateMap::iterator it = state_for_new_form_elements_.find(key);
- if (it != state_for_new_form_elements_.end()) {
+ ControlKey key(name.Impl(), type.Impl());
+ ControlStateMap::iterator it = state_for_new_controls_.find(key);
+ if (it != state_for_new_controls_.end()) {
it->value.push_back(state);
} else {
Deque<FormControlState> state_list;
state_list.push_back(state);
- state_for_new_form_elements_.Set(key, state_list);
+ state_for_new_controls_.Set(key, state_list);
}
control_state_count_++;
}
FormControlState SavedFormState::TakeControlState(const AtomicString& name,
const AtomicString& type) {
- if (state_for_new_form_elements_.IsEmpty())
+ if (state_for_new_controls_.IsEmpty())
return FormControlState();
- FormElementStateMap::iterator it = state_for_new_form_elements_.find(
- FormElementKey(name.Impl(), type.Impl()));
- if (it == state_for_new_form_elements_.end())
+ ControlStateMap::iterator it =
+ state_for_new_controls_.find(ControlKey(name.Impl(), type.Impl()));
+ if (it == state_for_new_controls_.end())
return FormControlState();
DCHECK_GT(it->value.size(), 0u);
FormControlState state = it->value.TakeFirst();
control_state_count_--;
if (it->value.empty())
- state_for_new_form_elements_.erase(it);
+ state_for_new_controls_.erase(it);
return state;
}
Vector<String> SavedFormState::GetReferencedFilePaths() const {
Vector<String> to_return;
- for (const auto& form_control : state_for_new_form_elements_) {
- const FormElementKey& key = form_control.key;
+ for (const auto& form_control : state_for_new_controls_) {
+ const ControlKey& key = form_control.key;
if (!Equal(key.GetType(), "file", 4))
continue;
const Deque<FormControlState>& queue = form_control.value;
@@ -316,9 +334,7 @@ Vector<String> SavedFormState::GetReferencedFilePaths() const {
// ----------------------------------------------------------------------------
-class FormKeyGenerator final
- : public GarbageCollectedFinalized<FormKeyGenerator> {
-
+class FormKeyGenerator final : public GarbageCollected<FormKeyGenerator> {
public:
FormKeyGenerator() = default;
@@ -417,14 +433,27 @@ DocumentState::DocumentState(Document& document) : document_(document) {}
void DocumentState::Trace(Visitor* visitor) {
visitor->Trace(document_);
- visitor->Trace(form_controls_);
+ visitor->Trace(control_list_);
}
void DocumentState::InvalidateControlList() {
- if (form_controls_dirty_)
+ if (is_control_list_dirty_)
return;
- form_controls_.resize(0);
- form_controls_dirty_ = true;
+ control_list_.resize(0);
+ is_control_list_dirty_ = true;
+}
+
+const DocumentState::ControlList& DocumentState::GetControlList() {
+ if (is_control_list_dirty_) {
+ for (auto& element : Traversal<Element>::DescendantsOf(*document_)) {
+ if (auto* control = ListedElement::From(element)) {
+ if (control->ClassSupportsStateRestore())
+ control_list_.push_back(control);
+ }
+ }
+ is_control_list_dirty_ = false;
+ }
+ return control_list_;
}
static String FormStateSignature() {
@@ -437,19 +466,10 @@ static String FormStateSignature() {
}
Vector<String> DocumentState::ToStateVector() {
- if (form_controls_dirty_) {
- for (auto& element : Traversal<Element>::DescendantsOf(*document_)) {
- if (auto* control = ListedElement::From(element)) {
- if (control->ClassSupportsStateRestore())
- form_controls_.push_back(control);
- }
- }
- form_controls_dirty_ = false;
- }
auto* key_generator = MakeGarbageCollected<FormKeyGenerator>();
std::unique_ptr<SavedFormStateMap> state_map =
base::WrapUnique(new SavedFormStateMap);
- for (auto& control : form_controls_) {
+ for (auto& control : GetControlList()) {
DCHECK(control->ToHTMLElement().isConnected());
if (!control->ShouldSaveAndRestoreFormControlState())
continue;
@@ -463,7 +483,7 @@ Vector<String> DocumentState::ToStateVector() {
}
Vector<String> state_vector;
- state_vector.ReserveInitialCapacity(form_controls_.size() * 4);
+ state_vector.ReserveInitialCapacity(GetControlList().size() * 4);
state_vector.push_back(FormStateSignature());
for (const auto& saved_form_state : *state_map) {
state_vector.push_back(saved_form_state.key);
@@ -478,29 +498,31 @@ Vector<String> DocumentState::ToStateVector() {
// ----------------------------------------------------------------------------
FormController::FormController(Document& document)
- : document_state_(MakeGarbageCollected<DocumentState>(document)) {}
+ : document_(document),
+ document_state_(MakeGarbageCollected<DocumentState>(document)) {}
FormController::~FormController() = default;
void FormController::Trace(Visitor* visitor) {
+ visitor->Trace(document_);
visitor->Trace(document_state_);
visitor->Trace(form_key_generator_);
}
-DocumentState* FormController::FormElementsState() const {
+DocumentState* FormController::ControlStates() const {
return document_state_.Get();
}
-void FormController::SetStateForNewFormElements(
+void FormController::SetStateForNewControls(
const Vector<String>& state_vector) {
- FormStatesFromStateVector(state_vector, saved_form_state_map_);
+ ControlStatesFromStateVector(state_vector, saved_form_state_map_);
}
-bool FormController::HasFormStates() const {
+bool FormController::HasControlStates() const {
return !saved_form_state_map_.IsEmpty();
}
-FormControlState FormController::TakeStateForFormElement(
+FormControlState FormController::TakeStateForControl(
const ListedElement& control) {
if (saved_form_state_map_.IsEmpty())
return FormControlState();
@@ -517,7 +539,7 @@ FormControlState FormController::TakeStateForFormElement(
return state;
}
-void FormController::FormStatesFromStateVector(
+void FormController::ControlStatesFromStateVector(
const Vector<String>& state_vector,
SavedFormStateMap& map) {
map.clear();
@@ -546,51 +568,85 @@ void FormController::WillDeleteForm(HTMLFormElement* form) {
}
void FormController::RestoreControlStateFor(ListedElement& control) {
- // We don't save state of a control with
- // ShouldSaveAndRestoreFormControlState() == false. But we need to skip
- // restoring process too because a control in another form might have the same
- // pair of name and type and saved its state.
- if (!control.ShouldSaveAndRestoreFormControlState())
+ if (kRestoreOnLoad && !document_->HasFinishedParsing())
return;
if (OwnerFormForState(control))
return;
- FormControlState state = TakeStateForFormElement(control);
- if (state.ValueSize() > 0)
- control.RestoreFormControlState(state);
+ RestoreControlStateInternal(control);
}
void FormController::RestoreControlStateIn(HTMLFormElement& form) {
+ if (kRestoreOnLoad && !document_->HasFinishedParsing())
+ return;
EventQueueScope scope;
const ListedElement::List& elements = form.ListedElements();
for (const auto& control : elements) {
if (!control->ClassSupportsStateRestore())
continue;
- if (!control->ShouldSaveAndRestoreFormControlState())
- continue;
if (OwnerFormForState(*control) != &form)
continue;
- FormControlState state = TakeStateForFormElement(*control);
- if (state.ValueSize() > 0) {
- // restoreFormControlState might dispatch input/change events.
- control->RestoreFormControlState(state);
- }
+ RestoreControlStateInternal(*control);
}
}
+void FormController::RestoreControlStateInternal(ListedElement& control) {
+ // We don't save state of a control with
+ // ShouldSaveAndRestoreFormControlState() == false. But we need to skip
+ // restoring process too because a control in another form might have the same
+ // pair of name and type and saved its state.
+ if (!control.ShouldSaveAndRestoreFormControlState())
+ return;
+ FormControlState state = TakeStateForControl(control);
+ if (state.ValueSize() <= 0)
+ return;
+ HTMLElement& element = control.ToHTMLElement();
+ if (element.IsDisabledFormControl() ||
+ element.FastHasAttribute(html_names::kReadonlyAttr))
+ return;
+ // If a user already edited the control, we should not overwrite it.
+ if (IsDirtyControl(control))
+ return;
+ // RestoreFormControlState might dispatch input/change events.
+ control.RestoreFormControlState(state);
+}
+
void FormController::RestoreControlStateOnUpgrade(ListedElement& control) {
DCHECK(control.ClassSupportsStateRestore());
if (!control.ShouldSaveAndRestoreFormControlState())
return;
- FormControlState state = TakeStateForFormElement(control);
+ FormControlState state = TakeStateForControl(control);
if (state.ValueSize() > 0)
control.RestoreFormControlState(state);
}
+void FormController::ScheduleRestore() {
+ if (!kRestoreOnLoad)
+ return;
+ document_->GetTaskRunner(TaskType::kInternalLoading)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&FormController::RestoreAllControlsInDocumentOrder,
+ WrapPersistent(this)));
+}
+
+void FormController::RestoreAllControlsInDocumentOrder() {
+ if (!document_->IsActive())
+ return;
+ HeapHashSet<Member<HTMLFormElement>> finished_forms;
+ EventQueueScope scope;
+ for (auto& control : document_state_->GetControlList()) {
+ auto* owner = OwnerFormForState(*control);
+ if (!owner)
+ RestoreControlStateFor(*control);
+ else if (finished_forms.insert(owner).is_new_entry)
+ RestoreControlStateIn(*owner);
+ }
+}
+
Vector<String> FormController::GetReferencedFilePaths(
const Vector<String>& state_vector) {
Vector<String> to_return;
SavedFormStateMap map;
- FormStatesFromStateVector(state_vector, map);
+ ControlStatesFromStateVector(state_vector, map);
for (const auto& saved_form_state : map)
to_return.AppendVector(saved_form_state.value->GetReferencedFilePaths());
return to_return;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_controller.h b/chromium/third_party/blink/renderer/core/html/forms/form_controller.h
index 4a5201871f1..038439dbc81 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_controller.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_controller.h
@@ -39,6 +39,7 @@ class HTMLFormElement;
class ListedElement;
class SavedFormState;
+// FormControlState represents state of a single form control.
class FormControlState {
DISALLOW_NEW();
@@ -78,51 +79,57 @@ inline void FormControlState::Append(const String& value) {
using SavedFormStateMap =
HashMap<AtomicString, std::unique_ptr<SavedFormState>>;
-class CORE_EXPORT DocumentState final
- : public GarbageCollectedFinalized<DocumentState> {
+class CORE_EXPORT DocumentState final : public GarbageCollected<DocumentState> {
public:
DocumentState(Document& document);
void Trace(Visitor*);
+ using ControlList = HeapVector<Member<ListedElement>, 64>;
void InvalidateControlList();
+ const ControlList& GetControlList();
Vector<String> ToStateVector();
private:
Member<Document> document_;
- using FormElementList = HeapVector<Member<ListedElement>, 64>;
- FormElementList form_controls_;
- bool form_controls_dirty_ = true;
+ ControlList control_list_;
+ bool is_control_list_dirty_ = true;
};
class CORE_EXPORT FormController final
- : public GarbageCollectedFinalized<FormController> {
+ : public GarbageCollected<FormController> {
public:
FormController(Document& document);
~FormController();
void Trace(Visitor*);
void InvalidateStatefulFormControlList();
- // This should be callled only by Document::formElementsState().
- DocumentState* FormElementsState() const;
- // This should be callled only by Document::setStateForNewFormElements().
- void SetStateForNewFormElements(const Vector<String>&);
+ // This should be called only by Document::FormElementsState().
+ DocumentState* ControlStates() const;
+ // This should be called only by Document::SetStateForNewFormElements().
+ void SetStateForNewControls(const Vector<String>&);
// Returns true if saved state is set to this object and there are entries
// which are not consumed yet.
- bool HasFormStates() const;
+ bool HasControlStates() const;
void WillDeleteForm(HTMLFormElement*);
void RestoreControlStateFor(ListedElement&);
void RestoreControlStateIn(HTMLFormElement&);
// For a upgraded form-associated custom element.
void RestoreControlStateOnUpgrade(ListedElement&);
+ void ScheduleRestore();
+
static Vector<String> GetReferencedFilePaths(
const Vector<String>& state_vector);
private:
- FormControlState TakeStateForFormElement(const ListedElement&);
- static void FormStatesFromStateVector(const Vector<String>&,
- SavedFormStateMap&);
+ FormControlState TakeStateForControl(const ListedElement&);
+ static void ControlStatesFromStateVector(const Vector<String>&,
+ SavedFormStateMap&);
+ // A helper for RestoreControlStateFor() and RestoreControlStateIn().
+ void RestoreControlStateInternal(ListedElement& control);
+ void RestoreAllControlsInDocumentOrder();
+ Member<Document> document_;
Member<DocumentState> document_state_;
SavedFormStateMap saved_form_state_map_;
Member<FormKeyGenerator> form_key_generator_;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_controller_test.cc b/chromium/third_party/blink/renderer/core/html/forms/form_controller_test.cc
index dddbe3c7d56..b278e95decd 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_controller_test.cc
@@ -21,7 +21,7 @@ TEST(DocumentStateTest, ToStateVectorConnected) {
doc.appendChild(html);
Node* body = html->appendChild(doc.CreateRawElement(html_names::kBodyTag));
To<Element>(body)->SetInnerHTMLFromString("<select form='ff'></select>");
- DocumentState* document_state = doc.GetFormController().FormElementsState();
+ DocumentState* document_state = doc.GetFormController().ControlStates();
Vector<String> state1 = document_state->ToStateVector();
// <signature>, <control-size>, <form-key>, <name>, <type>, <data-size(0)>
EXPECT_EQ(6u, state1.size());
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 5e9eb525234..4ebb24e3bc1 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
@@ -119,7 +119,7 @@ class CORE_EXPORT FormData final
// Represents entry, which is a pair of a name and a value.
// https://xhr.spec.whatwg.org/#concept-formdata-entry
// Entry objects are immutable.
-class FormData::Entry : public GarbageCollectedFinalized<FormData::Entry> {
+class FormData::Entry final : public GarbageCollected<FormData::Entry> {
public:
Entry(const String& name, const String& value);
Entry(const String& name, Blob* blob, const String& filename);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
index 79460a18287..5e2afac3475 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -109,6 +110,13 @@ void HTMLButtonElement::ParseAttribute(
}
void HTMLButtonElement::DefaultEventHandler(Event& event) {
+ DefaultEventHandlerInternal(event);
+
+ if (event.type() == event_type_names::kDOMActivate && formOwner())
+ formOwner()->DidActivateSubmitButton(this);
+}
+
+void HTMLButtonElement::DefaultEventHandlerInternal(Event& event) {
if (event.type() == event_type_names::kDOMActivate &&
!IsDisabledFormControl()) {
if (Form() && type_ == SUBMIT) {
@@ -203,10 +211,6 @@ bool HTMLButtonElement::IsInteractiveContent() const {
return true;
}
-bool HTMLButtonElement::SupportsAutofocus() const {
- return true;
-}
-
bool HTMLButtonElement::MatchesDefaultPseudoClass() const {
// HTMLFormElement::findDefaultButton() traverses the tree. So we check
// canBeSuccessfulSubmitButton() first for early return.
@@ -223,4 +227,16 @@ Node::InsertionNotificationRequest HTMLButtonElement::InsertedInto(
return request;
}
+EventDispatchHandlingState* HTMLButtonElement::PreDispatchEventHandler(
+ Event& event) {
+ if (Form() && CanBeSuccessfulSubmitButton())
+ Form()->WillActivateSubmitButton(this);
+ return nullptr;
+}
+
+void HTMLButtonElement::DidPreventDefault(const Event& event) {
+ if (auto* form = formOwner())
+ form->DidActivateSubmitButton(this);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.h
index 77b2eb56f12..0aaf454d54c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.h
@@ -64,7 +64,6 @@ class HTMLButtonElement final : public HTMLFormControlElement {
bool IsLabelable() const override { return true; }
bool TypeShouldForceLegacyLayout() const final { return true; }
bool IsInteractiveContent() const override;
- bool SupportsAutofocus() const override;
bool MatchesDefaultPseudoClass() const override;
bool CanBeSuccessfulSubmitButton() const override;
@@ -79,6 +78,13 @@ class HTMLButtonElement final : public HTMLFormControlElement {
bool IsOptionalFormControl() const override { return true; }
bool RecalcWillValidate() const override;
+ // TODO(crbug.com/1013385): Remove PreDispatchEventHandler, DidPreventDefault,
+ // and DefaultEventHandlerInternal. They are here to temporarily fix form
+ // double-submit.
+ EventDispatchHandlingState* PreDispatchEventHandler(Event&) override;
+ void DidPreventDefault(const Event&) final;
+ void DefaultEventHandlerInternal(Event&);
+
Type type_;
bool is_activated_submit_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.idl
index 9f41e83a751..ab21763b1c8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_button_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_button_element.idl
@@ -23,7 +23,6 @@
Exposed=Window,
HTMLConstructor
] interface HTMLButtonElement : HTMLElement {
- [CEReactions, Reflect] attribute boolean autofocus;
[CEReactions, Reflect] attribute boolean disabled;
[ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
[CEReactions, RaisesException=Setter] attribute URLString formAction;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h b/chromium/third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h
index 3559c2862a7..4b68f900289 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h
@@ -22,7 +22,7 @@ class HTMLDataListOptionsCollection : public HTMLCollection {
}
HTMLOptionElement* Item(unsigned offset) const {
- return ToHTMLOptionElement(HTMLCollection::item(offset));
+ return To<HTMLOptionElement>(HTMLCollection::item(offset));
}
bool ElementMatches(const HTMLElement&) const;
@@ -36,7 +36,7 @@ DEFINE_TYPE_CASTS(HTMLDataListOptionsCollection,
inline bool HTMLDataListOptionsCollection::ElementMatches(
const HTMLElement& element) const {
- return IsHTMLOptionElement(element);
+ return IsA<HTMLOptionElement>(element);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
index edd161af711..aa18e645d9c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -33,7 +33,6 @@
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/validity_state.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -179,14 +178,6 @@ bool HTMLFormControlElement::IsDisabledOrReadOnly() const {
return IsDisabledFormControl() || IsReadOnly();
}
-bool HTMLFormControlElement::SupportsAutofocus() const {
- return false;
-}
-
-bool HTMLFormControlElement::IsAutofocusable() const {
- return FastHasAttribute(kAutofocusAttr) && SupportsAutofocus();
-}
-
void HTMLFormControlElement::SetAutofillState(WebAutofillState autofill_state) {
if (autofill_state == autofill_state_)
return;
@@ -214,41 +205,6 @@ const AtomicString& HTMLFormControlElement::autocapitalize() const {
return g_empty_atom;
}
-static bool ShouldAutofocusOnAttach(const HTMLFormControlElement* element) {
- if (!element->IsAutofocusable())
- return false;
-
- Document& doc = element->GetDocument();
-
- // The rest of this function implements part of the autofocus algorithm in the
- // spec:
- // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofocusing-a-form-control:-the-autofocus-attribute
-
- // Step 4 of the spec algorithm above.
- if (doc.IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) {
- doc.AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kSecurity,
- mojom::ConsoleMessageLevel::kError,
- "Blocked autofocusing on a form control because the form's frame is "
- "sandboxed and the 'allow-scripts' permission is not set."));
- return false;
- }
-
- // TODO(mustaq): Add Step 5 checks.
-
- // Step 6 of the spec algorithm above.
- if (!doc.IsInMainFrame() &&
- !doc.TopFrameOrigin()->CanAccess(doc.GetSecurityOrigin())) {
- doc.AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kSecurity,
- mojom::ConsoleMessageLevel::kError,
- "Blocked autofocusing on a form control in a cross-origin subframe."));
- return false;
- }
-
- return true;
-}
-
void HTMLFormControlElement::AttachLayoutTree(AttachContext& context) {
HTMLElement::AttachLayoutTree(context);
@@ -259,11 +215,6 @@ void HTMLFormControlElement::AttachLayoutTree(AttachContext& context) {
// to the base class's attachLayoutTree() because that can sometimes do a
// close on the layoutObject.
GetLayoutObject()->UpdateFromElement();
-
- // FIXME: Autofocus handling should be moved to insertedInto according to
- // the standard.
- if (ShouldAutofocusOnAttach(this))
- GetDocument().SetAutofocusElement(this);
}
void HTMLFormControlElement::DidMoveToNewDocument(Document& old_document) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
index df09c1983db..dd726577dd4 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
@@ -96,8 +96,6 @@ class CORE_EXPORT HTMLFormControlElement : public HTMLElement,
bool IsReadOnly() const;
bool IsDisabledOrReadOnly() const;
- bool IsAutofocusable() const;
-
bool MayTriggerVirtualKeyboard() const override;
WebAutofillState GetAutofillState() const { return autofill_state_; }
@@ -153,7 +151,6 @@ class CORE_EXPORT HTMLFormControlElement : public HTMLElement,
void DidRecalcStyle(const StyleRecalcChange) override;
virtual void ResetImpl() {}
- virtual bool SupportsAutofocus() const;
private:
bool IsFormControlElement() const final { return true; }
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc
index 9d555103171..f3f5c1ca7b3 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element_test.cc
@@ -18,7 +18,7 @@ namespace blink {
namespace {
class MockFormValidationMessageClient
- : public GarbageCollectedFinalized<MockFormValidationMessageClient>,
+ : public GarbageCollected<MockFormValidationMessageClient>,
public ValidationMessageClient {
USING_GARBAGE_COLLECTED_MIXIN(MockFormValidationMessageClient);
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 1c89d7140e4..2340e4bcce3 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
@@ -94,6 +94,7 @@ void HTMLFormElement::Trace(Visitor* visitor) {
visitor->Trace(listed_elements_);
visitor->Trace(image_elements_);
visitor->Trace(planned_navigation_);
+ visitor->Trace(activated_submit_button_);
HTMLElement::Trace(visitor);
}
@@ -331,10 +332,27 @@ void HTMLFormElement::PrepareForSubmission(
planned_navigation_ = nullptr;
Submit(event, submit_button);
}
+ if (!planned_navigation_ || activated_submit_button_)
+ return;
+ base::AutoReset<bool> submit_scope(&is_submitting_, true);
+ SubmitForm(planned_navigation_);
+ planned_navigation_ = nullptr;
+}
+
+void HTMLFormElement::WillActivateSubmitButton(
+ HTMLFormControlElement* element) {
+ if (!activated_submit_button_)
+ activated_submit_button_ = element;
+}
+
+void HTMLFormElement::DidActivateSubmitButton(HTMLFormControlElement* element) {
+ if (activated_submit_button_ != element)
+ return;
+ activated_submit_button_ = nullptr;
if (!planned_navigation_)
return;
base::AutoReset<bool> submit_scope(&is_submitting_, true);
- ScheduleFormSubmission(planned_navigation_);
+ SubmitForm(planned_navigation_);
planned_navigation_ = nullptr;
}
@@ -449,14 +467,14 @@ void HTMLFormElement::Submit(Event* event,
}
if (form_submission->Method() == FormSubmission::kDialogMethod) {
SubmitDialog(form_submission);
- } else if (in_user_js_submit_event_) {
+ } else if (in_user_js_submit_event_ || activated_submit_button_) {
// Need to postpone the submission in order to make this cancelable by
// another submission request.
planned_navigation_ = form_submission;
} else {
// This runs JavaScript code if action attribute value is javascript:
// protocol.
- ScheduleFormSubmission(form_submission);
+ SubmitForm(form_submission);
}
}
@@ -489,13 +507,16 @@ FormData* HTMLFormElement::ConstructEntryList(
return &form_data;
}
-void HTMLFormElement::ScheduleFormSubmission(FormSubmission* submission) {
+// Actually submit the form - navigate now.
+void HTMLFormElement::SubmitForm(FormSubmission* submission) {
DCHECK(submission->Method() == FormSubmission::kPostMethod ||
submission->Method() == FormSubmission::kGetMethod);
DCHECK(submission->Data());
DCHECK(submission->Form());
if (submission->Action().IsEmpty())
return;
+ if (!GetDocument().IsActive())
+ return;
if (GetDocument().IsSandboxed(WebSandboxFlags::kForms)) {
// FIXME: This message should be moved off the console once a solution to
// https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
@@ -598,6 +619,11 @@ void HTMLFormElement::Disassociate(ListedElement& e) {
listed_elements_are_dirty_ = true;
listed_elements_.clear();
RemoveFromPastNamesMap(e.ToHTMLElement());
+
+ if (activated_submit_button_ != &e)
+ return;
+ activated_submit_button_ = nullptr;
+ planned_navigation_ = nullptr;
}
bool HTMLFormElement::IsURLAttribute(const Attribute& attribute) const {
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 eaab0fd48d7..ae78e4f578d 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
@@ -118,6 +118,12 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
unsigned UniqueRendererFormId() const { return unique_renderer_form_id_; }
+ // TODO(crbug.com/1013385): Remove WillActivateSubmitButton,
+ // DidActivateSubmitButton, and RemovedAssociatedControlElement. They are
+ // here temporarily to fix form double-submit.
+ void WillActivateSubmitButton(HTMLFormControlElement* element);
+ void DidActivateSubmitButton(HTMLFormControlElement* element);
+
private:
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
@@ -136,7 +142,7 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
void SubmitDialog(FormSubmission*);
void Submit(Event*, HTMLFormControlElement* submit_button);
- void ScheduleFormSubmission(FormSubmission*);
+ void SubmitForm(FormSubmission*);
void CollectListedElements(Node& root, ListedElement::List&) const;
void CollectImageElements(Node& root, HeapVector<Member<HTMLImageElement>>&);
@@ -182,6 +188,8 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
bool has_elements_associated_by_form_attribute_ : 1;
bool did_finish_parsing_children_ : 1;
bool is_in_reset_function_ : 1;
+
+ Member<HTMLFormControlElement> activated_submit_button_;
};
} // 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 fdb9ca0f7c7..a557aec181b 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
@@ -33,6 +33,7 @@
#include "third_party/blink/public/mojom/choosers/date_time_chooser.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
@@ -414,6 +415,10 @@ void HTMLInputElement::UpdateType() {
DropInnerEditorElement();
SetForceReattachLayoutTree();
+ // In this function, we should not do force to do style recalc and layout.
+ DocumentLifecycle::DisallowTransitionScope disallow_transition(
+ GetDocument().Lifecycle());
+
if (input_type_->SupportsRequired() != new_type->SupportsRequired() &&
IsRequired()) {
PseudoStateChanged(CSSSelector::kPseudoRequired);
@@ -788,7 +793,7 @@ void HTMLInputElement::ParseAttribute(
// attribute. So, delay the setChecked() call until
// finishParsingChildren() is called if parsing is in progress.
if ((!parsing_in_progress_ ||
- !GetDocument().GetFormController().HasFormStates()) &&
+ !GetDocument().GetFormController().HasControlStates()) &&
!dirty_checkedness_) {
setChecked(!value.IsNull());
dirty_checkedness_ = false;
@@ -919,7 +924,7 @@ String HTMLInputElement::AltText() const {
if (alt.IsNull())
alt = FastGetAttribute(kValueAttr);
if (alt.IsNull())
- alt = GetLocale().QueryString(WebLocalizedString::kInputElementAltText);
+ alt = GetLocale().QueryString(IDS_FORM_INPUT_ALT);
return alt;
}
@@ -1277,6 +1282,8 @@ EventDispatchHandlingState* HTMLInputElement::PreDispatchEventHandler(
ToMouseEvent(event).button() !=
static_cast<int16_t>(WebPointerProperties::Button::kLeft))
return nullptr;
+ if (formOwner() && CanBeSuccessfulSubmitButton())
+ formOwner()->WillActivateSubmitButton(this);
return input_type_view_->WillDispatchClick();
}
@@ -1289,7 +1296,19 @@ void HTMLInputElement::PostDispatchEventHandler(
*static_cast<ClickHandlingState*>(state));
}
-void HTMLInputElement::DefaultEventHandler(Event& evt) {
+void HTMLInputElement::DidPreventDefault(const Event& event) {
+ if (auto* form = formOwner())
+ form->DidActivateSubmitButton(this);
+}
+
+void HTMLInputElement::DefaultEventHandler(Event& event) {
+ DefaultEventHandlerInternal(event);
+
+ if (event.type() == event_type_names::kDOMActivate && formOwner())
+ formOwner()->DidActivateSubmitButton(this);
+}
+
+void HTMLInputElement::DefaultEventHandlerInternal(Event& evt) {
if (evt.IsMouseEvent() && evt.type() == event_type_names::kClick &&
ToMouseEvent(evt).button() ==
static_cast<int16_t>(WebPointerProperties::Button::kLeft)) {
@@ -1914,7 +1933,7 @@ bool HTMLInputElement::SetupDateTimeChooserParameters(
continue;
suggestion->localized_value = LocalizeValue(option->value());
suggestion->label =
- option->value() == option->label() ? String() : option->label();
+ option->value() == option->label() ? String("") : option->label();
parameters.suggestions.push_back(std::move(suggestion));
}
}
@@ -1941,10 +1960,6 @@ bool HTMLInputElement::IsInteractiveContent() const {
return input_type_->IsInteractiveContent();
}
-bool HTMLInputElement::SupportsAutofocus() const {
- return input_type_->IsInteractiveContent();
-}
-
scoped_refptr<ComputedStyle> HTMLInputElement::CustomStyleForLayoutObject() {
return input_type_view_->CustomStyleForLayoutObject(
OriginalStyleForLayoutObject());
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
index e6c85fbe906..0795e674ef6 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -369,10 +369,14 @@ class CORE_EXPORT HTMLInputElement
bool CanBeSuccessfulSubmitButton() const final;
void ResetImpl() final;
- bool SupportsAutofocus() const final;
EventDispatchHandlingState* PreDispatchEventHandler(Event&) final;
void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) final;
+ // TODO(crbug.com/1013385): Remove DidPreventDefault and
+ // DefaultEventHandlerInternal. They are here as a temporary fix for form
+ // double-submit.
+ void DidPreventDefault(const Event&) final;
+ void DefaultEventHandlerInternal(Event& evt);
bool IsURLAttribute(const Attribute&) const final;
bool HasLegalLinkAttribute(const QualifiedName&) const final;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
index 31b6b8e8535..fe030084f16 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
@@ -31,7 +31,6 @@ enum SelectionMode { "select", "start", "end", "preserve" };
[CEReactions, Reflect] attribute DOMString accept;
[CEReactions, Reflect] attribute DOMString alt;
[CEReactions, ImplementedAs=IDLExposedAutofillValue] attribute DOMString autocomplete;
- [CEReactions, Reflect] attribute boolean autofocus;
[CEReactions, Reflect=checked] attribute boolean defaultChecked;
attribute boolean checked;
[CEReactions, Reflect] attribute DOMString dirName;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
index 282cb3700cc..f68bfb64548 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
@@ -237,4 +237,16 @@ TEST_F(HTMLInputElementTest, RepaintAfterClearingFile) {
EXPECT_TRUE(input->GetLayoutObject()->ShouldCheckForPaintInvalidation());
}
+TEST_F(HTMLInputElementTest, UpdateTypeDcheck) {
+ Document& doc = GetDocument();
+ // Removing <body> is required to reproduce the issue.
+ doc.body()->remove();
+ Element* input = doc.CreateRawElement(html_names::kInputTag);
+ doc.documentElement()->appendChild(input);
+ input->focus();
+ input->setAttribute(html_names::kTypeAttr, AtomicString("radio"));
+ // Test succeeds if the above setAttribute() didn't trigger a DCHECK failure
+ // in Document::UpdateFocusAppearanceAfterLayout().
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
index de728937219..c7659e33b9e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_opt_group_element.cc
@@ -96,7 +96,7 @@ Node::InsertionNotificationRequest HTMLOptGroupElement::InsertedInto(
}
void HTMLOptGroupElement::RemovedFrom(ContainerNode& insertion_point) {
- if (auto* select = ToHTMLSelectElementOrNull(insertion_point)) {
+ if (auto* select = DynamicTo<HTMLSelectElement>(insertion_point)) {
if (!parentNode())
select->OptGroupInsertedOrRemoved(*this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
index a79c57ebb02..275f0f5e47d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -280,10 +280,10 @@ HTMLDataListElement* HTMLOptionElement::OwnerDataListElement() const {
HTMLSelectElement* HTMLOptionElement::OwnerSelectElement() const {
if (!parentNode())
return nullptr;
- if (auto* select = ToHTMLSelectElementOrNull(*parentNode()))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*parentNode()))
return select;
- if (IsHTMLOptGroupElement(*parentNode()))
- return ToHTMLSelectElementOrNull(parentNode()->parentNode());
+ if (IsA<HTMLOptGroupElement>(*parentNode()))
+ return DynamicTo<HTMLSelectElement>(parentNode()->parentNode());
return nullptr;
}
@@ -302,7 +302,7 @@ void HTMLOptionElement::setLabel(const AtomicString& label) {
String HTMLOptionElement::TextIndentedToRespectGroupLabel() const {
ContainerNode* parent = parentNode();
- if (parent && IsHTMLOptGroupElement(*parent))
+ if (parent && IsA<HTMLOptGroupElement>(*parent))
return " " + DisplayLabel();
return DisplayLabel();
}
@@ -315,7 +315,7 @@ bool HTMLOptionElement::IsDisabledFormControl() const {
if (OwnElementDisabled())
return true;
if (Element* parent = parentElement())
- return IsHTMLOptGroupElement(*parent) && parent->IsDisabledFormControl();
+ return IsA<HTMLOptGroupElement>(*parent) && parent->IsDisabledFormControl();
return false;
}
@@ -329,19 +329,20 @@ Node::InsertionNotificationRequest HTMLOptionElement::InsertedInto(
ContainerNode& insertion_point) {
HTMLElement::InsertedInto(insertion_point);
if (HTMLSelectElement* select = OwnerSelectElement()) {
- if (&insertion_point == select || (IsHTMLOptGroupElement(insertion_point) &&
- insertion_point.parentNode() == select))
+ if (&insertion_point == select ||
+ (IsA<HTMLOptGroupElement>(insertion_point) &&
+ insertion_point.parentNode() == select))
select->OptionInserted(*this, is_selected_);
}
return kInsertionDone;
}
void HTMLOptionElement::RemovedFrom(ContainerNode& insertion_point) {
- if (auto* select = ToHTMLSelectElementOrNull(insertion_point)) {
- if (!parentNode() || IsHTMLOptGroupElement(*parentNode()))
+ if (auto* select = DynamicTo<HTMLSelectElement>(insertion_point)) {
+ if (!parentNode() || IsA<HTMLOptGroupElement>(*parentNode()))
select->OptionRemoved(*this);
- } else if (IsHTMLOptGroupElement(insertion_point)) {
- select = ToHTMLSelectElementOrNull(insertion_point.parentNode());
+ } else if (IsA<HTMLOptGroupElement>(insertion_point)) {
+ select = DynamicTo<HTMLSelectElement>(insertion_point.parentNode());
if (select)
select->OptionRemoved(*this);
}
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 65de9989bb9..13c3d226f3d 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
@@ -31,7 +31,7 @@ namespace blink {
HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select)
: HTMLCollection(select, kSelectOptions, kDoesNotOverrideItemAfter) {
- DCHECK(IsHTMLSelectElement(select));
+ DCHECK(IsA<HTMLSelectElement>(select));
}
HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select,
@@ -74,31 +74,31 @@ void HTMLOptionsCollection::add(
const HTMLOptionElementOrHTMLOptGroupElement& element,
const HTMLElementOrLong& before,
ExceptionState& exception_state) {
- ToHTMLSelectElement(ownerNode()).add(element, before, exception_state);
+ To<HTMLSelectElement>(ownerNode()).add(element, before, exception_state);
}
void HTMLOptionsCollection::remove(int index) {
- ToHTMLSelectElement(ownerNode()).remove(index);
+ To<HTMLSelectElement>(ownerNode()).remove(index);
}
int HTMLOptionsCollection::selectedIndex() const {
- return ToHTMLSelectElement(ownerNode()).selectedIndex();
+ return To<HTMLSelectElement>(ownerNode()).selectedIndex();
}
void HTMLOptionsCollection::setSelectedIndex(int index) {
- ToHTMLSelectElement(ownerNode()).setSelectedIndex(index);
+ To<HTMLSelectElement>(ownerNode()).setSelectedIndex(index);
}
void HTMLOptionsCollection::setLength(unsigned length,
ExceptionState& exception_state) {
- ToHTMLSelectElement(ownerNode()).setLength(length, exception_state);
+ To<HTMLSelectElement>(ownerNode()).setLength(length, exception_state);
}
bool HTMLOptionsCollection::AnonymousIndexedSetter(
unsigned index,
HTMLOptionElement* value,
ExceptionState& exception_state) {
- HTMLSelectElement& base = ToHTMLSelectElement(ownerNode());
+ auto& base = To<HTMLSelectElement>(ownerNode());
if (!value) { // undefined or null
base.remove(index);
return true;
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 45fd818d433..2f371ef293b 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
@@ -41,7 +41,7 @@ class HTMLOptionsCollection final : public HTMLCollection {
HTMLOptionsCollection(ContainerNode&, CollectionType);
HTMLOptionElement* item(unsigned offset) const {
- return ToHTMLOptionElement(HTMLCollection::item(offset));
+ return To<HTMLOptionElement>(HTMLCollection::item(offset));
}
void add(const HTMLOptionElementOrHTMLOptGroupElement&,
@@ -69,14 +69,15 @@ DEFINE_TYPE_CASTS(HTMLOptionsCollection,
inline bool HTMLOptionsCollection::ElementMatches(
const HTMLElement& element) const {
- if (!IsHTMLOptionElement(element))
+ if (!IsA<HTMLOptionElement>(element))
return false;
Node* parent = element.parentNode();
if (!parent)
return false;
if (parent == &RootNode())
return true;
- return IsHTMLOptGroupElement(*parent) && parent->parentNode() == &RootNode();
+ return IsA<HTMLOptGroupElement>(*parent) &&
+ parent->parentNode() == &RootNode();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
index f13b22bed67..9cef32cec58 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -31,6 +31,7 @@
#include "build/build_config.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/core/accessibility/ax_object_cache.h"
@@ -140,9 +141,14 @@ bool HTMLSelectElement::HasPlaceholderLabelOption() const {
// TODO(tkent): This function is called in CSS selector matching. Using
// listItems() might have performance impact.
- if (GetListItems().size() == 0 || !IsHTMLOptionElement(GetListItems()[0]))
+ if (GetListItems().size() == 0)
return false;
- return ToHTMLOptionElement(GetListItems()[0].Get())->value().IsEmpty();
+
+ auto* option_element = DynamicTo<HTMLOptionElement>(GetListItems()[0].Get());
+ if (!option_element)
+ return false;
+
+ return option_element->value().IsEmpty();
}
String HTMLSelectElement::validationMessage() const {
@@ -151,8 +157,7 @@ String HTMLSelectElement::validationMessage() const {
if (CustomError())
return CustomValidationMessage();
if (ValueMissing()) {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationValueMissingForSelect);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_VALUE_MISSING_SELECT);
}
return String();
}
@@ -461,7 +466,7 @@ HTMLOptionElement* HTMLSelectElement::OptionAtListIndex(int list_index) const {
const ListItems& items = GetListItems();
if (static_cast<wtf_size_t>(list_index) >= items.size())
return nullptr;
- return ToHTMLOptionElementOrNull(items[list_index].Get());
+ return DynamicTo<HTMLOptionElement>(items[list_index].Get());
}
// Returns the 1st valid OPTION |skip| items from |listIndex| in direction
@@ -481,15 +486,16 @@ HTMLOptionElement* HTMLSelectElement::NextValidOption(int list_index,
list_index += direction) {
--skip;
HTMLElement* element = list_items[list_index];
- if (!IsHTMLOptionElement(*element))
+ auto* option_element = DynamicTo<HTMLOptionElement>(element);
+ if (!option_element)
continue;
- if (ToHTMLOptionElement(*element).IsDisplayNone())
+ if (option_element->IsDisplayNone())
continue;
if (element->IsDisabledFormControl())
continue;
if (!UsesMenuList() && !element->GetLayoutObject())
continue;
- last_good_option = ToHTMLOptionElement(element);
+ last_good_option = option_element;
if (skip <= 0)
break;
}
@@ -572,9 +578,9 @@ void HTMLSelectElement::SaveLastSelection() {
last_on_change_selection_.clear();
for (auto& element : GetListItems()) {
- last_on_change_selection_.push_back(
- IsHTMLOptionElement(*element) &&
- ToHTMLOptionElement(element.Get())->Selected());
+ auto* option_element = DynamicTo<HTMLOptionElement>(element.Get());
+ last_on_change_selection_.push_back(option_element &&
+ option_element->Selected());
}
}
@@ -664,8 +670,8 @@ void HTMLSelectElement::ListBoxOnChange() {
bool fire_on_change = false;
for (unsigned i = 0; i < items.size(); ++i) {
HTMLElement* element = items[i];
- bool selected = IsHTMLOptionElement(*element) &&
- ToHTMLOptionElement(element)->Selected();
+ auto* option_element = DynamicTo<HTMLOptionElement>(element);
+ bool selected = option_element && option_element->Selected();
if (selected != last_on_change_selection_[i])
fire_on_change = true;
last_on_change_selection_[i] = selected;
@@ -767,7 +773,7 @@ void HTMLSelectElement::RecalcListItems() const {
// We should ignore nested optgroup elements. The HTML parser flatten
// them. However we need to ignore nested optgroups built by DOM APIs.
// This behavior matches to IE and Firefox.
- if (IsHTMLOptGroupElement(*current_html_element)) {
+ if (IsA<HTMLOptGroupElement>(*current_html_element)) {
if (current_html_element->parentNode() != this) {
current_element =
ElementTraversal::NextSkippingChildren(*current_html_element, this);
@@ -781,7 +787,7 @@ void HTMLSelectElement::RecalcListItems() const {
}
}
- if (IsHTMLOptionElement(*current_html_element))
+ if (IsA<HTMLOptionElement>(*current_html_element))
list_items_.push_back(current_html_element);
if (IsA<HTMLHRElement>(*current_html_element))
@@ -869,8 +875,8 @@ void HTMLSelectElement::setSelectedIndex(int index) {
int HTMLSelectElement::SelectedListIndex() const {
int index = 0;
for (const auto& item : GetListItems()) {
- if (IsHTMLOptionElement(item) &&
- ToHTMLOptionElement(item.Get())->Selected())
+ auto* option_element = DynamicTo<HTMLOptionElement>(item.Get());
+ if (option_element && option_element->Selected())
return index;
++index;
}
@@ -1134,10 +1140,8 @@ FormControlState HTMLSelectElement::SaveFormControlState() const {
wtf_size_t length = items.size();
FormControlState state;
for (wtf_size_t i = 0; i < length; ++i) {
- if (!IsHTMLOptionElement(*items[i]))
- continue;
- HTMLOptionElement* option = ToHTMLOptionElement(items[i].Get());
- if (!option->Selected())
+ auto* option = DynamicTo<HTMLOptionElement>(items[i].Get());
+ if (!option || !option->Selected())
continue;
state.Append(option->value());
state.Append(String::Number(i));
@@ -1154,9 +1158,10 @@ wtf_size_t HTMLSelectElement::SearchOptionsForValue(
const ListItems& items = GetListItems();
wtf_size_t loop_end_index = std::min(items.size(), list_index_end);
for (wtf_size_t i = list_index_start; i < loop_end_index; ++i) {
- if (!IsHTMLOptionElement(items[i]))
+ auto* option_element = DynamicTo<HTMLOptionElement>(items[i].Get());
+ if (!option_element)
continue;
- if (ToHTMLOptionElement(items[i].Get())->value() == value)
+ if (option_element->value() == value)
return i;
}
return kNotFound;
@@ -1176,17 +1181,20 @@ void HTMLSelectElement::RestoreFormControlState(const FormControlState& state) {
DCHECK_GE(state.ValueSize(), 2u);
if (!IsMultiple()) {
unsigned index = state[1].ToUInt();
- if (index < items_size && IsHTMLOptionElement(items[index]) &&
- ToHTMLOptionElement(items[index].Get())->value() == state[0]) {
- ToHTMLOptionElement(items[index].Get())->SetSelectedState(true);
- ToHTMLOptionElement(items[index].Get())->SetDirty(true);
- last_on_change_option_ = ToHTMLOptionElement(items[index].Get());
+ auto* option_element =
+ index < items_size ? DynamicTo<HTMLOptionElement>(items[index].Get())
+ : nullptr;
+ if (option_element && option_element->value() == state[0]) {
+ option_element->SetSelectedState(true);
+ option_element->SetDirty(true);
+ last_on_change_option_ = option_element;
} else {
wtf_size_t found_index = SearchOptionsForValue(state[0], 0, items_size);
if (found_index != kNotFound) {
- ToHTMLOptionElement(items[found_index].Get())->SetSelectedState(true);
- ToHTMLOptionElement(items[found_index].Get())->SetDirty(true);
- last_on_change_option_ = ToHTMLOptionElement(items[found_index].Get());
+ auto* option_element = To<HTMLOptionElement>(items[found_index].Get());
+ option_element->SetSelectedState(true);
+ option_element->SetDirty(true);
+ last_on_change_option_ = option_element;
}
}
} else {
@@ -1194,10 +1202,12 @@ void HTMLSelectElement::RestoreFormControlState(const FormControlState& state) {
for (wtf_size_t i = 0; i < state.ValueSize(); i += 2) {
const String& value = state[i];
const unsigned index = state[i + 1].ToUInt();
- if (index < items_size && IsHTMLOptionElement(items[index]) &&
- ToHTMLOptionElement(items[index].Get())->value() == value) {
- ToHTMLOptionElement(items[index].Get())->SetSelectedState(true);
- ToHTMLOptionElement(items[index].Get())->SetDirty(true);
+ auto* option_element =
+ index < items_size ? DynamicTo<HTMLOptionElement>(items[index].Get())
+ : nullptr;
+ if (option_element && option_element->value() == value) {
+ option_element->SetSelectedState(true);
+ option_element->SetDirty(true);
start_index = index + 1;
} else {
wtf_size_t found_index =
@@ -1206,8 +1216,9 @@ void HTMLSelectElement::RestoreFormControlState(const FormControlState& state) {
found_index = SearchOptionsForValue(value, 0, start_index);
if (found_index == kNotFound)
continue;
- ToHTMLOptionElement(items[found_index].Get())->SetSelectedState(true);
- ToHTMLOptionElement(items[found_index].Get())->SetDirty(true);
+ auto* option_element = To<HTMLOptionElement>(items[found_index].Get());
+ option_element->SetSelectedState(true);
+ option_element->SetDirty(true);
start_index = found_index + 1;
}
}
@@ -1473,10 +1484,7 @@ void HTMLSelectElement::UpdateSelectedState(HTMLOptionElement* clicked_option,
}
HTMLOptionElement* HTMLSelectElement::EventTargetOption(const Event& event) {
- Node* target_node = event.target()->ToNode();
- if (!target_node || !IsHTMLOptionElement(*target_node))
- return nullptr;
- return ToHTMLOptionElement(target_node);
+ return DynamicTo<HTMLOptionElement>(event.target()->ToNode());
}
int HTMLSelectElement::ListIndexForOption(const HTMLOptionElement& option) {
@@ -1707,12 +1715,18 @@ void HTMLSelectElement::ListBoxDefaultEventHandler(Event& event) {
event.SetDefaultHandled();
} else if (is_multiple_ && key_code == ' ' &&
IsSpatialNavigationEnabled(GetDocument().GetFrame())) {
- // Use space to toggle selection change.
- active_selection_state_ = !active_selection_state_;
- UpdateSelectedState(active_selection_end_.Get(), true /*multi*/,
- false /*shift*/);
- ListBoxOnChange();
- event.SetDefaultHandled();
+ HTMLOptionElement* option = active_selection_end_;
+ // If there's no active selection,
+ // act as if "ArrowDown" had been pressed.
+ if (!option)
+ option = NextSelectableOption(LastSelectedOption());
+ if (option) {
+ // Use space to toggle selection change.
+ active_selection_state_ = !active_selection_state_;
+ UpdateSelectedState(option, true /*multi*/, false /*shift*/);
+ ListBoxOnChange();
+ event.SetDefaultHandled();
+ }
}
}
}
@@ -1851,10 +1865,6 @@ bool HTMLSelectElement::IsInteractiveContent() const {
return true;
}
-bool HTMLSelectElement::SupportsAutofocus() const {
- return true;
-}
-
void HTMLSelectElement::Trace(Visitor* visitor) {
visitor->Trace(list_items_);
visitor->Trace(last_on_change_option_);
@@ -1883,9 +1893,9 @@ HTMLOptionElement* HTMLSelectElement::SpatialNavigationFocusedOption() {
String HTMLSelectElement::ItemText(const Element& element) const {
String item_string;
- if (auto* optgroup = ToHTMLOptGroupElementOrNull(element))
+ if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(element))
item_string = optgroup->GroupLabelText();
- else if (auto* option = ToHTMLOptionElementOrNull(element))
+ else if (auto* option = DynamicTo<HTMLOptionElement>(element))
item_string = option->TextIndentedToRespectGroupLabel();
if (GetLayoutObject() && GetLayoutObject()->Style())
@@ -1894,7 +1904,7 @@ String HTMLSelectElement::ItemText(const Element& element) const {
}
bool HTMLSelectElement::ItemIsDisplayNone(Element& element) const {
- if (auto* option = ToHTMLOptionElementOrNull(element))
+ if (auto* option = DynamicTo<HTMLOptionElement>(element))
return option->IsDisplayNone();
const ComputedStyle* style = ItemComputedStyle(element);
return !style || style->Display() == EDisplay::kNone;
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 613dcfa5d2f..3d010de4760 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
@@ -194,7 +194,6 @@ class CORE_EXPORT HTMLSelectElement final
bool IsEnumeratable() const override { return true; }
bool IsInteractiveContent() const override;
- bool SupportsAutofocus() const override;
bool IsLabelable() const override { return true; }
FormControlState SaveFormControlState() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.idl
index feaf76f3fff..d5fde8e8542 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element.idl
@@ -25,7 +25,6 @@
HTMLConstructor
] interface HTMLSelectElement : HTMLElement {
[CEReactions, ImplementedAs=IDLExposedAutofillValue] attribute DOMString autocomplete;
- [CEReactions, Reflect] attribute boolean autofocus;
[CEReactions, Reflect] attribute boolean disabled;
[ImplementedAs=formOwner] readonly attribute HTMLFormElement? form;
[CEReactions, Reflect] attribute boolean multiple;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
index 1c85388124a..8da70996dff 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
@@ -34,25 +34,25 @@ TEST_F(HTMLSelectElementTest, SaveRestoreSelectSingleFormControlState) {
"<option value='111' selected id='2'>!666</option>"
"<option value='999'>999</option></select>");
Element* element = GetElementById("sel");
- HTMLFormControlElementWithState* select = ToHTMLSelectElement(element);
- HTMLOptionElement* opt0 = ToHTMLOptionElement(GetElementById("0"));
- HTMLOptionElement* opt2 = ToHTMLOptionElement(GetElementById("2"));
+ auto* opt0 = To<HTMLOptionElement>(GetElementById("0"));
+ auto* opt2 = To<HTMLOptionElement>(GetElementById("2"));
// Save the select element state, and then restore again.
// Test passes if the restored state is not changed.
- EXPECT_EQ(2, ToHTMLSelectElement(element)->selectedIndex());
+ EXPECT_EQ(2, To<HTMLSelectElement>(element)->selectedIndex());
EXPECT_FALSE(opt0->Selected());
EXPECT_TRUE(opt2->Selected());
+ HTMLFormControlElementWithState* select = To<HTMLSelectElement>(element);
FormControlState select_state = select->SaveFormControlState();
EXPECT_EQ(2U, select_state.ValueSize());
// Clear the selected state, to be restored by restoreFormControlState.
- ToHTMLSelectElement(select)->setSelectedIndex(-1);
+ To<HTMLSelectElement>(select)->setSelectedIndex(-1);
ASSERT_FALSE(opt2->Selected());
// Restore
select->RestoreFormControlState(select_state);
- EXPECT_EQ(2, ToHTMLSelectElement(element)->selectedIndex());
+ EXPECT_EQ(2, To<HTMLSelectElement>(element)->selectedIndex());
EXPECT_FALSE(opt0->Selected());
EXPECT_TRUE(opt2->Selected());
}
@@ -64,18 +64,18 @@ TEST_F(HTMLSelectElementTest, SaveRestoreSelectMultipleFormControlState) {
"<option value='222'>222</option>"
"<option value='111' selected id='2'>!666</option>"
"<option value='999' selected id='3'>999</option></select>");
- HTMLFormControlElementWithState* select =
- ToHTMLSelectElement(GetElementById("sel"));
- HTMLOptionElement* opt0 = ToHTMLOptionElement(GetElementById("0"));
- HTMLOptionElement* opt2 = ToHTMLOptionElement(GetElementById("2"));
- HTMLOptionElement* opt3 = ToHTMLOptionElement(GetElementById("3"));
+ auto* opt0 = To<HTMLOptionElement>(GetElementById("0"));
+ auto* opt2 = To<HTMLOptionElement>(GetElementById("2"));
+ auto* opt3 = To<HTMLOptionElement>(GetElementById("3"));
// Save the select element state, and then restore again.
// Test passes if the selected options are not changed.
EXPECT_FALSE(opt0->Selected());
EXPECT_TRUE(opt2->Selected());
EXPECT_TRUE(opt3->Selected());
+ HTMLFormControlElementWithState* select =
+ To<HTMLSelectElement>(GetElementById("sel"));
FormControlState select_state = select->SaveFormControlState();
EXPECT_EQ(4U, select_state.ValueSize());
@@ -105,11 +105,11 @@ TEST_F(HTMLSelectElementTest, RestoreUnmatchedFormControlState) {
</select>
)HTML");
Element* element = GetElementById("sel");
- HTMLFormControlElementWithState* select = ToHTMLSelectElement(element);
- HTMLOptionElement* opt2 = ToHTMLOptionElement(GetElementById("2"));
+ auto* opt2 = To<HTMLOptionElement>(GetElementById("2"));
- ToHTMLSelectElement(element)->setSelectedIndex(1);
+ To<HTMLSelectElement>(element)->setSelectedIndex(1);
// Save the current state.
+ HTMLFormControlElementWithState* select = To<HTMLSelectElement>(element);
FormControlState select_state = select->SaveFormControlState();
EXPECT_EQ(2U, select_state.ValueSize());
@@ -120,16 +120,15 @@ TEST_F(HTMLSelectElementTest, RestoreUnmatchedFormControlState) {
// Restore
select->RestoreFormControlState(select_state);
- EXPECT_EQ(-1, ToHTMLSelectElement(element)->selectedIndex());
- EXPECT_EQ(nullptr, ToHTMLSelectElement(element)->OptionToBeShown());
+ EXPECT_EQ(-1, To<HTMLSelectElement>(element)->selectedIndex());
+ EXPECT_EQ(nullptr, To<HTMLSelectElement>(element)->OptionToBeShown());
}
TEST_F(HTMLSelectElementTest, VisibleBoundsInVisualViewport) {
SetHtmlInnerHTML(
"<select style='position:fixed; top:12.3px; height:24px; "
"-webkit-appearance:none;'><option>o1</select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
ASSERT_NE(select, nullptr);
IntRect bounds = select->VisibleBoundsInVisualViewport();
EXPECT_EQ(24, bounds.Height());
@@ -137,8 +136,7 @@ TEST_F(HTMLSelectElementTest, VisibleBoundsInVisualViewport) {
TEST_F(HTMLSelectElementTest, PopupIsVisible) {
SetHtmlInnerHTML("<select><option>o1</option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
ASSERT_NE(select, nullptr);
EXPECT_FALSE(select->PopupIsVisible());
select->ShowPopup();
@@ -150,15 +148,13 @@ TEST_F(HTMLSelectElementTest, PopupIsVisible) {
TEST_F(HTMLSelectElementTest, FirstSelectableOption) {
{
SetHtmlInnerHTML("<select></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ(nullptr, select->FirstSelectableOption());
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->FirstSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -166,8 +162,7 @@ TEST_F(HTMLSelectElementTest, FirstSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1 disabled></option><option "
"id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->FirstSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -175,8 +170,7 @@ TEST_F(HTMLSelectElementTest, FirstSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1 style='display:none'></option><option "
"id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->FirstSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -184,8 +178,7 @@ TEST_F(HTMLSelectElementTest, FirstSelectableOption) {
SetHtmlInnerHTML(
"<select><optgroup><option id=o1></option><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->FirstSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -194,15 +187,13 @@ TEST_F(HTMLSelectElementTest, FirstSelectableOption) {
TEST_F(HTMLSelectElementTest, LastSelectableOption) {
{
SetHtmlInnerHTML("<select></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ(nullptr, select->LastSelectableOption());
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->LastSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -210,8 +201,7 @@ TEST_F(HTMLSelectElementTest, LastSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2 "
"disabled></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->LastSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -219,8 +209,7 @@ TEST_F(HTMLSelectElementTest, LastSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2 "
"style='display:none'></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->LastSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -228,8 +217,7 @@ TEST_F(HTMLSelectElementTest, LastSelectableOption) {
SetHtmlInnerHTML(
"<select><optgroup><option id=o1></option><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->LastSelectableOption()->FastGetAttribute(
html_names::kIdAttr));
}
@@ -238,15 +226,13 @@ TEST_F(HTMLSelectElementTest, LastSelectableOption) {
TEST_F(HTMLSelectElementTest, NextSelectableOption) {
{
SetHtmlInnerHTML("<select></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ(nullptr, select->NextSelectableOption(nullptr));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->NextSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -254,8 +240,7 @@ TEST_F(HTMLSelectElementTest, NextSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1 disabled></option><option "
"id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->NextSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -263,8 +248,7 @@ TEST_F(HTMLSelectElementTest, NextSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1 style='display:none'></option><option "
"id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->NextSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -272,30 +256,27 @@ TEST_F(HTMLSelectElementTest, NextSelectableOption) {
SetHtmlInnerHTML(
"<select><optgroup><option id=o1></option><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->NextSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
- HTMLOptionElement* option = ToHTMLOptionElement(GetElementById("o1"));
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ auto* option = To<HTMLOptionElement>(GetElementById("o1"));
EXPECT_EQ("o2", select->NextSelectableOption(option)->FastGetAttribute(
html_names::kIdAttr));
EXPECT_EQ(nullptr, select->NextSelectableOption(
- ToHTMLOptionElement(GetElementById("o2"))));
+ To<HTMLOptionElement>(GetElementById("o2"))));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><optgroup><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
- HTMLOptionElement* option = ToHTMLOptionElement(GetElementById("o1"));
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ auto* option = To<HTMLOptionElement>(GetElementById("o1"));
EXPECT_EQ("o2", select->NextSelectableOption(option)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -304,15 +285,13 @@ TEST_F(HTMLSelectElementTest, NextSelectableOption) {
TEST_F(HTMLSelectElementTest, PreviousSelectableOption) {
{
SetHtmlInnerHTML("<select></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ(nullptr, select->PreviousSelectableOption(nullptr));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->PreviousSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -320,8 +299,7 @@ TEST_F(HTMLSelectElementTest, PreviousSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2 "
"disabled></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->PreviousSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -329,8 +307,7 @@ TEST_F(HTMLSelectElementTest, PreviousSelectableOption) {
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2 "
"style='display:none'></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o1", select->PreviousSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -338,30 +315,27 @@ TEST_F(HTMLSelectElementTest, PreviousSelectableOption) {
SetHtmlInnerHTML(
"<select><optgroup><option id=o1></option><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
EXPECT_EQ("o2", select->PreviousSelectableOption(nullptr)->FastGetAttribute(
html_names::kIdAttr));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><option id=o2></option></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
- HTMLOptionElement* option = ToHTMLOptionElement(GetElementById("o2"));
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ auto* option = To<HTMLOptionElement>(GetElementById("o2"));
EXPECT_EQ("o1", select->PreviousSelectableOption(option)->FastGetAttribute(
html_names::kIdAttr));
EXPECT_EQ(nullptr, select->PreviousSelectableOption(
- ToHTMLOptionElement(GetElementById("o1"))));
+ To<HTMLOptionElement>(GetElementById("o1"))));
}
{
SetHtmlInnerHTML(
"<select><option id=o1></option><optgroup><option "
"id=o2></option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
- HTMLOptionElement* option = ToHTMLOptionElement(GetElementById("o2"));
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ auto* option = To<HTMLOptionElement>(GetElementById("o2"));
EXPECT_EQ("o1", select->PreviousSelectableOption(option)->FastGetAttribute(
html_names::kIdAttr));
}
@@ -370,10 +344,8 @@ TEST_F(HTMLSelectElementTest, PreviousSelectableOption) {
TEST_F(HTMLSelectElementTest, ActiveSelectionEndAfterOptionRemoval) {
SetHtmlInnerHTML(
"<select><optgroup><option selected>o1</option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
- HTMLOptionElement* option =
- ToHTMLOptionElement(select->firstChild()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
+ auto* option = To<HTMLOptionElement>(select->firstChild()->firstChild());
EXPECT_EQ(1, select->ActiveSelectionEndListIndex());
select->firstChild()->removeChild(option);
EXPECT_EQ(-1, select->ActiveSelectionEndListIndex());
@@ -385,8 +357,7 @@ TEST_F(HTMLSelectElementTest, DefaultToolTip) {
SetHtmlInnerHTML(
"<select size=4><option value="
">Placeholder</option><optgroup><option>o2</option></optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
auto* option = To<Element>(select->firstChild());
auto* optgroup = To<Element>(option->nextSibling());
@@ -429,8 +400,7 @@ TEST_F(HTMLSelectElementTest, SetRecalcListItemsByOptgroupRemoval) {
SetHtmlInnerHTML(
"<select><optgroup><option>sub1</option><option>sub2</option></"
"optgroup></select>");
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().body()->firstChild());
+ auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild());
select->SetInnerHTMLFromString("");
// PASS if setInnerHTML didn't have a check failure.
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
index 8030e872518..f3f9134d197 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -486,7 +487,7 @@ String HTMLTextAreaElement::validationMessage() const {
return CustomValidationMessage();
if (ValueMissing())
- return GetLocale().QueryString(WebLocalizedString::kValidationValueMissing);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_VALUE_MISSING);
if (TooLong()) {
return GetLocale().ValidationMessageTooLongText(value().length(),
@@ -613,10 +614,6 @@ bool HTMLTextAreaElement::IsInteractiveContent() const {
return true;
}
-bool HTMLTextAreaElement::SupportsAutofocus() const {
- return true;
-}
-
void HTMLTextAreaElement::CloneNonAttributePropertiesFrom(
const Element& source,
CloneChildrenFlag flag) {
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 8bbd305ac0f..4980524e917 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
@@ -101,7 +101,6 @@ class CORE_EXPORT HTMLTextAreaElement final : public TextControlElement {
bool IsEnumeratable() const override { return true; }
bool IsInteractiveContent() const override;
- bool SupportsAutofocus() const override;
bool IsLabelable() const override { return true; }
const AtomicString& FormControlType() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
index 4e1376f6602..591be3489a2 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.idl
@@ -25,7 +25,6 @@
HTMLConstructor
] interface HTMLTextAreaElement : HTMLElement {
[CEReactions, ImplementedAs=IDLExposedAutofillValue] attribute DOMString autocomplete;
- [CEReactions, Reflect] attribute boolean autofocus;
[CEReactions] attribute unsigned long cols;
[CEReactions, Reflect] attribute DOMString dirName;
[CEReactions, Reflect] attribute boolean disabled;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
index ec9b2091966..da8c7ae8c1d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
@@ -32,6 +32,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -75,7 +76,6 @@
namespace blink {
-using blink::WebLocalizedString;
using namespace html_names;
using InputTypeFactoryFunction = InputType* (*)(HTMLInputElement&);
@@ -377,7 +377,7 @@ bool InputType::StepMismatch(const String& value) const {
String InputType::BadInputText() const {
NOTREACHED();
- return GetLocale().QueryString(WebLocalizedString::kValidationTypeMismatch);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_TYPE_MISMATCH);
}
String InputType::RangeOverflowText(const Decimal&) const {
@@ -391,11 +391,11 @@ String InputType::RangeUnderflowText(const Decimal&) const {
}
String InputType::TypeMismatchText() const {
- return GetLocale().QueryString(WebLocalizedString::kValidationTypeMismatch);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_TYPE_MISMATCH);
}
String InputType::ValueMissingText() const {
- return GetLocale().QueryString(WebLocalizedString::kValidationValueMissing);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_VALUE_MISSING);
}
std::pair<String, String> InputType::ValidationMessage(
@@ -420,7 +420,7 @@ std::pair<String, String> InputType::ValidationMessage(
// pattern. User agents may use the contents of this attribute, if it
// is present, when informing the user that the pattern is not matched
return std::make_pair(
- GetLocale().QueryString(WebLocalizedString::kValidationPatternMismatch),
+ GetLocale().QueryString(IDS_FORM_VALIDATION_PATTERN_MISMATCH),
GetElement().FastGetAttribute(kTitleAttr).GetString());
}
@@ -464,19 +464,19 @@ std::pair<String, String> InputType::ValidationMessage(
candidate2 > step_range.Maximum()) {
return std::make_pair(
GetLocale().QueryString(
- WebLocalizedString::kValidationStepMismatchCloseToLimit,
+ IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT,
localized_candidate1),
g_empty_string);
}
String localized_candidate2 = LocalizeValue(Serialize(candidate2));
if (candidate1 < candidate2) {
return std::make_pair(
- GetLocale().QueryString(WebLocalizedString::kValidationStepMismatch,
+ GetLocale().QueryString(IDS_FORM_VALIDATION_STEP_MISMATCH,
localized_candidate1, localized_candidate2),
g_empty_string);
}
return std::make_pair(
- GetLocale().QueryString(WebLocalizedString::kValidationStepMismatch,
+ GetLocale().QueryString(IDS_FORM_VALIDATION_STEP_MISMATCH,
localized_candidate2, localized_candidate1),
g_empty_string);
}
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 e427d8efe2a..bce5e29b9cc 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
@@ -52,7 +52,7 @@ class InputTypeView;
// An InputType object represents the type-specific part of an HTMLInputElement.
// Do not expose instances of InputType and classes derived from it to classes
// other than HTMLInputElement.
-class CORE_EXPORT InputType : public GarbageCollectedFinalized<InputType> {
+class CORE_EXPORT InputType : public GarbageCollected<InputType> {
public:
static InputType* Create(HTMLInputElement&, const AtomicString&);
static const AtomicString& NormalizeTypeName(const AtomicString&);
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 3cbc9678751..9f018a553ba 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
@@ -231,7 +231,8 @@ void InternalPopupMenu::WriteDocument(SharedBuffer* data) {
owner_element.VisibleBoundsInVisualViewport(),
owner_element.GetDocument().View());
- float scale_factor = chrome_client_->WindowToViewportScalar(1.f);
+ float scale_factor = chrome_client_->WindowToViewportScalar(
+ owner_element.GetDocument().GetFrame(), 1.f);
PagePopupClient::AddString(
"<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
data->Append(ChooserResourceLoader::GetPickerCommonStyleSheet());
@@ -268,11 +269,11 @@ void InternalPopupMenu::WriteDocument(SharedBuffer* data) {
const HeapVector<Member<HTMLElement>>& items = owner_element.GetListItems();
for (; context.list_index_ < items.size(); ++context.list_index_) {
Element& child = *items[context.list_index_];
- if (!IsHTMLOptGroupElement(child.parentNode()))
+ if (!IsA<HTMLOptGroupElement>(child.parentNode()))
context.FinishGroupIfNecessary();
- if (auto* option = ToHTMLOptionElementOrNull(child))
+ if (auto* option = DynamicTo<HTMLOptionElement>(child))
AddOption(context, *option);
- else if (auto* optgroup = ToHTMLOptGroupElementOrNull(child))
+ else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(child))
AddOptGroup(context, *optgroup);
else if (auto* hr = ToHTMLHRElementOrNull(child))
AddSeparator(context, *hr);
@@ -534,11 +535,11 @@ void InternalPopupMenu::Update() {
const HeapVector<Member<HTMLElement>>& items = owner_element_->GetListItems();
for (; context.list_index_ < items.size(); ++context.list_index_) {
Element& child = *items[context.list_index_];
- if (!IsHTMLOptGroupElement(child.parentNode()))
+ if (!IsA<HTMLOptGroupElement>(child.parentNode()))
context.FinishGroupIfNecessary();
- if (auto* option = ToHTMLOptionElementOrNull(child))
+ if (auto* option = DynamicTo<HTMLOptionElement>(child))
AddOption(context, *option);
- else if (auto* optgroup = ToHTMLOptGroupElementOrNull(child))
+ else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(child))
AddOptGroup(context, *optgroup);
else if (auto* hr = ToHTMLHRElementOrNull(child))
AddSeparator(context, *hr);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
index c9f4f8c93ef..72c34bf2c8f 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu_test.cc
@@ -33,8 +33,7 @@ TEST(InternalPopupMenuTest, WriteDocumentInStyleDirtyTree) {
)HTML");
document.View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
- HTMLSelectElement* select =
- ToHTMLSelectElement(document.getElementById("select"));
+ auto* select = To<HTMLSelectElement>(document.getElementById("select"));
ASSERT_TRUE(select);
auto* menu = MakeGarbageCollected<InternalPopupMenu>(
MakeGarbageCollected<EmptyChromeClient>(), *select);
@@ -62,8 +61,7 @@ TEST(InternalPopupMenuTest, ShowSelectDisplayNone) {
document.View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
auto* div = document.getElementById("container");
- HTMLSelectElement* select =
- ToHTMLSelectElement(document.getElementById("select"));
+ auto* select = To<HTMLSelectElement>(document.getElementById("select"));
ASSERT_TRUE(select);
auto* menu = MakeGarbageCollected<InternalPopupMenu>(
MakeGarbageCollected<EmptyChromeClient>(), *select);
diff --git a/chromium/third_party/blink/renderer/core/html/forms/mock_file_chooser.h b/chromium/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
index 2058d12e4be..7aa77910cba 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/mock_file_chooser.h
@@ -5,35 +5,39 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MOCK_FILE_CHOOSER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MOCK_FILE_CHOOSER_H_
-#include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/choosers/file_chooser.mojom-blink.h"
+#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 "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/choosers/file_chooser.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
class MockFileChooser : public mojom::blink::FileChooser {
using FileChooser = mojom::blink::FileChooser;
- using FileChooserFileInfoPtr = mojom::blink::FileChooserFileInfoPtr;
using FileChooserParamsPtr = mojom::blink::FileChooserParamsPtr;
- using FileChooserRequest = mojom::blink::FileChooserRequest;
public:
// |reached_callback| is called when OpenFileChooser() or
// |EnumerateChosenDirectory() is called.
- MockFileChooser(service_manager::InterfaceProvider* provider,
+ MockFileChooser(blink::BrowserInterfaceBrokerProxy& broker,
base::OnceClosure reached_callback)
- : provider_(provider), reached_callback_(std::move(reached_callback)) {
- service_manager::InterfaceProvider::TestApi test_api(provider);
- test_api.SetBinderForName(
+ : broker_(broker), reached_callback_(std::move(reached_callback)) {
+ broker.SetBinderForTesting(
FileChooser::Name_,
- WTF::BindRepeating(&MockFileChooser::OnFileChooserRequest,
+ WTF::BindRepeating(&MockFileChooser::BindFileChooserReceiver,
WTF::Unretained(this)));
}
~MockFileChooser() override {
- service_manager::InterfaceProvider::TestApi test_api(provider_);
- test_api.ClearBinderForName(FileChooser::Name_);
+ broker_.SetBinderForTesting(FileChooser::Name_, {});
+ }
+
+ void SetQuitClosure(base::OnceClosure reached_callback) {
+ reached_callback_ = std::move(reached_callback);
}
void ResponseOnOpenFileChooser(FileChooserFileInfoList files) {
@@ -42,12 +46,12 @@ class MockFileChooser : public mojom::blink::FileChooser {
"be called beforehand.";
std::move(callback_).Run(mojom::blink::FileChooserResult::New(
std::move(files), base::FilePath()));
- bindings_.FlushForTesting();
+ receivers_.FlushForTesting();
}
private:
- void OnFileChooserRequest(mojo::ScopedMessagePipeHandle handle) {
- bindings_.AddBinding(this, FileChooserRequest(std::move(handle)));
+ void BindFileChooserReceiver(mojo::ScopedMessagePipeHandle handle) {
+ receivers_.Add(this, mojo::PendingReceiver<FileChooser>(std::move(handle)));
}
void OpenFileChooser(FileChooserParamsPtr params,
@@ -67,8 +71,8 @@ class MockFileChooser : public mojom::blink::FileChooser {
std::move(reached_callback_).Run();
}
- service_manager::InterfaceProvider* provider_;
- mojo::BindingSet<FileChooser> bindings_;
+ blink::BrowserInterfaceBrokerProxy& broker_;
+ mojo::ReceiverSet<FileChooser> receivers_;
OpenFileChooserCallback callback_;
FileChooserParamsPtr params_;
base::OnceClosure reached_callback_;
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 1464bb60828..2cda4c465e7 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
@@ -38,6 +38,8 @@
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/html/forms/base_temporal_input_type.h"
+#include "third_party/blink/renderer/core/html/forms/date_time_chooser.h"
+#include "third_party/blink/renderer/core/html/forms/date_time_field_element.h"
#include "third_party/blink/renderer/core/html/forms/date_time_fields_state.h"
#include "third_party/blink/renderer/core/html/forms/form_controller.h"
#include "third_party/blink/renderer/core/html/forms/html_data_list_element.h"
@@ -310,6 +312,14 @@ Element& MultipleFieldsTemporalInputTypeView::PickerOwnerElement() const {
bool MultipleFieldsTemporalInputTypeView::SetupDateTimeChooserParameters(
DateTimeChooserParameters& parameters) {
+ // TODO(iopopesc): Get the field information by parsing the datetime format.
+ if (DateTimeEditElement* edit = GetDateTimeEditElement()) {
+ parameters.is_ampm_first = edit->IsFirstFieldAMPM();
+ parameters.has_ampm = edit->HasField(DateTimeField::kAMPM);
+ parameters.has_second = edit->HasField(DateTimeField::kSecond);
+ parameters.has_millisecond = edit->HasField(DateTimeField::kMillisecond);
+ }
+
return GetElement().SetupDateTimeChooserParameters(parameters);
}
@@ -333,6 +343,7 @@ void MultipleFieldsTemporalInputTypeView::Trace(Visitor* visitor) {
void MultipleFieldsTemporalInputTypeView::Blur() {
if (DateTimeEditElement* edit = GetDateTimeEditElement())
edit->BlurByOwner();
+ ClosePopupView();
}
scoped_refptr<ComputedStyle>
@@ -465,7 +476,9 @@ void MultipleFieldsTemporalInputTypeView::HandleKeydownEvent(
if (picker_indicator_is_visible_ &&
((event.key() == "ArrowDown" && event.getModifierState("Alt")) ||
(LayoutTheme::GetTheme().ShouldOpenPickerWithF4Key() &&
- event.key() == "F4"))) {
+ event.key() == "F4") ||
+ (RuntimeEnabledFeatures::FormControlsRefreshEnabled() &&
+ (event.key() == "Enter" || 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 e0392ea8477..7ec1c405cce 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
@@ -44,7 +44,7 @@ class BaseTemporalInputType;
struct DateTimeChooserParameters;
class MultipleFieldsTemporalInputTypeView final
- : public GarbageCollectedFinalized<MultipleFieldsTemporalInputTypeView>,
+ : public GarbageCollected<MultipleFieldsTemporalInputTypeView>,
public InputTypeView,
protected DateTimeEditElement::EditControlOwner,
protected PickerIndicatorElement::PickerIndicatorOwner,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
index e6f3a8d8a37..2cd37594f2a 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/html/forms/number_input_type.h"
#include <limits>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/events/before_text_inserted_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
@@ -48,7 +49,6 @@
namespace blink {
-using blink::WebLocalizedString;
using namespace html_names;
static const int kNumberDefaultStep = 1;
@@ -261,17 +261,16 @@ bool NumberInputType::HasBadInput() const {
}
String NumberInputType::BadInputText() const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationBadInputForNumber);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_BAD_INPUT_NUMBER);
}
String NumberInputType::RangeOverflowText(const Decimal& maximum) const {
- return GetLocale().QueryString(WebLocalizedString::kValidationRangeOverflow,
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_RANGE_OVERFLOW,
LocalizeValue(Serialize(maximum)));
}
String NumberInputType::RangeUnderflowText(const Decimal& minimum) const {
- return GetLocale().QueryString(WebLocalizedString::kValidationRangeUnderflow,
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_RANGE_UNDERFLOW,
LocalizeValue(Serialize(minimum)));
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/option_list.cc b/chromium/third_party/blink/renderer/core/html/forms/option_list.cc
index b6c0994e69c..1b990eebaed 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/option_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/option_list.cc
@@ -23,11 +23,11 @@ void OptionListIterator::Advance(HTMLOptionElement* previous) {
current = ElementTraversal::FirstChild(*select_);
}
while (current) {
- if (auto* option = ToHTMLOptionElementOrNull(current)) {
+ if (auto* option = DynamicTo<HTMLOptionElement>(current)) {
current_ = option;
return;
}
- if (IsHTMLOptGroupElement(current) &&
+ if (IsA<HTMLOptGroupElement>(current) &&
current->parentNode() == select_.Get()) {
if ((current_ = Traversal<HTMLOptionElement>::FirstChild(*current)))
return;
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
index 9b76583da29..0f8b2d17211 100644
--- 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
@@ -10,8 +10,8 @@
#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 "services/service_manager/public/cpp/interface_provider.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_frame_view.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -22,9 +22,7 @@ namespace blink {
class MockInsecureInputService : public mojom::blink::InsecureInputService {
public:
explicit MockInsecureInputService(LocalFrame& frame) {
- service_manager::InterfaceProvider::TestApi test_api(
- &frame.GetInterfaceProvider());
- test_api.SetBinderForName(
+ frame.GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::InsecureInputService::Name_,
WTF::BindRepeating(&MockInsecureInputService::BindReceiver,
WTF::Unretained(this)));
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 661eb8cb399..73f882c0776 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
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/picker_indicator_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#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/frame/settings.h"
@@ -167,9 +168,9 @@ void PickerIndicatorElement::DidNotifySubtreeInsertionsToDocument() {
setAttribute(kTabindexAttr, "0");
setAttribute(kAriaHaspopupAttr, "menu");
setAttribute(kRoleAttr, "button");
- setAttribute(kAriaLabelAttr,
- AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXCalendarShowDatePicker)));
+ setAttribute(
+ kAriaLabelAttr,
+ AtomicString(GetLocale().QueryString(IDS_AX_CALENDAR_SHOW_DATE_PICKER)));
}
void PickerIndicatorElement::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/popup_menu.h b/chromium/third_party/blink/renderer/core/html/forms/popup_menu.h
index 8a14dcb89f2..af7e1aa3b63 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/popup_menu.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/popup_menu.h
@@ -26,7 +26,7 @@
namespace blink {
-class PopupMenu : public GarbageCollectedFinalized<PopupMenu> {
+class PopupMenu : public GarbageCollected<PopupMenu> {
public:
virtual ~PopupMenu() = default;
virtual void Trace(Visitor* visitor) {}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc
index f4f691d42c3..01f83e49ed1 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/radio_input_type.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/html/forms/radio_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
@@ -60,8 +61,7 @@ bool RadioInputType::ValueMissing(const String&) const {
}
String RadioInputType::ValueMissingText() const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationValueMissingForRadio);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_VALUE_MISSING_RADIO);
}
void RadioInputType::HandleClickEvent(MouseEvent& event) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
index cae012a35bd..05c46a7be3c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc
@@ -415,4 +415,8 @@ Decimal RangeInputType::FindClosestTickMarkValue(const Decimal& value) {
return closest_left;
}
+void RangeInputType::ValueAttributeChanged() {
+ UpdateView();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.h
index 1ff75669ad2..b4da9bce5a0 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/range_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/range_input_type.h
@@ -85,6 +85,7 @@ class RangeInputType final : public InputType, public InputTypeView {
// InputTypeView function:
void UpdateView() override;
+ void ValueAttributeChanged() override;
bool tick_mark_values_dirty_;
Vector<Decimal> tick_mark_values_;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/reset_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/reset_input_type.cc
index 73c5cf0ca05..87aa6348fc1 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/reset_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/reset_input_type.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html/forms/reset_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.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/forms/html_form_element.h"
@@ -60,7 +61,7 @@ void ResetInputType::HandleDOMActivateEvent(Event& event) {
}
String ResetInputType::DefaultLabel() const {
- return GetLocale().QueryString(WebLocalizedString::kResetButtonDefaultLabel);
+ return GetLocale().QueryString(IDS_FORM_RESET_LABEL);
}
bool ResetInputType::IsTextButton() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/.clang-format b/chromium/third_party/blink/renderer/core/html/forms/resources/.clang-format
index ea647be8464..ce154cc8301 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/.clang-format
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/.clang-format
@@ -1,7 +1,6 @@
---
BasedOnStyle: Chromium
Language: JavaScript
-ColumnLimit: 120
CommentPragmas: .*\@.*
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
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
new file mode 100644
index 00000000000..f28465828fa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/PRESUBMIT.py
@@ -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.
+
+def _CheckChangeOnUploadOrCommit(input_api, output_api):
+ return input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
+ check_js=True)
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _CheckChangeOnUploadOrCommit(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _CheckChangeOnUploadOrCommit(input_api, output_api)
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 f05e3a962e7..18ad0d5b3b0 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
@@ -105,6 +105,7 @@ body {
.week-number-cell.disabled,
.day-cell.disabled {
background-color: #f5f5f5;
+ pointer-events: none;
}
.day-cell.current-month {
@@ -260,6 +261,7 @@ body {
.month-button[aria-disabled="true"] {
color: GrayText;
+ pointer-events: none;
}
.scrubby-scroll-bar {
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 8c3d925f1f4..33cd644270f 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
@@ -33,7 +33,15 @@
/**
* @enum {number}
*/
-var WeekDay = {Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6};
+var WeekDay = {
+ Sunday: 0,
+ Monday: 1,
+ Tuesday: 2,
+ Wednesday: 3,
+ Thursday: 4,
+ Friday: 5,
+ Saturday: 6
+};
/**
* @type {Object}
@@ -44,10 +52,18 @@ var global = {
locale: 'en-US',
weekStartDay: WeekDay.Sunday,
dayLabels: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
- shortMonthLabels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
+ ampmLabels: ['AM', 'PM'],
+ shortMonthLabels: [
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct',
+ 'Nov', 'Dec'
+ ],
isLocaleRTL: false,
isFormControlsRefreshEnabled: false,
mode: 'date',
+ isAMPMFirst: false,
+ hasAMPM: false,
+ hasSecond: false,
+ hasMillisecond: false,
weekLabel: 'Week',
anchorRectInScreen: new Rectangle(0, 0, 0, 0),
currentValue: null
@@ -105,14 +121,15 @@ function formatJapaneseImperialEra(year, month) {
if (year <= 1867 || year == 1868 && month <= 9)
return '';
if (!japaneseEraFormatter) {
- japaneseEraFormatter = new Intl.DateTimeFormat('ja-JP-u-ca-japanese',
- {era: 'long'});
+ japaneseEraFormatter =
+ new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {era: 'long'});
}
// Produce the era for day 16 because it's almost the midpoint of a month.
// 275760-09-13 is the last valid date in ECMAScript. We apply day 7 in that
// case because it's the midpoint between 09-01 and 09-13.
let sampleDay = year == 275760 && month == 8 ? 7 : 16;
- let sampleDayString = japaneseEraFormatter.format(new Date(year, month, sampleDay));
+ let sampleDayString =
+ japaneseEraFormatter.format(new Date(year, month, sampleDay));
let nenIndex = sampleDayString.indexOf('\u5e74');
if (nenIndex == -1)
return '';
@@ -267,7 +284,8 @@ Day.createFromToday = function() {
* @return {!boolean}
*/
Day.prototype.equals = function(other) {
- return other instanceof Day && this.year === other.year && this.month === other.month && this.date === other.date;
+ return other instanceof Day && this.year === other.year &&
+ this.month === other.month && this.date === other.date;
};
/**
@@ -346,7 +364,8 @@ Day.prototype.toString = function() {
var yearString = String(this.year);
if (yearString.length < 4)
yearString = ('000' + yearString).substr(-4, 4);
- return yearString + '-' + ('0' + (this.month + 1)).substr(-2, 2) + '-' + ('0' + this.date).substr(-2, 2);
+ return yearString + '-' + ('0' + (this.month + 1)).substr(-2, 2) + '-' +
+ ('0' + this.date).substr(-2, 2);
};
/**
@@ -354,8 +373,13 @@ Day.prototype.toString = function() {
*/
Day.prototype.format = function() {
if (!Day.formatter) {
- Day.formatter = new Intl.DateTimeFormat(
- getLocale(), {weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC'});
+ Day.formatter = new Intl.DateTimeFormat(getLocale(), {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ timeZone: 'UTC'
+ });
}
return Day.formatter.format(this.startDate());
};
@@ -386,7 +410,8 @@ function Week(year, week) {
*/
this.week = week;
// Number of years per year is either 52 or 53.
- if (this.week < 1 || (this.week > 52 && this.week > Week.numberOfWeeksInYear(this.year))) {
+ if (this.week < 1 ||
+ (this.week > 52 && this.week > Week.numberOfWeeksInYear(this.year))) {
var normalizedWeek = Week.createFromDay(this.firstDay());
this.year = normalizedWeek.year;
this.week = normalizedWeek.week;
@@ -434,11 +459,14 @@ Week.createFromDate = function(date) {
if (isNaN(date.valueOf()))
throw 'Invalid date';
var year = date.getUTCFullYear();
- if (year <= Week.Maximum.year && Week.weekOneStartDateForYear(year + 1).getTime() <= date.getTime())
+ if (year <= Week.Maximum.year &&
+ Week.weekOneStartDateForYear(year + 1).getTime() <= date.getTime())
year++;
- else if (year > 1 && Week.weekOneStartDateForYear(year).getTime() > date.getTime())
+ else if (
+ year > 1 && Week.weekOneStartDateForYear(year).getTime() > date.getTime())
year--;
- var week = 1 + Week._numberOfWeeksSinceDate(Week.weekOneStartDateForYear(year), date);
+ var week = 1 +
+ Week._numberOfWeeksSinceDate(Week.weekOneStartDateForYear(year), date);
return new Week(year, week);
};
@@ -452,7 +480,10 @@ Week.createFromDay = function(day) {
year++;
else if (year > 1 && Week.weekOneStartDayForYear(year) > day)
year--;
- var week = Math.floor(1 + (day.valueOf() - Week.weekOneStartDayForYear(year).valueOf()) / MillisecondsPerWeek);
+ var week = Math.floor(
+ 1 +
+ (day.valueOf() - Week.weekOneStartDayForYear(year).valueOf()) /
+ MillisecondsPerWeek);
return new Week(year, week);
};
@@ -461,7 +492,8 @@ Week.createFromDay = function(day) {
*/
Week.createFromToday = function() {
var now = new Date();
- return Week.createFromDate(createUTCDate(now.getFullYear(), now.getMonth(), now.getDate()));
+ return Week.createFromDate(
+ createUTCDate(now.getFullYear(), now.getMonth(), now.getDate()));
};
/**
@@ -497,7 +529,9 @@ Week.numberOfWeeksInYear = function(year) {
return 0;
else if (year === Week.Maximum.year)
return Week.Maximum.week;
- return Week._numberOfWeeksSinceDate(Week.weekOneStartDateForYear(year), Week.weekOneStartDateForYear(year + 1));
+ return Week._numberOfWeeksSinceDate(
+ Week.weekOneStartDateForYear(year),
+ Week.weekOneStartDateForYear(year + 1));
};
/**
@@ -506,7 +540,8 @@ Week.numberOfWeeksInYear = function(year) {
* @return {!number}
*/
Week._numberOfWeeksSinceDate = function(baseDate, date) {
- return Math.floor((date.getTime() - baseDate.getTime()) / MillisecondsPerWeek);
+ return Math.floor(
+ (date.getTime() - baseDate.getTime()) / MillisecondsPerWeek);
};
/**
@@ -514,7 +549,8 @@ Week._numberOfWeeksSinceDate = function(baseDate, date) {
* @return {!boolean}
*/
Week.prototype.equals = function(other) {
- return other instanceof Week && this.year === other.year && this.week === other.week;
+ return other instanceof Week && this.year === other.year &&
+ this.week === other.week;
};
/**
@@ -612,7 +648,9 @@ function Month(year, month) {
* @type {number}
* @const
*/
- this.month = month % MonthsPerYear < 0 ? month % MonthsPerYear + MonthsPerYear : month % MonthsPerYear;
+ this.month = month % MonthsPerYear < 0 ?
+ month % MonthsPerYear + MonthsPerYear :
+ month % MonthsPerYear;
};
Month.ISOStringRegExp = /^(\d+)-(\d+)$/;
@@ -684,7 +722,8 @@ Month.prototype.containsDay = function(day) {
* @return {!boolean}
*/
Month.prototype.equals = function(other) {
- return other instanceof Month && this.year === other.year && this.month === other.month;
+ return other instanceof Month && this.year === other.year &&
+ this.month === other.month;
};
/**
@@ -768,8 +807,9 @@ Month.prototype.toString = function() {
*/
Month.prototype.toLocaleString = function() {
if (global.params.locale === 'ja')
- return '' + this.year + '\u5e74' + formatJapaneseImperialEra(this.year, this.month) + ' ' + (this.month + 1) +
- '\u6708';
+ return '' + this.year + '\u5e74' +
+ formatJapaneseImperialEra(this.year, this.month) + ' ' +
+ (this.month + 1) + '\u6708';
return window.pagePopupController.formatMonth(this.year, this.month);
};
@@ -828,11 +868,22 @@ 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);
+ }
+ }
+
global.picker = new CalendarPicker(global.params.mode, global.params);
global.picker.attachTo($('main'));
};
@@ -920,7 +971,8 @@ AnimationManager.prototype._animationFrameCallback = function(now) {
* @return {!boolean}
*/
AnimationManager.prototype._needsTimer = function() {
- return this._runningAnimatorCount > 0 || this.hasListener(AnimationManager.EventTypeAnimationFrameWillFinish);
+ return this._runningAnimatorCount > 0 ||
+ this.hasListener(AnimationManager.EventTypeAnimationFrameWillFinish);
};
/**
@@ -1081,7 +1133,8 @@ TransitionAnimator.prototype.onAnimationFrame = function(now) {
this.progress += (now - this._lastStepTime) / this.duration;
this.progress = Math.min(1.0, this.progress);
this._lastStepTime = now;
- this.currentValue = this.timingFunction(this.progress) * this._delta + this._from;
+ this.currentValue =
+ this.timingFunction(this.progress) * this._delta + this._from;
this.step(this);
if (this.progress === 1.0) {
this.stop();
@@ -1143,15 +1196,16 @@ FlingGestureAnimator._P2 = 0.0037;
* @param {!number} t
*/
FlingGestureAnimator.prototype._valueAtTime = function(t) {
- return FlingGestureAnimator._P0 * Math.exp(-FlingGestureAnimator._P2 * t) - FlingGestureAnimator._P1 * t -
- FlingGestureAnimator._P0;
+ return FlingGestureAnimator._P0 * Math.exp(-FlingGestureAnimator._P2 * t) -
+ FlingGestureAnimator._P1 * t - FlingGestureAnimator._P0;
};
/**
* @param {!number} t
*/
FlingGestureAnimator.prototype._velocityAtTime = function(t) {
- return -FlingGestureAnimator._P0 * FlingGestureAnimator._P2 * Math.exp(-FlingGestureAnimator._P2 * t) -
+ return -FlingGestureAnimator._P0 * FlingGestureAnimator._P2 *
+ Math.exp(-FlingGestureAnimator._P2 * t) -
FlingGestureAnimator._P1;
};
@@ -1159,7 +1213,9 @@ FlingGestureAnimator.prototype._velocityAtTime = function(t) {
* @param {!number} v
*/
FlingGestureAnimator.prototype._timeAtVelocity = function(v) {
- return -Math.log((v + FlingGestureAnimator._P1) / (-FlingGestureAnimator._P0 * FlingGestureAnimator._P2)) /
+ return -Math.log(
+ (v + FlingGestureAnimator._P1) /
+ (-FlingGestureAnimator._P0 * FlingGestureAnimator._P2)) /
FlingGestureAnimator._P2;
};
@@ -1178,7 +1234,8 @@ FlingGestureAnimator.prototype.onAnimationFrame = function(now) {
this.stop();
return;
}
- var position = this._valueAtTime(this._elapsedTime + this._timeOffset) - this._positionOffset;
+ var position = this._valueAtTime(this._elapsedTime + this._timeOffset) -
+ this._positionOffset;
if (this.initialVelocity < 0)
position = -position;
this.currentValue = position + this.initialValue;
@@ -1259,7 +1316,8 @@ function ScrollView() {
* @type {Element}
* @const
*/
- this.contentElement = createElement('div', ScrollView.ClassNameScrollViewContent);
+ this.contentElement =
+ createElement('div', ScrollView.ClassNameScrollViewContent);
this.element.appendChild(this.contentElement);
/**
* @type {number}
@@ -1358,7 +1416,8 @@ ScrollView.prototype.onWindowTouchMove = function(event) {
*/
ScrollView.prototype.onWindowTouchEnd = function(event) {
if (Math.abs(this._lastTouchVelocity) > 0.01) {
- this._scrollAnimator = new FlingGestureAnimator(this._lastTouchVelocity, this._contentOffset);
+ this._scrollAnimator =
+ new FlingGestureAnimator(this._lastTouchVelocity, this._contentOffset);
this._scrollAnimator.step = this.onFlingGestureAnimatorStep;
this._scrollAnimator.start();
}
@@ -1475,7 +1534,9 @@ ScrollView.prototype.onMouseWheel = function(event) {
*/
ScrollView.prototype.setContentOffset = function(value) {
console.assert(isFinite(value));
- value = Math.min(this.maximumContentOffset - this._height, Math.max(this.minimumContentOffset, Math.floor(value)));
+ value = Math.min(
+ this.maximumContentOffset - this._height,
+ Math.max(this.minimumContentOffset, Math.floor(value)));
if (this._contentOffset === value)
return;
this._contentOffset = value;
@@ -1485,11 +1546,12 @@ ScrollView.prototype.setContentOffset = function(value) {
};
ScrollView.prototype._updateScrollContent = function() {
- var newPartitionNumber = Math.floor(this._contentOffset / ScrollView.PartitionHeight);
+ var newPartitionNumber =
+ Math.floor(this._contentOffset / ScrollView.PartitionHeight);
var partitionChanged = this._partitionNumber !== newPartitionNumber;
this._partitionNumber = newPartitionNumber;
- this.contentElement.style.webkitTransform =
- 'translate(0, ' + (-this.contentPositionForContentOffset(this._contentOffset)) + 'px)';
+ this.contentElement.style.webkitTransform = 'translate(0, ' +
+ (-this.contentPositionForContentOffset(this._contentOffset)) + 'px)';
if (this.delegate && partitionChanged)
this.delegate.scrollViewDidChangePartition(this);
};
@@ -1542,14 +1604,17 @@ ListCell.ClassNameHidden = 'hidden';
* @return {!Array} An array to keep thrown away cells.
*/
ListCell.prototype._recycleBin = function() {
- console.assert(false, 'NOT REACHED: ListCell.prototype._recycleBin needs to be overridden.');
+ console.assert(
+ false,
+ 'NOT REACHED: ListCell.prototype._recycleBin needs to be overridden.');
return [];
};
ListCell.prototype.throwAway = function() {
this.hide();
- var limit = typeof this.constructor.RecycleBinLimit === 'undefined' ? ListCell.DefaultRecycleBinLimit :
- this.constructor.RecycleBinLimit;
+ var limit = typeof this.constructor.RecycleBinLimit === 'undefined' ?
+ ListCell.DefaultRecycleBinLimit :
+ this.constructor.RecycleBinLimit;
var recycleBin = this._recycleBin();
if (recycleBin.length < limit)
recycleBin.push(this);
@@ -1672,10 +1737,13 @@ ListView.prototype.setNeedsUpdateCells = function(needsUpdateCells) {
return;
this._needsUpdateCells = needsUpdateCells;
if (this._needsUpdateCells)
- AnimationManager.shared.on(AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
+ AnimationManager.shared.on(
+ AnimationManager.EventTypeAnimationFrameWillFinish,
+ this.onAnimationFrameWillFinish);
else
AnimationManager.shared.removeListener(
- AnimationManager.EventTypeAnimationFrameWillFinish, this.onAnimationFrameWillFinish);
+ AnimationManager.EventTypeAnimationFrameWillFinish,
+ this.onAnimationFrameWillFinish);
};
/**
@@ -1691,7 +1759,9 @@ ListView.prototype.cellAtRow = function(row) {
* @return {!number}
*/
ListView.prototype.rowAtScrollOffset = function(offset) {
- console.assert(false, 'NOT REACHED: ListView.prototype.rowAtScrollOffset needs to be overridden.');
+ console.assert(
+ false,
+ 'NOT REACHED: ListView.prototype.rowAtScrollOffset needs to be overridden.');
return 0;
};
@@ -1700,7 +1770,9 @@ ListView.prototype.rowAtScrollOffset = function(offset) {
* @return {!number} Scroll offset in pixels.
*/
ListView.prototype.scrollOffsetForRow = function(row) {
- console.assert(false, 'NOT REACHED: ListView.prototype.scrollOffsetForRow needs to be overridden.');
+ console.assert(
+ false,
+ 'NOT REACHED: ListView.prototype.scrollOffsetForRow needs to be overridden.');
return 0;
};
@@ -1715,7 +1787,8 @@ ListView.prototype.addCellIfNecessary = function(row) {
cell = this.prepareNewCell(row);
cell.attachTo(this.scrollView.contentElement);
cell.setWidth(this._width);
- cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(row)));
+ cell.setPosition(this.scrollView.contentPositionForContentOffset(
+ this.scrollOffsetForRow(row)));
this._cells[row] = cell;
return cell;
};
@@ -1725,7 +1798,9 @@ ListView.prototype.addCellIfNecessary = function(row) {
* @return {!ListCell}
*/
ListView.prototype.prepareNewCell = function(row) {
- console.assert(false, 'NOT REACHED: ListView.prototype.prepareNewCell should be overridden.');
+ console.assert(
+ false,
+ 'NOT REACHED: ListView.prototype.prepareNewCell should be overridden.');
return new ListCell();
};
@@ -1748,7 +1823,8 @@ ListView.prototype.firstVisibleRow = function() {
* @return {!number}
*/
ListView.prototype.lastVisibleRow = function() {
- return this.rowAtScrollOffset(this.scrollView.contentOffset() + this.scrollView.height() - 1);
+ return this.rowAtScrollOffset(
+ this.scrollView.contentOffset() + this.scrollView.height() - 1);
};
/**
@@ -1784,7 +1860,8 @@ ListView.prototype.updateCells = function() {
for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
var cell = this._cells[i];
if (cell)
- cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
+ cell.setPosition(this.scrollView.contentPositionForContentOffset(
+ this.scrollOffsetForRow(cell.row)));
else
this.addCellIfNecessary(i);
}
@@ -1831,7 +1908,8 @@ ListView.prototype.setHeight = function(height) {
* @param {?Event} event
*/
ListView.prototype.onClick = function(event) {
- var clickedCellElement = enclosingNodeOrSelfWithClass(event.target, ListCell.ClassNameListCell);
+ var clickedCellElement =
+ enclosingNodeOrSelfWithClass(event.target, ListCell.ClassNameListCell);
if (!clickedCellElement)
return;
var clickedCell = clickedCellElement.$view;
@@ -1877,13 +1955,15 @@ ListView.prototype.scrollToRow = function(row, animate) {
* @param {!ScrollView} scrollView
*/
function ScrubbyScrollBar(scrollView) {
- View.call(this, createElement('div', ScrubbyScrollBar.ClassNameScrubbyScrollBar));
+ View.call(
+ this, createElement('div', ScrubbyScrollBar.ClassNameScrubbyScrollBar));
/**
* @type {!Element}
* @const
*/
- this.thumb = createElement('div', ScrubbyScrollBar.ClassNameScrubbyScrollThumb);
+ this.thumb =
+ createElement('div', ScrubbyScrollBar.ClassNameScrubbyScrollThumb);
this.element.appendChild(this.thumb);
/**
@@ -1943,7 +2023,8 @@ ScrubbyScrollBar.prototype.onTouchStart = function(event) {
this._setThumbPositionFromEventPosition(touch.clientY);
if (this._thumbStyleTopAnimator)
this._thumbStyleTopAnimator.stop();
- this._timer = setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
+ this._timer =
+ setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
window.addEventListener('touchmove', this.onWindowTouchMove, false);
window.addEventListener('touchend', this.onWindowTouchEnd, false);
event.stopPropagation();
@@ -1968,7 +2049,8 @@ ScrubbyScrollBar.prototype.onWindowTouchEnd = function(event) {
this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep;
this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop);
this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2);
- this._thumbStyleTopAnimator.timingFunction = AnimationTimingFunction.EaseInOut;
+ this._thumbStyleTopAnimator.timingFunction =
+ AnimationTimingFunction.EaseInOut;
this._thumbStyleTopAnimator.duration = 100;
this._thumbStyleTopAnimator.start();
@@ -2011,15 +2093,19 @@ ScrubbyScrollBar.prototype.setThumbHeight = function(height) {
/**
* @param {number} position
*/
-ScrubbyScrollBar.prototype._setThumbPositionFromEventPosition = function(position) {
+ScrubbyScrollBar.prototype._setThumbPositionFromEventPosition = function(
+ position) {
var thumbMin = ScrubbyScrollBar.ThumbMargin;
- var thumbMax = this._height - this._thumbHeight - ScrubbyScrollBar.ThumbMargin * 2;
- var y = position - this.element.getBoundingClientRect().top - this.element.clientTop + this.element.scrollTop;
+ var thumbMax =
+ this._height - this._thumbHeight - ScrubbyScrollBar.ThumbMargin * 2;
+ var y = position - this.element.getBoundingClientRect().top -
+ this.element.clientTop + this.element.scrollTop;
var thumbPosition = y - this._thumbHeight / 2;
thumbPosition = Math.max(thumbPosition, thumbMin);
thumbPosition = Math.min(thumbPosition, thumbMax);
this.thumb.style.top = thumbPosition + 'px';
- this._thumbPosition = 1.0 - (thumbPosition - thumbMin) / (thumbMax - thumbMin) * 2;
+ this._thumbPosition =
+ 1.0 - (thumbPosition - thumbMin) / (thumbMax - thumbMin) * 2;
};
/**
@@ -2032,7 +2118,8 @@ ScrubbyScrollBar.prototype.onMouseDown = function(event) {
window.addEventListener('mouseup', this.onWindowMouseUp, false);
if (this._thumbStyleTopAnimator)
this._thumbStyleTopAnimator.stop();
- this._timer = setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
+ this._timer =
+ setInterval(this.onScrollTimer, ScrubbyScrollBar.ScrollInterval);
event.stopPropagation();
event.preventDefault();
};
@@ -2052,7 +2139,8 @@ ScrubbyScrollBar.prototype.onWindowMouseUp = function(event) {
this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep;
this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop);
this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2);
- this._thumbStyleTopAnimator.timingFunction = AnimationTimingFunction.EaseInOut;
+ this._thumbStyleTopAnimator.timingFunction =
+ AnimationTimingFunction.EaseInOut;
this._thumbStyleTopAnimator.duration = 100;
this._thumbStyleTopAnimator.start();
@@ -2083,7 +2171,7 @@ ScrubbyScrollBar.prototype.onScrollTimer = function() {
function YearListCell(shortMonthLabels) {
ListCell.call(this);
this.element.classList.add(YearListCell.ClassNameYearListCell);
- this.element.style.height = YearListCell.Height + 'px';
+ this.element.style.height = YearListCell.GetHeight() + 'px';
/**
* @type {!Element}
@@ -2091,21 +2179,26 @@ function YearListCell(shortMonthLabels) {
*/
this.label = createElement('div', YearListCell.ClassNameLabel, '----');
this.element.appendChild(this.label);
- this.label.style.height = (YearListCell.Height - YearListCell.BorderBottomWidth) + 'px';
- this.label.style.lineHeight = (YearListCell.Height - YearListCell.BorderBottomWidth) + 'px';
+ this.label.style.height =
+ (YearListCell.GetHeight() - YearListCell.BorderBottomWidth) + 'px';
+ this.label.style.lineHeight =
+ (YearListCell.GetHeight() - YearListCell.BorderBottomWidth) + 'px';
/**
* @type {!Array} Array of the 12 month button elements.
* @const
*/
this.monthButtons = [];
- var monthChooserElement = createElement('div', YearListCell.ClassNameMonthChooser);
+ var monthChooserElement =
+ createElement('div', YearListCell.ClassNameMonthChooser);
for (var r = 0; r < YearListCell.ButtonRows; ++r) {
- var buttonsRow = createElement('div', YearListCell.ClassNameMonthButtonsRow);
+ var buttonsRow =
+ createElement('div', YearListCell.ClassNameMonthButtonsRow);
buttonsRow.setAttribute('role', 'row');
for (var c = 0; c < YearListCell.ButtonColumns; ++c) {
var month = c + r * YearListCell.ButtonColumns;
- var button = createElement('div', YearListCell.ClassNameMonthButton, shortMonthLabels[month]);
+ var button = createElement(
+ 'div', YearListCell.ClassNameMonthButton, shortMonthLabels[month]);
button.setAttribute('role', 'gridcell');
button.dataset.month = month;
buttonsRow.appendChild(button);
@@ -2129,17 +2222,33 @@ function YearListCell(shortMonthLabels) {
YearListCell.prototype = Object.create(ListCell.prototype);
-YearListCell.Height = hasInaccuratePointingDevice() ? 31 : 25;
+YearListCell._Height = hasInaccuratePointingDevice() ? 31 : 25;
+YearListCell._HeightRefresh = 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._SelectedHeight = hasInaccuratePointingDevice() ? 127 : 121;
+YearListCell._SelectedHeightRefresh = 128;
+YearListCell.GetSelectedHeight = function() {
+ if (global.params.isFormControlsRefreshEnabled) {
+ return YearListCell._SelectedHeightRefresh;
+ }
+ return YearListCell._SelectedHeight;
+};
YearListCell.ClassNameYearListCell = 'year-list-cell';
YearListCell.ClassNameLabel = 'label';
YearListCell.ClassNameMonthChooser = 'month-chooser';
YearListCell.ClassNameMonthButtonsRow = 'month-buttons-row';
YearListCell.ClassNameMonthButton = 'month-button';
YearListCell.ClassNameHighlighted = 'highlighted';
+YearListCell.ClassNameSelected = 'selected';
+YearListCell.ClassNameToday = 'today';
YearListCell._recycleBin = [];
@@ -2159,6 +2268,8 @@ YearListCell.prototype.reset = function(row) {
this.label.textContent = row + 1;
for (var i = 0; i < this.monthButtons.length; ++i) {
this.monthButtons[i].classList.remove(YearListCell.ClassNameHighlighted);
+ this.monthButtons[i].classList.remove(YearListCell.ClassNameSelected);
+ this.monthButtons[i].classList.remove(YearListCell.ClassNameToday);
}
this.show();
};
@@ -2195,6 +2306,10 @@ function YearListView(minimumMonth, maximumMonth) {
*/
this.highlightedMonth = null;
/**
+ * @type {?Month}
+ */
+ this._selectedMonth = null;
+ /**
* @type {!Month}
* @const
* @protected
@@ -2207,9 +2322,11 @@ function YearListView(minimumMonth, maximumMonth) {
*/
this._maximumMonth = maximumMonth;
- this.scrollView.minimumContentOffset = (this._minimumMonth.year - 1) * YearListCell.Height;
+ this.scrollView.minimumContentOffset =
+ (this._minimumMonth.year - 1) * YearListCell.GetHeight();
this.scrollView.maximumContentOffset =
- (this._maximumMonth.year - 1) * YearListCell.Height + YearListCell.SelectedHeight;
+ (this._maximumMonth.year - 1) * YearListCell.GetHeight() +
+ YearListCell.GetSelectedHeight();
/**
* @type {!Object}
@@ -2244,7 +2361,16 @@ function YearListView(minimumMonth, maximumMonth) {
YearListView.prototype = Object.create(ListView.prototype);
-YearListView.Height = YearListCell.SelectedHeight - 1;
+YearListView._Height = YearListCell._SelectedHeight - 1;
+YearListView._VisibleYearsRefresh = 4;
+YearListView._HeightRefresh = YearListCell._SelectedHeightRefresh - 1 +
+ YearListView._VisibleYearsRefresh * YearListCell._HeightRefresh;
+YearListView.GetHeight = function() {
+ if (global.params.isFormControlsRefreshEnabled) {
+ return YearListView._HeightRefresh;
+ }
+ return YearListView._Height;
+};
YearListView.EventTypeYearListViewDidHide = 'yearListViewDidHide';
YearListView.EventTypeYearListViewDidSelectMonth = 'yearListViewDidSelectMonth';
@@ -2253,24 +2379,30 @@ YearListView.EventTypeYearListViewDidSelectMonth = 'yearListViewDidSelectMonth';
*/
YearListView.prototype.onTouchStart = function(event) {
var touch = event.touches[0];
- var monthButtonElement = enclosingNodeOrSelfWithClass(touch.target, YearListCell.ClassNameMonthButton);
+ var monthButtonElement = enclosingNodeOrSelfWithClass(
+ touch.target, YearListCell.ClassNameMonthButton);
if (!monthButtonElement)
return;
- var cellElement = enclosingNodeOrSelfWithClass(monthButtonElement, YearListCell.ClassNameYearListCell);
+ var cellElement = enclosingNodeOrSelfWithClass(
+ monthButtonElement, YearListCell.ClassNameYearListCell);
var cell = cellElement.$view;
- this.highlightMonth(new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
+ 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);
+ var monthButtonElement = enclosingNodeOrSelfWithClass(
+ event.target, YearListCell.ClassNameMonthButton);
if (!monthButtonElement)
return;
- var cellElement = enclosingNodeOrSelfWithClass(monthButtonElement, YearListCell.ClassNameYearListCell);
+ var cellElement = enclosingNodeOrSelfWithClass(
+ monthButtonElement, YearListCell.ClassNameYearListCell);
var cell = cellElement.$view;
- this.highlightMonth(new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
+ this.highlightMonth(
+ new Month(cell.row + 1, parseInt(monthButtonElement.dataset.month, 10)));
this._ignoreMouseOutUntillNextMouseOver = false;
};
@@ -2280,7 +2412,8 @@ YearListView.prototype.onMouseOver = function(event) {
YearListView.prototype.onMouseOut = function(event) {
if (this._ignoreMouseOutUntillNextMouseOver)
return;
- var monthButtonElement = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
+ var monthButtonElement = enclosingNodeOrSelfWithClass(
+ event.target, YearListCell.ClassNameMonthButton);
if (!monthButtonElement) {
this.dehighlightMonth();
}
@@ -2291,7 +2424,8 @@ YearListView.prototype.onMouseOut = function(event) {
* @override
*/
YearListView.prototype.setWidth = function(width) {
- ListView.prototype.setWidth.call(this, width - this.scrubbyScrollBar.element.offsetWidth);
+ ListView.prototype.setWidth.call(
+ this, width - this.scrubbyScrollBar.element.offsetWidth);
this.element.style.width = width + 'px';
};
@@ -2317,8 +2451,9 @@ YearListView.RowAnimationDirection = {
* @param {!YearListView.RowAnimationDirection} direction
*/
YearListView.prototype._animateRow = function(row, direction) {
- var fromValue =
- direction === YearListView.RowAnimationDirection.Closing ? YearListCell.SelectedHeight : YearListCell.Height;
+ var fromValue = direction === YearListView.RowAnimationDirection.Closing ?
+ YearListCell.GetSelectedHeight() :
+ YearListCell.GetHeight();
var oldAnimator = this._runningAnimators[row];
if (oldAnimator) {
oldAnimator.stop();
@@ -2329,11 +2464,14 @@ YearListView.prototype._animateRow = function(row, direction) {
animator.step = this.onCellHeightAnimatorStep;
animator.setFrom(fromValue);
animator.setTo(
- direction === YearListView.RowAnimationDirection.Opening ? YearListCell.SelectedHeight : YearListCell.Height);
+ direction === YearListView.RowAnimationDirection.Opening ?
+ YearListCell.GetSelectedHeight() :
+ YearListCell.GetHeight());
animator.timingFunction = AnimationTimingFunction.EaseInOut;
animator.duration = 300;
animator.row = row;
- animator.on(Animator.EventTypeDidAnimationStop, this.onCellHeightAnimatorDidStop);
+ animator.on(
+ Animator.EventTypeDidAnimationStop, this.onCellHeightAnimatorDidStop);
this._runningAnimators[row] = animator;
this._animatingRows.push(row);
this._animatingRows.sort();
@@ -2368,14 +2506,19 @@ YearListView.prototype.onClick = function(event) {
var year = this.selectedRow + 1;
if (this.selectedRow !== oldSelectedRow) {
var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
- this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
- this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
+ this.dispatchEvent(
+ YearListView.EventTypeYearListViewDidSelectMonth, this,
+ new Month(year, month));
+ this.scrollView.scrollTo(this.selectedRow * YearListCell.GetHeight(), true);
} else {
- var monthButton = enclosingNodeOrSelfWithClass(event.target, YearListCell.ClassNameMonthButton);
+ var monthButton = enclosingNodeOrSelfWithClass(
+ event.target, YearListCell.ClassNameMonthButton);
if (!monthButton || monthButton.getAttribute('aria-disabled') == 'true')
return;
var month = parseInt(monthButton.dataset.month, 10);
- this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, new Month(year, month));
+ this.dispatchEvent(
+ YearListView.EventTypeYearListViewDidSelectMonth, this,
+ new Month(year, month));
this.hide();
}
};
@@ -2396,17 +2539,21 @@ YearListView.prototype.rowAtScrollOffset = function(scrollOffset) {
for (var i = 0; i < rowsWithIrregularHeight.length; ++i) {
var row = rowsWithIrregularHeight[i];
var animator = this._runningAnimators[row];
- var rowHeight = animator ? animator.currentValue : YearListCell.SelectedHeight;
- if (remainingOffset <= (row - lastAnimatingRow) * YearListCell.Height) {
- return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
+ var rowHeight =
+ animator ? animator.currentValue : YearListCell.GetSelectedHeight();
+ if (remainingOffset <=
+ (row - lastAnimatingRow) * YearListCell.GetHeight()) {
+ return lastAnimatingRow +
+ Math.floor(remainingOffset / YearListCell.GetHeight());
}
- remainingOffset -= (row - lastAnimatingRow) * YearListCell.Height;
- if (remainingOffset <= (rowHeight - YearListCell.Height))
+ remainingOffset -= (row - lastAnimatingRow) * YearListCell.GetHeight();
+ if (remainingOffset <= (rowHeight - YearListCell.GetHeight()))
return row;
- remainingOffset -= rowHeight - YearListCell.Height;
+ remainingOffset -= rowHeight - YearListCell.GetHeight();
lastAnimatingRow = row;
}
- return lastAnimatingRow + Math.floor(remainingOffset / YearListCell.Height);
+ return lastAnimatingRow +
+ Math.floor(remainingOffset / YearListCell.GetHeight());
};
/**
@@ -2415,16 +2562,17 @@ YearListView.prototype.rowAtScrollOffset = function(scrollOffset) {
* @override
*/
YearListView.prototype.scrollOffsetForRow = function(row) {
- var scrollOffset = row * YearListCell.Height;
+ var scrollOffset = row * YearListCell.GetHeight();
for (var i = 0; i < this._animatingRows.length; ++i) {
var animatingRow = this._animatingRows[i];
if (animatingRow >= row)
break;
var animator = this._runningAnimators[animatingRow];
- scrollOffset += animator.currentValue - YearListCell.Height;
+ scrollOffset += animator.currentValue - YearListCell.GetHeight();
}
- if (this.selectedRow > -1 && this.selectedRow < row && !this._runningAnimators[this.selectedRow]) {
- scrollOffset += YearListCell.SelectedHeight - YearListCell.Height;
+ if (this.selectedRow > -1 && this.selectedRow < row &&
+ !this._runningAnimators[this.selectedRow]) {
+ scrollOffset += YearListCell.GetSelectedHeight() - YearListCell.GetHeight();
}
return scrollOffset;
};
@@ -2435,14 +2583,17 @@ YearListView.prototype.scrollOffsetForRow = function(row) {
* @override
*/
YearListView.prototype.prepareNewCell = function(row) {
- var cell = YearListCell._recycleBin.pop() || new YearListCell(global.params.shortMonthLabels);
+ var cell = YearListCell._recycleBin.pop() ||
+ new YearListCell(global.params.shortMonthLabels);
cell.reset(row);
cell.setSelected(this.selectedRow === row);
for (var i = 0; i < cell.monthButtons.length; ++i) {
var month = new Month(row + 1, i);
cell.monthButtons[i].id = month.toString();
cell.monthButtons[i].setAttribute(
- 'aria-disabled', this._minimumMonth > month || this._maximumMonth < month ? 'true' : 'false');
+ 'aria-disabled',
+ this._minimumMonth > month || this._maximumMonth < month ? 'true' :
+ 'false');
cell.monthButtons[i].setAttribute('aria-label', month.toLocaleString());
}
if (this.highlightedMonth && row === this.highlightedMonth.year - 1) {
@@ -2455,13 +2606,23 @@ YearListView.prototype.prepareNewCell = function(row) {
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);
+ }
+ const todayMonth = Month.createFromToday();
+ if ((todayMonth.year - 1) === row) {
+ var monthButton = cell.monthButtons[todayMonth.month];
+ monthButton.classList.add(YearListCell.ClassNameToday);
+ }
+
var animator = this._runningAnimators[row];
if (animator)
cell.setHeight(animator.currentValue);
else if (row === this.selectedRow)
- cell.setHeight(YearListCell.SelectedHeight);
+ cell.setHeight(YearListCell.GetSelectedHeight());
else
- cell.setHeight(YearListCell.Height);
+ cell.setHeight(YearListCell.GetHeight());
return cell;
};
@@ -2480,7 +2641,8 @@ YearListView.prototype.updateCells = function() {
for (var i = firstVisibleRow; i <= lastVisibleRow; ++i) {
var cell = this._cells[i];
if (cell)
- cell.setPosition(this.scrollView.contentPositionForContentOffset(this.scrollOffsetForRow(cell.row)));
+ cell.setPosition(this.scrollView.contentPositionForContentOffset(
+ this.scrollOffsetForRow(cell.row)));
else
this.addCellIfNecessary(i);
}
@@ -2496,7 +2658,8 @@ YearListView.prototype.deselect = function() {
var selectedCell = this._cells[this.selectedRow];
if (selectedCell)
selectedCell.setSelected(false);
- this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Closing);
+ this._animateRow(
+ this.selectedRow, YearListView.RowAnimationDirection.Closing);
this.selectedRow = ListView.NoSelection;
this.setNeedsUpdateCells(true);
};
@@ -2507,7 +2670,7 @@ YearListView.prototype.deselectWithoutAnimating = function() {
var selectedCell = this._cells[this.selectedRow];
if (selectedCell) {
selectedCell.setSelected(false);
- selectedCell.setHeight(YearListCell.Height);
+ selectedCell.setHeight(YearListCell.GetHeight());
}
this.selectedRow = ListView.NoSelection;
this.setNeedsUpdateCells(true);
@@ -2526,7 +2689,8 @@ YearListView.prototype.select = function(row) {
this.selectedRow = row;
if (this.selectedRow !== ListView.NoSelection) {
var selectedCell = this._cells[this.selectedRow];
- this._animateRow(this.selectedRow, YearListView.RowAnimationDirection.Opening);
+ this._animateRow(
+ this.selectedRow, YearListView.RowAnimationDirection.Opening);
if (selectedCell)
selectedCell.setSelected(true);
var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
@@ -2549,7 +2713,7 @@ YearListView.prototype.selectWithoutAnimating = function(row) {
var selectedCell = this._cells[this.selectedRow];
if (selectedCell) {
selectedCell.setSelected(true);
- selectedCell.setHeight(YearListCell.SelectedHeight);
+ selectedCell.setHeight(YearListCell.GetSelectedHeight());
}
var month = this.highlightedMonth ? this.highlightedMonth.month : 0;
this.highlightMonth(new Month(this.selectedRow + 1, month));
@@ -2599,6 +2763,17 @@ YearListView.prototype.highlightMonth = function(month) {
}
};
+YearListView.prototype.setSelectedMonth = function(month) {
+ this._selectedMonth = month;
+};
+
+YearListView.prototype.showSelectedMonth = function() {
+ var monthButton = this.buttonForMonth(this._selectedMonth);
+ if (monthButton) {
+ monthButton.classList.add(YearListCell.ClassNameSelected);
+ }
+};
+
/**
* @param {!Month} month
*/
@@ -2608,6 +2783,7 @@ YearListView.prototype.show = function(month) {
this.scrollToRow(month.year - 1, false);
this.selectWithoutAnimating(month.year - 1);
this.highlightMonth(month);
+ this.showSelectedMonth();
};
YearListView.prototype.hide = function() {
@@ -2621,8 +2797,9 @@ YearListView.prototype._moveHighlightTo = function(month) {
this.highlightMonth(month);
this.select(this.highlightedMonth.year - 1);
- this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, month);
- this.scrollView.scrollTo(this.selectedRow * YearListCell.Height, true);
+ this.dispatchEvent(
+ YearListView.EventTypeYearListViewDidSelectMonth, this, month);
+ this.scrollView.scrollTo(this.selectedRow * YearListCell.GetHeight(), true);
return true;
};
@@ -2638,25 +2815,32 @@ YearListView.prototype.onKeyDown = function(event) {
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.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));
+ eventHandled = this._moveHighlightTo(
+ this.highlightedMonth.next(YearListCell.ButtonColumns));
else if (key == 'PageUp')
- eventHandled = this._moveHighlightTo(this.highlightedMonth.previous(MonthsPerYear));
+ eventHandled =
+ this._moveHighlightTo(this.highlightedMonth.previous(MonthsPerYear));
else if (key == 'PageDown')
- eventHandled = this._moveHighlightTo(this.highlightedMonth.next(MonthsPerYear));
+ eventHandled =
+ this._moveHighlightTo(this.highlightedMonth.next(MonthsPerYear));
else if (key == 'Enter') {
- this.dispatchEvent(YearListView.EventTypeYearListViewDidSelectMonth, this, this.highlightedMonth);
+ this.dispatchEvent(
+ YearListView.EventTypeYearListViewDidSelectMonth, this,
+ this.highlightedMonth);
this.hide();
eventHandled = true;
}
} else if (key == 'ArrowUp') {
- this.scrollView.scrollBy(-YearListCell.Height, true);
+ this.scrollView.scrollBy(-YearListCell.GetHeight(), true);
eventHandled = true;
} else if (key == 'ArrowDown') {
- this.scrollView.scrollBy(YearListCell.Height, true);
+ this.scrollView.scrollBy(YearListCell.GetHeight(), true);
eventHandled = true;
} else if (key == 'PageUp') {
this.scrollView.scrollBy(-this.scrollView.height(), true);
@@ -2704,7 +2888,7 @@ MonthPopupView.prototype.show = function(initialMonth, calendarTableRect) {
this.isVisible = true;
document.body.appendChild(this.element);
this.yearListView.setWidth(calendarTableRect.width - 2);
- this.yearListView.setHeight(YearListView.Height);
+ this.yearListView.setHeight(YearListView.GetHeight());
if (global.params.isLocaleRTL)
this.yearListView.element.style.right = calendarTableRect.x + 'px';
else
@@ -2737,21 +2921,25 @@ MonthPopupView.prototype.onClick = function(event) {
* @param {!number} maxWidth Maximum width in pixels.
*/
function MonthPopupButton(maxWidth) {
- View.call(this, createElement('button', MonthPopupButton.ClassNameMonthPopupButton));
+ View.call(
+ this,
+ createElement('button', MonthPopupButton.ClassNameMonthPopupButton));
this.element.setAttribute('aria-label', global.params.axShowMonthSelector);
/**
* @type {!Element}
* @const
*/
- this.labelElement = createElement('span', MonthPopupButton.ClassNameMonthPopupButtonLabel, '-----');
+ this.labelElement = createElement(
+ 'span', MonthPopupButton.ClassNameMonthPopupButtonLabel, '-----');
this.element.appendChild(this.labelElement);
/**
* @type {!Element}
* @const
*/
- this.disclosureTriangleIcon = createElement('span', MonthPopupButton.ClassNameDisclosureTriangle);
+ this.disclosureTriangleIcon =
+ createElement('span', MonthPopupButton.ClassNameDisclosureTriangle);
this.disclosureTriangleIcon.innerHTML =
'<svg width=\'7\' height=\'5\'><polygon points=\'0,1 7,1 3.5,5\' style=\'fill:#000000;\' /></svg>';
this.element.appendChild(this.disclosureTriangleIcon);
@@ -2794,7 +2982,9 @@ MonthPopupButton.prototype._shouldUseShortMonth = function(maxWidth) {
* @param {!Month} month
*/
MonthPopupButton.prototype.setCurrentMonth = function(month) {
- this.labelElement.textContent = this._useShortMonth ? month.toShortLocaleString() : month.toLocaleString();
+ this.labelElement.textContent = this._useShortMonth ?
+ month.toShortLocaleString() :
+ month.toLocaleString();
};
/**
@@ -2809,15 +2999,21 @@ MonthPopupButton.prototype.onClick = function(event) {
* @extends View
*/
function CalendarNavigationButton() {
- View.call(this, createElement('button', CalendarNavigationButton.ClassNameCalendarNavigationButton));
+ View.call(
+ this,
+ createElement(
+ 'button',
+ CalendarNavigationButton.ClassNameCalendarNavigationButton));
/**
* @type {number} Threshold for starting repeating clicks in milliseconds.
*/
- this.repeatingClicksStartingThreshold = CalendarNavigationButton.DefaultRepeatingClicksStartingThreshold;
+ this.repeatingClicksStartingThreshold =
+ CalendarNavigationButton.DefaultRepeatingClicksStartingThreshold;
/**
* @type {number} Interval between reapeating clicks in milliseconds.
*/
- this.reapeatingClicksInterval = CalendarNavigationButton.DefaultRepeatingClicksInterval;
+ this.reapeatingClicksInterval =
+ CalendarNavigationButton.DefaultRepeatingClicksInterval;
/**
* @type {?number} The ID for the timeout that triggers the repeating clicks.
*/
@@ -2833,7 +3029,8 @@ CalendarNavigationButton.DefaultRepeatingClicksStartingThreshold = 600;
CalendarNavigationButton.DefaultRepeatingClicksInterval = 300;
CalendarNavigationButton.LeftMargin = 4;
CalendarNavigationButton.Width = 24;
-CalendarNavigationButton.ClassNameCalendarNavigationButton = 'calendar-navigation-button';
+CalendarNavigationButton.ClassNameCalendarNavigationButton =
+ 'calendar-navigation-button';
CalendarNavigationButton.EventTypeButtonClick = 'buttonClick';
CalendarNavigationButton.EventTypeRepeatingButtonClick = 'repeatingButtonClick';
@@ -2857,7 +3054,8 @@ CalendarNavigationButton.prototype.onClick = function(event) {
CalendarNavigationButton.prototype.onTouchStart = function(event) {
if (this._timer !== null)
return;
- this._timer = setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
+ this._timer =
+ setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
window.addEventListener('touchend', this.onWindowTouchEnd, false);
};
@@ -2878,7 +3076,8 @@ CalendarNavigationButton.prototype.onWindowTouchEnd = function(event) {
CalendarNavigationButton.prototype.onMouseDown = function(event) {
if (this._timer !== null)
return;
- this._timer = setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
+ this._timer =
+ setTimeout(this.onRepeatingClick, this.repeatingClicksStartingThreshold);
window.addEventListener('mouseup', this.onWindowMouseUp, false);
};
@@ -2897,8 +3096,10 @@ CalendarNavigationButton.prototype.onWindowMouseUp = function(event) {
* @param {?Event} event
*/
CalendarNavigationButton.prototype.onRepeatingClick = function(event) {
- this.dispatchEvent(CalendarNavigationButton.EventTypeRepeatingButtonClick, this);
- this._timer = setTimeout(this.onRepeatingClick, this.reapeatingClicksInterval);
+ this.dispatchEvent(
+ CalendarNavigationButton.EventTypeRepeatingButtonClick, this);
+ this._timer =
+ setTimeout(this.onRepeatingClick, this.reapeatingClicksInterval);
};
/**
@@ -2907,19 +3108,25 @@ CalendarNavigationButton.prototype.onRepeatingClick = function(event) {
* @param {!CalendarPicker} calendarPicker
*/
function CalendarHeaderView(calendarPicker) {
- View.call(this, createElement('div', CalendarHeaderView.ClassNameCalendarHeaderView));
+ View.call(
+ this,
+ createElement('div', CalendarHeaderView.ClassNameCalendarHeaderView));
this.calendarPicker = calendarPicker;
- this.calendarPicker.on(CalendarPicker.EventTypeCurrentMonthChanged, this.onCurrentMonthChanged);
+ this.calendarPicker.on(
+ CalendarPicker.EventTypeCurrentMonthChanged, this.onCurrentMonthChanged);
- var titleElement = createElement('div', CalendarHeaderView.ClassNameCalendarTitle);
+ var titleElement =
+ createElement('div', CalendarHeaderView.ClassNameCalendarTitle);
this.element.appendChild(titleElement);
/**
* @type {!MonthPopupButton}
*/
this.monthPopupButton = new MonthPopupButton(
- this.calendarPicker.calendarTableView.width() - CalendarTableView.GetBorderWidth() * 2 -
- CalendarNavigationButton.Width * 3 - CalendarNavigationButton.LeftMargin * 2);
+ this.calendarPicker.calendarTableView.width() -
+ CalendarTableView.GetBorderWidth() * 2 -
+ CalendarNavigationButton.Width * 3 -
+ CalendarNavigationButton.LeftMargin * 2);
this.monthPopupButton.attachTo(titleElement);
/**
@@ -2928,9 +3135,14 @@ function CalendarHeaderView(calendarPicker) {
*/
this._previousMonthButton = new CalendarNavigationButton();
this._previousMonthButton.attachTo(this);
- this._previousMonthButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
- this._previousMonthButton.on(CalendarNavigationButton.EventTypeRepeatingButtonClick, this.onNavigationButtonClick);
- this._previousMonthButton.element.setAttribute('aria-label', global.params.axShowPreviousMonth);
+ this._previousMonthButton.on(
+ CalendarNavigationButton.EventTypeButtonClick,
+ this.onNavigationButtonClick);
+ this._previousMonthButton.on(
+ CalendarNavigationButton.EventTypeRepeatingButtonClick,
+ this.onNavigationButtonClick);
+ this._previousMonthButton.element.setAttribute(
+ 'aria-label', global.params.axShowPreviousMonth);
if (!global.params.isFormControlsRefreshEnabled) {
/**
@@ -2939,13 +3151,17 @@ function CalendarHeaderView(calendarPicker) {
*/
this._todayButton = new CalendarNavigationButton();
this._todayButton.attachTo(this);
- this._todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
- this._todayButton.element.classList.add(CalendarHeaderView.GetClassNameTodayButton());
+ this._todayButton.on(
+ CalendarNavigationButton.EventTypeButtonClick,
+ this.onNavigationButtonClick);
+ this._todayButton.element.classList.add(
+ CalendarHeaderView.GetClassNameTodayButton());
var monthContainingToday = Month.createFromToday();
this._todayButton.setDisabled(
monthContainingToday < this.calendarPicker.minimumMonth ||
monthContainingToday > this.calendarPicker.maximumMonth);
- this._todayButton.element.setAttribute('aria-label', global.params.todayLabel);
+ this._todayButton.element.setAttribute(
+ 'aria-label', global.params.todayLabel);
}
/**
@@ -2954,16 +3170,25 @@ function CalendarHeaderView(calendarPicker) {
*/
this._nextMonthButton = new CalendarNavigationButton();
this._nextMonthButton.attachTo(this);
- this._nextMonthButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onNavigationButtonClick);
- this._nextMonthButton.on(CalendarNavigationButton.EventTypeRepeatingButtonClick, this.onNavigationButtonClick);
- this._nextMonthButton.element.setAttribute('aria-label', global.params.axShowNextMonth);
+ this._nextMonthButton.on(
+ CalendarNavigationButton.EventTypeButtonClick,
+ this.onNavigationButtonClick);
+ this._nextMonthButton.on(
+ CalendarNavigationButton.EventTypeRepeatingButtonClick,
+ this.onNavigationButtonClick);
+ this._nextMonthButton.element.setAttribute(
+ 'aria-label', global.params.axShowNextMonth);
if (global.params.isLocaleRTL) {
- this._nextMonthButton.element.innerHTML = CalendarHeaderView.GetBackwardTriangle();
- this._previousMonthButton.element.innerHTML = CalendarHeaderView.GetForwardTriangle();
+ this._nextMonthButton.element.innerHTML =
+ CalendarHeaderView.GetBackwardTriangle();
+ this._previousMonthButton.element.innerHTML =
+ CalendarHeaderView.GetForwardTriangle();
} else {
- this._nextMonthButton.element.innerHTML = CalendarHeaderView.GetForwardTriangle();
- this._previousMonthButton.element.innerHTML = CalendarHeaderView.GetBackwardTriangle();
+ this._nextMonthButton.element.innerHTML =
+ CalendarHeaderView.GetForwardTriangle();
+ this._previousMonthButton.element.innerHTML =
+ CalendarHeaderView.GetBackwardTriangle();
}
}
@@ -2982,7 +3207,7 @@ CalendarHeaderView.GetForwardTriangle = function() {
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 =
@@ -2994,7 +3219,7 @@ CalendarHeaderView.GetBackwardTriangle = function() {
return CalendarHeaderView._BackwardTriangleRefresh;
}
return CalendarHeaderView._BackwardTriangle;
-}
+};
CalendarHeaderView.ClassNameCalendarHeaderView = 'calendar-header-view';
CalendarHeaderView.ClassNameCalendarTitle = 'calendar-title';
CalendarHeaderView.ClassNameTodayButton = 'today-button';
@@ -3004,23 +3229,27 @@ CalendarHeaderView.GetClassNameTodayButton = function() {
return CalendarHeaderView.ClassNameTodayButtonRefresh;
}
return CalendarHeaderView.ClassNameTodayButton;
-}
+};
CalendarHeaderView.prototype.onCurrentMonthChanged = function() {
this.monthPopupButton.setCurrentMonth(this.calendarPicker.currentMonth());
this._previousMonthButton.setDisabled(
- this.disabled || this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
+ this.disabled ||
+ this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
this._nextMonthButton.setDisabled(
- this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
+ this.disabled ||
+ this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
};
CalendarHeaderView.prototype.onNavigationButtonClick = function(sender) {
if (sender === this._previousMonthButton)
this.calendarPicker.setCurrentMonth(
- this.calendarPicker.currentMonth().previous(), CalendarPicker.NavigationBehavior.WithAnimation);
+ this.calendarPicker.currentMonth().previous(),
+ CalendarPicker.NavigationBehavior.WithAnimation);
else if (sender === this._nextMonthButton)
this.calendarPicker.setCurrentMonth(
- this.calendarPicker.currentMonth().next(), CalendarPicker.NavigationBehavior.WithAnimation);
+ this.calendarPicker.currentMonth().next(),
+ CalendarPicker.NavigationBehavior.WithAnimation);
else
this.calendarPicker.selectRangeContainingDay(Day.createFromToday());
};
@@ -3031,19 +3260,24 @@ 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 || this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
+ this.disabled ||
+ this.calendarPicker.currentMonth() <= this.calendarPicker.minimumMonth);
this._nextMonthButton.setDisabled(
- this.disabled || this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
+ this.disabled ||
+ this.calendarPicker.currentMonth() >= this.calendarPicker.maximumMonth);
if (this._todayButton) {
var monthContainingToday = Month.createFromToday();
this._todayButton.setDisabled(
- this.disabled || monthContainingToday < this.calendarPicker.minimumMonth ||
+ this.disabled ||
+ monthContainingToday < this.calendarPicker.minimumMonth ||
monthContainingToday > this.calendarPicker.maximumMonth);
}
};
@@ -3057,7 +3291,8 @@ function DayCell() {
this.element.classList.add(DayCell.ClassNameDayCell);
this.element.style.width = DayCell.GetWidth() + 'px';
this.element.style.height = DayCell.GetHeight() + 'px';
- this.element.style.lineHeight = (DayCell.GetHeight() - DayCell.PaddingSize * 2) + 'px';
+ this.element.style.lineHeight =
+ (DayCell.GetHeight() - DayCell.PaddingSize * 2) + 'px';
this.element.setAttribute('role', 'gridcell');
/**
* @type {?Day}
@@ -3074,7 +3309,7 @@ DayCell.GetWidth = function() {
return DayCell._WidthRefresh;
}
return DayCell._Width;
-}
+};
DayCell._Height = hasInaccuratePointingDevice() ? 34 : 20;
DayCell._HeightRefresh = 28;
DayCell.GetHeight = function() {
@@ -3082,7 +3317,7 @@ DayCell.GetHeight = function() {
return DayCell._HeightRefresh;
}
return DayCell._Height;
-}
+};
DayCell.PaddingSize = 1;
DayCell.ClassNameDayCell = 'day-cell';
DayCell.ClassNameHighlighted = 'highlighted';
@@ -3173,9 +3408,11 @@ DayCell.prototype.reset = function(day) {
function WeekNumberCell() {
ListCell.call(this);
this.element.classList.add(WeekNumberCell.ClassNameWeekNumberCell);
- this.element.style.width = (WeekNumberCell.Width - WeekNumberCell.SeparatorWidth) + 'px';
+ this.element.style.width =
+ (WeekNumberCell.Width - WeekNumberCell.SeparatorWidth) + 'px';
this.element.style.height = WeekNumberCell.GetHeight() + 'px';
- this.element.style.lineHeight = (WeekNumberCell.GetHeight() - WeekNumberCell.PaddingSize * 2) + 'px';
+ this.element.style.lineHeight =
+ (WeekNumberCell.GetHeight() - WeekNumberCell.PaddingSize * 2) + 'px';
/**
* @type {?Week}
*/
@@ -3192,7 +3429,7 @@ WeekNumberCell.GetHeight = function() {
return WeekNumberCell._HeightRefresh;
}
return WeekNumberCell._Height;
-}
+};
WeekNumberCell.SeparatorWidth = 1;
WeekNumberCell.PaddingSize = 1;
WeekNumberCell.ClassNameWeekNumberCell = 'week-number-cell';
@@ -3224,7 +3461,9 @@ WeekNumberCell.prototype.reset = function(week) {
this.element.id = week.toString();
this.element.setAttribute('role', 'gridcell');
this.element.setAttribute(
- 'aria-label', window.pagePopupController.formatWeek(week.year, week.week, week.firstDay().format()));
+ 'aria-label',
+ window.pagePopupController.formatWeek(
+ week.year, week.week, week.firstDay().format()));
this.element.textContent = localizeNumber(this.week.week.toString());
this.show();
};
@@ -3262,13 +3501,15 @@ WeekNumberCell.prototype.setDisabled = function(disabled) {
function CalendarTableHeaderView(hasWeekNumberColumn) {
View.call(this, createElement('div', 'calendar-table-header-view'));
if (hasWeekNumberColumn) {
- var weekNumberLabelElement = createElement('div', 'week-number-label', global.params.weekLabel);
+ var weekNumberLabelElement =
+ createElement('div', 'week-number-label', global.params.weekLabel);
weekNumberLabelElement.style.width = WeekNumberCell.Width + 'px';
this.element.appendChild(weekNumberLabelElement);
}
for (var i = 0; i < DaysPerWeek; ++i) {
var weekDayNumber = (global.params.weekStartDay + i) % DaysPerWeek;
- var labelElement = createElement('div', 'week-day-label', global.params.dayLabels[weekDayNumber]);
+ var labelElement = createElement(
+ 'div', 'week-day-label', global.params.dayLabels[weekDayNumber]);
labelElement.style.width = DayCell.GetWidth() + 'px';
this.element.appendChild(labelElement);
if (getLanguage() === 'ja') {
@@ -3289,7 +3530,7 @@ CalendarTableHeaderView.GetHeight = function() {
return CalendarTableHeaderView._HeightRefresh;
}
return CalendarTableHeaderView._Height;
-}
+};
/**
* @constructor
@@ -3325,7 +3566,7 @@ CalendarRowCell.GetHeight = function() {
return CalendarRowCell._HeightRefresh;
}
return CalendarRowCell._Height;
-}
+};
CalendarRowCell.ClassNameCalendarRowCell = 'calendar-row-cell';
CalendarRowCell._recycleBin = [];
@@ -3368,7 +3609,8 @@ CalendarRowCell.prototype.throwAway = function() {
ListCell.prototype.throwAway.call(this);
if (this.weekNumberCell)
this.calendarTableView.throwAwayWeekNumberCell(this.weekNumberCell);
- this._dayCells.forEach(this.calendarTableView.throwAwayDayCell, this.calendarTableView);
+ this._dayCells.forEach(
+ this.calendarTableView.throwAwayDayCell, this.calendarTableView);
this._dayCells.length = 0;
};
@@ -3407,9 +3649,11 @@ function CalendarTableView(calendarPicker) {
*/
var todayButton = new CalendarNavigationButton();
todayButton.attachTo(this);
- todayButton.on(CalendarNavigationButton.EventTypeButtonClick, this.onTodayButtonClick);
+ todayButton.on(
+ CalendarNavigationButton.EventTypeButtonClick, this.onTodayButtonClick);
todayButton.element.textContent = global.params.todayLabel;
- todayButton.element.classList.add(CalendarHeaderView.GetClassNameTodayButton());
+ todayButton.element.classList.add(
+ CalendarHeaderView.GetClassNameTodayButton());
var monthContainingToday = Month.createFromToday();
todayButton.setDisabled(
monthContainingToday < this.calendarPicker.minimumMonth ||
@@ -3440,9 +3684,11 @@ function CalendarTableView(calendarPicker) {
this.element.addEventListener('mouseout', this.onMouseOut, false);
// You shouldn't be able to use the mouse wheel to scroll.
- this.scrollView.element.removeEventListener('mousewheel', this.scrollView.onMouseWheel, false);
+ this.scrollView.element.removeEventListener(
+ 'mousewheel', this.scrollView.onMouseWheel, false);
// You shouldn't be able to do gesture scroll.
- this.scrollView.element.removeEventListener('touchstart', this.scrollView.onTouchStart, false);
+ this.scrollView.element.removeEventListener(
+ 'touchstart', this.scrollView.onTouchStart, false);
}
CalendarTableView.prototype = Object.create(ListView.prototype);
@@ -3454,7 +3700,7 @@ CalendarTableView.GetBorderWidth = function() {
return CalendarTableView._BorderWidthRefresh;
}
return CalendarTableView._BorderWidth;
-}
+};
CalendarTableView._TodayButtonHeight = 0;
CalendarTableView._TodayButtonHeightRefresh = 28;
CalendarTableView.GetTodayButtonHeight = function() {
@@ -3462,7 +3708,7 @@ CalendarTableView.GetTodayButtonHeight = function() {
return CalendarTableView._TodayButtonHeightRefresh;
}
return CalendarTableView._TodayButtonHeight;
-}
+};
CalendarTableView.ClassNameCalendarTableView = 'calendar-table-view';
/**
@@ -3486,14 +3732,17 @@ CalendarTableView.prototype.scrollOffsetForRow = function(row) {
*/
CalendarTableView.prototype.onClick = function(event) {
if (this.hasWeekNumberColumn) {
- var weekNumberCellElement = enclosingNodeOrSelfWithClass(event.target, WeekNumberCell.ClassNameWeekNumberCell);
+ var weekNumberCellElement = enclosingNodeOrSelfWithClass(
+ event.target, WeekNumberCell.ClassNameWeekNumberCell);
if (weekNumberCellElement) {
var weekNumberCell = weekNumberCellElement.$view;
- this.calendarPicker.selectRangeContainingDay(weekNumberCell.week.firstDay());
+ this.calendarPicker.selectRangeContainingDay(
+ weekNumberCell.week.firstDay());
return;
}
}
- var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
+ var dayCellElement =
+ enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
if (!dayCellElement)
return;
var dayCell = dayCellElement.$view;
@@ -3502,22 +3751,25 @@ CalendarTableView.prototype.onClick = function(event) {
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);
+ var weekNumberCellElement = enclosingNodeOrSelfWithClass(
+ event.target, WeekNumberCell.ClassNameWeekNumberCell);
if (weekNumberCellElement) {
var weekNumberCell = weekNumberCellElement.$view;
- this.calendarPicker.highlightRangeContainingDay(weekNumberCell.week.firstDay());
+ this.calendarPicker.highlightRangeContainingDay(
+ weekNumberCell.week.firstDay());
this._ignoreMouseOutUntillNextMouseOver = false;
return;
}
}
- var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
+ var dayCellElement =
+ enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
if (!dayCellElement)
return;
var dayCell = dayCellElement.$view;
@@ -3531,7 +3783,8 @@ CalendarTableView.prototype.onMouseOver = function(event) {
CalendarTableView.prototype.onMouseOut = function(event) {
if (this._ignoreMouseOutUntillNextMouseOver)
return;
- var dayCellElement = enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
+ var dayCellElement =
+ enclosingNodeOrSelfWithClass(event.target, DayCell.ClassNameDayCell);
if (!dayCellElement) {
this.calendarPicker.highlightRangeContainingDay(null);
}
@@ -3551,14 +3804,19 @@ CalendarTableView.prototype.prepareNewCell = function(row) {
* @return {!number} Height in pixels.
*/
CalendarTableView.prototype.height = function() {
- return this.scrollView.height() + CalendarTableHeaderView.GetHeight() + CalendarTableView.GetBorderWidth() * 2 + CalendarTableView.GetTodayButtonHeight();
+ return this.scrollView.height() + CalendarTableHeaderView.GetHeight() +
+ CalendarTableView.GetBorderWidth() * 2 +
+ CalendarTableView.GetTodayButtonHeight();
};
/**
* @param {!number} height Height in pixels.
*/
CalendarTableView.prototype.setHeight = function(height) {
- this.scrollView.setHeight(height - CalendarTableHeaderView.GetHeight() - CalendarTableView.GetBorderWidth() * 2 - CalendarTableView.GetTodayButtonHeight());
+ this.scrollView.setHeight(
+ height - CalendarTableHeaderView.GetHeight() -
+ CalendarTableView.GetBorderWidth() * 2 -
+ CalendarTableView.GetTodayButtonHeight());
if (global.params.isFormControlsRefreshEnabled) {
this.element.style.height = height + 'px';
}
@@ -3570,7 +3828,8 @@ CalendarTableView.prototype.setHeight = function(height) {
*/
CalendarTableView.prototype.scrollToMonth = function(month, animate) {
var rowForFirstDayInMonth = this.columnAndRowForDay(month.firstDay()).row;
- this.scrollView.scrollTo(this.scrollOffsetForRow(rowForFirstDayInMonth), animate);
+ this.scrollView.scrollTo(
+ this.scrollOffsetForRow(rowForFirstDayInMonth), animate);
};
/**
@@ -3579,8 +3838,11 @@ CalendarTableView.prototype.scrollToMonth = function(month, animate) {
* @return {!Day}
*/
CalendarTableView.prototype.dayAtColumnAndRow = function(column, row) {
- var daysSinceMinimum = row * DaysPerWeek + column + global.params.weekStartDay - CalendarTableView._MinimumDayWeekDay;
- return Day.createFromValue(daysSinceMinimum * MillisecondsPerDay + CalendarTableView._MinimumDayValue);
+ var daysSinceMinimum = row * DaysPerWeek + column +
+ global.params.weekStartDay - CalendarTableView._MinimumDayWeekDay;
+ return Day.createFromValue(
+ daysSinceMinimum * MillisecondsPerDay +
+ CalendarTableView._MinimumDayValue);
};
CalendarTableView._MinimumDayValue = Day.Minimum.valueOf();
@@ -3591,8 +3853,10 @@ CalendarTableView._MinimumDayWeekDay = Day.Minimum.weekDay();
* @return {!Object} Object with properties column and row.
*/
CalendarTableView.prototype.columnAndRowForDay = function(day) {
- var daysSinceMinimum = (day.valueOf() - CalendarTableView._MinimumDayValue) / MillisecondsPerDay;
- var offset = daysSinceMinimum + CalendarTableView._MinimumDayWeekDay - global.params.weekStartDay;
+ var daysSinceMinimum =
+ (day.valueOf() - CalendarTableView._MinimumDayValue) / MillisecondsPerDay;
+ var offset = daysSinceMinimum + CalendarTableView._MinimumDayWeekDay -
+ global.params.weekStartDay;
var row = Math.floor(offset / DaysPerWeek);
var column = offset - row * DaysPerWeek;
return {column: column, row: row};
@@ -3629,16 +3893,19 @@ CalendarTableView.prototype.updateCells = function() {
var dayCell = this._dayCells[dayString];
var day = dayCell.day;
dayCell.setIsToday(Day.createFromToday().equals(day));
- dayCell.setSelected(day >= firstDayInSelection && day <= lastDayInSelection);
+ dayCell.setSelected(
+ day >= firstDayInSelection && day <= lastDayInSelection);
var isHighlighted = day >= firstDayInHighlight && day <= lastDayInHighlight;
dayCell.setHighlighted(isHighlighted);
if (isHighlighted) {
if (firstDayInHighlight == lastDayInHighlight)
activeCell = dayCell;
- else if (this.calendarPicker.type == 'month' && day == firstDayInHighlight)
+ else if (
+ this.calendarPicker.type == 'month' && day == firstDayInHighlight)
activeCell = dayCell;
}
- dayCell.setIsInCurrentMonth(day >= firstDayInCurrentMonth && day <= lastDayInCurrentMonth);
+ dayCell.setIsInCurrentMonth(
+ day >= firstDayInCurrentMonth && day <= lastDayInCurrentMonth);
dayCell.setDisabled(!this.calendarPicker.isValidDay(day));
}
if (this.hasWeekNumberColumn) {
@@ -3670,7 +3937,8 @@ CalendarTableView.prototype.prepareNewDayCell = function(day) {
var dayCell = DayCell.recycleOrCreate();
dayCell.reset(day);
if (this.calendarPicker.type == 'month')
- dayCell.element.setAttribute('aria-label', Month.createFromDay(day).toLocaleString());
+ dayCell.element.setAttribute(
+ 'aria-label', Month.createFromDay(day).toLocaleString());
this._dayCells[dayCell.day.toString()] = dayCell;
return dayCell;
};
@@ -3751,15 +4019,19 @@ function CalendarPicker(type, config) {
* @const
*/
this.calendarHeaderView = new CalendarHeaderView(this);
- this.calendarHeaderView.monthPopupButton.on(MonthPopupButton.EventTypeButtonClick, this.onMonthPopupButtonClick);
+ this.calendarHeaderView.monthPopupButton.on(
+ MonthPopupButton.EventTypeButtonClick, this.onMonthPopupButtonClick);
/**
* @type {!MonthPopupView}
* @const
*/
- this.monthPopupView = new MonthPopupView(this.minimumMonth, this.maximumMonth);
+ this.monthPopupView =
+ new MonthPopupView(this.minimumMonth, this.maximumMonth);
+ this.monthPopupView.yearListView.on(
+ YearListView.EventTypeYearListViewDidSelectMonth,
+ this.onYearListViewDidSelectMonth);
this.monthPopupView.yearListView.on(
- YearListView.EventTypeYearListViewDidSelectMonth, this.onYearListViewDidSelectMonth);
- this.monthPopupView.yearListView.on(YearListView.EventTypeYearListViewDidHide, this.onYearListViewDidHide);
+ YearListView.EventTypeYearListViewDidHide, this.onYearListViewDidHide);
this.calendarHeaderView.attachTo(this);
this.calendarTableView.attachTo(this);
/**
@@ -3777,7 +4049,8 @@ function CalendarPicker(type, config) {
* @protected
*/
this._highlight = null;
- this.calendarTableView.element.addEventListener('keydown', this.onCalendarTableKeyDown, false);
+ this.calendarTableView.element.addEventListener(
+ 'keydown', this.onCalendarTableKeyDown, false);
document.body.addEventListener('keydown', this.onBodyKeyDown, false);
window.addEventListener('resize', this.onWindowResize, false);
@@ -3790,10 +4063,13 @@ function CalendarPicker(type, config) {
var initialSelection = parseDateString(config.currentValue);
if (initialSelection) {
- this.setCurrentMonth(Month.createFromDay(initialSelection.middleDay()), CalendarPicker.NavigationBehavior.None);
+ this.setCurrentMonth(
+ Month.createFromDay(initialSelection.middleDay()),
+ CalendarPicker.NavigationBehavior.None);
this.setSelection(initialSelection);
} else
- this.setCurrentMonth(Month.createFromToday(), CalendarPicker.NavigationBehavior.None);
+ this.setCurrentMonth(
+ Month.createFromToday(), CalendarPicker.NavigationBehavior.None);
}
CalendarPicker.prototype = Object.create(View.prototype);
@@ -3820,14 +4096,19 @@ CalendarPicker.prototype.onWindowResize = function(event) {
CalendarPicker.prototype.onYearListViewDidHide = function(sender) {
this.monthPopupView.hide();
this.calendarHeaderView.setDisabled(false);
- this.adjustHeight();
+ if (global.params.isFormControlsRefreshEnabled) {
+ this.calendarTableView.element.style.visibility = 'visible';
+ } else {
+ this.adjustHeight();
+ }
};
/**
* @param {!YearListView} sender
* @param {!Month} month
*/
-CalendarPicker.prototype.onYearListViewDidSelectMonth = function(sender, month) {
+CalendarPicker.prototype.onYearListViewDidSelectMonth = function(
+ sender, month) {
this.setCurrentMonth(month, CalendarPicker.NavigationBehavior.None);
};
@@ -3843,7 +4124,8 @@ CalendarPicker.prototype.attachTo = function(parent, before) {
CalendarPicker.prototype.cleanup = function() {
window.removeEventListener('resize', this.onWindowResize, false);
- this.calendarTableView.element.removeEventListener('keydown', this.onBodyKeyDown, false);
+ this.calendarTableView.element.removeEventListener(
+ 'keydown', this.onBodyKeyDown, false);
// Month popup view might be attached to document.body.
this.monthPopupView.hide();
};
@@ -3854,23 +4136,33 @@ CalendarPicker.prototype.cleanup = function() {
CalendarPicker.prototype.onMonthPopupButtonClick = function(sender) {
var clientRect = this.calendarTableView.element.getBoundingClientRect();
var calendarTableRect = new Rectangle(
- clientRect.left + document.body.scrollLeft, clientRect.top + document.body.scrollTop, clientRect.width,
+ clientRect.left + document.body.scrollLeft,
+ clientRect.top + document.body.scrollTop, clientRect.width,
clientRect.height);
this.monthPopupView.show(this.currentMonth(), calendarTableRect);
this.calendarHeaderView.setDisabled(true);
- this.adjustHeight();
+ if (global.params.isFormControlsRefreshEnabled) {
+ this.calendarTableView.element.style.visibility = 'hidden';
+ } else {
+ this.adjustHeight();
+ }
};
CalendarPicker.prototype._setConfig = function(config) {
- this.config.minimum = (typeof config.min !== 'undefined' && config.min) ? parseDateString(config.min) :
- this._dateTypeConstructor.Minimum;
- this.config.maximum = (typeof config.max !== 'undefined' && config.max) ? parseDateString(config.max) :
- this._dateTypeConstructor.Maximum;
+ this.config.minimum = (typeof config.min !== 'undefined' && config.min) ?
+ parseDateString(config.min) :
+ this._dateTypeConstructor.Minimum;
+ this.config.maximum = (typeof config.max !== 'undefined' && config.max) ?
+ parseDateString(config.max) :
+ this._dateTypeConstructor.Maximum;
this.config.minimumValue = this.config.minimum.valueOf();
this.config.maximumValue = this.config.maximum.valueOf();
- this.config.step = (typeof config.step !== undefined) ? Number(config.step) : this._dateTypeConstructor.DefaultStep;
- this.config.stepBase =
- (typeof config.stepBase !== 'undefined') ? Number(config.stepBase) : this._dateTypeConstructor.DefaultStepBase;
+ this.config.step = (typeof config.step !== undefined) ?
+ Number(config.step) :
+ this._dateTypeConstructor.DefaultStep;
+ this.config.stepBase = (typeof config.stepBase !== 'undefined') ?
+ Number(config.stepBase) :
+ this._dateTypeConstructor.DefaultStepBase;
};
/**
@@ -3901,21 +4193,34 @@ CalendarPicker.prototype.setCurrentMonth = function(month, behavior) {
return;
this._currentMonth = month;
this.calendarTableView.scrollToMonth(
- this._currentMonth, behavior === CalendarPicker.NavigationBehavior.WithAnimation);
+ this._currentMonth,
+ behavior === CalendarPicker.NavigationBehavior.WithAnimation);
this.adjustHeight();
this.calendarTableView.setNeedsUpdateCells(true);
- this.dispatchEvent(CalendarPicker.EventTypeCurrentMonthChanged, {target: this});
+ this.dispatchEvent(
+ CalendarPicker.EventTypeCurrentMonthChanged, {target: this});
};
CalendarPicker.prototype.adjustHeight = function() {
- var rowForFirstDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.firstDay()).row;
- var rowForLastDayInMonth = this.calendarTableView.columnAndRowForDay(this._currentMonth.lastDay()).row;
- var numberOfRows = global.params.isFormControlsRefreshEnabled ? CalendarPicker.VisibleRowsRefresh : rowForLastDayInMonth - rowForFirstDayInMonth + 1;
- var calendarTableViewHeight =
- CalendarTableHeaderView.GetHeight() + numberOfRows * DayCell.GetHeight() + CalendarTableView.GetBorderWidth() * 2 + CalendarTableView.GetTodayButtonHeight();
- var height = (this.monthPopupView.isVisible ? YearListView.Height : calendarTableViewHeight) +
- CalendarHeaderView.Height + CalendarHeaderView.BottomMargin + CalendarPicker.Padding * 2 +
- CalendarPicker.BorderWidth * 2;
+ var rowForFirstDayInMonth =
+ this.calendarTableView.columnAndRowForDay(this._currentMonth.firstDay())
+ .row;
+ var rowForLastDayInMonth =
+ this.calendarTableView.columnAndRowForDay(this._currentMonth.lastDay())
+ .row;
+ var numberOfRows = global.params.isFormControlsRefreshEnabled ?
+ CalendarPicker.VisibleRowsRefresh :
+ rowForLastDayInMonth - rowForFirstDayInMonth + 1;
+ 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;
this.setHeight(height);
};
@@ -3931,8 +4236,11 @@ CalendarPicker.prototype.highlight = function() {
* @return {!Day}
*/
CalendarPicker.prototype.firstVisibleDay = function() {
- var firstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
- var firstVisibleDay = this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
+ var firstVisibleRow =
+ this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay())
+ .row;
+ var firstVisibleDay =
+ this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
if (!firstVisibleDay)
firstVisibleDay = Day.Minimum;
return firstVisibleDay;
@@ -3942,11 +4250,17 @@ CalendarPicker.prototype.firstVisibleDay = function() {
* @return {!Day}
*/
CalendarPicker.prototype.lastVisibleDay = function() {
- var lastVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().lastDay()).row;
+ 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.VisibleRowsRefresh - 1;
}
- var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
+ var lastVisibleDay =
+ this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
if (!lastVisibleDay)
lastVisibleDay = Day.Maximum;
return lastVisibleDay;
@@ -3980,23 +4294,40 @@ CalendarPicker.prototype.setSelection = function(dayOrWeekOrMonth) {
var firstDayInSelection = dayOrWeekOrMonth.firstDay();
var lastDayInSelection = dayOrWeekOrMonth.lastDay();
var candidateCurrentMonth = Month.createFromDay(firstDayInSelection);
- if (this.firstVisibleDay() > lastDayInSelection || this.lastVisibleDay() < firstDayInSelection) {
+ if (this.firstVisibleDay() > lastDayInSelection ||
+ this.lastVisibleDay() < firstDayInSelection) {
// Change current month if the selection is not visible at all.
- this.setCurrentMonth(candidateCurrentMonth, CalendarPicker.NavigationBehavior.WithAnimation);
- } else if (this.firstVisibleDay() < firstDayInSelection || this.lastVisibleDay() > lastDayInSelection) {
+ this.setCurrentMonth(
+ candidateCurrentMonth, CalendarPicker.NavigationBehavior.WithAnimation);
+ } else if (
+ this.firstVisibleDay() < firstDayInSelection ||
+ this.lastVisibleDay() > lastDayInSelection) {
// If the selection is partly visible, only change the current month if
// doing so will make the whole selection visible.
- var firstVisibleRow = this.calendarTableView.columnAndRowForDay(candidateCurrentMonth.firstDay()).row;
- var firstVisibleDay = this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
- var lastVisibleRow = this.calendarTableView.columnAndRowForDay(candidateCurrentMonth.lastDay()).row;
- var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(DaysPerWeek - 1, lastVisibleRow);
- if (firstDayInSelection >= firstVisibleDay && lastDayInSelection <= lastVisibleDay)
- this.setCurrentMonth(candidateCurrentMonth, CalendarPicker.NavigationBehavior.WithAnimation);
+ var firstVisibleRow =
+ this.calendarTableView
+ .columnAndRowForDay(candidateCurrentMonth.firstDay())
+ .row;
+ var firstVisibleDay =
+ this.calendarTableView.dayAtColumnAndRow(0, firstVisibleRow);
+ var lastVisibleRow =
+ this.calendarTableView
+ .columnAndRowForDay(candidateCurrentMonth.lastDay())
+ .row;
+ var lastVisibleDay = this.calendarTableView.dayAtColumnAndRow(
+ DaysPerWeek - 1, lastVisibleRow);
+ if (firstDayInSelection >= firstVisibleDay &&
+ lastDayInSelection <= lastVisibleDay)
+ this.setCurrentMonth(
+ candidateCurrentMonth,
+ CalendarPicker.NavigationBehavior.WithAnimation);
}
this._setHighlight(dayOrWeekOrMonth);
if (!this.isValid(dayOrWeekOrMonth))
return;
this._selection = dayOrWeekOrMonth;
+ this.monthPopupView.yearListView.setSelectedMonth(
+ Month.createFromDay(dayOrWeekOrMonth.middleDay()));
this.calendarTableView.setNeedsUpdateCells(true);
};
@@ -4043,7 +4374,9 @@ CalendarPicker.prototype._setHighlight = function(dayOrWeekOrMonth) {
*/
CalendarPicker.prototype._stepMismatch = function(value) {
var nextAllowedValue =
- Math.ceil((value - this.config.stepBase) / this.config.step) * this.config.step + this.config.stepBase;
+ Math.ceil((value - this.config.stepBase) / this.config.step) *
+ this.config.step +
+ this.config.stepBase;
return nextAllowedValue >= value + this._dateTypeConstructor.DefaultStep;
};
@@ -4061,8 +4394,8 @@ CalendarPicker.prototype._outOfRange = function(value) {
*/
CalendarPicker.prototype.isValid = function(dayOrWeekOrMonth) {
var value = dayOrWeekOrMonth.valueOf();
- return dayOrWeekOrMonth instanceof this._dateTypeConstructor && !this._outOfRange(value) &&
- !this._stepMismatch(value);
+ return dayOrWeekOrMonth instanceof this._dateTypeConstructor &&
+ !this._outOfRange(value) && !this._stepMismatch(value);
};
/**
@@ -4082,8 +4415,11 @@ CalendarPicker.prototype._moveHighlight = function(dateRange) {
return false;
if (this._outOfRange(dateRange.valueOf()))
return false;
- if (this.firstVisibleDay() > dateRange.middleDay() || this.lastVisibleDay() < dateRange.middleDay())
- this.setCurrentMonth(Month.createFromDay(dateRange.middleDay()), CalendarPicker.NavigationBehavior.WithAnimation);
+ if (this.firstVisibleDay() > dateRange.middleDay() ||
+ this.lastVisibleDay() < dateRange.middleDay())
+ this.setCurrentMonth(
+ Month.createFromDay(dateRange.middleDay()),
+ CalendarPicker.NavigationBehavior.WithAnimation);
this._setHighlight(dateRange);
return true;
};
@@ -4100,28 +4436,35 @@ CalendarPicker.prototype.onCalendarTableKeyDown = function(event) {
} else if (key == 'PageUp') {
var previousMonth = this.currentMonth().previous();
if (previousMonth && previousMonth >= this.config.minimumValue) {
- this.setCurrentMonth(previousMonth, CalendarPicker.NavigationBehavior.WithAnimation);
+ 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);
+ this.setCurrentMonth(
+ nextMonth, CalendarPicker.NavigationBehavior.WithAnimation);
eventHandled = true;
}
} else if (this._highlight) {
if (global.params.isLocaleRTL ? key == 'ArrowRight' : key == 'ArrowLeft') {
eventHandled = this._moveHighlight(this._highlight.previous());
} else if (key == 'ArrowUp') {
- eventHandled = this._moveHighlight(this._highlight.previous(this.type === 'date' ? DaysPerWeek : 1));
- } else if (global.params.isLocaleRTL ? key == 'ArrowLeft' : key == 'ArrowRight') {
+ eventHandled = this._moveHighlight(
+ this._highlight.previous(this.type === 'date' ? DaysPerWeek : 1));
+ } 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(this.type === 'date' ? DaysPerWeek : 1));
+ eventHandled = this._moveHighlight(
+ this._highlight.next(this.type === 'date' ? DaysPerWeek : 1));
} else if (key == 'Enter') {
this.setSelectionAndCommit(this._highlight);
}
- } else if (key == 'ArrowLeft' || key == 'ArrowUp' || key == 'ArrowRight' || key == 'ArrowDown') {
+ } else if (
+ key == 'ArrowLeft' || key == 'ArrowUp' || key == 'ArrowRight' ||
+ key == 'ArrowDown') {
// Highlight range near the middle.
this.highlightRangeContainingDay(this.currentMonth().middleDay());
eventHandled = true;
@@ -4138,7 +4481,9 @@ CalendarPicker.prototype.onCalendarTableKeyDown = function(event) {
*/
CalendarPicker.prototype.width = function() {
return this.calendarTableView.width() +
- (CalendarTableView.GetBorderWidth() + CalendarPicker.BorderWidth + CalendarPicker.Padding) * 2;
+ (CalendarTableView.GetBorderWidth() + CalendarPicker.BorderWidth +
+ CalendarPicker.Padding) *
+ 2;
};
/**
@@ -4157,7 +4502,8 @@ CalendarPicker.prototype.setHeight = function(height) {
this._height = height;
resizeWindow(this.width(), this._height);
this.calendarTableView.setHeight(
- this._height - CalendarHeaderView.Height - CalendarHeaderView.BottomMargin - CalendarPicker.Padding * 2 -
+ this._height - CalendarHeaderView.Height -
+ CalendarHeaderView.BottomMargin - CalendarPicker.Padding * 2 -
CalendarPicker.BorderWidth * 2);
};
@@ -4182,15 +4528,22 @@ CalendarPicker.prototype.onBodyKeyDown = function(event) {
case 'd':
case 'D':
offset = offset || MonthsPerYear * 10;
- var oldFirstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
+ var oldFirstVisibleRow =
+ this.calendarTableView
+ .columnAndRowForDay(this.currentMonth().firstDay())
+ .row;
this.setCurrentMonth(
- event.shiftKey ? this.currentMonth().previous(offset) : this.currentMonth().next(offset),
+ event.shiftKey ? this.currentMonth().previous(offset) :
+ this.currentMonth().next(offset),
CalendarPicker.NavigationBehavior.WithAnimation);
- var newFirstVisibleRow = this.calendarTableView.columnAndRowForDay(this.currentMonth().firstDay()).row;
+ var newFirstVisibleRow =
+ this.calendarTableView
+ .columnAndRowForDay(this.currentMonth().firstDay())
+ .row;
if (this._highlight) {
var highlightMiddleDay = this._highlight.middleDay();
- this.highlightRangeContainingDay(
- highlightMiddleDay.next((newFirstVisibleRow - oldFirstVisibleRow) * DaysPerWeek));
+ this.highlightRangeContainingDay(highlightMiddleDay.next(
+ (newFirstVisibleRow - oldFirstVisibleRow) * DaysPerWeek));
}
eventHandled = true;
break;
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
index 270321aa5ad..1ba883d0b83 100644
--- 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
@@ -4,7 +4,7 @@
*/
body {
- font: 12px "Segoe UI", system-ui, Roboto, Ubuntu, sans-serif;
+ font: 12px sans-serif;
}
.calendar-picker {
@@ -29,7 +29,7 @@ body {
.calendar-navigation-button {
-webkit-align-self: center;
background-color: #ffffff;
- border: 0;
+ border: 1px solid transparent;
color: #101010;
padding: 0;
text-align: center;
@@ -41,11 +41,15 @@ body {
}
.calendar-navigation-button:hover {
- background-color: #F3F3F3;
+ background-color: #E5E5E5;
}
.calendar-navigation-button:disabled {
- color: #C5C5C5;
+ background-color: #FFFFFF;
+}
+
+.calendar-navigation-button:disabled path {
+ fill: rgba(16, 16, 16, 0.3);
}
.calendar-title {
@@ -55,19 +59,37 @@ body {
}
.month-popup-button {
- border-width: 0px !important;
+ 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: 0;
+ border: 1px solid transparent !important;
border-radius: 2px;
color: #767676;
padding: 1px;
@@ -78,33 +100,43 @@ body {
color: #101010;
}
-.week-number-cell.highlighted,
-.day-cell.highlighted {
- background-color: #F3F3F3;
+.day-cell.highlighted,
+.month-button.highlighted,
+.week-number-cell.highlighted {
+ background-color: #E5E5E5;
}
-.week-number-cell.selected,
-.day-cell.selected {
- background-color: #D9EBF9;
+.day-cell.selected,
+.month-button.selected,
+.week-number-cell.selected {
+ background-color: #CECECE;
font-weight: bold;
}
-.week-number-cell.disabled,
-.day-cell.disabled {
- background-color: #ffffff;
- color: #C5C5C5;
-}
-
.day-cell.highlighted.today,
-.day-cell.today {
- background-color: #0078D4;
+.day-cell.today,
+.month-button.today {
+ background-color: #6E6E6E;
border: 0;
color: #FFFFFF;
font-weight: bold;
}
+.day-cell.selected.today,
+.month-button.selected.today {
+ border: 2px solid #CECECE !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: 0;
+ border: 1px solid transparent;
bottom: 12px;
color: #0078D4;
font-size: 12px;
@@ -115,4 +147,157 @@ body {
width: auto;
}
+.today-button-refresh:hover {
+ background-color: #E5E5E5;
+}
+
+.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;
+}
+
+/* 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 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;
+ }
+
+ .day-cell.highlighted,
+ .month-button.highlighted,
+ .week-number-cell.highlighted {
+ background-color: Window;
+ border-color: Highlight !important;
+ }
+
+ .day-cell.selected,
+ .month-button.selected,
+ .week-number-cell.selected {
+ background-color: Highlight;
+ color: Window;
+ }
+
+ .day-cell.highlighted.today,
+ .day-cell.today,
+ .month-button.today {
+ background-color: Highlight;
+ border: 2px solid Window !important;
+ color: Window;
+ }
+
+ .day-cell.selected.today,
+ .month-button.selected.today {
+ border: 1px solid Window !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;
+ }
+}
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 9a3e42df60f..dfa50b795cb 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
@@ -24,6 +24,11 @@
*/
body {
+ --color-swatch-border-width: 1px;
+ --color-swatch-margin: 1px;
+ --color-swatch-height: 20px;
+ --color-swatch-padding: 0;
+ --color-swatch-width: 20px;
-webkit-user-select: none;
background-color: white;
font: -webkit-small-control;
@@ -31,6 +36,13 @@ 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;
@@ -40,19 +52,30 @@ body {
float: left;
}
+.controls-refresh .color-suggestion-picker-main {
+ border: 0;
+ box-shadow: none;
+ padding: 8px 8px 4px 8px;
+}
+
.color-swatch {
float: left;
- width: 20px;
- height: 20px;
- margin: 1px;
- padding: 0;
- border: 1px solid #e0e0e0;
+ width: var(--color-swatch-width);
+ 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: 1px solid #000000;
+ border: var(--color-swatch-border-width) solid #000000;
outline: none;
}
@@ -65,7 +88,62 @@ body {
align-items: center;
}
+.controls-refresh .color-swatch-container {
+ margin: 4px;
+}
+
+.controls-refresh .color-swatch-container::-webkit-scrollbar {
+ width: var(--scrollbar-width);
+}
+
+.controls-refresh .color-swatch-container::-webkit-scrollbar-thumb {
+ background-color: #cecece;
+ border-radius: 2px;
+ height: 47px;
+ margin: 20px;
+ width: 4px;
+}
+
.other-color {
width: 100%;
margin: 4px 0 0 0;
}
+
+.controls-refresh .other-color {
+ background-color: #ffffff;
+ border-color: transparent;
+ border-radius: 2px;
+ color: #000000;
+ font-family: sans-serif;
+ font-size: 12px;
+ line-height: 16px;
+ margin: 0;
+ text-align: left;
+}
+
+.controls-refresh .other-color:hover {
+ background-color: #f3f3f3;
+}
+
+@media (forced-colors: active) {
+ .controls-refresh .color-suggestion-picker-main {
+ border: 1px solid WindowText;
+ }
+
+ .controls-refresh .color-swatch {
+ forced-color-adjust: none;
+ border-color: WindowText;
+ }
+
+ .controls-refresh .color-swatch:focus {
+ border-color: Highlight;
+ }
+
+ .controls-refresh .color-swatch-container {
+ forced-color-adjust: none;
+ }
+
+ .controls-refresh .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 15c60eb08ec..e5c54cc5ea0 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
@@ -35,7 +35,7 @@ function initializeColorSuggestionPicker() {
*/
function validateColorSuggestionPickerArguments(args) {
if (!args.shouldShowColorSuggestionPicker)
- return 'Should not be showing the color suggestion picker.'
+ return 'Should not be showing the color suggestion picker.';
if (!args.values)
return 'No values.';
if (!args.otherColorLabel)
@@ -63,14 +63,90 @@ function ColorSuggestionPicker(element, config) {
}
ColorSuggestionPicker.prototype = Object.create(Picker.prototype);
-var SwatchBorderBoxWidth = 24; // keep in sync with CSS
-var SwatchBorderBoxHeight = 24; // keep in sync with CSS
-var SwatchesPerRow = 5;
-var SwatchesMaxRow = 4;
+Object.defineProperty(ColorSuggestionPicker, '_ColorSwatchWidth', {
+ get: function() {
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--color-swatch-width')
+ .replace('px', ''));
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, '_ColorSwatchHeight', {
+ get: function() {
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--color-swatch-height')
+ .replace('px', ''));
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, '_ColorSwatchPadding', {
+ get: function() {
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--color-swatch-padding')
+ .replace('px', ''));
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, '_ColorSwatchBorderWidth', {
+ get: function() {
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--color-swatch-border-width')
+ .replace('px', ''));
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, '_ColorSwatchMargin', {
+ get: function() {
+ return Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--color-swatch-margin')
+ .replace('px', ''));
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, 'SwatchBorderBoxWidth', {
+ get: function() {
+ return ColorSuggestionPicker._ColorSwatchWidth +
+ (ColorSuggestionPicker._ColorSwatchPadding * 2) +
+ (ColorSuggestionPicker._ColorSwatchBorderWidth * 2) +
+ (ColorSuggestionPicker._ColorSwatchMargin * 2);
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, 'SwatchBorderBoxHeight', {
+ get: function() {
+ return ColorSuggestionPicker._ColorSwatchHeight +
+ (ColorSuggestionPicker._ColorSwatchPadding * 2) +
+ (ColorSuggestionPicker._ColorSwatchBorderWidth * 2) +
+ (ColorSuggestionPicker._ColorSwatchMargin * 2);
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, 'SwatchesPerRow', {
+ get: function() {
+ return 5;
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, 'SwatchesMaxRow', {
+ get: function() {
+ return global.params.isFormControlsRefreshEnabled ? 3 : 4;
+ }
+});
+
+Object.defineProperty(ColorSuggestionPicker, 'ScrollbarWidth', {
+ get: function() {
+ return !global.params.isFormControlsRefreshEnabled ?
+ getScrollbarWidth() :
+ Number(window.getComputedStyle(document.body)
+ .getPropertyValue('--scrollbar-width')
+ .replace('px', ''));
+ }
+});
ColorSuggestionPicker.prototype._layout = function() {
var container = createElement('div', 'color-swatch-container');
- container.addEventListener('click', this._handleSwatchClick.bind(this), false);
+ container.addEventListener(
+ 'click', this._handleSwatchClick.bind(this), false);
for (var i = 0; i < this._config.values.length; ++i) {
var swatch = createElement('button', 'color-swatch');
swatch.dataset.index = i;
@@ -79,14 +155,20 @@ ColorSuggestionPicker.prototype._layout = function() {
swatch.style.backgroundColor = this._config.values[i];
container.appendChild(swatch);
}
- var containerWidth = SwatchBorderBoxWidth * SwatchesPerRow;
- if (this._config.values.length > SwatchesPerRow * SwatchesMaxRow)
- containerWidth += getScrollbarWidth();
+ var containerWidth = ColorSuggestionPicker.SwatchBorderBoxWidth *
+ ColorSuggestionPicker.SwatchesPerRow;
+ if (this._config.values.length > (ColorSuggestionPicker.SwatchesPerRow *
+ ColorSuggestionPicker.SwatchesMaxRow))
+ containerWidth += ColorSuggestionPicker.ScrollbarWidth;
container.style.width = containerWidth + 'px';
- container.style.maxHeight = (SwatchBorderBoxHeight * SwatchesMaxRow) + 'px';
+ container.style.maxHeight = (ColorSuggestionPicker.SwatchBorderBoxHeight *
+ ColorSuggestionPicker.SwatchesMaxRow) +
+ 'px';
this._element.appendChild(container);
- var otherButton = createElement('button', 'other-color', this._config.otherColorLabel);
- otherButton.addEventListener('click', this._onOtherButtonClick.bind(this), false);
+ var otherButton =
+ createElement('button', 'other-color', this._config.otherColorLabel);
+ otherButton.addEventListener(
+ 'click', this._onOtherButtonClick.bind(this), false);
this._element.appendChild(otherButton);
this._container = container;
this._otherButton = otherButton;
@@ -109,7 +191,7 @@ ColorSuggestionPicker.prototype._onOtherButtonClick = function() {
} else {
this.chooseOtherColor();
}
-}
+};
ColorSuggestionPicker.prototype.selectColorAtIndex = function(index) {
index = Math.max(Math.min(this._container.childNodes.length - 1, index), 0);
@@ -131,7 +213,9 @@ ColorSuggestionPicker.prototype._handleKeyDown = function(event) {
var key = event.key;
if (key === 'Escape')
this.handleCancel();
- else if (key == 'ArrowLeft' || key == 'ArrowUp' || key == 'ArrowRight' || key == 'ArrowDown') {
+ else if (
+ key == 'ArrowLeft' || key == 'ArrowUp' || key == 'ArrowRight' ||
+ key == 'ArrowDown') {
var selectedElement = document.activeElement;
var index = 0;
if (selectedElement.classList.contains('other-color')) {
@@ -148,10 +232,10 @@ ColorSuggestionPicker.prototype._handleKeyDown = function(event) {
index++;
break;
case 'ArrowUp':
- index -= SwatchesPerRow;
+ index -= ColorSuggestionPicker.SwatchesPerRow;
break;
case 'ArrowDown':
- index += SwatchesPerRow;
+ index += ColorSuggestionPicker.SwatchesPerRow;
break;
}
if (index > this._container.childNodes.length - 1) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.css
index a54b79d925c..ed9cc009f44 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.css
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.css
@@ -4,7 +4,12 @@
*/
body {
- font-family: "Segoe UI", system-ui, Roboto, Ubuntu, sans-serif;
+ font-family: sans-serif;
+}
+
+.color-picker-main {
+ border: 0;
+ padding: 0;
}
color-picker {
@@ -17,6 +22,7 @@ color-picker {
visual-color-picker {
height: 59%;
+ min-height: 0;
}
color-well {
@@ -90,6 +96,7 @@ hue-slider > color-selection-ring {
manual-color-picker {
height: 28%;
+ min-height: 0;
}
color-value-container:not(.hidden-color-value-container) {
@@ -136,6 +143,11 @@ format-toggler:hover {
background-color: #F7F7F7;
}
+#up-down-icon {
+ display: flex;
+ align-items: center;
+}
+
format-label:not(.hidden-format-label) {
border-radius: 2px;
display: flex;
@@ -161,6 +173,7 @@ submission-controls {
display: flex;
flex-direction: row;
height: 13%;
+ min-height: 0;
}
#submission-controls-padding {
@@ -177,4 +190,25 @@ submission-button {
submission-button:hover {
background-color: #F3F3F3;
border-radius: 2px;
+}
+
+@media (forced-colors: active) {
+ color-viewer {
+ forced-color-adjust: none;
+ border-color: WindowText;
+ }
+ color-well {
+ border-bottom: 1px solid WindowText;
+ border-radius: 0;
+ }
+ color-selection-ring {
+ forced-color-adjust: none;
+ }
+ color-picker {
+ border: 1px solid WindowText;
+ border-radius: 2px;
+ }
+ format-toggler {
+ border: 1px solid WindowText;
+ }
} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
index 903d43d1d4e..83717cc3748 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/color_picker.js
@@ -23,25 +23,36 @@ function initializeColorPicker() {
*/
function validateColorPickerArguments(args) {
if (args.shouldShowColorSuggestionPicker)
- return 'Should be showing the color suggestion picker.'
+ return 'Should be showing the color suggestion picker.';
if (!args.selectedColor)
return 'No selectedColor.';
return null;
}
/**
+ * Supported movement directions.
+ * @enum {number}
+ */
+const Direction = {
+ UNDEFINED: 0,
+ LEFT: 1,
+ RIGHT: 2,
+ UP: 3,
+ DOWN: 4,
+}
+
+/**
* Supported color channels.
* @enum {number}
*/
const ColorChannel = {
- UNDEFINED: 0,
- HEX: 1,
- R: 2,
- G: 3,
- B: 4,
- H: 5,
- S: 6,
- L: 7,
+ HEX: 0,
+ R: 1,
+ G: 2,
+ B: 3,
+ H: 4,
+ S: 5,
+ L: 6,
};
/**
@@ -49,10 +60,9 @@ const ColorChannel = {
* @enum {number}
*/
const ColorFormat = {
- UNDEFINED: 0,
- HEX: 1,
- RGB: 2,
- HSL: 3,
+ HEX: 0,
+ RGB: 1,
+ HSL: 2,
};
/**
@@ -73,15 +83,17 @@ class Color {
colorStringOrFormat = colorStringOrFormat.replace(/\s+/g, '');
[this.rValue_, this.gValue_, this.bValue_] =
colorStringOrFormat.substring(4, colorStringOrFormat.length - 1)
- .split(',').map(Number);
+ .split(',')
+ .map(Number);
} else if (colorStringOrFormat.startsWith('hsl')) {
colorStringOrFormat = colorStringOrFormat.replace(/%|\s+/g, '');
[this.hValue_, this.sValue_, this.lValue_] =
colorStringOrFormat.substring(4, colorStringOrFormat.length - 1)
- .split(',').map(Number);
+ .split(',')
+ .map(Number);
}
} else {
- switch(colorStringOrFormat) {
+ switch (colorStringOrFormat) {
case ColorFormat.HEX:
this.hexValue_ = colorValues[0].toLowerCase();
break;
@@ -114,11 +126,9 @@ class Color {
if (this.hexValue_ !== undefined) {
// Already computed.
} else if (this.rValue_ !== undefined) {
- this.hexValue_ =
- Color.rgbToHex(this.rValue_, this.gValue_, this.bValue_);
+ this.hexValue_ = Color.rgbToHex(this.rValue_, this.gValue_, this.bValue_);
} else if (this.hValue_ !== undefined) {
- this.hexValue_ =
- Color.hslToHex(this.hValue_, this.sValue_, this.lValue_);
+ this.hexValue_ = Color.hslToHex(this.hValue_, this.sValue_, this.lValue_);
}
}
@@ -221,7 +231,9 @@ class Color {
static hexToRGB(hexValue) {
// Ex. 'ffffff' => '[255,255,255]'
const colorValue = parseInt(hexValue, 16);
- return [(colorValue >> 16) & 255, (colorValue >> 8) & 255, colorValue & 255];
+ return [
+ (colorValue >> 16) & 255, (colorValue >> 8) & 255, colorValue & 255
+ ];
}
/**
@@ -232,7 +244,7 @@ class Color {
// Ex. '[255,255,255]' => 'ffffff'
return rgbValues.reduce((cumulativeHexValue, rgbValue) => {
let hexValue = Number(rgbValue).toString(16);
- if(hexValue.length == 1) {
+ if (hexValue.length == 1) {
hexValue = '0' + hexValue;
}
return (cumulativeHexValue + hexValue);
@@ -347,9 +359,10 @@ class Color {
* Both color triples must be of the same color format.
*/
static distance(colorTripleA, colorTripleB) {
- return Math.sqrt(Math.pow(colorTripleA[0] - colorTripleB[0], 2)
- + Math.pow(colorTripleA[1] - colorTripleB[1], 2)
- + Math.pow(colorTripleA[2] - colorTripleB[2], 2));
+ return Math.sqrt(
+ Math.pow(colorTripleA[0] - colorTripleB[0], 2) +
+ Math.pow(colorTripleA[1] - colorTripleB[1], 2) +
+ Math.pow(colorTripleA[2] - colorTripleB[2], 2));
}
}
@@ -415,15 +428,14 @@ class ColorPicker extends HTMLElement {
this.visualColorPicker_ = new VisualColorPicker(initialColor);
this.manualColorPicker_ = new ManualColorPicker(initialColor);
- this.submissionControls_ =
- new SubmissionControls(this.onSubmitButtonClick_,
- this.onCancelButtonClick_);
- this.append(this.visualColorPicker_,
- this.manualColorPicker_,
- this.submissionControls_);
+ this.submissionControls_ = new SubmissionControls(
+ this.onSubmitButtonClick_, this.onCancelButtonClick_);
+ this.append(
+ this.visualColorPicker_, this.manualColorPicker_,
+ this.submissionControls_);
- this.visualColorPicker_.addEventListener('visual-color-picker-initialized',
- this.initializeListeners_);
+ this.visualColorPicker_.addEventListener(
+ 'visual-color-picker-initialized', this.initializeListeners_);
}
initializeListeners_ = () => {
@@ -431,6 +443,10 @@ class ColorPicker extends HTMLElement {
.addEventListener('manual-color-change', this.onManualColorChange_);
this.addEventListener('visual-color-change', this.onVisualColorChange_);
+
+ this.addEventListener('format-change', this.updateFocusableElements_);
+
+ document.documentElement.addEventListener('keydown', this.onKeyDown_);
}
get selectedColor() {
@@ -484,16 +500,60 @@ class ColorPicker extends HTMLElement {
}
}
+ /**
+ * @param {!Event} event
+ */
+ onKeyDown_ = (event) => {
+ switch(event.key) {
+ case 'Enter':
+ this.submissionControls_.submitButton.click();
+ break;
+ case 'Escape':
+ this.submissionControls_.cancelButton.click();
+ break;
+ case 'Tab':
+ event.preventDefault();
+ if (this.focusableElements_ === undefined) {
+ this.updateFocusableElements_();
+ }
+ const length = this.focusableElements_.length;
+ if (length > 0) {
+ const currentFocusIndex =
+ this.focusableElements_.indexOf(document.activeElement);
+ let nextFocusIndex;
+ if (event.shiftKey) {
+ nextFocusIndex = (currentFocusIndex > 0) ?
+ currentFocusIndex - 1 :
+ length - 1;
+ } else {
+ nextFocusIndex = (currentFocusIndex + 1) % length;
+ }
+ this.focusableElements_[nextFocusIndex].focus({preventScroll: true});
+ }
+ break;
+ }
+ }
+
+ updateFocusableElements_ = () => {
+ this.focusableElements_ = Array.from(this.querySelectorAll(
+ 'color-value-container:not(.hidden-color-value-container) > input,' +
+ '[tabindex]:not([tabindex=\'-1\'])'));
+ }
+
+ static get COMMIT_DELAY_MS() {
+ return 100;
+ }
+
onSubmitButtonClick_ = () => {
const selectedValue = this.selectedColor_.asHex();
window.setTimeout(function() {
window.pagePopupController.setValueAndClosePopup(0, selectedValue);
- }, 100);
- }
+ }, ColorPicker.COMMIT_DELAY_MS);
+ };
onCancelButtonClick_ = () => {
window.pagePopupController.closePopup();
- }
+ };
}
window.customElements.define('color-picker', ColorPicker);
@@ -513,9 +573,8 @@ class VisualColorPicker extends HTMLElement {
this.eyeDropper_ = new EyeDropper();
this.colorViewer_ = new ColorViewer(initialColor);
this.hueSlider_ = new HueSlider(initialColor);
- visualColorPickerStrip.append(this.eyeDropper_,
- this.colorViewer_,
- this.hueSlider_);
+ visualColorPickerStrip.append(
+ this.eyeDropper_, this.colorViewer_, this.hueSlider_);
this.append(visualColorPickerStrip);
this.colorWell_ = new ColorWell(initialColor);
@@ -538,13 +597,12 @@ class VisualColorPicker extends HTMLElement {
.addEventListener('mousedown', this.onColorWellMouseDown_);
this.hueSlider_
.addEventListener('mousedown', this.onHueSliderMouseDown_);
- this.colorWell_
- .addEventListener('mousedown', (event) => event.preventDefault());
- this.hueSlider_
- .addEventListener('mousedown', (event) => event.preventDefault());
+ document.documentElement
+ .addEventListener('mousedown', this.onMouseDown_);
document.documentElement
.addEventListener('mousemove', this.onMouseMove_);
document.documentElement.addEventListener('mouseup', this.onMouseUp_);
+ document.documentElement.addEventListener('keydown', this.onKeyDown_);
this.dispatchEvent(new CustomEvent('visual-color-picker-initialized'));
}
@@ -565,12 +623,30 @@ class VisualColorPicker extends HTMLElement {
* @param {!Event} event
*/
onColorWellMouseDown_ = (event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.hueSlider_.focused = false;
this.colorWell_.mouseDown(new Point(event.clientX, event.clientY));
}
/**
* @param {!Event} event
*/
+ onHueSliderMouseDown_ = (event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.colorWell_.focused = false;
+ this.hueSlider_.mouseDown(new Point(event.clientX, event.clientY));
+ }
+
+ onMouseDown_ = () => {
+ this.colorWell_.focused = false;
+ this.hueSlider_.focused = false;
+ }
+
+ /**
+ * @param {!Event} event
+ */
onMouseMove_ = (event) => {
var point = new Point(event.clientX, event.clientY);
this.colorWell_.mouseMove(point);
@@ -585,8 +661,27 @@ class VisualColorPicker extends HTMLElement {
/**
* @param {!Event} event
*/
- onHueSliderMouseDown_ = (event) => {
- this.hueSlider_.mouseDown(new Point(event.clientX, event.clientY));
+ onKeyDown_ = (event) => {
+ let moveDirection = Direction.UNDEFINED;
+ switch(event.key) {
+ case 'ArrowUp':
+ moveDirection = Direction.UP;
+ break;
+ case 'ArrowDown':
+ moveDirection = Direction.DOWN;
+ break;
+ case 'ArrowLeft':
+ moveDirection = Direction.LEFT;
+ break;
+ case 'ArrowRight':
+ moveDirection = Direction.RIGHT;
+ break;
+ }
+ if (moveDirection !== Direction.UNDEFINED) {
+ const acceleratedMove = event.ctrlKey;
+ this.hueSlider_.move(moveDirection, acceleratedMove);
+ this.colorWell_.move(moveDirection, acceleratedMove);
+ }
}
/**
@@ -605,7 +700,7 @@ window.customElements.define('visual-color-picker', VisualColorPicker);
* implementation.)
* TODO(http://crbug.com/992297): Implement eye dropper
*/
-class EyeDropper extends HTMLElement { }
+class EyeDropper extends HTMLElement {}
window.customElements.define('eye-dropper', EyeDropper);
/**
@@ -650,8 +745,10 @@ class ColorSelectionArea extends HTMLElement {
this.append(this.colorPalette_, this.colorSelectionRing_);
this.initialized_ = false;
- this.colorSelectionRing_.addEventListener('focus', this.onColorSelectionRingFocus_);
- this.colorSelectionRing_.addEventListener('blur', this.onColorSelectionRingBlur_);
+ this.colorSelectionRing_.addEventListener(
+ 'focus', this.onColorSelectionRingFocus_);
+ this.colorSelectionRing_.addEventListener(
+ 'blur', this.onColorSelectionRingBlur_);
}
get initialized() {
@@ -660,16 +757,17 @@ class ColorSelectionArea extends HTMLElement {
onColorSelectionRingFocus_ = () => {
this.focused_ = true;
- }
+ };
onColorSelectionRingBlur_ = () => {
this.focused_ = false;
- }
+ };
/**
* @param {!Point} point
*/
mouseDown(point) {
+ this.colorSelectionRing_.focus({preventScroll: true});
this.colorSelectionRing_.drag = true;
this.moveColorSelectionRingTo_(point);
}
@@ -686,6 +784,27 @@ class ColorSelectionArea extends HTMLElement {
mouseUp() {
this.colorSelectionRing_.drag = false;
}
+
+ /**
+ * @param {!Direction} direction
+ * @param {bool} accelerated
+ */
+ move(direction, accelerated) {
+ if (this.focused) {
+ this.colorSelectionRing_.move(direction, accelerated);
+ }
+ }
+
+ get focused() {
+ return this.focused_;
+ }
+
+ /**
+ * @param {bool} focused
+ */
+ set focused(focused) {
+ this.focused_ = focused;
+ }
}
window.customElements.define('color-selection-area', ColorSelectionArea);
@@ -712,14 +831,15 @@ class ColorPalette extends HTMLCanvasElement {
get hslImageData() {
if (this.pendingColorChange_) {
- const rgbaImageData = this.renderingContext
- .getImageData(0, 0, this.width, this.height).data;
- this.hslImageData_ = rgbaImageData
- .reduce((hslArray, {}, currentIndex, rgbaArray) => {
+ const rgbaImageData =
+ this.renderingContext.getImageData(0, 0, this.width, this.height)
+ .data;
+ this.hslImageData_ =
+ rgbaImageData.reduce((hslArray, {}, currentIndex, rgbaArray) => {
if ((currentIndex % 4) === 0) {
- hslArray.push(...Color.rgbToHSL(rgbaArray[currentIndex],
- rgbaArray[currentIndex + 1],
- rgbaArray[currentIndex + 2]));
+ hslArray.push(...Color.rgbToHSL(
+ rgbaArray[currentIndex], rgbaArray[currentIndex + 1],
+ rgbaArray[currentIndex + 2]));
}
return hslArray;
}, []);
@@ -744,8 +864,9 @@ class ColorPalette extends HTMLCanvasElement {
colorAtPoint(point) {
const hslImageDataAtPoint =
this.hslImageDataAtPoint_(point.x - this.left, point.y - this.top);
- return new Color(ColorFormat.HSL, hslImageDataAtPoint[0],
- hslImageDataAtPoint[1], hslImageDataAtPoint[2]);
+ return new Color(
+ ColorFormat.HSL, hslImageDataAtPoint[0], hslImageDataAtPoint[1],
+ hslImageDataAtPoint[2]);
}
/**
@@ -753,7 +874,17 @@ class ColorPalette extends HTMLCanvasElement {
* @param {number} y
*/
hslImageDataAtPoint_(x, y) {
- const offset = Math.round(y * this.width + x) * 3;
+ let offset = Math.round(y * this.width + x) * 3;
+ // It is possible that the computed offset is larger than the hslImageData
+ // array's length. This can happen at certain zoom levels (ex. 150%), where
+ // the height of the color well is not a round number. The getImageData API
+ // only works with integer values and will truncate decimal values. As
+ // such, if the color well's selection ring is placed at the bottom of the
+ // color well at such a zoom level, a valid data point for the ring's
+ // position will not be found in the hslImageData array. When this happens,
+ // we just report the color at the end of the hslImageData array. This will
+ // be the same color that is seen at the bottom of the color well (black).
+ offset = Math.min(offset, this.hslImageData.length - 3);
return this.hslImageData.slice(offset, offset + 3);
}
@@ -778,8 +909,9 @@ class ColorPalette extends HTMLCanvasElement {
* @param {!Color} color
*/
fillHue(color) {
- this.fillColor_ = new Color(ColorFormat.HSL, color.hValue,
- this.fillColor_.sValue, this.fillColor_.lValue);
+ this.fillColor_ = new Color(
+ ColorFormat.HSL, color.hValue, this.fillColor_.sValue,
+ this.fillColor_.lValue);
this.fillColorAndGradients_();
this.pendingHueChange_ = true;
}
@@ -803,15 +935,15 @@ class ColorPalette extends HTMLCanvasElement {
*/
nearestPointOnColorPalette(point) {
if (!this.isXCoordinateOnColorPalette_(point)) {
- if (point.x >= this.right) {
- point.x = this.right - 1;
+ if (point.x > this.right) {
+ point.x = this.right;
} else if (point.x < this.left) {
point.x = this.left;
}
}
if (!this.isYCoordinateOnColorPalette_(point)) {
- if (point.y >= this.bottom) {
- point.y = this.bottom - 1;
+ if (point.y > this.bottom) {
+ point.y = this.bottom;
} else if (point.y < this.top) {
point.y = this.top;
}
@@ -823,35 +955,34 @@ class ColorPalette extends HTMLCanvasElement {
* @param {!Point} point
*/
isXCoordinateOnColorPalette_(point) {
- return (point.x >= this.left) && (point.x < this.right);
+ return (point.x >= this.left) && (point.x <= this.right);
}
/**
* @param {!Point} point
*/
isYCoordinateOnColorPalette_(point) {
- return (point.y >= this.top) && (point.y < this.bottom);
+ return (point.y >= this.top) && (point.y <= this.bottom);
}
get left() {
- return this.getBoundingClientRect().left;
+ return Math.ceil(this.getBoundingClientRect().left);
}
get right() {
- return this.getBoundingClientRect().right;
+ return Math.ceil(this.getBoundingClientRect().right - 1);
}
get top() {
- return this.getBoundingClientRect().top;
+ return Math.ceil(this.getBoundingClientRect().top);
}
get bottom() {
- return this.getBoundingClientRect().bottom;
+ return Math.ceil(this.getBoundingClientRect().bottom - 1);
}
}
-window.customElements.define('color-palette',
- ColorPalette,
- { extends: 'canvas' });
+window.customElements.define(
+ 'color-palette', ColorPalette, {extends: 'canvas'});
/**
* ColorSelectionRing: Provides movement and color selection functionality to
@@ -870,6 +1001,14 @@ class ColorSelectionRing extends HTMLElement {
this.drag_ = false;
}
+ static get ACCELERATED_MOVE_DISTANCE() {
+ return 20;
+ }
+
+ static get MOVE_DISTANCE() {
+ return 1;
+ }
+
initialize() {
this.set(this.backingColorPalette_.left, this.backingColorPalette_.top);
}
@@ -904,6 +1043,16 @@ class ColorSelectionRing extends HTMLElement {
}
/**
+ * @param {number} x
+ */
+ setY(y) {
+ if (y !== this.position_.y) {
+ this.position_.y = y;
+ this.onPositionChange_();
+ }
+ }
+
+ /**
* @param {number} shiftFactor
*/
shiftX(shiftFactor) {
@@ -917,20 +1066,20 @@ class ColorSelectionRing extends HTMLElement {
setElementPosition_() {
if (this.height > this.backingColorPalette_.height) {
- this.style.top = this.top
- - (this.height - this.backingColorPalette_.height) / 2
- - this.backingColorPalette_.top + 'px';
+ this.style.top = this.top -
+ (this.height - this.backingColorPalette_.height) / 2 -
+ this.backingColorPalette_.top + 'px';
} else {
- this.style.top = this.top - this.radius
- - this.backingColorPalette_.top + 'px';
+ this.style.top =
+ this.top - this.radius - this.backingColorPalette_.top + 'px';
}
if (this.width > this.backingColorPalette_.width) {
- this.style.left = this.left
- - (this.width - this.backingColorPalette_.width) / 2
- - this.backingColorPalette_.left + 'px';
+ this.style.left = this.left -
+ (this.width - this.backingColorPalette_.width) / 2 -
+ this.backingColorPalette_.left + 'px';
} else {
- this.style.left = this.left - this.radius
- - this.backingColorPalette_.left + 'px';
+ this.style.left =
+ this.left - this.radius - this.backingColorPalette_.left + 'px';
}
}
@@ -953,6 +1102,57 @@ class ColorSelectionRing extends HTMLElement {
}
}
+ get canMoveHorizontally_() {
+ return this.width < this.backingColorPalette_.width;
+ }
+
+ get canMoveVertically_() {
+ return this.height < this.backingColorPalette_.height;
+ }
+
+ /**
+ * @param {!Direction} direction
+ * @param {bool} accelerated
+ */
+ move(direction, accelerated) {
+ let shiftFactor = accelerated ?
+ ColorSelectionRing.ACCELERATED_MOVE_DISTANCE :
+ ColorSelectionRing.MOVE_DISTANCE;
+ if ((direction === Direction.UP) || (direction === Direction.LEFT)) {
+ shiftFactor *= -1;
+ }
+ if (this.canMoveHorizontally_ &&
+ ((direction === Direction.LEFT) || (direction === Direction.RIGHT))) {
+ let newX = this.position_.x + shiftFactor;
+ if (direction === Direction.LEFT) {
+ if (this.position_.x + shiftFactor < this.backingColorPalette_.left) {
+ newX = this.backingColorPalette_.left;
+ }
+ } else {
+ // direction === Direction.RIGHT
+ if (this.position_.x + shiftFactor > this.backingColorPalette_.right) {
+ newX = this.backingColorPalette_.right;
+ }
+ }
+ this.setX(newX);
+ } else if (
+ this.canMoveVertically_ &&
+ ((direction === Direction.UP) || (direction === Direction.DOWN))) {
+ let newY = this.position_.y + shiftFactor;
+ if (direction === Direction.UP) {
+ if (this.position_.y + shiftFactor < this.backingColorPalette_.top) {
+ newY = this.backingColorPalette_.top;
+ }
+ } else {
+ // direction === Direction.DOWN
+ if (this.position_.y + shiftFactor > this.backingColorPalette_.bottom) {
+ newY = this.backingColorPalette_.bottom;
+ }
+ }
+ this.setY(newY);
+ }
+ }
+
get drag() {
return this.drag_;
}
@@ -969,11 +1169,11 @@ class ColorSelectionRing extends HTMLElement {
}
get width() {
- return this.getBoundingClientRect().width;
+ return Math.floor(this.getBoundingClientRect().width);
}
get height() {
- return this.getBoundingClientRect().height;
+ return Math.floor(this.getBoundingClientRect().height);
}
get left() {
@@ -1001,20 +1201,22 @@ class ColorWell extends ColorSelectionArea {
this.selectedColor_ = initialColor;
this.resizeObserver_ = new ResizeObserver(() => {
- let whiteGradient = this.colorPalette_.renderingContext
- .createLinearGradient(0, 0, this.colorPalette_.offsetWidth, 0);
+ let whiteGradient =
+ this.colorPalette_.renderingContext.createLinearGradient(
+ 0, 0, this.colorPalette_.offsetWidth, 0);
whiteGradient.addColorStop(0.01, 'hsla(0, 0%, 100%, 1)');
whiteGradient.addColorStop(0.99, 'hsla(0, 0%, 100%, 0)');
- let blackGradient = this.colorPalette_.renderingContext
- .createLinearGradient(0, this.colorPalette_.offsetHeight, 0, 0);
+ let blackGradient =
+ this.colorPalette_.renderingContext.createLinearGradient(
+ 0, this.colorPalette_.offsetHeight, 0, 0);
blackGradient.addColorStop(0.01, 'hsla(0, 0%, 0%, 1)');
blackGradient.addColorStop(0.99, 'hsla(0, 0%, 0%, 0)');
this.colorPalette_.initialize(whiteGradient, blackGradient);
this.colorPalette_.fillHue(this.fillColor_);
this.colorSelectionRing_.initialize();
- this.colorSelectionRing_.addEventListener('color-selection-ring-update',
- this.onColorSelectionRingUpdate_);
+ this.colorSelectionRing_.addEventListener(
+ 'color-selection-ring-update', this.onColorSelectionRingUpdate_);
this.moveColorSelectionRingTo_(this.selectedColor_);
@@ -1036,26 +1238,30 @@ class ColorWell extends ColorSelectionArea {
this.colorPalette_.nearestPointOnColorPalette(newPositionOrColor);
this.colorSelectionRing_.moveTo(point);
} else {
- const closestHSLValueIndex = this.colorPalette_.hslImageData
- .reduce((closestSoFar, {}, index, array) => {
+ const closestHSLValueIndex = this.colorPalette_.hslImageData.reduce(
+ (closestSoFar, {}, index, array) => {
if ((index % 3) === 0) {
- const currentHSLValueDistance = Color.distance([array[index],
- array[index + 1], array[index + 2]],
- newPositionOrColor.hslValues());
- const closestHSLValueDistance =
- Color.distance([array[closestSoFar], array[closestSoFar + 1],
- array[closestSoFar + 2]], newPositionOrColor.hslValues());
+ const currentHSLValueDistance = Color.distance(
+ [array[index], array[index + 1], array[index + 2]],
+ newPositionOrColor.hslValues());
+ const closestHSLValueDistance = Color.distance(
+ [
+ array[closestSoFar], array[closestSoFar + 1],
+ array[closestSoFar + 2]
+ ],
+ newPositionOrColor.hslValues());
if (currentHSLValueDistance < closestHSLValueDistance) {
return index;
}
}
return closestSoFar;
- }, 0);
+ },
+ 0);
const offsetX = (closestHSLValueIndex / 3) % this.colorPalette_.width;
const offsetY =
Math.floor((closestHSLValueIndex / 3) / this.colorPalette_.width);
- this.colorSelectionRing_.set(this.colorPalette_.left + offsetX,
- this.colorPalette_.top + offsetY);
+ this.colorSelectionRing_.set(
+ this.colorPalette_.left + offsetX, this.colorPalette_.top + offsetY);
}
}
@@ -1090,12 +1296,9 @@ class ColorWell extends ColorSelectionArea {
onColorSelectionRingUpdate_ = () => {
this.selectedColor_ = this.colorSelectionRing_.color;
- this.dispatchEvent(new CustomEvent('visual-color-change', {
- bubbles: true,
- detail: {
- color: this.selectedColor
- }
- }));
+ this.dispatchEvent(new CustomEvent(
+ 'visual-color-change',
+ {bubbles: true, detail: {color: this.selectedColor}}));
}
}
window.customElements.define('color-well', ColorWell);
@@ -1113,8 +1316,9 @@ class HueSlider extends ColorSelectionArea {
this.color_ = new Color(ColorFormat.HSL, initialColor.hValue, 100, 50);
this.resizeObserver_ = new ResizeObserver(() => {
- let hueSliderPaletteGradient = this.colorPalette_.renderingContext
- .createLinearGradient(0, 0, this.colorPalette_.offsetWidth, 0);
+ let hueSliderPaletteGradient =
+ this.colorPalette_.renderingContext.createLinearGradient(
+ 0, 0, this.colorPalette_.offsetWidth, 0);
hueSliderPaletteGradient.addColorStop(0.01, 'hsl(0, 100%, 50%)');
hueSliderPaletteGradient.addColorStop(0.17, 'hsl(300, 100%, 50%)');
hueSliderPaletteGradient.addColorStop(0.33, 'hsl(240, 100%, 50%)');
@@ -1125,8 +1329,8 @@ class HueSlider extends ColorSelectionArea {
this.colorPalette_.initialize(hueSliderPaletteGradient);
this.colorSelectionRing_.initialize();
- this.colorSelectionRing_.addEventListener('color-selection-ring-update',
- this.onColorSelectionRingUpdate_);
+ this.colorSelectionRing_.addEventListener(
+ 'color-selection-ring-update', this.onColorSelectionRingUpdate_);
this.moveColorSelectionRingTo_(this.color_);
@@ -1150,15 +1354,16 @@ class HueSlider extends ColorSelectionArea {
} else {
const targetHValue = newPositionOrColor.hValue;
if (targetHValue !== this.colorSelectionRing_.color.hValue) {
- const closestHValueIndex = this.colorPalette_.hslImageData
- .reduce((closestHValueIndexSoFar, currentHValue, index, array) => {
+ const closestHValueIndex = this.colorPalette_.hslImageData.reduce(
+ (closestHValueIndexSoFar, currentHValue, index, array) => {
if ((index % 3 === 0) &&
(Math.abs(currentHValue - targetHValue) <
- Math.abs(array[closestHValueIndexSoFar] - targetHValue))) {
+ Math.abs(array[closestHValueIndexSoFar] - targetHValue))) {
return index;
}
return closestHValueIndexSoFar;
- }, 0);
+ },
+ 0);
const offsetX = (closestHValueIndex / 3) % this.colorPalette_.width;
this.colorSelectionRing_.setX(this.colorPalette_.left + offsetX);
}
@@ -1181,9 +1386,7 @@ class HueSlider extends ColorSelectionArea {
onColorSelectionRingUpdate_ = () => {
this.color_ = this.colorSelectionRing_.color;
- this.dispatchEvent(new CustomEvent('hue-slider-update', {
- bubbles: true
- }));
+ this.dispatchEvent(new CustomEvent('hue-slider-update', {bubbles: true}));
}
}
window.customElements.define('hue-slider', HueSlider);
@@ -1199,12 +1402,12 @@ class ManualColorPicker extends HTMLElement {
constructor(initialColor) {
super();
- this.hexValueContainer_ = new ColorValueContainer(ColorChannel.HEX,
- initialColor);
- this.rgbValueContainer_ = new ColorValueContainer(ColorFormat.RGB,
- initialColor);
- this.hslValueContainer_ = new ColorValueContainer(ColorFormat.HSL,
- initialColor);
+ this.hexValueContainer_ =
+ new ColorValueContainer(ColorChannel.HEX, initialColor);
+ this.rgbValueContainer_ =
+ new ColorValueContainer(ColorFormat.RGB, initialColor);
+ this.hslValueContainer_ =
+ new ColorValueContainer(ColorFormat.HSL, initialColor);
this.colorValueContainers_ = [
this.hexValueContainer_,
this.rgbValueContainer_,
@@ -1215,8 +1418,7 @@ class ManualColorPicker extends HTMLElement {
this.formatToggler_ = new FormatToggler(this.currentColorFormat_);
this.append(...this.colorValueContainers_, this.formatToggler_);
- this.formatToggler_
- .addEventListener('format-change', this.onFormatChange_);
+ this.formatToggler_.addEventListener('format-change', this.onFormatChange_);
this.addEventListener('manual-color-change', this.onManualColorChange_);
}
@@ -1250,8 +1452,8 @@ class ManualColorPicker extends HTMLElement {
* @param {!Color} newColor
*/
set color(newColor) {
- this.colorValueContainers_.forEach((colorValueContainer) =>
- colorValueContainer.color = newColor);
+ this.colorValueContainers_.forEach(
+ (colorValueContainer) => colorValueContainer.color = newColor);
}
}
window.customElements.define('manual-color-picker', ManualColorPicker);
@@ -1271,35 +1473,33 @@ class ColorValueContainer extends HTMLElement {
this.colorFormat_ = colorFormat;
this.channelValueContainers_ = [];
if (this.colorFormat_ === ColorFormat.HEX) {
- const hexValueContainer = new ChannelValueContainer(ColorChannel.HEX,
- initialColor);
+ const hexValueContainer =
+ new ChannelValueContainer(ColorChannel.HEX, initialColor);
this.channelValueContainers_.push(hexValueContainer);
} else if (this.colorFormat_ === ColorFormat.RGB) {
- const rValueContainer = new ChannelValueContainer(ColorChannel.R,
- initialColor);
- const gValueContainer = new ChannelValueContainer(ColorChannel.G,
- initialColor);
- const bValueContainer = new ChannelValueContainer(ColorChannel.B,
- initialColor);
- this.channelValueContainers_.push(rValueContainer,
- gValueContainer,
- bValueContainer);
+ const rValueContainer =
+ new ChannelValueContainer(ColorChannel.R, initialColor);
+ const gValueContainer =
+ new ChannelValueContainer(ColorChannel.G, initialColor);
+ const bValueContainer =
+ new ChannelValueContainer(ColorChannel.B, initialColor);
+ this.channelValueContainers_.push(
+ rValueContainer, gValueContainer, bValueContainer);
} else if (this.colorFormat_ === ColorFormat.HSL) {
- const hValueContainer = new ChannelValueContainer(ColorChannel.H,
- initialColor);
- const sValueContainer = new ChannelValueContainer(ColorChannel.S,
- initialColor);
- const lValueContainer = new ChannelValueContainer(ColorChannel.L,
- initialColor);
- this.channelValueContainers_.push(hValueContainer,
- sValueContainer,
- lValueContainer);
+ const hValueContainer =
+ new ChannelValueContainer(ColorChannel.H, initialColor);
+ const sValueContainer =
+ new ChannelValueContainer(ColorChannel.S, initialColor);
+ const lValueContainer =
+ new ChannelValueContainer(ColorChannel.L, initialColor);
+ this.channelValueContainers_.push(
+ hValueContainer, sValueContainer, lValueContainer);
}
this.append(...this.channelValueContainers_);
- this.channelValueContainers_.forEach((channelValueContainer) =>
- channelValueContainer.addEventListener('input',
- this.onChannelValueChange_));
+ this.channelValueContainers_.forEach(
+ (channelValueContainer) => channelValueContainer.addEventListener(
+ 'input', this.onChannelValueChange_));
}
get colorFormat() {
@@ -1307,17 +1507,18 @@ class ColorValueContainer extends HTMLElement {
}
get color() {
- return new Color(this.colorFormat_,
- ...this.channelValueContainers_.map((channelValueContainer) =>
- channelValueContainer.channelValue));
+ return new Color(
+ this.colorFormat_,
+ ...this.channelValueContainers_.map(
+ (channelValueContainer) => channelValueContainer.channelValue));
}
/**
* @param {!Color} color
*/
set color(color) {
- this.channelValueContainers_.forEach((channelValueContainer) =>
- channelValueContainer.setValue(color));
+ this.channelValueContainers_.forEach(
+ (channelValueContainer) => channelValueContainer.setValue(color));
}
show() {
@@ -1329,12 +1530,8 @@ class ColorValueContainer extends HTMLElement {
}
onChannelValueChange_ = () => {
- this.dispatchEvent(new CustomEvent('manual-color-change', {
- bubbles: true,
- detail: {
- color: this.color
- }
- }));
+ this.dispatchEvent(new CustomEvent(
+ 'manual-color-change', {bubbles: true, detail: {color: this.color}}));
}
}
window.customElements.define('color-value-container', ColorValueContainer);
@@ -1353,7 +1550,7 @@ class ChannelValueContainer extends HTMLInputElement {
this.setAttribute('type', 'text');
this.colorChannel_ = colorChannel;
- switch(colorChannel) {
+ switch (colorChannel) {
case ColorChannel.HEX:
this.setAttribute('id', 'hexValueContainer');
this.setAttribute('maxlength', '7');
@@ -1398,7 +1595,7 @@ class ChannelValueContainer extends HTMLInputElement {
* @param {!Color} color
*/
setValue(color) {
- switch(this.colorChannel_) {
+ switch (this.colorChannel_) {
case ColorChannel.HEX:
if (this.channelValue_ !== color.hexValue) {
this.channelValue_ = color.hexValue;
@@ -1448,7 +1645,7 @@ class ChannelValueContainer extends HTMLInputElement {
// Set this.channelValue_ based on the element's new value.
let value = this.value;
if (value) {
- switch(this.colorChannel_) {
+ switch (this.colorChannel_) {
case ColorChannel.HEX:
if (value.startsWith('#')) {
value = value.substr(1).toLowerCase();
@@ -1484,9 +1681,8 @@ class ChannelValueContainer extends HTMLInputElement {
}
}
}
-window.customElements.define('channel-value-container',
- ChannelValueContainer,
- { extends: 'input' });
+window.customElements.define(
+ 'channel-value-container', ChannelValueContainer, {extends: 'input'});
/**
* FormatToggler: Button that powers switching between different color formats.
@@ -1511,20 +1707,43 @@ class FormatToggler extends HTMLElement {
this.adjustFormatLabelVisibility_();
this.upDownIcon_ = document.createElement('span');
+ this.upDownIcon_.setAttribute('id', 'up-down-icon');
this.upDownIcon_.innerHTML =
'<svg width="6" height="8" viewBox="0 0 6 8" fill="none" ' +
'xmlns="http://www.w3.org/2000/svg"><path d="M1.18359 ' +
'3.18359L0.617188 2.61719L3 0.234375L5.38281 2.61719L4.81641 ' +
'3.18359L3 1.36719L1.18359 3.18359ZM4.81641 4.81641L5.38281 ' +
'5.38281L3 7.76562L0.617188 5.38281L1.18359 4.81641L3 ' +
- '6.63281L4.81641 4.81641Z" fill="black"/></svg>';
+ '6.63281L4.81641 4.81641Z" fill="WindowText"/></svg>';
this.append(...this.colorFormatLabels_, this.upDownIcon_);
this.addEventListener('click', this.onClick_);
+ this.addEventListener('keydown', this.onKeyDown_);
this.addEventListener('mousedown', (event) => event.preventDefault());
}
+ /**
+ * @param {bool} choosePreviousFormat if true, choose previous format
+ * instead of next
+ */
+ updateColorFormat_(choosePreviousFormat) {
+ const numFormats = Object.keys(ColorFormat).length;
+ const newValue = choosePreviousFormat ? this.currentColorFormat_ - 1 :
+ this.currentColorFormat_ + 1;
+ const newColorFormatKey = Object.keys(ColorFormat).filter((key) => {
+ return ColorFormat[key] ===
+ (((newValue % numFormats) + numFormats) % numFormats);
+ });
+ this.currentColorFormat_ = ColorFormat[newColorFormatKey];
+
+ this.adjustFormatLabelVisibility_();
+
+ this.dispatchEvent(new CustomEvent(
+ 'format-change',
+ {bubbles: true, detail: {colorFormat: this.currentColorFormat_}}));
+ }
+
adjustFormatLabelVisibility_() {
this.colorFormatLabels_.forEach((colorFormatLabel) => {
if (colorFormatLabel.colorFormat === this.currentColorFormat_) {
@@ -1536,20 +1755,23 @@ class FormatToggler extends HTMLElement {
}
onClick_ = () => {
- if (this.currentColorFormat_ == ColorFormat.HEX) {
- this.currentColorFormat_ = ColorFormat.RGB;
- } else if (this.currentColorFormat_ == ColorFormat.RGB) {
- this.currentColorFormat_ = ColorFormat.HSL;
- } else if (this.currentColorFormat_ == ColorFormat.HSL) {
- this.currentColorFormat_ = ColorFormat.HEX;
- }
- this.adjustFormatLabelVisibility_();
+ this.focus();
+ this.updateColorFormat_(false);
+ };
- this.dispatchEvent(new CustomEvent('format-change', {
- detail: {
- colorFormat: this.currentColorFormat_
- }
- }));
+ /**
+ * @param {!Event} event
+ */
+ onKeyDown_ = (event) => {
+ switch (event.key) {
+ case 'ArrowUp':
+ this.updateColorFormat_(true);
+ break;
+ case 'ArrowDown':
+ case ' ':
+ this.updateColorFormat_(false);
+ break;
+ }
}
}
window.customElements.define('format-toggler', FormatToggler);
@@ -1572,16 +1794,14 @@ class FormatLabel extends HTMLElement {
this.rChannelLabel_ = new ChannelLabel(ColorChannel.R);
this.gChannelLabel_ = new ChannelLabel(ColorChannel.G);
this.bChannelLabel_ = new ChannelLabel(ColorChannel.B);
- this.append(this.rChannelLabel_,
- this.gChannelLabel_,
- this.bChannelLabel_);
+ this.append(
+ this.rChannelLabel_, this.gChannelLabel_, this.bChannelLabel_);
} else if (colorFormat === ColorFormat.HSL) {
this.hChannelLabel_ = new ChannelLabel(ColorChannel.H);
this.sChannelLabel_ = new ChannelLabel(ColorChannel.S);
this.lChannelLabel_ = new ChannelLabel(ColorChannel.L);
- this.append(this.hChannelLabel_,
- this.sChannelLabel_,
- this.lChannelLabel_);
+ this.append(
+ this.hChannelLabel_, this.sChannelLabel_, this.lChannelLabel_);
}
}
@@ -1643,22 +1863,30 @@ class SubmissionControls extends HTMLElement {
padding.setAttribute('id', 'submission-controls-padding');
this.append(padding);
- this.submitButton_ = new SubmissionButton(submitCallback,
+ this.submitButton_ = new SubmissionButton(
+ submitCallback,
'<svg width="14" height="10" viewBox="0 0 14 10" fill="none" ' +
- 'xmlns="http://www.w3.org/2000/svg"><path d="M13.3516 ' +
- '1.35156L5 9.71094L0.648438 5.35156L1.35156 4.64844L5 ' +
- '8.28906L12.6484 0.648438L13.3516 1.35156Z" fill="black"/></svg>'
- );
- this.cancelButton_ = new SubmissionButton(cancelCallback,
+ 'xmlns="http://www.w3.org/2000/svg"><path d="M13.3516 ' +
+ '1.35156L5 9.71094L0.648438 5.35156L1.35156 4.64844L5 ' +
+ '8.28906L12.6484 0.648438L13.3516 1.35156Z" fill="WindowText"/></svg>');
+ this.cancelButton_ = new SubmissionButton(
+ cancelCallback,
'<svg width="14" height="14" viewBox="0 0 14 14" fill="none" ' +
- 'xmlns="http://www.w3.org/2000/svg"><path d="M7.71094 7L13.1016 ' +
- '12.3984L12.3984 13.1016L7 7.71094L1.60156 13.1016L0.898438 ' +
- '12.3984L6.28906 7L0.898438 1.60156L1.60156 0.898438L7 ' +
- '6.28906L12.3984 0.898438L13.1016 1.60156L7.71094 7Z" ' +
- 'fill="black"/></svg>'
- );
+ 'xmlns="http://www.w3.org/2000/svg"><path d="M7.71094 7L13.1016 ' +
+ '12.3984L12.3984 13.1016L7 7.71094L1.60156 13.1016L0.898438 ' +
+ '12.3984L6.28906 7L0.898438 1.60156L1.60156 0.898438L7 ' +
+ '6.28906L12.3984 0.898438L13.1016 1.60156L7.71094 7Z" ' +
+ 'fill="WindowText"/></svg>');
this.append(this.submitButton_, this.cancelButton_);
}
+
+ get submitButton() {
+ return this.submitButton_;
+ }
+
+ get cancelButton() {
+ return this.cancelButton_;
+ }
}
window.customElements.define('submission-controls', SubmissionControls);
@@ -1680,4 +1908,4 @@ class SubmissionButton extends HTMLElement {
this.addEventListener('click', clickCallback);
}
}
-window.customElements.define('submission-button', SubmissionButton); \ No newline at end of file
+window.customElements.define('submission-button', SubmissionButton);
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 ba1120a22f5..bdd671d2cf0 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
@@ -39,6 +39,9 @@ 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');
errorString = validateColorSuggestionPickerArguments(args);
} else {
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 59af8767d28..8294f0b6d7e 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
@@ -44,16 +44,24 @@ function ListPicker(element, config) {
this._delayedChildrenConfig = null;
this._delayedChildrenConfigIndex = 0;
this._layout();
- this._selectElement.addEventListener('mouseup', this._handleMouseUp.bind(this), false);
- this._selectElement.addEventListener('touchstart', this._handleTouchStart.bind(this), false);
- this._selectElement.addEventListener('keydown', this._handleKeyDown.bind(this), false);
- this._selectElement.addEventListener('change', this._handleChange.bind(this), false);
- window.addEventListener('message', this._handleWindowMessage.bind(this), false);
- window.addEventListener('mousemove', this._handleWindowMouseMove.bind(this), false);
- window.addEventListener('mouseover', this._handleWindowMouseOver.bind(this), false);
+ this._selectElement.addEventListener(
+ 'mouseup', this._handleMouseUp.bind(this), false);
+ this._selectElement.addEventListener(
+ 'touchstart', this._handleTouchStart.bind(this), false);
+ this._selectElement.addEventListener(
+ 'keydown', this._handleKeyDown.bind(this), false);
+ this._selectElement.addEventListener(
+ 'change', this._handleChange.bind(this), false);
+ window.addEventListener(
+ 'message', this._handleWindowMessage.bind(this), false);
+ window.addEventListener(
+ 'mousemove', this._handleWindowMouseMove.bind(this), false);
+ window.addEventListener(
+ 'mouseover', this._handleWindowMouseOver.bind(this), false);
this._handleWindowTouchMoveBound = this._handleWindowTouchMove.bind(this);
this._handleWindowTouchEndBound = this._handleWindowTouchEnd.bind(this);
- this._handleTouchSelectModeScrollBound = this._handleTouchSelectModeScroll.bind(this);
+ this._handleTouchSelectModeScrollBound =
+ this._handleTouchSelectModeScroll.bind(this);
this.lastMousePositionX = Infinity;
this.lastMousePositionY = Infinity;
this._selectionSetByMouseHover = false;
@@ -68,7 +76,8 @@ ListPicker.prototype = Object.create(Picker.prototype);
ListPicker.prototype._handleWindowDidHide = function() {
this._fixWindowSize();
- var selectedOption = this._selectElement.options[this._selectElement.selectedIndex];
+ var selectedOption =
+ this._selectElement.options[this._selectElement.selectedIndex];
if (selectedOption)
selectedOption.scrollIntoView(false);
window.removeEventListener('didHide', this._handleWindowDidHideBound, false);
@@ -80,10 +89,14 @@ ListPicker.prototype._handleWindowMessage = function(event) {
this._config.baseStyle = window.updateData.baseStyle;
this._config.children = window.updateData.children;
this._update();
- if (this._config.anchorRectInScreen.x !== window.updateData.anchorRectInScreen.x ||
- this._config.anchorRectInScreen.y !== window.updateData.anchorRectInScreen.y ||
- this._config.anchorRectInScreen.width !== window.updateData.anchorRectInScreen.width ||
- this._config.anchorRectInScreen.height !== window.updateData.anchorRectInScreen.height) {
+ if (this._config.anchorRectInScreen.x !==
+ window.updateData.anchorRectInScreen.x ||
+ this._config.anchorRectInScreen.y !==
+ window.updateData.anchorRectInScreen.y ||
+ this._config.anchorRectInScreen.width !==
+ window.updateData.anchorRectInScreen.width ||
+ this._config.anchorRectInScreen.height !==
+ window.updateData.anchorRectInScreen.height) {
// TODO(tkent): Don't fix window size here due to a bug of Aura or
// compositor. crbug.com/863770
if (!navigator.platform.startsWith('Win')) {
@@ -101,7 +114,8 @@ ListPicker.ListboxSelectBorder = 1;
ListPicker.prototype._handleWindowMouseMove = function(event) {
var visibleTop = ListPicker.ListboxSelectBorder;
- var visibleBottom = this._selectElement.offsetHeight - ListPicker.ListboxSelectBorder;
+ var visibleBottom =
+ this._selectElement.offsetHeight - ListPicker.ListboxSelectBorder;
var optionBounds = event.target.getBoundingClientRect();
if (optionBounds.height >= 1.0) {
// If the height of the visible part of event.target is less than 1px,
@@ -128,7 +142,8 @@ ListPicker.prototype._handleWindowMouseOver = function(event) {
ListPicker.prototype._handleMouseUp = function(event) {
if (event.target.tagName !== 'OPTION')
return;
- window.pagePopupController.setValueAndClosePopup(0, this._selectElement.value);
+ window.pagePopupController.setValueAndClosePopup(
+ 0, this._selectElement.value);
};
ListPicker.prototype._handleTouchStart = function(event) {
@@ -140,7 +155,8 @@ ListPicker.prototype._handleTouchStart = function(event) {
this._trackingTouchId = touch.identifier;
this._highlightOption(touch.target);
this._selectionSetByMouseHover = false;
- this._selectElement.addEventListener('scroll', this._handleTouchSelectModeScrollBound, false);
+ this._selectElement.addEventListener(
+ 'scroll', this._handleTouchSelectModeScrollBound, false);
window.addEventListener('touchmove', this._handleWindowTouchMoveBound, false);
window.addEventListener('touchend', this._handleWindowTouchEndBound, false);
};
@@ -151,9 +167,12 @@ ListPicker.prototype._handleTouchSelectModeScroll = function(event) {
ListPicker.prototype._exitTouchSelectMode = function(event) {
this._trackingTouchId = null;
- this._selectElement.removeEventListener('scroll', this._handleTouchSelectModeScrollBound, false);
- window.removeEventListener('touchmove', this._handleWindowTouchMoveBound, false);
- window.removeEventListener('touchend', this._handleWindowTouchEndBound, false);
+ this._selectElement.removeEventListener(
+ 'scroll', this._handleTouchSelectModeScrollBound, false);
+ window.removeEventListener(
+ 'touchmove', this._handleWindowTouchMoveBound, false);
+ window.removeEventListener(
+ 'touchend', this._handleWindowTouchEndBound, false);
};
ListPicker.prototype._handleWindowTouchMove = function(event) {
@@ -162,7 +181,8 @@ ListPicker.prototype._handleWindowTouchMove = function(event) {
var touch = this._getTouchForId(event.touches, this._trackingTouchId);
if (!touch)
return;
- this._highlightOption(document.elementFromPoint(touch.clientX, touch.clientY));
+ this._highlightOption(
+ document.elementFromPoint(touch.clientX, touch.clientY));
this._selectionSetByMouseHover = false;
};
@@ -174,7 +194,8 @@ ListPicker.prototype._handleWindowTouchEnd = function(event) {
return;
var target = document.elementFromPoint(touch.clientX, touch.clientY);
if (target.tagName === 'OPTION' && !target.disabled)
- window.pagePopupController.setValueAndClosePopup(0, this._selectElement.value);
+ window.pagePopupController.setValueAndClosePopup(
+ 0, this._selectElement.value);
this._exitTouchSelectMode();
};
@@ -207,7 +228,8 @@ ListPicker.prototype._handleKeyDown = function(event) {
window.pagePopupController.closePopup();
event.preventDefault();
} else if (key === 'Tab' || key === 'Enter') {
- window.pagePopupController.setValueAndClosePopup(0, this._selectElement.value);
+ window.pagePopupController.setValueAndClosePopup(
+ 0, this._selectElement.value);
event.preventDefault();
} else if (event.altKey && (key === 'ArrowDown' || key === 'ArrowUp')) {
// We need to add a delay here because, if we do it immediately the key
@@ -224,7 +246,8 @@ ListPicker.prototype._fixWindowSize = function() {
this._selectElement.style.height = '';
var scale = this._config.scaleFactor;
var maxHeight = this._selectElement.offsetHeight;
- var noScrollHeight = (this._calculateScrollHeight() + ListPicker.ListboxSelectBorder * 2);
+ var noScrollHeight =
+ (this._calculateScrollHeight() + ListPicker.ListboxSelectBorder * 2);
var scrollbarWidth = getScrollbarWidth();
var elementOffsetWidth = this._selectElement.offsetWidth;
var desiredWindowHeight = noScrollHeight;
@@ -241,13 +264,17 @@ ListPicker.prototype._fixWindowSize = function() {
expectingScrollbar = true;
}
// Screen coordinate for anchorRectInScreen and windowRect is DIP.
- desiredWindowWidth = Math.max(this._config.anchorRectInScreen.width * scale, desiredWindowWidth);
- var windowRect =
- adjustWindowRect(desiredWindowWidth / scale, desiredWindowHeight / scale, elementOffsetWidth / scale, 0);
+ desiredWindowWidth = Math.max(
+ this._config.anchorRectInScreen.width * scale, desiredWindowWidth);
+ var windowRect = adjustWindowRect(
+ desiredWindowWidth / scale, desiredWindowHeight / scale,
+ elementOffsetWidth / scale, 0);
// If the available screen space is smaller than maxHeight, we will get an unexpected scrollbar.
if (!expectingScrollbar && windowRect.height < noScrollHeight / scale) {
desiredWindowWidth = windowRect.width * scale + scrollbarWidth;
- windowRect = adjustWindowRect(desiredWindowWidth / scale, windowRect.height, windowRect.width, windowRect.height);
+ windowRect = adjustWindowRect(
+ desiredWindowWidth / scale, windowRect.height, windowRect.width,
+ windowRect.height);
}
this._selectElement.style.width = (windowRect.width * scale) + 'px';
this._selectElement.style.height = (windowRect.height * scale) + 'px';
@@ -279,11 +306,14 @@ ListPicker.prototype._listItemCount = function() {
ListPicker.prototype._layout = function() {
if (this._config.isRTL)
this._element.classList.add('rtl');
- this._selectElement.style.backgroundColor = this._config.baseStyle.backgroundColor;
+ this._selectElement.style.backgroundColor =
+ this._config.baseStyle.backgroundColor;
this._selectElement.style.color = this._config.baseStyle.color;
- this._selectElement.style.textTransform = this._config.baseStyle.textTransform;
+ this._selectElement.style.textTransform =
+ this._config.baseStyle.textTransform;
this._selectElement.style.fontSize = this._config.baseStyle.fontSize + 'px';
- this._selectElement.style.fontFamily = this._config.baseStyle.fontFamily.map(s => '"' + s + '"').join(',');
+ this._selectElement.style.fontFamily =
+ this._config.baseStyle.fontFamily.map(s => '"' + s + '"').join(',');
this._selectElement.style.fontStyle = this._config.baseStyle.fontStyle;
this._selectElement.style.fontVariant = this._config.baseStyle.fontVariant;
this._updateChildren(this._selectElement, this._config);
@@ -297,7 +327,8 @@ ListPicker.prototype._update = function() {
this._selectElement.scrollTop = scrollPosition;
var optionUnderMouse = null;
if (this._selectionSetByMouseHover) {
- var elementUnderMouse = document.elementFromPoint(this.lastMousePositionX, this.lastMousePositionY);
+ var elementUnderMouse = document.elementFromPoint(
+ this.lastMousePositionX, this.lastMousePositionY);
optionUnderMouse = elementUnderMouse && elementUnderMouse.closest('option');
}
if (optionUnderMouse)
@@ -319,13 +350,15 @@ ListPicker.prototype._updateChildren = function(parent, config) {
var fragment = null;
var inGroup = parent.tagName === 'OPTGROUP';
var lastListIndex = -1;
- var limit = Math.max(this._config.selectedIndex, ListPicker.DelayedLayoutThreshold);
+ var limit =
+ Math.max(this._config.selectedIndex, ListPicker.DelayedLayoutThreshold);
var i;
for (i = 0; i < config.children.length; ++i) {
if (!inGroup && lastListIndex >= limit)
break;
var childConfig = config.children[i];
- var item = this._findReusableItem(parent, childConfig, outOfDateIndex) || this._createItemElement(childConfig);
+ var item = this._findReusableItem(parent, childConfig, outOfDateIndex) ||
+ this._createItemElement(childConfig);
this._configureItem(item, childConfig, inGroup);
lastListIndex = item.value ? Number(item.value) : -1;
if (outOfDateIndex < parent.children.length) {
@@ -361,8 +394,10 @@ ListPicker.prototype._updateChildrenLater = function(timeStamp) {
return;
var fragment = document.createDocumentFragment();
var startIndex = this._delayedChildrenConfigIndex;
- for (; this._delayedChildrenConfigIndex < this._delayedChildrenConfig.length; ++this._delayedChildrenConfigIndex) {
- var childConfig = this._delayedChildrenConfig[this._delayedChildrenConfigIndex];
+ for (; this._delayedChildrenConfigIndex < this._delayedChildrenConfig.length;
+ ++this._delayedChildrenConfigIndex) {
+ var childConfig =
+ this._delayedChildrenConfig[this._delayedChildrenConfigIndex];
var item = this._createItemElement(childConfig);
this._configureItem(item, childConfig, false);
fragment.appendChild(item);
@@ -409,13 +444,17 @@ ListPicker.prototype._applyItemStyle = function(element, styleConfig) {
style.direction = styleConfig.direction ? styleConfig.direction : '';
style.unicodeBidi = styleConfig.unicodeBidi ? styleConfig.unicodeBidi : '';
style.color = styleConfig.color ? styleConfig.color : '';
- style.backgroundColor = styleConfig.backgroundColor ? styleConfig.backgroundColor : '';
+ style.backgroundColor =
+ styleConfig.backgroundColor ? styleConfig.backgroundColor : '';
style.fontSize = styleConfig.fontSize ? styleConfig.fontSize + 'px' : '';
style.fontWeight = styleConfig.fontWeight ? styleConfig.fontWeight : '';
- style.fontFamily = styleConfig.fontFamily ? styleConfig.fontFamily.map(s => '"' + s + '"').join(',') : '';
+ style.fontFamily = styleConfig.fontFamily ?
+ styleConfig.fontFamily.map(s => '"' + s + '"').join(',') :
+ '';
style.fontStyle = styleConfig.fontStyle ? styleConfig.fontStyle : '';
style.fontVariant = styleConfig.fontVariant ? styleConfig.fontVariant : '';
- style.textTransform = styleConfig.textTransform ? styleConfig.textTransform : '';
+ style.textTransform =
+ styleConfig.textTransform ? styleConfig.textTransform : '';
};
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
new file mode 100644
index 00000000000..47cf5ee0c4a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/month_picker.js
@@ -0,0 +1,135 @@
+'use strict';
+// 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.
+
+/**
+ * @fileoverview Picker used by <input type='month' />
+ */
+
+function initializeMonthPicker(config) {
+ global.picker = new MonthPicker(config);
+ main.append(global.picker);
+ main.style.border = '1px solid transparent';
+ main.style.height = (MonthPicker.Height - 2) + 'px';
+ main.style.width = (MonthPicker.Width - 2) + 'px';
+ resizeWindow(MonthPicker.Width, MonthPicker.Height);
+}
+
+/**
+ * MonthPicker: Custom element providing a month picker implementation.
+ * MonthPicker contains 2 parts:
+ * - year list view
+ * - today button
+ */
+class MonthPicker extends HTMLElement {
+ constructor(config) {
+ super();
+
+ this.initializeFromConfig_(config);
+
+ this.yearListView_ =
+ new YearListView(this.minimumMonth_, this.maximumMonth_);
+ this.append(this.yearListView_.element);
+ this.initializeYearListView_();
+
+ this.todayButton_ = new CalendarNavigationButton();
+ this.append(this.todayButton_.element);
+ this.initializeTodayButton_();
+
+ window.addEventListener('resize', this.onWindowResize_);
+ }
+
+ initializeFromConfig_ = (config) => {
+ const minimum = (typeof config.min !== 'undefined' && config.min) ?
+ parseDateString(config.min) :
+ Month.Minimum;
+ const maximum = (typeof config.max !== 'undefined' && config.max) ?
+ parseDateString(config.max) :
+ Month.Maximum;
+ this.minimumMonth_ = Month.createFromDay(minimum.firstDay());
+ this.maximumMonth_ = Month.createFromDay(maximum.lastDay());
+
+ const initialSelection = parseDateString(config.currentValue);
+ const initialSelectedMonth = initialSelection ?
+ Month.createFromDay(initialSelection.middleDay()) :
+ Month.createFromToday();
+ this.initialValidSelection_ = false;
+ if (initialSelectedMonth < this.minimumMonth_) {
+ this.selectedMonth_ = this.minimumMonth_;
+ } else if (initialSelectedMonth > this.maximumMonth_) {
+ this.selectedMonth_ = this.maximumMonth_;
+ } else {
+ this.selectedMonth_ = initialSelectedMonth;
+ this.initialValidSelection_ = initialSelection != null;
+ }
+ };
+
+ initializeYearListView_ = () => {
+ this.yearListView_.setWidth(MonthPicker.YearWidth);
+ this.yearListView_.setHeight(MonthPicker.YearHeight);
+ if (global.params.isLocaleRTL) {
+ this.yearListView_.element.style.right = MonthPicker.YearPadding + 'px';
+ this.yearListView_.scrubbyScrollBar.element.style.right =
+ MonthPicker.YearWidth + 'px';
+ } else {
+ this.yearListView_.element.style.left = MonthPicker.YearPadding + 'px';
+ this.yearListView_.scrubbyScrollBar.element.style.left =
+ MonthPicker.YearWidth + 'px';
+ }
+ this.yearListView_.element.style.top = MonthPicker.YearPadding + 'px';
+ if (this.initialValidSelection_) {
+ this.yearListView_.setSelectedMonth(this.selectedMonth_);
+ }
+ this.yearListView_.show(this.selectedMonth_);
+ this.yearListView_.on(
+ YearListView.EventTypeYearListViewDidSelectMonth,
+ this.onYearListViewDidSelectMonth_);
+ this.yearListView_.on(
+ YearListView.EventTypeYearListViewDidHide, this.onYearListViewDidHide_);
+ };
+
+ onYearListViewDidHide_ = (sender) => {
+ const selectedValue = this.selectedMonth_.toString();
+ window.setTimeout(function() {
+ window.pagePopupController.setValueAndClosePopup(0, selectedValue);
+ }, 100);
+ };
+
+ onYearListViewDidSelectMonth_ = (sender, month) => {
+ this.selectedMonth_ = month;
+ };
+
+ initializeTodayButton_ = () => {
+ this.todayButton_.element.textContent = global.params.todayLabel;
+ this.todayButton_.element.setAttribute(
+ 'aria-label', global.params.todayLabel);
+ this.todayButton_.element.classList.add(MonthPicker.ClassNameTodayButton);
+ const monthContainingToday = Month.createFromToday();
+ this.todayButton_.setDisabled(
+ monthContainingToday < this.minimumMonth_ ||
+ monthContainingToday > this.maximumMonth_);
+ this.todayButton_.on(
+ CalendarNavigationButton.EventTypeButtonClick,
+ this.onTodayButtonClick_);
+ };
+
+ onTodayButtonClick_ = (sender) => {
+ const selectedValue = Month.createFromToday().toString();
+ window.setTimeout(function() {
+ window.pagePopupController.setValueAndClosePopup(0, selectedValue);
+ }, 100);
+ };
+
+ onWindowResize_ = (event) => {
+ window.removeEventListener('resize', this.onWindowResize_);
+ this.yearListView_.element.focus();
+ };
+}
+MonthPicker.Width = 232;
+MonthPicker.YearWidth = 194;
+MonthPicker.YearHeight = 128;
+MonthPicker.YearPadding = 12;
+MonthPicker.Height = 182;
+MonthPicker.ClassNameTodayButton = 'today-button-refresh';
+window.customElements.define('month-picker', MonthPicker);
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 b5071055647..ae3504dd303 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
@@ -74,7 +74,8 @@ Rectangle.prototype = {
return this.y + this.height;
},
toString: function() {
- return 'Rectangle(' + this.x + ',' + this.y + ',' + this.width + ',' + this.height + ')';
+ return 'Rectangle(' + this.x + ',' + this.y + ',' + this.width + ',' +
+ this.height + ')';
}
};
@@ -101,7 +102,8 @@ Rectangle.intersection = function(rect1, rect2) {
*/
function resizeWindow(width, height) {
var zoom = global.params.zoomFactor ? global.params.zoomFactor : 1;
- setWindowRect(adjustWindowRect(width * zoom, height * zoom, width * zoom, height * zoom));
+ setWindowRect(adjustWindowRect(
+ width * zoom, height * zoom, width * zoom, height * zoom));
}
/**
@@ -124,7 +126,8 @@ function adjustWindowRect(width, height, minWidth, minHeight) {
var anchorRect = new Rectangle(global.params.anchorRectInScreen);
var availRect = new Rectangle(
- window.screen.availLeft, window.screen.availTop, window.screen.availWidth, window.screen.availHeight);
+ window.screen.availLeft, window.screen.availTop, window.screen.availWidth,
+ window.screen.availHeight);
_adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight);
_adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth);
@@ -135,12 +138,15 @@ function adjustWindowRect(width, height, minWidth, minHeight) {
/**
* Arguments are DIPs.
*/
-function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeight) {
+function _adjustWindowRectVertically(
+ windowRect, availRect, anchorRect, minHeight) {
var availableSpaceAbove = anchorRect.y - availRect.y;
- availableSpaceAbove = Math.max(0, Math.min(availRect.height, availableSpaceAbove));
+ availableSpaceAbove =
+ Math.max(0, Math.min(availRect.height, availableSpaceAbove));
var availableSpaceBelow = availRect.maxY - anchorRect.maxY;
- availableSpaceBelow = Math.max(0, Math.min(availRect.height, availableSpaceBelow));
+ 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
@@ -148,7 +154,9 @@ function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeigh
if (availableSpaceAbove == 0 && availableSpaceBelow == 0) {
windowRect.height = Math.max(minHeight, windowRect.height);
windowRect.y = anchorRect.maxY;
- } else if (windowRect.height > availableSpaceBelow && availableSpaceBelow < availableSpaceAbove) {
+ } else if (
+ windowRect.height > availableSpaceBelow &&
+ availableSpaceBelow < availableSpaceAbove) {
windowRect.height = Math.min(windowRect.height, availableSpaceAbove);
windowRect.height = Math.max(windowRect.height, minHeight);
windowRect.y = anchorRect.y - windowRect.height;
@@ -162,7 +170,8 @@ function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeigh
/**
* Arguments are DIPs.
*/
-function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth) {
+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
@@ -174,7 +183,8 @@ function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWid
// If we are getting clipped, we want to switch alignment to the right side
// of the anchor rect as long as doing so will make the popup not clipped.
var rightAlignedX = windowRect.x + anchorRect.width - windowRect.width;
- if (rightAlignedX >= availRect.x && (windowRect.maxX > availRect.maxX || global.params.isRTL))
+ if (rightAlignedX >= availRect.x &&
+ (windowRect.maxX > availRect.maxX || global.params.isRTL))
windowRect.x = rightAlignedX;
}
@@ -186,7 +196,8 @@ function setWindowRect(rect) {
window.frameElement.style.width = rect.width + 'px';
window.frameElement.style.height = rect.height + 'px';
} else {
- window.pagePopupController.setWindowRect(rect.x, rect.y, rect.width, rect.height);
+ window.pagePopupController.setWindowRect(
+ rect.x, rect.y, rect.width, rect.height);
}
}
@@ -233,8 +244,10 @@ function getScrollbarWidth() {
* @return {?Element}
*/
function enclosingNodeOrSelfWithClass(selfNode, className) {
- for (var node = selfNode; node && node !== selfNode.ownerDocument; node = node.parentNode) {
- if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains(className))
+ for (var node = selfNode; node && node !== selfNode.ownerDocument;
+ node = node.parentNode) {
+ if (node.nodeType === Node.ELEMENT_NODE &&
+ node.classList.contains(className))
return node;
}
return null;
@@ -243,7 +256,8 @@ function enclosingNodeOrSelfWithClass(selfNode, className) {
/**
* @constructor
*/
-function EventEmitter(){};
+function EventEmitter() {
+}
/**
* @param {!string} type
@@ -333,7 +347,8 @@ Picker.prototype.handleCancel = function() {
};
Picker.prototype.chooseOtherColor = function() {
- window.pagePopupController.setValueAndClosePopup(Picker.Actions.ChooseOtherColor, '');
+ window.pagePopupController.setValueAndClosePopup(
+ Picker.Actions.ChooseOtherColor, '');
};
Picker.prototype.cleanup = function() {};
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 0281d0df5bf..860e2a397f0 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
@@ -54,3 +54,39 @@
border-top: 1px solid #dcdcdc;
height: 0;
}
+
+.controls-refresh .suggestion-list {
+ border-color: transparent;
+ 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;
+}
+
+.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) {
+ .suggestion-list-entry:focus {
+ background-color: Highlight !important;
+ color: Window !important;
+ forced-color-adjust: none;
+ }
+
+ .suggestion-list-entry:focus .label {
+ color: Window !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 e56b93ea0e7..e42d5424a39 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
@@ -38,7 +38,8 @@ function SuggestionPicker(element, config) {
this._fixWindowSize();
this._handleBodyKeyDownBound = this._handleBodyKeyDown.bind(this);
document.body.addEventListener('keydown', this._handleBodyKeyDownBound);
- this._element.addEventListener('mouseout', this._handleMouseOut.bind(this), false);
+ this._element.addEventListener(
+ 'mouseout', this._handleMouseOut.bind(this), false);
}
SuggestionPicker.prototype = Object.create(Picker.prototype);
@@ -58,9 +59,11 @@ SuggestionPicker.validateConfig = function(config) {
return 'No otherDateLabel.';
if (config.suggestionHighlightColor && !config.suggestionHighlightColor)
return 'No suggestionHighlightColor.';
- if (config.suggestionHighlightTextColor && !config.suggestionHighlightTextColor)
+ if (config.suggestionHighlightTextColor &&
+ !config.suggestionHighlightTextColor)
return 'No suggestionHighlightTextColor.';
- if (config.suggestionValues.length !== config.localizedSuggestionValues.length)
+ if (config.suggestionValues.length !==
+ config.localizedSuggestionValues.length)
return 'localizedSuggestionValues.length must equal suggestionValues.length.';
if (config.suggestionValues.length !== config.suggestionLabels.length)
return 'suggestionLabels.length must equal suggestionValues.length.';
@@ -69,6 +72,15 @@ SuggestionPicker.validateConfig = function(config) {
return null;
};
+Object.defineProperty(SuggestionPicker, 'Padding', {
+ get: function() {
+ return Number(
+ window.getComputedStyle(document.querySelector('.suggestion-list'))
+ .getPropertyValue('padding')
+ .replace('px', ''));
+ }
+});
+
SuggestionPicker.prototype._setColors = function() {
var text = '.' + SuggestionPicker.ListEntryClass + ':focus {\
background-color: ' +
@@ -76,12 +88,14 @@ SuggestionPicker.prototype._setColors = function() {
color: ' +
this._config.suggestionHighlightTextColor + '; }';
text += '.' + SuggestionPicker.ListEntryClass +
- ':focus .label { color: ' + this._config.suggestionHighlightTextColor + '; }';
+ ':focus .label { color: ' + this._config.suggestionHighlightTextColor +
+ '; }';
document.head.appendChild(createElement('style', null, text));
};
SuggestionPicker.prototype.cleanup = function() {
- document.body.removeEventListener('keydown', this._handleBodyKeyDownBound, false);
+ document.body.removeEventListener(
+ 'keydown', this._handleBodyKeyDownBound, false);
};
/**
@@ -90,7 +104,8 @@ SuggestionPicker.prototype.cleanup = function() {
* @param {!string} value
* @return {!Element}
*/
-SuggestionPicker.prototype._createSuggestionEntryElement = function(title, label, value) {
+SuggestionPicker.prototype._createSuggestionEntryElement = function(
+ title, label, value) {
var entryElement = createElement('li', SuggestionPicker.ListEntryClass);
entryElement.tabIndex = 0;
entryElement.dataset.value = value;
@@ -102,7 +117,8 @@ SuggestionPicker.prototype._createSuggestionEntryElement = function(title, label
var labelElement = createElement('span', 'label', label);
content.appendChild(labelElement);
}
- entryElement.addEventListener('mouseover', this._handleEntryMouseOver.bind(this), false);
+ entryElement.addEventListener(
+ 'mouseover', this._handleEntryMouseOver.bind(this), false);
return entryElement;
};
@@ -111,7 +127,8 @@ SuggestionPicker.prototype._createSuggestionEntryElement = function(title, label
* @param {!string} actionName
* @return {!Element}
*/
-SuggestionPicker.prototype._createActionEntryElement = function(title, actionName) {
+SuggestionPicker.prototype._createActionEntryElement = function(
+ title, actionName) {
var entryElement = createElement('li', SuggestionPicker.ListEntryClass);
entryElement.tabIndex = 0;
entryElement.dataset.action = actionName;
@@ -119,7 +136,8 @@ SuggestionPicker.prototype._createActionEntryElement = function(title, actionNam
entryElement.appendChild(content);
var titleElement = createElement('span', 'title', title);
content.appendChild(titleElement);
- entryElement.addEventListener('mouseover', this._handleEntryMouseOver.bind(this), false);
+ entryElement.addEventListener(
+ 'mouseover', this._handleEntryMouseOver.bind(this), false);
return entryElement;
};
@@ -131,9 +149,11 @@ SuggestionPicker.prototype._measureMaxContentWidth = function() {
// left aligns all the content including label.
this._containerElement.classList.add('measuring-width');
var maxContentWidth = 0;
- var contentElements = this._containerElement.getElementsByClassName('content');
+ var contentElements =
+ this._containerElement.getElementsByClassName('content');
for (var i = 0; i < contentElements.length; ++i) {
- maxContentWidth = Math.max(maxContentWidth, contentElements[i].getBoundingClientRect().width);
+ maxContentWidth = Math.max(
+ maxContentWidth, contentElements[i].getBoundingClientRect().width);
}
this._containerElement.classList.remove('measuring-width');
return maxContentWidth;
@@ -141,11 +161,13 @@ SuggestionPicker.prototype._measureMaxContentWidth = function() {
SuggestionPicker.prototype._fixWindowSize = function() {
var ListBorder = 2;
+ const ListPadding = 2 * SuggestionPicker.Padding;
var zoom = this._config.zoomFactor;
- var desiredWindowWidth = (this._measureMaxContentWidth() + ListBorder) * zoom;
+ var desiredWindowWidth =
+ (this._measureMaxContentWidth() + ListBorder + ListPadding) * zoom;
if (typeof this._config.inputWidth === 'number')
desiredWindowWidth = Math.max(this._config.inputWidth, desiredWindowWidth);
- var totalHeight = ListBorder;
+ var totalHeight = ListBorder + ListPadding;
var maxHeight = 0;
var entryCount = 0;
for (var i = 0; i < this._containerElement.childNodes.length; ++i) {
@@ -153,18 +175,22 @@ SuggestionPicker.prototype._fixWindowSize = function() {
if (node.classList.contains(SuggestionPicker.ListEntryClass))
entryCount++;
totalHeight += node.offsetHeight;
- if (maxHeight === 0 && entryCount == SuggestionPicker.NumberOfVisibleEntries)
+ if (maxHeight === 0 &&
+ entryCount == SuggestionPicker.NumberOfVisibleEntries)
maxHeight = totalHeight;
}
var desiredWindowHeight = totalHeight * zoom;
if (maxHeight !== 0 && totalHeight > maxHeight * zoom) {
- this._containerElement.style.maxHeight = (maxHeight - ListBorder) + 'px';
+ this._containerElement.style.maxHeight =
+ (maxHeight - ListBorder - ListPadding) + 'px';
desiredWindowWidth += getScrollbarWidth() * zoom;
desiredWindowHeight = maxHeight * zoom;
this._containerElement.style.overflowY = 'scroll';
}
- var windowRect = adjustWindowRect(desiredWindowWidth, desiredWindowHeight, desiredWindowWidth, 0);
- this._containerElement.style.height = (windowRect.height / zoom - ListBorder) + 'px';
+ var windowRect = adjustWindowRect(
+ desiredWindowWidth, desiredWindowHeight, desiredWindowWidth, 0);
+ this._containerElement.style.height =
+ (windowRect.height / zoom - ListBorder - ListPadding) + 'px';
setWindowRect(windowRect);
};
@@ -174,19 +200,24 @@ SuggestionPicker.prototype._layout = function() {
if (this._config.isLocaleRTL)
this._element.classList.add('locale-rtl');
this._containerElement = createElement('ul', 'suggestion-list');
- this._containerElement.addEventListener('click', this._handleEntryClick.bind(this), false);
+ this._containerElement.addEventListener(
+ 'click', this._handleEntryClick.bind(this), false);
for (var i = 0; i < this._config.suggestionValues.length; ++i) {
this._containerElement.appendChild(this._createSuggestionEntryElement(
- this._config.localizedSuggestionValues[i], this._config.suggestionLabels[i], this._config.suggestionValues[i]));
+ this._config.localizedSuggestionValues[i],
+ this._config.suggestionLabels[i], this._config.suggestionValues[i]));
}
if (this._config.showOtherDateEntry) {
// Add separator
- var separator = createElement('div', 'separator');
- this._containerElement.appendChild(separator);
+ if (!global.params.isFormControlsRefreshEnabled) {
+ var separator = createElement('div', 'separator');
+ this._containerElement.appendChild(separator);
+ }
// Add "Other..." entry
- var otherEntry =
- this._createActionEntryElement(this._config.otherDateLabel, SuggestionPicker.ActionNames.OpenCalendarPicker);
+ var otherEntry = this._createActionEntryElement(
+ this._config.otherDateLabel,
+ SuggestionPicker.ActionNames.OpenCalendarPicker);
this._containerElement.appendChild(otherEntry);
}
this._element.appendChild(this._containerElement);
@@ -198,8 +229,11 @@ SuggestionPicker.prototype._layout = function() {
SuggestionPicker.prototype.selectEntry = function(entry) {
if (typeof entry.dataset.value !== 'undefined') {
this.submitValue(entry.dataset.value);
- } else if (entry.dataset.action === SuggestionPicker.ActionNames.OpenCalendarPicker) {
- window.addEventListener('didHide', SuggestionPicker._handleWindowDidHide, false);
+ } else if (
+ entry.dataset.action ===
+ SuggestionPicker.ActionNames.OpenCalendarPicker) {
+ window.addEventListener(
+ 'didHide', SuggestionPicker._handleWindowDidHide, false);
hideWindow();
}
};
@@ -213,7 +247,8 @@ SuggestionPicker._handleWindowDidHide = function() {
* @param {!Event} event
*/
SuggestionPicker.prototype._handleEntryClick = function(event) {
- var entry = enclosingNodeOrSelfWithClass(event.target, SuggestionPicker.ListEntryClass);
+ var entry = enclosingNodeOrSelfWithClass(
+ event.target, SuggestionPicker.ListEntryClass);
if (!entry)
return;
this.selectEntry(entry);
@@ -228,9 +263,11 @@ SuggestionPicker.prototype._findFirstVisibleEntry = function() {
var childNodes = this._containerElement.childNodes;
for (var i = 0; i < childNodes.length; ++i) {
var node = childNodes[i];
- if (node.nodeType !== Node.ELEMENT_NODE || !node.classList.contains(SuggestionPicker.ListEntryClass))
+ if (node.nodeType !== Node.ELEMENT_NODE ||
+ !node.classList.contains(SuggestionPicker.ListEntryClass))
continue;
- if (node.offsetTop + node.offsetHeight - scrollTop > SuggestionPicker.VisibleEntryThresholdHeight)
+ if (node.offsetTop + node.offsetHeight - scrollTop >
+ SuggestionPicker.VisibleEntryThresholdHeight)
return node;
}
return null;
@@ -240,13 +277,16 @@ SuggestionPicker.prototype._findFirstVisibleEntry = function() {
* @return {?Element}
*/
SuggestionPicker.prototype._findLastVisibleEntry = function() {
- var scrollBottom = this._containerElement.scrollTop + this._containerElement.offsetHeight;
+ var scrollBottom =
+ this._containerElement.scrollTop + this._containerElement.offsetHeight;
var childNodes = this._containerElement.childNodes;
for (var i = childNodes.length - 1; i >= 0; --i) {
var node = childNodes[i];
- if (node.nodeType !== Node.ELEMENT_NODE || !node.classList.contains(SuggestionPicker.ListEntryClass))
+ if (node.nodeType !== Node.ELEMENT_NODE ||
+ !node.classList.contains(SuggestionPicker.ListEntryClass))
continue;
- if (scrollBottom - node.offsetTop > SuggestionPicker.VisibleEntryThresholdHeight)
+ if (scrollBottom - node.offsetTop >
+ SuggestionPicker.VisibleEntryThresholdHeight)
return node;
}
return null;
@@ -262,8 +302,11 @@ SuggestionPicker.prototype._handleBodyKeyDown = function(event) {
this.handleCancel();
eventHandled = true;
} else if (key == 'ArrowUp') {
- if (document.activeElement && document.activeElement.classList.contains(SuggestionPicker.ListEntryClass)) {
- for (var node = document.activeElement.previousElementSibling; node; node = node.previousElementSibling) {
+ if (document.activeElement &&
+ document.activeElement.classList.contains(
+ SuggestionPicker.ListEntryClass)) {
+ for (var node = document.activeElement.previousElementSibling; node;
+ node = node.previousElementSibling) {
if (node.classList.contains(SuggestionPicker.ListEntryClass)) {
this._isFocusByMouse = false;
node.focus();
@@ -271,12 +314,17 @@ SuggestionPicker.prototype._handleBodyKeyDown = function(event) {
}
}
} else {
- this._element.querySelector('.' + SuggestionPicker.ListEntryClass + ':last-child').focus();
+ this._element
+ .querySelector('.' + SuggestionPicker.ListEntryClass + ':last-child')
+ .focus();
}
eventHandled = true;
} else if (key == 'ArrowDown') {
- if (document.activeElement && document.activeElement.classList.contains(SuggestionPicker.ListEntryClass)) {
- for (var node = document.activeElement.nextElementSibling; node; node = node.nextElementSibling) {
+ if (document.activeElement &&
+ document.activeElement.classList.contains(
+ SuggestionPicker.ListEntryClass)) {
+ for (var node = document.activeElement.nextElementSibling; node;
+ node = node.nextElementSibling) {
if (node.classList.contains(SuggestionPicker.ListEntryClass)) {
this._isFocusByMouse = false;
node.focus();
@@ -284,7 +332,9 @@ SuggestionPicker.prototype._handleBodyKeyDown = function(event) {
}
}
} else {
- this._element.querySelector('.' + SuggestionPicker.ListEntryClass + ':first-child').focus();
+ this._element
+ .querySelector('.' + SuggestionPicker.ListEntryClass + ':first-child')
+ .focus();
}
eventHandled = true;
} else if (key === 'Enter') {
@@ -311,7 +361,8 @@ SuggestionPicker.prototype._handleBodyKeyDown = function(event) {
* @param {!Event} event
*/
SuggestionPicker.prototype._handleEntryMouseOver = function(event) {
- var entry = enclosingNodeOrSelfWithClass(event.target, SuggestionPicker.ListEntryClass);
+ var entry = enclosingNodeOrSelfWithClass(
+ event.target, SuggestionPicker.ListEntryClass);
if (!entry)
return;
this._isFocusByMouse = true;
@@ -323,7 +374,8 @@ SuggestionPicker.prototype._handleEntryMouseOver = function(event) {
* @param {!Event} event
*/
SuggestionPicker.prototype._handleMouseOut = function(event) {
- if (!document.activeElement.classList.contains(SuggestionPicker.ListEntryClass))
+ if (!document.activeElement.classList.contains(
+ SuggestionPicker.ListEntryClass))
return;
this._isFocusByMouse = false;
document.activeElement.blur();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.css b/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.css
new file mode 100644
index 00000000000..0d3d91cabf3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.css
@@ -0,0 +1,94 @@
+/* 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-family: sans-serif;
+}
+
+.time-picker {
+ background: #FFFFFF;
+ display: flex;
+ flex-direction: column;
+ height: 273px;
+}
+
+.time-columns {
+ display: flex;
+ flex-direction: row;
+ height: 82%;
+ margin: 2px;
+}
+
+.time-column {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ list-style-type: none;
+ margin: 2px;
+ outline: none;
+ overflow: scroll;
+ padding: 0;
+ scroll-snap-type: y mandatory;
+ width: 52px;
+}
+
+.time-column::-webkit-scrollbar {
+ display: none;
+}
+
+.time-cell {
+ color: #101010;
+ font-size: 14px;
+ height: 32px;
+ line-height: 32px;
+ scroll-snap-align: start;
+ text-align: center;
+ width: 48px;
+}
+
+.time-cell:hover {
+ background: #E5E5E5;
+ border-radius: 2px;
+}
+
+.time-cell.selected {
+ background-color: #CECECE;
+ border-radius: 2px;
+ font-weight: bold;
+}
+
+.time-column:focus .time-cell.selected {
+ outline: auto 1px -webkit-focus-ring-color;
+}
+
+.submission-controls {
+ align-items: center;
+ border-top: 1px solid #CECECE;
+ bottom: 0px;
+ display: flex;
+ flex-direction: row;
+ height: 15%;
+ position: absolute;
+ width: 100%;
+}
+
+#submission-controls-padding {
+ height: 100%;
+ width: 84%;
+}
+
+.submission-button {
+ background-color: #FFFFFF;
+ border: 0;
+ height: 32px;
+ margin: 4px;
+ padding: 8px;
+ width: 32px;
+}
+
+.submission-button:hover {
+ background-color: #E5E5E5;
+ border-radius: 2px;
+}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.js b/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.js
new file mode 100644
index 00000000000..bec6a53bfa0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/time_picker.js
@@ -0,0 +1,538 @@
+'use strict';
+// 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.
+
+/**
+ * @fileoverview Picker used by <input type='time' />
+ */
+
+function initializeTimePicker(config) {
+ const timePicker = new TimePicker(config);
+ global.picker = timePicker;
+ main.append(timePicker);
+ resizeWindow(timePicker.width, timePicker.height);
+}
+
+/**
+ * Supported time column types.
+ * @enum {number}
+ */
+const TimeColumnType = {
+ UNDEFINED: 0,
+ HOUR: 1,
+ MINUTE: 2,
+ SECOND: 3,
+ MILLISECOND: 4,
+ AMPM: 5,
+};
+
+
+/**
+ * Supported label types.
+ * @enum {number}
+ */
+const Label = {
+ AM: 0,
+ PM: 1,
+};
+
+/**
+ * @param {string} dateTimeString
+ * @return {?Day|Week|Month|Time}
+ */
+function parseDateTimeString(dateTimeString) {
+ var time = Time.parse(dateTimeString);
+ if (time)
+ return time;
+ return parseDateString(dateTimeString);
+}
+
+class Time {
+ constructor(hour, minute, second, millisecond) {
+ this.hour_ = hour;
+ this.minute_ = minute;
+ this.second_ = second;
+ this.millisecond_ = millisecond;
+ }
+
+ next = (columnType) => {
+ switch (columnType) {
+ case TimeColumnType.HOUR:
+ this.hour_ = (this.hour_ + 1) % Time.HOUR_VALUES;
+ break;
+ case TimeColumnType.MINUTE:
+ this.minute_ = (this.minute_ + 1) % Time.MINUTE_VALUES;
+ break;
+ case TimeColumnType.SECOND:
+ this.second_ = (this.second_ + 1) % Time.SECOND_VALUES;
+ break;
+ case TimeColumnType.MILLISECOND:
+ // TODO(https://crbug.com/1008294): Use increments of 1 instead of 100 for milliseconds.
+ // support 100, 200, 300... for milliseconds
+ this.millisecond_ =
+ (Math.round(this.millisecond_ / 100) * 100 + 100) % 1000;
+ break;
+ }
+ };
+
+ value = (columnType, hasAMPM) => {
+ switch (columnType) {
+ case TimeColumnType.HOUR:
+ let hour = hasAMPM ?
+ (this.hour_ % Time.Maximum_Hour_AMPM || Time.Maximum_Hour_AMPM) :
+ this.hour_;
+ return hour.toString().padStart(2, '0');
+ case TimeColumnType.MINUTE:
+ return this.minute_.toString().padStart(2, '0');
+ case TimeColumnType.SECOND:
+ return this.second_.toString().padStart(2, '0');
+ case TimeColumnType.MILLISECOND:
+ return this.millisecond_.toString().padStart(3, '0');
+ }
+ };
+
+ toString = (hasSecond, hasMillisecond) => {
+ let value = `${this.value(TimeColumnType.HOUR)}:${
+ this.value(TimeColumnType.MINUTE)}`;
+ if (hasSecond) {
+ value += `:${this.value(TimeColumnType.SECOND)}`;
+ }
+ if (hasMillisecond) {
+ value += `.${this.value(TimeColumnType.MILLISECOND)}`;
+ }
+ return value;
+ };
+
+ clone =
+ () => {
+ return new Time(
+ this.hour_, this.minute_, this.second_, this.millisecond_);
+ }
+
+ isAM = () => {
+ return this.hour_ < Time.Maximum_Hour_AMPM;
+ };
+
+ static parse = (str) => {
+ var match = Time.ISOStringRegExp.exec(str);
+ if (!match)
+ return null;
+ var hour = parseInt(match[1], 10);
+ var minute = parseInt(match[2], 10);
+ var second = 0;
+ if (match[3])
+ second = parseInt(match[3], 10);
+ var millisecond = 0;
+ if (match[4])
+ millisecond = parseInt(match[4], 10);
+ return new Time(hour, minute, second, millisecond);
+ };
+
+ static currentTime = () => {
+ var currentDate = new Date();
+ return new Time(
+ currentDate.getHours(), currentDate.getMinutes(),
+ currentDate.getSeconds(), currentDate.getMilliseconds());
+ };
+
+ static numberOfValues = (columnType, hasAMPM) => {
+ switch (columnType) {
+ case TimeColumnType.HOUR:
+ return hasAMPM ? Time.HOUR_VALUES_AMPM : Time.HOUR_VALUES;
+ case TimeColumnType.MINUTE:
+ return Time.MINUTE_VALUES;
+ case TimeColumnType.SECOND:
+ return Time.SECOND_VALUES;
+ case TimeColumnType.MILLISECOND:
+ return Time.MILLISECOND_VALUES;
+ }
+ };
+}
+// See platform/date_components.h.
+Time.Minimum = new Time(0, 0, 0, 0);
+Time.Maximum = new Time(23, 59, 59, 999);
+Time.Maximum_Hour_AMPM = 12;
+Time.ISOStringRegExp = /^(\d+):(\d+):?(\d*).?(\d*)/;
+// Number of values for each column.
+Time.HOUR_VALUES = 24;
+Time.HOUR_VALUES_AMPM = 12;
+Time.MINUTE_VALUES = 60;
+Time.SECOND_VALUES = 60;
+Time.MILLISECOND_VALUES = 10;
+
+/**
+ * TimePicker: Custom element providing a time picker implementation.
+ * TimePicker contains 2 parts:
+ * - column container
+ * - submission controls
+ */
+class TimePicker extends HTMLElement {
+ constructor(config) {
+ super();
+
+ this.className = TimePicker.ClassName;
+ this.initializeFromConfig_(config);
+
+ this.timeColumns_ = new TimeColumns(this);
+ this.submissionControls_ = new SubmissionControls(
+ this.onSubmitButtonClick_, this.onCancelButtonClick_);
+ this.append(this.timeColumns_, this.submissionControls_);
+
+ window.addEventListener('resize', this.onWindowResize_, {once: true});
+ this.addEventListener('keydown', this.onKeyDown_);
+ };
+
+ initializeFromConfig_ = (config) => {
+ const initialSelection = parseDateTimeString(config.currentValue);
+ this.selectedTime_ =
+ initialSelection ? initialSelection : Time.currentTime();
+ this.hasSecond_ = config.hasSecond;
+ this.hasMillisecond_ = config.hasMillisecond;
+ this.hasAMPM_ = config.hasAMPM;
+ };
+
+ onSubmitButtonClick_ = () => {
+ const selectedValue = this.timeColumns_.selectedValue().toString(
+ this.hasSecond, this.hasMillisecond);
+ window.setTimeout(function() {
+ window.pagePopupController.setValueAndClosePopup(0, selectedValue);
+ }, 100);
+ };
+
+ onCancelButtonClick_ = () => {
+ window.pagePopupController.closePopup();
+ };
+
+ onWindowResize_ = (event) => {
+ this.timeColumns_.firstChild.focus();
+ };
+
+ onKeyDown_ = (event) => {
+ switch (event.key) {
+ case 'Enter':
+ this.submissionControls_.submitButton.click();
+ break;
+ case 'Escape':
+ this.submissionControls_.cancelButton.click();
+ break;
+ }
+ };
+
+ get selectedTime() {
+ return this.selectedTime_;
+ }
+
+ get hasSecond() {
+ return this.hasSecond_;
+ }
+
+ get hasMillisecond() {
+ return this.hasMillisecond_;
+ }
+
+ get hasAMPM() {
+ return this.hasAMPM_;
+ }
+
+ get width() {
+ return this.timeColumns_.width;
+ }
+
+ get height() {
+ return TimePicker.Height;
+ }
+
+ get timeColumns() {
+ return this.timeColumns_;
+ }
+
+ get submissionControls() {
+ return this.submissionControls_;
+ }
+}
+TimePicker.ClassName = 'time-picker';
+TimePicker.Height = 273;
+TimePicker.ColumnWidth = 54;
+window.customElements.define('time-picker', TimePicker);
+
+/**
+ * TimeColumns: Columns container that provides functionality for creating
+ * the required columns and for updating the selected value.
+ */
+class TimeColumns extends HTMLElement {
+ constructor(timePicker) {
+ super();
+
+ this.className = TimeColumns.ClassName;
+ this.hourColumn_ = new TimeColumn(TimeColumnType.HOUR, timePicker);
+ this.width_ = 0;
+ this.minuteColumn_ = new TimeColumn(TimeColumnType.MINUTE, timePicker);
+ if (timePicker.hasAMPM) {
+ this.ampmColumn_ = new TimeColumn(TimeColumnType.AMPM, timePicker);
+ }
+ if (timePicker.hasAMPM && global.params.isAMPMFirst) {
+ this.append(this.ampmColumn_, this.hourColumn_, this.minuteColumn_);
+ this.width_ += 3 * TimePicker.ColumnWidth;
+ } else {
+ this.append(this.hourColumn_, this.minuteColumn_);
+ this.width_ += 2 * TimePicker.ColumnWidth;
+ }
+ if (timePicker.hasSecond) {
+ this.secondColumn_ = new TimeColumn(TimeColumnType.SECOND, timePicker);
+ this.append(this.secondColumn_);
+ this.width_ += TimePicker.ColumnWidth;
+ }
+ if (timePicker.hasMillisecond) {
+ this.millisecondColumn_ =
+ new TimeColumn(TimeColumnType.MILLISECOND, timePicker);
+ this.append(this.millisecondColumn_);
+ this.width_ += TimePicker.ColumnWidth;
+ }
+ if (timePicker.hasAMPM && !global.params.isAMPMFirst) {
+ this.append(this.ampmColumn_);
+ this.width_ += TimePicker.ColumnWidth;
+ }
+ };
+
+ get width() {
+ return this.width_;
+ }
+
+ selectedValue = () => {
+ let hour = parseInt(this.hourColumn_.selectedTimeCell.value, 10);
+ const minute = parseInt(this.minuteColumn_.selectedTimeCell.value, 10);
+ const second = this.secondColumn_ ?
+ parseInt(this.secondColumn_.selectedTimeCell.value, 10) :
+ 0;
+ const millisecond = this.millisecondColumn_ ?
+ parseInt(this.millisecondColumn_.selectedTimeCell.value, 10) :
+ 0;
+ if (this.ampmColumn_) {
+ const isAM = this.ampmColumn_.selectedTimeCell.textContent ==
+ global.params.ampmLabels[Label.AM];
+ if (isAM && hour == Time.Maximum_Hour_AMPM) {
+ hour = 0;
+ } else if (!isAM && hour != Time.Maximum_Hour_AMPM) {
+ hour += Time.Maximum_Hour_AMPM;
+ }
+ }
+ return new Time(hour, minute, second, millisecond);
+ };
+}
+TimeColumns.ClassName = 'time-columns';
+window.customElements.define('time-columns', TimeColumns);
+
+/**
+ * TimeColumn: Column that contains all values available for a time column type.
+ */
+class TimeColumn extends HTMLUListElement {
+ constructor(columnType, timePicker) {
+ super();
+
+ this.className = TimeColumn.ClassName;
+ this.tabIndex = 0;
+ this.columnType_ = columnType;
+ if (this.columnType_ == TimeColumnType.AMPM) {
+ this.createAndInitializeAMPMCells_(timePicker);
+ } else {
+ this.createAndInitializeCells_(timePicker);
+ }
+
+ this.addEventListener('click', this.onClick_);
+ this.addEventListener('keydown', this.onKeyDown_);
+ };
+
+ createAndInitializeCells_ = (timePicker) => {
+ const totalCells = Time.numberOfValues(this.columnType_, timePicker.hasAMPM);
+ let currentTime = timePicker.selectedTime.clone();
+ let cells = [];
+ let duplicateCells = [];
+ // In order to support a continuous looping navigation for up/down arrows,
+ // the initial list of cells is doubled and middleTimeCell is kept
+ // to inform where the duplicated cells begin.
+ for (let i = 0; i < totalCells; i++) {
+ let value = currentTime.value(this.columnType_, timePicker.hasAMPM);
+ let timeCell = new TimeCell(value, localizeNumber(value));
+ let duplicatedTimeCell = new TimeCell(value, localizeNumber(value));
+ cells.push(timeCell);
+ duplicateCells.push(duplicatedTimeCell);
+ currentTime.next(this.columnType_);
+ }
+ this.selectedTimeCell = cells[0];
+ this.middleTimeCell_ = duplicateCells[0];
+ this.append(...cells, ...duplicateCells);
+ };
+
+ createAndInitializeAMPMCells_ = (timePicker) => {
+ let cells = [];
+ for (let i = 0; i < 2; i++) {
+ let value = global.params.ampmLabels[i];
+ let timeCell = new TimeCell(value, value);
+ cells.push(timeCell);
+ }
+
+ if (timePicker.selectedTime.isAM()) {
+ this.append(cells[Label.AM], cells[Label.PM]);
+ this.selectedTimeCell = cells[Label.AM];
+ } else {
+ this.append(cells[Label.PM], cells[Label.AM]);
+ this.selectedTimeCell = cells[Label.PM];
+ }
+ };
+
+ onClick_ = (event) => {
+ this.selectedTimeCell = event.target;
+ };
+
+ /**
+ * Continuous looping navigation for up/down arrows is supported by:
+ * - moving for ArrowUp to previous cell and for topmost cell which
+ * has no previous, we are moving to the last cell from the first list
+ * - moving for ArrowDown to next cell and for the last duplicated cell
+ * which has no next, we are moving to the first cell from the duplicated list
+ */
+ onKeyDown_ = (event) => {
+ let eventHandled = false;
+ switch (event.key) {
+ case 'ArrowUp':
+ const previousTimeCell = this.selectedTimeCell.previousSibling;
+ if (previousTimeCell) {
+ this.selectedTimeCell = previousTimeCell;
+ previousTimeCell.scrollIntoViewIfNeeded(false);
+ } else if (this.columnType != TimeColumnType.AMPM) {
+ // move from the topmost cell to the last cell (the last cell is
+ // the first one before the duplicated list).
+ this.selectedTimeCell = this.middleTimeCell.previousSibling;
+ this.selectedTimeCell.scrollIntoView();
+ }
+ eventHandled = true;
+ break;
+ case 'ArrowDown':
+ const nextTimeCell = this.selectedTimeCell.nextSibling;
+ if (nextTimeCell) {
+ this.selectedTimeCell = nextTimeCell;
+ nextTimeCell.scrollIntoViewIfNeeded(false);
+ } else if (this.columnType != TimeColumnType.AMPM) {
+ // move from the last duplicated cell to the first cell
+ // of the duplicated list.
+ this.selectedTimeCell = this.middleTimeCell;
+ this.selectedTimeCell.scrollIntoView(false);
+ }
+ eventHandled = true;
+ break;
+ case 'ArrowLeft':
+ const previousTimeColumn = this.previousSibling;
+ if (previousTimeColumn) {
+ previousTimeColumn.focus();
+ }
+ break;
+ case 'ArrowRight':
+ const nextTimeColumn = this.nextSibling;
+ if (nextTimeColumn) {
+ nextTimeColumn.focus();
+ }
+ break;
+ }
+
+ if (eventHandled) {
+ event.stopPropagation();
+ event.preventDefault();
+ }
+ };
+
+ get selectedTimeCell() {
+ return this.selectedTimeCell_;
+ }
+
+ set selectedTimeCell(timeCell) {
+ if (this.selectedTimeCell_) {
+ this.selectedTimeCell_.classList.remove('selected');
+ }
+ this.selectedTimeCell_ = timeCell;
+ this.selectedTimeCell_.classList.add('selected');
+ }
+
+ get middleTimeCell() {
+ return this.middleTimeCell_;
+ }
+
+ get columnType() {
+ return this.columnType_;
+ }
+}
+TimeColumn.ClassName = 'time-column';
+window.customElements.define('time-column', TimeColumn, {extends: 'ul'});
+
+/**
+ * TimeCell: List item with a custom look that displays a time value.
+ */
+class TimeCell extends HTMLLIElement {
+ constructor(value, localizedValue) {
+ super();
+
+ this.className = TimeCell.ClassName;
+ this.textContent = localizedValue;
+ this.value = value;
+ };
+}
+TimeCell.ClassName = 'time-cell';
+window.customElements.define('time-cell', TimeCell, {extends: 'li'});
+
+/**
+ * SubmissionControls: Provides functionality to submit or discard a change.
+ */
+class SubmissionControls extends HTMLElement {
+ constructor(submitCallback, cancelCallback) {
+ super();
+
+ const padding = document.createElement('span');
+ padding.setAttribute('id', 'submission-controls-padding');
+ this.append(padding);
+
+ this.className = SubmissionControls.ClassName;
+
+ this.submitButton_ = new SubmissionButton(
+ submitCallback,
+ '<svg width="14" height="10" viewBox="0 0 14 10" fill="none" ' +
+ 'xmlns="http://www.w3.org/2000/svg"><path d="M13.3516 ' +
+ '1.35156L5 9.71094L0.648438 5.35156L1.35156 4.64844L5 ' +
+ '8.28906L12.6484 0.648438L13.3516 1.35156Z" fill="black"/></svg>');
+ this.cancelButton_ = new SubmissionButton(
+ cancelCallback,
+ '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" ' +
+ 'xmlns="http://www.w3.org/2000/svg"><path d="M7.71094 7L13.1016 ' +
+ '12.3984L12.3984 13.1016L7 7.71094L1.60156 13.1016L0.898438 ' +
+ '12.3984L6.28906 7L0.898438 1.60156L1.60156 0.898438L7 ' +
+ '6.28906L12.3984 0.898438L13.1016 1.60156L7.71094 7Z" ' +
+ 'fill="black"/></svg>');
+ this.append(this.submitButton_, this.cancelButton_);
+ }
+
+ get submitButton() {
+ return this.submitButton_;
+ }
+
+ get cancelButton() {
+ return this.cancelButton_;
+ }
+}
+SubmissionControls.ClassName = 'submission-controls';
+window.customElements.define('submission-controls', SubmissionControls);
+
+/**
+ * SubmissionButton: Button with a custom look that can be clicked for
+ * a submission action.
+ */
+class SubmissionButton extends HTMLButtonElement {
+ constructor(clickCallback, htmlString) {
+ super();
+
+ this.className = SubmissionButton.ClassName;
+ this.innerHTML = htmlString;
+ this.addEventListener('click', clickCallback);
+ }
+}
+SubmissionButton.ClassName = 'submission-button';
+window.customElements.define(
+ 'submission-button', SubmissionButton, {extends: 'button'});
diff --git a/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
index 51eee5209aa..5639595e184 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html/forms/submit_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.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/forms/form_data.h"
@@ -75,7 +76,7 @@ bool SubmitInputType::CanBeSuccessfulSubmitButton() {
}
String SubmitInputType::DefaultLabel() const {
- return GetLocale().QueryString(WebLocalizedString::kSubmitButtonDefaultLabel);
+ return GetLocale().QueryString(IDS_FORM_SUBMIT_LABEL);
}
bool SubmitInputType::IsTextButton() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
index f8fc94ae14d..7cbc1b7c65b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -408,7 +408,8 @@ unsigned TextControlElement::IndexForPosition(HTMLElement* inner_editor,
index += std::min(length, passed_position.OffsetInContainerNode());
else
index += length;
- } else if (node->HasTagName(kBrTag)) {
+ // Disregard the last auto added placeholder BrTag.
+ } else if (node->HasTagName(kBrTag) && node != inner_editor->lastChild()) {
++index;
}
}
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 fdaf84b7d33..a1c7cbd8b12 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
@@ -188,8 +188,8 @@ TextControlInnerEditorElement::CreateInnerEditorStyle() const {
scoped_refptr<ComputedStyle> no_scrollbar_style = ComputedStyle::Create();
no_scrollbar_style->SetStyleType(kPseudoIdScrollbar);
no_scrollbar_style->SetDisplay(EDisplay::kNone);
- text_block_style->AddCachedPseudoStyle(no_scrollbar_style);
- text_block_style->SetHasPseudoStyle(kPseudoIdScrollbar);
+ text_block_style->AddCachedPseudoElementStyle(no_scrollbar_style);
+ text_block_style->SetHasPseudoElementStyle(kPseudoIdScrollbar);
}
return text_block_style;
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 ef55cd7a76b..816a88dd1dd 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
@@ -375,8 +375,8 @@ void TextFieldInputType::ListAttributeTargetChanged() {
}
void TextFieldInputType::AttributeChanged() {
- // FIXME: Updating on any attribute update should be unnecessary. We should
- // figure out what attributes affect.
+ // TODO(crbug.com/1012774): Updating on any attribute update should be
+ // unnecessary. We should figure out what attributes affect.
UpdateView();
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/url_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/url_input_type.cc
index d6722970e30..a4425146488 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/url_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/url_input_type.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/html/forms/url_input_type.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#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/parser/html_parser_idioms.h"
@@ -55,8 +56,7 @@ bool URLInputType::TypeMismatch() const {
}
String URLInputType::TypeMismatchText() const {
- return GetLocale().QueryString(
- WebLocalizedString::kValidationTypeMismatchForURL);
+ return GetLocale().QueryString(IDS_FORM_VALIDATION_TYPE_MISMATCH_URL);
}
String URLInputType::SanitizeValue(const String& proposed_value) const {
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 93801116726..a284d4bb463 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
@@ -433,7 +433,7 @@ void HTMLAnchorElement::HandleClick(Event& event) {
request.SetRequestContext(mojom::RequestContextType::DOWNLOAD);
request.SetRequestorOrigin(GetDocument().GetSecurityOrigin());
frame->Client()->DownloadURL(request,
- DownloadCrossOriginRedirects::kNavigate);
+ network::mojom::RedirectMode::kManual);
return;
}
@@ -455,8 +455,8 @@ void HTMLAnchorElement::HandleClick(Event& event) {
WebFeature::kHTMLAnchorElementHrefTranslateAttribute);
}
frame_request.SetTriggeringEventInfo(
- event.isTrusted() ? WebTriggeringEventInfo::kFromTrustedEvent
- : WebTriggeringEventInfo::kFromUntrustedEvent);
+ event.isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
+ : TriggeringEventInfo::kFromUntrustedEvent);
frame_request.SetInputStartTime(event.PlatformTimeStamp());
frame->MaybeLogAdClickNavigation();
diff --git a/chromium/third_party/blink/renderer/core/html/html_collection.cc b/chromium/third_party/blink/renderer/core/html/html_collection.cc
index 6072f639065..3450872e5c6 100644
--- a/chromium/third_party/blink/renderer/core/html/html_collection.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_collection.cc
@@ -233,9 +233,10 @@ static inline bool IsMatchingHTMLElement(const HTMLCollection& html_collection,
return element.HasTagName(kTrTag);
case kSelectOptions:
return ToHTMLOptionsCollection(html_collection).ElementMatches(element);
- case kSelectedOptions:
- return IsHTMLOptionElement(element) &&
- ToHTMLOptionElement(element).Selected();
+ case kSelectedOptions: {
+ auto* option_element = DynamicTo<HTMLOptionElement>(element);
+ return option_element && option_element->Selected();
+ }
case kDataListOptions:
return ToHTMLDataListOptionsCollection(html_collection)
.ElementMatches(element);
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 f502e8a9dcf..043d0e3a3bf 100644
--- a/chromium/third_party/blink/renderer/core/html/html_details_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_details_element.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/html/html_details_element.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/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -82,7 +83,7 @@ void HTMLDetailsElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
MakeGarbageCollected<HTMLSummaryElement>(GetDocument());
default_summary->AppendChild(
Text::Create(GetDocument(),
- GetLocale().QueryString(WebLocalizedString::kDetailsLabel)));
+ GetLocale().QueryString(IDS_DETAILS_WITHOUT_SUMMARY_LABEL)));
HTMLSlotElement* summary_slot =
HTMLSlotElement::CreateUserAgentCustomAssignSlot(GetDocument());
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 8fbab586818..0036d0d1621 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
@@ -58,11 +58,9 @@ static void SetFocusForDialog(HTMLDialogElement* dialog) {
auto* element = DynamicTo<Element>(node);
if (!element)
continue;
- if (auto* control = DynamicTo<HTMLFormControlElement>(node)) {
- if (control->IsAutofocusable() && control->IsFocusable()) {
- control->focus();
- return;
- }
+ if (element->IsAutofocusable() && element->IsFocusable()) {
+ element->focus();
+ return;
}
if (!focusable_descendant && element->IsFocusable())
focusable_descendant = element;
@@ -182,6 +180,13 @@ void HTMLDialogElement::showModal(ExceptionState& exception_state) {
void HTMLDialogElement::RemovedFrom(ContainerNode& insertion_point) {
HTMLElement::RemovedFrom(insertion_point);
SetNotCentered();
+
+ // TODO(671907): Calling UpdateDistributionForFlatTreeTraversal here is a
+ // workaround for https://crbug.com/895511. This shouldn't be done during DOM
+ // mutation. However, Shadow DOM v0 will be removed, at which point this call
+ // can be removed.
+ GetDocument().UpdateDistributionForFlatTreeTraversal();
+
InertSubtreesChanged(GetDocument());
}
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 bf4a1b05baa..7c1ff5e55b8 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_element.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
@@ -655,7 +656,10 @@ void HTMLElement::ParseAttribute(const AttributeModificationParams& params) {
if (triggers->web_feature != kNoWebFeature) {
// Count usage of attributes but ignore attributes in user agent shadow DOM.
if (!IsInUserAgentShadowRoot()) {
- UseCounter::Count(GetDocument(), triggers->web_feature);
+ if (triggers->web_feature == WebFeature::kARIAHelpAttribute)
+ Deprecation::CountDeprecation(GetDocument(), triggers->web_feature);
+ else
+ UseCounter::Count(GetDocument(), triggers->web_feature);
}
}
if (triggers->function)
diff --git a/chromium/third_party/blink/renderer/core/html/html_embed_element.cc b/chromium/third_party/blink/renderer/core/html/html_embed_element.cc
index 547dc4fad93..577b7a6da93 100644
--- a/chromium/third_party/blink/renderer/core/html/html_embed_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -101,10 +101,6 @@ void HTMLEmbedElement::CollectStyleForPresentationAttribute(
void HTMLEmbedElement::ParseAttribute(
const AttributeModificationParams& params) {
- // Changing an attribute may change the content, type of content, layout
- // object type, or all of the above. Not safe to re-use through reattach.
- SetDisposeView();
-
if (params.name == kTypeAttr) {
SetServiceType(params.new_value.LowerASCII());
wtf_size_t pos = service_type_.Find(";");
@@ -112,6 +108,7 @@ void HTMLEmbedElement::ParseAttribute(
SetServiceType(service_type_.Left(pos));
if (GetLayoutObject()) {
SetNeedsPluginUpdate(true);
+ SetDisposeView();
GetLayoutObject()->SetNeedsLayoutAndFullPaintInvalidation(
"Embed type changed");
}
@@ -119,9 +116,11 @@ void HTMLEmbedElement::ParseAttribute(
// TODO(schenney): Remove this branch? It's not in the spec and we're not in
// the HTMLAppletElement hierarchy.
SetUrl(StripLeadingAndTrailingHTMLSpaces(params.new_value));
+ SetDisposeView();
} else if (params.name == kSrcAttr) {
SetUrl(StripLeadingAndTrailingHTMLSpaces(params.new_value));
if (GetLayoutObject() && IsImageType()) {
+ SetDisposeView();
if (!image_loader_)
image_loader_ = MakeGarbageCollected<HTMLImageLoader>(this);
image_loader_->UpdateFromElement(ImageLoader::kUpdateIgnorePreviousError);
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
index 5382a7f2a23..16afe15460b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/html/html_frame_element.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/html/html_frame_set_element.h"
#include "third_party/blink/renderer/core/html_names.h"
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
index 6bcc0eff463..1f51546d661 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/html_frame_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
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 3c8cb20a2a3..283c6919786 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
@@ -131,8 +132,7 @@ bool ShouldLazilyLoadFrame(const Document& document,
// holdback into consideration.
if (RuntimeEnabledFeatures::
RestrictAutomaticLazyFrameLoadingToDataSaverEnabled() &&
- (document.GetSettings()->GetDataSaverHoldbackWebApi() ||
- !GetNetworkStateNotifier().SaveDataEnabled())) {
+ !GetNetworkStateNotifier().SaveDataEnabled()) {
return false;
}
@@ -172,8 +172,8 @@ HTMLFrameOwnerElement::HTMLFrameOwnerElement(const QualifiedName& tag_name,
: HTMLElement(tag_name, document),
content_frame_(nullptr),
embedded_content_view_(nullptr),
- should_lazy_load_children_(DoesParentAllowLazyLoadingChildren(document)) {
-}
+ should_lazy_load_children_(DoesParentAllowLazyLoadingChildren(document)),
+ is_swapping_frames_(false) {}
LayoutEmbeddedContent* HTMLFrameOwnerElement::GetLayoutEmbeddedContent() const {
// HTMLObjectElement and HTMLEmbedElement may return arbitrary layoutObjects
@@ -307,15 +307,12 @@ void HTMLFrameOwnerElement::UpdateContainerPolicy(Vector<String>* messages) {
}
}
-void HTMLFrameOwnerElement::PointerEventsChanged() {
- if (auto* remote_frame = DynamicTo<RemoteFrame>(ContentFrame()))
- remote_frame->PointerEventsChanged();
-}
-
void HTMLFrameOwnerElement::FrameOwnerPropertiesChanged() {
// Don't notify about updates if ContentFrame() is null, for example when
- // the subframe hasn't been created yet.
- if (ContentFrame()) {
+ // the subframe hasn't been created yet; or if we are in the middle of
+ // swapping one frame for another, in which case the final state of
+ // properties will be propagated at the end of the swapping operation.
+ if (!is_swapping_frames_ && ContentFrame()) {
GetDocument().GetFrame()->Client()->DidChangeFrameOwnerProperties(this);
}
}
@@ -356,17 +353,18 @@ void HTMLFrameOwnerElement::SetEmbeddedContentView(
}
}
- if (embedded_content_view_) {
- if (embedded_content_view_->IsAttached()) {
- embedded_content_view_->DetachFromLayout();
- if (embedded_content_view_->IsPluginView())
- DisposePluginSoon(ToWebPluginContainerImpl(embedded_content_view_));
+ EmbeddedContentView* old_view = embedded_content_view_.Get();
+ embedded_content_view_ = embedded_content_view;
+ if (old_view) {
+ if (old_view->IsAttached()) {
+ old_view->DetachFromLayout();
+ if (old_view->IsPluginView())
+ DisposePluginSoon(ToWebPluginContainerImpl(old_view));
else
- embedded_content_view_->Dispose();
+ old_view->Dispose();
}
}
- embedded_content_view_ = embedded_content_view;
FrameOwnerPropertiesChanged();
GetDocument().GetRootScrollerController().DidUpdateIFrameFrameView(*this);
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 14cb408609e..3d7304108ed 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
@@ -46,7 +46,6 @@ class WebPluginContainerImpl;
class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
public FrameOwner {
USING_GARBAGE_COLLECTED_MIXIN(HTMLFrameOwnerElement);
-
public:
~HTMLFrameOwnerElement() override;
@@ -120,10 +119,6 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
// For unit tests, manually trigger the UpdateContainerPolicy method.
void UpdateContainerPolicyForTests() { UpdateContainerPolicy(); }
- // This function is to notify ChildFrameCompositor of pointer-events changes
- // of an OOPIF.
- void PointerEventsChanged();
-
void CancelPendingLazyLoad();
void ParseAttribute(const AttributeModificationParams&) override;
@@ -142,9 +137,9 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
const AtomicString& frame_name,
bool replace_current_item);
bool IsKeyboardFocusable() const override;
+ void FrameOwnerPropertiesChanged() override;
void DisposePluginSoon(WebPluginContainerImpl*);
- void FrameOwnerPropertiesChanged();
// Return the origin which is to be used for feature policy container
// policies, as "the origin of the URL in the frame's src attribute" (see
@@ -170,8 +165,10 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
// already HTMLFrameOwnerElement.
bool IsLocal() const final { return true; }
bool IsRemote() const final { return false; }
-
bool IsFrameOwnerElement() const final { return true; }
+ void SetIsSwappingFrames(bool is_swapping) override {
+ is_swapping_frames_ = is_swapping;
+ }
virtual network::mojom::ReferrerPolicy ReferrerPolicyAttribute() {
return network::mojom::ReferrerPolicy::kDefault;
@@ -185,6 +182,7 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
Member<LazyLoadFrameObserver> lazy_load_frame_observer_;
bool should_lazy_load_children_;
+ bool is_swapping_frames_;
};
class SubframeLoadingDisabler {
diff --git a/chromium/third_party/blink/renderer/core/html/html_hr_element.cc b/chromium/third_party/blink/renderer/core/html/html_hr_element.cc
index b55a94c32c1..16a88caf355 100644
--- a/chromium/third_party/blink/renderer/core/html/html_hr_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_hr_element.cc
@@ -112,31 +112,32 @@ void HTMLHRElement::CollectStyleForPresentationAttribute(
HTMLSelectElement* HTMLHRElement::OwnerSelectElement() const {
if (!parentNode())
return nullptr;
- if (auto* select = ToHTMLSelectElementOrNull(*parentNode()))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*parentNode()))
return select;
- if (!IsHTMLOptGroupElement(*parentNode()))
+ if (!IsA<HTMLOptGroupElement>(*parentNode()))
return nullptr;
- return ToHTMLSelectElementOrNull(parentNode()->parentNode());
+ return DynamicTo<HTMLSelectElement>(parentNode()->parentNode());
}
Node::InsertionNotificationRequest HTMLHRElement::InsertedInto(
ContainerNode& insertion_point) {
HTMLElement::InsertedInto(insertion_point);
if (HTMLSelectElement* select = OwnerSelectElement()) {
- if (&insertion_point == select || (IsHTMLOptGroupElement(insertion_point) &&
- insertion_point.parentNode() == select))
+ if (&insertion_point == select ||
+ (IsA<HTMLOptGroupElement>(insertion_point) &&
+ insertion_point.parentNode() == select))
select->HrInsertedOrRemoved(*this);
}
return kInsertionDone;
}
void HTMLHRElement::RemovedFrom(ContainerNode& insertion_point) {
- if (auto* select = ToHTMLSelectElementOrNull(insertion_point)) {
- if (!parentNode() || IsHTMLOptGroupElement(*parentNode()))
+ if (auto* select = DynamicTo<HTMLSelectElement>(insertion_point)) {
+ if (!parentNode() || IsA<HTMLOptGroupElement>(*parentNode()))
select->HrInsertedOrRemoved(*this);
- } else if (IsHTMLOptGroupElement(insertion_point)) {
+ } else if (IsA<HTMLOptGroupElement>(insertion_point)) {
Node* parent = insertion_point.parentNode();
- select = ToHTMLSelectElementOrNull(parent);
+ select = DynamicTo<HTMLSelectElement>(parent);
if (select)
select->HrInsertedOrRemoved(*this);
}
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 50416b0b7bc..e66a2d427a4 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
@@ -26,13 +26,16 @@
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.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"
#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/style/computed_style.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -116,4 +119,69 @@ HTMLHtmlElement::AdditionalPresentationAttributeStyle() {
return nullptr;
}
+namespace {
+
+bool NeedsLayoutStylePropagation(const ComputedStyle& layout_style,
+ const ComputedStyle& propagated_style) {
+ return layout_style.GetWritingMode() != propagated_style.GetWritingMode() ||
+ layout_style.Direction() != propagated_style.Direction();
+}
+
+scoped_refptr<ComputedStyle> CreateLayoutStyle(
+ const ComputedStyle& style,
+ const ComputedStyle& propagated_style) {
+ scoped_refptr<ComputedStyle> layout_style = ComputedStyle::Clone(style);
+ layout_style->SetDirection(propagated_style.Direction());
+ layout_style->SetWritingMode(propagated_style.GetWritingMode());
+ return layout_style;
+}
+
+} // namespace
+
+scoped_refptr<const ComputedStyle> HTMLHtmlElement::LayoutStyleForElement(
+ scoped_refptr<const ComputedStyle> style) {
+ DCHECK(style);
+ DCHECK(GetDocument().InStyleRecalc());
+ if (const Element* body_element = GetDocument().body()) {
+ if (const ComputedStyle* body_style = body_element->GetComputedStyle()) {
+ if (NeedsLayoutStylePropagation(*style, *body_style))
+ return CreateLayoutStyle(*style, *body_style);
+ }
+ }
+ return style;
+}
+
+void HTMLHtmlElement::PropagateWritingModeAndDirectionFromBody() {
+ // Will be propagated in HTMLHtmlElement::AttachLayoutTree().
+ if (NeedsReattachLayoutTree())
+ 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)) {
+ layout_object->SetStyle(CreateLayoutStyle(*style, *propagated_style));
+ }
+}
+
+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 66abdee9384..a9054ded91e 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
@@ -38,12 +38,16 @@ class CORE_EXPORT HTMLHtmlElement final : public HTMLElement {
void InsertedByParser();
bool HasNonInBodyInsertionMode() const override { return true; }
+ void PropagateWritingModeAndDirectionFromBody();
+ scoped_refptr<const ComputedStyle> LayoutStyleForElement(
+ scoped_refptr<const ComputedStyle> style);
private:
void MaybeSetupApplicationCache();
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 81677263fcc..ec017801693 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_html_iframe_element.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc b/chromium/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
index 4b823fca496..e56d310446a 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element_sandbox.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element_sandbox.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -27,11 +28,24 @@ const char* const kSupportedSandboxTokens[] = {
"allow-top-navigation-by-user-activation",
"allow-downloads-without-user-activation"};
+// TODO (http://crbug.com/989663) move this into |kSupportedSandboxTokens| when
+// feature flag is enabled by default.
+constexpr char kStorageAccessAPISandboxToken[] =
+ "allow-storage-access-by-user-activation";
+
bool IsTokenSupported(const AtomicString& token) {
for (const char* supported_token : kSupportedSandboxTokens) {
if (token == supported_token)
return true;
}
+
+ // The Storage Access API and corresponding sandbox token is behind the
+ // |StorageAccessAPI| runtimeflag. Only check this token if
+ // the feature is enabled.
+ if (RuntimeEnabledFeatures::StorageAccessAPIEnabled() &&
+ (token == kStorageAccessAPISandboxToken)) {
+ return true;
+ }
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
index 4bb966fb236..031ca8bd1b5 100644
--- a/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
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 cc5dedb738e..c7732687211 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
@@ -22,6 +22,8 @@
*/
#include "third_party/blink/renderer/core/html/html_image_element.h"
+
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
@@ -326,7 +328,7 @@ ImageCandidate HTMLImageElement::FindBestFitImageFromPictureParent() {
DCHECK(IsMainThread());
Node* parent = parentNode();
source_ = nullptr;
- if (!parent || !IsHTMLPictureElement(*parent))
+ if (!parent || !IsA<HTMLPictureElement>(*parent))
return ImageCandidate();
for (Node* child = parent->firstChild(); child;
child = child->nextSibling()) {
@@ -416,7 +418,7 @@ Node::InsertionNotificationRequest HTMLImageElement::InsertedInto(
if (listener_)
GetDocument().GetMediaQueryMatcher().AddViewportListener(listener_);
bool was_added_to_picture_parent = false;
- if (auto* picture_parent = ToHTMLPictureElementOrNull(parentNode())) {
+ if (auto* picture_parent = DynamicTo<HTMLPictureElement>(parentNode())) {
picture_parent->AddListenerToSourceChildren();
was_added_to_picture_parent = picture_parent == insertion_point;
}
@@ -444,7 +446,7 @@ void HTMLImageElement::RemovedFrom(ContainerNode& insertion_point) {
ResetFormOwner();
if (listener_) {
GetDocument().GetMediaQueryMatcher().RemoveViewportListener(listener_);
- if (auto* picture_parent = ToHTMLPictureElementOrNull(parentNode()))
+ if (auto* picture_parent = DynamicTo<HTMLPictureElement>(parentNode()))
picture_parent->RemoveListenerFromSourceChildren();
}
HTMLElement::RemovedFrom(insertion_point);
@@ -456,6 +458,7 @@ unsigned HTMLImageElement::width() {
if (!GetLayoutObject()) {
// check the attribute first for an explicit pixel value
+ // TODO(cbiesinger): The attribute could be a float or percentage value...
unsigned width = 0;
if (ParseHTMLNonNegativeInteger(getAttribute(kWidthAttr), width))
return width;
@@ -477,6 +480,7 @@ unsigned HTMLImageElement::height() {
if (!GetLayoutObject()) {
// check the attribute first for an explicit pixel value
+ // TODO(cbiesinger): The attribute could be a float or percentage value...
unsigned height = 0;
if (ParseHTMLNonNegativeInteger(getAttribute(kHeightAttr), height))
return height;
@@ -622,9 +626,9 @@ bool HTMLImageElement::complete() const {
}
void HTMLImageElement::DidMoveToNewDocument(Document& old_document) {
- SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError);
GetImageLoader().ElementDidMoveToNewDocument();
HTMLElement::DidMoveToNewDocument(old_document);
+ SelectSourceURL(ImageLoader::kUpdateIgnorePreviousError);
}
bool HTMLImageElement::IsServerMap() const {
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 6fbf1efbc50..fa619dfe522 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
@@ -113,16 +113,12 @@ class ImageFallbackContentBuilder {
} // namespace
void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) {
- ShadowRoot& root = element.EnsureUserAgentShadowRoot();
+ Document& document = element.GetDocument();
- auto* container =
- MakeGarbageCollected<HTMLSpanElement>(element.GetDocument());
- root.AppendChild(container);
+ auto* container = MakeGarbageCollected<HTMLSpanElement>(document);
container->setAttribute(kIdAttr, AtomicString("alttext-container"));
- auto* broken_image =
- MakeGarbageCollected<HTMLImageElement>(element.GetDocument());
- container->AppendChild(broken_image);
+ auto* broken_image = MakeGarbageCollected<HTMLImageElement>(document);
broken_image->SetIsFallbackImage();
broken_image->setAttribute(kIdAttr, AtomicString("alttext-image"));
broken_image->setAttribute(kWidthAttr, AtomicString("16"));
@@ -130,14 +126,16 @@ void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) {
broken_image->setAttribute(kAlignAttr, AtomicString("left"));
broken_image->SetInlineStyleProperty(CSSPropertyID::kMargin, 0,
CSSPrimitiveValue::UnitType::kPixels);
+ container->AppendChild(broken_image);
- auto* alt_text = MakeGarbageCollected<HTMLSpanElement>(element.GetDocument());
- container->AppendChild(alt_text);
+ auto* alt_text = MakeGarbageCollected<HTMLSpanElement>(document);
alt_text->setAttribute(kIdAttr, AtomicString("alttext"));
- Text* text =
- Text::Create(element.GetDocument(), To<HTMLElement>(element).AltText());
+ auto* text = Text::Create(document, To<HTMLElement>(element).AltText());
alt_text->AppendChild(text);
+ container->AppendChild(alt_text);
+
+ element.EnsureUserAgentShadowRoot().AppendChild(container);
}
scoped_refptr<ComputedStyle> HTMLImageFallbackHelper::CustomStyleForAltText(
diff --git a/chromium/third_party/blink/renderer/core/html/html_li_element.cc b/chromium/third_party/blink/renderer/core/html/html_li_element.cc
index e084d98efc2..eaed1930814 100644
--- a/chromium/third_party/blink/renderer/core/html/html_li_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_li_element.cc
@@ -102,7 +102,7 @@ void HTMLLIElement::AttachLayoutTree(AttachContext& context) {
current = LayoutTreeBuilderTraversal::ParentElement(*current);
if (!current)
break;
- if (IsHTMLUListElement(*current) || IsHTMLOListElement(*current))
+ if (IsHTMLUListElement(*current) || IsA<HTMLOListElement>(*current))
list_node = current;
}
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 e763d450bee..e8713d5a474 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
@@ -202,8 +202,8 @@ Length HTMLMetaElement::ParseViewportValueAsLength(Document* document,
return Length(); // auto
if (document && document->GetPage()) {
- value =
- document->GetPage()->GetChromeClient().WindowToViewportScalar(value);
+ value = document->GetPage()->GetChromeClient().WindowToViewportScalar(
+ document->GetFrame(), value);
}
return Length::Fixed(ClampLengthValue(value));
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
index c1731470a63..11fcd1167a4 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -55,8 +55,7 @@ class HTMLMetaElementTest : public PageTestBase,
}
void SetColorScheme(const AtomicString& content) {
- HTMLMetaElement* meta =
- ToHTMLMetaElement(GetDocument().head()->firstChild());
+ auto* meta = To<HTMLMetaElement>(GetDocument().head()->firstChild());
ASSERT_TRUE(meta);
meta->setAttribute(html_names::kContentAttr, content);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_meter_element.cc b/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
index fb36660931a..be1ba8f145e 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
@@ -182,7 +182,15 @@ void HTMLMeterElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
value_ = MakeGarbageCollected<HTMLDivElement>(GetDocument());
UpdateValueAppearance(0);
- bar->AppendChild(value_);
+
+ if (RuntimeEnabledFeatures::FormControlsRefreshEnabled()) {
+ auto* clip = MakeGarbageCollected<HTMLDivElement>(GetDocument());
+ clip->SetShadowPseudoId(AtomicString("-internal-meter-clip"));
+ bar->AppendChild(clip);
+ clip->AppendChild(value_);
+ } else {
+ bar->AppendChild(value_);
+ }
inner->AppendChild(bar);
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element.cc b/chromium/third_party/blink/renderer/core/html/html_object_element.cc
index d60738d8bfd..cd7aa2be60f 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element.cc
@@ -431,6 +431,21 @@ void HTMLObjectElement::AssociateWith(HTMLFormElement* form) {
AssociateByParser(form);
}
+bool HTMLObjectElement::DidFinishLoading() const {
+ if (!isConnected())
+ return false;
+ if (OwnedPlugin())
+ return true;
+ if (auto* frame = ContentFrame()) {
+ if (!frame->IsLoading())
+ return true;
+ }
+ if (ImageLoader() && !HasPendingActivity() && IsImageType())
+ return true;
+
+ return UseFallbackContent();
+}
+
const HTMLObjectElement* ToHTMLObjectElementFromListedElement(
const ListedElement* element) {
SECURITY_DCHECK(!element || !element->IsFormControlElement());
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element.h b/chromium/third_party/blink/renderer/core/html/html_object_element.h
index d3421468ad2..ecd9302ef14 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element.h
@@ -89,6 +89,10 @@ class CORE_EXPORT HTMLObjectElement final : public HTMLPlugInElement,
FormAssociated* ToFormAssociatedOrNull() override { return this; }
void AssociateWith(HTMLFormElement*) override;
+ // Returns true if this object started to load something, and finished
+ // the loading regardless of success or failure.
+ bool DidFinishLoading() const;
+
private:
void ParseAttribute(const AttributeModificationParams&) override;
bool IsPresentationAttribute(const QualifiedName&) const override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_object_element_test.cc
index 541fd72f1ca..a36f03b203f 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element_test.cc
@@ -42,7 +42,7 @@ TEST_F(HTMLObjectElementTest, FallbackRecalcForReattach) {
object->RenderFallbackContent(nullptr);
GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
GetDocument().GetStyleEngine().RecalcStyle();
- EXPECT_TRUE(IsHTMLSlotElement(slot));
+ EXPECT_TRUE(IsA<HTMLSlotElement>(slot));
EXPECT_TRUE(object->UseFallbackContent());
EXPECT_TRUE(object->GetComputedStyle());
EXPECT_TRUE(slot->GetComputedStyle());
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 c153491d9fe..8ee6971d8eb 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
@@ -9,6 +9,7 @@ interface mixin HTMLOrForeignElement {
[SameObject, PerWorldBindings] readonly attribute DOMStringMap dataset;
[CEReactions] attribute DOMString nonce;
+ [CEReactions, Reflect] attribute boolean autofocus;
[Affects=Nothing, CEReactions, CustomElementCallbacks] 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 52dba9cf712..39e585146cd 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
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
@@ -52,6 +53,7 @@
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.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/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_from_url.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -580,6 +582,16 @@ bool HTMLPlugInElement::RequestObject(const PluginParameters& plugin_params) {
ResetInstance();
if (object_type == ObjectContentType::kFrame ||
object_type == ObjectContentType::kImage || handled_externally) {
+ if (object_type == ObjectContentType::kFrame) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kPluginElementLoadedDocument);
+ } else if (object_type == ObjectContentType::kImage) {
+ UseCounter::Count(GetDocument(), WebFeature::kPluginElementLoadedImage);
+ } else {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kPluginElementLoadedExternal);
+ }
+
if (ContentFrame() && ContentFrame()->IsRemoteFrame()) {
// During lazy reattaching, the plugin element loses EmbeddedContentView.
// Since the ContentFrame() is not torn down the options here are to
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 7d191999bc3..b09c23dc2dc 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
@@ -28,7 +28,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/create_element_flags.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/platform/bindings/shared_persistent.h"
#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/html_progress_element.cc b/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
index 40dbeb8df2c..7847ce948ef 100644
--- a/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/shadow/progress_shadow_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -55,7 +56,7 @@ LayoutObject* HTMLProgressElement::CreateLayoutObject(
}
UseCounter::Count(GetDocument(),
WebFeature::kProgressElementWithProgressBarAppearance);
- return new LayoutProgress(this);
+ return LayoutObjectFactory::CreateProgress(this, style, legacy);
}
LayoutProgress* HTMLProgressElement::GetLayoutProgress() const {
diff --git a/chromium/third_party/blink/renderer/core/html/html_progress_element.h b/chromium/third_party/blink/renderer/core/html/html_progress_element.h
index 3b7dab2f329..1473489db2a 100644
--- a/chromium/third_party/blink/renderer/core/html/html_progress_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_progress_element.h
@@ -56,7 +56,6 @@ class CORE_EXPORT HTMLProgressElement final : public HTMLElement {
bool AreAuthorShadowsAllowed() const override { return false; }
bool ShouldAppearIndeterminate() const override;
bool IsLabelable() const override { return true; }
- bool TypeShouldForceLegacyLayout() const final { return true; }
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
LayoutProgress* GetLayoutProgress() const;
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element.cc b/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
index a8d9f87d503..e302289203c 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -74,7 +74,8 @@ HTMLSlotElement* HTMLSlotElement::CreateUserAgentCustomAssignSlot(
HTMLSlotElement::HTMLSlotElement(Document& document)
: HTMLElement(kSlotTag, document) {
UseCounter::Count(document, WebFeature::kHTMLSlotElement);
- SetHasCustomStyleCallbacks();
+ if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())
+ SetHasCustomStyleCallbacks();
}
// static
@@ -384,6 +385,7 @@ void HTMLSlotElement::RemovedFrom(ContainerNode& insertion_point) {
}
void HTMLSlotElement::DidRecalcStyle(const StyleRecalcChange change) {
+ DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled());
if (!change.RecalcChildren())
return;
for (auto& node : assigned_nodes_) {
@@ -396,6 +398,22 @@ void HTMLSlotElement::DidRecalcStyle(const StyleRecalcChange change) {
}
}
+void HTMLSlotElement::RecalcStyleForSlotChildren(
+ const StyleRecalcChange change) {
+ if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
+ RecalcDescendantStyles(change);
+ return;
+ }
+ for (auto& node : flat_tree_children_) {
+ if (!change.TraverseChild(*node))
+ continue;
+ if (auto* element = DynamicTo<Element>(node.Get()))
+ element->RecalcStyle(change);
+ else if (auto* text_node = DynamicTo<Text>(node.Get()))
+ text_node->RecalcTextStyle(change);
+ }
+}
+
void HTMLSlotElement::NotifySlottedNodesOfFlatTreeChangeByDynamicProgramming(
const HeapVector<Member<Node>>& old_slotted,
const HeapVector<Member<Node>>& new_slotted) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element.h b/chromium/third_party/blink/renderer/core/html/html_slot_element.h
index 89dc1d55577..42c9f0e7733 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element.h
@@ -104,6 +104,8 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
static AtomicString NormalizeSlotName(const AtomicString&);
+ void RecalcStyleForSlotChildren(const StyleRecalcChange);
+
// For User-Agent Shadow DOM
static const AtomicString& UserAgentCustomAssignSlotName();
static const AtomicString& UserAgentDefaultSlotName();
@@ -200,7 +202,7 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
inline const HTMLSlotElement* ToHTMLSlotElementIfSupportsAssignmentOrNull(
const Node& node) {
- if (auto* slot = ToHTMLSlotElementOrNull(node)) {
+ if (auto* slot = DynamicTo<HTMLSlotElement>(node)) {
if (slot->SupportsAssignment())
return slot;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_source_element.cc b/chromium/third_party/blink/renderer/core/html/html_source_element.cc
index ef77c39bcf3..ff29f8c2cf5 100644
--- a/chromium/third_party/blink/renderer/core/html/html_source_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_source_element.cc
@@ -100,8 +100,13 @@ Node::InsertionNotificationRequest HTMLSourceElement::InsertedInto(
Element* parent = parentElement();
if (auto* media = ToHTMLMediaElementOrNull(parent))
media->SourceWasAdded(this);
- if (parent == insertion_point && IsHTMLPictureElement(parent))
- ToHTMLPictureElement(parent)->SourceOrMediaChanged();
+
+ auto* html_picture_element = parent == insertion_point
+ ? DynamicTo<HTMLPictureElement>(parent)
+ : nullptr;
+ if (html_picture_element)
+ html_picture_element->SourceOrMediaChanged();
+
return kInsertionDone;
}
@@ -112,7 +117,7 @@ void HTMLSourceElement::RemovedFrom(ContainerNode& removal_root) {
parent = DynamicTo<Element>(&removal_root);
if (auto* media = ToHTMLMediaElementOrNull(parent))
media->SourceWasRemoved(this);
- if (auto* picture = ToHTMLPictureElementOrNull(parent)) {
+ if (auto* picture = DynamicTo<HTMLPictureElement>(parent)) {
RemoveMediaQueryListListener();
if (was_removed_from_parent)
picture->SourceOrMediaChanged();
@@ -177,13 +182,13 @@ void HTMLSourceElement::ParseAttribute(
CreateMediaQueryList(params.new_value);
if (name == kSrcsetAttr || name == kSizesAttr || name == kMediaAttr ||
name == kTypeAttr) {
- if (auto* picture = ToHTMLPictureElementOrNull(parentElement()))
+ if (auto* picture = DynamicTo<HTMLPictureElement>(parentElement()))
picture->SourceOrMediaChanged();
}
}
void HTMLSourceElement::NotifyMediaQueryChanged() {
- if (auto* picture = ToHTMLPictureElementOrNull(parentElement()))
+ if (auto* picture = DynamicTo<HTMLPictureElement>(parentElement()))
picture->SourceOrMediaChanged();
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_style_element.cc b/chromium/third_party/blink/renderer/core/html/html_style_element.cc
index dc71531e63e..7d060f23f16 100644
--- a/chromium/third_party/blink/renderer/core/html/html_style_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_style_element.cc
@@ -124,8 +124,14 @@ void HTMLStyleElement::NotifyLoadedSheetAndAllCriticalSubresources(
if (fired_load_ && is_load_event)
return;
loaded_sheet_ = is_load_event;
+ // Per the spec this should post on the network task source.
+ // https://html.spec.whatwg.org/multipage/semantics.html#the-style-element
+ // This guarantees that the <style> will be applied before the next <script>
+ // is loaded. Note: this means that for the potential future efforts to
+ // prioritise individual network requests we should ensure that their priority
+ // is lower than of this task.
GetDocument()
- .GetTaskRunner(TaskType::kDOMManipulation)
+ .GetTaskRunner(TaskType::kNetworking)
->PostTask(
FROM_HERE,
WTF::Bind(&HTMLStyleElement::DispatchPendingEvent,
diff --git a/chromium/third_party/blink/renderer/core/html/image_document.cc b/chromium/third_party/blink/renderer/core/html/image_document.cc
index 6947540ca6a..2b580f3e3eb 100644
--- a/chromium/third_party/blink/renderer/core/html/image_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/image_document.cc
@@ -309,7 +309,7 @@ float ImageDocument::Scale() const {
// We want to pretend the viewport is larger when the user has zoomed the
// page in (but not when the zoom is coming from device scale).
const float viewport_zoom =
- view->GetChromeClient()->WindowToViewportScalar(1.f);
+ view->GetChromeClient()->WindowToViewportScalar(GetFrame(), 1.f);
float width_scale = view->Width() / (viewport_zoom * image_size.Width());
float height_scale = view->Height() / (viewport_zoom * image_size.Height());
@@ -352,7 +352,8 @@ void ImageDocument::ImageClicked(int x, int y) {
double scale = Scale();
double device_scale_factor =
- GetFrame()->View()->GetChromeClient()->WindowToViewportScalar(1.f);
+ GetFrame()->View()->GetChromeClient()->WindowToViewportScalar(
+ GetFrame(), 1.f);
float scroll_x = (image_x * device_scale_factor) / scale -
static_cast<float>(GetFrame()->View()->Width()) / 2;
diff --git a/chromium/third_party/blink/renderer/core/html/image_document_test.cc b/chromium/third_party/blink/renderer/core/html/image_document_test.cc
index 23d0f6a24c8..414457e2fda 100644
--- a/chromium/third_party/blink/renderer/core/html/image_document_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/image_document_test.cc
@@ -66,7 +66,7 @@ class WindowToViewportScalingChromeClient : public EmptyChromeClient {
: EmptyChromeClient(), scale_factor_(1.f) {}
void SetScalingFactor(float s) { scale_factor_ = s; }
- float WindowToViewportScalar(const float s) const override {
+ float WindowToViewportScalar(LocalFrame*, const float s) const override {
return s * scale_factor_;
}
@@ -111,6 +111,7 @@ void ImageDocumentTest::CreateDocumentWithoutLoadingImage(int view_width,
DocumentInit init = DocumentInit::Create().WithDocumentLoader(
frame.Loader().GetDocumentLoader());
frame.DomWindow()->InstallNewDocument("image/jpeg", init, false);
+ frame.GetDocument()->SetURL(KURL("http://www.example.com/image.jpg"));
}
void ImageDocumentTest::CreateDocument(int view_width, int view_height) {
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_import.h b/chromium/third_party/blink/renderer/core/html/imports/html_import.h
index 45078adb4ed..cc874f35d79 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_import.h
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_import.h
@@ -43,7 +43,7 @@ class HTMLImportLoader;
// The superclass of HTMLImportTreeRoot and HTMLImportChild
// This represents the import tree data structure.
-class HTMLImport : public GarbageCollectedFinalized<HTMLImport>,
+class HTMLImport : public GarbageCollected<HTMLImport>,
public TreeNode<HTMLImport> {
public:
enum SyncMode { kSync = 0, kAsync = 1 };
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.h b/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.h
index 3034cc534d9..cbae34ab7f2 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.h
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_import_loader.h
@@ -47,10 +47,9 @@ class HTMLImportsController;
// Owning imported Document lifetime. It also implements RawResourceClient
// to feed fetched bytes to the DocumentParser of the imported
// document. HTMLImportLoader is owned by HTMLImportsController.
-class HTMLImportLoader final
- : public GarbageCollectedFinalized<HTMLImportLoader>,
- public RawResourceClient,
- public DocumentParserClient {
+class HTMLImportLoader final : public GarbageCollected<HTMLImportLoader>,
+ public RawResourceClient,
+ public DocumentParserClient {
USING_GARBAGE_COLLECTED_MIXIN(HTMLImportLoader);
public:
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
index 9750e22dadf..eec517758a1 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
@@ -20,8 +20,8 @@ class HTMLFrameOwnerElement;
class ResourceRequest;
class Visitor;
-class LazyLoadFrameObserver
- : public GarbageCollectedFinalized<LazyLoadFrameObserver> {
+class LazyLoadFrameObserver final
+ : public GarbageCollected<LazyLoadFrameObserver> {
public:
// This enum is logged to histograms, so values should not be reordered or
// reused, and it must match the corresponding enum
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
index 73da6322fec..b48d92a8e2f 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
@@ -1151,7 +1151,6 @@ class LazyLoadFramesTest : public SimTest {
settings.SetLazyFrameLoadingDistanceThresholdPx4G(
kLoadingDistanceThresholdPx);
settings.SetLazyLoadEnabled(true);
- settings.SetDataSaverHoldbackWebApi(false);
}
void TearDown() override {
@@ -1426,20 +1425,6 @@ TEST_F(LazyLoadFramesTest, LazyLoadWhenDataSaverDisabledAndRestricted) {
scoped_restrict_automatic_lazy_frame_loading_to_data_saver_for_test_(
true);
- WebView().GetPage()->GetSettings().SetDataSaverHoldbackWebApi(false);
- TestCrossOriginFrameIsImmediatelyLoaded("");
-}
-
-TEST_F(LazyLoadFramesTest, LazyLoadWhenDataSaverEnabledHoldbackAndRestricted) {
- ScopedLazyFrameLoadingForTest scoped_lazy_frame_loading_for_test(true);
- ScopedAutomaticLazyFrameLoadingForTest
- scoped_automatic_lazy_frame_loading_for_test(true);
- ScopedRestrictAutomaticLazyFrameLoadingToDataSaverForTest
- scoped_restrict_automatic_lazy_frame_loading_to_data_saver_for_test_(
- true);
-
- GetNetworkStateNotifier().SetSaveDataEnabledOverride(true);
- WebView().GetPage()->GetSettings().SetDataSaverHoldbackWebApi(true);
TestCrossOriginFrameIsImmediatelyLoaded("");
}
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
index 621bafd8aaf..90e19970bee 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
@@ -52,6 +52,29 @@ int GetLazyImageLoadingViewportDistanceThresholdPx(const Document& document) {
return 0;
}
+int GetFirstKFullyLoadCount(const Document& document) {
+ const Settings* settings = document.GetSettings();
+ if (!settings)
+ return 0;
+
+ switch (GetNetworkStateNotifier().EffectiveType()) {
+ case WebEffectiveConnectionType::kTypeOffline:
+ return 0;
+ case WebEffectiveConnectionType::kTypeUnknown:
+ return settings->GetLazyImageFirstKFullyLoadUnknown();
+ case WebEffectiveConnectionType::kTypeSlow2G:
+ return settings->GetLazyImageFirstKFullyLoadSlow2G();
+ case WebEffectiveConnectionType::kType2G:
+ return settings->GetLazyImageFirstKFullyLoad2G();
+ case WebEffectiveConnectionType::kType3G:
+ return settings->GetLazyImageFirstKFullyLoad3G();
+ case WebEffectiveConnectionType::kType4G:
+ return settings->GetLazyImageFirstKFullyLoad4G();
+ }
+ NOTREACHED();
+ return 0;
+}
+
// Returns if the element or its ancestors are invisible, due to their style or
// attribute or due to themselves not connected to the main document tree.
bool IsElementInInvisibleSubTree(const Element& element) {
@@ -70,9 +93,80 @@ bool IsElementInInvisibleSubTree(const Element& element) {
return false;
}
+void RecordVisibleLoadTimeForImage(
+ const LazyLoadImageObserver::VisibleLoadTimeMetrics&
+ visible_load_time_metrics) {
+ DCHECK(visible_load_time_metrics.has_initial_intersection_been_set);
+ DCHECK(!visible_load_time_metrics.time_when_first_visible.is_null());
+ DCHECK(!visible_load_time_metrics.time_when_first_load_finished.is_null());
+
+ base::TimeDelta visible_load_delay =
+ visible_load_time_metrics.time_when_first_load_finished -
+ visible_load_time_metrics.time_when_first_visible;
+ if (visible_load_delay < base::TimeDelta())
+ visible_load_delay = base::TimeDelta();
+
+ switch (GetNetworkStateNotifier().EffectiveType()) {
+ case WebEffectiveConnectionType::kTypeSlow2G:
+ if (visible_load_time_metrics.is_initially_intersecting) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.Slow2G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.Slow2G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType2G:
+ if (visible_load_time_metrics.is_initially_intersecting) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.2G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.2G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType3G:
+ if (visible_load_time_metrics.is_initially_intersecting) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.3G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.3G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType4G:
+ if (visible_load_time_metrics.is_initially_intersecting) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kTypeUnknown:
+ case WebEffectiveConnectionType::kTypeOffline:
+ // No VisibleLoadTime histograms are recorded for these effective
+ // connection types.
+ break;
+ }
+}
+
} // namespace
-LazyLoadImageObserver::LazyLoadImageObserver() = default;
+LazyLoadImageObserver::LazyLoadImageObserver(const Document& document)
+ : count_remaining_images_fully_loaded_(GetFirstKFullyLoadCount(document)) {}
void LazyLoadImageObserver::StartMonitoringNearViewport(
Document* root_document,
@@ -159,8 +253,9 @@ void LazyLoadImageObserver::StartMonitoringVisibility(
VisibleLoadTimeMetrics& visible_load_time_metrics =
image_element->EnsureVisibleLoadTimeMetrics();
- if (visible_load_time_metrics.has_initial_intersection_been_set) {
- // The element has already been monitored.
+ if (!visible_load_time_metrics.time_when_first_visible.is_null()) {
+ // The time when the image first became visible has already been measured,
+ // so there's no need to monitor the visibility of the image any more.
return;
}
if (!visibility_metrics_observer_) {
@@ -169,128 +264,78 @@ void LazyLoadImageObserver::StartMonitoringVisibility(
WTF::BindRepeating(&LazyLoadImageObserver::OnVisibilityChanged,
WrapWeakPersistent(this)));
}
- visible_load_time_metrics.record_visibility_metrics = true;
visibility_metrics_observer_->observe(image_element);
}
void LazyLoadImageObserver::OnLoadFinished(HTMLImageElement* image_element) {
DCHECK(RuntimeEnabledFeatures::LazyImageVisibleLoadTimeMetricsEnabled());
-
VisibleLoadTimeMetrics& visible_load_time_metrics =
image_element->EnsureVisibleLoadTimeMetrics();
- if (!visible_load_time_metrics.record_visibility_metrics)
+
+ if (!visible_load_time_metrics.time_when_first_load_finished.is_null())
return;
+ visible_load_time_metrics.time_when_first_load_finished =
+ base::TimeTicks::Now();
- visible_load_time_metrics.record_visibility_metrics = false;
- visibility_metrics_observer_->unobserve(image_element);
+ if (visible_load_time_metrics.time_when_first_visible.is_null())
+ return;
- base::TimeDelta visible_load_delay;
- if (!visible_load_time_metrics.time_when_first_visible.is_null()) {
- visible_load_delay = base::TimeTicks::Now() -
- visible_load_time_metrics.time_when_first_visible;
- }
+ RecordVisibleLoadTimeForImage(visible_load_time_metrics);
+}
- switch (GetNetworkStateNotifier().EffectiveType()) {
- case WebEffectiveConnectionType::kTypeSlow2G:
- if (visible_load_time_metrics.is_initially_intersecting) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.Slow2G",
- visible_load_delay);
- } else {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.Slow2G",
- visible_load_delay);
- }
- break;
+void LazyLoadImageObserver::OnVisibilityChanged(
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ DCHECK(!entries.IsEmpty());
- case WebEffectiveConnectionType::kType2G:
- if (visible_load_time_metrics.is_initially_intersecting) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.2G",
- visible_load_delay);
- } else {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.2G",
- visible_load_delay);
- }
- break;
+ for (auto entry : entries) {
+ auto* image_element = ToHTMLImageElementOrNull(entry->target());
+ if (!image_element)
+ continue;
- case WebEffectiveConnectionType::kType3G:
- if (visible_load_time_metrics.is_initially_intersecting) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.3G",
- visible_load_delay);
- } else {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.3G",
- visible_load_delay);
- }
- break;
+ VisibleLoadTimeMetrics& visible_load_time_metrics =
+ image_element->EnsureVisibleLoadTimeMetrics();
+ // The image's visiblity shouldn't still be monitored if the time when the
+ // image first became visible has already been measured.
+ DCHECK(visible_load_time_metrics.time_when_first_visible.is_null());
- case WebEffectiveConnectionType::kType4G:
+ if (!visible_load_time_metrics.has_initial_intersection_been_set) {
+ visible_load_time_metrics.has_initial_intersection_been_set = true;
+ visible_load_time_metrics.is_initially_intersecting =
+ entry->isIntersecting();
+ }
+ if (!entry->isIntersecting())
+ continue;
+
+ visible_load_time_metrics.time_when_first_visible = base::TimeTicks::Now();
+ if (visible_load_time_metrics.time_when_first_load_finished.is_null()) {
+ // Note: If the WebEffectiveConnectionType enum ever gets out of sync
+ // with net::EffectiveConnectionType, then both the AboveTheFold and
+ // BelowTheFold histograms here will have to be updated to record the
+ // sample in terms of net::EffectiveConnectionType instead of
+ // WebEffectiveConnectionType.
if (visible_load_time_metrics.is_initially_intersecting) {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G",
- visible_load_delay);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold",
+ GetNetworkStateNotifier().EffectiveType());
} else {
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G",
- visible_load_delay);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold",
+ GetNetworkStateNotifier().EffectiveType());
}
- break;
+ } else {
+ RecordVisibleLoadTimeForImage(visible_load_time_metrics);
+ }
- case WebEffectiveConnectionType::kTypeUnknown:
- case WebEffectiveConnectionType::kTypeOffline:
- // No VisibleLoadTime histograms are recorded for these effective
- // connection types.
- break;
+ visibility_metrics_observer_->unobserve(image_element);
}
}
-void LazyLoadImageObserver::OnVisibilityChanged(
- const HeapVector<Member<IntersectionObserverEntry>>& entries) {
- DCHECK(!entries.IsEmpty());
-
- for (auto entry : entries) {
- if (auto* image_element = ToHTMLImageElementOrNull(entry->target())) {
- VisibleLoadTimeMetrics& visible_load_time_metrics =
- image_element->EnsureVisibleLoadTimeMetrics();
- if (!visible_load_time_metrics.has_initial_intersection_been_set) {
- visible_load_time_metrics.is_initially_intersecting =
- entry->isIntersecting();
- visible_load_time_metrics.has_initial_intersection_been_set = true;
- }
- if (entry->isIntersecting()) {
- DCHECK(visible_load_time_metrics.time_when_first_visible.is_null());
- visible_load_time_metrics.time_when_first_visible =
- base::TimeTicks::Now();
-
- if (visible_load_time_metrics.record_visibility_metrics &&
- image_element->GetDocument().GetFrame()) {
- // Since the visibility metrics are recorded when the image finishes
- // loading, this means that the image became visible before it
- // finished loading.
-
- // Note: If the WebEffectiveConnectionType enum ever gets out of sync
- // with net::EffectiveConnectionType, then both the AboveTheFold and
- // BelowTheFold histograms here will have to be updated to record the
- // sample in terms of net::EffectiveConnectionType instead of
- // WebEffectiveConnectionType.
- if (visible_load_time_metrics.is_initially_intersecting) {
- UMA_HISTOGRAM_ENUMERATION(
- "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold",
- GetNetworkStateNotifier().EffectiveType());
- } else {
- UMA_HISTOGRAM_ENUMERATION(
- "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold",
- GetNetworkStateNotifier().EffectiveType());
- }
- }
-
- visibility_metrics_observer_->unobserve(image_element);
- }
- }
+bool LazyLoadImageObserver::IsFullyLoadableFirstKImageAndDecrementCount() {
+ if (count_remaining_images_fully_loaded_ > 0) {
+ count_remaining_images_fully_loaded_--;
+ return true;
}
+ return false;
}
void LazyLoadImageObserver::Trace(Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
index d11b8cbea03..36941719432 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer.h
@@ -32,14 +32,14 @@ class LazyLoadImageObserver final
bool is_initially_intersecting = false;
bool has_initial_intersection_been_set = false;
- // True if metrics need to be recorded and has not been recorded yet.
- bool record_visibility_metrics = false;
-
// Set when the image first becomes visible (i.e. appears in the viewport).
base::TimeTicks time_when_first_visible;
+
+ // Set when the first load event is dispatched for the image.
+ base::TimeTicks time_when_first_load_finished;
};
- LazyLoadImageObserver();
+ LazyLoadImageObserver(const Document&);
void StartMonitoringNearViewport(Document*, Element*, DeferralMessage);
void StopMonitoring(Element*);
@@ -47,6 +47,8 @@ class LazyLoadImageObserver final
void StartMonitoringVisibility(Document*, HTMLImageElement*);
void OnLoadFinished(HTMLImageElement*);
+ bool IsFullyLoadableFirstKImageAndDecrementCount();
+
void Trace(Visitor*);
private:
@@ -62,6 +64,9 @@ class LazyLoadImageObserver final
// The intersection observer used to track when the image becomes visible.
Member<IntersectionObserver> visibility_metrics_observer_;
+ // Count of remaining images that can be fully loaded.
+ int count_remaining_images_fully_loaded_ = 0;
+
// Used to show the intervention console message one time only.
bool is_load_event_deferred_intervention_shown_ = false;
bool is_missing_dimension_intervention_shown_ = false;
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
index 0ac94b4f4f9..c3a4c2a479e 100644
--- a/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
@@ -443,6 +443,11 @@ class LazyLoadImagesParamsTest : public SimTest,
settings.SetLazyImageLoadingDistanceThresholdPx4G(700);
settings.SetLazyLoadEnabled(
RuntimeEnabledFeatures::LazyImageLoadingEnabled());
+ settings.SetLazyImageFirstKFullyLoadUnknown(0);
+ settings.SetLazyImageFirstKFullyLoadSlow2G(0);
+ settings.SetLazyImageFirstKFullyLoad2G(0);
+ settings.SetLazyImageFirstKFullyLoad3G(0);
+ settings.SetLazyImageFirstKFullyLoad4G(0);
}
int GetLoadingDistanceThreshold() const {
@@ -850,6 +855,12 @@ class LazyLoadAutomaticImagesTest : public SimTest {
kLoadingDistanceThreshold);
settings.SetLazyLoadEnabled(
RuntimeEnabledFeatures::LazyImageLoadingEnabled());
+ settings.SetLazyImageFirstKFullyLoad4G(0);
+ }
+
+ void SetLazyImageFirstKFullyLoad(int count) {
+ Settings& settings = WebView().GetPage()->GetSettings();
+ settings.SetLazyImageFirstKFullyLoad4G(count);
}
void LoadMainResourceWithImageFarFromViewport(const char* image_attributes) {
@@ -1105,6 +1116,57 @@ TEST_F(LazyLoadAutomaticImagesTest, TinyImageViaStyleWidth11Height1) {
"style='width:11px;height:1px;'");
}
+TEST_F(LazyLoadAutomaticImagesTest, FirstKImagesLoaded) {
+ ScopedLazyImageLoadingMetadataFetchForTest
+ scoped_lazy_image_loading_metadata_fetch_for_test = false;
+ SetLazyImageFirstKFullyLoad(1);
+
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimSubresourceRequest img1("https://example.com/image.png?id=1", "image/png");
+
+ LoadURL("https://example.com/");
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <img src='https://example.com/image.png?id=1'
+ onload='console.log("image id=1 onload");' />
+ <img src='https://example.com/image.png?id=2'
+ onload='console.log("image id=2 onload");' />
+ </body>)HTML",
+ kViewportHeight + kLoadingDistanceThreshold + 100));
+ Compositor().BeginFrame();
+
+ // One image should be loaded fully, even though it is below viewport.
+ img1.Complete(ReadTestImage());
+ ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
+ KURL("https://example.com/image.png?id=1")));
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("image id=1 onload"));
+ EXPECT_FALSE(ConsoleMessages().Contains("image id=2 onload"));
+
+ // Scrolling down should trigger the fetch of the second image.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kLoadingDistanceThreshold + kViewportHeight),
+ kProgrammaticScroll);
+
+ SimSubresourceRequest img2("https://example.com/image.png?id=2", "image/png");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ img2.Complete(ReadTestImage());
+
+ ExpectResourceIsFullImage(GetDocument().Fetcher()->CachedResource(
+ KURL("https://example.com/image.png?id=2")));
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("image id=1 onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("image id=2 onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains(kLazyLoadEventsDeferredMessage));
+}
+
TEST_F(LazyLoadAutomaticImagesTest, JavascriptCreatedImageFarFromViewport) {
SimRequest main_resource("https://example.com/", "text/html");
SimSubresourceRequest image_resource("https://example.com/image.png",
@@ -1389,6 +1451,202 @@ TEST_F(LazyLoadAutomaticImagesTest, LazyLoadDisabledOnReload) {
}
}
+TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageLoadedBeforeVisible) {
+ ScopedLazyImageLoadingMetadataFetchForTest
+ scoped_lazy_image_loading_metadata_fetch_for_test = false;
+ HistogramTester histogram_tester;
+
+ // Since the image is above the fold, ensure that the image starts loading
+ // before it becomes visible. When automatic lazyloading is enabled, the main
+ // way that an above-the-fold image that's relevant to automatic lazyload
+ // (i.e. would have visible load time metrics recorded for it) can be finshed
+ // loading by the time it becomes visible is for it to be fully loaded as one
+ // of the first K images seen by the parser.
+ SetLazyImageFirstKFullyLoad(1);
+
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimSubresourceRequest image_resource("https://example.com/image.png",
+ "image/png");
+
+ LoadURL("https://example.com/");
+ main_resource.Complete(
+ "<body><img src='https://example.com/image.png' /></body>");
+ image_resource.Complete(ReadTestImage());
+
+ // VisibleLoadTime should not have been recorded yet, since the image is not
+ // visible yet.
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 0);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold", 0);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold", 0);
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 0, 1);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 0);
+}
+
+TEST_F(LazyLoadAutomaticImagesTest, AboveTheFoldImageVisibleBeforeLoaded) {
+ ScopedLazyImageLoadingMetadataFetchForTest
+ scoped_lazy_image_loading_metadata_fetch_for_test = false;
+ HistogramTester histogram_tester;
+
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimSubresourceRequest image_resource("https://example.com/image.png",
+ "image/png");
+
+ LoadURL("https://example.com/");
+ main_resource.Complete(
+ "<body><img src='https://example.com/image.png' /></body>");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // VisibleBeforeLoaded should have been recorded immediately when the image
+ // became visible.
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold",
+ static_cast<int>(WebEffectiveConnectionType::kType4G), 1);
+
+ // VisibleLoadTime should not have been recorded yet, since the image is not
+ // finished loading yet.
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 0);
+
+ image_resource.Complete(ReadTestImage());
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold",
+ static_cast<int>(WebEffectiveConnectionType::kType4G), 1);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold", 0);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 1);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 0);
+}
+
+TEST_F(LazyLoadAutomaticImagesTest, BelowTheFoldImageLoadedBeforeVisible) {
+ ScopedLazyImageLoadingMetadataFetchForTest
+ scoped_lazy_image_loading_metadata_fetch_for_test = false;
+ HistogramTester histogram_tester;
+
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body>
+ <div style='height: %dpx;'></div>
+ <img src='https://example.com/image.png' />
+ </body>)HTML",
+ kViewportHeight + kLoadingDistanceThreshold + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ SimSubresourceRequest image_resource("https://example.com/image.png",
+ "image/png");
+
+ // Scroll down such that the image is within kLoadingDistanceThreshold of the
+ // viewport, but isn't visible yet.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 200),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ image_resource.Complete(ReadTestImage());
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // VisibleLoadTime should not have been recorded yet, since the image is not
+ // visible yet.
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 0);
+
+ // Scroll down such that the image is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight + kLoadingDistanceThreshold),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold", 0);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold", 0);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 0);
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 0, 1);
+}
+
+TEST_F(LazyLoadAutomaticImagesTest, BelowTheFoldImageVisibleBeforeLoaded) {
+ ScopedLazyImageLoadingMetadataFetchForTest
+ scoped_lazy_image_loading_metadata_fetch_for_test = false;
+ HistogramTester histogram_tester;
+
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body>
+ <div style='height: %dpx;'></div>
+ <img src='https://example.com/image.png' />
+ </body>)HTML",
+ kViewportHeight + kLoadingDistanceThreshold + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ SimSubresourceRequest image_resource("https://example.com/image.png",
+ "image/png");
+
+ // Scroll down such that the image is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight + kLoadingDistanceThreshold),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // VisibleBeforeLoaded should have been recorded immediately when the image
+ // became visible.
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold",
+ static_cast<int>(WebEffectiveConnectionType::kType4G), 1);
+
+ // VisibleLoadTime should not have been recorded yet, since the image is not
+ // finished loading yet.
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 0);
+
+ image_resource.Complete(ReadTestImage());
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.AboveTheFold", 0);
+ histogram_tester.ExpectUniqueSample(
+ "Blink.VisibleBeforeLoaded.LazyLoadImages.BelowTheFold",
+ static_cast<int>(WebEffectiveConnectionType::kType4G), 1);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.AboveTheFold.4G", 0);
+ histogram_tester.ExpectTotalCount(
+ "Blink.VisibleLoadTime.LazyLoadImages.BelowTheFold.4G", 1);
+}
+
} // namespace
} // namespace blink
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 d98f8b688d0..912368cbf52 100644
--- a/chromium/third_party/blink/renderer/core/html/link_resource.h
+++ b/chromium/third_party/blink/renderer/core/html/link_resource.h
@@ -42,9 +42,7 @@ class Document;
class HTMLLinkElement;
class LocalFrame;
-class CORE_EXPORT LinkResource
- : public GarbageCollectedFinalized<LinkResource> {
-
+class CORE_EXPORT LinkResource : public GarbageCollected<LinkResource> {
public:
enum LinkResourceType { kStyle, kImport, kManifest, kOther };
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 67e4d57add0..4cff54378d2 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
@@ -39,7 +39,7 @@ ListItemOrdinal::ListItemOrdinal()
: type_(kNeedsUpdate), not_in_list_(false), not_in_list_changed_(false) {}
bool ListItemOrdinal::IsList(const Node& node) {
- return IsHTMLUListElement(node) || IsHTMLOListElement(node);
+ return IsHTMLUListElement(node) || IsA<HTMLOListElement>(node);
}
bool ListItemOrdinal::IsListItem(const LayoutObject* layout_object) {
@@ -162,7 +162,7 @@ int ListItemOrdinal::CalcValue(const Node& item_node) const {
return value_;
Node* list = EnclosingList(&item_node);
- HTMLOListElement* o_list_element = ToHTMLOListElementOrNull(list);
+ auto* o_list_element = DynamicTo<HTMLOListElement>(list);
int value_step = 1;
if (o_list_element && o_list_element->IsReversed())
value_step = -1;
@@ -296,7 +296,7 @@ void ListItemOrdinal::ItemInsertedOrRemoved(
CHECK(list_node);
bool is_list_reversed = false;
- if (auto* o_list_element = ToHTMLOListElementOrNull(list_node)) {
+ if (auto* o_list_element = DynamicTo<HTMLOListElement>(list_node)) {
o_list_element->ItemCountChanged();
is_list_reversed = o_list_element->IsReversed();
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/DEPS b/chromium/third_party/blink/renderer/core/html/media/DEPS
index 7e0f6285749..18abf950027 100644
--- a/chromium/third_party/blink/renderer/core/html/media/DEPS
+++ b/chromium/third_party/blink/renderer/core/html/media/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+media/base/logging_override_if_enabled.h",
+ "+media/base/media_switches.h",
]
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h b/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
index a5add0011c7..89d7af81537 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
@@ -49,7 +49,7 @@ class CORE_EXPORT HTMLAudioElement final : public HTMLMediaElement {
// WebMediaPlayerClient implementation.
void MediaRemotingStarted(
const WebString& remote_device_friendly_name) override {}
- void MediaRemotingStopped(WebLocalizedString::Name error_msg) override {}
+ void MediaRemotingStopped(int error_code) override {}
void OnPictureInPictureStateChange() final { NOTREACHED(); }
void ActivateViewportIntersectionMonitoring(bool) final {}
};
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 1c35c3ca476..c513a75167c 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
@@ -31,9 +31,11 @@
#include "base/auto_reset.h"
#include "base/debug/crash_logging.h"
+#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "media/base/logging_override_if_enabled.h"
+#include "media/base/media_switches.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -57,6 +59,7 @@
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/fileapi/url_file_api.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -1165,6 +1168,10 @@ void HTMLMediaElement::LoadResource(const WebMediaPlayerSource& source,
// media element API.
current_src_ = url;
+ // Default this to empty, so that we use |current_src_| unless the player
+ // provides one later.
+ current_src_after_redirects_ = KURL();
+
if (audio_source_node_)
audio_source_node_->OnCurrentSrcChanged(current_src_);
@@ -1188,11 +1195,24 @@ void HTMLMediaElement::LoadResource(const WebMediaPlayerSource& source,
bool attempt_load = true;
media_source_ = HTMLMediaSource::Lookup(url.GetString());
- if (media_source_ && !media_source_->AttachToElement(this)) {
- // Forget our reference to the MediaSource, so we leave it alone
- // while processing remainder of load failure.
- media_source_ = nullptr;
- attempt_load = false;
+ if (media_source_) {
+ if (media_source_->AttachToElement(this)) {
+ // If the associated feature is enabled, auto-revoke the MediaSource
+ // object URL that was used for attachment on successful (start of)
+ // attachment. This can help reduce memory bloat later if the app does not
+ // revoke the object URL explicitly and the object URL was the only
+ // remaining strong reference to an attached HTMLMediaElement+MediaSource
+ // cycle of objects that could otherwise be garbage-collectable.
+ if (base::FeatureList::IsEnabled(
+ media::kRevokeMediaSourceObjectURLOnAttach)) {
+ URLFileAPI::revokeObjectURL(GetExecutionContext(), url.GetString());
+ }
+ } else {
+ // Forget our reference to the MediaSource, so we leave it alone
+ // while processing remainder of load failure.
+ media_source_ = nullptr;
+ attempt_load = false;
+ }
}
bool can_load_resource =
@@ -1442,6 +1462,12 @@ void HTMLMediaElement::TextTrackModeChanged(TextTrack* track) {
if (track->TrackType() == TextTrack::kTrackElement)
track->SetHasBeenConfigured(true);
+ if (track->IsRendered()) {
+ GetDocument().GetStyleEngine().AddTextTrack(track);
+ } else {
+ GetDocument().GetStyleEngine().RemoveTextTrack(track);
+ }
+
ConfigureTextTrackDisplay();
DCHECK(textTracks()->Contains(track));
@@ -1774,6 +1800,13 @@ void HTMLMediaElement::SetReadyState(ReadyState state) {
ready_state_ = kHaveCurrentData;
}
+ // If we're transitioning to / past kHaveMetadata, then cache the final URL.
+ if (old_state < kHaveMetadata && new_state >= kHaveMetadata &&
+ web_media_player_) {
+ current_src_after_redirects_ =
+ KURL(web_media_player_->GetSrcAfterRedirects());
+ }
+
if (new_state > ready_state_maximum_)
ready_state_maximum_ = new_state;
@@ -1950,8 +1983,11 @@ bool HTMLMediaElement::SupportsSave() const {
return false;
}
+ // Get the URL that we'll use for downloading.
+ const KURL url = downloadURL();
+
// URLs that lead to nowhere are ignored.
- if (current_src_.IsNull() || current_src_.IsEmpty())
+ if (url.IsNull() || url.IsEmpty())
return false;
// If we have no source, we can't download.
@@ -1959,7 +1995,7 @@ bool HTMLMediaElement::SupportsSave() const {
return false;
// It is not useful to offer a save feature on local files.
- if (current_src_.IsLocalFile())
+ if (url.IsLocalFile())
return false;
// MediaStream can't be downloaded.
@@ -1971,7 +2007,7 @@ bool HTMLMediaElement::SupportsSave() const {
return false;
// HLS stream shouldn't have a download button.
- if (IsHLSURL(current_src_))
+ if (IsHLSURL(url))
return false;
// Infinite streams don't have a clear end at which to finish the download.
@@ -4103,22 +4139,6 @@ void HTMLMediaElement::OnRemovedFromDocumentTimerFired(TimerBase*) {
PauseInternal();
}
-void HTMLMediaElement::DefaultEventHandler(Event& event) {
- if (event.IsKeyboardEvent() && event.type() == event_type_names::kKeyup &&
- ShouldShowControls()) {
- // TODO(bokan): Cleanup magic numbers once https://crbug.com/949766 lands.
- const int key =
- static_cast<int>(ToKeyboardEvent(event).KeyEvent()->dom_key);
- if (key == 0x00200310) {
- // We need to handle the event here rather than in
- // MediaControlsTouchlessImpl because it is not sent to JS.
- GetMediaControls()->ShowContextMenu();
- event.SetDefaultHandled();
- }
- }
- HTMLElement::DefaultEventHandler(event);
-}
-
void HTMLMediaElement::AudioSourceProviderImpl::Wrap(
scoped_refptr<WebAudioSourceProviderImpl> provider) {
MutexLocker locker(provide_input_lock);
@@ -4192,10 +4212,10 @@ WebMediaPlayer::DisplayType HTMLMediaElement::DisplayType() const {
}
gfx::ColorSpace HTMLMediaElement::TargetColorSpace() {
- const LocalFrame* frame = GetDocument().GetFrame();
+ LocalFrame* frame = GetDocument().GetFrame();
if (!frame)
return gfx::ColorSpace();
- return frame->GetPage()->GetChromeClient().GetScreenInfo().color_space;
+ return frame->GetPage()->GetChromeClient().GetScreenInfo(*frame).color_space;
}
bool HTMLMediaElement::WasAutoplayInitiated() {
@@ -4221,6 +4241,26 @@ bool HTMLMediaElement::MediaShouldBeOpaque() const {
EffectivePreloadType() != WebMediaPlayer::kPreloadNone;
}
+WebMediaPlayerClient::Features HTMLMediaElement::GetFeatures() {
+ WebMediaPlayerClient::Features features;
+
+ features.id = FastGetAttribute(kIdAttr);
+ features.width = FastGetAttribute(kWidthAttr);
+
+ if (auto* parent = parentElement())
+ features.parent_id = parent->FastGetAttribute(kIdAttr);
+
+ features.alt_text = AltText();
+ features.is_page_visible = GetDocument().IsPageVisible();
+ features.is_in_main_frame = GetDocument().IsInMainFrame();
+
+ const KURL& url = GetDocument().Url();
+ features.url_host = url.Host();
+ features.url_path = url.GetPath();
+
+ return features;
+}
+
STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveNothing,
HTMLMediaElement::kHaveNothing);
STATIC_ASSERT_ENUM(WebMediaPlayer::kReadyStateHaveMetadata,
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 ca75a836dcd..d84c16a08e5 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
@@ -144,6 +144,17 @@ class CORE_EXPORT HTMLMediaElement
void SetSrc(const AtomicString&);
void SetSrc(const USVStringOrTrustedURL&, ExceptionState&);
const KURL& currentSrc() const { return current_src_; }
+
+ // Return the URL to be used for downloading the media.
+ const KURL& downloadURL() const {
+ // If we didn't get a redirected URL from the player, then use the original.
+ if (current_src_after_redirects_.IsNull() ||
+ current_src_after_redirects_.IsEmpty()) {
+ return currentSrc();
+ }
+ return current_src_after_redirects_;
+ }
+
void SetSrcObject(MediaStreamDescriptor*);
MediaStreamDescriptor* GetSrcObject() const { return src_object_.Get(); }
@@ -556,7 +567,7 @@ class CORE_EXPORT HTMLMediaElement
void OnRemovedFromDocumentTimerFired(TimerBase*);
- void DefaultEventHandler(Event&) override;
+ Features GetFeatures() override;
TaskRunnerTimer<HTMLMediaElement> load_timer_;
TaskRunnerTimer<HTMLMediaElement> progress_event_timer_;
@@ -573,6 +584,7 @@ class CORE_EXPORT HTMLMediaElement
ReadyState ready_state_;
ReadyState ready_state_maximum_;
KURL current_src_;
+ KURL current_src_after_redirects_;
Member<MediaStreamDescriptor> src_object_;
Member<MediaError> error_;
@@ -686,9 +698,8 @@ class CORE_EXPORT HTMLMediaElement
// AudioClientImpl wraps an AudioSourceProviderClient.
// When the audio format is known, Chromium calls setFormat().
- class AudioClientImpl final
- : public GarbageCollectedFinalized<AudioClientImpl>,
- public WebAudioSourceProviderClient {
+ class AudioClientImpl final : public GarbageCollected<AudioClientImpl>,
+ public WebAudioSourceProviderClient {
public:
explicit AudioClientImpl(AudioSourceProviderClient* client)
: client_(client) {}
@@ -735,7 +746,6 @@ class CORE_EXPORT HTMLMediaElement
friend class Internals;
friend class TrackDisplayUpdateScope;
friend class MediaControlsImplTest;
- friend class MediaControlsTouchlessImplTest;
friend class HTMLMediaElementTest;
friend class HTMLMediaElementEventListenersTest;
friend class HTMLVideoElement;
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 2a0ab1d1d5d..e2688d31bb5 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
@@ -45,6 +45,8 @@ class MockWebMediaPlayer : public EmptyWebMediaPlayer {
const blink::WebMediaPlayerSource& source,
CorsMode cors_mode));
MOCK_CONST_METHOD0(DidLazyLoad, bool());
+
+ MOCK_METHOD0(GetSrcAfterRedirects, GURL());
};
class WebMediaStubLocalFrameClient : public EmptyLocalFrameClient {
@@ -519,4 +521,32 @@ TEST_P(HTMLMediaElementTest, GcMarkingNoAllocHasActivity) {
Media()->HasPendingActivity();
}
+TEST_P(HTMLMediaElementTest, CapturesRedirectedSrc) {
+ // Verify that the element captures the redirected URL.
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+ Media()->Play();
+ test::RunPendingTasks();
+
+ // Should start at the original.
+ EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
+
+ GURL redirected_url("https://redirected.com");
+ EXPECT_CALL(*MockMediaPlayer(), GetSrcAfterRedirects())
+ .WillRepeatedly(Return(redirected_url));
+ SetReadyState(HTMLMediaElement::kHaveFutureData);
+
+ EXPECT_EQ(Media()->downloadURL(), redirected_url);
+}
+
+TEST_P(HTMLMediaElementTest, EmptyRedirectedSrcUsesOriginal) {
+ // If the player returns an empty URL for the redirected src, then the element
+ // should continue using currentSrc().
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+ Media()->Play();
+ test::RunPendingTasks();
+ EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
+ SetReadyState(HTMLMediaElement::kHaveFutureData);
+ EXPECT_EQ(Media()->downloadURL(), Media()->currentSrc());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_source.h b/chromium/third_party/blink/renderer/core/html/media/html_media_source.h
index a759c7b8def..4e89100cea4 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_source.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_source.h
@@ -74,11 +74,8 @@ class CORE_EXPORT HTMLMediaSource : public URLRegistrable,
// The JavaScript exposed version of this is Buffered.
virtual WebTimeRanges BufferedInternal() const = 0;
- // The JavaScript exposed version of this is Seekable.
virtual WebTimeRanges SeekableInternal() const = 0;
-
virtual TimeRanges* Buffered() const = 0;
- virtual TimeRanges* Seekable() const = 0;
virtual void OnTrackChanged(TrackBase*) = 0;
// URLRegistrable
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 de3be31f9f9..37abcf522ee 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
@@ -29,6 +29,7 @@
#include "base/bind_helpers.h"
#include "cc/paint/paint_canvas.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
@@ -356,6 +357,7 @@ void HTMLVideoElement::ActivateViewportIntersectionMonitoring(bool activate) {
{}, {kMostlyFillViewportThreshold}, &(GetDocument()),
WTF::BindRepeating(&HTMLVideoElement::OnViewportIntersectionChanged,
WrapWeakPersistent(this)),
+ IntersectionObserver::kDeliverDuringPostLifecycleSteps,
IntersectionObserver::kFractionOfRoot);
viewport_intersection_observer_->observe(this);
} else if (!activate && viewport_intersection_observer_) {
@@ -701,10 +703,9 @@ void HTMLVideoElement::MediaRemotingStarted(
remoting_interstitial_->Show(remote_device_friendly_name);
}
-void HTMLVideoElement::MediaRemotingStopped(
- WebLocalizedString::Name error_msg) {
+void HTMLVideoElement::MediaRemotingStopped(int error_code) {
if (remoting_interstitial_)
- remoting_interstitial_->Hide(error_msg);
+ remoting_interstitial_->Hide(error_code);
}
bool HTMLVideoElement::SupportsPictureInPicture() const {
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 b0211dd1095..0e903b1552a 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
@@ -184,7 +184,7 @@ class CORE_EXPORT HTMLVideoElement final : public HTMLMediaElement,
void MediaRemotingStarted(const WebString& remote_device_friendly_name) final;
bool SupportsPictureInPicture() const final;
- void MediaRemotingStopped(WebLocalizedString::Name error_msg) final;
+ void MediaRemotingStopped(int error_code) final;
WebMediaPlayer::DisplayType DisplayType() const final;
bool IsInAutoPIP() const final;
void OnPictureInPictureStateChange() final;
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc b/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
index a62627c5729..83f44168c69 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
@@ -194,7 +194,7 @@ TEST_F(HTMLVideoElementPersistentTest, internalPseudoClassOnlyUAStyleSheet) {
DummyExceptionStateForTesting exception_state;
- EXPECT_FALSE(DivElement()->matches(":-webkit-full-screen"));
+ EXPECT_FALSE(DivElement()->matches(":fullscreen"));
EXPECT_FALSE(DivElement()->matches(":-internal-video-persistent-ancestor",
exception_state));
EXPECT_TRUE(exception_state.HadException());
@@ -220,7 +220,7 @@ TEST_F(HTMLVideoElementPersistentTest, internalPseudoClassOnlyUAStyleSheet) {
EXPECT_TRUE(VideoElement()->ContainsPersistentVideo());
// The :internal-* rules apply only from the UA stylesheet.
- EXPECT_TRUE(DivElement()->matches(":-webkit-full-screen"));
+ EXPECT_TRUE(DivElement()->matches(":fullscreen"));
EXPECT_FALSE(DivElement()->matches(":-internal-video-persistent-ancestor",
exception_state));
EXPECT_TRUE(exception_state.HadException());
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_controls.h b/chromium/third_party/blink/renderer/core/html/media/media_controls.h
index 057adfad536..57c9b42217f 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_controls.h
+++ b/chromium/third_party/blink/renderer/core/html/media/media_controls.h
@@ -77,10 +77,6 @@ class CORE_EXPORT MediaControls : public GarbageCollectedMixin {
virtual HTMLDivElement* PanelElement() = 0;
virtual void OnMediaControlsEnabledChange() = 0;
- // This is required for showing a context menu upon pressing right soft key
- // on a touchless device.
- virtual void ShowContextMenu() = 0;
-
void Trace(Visitor*) override;
private:
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc b/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
index 78f797a93ce..79fdf9fa33b 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
@@ -51,6 +51,7 @@ void MediaCustomControlsFullscreenDetector::Attach() {
WTF::BindRepeating(
&MediaCustomControlsFullscreenDetector::OnIntersectionChanged,
WrapWeakPersistent(this)),
+ IntersectionObserver::kDeliverDuringPostLifecycleSteps,
IntersectionObserver::kFractionOfTarget, 0, false, true);
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc b/chromium/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
index 125842c3c4d..996276d27d7 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/html/media/media_element_parser_helpers.h"
+
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.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"
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
index bc88fa24dfa..d255d1bdc7b 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/html/media/media_remoting_interstitial.h"
-#include "third_party/blink/public/platform/web_localized_string.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -65,13 +65,12 @@ void MediaRemotingInterstitial::Show(
if (remote_device_friendly_name.IsEmpty()) {
cast_text_message_->setInnerText(
GetVideoElement().GetLocale().QueryString(
- WebLocalizedString::kMediaRemotingCastToUnknownDeviceText),
+ IDS_MEDIA_REMOTING_CAST_TO_UNKNOWN_DEVICE_TEXT),
ASSERT_NO_EXCEPTION);
} else {
cast_text_message_->setInnerText(
- GetVideoElement().GetLocale().QueryString(
- WebLocalizedString::kMediaRemotingCastText,
- remote_device_friendly_name),
+ GetVideoElement().GetLocale().QueryString(IDS_MEDIA_REMOTING_CAST_TEXT,
+ remote_device_friendly_name),
ASSERT_NO_EXCEPTION);
}
if (toggle_interstitial_timer_.IsActive())
@@ -84,18 +83,18 @@ void MediaRemotingInterstitial::Show(
FROM_HERE);
}
-void MediaRemotingInterstitial::Hide(WebLocalizedString::Name error_msg) {
+void MediaRemotingInterstitial::Hide(int error_code) {
if (!IsVisible())
return;
if (toggle_interstitial_timer_.IsActive())
toggle_interstitial_timer_.Stop();
- if (error_msg == WebLocalizedString::kMediaRemotingStopNoText) {
+ if (error_code == WebMediaPlayerClient::kMediaRemotingStopNoText) {
state_ = HIDDEN;
} else {
- String stop_text = GetVideoElement().GetLocale().QueryString(
- WebLocalizedString::kMediaRemotingStopText);
- if (error_msg != WebLocalizedString::kMediaRemotingStopText) {
- stop_text = GetVideoElement().GetLocale().QueryString(error_msg) + ", " +
+ String stop_text =
+ GetVideoElement().GetLocale().QueryString(IDS_MEDIA_REMOTING_STOP_TEXT);
+ if (error_code != IDS_MEDIA_REMOTING_STOP_TEXT) {
+ stop_text = GetVideoElement().GetLocale().QueryString(error_code) + ", " +
stop_text;
}
toast_message_->setInnerText(stop_text, ASSERT_NO_EXCEPTION);
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
index 6f0e77fa94e..c00cfa0609a 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
+++ b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_
-#include "third_party/blink/public/platform/web_localized_string.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -38,8 +38,8 @@ class MediaRemotingInterstitial final : public HTMLDivElement {
void Show(const WebString& remote_device_friendly_name);
// Hide Media Remoting interstitial. A text message may be displayed for five
- // seconds according to |error_msg|.
- void Hide(WebLocalizedString::Name error_msg);
+ // seconds according to the IDS string associated with the given |error_code|.
+ void Hide(int error_code);
void OnPosterImageChanged();
diff --git a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
index 5159cdf2528..e9541ec8a1d 100644
--- a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h"
#include "cc/layers/layer.h"
-#include "third_party/blink/public/platform/web_localized_string.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
@@ -81,7 +81,7 @@ PictureInPictureInterstitial::PictureInPictureInterstitial(
AtomicString("-internal-picture-in-picture-interstitial-message"));
message_element_->setInnerText(
GetVideoElement().GetLocale().QueryString(
- WebLocalizedString::kPictureInPictureInterstitialText),
+ IDS_MEDIA_PICTURE_IN_PICTURE_INTERSTITIAL_TEXT),
ASSERT_NO_EXCEPTION);
ParserAppendChild(message_element_);
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc b/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
index 89ee4226067..ba2cccdf34f 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_auto_fullscreen_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -12,6 +13,7 @@
#include "third_party/blink/renderer/core/html/media/autoplay_policy.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/testing/fake_local_frame_host.h"
#include "third_party/blink/renderer/core/testing/wait_for_event.h"
#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -19,19 +21,13 @@
namespace blink {
-class VideoAutoFullscreenFrameClient
- : public frame_test_helpers::TestWebFrameClient {
+// Override a FakeLocalFrameHost so that we can enter and exit the fullscreen
+// on the appropriate request calls.
+class VideoAutoFullscreenFrameHost : public FakeLocalFrameHost {
public:
- WebMediaPlayer* CreateMediaPlayer(const WebMediaPlayerSource&,
- WebMediaPlayerClient*,
- blink::MediaInspectorContext*,
- WebMediaPlayerEncryptedMediaClient*,
- WebContentDecryptionModule*,
- const WebString& sink_id) final {
- return new EmptyWebMediaPlayer();
- }
+ VideoAutoFullscreenFrameHost() = default;
- void EnterFullscreen(const blink::WebFullscreenOptions&) final {
+ void EnterFullscreen(mojom::blink::FullscreenOptionsPtr options) override {
Thread::Current()->GetTaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(
@@ -39,7 +35,7 @@ class VideoAutoFullscreenFrameClient
WTF::Unretained(web_widget_)));
}
- void ExitFullscreen() final {
+ void ExitFullscreen() override {
Thread::Current()->GetTaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(
@@ -53,12 +49,27 @@ class VideoAutoFullscreenFrameClient
WebWidget* web_widget_;
};
+class VideoAutoFullscreenFrameClient
+ : public frame_test_helpers::TestWebFrameClient {
+ public:
+ WebMediaPlayer* CreateMediaPlayer(const WebMediaPlayerSource&,
+ WebMediaPlayerClient*,
+ blink::MediaInspectorContext*,
+ WebMediaPlayerEncryptedMediaClient*,
+ WebContentDecryptionModule*,
+ const WebString& sink_id) final {
+ return new EmptyWebMediaPlayer();
+ }
+};
+
class VideoAutoFullscreen : public testing::Test,
private ScopedVideoAutoFullscreenForTest {
public:
VideoAutoFullscreen() : ScopedVideoAutoFullscreenForTest(true) {}
void SetUp() override {
web_view_helper_.Initialize(&web_frame_client_);
+ frame_host_.Init(
+ web_frame_client_.GetRemoteNavigationAssociatedInterfaces());
GetWebView()->GetSettings()->SetAutoplayPolicy(
WebSettings::AutoplayPolicy::kUserGestureRequired);
@@ -68,7 +79,7 @@ class VideoAutoFullscreen : public testing::Test,
video_ = ToHTMLVideoElement(*GetDocument()->QuerySelector("video"));
- web_frame_client_.set_frame_widget(GetWebView()->MainFrameWidget());
+ frame_host_.set_frame_widget(GetWebView()->MainFrameWidget());
}
WebViewImpl* GetWebView() { return web_view_helper_.GetWebView(); }
@@ -83,6 +94,7 @@ class VideoAutoFullscreen : public testing::Test,
private:
Persistent<HTMLVideoElement> video_;
+ VideoAutoFullscreenFrameHost frame_host_;
VideoAutoFullscreenFrameClient web_frame_client_;
frame_test_helpers::WebViewHelper web_view_helper_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_filling_viewport_test.cc b/chromium/third_party/blink/renderer/core/html/media/video_filling_viewport_test.cc
index 6a6814ef01f..2c8002c0f01 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_filling_viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_filling_viewport_test.cc
@@ -68,7 +68,7 @@ TEST_F(VideoFillingViewportTest, MostlyFillingViewport) {
EXPECT_TRUE(IsMostlyFillingViewport(element));
ActivateViewportIntersectionMonitoring(element, false);
- DoCompositeAndPropagate();
+ EXPECT_FALSE(Compositor().NeedsBeginFrame());
EXPECT_FALSE(IsMostlyFillingViewport(element));
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
index eba95c6c818..eebb27cd3c5 100644
--- a/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/video_wake_lock.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/html/media/video_wake_lock.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -115,7 +115,7 @@ void VideoWakeLock::EnsureWakeLockService() {
frame->GetTaskRunner(TaskType::kMediaElementEvent);
mojo::Remote<blink::mojom::blink::WakeLockService> service;
- frame->GetInterfaceProvider().GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
service.BindNewPipeAndPassReceiver(task_runner));
service->GetWakeLock(device::mojom::WakeLockType::kPreventDisplaySleep,
device::mojom::blink::WakeLockReason::kVideoPlayback,
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 148cbc47d53..3908425d036 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
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
@@ -86,16 +87,9 @@ class VideoWakeLockMediaPlayer final : public EmptyWebMediaPlayer {
class VideoWakeLockFrameClient : public test::MediaStubLocalFrameClient {
public:
explicit VideoWakeLockFrameClient(std::unique_ptr<WebMediaPlayer> player)
- : test::MediaStubLocalFrameClient(std::move(player)),
- interface_provider_(new service_manager::InterfaceProvider()) {}
-
- service_manager::InterfaceProvider* GetInterfaceProvider() override {
- return interface_provider_.get();
- }
+ : test::MediaStubLocalFrameClient(std::move(player)) {}
private:
- std::unique_ptr<service_manager::InterfaceProvider> interface_provider_;
-
DISALLOW_COPY_AND_ASSIGN(VideoWakeLockFrameClient);
};
@@ -106,9 +100,7 @@ class VideoWakeLockTest : public PageTestBase {
nullptr, MakeGarbageCollected<VideoWakeLockFrameClient>(
std::make_unique<VideoWakeLockMediaPlayer>()));
- service_manager::InterfaceProvider::TestApi test_api(
- GetFrame().Client()->GetInterfaceProvider());
- test_api.SetBinderForName(
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::PictureInPictureService::Name_,
WTF::BindRepeating(&VideoWakeLockPictureInPictureService::Bind,
WTF::Unretained(&pip_service_)));
@@ -120,6 +112,11 @@ class VideoWakeLockTest : public PageTestBase {
GetPage().SetIsHidden(false, true);
}
+ void TearDown() override {
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::PictureInPictureService::Name_, {});
+ }
+
HTMLVideoElement* Video() const { return video_.Get(); }
VideoWakeLock* GetVideoWakeLock() const { return video_wake_lock_.Get(); }
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 711a66ea407..676cb23a9ac 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
@@ -31,10 +31,10 @@
#include "base/auto_reset.h"
#include "base/numerics/safe_conversions.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"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
@@ -1202,7 +1202,7 @@ void HTMLDocumentParser::DocumentElementAvailable() {
// from extensions. See example callstacks linked from crbug.com/931330.
if (document->Loader()) {
document->Loader()->DidObserveLoadingBehavior(
- kWebLoadingBehaviorAmpDocumentLoaded);
+ kLoadingBehaviorAmpDocumentLoaded);
}
}
if (preloader_)
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
index f7fd1e2683f..e62d0fd78b4 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_element_stack.cc
@@ -168,7 +168,7 @@ void HTMLElementStack::PopAll() {
auto* element = DynamicTo<Element>(node);
if (element) {
element->FinishParsingChildren();
- if (auto* select = ToHTMLSelectElementOrNull(node))
+ if (auto* select = DynamicTo<HTMLSelectElement>(node))
select->SetBlocksFormSubmission(true);
}
top_ = top_->ReleaseNext();
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 d947fcd22ef..9c63198537a 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
@@ -54,8 +54,7 @@ class SpeculationsPumpSession : public NestingLevelIncrementer {
size_t processed_element_tokens_;
};
-class HTMLParserScheduler final
- : public GarbageCollectedFinalized<HTMLParserScheduler> {
+class HTMLParserScheduler final : public GarbageCollected<HTMLParserScheduler> {
public:
HTMLParserScheduler(HTMLDocumentParser*,
scoped_refptr<base::SingleThreadTaskRunner>);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
index fa4f9a9215a..7247ddc7857 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
@@ -61,7 +61,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
media_data.three_d_enabled = true;
media_data.media_type = media_type_names::kScreen;
media_data.strict_mode = true;
- media_data.display_mode = kWebDisplayModeBrowser;
+ media_data.display_mode = blink::mojom::DisplayMode::kBrowser;
MockResourcePreloader preloader;
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 d40e3ab1108..b4699156f62 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
@@ -232,7 +232,7 @@ class HTMLPreloadScannerTest : public PageTestBase {
data.three_d_enabled = true;
data.media_type = media_type_names::kScreen;
data.strict_mode = true;
- data.display_mode = kWebDisplayModeBrowser;
+ data.display_mode = blink::mojom::DisplayMode::kBrowser;
return data;
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.cc b/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.cc
index 458b26d64e7..10556a31f0f 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_resource_preloader.cc
@@ -118,7 +118,7 @@ bool HTMLResourcePreloader::AllowPreloadRequest(PreloadRequest* preload) const {
case ResourceType::kManifest:
case ResourceType::kMock:
return !GetFieldTrialParamByFeatureAsBool(
- features::kLightweightNoStatePrefetch, "skip_other", false);
+ features::kLightweightNoStatePrefetch, "skip_other", true);
case ResourceType::kImage:
return false;
case ResourceType::kCSSStyleSheet:
@@ -133,7 +133,7 @@ bool HTMLResourcePreloader::AllowPreloadRequest(PreloadRequest* preload) const {
// Otherwise, we might skip async/deferred script.
return !GetFieldTrialParamByFeatureAsBool(
features::kLightweightNoStatePrefetch, "skip_async_script",
- false) ||
+ true) ||
preload->DeferOption() == FetchParameters::DeferOption::kNoDefer;
}
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_stack_item.h b/chromium/third_party/blink/renderer/core/html/parser/html_stack_item.h
index d81933a4b70..3d7bc5aa4b3 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_stack_item.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_stack_item.h
@@ -37,7 +37,7 @@ namespace blink {
class ContainerNode;
-class HTMLStackItem : public GarbageCollectedFinalized<HTMLStackItem> {
+class HTMLStackItem final : public GarbageCollected<HTMLStackItem> {
public:
enum ItemType { kItemForContextElement, kItemForDocumentFragmentNode };
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 af7b90d7d28..64dc15e3319 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
@@ -45,8 +45,7 @@ class Element;
class HTMLDocument;
class HTMLDocumentParser;
-class HTMLTreeBuilder final
- : public GarbageCollectedFinalized<HTMLTreeBuilder> {
+class HTMLTreeBuilder final : public GarbageCollected<HTMLTreeBuilder> {
public:
// HTMLTreeBuilder can be created for non-HTMLDocument (XHTMLDocument) from
// editing code.
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
index f28f7f02368..3e9be89476c 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -105,14 +105,8 @@ Resource* PreloadRequest::Start(Document* document) {
}
if (resource_type_ == ResourceType::kImage &&
- params.Url().ProtocolIsInHTTPFamily()) {
- if (const auto* frame = document->Loader()->GetFrame()) {
- if (frame->IsClientLoFiAllowed(params.GetResourceRequest())) {
- params.SetClientLoFiPlaceholder();
- } else if (is_lazy_load_image_enabled_) {
- params.SetLazyImagePlaceholder();
- }
- }
+ params.Url().ProtocolIsInHTTPFamily() && is_lazy_load_image_enabled_) {
+ params.SetLazyImagePlaceholder();
}
return PreloadHelper::StartPreload(resource_type_, params,
diff --git a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
index ad64c70ccf8..afb88f92b21 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -8,8 +8,8 @@
#include <memory>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
diff --git a/chromium/third_party/blink/renderer/core/html/portal/OWNERS b/chromium/third_party/blink/renderer/core/html/portal/OWNERS
new file mode 100644
index 00000000000..4c925a2a4b7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/portal/OWNERS
@@ -0,0 +1,6 @@
+adithyas@chromium.org
+jbroman@chromium.org
+lfg@chromium.org
+mcnee@chromium.org
+
+# COMPONENT: Blink>HTML>Portal
diff --git a/chromium/third_party/blink/renderer/core/html/portal/document_portals.cc b/chromium/third_party/blink/renderer/core/html/portal/document_portals.cc
index a2cfb0b1b33..bf53d46e18b 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/document_portals.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/document_portals.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
-#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
namespace blink {
@@ -25,35 +26,20 @@ DocumentPortals& DocumentPortals::From(Document& document) {
DocumentPortals::DocumentPortals(Document& document)
: Supplement<Document>(document) {}
-void DocumentPortals::OnPortalInserted(HTMLPortalElement* portal) {
+void DocumentPortals::RegisterPortalContents(PortalContents* portal) {
portals_.push_back(portal);
}
-void DocumentPortals::OnPortalRemoved(HTMLPortalElement* portal) {
- portals_.EraseAt(portals_.Find(portal));
-}
-
-HTMLPortalElement* DocumentPortals::GetPortal(
- const base::UnguessableToken& token) const {
- for (HTMLPortalElement* portal : portals_) {
- if (portal->GetToken() == token)
- return portal;
- }
-
- return nullptr;
-}
-
-bool DocumentPortals::IsPortalInDocumentActivating() const {
- for (HTMLPortalElement* portal : portals_) {
- if (portal->IsActivating())
- return true;
- }
- return false;
+void DocumentPortals::DeregisterPortalContents(PortalContents* portal) {
+ wtf_size_t index = portals_.Find(portal);
+ if (index != WTF::kNotFound)
+ portals_.EraseAt(index);
}
void DocumentPortals::Trace(Visitor* visitor) {
Supplement<Document>::Trace(visitor);
visitor->Trace(portals_);
+ visitor->Trace(activating_portal_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/portal/document_portals.h b/chromium/third_party/blink/renderer/core/html/portal/document_portals.h
index 5726d527282..96b264aeb60 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/document_portals.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/document_portals.h
@@ -11,8 +11,17 @@
namespace blink {
-class HTMLPortalElement;
-
+class PortalContents;
+
+// Tracks "active" portal contents associated with a document.
+//
+// An active contents is registered when it is created, either through creation
+// of a new contents in the browser, or through adoption of an existing one.
+// It is deregistered when that contents is closed, even though the
+// PortalContents object may not yet have been garbage-collected.
+//
+// At most one such contents may be activating at a given time. If there is such
+// a contents, it is also tracked by this object.
class DocumentPortals final : public GarbageCollected<DocumentPortals>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(DocumentPortals);
@@ -21,29 +30,39 @@ class DocumentPortals final : public GarbageCollected<DocumentPortals>,
static const char kSupplementName[];
static DocumentPortals& From(Document&);
- // Used to notify the document that a portal was inserted.
- void OnPortalInserted(HTMLPortalElement* portal);
-
- // Notifies that a portal was removed from the Document.
- void OnPortalRemoved(HTMLPortalElement* portal);
-
- // Retrieves the portal identified by the token.
- HTMLPortalElement* GetPortal(const base::UnguessableToken&) const;
+ void RegisterPortalContents(PortalContents*);
+ void DeregisterPortalContents(PortalContents*);
// Retrieves all portals in the document.
- const HeapVector<Member<HTMLPortalElement>>& GetPortals() const {
+ const HeapVector<Member<PortalContents>>& GetPortals() const {
return portals_;
}
// Returns true if any portal in the document is currently activating.
- bool IsPortalInDocumentActivating() const;
+ bool IsPortalInDocumentActivating() const { return activating_portal_; }
+
+ PortalContents* GetActivatingPortalContents() const {
+ return activating_portal_;
+ }
+ void SetActivatingPortalContents(PortalContents* portal) {
+ DCHECK(!activating_portal_);
+ activating_portal_ = portal;
+ }
+ void ClearActivatingPortalContents() { activating_portal_ = nullptr; }
explicit DocumentPortals(Document&);
void Trace(Visitor*) override;
private:
- HeapVector<Member<HTMLPortalElement>> portals_;
+ HeapVector<Member<PortalContents>> portals_;
+
+ // Needed to keep the activating contents alive so that it can receive an IPC
+ // reply from the browser process and respond accordingly (e.g. by resolving
+ // the promise).
+ //
+ // At most one portal contents can be undergoing activation at a time.
+ Member<PortalContents> activating_portal_;
};
} // namespace blink
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 b0caf96fe77..25aeeba12cc 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
#include "third_party/blink/renderer/core/html/portal/portal_activate_options.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
#include "third_party/blink/renderer/core/html/portal/portal_post_message_helper.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -51,21 +52,15 @@ HTMLPortalElement::HTMLPortalElement(
mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal,
mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
portal_client_receiver)
- : HTMLFrameOwnerElement(html_names::kPortalTag, document),
- portal_token_(portal_token),
- remote_portal_(std::move(remote_portal)),
- portal_client_receiver_(this, std::move(portal_client_receiver)) {
- if (remote_portal_) {
+ : HTMLFrameOwnerElement(html_names::kPortalTag, document) {
+ if (remote_portal) {
was_just_adopted_ = true;
-
DCHECK(CanHaveGuestContents())
<< "<portal> element was created with an existing contents but is not "
"permitted to have one";
-
- // If the portal element hosts a predecessor from activation, it can be
- // activated before being inserted into the DOM, and we need to keep track
- // of it from creation.
- DocumentPortals::From(GetDocument()).OnPortalInserted(this);
+ portal_ = MakeGarbageCollected<PortalContents>(
+ *this, portal_token, std::move(remote_portal),
+ std::move(portal_client_receiver));
}
}
@@ -73,16 +68,12 @@ HTMLPortalElement::~HTMLPortalElement() {}
void HTMLPortalElement::Trace(Visitor* visitor) {
HTMLFrameOwnerElement::Trace(visitor);
- visitor->Trace(portal_frame_);
+ visitor->Trace(portal_);
}
void HTMLPortalElement::ConsumePortal() {
- if (portal_token_) {
- DocumentPortals::From(GetDocument()).OnPortalRemoved(this);
- portal_token_ = base::UnguessableToken();
- }
- remote_portal_.reset();
- portal_client_receiver_.reset();
+ if (PortalContents* portal = std::exchange(portal_, nullptr))
+ portal->Destroy();
}
void HTMLPortalElement::ExpireAdoptionLifetime() {
@@ -91,7 +82,7 @@ void HTMLPortalElement::ExpireAdoptionLifetime() {
// After dispatching the portalactivate event, we check to see if we need to
// cleanup the portal hosting the predecessor. If the portal was created,
// but wasn't inserted or activated, we destroy it.
- if (!CanHaveGuestContents() && !IsActivating())
+ if (!CanHaveGuestContents())
ConsumePortal();
}
@@ -115,27 +106,10 @@ HTMLPortalElement::GetGuestContentsEligibility() const {
}
void HTMLPortalElement::Navigate() {
- KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
- if (!remote_portal_ || url.IsEmpty())
- return;
-
- if (!url.ProtocolIsInHTTPFamily()) {
- GetDocument().AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kRendering,
- mojom::ConsoleMessageLevel::kWarning,
- "Portals only allow navigation to protocols in the HTTP family."));
- return;
+ if (portal_) {
+ portal_->Navigate(GetNonEmptyURLAttribute(html_names::kSrcAttr),
+ ReferrerPolicyAttribute());
}
-
- auto referrer_policy_to_use = ReferrerPolicyAttribute();
- if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
- referrer_policy_to_use = GetDocument().GetReferrerPolicy();
- Referrer referrer = SecurityPolicy::GenerateReferrer(
- referrer_policy_to_use, url, GetDocument().OutgoingReferrer());
- auto mojo_referrer = mojom::blink::Referrer::New(
- KURL(NullURL(), referrer.referrer), referrer.referrer_policy);
-
- remote_portal_->Navigate(url, std::move(mojo_referrer));
}
namespace {
@@ -194,80 +168,41 @@ BlinkTransferableMessage ActivateDataAsMessage(
} // namespace
ScriptPromise HTMLPortalElement::activate(ScriptState* script_state,
- PortalActivateOptions* options) {
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- ScriptPromise promise = resolver->Promise();
-
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kExecutionContext,
- "HTMLPortalElement", "activate");
-
- if (!remote_portal_) {
+ PortalActivateOptions* options,
+ ExceptionState& exception_state) {
+ if (!portal_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"The HTMLPortalElement is not associated with a portal context.");
- resolver->Reject(exception_state);
- return promise;
- }
- if (is_activating_) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidStateError,
- "activate() has already been called on this HTMLPortalElement.");
- resolver->Reject(exception_state);
- return promise;
+ return ScriptPromise();
}
if (DocumentPortals::From(GetDocument()).IsPortalInDocumentActivating()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"activate() has already been called on another "
"HTMLPortalElement in this document.");
- resolver->Reject(exception_state);
- return promise;
+ return ScriptPromise();
}
if (GetDocument().GetPage()->InsidePortal()) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"Cannot activate a portal that is inside another portal.");
- resolver->Reject(exception_state);
- return promise;
+ return ScriptPromise();
}
BlinkTransferableMessage data =
ActivateDataAsMessage(script_state, options, exception_state);
- if (exception_state.HadException()) {
- resolver->Reject(exception_state);
- return promise;
- }
+ if (exception_state.HadException())
+ return ScriptPromise();
- // The HTMLPortalElement is bound as a persistent so that it won't get
- // garbage collected while there is a pending callback.
- // We also pass the ownership of the
- // mojo::AssociatedRemote<mojom::blink::Portal>, which guarantees that the
- // mojo::AssociatedRemote<mojom::blink::Portal> stays alive until the callback
- // is called.
- is_activating_ = true;
- auto* raw_remote_portal = remote_portal_.get();
- raw_remote_portal->Activate(
- std::move(data),
- WTF::Bind(
- [](HTMLPortalElement* portal,
- mojo::AssociatedRemote<mojom::blink::Portal>,
- ScriptPromiseResolver* resolver, bool was_adopted) {
- if (was_adopted)
- portal->GetDocument().GetPage()->SetInsidePortal(true);
- resolver->Resolve();
- portal->is_activating_ = false;
- portal->ConsumePortal();
- },
- WrapPersistent(this), std::move(remote_portal_),
- WrapPersistent(resolver)));
- return promise;
+ PortalContents* portal = std::exchange(portal_, nullptr);
+ return portal->Activate(script_state, std::move(data));
}
void HTMLPortalElement::postMessage(ScriptState* script_state,
const ScriptValue& message,
const String& target_origin,
- const Vector<ScriptValue>& transfer,
+ const HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
WindowPostMessageOptions* options = WindowPostMessageOptions::Create();
options->setTargetOrigin(target_origin);
@@ -280,7 +215,7 @@ void HTMLPortalElement::postMessage(ScriptState* script_state,
const ScriptValue& message,
const WindowPostMessageOptions* options,
ExceptionState& exception_state) {
- if (!remote_portal_ || is_activating_) {
+ if (!portal_) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"The HTMLPortalElement is not associated with a portal context");
@@ -299,8 +234,7 @@ void HTMLPortalElement::postMessage(ScriptState* script_state,
if (exception_state.HadException())
return;
- remote_portal_->PostMessageToGuest(std::move(transferable_message),
- target_origin);
+ portal_->PostMessageToGuest(std::move(transferable_message), target_origin);
}
EventListener* HTMLPortalElement::onmessage() {
@@ -319,23 +253,9 @@ void HTMLPortalElement::setOnmessageerror(EventListener* listener) {
SetAttributeEventListener(event_type_names::kMessageerror, listener);
}
-void HTMLPortalElement::ForwardMessageFromGuest(
- BlinkTransferableMessage message,
- const scoped_refptr<const SecurityOrigin>& source_origin,
- const scoped_refptr<const SecurityOrigin>& target_origin) {
- if (!remote_portal_)
- return;
-
- PortalPostMessageHelper::CreateAndDispatchMessageEvent(
- this, std::move(message), source_origin, target_origin);
-}
-
-void HTMLPortalElement::DispatchLoadEvent() {
- if (!remote_portal_)
- return;
-
- DispatchLoad();
- GetDocument().CheckCompleted();
+const base::UnguessableToken& HTMLPortalElement::GetToken() const {
+ DCHECK(portal_ && portal_->IsValid());
+ return portal_->GetToken();
}
HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto(
@@ -357,22 +277,28 @@ HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto(
break;
};
- if (remote_portal_) {
+ if (portal_) {
// The interface is already bound if the HTMLPortalElement is adopting the
// predecessor.
- portal_frame_ = GetDocument().GetFrame()->Client()->AdoptPortal(this);
- remote_portal_.set_disconnect_handler(
- WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
+ GetDocument().GetFrame()->Client()->AdoptPortal(this);
} else {
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> portal;
+ mojo::PendingAssociatedReceiver<mojom::blink::Portal> portal_receiver =
+ portal.InitWithNewEndpointAndPassReceiver();
+
mojo::PendingAssociatedRemote<mojom::blink::PortalClient> client;
- portal_client_receiver_.Bind(client.InitWithNewEndpointAndPassReceiver());
- std::tie(portal_frame_, portal_token_) =
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
+ client_receiver = client.InitWithNewEndpointAndPassReceiver();
+
+ RemoteFrame* portal_frame;
+ base::UnguessableToken portal_token;
+ std::tie(portal_frame, portal_token) =
GetDocument().GetFrame()->Client()->CreatePortal(
- this, remote_portal_.BindNewEndpointAndPassReceiver(),
- std::move(client));
- remote_portal_.set_disconnect_handler(
- WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
- DocumentPortals::From(GetDocument()).OnPortalInserted(this);
+ this, std::move(portal_receiver), std::move(client));
+
+ portal_ = MakeGarbageCollected<PortalContents>(
+ *this, portal_token, std::move(portal), std::move(client_receiver));
+
Navigate();
}
probe::PortalRemoteFrameCreated(&GetDocument(), this);
@@ -380,7 +306,8 @@ HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto(
}
void HTMLPortalElement::RemovedFrom(ContainerNode& node) {
- DCHECK(!remote_portal_.is_bound());
+ DCHECK(!portal_) << "This element should have previously dissociated in "
+ "DisconnectContentFrame";
HTMLFrameOwnerElement::RemovedFrom(node);
}
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 7462fd29e4d..3d9cc79b037 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
@@ -9,7 +9,7 @@
#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/blink/public/mojom/portal/portal.mojom-blink.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/node.h"
@@ -19,7 +19,7 @@ namespace blink {
class Document;
class PortalActivateOptions;
-class RemoteFrame;
+class PortalContents;
class ScriptState;
// The HTMLPortalElement implements the <portal> HTML element. The portal
@@ -27,8 +27,7 @@ class ScriptState;
// activated using script. The portal element is still under development and not
// part of the HTML standard. It can be enabled by passing
// --enable-features=Portals. See also https://github.com/WICG/portals.
-class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement,
- public mojom::blink::PortalClient {
+class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -44,11 +43,11 @@ class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement,
void Trace(Visitor* visitor) override;
// idl implementation.
- ScriptPromise activate(ScriptState*, PortalActivateOptions*);
+ ScriptPromise activate(ScriptState*, PortalActivateOptions*, ExceptionState&);
void postMessage(ScriptState* script_state,
const ScriptValue& message,
const String& target_origin,
- const Vector<ScriptValue>& transfer,
+ const HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state);
void postMessage(ScriptState* script_state,
const ScriptValue& message,
@@ -59,21 +58,12 @@ class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement,
EventListener* onmessageerror();
void setOnmessageerror(EventListener* listener);
- // blink::mojom::PortalClient implementation
- void ForwardMessageFromGuest(
- BlinkTransferableMessage message,
- const scoped_refptr<const SecurityOrigin>& source_origin,
- const scoped_refptr<const SecurityOrigin>& target_origin) override;
- void DispatchLoadEvent() override;
-
- const base::UnguessableToken& GetToken() const { return portal_token_; }
+ const base::UnguessableToken& GetToken() const;
FrameOwnerElementType OwnerType() const override {
return FrameOwnerElementType::kPortal;
}
- bool IsActivating() { return is_activating_; }
-
// Consumes the portal interface. When a Portal is activated, or if the
// renderer receives a connection error, this function will gracefully
// terminate the portal interface.
@@ -119,22 +109,11 @@ class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement,
void AttachLayoutTree(AttachContext& context) override;
network::mojom::ReferrerPolicy ReferrerPolicyAttribute() override;
- // Uniquely identifies the portal, this token is used by the browser process
- // to reference this portal when communicating with the renderer.
- base::UnguessableToken portal_token_;
-
- Member<RemoteFrame> portal_frame_;
-
- // Set to true after activate() is called on the portal. It is set to false
- // right before the promise returned by activate() is resolved or rejected.
- bool is_activating_ = false;
+ Member<PortalContents> portal_;
network::mojom::ReferrerPolicy referrer_policy_ =
network::mojom::ReferrerPolicy::kDefault;
- mojo::AssociatedRemote<mojom::blink::Portal> remote_portal_;
- mojo::AssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver_;
-
// Temporarily set to keep this element alive after adoption.
bool was_just_adopted_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
index b71a0ab9e6f..e0d5684616b 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/html_portal_element.idl
@@ -9,7 +9,7 @@ interface HTMLPortalElement : HTMLElement {
[CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy;
- [CallWith=ScriptState] Promise<void> activate(optional PortalActivateOptions options);
+ [CallWith=ScriptState, RaisesException] Promise<void> activate(optional PortalActivateOptions options);
[CallWith=ScriptState, RaisesException] void postMessage(any message, DOMString targetOrigin,
optional sequence<object> transfer = []);
[CallWith=ScriptState, RaisesException] void postMessage(any message, optional WindowPostMessageOptions options);
diff --git a/chromium/third_party/blink/renderer/core/events/portal_activate_event.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
index 1b34ff4c340..0d5ebc34dc8 100644
--- a/chromium/third_party/blink/renderer/core/events/portal_activate_event.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.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/renderer/core/events/portal_activate_event.h"
+#include "third_party/blink/renderer/core/html/portal/portal_activate_event.h"
#include <utility>
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/event_type_names.h"
-#include "third_party/blink/renderer/core/events/portal_activate_event_init.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_activate_event_init.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -80,7 +80,7 @@ ScriptValue PortalActivateEvent::data(ScriptState* script_state) {
v8::Isolate* isolate = script_state->GetIsolate();
v8::HandleScope handle_scope(isolate);
if (!data_ && data_from_init_.IsEmpty())
- return ScriptValue(script_state, v8::Null(isolate));
+ return ScriptValue(isolate, v8::Null(isolate));
auto result =
v8_data_.insert(script_state, TraceWrapperV8Reference<v8::Value>());
@@ -88,7 +88,7 @@ ScriptValue PortalActivateEvent::data(ScriptState* script_state) {
result.stored_value->value;
if (!result.is_new_entry)
- return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+ return ScriptValue(isolate, relevant_data.NewLocal(isolate));
v8::Local<v8::Value> value;
if (data_) {
@@ -101,7 +101,7 @@ ScriptValue PortalActivateEvent::data(ScriptState* script_state) {
}
relevant_data.Set(isolate, value);
- return ScriptValue(script_state, value);
+ return ScriptValue(isolate, value);
}
void PortalActivateEvent::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/events/portal_activate_event.h b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.h
index 51cff482bfc..f11e7cf35b4 100644
--- a/chromium/third_party/blink/renderer/core/events/portal_activate_event.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PORTAL_ACTIVATE_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PORTAL_ACTIVATE_EVENT_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_ACTIVATE_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_ACTIVATE_EVENT_H_
#include "base/unguessable_token.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/mojom/portal/portal.mojom-blink.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h"
@@ -101,4 +101,4 @@ class CORE_EXPORT PortalActivateEvent : public Event {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PORTAL_ACTIVATE_EVENT_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_ACTIVATE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/core/events/portal_activate_event.idl b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.idl
index 6bbb5a9b5f8..6bbb5a9b5f8 100644
--- a/chromium/third_party/blink/renderer/core/events/portal_activate_event.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event.idl
diff --git a/chromium/third_party/blink/renderer/core/events/portal_activate_event_init.idl b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl
index 8aeb9a7f91a..8aeb9a7f91a 100644
--- a/chromium/third_party/blink/renderer/core/events/portal_activate_event_init.idl
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_activate_event_init.idl
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc
new file mode 100644
index 00000000000..0994fdbb1fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -0,0 +1,161 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
+
+#include "third_party/blink/public/mojom/referrer.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h"
+#include "third_party/blink/renderer/core/dom/increment_load_event_delay_count.h"
+#include "third_party/blink/renderer/core/frame/remote_frame.h"
+#include "third_party/blink/renderer/core/html/portal/document_portals.h"
+#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_post_message_helper.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
+#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+
+namespace blink {
+
+PortalContents::PortalContents(
+ HTMLPortalElement& portal_element,
+ const base::UnguessableToken& portal_token,
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal,
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
+ portal_client_receiver)
+ : document_(portal_element.GetDocument()),
+ portal_element_(&portal_element),
+ portal_token_(portal_token),
+ remote_portal_(std::move(remote_portal)),
+ portal_client_receiver_(this, std::move(portal_client_receiver)) {
+ remote_portal_.set_disconnect_handler(
+ WTF::Bind(&PortalContents::Destroy, WrapWeakPersistent(this)));
+ DocumentPortals::From(GetDocument()).RegisterPortalContents(this);
+}
+
+PortalContents::~PortalContents() {}
+
+RemoteFrame* PortalContents::GetFrame() const {
+ if (portal_element_)
+ return To<RemoteFrame>(portal_element_->ContentFrame());
+ return nullptr;
+}
+
+ScriptPromise PortalContents::Activate(ScriptState* script_state,
+ BlinkTransferableMessage data) {
+ DCHECK(!IsActivating());
+ DCHECK(portal_element_);
+
+ // Mark this contents as having activation in progress.
+ DocumentPortals& document_portals = DocumentPortals::From(GetDocument());
+ document_portals.SetActivatingPortalContents(this);
+ activate_resolver_ =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+
+ // Request activation from the browser process.
+ // This object (and thus the Mojo connection it owns) remains alive while the
+ // renderer awaits the response.
+ remote_portal_->Activate(
+ std::move(data),
+ WTF::Bind(&PortalContents::OnActivateResponse, WrapPersistent(this)));
+
+ // Dissociate from the element. The element is expected to do the same.
+ portal_element_ = nullptr;
+
+ return activate_resolver_->Promise();
+}
+
+void PortalContents::OnActivateResponse(bool was_adopted) {
+ if (was_adopted)
+ GetDocument().GetPage()->SetInsidePortal(true);
+
+ DocumentPortals& document_portals = DocumentPortals::From(GetDocument());
+ DCHECK_EQ(document_portals.GetActivatingPortalContents(), this);
+ document_portals.ClearActivatingPortalContents();
+
+ activate_resolver_->Resolve();
+ activate_resolver_ = nullptr;
+ Destroy();
+}
+
+void PortalContents::PostMessageToGuest(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& target_origin) {
+ remote_portal_->PostMessageToGuest(std::move(message), target_origin);
+}
+
+void PortalContents::Navigate(
+ const KURL& url,
+ network::mojom::ReferrerPolicy referrer_policy_to_use) {
+ if (url.IsEmpty())
+ return;
+
+ if (!url.ProtocolIsInHTTPFamily()) {
+ GetDocument().AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kWarning,
+ "Portals only allow navigation to protocols in the HTTP family."));
+ return;
+ }
+
+ if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
+ referrer_policy_to_use = GetDocument().GetReferrerPolicy();
+ Referrer referrer = SecurityPolicy::GenerateReferrer(
+ referrer_policy_to_use, url, GetDocument().OutgoingReferrer());
+ auto mojo_referrer = mojom::blink::Referrer::New(
+ KURL(NullURL(), referrer.referrer), referrer.referrer_policy);
+
+ // There is a brief window of time between when Navigate is called and its
+ // callback is run, during which the Portal's content frame is not marked as
+ // loading. We use IncrementLoadEventDelayCount to block its document's load
+ // event in this time window. Once it goes out of scope,
+ // IncrementLoadEventDelayCount will call Document::CheckCompleted and fire
+ // load events if necessary.
+ std::unique_ptr<IncrementLoadEventDelayCount>
+ increment_load_event_delay_count =
+ std::make_unique<IncrementLoadEventDelayCount>(GetDocument());
+ remote_portal_->Navigate(
+ url, std::move(mojo_referrer),
+ WTF::Bind([](std::unique_ptr<IncrementLoadEventDelayCount>
+ increment_load_event_delay_count) {},
+ std::move(increment_load_event_delay_count)));
+}
+
+void PortalContents::Destroy() {
+ DCHECK(!IsActivating());
+ if (HTMLPortalElement* element = std::exchange(portal_element_, nullptr))
+ element->ConsumePortal();
+ portal_token_ = base::UnguessableToken();
+ remote_portal_.reset();
+ portal_client_receiver_.reset();
+ DocumentPortals::From(GetDocument()).DeregisterPortalContents(this);
+}
+
+void PortalContents::ForwardMessageFromGuest(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& source_origin,
+ const scoped_refptr<const SecurityOrigin>& target_origin) {
+ if (!IsValid() || !portal_element_)
+ return;
+
+ PortalPostMessageHelper::CreateAndDispatchMessageEvent(
+ portal_element_, std::move(message), source_origin, target_origin);
+}
+
+void PortalContents::DispatchLoadEvent() {
+ if (!IsValid() || !portal_element_)
+ return;
+
+ portal_element_->DispatchLoad();
+ GetDocument().CheckCompleted();
+}
+
+void PortalContents::Trace(Visitor* visitor) {
+ visitor->Trace(document_);
+ visitor->Trace(portal_element_);
+ visitor->Trace(activate_resolver_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_contents.h b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.h
new file mode 100644
index 00000000000..a9d5d993061
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_contents.h
@@ -0,0 +1,121 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_CONTENTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_CONTENTS_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/unguessable_token.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "third_party/blink/public/mojom/portal/portal.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+
+namespace blink {
+
+class Document;
+class HTMLPortalElement;
+class KURL;
+class RemoteFrame;
+class ScriptPromise;
+class ScriptPromiseResolver;
+class ScriptState;
+class SecurityOrigin;
+struct BlinkTransferableMessage;
+
+// The contents of an HTMLPortalElement, corresponding to ownership of a
+// content::WebContents.
+//
+// This object is usually owned by an HTMLPortalElement but may be briefly owned
+// elsewhere. For example, during activation it is necessary to keep the Mojo
+// connection to the browser-side portal state alive (so that the reply can be
+// received), but this should not prevent the <portal> element from being reused
+// in the meantime.
+class PortalContents : public GarbageCollected<PortalContents>,
+ public mojom::blink::PortalClient {
+ public:
+ PortalContents(
+ HTMLPortalElement& portal_element,
+ const base::UnguessableToken& portal_token,
+ mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal,
+ mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
+ portal_client_receiver);
+ ~PortalContents() override;
+
+ // Returns true if this object corresponds to an existent portal contents.
+ bool IsValid() const { return remote_portal_.is_bound(); }
+
+ // Returns true if this contents is currently being activated.
+ bool IsActivating() const { return activate_resolver_; }
+
+ // Returns an unguessable token which uniquely identifies the contents, if
+ // valid.
+ const base::UnguessableToken& GetToken() const { return portal_token_; }
+
+ // Returns the RemoteFrame associated with this portal, if any.
+ RemoteFrame* GetFrame() const;
+
+ // Activates the portal contents, and produces a promise which resolves when
+ // complete. The caller is expected to do all necessary preflight checks in
+ // advance.
+ ScriptPromise Activate(ScriptState*, BlinkTransferableMessage data);
+
+ // Posts a message which will be delivered in the guest contents via the
+ // PortalHost object.
+ void PostMessageToGuest(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& target_origin);
+
+ // Request navigation to the specified URL. May be a no-op if navigation to
+ // this URL is not permitted.
+ void Navigate(const KURL&, network::mojom::ReferrerPolicy);
+
+ // Tears down the internal state of this object. If ownership has not been
+ // transferred (via adoption), then the underlying contents will also be torn
+ // down.
+ void Destroy();
+
+ // blink::mojom::PortalClient implementation
+ void ForwardMessageFromGuest(
+ BlinkTransferableMessage message,
+ const scoped_refptr<const SecurityOrigin>& source_origin,
+ const scoped_refptr<const SecurityOrigin>& target_origin) override;
+ void DispatchLoadEvent() override;
+
+ void Trace(Visitor* visitor);
+
+ private:
+ // Returns the document which controls the lifetime of this portal (usually,
+ // the document of the HTMLPortalElement which owns this).
+ Document& GetDocument() const { return *document_; }
+
+ // Called on response to the request to activate the portal contents.
+ void OnActivateResponse(bool was_adopted);
+
+ // The document which owns this contents.
+ // TODO(jbroman): Should this be a DocumentShutdownObserver instead?
+ Member<Document> document_;
+
+ // The element which owns this contents, if any.
+ Member<HTMLPortalElement> portal_element_;
+
+ // Set if the portal contents is currently being activated.
+ // If so it will be the activating portal contents of the associated
+ // DocumentPortals.
+ Member<ScriptPromiseResolver> activate_resolver_;
+
+ // Uniquely identifies the portal, this token is used by the browser process
+ // to reference this portal when communicating with the renderer.
+ base::UnguessableToken portal_token_;
+
+ mojo::AssociatedRemote<mojom::blink::Portal> remote_portal_;
+ mojo::AssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_CONTENTS_H_
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_host.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_host.cc
index 706104f4fde..42b6924453f 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_host.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_host.cc
@@ -65,7 +65,7 @@ void PortalHost::OnPortalActivated() {
void PortalHost::postMessage(ScriptState* script_state,
const ScriptValue& message,
const String& target_origin,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
WindowPostMessageOptions* options = WindowPostMessageOptions::Create();
options->setTargetOrigin(target_origin);
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_host.h b/chromium/third_party/blink/renderer/core/html/portal/portal_host.h
index 24fa31c50ad..b23977cb65b 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_host.h
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_host.h
@@ -48,7 +48,7 @@ class CORE_EXPORT PortalHost : public EventTargetWithInlineData,
void postMessage(ScriptState* script_state,
const ScriptValue& message,
const String& target_origin,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state);
void postMessage(ScriptState* script_state,
const ScriptValue& message,
diff --git a/chromium/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc b/chromium/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
index 82e04cc752c..d9a2ae3fe8b 100644
--- a/chromium/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
+++ b/chromium/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
@@ -67,8 +67,7 @@ void PortalPostMessageHelper::CreateAndDispatchMessageEvent(
scoped_refptr<const SecurityOrigin> source_origin,
scoped_refptr<const SecurityOrigin> target_origin) {
DCHECK(event_target->ToPortalHost() ||
- (event_target->ToNode() &&
- ToHTMLPortalElementOrNull(event_target->ToNode())));
+ IsA<HTMLPortalElement>(event_target->ToNode()));
if (target_origin &&
!target_origin->IsSameSchemeHostPort(
diff --git a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css b/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
index 8e5ce9e21ea..98b3f6c0092 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -13,21 +13,14 @@ select,
select:-internal-list-box,
textarea {
background-color: #ffffff;
- border-color: #cecece;
-}
-
-input:hover,
-select:hover,
-select:-internal-list-box:hover,
-textarea:hover {
- border-color: #9d9d9d;
+ border-color: #767676;
}
input:disabled,
select:disabled,
textarea:disabled {
- background-color: #ffffff;
- border-color: #c5c5c5;
+ background-color: rgba(239, 239, 239, 0.3);
+ border-color: rgba(118, 118, 118, 0.3);
}
input[type="button" i],
@@ -37,7 +30,7 @@ input[type="color" i],
input[type="file" i]::-webkit-file-upload-button,
button {
background-color: #efefef;
- border-color: #cecece;
+ border-color: #767676;
}
input[type="button" i]:disabled,
@@ -46,7 +39,9 @@ input[type="reset" i]:disabled,
input[type="color" i]:disabled,
input[type="file" i]:disabled::-webkit-file-upload-button,
button:disabled {
- border-color: #c5c5c5;
+ background-color: rgba(239, 239, 239, 0.3);
+ border-color: rgba(118, 118, 118, 0.3);
+ color: rgba(16, 16, 16, 0.3);
}
input[type="password" i]::-internal-reveal {
@@ -68,7 +63,6 @@ input[type="password" i]::-internal-reveal.reveal {
input[type="password" i]::-internal-reveal:hover,
input[type="password" i]::-internal-reveal:focus {
- background-color: #F7F7F7;
border-radius: 1px;
cursor: pointer;
}
@@ -81,29 +75,38 @@ input[type="range" i]:disabled {
color: #c5c5c5;
}
+meter::-webkit-meter-inner-element::before,
+meter::-webkit-meter-inner-element::after {
+ display: block;
+ content: "";
+ height: 25%;
+}
+
meter::-webkit-meter-bar {
background: #efefef;
border-width: 1px;
+ height: 50%;
border-style: solid;
- border-color: #cecece;
- border-radius: 2px;
+ border-color: rgba(118, 118, 118, 0.3);
+ border-radius: 20px;
box-sizing: border-box;
- padding: 1px;
+}
+
+meter::-internal-meter-clip {
+ clip-path: inset(0px round 20px);
+ height: 100%;
}
meter::-webkit-meter-optimum-value {
background: #107c10;
- border-radius: 1px 0px 0px 1px;
}
meter::-webkit-meter-suboptimum-value {
background: #ffb900;
- border-radius: 1px 0px 0px 1px;
}
meter::-webkit-meter-even-less-good-value {
background: #d83b01;
- border-radius: 1px 0px 0px 1px;
}
input[type="date" i]::-webkit-calendar-picker-indicator,
@@ -124,6 +127,21 @@ input[type="week" i]::-webkit-calendar-picker-indicator {
width: 1.2em;
}
+input[type="time" i]::-webkit-calendar-picker-indicator {
+ background-image: -webkit-image-set(url(images/time_icon.svg) 1x);
+ background-origin: content-box;
+ background-repeat: no-repeat;
+ background-size: contain;
+ height: 1.05em;
+ opacity: 1;
+ outline: none;
+ padding-bottom: 3px;
+ padding-inline-start: 11px;
+ padding-inline-end: 3px;
+ padding-top: 3px;
+ width: 1.05em;
+}
+
input::-webkit-calendar-picker-indicator:hover {
background-color: initial;
}
diff --git a/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css b/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
index c04c9386e07..18fa3a93ea9 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -73,10 +73,32 @@
color: ButtonText;
}
+ 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;
+ outline: none;
+ }
+
input[type="color"]:disabled {
border-color: GrayText;
}
+ input[type="color"] {
+ forced-color-adjust: none;
+ }
+
+ input[type="color"]::-webkit-color-swatch {
+ border-color: WindowText !important;
+ }
+
button,
input[type="button"],
input[type="submit"],
@@ -106,6 +128,52 @@
color: GrayText;
}
+ /* same color as hyperlinks */
+ details summary {
+ color: LinkText;
+ }
+
+ select:-internal-list-box {
+ background-color: Window !important;
+ border-color: ButtonText;
+ }
+
+ /* option disabled */
+ select:-internal-list-box option:disabled,
+ select:-internal-list-box option:disabled:hover,
+ select:-internal-list-box:disabled option,
+ select:-internal-list-box:disabled option:hover {
+ background-color: Window !important;
+ color: GrayText !important;
+ }
+
+ /* option selected */
+ select:-internal-list-box:focus option:checked,
+ select:-internal-list-box:focus option:checked:hover,
+ select:-internal-list-box option:checked,
+ select:-internal-list-box option:checked:hover {
+ background-color: Highlight !important;
+ color: Window !important;
+ forced-color-adjust: none;
+ }
+
+ /* option both disabled and selected */
+ select:-internal-list-box:focus option:checked:disabled,
+ select:-internal-list-box:focus option:checked:disabled:hover,
+ select:-internal-list-box:disabled option:checked,
+ select:-internal-list-box:disabled option:checked:hover,
+ select:-internal-list-box option:checked:disabled,
+ select:-internal-list-box option:checked:disabled:hover {
+ background-color: GrayText !important;
+ color: Window !important;
+ forced-color-adjust: none;
+ }
+
+ select:-internal-list-box option:hover {
+ background-color: Window;
+ color: Highlight;
+ }
+
select {
background: Window;
border-color: WindowText;
@@ -125,21 +193,14 @@
color: GrayText;
}
- progress::-webkit-progress-bar {
- background: ButtonFace;
- }
-
- progress::-webkit-progress-value {
- background: Highlight;
- }
-
meter::-webkit-meter-bar {
background: ButtonFace;
+ border-color: WindowText;
}
meter::-webkit-meter-even-less-good-value,
meter::-webkit-meter-optimum-value,
- meter::-webkit-meter-suboptimal-value {
+ meter::-webkit-meter-suboptimum-value {
background: Highlight;
}
}
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 e76db8bf9ef..9df20392693 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/html.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/html.css
@@ -407,7 +407,7 @@ input, textarea, select, button {
margin: 0__qem;
font: -webkit-small-control;
text-rendering: auto; /* FIXME: Remove when tabs work with optimizeLegibility. */
- color: initial;
+ color: -internal-light-dark-color(black, white);
letter-spacing: normal;
word-spacing: normal;
line-height: normal;
@@ -425,7 +425,7 @@ input[type="hidden" i] {
input {
-webkit-appearance: textfield; /* AutoAppearanceFor() should match to this. */
padding: 1px;
- background-color: white;
+ background-color: -internal-light-dark-color(white, black);
border: 2px inset;
-webkit-rtl-ordering: logical;
cursor: text;
@@ -498,7 +498,7 @@ select {
textarea {
-webkit-appearance: textarea; /* AutoAppearanceFor() should match to this. */
- background-color: white;
+ background-color: -internal-light-dark-color(white, black);
border: 1px solid;
-webkit-rtl-ordering: logical;
flex-direction: column;
@@ -568,7 +568,7 @@ textarea:-internal-autofill-previewed,
select:-internal-autofill-previewed {
background-color: #E8F0FE !important;
background-image:none !important;
- color: #000000 !important;
+ color: -internal-light-dark-color(black, white) !important;
}
input:-internal-autofill-selected,
@@ -576,7 +576,7 @@ textarea:-internal-autofill-selected,
select:-internal-autofill-selected {
background-color: #E8F0FE !important;
background-image:none !important;
- color: #000000 !important;
+ color: -internal-light-dark-color(black, white) !important;
}
input[type="radio" i], input[type="checkbox" i] {
@@ -651,7 +651,7 @@ input[type="button" i]:disabled, input[type="submit" i]:disabled, input[type="re
input[type="file" i]:disabled::-webkit-file-upload-button, button:disabled,
select:disabled, optgroup:disabled, option:disabled,
select[disabled]>option {
- color: GrayText
+ color: -internal-light-dark-color(GrayText, #aaa);
}
input[type="button" i]:active, input[type="submit" i]:active, input[type="reset" i]:active, input[type="file" i]:active::-webkit-file-upload-button, button:active {
@@ -663,12 +663,12 @@ input[type="button" i]:active:disabled, input[type="submit" i]:active:disabled,
}
input:disabled, textarea:disabled {
- color: #545454;
+ color: -internal-light-dark-color(#545454, #aaa);
cursor: default;
}
option:-internal-spatial-navigation-focus {
- outline: black dashed 1px;
+ outline: -internal-light-dark-color(black, white) dashed 1px;
outline-offset: -1px;
}
@@ -790,8 +790,8 @@ select {
border: 1px solid;
white-space: pre;
-webkit-rtl-ordering: logical;
- color: black;
- background-color: white;
+ color: -internal-light-dark-color(black, white);
+ background-color: -internal-light-dark-color(white, black);
cursor: default;
}
@@ -1146,8 +1146,8 @@ dialog {
margin: auto;
border: solid;
padding: 1em;
- background: white;
- color: black
+ background: -internal-light-dark-color(white, black);
+ color: -internal-light-dark-color(black, white);
}
/* TODO(foolip): In the Fullscreen spec, there's a ::backdrop block with the
diff --git a/chromium/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg b/chromium/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg
index f66e72ebe01..c625f9d47b7 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg
+++ b/chromium/third_party/blink/renderer/core/html/resources/images/calendar_icon.svg
@@ -1,3 +1,3 @@
<svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M6 6H7V7H6V6ZM9 12H10V13H9V12ZM12 6H13V7H12V6ZM9 6H10V7H9V6ZM6 8H7V9H6V8ZM3 8H4V9H3V8ZM12 8H13V9H12V8ZM9 8H10V9H9V8ZM6 10H7V11H6V10ZM3 10H4V11H3V10ZM12 10H13V11H12V10ZM9 10H10V11H9V10ZM6 12H7V13H6V12ZM3 12H4V13H3V12ZM16 1V15H0V1H3V0H4V1H12V0H13V1H16ZM1 2V4H15V2H13V3H12V2H4V3H3V2H1ZM15 14V5H1V14H15Z" fill="#101010"/>
+<path d="M6 6H7V7H6V6ZM9 12H10V13H9V12ZM12 6H13V7H12V6ZM9 6H10V7H9V6ZM6 8H7V9H6V8ZM3 8H4V9H3V8ZM12 8H13V9H12V8ZM9 8H10V9H9V8ZM6 10H7V11H6V10ZM3 10H4V11H3V10ZM12 10H13V11H12V10ZM9 10H10V11H9V10ZM6 12H7V13H6V12ZM3 12H4V13H3V12ZM16 1V15H0V1H3V0H4V1H12V0H13V1H16ZM1 2V4H15V2H13V3H12V2H4V3H3V2H1ZM15 14V5H1V14H15Z" fill="WindowText"/>
</svg>
diff --git a/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_off.svg b/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_off.svg
index 39f9115063c..ff7b16c1eae 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_off.svg
+++ b/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_off.svg
@@ -1,4 +1,4 @@
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M10 4C10.7812 4 11.5417 4.10156 12.2812 4.30469C13.0208 4.50781 13.7292 4.78906 14.4062 5.14844C15.0885 5.5026 15.7292 5.92448 16.3281 6.41406C16.9323 6.90365 17.4896 7.43229 18 8C17.4896 8.57292 16.9323 9.10417 16.3281 9.59375C15.7292 10.0781 15.0885 10.5 14.4062 10.8594C13.7292 11.2135 13.0208 11.4922 12.2812 11.6953C11.5417 11.8984 10.7812 12 10 12C9.21875 12 8.45833 11.8984 7.71875 11.6953C6.97917 11.4922 6.26823 11.2135 5.58594 10.8594C4.90885 10.5 4.26823 10.0781 3.66406 9.59375C3.0599 9.10417 2.50521 8.57292 2 8C2.50521 7.43229 3.0599 6.90365 3.66406 6.41406C4.26823 5.92448 4.90885 5.5026 5.58594 5.14844C6.26823 4.78906 6.97917 4.50781 7.71875 4.30469C8.45833 4.10156 9.21875 4 10 4ZM13 8C13 7.58854 12.9193 7.20052 12.7578 6.83594C12.6016 6.47135 12.388 6.15365 12.1172 5.88281C11.8464 5.61198 11.5286 5.39844 11.1641 5.24219C10.7995 5.08073 10.4115 5 10 5C9.58854 5 9.20052 5.08073 8.83594 5.24219C8.47135 5.39844 8.15365 5.61198 7.88281 5.88281C7.61198 6.15365 7.39583 6.47135 7.23438 6.83594C7.07812 7.20052 7 7.58854 7 8C7 8.41146 7.07812 8.79948 7.23438 9.16406C7.39583 9.52865 7.61198 9.84635 7.88281 10.1172C8.15365 10.388 8.47135 10.6042 8.83594 10.7656C9.20052 10.9219 9.58854 11 10 11C10.4115 11 10.7995 10.9219 11.1641 10.7656C11.5286 10.6042 11.8464 10.388 12.1172 10.1172C12.388 9.84635 12.6016 9.52865 12.7578 9.16406C12.9193 8.79948 13 8.41146 13 8ZM3.38281 8C3.8724 8.47396 4.39323 8.90885 4.94531 9.30469C5.4974 9.69531 6.08854 10.0234 6.71875 10.2891C6.48438 9.95573 6.30469 9.59375 6.17969 9.20312C6.0599 8.80729 6 8.40625 6 8C6 7.59375 6.0599 7.19531 6.17969 6.80469C6.30469 6.40885 6.48438 6.04427 6.71875 5.71094C6.08854 5.97656 5.4974 6.30729 4.94531 6.70312C4.39323 7.09375 3.8724 7.52604 3.38281 8ZM13.2812 10.2891C13.9115 10.0234 14.5026 9.69531 15.0547 9.30469C15.6068 8.90885 16.1276 8.47396 16.6172 8C16.1276 7.52604 15.6068 7.09375 15.0547 6.70312C14.5026 6.30729 13.9115 5.97656 13.2812 5.71094C13.5156 6.04427 13.6927 6.40885 13.8125 6.80469C13.9375 7.19531 14 7.59375 14 8C14 8.40625 13.9375 8.80729 13.8125 9.20312C13.6927 9.59375 13.5156 9.95573 13.2812 10.2891ZM10 9C9.85938 9 9.72917 8.97396 9.60938 8.92188C9.48958 8.86979 9.38281 8.79948 9.28906 8.71094C9.20052 8.61719 9.13021 8.51042 9.07812 8.39062C9.02604 8.27083 9 8.14062 9 8C9 7.85938 9.02604 7.72917 9.07812 7.60938C9.13021 7.48958 9.20052 7.38542 9.28906 7.29688C9.38281 7.20312 9.48958 7.13021 9.60938 7.07812C9.72917 7.02604 9.85938 7 10 7C10.1406 7 10.2708 7.02604 10.3906 7.07812C10.5104 7.13021 10.6146 7.20312 10.7031 7.29688C10.7969 7.38542 10.8698 7.48958 10.9219 7.60938C10.974 7.72917 11 7.85938 11 8C11 8.14062 10.974 8.27083 10.9219 8.39062C10.8698 8.51042 10.7969 8.61719 10.7031 8.71094C10.6146 8.79948 10.5104 8.86979 10.3906 8.92188C10.2708 8.97396 10.1406 9 10 9Z" fill="black"/>
-<line x1="3.36031" y1="14.5754" x2="17.3603" y2="0.575402" stroke="black"/>
+<path d="M10 4C10.7812 4 11.5417 4.10156 12.2812 4.30469C13.0208 4.50781 13.7292 4.78906 14.4062 5.14844C15.0885 5.5026 15.7292 5.92448 16.3281 6.41406C16.9323 6.90365 17.4896 7.43229 18 8C17.4896 8.57292 16.9323 9.10417 16.3281 9.59375C15.7292 10.0781 15.0885 10.5 14.4062 10.8594C13.7292 11.2135 13.0208 11.4922 12.2812 11.6953C11.5417 11.8984 10.7812 12 10 12C9.21875 12 8.45833 11.8984 7.71875 11.6953C6.97917 11.4922 6.26823 11.2135 5.58594 10.8594C4.90885 10.5 4.26823 10.0781 3.66406 9.59375C3.0599 9.10417 2.50521 8.57292 2 8C2.50521 7.43229 3.0599 6.90365 3.66406 6.41406C4.26823 5.92448 4.90885 5.5026 5.58594 5.14844C6.26823 4.78906 6.97917 4.50781 7.71875 4.30469C8.45833 4.10156 9.21875 4 10 4ZM13 8C13 7.58854 12.9193 7.20052 12.7578 6.83594C12.6016 6.47135 12.388 6.15365 12.1172 5.88281C11.8464 5.61198 11.5286 5.39844 11.1641 5.24219C10.7995 5.08073 10.4115 5 10 5C9.58854 5 9.20052 5.08073 8.83594 5.24219C8.47135 5.39844 8.15365 5.61198 7.88281 5.88281C7.61198 6.15365 7.39583 6.47135 7.23438 6.83594C7.07812 7.20052 7 7.58854 7 8C7 8.41146 7.07812 8.79948 7.23438 9.16406C7.39583 9.52865 7.61198 9.84635 7.88281 10.1172C8.15365 10.388 8.47135 10.6042 8.83594 10.7656C9.20052 10.9219 9.58854 11 10 11C10.4115 11 10.7995 10.9219 11.1641 10.7656C11.5286 10.6042 11.8464 10.388 12.1172 10.1172C12.388 9.84635 12.6016 9.52865 12.7578 9.16406C12.9193 8.79948 13 8.41146 13 8ZM3.38281 8C3.8724 8.47396 4.39323 8.90885 4.94531 9.30469C5.4974 9.69531 6.08854 10.0234 6.71875 10.2891C6.48438 9.95573 6.30469 9.59375 6.17969 9.20312C6.0599 8.80729 6 8.40625 6 8C6 7.59375 6.0599 7.19531 6.17969 6.80469C6.30469 6.40885 6.48438 6.04427 6.71875 5.71094C6.08854 5.97656 5.4974 6.30729 4.94531 6.70312C4.39323 7.09375 3.8724 7.52604 3.38281 8ZM13.2812 10.2891C13.9115 10.0234 14.5026 9.69531 15.0547 9.30469C15.6068 8.90885 16.1276 8.47396 16.6172 8C16.1276 7.52604 15.6068 7.09375 15.0547 6.70312C14.5026 6.30729 13.9115 5.97656 13.2812 5.71094C13.5156 6.04427 13.6927 6.40885 13.8125 6.80469C13.9375 7.19531 14 7.59375 14 8C14 8.40625 13.9375 8.80729 13.8125 9.20312C13.6927 9.59375 13.5156 9.95573 13.2812 10.2891ZM10 9C9.85938 9 9.72917 8.97396 9.60938 8.92188C9.48958 8.86979 9.38281 8.79948 9.28906 8.71094C9.20052 8.61719 9.13021 8.51042 9.07812 8.39062C9.02604 8.27083 9 8.14062 9 8C9 7.85938 9.02604 7.72917 9.07812 7.60938C9.13021 7.48958 9.20052 7.38542 9.28906 7.29688C9.38281 7.20312 9.48958 7.13021 9.60938 7.07812C9.72917 7.02604 9.85938 7 10 7C10.1406 7 10.2708 7.02604 10.3906 7.07812C10.5104 7.13021 10.6146 7.20312 10.7031 7.29688C10.7969 7.38542 10.8698 7.48958 10.9219 7.60938C10.974 7.72917 11 7.85938 11 8C11 8.14062 10.974 8.27083 10.9219 8.39062C10.8698 8.51042 10.7969 8.61719 10.7031 8.71094C10.6146 8.79948 10.5104 8.86979 10.3906 8.92188C10.2708 8.97396 10.1406 9 10 9Z" fill="WindowText"/>
+<line x1="3.36031" y1="14.5754" x2="17.3603" y2="0.575402" stroke="WindowText"/>
</svg> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_on.svg b/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_on.svg
index d8d940e71f0..828b3dbedd0 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_on.svg
+++ b/chromium/third_party/blink/renderer/core/html/resources/images/password_reveal_on.svg
@@ -1,3 +1,3 @@
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M10 4C10.7812 4 11.5417 4.10156 12.2812 4.30469C13.0208 4.50781 13.7292 4.78906 14.4062 5.14844C15.0885 5.5026 15.7292 5.92448 16.3281 6.41406C16.9323 6.90365 17.4896 7.43229 18 8C17.4896 8.57292 16.9323 9.10417 16.3281 9.59375C15.7292 10.0781 15.0885 10.5 14.4062 10.8594C13.7292 11.2135 13.0208 11.4922 12.2812 11.6953C11.5417 11.8984 10.7812 12 10 12C9.21875 12 8.45833 11.8984 7.71875 11.6953C6.97917 11.4922 6.26823 11.2135 5.58594 10.8594C4.90885 10.5 4.26823 10.0781 3.66406 9.59375C3.0599 9.10417 2.50521 8.57292 2 8C2.50521 7.43229 3.0599 6.90365 3.66406 6.41406C4.26823 5.92448 4.90885 5.5026 5.58594 5.14844C6.26823 4.78906 6.97917 4.50781 7.71875 4.30469C8.45833 4.10156 9.21875 4 10 4ZM13 8C13 7.58854 12.9193 7.20052 12.7578 6.83594C12.6016 6.47135 12.388 6.15365 12.1172 5.88281C11.8464 5.61198 11.5286 5.39844 11.1641 5.24219C10.7995 5.08073 10.4115 5 10 5C9.58854 5 9.20052 5.08073 8.83594 5.24219C8.47135 5.39844 8.15365 5.61198 7.88281 5.88281C7.61198 6.15365 7.39583 6.47135 7.23438 6.83594C7.07812 7.20052 7 7.58854 7 8C7 8.41146 7.07812 8.79948 7.23438 9.16406C7.39583 9.52865 7.61198 9.84635 7.88281 10.1172C8.15365 10.388 8.47135 10.6042 8.83594 10.7656C9.20052 10.9219 9.58854 11 10 11C10.4115 11 10.7995 10.9219 11.1641 10.7656C11.5286 10.6042 11.8464 10.388 12.1172 10.1172C12.388 9.84635 12.6016 9.52865 12.7578 9.16406C12.9193 8.79948 13 8.41146 13 8ZM3.38281 8C3.8724 8.47396 4.39323 8.90885 4.94531 9.30469C5.4974 9.69531 6.08854 10.0234 6.71875 10.2891C6.48438 9.95573 6.30469 9.59375 6.17969 9.20312C6.0599 8.80729 6 8.40625 6 8C6 7.59375 6.0599 7.19531 6.17969 6.80469C6.30469 6.40885 6.48438 6.04427 6.71875 5.71094C6.08854 5.97656 5.4974 6.30729 4.94531 6.70312C4.39323 7.09375 3.8724 7.52604 3.38281 8ZM13.2812 10.2891C13.9115 10.0234 14.5026 9.69531 15.0547 9.30469C15.6068 8.90885 16.1276 8.47396 16.6172 8C16.1276 7.52604 15.6068 7.09375 15.0547 6.70312C14.5026 6.30729 13.9115 5.97656 13.2812 5.71094C13.5156 6.04427 13.6927 6.40885 13.8125 6.80469C13.9375 7.19531 14 7.59375 14 8C14 8.40625 13.9375 8.80729 13.8125 9.20312C13.6927 9.59375 13.5156 9.95573 13.2812 10.2891ZM10 9C9.85938 9 9.72917 8.97396 9.60938 8.92188C9.48958 8.86979 9.38281 8.79948 9.28906 8.71094C9.20052 8.61719 9.13021 8.51042 9.07812 8.39062C9.02604 8.27083 9 8.14062 9 8C9 7.85938 9.02604 7.72917 9.07812 7.60938C9.13021 7.48958 9.20052 7.38542 9.28906 7.29688C9.38281 7.20312 9.48958 7.13021 9.60938 7.07812C9.72917 7.02604 9.85938 7 10 7C10.1406 7 10.2708 7.02604 10.3906 7.07812C10.5104 7.13021 10.6146 7.20312 10.7031 7.29688C10.7969 7.38542 10.8698 7.48958 10.9219 7.60938C10.974 7.72917 11 7.85938 11 8C11 8.14062 10.974 8.27083 10.9219 8.39062C10.8698 8.51042 10.7969 8.61719 10.7031 8.71094C10.6146 8.79948 10.5104 8.86979 10.3906 8.92188C10.2708 8.97396 10.1406 9 10 9Z" fill="black"/>
+<path d="M10 4C10.7812 4 11.5417 4.10156 12.2812 4.30469C13.0208 4.50781 13.7292 4.78906 14.4062 5.14844C15.0885 5.5026 15.7292 5.92448 16.3281 6.41406C16.9323 6.90365 17.4896 7.43229 18 8C17.4896 8.57292 16.9323 9.10417 16.3281 9.59375C15.7292 10.0781 15.0885 10.5 14.4062 10.8594C13.7292 11.2135 13.0208 11.4922 12.2812 11.6953C11.5417 11.8984 10.7812 12 10 12C9.21875 12 8.45833 11.8984 7.71875 11.6953C6.97917 11.4922 6.26823 11.2135 5.58594 10.8594C4.90885 10.5 4.26823 10.0781 3.66406 9.59375C3.0599 9.10417 2.50521 8.57292 2 8C2.50521 7.43229 3.0599 6.90365 3.66406 6.41406C4.26823 5.92448 4.90885 5.5026 5.58594 5.14844C6.26823 4.78906 6.97917 4.50781 7.71875 4.30469C8.45833 4.10156 9.21875 4 10 4ZM13 8C13 7.58854 12.9193 7.20052 12.7578 6.83594C12.6016 6.47135 12.388 6.15365 12.1172 5.88281C11.8464 5.61198 11.5286 5.39844 11.1641 5.24219C10.7995 5.08073 10.4115 5 10 5C9.58854 5 9.20052 5.08073 8.83594 5.24219C8.47135 5.39844 8.15365 5.61198 7.88281 5.88281C7.61198 6.15365 7.39583 6.47135 7.23438 6.83594C7.07812 7.20052 7 7.58854 7 8C7 8.41146 7.07812 8.79948 7.23438 9.16406C7.39583 9.52865 7.61198 9.84635 7.88281 10.1172C8.15365 10.388 8.47135 10.6042 8.83594 10.7656C9.20052 10.9219 9.58854 11 10 11C10.4115 11 10.7995 10.9219 11.1641 10.7656C11.5286 10.6042 11.8464 10.388 12.1172 10.1172C12.388 9.84635 12.6016 9.52865 12.7578 9.16406C12.9193 8.79948 13 8.41146 13 8ZM3.38281 8C3.8724 8.47396 4.39323 8.90885 4.94531 9.30469C5.4974 9.69531 6.08854 10.0234 6.71875 10.2891C6.48438 9.95573 6.30469 9.59375 6.17969 9.20312C6.0599 8.80729 6 8.40625 6 8C6 7.59375 6.0599 7.19531 6.17969 6.80469C6.30469 6.40885 6.48438 6.04427 6.71875 5.71094C6.08854 5.97656 5.4974 6.30729 4.94531 6.70312C4.39323 7.09375 3.8724 7.52604 3.38281 8ZM13.2812 10.2891C13.9115 10.0234 14.5026 9.69531 15.0547 9.30469C15.6068 8.90885 16.1276 8.47396 16.6172 8C16.1276 7.52604 15.6068 7.09375 15.0547 6.70312C14.5026 6.30729 13.9115 5.97656 13.2812 5.71094C13.5156 6.04427 13.6927 6.40885 13.8125 6.80469C13.9375 7.19531 14 7.59375 14 8C14 8.40625 13.9375 8.80729 13.8125 9.20312C13.6927 9.59375 13.5156 9.95573 13.2812 10.2891ZM10 9C9.85938 9 9.72917 8.97396 9.60938 8.92188C9.48958 8.86979 9.38281 8.79948 9.28906 8.71094C9.20052 8.61719 9.13021 8.51042 9.07812 8.39062C9.02604 8.27083 9 8.14062 9 8C9 7.85938 9.02604 7.72917 9.07812 7.60938C9.13021 7.48958 9.20052 7.38542 9.28906 7.29688C9.38281 7.20312 9.48958 7.13021 9.60938 7.07812C9.72917 7.02604 9.85938 7 10 7C10.1406 7 10.2708 7.02604 10.3906 7.07812C10.5104 7.13021 10.6146 7.20312 10.7031 7.29688C10.7969 7.38542 10.8698 7.48958 10.9219 7.60938C10.974 7.72917 11 7.85938 11 8C11 8.14062 10.974 8.27083 10.9219 8.39062C10.8698 8.51042 10.7969 8.61719 10.7031 8.71094C10.6146 8.79948 10.5104 8.86979 10.3906 8.92188C10.2708 8.97396 10.1406 9 10 9Z" fill="WindowText"/>
</svg> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/html/resources/images/time_icon.svg b/chromium/third_party/blink/renderer/core/html/resources/images/time_icon.svg
new file mode 100644
index 00000000000..464453a040c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/resources/images/time_icon.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7 14C6.35417 14 5.73177 13.9167 5.13281 13.75C4.53906 13.5833 3.98177 13.349 3.46094 13.0469C2.94531 12.7396 2.47396 12.375 2.04688 11.9531C1.625 11.526 1.26042 11.0547 0.953125 10.5391C0.651042 10.0182 0.416667 9.46094 0.25 8.86719C0.0833333 8.26823 0 7.64583 0 7C0 6.35417 0.0833333 5.73438 0.25 5.14062C0.416667 4.54167 0.651042 3.98438 0.953125 3.46875C1.26042 2.94792 1.625 2.47656 2.04688 2.05469C2.47396 1.6276 2.94531 1.26302 3.46094 0.960938C3.98177 0.653646 4.53906 0.416667 5.13281 0.25C5.73177 0.0833333 6.35417 0 7 0C7.64583 0 8.26562 0.0833333 8.85938 0.25C9.45833 0.416667 10.0156 0.653646 10.5312 0.960938C11.0521 1.26302 11.5234 1.6276 11.9453 2.05469C12.3724 2.47656 12.737 2.94792 13.0391 3.46875C13.3464 3.98438 13.5833 4.54167 13.75 5.14062C13.9167 5.73438 14 6.35417 14 7C14 7.64583 13.9167 8.26823 13.75 8.86719C13.5833 9.46094 13.3464 10.0182 13.0391 10.5391C12.737 11.0547 12.3724 11.526 11.9453 11.9531C11.5234 12.375 11.0521 12.7396 10.5312 13.0469C10.0156 13.349 9.45833 13.5833 8.85938 13.75C8.26562 13.9167 7.64583 14 7 14ZM7 1C6.17188 1 5.39323 1.15885 4.66406 1.47656C3.9401 1.78906 3.30469 2.21875 2.75781 2.76562C2.21615 3.30729 1.78646 3.94271 1.46875 4.67188C1.15625 5.39583 1 6.17188 1 7C1 7.82812 1.15625 8.60677 1.46875 9.33594C1.78646 10.0599 2.21615 10.6953 2.75781 11.2422C3.30469 11.7839 3.9401 12.2135 4.66406 12.5312C5.39323 12.8438 6.17188 13 7 13C7.82812 13 8.60417 12.8438 9.32812 12.5312C10.0573 12.2135 10.6927 11.7839 11.2344 11.2422C11.7812 10.6953 12.2109 10.0599 12.5234 9.33594C12.8411 8.60677 13 7.82812 13 7C13 6.17188 12.8411 5.39583 12.5234 4.67188C12.2109 3.94271 11.7812 3.30729 11.2344 2.76562C10.6927 2.21875 10.0573 1.78906 9.32812 1.47656C8.60417 1.15885 7.82812 1 7 1ZM7 7V3H6V8H10V7H7Z" fill="#101010"/>
+</svg>
diff --git a/chromium/third_party/blink/renderer/core/html/resources/win.css b/chromium/third_party/blink/renderer/core/html/resources/win.css
index 1ea7fd3ea40..ce9f3120007 100644
--- a/chromium/third_party/blink/renderer/core/html/resources/win.css
+++ b/chromium/third_party/blink/renderer/core/html/resources/win.css
@@ -60,7 +60,7 @@ input[type="range" i] {
/* Not sure this is the right color. #EBEBE4 is what Firefox uses. */
textarea:disabled,
input:disabled {
- background-color: #EBEBE4;
+ background-color: -internal-light-dark-color(#ebebe4, #2d2d2d);
}
/* Cancel the above rule set for some input types. */
diff --git a/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc b/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
index f8a92e77705..f1cea3811d9 100644
--- a/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element.cc
@@ -41,7 +41,7 @@ ProgressShadowElement::ProgressShadowElement(Document& document)
}
HTMLProgressElement* ProgressShadowElement::ProgressElement() const {
- return ToHTMLProgressElement(OwnerShadowHost());
+ return To<HTMLProgressElement>(OwnerShadowHost());
}
scoped_refptr<ComputedStyle>
diff --git a/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc b/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
index b193f6f48e5..8fd9326caf0 100644
--- a/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
@@ -30,8 +30,8 @@ TEST_F(ProgressShadowElementTest, LayoutObjectIsNeeded) {
<progress id='prog' style='-webkit-appearance:none' />
)HTML");
- HTMLProgressElement* progress =
- ToHTMLProgressElement(GetDocument().getElementById("prog"));
+ auto* progress =
+ To<HTMLProgressElement>(GetDocument().getElementById("prog"));
ASSERT_TRUE(progress);
auto* shadow_element = To<Element>(progress->GetShadowRoot()->firstChild());
diff --git a/chromium/third_party/blink/renderer/core/html/track/cue_timeline.h b/chromium/third_party/blink/renderer/core/html/track/cue_timeline.h
index ad33240e593..ec9d9550c20 100644
--- a/chromium/third_party/blink/renderer/core/html/track/cue_timeline.h
+++ b/chromium/third_party/blink/renderer/core/html/track/cue_timeline.h
@@ -28,7 +28,7 @@ typedef Vector<CueInterval> CueList;
// This class manages the timeline and rendering updates of cues associated
// with TextTracks. Owned by a HTMLMediaElement.
-class CueTimeline final : public GarbageCollectedFinalized<CueTimeline> {
+class CueTimeline final : public GarbageCollected<CueTimeline> {
public:
CueTimeline(HTMLMediaElement&);
diff --git a/chromium/third_party/blink/renderer/core/html/track/html_track_element.cc b/chromium/third_party/blink/renderer/core/html/track/html_track_element.cc
index 66efed10dea..36fb6fc1cca 100644
--- a/chromium/third_party/blink/renderer/core/html/track/html_track_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/html_track_element.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/track/html_track_element.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -190,7 +191,7 @@ void HTMLTrackElement::LoadTimerFired(TimerBase*) {
return;
if (track_)
- track_->RemoveAllCues();
+ track_->Reset();
url_ = url;
@@ -287,6 +288,13 @@ void HTMLTrackElement::NewCuesAvailable(TextTrackLoader* loader) {
HeapVector<Member<TextTrackCue>> new_cues;
loader_->GetNewCues(new_cues);
+ HeapVector<Member<CSSStyleSheet>> new_sheets;
+ loader_->GetNewStyleSheets(new_sheets);
+
+ if (!new_sheets.IsEmpty()) {
+ track_->SetCSSStyleSheets(std::move(new_sheets));
+ }
+
track_->AddListOfCues(new_cues);
}
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track.cc b/chromium/third_party/blink/renderer/core/html/track/text_track.cc
index d2cb695edfd..703706b3b98 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track.cc
@@ -165,7 +165,7 @@ TextTrackCueList* TextTrack::cues() {
return nullptr;
}
-void TextTrack::RemoveAllCues() {
+void TextTrack::Reset() {
if (!cues_)
return;
@@ -178,6 +178,8 @@ void TextTrack::RemoveAllCues() {
cues_->RemoveAll();
if (active_cues_)
active_cues_->RemoveAll();
+
+ style_sheets_.clear();
}
void TextTrack::AddListOfCues(
@@ -239,6 +241,12 @@ void TextTrack::addCue(TextTrackCue* cue) {
GetCueTimeline()->AddCue(this, cue);
}
+void TextTrack::SetCSSStyleSheets(
+ HeapVector<Member<CSSStyleSheet>> style_sheets) {
+ DCHECK(style_sheets_.IsEmpty());
+ style_sheets_ = std::move(style_sheets);
+}
+
void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exception_state) {
DCHECK(cue);
@@ -372,6 +380,7 @@ void TextTrack::Trace(Visitor* visitor) {
visitor->Trace(cues_);
visitor->Trace(active_cues_);
visitor->Trace(track_list_);
+ visitor->Trace(style_sheets_);
TrackBase::Trace(visitor);
EventTargetWithInlineData::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track.h b/chromium/third_party/blink/renderer/core/html/track/text_track.h
index 1abd4c2485a..d8e3bc50371 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track.h
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track.h
@@ -28,6 +28,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_TEXT_TRACK_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/dom/events/event_target.h"
#include "third_party/blink/renderer/core/html/track/track_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -126,7 +127,7 @@ class CORE_EXPORT TextTrack : public EventTargetWithInlineData,
virtual bool IsDefault() const { return false; }
- void RemoveAllCues();
+ void Reset();
// EventTarget methods
const AtomicString& InterfaceName() const override;
@@ -134,6 +135,12 @@ class CORE_EXPORT TextTrack : public EventTargetWithInlineData,
void Trace(Visitor*) override;
+ const HeapVector<Member<CSSStyleSheet>>& GetCSSStyleSheets() const {
+ return style_sheets_;
+ }
+
+ void SetCSSStyleSheets(HeapVector<Member<CSSStyleSheet>>);
+
protected:
void AddListOfCues(HeapVector<Member<TextTrackCue>>&);
@@ -143,6 +150,7 @@ class CORE_EXPORT TextTrack : public EventTargetWithInlineData,
TextTrackCueList* EnsureTextTrackCueList();
Member<TextTrackCueList> cues_;
Member<TextTrackCueList> active_cues_;
+ HeapVector<Member<CSSStyleSheet>> style_sheets_;
Member<TextTrackList> track_list_;
AtomicString mode_;
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 95e245b900f..2a786fe32b3 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
@@ -140,6 +140,20 @@ VTTCueBox::VTTCueBox(Document& document)
SetShadowPseudoId(AtomicString("-webkit-media-text-track-display"));
}
+VTTCueBackgroundBox::VTTCueBackgroundBox(Document& document)
+ : HTMLDivElement(document) {
+ SetShadowPseudoId(TextTrackCue::CueShadowPseudoId());
+}
+
+void VTTCueBackgroundBox::Trace(blink::Visitor* visitor) {
+ visitor->Trace(track_);
+ HTMLDivElement::Trace(visitor);
+}
+
+void VTTCueBackgroundBox::SetTrack(TextTrack* track) {
+ track_ = track;
+}
+
void VTTCueBox::ApplyCSSProperties(
const VTTDisplayParameters& display_parameters) {
// http://dev.w3.org/html5/webvtt/#applying-css-properties-to-webvtt-node-objects
@@ -238,11 +252,10 @@ VTTCue::VTTCue(Document& document,
writing_direction_(kHorizontal),
cue_alignment_(kCenter),
vtt_node_tree_(nullptr),
- cue_background_box_(MakeGarbageCollected<HTMLDivElement>(document)),
+ cue_background_box_(MakeGarbageCollected<VTTCueBackgroundBox>(document)),
snap_to_lines_(true),
display_tree_should_change_(true) {
UseCounter::Count(document, WebFeature::kVTTCue);
- cue_background_box_->SetShadowPseudoId(CueShadowPseudoId());
}
VTTCue::~VTTCue() = default;
@@ -441,9 +454,11 @@ void VTTCue::setText(const String& text) {
}
void VTTCue::CreateVTTNodeTree() {
- if (!vtt_node_tree_)
- vtt_node_tree_ =
- VTTParser::CreateDocumentFragmentFromCueText(GetDocument(), text_);
+ if (!vtt_node_tree_) {
+ vtt_node_tree_ = VTTParser::CreateDocumentFragmentFromCueText(
+ GetDocument(), text_, this->track());
+ cue_background_box_->SetTrack(this->track());
+ }
}
void VTTCue::CopyVTTNodeToDOMTree(ContainerNode* vtt_node,
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 2ff89988337..fe16a16a72b 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
@@ -75,6 +75,26 @@ class VTTCueBox final : public HTMLDivElement {
float snap_to_lines_position_;
};
+class VTTCueBackgroundBox final : public HTMLDivElement {
+ public:
+ explicit VTTCueBackgroundBox(Document&);
+ bool IsVTTCueBackgroundBox() const override { return true; }
+ void SetTrack(TextTrack*);
+ void Trace(Visitor*) override;
+
+ const TextTrack* GetTrack() const { return track_; }
+
+ private:
+ Member<TextTrack> track_;
+};
+
+template <>
+struct DowncastTraits<VTTCueBackgroundBox> {
+ static bool AllowFrom(const Element& element) {
+ return element.IsVTTCueBackgroundBox();
+ }
+};
+
class VTTCue final : public TextTrackCue {
DEFINE_WRAPPERTYPEINFO();
@@ -192,7 +212,7 @@ class VTTCue final : public TextTrackCue {
Member<VTTRegion> region_;
Member<DocumentFragment> vtt_node_tree_;
- Member<HTMLDivElement> cue_background_box_;
+ Member<VTTCueBackgroundBox> cue_background_box_;
Member<VTTCueBox> display_tree_;
bool snap_to_lines_ : 1;
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
index db766921b1e..90d64e2a8f1 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.cc
@@ -76,6 +76,7 @@ Element& VTTElement::CloneWithoutAttributesAndChildren(
auto* clone = MakeGarbageCollected<VTTElement>(
static_cast<VTTNodeType>(web_vtt_node_type_), &factory);
clone->SetLanguage(language_);
+ clone->SetTrack(track_);
return *clone;
}
@@ -132,4 +133,13 @@ void VTTElement::SetIsPastNode(bool is_past_node) {
style_change_reason::kPseudoClass, style_change_extra_data::g_past));
}
+void VTTElement::SetTrack(TextTrack* track) {
+ track_ = track;
+}
+
+void VTTElement::Trace(blink::Visitor* visitor) {
+ visitor->Trace(track_);
+ Element::Trace(visitor);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.h b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
index 250ecd5657c..25a52b56d0b 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_element.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_VTT_VTT_ELEMENT_H_
#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
@@ -78,7 +79,13 @@ class VTTElement final : public Element {
return voice_attr;
}
+ const TextTrack* GetTrack() const { return track_; }
+
+ void SetTrack(TextTrack*);
+ void Trace(blink::Visitor*) override;
+
private:
+ Member<TextTrack> track_;
unsigned is_past_node_ : 1;
unsigned web_vtt_node_type_ : 4;
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
index 4b1220f239e..d6db8928949 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc
@@ -30,10 +30,14 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_parser.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_element.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_region.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h"
@@ -52,6 +56,7 @@ using namespace html_names;
const unsigned kFileIdentifierLength = 6;
const unsigned kRegionIdentifierLength = 6;
+const unsigned kStyleIdentifierLength = 5;
bool VTTParser::ParsePercentageValue(VTTScanner& value_scanner,
double& percentage) {
@@ -103,6 +108,12 @@ void VTTParser::GetNewCues(HeapVector<Member<TextTrackCue>>& output_cues) {
output_cues.swap(cue_list_);
}
+void VTTParser::GetNewStyleSheets(
+ HeapVector<Member<CSSStyleSheet>>& output_sheets) {
+ DCHECK(output_sheets.IsEmpty());
+ output_sheets.swap(style_sheets_);
+}
+
void VTTParser::ParseBytes(const char* data, size_t length) {
String text_data = decoder_->Decode(data, length);
line_reader_.Append(text_data);
@@ -146,6 +157,11 @@ void VTTParser::Parse() {
state_ = CollectRegionSettings(line);
break;
+ case kStyle:
+ // Collect style sheet
+ state_ = CollectStyleSheet(line);
+ break;
+
case kId:
// Steps 17 - 20 - Allow any number of line terminators, then initialize
// new cue values.
@@ -222,13 +238,55 @@ VTTParser::ParseState VTTParser::CollectRegionSettings(const String& line) {
return kRegion;
}
+VTTParser::ParseState VTTParser::CollectStyleSheet(const String& line) {
+ if (line.IsEmpty() || line.Contains("-->")) {
+ auto* parser_context = MakeGarbageCollected<CSSParserContext>(
+ *document_, NullURL(), true /* origin_clean */,
+ document_->GetReferrerPolicy(), UTF8Encoding(),
+ CSSParserContext::kLiveProfile,
+ ResourceFetchRestriction::kOnlyDataUrls);
+ auto* style_sheet_contents =
+ MakeGarbageCollected<StyleSheetContents>(parser_context);
+ CSSParser::ParseSheet(
+ parser_context, style_sheet_contents, current_content_.ToString(),
+ CSSDeferPropertyParsing::kNo, false /* allow_import_rules */);
+ auto* style_sheet =
+ MakeGarbageCollected<CSSStyleSheet>(style_sheet_contents);
+ style_sheet->SetAssociatedDocument(document_);
+ style_sheet->SetIsConstructed(true);
+ style_sheet->SetTitle("");
+ style_sheets_.push_back(style_sheet);
+
+ return CheckAndRecoverCue(line);
+ }
+
+ if (!current_content_.IsEmpty())
+ current_content_.Append('\n');
+ current_content_.Append(line);
+
+ return kStyle;
+}
+
VTTParser::ParseState VTTParser::CollectWebVTTBlock(const String& line) {
// collect a WebVTT block parsing. (WebVTT parser algorithm step 14)
- // If Region support is enabled.
- if (RuntimeEnabledFeatures::WebVTTRegionsEnabled() &&
- CheckAndCreateRegion(line))
- return kRegion;
+ if (!previous_line_.Contains("-->")) {
+ // If Region support is enabled.
+ if (RuntimeEnabledFeatures::WebVTTRegionsEnabled() &&
+ CheckAndCreateRegion(line))
+ return kRegion;
+
+ // line starts with the substring "STYLE" and remaining characters
+ // zero or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION
+ // (tab) characters expected other than these characters it is invalid.
+ if (RuntimeEnabledFeatures::EmbeddedVTTStylesheetsEnabled() &&
+ line.StartsWith("STYLE") &&
+ StringView(line, kStyleIdentifierLength)
+ .IsAllSpecialCharacters<IsASpace>()) {
+ current_content_.Clear();
+ return kStyle;
+ }
+ }
// Handle cue block.
ParseState state = CheckAndRecoverCue(line);
@@ -260,11 +318,9 @@ VTTParser::ParseState VTTParser::CheckAndRecoverCue(const String& line) {
}
bool VTTParser::CheckAndCreateRegion(const String& line) {
- if (previous_line_.Contains("-->"))
- return false;
// line starts with the substring "REGION" and remaining characters
// zero or more U+0020 SPACE characters or U+0009 CHARACTER TABULATION
- // (tab) characters expected other than these charecters it is invalid.
+ // (tab) characters expected other than these characters it is invalid.
if (line.StartsWith("REGION") && StringView(line, kRegionIdentifierLength)
.IsAllSpecialCharacters<IsASpace>()) {
current_region_ = VTTRegion::Create();
@@ -367,7 +423,8 @@ class VTTTreeBuilder {
STACK_ALLOCATED();
public:
- explicit VTTTreeBuilder(Document& document) : document_(&document) {}
+ explicit VTTTreeBuilder(Document& document, TextTrack* track)
+ : document_(&document), track_(track) {}
DocumentFragment* BuildFromString(const String& cue_text);
@@ -379,6 +436,7 @@ class VTTTreeBuilder {
Member<ContainerNode> current_node_;
Vector<AtomicString> language_stack_;
Member<Document> document_;
+ Member<TextTrack> track_;
};
DocumentFragment* VTTTreeBuilder::BuildFromString(const String& cue_text) {
@@ -406,8 +464,9 @@ DocumentFragment* VTTTreeBuilder::BuildFromString(const String& cue_text) {
DocumentFragment* VTTParser::CreateDocumentFragmentFromCueText(
Document& document,
- const String& cue_text) {
- VTTTreeBuilder tree_builder(document);
+ const String& cue_text,
+ TextTrack* track) {
+ VTTTreeBuilder tree_builder(document, track);
return tree_builder.BuildFromString(cue_text);
}
@@ -546,6 +605,8 @@ void VTTTreeBuilder::ConstructTreeFromToken(Document& document) {
break;
auto* child = MakeGarbageCollected<VTTElement>(node_type, &document);
+ child->SetTrack(track_);
+
if (!token_.Classes().IsEmpty())
child->setAttribute(kClassAttr, token_.Classes());
@@ -611,6 +672,7 @@ void VTTParser::Trace(Visitor* visitor) {
visitor->Trace(client_);
visitor->Trace(cue_list_);
visitor->Trace(region_map_);
+ visitor->Trace(style_sheets_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.h b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.h
index 4a4196d7bff..ede0025d12f 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_parser.h
@@ -59,7 +59,7 @@ class VTTParserClient : public GarbageCollectedMixin {
// Implementation of the WebVTT parser algorithm.
// https://w3c.github.io/webvtt/#webvtt-parser-algorithm
-class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
+class VTTParser final : public GarbageCollected<VTTParser> {
public:
enum ParseState {
kInitial,
@@ -68,7 +68,8 @@ class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
kTimingsAndSettings,
kCueText,
kRegion,
- kBadCue
+ kBadCue,
+ kStyle
};
VTTParser(VTTParserClient*, Document&);
@@ -100,7 +101,8 @@ class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
// Create the DocumentFragment representation of the WebVTT cue text.
static DocumentFragment* CreateDocumentFragmentFromCueText(Document&,
- const String&);
+ const String&,
+ TextTrack*);
// Input data to the parser to parse.
void ParseBytes(const char* data, size_t length);
@@ -109,6 +111,9 @@ class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
// Transfers ownership of last parsed cues to caller.
void GetNewCues(HeapVector<Member<TextTrackCue>>&);
+ // Transfers ownership of last parsed style sheets to caller.
+ void GetNewStyleSheets(HeapVector<Member<CSSStyleSheet>>&);
+
void Trace(Visitor*);
private:
@@ -126,9 +131,9 @@ class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
ParseState CollectRegionSettings(const String&);
ParseState CollectWebVTTBlock(const String&);
ParseState CheckAndRecoverCue(const String& line);
+ ParseState CollectStyleSheet(const String& line);
bool CheckAndCreateRegion(const String& line);
bool CheckAndStoreRegion(const String& line);
-
void CreateNewCue();
void ResetCueValues();
@@ -144,7 +149,7 @@ class VTTParser final : public GarbageCollectedFinalized<VTTParser> {
String current_settings_;
Member<VTTRegion> current_region_;
Member<VTTParserClient> client_;
-
+ HeapVector<Member<CSSStyleSheet>> style_sheets_;
HeapVector<Member<TextTrackCue>> cue_list_;
VTTRegionMap region_map_;
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 fc21269d7f6..83c1ece8d0b 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -191,35 +191,29 @@ SkImageInfo GetSkImageInfo(const scoped_refptr<StaticBitmapImage>& input) {
// This function results in a readback due to using SkImage::readPixels().
// Returns transparent black pixels if the input SkImageInfo.bounds() does
// not intersect with the input image boundaries.
-scoped_refptr<Uint8Array> CopyImageData(
- const scoped_refptr<StaticBitmapImage>& input,
- const SkImageInfo& info,
- const unsigned x = 0,
- const unsigned y = 0) {
+Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input,
+ const SkImageInfo& info,
+ const unsigned x = 0,
+ const unsigned y = 0) {
if (info.isEmpty())
- return nullptr;
+ return {};
sk_sp<SkImage> sk_image = input->PaintImageForCurrentFrame().GetSkImage();
if (sk_image->bounds().isEmpty())
- return nullptr;
- scoped_refptr<ArrayBuffer> dst_buffer =
- ArrayBuffer::CreateOrNull(info.computeMinByteSize(), 1);
- if (!dst_buffer)
- return nullptr;
- unsigned byte_length = dst_buffer->ByteLength();
- scoped_refptr<Uint8Array> dst_pixels =
- Uint8Array::Create(std::move(dst_buffer), 0, byte_length);
- if (!dst_pixels)
- return nullptr;
+ return {};
+
+ wtf_size_t byte_length =
+ base::checked_cast<wtf_size_t>(info.computeMinByteSize());
+ Vector<uint8_t> dst_buffer(byte_length);
+
bool read_pixels_successful =
- sk_image->readPixels(info, dst_pixels->Data(), info.minRowBytes(), x, y);
+ sk_image->readPixels(info, dst_buffer.data(), info.minRowBytes(), x, y);
DCHECK(read_pixels_successful);
if (!read_pixels_successful)
- return nullptr;
- return dst_pixels;
+ return {};
+ return dst_buffer;
}
-scoped_refptr<Uint8Array> CopyImageData(
- const scoped_refptr<StaticBitmapImage>& input) {
+Vector<uint8_t> CopyImageData(const scoped_refptr<StaticBitmapImage>& input) {
SkImageInfo info = GetSkImageInfo(input);
return CopyImageData(std::move(input), info);
}
@@ -238,18 +232,32 @@ scoped_refptr<StaticBitmapImage> FlipImageVertically(
// Unpremul code path results in a GPU readback if |input| is texture
// backed since CopyImageData() uses SkImage::readPixels() to extract the
// pixels from SkImage.
- scoped_refptr<Uint8Array> image_pixels = CopyImageData(input);
+ SkImageInfo info = GetSkImageInfo(input);
+ if (info.isEmpty())
+ return nullptr;
+
+ sk_sp<SkImage> sk_image = input->PaintImageForCurrentFrame().GetSkImage();
+ if (sk_image->bounds().isEmpty())
+ return nullptr;
+
+ sk_sp<SkData> image_pixels = TryAllocateSkData(info.computeMinByteSize());
if (!image_pixels)
return nullptr;
- SkImageInfo info = GetSkImageInfo(input);
- unsigned image_row_bytes = info.width() * info.bytesPerPixel();
+
+ uint8_t* writable_pixels =
+ static_cast<uint8_t*>(image_pixels->writable_data());
+ size_t image_row_bytes = static_cast<size_t>(info.minRowBytes64());
+ bool read_successful =
+ sk_image->readPixels(info, writable_pixels, image_row_bytes, 0, 0);
+ DCHECK(read_successful);
+
for (int i = 0; i < info.height() / 2; i++) {
- unsigned top_first_element = i * image_row_bytes;
- unsigned top_last_element = (i + 1) * image_row_bytes;
- unsigned bottom_first_element = (info.height() - 1 - i) * image_row_bytes;
- std::swap_ranges(image_pixels->Data() + top_first_element,
- image_pixels->Data() + top_last_element,
- image_pixels->Data() + bottom_first_element);
+ size_t top_first_element = i * image_row_bytes;
+ size_t top_last_element = (i + 1) * image_row_bytes;
+ size_t bottom_first_element = (info.height() - 1 - i) * image_row_bytes;
+ std::swap_ranges(&writable_pixels[top_first_element],
+ &writable_pixels[top_last_element],
+ &writable_pixels[bottom_first_element]);
}
return StaticBitmapImage::Create(std::move(image_pixels), info);
}
@@ -315,10 +323,21 @@ scoped_refptr<StaticBitmapImage> GetImageWithAlphaDisposition(
return StaticBitmapImage::Create(surface->makeImageSnapshot(),
image->ContextProviderWrapper());
}
+
// To unpremul, read back the pixels.
- auto dst_pixels = CopyImageData(image, info);
+
+ if (skia_image->bounds().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 =
+ skia_image->readPixels(info, writable_pixels, image_row_bytes, 0, 0);
+ DCHECK(read_successful);
return StaticBitmapImage::Create(std::move(dst_pixels), info);
}
@@ -712,19 +731,20 @@ ImageBitmap::ImageBitmap(ImageData* data,
}
// Copy / color convert the pixels
- scoped_refptr<ArrayBuffer> pixels_buffer =
- ArrayBuffer::CreateOrNull(SafeCast<uint32_t>(src_rect.Size().Area()),
- parsed_options.color_params.BytesPerPixel());
- if (!pixels_buffer)
+ size_t image_pixels_size;
+ if (!base::CheckMul(parsed_options.color_params.BytesPerPixel(),
+ static_cast<unsigned>(src_rect.Width()),
+ static_cast<unsigned>(src_rect.Height()))
+ .AssignIfValid(&image_pixels_size)) {
return;
- unsigned byte_length = pixels_buffer->ByteLength();
- scoped_refptr<Uint8Array> image_pixels =
- Uint8Array::Create(std::move(pixels_buffer), 0, byte_length);
+ }
+ sk_sp<SkData> image_pixels = TryAllocateSkData(image_pixels_size);
if (!image_pixels)
return;
if (!data->ImageDataInCanvasColorSettings(
parsed_options.color_params.ColorSpace(),
- parsed_options.color_params.PixelFormat(), image_pixels->Data(),
+ parsed_options.color_params.PixelFormat(),
+ static_cast<unsigned char*>(image_pixels->writable_data()),
kN32ColorType, &src_rect,
parsed_options.premultiply_alpha ? kPremultiplyAlpha
: kUnpremultiplyAlpha))
@@ -911,12 +931,12 @@ ImageBitmap* ImageBitmap::Create(const void* pixel_data,
void ImageBitmap::ResolvePromiseOnOriginalThread(
ScriptPromiseResolver* resolver,
- sk_sp<SkImage> skia_image,
bool origin_clean,
- std::unique_ptr<ParsedOptions> parsed_options) {
+ std::unique_ptr<ParsedOptions> parsed_options,
+ sk_sp<SkImage> skia_image) {
if (!skia_image) {
resolver->Reject(
- ScriptValue(resolver->GetScriptState(),
+ ScriptValue(resolver->GetScriptState()->GetIsolate(),
v8::Null(resolver->GetScriptState()->GetIsolate())));
return;
}
@@ -928,14 +948,14 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
}
if (!image) {
resolver->Reject(
- ScriptValue(resolver->GetScriptState(),
+ ScriptValue(resolver->GetScriptState()->GetIsolate(),
v8::Null(resolver->GetScriptState()->GetIsolate())));
return;
}
image = ApplyColorSpaceConversion(std::move(image), *(parsed_options.get()));
if (!image) {
resolver->Reject(
- ScriptValue(resolver->GetScriptState(),
+ ScriptValue(resolver->GetScriptState()->GetIsolate(),
v8::Null(resolver->GetScriptState()->GetIsolate())));
return;
}
@@ -945,11 +965,10 @@ void ImageBitmap::ResolvePromiseOnOriginalThread(
}
void ImageBitmap::RasterizeImageOnBackgroundThread(
- ScriptPromiseResolver* resolver,
sk_sp<PaintRecord> paint_record,
const IntRect& dst_rect,
- bool origin_clean,
- std::unique_ptr<ParsedOptions> parsed_options) {
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback) {
DCHECK(!IsMainThread());
SkImageInfo info =
SkImageInfo::MakeN32Premul(dst_rect.Width(), dst_rect.Height());
@@ -959,14 +978,9 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
paint_record->Playback(surface->getCanvas());
skia_image = surface->makeImageSnapshot();
}
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- Thread::MainThread()->GetTaskRunner();
PostCrossThreadTask(
*task_runner, FROM_HERE,
- CrossThreadBindOnce(&ResolvePromiseOnOriginalThread,
- WrapCrossThreadPersistent(resolver),
- std::move(skia_image), origin_clean,
- WTF::Passed(std::move(parsed_options))));
+ CrossThreadBindOnce(std::move(callback), std::move(skia_image)));
}
ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
@@ -1017,11 +1031,13 @@ ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
std::make_unique<ParsedOptions>(parsed_options);
worker_pool::PostTask(
FROM_HERE,
- CrossThreadBindOnce(&RasterizeImageOnBackgroundThread,
- WrapCrossThreadPersistent(resolver),
- std::move(paint_record), draw_dst_rect,
- !image->WouldTaintOrigin(),
- WTF::Passed(std::move(passed_parsed_options))));
+ CrossThreadBindOnce(
+ &RasterizeImageOnBackgroundThread, std::move(paint_record),
+ draw_dst_rect, Thread::MainThread()->GetTaskRunner(),
+ CrossThreadBindOnce(&ResolvePromiseOnOriginalThread,
+ WrapCrossThreadPersistent(resolver),
+ !image->WouldTaintOrigin(),
+ WTF::Passed(std::move(passed_parsed_options)))));
return promise;
}
@@ -1041,9 +1057,8 @@ CanvasColorParams ImageBitmap::GetCanvasColorParams() {
return CanvasColorParams(GetSkImageInfo(image_));
}
-scoped_refptr<Uint8Array> ImageBitmap::CopyBitmapData(
- AlphaDisposition alpha_op,
- DataU8ColorType u8_color_type) {
+Vector<uint8_t> ImageBitmap::CopyBitmapData(AlphaDisposition alpha_op,
+ DataU8ColorType u8_color_type) {
DCHECK(alpha_op != kDontChangeAlpha);
SkImageInfo info = GetSkImageInfo(image_);
auto color_type = info.colorType();
@@ -1057,7 +1072,7 @@ scoped_refptr<Uint8Array> ImageBitmap::CopyBitmapData(
return CopyImageData(image_, info);
}
-scoped_refptr<Uint8Array> ImageBitmap::CopyBitmapData() {
+Vector<uint8_t> ImageBitmap::CopyBitmapData() {
return CopyImageData(image_);
}
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 bea78c0d82d..f4fde0b280a 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -7,6 +7,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "base/sequenced_task_runner.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/canvas/image_element_base.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
namespace blink {
@@ -120,9 +122,9 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
static ImageBitmap* Take(ScriptPromiseResolver*, sk_sp<SkImage>);
scoped_refptr<StaticBitmapImage> BitmapImage() const { return image_; }
- scoped_refptr<Uint8Array> CopyBitmapData();
- scoped_refptr<Uint8Array> CopyBitmapData(AlphaDisposition,
- DataU8ColorType = kRGBAColorType);
+ Vector<uint8_t> CopyBitmapData();
+ Vector<uint8_t> CopyBitmapData(AlphaDisposition,
+ DataU8ColorType = kRGBAColorType);
unsigned width() const;
unsigned height() const;
IntSize Size() const;
@@ -172,14 +174,14 @@ class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
private:
void UpdateImageBitmapMemoryUsage();
static void ResolvePromiseOnOriginalThread(ScriptPromiseResolver*,
- sk_sp<SkImage>,
bool origin_clean,
- std::unique_ptr<ParsedOptions>);
- static void RasterizeImageOnBackgroundThread(ScriptPromiseResolver*,
- sk_sp<PaintRecord>,
- const IntRect&,
- bool origin_clean,
- std::unique_ptr<ParsedOptions>);
+ std::unique_ptr<ParsedOptions>,
+ sk_sp<SkImage>);
+ static void RasterizeImageOnBackgroundThread(
+ sk_sp<PaintRecord>,
+ const IntRect&,
+ scoped_refptr<base::SequencedTaskRunner>,
+ WTF::CrossThreadOnceFunction<void(sk_sp<SkImage>)> callback);
scoped_refptr<StaticBitmapImage> image_;
bool is_neutered_ = false;
int32_t memory_usage_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
index 465ccbfa787..60bbce8336c 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
@@ -61,7 +61,7 @@ class ImageBitmapSource;
class ImageBitmapOptions;
class ImageBitmapFactories final
- : public GarbageCollectedFinalized<ImageBitmapFactories>,
+ : public GarbageCollected<ImageBitmapFactories>,
public Supplement<LocalDOMWindow>,
public Supplement<WorkerGlobalScope>,
public NameClient {
@@ -102,10 +102,9 @@ class ImageBitmapFactories final
}
private:
- class ImageBitmapLoader final
- : public GarbageCollectedFinalized<ImageBitmapLoader>,
- public ContextLifecycleObserver,
- public FileReaderLoaderClient {
+ class ImageBitmapLoader final : public GarbageCollected<ImageBitmapLoader>,
+ public ContextLifecycleObserver,
+ public FileReaderLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ImageBitmapLoader);
public:
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 1826a4b1afd..fd8cf8987ae 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.cc
@@ -47,7 +47,12 @@
#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/local_caret_rect.h"
#include "third_party/blink/renderer/core/editing/selection_controller.h"
+#include "third_party/blink/renderer/core/editing/selection_template.h"
+#include "third_party/blink/renderer/core/editing/text_affinity.h"
+#include "third_party/blink/renderer/core/editing/visible_position.h"
+#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
@@ -93,6 +98,8 @@
#include "third_party/blink/renderer/core/style/cursor_data.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
+#include "third_party/blink/renderer/platform/geometry/int_point.h"
+#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -122,6 +129,41 @@ bool ShouldRefetchEventTarget(const MouseEventWithHitTestResults& mev) {
return false;
}
+IntPoint GetSelectionStartpoint(const PositionWithAffinity& position) {
+ const LocalCaretRect& local_caret_rect = LocalCaretRectOfPosition(position);
+ if (local_caret_rect.IsEmpty())
+ return IntPoint();
+ const IntRect rect = AbsoluteCaretBoundsOf(position);
+ // In a multiline edit, rect.MaxY() would end up on the next line, so
+ // take the midpoint in order to use this corner point directly.
+ if (local_caret_rect.layout_object->IsHorizontalWritingMode())
+ return {rect.X(), (rect.Y() + rect.MaxY()) / 2};
+
+ // When text is vertical, rect.MaxX() would end up on the next line, so
+ // take the midpoint in order to use this corner point directly.
+ return {(rect.X() + rect.MaxX()) / 2, rect.Y()};
+}
+
+IntPoint GetSelectionEndpoint(const PositionWithAffinity& position) {
+ const LocalCaretRect& local_caret_rect = LocalCaretRectOfPosition(position);
+ if (local_caret_rect.IsEmpty())
+ return IntPoint();
+ const IntRect rect = AbsoluteCaretBoundsOf(position);
+ // In a multiline edit, rect.MaxY() would end up on the next line, so
+ // take the midpoint in order to use this corner point directly.
+ if (local_caret_rect.layout_object->IsHorizontalWritingMode())
+ return {rect.X(), (rect.Y() + rect.MaxY()) / 2};
+
+ // When text is vertical, rect.MaxX() would end up on the next line, so
+ // take the midpoint in order to use this corner point directly.
+ return {(rect.X() + rect.MaxX()) / 2, rect.Y()};
+}
+
+bool ContainsEvenAtEdge(const IntRect& rect, const IntPoint& point) {
+ return point.X() >= rect.X() && point.X() <= rect.MaxX() &&
+ point.Y() >= rect.Y() && point.Y() <= rect.MaxY();
+}
+
} // namespace
// The amount of time to wait for a cursor update on style and layout changes
@@ -1427,6 +1469,10 @@ void EventHandler::ResetMousePositionForPointerUnlock() {
pointer_event_manager_->RemoveLastMousePosition();
}
+bool EventHandler::LongTapShouldInvokeContextMenu() {
+ return gesture_manager_->LongTapShouldInvokeContextMenu();
+}
+
WebInputEventResult EventHandler::DispatchMousePointerEvent(
const WebInputEvent::Type event_type,
Element* target_element,
@@ -2025,15 +2071,41 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
if (!override_target_element && ShouldShowContextMenuAtSelection(selection)) {
DCHECK(!doc->NeedsLayoutTreeUpdate());
- IntRect first_rect =
- FirstRectForRange(selection.ComputeVisibleSelectionInDOMTree()
- .ToNormalizedEphemeralRange());
+ // Enclose the selection rect fully between the handles. If the handles are
+ // on the same line, the selection rect is empty.
+ const SelectionInDOMTree& visible_selection =
+ selection.ComputeVisibleSelectionInDOMTree().AsSelection();
+ const PositionWithAffinity start_position(
+ visible_selection.ComputeStartPosition(), visible_selection.Affinity());
+ const IntPoint start_point = GetSelectionStartpoint(start_position);
+ const PositionWithAffinity end_position(
+ visible_selection.ComputeEndPosition(), visible_selection.Affinity());
+ const IntPoint end_point = GetSelectionEndpoint(end_position);
+
+ int left = std::min(start_point.X(), end_point.X());
+ int top = std::min(start_point.Y(), end_point.Y());
+ int right = std::max(start_point.X(), end_point.X());
+ int bottom = std::max(start_point.Y(), end_point.Y());
+
+ // Intersect the selection rect and the visible bounds of focused_element.
+ if (focused_element) {
+ IntRect clipped_rect = view->ViewportToFrame(
+ focused_element->VisibleBoundsInVisualViewport());
+ left = std::max(clipped_rect.X(), left);
+ top = std::max(clipped_rect.Y(), top);
+ right = std::min(clipped_rect.MaxX(), right);
+ bottom = std::min(clipped_rect.MaxY(), bottom);
+ }
+ IntRect selection_rect = IntRect(left, top, right - left, bottom - top);
- int x = first_rect.X();
- // In a multiline edit, firstRect.maxY() would end up on the next line, so
- // take the midpoint.
- int y = (first_rect.MaxY() + first_rect.Y()) / 2;
- location_in_root_frame = view->ConvertToRootFrame(IntPoint(x, y));
+ if (ContainsEvenAtEdge(selection_rect, start_point)) {
+ location_in_root_frame = view->ConvertToRootFrame(start_point);
+ } else if (ContainsEvenAtEdge(selection_rect, end_point)) {
+ location_in_root_frame = view->ConvertToRootFrame(end_point);
+ } else {
+ location_in_root_frame =
+ view->ConvertToRootFrame(selection_rect.Center());
+ }
} else if (focused_element) {
IntRect clipped_rect = focused_element->BoundsInViewport();
location_in_root_frame =
@@ -2335,11 +2407,7 @@ WebInputEventResult EventHandler::PassMouseMoveEventToSubframe(
WebInputEventResult EventHandler::PassMouseReleaseEventToSubframe(
MouseEventWithHitTestResults& mev,
LocalFrame* subframe) {
- WebInputEventResult result =
- subframe->GetEventHandler().HandleMouseReleaseEvent(mev.Event());
- if (result != WebInputEventResult::kNotHandled)
- return result;
- return WebInputEventResult::kHandledSystem;
+ return subframe->GetEventHandler().HandleMouseReleaseEvent(mev.Event());
}
void EventHandler::CaptureMouseEventsToWidget(bool capture) {
diff --git a/chromium/third_party/blink/renderer/core/input/event_handler.h b/chromium/third_party/blink/renderer/core/input/event_handler.h
index 26a8dcadfbc..fc5d5244ead 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.h
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.h
@@ -79,8 +79,7 @@ class WebMouseEvent;
class WebMouseWheelEvent;
// Handles events for Pointers (Mouse/Touch), HitTests, DragAndDrop, etc.
-class CORE_EXPORT EventHandler final
- : public GarbageCollectedFinalized<EventHandler> {
+class CORE_EXPORT EventHandler final : public GarbageCollected<EventHandler> {
public:
explicit EventHandler(LocalFrame&);
void Trace(blink::Visitor*);
@@ -299,6 +298,8 @@ class CORE_EXPORT EventHandler final
// restart from the lock position.
void ResetMousePositionForPointerUnlock();
+ bool LongTapShouldInvokeContextMenu();
+
private:
enum NoCursorChangeType { kNoCursorChange };
@@ -461,8 +462,6 @@ class CORE_EXPORT EventHandler final
double max_mouse_moved_duration_;
- bool long_tap_should_invoke_context_menu_;
-
TaskRunnerTimer<EventHandler> active_interval_timer_;
// last_show_press_timestamp_ prevents the active state rewrited by
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 dabf3969d33..58d90326239 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
@@ -1044,112 +1044,7 @@ TEST_F(EventHandlerLatencyTest, NeedsUnbufferedInput) {
ASSERT_FALSE(chrome_client_->ReceivedRequestForUnbufferedInput());
}
-class NavigationCapturingFrameClient : public EmptyLocalFrameClient {
- public:
- NavigationCapturingFrameClient() = default;
-
- bool NavigateBackForward(int offset, bool from_script) const override {
- offset_ = offset;
- return true;
- }
-
- int Offset() const { return offset_; }
-
- private:
- mutable int offset_ = 0;
-};
-
-class EventHandlerNavigationTest : public EventHandlerTest {
- public:
- EventHandlerNavigationTest() = default;
-
- void SetUp() override {
- frame_client_ = MakeGarbageCollected<NavigationCapturingFrameClient>();
- Page::PageClients clients;
- FillWithEmptyClients(clients);
- SetupPageWithClients(&clients, frame_client_);
- }
-
- int Offset() { return frame_client_->Offset(); }
-
- private:
- Persistent<NavigationCapturingFrameClient> frame_client_;
-};
-
-TEST_F(EventHandlerNavigationTest, MouseButtonsNavigate) {
- SetHtmlInnerHTML("<div>");
-
- EXPECT_EQ(0, Offset());
-
- WebMouseEvent mouse_back_event(
- WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
- WebPointerProperties::Button::kBack, 0, WebInputEvent::kNoModifiers,
- base::TimeTicks::Now());
- mouse_back_event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
- mouse_back_event);
-
- EXPECT_EQ(-1, Offset());
-
- WebMouseEvent mouse_forward_event(
- WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
- WebPointerProperties::Button::kForward, 0, WebInputEvent::kNoModifiers,
- base::TimeTicks::Now());
- mouse_forward_event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
- mouse_forward_event);
-
- EXPECT_EQ(1, Offset());
-}
-
-TEST_F(EventHandlerNavigationTest, MouseButtonsDontNavigate) {
- SetHtmlInnerHTML("<div>");
- GetDocument().GetSettings()->SetScriptEnabled(true);
- Element* script = GetDocument().CreateRawElement(html_names::kScriptTag);
- script->SetInnerHTMLFromString(
- "document.addEventListener('mouseup', event => "
- "event.preventDefault());");
- GetDocument().body()->AppendChild(script);
-
- EXPECT_EQ(0, Offset());
-
- WebMouseEvent mouse_back_event(
- WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
- WebPointerProperties::Button::kBack, 0, WebInputEvent::kNoModifiers,
- base::TimeTicks::Now());
- mouse_back_event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
- mouse_back_event);
-
- EXPECT_EQ(0, Offset());
-
- WebMouseEvent mouse_forward_event(
- WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
- WebPointerProperties::Button::kForward, 0, WebInputEvent::kNoModifiers,
- base::TimeTicks::Now());
- mouse_forward_event.SetFrameScale(1);
- GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
- mouse_forward_event);
-
- EXPECT_EQ(0, Offset());
-}
-
-class EventHandlerScrollbarGestureInjectionTest : public SimTest {
- public:
- EventHandlerScrollbarGestureInjectionTest() = default;
-
- void SetUp() override {
- scoped_feature_list_.InitAndEnableFeature(
- features::kScrollbarInjectScrollGestures);
- SimTest::SetUp();
- }
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(EventHandlerScrollbarGestureInjectionTest,
- MouseUpOffScrollbarGeneratesScrollEnd) {
+TEST_F(EventHandlerSimTest, MouseUpOffScrollbarGeneratesScrollEnd) {
WebView().MainFrameWidget()->Resize(WebSize(800, 600));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1223,7 +1118,7 @@ TEST_F(EventHandlerScrollbarGestureInjectionTest,
}
}
-TEST_F(EventHandlerScrollbarGestureInjectionTest, MouseUpOnlyOnScrollbar) {
+TEST_F(EventHandlerSimTest, MouseUpOnlyOnScrollbar) {
WebView().MainFrameWidget()->Resize(WebSize(800, 600));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1275,7 +1170,7 @@ TEST_F(EventHandlerScrollbarGestureInjectionTest, MouseUpOnlyOnScrollbar) {
EXPECT_EQ(WebWidgetClient().GetInjectedScrollGestureData().size(), 0u);
}
-TEST_F(EventHandlerScrollbarGestureInjectionTest, RightClickNoGestures) {
+TEST_F(EventHandlerSimTest, RightClickNoGestures) {
WebView().MainFrameWidget()->Resize(WebSize(800, 600));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -1320,8 +1215,7 @@ TEST_F(EventHandlerScrollbarGestureInjectionTest, RightClickNoGestures) {
#define MAYBE_GestureTapWithScrollSnaps GestureTapWithScrollSnaps
#endif
-TEST_F(EventHandlerScrollbarGestureInjectionTest,
- MAYBE_GestureTapWithScrollSnaps) {
+TEST_F(EventHandlerSimTest, MAYBE_GestureTapWithScrollSnaps) {
// Create a page that has scroll snaps enabled for a scroller. Tap on the
// scrollbar and verify that the SnapController does not immediately cancel
// the resulting animation during the handling of GestureScrollEnd - this
@@ -1398,7 +1292,7 @@ TEST_F(EventHandlerScrollbarGestureInjectionTest,
gsb.data.scroll_begin.delta_x_hint = -gsb_data.delta.width;
gsb.data.scroll_begin.delta_y_hint = -gsb_data.delta.height;
gsb.data.scroll_begin.scrollable_area_element_id =
- gsb_data.scrollable_area_element_id.GetInternalValue();
+ gsb_data.scrollable_area_element_id.GetStableId();
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(gsb);
WebGestureEvent gsu{WebInputEvent::kGestureScrollUpdate,
WebInputEvent::kNoModifiers,
@@ -1761,8 +1655,8 @@ TEST_F(EventHandlerSimTest, TestUpdateHoverAfterMainThreadScrollAtBeginFrame) {
LocalFrameView* frame_view = GetDocument().View();
constexpr float delta_y = 500;
InjectScrollFromGestureEvents(
- frame_view->LayoutViewport()->GetCompositorElementId().GetInternalValue(),
- 0, delta_y);
+ frame_view->LayoutViewport()->GetCompositorElementId().GetStableId(), 0,
+ delta_y);
ASSERT_EQ(500, frame_view->LayoutViewport()->GetScrollOffset().Height());
EXPECT_EQ("currently hovered", element1.InnerHTML().Utf8());
EXPECT_EQ("hover over me", element2.InnerHTML().Utf8());
@@ -1836,7 +1730,7 @@ TEST_F(EventHandlerSimTest,
// and mark hover state dirty in ScrollManager.
constexpr float delta_y = 1000;
InjectScrollFromGestureEvents(
- iframe_scrollable_area->GetCompositorElementId().GetInternalValue(), 0,
+ iframe_scrollable_area->GetCompositorElementId().GetStableId(), 0,
delta_y);
LocalFrameView* frame_view = GetDocument().View();
ASSERT_EQ(0, frame_view->LayoutViewport()->GetScrollOffset().Height());
@@ -1968,7 +1862,7 @@ TEST_F(EventHandlerSimTest,
scroller->GetLayoutBox()->GetScrollableArea();
constexpr float delta_y = 300;
InjectScrollFromGestureEvents(
- scrollable_area->GetCompositorElementId().GetInternalValue(), 0, delta_y);
+ scrollable_area->GetCompositorElementId().GetStableId(), 0, delta_y);
ASSERT_EQ(300, scrollable_area->GetScrollOffset().Height());
EXPECT_TRUE(target1->IsHovered());
EXPECT_FALSE(target2->IsHovered());
@@ -2121,7 +2015,7 @@ TEST_F(EventHandlerSimTest, NeverExposeKeyboardEvent) {
GetDocument().GetSettings()->SetDontSendKeyEventsToJavascript(true);
GetDocument().GetSettings()->SetScrollAnimatorEnabled(false);
GetDocument().GetSettings()->SetWebAppScope(GetDocument().Url());
- GetDocument().View()->SetDisplayMode(kWebDisplayModeFullscreen);
+ GetDocument().View()->SetDisplayMode(blink::mojom::DisplayMode::kFullscreen);
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -2457,7 +2351,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScroll) {
ScrollableArea* scrollable_area =
scroller->GetLayoutBox()->GetScrollableArea();
gesture_scroll_begin.data.scroll_begin.scrollable_area_element_id =
- scrollable_area->GetCompositorElementId().GetInternalValue();
+ scrollable_area->GetCompositorElementId().GetStableId();
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
gesture_scroll_begin);
@@ -2517,7 +2411,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollIFrame) {
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = -delta_y;
gesture_scroll_begin.data.scroll_begin.scrollable_area_element_id =
- scrollable_area->GetCompositorElementId().GetInternalValue();
+ scrollable_area->GetCompositorElementId().GetStableId();
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
gesture_scroll_begin);
@@ -2568,7 +2462,7 @@ TEST_F(EventHandlerSimTest, ElementTargetedGestureScrollViewport) {
gesture_scroll_begin.data.scroll_begin.delta_x_hint = 0;
gesture_scroll_begin.data.scroll_begin.delta_y_hint = -delta_y;
gesture_scroll_begin.data.scroll_begin.scrollable_area_element_id =
- visual_viewport.GetCompositorElementId().GetInternalValue();
+ visual_viewport.GetCompositorElementId().GetStableId();
GetDocument().GetFrame()->GetEventHandler().HandleGestureEvent(
gesture_scroll_begin);
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 ebf43f8b7b7..76b7d7bf604 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -140,6 +140,10 @@ WebInputEventResult GestureManager::HandleGestureEventInFrame(
return WebInputEventResult::kNotHandled;
}
+bool GestureManager::LongTapShouldInvokeContextMenu() const {
+ return long_tap_should_invoke_context_menu_;
+}
+
WebInputEventResult GestureManager::HandleGestureTapDown(
const GestureEventWithHitTestResults& targeted_event) {
suppress_mouse_events_from_gestures_ =
@@ -372,12 +376,10 @@ WebInputEventResult GestureManager::HandleGestureLongPress(
WebInputEventResult GestureManager::HandleGestureLongTap(
const GestureEventWithHitTestResults& targeted_event) {
-#if !defined(OS_ANDROID)
- if (long_tap_should_invoke_context_menu_) {
+ if (LongTapShouldInvokeContextMenu()) {
long_tap_should_invoke_context_menu_ = false;
return SendContextMenuEventForGesture(targeted_event);
}
-#endif
return WebInputEventResult::kNotHandled;
}
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 7d9c04624b7..69a18d787a5 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.h
@@ -22,8 +22,8 @@ class MouseEventManager;
// This class takes care of gestures and delegating the action based on the
// gesture to the responsible class.
-class CORE_EXPORT GestureManager
- : public GarbageCollectedFinalized<GestureManager> {
+class CORE_EXPORT GestureManager final
+ : public GarbageCollected<GestureManager> {
public:
GestureManager(LocalFrame&,
ScrollManager&,
@@ -38,6 +38,7 @@ class CORE_EXPORT GestureManager
WebInputEvent::Type);
WebInputEventResult HandleGestureEventInFrame(
const GestureEventWithHitTestResults&);
+ bool LongTapShouldInvokeContextMenu() const;
private:
WebInputEventResult HandleGestureShowPress();
diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
index a09ac6bdfae..b229fe41e9d 100644
--- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -216,10 +216,11 @@ WebInputEventResult KeyboardEventManager::KeyEvent(
if (!should_send_key_events_to_js &&
frame_->GetDocument()->IsInWebAppScope()) {
DCHECK(frame_->View());
- WebDisplayMode display_mode = frame_->View()->DisplayMode();
- should_send_key_events_to_js = display_mode == kWebDisplayModeMinimalUi ||
- display_mode == kWebDisplayModeStandalone ||
- display_mode == kWebDisplayModeFullscreen;
+ blink::mojom::DisplayMode display_mode = frame_->View()->DisplayMode();
+ should_send_key_events_to_js =
+ display_mode == blink::mojom::DisplayMode::kMinimalUi ||
+ display_mode == blink::mojom::DisplayMode::kStandalone ||
+ display_mode == blink::mojom::DisplayMode::kFullscreen;
}
// We have 2 level of not exposing key event to js, not send and send but not
diff --git a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
index 1c4373bcdfa..15d3b7b9f96 100644
--- a/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/keyboard_event_manager.h
@@ -24,8 +24,8 @@ class WebKeyboardEvent;
enum class OverrideCapsLockState { kDefault, kOn, kOff };
-class CORE_EXPORT KeyboardEventManager
- : public GarbageCollectedFinalized<KeyboardEventManager> {
+class CORE_EXPORT KeyboardEventManager final
+ : public GarbageCollected<KeyboardEventManager> {
public:
static const int kAccessKeyModifiers =
// TODO(crbug.com/618397): Add a settings to control this behavior.
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 fef96683633..79575861133 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
@@ -78,10 +78,9 @@ void UpdateMouseMovementXY(const WebMouseEvent& mouse_event,
if (dom_window && dom_window->GetFrame()) {
LocalFrame* frame = dom_window->GetFrame();
if (frame->GetPage()->DeviceScaleFactorDeprecated() == 1) {
- device_scale_factor = frame->GetPage()
- ->GetChromeClient()
- .GetScreenInfo()
- .device_scale_factor;
+ ChromeClient& chrome_client = frame->GetChromeClient();
+ device_scale_factor =
+ chrome_client.GetScreenInfo(*frame).device_scale_factor;
}
}
// movementX/Y is type int for now, so we need to truncated the coordinates
@@ -97,6 +96,45 @@ void UpdateMouseMovementXY(const WebMouseEvent& mouse_event,
}
}
+void SetMouseEventAttributes(MouseEventInit* initializer,
+ Node* target_node,
+ const AtomicString& mouse_event_type,
+ const WebMouseEvent& mouse_event,
+ const String& canvas_region_id,
+ const FloatPoint* last_position,
+ EventTarget* related_target,
+ int click_count) {
+ bool is_mouse_enter_or_leave =
+ mouse_event_type == event_type_names::kMouseenter ||
+ mouse_event_type == event_type_names::kMouseleave;
+
+ initializer->setBubbles(!is_mouse_enter_or_leave);
+ initializer->setCancelable(!is_mouse_enter_or_leave);
+ MouseEvent::SetCoordinatesFromWebPointerProperties(
+ mouse_event.FlattenTransform(), target_node->GetDocument().domWindow(),
+ initializer);
+ UpdateMouseMovementXY(mouse_event, last_position,
+ target_node->GetDocument().domWindow(), initializer);
+ initializer->setButton(static_cast<int16_t>(mouse_event.button));
+ initializer->setButtons(
+ MouseEvent::WebInputEventModifiersToButtons(mouse_event.GetModifiers()));
+ initializer->setView(target_node->GetDocument().domWindow());
+ initializer->setComposed(true);
+ initializer->setDetail(click_count);
+ initializer->setRegion(canvas_region_id);
+ initializer->setRelatedTarget(related_target);
+ UIEventWithKeyState::SetFromWebInputEventModifiers(
+ initializer,
+ static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers()));
+ initializer->setSourceCapabilities(
+ target_node->GetDocument().domWindow()
+ ? target_node->GetDocument()
+ .domWindow()
+ ->GetInputDeviceCapabilities()
+ ->FiresTouchEvents(mouse_event.FromTouch())
+ : nullptr);
+}
+
// The amount of time to wait before sending a fake mouse event triggered
// during a scroll.
constexpr base::TimeDelta kFakeMouseMoveIntervalDuringScroll =
@@ -249,7 +287,20 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
const String& canvas_region_id,
const FloatPoint* last_position,
EventTarget* related_target,
- bool check_for_listener) {
+ bool check_for_listener,
+ const PointerId& pointer_id,
+ const String& pointer_type) {
+ DCHECK(mouse_event_type == event_type_names::kMouseup ||
+ mouse_event_type == event_type_names::kMousedown ||
+ mouse_event_type == event_type_names::kMousemove ||
+ mouse_event_type == event_type_names::kMouseout ||
+ mouse_event_type == event_type_names::kMouseover ||
+ mouse_event_type == event_type_names::kMouseleave ||
+ mouse_event_type == event_type_names::kMouseenter ||
+ mouse_event_type == event_type_names::kContextmenu ||
+ 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))) {
Node* target_node = target->ToNode();
@@ -257,47 +308,42 @@ WebInputEventResult MouseEventManager::DispatchMouseEvent(
if (mouse_event_type == event_type_names::kMouseup ||
mouse_event_type == event_type_names::kMousedown ||
mouse_event_type == event_type_names::kClick ||
- mouse_event_type == event_type_names::kAuxclick ||
- mouse_event_type == event_type_names::kDblclick) {
+ mouse_event_type == event_type_names::kAuxclick) {
click_count = click_count_;
}
- bool is_mouse_enter_or_leave =
- mouse_event_type == event_type_names::kMouseenter ||
- mouse_event_type == event_type_names::kMouseleave;
- MouseEventInit* initializer = MouseEventInit::Create();
- initializer->setBubbles(!is_mouse_enter_or_leave);
- initializer->setCancelable(!is_mouse_enter_or_leave);
- MouseEvent::SetCoordinatesFromWebPointerProperties(
- mouse_event.FlattenTransform(), target_node->GetDocument().domWindow(),
- initializer);
- UpdateMouseMovementXY(mouse_event, last_position,
- target_node->GetDocument().domWindow(), initializer);
- initializer->setButton(static_cast<int16_t>(mouse_event.button));
- initializer->setButtons(MouseEvent::WebInputEventModifiersToButtons(
- mouse_event.GetModifiers()));
- initializer->setView(target_node->GetDocument().domWindow());
- initializer->setComposed(true);
- initializer->setDetail(click_count);
- initializer->setRegion(canvas_region_id);
- initializer->setRelatedTarget(related_target);
- UIEventWithKeyState::SetFromWebInputEventModifiers(
- initializer,
- static_cast<WebInputEvent::Modifiers>(mouse_event.GetModifiers()));
- initializer->setSourceCapabilities(
- target_node->GetDocument().domWindow()
- ? target_node->GetDocument()
- .domWindow()
- ->GetInputDeviceCapabilities()
- ->FiresTouchEvents(mouse_event.FromTouch())
- : nullptr);
-
- MouseEvent* event = MouseEvent::Create(
- mouse_event_type, initializer, mouse_event.TimeStamp(),
- mouse_event.FromTouch() ? MouseEvent::kFromTouch
- : MouseEvent::kRealOrIndistinguishable,
- mouse_event.menu_source_type);
-
- DispatchEventResult dispatch_result = target->DispatchEvent(*event);
+
+ DispatchEventResult dispatch_result;
+
+ if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
+ (mouse_event_type == event_type_names::kContextmenu ||
+ mouse_event_type == event_type_names::kClick ||
+ mouse_event_type == event_type_names::kAuxclick)) {
+ PointerEventInit* initializer = PointerEventInit::Create();
+ SetMouseEventAttributes(initializer, target_node, mouse_event_type,
+ mouse_event, canvas_region_id, last_position,
+ related_target, click_count);
+ initializer->setPointerId(pointer_id);
+ initializer->setPointerType(pointer_type);
+ PointerEvent* event = PointerEvent::Create(
+ mouse_event_type, initializer, mouse_event.TimeStamp(),
+ mouse_event.FromTouch() ? MouseEvent::kFromTouch
+ : MouseEvent::kRealOrIndistinguishable,
+ mouse_event.menu_source_type);
+ dispatch_result = target->DispatchEvent(*event);
+ } else {
+ MouseEventInit* initializer = MouseEventInit::Create();
+ SetMouseEventAttributes(initializer, target_node, mouse_event_type,
+ mouse_event, canvas_region_id, last_position,
+ related_target, click_count);
+ MouseEvent* event = MouseEvent::Create(
+ mouse_event_type, initializer, mouse_event.TimeStamp(),
+ mouse_event.FromTouch() ? MouseEvent::kFromTouch
+ : MouseEvent::kRealOrIndistinguishable,
+ mouse_event.menu_source_type);
+
+ dispatch_result = target->DispatchEvent(*event);
+ }
+
return event_handling_util::ToWebInputEventResult(dispatch_result);
}
return WebInputEventResult::kNotHandled;
@@ -316,7 +362,9 @@ WebInputEventResult MouseEventManager::SetMousePositionAndDispatchMouseEvent(
WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded(
Element* mouse_release_target,
const WebMouseEvent& mouse_event,
- const String& canvas_region_id) {
+ const String& canvas_region_id,
+ const PointerId& pointer_id,
+ const String& pointer_type) {
// We only prevent click event when the click may cause contextmenu to popup.
// However, we always send auxclick.
bool context_menu_event = false;
@@ -383,7 +431,8 @@ WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded(
(mouse_event.button == WebPointerProperties::Button::kLeft)
? event_type_names::kClick
: event_type_names::kAuxclick,
- mouse_event, canvas_region_id, nullptr, nullptr);
+ mouse_event, canvas_region_id, nullptr, nullptr, false, pointer_id,
+ pointer_type);
}
return WebInputEventResult::kNotHandled;
@@ -599,6 +648,7 @@ bool MouseEventManager::SlideFocusOnShadowHostIfNecessary(
if (element.AuthorShadowRoot() &&
element.AuthorShadowRoot()->delegatesFocus()) {
Document* doc = frame_->GetDocument();
+ UseCounter::Count(doc, WebFeature::kDelegateFocus);
Element* focused_element = doc->FocusedElement();
if (focused_element &&
element.IsShadowIncludingInclusiveAncestorOf(*focused_element)) {
diff --git a/chromium/third_party/blink/renderer/core/input/mouse_event_manager.h b/chromium/third_party/blink/renderer/core/input/mouse_event_manager.h
index 700a95c4de1..aa78ae0d8f5 100644
--- a/chromium/third_party/blink/renderer/core/input/mouse_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/mouse_event_manager.h
@@ -33,7 +33,7 @@ enum class DragInitiator;
// This class takes care of dispatching all mouse events and keeps track of
// positions and states of mouse.
class CORE_EXPORT MouseEventManager final
- : public GarbageCollectedFinalized<MouseEventManager>,
+ : public GarbageCollected<MouseEventManager>,
public SynchronousMutationObserver {
USING_GARBAGE_COLLECTED_MIXIN(MouseEventManager);
@@ -50,7 +50,9 @@ class CORE_EXPORT MouseEventManager final
const String& canvas_region_id,
const FloatPoint* last_position,
EventTarget* related_target,
- bool check_for_listener = false);
+ bool check_for_listener = false,
+ const PointerId& pointer_id = 0,
+ const String& pointer_type = "");
WebInputEventResult SetMousePositionAndDispatchMouseEvent(
Element* target_element,
@@ -61,7 +63,9 @@ class CORE_EXPORT MouseEventManager final
WebInputEventResult DispatchMouseClickIfNeeded(
Element* mouse_release_target,
const WebMouseEvent& mouse_event,
- const String& canvas_region_id);
+ const String& canvas_region_id,
+ const PointerId& pointer_id,
+ const String& pointer_type);
WebInputEventResult DispatchDragSrcEvent(const AtomicString& event_type,
const WebMouseEvent&);
diff --git a/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.h b/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.h
index 49fa57a6dbb..80f2fb721b4 100644
--- a/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.h
@@ -19,7 +19,7 @@ class Node;
class WebMouseWheelEvent;
class MouseWheelEventManager final
- : public GarbageCollectedFinalized<MouseWheelEventManager> {
+ : public GarbageCollected<MouseWheelEventManager> {
public:
explicit MouseWheelEventManager(LocalFrame&);
void Trace(blink::Visitor*);
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 152866713e1..6baf318132e 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
@@ -828,7 +828,8 @@ WebInputEventResult PointerEventManager::SendMousePointerEvent(
if (!skip_click_dispatch && mouse_target &&
event_type == WebInputEvent::kPointerUp) {
mouse_event_manager_->DispatchMouseClickIfNeeded(
- mouse_target, mouse_event, canvas_region_id);
+ mouse_target, mouse_event, canvas_region_id,
+ pointer_event->pointerId(), pointer_event->pointerType());
}
}
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 f02d6ca8a98..1da760581d3 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
@@ -24,8 +24,8 @@ class MouseEventManager;
// This class takes care of dispatching all pointer events and keeps track of
// properties of active pointer events.
-class CORE_EXPORT PointerEventManager
- : public GarbageCollectedFinalized<PointerEventManager> {
+class CORE_EXPORT PointerEventManager final
+ : public GarbageCollected<PointerEventManager> {
public:
PointerEventManager(LocalFrame&, MouseEventManager&);
void Trace(blink::Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
index 8408fb7ff18..3135f698168 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/overscroll_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
@@ -302,7 +301,7 @@ bool ScrollManager::LogicalScroll(ScrollDirection direction,
DCHECK(scrollable_area);
- SnapCoordinator* snap_coordinator =
+ SnapCoordinator& snap_coordinator =
frame_->GetDocument()->GetSnapCoordinator();
ScrollOffset delta = ToScrollDelta(physical_direction, 1);
delta.Scale(scrollable_area->ScrollStep(granularity, kHorizontalScrollbar),
@@ -313,12 +312,12 @@ bool ScrollManager::LogicalScroll(ScrollDirection direction,
// scroll with intended end position only.
switch (granularity) {
case ScrollGranularity::kScrollByLine: {
- if (snap_coordinator->SnapForDirection(*box, delta))
+ if (snap_coordinator.SnapForDirection(*box, delta))
return true;
break;
}
case ScrollGranularity::kScrollByPage: {
- if (snap_coordinator->SnapForEndAndDirection(*box, delta))
+ if (snap_coordinator.SnapForEndAndDirection(*box, delta))
return true;
break;
}
@@ -328,8 +327,8 @@ bool ScrollManager::LogicalScroll(ScrollDirection direction,
physical_direction == kScrollRight;
bool scrolled_y = physical_direction == kScrollUp ||
physical_direction == kScrollDown;
- if (snap_coordinator->SnapForEndPosition(*box, end_position, scrolled_x,
- scrolled_y))
+ if (snap_coordinator.SnapForEndPosition(*box, end_position, scrolled_x,
+ scrolled_y))
return true;
break;
}
@@ -760,10 +759,10 @@ bool ScrollManager::SnapAtGestureScrollEnd(const WebGestureEvent& end_event) {
if (!previous_gesture_scrolled_node_ ||
(!did_scroll_x_for_scroll_gesture_ && !did_scroll_y_for_scroll_gesture_))
return false;
- SnapCoordinator* snap_coordinator =
+ SnapCoordinator& snap_coordinator =
frame_->GetDocument()->GetSnapCoordinator();
LayoutBox* layout_box = LayoutBoxForSnapping();
- if (!snap_coordinator || !layout_box)
+ if (!layout_box)
return false;
bool is_mouse_wheel =
@@ -787,10 +786,10 @@ bool ScrollManager::SnapAtGestureScrollEnd(const WebGestureEvent& end_event) {
// limit the miscalculation to 1px.
ScrollOffset scroll_direction =
GetScrollDirection(last_scroll_delta_for_scroll_gesture_);
- return snap_coordinator->SnapForDirection(*layout_box, scroll_direction);
+ return snap_coordinator.SnapForDirection(*layout_box, scroll_direction);
}
- return snap_coordinator->SnapAtCurrentPosition(
+ return snap_coordinator.SnapAtCurrentPosition(
*layout_box, did_scroll_x_for_scroll_gesture_,
did_scroll_y_for_scroll_gesture_);
}
@@ -799,11 +798,11 @@ bool ScrollManager::GetSnapFlingInfo(
const gfx::Vector2dF& natural_displacement,
gfx::Vector2dF* out_initial_position,
gfx::Vector2dF* out_target_position) const {
- SnapCoordinator* snap_coordinator =
+ SnapCoordinator& snap_coordinator =
frame_->GetDocument()->GetSnapCoordinator();
LayoutBox* layout_box = LayoutBoxForSnapping();
ScrollableArea* scrollable_area = ScrollableAreaForSnapping(layout_box);
- if (!snap_coordinator || !layout_box || !scrollable_area)
+ if (!layout_box || !scrollable_area)
return false;
FloatPoint current_position = scrollable_area->ScrollPosition();
@@ -813,7 +812,7 @@ bool ScrollManager::GetSnapFlingInfo(
gfx::ScrollOffset(*out_initial_position),
gfx::ScrollOffset(natural_displacement));
base::Optional<FloatPoint> snap_end =
- snap_coordinator->GetSnapPosition(*layout_box, *strategy);
+ snap_coordinator.GetSnapPosition(*layout_box, *strategy);
if (!snap_end.has_value())
return false;
*out_target_position = gfx::Vector2dF(snap_end.value());
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.h b/chromium/third_party/blink/renderer/core/input/scroll_manager.h
index 4f2a562e943..e86a8510ffe 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.h
@@ -37,9 +37,8 @@ class WebGestureEvent;
// This class takes care of scrolling and resizing and the related states. The
// user action that causes scrolling or resizing is determined in other *Manager
// classes and they call into this class for doing the work.
-class CORE_EXPORT ScrollManager
- : public GarbageCollectedFinalized<ScrollManager>,
- public cc::SnapFlingClient {
+class CORE_EXPORT ScrollManager : public GarbageCollected<ScrollManager>,
+ public cc::SnapFlingClient {
public:
explicit ScrollManager(LocalFrame&);
virtual ~ScrollManager() = default;
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 e168bcb67a7..f55565f273c 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
@@ -26,8 +26,8 @@ class Touch;
// This class takes care of dispatching all touch events and
// maintaining related states.
-class CORE_EXPORT TouchEventManager
- : public GarbageCollectedFinalized<TouchEventManager> {
+class CORE_EXPORT TouchEventManager final
+ : public GarbageCollected<TouchEventManager> {
public:
explicit TouchEventManager(LocalFrame&);
@@ -48,8 +48,8 @@ class CORE_EXPORT TouchEventManager
private:
// Class represending one touch point event with its coalesced events and
// related attributes.
- class TouchPointAttributes
- : public GarbageCollectedFinalized<TouchPointAttributes> {
+ class TouchPointAttributes final
+ : public GarbageCollected<TouchPointAttributes> {
public:
void Trace(blink::Visitor* visitor) { visitor->Trace(target_); }
diff --git a/chromium/third_party/blink/renderer/core/inspector/OWNERS b/chromium/third_party/blink/renderer/core/inspector/OWNERS
index 9603f44128a..2b5fdc688b7 100644
--- a/chromium/third_party/blink/renderer/core/inspector/OWNERS
+++ b/chromium/third_party/blink/renderer/core/inspector/OWNERS
@@ -2,6 +2,7 @@ alph@chromium.org
caseq@chromium.org
dgozman@chromium.org
pfeldman@chromium.org
+yangguo@chromium.org
# Changes to remote debugging protocol require devtools review to
# ensure backwards compatibility and committment to maintain.
diff --git a/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
index 1ee3235a895..10a9a87d8e6 100644
--- a/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
+++ b/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -844,6 +844,10 @@ experimental domain CSS
number startColumn
# Size of the content (in characters).
number length
+ # Line offset of the end of the stylesheet within the resource (zero based).
+ number endLine
+ # Column offset of the end of the stylesheet within the resource (zero based).
+ number endColumn
# CSS rule representation.
type CSSRule extends object
@@ -1730,7 +1734,7 @@ domain DOM
# Returns node id at given location. Depending on whether DOM domain is enabled, nodeId is
# either returned or not.
- experimental command getNodeForLocation
+ command getNodeForLocation
parameters
# X coordinate.
integer x
@@ -1738,9 +1742,13 @@ domain DOM
integer y
# False to skip to the nearest non-UA shadow root ancestor (default: false).
optional boolean includeUserAgentShadowDOM
+ # Whether to ignore pointer-events: none on elements and hit test them.
+ optional boolean ignorePointerEventsNone
returns
# Resulting node.
BackendNodeId backendNodeId
+ # Frame this node belongs to.
+ Page.FrameId frameId
# Id of the node at given coordinates, only when enabled and requested document.
optional NodeId nodeId
@@ -2396,6 +2404,8 @@ experimental domain DOMSnapshot
properties
# Document URL that `Document` or `FrameOwner` node points to.
StringIndex documentURL
+ # Document title.
+ StringIndex title
# Base URL that `Document` or `FrameOwner` node uses for URL completion.
StringIndex baseURL
# Contains the document's content language.
@@ -2418,6 +2428,10 @@ experimental domain DOMSnapshot
optional number scrollOffsetX
# Vertical scroll offset.
optional number scrollOffsetY
+ # Document content width.
+ optional number contentWidth
+ # Document content height.
+ optional number contentHeight
# Table containing nodes.
type NodeTreeSnapshot extends object
@@ -2686,6 +2700,11 @@ domain Emulation
# Orientation angle.
integer angle
+ type MediaFeature extends object
+ properties
+ string name
+ string value
+
# advance: If the scheduler runs out of immediate work, the virtual time base may fast forward to
# allow the next delayed task (if any) to run; pause: The virtual time base may not advance;
# pauseIfNetworkFetchesPending: The virtual time base may not advance if there are any pending
@@ -2782,11 +2801,13 @@ domain Emulation
mobile
desktop
- # Emulates the given media for CSS media queries.
+ # Emulates the given media type or media feature for CSS media queries.
command setEmulatedMedia
parameters
# Media type to emulate. Empty string disables the override.
- string media
+ optional string media
+ # Media features to emulate.
+ optional array of MediaFeature features
# Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position
# unavailable.
@@ -2924,7 +2945,9 @@ experimental domain HeadlessExperimental
command enable
# Issued when the target starts or stops needing BeginFrames.
- event needsBeginFramesChanged
+ # Deprecated. Issue beginFrame unconditionally instead and use result from
+ # beginFrame to detect whether the frames were suppressed.
+ deprecated event needsBeginFramesChanged
parameters
# True if BeginFrames are needed, false otherwise.
boolean needsBeginFrames
@@ -4189,8 +4212,8 @@ domain Network
# A cookie which was not stored from a response with the corresponding reason.
experimental type BlockedSetCookieWithReason extends object
properties
- # The reason this cookie was blocked.
- SetCookieBlockedReason blockedReason
+ # The reason(s) this cookie was blocked.
+ array of SetCookieBlockedReason blockedReasons
# The string representing this individual cookie as it would appear in the header.
# This is not the entire "cookie" or "set-cookie" header which could have multiple cookies.
string cookieLine
@@ -4202,8 +4225,8 @@ domain Network
# A cookie with was not sent with a request with the corresponding reason.
experimental type BlockedCookieWithReason extends object
properties
- # The reason the cookie was blocked.
- CookieBlockedReason blockedReason
+ # The reason(s) the cookie was blocked.
+ array of CookieBlockedReason blockedReasons
# The cookie object representing the cookie which was not sent.
Cookie cookie
@@ -6039,6 +6062,52 @@ domain Security
secure
info
+ # Details about the security state of the page certificate.
+ experimental type CertificateSecurityState extends object
+ properties
+ # Protocol name (e.g. "TLS 1.2" or "QUIC").
+ string protocol
+ # Key Exchange used by the connection, or the empty string if not applicable.
+ string keyExchange
+ # (EC)DH group used by the connection, if applicable.
+ optional string keyExchangeGroup
+ # Cipher name.
+ string cipher
+ # TLS MAC. Note that AEAD ciphers do not have separate MACs.
+ optional string mac
+ # Page certificate.
+ array of string certificate
+ # Certificate subject name.
+ string subjectName
+ # Name of the issuing CA.
+ string issuer
+ # Certificate valid from date.
+ Network.TimeSinceEpoch validFrom
+ # Certificate valid to (expiration) date
+ Network.TimeSinceEpoch validTo
+ # True if the certificate uses a weak signature aglorithm.
+ boolean certifcateHasWeakSignature
+ # True if modern SSL
+ boolean modernSSL
+ # True if the connection is using an obsolete SSL protocol.
+ boolean obsoleteSslProtocol
+ # True if the connection is using an obsolete SSL key exchange.
+ boolean obsoleteSslKeyExchange
+ # True if the connection is using an obsolete SSL cipher.
+ boolean obsoleteSslCipher
+ # True if the connection is using an obsolete SSL signature.
+ boolean obsoleteSslSignature
+
+ # Security state information about the page.
+ experimental type VisibleSecurityState extends object
+ properties
+ # The security level of the page.
+ SecurityState securityState
+ # Security state details about the page certificate.
+ optional CertificateSecurityState certificateSecurityState
+ # Array of security state issues ids.
+ array of string securityStateIssueIds
+
# An explanation of an factor contributing to the security state.
type SecurityStateExplanation extends object
properties
@@ -6123,6 +6192,12 @@ domain Security
string requestURL
# The security state of the page changed.
+ experimental event visibleSecurityStateChanged
+ parameters
+ # Security state information about the page.
+ VisibleSecurityState visibleSecurityState
+
+ # The security state of the page changed.
event securityStateChanged
parameters
# Security state.
@@ -6364,6 +6439,10 @@ experimental domain SystemInfo
number vendorId
# PCI ID of the GPU device, if available; 0 otherwise.
number deviceId
+ # Sub sys ID of the GPU, only available on Windows.
+ optional number subSysId
+ # Revision of the GPU, only available on Windows.
+ optional number revision
# String description of the GPU vendor, if the PCI ID is not available.
string vendorString
# String description of the GPU device, if the PCI ID is not available.
@@ -6520,7 +6599,9 @@ domain Target
parameters
TargetID targetId
# Enables "flat" access to the session via specifying sessionId attribute in the commands.
- experimental optional boolean flatten
+ # We plan to make this the default, deprecate non-flattened mode,
+ # and eventually retire it. See crbug.com/991325.
+ optional boolean flatten
returns
# Id assigned to the session.
SessionID sessionId
@@ -6616,7 +6697,9 @@ domain Target
array of TargetInfo targetInfos
# Sends protocol message over session with given id.
- command sendMessageToTarget
+ # Consider using flat mode instead; see commands attachToTarget, setAutoAttach,
+ # and crbug.com/991325.
+ deprecated command sendMessageToTarget
parameters
string message
# Identifier of the session.
@@ -6635,7 +6718,11 @@ domain Target
# to run paused targets.
boolean waitForDebuggerOnStart
# Enables "flat" access to the session via specifying sessionId attribute in the commands.
- experimental optional boolean flatten
+ # We plan to make this the default, deprecate non-flattened mode,
+ # and eventually retire it. See crbug.com/991325.
+ optional boolean flatten
+ # Auto-attach to the targets created via window.open from current target.
+ experimental optional boolean windowOpen
# Controls whether to discover available targets and notify via
# `targetCreated/targetInfoChanged/targetDestroyed` events.
@@ -6785,6 +6872,9 @@ experimental domain Tracing
# Request a global memory dump.
command requestMemoryDump
+ parameters
+ # Enables more deterministic results by forcing garbage collection
+ optional boolean deterministic
returns
# GUID of the resulting global memory dump.
string dumpGuid
@@ -6939,11 +7029,16 @@ experimental domain Fetch
# An HTTP response code.
integer responseCode
# Response headers.
- array of HeaderEntry responseHeaders
+ optional array of HeaderEntry responseHeaders
+ # Alternative way of specifying response headers as a \0-separated
+ # series of name: value pairs. Prefer the above method unless you
+ # need to represent some non-UTF8 values that can't be transmitted
+ # over the protocol as text.
+ optional binary binaryResponseHeaders
# A response body.
optional binary body
# A textual representation of responseCode.
- # If absent, a standard phrase mathcing responseCode is used.
+ # If absent, a standard phrase matching responseCode is used.
optional string responsePhrase
# Continues the request, optionally modifying some of its parameters.
@@ -7268,11 +7363,16 @@ experimental domain WebAuthn
properties
AuthenticatorProtocol protocol
AuthenticatorTransport transport
- boolean hasResidentKey
- boolean hasUserVerification
+ # Defaults to false.
+ optional boolean hasResidentKey
+ # Defaults to false.
+ optional boolean hasUserVerification
# If set to true, tests of user presence will succeed immediately.
# Otherwise, they will not be resolved. Defaults to true.
optional boolean automaticPresenceSimulation
+ # Sets whether User Verification succeeds or fails for an authenticator.
+ # Defaults to false.
+ optional boolean isUserVerified
type Credential extends object
properties
diff --git a/chromium/third_party/blink/renderer/core/inspector/console_message.h b/chromium/third_party/blink/renderer/core/inspector/console_message.h
index ecaf42b8ebf..87abf1e7ec4 100644
--- a/chromium/third_party/blink/renderer/core/inspector/console_message.h
+++ b/chromium/third_party/blink/renderer/core/inspector/console_message.h
@@ -21,7 +21,7 @@ class WorkerThread;
struct WebConsoleMessage;
class CORE_EXPORT ConsoleMessage final
- : public GarbageCollectedFinalized<ConsoleMessage> {
+ : public GarbageCollected<ConsoleMessage> {
public:
// Location must be non-null.
static ConsoleMessage* Create(mojom::ConsoleMessageSource,
diff --git a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
index b6e6b56c51a..1d7c027e628 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
@@ -370,20 +370,9 @@ void DevToolsEmulator::DisableMobileEmulation() {
TransformationMatrix DevToolsEmulator::ForceViewport(
const WebFloatPoint& position,
float scale) {
- if (!viewport_override_) {
+ if (!viewport_override_)
viewport_override_ = ViewportOverride();
- GraphicsLayer* container_layer =
- web_view_->GetPage()->GetVisualViewport().ContainerLayer();
- // Disable clipping on the visual viewport layer, to ensure the whole area
- // is painted.
- if (container_layer) {
- viewport_override_->original_visual_viewport_masking =
- container_layer->MasksToBounds();
- container_layer->SetMasksToBounds(false);
- }
- }
-
viewport_override_->position = FloatPoint(position.x, position.y);
viewport_override_->scale = scale;
@@ -393,17 +382,7 @@ TransformationMatrix DevToolsEmulator::ForceViewport(
}
TransformationMatrix DevToolsEmulator::ResetViewport() {
- if (viewport_override_) {
- GraphicsLayer* container_layer =
- web_view_->GetPage()->GetVisualViewport().ContainerLayer();
- if (container_layer) {
- container_layer->SetMasksToBounds(
- viewport_override_->original_visual_viewport_masking);
- }
-
- viewport_override_ = base::nullopt;
- }
-
+ viewport_override_ = base::nullopt;
return ComputeRootLayerTransform();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
index fc743bdffd5..369cf79e5ca 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
+++ b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
@@ -22,7 +22,7 @@ class IntRect;
class WebViewImpl;
class CORE_EXPORT DevToolsEmulator final
- : public GarbageCollectedFinalized<DevToolsEmulator> {
+ : public GarbageCollected<DevToolsEmulator> {
public:
explicit DevToolsEmulator(WebViewImpl*);
~DevToolsEmulator();
@@ -110,7 +110,6 @@ class CORE_EXPORT DevToolsEmulator final
struct ViewportOverride {
FloatPoint position;
double scale;
- bool original_visual_viewport_masking;
};
base::Optional<ViewportOverride> viewport_override_;
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 3474394945f..082fe360ae6 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
@@ -153,7 +153,8 @@ float DevToolsHost::zoomFactor() {
// use-zoom-for-dsf mode.
const ChromeClient* client =
frontend_frame_->View()->GetChromeClient();
- float window_to_viewport_ratio = client->WindowToViewportScalar(1.0f);
+ float window_to_viewport_ratio =
+ client->WindowToViewportScalar(frontend_frame_, 1.0f);
return zoom_factor / window_to_viewport_ratio;
}
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 b80640f9ec3..99f3b2750f1 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_agent.cc
@@ -76,7 +76,7 @@ void DevToolsAgent::Dispose() {
CleanupConnection();
}
-void DevToolsAgent::BindRequest(
+void DevToolsAgent::BindReceiver(
mojo::PendingRemote<mojom::blink::DevToolsAgentHost> host_remote,
mojo::PendingReceiver<mojom::blink::DevToolsAgent> receiver,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
@@ -88,7 +88,7 @@ void DevToolsAgent::BindRequest(
WTF::Bind(&DevToolsAgent::CleanupConnection, WrapWeakPersistent(this)));
}
-void DevToolsAgent::BindRequest(
+void DevToolsAgent::BindReceiver(
mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost> host_remote,
mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent> receiver,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
diff --git a/chromium/third_party/blink/renderer/core/inspector/devtools_agent.h b/chromium/third_party/blink/renderer/core/inspector/devtools_agent.h
index 509e9e8df9f..78c07bc2bdb 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_agent.h
@@ -29,9 +29,8 @@ class InspectorTaskRunner;
class WorkerThread;
struct WorkerDevToolsParams;
-class CORE_EXPORT DevToolsAgent
- : public GarbageCollectedFinalized<DevToolsAgent>,
- public mojom::blink::DevToolsAgent {
+class CORE_EXPORT DevToolsAgent : public GarbageCollected<DevToolsAgent>,
+ public mojom::blink::DevToolsAgent {
public:
class Client {
public:
@@ -60,10 +59,10 @@ class CORE_EXPORT DevToolsAgent
void Dispose();
void FlushProtocolNotifications();
- void BindRequest(mojo::PendingRemote<mojom::blink::DevToolsAgentHost>,
- mojo::PendingReceiver<mojom::blink::DevToolsAgent>,
- scoped_refptr<base::SingleThreadTaskRunner>);
- void BindRequest(
+ void BindReceiver(mojo::PendingRemote<mojom::blink::DevToolsAgentHost>,
+ mojo::PendingReceiver<mojom::blink::DevToolsAgent>,
+ scoped_refptr<base::SingleThreadTaskRunner>);
+ void BindReceiver(
mojo::PendingAssociatedRemote<mojom::blink::DevToolsAgentHost>,
mojo::PendingAssociatedReceiver<mojom::blink::DevToolsAgent>,
scoped_refptr<base::SingleThreadTaskRunner>);
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 3f076338408..8cf28b8645e 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_session.cc
@@ -56,20 +56,6 @@ Vector<uint8_t> UnwrapMessage(const mojom::blink::DevToolsMessagePtr& message) {
return unwrap_message;
}
-mojom::blink::DevToolsMessagePtr WrapMessage(
- protocol::ProtocolMessage message) {
- auto result = mojom::blink::DevToolsMessage::New();
-
- if (message.json.IsEmpty()) {
- result->data = message.binary.ReleaseVector();
- } else {
- WTF::StringUTF8Adaptor adaptor(message.json);
- result->data =
- mojo_base::BigBuffer(base::as_bytes(base::make_span(adaptor)));
- }
- return result;
-}
-
protocol::ProtocolMessage ToProtocolMessage(
std::unique_ptr<v8_inspector::StringBuffer> buffer) {
protocol::ProtocolMessage message;
@@ -159,13 +145,15 @@ class DevToolsSession::IOSession : public mojom::blink::DevToolsSession {
DevToolsSession::DevToolsSession(
DevToolsAgent* agent,
- mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
- mojom::blink::DevToolsSessionAssociatedRequest main_request,
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsSessionHost>
+ host_remote,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsSession>
+ main_receiver,
mojo::PendingReceiver<mojom::blink::DevToolsSession> io_receiver,
mojom::blink::DevToolsSessionStatePtr reattach_session_state,
bool client_expects_binary_responses)
: agent_(agent),
- binding_(this, std::move(main_request)),
+ receiver_(this, std::move(main_receiver)),
inspector_backend_dispatcher_(new protocol::UberDispatcher(this)),
session_state_(std::move(reattach_session_state)),
client_expects_binary_responses_(client_expects_binary_responses),
@@ -176,8 +164,8 @@ DevToolsSession::DevToolsSession(
agent_->io_task_runner_, agent_->inspector_task_runner_,
WrapCrossThreadWeakPersistent(this), std::move(io_receiver));
- host_ptr_.Bind(std::move(host_ptr_info));
- host_ptr_.set_connection_error_handler(
+ host_remote_.Bind(std::move(host_remote));
+ host_remote_.set_disconnect_handler(
WTF::Bind(&DevToolsSession::Detach, WrapWeakPersistent(this)));
bool restore = !!session_state_.ReattachState();
@@ -203,7 +191,7 @@ void DevToolsSession::ConnectToV8(v8_inspector::V8Inspector* inspector,
}
bool DevToolsSession::IsDetached() {
- return !host_ptr_.is_bound();
+ return !host_remote_.is_bound();
}
void DevToolsSession::Append(InspectorAgent* agent) {
@@ -216,8 +204,9 @@ void DevToolsSession::Detach() {
agent_->client_->DebuggerTaskStarted();
agent_->client_->DetachSession(this);
agent_->sessions_.erase(this);
- binding_.Close();
- host_ptr_.reset();
+ receiver_.reset();
+ host_remote_.reset();
+ CHECK(io_session_);
io_session_->DeleteSoon();
io_session_ = nullptr;
agent_->probe_sink_->RemoveDevToolsSession(this);
@@ -328,16 +317,8 @@ void DevToolsSession::SendProtocolResponse(
if (WebTestSupport::IsRunningWebTest())
agent_->FlushProtocolNotifications();
- mojom::blink::DevToolsMessagePtr serialized = WrapMessage(message);
- if (!client_expects_binary_responses_) {
- std::vector<uint8_t> json;
- IPEStatus status = ConvertCBORToJSON(
- span<uint8_t>(serialized->data.data(), serialized->data.size()), &json);
- CHECK(status.ok()) << status.ToASCIIString();
- serialized->data = mojo_base::BigBuffer(json);
- }
- host_ptr_->DispatchProtocolResponse(std::move(serialized), call_id,
- session_state_.TakeUpdates());
+ host_remote_->DispatchProtocolResponse(FinalizeMessage(message), call_id,
+ session_state_.TakeUpdates());
}
class DevToolsSession::Notification {
@@ -361,16 +342,16 @@ class DevToolsSession::Notification {
std::unique_ptr<v8_inspector::StringBuffer> notification)
: v8_notification_(std::move(notification)) {}
- mojom::blink::DevToolsMessagePtr Serialize() {
- protocol::ProtocolMessage serialized;
+ protocol::ProtocolMessage Serialize() {
+ protocol::ProtocolMessage result;
if (blink_notification_) {
- serialized = blink_notification_->serialize(/*binary=*/true);
+ result = blink_notification_->serialize(/*binary=*/true);
blink_notification_.reset();
} else if (v8_notification_) {
- serialized = ToProtocolMessage(std::move(v8_notification_));
+ result = ToProtocolMessage(std::move(v8_notification_));
v8_notification_.reset();
}
- return WrapMessage(std::move(serialized));
+ return result;
}
private:
@@ -404,18 +385,9 @@ void DevToolsSession::flushProtocolNotifications() {
if (v8_session_)
v8_session_state_cbor_.Set(v8_session_->state());
for (wtf_size_t i = 0; i < notification_queue_.size(); ++i) {
- mojom::blink::DevToolsMessagePtr serialized =
- notification_queue_[i]->Serialize();
- if (!client_expects_binary_responses_) {
- std::vector<uint8_t> json;
- IPEStatus status = ConvertCBORToJSON(
- span<uint8_t>(serialized->data.data(), serialized->data.size()),
- &json);
- CHECK(status.ok()) << status.ToASCIIString();
- serialized->data = mojo_base::BigBuffer(json);
- }
- host_ptr_->DispatchProtocolNotification(std::move(serialized),
- session_state_.TakeUpdates());
+ host_remote_->DispatchProtocolNotification(
+ FinalizeMessage(notification_queue_[i]->Serialize()),
+ session_state_.TakeUpdates());
}
notification_queue_.clear();
}
@@ -425,4 +397,18 @@ void DevToolsSession::Trace(blink::Visitor* visitor) {
visitor->Trace(agents_);
}
+blink::mojom::blink::DevToolsMessagePtr DevToolsSession::FinalizeMessage(
+ protocol::ProtocolMessage message) {
+ std::vector<uint8_t> message_to_send = message.binary.ReleaseVector();
+ if (!client_expects_binary_responses_) {
+ std::vector<uint8_t> json;
+ IPEStatus status = ConvertCBORToJSON(SpanFrom(message_to_send), &json);
+ CHECK(status.ok()) << status.ToASCIIString();
+ message_to_send = std::move(json);
+ }
+ auto mojo_msg = mojom::blink::DevToolsMessage::New();
+ mojo_msg->data = std::move(message_to_send);
+ return mojo_msg;
+}
+
} // namespace blink
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 e8555f5b5cf..4cb447caf5b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/devtools_session.h
+++ b/chromium/third_party/blink/renderer/core/inspector/devtools_session.h
@@ -8,7 +8,10 @@
#include <memory>
#include "base/macros.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -27,16 +30,17 @@ class DocumentLoader;
class InspectorAgent;
class LocalFrame;
-class CORE_EXPORT DevToolsSession
- : public GarbageCollectedFinalized<DevToolsSession>,
- public mojom::blink::DevToolsSession,
- public protocol::FrontendChannel,
- public v8_inspector::V8Inspector::Channel {
+class CORE_EXPORT DevToolsSession : public GarbageCollected<DevToolsSession>,
+ public mojom::blink::DevToolsSession,
+ public protocol::FrontendChannel,
+ public v8_inspector::V8Inspector::Channel {
public:
DevToolsSession(
DevToolsAgent*,
- mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
- mojom::blink::DevToolsSessionAssociatedRequest main_request,
+ mojo::PendingAssociatedRemote<mojom::blink::DevToolsSessionHost>
+ host_remote,
+ mojo::PendingAssociatedReceiver<mojom::blink::DevToolsSession>
+ main_receiver,
mojo::PendingReceiver<mojom::blink::DevToolsSession> io_receiver,
mojom::blink::DevToolsSessionStatePtr reattach_session_state,
bool client_expects_binary_responses);
@@ -89,9 +93,13 @@ class CORE_EXPORT DevToolsSession
void SendProtocolResponse(int call_id,
const protocol::ProtocolMessage& message);
+ // Converts to JSON if requested by the client.
+ blink::mojom::blink::DevToolsMessagePtr FinalizeMessage(
+ protocol::ProtocolMessage message);
+
Member<DevToolsAgent> agent_;
- mojo::AssociatedBinding<mojom::blink::DevToolsSession> binding_;
- mojom::blink::DevToolsSessionHostAssociatedPtr host_ptr_;
+ mojo::AssociatedReceiver<mojom::blink::DevToolsSession> receiver_;
+ mojo::AssociatedRemote<mojom::blink::DevToolsSessionHost> host_remote_;
IOSession* io_session_;
std::unique_ptr<v8_inspector::V8InspectorSession> v8_session_;
std::unique_ptr<protocol::UberDispatcher> inspector_backend_dispatcher_;
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 4093b871fe6..fcfb8c3fc2c 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
@@ -55,7 +55,7 @@ class DOMPatchSupport final {
Node* PatchNode(Node*, const String& markup, ExceptionState&);
private:
- class Digest : public GarbageCollectedFinalized<Digest> {
+ class Digest final : public GarbageCollected<Digest> {
public:
explicit Digest(Node* node) : node_(node) {}
void Trace(blink::Visitor*);
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 0e2eda6e83e..5885c32ff28 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspected_frames.h
@@ -16,7 +16,7 @@ namespace blink {
class LocalFrame;
class CORE_EXPORT InspectedFrames final
- : public GarbageCollectedFinalized<InspectedFrames> {
+ : public GarbageCollected<InspectedFrames> {
public:
class CORE_EXPORT Iterator {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_base_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_base_agent.h
index 146575a4a18..f91d1e56062 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_base_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_base_agent.h
@@ -43,8 +43,7 @@ namespace blink {
class LocalFrame;
-class CORE_EXPORT InspectorAgent
- : public GarbageCollectedFinalized<InspectorAgent> {
+class CORE_EXPORT InspectorAgent : public GarbageCollected<InspectorAgent> {
public:
InspectorAgent() = default;
virtual ~InspectorAgent() = default;
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 b5520a543da..d44ef402be8 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
@@ -264,7 +264,7 @@ bool GetColorsFromRect(PhysicalRect rect,
if (IsA<HTMLCanvasElement>(element) || IsHTMLEmbedElement(element) ||
IsHTMLImageElement(element) || IsHTMLObjectElement(element) ||
- IsHTMLPictureElement(element) || element->IsSVGElement() ||
+ IsA<HTMLPictureElement>(element) || element->IsSVGElement() ||
IsHTMLVideoElement(element)) {
colors.clear();
found_opaque_color = false;
@@ -1041,11 +1041,12 @@ InspectorCSSAgent::AnimationsForNode(Element* element) {
std::make_unique<protocol::Array<protocol::CSS::CSSKeyframesRule>>();
Document* owner_document = element->ownerDocument();
- StyleResolver& style_resolver = owner_document->EnsureStyleResolver();
- scoped_refptr<ComputedStyle> style = style_resolver.StyleForElement(element);
+ owner_document->UpdateStyleAndLayoutTreeForNode(element);
+ const ComputedStyle* style = element->EnsureComputedStyle();
if (!style)
return css_keyframes_rules;
const CSSAnimationData* animation_data = style->Animations();
+ StyleResolver& style_resolver = owner_document->EnsureStyleResolver();
for (wtf_size_t i = 0;
animation_data && i < animation_data->NameList().size(); ++i) {
AtomicString animation_name(animation_data->NameList()[i]);
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 d97813a11b1..d43fce562ba 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
@@ -55,6 +55,7 @@
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
@@ -64,6 +65,7 @@
#include "third_party/blink/renderer/core/html/imports/html_import_loader.h"
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
#include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
+#include "third_party/blink/renderer/core/html/portal/portal_contents.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/inspector/dom_editor.h"
#include "third_party/blink/renderer/core/inspector/dom_patch_support.h"
@@ -100,7 +102,7 @@ const UChar kEllipsisUChar[] = {0x2026, 0};
} // namespace
class InspectorRevalidateDOMTask final
- : public GarbageCollectedFinalized<InspectorRevalidateDOMTask> {
+ : public GarbageCollected<InspectorRevalidateDOMTask> {
public:
explicit InspectorRevalidateDOMTask(InspectorDOMAgent*);
void ScheduleStyleAttrRevalidationFor(Element*);
@@ -1339,7 +1341,9 @@ Response InspectorDOMAgent::getNodeForLocation(
int x,
int y,
Maybe<bool> optional_include_user_agent_shadow_dom,
+ Maybe<bool> optional_ignore_pointer_events_none,
int* backend_node_id,
+ String* frame_id,
Maybe<int>* node_id) {
bool include_user_agent_shadow_dom =
optional_include_user_agent_shadow_dom.fromMaybe(false);
@@ -1347,8 +1351,12 @@ Response InspectorDOMAgent::getNodeForLocation(
PhysicalOffset document_point(
LayoutUnit(x * inspected_frames_->Root()->PageZoomFactor()),
LayoutUnit(y * inspected_frames_->Root()->PageZoomFactor()));
- HitTestRequest request(HitTestRequest::kMove | HitTestRequest::kReadOnly |
- HitTestRequest::kAllowChildFrameContent);
+ HitTestRequest::HitTestRequestType hit_type =
+ HitTestRequest::kMove | HitTestRequest::kReadOnly |
+ HitTestRequest::kAllowChildFrameContent;
+ if (optional_ignore_pointer_events_none.fromMaybe(false))
+ hit_type |= HitTestRequest::kIgnorePointerEventsNone;
+ HitTestRequest request(hit_type);
HitTestLocation location(document->View()->DocumentToFrame(document_point));
HitTestResult result(request, location);
document->GetFrame()->ContentLayoutObject()->HitTest(location, result);
@@ -1360,6 +1368,8 @@ Response InspectorDOMAgent::getNodeForLocation(
if (!node)
return Response::Error("No node found at given location");
*backend_node_id = IdentifiersFactory::IntIdForNode(node);
+ LocalFrame* frame = node->GetDocument().GetFrame();
+ *frame_id = IdentifiersFactory::FrameId(frame);
if (enabled_.Get() && document_ &&
document_node_to_id_map_->Contains(document_)) {
*node_id = PushNodePathToFrontend(node);
@@ -1552,7 +1562,7 @@ std::unique_ptr<protocol::DOM::Node> InspectorDOMAgent::BuildObjectForNode(
BuildArrayForDistributedNodes(insertion_point));
force_push_children = true;
}
- if (auto* slot = ToHTMLSlotElementOrNull(*element)) {
+ if (auto* slot = DynamicTo<HTMLSlotElement>(*element)) {
if (node->IsInShadowTree()) {
value->setDistributedNodes(BuildDistributedNodesForSlot(slot));
force_push_children = true;
@@ -2273,10 +2283,10 @@ protocol::Response InspectorDOMAgent::getFrameOwner(
break;
}
if (!frame) {
- for (HTMLPortalElement* portal :
+ for (PortalContents* portal :
DocumentPortals::From(*inspected_frames_->Root()->GetDocument())
.GetPortals()) {
- frame = portal->ContentFrame();
+ frame = portal->GetFrame();
if (IdentifiersFactory::FrameId(frame) == frame_id)
break;
}
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 bd9901a9228..39f63d30265 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
@@ -81,7 +81,7 @@ class CORE_EXPORT InspectorDOMAgent final
};
class CORE_EXPORT InspectorSourceLocation final
- : public GarbageCollectedFinalized<InspectorSourceLocation> {
+ : public GarbageCollected<InspectorSourceLocation> {
public:
InspectorSourceLocation(std::unique_ptr<SourceLocation> source_location)
: source_location_(std::move(source_location)) {}
@@ -221,7 +221,9 @@ class CORE_EXPORT InspectorDOMAgent final
int x,
int y,
protocol::Maybe<bool> include_user_agent_shadow_dom,
+ protocol::Maybe<bool> ignore_pointer_events_none,
int* backend_node_id,
+ String* frame_id,
protocol::Maybe<int>* node_id) override;
protocol::Response getRelayoutBoundary(int node_id,
int* out_node_id) override;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
index e10e9c156ac..10db62e2ccf 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
@@ -324,6 +324,7 @@ void InspectorDOMSnapshotAgent::VisitDocument(Document* document) {
AddString(InspectorDOMAgent::DocumentURLString(document)))
.setBaseURL(
AddString(InspectorDOMAgent::DocumentBaseURLString(document)))
+ .setTitle(AddString(document->title()))
.setContentLanguage(AddString(document->ContentLanguage()))
.setEncodingName(AddString(document->EncodingName()))
.setFrameId(
@@ -373,6 +374,9 @@ void InspectorDOMSnapshotAgent::VisitDocument(Document* document) {
auto offset = document->View()->LayoutViewport()->GetScrollOffset();
document_->setScrollOffsetX(offset.Width());
document_->setScrollOffsetY(offset.Height());
+ auto contents_size = document->View()->LayoutViewport()->ContentsSize();
+ document_->setContentWidth(contents_size.Width());
+ document_->setContentHeight(contents_size.Height());
}
if (paint_order_map_) {
@@ -460,7 +464,7 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node, int parent_index) {
}
}
- if (auto* option_element = ToHTMLOptionElementOrNull(*element)) {
+ if (auto* option_element = DynamicTo<HTMLOptionElement>(*element)) {
if (option_element->Selected()) {
SetRare(nodes->getOptionSelected(nullptr), index);
}
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 a3facc4eba4..bc3f69324fe 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
@@ -38,6 +38,7 @@ InspectorEmulationAgent::InspectorEmulationAgent(
touch_event_emulation_enabled_(&agent_state_, /*default_value=*/false),
max_touch_points_(&agent_state_, /*default_value=*/1),
emulated_media_(&agent_state_, /*default_value=*/WTF::String()),
+ emulated_media_features_(&agent_state_, /*default_value=*/WTF::String()),
navigator_platform_override_(&agent_state_,
/*default_value=*/WTF::String()),
user_agent_override_(&agent_state_, /*default_value=*/WTF::String()),
@@ -89,7 +90,16 @@ void InspectorEmulationAgent::Restore() {
GetWebViewImpl()->GetDevToolsEmulator()->SetDocumentCookieDisabled(true);
setTouchEmulationEnabled(touch_event_emulation_enabled_.Get(),
max_touch_points_.Get());
- setEmulatedMedia(emulated_media_.Get());
+ auto features =
+ std::make_unique<protocol::Array<protocol::Emulation::MediaFeature>>();
+ for (auto const& name : emulated_media_features_.Keys()) {
+ auto const& value = emulated_media_features_.Get(name);
+ features->push_back(protocol::Emulation::MediaFeature::create()
+ .setName(name)
+ .setValue(value)
+ .build());
+ }
+ setEmulatedMedia(emulated_media_.Get(), std::move(features));
auto rgba = ParseRGBA(default_background_color_override_rgba_.Get());
if (rgba)
setDefaultBackgroundColorOverride(std::move(rgba));
@@ -145,7 +155,12 @@ Response InspectorEmulationAgent::disable() {
setScrollbarsHidden(false);
setDocumentCookieDisabled(false);
setTouchEmulationEnabled(false, Maybe<int>());
- setEmulatedMedia(String());
+ // Clear emulated media features. Note that the current approach
+ // doesn't work well in cases where two clients have the same set of
+ // features overridden to the same value by two different clients
+ // (e.g. if we allowed two different front-ends with the same
+ // settings to attach to the same page). TODO: support this use case.
+ setEmulatedMedia(String(), {});
setCPUThrottlingRate(1);
setFocusEmulationEnabled(false);
setDefaultBackgroundColorOverride(Maybe<protocol::DOM::RGBA>());
@@ -220,12 +235,35 @@ Response InspectorEmulationAgent::setTouchEmulationEnabled(
return response;
}
-Response InspectorEmulationAgent::setEmulatedMedia(const String& media) {
+Response InspectorEmulationAgent::setEmulatedMedia(
+ Maybe<String> media,
+ Maybe<protocol::Array<protocol::Emulation::MediaFeature>> features) {
Response response = AssertPage();
if (!response.isSuccess())
return response;
- emulated_media_.Set(media);
- GetWebViewImpl()->GetPage()->GetSettings().SetMediaTypeOverride(media);
+ if (media.isJust()) {
+ auto mediaValue = media.takeJust();
+ emulated_media_.Set(mediaValue);
+ GetWebViewImpl()->GetPage()->GetSettings().SetMediaTypeOverride(mediaValue);
+ } else {
+ emulated_media_.Set("");
+ GetWebViewImpl()->GetPage()->GetSettings().SetMediaTypeOverride("");
+ }
+ for (const WTF::String& feature : emulated_media_features_.Keys()) {
+ GetWebViewImpl()->GetPage()->SetMediaFeatureOverride(AtomicString(feature),
+ "");
+ }
+ emulated_media_features_.Clear();
+ if (features.isJust()) {
+ auto featuresValue = features.takeJust();
+ for (auto const& mediaFeature : *featuresValue.get()) {
+ auto const& name = mediaFeature->getName();
+ auto const& value = mediaFeature->getValue();
+ emulated_media_features_.Set(name, value);
+ GetWebViewImpl()->GetPage()->SetMediaFeatureOverride(AtomicString(name),
+ value);
+ }
+ }
return response;
}
@@ -463,8 +501,11 @@ Response InspectorEmulationAgent::setTimezoneOverride(
timezone_override_.reset();
if (!timezone_id.IsEmpty()) {
timezone_override_ = TimeZoneController::SetTimeZoneOverride(timezone_id);
- if (!timezone_override_)
- return Response::Error("Timezone override is already in effect");
+ if (!timezone_override_) {
+ return TimeZoneController::HasTimeZoneOverride()
+ ? Response::Error("Timezone override is already in effect")
+ : Response::InvalidParams("Invalid timezone id");
+ }
}
timezone_id_override_.Set(timezone_id);
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 8704f250932..87a2fd33b52 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
@@ -44,7 +44,10 @@ class CORE_EXPORT InspectorEmulationAgent final
protocol::Response setTouchEmulationEnabled(
bool enabled,
protocol::Maybe<int> max_touch_points) override;
- protocol::Response setEmulatedMedia(const String&) override;
+ protocol::Response setEmulatedMedia(
+ protocol::Maybe<String> media,
+ protocol::Maybe<protocol::Array<protocol::Emulation::MediaFeature>>
+ features) override;
protocol::Response setCPUThrottlingRate(double) override;
protocol::Response setFocusEmulationEnabled(bool) override;
protocol::Response setVirtualTimePolicy(
@@ -122,6 +125,7 @@ class CORE_EXPORT InspectorEmulationAgent final
InspectorAgentState::Boolean touch_event_emulation_enabled_;
InspectorAgentState::Integer max_touch_points_;
InspectorAgentState::String emulated_media_;
+ InspectorAgentState::StringMap emulated_media_features_;
InspectorAgentState::String navigator_platform_override_;
InspectorAgentState::String user_agent_override_;
InspectorAgentState::String accept_language_override_;
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 bee7c0b4be4..db0c40dd586 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -287,19 +287,19 @@ std::unique_ptr<protocol::DictionaryValue> BuildElementInfo(Element* element) {
if (!layout_object || !containing_view)
return element_info;
- if (auto* context = element->GetDisplayLockContext()) {
- if (context->IsLocked()) {
- // If it's a locked element, use the values from the locked frame rect.
- // TODO(vmpstr): Verify that these values are correct here.
- element_info->setString(
- "nodeWidth",
- String::Number(context->GetLockedContentLogicalWidth().ToDouble()));
- element_info->setString(
- "nodeHeight",
- String::Number(context->GetLockedContentLogicalHeight().ToDouble()));
- }
- return element_info;
- }
+ // if (auto* context = element->GetDisplayLockContext()) {
+ // if (context->IsLocked()) {
+ // // If it's a locked element, use the values from the locked frame rect.
+ // // TODO(vmpstr): Verify that these values are correct here.
+ // element_info->setString(
+ // "nodeWidth",
+ // String::Number(context->GetLockedContentLogicalWidth().ToDouble()));
+ // element_info->setString(
+ // "nodeHeight",
+ // String::Number(context->GetLockedContentLogicalHeight().ToDouble()));
+ // }
+ // return element_info;
+ //}
// layoutObject the getBoundingClientRect() data in the tooltip
// to be consistent with the rulers (see http://crbug.com/262338).
@@ -448,8 +448,10 @@ InspectorHighlight::InspectorHighlight(
scale_(1.f) {
DCHECK(!DisplayLockUtilities::NearestLockedExclusiveAncestor(*node));
LocalFrameView* frame_view = node->GetDocument().View();
- if (frame_view)
- scale_ = 1.f / frame_view->GetChromeClient()->WindowToViewportScalar(1.f);
+ if (frame_view) {
+ scale_ = 1.f / frame_view->GetChromeClient()->WindowToViewportScalar(
+ &frame_view->GetFrame(), 1.f);
+ }
AppendPathsForShapeOutside(node, highlight_config);
AppendNodeHighlight(node, highlight_config);
auto* text_node = DynamicTo<Text>(node);
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 d45e3ed8970..c94ece9dfd6 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_history.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_history.h
@@ -43,7 +43,7 @@ class ExceptionState;
class InspectorHistory final : public GarbageCollected<InspectorHistory> {
public:
- class Action : public GarbageCollectedFinalized<Action> {
+ class Action : public GarbageCollected<Action> {
public:
explicit Action(const String& name);
virtual ~Action();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
index dbf5bb4f6d2..f863a1ea110 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_media_context_impl.h
@@ -21,7 +21,7 @@ namespace blink {
class Document;
class HTMLMediaElement;
-struct MediaPlayer final : public GarbageCollectedFinalized<MediaPlayer> {
+struct MediaPlayer final : public GarbageCollected<MediaPlayer> {
void Trace(blink::Visitor*) {}
WebString player_id;
@@ -30,7 +30,7 @@ struct MediaPlayer final : public GarbageCollectedFinalized<MediaPlayer> {
};
class CORE_EXPORT MediaInspectorContextImpl final
- : public GarbageCollectedFinalized<MediaInspectorContextImpl>,
+ : public GarbageCollected<MediaInspectorContextImpl>,
public Supplement<LocalFrame>,
public MediaInspectorContext {
USING_GARBAGE_COLLECTED_MIXIN(MediaInspectorContextImpl);
@@ -54,7 +54,7 @@ class CORE_EXPORT MediaInspectorContextImpl final
void NotifyPlayerEvents(WebString, InspectorPlayerEvents) override;
void SetPlayerProperties(WebString, InspectorPlayerProperties) override;
- // GarbageCollectedFinalized methods.
+ // GarbageCollected methods.
void Trace(blink::Visitor*) override;
Vector<WebString> GetAllPlayerIds();
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 5bb5078e1c6..0e18ea221e6 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
@@ -70,6 +70,7 @@
#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"
@@ -539,16 +540,16 @@ BuildObjectForResourceResponse(const ResourceResponse& response,
String security_state = protocol::Security::SecurityStateEnum::Unknown;
switch (response.GetSecurityStyle()) {
- case kWebSecurityStyleUnknown:
+ case SecurityStyle::kUnknown:
security_state = protocol::Security::SecurityStateEnum::Unknown;
break;
- case kWebSecurityStyleNeutral:
+ case SecurityStyle::kNeutral:
security_state = protocol::Security::SecurityStateEnum::Neutral;
break;
- case kWebSecurityStyleInsecure:
+ case SecurityStyle::kInsecure:
security_state = protocol::Security::SecurityStateEnum::Insecure;
break;
- case kWebSecurityStyleSecure:
+ case SecurityStyle::kSecure:
security_state = protocol::Security::SecurityStateEnum::Secure;
break;
}
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 9193e4239dc..dba8a6d4c3f 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
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_page_agent.h"
#include "third_party/blink/renderer/core/inspector/protocol/Network.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -54,7 +55,6 @@ class WebSocketHandshakeRequest;
namespace blink {
-class BlobDataHandle;
class Document;
class DocumentLoader;
class ExecutionContext;
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 429eddd810f..c8ee833ffb1 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
@@ -235,9 +235,7 @@ class InspectorOverlayAgent::InspectorPageOverlayDelegate final
return;
}
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- graphics_context, frame_overlay, DisplayItem::kFrameOverlay))
- return;
+ frame_overlay.Invalidate();
DrawingRecorder recorder(graphics_context, frame_overlay,
DisplayItem::kFrameOverlay);
// The overlay frame is has a standalone paint property tree. Paint it in
@@ -830,7 +828,8 @@ float InspectorOverlayAgent::WindowToViewportScale() const {
LocalFrame* frame = GetFrame();
if (!frame)
return 1.0f;
- return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f);
+ return frame->GetPage()->GetChromeClient().WindowToViewportScalar(frame,
+ 1.0f);
}
void InspectorOverlayAgent::EnsureOverlayPageCreated() {
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 6c9175f23b3..f03de4b7e99 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
@@ -72,7 +72,7 @@ class InspectorOverlayAgent;
using OverlayFrontend = protocol::Overlay::Metainfo::FrontendClass;
-class CORE_EXPORT InspectTool : public GarbageCollectedFinalized<InspectTool> {
+class CORE_EXPORT InspectTool : public GarbageCollected<InspectTool> {
public:
virtual ~InspectTool() = default;
void Init(InspectorOverlayAgent* overlay, OverlayFrontend* frontend);
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 fa9d6d1aea0..1cd4296239c 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
@@ -1181,7 +1181,8 @@ Response InspectorPageAgent::getLayoutMetrics(
// page_zoom_factor is CSS to DIP (device independent pixels).
float page_zoom_factor =
page_zoom /
- main_frame->GetPage()->GetChromeClient().WindowToViewportScalar(1);
+ main_frame->GetPage()->GetChromeClient().WindowToViewportScalar(
+ main_frame, 1);
FloatRect visible_rect = visual_viewport.VisibleRect();
float scale = visual_viewport.Scale();
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 ca49dbe223a..c8222ba0d34 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,6 +6,7 @@
#include <utility>
+#include "base/stl_util.h"
#include "base/time/time_override.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -15,7 +16,7 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
namespace blink {
@@ -138,7 +139,7 @@ Response InspectorPerformanceAgent::getMetrics(
base::TimeTicks::Now().since_origin().InSecondsF());
// Renderer instance counters.
- for (size_t i = 0; i < ARRAY_SIZE(kInstanceCounterNames); ++i) {
+ for (size_t i = 0; i < base::size(kInstanceCounterNames); ++i) {
AppendMetric(result.get(), kInstanceCounterNames[i],
InstanceCounters::CounterValue(
static_cast<InstanceCounters::CounterType>(i)));
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 74bd997f119..de3a844e6b6 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
@@ -19,8 +19,8 @@ namespace blink {
class InspectedFrames;
class LocalFrame;
-class CORE_EXPORT InspectorResourceContainer
- : public GarbageCollectedFinalized<InspectorResourceContainer> {
+class CORE_EXPORT InspectorResourceContainer final
+ : public GarbageCollected<InspectorResourceContainer> {
public:
explicit InspectorResourceContainer(InspectedFrames*);
~InspectorResourceContainer();
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 ba9eb2836b9..1fca67c4f37 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_resource_content_loader.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/platform/web_url_request.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
@@ -28,8 +29,7 @@ namespace blink {
// resources. Stylesheets can only safely use a RawResourceClient because it has
// no custom interface and simply uses the base ResourceClient.
class InspectorResourceContentLoader::ResourceClient final
- : public GarbageCollectedFinalized<
- InspectorResourceContentLoader::ResourceClient>,
+ : public GarbageCollected<InspectorResourceContentLoader::ResourceClient>,
private RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(ResourceClient);
@@ -93,6 +93,18 @@ void InspectorResourceContentLoader::Start() {
resource_request.SetCacheMode(mojom::FetchCacheMode::kDefault);
}
+ ResourceFetcher* fetcher = document->Fetcher();
+ if (base::FeatureList::IsEnabled(
+ features::kHtmlImportsRequestInitiatorLock)) {
+ // For @imports from HTML imported Documents, we use the
+ // context document for getting origin and ResourceFetcher to use the
+ // main Document's origin, while using the element document for
+ // CompleteURL() to use imported Documents' base URLs.
+ if (!document->ContextDocument()) {
+ continue;
+ }
+ fetcher = document->ContextDocument()->Fetcher();
+ }
if (!resource_request.Url().GetString().IsEmpty()) {
urls_to_fetch.insert(resource_request.Url().GetString());
ResourceLoaderOptions options;
@@ -102,7 +114,7 @@ void InspectorResourceContentLoader::Start() {
MakeGarbageCollected<ResourceClient>(this);
// Prevent garbage collection by holding a reference to this resource.
resources_.push_back(
- RawResource::Fetch(params, document->Fetcher(), resource_client));
+ RawResource::Fetch(params, fetcher, resource_client));
pending_resource_clients_.insert(resource_client);
}
@@ -123,8 +135,8 @@ void InspectorResourceContentLoader::Start() {
ResourceClient* resource_client =
MakeGarbageCollected<ResourceClient>(this);
// Prevent garbage collection by holding a reference to this resource.
- resources_.push_back(CSSStyleSheetResource::Fetch(
- params, document->Fetcher(), resource_client));
+ resources_.push_back(
+ CSSStyleSheetResource::Fetch(params, fetcher, resource_client));
// A cache hit for a css stylesheet will complete synchronously. Don't
// mark the client as pending if it already finished.
if (resource_client->GetResource())
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 33fc7e6bf52..ec8d98c9a30 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
@@ -20,7 +20,7 @@ class LocalFrame;
class Resource;
class CORE_EXPORT InspectorResourceContentLoader final
- : public GarbageCollectedFinalized<InspectorResourceContentLoader> {
+ : public GarbageCollected<InspectorResourceContentLoader> {
public:
explicit InspectorResourceContentLoader(LocalFrame*);
~InspectorResourceContentLoader();
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 5c8dc0d6b6d..21246912796 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
@@ -539,7 +539,6 @@ void CollectFlatRules(RuleList rule_list, CSSRuleVector* result) {
case CSSRule::kFontFaceRule:
case CSSRule::kViewportRule:
case CSSRule::kKeyframeRule:
- case CSSRule::kFontFeatureValuesRule:
result->push_back(rule);
break;
case CSSRule::kMediaRule:
@@ -1448,6 +1447,29 @@ void InspectorStyleSheet::InnerSetText(const String& text,
}
}
+namespace {
+
+TextPosition TextPositionFromOffsetAndLineEndingsRelativeToStartPosition(
+ unsigned offset,
+ const Vector<unsigned>& line_endings,
+ const TextPosition& start_position) {
+ TextPosition position =
+ TextPosition::FromOffsetAndLineEndings(offset, line_endings);
+ unsigned column = position.column_.ZeroBasedInt();
+ // A non-zero `start_position.column_` means that the text started in the
+ // middle of a line, so the start column position must be added if `offset`
+ // translates to a `position` in the first line of the text.
+ if (position.line_.ZeroBasedInt() == 0) {
+ column += start_position.column_.ZeroBasedInt();
+ }
+ unsigned line_index =
+ start_position.line_.ZeroBasedInt() + position.line_.ZeroBasedInt();
+ return TextPosition(OrdinalNumber::FromZeroBasedInt(line_index),
+ OrdinalNumber::FromZeroBasedInt(column));
+}
+
+} // namespace
+
std::unique_ptr<protocol::CSS::CSSStyleSheetHeader>
InspectorStyleSheet::BuildObjectForStyleSheetInfo() {
CSSStyleSheet* style_sheet = PageStyleSheet();
@@ -1456,8 +1478,16 @@ InspectorStyleSheet::BuildObjectForStyleSheetInfo() {
Document* document = style_sheet->OwnerDocument();
LocalFrame* frame = document ? document->GetFrame() : nullptr;
- String text;
- GetText(&text);
+ const LineEndings* line_endings = this->GetLineEndings();
+ TextPosition start = style_sheet->StartPositionInSource();
+ TextPosition end = start;
+ unsigned text_length = 0;
+ if (line_endings->size() > 0) {
+ text_length = line_endings->back();
+ end = TextPositionFromOffsetAndLineEndingsRelativeToStartPosition(
+ text_length, *line_endings, start);
+ }
+
std::unique_ptr<protocol::CSS::CSSStyleSheetHeader> result =
protocol::CSS::CSSStyleSheetHeader::create()
.setStyleSheetId(Id())
@@ -1467,11 +1497,11 @@ InspectorStyleSheet::BuildObjectForStyleSheetInfo() {
.setTitle(style_sheet->title())
.setFrameId(frame ? IdentifiersFactory::FrameId(frame) : "")
.setIsInline(style_sheet->IsInline() && !StartsAtZero())
- .setStartLine(
- style_sheet->StartPositionInSource().line_.ZeroBasedInt())
- .setStartColumn(
- style_sheet->StartPositionInSource().column_.ZeroBasedInt())
- .setLength(text.length())
+ .setStartLine(start.line_.ZeroBasedInt())
+ .setStartColumn(start.column_.ZeroBasedInt())
+ .setLength(text_length)
+ .setEndLine(end.line_.ZeroBasedInt())
+ .setEndColumn(end.column_.ZeroBasedInt())
.build();
if (HasSourceURL())
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 aab935342c5..c59f456f79d 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
@@ -52,7 +52,7 @@ class InspectorStyleSheetBase;
typedef HeapVector<Member<CSSRule>> CSSRuleVector;
typedef Vector<unsigned> LineEndings;
-class InspectorStyle final : public GarbageCollectedFinalized<InspectorStyle> {
+class InspectorStyle final : public GarbageCollected<InspectorStyle> {
public:
InspectorStyle(CSSStyleDeclaration*,
CSSRuleSourceData*,
@@ -77,7 +77,7 @@ class InspectorStyle final : public GarbageCollectedFinalized<InspectorStyle> {
};
class InspectorStyleSheetBase
- : public GarbageCollectedFinalized<InspectorStyleSheetBase> {
+ : public GarbageCollected<InspectorStyleSheetBase> {
public:
class CORE_EXPORT Listener {
public:
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 8ef8fa09645..655460057ae 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
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.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"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -257,6 +258,7 @@ const char* PseudoTypeToString(CSSSelector::PseudoType pseudo_type) {
DEFINE_STRING_MAPPING(PseudoNthLastChild)
DEFINE_STRING_MAPPING(PseudoNthLastOfType)
DEFINE_STRING_MAPPING(PseudoPart)
+ DEFINE_STRING_MAPPING(PseudoState)
DEFINE_STRING_MAPPING(PseudoLink)
DEFINE_STRING_MAPPING(PseudoVisited)
DEFINE_STRING_MAPPING(PseudoAny)
@@ -342,6 +344,7 @@ const char* PseudoTypeToString(CSSSelector::PseudoType pseudo_type) {
DEFINE_STRING_MAPPING(PseudoHostHasAppearance)
DEFINE_STRING_MAPPING(PseudoVideoPersistent)
DEFINE_STRING_MAPPING(PseudoVideoPersistentAncestor)
+ DEFINE_STRING_MAPPING(PseudoXrImmersiveDomOverlay)
#undef DEFINE_STRING_MAPPING
}
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 8073d7151b3..f9042ee78eb 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
@@ -252,7 +252,7 @@ int LegacyDOMSnapshotAgent::VisitNode(Node* node,
}
}
- if (auto* option_element = ToHTMLOptionElementOrNull(*element))
+ if (auto* option_element = DynamicTo<HTMLOptionElement>(*element))
value->setOptionSelected(option_element->Selected());
if (element->GetPseudoId()) {
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 25aad342b53..0a4c41a3584 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
@@ -48,7 +48,7 @@ class Resource;
class ResourceResponse;
class TextResourceDecoder;
-class XHRReplayData final : public GarbageCollectedFinalized<XHRReplayData> {
+class XHRReplayData final : public GarbageCollected<XHRReplayData> {
public:
static XHRReplayData* Create(ExecutionContext*,
const AtomicString& method,
@@ -92,9 +92,9 @@ class XHRReplayData final : public GarbageCollectedFinalized<XHRReplayData> {
};
class NetworkResourcesData final
- : public GarbageCollectedFinalized<NetworkResourcesData> {
+ : public GarbageCollected<NetworkResourcesData> {
public:
- class ResourceData final : public GarbageCollectedFinalized<ResourceData> {
+ class ResourceData final : public GarbageCollected<ResourceData> {
friend class NetworkResourcesData;
public:
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 7adb02fcbea..5c6ee138564 100644
--- a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
+++ b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
@@ -7,7 +7,7 @@
#include <memory>
#include "base/macros.h"
-#include "third_party/blink/public/mojom/devtools/console_message.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/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc b/chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc
index 9e63b6be5c6..9a2ef55c1c4 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
@@ -87,9 +87,9 @@ WorkerInspectorController::WorkerInspectorController(
agent_ = MakeGarbageCollected<DevToolsAgent>(
this, inspected_frames_.Get(), probe_sink_.Get(),
std::move(inspector_task_runner), std::move(io_task_runner));
- agent_->BindRequest(std::move(devtools_params->agent_host_remote),
- std::move(devtools_params->agent_receiver),
- thread->GetTaskRunner(TaskType::kInternalInspector));
+ agent_->BindReceiver(std::move(devtools_params->agent_host_remote),
+ std::move(devtools_params->agent_receiver),
+ thread->GetTaskRunner(TaskType::kInternalInspector));
}
trace_event::AddEnabledStateObserver(this);
EmitTraceEvent();
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 4014ad57e06..4d8943a9780 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
@@ -53,7 +53,7 @@ class WorkerThreadDebugger;
struct WorkerDevToolsParams;
class WorkerInspectorController final
- : public GarbageCollectedFinalized<WorkerInspectorController>,
+ : public GarbageCollected<WorkerInspectorController>,
public trace_event::EnabledStateObserver,
public DevToolsAgent::Client,
private Thread::TaskObserver {
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 7628b902adb..7ab8fb87ecc 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
@@ -192,6 +192,11 @@ IntersectionGeometry::RootGeometry::RootGeometry(const LayoutObject* root,
if (!root || !root->GetNode() || !root->GetNode()->isConnected() ||
!root->IsBox())
return;
+ if (RuntimeEnabledFeatures::
+ IntersectionObserverDocumentScrollingElementRootEnabled() &&
+ root->GetNode() == root->GetDocument().scrollingElement()) {
+ root = root->GetDocument().GetLayoutView();
+ }
zoom = root->StyleRef().EffectiveZoom();
local_root_rect = InitializeRootRect(root, margin);
TransformState transform_state(TransformState::kApplyTransformDirection);
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 c07392fc23c..ed942cd8408 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
@@ -16,6 +16,11 @@ namespace blink {
namespace {
+Document& TrackingDocument(const IntersectionObservation* observation) {
+ if (observation->Observer()->RootIsImplicit())
+ return observation->Target()->GetDocument();
+ return (observation->Observer()->root()->GetDocument());
+}
} // namespace
@@ -65,12 +70,17 @@ void IntersectionObservation::Disconnect() {
ElementIntersectionObserverData* observer_data =
target_->IntersectionObserverData();
observer_data->RemoveObservation(*Observer());
- if (target_->isConnected() &&
+ // We track connected elements that are either the root of an explicit root
+ // observer, or the target of an implicit root observer. If the target was
+ // previously being tracked, but no longer needs to be tracked, then remove
+ // it.
+ if (target_->isConnected() && Observer()->RootIsImplicit() &&
!observer_data->IsTargetOfImplicitRootObserver() &&
!observer_data->IsRoot()) {
- target_->GetDocument()
- .EnsureIntersectionObserverController()
- .RemoveTrackedElement(*target_);
+ IntersectionObserverController* controller =
+ target_->GetDocument().GetIntersectionObserverController();
+ if (controller)
+ controller->RemoveTrackedElement(*target_);
}
}
entries_.clear();
@@ -97,8 +107,10 @@ bool IntersectionObservation::ShouldCompute(unsigned flags) {
DOMHighResTimeStamp timestamp = observer_->GetTimeStamp();
if (timestamp == -1)
return false;
- if (!(flags & kIgnoreDelay) &&
- timestamp - last_run_time_ < observer_->GetEffectiveDelay()) {
+ 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()) {
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 c8b56a7317d..fab611c1953 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
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/numerics/clamped_math.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
@@ -26,6 +27,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -38,12 +40,16 @@ class IntersectionObserverDelegateImpl final
: public IntersectionObserverDelegate {
public:
- IntersectionObserverDelegateImpl(ExecutionContext* context,
- IntersectionObserver::EventCallback callback)
- : context_(context), callback_(std::move(callback)) {}
+ IntersectionObserverDelegateImpl(
+ ExecutionContext* context,
+ IntersectionObserver::EventCallback callback,
+ IntersectionObserver::DeliveryBehavior delivery_behavior)
+ : context_(context),
+ callback_(std::move(callback)),
+ delivery_behavior_(delivery_behavior) {}
IntersectionObserver::DeliveryBehavior GetDeliveryBehavior() const override {
- return IntersectionObserver::kDeliverDuringPostLifecycleSteps;
+ return delivery_behavior_;
}
void Deliver(const HeapVector<Member<IntersectionObserverEntry>>& entries,
@@ -61,6 +67,7 @@ class IntersectionObserverDelegateImpl final
private:
WeakMember<ExecutionContext> context_;
IntersectionObserver::EventCallback callback_;
+ IntersectionObserver::DeliveryBehavior delivery_behavior_;
DISALLOW_COPY_AND_ASSIGN(IntersectionObserverDelegateImpl);
};
@@ -195,6 +202,10 @@ IntersectionObserver* IntersectionObserver::Create(
V8IntersectionObserverDelegate* delegate =
MakeGarbageCollected<V8IntersectionObserverDelegate>(callback,
script_state);
+ if (observer_init && observer_init->trackVisibility()) {
+ UseCounter::Count(delegate->GetExecutionContext(),
+ WebFeature::kIntersectionObserverV2);
+ }
return Create(observer_init, *delegate, exception_state);
}
@@ -203,6 +214,7 @@ IntersectionObserver* IntersectionObserver::Create(
const Vector<float>& thresholds,
Document* document,
EventCallback callback,
+ DeliveryBehavior behavior,
ThresholdInterpretation semantics,
DOMHighResTimeStamp delay,
bool track_visibility,
@@ -210,7 +222,7 @@ IntersectionObserver* IntersectionObserver::Create(
ExceptionState& exception_state) {
IntersectionObserverDelegateImpl* intersection_observer_delegate =
MakeGarbageCollected<IntersectionObserverDelegateImpl>(
- document, std::move(callback));
+ document, std::move(callback), behavior);
return MakeGarbageCollected<IntersectionObserver>(
*intersection_observer_delegate, nullptr, root_margin, thresholds,
semantics, delay, track_visibility, always_report_root_bounds);
@@ -318,7 +330,8 @@ void IntersectionObserver::observe(Element* target,
// be recorded after observe() is called, even if the target is detached.
observation->ComputeIntersection(
IntersectionObservation::kImplicitRootObserversNeedUpdate |
- IntersectionObservation::kExplicitRootObserversNeedUpdate);
+ IntersectionObservation::kExplicitRootObserversNeedUpdate |
+ IntersectionObservation::kIgnoreDelay);
}
}
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 2cbd6de232f..b02f3537ec7 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
@@ -91,6 +91,7 @@ class CORE_EXPORT IntersectionObserver final
const Vector<float>& thresholds,
Document* document,
EventCallback callback,
+ DeliveryBehavior behavior = kDeliverDuringPostLifecycleSteps,
ThresholdInterpretation semantics = kFractionOfTarget,
DOMHighResTimeStamp delay = 0,
bool track_visbility = false,
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 c67d7347bb5..edc08b0ec74 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
@@ -19,7 +19,7 @@ namespace blink {
class Document;
class IntersectionObserverController
- : public GarbageCollectedFinalized<IntersectionObserverController>,
+ : public GarbageCollected<IntersectionObserverController>,
public ContextClient,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(IntersectionObserverController);
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
index 8633bb771e4..3ed349b0d37 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
@@ -16,7 +16,7 @@ class IntersectionObserver;
class IntersectionObserverEntry;
class IntersectionObserverDelegate
- : public GarbageCollectedFinalized<IntersectionObserverDelegate>,
+ : public GarbageCollected<IntersectionObserverDelegate>,
public NameClient {
public:
virtual ~IntersectionObserverDelegate() = default;
diff --git a/chromium/third_party/blink/renderer/core/layout/BUILD.gn b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
index a93d0d5422a..18a5174dfd0 100644
--- a/chromium/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
@@ -5,8 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("layout") {
- split_count = 5
-
sources = [
"api/hit_test_action.h",
"api/line_layout_api_shim.h",
@@ -39,6 +37,8 @@ blink_core_sources("layout") {
"content_change_type.h",
"counter_node.cc",
"counter_node.h",
+ "custom_scrollbar.cc",
+ "custom_scrollbar.h",
"depth_ordered_layout_object_list.cc",
"depth_ordered_layout_object_list.h",
"flexible_box_algorithm.cc",
@@ -100,6 +100,8 @@ blink_core_sources("layout") {
"layout_button.h",
"layout_counter.cc",
"layout_counter.h",
+ "layout_custom_scrollbar_part.cc",
+ "layout_custom_scrollbar_part.h",
"layout_deprecated_flexible_box.cc",
"layout_deprecated_flexible_box.h",
"layout_details_marker.cc",
@@ -174,12 +176,6 @@ blink_core_sources("layout") {
"layout_ruby_run.h",
"layout_ruby_text.cc",
"layout_ruby_text.h",
- "layout_scrollbar.cc",
- "layout_scrollbar.h",
- "layout_scrollbar_part.cc",
- "layout_scrollbar_part.h",
- "layout_scrollbar_theme.cc",
- "layout_scrollbar_theme.h",
"layout_search_field.cc",
"layout_search_field.h",
"layout_shift_region.cc",
@@ -403,6 +399,8 @@ blink_core_sources("layout") {
"ng/layout_ng_flexible_box.h",
"ng/layout_ng_mixin.cc",
"ng/layout_ng_mixin.h",
+ "ng/layout_ng_progress.cc",
+ "ng/layout_ng_progress.h",
"ng/layout_ng_table_caption.cc",
"ng/layout_ng_table_caption.h",
"ng/layout_ng_table_cell.cc",
@@ -434,6 +432,7 @@ blink_core_sources("layout") {
"ng/ng_box_fragment.h",
"ng/ng_box_fragment_builder.cc",
"ng/ng_box_fragment_builder.h",
+ "ng/ng_break_appeal.h",
"ng/ng_break_token.cc",
"ng/ng_break_token.h",
"ng/ng_column_layout_algorithm.cc",
@@ -444,6 +443,7 @@ blink_core_sources("layout") {
"ng/ng_constraint_space_builder.h",
"ng/ng_container_fragment_builder.cc",
"ng/ng_container_fragment_builder.h",
+ "ng/ng_early_break.h",
"ng/ng_fieldset_layout_algorithm.cc",
"ng/ng_fieldset_layout_algorithm.h",
"ng/ng_flex_layout_algorithm.cc",
@@ -567,17 +567,10 @@ blink_core_sources("layout") {
}
if (is_android) {
- if (notouch_build) {
- sources += [
- "layout_theme_touchless.cc",
- "layout_theme_touchless.h",
- ]
- } else {
- sources += [
- "layout_theme_android.cc",
- "layout_theme_android.h",
- ]
- }
+ sources += [
+ "layout_theme_android.cc",
+ "layout_theme_android.h",
+ ]
}
if (is_fuchsia) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc
index 283ccd672e9..456ffcf24d8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.cc
@@ -23,28 +23,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
+#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
#include "third_party/blink/renderer/core/css/pseudo_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"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/custom_scrollbar_theme.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
namespace blink {
-Scrollbar* LayoutScrollbar::CreateCustomScrollbar(
+Scrollbar* CustomScrollbar::CreateCustomScrollbar(
ScrollableArea* scrollable_area,
ScrollbarOrientation orientation,
Element* style_source) {
- return MakeGarbageCollected<LayoutScrollbar>(scrollable_area, orientation,
+ return MakeGarbageCollected<CustomScrollbar>(scrollable_area, orientation,
style_source);
}
-LayoutScrollbar::LayoutScrollbar(ScrollableArea* scrollable_area,
+CustomScrollbar::CustomScrollbar(ScrollableArea* scrollable_area,
ScrollbarOrientation orientation,
Element* style_source)
: Scrollbar(scrollable_area,
@@ -52,16 +52,16 @@ LayoutScrollbar::LayoutScrollbar(ScrollableArea* scrollable_area,
kRegularScrollbar,
style_source,
nullptr,
- LayoutScrollbarTheme::GetLayoutScrollbarTheme()) {
+ CustomScrollbarTheme::GetCustomScrollbarTheme()) {
DCHECK(style_source);
- // FIXME: We need to do this because LayoutScrollbar::styleChanged is called
+ // FIXME: We need to do this because CustomScrollbar::styleChanged is called
// as soon as the scrollbar is created.
// Update the scrollbar size.
IntRect rect(0, 0, 0, 0);
UpdateScrollbarPart(kScrollbarBGPart);
- if (LayoutScrollbarPart* part = parts_.at(kScrollbarBGPart)) {
+ if (LayoutCustomScrollbarPart* part = parts_.at(kScrollbarBGPart)) {
part->UpdateLayout();
rect.SetSize(FlooredIntSize(part->Size()));
} else if (Orientation() == kHorizontalScrollbar) {
@@ -73,7 +73,7 @@ LayoutScrollbar::LayoutScrollbar(ScrollableArea* scrollable_area,
SetFrameRect(rect);
}
-LayoutScrollbar::~LayoutScrollbar() {
+CustomScrollbar::~CustomScrollbar() {
if (parts_.IsEmpty())
return;
@@ -87,43 +87,44 @@ LayoutScrollbar::~LayoutScrollbar() {
UpdateScrollbarParts(true);
}
-int LayoutScrollbar::HypotheticalScrollbarThickness(
+int CustomScrollbar::HypotheticalScrollbarThickness(
ScrollbarOrientation orientation,
const LayoutBox& enclosing_box,
const LayoutObject& style_source) {
scoped_refptr<const ComputedStyle> part_style =
- style_source.GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdScrollbar, nullptr, kScrollbarBGPart),
+ style_source.GetUncachedPseudoElementStyle(
+ PseudoElementStyleRequest(kPseudoIdScrollbar, nullptr,
+ kScrollbarBGPart),
style_source.Style());
if (orientation == kHorizontalScrollbar) {
- return LayoutScrollbarPart::ComputeScrollbarHeight(
+ return LayoutCustomScrollbarPart::ComputeScrollbarHeight(
enclosing_box.ClientHeight().ToInt(), part_style.get());
}
- return LayoutScrollbarPart::ComputeScrollbarWidth(
+ return LayoutCustomScrollbarPart::ComputeScrollbarWidth(
enclosing_box.ClientWidth().ToInt(), part_style.get());
}
-void LayoutScrollbar::Trace(blink::Visitor* visitor) {
+void CustomScrollbar::Trace(blink::Visitor* visitor) {
Scrollbar::Trace(visitor);
}
-void LayoutScrollbar::DisconnectFromScrollableArea() {
+void CustomScrollbar::DisconnectFromScrollableArea() {
UpdateScrollbarParts(true);
Scrollbar::DisconnectFromScrollableArea();
}
-void LayoutScrollbar::SetEnabled(bool e) {
+void CustomScrollbar::SetEnabled(bool e) {
bool was_enabled = Enabled();
Scrollbar::SetEnabled(e);
if (was_enabled != e)
UpdateScrollbarParts();
}
-void LayoutScrollbar::StyleChanged() {
+void CustomScrollbar::StyleChanged() {
UpdateScrollbarParts();
}
-void LayoutScrollbar::SetHoveredPart(ScrollbarPart part) {
+void CustomScrollbar::SetHoveredPart(ScrollbarPart part) {
if (part == hovered_part_)
return;
@@ -137,7 +138,7 @@ void LayoutScrollbar::SetHoveredPart(ScrollbarPart part) {
UpdateScrollbarPart(kTrackBGPart);
}
-void LayoutScrollbar::SetPressedPart(ScrollbarPart part,
+void CustomScrollbar::SetPressedPart(ScrollbarPart part,
WebInputEvent::Type type) {
ScrollbarPart old_part = pressed_part_;
Scrollbar::SetPressedPart(part, type);
@@ -149,17 +150,17 @@ void LayoutScrollbar::SetPressedPart(ScrollbarPart part,
UpdateScrollbarPart(kTrackBGPart);
}
-scoped_refptr<ComputedStyle> LayoutScrollbar::GetScrollbarPseudoStyle(
+scoped_refptr<ComputedStyle> CustomScrollbar::GetScrollbarPseudoElementStyle(
ScrollbarPart part_type,
PseudoId pseudo_id) {
if (!StyleSource()->GetLayoutObject())
return nullptr;
return StyleSource()->StyleForPseudoElement(
- PseudoStyleRequest(pseudo_id, this, part_type),
+ PseudoElementStyleRequest(pseudo_id, this, part_type),
StyleSource()->GetLayoutObject()->Style());
}
-void LayoutScrollbar::UpdateScrollbarParts(bool destroy) {
+void CustomScrollbar::UpdateScrollbarParts(bool destroy) {
UpdateScrollbarPart(kScrollbarBGPart, destroy);
UpdateScrollbarPart(kBackButtonStartPart, destroy);
UpdateScrollbarPart(kForwardButtonStartPart, destroy);
@@ -178,7 +179,7 @@ void LayoutScrollbar::UpdateScrollbarParts(bool destroy) {
bool is_horizontal = Orientation() == kHorizontalScrollbar;
int old_thickness = is_horizontal ? Height() : Width();
int new_thickness = 0;
- LayoutScrollbarPart* part = parts_.at(kScrollbarBGPart);
+ LayoutCustomScrollbarPart* part = parts_.at(kScrollbarBGPart);
if (part) {
part->UpdateLayout();
new_thickness =
@@ -230,14 +231,14 @@ static PseudoId PseudoForScrollbarPart(ScrollbarPart part) {
return kPseudoIdScrollbar;
}
-void LayoutScrollbar::UpdateScrollbarPart(ScrollbarPart part_type,
+void CustomScrollbar::UpdateScrollbarPart(ScrollbarPart part_type,
bool destroy) {
if (part_type == kNoPart)
return;
scoped_refptr<ComputedStyle> part_style =
- !destroy ? GetScrollbarPseudoStyle(part_type,
- PseudoForScrollbarPart(part_type))
+ !destroy ? GetScrollbarPseudoElementStyle(
+ part_type, PseudoForScrollbarPart(part_type))
: scoped_refptr<ComputedStyle>(nullptr);
bool need_layout_object =
@@ -276,9 +277,9 @@ void LayoutScrollbar::UpdateScrollbarPart(ScrollbarPart part_type,
}
}
- LayoutScrollbarPart* part_layout_object = parts_.at(part_type);
+ LayoutCustomScrollbarPart* part_layout_object = parts_.at(part_type);
if (!part_layout_object && need_layout_object && scrollable_area_) {
- part_layout_object = LayoutScrollbarPart::CreateAnonymous(
+ part_layout_object = LayoutCustomScrollbarPart::CreateAnonymous(
&StyleSource()->GetDocument(), scrollable_area_, this, part_type);
parts_.Set(part_type, part_layout_object);
SetNeedsPaintInvalidation(part_type);
@@ -294,8 +295,8 @@ void LayoutScrollbar::UpdateScrollbarPart(ScrollbarPart part_type,
part_layout_object->SetStyle(std::move(part_style));
}
-IntRect LayoutScrollbar::ButtonRect(ScrollbarPart part_type) const {
- LayoutScrollbarPart* part_layout_object = parts_.at(part_type);
+IntRect CustomScrollbar::ButtonRect(ScrollbarPart part_type) const {
+ LayoutCustomScrollbarPart* part_layout_object = parts_.at(part_type);
if (!part_layout_object)
return IntRect();
@@ -341,8 +342,8 @@ IntRect LayoutScrollbar::ButtonRect(ScrollbarPart part_type) const {
is_horizontal ? Height() : part_layout_object->PixelSnappedHeight());
}
-IntRect LayoutScrollbar::TrackRect(int start_length, int end_length) const {
- LayoutScrollbarPart* part = parts_.at(kTrackBGPart);
+IntRect CustomScrollbar::TrackRect(int start_length, int end_length) const {
+ LayoutCustomScrollbarPart* part = parts_.at(kTrackBGPart);
if (part)
part->UpdateLayout();
@@ -364,10 +365,10 @@ IntRect LayoutScrollbar::TrackRect(int start_length, int end_length) const {
return IntRect(X(), Y() + start_length, Width(), Height() - total_length);
}
-IntRect LayoutScrollbar::TrackPieceRectWithMargins(
+IntRect CustomScrollbar::TrackPieceRectWithMargins(
ScrollbarPart part_type,
const IntRect& old_rect) const {
- LayoutScrollbarPart* part_layout_object = parts_.at(part_type);
+ LayoutCustomScrollbarPart* part_layout_object = parts_.at(part_type);
if (!part_layout_object)
return old_rect;
@@ -385,8 +386,8 @@ IntRect LayoutScrollbar::TrackPieceRectWithMargins(
return rect;
}
-int LayoutScrollbar::MinimumThumbLength() const {
- LayoutScrollbarPart* part_layout_object = parts_.at(kThumbPart);
+int CustomScrollbar::MinimumThumbLength() const {
+ LayoutCustomScrollbarPart* part_layout_object = parts_.at(kThumbPart);
if (!part_layout_object)
return 0;
part_layout_object->UpdateLayout();
@@ -396,7 +397,7 @@ int LayoutScrollbar::MinimumThumbLength() const {
.ToInt();
}
-void LayoutScrollbar::InvalidateDisplayItemClientsOfScrollbarParts() {
+void CustomScrollbar::InvalidateDisplayItemClientsOfScrollbarParts() {
for (auto& part : parts_) {
ObjectPaintInvalidator(*part.value)
.InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
@@ -404,7 +405,7 @@ void LayoutScrollbar::InvalidateDisplayItemClientsOfScrollbarParts() {
}
}
-void LayoutScrollbar::SetVisualRect(const IntRect& rect) {
+void CustomScrollbar::SetVisualRect(const IntRect& rect) {
Scrollbar::SetVisualRect(rect);
for (auto& part : parts_)
part.value->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h
index b4d38c55542..6f097019e0f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom_scrollbar.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_SCROLLBAR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_SCROLLBAR_H_
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
@@ -37,17 +37,20 @@ namespace blink {
class ComputedStyle;
class Element;
class LayoutBox;
+class LayoutCustomScrollbarPart;
class LayoutObject;
-class LayoutScrollbarPart;
-class LayoutScrollbar final : public Scrollbar {
+// Custom scrollbars are created when a box has -webkit-scrollbar* pseudo
+// styles. The parts of a custom scrollbar are layout objects of class
+// LayoutCustomScrollbarPart.
+class CustomScrollbar final : public Scrollbar {
public:
static Scrollbar* CreateCustomScrollbar(ScrollableArea*,
ScrollbarOrientation,
Element*);
- LayoutScrollbar(ScrollableArea*, ScrollbarOrientation, Element*);
- ~LayoutScrollbar() override;
+ CustomScrollbar(ScrollableArea*, ScrollbarOrientation, Element*);
+ ~CustomScrollbar() override;
// Return the thickness that a custom scrollbar would have, without actually
// constructing the scrollbar.
@@ -63,10 +66,10 @@ class LayoutScrollbar final : public Scrollbar {
bool IsOverlayScrollbar() const override { return false; }
- LayoutScrollbarPart* GetPart(ScrollbarPart part_type) {
+ LayoutCustomScrollbarPart* GetPart(ScrollbarPart part_type) {
return parts_.at(part_type);
}
- const LayoutScrollbarPart* GetPart(ScrollbarPart part_type) const {
+ const LayoutCustomScrollbarPart* GetPart(ScrollbarPart part_type) const {
return parts_.at(part_type);
}
@@ -91,14 +94,15 @@ class LayoutScrollbar final : public Scrollbar {
void UpdateScrollbarParts(bool destroy = false);
- scoped_refptr<ComputedStyle> GetScrollbarPseudoStyle(ScrollbarPart, PseudoId);
+ scoped_refptr<ComputedStyle> GetScrollbarPseudoElementStyle(ScrollbarPart,
+ PseudoId);
void UpdateScrollbarPart(ScrollbarPart, bool destroy = false);
- HashMap<unsigned, LayoutScrollbarPart*> parts_;
+ HashMap<unsigned, LayoutCustomScrollbarPart*> parts_;
};
template <>
-struct DowncastTraits<LayoutScrollbar> {
+struct DowncastTraits<CustomScrollbar> {
static bool AllowFrom(const Scrollbar& scrollbar) {
return scrollbar.IsCustomScrollbar();
}
@@ -106,4 +110,4 @@ struct DowncastTraits<LayoutScrollbar> {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_SCROLLBAR_H_
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 1295330dc99..72410d082f8 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
@@ -431,7 +431,9 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_offset,
const LayoutUnit available_free_space = remaining_free_space;
LayoutUnit initial_position =
FlexLayoutAlgorithm::InitialContentPositionOffset(
- available_free_space, justify_content, line_items.size());
+ algorithm->StyleRef(), available_free_space, justify_content,
+ line_items.size());
+
main_axis_offset += initial_position;
sum_justify_adjustments += initial_position;
LayoutUnit max_descent; // Used when align-items: baseline.
@@ -439,6 +441,11 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_offset,
bool should_flip_main_axis =
!algorithm->StyleRef().ResolvedIsColumnFlexDirection() &&
!algorithm->IsLeftToRightFlow();
+ LayoutUnit width_for_rtl = container_logical_width;
+ // -webkit-box always started layout at an origin of 0, regardless of
+ // direction.
+ if (should_flip_main_axis && algorithm->StyleRef().IsDeprecatedWebkitBox())
+ width_for_rtl = sum_hypothetical_main_size;
for (size_t i = 0; i < line_items.size(); ++i) {
FlexItem& flex_item = line_items[i];
@@ -471,11 +478,11 @@ void FlexLine::ComputeLineItemsPosition(LayoutUnit main_axis_offset,
// In an RTL column situation, this will apply the margin-right/margin-end
// on the left. This will be fixed later in
// LayoutFlexibleBox::FlipForRightToLeftColumn.
- flex_item.desired_location = LayoutPoint(
- should_flip_main_axis
- ? container_logical_width - main_axis_offset - child_main_extent
- : main_axis_offset,
- cross_axis_offset + flex_item.FlowAwareMarginBefore());
+ flex_item.desired_location =
+ LayoutPoint(should_flip_main_axis
+ ? width_for_rtl - main_axis_offset - child_main_extent
+ : main_axis_offset,
+ cross_axis_offset + flex_item.FlowAwareMarginBefore());
main_axis_offset += child_main_extent + flex_item.FlowAwareMarginEnd();
if (i != line_items.size() - 1) {
@@ -592,18 +599,11 @@ bool FlexLayoutAlgorithm::ShouldApplyMinSizeAutoForChild(
if (!min.IsAuto())
return false;
- // TODO(crbug.com/927066): We calculate an incorrect intrinsic logical height
- // when percentages are involved, so for now don't apply min-height: auto
- // in such cases. (This is only a problem if the child has a definite height)
- const LayoutBlock* child_block = DynamicTo<LayoutBlock>(child);
- AutoClearOverrideHeight clear(const_cast<LayoutBlock*>(child_block));
- if (IsColumnFlow() && child_block &&
- child_block->HasPercentHeightDescendants() &&
- child_block->HasDefiniteLogicalHeight())
+ // webkit-box treats min-size: auto as 0.
+ if (StyleRef().IsDeprecatedWebkitBox())
return false;
return !child.ShouldApplySizeContainment() &&
- !child.DisplayLockInducesSizeContainment() &&
MainAxisOverflowForChild(child) == EOverflow::kVisible;
}
@@ -638,8 +638,9 @@ 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(
- available_cross_axis_space, align_content, flex_lines_.size());
+ LayoutUnit line_offset =
+ InitialContentPositionOffset(StyleRef(), available_cross_axis_space,
+ align_content, flex_lines_.size());
for (FlexLine& line_context : flex_lines_) {
line_context.cross_axis_offset += line_offset;
@@ -700,12 +701,20 @@ TransformedWritingMode FlexLayoutAlgorithm::GetTransformedWritingMode(
// static
StyleContentAlignmentData FlexLayoutAlgorithm::ResolvedJustifyContent(
const ComputedStyle& style) {
- const bool is_webkit_box = (style.Display() == EDisplay::kWebkitBox ||
- style.Display() == EDisplay::kWebkitInlineBox);
- ContentPosition position = is_webkit_box
- ? BoxPackToContentPosition(style.BoxPack())
- : style.ResolvedJustifyContentPosition(
- ContentAlignmentNormalBehavior());
+ const bool is_webkit_box = style.IsDeprecatedWebkitBox();
+ ContentPosition position;
+ if (is_webkit_box) {
+ position = BoxPackToContentPosition(style.BoxPack());
+ // -webkit-box treats end as start for horizontal rtl.
+ if (position == ContentPosition::kFlexEnd &&
+ !style.ResolvedIsColumnReverseFlexDirection() &&
+ !style.IsLeftToRightDirection()) {
+ position = ContentPosition::kFlexStart;
+ }
+ } else {
+ position =
+ style.ResolvedJustifyContentPosition(ContentAlignmentNormalBehavior());
+ }
ContentDistributionType distribution =
is_webkit_box ? BoxPackToContentDistribution(style.BoxPack())
: style.ResolvedJustifyContentDistribution(
@@ -735,11 +744,8 @@ StyleContentAlignmentData FlexLayoutAlgorithm::ResolvedAlignContent(
ItemPosition FlexLayoutAlgorithm::AlignmentForChild(
const ComputedStyle& flexbox_style,
const ComputedStyle& child_style) {
- const bool is_webkit_box =
- (flexbox_style.Display() == EDisplay::kWebkitBox ||
- flexbox_style.Display() == EDisplay::kWebkitInlineBox);
ItemPosition align =
- is_webkit_box
+ flexbox_style.IsDeprecatedWebkitBox()
? BoxAlignmentToItemPosition(flexbox_style.BoxAlign())
: child_style
.ResolvedAlignSelf(ItemPosition::kStretch, &flexbox_style)
@@ -763,9 +769,16 @@ ItemPosition FlexLayoutAlgorithm::AlignmentForChild(
// static
LayoutUnit FlexLayoutAlgorithm::InitialContentPositionOffset(
+ const ComputedStyle& style,
LayoutUnit available_free_space,
const StyleContentAlignmentData& data,
unsigned number_of_items) {
+ if (available_free_space <= 0 && style.IsDeprecatedWebkitBox() &&
+ style.ResolvedIsColumnFlexDirection()) {
+ // -webkit-box with vertical orientation and no available spaces positions
+ // relative to the start regardless of ContentPosition.
+ return LayoutUnit();
+ }
if (data.GetPosition() == ContentPosition::kFlexEnd)
return available_free_space;
if (data.GetPosition() == ContentPosition::kCenter)
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 e46121fb17b..0849860541b 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
@@ -65,27 +65,48 @@ enum class TransformedWritingMode {
typedef Vector<FlexItem, 8> FlexItemVector;
-class AutoClearOverrideHeight {
+class AutoClearOverrideLogicalHeight {
public:
- explicit AutoClearOverrideHeight(LayoutBlock* block)
- : block_(block), old_override_height_(-1) {
- if (block_ && block_->HasOverrideLogicalHeight()) {
- old_override_height_ = block_->OverrideLogicalHeight();
- block_->ClearOverrideLogicalHeight();
+ explicit AutoClearOverrideLogicalHeight(LayoutBox* box)
+ : box_(box), old_override_height_(-1) {
+ if (box_ && box_->HasOverrideLogicalHeight()) {
+ old_override_height_ = box_->OverrideLogicalHeight();
+ box_->ClearOverrideLogicalHeight();
}
}
- ~AutoClearOverrideHeight() {
+ ~AutoClearOverrideLogicalHeight() {
if (old_override_height_ != LayoutUnit(-1)) {
- DCHECK(block_);
- block_->SetOverrideLogicalHeight(old_override_height_);
+ DCHECK(box_);
+ box_->SetOverrideLogicalHeight(old_override_height_);
}
}
private:
- LayoutBlock* block_;
+ LayoutBox* box_;
LayoutUnit old_override_height_;
};
+class AutoClearOverrideLogicalWidth {
+ public:
+ explicit AutoClearOverrideLogicalWidth(LayoutBox* box)
+ : box_(box), old_override_width_(-1) {
+ if (box_ && box_->HasOverrideLogicalWidth()) {
+ old_override_width_ = box_->OverrideLogicalWidth();
+ box_->ClearOverrideLogicalWidth();
+ }
+ }
+ ~AutoClearOverrideLogicalWidth() {
+ if (old_override_width_ != LayoutUnit(-1)) {
+ DCHECK(box_);
+ box_->SetOverrideLogicalWidth(old_override_width_);
+ }
+ }
+
+ private:
+ LayoutBox* box_;
+ LayoutUnit old_override_width_;
+};
+
class FlexItem {
DISALLOW_NEW();
@@ -366,6 +387,7 @@ class FlexLayoutAlgorithm {
const ComputedStyle& child_style);
static LayoutUnit InitialContentPositionOffset(
+ const ComputedStyle& style,
LayoutUnit available_free_space,
const StyleContentAlignmentData&,
unsigned number_of_items);
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 976bea31e4b..b052acc1de1 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
@@ -135,6 +135,10 @@ class DefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
return false;
}
LayoutUnit FreeSpaceForStretchAutoTracksStep() const override;
+ LayoutUnit MinContentForChild(LayoutBox&) const override;
+ LayoutUnit MinLogicalSizeForChild(LayoutBox&,
+ const Length& child_min_size,
+ LayoutUnit available_size) const override;
bool IsComputingSizeContainment() const override { return false; }
};
@@ -149,10 +153,18 @@ bool GridTrackSizingAlgorithmStrategy::
GridLayoutUtils::FlowAwareDirectionForChild(grid, child, kForColumns);
if (direction == child_inline_direction) {
return child.HasRelativeLogicalWidth() ||
- child.StyleRef().LogicalWidth().IsIntrinsicOrAuto();
+ child.StyleRef().LogicalWidth().IsIntrinsicOrAuto() ||
+ child.StyleRef().MarginStart().IsPercentOrCalc() ||
+ child.StyleRef().MarginEnd().IsPercentOrCalc() ||
+ child.StyleRef().PaddingStart().IsPercentOrCalc() ||
+ child.StyleRef().PaddingEnd().IsPercentOrCalc();
}
return child.HasRelativeLogicalHeight() ||
- child.StyleRef().LogicalHeight().IsIntrinsicOrAuto();
+ child.StyleRef().LogicalHeight().IsIntrinsicOrAuto() ||
+ child.StyleRef().MarginBefore().IsPercentOrCalc() ||
+ child.StyleRef().MarginAfter().IsPercentOrCalc() ||
+ child.StyleRef().PaddingBefore().IsPercentOrCalc() ||
+ child.StyleRef().PaddingAfter().IsPercentOrCalc();
}
void GridTrackSizingAlgorithmStrategy::
@@ -404,21 +416,8 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
LayoutUnit grid_area_size =
algorithm_.GridAreaBreadthForChild(child, child_inline_direction);
-
- if (is_row_axis) {
- return MinLogicalWidthForChild(child, child_min_size, grid_area_size) +
- baseline_shim;
- }
-
- bool override_size_has_changed =
- UpdateOverrideContainingBlockContentSizeForChild(
- child, child_inline_direction, grid_area_size);
- LayoutGridItemForMinSizeComputation(child, override_size_has_changed);
-
- return child.ComputeLogicalHeightUsing(kMinSize, child_min_size,
- child.IntrinsicLogicalHeight()) +
- GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
- child.ScrollbarLogicalHeight() + baseline_shim;
+ return MinLogicalSizeForChild(child, child_min_size, grid_area_size) +
+ baseline_shim;
}
bool GridTrackSizingAlgorithm::CanParticipateInBaselineAlignment(
@@ -526,13 +525,47 @@ void GridTrackSizingAlgorithmStrategy::DistributeSpaceToTracks(
available_logical_space);
}
-LayoutUnit GridTrackSizingAlgorithmStrategy::MinLogicalWidthForChild(
+LayoutUnit GridTrackSizingAlgorithmStrategy::MinLogicalSizeForChild(
LayoutBox& child,
const Length& child_min_size,
LayoutUnit available_size) const {
- return child.ComputeLogicalWidthUsing(kMinSize, child_min_size,
- available_size, GetLayoutGrid()) +
- GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(), child);
+ GridTrackSizingDirection child_inline_direction =
+ GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
+ kForColumns);
+ bool is_row_axis = Direction() == child_inline_direction;
+
+ if (is_row_axis) {
+ return child.ComputeLogicalWidthUsing(kMinSize, child_min_size,
+ available_size, GetLayoutGrid()) +
+ GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(), child);
+ }
+
+ bool override_size_has_changed =
+ UpdateOverrideContainingBlockContentSizeForChild(
+ child, child_inline_direction, available_size);
+ LayoutGridItemForMinSizeComputation(child, override_size_has_changed);
+
+ return child.ComputeLogicalHeightUsing(kMinSize, child_min_size,
+ child.IntrinsicLogicalHeight()) +
+ GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child);
+}
+
+LayoutUnit DefiniteSizeStrategy::MinLogicalSizeForChild(
+ LayoutBox& child,
+ const Length& child_min_size,
+ LayoutUnit available_size) const {
+ GridTrackSizingDirection child_inline_direction =
+ GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
+ kForColumns);
+ LayoutUnit indefinite_size =
+ Direction() == child_inline_direction ? LayoutUnit() : LayoutUnit(-1);
+ if (ShouldClearOverrideContainingBlockContentSizeForChild(
+ *GetLayoutGrid(), child, Direction())) {
+ SetOverrideContainingBlockContentSizeForChild(child, Direction(),
+ indefinite_size);
+ }
+ return GridTrackSizingAlgorithmStrategy::MinLogicalSizeForChild(
+ child, child_min_size, available_size);
}
void DefiniteSizeStrategy::LayoutGridItemForMinSizeComputation(
@@ -577,6 +610,21 @@ LayoutUnit DefiniteSizeStrategy::FreeSpaceForStretchAutoTracksStep() const {
return algorithm_.FreeSpace(Direction()).value();
}
+DISABLE_CFI_PERF
+LayoutUnit DefiniteSizeStrategy::MinContentForChild(LayoutBox& child) const {
+ GridTrackSizingDirection child_inline_direction =
+ GridLayoutUtils::FlowAwareDirectionForChild(*GetLayoutGrid(), child,
+ kForColumns);
+ if (Direction() == child_inline_direction && child.NeedsLayout() &&
+ ShouldClearOverrideContainingBlockContentSizeForChild(
+ *GetLayoutGrid(), child, child_inline_direction)) {
+ SetOverrideContainingBlockContentSizeForChild(child, child_inline_direction,
+ LayoutUnit());
+ }
+
+ return GridTrackSizingAlgorithmStrategy::MinContentForChild(child);
+}
+
void IndefiniteSizeStrategy::LayoutGridItemForMinSizeComputation(
LayoutBox& child,
bool override_size_has_changed) const {
@@ -873,9 +921,8 @@ GridTrackSize GridTrackSizingAlgorithm::GetGridTrackSize(
// values are treated as <auto>.
if (IsRelativeSizedTrackAsAuto(track_size, direction)) {
if (direction == kForRows) {
- Deprecation::CountDeprecation(
- layout_grid_->GetDocument(),
- WebFeature::kGridRowTrackPercentIndefiniteHeight);
+ UseCounter::Count(layout_grid_->GetDocument(),
+ WebFeature::kGridRowTrackPercentIndefiniteHeight);
}
if (min_track_breadth.HasPercentage())
min_track_breadth = Length::Auto();
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 1f81a76b93b..6107043fa69 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
@@ -293,9 +293,9 @@ class GridTrackSizingAlgorithmStrategy {
GridTrackSizingAlgorithmStrategy(GridTrackSizingAlgorithm& algorithm)
: algorithm_(algorithm) {}
- virtual LayoutUnit MinLogicalWidthForChild(LayoutBox&,
- const Length& child_min_size,
- LayoutUnit available_size) const;
+ virtual LayoutUnit MinLogicalSizeForChild(LayoutBox&,
+ const Length& child_min_size,
+ LayoutUnit available_size) const;
virtual void LayoutGridItemForMinSizeComputation(
LayoutBox&,
bool override_size_has_changed) const = 0;
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
index bc42a71066f..43f3e253c9d 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
@@ -44,8 +44,7 @@ struct HitTestCacheEntry {
void CacheValues(const HitTestCacheEntry&);
};
-class CORE_EXPORT HitTestCache final
- : public GarbageCollectedFinalized<HitTestCache> {
+class CORE_EXPORT HitTestCache final : public GarbageCollected<HitTestCache> {
public:
HitTestCache() : update_index_(0), dom_tree_version_(0) {}
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_canvas_result.h b/chromium/third_party/blink/renderer/core/layout/hit_test_canvas_result.h
index e6478592201..341faf0840b 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_canvas_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_canvas_result.h
@@ -10,7 +10,7 @@
namespace blink {
class CORE_EXPORT HitTestCanvasResult final
- : public GarbageCollectedFinalized<HitTestCanvasResult> {
+ : public GarbageCollected<HitTestCanvasResult> {
public:
HitTestCanvasResult(String id, Member<Element> control);
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 af040312df0..92d0ae44651 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block.cc
@@ -308,7 +308,8 @@ void LayoutBlock::AddChildBeforeDescendant(LayoutObject* new_child,
// Insert the child into the anonymous block box instead of here.
if (new_child->IsInline() ||
(new_child->IsFloatingOrOutOfFlowPositioned() &&
- !IsFlexibleBoxIncludingNG() && !IsLayoutGrid()) ||
+ (StyleRef().IsDeprecatedFlexboxUsingFlexLayout() ||
+ (!IsFlexibleBoxIncludingNG() && !IsLayoutGrid()))) ||
before_descendant->Parent()->SlowFirstChild() != before_descendant) {
before_descendant_container->AddChild(new_child, before_descendant);
} else {
@@ -350,7 +351,8 @@ void LayoutBlock::AddChild(LayoutObject* new_child,
if (new_child->IsInline() ||
(new_child->IsFloatingOrOutOfFlowPositioned() &&
- !IsFlexibleBoxIncludingNG() && !IsLayoutGrid())) {
+ (StyleRef().IsDeprecatedFlexboxUsingFlexLayout() ||
+ (!IsFlexibleBoxIncludingNG() && !IsLayoutGrid())))) {
// If we're inserting an inline child but all of our children are blocks,
// then we have to make sure it is put into an anomyous block box. We try to
// use an existing anonymous box if possible, otherwise a new one is created
@@ -470,6 +472,9 @@ void LayoutBlock::UpdateBlockLayout(bool) {
}
void LayoutBlock::AddVisualOverflowFromChildren() {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
if (ChildrenInline())
To<LayoutBlockFlow>(this)->AddVisualOverflowFromInlineChildren();
else
@@ -477,7 +482,7 @@ void LayoutBlock::AddVisualOverflowFromChildren() {
}
void LayoutBlock::AddLayoutOverflowFromChildren() {
- if (DisplayLockInducesSizeContainment())
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
return;
if (ChildrenInline())
@@ -571,6 +576,9 @@ void LayoutBlock::AddLayoutOverflowFromBlockChildren() {
}
void LayoutBlock::AddLayoutOverflowFromPositionedObjects() {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects();
if (!positioned_descendants)
return;
@@ -1042,7 +1050,7 @@ void LayoutBlock::ImageChanged(WrappedImagePtr image,
CanDeferInvalidation defer) {
LayoutBox::ImageChanged(image, defer);
- if (!StyleRef().HasPseudoStyle(kPseudoIdFirstLine))
+ if (!StyleRef().HasPseudoElementStyle(kPseudoIdFirstLine))
return;
const auto* first_line_style = FirstLineStyleWithoutFallback();
@@ -1445,11 +1453,6 @@ void LayoutBlock::ComputeIntrinsicLogicalWidths(
ContentLogicalWidthForSizeContainment() + LayoutUnit(scrollbar_width);
return;
}
- } else if (DisplayLockInducesSizeContainment()) {
- min_logical_width = max_logical_width =
- LayoutUnit(scrollbar_width) +
- GetDisplayLockContext()->GetLockedContentLogicalWidth();
- return;
}
if (ChildrenInline()) {
@@ -1493,7 +1496,8 @@ void LayoutBlock::ComputePreferredLogicalWidths() {
const ComputedStyle& style_to_use = StyleRef();
if (!IsTableCell() && style_to_use.LogicalWidth().IsFixed() &&
style_to_use.LogicalWidth().Value() >= 0 &&
- !(IsDeprecatedFlexItem() && !style_to_use.LogicalWidth().IntValue()))
+ !(IsFlexItemCommon() && Parent()->StyleRef().IsDeprecatedWebkitBox() &&
+ !style_to_use.LogicalWidth().IntValue()))
min_preferred_logical_width_ = max_preferred_logical_width_ =
AdjustContentBoxLogicalWidthForBoxSizing(
LayoutUnit(style_to_use.LogicalWidth().Value()));
@@ -1896,7 +1900,7 @@ const LayoutBlock* LayoutBlock::EnclosingFirstLineStyleBlock() const {
bool has_pseudo = false;
while (true) {
has_pseudo =
- first_line_block->StyleRef().HasPseudoStyle(kPseudoIdFirstLine);
+ first_line_block->StyleRef().HasPseudoElementStyle(kPseudoIdFirstLine);
if (has_pseudo)
break;
LayoutObject* parent_block = first_line_block->Parent();
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 0c2558ae24b..5d06f924de1 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
@@ -2033,8 +2033,12 @@ void LayoutBlockFlow::LayoutInlineChildren(bool relayout_children,
// |LayoutIfNeeded| should not mark itself and its ancestors to
// |NeedsLayout|.
for (const LayoutObject* parent = atomic_inline_child;
- parent && parent != this; parent = parent->Parent())
- DCHECK(!parent->NeedsLayout());
+ parent && parent != this; parent = parent->Parent()) {
+ DCHECK(!parent->SelfNeedsLayout());
+ DCHECK(!parent->NeedsLayout() ||
+ parent->LayoutBlockedByDisplayLock(
+ DisplayLockLifecycleTarget::kChildren));
+ }
#endif
}
@@ -2124,7 +2128,6 @@ RootInlineBox* LayoutBlockFlow::DetermineStartPosition(
if (layout_state.HasInlineChild() && !SelfNeedsLayout()) {
SetNeedsLayoutAndFullPaintInvalidation(
layout_invalidation_reason::kFloatDescendantChanged, kMarkOnlyThis);
- SetShouldDoFullPaintInvalidation();
}
DeleteLineBoxTree();
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 29c0f7e5ea8..be772cbd111 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
@@ -182,6 +182,7 @@ void LayoutBox::WillBeDestroyed() {
first_inline_fragment->LayoutObjectWillBeDestroyed();
}
+ SetSnapContainer(nullptr);
LayoutBoxModelObject::WillBeDestroyed();
}
@@ -475,9 +476,7 @@ void LayoutBox::UpdateGridPositionAfterStyleChange(
void LayoutBox::UpdateScrollSnapMappingAfterStyleChange(
const ComputedStyle& old_style) {
DCHECK(Style());
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- if (!snap_coordinator)
- return;
+ SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator();
// scroll-snap-type and scroll-padding invalidate the snap container.
if (old_style.GetScrollSnapType() != StyleRef().GetScrollSnapType() ||
@@ -485,7 +484,7 @@ void LayoutBox::UpdateScrollSnapMappingAfterStyleChange(
old_style.ScrollPaddingLeft() != StyleRef().ScrollPaddingLeft() ||
old_style.ScrollPaddingTop() != StyleRef().ScrollPaddingTop() ||
old_style.ScrollPaddingRight() != StyleRef().ScrollPaddingRight()) {
- snap_coordinator->SnapContainerDidChange(*this, false /* is_removed */);
+ snap_coordinator.SnapContainerDidChange(*this);
}
// scroll-snap-align, scroll-snap-stop and scroll-margin invalidate the snap
@@ -496,25 +495,17 @@ void LayoutBox::UpdateScrollSnapMappingAfterStyleChange(
old_style.ScrollMarginLeft() != StyleRef().ScrollMarginLeft() ||
old_style.ScrollMarginTop() != StyleRef().ScrollMarginTop() ||
old_style.ScrollMarginRight() != StyleRef().ScrollMarginRight())
- snap_coordinator->SnapAreaDidChange(*this, StyleRef().GetScrollSnapAlign());
+ snap_coordinator.SnapAreaDidChange(*this, StyleRef().GetScrollSnapAlign());
}
void LayoutBox::AddScrollSnapMapping() {
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- if (!snap_coordinator)
- return;
-
- snap_coordinator->SnapContainerDidChange(*this, false /* is_removed */);
- snap_coordinator->SnapAreaDidChange(*this, Style()->GetScrollSnapAlign());
+ SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator();
+ snap_coordinator.SnapAreaDidChange(*this, Style()->GetScrollSnapAlign());
}
void LayoutBox::ClearScrollSnapMapping() {
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- if (!snap_coordinator)
- return;
-
- snap_coordinator->SnapContainerDidChange(*this, true /* is_removed */);
- snap_coordinator->SnapAreaDidChange(*this, cc::ScrollSnapAlign());
+ SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator();
+ snap_coordinator.SnapAreaDidChange(*this, cc::ScrollSnapAlign());
}
void LayoutBox::UpdateFromStyle() {
@@ -588,6 +579,41 @@ int LayoutBox::PixelSnappedClientHeight() const {
return SnapSizeToPixel(ClientHeight(), Location().Y() + ClientTop());
}
+int LayoutBox::PixelSnappedClientWidthWithTableSpecialBehavior() const {
+ // clientWidth/Height is the visual portion of the box content, not including
+ // borders or scroll bars, but includes padding. And per
+ // https://www.w3.org/TR/CSS2/tables.html#model,
+ // table wrapper box is a principal block box that contains the table box
+ // itself and any caption boxes, and table grid box is a block-level box that
+ // contains the table's internal table boxes. When table's border is specified
+ // in CSS, the border is added to table grid box, not table wrapper box.
+ // Currently, Blink doesn't have table wrapper box, and we are supposed to
+ // retrieve clientWidth/Height from table wrapper box, not table grid box. So
+ // when we retrieve clientWidth/Height, it includes table's border size.
+ LayoutUnit client_width = ClientWidth();
+ if (IsTable())
+ client_width += BorderLeft() + BorderRight();
+ return SnapSizeToPixel(client_width, Location().X() + ClientLeft());
+}
+
+DISABLE_CFI_PERF
+int LayoutBox::PixelSnappedClientHeightWithTableSpecialBehavior() const {
+ // clientWidth/Height is the visual portion of the box content, not including
+ // borders or scroll bars, but includes padding. And per
+ // https://www.w3.org/TR/CSS2/tables.html#model,
+ // table wrapper box is a principal block box that contains the table box
+ // itself and any caption boxes, and table grid box is a block-level box that
+ // contains the table's internal table boxes. When table's border is specified
+ // in CSS, the border is added to table grid box, not table wrapper box.
+ // Currently, Blink doesn't have table wrapper box, and we are supposed to
+ // retrieve clientWidth/Height from table wrapper box, not table grid box. So
+ // when we retrieve clientWidth/Height, it includes table's border size.
+ LayoutUnit client_height = ClientHeight();
+ if (IsTable())
+ client_height += BorderTop() + BorderBottom();
+ return SnapSizeToPixel(client_height, Location().Y() + ClientTop());
+}
+
int LayoutBox::PixelSnappedOffsetWidth(const Element*) const {
return SnapSizeToPixel(OffsetWidth(), Location().X() + ClientLeft());
}
@@ -2028,6 +2054,7 @@ void LayoutBox::ExcludeScrollbars(
overlay_scrollbar_clip_behavior);
rect.size.height -= scrollable_area->HorizontalScrollbarHeight(
overlay_scrollbar_clip_behavior);
+ rect.size.ClampNegativeToZero();
}
}
@@ -2278,23 +2305,25 @@ void LayoutBox::InLayoutNGInlineFormattingContextWillChange(bool new_value) {
void LayoutBox::SetCachedLayoutResult(const NGLayoutResult& layout_result,
const NGBreakToken* break_token) {
+ DCHECK_EQ(layout_result.Status(), NGLayoutResult::kSuccess);
+ DCHECK(!layout_result.GetConstraintSpaceForCaching().IsIntermediateLayout());
+
if (break_token)
return;
- if (layout_result.Status() != NGLayoutResult::kSuccess)
- return;
- if (!layout_result.HasValidConstraintSpaceForCaching())
- return;
- if (layout_result.GetConstraintSpaceForCaching().IsIntermediateLayout())
- return;
if (layout_result.PhysicalFragment().BreakToken())
return;
cached_layout_result_ = &layout_result;
}
+void LayoutBox::ClearCachedLayoutResult() {
+ cached_layout_result_ = nullptr;
+}
+
scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
const NGConstraintSpace& new_space,
const NGBreakToken* break_token,
+ const NGEarlyBreak* early_break,
base::Optional<NGFragmentGeometry>* initial_fragment_geometry,
NGLayoutCacheStatus* out_cache_status) {
*out_cache_status = NGLayoutCacheStatus::kNeedsLayout;
@@ -2310,6 +2339,11 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
if (break_token)
return nullptr;
+ if (early_break)
+ return nullptr;
+
+ DCHECK_EQ(cached_layout_result->Status(), NGLayoutResult::kSuccess);
+
// Set our initial temporary cache status to "hit".
NGLayoutCacheStatus cache_status = NGLayoutCacheStatus::kHit;
@@ -2443,10 +2477,6 @@ scoped_refptr<const NGLayoutResult> LayoutBox::CachedLayoutResult(
// not clear the child dirty bits.
ClearNeedsLayout();
- // The checks above should be enough to bail if layout is incomplete, but
- // let's verify:
- DCHECK(IsBlockLayoutComplete(old_space, *cached_layout_result));
-
// OOF-positioned nodes have to two-tier cache. The additional cache check
// runs before the OOF-positioned sizing, and positioning calculations.
//
@@ -2870,7 +2900,7 @@ static float GetMaxWidthListMarker(const LayoutBox* layout_object) {
DCHECK(layout_object);
Node* parent_node = layout_object->GeneratingNode();
DCHECK(parent_node);
- DCHECK(IsHTMLOListElement(parent_node) || IsHTMLUListElement(parent_node));
+ DCHECK(IsA<HTMLOListElement>(parent_node) || IsHTMLUListElement(parent_node));
DCHECK_NE(layout_object->StyleRef().TextAutosizingMultiplier(), 1);
#endif
float max_width = 0;
@@ -2903,10 +2933,6 @@ void LayoutBox::ComputeLogicalWidth(
computed_values.extent_ = ContentLogicalWidthForSizeContainment() +
BorderAndPaddingLogicalWidth() +
ScrollbarLogicalWidth();
- } else if (DisplayLockInducesSizeContainment()) {
- computed_values.extent_ =
- BorderAndPaddingLogicalWidth() + ScrollbarLogicalWidth() +
- GetDisplayLockContext()->GetLockedContentLogicalWidth();
} else {
computed_values.extent_ = LogicalWidth();
}
@@ -3011,7 +3037,7 @@ void LayoutBox::ComputeLogicalWidth(
if (style_to_use.TextAutosizingMultiplier() != 1 &&
style_to_use.MarginStart().IsFixed()) {
Node* parent_node = GeneratingNode();
- if (parent_node && (IsHTMLOListElement(*parent_node) ||
+ if (parent_node && (IsA<HTMLOListElement>(*parent_node) ||
IsHTMLUListElement(*parent_node))) {
// Make sure the markers in a list are properly positioned (i.e. not
// chopped off) when autosized.
@@ -3162,7 +3188,7 @@ bool LayoutBox::ColumnFlexItemHasStretchAlignment() const {
bool LayoutBox::IsStretchingColumnFlexItem() const {
LayoutObject* parent = Parent();
- if (parent->IsDeprecatedFlexibleBox() &&
+ if (parent->StyleRef().IsDeprecatedWebkitBox() &&
parent->StyleRef().BoxOrient() == EBoxOrient::kVertical &&
parent->StyleRef().BoxAlign() == EBoxAlignment::kStretch)
return true;
@@ -3231,7 +3257,9 @@ bool LayoutBox::SizesLogicalWidthToFitContent(
// their intrinsic widths.
// FIXME: Think about writing-mode here.
// https://bugs.webkit.org/show_bug.cgi?id=46473
- if (Parent()->IsDeprecatedFlexibleBox() &&
+ if ((Parent()->IsDeprecatedFlexibleBox() ||
+ (Parent()->StyleRef().IsDeprecatedWebkitBox() &&
+ Parent()->IsFlexibleBox())) &&
(Parent()->StyleRef().BoxOrient() == EBoxOrient::kHorizontal ||
Parent()->StyleRef().BoxAlign() != EBoxAlignment::kStretch))
return true;
@@ -3254,10 +3282,10 @@ bool LayoutBox::SizesLogicalWidthToFitContent(
}
bool LayoutBox::AutoWidthShouldFitContent() const {
- return GetNode() &&
- (IsHTMLInputElement(*GetNode()) || IsHTMLSelectElement(*GetNode()) ||
- IsA<HTMLButtonElement>(*GetNode()) ||
- IsHTMLTextAreaElement(*GetNode()) || IsRenderedLegend());
+ return GetNode() && (IsHTMLInputElement(*GetNode()) ||
+ IsA<HTMLSelectElement>(*GetNode()) ||
+ IsA<HTMLButtonElement>(*GetNode()) ||
+ IsHTMLTextAreaElement(*GetNode()) || IsRenderedLegend());
}
void LayoutBox::ComputeMarginsForDirection(MarginDirection flow_direction,
@@ -3409,9 +3437,6 @@ void LayoutBox::ComputeLogicalHeight(
if (ShouldApplySizeContainment() && !IsLayoutGrid()) {
height = ContentLogicalHeightForSizeContainment() +
BorderAndPaddingLogicalHeight() + ScrollbarLogicalHeight();
- } else if (DisplayLockInducesSizeContainment()) {
- height = BorderAndPaddingLogicalHeight() + ScrollbarLogicalHeight() +
- GetDisplayLockContext()->GetLockedContentLogicalHeight();
} else {
height = LogicalHeight();
}
@@ -3549,17 +3574,10 @@ void LayoutBox::ComputeLogicalHeight(
LayoutUnit LayoutBox::ComputeLogicalHeightWithoutLayout() const {
LogicalExtentComputedValues computed_values;
- if (!SelfNeedsLayout()) {
- if (ShouldApplySizeContainment()) {
- ComputeLogicalHeight(ContentLogicalHeightForSizeContainment() +
- BorderAndPaddingLogicalHeight(),
- LayoutUnit(), computed_values);
- } else if (DisplayLockInducesSizeContainment()) {
- ComputeLogicalHeight(
- BorderAndPaddingLogicalHeight() +
- GetDisplayLockContext()->GetLockedContentLogicalHeight(),
- LayoutUnit(), computed_values);
- }
+ if (!SelfNeedsLayout() && ShouldApplySizeContainment()) {
+ ComputeLogicalHeight(ContentLogicalHeightForSizeContainment() +
+ BorderAndPaddingLogicalHeight(),
+ LayoutUnit(), computed_values);
} else {
// TODO(cbiesinger): We should probably return something other than just
// border + padding, but for now we have no good way to do anything else
@@ -5542,6 +5560,8 @@ void LayoutBox::AddVisualOverflowFromChild(const LayoutBox& child,
DISABLE_CFI_PERF
void LayoutBox::AddLayoutOverflowFromChild(const LayoutBox& child,
const LayoutSize& delta) {
+ DCHECK(!LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren));
+
// Never allow flow threads to propagate overflow up to a parent.
if (child.IsLayoutFlowThread())
return;
@@ -5729,8 +5749,7 @@ LayoutBox::PaginationBreakability LayoutBox::GetPaginationBreakability() const {
(Parent() && IsWritingModeRoot()) ||
(IsOutOfFlowPositioned() &&
StyleRef().GetPosition() == EPosition::kFixed) ||
- ShouldApplySizeContainment() || DisplayLockInducesSizeContainment() ||
- IsFrameSet())
+ ShouldApplySizeContainment() || IsFrameSet())
return kForbidBreaks;
EBreakInside break_value = BreakInside();
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 1ce02c21350..87a70c14134 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.h
@@ -42,6 +42,7 @@ class NGBoxFragmentBuilder;
class NGConstraintSpace;
class ShapeOutsideInfo;
struct BoxLayoutExtraInput;
+class NGEarlyBreak;
class NGBreakToken;
struct NGFragmentGeometry;
enum class NGLayoutCacheStatus;
@@ -704,6 +705,8 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// TODO(crbug.com/962299): This is incorrect in some cases.
int PixelSnappedClientWidth() const;
int PixelSnappedClientHeight() const;
+ int PixelSnappedClientWidthWithTableSpecialBehavior() const;
+ int PixelSnappedClientHeightWithTableSpecialBehavior() const;
// scrollWidth/scrollHeight will be the same as clientWidth/clientHeight
// unless the object has overflow:hidden/scroll/auto specified and also has
@@ -950,6 +953,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
void SetFirstInlineFragment(NGPaintFragment*) final;
void SetCachedLayoutResult(const NGLayoutResult&, const NGBreakToken*);
+ void ClearCachedLayoutResult();
const NGLayoutResult* GetCachedLayoutResult() const {
return cached_layout_result_.get();
}
@@ -966,6 +970,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
scoped_refptr<const NGLayoutResult> CachedLayoutResult(
const NGConstraintSpace&,
const NGBreakToken*,
+ const NGEarlyBreak*,
base::Optional<NGFragmentGeometry>* initial_fragment_geometry,
NGLayoutCacheStatus* out_cache_status);
@@ -1293,9 +1298,6 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
bool IsCustomItem() const;
bool IsCustomItemShrinkToFit() const;
- bool IsDeprecatedFlexItem() const {
- return IsFlexItemCommon() && Parent()->IsDeprecatedFlexibleBox();
- }
bool IsFlexItemIncludingDeprecatedAndNG() const {
return IsFlexItemCommon() &&
Parent()->IsFlexibleBoxIncludingDeprecatedAndNG();
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 e905b1ae203..d585612af79 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
@@ -464,6 +464,15 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
if (old_transform.IsInvertible() != new_transform.IsInvertible())
Layer()->SetNeedsRepaint();
}
+
+ // We can't squash across a layout containment boundary. So, if the
+ // containment changes, we need to update the compositing inputs.
+ if (old_style &&
+ ShouldApplyLayoutContainment(*old_style) !=
+ ShouldApplyLayoutContainment() &&
+ Layer()) {
+ Layer()->SetNeedsCompositingInputsUpdate();
+ }
}
void LayoutBoxModelObject::InvalidateStickyConstraints() {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
index 3b672593b1c..ce392f5ce23 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
@@ -1198,4 +1198,35 @@ TEST_F(LayoutBoxModelObjectTest, UpdateStackingContextForOption) {
EXPECT_TRUE(option_layout->StyleRef().HasCurrentOpacityAnimation());
}
+// Tests that contain: layout changes cause compositing inputs update.
+TEST_F(LayoutBoxModelObjectTest,
+ LayoutContainmentChangeCausesCompositingInputsUpdate) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ /* ensure we retain the paint layer after removing .contained class. */
+ div { position: relative; }
+ .contained { contain: layout; }
+ </style>
+ <div id=target class=contained></div>
+ <div id=unrelated class=contained></div>
+ )HTML");
+ LayoutBoxModelObject* target =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"));
+ ASSERT_TRUE(target->Layer());
+
+ EXPECT_FALSE(target->Layer()->NeedsCompositingInputsUpdate());
+ EXPECT_EQ(target->Layer(), target->Layer()->NearestContainedLayoutLayer());
+
+ To<HTMLElement>(target->GetNode())->classList().Remove("contained");
+ GetDocument().View()->UpdateLifecycleToLayoutClean();
+
+ EXPECT_TRUE(target->Layer()->NeedsCompositingInputsUpdate());
+
+ // After updating compositing inputs we should have no contained layer
+ // ancestors.
+ UpdateAllLifecyclePhasesForTest();
+ ASSERT_TRUE(target->Layer());
+ EXPECT_FALSE(target->Layer()->NeedsCompositingInputsUpdate());
+ EXPECT_EQ(nullptr, target->Layer()->NearestContainedLayoutLayer());
+}
} // namespace blink
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 b7f4bd48812..23c9d72e7a0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -185,7 +185,7 @@ static bool PlanCounter(LayoutObject& object,
is_reset = false;
return true;
}
- if (auto* olist = ToHTMLOListElementOrNull(*e)) {
+ if (auto* olist = DynamicTo<HTMLOListElement>(*e)) {
value = olist->StartConsideringItemCount();
is_reset = true;
return true;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
index a72c970b2f1..92de8406cde 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -23,21 +23,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
+#include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.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/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_theme.h"
+#include "third_party/blink/renderer/core/layout/custom_scrollbar.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/custom_scrollbar_theme.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
-LayoutScrollbarPart::LayoutScrollbarPart(ScrollableArea* scrollable_area,
- LayoutScrollbar* scrollbar,
- ScrollbarPart part)
+LayoutCustomScrollbarPart::LayoutCustomScrollbarPart(
+ ScrollableArea* scrollable_area,
+ CustomScrollbar* scrollbar,
+ ScrollbarPart part)
: LayoutBlock(nullptr),
scrollable_area_(scrollable_area),
scrollbar_(scrollbar),
@@ -47,9 +48,13 @@ LayoutScrollbarPart::LayoutScrollbarPart(ScrollableArea* scrollable_area,
static void RecordScrollbarPartStats(Document& document, ScrollbarPart part) {
switch (part) {
- case kBackButtonStartPart:
- case kForwardButtonStartPart:
case kBackButtonEndPart:
+ case kForwardButtonStartPart:
+ UseCounter::Count(
+ document,
+ WebFeature::kCSSSelectorPseudoScrollbarButtonReversedDirection);
+ U_FALLTHROUGH;
+ case kBackButtonStartPart:
case kForwardButtonEndPart:
UseCounter::Count(document,
WebFeature::kCSSSelectorPseudoScrollbarButton);
@@ -74,19 +79,19 @@ static void RecordScrollbarPartStats(Document& document, ScrollbarPart part) {
}
}
-LayoutScrollbarPart* LayoutScrollbarPart::CreateAnonymous(
+LayoutCustomScrollbarPart* LayoutCustomScrollbarPart::CreateAnonymous(
Document* document,
ScrollableArea* scrollable_area,
- LayoutScrollbar* scrollbar,
+ CustomScrollbar* scrollbar,
ScrollbarPart part) {
- LayoutScrollbarPart* layout_object =
- new LayoutScrollbarPart(scrollable_area, scrollbar, part);
+ LayoutCustomScrollbarPart* layout_object =
+ new LayoutCustomScrollbarPart(scrollable_area, scrollbar, part);
RecordScrollbarPartStats(*document, part);
layout_object->SetDocumentForAnonymous(document);
return layout_object;
}
-void LayoutScrollbarPart::UpdateLayout() {
+void LayoutCustomScrollbarPart::UpdateLayout() {
// We don't worry about positioning ourselves. We're just determining our
// minimum width/height.
SetLocation(LayoutPoint());
@@ -98,7 +103,7 @@ void LayoutScrollbarPart::UpdateLayout() {
ClearNeedsLayout();
}
-void LayoutScrollbarPart::LayoutHorizontalPart() {
+void LayoutCustomScrollbarPart::LayoutHorizontalPart() {
if (part_ == kScrollbarBGPart) {
SetWidth(LayoutUnit(scrollbar_->Width()));
UpdateScrollbarHeight();
@@ -108,7 +113,7 @@ void LayoutScrollbarPart::LayoutHorizontalPart() {
}
}
-void LayoutScrollbarPart::LayoutVerticalPart() {
+void LayoutCustomScrollbarPart::LayoutVerticalPart() {
if (part_ == kScrollbarBGPart) {
UpdateScrollbarWidth();
SetHeight(LayoutUnit(scrollbar_->Height()));
@@ -127,9 +132,10 @@ static int CalcScrollbarThicknessUsing(SizeType size_type,
return theme->ScrollbarThickness();
}
-int LayoutScrollbarPart::ComputeScrollbarWidth(int visible_size,
- const ComputedStyle* style) {
- LayoutScrollbarTheme* theme = LayoutScrollbarTheme::GetLayoutScrollbarTheme();
+int LayoutCustomScrollbarPart::ComputeScrollbarWidth(
+ int visible_size,
+ const ComputedStyle* style) {
+ CustomScrollbarTheme* theme = CustomScrollbarTheme::GetCustomScrollbarTheme();
int w = CalcScrollbarThicknessUsing(kMainOrPreferredSize, style->Width(),
visible_size, theme);
int min_width = CalcScrollbarThicknessUsing(kMinSize, style->MinWidth(),
@@ -143,9 +149,10 @@ int LayoutScrollbarPart::ComputeScrollbarWidth(int visible_size,
return std::max(min_width, std::min(max_width, w));
}
-int LayoutScrollbarPart::ComputeScrollbarHeight(int visible_size,
- const ComputedStyle* style) {
- LayoutScrollbarTheme* theme = LayoutScrollbarTheme::GetLayoutScrollbarTheme();
+int LayoutCustomScrollbarPart::ComputeScrollbarHeight(
+ int visible_size,
+ const ComputedStyle* style) {
+ CustomScrollbarTheme* theme = CustomScrollbarTheme::GetCustomScrollbarTheme();
int h = CalcScrollbarThicknessUsing(kMainOrPreferredSize, style->Height(),
visible_size, theme);
int min_height = CalcScrollbarThicknessUsing(kMinSize, style->MinHeight(),
@@ -158,7 +165,7 @@ int LayoutScrollbarPart::ComputeScrollbarHeight(int visible_size,
return std::max(min_height, std::min(max_height, h));
}
-void LayoutScrollbarPart::UpdateScrollbarWidth() {
+void LayoutCustomScrollbarPart::UpdateScrollbarWidth() {
LayoutBox* box = scrollbar_->GetScrollableArea()->GetLayoutBox();
if (!box)
return;
@@ -181,7 +188,7 @@ void LayoutScrollbarPart::UpdateScrollbarWidth() {
.Round()));
}
-void LayoutScrollbarPart::UpdateScrollbarHeight() {
+void LayoutCustomScrollbarPart::UpdateScrollbarHeight() {
LayoutBox* box = scrollbar_->GetScrollableArea()->GetLayoutBox();
if (!box)
return;
@@ -204,7 +211,7 @@ void LayoutScrollbarPart::UpdateScrollbarHeight() {
.Round()));
}
-void LayoutScrollbarPart::ComputePreferredLogicalWidths() {
+void LayoutCustomScrollbarPart::ComputePreferredLogicalWidths() {
if (!PreferredLogicalWidthsDirty())
return;
@@ -213,14 +220,15 @@ void LayoutScrollbarPart::ComputePreferredLogicalWidths() {
ClearPreferredLogicalWidthsDirty();
}
-void LayoutScrollbarPart::StyleWillChange(StyleDifference diff,
- const ComputedStyle& new_style) {
+void LayoutCustomScrollbarPart::StyleWillChange(
+ StyleDifference diff,
+ const ComputedStyle& new_style) {
LayoutBlock::StyleWillChange(diff, new_style);
SetInline(false);
}
-void LayoutScrollbarPart::StyleDidChange(StyleDifference diff,
- const ComputedStyle* old_style) {
+void LayoutCustomScrollbarPart::StyleDidChange(StyleDifference diff,
+ const ComputedStyle* old_style) {
LayoutBlock::StyleDidChange(diff, old_style);
// See adjustStyleBeforeSet() above.
DCHECK(!IsOrthogonalWritingModeRoot());
@@ -231,19 +239,19 @@ void LayoutScrollbarPart::StyleDidChange(StyleDifference diff,
SetNeedsPaintInvalidation();
}
-void LayoutScrollbarPart::ImageChanged(WrappedImagePtr image,
- CanDeferInvalidation defer) {
+void LayoutCustomScrollbarPart::ImageChanged(WrappedImagePtr image,
+ CanDeferInvalidation defer) {
SetNeedsPaintInvalidation();
LayoutBlock::ImageChanged(image, defer);
}
-void LayoutScrollbarPart::SetNeedsPaintInvalidation() {
+void LayoutCustomScrollbarPart::SetNeedsPaintInvalidation() {
if (scrollbar_) {
scrollbar_->SetNeedsPaintInvalidation(kAllParts);
return;
}
- // This LayoutScrollbarPart is a scroll corner or a resizer.
+ // This LayoutCustomScrollbarPart is a scroll corner or a resizer.
DCHECK_EQ(part_, kNoPart);
scrollable_area_->SetScrollCornerNeedsPaintInvalidation();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
index 2fd0d97b293..c6848666b51 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
@@ -23,25 +23,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_PART_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_PART_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_CUSTOM_SCROLLBAR_PART_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_CUSTOM_SCROLLBAR_PART_H_
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/scroll/scroll_types.h"
namespace blink {
-class LayoutScrollbar;
+class CustomScrollbar;
class ScrollableArea;
-class LayoutScrollbarPart final : public LayoutBlock {
+class LayoutCustomScrollbarPart final : public LayoutBlock {
public:
- static LayoutScrollbarPart* CreateAnonymous(Document*,
- ScrollableArea*,
- LayoutScrollbar* = nullptr,
- ScrollbarPart = kNoPart);
+ static LayoutCustomScrollbarPart* CreateAnonymous(Document*,
+ ScrollableArea*,
+ CustomScrollbar* = nullptr,
+ ScrollbarPart = kNoPart);
- const char* GetName() const override { return "LayoutScrollbarPart"; }
+ const char* GetName() const override { return "LayoutCustomScrollbarPart"; }
PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; }
@@ -69,7 +69,7 @@ class LayoutScrollbarPart final : public LayoutBlock {
}
bool IsOfType(LayoutObjectType type) const override {
- return type == kLayoutObjectLayoutScrollbarPart ||
+ return type == kLayoutObjectLayoutCustomScrollbarPart ||
LayoutBlock::IsOfType(type);
}
ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
@@ -81,7 +81,7 @@ class LayoutScrollbarPart final : public LayoutBlock {
void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override;
private:
- LayoutScrollbarPart(ScrollableArea*, LayoutScrollbar*, ScrollbarPart);
+ LayoutCustomScrollbarPart(ScrollableArea*, CustomScrollbar*, ScrollbarPart);
void ComputePreferredLogicalWidths() override;
@@ -106,12 +106,13 @@ class LayoutScrollbarPart final : public LayoutBlock {
bool AllowsOverflowClip() const override { return false; }
UntracedMember<ScrollableArea> scrollable_area_;
- UntracedMember<LayoutScrollbar> scrollbar_;
+ UntracedMember<CustomScrollbar> scrollbar_;
ScrollbarPart part_;
};
-DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutScrollbarPart, IsLayoutScrollbarPart());
+DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutCustomScrollbarPart,
+ IsLayoutCustomScrollbarPart());
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_PART_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_CUSTOM_SCROLLBAR_PART_H_
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 4ee529180be..856dba94459 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
@@ -433,7 +433,7 @@ void LayoutDeprecatedFlexibleBox::UpdateBlockLayout(bool relayout_children) {
TextAutosizer::LayoutScope text_autosizer_layout_scope(this);
if (previous_size != Size() ||
- (Parent()->IsDeprecatedFlexibleBox() &&
+ (Parent()->StyleRef().IsDeprecatedWebkitBox() &&
Parent()->StyleRef().BoxOrient() == EBoxOrient::kHorizontal &&
Parent()->StyleRef().BoxAlign() == EBoxAlignment::kStretch))
relayout_children = true;
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 557c3f4e556..523a69acad0 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
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/frame/embedded_content_view.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/remote_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame_view.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
@@ -254,20 +255,28 @@ void LayoutEmbeddedContent::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
LayoutReplaced::StyleDidChange(diff, old_style);
- if (!old_style || Style()->PointerEvents() != old_style->PointerEvents()) {
- if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(GetNode()))
- frame_owner->PointerEventsChanged();
+ if (EmbeddedContentView* embedded_content_view = GetEmbeddedContentView()) {
+ if (StyleRef().Visibility() != EVisibility::kVisible) {
+ embedded_content_view->Hide();
+ } else {
+ embedded_content_view->Show();
+ }
}
- EmbeddedContentView* embedded_content_view = GetEmbeddedContentView();
- if (!embedded_content_view)
+ if (old_style &&
+ StyleRef().VisibleToHitTesting() == old_style->VisibleToHitTesting()) {
return;
-
- if (StyleRef().Visibility() != EVisibility::kVisible) {
- embedded_content_view->Hide();
- } else {
- embedded_content_view->Show();
}
+
+ auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(GetNode());
+ if (!frame_owner)
+ return;
+
+ auto* frame = frame_owner->ContentFrame();
+ if (!frame)
+ return;
+
+ frame->UpdateVisibleToHitTesting();
}
void LayoutEmbeddedContent::UpdateLayout() {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
index cc9106b3d10..6c95dd69bc5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -54,9 +55,12 @@ static String LocalizedUnavailablePluginReplacementText(
case LayoutEmbeddedObject::kPluginAvailable:
break;
case LayoutEmbeddedObject::kPluginMissing:
- return locale.QueryString(WebLocalizedString::kMissingPluginText);
+ return locale.QueryString(IDS_PLUGIN_INITIALIZATION_ERROR);
case LayoutEmbeddedObject::kPluginBlockedByContentSecurityPolicy:
- return locale.QueryString(WebLocalizedString::kBlockedPluginText);
+ return String(); // There is no matched resource_id for
+ // kPluginBlockedByContentSecurityPolicy yet. Return an
+ // empty String(). See crbug.com/302130 for more
+ // details.
}
NOTREACHED();
return String();
@@ -111,7 +115,7 @@ CompositingReasons LayoutEmbeddedObject::AdditionalCompositingReasons() const {
void LayoutEmbeddedObject::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
- DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
+ DCHECK(!ShouldApplySizeContainment());
FrameView* frame_view = ChildFrameView();
if (frame_view && frame_view->GetIntrinsicSizingInfo(intrinsic_sizing_info)) {
// Handle zoom & vertical writing modes here, as the embedded document
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 9f3d43815f6..eaf12e75073 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -35,7 +35,7 @@ LayoutFieldset::LayoutFieldset(Element* element) : LayoutBlockFlow(element) {}
void LayoutFieldset::ComputePreferredLogicalWidths() {
LayoutBlockFlow::ComputePreferredLogicalWidths();
// Size-contained elements don't consider their contents for preferred sizing.
- if (ShouldApplySizeContainment() || DisplayLockInducesSizeContainment())
+ if (ShouldApplySizeContainment())
return;
if (LayoutBox* legend = FindInFlowLegend()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.cc b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.cc
index 3c4467b2c27..f2c8ab87ae7 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.cc
@@ -21,6 +21,7 @@
#include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
#include <math.h>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/fileapi/file_list.h"
@@ -92,7 +93,7 @@ void LayoutFileUploadControl::ComputeIntrinsicLogicalWidths(
TextRun::kAllowTrailingExpansion));
const String label = ToHTMLInputElement(GetNode())->GetLocale().QueryString(
- WebLocalizedString::kFileButtonNoFileSelectedLabel);
+ IDS_FORM_FILE_NO_FILE_LABEL);
float default_label_width = font.Width(ConstructTextRun(
font, label, StyleRef(), TextRun::kAllowTrailingExpansion));
if (HTMLInputElement* button = UploadButton()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
index bdd8d843941..83aceca59f4 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
@@ -55,6 +55,10 @@ class CORE_EXPORT LayoutFileUploadControl final : public LayoutBlockFlow {
PhysicalRect OverflowClipRect(const PhysicalOffset&,
OverlayScrollbarClipBehavior) const override;
+ bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override {
+ return false;
+ }
+
static const int kAfterButtonSpacing = 4;
const char* GetName() const override { return "LayoutFileUploadControl"; }
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 2eee46bcf9e..25a5729e630 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
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.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/wtf/math_extras.h"
namespace blink {
@@ -70,14 +71,8 @@ void LayoutFlexibleBox::ComputeIntrinsicLogicalWidths(
LayoutUnit& max_logical_width) const {
LayoutUnit scrollbar_width(ScrollbarLogicalWidth());
if (ShouldApplySizeContainment()) {
- max_logical_width = scrollbar_width;
- min_logical_width = scrollbar_width;
- return;
- }
- if (DisplayLockInducesSizeContainment()) {
- min_logical_width = max_logical_width =
- scrollbar_width +
- GetDisplayLockContext()->GetLockedContentLogicalWidth();
+ max_logical_width = min_logical_width =
+ ContentLogicalWidthForSizeContainment() + scrollbar_width;
return;
}
@@ -273,8 +268,10 @@ void LayoutFlexibleBox::MergeAnonymousFlexItems(LayoutObject* remove_child) {
}
void LayoutFlexibleBox::RemoveChild(LayoutObject* child) {
- if (!DocumentBeingDestroyed())
+ if (!DocumentBeingDestroyed() &&
+ !StyleRef().IsDeprecatedFlexboxUsingFlexLayout()) {
MergeAnonymousFlexItems(child);
+ }
LayoutBlock::RemoveChild(child);
intrinsic_size_along_main_axis_.erase(child);
@@ -498,21 +495,15 @@ LayoutUnit LayoutFlexibleBox::ChildUnstretchedLogicalHeight(
// This should only be called if the logical height is the cross size
DCHECK(MainAxisIsInlineAxis(child));
if (NeedToStretchChildLogicalHeight(child)) {
- LayoutUnit old_override_height = LayoutUnit(-1);
- if (child.HasOverrideLogicalHeight()) {
- old_override_height = child.OverrideLogicalHeight();
- const_cast<LayoutBox&>(child).ClearOverrideLogicalHeight();
- }
+ AutoClearOverrideLogicalHeight clear(const_cast<LayoutBox*>(&child));
LayoutUnit child_intrinsic_content_logical_height;
- if (!child.ShouldApplySizeContainment()) {
- if (child.DisplayLockInducesSizeContainment()) {
- child_intrinsic_content_logical_height =
- child.GetDisplayLockContext()->GetLockedContentLogicalHeight();
- } else {
- child_intrinsic_content_logical_height =
- child.IntrinsicContentLogicalHeight();
- }
+ if (child.ShouldApplySizeContainment()) {
+ child_intrinsic_content_logical_height =
+ child.ContentLogicalHeightForSizeContainment();
+ } else {
+ child_intrinsic_content_logical_height =
+ child.IntrinsicContentLogicalHeight();
}
LayoutUnit child_intrinsic_logical_height =
@@ -521,10 +512,6 @@ LayoutUnit LayoutFlexibleBox::ChildUnstretchedLogicalHeight(
LogicalExtentComputedValues values;
child.ComputeLogicalHeight(child_intrinsic_logical_height, LayoutUnit(),
values);
- if (old_override_height != LayoutUnit(-1)) {
- const_cast<LayoutBox&>(child).SetOverrideLogicalHeight(
- old_override_height);
- }
return values.extent_;
}
return child.LogicalHeight();
@@ -541,17 +528,10 @@ LayoutUnit LayoutFlexibleBox::ChildUnstretchedLogicalWidth(
// However, if our cross axis length is definite we don't need to recompute
// and can just return the already-set logical width.
if (!CrossAxisLengthIsDefinite(child, child.StyleRef().LogicalWidth())) {
- LayoutUnit old_override_width = LayoutUnit(-1);
- if (child.HasOverrideLogicalWidth()) {
- old_override_width = child.OverrideLogicalWidth();
- const_cast<LayoutBox&>(child).ClearOverrideLogicalWidth();
- }
+ AutoClearOverrideLogicalWidth clear(const_cast<LayoutBox*>(&child));
LogicalExtentComputedValues values;
child.ComputeLogicalWidth(values);
-
- if (old_override_width != LayoutUnit(-1))
- const_cast<LayoutBox&>(child).SetOverrideLogicalWidth(old_override_width);
return values.extent_;
}
@@ -770,7 +750,7 @@ bool LayoutFlexibleBox::MainAxisLengthIsDefinite(const LayoutBox& child,
child.ContainingBlockLogicalHeightForPercentageResolution(&cb) != -1;
if (add_to_cb)
cb->AddPercentHeightDescendant(const_cast<LayoutBox*>(&child));
- if (in_layout_) {
+ if (in_layout_ && !child.HasOverrideContainingBlockContentLogicalHeight()) {
// We can reach this code even while we're not laying ourselves out, such
// as from mainSizeForPercentageResolution.
has_definite_height_ = definite ? SizeDefiniteness::kDefinite
@@ -867,8 +847,7 @@ LayoutUnit LayoutFlexibleBox::ComputeInnerFlexBaseSizeForChild(
Length flex_basis = FlexBasisForChild(child);
// -webkit-box sizes as fit-content instead of max-content.
if (flex_basis.IsAuto() &&
- ((StyleRef().Display() == EDisplay::kWebkitBox ||
- StyleRef().Display() == EDisplay::kWebkitInlineBox) &&
+ (StyleRef().IsDeprecatedWebkitBox() &&
(StyleRef().BoxOrient() == EBoxOrient::kHorizontal ||
StyleRef().BoxAlign() != EBoxAlignment::kStretch))) {
flex_basis = Length(Length::kFitContent);
@@ -898,13 +877,11 @@ LayoutUnit LayoutFlexibleBox::ComputeInnerFlexBaseSizeForChild(
// width includes the scrollbar, even for overflow: auto.
main_axis_extent = child.MaxPreferredLogicalWidth();
} else {
- if (child.ShouldApplySizeContainment())
- return LayoutUnit(child.ScrollbarLogicalHeight());
// The needed value here is the logical height. This value does not include
// the border/scrollbar/padding size, so we have to add the scrollbar.
- if (child.DisplayLockInducesSizeContainment()) {
- return child.GetDisplayLockContext()->GetLockedContentLogicalHeight() +
- child.ScrollbarLogicalHeight();
+ if (child.ShouldApplySizeContainment()) {
+ return child.ContentLogicalHeightForSizeContainment() +
+ LayoutUnit(child.ScrollbarLogicalHeight());
}
if (child_layout_type == kNeverLayout)
@@ -942,6 +919,10 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children,
ConstructAndAppendFlexItem(&flex_algorithm, *child, layout_type);
}
+ // Because we set the override containing block logical height to -1 in
+ // ConstructAndAppendFlexItem, any value we may have cached for definiteness
+ // is incorrect; just reset it here.
+ has_definite_height_ = SizeDefiniteness::kUnknown;
LayoutUnit cross_axis_offset = FlowAwareContentInsetBefore();
LayoutUnit logical_width = LogicalWidth();
@@ -1184,9 +1165,19 @@ void LayoutFlexibleBox::ConstructAndAppendFlexItem(
UpdateBlockChildDirtyBitsBeforeLayout(layout_type == kForceLayout, child);
if (child.NeedsLayout() || layout_type == kForceLayout ||
!intrinsic_size_along_main_axis_.Contains(&child)) {
+ // Don't resolve percentages in children. This is especially important
+ // for the min-height calculation, where we want percentages to be
+ // treated as auto. For flex-basis itself, this is not a problem because
+ // by definition we have an indefinite flex basis here and thus
+ // percentages should not resolve.
+ if (IsHorizontalWritingMode() == child.IsHorizontalWritingMode())
+ child.SetOverrideContainingBlockContentLogicalHeight(LayoutUnit(-1));
+ else
+ child.SetOverrideContainingBlockContentLogicalWidth(LayoutUnit(-1));
child.ClearOverrideSize();
child.ForceLayout();
CacheChildMainSize(child);
+ child.ClearOverrideContainingBlockContentSize();
}
}
@@ -1211,7 +1202,8 @@ static LayoutUnit AlignmentOffset(LayoutUnit available_free_space,
ItemPosition position,
LayoutUnit ascent,
LayoutUnit max_ascent,
- bool is_wrap_reverse) {
+ bool is_wrap_reverse,
+ bool is_deprecated_webkit_box) {
switch (position) {
case ItemPosition::kLegacy:
case ItemPosition::kAuto:
@@ -1232,8 +1224,10 @@ static LayoutUnit AlignmentOffset(LayoutUnit available_free_space,
break;
case ItemPosition::kFlexEnd:
return available_free_space;
- case ItemPosition::kCenter:
- return available_free_space / 2;
+ case ItemPosition::kCenter: {
+ const LayoutUnit result = (available_free_space / 2);
+ return is_deprecated_webkit_box ? result.ClampNegativeToZero() : result;
+ }
case ItemPosition::kBaseline:
// FIXME: If we get here in columns, we want the use the descent, except
// we currently can't get the ascent/descent of orthogonal children.
@@ -1267,8 +1261,8 @@ LayoutUnit LayoutFlexibleBox::StaticMainAxisPositionForPositionedChild(
MainAxisExtentForChild(child);
LayoutUnit offset = FlexLayoutAlgorithm::InitialContentPositionOffset(
- available_space, FlexLayoutAlgorithm::ResolvedJustifyContent(StyleRef()),
- 1);
+ StyleRef(), available_space,
+ FlexLayoutAlgorithm::ResolvedJustifyContent(StyleRef()), 1);
if (StyleRef().ResolvedIsRowReverseFlexDirection() ||
StyleRef().ResolvedIsColumnReverseFlexDirection())
offset = available_space - offset;
@@ -1283,14 +1277,18 @@ LayoutUnit LayoutFlexibleBox::StaticCrossAxisPositionForPositionedChild(
available_space,
FlexLayoutAlgorithm::AlignmentForChild(StyleRef(), child.StyleRef()),
LayoutUnit(), LayoutUnit(),
- StyleRef().FlexWrap() == EFlexWrap::kWrapReverse);
+ StyleRef().FlexWrap() == EFlexWrap::kWrapReverse,
+ StyleRef().IsDeprecatedWebkitBox());
}
LayoutUnit LayoutFlexibleBox::StaticInlinePositionForPositionedChild(
const LayoutBox& child) {
- return StartOffsetForContent() +
- (IsColumnFlow() ? StaticCrossAxisPositionForPositionedChild(child)
- : StaticMainAxisPositionForPositionedChild(child));
+ const LayoutUnit start_offset = StartOffsetForContent();
+ if (StyleRef().IsDeprecatedWebkitBox())
+ return start_offset;
+ return start_offset + (IsColumnFlow()
+ ? StaticCrossAxisPositionForPositionedChild(child)
+ : StaticMainAxisPositionForPositionedChild(child));
}
LayoutUnit LayoutFlexibleBox::StaticBlockPositionForPositionedChild(
@@ -1384,8 +1382,7 @@ bool LayoutFlexibleBox::ChildHasIntrinsicMainAxisSize(
const FlexLayoutAlgorithm& algorithm,
const LayoutBox& child) const {
bool result = false;
- if (!MainAxisIsInlineAxis(child) && !child.ShouldApplySizeContainment() &&
- !child.DisplayLockInducesSizeContainment()) {
+ if (!MainAxisIsInlineAxis(child) && !child.ShouldApplySizeContainment()) {
Length child_flex_basis = FlexBasisForChild(child);
const Length& child_min_size = IsHorizontalFlow()
? child.StyleRef().MinWidth()
@@ -1519,7 +1516,7 @@ void LayoutFlexibleBox::LayoutColumnReverse(FlexItemVectorView& children,
// we place the children starting from the end of the flexbox.
LayoutUnit main_axis_offset = LogicalHeight() - FlowAwareContentInsetEnd();
main_axis_offset -= FlexLayoutAlgorithm::InitialContentPositionOffset(
- available_free_space, justify_content, children.size());
+ StyleRef(), available_free_space, justify_content, children.size());
for (wtf_size_t i = 0; i < children.size(); ++i) {
FlexItem& flex_item = children[i];
@@ -1607,7 +1604,8 @@ void LayoutFlexibleBox::AlignChildren(Vector<FlexLine>& line_contexts) {
LayoutUnit available_space = flex_item.AvailableAlignmentSpace();
LayoutUnit offset = AlignmentOffset(
available_space, position, flex_item.MarginBoxAscent(), max_ascent,
- StyleRef().FlexWrap() == EFlexWrap::kWrapReverse);
+ StyleRef().FlexWrap() == EFlexWrap::kWrapReverse,
+ StyleRef().IsDeprecatedWebkitBox());
AdjustAlignmentForChild(*flex_item.box, offset);
if (position == ItemPosition::kBaseline &&
StyleRef().FlexWrap() == EFlexWrap::kWrapReverse) {
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 a418fdbdbf0..65994667e48 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -1247,6 +1247,9 @@ void LayoutGrid::UpdateGridAreaLogicalSize(
}
void LayoutGrid::LayoutGridItems() {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
PopulateGridPositionsForDirection(kForColumns);
PopulateGridPositionsForDirection(kForRows);
@@ -1325,6 +1328,9 @@ bool LayoutGrid::HasStaticPositionForChild(
void LayoutGrid::LayoutPositionedObjects(bool relayout_children,
PositionedLayoutBehavior info) {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
column_of_positioned_item_.clear();
row_of_positioned_item_.clear();
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 2794fb05c4c..71066fd852e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image.cc
@@ -142,7 +142,7 @@ void LayoutImage::ImageChanged(WrappedImagePtr new_image,
}
void LayoutImage::UpdateIntrinsicSizeIfNeeded(const LayoutSize& new_size) {
- if (image_resource_->ErrorOccurred() || !image_resource_->HasImage())
+ if (image_resource_->ErrorOccurred())
return;
SetIntrinsicSize(new_size);
}
@@ -347,7 +347,7 @@ bool LayoutImage::OverrideIntrinsicSizingInfo(
void LayoutImage::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
- DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
+ DCHECK(!ShouldApplySizeContainment());
if (!OverrideIntrinsicSizingInfo(intrinsic_sizing_info)) {
if (SVGImage* svg_image = EmbeddedSVGImage()) {
svg_image->GetIntrinsicSizingInfo(intrinsic_sizing_info);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
index 11af6c1ef4f..af9230cd5f0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
@@ -37,7 +37,7 @@ namespace blink {
class LayoutObject;
class CORE_EXPORT LayoutImageResource
- : public GarbageCollectedFinalized<LayoutImageResource> {
+ : public GarbageCollected<LayoutImageResource> {
public:
LayoutImageResource();
virtual ~LayoutImageResource();
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 9058953c56c..d3459a9c7e7 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -37,7 +37,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/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_fragment_traversal.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.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"
@@ -55,15 +55,6 @@ namespace blink {
namespace {
-// TODO(layout-dev): Once we generate fragment for all inline element, we should
-// use |LayoutObject::EnclosingBlockFlowFragment()|.
-const NGPhysicalBoxFragment* ContainingBlockFlowFragmentOf(
- const LayoutInline& node) {
- if (!RuntimeEnabledFeatures::LayoutNGEnabled())
- return nullptr;
- return node.ContainingBlockFlowFragment();
-}
-
// TODO(xiaochengh): Deduplicate with a similar function in ng_paint_fragment.cc
// ::before, ::after and ::first-letter can be hit test targets.
bool CanBeHitTestTargetPseudoNodeStyle(const ComputedStyle& style) {
@@ -508,39 +499,7 @@ void LayoutInline::AddChildIgnoringContinuation(LayoutObject* new_child,
if (!new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned() &&
!new_child->IsTablePart()) {
- // 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 hold |newChild|. We then make that block box a continuation
- // of this inline. We take all of the children after |beforeChild| and put
- // them in a clone of this object.
- scoped_refptr<ComputedStyle> new_style =
- ComputedStyle::CreateAnonymousStyleWithDisplay(StyleRef(),
- EDisplay::kBlock);
- const LayoutBlock* containing_block = ContainingBlock();
- // The anon block we create here doesn't exist in the CSS spec, so
- // we need to ensure that any blocks it contains inherit properly
- // from its true parent. This means they must use the direction set by the
- // anon block's containing block, so we need to prevent the anon block
- // from inheriting direction from the inline. If there are any other
- // inheritable properties that apply to block and inline elements
- // but only affect the layout of children we will want to special-case
- // them here too. Writing-mode would be one if it didn't create a
- // formatting context of its own, removing the need 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());
-
- LegacyLayout legacy = containing_block->ForceLegacyLayout()
- ? LegacyLayout::kForce
- : LegacyLayout::kAuto;
-
- LayoutBlockFlow* new_box = LayoutBlockFlow::CreateAnonymous(
- &GetDocument(), std::move(new_style), legacy);
+ LayoutBlockFlow* new_box = CreateAnonymousContainerForBlockChildren();
LayoutBoxModelObject* old_continuation = Continuation();
SetContinuation(new_box);
@@ -731,6 +690,41 @@ void LayoutInline::SplitFlow(LayoutObject* before_child,
layout_invalidation_reason::kAnonymousBlockChange);
}
+LayoutBlockFlow* LayoutInline::CreateAnonymousContainerForBlockChildren() {
+ // 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
+ // hold |newChild|. We then make that block box a continuation of this
+ // inline. We take all of the children after |beforeChild| and put them in a
+ // clone of this object.
+ scoped_refptr<ComputedStyle> new_style =
+ ComputedStyle::CreateAnonymousStyleWithDisplay(StyleRef(),
+ EDisplay::kBlock);
+ const LayoutBlock* containing_block = ContainingBlock();
+ // The anon block we create here doesn't exist in the CSS spec, so we need to
+ // ensure that any blocks it contains inherit properly from its true
+ // parent. This means they must use the direction set by the anon block's
+ // containing block, so we need to prevent the anon block from inheriting
+ // direction from the inline. If there are any other inheritable properties
+ // that apply to block and inline elements but only affect the layout of
+ // children we will want to special-case them here too. Writing-mode would be
+ // one if it didn't create a formatting context of its own, removing the need
+ // 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());
+
+ LegacyLayout legacy = containing_block->ForceLegacyLayout()
+ ? LegacyLayout::kForce
+ : LegacyLayout::kAuto;
+
+ return LayoutBlockFlow::CreateAnonymous(&GetDocument(), std::move(new_style),
+ legacy);
+}
+
void LayoutInline::AddChildToContinuation(LayoutObject* new_child,
LayoutObject* before_child) {
// A continuation always consists of two potential candidates: an inline or an
@@ -784,12 +778,10 @@ template <typename PhysicalRectCollector>
void LayoutInline::CollectLineBoxRects(
const PhysicalRectCollector& yield) const {
if (IsInLayoutNGInlineFormattingContext()) {
- const auto* box_fragment = ContainingBlockFlowFragmentOf(*this);
- if (!box_fragment)
- return;
- for (const auto& fragment :
- NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this))
- yield(fragment.RectInContainerBox());
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject())
+ yield(cursor.CurrentRect());
return;
}
if (!AlwaysCreateLineBoxes()) {
@@ -933,15 +925,11 @@ void LayoutInline::AbsoluteQuadsForSelf(Vector<FloatQuad>& quads,
base::Optional<PhysicalOffset> LayoutInline::FirstLineBoxTopLeftInternal()
const {
if (IsInLayoutNGInlineFormattingContext()) {
- const NGPhysicalBoxFragment* box_fragment =
- ContainingBlockFlowFragmentOf(*this);
- if (!box_fragment)
- return base::nullopt;
- const auto& fragments =
- NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
- if (fragments.IsEmpty())
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ if (!cursor)
return base::nullopt;
- return fragments.front().offset_to_container_box;
+ return cursor.CurrentOffset();
}
if (const InlineBox* first_box = FirstLineBoxIncludingCulling()) {
LayoutPoint location = first_box->Location();
@@ -1080,18 +1068,11 @@ bool LayoutInline::HitTestCulledInline(
DCHECK(ContainingNGBlockFlow());
DCHECK(container_fragment->IsDescendantOfNotSelf(
*ContainingNGBlockFlow()->PaintFragment()));
- const auto& traversal_root =
- To<NGPhysicalContainerFragment>(container_fragment->PhysicalFragment());
- DCHECK(traversal_root.IsInline() || traversal_root.IsLineBox());
- PhysicalOffset root_offset =
- container_fragment->InlineOffsetToContainerBox();
- const auto& descendants =
- NGInlineFragmentTraversal::SelfFragmentsOf(traversal_root, this);
- for (const auto& descendant : descendants) {
- PhysicalRect rect = descendant.RectInContainerBox();
- rect.Move(root_offset);
- yield(rect);
- }
+ DCHECK(container_fragment->PhysicalFragment().IsInline() ||
+ container_fragment->PhysicalFragment().IsLineBox());
+ NGInlineCursor cursor(*container_fragment);
+ for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject())
+ yield(cursor.CurrentRect());
} else {
DCHECK(!ContainingNGBlockFlow());
CollectCulledLineBoxRects(yield);
@@ -1139,15 +1120,11 @@ PositionWithAffinity LayoutInline::PositionForPoint(
PhysicalRect LayoutInline::PhysicalLinesBoundingBox() const {
if (IsInLayoutNGInlineFormattingContext()) {
- const NGPhysicalBoxFragment* box_fragment =
- ContainingBlockFlowFragmentOf(*this);
- if (!box_fragment)
- return PhysicalRect();
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
PhysicalRect bounding_box;
- auto children =
- NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
- for (const auto& child : children)
- bounding_box.UniteIfNonZero(child.RectInContainerBox());
+ for (; cursor; cursor.MoveToNextForSameLayoutObject())
+ bounding_box.UniteIfNonZero(cursor.CurrentRect());
return bounding_box;
}
@@ -1474,8 +1451,7 @@ PaintLayerType LayoutInline::LayerTypeRequired() const {
void LayoutInline::ChildBecameNonInline(LayoutObject* child) {
// We have to split the parent flow.
- auto* new_box =
- To<LayoutBlockFlow>(ContainingBlock()->CreateAnonymousBlock());
+ LayoutBlockFlow* new_box = CreateAnonymousContainerForBlockChildren();
LayoutBoxModelObject* old_continuation = Continuation();
SetContinuation(new_box);
LayoutObject* before_child = child->NextSibling();
@@ -1749,10 +1725,6 @@ void LayoutInline::InvalidateDisplayItemClients(
if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
auto fragments = NGPaintFragment::InlineFragmentsFor(this);
if (fragments.IsInLayoutNGInlineFormattingContext()) {
- if (Container()->IsLayoutNGMixin() && StyleRef().HasOutline()) {
- Container()->InvalidateDisplayItemClients(
- PaintInvalidationReason::kOutline);
- }
for (NGPaintFragment* fragment : fragments) {
paint_invalidator.InvalidateDisplayItemClient(*fragment,
invalidation_reason);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_inline.h b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
index de6e98d9b5d..27a782cb538 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
@@ -327,6 +327,9 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
LayoutObject* new_child,
LayoutBoxModelObject* old_cont);
+ // Create an anoymous block for block children of this inline.
+ LayoutBlockFlow* CreateAnonymousContainerForBlockChildren();
+
void UpdateLayout() final { NOTREACHED(); } // Do nothing for layout()
void Paint(const PaintInfo&) const final;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
index a505cc55b17..f66410463cf 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
@@ -52,13 +52,13 @@ const int kDefaultPaddingBottom = 1;
LayoutListBox::LayoutListBox(Element* element) : LayoutBlockFlow(element) {
DCHECK(element);
DCHECK(element->IsHTMLElement());
- DCHECK(IsHTMLSelectElement(element));
+ DCHECK(IsA<HTMLSelectElement>(element));
}
LayoutListBox::~LayoutListBox() = default;
inline HTMLSelectElement* LayoutListBox::SelectElement() const {
- return ToHTMLSelectElement(GetNode());
+ return To<HTMLSelectElement>(GetNode());
}
unsigned LayoutListBox::size() const {
@@ -93,7 +93,7 @@ LayoutUnit LayoutListBox::ItemHeight() const {
LayoutUnit max_height;
for (Element* element : items) {
- if (auto* optgroup = ToHTMLOptGroupElementOrNull(element))
+ if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(element))
element = &optgroup->OptGroupLabelElement();
LayoutObject* layout_object = element->GetLayoutObject();
LayoutUnit item_height;
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 a584f566ed0..562427bee96 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
@@ -147,7 +147,7 @@ LayoutObject* GetParentOfFirstLineBox(LayoutBlockFlow* curr,
if (curr->IsListItem() && in_quirks_mode && curr_child->GetNode() &&
(IsHTMLUListElement(*curr_child->GetNode()) ||
- IsHTMLOListElement(*curr_child->GetNode())))
+ IsA<HTMLOListElement>(*curr_child->GetNode())))
break;
LayoutObject* line_box = GetParentOfFirstLineBox(child_block_flow, marker);
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 1598696047f..6ef978863d6 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
@@ -84,7 +84,10 @@ void LayoutListMarker::StyleWillChange(StyleDifference diff,
const ComputedStyle& new_style) {
if (Style() &&
(new_style.ListStylePosition() != StyleRef().ListStylePosition() ||
- new_style.ListStyleType() != StyleRef().ListStyleType())) {
+ new_style.ListStyleType() != StyleRef().ListStyleType() ||
+ (new_style.ListStyleType() == EListStyleType::kString &&
+ new_style.ListStyleStringValue() !=
+ StyleRef().ListStyleStringValue()))) {
SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
layout_invalidation_reason::kStyleChange);
}
@@ -201,21 +204,31 @@ void LayoutListMarker::UpdateContent() {
text_ = list_marker_text::GetText(StyleRef().ListStyleType(),
list_item_->Value());
break;
+ case ListStyleCategory::kStaticString:
+ text_ = StyleRef().ListStyleStringValue();
+ break;
}
}
String LayoutListMarker::TextAlternative() const {
+ if (GetListStyleCategory() == ListStyleCategory::kStaticString)
+ return text_;
UChar suffix =
list_marker_text::Suffix(StyleRef().ListStyleType(), list_item_->Value());
// Return suffix after the marker text, even in RTL, reflecting speech order.
return text_ + suffix + ' ';
}
-LayoutUnit LayoutListMarker::GetWidthOfTextWithSuffix() const {
+LayoutUnit LayoutListMarker::GetWidthOfText(ListStyleCategory category) const {
+ // TODO(crbug.com/1012289): this code doesn't support bidi algorithm.
if (text_.IsEmpty())
return LayoutUnit();
const Font& font = StyleRef().GetFont();
LayoutUnit item_width = LayoutUnit(font.Width(TextRun(text_)));
+ if (category == ListStyleCategory::kStaticString) {
+ // Don't add a suffix.
+ return item_width;
+ }
// TODO(wkorman): Look into constructing a text run for both text and suffix
// and painting them together.
UChar suffix[2] = {
@@ -242,14 +255,16 @@ void LayoutListMarker::ComputePreferredLogicalWidths() {
}
LayoutUnit logical_width;
- switch (GetListStyleCategory()) {
+ ListStyleCategory category = GetListStyleCategory();
+ switch (category) {
case ListStyleCategory::kNone:
break;
case ListStyleCategory::kSymbol:
logical_width = WidthOfSymbol(StyleRef());
break;
case ListStyleCategory::kLanguage:
- logical_width = GetWidthOfTextWithSuffix();
+ case ListStyleCategory::kStaticString:
+ logical_width = GetWidthOfText(category);
break;
}
@@ -395,6 +410,8 @@ LayoutListMarker::ListStyleCategory LayoutListMarker::GetListStyleCategory(
switch (type) {
case EListStyleType::kNone:
return ListStyleCategory::kNone;
+ case EListStyleType::kString:
+ return ListStyleCategory::kStaticString;
case EListStyleType::kDisc:
case EListStyleType::kCircle:
case EListStyleType::kSquare:
@@ -468,18 +485,20 @@ LayoutRect LayoutListMarker::GetRelativeMarkerRect() const {
return LayoutRect(LayoutPoint(), ImageBulletSize());
LayoutRect relative_rect;
- switch (GetListStyleCategory()) {
+ ListStyleCategory category = GetListStyleCategory();
+ switch (category) {
case ListStyleCategory::kNone:
return LayoutRect();
case ListStyleCategory::kSymbol:
return RelativeSymbolMarkerRect(StyleRef(), Size().Width());
- case ListStyleCategory::kLanguage: {
+ case ListStyleCategory::kLanguage:
+ case ListStyleCategory::kStaticString: {
const SimpleFontData* font_data = StyleRef().GetFont().PrimaryFont();
DCHECK(font_data);
if (!font_data)
return relative_rect;
relative_rect =
- LayoutRect(LayoutUnit(), LayoutUnit(), GetWidthOfTextWithSuffix(),
+ LayoutRect(LayoutUnit(), LayoutUnit(), GetWidthOfText(category),
LayoutUnit(font_data->GetFontMetrics().Height()));
break;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
index 69c6ed6574a..68d1a290b0f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
@@ -46,7 +46,7 @@ class CORE_EXPORT LayoutListMarker final : public LayoutBox {
// A reduced set of list style categories allowing for more concise expression
// of list style specific logic.
- enum class ListStyleCategory { kNone, kSymbol, kLanguage };
+ enum class ListStyleCategory { kNone, kSymbol, kLanguage, kStaticString };
// Returns the list's style as one of a reduced high level categorical set of
// styles.
@@ -113,7 +113,7 @@ class CORE_EXPORT LayoutListMarker final : public LayoutBox {
bool IsText() const { return !IsImage(); }
- LayoutUnit GetWidthOfTextWithSuffix() const;
+ LayoutUnit GetWidthOfText(ListStyleCategory) const;
void UpdateMargins();
void UpdateContent();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc b/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
index 0856171d26a..d10d4e199cd 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/layout/layout_menu_list.h"
#include <math.h>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -49,7 +50,7 @@ LayoutMenuList::LayoutMenuList(Element* element)
inner_block_height_(LayoutUnit()),
options_width_(0),
last_active_index_(-1) {
- DCHECK(IsHTMLSelectElement(element));
+ DCHECK(IsA<HTMLSelectElement>(element));
}
LayoutMenuList::~LayoutMenuList() = default;
@@ -137,9 +138,8 @@ void LayoutMenuList::AdjustInnerStyle(ComputedStyle& inner_style) const {
Length padding_start = Length::Fixed(
LayoutTheme::GetTheme().PopupInternalPaddingStart(StyleRef()));
- Length padding_end =
- Length::Fixed(LayoutTheme::GetTheme().PopupInternalPaddingEnd(
- GetFrameView()->GetChromeClient(), StyleRef()));
+ Length padding_end = Length::Fixed(
+ LayoutTheme::GetTheme().PopupInternalPaddingEnd(GetFrame(), StyleRef()));
inner_style.SetPaddingLeft(StyleRef().Direction() == TextDirection::kLtr
? padding_start
: padding_end);
@@ -163,7 +163,7 @@ void LayoutMenuList::AdjustInnerStyle(ComputedStyle& inner_style) const {
}
HTMLSelectElement* LayoutMenuList::SelectElement() const {
- return ToHTMLSelectElement(GetNode());
+ return To<HTMLSelectElement>(GetNode());
}
void LayoutMenuList::AddChild(LayoutObject* new_child,
@@ -253,7 +253,7 @@ void LayoutMenuList::UpdateFromElement() {
Locale& locale = select->GetLocale();
String localized_number_string =
locale.ConvertToLocalizedNumber(String::Number(selected_count));
- text = locale.QueryString(WebLocalizedString::kSelectMenuListText,
+ text = locale.QueryString(IDS_FORM_SELECT_MENU_LIST_TEXT,
localized_number_string);
DCHECK(!option_style_);
}
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 fa0e2eeef7a..dd583731f63 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
@@ -1343,7 +1343,6 @@ void LayoutMultiColumnFlowThread::ComputePreferredLogicalWidths() {
LayoutUnit gap_extra((column_count - 1) *
ColumnGap(*multicol_style, LayoutUnit()));
- DCHECK(!MultiColumnBlockFlow()->DisplayLockInducesSizeContainment());
if (MultiColumnBlockFlow()->ShouldApplySizeContainment()) {
min_preferred_logical_width_ = max_preferred_logical_width_ =
MultiColumnBlockFlow()->ContentLogicalWidthForSizeContainment();
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 e351e0691b0..924dd0ea1db 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
@@ -540,6 +540,9 @@ void LayoutMultiColumnSet::ComputeVisualOverflow(
}
void LayoutMultiColumnSet::AddVisualOverflowFromChildren() {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
// It's useless to calculate overflow if we haven't determined the page
// logical height yet.
if (!IsPageLogicalHeightKnown())
@@ -554,6 +557,9 @@ void LayoutMultiColumnSet::AddVisualOverflowFromChildren() {
}
void LayoutMultiColumnSet::AddLayoutOverflowFromChildren() {
+ if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
// It's useless to calculate overflow if we haven't determined the page
// logical height yet.
if (!IsPageLogicalHeightKnown())
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 13220f6d0e9..d08cd063337 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
@@ -131,7 +131,11 @@ void LayoutMultiColumnSpannerPlaceholder::UpdateLayout() {
// calculated and set before layout. Copy this to the actual column-span:all
// object before laying it out, so that it gets paginated correctly, in case
// we have an enclosing fragmentation context.
- layout_object_in_flow_thread_->SetLogicalTop(LogicalTop());
+ if (layout_object_in_flow_thread_->LogicalTop() != LogicalTop()) {
+ layout_object_in_flow_thread_->SetLogicalTop(LogicalTop());
+ if (FlowThread()->EnclosingFragmentationContext())
+ layout_object_in_flow_thread_->SetChildNeedsLayout(kMarkOnlyThis);
+ }
// Lay out the actual column-span:all element.
layout_object_in_flow_thread_->LayoutIfNeeded();
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 f25b4e614ae..206024852dc 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
@@ -63,6 +63,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_counter.h"
+#include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
@@ -75,7 +76,6 @@
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_table_col.h"
@@ -255,11 +255,8 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
return LayoutObjectFactory::CreateTableCaption(*element, style, legacy);
case EDisplay::kWebkitBox:
case EDisplay::kWebkitInlineBox:
- if (RuntimeEnabledFeatures::WebkitBoxLayoutUsesFlexLayoutEnabled() &&
- (!style.HasLineClamp() ||
- style.BoxOrient() == EBoxOrient::kHorizontal)) {
+ if (style.IsDeprecatedFlexboxUsingFlexLayout())
return new LayoutFlexibleBox(element);
- }
return new LayoutDeprecatedFlexibleBox(*element);
case EDisplay::kFlex:
case EDisplay::kInlineFlex:
@@ -886,7 +883,7 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
// Scrollbar parts can be removed during layout. Avoid the complexity of
// having to deal with that.
- if (object->IsLayoutScrollbarPart())
+ if (object->IsLayoutCustomScrollbarPart())
return false;
if (const LayoutBox* layout_box = ToLayoutBoxOrNull(object)) {
@@ -1229,8 +1226,11 @@ LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const {
object = SpannerPlaceholder()->ContainingBlock();
} else {
object = Parent();
- if (!object && IsLayoutScrollbarPart())
- object = ToLayoutScrollbarPart(this)->GetScrollableArea()->GetLayoutBox();
+ if (!object && IsLayoutCustomScrollbarPart()) {
+ object = ToLayoutCustomScrollbarPart(this)
+ ->GetScrollableArea()
+ ->GetLayoutBox();
+ }
while (object && ((object->IsInline() && !object->IsAtomicInlineLevel()) ||
!object->IsLayoutBlock())) {
if (skip_info)
@@ -1414,6 +1414,13 @@ const LayoutBoxModelObject* LayoutObject::EnclosingCompositedContainer() const {
bool LayoutObject::HasDistortingVisualEffects() const {
// TODO(szager): Check occlusion information propagated from out-of-process
// parent frame.
+
+ // TODO(szager): Remove CHECK's after diagnosing crash.
+ PaintLayer* enclosing_layer = EnclosingLayer();
+ CHECK(enclosing_layer);
+ CHECK(enclosing_layer->GetLayoutObject()
+ .FirstFragment()
+ .HasLocalBorderBoxProperties());
PropertyTreeState paint_properties = EnclosingLayer()
->GetLayoutObject()
.FirstFragment()
@@ -1430,12 +1437,15 @@ bool LayoutObject::HasDistortingVisualEffects() const {
}
}
- PropertyTreeState root_properties = GetDocument()
- .GetFrame()
- ->LocalFrameRoot()
- .ContentLayoutObject()
- ->FirstFragment()
- .LocalBorderBoxProperties();
+ // TODO(szager): Remove CHECK's after diagnosing crash.
+ CHECK(GetDocument().IsActive());
+ LocalFrame* frame = GetDocument().GetFrame();
+ CHECK(frame);
+ LayoutView* layout_view = frame->LocalFrameRoot().ContentLayoutObject();
+ CHECK(layout_view);
+ CHECK(layout_view->FirstFragment().HasLocalBorderBoxProperties());
+ PropertyTreeState root_properties =
+ layout_view->FirstFragment().LocalBorderBoxProperties();
// The only allowed transforms are 2D translation and proportional up-scaling.
const auto& translation_2d_or_matrix =
@@ -1927,7 +1937,7 @@ StyleDifference LayoutObject::AdjustStyleDifference(
return diff;
}
-void LayoutObject::SetPseudoStyle(
+void LayoutObject::SetPseudoElementStyle(
scoped_refptr<const ComputedStyle> pseudo_style) {
DCHECK(pseudo_style->StyleType() == kPseudoIdBefore ||
pseudo_style->StyleType() == kPseudoIdAfter ||
@@ -1970,11 +1980,15 @@ void LayoutObject::MarkContainerChainForOverflowRecalcIfNeeded() {
} while (object);
}
+void LayoutObject::SetNeedsVisualOverflowAndPaintInvalidation() {
+ SetShouldCheckForPaintInvalidation();
+ MarkSelfPaintingLayerForVisualOverflowRecalc();
+}
+
void LayoutObject::SetNeedsOverflowRecalc() {
bool needed_recalc = SelfNeedsLayoutOverflowRecalc();
SetSelfNeedsLayoutOverflowRecalc();
- SetShouldCheckForPaintInvalidation();
- MarkSelfPaintingLayerForVisualOverflowRecalc();
+ SetNeedsVisualOverflowAndPaintInvalidation();
if (!needed_recalc)
MarkContainerChainForOverflowRecalcIfNeeded();
@@ -1997,7 +2011,7 @@ void LayoutObject::SetStyle(scoped_refptr<const ComputedStyle> style,
if (style_) {
diff = style_->VisualInvalidationDiff(GetDocument(), *style);
if (const auto* cached_inherited_first_line_style =
- style_->GetCachedPseudoStyle(kPseudoIdFirstLineInherited)) {
+ style_->GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited)) {
// Merge the difference to the first line style because even if the new
// style is the same as the old style, the new style may have some higher
// priority properties overriding first line style.
@@ -2145,7 +2159,7 @@ void LayoutObject::UpdateImageObservers(const ComputedStyle* old_style,
void LayoutObject::UpdateFirstLineImageObservers(
const ComputedStyle* new_style) {
bool has_new_first_line_style =
- new_style && new_style->HasPseudoStyle(kPseudoIdFirstLine) &&
+ new_style && new_style->HasPseudoElementStyle(kPseudoIdFirstLine) &&
BehavesLikeBlockContainer();
DCHECK(!has_new_first_line_style || new_style == Style());
@@ -2392,7 +2406,7 @@ void LayoutObject::StyleDidChange(StyleDifference diff,
SetBackgroundNeedsFullPaintInvalidation();
}
- ApplyPseudoStyleChanges(old_style);
+ ApplyPseudoElementStyleChanges(old_style);
if (old_style &&
old_style->UsedTransformStyle3D() != StyleRef().UsedTransformStyle3D()) {
@@ -2402,18 +2416,20 @@ void LayoutObject::StyleDidChange(StyleDifference diff,
}
}
-void LayoutObject::ApplyPseudoStyleChanges(const ComputedStyle* old_style) {
+void LayoutObject::ApplyPseudoElementStyleChanges(
+ const ComputedStyle* old_style) {
ApplyFirstLineChanges(old_style);
- if ((old_style && old_style->HasPseudoStyle(kPseudoIdSelection)) ||
- StyleRef().HasPseudoStyle(kPseudoIdSelection))
+ if ((old_style && old_style->HasPseudoElementStyle(kPseudoIdSelection)) ||
+ StyleRef().HasPseudoElementStyle(kPseudoIdSelection))
InvalidateSelectedChildrenOnStyleChange();
}
void LayoutObject::ApplyFirstLineChanges(const ComputedStyle* old_style) {
bool has_old_first_line_style =
- old_style && old_style->HasPseudoStyle(kPseudoIdFirstLine);
- bool has_new_first_line_style = StyleRef().HasPseudoStyle(kPseudoIdFirstLine);
+ old_style && old_style->HasPseudoElementStyle(kPseudoIdFirstLine);
+ bool has_new_first_line_style =
+ StyleRef().HasPseudoElementStyle(kPseudoIdFirstLine);
if (!has_old_first_line_style && !has_new_first_line_style)
return;
@@ -2421,7 +2437,7 @@ void LayoutObject::ApplyFirstLineChanges(const ComputedStyle* old_style) {
bool has_diff = false;
if (Parent() && has_old_first_line_style && has_new_first_line_style) {
if (const auto* old_first_line_style =
- old_style->GetCachedPseudoStyle(kPseudoIdFirstLine)) {
+ old_style->GetCachedPseudoElementStyle(kPseudoIdFirstLine)) {
if (const auto* new_first_line_style = FirstLineStyleWithoutFallback()) {
diff = old_first_line_style->VisualInvalidationDiff(
GetDocument(), *new_first_line_style);
@@ -2500,7 +2516,7 @@ void LayoutObject::PropagateStyleToAnonymousChildren() {
continue;
}
if (child->IsText() || child->IsQuote() || child->IsImage())
- child->SetPseudoStyle(Style());
+ child->SetPseudoElementStyle(Style());
child = child->NextInPreOrder(this);
}
}
@@ -3162,12 +3178,8 @@ void LayoutObject::WillBeRemovedFromTree() {
FindReferencingScrollAnchors(this, kClear);
}
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(&GetDocument())) {
- if (LocalFrameView* frame_view = GetFrameView()) {
- frame_view->GetPaintTimingDetector().LayoutObjectWillBeDestroyed(*this);
- }
- }
+ if (LocalFrameView* frame_view = GetFrameView())
+ frame_view->GetPaintTimingDetector().LayoutObjectWillBeDestroyed(*this);
}
void LayoutObject::SetNeedsPaintPropertyUpdate() {
@@ -3390,39 +3402,44 @@ const ComputedStyle* LayoutObject::FirstLineStyleWithoutFallback() const {
if (BehavesLikeBlockContainer()) {
if (const ComputedStyle* cached =
- StyleRef().GetCachedPseudoStyle(kPseudoIdFirstLine))
+ StyleRef().GetCachedPseudoElementStyle(kPseudoIdFirstLine))
return cached;
if (const LayoutBlock* first_line_block =
To<LayoutBlock>(this)->EnclosingFirstLineStyleBlock()) {
- if (first_line_block->Style() == Style())
- return first_line_block->GetCachedPseudoStyle(kPseudoIdFirstLine);
-
- // We can't use first_line_block->GetCachedPseudoStyle() because it's
- // based on first_line_block's style. We need to get the uncached first
- // line style based on this object's style and cache the result in it.
- return StyleRef().AddCachedPseudoStyle(
- first_line_block->GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdFirstLine), Style()));
+ if (first_line_block->Style() == Style()) {
+ return first_line_block->GetCachedPseudoElementStyle(
+ kPseudoIdFirstLine);
+ }
+
+ // We can't use first_line_block->GetCachedPseudoElementStyle() because
+ // it's based on first_line_block's style. We need to get the uncached
+ // first line style based on this object's style and cache the result in
+ // it.
+ return StyleRef().AddCachedPseudoElementStyle(
+ first_line_block->GetUncachedPseudoElementStyle(
+ PseudoElementStyleRequest(kPseudoIdFirstLine), Style()));
}
} else if (!IsAnonymous() && IsLayoutInline() &&
!GetNode()->IsFirstLetterPseudoElement()) {
if (const ComputedStyle* cached =
- StyleRef().GetCachedPseudoStyle(kPseudoIdFirstLineInherited))
+ StyleRef().GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited))
return cached;
if (const ComputedStyle* parent_first_line_style =
Parent()->FirstLineStyleWithoutFallback()) {
// A first-line style is in effect. Get uncached first line style based on
// parent_first_line_style and cache the result in this object's style.
- return StyleRef().AddCachedPseudoStyle(GetUncachedPseudoStyle(
- kPseudoIdFirstLineInherited, parent_first_line_style));
+ return StyleRef().AddCachedPseudoElementStyle(
+ GetUncachedPseudoElementStyle(kPseudoIdFirstLineInherited,
+ parent_first_line_style));
}
}
return nullptr;
}
-const ComputedStyle* LayoutObject::GetCachedPseudoStyle(PseudoId pseudo) const {
+const ComputedStyle* LayoutObject::GetCachedPseudoElementStyle(
+ PseudoId pseudo) const {
DCHECK_NE(pseudo, kPseudoIdBefore);
DCHECK_NE(pseudo, kPseudoIdAfter);
if (!GetNode())
@@ -3432,11 +3449,12 @@ const ComputedStyle* LayoutObject::GetCachedPseudoStyle(PseudoId pseudo) const {
if (!element)
return nullptr;
- return element->CachedStyleForPseudoElement(PseudoStyleRequest(pseudo));
+ return element->CachedStyleForPseudoElement(
+ PseudoElementStyleRequest(pseudo));
}
-scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoStyle(
- const PseudoStyleRequest& request,
+scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoElementStyle(
+ const PseudoElementStyleRequest& request,
const ComputedStyle* parent_style) const {
DCHECK_NE(request.pseudo_id, kPseudoIdBefore);
DCHECK_NE(request.pseudo_id, kPseudoIdAfter);
@@ -3533,17 +3551,10 @@ void LayoutObject::ImageNotifyFinished(ImageResourceContent* image) {
if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
cache->ImageLoaded(this);
- if (RuntimeEnabledFeatures::ElementTimingEnabled(&GetDocument())) {
- LocalDOMWindow* window = GetDocument().domWindow();
- if (window) {
- ImageElementTiming::From(*window).NotifyImageFinished(*this, image);
- }
- }
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- if (LocalFrameView* frame_view = GetFrameView()) {
- frame_view->GetPaintTimingDetector().NotifyImageFinished(*this, image);
- }
- }
+ if (LocalDOMWindow* window = GetDocument().domWindow())
+ ImageElementTiming::From(*window).NotifyImageFinished(*this, image);
+ if (LocalFrameView* frame_view = GetFrameView())
+ frame_view->GetPaintTimingDetector().NotifyImageFinished(*this, image);
}
Element* LayoutObject::OffsetParent(const Element* base) const {
@@ -3596,17 +3607,10 @@ Element* LayoutObject::OffsetParent(const Element* base) const {
}
void LayoutObject::NotifyImageFullyRemoved(ImageResourceContent* image) {
- if (RuntimeEnabledFeatures::ElementTimingEnabled(&GetDocument())) {
- LocalDOMWindow* window = GetDocument().domWindow();
- if (window) {
- ImageElementTiming::From(*window).NotifyImageRemoved(this, image);
- }
- }
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- if (LocalFrameView* frame_view = GetFrameView()) {
- frame_view->GetPaintTimingDetector().NotifyImageRemoved(*this, image);
- }
- }
+ if (LocalDOMWindow* window = GetDocument().domWindow())
+ ImageElementTiming::From(*window).NotifyImageRemoved(this, image);
+ if (LocalFrameView* frame_view = GetFrameView())
+ frame_view->GetPaintTimingDetector().NotifyImageRemoved(*this, image);
}
PositionWithAffinity LayoutObject::CreatePositionWithAffinity(
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 7b4bfd3e452..11256b7671d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.h
@@ -86,7 +86,7 @@ class LocalFrameView;
class NGPaintFragment;
class NGPhysicalBoxFragment;
class PaintLayer;
-class PseudoStyleRequest;
+class PseudoElementStyleRequest;
struct PaintInfo;
struct PaintInvalidatorContext;
struct WebScrollIntoViewParams;
@@ -661,6 +661,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsLayoutNGListMarkerImage() const {
return IsOfType(kLayoutObjectNGListMarkerImage);
}
+ bool IsLayoutNGProgress() const { return IsOfType(kLayoutObjectNGProgress); }
bool IsLayoutNGText() const { return IsOfType(kLayoutObjectNGText); }
bool IsLayoutTableCol() const {
return IsOfType(kLayoutObjectLayoutTableCol);
@@ -688,8 +689,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsLayoutReplaced() const {
return IsOfType(kLayoutObjectLayoutReplaced);
}
- bool IsLayoutScrollbarPart() const {
- return IsOfType(kLayoutObjectLayoutScrollbarPart);
+ bool IsLayoutCustomScrollbarPart() const {
+ return IsOfType(kLayoutObjectLayoutCustomScrollbarPart);
}
bool IsLayoutView() const { return IsOfType(kLayoutObjectLayoutView); }
bool IsRuby() const { return IsOfType(kLayoutObjectRuby); }
@@ -1170,9 +1171,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// has no concept of changing state). The cached pseudo style always inherits
// from the originating element's style (because we can cache only one
// version), while the uncached pseudo style can inherit from any style.
- const ComputedStyle* GetCachedPseudoStyle(PseudoId) const;
- scoped_refptr<ComputedStyle> GetUncachedPseudoStyle(
- const PseudoStyleRequest&,
+ const ComputedStyle* GetCachedPseudoElementStyle(PseudoId) const;
+ scoped_refptr<ComputedStyle> GetUncachedPseudoElementStyle(
+ const PseudoElementStyleRequest&,
const ComputedStyle* parent_style = nullptr) const;
LayoutView* View() const { return GetDocument().GetLayoutView(); }
@@ -1519,7 +1520,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
ApplyStyleChanges = ApplyStyleChanges::kYes);
// Set the style of the object if it's generated content.
- void SetPseudoStyle(scoped_refptr<const ComputedStyle>);
+ void SetPseudoElementStyle(scoped_refptr<const ComputedStyle>);
// In some cases we modify the ComputedStyle after the style recalc, either
// for updating anonymous style or doing layout hacks for special elements
@@ -2174,6 +2175,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
IntRect FragmentsVisualRectBoundingBox() const;
void SetNeedsOverflowRecalc();
+ void SetNeedsVisualOverflowAndPaintInvalidation();
void InvalidateClipPathCache();
@@ -2316,7 +2318,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
protected:
friend class LayoutBoxModelObject;
- friend class LayoutScrollbar;
+ friend class CustomScrollbar;
friend class PaintInvalidator;
friend class PaintPropertyTreeBuilder;
friend class PrePaintTreeWalk;
@@ -2431,11 +2433,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return context && !context->ShouldLayout(target);
}
- bool DisplayLockInducesSizeContainment() const {
- auto* context = GetDisplayLockContext();
- return context && context->IsLocked();
- }
-
bool PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget target) const {
auto* context = GetDisplayLockContext();
return context && !context->ShouldPrePaint(target);
@@ -2469,7 +2466,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
DisplayLockContext* GetDisplayLockContext() const {
- if (!RuntimeEnabledFeatures::DisplayLockingEnabled())
+ if (!RuntimeEnabledFeatures::DisplayLockingEnabled(&GetDocument()))
return nullptr;
auto* element = DynamicTo<Element>(GetNode());
if (!element)
@@ -2502,6 +2499,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectNGListMarker,
kLayoutObjectNGInsideListMarker,
kLayoutObjectNGListMarkerImage,
+ kLayoutObjectNGProgress,
kLayoutObjectNGText,
kLayoutObjectProgress,
kLayoutObjectQuote,
@@ -2516,7 +2514,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectLayoutMultiColumnSpannerPlaceholder,
kLayoutObjectLayoutEmbeddedContent,
kLayoutObjectLayoutReplaced,
- kLayoutObjectLayoutScrollbarPart,
+ kLayoutObjectLayoutCustomScrollbarPart,
kLayoutObjectLayoutView,
kLayoutObjectRuby,
kLayoutObjectRubyBase,
@@ -2745,7 +2743,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
const ComputedStyle* new_style);
void UpdateFirstLineImageObservers(const ComputedStyle* new_style);
- void ApplyPseudoStyleChanges(const ComputedStyle* old_style);
+ void ApplyPseudoElementStyleChanges(const ComputedStyle* old_style);
void ApplyFirstLineChanges(const ComputedStyle* old_style);
IntRect AdjustVisualRectForInlineBox(const IntRect&) const;
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 9b6024f0f83..c23306ddf3a 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
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_caption.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
@@ -146,4 +147,10 @@ LayoutTextFragment* LayoutObjectFactory::CreateTextFragment(
return layout_text_fragment;
}
+LayoutProgress* LayoutObjectFactory::CreateProgress(Node* node,
+ const ComputedStyle& style,
+ LegacyLayout legacy) {
+ return CreateObject<LayoutProgress, LayoutNGProgress>(*node, style, legacy);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
index a9596a42359..3fbd47bab00 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
@@ -15,6 +15,7 @@ class ComputedStyle;
class LayoutBlock;
class LayoutBlockFlow;
enum class LegacyLayout;
+class LayoutProgress;
class LayoutTableCaption;
class LayoutTableCell;
class LayoutText;
@@ -55,6 +56,9 @@ class LayoutObjectFactory {
int start_offset,
int length,
LegacyLayout);
+ static LayoutProgress* CreateProgress(Node* node,
+ const ComputedStyle& style,
+ LegacyLayout legacy);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_object_test.cc
index 61a6ebab391..87b11ab9403 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
@@ -1064,4 +1064,36 @@ TEST_F(LayoutObjectTest, FirstLineBackgroundImageChangeStyleCrash) {
UpdateAllLifecyclePhasesForTest();
}
+TEST_F(LayoutObjectTest, NeedsLayoutOverflowRecalc) {
+ if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+ return;
+
+ SetBodyInnerHTML(R"HTML(
+ <div id='wrapper'>
+ <div id='target'>foo</div>
+ <div id='other'>bar</div>
+ </div>
+ )HTML");
+
+ auto* wrapper = GetLayoutObjectByElementId("wrapper");
+ auto* target = GetLayoutObjectByElementId("target");
+ auto* other = GetLayoutObjectByElementId("other");
+
+ DCHECK(wrapper);
+ DCHECK(target);
+ DCHECK(other);
+
+ EXPECT_FALSE(wrapper->NeedsLayoutOverflowRecalc());
+ EXPECT_FALSE(target->NeedsLayoutOverflowRecalc());
+ EXPECT_FALSE(other->NeedsLayoutOverflowRecalc());
+
+ auto* target_element = GetDocument().getElementById("target");
+ target_element->SetInnerHTMLFromString("baz");
+ UpdateAllLifecyclePhasesForTest();
+
+ EXPECT_FALSE(wrapper->NeedsLayoutOverflowRecalc());
+ EXPECT_FALSE(target->NeedsLayoutOverflowRecalc());
+ EXPECT_FALSE(other->NeedsLayoutOverflowRecalc());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_progress.cc b/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
index 76f2ef72fd6..6b285eb4987 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
@@ -27,14 +27,16 @@
namespace blink {
-LayoutProgress::LayoutProgress(HTMLProgressElement* element)
+LayoutProgress::LayoutProgress(Element* element)
: LayoutBlockFlow(element),
position_(HTMLProgressElement::kInvalidPosition),
animating_(false),
animation_timer_(
element->GetDocument().GetTaskRunner(TaskType::kInternalDefault),
this,
- &LayoutProgress::AnimationTimerFired) {}
+ &LayoutProgress::AnimationTimerFired) {
+ DCHECK(IsHTMLProgressElement(element));
+}
LayoutProgress::~LayoutProgress() = default;
@@ -105,7 +107,7 @@ void LayoutProgress::UpdateAnimationState() {
}
HTMLProgressElement* LayoutProgress::ProgressElement() const {
- return ToHTMLProgressElement(GetNode());
+ return To<HTMLProgressElement>(GetNode());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_progress.h b/chromium/third_party/blink/renderer/core/layout/layout_progress.h
index 7430461c998..0c24c53ac3e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_progress.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_progress.h
@@ -28,9 +28,9 @@ namespace blink {
class HTMLProgressElement;
-class CORE_EXPORT LayoutProgress final : public LayoutBlockFlow {
+class CORE_EXPORT LayoutProgress : public LayoutBlockFlow {
public:
- explicit LayoutProgress(HTMLProgressElement*);
+ explicit LayoutProgress(Element* element);
~LayoutProgress() override;
double GetPosition() const { return position_; }
@@ -45,15 +45,14 @@ class CORE_EXPORT LayoutProgress final : public LayoutBlockFlow {
protected:
void WillBeDestroyed() override;
+ bool IsOfType(LayoutObjectType type) const override {
+ return type == kLayoutObjectProgress || LayoutBlockFlow::IsOfType(type);
+ }
bool IsAnimating() const;
bool IsAnimationTimerActive() const;
private:
- bool IsOfType(LayoutObjectType type) const override {
- return type == kLayoutObjectProgress || LayoutBlockFlow::IsOfType(type);
- }
-
void AnimationTimerFired(TimerBase*);
void UpdateAnimationState();
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 ca219039e58..b774588b2ed 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/core/html/html_dimension.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
@@ -39,6 +40,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/replaced_painter.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -161,14 +163,8 @@ void LayoutReplaced::RecalcVisualOverflow() {
void LayoutReplaced::ComputeIntrinsicSizingInfoForReplacedContent(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
if (ShouldApplySizeContainment()) {
- intrinsic_sizing_info.size = FloatSize();
- return;
- }
- if (DisplayLockInducesSizeContainment()) {
- auto* context = GetDisplayLockContext();
intrinsic_sizing_info.size =
- FloatSize(context->GetLockedContentLogicalWidth(),
- context->GetLockedContentLogicalHeight());
+ FloatSize(ContentLogicalSizeForSizeContainment());
return;
}
@@ -665,15 +661,35 @@ PhysicalRect LayoutReplaced::PreSnappedRectForPersistentSizing(
void LayoutReplaced::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
- DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
+ DCHECK(!ShouldApplySizeContainment());
intrinsic_sizing_info.size = FloatSize(IntrinsicLogicalWidth().ToFloat(),
IntrinsicLogicalHeight().ToFloat());
// Figure out if we need to compute an intrinsic ratio.
- if (intrinsic_sizing_info.size.IsEmpty() || !LayoutObjectHasAspectRatio(this))
+ if (!LayoutObjectHasAspectRatio(this))
return;
- intrinsic_sizing_info.aspect_ratio = intrinsic_sizing_info.size;
+ if (!intrinsic_sizing_info.size.IsEmpty())
+ intrinsic_sizing_info.aspect_ratio = intrinsic_sizing_info.size;
+
+ auto* elem = DynamicTo<Element>(GetNode());
+ if (RuntimeEnabledFeatures::AspectRatioFromWidthAndHeightEnabled() && elem &&
+ IsHTMLImageElement(elem) &&
+ intrinsic_sizing_info.aspect_ratio.IsEmpty() &&
+ elem->FastHasAttribute(html_names::kWidthAttr) &&
+ elem->FastHasAttribute(html_names::kHeightAttr)) {
+ const AtomicString& width_str =
+ elem->FastGetAttribute(html_names::kWidthAttr);
+ const AtomicString& height_str =
+ elem->FastGetAttribute(html_names::kHeightAttr);
+ HTMLDimension width_dim, height_dim;
+ if (ParseDimensionValue(width_str, width_dim) &&
+ ParseDimensionValue(height_str, height_dim) && width_dim.IsAbsolute() &&
+ height_dim.IsAbsolute()) {
+ intrinsic_sizing_info.aspect_ratio.SetWidth(width_dim.Value());
+ intrinsic_sizing_info.aspect_ratio.SetHeight(height_dim.Value());
+ }
+ }
}
static inline LayoutUnit ResolveWidthForRatio(LayoutUnit height,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_replaced.h b/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
index e20d5433296..912479fa427 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
@@ -113,9 +113,8 @@ class CORE_EXPORT LayoutReplaced : public LayoutBox {
void UpdateLayout() override;
LayoutSize IntrinsicSize() const final {
- // TODO(vmpstr): To address the intrinsic size of replaced element for
- // display lock.
- return ShouldApplySizeContainment() ? LayoutSize() : intrinsic_size_;
+ return ShouldApplySizeContainment() ? ContentLogicalSizeForSizeContainment()
+ : intrinsic_size_;
}
void ComputePositionedLogicalWidth(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_shift_region.h b/chromium/third_party/blink/renderer/core/layout/layout_shift_region.h
index 78a774bb64c..461cddf6357 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_shift_region.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_shift_region.h
@@ -12,8 +12,7 @@
namespace blink {
-// Represents a per-frame layout shift region for LayoutShiftTracker. Only used
-// when the JankTrackingSweepLine feature is enabled.
+// Represents a per-frame layout shift region for LayoutShiftTracker.
//
// This class uses a sweep line algorithm to compute the area in O(n log n) time
// where n is the number of rects recorded by AddRect. For complex layout shift
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 1fec2d84304..d3c7eae459f 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
@@ -28,9 +28,6 @@ namespace blink {
static constexpr base::TimeDelta kTimerDelay =
base::TimeDelta::FromMilliseconds(500);
-static const float kRegionGranularitySteps = 60.0;
-// TODO: Vary by Finch experiment parameter.
-static const float kSweepLineRegionGranularity = 1.0;
static const float kMovementThreshold = 3.0; // CSS pixels.
static FloatPoint LogicalStart(const FloatRect& rect,
@@ -51,15 +48,6 @@ static float GetMoveDistance(const FloatRect& old_rect,
return std::max(fabs(location_delta.Width()), fabs(location_delta.Height()));
}
-float LayoutShiftTracker::RegionGranularityScale(
- const IntRect& viewport) const {
- if (RuntimeEnabledFeatures::JankTrackingSweepLineEnabled())
- return kSweepLineRegionGranularity;
-
- return kRegionGranularitySteps /
- std::min(viewport.Height(), viewport.Width());
-}
-
static bool EqualWithinMovementThreshold(const FloatPoint& a,
const FloatPoint& b,
const LayoutObject& object) {
@@ -69,10 +57,10 @@ static bool EqualWithinMovementThreshold(const FloatPoint& a,
fabs(a.Y() - b.Y()) < threshold_physical_px;
}
-static bool SmallerThanRegionGranularity(const FloatRect& rect,
- float granularity_scale) {
- return rect.Width() * granularity_scale < 0.5 ||
- rect.Height() * granularity_scale < 0.5;
+static bool SmallerThanRegionGranularity(const FloatRect& rect) {
+ // The region uses integer coordinates, so the rects are snapped to
+ // pixel boundaries. Ignore rects smaller than half a pixel.
+ return rect.Width() < 0.5 || rect.Height() < 0.5;
}
static const PropertyTreeState PropertyTreeStateFor(
@@ -80,30 +68,24 @@ static const PropertyTreeState PropertyTreeStateFor(
return object.FirstFragment().LocalBorderBoxProperties();
}
-static void RegionToTracedValue(const Region& region,
- double granularity_scale,
+static void RegionToTracedValue(const LayoutShiftRegion& region,
TracedValue& value) {
+ Region blink_region;
+ for (IntRect rect : region.GetRects())
+ blink_region.Unite(Region(rect));
+
value.BeginArray("region_rects");
- for (const IntRect& rect : region.Rects()) {
+ for (const IntRect& rect : blink_region.Rects()) {
value.BeginArray();
- value.PushInteger(clampTo<int>(roundf(rect.X() / granularity_scale)));
- value.PushInteger(clampTo<int>(roundf(rect.Y() / granularity_scale)));
- value.PushInteger(clampTo<int>(roundf(rect.Width() / granularity_scale)));
- value.PushInteger(clampTo<int>(roundf(rect.Height() / granularity_scale)));
+ value.PushInteger(rect.X());
+ value.PushInteger(rect.Y());
+ value.PushInteger(rect.Width());
+ value.PushInteger(rect.Height());
value.EndArray();
}
value.EndArray();
}
-static void RegionToTracedValue(const LayoutShiftRegion& region,
- double granularity_scale,
- TracedValue& value) {
- Region old_region;
- for (IntRect rect : region.GetRects())
- old_region.Unite(Region(rect));
- RegionToTracedValue(old_region, granularity_scale, value);
-}
-
#if DCHECK_IS_ON()
static bool ShouldLog(const LocalFrame& frame) {
const String& url = frame.GetDocument()->Url().GetString();
@@ -127,21 +109,19 @@ void LayoutShiftTracker::ObjectShifted(
const LayoutObject& source,
const PropertyTreeState& property_tree_state,
FloatRect old_rect,
- FloatRect new_rect) {
+ FloatRect new_rect,
+ FloatSize paint_offset_delta) {
if (old_rect.IsEmpty() || new_rect.IsEmpty())
return;
+ old_rect.Move(paint_offset_delta);
+
if (EqualWithinMovementThreshold(LogicalStart(old_rect, source),
LogicalStart(new_rect, source), source))
return;
- IntRect viewport =
- IntRect(IntPoint(),
- frame_view_->GetScrollableArea()->VisibleContentRect().Size());
- float scale = RegionGranularityScale(viewport);
-
- if (SmallerThanRegionGranularity(old_rect, scale) &&
- SmallerThanRegionGranularity(new_rect, scale))
+ if (SmallerThanRegionGranularity(old_rect) &&
+ SmallerThanRegionGranularity(new_rect))
return;
// Ignore layout objects that move (in the coordinate space of the paint
@@ -189,6 +169,10 @@ void LayoutShiftTracker::ObjectShifted(
clipped_new_rect.Intersect(clip_rect.Rect());
}
+ IntRect viewport =
+ IntRect(IntPoint(),
+ frame_view_->GetScrollableArea()->VisibleContentRect().Size());
+
IntRect visible_old_rect = RoundedIntRect(clipped_old_rect);
visible_old_rect.Intersect(viewport);
IntRect visible_new_rect = RoundedIntRect(clipped_new_rect);
@@ -214,43 +198,21 @@ void LayoutShiftTracker::ObjectShifted(
}
#endif
- visible_old_rect.Scale(scale);
- visible_new_rect.Scale(scale);
-
- if (RuntimeEnabledFeatures::JankTrackingSweepLineEnabled()) {
- region_experimental_.AddRect(visible_old_rect);
- region_experimental_.AddRect(visible_new_rect);
- } else {
- region_.Unite(Region(visible_old_rect));
- region_.Unite(Region(visible_new_rect));
- }
+ region_.AddRect(visible_old_rect);
+ region_.AddRect(visible_new_rect);
}
void LayoutShiftTracker::NotifyObjectPrePaint(
const LayoutObject& object,
const PropertyTreeState& property_tree_state,
const IntRect& old_visual_rect,
- const IntRect& new_visual_rect) {
+ const IntRect& new_visual_rect,
+ FloatSize paint_offset_delta) {
if (!IsActive())
return;
ObjectShifted(object, property_tree_state, FloatRect(old_visual_rect),
- FloatRect(new_visual_rect));
-}
-
-void LayoutShiftTracker::NotifyCompositedLayerMoved(
- const LayoutObject& layout_object,
- FloatRect old_layer_rect,
- FloatRect new_layer_rect) {
- if (!IsActive())
- return;
-
- // Make sure we can access a transform node.
- if (!layout_object.FirstFragment().HasLocalBorderBoxProperties())
- return;
-
- ObjectShifted(layout_object, PropertyTreeStateFor(layout_object),
- old_layer_rect, new_layer_rect);
+ FloatRect(new_visual_rect), paint_offset_delta);
}
double LayoutShiftTracker::SubframeWeightingFactor() const {
@@ -280,25 +242,15 @@ double LayoutShiftTracker::SubframeWeightingFactor() const {
void LayoutShiftTracker::NotifyPrePaintFinished() {
if (!IsActive())
return;
- bool use_sweep_line = RuntimeEnabledFeatures::JankTrackingSweepLineEnabled();
- bool region_is_empty =
- use_sweep_line ? region_experimental_.IsEmpty() : region_.IsEmpty();
- if (region_is_empty)
+ if (region_.IsEmpty())
return;
IntRect viewport = frame_view_->GetScrollableArea()->VisibleContentRect();
if (viewport.IsEmpty())
return;
- double granularity_scale = RegionGranularityScale(viewport);
- IntRect scaled_viewport = viewport;
- scaled_viewport.Scale(granularity_scale);
-
- double viewport_area =
- double(scaled_viewport.Width()) * double(scaled_viewport.Height());
- uint64_t region_area =
- use_sweep_line ? region_experimental_.Area() : region_.Area();
- double impact_fraction = region_area / viewport_area;
+ double viewport_area = double(viewport.Width()) * double(viewport.Height());
+ double impact_fraction = region_.Area() / viewport_area;
DCHECK_GT(impact_fraction, 0);
DCHECK_GT(frame_max_distance_, 0.0);
@@ -329,17 +281,10 @@ void LayoutShiftTracker::NotifyPrePaintFinished() {
ReportShift(score_delta, weighted_score_delta);
}
- if (use_sweep_line) {
- if (!region_experimental_.IsEmpty()) {
- SetLayoutShiftRects(region_experimental_.GetRects(), 1, true);
- }
- region_experimental_.Reset();
- } else {
- if (!region_.IsEmpty()) {
- SetLayoutShiftRects(region_.Rects(), granularity_scale, false);
- }
- region_ = Region();
- }
+ if (!region_.IsEmpty())
+ SetLayoutShiftRects(region_.GetRects());
+ region_.Reset();
+
frame_max_distance_ = 0.0;
frame_scroll_delta_ = ScrollOffset();
}
@@ -358,9 +303,7 @@ void LayoutShiftTracker::ReportShift(double score_delta,
}
}
- if (RuntimeEnabledFeatures::LayoutInstabilityAPIEnabled(
- frame.GetDocument()) &&
- frame.DomWindow()) {
+ if (frame.DomWindow()) {
WindowPerformance* performance =
DOMWindowPerformance::performance(*frame.DomWindow());
if (performance) {
@@ -466,36 +409,13 @@ std::unique_ptr<TracedValue> LayoutShiftTracker::PerFrameTraceData(
value->SetDouble("cumulative_score", score_);
value->SetDouble("overall_max_distance", overall_max_distance_);
value->SetDouble("frame_max_distance", frame_max_distance_);
-
- float granularity_scale = RegionGranularityScale(
- IntRect(IntPoint(),
- frame_view_->GetScrollableArea()->VisibleContentRect().Size()));
- if (RuntimeEnabledFeatures::JankTrackingSweepLineEnabled())
- RegionToTracedValue(region_experimental_, granularity_scale, *value);
- else
- RegionToTracedValue(region_, granularity_scale, *value);
-
+ RegionToTracedValue(region_, *value);
value->SetBoolean("is_main_frame", frame_view_->GetFrame().IsMainFrame());
value->SetBoolean("had_recent_input", input_detected);
return value;
}
-WebVector<gfx::Rect> LayoutShiftTracker::ConvertIntRectsToGfxRects(
- const Vector<IntRect>& int_rects,
- double granularity_scale) {
- WebVector<gfx::Rect> rects;
- for (const IntRect& rect : int_rects) {
- gfx::Rect r = gfx::Rect(
- rect.X() / granularity_scale, rect.Y() / granularity_scale,
- rect.Width() / granularity_scale, rect.Height() / granularity_scale);
- rects.emplace_back(r);
- }
- return rects;
-}
-
-void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects,
- double granularity_scale,
- bool using_sweep_line) {
+void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects) {
// Store the layout shift rects in the HUD layer.
GraphicsLayer* root_graphics_layer =
frame_view_->GetLayoutView()->Compositor()->RootGraphicsLayer();
@@ -510,15 +430,11 @@ void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects,
return;
if (cc_layer->layer_tree_host()->hud_layer()) {
WebVector<gfx::Rect> rects;
- if (using_sweep_line) {
- Region old_region;
- for (IntRect rect : int_rects)
- old_region.Unite(Region(rect));
- rects =
- ConvertIntRectsToGfxRects(old_region.Rects(), granularity_scale);
- } else {
- rects = ConvertIntRectsToGfxRects(int_rects, granularity_scale);
- }
+ Region blink_region;
+ for (IntRect rect : int_rects)
+ blink_region.Unite(Region(rect));
+ for (const IntRect& rect : blink_region.Rects())
+ rects.emplace_back(rect);
cc_layer->layer_tree_host()->hud_layer()->SetLayoutShiftRects(
rects.ReleaseVector());
cc_layer->layer_tree_host()->hud_layer()->SetNeedsPushProperties();
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 d095b646980..79185e29907 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
@@ -30,14 +30,22 @@ class CORE_EXPORT LayoutShiftTracker {
public:
LayoutShiftTracker(LocalFrameView*);
~LayoutShiftTracker() {}
+ // |paint_offset_diff| is an additional amount by which the paint offset
+ // shifted that is not tracked in visual rects. Visual rects are in the
+ // local transform space of the LayoutObject. Any time the transform space is
+ // changed, the offset of that rect to the "origin" is reset. This offset
+ // is also known as the paint offset.
+ // In cases where we can communicate paint offset diffs across transform
+ // space change boundaries, |paint_offset_diff| is how to do it. In
+ // particular, many transform spaces are artificial and are used as an
+ // implementation detail of compositing to make it easier to isolate state for
+ // composited layers. We can easily pass the paint offset diff across such
+ // boundaries.
void NotifyObjectPrePaint(const LayoutObject& object,
const PropertyTreeState& property_tree_state,
const IntRect& old_visual_rect,
- const IntRect& new_visual_rect);
- // Layer rects are relative to old layer position.
- void NotifyCompositedLayerMoved(const LayoutObject& object,
- FloatRect old_layer_rect,
- FloatRect new_layer_rect);
+ const IntRect& new_visual_rect,
+ FloatSize paint_offset_delta);
void NotifyPrePaintFinished();
void NotifyInput(const WebInputEvent&);
void NotifyScroll(ScrollType, ScrollOffset delta);
@@ -56,19 +64,14 @@ class CORE_EXPORT LayoutShiftTracker {
void ObjectShifted(const LayoutObject&,
const PropertyTreeState&,
FloatRect old_rect,
- FloatRect new_rect);
+ FloatRect new_rect,
+ FloatSize paint_offset_diff);
void ReportShift(double score_delta, double weighted_score_delta);
void TimerFired(TimerBase*) {}
std::unique_ptr<TracedValue> PerFrameTraceData(double score_delta,
bool input_detected) const;
- float RegionGranularityScale(const IntRect& viewport) const;
double SubframeWeightingFactor() const;
- WebVector<gfx::Rect> ConvertIntRectsToGfxRects(
- const Vector<IntRect>& int_rects,
- double granularity_scale);
- void SetLayoutShiftRects(const Vector<IntRect>& int_rects,
- double granularity_scale,
- bool using_sweep_line);
+ void SetLayoutShiftRects(const Vector<IntRect>& int_rects);
void UpdateInputTimestamp(base::TimeTicks timestamp);
// This owns us.
@@ -101,10 +104,7 @@ class CORE_EXPORT LayoutShiftTracker {
PointerdownPendingData pointerdown_pending_data_;
// The per-animation-frame impact region.
- Region region_;
-
- // Experimental impact region implementation using sweep-line algorithm.
- LayoutShiftRegion region_experimental_;
+ LayoutShiftRegion region_;
// Tracks the short period after an input event during which we ignore shifts
// for the purpose of cumulative scoring, and report them to the web perf API
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 29d33016427..ec88c25b279 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
@@ -60,23 +60,6 @@ TEST_F(LayoutShiftTrackerTest, SimpleBlockMovement) {
EXPECT_FLOAT_EQ(60.0, GetLayoutShiftTracker().OverallMaxDistance());
}
-TEST_F(LayoutShiftTrackerTest, GranularitySnapping) {
- if (RuntimeEnabledFeatures::JankTrackingSweepLineEnabled())
- return;
-
- SetBodyInnerHTML(R"HTML(
- <style>
- #j { position: relative; width: 304px; height: 104px; }
- </style>
- <div id='j'></div>
- )HTML");
- GetDocument().getElementById("j")->setAttribute(html_names::kStyleAttr,
- AtomicString("top: 58px"));
- UpdateAllLifecyclePhases();
- // Rect locations and sizes should snap to multiples of 600 / 60 = 10.
- EXPECT_FLOAT_EQ(0.1, GetLayoutShiftTracker().Score());
-}
-
TEST_F(LayoutShiftTrackerTest, Transform) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -109,33 +92,6 @@ TEST_F(LayoutShiftTrackerTest, RtlDistance) {
EXPECT_FLOAT_EQ(20.0, GetLayoutShiftTracker().OverallMaxDistance());
}
-TEST_F(LayoutShiftTrackerTest, SmallMovementIgnored) {
- SetBodyInnerHTML(R"HTML(
- <style>
- #j { position: relative; width: 300px; height: 100px; }
- </style>
- <div id='j'></div>
- )HTML");
- GetDocument().getElementById("j")->setAttribute(html_names::kStyleAttr,
- AtomicString("top: 2px"));
- UpdateAllLifecyclePhases();
- EXPECT_EQ(0.0, GetLayoutShiftTracker().Score());
-}
-
-TEST_F(LayoutShiftTrackerTest, SmallMovementIgnoredWithZoom) {
- GetDocument().GetFrame()->SetPageZoomFactor(2);
- SetBodyInnerHTML(R"HTML(
- <style>
- #j { position: relative; width: 300px; height: 100px; }
- </style>
- <div id='j'></div>
- )HTML");
- GetDocument().getElementById("j")->setAttribute(html_names::kStyleAttr,
- AtomicString("top: 2px"));
- UpdateAllLifecyclePhases();
- EXPECT_EQ(0.0, GetLayoutShiftTracker().Score());
-}
-
TEST_F(LayoutShiftTrackerTest, IgnoreAfterInput) {
SetBodyInnerHTML(R"HTML(
<style>
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
index 7677b4220f4..ce97dd7d32c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -1061,6 +1061,8 @@ void LayoutTableCell::UpdateCollapsedBorderValues() const {
}
} else {
Table()->InvalidateCollapsedBordersForAllCellsIfNeeded();
+ if (Section())
+ Section()->RecalcCellsIfNeeded();
if (collapsed_border_values_valid_)
return;
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 d02e1a8e137..58a04d4d8bf 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.cc
@@ -54,7 +54,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.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_fragment_traversal.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_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
@@ -297,6 +297,9 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
for (const NGPaintFragment* fragment : fragments) {
const auto& text_fragment =
To<NGPhysicalTextFragment>(fragment->PhysicalFragment());
+ // TODO(yosin): We should introduce
+ // |NGPhysicalTextFragment::IsTruncated()| to skip them instead of using
+ // |IsHiddenForPaint()| with ordering of fragments.
if (text_fragment.IsHiddenForPaint()) {
in_hidden_for_paint = true;
} else if (in_hidden_for_paint) {
@@ -304,6 +307,10 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
// ignore truncated fragments (actually painted).
break;
}
+ // We don't put generated texts, e.g. ellipsis, hyphen, etc. not in text
+ // content, into results. Note: CSS "content" aren't categorized this.
+ if (text_fragment.TextType() == NGPhysicalTextFragment::kGeneratedText)
+ continue;
// When the corresponding DOM range contains collapsed whitespaces, NG
// produces one fragment but legacy produces multiple text boxes broken at
// collapsed whitespaces. We break the fragment at collapsed whitespaces
@@ -311,6 +318,7 @@ Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const {
for (const NGOffsetMappingUnit& unit :
mapping->GetMappingUnitsForTextContentOffsetRange(
text_fragment.StartOffset(), text_fragment.EndOffset())) {
+ DCHECK_EQ(unit.GetLayoutObject(), this);
if (unit.GetType() == NGOffsetMappingUnitType::kCollapsed)
continue;
// [clamped_start, clamped_end] of |fragment| matches a legacy text box.
@@ -441,17 +449,16 @@ static IntRect EllipsisRectForBox(InlineTextBox* box,
template <typename PhysicalRectCollector>
void LayoutText::CollectLineBoxRects(const PhysicalRectCollector& yield,
ClippingOption option) const {
- if (const NGPhysicalBoxFragment* box_fragment =
- ContainingBlockFlowFragment()) {
- const auto children =
- NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
- for (const auto& child : children) {
+ if (IsInLayoutNGInlineFormattingContext()) {
+ NGInlineCursor cursor;
+ cursor.MoveTo(*this);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
if (UNLIKELY(option != ClippingOption::kNoClipping)) {
DCHECK_EQ(option, ClippingOption::kClipToEllipsis);
- if (child.fragment->IsHiddenForPaint())
+ if (cursor.IsHiddenForPaint())
continue;
}
- yield(child.RectInContainerBox());
+ yield(cursor.CurrentRect());
}
return;
}
@@ -2076,18 +2083,19 @@ PhysicalRect LayoutText::LocalSelectionVisualRect() const {
return PhysicalRect();
const FrameSelection& frame_selection = GetFrame()->Selection();
- const auto fragments = NGPaintFragment::InlineFragmentsFor(this);
- if (fragments.IsInLayoutNGInlineFormattingContext()) {
+ if (IsInLayoutNGInlineFormattingContext()) {
PhysicalRect rect;
- for (const NGPaintFragment* fragment : fragments) {
+ NGInlineCursor cursor(*RootInlineFormattingContext());
+ for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) {
+ if (cursor.IsHiddenForPaint())
+ continue;
const LayoutSelectionStatus status =
- frame_selection.ComputeLayoutSelectionStatus(*fragment);
+ frame_selection.ComputeLayoutSelectionStatus(cursor);
if (status.start == status.end)
continue;
- PhysicalRect fragment_rect =
- fragment->ComputeLocalSelectionRectForText(status);
- fragment_rect.offset += fragment->InlineOffsetToContainerBox();
- rect.Unite(fragment_rect);
+ PhysicalRect item_rect = ComputeLocalSelectionRectForText(cursor, status);
+ item_rect.offset += cursor.CurrentOffset();
+ rect.Unite(item_rect);
}
return rect;
}
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 fd3a10666ff..6cabfb11d17 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
@@ -63,8 +63,8 @@ void LayoutTextControl::StyleDidChange(StyleDifference diff,
// (see: GetUncachedSelectionStyle in SelectionPaintingUtils.cpp) so ensure
// the inner editor selection is invalidated anytime style changes and a
// ::selection style is or was present on LayoutTextControl.
- if (StyleRef().HasPseudoStyle(kPseudoIdSelection) ||
- (old_style && old_style->HasPseudoStyle(kPseudoIdSelection))) {
+ if (StyleRef().HasPseudoElementStyle(kPseudoIdSelection) ||
+ (old_style && old_style->HasPseudoElementStyle(kPseudoIdSelection))) {
inner_editor_layout_object->InvalidateSelectedChildrenOnStyleChange();
}
}
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 14c81719614..ac8fb58a804 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
@@ -492,6 +492,37 @@ TEST_P(ParameterizedLayoutTextTest, GetTextBoxInfoWithEllipsis) {
EXPECT_EQ(LayoutRect(60, 0, 50, 10), boxes[1].local_rect);
}
+// For http://crbug.com/1003413
+TEST_P(ParameterizedLayoutTextTest, GetTextBoxInfoWithEllipsisForPseudoAfter) {
+ LoadAhem();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #sample {
+ box-sizing: border-box;
+ font: 10px/1 Ahem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 5ch;
+ }
+ b::after { content: ","; }
+ </style>
+ <div id=sample><b id=target>abc</b><b>xyz</b></div>
+ )HTML");
+ const Element& target = *GetElementById("target");
+ const Element& after = *target.GetPseudoElement(kPseudoIdAfter);
+ // Set |layout_text| to "," in <pseudo::after>,</pseudo::after>
+ const LayoutText& layout_text =
+ *ToLayoutText(after.GetLayoutObject()->SlowFirstChild());
+
+ auto boxes = layout_text.GetTextBoxInfo();
+ EXPECT_EQ(1u, boxes.size());
+
+ EXPECT_EQ(0u, boxes[0].dom_start_offset);
+ EXPECT_EQ(1u, boxes[0].dom_length);
+ EXPECT_EQ(LayoutRect(30, 0, 10, 10), boxes[0].local_rect);
+}
+
TEST_P(ParameterizedLayoutTextTest,
IsBeforeAfterNonCollapsedCharacterNoLineWrap) {
// Basic tests
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 077ad2b5fe3..a453aa74184 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -24,6 +24,7 @@
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_rect.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -140,12 +141,6 @@ ControlPart AutoAppearanceFor(const Element& element) {
} // namespace
-// Wrapper function defined in WebKit.h
-void SetMockThemeEnabledForTest(bool value) {
- WebTestSupport::SetMockThemeEnabledForTest(value);
- LayoutTheme::GetTheme().DidChangeThemeEngine();
-}
-
LayoutTheme& LayoutTheme::GetTheme() {
if (RuntimeEnabledFeatures::MobileLayoutThemeEnabled()) {
DEFINE_STATIC_REF(LayoutTheme, layout_theme_mobile,
@@ -312,36 +307,45 @@ String LayoutTheme::ExtraFullscreenStyleSheet() {
return String();
}
-Color LayoutTheme::ActiveSelectionBackgroundColor() const {
- return PlatformActiveSelectionBackgroundColor().BlendWithWhite();
+Color LayoutTheme::ActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveSelectionBackgroundColor(color_scheme).BlendWithWhite();
}
-Color LayoutTheme::InactiveSelectionBackgroundColor() const {
- return PlatformInactiveSelectionBackgroundColor().BlendWithWhite();
+Color LayoutTheme::InactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveSelectionBackgroundColor(color_scheme)
+ .BlendWithWhite();
}
-Color LayoutTheme::ActiveSelectionForegroundColor() const {
- return PlatformActiveSelectionForegroundColor();
+Color LayoutTheme::ActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveSelectionForegroundColor(color_scheme);
}
-Color LayoutTheme::InactiveSelectionForegroundColor() const {
- return PlatformInactiveSelectionForegroundColor();
+Color LayoutTheme::InactiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveSelectionForegroundColor(color_scheme);
}
-Color LayoutTheme::ActiveListBoxSelectionBackgroundColor() const {
- return PlatformActiveListBoxSelectionBackgroundColor();
+Color LayoutTheme::ActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveListBoxSelectionBackgroundColor(color_scheme);
}
-Color LayoutTheme::InactiveListBoxSelectionBackgroundColor() const {
- return PlatformInactiveListBoxSelectionBackgroundColor();
+Color LayoutTheme::InactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveListBoxSelectionBackgroundColor(color_scheme);
}
-Color LayoutTheme::ActiveListBoxSelectionForegroundColor() const {
- return PlatformActiveListBoxSelectionForegroundColor();
+Color LayoutTheme::ActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveListBoxSelectionForegroundColor(color_scheme);
}
-Color LayoutTheme::InactiveListBoxSelectionForegroundColor() const {
- return PlatformInactiveListBoxSelectionForegroundColor();
+Color LayoutTheme::InactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveListBoxSelectionForegroundColor(color_scheme);
}
Color LayoutTheme::PlatformSpellingMarkerUnderlineColor() const {
@@ -356,41 +360,49 @@ Color LayoutTheme::PlatformActiveSpellingMarkerHighlightColor() const {
return Color(255, 0, 0, 102);
}
-Color LayoutTheme::PlatformActiveSelectionBackgroundColor() const {
+Color LayoutTheme::PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
// Use a blue color by default if the platform theme doesn't define anything.
return Color(0, 0, 255);
}
-Color LayoutTheme::PlatformActiveSelectionForegroundColor() const {
+Color LayoutTheme::PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
// Use a white color by default if the platform theme doesn't define anything.
return Color::kWhite;
}
-Color LayoutTheme::PlatformInactiveSelectionBackgroundColor() const {
+Color LayoutTheme::PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
// Use a grey color by default if the platform theme doesn't define anything.
// This color matches Firefox's inactive color.
return Color(176, 176, 176);
}
-Color LayoutTheme::PlatformInactiveSelectionForegroundColor() const {
+Color LayoutTheme::PlatformInactiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
// Use a black color by default.
return Color::kBlack;
}
-Color LayoutTheme::PlatformActiveListBoxSelectionBackgroundColor() const {
- return PlatformActiveSelectionBackgroundColor();
+Color LayoutTheme::PlatformActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveSelectionBackgroundColor(color_scheme);
}
-Color LayoutTheme::PlatformActiveListBoxSelectionForegroundColor() const {
- return PlatformActiveSelectionForegroundColor();
+Color LayoutTheme::PlatformActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformActiveSelectionForegroundColor(color_scheme);
}
-Color LayoutTheme::PlatformInactiveListBoxSelectionBackgroundColor() const {
- return PlatformInactiveSelectionBackgroundColor();
+Color LayoutTheme::PlatformInactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveSelectionBackgroundColor(color_scheme);
}
-Color LayoutTheme::PlatformInactiveListBoxSelectionForegroundColor() const {
- return PlatformInactiveSelectionForegroundColor();
+Color LayoutTheme::PlatformInactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveSelectionForegroundColor(color_scheme);
}
LayoutUnit LayoutTheme::BaselinePositionAdjustment(
@@ -720,25 +732,25 @@ Color LayoutTheme::SystemColor(CSSValueID css_value_id,
case CSSValueID::kActivecaption:
return 0xFFCCCCCC;
case CSSValueID::kAppworkspace:
- return 0xFFFFFFFF;
+ return color_scheme == WebColorScheme::kDark ? 0xFF000000 : 0xFFFFFFFF;
case CSSValueID::kBackground:
return 0xFF6363CE;
case CSSValueID::kButtonface:
- return 0xFFC0C0C0;
+ return color_scheme == WebColorScheme::kDark ? 0xFF404040 : 0xFFC0C0C0;
case CSSValueID::kButtonhighlight:
return 0xFFDDDDDD;
case CSSValueID::kButtonshadow:
return 0xFF888888;
case CSSValueID::kButtontext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kCaptiontext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kGraytext:
return 0xFF808080;
case CSSValueID::kHighlight:
return 0xFFB5D5FF;
case CSSValueID::kHighlighttext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kInactiveborder:
return 0xFFFFFFFF;
case CSSValueID::kInactivecaption:
@@ -746,19 +758,19 @@ Color LayoutTheme::SystemColor(CSSValueID css_value_id,
case CSSValueID::kInactivecaptiontext:
return 0xFF7F7F7F;
case CSSValueID::kInfobackground:
- return 0xFFFBFCC5;
+ return color_scheme == WebColorScheme::kDark ? 0xFFB46E32 : 0xFFFBFCC5;
case CSSValueID::kInfotext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kLinktext:
return 0xFF0000EE;
case CSSValueID::kMenu:
- return 0xFFC0C0C0;
+ return color_scheme == WebColorScheme::kDark ? 0xFF404040 : 0xFFC0C0C0;
case CSSValueID::kMenutext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kScrollbar:
return 0xFFFFFFFF;
case CSSValueID::kText:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kThreeddarkshadow:
return 0xFF666666;
case CSSValueID::kThreedface:
@@ -772,19 +784,19 @@ Color LayoutTheme::SystemColor(CSSValueID css_value_id,
case CSSValueID::kVisitedtext:
return 0xFF551A8B;
case CSSValueID::kWindow:
- return 0xFFFFFFFF;
+ return color_scheme == WebColorScheme::kDark ? 0xFF000000 : 0xFFFFFFFF;
case CSSValueID::kWindowframe:
return 0xFFCCCCCC;
case CSSValueID::kWindowtext:
- return 0xFF000000;
+ return color_scheme == WebColorScheme::kDark ? 0xFFFFFFFF : 0xFF000000;
case CSSValueID::kInternalActiveListBoxSelection:
- return ActiveListBoxSelectionBackgroundColor();
+ return ActiveListBoxSelectionBackgroundColor(color_scheme);
case CSSValueID::kInternalActiveListBoxSelectionText:
- return ActiveListBoxSelectionForegroundColor();
+ return ActiveListBoxSelectionForegroundColor(color_scheme);
case CSSValueID::kInternalInactiveListBoxSelection:
- return InactiveListBoxSelectionBackgroundColor();
+ return InactiveListBoxSelectionBackgroundColor(color_scheme);
case CSSValueID::kInternalInactiveListBoxSelectionText:
- return InactiveListBoxSelectionForegroundColor();
+ return InactiveListBoxSelectionForegroundColor(color_scheme);
default:
break;
}
@@ -839,13 +851,12 @@ String LayoutTheme::FileListNameForWidth(Locale& locale,
String string;
if (file_list->IsEmpty()) {
- string =
- locale.QueryString(WebLocalizedString::kFileButtonNoFileSelectedLabel);
+ string = locale.QueryString(IDS_FORM_FILE_NO_FILE_LABEL);
} else if (file_list->length() == 1) {
string = file_list->item(0)->name();
} else {
return StringTruncator::RightTruncate(
- locale.QueryString(WebLocalizedString::kMultipleFileUploadText,
+ locale.QueryString(IDS_FORM_FILE_MULTIPLE_UPLOAD,
locale.ConvertToLocalizedNumber(
String::Number(file_list->length()))),
width, font);
@@ -860,6 +871,10 @@ bool LayoutTheme::ShouldOpenPickerWithF4Key() const {
bool LayoutTheme::SupportsCalendarPicker(const AtomicString& type) const {
DCHECK(RuntimeEnabledFeatures::InputMultipleFieldsUIEnabled());
+ if (RuntimeEnabledFeatures::FormControlsRefreshEnabled() &&
+ type == input_type_names::kTime)
+ return true;
+
return type == input_type_names::kDate ||
type == input_type_names::kDatetime ||
type == input_type_names::kDatetimeLocal ||
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 8b9172ddae5..a62bbd3db2f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.h
@@ -48,8 +48,8 @@ class FontDescription;
class HTMLInputElement;
class LengthSize;
class Locale;
+class LocalFrame;
class Node;
-class ChromeClient;
class ThemePainter;
class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
@@ -137,20 +137,24 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
virtual bool SupportsCalendarPicker(const AtomicString&) const;
// Text selection colors.
- Color ActiveSelectionBackgroundColor() const;
- Color InactiveSelectionBackgroundColor() const;
- Color ActiveSelectionForegroundColor() const;
- Color InactiveSelectionForegroundColor() const;
+ Color ActiveSelectionBackgroundColor(WebColorScheme color_scheme) const;
+ Color InactiveSelectionBackgroundColor(WebColorScheme color_scheme) const;
+ Color ActiveSelectionForegroundColor(WebColorScheme color_scheme) const;
+ Color InactiveSelectionForegroundColor(WebColorScheme color_scheme) const;
virtual void SetSelectionColors(Color active_background_color,
Color active_foreground_color,
Color inactive_background_color,
Color inactive_foreground_color) {}
// List box selection colors
- Color ActiveListBoxSelectionBackgroundColor() const;
- Color ActiveListBoxSelectionForegroundColor() const;
- Color InactiveListBoxSelectionBackgroundColor() const;
- Color InactiveListBoxSelectionForegroundColor() const;
+ Color ActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ Color ActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+ Color InactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ Color InactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
virtual Color PlatformSpellingMarkerUnderlineColor() const;
virtual Color PlatformGrammarMarkerUnderlineColor() const;
@@ -209,8 +213,7 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
virtual int PopupInternalPaddingStart(const ComputedStyle&) const {
return 0;
}
- virtual int PopupInternalPaddingEnd(const ChromeClient*,
- const ComputedStyle&) const {
+ virtual int PopupInternalPaddingEnd(LocalFrame*, const ComputedStyle&) const {
return 0;
}
virtual int PopupInternalPaddingTop(const ComputedStyle&) const { return 0; }
@@ -305,15 +308,23 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
protected:
// The platform selection color.
- virtual Color PlatformActiveSelectionBackgroundColor() const;
- virtual Color PlatformInactiveSelectionBackgroundColor() const;
- virtual Color PlatformActiveSelectionForegroundColor() const;
- virtual Color PlatformInactiveSelectionForegroundColor() const;
-
- virtual Color PlatformActiveListBoxSelectionBackgroundColor() const;
- virtual Color PlatformInactiveListBoxSelectionBackgroundColor() const;
- virtual Color PlatformActiveListBoxSelectionForegroundColor() const;
- virtual Color PlatformInactiveListBoxSelectionForegroundColor() const;
+ virtual Color PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformInactiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+
+ virtual Color PlatformActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformInactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color PlatformInactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
virtual bool ThemeDrawsFocusRing(const ComputedStyle&) const = 0;
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 317e71dbf4b..8f227a576b7 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc
@@ -28,8 +28,10 @@
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/public/resources/grit/blink_resources.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/data_resource_helper.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
@@ -70,7 +72,9 @@ bool LayoutThemeDefault::ThemeDrawsFocusRing(const ComputedStyle& style) const {
Color LayoutThemeDefault::SystemColor(CSSValueID css_value_id,
WebColorScheme color_scheme) const {
constexpr Color kDefaultButtonGrayColor(0xffdddddd);
+ constexpr Color kDefaultButtonGrayColorDark(0xff444444);
constexpr Color kDefaultMenuColor(0xfff7f7f7);
+ constexpr Color kDefaultMenuColorDark(0xff404040);
if (css_value_id == CSSValueID::kButtonface) {
if (UseMockTheme()) {
@@ -79,10 +83,21 @@ Color LayoutThemeDefault::SystemColor(CSSValueID css_value_id,
else
return Color(0x80, 0x80, 0x80);
}
- return kDefaultButtonGrayColor;
+ switch (color_scheme) {
+ case WebColorScheme::kLight:
+ return kDefaultButtonGrayColor;
+ case WebColorScheme::kDark:
+ return kDefaultButtonGrayColorDark;
+ }
+ }
+ if (css_value_id == CSSValueID::kMenu) {
+ switch (color_scheme) {
+ case WebColorScheme::kLight:
+ return kDefaultMenuColor;
+ case WebColorScheme::kDark:
+ return kDefaultMenuColorDark;
+ }
}
- if (css_value_id == CSSValueID::kMenu)
- return kDefaultMenuColor;
return LayoutTheme::SystemColor(css_value_id, color_scheme);
}
@@ -116,41 +131,49 @@ String LayoutThemeDefault::ExtraQuirksStyleSheet() {
return UncompressResourceAsASCIIString(IDR_UASTYLE_THEME_WIN_QUIRKS_CSS);
}
-Color LayoutThemeDefault::ActiveListBoxSelectionBackgroundColor() const {
+Color LayoutThemeDefault::ActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
return Color(0x28, 0x28, 0x28);
}
-Color LayoutThemeDefault::ActiveListBoxSelectionForegroundColor() const {
- return Color::kBlack;
+Color LayoutThemeDefault::ActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
+ return color_scheme == WebColorScheme::kDark ? Color::kWhite : Color::kBlack;
}
-Color LayoutThemeDefault::InactiveListBoxSelectionBackgroundColor() const {
+Color LayoutThemeDefault::InactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
return Color(0xc8, 0xc8, 0xc8);
}
-Color LayoutThemeDefault::InactiveListBoxSelectionForegroundColor() const {
+Color LayoutThemeDefault::InactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
return Color(0x32, 0x32, 0x32);
}
-Color LayoutThemeDefault::PlatformActiveSelectionBackgroundColor() const {
+Color LayoutThemeDefault::PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
if (UseMockTheme())
return Color(0x00, 0x00, 0xff); // Royal blue.
return active_selection_background_color_;
}
-Color LayoutThemeDefault::PlatformInactiveSelectionBackgroundColor() const {
+Color LayoutThemeDefault::PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
if (UseMockTheme())
return Color(0x99, 0x99, 0x99); // Medium gray.
return inactive_selection_background_color_;
}
-Color LayoutThemeDefault::PlatformActiveSelectionForegroundColor() const {
+Color LayoutThemeDefault::PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
if (UseMockTheme())
return Color(0xff, 0xff, 0xcc); // Pale yellow.
return active_selection_foreground_color_;
}
-Color LayoutThemeDefault::PlatformInactiveSelectionForegroundColor() const {
+Color LayoutThemeDefault::PlatformInactiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
if (UseMockTheme())
return Color::kWhite;
return inactive_selection_foreground_color_;
@@ -159,13 +182,19 @@ Color LayoutThemeDefault::PlatformInactiveSelectionForegroundColor() const {
IntSize LayoutThemeDefault::SliderTickSize() const {
if (UseMockTheme())
return IntSize(1, 3);
- return IntSize(1, 6);
+ if (RuntimeEnabledFeatures::FormControlsRefreshEnabled())
+ return IntSize(1, 4);
+ else
+ return IntSize(1, 6);
}
int LayoutThemeDefault::SliderTickOffsetFromTrackCenter() const {
if (UseMockTheme())
return 11;
- return -16;
+ if (RuntimeEnabledFeatures::FormControlsRefreshEnabled())
+ return 7;
+ else
+ return -16;
}
void LayoutThemeDefault::AdjustSliderThumbSize(ComputedStyle& style) const {
@@ -327,12 +356,12 @@ int LayoutThemeDefault::PopupInternalPaddingStart(
}
int LayoutThemeDefault::PopupInternalPaddingEnd(
- const ChromeClient* client,
+ LocalFrame* frame,
const ComputedStyle& style) const {
if (!style.HasEffectiveAppearance())
return 0;
return 1 * style.EffectiveZoom() +
- ClampedMenuListArrowPaddingSize(client, style);
+ ClampedMenuListArrowPaddingSize(frame, style);
}
int LayoutThemeDefault::PopupInternalPaddingTop(
@@ -354,15 +383,15 @@ int LayoutThemeDefault::MenuListArrowWidthInDIP() const {
}
float LayoutThemeDefault::ClampedMenuListArrowPaddingSize(
- const ChromeClient* client,
+ LocalFrame* frame,
const ComputedStyle& style) const {
if (cached_menu_list_arrow_padding_size_ > 0 &&
style.EffectiveZoom() == cached_menu_list_arrow_zoom_level_)
return cached_menu_list_arrow_padding_size_;
cached_menu_list_arrow_zoom_level_ = style.EffectiveZoom();
int original_size = MenuListArrowWidthInDIP();
- int scaled_size =
- client ? client->WindowToViewportScalar(original_size) : original_size;
+ int scaled_size = frame->GetPage()->GetChromeClient().WindowToViewportScalar(
+ frame, original_size);
// The result should not be samller than the scrollbar thickness in order to
// secure space for scrollbar in popup.
float device_scale = 1.0f * scaled_size / original_size;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
index a65e945432e..ff349a83bdc 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_default.h
@@ -47,15 +47,23 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
bool ThemeDrawsFocusRing(const ComputedStyle&) const override;
// List Box selection color
- virtual Color ActiveListBoxSelectionBackgroundColor() const;
- virtual Color ActiveListBoxSelectionForegroundColor() const;
- virtual Color InactiveListBoxSelectionBackgroundColor() const;
- virtual Color InactiveListBoxSelectionForegroundColor() const;
-
- Color PlatformActiveSelectionBackgroundColor() const override;
- Color PlatformInactiveSelectionBackgroundColor() const override;
- Color PlatformActiveSelectionForegroundColor() const override;
- Color PlatformInactiveSelectionForegroundColor() const override;
+ virtual Color ActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color ActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color InactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const;
+ virtual Color InactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const;
+
+ Color PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformInactiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const override;
IntSize SliderTickSize() const override;
int SliderTickOffsetFromTrackCenter() const override;
@@ -115,8 +123,7 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
// These methods define the padding for the MenuList's inner block.
int PopupInternalPaddingStart(const ComputedStyle&) const override;
- int PopupInternalPaddingEnd(const ChromeClient*,
- const ComputedStyle&) const override;
+ int PopupInternalPaddingEnd(LocalFrame*, const ComputedStyle&) const override;
int PopupInternalPaddingTop(const ComputedStyle&) const override;
int PopupInternalPaddingBottom(const ComputedStyle&) const override;
// This returns a value based on scrollbar thickness. It's not 0 even in
@@ -124,7 +131,7 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
// thickness, which is 3px or 4px, and we use the value from the default Aura
// theme.
int MenuListArrowWidthInDIP() const;
- float ClampedMenuListArrowPaddingSize(const ChromeClient*,
+ float ClampedMenuListArrowPaddingSize(LocalFrame*,
const ComputedStyle&) const;
protected:
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
index 20e5a17cccf..ae22fe65b67 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
@@ -45,13 +45,20 @@ class LayoutThemeMac final : public LayoutTheme {
bool IsControlStyled(ControlPart part, const ComputedStyle&) const override;
- Color PlatformActiveSelectionBackgroundColor() const override;
- Color PlatformInactiveSelectionBackgroundColor() const override;
- Color PlatformActiveSelectionForegroundColor() const override;
- Color PlatformActiveListBoxSelectionBackgroundColor() const override;
- Color PlatformActiveListBoxSelectionForegroundColor() const override;
- Color PlatformInactiveListBoxSelectionBackgroundColor() const override;
- Color PlatformInactiveListBoxSelectionForegroundColor() const override;
+ Color PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformInactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override;
+ Color PlatformInactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const override;
Color PlatformSpellingMarkerUnderlineColor() const override;
Color PlatformGrammarMarkerUnderlineColor() const override;
Color PlatformFocusRingColor() const override;
@@ -77,8 +84,7 @@ class LayoutThemeMac final : public LayoutTheme {
int SliderTickOffsetFromTrackCenter() const override;
int PopupInternalPaddingStart(const ComputedStyle&) const override;
- int PopupInternalPaddingEnd(const ChromeClient*,
- const ComputedStyle&) const override;
+ int PopupInternalPaddingEnd(LocalFrame*, const ComputedStyle&) const override;
int PopupInternalPaddingTop(const ComputedStyle&) const override;
int PopupInternalPaddingBottom(const ComputedStyle&) const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm
index b80640e6b0f..c51e5366065 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
@@ -29,6 +29,7 @@
#import "third_party/blink/public/platform/mac/web_sandbox_support.h"
#import "third_party/blink/public/platform/platform.h"
#import "third_party/blink/public/resources/grit/blink_resources.h"
+#import "third_party/blink/public/strings/grit/blink_strings.h"
#import "third_party/blink/renderer/core/css_value_keywords.h"
#import "third_party/blink/renderer/core/fileapi/file_list.h"
#import "third_party/blink/renderer/core/html_names.h"
@@ -222,27 +223,33 @@ LayoutThemeMac::~LayoutThemeMac() {
[[NSNotificationCenter defaultCenter] removeObserver:notification_observer_];
}
-Color LayoutThemeMac::PlatformActiveSelectionBackgroundColor() const {
+Color LayoutThemeMac::PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
return GetSystemColor(MacSystemColorID::kSelectedTextBackground);
}
-Color LayoutThemeMac::PlatformInactiveSelectionBackgroundColor() const {
+Color LayoutThemeMac::PlatformInactiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
return GetSystemColor(MacSystemColorID::kSecondarySelectedControl);
}
-Color LayoutThemeMac::PlatformActiveSelectionForegroundColor() const {
+Color LayoutThemeMac::PlatformActiveSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
return Color::kBlack;
}
-Color LayoutThemeMac::PlatformActiveListBoxSelectionBackgroundColor() const {
+Color LayoutThemeMac::PlatformActiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
return GetSystemColor(MacSystemColorID::kAlternateSelectedControl);
}
-Color LayoutThemeMac::PlatformActiveListBoxSelectionForegroundColor() const {
+Color LayoutThemeMac::PlatformActiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
return Color::kWhite;
}
-Color LayoutThemeMac::PlatformInactiveListBoxSelectionForegroundColor() const {
+Color LayoutThemeMac::PlatformInactiveListBoxSelectionForegroundColor(
+ WebColorScheme color_scheme) const {
return Color::kBlack;
}
@@ -264,8 +271,9 @@ Color LayoutThemeMac::PlatformFocusRingColor() const {
ComputedStyle::InitialStyle().UsedColorScheme());
}
-Color LayoutThemeMac::PlatformInactiveListBoxSelectionBackgroundColor() const {
- return PlatformInactiveSelectionBackgroundColor();
+Color LayoutThemeMac::PlatformInactiveListBoxSelectionBackgroundColor(
+ WebColorScheme color_scheme) const {
+ return PlatformInactiveSelectionBackgroundColor(color_scheme);
}
static FontSelectionValue ToFontWeight(NSInteger app_kit_font_weight) {
@@ -744,7 +752,7 @@ int LayoutThemeMac::PopupInternalPaddingStart(
return 0;
}
-int LayoutThemeMac::PopupInternalPaddingEnd(const ChromeClient*,
+int LayoutThemeMac::PopupInternalPaddingEnd(LocalFrame*,
const ComputedStyle& style) const {
if (style.EffectiveAppearance() == kMenulistPart)
return PopupButtonPadding(ControlSizeForFont(style))[kRightMargin] *
@@ -996,8 +1004,7 @@ String LayoutThemeMac::FileListNameForWidth(Locale& locale,
String str_to_truncate;
if (file_list->IsEmpty()) {
- str_to_truncate =
- locale.QueryString(WebLocalizedString::kFileButtonNoFileSelectedLabel);
+ str_to_truncate = locale.QueryString(IDS_FORM_FILE_NO_FILE_LABEL);
} else if (file_list->length() == 1) {
File* file = file_list->item(0);
if (file->GetUserVisibility() == File::kIsUserVisible)
@@ -1007,7 +1014,7 @@ String LayoutThemeMac::FileListNameForWidth(Locale& locale,
str_to_truncate = file->name();
} else {
return StringTruncator::RightTruncate(
- locale.QueryString(WebLocalizedString::kMultipleFileUploadText,
+ locale.QueryString(IDS_FORM_FILE_MULTIPLE_UPLOAD,
locale.ConvertToLocalizedNumber(
String::Number(file_list->length()))),
width, font);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_mobile.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_mobile.h
index 7193f097ae0..82bee8c8937 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_mobile.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_mobile.h
@@ -43,7 +43,8 @@ class LayoutThemeMobile : public LayoutThemeDefault {
return LayoutThemeMobile::kDefaultTapHighlightColor;
}
- Color PlatformActiveSelectionBackgroundColor() const override {
+ Color PlatformActiveSelectionBackgroundColor(
+ WebColorScheme color_scheme) const override {
return LayoutThemeMobile::kDefaultActiveSelectionBackgroundColor;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.cc b/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.cc
deleted file mode 100644
index e973cda23d5..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/layout/layout_theme_touchless.h"
-
-#include "third_party/blink/public/resources/grit/blink_resources.h"
-#include "third_party/blink/renderer/platform/data_resource_helper.h"
-
-namespace blink {
-
-scoped_refptr<LayoutTheme> LayoutThemeTouchless::Create() {
- return base::AdoptRef(new LayoutThemeTouchless());
-}
-
-LayoutTheme& LayoutTheme::NativeTheme() {
- DEFINE_STATIC_REF(LayoutTheme, layout_theme,
- (LayoutThemeTouchless::Create()));
- return *layout_theme;
-}
-
-LayoutThemeTouchless::~LayoutThemeTouchless() {}
-
-String LayoutThemeTouchless::ExtraDefaultStyleSheet() {
- return LayoutThemeMobile::ExtraDefaultStyleSheet() +
- UncompressResourceAsASCIIString(IDR_UASTYLE_THEME_TOUCHLESS_CSS);
-}
-
-bool LayoutThemeTouchless::IsFocusRingOutset() const {
- return true;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.h
deleted file mode 100644
index 8342879992e..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_touchless.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_THEME_TOUCHLESS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_THEME_TOUCHLESS_H_
-
-#include "third_party/blink/renderer/core/layout/layout_theme_mobile.h"
-
-namespace blink {
-
-class LayoutThemeTouchless final : public LayoutThemeMobile {
- public:
- static scoped_refptr<LayoutTheme> Create();
- bool DelegatesMenuListRendering() const override { return true; }
-
- String ExtraDefaultStyleSheet() override;
- bool IsFocusRingOutset() const override;
-
- private:
- ~LayoutThemeTouchless() override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_THEME_TOUCHLESS_H_
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 43fd8ef97e0..3e4d9f0209e 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
@@ -6,6 +6,7 @@
#include <windows.h>
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -25,45 +26,44 @@ Color LayoutThemeWin::SystemColor(CSSValueID css_value_id,
return LayoutThemeDefault::SystemColor(css_value_id, color_scheme);
}
- int system_index;
-
+ blink::WebThemeEngine::SystemThemeColor theme_color;
switch (css_value_id) {
case CSSValueID::kButtonface:
- system_index = COLOR_BTNFACE;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonFace;
break;
case CSSValueID::kButtontext:
- system_index = COLOR_BTNTEXT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonText;
break;
case CSSValueID::kGraytext:
- system_index = COLOR_GRAYTEXT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kGrayText;
break;
case CSSValueID::kHighlight:
- system_index = COLOR_HIGHLIGHT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlight;
break;
case CSSValueID::kHighlighttext:
- system_index = COLOR_HIGHLIGHTTEXT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlightText;
break;
case CSSValueID::kLinktext:
case CSSValueID::kVisitedtext:
- system_index = COLOR_HOTLIGHT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kHotlight;
break;
case CSSValueID::kWindow:
- system_index = COLOR_WINDOW;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kWindow;
break;
case CSSValueID::kWindowtext:
- system_index = COLOR_WINDOWTEXT;
+ theme_color = blink::WebThemeEngine::SystemThemeColor::kWindowText;
break;
default:
return LayoutThemeDefault::SystemColor(css_value_id, color_scheme);
}
- return SystemColorBySystemIndex(system_index);
-}
-
-Color LayoutThemeWin::SystemColorBySystemIndex(int system_index) {
- DWORD system_color = ::GetSysColor(system_index);
- return Color(GetRValue(system_color), GetGValue(system_color),
- GetBValue(system_color));
+ if (Platform::Current() && Platform::Current()->ThemeEngine()) {
+ const base::Optional<SkColor> system_color =
+ Platform::Current()->ThemeEngine()->GetSystemColor(theme_color);
+ if (system_color)
+ return Color(system_color.value());
+ }
+ return LayoutThemeDefault::SystemColor(css_value_id, color_scheme);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_win.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_win.h
index 842870a4a2e..860a0a74d31 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_win.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_win.h
@@ -15,9 +15,6 @@ class LayoutThemeWin final : public LayoutThemeDefault {
Color SystemColor(CSSValueID css_value_id,
WebColorScheme color_scheme) const override;
-
- private:
- static Color SystemColorBySystemIndex(int system_index);
};
} // 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 fe4a22cc431..e4bf50b3a2a 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
@@ -46,7 +46,8 @@
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_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_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
@@ -450,21 +451,17 @@ static void WriteTextRun(WTF::TextStream& ts,
}
static void WriteTextFragment(WTF::TextStream& ts,
- const NGPhysicalFragment& physical_fragment,
- PhysicalOffset offset_to_container_box) {
- const auto* physical_text_fragment =
- DynamicTo<NGPhysicalTextFragment>(physical_fragment);
- if (!physical_text_fragment)
- return;
- const ComputedStyle& style = physical_fragment.Style();
+ const LayoutObject* layout_object,
+ PhysicalRect rect,
+ const ComputedStyle& style,
+ StringView text,
+ LayoutUnit inline_size) {
// TODO(layout-dev): Dump physical coordinates when removing the legacy inline
// layout code.
- NGTextFragment fragment(style.GetWritingMode(), *physical_text_fragment);
+ PhysicalOffset offset_to_container_box = rect.offset;
if (UNLIKELY(style.IsFlippedBlocksWritingMode())) {
- if (physical_fragment.GetLayoutObject()) {
- PhysicalRect rect(offset_to_container_box, physical_fragment.Size());
- const LayoutBlock* containing_block =
- physical_fragment.GetLayoutObject()->ContainingBlock();
+ if (layout_object) {
+ const LayoutBlock* containing_block = layout_object->ContainingBlock();
LayoutRect layout_rect = containing_block->FlipForWritingMode(rect);
offset_to_container_box.left = layout_rect.X();
}
@@ -473,14 +470,39 @@ static void WriteTextFragment(WTF::TextStream& ts,
// See WriteTextRun() for why we convert to int.
int x = offset_to_container_box.left.ToInt();
int y = offset_to_container_box.top.ToInt();
- int logical_width =
- (offset_to_container_box.left + fragment.InlineSize()).Ceil() - x;
+ int logical_width = (offset_to_container_box.left + inline_size).Ceil() - x;
ts << "text run at (" << x << "," << y << ") width " << logical_width;
- ts << ": "
- << QuoteAndEscapeNonPrintables(physical_text_fragment->Text().ToString());
+ ts << ": " << QuoteAndEscapeNonPrintables(text.ToString());
ts << "\n";
}
+static void WriteTextFragment(WTF::TextStream& ts,
+ const NGInlineCursor& cursor) {
+ if (const NGPaintFragment* const paint_fragment =
+ cursor.CurrentPaintFragment()) {
+ const auto* physical_text_fragment =
+ DynamicTo<NGPhysicalTextFragment>(paint_fragment->PhysicalFragment());
+ if (!physical_text_fragment)
+ return;
+ const NGTextFragment fragment(paint_fragment->Style().GetWritingMode(),
+ *physical_text_fragment);
+ WriteTextFragment(ts, paint_fragment->GetLayoutObject(),
+ PhysicalRect(paint_fragment->InlineOffsetToContainerBox(),
+ paint_fragment->Size()),
+ paint_fragment->Style(), physical_text_fragment->Text(),
+ fragment.InlineSize());
+ return;
+ }
+ DCHECK(cursor.CurrentItem());
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ DCHECK(item.Type() == NGFragmentItem::kText ||
+ item.Type() == NGFragmentItem::kGeneratedText);
+ const LayoutUnit inline_size =
+ item.IsHorizontal() ? item.Size().width : item.Size().height;
+ WriteTextFragment(ts, item.GetLayoutObject(), item.Rect(), item.Style(),
+ item.Text(cursor.Items()), inline_size);
+}
+
static void WritePaintProperties(WTF::TextStream& ts,
const LayoutObject& o,
int indent) {
@@ -560,12 +582,12 @@ void Write(WTF::TextStream& ts,
if (o.IsText() && !o.IsBR()) {
const LayoutText& text = ToLayoutText(o);
- if (const NGPhysicalBoxFragment* box_fragment =
- text.ContainingBlockFlowFragment()) {
- for (const auto& child :
- NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, &text)) {
+ if (const LayoutBlockFlow* block_flow = text.ContainingNGBlockFlow()) {
+ NGInlineCursor cursor(*block_flow);
+ cursor.MoveTo(text);
+ for (; cursor; cursor.MoveToNextForSameLayoutObject()) {
WriteIndent(ts, indent + 1);
- WriteTextFragment(ts, *child.fragment, child.offset_to_container_box);
+ WriteTextFragment(ts, cursor);
}
} else {
for (InlineTextBox* box : text.TextBoxes()) {
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 6f50070e634..b45e3da976c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_video.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_video.cc
@@ -110,9 +110,10 @@ void LayoutVideo::ImageChanged(WrappedImagePtr new_image,
// Cache the image intrinsic size so we can continue to use it to draw the
// image correctly even if we know the video intrinsic size but aren't able to
// draw video frames yet (we don't want to scale the poster to the video size
- // without keeping aspect ratio).
- if (VideoElement()->ShouldDisplayPosterImage())
- cached_image_size_ = IntrinsicSize();
+ // without keeping aspect ratio). We do not need to check
+ // |ShouldDisplayPosterImage| because the image can be ready before we find
+ // out we actually need it.
+ cached_image_size_ = IntrinsicSize();
// The intrinsic size is now that of the image, but in case we already had the
// intrinsic size of the video we call this here to restore the video size.
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 f709c11971d..82387ff4973 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.cc
@@ -331,11 +331,10 @@ void LayoutView::UpdateLayout() {
// to date DSF when layout happens, we plumb this through to the FontCache, so
// that we can correctly retrieve RenderStyleForStrike from out of
// process. crbug.com/845468
- FontCache::SetDeviceScaleFactor(GetFrameView()
- ->GetFrame()
- .GetChromeClient()
- .GetScreenInfo()
- .device_scale_factor);
+ LocalFrame& frame = GetFrameView()->GetFrame();
+ ChromeClient& chrome_client = frame.GetChromeClient();
+ FontCache::SetDeviceScaleFactor(
+ chrome_client.GetScreenInfo(frame).device_scale_factor);
#endif
LayoutBlockFlow::UpdateLayout();
@@ -717,10 +716,8 @@ void LayoutView::MayUpdateHoverWhenContentUnderMouseChanged(
MouseEventManager::UpdateHoverReason::kScrollOffsetChanged);
}
-IntRect LayoutView::DocumentRect() const {
- PhysicalRect overflow_rect = FlipForWritingMode(LayoutOverflowRect());
- // TODO(crbug.com/650768): The pixel snapping looks incorrect.
- return PixelSnappedIntRect(overflow_rect);
+PhysicalRect LayoutView::DocumentRect() const {
+ return FlipForWritingMode(LayoutOverflowRect());
}
IntSize LayoutView::GetLayoutSize(
@@ -900,6 +897,11 @@ void LayoutView::UpdateCounters() {
}
}
+bool LayoutView::HasTickmarks() const {
+ return !tickmarks_override_.IsEmpty() ||
+ GetDocument().Markers().PossiblyHasTextMatchMarkers();
+}
+
Vector<IntRect> LayoutView::GetTickmarks() const {
if (!tickmarks_override_.IsEmpty())
return tickmarks_override_;
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 ca4d4bb5728..f37105eff18 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.h
@@ -193,7 +193,7 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
PaintLayerCompositor* Compositor();
bool UsesCompositing() const;
- IntRect DocumentRect() const;
+ PhysicalRect DocumentRect() const;
IntervalArena* GetIntervalArena();
@@ -243,8 +243,9 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
PhysicalRect DebugRect() const override;
// Returns the coordinates of find-in-page scrollbar tickmarks. These come
- // from DocumentMarkerController, unless overridden by SetTickmarks.
+ // from DocumentMarkerController, unless overridden by OverrideTickmarks().
Vector<IntRect> GetTickmarks() const;
+ bool HasTickmarks() const;
// Sets the coordinates of find-in-page scrollbar tickmarks, bypassing
// DocumentMarkerController. This is used by the PDF plugin.
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 ec039f06bfa..e9fb4e46810 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
@@ -354,7 +354,7 @@ LayoutPoint InlineBox::FlipForWritingMode(const LayoutPoint& point) const {
}
void InlineBox::SetShouldDoFullPaintInvalidationForFirstLine() {
- GetLineLayoutItem().StyleRef().ClearCachedPseudoStyles();
+ GetLineLayoutItem().StyleRef().ClearCachedPseudoElementStyles();
GetLineLayoutItem().SetShouldDoFullPaintInvalidation();
if (!IsInlineFlowBox())
return;
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
index 98caacb9488..26d4dc3cc29 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
@@ -510,24 +510,22 @@ void InlineTextBox::PaintDocumentMarker(GraphicsContext& pt,
font, grammar);
}
-void InlineTextBox::PaintTextMatchMarkerForeground(
- const PaintInfo& paint_info,
- const LayoutPoint& box_origin,
- const TextMatchMarker& marker,
- const ComputedStyle& style,
- const Font& font) const {
- InlineTextBoxPainter(*this).PaintTextMatchMarkerForeground(
- paint_info, box_origin, marker, style, font);
-}
-
-void InlineTextBox::PaintTextMatchMarkerBackground(
- const PaintInfo& paint_info,
- const LayoutPoint& box_origin,
- const TextMatchMarker& marker,
- const ComputedStyle& style,
- const Font& font) const {
- InlineTextBoxPainter(*this).PaintTextMatchMarkerBackground(
- paint_info, box_origin, marker, style, font);
+void InlineTextBox::PaintTextMarkerForeground(const PaintInfo& paint_info,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase& marker,
+ const ComputedStyle& style,
+ const Font& font) const {
+ InlineTextBoxPainter(*this).PaintTextMarkerForeground(paint_info, box_origin,
+ marker, style, font);
+}
+
+void InlineTextBox::PaintTextMarkerBackground(const PaintInfo& paint_info,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase& marker,
+ const ComputedStyle& style,
+ const Font& font) const {
+ InlineTextBoxPainter(*this).PaintTextMarkerBackground(paint_info, box_origin,
+ marker, style, font);
}
int InlineTextBox::CaretMinOffset() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
index f2812873467..f5467ffedbc 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
@@ -35,7 +35,7 @@ namespace blink {
class DocumentMarker;
class GraphicsContext;
-class TextMatchMarker;
+class TextMarkerBase;
class CORE_EXPORT InlineTextBox : public InlineBox {
public:
@@ -140,16 +140,16 @@ class CORE_EXPORT InlineTextBox : public InlineBox {
const ComputedStyle&,
const Font&,
bool grammar) const;
- virtual void PaintTextMatchMarkerForeground(const PaintInfo&,
- const LayoutPoint& box_origin,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&) const;
- virtual void PaintTextMatchMarkerBackground(const PaintInfo&,
- const LayoutPoint& box_origin,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&) const;
+ virtual void PaintTextMarkerForeground(const PaintInfo&,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&) const;
+ virtual void PaintTextMarkerBackground(const PaintInfo&,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&) const;
void Move(const LayoutSize&) final;
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
index 4d76b7e4490..174c83ee69c 100644
--- a/chromium/third_party/blink/renderer/core/layout/list_marker_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/list_marker_text.cc
@@ -515,6 +515,9 @@ static EListStyleType EffectiveListMarkerType(EListStyleType type, int count) {
case EListStyleType::kUpperAlpha:
case EListStyleType::kUpperLatin:
return (count < 1) ? EListStyleType::kDecimal : type;
+ case EListStyleType::kString:
+ NOTREACHED();
+ break;
}
NOTREACHED();
@@ -590,6 +593,9 @@ UChar Suffix(EListStyleType type, int count) {
case EListStyleType::kKoreanHanjaFormal:
case EListStyleType::kKoreanHanjaInformal:
return 0x3001;
+ case EListStyleType::kString:
+ NOTREACHED();
+ break;
}
NOTREACHED();
@@ -924,6 +930,10 @@ String GetText(EListStyleType type, int count) {
return ToGeorgian(count);
case EListStyleType::kHebrew:
return ToHebrew(count);
+
+ case EListStyleType::kString:
+ NOTREACHED();
+ break;
}
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
index cd27fbf54b7..3ac1c1fbcb5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
@@ -236,6 +236,7 @@ CSSLayoutDefinition::Instance* CSSLayoutDefinition::CreateInstance() {
void CSSLayoutDefinition::Instance::Trace(blink::Visitor* visitor) {
visitor->Trace(definition_);
+ visitor->Trace(instance_);
}
void CSSLayoutDefinition::Trace(Visitor* visitor) {
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 fffb7ae4dc5..b8690a9e84f 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
@@ -30,9 +30,8 @@ class V8NoArgumentConstructor;
// Represents a javascript class registered on the LayoutWorkletGlobalScope by
// the author.
// https://drafts.css-houdini.org/css-layout-api/#layout-definition
-class CSSLayoutDefinition final
- : public GarbageCollectedFinalized<CSSLayoutDefinition>,
- public NameClient {
+class CSSLayoutDefinition final : public GarbageCollected<CSSLayoutDefinition>,
+ public NameClient {
public:
CSSLayoutDefinition(
ScriptState*,
@@ -47,7 +46,7 @@ class CSSLayoutDefinition final
// This class represents an instance of the layout class defined by the
// CSSLayoutDefinition.
- class Instance final : public GarbageCollectedFinalized<Instance> {
+ class Instance final : public GarbageCollected<Instance> {
public:
Instance(CSSLayoutDefinition*, v8::Local<v8::Value> instance);
@@ -69,7 +68,7 @@ class CSSLayoutDefinition final
void ReportException(ExceptionState*);
Member<CSSLayoutDefinition> definition_;
- ScopedPersistent<v8::Value> instance_;
+ TraceWrapperV8Reference<v8::Value> instance_;
};
// Creates an instance of the web developer defined class. May return a
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
index 2bb3946b5a9..ec4f27e6957 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_constraints.cc
@@ -43,10 +43,11 @@ ScriptValue CustomLayoutConstraints::data(ScriptState* script_state) const {
DCHECK(script_state->World().IsWorkerWorld());
if (layout_worklet_world_v8_data_.IsEmpty())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
- return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
- script_state->GetIsolate()));
+ return ScriptValue(
+ script_state->GetIsolate(),
+ layout_worklet_world_v8_data_.NewLocal(script_state->GetIsolate()));
}
void CustomLayoutConstraints::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
index 83ea4e18d63..1019fd242bb 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.cc
@@ -44,10 +44,11 @@ ScriptValue CustomLayoutFragment::data(ScriptState* script_state) const {
DCHECK(script_state->World().IsWorkerWorld());
if (layout_worklet_world_v8_data_.IsEmpty())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
- return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
- script_state->GetIsolate()));
+ return ScriptValue(
+ script_state->GetIsolate(),
+ layout_worklet_world_v8_data_.NewLocal(script_state->GetIsolate()));
}
void CustomLayoutFragment::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/document_layout_definition.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/document_layout_definition.h
index b3b77adcccf..2a8e359b1cf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/document_layout_definition.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/document_layout_definition.h
@@ -13,7 +13,7 @@ namespace blink {
// needed by the document about the author defined layout.
// https://drafts.css-houdini.org/css-layout-api/#document-layout-definition
class DocumentLayoutDefinition final
- : public GarbageCollectedFinalized<DocumentLayoutDefinition> {
+ : public GarbageCollected<DocumentLayoutDefinition> {
public:
explicit DocumentLayoutDefinition(CSSLayoutDefinition*);
virtual ~DocumentLayoutDefinition();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.h b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.h
index 77c4d3fed99..46837b1ea3a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.h
@@ -18,7 +18,7 @@ class WorkletModuleResponsesMap;
// A proxy for LayoutWorklet to talk to LayoutWorkletGlobalScope.
class CORE_EXPORT LayoutWorkletGlobalScopeProxy
- : public GarbageCollectedFinalized<LayoutWorkletGlobalScopeProxy>,
+ : public GarbageCollected<LayoutWorkletGlobalScopeProxy>,
public WorkletGlobalScopeProxy {
USING_GARBAGE_COLLECTED_MIXIN(LayoutWorkletGlobalScopeProxy);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
index 3f40568b094..b592b3c9e83 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -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 NGExclusionSpace_h
-#define NGExclusionSpace_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_EXCLUSION_SPACE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_EXCLUSION_SPACE_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h"
@@ -586,4 +586,4 @@ class CORE_EXPORT NGExclusionSpace {
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
blink::NGExclusionSpaceInternal::NGShelfEdge)
-#endif // NGExclusionSpace_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_EXCLUSION_SPACE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.h b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.h
index 226f01d89df..abf46f88fff 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.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 NGLayoutOpportunity_h
-#define NGLayoutOpportunity_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_LAYOUT_OPPORTUNITY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_LAYOUT_OPPORTUNITY_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_line_layout_opportunity.h"
@@ -62,4 +62,4 @@ struct CORE_EXPORT NGLayoutOpportunity {
} // namespace blink
-#endif // NGLayoutOpportunity_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_LAYOUT_OPPORTUNITY_H_
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 ee363f9357a..91471c971f2 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
@@ -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 NGBfcOffset_h
-#define NGBfcOffset_h
+#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 "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -58,4 +58,4 @@ CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGBfcOffset&);
} // namespace blink
-#endif // NGBfcOffset_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_OFFSET_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h
index eac77c3251f..2801e817eff 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.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 NGBfcRect_h
-#define NGBfcRect_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_RECT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_RECT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
@@ -51,4 +51,4 @@ struct CORE_EXPORT NGBfcRect {
} // namespace blink
-#endif // NGBfcRect_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BFC_RECT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h
index 975cbdf99e0..424d64a51ae 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.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 NGBorderEdges_h
-#define NGBorderEdges_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BORDER_EDGES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BORDER_EDGES_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h"
@@ -65,4 +65,4 @@ struct CORE_EXPORT NGBorderEdges {
} // namespace blink
-#endif // NGBorderEdges_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BORDER_EDGES_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
index e4e8a9ed325..f5c78a92dad 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
@@ -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 NGBoxStrut_h
-#define NGBoxStrut_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BOX_STRUT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BOX_STRUT_H_
#include <utility>
@@ -241,4 +241,4 @@ inline NGPhysicalBoxStrut NGBoxStrut::ConvertToPhysical(
} // namespace blink
-#endif // NGBoxStrut_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_BOX_STRUT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
index d5337978b10..50f699428ac 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
@@ -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 NGMarginStrut_h
-#define NGMarginStrut_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_MARGIN_STRUT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_MARGIN_STRUT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -57,4 +57,4 @@ struct CORE_EXPORT NGMarginStrut {
} // namespace blink
-#endif // NGMarginStrut_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_MARGIN_STRUT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h
index 2da520c5a7c..bda114a61e1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.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 NGStaticPosition_h
-#define NGStaticPosition_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_STATIC_POSITION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_STATIC_POSITION_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
@@ -144,4 +144,4 @@ inline NGPhysicalStaticPosition NGLogicalStaticPosition::ConvertToPhysical(
} // namespace blink
-#endif // NGStaticPosition_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GEOMETRY_NG_STATIC_POSITION_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.h
index 0de484a0885..7c69dad0db1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/empty_offset_mapping_builder.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 EmptyOffsetMappingBuilder_h
-#define EmptyOffsetMappingBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_EMPTY_OFFSET_MAPPING_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_EMPTY_OFFSET_MAPPING_BUILDER_H_
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -39,4 +39,4 @@ class EmptyOffsetMappingBuilder {
} // namespace blink
-#endif // EmptyOffsetMappingBuilder_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_EMPTY_OFFSET_MAPPING_BUILDER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc
index da4b412bbff..bd55b43700a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_test.cc
@@ -47,6 +47,21 @@ class LayoutNGTextTest : public PageTestBase {
}
};
+TEST_F(LayoutNGTextTest, SetTextWithOffsetAppendControl) {
+ if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+ return;
+
+ SetBodyInnerHTML(u"<pre id=target>a</pre>");
+ Text& text = To<Text>(*GetElementById("target")->firstChild());
+ // Note: "\n" is control character instead of text character.
+ text.appendData("\nX");
+
+ EXPECT_EQ(
+ "*{'a', ShapeResult=0+1}\n"
+ "*{'X', ShapeResult=2+1}\n",
+ GetItemsAsString(*text.GetLayoutObject()));
+}
+
TEST_F(LayoutNGTextTest, SetTextWithOffsetAppendCollapseWhiteSpace) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return;
@@ -125,6 +140,19 @@ TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteRTL) {
GetItemsAsString(*text.GetLayoutObject()));
}
+// http://crbug.com/1000685
+TEST_F(LayoutNGTextTest, SetTextWithOffsetDeleteRTL2) {
+ if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+ return;
+
+ SetBodyInnerHTML(u"<p id=target dir=rtl>0(xy)5</p>");
+ Text& text = To<Text>(*GetElementById("target")->firstChild());
+ text.deleteData(0, 1, ASSERT_NO_EXCEPTION); // remove "0"
+
+ EXPECT_EQ("*{'(xy)5', ShapeResult=0+5}\n",
+ GetItemsAsString(*text.GetLayoutObject()));
+}
+
TEST_F(LayoutNGTextTest, SetTextWithOffsetInsert) {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
index cf430a648e4..797750264ee 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
@@ -147,8 +147,8 @@ unsigned NGAbstractInlineTextBox::Len() const {
if (!fragment_)
return 0;
if (NeedsTrailingSpace())
- return PhysicalTextFragment().Length() + 1;
- return PhysicalTextFragment().Length();
+ return PhysicalTextFragment().TextLength() + 1;
+ return PhysicalTextFragment().TextLength();
}
AbstractInlineTextBox::Direction NGAbstractInlineTextBox::GetDirection() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h
index 4f4a1978af6..64426201e06 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.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 NGBaseline_h
-#define NGBaseline_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BASELINE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BASELINE_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -204,4 +204,4 @@ class CORE_EXPORT NGBaselineList {
} // namespace blink
-#endif // NGBaseline_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BASELINE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h
index ee1c47fba4d..dc53a487dfa 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.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 NGBidiParagraph_h
-#define NGBidiParagraph_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -69,4 +69,4 @@ class NGBidiParagraph {
} // namespace blink
-#endif // NGBidiParagraph_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_BIDI_PARAGRAPH_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h
index d7a1a029e07..47db5da2c0b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.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 NGCaretRect_h
-#define NGCaretRect_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_RECT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_RECT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -27,4 +27,4 @@ ComputeNGLocalSelectionRect(const PositionWithAffinity&);
} // namespace blink
-#endif // NGCaretRect_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_CARET_RECT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 35aa96a8c03..ab9ab640272 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
@@ -15,7 +15,9 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalTextFragment& text)
rect_({PhysicalOffset(), text.Size()}),
type_(kText),
style_variant_(static_cast<unsigned>(text.StyleVariant())),
- is_hidden_for_paint_(false) {
+ is_flow_control_(text.IsFlowControl()),
+ is_hidden_for_paint_(false),
+ text_direction_(static_cast<unsigned>(text.ResolvedDirection())) {
DCHECK_LE(text_.start_offset, text_.end_offset);
#if DCHECK_IS_ON()
if (text_.shape_result) {
@@ -33,7 +35,8 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalLineBoxFragment& line,
rect_({PhysicalOffset(), line.Size()}),
type_(kLine),
style_variant_(static_cast<unsigned>(line.StyleVariant())),
- is_hidden_for_paint_(false) {}
+ is_hidden_for_paint_(false),
+ text_direction_(static_cast<unsigned>(line.BaseDirection())) {}
NGFragmentItem::NGFragmentItem(const NGPhysicalBoxFragment& box,
wtf_size_t item_count)
@@ -42,7 +45,10 @@ NGFragmentItem::NGFragmentItem(const NGPhysicalBoxFragment& box,
rect_({PhysicalOffset(), box.Size()}),
type_(kBox),
style_variant_(static_cast<unsigned>(box.StyleVariant())),
- is_hidden_for_paint_(false) {}
+ is_hidden_for_paint_(false),
+ // TODO(yosin): We should have |textDirection| parameter from
+ // |NGLineBoxFragmentBuilder::Child::BidiLevel()|
+ text_direction_(box.IsAtomicInline() && IsLtr(box.ResolvedDirection())) {}
NGFragmentItem::~NGFragmentItem() {
switch (Type()) {
@@ -61,11 +67,54 @@ NGFragmentItem::~NGFragmentItem() {
}
}
+bool NGFragmentItem::HasSameParent(const NGFragmentItem& other) const {
+ if (!GetLayoutObject())
+ return !other.GetLayoutObject();
+ if (!other.GetLayoutObject())
+ return false;
+ return GetLayoutObject()->Parent() == other.GetLayoutObject()->Parent();
+}
+
+bool NGFragmentItem::IsAtomicInline() const {
+ if (Type() != kBox)
+ return false;
+ if (const NGPhysicalBoxFragment* box = BoxFragment())
+ return box->IsAtomicInline();
+ return false;
+}
+
PhysicalRect NGFragmentItem::SelfInkOverflow() const {
// TODO(kojii): Implement.
return LocalRect();
}
+const ShapeResultView* NGFragmentItem::TextShapeResult() const {
+ if (Type() == kText)
+ return text_.shape_result.get();
+ if (Type() == kGeneratedText)
+ return generated_text_.shape_result.get();
+ NOTREACHED();
+ return nullptr;
+}
+
+unsigned NGFragmentItem::StartOffset() const {
+ if (Type() == kText)
+ return text_.start_offset;
+ if (Type() == kGeneratedText)
+ return 0;
+ NOTREACHED();
+ return 0;
+}
+
+unsigned NGFragmentItem::EndOffset() const {
+ if (Type() == kText)
+ return text_.end_offset;
+ if (Type() == kGeneratedText)
+ return generated_text_.text.length();
+ NOTREACHED();
+ return 0;
+}
+
StringView NGFragmentItem::Text(const NGFragmentItems& items) const {
if (Type() == kText) {
DCHECK_LE(text_.start_offset, text_.end_offset);
@@ -86,6 +135,16 @@ NGTextFragmentPaintInfo NGFragmentItem::TextPaintInfo(
return {};
}
+TextDirection NGFragmentItem::BaseDirection() const {
+ DCHECK_EQ(Type(), kLine);
+ return static_cast<TextDirection>(text_direction_);
+}
+
+TextDirection NGFragmentItem::ResolvedDirection() const {
+ DCHECK(Type() == kText || Type() == kGeneratedText || IsAtomicInline());
+ return static_cast<TextDirection>(text_direction_);
+}
+
String NGFragmentItem::DebugName() const {
return "NGFragmentItem";
}
@@ -152,4 +211,47 @@ NGFragmentItem::ItemsForLayoutObject::Iterator::operator++() {
return *this;
}
+std::ostream& operator<<(std::ostream& ostream, const NGFragmentItem& item) {
+ ostream << "{";
+ switch (item.Type()) {
+ case NGFragmentItem::kText:
+ ostream << "Text " << item.StartOffset() << "-" << item.EndOffset() << " "
+ << (IsLtr(item.ResolvedDirection()) ? "LTR" : "RTL");
+ break;
+ case NGFragmentItem::kGeneratedText:
+ ostream << "GeneratedText \"" << item.GeneratedText() << "\"";
+ break;
+ case NGFragmentItem::kLine:
+ ostream << "Line #descendants=" << item.DescendantsCount() << " "
+ << (IsLtr(item.BaseDirection()) ? "LTR" : "RTL");
+ break;
+ case NGFragmentItem::kBox:
+ ostream << "Box #descendants=" << item.DescendantsCount();
+ if (item.IsAtomicInline()) {
+ ostream << " AtomicInline"
+ << (IsLtr(item.ResolvedDirection()) ? "LTR" : "RTL");
+ }
+ break;
+ }
+ ostream << " ";
+ switch (item.StyleVariant()) {
+ case NGStyleVariant::kStandard:
+ ostream << "Standard";
+ break;
+ case NGStyleVariant::kFirstLine:
+ ostream << "FirstLine";
+ break;
+ case NGStyleVariant::kEllipsis:
+ ostream << "Ellipsis";
+ break;
+ }
+ return ostream << "}";
+}
+
+std::ostream& operator<<(std::ostream& ostream, const NGFragmentItem* item) {
+ if (!item)
+ return ostream << "<null>";
+ return ostream << *item;
+}
+
} // namespace blink
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 cf7cfc2803a..526f635e513 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
@@ -42,18 +42,20 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
struct LineItem {
NGLineHeightMetrics metrics;
scoped_refptr<const NGInlineBreakToken> inline_break_token;
- wtf_size_t children_count;
+ wtf_size_t descendants_count;
};
// Represents a box fragment appeared in a line. This includes inline boxes
// (e.g., <span>text</span>) and atomic inlines.
struct BoxItem {
// If this item is an inline box, its children are stored as following
- // items. |children_count_| has the number of such items.
+ // items. |descendants_count_| has the number of such items.
//
// If this item is a root of another IFC/BFC, children are stored normally,
// as children of |box_fragment|.
+ //
+ // Note:|box_fragment| can be null for <span>.
scoped_refptr<const NGPhysicalBoxFragment> box_fragment;
- wtf_size_t children_count;
+ wtf_size_t descendants_count;
};
enum ItemType { kText, kGeneratedText, kLine, kBox };
@@ -67,6 +69,7 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
ItemType Type() const { return static_cast<ItemType>(type_); }
+ bool IsAtomicInline() const;
bool IsHiddenForPaint() const { return is_hidden_for_paint_; }
NGStyleVariant StyleVariant() const {
@@ -85,6 +88,7 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
return layout_object_->EffectiveStyle(StyleVariant());
}
const LayoutObject* GetLayoutObject() const { return layout_object_; }
+ bool HasSameParent(const NGFragmentItem& other) const;
const PhysicalRect& Rect() const { return rect_; }
const PhysicalOffset& Offset() const { return rect_.offset; }
@@ -96,12 +100,12 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
// 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
- // children. 0 if this item type cannot have children.
- wtf_size_t ChildrenCount() const {
+ // descendants. 0 if this item type cannot have children.
+ wtf_size_t DescendantsCount() const {
if (Type() == kBox)
- return box_.children_count;
+ return box_.descendants_count;
if (Type() == kLine)
- return line_.children_count;
+ return line_.descendants_count;
return 0;
}
@@ -112,11 +116,8 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
return nullptr;
}
- unsigned TextLength() const {
- DCHECK_EQ(Type(), kText);
- return text_.end_offset - text_.start_offset;
- }
- StringView Text(const NGFragmentItems& items) const;
+ Node* GetNode() const { return layout_object_->GetNode(); }
+
NGTextFragmentPaintInfo TextPaintInfo(const NGFragmentItems& items) const;
// DisplayItemClient overrides
@@ -187,6 +188,71 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
return MutableForPainting(*this);
}
+ // Functions for |TextItem| and |GeneratedTextItem|
+
+ bool IsFlowControl() const {
+ DCHECK_EQ(Type(), kText);
+ return is_flow_control_;
+ }
+
+ bool IsHorizontal() const {
+ return IsHorizontalWritingMode(GetWritingMode());
+ }
+
+ WritingMode GetWritingMode() const {
+ DCHECK_EQ(Type(), kText);
+ return Style().GetWritingMode();
+ }
+
+ // TODO(yosin): We'll implement following functions.
+ bool IsLineBreak() const { return false; }
+ bool IsEllipsis() const { return false; }
+ bool IsSymbolMarker() const { return false; }
+
+ const ShapeResultView* TextShapeResult() const;
+
+ unsigned StartOffset() const;
+ unsigned EndOffset() const;
+ unsigned TextLength() const { return EndOffset() - StartOffset(); }
+ StringView Text(const NGFragmentItems& items) const;
+ String GeneratedText() const {
+ DCHECK_EQ(Type(), kGeneratedText);
+ return generated_text_.text;
+ }
+
+ // 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;
+
+ // Compute line-relative coordinates for given offsets, this is not
+ // flow-relative:
+ // https://drafts.csswg.org/css-writing-modes-3/#line-directions
+ std::pair<LayoutUnit, LayoutUnit> LineLeftAndRightForOffsets(
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) const;
+
+ // The layout box of text in (start, end) range in local coordinate.
+ // Start and end offsets must be between StartOffset() and EndOffset().
+ PhysicalRect LocalRect(StringView text,
+ unsigned start_offset,
+ unsigned end_offset) const;
+
+ // The base direction of line. Also known as the paragraph direction. This may
+ // be different from the direction of the container box when first-line style
+ // is used, or when 'unicode-bidi: plaintext' is used.
+ // Note: This is valid only for |LineItem|.
+ TextDirection BaseDirection() const;
+
+ // Direction of this item valid for |TextItem| and |IsAtomicInline()|.
+ // Note: <span> doesn't have text direction.
+ TextDirection ResolvedDirection() const;
+
private:
const LayoutObject* layout_object_;
@@ -221,9 +287,16 @@ class CORE_EXPORT NGFragmentItem : public DisplayItemClient {
// Item index delta to the next item for the same |LayoutObject|.
// wtf_size_t delta_to_next_for_same_layout_object_ = 0;
+ // Note: We should not add |bidi_level_| because it is used only for layout.
unsigned type_ : 2; // ItemType
unsigned style_variant_ : 2; // NGStyleVariant
+ // TODO(yosin): We will change |is_flow_control_| to call |IsLineBreak()| and
+ // |TextType() == kFlowControl|.
+ unsigned is_flow_control_ : 1;
unsigned is_hidden_for_paint_ : 1;
+ // Note: For |TextItem| and |GeneratedTextItem|, |text_direction_| equals to
+ // |ShapeResult::Direction()|.
+ unsigned text_direction_ : 1; // TextDirection.
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
index 31a90c76b39..a30f40cfec8 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
@@ -80,11 +80,17 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
const NGPhysicalBoxFragment& box =
To<NGPhysicalBoxFragment>(child.layout_result->PhysicalFragment());
if (child.children_count <= 1) {
+ // Compute |has_floating_descendants_| to optimize tree traversal in
+ // paint.
+ if (!has_floating_descendants_ && box.IsFloating())
+ has_floating_descendants_ = true;
+
items_.push_back(std::make_unique<NGFragmentItem>(box, 1));
offsets_.push_back(child.offset);
++child_iter;
continue;
}
+ DCHECK(!box.IsFloating());
// Children of inline boxes are flattened and added to |items_|, with the
// count of descendant items to preserve the tree structure.
@@ -118,6 +124,13 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
}
}
+void NGFragmentItemsBuilder::AddListMarker(
+ const NGPhysicalBoxFragment& marker_fragment,
+ const LogicalOffset& offset) {
+ items_.push_back(std::make_unique<NGFragmentItem>(marker_fragment, 1));
+ offsets_.push_back(offset);
+}
+
// Convert internal logical offsets to physical. Items are kept with logical
// offset until outer box size is determined.
void NGFragmentItemsBuilder::ConvertToPhysical(WritingMode writing_mode,
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 fcd9a1d5dce..b0265f18328 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
@@ -25,6 +25,9 @@ class CORE_EXPORT NGFragmentItemsBuilder {
public:
NGFragmentItemsBuilder(NGBoxFragmentBuilder* box_builder) {}
+ // Returns true if we have any floating descendants.
+ bool HasFloatingDescendants() const { return has_floating_descendants_; }
+
const String& TextContent(bool first_line) const {
return UNLIKELY(first_line && first_line_text_content_)
? first_line_text_content_
@@ -49,6 +52,10 @@ class CORE_EXPORT NGFragmentItemsBuilder {
void AddLine(const NGPhysicalLineBoxFragment& line,
const LogicalOffset& offset);
+ // Add a list marker to the current line.
+ void AddListMarker(const NGPhysicalBoxFragment& marker_fragment,
+ const LogicalOffset& offset);
+
// Build a |NGFragmentItems|. The builder cannot build twice because data set
// to this builder may be cleared.
void ToFragmentItems(WritingMode writing_mode,
@@ -71,6 +78,8 @@ class CORE_EXPORT NGFragmentItemsBuilder {
// Keeps children of a line until the offset is determined. See |AddLine|.
ChildList current_line_;
+ bool has_floating_descendants_ = false;
+
#if DCHECK_IS_ON()
const NGPhysicalLineBoxFragment* current_line_fragment_ = nullptr;
bool is_converted_to_physical_ = false;
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 335e04297e0..066225e80ec 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
@@ -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 NGInlineBoxState_h
-#define NGInlineBoxState_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_BOX_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_BOX_STATE_H_
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h"
@@ -256,4 +256,4 @@ class CORE_EXPORT NGInlineLayoutStateStack {
} // namespace blink
-#endif // NGInlineBoxState_h
+#endif // 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_break_token.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h
index f5c93cd9d2b..fdf2ebdccde 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
@@ -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 NGInlineBreakToken_h
-#define NGInlineBreakToken_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_BREAK_TOKEN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_BREAK_TOKEN_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
@@ -96,4 +96,4 @@ struct DowncastTraits<NGInlineBreakToken> {
} // namespace blink
-#endif // NGInlineBreakToken_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_BREAK_TOKEN_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 74053c0f0ab..a7a1c313e71 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
@@ -6,17 +6,17 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
namespace blink {
void NGInlineCursor::MoveToItem(const ItemsSpan::iterator& iter) {
- DCHECK((items_.data() || !items_.size()) && !root_paint_fragment_);
- DCHECK(iter == items_.end() ||
- (&*iter >= items_.data() && iter < items_.end()));
+ DCHECK(IsItemCursor());
+ DCHECK(iter >= items_.begin() && iter <= items_.end());
item_iter_ = iter;
- current_item_ = item_iter_ != items_.end() ? item_iter_->get() : nullptr;
+ current_item_ = iter == items_.end() ? nullptr : iter->get();
}
void NGInlineCursor::SetRoot(ItemsSpan items) {
@@ -33,6 +33,7 @@ void NGInlineCursor::SetRoot(const NGFragmentItems& items) {
void NGInlineCursor::SetRoot(const NGPaintFragment& root_paint_fragment) {
DCHECK(&root_paint_fragment);
+ DCHECK(!root_paint_fragment.Parent()) << root_paint_fragment;
root_paint_fragment_ = &root_paint_fragment;
current_paint_fragment_ = root_paint_fragment.FirstChild();
}
@@ -42,6 +43,7 @@ NGInlineCursor::NGInlineCursor(const LayoutBlockFlow& block_flow) {
if (const NGPhysicalBoxFragment* fragment = block_flow.CurrentFragment()) {
if (const NGFragmentItems* items = fragment->Items()) {
+ fragment_items_ = items;
SetRoot(*items);
return;
}
@@ -52,10 +54,13 @@ NGInlineCursor::NGInlineCursor(const LayoutBlockFlow& block_flow) {
return;
}
- NOTREACHED();
+ // We reach here in case of |ScrollANchor::NotifyBeforeLayout()| via
+ // |LayoutText::PhysicalLinesBoundingBox()|
+ // See external/wpt/css/css-scroll-anchoring/wrapped-text.html
}
-NGInlineCursor::NGInlineCursor(const NGFragmentItems& items) {
+NGInlineCursor::NGInlineCursor(const NGFragmentItems& items)
+ : fragment_items_(&items) {
SetRoot(items);
}
@@ -63,6 +68,156 @@ NGInlineCursor::NGInlineCursor(const NGPaintFragment& root_paint_fragment) {
SetRoot(root_paint_fragment);
}
+NGInlineCursor::NGInlineCursor(const NGInlineCursor& other)
+ : items_(other.items_),
+ item_iter_(other.item_iter_),
+ current_item_(other.current_item_),
+ fragment_items_(other.fragment_items_),
+ root_paint_fragment_(other.root_paint_fragment_),
+ current_paint_fragment_(other.current_paint_fragment_),
+ layout_inline_(other.layout_inline_) {}
+
+NGInlineCursor::NGInlineCursor() = default;
+
+bool NGInlineCursor::operator==(const NGInlineCursor& other) const {
+ if (root_paint_fragment_) {
+ return root_paint_fragment_ == other.root_paint_fragment_ &&
+ current_paint_fragment_ == other.current_paint_fragment_;
+ }
+ if (current_item_ != other.current_item_)
+ return false;
+ DCHECK_EQ(items_.data(), other.items_.data());
+ DCHECK_EQ(items_.size(), other.items_.size());
+ DCHECK_EQ(fragment_items_, other.fragment_items_);
+ DCHECK(item_iter_ == other.item_iter_);
+ return true;
+}
+
+const LayoutBlockFlow* NGInlineCursor::GetLayoutBlockFlow() const {
+ if (root_paint_fragment_)
+ return To<LayoutBlockFlow>(root_paint_fragment_->GetLayoutObject());
+ for (const auto& item : items_) {
+ if (item->GetLayoutObject() && item->GetLayoutObject()->IsInline())
+ return item->GetLayoutObject()->RootInlineFormattingContext();
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+bool NGInlineCursor::HasChildren() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->FirstChild();
+ if (current_item_) {
+ // Note: |DescendantsCount() == 1| means box/line without children.
+ return current_item_->DescendantsCount() > 1;
+ }
+ NOTREACHED();
+ return false;
+}
+
+bool NGInlineCursor::IsAtomicInline() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->PhysicalFragment().IsAtomicInline();
+ if (current_item_)
+ return current_item_->IsAtomicInline();
+ NOTREACHED();
+ return false;
+}
+
+bool NGInlineCursor::IsEllipsis() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->IsEllipsis();
+ if (current_item_)
+ return current_item_->IsEllipsis();
+ NOTREACHED();
+ return false;
+}
+
+bool NGInlineCursor::IsHiddenForPaint() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->PhysicalFragment().IsHiddenForPaint();
+ if (current_item_)
+ return current_item_->IsHiddenForPaint();
+ NOTREACHED();
+ return false;
+}
+
+bool NGInlineCursor::IsPartOfCulledInlineBox(
+ const LayoutInline& layout_inline) const {
+ const LayoutObject* const layout_object = CurrentLayoutObject();
+ // We use |IsInline()| to exclude floating and out-of-flow objects.
+ if (!layout_object || !layout_object->IsInline())
+ return false;
+ return layout_object->IsDescendantOf(&layout_inline);
+}
+
+bool NGInlineCursor::IsLastLineInInlineBlock() const {
+ DCHECK(IsLineBox());
+ if (!GetLayoutBlockFlow()->IsAtomicInlineLevel())
+ return false;
+ NGInlineCursor next_sibling(*this);
+ for (;;) {
+ next_sibling.MoveToNextSibling();
+ if (!next_sibling)
+ return true;
+ if (next_sibling.IsLineBox())
+ return false;
+ // There maybe other top-level objects such as floats, OOF, or list-markers.
+ }
+}
+
+bool NGInlineCursor::IsLineBreak() const {
+ if (current_paint_fragment_) {
+ if (auto* text_fragment = DynamicTo<NGPhysicalTextFragment>(
+ current_paint_fragment_->PhysicalFragment()))
+ return text_fragment->IsLineBreak();
+ return false;
+ }
+ if (current_item_)
+ return current_item_->IsLineBreak();
+ NOTREACHED();
+ return false;
+}
+
+bool NGInlineCursor::IsBeforeSoftLineBreak() const {
+ if (IsLineBreak())
+ return false;
+ // Inline block is not be container line box.
+ // See paint/selection/text-selection-inline-block.html.
+ NGInlineCursor line(*this);
+ line.MoveToContainingLine();
+ if (line.IsLastLineInInlineBlock()) {
+ // We don't paint a line break the end of inline-block
+ // because if an inline-block is at the middle of line, we should not paint
+ // a line break.
+ // Old layout paints line break if the inline-block is at the end of line,
+ // but since its complex to determine if the inline-block is at the end of
+ // line on NG, we just cancels block-end line break painting for any
+ // inline-block.
+ return false;
+ }
+ NGInlineCursor last_leaf(line);
+ last_leaf.MoveToLastLogicalLeaf();
+ if (last_leaf != *this)
+ return false;
+ // Even If |fragment| is before linebreak, if its direction differs to line
+ // direction, we don't paint line break. See
+ // paint/selection/text-selection-newline-mixed-ltr-rtl.html.
+ return line.CurrentBaseDirection() == CurrentResolvedDirection();
+}
+
+bool NGInlineCursor::CanHaveChildren() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->PhysicalFragment().IsContainer();
+ if (current_item_) {
+ return current_item_->Type() == NGFragmentItem::kLine ||
+ (current_item_->Type() == NGFragmentItem::kBox &&
+ !current_item_->IsAtomicInline());
+ }
+ NOTREACHED();
+ return false;
+}
+
bool NGInlineCursor::IsLineBox() const {
if (current_paint_fragment_)
return current_paint_fragment_->PhysicalFragment().IsLineBox();
@@ -72,6 +227,19 @@ bool NGInlineCursor::IsLineBox() const {
return false;
}
+TextDirection NGInlineCursor::CurrentBaseDirection() const {
+ DCHECK(IsLineBox());
+ if (current_paint_fragment_) {
+ return To<NGPhysicalLineBoxFragment>(
+ current_paint_fragment_->PhysicalFragment())
+ .BaseDirection();
+ }
+ if (current_item_)
+ return current_item_->BaseDirection();
+ NOTREACHED();
+ return TextDirection::kLtr;
+}
+
const NGPhysicalBoxFragment* NGInlineCursor::CurrentBoxFragment() const {
if (current_paint_fragment_) {
return DynamicTo<NGPhysicalBoxFragment>(
@@ -101,46 +269,285 @@ const PhysicalOffset NGInlineCursor::CurrentOffset() const {
return PhysicalOffset();
}
-void NGInlineCursor::MoveToNext() {
+const PhysicalRect NGInlineCursor::CurrentRect() const {
+ return PhysicalRect(CurrentOffset(), CurrentSize());
+}
+
+TextDirection NGInlineCursor::CurrentResolvedDirection() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->PhysicalFragment().ResolvedDirection();
+ if (current_item_)
+ return current_item_->ResolvedDirection();
+ NOTREACHED();
+ return TextDirection::kLtr;
+}
+
+const PhysicalSize NGInlineCursor::CurrentSize() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->Size();
+ if (current_item_)
+ return current_item_->Size();
+ NOTREACHED();
+ return PhysicalSize();
+}
+
+const ComputedStyle& NGInlineCursor::CurrentStyle() const {
+ if (current_paint_fragment_)
+ return current_paint_fragment_->Style();
+ return current_item_->Style();
+}
+
+unsigned NGInlineCursor::CurrentTextStartOffset() const {
+ if (current_paint_fragment_) {
+ return To<NGPhysicalTextFragment>(
+ current_paint_fragment_->PhysicalFragment())
+ .StartOffset();
+ }
+ if (current_item_)
+ return current_item_->StartOffset();
+ NOTREACHED();
+ return 0u;
+}
+
+unsigned NGInlineCursor::CurrentTextEndOffset() const {
+ if (current_paint_fragment_) {
+ return To<NGPhysicalTextFragment>(
+ current_paint_fragment_->PhysicalFragment())
+ .EndOffset();
+ }
+ if (current_item_)
+ return current_item_->EndOffset();
+ NOTREACHED();
+ return 0u;
+}
+
+void NGInlineCursor::MakeNull() {
if (root_paint_fragment_) {
- MoveToNextPaintFragment();
+ current_paint_fragment_ = nullptr;
return;
}
- MoveToNextItem();
+ if (fragment_items_)
+ return MoveToItem(items_.end());
}
-void NGInlineCursor::MoveToNextSkippingChildren() {
+void NGInlineCursor::InternalMoveTo(const LayoutObject& layout_object) {
+ DCHECK(layout_object.IsInLayoutNGInlineFormattingContext());
+ if (fragment_items_) {
+ item_iter_ = items_.begin();
+ while (current_item_ && CurrentLayoutObject() != &layout_object)
+ MoveToNextItem();
+ return;
+ }
+ const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
+ if (!fragments.IsInLayoutNGInlineFormattingContext() || fragments.IsEmpty())
+ return MakeNull();
+ if (!root_paint_fragment_) {
+ // We reach here in case of |ScrollANchor::NotifyBeforeLayout()| via
+ // |LayoutText::PhysicalLinesBoundingBox()|
+ // See external/wpt/css/css-scroll-anchoring/wrapped-text.html
+ root_paint_fragment_ = fragments.front().Root();
+ }
+ return MoveTo(fragments.front());
+}
+
+void NGInlineCursor::MoveTo(const LayoutObject& layout_object) {
+ DCHECK(layout_object.IsInLayoutNGInlineFormattingContext()) << layout_object;
+ InternalMoveTo(layout_object);
+ if (IsNotNull() || !layout_object.IsLayoutInline()) {
+ layout_inline_ = nullptr;
+ return;
+ }
+ // In case of |layout_object| is cullred inline.
+ if (!fragment_items_ && !root_paint_fragment_) {
+ root_paint_fragment_ =
+ layout_object.RootInlineFormattingContext()->PaintFragment();
+ if (!root_paint_fragment_)
+ return MakeNull();
+ }
+ layout_inline_ = ToLayoutInline(&layout_object);
+ MoveToFirst();
+ while (IsNotNull() && !IsPartOfCulledInlineBox(*layout_inline_))
+ MoveToNext();
+}
+
+void NGInlineCursor::MoveTo(const NGPaintFragment& paint_fragment) {
+ DCHECK(root_paint_fragment_);
+ DCHECK(paint_fragment.IsDescendantOfNotSelf(*root_paint_fragment_))
+ << paint_fragment << " " << root_paint_fragment_;
+ current_paint_fragment_ = &paint_fragment;
+}
+
+void NGInlineCursor::MoveToContainingLine() {
+ DCHECK(!IsLineBox());
+ if (current_paint_fragment_) {
+ current_paint_fragment_ = current_paint_fragment_->ContainerLineBox();
+ return;
+ }
+ if (current_item_) {
+ do {
+ MoveToPreviousItem();
+ } while (current_item_ && !IsLineBox());
+ return;
+ }
+ NOTREACHED();
+}
+
+void NGInlineCursor::MoveToFirst() {
if (root_paint_fragment_) {
- MoveToNextPaintFragmentSkippingChildren();
+ current_paint_fragment_ = root_paint_fragment_->FirstChild();
return;
}
- MoveToNextItemSkippingChildren();
+ if (IsItemCursor()) {
+ MoveToItem(items_.begin());
+ return;
+ }
+ NOTREACHED();
}
-void NGInlineCursor::MoveToNextItem() {
- DCHECK((items_.data() || !items_.size()) && !root_paint_fragment_);
+void NGInlineCursor::MoveToFirstChild() {
+ DCHECK(CanHaveChildren());
+ if (!TryToMoveToFirstChild())
+ MakeNull();
+}
+
+void NGInlineCursor::MoveToLastChild() {
+ DCHECK(CanHaveChildren());
+ if (!TryToMoveToLastChild())
+ MakeNull();
+}
+
+void NGInlineCursor::MoveToLastLogicalLeaf() {
+ DCHECK(IsLineBox());
+ // TODO(yosin): This isn't correct for mixed Bidi. Fix it. Besides, we
+ // should compute and store it during layout.
+ // TODO(yosin): We should check direction of each container instead of line
+ // box. See also |NGPhysicalLineBoxFragment::LastLogicalLeaf()|.
+ if (IsLtr(CurrentStyle().Direction())) {
+ while (TryToMoveToLastChild())
+ continue;
+ return;
+ }
+ while (TryToMoveToFirstChild())
+ continue;
+}
+
+void NGInlineCursor::MoveToNext() {
+ if (root_paint_fragment_)
+ return MoveToNextPaintFragment();
+ MoveToNextItem();
+}
+
+void NGInlineCursor::MoveToNextForSameLayoutObject() {
+ if (layout_inline_) {
+ // Move to next fragment in culled inline box undef |layout_inline_|.
+ do {
+ MoveToNext();
+ } while (IsNotNull() && !IsPartOfCulledInlineBox(*layout_inline_));
+ return;
+ }
+ if (current_paint_fragment_) {
+ if (auto* paint_fragment =
+ current_paint_fragment_->NextForSameLayoutObject()) {
+ // |paint_fragment| can be in another fragment tree rooted by
+ // |root_paint_fragment_|, e.g. "multicol-span-all-restyle-002.html"
+ root_paint_fragment_ = paint_fragment->Root();
+ return MoveTo(*paint_fragment);
+ }
+ return MakeNull();
+ }
if (current_item_) {
- DCHECK(item_iter_ != items_.end());
- ++item_iter_;
- current_item_ = item_iter_ != items_.end() ? item_iter_->get() : nullptr;
+ const LayoutObject* const layout_object = CurrentLayoutObject();
+ DCHECK(layout_object);
+ do {
+ MoveToNextItem();
+ } while (current_item_ && CurrentLayoutObject() != layout_object);
+ return;
+ }
+}
+
+void NGInlineCursor::MoveToNextSibling() {
+ if (current_paint_fragment_)
+ return MoveToNextSiblingPaintFragment();
+ return MoveToNextSiblingItem();
+}
+
+void NGInlineCursor::MoveToNextSkippingChildren() {
+ if (root_paint_fragment_)
+ return MoveToNextPaintFragmentSkippingChildren();
+ MoveToNextItemSkippingChildren();
+}
+
+bool NGInlineCursor::TryToMoveToFirstChild() {
+ if (!HasChildren())
+ return false;
+ if (root_paint_fragment_) {
+ MoveTo(*current_paint_fragment_->FirstChild());
+ return true;
+ }
+ MoveToItem(item_iter_ + 1);
+ return true;
+}
+
+bool NGInlineCursor::TryToMoveToLastChild() {
+ if (!HasChildren())
+ return false;
+ if (root_paint_fragment_) {
+ MoveTo(current_paint_fragment_->Children().back());
+ return true;
+ }
+ const auto end = item_iter_ + CurrentItem()->DescendantsCount();
+ MoveToNextItem();
+ DCHECK(!IsNull());
+ for (auto it = item_iter_ + 1; it != end; ++it) {
+ if (CurrentItem()->HasSameParent(**it))
+ MoveToItem(it);
}
+ return true;
+}
+
+void NGInlineCursor::MoveToNextItem() {
+ DCHECK(IsItemCursor());
+ if (UNLIKELY(!current_item_))
+ return;
+ DCHECK(item_iter_ != items_.end());
+ ++item_iter_;
+ MoveToItem(item_iter_);
}
void NGInlineCursor::MoveToNextItemSkippingChildren() {
- DCHECK((items_.data() || !items_.size()) && !root_paint_fragment_);
+ DCHECK(IsItemCursor());
if (UNLIKELY(!current_item_))
return;
- // If the current item has |ChildrenCount|, add it to move to the next
+ // If the current item has |DescendantsCount|, add it to move to the next
// sibling, skipping all children and their descendants.
- if (wtf_size_t children_count = current_item_->ChildrenCount()) {
- MoveToItem(item_iter_ + children_count);
- return;
- }
+ if (wtf_size_t descendants_count = current_item_->DescendantsCount())
+ return MoveToItem(item_iter_ + descendants_count);
return MoveToNextItem();
}
+void NGInlineCursor::MoveToNextSiblingItem() {
+ DCHECK(IsItemCursor());
+ if (UNLIKELY(!current_item_))
+ return;
+ const NGFragmentItem& item = *CurrentItem();
+ MoveToNextItemSkippingChildren();
+ if (IsNull() || item.HasSameParent(*CurrentItem()))
+ return;
+ MakeNull();
+}
+
+void NGInlineCursor::MoveToPreviousItem() {
+ DCHECK(IsItemCursor());
+ if (UNLIKELY(!current_item_))
+ return;
+ if (item_iter_ == items_.begin())
+ return MakeNull();
+ --item_iter_;
+ current_item_ = item_iter_->get();
+}
+
void NGInlineCursor::MoveToParentPaintFragment() {
- DCHECK(root_paint_fragment_ && current_paint_fragment_);
+ DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
const NGPaintFragment* parent = current_paint_fragment_->Parent();
if (parent && parent != root_paint_fragment_) {
current_paint_fragment_ = parent;
@@ -150,7 +557,7 @@ void NGInlineCursor::MoveToParentPaintFragment() {
}
void NGInlineCursor::MoveToNextPaintFragment() {
- DCHECK(root_paint_fragment_ && current_paint_fragment_);
+ DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
if (const NGPaintFragment* child = current_paint_fragment_->FirstChild()) {
current_paint_fragment_ = child;
return;
@@ -158,8 +565,8 @@ void NGInlineCursor::MoveToNextPaintFragment() {
MoveToNextPaintFragmentSkippingChildren();
}
-void NGInlineCursor::MoveToNextSibilingPaintFragment() {
- DCHECK(root_paint_fragment_ && current_paint_fragment_);
+void NGInlineCursor::MoveToNextSiblingPaintFragment() {
+ DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
if (const NGPaintFragment* next = current_paint_fragment_->NextSibling()) {
current_paint_fragment_ = next;
return;
@@ -168,8 +575,8 @@ void NGInlineCursor::MoveToNextSibilingPaintFragment() {
}
void NGInlineCursor::MoveToNextPaintFragmentSkippingChildren() {
- DCHECK(root_paint_fragment_ && current_paint_fragment_);
- while (!IsAtEnd()) {
+ DCHECK(IsPaintFragmentCursor() && current_paint_fragment_);
+ while (current_paint_fragment_) {
if (const NGPaintFragment* next = current_paint_fragment_->NextSibling()) {
current_paint_fragment_ = next;
return;
@@ -178,4 +585,21 @@ void NGInlineCursor::MoveToNextPaintFragmentSkippingChildren() {
}
}
+std::ostream& operator<<(std::ostream& ostream, const NGInlineCursor& cursor) {
+ if (cursor.IsNull())
+ return ostream << "NGInlineCursor()";
+ if (cursor.IsPaintFragmentCursor()) {
+ return ostream << "NGInlineCursor(" << *cursor.CurrentPaintFragment()
+ << ")";
+ }
+ DCHECK(cursor.IsItemCursor());
+ return ostream << "NGInlineCursor(" << *cursor.CurrentItem() << ")";
+}
+
+std::ostream& operator<<(std::ostream& ostream, const NGInlineCursor* cursor) {
+ if (!cursor)
+ return ostream << "<null>";
+ return ostream << *cursor;
+}
+
} // namespace blink
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 6468d9d5a0a..99280129efe 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,17 +7,22 @@
#include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
-class LayoutObject;
+class ComputedStyle;
class LayoutBlockFlow;
+class LayoutInline;
+class LayoutObject;
class NGFragmentItem;
class NGFragmentItems;
class NGPaintFragment;
class NGPhysicalBoxFragment;
struct PhysicalOffset;
+struct PhysicalRect;
+struct PhysicalSize;
// This class traverses fragments in an inline formatting context.
//
@@ -30,48 +35,162 @@ class CORE_EXPORT NGInlineCursor {
STACK_ALLOCATED();
public:
- NGInlineCursor(const LayoutBlockFlow& block_flow);
- NGInlineCursor(const NGFragmentItems& items);
- NGInlineCursor(const NGPaintFragment& root_paint_fragment);
+ explicit NGInlineCursor(const LayoutBlockFlow& block_flow);
+ explicit NGInlineCursor(const NGFragmentItems& items);
+ explicit NGInlineCursor(const NGPaintFragment& root_paint_fragment);
+ NGInlineCursor(const NGInlineCursor& other);
+ NGInlineCursor();
+
+ bool operator==(const NGInlineCursor& other) const;
+ bool operator!=(const NGInlineCursor& other) const {
+ return !operator==(other);
+ }
+
+ bool IsItemCursor() const { return fragment_items_; }
+ bool IsPaintFragmentCursor() const { return root_paint_fragment_; }
+
+ const NGFragmentItems& Items() const {
+ DCHECK(fragment_items_);
+ return *fragment_items_;
+ }
+
+ // Returns the |LayoutBlockFlow| containing this cursor.
+ const LayoutBlockFlow* GetLayoutBlockFlow() const;
//
// Functions to query the current position.
//
- bool IsAtEnd() const { return !current_item_ && !current_paint_fragment_; }
- explicit operator bool() const { return !IsAtEnd(); }
+ // Returns true if cursor is out of fragment tree, e.g. before first fragment
+ // or after last fragment in tree.
+ bool IsNull() const { return !current_item_ && !current_paint_fragment_; }
+ bool IsNotNull() const { return !IsNull(); }
+ explicit operator bool() const { return !IsNull(); }
+
+ // True if fragment at the current position can have children.
+ bool CanHaveChildren() const;
- // True if the current position is a line box.
+ // True if fragment at the current position has children.
+ bool HasChildren() const;
+
+ // True if the current position is a atomic inline. It is error to call at
+ // end.
+ bool IsAtomicInline() const;
+
+ // True if the current position is before soft line break. It is error to call
+ // at end.
+ bool IsBeforeSoftLineBreak() const;
+
+ // True if the current position is an ellipsis. It is error to call at end.
+ bool IsEllipsis() const;
+
+ // True if the current position is hidden for paint. It is error to call at
+ // end.
+ bool IsHiddenForPaint() const;
+
+ // True if the current position is a line box. It is error to call at end.
bool IsLineBox() const;
+ // True if the current position is a line break. It is error to call at end.
+ bool IsLineBreak() const;
+
// |Current*| functions return an object for the current position.
const NGFragmentItem* CurrentItem() const { return current_item_; }
const NGPaintFragment* CurrentPaintFragment() const {
return current_paint_fragment_;
}
+ // Returns text direction of current line. It is error to call at other than
+ // line.
+ TextDirection CurrentBaseDirection() const;
const NGPhysicalBoxFragment* CurrentBoxFragment() const;
const LayoutObject* CurrentLayoutObject() const;
+ // Returns text direction of current text or atomic inline. It is error to
+ // call at other than text or atomic inline. Note: <span> doesn't have
+ // reserved direction.
+ TextDirection CurrentResolvedDirection() const;
+ const ComputedStyle& CurrentStyle() const;
// The offset relative to the root of the inline formatting context.
const PhysicalOffset CurrentOffset() const;
+ const PhysicalRect CurrentRect() const;
+ const PhysicalSize CurrentSize() const;
+
+ // Returns start/end of offset in text content of current text fragment.
+ // It is error when this cursor doesn't point to text fragment.
+ unsigned CurrentTextStartOffset() const;
+ unsigned CurrentTextEndOffset() const;
//
// Functions to move the current position.
//
- // Move the current position to the next fragment in pre-order DFS. Returns
- // |true| if the move was successful.
+ // Move the current posint at |paint_fragment|.
+ void MoveTo(const NGPaintFragment& paint_fragment);
+
+ // Move to first |NGFragmentItem| or |NGPaintFragment| associated to
+ // |layout_object|. When |layout_object| has no associated fragments, this
+ // cursor points nothing.
+ void MoveTo(const LayoutObject& layout_object);
+
+ // Move to containing line box. It is error if the current position is line.
+ void MoveToContainingLine();
+
+ // Move to first child of current container box. If the current position is
+ // at fragment without children, this cursor points nothing.
+ // See also |TryToMoveToFirstChild()|.
+ void MoveToFirstChild();
+
+ // Move to last child of current container box. If the current position is
+ // at fragment without children, this cursor points nothing.
+ // See also |TryToMoveToFirstChild()|.
+ void MoveToLastChild();
+
+ // Move to last logical leaf of current line box. If current line box has
+ // no children, curosr becomes null.
+ void MoveToLastLogicalLeaf();
+
+ // Move the current position to the next fragment in pre-order DFS. When
+ // the current position is at last fragment, this cursor points nothing.
void MoveToNext();
+ // Move the current position to next fragment on same layout object.
+ void MoveToNextForSameLayoutObject();
+
+ // Move the current position to next sibling fragment.
+ void MoveToNextSibling();
+
// Same as |MoveToNext| except that this skips children even if they exist.
void MoveToNextSkippingChildren();
+ // Returns true if the current position moves to first child.
+ bool TryToMoveToFirstChild();
+
+ // Returns true if the current position moves to last child.
+ bool TryToMoveToLastChild();
+
// TODO(kojii): Add more variations as needed, NextSibling,
// NextSkippingChildren, Previous, etc.
private:
using ItemsSpan = base::span<const std::unique_ptr<NGFragmentItem>>;
+ // True if current position is part of culled inline box |layout_inline|.
+ bool IsPartOfCulledInlineBox(const LayoutInline& layout_inline) const;
+
+ // True if the current position is a last line in inline block. It is error
+ // to call at end or the current position is not line.
+ bool IsLastLineInInlineBlock() const;
+
+ // Make the current position points nothing, e.g. cursor moves over start/end
+ // fragment, cursor moves to first/last child to parent has no children.
+ void MakeNull();
+
+ // Move the cursor position to the first fragment in tree.
+ void MoveToFirst();
+
+ // Same as |MoveTo()| but not support culled inline.
+ void InternalMoveTo(const LayoutObject& layout_object);
+
void SetRoot(const NGFragmentItems& items);
void SetRoot(ItemsSpan items);
void SetRoot(const NGPaintFragment& root_paint_fragment);
@@ -79,20 +198,29 @@ class CORE_EXPORT NGInlineCursor {
void MoveToItem(const ItemsSpan::iterator& iter);
void MoveToNextItem();
void MoveToNextItemSkippingChildren();
+ void MoveToNextSiblingItem();
+ void MoveToPreviousItem();
void MoveToParentPaintFragment();
void MoveToNextPaintFragment();
- void MoveToNextSibilingPaintFragment();
+ void MoveToNextSiblingPaintFragment();
void MoveToNextPaintFragmentSkippingChildren();
ItemsSpan items_;
ItemsSpan::iterator item_iter_;
const NGFragmentItem* current_item_ = nullptr;
+ const NGFragmentItems* fragment_items_ = nullptr;
const NGPaintFragment* root_paint_fragment_ = nullptr;
const NGPaintFragment* current_paint_fragment_ = nullptr;
+
+ // Used in |MoveToNextForSameLayoutObject()| to support culled inline.
+ const LayoutInline* layout_inline_ = nullptr;
};
+CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGInlineCursor&);
+CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGInlineCursor*);
+
} // namespace blink
#endif // 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_inline_cursor_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
index dc23eb46ed4..b09bb84116a 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
@@ -7,6 +7,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
namespace blink {
@@ -20,18 +21,31 @@ class NGInlineCursorTest : public NGLayoutTest,
NGInlineCursorTest() : ScopedLayoutNGFragmentItemForTest(GetParam()) {}
protected:
- Vector<String> ToDebugStringList(NGInlineCursor* cursor) {
+ NGInlineCursor SetupCursor(const String& html) {
+ SetBodyInnerHTML(html);
+ const LayoutBlockFlow& block_flow =
+ *To<LayoutBlockFlow>(GetLayoutObjectByElementId("root"));
+ return NGInlineCursor(block_flow);
+ }
+
+ Vector<String> ToDebugStringList(const NGInlineCursor& start) {
Vector<String> list;
- for (; *cursor; cursor->MoveToNext())
- list.push_back(ToDebugString(*cursor));
+ for (NGInlineCursor cursor(start); cursor; cursor.MoveToNext())
+ list.push_back(ToDebugString(cursor));
return list;
}
String ToDebugString(const NGInlineCursor& cursor) {
+ const String text_content =
+ cursor.GetLayoutBlockFlow()->GetNGInlineNodeData()->text_content;
if (const LayoutObject* layout_object = cursor.CurrentLayoutObject()) {
- if (const LayoutText* text = ToLayoutTextOrNull(layout_object))
- return text->GetText().StripWhiteSpace();
-
+ if (layout_object->IsText()) {
+ return text_content
+ .Substring(
+ cursor.CurrentTextStartOffset(),
+ cursor.CurrentTextEndOffset() - cursor.CurrentTextStartOffset())
+ .StripWhiteSpace();
+ }
if (const Element* element =
DynamicTo<Element>(layout_object->GetNode())) {
if (const AtomicString& id = element->GetIdAttribute())
@@ -51,6 +65,131 @@ INSTANTIATE_TEST_SUITE_P(NGInlineCursorTest,
NGInlineCursorTest,
testing::Bool());
+TEST_P(NGInlineCursorTest, ContainingLine) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root>abc<a id=target>def</a>ghi<br>xyz</div>");
+ const LayoutBlockFlow& block_flow = *cursor.GetLayoutBlockFlow();
+ NGInlineCursor line1(cursor);
+ ASSERT_TRUE(line1.IsLineBox());
+
+ NGInlineCursor line2(line1);
+ line2.MoveToNextSibling();
+ ASSERT_TRUE(line2.IsLineBox());
+
+ cursor.MoveTo(*block_flow.FirstChild());
+ cursor.MoveToContainingLine();
+ EXPECT_EQ(line1, cursor);
+
+ const LayoutInline& target =
+ ToLayoutInline(*GetLayoutObjectByElementId("target"));
+ cursor.MoveTo(target);
+ cursor.MoveToContainingLine();
+ EXPECT_EQ(line1, cursor);
+
+ cursor.MoveTo(*target.FirstChild());
+ cursor.MoveToContainingLine();
+ EXPECT_EQ(line1, cursor);
+
+ cursor.MoveTo(*block_flow.LastChild());
+ cursor.MoveToContainingLine();
+ EXPECT_EQ(line2, cursor);
+}
+
+TEST_P(NGInlineCursorTest, CulledInlineWithAtomicInline) {
+ SetBodyInnerHTML(
+ "<div id=root>"
+ "<b id=culled>abc<div style=display:inline>ABC<br>XYZ</div>xyz</b>"
+ "</div>");
+ NGInlineCursor cursor;
+ cursor.MoveTo(*GetLayoutObjectByElementId("culled"));
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextForSameLayoutObject();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "ABC", "", "XYZ", "xyz"));
+}
+
+// For https://crbug.com/1026022
+TEST_P(NGInlineCursorTest, CulledInlineWithFloat) {
+ SetBodyInnerHTML(
+ "<div id=root>"
+ "<b id=culled>abc<div style=float:right></div>xyz</b>"
+ "</div>");
+ NGInlineCursor cursor;
+ cursor.MoveTo(*GetLayoutObjectByElementId("culled"));
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextForSameLayoutObject();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "xyz"))
+ << "We should not have float:right fragment, because it isn't in-flow in "
+ "an inline formatting context.";
+}
+
+TEST_P(NGInlineCursorTest, CulledInlineWithRoot) {
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root><a><b>abc</b><br><i>xyz</i></a></div>");
+ const LayoutInline& layout_inline =
+ ToLayoutInline(*cursor.GetLayoutBlockFlow()->FirstChild());
+ cursor.MoveTo(layout_inline);
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextForSameLayoutObject();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "", "xyz"));
+}
+
+TEST_P(NGInlineCursorTest, FirstChild) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root>abc<a>DEF<b>GHI</b></a>xyz</div>");
+ cursor.MoveToFirstChild();
+ EXPECT_EQ("abc", ToDebugString(cursor));
+ EXPECT_FALSE(cursor.TryToMoveToFirstChild());
+}
+
+TEST_P(NGInlineCursorTest, FirstChild2) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor = SetupCursor(
+ "<div id=root><b id=first>abc</b><a>DEF<b>GHI</b></a><a "
+ "id=last>xyz</a></div>");
+ cursor.MoveToFirstChild();
+ EXPECT_EQ("#first", ToDebugString(cursor));
+ cursor.MoveToFirstChild();
+ EXPECT_EQ("abc", ToDebugString(cursor));
+ EXPECT_FALSE(cursor.TryToMoveToFirstChild());
+}
+
+TEST_P(NGInlineCursorTest, LastChild) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root>abc<a>DEF<b>GHI</b></a>xyz</div>");
+ cursor.MoveToLastChild();
+ EXPECT_EQ("xyz", ToDebugString(cursor));
+ EXPECT_FALSE(cursor.TryToMoveToLastChild());
+}
+
+TEST_P(NGInlineCursorTest, LastChild2) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor = SetupCursor(
+ "<div id=root><b id=first>abc</b><a>DEF<b>GHI</b></a>"
+ "<a id=last>xyz</a></div>");
+ cursor.MoveToLastChild();
+ EXPECT_EQ("#last", ToDebugString(cursor));
+ cursor.MoveToLastChild();
+ EXPECT_EQ("xyz", ToDebugString(cursor));
+ EXPECT_FALSE(cursor.TryToMoveToLastChild());
+}
+
TEST_P(NGInlineCursorTest, Next) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -72,16 +211,69 @@ TEST_P(NGInlineCursorTest, Next) {
LayoutBlockFlow* block_flow =
To<LayoutBlockFlow>(GetLayoutObjectByElementId("root"));
NGInlineCursor cursor(*block_flow);
- Vector<String> list = ToDebugStringList(&cursor);
+ Vector<String> list = ToDebugStringList(cursor);
EXPECT_THAT(list, ElementsAre("#linebox", "text1", "#span1", "text2",
"#span2", "text3", "text4", "text5"));
}
+TEST_P(NGInlineCursorTest, NextWithImage) {
+ NGInlineCursor cursor = SetupCursor("<div id=root>abc<img id=img>xyz</div>");
+ Vector<String> list = ToDebugStringList(cursor);
+ EXPECT_THAT(list, ElementsAre("#linebox", "abc", "#img", "xyz"));
+}
+
+TEST_P(NGInlineCursorTest, NextWithInlineBox) {
+ InsertStyleElement("b { display: inline-block; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root>abc<b id=ib>def</b>xyz</div>");
+ Vector<String> list = ToDebugStringList(cursor);
+ EXPECT_THAT(list, ElementsAre("#linebox", "abc", "#ib", "xyz"));
+}
+
+TEST_P(NGInlineCursorTest, NextForSameLayoutObject) {
+ NGInlineCursor cursor = SetupCursor("<pre id=root>abc\ndef\nghi</pre>");
+ cursor.MoveTo(*GetLayoutObjectByElementId("root")->SlowFirstChild());
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextForSameLayoutObject();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "", "def", "", "ghi"));
+}
+
+TEST_P(NGInlineCursorTest, NextSibling) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root>abc<a>DEF<b>GHI</b></a>xyz</div>");
+ cursor.MoveToFirstChild(); // go to "abc"
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextSibling();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "LayoutInline A", "xyz"));
+}
+
+TEST_P(NGInlineCursorTest, NextSibling2) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("a, b { background: gray; }");
+ NGInlineCursor cursor =
+ SetupCursor("<div id=root><a>abc<b>def</b>xyz</a></div>");
+ cursor.MoveToFirstChild(); // go to <a>abc</a>
+ cursor.MoveToFirstChild(); // go to "abc"
+ Vector<String> list;
+ while (cursor) {
+ list.push_back(ToDebugString(cursor));
+ cursor.MoveToNextSibling();
+ }
+ EXPECT_THAT(list, ElementsAre("abc", "LayoutInline B", "xyz"));
+}
+
TEST_P(NGInlineCursorTest, NextSkippingChildren) {
+ // TDOO(yosin): Remove <style> once NGFragmentItem don't do culled inline.
+ InsertStyleElement("span { background: gray; }");
SetBodyInnerHTML(R"HTML(
- <style>
- span { background: gray; }
- </style>
<div id=root>
text1
<span id="span1">
@@ -121,7 +313,7 @@ TEST_P(NGInlineCursorTest, EmptyOutOfFlow) {
LayoutBlockFlow* block_flow =
To<LayoutBlockFlow>(GetLayoutObjectByElementId("root"));
NGInlineCursor cursor(*block_flow);
- Vector<String> list = ToDebugStringList(&cursor);
+ Vector<String> list = ToDebugStringList(cursor);
EXPECT_THAT(list, ElementsAre());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
index e2ec8c64b45..c286b791881 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
@@ -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 NGInlineFragmentTraversal_h
-#define NGInlineFragmentTraversal_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_FRAGMENT_TRAVERSAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_FRAGMENT_TRAVERSAL_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
@@ -42,4 +42,4 @@ class CORE_EXPORT NGInlineFragmentTraversal {
} // namespace blink
-#endif // NGInlineFragmentTraversal_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_FRAGMENT_TRAVERSAL_H_
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 0ae66308706..018e02db8d5 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
@@ -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 NGInlineItem_h
-#define NGInlineItem_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
@@ -297,4 +297,4 @@ struct CORE_EXPORT NGInlineItemsData {
} // namespace blink
-#endif // NGInlineItem_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_H_
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 95ba2a64962..c55dfae46de 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
@@ -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 NGInlineItemResult_h
-#define NGInlineItemResult_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_RESULT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_RESULT_H_
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
@@ -284,4 +284,4 @@ class CORE_EXPORT NGLineInfo {
} // namespace blink
-#endif // NGInlineItemResult_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_RESULT_H_
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 07abca2e18b..8b0939aa096 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
@@ -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 NGInlineItemsBuilder_h
-#define NGInlineItemsBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_BUILDER_H_
+#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/ng/inline/empty_offset_mapping_builder.h"
@@ -263,4 +263,4 @@ using NGInlineItemsBuilderForOffsetMapping =
} // namespace blink
-#endif // NGInlineItemsBuilder_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEMS_BUILDER_H_
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 39612fa1c01..a3558995e0e 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
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/containers/adapters.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.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"
@@ -533,11 +534,13 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
// object is placed on, we need to keep track of if there is any inline-level
// content preceeding it.
bool has_preceding_inline_level_content = false;
+ bool has_rtl_block_level_out_of_flow_objects = false;
+ bool is_ltr = IsLtr(line_info.BaseDirection());
for (NGLineBoxFragmentBuilder::Child& child : line_box_) {
has_preceding_inline_level_content |= child.HasInFlowFragment();
- LayoutObject* box = child.out_of_flow_positioned_box;
+ const LayoutObject* box = child.out_of_flow_positioned_box;
if (!box)
continue;
@@ -557,14 +560,35 @@ void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
container_builder_.AddAdjoiningObjectTypes(kAdjoiningInlineOutOfFlow);
} else {
// A block-level OOF element positions itself on the "next" line. However
- // only shifts down if there is inline-level content.
+ // only shifts down if there is preceding inline-level content.
static_offset.inline_offset = block_level_inline_offset;
- if (has_preceding_inline_level_content)
- static_offset.block_offset += line_height;
+ if (is_ltr) {
+ if (has_preceding_inline_level_content)
+ static_offset.block_offset += line_height;
+ } else {
+ // "Preceding" is in logical order, but this loop is in visual order. In
+ // RTL, move objects down in the reverse-order loop below.
+ has_rtl_block_level_out_of_flow_objects = true;
+ }
}
child.offset = static_offset;
}
+
+ if (UNLIKELY(has_rtl_block_level_out_of_flow_objects)) {
+ has_preceding_inline_level_content = false;
+ for (NGLineBoxFragmentBuilder::Child& child : base::Reversed(line_box_)) {
+ const LayoutObject* box = child.out_of_flow_positioned_box;
+ if (!box) {
+ has_preceding_inline_level_content |= child.HasInFlowFragment();
+ continue;
+ }
+ if (has_preceding_inline_level_content &&
+ !box->StyleRef().IsOriginalDisplayInlineType()) {
+ child.offset.block_offset += line_height;
+ }
+ }
+ }
}
void NGInlineLayoutAlgorithm::PlaceFloatingObjects(
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 4b7c45e4a14..6fe33fe9220 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
@@ -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 NGInlineLayoutAlgorithm_h
-#define NGInlineLayoutAlgorithm_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_LAYOUT_ALGORITHM_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
@@ -123,4 +123,4 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
} // namespace blink
-#endif // NGInlineLayoutAlgorithm_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_LAYOUT_ALGORITHM_H_
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 e055e19d365..7e371d0776a 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
@@ -209,7 +209,6 @@ class ReusingTextShaper final {
return item.EndOffset() <= offset;
});
item != reusable_items_->end(); ++item) {
- DCHECK_LE(start_offset, item->StartOffset());
if (end_offset <= item->StartOffset())
break;
if (item->EndOffset() < start_offset)
@@ -399,7 +398,10 @@ inline bool ShouldBreakShapingAfterBox(const NGInlineItem& item,
}
inline bool NeedsShaping(const NGInlineItem& item) {
- return item.Type() == NGInlineItem::kText && !item.TextShapeResult();
+ return item.Type() == NGInlineItem::kText && !item.TextShapeResult() &&
+ // Text item with length==0 exists to maintain LayoutObject states such
+ // as ClearNeedsLayout, but not needed to shape.
+ item.Length();
}
// Determine if reshape is needed for ::first-line style.
@@ -478,7 +480,7 @@ void NGInlineNode::PrepareLayout(
DCHECK(data);
CollectInlines(data, previous_data.get(), dirty_lines);
SegmentText(data);
- ShapeText(data, &previous_data->text_content);
+ ShapeText(data, previous_data ? &previous_data->text_content : nullptr);
ShapeTextForFirstLineIfNeeded(data);
AssociateItemsWithInlines(data);
DCHECK_EQ(data, MutableData());
@@ -615,7 +617,6 @@ class NGInlineNodeDataEditor final {
// Copy items after replaced range
++it;
while (it != data_->items.end()) {
- DCHECK_NE(it->layout_object_, layout_text_);
DCHECK_LE(end_offset, it->start_offset_);
items.push_back(*it);
ShiftItem(&items.back(), diff);
@@ -1161,9 +1162,9 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data,
// If the text is from multiple items, split the ShapeResult to
// corresponding items.
DCHECK_GT(num_text_items, 0u);
- std::unique_ptr<ShapeResult::ShapeRange[]> text_item_ranges =
- std::make_unique<ShapeResult::ShapeRange[]>(num_text_items);
- unsigned range_index = 0;
+ // "32" is heuristic, most major sites are up to 8 or so, wikipedia is 21.
+ Vector<ShapeResult::ShapeRange, 32> text_item_ranges;
+ text_item_ranges.ReserveInitialCapacity(num_text_items);
for (; index < end_index; index++) {
NGInlineItem& item = (*items)[index];
if (item.Type() != NGInlineItem::kText || !item.Length())
@@ -1177,12 +1178,12 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data,
// item that has its first code unit keeps the glyph.
scoped_refptr<ShapeResult> item_result =
ShapeResult::CreateEmpty(*shape_result.get());
- item.shape_result_ = item_result;
- text_item_ranges[range_index++] = {item.StartOffset(), item.EndOffset(),
- item_result.get()};
+ text_item_ranges.emplace_back(item.StartOffset(), item.EndOffset(),
+ item_result.get());
+ item.shape_result_ = std::move(item_result);
}
- DCHECK_EQ(range_index, num_text_items);
- shape_result->CopyRanges(&text_item_ranges[0], num_text_items);
+ DCHECK_EQ(text_item_ranges.size(), num_text_items);
+ shape_result->CopyRanges(text_item_ranges.data(), text_item_ranges.size());
}
#if DCHECK_IS_ON()
@@ -1691,21 +1692,25 @@ static LayoutUnit ComputeContentSize(
MaxSizeFromMinSize max_size_from_min_size(items_data, *max_size_cache,
&floats_max_size);
- Vector<LayoutObject*> floats_for_min_max;
do {
- floats_for_min_max.Shrink(0);
-
NGLineInfo line_info;
- line_breaker.NextLine(input.percentage_resolution_block_size,
- &floats_for_min_max, &line_info);
+ line_breaker.NextLine(input.percentage_resolution_block_size, &line_info);
if (line_info.Results().IsEmpty())
break;
LayoutUnit inline_size = line_info.Width();
- DCHECK_EQ(inline_size, line_info.ComputeWidth().ClampNegativeToZero());
-
- for (auto* floating_object : floats_for_min_max) {
- DCHECK(floating_object->IsFloating());
+ // Text measurement is done using floats which may introduce small rounding
+ // errors for near-saturated values.
+ DCHECK_EQ(inline_size.Round(),
+ line_info.ComputeWidth().ClampNegativeToZero().Round());
+
+ for (const NGInlineItemResult& item_result : line_info.Results()) {
+ DCHECK(item_result.item);
+ const NGInlineItem& item = *item_result.item;
+ if (item.Type() != NGInlineItem::kFloating)
+ continue;
+ LayoutObject* floating_object = item.GetLayoutObject();
+ DCHECK(floating_object && floating_object->IsFloating());
NGBlockNode float_node(ToLayoutBox(floating_object));
const ComputedStyle& float_style = float_node.Style();
@@ -1735,11 +1740,17 @@ static LayoutUnit ComputeContentSize(
if (mode == NGLineBreakerMode::kMinContent) {
*max_size_out = max_size_from_min_size.Finish(items_data.items.end());
// Check the max size matches to the value computed from 2 pass.
- DCHECK_EQ(**max_size_out,
- ComputeContentSize(node, container_writing_mode, input,
- NGLineBreakerMode::kMaxContent, max_size_cache,
- nullptr))
- << node.GetLayoutBox();
+#if DCHECK_IS_ON()
+ LayoutUnit content_size = ComputeContentSize(
+ node, container_writing_mode, input, NGLineBreakerMode::kMaxContent,
+ max_size_cache, nullptr);
+ bool values_might_be_saturated =
+ (*max_size_out)->MightBeSaturated() || content_size.MightBeSaturated();
+ if (!values_might_be_saturated) {
+ DCHECK_EQ((*max_size_out)->Round(), content_size.Round())
+ << node.GetLayoutBox();
+ }
+#endif
}
return result;
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 318a6cefa28..ddb8325722d 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
@@ -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 NGInlineNode_h
-#define NGInlineNode_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
@@ -202,4 +202,4 @@ struct DowncastTraits<NGInlineNode> {
} // namespace blink
-#endif // NGInlineNode_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_H_
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 b7c04d46b10..1db462747a4 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
@@ -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 NGInlineNodeData_h
-#define NGInlineNodeData_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_DATA_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_DATA_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h"
@@ -68,4 +68,4 @@ struct CORE_EXPORT NGInlineNodeData : NGInlineItemsData {
} // namespace blink
-#endif // NGInlineNode_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_NODE_DATA_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment.h
index 3625e414f85..b1a43d80a0d 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment.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 NGLineBoxFragment_h
-#define NGLineBoxFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -29,4 +29,4 @@ struct DowncastTraits<NGLineBoxFragment> {
} // namespace blink
-#endif // NGLineBoxFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_H_
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 206b6163dbc..3317ee87996 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
@@ -26,7 +26,7 @@ void NGLineBoxFragmentBuilder::Reset() {
metrics_ = NGLineHeightMetrics();
line_box_type_ = NGPhysicalLineBoxFragment::kNormalLineBox;
- has_last_resort_break_ = false;
+ break_appeal_ = kBreakAppealPerfect;
has_floating_descendants_ = false;
has_orthogonal_flow_roots_ = false;
has_descendant_that_depends_on_percentage_block_size_ = false;
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 80aaf47eba1..d7320ddcdc0 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
@@ -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 NGLineBoxFragmentBuilder_h
-#define NGLineBoxFragmentBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_BUILDER_H_
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
@@ -195,7 +195,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
public:
ChildList() = default;
- void operator=(ChildList&& other) noexcept {
+ void operator=(ChildList&& other) {
children_ = std::move(other.children_);
}
@@ -278,4 +278,4 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
blink::NGLineBoxFragmentBuilder::Child)
-#endif // NGLineBoxFragmentBuilder
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BOX_FRAGMENT_BUILDER_H_
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 c3cd893ac35..d08ea840567 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
+#include "base/containers/adapters.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"
@@ -31,6 +32,26 @@ inline bool IsBreakableSpace(UChar c) {
return c == kSpaceCharacter || c == kTabulationCharacter;
}
+inline bool IsAllBreakableSpaces(const String& string,
+ unsigned start,
+ unsigned end) {
+ DCHECK_GE(end, start);
+ return StringView(string, start, end - start)
+ .IsAllSpecialCharacters<IsBreakableSpace>();
+}
+
+// True if the item is "trailable". Trailable items should be included in the
+// line if they are after the soft wrap point.
+//
+// Note that some items are ambiguous; e.g., text is trailable if it has leading
+// spaces, and open tags are trailable if spaces follow. This function returns
+// true for such cases.
+inline bool IsTrailableItemType(NGInlineItem::NGInlineItemType type) {
+ return type != NGInlineItem::kAtomicInline &&
+ type != NGInlineItem::kOutOfFlowPositioned &&
+ type != NGInlineItem::kListMarker;
+}
+
inline bool CanBreakAfterLast(const NGInlineItemResults& item_results) {
return !item_results.IsEmpty() && item_results.back().can_break_after;
}
@@ -75,6 +96,12 @@ inline void ComputeCanBreakAfter(NGInlineItemResult* item_result,
auto_wrap && break_iterator.IsBreakable(item_result->end_offset);
}
+inline void RemoveLastItem(NGLineInfo* line_info) {
+ NGInlineItemResults* item_results = line_info->MutableResults();
+ DCHECK_GT(item_results->size(), 0u);
+ item_results->Shrink(item_results->size() - 1);
+}
+
// To correctly determine if a float is allowed to be on the same line as its
// content, we need to determine if it has any ancestors with inline-end
// padding, border, or margin.
@@ -172,16 +199,31 @@ NGLineBreaker::NGLineBreaker(NGInlineNode node,
available_width_ = ComputeAvailableWidth();
break_iterator_.SetBreakSpace(BreakSpaceType::kBeforeSpaceRun);
- if (break_token) {
- item_index_ = break_token->ItemIndex();
- offset_ = break_token->TextOffset();
- break_iterator_.SetStartOffset(offset_);
- is_after_forced_break_ = break_token->IsForcedBreak();
- items_data_.AssertOffset(item_index_, offset_);
- // TODO(crbug.com/1013040): |break_token->Style()| should not be nullptr.
- if (const ComputedStyle* line_initial_style = break_token->Style())
- SetCurrentStyle(*line_initial_style);
+ if (!break_token)
+ return;
+
+ const ComputedStyle* line_initial_style = break_token->Style();
+ if (UNLIKELY(!line_initial_style)) {
+ // Usually an inline break token has the line initial style, but class C
+ // breaks and last-resort breaks require a break token to start from the
+ // beginning of the block. In that case, the line is still the first
+ // formatted line, and the line initial style should be computed from the
+ // containing block.
+ DCHECK_EQ(break_token->ItemIndex(), 0u);
+ DCHECK_EQ(break_token->TextOffset(), 0u);
+ DCHECK(!break_token->IsForcedBreak());
+ DCHECK_EQ(item_index_, break_token->ItemIndex());
+ DCHECK_EQ(offset_, break_token->TextOffset());
+ DCHECK_EQ(is_after_forced_break_, break_token->IsForcedBreak());
+ return;
}
+
+ item_index_ = break_token->ItemIndex();
+ offset_ = break_token->TextOffset();
+ break_iterator_.SetStartOffset(offset_);
+ is_after_forced_break_ = break_token->IsForcedBreak();
+ items_data_.AssertOffset(item_index_, offset_);
+ SetCurrentStyle(*line_initial_style);
}
// Define the destructor here, so that we can forward-declare more in the
@@ -191,6 +233,8 @@ NGLineBreaker::~NGLineBreaker() = default;
inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item,
unsigned end_offset,
NGLineInfo* line_info) {
+ DCHECK_GE(offset_, item.StartOffset());
+ DCHECK_GE(end_offset, offset_);
DCHECK_LE(end_offset, item.EndOffset());
NGInlineItemResults* item_results = line_info->MutableResults();
return &item_results->emplace_back(
@@ -203,6 +247,15 @@ inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item,
return AddItem(item, item.EndOffset(), line_info);
}
+// Call |HandleOverflow()| if the position is beyond the available space.
+inline bool NGLineBreaker::HandleOverflowIfNeeded(NGLineInfo* line_info) {
+ if (state_ == LineBreakState::kContinue && !CanFitOnLine()) {
+ HandleOverflow(line_info);
+ return true;
+ }
+ return false;
+}
+
void NGLineBreaker::SetMaxSizeCache(MaxSizeCache* max_size_cache) {
DCHECK_NE(mode_, NGLineBreakerMode::kContent);
DCHECK(max_size_cache);
@@ -248,7 +301,7 @@ void NGLineBreaker::ComputeBaseDirection() {
// Initialize internal states for the next line.
void NGLineBreaker::PrepareNextLine(NGLineInfo* line_info) {
- // NGLineInfo is not supposed to be re-used becase it's not much gain and to
+ // NGLineInfo is not supposed to be re-used because it's not much gain and to
// avoid rare code path.
const NGInlineItemResults& item_results = line_info->Results();
DCHECK(item_results.IsEmpty());
@@ -290,21 +343,14 @@ void NGLineBreaker::PrepareNextLine(NGLineInfo* line_info) {
// regardless of 'text-indent'.
position_ = line_info->TextIndent();
- overflow_item_index_ = 0;
+ ResetRewindLoopDetector();
}
void NGLineBreaker::NextLine(
LayoutUnit percentage_resolution_block_size_for_min_max,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo* line_info) {
- // out_floats_for_min_max is required for min/max and prohibited for regular
- // content mode.
- DCHECK(mode_ == NGLineBreakerMode::kContent || out_floats_for_min_max);
- DCHECK(!(mode_ == NGLineBreakerMode::kContent && out_floats_for_min_max));
-
PrepareNextLine(line_info);
- BreakLine(percentage_resolution_block_size_for_min_max,
- out_floats_for_min_max, line_info);
+ BreakLine(percentage_resolution_block_size_for_min_max, line_info);
RemoveTrailingCollapsibleSpace(line_info);
const NGInlineItemResults& item_results = line_info->Results();
@@ -337,28 +383,28 @@ void NGLineBreaker::NextLine(
void NGLineBreaker::BreakLine(
LayoutUnit percentage_resolution_block_size_for_min_max,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo* line_info) {
+ DCHECK(!line_info->IsLastLine());
const Vector<NGInlineItem>& items = Items();
state_ = LineBreakState::kContinue;
trailing_whitespace_ = WhitespaceState::kLeading;
while (state_ != LineBreakState::kDone) {
- // Check overflow even if |item_index_| is at the end of the block, because
- // the last item of the block may have caused overflow. In that case,
- // |HandleOverflow| will rewind |item_index_|.
- if (state_ == LineBreakState::kContinue &&
- position_ > AvailableWidthToFit()) {
- HandleOverflow(line_info);
- }
-
// If we reach at the end of the block, this is the last line.
DCHECK_LE(item_index_, items.size());
if (item_index_ == items.size()) {
+ // Still check overflow because the last item may have overflowed.
+ if (HandleOverflowIfNeeded(line_info) && item_index_ != items.size())
+ continue;
line_info->SetIsLastLine(true);
return;
}
+ // If |state_| is overflow, break at the earliest break opportunity.
const NGInlineItemResults& item_results = line_info->Results();
+ if (UNLIKELY(state_ == LineBreakState::kOverflow &&
+ CanBreakAfterLast(item_results))) {
+ state_ = LineBreakState::kTrailing;
+ }
// Handle trailable items first. These items may not be break before.
// They (or part of them) may also overhang the available width.
@@ -375,9 +421,8 @@ void NGLineBreaker::BreakLine(
continue;
}
if (item.Type() == NGInlineItem::kOpenTag) {
- if (HandleOpenTag(item, line_info))
- continue;
- return;
+ HandleOpenTag(item, line_info);
+ continue;
}
if (item.Type() == NGInlineItem::kCloseTag) {
HandleCloseTag(item, line_info);
@@ -388,7 +433,7 @@ void NGLineBreaker::BreakLine(
continue;
}
if (item.Type() == NGInlineItem::kFloating) {
- HandleFloat(item, out_floats_for_min_max, line_info);
+ HandleFloat(item, line_info);
continue;
}
if (item.Type() == NGInlineItem::kBidiControl) {
@@ -396,11 +441,11 @@ void NGLineBreaker::BreakLine(
continue;
}
- // Items after this point are not trailable. Break at the earliest break
- // opportunity if we're trailing.
- if (state_ == LineBreakState::kTrailing &&
- CanBreakAfterLast(item_results)) {
- line_info->SetIsLastLine(false);
+ // Items after this point are not trailable. If we're trailing, break before
+ // any non-trailable items
+ DCHECK(!IsTrailableItemType(item.Type()));
+ if (state_ == LineBreakState::kTrailing) {
+ DCHECK(!line_info->IsLastLine());
return;
}
@@ -501,16 +546,9 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
DCHECK_EQ(auto_wrap_, item.Style()->AutoWrap());
// If we're trailing, only trailing spaces can be included in this line.
- if (state_ == LineBreakState::kTrailing) {
- if (CanBreakAfterLast(line_info->Results()))
- return HandleTrailingSpaces(item, shape_result, line_info);
- // When a run of preserved spaces are across items, |CanBreakAfterLast| is
- // false for between spaces. But we still need to handle them as trailing
- // spaces.
- const String& text = Text();
- if (auto_wrap_ && offset_ < text.length() &&
- IsBreakableSpace(text[offset_]))
- return HandleTrailingSpaces(item, shape_result, line_info);
+ if (UNLIKELY(state_ == LineBreakState::kTrailing)) {
+ HandleTrailingSpaces(item, shape_result, line_info);
+ return;
}
// Skip leading collapsible spaces.
@@ -532,6 +570,25 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
// |trailing_whitespace_| will be updated as we read the text.
}
+ // Go to |HandleOverflow()| if the last item overflowed, and we're adding
+ // text.
+ if (state_ == LineBreakState::kContinue && !CanFitOnLine()) {
+ // |HandleOverflow()| expects all trailable items are added. If this text
+ // starts with trailable spaces, add them. TODO(kojii): This can be
+ // optimzied further. This is necesasry only if |HandleOverflow()| does not
+ // rewind, but in most cases it will rewind.
+ const String& text = Text();
+ if (auto_wrap_ && IsBreakableSpace(text[offset_])) {
+ HandleTrailingSpaces(item, shape_result, line_info);
+ if (state_ != LineBreakState::kDone) {
+ state_ = LineBreakState::kContinue;
+ return;
+ }
+ }
+ HandleOverflow(line_info);
+ return;
+ }
+
NGInlineItemResult* item_result = AddItem(item, line_info);
item_result->should_create_line_box = true;
@@ -543,32 +600,53 @@ void NGLineBreaker::HandleText(const NGInlineItem& item,
}
// Try to break inside of this text item.
- LayoutUnit available_width = AvailableWidthToFit();
- BreakResult break_result =
- BreakText(item_result, item, shape_result, available_width - position_,
- line_info);
+ BreakResult break_result = BreakText(item_result, item, shape_result,
+ RemainingAvailableWidth(), line_info);
DCHECK(item_result->shape_result ||
(break_result == kOverflow && break_anywhere_if_overflow_ &&
!override_break_anywhere_));
position_ += item_result->inline_size;
- DCHECK_EQ(break_result == kSuccess, position_ <= available_width);
+ DCHECK_EQ(break_result == kSuccess, CanFitOnLine());
MoveToNextOf(*item_result);
- if (break_result == kSuccess ||
- (state_ == LineBreakState::kTrailing && item_result->shape_result)) {
- if (item_result->end_offset < item.EndOffset()) {
- // The break point found, and text follows. Break here, after trailing
- // spaces.
+ if (break_result == kSuccess) {
+ DCHECK(item_result->shape_result);
+
+ // If the break is at the middle of a text item, we know no trailable
+ // items follow, only trailable spaces if any. This is very common that
+ // shortcut to handling trailing spaces.
+ if (item_result->end_offset < item.EndOffset())
return HandleTrailingSpaces(item, shape_result, line_info);
- }
- // The break point found, but items that prohibit breaking before them may
- // follow. Continue looking next items.
+ // The break point found at the end of this text item. Continue looking
+ // next items, because the next item maybe trailable, or can prohibit
+ // breaking before.
return;
}
-
DCHECK_EQ(break_result, kOverflow);
- return HandleOverflow(line_info);
+
+ // Handle `overflow-wrap` if it is enabled and if this text item overflows.
+ if (UNLIKELY(!item_result->shape_result)) {
+ DCHECK(break_anywhere_if_overflow_ && !override_break_anywhere_);
+ HandleOverflow(line_info);
+ return;
+ }
+
+ // If we're seeking for the first break opportunity, update the state.
+ if (UNLIKELY(state_ == LineBreakState::kOverflow)) {
+ if (item_result->can_break_after)
+ state_ = LineBreakState::kTrailing;
+ return;
+ }
+
+ // If this is all trailable spaces, this item is trailable, and next item
+ // maybe too. Don't go to |HandleOverflow()| yet.
+ if (IsAllBreakableSpaces(Text(), item_result->start_offset,
+ item_result->end_offset))
+ return;
+
+ HandleOverflow(line_info);
+ return;
}
// Add until the end of the item if !auto_wrap. In most cases, it's the whole
@@ -734,6 +812,31 @@ NGLineBreaker::BreakResult NGLineBreaker::BreakText(
return inline_size <= available_width ? kSuccess : kOverflow;
}
+// Breaks the text item at the previous break opportunity from
+// |item_result->end_offset|. Returns false if there were no previous break
+// opportunities.
+bool NGLineBreaker::BreakTextAtPreviousBreakOpportunity(
+ NGInlineItemResult* item_result) {
+ DCHECK(item_result->item);
+ DCHECK(item_result->may_break_inside);
+ const NGInlineItem& item = *item_result->item;
+ DCHECK_EQ(item.Type(), NGInlineItem::kText);
+ DCHECK(item.Style() && item.Style()->AutoWrap());
+
+ unsigned break_opportunity = break_iterator_.PreviousBreakOpportunity(
+ item_result->end_offset - 1, item_result->start_offset);
+ if (break_opportunity <= item_result->start_offset)
+ return false;
+ item_result->end_offset = break_opportunity;
+ item_result->shape_result =
+ ShapeResultView::Create(item.TextShapeResult(), item_result->start_offset,
+ item_result->end_offset);
+ item_result->inline_size =
+ item_result->shape_result->SnappedWidth().ClampNegativeToZero();
+ item_result->can_break_after = true;
+ return true;
+}
+
// This function handles text item for min-content. The specialized logic is
// because min-content is very expensive by breaking at every break opportunity
// and producing as many lines as the number of break opportunities.
@@ -910,6 +1013,13 @@ void NGLineBreaker::UpdateShapeResult(const NGLineInfo& line_info,
item_result->inline_size = item_result->shape_result->SnappedWidth();
}
+inline void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
+ NGLineInfo* line_info) {
+ const ShapeResult* shape_result = item.TextShapeResult();
+ DCHECK(shape_result);
+ HandleTrailingSpaces(item, *shape_result, line_info);
+}
+
void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
const ShapeResult& shape_result,
NGLineInfo* line_info) {
@@ -917,6 +1027,7 @@ void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
(item.Type() == NGInlineItem::kControl &&
Text()[item.StartOffset()] == kTabulationCharacter));
DCHECK(&shape_result);
+ DCHECK_GE(offset_, item.StartOffset());
DCHECK_LT(offset_, item.EndOffset());
const String& text = Text();
DCHECK(item.Style());
@@ -984,6 +1095,31 @@ void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item,
// Remove trailing collapsible spaces in |line_info|.
// https://drafts.csswg.org/css-text-3/#white-space-phase-2
void NGLineBreaker::RemoveTrailingCollapsibleSpace(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.
+ // TODO(crbug.com/1009936): Open tags and trailing space items can interleave,
+ // but the current code supports only one trailing space item. Multiple
+ // trailing space items and interleaved open/close tags should be supported.
+ const NGInlineItemResults& item_results = line_info->Results();
+ 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;
+ if (end_index < item_results.size()) {
+ const NGInlineItemResult& end_item_result = item_results[end_index];
+ unsigned end_item_index = end_item_result.item_index;
+ unsigned end_offset = end_item_result.start_offset;
+ ResetRewindLoopDetector();
+ Rewind(end_index, line_info);
+ item_index_ = end_item_index;
+ offset_ = end_offset;
+ items_data_.AssertOffset(item_index_, offset_);
+ }
+ break;
+ }
+ }
+
ComputeTrailingCollapsibleSpace(line_info);
if (!trailing_collapsible_space_.has_value()) {
return;
@@ -1094,6 +1230,10 @@ void NGLineBreaker::HandleControlItem(const NGInlineItem& item,
UChar character = Text()[item.StartOffset()];
switch (character) {
case kNewlineCharacter: {
+ // Check overflow, because the last item may have overflowed.
+ if (HandleOverflowIfNeeded(line_info))
+ return;
+
NGInlineItemResult* item_result = AddItem(item, line_info);
item_result->should_create_line_box = true;
item_result->has_only_trailing_spaces = true;
@@ -1187,7 +1327,7 @@ void NGLineBreaker::HandleBidiControlItem(const NGInlineItem& item,
} else {
if (state_ == LineBreakState::kTrailing &&
CanBreakAfterLast(*item_results)) {
- line_info->SetIsLastLine(false);
+ DCHECK(!line_info->IsLastLine());
MoveToNextOf(item);
state_ = LineBreakState::kDone;
return;
@@ -1206,8 +1346,22 @@ void NGLineBreaker::HandleAtomicInline(
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
+ // Compute margins before computing overflow, because even when the current
+ // position is beyond the end, negative margins can bring this item back to on
+ // the current line.
NGInlineItemResult* item_result = AddItem(item, line_info);
- item_result->should_create_line_box = true;
+ item_result->margins =
+ ComputeLineMarginsForVisualContainer(constraint_space_, style);
+ LayoutUnit inline_margins = item_result->margins.InlineSum();
+ LayoutUnit remaining_width = RemainingAvailableWidth();
+ bool is_overflow_before =
+ state_ == LineBreakState::kContinue && remaining_width < 0;
+ if (UNLIKELY(is_overflow_before && inline_margins > remaining_width)) {
+ RemoveLastItem(line_info);
+ HandleOverflow(line_info);
+ return;
+ }
+
// When we're just computing min/max content sizes, we can skip the full
// layout and just compute those sizes. On the other hand, for regular
// layout we need to do the full layout and get the layout result.
@@ -1223,20 +1377,16 @@ void NGLineBreaker::HandleAtomicInline(
NGFragment(constraint_space_.GetWritingMode(),
item_result->layout_result->PhysicalFragment())
.InlineSize();
- item_result->margins =
- ComputeLineMarginsForVisualContainer(constraint_space_, style);
- item_result->inline_size += item_result->margins.InlineSum();
+ 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(ToLayoutBox(item.GetLayoutObject()));
MinMaxSizeInput input(percentage_resolution_block_size_for_min_max);
MinMaxSize sizes =
ComputeMinAndMaxContentContribution(node_.Style(), child, input);
- LayoutUnit inline_margins =
- ComputeLineMarginsForVisualContainer(constraint_space_, style)
- .InlineSum();
if (mode_ == NGLineBreakerMode::kMinContent) {
item_result->inline_size = sizes.min_size + inline_margins;
if (max_size_cache_) {
@@ -1250,13 +1400,14 @@ void NGLineBreaker::HandleAtomicInline(
}
}
- trailing_whitespace_ = WhitespaceState::kNone;
- position_ += item_result->inline_size;
+ item_result->should_create_line_box = true;
ComputeCanBreakAfter(item_result, auto_wrap_, break_iterator_);
if (!item_result->can_break_after && auto_wrap_ &&
IsAtomicInlineBeforeNoBreakSpace(*item_result))
item_result->can_break_after = true;
+ position_ += item_result->inline_size;
+ trailing_whitespace_ = WhitespaceState::kNone;
MoveToNextOf(item);
}
@@ -1275,7 +1426,6 @@ void NGLineBreaker::HandleAtomicInline(
// allowed to position a float "above" another float which has come before us
// in the document.
void NGLineBreaker::HandleFloat(const NGInlineItem& item,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo* line_info) {
// When rewind occurs, an item may be handled multiple times.
// Since floats are put into a separate list, avoid handling same floats
@@ -1290,13 +1440,10 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
item_result->can_break_after = auto_wrap_;
MoveToNextOf(item);
- // If we are currently computing our min/max-content size simply append to
- // the unpositioned floats list and abort.
- if (mode_ != NGLineBreakerMode::kContent) {
- DCHECK(out_floats_for_min_max);
- out_floats_for_min_max->push_back(item.GetLayoutObject());
+ // If we are currently computing our min/max-content size, simply append the
+ // unpositioned floats to |NGLineInfo| and abort.
+ if (mode_ != NGLineBreakerMode::kContent)
return;
- }
// Make sure we populate the positioned_float inside the |item_result|.
if (item_index_ <= handled_leading_floats_index_ &&
@@ -1376,8 +1523,7 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
bool NGLineBreaker::ComputeOpenTagResult(
const NGInlineItem& item,
const NGConstraintSpace& constraint_space,
- NGInlineItemResult* item_result,
- base::Optional<NGLineBoxStrut> margins) {
+ NGInlineItemResult* item_result) {
DCHECK_EQ(item.Type(), NGInlineItem::kOpenTag);
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
@@ -1388,9 +1534,7 @@ bool NGLineBreaker::ComputeOpenTagResult(
item_result->borders = ComputeLineBorders(style);
item_result->padding = ComputeLinePadding(constraint_space, style);
if (item_result->has_edge) {
- item_result->margins =
- margins ? *margins
- : ComputeLineMarginsForSelf(constraint_space, style);
+ item_result->margins = ComputeLineMarginsForSelf(constraint_space, style);
item_result->inline_size = item_result->margins.inline_start +
item_result->borders.inline_start +
item_result->padding.inline_start;
@@ -1400,39 +1544,23 @@ bool NGLineBreaker::ComputeOpenTagResult(
return false;
}
-bool NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
+void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
NGLineInfo* line_info) {
DCHECK_EQ(item.Type(), NGInlineItem::kOpenTag);
- DCHECK(item.Style());
- const ComputedStyle& style = *item.Style();
-
- // OpenTag is not trailable, except when it has negative inline-start margin,
- // which can bring the position back to inside of the available width.
- base::Optional<NGLineBoxStrut> margins;
- if (UNLIKELY(state_ == LineBreakState::kTrailing &&
- CanBreakAfterLast(line_info->Results()))) {
- bool can_continue = false;
- if (UNLIKELY(item_index_ >= overflow_item_index_ &&
- item.ShouldCreateBoxFragment() && item.HasStartEdge() &&
- style.MayHaveMargin())) {
- margins = ComputeLineMarginsForSelf(constraint_space_, style);
- LayoutUnit inline_start_margin = margins->inline_start;
- can_continue = inline_start_margin < 0 &&
- position_ + inline_start_margin < AvailableWidthToFit();
- }
- if (!can_continue) {
- // Not that case. Break the line before this OpenTag.
- line_info->SetIsLastLine(false);
- return false;
- }
- // The state is back to normal because the position is back to inside of the
- // available width.
- state_ = LineBreakState::kContinue;
- }
NGInlineItemResult* item_result = AddItem(item, line_info);
+ if (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 &&
+ state_ == LineBreakState::kTrailing)) {
+ LayoutUnit available_width = AvailableWidthToFit();
+ if (position_ > available_width &&
+ position_ + item_result->inline_size <= available_width) {
+ state_ = LineBreakState::kContinue;
+ }
+ }
- if (ComputeOpenTagResult(item, constraint_space_, item_result, margins)) {
position_ += item_result->inline_size;
// While the spec defines "non-zero margins, padding, or borders" prevents
@@ -1444,6 +1572,8 @@ bool NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
}
bool was_auto_wrap = auto_wrap_;
+ DCHECK(item.Style());
+ const ComputedStyle& style = *item.Style();
SetCurrentStyle(style);
MoveToNextOf(item);
@@ -1452,7 +1582,6 @@ bool NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
if (UNLIKELY(!was_auto_wrap && auto_wrap_ && item_results.size() >= 2)) {
ComputeCanBreakAfter(std::prev(item_result), auto_wrap_, break_iterator_);
}
- return true;
}
void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
@@ -1527,8 +1656,6 @@ bool NGLineBreaker::ShouldHangTraillingSpaces(const NGInlineItem& item) {
// At this point, item_results does not fit into the current line, and there
// are no break opportunities in item_results.back().
void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
- overflow_item_index_ = std::max(overflow_item_index_, item_index_);
-
// Compute the width needing to rewind. When |width_to_rewind| goes negative,
// items can fit within the line.
LayoutUnit available_width = AvailableWidthToFit();
@@ -1548,43 +1675,58 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
NGInlineItemResults* item_results = line_info->MutableResults();
for (unsigned i = item_results->size(); i;) {
NGInlineItemResult* item_result = &(*item_results)[--i];
+ has_break_anywhere_if_overflow |= item_result->break_anywhere_if_overflow;
// Try to break after this item.
if (i < item_results->size() - 1 && item_result->can_break_after) {
if (width_to_rewind <= 0) {
position_ = available_width + width_to_rewind;
- Rewind(i + 1, line_info);
- state_ = LineBreakState::kTrailing;
+ RewindOverflow(i + 1, line_info);
return;
}
break_before = i + 1;
}
- // Try to break inside of this item.
+ // Compute the position after this item was removed entirely.
width_to_rewind -= item_result->inline_size;
+
+ // Try next if still does not fit.
+ if (width_to_rewind > 0)
+ continue;
+
DCHECK(item_result->item);
const NGInlineItem& item = *item_result->item;
if (item.Type() == NGInlineItem::kText) {
DCHECK(item_result->shape_result ||
(item_result->break_anywhere_if_overflow &&
!override_break_anywhere_));
- if (width_to_rewind <= 0) {
- if (!width_to_rewind || !item_result->may_break_inside) {
- if (ShouldHangTraillingSpaces(item)) {
- Rewind(i, line_info);
- state_ = LineBreakState::kTrailing;
- return;
+ // If space is available, and if this text is breakable, part of the text
+ // may fit. Try to break this item.
+ if (width_to_rewind < 0 && item_result->may_break_inside) {
+ LayoutUnit item_available_width = -width_to_rewind;
+ // Make sure the available width is smaller than the current width. The
+ // break point must not be at the end when e.g., the text fits but its
+ // right margin does not or following items do not.
+ const LayoutUnit min_available_width = item_result->inline_size - 1;
+ if (item_available_width > min_available_width) {
+ item_available_width = min_available_width;
+ // If |inline_size| is zero (e.g., `font-size: 0`), |BreakText| cannot
+ // make it shorter. Take the previous break opportunity.
+ if (UNLIKELY(item_available_width <= 0)) {
+ if (BreakTextAtPreviousBreakOpportunity(item_result)) {
+ RewindOverflow(i + 1, line_info);
+ return;
+ }
+ continue;
}
- continue;
}
- // When the text fits but its right margin does not, the break point
- // must not be at the end.
- LayoutUnit item_available_width =
- std::min(-width_to_rewind, item_result->inline_size - 1);
+ auto was_current_style = current_style_;
SetCurrentStyle(*item.Style());
+ const unsigned end_offset_before = item_result->end_offset;
BreakResult break_result =
BreakText(item_result, item, *item.TextShapeResult(),
item_available_width, line_info);
+ DCHECK_LE(item_result->end_offset, end_offset_before);
#if DCHECK_IS_ON()
item_result->CheckConsistency(true);
#endif
@@ -1595,9 +1737,11 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
DCHECK_LE(item_result->inline_size, item_available_width);
DCHECK_LT(item_result->end_offset, item.EndOffset());
DCHECK(item_result->can_break_after);
- DCHECK_LE(i + 1, item_results->size());
- if (i + 1 == item_results->size()) {
- // If this is the last item, adjust states to accomodate the change.
+
+ // If this is the last item, adjust it to accommodate the change.
+ const unsigned new_end = i + 1;
+ DCHECK_LE(new_end, item_results->size());
+ if (new_end == item_results->size()) {
position_ =
available_width + width_to_rewind + item_result->inline_size;
if (line_info->LineEndFragment())
@@ -1606,17 +1750,21 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
item_index_ = item_result->item_index;
offset_ = item_result->end_offset;
items_data_.AssertOffset(item_index_, offset_);
- } else {
- Rewind(i + 1, line_info);
+ HandleTrailingSpaces(item, line_info);
+ return;
}
- state_ = LineBreakState::kTrailing;
+
+ Rewind(new_end, line_info);
+ if (new_end < item_results->size())
+ state_ = LineBreakState::kTrailing;
+ else
+ HandleTrailingSpaces(item, line_info);
return;
}
+ SetCurrentStyle(*was_current_style);
position_maybe_changed = true;
}
}
-
- has_break_anywhere_if_overflow |= item_result->break_anywhere_if_overflow;
}
// Reaching here means that the rewind point was not found.
@@ -1629,7 +1777,7 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
if (!item_results->IsEmpty())
Rewind(0, line_info);
state_ = LineBreakState::kContinue;
- overflow_item_index_ = 0;
+ ResetRewindLoopDetector();
return;
}
@@ -1638,8 +1786,7 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
// If there was a break opportunity, the overflow should stop there.
if (break_before) {
- Rewind(break_before, line_info);
- state_ = LineBreakState::kTrailing;
+ RewindOverflow(break_before, line_info);
return;
}
@@ -1648,10 +1795,123 @@ void NGLineBreaker::HandleOverflow(NGLineInfo* line_info) {
position_ = line_info->ComputeWidth();
}
- state_ = LineBreakState::kTrailing;
+ if (CanBreakAfterLast(*item_results)) {
+ state_ = LineBreakState::kTrailing;
+ return;
+ }
+
+ // No break opportunities. Break at the earliest break opportunity.
+ DCHECK(std::all_of(item_results->begin(), item_results->end(),
+ [](const NGInlineItemResult& item_result) {
+ return !item_result.can_break_after;
+ }));
+ state_ = LineBreakState::kOverflow;
+}
+
+// Rewind to |new_end| on overflow. If trailable items follow at |new_end|, they
+// are included (not rewound).
+void NGLineBreaker::RewindOverflow(unsigned new_end, NGLineInfo* line_info) {
+ const Vector<NGInlineItem>& items = Items();
+ const NGInlineItemResults& item_results = line_info->Results();
+ DCHECK_LT(new_end, item_results.size());
+ unsigned open_tag_count = 0;
+ const String& text = Text();
+ for (unsigned index = new_end; index < item_results.size(); index++) {
+ const NGInlineItemResult& item_result = item_results[index];
+ DCHECK(item_result.item);
+ const NGInlineItem& item = *item_result.item;
+ if (item.Type() == NGInlineItem::kText) {
+ // Text items are trailable if they start with trailable spaces.
+ DCHECK_GT(item_result.Length(), 0u);
+ if (item_result.shape_result) {
+ DCHECK(item.Style());
+ const EWhiteSpace white_space = item.Style()->WhiteSpace();
+ if (ComputedStyle::AutoWrap(white_space) &&
+ white_space != EWhiteSpace::kBreakSpaces &&
+ IsBreakableSpace(text[item_result.start_offset])) {
+ // If all characters are trailable spaces, check the next item.
+ if (IsAllBreakableSpaces(text, item_result.start_offset + 1,
+ item_result.end_offset))
+ continue;
+ // If this item starts with spaces followed by non-space characters,
+ // rewind to before this item. |HandleText()| will include the spaces
+ // and break there.
+ // TODO: optimize more?
+ Rewind(index, line_info);
+ DCHECK_EQ(static_cast<unsigned>(&item - items.begin()), item_index_);
+ HandleTrailingSpaces(item, line_info);
+ return;
+ }
+ }
+ } else if (item.Type() == NGInlineItem::kControl) {
+ // All control characters except newline are trailable if auto_wrap. We
+ // should not have rewound if there was a newline, so safe to assume all
+ // controls are trailable.
+ DCHECK_NE(text[item_result.start_offset], kNewlineCharacter);
+ DCHECK(item.Style());
+ EWhiteSpace white_space = item.Style()->WhiteSpace();
+ if (ComputedStyle::AutoWrap(white_space) &&
+ white_space != EWhiteSpace::kBreakSpaces)
+ continue;
+ } else if (item.Type() == NGInlineItem::kOpenTag) {
+ // Open tags are ambiguous. This open tag is not trailable:
+ // <span>text
+ // but these are trailable:
+ // <span> text
+ // <span></span>text
+ // <span> </span>text
+ // Count the nest-level and mark where the nest-level was 0.
+ if (!open_tag_count)
+ new_end = index;
+ open_tag_count++;
+ continue;
+ } else if (item.Type() == NGInlineItem::kCloseTag) {
+ if (open_tag_count > 0)
+ open_tag_count--;
+ continue;
+ } else if (IsTrailableItemType(item.Type())) {
+ continue;
+ }
+
+ // Found a non-trailable item. Rewind to before the item, or to before the
+ // open tag if the nest-level is not zero.
+ if (open_tag_count)
+ index = new_end;
+ state_ = LineBreakState::kDone;
+ DCHECK(!line_info->IsLastLine());
+ Rewind(index, line_info);
+ return;
+ }
+
+ // The open tag turned out to be non-trailable if the nest-level is not zero.
+ // Rewind to before the open tag.
+ if (open_tag_count) {
+ state_ = LineBreakState::kDone;
+ DCHECK(!line_info->IsLastLine());
+ Rewind(new_end, line_info);
+ return;
+ }
+
+ // All items are trailable. Done without rewinding.
+ trailing_whitespace_ = WhitespaceState::kUnknown;
+ position_ = line_info->ComputeWidth();
+ state_ = LineBreakState::kDone;
+ DCHECK(!line_info->IsLastLine());
+ if (item_index_ == items.size())
+ line_info->SetIsLastLine(true);
}
void NGLineBreaker::Rewind(unsigned new_end, NGLineInfo* line_info) {
+#if DCHECK_IS_ON()
+ // Detect rewind-loop. If we're trying to rewind to the same index twice,
+ // we're in the infinite loop.
+ DCHECK(item_index_ != last_rewind_from_item_index_ ||
+ new_end != last_rewind_to_item_index_)
+ << item_index_ << ", " << offset_ << "->" << new_end;
+ last_rewind_from_item_index_ = item_index_;
+ last_rewind_to_item_index_ = new_end;
+#endif
+
NGInlineItemResults& item_results = *line_info->MutableResults();
DCHECK_LT(new_end, item_results.size());
@@ -1769,26 +2029,26 @@ void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
if (auto_wrap_) {
LineBreakType line_break_type;
- switch (style.WordBreak()) {
+ EWordBreak word_break = style.WordBreak();
+ switch (word_break) {
case EWordBreak::kNormal:
- break_anywhere_if_overflow_ =
- style.OverflowWrap() == EOverflowWrap::kBreakWord &&
- mode_ == NGLineBreakerMode::kContent;
line_break_type = LineBreakType::kNormal;
break;
case EWordBreak::kBreakAll:
- break_anywhere_if_overflow_ = false;
line_break_type = LineBreakType::kBreakAll;
break;
case EWordBreak::kBreakWord:
- break_anywhere_if_overflow_ = true;
line_break_type = LineBreakType::kNormal;
break;
case EWordBreak::kKeepAll:
- break_anywhere_if_overflow_ = false;
line_break_type = LineBreakType::kKeepAll;
break;
}
+ break_anywhere_if_overflow_ =
+ word_break == EWordBreak::kBreakWord ||
+ // `overflow-/word-wrap: break-word` affects layout but not min-content.
+ (style.OverflowWrap() == EOverflowWrap::kBreakWord &&
+ mode_ == NGLineBreakerMode::kContent);
if (UNLIKELY((override_break_anywhere_ && break_anywhere_if_overflow_) ||
style.GetLineBreak() == LineBreak::kAnywhere)) {
line_break_type = LineBreakType::kBreakCharacter;
@@ -1830,7 +2090,9 @@ void NGLineBreaker::MoveToNextOf(const NGInlineItemResult& item_result) {
scoped_refptr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken(
const NGLineInfo& line_info) const {
+ DCHECK(current_style_);
const Vector<NGInlineItem>& items = Items();
+ DCHECK_LE(item_index_, items.size());
if (item_index_ >= items.size())
return NGInlineBreakToken::Create(node_);
return NGInlineBreakToken::Create(
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 fc24745e176..37ceadff167 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
@@ -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 NGLineBreaker_h
-#define NGLineBreaker_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BREAKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BREAKER_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -47,7 +47,7 @@ class CORE_EXPORT NGLineBreaker {
// Compute the next line break point and produces NGInlineItemResults for
// the line.
inline void NextLine(NGLineInfo* line_info) {
- NextLine(kIndefiniteSize, nullptr, line_info);
+ NextLine(kIndefiniteSize, line_info);
}
// During the min/max size calculation we need a special percentage
@@ -56,7 +56,6 @@ class CORE_EXPORT NGLineBreaker {
// better yet, subclass or templetize the line-breaker for Min/Max computation
// if we can do that without incurring a performance penalty
void NextLine(LayoutUnit percentage_resolution_block_size_for_min_max,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo*);
bool IsFinished() const { return item_index_ >= Items().size(); }
@@ -72,11 +71,9 @@ class CORE_EXPORT NGLineBreaker {
// Compute NGInlineItemResult for an open tag item.
// Returns true if this item has edge and may have non-zero inline size.
- static bool ComputeOpenTagResult(
- const NGInlineItem&,
- const NGConstraintSpace&,
- NGInlineItemResult*,
- base::Optional<NGLineBoxStrut> margins = base::nullopt);
+ static bool ComputeOpenTagResult(const NGInlineItem&,
+ const NGConstraintSpace&,
+ NGInlineItemResult*);
// This enum is private, except for |WhitespaceStateForTesting()|. See
// |whitespace_| member.
@@ -106,7 +103,6 @@ class CORE_EXPORT NGLineBreaker {
NGLineInfo*);
void BreakLine(LayoutUnit percentage_resolution_block_size_for_min_max,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo*);
void PrepareNextLine(NGLineInfo*);
@@ -116,6 +112,10 @@ class CORE_EXPORT NGLineBreaker {
// The line breaking is complete.
kDone,
+ // Overflow is detected without any earlier break opportunities. This line
+ // should break at the earliest break opportunity.
+ kOverflow,
+
// Should complete the line at the earliest possible point.
// Trailing spaces, <br>, or close tags should be included to the line even
// when it is overflowing.
@@ -136,6 +136,7 @@ class CORE_EXPORT NGLineBreaker {
const ShapeResult&,
LayoutUnit available_width,
NGLineInfo*);
+ bool BreakTextAtPreviousBreakOpportunity(NGInlineItemResult* item_result);
bool ShouldHangTraillingSpaces(const NGInlineItem&);
bool HandleTextForFastMinContent(NGInlineItemResult*,
const NGInlineItem&,
@@ -152,6 +153,7 @@ class CORE_EXPORT NGLineBreaker {
unsigned start,
unsigned end);
+ void HandleTrailingSpaces(const NGInlineItem&, NGLineInfo*);
void HandleTrailingSpaces(const NGInlineItem&,
const ShapeResult&,
NGLineInfo*);
@@ -170,14 +172,20 @@ class CORE_EXPORT NGLineBreaker {
bool IsAtomicInlineBeforeNoBreakSpace(
const NGInlineItemResult& item_result) const;
void HandleFloat(const NGInlineItem&,
- Vector<LayoutObject*>* out_floats_for_min_max,
NGLineInfo*);
- bool HandleOpenTag(const NGInlineItem&, NGLineInfo*);
+ void HandleOpenTag(const NGInlineItem&, NGLineInfo*);
void HandleCloseTag(const NGInlineItem&, NGLineInfo*);
+ bool HandleOverflowIfNeeded(NGLineInfo*);
void HandleOverflow(NGLineInfo*);
+ void RewindOverflow(unsigned new_end, NGLineInfo*);
void Rewind(unsigned new_end, NGLineInfo*);
+ void ResetRewindLoopDetector() {
+#if DCHECK_IS_ON()
+ last_rewind_from_item_index_ = last_rewind_to_item_index_ = 0;
+#endif
+ }
const ComputedStyle& ComputeCurrentStyle(unsigned item_result_index,
NGLineInfo*) const;
@@ -195,6 +203,10 @@ class CORE_EXPORT NGLineBreaker {
LayoutUnit AvailableWidthToFit() const {
return AvailableWidth().AddEpsilon();
}
+ LayoutUnit RemainingAvailableWidth() const {
+ return AvailableWidthToFit() - position_;
+ }
+ bool CanFitOnLine() const { return position_ <= AvailableWidthToFit(); }
LayoutUnit ComputeAvailableWidth() const;
// Represents the current offset of the input.
@@ -274,9 +286,6 @@ class CORE_EXPORT NGLineBreaker {
};
base::Optional<TrailingCollapsibleSpace> trailing_collapsible_space_;
- // Keep track of item index where overflow occurrred.
- unsigned overflow_item_index_;
-
// Keep track of handled float items. See HandleFloat().
const NGPositionedFloatVector& leading_floats_;
unsigned leading_floats_index_ = 0u;
@@ -293,8 +302,14 @@ class CORE_EXPORT NGLineBreaker {
// This is copied from NGInlineNode, then updated after each forced line break
// if 'unicode-bidi: plaintext'.
TextDirection base_direction_;
+
+#if DCHECK_IS_ON()
+ // These fields are to detect rewind-loop.
+ unsigned last_rewind_from_item_index_ = 0;
+ unsigned last_rewind_to_item_index_ = 0;
+#endif
};
} // namespace blink
-#endif // NGLineBreaker_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_BREAKER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
index d8d9eba3f0f..4e3be49d0bf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
@@ -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 NGLineHeightMetrics_h
-#define NGLineHeightMetrics_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_HEIGHT_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_HEIGHT_METRICS_H_
#include "third_party/blink/renderer/platform/fonts/font_baseline.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -70,4 +70,4 @@ std::ostream& operator<<(std::ostream&, const NGLineHeightMetrics&);
} // namespace blink
-#endif // NGLineHeightMetrics_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_LINE_HEIGHT_METRICS_H_
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 ddadc0953aa..0014fe382c4 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
@@ -249,8 +249,8 @@ bool NGLineTruncator::TruncateChild(
IsLtr(line_direction_) ? space_for_child
: shape_result->Width() - space_for_child,
line_direction_);
- DCHECK_LE(new_length, fragment.Length());
- if (!new_length || new_length == fragment.Length()) {
+ DCHECK_LE(new_length, fragment.TextLength());
+ if (!new_length || new_length == fragment.TextLength()) {
if (!is_first_child)
return false;
new_length = !new_length ? 1 : new_length - 1;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
index 1a2ad8c41d0..40ab1e60d63 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h
@@ -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 NGOffsetMapping_h
-#define NGOffsetMapping_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -243,4 +243,4 @@ CORE_EXPORT LayoutBlockFlow* NGInlineFormattingContextOf(const Position&);
} // namespace blink
-#endif // NGOffsetMapping_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h
index 652d6033e41..957e64a80f9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_builder.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 NGOffsetMappingBuilder_h
-#define NGOffsetMappingBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_BUILDER_H_
#include <memory>
#include "base/auto_reset.h"
@@ -146,4 +146,4 @@ class CORE_EXPORT NGOffsetMappingBuilder {
} // namespace blink
-#endif // OffsetMappingBuilder_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_OFFSET_MAPPING_BUILDER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
index aeaa0c8ba9a..722bc554968 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -107,9 +107,11 @@ PhysicalRect NGPhysicalLineBoxFragment::ScrollableOverflow(
}
}
- // If child has the same style as parent, parent will compute relative
- // offset.
- if (&child->Style() != container_style) {
+ // For implementation reasons, text nodes inherit computed style from their
+ // container, including everything, also non-inherited properties. So, if
+ // the container has a relative offset, this will be falsely reflected on
+ // text children. We need to guard against this.
+ if (!child->IsText()) {
child_scroll_overflow.offset +=
ComputeRelativeOffset(child->Style(), container_writing_mode,
container_direction, container_physical_size);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
index 7fc614ba21c..ad017734837 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
@@ -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 NGPhysicalLineBoxFragment_h
-#define NGPhysicalLineBoxFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_LINE_BOX_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_LINE_BOX_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h"
@@ -96,4 +96,4 @@ struct DowncastTraits<NGPhysicalLineBoxFragment> {
} // namespace blink
-#endif // NGPhysicalBoxFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_LINE_BOX_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
index 10cae6bffed..66ec0cea1fd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
-#include "third_party/blink/renderer/core/layout/line/line_orientation_utils.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_item.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
@@ -29,21 +29,6 @@ static_assert(sizeof(NGPhysicalTextFragment) ==
sizeof(SameSizeAsNGPhysicalTextFragment),
"NGPhysicalTextFragment should stay small");
-NGLineOrientation ToLineOrientation(WritingMode writing_mode) {
- switch (writing_mode) {
- case WritingMode::kHorizontalTb:
- return NGLineOrientation::kHorizontal;
- case WritingMode::kVerticalRl:
- case WritingMode::kVerticalLr:
- case WritingMode::kSidewaysRl:
- return NGLineOrientation::kClockWiseVertical;
- case WritingMode::kSidewaysLr:
- return NGLineOrientation::kCounterClockWiseVertical;
- }
- NOTREACHED();
- return NGLineOrientation::kHorizontal;
-}
-
} // anonymous namespace
NGPhysicalTextFragment::NGPhysicalTextFragment(
@@ -66,7 +51,6 @@ NGPhysicalTextFragment::NGPhysicalTextFragment(
DCHECK_GE(start_offset_, source.StartOffset());
DCHECK_LE(end_offset_, source.EndOffset());
DCHECK(shape_result_ || IsFlowControl()) << *this;
- line_orientation_ = source.line_orientation_;
is_generated_text_ = source.is_generated_text_;
ink_overflow_computed_ = false;
}
@@ -78,55 +62,84 @@ NGPhysicalTextFragment::NGPhysicalTextFragment(NGTextFragmentBuilder* builder)
end_offset_(builder->end_offset_),
shape_result_(std::move(builder->shape_result_)) {
DCHECK(shape_result_ || IsFlowControl()) << *this;
- line_orientation_ =
- static_cast<unsigned>(ToLineOrientation(builder->GetWritingMode()));
is_generated_text_ = builder->IsGeneratedText();
ink_overflow_computed_ = false;
}
+LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
+ unsigned offset,
+ LayoutUnit (*round_function)(float),
+ AdjustMidCluster adjust_mid_cluster) const {
+ return NGFragmentItem(*this).InlinePositionForOffset(
+ Text(), offset, round_function, adjust_mid_cluster);
+}
+
+// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
+// "ng_fragment_item.cc"
// Compute the inline position from text offset, in logical coordinate relative
// to this fragment.
-LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
+LayoutUnit NGFragmentItem::InlinePositionForOffset(
+ StringView text,
unsigned offset,
- LayoutUnit (*round)(float),
+ LayoutUnit (*round_function)(float),
AdjustMidCluster adjust_mid_cluster) const {
- DCHECK_GE(offset, start_offset_);
- DCHECK_LE(offset, end_offset_);
+ DCHECK_GE(offset, StartOffset());
+ DCHECK_LE(offset, EndOffset());
+ DCHECK_EQ(text.length(), TextLength());
- offset -= start_offset_;
- if (shape_result_) {
+ offset -= StartOffset();
+ if (TextShapeResult()) {
// TODO(layout-dev): Move caret position out of ShapeResult and into a
// separate support class that can take a ShapeResult or ShapeResultView.
// Allows for better code separation and avoids the extra copy below.
- return round(shape_result_->CreateShapeResult()->CaretPositionForOffset(
- offset, Text(), adjust_mid_cluster));
+ return round_function(
+ TextShapeResult()->CreateShapeResult()->CaretPositionForOffset(
+ offset, text, adjust_mid_cluster));
}
// This fragment is a flow control because otherwise ShapeResult exists.
DCHECK(IsFlowControl());
- DCHECK_EQ(1u, Length());
+ DCHECK_EQ(1u, text.length());
if (!offset || UNLIKELY(IsRtl(Style().Direction())))
return LayoutUnit();
return IsHorizontal() ? Size().width : Size().height;
}
+// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
+// "ng_fragment_item.cc"
+LayoutUnit NGFragmentItem::InlinePositionForOffset(StringView text,
+ unsigned offset) const {
+ return InlinePositionForOffset(text, offset, LayoutUnit::FromFloatRound,
+ AdjustMidCluster::kToEnd);
+}
+
LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
unsigned offset) const {
- return InlinePositionForOffset(offset, LayoutUnit::FromFloatRound,
- AdjustMidCluster::kToEnd);
+ return NGFragmentItem(*this).InlinePositionForOffset(Text(), offset);
}
std::pair<LayoutUnit, LayoutUnit>
NGPhysicalTextFragment::LineLeftAndRightForOffsets(unsigned start_offset,
unsigned end_offset) const {
- DCHECK_LE(start_offset, end_offset);
- DCHECK_GE(start_offset, start_offset_);
- DCHECK_LE(end_offset, end_offset_);
+ return NGFragmentItem(*this).LineLeftAndRightForOffsets(Text(), start_offset,
+ end_offset);
+}
+
+// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
+// "ng_fragment_item.cc"
+std::pair<LayoutUnit, LayoutUnit> NGFragmentItem::LineLeftAndRightForOffsets(
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) const {
+ DCHECK_LE(start_offset, EndOffset());
+ DCHECK_GE(start_offset, StartOffset());
+ DCHECK_LE(end_offset, EndOffset());
- const LayoutUnit start_position = InlinePositionForOffset(
- start_offset, LayoutUnit::FromFloatFloor, AdjustMidCluster::kToStart);
+ const LayoutUnit start_position =
+ InlinePositionForOffset(text, start_offset, LayoutUnit::FromFloatFloor,
+ AdjustMidCluster::kToStart);
const LayoutUnit end_position = InlinePositionForOffset(
- end_offset, LayoutUnit::FromFloatCeil, AdjustMidCluster::kToEnd);
+ text, end_offset, LayoutUnit::FromFloatCeil, AdjustMidCluster::kToEnd);
// Swap positions if RTL.
return (UNLIKELY(start_position > end_position))
@@ -136,18 +149,28 @@ NGPhysicalTextFragment::LineLeftAndRightForOffsets(unsigned start_offset,
PhysicalRect NGPhysicalTextFragment::LocalRect(unsigned start_offset,
unsigned end_offset) const {
- if (start_offset == start_offset_ && end_offset == end_offset_)
+ return NGFragmentItem(*this).LocalRect(Text(), start_offset, end_offset);
+}
+
+// TODO(yosin): We should move |NGFragmentItem::InlinePositionForOffset" to
+// "ng_fragment_item.cc"
+PhysicalRect NGFragmentItem::LocalRect(StringView text,
+ unsigned start_offset,
+ unsigned end_offset) const {
+ if (start_offset == StartOffset() && end_offset == EndOffset())
return LocalRect();
LayoutUnit start_position, end_position;
std::tie(start_position, end_position) =
- LineLeftAndRightForOffsets(start_offset, end_offset);
+ LineLeftAndRightForOffsets(text, start_offset, end_offset);
const LayoutUnit inline_size = end_position - start_position;
- switch (LineOrientation()) {
- case NGLineOrientation::kHorizontal:
+ switch (GetWritingMode()) {
+ case WritingMode::kHorizontalTb:
return {start_position, LayoutUnit(), inline_size, Size().height};
- case NGLineOrientation::kClockWiseVertical:
+ case WritingMode::kVerticalRl:
+ case WritingMode::kVerticalLr:
+ case WritingMode::kSidewaysRl:
return {LayoutUnit(), start_position, Size().width, inline_size};
- case NGLineOrientation::kCounterClockWiseVertical:
+ case WritingMode::kSidewaysLr:
return {LayoutUnit(), Size().height - end_position, Size().width,
inline_size};
}
@@ -221,7 +244,7 @@ unsigned NGPhysicalTextFragment::TextOffsetForPoint(
LayoutUnit inline_offset = IsLtr(ResolvedDirection())
? point_in_line_direction
: size.inline_size - point_in_line_direction;
- DCHECK_EQ(1u, Length());
+ DCHECK_EQ(1u, TextLength());
return inline_offset <= size.inline_size / 2 ? StartOffset() : EndOffset();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
index e4b7ba1ca08..7d0adc9bfce 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h
@@ -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 NGPhysicalTextFragment_h
-#define NGPhysicalTextFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h"
@@ -24,25 +24,6 @@ struct PhysicalRect;
enum class AdjustMidCluster;
-// In CSS Writing Modes Levle 4, line orientation for layout and line
-// orientation for paint are not always the same.
-//
-// Specifically, 'sideways-lr' typesets as if lines are horizontal flow, but
-// rotates counterclockwise.
-enum class NGLineOrientation {
- // Lines are horizontal.
- kHorizontal,
- // Lines are vertical, rotated clockwise. Inside of the line, it may be
- // typeset using vertical characteristics, horizontal characteristics, or
- // mixed. Lines flow left to right, or right to left.
- kClockWiseVertical,
- // Lines are vertical, rotated counterclockwise. Inside of the line is typeset
- // as if horizontal flow. Lines flow left to right.
- kCounterClockWiseVertical
-
- // When adding new values, ensure NGPhysicalTextFragment has enough bits.
-};
-
class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
public:
enum NGTextType {
@@ -80,8 +61,12 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
return StyleVariant() == NGStyleVariant::kEllipsis;
}
- unsigned Length() const { return end_offset_ - start_offset_; }
- StringView Text() const { return StringView(text_, start_offset_, Length()); }
+ bool IsSymbolMarker() const { return TextType() == kSymbolMarker; }
+
+ unsigned TextLength() const { return end_offset_ - start_offset_; }
+ StringView Text() const {
+ return StringView(text_, start_offset_, TextLength());
+ }
const String& TextContent() const { return text_; }
// ShapeResult may be nullptr if |IsFlowControl()|.
@@ -91,11 +76,9 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
unsigned StartOffset() const { return start_offset_; }
unsigned EndOffset() const { return end_offset_; }
- NGLineOrientation LineOrientation() const {
- return static_cast<NGLineOrientation>(line_orientation_);
- }
+ WritingMode GetWritingMode() const { return Style().GetWritingMode(); }
bool IsHorizontal() const {
- return LineOrientation() == NGLineOrientation::kHorizontal;
+ return IsHorizontalWritingMode(GetWritingMode());
}
// Compute the inline position from text offset, in logical coordinate
@@ -178,4 +161,4 @@ struct DowncastTraits<NGPhysicalTextFragment> {
} // namespace blink
-#endif // NGPhysicalTextFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_PHYSICAL_TEXT_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h
index 48af3917979..0dbc9f84a77 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_end_effect.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 NGTextEndEffect_h
-#define NGTextEndEffect_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_END_EFFECT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_END_EFFECT_H_
namespace blink {
@@ -17,4 +17,4 @@ enum class NGTextEndEffect {
} // namespace blink
-#endif // NGTextEndEffect_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_END_EFFECT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.h
index abf640fd359..dc2e79fdd36 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.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 NGTextFragment_h
-#define NGTextFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
@@ -20,4 +20,4 @@ class CORE_EXPORT NGTextFragment final : public NGFragment {
} // namespace blink
-#endif // NGTextFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
index 97ec61d1d51..422fcd3aa3e 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h
@@ -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 NGTextFragmentBuilder_h
-#define NGTextFragmentBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_BUILDER_H_
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
@@ -61,4 +61,4 @@ class CORE_EXPORT NGTextFragmentBuilder final : public NGFragmentBuilder {
} // namespace blink
-#endif // NGTextFragmentBuilder
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_TEXT_FRAGMENT_BUILDER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
index b5fc291eb09..feb0ff65d2a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
@@ -4,14 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_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/layout_object.h"
namespace blink {
@@ -26,47 +19,7 @@ bool LayoutNGBlockFlow::IsOfType(LayoutObjectType type) const {
}
void LayoutNGBlockFlow::UpdateBlockLayout(bool relayout_children) {
- LayoutAnalyzer::BlockScope analyzer(*this);
-
- if (IsOutOfFlowPositioned()) {
- UpdateOutOfFlowBlockLayout();
- return;
- }
-
- NGConstraintSpace constraint_space =
- NGConstraintSpace::CreateFromLayoutObject(
- *this, !View()->GetLayoutState()->Next() /* is_layout_root */);
-
- scoped_refptr<const NGLayoutResult> result =
- NGBlockNode(this).Layout(constraint_space);
-
- for (const auto& descendant :
- result->PhysicalFragment().OutOfFlowPositionedDescendants())
- descendant.node.UseLegacyOutOfFlowPositioning();
-
- UpdateMargins(constraint_space);
-}
-
-void LayoutNGBlockFlow::UpdateMargins(const NGConstraintSpace& space) {
- const LayoutBlock* containing_block = ContainingBlock();
- if (!containing_block || !containing_block->IsLayoutBlockFlow())
- return;
-
- // In the legacy engine, for regular block container layout, children
- // calculate and store margins on themselves, while in NG that's done by the
- // container. Since this object is a LayoutNG entry-point, we'll have to do it
- // on ourselves, since that's what the legacy container expects.
- const ComputedStyle& style = StyleRef();
- const ComputedStyle& cb_style = containing_block->StyleRef();
- const auto writing_mode = cb_style.GetWritingMode();
- const auto direction = cb_style.Direction();
- LayoutUnit percentage_resolution_size =
- space.PercentageResolutionInlineSizeForParentWritingMode();
- NGBoxStrut margins = ComputePhysicalMargins(style, percentage_resolution_size)
- .ConvertToLogical(writing_mode, direction);
- ResolveInlineMargins(style, cb_style, space.AvailableSize().inline_size,
- LogicalWidth(), &margins);
- SetMargin(margins.ConvertToPhysical(writing_mode, direction));
+ UpdateNGBlockLayout();
}
} // namespace blink
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 ae132bba87c..c17a0caf9e2 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
@@ -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 LayoutNGBlockFlow_h
-#define LayoutNGBlockFlow_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_FLOW_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_FLOW_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
@@ -24,13 +24,10 @@ class CORE_EXPORT LayoutNGBlockFlow
protected:
bool IsOfType(LayoutObjectType) const override;
-
- private:
- void UpdateMargins(const NGConstraintSpace&);
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGBlockFlow, IsLayoutNGBlockFlow());
} // namespace blink
-#endif // LayoutNGBlockFlow_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_BLOCK_FLOW_H_
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 1e5ad9ee393..0124e6eef87 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
@@ -9,6 +9,8 @@
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h"
+#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/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"
@@ -86,6 +88,9 @@ const NGPhysicalBoxFragment* LayoutNGBlockFlowMixin<Base>::CurrentFragment()
template <typename Base>
void LayoutNGBlockFlowMixin<Base>::AddLayoutOverflowFromChildren() {
+ if (Base::LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
+ return;
+
// |ComputeOverflow()| calls this, which is called from
// |CopyFragmentDataToLayoutBox()| and |RecalcOverflow()|.
// Add overflow from the last layout cycle.
@@ -98,72 +103,83 @@ void LayoutNGBlockFlowMixin<Base>::AddLayoutOverflowFromChildren() {
template <typename Base>
void LayoutNGBlockFlowMixin<Base>::AddScrollingOverflowFromChildren() {
- bool children_inline = Base::ChildrenInline();
const NGPhysicalBoxFragment* physical_fragment = CurrentFragment();
DCHECK(physical_fragment);
- // inline-end LayoutOverflow padding spec is still undecided:
+ if (physical_fragment->Children().empty())
+ return;
+
+ const ComputedStyle& style = Base::StyleRef();
+ const WritingMode writing_mode = style.GetWritingMode();
+ const TextDirection direction = style.Direction();
+ const LayoutUnit border_inline_start = LayoutUnit(style.BorderStartWidth());
+ const LayoutUnit border_block_start = LayoutUnit(style.BorderBeforeWidth());
+ const PhysicalSize& size = physical_fragment->Size();
+
+ // End and under padding are added to scroll overflow of inline children.
// https://github.com/w3c/csswg-drafts/issues/129
- // For backwards compatibility, if container clips overflow,
- // padding is added to the inline-end for inline children.
base::Optional<NGPhysicalBoxStrut> padding_strut;
if (Base::HasOverflowClip()) {
- padding_strut =
- NGBoxStrut(LayoutUnit(), Base::PaddingEnd(), LayoutUnit(), LayoutUnit())
- .ConvertToPhysical(Base::StyleRef().GetWritingMode(),
- Base::StyleRef().Direction());
+ padding_strut = NGBoxStrut(LayoutUnit(), Base::PaddingEnd(), LayoutUnit(),
+ Base::PaddingUnder())
+ .ConvertToPhysical(writing_mode, direction);
}
- PhysicalRect children_overflow;
+ // Rectangles not reachable by scroll should not be added to overflow.
+ auto IsRectReachableByScroll = [&border_inline_start, &border_block_start,
+ &writing_mode, &direction,
+ &size](const PhysicalRect& rect) {
+ LogicalOffset rect_logical_end =
+ rect.offset.ConvertToLogical(writing_mode, direction, size, rect.size) +
+ rect.size.ConvertToLogical(writing_mode);
+ return (rect_logical_end.inline_offset > border_inline_start &&
+ rect_logical_end.block_offset > border_block_start);
+ };
+ bool children_inline = Base::ChildrenInline();
+ PhysicalRect children_overflow;
+ base::Optional<PhysicalRect> lineboxes_enclosing_rect;
// Only add overflow for fragments NG has not reflected into Legacy.
// These fragments are:
// - inline fragments,
// - out of flow fragments whose css container is inline box.
// TODO(layout-dev) Transforms also need to be applied to compute overflow
// correctly. NG is not yet transform-aware. crbug.com/855965
- if (!physical_fragment->Children().empty()) {
- LayoutUnit border_inline_start =
- LayoutUnit(Base::StyleRef().BorderStartWidth());
- LayoutUnit border_block_start =
- LayoutUnit(Base::StyleRef().BorderBeforeWidth());
- for (const auto& child : physical_fragment->Children()) {
- PhysicalRect child_scrollable_overflow;
- if (child->IsFloatingOrOutOfFlowPositioned()) {
- child_scrollable_overflow =
- child->ScrollableOverflowForPropagation(this);
- child_scrollable_overflow.offset += ComputeRelativeOffset(
- child->Style(), Base::StyleRef().GetWritingMode(),
- Base::StyleRef().Direction(), physical_fragment->Size());
- } else if (children_inline && child->IsLineBox()) {
- DCHECK(child->IsLineBox());
- child_scrollable_overflow =
- To<NGPhysicalLineBoxFragment>(*child).ScrollableOverflow(
- this, Base::Style(), physical_fragment->Size());
- if (padding_strut)
- child_scrollable_overflow.Expand(*padding_strut);
- } else {
- continue;
+ for (const auto& child : physical_fragment->Children()) {
+ PhysicalRect child_scrollable_overflow;
+ if (child->IsFloatingOrOutOfFlowPositioned()) {
+ child_scrollable_overflow = child->ScrollableOverflowForPropagation(this);
+ child_scrollable_overflow.offset +=
+ ComputeRelativeOffset(child->Style(), writing_mode, direction, size);
+ } else if (children_inline && child->IsLineBox()) {
+ DCHECK(child->IsLineBox());
+ child_scrollable_overflow =
+ To<NGPhysicalLineBoxFragment>(*child).ScrollableOverflow(this, &style,
+ size);
+ if (padding_strut) {
+ PhysicalRect linebox_rect(child.Offset(), child->Size());
+ if (lineboxes_enclosing_rect)
+ lineboxes_enclosing_rect->Unite(linebox_rect);
+ else
+ lineboxes_enclosing_rect = linebox_rect;
}
- child_scrollable_overflow.offset += child.Offset();
-
- // Do not add overflow if fragment is not reachable by scrolling.
- WritingMode writing_mode = Base::StyleRef().GetWritingMode();
- LogicalOffset child_logical_end =
- child_scrollable_overflow.offset.ConvertToLogical(
- writing_mode, Base::StyleRef().Direction(),
- physical_fragment->Size(), child_scrollable_overflow.size) +
- child_scrollable_overflow.size.ConvertToLogical(writing_mode);
-
- if (child_logical_end.inline_offset > border_inline_start &&
- child_logical_end.block_offset > border_block_start)
- children_overflow.Unite(child_scrollable_overflow);
+ } else {
+ continue;
}
+ child_scrollable_overflow.offset += child.Offset();
+ // Do not add overflow if fragment is not reachable by scrolling.
+ if (IsRectReachableByScroll(child_scrollable_overflow))
+ children_overflow.Unite(child_scrollable_overflow);
+ }
+ if (lineboxes_enclosing_rect) {
+ lineboxes_enclosing_rect->Expand(*padding_strut);
+ if (IsRectReachableByScroll(*lineboxes_enclosing_rect))
+ children_overflow.Unite(*lineboxes_enclosing_rect);
}
// LayoutOverflow takes flipped blocks coordinates, adjust as needed.
- LayoutRect children_flipped_overflow = children_overflow.ToLayoutFlippedRect(
- physical_fragment->Style(), physical_fragment->Size());
+ LayoutRect children_flipped_overflow =
+ children_overflow.ToLayoutFlippedRect(style, size);
Base::AddLayoutOverflow(children_flipped_overflow);
}
@@ -173,8 +189,9 @@ void LayoutNGBlockFlowMixin<Base>::AddOutlineRects(
const PhysicalOffset& additional_offset,
NGOutlineType include_block_overflows) const {
if (PaintFragment()) {
- PaintFragment()->AddSelfOutlineRects(&rects, additional_offset,
- include_block_overflows);
+ To<NGPhysicalBoxFragment>(PaintFragment()->PhysicalFragment())
+ .AddSelfOutlineRects(additional_offset, include_block_overflows,
+ &rects);
} else {
Base::AddOutlineRects(rects, additional_offset, include_block_overflows);
}
@@ -266,6 +283,13 @@ void LayoutNGBlockFlowMixin<Base>::Paint(const PaintInfo& paint_info) const {
}
}
+ if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentPaintEnabled())) {
+ if (const NGPhysicalBoxFragment* fragment = CurrentFragment()) {
+ NGBoxFragmentPainter(*fragment, PaintFragment()).Paint(paint_info);
+ return;
+ }
+ }
+
if (const NGPaintFragment* paint_fragment = PaintFragment())
NGBoxFragmentPainter(*paint_fragment).Paint(paint_info);
else
@@ -343,8 +367,55 @@ void LayoutNGBlockFlowMixin<Base>::DirtyLinesFromChangedChild(
NGPaintFragment::DirtyLinesFromChangedChild(child);
}
+template <typename Base>
+void LayoutNGBlockFlowMixin<Base>::UpdateNGBlockLayout() {
+ LayoutAnalyzer::BlockScope analyzer(*this);
+
+ if (Base::IsOutOfFlowPositioned()) {
+ this->UpdateOutOfFlowBlockLayout();
+ return;
+ }
+
+ NGConstraintSpace constraint_space =
+ NGConstraintSpace::CreateFromLayoutObject(
+ *this, !Base::View()->GetLayoutState()->Next() /* is_layout_root */);
+
+ scoped_refptr<const NGLayoutResult> result =
+ NGBlockNode(this).Layout(constraint_space);
+
+ for (const auto& descendant :
+ result->PhysicalFragment().OutOfFlowPositionedDescendants())
+ descendant.node.UseLegacyOutOfFlowPositioning();
+ this->UpdateMargins(constraint_space);
+}
+
+template <typename Base>
+void LayoutNGBlockFlowMixin<Base>::UpdateMargins(
+ const NGConstraintSpace& space) {
+ const LayoutBlock* containing_block = Base::ContainingBlock();
+ if (!containing_block || !containing_block->IsLayoutBlockFlow())
+ return;
+
+ // In the legacy engine, for regular block container layout, children
+ // calculate and store margins on themselves, while in NG that's done by the
+ // container. Since this object is a LayoutNG entry-point, we'll have to do it
+ // on ourselves, since that's what the legacy container expects.
+ const ComputedStyle& style = Base::StyleRef();
+ const ComputedStyle& cb_style = containing_block->StyleRef();
+ const auto writing_mode = cb_style.GetWritingMode();
+ const auto direction = cb_style.Direction();
+ LayoutUnit percentage_resolution_size =
+ space.PercentageResolutionInlineSizeForParentWritingMode();
+ NGBoxStrut margins = ComputePhysicalMargins(style, percentage_resolution_size)
+ .ConvertToLogical(writing_mode, direction);
+ ResolveInlineMargins(style, cb_style, space.AvailableSize().inline_size,
+ Base::LogicalWidth(), &margins);
+ this->SetMargin(margins.ConvertToPhysical(writing_mode, direction));
+}
+
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutBlockFlow>;
+template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutProgress>;
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutTableCaption>;
template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutTableCell>;
-template class CORE_TEMPLATE_EXPORT LayoutNGBlockFlowMixin<LayoutBlockFlow>;
} // namespace blink
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 8e673601b77..6b5d874ce5d 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
@@ -10,6 +10,7 @@
#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_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"
@@ -77,6 +78,10 @@ class LayoutNGBlockFlowMixin : public LayoutNGMixin<Base> {
void DirtyLinesFromChangedChild(LayoutObject* child,
MarkingBehavior marking_behavior) final;
+ // Intended to be called from UpdateLayout() for subclasses that want the same
+ // behavior as LayoutNGBlockFlow.
+ void UpdateNGBlockLayout();
+
std::unique_ptr<NGInlineNodeData> ng_inline_node_data_;
scoped_refptr<NGPaintFragment> paint_fragment_;
@@ -84,6 +89,7 @@ class LayoutNGBlockFlowMixin : public LayoutNGMixin<Base> {
private:
void AddScrollingOverflowFromChildren();
+ void UpdateMargins(const NGConstraintSpace& space);
};
// If you edit these export templates, also update templates in
@@ -91,6 +97,8 @@ class LayoutNGBlockFlowMixin : public LayoutNGMixin<Base> {
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<LayoutTableCaption>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
LayoutNGBlockFlowMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
index 50d1b09cf48..a39b2b4dee0 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
@@ -74,12 +74,16 @@ bool LayoutNGFieldset::IsOfType(LayoutObjectType type) const {
}
void LayoutNGFieldset::Paint(const PaintInfo& paint_info) const {
- // TODO(kojii): This override shiould not be needed when painting fragment is
- // enabled in parent classes.
- if (const NGPhysicalBoxFragment* fragment = CurrentFragment())
- NGBoxFragmentPainter(*fragment, PaintFragment()).Paint(paint_info);
- else
- LayoutNGBlockFlow::Paint(paint_info);
+ // TODO(crbug.com/988015): This override should not be needed when painting
+ // fragment is enabled in parent classes.
+ if (!RuntimeEnabledFeatures::LayoutNGFragmentPaintEnabled()) {
+ if (const NGPhysicalBoxFragment* fragment = CurrentFragment()) {
+ NGBoxFragmentPainter(*fragment, PaintFragment()).Paint(paint_info);
+ return;
+ }
+ }
+
+ LayoutNGBlockFlow::Paint(paint_info);
}
} // 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 88bafe7afe1..bc31a16375c 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
@@ -192,6 +192,7 @@ void LayoutNGMixin<Base>::UpdateOutOfFlowBlockLayout() {
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlock>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutBlockFlow>;
+template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutProgress>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutTableCaption>;
template class CORE_TEMPLATE_EXPORT LayoutNGMixin<LayoutTableCell>;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
index 57eea646a14..e75f321437e 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
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LayoutNGMixin_h
-#define LayoutNGMixin_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_MIXIN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_MIXIN_H_
#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_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -37,6 +38,7 @@ class LayoutNGMixin : public Base {
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<LayoutTableCaption>;
extern template class CORE_EXTERN_TEMPLATE_EXPORT
@@ -44,4 +46,4 @@ extern template class CORE_EXTERN_TEMPLATE_EXPORT
} // namespace blink
-#endif // LayoutNGMixin_h
+#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.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.cc
new file mode 100644
index 00000000000..9ad94217a36
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_progress.h"
+
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+
+namespace blink {
+
+LayoutNGProgress::LayoutNGProgress(Element* element)
+ : LayoutNGBlockFlowMixin<LayoutProgress>(element) {}
+
+LayoutNGProgress::~LayoutNGProgress() = default;
+
+void LayoutNGProgress::UpdateBlockLayout(bool relayout_children) {
+ UpdateNGBlockLayout();
+}
+
+bool LayoutNGProgress::IsOfType(LayoutObjectType type) const {
+ return type == kLayoutObjectNGProgress ||
+ LayoutNGMixin<LayoutProgress>::IsOfType(type);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..7ad4c0c18d7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_PROGRESS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_PROGRESS_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_progress.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow_mixin.h"
+
+namespace blink {
+
+class CORE_EXPORT LayoutNGProgress
+ : public LayoutNGBlockFlowMixin<LayoutProgress> {
+ public:
+ explicit LayoutNGProgress(Element*);
+ ~LayoutNGProgress() override;
+
+ void UpdateBlockLayout(bool relayout_children) override;
+
+ const char* GetName() const override { return "LayoutNGProgress"; }
+
+ protected:
+ bool IsOfType(LayoutObjectType type) const override;
+};
+
+DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGProgress, IsLayoutNGProgress());
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_PROGRESS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h
index d51ed533865..4781aa05bb3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_table_cell.h
@@ -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 LayoutNGTableCell_h
-#define LayoutNGTableCell_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -23,4 +23,4 @@ class CORE_EXPORT LayoutNGTableCell final
} // namespace blink
-#endif // LayoutNGTableCell_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LAYOUT_NG_TABLE_CELL_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h
index 82ea95eb171..e01bc5d90ec 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
@@ -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 LegacyLayoutTreeWalking_h
-#define LegacyLayoutTreeWalking_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LEGACY_LAYOUT_TREE_WALKING_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LEGACY_LAYOUT_TREE_WALKING_H_
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
@@ -106,4 +106,4 @@ inline bool IsManagedByLayoutNG(const LayoutObject& object) {
} // namespace blink
-#endif // LegacyLayoutTreeWalking_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LEGACY_LAYOUT_TREE_WALKING_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index 60052f733de..a7d551b6fb0 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
@@ -53,7 +53,10 @@ void LayoutNGListItem::StyleDidChange(StyleDifference diff,
UpdateMarker();
- if (old_style && old_style->ListStyleType() != StyleRef().ListStyleType())
+ if (old_style && (old_style->ListStyleType() != StyleRef().ListStyleType() ||
+ (StyleRef().ListStyleType() == EListStyleType::kString &&
+ old_style->ListStyleStringValue() !=
+ StyleRef().ListStyleStringValue())))
ListStyleTypeChanged();
}
@@ -152,6 +155,11 @@ void LayoutNGListItem::UpdateMarker() {
LayoutListMarker::InlineMarginsForInside(style, IsMarkerImage());
marker_style->SetMarginStart(Length::Fixed(margins.first));
marker_style->SetMarginEnd(Length::Fixed(margins.second));
+ // Markers should have unicode-bidi:isolate according to the spec
+ // (https://drafts.csswg.org/css-lists/#ua-stylesheet).
+ // Note this is only relevant for inside markers with arbitrary strings.
+ if (style.ListStyleType() == EListStyleType::kString)
+ marker_style->SetUnicodeBidi(UnicodeBidi::kIsolate);
} else {
if (marker_ && !marker_->IsLayoutBlockFlow())
DestroyMarker();
@@ -212,11 +220,15 @@ LayoutNGListItem::MarkerType LayoutNGListItem::MarkerText(
switch (style.ListStyleType()) {
case EListStyleType::kNone:
return kStatic;
+ case EListStyleType::kString: {
+ text->Append(style.ListStyleStringValue());
+ return kStatic;
+ }
case EListStyleType::kDisc:
case EListStyleType::kCircle:
case EListStyleType::kSquare:
// value is ignored for these types
- text->Append(list_marker_text::GetText(Style()->ListStyleType(), 0));
+ text->Append(list_marker_text::GetText(style.ListStyleType(), 0));
if (format == kWithSuffix)
text->Append(' ');
return kSymbolValue;
@@ -273,9 +285,9 @@ LayoutNGListItem::MarkerType LayoutNGListItem::MarkerText(
case EListStyleType::kUpperRoman:
case EListStyleType::kUrdu: {
int value = Value();
- text->Append(list_marker_text::GetText(Style()->ListStyleType(), value));
+ text->Append(list_marker_text::GetText(style.ListStyleType(), value));
if (format == kWithSuffix) {
- text->Append(list_marker_text::Suffix(Style()->ListStyleType(), value));
+ text->Append(list_marker_text::Suffix(style.ListStyleType(), value));
text->Append(' ');
}
return kOrdinalValue;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
index 06b77320f05..bcf4880fa35 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
@@ -47,7 +47,7 @@ bool LayoutNGListMarker::NeedsOccupyWholeLine() const {
LayoutObject* next_sibling = NextSibling();
if (next_sibling && next_sibling->GetNode() &&
(IsHTMLUListElement(*next_sibling->GetNode()) ||
- IsHTMLOListElement(*next_sibling->GetNode())))
+ IsA<HTMLOListElement>(*next_sibling->GetNode())))
return true;
return false;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
index 653ab1b4682..65a6f555531 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
@@ -22,6 +22,21 @@ bool LayoutNGListMarkerImage::IsOfType(LayoutObjectType type) const {
return type == kLayoutObjectNGListMarkerImage || LayoutImage::IsOfType(type);
}
+Node* LayoutNGListMarkerImage::NodeForHitTest() const {
+ // In LayoutNG tree, image list marker is structured like this:
+ // <li> (LayoutListItem)
+ // <anonymous block> (LayoutNGListMarker or LayoutNGInsideListMarker)
+ // <anonymous img> (LayoutNGListMarkerImage)
+ // Hit testing should return the list-item node.
+ DCHECK(!GetNode());
+ for (const LayoutObject* parent = Parent(); parent;
+ parent = parent->Parent()) {
+ if (Node* node = parent->GetNode())
+ return node;
+ }
+ return nullptr;
+}
+
// Because ImageResource() is always LayoutImageResourceStyleImage. So we could
// use StyleImage::ImageSize to determine the concrete object size with
// default object size(ascent/2 x ascent/2).
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
index 44af6cbbb50..6ebae9a91d7 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
@@ -19,6 +19,8 @@ class CORE_EXPORT LayoutNGListMarkerImage final : public LayoutImage {
bool IsLayoutNGObject() const override { return true; }
+ Node* NodeForHitTest() const final;
+
private:
bool IsOfType(LayoutObjectType) const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
index 374086ae587..710824388d4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_list_marker.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_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
@@ -124,6 +125,11 @@ void NGUnpositionedListMarker::AddToBox(
marker_offset.block_offset);
DCHECK(container_builder);
+ if (NGFragmentItemsBuilder* items_builder =
+ container_builder->ItemsBuilder()) {
+ items_builder->AddListMarker(marker_physical_fragment, marker_offset);
+ return;
+ }
container_builder->AddChild(marker_physical_fragment, marker_offset);
}
@@ -142,6 +148,7 @@ LayoutUnit NGUnpositionedListMarker::AddToBoxWithoutLineBoxes(
LogicalOffset offset(InlineOffset(marker_size.inline_size), LayoutUnit());
DCHECK(container_builder);
+ DCHECK(!container_builder->ItemsBuilder());
container_builder->AddChild(marker_physical_fragment, offset);
return marker_size.block_size;
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 d71cc258e01..07d9515ee0f 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
@@ -70,9 +70,21 @@ inline LayoutUnit StaticPositionEndInset(bool is_static_position_start,
(is_static_position_start ? size : LayoutUnit());
}
+LayoutUnit ComputeShrinkToFitSize(
+ const base::Optional<MinMaxSize>& child_minmax,
+ LayoutUnit computed_available_size,
+ LayoutUnit margin_start,
+ LayoutUnit margin_end) {
+ return child_minmax->ShrinkToFit(
+ (computed_available_size - margin_start - margin_end)
+ .ClampNegativeToZero());
+}
+
// Implement the absolute size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-height
+// |child_minmax| can have no value if an element is replaced, and has no
+// intrinsic width or height, but has an aspect ratio.
void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
const base::Optional<MinMaxSize>& child_minmax,
const LayoutUnit margin_percentage_resolution_size,
@@ -113,9 +125,7 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
if (!inset_end_length.IsAuto()) {
inset_end = MinimumValueForLength(inset_end_length, available_size);
}
-#if DCHECK_IS_ON()
- bool values_might_be_saturated = false;
-#endif
+
// Solving the equation:
// |inset_start| + |margin_start| + |size| + |margin_end| + |inset_end| =
// |available_size|
@@ -125,14 +135,12 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
margin_start = LayoutUnit();
if (!margin_end)
margin_end = LayoutUnit();
- DCHECK(child_minmax.has_value());
LayoutUnit computed_available_size =
is_static_position_start ? available_size - static_position_offset
: static_position_offset;
- size = child_minmax->ShrinkToFit(
- (computed_available_size - *margin_start - *margin_end)
- .ClampNegativeToZero());
+ size = ComputeShrinkToFitSize(child_minmax, computed_available_size,
+ *margin_start, *margin_end);
LayoutUnit margin_size = *size + *margin_start + *margin_end;
if (is_start_dominant) {
inset_start = StaticPositionStartInset(
@@ -147,9 +155,6 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
// Compute margins.
LayoutUnit margin_space =
available_size - *inset_start - *inset_end - *size;
-#if DCHECK_IS_ON()
- values_might_be_saturated |= margin_space.MightBeSaturated();
-#endif
if (!margin_start && !margin_end) {
// When both margins are auto.
@@ -173,9 +178,6 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
} else {
// Are the values over-constrained?
LayoutUnit margin_extra = margin_space - *margin_start - *margin_end;
-#if DCHECK_IS_ON()
- values_might_be_saturated |= margin_extra.MightBeSaturated();
-#endif
if (margin_extra) {
// Relax the end.
if (is_start_dominant)
@@ -196,11 +198,9 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
if (!inset_start && !size) {
// Rule 1: left/width are unknown.
DCHECK(inset_end.has_value());
- DCHECK(child_minmax.has_value());
LayoutUnit computed_available_size = available_size - *inset_end;
- size = child_minmax->ShrinkToFit(
- (computed_available_size - *margin_start - *margin_end)
- .ClampNegativeToZero());
+ size = ComputeShrinkToFitSize(child_minmax, computed_available_size,
+ *margin_start, *margin_end);
} else if (!inset_start && !inset_end) {
// Rule 2.
DCHECK(size.has_value());
@@ -215,11 +215,9 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
}
} else if (!size && !inset_end) {
// Rule 3.
- DCHECK(child_minmax.has_value());
LayoutUnit computed_available_size = available_size - *inset_start;
- size = child_minmax->ShrinkToFit(
- (computed_available_size - *margin_start - *margin_end)
- .ClampNegativeToZero());
+ size = ComputeShrinkToFitSize(child_minmax, computed_available_size,
+ *margin_start, *margin_end);
}
// Rules 4 through 6: 1 out of 3 are unknown.
@@ -234,18 +232,6 @@ void ComputeAbsoluteSize(const LayoutUnit border_padding_size,
*margin_end;
}
-#if DCHECK_IS_ON()
- values_might_be_saturated |=
- inset_start->MightBeSaturated() || inset_end->MightBeSaturated() ||
- size->MightBeSaturated() || margin_start->MightBeSaturated() ||
- margin_end->MightBeSaturated() || available_size.MightBeSaturated();
- // The DCHECK is useful, but only holds true if the values aren't saturated.
- if (!values_might_be_saturated) {
- DCHECK_EQ(available_size,
- *inset_start + *inset_end + *margin_start + *margin_end + *size);
- }
-#endif // #if DCHECK_IS_ON()
-
// If calculated |size| is outside of min/max constraints, rerun the
// algorithm with the constrained |size|.
LayoutUnit constrained_size = ConstrainByMinMax(*size, min_size, max_size);
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 f6d237aa201..bcfa41fc6a7 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
@@ -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 NGAbsoluteUtils_h
-#define NGAbsoluteUtils_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_ABSOLUTE_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_ABSOLUTE_UTILS_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -85,4 +85,4 @@ CORE_EXPORT void ComputeFullAbsoluteWithChildBlockSize(
} // namespace blink
-#endif // NGAbsoluteUtils_h
+#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 a3d0a905a04..7f919d2599f 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
@@ -111,7 +111,7 @@ NGConstraintSpace ConstructBlockLayoutTestConstraintSpace(
builder.SetPercentageResolutionSize(size);
builder.SetTextDirection(direction);
builder.SetIsShrinkToFit(shrink_to_fit);
- builder.SetFragmentainerSpaceAtBfcStart(fragmentainer_space_available);
+ 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 98efb5bbaf5..6e9781b9bdf 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
@@ -24,12 +24,12 @@ NGBlockBreakToken::NGBlockBreakToken(
NGLayoutInputNode node,
LayoutUnit consumed_block_size,
const NGBreakTokenVector& child_break_tokens,
- bool has_last_resort_break,
+ NGBreakAppeal break_appeal,
bool has_seen_all_children)
: NGBreakToken(kBlockBreakToken, kUnfinished, node),
consumed_block_size_(consumed_block_size),
num_children_(child_break_tokens.size()) {
- has_last_resort_break_ = has_last_resort_break;
+ break_appeal_ = break_appeal;
has_seen_all_children_ = has_seen_all_children;
for (wtf_size_t i = 0; i < child_break_tokens.size(); ++i) {
child_break_tokens_[i] = child_break_tokens[i].get();
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 d2ecc67e82e..fc5ab4ba485 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
@@ -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 NGBlockBreakToken_h
-#define NGBlockBreakToken_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_BREAK_TOKEN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_BREAK_TOKEN_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -28,7 +28,7 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
NGLayoutInputNode node,
LayoutUnit consumed_block_size,
const NGBreakTokenVector& child_break_tokens,
- bool has_last_resort_break,
+ NGBreakAppeal break_appeal,
bool has_seen_all_children) {
// 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
@@ -38,7 +38,7 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
child_break_tokens.size() * sizeof(NGBreakToken*),
::WTF::GetStringWithTypeName<NGBlockBreakToken>());
new (data) NGBlockBreakToken(node, consumed_block_size, child_break_tokens,
- has_last_resort_break, has_seen_all_children);
+ break_appeal, has_seen_all_children);
return base::AdoptRef(static_cast<NGBlockBreakToken*>(data));
}
@@ -76,8 +76,6 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
bool IsForcedBreak() const { return is_forced_break_; }
- bool HasLastResortBreak() const { return has_last_resort_break_; }
-
// Return true if all children have been "seen". When we have reached this
// point, and resume layout in a fragmentainer, we should only process child
// break tokens, if any, and not attempt to start laying out nodes that don't
@@ -110,7 +108,7 @@ class CORE_EXPORT NGBlockBreakToken final : public NGBreakToken {
NGBlockBreakToken(NGLayoutInputNode node,
LayoutUnit consumed_block_size,
const NGBreakTokenVector& child_break_tokens,
- bool has_last_resort_break,
+ NGBreakAppeal break_appeal,
bool has_seen_all_children);
explicit NGBlockBreakToken(NGLayoutInputNode node);
@@ -131,4 +129,4 @@ struct DowncastTraits<NGBlockBreakToken> {
} // namespace blink
-#endif // NGBlockBreakToken_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_BREAK_TOKEN_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
index cf4436656bd..3b7636ad530 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NGBlockChildIterator_h
-#define NGBlockChildIterator_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_CHILD_ITERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_CHILD_ITERATOR_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
@@ -72,4 +72,4 @@ struct NGBlockChildIterator::Entry {
} // namespace blink
-#endif // NGBlockChildIterator_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_CHILD_ITERATOR_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
index 9bda34aae50..917eb7864f5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
@@ -58,20 +58,20 @@ TEST_F(NGBlockChildIteratorTest, BreakTokens) {
NGBreakTokenVector empty_tokens_list;
scoped_refptr<NGBreakToken> child_token1 = NGBlockBreakToken::Create(
- node1, LayoutUnit(), empty_tokens_list,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ node1, LayoutUnit(), empty_tokens_list, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
scoped_refptr<NGBreakToken> child_token2 = NGBlockBreakToken::Create(
- node2, LayoutUnit(), empty_tokens_list,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ node2, LayoutUnit(), empty_tokens_list, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
scoped_refptr<NGBreakToken> child_token3 = NGBlockBreakToken::Create(
- node3, LayoutUnit(), empty_tokens_list,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ node3, LayoutUnit(), empty_tokens_list, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
NGBreakTokenVector child_break_tokens;
child_break_tokens.push_back(child_token1);
scoped_refptr<NGBlockBreakToken> parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
NGBlockChildIterator iterator(node1, parent_token.get());
ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1.get()),
@@ -86,8 +86,8 @@ TEST_F(NGBlockChildIteratorTest, BreakTokens) {
child_break_tokens.push_back(child_token1);
child_break_tokens.push_back(child_token2);
parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
iterator = NGBlockChildIterator(node1, parent_token.get());
ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1.get()),
@@ -103,8 +103,8 @@ TEST_F(NGBlockChildIteratorTest, BreakTokens) {
child_break_tokens.push_back(child_token2);
child_break_tokens.push_back(child_token3);
parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
iterator = NGBlockChildIterator(node1, parent_token.get());
ASSERT_EQ(NGBlockChildIterator::Entry(node2, child_token2.get()),
@@ -119,8 +119,8 @@ TEST_F(NGBlockChildIteratorTest, BreakTokens) {
child_break_tokens.push_back(child_token1);
child_break_tokens.push_back(child_token3);
parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
iterator = NGBlockChildIterator(node1, parent_token.get());
ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1.get()),
@@ -145,14 +145,14 @@ TEST_F(NGBlockChildIteratorTest, SeenAllChildren) {
NGBreakTokenVector empty_tokens_list;
scoped_refptr<NGBreakToken> child_token1 = NGBlockBreakToken::Create(
- node1, LayoutUnit(), empty_tokens_list,
- /* has_last_resort_break */ false, /* has_seen_all_children */ false);
+ node1, LayoutUnit(), empty_tokens_list, kBreakAppealPerfect,
+ /* has_seen_all_children */ false);
NGBreakTokenVector child_break_tokens;
child_break_tokens.push_back(child_token1);
scoped_refptr<NGBlockBreakToken> parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ true);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ true);
// We have a break token for #child1, but have seen all children. This happens
// e.g. when #child1 has overflow into a new fragmentainer, while #child2 was
@@ -166,8 +166,8 @@ TEST_F(NGBlockChildIteratorTest, SeenAllChildren) {
child_break_tokens.clear();
parent_token = NGBlockBreakToken::Create(
- container, LayoutUnit(), child_break_tokens,
- /* has_last_resort_break */ false, /* has_seen_all_children */ true);
+ container, LayoutUnit(), child_break_tokens, kBreakAppealPerfect,
+ /* has_seen_all_children */ true);
// We have no break tokens, but have seen all children. This happens e.g. when
// we have a large container with fixed block-size, with empty space at the
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 52feec79c06..13114b5c084 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
@@ -19,6 +19,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_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.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h"
@@ -36,14 +37,35 @@
namespace blink {
namespace {
+inline scoped_refptr<const NGLayoutResult> LayoutBlockChild(
+ const NGConstraintSpace& space,
+ const NGBreakToken* break_token,
+ const NGEarlyBreak* early_break,
+ NGBlockNode* node) {
+ const NGEarlyBreak* early_break_in_child = nullptr;
+ if (UNLIKELY(early_break && early_break->Type() == NGEarlyBreak::kBlock &&
+ early_break->BlockNode() == *node)) {
+ // We're entering a child that we know that we're going to break inside, and
+ // even where to break. Look inside, and pass the inner breakpoint to
+ // layout.
+ early_break_in_child = early_break->BreakInside();
+ // If there's no break inside, we should already have broken before this
+ // child.
+ DCHECK(early_break_in_child);
+ }
+ return node->Layout(space, break_token, early_break_in_child);
+}
+
inline scoped_refptr<const NGLayoutResult> LayoutInflow(
const NGConstraintSpace& space,
const NGBreakToken* break_token,
+ const NGEarlyBreak* early_break,
NGLayoutInputNode* node,
NGInlineChildLayoutContext* context) {
- auto* inline_node = DynamicTo<NGInlineNode>(node);
- return inline_node ? inline_node->Layout(space, break_token, context)
- : To<NGBlockNode>(node)->Layout(space, break_token);
+ if (auto* inline_node = DynamicTo<NGInlineNode>(node))
+ return inline_node->Layout(space, break_token, context);
+ return LayoutBlockChild(space, break_token, early_break,
+ To<NGBlockNode>(node));
}
NGAdjoiningObjectTypes ToAdjoiningObjectTypes(EClear clear) {
@@ -137,6 +159,16 @@ LogicalOffset LogicalFromBfcOffsets(const NGBfcOffset& child_bfc_offset,
child_bfc_offset.block_offset - parent_bfc_offset.block_offset};
}
+inline bool IsEarlyBreakpoint(const NGEarlyBreak& breakpoint,
+ const NGBoxFragmentBuilder& builder,
+ NGLayoutInputNode child) {
+ if (breakpoint.Type() == NGEarlyBreak::kLine)
+ return child.IsInline() && breakpoint.LineNumber() == builder.LineCount();
+ if (breakpoint.IsBreakBefore())
+ return breakpoint.BlockNode() == child;
+ return false;
+}
+
} // namespace
NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
@@ -147,7 +179,8 @@ NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(
border_scrollbar_padding_(border_padding_ +
params.fragment_geometry.scrollbar),
is_resuming_(IsResumingLayout(params.break_token)),
- exclusion_space_(params.space.ExclusionSpace()) {
+ exclusion_space_(params.space.ExclusionSpace()),
+ early_break_(params.early_break) {
container_builder_.SetIsNewFormattingContext(
params.space.IsNewFormattingContext());
container_builder_.SetInitialFragmentGeometry(params.fragment_geometry);
@@ -326,12 +359,22 @@ LogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
}
scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
+ scoped_refptr<const NGLayoutResult> result;
// Inline children require an inline child layout context to be
// passed between siblings. We want to stack-allocate that one, but
// only on demand, as it's quite big.
if (Node().ChildrenInline())
- return LayoutWithInlineChildLayoutContext();
- return Layout(nullptr);
+ result = LayoutWithInlineChildLayoutContext();
+ else
+ result = Layout(nullptr);
+ if (UNLIKELY(result->Status() == NGLayoutResult::kNeedsEarlierBreak)) {
+ // If we found a good break somewhere inside this block, re-layout and break
+ // at that location.
+ DCHECK(!early_break_);
+ DCHECK(result->GetEarlyBreak());
+ return RelayoutAndBreakEarlier(*result->GetEarlyBreak());
+ }
+ return result;
}
NOINLINE scoped_refptr<const NGLayoutResult>
@@ -357,6 +400,22 @@ NGBlockLayoutAlgorithm::LayoutWithItemsBuilder(
return result;
}
+NOINLINE scoped_refptr<const NGLayoutResult>
+NGBlockLayoutAlgorithm::RelayoutAndBreakEarlier(
+ const NGEarlyBreak& breakpoint) {
+ NGLayoutAlgorithmParams params(Node(),
+ container_builder_.InitialFragmentGeometry(),
+ ConstraintSpace(), BreakToken(), &breakpoint);
+ NGBlockLayoutAlgorithm algorithm_with_break(params);
+ NGBoxFragmentBuilder& new_builder = algorithm_with_break.container_builder_;
+ new_builder.SetBoxType(container_builder_.BoxType());
+ // We're not going to run out of space in the next layout pass, since we're
+ // breaking earlier, so no space shortage will be detected. Repeat what we
+ // found in this pass.
+ new_builder.PropagateSpaceShortage(container_builder_.MinimalSpaceShortage());
+ return algorithm_with_break.Layout();
+}
+
inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
NGInlineChildLayoutContext* inline_child_layout_context) {
const LogicalSize border_box_size = container_builder_.InitialBorderBoxSize();
@@ -376,8 +435,16 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
ConstraintSpace(), Style(), container_builder_.Scrollbar());
}
- if (ConstraintSpace().HasBlockFragmentation())
+ if (ConstraintSpace().HasBlockFragmentation()) {
container_builder_.SetHasBlockFragmentation();
+ // The whereabouts of our container's so far best breakpoint is none of our
+ // business, but we store its appeal, so that we don't look for breakpoints
+ // with lower appeal than that.
+ container_builder_.SetBreakAppeal(ConstraintSpace().EarlyBreakAppeal());
+
+ if (ConstraintSpace().IsInitialColumnBalancingPass())
+ container_builder_.SetIsInitialColumnBalancingPass();
+ }
container_builder_.SetBfcLineOffset(
ConstraintSpace().BfcOffset().line_offset);
@@ -521,19 +588,37 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
// we'll need to keep looking for subsequent content on the way up the
// tree.
if (NGLayoutInputNode next = child.NextSibling()) {
- container_builder_.AddBreakBeforeChild(next,
+ container_builder_.AddBreakBeforeChild(next, kBreakAppealPerfect,
/* is_forced_break */ true);
- container_builder_.SetDidBreak();
}
break;
} else {
- bool abort;
+ // If this is the child we had previously determined to break before, do
+ // so now and finish layout.
+ if (UNLIKELY(
+ early_break_ &&
+ IsEarlyBreakpoint(*early_break_, container_builder_, child))) {
+ if (!ResolveBfcBlockOffset(&previous_inflow_position)) {
+ // However, the predetermined breakpoint may be exactly where the BFC
+ // block-offset gets resolved. If that hasn't yet happened, we need to
+ // do that first and re-layout at the right BFC block-offset, and THEN
+ // break.
+ return container_builder_.Abort(
+ NGLayoutResult::kBfcBlockOffsetResolved);
+ }
+ BreakBeforeChild(child, kBreakAppealPerfect,
+ /* is_forced_break */ false,
+ &previous_inflow_position);
+ break;
+ }
+
+ NGLayoutResult::EStatus status;
if (child.CreatesNewFormattingContext()) {
- abort = !HandleNewFormattingContext(child, child_break_token,
+ status = HandleNewFormattingContext(child, child_break_token,
&previous_inflow_position);
previous_inline_break_token = nullptr;
} else {
- abort = !HandleInflow(
+ status = HandleInflow(
child, child_break_token, &previous_inflow_position,
inline_child_layout_context, &previous_inline_break_token);
if (container_builder_.FoundColumnSpanner())
@@ -545,10 +630,9 @@ inline scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::Layout(
// container.
DCHECK(!container_builder_.FoundColumnSpanner());
- if (abort) {
- // We need to abort the layout, as our BFC block offset was resolved.
- return container_builder_.Abort(
- NGLayoutResult::kBfcBlockOffsetResolved);
+ if (status != NGLayoutResult::kSuccess) {
+ // We need to abort the layout. No fragment will be generated.
+ return container_builder_.Abort(status);
}
if (ConstraintSpace().HasBlockFragmentation()) {
if (container_builder_.DidBreak() &&
@@ -661,6 +745,9 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
intrinsic_block_size_ = std::max(intrinsic_block_size_,
CalculateMinimumBlockSize(end_margin_strut));
+ // Save the unconstrained intrinsic size on the builder before clamping it.
+ container_builder_.SetUnconstrainedIntrinsicBlockSize(intrinsic_block_size_);
+
// TODO(layout-dev): Is CalculateMinimumBlockSize common to other algorithms,
// and should move into ClampIntrinsicBlockSize?
intrinsic_block_size_ = ClampIntrinsicBlockSize(
@@ -685,10 +772,11 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
if (container_builder_.BfcBlockOffset()) {
// Do not collapse margins between the last in-flow child and bottom margin
// of its parent if:
- // - The parent has block-size != auto.
// - The block-size differs from the intrinsic size.
- if (!Style().LogicalHeight().IsAuto() ||
- border_box_size.block_size != intrinsic_block_size_) {
+ // - The parent has computed block-size != auto.
+ if (border_box_size.block_size != intrinsic_block_size_ ||
+ !BlockLengthUnresolvable(ConstraintSpace(), Style().LogicalHeight(),
+ LengthResolvePhase::kLayout)) {
end_margin_strut = NGMarginStrut();
}
}
@@ -726,8 +814,10 @@ scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::FinishLayout(
// 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 (container_builder_.BfcBlockOffset() &&
- ConstraintSpace().HasBlockFragmentation())
- FinalizeForFragmentation();
+ ConstraintSpace().HasBlockFragmentation()) {
+ if (!FinalizeForFragmentation())
+ return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+ }
NGOutOfFlowLayoutPart(
Node(), ConstraintSpace(),
@@ -930,7 +1020,7 @@ void NGBlockLayoutAlgorithm::HandleFloat(
container_builder_.AddResult(*positioned_float.layout_result, logical_offset);
}
-bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
+NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleNewFormattingContext(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
NGPreviousInflowPosition* previous_inflow_position) {
@@ -948,8 +1038,7 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
LayoutUnit child_origin_line_offset =
ConstraintSpace().BfcOffset().line_offset +
- border_scrollbar_padding_.LineLeft(direction) +
- child_data.margins.LineLeft(direction).ClampNegativeToZero();
+ border_scrollbar_padding_.LineLeft(direction);
// If the child has a block-start margin, and the BFC block offset is still
// unresolved, and we have preceding adjoining floats, things get complicated
@@ -1023,7 +1112,7 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
// If we need to abort here, it means that we had preceding unpositioned
// floats. This is only expected if we're here for the first time.
DCHECK(!bfc_offset_already_resolved);
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
}
// We reset the block offset here as it may have been affected by clearance.
@@ -1044,11 +1133,12 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
bool abort_if_cleared = child_data.margins.block_start != LayoutUnit() &&
!child_margin_got_separated &&
child_determined_bfc_offset;
- NGLayoutOpportunity opportunity;
- scoped_refptr<const NGLayoutResult> layout_result;
- std::tie(layout_result, opportunity) = LayoutNewFormattingContext(
- child, child_break_token, child_data,
- {child_origin_line_offset, child_bfc_offset_estimate}, abort_if_cleared);
+ NGBfcOffset child_bfc_offset;
+ scoped_refptr<const NGLayoutResult> layout_result =
+ LayoutNewFormattingContext(
+ child, child_break_token, child_data,
+ {child_origin_line_offset, child_bfc_offset_estimate},
+ abort_if_cleared, &child_bfc_offset);
if (!layout_result) {
DCHECK(abort_if_cleared);
@@ -1081,97 +1171,40 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
// incorrect estimate is with the child's margin adjoining. Any other
// incorrect estimate will result in failed layout.
DCHECK_EQ(old_offset, adjoining_bfc_offset_estimate);
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
}
}
- DCHECK_GT(opportunity.rect.start_offset.block_offset,
- child_bfc_offset_estimate);
child_bfc_offset_estimate = non_adjoining_bfc_offset_estimate;
child_margin_got_separated = true;
// We can re-layout the child right away. This re-layout *must* produce a
- // fragment and opportunity which fits within the exclusion space.
- std::tie(layout_result, opportunity) = LayoutNewFormattingContext(
+ // fragment which fits within the exclusion space.
+ layout_result = LayoutNewFormattingContext(
child, child_break_token, child_data,
{child_origin_line_offset, child_bfc_offset_estimate},
- /* abort_if_cleared */ false);
+ /* abort_if_cleared */ false, &child_bfc_offset);
}
NGFragment fragment(ConstraintSpace().GetWritingMode(),
layout_result->PhysicalFragment());
- // Auto-margins are applied within the layout opportunity which fits. We'll
- // pretend that computed margins are 0 here, as they have already been
- // excluded from the layout opportunity rectangle.
- NGBoxStrut auto_margins;
- if (child.IsListMarker()) {
- // Deal with marker's margin. It happens only when marker needs to occupy
- // the whole line.
- DCHECK(child.ListMarkerOccupiesWholeLine());
- // Because the marker is laid out as a normal block child, its inline size
- // is extended to fill up the space. Compute the regular marker size from
- // the first child.
- const NGPhysicalContainerFragment& marker_fragment =
- layout_result->PhysicalFragment();
- LayoutUnit marker_inline_size = LayoutUnit();
- if (!marker_fragment.Children().empty()) {
- const NGPhysicalFragment& marker_child_fragment =
- *marker_fragment.Children().front();
- marker_inline_size =
- marker_child_fragment.Size()
- .ConvertToLogical(ConstraintSpace().GetWritingMode())
- .inline_size;
- }
- auto_margins.inline_start = NGUnpositionedListMarker(To<NGBlockNode>(child))
- .InlineOffset(marker_inline_size);
- auto_margins.inline_end = opportunity.rect.InlineSize() -
- fragment.InlineSize() - auto_margins.inline_start;
- } else {
- LayoutUnit inline_size = fragment.InlineSize();
- // Negative margins are not used to determine opportunity, but need to take
- // them into account for positioning.
- LayoutUnit inline_margin = child_data.margins.InlineSum();
- if (inline_margin < 0)
- inline_size += inline_margin;
- ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(),
- inline_size, &auto_margins);
- }
-
- LayoutUnit child_bfc_line_offset = opportunity.rect.start_offset.line_offset +
- auto_margins.LineLeft(direction);
-
- // When there are negative margins present, a new formatting context can move
- // outside its layout opportunity. This occurs when the *line-left* edge
- // hasn't been shifted by floats.
- //
- // NOTE: Firefox and EdgeHTML both match this behaviour of only considering
- // the line-left edge. WebKit also considers this line-right edge, but this
- // is slightly more complicated to implement, and probably not needed for web
- // compatibility.
- bool can_move_outside_opportunity =
- opportunity.rect.start_offset.line_offset == child_origin_line_offset;
-
- if (can_move_outside_opportunity) {
- child_bfc_line_offset +=
- child_data.margins.LineLeft(direction).ClampPositiveToZero();
- }
-
- NGBfcOffset child_bfc_offset(child_bfc_line_offset,
- opportunity.rect.start_offset.block_offset);
-
LogicalOffset logical_offset = LogicalFromBfcOffsets(
child_bfc_offset, ContainerBfcOffset(), fragment.InlineSize(),
container_builder_.Size().inline_size, ConstraintSpace().Direction());
if (ConstraintSpace().HasBlockFragmentation()) {
- bool is_pushed_by_floats =
- child_margin_got_separated ||
+ bool has_container_separation =
+ has_processed_first_child_ || child_margin_got_separated ||
child_bfc_offset.block_offset > child_bfc_offset_estimate ||
layout_result->IsPushedByFloats();
- if (BreakBeforeChild(child, *layout_result, previous_inflow_position,
- logical_offset.block_offset, is_pushed_by_floats))
- return true;
+ BreakStatus break_status = BreakBeforeChildIfNeeded(
+ child, *layout_result, previous_inflow_position,
+ logical_offset.block_offset, has_container_separation);
+ if (break_status == kBrokeBefore)
+ return NGLayoutResult::kSuccess;
+ if (break_status == kNeedsEarlierBreak)
+ return NGLayoutResult::kNeedsEarlierBreak;
EBreakBetween break_after = JoinFragmentainerBreakValues(
layout_result->FinalBreakAfter(), child.Style().BreakAfter());
container_builder_.SetPreviousBreakAfter(break_after);
@@ -1179,7 +1212,7 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
if (!PositionOrPropagateListMarker(*layout_result, &logical_offset,
previous_inflow_position))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
container_builder_.AddResult(*layout_result, logical_offset);
@@ -1195,39 +1228,31 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
child_bfc_offset.block_offset, logical_offset, *layout_result, fragment,
/* self_collapsing_child_had_clearance */ false);
- return true;
+ return NGLayoutResult::kSuccess;
}
-std::pair<scoped_refptr<const NGLayoutResult>, NGLayoutOpportunity>
+scoped_refptr<const NGLayoutResult>
NGBlockLayoutAlgorithm::LayoutNewFormattingContext(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
const NGInflowChildData& child_data,
NGBfcOffset origin_offset,
- bool abort_if_cleared) {
+ bool abort_if_cleared,
+ NGBfcOffset* out_child_bfc_offset) {
+ const ComputedStyle& child_style = child.Style();
+ const TextDirection direction = ConstraintSpace().Direction();
+ const WritingMode writing_mode = ConstraintSpace().GetWritingMode();
+
// The origin offset is where we should start looking for layout
// opportunities. It needs to be adjusted by the child's clearance.
AdjustToClearance(
- exclusion_space_.ClearanceOffset(child.Style().Clear(Style())),
+ exclusion_space_.ClearanceOffset(child_style.Clear(Style())),
&origin_offset);
DCHECK(container_builder_.BfcBlockOffset());
- // Before we lay out, figure out how much inline space we have available at
- // the start block offset estimate (the child is not allowed to overlap with
- // floats, so we need to find out how much space is used by floats at this
- // block offset). This may affect the inline size of the child, e.g. when it's
- // specified as auto, or if it's a table (with table-layout:auto). This will
- // not affect percentage resolution, because that's going to be resolved
- // against the containing block, regardless of adjacent floats. When looking
- // for space, we ignore inline margins, as they will overlap with any adjacent
- // floats.
- LayoutUnit inline_margin = child_data.margins.InlineSum();
- LayoutUnit inline_size =
- (child_available_size_.inline_size - inline_margin.ClampNegativeToZero())
- .ClampNegativeToZero();
-
LayoutOpportunityVector opportunities =
- exclusion_space_.AllLayoutOpportunities(origin_offset, inline_size);
+ exclusion_space_.AllLayoutOpportunities(
+ origin_offset, child_available_size_.inline_size);
// We should always have at least one opportunity.
DCHECK_GT(opportunities.size(), 0u);
@@ -1243,59 +1268,123 @@ NGBlockLayoutAlgorithm::LayoutNewFormattingContext(
// Abort if we got pushed downwards. We need to adjust
// origin_offset.block_offset, reposition any floats affected by that, and
// try again.
- return std::make_pair(nullptr, opportunity);
+ return nullptr;
}
+ // Find the available inline-size which should be given to the child.
+ LayoutUnit line_left_offset = opportunity.rect.start_offset.line_offset;
+ LayoutUnit line_right_offset = opportunity.rect.end_offset.line_offset;
+
+ LayoutUnit line_left_margin = child_data.margins.LineLeft(direction);
+ LayoutUnit line_right_margin = child_data.margins.LineRight(direction);
+
// When the inline dimensions of layout opportunity match the available
- // space, a new formatting context can expand outside of the opportunity if
- // negative margins are present.
+ // inline-size, a new formatting context can expand outside of the
+ // opportunity if negative margins are present.
bool can_expand_outside_opportunity =
- (opportunity.rect.start_offset.line_offset ==
- origin_offset.line_offset &&
- opportunity.rect.InlineSize() == inline_size);
-
- LayoutUnit inline_negative_margin =
- can_expand_outside_opportunity ? inline_margin.ClampPositiveToZero()
- : LayoutUnit();
+ opportunity.rect.start_offset.line_offset ==
+ origin_offset.line_offset &&
+ opportunity.rect.InlineSize() == child_available_size_.inline_size;
+
+ if (can_expand_outside_opportunity) {
+ // No floats have affected the available inline-size, adjust the
+ // available inline-size by the margins.
+ DCHECK_EQ(line_left_offset, origin_offset.line_offset);
+ DCHECK_EQ(line_right_offset,
+ origin_offset.line_offset + child_available_size_.inline_size);
+ line_left_offset += line_left_margin;
+ line_right_offset -= line_right_margin;
+ } else {
+ // Margins are applied from the content-box, not the layout opportunity
+ // area. Instead of adjusting by the size of the margins, we "shrink" the
+ // available inline-size if required.
+ line_left_offset = std::max(
+ line_left_offset,
+ origin_offset.line_offset + line_left_margin.ClampNegativeToZero());
+ line_right_offset = std::min(line_right_offset,
+ origin_offset.line_offset +
+ child_available_size_.inline_size -
+ line_right_margin.ClampNegativeToZero());
+ }
+ LayoutUnit opportunity_size =
+ (line_right_offset - line_left_offset).ClampNegativeToZero();
// The available inline size in the child constraint space needs to include
// inline margins, since layout algorithms (both legacy and NG) will resolve
// auto inline size by subtracting the inline margins from available inline
// size. We have calculated a layout opportunity without margins in mind,
// since they overlap with adjacent floats. Now we need to add them.
- LogicalSize child_available_size = {
- (opportunity.rect.InlineSize() - inline_negative_margin + inline_margin)
- .ClampNegativeToZero(),
- child_available_size_.block_size};
+ LayoutUnit child_available_inline_size =
+ (opportunity_size + child_data.margins.InlineSum())
+ .ClampNegativeToZero();
+
NGConstraintSpace child_space = CreateConstraintSpaceForChild(
- child, child_data, child_available_size, /* is_new_fc */ true);
+ child, child_data,
+ {child_available_inline_size, child_available_size_.block_size},
+ /* is_new_fc */ true);
// All formatting context roots (like this child) should start with an empty
// exclusion space.
DCHECK(child_space.ExclusionSpace().IsEmpty());
- scoped_refptr<const NGLayoutResult> layout_result =
- To<NGBlockNode>(child).Layout(child_space, child_break_token);
+ scoped_refptr<const NGLayoutResult> layout_result = LayoutBlockChild(
+ child_space, child_break_token, early_break_, &To<NGBlockNode>(child));
// Since this child establishes a new formatting context, no exclusion space
// should be returned.
DCHECK(layout_result->ExclusionSpace().IsEmpty());
- NGFragment fragment(ConstraintSpace().GetWritingMode(),
- layout_result->PhysicalFragment());
+ NGFragment fragment(writing_mode, layout_result->PhysicalFragment());
+
+ // Check if the fragment will fit in this layout opportunity, if not proceed
+ // to the next opportunity.
+ if ((fragment.InlineSize() > opportunity.rect.InlineSize() &&
+ !can_expand_outside_opportunity) ||
+ fragment.BlockSize() > opportunity.rect.BlockSize())
+ continue;
+
+ // Now find the fragment's (final) position calculating the auto margins.
+ NGBoxStrut auto_margins = child_data.margins;
+ if (child.IsListMarker()) {
+ // Deal with marker's margin. It happens only when marker needs to occupy
+ // the whole line.
+ DCHECK(child.ListMarkerOccupiesWholeLine());
+ // Because the marker is laid out as a normal block child, its inline
+ // size is extended to fill up the space. Compute the regular marker size
+ // from the first child.
+ const auto& marker_fragment = layout_result->PhysicalFragment();
+ LayoutUnit marker_inline_size;
+ if (!marker_fragment.Children().empty()) {
+ marker_inline_size =
+ NGFragment(writing_mode, *marker_fragment.Children().front())
+ .InlineSize();
+ }
+ auto_margins.inline_start =
+ NGUnpositionedListMarker(To<NGBlockNode>(child))
+ .InlineOffset(marker_inline_size);
+ auto_margins.inline_end = opportunity.rect.InlineSize() -
+ fragment.InlineSize() -
+ auto_margins.inline_start;
+ } else {
+ ResolveInlineMargins(child_style, Style(), child_available_inline_size,
+ fragment.InlineSize(), &auto_margins);
+ }
- // Now we can check if the fragment will fit in this layout opportunity.
- if ((opportunity.rect.InlineSize() >= fragment.InlineSize() ||
- opportunity.rect.InlineSize() == inline_size) &&
- opportunity.rect.BlockSize() >= fragment.BlockSize())
- return std::make_pair(std::move(layout_result), opportunity);
+ // |auto_margins| are initialized as a copy of the child's initial margins.
+ // To determine the effect of the auto-margins we only apply the difference.
+ LayoutUnit auto_margin_line_left =
+ auto_margins.LineLeft(direction) - line_left_margin;
+
+ *out_child_bfc_offset = {line_left_offset + auto_margin_line_left,
+ opportunity.rect.start_offset.block_offset};
+ return layout_result;
}
NOTREACHED();
- return std::make_pair(nullptr, NGLayoutOpportunity());
+ return nullptr;
}
-bool NGBlockLayoutAlgorithm::HandleInflow(
+NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleInflow(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
NGPreviousInflowPosition* previous_inflow_position,
@@ -1314,9 +1403,9 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
*previous_inline_break_token = TryReuseFragmentsFromCache(
*child_inline_node, previous_inflow_position, &aborted);
if (*previous_inline_break_token)
- return true;
+ return NGLayoutResult::kSuccess;
if (aborted)
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
}
bool is_non_empty_inline =
@@ -1338,7 +1427,7 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
// keep in sync.
if (has_clearance_past_adjoining_floats || is_non_empty_inline) {
if (!ResolveBfcBlockOffset(previous_inflow_position))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
// If we had clearance past any adjoining floats, we already know where the
// child is going to be (the child's margins won't have any effect).
@@ -1358,8 +1447,9 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
NGConstraintSpace child_space = CreateConstraintSpaceForChild(
child, child_data, child_available_size_, /* is_new_fc */ false,
forced_bfc_block_offset, has_clearance_past_adjoining_floats);
- scoped_refptr<const NGLayoutResult> layout_result = LayoutInflow(
- child_space, child_break_token, &child, inline_child_layout_context);
+ scoped_refptr<const NGLayoutResult> layout_result =
+ LayoutInflow(child_space, child_break_token, early_break_, &child,
+ inline_child_layout_context);
// To save space of the stack when we recurse into |NGBlockNode::Layout|
// above, the rest of this function is continued within |FinishInflow|.
@@ -1371,7 +1461,7 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
previous_inline_break_token);
}
-bool NGBlockLayoutAlgorithm::FinishInflow(
+NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
const NGConstraintSpace& child_space,
@@ -1425,7 +1515,7 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
if (!ResolveBfcBlockOffset(previous_inflow_position, bfc_block_offset,
/* forced_bfc_block_offset */ base::nullopt))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
}
// We have special behaviour for a self-collapsing child which gets pushed
@@ -1458,7 +1548,7 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
// is therefore resolvable, and if it hasn't already been resolved, we'll
// do it now to separate the child's collapsed margin from this container.
if (!ResolveBfcBlockOffset(previous_inflow_position))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
} else if (layout_result->SubtreeModifiedMarginStrut()) {
// The child doesn't have clearance, and modified its incoming
// margin-strut. Propagate this information up to our parent if needed.
@@ -1493,7 +1583,7 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
// resolved.
if (!ResolveBfcBlockOffset(previous_inflow_position,
*child_bfc_block_offset))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
}
// We need to re-layout a self-collapsing child if it was affected by
@@ -1535,8 +1625,9 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
NGConstraintSpace new_child_space = CreateConstraintSpaceForChild(
child, *child_data, child_available_size_, /* is_new_fc */ false,
child_bfc_block_offset);
- layout_result = LayoutInflow(new_child_space, child_break_token, &child,
- inline_child_layout_context);
+ layout_result =
+ LayoutInflow(new_child_space, child_break_token, early_break_, &child,
+ inline_child_layout_context);
if (layout_result->Status() == NGLayoutResult::kBfcBlockOffsetResolved) {
// Even a second layout pass may abort, if the BFC block offset initially
@@ -1549,8 +1640,9 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
new_child_space = CreateConstraintSpaceForChild(
child, *child_data, child_available_size_, /* is_new_fc */ false,
child_bfc_block_offset);
- layout_result = LayoutInflow(new_child_space, child_break_token, &child,
- inline_child_layout_context);
+ layout_result =
+ LayoutInflow(new_child_space, child_break_token, early_break_, &child,
+ inline_child_layout_context);
}
DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
@@ -1595,10 +1687,19 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
fragment, layout_result->BfcLineOffset(), child_bfc_block_offset);
if (ConstraintSpace().HasBlockFragmentation()) {
- if (BreakBeforeChild(child, *layout_result, previous_inflow_position,
- logical_offset.block_offset,
- layout_result->IsPushedByFloats()))
- return true;
+ // 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());
+ BreakStatus break_status = BreakBeforeChildIfNeeded(
+ child, *layout_result, previous_inflow_position,
+ logical_offset.block_offset, has_container_separation);
+ if (break_status == kBrokeBefore)
+ return NGLayoutResult::kSuccess;
+ if (break_status == kNeedsEarlierBreak)
+ return NGLayoutResult::kNeedsEarlierBreak;
EBreakBetween break_after = JoinFragmentainerBreakValues(
layout_result->FinalBreakAfter(), child.Style().BreakAfter());
container_builder_.SetPreviousBreakAfter(break_after);
@@ -1606,7 +1707,7 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
if (!PositionOrPropagateListMarker(*layout_result, &logical_offset,
previous_inflow_position))
- return false;
+ return NGLayoutResult::kBfcBlockOffsetResolved;
container_builder_.AddResult(*layout_result, logical_offset);
@@ -1643,15 +1744,14 @@ bool NGBlockLayoutAlgorithm::FinishInflow(
// If we still haven't found a descendant at which to resume column
// layout after the spanner, look for one now.
if (NGLayoutInputNode next = child.NextSibling()) {
- container_builder_.AddBreakBeforeChild(next,
+ container_builder_.AddBreakBeforeChild(next, kBreakAppealPerfect,
/* is_forced_break */ true);
- container_builder_.SetDidBreak();
}
}
}
}
- return true;
+ return NGLayoutResult::kSuccess;
}
NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData(
@@ -1872,29 +1972,81 @@ LayoutUnit NGBlockLayoutAlgorithm::PositionSelfCollapsingChildWithParentBfc(
LayoutUnit NGBlockLayoutAlgorithm::FragmentainerSpaceAvailable() const {
DCHECK(container_builder_.BfcBlockOffset());
- return ConstraintSpace().FragmentainerSpaceAtBfcStart() -
+ return FragmentainerSpaceAtBfcStart(ConstraintSpace()) -
*container_builder_.BfcBlockOffset();
}
bool NGBlockLayoutAlgorithm::IsFragmentainerOutOfSpace(
LayoutUnit block_offset) const {
- if (!ConstraintSpace().HasBlockFragmentation())
+ if (did_break_before_child_)
+ return true;
+ if (!ConstraintSpace().HasKnownFragmentainerBlockSize())
return false;
if (!container_builder_.BfcBlockOffset().has_value())
return false;
return block_offset >= FragmentainerSpaceAvailable();
}
-void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
- if (first_overflowing_line_ && !fit_all_lines_) {
- // A line box overflowed the fragmentainer, but we continued layout anyway,
- // in order to determine where to break in order to honor the widows
- // request. We never got around to actually breaking, before we ran out of
- // lines. So do it now.
- intrinsic_block_size_ = FragmentainerSpaceAvailable();
- container_builder_.SetDidBreak();
+LayoutUnit NGBlockLayoutAlgorithm::OffsetFromFragmentainerStart() const {
+ DCHECK(container_builder_.BfcBlockOffset());
+ return ConstraintSpace().FragmentainerOffsetAtBfc() +
+ *container_builder_.BfcBlockOffset();
+}
+
+LayoutUnit NGBlockLayoutAlgorithm::PortionIntersectingWithFragmentainer(
+ LayoutUnit block_offset,
+ LayoutUnit block_size) const {
+ LayoutUnit offset_from_fragmentainer_start =
+ OffsetFromFragmentainerStart() + block_offset;
+ // Whatever is before the block-start of the fragmentainer isn't considered to
+ // intersect with the fragmentainer, so subtract it (by adding the negative
+ // offset).
+ if (offset_from_fragmentainer_start < LayoutUnit())
+ block_size += offset_from_fragmentainer_start;
+ return block_size;
+}
+
+void NGBlockLayoutAlgorithm::PropagateUnbreakableBlockSize(
+ LayoutUnit block_offset,
+ LayoutUnit block_size) {
+ DCHECK(ConstraintSpace().IsInitialColumnBalancingPass());
+ block_size = PortionIntersectingWithFragmentainer(block_offset, block_size);
+ container_builder_.PropagateTallestUnbreakableBlockSize(block_size);
+}
+
+bool NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
+ if (Node().ChildrenInline() && !early_break_) {
+ if (container_builder_.DidBreak() || first_overflowing_line_) {
+ if (first_overflowing_line_ &&
+ first_overflowing_line_ < container_builder_.LineCount()) {
+ int line_number;
+ if (fit_all_lines_) {
+ line_number = first_overflowing_line_;
+ } else {
+ // We managed to finish layout of all the lines for the node, which
+ // means that we won't have enough widows, unless we break earlier
+ // than where we overflowed.
+ int line_count = container_builder_.LineCount();
+ line_number = std::max(line_count - Style().Widows(),
+ std::min(line_count, int(Style().Orphans())));
+ }
+ // We need to layout again, and stop at the right line number.
+ scoped_refptr<const NGEarlyBreak> breakpoint =
+ base::AdoptRef(new NGEarlyBreak(line_number));
+ container_builder_.SetEarlyBreak(breakpoint, kBreakAppealPerfect);
+ return false;
+ }
+ } else {
+ // Everything could fit in the current fragmentainer, but, depending on
+ // what comes after, the best location to break at may be between two of
+ // our lines.
+ UpdateEarlyBreakBetweenLines();
+ }
}
+ if (!ConstraintSpace().HasKnownFragmentainerBlockSize())
+ return true;
+
LayoutUnit consumed_block_size =
BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
LayoutUnit block_size =
@@ -1919,58 +2071,135 @@ void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
// detect that there's no room for a fragment for this node, and drop the
// fragment on the floor. Therefore it doesn't matter how we set up the
// container builder, so just return.
- return;
+ return true;
}
- if (container_builder_.DidBreak() && first_overflowing_line_) {
- int line_number;
- if (fit_all_lines_) {
- line_number = first_overflowing_line_;
- } else {
- // We managed to finish layout of all the lines for the node, which means
- // that we won't have enough widows, unless we break earlier than where we
- // overflowed.
- int line_count = container_builder_.LineCount();
- line_number = std::max(line_count - Style().Widows(),
- std::min(line_count, int(Style().Orphans())));
- }
- container_builder_.AddBreakBeforeLine(line_number);
- }
+ FinishFragmentation(ConstraintSpace(), block_size, intrinsic_block_size_,
+ consumed_block_size, space_left, &container_builder_);
- FinishFragmentation(&container_builder_, block_size, intrinsic_block_size_,
- consumed_block_size, space_left);
+ return true;
}
-bool NGBlockLayoutAlgorithm::BreakBeforeChild(
+NGBlockLayoutAlgorithm::BreakStatus
+NGBlockLayoutAlgorithm::BreakBeforeChildIfNeeded(
NGLayoutInputNode child,
const NGLayoutResult& layout_result,
NGPreviousInflowPosition* previous_inflow_position,
LayoutUnit block_offset,
- bool is_pushed_by_floats) {
+ bool has_container_separation) {
DCHECK(ConstraintSpace().HasBlockFragmentation());
- BreakType break_type = BreakTypeBeforeChild(
- child, layout_result, block_offset, is_pushed_by_floats);
- if (break_type == NoBreak)
- return false;
- LayoutUnit space_available = FragmentainerSpaceAvailable();
- LayoutUnit space_shortage;
- if (layout_result.MinimalSpaceShortage() == LayoutUnit::Max()) {
- // Calculate space shortage: Figure out how much more space would have been
- // sufficient to make the child fit right here in the current fragment.
- NGFragment fragment(ConstraintSpace().GetWritingMode(),
- layout_result.PhysicalFragment());
- LayoutUnit space_left = space_available - block_offset;
- space_shortage = fragment.BlockSize() - space_left;
+ // If the BFC offset is unknown, there's nowhere to break, since there's no
+ // non-empty child content yet (as that would have resolved the BFC offset).
+ if (!container_builder_.BfcBlockOffset())
+ return kContinueWithoutBreaking;
+
+ // If we already know where to insert the break, we already know that it's not
+ // going to be here, since that's something we check before entering layout of
+ // a child.
+ if (early_break_)
+ return kContinueWithoutBreaking;
+
+ NGBreakAppeal appeal_before = kBreakAppealPerfect;
+ if (has_container_separation) {
+ EBreakBetween break_between =
+ CalculateBreakBetweenValue(child, layout_result, container_builder_);
+ if (IsForcedBreakValue(ConstraintSpace(), break_between)) {
+ BreakBeforeChild(child, layout_result, block_offset, kBreakAppealPerfect,
+ /* is_forced_break */ true, previous_inflow_position);
+ return kBrokeBefore;
+ }
+
+ // If there's a break-{after,before}:avoid* involved at this breakpoint,
+ // its appeal will decrease.
+ if (IsAvoidBreakValue(ConstraintSpace(), break_between))
+ appeal_before = kBreakAppealViolatingBreakAvoid;
} else {
- // However, if space shortage was reported inside the child, use that. If we
- // broke inside the child, we didn't complete layout, so calculating space
- // shortage for the child as a whole would be impossible and pointless.
- space_shortage = layout_result.MinimalSpaceShortage();
+ // This is not a valid break point. If there's no container separation, it
+ // means that we're breaking before the first piece of in-flow content
+ // inside this block, even if it's not a valid class C break point [1] We
+ // really don't want to break here, if we can find something better.
+ //
+ // [1] https://www.w3.org/TR/css-break-3/#possible-breaks
+ appeal_before = kBreakAppealLastResort;
+ }
+
+ const auto& physical_fragment = layout_result.PhysicalFragment();
+ NGFragment fragment(ConstraintSpace().GetWritingMode(), physical_fragment);
+
+ if (!ConstraintSpace().HasKnownFragmentainerBlockSize()) {
+ if (ConstraintSpace().IsInitialColumnBalancingPass()) {
+ if (child.IsMonolithic() ||
+ (child.IsBlock() &&
+ IsAvoidBreakValue(ConstraintSpace(), child.Style().BreakInside()))) {
+ // If this is the initial column balancing pass, attempt to make the
+ // column block-size at least as large as the tallest piece of
+ // monolithic content and/or block with break-inside:avoid.
+ PropagateUnbreakableBlockSize(block_offset, fragment.BlockSize());
+ }
+ }
+ // We only care about soft breaks if we have a fragmentainer block-size.
+ // During column balancing this may be unknown.
+ return kContinueWithoutBreaking;
+ }
+
+ if (IsA<NGBlockBreakToken>(physical_fragment.BreakToken())) {
+ // The block child broke inside. We now need to decide whether to keep that
+ // break, or if it would be better to break before it.
+ NGBreakAppeal appeal_inside = CalculateBreakAppealInside(
+ ConstraintSpace(), To<NGBlockNode>(child), layout_result);
+ // Allow breaking inside if it has the same appeal or higher than breaking
+ // before or breaking earlier.
+ if (appeal_inside >= appeal_before &&
+ (!container_builder_.HasEarlyBreak() ||
+ appeal_inside >= container_builder_.BreakAppeal())) {
+ container_builder_.SetBreakAppeal(appeal_inside);
+ return kContinueWithoutBreaking;
+ }
+ } else {
+ LayoutUnit space_left = FragmentainerSpaceAvailable() - block_offset;
+ bool want_break;
+ if (child.IsMonolithic()) {
+ // If the monolithic piece of content (e.g. a line, or block-level
+ // replaced content) doesn't fit, we need a break.
+ want_break = fragment.BlockSize() > space_left;
+ } else {
+ // If the block-offset is past the fragmentainer boundary (or exactly at
+ // the boundary), no part of the fragment is going to fit in the current
+ // fragmentainer. Fragments may be pushed past the fragmentainer boundary
+ // by margins.
+ want_break = space_left <= LayoutUnit();
+ }
+ if (want_break) {
+ // If we haven't used any space at all in the fragmentainer yet, though,
+ // we cannot break even if we really want to, or there'd be no progress.
+ // We'd end up creating an infinite number of fragmentainers without
+ // putting any content into them.
+ if (space_left >= ConstraintSpace().FragmentainerBlockSize())
+ want_break = false;
+ }
+
+ if (!want_break) {
+ if (child.IsBlock()) {
+ // If this doesn't happen, though, we're tentatively not going to break
+ // before or inside this child, but we'll check the appeal of breaking
+ // there anyway. It may be the best breakpoint we'll ever find. (Note
+ // that we only do this for block children, since, when it comes to
+ // inline layout, we first need to lay out all the line boxes, so that
+ // we know what do to in order to honor orphans and widows, if at all
+ // possible.)
+ UpdateEarlyBreakAtBlockChild(To<NGBlockNode>(child), layout_result,
+ appeal_before);
+ }
+ return kContinueWithoutBreaking;
+ }
}
+ // Figure out where to insert a soft break. It will either be before this
+ // child, or before an earlier sibling, if there's a more appealing breakpoint
+ // there.
+
if (child.IsInline()) {
- DCHECK_EQ(break_type, SoftBreak);
if (!first_overflowing_line_) {
// We're at the first overflowing line. This is the space shortage that
// we are going to report. We do this in spite of not yet knowing
@@ -1981,7 +2210,7 @@ bool NGBlockLayoutAlgorithm::BreakBeforeChild(
// require an additional piece of machinery. This case should be rare
// enough (to worry about performance), so let's focus on code
// simplicity instead.
- container_builder_.PropagateSpaceShortage(space_shortage);
+ PropagateSpaceShortage(layout_result, block_offset);
}
// Attempt to honor orphans and widows requests.
if (int line_count = container_builder_.LineCount()) {
@@ -1999,16 +2228,12 @@ bool NGBlockLayoutAlgorithm::BreakBeforeChild(
std::max(minimum_line_count, static_cast<int>(Style().Widows()));
}
if (line_count < minimum_line_count) {
- if (is_first_fragment) {
- // Not enough orphans. Our only hope is if we can break before the
- // start of this block to improve on the situation. That's not
- // something we can determine at this point though. Permit the break,
- // but mark it as undesirable.
- container_builder_.SetHasLastResortBreak();
- }
- // We're already failing with orphans, so don't even try to deal with
- // widows.
- fit_all_lines_ = true;
+ // Not enough orphans. Our only hope is if we can break before the start
+ // of this block to improve on the situation. That's not something we
+ // can determine at this point though. Permit the break, but mark it as
+ // undesirable.
+ if (appeal_before > kBreakAppealViolatingOrphansAndWidows)
+ appeal_before = kBreakAppealViolatingOrphansAndWidows;
} else {
// There are enough lines before the break. Try to make sure that
// there'll be enough lines after the break as well. Attempt to honor
@@ -2023,129 +2248,181 @@ bool NGBlockLayoutAlgorithm::BreakBeforeChild(
// (if at all possible), which means that lines that could fit in the
// current fragment (that we have already laid out) may have to be
// saved for the next fragment.
- return false;
- } else {
- // We have determined that there are plenty of lines for the next
- // fragment, so we can just break exactly where we ran out of space,
- // rather than pushing some of the line boxes over to the next
- // fragment.
- fit_all_lines_ = true;
+ return kContinueWithoutBreaking;
}
+
+ // We have determined that there are plenty of lines for the next
+ // fragment, so we can just break exactly where we ran out of space,
+ // rather than pushing some of the line boxes over to the next fragment.
}
+ fit_all_lines_ = true;
}
}
- if (!has_processed_first_child_ &&
- (container_builder_.IsPushedByFloats() || !is_pushed_by_floats)) {
- // We're breaking before the first piece of in-flow content inside this
- // block, even if it's not a valid class C break point [1] in this case. We
- // really don't want to break here, if we can find something better. A class
- // C break point occurs if a first child has been pushed by floats, but this
- // only applies to the outermost block that gets pushed (in case this parent
- // and the child have adjoining top margins).
- //
- // [1] https://www.w3.org/TR/css-break-3/#possible-breaks
- container_builder_.SetHasLastResortBreak();
- }
-
- // The remaining part of the fragmentainer (the unusable space for child
- // content, due to the break) should still be occupied by this container.
- // TODO(mstensho): Figure out if we really need to <0 here. It doesn't seem
- // right to have negative available space.
- previous_inflow_position->logical_block_offset =
- space_available.ClampNegativeToZero();
- // Drop the fragment on the floor and retry at the start of the next
- // fragmentainer.
- container_builder_.AddBreakBeforeChild(child, break_type == ForcedBreak);
- container_builder_.SetDidBreak();
- if (break_type == ForcedBreak) {
- container_builder_.SetHasForcedBreak();
- } else {
- // Report space shortage, unless we're at a line box (in that case we've
- // already dealt with it further up).
- if (!child.IsInline()) {
- // TODO(mstensho): Turn this into a DCHECK, when the engine is ready for
- // it. Space shortage should really be positive here, or we might
- // ultimately fail to stretch the columns (column balancing).
- if (space_shortage > LayoutUnit())
- container_builder_.PropagateSpaceShortage(space_shortage);
- }
+ // So, we've run out of space, and the child won't fit here. But if there's a
+ // breakpoint with higher appeal among earlier siblings, abort and re-layout
+ // to that breakpoint now.
+ if (container_builder_.HasEarlyBreak() &&
+ container_builder_.BreakAppeal() > appeal_before) {
+ // Found a better place to break. Before aborting, calculate and report
+ // space shortage from where we'd actually break.
+ PropagateSpaceShortage(layout_result, block_offset);
+ return kNeedsEarlierBreak;
}
- return true;
+
+ // Break before the child. Note that there may be a better break further up
+ // with higher appeal (but it's too early to tell), in which case this
+ // breakpoint will be replaced.
+ BreakBeforeChild(child, layout_result, block_offset, appeal_before,
+ /* is_forced_break */ false, previous_inflow_position);
+ return kBrokeBefore;
}
-NGBlockLayoutAlgorithm::BreakType NGBlockLayoutAlgorithm::BreakTypeBeforeChild(
+void NGBlockLayoutAlgorithm::BreakBeforeChild(
NGLayoutInputNode child,
const NGLayoutResult& layout_result,
LayoutUnit block_offset,
- bool is_pushed_by_floats) const {
- if (!container_builder_.BfcBlockOffset().has_value())
- return NoBreak;
+ NGBreakAppeal appeal,
+ bool is_forced_break,
+ NGPreviousInflowPosition* previous_inflow_position) {
+#if DCHECK_IS_ON()
+ // In order to successfully break before a node, this has to be its first
+ // fragment.
+ const auto& physical_fragment = layout_result.PhysicalFragment();
+ DCHECK(!physical_fragment.IsBox() ||
+ To<NGPhysicalBoxFragment>(physical_fragment).IsFirstForNode());
+#endif
- const NGPhysicalContainerFragment& physical_fragment =
- layout_result.PhysicalFragment();
+ // Report space shortage. Note that we're not doing this for line boxes here
+ // (only blocks), because line boxes need handle it in their own way (due to
+ // how we implement widows).
+ if (child.IsBlock())
+ PropagateSpaceShortage(layout_result, block_offset);
- // If we haven't used any space at all in the fragmentainer yet, we cannot
- // break, or there'd be no progress. We'd end up creating an infinite number
- // of fragmentainers without putting any content into them.
- auto space_left = FragmentainerSpaceAvailable() - block_offset;
- if (space_left >= ConstraintSpace().FragmentainerBlockSize())
- return NoBreak;
+ BreakBeforeChild(child, appeal, is_forced_break, previous_inflow_position);
+}
- if (child.IsInline()) {
- NGFragment fragment(ConstraintSpace().GetWritingMode(), physical_fragment);
- return fragment.BlockSize() > space_left ? SoftBreak : NoBreak;
- }
-
- EBreakBetween break_before = JoinFragmentainerBreakValues(
- child.Style().BreakBefore(), layout_result.InitialBreakBefore());
- EBreakBetween break_between =
- container_builder_.JoinedBreakBetweenValue(break_before);
- if (IsForcedBreakValue(ConstraintSpace(), break_between)) {
- // There should be a forced break before this child, and if we're not at the
- // first in-flow child, just go ahead and break.
- if (has_processed_first_child_)
- return ForcedBreak;
- }
-
- // If the block offset is past the fragmentainer boundary (or exactly at the
- // boundary), no part of the fragment is going to fit in the current
- // fragmentainer. Fragments may be pushed past the fragmentainer boundary by
- // margins.
- if (space_left <= LayoutUnit())
- return SoftBreak;
-
- const NGBreakToken* token = physical_fragment.BreakToken();
- if (!token || token->IsFinished())
- return NoBreak;
- auto* block_break_token = DynamicTo<NGBlockBreakToken>(token);
- if (block_break_token && block_break_token->HasLastResortBreak()) {
- // We've already found a place to break inside the child, but it wasn't an
- // optimal one, because it would violate some rules for breaking. Consider
- // breaking before this child instead, but only do so if it's at a valid
- // break point. It's a valid break point if we're between siblings, or if
- // it's a first child at a class C break point [1] (if it got pushed down by
- // floats). The break we've already found has been marked as a last-resort
- // break, but moving that last-resort break to an earlier (but equally bad)
- // last-resort break would just waste fragmentainer space and slow down
- // content progression.
- //
- // [1] https://www.w3.org/TR/css-break-3/#possible-breaks
- if (has_processed_first_child_ || is_pushed_by_floats) {
- // This is a valid break point, and we can resolve the last-resort
- // situation.
- return SoftBreak;
+void NGBlockLayoutAlgorithm::BreakBeforeChild(
+ NGLayoutInputNode child,
+ NGBreakAppeal appeal,
+ bool is_forced_break,
+ NGPreviousInflowPosition* previous_inflow_position) {
+ did_break_before_child_ = true;
+
+ if (ConstraintSpace().HasKnownFragmentainerBlockSize()) {
+ // The remaining part of the fragmentainer (the unusable space for child
+ // content, due to the break) should still be occupied by this container.
+ previous_inflow_position->logical_block_offset =
+ FragmentainerSpaceAvailable();
+ }
+
+ DCHECK(is_forced_break || ConstraintSpace().HasKnownFragmentainerBlockSize());
+
+ // This will drop the fragment (if any) on the floor and retry at the start of
+ // the next fragmentainer.
+ container_builder_.AddBreakBeforeChild(child, appeal, is_forced_break);
+}
+
+void NGBlockLayoutAlgorithm::PropagateSpaceShortage(
+ const NGLayoutResult& layout_result,
+ LayoutUnit block_offset) {
+ // There's no shortage to report in the initial column balancing pass, since
+ // we haven't even calculated a tentative column block-size yet.
+ if (ConstraintSpace().IsInitialColumnBalancingPass())
+ return;
+
+ // Only multicol cares about space shortage.
+ if (ConstraintSpace().BlockFragmentationType() != kFragmentColumn)
+ return;
+
+ LayoutUnit space_shortage;
+ if (layout_result.MinimalSpaceShortage() == LayoutUnit::Max()) {
+ // Calculate space shortage: Figure out how much more space would have been
+ // sufficient to make the child fit right here in the current fragment.
+ NGFragment fragment(ConstraintSpace().GetWritingMode(),
+ layout_result.PhysicalFragment());
+ LayoutUnit space_left = FragmentainerSpaceAvailable() - block_offset;
+ space_shortage = fragment.BlockSize() - space_left;
+ } else {
+ // However, if space shortage was reported inside the child, use that. If we
+ // broke inside the child, we didn't complete layout, so calculating space
+ // shortage for the child as a whole would be impossible and pointless.
+ space_shortage = layout_result.MinimalSpaceShortage();
+ }
+
+ // TODO(mstensho): Turn this into a DCHECK, when the engine is ready for
+ // it. Space shortage should really be positive here, or we might ultimately
+ // fail to stretch the columns (column balancing).
+ if (space_shortage > LayoutUnit())
+ container_builder_.PropagateSpaceShortage(space_shortage);
+}
+
+void NGBlockLayoutAlgorithm::UpdateEarlyBreakAtBlockChild(
+ NGBlockNode child,
+ const NGLayoutResult& layout_result,
+ NGBreakAppeal appeal_before) {
+ // We shouldn't be here if we already know where to break.
+ DCHECK(!early_break_);
+
+ // If the child already broke, it's a little too late to look for breakpoints.
+ DCHECK(!layout_result.PhysicalFragment().BreakToken());
+
+ // See if there's a good breakpoint inside the child.
+ NGBreakAppeal appeal_inside = kBreakAppealLastResort;
+ if (scoped_refptr<const NGEarlyBreak> breakpoint =
+ layout_result.GetEarlyBreak()) {
+ appeal_inside =
+ CalculateBreakAppealInside(ConstraintSpace(), child, layout_result);
+ if (container_builder_.BreakAppeal() <= appeal_inside) {
+ // Found a good breakpoint inside the child. Add the child to the early
+ // break container chain, and store it.
+ auto parent_break = base::AdoptRef(new NGEarlyBreak(child, breakpoint));
+ container_builder_.SetEarlyBreak(parent_break, appeal_inside);
}
}
- // TODO(mstensho): There are other break-inside values to consider here.
- if (child.Style().BreakInside() != EBreakInside::kAvoid)
- return NoBreak;
- // The child broke, and we're not at the start of a fragmentainer, and we're
- // supposed to avoid breaking inside the child.
- DCHECK(!physical_fragment.IsBox() ||
- To<NGPhysicalBoxFragment>(physical_fragment).IsFirstForNode());
- return SoftBreak;
+ // Breaking before isn't better if it's less appealing than what we already
+ // have (obviously), and also not if it has the same appeal as the break
+ // location inside the child that we just found (when the appeal is the same,
+ // whatever takes us further wins).
+ if (appeal_before < container_builder_.BreakAppeal() ||
+ appeal_before == appeal_inside)
+ return;
+
+ container_builder_.SetEarlyBreak(base::AdoptRef(new NGEarlyBreak(child)),
+ appeal_before);
+}
+
+void NGBlockLayoutAlgorithm::UpdateEarlyBreakBetweenLines() {
+ // We shouldn't be here if we already know where to break.
+ DCHECK(!early_break_);
+
+ // If the child already broke, it's a little too late to look for breakpoints.
+ DCHECK(!container_builder_.DidBreak());
+
+ int line_count = container_builder_.LineCount();
+ if (line_count < 2)
+ return;
+ // We can break between two of the lines if we have to. Calculate the best
+ // line number to break before, and the appeal of such a breakpoint.
+ int line_number =
+ std::max(line_count - Style().Widows(),
+ std::min(line_count - 1, static_cast<int>(Style().Orphans())));
+ NGBreakAppeal appeal = kBreakAppealPerfect;
+ if (line_number < Style().Orphans() ||
+ line_count - line_number < Style().Widows()) {
+ // Not enough lines in this container to satisfy the orphans and/or widows
+ // requirement. If we break before the last line (i.e. the last possible
+ // class B breakpoint), we'll fit as much as possible, and that's the best
+ // we can do.
+ line_number = line_count - 1;
+ appeal = kBreakAppealViolatingOrphansAndWidows;
+ }
+ if (container_builder_.BreakAppeal() <= appeal) {
+ scoped_refptr<const NGEarlyBreak> breakpoint =
+ base::AdoptRef(new NGEarlyBreak(line_number));
+ container_builder_.SetEarlyBreak(breakpoint, appeal);
+ }
}
NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
@@ -2355,6 +2632,7 @@ NGConstraintSpace NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
new_bfc_block_offset = child_data.bfc_offset_estimate.block_offset;
SetupFragmentation(ConstraintSpace(), new_bfc_block_offset, &builder,
is_new_fc);
+ builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
}
return builder.ToConstraintSpace();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 8f98f604158..31223a24099 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -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 NGBlockLayoutAlgorithm_h
-#define NGBlockLayoutAlgorithm_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_LAYOUT_ALGORITHM_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -15,13 +15,14 @@
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_floats_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
namespace blink {
class NGConstraintSpace;
+class NGEarlyBreak;
class NGFragment;
-class NGLayoutResult;
class NGPhysicalLineBoxFragment;
// This struct is used for communicating to a child the position of the previous
@@ -66,6 +67,13 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
NOINLINE scoped_refptr<const NGLayoutResult> LayoutWithItemsBuilder(
NGInlineChildLayoutContext* context);
+ // Lay out again, this time with a predefined good breakpoint that we
+ // discovered in the first pass. This happens when we run out of space in a
+ // fragmentainer at an less-than-ideal location, due to breaking restrictions,
+ // such as orphans, widows, break-before:avoid or break-after:avoid.
+ NOINLINE scoped_refptr<const NGLayoutResult> RelayoutAndBreakEarlier(
+ const NGEarlyBreak&);
+
inline scoped_refptr<const NGLayoutResult> Layout(
NGInlineChildLayoutContext* inline_child_layout_context);
@@ -167,30 +175,32 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
//
// Returns false if we need to abort layout, because a previously unknown BFC
// block offset has now been resolved.
- bool HandleNewFormattingContext(NGLayoutInputNode child,
- const NGBreakToken* child_break_token,
- NGPreviousInflowPosition*);
+ NGLayoutResult::EStatus HandleNewFormattingContext(
+ NGLayoutInputNode child,
+ const NGBreakToken* child_break_token,
+ NGPreviousInflowPosition*);
// Performs the actual layout of a new formatting context. This may be called
// multiple times from HandleNewFormattingContext.
- std::pair<scoped_refptr<const NGLayoutResult>, NGLayoutOpportunity>
- LayoutNewFormattingContext(NGLayoutInputNode child,
- const NGBreakToken* child_break_token,
- const NGInflowChildData&,
- NGBfcOffset origin_offset,
- bool abort_if_cleared);
+ scoped_refptr<const NGLayoutResult> LayoutNewFormattingContext(
+ NGLayoutInputNode child,
+ const NGBreakToken* child_break_token,
+ const NGInflowChildData&,
+ NGBfcOffset origin_offset,
+ bool abort_if_cleared,
+ NGBfcOffset* out_child_bfc_offset);
// Handle an in-flow child.
// Returns false if we need to abort layout, because a previously unknown BFC
// block offset has now been resolved. (Same as HandleNewFormattingContext).
- bool HandleInflow(
+ NGLayoutResult::EStatus HandleInflow(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
NGPreviousInflowPosition*,
NGInlineChildLayoutContext*,
scoped_refptr<const NGInlineBreakToken>* previous_inline_break_token);
- bool FinishInflow(
+ NGLayoutResult::EStatus FinishInflow(
NGLayoutInputNode child,
const NGBreakToken* child_break_token,
const NGConstraintSpace&,
@@ -211,28 +221,96 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// whether fits within the fragmentainer or not.
bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const;
- // Insert a fragmentainer break before the child if necessary.
- // Update previous in-flow position and return true if a break was inserted.
- // Otherwise return false.
- bool BreakBeforeChild(NGLayoutInputNode child,
+ // Return the block-offset from the start of the fragmentainer, to this node.
+ LayoutUnit OffsetFromFragmentainerStart() const;
+
+ // Return the block-size of the portion that intersects with the
+ // fragmentainer. The block-offset is relative to this node.
+ LayoutUnit PortionIntersectingWithFragmentainer(LayoutUnit block_offset,
+ LayoutUnit block_size) const;
+
+ // Propagate the block-size of unbreakable content. This is used to inflate
+ // the initial minimal column block-size when balancing columns. Unbreakable
+ // content will actually fragment if the columns aren't large enough, and we
+ // want to prevent that, if possible.
+ void PropagateUnbreakableBlockSize(LayoutUnit block_offset,
+ LayoutUnit block_size);
+
+ // Final adjustments before fragment creation. We need to prevent the fragment
+ // from crossing fragmentainer boundaries, and rather create a break token if
+ // we're out of space. As part of finalizing we may also discover that we need
+ // to abort layout, because we've run out of space at a less-than-ideal
+ // location. In this case, false will be returned. Otherwise, true will be
+ // returned.
+ bool FinalizeForFragmentation();
+
+ // Outcome of considering (and possibly attempting) breaking before a child.
+ enum BreakStatus {
+ // Continue layout. No break was inserted before the child (but there may be
+ // a break inside).
+ kContinueWithoutBreaking,
+
+ // A break was inserted before the child. Discard the child fragment and
+ // finish layout of the container. If there was a break inside the child, it
+ // will be discarded along with the child fragment.
+ kBrokeBefore,
+
+ // The child couldn't fit here, but no break was inserted before the child,
+ // as it was an unappealing place to break, and we have a better earlier
+ // breakpoint. We now need to abort the current layout, and go back and
+ // re-layout to said earlier breakpoint.
+ kNeedsEarlierBreak
+ };
+
+ // 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 it as the most appealing break point so far if that's the case),
+ // since we might have to go back and break here. Return
+ // |kContinueWithoutBreaking| if we're to continue laying out. If
+ // |kNeedsEarlierBreak| is returned, it means that we ran out of space, but
+ // shouldn't break before the child, but rather abort layout, and re-layout to
+ // a previously found good breakpoint.
+ // If |has_container_separation| is true, it means that we're at a valid
+ // breakpoint. We obviously prefer valid breakpoints, but sometimes we need to
+ // break at undesirable locations. Class A breakpoints occur between block
+ // siblings. Class B breakpoints between line boxes. Both these breakpoint
+ // classes imply that we're already past the first in-flow child in the
+ // container, but there's also another way of achieving container separation:
+ // class C breakpoints. Those occur if there's a positive gap between the
+ // block-start content edge of the container and the block-start margin edge
+ // of the first in-flow child. This can happen when in-flow content is pushed
+ // down by floats. https://www.w3.org/TR/css-break-3/#possible-breaks
+ BreakStatus BreakBeforeChildIfNeeded(NGLayoutInputNode child,
+ const NGLayoutResult&,
+ NGPreviousInflowPosition*,
+ LayoutUnit block_offset,
+ bool has_container_separation);
+
+ // Insert either a soft or forced break before the child.
+ void BreakBeforeChild(NGLayoutInputNode child,
const NGLayoutResult&,
- NGPreviousInflowPosition*,
LayoutUnit block_offset,
- bool is_pushed_by_floats);
-
- enum BreakType { NoBreak, SoftBreak, ForcedBreak };
-
- // Given a child fragment and the corresponding node's style, determine the
- // type of break we should insert in front of it, if any.
- BreakType BreakTypeBeforeChild(NGLayoutInputNode child,
- const NGLayoutResult&,
- LayoutUnit block_offset,
- bool is_pushed_by_floats) const;
-
- // Final adjustments before fragment creation. We need to prevent the
- // fragment from crossing fragmentainer boundaries, and rather create a break
- // token if we're out of space.
- void FinalizeForFragmentation();
+ NGBreakAppeal,
+ bool is_forced_break,
+ NGPreviousInflowPosition*);
+ void BreakBeforeChild(NGLayoutInputNode child,
+ NGBreakAppeal,
+ bool is_forced_break,
+ NGPreviousInflowPosition*);
+
+ // Propagate the minimal space shortage from a child.
+ void PropagateSpaceShortage(const NGLayoutResult&, LayoutUnit block_offset);
+
+ // Look for a better breakpoint (than we already have) either before the child
+ // (class A breakpoint), or inside it (class A or B breakpoint), and store it.
+ void UpdateEarlyBreakAtBlockChild(NGBlockNode child,
+ const NGLayoutResult& layout_result,
+ NGBreakAppeal break_before);
+
+ // Look for a better breakpoint (than we already have) between lines (i.e. a
+ // class B breakpoint), and store it.
+ void UpdateEarlyBreakBetweenLines();
void PropagateBaselinesFromChildren();
bool AddBaseline(const NGBaselineRequest&,
@@ -333,6 +411,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
LogicalSize child_percentage_size_;
LogicalSize replaced_child_percentage_size_;
+ // Intrinsic block size based on child layout and containment.
LayoutUnit intrinsic_block_size_;
// The line box index at which we ran out of space. This where we'll actually
@@ -362,9 +441,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// A or B breakpoint (between block-level siblings or line box siblings).
bool has_processed_first_child_ = false;
+ bool did_break_before_child_ = false;
+
NGExclusionSpace exclusion_space_;
+
+ // When set, this will specify where to break before or inside.
+ const NGEarlyBreak* early_break_ = nullptr;
};
} // namespace blink
-#endif // NGBlockLayoutAlgorithm_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_LAYOUT_ALGORITHM_H_
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 e568d011f5e..1cc8a99f1ed 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
@@ -56,8 +56,8 @@ class NGBlockLayoutAlgorithmTest : public NGBaseLayoutAlgorithmTest {
NGLayoutCacheStatus cache_status;
base::Optional<NGFragmentGeometry> initial_fragment_geometry;
return To<LayoutBlockFlow>(node.GetLayoutBox())
- ->CachedLayoutResult(space, nullptr, &initial_fragment_geometry,
- &cache_status);
+ ->CachedLayoutResult(space, nullptr, nullptr,
+ &initial_fragment_geometry, &cache_status);
}
String DumpFragmentTree(const NGPhysicalBoxFragment* fragment) {
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 ea608532891..32e6ad5c630 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
@@ -203,11 +203,51 @@ LayoutUnit CalculateAvailableBlockSizeForLegacy(
return space.PercentageResolutionBlockSize();
}
+void SetupBoxLayoutExtraInput(const NGConstraintSpace& space,
+ const LayoutBox& box,
+ BoxLayoutExtraInput* input) {
+ input->containing_block_content_inline_size =
+ CalculateAvailableInlineSizeForLegacy(box, space);
+ input->containing_block_content_block_size =
+ CalculateAvailableBlockSizeForLegacy(box, space);
+
+ WritingMode writing_mode = box.StyleRef().GetWritingMode();
+ if (LayoutObject* containing_block = box.ContainingBlock()) {
+ if (!IsParallelWritingMode(containing_block->StyleRef().GetWritingMode(),
+ writing_mode)) {
+ // The sizes should be in the containing block writing mode.
+ std::swap(input->containing_block_content_block_size,
+ input->containing_block_content_inline_size);
+
+ // We cannot lay out without a definite containing block inline-size. We
+ // end up here if we're performing a measure pass (as part of resolving
+ // the intrinsic min/max inline-size of some ancestor, for instance).
+ // Legacy layout has a tendency of clamping negative sizes to 0 anyway,
+ // but this is missing when it comes to resolving percentage-based
+ // padding, for instance.
+ if (input->containing_block_content_inline_size == kIndefiniteSize)
+ input->containing_block_content_inline_size = LayoutUnit();
+ }
+ }
+
+ // We need a definite containing block inline-size, or we'd be unable to
+ // resolve percentages.
+ DCHECK_GE(input->containing_block_content_inline_size, LayoutUnit());
+
+ input->available_inline_size = space.AvailableSize().inline_size;
+
+ if (space.IsFixedInlineSize())
+ input->override_inline_size = space.AvailableSize().inline_size;
+ if (space.IsFixedBlockSize())
+ input->override_block_size = space.AvailableSize().block_size;
+}
+
} // namespace
scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
const NGConstraintSpace& constraint_space,
- const NGBreakToken* break_token) {
+ const NGBreakToken* break_token,
+ const NGEarlyBreak* early_break) {
// Use the old layout code and synthesize a fragment.
if (!CanUseNewLayout())
return RunLegacyLayout(constraint_space);
@@ -228,8 +268,9 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
NGLayoutCacheStatus cache_status;
base::Optional<NGFragmentGeometry> fragment_geometry;
- scoped_refptr<const NGLayoutResult> layout_result = box_->CachedLayoutResult(
- constraint_space, break_token, &fragment_geometry, &cache_status);
+ scoped_refptr<const NGLayoutResult> layout_result =
+ box_->CachedLayoutResult(constraint_space, break_token, early_break,
+ &fragment_geometry, &cache_status);
if (layout_result) {
DCHECK_EQ(cache_status, NGLayoutCacheStatus::kHit);
@@ -264,7 +305,8 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::Layout(
PrepareForLayout();
NGLayoutAlgorithmParams params(*this, *fragment_geometry, constraint_space,
- To<NGBlockBreakToken>(break_token));
+ To<NGBlockBreakToken>(break_token),
+ early_break);
// Try to perform "simplified" layout.
// TODO(crbug.com/992953): Add a simplified layout pass for custom layout.
@@ -438,11 +480,20 @@ void NGBlockNode::FinishLayout(
const NGConstraintSpace& constraint_space,
const NGBreakToken* break_token,
scoped_refptr<const NGLayoutResult> layout_result) {
- if (!IsBlockLayoutComplete(constraint_space, *layout_result))
+ if (constraint_space.IsIntermediateLayout())
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.
+ if (layout_result->Status() != NGLayoutResult::kSuccess) {
+ box_->ClearCachedLayoutResult();
+ return;
+ }
+
if (!constraint_space.HasBlockFragmentation())
box_->SetCachedLayoutResult(*layout_result, break_token);
+
if (block_flow) {
auto* child = GetLayoutObjectForFirstChildNode(block_flow);
bool has_inline_children =
@@ -763,27 +814,33 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
auto* block_flow = DynamicTo<LayoutBlockFlow>(box_);
LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(block_flow);
- if (UNLIKELY(flow_thread)) {
- PlaceChildrenInFlowThread(physical_fragment);
- } else {
- PhysicalOffset offset_from_start;
- if (UNLIKELY(constraint_space.HasBlockFragmentation())) {
- // Need to include any block space that this container has used in
- // previous fragmentainers. The offset of children will be relative to
- // the container, in flow thread coordinates, i.e. the model where
- // everything is represented as one single strip, rather than being
- // sliced and translated into columns.
-
- // TODO(mstensho): writing modes
- if (previous_break_token)
- offset_from_start.top = previous_break_token->ConsumedBlockSize();
+
+ // Position the children inside the box. We skip this if display-lock prevents
+ // child layout.
+ if (!LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren)) {
+ if (UNLIKELY(flow_thread)) {
+ PlaceChildrenInFlowThread(physical_fragment);
+ } else {
+ PhysicalOffset offset_from_start;
+ if (UNLIKELY(constraint_space.HasBlockFragmentation())) {
+ // Need to include any block space that this container has used in
+ // previous fragmentainers. The offset of children will be relative to
+ // the container, in flow thread coordinates, i.e. the model where
+ // everything is represented as one single strip, rather than being
+ // sliced and translated into columns.
+
+ // TODO(mstensho): writing modes
+ if (previous_break_token)
+ offset_from_start.top = previous_break_token->ConsumedBlockSize();
+ }
+ PlaceChildrenInLayoutBox(physical_fragment, offset_from_start);
}
- PlaceChildrenInLayoutBox(physical_fragment, offset_from_start);
}
LayoutBlock* block = DynamicTo<LayoutBlock>(box_);
if (LIKELY(block && is_last_fragment)) {
- LayoutUnit intrinsic_block_size = layout_result.IntrinsicBlockSize();
+ LayoutUnit intrinsic_block_size =
+ layout_result.UnconstrainedIntrinsicBlockSize();
if (UNLIKELY(previous_break_token))
intrinsic_block_size += previous_break_token->ConsumedBlockSize();
@@ -796,9 +853,12 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
physical_fragment);
}
+ BoxLayoutExtraInput input(*block);
+ SetupBoxLayoutExtraInput(constraint_space, *block, &input);
+
// |ComputeOverflow()| below calls |AddVisualOverflowFromChildren()|, which
// computes visual overflow from |RootInlineBox| if |ChildrenInline()|
- block->SetNeedsOverflowRecalc();
+ block->SetNeedsVisualOverflowAndPaintInvalidation();
block->ComputeLayoutOverflow(intrinsic_block_size - borders.block_end -
scrollbars.block_end);
}
@@ -861,8 +921,7 @@ void NGBlockNode::PlaceChildrenInFlowThread(
for (const auto& child : physical_fragment.Children()) {
if (child->GetLayoutObject() != box_) {
DCHECK(child->GetLayoutObject()->IsColumnSpanAll());
- // TODO(mstensho): Write back the spanner offset to the associated
- // LayoutMultiColumnSpannerPlaceholder (if we bother)
+ CopyChildFragmentPosition(*child, child.offset);
continue;
}
// Each anonymous child of a multicol container constitutes one column.
@@ -1089,42 +1148,9 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
if (box_->NeedsLayout() || !layout_result || needs_force_relayout) {
BoxLayoutExtraInput input(*box_);
- input.containing_block_content_inline_size =
- CalculateAvailableInlineSizeForLegacy(*box_, constraint_space);
- input.containing_block_content_block_size =
- CalculateAvailableBlockSizeForLegacy(*box_, constraint_space);
-
WritingMode writing_mode = Style().GetWritingMode();
- if (LayoutObject* containing_block = box_->ContainingBlock()) {
- if (!IsParallelWritingMode(containing_block->StyleRef().GetWritingMode(),
- writing_mode)) {
- // The sizes should be in the containing block writing mode.
- std::swap(input.containing_block_content_block_size,
- input.containing_block_content_inline_size);
-
- // We cannot lay out without a definite containing block inline-size. We
- // end up here if we're performing a measure pass (as part of resolving
- // the intrinsic min/max inline-size of some ancestor, for instance).
- // Legacy layout has a tendency of clamping negative sizes to 0 anyway,
- // but this is missing when it comes to resolving percentage-based
- // padding, for instance.
- if (input.containing_block_content_inline_size == kIndefiniteSize) {
- DCHECK(constraint_space.IsIntermediateLayout());
- input.containing_block_content_inline_size = LayoutUnit();
- }
- }
- }
-
- // We need a definite containing block inline-size, or we'd be unable to
- // resolve percentages.
- DCHECK_GE(input.containing_block_content_inline_size, LayoutUnit());
-
- input.available_inline_size = constraint_space.AvailableSize().inline_size;
- if (constraint_space.IsFixedInlineSize())
- input.override_inline_size = constraint_space.AvailableSize().inline_size;
- if (constraint_space.IsFixedBlockSize())
- input.override_block_size = constraint_space.AvailableSize().block_size;
+ SetupBoxLayoutExtraInput(constraint_space, *box_, &input);
box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock());
// Using |LayoutObject::LayoutIfNeeded| save us a little bit of overhead,
@@ -1154,10 +1180,25 @@ scoped_refptr<const NGLayoutResult> NGBlockNode::RunLegacyLayout(
builder.SetInitialFragmentGeometry(fragment_geometry);
builder.SetIsLegacyLayoutRoot();
+ // If we're block-fragmented, we can only handle monolithic content, since
+ // the two block fragmentation machineries (NG and legacy) cannot cooperate.
+ DCHECK(!constraint_space.HasBlockFragmentation() || IsMonolithic());
+
+ if (constraint_space.IsInitialColumnBalancingPass()) {
+ // In the initial column balancing pass we need to provide the tallest
+ // unbreakable block-size. However, since the content is monolithic,
+ // that's already handled by the parent algorithm (so we don't need to
+ // propagate anything here). We still have to tell the builder that we're
+ // in this layout pass, though, so that the layout result is set up
+ // correctly.
+ builder.SetIsInitialColumnBalancingPass();
+ }
+
CopyBaselinesFromLegacyLayout(constraint_space, &builder);
layout_result = builder.ToBoxFragment();
- box_->SetCachedLayoutResult(*layout_result, /* break_token */ nullptr);
+ if (!constraint_space.IsIntermediateLayout())
+ box_->SetCachedLayoutResult(*layout_result, /* break_token */ nullptr);
// If |SetCachedLayoutResult| did not update cached |LayoutResult|,
// |NeedsLayout()| flag should not be cleared.
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 1764db7b9bf..306838b04d0 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
@@ -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 NGBlockNode_h
-#define NGBlockNode_h
+#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/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -16,9 +16,10 @@ namespace blink {
class LayoutBox;
class NGBaselineRequest;
class NGBlockBreakToken;
+class NGBoxFragmentBuilder;
class NGBreakToken;
class NGConstraintSpace;
-class NGBoxFragmentBuilder;
+class NGEarlyBreak;
class NGLayoutResult;
class NGPhysicalBoxFragment;
class NGPhysicalContainerFragment;
@@ -38,7 +39,8 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
scoped_refptr<const NGLayoutResult> Layout(
const NGConstraintSpace& constraint_space,
- const NGBreakToken* break_token = nullptr);
+ const NGBreakToken* break_token = nullptr,
+ const NGEarlyBreak* = nullptr);
// This method is just for use within the |NGSimplifiedLayoutAlgorithm|.
//
@@ -198,4 +200,4 @@ struct DowncastTraits<NGBlockNode> {
} // namespace blink
-#endif // NGBlockNode
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BLOCK_NODE_H_
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 d282938bb87..dbfd474e7c8 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
@@ -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 NGBoxFragment_h
-#define NGBoxFragment_h
+#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/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
@@ -63,4 +63,4 @@ class CORE_EXPORT NGBoxFragment final : public NGFragment {
} // namespace blink
-#endif // NGBoxFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_H_
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 b82787b67d9..6ca6a600f08 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
@@ -80,8 +80,18 @@ void GatherInlineContainerFragmentsFromLinebox(
} // namespace
void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child,
+ NGBreakAppeal appeal,
bool is_forced_break) {
+ break_appeal_ = appeal;
+ if (is_forced_break) {
+ SetHasForcedBreak();
+ // A forced break is considered to always have perfect appeal; they should
+ // never be weighed against other potential breakpoints.
+ DCHECK_EQ(appeal, kBreakAppealPerfect);
+ }
+
DCHECK(has_block_fragmentation_);
+ SetDidBreak();
if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) {
if (inline_break_tokens_.IsEmpty()) {
// In some cases we may want to break before the first line, as a last
@@ -99,32 +109,6 @@ void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child,
child_break_tokens_.push_back(token);
}
-void NGBoxFragmentBuilder::AddBreakBeforeLine(int line_number) {
- DCHECK(has_block_fragmentation_);
- DCHECK_GT(line_number, 0);
- DCHECK_LE(unsigned(line_number), inline_break_tokens_.size());
- int lines_to_remove = inline_break_tokens_.size() - line_number;
- if (lines_to_remove > 0) {
- // Remove widows that should be pushed to the next fragment. We'll also
- // remove all other child fragments than line boxes (typically floats) that
- // come after the first line that's moved, as those also have to be re-laid
- // out in the next fragment.
- inline_break_tokens_.resize(line_number);
- DCHECK_GT(children_.size(), 0UL);
- for (int i = children_.size() - 1; i >= 0; i--) {
- DCHECK_NE(i, 0);
- if (!children_[i].fragment->IsLineBox())
- continue;
- if (!--lines_to_remove) {
- // This is the first line that is going to the next fragment. Remove it,
- // and everything after it.
- children_.resize(i);
- break;
- }
- }
- }
-}
-
void NGBoxFragmentBuilder::AddResult(const NGLayoutResult& child_layout_result,
const LogicalOffset offset,
const LayoutInline* inline_container) {
@@ -205,14 +189,30 @@ void NGBoxFragmentBuilder::PropagateBreak(
const auto* token = child_layout_result.PhysicalFragment().BreakToken();
did_break_ = token && !token->IsFinished();
}
- if (child_layout_result.HasForcedBreak())
+ if (child_layout_result.HasForcedBreak()) {
SetHasForcedBreak();
- else
+ } else if (IsInitialColumnBalancingPass()) {
+ PropagateTallestUnbreakableBlockSize(
+ child_layout_result.TallestUnbreakableBlockSize());
+ } else {
PropagateSpaceShortage(child_layout_result.MinimalSpaceShortage());
+ }
}
scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::ToBoxFragment(
WritingMode block_or_line_writing_mode) {
+#if DCHECK_IS_ON()
+ if (ItemsBuilder()) {
+ for (const ChildWithOffset& child : Children()) {
+ DCHECK(child.fragment);
+ const NGPhysicalFragment& fragment = *child.fragment;
+ DCHECK(fragment.IsLineBox() ||
+ // TODO(kojii): How to place floats and OOF is TBD.
+ fragment.IsFloatingOrOutOfFlowPositioned());
+ }
+ }
+#endif
+
if (UNLIKELY(node_ && has_block_fragmentation_)) {
if (!inline_break_tokens_.IsEmpty()) {
if (auto token = inline_break_tokens_.back()) {
@@ -222,11 +222,14 @@ scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::ToBoxFragment(
}
if (did_break_) {
break_token_ = NGBlockBreakToken::Create(
- node_, consumed_block_size_, child_break_tokens_,
- has_last_resort_break_, has_seen_all_children_);
+ node_, consumed_block_size_, child_break_tokens_, break_appeal_,
+ has_seen_all_children_);
}
}
+ if (!has_floating_descendants_ && items_builder_)
+ has_floating_descendants_ = items_builder_->HasFloatingDescendants();
+
scoped_refptr<const NGPhysicalBoxFragment> fragment =
NGPhysicalBoxFragment::Create(this, block_or_line_writing_mode);
fragment->CheckType();
@@ -235,7 +238,7 @@ scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::ToBoxFragment(
}
scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::Abort(
- NGLayoutResult::NGLayoutResultStatus status) {
+ NGLayoutResult::EStatus status) {
return base::AdoptRef(new NGLayoutResult(status, this));
}
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 8f8dd379ce8..bc035d14d67 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
@@ -63,6 +63,15 @@ class CORE_EXPORT NGBoxFragmentBuilder final
is_initial_block_size_indefinite_ = size_.block_size == kIndefiniteSize;
}
+ const NGFragmentGeometry& InitialFragmentGeometry() const {
+ DCHECK(initial_fragment_geometry_);
+ return *initial_fragment_geometry_;
+ }
+
+ void SetUnconstrainedIntrinsicBlockSize(
+ LayoutUnit unconstrained_intrinsic_block_size) {
+ unconstrained_intrinsic_block_size_ = unconstrained_intrinsic_block_size;
+ }
void SetIntrinsicBlockSize(LayoutUnit intrinsic_block_size) {
intrinsic_block_size_ = intrinsic_block_size;
}
@@ -87,10 +96,9 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Add a break token for a child that doesn't yet have any fragments, because
// its first fragment is to be produced in the next fragmentainer. This will
// add a break token for the child, but no fragment.
- void AddBreakBeforeChild(NGLayoutInputNode child, bool is_forced_break);
-
- // Prepare for a break token before the specified line.
- void AddBreakBeforeLine(int line_number);
+ void AddBreakBeforeChild(NGLayoutInputNode child,
+ NGBreakAppeal,
+ bool is_forced_break);
// Add a layout result. This involves appending the fragment and its relative
// offset to the builder, but also keeping track of out-of-flow positioned
@@ -115,19 +123,45 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// This will result in a fragment which has an unfinished break token.
void SetDidBreak() { did_break_ = true; }
- void SetHasForcedBreak() {
- has_forced_break_ = true;
- minimal_space_shortage_ = LayoutUnit();
- }
-
// Report space shortage, i.e. how much more space would have been sufficient
// to prevent some piece of content from breaking. This information may be
// used by the column balancer to stretch columns.
void PropagateSpaceShortage(LayoutUnit space_shortage) {
DCHECK_GT(space_shortage, LayoutUnit());
+
+ // Space shortage should only be reported when we already have a tentative
+ // fragmentainer block-size. It's meaningless to talk about space shortage
+ // in the initial column balancing pass, because then we have no
+ // fragmentainer block-size at all, so who's to tell what's too short or
+ // not?
+ DCHECK(!IsInitialColumnBalancingPass());
+
if (minimal_space_shortage_ > space_shortage)
minimal_space_shortage_ = space_shortage;
}
+ LayoutUnit MinimalSpaceShortage() const { return minimal_space_shortage_; }
+
+ void PropagateTallestUnbreakableBlockSize(LayoutUnit unbreakable_block_size) {
+ // We should only calculate the block-size of the tallest piece of
+ // unbreakable content during the initial column balancing pass, when we
+ // haven't set a tentative fragmentainer block-size yet.
+ DCHECK(IsInitialColumnBalancingPass());
+
+ tallest_unbreakable_block_size_ =
+ std::max(tallest_unbreakable_block_size_, unbreakable_block_size);
+ }
+
+ void SetIsInitialColumnBalancingPass() {
+ // Note that we have no dedicated flag for being in the initial column
+ // balancing pass here. We'll just bump tallest_unbreakable_block_size_ to
+ // 0, so that NGLayoutResult knows that we need to store unbreakable
+ // block-size.
+ DCHECK_EQ(tallest_unbreakable_block_size_, LayoutUnit::Min());
+ tallest_unbreakable_block_size_ = LayoutUnit();
+ }
+ bool IsInitialColumnBalancingPass() const {
+ return tallest_unbreakable_block_size_ >= LayoutUnit();
+ }
void SetInitialBreakBefore(EBreakBetween break_before) {
initial_break_before_ = break_before;
@@ -152,10 +186,6 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Return the number of line boxes laid out.
int LineCount() const { return inline_break_tokens_.size(); }
- // Call when we're setting an undersirable break. It may be possible to avoid
- // the break if we instead break at an earlier element.
- void SetHasLastResortBreak() { has_last_resort_break_ = true; }
-
// Set when we have iterated over all the children. This means that all
// children have been fully laid out, or have break tokens. No more children
// left to discover.
@@ -164,6 +194,20 @@ class CORE_EXPORT NGBoxFragmentBuilder final
void SetColumnSpanner(NGBlockNode spanner) { column_spanner_ = spanner; }
bool FoundColumnSpanner() const { return !!column_spanner_; }
+ void SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint,
+ NGBreakAppeal appeal) {
+ early_break_ = breakpoint;
+ break_appeal_ = appeal;
+ }
+ bool HasEarlyBreak() const { return early_break_.get(); }
+
+ // Set the highest break appeal found so far. This is either:
+ // 1: The highest appeal of a breakpoint found by our container
+ // 2: The appeal of a possible early break inside
+ // 3: The appeal of an actual break inside (to be stored in a break token)
+ void SetBreakAppeal(NGBreakAppeal appeal) { break_appeal_ = appeal; }
+ NGBreakAppeal BreakAppeal() const { return break_appeal_; }
+
// Offsets are not supposed to be set during fragment construction, so we
// do not provide a setter here.
@@ -180,8 +224,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
}
- scoped_refptr<const NGLayoutResult> Abort(
- NGLayoutResult::NGLayoutResultStatus);
+ scoped_refptr<const NGLayoutResult> Abort(NGLayoutResult::EStatus);
NGPhysicalFragment::NGBoxType BoxType() const;
void SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
@@ -246,9 +289,15 @@ class CORE_EXPORT NGBoxFragmentBuilder final
// Update whether we have fragmented in this flow.
void PropagateBreak(const NGLayoutResult&);
+ void SetHasForcedBreak() {
+ has_forced_break_ = true;
+ minimal_space_shortage_ = LayoutUnit();
+ }
+
scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode);
const NGFragmentGeometry* initial_fragment_geometry_ = nullptr;
+ LayoutUnit unconstrained_intrinsic_block_size_ = kIndefiniteSize;
LayoutUnit intrinsic_block_size_;
NGFragmentItemsBuilder* items_builder_ = nullptr;
@@ -266,6 +315,7 @@ class CORE_EXPORT NGBoxFragmentBuilder final
LayoutUnit consumed_block_size_;
LayoutUnit minimal_space_shortage_ = LayoutUnit::Max();
+ LayoutUnit tallest_unbreakable_block_size_ = LayoutUnit::Min();
// The break-before value on the initial child we cannot honor. There's no
// valid class A break point before a first child, only *between* siblings.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_break_appeal.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_break_appeal.h
new file mode 100644
index 00000000000..f1eb70765aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_break_appeal.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_APPEAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_APPEAL_H_
+
+namespace blink {
+
+// The "appeal" of a breakpoint. Higher is better. The perfect appeal is when
+// we're not violating any rules. As we violate rule after rule, appeal will
+// decrease. When figuring out where to break, a layout algorithm will use the
+// breakpoint with the highest appeal (first priority) that has progressed the
+// furthest through the content (second priority). The list here is sorted by
+// rule violation severity, i.e. reverse appeal.
+enum NGBreakAppeal {
+ // We're attempting to break at a really undesirable place. This is not a
+ // valid class A, B or C breakpoint [1]. The only requirement we're satisfying
+ // is to not slice monolithic content.
+ //
+ // [1] https://www.w3.org/TR/css-break-3/#possible-breaks
+ kBreakAppealLastResort,
+
+ // The worst thing we're violating is an avoid* value of break-before,
+ // break-after, or break-inside.
+ kBreakAppealViolatingBreakAvoid,
+
+ // The only thing we're violating is orphans and/or widows requirements.
+ kBreakAppealViolatingOrphansAndWidows,
+
+ // We're not violating anything. This is a perfect break location. Note that
+ // forced breaks are always perfect, since they trump everything else.
+ kBreakAppealPerfect,
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_APPEAL_H_
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 9f5e2135ae0..29c7bb6009b 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
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NGBreakToken_h
-#define NGBreakToken_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_TOKEN_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_TOKEN_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_break_appeal.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -58,6 +59,10 @@ class CORE_EXPORT NGBreakToken : public RefCounted<NGBreakToken> {
box_, static_cast<NGLayoutInputNode::NGLayoutInputNodeType>(type_));
}
+ NGBreakAppeal BreakAppeal() const {
+ return static_cast<NGBreakAppeal>(break_appeal_);
+ }
+
#if DCHECK_IS_ON()
virtual String ToString() const;
void ShowBreakTokenTree() const;
@@ -73,7 +78,7 @@ class CORE_EXPORT NGBreakToken : public RefCounted<NGBreakToken> {
flags_(0),
is_break_before_(false),
is_forced_break_(false),
- has_last_resort_break_(false),
+ break_appeal_(kBreakAppealPerfect),
has_seen_all_children_(false) {
DCHECK_EQ(type, static_cast<NGBreakTokenType>(node.Type()));
}
@@ -99,10 +104,10 @@ class CORE_EXPORT NGBreakToken : public RefCounted<NGBreakToken> {
unsigned is_forced_break_ : 1;
- // We're attempting to break at an undesirable place. Sometimes that's
- // unavoidable, but we should only break here if we cannot find a better break
- // point further up in the ancestry.
- unsigned has_last_resort_break_ : 1;
+ // If the break is unforced, this is the appeal of the break. Higher is
+ // better. Violating breaking rules decreases appeal. Forced breaks always
+ // have perfect appeal.
+ unsigned break_appeal_ : 2; // NGBreakAppeal
// All children of this container have been "seen" at this point. This means
// that all children have been fully laid out, or have break tokens. No more
@@ -114,4 +119,4 @@ typedef Vector<scoped_refptr<const NGBreakToken>> NGBreakTokenVector;
} // namespace blink
-#endif // NGBreakToken_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BREAK_TOKEN_H_
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 e7a7e8f29ed..466e4d6301b 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
@@ -7,6 +7,7 @@
#include <algorithm>
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_fragment_geometry.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
@@ -105,8 +106,24 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
used_column_count_ =
ResolveUsedColumnCount(content_box_size_.inline_size, Style());
- if (ConstraintSpace().HasBlockFragmentation())
+ // If we know the block-size of the fragmentainers in an outer fragmentation
+ // context (if any), our columns may be constrained by that, meaning that we
+ // may have to fragment earlier than what we would have otherwise, and, if
+ // that's the case, that we may also not create overflowing columns (in the
+ // inline axis), but rather finish the row and resume in the next row in the
+ // next outer fragmentainer. Note that it is possible to be nested inside a
+ // fragmentation context that doesn't know the block-size of its
+ // fragmentainers. This would be in the first layout pass of an outer multicol
+ // container, before any tentative column block-size has been calculated.
+ is_constrained_by_outer_fragmentation_context_ =
+ ConstraintSpace().HasKnownFragmentainerBlockSize();
+
+ if (ConstraintSpace().HasBlockFragmentation()) {
container_builder_.SetHasBlockFragmentation();
+ if (ConstraintSpace().IsInitialColumnBalancingPass())
+ container_builder_.SetIsInitialColumnBalancingPass();
+ }
+
container_builder_.SetIsBlockFragmentationContextRoot();
// Omit leading border+padding+scrollbar for all fragments but the first.
@@ -134,12 +151,13 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
block_size = border_box_size.block_size - previously_consumed_block_size;
}
- if (ConstraintSpace().HasBlockFragmentation()) {
+ if (is_constrained_by_outer_fragmentation_context_) {
// In addition to establishing one, we're nested inside another
// fragmentation context.
- FinishFragmentation(&container_builder_, block_size, intrinsic_block_size_,
+ FinishFragmentation(ConstraintSpace(), block_size, intrinsic_block_size_,
previously_consumed_block_size,
- ConstraintSpace().FragmentainerSpaceAtBfcStart());
+ FragmentainerSpaceAtBfcStart(ConstraintSpace()),
+ &container_builder_);
} else {
container_builder_.SetBlockSize(block_size);
container_builder_.SetIntrinsicBlockSize(intrinsic_block_size_);
@@ -195,6 +213,8 @@ base::Optional<MinMaxSize> NGColumnLayoutAlgorithm::ComputeMinMaxSize(
}
void NGColumnLayoutAlgorithm::LayoutChildren() {
+ NGMarginStrut margin_strut;
+
// First extract incoming child break tokens.
scoped_refptr<const NGBlockBreakToken> spanner_break_token;
scoped_refptr<const NGBlockBreakToken> next_column_token;
@@ -240,7 +260,7 @@ void NGColumnLayoutAlgorithm::LayoutChildren() {
// resume now.
spanner_break_token =
LayoutSpanner(To<NGBlockNode>(spanner_break_token->InputNode()),
- spanner_break_token.get());
+ spanner_break_token.get(), &margin_strut);
if (spanner_break_token) {
// We broke at the spanner again!
@@ -260,7 +280,7 @@ void NGColumnLayoutAlgorithm::LayoutChildren() {
// child is a spanner.
do {
scoped_refptr<const NGLayoutResult> result =
- LayoutRow(next_column_token.get());
+ LayoutRow(next_column_token.get(), &margin_strut);
next_column_token =
To<NGBlockBreakToken>(result->PhysicalFragment().BreakToken());
@@ -272,7 +292,7 @@ void NGColumnLayoutAlgorithm::LayoutChildren() {
break;
// We found a spanner. Lay it out, and then resume column layout.
- spanner_break_token = LayoutSpanner(spanner_node, nullptr);
+ spanner_break_token = LayoutSpanner(spanner_node, nullptr, &margin_strut);
if (spanner_break_token) {
// We broke before or inside the spanner. This may happen if we're nested
@@ -295,18 +315,20 @@ void NGColumnLayoutAlgorithm::LayoutChildren() {
// context. In that case we must make sure to skip the contents when
// resuming.
container_builder_.SetHasSeenAllChildren();
+
+ intrinsic_block_size_ += margin_strut.Sum();
}
}
scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
- const NGBlockBreakToken* next_column_token) {
- LayoutUnit column_block_offset = intrinsic_block_size_;
+ const NGBlockBreakToken* next_column_token,
+ NGMarginStrut* margin_strut) {
LogicalSize column_size(column_inline_size_, content_box_size_.block_size);
// 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
// fragmentation context.
- if (ConstraintSpace().HasBlockFragmentation() &&
+ if (is_constrained_by_outer_fragmentation_context_ &&
column_size.block_size != kIndefiniteSize) {
if (const auto* token = BreakToken())
column_size.block_size -= token->ConsumedBlockSize();
@@ -323,17 +345,21 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
// contexts, not just by a block-size specified on this multicol container.
bool balance_columns = Style().GetColumnFill() == EColumnFill::kBalance ||
(column_size.block_size == kIndefiniteSize &&
- !ConstraintSpace().HasBlockFragmentation());
+ !is_constrained_by_outer_fragmentation_context_);
if (balance_columns) {
column_size.block_size =
CalculateBalancedColumnBlockSize(column_size, next_column_token);
}
+ // Column rows have no representation in the DOM and have no margins, but
+ // there may be a trailing margin from a preceding spanner.
+ LayoutUnit column_block_offset = intrinsic_block_size_ + margin_strut->Sum();
+
bool needs_more_fragments_in_outer = false;
- if (ConstraintSpace().HasBlockFragmentation()) {
+ if (is_constrained_by_outer_fragmentation_context_) {
LayoutUnit available_outer_space =
- ConstraintSpace().FragmentainerSpaceAtBfcStart() - column_block_offset;
+ FragmentainerSpaceAtBfcStart(ConstraintSpace()) - column_block_offset;
// TODO(mstensho): This should never be negative, or even zero. Turn into a
// DCHECK when the underlying problem is fixed.
@@ -429,6 +455,7 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
actual_column_count >= used_column_count_ &&
needs_more_fragments_in_outer) {
container_builder_.SetDidBreak();
+ container_builder_.SetBreakAppeal(kBreakAppealPerfect);
break;
}
@@ -484,20 +511,31 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
break;
} while (true);
+ bool keep_margin = false;
+
// If there was no content inside to process, we don't want the resulting
// empty column fragment.
if (new_columns.size() == 1u) {
const NGPhysicalBoxFragment& column =
*To<NGPhysicalBoxFragment>(new_columns[0].fragment.get());
- // TODO(mstensho): Keeping the empty fragment, just so that out-of-flow
- // descendants get propagated correctly isn't right. Find some other way of
- // propagating them.
- if (column.Children().size() == 0 &&
- !column.HasOutOfFlowPositionedDescendants())
- return result;
+
+ if (column.Children().size() == 0) {
+ // No content. Keep the trailing margin from any previous column spanner.
+ keep_margin = true;
+
+ // TODO(mstensho): It's wrong to keep the empty fragment, just so that
+ // out-of-flow descendants get propagated correctly. Find some other way
+ // of propagating them.
+ if (!column.HasOutOfFlowPositionedDescendants())
+ return result;
+ }
}
- intrinsic_block_size_ += column_size.block_size;
+ intrinsic_block_size_ = column_block_offset + column_size.block_size;
+
+ // We added a row. Reset the trailing margin from any previous column spanner.
+ if (!keep_margin)
+ *margin_strut = NGMarginStrut();
// Commit all column fragments to the fragment builder.
for (auto column : new_columns) {
@@ -510,24 +548,60 @@ scoped_refptr<const NGLayoutResult> NGColumnLayoutAlgorithm::LayoutRow(
scoped_refptr<const NGBlockBreakToken> NGColumnLayoutAlgorithm::LayoutSpanner(
NGBlockNode spanner_node,
- const NGBlockBreakToken* break_token) {
- // TODO(mstensho): Margins (including margin collapsing), inline alignment,
- // and outer fragmentainer breaks between spanners and rows (the spanner may
- // be unbreakable inside, and we may be in a nested fragmentation context and
- // out of space).
- LayoutUnit block_offset = intrinsic_block_size_;
+ const NGBlockBreakToken* break_token,
+ NGMarginStrut* margin_strut) {
+ const ComputedStyle& spanner_style = spanner_node.Style();
+ NGBoxStrut margins = ComputeMarginsFor(
+ spanner_style, content_box_size_.inline_size,
+ ConstraintSpace().GetWritingMode(), ConstraintSpace().Direction());
+
+ if (break_token) {
+ // Truncate block-start margins at fragmentainer breaks, and also make sure
+ // that we don't repeat them at the beginning of every fragment generated
+ // from the spanner node.
+ margins.block_start = LayoutUnit();
+
+ if (break_token->IsBreakBefore()) {
+ // TODO(mstensho): Passing a break-before token shouldn't be a problem,
+ // but it would cause problems for the NGPaintFragment code. Just pass
+ // nullptr. Won't make any difference anyway.
+ break_token = nullptr;
+ }
+ }
+
+ // Collapse the block-start margin of this spanner with the block-end margin
+ // of an immediately preceding spanner, if any.
+ margin_strut->Append(margins.block_start, /* is_quirky */ false);
+
+ // TODO(mstensho): outer fragmentainer breaks between spanners and rows (the
+ // spanner may be unbreakable inside, and we may be in a nested fragmentation
+ // context and out of space).
+ LayoutUnit block_offset = intrinsic_block_size_ + margin_strut->Sum();
auto spanner_space = CreateConstraintSpaceForSpanner(block_offset);
- // TODO(mstensho): Passing a break-before token shouldn't be a problem, but it
- // would cause problems for the NGPaintFragment code. Just pass nullptr. Won't
- // make any difference anyway.
- if (break_token && break_token->IsBreakBefore())
- break_token = nullptr;
auto result = spanner_node.Layout(spanner_space, break_token);
- LogicalOffset offset(border_scrollbar_padding_.inline_start,
- intrinsic_block_size_);
+ NGFragment fragment(ConstraintSpace().GetWritingMode(),
+ result->PhysicalFragment());
+
+ ResolveInlineMargins(spanner_style, Style(), content_box_size_.inline_size,
+ fragment.InlineSize(), &margins);
+
+ LogicalOffset offset(
+ border_scrollbar_padding_.inline_start + margins.inline_start,
+ block_offset);
container_builder_.AddResult(*result, offset);
- NGFragment fragment(Style().GetWritingMode(), result->PhysicalFragment());
+ *margin_strut = NGMarginStrut();
+ margin_strut->Append(margins.block_end, /* is_quirky */ false);
+
+ // TODO(mstensho): The correct thing would be to weigh any break inside
+ // against the appeal of breaking before the spanner, like we do in
+ // BreakBeforeChildIfNeeded() for the block layout algorithm. Just setting the
+ // appeal to perfect isn't right, but we're doing it for now, so that any
+ // break inside the spanner (in case we're nested inside another fragmentation
+ // context) isn't just discarded.
+ if (ConstraintSpace().HasBlockFragmentation())
+ container_builder_.SetBreakAppeal(kBreakAppealPerfect);
+
intrinsic_block_size_ = offset.block_offset + fragment.BlockSize();
return To<NGBlockBreakToken>(result->PhysicalFragment().BreakToken());
@@ -605,6 +679,7 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
// First split into content runs at explicit (forced) breaks.
ContentRuns content_runs;
scoped_refptr<const NGBlockBreakToken> break_token = child_break_token;
+ LayoutUnit tallest_unbreakable_block_size;
do {
NGBlockLayoutAlgorithm balancing_algorithm(
{Node(), fragment_geometry, space, break_token.get()});
@@ -615,6 +690,9 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
fragment, IsHorizontalWritingMode(space.GetWritingMode()));
content_runs.emplace_back(column_block_size);
+ tallest_unbreakable_block_size = std::max(
+ tallest_unbreakable_block_size, result->TallestUnbreakableBlockSize());
+
// Stop when we reach a spanner. That's where this row of columns will end.
if (result->ColumnSpanner())
break;
@@ -633,6 +711,14 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
content_runs[index].implicit_breaks_assumed_count++;
}
+ if (ConstraintSpace().IsInitialColumnBalancingPass()) {
+ // Nested column balancing. Our outer fragmentation context is in its
+ // initial balancing pass, so it also wants to know the largest unbreakable
+ // block-size.
+ container_builder_.PropagateTallestUnbreakableBlockSize(
+ tallest_unbreakable_block_size);
+ }
+
// We now have an estimated minimal block-size for the columns. Roughly
// speaking, this is the block-size that the columns will need if we are
// allowed to break freely at any offset. This is normally not the case,
@@ -641,7 +727,9 @@ LayoutUnit NGColumnLayoutAlgorithm::CalculateBalancedColumnBlockSize(
// lay out into columns to figure out if they are tall enough or not (and
// stretch and retry if not). Also honor {,min-,max-}{height,width} properties
// before returning.
- LayoutUnit block_size = content_runs.TallestColumnBlockSize();
+ LayoutUnit block_size = std::max(content_runs.TallestColumnBlockSize(),
+ tallest_unbreakable_block_size);
+
return ConstrainColumnBlockSize(block_size);
}
@@ -716,7 +804,6 @@ NGConstraintSpace NGColumnLayoutAlgorithm::CreateConstraintSpaceForColumns(
space_builder.SetFragmentationType(kFragmentColumn);
space_builder.SetFragmentainerBlockSize(column_block_size);
- space_builder.SetFragmentainerSpaceAtBfcStart(column_block_size);
space_builder.SetIsAnonymous(true);
space_builder.SetIsInColumnBfc();
if (balance_columns)
@@ -737,11 +824,6 @@ NGConstraintSpace NGColumnLayoutAlgorithm::CreateConstraintSpaceForBalancing(
NGConstraintSpaceBuilder space_builder(
ConstraintSpace(), Style().GetWritingMode(), /* is_new_fc */ true);
space_builder.SetFragmentationType(kFragmentColumn);
- // TODO(mstensho): It would be better to use kIndefiniteSize here, rather than
- // LayoutUnit::Max(), but the fragmentation machinery currently gets confused
- // by such a value.
- space_builder.SetFragmentainerBlockSize(LayoutUnit::Max());
- space_builder.SetFragmentainerSpaceAtBfcStart(LayoutUnit::Max());
space_builder.SetAvailableSize({column_size.inline_size, kIndefiniteSize});
space_builder.SetPercentageResolutionSize(column_size);
space_builder.SetIsAnonymous(true);
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 06a3ad1c7e7..5707f8337b0 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
@@ -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 NGColumnLayoutAlgorithm_h
-#define NGColumnLayoutAlgorithm_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
@@ -14,6 +14,7 @@ class NGBlockNode;
class NGBlockBreakToken;
class NGConstraintSpace;
struct LogicalSize;
+struct NGMarginStrut;
class CORE_EXPORT NGColumnLayoutAlgorithm
: public NGLayoutAlgorithm<NGBlockNode,
@@ -34,14 +35,16 @@ class CORE_EXPORT NGColumnLayoutAlgorithm
// Lay out one row of columns. The layout result returned is for the last
// column that was laid out. The rows themselves don't create fragments.
scoped_refptr<const NGLayoutResult> LayoutRow(
- const NGBlockBreakToken* next_column_token);
+ const NGBlockBreakToken* next_column_token,
+ NGMarginStrut*);
// Lay out a column spanner. Will return a break token if we break before or
// inside the spanner. If no break token is returned, it means that we can
// proceed to the next row of columns.
scoped_refptr<const NGBlockBreakToken> LayoutSpanner(
NGBlockNode spanner_node,
- const NGBlockBreakToken* break_token);
+ const NGBlockBreakToken* break_token,
+ NGMarginStrut*);
LayoutUnit CalculateBalancedColumnBlockSize(
const LogicalSize& column_size,
@@ -72,8 +75,9 @@ class CORE_EXPORT NGColumnLayoutAlgorithm
LayoutUnit column_inline_size_;
LayoutUnit column_inline_progression_;
LayoutUnit intrinsic_block_size_;
+ bool is_constrained_by_outer_fragmentation_context_ = false;
};
} // namespace blink
-#endif // NGColumnLayoutAlgorithm_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_COLUMN_LAYOUT_ALGORITHM_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index c770506d228..e5de35ad584 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -798,6 +798,70 @@ TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideAvoid) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideAvoidColumn) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:10px; height:50px;"></div>
+ <div style="break-inside:avoid-column; width:20px; height:70px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:10x50
+ offset:110,0 size:100x70
+ offset:0,0 size:20x70
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideAvoidPage) {
+ // break-inside:avoid-page has no effect, unless we're breaking into pages.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:10px; height:50px;"></div>
+ <div style="break-inside:avoid-page; width:20px; height:70px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:10x50
+ offset:0,50 size:20x50
+ offset:110,0 size:100x20
+ offset:0,0 size:20x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideAvoidTallBlock) {
// The block that has break-inside:avoid is too tall to fit in one
// fragmentainer. So a break is unavoidable. Let's check that:
@@ -1812,6 +1876,196 @@ TEST_F(NGColumnLayoutAlgorithmTest, UnsatisfiableOrphansAndWidows) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, WidowsAndAbspos) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 70px;
+ line-height: 20px;
+ orphans: 1;
+ widows: 3;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="position:relative;">
+ <br>
+ <br>
+ <br>
+ <br>
+ <div style="position:absolute; width:33px; height:33px;"></div>
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x70
+ offset:0,0 size:320x70
+ offset:0,0 size:100x70
+ offset:0,0 size:100x70
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x60
+ offset:0,0 size:100x60
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:33x33
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, BreakBetweenLinesNotBefore) {
+ // Just breaking where we run out of space is perfect, since it won't violate
+ // the orphans/widows requirement, since there'll be two lines both before and
+ // after the break.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 2;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:44px; height:60px;"></div>
+ <div style="width:55px;">
+ <br>
+ <br>
+ <br>
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:44x60
+ offset:0,60 size:55x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x40
+ offset:0,0 size:55x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, BreakBetweenLinesNotBefore2) {
+ // Prefer breaking between lines and violate an orphans requirement, rather
+ // than violating break-before:avoid.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 1;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:44px; height:80px;"></div>
+ <div style="break-before:avoid; width:55px;">
+ <br>
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:44x80
+ offset:0,80 size:55x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x20
+ offset:0,0 size:55x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, BreakBetweenLinesNotBefore3) {
+ // Prefer breaking between lines and violate a widows requirement, rather than
+ // violating break-before:avoid.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-fill: auto;
+ column-gap: 10px;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 1;
+ widows: 2;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:44px; height:80px;"></div>
+ <div style="break-before:avoid; width:55px;">
+ <br>
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:44x80
+ offset:0,80 size:55x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x20
+ offset:0,0 size:55x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
// TODO(crbug.com/915929): Fix inline-level float fragmentation.
TEST_F(NGColumnLayoutAlgorithmTest, DISABLED_FloatInBlockMovedByOrphans) {
SetBodyInnerHTML(R"HTML(
@@ -2544,6 +2798,100 @@ TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingEmptyBlock) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingSingleLine) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ line-height: 20px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <br>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x20
+ offset:0,0 size:320x20
+ offset:0,0 size:100x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingSingleLineInNested) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ line-height: 20px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="columns:2; column-gap:10px;">
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x20
+ offset:0,0 size:320x20
+ offset:0,0 size:100x20
+ offset:0,0 size:100x20
+ offset:0,0 size:45x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingSingleLineInNestedSpanner) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ line-height: 20px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="columns:2;">
+ <div style="column-span:all;">
+ <br>
+ </div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x20
+ offset:0,0 size:320x20
+ offset:0,0 size:100x20
+ offset:0,0 size:100x20
+ offset:0,0 size:100x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingOverflow) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -2788,6 +3136,77 @@ TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesForcedBreak2) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesForcedBreak3) {
+ // We have 7+5 lines and 3 columns. There's a forced break after 7 lines, then
+ // 5 more lines. There will be another implicit break among the first 7 lines,
+ // while the columns will have to fit 5 lines, because of the 5 lines after
+ // the forced break. The first column will have 5 lines. The second one will
+ // have 2. The third one (after the break) will have 5. The lines are wrapped
+ // inside a block child of the multicol container.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ line-height: 20px;
+ orphans: 1;
+ widows: 1;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:66px;">
+ <br><br><br><br><br><br><br>
+ <div style="width:99px; break-before:column;"></div>
+ <br><br><br><br><br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:66x100
+ offset:0,0 size:66x100
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:0x20
+ offset:0,9 size:0x1
+ offset:0,60 size:0x20
+ offset:0,9 size:0x1
+ offset:0,80 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x100
+ offset:0,0 size:66x100
+ offset:0,0 size:66x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:220,0 size:100x100
+ offset:0,0 size:66x100
+ offset:0,0 size:99x0
+ offset:0,0 size:66x100
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:0x20
+ offset:0,9 size:0x1
+ offset:0,60 size:0x20
+ offset:0,9 size:0x1
+ offset:0,80 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesAvoidBreakInside) {
// We have 6 lines and 3 columns. If we make the columns tall enough to hold 2
// lines each, it should all fit. But then there's a block with 3 lines and
@@ -2840,6 +3259,82 @@ TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesAvoidBreakInside) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesAvoidBreakInside2) {
+ // We have 5 lines and 3 columns. If we make the columns tall enough to hold 2
+ // lines each, it should all fit. But then there's a block with 3 lines and
+ // break-inside:avoid...
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ line-height: 20px;
+ orphans: 1;
+ widows: 1;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <br>
+ <div style="break-inside:avoid;">
+ <br><br><br>
+ </div>
+ <br>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x60
+ offset:0,0 size:320x60
+ offset:0,0 size:100x60
+ offset:0,0 size:100x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x60
+ offset:0,0 size:100x60
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:0x20
+ offset:0,9 size:0x1
+ offset:220,0 size:100x20
+ offset:0,0 size:100x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingUnderflow) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="break-inside:avoid; margin-top:-100px; width:55px; height:110px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x10
+ offset:0,0 size:320x10
+ offset:0,0 size:100x10
+ offset:0,-100 size:55x110
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, ClassCBreakPointBeforeBfc) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -3113,6 +3608,43 @@ TEST_F(NGColumnLayoutAlgorithmTest, ClassCBreakPointBeforeLine) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, ForcedBreakAtClassCBreakPoint) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height:100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:50px; height:50px;"></div>
+ <div style="float:left; width:100%; height:40px;"></div>
+ <div style="width:55px;">
+ <div style="display:flow-root; break-before:column; width:44px; height:20px;"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:50x50
+ offset:0,50 size:100x40
+ offset:0,50 size:55x50
+ offset:110,0 size:100x20
+ offset:0,0 size:55x20
+ offset:0,0 size:44x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, Nested) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -3842,6 +4374,112 @@ TEST_F(NGColumnLayoutAlgorithmTest, SpannerInBlockWithSiblings) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, SpannerMargins) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="column-span:all; margin:10px; width:33px; height:10px;"></div>
+ <div class="content"></div>
+ <div style="column-span:all; margin:10px auto; width:44px; height:10px;"></div>
+ <div style="column-span:all; margin:20px; width:55px;"></div>
+ <div style="column-span:all; margin:10px; width:66px; height:10px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x130
+ offset:0,0 size:320x130
+ offset:10,10 size:33x10
+ offset:0,30 size:100x20
+ offset:0,0 size:100x20
+ offset:138,60 size:44x10
+ offset:20,90 size:55x0
+ offset:10,110 size:66x10
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, SpannerMarginsRtl) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ direction: rtl;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="column-span:all; margin:10px; width:33px; height:10px;"></div>
+ <div class="content"></div>
+ <div style="column-span:all; margin:10px auto; width:44px; height:10px;"></div>
+ <div style="column-span:all; margin:20px; width:55px;"></div>
+ <div style="column-span:all; margin:10px; width:66px; height:10px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x130
+ offset:0,0 size:320x130
+ offset:277,10 size:33x10
+ offset:220,30 size:100x20
+ offset:0,0 size:100x20
+ offset:138,60 size:44x10
+ offset:245,90 size:55x0
+ offset:244,110 size:66x10
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, BreakInsideSpannerWithMargins) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ width: 320px;
+ column-fill: auto;
+ height: 100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="columns:2;">
+ <div style="column-span:all; margin-top:10px; margin-bottom:20px; width:33px; height:100px;"></div>
+ <div style="column-span:all; width:44px; height:10px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,10 size:33x90
+ offset:110,0 size:100x40
+ offset:0,0 size:100x40
+ offset:0,0 size:33x10
+ offset:0,30 size:44x10
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
TEST_F(NGColumnLayoutAlgorithmTest, InvalidSpanners) {
// Spanners cannot exist inside new formatting context roots. They will just
// be treated as normal column content then.
@@ -4085,5 +4723,751 @@ TEST_F(NGColumnLayoutAlgorithmTest, SpannerAsMulticol) {
EXPECT_EQ(expectation, dump);
}
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetween) {
+ // Breaking exactly where we run out of space would violate a
+ // break-before:avoid rule. There's a perfect break opportunity before the
+ // previous sibling, so use that one instead.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:81px;"></div>
+ <div class="content" style="width:82px;"></div>
+ <div class="content" style="width:83px;"></div>
+ <div class="content" style="width:84px; break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:81x30
+ offset:0,30 size:82x30
+ offset:110,0 size:100x60
+ offset:0,0 size:83x30
+ offset:0,30 size:84x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidAndForceBreakBetween) {
+ // If we're both told to avoid and force breaking at a breakpoint, forcing
+ // always wins.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:81px;"></div>
+ <div class="content" style="width:82px;"></div>
+ <div class="content" style="width:83px; break-after:column;"></div>
+ <div class="content" style="width:84px; break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:81x30
+ offset:0,30 size:82x30
+ offset:0,60 size:83x30
+ offset:110,0 size:100x30
+ offset:0,0 size:84x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenInFloat) {
+ // There are two parallel flows here; one for the float, and one for its
+ // sibling. They don't affect each other as far as breaking is concerned.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="float:left; width:100%;">
+ <div class="content" style="width:81px;"></div>
+ <div class="content" style="width:82px;"></div>
+ <div class="content" style="width:83px;"></div>
+ <div class="content" style="width:84px; break-before:avoid;"></div>
+ </div>
+ <div style="height:150px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,0 size:81x30
+ offset:0,30 size:82x30
+ offset:0,0 size:100x100
+ offset:110,0 size:100x60
+ offset:0,0 size:100x60
+ offset:0,0 size:83x30
+ offset:0,30 size:84x30
+ offset:0,0 size:100x50
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest,
+ IgnoreBreakInsideAvoidBecauseBreakBetweenAvoid) {
+ // We want to avoid breaks between all the children, and at the same time
+ // avoid breaks inside of them. This is impossible to honor in this test,
+ // since the content is taller than one column. There are no ideal
+ // breakpoints; all are equally bad. The spec is explicit about the fact that
+ // it "does not suggest a precise algorithm" when it comes to picking which
+ // breaking rule to violate before others, so whether we should drop
+ // break-before or break-inside first is undefined. However, the spec does
+ // also mention that we should break as few times as possible, which suggests
+ // that we should favor whatever gives more progression.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:81px;"></div>
+ <div class="content" style="width:82px; break-before:avoid;"></div>
+ <div class="content" style="width:83px; break-before:avoid;"></div>
+ <div class="content" style="width:84px; break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:81x30
+ offset:0,30 size:82x30
+ offset:0,60 size:83x30
+ offset:0,90 size:84x10
+ offset:110,0 size:100x20
+ offset:0,0 size:84x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenAndInsideIgnoreInside) {
+ // This one isn't obvious, spec-wise, since it's not defined which rules to
+ // disregard first (break-inside vs. break-before, and break-inside on a child
+ // vs. on its container), but it seems right to disregard break-inside:avoid
+ // on the container, and at the same time honor break avoidance specified
+ // further within (smaller pieces, more progression), rather than e.g. giving
+ // up on everything and breaking wherever.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="break-inside:avoid;">
+ <div style="width:80px; height:20px;"></div>
+ <div class="content" style="width:81px;"></div>
+ <div class="content" style="width:82px;"></div>
+ <div class="content" style="width:83px; break-before:avoid;"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,0 size:80x20
+ offset:0,20 size:81x30
+ offset:110,0 size:100x60
+ offset:0,0 size:100x60
+ offset:0,0 size:82x30
+ offset:0,30 size:83x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenAndInside) {
+ // When looking for possible breaks inside #middle, we need to take into
+ // account that we're supposed to avoid breaking inside. The only breakpoint
+ // that doesn't violate any rules in this test is *before* #middle.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:32px;"></div>
+ <div id="middle" style="break-inside:avoid; break-after:avoid;">
+ <div class="content" style="width:33px;"></div>
+ <div class="content" style="width:34px;"></div>
+ <div class="content" style="width:35px;"></div>
+ <div class="content" style="width:36px;"></div>
+ </div>
+ <div class="content" style="width:37px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:32x20
+ offset:110,0 size:100x100
+ offset:0,0 size:100x80
+ offset:0,0 size:33x20
+ offset:0,20 size:34x20
+ offset:0,40 size:35x20
+ offset:0,60 size:36x20
+ offset:0,80 size:37x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenInsideBreakableParent) {
+ // There's a perfect breakpoint between the two direct children of the
+ // multicol container - i.e. between #first and #second. We should avoid
+ // breaking between between any of the children of #second (we run out of
+ // space between the third and the fourth child). There are no restrictions on
+ // breaking between the children inside #first, but we should progress as much
+ // as possible, so the correct thing to do is to break between #first and
+ // #second.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div id="#first">
+ <div class="content" style="width:33px;"></div>
+ <div class="content" style="width:34px;"></div>
+ </div>
+ <div id="#second">
+ <div class="content" style="width:35px;"></div>
+ <div class="content" style="width:36px; break-before:avoid;"></div>
+ <div class="content" style="width:37px; break-before:avoid;"></div>
+ <div class="content" style="width:38px; break-before:avoid;"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x40
+ offset:0,0 size:33x20
+ offset:0,20 size:34x20
+ offset:110,0 size:100x80
+ offset:0,0 size:100x80
+ offset:0,0 size:35x20
+ offset:0,20 size:36x20
+ offset:0,40 size:37x20
+ offset:0,60 size:38x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenAfterBreakableSibling) {
+ // We should avoid breaking between the two direct children of the multicol
+ // container - i.e. between #first and #second. We should also avoid breaking
+ // between between the children of #second (we run out of space before its
+ // second child). The only restriction inside #first is between the third and
+ // fourth child, while there are perfect breakpoints between the first and the
+ // second, and between the second and the third. We should progress as much as
+ // possible, so the correct thing to do is to break between the second and
+ // third child of #first.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="break-after:avoid;">
+ <div class="content" style="width:33px;"></div>
+ <div class="content" style="width:34px;"></div>
+ <div class="content" style="width:35px;"></div>
+ <div class="content" style="width:36px; break-before:avoid;"></div>
+ </div>
+ <div>
+ <div class="content" style="width:37px;"></div>
+ <div class="content" style="width:38px; break-before:avoid;"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,0 size:33x20
+ offset:0,20 size:34x20
+ offset:110,0 size:100x80
+ offset:0,0 size:100x40
+ offset:0,0 size:35x20
+ offset:0,20 size:36x20
+ offset:0,40 size:100x40
+ offset:0,0 size:37x20
+ offset:0,20 size:38x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest,
+ AvoidBreakBetweenBreakInsidePreviousSibling) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:32px;"></div>
+ <div style="break-after:avoid;">
+ <div class="content" style="width:33px;"></div>
+ <div class="content" style="width:34px;"></div>
+ <div class="content" style="width:35px;"></div>
+ <div class="content" style="width:36px;"></div>
+ </div>
+ <div class="content" style="width:37px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:32x20
+ offset:0,20 size:100x80
+ offset:0,0 size:33x20
+ offset:0,20 size:34x20
+ offset:0,40 size:35x20
+ offset:110,0 size:100x40
+ offset:0,0 size:100x20
+ offset:0,0 size:36x20
+ offset:0,20 size:37x20
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenHonorOrphansWidows) {
+ // We run out of space at .content, but this isn't a good location, because of
+ // break-before:avoid. Break between the lines. Honor orphans and widows, so
+ // that two of the four lines will be pushed to the second column.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 2;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <br>
+ <br>
+ <br>
+ <br>
+ <div class="content" style="break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x70
+ offset:0,0 size:100x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:100x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenHonorOrphansWidows2) {
+ // We run out of space at .content, but this isn't a good location, because of
+ // break-before:avoid. Break between the first block and the two lines, in
+ // order to honor orphans and widows.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 2;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="height:40px;"></div>
+ <br>
+ <br>
+ <div class="content" style="break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x40
+ offset:110,0 size:100x70
+ offset:0,0 size:100x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:100x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenHonorOrphansWidows3) {
+ // We run out of space between the first and the second line in the second
+ // container, but this isn't a good location, because of the orphans and
+ // widows requirement. Break between the second and third line inside the
+ // first container instead. We should not break between the two containers,
+ // because of break-before:avoid.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 2;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div>
+ <br>
+ <br>
+ <br>
+ <br>
+ </div>
+ <div style="break-before:avoid;">
+ <br>
+ <br>
+ <br>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x100
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x100
+ offset:0,0 size:100x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:100x60
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:0x20
+ offset:0,9 size:0x1
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenIgnoreOrphansWidows) {
+ // We run out of space at .content, but this isn't a good location, because of
+ // break-before:avoid. Break between the two lines, even if that will violate
+ // the orphans and widows requirement. According to the spec, this is better
+ // then ignoring the the break-after:avoid declaration on the first child.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 2;
+ widows: 2;
+ }
+ .content { break-inside:avoid; height:30px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="height:40px; break-after:avoid;"></div>
+ <br>
+ <br>
+ <div class="content" style="break-before:avoid;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:100x40
+ offset:0,40 size:100x60
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:110,0 size:100x50
+ offset:0,0 size:100x20
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:100x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenLinesInsideBreakAvoid) {
+ // We run out of space at the second line inside the last container, and we're
+ // not supposed to break inside it. We're also not supposed to break between
+ // the lines in the previous container (since it has break-inside:avoid,
+ // albeit no orphans/widows restrictions). Breaking before that container
+ // instead is as far as we get without breaking any rules.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ line-height: 20px;
+ orphans: 1;
+ widows: 1;
+ }
+ .content { break-inside:avoid; height:20px; }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div class="content" style="width:33px;"></div>
+ <div class="content" style="width:34px;"></div>
+ <div style="break-inside:avoid; width:35px;">
+ <br>
+ <br>
+ </div>
+ <div class="content" style="break-before:avoid; width:36px; height:30px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:33x20
+ offset:0,20 size:34x20
+ offset:110,0 size:100x70
+ offset:0,0 size:35x40
+ offset:0,0 size:0x20
+ offset:0,9 size:0x1
+ offset:0,20 size:0x20
+ offset:0,9 size:0x1
+ offset:0,40 size:36x30
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBetweenBreakAtEarlyClassC) {
+ // The early break is a class C breakpoint, and this is also exactly where the
+ // BFC block-offset is resolved. There are no possible breaks as long as we
+ // don't know our BFC offset, but breaking just before the box that resolves
+ // the BFC block-offset should be allowed.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:22px;">
+ <div style="float:left; width:100%; width:33px; height:20px;"></div>
+ <div style="display:flow-root; width:44px; height:20px;"></div>
+ </div>
+ <div style="break-before:avoid; break-inside:avoid; width:55px; height:70px;"></div>
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:22x100
+ offset:0,0 size:33x20
+ offset:110,0 size:100x90
+ offset:0,0 size:22x20
+ offset:0,0 size:44x20
+ offset:0,20 size:55x70
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
+TEST_F(NGColumnLayoutAlgorithmTest, AvoidBreakBeforeBlockReplacedContent) {
+ // Replaced content is unbreakable. Don't break right before it if we have
+ // break-before:avoid, though.
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #parent {
+ columns: 3;
+ column-gap: 10px;
+ column-fill: auto;
+ width: 320px;
+ height: 100px;
+ }
+ </style>
+ <div id="container">
+ <div id="parent">
+ <div style="width:22px; height:40px;"></div>
+ <div style="width:33px; height:50px; break-inside:avoid;"></div>
+ <img style="break-before:avoid; display:block; width:44px; height:50px;">
+ </div>
+ </div>
+ )HTML");
+
+ String dump = DumpFragmentTree(GetElementById("container"));
+ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+ offset:unplaced size:1000x100
+ offset:0,0 size:320x100
+ offset:0,0 size:100x100
+ offset:0,0 size:22x40
+ offset:110,0 size:100x100
+ offset:0,0 size:33x50
+ offset:0,50 size:44x50
+)DUMP";
+ EXPECT_EQ(expectation, dump);
+}
+
} // anonymous namespace
} // namespace blink
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 8f77b9045a8..eb57e54cc5d 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
@@ -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 NGConstraintSpace_h
-#define NGConstraintSpace_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_H_
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_break_appeal.h"
#include "third_party/blink/renderer/core/layout/ng/ng_floats_utils.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/text/writing_mode.h"
@@ -86,7 +87,7 @@ class CORE_EXPORT NGConstraintSpace final {
else
bfc_offset_ = other.bfc_offset_;
}
- NGConstraintSpace(NGConstraintSpace&& other) noexcept
+ NGConstraintSpace(NGConstraintSpace&& other)
: available_size_(other.available_size_),
exclusion_space_(std::move(other.exclusion_space_)),
bitfields_(other.bitfields_) {
@@ -110,7 +111,7 @@ class CORE_EXPORT NGConstraintSpace final {
bitfields_ = other.bitfields_;
return *this;
}
- NGConstraintSpace& operator=(NGConstraintSpace&& other) noexcept {
+ NGConstraintSpace& operator=(NGConstraintSpace&& other) {
available_size_ = other.available_size_;
if (HasRareData())
delete rare_data_;
@@ -254,14 +255,34 @@ class CORE_EXPORT NGConstraintSpace final {
: kIndefiniteSize;
}
- // Return the block space that was available in the current fragmentainer at
- // the start of the current block formatting context. Note that if the start
- // of the current block formatting context is in a previous fragmentainer, the
- // size of the current fragmentainer is returned instead.
- LayoutUnit FragmentainerSpaceAtBfcStart() const {
+ // Return true if we're column-balancing, and are in the initial pass where
+ // we're calculating the initial minimal column block-size.
+ bool IsInitialColumnBalancingPass() const {
+ return BlockFragmentationType() == kFragmentColumn &&
+ FragmentainerBlockSize() == kIndefiniteSize;
+ }
+
+ // Return true if we're block-fragmented and know our fragmentainer
+ // block-size.
+ bool HasKnownFragmentainerBlockSize() const {
+ if (!HasBlockFragmentation() || IsInitialColumnBalancingPass())
+ return false;
+ // The only case where we allow an unknown fragmentainer block-size is if
+ // we're in the initial column balancing pass.
+ DCHECK(FragmentainerBlockSize() != kIndefiniteSize);
+ return true;
+ }
+
+ // Return the block-offset from the block-start of the fragmentainer
+ // relative to the block-start of the current block formatting context in
+ // the current fragmentainer. Note that if the current block formatting
+ // context starts in a previous fragmentainer, we'll return the block-offset
+ // relative to the current fragmentainer.
+ LayoutUnit FragmentainerOffsetAtBfc() const {
DCHECK(HasBlockFragmentation());
- return HasRareData() ? rare_data_->fragmentainer_space_at_bfc_start
- : kIndefiniteSize;
+ if (HasRareData())
+ return rare_data_->fragmentainer_offset_at_bfc;
+ return LayoutUnit();
}
// Whether the current constraint space is for the newly established
@@ -348,6 +369,15 @@ class CORE_EXPORT NGConstraintSpace final {
return HasRareData() && rare_data_->is_in_column_bfc;
}
+ // Get the appeal of the best breakpoint found so far. When progressing
+ // through layout, we know that we don't need to consider less appealing
+ // breakpoints than this.
+ NGBreakAppeal EarlyBreakAppeal() const {
+ if (!HasRareData())
+ return kBreakAppealLastResort;
+ return static_cast<NGBreakAppeal>(rare_data_->early_break_appeal);
+ }
+
// Returns if this node is a table cell child, and which table layout mode
// is occurring.
NGTableCellChildLayoutMode TableCellChildLayoutMode() const {
@@ -561,20 +591,21 @@ class CORE_EXPORT NGConstraintSpace final {
block_direction_fragmentation_type(
static_cast<unsigned>(kFragmentNone)),
is_inside_balanced_columns(false),
- is_in_column_bfc(false) {}
+ is_in_column_bfc(false),
+ early_break_appeal(kBreakAppealLastResort) {}
RareData(const RareData& other)
: percentage_resolution_size(other.percentage_resolution_size),
replaced_percentage_resolution_block_size(
other.replaced_percentage_resolution_block_size),
bfc_offset(other.bfc_offset),
fragmentainer_block_size(other.fragmentainer_block_size),
- fragmentainer_space_at_bfc_start(
- other.fragmentainer_space_at_bfc_start),
+ fragmentainer_offset_at_bfc(other.fragmentainer_offset_at_bfc),
data_union_type(other.data_union_type),
block_direction_fragmentation_type(
other.block_direction_fragmentation_type),
is_inside_balanced_columns(other.is_inside_balanced_columns),
- is_in_column_bfc(other.is_in_column_bfc) {
+ is_in_column_bfc(other.is_in_column_bfc),
+ early_break_appeal(other.early_break_appeal) {
switch (data_union_type) {
case kNone:
break;
@@ -623,22 +654,23 @@ class CORE_EXPORT NGConstraintSpace final {
NGBfcOffset bfc_offset;
LayoutUnit fragmentainer_block_size = kIndefiniteSize;
- LayoutUnit fragmentainer_space_at_bfc_start = kIndefiniteSize;
+ LayoutUnit fragmentainer_offset_at_bfc;
unsigned data_union_type : 2;
unsigned block_direction_fragmentation_type : 2;
unsigned is_inside_balanced_columns : 1;
unsigned is_in_column_bfc : 1;
+ unsigned early_break_appeal : 2; // NGBreakAppeal
bool MaySkipLayout(const RareData& other) const {
if (fragmentainer_block_size != other.fragmentainer_block_size ||
- fragmentainer_space_at_bfc_start !=
- other.fragmentainer_space_at_bfc_start ||
+ fragmentainer_offset_at_bfc != other.fragmentainer_offset_at_bfc ||
data_union_type != other.data_union_type ||
block_direction_fragmentation_type !=
other.block_direction_fragmentation_type ||
is_inside_balanced_columns != other.is_inside_balanced_columns ||
- is_in_column_bfc != other.is_in_column_bfc)
+ is_in_column_bfc != other.is_in_column_bfc ||
+ early_break_appeal != other.early_break_appeal)
return false;
if (data_union_type == kNone)
@@ -657,9 +689,10 @@ class CORE_EXPORT NGConstraintSpace final {
// Must be kept in sync with members checked within |MaySkipLayout|.
bool IsInitialForMaySkipLayout() const {
if (fragmentainer_block_size != kIndefiniteSize ||
- fragmentainer_space_at_bfc_start != kIndefiniteSize ||
+ fragmentainer_offset_at_bfc ||
block_direction_fragmentation_type != kFragmentNone ||
- is_inside_balanced_columns || is_in_column_bfc)
+ is_inside_balanced_columns || is_in_column_bfc ||
+ early_break_appeal != kBreakAppealLastResort)
return false;
if (data_union_type == kNone)
@@ -941,4 +974,4 @@ inline std::ostream& operator<<(std::ostream& stream,
} // namespace blink
-#endif // NGConstraintSpace_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_H_
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 a94ee1a7dcd..152b5be0c8b 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
@@ -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 NGConstraintSpaceBuilder_h
-#define NGConstraintSpaceBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_BUILDER_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
@@ -114,13 +114,13 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
space_.EnsureRareData()->fragmentainer_block_size = size;
}
- void SetFragmentainerSpaceAtBfcStart(LayoutUnit space) {
+ void SetFragmentainerOffsetAtBfc(LayoutUnit offset) {
#if DCHECK_IS_ON()
- DCHECK(!is_fragmentainer_space_at_bfc_start_set_);
- is_fragmentainer_space_at_bfc_start_set_ = true;
+ DCHECK(!is_fragmentainer_offset_at_bfc_set_);
+ is_fragmentainer_offset_at_bfc_set_ = true;
#endif
- if (space != kIndefiniteSize)
- space_.EnsureRareData()->fragmentainer_space_at_bfc_start = space;
+ if (offset != LayoutUnit())
+ space_.EnsureRareData()->fragmentainer_offset_at_bfc = offset;
}
void SetTextDirection(TextDirection direction) {
@@ -169,6 +169,12 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
void SetIsInColumnBfc() { space_.EnsureRareData()->is_in_column_bfc = true; }
+ void SetEarlyBreakAppeal(NGBreakAppeal appeal) {
+ if (appeal == kBreakAppealLastResort && !space_.rare_data_)
+ return;
+ space_.EnsureRareData()->early_break_appeal = appeal;
+ }
+
void SetIsTableCell(bool b) { space_.bitfields_.is_table_cell = b; }
void SetIsRestrictedBlockSizeTableCell(bool b) {
@@ -341,7 +347,7 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
bool is_available_size_set_ = false;
bool is_percentage_resolution_size_set_ = false;
bool is_fragmentainer_block_size_set_ = false;
- bool is_fragmentainer_space_at_bfc_start_set_ = false;
+ bool is_fragmentainer_offset_at_bfc_set_ = false;
bool is_block_direction_fragmentation_type_set_ = false;
bool is_margin_strut_set_ = false;
bool is_optimistic_bfc_block_offset_set_ = false;
@@ -359,4 +365,4 @@ class CORE_EXPORT NGConstraintSpaceBuilder final {
} // namespace blink
-#endif // NGConstraintSpaceBuilder
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONSTRAINT_SPACE_BUILDER_H_
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 a4077751018..f5bf0144756 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
@@ -124,8 +124,6 @@ void NGContainerFragmentBuilder::AddChild(
switch (child.Type()) {
case NGPhysicalFragment::kFragmentBox:
case NGPhysicalFragment::kFragmentRenderedLegend:
- if (To<NGBlockBreakToken>(child_break_token)->HasLastResortBreak())
- has_last_resort_break_ = true;
child_break_tokens_.push_back(child_break_token);
break;
case NGPhysicalFragment::kFragmentLineBox:
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 9fc1edd1c7e..870f70f21cd 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
@@ -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 NGContainerFragmentBuilder_h
-#define NGContainerFragmentBuilder_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONTAINER_FRAGMENT_BUILDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONTAINER_FRAGMENT_BUILDER_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -13,6 +13,8 @@
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_break_appeal.h"
+#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_link.h"
@@ -214,6 +216,9 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
NGBreakTokenVector child_break_tokens_;
NGBreakTokenVector inline_break_tokens_;
+ scoped_refptr<const NGEarlyBreak> early_break_;
+ NGBreakAppeal break_appeal_ = kBreakAppealLastResort;
+
NGAdjoiningObjectTypes adjoining_object_types_ = kAdjoiningNone;
bool has_adjoining_object_descendants_ = false;
@@ -221,7 +226,6 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
bool is_pushed_by_floats_ = false;
bool is_legacy_layout_root_ = false;
- bool has_last_resort_break_ = false;
bool has_floating_descendants_ = false;
bool has_orthogonal_flow_roots_ = false;
bool has_descendant_that_depends_on_percentage_block_size_ = false;
@@ -235,4 +239,4 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGFragmentBuilder {
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(
blink::NGContainerFragmentBuilder::ChildWithOffset)
-#endif // NGContainerFragmentBuilder
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_CONTAINER_FRAGMENT_BUILDER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_early_break.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_early_break.h
new file mode 100644
index 00000000000..e66bb4e8f58
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_early_break.h
@@ -0,0 +1,55 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_EARLY_BREAK_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_EARLY_BREAK_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+
+namespace blink {
+
+// Possible early unforced breakpoint. This represents a possible (and good)
+// location to break. In cases where we run out of space at an unideal location,
+// we may want to go back and break here instead.
+class NGEarlyBreak : public RefCounted<NGEarlyBreak> {
+ public:
+ enum BreakType {
+ kLine, // Break before a specified line number.
+ kBlock // Break before or inside a specified child block.
+ };
+
+ explicit NGEarlyBreak(
+ NGBlockNode block,
+ scoped_refptr<const NGEarlyBreak> break_inside_child = nullptr)
+ : box_(block.GetLayoutBox()),
+ break_inside_child_(break_inside_child),
+ type_(kBlock) {}
+ explicit NGEarlyBreak(int line_number)
+ : line_number_(line_number), type_(kLine) {}
+
+ BreakType Type() const { return type_; }
+ bool IsBreakBefore() const { return !break_inside_child_; }
+ NGBlockNode BlockNode() const {
+ CHECK_EQ(type_, kBlock);
+ return NGBlockNode(box_);
+ }
+ int LineNumber() const {
+ DCHECK_EQ(type_, kLine);
+ return line_number_;
+ }
+ const NGEarlyBreak* BreakInside() const { return break_inside_child_.get(); }
+
+ private:
+ union {
+ LayoutBox* box_; // Set if type_ == kBlock
+ int line_number_; // Set if type_ == kLine
+ };
+ scoped_refptr<const NGEarlyBreak> break_inside_child_;
+ BreakType type_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_EARLY_BREAK_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 4fb3a168176..ffc97a05c02 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
@@ -130,8 +130,7 @@ scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() {
// Note that in size containment, we have to consider sizing as if we have no
// contents, with the conjecture being that legend is part of the contents.
// Thus, only do this adjustment if we do not contain size.
- if (!Node().ShouldApplySizeContainment() &&
- !Node().DisplayLockInducesSizeContainment()) {
+ if (!Node().ShouldApplySizeContainment()) {
LayoutUnit minimum_border_box_block_size =
borders_with_legend.BlockSum() + padding.BlockSum();
border_box_size.block_size =
@@ -154,14 +153,10 @@ base::Optional<MinMaxSize> NGFieldsetLayoutAlgorithm::ComputeMinMaxSize(
MinMaxSize sizes;
bool apply_size_containment = node_.ShouldApplySizeContainment();
+ // TODO(crbug.com/1011842): Need to consider content-size here.
if (apply_size_containment) {
if (input.size_type == NGMinMaxSizeType::kContentBoxSize)
return sizes;
- } else if (node_.DisplayLockInducesSizeContainment()) {
- sizes = node_.GetDisplayLockContext().GetLockedContentLogicalWidth();
- if (input.size_type == NGMinMaxSizeType::kContentBoxSize)
- return sizes;
- apply_size_containment = true;
}
// Size containment does not consider the legend for sizing.
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
index d35b09c59f1..bbfc9035ebb 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -61,6 +61,18 @@ void NGFlexLayoutAlgorithm::HandleOutOfFlowPositioned(NGBlockNode child) {
border_scrollbar_padding_.block_start});
}
+bool NGFlexLayoutAlgorithm::IsColumnContainerMainSizeDefinite() const {
+ DCHECK(is_column_);
+ // If this flex container is also a flex item, it might have a definite size
+ // imposed on it by its parent flex container.
+ if (ConstraintSpace().IsFixedBlockSize() &&
+ !ConstraintSpace().IsFixedBlockSizeIndefinite())
+ return true;
+ Length main_size = Style().LogicalHeight();
+ return !BlockLengthUnresolvable(ConstraintSpace(), main_size,
+ LengthResolvePhase::kLayout);
+}
+
bool NGFlexLayoutAlgorithm::IsContainerCrossSizeDefinite() const {
// A column flexbox's cross axis is an inline size, so is definite.
if (is_column_)
@@ -71,12 +83,7 @@ bool NGFlexLayoutAlgorithm::IsContainerCrossSizeDefinite() const {
!ConstraintSpace().IsFixedBlockSizeIndefinite())
return true;
- Length cross_size = Style().LogicalHeight();
- if (cross_size.IsAuto() || cross_size.IsMinContent() ||
- cross_size.IsMaxContent() || cross_size.IsFitContent()) {
- return false;
- }
- return !BlockLengthUnresolvable(ConstraintSpace(), cross_size,
+ return !BlockLengthUnresolvable(ConstraintSpace(), Style().LogicalHeight(),
LengthResolvePhase::kLayout);
}
@@ -97,6 +104,28 @@ bool NGFlexLayoutAlgorithm::DoesItemStretch(const NGBlockNode& child) const {
ItemPosition::kStretch;
}
+// This behavior is under discussion: the item's pre-flexing main size
+// definiteness may no longer imply post-flexing definiteness.
+// TODO(dgrogan): Have https://crbug.com/1003506 and
+// https://github.com/w3c/csswg-drafts/issues/4305 been resolved yet?
+bool NGFlexLayoutAlgorithm::IsItemMainSizeDefinite(
+ const NGBlockNode& child) const {
+ DCHECK(is_column_);
+ // Inline sizes are always definite.
+ // TODO(dgrogan): The relevant tests, the last two cases in
+ // css/css-flexbox/percentage-heights-003.html passed even without this, so it
+ // may be untested or unnecessary.
+ if (MainAxisIsInlineAxis(child))
+ return true;
+ // We need a constraint space for the child to determine resolvability and the
+ // space for flex-basis is sufficient, even though it has some unnecessary
+ // stuff (ShrinkToFit and fixed cross sizes).
+ NGConstraintSpace child_space =
+ BuildConstraintSpaceForDeterminingFlexBasis(child);
+ return !BlockLengthUnresolvable(child_space, child.Style().LogicalHeight(),
+ LengthResolvePhase::kLayout);
+}
+
bool NGFlexLayoutAlgorithm::DoesItemCrossSizeComputeToAuto(
const NGBlockNode& child) const {
const ComputedStyle& child_style = child.Style();
@@ -150,6 +179,33 @@ bool NGFlexLayoutAlgorithm::WillChildCrossSizeBeContainerCrossSize(
DoesItemStretch(child);
}
+NGConstraintSpace
+NGFlexLayoutAlgorithm::BuildConstraintSpaceForDeterminingFlexBasis(
+ const NGBlockNode& flex_item) const {
+ const ComputedStyle& child_style = flex_item.Style();
+ NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
+ child_style.GetWritingMode(),
+ /* is_new_fc */ true);
+ SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item, &space_builder);
+
+ if (ShouldItemShrinkToFit(flex_item))
+ space_builder.SetIsShrinkToFit(true);
+ if (WillChildCrossSizeBeContainerCrossSize(flex_item)) {
+ if (is_column_) {
+ space_builder.SetIsFixedInlineSize(true);
+ } else {
+ space_builder.SetIsFixedBlockSize(true);
+ DCHECK_NE(content_box_size_.block_size, kIndefiniteSize);
+ }
+ }
+
+ // TODO(dgrogan): Change SetPercentageResolutionSize everywhere in this file
+ // to use CalculateChildPercentageSize.
+ space_builder.SetAvailableSize(content_box_size_);
+ space_builder.SetPercentageResolutionSize(content_box_size_);
+ return space_builder.ToConstraintSpace();
+}
+
void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
for (NGLayoutInputNode generic_child = Node().FirstChild(); generic_child;
generic_child = generic_child.NextSibling()) {
@@ -160,27 +216,8 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
}
const ComputedStyle& child_style = child.Style();
- NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
- child_style.GetWritingMode(),
- /* is_new_fc */ true);
- SetOrthogonalFallbackInlineSizeIfNeeded(Style(), child, &space_builder);
-
- if (ShouldItemShrinkToFit(child))
- space_builder.SetIsShrinkToFit(true);
- if (WillChildCrossSizeBeContainerCrossSize(child)) {
- if (is_column_) {
- space_builder.SetIsFixedInlineSize(true);
- } else {
- space_builder.SetIsFixedBlockSize(true);
- DCHECK_NE(content_box_size_.block_size, kIndefiniteSize);
- }
- }
-
- // TODO(dgrogan): Change SetPercentageResolutionSize everywhere in this file
- // to use CalculateChildPercentageSize.
- space_builder.SetAvailableSize(content_box_size_);
- space_builder.SetPercentageResolutionSize(content_box_size_);
- NGConstraintSpace child_space = space_builder.ToConstraintSpace();
+ NGConstraintSpace child_space =
+ BuildConstraintSpaceForDeterminingFlexBasis(child);
NGBoxStrut border_padding_in_child_writing_mode =
ComputeBorders(child_space, child) +
@@ -339,8 +376,7 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
child_space, child_style, border_padding_in_child_writing_mode,
intrinsic_sizes_border_box, specified_length_in_main_axis);
}
- } else if (!specified_length_in_main_axis.IsAuto() &&
- !BlockLengthUnresolvable(child_space,
+ } else if (!BlockLengthUnresolvable(child_space,
specified_length_in_main_axis,
LengthResolvePhase::kLayout)) {
specified_size_suggestion = ResolveMainBlockLength(
@@ -430,9 +466,14 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
available_size.block_size =
flex_item.flexed_content_size + flex_item.main_axis_border_padding;
space_builder.SetIsFixedBlockSize(true);
- // TODO(dgrogan): Set IsFixedBlockSizeIndefinite if neither the item's
- // nor container's main size is definite. (The latter being exception 2
- // from https://drafts.csswg.org/css-flexbox/#definite-sizes )
+ // 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);
+ }
} else {
available_size.inline_size =
flex_item.flexed_content_size + flex_item.main_axis_border_padding;
@@ -525,9 +566,10 @@ void NGFlexLayoutAlgorithm::GiveLinesAndItemsFinalPositionAndSize() {
flex_item.cross_axis_size);
if (is_column_) {
available_size.Transpose();
- // TODO(dgrogan): Set IsFixedBlockSizeIndefinite if neither the item's
- // nor container's main size is definite. (The latter being exception
- // 2 from https://drafts.csswg.org/css-flexbox/#definite-sizes )
+ if (!IsColumnContainerMainSizeDefinite() &&
+ !IsItemMainSizeDefinite(flex_item.ng_input_node)) {
+ space_builder.SetIsFixedBlockSizeIndefinite(true);
+ }
}
space_builder.SetAvailableSize(available_size);
space_builder.SetPercentageResolutionSize(content_box_size_);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
index 2f10de2911a..b9af9a28c2a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
@@ -29,6 +29,7 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
private:
bool DoesItemCrossSizeComputeToAuto(const NGBlockNode& child) const;
+ bool IsItemMainSizeDefinite(const NGBlockNode& child) const;
bool ShouldItemShrinkToFit(const NGBlockNode& child) const;
bool DoesItemStretch(const NGBlockNode& child) const;
// This implements the first of the additional scenarios where a flex item
@@ -39,6 +40,8 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
bool IsColumnContainerMainSizeDefinite() const;
bool IsContainerCrossSizeDefinite() const;
+ NGConstraintSpace BuildConstraintSpaceForDeterminingFlexBasis(
+ const NGBlockNode& flex_item) const;
void ConstructAndAppendFlexItems();
void GiveLinesAndItemsFinalPositionAndSize();
// This is same method as FlexItem but we need that logic before FlexItem is
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
index bc75b013129..06fedcf926a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
@@ -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 NGFloatsUtils_h
-#define NGFloatsUtils_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLOATS_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLOATS_UTILS_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -44,4 +44,4 @@ PositionFloat(const LogicalSize& float_available_size,
} // namespace blink
-#endif // NGFloatsUtils_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FLOATS_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment.h
index cd5ac2aac6d..63e80ed8bd6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment.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 NGFragment_h
-#define NGFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h"
@@ -57,4 +57,4 @@ class CORE_EXPORT NGFragment {
} // namespace blink
-#endif // NGFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENT_H_
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 0b10af14a77..31af1043769 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,12 +4,14 @@
#include "third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.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"
#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_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -64,6 +66,9 @@ bool IsForcedBreakValue(const NGConstraintSpace& constraint_space,
EBreakBetween break_value) {
if (break_value == EBreakBetween::kColumn)
return constraint_space.BlockFragmentationType() == kFragmentColumn;
+ // TODO(mstensho): The innermost fragmentation type doesn't tell us everything
+ // here. We might want to force a break to the next page, even if we're in
+ // multicol (printing multicol, for instance).
if (break_value == EBreakBetween::kLeft ||
break_value == EBreakBetween::kPage ||
break_value == EBreakBetween::kRecto ||
@@ -73,28 +78,87 @@ bool IsForcedBreakValue(const NGConstraintSpace& constraint_space,
return false;
}
+template <typename Property>
+bool IsAvoidBreakValue(const NGConstraintSpace& constraint_space,
+ Property break_value) {
+ if (break_value == Property::kAvoid)
+ return constraint_space.HasBlockFragmentation();
+ if (break_value == Property::kAvoidColumn)
+ return constraint_space.BlockFragmentationType() == kFragmentColumn;
+ // TODO(mstensho): The innermost fragmentation type doesn't tell us everything
+ // here. We might want to avoid breaking to the next page, even if we're
+ // in multicol (printing multicol, for instance).
+ if (break_value == Property::kAvoidPage)
+ return constraint_space.BlockFragmentationType() == kFragmentPage;
+ return false;
+}
+// The properties break-after, break-before and break-inside may all specify
+// avoid* values. break-after and break-before use EBreakBetween, and
+// break-inside uses EBreakInside.
+template bool CORE_TEMPLATE_EXPORT IsAvoidBreakValue(const NGConstraintSpace&,
+ EBreakBetween);
+template bool CORE_TEMPLATE_EXPORT IsAvoidBreakValue(const NGConstraintSpace&,
+ EBreakInside);
+
+EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child,
+ const NGLayoutResult& layout_result,
+ const NGBoxFragmentBuilder& builder) {
+ if (child.IsInline())
+ return EBreakBetween::kAuto;
+ EBreakBetween break_before = JoinFragmentainerBreakValues(
+ child.Style().BreakBefore(), layout_result.InitialBreakBefore());
+ return builder.JoinedBreakBetweenValue(break_before);
+}
+
+NGBreakAppeal CalculateBreakAppealInside(const NGConstraintSpace& space,
+ NGBlockNode child,
+ const NGLayoutResult& layout_result) {
+ if (layout_result.HasForcedBreak())
+ return kBreakAppealPerfect;
+ const auto& physical_fragment = layout_result.PhysicalFragment();
+ NGBreakAppeal appeal;
+ // If we actually broke, get the appeal from the break token. Otherwise, get
+ // the early break appeal.
+ if (const auto* block_break_token =
+ DynamicTo<NGBlockBreakToken>(physical_fragment.BreakToken()))
+ appeal = block_break_token->BreakAppeal();
+ else
+ appeal = layout_result.EarlyBreakAppeal();
+
+ // We don't let break-inside:avoid affect the child's stored break appeal, but
+ // we rather handle it now, on the outside. The reason is that we want to be
+ // able to honor any 'avoid' values on break-before or break-after among the
+ // children of the child, even if we need to disregrard a break-inside:avoid
+ // rule on the child itself. This prevents us from violating more rules than
+ // necessary: if we need to break inside the child (even if it should be
+ // avoided), we'll at least break at the most appealing location inside.
+ if (appeal > kBreakAppealViolatingBreakAvoid &&
+ IsAvoidBreakValue(space, child.Style().BreakInside()))
+ appeal = kBreakAppealViolatingBreakAvoid;
+ return appeal;
+}
+
void SetupFragmentation(const NGConstraintSpace& parent_space,
LayoutUnit new_bfc_block_offset,
NGConstraintSpaceBuilder* builder,
bool is_new_fc) {
DCHECK(parent_space.HasBlockFragmentation());
- LayoutUnit space_available =
- parent_space.FragmentainerSpaceAtBfcStart() - new_bfc_block_offset;
-
builder->SetFragmentainerBlockSize(parent_space.FragmentainerBlockSize());
- builder->SetFragmentainerSpaceAtBfcStart(space_available);
+ new_bfc_block_offset += parent_space.FragmentainerOffsetAtBfc();
+ builder->SetFragmentainerOffsetAtBfc(new_bfc_block_offset);
builder->SetFragmentationType(parent_space.BlockFragmentationType());
if (parent_space.IsInColumnBfc() && !is_new_fc)
builder->SetIsInColumnBfc();
}
-void FinishFragmentation(NGBoxFragmentBuilder* builder,
+void FinishFragmentation(const NGConstraintSpace& space,
LayoutUnit block_size,
LayoutUnit intrinsic_block_size,
LayoutUnit previously_consumed_block_size,
- LayoutUnit space_left) {
+ LayoutUnit space_left,
+ NGBoxFragmentBuilder* builder) {
if (builder->DidBreak()) {
// One of our children broke. Even if we fit within the remaining space, we
// need to prepare a break token.
@@ -109,9 +173,12 @@ void FinishFragmentation(NGBoxFragmentBuilder* builder,
// Need a break inside this block.
builder->SetConsumedBlockSize(space_left + previously_consumed_block_size);
builder->SetDidBreak();
+ builder->SetBreakAppeal(kBreakAppealPerfect);
builder->SetBlockSize(space_left);
builder->SetIntrinsicBlockSize(space_left);
- builder->PropagateSpaceShortage(block_size - space_left);
+ if (space.BlockFragmentationType() == kFragmentColumn &&
+ !space.IsInitialColumnBalancingPass())
+ builder->PropagateSpaceShortage(block_size - space_left);
return;
}
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 0d5a71d21f2..6e8ae1aeb8a 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
@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NGFragmentationUtils_h
-#define NGFragmentationUtils_h
+#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/blink/renderer/core/layout/ng/ng_block_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.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_physical_container_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
namespace blink {
-class NGConstraintSpace;
+class NGBoxFragmentBuilder;
+class NGLayoutResult;
// Join two adjacent break values specified on break-before and/or break-
// after. avoid* values win over auto values, and forced break values win over
@@ -32,11 +34,37 @@ EBreakBetween JoinFragmentainerBreakValues(EBreakBetween first_value,
// current fragmentation context.
bool IsForcedBreakValue(const NGConstraintSpace&, EBreakBetween);
+// Return true if the specified break value means that we should avoid breaking,
+// given the current fragmentation context.
+template <typename Property>
+bool IsAvoidBreakValue(const NGConstraintSpace&, Property);
+
// Return true if we're resuming layout after a previous break.
inline bool IsResumingLayout(const NGBlockBreakToken* token) {
return token && !token->IsBreakBefore();
}
+// Calculate the final "break-between" value at a class A or C breakpoint. This
+// is the combination of all break-before and break-after values that met at the
+// breakpoint.
+EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child,
+ const NGLayoutResult&,
+ const NGBoxFragmentBuilder&);
+
+// Calculate the appeal of breaking inside this child.
+NGBreakAppeal CalculateBreakAppealInside(const NGConstraintSpace& space,
+ NGBlockNode child,
+ const NGLayoutResult&);
+
+// Return the block space that was available in the current fragmentainer at the
+// start of the current block formatting context. Note that if the start of the
+// current block formatting context is in a previous fragmentainer, the size of
+// the current fragmentainer is returned instead.
+inline LayoutUnit FragmentainerSpaceAtBfcStart(const NGConstraintSpace& space) {
+ DCHECK(space.HasKnownFragmentainerBlockSize());
+ return space.FragmentainerBlockSize() - space.FragmentainerOffsetAtBfc();
+}
+
// Set up a child's constraint space builder for block fragmentation. The child
// participates in the same fragmentation context as parent_space. If the child
// establishes a new formatting context, new_bfc_block_offset must be set to the
@@ -49,12 +77,13 @@ void SetupFragmentation(const NGConstraintSpace& parent_space,
bool is_new_fc);
// Write fragmentation information to the fragment builder after layout.
-void FinishFragmentation(NGBoxFragmentBuilder*,
+void FinishFragmentation(const NGConstraintSpace&,
LayoutUnit block_size,
LayoutUnit intrinsic_block_size,
LayoutUnit previously_consumed_block_size,
- LayoutUnit space_left);
+ LayoutUnit space_left,
+ NGBoxFragmentBuilder*);
} // namespace blink
-#endif // NGFragmentationUtils_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_FRAGMENTATION_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
index 972af291482..2ef8605d97e 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
@@ -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 NGLayoutAlgorithm_h
-#define NGLayoutAlgorithm_h
+#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 "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -15,6 +15,7 @@
namespace blink {
class ComputedStyle;
+class NGEarlyBreak;
class NGLayoutResult;
struct MinMaxSizeInput;
@@ -46,16 +47,19 @@ struct NGLayoutAlgorithmParams {
NGLayoutAlgorithmParams(NGBlockNode node,
const NGFragmentGeometry& fragment_geometry,
const NGConstraintSpace& space,
- const NGBlockBreakToken* break_token = nullptr)
+ const NGBlockBreakToken* break_token = nullptr,
+ const NGEarlyBreak* early_break = nullptr)
: node(node),
fragment_geometry(fragment_geometry),
space(space),
- break_token(break_token) {}
+ break_token(break_token),
+ early_break(early_break) {}
NGBlockNode node;
const NGFragmentGeometry& fragment_geometry;
const NGConstraintSpace& space;
const NGBlockBreakToken* break_token;
+ const NGEarlyBreak* early_break;
};
// Base class for all LayoutNG algorithms.
@@ -115,4 +119,4 @@ class CORE_EXPORT NGLayoutAlgorithm : public NGLayoutAlgorithmOperations {
} // namespace blink
-#endif // NGLayoutAlgorithm_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_ALGORITHM_H_
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 83e33bba595..3bbf14e1cc0 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
@@ -81,14 +81,6 @@ void NGLayoutInputNode::IntrinsicSize(
*aspect_ratio = LogicalSize(**computed_inline_size, **computed_block_size);
return;
}
- if (DisplayLockInducesSizeContainment()) {
- *computed_inline_size =
- GetDisplayLockContext().GetLockedContentLogicalWidth();
- *computed_block_size =
- GetDisplayLockContext().GetLockedContentLogicalHeight();
- *aspect_ratio = LogicalSize(**computed_inline_size, **computed_block_size);
- return;
- }
IntrinsicSizingInfo legacy_sizing_info;
ToLayoutReplaced(box_)->ComputeIntrinsicSizingInfo(legacy_sizing_info);
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 d5a0da8389d..85b38417897 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
@@ -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 NGLayoutInputNode_h
-#define NGLayoutInputNode_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_INPUT_NODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_INPUT_NODE_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -134,6 +134,14 @@ class CORE_EXPORT NGLayoutInputNode {
(box_->IsBody() || box_->IsTableCell());
}
+ // Return true if this node is monolithic for block fragmentation.
+ bool IsMonolithic() const {
+ // Lines are always monolithic. We cannot block-fragment inside them.
+ if (IsInline())
+ return true;
+ return box_->GetPaginationBreakability() == LayoutBox::kForbidBreaks;
+ }
+
bool CreatesNewFormattingContext() const {
return IsBlock() && box_->CreatesNewFormattingContext();
}
@@ -189,9 +197,6 @@ class CORE_EXPORT NGLayoutInputNode {
DCHECK(box_->GetDisplayLockContext());
return *box_->GetDisplayLockContext();
}
- bool DisplayLockInducesSizeContainment() const {
- return box_->DisplayLockInducesSizeContainment();
- }
bool LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget target) const {
return box_->LayoutBlockedByDisplayLock(target);
}
@@ -233,4 +238,4 @@ class CORE_EXPORT NGLayoutInputNode {
} // namespace blink
-#endif // NGLayoutInputNode_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_INPUT_NODE_H_
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 495711087af..fac77834d22 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
@@ -27,6 +27,10 @@ struct SameSizeAsNGLayoutResult : public RefCounted<SameSizeAsNGLayoutResult> {
};
LayoutUnit intrinsic_block_size;
unsigned bitfields[1];
+
+#if DCHECK_IS_ON()
+ bool has_valid_space;
+#endif
};
static_assert(sizeof(NGLayoutResult) == sizeof(SameSizeAsNGLayoutResult),
@@ -38,15 +42,31 @@ NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
NGBoxFragmentBuilder* builder)
: NGLayoutResult(std::move(physical_fragment),
- builder,
- /* cache_space */ true) {
+ static_cast<NGContainerFragmentBuilder*>(builder)) {
bitfields_.is_initial_block_size_indefinite =
builder->is_initial_block_size_indefinite_;
bitfields_.subtree_modified_margin_strut =
builder->subtree_modified_margin_strut_;
intrinsic_block_size_ = builder->intrinsic_block_size_;
- if (builder->minimal_space_shortage_ != LayoutUnit::Max())
+ if (builder->minimal_space_shortage_ != LayoutUnit::Max()) {
+#if DCHECK_IS_ON()
+ DCHECK(!HasRareData() || !rare_data_->has_tallest_unbreakable_block_size);
+#endif
EnsureRareData()->minimal_space_shortage = builder->minimal_space_shortage_;
+ }
+ if (builder->tallest_unbreakable_block_size_ >= LayoutUnit()) {
+ auto* rare_data = EnsureRareData();
+ rare_data->tallest_unbreakable_block_size =
+ builder->tallest_unbreakable_block_size_;
+#if DCHECK_IS_ON()
+ rare_data->has_tallest_unbreakable_block_size = true;
+#endif
+ }
+ if (builder->unconstrained_intrinsic_block_size_ != kIndefiniteSize &&
+ builder->unconstrained_intrinsic_block_size_ != intrinsic_block_size_) {
+ EnsureRareData()->unconstrained_intrinsic_block_size_ =
+ builder->unconstrained_intrinsic_block_size_;
+ }
if (builder->custom_layout_data_) {
EnsureRareData()->custom_layout_data =
std::move(builder->custom_layout_data_);
@@ -64,14 +84,11 @@ NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
NGLineBoxFragmentBuilder* builder)
: NGLayoutResult(std::move(physical_fragment),
- builder,
- /* cache_space */ false) {}
+ static_cast<NGContainerFragmentBuilder*>(builder)) {}
-NGLayoutResult::NGLayoutResult(NGLayoutResultStatus status,
- NGBoxFragmentBuilder* builder)
+NGLayoutResult::NGLayoutResult(EStatus status, NGBoxFragmentBuilder* builder)
: NGLayoutResult(/* physical_fragment */ nullptr,
- builder,
- /* cache_space */ false) {
+ static_cast<NGContainerFragmentBuilder*>(builder)) {
bitfields_.status = status;
DCHECK_NE(status, kSuccess)
<< "Use the other constructor for successful layout";
@@ -114,17 +131,19 @@ NGLayoutResult::NGLayoutResult(const NGLayoutResult& other,
if (new_end_margin_strut != NGMarginStrut() || HasRareData())
EnsureRareData()->end_margin_strut = new_end_margin_strut;
+
+#if DCHECK_IS_ON()
+ has_valid_space_ = other.has_valid_space_;
+#endif
}
NGLayoutResult::NGLayoutResult(
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
- NGContainerFragmentBuilder* builder,
- bool cache_space)
+ NGContainerFragmentBuilder* builder)
: space_(builder->space_ ? NGConstraintSpace(*builder->space_)
: NGConstraintSpace()),
physical_fragment_(std::move(physical_fragment)),
bitfields_(
- /* has_valid_space */ cache_space && builder->space_,
/* is_self_collapsing */ builder->is_self_collapsing_,
/* is_pushed_by_floats */ builder->is_pushed_by_floats_,
/* adjoining_object_types */ builder->adjoining_object_types_,
@@ -155,6 +174,19 @@ NGLayoutResult::NGLayoutResult(
space_.ExclusionSpace().MoveDerivedGeometry(builder->exclusion_space_);
}
+ // If we produced a fragment that we didn't break inside, provide the best
+ // early possible breakpoint that we found inside. This early breakpoint will
+ // be propagated to the container for further consideration. If we didn't
+ // produce a fragment, on the other hand, it means that we're going to
+ // re-layout now, and break at the early breakpoint (i.e. the status is
+ // kNeedsEarlierBreak).
+ if (builder->early_break_ &&
+ (!physical_fragment_ || !physical_fragment_->BreakToken())) {
+ auto* rare_data = EnsureRareData();
+ rare_data->early_break = builder->early_break_;
+ rare_data->early_break_appeal = builder->break_appeal_;
+ }
+
if (HasRareData()) {
rare_data_->bfc_line_offset = builder->bfc_line_offset_;
rare_data_->bfc_block_offset = builder->bfc_block_offset_;
@@ -165,6 +197,10 @@ NGLayoutResult::NGLayoutResult(
bitfields_.is_bfc_block_offset_nullopt =
!builder->bfc_block_offset_.has_value();
}
+
+#if DCHECK_IS_ON()
+ has_valid_space_ = builder->space_;
+#endif
}
NGLayoutResult::~NGLayoutResult() {
@@ -219,7 +255,6 @@ void NGLayoutResult::CheckSameForSimplifiedLayout(
DCHECK(EndMarginStrut() == other.EndMarginStrut());
DCHECK_EQ(MinimalSpaceShortage(), other.MinimalSpaceShortage());
- DCHECK_EQ(bitfields_.has_valid_space, other.bitfields_.has_valid_space);
DCHECK_EQ(bitfields_.has_forced_break, other.bitfields_.has_forced_break);
DCHECK_EQ(bitfields_.is_self_collapsing, other.bitfields_.is_self_collapsing);
DCHECK_EQ(bitfields_.is_pushed_by_floats,
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 ae90f2afdfd..46123a06de0 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
@@ -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 NGLayoutResult_h
-#define NGLayoutResult_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_RESULT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_RESULT_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
@@ -13,6 +13,8 @@
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_break_appeal.h"
+#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.h"
#include "third_party/blink/renderer/core/layout/ng/ng_link.h"
@@ -35,9 +37,10 @@ class NGLineBoxFragmentBuilder;
// NGFragment et al.
class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
public:
- enum NGLayoutResultStatus {
+ enum EStatus {
kSuccess = 0,
kBfcBlockOffsetResolved = 1,
+ kNeedsEarlierBreak = 2,
// When adding new values, make sure the bit size of |Bitfields::status| is
// large enough to store.
};
@@ -55,7 +58,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
const NGPhysicalContainerFragment& PhysicalFragment() const {
DCHECK(physical_fragment_);
- DCHECK_EQ(NGLayoutResultStatus::kSuccess, Status());
+ DCHECK_EQ(kSuccess, Status());
return *physical_fragment_;
}
@@ -75,6 +78,19 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return HasRareData() ? rare_data_->column_spanner : NGBlockNode(nullptr);
}
+ scoped_refptr<const NGEarlyBreak> GetEarlyBreak() const {
+ if (!HasRareData())
+ return nullptr;
+ return rare_data_->early_break;
+ }
+
+ // Return the appeal of the best breakpoint (if any) we found inside the node.
+ NGBreakAppeal EarlyBreakAppeal() const {
+ if (HasRareData())
+ return static_cast<NGBreakAppeal>(rare_data_->early_break_appeal);
+ return kBreakAppealLastResort;
+ }
+
const NGExclusionSpace& ExclusionSpace() const {
if (bitfields_.has_rare_data_exclusion_space) {
DCHECK(HasRareData());
@@ -84,9 +100,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return space_.ExclusionSpace();
}
- NGLayoutResultStatus Status() const {
- return static_cast<NGLayoutResultStatus>(bitfields_.status);
- }
+ EStatus Status() const { return static_cast<EStatus>(bitfields_.status); }
LayoutUnit BfcLineOffset() const {
if (HasRareData())
@@ -126,9 +140,31 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return intrinsic_block_size_;
}
+ LayoutUnit UnconstrainedIntrinsicBlockSize() const {
+ return HasRareData() && rare_data_->unconstrained_intrinsic_block_size_ !=
+ kIndefiniteSize
+ ? rare_data_->unconstrained_intrinsic_block_size_
+ : intrinsic_block_size_;
+ }
+
LayoutUnit MinimalSpaceShortage() const {
- return HasRareData() ? rare_data_->minimal_space_shortage
- : LayoutUnit::Max();
+ if (!HasRareData())
+ return LayoutUnit::Max();
+#if DCHECK_IS_ON()
+ // This field shares storage with another field.
+ DCHECK(!rare_data_->has_tallest_unbreakable_block_size);
+#endif
+ return rare_data_->minimal_space_shortage;
+ }
+
+ LayoutUnit TallestUnbreakableBlockSize() const {
+ if (!HasRareData())
+ return LayoutUnit();
+#if DCHECK_IS_ON()
+ // This field shares storage with another field.
+ DCHECK(rare_data_->has_tallest_unbreakable_block_size);
+#endif
+ return rare_data_->tallest_unbreakable_block_size;
}
SerializedScriptValue* CustomLayoutData() const {
@@ -191,14 +227,11 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
return bitfields_.subtree_modified_margin_strut;
}
- // Returns true if the space stored with this layout result, is valid.
- bool HasValidConstraintSpaceForCaching() const {
- return bitfields_.has_valid_space;
- }
-
// Returns the space which generated this object for caching purposes.
const NGConstraintSpace& GetConstraintSpaceForCaching() const {
- DCHECK(bitfields_.has_valid_space);
+#if DCHECK_IS_ON()
+ DCHECK(has_valid_space_);
+#endif
return space_;
}
@@ -255,7 +288,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
NGLineBoxFragmentBuilder*);
// This constructor is for a non-success status.
- NGLayoutResult(NGLayoutResultStatus, NGBoxFragmentBuilder*);
+ NGLayoutResult(EStatus, NGBoxFragmentBuilder*);
// We don't need the copy constructor, move constructor, copy
// assigmnment-operator, or move assignment-operator today.
@@ -273,8 +306,7 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
// Delegate constructor that sets up what it can, based on the builder.
NGLayoutResult(
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment,
- NGContainerFragmentBuilder* builder,
- bool cache_space);
+ NGContainerFragmentBuilder* builder);
static NGExclusionSpace MergeExclusionSpaces(
const NGLayoutResult& other,
@@ -294,13 +326,31 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
LayoutUnit bfc_line_offset;
base::Optional<LayoutUnit> bfc_block_offset;
+ scoped_refptr<const NGEarlyBreak> early_break;
+ NGBreakAppeal early_break_appeal = kBreakAppealLastResort;
LogicalOffset oof_positioned_offset;
NGMarginStrut end_margin_strut;
NGUnpositionedListMarker unpositioned_list_marker;
NGBlockNode column_spanner = nullptr;
- LayoutUnit minimal_space_shortage = LayoutUnit::Max();
+ union {
+ // Only set in the initial column balancing layout pass, when we have no
+ // clue what the column block-size is going to be.
+ LayoutUnit tallest_unbreakable_block_size;
+
+ // Only set in subsequent column balancing passes, when we have set a
+ // tentative column block-size. At every column boundary we'll record
+ // space shortage, and store the smallest one here. If the columns
+ // couldn't fit all the content, and we're allowed to stretch columns
+ // further, we'll perform another pass with the column block-size
+ // increased by this amount.
+ LayoutUnit minimal_space_shortage = LayoutUnit::Max();
+ };
NGExclusionSpace exclusion_space;
scoped_refptr<SerializedScriptValue> custom_layout_data;
+ LayoutUnit unconstrained_intrinsic_block_size_ = kIndefiniteSize;
+#if DCHECK_IS_ON()
+ bool has_tallest_unbreakable_block_size = false;
+#endif
};
bool HasRareData() const { return bitfields_.has_rare_data; }
@@ -314,14 +364,12 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
// never uninitialized (potentially allowing a dangling pointer).
Bitfields()
: Bitfields(
- /* has_valid_space */ false,
/* is_self_collapsing */ false,
/* is_pushed_by_floats */ false,
/* adjoining_object_types */ kAdjoiningNone,
/* has_descendant_that_depends_on_percentage_block_size */
false) {}
- Bitfields(bool has_valid_space,
- bool is_self_collapsing,
+ Bitfields(bool is_self_collapsing,
bool is_pushed_by_floats,
NGAdjoiningObjectTypes adjoining_object_types,
bool has_descendant_that_depends_on_percentage_block_size)
@@ -329,7 +377,6 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
has_rare_data_exclusion_space(false),
has_oof_positioned_offset(false),
is_bfc_block_offset_nullopt(false),
- has_valid_space(has_valid_space),
has_forced_break(false),
is_self_collapsing(is_self_collapsing),
is_pushed_by_floats(is_pushed_by_floats),
@@ -347,7 +394,6 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
unsigned has_oof_positioned_offset : 1;
unsigned is_bfc_block_offset_nullopt : 1;
- unsigned has_valid_space : 1;
unsigned has_forced_break : 1;
unsigned is_self_collapsing : 1;
@@ -362,11 +408,11 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
unsigned initial_break_before : 4; // EBreakBetween
unsigned final_break_after : 4; // EBreakBetween
- unsigned status : 1; // NGLayoutResultStatus
+ unsigned status : 2; // EStatus
};
// The constraint space which generated this layout result, may not be valid
- // as indicated by |Bitfields::has_valid_space|.
+ // as indicated by |has_valid_space_|.
const NGConstraintSpace space_;
scoped_refptr<const NGPhysicalContainerFragment> physical_fragment_;
@@ -390,8 +436,12 @@ class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> {
LayoutUnit intrinsic_block_size_;
Bitfields bitfields_;
+
+#if DCHECK_IS_ON()
+ bool has_valid_space_ = false;
+#endif
};
} // namespace blink
-#endif // NGLayoutResult_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_RESULT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
index 86905340f5b..107e1cc3dc8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
@@ -49,7 +49,7 @@ TEST_F(NGLayoutResultCachingTest, HitDifferentExclusionSpace) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -92,7 +92,7 @@ TEST_F(NGLayoutResultCachingTest, HitDifferentBFCOffset) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -148,7 +148,7 @@ TEST_F(NGLayoutResultCachingTest, HitDifferentBFCOffsetSameMarginStrut) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -188,7 +188,7 @@ TEST_F(NGLayoutResultCachingTest, MissDescendantAboveBlockStart1) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -228,7 +228,7 @@ TEST_F(NGLayoutResultCachingTest, MissDescendantAboveBlockStart2) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -268,7 +268,7 @@ TEST_F(NGLayoutResultCachingTest, HitOOFDescendantAboveBlockStart) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -313,7 +313,7 @@ TEST_F(NGLayoutResultCachingTest, HitLineBoxDescendantAboveBlockStart) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -351,7 +351,7 @@ TEST_F(NGLayoutResultCachingTest, MissFloatInitiallyIntruding1) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -389,7 +389,7 @@ TEST_F(NGLayoutResultCachingTest, MissFloatInitiallyIntruding2) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -426,7 +426,7 @@ TEST_F(NGLayoutResultCachingTest, MissFloatWillIntrude1) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -463,7 +463,7 @@ TEST_F(NGLayoutResultCachingTest, MissFloatWillIntrude2) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -500,7 +500,7 @@ TEST_F(NGLayoutResultCachingTest, HitPushedByFloats1) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -537,7 +537,7 @@ TEST_F(NGLayoutResultCachingTest, HitPushedByFloats2) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -575,7 +575,7 @@ TEST_F(NGLayoutResultCachingTest, MissPushedByFloats1) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -613,7 +613,7 @@ TEST_F(NGLayoutResultCachingTest, MissPushedByFloats2) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -644,7 +644,7 @@ TEST_F(NGLayoutResultCachingTest, HitDifferentRareData) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -675,7 +675,7 @@ TEST_F(NGLayoutResultCachingTest, HitPercentageMinWidth) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -706,7 +706,7 @@ TEST_F(NGLayoutResultCachingTest, HitFixedMinWidth) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -743,7 +743,7 @@ TEST_F(NGLayoutResultCachingTest, HitShrinkToFitSameIntrinsicSizes) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -779,7 +779,7 @@ TEST_F(NGLayoutResultCachingTest, HitShrinkToFitDifferentParent) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -815,7 +815,7 @@ TEST_F(NGLayoutResultCachingTest, MissQuirksModePercentageBasedChild) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
EXPECT_EQ(result.get(), nullptr);
@@ -856,7 +856,7 @@ TEST_F(NGLayoutResultCachingTest, HitQuirksModePercentageBasedParentAndChild) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -891,7 +891,7 @@ TEST_F(NGLayoutResultCachingTest, HitStandardsModePercentageBasedChild) {
const NGConstraintSpace& space =
src->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
EXPECT_NE(result.get(), nullptr);
@@ -939,7 +939,7 @@ TEST_F(NGLayoutResultCachingTest, ChangeTableCellBlockSizeConstrainedness) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// The first child has a fixed height, and shouldn't be affected by the cell
// height.
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
@@ -947,8 +947,8 @@ TEST_F(NGLayoutResultCachingTest, ChangeTableCellBlockSizeConstrainedness) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// The second child has overflow:auto and a percentage height, but its
// intrinsic height is identical to its extrinsic height (when the cell has a
// height). So it won't need layout, either.
@@ -957,8 +957,8 @@ TEST_F(NGLayoutResultCachingTest, ChangeTableCellBlockSizeConstrainedness) {
fragment_geometry.reset();
space = src3->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test3->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test3->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// The third child has overflow:auto and a percentage height, and its
// intrinsic height is 0 (no children), so it matters whether the cell has a
// height or not. We're only going to need simplified layout, though, since no
@@ -1051,7 +1051,7 @@ TEST_F(NGLayoutResultCachingTest, SelfCollapsingShifting) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// Case 1: We have a different set of constraints, but as the child has no
// adjoining descendants it can be shifted anywhere.
@@ -1060,8 +1060,8 @@ TEST_F(NGLayoutResultCachingTest, SelfCollapsingShifting) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 2: We have a different set of constraints, but the child has an
// adjoining object and isn't "past" the floats - it can't be reused.
@@ -1070,8 +1070,8 @@ TEST_F(NGLayoutResultCachingTest, SelfCollapsingShifting) {
fragment_geometry.reset();
space = src3->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test3->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test3->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 3: We have a different set of constraints, and adjoining descendants,
// but have a position past where they might affect us.
@@ -1129,7 +1129,7 @@ TEST_F(NGLayoutResultCachingTest, ClearancePastAdjoiningFloatsMovement) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// Case 1: We have forced clearance, but floats won't impact our children.
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
@@ -1137,8 +1137,8 @@ TEST_F(NGLayoutResultCachingTest, ClearancePastAdjoiningFloatsMovement) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 2: We have forced clearance, and floats will impact our children.
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
@@ -1193,7 +1193,7 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementSelfCollapsing) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// Case 1: We can safely re-use this fragment as it doesn't append anything
// to the margin-strut within the sub-tree.
@@ -1207,8 +1207,8 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementSelfCollapsing) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 2: We can't re-use this fragment as it appended a non-zero value to
// the margin-strut within the sub-tree.
@@ -1286,7 +1286,7 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementInFlow) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// Case 1: We can safely re-use this fragment as it doesn't append anything
// to the margin-strut within the sub-tree.
@@ -1295,8 +1295,8 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementInFlow) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 2: We can't re-use this fragment as it appended a non-zero value to
// the margin-strut within the sub-tree.
@@ -1305,8 +1305,8 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementInFlow) {
fragment_geometry.reset();
space = src3->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test3->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test3->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 3: We can't re-use this fragment as a (inner) self-collapsing block
// appended a non-zero value to the margin-strut within the sub-tree.
@@ -1346,7 +1346,7 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementPercentage) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// We can't re-use this fragment as it appended a non-zero value (50%) to the
// margin-strut within the sub-tree.
@@ -1408,7 +1408,7 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementDiscard) {
NGConstraintSpace space =
src1->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
scoped_refptr<const NGLayoutResult> result = test1->CachedLayoutResult(
- space, nullptr, &fragment_geometry, &cache_status);
+ space, nullptr, nullptr, &fragment_geometry, &cache_status);
// Case 1: We can't re-use this fragment as the sub-tree discards margins.
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
@@ -1416,8 +1416,8 @@ TEST_F(NGLayoutResultCachingTest, MarginStrutMovementDiscard) {
fragment_geometry.reset();
space = src2->GetCachedLayoutResult()->GetConstraintSpaceForCaching();
- result = test2->CachedLayoutResult(space, nullptr, &fragment_geometry,
- &cache_status);
+ result = test2->CachedLayoutResult(space, nullptr, nullptr,
+ &fragment_geometry, &cache_status);
// Case 2: Also check a self-collapsing block with a block-end discard.
EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
index f0eb0962f8c..95b6a5f5860 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
@@ -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 NGLayoutTest_h
-#define NGLayoutTest_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_TEST_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_TEST_H_
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
@@ -22,4 +22,4 @@ class NGLayoutTest : public RenderingTest, private ScopedLayoutNGForTest {
} // namespace blink
-#endif // NGLayoutTest_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_TEST_H_
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 9df4faa0413..229af34617d 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
@@ -310,7 +310,6 @@ NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatus(
const NGConstraintSpace& new_space,
base::Optional<NGFragmentGeometry>* fragment_geometry) {
DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess);
- DCHECK(cached_layout_result.HasValidConstraintSpaceForCaching());
const NGConstraintSpace& old_space =
cached_layout_result.GetConstraintSpaceForCaching();
@@ -346,7 +345,6 @@ bool MaySkipLegacyLayout(const NGBlockNode& node,
const NGLayoutResult& cached_layout_result,
const NGConstraintSpace& new_space) {
DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess);
- DCHECK(cached_layout_result.HasValidConstraintSpaceForCaching());
const NGConstraintSpace& old_space =
cached_layout_result.GetConstraintSpaceForCaching();
@@ -372,7 +370,6 @@ bool MaySkipLayoutWithinBlockFormattingContext(
LayoutUnit* block_offset_delta,
NGMarginStrut* end_margin_strut) {
DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess);
- DCHECK(cached_layout_result.HasValidConstraintSpaceForCaching());
DCHECK(bfc_block_offset);
DCHECK(block_offset_delta);
DCHECK(end_margin_strut);
@@ -544,13 +541,4 @@ bool MaySkipLayoutWithinBlockFormattingContext(
return true;
}
-bool IsBlockLayoutComplete(const NGConstraintSpace& space,
- const NGLayoutResult& result) {
- if (result.Status() != NGLayoutResult::kSuccess)
- return false;
- if (space.IsIntermediateLayout())
- return false;
- return true;
-}
-
} // namespace blink
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 3989312d801..a1d2b06980d 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
@@ -62,12 +62,6 @@ bool MaySkipLayoutWithinBlockFormattingContext(
LayoutUnit* block_offset_delta,
NGMarginStrut* end_margin_strut);
-// Return true if layout is considered complete. In some cases we require more
-// than one layout pass.
-// This function never considers intermediate layouts with
-// |NGConstraintSpace::IsIntermediateLayout| to be complete.
-bool IsBlockLayoutComplete(const NGConstraintSpace&, const NGLayoutResult&);
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_UTILS_H_
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 6ce2db92047..21e6e385b82 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
@@ -89,10 +89,16 @@ bool BlockLengthUnresolvable(
const Length& length,
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max) {
+ if (length.IsAuto() || length.IsMinContent() || length.IsMaxContent() ||
+ length.IsFitContent() || length.IsMaxSizeNone())
+ return true;
if (length.IsPercentOrCalc()) {
if (phase == LengthResolvePhase::kIntrinsic)
return true;
+ // TODO(dgrogan): Make this account for constraint_space.IsFixedSizeBlock &&
+ // constraint_space.IsFixedBlockSizeIndefinite?
+
LayoutUnit percentage_resolution_block_size =
opt_percentage_resolution_block_size_for_min_max
? *opt_percentage_resolution_block_size_for_min_max
@@ -543,11 +549,15 @@ LayoutUnit ComputeBlockSizeForFragment(
}
// Computes size for a replaced element.
-LogicalSize ComputeReplacedSize(
- const NGLayoutInputNode& node,
- const NGConstraintSpace& space,
- const base::Optional<MinMaxSize>& child_minmax) {
+void ComputeReplacedSize(const NGLayoutInputNode& node,
+ const NGConstraintSpace& space,
+ const base::Optional<MinMaxSize>& child_minmax,
+ base::Optional<LogicalSize>* out_replaced_size,
+ base::Optional<LogicalSize>* out_aspect_ratio) {
DCHECK(node.IsReplaced());
+ DCHECK(!out_replaced_size->has_value());
+ DCHECK(!out_aspect_ratio->has_value());
+
const ComputedStyle& style = node.Style();
NGBoxStrut border_padding =
@@ -581,8 +591,10 @@ LogicalSize ComputeReplacedSize(
space.AvailableSize().block_size, LengthResolvePhase::kLayout);
replaced_block = ConstrainByMinMax(*replaced_block, block_min, block_max);
}
- if (replaced_inline && replaced_block)
- return LogicalSize(*replaced_inline, *replaced_block);
+ if (replaced_inline && replaced_block) {
+ out_replaced_size->emplace(*replaced_inline, *replaced_block);
+ return;
+ }
base::Optional<LayoutUnit> intrinsic_inline;
base::Optional<LayoutUnit> intrinsic_block;
@@ -606,22 +618,29 @@ LogicalSize ComputeReplacedSize(
intrinsic_inline = ((*intrinsic_block - border_padding.BlockSum()) *
aspect_ratio.inline_size / aspect_ratio.block_size) +
border_padding.InlineSum();
- } else {
- intrinsic_inline = space.AvailableSize().inline_size;
+ } else if (!replaced_inline && !replaced_block) {
+ // No sizes available, return only the aspect ratio.
+ *out_aspect_ratio = aspect_ratio;
+ return;
}
}
- if (!intrinsic_block) {
+ if (intrinsic_inline && !intrinsic_block) {
+ DCHECK(!aspect_ratio.IsEmpty());
intrinsic_block = ((*intrinsic_inline - border_padding.InlineSum()) *
aspect_ratio.block_size / aspect_ratio.inline_size) +
border_padding.BlockSum();
}
- // At this point, both intrinsic_inline and intrinsic_block have value.
+
+ DCHECK(intrinsic_inline || intrinsic_block || replaced_inline ||
+ replaced_block);
+
// If we only know one length, the other length gets computed wrt one we know.
auto ComputeBlockFromInline = [&replaced_inline, &aspect_ratio,
&border_padding](LayoutUnit default_block) {
- DCHECK(default_block >= border_padding.BlockSum());
- if (aspect_ratio.IsEmpty())
+ if (aspect_ratio.IsEmpty()) {
+ DCHECK_GE(default_block, border_padding.BlockSum());
return default_block;
+ }
return ((*replaced_inline - border_padding.InlineSum()) *
aspect_ratio.block_size / aspect_ratio.inline_size) +
border_padding.BlockSum();
@@ -629,20 +648,25 @@ LogicalSize ComputeReplacedSize(
auto ComputeInlineFromBlock = [&replaced_block, &aspect_ratio,
&border_padding](LayoutUnit default_inline) {
- DCHECK(default_inline >= border_padding.InlineSum());
- if (aspect_ratio.IsEmpty())
+ if (aspect_ratio.IsEmpty()) {
+ DCHECK_GE(default_inline, border_padding.InlineSum());
return default_inline;
+ }
return ((*replaced_block - border_padding.BlockSum()) *
aspect_ratio.inline_size / aspect_ratio.block_size) +
border_padding.InlineSum();
};
if (replaced_inline) {
DCHECK(!replaced_block);
- replaced_block = ComputeBlockFromInline(*intrinsic_block);
+ DCHECK(intrinsic_block || !aspect_ratio.IsEmpty());
+ replaced_block =
+ ComputeBlockFromInline(intrinsic_block.value_or(kIndefiniteSize));
replaced_block = ConstrainByMinMax(*replaced_block, block_min, block_max);
} else if (replaced_block) {
DCHECK(!replaced_inline);
- replaced_inline = ComputeInlineFromBlock(*intrinsic_inline);
+ DCHECK(intrinsic_inline || !aspect_ratio.IsEmpty());
+ replaced_inline =
+ ComputeInlineFromBlock(intrinsic_inline.value_or(kIndefiniteSize));
replaced_inline =
ConstrainByMinMax(*replaced_inline, inline_min, inline_max);
} else {
@@ -703,7 +727,8 @@ LogicalSize ComputeReplacedSize(
}
}
}
- return LogicalSize(*replaced_inline, *replaced_block);
+ out_replaced_size->emplace(*replaced_inline, *replaced_block);
+ return;
}
int ResolveUsedColumnCount(int computed_count,
@@ -1220,14 +1245,6 @@ LayoutUnit ClampIntrinsicBlockSize(const NGBlockNode& node,
return node.ContentBlockSizeForSizeContainment() +
border_scrollbar_padding.BlockSum();
}
-
- // If display locking induces size containment, then we replace its content
- // size with the locked content size.
- if (node.DisplayLockInducesSizeContainment()) {
- return node.GetDisplayLockContext().GetLockedContentLogicalHeight() +
- border_scrollbar_padding.BlockSum();
- }
-
return current_intrinsic_block_size;
}
@@ -1245,14 +1262,6 @@ base::Optional<MinMaxSize> CalculateMinMaxSizesIgnoringChildren(
return sizes;
}
- // Display locked elements override the content size, without considering
- // children. Note that contain: size (above) takes precedence over display
- // locking.
- if (node.DisplayLockInducesSizeContainment()) {
- sizes += node.GetDisplayLockContext().GetLockedContentLogicalWidth();
- return sizes;
- }
-
// If we don't have children, we can also determine the size immediately.
if (!node.FirstChild())
return sizes;
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 a1a1d519bd5..4d69861959a 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
@@ -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 NGLengthUtils_h
-#define NGLengthUtils_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LENGTH_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LENGTH_UTILS_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -59,7 +59,9 @@ CORE_EXPORT bool NeedMinMaxSizeForContentContribution(WritingMode mode,
const ComputedStyle&);
// Returns if the given |Length| is unresolvable, e.g. the length is %-based
-// during the intrinsic phase. Considers 'auto' as resolvable.
+// during the intrinsic phase. For block lengths we also consider 'auto',
+// 'min-content', 'max-content', 'fit-content' and 'none' (for max-block-size)
+// as unresolvable.
CORE_EXPORT bool InlineLengthUnresolvable(const Length&, LengthResolvePhase);
CORE_EXPORT bool BlockLengthUnresolvable(
const NGConstraintSpace&,
@@ -145,11 +147,9 @@ inline LayoutUnit ResolveMinBlockLength(
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
- if (LIKELY(length.IsAuto() || length.IsMinContent() ||
- length.IsMaxContent() || length.IsFitContent() ||
- BlockLengthUnresolvable(
- constraint_space, length, phase,
- opt_percentage_resolution_block_size_for_min_max)))
+ if (LIKELY(BlockLengthUnresolvable(
+ constraint_space, length, phase,
+ opt_percentage_resolution_block_size_for_min_max)))
return border_padding.BlockSum();
return ResolveBlockLengthInternal(
@@ -167,11 +167,9 @@ inline LayoutUnit ResolveMaxBlockLength(
LengthResolvePhase phase,
const LayoutUnit* opt_percentage_resolution_block_size_for_min_max =
nullptr) {
- if (LIKELY(length.IsMaxSizeNone() || length.IsMinContent() ||
- length.IsMaxContent() || length.IsFitContent() ||
- BlockLengthUnresolvable(
- constraint_space, length, phase,
- opt_percentage_resolution_block_size_for_min_max)))
+ if (LIKELY(BlockLengthUnresolvable(
+ constraint_space, length, phase,
+ opt_percentage_resolution_block_size_for_min_max)))
return LayoutUnit::Max();
return ResolveBlockLengthInternal(
@@ -257,10 +255,21 @@ ComputeBlockSizeForFragment(const NGConstraintSpace&,
const NGBoxStrut& border_padding,
LayoutUnit content_size);
-// Computes intrinsic size for replaced elements.
-CORE_EXPORT LogicalSize ComputeReplacedSize(const NGLayoutInputNode&,
- const NGConstraintSpace&,
- const base::Optional<MinMaxSize>&);
+// Intrinsic size for replaced elements is computed as:
+// - |out_replaced_size| intrinsic size of the element. It might have no value.
+// - |out_aspect_ratio| only set if out_replaced_size is empty.
+// If out_replaced_size is not empty, that is the aspect ratio.
+// This routine will return one of the following:
+// - out_replaced_size, and no out_aspect_ratio
+// - out_aspect_ratio, and no out_replaced_size
+// - neither out_aspect_ratio, nor out_replaced_size
+// SVG elements can return any of the three options above.
+CORE_EXPORT void ComputeReplacedSize(
+ const NGLayoutInputNode&,
+ const NGConstraintSpace&,
+ const base::Optional<MinMaxSize>&,
+ base::Optional<LogicalSize>* out_replaced_size,
+ base::Optional<LogicalSize>* out_aspect_ratio);
// Based on available inline size, CSS computed column-width, CSS computed
// column-count and CSS used column-gap, return CSS used column-count.
@@ -475,4 +484,4 @@ base::Optional<MinMaxSize> CalculateMinMaxSizesIgnoringChildren(
} // namespace blink
-#endif // NGLengthUtils_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LENGTH_UTILS_H_
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 1e46d691f59..b438bd7bd55 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
@@ -111,6 +111,11 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
void NGOutOfFlowLayoutPart::Run(const LayoutBox* only_layout) {
Vector<NGLogicalOutOfFlowPositionedNode> candidates;
const LayoutObject* current_container = container_builder_->GetLayoutObject();
+ // If the container is display-locked, then we skip the layout of descendants,
+ // so we can early out immediately.
+ if (current_container->LayoutBlockedByDisplayLock(
+ DisplayLockLifecycleTarget::kChildren))
+ return;
container_builder_->SwapOutOfFlowPositionedCandidates(&candidates,
current_container);
@@ -565,9 +570,21 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
}
base::Optional<LogicalSize> replaced_size;
+ base::Optional<LogicalSize> replaced_aspect_ratio;
+ bool is_replaced_with_only_aspect_ratio = false;
if (is_replaced) {
- replaced_size =
- ComputeReplacedSize(node, candidate_constraint_space, min_max_size);
+ ComputeReplacedSize(node, candidate_constraint_space, min_max_size,
+ &replaced_size, &replaced_aspect_ratio);
+ is_replaced_with_only_aspect_ratio = !replaced_size &&
+ replaced_aspect_ratio &&
+ !replaced_aspect_ratio->IsEmpty();
+ // If we only have aspect ratio, and no replaced size, intrinsic size
+ // defaults to 300x150. min_max_size gets computed from the intrinsic size.
+ // We reset the min_max_size because spec says that OOF-positioned size
+ // should not be constrained by intrinsic size in this case.
+ // https://www.w3.org/TR/CSS22/visudet.html#inline-replaced-width
+ if (is_replaced_with_only_aspect_ratio)
+ min_max_size = MinMaxSize{LayoutUnit(), LayoutUnit::NearlyMax()};
} else if (should_be_considered_as_replaced) {
replaced_size =
LogicalSize{min_max_size->ShrinkToFit(
@@ -585,6 +602,17 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
if (!is_replaced && should_be_considered_as_replaced)
replaced_size.reset();
+ // Replaced elements with only aspect ratio compute their block size from
+ // inline size and aspect ratio.
+ // https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes
+ if (is_replaced_with_only_aspect_ratio) {
+ replaced_size = LogicalSize(
+ node_position.size.inline_size,
+ (replaced_aspect_ratio->block_size *
+ ((node_position.size.inline_size - border_padding.InlineSum()) /
+ replaced_aspect_ratio->inline_size)) +
+ border_padding.BlockSum());
+ }
if (AbsoluteNeedsChildBlockSize(candidate_style)) {
layout_result =
GenerateFragment(node, container_content_size_in_candidate_writing_mode,
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 dc32c3e1d40..0564516d49c 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
@@ -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 NGOutOfFlowLayoutPart_h
-#define NGOutOfFlowLayoutPart_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
#include "third_party/blink/renderer/core/core_export.h"
@@ -135,4 +135,4 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc
index 4e3ceb48b1e..2562c733766 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc
@@ -5,12 +5,11 @@
#include "third_party/blink/renderer/core/layout/ng/ng_outline_utils.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
-#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
-
bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style,
const Node* node) {
if (!style.HasOutline() || style.Visibility() != EVisibility::kVisible)
@@ -21,22 +20,24 @@ bool NGOutlineUtils::HasPaintedOutline(const ComputedStyle& style,
return true;
}
-bool NGOutlineUtils::IsInlineOutlineNonpaintingFragment(
- const NGPhysicalFragment& physical_fragment) {
+bool NGOutlineUtils::ShouldPaintOutline(
+ const NGPhysicalBoxFragment& physical_fragment) {
const LayoutObject* layout_object = physical_fragment.GetLayoutObject();
- if (!layout_object)
- return false;
+ DCHECK(layout_object);
if (!layout_object->IsLayoutInline())
- return false;
+ return true;
+
+ // A |LayoutInline| can be split across multiple objects. The first fragment
+ // produced should paint the outline for *all* fragments.
if (layout_object->IsElementContinuation()) {
- // If continuation root did generate a fragment,
- // this fragment should not paint.
+ // If the |LayoutInline|'s continuation-root generated a fragment, we
+ // shouldn't paint the outline.
if (layout_object->ContinuationRoot()->FirstInlineFragment())
- return true;
+ return false;
}
- if (!layout_object->FirstInlineFragment())
- return false;
- return &layout_object->FirstInlineFragment()->PhysicalFragment() !=
+
+ DCHECK(layout_object->FirstInlineFragment());
+ return &layout_object->FirstInlineFragment()->PhysicalFragment() ==
&physical_fragment;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.h
index 09107f93607..39d3852b796 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_outline_utils.h
@@ -12,19 +12,19 @@ namespace blink {
class ComputedStyle;
class Node;
-class NGPhysicalFragment;
+class NGPhysicalBoxFragment;
class CORE_EXPORT NGOutlineUtils {
STATIC_ONLY(NGOutlineUtils);
public:
-
static bool HasPaintedOutline(const ComputedStyle& style, const Node* node);
- // First fragment paints the entire outline for LayoutInline.
- // Returns true if this is the painting fragment.
- static bool IsInlineOutlineNonpaintingFragment(
- const NGPhysicalFragment& physical_fragment);
+ // Returns true if this fragment should paint an outline.
+ //
+ // Specifically a |LayoutInline| can be split across multiple flows. The
+ // first fragment produced should paint the outline for *all* fragments.
+ static bool ShouldPaintOutline(const NGPhysicalBoxFragment&);
};
} // namespace blink
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 b630a5ab612..21ab11cf7b5 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
@@ -103,7 +103,6 @@ NGConstraintSpace NGPageLayoutAlgorithm::CreateConstraintSpaceForPages(
// TODO(mstensho): Handle auto block size.
space_builder.SetFragmentationType(kFragmentPage);
space_builder.SetFragmentainerBlockSize(page_size.block_size);
- space_builder.SetFragmentainerSpaceAtBfcStart(page_size.block_size);
space_builder.SetIsAnonymous(true);
return space_builder.ToConstraintSpace();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
index 8491eaa198e..f05b8a8d717 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
@@ -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 NGPageLayoutAlgorithm_h
-#define NGPageLayoutAlgorithm_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PAGE_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PAGE_LAYOUT_ALGORITHM_H_
#include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h"
@@ -38,4 +38,4 @@ class CORE_EXPORT NGPageLayoutAlgorithm
} // namespace blink
-#endif // NGPageLayoutAlgorithm_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PAGE_LAYOUT_ALGORITHM_H_
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 898d05f4b27..df53440870d 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
@@ -190,12 +190,13 @@ PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const {
ink_overflow.Expand(style.BoxDecorationOutsets());
if (NGOutlineUtils::HasPaintedOutline(style,
GetLayoutObject()->GetNode()) &&
- !NGOutlineUtils::IsInlineOutlineNonpaintingFragment(*this)) {
+ NGOutlineUtils::ShouldPaintOutline(*this)) {
Vector<PhysicalRect> outline_rects;
// The result rects are in coordinates of this object's border box.
AddSelfOutlineRects(
- &outline_rects, PhysicalOffset(),
- GetLayoutObject()->OutlineRectsShouldIncludeBlockVisualOverflow());
+ PhysicalOffset(),
+ GetLayoutObject()->OutlineRectsShouldIncludeBlockVisualOverflow(),
+ &outline_rects);
PhysicalRect rect = UnionRectEvenIfEmpty(outline_rects);
rect.Inflate(LayoutUnit(style.OutlineOutsetExtent()));
ink_overflow.Unite(rect);
@@ -205,11 +206,11 @@ PhysicalRect NGPhysicalBoxFragment::ComputeSelfInkOverflow() const {
}
void NGPhysicalBoxFragment::AddSelfOutlineRects(
- Vector<PhysicalRect>* outline_rects,
const PhysicalOffset& additional_offset,
- NGOutlineType outline_type) const {
- // TODO(kojii): Needs inline_element_continuation logic from
- // LayoutBlockFlow::AddOutlineRects?
+ NGOutlineType outline_type,
+ Vector<PhysicalRect>* outline_rects) const {
+ if (!NGOutlineUtils::ShouldPaintOutline(*this))
+ return;
const LayoutObject* layout_object = GetLayoutObject();
DCHECK(layout_object);
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 6539b5bad70..6bb45d5aba3 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
@@ -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 NGPhysicalBoxFragment_h
-#define NGPhysicalBoxFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
@@ -81,9 +81,9 @@ class CORE_EXPORT NGPhysicalBoxFragment final
// Fragment offset is this fragment's offset from parent.
// Needed to compensate for LayoutInline Legacy code offsets.
- void AddSelfOutlineRects(Vector<PhysicalRect>* outline_rects,
- const PhysicalOffset& additional_offset,
- NGOutlineType include_block_overflows) const;
+ void AddSelfOutlineRects(const PhysicalOffset& additional_offset,
+ NGOutlineType include_block_overflows,
+ Vector<PhysicalRect>* outline_rects) const;
UBiDiLevel BidiLevel() const;
@@ -140,4 +140,4 @@ struct DowncastTraits<NGPhysicalBoxFragment> {
} // namespace blink
-#endif // NGPhysicalBoxFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
index 4eb0b4413be..f418fabb5cd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
@@ -131,8 +131,8 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
// may have transforms and so we have to go through LocalToAncestorRects?
if (descendant_box->HasLayer()) {
Vector<PhysicalRect> layer_outline_rects;
- descendant_box->AddSelfOutlineRects(&layer_outline_rects,
- PhysicalOffset(), outline_type);
+ descendant_box->AddSelfOutlineRects(PhysicalOffset(), outline_type,
+ &layer_outline_rects);
// Don't pass additional_offset because LocalToAncestorRects will itself
// apply it.
@@ -145,7 +145,7 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
if (descendant_layout_object->IsBox()) {
descendant_box->AddSelfOutlineRects(
- outline_rects, additional_offset + descendant.Offset(), outline_type);
+ additional_offset + descendant.Offset(), outline_type, outline_rects);
return;
}
@@ -158,7 +158,7 @@ void NGPhysicalContainerFragment::AddOutlineRectsForDescendant(
// for its line box which cover the line boxes of this LayoutInline. So
// the LayoutInline needs to add rects for children and continuations
// only.
- if (!NGOutlineUtils::IsInlineOutlineNonpaintingFragment(*descendant)) {
+ if (NGOutlineUtils::ShouldPaintOutline(*descendant_box)) {
descendant_layout_inline->AddOutlineRectsForChildrenAndContinuations(
*outline_rects, additional_offset, outline_type);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
index b76a86307cb..86f35a55028 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h
@@ -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 NGPhysicalContainerFragment_h
-#define NGPhysicalContainerFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
#include "base/containers/span.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -179,4 +179,4 @@ struct DowncastTraits<NGPhysicalContainerFragment> {
} // namespace blink
-#endif // NGPhysicalContainerFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_CONTAINER_FRAGMENT_H_
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 02d099f6eda..271350d41a2 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
@@ -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 NGPhysicalFragment_h
-#define NGPhysicalFragment_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -323,7 +323,6 @@ class CORE_EXPORT NGPhysicalFragment
// The following bitfields are only to be used by NGPhysicalTextFragment
// (it's defined here to save memory, since that class has no bitfields).
- unsigned line_orientation_ : 2; // NGLineOrientation
unsigned is_generated_text_ : 1;
mutable unsigned ink_overflow_computed_ : 1;
@@ -352,4 +351,4 @@ inline void NGPhysicalFragment::CheckCanUpdateInkOverflow() const {}
} // namespace blink
-#endif // NGPhysicalFragment_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
index 72c6eadc9af..e24bf5b2c18 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_positioned_float.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 NGPositionedFloat_h
-#define NGPositionedFloat_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_POSITIONED_FLOAT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_POSITIONED_FLOAT_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -30,4 +30,4 @@ struct CORE_EXPORT NGPositionedFloat {
} // namespace blink
-#endif // NGPositionedFloat_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_POSITIONED_FLOAT_H_
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 5c2ce9d5015..e15d55630a3 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
@@ -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 NGRelativeUtils_h
-#define NGRelativeUtils_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_RELATIVE_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_RELATIVE_UTILS_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
@@ -25,4 +25,4 @@ ComputeRelativeOffset(const ComputedStyle& child_style,
} // namespace blink
-#endif // NGRelativeUtils_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_RELATIVE_UTILS_H_
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 90f3adb0432..af96da0cb51 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
@@ -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 NGSpaceUtils_h
-#define NGSpaceUtils_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_SPACE_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_SPACE_UTILS_H_
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
@@ -44,4 +44,4 @@ void SetOrthogonalFallbackInlineSizeIfNeeded(const ComputedStyle& parent_style,
} // namespace blink
-#endif // NGSpaceUtils_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_SPACE_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
index 559bef22a49..13a027e0b88 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_baseline.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
@@ -16,7 +16,7 @@ int NGTextDecorationOffset::ComputeUnderlineOffsetForUnder(
float text_decoration_thickness,
FontVerticalPositionType position_type) const {
LayoutUnit offset = LayoutUnit::Max();
- const ComputedStyle& style = text_fragment_.Style();
+ const ComputedStyle& style = text_style_;
FontBaseline baseline_type = style.GetFontBaseline();
if (decorating_box_) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
index 68f45a41e8f..057705e141c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
@@ -12,7 +12,6 @@ namespace blink {
class ComputedStyle;
class NGPhysicalBoxFragment;
-class NGPhysicalTextFragment;
// Class for computing the decoration offset for text fragments in LayoutNG.
class CORE_EXPORT NGTextDecorationOffset : public TextDecorationOffsetBase {
@@ -20,10 +19,10 @@ class CORE_EXPORT NGTextDecorationOffset : public TextDecorationOffsetBase {
public:
NGTextDecorationOffset(const ComputedStyle& style,
- const NGPhysicalTextFragment& text_fragment,
+ const ComputedStyle& text_style,
const NGPhysicalBoxFragment* decorating_box)
: TextDecorationOffsetBase(style),
- text_fragment_(text_fragment),
+ text_style_(text_style),
decorating_box_(decorating_box) {}
~NGTextDecorationOffset() = default;
@@ -31,7 +30,7 @@ class CORE_EXPORT NGTextDecorationOffset : public TextDecorationOffsetBase {
FontVerticalPositionType) const override;
private:
- const NGPhysicalTextFragment& text_fragment_;
+ const ComputedStyle& text_style_;
const NGPhysicalBoxFragment* decorating_box_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
index b0148f5b485..ce5d0b97ae6 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.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 NGUnpositionedFloat_h
-#define NGUnpositionedFloat_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_UNPOSITIONED_FLOAT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_UNPOSITIONED_FLOAT_H_
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
@@ -53,4 +53,4 @@ struct CORE_EXPORT NGUnpositionedFloat final {
} // namespace blink
-#endif // NGUnpositionedFloat_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_UNPOSITIONED_FLOAT_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/order_iterator.cc b/chromium/third_party/blink/renderer/core/layout/order_iterator.cc
index 54b62fa59f5..82f203390e3 100644
--- a/chromium/third_party/blink/renderer/core/layout/order_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/layout/order_iterator.cc
@@ -73,10 +73,8 @@ void OrderIterator::Reset() {
}
int OrderIterator::ResolvedOrder(const LayoutBox& child) const {
- if (container_box_->StyleRef().Display() == EDisplay::kWebkitBox ||
- container_box_->StyleRef().Display() == EDisplay::kWebkitInlineBox) {
+ if (container_box_->StyleRef().IsDeprecatedWebkitBox())
return child.StyleRef().BoxOrdinalGroup();
- }
return child.StyleRef().Order();
}
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 dacbc3ca71a..72ca0a65364 100644
--- a/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scrollbars_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/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
@@ -18,7 +17,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/layout_scrollbar_part.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"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -163,8 +162,6 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
void SetUp() override {
ScrollbarsTest::SetUp();
WebView().Scheduler()->EnableVirtualTime();
- scoped_feature_list_.InitAndEnableFeature(
- features::kScrollbarInjectScrollGestures);
}
void TearDown() override {
@@ -195,9 +192,6 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
delay);
test::EnterRunLoop();
}
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(ScrollbarsTest, DocumentStyleRecalcPreservesScrollbars) {
@@ -1430,11 +1424,8 @@ class ScrollbarAppearanceTest
void SetUp() override {
SimTest::SetUp();
// Use real scrollbars to ensure we're testing the real ScrollbarThemes.
- // TODO(bokan): For some reason this has to happen *after* the WebViewImpl
- // loads and everything or the test fails. But not doing it also fails.
- // However this changes a runtime feature and should go *before* anything
- // is set up!! Otherwise blink sees inconsistent values which doesn't happen
- // in reality.
+ // This is after SimTest::SetUp() to override the mock scrollbar settings
+ // initialized there.
mock_scrollbars_ =
std::make_unique<UseMockScrollbarSettings>(false, GetParam());
}
@@ -2501,6 +2492,58 @@ TEST_F(ScrollbarsTest, UseCounterPositiveWhenThumbIsScrolledWithTouch) {
WebFeature::kHorizontalScrollbarThumbScrollingWithTouch));
}
+TEST_F(ScrollbarsTest, CheckScrollCornerIfThereIsNoScrollbar) {
+ WebView().MainFrameWidget()->Resize(WebSize(200, 200));
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 50px;
+ height: 100px;
+ overflow-x: auto;
+ }
+ #content {
+ width: 75px;
+ height: 50px;
+ background-color: green;
+ }
+ #container::-webkit-scrollbar {
+ height: 8px;
+ width: 8px;
+ }
+ #container::-webkit-scrollbar-corner {
+ background: transparent;
+ }
+ </style>
+ <div id='container'>
+ <div id='content'></div>
+ </div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ // This test is specifically checking the behavior when overlay scrollbars
+ // are enabled.
+ DCHECK(GetScrollbarTheme().UsesOverlayScrollbars());
+
+ auto* element = GetDocument().getElementById("container");
+ PaintLayerScrollableArea* scrollable_container =
+ ToLayoutBox(element->GetLayoutObject())->GetScrollableArea();
+
+ // There should initially be a scrollbar and a scroll corner.
+ EXPECT_TRUE(scrollable_container->HasScrollbar());
+ EXPECT_TRUE(scrollable_container->ScrollCorner());
+
+ // Make the container non-scrollable so the scrollbar and corner disappear.
+ element->setAttribute(html_names::kStyleAttr, "width: 100px;");
+ GetDocument().UpdateStyleAndLayout();
+
+ EXPECT_FALSE(scrollable_container->HasScrollbar());
+ EXPECT_FALSE(scrollable_container->ScrollCorner());
+}
+
// For infinite scrolling page (load more content when scroll to bottom), user
// press on scrollbar button should keep scrolling after content loaded.
// Disable on Android since VirtualTime not work for Android.
@@ -2617,20 +2660,20 @@ class ScrollbarTrackMarginsTest : public ScrollbarsTest {
ToLayoutBox(div->GetLayoutObject())->GetScrollableArea();
ASSERT_TRUE(div_scrollable->HorizontalScrollbar());
- LayoutScrollbar* horizontal_scrollbar =
- To<LayoutScrollbar>(div_scrollable->HorizontalScrollbar());
+ CustomScrollbar* horizontal_scrollbar =
+ To<CustomScrollbar>(div_scrollable->HorizontalScrollbar());
horizontal_track_ = horizontal_scrollbar->GetPart(kTrackBGPart);
ASSERT_TRUE(horizontal_track_);
ASSERT_TRUE(div_scrollable->VerticalScrollbar());
- LayoutScrollbar* vertical_scrollbar =
- To<LayoutScrollbar>(div_scrollable->VerticalScrollbar());
+ CustomScrollbar* vertical_scrollbar =
+ To<CustomScrollbar>(div_scrollable->VerticalScrollbar());
vertical_track_ = vertical_scrollbar->GetPart(kTrackBGPart);
ASSERT_TRUE(vertical_track_);
}
- LayoutScrollbarPart* horizontal_track_ = nullptr;
- LayoutScrollbarPart* vertical_track_ = nullptr;
+ LayoutCustomScrollbarPart* horizontal_track_ = nullptr;
+ LayoutCustomScrollbarPart* vertical_track_ = nullptr;
};
TEST_F(ScrollbarTrackMarginsTest,
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/BUILD.gn b/chromium/third_party/blink/renderer/core/layout/svg/BUILD.gn
index 8d013890a44..d8e784c99a7 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/layout/svg/BUILD.gn
@@ -91,6 +91,8 @@ blink_core_sources("svg_layout") {
"svg_text_metrics.h",
"svg_text_query.cc",
"svg_text_query.h",
+ "transform_helper.cc",
+ "transform_helper.h",
"transformed_hit_test_location.cc",
"transformed_hit_test_location.h",
]
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
index a1cc725f281..c9085ba3376 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -28,6 +28,7 @@
#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/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
#include "third_party/blink/renderer/core/paint/svg_container_painter.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
index 9e472948d77..6f005867573 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
@@ -34,6 +34,7 @@
#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/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
#include "third_party/blink/renderer/core/paint/svg_image_painter.h"
@@ -47,12 +48,20 @@ LayoutSVGImage::LayoutSVGImage(SVGImageElement* impl)
: LayoutSVGModelObject(impl),
needs_boundaries_update_(true),
needs_transform_update_(true),
+ transform_uses_reference_box_(false),
image_resource_(MakeGarbageCollected<LayoutImageResource>()) {
image_resource_->Initialize(this);
}
LayoutSVGImage::~LayoutSVGImage() = default;
+void LayoutSVGImage::StyleDidChange(StyleDifference diff,
+ const ComputedStyle* old_style) {
+ transform_uses_reference_box_ =
+ TransformHelper::DependsOnReferenceBox(StyleRef());
+ LayoutSVGModelObject::StyleDidChange(diff, old_style);
+}
+
void LayoutSVGImage::WillBeDestroyed() {
image_resource_->Shutdown();
@@ -132,17 +141,11 @@ void LayoutSVGImage::UpdateLayout() {
if (EverHadLayout() && SelfNeedsLayout())
SVGResourcesCache::ClientLayoutChanged(*this);
- UpdateBoundingBox();
+ FloatPoint old_bbox_location = object_bounding_box_.Location();
+ bool bbox_changed = UpdateBoundingBox() ||
+ old_bbox_location != object_bounding_box_.Location();
bool update_parent_boundaries = false;
- if (needs_transform_update_) {
- local_transform_ =
- ToSVGImageElement(GetElement())
- ->CalculateTransform(SVGElement::kIncludeMotionTransform);
- needs_transform_update_ = false;
- update_parent_boundaries = true;
- }
-
if (needs_boundaries_update_) {
local_visual_rect_ = object_bounding_box_;
SVGLayoutSupport::AdjustVisualRectWithResources(*this, object_bounding_box_,
@@ -151,6 +154,18 @@ void LayoutSVGImage::UpdateLayout() {
update_parent_boundaries = true;
}
+ if (!needs_transform_update_ && transform_uses_reference_box_) {
+ needs_transform_update_ = CheckForImplicitTransformChange(bbox_changed);
+ if (needs_transform_update_)
+ SetNeedsPaintPropertyUpdate();
+ }
+
+ if (needs_transform_update_) {
+ local_transform_ = CalculateLocalTransform();
+ needs_transform_update_ = false;
+ update_parent_boundaries = true;
+ }
+
// If our bounds changed, notify the parents.
if (update_parent_boundaries)
LayoutSVGModelObject::SetNeedsBoundariesUpdate();
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
index b28f212dce2..a56500db2f8 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
@@ -57,6 +57,7 @@ class LayoutSVGImage final : public LayoutSVGModelObject {
const char* GetName() const override { return "LayoutSVGImage"; }
protected:
+ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void WillBeDestroyed() override;
private:
@@ -83,6 +84,7 @@ class LayoutSVGImage final : public LayoutSVGModelObject {
bool needs_boundaries_update_ : 1;
bool needs_transform_update_ : 1;
+ bool transform_uses_reference_box_ : 1;
AffineTransform local_transform_;
FloatRect object_bounding_box_;
Persistent<LayoutImageResource> image_resource_;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index e578f5d15c5..484600026e7 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -97,6 +97,27 @@ void LayoutSVGModelObject::WillBeDestroyed() {
LayoutObject::WillBeDestroyed();
}
+AffineTransform LayoutSVGModelObject::CalculateLocalTransform() const {
+ auto* element = GetElement();
+ if (element->HasTransform(SVGElement::kIncludeMotionTransform))
+ return element->CalculateTransform(SVGElement::kIncludeMotionTransform);
+ return AffineTransform();
+}
+
+bool LayoutSVGModelObject::CheckForImplicitTransformChange(
+ bool bbox_changed) const {
+ // If the transform is relative to the reference box, check relevant
+ // conditions to see if we need to recompute the transform.
+ switch (StyleRef().TransformBox()) {
+ case ETransformBox::kViewBox:
+ return SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
+ case ETransformBox::kFillBox:
+ return bbox_changed;
+ }
+ NOTREACHED();
+ return false;
+}
+
void LayoutSVGModelObject::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
// Since layout depends on the bounds of the filter, we need to force layout
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
index ab5ee1f021d..9118a3f7214 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -80,6 +80,9 @@ class LayoutSVGModelObject : public LayoutObject {
protected:
void WillBeDestroyed() override;
+ AffineTransform CalculateLocalTransform() const;
+ bool CheckForImplicitTransformChange(bool bbox_changed) const;
+
private:
// LayoutSVGModelObject subclasses should use GetElement() instead.
void GetNode() const = delete;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
index 659ee171c0f..498d5d33b68 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -22,7 +22,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h"
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
namespace blink {
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 3cb465412f9..cdaf946a8cd 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
@@ -35,6 +35,7 @@
#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/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/svg_root_painter.h"
@@ -95,7 +96,7 @@ void LayoutSVGRoot::UnscaledIntrinsicSizingInfo(
void LayoutSVGRoot::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
- DCHECK(!ShouldApplySizeContainment() && !DisplayLockInducesSizeContainment());
+ DCHECK(!ShouldApplySizeContainment());
UnscaledIntrinsicSizingInfo(intrinsic_sizing_info);
intrinsic_sizing_info.size.Scale(StyleRef().EffectiveZoom());
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 4418ac862ac..6286842b095 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
@@ -35,6 +35,7 @@
#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/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/layout/svg/transformed_hit_test_location.h"
#include "third_party/blink/renderer/core/paint/svg_shape_painter.h"
#include "third_party/blink/renderer/core/svg/svg_geometry_element.h"
@@ -58,14 +59,14 @@ LayoutSVGShape::LayoutSVGShape(SVGGeometryElement* node,
// Default is true, so we grab a AffineTransform object once from
// SVGGeometryElement.
needs_transform_update_(true),
- // Default to false, since |needs_transform_update_| is true this will be
- // updated the first time transforms are updated.
transform_uses_reference_box_(false) {}
LayoutSVGShape::~LayoutSVGShape() = default;
void LayoutSVGShape::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
+ transform_uses_reference_box_ =
+ TransformHelper::DependsOnReferenceBox(StyleRef());
LayoutSVGModelObject::StyleDidChange(diff, old_style);
SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef());
}
@@ -94,7 +95,7 @@ void LayoutSVGShape::UpdateShapeFromElement() {
if (HasNonScalingStroke()) {
// NonScalingStrokeTransform may depend on LocalTransform which in turn may
// depend on ObjectBoundingBox, thus we need to call them in this order.
- UpdateLocalTransform();
+ local_transform_ = CalculateLocalTransform();
UpdateNonScalingStrokeData();
}
@@ -209,42 +210,6 @@ bool LayoutSVGShape::StrokeContains(const HitTestLocation& location,
return ShapeDependentStrokeContains(location);
}
-static inline bool TransformOriginIsFixed(const ComputedStyle& style) {
- // If the transform box is view-box and the transform origin is absolute, then
- // is does not depend on the reference box. For fill-box, the origin will
- // always move with the bounding box.
- return style.TransformBox() == ETransformBox::kViewBox &&
- style.TransformOriginX().IsFixed() &&
- style.TransformOriginY().IsFixed();
-}
-
-static inline bool TransformDependsOnReferenceBox(const ComputedStyle& style) {
- // We're passing kExcludeMotionPath here because we're checking that
- // explicitly later.
- if (!TransformOriginIsFixed(style) &&
- style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
- ComputedStyle::kExcludeMotionPath))
- return true;
- if (style.Transform().DependsOnBoxSize())
- return true;
- if (style.Translate() && style.Translate()->DependsOnBoxSize())
- return true;
- if (style.HasOffset())
- return true;
- return false;
-}
-
-bool LayoutSVGShape::UpdateLocalTransform() {
- auto* graphics_element = To<SVGGraphicsElement>(GetElement());
- if (graphics_element->HasTransform(SVGElement::kIncludeMotionTransform)) {
- local_transform_.SetTransform(graphics_element->CalculateTransform(
- SVGElement::kIncludeMotionTransform));
- return TransformDependsOnReferenceBox(StyleRef());
- }
- local_transform_ = AffineTransform();
- return false;
-}
-
void LayoutSVGShape::UpdateLayout() {
LayoutAnalyzer::Scope analyzer(*this);
@@ -278,24 +243,14 @@ void LayoutSVGShape::UpdateLayout() {
update_parent_boundaries = true;
}
- // If the transform is relative to the reference box, check relevant
- // conditions to see if we need to recompute the transform.
if (!needs_transform_update_ && transform_uses_reference_box_) {
- switch (StyleRef().TransformBox()) {
- case ETransformBox::kViewBox:
- needs_transform_update_ =
- SVGLayoutSupport::LayoutSizeOfNearestViewportChanged(this);
- break;
- case ETransformBox::kFillBox:
- needs_transform_update_ = bbox_changed;
- break;
- }
+ needs_transform_update_ = CheckForImplicitTransformChange(bbox_changed);
if (needs_transform_update_)
SetNeedsPaintPropertyUpdate();
}
if (needs_transform_update_) {
- transform_uses_reference_box_ = UpdateLocalTransform();
+ local_transform_ = CalculateLocalTransform();
needs_transform_update_ = false;
update_parent_boundaries = true;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
index b2563c7a1b8..1b11df34d50 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -179,7 +179,6 @@ class LayoutSVGShape : public LayoutSVGModelObject {
FloatRect ApproximateStrokeBoundingBox(const FloatRect& shape_bounds) const;
FloatRect CalculateNonScalingStrokeBoundingBox() const;
void UpdateNonScalingStrokeData();
- bool UpdateLocalTransform();
private:
AffineTransform local_transform_;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
index 92f8d554867..391b8dcea99 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
@@ -21,7 +21,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h"
-#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/svg/svg_g_element.h"
#include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
#include "third_party/blink/renderer/core/svg/svg_use_element.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
index 7e4fc9e0c0f..544fa6ec42c 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
index 632ab791244..28e90498d56 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
@@ -21,6 +21,9 @@
#include "third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h"
+#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/core/editing/markers/text_marker_base.h"
+#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_svg_inline_text.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/pointer_events_hit_rules.h"
@@ -237,24 +240,22 @@ void SVGInlineTextBox::PaintDocumentMarker(GraphicsContext&,
// spellchecking, etc).
}
-void SVGInlineTextBox::PaintTextMatchMarkerForeground(
- const PaintInfo& paint_info,
- const LayoutPoint& point,
- const TextMatchMarker& marker,
- const ComputedStyle& style,
- const Font& font) const {
- SVGInlineTextBoxPainter(*this).PaintTextMatchMarkerForeground(
- paint_info, point, marker, style, font);
+void SVGInlineTextBox::PaintTextMarkerForeground(const PaintInfo& paint_info,
+ const LayoutPoint& point,
+ const TextMarkerBase& marker,
+ const ComputedStyle& style,
+ const Font& font) const {
+ SVGInlineTextBoxPainter(*this).PaintTextMarkerForeground(paint_info, point,
+ marker, style, font);
}
-void SVGInlineTextBox::PaintTextMatchMarkerBackground(
- const PaintInfo& paint_info,
- const LayoutPoint& point,
- const TextMatchMarker& marker,
- const ComputedStyle& style,
- const Font& font) const {
- SVGInlineTextBoxPainter(*this).PaintTextMatchMarkerBackground(
- paint_info, point, marker, style, font);
+void SVGInlineTextBox::PaintTextMarkerBackground(const PaintInfo& paint_info,
+ const LayoutPoint& point,
+ const TextMarkerBase& marker,
+ const ComputedStyle& style,
+ const Font& font) const {
+ SVGInlineTextBoxPainter(*this).PaintTextMarkerBackground(paint_info, point,
+ marker, style, font);
}
FloatRect SVGInlineTextBox::CalculateBoundaries() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
index e2fd77f4ddc..3ce95efaac1 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
@@ -27,7 +27,7 @@
namespace blink {
-class TextMatchMarker;
+class TextMarkerBase;
class SVGInlineTextBox final : public InlineTextBox {
public:
@@ -86,16 +86,16 @@ class SVGInlineTextBox final : public InlineTextBox {
const ComputedStyle&,
const Font&,
bool) const final;
- void PaintTextMatchMarkerForeground(const PaintInfo&,
- const LayoutPoint&,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&) const final;
- void PaintTextMatchMarkerBackground(const PaintInfo&,
- const LayoutPoint&,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&) const final;
+ void PaintTextMarkerForeground(const PaintInfo&,
+ const LayoutPoint&,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&) const final;
+ void PaintTextMarkerBackground(const PaintInfo&,
+ const LayoutPoint&,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&) const final;
bool HitTestFragments(const HitTestLocation& hit_test_location) const;
bool NodeAtPoint(HitTestResult&,
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 249f9fa383c..92b33e48eb6 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
@@ -178,41 +178,6 @@ class SubtreeContentTransformScope {
AffineTransform saved_content_transformation_;
};
-// The following enumeration is used to optimize cases where the scale is known
-// to be invariant (see: LayoutSVGContainer::layout and LayoutSVGroot). The
-// value 'Full' can be used in the general case when the scale change is
-// unknown, or known to change.
-enum class SVGTransformChange {
- kNone,
- kScaleInvariant,
- kFull,
-};
-
-// Helper for computing ("classifying") a change to a transform using the
-// categoies defined above.
-class SVGTransformChangeDetector {
- STACK_ALLOCATED();
-
- public:
- explicit SVGTransformChangeDetector(const AffineTransform& previous)
- : previous_transform_(previous) {}
-
- SVGTransformChange ComputeChange(const AffineTransform& current) {
- if (previous_transform_ == current)
- return SVGTransformChange::kNone;
- if (ScaleReference(previous_transform_) == ScaleReference(current))
- return SVGTransformChange::kScaleInvariant;
- return SVGTransformChange::kFull;
- }
-
- private:
- static std::pair<double, double> ScaleReference(
- const AffineTransform& transform) {
- return std::make_pair(transform.XScaleSquared(), transform.YScaleSquared());
- }
- AffineTransform previous_transform_;
-};
-
template <typename LayoutObjectType>
bool SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(
const LayoutObjectType* object) {
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 83ad1b140c5..cfbf2ca4a1e 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
@@ -369,7 +369,8 @@ void SVGTextLayoutEngine::LayoutTextOnLineOrPath(
const Font& font = style.GetFont();
SVGTextLayoutEngineSpacing spacing_layout(font, style.EffectiveZoom());
- SVGTextLayoutEngineBaseline baseline_layout(font, style.EffectiveZoom());
+ SVGTextLayoutEngineBaseline baseline_layout(text_line_layout.ScaledFont(),
+ text_line_layout.ScalingFactor());
bool did_start_text_fragment = false;
bool apply_spacing_to_next_character = false;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.cc b/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.cc
new file mode 100644
index 00000000000..8e8e374fa1f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.cc
@@ -0,0 +1,95 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
+
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/core/svg/svg_length_context.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/instrumentation/use_counter.h"
+
+namespace blink {
+
+static inline bool TransformOriginIsFixed(const ComputedStyle& style) {
+ // If the transform box is view-box and the transform origin is absolute,
+ // then is does not depend on the reference box. For fill-box, the origin
+ // will always move with the bounding box.
+ return style.TransformBox() == ETransformBox::kViewBox &&
+ style.TransformOriginX().IsFixed() &&
+ style.TransformOriginY().IsFixed();
+}
+
+bool TransformHelper::DependsOnReferenceBox(const ComputedStyle& style) {
+ // We're passing kExcludeMotionPath here because we're checking that
+ // explicitly later.
+ if (!TransformOriginIsFixed(style) &&
+ style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
+ ComputedStyle::kExcludeMotionPath))
+ return true;
+ if (style.Transform().DependsOnBoxSize())
+ return true;
+ if (style.Translate() && style.Translate()->DependsOnBoxSize())
+ return true;
+ if (style.HasOffset())
+ return true;
+ return false;
+}
+
+FloatRect TransformHelper::ComputeReferenceBox(
+ const LayoutObject& layout_object) {
+ const ComputedStyle& style = layout_object.StyleRef();
+ FloatRect reference_box;
+ if (style.TransformBox() == ETransformBox::kFillBox) {
+ reference_box = layout_object.ObjectBoundingBox();
+ } else {
+ DCHECK_EQ(style.TransformBox(), ETransformBox::kViewBox);
+ SVGLengthContext length_context(
+ DynamicTo<SVGElement>(layout_object.GetNode()));
+ FloatSize viewport_size;
+ length_context.DetermineViewport(viewport_size);
+ reference_box.SetSize(viewport_size);
+ }
+ const float zoom = style.EffectiveZoom();
+ if (zoom != 1)
+ reference_box.Scale(zoom);
+ return reference_box;
+}
+
+AffineTransform TransformHelper::ComputeTransform(
+ const LayoutObject& layout_object) {
+ const ComputedStyle& style = layout_object.StyleRef();
+ if (DependsOnReferenceBox(style)) {
+ UseCounter::Count(layout_object.GetDocument(),
+ WebFeature::kTransformUsesBoxSizeOnSVG);
+ }
+
+ // CSS transforms operate with pre-scaled lengths. To make this work with SVG
+ // (which applies the zoom factor globally, at the root level) we
+ //
+ // * pre-scale the reference box (to bring it into the same space as the
+ // other CSS values) (Handled by ComputeSVGTransformReferenceBox)
+ // * invert the zoom factor (to effectively compute the CSS transform under
+ // a 1.0 zoom)
+ //
+ // Note: objectBoundingBox is an empty rect for elements like pattern or
+ // clipPath. See
+ // https://svgwg.org/svg2-draft/coords.html#ObjectBoundingBoxUnits
+ TransformationMatrix transform;
+ FloatRect reference_box = ComputeReferenceBox(layout_object);
+ style.ApplyTransform(transform, reference_box,
+ ComputedStyle::kIncludeTransformOrigin,
+ ComputedStyle::kIncludeMotionPath,
+ ComputedStyle::kIncludeIndependentTransformProperties);
+ const float zoom = style.EffectiveZoom();
+ if (zoom != 1)
+ transform.Zoom(1 / zoom);
+ // Flatten any 3D transform.
+ return transform.ToAffineTransform();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.h b/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.h
new file mode 100644
index 00000000000..4423a05afe4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/svg/transform_helper.h
@@ -0,0 +1,71 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
+
+#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class ComputedStyle;
+class FloatRect;
+class LayoutObject;
+
+class TransformHelper {
+ STATIC_ONLY(TransformHelper);
+
+ public:
+ // Returns true if the passed in ComputedStyle has a transform that needs to
+ // resolve against the reference box.
+ static bool DependsOnReferenceBox(const ComputedStyle&);
+
+ // Computes the reference box for the LayoutObject based on the
+ // 'transform-box'. Applies zoom if needed.
+ static FloatRect ComputeReferenceBox(const LayoutObject&);
+
+ // Compute the transform for the LayoutObject based on the various
+ // 'transform*' properties.
+ static AffineTransform ComputeTransform(const LayoutObject&);
+};
+
+// The following enumeration is used to optimize cases where the scale is known
+// to be invariant (see: LayoutSVGContainer::UpdateLayout and
+// LayoutSVGRoot). The value 'Full' can be used in the general case when the
+// scale change is unknown, or known to have changed.
+enum class SVGTransformChange {
+ kNone,
+ kScaleInvariant,
+ kFull,
+};
+
+// Helper for computing ("classifying") a change to a transform using the
+// categories defined above.
+class SVGTransformChangeDetector {
+ STACK_ALLOCATED();
+
+ public:
+ explicit SVGTransformChangeDetector(const AffineTransform& previous)
+ : previous_transform_(previous) {}
+
+ SVGTransformChange ComputeChange(const AffineTransform& current) {
+ if (previous_transform_ == current)
+ return SVGTransformChange::kNone;
+ if (ScaleReference(previous_transform_) == ScaleReference(current))
+ return SVGTransformChange::kScaleInvariant;
+ return SVGTransformChange::kFull;
+ }
+
+ private:
+ static std::pair<double, double> ScaleReference(
+ const AffineTransform& transform) {
+ return std::make_pair(transform.XScaleSquared(), transform.YScaleSquared());
+ }
+ AffineTransform previous_transform_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_SVG_TRANSFORM_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
index f72348622b7..61f5ae670cd 100644
--- a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
+++ b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
@@ -85,9 +85,9 @@ void TableLayoutAlgorithmAuto::RecalcColumn(unsigned eff_col) {
// FIXME: Other browsers have a lower limit for the cell's max width.
const int kCCellMaxWidth = 32760;
Length cell_logical_width = cell->StyleOrColLogicalWidth();
- // TODO(crbug.com/382725): CSS math function results on tables should
- // be handled consistently with other lengths. Currently, only calc(%
- // + 0px) case is handled as calc(%).
+ // A calculated width that mixes lengths and percentages in fixed
+ // table layout must be treated as 'auto'.
+ // https://drafts.csswg.org/css-values-4/#calc-computed-value
if (cell_logical_width.IsCalculated()) {
const CalculationValue& calc =
cell_logical_width.GetCalculationValue();
@@ -182,8 +182,6 @@ void TableLayoutAlgorithmAuto::FullRecalc() {
group_logical_width = column->StyleRef().LogicalWidth();
} else {
Length col_logical_width = column->StyleRef().LogicalWidth();
- // FIXME: calc() on tables should be handled consistently with other
- // lengths. See bug: https://crbug.com/382725
if (col_logical_width.IsCalculated() || col_logical_width.IsAuto())
col_logical_width = group_logical_width;
// TODO(alancutter): Make this work correctly for calc lengths.
@@ -234,8 +232,12 @@ static bool ShouldScaleColumnsForParent(LayoutTable* table) {
// use ~infinity to make sure we use all available size in the containing
// block. However, this just doesn't work if this is a flex or grid item, so
// disallow scaling in that case.
- if (cb->IsFlexibleBoxIncludingNG() || cb->IsLayoutGrid())
+ const bool is_deprecated_webkit_box =
+ cb->StyleRef().IsDeprecatedWebkitBox();
+ if ((!is_deprecated_webkit_box && cb->IsFlexibleBoxIncludingNG()) ||
+ cb->IsLayoutGrid()) {
return false;
+ }
cb = cb->ContainingBlock();
}
return true;
@@ -387,8 +389,6 @@ int TableLayoutAlgorithmAuto::CalcEffectiveLogicalWidth() {
unsigned span = cell->ColSpan();
Length cell_logical_width = cell->StyleOrColLogicalWidth();
- // FIXME: calc() on tables should be handled consistently with other
- // lengths. See bug: https://crbug.com/382725
if (cell_logical_width.IsZero() || cell_logical_width.IsCalculated())
cell_logical_width = Length(); // Make it Auto
diff --git a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc
index 25f752f8eca..f869ceb3a9d 100644
--- a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc
+++ b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_fixed.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_table_col.h"
#include "third_party/blink/renderer/core/layout/layout_table_section.h"
+#include "third_party/blink/renderer/platform/geometry/calculation_value.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
@@ -147,10 +148,16 @@ int TableLayoutAlgorithmFixed::CalcWidthArray() {
cell = cell->NextCell()) {
Length logical_width = cell->StyleOrColLogicalWidth();
- // FIXME: calc() on tables should be handled consistently with other
- // lengths. See bug: https://crbug.com/382725
- if (logical_width.IsCalculated())
- logical_width = Length(); // Make it Auto
+ if (logical_width.IsCalculated()) {
+ // A calculated width that mixes lengths and percentages in fixed table
+ // layout must be treated as 'auto'.
+ // https://drafts.csswg.org/css-values-4/#calc-computed-value
+ const CalculationValue& calc = logical_width.GetCalculationValue();
+ if (calc.IsExpression() || calc.Pixels())
+ logical_width = Length();
+ else
+ logical_width = Length::Percent(calc.Percent());
+ }
unsigned span = cell->ColSpan();
int fixed_border_box_logical_width = 0;
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 34dad21002f..19111b9123b 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
@@ -58,8 +58,7 @@ class SubtreeLayoutScope;
// Single-pass text autosizer. Documentation at:
// http://tinyurl.com/TextAutosizer
-class CORE_EXPORT TextAutosizer final
- : public GarbageCollectedFinalized<TextAutosizer> {
+class CORE_EXPORT TextAutosizer final : public GarbageCollected<TextAutosizer> {
public:
explicit TextAutosizer(const Document*);
~TextAutosizer();
diff --git a/chromium/third_party/blink/renderer/core/layout/text_autosizer_test.cc b/chromium/third_party/blink/renderer/core/layout/text_autosizer_test.cc
index aa7e84929d1..fcf01c4cbce 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer_test.cc
@@ -19,7 +19,7 @@
namespace blink {
class TextAutosizerClient : public RenderingTestChromeClient {
public:
- float WindowToViewportScalar(const float value) const override {
+ float WindowToViewportScalar(LocalFrame*, const float value) const override {
return value * device_scale_factor_;
}
IntRect ViewportToScreen(const IntRect& rect,
diff --git a/chromium/third_party/blink/renderer/core/loader/BUILD.gn b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
index 4178ea6fc26..0b517e7463b 100644
--- a/chromium/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
@@ -103,8 +103,6 @@ blink_core_sources("loader") {
"prerenderer_client.h",
"previews_resource_loading_hints.cc",
"previews_resource_loading_hints.h",
- "previews_resource_loading_hints_receiver_impl.cc",
- "previews_resource_loading_hints_receiver_impl.h",
"private/frame_client_hints_preferences_context.cc",
"private/frame_client_hints_preferences_context.h",
"private/prerender_handle.cc",
diff --git a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
index 96ab51b7ab1..ddc6ee5674f 100644
--- a/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
+++ b/chromium/third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc
@@ -7,6 +7,7 @@
#include "net/http/http_request_headers.h"
#include "third_party/blink/public/common/web_package/signed_exchange_consts.h"
#include "third_party/blink/public/common/web_package/signed_exchange_request_matcher.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/link_header.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 c1fe8c0ad68..1ecddf9426b 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
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/optional.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.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/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
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 9ac6dbb59de..e574556094d 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
@@ -6,6 +6,7 @@
#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"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
index 2c65c7d2bff..ec3dd6982d2 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc
@@ -155,7 +155,8 @@ void ApplicationCache::RecordAPIUseType() const {
return;
if (document->IsSecureContext()) {
- UseCounter::Count(document, WebFeature::kApplicationCacheAPISecureOrigin);
+ Deprecation::CountDeprecation(document,
+ WebFeature::kApplicationCacheAPISecureOrigin);
} else {
Deprecation::CountDeprecation(
document, WebFeature::kApplicationCacheAPIInsecureOrigin);
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
index 2eb1d794417..cc2bb42e4e8 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_APPCACHE_APPLICATION_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_APPCACHE_APPLICATION_CACHE_H_
-#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
+#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
index b7670b0a12b..88409036ad4 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -86,8 +86,6 @@ ApplicationCacheHost::CacheInfo ApplicationCacheHost::ApplicationCacheInfo() {
}
const base::UnguessableToken& ApplicationCacheHost::GetHostID() const {
- if (!backend_host_.is_bound())
- return base::UnguessableToken::Null();
return host_id_;
}
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 28ba68fa99c..2ab5f3b9d6c 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
@@ -35,12 +35,13 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom-blink.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -51,7 +52,7 @@
namespace blink {
class CORE_EXPORT ApplicationCacheHost
- : public GarbageCollectedFinalized<ApplicationCacheHost>,
+ : public GarbageCollected<ApplicationCacheHost>,
public mojom::blink::AppCacheFrontend {
public:
ApplicationCacheHost(
@@ -104,7 +105,8 @@ class CORE_EXPORT ApplicationCacheHost
void LogMessage(mojom::blink::ConsoleMessageLevel log_level,
const String& message) override {}
void SetSubresourceFactory(
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory) override {}
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory) override {}
virtual void Trace(blink::Visitor*) {}
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
index 12d8f5ea0e3..730968054bb 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
@@ -44,10 +44,15 @@ void RestartNavigation(LocalFrame* frame) {
ApplicationCacheHostForFrame::ApplicationCacheHostForFrame(
DocumentLoader* document_loader,
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::UnguessableToken& appcache_host_id)
: ApplicationCacheHost(interface_broker_proxy, std::move(task_runner)),
local_frame_(document_loader->GetFrame()),
- document_loader_(document_loader) {}
+ document_loader_(document_loader) {
+ // PlzNavigate: The browser passes the ID to be used.
+ if (!appcache_host_id.is_empty())
+ SetHostID(appcache_host_id);
+}
void ApplicationCacheHostForFrame::Detach() {
ApplicationCacheHost::Detach();
@@ -124,12 +129,12 @@ void ApplicationCacheHostForFrame::LogMessage(
}
void ApplicationCacheHostForFrame::SetSubresourceFactory(
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory) {
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory) {
auto pending_factories = std::make_unique<URLLoaderFactoryBundleInfo>();
pending_factories->pending_appcache_factory() =
mojo::PendingRemote<network::mojom::URLLoaderFactory>(
- url_loader_factory.PassInterface().PassHandle(),
- url_loader_factory.version());
+ url_loader_factory.PassPipe(), url_loader_factory.version());
local_frame_->Client()->UpdateSubresourceFactory(
std::move(pending_factories));
}
@@ -141,12 +146,11 @@ void ApplicationCacheHostForFrame::WillStartLoadingMainResource(
if (!IsApplicationCacheEnabled())
return;
- // PlzNavigate: The browser passes the ID to be used.
- DCHECK(GetHostID().is_empty());
- if (!document_loader_->AppcacheHostId().is_empty())
- SetHostID(document_loader_->AppcacheHostId());
- else
+ if (GetHostID().is_empty()) {
+ // If we did not get host id from the browser, we postpone creation of a new
+ // one until this point, where we actually load non-empty document.
SetHostID(base::UnguessableToken::Create());
+ }
// We defer binding to backend to avoid unnecessary binding around creating
// empty documents. At this point, we're initiating a main resource load for
@@ -206,13 +210,11 @@ void ApplicationCacheHostForFrame::SelectCacheWithManifest(
return;
}
if (document->IsSecureContext()) {
- UseCounter::Count(document,
- WebFeature::kApplicationCacheManifestSelectSecureOrigin);
+ Deprecation::CountDeprecation(
+ document, WebFeature::kApplicationCacheManifestSelectSecureOrigin);
} else {
Deprecation::CountDeprecation(
document, WebFeature::kApplicationCacheManifestSelectInsecureOrigin);
- Deprecation::CountDeprecationCrossOriginIframe(
- *document, WebFeature::kApplicationCacheManifestSelectInsecureOrigin);
HostsUsingFeatures::CountAnyWorld(
*document, HostsUsingFeatures::Feature::
kApplicationCacheManifestSelectInsecureHost);
diff --git a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h
index 575999782d0..a43d4f41399 100644
--- a/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h
+++ b/chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_APPCACHE_APPLICATION_CACHE_HOST_FOR_FRAME_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_APPCACHE_APPLICATION_CACHE_HOST_FOR_FRAME_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/appcache/application_cache_host.h"
@@ -19,7 +20,8 @@ class CORE_EXPORT ApplicationCacheHostForFrame : public ApplicationCacheHost {
ApplicationCacheHostForFrame(
DocumentLoader* document_loader,
const BrowserInterfaceBrokerProxy& interface_broker_proxy,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ const base::UnguessableToken& appcache_host_id);
// ApplicationCacheHost:
void Detach() override;
@@ -33,7 +35,8 @@ class CORE_EXPORT ApplicationCacheHostForFrame : public ApplicationCacheHost {
void LogMessage(mojom::blink::ConsoleMessageLevel log_level,
const String& message) override;
void SetSubresourceFactory(
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory) override;
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory) override;
void WillStartLoadingMainResource(DocumentLoader* loader,
const KURL& url,
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 33d2cacaa9e..c297d32bf82 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
@@ -139,7 +139,7 @@ BaseFetchContext::CanRequestInternal(
// TODO(yhirano): Figure out if it's actually fine.
DCHECK(network::IsNavigationRequestMode(request_mode) || origin);
if (!network::IsNavigationRequestMode(request_mode) &&
- !origin->CanDisplay(url)) {
+ !resource_request.CanDisplay(url)) {
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
AddConsoleMessage(ConsoleMessage::Create(
mojom::ConsoleMessageSource::kJavaScript,
@@ -152,7 +152,9 @@ BaseFetchContext::CanRequestInternal(
}
if (request_mode == network::mojom::RequestMode::kSameOrigin &&
- cors::CalculateCorsFlag(url, origin.get(), request_mode)) {
+ cors::CalculateCorsFlag(url, origin.get(),
+ resource_request.IsolatedWorldOrigin().get(),
+ request_mode)) {
PrintAccessDeniedMessage(url);
return ResourceRequestBlockedReason::kOrigin;
}
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 1f3fc31ece6..317279170ce 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
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_BASE_FETCH_CONTEXT_H_
#include "base/optional.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/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
index cc4d4bf0a09..d9b69e509d8 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -32,6 +32,7 @@
#include "testing/gmock/include/gmock/gmock.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/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
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 d2ce1001071..4b2aa2d0b1f 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.cc
@@ -34,13 +34,11 @@
#include "base/auto_reset.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/default_tick_clock.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/origin_policy/origin_policy.h"
#include "third_party/blink/public/mojom/commit_result/commit_result.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/public/web/web_history_commit_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
@@ -126,10 +124,9 @@ DocumentLoader::DocumentLoader(
document_load_timing_(*this),
service_worker_network_provider_(
std::move(params_->service_worker_network_provider)),
- was_blocked_after_csp_(false),
+ was_blocked_by_csp_(false),
state_(kNotStarted),
- committed_data_buffer_(nullptr),
- in_data_received_(false),
+ in_commit_data_(false),
data_buffer_(SharedBuffer::Create()),
devtools_navigation_token_(params_->devtools_navigation_token),
had_sticky_activation_(params_->is_user_activated),
@@ -166,10 +163,16 @@ DocumentLoader::DocumentLoader(
origin_policy_ = params_->origin_policy;
requestor_origin_ = params_->requestor_origin;
unreachable_url_ = params_->unreachable_url;
- error_code_ = params_->error_code;
- previews_state_ = params_->previews_state;
- appcache_host_id_ = params_->appcache_host_id;
+ if (frame_->IsMainFrame()) {
+ previews_state_ = params_->previews_state;
+ } else {
+ // Subframes inherit previews state from the main frame.
+ if (auto* parent = DynamicTo<LocalFrame>(frame_->Tree().Parent()))
+ previews_state_ = parent->Loader().GetDocumentLoader()->previews_state_;
+ }
ip_address_space_ = params_->ip_address_space;
+ grant_load_local_resources_ = params_->grant_load_local_resources;
+ force_fetch_cache_mode_ = params_->force_fetch_cache_mode;
WebNavigationTimings& timings = params_->navigation_timings;
if (!timings.input_start.is_null())
@@ -230,7 +233,16 @@ DocumentLoader::DocumentLoader(
// original URL (https://crbug.com/622385).
// TODO(mkwst): Remove this once XFO moves to the browser.
// https://crbug.com/555418.
- was_blocked_after_csp_ = true;
+
+ // Update |origin_to_commit_| to contain an opaque origin with precursor
+ // information that is consistent with the final request URL.
+ // Note: We can't use |url_| for the origin calculation because
+ // we need to take into account any redirects that may have occurred.
+ const auto request_url_origin = blink::SecurityOrigin::Create(
+ params_->response.ToResourceResponse().CurrentRequestUrl());
+ origin_to_commit_ = request_url_origin->DeriveNewOpaqueOrigin();
+
+ was_blocked_by_csp_ = true;
KURL blocked_url = SecurityOrigin::UrlWithUniqueOpaqueOrigin();
original_url_ = blocked_url;
url_ = blocked_url;
@@ -253,6 +265,19 @@ DocumentLoader::DocumentLoader(
initiator_origin_trial_features_.push_back(
static_cast<OriginTrialFeature>(feature));
}
+
+ // For back/forward navigations, the browser passed a history item to use at
+ // commit time in |params_|. Set it as the current history item of this
+ // DocumentLoader. For other navigations, |history_item_| will be created when
+ // the FrameLoader calls SetHistoryItemStateForCommit.
+ if (IsBackForwardLoadType(params_->frame_load_type)) {
+ HistoryItem* history_item = params_->history_item;
+ DCHECK(history_item);
+ history_item_ = history_item;
+ }
+
+ base_url_override_for_bundled_exchanges_ =
+ params_->base_url_override_for_bundled_exchanges;
}
FrameLoader& DocumentLoader::GetFrameLoader() const {
@@ -338,7 +363,8 @@ void DocumentLoader::DispatchLinkHeaderPreloads(
GetResponse().HttpHeaderField(http_names::kLink),
GetResponse().CurrentRequestUrl(), *frame_, frame_->GetDocument(),
PreloadHelper::kOnlyLoadResources, media_policy, viewport,
- nullptr /* alternate_resource_info */);
+ nullptr /* alternate_resource_info */,
+ base::nullopt /* recursive_prefetch_token */);
}
void DocumentLoader::DidChangePerformanceTiming() {
@@ -347,8 +373,7 @@ void DocumentLoader::DidChangePerformanceTiming() {
}
}
-void DocumentLoader::DidObserveLoadingBehavior(
- WebLoadingBehaviorFlag behavior) {
+void DocumentLoader::DidObserveLoadingBehavior(LoadingBehaviorFlag behavior) {
if (frame_) {
DCHECK_GE(state_, kCommitted);
GetLocalFrameClient().DidObserveLoadingBehavior(behavior);
@@ -360,7 +385,9 @@ void DocumentLoader::MarkAsCommitted() {
state_ = kCommitted;
}
-static WebHistoryCommitType LoadTypeToCommitType(WebFrameLoadType type) {
+// static
+WebHistoryCommitType DocumentLoader::LoadTypeToCommitType(
+ WebFrameLoadType type) {
switch (type) {
case WebFrameLoadType::kStandard:
return kWebStandardCommit;
@@ -446,7 +473,7 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
same_document_navigation_source == kSameDocumentNavigationHistoryApi
? HistoryNavigationType::kHistoryApi
: HistoryNavigationType::kFragment);
- history_item_->SetDocumentState(frame_->GetDocument()->FormElementsState());
+ history_item_->SetDocumentState(frame_->GetDocument()->GetDocumentState());
if (same_document_navigation_source == kSameDocumentNavigationHistoryApi) {
history_item_->SetStateObject(std::move(data));
history_item_->SetScrollRestorationType(scroll_restoration_type);
@@ -467,14 +494,6 @@ const KURL& DocumentLoader::UrlForHistory() const {
return UnreachableURL().IsEmpty() ? Url() : UnreachableURL();
}
-EncodedFormData* DocumentLoader::HttpBody() const {
- return http_body_.get();
-}
-
-const base::UnguessableToken& DocumentLoader::AppcacheHostId() const {
- return appcache_host_id_;
-}
-
void DocumentLoader::FillNavigationParamsForErrorPage(
WebNavigationParams* params) {
params->http_method = http_method_;
@@ -485,6 +504,12 @@ void DocumentLoader::FillNavigationParamsForErrorPage(
params->previews_state = previews_state_;
params->requestor_origin = requestor_origin_;
params->origin_policy = origin_policy_;
+ // Force the commit origin for the error page to be opaque and
+ // contain precursor information from the document's origin.
+ // This is only used for renderer-side enforcement of CSP and the
+ // document origin used here is the origin of the document that was blocked.
+ params->origin_to_commit =
+ frame_->GetDocument()->GetSecurityOrigin()->DeriveNewOpaqueOrigin();
}
void DocumentLoader::SetHistoryItemStateForCommit(
@@ -553,7 +578,24 @@ void DocumentLoader::BodyDataReceived(base::span<const char> data) {
probe::DidReceiveData(probe::ToCoreProbeSink(GetFrame()),
main_resource_identifier_, this, data.data(),
data.size());
- HandleData(data.data(), data.size());
+
+ TRACE_EVENT1("loading", "DocumentLoader::HandleData", "length", data.size());
+
+ DCHECK(data.data());
+ DCHECK(data.size());
+ DCHECK(!frame_->GetPage()->Paused());
+ time_of_last_data_received_ = clock_->NowTicks();
+
+ if (listing_ftp_directory_ || loading_mhtml_archive_) {
+ // 1) Ftp directory listings accumulate data buffer and transform it later
+ // to the actual document content.
+ // 2) Mhtml archives accumulate data buffer and parse it as mhtml later
+ // to retrieve the actual document content.
+ data_buffer_->Append(data.data(), data.size());
+ return;
+ }
+
+ ProcessDataBuffer(data.data(), data.size());
}
void DocumentLoader::BodyLoadingFinished(
@@ -637,10 +679,9 @@ void DocumentLoader::FinishedLoading(base::TimeTicks finish_time) {
MainThreadDebugger::Instance()->IsPaused());
if (listing_ftp_directory_) {
- scoped_refptr<SharedBuffer> buffer = GenerateFtpDirectoryListingHtml(
+ data_buffer_ = GenerateFtpDirectoryListingHtml(
response_.CurrentRequestUrl(), data_buffer_.get());
- for (const auto& span : *buffer)
- CommitData(span.data(), span.size());
+ ProcessDataBuffer();
}
if (loading_mhtml_archive_ && state_ < kCommitted) {
@@ -667,7 +708,7 @@ void DocumentLoader::FinishedLoading(base::TimeTicks finish_time) {
if (parser_) {
if (parser_blocked_count_) {
- finished_loading_ = true;
+ finish_loading_when_parser_resumed_ = true;
} else {
parser_->Finish();
parser_.Clear();
@@ -701,19 +742,18 @@ void DocumentLoader::FinalizeMHTMLArchiveLoad() {
void DocumentLoader::HandleRedirect(const KURL& current_request_url) {
// Browser process should have already checked that redirecting url is
// allowed to display content from the target origin.
- CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_));
+ // When the referrer page is in an unsigned bundled exchanges file in local
+ // (eg: file:///tmp/a.wbn), Chrome internally redirects the navigation to the
+ // page (eg: https://example.com/page.html) inside the bundled exchanges file
+ // to the file's URL (file:///tmp/a.wbn?https://example.com/page.html). In
+ // this case, CanDisplay() returns false, and
+ // base_url_override_for_bundled_exchanges must not be null.
+ CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_) ||
+ !params_->base_url_override_for_bundled_exchanges.IsNull());
DCHECK(!GetTiming().FetchStart().is_null());
redirect_chain_.push_back(url_);
GetTiming().AddRedirect(current_request_url, url_);
-
- // If a redirection happens during a back/forward navigation, don't restore
- // any state from the old HistoryItem. There is a provisional history item for
- // back/forward navigation only. In the other case, clearing it is a no-op.
- history_item_.Clear();
-
- // TODO(creis): Determine if we need to clear any history state
- // in embedder to fix https://crbug.com/671276.
}
bool DocumentLoader::ShouldReportTimingInfoToParent() {
@@ -762,8 +802,11 @@ ContentSecurityPolicy* DocumentLoader::CreateCSP(
}
}
}
- if (!csp->AllowAncestors(frame_, response.CurrentRequestUrl()))
- return nullptr;
+ if (!base::FeatureList::IsEnabled(
+ network::features::kOutOfBlinkFrameAncestors)) {
+ if (!csp->AllowAncestors(frame_, response.CurrentRequestUrl()))
+ return nullptr;
+ }
if (!frame_->GetSettings()->BypassCSP() &&
!GetFrameLoader().RequiredCSP().IsEmpty()) {
@@ -824,25 +867,12 @@ void DocumentLoader::HandleResponse() {
frame_->Owner()->RenderFallbackContent(frame_);
}
-void DocumentLoader::PrepareForNavigationCommit() {
- if (state_ != kProvisional)
- return;
-
- // Set history state before commitProvisionalLoad() so that we still have
- // access to the previous committed DocumentLoader's HistoryItem, in case we
- // need to copy state from it.
- if (!GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
- SetHistoryItemStateForCommit(
- GetFrameLoader().GetDocumentLoader()->GetHistoryItem(), load_type_,
- HistoryNavigationType::kDifferentDocument);
- }
-
- DCHECK_EQ(state_, kProvisional);
-}
+void DocumentLoader::CommitNavigation() {
+ CHECK_GE(state_, kCommitted);
-void DocumentLoader::FinishNavigationCommit(const AtomicString& mime_type,
- const KURL& overriding_url) {
- const AtomicString& encoding = GetResponse().TextEncodingName();
+ KURL overriding_url = base_url_override_for_bundled_exchanges_;
+ if (loading_mhtml_archive_ && archive_)
+ overriding_url = archive_->MainResource()->Url();
// Prepare a DocumentInit before clearing the frame, because it may need to
// inherit an aliased security context.
@@ -864,26 +894,12 @@ void DocumentLoader::FinishNavigationCommit(const AtomicString& mime_type,
}
DCHECK(frame_->GetPage());
- ParserSynchronizationPolicy parsing_policy = kAllowAsynchronousParsing;
- if (loading_url_as_javascript_ ||
- !Document::ThreadedParsingEnabledForTesting()) {
- parsing_policy = kForceSynchronousParsing;
- }
-
- InstallNewDocument(Url(), initiator_origin, owner_document, mime_type,
- encoding, parsing_policy, overriding_url);
- parser_->SetDocumentWasLoadedAsPartOfNavigation();
- if (was_discarded_)
- frame_->GetDocument()->SetWasDiscarded(true);
- frame_->GetDocument()->MaybeHandleHttpRefresh(
- response_.HttpHeaderField(http_names::kRefresh),
- Document::kHttpRefreshFromHeader);
- ReportPreviewsIntervention();
+ InstallNewDocument(Url(), initiator_origin, owner_document, MimeType(),
+ overriding_url);
}
void DocumentLoader::CommitData(const char* bytes, size_t length) {
TRACE_EVENT1("loading", "DocumentLoader::CommitData", "length", length);
- DCHECK_GE(state_, kCommitted);
// This can happen if document.close() is called by an event handler while
// there's still pending incoming data.
@@ -893,16 +909,10 @@ void DocumentLoader::CommitData(const char* bytes, size_t length) {
if (!frame_ || !frame_->GetDocument()->Parsing())
return;
+ base::AutoReset<bool> reentrancy_protector(&in_commit_data_, true);
if (length)
data_received_ = true;
-
- if (parser_blocked_count_) {
- if (!committed_data_buffer_)
- committed_data_buffer_ = SharedBuffer::Create();
- committed_data_buffer_->Append(bytes, length);
- } else {
- parser_->AppendBytes(bytes, length);
- }
+ parser_->AppendBytes(bytes, length);
}
mojom::CommitResult DocumentLoader::CommitSameDocumentNavigation(
@@ -973,12 +983,15 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
// If we have a provisional request for a different document, a fragment
// scroll should cancel it.
+ // Note: see fragment-change-does-not-cancel-pending-navigation, where
+ // this does not actually happen.
GetFrameLoader().DetachProvisionalDocumentLoader();
- GetFrameLoader().CancelClientNavigation();
GetFrameLoader().DidFinishNavigation(
FrameLoader::NavigationFinishState::kSuccess);
- if (!frame_->GetPage())
+ // GetFrameLoader().DidFinishNavigation can lead to DetachFromFrame so need
+ // to check again if frame_ is null.
+ if (!frame_ || !frame_->GetPage())
return;
GetFrameLoader().SaveScrollState();
@@ -1008,35 +1021,23 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
history_item);
}
-void DocumentLoader::HandleData(const char* data, size_t length) {
- TRACE_EVENT1("loading", "DocumentLoader::HandleData", "length", length);
- DCHECK(data);
- DCHECK(length);
- DCHECK(!frame_->GetPage()->Paused());
- time_of_last_data_received_ = clock_->NowTicks();
-
- if (listing_ftp_directory_ || loading_mhtml_archive_) {
- data_buffer_->Append(data, length);
- return;
- }
-
- if (in_data_received_) {
- // If this function is reentered, defer processing of the additional data to
- // the top-level invocation. Reentrant calls can occur because of web
- // platform (mis-)features that require running a nested run loop:
- // - alert(), confirm(), prompt()
- // - Detach of plugin elements.
- // - Synchronous XMLHTTPRequest
- data_buffer_->Append(data, length);
+void DocumentLoader::ProcessDataBuffer(const char* bytes, size_t length) {
+ DCHECK_GE(state_, kCommitted);
+ if (parser_blocked_count_ || in_commit_data_) {
+ // 1) If parser is blocked, we buffer data and process it upon resume.
+ // 2) If this function is reentered, we defer processing of the additional
+ // data to the top-level invocation. Reentrant calls can occur because
+ // of web platform (mis-)features that require running a nested run loop:
+ // - alert(), confirm(), prompt()
+ // - Detach of plugin elements.
+ // - Synchronous XMLHTTPRequest
+ if (bytes)
+ data_buffer_->Append(bytes, length);
return;
}
- base::AutoReset<bool> reentrancy_protector(&in_data_received_, true);
- CommitData(data, length);
- ProcessDataBuffer();
-}
-
-void DocumentLoader::ProcessDataBuffer() {
+ if (bytes)
+ CommitData(bytes, length);
// Process data received in reentrant invocations. Note that the invocations
// of CommitData() may queue more data in reentrant invocations, so iterate
// until it's empty.
@@ -1103,6 +1104,11 @@ const KURL& DocumentLoader::UnreachableURL() const {
return unreachable_url_;
}
+const base::Optional<blink::mojom::FetchCacheMode>&
+DocumentLoader::ForceFetchCacheMode() const {
+ return force_fetch_cache_mode_;
+}
+
bool DocumentLoader::WillLoadUrlAsEmpty(const KURL& url) {
if (url.IsEmpty())
return true;
@@ -1135,7 +1141,8 @@ void DocumentLoader::StartLoadingInternal() {
state_ = kProvisional;
application_cache_host_ = MakeGarbageCollected<ApplicationCacheHostForFrame>(
this, GetFrame()->Client()->GetBrowserInterfaceBroker(),
- GetFrame()->GetTaskRunner(TaskType::kNetworking));
+ GetFrame()->GetTaskRunner(TaskType::kNetworking),
+ params_->appcache_host_id);
if (url_.IsEmpty() &&
!GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
@@ -1144,7 +1151,6 @@ void DocumentLoader::StartLoadingInternal() {
if (loading_url_as_empty_document_) {
InitializeEmptyResponse();
- PrepareForNavigationCommit();
return;
}
@@ -1221,7 +1227,8 @@ void DocumentLoader::StartLoadingInternal() {
response_.CurrentRequestUrl(), *GetFrame(), nullptr,
PreloadHelper::kDoNotLoadResources, PreloadHelper::kLoadAll,
base::nullopt /* viewport_description */,
- nullptr /* alternate_resource_info */);
+ nullptr /* alternate_resource_info */,
+ base::nullopt /* recursive_prefetch_token */);
if (!frame_->IsMainFrame() && response_.HasMajorCertificateErrors()) {
MixedContentChecker::HandleCertificateError(
GetFrame(), response_, mojom::RequestContextType::HYPERLINK);
@@ -1253,7 +1260,6 @@ void DocumentLoader::StartLoadingInternal() {
// TODO(clamy): Simplify this code path.
FinalizeMHTMLArchiveLoad();
}
- PrepareForNavigationCommit();
return;
}
@@ -1261,28 +1267,21 @@ void DocumentLoader::StartLoadingInternal() {
if (defers_loading_)
body_loader_->SetDefersLoading(true);
-
- PrepareForNavigationCommit();
}
void DocumentLoader::StartLoadingResponse() {
if (!frame_)
return;
- ArchiveResource* main_resource =
- loading_mhtml_archive_ && archive_ ? archive_->MainResource() : nullptr;
- if (main_resource)
- FinishNavigationCommit(main_resource->MimeType(), main_resource->Url());
- else
- FinishNavigationCommit(response_.MimeType());
-
CHECK_GE(state_, kCommitted);
+ CreateParserPostCommit();
// Finish load of MHTML archives and empty documents.
+ ArchiveResource* main_resource =
+ loading_mhtml_archive_ && archive_ ? archive_->MainResource() : nullptr;
if (main_resource) {
- scoped_refptr<SharedBuffer> data(main_resource->Data());
- for (const auto& span : *data)
- CommitData(span.data(), span.size());
+ data_buffer_ = main_resource->Data();
+ ProcessDataBuffer();
}
if (loading_mhtml_archive_ || loading_url_as_empty_document_) {
@@ -1335,7 +1334,7 @@ void DocumentLoader::DidInstallNewDocument(Document* document) {
document->BindContentSecurityPolicy();
if (history_item_ && IsBackForwardLoadType(load_type_))
- document->SetStateForNewFormElements(history_item_->GetDocumentState());
+ document->SetStateForNewControls(history_item_->GetDocumentState());
DCHECK(document->GetFrame());
// TODO(dgozman): modify frame's client hints directly once we commit
@@ -1374,8 +1373,6 @@ void DocumentLoader::DidInstallNewDocument(Document* document) {
? WebFeature::kSignedExchangeInnerResponseInMainFrame
: WebFeature::kSignedExchangeInnerResponseInSubFrame);
}
-
- GetLocalFrameClient().DidCreateNewDocument();
}
void DocumentLoader::WillCommitNavigation() {
@@ -1385,8 +1382,7 @@ void DocumentLoader::WillCommitNavigation() {
frame_->GetIdlenessDetector()->WillCommitLoad();
}
-void DocumentLoader::DidCommitNavigation(
- GlobalObjectReusePolicy global_object_reuse_policy) {
+void DocumentLoader::DidCommitNavigation() {
if (GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument())
return;
@@ -1416,25 +1412,6 @@ void DocumentLoader::DidCommitNavigation(
// When a new navigation commits in the frame, subresource loading should be
// resumed.
frame_->ResumeSubresourceLoading();
- GetLocalFrameClient().DispatchDidCommitLoad(history_item_.Get(), commit_type,
- global_object_reuse_policy);
-
- // When the embedder gets notified (above) that the new navigation has
- // committed, the embedder will drop the old Content Security Policy and
- // therefore now is a good time to report to the embedder the Content
- // Security Policies that have accumulated so far for the new navigation.
- frame_->GetSecurityContext()
- ->GetContentSecurityPolicy()
- ->ReportAccumulatedHeaders(&GetLocalFrameClient());
-
- // DidObserveLoadingBehavior() must be called after DispatchDidCommitLoad() is
- // called for the metrics tracking logic to handle it properly.
- if (service_worker_network_provider_ &&
- service_worker_network_provider_->GetControllerServiceWorkerMode() ==
- blink::mojom::ControllerServiceWorkerMode::kControlled) {
- GetLocalFrameClient().DidObserveLoadingBehavior(
- kWebLoadingBehaviorServiceWorkerControlled);
- }
Document* document = frame_->GetDocument();
InteractiveDetector* interactive_detector =
@@ -1448,37 +1425,15 @@ void DocumentLoader::DidCommitNavigation(
// Needs to run before dispatching preloads, as it may evict the memory cache.
probe::DidCommitLoad(frame_, this);
- // Links with media values need more information (like viewport information).
- // This happens after the first chunk is parsed in HTMLDocumentParser.
- DispatchLinkHeaderPreloads(base::nullopt /* viewport */,
- PreloadHelper::kOnlyLoadNonMedia);
-
frame_->GetPage()->DidCommitLoad(frame_);
GetUseCounterHelper().DidCommitLoad(frame_);
// Report legacy TLS versions after Page::DidCommitLoad, because the latter
// clears the console.
if (response_.IsLegacyTLSVersion()) {
- CountUse(frame_->Tree().Parent()
- ? WebFeature::kLegacyTLSVersionInSubframeMainResource
- : WebFeature::kLegacyTLSVersionInMainFrameResource);
- GetLocalFrameClient().ReportLegacyTLSVersion(response_.CurrentRequestUrl());
- if (!frame_->Tree().Parent()) {
- ukm::builders::Net_LegacyTLSVersion(document->UkmSourceID())
- .SetIsMainFrame(true)
- .SetIsSubresource(false)
- .SetIsAdResource(frame_->IsAdSubframe() || frame_->IsAdRoot())
- .Record(document->UkmRecorder());
- } else {
- // For non-main-frame loads, we have to use the main frame's document for
- // the UKM recorder and source ID.
- auto& root = frame_->LocalFrameRoot();
- ukm::builders::Net_LegacyTLSVersion(root.GetDocument()->UkmSourceID())
- .SetIsMainFrame(false)
- .SetIsSubresource(false)
- .SetIsAdResource(frame_->IsAdSubframe())
- .Record(root.GetDocument()->UkmRecorder());
- }
+ GetFrameLoader().ReportLegacyTLSVersion(
+ response_.CurrentRequestUrl(), false /* is_subresource */,
+ frame_->IsAdSubframe() || frame_->IsAdRoot());
}
}
@@ -1501,8 +1456,6 @@ void DocumentLoader::InstallNewDocument(
const scoped_refptr<const SecurityOrigin> initiator_origin,
Document* owner_document,
const AtomicString& mime_type,
- const AtomicString& encoding,
- ParserSynchronizationPolicy parsing_policy,
const KURL& overriding_url) {
DCHECK(!frame_->GetDocument() || !frame_->GetDocument()->IsActive());
DCHECK_EQ(frame_->Tree().ChildCount(), 0u);
@@ -1525,6 +1478,8 @@ void DocumentLoader::InstallNewDocument(
.WithOriginToCommit(origin_to_commit_)
.WithIPAddressSpace(ip_address_space_)
.WithSrcdocDocument(loading_srcdoc_)
+ .WithBlockedByCSP(was_blocked_by_csp_)
+ .WithGrantLoadLocalResources(grant_load_local_resources_)
.WithNewRegistrationContext()
.WithFeaturePolicyHeader(feature_policy.ToString())
.WithOriginTrialsHeader(
@@ -1537,7 +1492,7 @@ void DocumentLoader::InstallNewDocument(
loading_url_as_javascript_
? frame_->GetDocument()->GetContentSecurityPolicy()
: content_security_policy_.Get();
- GlobalObjectReusePolicy global_object_reuse_policy =
+ global_object_reuse_policy_ =
GetFrameLoader().ShouldReuseDefaultView(init.GetDocumentOrigin(), csp)
? GlobalObjectReusePolicy::kUseExisting
: GlobalObjectReusePolicy::kCreateNew;
@@ -1560,7 +1515,7 @@ void DocumentLoader::InstallNewDocument(
// commits. To make that happen, we "securely transition" the existing
// LocalDOMWindow to the Document that results from the network load. See also
// Document::IsSecureTransitionTo.
- if (global_object_reuse_policy != GlobalObjectReusePolicy::kUseExisting) {
+ if (global_object_reuse_policy_ != GlobalObjectReusePolicy::kUseExisting) {
if (frame_->GetDocument())
frame_->GetDocument()->RemoveAllEventListenersRecursively();
frame_->SetDOMWindow(MakeGarbageCollected<LocalDOMWindow>(*frame_));
@@ -1609,7 +1564,50 @@ void DocumentLoader::InstallNewDocument(
// This must be called before the document is opened, otherwise HTML parser
// will use stale values from HTMLParserOption.
if (!loading_url_as_javascript_)
- DidCommitNavigation(global_object_reuse_policy);
+ DidCommitNavigation();
+
+ // Determine if the load is from a document from the same origin to enable
+ // deferred commits to avoid white flash on load. We only want to delay
+ // commits on same origin loads to avoid confusing users. We also require
+ // that this be an html document served via http.
+ if (initiator_origin) {
+ const scoped_refptr<const SecurityOrigin> url_origin =
+ SecurityOrigin::Create(Url());
+ document->SetDeferredCompositorCommitIsAllowed(
+ initiator_origin->IsSameSchemeHostPort(url_origin.get()) &&
+ Url().ProtocolIsInHTTPFamily() && document->IsHTMLDocument());
+ } else {
+ document->SetDeferredCompositorCommitIsAllowed(false);
+ }
+}
+
+void DocumentLoader::CreateParserPostCommit() {
+ Document* document = frame_->GetDocument();
+
+ // DidObserveLoadingBehavior() must be called after DispatchDidCommitLoad() is
+ // called for the metrics tracking logic to handle it properly.
+ if (service_worker_network_provider_ &&
+ service_worker_network_provider_->GetControllerServiceWorkerMode() ==
+ blink::mojom::ControllerServiceWorkerMode::kControlled) {
+ GetLocalFrameClient().DidObserveLoadingBehavior(
+ kLoadingBehaviorServiceWorkerControlled);
+ }
+
+ // Links with media values need more information (like viewport information).
+ // This happens after the first chunk is parsed in HTMLDocumentParser.
+ DispatchLinkHeaderPreloads(base::nullopt /* viewport */,
+ PreloadHelper::kOnlyLoadNonMedia);
+
+ if (!loading_url_as_javascript_ &&
+ !GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
+ // When the embedder gets notified (above) that the new navigation has
+ // committed, the embedder will drop the old Content Security Policy and
+ // therefore now is a good time to report to the embedder the Content
+ // Security Policies that have accumulated so far for the new navigation.
+ frame_->GetSecurityContext()
+ ->GetContentSecurityPolicy()
+ ->ReportAccumulatedHeaders(&GetLocalFrameClient());
+ }
// Initializing origin trials might force window proxy initialization,
// which later triggers CHECK when swapping in via WebFrame::Swap().
@@ -1637,10 +1635,6 @@ void DocumentLoader::InstallNewDocument(
OriginTrialContext::ActivateNavigationFeaturesFromInitiator(
document, &initiator_origin_trial_features_);
}
- bool stale_while_revalidate_enabled =
- RuntimeEnabledFeatures::StaleWhileRevalidateEnabled(document);
- document->Fetcher()->SetStaleWhileRevalidateEnabled(
- stale_while_revalidate_enabled);
bool opted_out_mixed_autoupgrade = EqualIgnoringASCIICase(
response_.HttpHeaderField("mixed-content"), "noupgrade");
@@ -1651,12 +1645,13 @@ void DocumentLoader::InstallNewDocument(
UMA_HISTOGRAM_BOOLEAN("MixedAutoupgrade.Navigation.OptedOut",
opted_out_mixed_autoupgrade);
- // If stale while revalidate is enabled via Origin Trials count it as such.
- if (stale_while_revalidate_enabled &&
- !RuntimeEnabledFeatures::StaleWhileRevalidateEnabledByRuntimeFlag())
- UseCounter::Count(document, WebFeature::kStaleWhileRevalidateEnabled);
-
- parser_ = document->OpenForNavigation(parsing_policy, mime_type, encoding);
+ ParserSynchronizationPolicy parsing_policy = kAllowAsynchronousParsing;
+ if (loading_url_as_javascript_ ||
+ !Document::ThreadedParsingEnabledForTesting()) {
+ parsing_policy = kForceSynchronousParsing;
+ }
+ parser_ = document->OpenForNavigation(parsing_policy, MimeType(),
+ response_.TextEncodingName());
// If this is a scriptable parser and there is a resource, register the
// resource's cache handler with the parser.
@@ -1677,19 +1672,13 @@ void DocumentLoader::InstallNewDocument(
GetFrameLoader().DispatchDidClearDocumentOfWindowObject();
- // Determine if the load is from a document from the same origin to enable
- // deferred commits to avoid white flash on load. We only want to delay
- // commits on same origin loads to avoid confusing users. We also require
- // that this be an html document served via http.
- if (initiator_origin) {
- const scoped_refptr<const SecurityOrigin> url_origin =
- SecurityOrigin::Create(Url());
- document->SetDeferredCompositorCommitIsAllowed(
- initiator_origin->IsSameSchemeHostPort(url_origin.get()) &&
- Url().ProtocolIsInHTTPFamily() && document->IsHTMLDocument());
- } else {
- document->SetDeferredCompositorCommitIsAllowed(false);
- }
+ parser_->SetDocumentWasLoadedAsPartOfNavigation();
+ if (was_discarded_)
+ document->SetWasDiscarded(true);
+ document->MaybeHandleHttpRefresh(
+ response_.HttpHeaderField(http_names::kRefresh),
+ Document::kHttpRefreshFromHeader);
+ ReportPreviewsIntervention();
}
const AtomicString& DocumentLoader::MimeType() const {
@@ -1711,22 +1700,10 @@ void DocumentLoader::ResumeParser() {
if (parser_blocked_count_ != 0)
return;
- if (committed_data_buffer_ && !committed_data_buffer_->IsEmpty()) {
- // Don't recursively process data.
- base::AutoReset<bool> reentrancy_protector(&in_data_received_, true);
-
- // Append data to the parser that may have been received while the parser
- // was blocked.
- for (const auto& span : *committed_data_buffer_)
- parser_->AppendBytes(span.data(), span.size());
- committed_data_buffer_->Clear();
-
- // DataReceived may be called in a nested message loop.
- ProcessDataBuffer();
- }
+ ProcessDataBuffer();
- if (finished_loading_) {
- finished_loading_ = false;
+ if (finish_loading_when_parser_resumed_) {
+ finish_loading_when_parser_resumed_ = false;
parser_->Finish();
parser_.Clear();
}
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 684fc13ea19..5c20f73afab 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.h
@@ -35,12 +35,13 @@
#include "base/optional.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/base/big_buffer.h"
-#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink.h"
+#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
+#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
-#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
#include "third_party/blink/public/platform/web_navigation_body_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_history_commit_type.h"
#include "third_party/blink/public/web/web_navigation_params.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_origin_policy.h"
@@ -102,10 +103,9 @@ enum class CommitResult : int32_t;
enum class GlobalObjectReusePolicy { kCreateNew, kUseExisting };
// The DocumentLoader fetches a main resource and handles the result.
-class CORE_EXPORT DocumentLoader
- : public GarbageCollectedFinalized<DocumentLoader>,
- public UseCounter,
- public WebNavigationBodyLoader::Client {
+class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
+ public UseCounter,
+ public WebNavigationBodyLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(DocumentLoader);
public:
@@ -115,6 +115,7 @@ class CORE_EXPORT DocumentLoader
~DocumentLoader() override;
static bool WillLoadUrlAsEmpty(const KURL&);
+ static WebHistoryCommitType LoadTypeToCommitType(WebFrameLoadType);
LocalFrame* GetFrame() const { return frame_; }
@@ -148,11 +149,11 @@ class CORE_EXPORT DocumentLoader
const AtomicString& HttpMethod() const;
const Referrer& GetReferrer() const;
const KURL& UnreachableURL() const;
- EncodedFormData* HttpBody() const;
- const base::UnguessableToken& AppcacheHostId() const;
+ const base::Optional<blink::mojom::FetchCacheMode>& ForceFetchCacheMode()
+ const;
void DidChangePerformanceTiming();
- void DidObserveLoadingBehavior(WebLoadingBehaviorFlag);
+ void DidObserveLoadingBehavior(LoadingBehaviorFlag);
void UpdateForSameDocumentNavigation(const KURL&,
SameDocumentNavigationSource,
scoped_refptr<SerializedScriptValue>,
@@ -183,12 +184,17 @@ class CORE_EXPORT DocumentLoader
navigation_type_ = navigation_type;
}
- void SetItemForHistoryNavigation(HistoryItem* item) { history_item_ = item; }
HistoryItem* GetHistoryItem() const { return history_item_; }
void StartLoading();
void StopLoading();
+ void CommitNavigation();
+
+ GlobalObjectReusePolicy GetGlobalObjectReusePolicy() const {
+ return global_object_reuse_policy_;
+ }
+
// Starts loading the response.
void StartLoadingResponse();
@@ -216,6 +222,10 @@ class CORE_EXPORT DocumentLoader
return client_hints_preferences_;
}
+ WebURLRequest::PreviewsState GetPreviewsState() const {
+ return previews_state_;
+ }
+
struct InitialScrollState {
DISALLOW_NEW();
InitialScrollState()
@@ -226,8 +236,6 @@ class CORE_EXPORT DocumentLoader
};
InitialScrollState& GetInitialScrollState() { return initial_scroll_state_; }
- bool WasBlockedAfterCSP() { return was_blocked_after_csp_; }
-
void DispatchLinkHeaderPreloads(const base::Optional<ViewportDescription>&,
PreloadHelper::MediaPreloadPolicy);
@@ -270,30 +278,18 @@ class CORE_EXPORT DocumentLoader
UseCounterHelper& GetUseCounterHelper() { return use_counter_; }
Dactyloscoper& GetDactyloscoper() { return dactyloscoper_; }
- int ErrorCode() const { return error_code_; }
-
- network::mojom::IPAddressSpace GetIPAddressSpace() const {
- return ip_address_space_;
- }
-
PrefetchedSignedExchangeManager* GetPrefetchedSignedExchangeManager() const;
// UseCounter
void CountUse(mojom::WebFeature) override;
void CountDeprecation(mojom::WebFeature) override;
- // The caller owns the |clock| which must outlive the DocumentLoader.
- void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; }
void SetApplicationCacheHostForTesting(ApplicationCacheHostForFrame* host) {
application_cache_host_ = host;
}
void SetLoadingJavaScriptUrl() { loading_url_as_javascript_ = true; }
- WebURLRequest::PreviewsState previews_state() const {
- return previews_state_;
- }
-
bool HadTransientActivation() const { return had_transient_activation_; }
bool IsBrowserInitiated() const { return is_browser_initiated_; }
@@ -303,6 +299,16 @@ class CORE_EXPORT DocumentLoader
// day though.
void UpdateUrlForDocumentOpen(const KURL& url) { url_ = url; }
+ enum class HistoryNavigationType {
+ kDifferentDocument,
+ kFragment,
+ kHistoryApi
+ };
+
+ void SetHistoryItemStateForCommit(HistoryItem* old_item,
+ WebFrameLoadType,
+ HistoryNavigationType);
+
protected:
Vector<KURL> redirect_chain_;
@@ -324,16 +330,12 @@ class CORE_EXPORT DocumentLoader
const scoped_refptr<const SecurityOrigin> initiator_origin,
Document* owner_document,
const AtomicString& mime_type,
- const AtomicString& encoding,
- ParserSynchronizationPolicy,
const KURL& overriding_url);
void DidInstallNewDocument(Document*);
void WillCommitNavigation();
- void DidCommitNavigation(GlobalObjectReusePolicy);
+ void DidCommitNavigation();
- void PrepareForNavigationCommit();
- void FinishNavigationCommit(const AtomicString& mime_type,
- const KURL& overriding_url = KURL());
+ void CreateParserPostCommit();
void CommitSameDocumentNavigationInternal(
const KURL&,
@@ -349,8 +351,6 @@ class CORE_EXPORT DocumentLoader
FrameLoader& GetFrameLoader() const;
LocalFrameClient& GetLocalFrameClient() const;
- void CommitData(const char* bytes, size_t length);
-
ContentSecurityPolicy* CreateCSP(
const ResourceResponse&,
const base::Optional<WebOriginPolicy>& origin_policy);
@@ -358,27 +358,18 @@ class CORE_EXPORT DocumentLoader
void FinishedLoading(base::TimeTicks finish_time);
void CancelLoadAfterCSPDenied(const ResourceResponse&);
- enum class HistoryNavigationType {
- kDifferentDocument,
- kFragment,
- kHistoryApi
- };
- void SetHistoryItemStateForCommit(HistoryItem* old_item,
- WebFrameLoadType,
- HistoryNavigationType);
-
void FinalizeMHTMLArchiveLoad();
void HandleRedirect(const KURL& current_request_url);
void HandleResponse();
- void HandleData(const char* data, size_t length);
void InitializeEmptyResponse();
bool ShouldReportTimingInfoToParent();
+ void CommitData(const char* bytes, size_t length);
// Processes the data stored in the data_buffer_, used to avoid appending data
// to the parser in a nested message loop.
- void ProcessDataBuffer();
+ void ProcessDataBuffer(const char* bytes = nullptr, size_t length = 0);
// Sends an intervention report if the page is being served as a preview.
void ReportPreviewsIntervention() const;
@@ -419,11 +410,11 @@ class CORE_EXPORT DocumentLoader
base::Optional<WebOriginPolicy> origin_policy_;
scoped_refptr<const SecurityOrigin> requestor_origin_;
KURL unreachable_url_;
- int error_code_;
std::unique_ptr<WebNavigationBodyLoader> body_loader_;
- base::UnguessableToken appcache_host_id_;
network::mojom::IPAddressSpace ip_address_space_ =
network::mojom::IPAddressSpace::kUnknown;
+ bool grant_load_local_resources_ = false;
+ base::Optional<blink::mojom::FetchCacheMode> force_fetch_cache_mode_;
// Params are saved in constructor and are cleared after StartLoading().
// TODO(dgozman): remove once StartLoading is merged with constructor.
@@ -451,6 +442,8 @@ class CORE_EXPORT DocumentLoader
ResourceResponse response_;
WebFrameLoadType load_type_;
+ GlobalObjectReusePolicy global_object_reuse_policy_ =
+ GlobalObjectReusePolicy::kCreateNew;
bool is_client_redirect_;
bool replaces_current_history_item_;
@@ -472,18 +465,17 @@ class CORE_EXPORT DocumentLoader
ClientHintsPreferences client_hints_preferences_;
InitialScrollState initial_scroll_state_;
- bool was_blocked_after_csp_;
+ bool was_blocked_by_csp_;
enum State { kNotStarted, kProvisional, kCommitted, kSentDidFinishLoad };
State state_;
// Used to block the parser.
int parser_blocked_count_ = 0;
- bool finished_loading_ = false;
- scoped_refptr<SharedBuffer> committed_data_buffer_;
+ bool finish_loading_when_parser_resumed_ = false;
- // Used to protect against reentrancy into dataReceived().
- bool in_data_received_;
+ // Used to protect against reentrancy into CommitData().
+ bool in_commit_data_;
scoped_refptr<SharedBuffer> data_buffer_;
base::UnguessableToken devtools_navigation_token_;
@@ -511,6 +503,7 @@ class CORE_EXPORT DocumentLoader
WebScopedVirtualTimePauser virtual_time_pauser_;
Member<SourceKeyedCachedMetadataHandler> cached_metadata_handler_;
Member<PrefetchedSignedExchangeManager> prefetched_signed_exchange_manager_;
+ KURL base_url_override_for_bundled_exchanges_;
// This UseCounterHelper tracks feature usage associated with the lifetime of
// the document load. Features recorded prior to commit will be recorded
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 42d53637e2c..06f85701308 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
@@ -37,11 +37,17 @@ class DocumentLoaderTest : public testing::Test {
}
void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
+ url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
}
+ class ScopedLoaderDelegate {
+ public:
+ ScopedLoaderDelegate(WebURLLoaderTestDelegate* delegate) {
+ url_test_helpers::SetLoaderDelegate(delegate);
+ }
+ ~ScopedLoaderDelegate() { url_test_helpers::SetLoaderDelegate(nullptr); }
+ };
+
WebLocalFrameImpl* MainFrame() { return web_view_helper_.LocalMainFrame(); }
frame_test_helpers::WebViewHelper web_view_helper_;
@@ -58,9 +64,8 @@ TEST_F(DocumentLoaderTest, SingleChunk) {
}
} delegate;
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(&delegate);
+ ScopedLoaderDelegate loader_delegate(&delegate);
frame_test_helpers::LoadFrame(MainFrame(), "https://example.com/foo.html");
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
// TODO(dcheng): How should the test verify that the original callback is
// invoked? The test currently still passes even if the test delegate
@@ -82,9 +87,8 @@ TEST_F(DocumentLoaderTest, MultiChunkNoReentrancy) {
}
} delegate;
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(&delegate);
+ ScopedLoaderDelegate loader_delegate(&delegate);
frame_test_helpers::LoadFrame(MainFrame(), "https://example.com/foo.html");
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
}
// Finally, test reentrant callbacks to DocumentLoader::BodyDataReceived().
@@ -171,13 +175,13 @@ TEST_F(DocumentLoaderTest, MultiChunkWithReentrancy) {
web_view_helper_.GetWebView()->GetPage()->GetSettings().SetPluginsEnabled(
true);
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(
- &main_frame_client);
- frame_test_helpers::LoadFrameDontWait(
- MainFrame(), url_test_helpers::ToKURL("https://example.com/foo.html"));
- main_frame_client.Serve();
- frame_test_helpers::PumpPendingRequestsForFrameToLoad(MainFrame());
- Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
+ {
+ ScopedLoaderDelegate loader_delegate(&main_frame_client);
+ frame_test_helpers::LoadFrameDontWait(
+ MainFrame(), url_test_helpers::ToKURL("https://example.com/foo.html"));
+ main_frame_client.Serve();
+ frame_test_helpers::PumpPendingRequestsForFrameToLoad(MainFrame());
+ }
// Sanity check that we did actually test reeentrancy.
EXPECT_TRUE(main_frame_client.ServedReentrantly());
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 dff1b8c8636..216a525da48 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -30,6 +30,7 @@
#include <memory>
#include "cc/layers/layer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h"
#include "third_party/blink/public/platform/platform.h"
@@ -105,7 +106,7 @@ void EmptyLocalFrameClient::BeginNavigation(
bool,
WebFrameLoadType,
bool,
- WebTriggeringEventInfo,
+ TriggeringEventInfo,
HTMLFormElement*,
ContentSecurityPolicyDisposition,
mojo::PendingRemote<mojom::blink::BlobURLToken>,
@@ -200,6 +201,11 @@ Frame* EmptyLocalFrameClient::FindFrame(const AtomicString& name) const {
return nullptr;
}
+AssociatedInterfaceProvider*
+EmptyLocalFrameClient::GetRemoteNavigationAssociatedInterfaces() {
+ return AssociatedInterfaceProvider::GetEmptyAssociatedInterfaceProvider();
+}
+
std::unique_ptr<WebServiceWorkerProvider>
EmptyLocalFrameClient::CreateServiceWorkerProvider() {
return nullptr;
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 bebb248e1d5..4d8d3f8c18b 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.h
@@ -169,17 +169,19 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
bool TabsToLinks() override { return false; }
void InvalidateRect(const IntRect&) override {}
- void ScheduleAnimation(const LocalFrameView*) override {}
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) override {}
IntRect ViewportToScreen(const IntRect& r,
const LocalFrameView*) const override {
return r;
}
- float WindowToViewportScalar(const float s) const override { return s; }
float WindowToViewportScalar(LocalFrame*, const float s) const override {
return s;
}
- WebScreenInfo GetScreenInfo() const override { return WebScreenInfo(); }
+ WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+ return WebScreenInfo();
+ }
void ContentsSizeChanged(LocalFrame*, const IntSize&) const override {}
void ShowMouseOverURL(const HitTestResult&) override {}
@@ -281,9 +283,6 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void DispatchDidCommitLoad(HistoryItem*,
WebHistoryCommitType,
GlobalObjectReusePolicy) override {}
- void DispatchDidFailProvisionalLoad(
- const ResourceError&,
- const AtomicString& http_method) override {}
void DispatchDidFailLoad(const ResourceError&,
WebHistoryCommitType) override {}
void DispatchDidFinishDocumentLoad() override {}
@@ -300,7 +299,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
bool,
WebFrameLoadType,
bool,
- WebTriggeringEventInfo,
+ TriggeringEventInfo,
HTMLFormElement*,
ContentSecurityPolicyDisposition,
mojo::PendingRemote<mojom::blink::BlobURLToken>,
@@ -319,8 +318,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void ForwardResourceTimingToParent(const WebResourceTimingInfo&) override {}
void DownloadURL(const ResourceRequest&,
- DownloadCrossOriginRedirects) override {}
- void LoadErrorPage(int reason) override {}
+ network::mojom::RedirectMode) override {}
DocumentLoader* CreateDocumentLoader(
LocalFrame*,
@@ -340,9 +338,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void TransitionToCommittedForNewPage() override {}
- bool NavigateBackForward(int offset, bool from_script) const override {
- return false;
- }
+ bool NavigateBackForward(int offset) const override { return false; }
void DidDisplayInsecureContent() override {}
void DidContainInsecureFormAction() override {}
void DidRunInsecureContent(const SecurityOrigin*, const KURL&) override {}
@@ -397,6 +393,9 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
return GetEmptyBrowserInterfaceBroker();
}
+ AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces()
+ override;
+
WebSpellCheckPanelHostClient* SpellCheckPanelHostClient() const override {
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/form_submission.cc b/chromium/third_party/blink/renderer/core/loader/form_submission.cc
index ccb7d076a0e..d5e9b3834bf 100644
--- a/chromium/third_party/blink/renderer/core/loader/form_submission.cc
+++ b/chromium/third_party/blink/renderer/core/loader/form_submission.cc
@@ -160,12 +160,12 @@ inline FormSubmission::FormSubmission(SubmitMethod method,
boundary_(boundary) {
if (event) {
triggering_event_info_ = event->isTrusted()
- ? WebTriggeringEventInfo::kFromTrustedEvent
- : WebTriggeringEventInfo::kFromUntrustedEvent;
+ ? TriggeringEventInfo::kFromTrustedEvent
+ : TriggeringEventInfo::kFromUntrustedEvent;
if (event->UnderlyingEvent())
event = event->UnderlyingEvent();
} else {
- triggering_event_info_ = WebTriggeringEventInfo::kNotFromEvent;
+ triggering_event_info_ = TriggeringEventInfo::kNotFromEvent;
}
navigation_policy_ = NavigationPolicyFromEvent(event);
}
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 519bdea77ec..7e4465a22cf 100644
--- a/chromium/third_party/blink/renderer/core/loader/form_submission.h
+++ b/chromium/third_party/blink/renderer/core/loader/form_submission.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FORM_SUBMISSION_H_
#include "base/macros.h"
-#include "third_party/blink/public/web/web_triggering_event_info.h"
+#include "third_party/blink/public/common/navigation/triggering_event_info.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/navigation_policy.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -47,7 +47,7 @@ class Event;
class HTMLFormControlElement;
class HTMLFormElement;
-class FormSubmission : public GarbageCollectedFinalized<FormSubmission> {
+class FormSubmission final : public GarbageCollected<FormSubmission> {
public:
enum SubmitMethod { kGetMethod, kPostMethod, kDialogMethod };
@@ -132,7 +132,7 @@ class FormSubmission : public GarbageCollectedFinalized<FormSubmission> {
scoped_refptr<EncodedFormData> form_data_;
String boundary_;
NavigationPolicy navigation_policy_;
- WebTriggeringEventInfo triggering_event_info_;
+ TriggeringEventInfo triggering_event_info_;
String result_;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 9b5ce27b7e1..753155f5628 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
@@ -38,6 +38,7 @@
#include "build/build_config.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
@@ -182,10 +183,21 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame) {
return mojom::FetchCacheMode::kDefault;
}
+// Simple function to add quotes to make headers strings.
+const AtomicString AddQuotes(std::string str) {
+ if (str.empty())
+ return AtomicString("");
+
+ StringBuilder quoted_string;
+ quoted_string.Append("\"");
+ quoted_string.Append(str.data());
+ quoted_string.Append("\"");
+ return quoted_string.ToAtomicString();
+}
+
} // namespace
-struct FrameFetchContext::FrozenState final
- : GarbageCollectedFinalized<FrozenState> {
+struct FrameFetchContext::FrozenState final : GarbageCollected<FrozenState> {
FrozenState(const KURL& url,
scoped_refptr<const SecurityOrigin> parent_security_origin,
const ContentSecurityPolicy* content_security_policy,
@@ -324,7 +336,9 @@ FrameFetchContext::GetPreviewsResourceLoadingHints() const {
}
WebURLRequest::PreviewsState FrameFetchContext::previews_state() const {
- return GetLocalFrameClient()->GetPreviewsStateForFrame();
+ DocumentLoader* document_loader = MasterDocumentLoader();
+ return document_loader ? document_loader->GetPreviewsState()
+ : WebURLRequest::kPreviewsUnspecified;
}
LocalFrame* FrameFetchContext::GetFrame() const {
@@ -411,11 +425,20 @@ void FrameFetchContext::PrepareRequest(
if (GetResourceFetcherProperties().IsDetached())
return;
- if (!frame_or_imported_document_->GetDocumentLoader()) {
- // When HTML imports are involved, it is dangerous to rely on the
- // factory bound origin.
- DCHECK(frame_or_imported_document_->GetDocument().ImportsController());
- request.SetShouldAlsoUseFactoryBoundOriginForCors(false);
+ DocumentLoader* document_loader = MasterDocumentLoader();
+ if (document_loader->ForceFetchCacheMode())
+ request.SetCacheMode(*document_loader->ForceFetchCacheMode());
+
+ if (request.GetPreviewsState() == WebURLRequest::kPreviewsUnspecified) {
+ WebURLRequest::PreviewsState request_previews_state =
+ document_loader->GetPreviewsState();
+ // The decision of whether or not to enable Client Lo-Fi is made earlier
+ // in the request lifetime, in LocalFrame::MaybeAllowImagePlaceholder(),
+ // so don't add the Client Lo-Fi bit to the request here.
+ request_previews_state &= ~(WebURLRequest::kLazyImageLoadDeferred);
+ if (request_previews_state == WebURLRequest::kPreviewsUnspecified)
+ request_previews_state = WebURLRequest::kPreviewsOff;
+ request.SetPreviewsState(request_previews_state);
}
GetLocalFrameClient()->DispatchWillSendRequest(request);
@@ -426,14 +449,13 @@ void FrameFetchContext::PrepareRequest(
WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
}
- probe::PrepareRequest(Probe(), MasterDocumentLoader(), request,
- initiator_info, resource_type);
+ probe::PrepareRequest(Probe(), document_loader, request, initiator_info,
+ resource_type);
// ServiceWorker hook ups.
- if (MasterDocumentLoader()->GetServiceWorkerNetworkProvider()) {
+ if (document_loader->GetServiceWorkerNetworkProvider()) {
WrappedResourceRequest webreq(request);
- MasterDocumentLoader()->GetServiceWorkerNetworkProvider()->WillSendRequest(
- webreq);
+ document_loader->GetServiceWorkerNetworkProvider()->WillSendRequest(webreq);
}
}
@@ -523,10 +545,10 @@ void FrameFetchContext::AddClientHintsIfNecessary(
result.Append(' ');
result.Append(version.data());
}
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUA)],
- result.ToAtomicString());
+ AddQuotes(result.ToString().Ascii()));
}
// If the frame is detached, then don't send any hints other than UA.
@@ -561,7 +583,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
resource_origin)) &&
ShouldSendClientHint(mojom::WebClientHintsType::kDeviceMemory,
hints_preferences, enabled_hints)) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
"Device-Memory",
AtomicString(String::Number(
ApproximatedDeviceMemory::GetApproximatedDeviceMemory())));
@@ -573,7 +595,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
mojom::FeaturePolicyFeature::kClientHintDPR, resource_origin)) &&
ShouldSendClientHint(mojom::WebClientHintsType::kDpr, hints_preferences,
enabled_hints)) {
- request.AddHttpHeaderField("DPR", AtomicString(String::Number(dpr)));
+ request.SetHttpHeaderField("DPR", AtomicString(String::Number(dpr)));
}
if ((!RuntimeEnabledFeatures::FeaturePolicyForClientHintsEnabled() ||
@@ -583,7 +605,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
hints_preferences, enabled_hints)) {
if (resource_width.is_set) {
float physical_width = resource_width.width * dpr;
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
"Width", AtomicString(String::Number(ceil(physical_width))));
}
}
@@ -595,7 +617,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
ShouldSendClientHint(mojom::WebClientHintsType::kViewportWidth,
hints_preferences, enabled_hints) &&
!GetResourceFetcherProperties().IsDetached() && GetFrame()->View()) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
"Viewport-Width",
AtomicString(String::Number(GetFrame()->View()->ViewportWidth())));
}
@@ -630,7 +652,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
uint32_t rtt =
GetNetworkStateNotifier().RoundRtt(request.Url().Host(), http_rtt);
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kRtt)],
AtomicString(String::Number(rtt)));
@@ -651,7 +673,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
double mbps = GetNetworkStateNotifier().RoundMbps(request.Url().Host(),
throughput_mbps);
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kDownlink)],
AtomicString(String::Number(mbps)));
@@ -668,7 +690,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
if (!holdback_ect)
holdback_ect = GetNetworkStateNotifier().EffectiveType();
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kEct)],
AtomicString(NetworkStateNotifier::EffectiveConnectionTypeToString(
@@ -681,7 +703,7 @@ void FrameFetchContext::AddClientHintsIfNecessary(
mojom::FeaturePolicyFeature::kClientHintLang, resource_origin))) &&
ShouldSendClientHint(mojom::WebClientHintsType::kLang, hints_preferences,
enabled_hints)) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kLang)],
GetFrame()
@@ -697,10 +719,10 @@ void FrameFetchContext::AddClientHintsIfNecessary(
resource_origin))) &&
ShouldSendClientHint(mojom::WebClientHintsType::kUAArch,
hints_preferences, enabled_hints)) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUAArch)],
- AtomicString(ua.architecture.data()));
+ AddQuotes(ua.architecture));
}
if ((can_always_send_hints ||
@@ -710,10 +732,10 @@ void FrameFetchContext::AddClientHintsIfNecessary(
resource_origin))) &&
ShouldSendClientHint(mojom::WebClientHintsType::kUAPlatform,
hints_preferences, enabled_hints)) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUAPlatform)],
- AtomicString(ua.platform.data()));
+ AddQuotes(ua.platform));
}
if ((can_always_send_hints ||
@@ -723,10 +745,10 @@ void FrameFetchContext::AddClientHintsIfNecessary(
resource_origin))) &&
ShouldSendClientHint(mojom::WebClientHintsType::kUAModel,
hints_preferences, enabled_hints)) {
- request.AddHttpHeaderField(
+ request.SetHttpHeaderField(
blink::kClientHintsHeaderMapping[static_cast<size_t>(
mojom::WebClientHintsType::kUAModel)],
- AtomicString(ua.model.data()));
+ AddQuotes(ua.model));
}
}
@@ -740,6 +762,9 @@ void FrameFetchContext::PopulateResourceRequest(
const ContentSecurityPolicy* csp = GetContentSecurityPolicy();
if (csp && csp->ShouldSendCSPHeader(type))
+ // TODO(crbug.com/993769): Test if this header returns duplicated values
+ // (i.e. "CSP: active, active") on asynchronous "stale-while-revalidate"
+ // revalidation requests and if this is unexpected behavior.
request.AddHttpHeaderField("CSP", "active");
}
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 245079bec77..419103ec905 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -34,7 +34,7 @@ n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/base_fetch_context.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
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 90afdb4cad3..f274d819471 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
@@ -1279,8 +1279,8 @@ TEST_F(FrameFetchContextTest, SetFirstPartyCookieWhenDetached) {
SetFirstPartyCookie(request);
- EXPECT_EQ(document_url, request.SiteForCookies());
- EXPECT_EQ(document_url.GetString(), request.SiteForCookies().GetString());
+ EXPECT_TRUE(SecurityOrigin::AreSameSchemeHostPort(document_url,
+ request.SiteForCookies()));
}
TEST_F(FrameFetchContextTest, TopFrameOrigin) {
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
index ee2eeb0c4d8..270ec3c90ff 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.cc
@@ -89,4 +89,15 @@ ClientRedirectPolicy FrameLoadRequest::ClientRedirect() const {
return ClientRedirectPolicy::kClientRedirect;
}
+bool FrameLoadRequest::CanDisplay(const KURL& url) const {
+ if (OriginDocument() &&
+ OriginDocument()->GetSecurityOrigin()->CanDisplay(url))
+ return true;
+
+ if (resource_request_.CanDisplay(url))
+ return true;
+
+ return false;
+}
+
} // namespace blink
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 1bafa6bc2f9..a68c671de7c 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_load_request.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -27,9 +27,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_LOAD_REQUEST_H_
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/navigation/triggering_event_info.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
-#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
@@ -41,6 +41,7 @@
namespace blink {
class HTMLFormElement;
+class KURL;
struct CORE_EXPORT FrameLoadRequest {
STACK_ALLOCATED();
@@ -79,11 +80,11 @@ struct CORE_EXPORT FrameLoadRequest {
navigation_policy_ = navigation_policy;
}
- WebTriggeringEventInfo TriggeringEventInfo() const {
+ TriggeringEventInfo GetTriggeringEventInfo() const {
return triggering_event_info_;
}
- void SetTriggeringEventInfo(WebTriggeringEventInfo info) {
- DCHECK(info != WebTriggeringEventInfo::kUnknown);
+ void SetTriggeringEventInfo(TriggeringEventInfo info) {
+ DCHECK(info != TriggeringEventInfo::kUnknown);
triggering_event_info_ = info;
}
@@ -139,6 +140,10 @@ struct CORE_EXPORT FrameLoadRequest {
resource_request_.ClearHTTPOrigin();
}
+ // Whether either OriginDocument, RequestorOrigin or IsolatedWorldOrigin can
+ // display the |url|,
+ bool CanDisplay(const KURL&) const;
+
private:
Member<Document> origin_document_;
ResourceRequest resource_request_;
@@ -146,8 +151,8 @@ struct CORE_EXPORT FrameLoadRequest {
ClientNavigationReason client_navigation_reason_ =
ClientNavigationReason::kNone;
NavigationPolicy navigation_policy_ = kNavigationPolicyCurrentTab;
- WebTriggeringEventInfo triggering_event_info_ =
- WebTriggeringEventInfo::kNotFromEvent;
+ TriggeringEventInfo triggering_event_info_ =
+ TriggeringEventInfo::kNotFromEvent;
Member<HTMLFormElement> form_;
ShouldSendReferrer should_send_referrer_;
ContentSecurityPolicyDisposition
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 1c862cf6101..e60598f9c8c 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -41,7 +41,10 @@
#include "base/auto_reset.h"
#include "base/unguessable_token.h"
+#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_remote.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/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h"
@@ -57,12 +60,13 @@
#include "third_party/blink/public/web/web_navigation_params.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
#include "third_party/blink/renderer/core/events/page_transition_event.h"
+#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/csp/navigation_initiator_impl.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"
@@ -110,6 +114,7 @@
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/network/network_utils.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/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -206,14 +211,10 @@ void FrameLoader::Init() {
frame_, kWebNavigationTypeOther, std::move(navigation_params),
nullptr /* extra_data */);
provisional_document_loader_->StartLoading();
- WillCommitNavigation();
- if (!DetachDocument())
- return;
- CommitDocumentLoader(provisional_document_loader_.Release());
-
- // Load the document if needed.
- document_loader_->StartLoadingResponse();
+ CommitDocumentLoader(provisional_document_loader_.Release(), base::nullopt,
+ false /* dispatch_did_start */, base::DoNothing::Once(),
+ false /* dispatch_did_commit */);
frame_->GetDocument()->CancelParsing();
@@ -243,9 +244,6 @@ void FrameLoader::SetDefersLoading(bool defers) {
}
void FrameLoader::SaveScrollAnchor() {
- if (!RuntimeEnabledFeatures::ScrollAnchorSerializationEnabled())
- return;
-
if (!document_loader_ || !document_loader_->GetHistoryItem() ||
!frame_->View())
return;
@@ -299,21 +297,20 @@ void FrameLoader::SaveScrollState() {
Client()->DidUpdateCurrentHistoryItem();
}
-void FrameLoader::DispatchUnloadEvent() {
+void FrameLoader::DispatchUnloadEvent(
+ SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>* timing) {
FrameNavigationDisabler navigation_disabler(*frame_);
SaveScrollState();
Document* document = frame_->GetDocument();
if (document && !SVGImage::IsInSVGImage(document)) {
- document->DispatchUnloadEvents(
- provisional_document_loader_
- ? &provisional_document_loader_->GetTiming()
- : nullptr);
+ document->DispatchUnloadEvents(committing_origin, timing);
// Remove event listeners if we're firing unload events for a reason other
// than committing a navigation. In the commit case, we'll determine whether
// event listeners should be retained when choosing whether to reuse the
// LocalDOMWindow.
- if (!provisional_document_loader_)
+ if (!timing)
document->RemoveAllEventListenersRecursively();
}
}
@@ -545,7 +542,7 @@ bool FrameLoader::AllowRequestForThisFrame(const FrameLoadRequest& request) {
return false;
}
- if (!request.OriginDocument()->GetSecurityOrigin()->CanDisplay(url)) {
+ if (!request.CanDisplay(url)) {
request.OriginDocument()->AddConsoleMessage(ConsoleMessage::Create(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kError,
@@ -598,8 +595,8 @@ static mojom::RequestContextType DetermineRequestContextFromNavigationType(
void FrameLoader::StartNavigation(const FrameLoadRequest& passed_request,
WebFrameLoadType frame_load_type) {
CHECK(!IsBackForwardLoadType(frame_load_type));
- DCHECK(passed_request.TriggeringEventInfo() !=
- WebTriggeringEventInfo::kUnknown);
+ DCHECK(passed_request.GetTriggeringEventInfo() !=
+ TriggeringEventInfo::kUnknown);
DCHECK(frame_->GetDocument());
if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
element->CancelPendingLazyLoad();
@@ -658,14 +655,14 @@ void FrameLoader::StartNavigation(const FrameLoadRequest& passed_request,
document_loader_->CommitSameDocumentNavigation(
url, frame_load_type, nullptr, request.ClientRedirect(),
origin_document,
- request.TriggeringEventInfo() != WebTriggeringEventInfo::kNotFromEvent,
+ request.GetTriggeringEventInfo() != TriggeringEventInfo::kNotFromEvent,
nullptr /* extra_data */);
return;
}
WebNavigationType navigation_type = DetermineNavigationType(
frame_load_type, resource_request.HttpBody() || request.Form(),
- request.TriggeringEventInfo() != WebTriggeringEventInfo::kNotFromEvent);
+ request.GetTriggeringEventInfo() != TriggeringEventInfo::kNotFromEvent);
resource_request.SetRequestContext(
DetermineRequestContextFromNavigationType(navigation_type));
request.SetFrameType(frame_->IsMainFrame()
@@ -770,7 +767,7 @@ void FrameLoader::StartNavigation(const FrameLoadRequest& passed_request,
nullptr /* document_loader */, navigation_type,
request.GetNavigationPolicy(), has_transient_activation, frame_load_type,
request.ClientRedirect() == ClientRedirectPolicy::kClientRedirect,
- request.TriggeringEventInfo(), request.Form(),
+ request.GetTriggeringEventInfo(), request.Form(),
request.ShouldCheckMainWorldContentSecurityPolicy(),
request.GetBlobURLToken(), request.GetInputStartTime(),
request.HrefTranslate().GetString(), std::move(initiator_csp),
@@ -876,8 +873,9 @@ void FrameLoader::CommitNavigation(
// TODO(dgozman): figure out the better place for this check
// to cancel lazy load both on start and commit. Perhaps
// CancelProvisionalLoaderForNewNavigation() is a good one.
- if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
- element->CancelPendingLazyLoad();
+ HTMLFrameOwnerElement* frame_owner = frame_->DeprecatedLocalOwner();
+ if (frame_owner)
+ frame_owner->CancelPendingLazyLoad();
navigation_params->frame_load_type = DetermineFrameLoadType(
navigation_params->url, navigation_params->http_method,
@@ -911,11 +909,16 @@ void FrameLoader::CommitNavigation(
navigation_params->frame_load_type,
!navigation_params->http_body.IsNull(), false /* have_event */);
- HistoryItem* history_item = nullptr;
- if (IsBackForwardLoadType(navigation_params->frame_load_type)) {
- history_item = navigation_params->history_item;
- DCHECK(history_item);
- }
+ // Keep track of the current Document HistoryItem as the new DocumentLoader
+ // might need to copy state from it. Note that the current DocumentLoader
+ // should always exist, as the initial empty document is committed through
+ // FrameLoader::Init.
+ DCHECK(!StateMachine()->CreatingInitialEmptyDocument());
+ HistoryItem* previous_history_item = GetDocumentLoader()->GetHistoryItem();
+
+ base::Optional<Document::UnloadEventTiming> unload_timing;
+ scoped_refptr<SecurityOrigin> security_origin =
+ SecurityOrigin::Create(navigation_params->url);
// TODO(dgozman): get rid of provisional document loader and most of the code
// below. We should probably call DocumentLoader::CommitNavigation directly.
@@ -923,36 +926,40 @@ void FrameLoader::CommitNavigation(
frame_, navigation_type, std::move(navigation_params),
std::move(extra_data));
+ FrameSwapScope frame_swap_scope(frame_owner);
+
{
base::AutoReset<bool> scoped_committing(&committing_navigation_, true);
- if (history_item)
- provisional_document_loader->SetItemForHistoryNavigation(history_item);
if (is_javascript_url)
provisional_document_loader->SetLoadingJavaScriptUrl();
progress_tracker_->ProgressStarted();
provisional_document_loader_ = provisional_document_loader;
frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
- {
- FrameNavigationDisabler navigation_disabler(*frame_);
- Client()->DispatchDidStartProvisionalLoad(provisional_document_loader_);
- }
probe::DidStartProvisionalLoad(frame_);
virtual_time_pauser_.PauseVirtualTime();
provisional_document_loader_->StartLoading();
- WillCommitNavigation();
-
- if (!DetachDocument())
+ virtual_time_pauser_.UnpauseVirtualTime();
+ DCHECK(Client()->HasWebView());
+ if (!DetachDocument(security_origin.get(), &unload_timing))
return;
}
- std::move(call_before_attaching_new_document).Run();
+ tls_version_warning_origins_.clear();
- CommitDocumentLoader(provisional_document_loader_.Release());
+ // Following the call to StartLoading, the provisional DocumentLoader state
+ // has taken into account all redirects that happened during navigation. Its
+ // HistoryItem can be properly updated for the commit, using the HistoryItem
+ // of the previous Document.
+ provisional_document_loader_->SetHistoryItemStateForCommit(
+ previous_history_item, provisional_document_loader_->LoadType(),
+ DocumentLoader::HistoryNavigationType::kDifferentDocument);
- // Load the document if needed.
- document_loader_->StartLoadingResponse();
+ CommitDocumentLoader(provisional_document_loader_.Release(), unload_timing,
+ true /* dispatch_did_start */,
+ std::move(call_before_attaching_new_document),
+ !is_javascript_url /* dispatch_did_commit */);
TakeObjectSnapshot();
}
@@ -965,7 +972,6 @@ bool FrameLoader::WillStartNavigation(const WebNavigationInfo& info,
progress_tracker_->ProgressStarted();
client_navigation_ = std::make_unique<ClientNavigationState>();
client_navigation_->url = info.url_request.Url();
- client_navigation_->http_method = info.url_request.HttpMethod();
client_navigation_->is_history_navigation_in_new_frame =
is_history_navigation_in_new_frame;
frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
@@ -1012,7 +1018,9 @@ void FrameLoader::DidAccessInitialDocument() {
}
}
-bool FrameLoader::DetachDocument() {
+bool FrameLoader::DetachDocument(
+ SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>* timing) {
PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
DocumentLoader* pdl = provisional_document_loader_;
@@ -1031,7 +1039,7 @@ bool FrameLoader::DetachDocument() {
IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
frame_->GetDocument());
if (document_loader_)
- DispatchUnloadEvent();
+ DispatchUnloadEvent(committing_origin, timing);
frame_->DetachChildren();
// The previous calls to dispatchUnloadEvent() and detachChildren() can
// execute arbitrary script via things like unload events. If the executed
@@ -1065,29 +1073,56 @@ bool FrameLoader::DetachDocument() {
return true;
}
-void FrameLoader::WillCommitNavigation() {
- DCHECK(Client()->HasWebView());
+void FrameLoader::CommitDocumentLoader(
+ DocumentLoader* document_loader,
+ const base::Optional<Document::UnloadEventTiming>& unload_timing,
+ bool dispatch_did_start,
+ base::OnceClosure call_before_attaching_new_document,
+ bool dispatch_did_commit) {
+ document_loader_ = document_loader;
+ CHECK(document_loader_);
- // Check if the destination page is allowed to access the previous page's
- // timing information.
- if (frame_->GetDocument()) {
- scoped_refptr<const SecurityOrigin> security_origin =
- SecurityOrigin::Create(provisional_document_loader_->Url());
- provisional_document_loader_->GetTiming()
- .SetHasSameOriginAsPreviousDocument(
- security_origin->CanRequest(frame_->GetDocument()->Url()));
+ // Update the DocumentLoadTiming with the timings from the previous document
+ // unload event.
+ if (unload_timing.has_value()) {
+ document_loader_->GetTiming().SetHasSameOriginAsPreviousDocument(true);
+ document_loader_->GetTiming().MarkUnloadEventStart(
+ unload_timing->unload_event_start);
+ document_loader_->GetTiming().MarkUnloadEventEnd(
+ unload_timing->unload_event_end);
}
- virtual_time_pauser_.UnpauseVirtualTime();
-}
-void FrameLoader::CommitDocumentLoader(DocumentLoader* document_loader) {
- document_loader_ = document_loader;
- CHECK(document_loader_);
document_loader_->MarkAsCommitted();
TakeObjectSnapshot();
Client()->TransitionToCommittedForNewPage();
+
+ document_loader_->CommitNavigation();
+
+ {
+ FrameNavigationDisabler navigation_disabler(*frame_);
+ // TODO(https://crbug.com/855189): replace DispatchDidStartProvisionalLoad,
+ // call_before_attaching_new_document and DispatchDidCommitLoad with a
+ // single call.
+ if (dispatch_did_start)
+ Client()->DispatchDidStartProvisionalLoad(document_loader_);
+ std::move(call_before_attaching_new_document).Run();
+ Client()->DidCreateNewDocument();
+ if (dispatch_did_commit) {
+ // TODO(https://crbug.com/855189): Do not make exceptions
+ // for javascript urls.
+ Client()->DispatchDidCommitLoad(
+ document_loader_->GetHistoryItem(),
+ DocumentLoader::LoadTypeToCommitType(document_loader_->LoadType()),
+ document_loader_->GetGlobalObjectReusePolicy());
+ }
+ // TODO(dgozman): make DidCreateScriptContext notification call currently
+ // triggered by installing new document happen here, after commit.
+ }
+
+ // Load the document if needed.
+ document_loader_->StartLoadingResponse();
}
void FrameLoader::RestoreScrollPositionAndViewState() {
@@ -1151,13 +1186,11 @@ void FrameLoader::RestoreScrollPositionAndViewState(
if (should_restore_scroll) {
// TODO(pnoland): attempt to restore the anchor in more places than this.
// Anchor-based restore should allow for earlier restoration.
- bool did_restore =
- RuntimeEnabledFeatures::ScrollAnchorSerializationEnabled() &&
- view->LayoutViewport()->RestoreScrollAnchor(
- {view_state.scroll_anchor_data_.selector_,
- LayoutPoint(view_state.scroll_anchor_data_.offset_.x,
- view_state.scroll_anchor_data_.offset_.y),
- view_state.scroll_anchor_data_.simhash_});
+ bool did_restore = view->LayoutViewport()->RestoreScrollAnchor(
+ {view_state.scroll_anchor_data_.selector_,
+ LayoutPoint(view_state.scroll_anchor_data_.offset_.x,
+ view_state.scroll_anchor_data_.offset_.y),
+ view_state.scroll_anchor_data_.simhash_});
if (!did_restore) {
view->LayoutViewport()->SetScrollOffset(view_state.scroll_offset_,
kProgrammaticScroll);
@@ -1412,8 +1445,10 @@ bool FrameLoader::ShouldReuseDefaultView(
// be considered when deciding whether to reuse it.
// Spec:
// https://html.spec.whatwg.org/C/#initialise-the-document-object
- if (csp && (csp->GetSandboxMask() & WebSandboxFlags::kOrigin) !=
- WebSandboxFlags::kNone) {
+ if ((csp && (csp->GetSandboxMask() & WebSandboxFlags::kOrigin) !=
+ WebSandboxFlags::kNone) ||
+ ((EffectiveSandboxFlags() & WebSandboxFlags::kOrigin) !=
+ WebSandboxFlags::kNone)) {
return false;
}
@@ -1457,9 +1492,10 @@ void FrameLoader::CancelClientNavigation() {
if (!client_navigation_)
return;
ResourceError error = ResourceError::CancelledError(client_navigation_->url);
- AtomicString http_method = client_navigation_->http_method;
ClearClientNavigation();
- Client()->DispatchDidFailProvisionalLoad(error, http_method);
+ if (WebPluginContainerImpl* plugin = frame_->GetWebPluginContainer())
+ plugin->DidFailLoading(error);
+ Client()->AbortClientNavigation();
}
void FrameLoader::DispatchDocumentElementAvailable() {
@@ -1548,6 +1584,76 @@ void FrameLoader::ModifyRequestForCSP(
document_for_logging, frame_type);
}
+void FrameLoader::ReportLegacyTLSVersion(const KURL& url,
+ bool is_subresource,
+ bool is_ad_resource) {
+ document_loader_->GetUseCounterHelper().Count(
+ is_subresource
+ ? WebFeature::kLegacyTLSVersionInSubresource
+ : (frame_->Tree().Parent()
+ ? WebFeature::kLegacyTLSVersionInSubframeMainResource
+ : WebFeature::kLegacyTLSVersionInMainFrameResource),
+ frame_.Get());
+
+ // For non-main-frame loads, we have to use the main frame's document for
+ // the UKM recorder and source ID.
+ auto& root = frame_->LocalFrameRoot();
+ ukm::builders::Net_LegacyTLSVersion(root.GetDocument()->UkmSourceID())
+ .SetIsMainFrame(frame_->IsMainFrame())
+ .SetIsSubresource(is_subresource)
+ .SetIsAdResource(is_ad_resource)
+ .Record(root.GetDocument()->UkmRecorder());
+
+ // Web tests use an outdated server on macOS. See https://crbug.com/936515.
+#if defined(OS_MACOSX)
+ if (WebTestSupport::IsRunningWebTest())
+ return;
+#endif
+
+ String origin = SecurityOrigin::Create(url)->ToString();
+ // To prevent log spam, only log the message once per origin.
+ if (tls_version_warning_origins_.Contains(origin))
+ return;
+
+ // After |kMaxSecurityWarningMessages| warnings, stop printing messages to the
+ // console. At exactly |kMaxSecurityWarningMessages| warnings, print a message
+ // that additional resources on the page use legacy certificates without
+ // specifying which exact resources. Before |kMaxSecurityWarningMessages|
+ // messages, print the exact resource URL in the message to help the developer
+ // pinpoint the problematic resources.
+ const size_t kMaxSecurityWarningMessages = 10;
+ size_t num_warnings = tls_version_warning_origins_.size();
+ if (num_warnings > kMaxSecurityWarningMessages)
+ return;
+
+ String console_message;
+ if (num_warnings == kMaxSecurityWarningMessages) {
+ console_message =
+ "Additional resources on this page were loaded with TLS 1.0 or TLS "
+ "1.1, which are deprecated and will be disabled in the future. Once "
+ "disabled, users will be prevented from loading these resources. "
+ "Servers should enable TLS 1.2 or later. See "
+ "https://www.chromestatus.com/feature/5654791610957824 for more "
+ "information.";
+ } else {
+ console_message =
+ "The connection used to load resources from " + origin +
+ " used TLS 1.0 or TLS "
+ "1.1, which are deprecated and will be disabled in the future. Once "
+ "disabled, users will be prevented from loading these resources. The "
+ "server should enable TLS 1.2 or later. See "
+ "https://www.chromestatus.com/feature/5654791610957824 for more "
+ "information.";
+ }
+ tls_version_warning_origins_.insert(origin);
+ // To avoid spamming the console, use verbose message level for subframe
+ // resources, and only use the warning level for main-frame resources.
+ frame_->Console().AddMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kOther,
+ frame_->IsMainFrame() ? mojom::ConsoleMessageLevel::kWarning
+ : mojom::ConsoleMessageLevel::kVerbose,
+ console_message));
+}
void FrameLoader::RecordLatestRequiredCSP() {
required_csp_ =
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader.h b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
index b13f954a08b..c16d98c82a5 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.h
@@ -38,12 +38,13 @@
#include "base/bind_helpers.h"
#include "base/macros.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.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#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"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/loader/frame_loader_state_machine.h"
@@ -57,7 +58,6 @@
namespace blink {
class ContentSecurityPolicy;
-class Document;
class DocumentLoader;
class LocalFrame;
class Frame;
@@ -160,6 +160,9 @@ class CORE_EXPORT FrameLoader final {
const FetchClientSettingsObject* fetch_client_settings_object,
Document* document_for_logging,
network::mojom::RequestContextFrameType) const;
+ void ReportLegacyTLSVersion(const KURL& url,
+ bool is_subresource,
+ bool is_ad_resource);
Frame* Opener();
void SetOpener(LocalFrame*);
@@ -180,12 +183,23 @@ class CORE_EXPORT FrameLoader final {
// This will attempt to detach the current document. It will dispatch unload
// events and abort XHR requests. Returns true if the frame is ready to
// receive the next document commit, or false otherwise.
- bool DetachDocument();
+ bool DetachDocument(SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>*);
FrameLoaderStateMachine* StateMachine() const { return &state_machine_; }
bool ShouldClose(bool is_reload = false);
- void DispatchUnloadEvent();
+
+ // Dispatches the Unload event for the current document. If this is due to the
+ // commit of a navigation, both |committing_origin| and the
+ // Optional<Document::UnloadEventTiming>* should be non null.
+ // |committing_origin| is the origin of the document that is being committed.
+ // If it is allowed to access the unload timings of the current document, the
+ // Document::UnloadEventTiming will be created and populated.
+ // If the dispatch of the unload event is not due to a commit, both parameters
+ // should be null.
+ void DispatchUnloadEvent(SecurityOrigin* committing_origin,
+ base::Optional<Document::UnloadEventTiming>*);
bool AllowPlugins(ReasonForCallingAllowPlugins);
@@ -248,10 +262,13 @@ class CORE_EXPORT FrameLoader final {
std::unique_ptr<TracedValue> ToTracedValue() const;
void TakeObjectSnapshot() const;
- void WillCommitNavigation();
-
// Commits the given |document_loader|.
- void CommitDocumentLoader(DocumentLoader* document_loader);
+ void CommitDocumentLoader(
+ DocumentLoader* document_loader,
+ const base::Optional<Document::UnloadEventTiming>&,
+ bool dispatch_did_start,
+ base::OnceClosure call_before_attaching_new_document,
+ bool dispatch_did_commit);
LocalFrameClient* Client() const;
@@ -278,7 +295,6 @@ class CORE_EXPORT FrameLoader final {
// is either committed or cancelled.
struct ClientNavigationState {
KURL url;
- AtomicString http_method;
bool is_history_navigation_in_new_frame = false;
};
std::unique_ptr<ClientNavigationState> client_navigation_;
@@ -295,6 +311,10 @@ class CORE_EXPORT FrameLoader final {
Member<ContentSecurityPolicy> last_origin_document_csp_;
+ // The origins for which a legacy TLS version warning has been printed. The
+ // size of this set is capped, after which no more warnings are printed.
+ HashSet<String> tls_version_warning_origins_;
+
DISALLOW_COPY_AND_ASSIGN(FrameLoader);
};
diff --git a/chromium/third_party/blink/renderer/core/loader/frame_loader_state_machine.h b/chromium/third_party/blink/renderer/core/loader/frame_loader_state_machine.h
index 4e73e2d832c..2134e534f6a 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader_state_machine.h
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader_state_machine.h
@@ -46,9 +46,7 @@ class CORE_EXPORT FrameLoaderStateMachine {
public:
FrameLoaderStateMachine();
- // Once a load has been committed, the state may alternate between
- // CommittedFirstRealLoad and FirstLayoutDone. Otherwise, the states only go
- // down the list.
+ // The states only go down the list.
enum State {
kCreatingInitialEmptyDocument,
kDisplayingInitialEmptyDocument,
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 d9eefe681f2..5d29c48f099 100644
--- a/chromium/third_party/blink/renderer/core/loader/history_item.h
+++ b/chromium/third_party/blink/renderer/core/loader/history_item.h
@@ -48,8 +48,7 @@ namespace mojom {
enum class FetchCacheMode : int32_t;
} // namespace mojom
-class CORE_EXPORT HistoryItem final
- : public GarbageCollectedFinalized<HistoryItem> {
+class CORE_EXPORT HistoryItem final : public GarbageCollected<HistoryItem> {
public:
static HistoryItem* Create() { return MakeGarbageCollected<HistoryItem>(); }
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 099bf72fa83..c77f1c1ccf3 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,7 @@
#include "third_party/blink/renderer/core/loader/http_refresh_scheduler.h"
#include <memory>
+#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"
#include "third_party/blink/renderer/core/frame/local_frame.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 d1cd38572ff..5381292e363 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
@@ -46,7 +46,7 @@
namespace blink {
class CORE_EXPORT HttpRefreshScheduler final
- : public GarbageCollectedFinalized<HttpRefreshScheduler> {
+ : public GarbageCollected<HttpRefreshScheduler> {
public:
explicit HttpRefreshScheduler(Document*);
~HttpRefreshScheduler() = default;
diff --git a/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc b/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
index a0348835352..dd1f4ce89cd 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
@@ -18,6 +18,7 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
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 ebf87852118..9325a9d9360 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
@@ -23,7 +23,7 @@ class ResourceFetcher;
// seconds, and a network idle signal when there are 0 network connections
// active in 0.5 seconds.
class CORE_EXPORT IdlenessDetector
- : public GarbageCollectedFinalized<IdlenessDetector>,
+ : public GarbageCollected<IdlenessDetector>,
public base::sequence_manager::TaskTimeObserver {
public:
IdlenessDetector(
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 d05186315fb..a285b86dee8 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.cc
@@ -486,7 +486,7 @@ void ImageLoader::DoUpdateFromElement(
resource_request.SetReferrerPolicy(referrer_policy);
// Correct the RequestContext if necessary.
- if (IsHTMLPictureElement(GetElement()->parentNode()) ||
+ if (IsA<HTMLPictureElement>(GetElement()->parentNode()) ||
!GetElement()->FastGetAttribute(html_names::kSrcsetAttr).IsNull()) {
resource_request.SetRequestContext(mojom::RequestContextType::IMAGE_SET);
} else if (IsHTMLObjectElement(GetElement())) {
@@ -521,13 +521,9 @@ void ImageLoader::DoUpdateFromElement(
if (update_behavior != kUpdateForcedReload &&
lazy_image_load_state_ == LazyImageLoadState::kNone) {
const auto* frame = document.GetFrame();
- if (frame->IsClientLoFiAllowed(params.GetResourceRequest())) {
- params.SetClientLoFiPlaceholder();
- } else if (auto* html_image = ToHTMLImageElementOrNull(GetElement())) {
- const LazyImageHelper::Eligibility lazy_image_eligibility =
- LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
- *frame, html_image, params.Url());
- switch (lazy_image_eligibility) {
+ if (auto* html_image = ToHTMLImageElementOrNull(GetElement())) {
+ switch (LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
+ *frame, html_image, params.Url())) {
case LazyImageHelper::Eligibility::kEnabledFullyDeferred:
lazy_image_load_state_ = LazyImageLoadState::kDeferred;
was_fully_deferred_ = true;
@@ -555,7 +551,7 @@ void ImageLoader::DoUpdateFromElement(
}
if (lazy_image_load_state_ == LazyImageLoadState::kDeferred &&
- was_fully_deferred_) {
+ was_fully_deferred_ && !ShouldLoadImmediately(url)) {
// TODO(rajendrant): Remove this temporary workaround of creating a 1x1
// placeholder to fix an intersection observer issue not firing with
// certain styles (https://crbug.com/992765). Instead
@@ -792,10 +788,6 @@ void ImageLoader::ImageNotifyFinished(ImageResourceContent* resource) {
image_complete_ = true;
delay_until_image_notify_finished_ = nullptr;
- // Update ImageAnimationPolicy for image_content_.
- if (image_content_)
- image_content_->UpdateImageAnimationPolicy();
-
UpdateLayoutObject();
if (image_content_ && image_content_->HasImage()) {
diff --git a/chromium/third_party/blink/renderer/core/loader/image_loader.h b/chromium/third_party/blink/renderer/core/loader/image_loader.h
index ffea35f5fd3..f60beba5f22 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.h
@@ -38,13 +38,14 @@
namespace blink {
-class IncrementLoadEventDelayCount;
+class ContainerNode;
class Element;
-class LayoutImageResource;
class ExceptionState;
+class IncrementLoadEventDelayCount;
+class LayoutImageResource;
class ScriptState;
-class CORE_EXPORT ImageLoader : public GarbageCollectedFinalized<ImageLoader>,
+class CORE_EXPORT ImageLoader : public GarbageCollected<ImageLoader>,
public ImageResourceObserver {
USING_PRE_FINALIZER(ImageLoader, Dispose);
diff --git a/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc b/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc
index d2a836df313..d7632a200d1 100644
--- a/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc
+++ b/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/loader/importance_attribute.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/loader/importance_attribute.h b/chromium/third_party/blink/renderer/core/loader/importance_attribute.h
index 92f8aa29a60..a249c4e1617 100644
--- a/chromium/third_party/blink/renderer/core/loader/importance_attribute.h
+++ b/chromium/third_party/blink/renderer/core/loader/importance_attribute.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IMPORTANCE_ATTRIBUTE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IMPORTANCE_ATTRIBUTE_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/loader/interactive_detector.h b/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
index ffe5ca4a151..a7c7cdd1e32 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -35,7 +35,7 @@ class Event;
// TODO(crbug.com/631203): This class currently only detects Time to
// Interactive. Implement First Idle.
class CORE_EXPORT InteractiveDetector
- : public GarbageCollectedFinalized<InteractiveDetector>,
+ : public GarbageCollected<InteractiveDetector>,
public Supplement<Document>,
public ContextLifecycleObserver,
public LongTaskObserver {
diff --git a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
index a09a7e4fb78..6bebd70c71e 100644
--- a/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/lazy_image_helper.cc
@@ -62,6 +62,15 @@ void StartMonitoringVisibility(HTMLImageElement* html_image) {
}
}
+bool IsFullyLoadableFirstKImageAndDecrementCount(
+ HTMLImageElement* image_element) {
+ Document* document = GetRootDocumentOrNull(image_element);
+ if (!document)
+ return true;
+ return document->EnsureLazyLoadImageObserver()
+ .IsFullyLoadableFirstKImageAndDecrementCount();
+}
+
} // namespace
// static
@@ -103,6 +112,8 @@ LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
const auto lazy_load_image_setting = frame.GetLazyLoadImageSetting();
LoadingAttrValue loading_attr = GetLoadingAttrValue(*html_image);
+ bool is_fully_loadable =
+ IsFullyLoadableFirstKImageAndDecrementCount(html_image);
if (loading_attr == LoadingAttrValue::kLazy) {
StartMonitoringVisibility(html_image);
UseCounter::Count(frame.GetDocument(),
@@ -153,8 +164,9 @@ LazyImageHelper::DetermineEligibilityAndTrackVisibilityMetrics(
StartMonitoringVisibility(html_image);
- if (lazy_load_image_setting ==
- LocalFrame::LazyLoadImageSetting::kEnabledAutomatic) {
+ if (!is_fully_loadable &&
+ lazy_load_image_setting ==
+ LocalFrame::LazyLoadImageSetting::kEnabledAutomatic) {
// Automatic lazyload
if (!RuntimeEnabledFeatures::LazyImageLoadingMetadataFetchEnabled() ||
IsDimensionAbsoluteLarge(*html_image)) {
diff --git a/chromium/third_party/blink/renderer/core/loader/link_load_parameters.cc b/chromium/third_party/blink/renderer/core/loader/link_load_parameters.cc
index 0bc29e534f3..b5fa4e97838 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_load_parameters.cc
+++ b/chromium/third_party/blink/renderer/core/loader/link_load_parameters.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/loader/link_load_parameters.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/link_header.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/loader/link_load_parameters.h b/chromium/third_party/blink/renderer/core/loader/link_load_parameters.h
index ce2c3a00d7c..88a98bc00dd 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_load_parameters.h
+++ b/chromium/third_party/blink/renderer/core/loader/link_load_parameters.h
@@ -5,7 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_LINK_LOAD_PARAMETERS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_LINK_LOAD_PARAMETERS_H_
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/core/html/link_rel_attribute.h"
@@ -43,6 +45,7 @@ struct CORE_EXPORT LinkLoadParameters {
KURL href;
String image_srcset;
String image_sizes;
+ base::Optional<base::UnguessableToken> recursive_prefetch_token;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/link_loader.cc b/chromium/third_party/blink/renderer/core/loader/link_loader.cc
index e0add05d6a8..f1128cb94bd 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader.cc
@@ -82,7 +82,7 @@ LinkLoader* LinkLoader::Create(LinkLoaderClient* client) {
}
class LinkLoader::FinishObserver final
- : public GarbageCollectedFinalized<LinkLoader::FinishObserver>,
+ : public GarbageCollected<LinkLoader::FinishObserver>,
public ResourceFinishObserver {
USING_GARBAGE_COLLECTED_MIXIN(FinishObserver);
USING_PRE_FINALIZER(FinishObserver, ClearResource);
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 b18063ba20e..3e68c885729 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
@@ -32,7 +32,7 @@ namespace blink {
namespace {
class MockLinkLoaderClient final
- : public GarbageCollectedFinalized<MockLinkLoaderClient>,
+ : public GarbageCollected<MockLinkLoaderClient>,
public LinkLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(MockLinkLoaderClient);
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 a5d51574c08..d0bbcb27424 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
@@ -5,6 +5,9 @@
#include "third_party/blink/renderer/core/loader/loader_factory_for_frame.h"
#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/platform.h"
@@ -41,9 +44,13 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
WrappedResourceRequest webreq(request);
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory;
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory;
if (options.url_loader_factory) {
- options.url_loader_factory->data->Clone(MakeRequest(&url_loader_factory));
+ mojo::Remote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory_remote(std::move(options.url_loader_factory->data));
+ url_loader_factory_remote->Clone(
+ url_loader_factory.InitWithNewPipeAndPassReceiver());
}
// Resolve any blob: URLs that haven't been resolved yet. The XHR and
// fetch() API implementations resolve blob URLs earlier because there can
@@ -65,7 +72,7 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
if (request.Url().ProtocolIs("blob") && !url_loader_factory &&
request.GetRequestContext() != mojom::RequestContextType::SHARED_WORKER) {
frame_or_imported_document_->GetDocument().GetPublicURLManager().Resolve(
- request.Url(), MakeRequest(&url_loader_factory));
+ request.Url(), url_loader_factory.InitWithNewPipeAndPassReceiver());
}
LocalFrame& frame = frame_or_imported_document_->GetFrame();
FrameScheduler* frame_scheduler = frame.GetFrameScheduler();
@@ -78,7 +85,7 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForFrame::CreateURLLoader(
// resource loader handle's task runner.
if (url_loader_factory) {
return Platform::Current()
- ->WrapURLLoaderFactory(url_loader_factory.PassInterface().PassHandle())
+ ->WrapURLLoaderFactory(url_loader_factory.PassPipe())
->CreateURLLoader(
webreq, frame_scheduler->CreateResourceLoadingTaskRunnerHandle());
}
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 7707005c771..1e5089d1b52 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
@@ -4,6 +4,9 @@
#include "third_party/blink/renderer/core/loader/loader_factory_for_worker.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
@@ -26,9 +29,13 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForWorker::CreateURLLoader(
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
WrappedResourceRequest wrapped(request);
- network::mojom::blink::URLLoaderFactoryPtr url_loader_factory;
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory;
if (options.url_loader_factory) {
- options.url_loader_factory->data->Clone(MakeRequest(&url_loader_factory));
+ mojo::Remote<network::mojom::blink::URLLoaderFactory>
+ url_loader_factory_remote(std::move(options.url_loader_factory->data));
+ url_loader_factory_remote->Clone(
+ url_loader_factory.InitWithNewPipeAndPassReceiver());
}
// Resolve any blob: URLs that haven't been resolved yet. The XHR and
// fetch() API implementations resolve blob URLs earlier because there can
@@ -38,12 +45,11 @@ std::unique_ptr<WebURLLoader> LoaderFactoryForWorker::CreateURLLoader(
// simplest.
if (request.Url().ProtocolIs("blob") && !url_loader_factory) {
global_scope_->GetPublicURLManager().Resolve(
- request.Url(), MakeRequest(&url_loader_factory));
+ request.Url(), url_loader_factory.InitWithNewPipeAndPassReceiver());
}
if (url_loader_factory) {
- return web_context_
- ->WrapURLLoaderFactory(url_loader_factory.PassInterface().PassHandle())
+ return web_context_->WrapURLLoaderFactory(url_loader_factory.PassPipe())
->CreateURLLoader(wrapped, CreateTaskRunnerHandle(task_runner));
}
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 98269ca263f..efb1675d751 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
@@ -27,7 +27,7 @@ class CORE_EXPORT LongTaskObserver : public GarbageCollectedMixin {
// of LongTaskObservers drop to zero it automatically removes itself as a
// TaskTimeObserver.
class CORE_EXPORT LongTaskDetector final
- : public GarbageCollectedFinalized<LongTaskDetector>,
+ : public GarbageCollected<LongTaskDetector>,
public base::sequence_manager::TaskTimeObserver {
public:
static LongTaskDetector& Instance();
diff --git a/chromium/third_party/blink/renderer/core/loader/long_task_detector_test.cc b/chromium/third_party/blink/renderer/core/loader/long_task_detector_test.cc
index 3690034731a..deacc8ae18b 100644
--- a/chromium/third_party/blink/renderer/core/loader/long_task_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/long_task_detector_test.cc
@@ -15,7 +15,7 @@ namespace {
class TestLongTaskObserver :
// This has to be garbage collected since LongTaskObserver uses
// GarbageCollectedMixin.
- public GarbageCollectedFinalized<TestLongTaskObserver>,
+ public GarbageCollected<TestLongTaskObserver>,
public LongTaskObserver {
USING_GARBAGE_COLLECTED_MIXIN(TestLongTaskObserver);
diff --git a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
index d103a0a56b8..868e662e88e 100644
--- a/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -765,7 +765,7 @@ ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutFetchAutoupgrade(
const KURL& mixed_content_url) {
String message = String::Format(
"Mixed Content: The page at '%s' was loaded over HTTPS, but requested an "
- "insecure element '%s'. As part of an experiment this request was "
+ "insecure element '%s'. This request was "
"automatically upgraded to HTTPS, For more information see "
"https://chromium.googlesource.com/chromium/src/+/master/docs/security/"
"autoupgrade-mixed.md",
@@ -782,8 +782,8 @@ MixedContentChecker::CreateConsoleMessageAboutWebSocketAutoupgrade(
const KURL& mixed_content_url) {
String message = String::Format(
"Mixed Content: The page at '%s' was loaded over HTTPS, but attempted "
- "to connect to the insecure WebSocket endpoint '%s'. As part of an "
- "experiment this request was automatically upgraded to HTTPS, For more "
+ "to connect to the insecure WebSocket endpoint '%s'. "
+ "This request was automatically upgraded to HTTPS, For more "
"information see "
"https://chromium.googlesource.com/chromium/src/+/master/docs/security/"
"autoupgrade-mixed.md",
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
index 4ca66cbbafd..35ee3d74587 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
@@ -16,7 +16,7 @@ namespace blink {
// workers. We should rename this to something like ModuleScriptFetcherImpl that
// doesn't relate to Document.
class CORE_EXPORT DocumentModuleScriptFetcher final
- : public GarbageCollectedFinalized<DocumentModuleScriptFetcher>,
+ : public GarbageCollected<DocumentModuleScriptFetcher>,
public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(DocumentModuleScriptFetcher);
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
index b4e8abdcfb6..d1976649db4 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
@@ -15,7 +15,9 @@ namespace blink {
InstalledServiceWorkerModuleScriptFetcher::
InstalledServiceWorkerModuleScriptFetcher(WorkerGlobalScope* global_scope)
- : global_scope_(global_scope) {}
+ : global_scope_(global_scope) {
+ DCHECK(global_scope_->IsServiceWorkerGlobalScope());
+}
void InstalledServiceWorkerModuleScriptFetcher::Fetch(
FetchParameters& fetch_params,
@@ -24,8 +26,7 @@ void InstalledServiceWorkerModuleScriptFetcher::Fetch(
ModuleGraphLevel level,
ModuleScriptFetcher::Client* client) {
DCHECK(global_scope_->IsContextThread());
- InstalledScriptsManager* installed_scripts_manager =
- global_scope_->GetThread()->GetInstalledScriptsManager();
+ auto* installed_scripts_manager = global_scope_->GetInstalledScriptsManager();
DCHECK(installed_scripts_manager);
DCHECK(installed_scripts_manager->IsScriptInstalled(fetch_params.Url()));
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.h
index 3ddc2a8a7ff..b03fe39bc5c 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.h
@@ -15,8 +15,7 @@ class WorkerGlobalScope;
// ModuleScriptFetcher for retrieving an installed ServiceWorker script
// from ServiceWorker's script storage.
class CORE_EXPORT InstalledServiceWorkerModuleScriptFetcher final
- : public GarbageCollectedFinalized<
- InstalledServiceWorkerModuleScriptFetcher>,
+ : public GarbageCollected<InstalledServiceWorkerModuleScriptFetcher>,
public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(InstalledServiceWorkerModuleScriptFetcher);
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
index e60a882c9f7..57272881322 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
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 223bd92023f..7541555d508 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
@@ -31,7 +31,7 @@ enum class ModuleGraphLevel;
//
// ModuleScriptLoader(s) should only be used via Modulator and its ModuleMap.
class CORE_EXPORT ModuleScriptLoader final
- : public GarbageCollectedFinalized<ModuleScriptLoader>,
+ : public GarbageCollected<ModuleScriptLoader>,
public ModuleScriptFetcher::Client {
USING_GARBAGE_COLLECTED_MIXIN(ModuleScriptLoader);
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 5670bdc142b..3800534be20 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
@@ -43,7 +43,7 @@ namespace blink {
namespace {
class TestModuleScriptLoaderClient final
- : public GarbageCollectedFinalized<TestModuleScriptLoaderClient>,
+ : public GarbageCollected<TestModuleScriptLoaderClient>,
public ModuleScriptLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(TestModuleScriptLoaderClient);
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 86a7606556d..e2c000bcd97 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
@@ -342,8 +342,8 @@ void ModuleTreeLinker::NotifyModuleLoadFinished(ModuleScript* module_script) {
void ModuleTreeLinker::FetchDescendants(const ModuleScript* module_script) {
DCHECK(module_script);
- // TODO(crbug.com/1000152): Replace ScriptState::Scope with v8::HandleScope
- ScriptState::Scope scope(modulator_->GetScriptState());
+ 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;
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 bbee0646ab8..bc618489efd 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
@@ -93,7 +93,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
v8::Local<v8::Value> error = V8ThrowException::CreateError(
script_state_->GetIsolate(), "Parse failure.");
module_script->SetParseErrorAndClearRecord(
- ScriptValue(script_state_, error));
+ ScriptValue(script_state_->GetIsolate(), error));
}
EXPECT_TRUE(pending_clients_.Contains(url));
@@ -152,7 +152,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
ScriptState::Scope scope(script_state_);
v8::Local<v8::Value> error = V8ThrowException::CreateError(
script_state_->GetIsolate(), "Instantiation failure.");
- return ScriptValue(script_state_, error);
+ return ScriptValue(script_state_->GetIsolate(), error);
}
instantiated_records_.insert(MakeGarbageCollected<BoxedV8Module>(
script_state_->GetIsolate(), record));
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
index 65a616bb097..088efc21339 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
index f36f528658e..36710fdbcf3 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
@@ -17,7 +17,7 @@ class WorkerGlobalScope;
// https://html.spec.whatwg.org/C/#fetching-scripts-perform-fetch
// https://html.spec.whatwg.org/C/#worker-processing-model
class CORE_EXPORT WorkerModuleScriptFetcher final
- : public GarbageCollectedFinalized<WorkerModuleScriptFetcher>,
+ : public GarbageCollected<WorkerModuleScriptFetcher>,
public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(WorkerModuleScriptFetcher);
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 08c46a4d2a2..4bc3312d663 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
@@ -23,7 +23,7 @@ class ResourceFetcher;
// WorkletModuleResponsesMap, or defers to ModuleScriptFetcher and
// stores the result in WorkletModuleResponsesMap on fetch completion.
class CORE_EXPORT WorkletModuleScriptFetcher final
- : public GarbageCollectedFinalized<WorkletModuleScriptFetcher>,
+ : public GarbageCollected<WorkletModuleScriptFetcher>,
public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleScriptFetcher);
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 d65e7050798..f5752cbbaab 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
@@ -7,6 +7,8 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -211,9 +213,10 @@ PrefetchedSignedExchangeManager::CreateDefaultURLLoader(
std::unique_ptr<WebURLLoader>
PrefetchedSignedExchangeManager::CreatePrefetchedSignedExchangeURLLoader(
const WebURLRequest& request,
- network::mojom::blink::URLLoaderFactoryPtr loader_factory) {
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ loader_factory) {
return Platform::Current()
- ->WrapURLLoaderFactory(loader_factory.PassInterface().PassHandle())
+ ->WrapURLLoaderFactory(loader_factory.PassPipe())
->CreateURLLoader(
request,
frame_->GetFrameScheduler()->CreateResourceLoadingTaskRunnerHandle());
@@ -277,18 +280,19 @@ void PrefetchedSignedExchangeManager::TriggerLoad() {
if (!loader)
continue;
auto* prefetched_exchange = maching_prefetched_exchanges.at(i);
- network::mojom::blink::URLLoaderFactoryPtr loader_factory =
- network::mojom::blink::URLLoaderFactoryPtr(
- network::mojom::blink::URLLoaderFactoryPtrInfo(
- std::move(prefetched_exchange->loader_factory_handle),
- network::mojom::URLLoaderFactory::Version_));
- network::mojom::blink::URLLoaderFactoryPtr loader_factory_clone;
- loader_factory->Clone(MakeRequest(&loader_factory_clone));
+ mojo::Remote<network::mojom::blink::URLLoaderFactory> loader_factory(
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>(
+ std::move(prefetched_exchange->loader_factory_handle),
+ network::mojom::URLLoaderFactory::Version_));
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ loader_factory_clone;
+ loader_factory->Clone(
+ loader_factory_clone.InitWithNewPipeAndPassReceiver());
// Reset loader_factory_handle to support loading the same resource again.
prefetched_exchange->loader_factory_handle =
- loader_factory_clone.PassInterface().PassHandle();
+ loader_factory_clone.PassPipe();
loader->SetURLLoader(CreatePrefetchedSignedExchangeURLLoader(
- loader->request(), std::move(loader_factory)));
+ loader->request(), loader_factory.Unbind()));
}
}
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 9cad373739d..40dfc6f5aa4 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
@@ -6,7 +6,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREFETCHED_SIGNED_EXCHANGE_MANAGER_H_
#include "base/macros.h"
-#include "services/network/public/mojom/url_loader_factory.mojom-blink.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"
#include "third_party/blink/renderer/core/loader/preload_helper.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -25,8 +26,8 @@ class WebURLRequest;
// For SignedExchangeSubresourcePrefetch feature. This class holds the
// prefetched signed exchange info and will returns loaders for matching
// requests.
-class PrefetchedSignedExchangeManager
- : public GarbageCollectedFinalized<PrefetchedSignedExchangeManager> {
+class PrefetchedSignedExchangeManager final
+ : public GarbageCollected<PrefetchedSignedExchangeManager> {
public:
// If threre are no "allowed-alt-sxg" link headers in |inner_link_header|,
// or |prefetched_signed_exchanges| is empty, returns null.
@@ -84,7 +85,8 @@ class PrefetchedSignedExchangeManager
const WebURLRequest& request);
std::unique_ptr<WebURLLoader> CreatePrefetchedSignedExchangeURLLoader(
const WebURLRequest& request,
- network::mojom::blink::URLLoaderFactoryPtr loader_factory);
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ loader_factory);
Member<LocalFrame> frame_;
std::unique_ptr<AlternateSignedExchangeResourceInfo> alternative_resources_;
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 2e6ca0ef186..a6c93a6fca3 100644
--- a/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -484,13 +484,16 @@ Resource* PreloadHelper::PrefetchIfNeeded(const LinkLoadParameters& params,
ResourceRequest resource_request(params.href);
- // TODO(domfarolino): When SplitCache is enabled by default and we can
- // remove this feature check, also remove the exceptions in
- // net/base/features.h DEPS as well as audit_non_blink_usage.py.
if (base::FeatureList::IsEnabled(
- network::features::kPrefetchMainResourceNetworkIsolationKey) &&
- EqualIgnoringASCIICase(params.as, "document")) {
- resource_request.SetPrefetchMaybeForTopLevelNavigation(true);
+ network::features::kPrefetchMainResourceNetworkIsolationKey)) {
+ if (EqualIgnoringASCIICase(params.as, "document"))
+ resource_request.SetPrefetchMaybeForTopLevelNavigation(true);
+
+ // If this request was originally a preload header on a prefetch response,
+ // it may have a recursive prefetch token, used by the browser process to
+ // ensure this request is cached correctly.
+ resource_request.SetRecursivePrefetchToken(
+ params.recursive_prefetch_token);
}
resource_request.SetReferrerPolicy(params.referrer_policy);
@@ -533,7 +536,8 @@ void PreloadHelper::LoadLinksFromHeader(
MediaPreloadPolicy media_policy,
const base::Optional<ViewportDescription>& viewport_description,
std::unique_ptr<AlternateSignedExchangeResourceInfo>
- alternate_resource_info) {
+ alternate_resource_info,
+ base::Optional<base::UnguessableToken> recursive_prefetch_token) {
if (header_value.IsEmpty())
return;
LinkHeaderSet header_set(header_value);
@@ -547,6 +551,14 @@ void PreloadHelper::LoadLinksFromHeader(
continue;
LinkLoadParameters params(header, base_url);
+ if (params.rel.IsLinkPreload() && recursive_prefetch_token) {
+ // Only preload headers are expected to have a recursive prefetch token
+ // In response to that token's existence, we treat the request as a
+ // prefetch.
+ params.recursive_prefetch_token = recursive_prefetch_token;
+ params.rel = LinkRelAttribute("prefetch");
+ }
+
if (alternate_resource_info && params.rel.IsLinkPreload()) {
DCHECK(document);
DCHECK(RuntimeEnabledFeatures::SignedExchangeSubresourcePrefetchEnabled(
diff --git a/chromium/third_party/blink/renderer/core/loader/preload_helper.h b/chromium/third_party/blink/renderer/core/loader/preload_helper.h
index b045e8e37ad..79522b5f6fc 100644
--- a/chromium/third_party/blink/renderer/core/loader/preload_helper.h
+++ b/chromium/third_party/blink/renderer/core/loader/preload_helper.h
@@ -42,7 +42,8 @@ class PreloadHelper final {
CanLoadResources,
MediaPreloadPolicy,
const base::Optional<ViewportDescription>&,
- std::unique_ptr<AlternateSignedExchangeResourceInfo>);
+ std::unique_ptr<AlternateSignedExchangeResourceInfo>,
+ base::Optional<base::UnguessableToken>);
static Resource* StartPreload(ResourceType,
FetchParameters&,
ResourceFetcher*);
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
index 8eed4903953..5033635a421 100644
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
@@ -27,7 +27,7 @@ class KURL;
// PreviewsResourceLoadingHints stores the resource loading hints that apply to
// a single document.
class CORE_EXPORT PreviewsResourceLoadingHints final
- : public GarbageCollectedFinalized<PreviewsResourceLoadingHints> {
+ : public GarbageCollected<PreviewsResourceLoadingHints> {
public:
static PreviewsResourceLoadingHints* Create(
ExecutionContext& execution_context,
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc
deleted file mode 100644
index 5847eab3f9c..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-PreviewsResourceLoadingHintsReceiverImpl::
- PreviewsResourceLoadingHintsReceiverImpl(
- mojo::PendingReceiver<
- mojom::blink::PreviewsResourceLoadingHintsReceiver> receiver,
- Document* document)
- : receiver_(this, std::move(receiver)), document_(document) {
- DCHECK(!base::FeatureList::IsEnabled(
- blink::features::kSendPreviewsLoadingHintsBeforeCommit));
-}
-
-PreviewsResourceLoadingHintsReceiverImpl::
- ~PreviewsResourceLoadingHintsReceiverImpl() {}
-
-void PreviewsResourceLoadingHintsReceiverImpl::SetResourceLoadingHints(
- mojom::blink::PreviewsResourceLoadingHintsPtr resource_loading_hints) {
- // TODO(tbansal): https://crbug.com/856247. Block loading of resources based
- // on |resource_loading_hints|.
- UMA_HISTOGRAM_COUNTS_100(
- "ResourceLoadingHints.CountBlockedSubresourcePatterns",
- resource_loading_hints->subresources_to_block.size());
-
- Vector<WTF::String> subresource_patterns_to_block;
- for (const auto& subresource :
- resource_loading_hints->subresources_to_block) {
- subresource_patterns_to_block.push_back(subresource);
- }
-
- document_->Loader()->SetPreviewsResourceLoadingHints(
- PreviewsResourceLoadingHints::Create(
- *(document_.Get()), resource_loading_hints->ukm_source_id,
- subresource_patterns_to_block));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h
deleted file mode 100644
index 0d165a9c2d0..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/loader/previews_resource_loading_hints.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/platform/heap/persistent.h"
-
-namespace blink {
-
-// Created and attached to a LocalFrame when the frame receives a
-// PreviewsResourceLoadingHintsReceiver interface receiver from the browser
-// process.
-class PreviewsResourceLoadingHintsReceiverImpl
- : public mojom::blink::PreviewsResourceLoadingHintsReceiver {
- public:
- PreviewsResourceLoadingHintsReceiverImpl(
- mojo::PendingReceiver<mojom::blink::PreviewsResourceLoadingHintsReceiver>
- receiver,
- Document* document);
- ~PreviewsResourceLoadingHintsReceiverImpl() override;
-
- private:
- void SetResourceLoadingHints(mojom::blink::PreviewsResourceLoadingHintsPtr
- resource_loading_hints) override;
-
- // TODO(tbansal): https://crbug.com/800641. Consider using a RevocableBinding.
- mojo::Receiver<mojom::blink::PreviewsResourceLoadingHintsReceiver> receiver_;
-
- WeakPersistent<Document> document_;
-
- DISALLOW_COPY_AND_ASSIGN(PreviewsResourceLoadingHintsReceiverImpl);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
index 14ad87f0870..b9d4a97460a 100644
--- a/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
+++ b/chromium/third_party/blink/renderer/core/loader/private/prerender_handle.h
@@ -43,7 +43,7 @@ class Document;
class Prerender;
class PrerenderClient;
-class PrerenderHandle final : public GarbageCollectedFinalized<PrerenderHandle>,
+class PrerenderHandle final : public GarbageCollected<PrerenderHandle>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(PrerenderHandle);
USING_PRE_FINALIZER(PrerenderHandle, Dispose);
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 94be6b94041..36e97827799 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
@@ -48,7 +48,7 @@ struct ProgressItem;
// browser which shows a progress bar during loading.
// We should find a better way for Android to get this data and remove this!
class CORE_EXPORT ProgressTracker final
- : public GarbageCollectedFinalized<ProgressTracker> {
+ : public GarbageCollected<ProgressTracker> {
public:
explicit ProgressTracker(LocalFrame*);
~ProgressTracker();
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
index 070f330bbac..79733761842 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
index 15bbee3d1ab..b1d14480dcf 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/loader/resource/document_resource.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/xml_document.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
index 24d02ddd4b0..e5bc075c229 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/font_resource.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/loader/resource/font_resource.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc
index af0feb1c4ff..47f73bf1fb4 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
@@ -29,6 +29,7 @@
#include <utility>
#include "base/numerics/safe_conversions.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/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_info.h"
@@ -67,7 +68,7 @@ constexpr auto kFlushDelay = base::TimeDelta::FromSeconds(1);
} // namespace
class ImageResource::ImageResourceInfoImpl final
- : public GarbageCollectedFinalized<ImageResourceInfoImpl>,
+ : public GarbageCollected<ImageResourceInfoImpl>,
public ImageResourceInfo {
USING_GARBAGE_COLLECTED_MIXIN(ImageResourceInfoImpl);
@@ -557,36 +558,16 @@ void ImageResource::ReloadIfLoFiOrPlaceholderImage(
DCHECK(!is_scheduling_reload_);
is_scheduling_reload_ = true;
- if (GetResourceRequest().GetPreviewsState() & WebURLRequest::kClientLoFiOn) {
- SetCachePolicyBypassingCache();
- }
-
// The reloaded image should not use any previews transformations.
WebURLRequest::PreviewsState previews_state_for_reload =
WebURLRequest::kPreviewsNoTransform;
- WebURLRequest::PreviewsState old_previews_state =
- GetResourceRequest().GetPreviewsState();
-
- if (policy == kReloadIfNeeded && (GetResourceRequest().GetPreviewsState() &
- WebURLRequest::kClientLoFiOn)) {
- // If the image attempted to use Client LoFi, but encountered a decoding
- // error and is being automatically reloaded, then also set the appropriate
- // PreviewsState bit for that. This allows the embedder to count the
- // bandwidth used for this reload against the data savings of the initial
- // response.
- previews_state_for_reload |= WebURLRequest::kClientLoFiAutoReload;
- }
+
SetPreviewsState(previews_state_for_reload);
if (placeholder_option_ != PlaceholderOption::kDoNotReloadPlaceholder)
ClearRangeRequestHeader();
- if (old_previews_state & WebURLRequest::kClientLoFiOn &&
- policy != kReloadAlways) {
- placeholder_option_ = PlaceholderOption::kShowAndDoNotReloadPlaceholder;
- } else {
placeholder_option_ = PlaceholderOption::kDoNotReloadPlaceholder;
- }
if (IsLoading()) {
Loader()->Cancel();
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 89d765fbf4f..6247d3f5e82 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
@@ -6,6 +6,8 @@
#include <memory>
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_info.h"
@@ -28,7 +30,7 @@ namespace blink {
namespace {
class NullImageResourceInfo final
- : public GarbageCollectedFinalized<NullImageResourceInfo>,
+ : public GarbageCollected<NullImageResourceInfo>,
public ImageResourceInfo {
USING_GARBAGE_COLLECTED_MIXIN(NullImageResourceInfo);
@@ -146,15 +148,21 @@ void ImageResourceContent::Trace(blink::Visitor* visitor) {
ImageObserver::Trace(visitor);
}
-void ImageResourceContent::MarkObserverFinished(
+void ImageResourceContent::HandleObserverFinished(
ImageResourceObserver* observer) {
- ProhibitAddRemoveObserverInScope prohibit_add_remove_observer_in_scope(this);
-
- auto it = observers_.find(observer);
- if (it == observers_.end())
+ if (info_->SchedulingReloadOrShouldReloadBrokenPlaceholder())
return;
- observers_.erase(it);
- finished_observers_.insert(observer);
+ {
+ ProhibitAddRemoveObserverInScope prohibit_add_remove_observer_in_scope(
+ this);
+ auto it = observers_.find(observer);
+ if (it != observers_.end()) {
+ observers_.erase(it);
+ finished_observers_.insert(observer);
+ }
+ }
+ observer->ImageNotifyFinished(this);
+ UpdateImageAnimationPolicy();
}
void ImageResourceContent::AddObserver(ImageResourceObserver* observer) {
@@ -175,11 +183,8 @@ void ImageResourceContent::AddObserver(ImageResourceObserver* observer) {
observer->ImageChanged(this, CanDeferInvalidation::kNo);
}
- if (IsLoaded() && observers_.Contains(observer) &&
- !info_->SchedulingReloadOrShouldReloadBrokenPlaceholder()) {
- MarkObserverFinished(observer);
- observer->ImageNotifyFinished(this);
- }
+ if (IsLoaded() && observers_.Contains(observer))
+ HandleObserverFinished(observer);
}
void ImageResourceContent::RemoveObserver(ImageResourceObserver* observer) {
@@ -294,10 +299,8 @@ void ImageResourceContent::NotifyObservers(
if (observers_.Contains(observer)) {
observer->ImageChanged(this, defer);
if (notifying_finish_option == kShouldNotifyFinish &&
- observers_.Contains(observer) &&
- !info_->SchedulingReloadOrShouldReloadBrokenPlaceholder()) {
- MarkObserverFinished(observer);
- observer->ImageNotifyFinished(this);
+ observers_.Contains(observer)) {
+ HandleObserverFinished(observer);
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
index c022783bd1a..21d16460d63 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -42,7 +42,7 @@ class SecurityContext;
// TODO(hiroshige): Rename local variables of type ImageResourceContent to
// e.g. |imageContent|. Currently they have Resource-like names.
class CORE_EXPORT ImageResourceContent final
- : public GarbageCollectedFinalized<ImageResourceContent>,
+ : public GarbageCollected<ImageResourceContent>,
public ImageObserver {
USING_GARBAGE_COLLECTED_MIXIN(ImageResourceContent);
@@ -79,8 +79,6 @@ class CORE_EXPORT ImageResourceContent final
IntSize IntrinsicSize(
RespectImageOrientationEnum should_respect_image_orientation) const;
- void UpdateImageAnimationPolicy();
-
void AddObserver(ImageResourceObserver*);
void RemoveObserver(ImageResourceObserver*);
@@ -202,10 +200,10 @@ class CORE_EXPORT ImageResourceContent final
enum NotifyFinishOption { kShouldNotifyFinish, kDoNotNotifyFinish };
- // If not null, changeRect is the changed part of the image.
void NotifyObservers(NotifyFinishOption, CanDeferInvalidation);
- void MarkObserverFinished(ImageResourceObserver*);
+ void HandleObserverFinished(ImageResourceObserver*);
void UpdateToLoadedContentStatus(ResourceStatus);
+ void UpdateImageAnimationPolicy();
class ProhibitAddRemoveObserverInScope : public base::AutoReset<bool> {
public:
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
index e0a29279854..5bab2d34365 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc
@@ -514,7 +514,7 @@ TEST(ImageResourceTest, CancelOnRemoveObserver) {
EXPECT_FALSE(GetMemoryCache()->ResourceForURL(test_url));
}
-class MockFinishObserver : public GarbageCollectedFinalized<MockFinishObserver>,
+class MockFinishObserver : public GarbageCollected<MockFinishObserver>,
public ResourceFinishObserver {
USING_GARBAGE_COLLECTED_MIXIN(MockFinishObserver);
@@ -662,36 +662,6 @@ TEST(ImageResourceReloadTest, ReloadIfLoFiOrPlaceholderForPlaceholder) {
observer.get(), false);
}
-TEST(ImageResourceReloadTest, ReloadLoFiImagesWithDuplicateURLs) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
- ResourceFetcher* fetcher = CreateFetcher();
-
- FetchParameters placeholder_params{ResourceRequest(test_url)};
- placeholder_params.SetAllowImagePlaceholder();
- ImageResource* placeholder_resource =
- ImageResource::Fetch(placeholder_params, fetcher);
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- placeholder_params.GetImageRequestOptimization());
- EXPECT_TRUE(placeholder_resource->ShouldShowPlaceholder());
-
- FetchParameters full_image_params{ResourceRequest(test_url)};
- ImageResource* full_image_resource =
- ImageResource::Fetch(full_image_params, fetcher);
- EXPECT_EQ(FetchParameters::kNone,
- full_image_params.GetImageRequestOptimization());
- EXPECT_FALSE(full_image_resource->ShouldShowPlaceholder());
-
- // The |placeholder_resource| should not be reused for the
- // |full_image_resource|.
- EXPECT_NE(placeholder_resource, full_image_resource);
-
- fetcher->ReloadLoFiImages();
-
- EXPECT_FALSE(placeholder_resource->ShouldShowPlaceholder());
- EXPECT_FALSE(full_image_resource->ShouldShowPlaceholder());
-}
-
TEST(ImageResourceTest, SVGImage) {
KURL url("http://127.0.0.1:8000/foo");
ImageResource* image_resource = ImageResource::CreateForTest(url);
@@ -1209,52 +1179,6 @@ TEST(ImageResourceTest, FetchAllowPlaceholderUnsuccessful) {
observer.get(), false);
}
-TEST(ImageResourceTest, FetchAllowPlaceholderUnsuccessfulClientLoFi) {
- KURL test_url(kTestURL);
- ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
-
- ResourceRequest request = ResourceRequest(test_url);
- request.SetPreviewsState(WebURLRequest::kClientLoFiOn);
- FetchParameters params{request};
- params.SetAllowImagePlaceholder();
- ImageResource* image_resource = ImageResource::Fetch(params, CreateFetcher());
- EXPECT_EQ(FetchParameters::kAllowPlaceholder,
- params.GetImageRequestOptimization());
- EXPECT_EQ("bytes=0-2047",
- image_resource->GetResourceRequest().HttpHeaderField("range"));
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
- auto observer =
- std::make_unique<MockImageResourceObserver>(image_resource->GetContent());
-
- const char kBadData[] = "notanimageresponse";
-
- ResourceResponse bad_response(test_url);
- bad_response.SetMimeType("image/jpeg");
- bad_response.SetExpectedContentLength(sizeof(kBadData));
- bad_response.SetHttpStatusCode(206);
- bad_response.SetHttpHeaderField(
- "content-range", BuildContentRange(sizeof(kBadData), sizeof(kJpegImage)));
-
- image_resource->Loader()->DidReceiveResponse(
- WrappedResourceResponse(bad_response));
-
- EXPECT_EQ(0, observer->ImageChangedCount());
-
- image_resource->Loader()->DidReceiveData(kBadData, sizeof(kBadData));
-
- // The dimensions could not be extracted, so the full original image should be
- // loading.
- EXPECT_FALSE(observer->ImageNotifyFinishedCalled());
- EXPECT_EQ(2, observer->ImageChangedCount());
-
- TestThatReloadIsStartedThenServeReload(test_url, image_resource,
- image_resource->GetContent(),
- observer.get(), true);
-
- EXPECT_FALSE(image_resource->GetContent()->GetImage()->IsBitmapImage());
- EXPECT_TRUE(image_resource->ShouldShowPlaceholder());
-}
-
TEST(ImageResourceTest, FetchAllowPlaceholderPartialContentWithoutDimensions) {
const struct {
WebURLRequest::PreviewsState initial_previews_state;
@@ -1264,10 +1188,6 @@ TEST(ImageResourceTest, FetchAllowPlaceholderPartialContentWithoutDimensions) {
} tests[] = {
{WebURLRequest::kPreviewsUnspecified, WebURLRequest::kPreviewsNoTransform,
false},
- {WebURLRequest::kClientLoFiOn,
- WebURLRequest::kPreviewsNoTransform |
- WebURLRequest::kClientLoFiAutoReload,
- true},
};
for (const auto& test : tests) {
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h b/chromium/third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h
index eb5ceed3f0a..7d9d908d733 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/mock_font_resource_client.h
@@ -13,7 +13,7 @@
namespace blink {
class MockFontResourceClient final
- : public GarbageCollectedFinalized<MockFontResourceClient>,
+ : public GarbageCollected<MockFontResourceClient>,
public FontResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(MockFontResourceClient);
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 cfa2351b748..9fc6648bff1 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
@@ -51,7 +51,7 @@ namespace blink {
// A parser parsing mlutipart/x-mixed-replace resource.
class CORE_EXPORT MultipartImageResourceParser final
- : public GarbageCollectedFinalized<MultipartImageResourceParser> {
+ : public GarbageCollected<MultipartImageResourceParser> {
public:
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
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 711fed34170..66df03ca714 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
@@ -22,7 +22,7 @@ String ToString(const Vector<char>& data) {
return String(data.data(), data.size());
}
-class MockClient final : public GarbageCollectedFinalized<MockClient>,
+class MockClient final : public GarbageCollected<MockClient>,
public MultipartImageResourceParser::Client {
USING_GARBAGE_COLLECTED_MIXIN(MockClient);
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 559e9568733..1e8c9059808 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
@@ -109,6 +109,18 @@ ScriptResource* ScriptResource::Fetch(FetchParameters& params,
return resource;
}
+ScriptResource* ScriptResource::CreateForTest(
+ const KURL& url,
+ const WTF::TextEncoding& encoding) {
+ ResourceRequest request(url);
+ request.SetCredentialsMode(network::mojom::CredentialsMode::kOmit);
+ ResourceLoaderOptions options;
+ TextResourceDecoderOptions decoder_options(
+ TextResourceDecoderOptions::kPlainTextContent, encoding);
+ return MakeGarbageCollected<ScriptResource>(request, options,
+ decoder_options);
+}
+
ScriptResource::ScriptResource(
const ResourceRequest& resource_request,
const ResourceLoaderOptions& options,
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 c6c9e72aa25..010d12222b0 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
@@ -37,12 +37,17 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
+namespace mojo {
+class SimpleWatcher;
+}
+
namespace blink {
class FetchParameters;
class KURL;
class ResourceFetcher;
class ResponseBodyLoaderClient;
+class SingleCachedMetadataHandler;
// ScriptResource is a resource representing a JavaScript script. It is only
// used for "classic" scripts, i.e. not modules.
@@ -77,15 +82,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
// Public for testing
static ScriptResource* CreateForTest(const KURL& url,
- const WTF::TextEncoding& encoding) {
- ResourceRequest request(url);
- request.SetCredentialsMode(network::mojom::CredentialsMode::kOmit);
- ResourceLoaderOptions options;
- TextResourceDecoderOptions decoder_options(
- TextResourceDecoderOptions::kPlainTextContent, encoding);
- return MakeGarbageCollected<ScriptResource>(request, options,
- decoder_options);
- }
+ const WTF::TextEncoding& encoding);
ScriptResource(const ResourceRequest&,
const ResourceLoaderOptions&,
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.cc b/chromium/third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.cc
index 47acd283fbe..ce39f0ac1ad 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/loader/resource/xsl_style_sheet_resource.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
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 22c1a913dff..24a82f4c1e1 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,8 +4,6 @@
#include "third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/renderer/core/core_probes_inl.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -171,7 +169,7 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
frame, &frame_or_imported_document_->GetDocument(),
resource_loading_policy, PreloadHelper::kLoadAll,
base::nullopt /* viewport_description */,
- std::move(alternate_resource_info));
+ std::move(alternate_resource_info), response.RecursivePrefetchToken());
if (response.HasMajorCertificateErrors()) {
MixedContentChecker::HandleCertificateError(&frame, response,
@@ -179,16 +177,9 @@ void ResourceLoadObserverForFrame::DidReceiveResponse(
}
if (response.IsLegacyTLSVersion()) {
- CountUsage(WebFeature::kLegacyTLSVersionInSubresource);
- frame_client->ReportLegacyTLSVersion(response.CurrentRequestUrl());
- // For non-main-frame loads, we have to use the main frame's document for
- // the UKM recorder and source ID.
- auto& root = frame.LocalFrameRoot();
- ukm::builders::Net_LegacyTLSVersion(root.GetDocument()->UkmSourceID())
- .SetIsMainFrame(frame.IsMainFrame())
- .SetIsSubresource(true)
- .SetIsAdResource(resource->GetResourceRequest().IsAdResource())
- .Record(root.GetDocument()->UkmRecorder());
+ frame.Loader().ReportLegacyTLSVersion(
+ response.CurrentRequestUrl(), true /* is_subresource */,
+ resource->GetResourceRequest().IsAdResource());
}
frame.Loader().Progress().IncrementProgress(identifier, response);
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc b/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
index 7e793d8b46b..5b9982fb00f 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_filter.cc
@@ -142,7 +142,7 @@ void SubresourceFilter::ReportLoad(
if (auto* document = DynamicTo<Document>(execution_context_.Get())) {
if (DocumentLoader* loader = document->Loader()) {
loader->DidObserveLoadingBehavior(
- kWebLoadingBehaviorSubresourceFilterMatch);
+ kLoadingBehaviorSubresourceFilterMatch);
}
}
break;
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_filter.h b/chromium/third_party/blink/renderer/core/loader/subresource_filter.h
index 479e288e61e..d8c9a2ce833 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_filter.h
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_filter.h
@@ -24,7 +24,7 @@ class KURL;
// to extend the subresource filter with optimizations only possible using blink
// types (e.g. a caching layer using StringImpl).
class CORE_EXPORT SubresourceFilter final
- : public GarbageCollectedFinalized<SubresourceFilter> {
+ : public GarbageCollected<SubresourceFilter> {
public:
static SubresourceFilter* Create(
ExecutionContext&,
diff --git a/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc b/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
index c90e3869616..3fb26f885cd 100644
--- a/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
@@ -150,6 +150,13 @@ void TextTrackLoader::GetNewCues(
cue_parser_->GetNewCues(output_cues);
}
+void TextTrackLoader::GetNewStyleSheets(
+ HeapVector<Member<CSSStyleSheet>>& output_sheets) {
+ DCHECK(cue_parser_);
+ if (cue_parser_)
+ cue_parser_->GetNewStyleSheets(output_sheets);
+}
+
void TextTrackLoader::Trace(blink::Visitor* visitor) {
visitor->Trace(client_);
visitor->Trace(cue_parser_);
diff --git a/chromium/third_party/blink/renderer/core/loader/text_track_loader.h b/chromium/third_party/blink/renderer/core/loader/text_track_loader.h
index eda65bf5560..2621d7fee27 100644
--- a/chromium/third_party/blink/renderer/core/loader/text_track_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/text_track_loader.h
@@ -44,7 +44,7 @@ class TextTrackLoaderClient : public GarbageCollectedMixin {
virtual void CueLoadingCompleted(TextTrackLoader*, bool loading_failed) = 0;
};
-class TextTrackLoader final : public GarbageCollectedFinalized<TextTrackLoader>,
+class TextTrackLoader final : public GarbageCollected<TextTrackLoader>,
public RawResourceClient,
private VTTParserClient {
USING_GARBAGE_COLLECTED_MIXIN(TextTrackLoader);
@@ -60,6 +60,7 @@ class TextTrackLoader final : public GarbageCollectedFinalized<TextTrackLoader>,
State LoadState() { return state_; }
void GetNewCues(HeapVector<Member<TextTrackCue>>& output_cues);
+ void GetNewStyleSheets(HeapVector<Member<CSSStyleSheet>>& output_sheets);
void Trace(blink::Visitor*) override;
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 3794fc783af..1185c6c50a8 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -104,7 +104,7 @@ AtomicString CreateAccessControlRequestHeadersHeader(
// ThreadableLoader. It's for fetch requests with keepalive set, so
// it keeps itself alive during loading.
class ThreadableLoader::DetachedClient final
- : public GarbageCollectedFinalized<DetachedClient>,
+ : public GarbageCollected<DetachedClient>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(DetachedClient);
@@ -250,6 +250,7 @@ void ThreadableLoader::Start(const ResourceRequest& request) {
SECURITY_CHECK(cors::IsNoCorsAllowedContext(request_context_));
}
cors_flag_ = cors::CalculateCorsFlag(request.Url(), GetSecurityOrigin(),
+ request.IsolatedWorldOrigin().get(),
request.GetMode());
// The CORS flag variable is not yet used at the step in the spec that
@@ -613,12 +614,15 @@ bool ThreadableLoader::RedirectReceived(
// Allow same origin requests to continue after allowing clients to audit
// the redirect.
- if (!(cors_flag_ || cors::CalculateCorsFlag(new_url, GetSecurityOrigin(),
- new_request.GetMode()))) {
+ if (!(cors_flag_ ||
+ cors::CalculateCorsFlag(new_url, GetSecurityOrigin(),
+ new_request.IsolatedWorldOrigin().get(),
+ new_request.GetMode()))) {
bool follow =
client_->WillFollowRedirect(new_url, redirect_response_to_pass);
response_tainting_ = cors::CalculateResponseTainting(
- new_url, new_request.GetMode(), GetSecurityOrigin(), CorsFlag::Unset);
+ new_url, new_request.GetMode(), GetSecurityOrigin(),
+ new_request.IsolatedWorldOrigin().get(), CorsFlag::Unset);
return follow;
}
@@ -1024,6 +1028,7 @@ void ThreadableLoader::LoadRequest(
if (actual_request_.IsNull()) {
response_tainting_ = cors::CalculateResponseTainting(
request.Url(), request.GetMode(), GetSecurityOrigin(),
+ request.IsolatedWorldOrigin().get(),
cors_flag_ ? CorsFlag::Set : CorsFlag::Unset);
request.SetAllowStoredCredentials(cors::CalculateCredentialsFlag(
request.GetCredentialsMode(), response_tainting_));
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 fa27da69cce..ff82a734a0d 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.h
@@ -67,7 +67,7 @@ class ThreadableLoaderClient;
// the constructor.
// In either case, Start() must be called to actaully begin the request.
class CORE_EXPORT ThreadableLoader final
- : public GarbageCollectedFinalized<ThreadableLoader>,
+ : public GarbageCollected<ThreadableLoader>,
private RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(ThreadableLoader);
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 73cbbfc0c83..6fb01f8c0fe 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
@@ -52,7 +52,7 @@ using Checkpoint = testing::StrictMock<testing::MockFunction<void(int)>>;
constexpr char kFileName[] = "fox-null-terminated.html";
class MockThreadableLoaderClient final
- : public GarbageCollectedFinalized<MockThreadableLoaderClient>,
+ : public GarbageCollected<MockThreadableLoaderClient>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(MockThreadableLoaderClient);
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 f01a4a31778..355a5542de2 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
@@ -8,6 +8,7 @@
#include "base/metrics/histogram_macros.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"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
@@ -15,6 +16,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
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 2b8b9fdd224..4384d7b8bd6 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
@@ -23,7 +23,7 @@ class SegmentReader;
// Utility class for loading, decoding, and potentially rescaling an icon on a
// background thread. Note that icons are only downscaled and never upscaled.
class CORE_EXPORT ThreadedIconLoader final
- : public GarbageCollectedFinalized<ThreadedIconLoader>,
+ : public GarbageCollected<ThreadedIconLoader>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ThreadedIconLoader);
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 481fea92e5a..13b5e510efb 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
@@ -38,6 +38,7 @@
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "services/network/public/cpp/request_mode.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/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/task_type.h"
@@ -58,6 +59,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -95,7 +97,7 @@ void HTTPRequestHeaderValidator::VisitHeader(const WebString& name,
// It forwards its ThreadableLoaderClient notifications to a
// WebAssociatedURLLoaderClient.
class WebAssociatedURLLoaderImpl::ClientAdapter final
- : public GarbageCollectedFinalized<ClientAdapter>,
+ : public GarbageCollected<ClientAdapter>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ClientAdapter);
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 f9855015fff..be5939bad5c 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
@@ -73,12 +73,19 @@ class WebAssociatedURLLoaderTest : public testing::Test,
frame_file_path_ = test::CoreTestDataPath("iframes_test.html");
}
+ void RegisterMockedURLLoadWithCustomResponse(const WebURL& full_url,
+ WebURLResponse response,
+ const WebString& file_path) {
+ url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
+ full_url, file_path, response);
+ }
+
KURL RegisterMockedUrl(const std::string& url_root,
const WTF::String& filename) {
WebURLResponse response;
response.SetMimeType("text/html");
KURL url = ToKURL(url_root + filename.Utf8());
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
+ RegisterMockedURLLoadWithCustomResponse(
url, response, test::CoreTestDataPath(filename.Utf8().c_str()));
return url;
}
@@ -99,18 +106,14 @@ class WebAssociatedURLLoaderTest : public testing::Test,
frame_test_helpers::LoadFrame(MainFrame(), url.GetString().Utf8().c_str());
- Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(url);
+ url_test_helpers::RegisterMockedURLUnregister(url);
}
void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
+ url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
}
- void ServeRequests() {
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- }
+ void ServeRequests() { url_test_helpers::ServeAsynchronousRequests(); }
std::unique_ptr<WebAssociatedURLLoader> CreateAssociatedURLLoader(
const WebAssociatedURLLoaderOptions options =
@@ -231,8 +234,8 @@ class WebAssociatedURLLoaderTest : public testing::Test,
header_name_string);
}
expected_response_.AddHttpHeaderField(header_name_string, "foo");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -279,8 +282,8 @@ TEST_F(WebAssociatedURLLoaderTest, SameOriginSuccess) {
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
expected_loader_ = CreateAssociatedURLLoader();
EXPECT_TRUE(expected_loader_);
@@ -314,8 +317,8 @@ TEST_F(WebAssociatedURLLoaderTest, CrossOriginSuccess) {
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -340,8 +343,8 @@ TEST_F(WebAssociatedURLLoaderTest, CrossOriginWithAccessControlSuccess) {
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
expected_response_.AddHttpHeaderField("access-control-allow-origin", "*");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -368,8 +371,8 @@ TEST_F(WebAssociatedURLLoaderTest, CrossOriginWithAccessControlFailure) {
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
expected_response_.AddHttpHeaderField("access-control-allow-origin", "*");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -398,8 +401,8 @@ TEST_F(WebAssociatedURLLoaderTest,
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(0);
expected_response_.AddHttpHeaderField("access-control-allow-origin", "*");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -428,16 +431,16 @@ TEST_F(WebAssociatedURLLoaderTest, RedirectSuccess) {
expected_redirect_response_.SetMimeType("text/html");
expected_redirect_response_.SetHttpStatusCode(301);
expected_redirect_response_.SetHttpHeaderField("Location", redirect);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_redirect_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_redirect_response_,
+ frame_file_path_);
expected_new_url_ = WebURL(redirect_url);
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- redirect_url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(redirect_url, expected_response_,
+ frame_file_path_);
expected_loader_ = CreateAssociatedURLLoader();
EXPECT_TRUE(expected_loader_);
@@ -464,16 +467,16 @@ TEST_F(WebAssociatedURLLoaderTest, RedirectCrossOriginFailure) {
expected_redirect_response_.SetMimeType("text/html");
expected_redirect_response_.SetHttpStatusCode(301);
expected_redirect_response_.SetHttpHeaderField("Location", redirect);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_redirect_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_redirect_response_,
+ frame_file_path_);
expected_new_url_ = WebURL(redirect_url);
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- redirect_url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(redirect_url, expected_response_,
+ frame_file_path_);
expected_loader_ = CreateAssociatedURLLoader();
EXPECT_TRUE(expected_loader_);
@@ -504,16 +507,16 @@ TEST_F(WebAssociatedURLLoaderTest,
expected_redirect_response_.SetMimeType("text/html");
expected_redirect_response_.SetHttpStatusCode(301);
expected_redirect_response_.SetHttpHeaderField("Location", redirect);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_redirect_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_redirect_response_,
+ frame_file_path_);
expected_new_url_ = WebURL(redirect_url);
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- redirect_url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(redirect_url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -553,8 +556,8 @@ TEST_F(WebAssociatedURLLoaderTest,
expected_redirect_response_.SetHttpHeaderField("Location", redirect);
expected_redirect_response_.AddHttpHeaderField("access-control-allow-origin",
"*");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_redirect_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_redirect_response_,
+ frame_file_path_);
expected_new_url_ = WebURL(redirect_url);
@@ -562,8 +565,8 @@ TEST_F(WebAssociatedURLLoaderTest,
expected_response_.SetMimeType("text/html");
expected_response_.SetHttpStatusCode(200);
expected_response_.AddHttpHeaderField("access-control-allow-origin", "*");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- redirect_url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(redirect_url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -670,8 +673,8 @@ TEST_F(WebAssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders) {
expected_response_.SetHttpStatusCode(200);
expected_response_.AddHttpHeaderField("Access-Control-Allow-Origin", "*");
expected_response_.AddHttpHeaderField(header_name_string, "foo");
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
// This turns off response safelisting.
@@ -698,8 +701,8 @@ TEST_F(WebAssociatedURLLoaderTest, AccessCheckForLocalURL) {
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/plain");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
expected_loader_ = CreateAssociatedURLLoader(options);
@@ -725,8 +728,8 @@ TEST_F(WebAssociatedURLLoaderTest, BypassAccessCheckForLocalURL) {
expected_response_ = WebURLResponse();
expected_response_.SetMimeType("text/plain");
expected_response_.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- url, expected_response_, frame_file_path_);
+ RegisterMockedURLLoadWithCustomResponse(url, expected_response_,
+ frame_file_path_);
WebAssociatedURLLoaderOptions options;
options.grant_universal_access = true;
diff --git a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
index b71d3919be2..2b192807f5f 100644
--- a/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -7,8 +7,8 @@
#include <memory>
#include "base/single_thread_task_runner.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_object.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/base_fetch_context.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.cc b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.cc
index b6c87684158..74239307e6e 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message.cc
@@ -9,9 +9,8 @@ namespace blink {
BlinkCloneableMessage::BlinkCloneableMessage() = default;
BlinkCloneableMessage::~BlinkCloneableMessage() = default;
-BlinkCloneableMessage::BlinkCloneableMessage(BlinkCloneableMessage&&) noexcept =
- default;
+BlinkCloneableMessage::BlinkCloneableMessage(BlinkCloneableMessage&&) = default;
BlinkCloneableMessage& BlinkCloneableMessage::operator=(
- BlinkCloneableMessage&&) noexcept = default;
+ BlinkCloneableMessage&&) = default;
} // 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 337b0f82b81..a51e888047a 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
@@ -21,8 +21,8 @@ struct CORE_EXPORT BlinkCloneableMessage {
BlinkCloneableMessage();
~BlinkCloneableMessage();
- BlinkCloneableMessage(BlinkCloneableMessage&&) noexcept;
- BlinkCloneableMessage& operator=(BlinkCloneableMessage&&) noexcept;
+ BlinkCloneableMessage(BlinkCloneableMessage&&);
+ BlinkCloneableMessage& operator=(BlinkCloneableMessage&&);
scoped_refptr<blink::SerializedScriptValue> message;
v8_inspector::V8StackTraceId sender_stack_trace_id;
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
index 47d739f42d2..452fb50e6df 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
@@ -39,7 +39,8 @@ bool StructTraits<blink::mojom::blink::CloneableMessage::DataView,
out->sender_stack_trace_id = v8_inspector::V8StackTraceId(
static_cast<uintptr_t>(data.stack_trace_id()),
std::make_pair(data.stack_trace_debugger_id_first(),
- data.stack_trace_debugger_id_second()));
+ data.stack_trace_debugger_id_second()),
+ data.stack_trace_should_pause());
base::Optional<base::UnguessableToken> locked_agent_cluster_id;
if (!data.ReadLockedAgentClusterId(&locked_agent_cluster_id))
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 788b2a1391b..34b535438be 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
@@ -42,6 +42,11 @@ struct CORE_EXPORT StructTraits<blink::mojom::blink::CloneableMessage::DataView,
return input.sender_stack_trace_id.debugger_id.second;
}
+ static bool stack_trace_should_pause(
+ const blink::BlinkCloneableMessage& input) {
+ return input.sender_stack_trace_id.should_pause;
+ }
+
static const base::Optional<base::UnguessableToken>& locked_agent_cluster_id(
const blink::BlinkCloneableMessage& input) {
return input.locked_agent_cluster_id;
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 00431707521..e64ed125207 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
@@ -6,6 +6,7 @@
#include <utility>
#include "mojo/public/cpp/base/big_buffer.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -15,29 +16,18 @@ namespace blink {
BlinkTransferableMessage::BlinkTransferableMessage() = default;
BlinkTransferableMessage::~BlinkTransferableMessage() = default;
-BlinkTransferableMessage::BlinkTransferableMessage(
- BlinkTransferableMessage&&) noexcept = default;
+BlinkTransferableMessage::BlinkTransferableMessage(BlinkTransferableMessage&&) =
+ default;
BlinkTransferableMessage& BlinkTransferableMessage::operator=(
- BlinkTransferableMessage&&) noexcept = default;
+ BlinkTransferableMessage&&) = default;
-scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage(
+scoped_refptr<StaticBitmapImage> ToStaticBitmapImage(
const SkBitmap& sk_bitmap) {
- auto handle = WTF::ArrayBufferContents::CreateDataHandle(
- sk_bitmap.computeByteSize(), WTF::ArrayBufferContents::kZeroInitialize);
- if (!handle)
+ sk_sp<SkImage> image = SkImage::MakeFromBitmap(sk_bitmap);
+ if (!image)
return nullptr;
- WTF::ArrayBufferContents array_buffer_contents(
- std::move(handle), WTF::ArrayBufferContents::kNotShared);
- if (!array_buffer_contents.Data())
- return nullptr;
-
- SkImageInfo info = sk_bitmap.info();
- if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(),
- info.minRowBytes(), 0, 0))
- return nullptr;
-
- return blink::StaticBitmapImage::Create(array_buffer_contents, info);
+ return StaticBitmapImage::Create(std::move(image));
}
base::Optional<SkBitmap> ToSkBitmap(
@@ -64,13 +54,14 @@ BlinkTransferableMessage ToBlinkTransferableMessage(
BlobDataHandle::Create(
String::FromUTF8(blob->uuid), String::FromUTF8(blob->content_type),
blob->size,
- mojom::blink::BlobPtrInfo(blob->blob.PassHandle(),
- mojom::Blob::Version_)));
+ mojo::PendingRemote<mojom::blink::Blob>(blob->blob.PassPipe(),
+ mojom::Blob::Version_)));
}
result.sender_stack_trace_id = v8_inspector::V8StackTraceId(
static_cast<uintptr_t>(message.stack_trace_id),
std::make_pair(message.stack_trace_debugger_id_first,
- message.stack_trace_debugger_id_second));
+ message.stack_trace_debugger_id_second),
+ message.stack_trace_should_pause);
result.locked_agent_cluster_id = message.locked_agent_cluster_id;
result.ports.AppendRange(message.ports.begin(), message.ports.end());
result.message->GetStreamChannels().AppendRange(
@@ -91,10 +82,12 @@ BlinkTransferableMessage ToBlinkTransferableMessage(
for (auto& item : message.array_buffer_contents_array) {
mojo_base::BigBuffer& big_buffer = item->contents;
- auto handle = WTF::ArrayBufferContents::CreateDataHandle(
- big_buffer.size(), WTF::ArrayBufferContents::kZeroInitialize);
- WTF::ArrayBufferContents contents(std::move(handle),
- WTF::ArrayBufferContents::kNotShared);
+ WTF::ArrayBufferContents contents(
+ big_buffer.size(), 1, WTF::ArrayBufferContents::kNotShared,
+ WTF::ArrayBufferContents::kDontInitialize);
+ // Check if we allocated the backing store of the ArrayBufferContents
+ // correctly.
+ CHECK_EQ(contents.DataLength(), big_buffer.size());
memcpy(contents.Data(), big_buffer.data(), big_buffer.size());
array_buffer_contents_array.push_back(std::move(contents));
}
@@ -130,14 +123,15 @@ TransferableMessage ToTransferableMessage(BlinkTransferableMessage message) {
result.blobs.push_back(mojom::SerializedBlob::New(
blob.value->Uuid().Utf8(), blob.value->GetType().Utf8(),
blob.value->size(),
- mojom::BlobPtrInfo(blob.value->CloneBlobRemote().PassPipe(),
- mojom::Blob::Version_)));
+ mojo::PendingRemote<mojom::Blob>(
+ blob.value->CloneBlobRemote().PassPipe(), mojom::Blob::Version_)));
}
result.stack_trace_id = message.sender_stack_trace_id.id;
result.stack_trace_debugger_id_first =
message.sender_stack_trace_id.debugger_id.first;
result.stack_trace_debugger_id_second =
message.sender_stack_trace_id.debugger_id.second;
+ result.stack_trace_should_pause = message.sender_stack_trace_id.should_pause;
result.locked_agent_cluster_id = message.locked_agent_cluster_id;
result.ports.assign(message.ports.begin(), message.ports.end());
auto& stream_channels = message.message->GetStreamChannels();
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 edf4fab0ffa..3957bed8775 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
@@ -24,8 +24,8 @@ struct CORE_EXPORT BlinkTransferableMessage : BlinkCloneableMessage {
BlinkTransferableMessage();
~BlinkTransferableMessage();
- BlinkTransferableMessage(BlinkTransferableMessage&&) noexcept;
- BlinkTransferableMessage& operator=(BlinkTransferableMessage&&) noexcept;
+ BlinkTransferableMessage(BlinkTransferableMessage&&);
+ BlinkTransferableMessage& operator=(BlinkTransferableMessage&&);
Vector<MessagePortChannel> ports;
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
index e426bbf33c8..9c17e06cebd 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.cc
@@ -82,13 +82,13 @@ bool StructTraits<blink::mojom::blink::SerializedArrayBufferContents::DataView,
if (!data.ReadContents(&contents_view))
return false;
auto contents_data = contents_view.data();
- auto handle = WTF::ArrayBufferContents::CreateDataHandle(
- contents_data.size(), WTF::ArrayBufferContents::kZeroInitialize);
- if (!handle)
- return false;
WTF::ArrayBufferContents array_buffer_contents(
- std::move(handle), WTF::ArrayBufferContents::kNotShared);
+ contents_data.size(), 1, WTF::ArrayBufferContents::kNotShared,
+ WTF::ArrayBufferContents::kDontInitialize);
+ if (contents_data.size() != array_buffer_contents.DataLength()) {
+ return false;
+ }
memcpy(array_buffer_contents.Data(), contents_data.data(),
contents_data.size());
*out = std::move(array_buffer_contents);
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 62ca4304fc7..253da24c02b 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.cc
@@ -65,7 +65,7 @@ MessagePort::~MessagePort() {
void MessagePort::postMessage(ScriptState* script_state,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
PostMessageOptions* options = PostMessageOptions::Create();
if (!transfer.IsEmpty())
diff --git a/chromium/third_party/blink/renderer/core/messaging/message_port.h b/chromium/third_party/blink/renderer/core/messaging/message_port.h
index 1f9f0b453e6..b6ae50f284b 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.h
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.h
@@ -62,7 +62,7 @@ class CORE_EXPORT MessagePort : public EventTargetWithInlineData,
void postMessage(ScriptState*,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(ScriptState*,
const ScriptValue& message,
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 102d5493f0e..14be3f9c5b4 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -19,7 +19,8 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.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/workers/worker_global_scope.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"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
@@ -34,17 +35,20 @@
namespace blink {
-OffscreenCanvas::OffscreenCanvas(const IntSize& size)
+OffscreenCanvas::OffscreenCanvas(ExecutionContext* context, const IntSize& size)
: CanvasRenderingContextHost(
CanvasRenderingContextHost::HostType::kOffscreenCanvasHost),
+ execution_context_(context),
size_(size) {
UpdateMemoryUsage();
}
-OffscreenCanvas* OffscreenCanvas::Create(unsigned width, unsigned height) {
+OffscreenCanvas* OffscreenCanvas::Create(ExecutionContext* context,
+ unsigned width,
+ unsigned height) {
UMA_HISTOGRAM_BOOLEAN("Blink.OffscreenCanvas.NewOffscreenCanvas", true);
return MakeGarbageCollected<OffscreenCanvas>(
- IntSize(clampTo<int>(width), clampTo<int>(height)));
+ context, IntSize(clampTo<int>(width), clampTo<int>(height)));
}
OffscreenCanvas::~OffscreenCanvas() {
@@ -76,10 +80,14 @@ void OffscreenCanvas::Dispose() {
context_ = nullptr;
}
+ DeregisterFromAnimationFrameProvider();
+}
+
+void OffscreenCanvas::DeregisterFromAnimationFrameProvider() {
if (HasPlaceholderCanvas() && GetTopExecutionContext() &&
- GetTopExecutionContext()->IsWorkerGlobalScope()) {
+ GetTopExecutionContext()->IsDedicatedWorkerGlobalScope()) {
WorkerAnimationFrameProvider* animation_frame_provider =
- To<WorkerGlobalScope>(GetTopExecutionContext())
+ To<DedicatedWorkerGlobalScope>(GetTopExecutionContext())
->GetAnimationFrameProvider();
if (animation_frame_provider)
animation_frame_provider->DeregisterOffscreenCanvas(this);
@@ -89,10 +97,11 @@ void OffscreenCanvas::Dispose() {
void OffscreenCanvas::SetPlaceholderCanvasId(DOMNodeId canvas_id) {
placeholder_canvas_id_ = canvas_id;
if (GetTopExecutionContext() &&
- GetTopExecutionContext()->IsWorkerGlobalScope()) {
+ GetTopExecutionContext()->IsDedicatedWorkerGlobalScope()) {
WorkerAnimationFrameProvider* animation_frame_provider =
- To<WorkerGlobalScope>(GetTopExecutionContext())
+ To<DedicatedWorkerGlobalScope>(GetTopExecutionContext())
->GetAnimationFrameProvider();
+ DCHECK(animation_frame_provider);
if (animation_frame_provider)
animation_frame_provider->RegisterOffscreenCanvas(this);
}
@@ -111,25 +120,30 @@ void OffscreenCanvas::setHeight(unsigned height) {
}
void OffscreenCanvas::SetSize(const IntSize& size) {
- if (context_) {
- if (context_->Is3d()) {
- if (size != size_)
- context_->Reshape(size.Width(), size.Height());
- } else if (context_->Is2d()) {
+ // Setting size of a canvas also resets it.
+ if (size == size_) {
+ if (context_ && context_->Is2d()) {
context_->Reset();
origin_clean_ = true;
}
+ return;
}
- if (size != size_) {
- UpdateMemoryUsage();
- }
+
size_ = size;
+ UpdateMemoryUsage();
+ current_frame_damage_rect_ = SkIRect::MakeWH(size_.Width(), size_.Height());
+
if (frame_dispatcher_)
frame_dispatcher_->Reshape(size_);
-
- current_frame_damage_rect_ = SkIRect::MakeWH(size_.Width(), size_.Height());
- if (context_)
+ if (context_) {
+ if (context_->Is3d()) {
+ context_->Reshape(size_.Width(), size_.Height());
+ } else if (context_->Is2d()) {
+ context_->Reset();
+ origin_clean_ = true;
+ }
context_->DidDraw();
+ }
}
void OffscreenCanvas::RecordTransfer() {
@@ -141,6 +155,7 @@ void OffscreenCanvas::SetNeutered() {
is_neutered_ = true;
size_.SetWidth(0);
size_.SetHeight(0);
+ DeregisterFromAnimationFrameProvider();
}
ImageBitmap* OffscreenCanvas::transferToImageBitmap(
@@ -200,6 +215,8 @@ ScriptPromise OffscreenCanvas::CreateImageBitmap(
EventTarget&,
base::Optional<IntRect> crop_rect,
const ImageBitmapOptions* options) {
+ if (context_)
+ context_->FinalizeFrame();
return ImageBitmapSource::FulfillImageBitmap(
script_state,
IsPaintable() ? ImageBitmap::Create(this, crop_rect, options) : nullptr);
@@ -213,8 +230,7 @@ CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
ExecutionContext* execution_context,
const String& id,
const CanvasContextCreationAttributesCore& attributes) {
- execution_context_ = execution_context;
-
+ DCHECK_EQ(execution_context, GetTopExecutionContext());
CanvasRenderingContext::ContextType context_type =
CanvasRenderingContext::ContextTypeFromId(id);
@@ -243,7 +259,11 @@ CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
return nullptr;
}
} else {
- context_ = factory->Create(this, attributes);
+ CanvasContextCreationAttributesCore recomputed_attributes = attributes;
+ if (!allow_high_performance_power_preference_)
+ recomputed_attributes.power_preference = "low-power";
+
+ context_ = factory->Create(this, recomputed_attributes);
}
return context_.Get();
@@ -299,7 +319,10 @@ CanvasResourceDispatcher* OffscreenCanvas::GetOrCreateResourceDispatcher() {
void OffscreenCanvas::DiscardResourceProvider() {
CanvasResourceHost::DiscardResourceProvider();
- needs_matrix_clip_restore_ = true;
+ // If deferral is enabled the recorder will play back the transform, so
+ // we should not do it here or else it will be applied twice
+ if (!context_->IsDeferralEnabled())
+ needs_matrix_clip_restore_ = true;
}
CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProvider() {
@@ -386,44 +409,46 @@ void OffscreenCanvas::DidDraw(const FloatRect& rect) {
if (HasPlaceholderCanvas()) {
needs_push_frame_ = true;
- // TODO(fserb): perhaps we could avoid requesting begin frames here in cases
- // where the draw is call from within a worker rAF?
- GetOrCreateResourceDispatcher()->SetNeedsBeginFrame(true);
+ if (!inside_worker_raf_)
+ GetOrCreateResourceDispatcher()->SetNeedsBeginFrame(true);
}
}
-void OffscreenCanvas::BeginFrame() {
+bool OffscreenCanvas::BeginFrame() {
DCHECK(HasPlaceholderCanvas());
- PushFrameIfNeeded();
GetOrCreateResourceDispatcher()->SetNeedsBeginFrame(false);
+ return PushFrameIfNeeded();
}
-void OffscreenCanvas::PushFrameIfNeeded() {
+bool OffscreenCanvas::PushFrameIfNeeded() {
if (needs_push_frame_ && context_) {
- context_->PushFrame();
+ return context_->PushFrame();
}
+ return false;
}
-bool OffscreenCanvas::ShouldAccelerate2dContext() const {
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
- SharedGpuContext::ContextProviderWrapper();
- return context_provider_wrapper &&
- context_provider_wrapper->Utils()->Accelerated2DCanvasFeatureEnabled();
-}
-
-void OffscreenCanvas::PushFrame(scoped_refptr<CanvasResource> canvas_resource,
+bool OffscreenCanvas::PushFrame(scoped_refptr<CanvasResource> canvas_resource,
const SkIRect& damage_rect) {
+ TRACE_EVENT0("blink", "OffscreenCanvas::PushFrame");
DCHECK(needs_push_frame_);
needs_push_frame_ = false;
current_frame_damage_rect_.join(damage_rect);
if (current_frame_damage_rect_.isEmpty() || !canvas_resource)
- return;
+ return false;
const base::TimeTicks commit_start_time = base::TimeTicks::Now();
GetOrCreateResourceDispatcher()->DispatchFrame(
std::move(canvas_resource), commit_start_time, current_frame_damage_rect_,
!RenderingContext()->IsOriginTopLeft() /* needs_vertical_flip */,
IsOpaque());
current_frame_damage_rect_ = SkIRect::MakeEmpty();
+ return true;
+}
+
+bool OffscreenCanvas::ShouldAccelerate2dContext() const {
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
+ SharedGpuContext::ContextProviderWrapper();
+ return context_provider_wrapper &&
+ context_provider_wrapper->Utils()->Accelerated2DCanvasFeatureEnabled();
}
FontSelector* OffscreenCanvas::GetFontSelector() {
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
index d4394c50316..c198d424c6c 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -46,9 +46,11 @@ class CORE_EXPORT OffscreenCanvas final
USING_PRE_FINALIZER(OffscreenCanvas, Dispose);
public:
- static OffscreenCanvas* Create(unsigned width, unsigned height);
+ static OffscreenCanvas* Create(ExecutionContext*,
+ unsigned width,
+ unsigned height);
- explicit OffscreenCanvas(const IntSize&);
+ OffscreenCanvas(ExecutionContext*, const IntSize&);
~OffscreenCanvas() override;
void Dispose();
@@ -60,7 +62,7 @@ class CORE_EXPORT OffscreenCanvas final
void setHeight(unsigned);
// CanvasResourceDispatcherClient
- void BeginFrame() override;
+ bool BeginFrame() override;
// API Methods
ImageBitmap* transferToImageBitmap(ScriptState*, ExceptionState&);
@@ -70,6 +72,7 @@ class CORE_EXPORT OffscreenCanvas final
void RecordTransfer();
void SetPlaceholderCanvasId(DOMNodeId canvas_id);
+ void DeregisterFromAnimationFrameProvider();
DOMNodeId PlaceholderCanvasId() const { return placeholder_canvas_id_; }
bool HasPlaceholderCanvas() const;
bool IsNeutered() const override { return is_neutered_; }
@@ -88,6 +91,9 @@ class CORE_EXPORT OffscreenCanvas final
void SetDisableReadingFromCanvasTrue() {
disable_reading_from_canvas_ = true;
}
+ void SetNeedsMatrixClipRestore() override {
+ needs_matrix_clip_restore_ = true;
+ }
CanvasResourceProvider* GetOrCreateResourceProvider();
void DiscardResourceProvider() override;
@@ -103,12 +109,18 @@ class CORE_EXPORT OffscreenCanvas final
filter_quality_ = quality;
}
+ void AllowHighPerformancePowerPreference() {
+ allow_high_performance_power_preference_ = true;
+ }
+
// CanvasRenderingContextHost implementation.
- void FinalizeFrame() override {}
+ void PreFinalizeFrame() override {}
+ void PostFinalizeFrame() override {}
void DetachContext() override { context_ = nullptr; }
CanvasRenderingContext* RenderingContext() const override { return context_; }
- void PushFrameIfNeeded();
- void PushFrame(scoped_refptr<CanvasResource> frame,
+
+ bool PushFrameIfNeeded();
+ bool PushFrame(scoped_refptr<CanvasResource> frame,
const SkIRect& damage_rect) override;
void DidDraw(const FloatRect&) override;
void DidDraw() override;
@@ -171,6 +183,51 @@ class CORE_EXPORT OffscreenCanvas final
void Trace(blink::Visitor*) override;
+ class ScopedInsideWorkerRAF {
+ STACK_ALLOCATED();
+
+ public:
+ ScopedInsideWorkerRAF(const viz::BeginFrameArgs& args)
+ : abort_raf_(false), begin_frame_args_(args) {}
+
+ bool AddOffscreenCanvas(OffscreenCanvas* canvas) {
+ DCHECK(!abort_raf_);
+ DCHECK(!canvas->inside_worker_raf_);
+ if (canvas->GetOrCreateResourceDispatcher()) {
+ // If we are blocked with too many frames, we must stop.
+ if (canvas->GetOrCreateResourceDispatcher()
+ ->HasTooManyPendingFrames()) {
+ abort_raf_ = true;
+ return false;
+ }
+ }
+
+ canvas->inside_worker_raf_ = true;
+ canvases_.push_back(canvas);
+ return true;
+ }
+
+ ~ScopedInsideWorkerRAF() {
+ for (auto canvas : canvases_) {
+ DCHECK(canvas->inside_worker_raf_);
+ canvas->inside_worker_raf_ = false;
+ // If we have skipped raf, don't push frames.
+ if (abort_raf_)
+ continue;
+ if (canvas->GetOrCreateResourceDispatcher()) {
+ canvas->GetOrCreateResourceDispatcher()->ReplaceBeginFrameAck(
+ begin_frame_args_);
+ }
+ canvas->PushFrameIfNeeded();
+ }
+ }
+
+ private:
+ bool abort_raf_;
+ const viz::BeginFrameArgs& begin_frame_args_;
+ HeapVector<Member<OffscreenCanvas>> canvases_;
+ };
+
private:
int32_t memory_usage_ = 0;
@@ -187,7 +244,6 @@ class CORE_EXPORT OffscreenCanvas final
IntSize size_;
bool is_neutered_ = false;
-
bool origin_clean_ = true;
bool disable_reading_from_canvas_ = false;
@@ -197,9 +253,15 @@ class CORE_EXPORT OffscreenCanvas final
bool needs_matrix_clip_restore_ = false;
bool needs_push_frame_ = false;
+ bool inside_worker_raf_ = false;
SkFilterQuality filter_quality_ = kLow_SkFilterQuality;
+ // An offscreen canvas should only prefer the high-performance GPU if it is
+ // initialized by transferring control from an HTML canvas that is not
+ // cross-origin.
+ bool allow_high_performance_power_preference_ = false;
+
// cc::FrameSinkId is broken into two integer components as this can be used
// in transfer of OffscreenCanvas across threads
// If this object is not created via
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl
index 767f6f5ac0d..0890b3be942 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl
@@ -8,6 +8,7 @@
Constructor([EnforceRange] unsigned long width, [EnforceRange] unsigned long height),
Exposed=(Window,Worker),
Transferable,
+ ConstructorCallWith=ExecutionContext,
MeasureAs=OffscreenCanvas,
RuntimeEnabled=SurfaceEmbeddingFeatures
] interface OffscreenCanvas : EventTarget {
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 acf07bca187..ecf41cc05ec 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
@@ -33,7 +33,7 @@ class ExecutionContext;
//
// For more information, see https://github.com/jpchase/OriginTrials.
class CORE_EXPORT OriginTrialContext final
- : public GarbageCollectedFinalized<OriginTrialContext> {
+ : public GarbageCollected<OriginTrialContext> {
public:
OriginTrialContext();
explicit OriginTrialContext(std::unique_ptr<TrialTokenValidator> validator);
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 4cd75affd4b..32e036aad2e 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
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.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/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
diff --git a/chromium/third_party/blink/renderer/core/page/BUILD.gn b/chromium/third_party/blink/renderer/core/page/BUILD.gn
index 10ee308abd8..9c440eeb656 100644
--- a/chromium/third_party/blink/renderer/core/page/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/page/BUILD.gn
@@ -32,6 +32,8 @@ blink_core_sources("page") {
"focus_controller.h",
"frame_tree.cc",
"frame_tree.h",
+ "link_highlight.cc",
+ "link_highlight.h",
"page.cc",
"page.h",
"page_animator.cc",
@@ -71,8 +73,6 @@ blink_core_sources("page") {
"scrolling/overscroll_controller.h",
"scrolling/root_scroller_controller.cc",
"scrolling/root_scroller_controller.h",
- "scrolling/root_scroller_util.cc",
- "scrolling/root_scroller_util.h",
"scrolling/scroll_customization_callbacks.cc",
"scrolling/scroll_customization_callbacks.h",
"scrolling/scroll_state.cc",
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 ee6869ada4a..212a909e1f8 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
@@ -50,7 +50,7 @@ void ChromeClient::InstallSupplements(LocalFrame& frame) {
void ChromeClient::SetWindowRectWithAdjustment(const IntRect& pending_rect,
LocalFrame& frame) {
- IntRect screen = GetScreenInfo().available_rect;
+ IntRect screen = GetScreenInfo(frame).available_rect;
IntRect window = pending_rect;
IntSize minimum_size = MinimumWindowSize();
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 ab88caa833a..4ee85902767 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.h
@@ -32,7 +32,7 @@
#include "cc/trees/paint_holding_commit_trigger.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
#include "third_party/blink/public/platform/web_focus_type.h"
@@ -104,16 +104,13 @@ struct WebWindowFeatures;
using CompositorElementId = cc::ElementId;
-class CORE_EXPORT ChromeClient
- : public GarbageCollectedFinalized<ChromeClient> {
+class CORE_EXPORT ChromeClient : public GarbageCollected<ChromeClient> {
DISALLOW_COPY_AND_ASSIGN(ChromeClient);
public:
virtual ~ChromeClient() = default;
- // Converts the scalar value from the window coordinates to the viewport
- // scale. TODO(darin): Convert all callers over to the LocalFrame version.
- virtual float WindowToViewportScalar(const float) const = 0;
+ // Converts the scalar value from window coordinates to viewport scale.
virtual float WindowToViewportScalar(LocalFrame*,
const float value) const = 0;
@@ -129,7 +126,8 @@ class CORE_EXPORT ChromeClient
virtual IntRect ViewportToScreen(const IntRect&,
const LocalFrameView*) const = 0;
- virtual void ScheduleAnimation(const LocalFrameView*) = 0;
+ virtual void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) = 0;
// The specified rectangle is adjusted for the minimum window size and the
// screen, then setWindowRect with the adjusted rectangle is called.
@@ -259,7 +257,7 @@ class CORE_EXPORT ChromeClient
virtual WebViewImpl* GetWebView() const = 0;
- virtual WebScreenInfo GetScreenInfo() const = 0;
+ virtual WebScreenInfo GetScreenInfo(LocalFrame& frame) const = 0;
virtual void SetCursor(const Cursor&, LocalFrame* local_root) = 0;
virtual void SetCursorOverridden(bool) = 0;
@@ -432,8 +430,6 @@ class CORE_EXPORT ChromeClient
// Input method editor related functions.
virtual void ShowVirtualKeyboardOnElementFocus(LocalFrame&) {}
- virtual void RegisterViewportLayers() const {}
-
virtual TransformationMatrix GetDeviceEmulationTransform() const {
return TransformationMatrix();
}
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 00037d0439e..ce971d88932 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
@@ -429,7 +429,8 @@ void ChromeClientImpl::InvalidateRect(const IntRect& update_rect) {
web_view_->InvalidateRect(update_rect);
}
-void ChromeClientImpl::ScheduleAnimation(const LocalFrameView* frame_view) {
+void ChromeClientImpl::ScheduleAnimation(const LocalFrameView* frame_view,
+ base::TimeDelta delay) {
LocalFrame& frame = frame_view->GetFrame();
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
DCHECK(web_frame);
@@ -440,9 +441,13 @@ void ChromeClientImpl::ScheduleAnimation(const LocalFrameView* frame_view) {
// WebFrameWidget needs to be initialized before initializing the core frame?
WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
if (widget) {
- // LocalRootFrameWidget() is a WebWidget, its client is the embedder.
- WebWidgetClient* web_widget_client = widget->Client();
- web_widget_client->ScheduleAnimation();
+ if (delay.is_zero()) {
+ // LocalRootFrameWidget() is a WebWidget, its client is the embedder.
+ WebWidgetClient* web_widget_client = widget->Client();
+ web_widget_client->ScheduleAnimation();
+ } else {
+ widget->RequestAnimationAfterDelay(delay);
+ }
}
}
@@ -467,31 +472,30 @@ IntRect ChromeClientImpl::ViewportToScreen(
return screen_rect;
}
-float ChromeClientImpl::WindowToViewportScalar(const float scalar_value) const {
- // TODO(darin): Change callers to pass a LocalFrame.
- return WindowToViewportScalar(web_view_->MainFrameImpl()
- ? web_view_->MainFrameImpl()->GetFrame()
- : nullptr,
- scalar_value);
-}
-
float ChromeClientImpl::WindowToViewportScalar(LocalFrame* frame,
const float scalar_value) const {
- // Note, FrameWidgetImpl() can be null during Scrollbar() construction.
- WebLocalFrameImpl* local_frame = WebLocalFrameImpl::FromFrame(frame);
- if (!local_frame || !local_frame->FrameWidgetImpl())
+
+ // TODO(darin): Clean up callers to not pass null. E.g., VisualViewport::
+ // ScrollbarThickness() is one such caller. See https://pastebin.com/axgctw0N
+ // for a sample call stack.
+ if (!frame) {
+ DLOG(WARNING) << "LocalFrame is null!";
return scalar_value;
+ }
WebFloatRect viewport_rect(0, 0, scalar_value, 0);
- local_frame->FrameWidgetImpl()->Client()->ConvertWindowToViewport(
- &viewport_rect);
+ WebLocalFrameImpl::FromFrame(frame)
+ ->LocalRootFrameWidget()
+ ->Client()
+ ->ConvertWindowToViewport(&viewport_rect);
return viewport_rect.width;
}
-WebScreenInfo ChromeClientImpl::GetScreenInfo() const {
- if (!web_view_->Client())
- return {};
- return web_view_->Client()->GetScreenInfo();
+WebScreenInfo ChromeClientImpl::GetScreenInfo(LocalFrame& frame) const {
+ WebWidgetClient* client =
+ WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget()->Client();
+ DCHECK(client);
+ return client->GetScreenInfo();
}
void ChromeClientImpl::OverrideVisibleRectForMainFrame(
@@ -1255,11 +1259,6 @@ void ChromeClientImpl::AjaxSucceeded(LocalFrame* frame) {
fill_client->AjaxSucceeded();
}
-void ChromeClientImpl::RegisterViewportLayers() const {
- if (web_view_->RootGraphicsLayer())
- web_view_->RegisterViewportLayersWithCompositor();
-}
-
TransformationMatrix ChromeClientImpl::GetDeviceEmulationTransform() const {
return web_view_->GetDeviceEmulationTransform();
}
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 74ae9f584fc..9c3f5243fbd 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
@@ -120,12 +120,12 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
String& result) override;
bool TabsToLinks() override;
void InvalidateRect(const IntRect&) override;
- void ScheduleAnimation(const LocalFrameView*) override;
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) override;
IntRect ViewportToScreen(const IntRect&,
const LocalFrameView*) const override;
- float WindowToViewportScalar(const float) const override;
float WindowToViewportScalar(LocalFrame*, const float) const override;
- WebScreenInfo GetScreenInfo() const override;
+ WebScreenInfo GetScreenInfo(LocalFrame&) const override;
void OverrideVisibleRectForMainFrame(LocalFrame& frame,
IntRect* paint_rect) const override;
float InputEventsScaleForEmulation() const override;
@@ -234,8 +234,6 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
void ShowVirtualKeyboardOnElementFocus(LocalFrame&) override;
- void RegisterViewportLayers() const override;
-
TransformationMatrix GetDeviceEmulationTransform() const override;
void OnMouseDown(Node&) 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 61bc163fedf..127fcc57a62 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
@@ -32,6 +32,7 @@
#include "cc/trees/layer_tree_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/mojom/choosers/color_chooser.mojom-blink.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
@@ -98,9 +99,8 @@ TEST_F(CreateWindowTest, CreateWindowFromPausedPage) {
FeaturePolicy::FeatureState(), ""));
}
-class FakeColorChooserClient
- : public GarbageCollectedFinalized<FakeColorChooserClient>,
- public ColorChooserClient {
+class FakeColorChooserClient : public GarbageCollected<FakeColorChooserClient>,
+ public ColorChooserClient {
public:
FakeColorChooserClient(Element* owner_element)
: owner_element_(owner_element) {}
@@ -129,7 +129,7 @@ class FakeColorChooserClient
};
class FakeDateTimeChooserClient
- : public GarbageCollectedFinalized<FakeDateTimeChooserClient>,
+ : public GarbageCollected<FakeDateTimeChooserClient>,
public DateTimeChooserClient {
public:
FakeDateTimeChooserClient(Element* owner_element)
@@ -231,9 +231,8 @@ TEST_F(PagePopupSuppressionTest, SuppressDateTimeChooser) {
}
// A FileChooserClient which makes FileChooser::OpenFileChooser() success.
-class MockFileChooserClient
- : public GarbageCollectedFinalized<MockFileChooserClient>,
- public FileChooserClient {
+class MockFileChooserClient : public GarbageCollected<MockFileChooserClient>,
+ public FileChooserClient {
USING_GARBAGE_COLLECTED_MIXIN(MockFileChooserClient);
public:
@@ -268,9 +267,9 @@ class FileChooserQueueTest : public testing::Test {
TEST_F(FileChooserQueueTest, DerefQueuedChooser) {
LocalFrame* frame = helper_.LocalMainFrame()->GetFrame();
- base::RunLoop run_loop;
- MockFileChooser chooser(&frame->GetInterfaceProvider(),
- run_loop.QuitClosure());
+ base::RunLoop run_loop_for_chooser1;
+ MockFileChooser chooser(frame->GetBrowserInterfaceBroker(),
+ run_loop_for_chooser1.QuitClosure());
auto* client1 = MakeGarbageCollected<MockFileChooserClient>(frame);
auto* client2 = MakeGarbageCollected<MockFileChooserClient>(frame);
mojom::blink::FileChooserParams params;
@@ -284,12 +283,15 @@ TEST_F(FileChooserQueueTest, DerefQueuedChooser) {
chooser2.reset();
// Kicks ChromeClientImpl::DidCompleteFileChooser() for chooser1.
- run_loop.Run();
+ run_loop_for_chooser1.Run();
chooser.ResponseOnOpenFileChooser(FileChooserFileInfoList());
EXPECT_EQ(1u, chrome_client_impl_->file_chooser_queue_.size());
+ base::RunLoop run_loop_for_chooser2;
+
+ chooser.SetQuitClosure(run_loop_for_chooser2.QuitClosure());
+ run_loop_for_chooser2.Run();
- // Cleanup for the second OpenFileChooser request.
chooser.ResponseOnOpenFileChooser(FileChooserFileInfoList());
}
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 df28bc8a3b7..8aef3cb9f85 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
@@ -44,7 +44,7 @@ class Page;
struct WebContextMenuData;
class CORE_EXPORT ContextMenuController final
- : public GarbageCollectedFinalized<ContextMenuController> {
+ : public GarbageCollected<ContextMenuController> {
public:
explicit ContextMenuController(Page*);
~ContextMenuController();
diff --git a/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
index 7baf33b8e64..7235fcab105 100644
--- a/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -94,6 +94,7 @@ class ContextMenuControllerTest : public testing::Test {
web_view_helper_.LocalMainFrame()->GetDocument());
}
+ WebView* GetWebView() { return web_view_helper_.GetWebView(); }
Page* GetPage() { return web_view_helper_.GetWebView()->GetPage(); }
WebLocalFrameImpl* LocalMainFrame() {
return web_view_helper_.LocalMainFrame();
@@ -543,4 +544,48 @@ TEST_F(ContextMenuControllerTest, EditingActionsEnabledInXMLDocument) {
EXPECT_EQ(context_menu_data.selected_text, "Blue text");
}
+TEST_F(ContextMenuControllerTest, ShowNonLocatedContextMenuEvent) {
+ GetDocument()->documentElement()->SetInnerHTMLFromString(
+ "<input id='sample' type='text' size='5' value='Sample Input Text'>");
+
+ Document* document = GetDocument();
+ Element* input_element = document->getElementById("sample");
+ document->UpdateStyleAndLayout();
+
+ // Select the 'Sample' of |input|.
+ DOMRect* rect = input_element->getBoundingClientRect();
+ WebGestureEvent gesture_event(
+ WebInputEvent::kGestureLongPress, WebInputEvent::kNoModifiers,
+ base::TimeTicks::Now(), WebGestureDevice::kTouchscreen);
+ gesture_event.SetPositionInWidget(WebFloatPoint(rect->left(), rect->top()));
+ GetWebView()->MainFrameWidget()->HandleInputEvent(
+ WebCoalescedInputEvent(gesture_event));
+
+ WebContextMenuData context_menu_data =
+ GetWebFrameClient().GetContextMenuData();
+ EXPECT_EQ(context_menu_data.selected_text, "Sample");
+
+ // Adjust the selection from the start of |input| to the middle.
+ LayoutPoint middle_point((rect->left() + rect->right()) / 2,
+ (rect->top() + rect->bottom()) / 2);
+ LocalMainFrame()->MoveRangeSelectionExtent(
+ WebPoint(middle_point.X().ToInt(), middle_point.Y().ToInt()));
+ GetWebView()->MainFrameWidget()->ShowContextMenu(kMenuSourceTouchHandle);
+
+ context_menu_data = GetWebFrameClient().GetContextMenuData();
+ EXPECT_NE(context_menu_data.selected_text, "");
+
+ // Scroll the value of |input| to end.
+ input_element->setScrollLeft(input_element->scrollWidth());
+
+ // Select all the value of |input| to ensure the start of selection is
+ // invisible.
+ LocalMainFrame()->MoveRangeSelectionExtent(
+ WebPoint(rect->right(), rect->bottom()));
+ GetWebView()->MainFrameWidget()->ShowContextMenu(kMenuSourceTouchHandle);
+
+ context_menu_data = GetWebFrameClient().GetContextMenuData();
+ EXPECT_EQ(context_menu_data.selected_text, "Sample Input Text");
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/context_menu_provider.h b/chromium/third_party/blink/renderer/core/page/context_menu_provider.h
index 79fdd438458..b712a07bca1 100644
--- a/chromium/third_party/blink/renderer/core/page/context_menu_provider.h
+++ b/chromium/third_party/blink/renderer/core/page/context_menu_provider.h
@@ -38,8 +38,7 @@ namespace blink {
struct WebMenuItemInfo;
-class ContextMenuProvider
- : public GarbageCollectedFinalized<ContextMenuProvider> {
+class ContextMenuProvider : public GarbageCollected<ContextMenuProvider> {
public:
virtual ~ContextMenuProvider() = default;
virtual void Trace(blink::Visitor* visitor) {}
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 ac8e3581188..85275afa79d 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.cc
@@ -284,8 +284,6 @@ void DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
return;
}
- document_under_mouse_ = nullptr;
-
if (OperationForLoad(drag_data, local_root) != kDragOperationNone) {
if (page_->GetSettings().GetNavigateOnDragDrop()) {
ResourceRequest resource_request(drag_data->AsURL());
@@ -315,6 +313,8 @@ void DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
// be sending these events. crbug.com/748243.
local_root.GetEventHandler().ClearDragState();
}
+
+ document_under_mouse_ = nullptr;
}
void DragController::MouseMovedIntoDocument(Document* new_document) {
@@ -1147,7 +1147,7 @@ static IntPoint DragLocationForLink(const DragImage* link_image,
// static
std::unique_ptr<DragImage> DragController::DragImageForSelection(
- const LocalFrame& frame,
+ LocalFrame& frame,
float opacity) {
if (!frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsRange())
return nullptr;
@@ -1244,7 +1244,7 @@ bool DragController::StartDrag(LocalFrame* src,
src->GetPage()->GetVisualViewport().Scale());
float screen_device_scale_factor =
- src->GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+ src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
// Pass the selected image size in DIP becasue dragImageForImage clips the
// image in DIP. The coordinates of the locations are in Viewport
// coordinates, and they're converted in the Blink client.
@@ -1281,7 +1281,7 @@ bool DragController::StartDrag(LocalFrame* src,
if (!drag_image) {
DCHECK(src->GetPage());
float screen_device_scale_factor =
- src->GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+ src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
drag_image = DragImageForLink(link_url, hit_test_result.TextContent(),
screen_device_scale_factor);
drag_location = DragLocationForLink(drag_image.get(), mouse_dragged_point,
@@ -1328,7 +1328,7 @@ void DragController::DoSystemDrag(DragImage* image,
if (image) {
float resolution_scale = image->ResolutionScale();
float device_scale_factor =
- page_->GetChromeClient().GetScreenInfo().device_scale_factor;
+ frame->GetChromeClient().GetScreenInfo(*frame).device_scale_factor;
if (device_scale_factor != resolution_scale) {
DCHECK_GT(resolution_scale, 0);
float scale = device_scale_factor / resolution_scale;
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 626b42cd3c8..daeed24b63d 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.h
@@ -84,8 +84,7 @@ class CORE_EXPORT DragController final
DragState& GetDragState();
- static std::unique_ptr<DragImage> DragImageForSelection(const LocalFrame&,
- float);
+ static std::unique_ptr<DragImage> DragImageForSelection(LocalFrame&, float);
// Return the selection bounds in absolute coordinates for the frame, clipped
// to the visual viewport.
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 aa350fb7a01..fa56cbae58d 100644
--- a/chromium/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/focus_controller.cc
@@ -139,7 +139,7 @@ class FocusNavigation : public GarbageCollected<FocusNavigation> {
Element* owner = nullptr;
if (node.AssignedSlot())
owner = node.AssignedSlot();
- else if (IsHTMLSlotElement(node.parentNode()))
+ else if (IsA<HTMLSlotElement>(node.parentNode()))
owner = node.ParentOrShadowHostElement();
else if (&node == node.ContainingTreeScope().RootNode())
owner = TreeOwner(&node);
@@ -230,7 +230,7 @@ ScopedFocusNavigation::ScopedFocusNavigation(
const Element* current,
FocusController::OwnerMap& owner_map)
: current_(current) {
- if (HTMLSlotElement* slot = ToHTMLSlotElementOrNull(scoping_root_node)) {
+ if (auto* slot = DynamicTo<HTMLSlotElement>(scoping_root_node)) {
if (slot->AssignedNodes().IsEmpty()) {
navigation_ = MakeGarbageCollected<FocusNavigation>(scoping_root_node,
*slot, owner_map);
@@ -239,8 +239,7 @@ ScopedFocusNavigation::ScopedFocusNavigation(
// the shadow tree.
DCHECK(scoping_root_node.ContainingShadowRoot());
navigation_ = MakeGarbageCollected<FocusNavigation>(
- scoping_root_node.ContainingShadowRoot()->host(),
- ToHTMLSlotElement(scoping_root_node), owner_map);
+ scoping_root_node.ContainingShadowRoot()->host(), *slot, owner_map);
}
} else {
navigation_ =
@@ -295,7 +294,7 @@ ScopedFocusNavigation ScopedFocusNavigation::OwnedByNonFocusableFocusScopeOwner(
if (IsShadowHost(element))
return ScopedFocusNavigation::OwnedByShadowHost(element, owner_map);
return ScopedFocusNavigation::OwnedByHTMLSlotElement(
- ToHTMLSlotElement(element), owner_map);
+ To<HTMLSlotElement>(element), owner_map);
}
ScopedFocusNavigation ScopedFocusNavigation::OwnedByShadowHost(
@@ -327,7 +326,7 @@ HTMLSlotElement* ScopedFocusNavigation::FindFallbackScopeOwnerSlot(
const Element& element) {
Element* parent = const_cast<Element*>(element.parentElement());
while (parent) {
- if (auto* slot = ToHTMLSlotElementOrNull(parent))
+ if (auto* slot = DynamicTo<HTMLSlotElement>(parent))
return slot->AssignedNodes().IsEmpty() ? slot : nullptr;
parent = parent->parentElement();
}
@@ -343,10 +342,10 @@ bool ScopedFocusNavigation::IsSlotFallbackScopedForThisSlot(
const Element& current) {
Element* parent = current.parentElement();
while (parent) {
- if (IsHTMLSlotElement(parent) &&
- ToHTMLSlotElement(parent)->AssignedNodes().IsEmpty()) {
+ auto* html_slot_element = DynamicTo<HTMLSlotElement>(parent);
+ if (html_slot_element && html_slot_element->AssignedNodes().IsEmpty()) {
return !SlotScopedTraversal::IsSlotScoped(current) &&
- ToHTMLSlotElement(parent) == slot;
+ html_slot_element == slot;
}
parent = parent->parentElement();
}
@@ -434,7 +433,7 @@ inline bool IsKeyboardFocusableShadowHost(const Element& element) {
inline bool IsNonFocusableFocusScopeOwner(Element& element) {
return IsNonKeyboardFocusableShadowHost(element) ||
- IsHTMLSlotElement(element);
+ IsA<HTMLSlotElement>(element);
}
inline bool IsShadowHostDelegatesFocus(const Element& element) {
@@ -1190,8 +1189,29 @@ Element* FocusController::FindFocusableElementInShadowHost(
OwnerMap owner_map;
ScopedFocusNavigation scope =
ScopedFocusNavigation::OwnedByShadowHost(shadow_host, owner_map);
- return FindFocusableElementAcrossFocusScopes(kWebFocusTypeForward, scope,
- owner_map);
+ Element* result = FindFocusableElementAcrossFocusScopes(kWebFocusTypeForward,
+ scope, owner_map);
+ if (!result)
+ return nullptr;
+ // Check if |found| is the first focusable element under |element|, and count
+ // if it's not.
+ const Node* current = &shadow_host;
+ while ((current = FlatTreeTraversal::Next(*current))) {
+ if (!current->IsElementNode())
+ continue;
+ if (current == result) {
+ // We've reached |found|, which means |found| is the first focusable
+ // element so we don't count this.
+ break;
+ }
+ if (ToElement(current)->IsFocusable()) {
+ UseCounter::Count(shadow_host.GetDocument(),
+ WebFeature::kDelegateFocusNotFirstInFlatTree);
+ break;
+ }
+ }
+
+ return result;
}
Element* FocusController::FindFocusableElementAfter(Element& element,
diff --git a/chromium/third_party/blink/renderer/core/page/link_highlight.cc b/chromium/third_party/blink/renderer/core/page/link_highlight.cc
new file mode 100644
index 00000000000..6c4945fb795
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/link_highlight.cc
@@ -0,0 +1,125 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/page/link_highlight.h"
+
+#include <memory>
+
+#include "cc/animation/animation_host.h"
+#include "cc/layers/picture_layer.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/link_highlight_impl.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
+
+namespace blink {
+
+LinkHighlight::LinkHighlight(Page& owner) : page_(&owner) {}
+
+LinkHighlight::~LinkHighlight() {
+ RemoveHighlight();
+}
+
+void LinkHighlight::Trace(blink::Visitor* visitor) {
+ visitor->Trace(page_);
+}
+
+void LinkHighlight::RemoveHighlight() {
+ if (impl_) {
+ if (timeline_)
+ timeline_->AnimationDestroyed(*impl_);
+ if (auto* node = impl_->GetNode()) {
+ if (auto* layout_object = node->GetLayoutObject())
+ layout_object->SetNeedsPaintPropertyUpdate();
+ }
+ }
+ impl_.reset();
+}
+
+void LinkHighlight::ResetForPageNavigation() {
+ RemoveHighlight();
+}
+
+void LinkHighlight::SetTapHighlight(Node* node) {
+ // Always clear any existing highlight when this is invoked, even if we
+ // don't get a new target to highlight.
+ RemoveHighlight();
+
+ if (!node || !node->GetLayoutObject())
+ return;
+
+ Color highlight_color =
+ node->GetLayoutObject()->StyleRef().TapHighlightColor();
+ // Safari documentation for -webkit-tap-highlight-color says if the
+ // specified color has 0 alpha, then tap highlighting is disabled.
+ // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
+ if (!highlight_color.Alpha())
+ return;
+
+ impl_ = std::make_unique<LinkHighlightImpl>(node);
+ if (timeline_)
+ timeline_->AnimationAttached(*impl_);
+ node->GetLayoutObject()->SetNeedsPaintPropertyUpdate();
+}
+
+LocalFrame* LinkHighlight::MainFrame() const {
+ return GetPage().MainFrame() && GetPage().MainFrame()->IsLocalFrame()
+ ? GetPage().DeprecatedLocalMainFrame()
+ : nullptr;
+}
+
+void LinkHighlight::StartHighlightAnimationIfNeeded() {
+ if (impl_)
+ impl_->StartHighlightAnimationIfNeeded();
+
+ if (auto* local_frame = MainFrame())
+ GetPage().GetChromeClient().ScheduleAnimation(local_frame->View());
+}
+
+void LinkHighlight::AnimationHostInitialized(
+ cc::AnimationHost& animation_host) {
+ animation_host_ = &animation_host;
+ if (Platform::Current()->IsThreadedAnimationEnabled()) {
+ timeline_ = std::make_unique<CompositorAnimationTimeline>();
+ animation_host_->AddAnimationTimeline(timeline_->GetAnimationTimeline());
+ }
+}
+
+void LinkHighlight::WillCloseAnimationHost() {
+ RemoveHighlight();
+ if (timeline_) {
+ animation_host_->RemoveAnimationTimeline(timeline_->GetAnimationTimeline());
+ timeline_.reset();
+ }
+ animation_host_ = nullptr;
+}
+
+bool LinkHighlight::NeedsHighlightEffectInternal(
+ const LayoutObject& object) const {
+ DCHECK(impl_);
+ if (auto* node = impl_->GetNode())
+ return node->GetLayoutObject() == &object;
+ return false;
+}
+
+void LinkHighlight::UpdateBeforePrePaint() {
+ if (impl_)
+ impl_->UpdateBeforePrePaint();
+}
+
+void LinkHighlight::UpdateAfterPrePaint() {
+ if (impl_)
+ impl_->UpdateAfterPrePaint();
+}
+
+void LinkHighlight::Paint(GraphicsContext& context) const {
+ if (impl_)
+ impl_->Paint(context);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/link_highlight.h b/chromium/third_party/blink/renderer/core/page/link_highlight.h
new file mode 100644
index 00000000000..b1df87c73f1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/link_highlight.h
@@ -0,0 +1,72 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_LINK_HIGHLIGHT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_LINK_HIGHLIGHT_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace cc {
+class AnimationHost;
+}
+
+namespace blink {
+class GraphicsContext;
+class Page;
+class LinkHighlightImpl;
+class CompositorAnimationTimeline;
+class LocalFrame;
+class LayoutObject;
+
+class CORE_EXPORT LinkHighlight final : public GarbageCollected<LinkHighlight> {
+ public:
+ explicit LinkHighlight(Page&);
+ virtual ~LinkHighlight();
+
+ virtual void Trace(blink::Visitor*);
+
+ void ResetForPageNavigation();
+
+ void SetTapHighlight(Node*);
+
+ void StartHighlightAnimationIfNeeded();
+
+ void AnimationHostInitialized(cc::AnimationHost&);
+ void WillCloseAnimationHost();
+
+ bool NeedsHighlightEffect(const LayoutObject& object) const {
+ return impl_ && NeedsHighlightEffectInternal(object);
+ }
+
+ void UpdateBeforePrePaint();
+ void UpdateAfterPrePaint();
+ void Paint(GraphicsContext&) const;
+
+ private:
+ friend class LinkHighlightImplTest;
+
+ void RemoveHighlight();
+
+ LocalFrame* MainFrame() const;
+
+ Page& GetPage() const {
+ DCHECK(page_);
+ return *page_;
+ }
+
+ bool NeedsHighlightEffectInternal(const LayoutObject& object) const;
+
+ Member<Page> page_;
+ std::unique_ptr<LinkHighlightImpl> impl_;
+ cc::AnimationHost* animation_host_ = nullptr;
+ std::unique_ptr<CompositorAnimationTimeline> timeline_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_LINK_HIGHLIGHT_H_
diff --git a/chromium/third_party/blink/renderer/core/page/page.cc b/chromium/third_party/blink/renderer/core/page/page.cc
index 57e3a515bcc..c5a1faaedad 100644
--- a/chromium/third_party/blink/renderer/core/page/page.cc
+++ b/chromium/third_party/blink/renderer/core/page/page.cc
@@ -25,17 +25,18 @@
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/core/css/media_feature_overrides.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/events/event.h"
#include "third_party/blink/renderer/core/dom/visited_link_state.h"
#include "third_party/blink/renderer/core/editing/drag_caret.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
+#include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/dom_timer.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -58,6 +59,7 @@
#include "third_party/blink/renderer/core/page/context_menu_controller.h"
#include "third_party/blink/renderer/core/page/drag_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page_hidden_state.h"
#include "third_party/blink/renderer/core/page/plugin_data.h"
#include "third_party/blink/renderer/core/page/plugins_changed_observer.h"
@@ -104,6 +106,12 @@ Page::PageSet& Page::OrdinaryPages() {
return *pages;
}
+static AgentMetricsCollector& GlobalAgentMetricsCollector() {
+ DEFINE_STATIC_LOCAL(Persistent<AgentMetricsCollector>, metrics_collector,
+ (MakeGarbageCollected<AgentMetricsCollector>()));
+ return *metrics_collector;
+}
+
void Page::InsertOrdinaryPageForTesting(Page* page) {
OrdinaryPages().insert(page);
}
@@ -136,6 +144,7 @@ Page* Page::CreateNonOrdinary(PageClients& page_clients) {
Page* Page::CreateOrdinary(PageClients& page_clients, Page* opener) {
Page* page = MakeGarbageCollected<Page>(page_clients);
page->is_ordinary_ = true;
+ page->agent_metrics_collector_ = &GlobalAgentMetricsCollector();
page->SetPageScheduler(ThreadScheduler::Current()->CreatePageScheduler(page));
if (opener) {
@@ -182,7 +191,7 @@ Page::Page(PageClients& page_clients)
overscroll_controller_(
MakeGarbageCollected<OverscrollController>(GetVisualViewport(),
GetChromeClient())),
- link_highlights_(MakeGarbageCollected<LinkHighlights>(*this)),
+ link_highlight_(MakeGarbageCollected<LinkHighlight>(*this)),
plugin_data_(nullptr),
// TODO(pdr): Initialize |validation_message_client_| lazily.
validation_message_client_(
@@ -205,7 +214,7 @@ Page::Page(PageClients& page_clients)
}
Page::~Page() {
- // willBeDestroyed() must be called before Page destruction.
+ // WillBeDestroyed() must be called before Page destruction.
DCHECK(!main_frame_);
}
@@ -281,8 +290,8 @@ const OverscrollController& Page::GetOverscrollController() const {
return *overscroll_controller_;
}
-LinkHighlights& Page::GetLinkHighlights() {
- return *link_highlights_;
+LinkHighlight& Page::GetLinkHighlight() {
+ return *link_highlight_;
}
void Page::SetMainFrame(Frame* main_frame) {
@@ -306,6 +315,9 @@ void Page::DocumentDetached(Document* document) {
if (validation_message_client_)
validation_message_client_->DocumentDetached(*document);
hosts_using_features_.DocumentDetached(*document);
+
+ if (agent_metrics_collector_)
+ agent_metrics_collector_->DidDetachDocument(*document);
}
bool Page::OpenedByDOM() const {
@@ -500,50 +512,27 @@ void Page::SetLifecycleState(PageLifecycleState state) {
return;
DCHECK_NE(state, PageLifecycleState::kUnknown);
- // When background tab freezing was first shipped it didn't pause
- // the execution context but froze the frame scheduler. This feature
- // flag attempts to bring the two mechanisms to use the same path for
- // all pausing and freezing.
- // This allows for mojo channels, workers to also be frozen because
- // they listen for the page execution context being paused/frozen.
- if (RuntimeEnabledFeatures::
- PauseExecutionContextOnBackgroundFreezeEnabled()) {
- base::Optional<mojom::FrameLifecycleState> next_state;
- if (state == PageLifecycleState::kFrozen) {
- next_state = mojom::FrameLifecycleState::kFrozen;
- } else if (page_lifecycle_state_ == PageLifecycleState::kFrozen) {
- // TODO(fmeawad): Only resume the page that just became visible, blocked
- // on task queues per frame.
- DCHECK(state == PageLifecycleState::kActive ||
- state == PageLifecycleState::kHiddenBackgrounded ||
- state == PageLifecycleState::kHiddenForegrounded);
- next_state = mojom::FrameLifecycleState::kRunning;
- }
+ base::Optional<mojom::FrameLifecycleState> next_state;
+ if (state == PageLifecycleState::kFrozen) {
+ next_state = mojom::FrameLifecycleState::kFrozen;
+ } else if (page_lifecycle_state_ == PageLifecycleState::kFrozen) {
+ // TODO(fmeawad): Only resume the page that just became visible, blocked
+ // on task queues per frame.
+ DCHECK(state == PageLifecycleState::kActive ||
+ state == PageLifecycleState::kHiddenBackgrounded ||
+ state == PageLifecycleState::kHiddenForegrounded);
+ next_state = mojom::FrameLifecycleState::kRunning;
+ }
- if (next_state) {
- for (Frame* frame = main_frame_.Get(); frame;
- frame = frame->Tree().TraverseNext()) {
- if (auto* local_frame = DynamicTo<LocalFrame>(frame))
- local_frame->SetLifecycleState(next_state.value());
- }
- }
- } else {
- // The following code will dispatch the freeze/resume events,
- // freeze the frame scheduler but but not pause the execution context.
- if (state == PageLifecycleState::kFrozen) {
- for (Frame* frame = main_frame_.Get(); frame;
- frame = frame->Tree().TraverseNext()) {
- frame->DidFreeze();
- }
- } else if (page_lifecycle_state_ == PageLifecycleState::kFrozen) {
- // TODO(fmeawad): Only resume the page that just became visible, blocked
- // on task queues per frame.
- DCHECK(state == PageLifecycleState::kActive ||
- state == PageLifecycleState::kHiddenBackgrounded ||
- state == PageLifecycleState::kHiddenForegrounded);
- for (Frame* frame = main_frame_.Get(); frame;
- frame = frame->Tree().TraverseNext()) {
- frame->DidResume();
+ if (next_state) {
+ for (Frame* frame = main_frame_.Get(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
+ // TODO(chrisha): Determine if dispatching the before unload
+ // makes sense and if so put it into a specification.
+ if (next_state == mojom::FrameLifecycleState::kFrozen)
+ local_frame->DispatchBeforeUnloadEventForFreeze();
+ local_frame->SetLifecycleState(next_state.value());
}
}
}
@@ -786,8 +775,8 @@ void Page::UpdateAcceleratedCompositingSettings() {
auto* local_frame = DynamicTo<LocalFrame>(frame);
if (!local_frame)
continue;
- if (LocalFrameView* view = local_frame->View())
- view->UpdateAcceleratedCompositingSettings();
+ LayoutView* layout_view = local_frame->ContentLayoutObject();
+ layout_view->Compositor()->UpdateAcceleratedCompositingSettings();
}
}
@@ -809,7 +798,7 @@ void Page::DidCommitLoad(LocalFrame* frame) {
// Update |has_related_pages_| as features are reset after navigation.
UpdateHasRelatedPages();
}
- GetLinkHighlights().ResetForPageNavigation();
+ GetLinkHighlight().ResetForPageNavigation();
}
void Page::AcceptLanguagesChanged() {
@@ -843,11 +832,12 @@ void Page::Trace(blink::Visitor* visitor) {
visitor->Trace(global_root_scroller_controller_);
visitor->Trace(visual_viewport_);
visitor->Trace(overscroll_controller_);
- visitor->Trace(link_highlights_);
+ visitor->Trace(link_highlight_);
visitor->Trace(spatial_navigation_controller_);
visitor->Trace(main_frame_);
visitor->Trace(plugin_data_);
visitor->Trace(validation_message_client_);
+ visitor->Trace(agent_metrics_collector_);
visitor->Trace(plugins_changed_observers_);
visitor->Trace(next_related_page_);
visitor->Trace(prev_related_page_);
@@ -860,13 +850,13 @@ void Page::AnimationHostInitialized(cc::AnimationHost& animation_host,
if (GetScrollingCoordinator()) {
GetScrollingCoordinator()->AnimationHostInitialized(animation_host, view);
}
- GetLinkHighlights().AnimationHostInitialized(animation_host);
+ GetLinkHighlight().AnimationHostInitialized(animation_host);
}
void Page::WillCloseAnimationHost(LocalFrameView* view) {
if (scrolling_coordinator_)
scrolling_coordinator_->WillCloseAnimationHost(view);
- GetLinkHighlights().WillCloseAnimationHost();
+ GetLinkHighlight().WillCloseAnimationHost();
}
void Page::WillBeDestroyed() {
@@ -902,6 +892,9 @@ void Page::WillBeDestroyed() {
validation_message_client_->WillBeDestroyed();
main_frame_ = nullptr;
+ if (agent_metrics_collector_)
+ agent_metrics_collector_->ReportMetrics();
+
PageVisibilityNotifier::NotifyContextDestroyed();
page_scheduler_.reset();
@@ -985,7 +978,7 @@ void Page::UpdateHasRelatedPages() {
LocalFrame* local_main_frame = DynamicTo<LocalFrame>(main_frame_.Get());
// We want to record this only for the pages which have local main frame,
// which is fine as we are aggregating results across all processes.
- if (!local_main_frame)
+ if (!local_main_frame || !local_main_frame->IsAttached())
return;
has_related_pages_ = local_main_frame->GetFrameScheduler()->RegisterFeature(
SchedulingPolicy::Feature::kHasScriptableFramesInMultipleTabs,
@@ -993,6 +986,26 @@ void Page::UpdateHasRelatedPages() {
}
}
+void Page::SetMediaFeatureOverride(const AtomicString& media_feature,
+ const String& value) {
+ if (!media_feature_overrides_) {
+ if (value.IsEmpty())
+ return;
+ media_feature_overrides_ = std::make_unique<MediaFeatureOverrides>();
+ }
+ media_feature_overrides_->SetOverride(media_feature, value);
+ if (media_feature == "prefers-color-scheme")
+ SettingsChanged(SettingsDelegate::kColorSchemeChange);
+ else
+ SettingsChanged(SettingsDelegate::kMediaQueryChange);
+}
+
+void Page::ClearMediaFeatureOverrides() {
+ media_feature_overrides_.reset();
+ SettingsChanged(SettingsDelegate::kMediaQueryChange);
+ SettingsChanged(SettingsDelegate::kColorSchemeChange);
+}
+
Page::PageClients::PageClients() : chrome_client(nullptr) {}
Page::PageClients::~PageClients() = default;
diff --git a/chromium/third_party/blink/renderer/core/page/page.h b/chromium/third_party/blink/renderer/core/page/page.h
index 9f70ee04554..e4a4c36701f 100644
--- a/chromium/third_party/blink/renderer/core/page/page.h
+++ b/chromium/third_party/blink/renderer/core/page/page.h
@@ -50,6 +50,7 @@ class AnimationHost;
}
namespace blink {
+class AgentMetricsCollector;
class AutoscrollController;
class BrowserControls;
class ChromeClient;
@@ -60,9 +61,10 @@ class DragCaret;
class DragController;
class FocusController;
class Frame;
-class LinkHighlights;
+class LinkHighlight;
class LocalFrame;
class LocalFrameView;
+class MediaFeatureOverrides;
class OverscrollController;
struct PageScaleConstraints;
class PageScaleConstraintsSet;
@@ -83,7 +85,7 @@ typedef uint64_t LinkHash;
float DeviceScaleFactorDeprecated(LocalFrame*);
-class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
+class CORE_EXPORT Page final : public GarbageCollected<Page>,
public Supplementable<Page>,
public PageVisibilityNotifier,
public SettingsDelegate,
@@ -184,6 +186,9 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
ValidationMessageClient& GetValidationMessageClient() const {
return *validation_message_client_;
}
+ AgentMetricsCollector* GetAgentMetricsCollector() const {
+ return agent_metrics_collector_.Get();
+ }
void SetValidationMessageClientForTesting(ValidationMessageClient*);
ScrollingCoordinator* GetScrollingCoordinator();
@@ -214,7 +219,7 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
VisualViewport& GetVisualViewport();
const VisualViewport& GetVisualViewport() const;
- LinkHighlights& GetLinkHighlights();
+ LinkHighlight& GetLinkHighlight();
OverscrollController& GetOverscrollController();
const OverscrollController& GetOverscrollController() const;
@@ -323,6 +328,13 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
return web_text_autosizer_page_info_;
}
+ void SetMediaFeatureOverride(const AtomicString& media_feature,
+ const String& value);
+ const MediaFeatureOverrides* GetMediaFeatureOverrides() const {
+ return media_feature_overrides_.get();
+ }
+ void ClearMediaFeatureOverrides();
+
private:
friend class ScopedPagePauser;
@@ -368,13 +380,17 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
global_root_scroller_controller_;
const Member<VisualViewport> visual_viewport_;
const Member<OverscrollController> overscroll_controller_;
- const Member<LinkHighlights> link_highlights_;
+ const Member<LinkHighlight> link_highlight_;
Member<SpatialNavigationController> spatial_navigation_controller_;
Member<PluginData> plugin_data_;
Member<ValidationMessageClient> validation_message_client_;
+ // Stored only for ordinary pages to avoid adding metrics from things like
+ // overlays, popups and SVG.
+ Member<AgentMetricsCollector> agent_metrics_collector_;
+
Deprecation deprecation_;
HostsUsingFeatures hosts_using_features_;
WebWindowFeatures window_features_;
@@ -419,6 +435,9 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
std::unique_ptr<PageScheduler> page_scheduler_;
+ // Overrides for various media features set from the devtools.
+ std::unique_ptr<MediaFeatureOverrides> media_feature_overrides_;
+
int32_t autoplay_flags_;
// Accessed by frames to determine whether to expose the PortalHost object.
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc b/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
index bf606fc0354..8a56d320cea 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_controller.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/page/page_popup_controller.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/page/page_popup.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -100,8 +101,7 @@ String PagePopupController::formatWeek(int year,
DCHECK(set_week_result);
String localized_week = popup_client_->GetLocale().FormatDateTime(week);
return popup_client_->GetLocale().QueryString(
- WebLocalizedString::kAXCalendarWeekDescription, localized_week,
- localized_date_string);
+ IDS_AX_CALENDAR_WEEK_DESCRIPTION, localized_week, localized_date_string);
}
void PagePopupController::ClearPagePopupClient() {
diff --git a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
index caf005f3407..6a25df5fb9b 100644
--- a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -142,8 +142,8 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
case WebInputEvent::kMouseUp:
if (!root || !root->View())
return WebInputEventResult::kHandledSuppressed;
- handler.HandleMouseUp(*root, static_cast<const WebMouseEvent&>(event));
- return WebInputEventResult::kHandledSystem;
+ return handler.HandleMouseUp(*root,
+ static_cast<const WebMouseEvent&>(event));
case WebInputEvent::kMouseWheel:
if (!root || !root->View())
return WebInputEventResult::kNotHandled;
@@ -239,11 +239,13 @@ void PageWidgetEventHandler::HandleMouseDown(LocalFrame& main_frame,
main_frame.GetEventHandler().HandleMousePressEvent(transformed_event);
}
-void PageWidgetEventHandler::HandleMouseUp(LocalFrame& main_frame,
- const WebMouseEvent& event) {
+WebInputEventResult PageWidgetEventHandler::HandleMouseUp(
+ LocalFrame& main_frame,
+ const WebMouseEvent& event) {
WebMouseEvent transformed_event =
TransformWebMouseEvent(main_frame.View(), event);
- main_frame.GetEventHandler().HandleMouseReleaseEvent(transformed_event);
+ return main_frame.GetEventHandler().HandleMouseReleaseEvent(
+ transformed_event);
}
WebInputEventResult PageWidgetEventHandler::HandleMouseWheel(
diff --git a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
index 645d4acb280..996e0dcd785 100644
--- a/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
+++ b/chromium/third_party/blink/renderer/core/page/page_widget_delegate.h
@@ -54,7 +54,8 @@ class CORE_EXPORT PageWidgetEventHandler {
const WebVector<const WebInputEvent*>&);
virtual void HandleMouseLeave(LocalFrame& main_frame, const WebMouseEvent&);
virtual void HandleMouseDown(LocalFrame& main_frame, const WebMouseEvent&);
- virtual void HandleMouseUp(LocalFrame& main_frame, const WebMouseEvent&);
+ virtual WebInputEventResult HandleMouseUp(LocalFrame& main_frame,
+ const WebMouseEvent&);
virtual WebInputEventResult HandleMouseWheel(LocalFrame& main_frame,
const WebMouseWheelEvent&);
virtual WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) = 0;
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 7ca6da99d9a..efd11fb5b5e 100644
--- a/chromium/third_party/blink/renderer/core/page/plugin_data.h
+++ b/chromium/third_party/blink/renderer/core/page/plugin_data.h
@@ -33,8 +33,7 @@ namespace blink {
class PluginInfo;
-class CORE_EXPORT MimeClassInfo final
- : public GarbageCollectedFinalized<MimeClassInfo> {
+class CORE_EXPORT MimeClassInfo final : public GarbageCollected<MimeClassInfo> {
public:
void Trace(blink::Visitor*);
@@ -54,8 +53,7 @@ class CORE_EXPORT MimeClassInfo final
Member<PluginInfo> plugin_;
};
-class CORE_EXPORT PluginInfo final
- : public GarbageCollectedFinalized<PluginInfo> {
+class CORE_EXPORT PluginInfo final : public GarbageCollected<PluginInfo> {
public:
void Trace(blink::Visitor*);
@@ -90,8 +88,7 @@ class CORE_EXPORT PluginInfo final
HeapVector<Member<MimeClassInfo>> mimes_;
};
-class CORE_EXPORT PluginData final
- : public GarbageCollectedFinalized<PluginData> {
+class CORE_EXPORT PluginData final : public GarbageCollected<PluginData> {
public:
void Trace(blink::Visitor*);
diff --git a/chromium/third_party/blink/renderer/core/page/print_context.cc b/chromium/third_party/blink/renderer/core/page/print_context.cc
index 2c91f87a726..d87dad4e1b0 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.cc
+++ b/chromium/third_party/blink/renderer/core/page/print_context.cc
@@ -70,7 +70,7 @@ void PrintContext::ComputePageRects(const FloatSize& print_size) {
}
auto* view = frame_->GetDocument()->GetLayoutView();
- const IntRect& document_rect = view->DocumentRect();
+ const PhysicalRect& document_rect = view->DocumentRect();
FloatSize page_size = frame_->ResizePageRectsKeepingRatio(
print_size, FloatSize(document_rect.Width(), document_rect.Height()));
ComputePageRectsWithPageSizeInternal(page_size);
@@ -89,7 +89,7 @@ void PrintContext::ComputePageRectsWithPageSizeInternal(
auto* view = frame_->GetDocument()->GetLayoutView();
- IntRect doc_rect = view->DocumentRect();
+ IntRect snapped_doc_rect = PixelSnappedIntRect(view->DocumentRect());
int page_width = page_size_in_pixels.Width();
// We scaled with floating point arithmetic and need to ensure results like
@@ -99,14 +99,15 @@ void PrintContext::ComputePageRectsWithPageSizeInternal(
bool is_horizontal = view->StyleRef().IsHorizontalWritingMode();
- int doc_logical_height = is_horizontal ? doc_rect.Height() : doc_rect.Width();
+ int doc_logical_height =
+ is_horizontal ? snapped_doc_rect.Height() : snapped_doc_rect.Width();
int page_logical_height = is_horizontal ? page_height : page_width;
int page_logical_width = is_horizontal ? page_width : page_height;
- int inline_direction_start = doc_rect.X();
- int inline_direction_end = doc_rect.MaxX();
- int block_direction_start = doc_rect.Y();
- int block_direction_end = doc_rect.MaxY();
+ int inline_direction_start = snapped_doc_rect.X();
+ int inline_direction_end = snapped_doc_rect.MaxX();
+ int block_direction_start = snapped_doc_rect.Y();
+ int block_direction_end = snapped_doc_rect.MaxY();
if (!is_horizontal) {
std::swap(block_direction_start, inline_direction_start);
std::swap(block_direction_end, inline_direction_end);
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 fdceab55c6a..18270df3f9a 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.h
+++ b/chromium/third_party/blink/renderer/core/page/print_context.h
@@ -37,8 +37,7 @@ class IntRect;
class LocalFrame;
class Node;
-class CORE_EXPORT PrintContext
- : public GarbageCollectedFinalized<PrintContext> {
+class CORE_EXPORT PrintContext : public GarbageCollected<PrintContext> {
public:
// By shrinking to a width of 75%, we will render the correct physical
// dimensions in paged media (i.e. cm, pt,). The shrinkage used
diff --git a/chromium/third_party/blink/renderer/core/page/print_context_test.cc b/chromium/third_party/blink/renderer/core/page/print_context_test.cc
index b14acfddfeb..cd38040c55b 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/print_context_test.cc
@@ -115,7 +115,8 @@ class PrintContextTest : public PaintTestConfigurations, public RenderingTest {
GraphicsContext& context = builder.Context();
context.SetPrinting(true);
GetDocument().View()->PaintContentsOutsideOfLifecycle(
- context, kGlobalPaintPrinting, CullRect(page_rect));
+ context, kGlobalPaintPrinting | kGlobalPaintAddUrlMetadata,
+ CullRect(page_rect));
{
DrawingRecorder recorder(
context, *GetDocument().GetLayoutView(),
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
index 6cea1198c05..28b4377bb51 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node.h"
@@ -33,7 +34,8 @@ Node* FindAnchorFromFragment(const String& fragment, Document& doc) {
} // namespace
ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
- LocalFrame& frame) {
+ LocalFrame& frame,
+ bool should_scroll) {
DCHECK(frame.GetDocument());
Document& doc = *frame.GetDocument();
@@ -72,7 +74,7 @@ ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
}
if (target) {
- target->ActivateDisplayLockIfNeeded();
+ target->ActivateDisplayLockIfNeeded(DisplayLockActivationReason::kUser);
target->DispatchActivateInvisibleEventIfNeeded();
}
@@ -82,6 +84,10 @@ ElementFragmentAnchor* ElementFragmentAnchor::TryCreate(const KURL& url,
if (!anchor_node)
return nullptr;
+ // Element fragment anchors only need to be kept alive if they need scrolling.
+ if (!should_scroll)
+ return nullptr;
+
return MakeGarbageCollected<ElementFragmentAnchor>(*anchor_node, frame);
}
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 bef10280e01..f51ce60afd2 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
@@ -29,7 +29,9 @@ class CORE_EXPORT ElementFragmentAnchor final : public FragmentAnchor {
// Parses the URL fragment and, if possible, creates and returns a fragment
// based on an Element in the page. Returns nullptr otherwise. Produces side
// effects related to fragment targeting in the page in either case.
- static ElementFragmentAnchor* TryCreate(const KURL& url, LocalFrame& frame);
+ static ElementFragmentAnchor* TryCreate(const KURL& url,
+ LocalFrame& frame,
+ bool should_scroll);
ElementFragmentAnchor(Node& anchor_node, LocalFrame& frame);
~ElementFragmentAnchor() override = default;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
index 5b3d161c9a1..db3ebbc7839 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.cc
@@ -15,7 +15,8 @@ namespace blink {
FragmentAnchor* FragmentAnchor::TryCreate(const KURL& url,
LocalFrame& frame,
- bool same_document_navigation) {
+ bool same_document_navigation,
+ bool should_scroll) {
DCHECK(frame.GetDocument());
FragmentAnchor* anchor = nullptr;
@@ -24,27 +25,18 @@ FragmentAnchor* FragmentAnchor::TryCreate(const KURL& url,
frame.GetDocument());
// The text fragment anchor will be created if we successfully parsed the
- // targetText but we only do the text matching later on.
+ // text directive but we only do the text matching later on.
bool text_fragment_anchor_created = false;
if (text_fragment_identifiers_enabled) {
anchor = TextFragmentAnchor::TryCreateFragmentDirective(
- url, frame, same_document_navigation);
+ url, frame, same_document_navigation, should_scroll);
text_fragment_anchor_created = anchor;
}
- // Count how often we see a # in the fragment (i.e. after the # delimiting
- // the hash). We avoid counting cases with ##targetText since we're trying to
- // determine how often this happens outside our feature so we don't want to
- // pollute it with our own usage.
+ // Count cases of other delimiter candidates. We don't care about whether
+ // they're followed by a text directive since they've never been used with
+ // it.
if (url.HasFragmentIdentifier()) {
- size_t hash_pos = url.FragmentIdentifier().Find("#");
- if (hash_pos != kNotFound) {
- if (url.FragmentIdentifier().Find("#targetText=") == kNotFound)
- UseCounter::Count(frame.GetDocument(), WebFeature::kFragmentDoubleHash);
- }
-
- // Count cases of other delimiter candidates. We don't care about whether
- // they're followed by targetText since they've never been used with it.
if (url.FragmentIdentifier().Find("~&~") != kNotFound) {
UseCounter::Count(frame.GetDocument(),
WebFeature::kFragmentHasTildeAmpersandTilde);
@@ -69,21 +61,10 @@ FragmentAnchor* FragmentAnchor::TryCreate(const KURL& url,
bool element_id_anchor_found = false;
if (!anchor) {
- anchor = ElementFragmentAnchor::TryCreate(url, frame);
+ anchor = ElementFragmentAnchor::TryCreate(url, frame, should_scroll);
element_id_anchor_found = anchor;
}
- if (text_fragment_identifiers_enabled) {
- FragmentAnchor* text_anchor =
- TextFragmentAnchor::TryCreate(url, frame, same_document_navigation);
- text_fragment_anchor_created |= static_cast<bool>(text_anchor);
- // We parse the anchor to determine if we should report the UMA metric
- // below but we should only use it if we didn't find an element-id based
- // fragment.
- if (!anchor)
- anchor = text_anchor;
- }
-
// Track how often we have a element fragment that we can't find. Only track
// if we didn't match a text fragment since we expect those would inflate the
// "failed" case.
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
index ffe384df6a8..7550d5674a9 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/fragment_anchor.h
@@ -24,8 +24,7 @@ class KURL;
// can implement, allowing fragments to specify different kinds of anchors.
// Callers should use the TryCreate static method to create and return the
// appropriate type of base class.
-class CORE_EXPORT FragmentAnchor
- : public GarbageCollectedFinalized<FragmentAnchor> {
+class CORE_EXPORT FragmentAnchor : public GarbageCollected<FragmentAnchor> {
public:
// Parses the fragment string and tries to create a FragmentAnchor object of
// the appropriate derived type. If no anchor could be created from the given
@@ -33,7 +32,8 @@ class CORE_EXPORT FragmentAnchor
// will be performed, for example, setting/clearing :target and svgView().
static FragmentAnchor* TryCreate(const KURL& url,
LocalFrame& frame,
- bool same_document_navigation);
+ bool same_document_navigation,
+ bool should_scroll);
FragmentAnchor() = default;
virtual ~FragmentAnchor() = default;
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 164aeac6bb2..d003626470b 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
@@ -71,6 +71,14 @@ class MainThreadScrollingReasonsTest : public testing::Test {
WebString(base_url_), test::CoreTestDataPath(), WebString(file_name));
}
+ uint32_t GetMainThreadScrollingReasons(const GraphicsLayer& layer) const {
+ const auto* scroll = layer.GetPropertyTreeState()
+ .Transform()
+ .NearestScrollTranslationNode()
+ .ScrollNode();
+ return scroll->GetMainThreadScrollingReasons();
+ }
+
uint32_t GetViewMainThreadScrollingReasons() const {
const auto* scroll = GetFrame()
->View()
@@ -135,7 +143,7 @@ TEST_F(MainThreadScrollingReasonsTest,
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_TRUE(
- cc_scroll_layer->GetMainThreadScrollingReasons() &
+ GetMainThreadScrollingReasons(*scroll_layer) &
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
// Remove fixed background-attachment should make the iframe
@@ -157,7 +165,7 @@ TEST_F(MainThreadScrollingReasonsTest,
cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_FALSE(
- cc_scroll_layer->GetMainThreadScrollingReasons() &
+ GetMainThreadScrollingReasons(*scroll_layer) &
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
// Force main frame to scroll on main thread. All its descendants
@@ -180,7 +188,7 @@ TEST_F(MainThreadScrollingReasonsTest,
cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
ASSERT_TRUE(
- cc_scroll_layer->GetMainThreadScrollingReasons() &
+ GetMainThreadScrollingReasons(*scroll_layer) &
cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects);
}
@@ -232,10 +240,11 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingCanBeDisabledWithSetting) {
EXPECT_TRUE(GetViewMainThreadScrollingReasons());
// Main scrolling should also propagate to inner viewport layer.
- cc::Layer* inner_viewport_scroll_layer =
- GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
- ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
- EXPECT_TRUE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& visual_viewport_scroll_graphics_layer =
+ *GetFrame()->GetPage()->GetVisualViewport().ScrollLayer();
+ ASSERT_TRUE(visual_viewport_scroll_graphics_layer.CcLayer()->scrollable());
+ EXPECT_TRUE(
+ GetMainThreadScrollingReasons(visual_viewport_scroll_graphics_layer));
}
TEST_F(MainThreadScrollingReasonsTest, FastScrollingForFixedPosition) {
@@ -264,10 +273,11 @@ TEST_F(MainThreadScrollingReasonsTest, FastScrollingByDefault) {
// Fast scrolling should be enabled by default.
EXPECT_FALSE(GetViewMainThreadScrollingReasons());
- cc::Layer* inner_viewport_scroll_layer =
- GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
- ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
- EXPECT_FALSE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& visual_viewport_scroll_graphics_layer =
+ *GetFrame()->GetPage()->GetVisualViewport().ScrollLayer();
+ ASSERT_TRUE(visual_viewport_scroll_graphics_layer.CcLayer()->scrollable());
+ EXPECT_FALSE(
+ GetMainThreadScrollingReasons(visual_viewport_scroll_graphics_layer));
}
TEST_F(MainThreadScrollingReasonsTest,
@@ -291,9 +301,8 @@ TEST_F(MainThreadScrollingReasonsTest,
ASSERT_TRUE(scrollbar_graphics_layer);
bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent();
- EXPECT_TRUE(
- has_cc_scrollbar_layer ||
- scrollbar_graphics_layer->CcLayer()->GetMainThreadScrollingReasons());
+ EXPECT_TRUE(has_cc_scrollbar_layer ||
+ GetMainThreadScrollingReasons(*scrollbar_graphics_layer));
}
class NonCompositedMainThreadScrollingReasonsTest
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
index cad82fbd738..ee3bbb94f37 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
@@ -17,7 +17,6 @@
#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/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -410,11 +409,6 @@ void RootScrollerController::ProcessImplicitCandidates() {
implicit_root_scroller_ = nullptr;
}
-PaintLayer* RootScrollerController::RootScrollerPaintLayer() const {
- return root_scroller_util::PaintLayerForRootScroller(
- effective_root_scroller_);
-}
-
void RootScrollerController::ElementRemoved(const Element& element) {
if (element != effective_root_scroller_.Get())
return;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h
index c7cb908c130..834957baf45 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h
@@ -13,7 +13,6 @@ namespace blink {
class Document;
class Element;
class HTMLFrameOwnerElement;
-class PaintLayer;
// Manages the root scroller associated with a given document. The root
// scroller causes browser controls movement, overscroll effects and prevents
@@ -72,10 +71,6 @@ class CORE_EXPORT RootScrollerController
// root scroller and set the appropriate properties on the view.
void DidUpdateIFrameFrameView(HTMLFrameOwnerElement&);
- // Returns the PaintLayer associated with the currently effective root
- // scroller.
- PaintLayer* RootScrollerPaintLayer() const;
-
void ElementRemoved(const Element&);
// In the "implicit root scroller" mode, we might promote an element to
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 120ccb2dd8b..244ff2ac856 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_console_message.h"
@@ -539,8 +540,6 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// No root scroller set, the document node should be the global root and the
// main LocalFrameView's scroll layer should be the layer to use.
{
- EXPECT_EQ(main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->GetApplyScroll()));
}
@@ -550,8 +549,6 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
{
SetAndSelectRootScroller(*iframe->contentDocument(), container);
- EXPECT_EQ(main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->GetApplyScroll()));
}
@@ -562,10 +559,6 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
{
SetAndSelectRootScroller(*MainFrame()->GetDocument(), iframe);
- ScrollableArea* container_scroller =
- ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
- EXPECT_EQ(main_controller.RootScrollerLayer(),
- container_scroller->LayerForScrolling());
EXPECT_FALSE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->GetApplyScroll()));
EXPECT_TRUE(
@@ -577,10 +570,6 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// scroller.
{
SetAndSelectRootScroller(*iframe->contentDocument(), nullptr);
- EXPECT_EQ(main_controller.RootScrollerLayer(), iframe->contentDocument()
- ->View()
- ->LayoutViewport()
- ->LayerForScrolling());
EXPECT_FALSE(
main_controller.IsViewportScrollCallback(container->GetApplyScroll()));
EXPECT_FALSE(main_controller.IsViewportScrollCallback(
@@ -593,8 +582,6 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// document node and corresponding layer.
{
SetAndSelectRootScroller(*MainFrame()->GetDocument(), nullptr);
- EXPECT_EQ(main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->GetApplyScroll()));
EXPECT_FALSE(
@@ -880,11 +867,6 @@ TEST_F(RootScrollerTest, NonMainLocalRootLifecycle) {
ASSERT_EQ(MainFrame()->GetDocument(), global_controller.GlobalRootScroller());
UpdateAllLifecyclePhases(MainFrameView());
- GraphicsLayer* scroll_layer = global_controller.RootScrollerLayer();
- GraphicsLayer* container_layer = global_controller.RootContainerLayer();
-
- ASSERT_TRUE(scroll_layer);
- ASSERT_TRUE(container_layer);
// Put the local main frame into Layout clean and have the non-main local
// root do a complete lifecycle update.
@@ -894,8 +876,6 @@ TEST_F(RootScrollerTest, NonMainLocalRootLifecycle) {
UpdateAllLifecyclePhases(helper_.LocalMainFrame()->GetFrameView());
EXPECT_EQ(MainFrame()->GetDocument(), global_controller.GlobalRootScroller());
- EXPECT_EQ(global_controller.RootScrollerLayer(), scroll_layer);
- EXPECT_EQ(global_controller.RootContainerLayer(), container_layer);
}
// Tests that removing the root scroller element from the DOM resets the
@@ -940,8 +920,6 @@ TEST_F(RootScrollerTest, DocumentElementHasNoLayoutObject) {
MainFrame()->GetDocument()->GetPage()->GlobalRootScrollerController();
EXPECT_EQ(MainFrame()->GetDocument(), global_controller.GlobalRootScroller());
- EXPECT_EQ(MainFrameView()->LayoutViewport()->LayerForScrolling(),
- global_controller.RootScrollerLayer());
}
// On Android, the main scrollbars are owned by the visual viewport and the
@@ -2354,7 +2332,7 @@ TEST_F(ImplicitRootScrollerSimTest,
EXPECT_EQ(container,
GetDocument().GetRootScrollerController().EffectiveRootScroller());
EXPECT_EQ(ToLayoutBox(container->GetLayoutObject())->Size().Height(), 600);
- WebView().SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0));
+ WebView().SetZoomLevel(PageZoomFactorToZoomLevel(2.0));
WebView().GetPage()->GetBrowserControls().SetShownRatio(0);
WebView().ResizeWithBrowserControls(IntSize(800, 650), 50, 0, false);
Compositor().BeginFrame();
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
deleted file mode 100644
index 9b464e6daa3..00000000000
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
+++ /dev/null
@@ -1,37 +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/page/scrolling/root_scroller_util.h"
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.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/page/page.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
-#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-
-namespace blink {
-
-namespace root_scroller_util {
-
-PaintLayer* PaintLayerForRootScroller(const Node* node) {
- if (!node)
- return nullptr;
-
- if (!node->GetLayoutObject() || !node->GetLayoutObject()->IsBox())
- return nullptr;
-
- LayoutBox* box = ToLayoutBox(node->GetLayoutObject());
- return box->Layer();
-}
-
-} // namespace root_scroller_util
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.h b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.h
deleted file mode 100644
index 9c444455687..00000000000
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_ROOT_SCROLLER_UTIL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_ROOT_SCROLLER_UTIL_H_
-
-namespace blink {
-
-class Node;
-class PaintLayer;
-
-namespace root_scroller_util {
-
-// Returns the PaintLayer that'll be used as the root scrolling layer. For the
-// <html> element and document Node, this returns the LayoutView's PaintLayer
-// rather than <html>'s since scrolling is handled by LayoutView.
-PaintLayer* PaintLayerForRootScroller(const Node*);
-
-} // namespace root_scroller_util
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_ROOT_SCROLLER_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h
index 840f045958b..ecb13e2ea66 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h
@@ -13,8 +13,7 @@ namespace blink {
class ScrollState;
-class ScrollStateCallback
- : public GarbageCollectedFinalized<ScrollStateCallback> {
+class ScrollStateCallback : public GarbageCollected<ScrollStateCallback> {
public:
virtual ~ScrollStateCallback() = default;
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 9ebf3ffa41f..eb84f2363f1 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
@@ -34,12 +34,9 @@
#include "cc/layers/painted_overlay_scrollbar_layer.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/picture_layer.h"
-#include "cc/layers/scrollbar_layer_interface.h"
+#include "cc/layers/scrollbar_layer_base.h"
#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_element.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"
@@ -48,19 +45,15 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/layout/geometry/transform_state.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/core/page/scrolling/scrolling_coordinator_context.h"
-#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer.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/core/scroll/scrollbar_layer_delegate.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
-#include "third_party/blink/renderer/platform/geometry/region.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/histogram.h"
@@ -89,14 +82,6 @@ void ScrollingCoordinator::Trace(blink::Visitor* visitor) {
visitor->Trace(vertical_scrollbars_);
}
-void ScrollingCoordinator::SetShouldHandleScrollGestureOnMainThreadRegion(
- const Region& region,
- GraphicsLayer* layer) {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
- if (cc::Layer* cc_layer = GraphicsLayerToCcLayer(layer))
- cc_layer->SetNonFastScrollableRegion(RegionToCCRegion(region));
-}
-
void ScrollingCoordinator::NotifyGeometryChanged(LocalFrameView* frame_view) {
frame_view->GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
frame_view->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(true);
@@ -201,7 +186,6 @@ static void ForAllPaintingGraphicsLayers(GraphicsLayer& layer,
// Set the non-fast scrollable regions on |layer|'s cc layer.
static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) {
- DCHECK(RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
// CompositeAfterPaint does this update in PaintArtifactCompositor.
DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
@@ -230,27 +214,9 @@ static void UpdateLayerNonFastScrollableRegions(GraphicsLayer& layer) {
// div/textarea/iframe when CSS property "resize" is enabled.
// 3. Plugin areas.
void ScrollingCoordinator::UpdateNonFastScrollableRegions(LocalFrame* frame) {
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- auto* view_layer = frame->View()->GetLayoutView()->Layer();
- if (auto* root = view_layer->Compositor()->PaintRootGraphicsLayer())
- ForAllPaintingGraphicsLayers(*root, UpdateLayerNonFastScrollableRegions);
- } else {
- Region main_thread_scrolling_region;
- Region main_thread_fixed_region;
- ComputeShouldHandleScrollGestureOnMainThreadRegion(
- frame, &main_thread_scrolling_region, &main_thread_fixed_region);
-
- SetShouldHandleScrollGestureOnMainThreadRegion(
- main_thread_scrolling_region,
- frame->View()->GetScrollableArea()->LayerForScrolling());
-
- // Fixed regions will be stored on the visual viewport's scroll layer.
- // This is because a region for an area that's fixed to the layout
- // viewport won't move when the layout viewport scrolls.
- SetShouldHandleScrollGestureOnMainThreadRegion(
- main_thread_fixed_region,
- page_->GetVisualViewport().LayerForScrolling());
- }
+ auto* view_layer = frame->View()->GetLayoutView()->Layer();
+ if (auto* root = view_layer->Compositor()->PaintRootGraphicsLayer())
+ ForAllPaintingGraphicsLayers(*root, UpdateLayerNonFastScrollableRegions);
}
// Set the touch action rects on the cc layer from the touch action data stored
@@ -272,50 +238,42 @@ static void UpdateLayerTouchActionRects(GraphicsLayer& layer) {
void ScrollingCoordinator::WillDestroyScrollableArea(
ScrollableArea* scrollable_area) {
- RemoveScrollbarLayerGroup(scrollable_area, kHorizontalScrollbar);
- RemoveScrollbarLayerGroup(scrollable_area, kVerticalScrollbar);
+ RemoveScrollbarLayer(scrollable_area, kHorizontalScrollbar);
+ RemoveScrollbarLayer(scrollable_area, kVerticalScrollbar);
}
-void ScrollingCoordinator::RemoveScrollbarLayerGroup(
+void ScrollingCoordinator::RemoveScrollbarLayer(
ScrollableArea* scrollable_area,
ScrollbarOrientation orientation) {
ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
? horizontal_scrollbars_
: vertical_scrollbars_;
- if (std::unique_ptr<ScrollbarLayerGroup> scrollbar_layer_group =
+ if (scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer =
scrollbars.Take(scrollable_area)) {
- GraphicsLayer::UnregisterContentsLayer(scrollbar_layer_group->layer.get());
+ GraphicsLayer::UnregisterContentsLayer(scrollbar_layer.get());
}
}
-static std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
-CreateScrollbarLayer(Scrollbar& scrollbar, float device_scale_factor) {
+static scoped_refptr<cc::ScrollbarLayerBase> CreateScrollbarLayer(
+ Scrollbar& scrollbar,
+ float device_scale_factor) {
ScrollbarTheme& theme = scrollbar.GetTheme();
auto scrollbar_delegate =
std::make_unique<ScrollbarLayerDelegate>(scrollbar, device_scale_factor);
-
- auto layer_group =
- std::make_unique<ScrollingCoordinator::ScrollbarLayerGroup>();
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer;
if (theme.UsesOverlayScrollbars() && theme.UsesNinePatchThumbResource()) {
- auto scrollbar_layer = cc::PaintedOverlayScrollbarLayer::Create(
- std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
- scrollbar_layer->SetElementId(scrollbar.GetElementId());
- layer_group->scrollbar_layer = scrollbar_layer.get();
- layer_group->layer = std::move(scrollbar_layer);
+ scrollbar_layer =
+ cc::PaintedOverlayScrollbarLayer::Create(std::move(scrollbar_delegate));
} else {
- auto scrollbar_layer = cc::PaintedScrollbarLayer::Create(
- std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
- scrollbar_layer->SetElementId(scrollbar.GetElementId());
- layer_group->scrollbar_layer = scrollbar_layer.get();
- layer_group->layer = std::move(scrollbar_layer);
+ scrollbar_layer =
+ cc::PaintedScrollbarLayer::Create(std::move(scrollbar_delegate));
}
-
- GraphicsLayer::RegisterContentsLayer(layer_group->layer.get());
-
- return layer_group;
+ scrollbar_layer->SetElementId(scrollbar.GetElementId());
+ GraphicsLayer::RegisterContentsLayer(scrollbar_layer.get());
+ return scrollbar_layer;
}
-std::unique_ptr<ScrollingCoordinator::ScrollbarLayerGroup>
+scoped_refptr<cc::ScrollbarLayerBase>
ScrollingCoordinator::CreateSolidColorScrollbarLayer(
ScrollbarOrientation orientation,
int thumb_thickness,
@@ -326,15 +284,10 @@ ScrollingCoordinator::CreateSolidColorScrollbarLayer(
orientation == kHorizontalScrollbar ? cc::HORIZONTAL : cc::VERTICAL;
auto scrollbar_layer = cc::SolidColorScrollbarLayer::Create(
cc_orientation, thumb_thickness, track_start,
- is_left_side_vertical_scrollbar, cc::ElementId());
+ is_left_side_vertical_scrollbar);
scrollbar_layer->SetElementId(element_id);
-
- auto layer_group = std::make_unique<ScrollbarLayerGroup>();
- layer_group->scrollbar_layer = scrollbar_layer.get();
- layer_group->layer = std::move(scrollbar_layer);
- GraphicsLayer::RegisterContentsLayer(layer_group->layer.get());
-
- return layer_group;
+ GraphicsLayer::RegisterContentsLayer(scrollbar_layer.get());
+ return scrollbar_layer;
}
static void DetachScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer) {
@@ -345,10 +298,9 @@ static void DetachScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer) {
scrollbar_graphics_layer->SetHitTestable(true);
}
-static void SetupScrollbarLayer(
- GraphicsLayer* scrollbar_graphics_layer,
- const ScrollingCoordinator::ScrollbarLayerGroup* scrollbar_layer_group,
- cc::Layer* scrolling_layer) {
+static void SetupScrollbarLayer(GraphicsLayer* scrollbar_graphics_layer,
+ cc::ScrollbarLayerBase* scrollbar_layer,
+ cc::Layer* scrolling_layer) {
DCHECK(scrollbar_graphics_layer);
if (!scrolling_layer) {
@@ -356,28 +308,27 @@ static void SetupScrollbarLayer(
return;
}
- scrollbar_layer_group->scrollbar_layer->SetScrollElementId(
- scrolling_layer->element_id());
+ scrollbar_layer->SetScrollElementId(scrolling_layer->element_id());
scrollbar_graphics_layer->SetContentsToCcLayer(
- scrollbar_layer_group->layer.get(),
+ scrollbar_layer,
/*prevent_contents_opaque_changes=*/false);
scrollbar_graphics_layer->SetDrawsContent(false);
scrollbar_graphics_layer->SetHitTestable(false);
}
-void ScrollingCoordinator::AddScrollbarLayerGroup(
+void ScrollingCoordinator::AddScrollbarLayer(
ScrollableArea* scrollable_area,
ScrollbarOrientation orientation,
- std::unique_ptr<ScrollbarLayerGroup> scrollbar_layer_group) {
+ scoped_refptr<cc::ScrollbarLayerBase> scrollbar_layer_group) {
ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
? horizontal_scrollbars_
: vertical_scrollbars_;
scrollbars.insert(scrollable_area, std::move(scrollbar_layer_group));
}
-ScrollingCoordinator::ScrollbarLayerGroup*
-ScrollingCoordinator::GetScrollbarLayerGroup(ScrollableArea* scrollable_area,
- ScrollbarOrientation orientation) {
+cc::ScrollbarLayerBase* ScrollingCoordinator::GetScrollbarLayer(
+ ScrollableArea* scrollable_area,
+ ScrollbarOrientation orientation) {
ScrollbarMap& scrollbars = orientation == kHorizontalScrollbar
? horizontal_scrollbars_
: vertical_scrollbars_;
@@ -405,31 +356,32 @@ void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
return;
}
- ScrollbarLayerGroup* scrollbar_layer_group =
- GetScrollbarLayerGroup(scrollable_area, orientation);
- if (!scrollbar_layer_group) {
+ cc::ScrollbarLayerBase* scrollbar_layer =
+ GetScrollbarLayer(scrollable_area, orientation);
+ if (!scrollbar_layer) {
Settings* settings = page_->MainFrame()->GetSettings();
- std::unique_ptr<ScrollbarLayerGroup> group;
+ scoped_refptr<cc::ScrollbarLayerBase> new_scrollbar_layer;
if (settings->GetUseSolidColorScrollbars()) {
DCHECK(RuntimeEnabledFeatures::OverlayScrollbarsEnabled());
- group = CreateSolidColorScrollbarLayer(
+ new_scrollbar_layer = CreateSolidColorScrollbarLayer(
orientation, scrollbar.GetTheme().ThumbThickness(scrollbar),
scrollbar.GetTheme().TrackPosition(scrollbar),
scrollable_area->ShouldPlaceVerticalScrollbarOnLeft(),
scrollable_area->GetScrollbarElementId(orientation));
} else {
- group = CreateScrollbarLayer(scrollbar,
- page_->DeviceScaleFactorDeprecated());
+ new_scrollbar_layer = CreateScrollbarLayer(
+ scrollbar, page_->DeviceScaleFactorDeprecated());
}
- scrollbar_layer_group = group.get();
- AddScrollbarLayerGroup(scrollable_area, orientation, std::move(group));
+ scrollbar_layer = new_scrollbar_layer.get();
+ AddScrollbarLayer(scrollable_area, orientation,
+ std::move(new_scrollbar_layer));
}
cc::Layer* scroll_layer =
GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
- SetupScrollbarLayer(scrollbar_graphics_layer, scrollbar_layer_group,
+ SetupScrollbarLayer(scrollbar_graphics_layer, scrollbar_layer,
scroll_layer);
// Root layer non-overlay scrollbars should be marked opaque to disable
@@ -438,7 +390,7 @@ void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
scrollbar_graphics_layer->SetContentsOpaque(
IsForMainFrame(scrollable_area) && is_opaque_scrollbar);
} else {
- RemoveScrollbarLayerGroup(scrollable_area, orientation);
+ RemoveScrollbarLayer(scrollable_area, orientation);
}
}
@@ -465,11 +417,7 @@ void ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
cc::Layer* cc_layer =
GraphicsLayerToCcLayer(scrollable_area->LayerForScrolling());
- cc::Layer* container_layer =
- GraphicsLayerToCcLayer(scrollable_area->LayerForContainer());
if (cc_layer) {
- cc_layer->SetScrollable(container_layer->bounds());
-
// TODO(bokan): This method shouldn't be resizing the layer geometry. That
// happens in CompositedLayerMapping::UpdateScrollingLayerGeometry.
PhysicalOffset subpixel_accumulation =
@@ -485,13 +433,15 @@ void ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
PhysicalRect(subpixel_accumulation, contents_size).PixelSnappedSize();
if (scrollable_area != &page_->GetVisualViewport()) {
+ IntSize container_size = scrollable_area->VisibleContentRect().Size();
+ cc_layer->SetScrollable(gfx::Size(container_size));
+
// The scrolling contents layer must be at least as large as its clip.
// The visual viewport is special because the size of its scrolling
// content depends on the page scale factor. Its scrollable content is
// the layout viewport which is sized based on the minimum allowed page
// scale so it actually can be smaller than its clip.
- scroll_contents_size =
- scroll_contents_size.ExpandedTo(IntSize(container_layer->bounds()));
+ scroll_contents_size = scroll_contents_size.ExpandedTo(container_size);
// VisualViewport scrolling may involve pinch zoom and gets routed through
// WebViewImpl explicitly rather than via ScrollingCoordinator::DidScroll
@@ -505,31 +455,22 @@ void ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
scrollable_area->LayerForScrolling()->SetSize(
static_cast<gfx::Size>(scroll_contents_size));
}
- if (ScrollbarLayerGroup* scrollbar_layer_group =
- GetScrollbarLayerGroup(scrollable_area, kHorizontalScrollbar)) {
- GraphicsLayer* horizontal_scrollbar_layer =
- scrollable_area->LayerForHorizontalScrollbar();
- if (horizontal_scrollbar_layer) {
- SetupScrollbarLayer(horizontal_scrollbar_layer, scrollbar_layer_group,
+ if (cc::ScrollbarLayerBase* scrollbar_layer =
+ GetScrollbarLayer(scrollable_area, kHorizontalScrollbar)) {
+ if (GraphicsLayer* horizontal_scrollbar_layer =
+ scrollable_area->LayerForHorizontalScrollbar()) {
+ SetupScrollbarLayer(horizontal_scrollbar_layer, scrollbar_layer,
cc_layer);
}
}
- if (ScrollbarLayerGroup* scrollbar_layer_group =
- GetScrollbarLayerGroup(scrollable_area, kVerticalScrollbar)) {
- GraphicsLayer* vertical_scrollbar_layer =
- scrollable_area->LayerForVerticalScrollbar();
-
- if (vertical_scrollbar_layer) {
- SetupScrollbarLayer(vertical_scrollbar_layer, scrollbar_layer_group,
- cc_layer);
+ if (cc::ScrollbarLayerBase* scrollbar_layer =
+ GetScrollbarLayer(scrollable_area, kVerticalScrollbar)) {
+ if (GraphicsLayer* vertical_scrollbar_layer =
+ scrollable_area->LayerForVerticalScrollbar()) {
+ SetupScrollbarLayer(vertical_scrollbar_layer, scrollbar_layer, cc_layer);
}
}
- // Update the viewport layer registration if the outer viewport may have
- // changed.
- if (IsForRootLayer(scrollable_area))
- page_->GetChromeClient().RegisterViewportLayers();
-
CompositorAnimationTimeline* timeline;
// LocalFrameView::CompositorAnimationTimeline() can indirectly return
// m_programmaticScrollAnimatorTimeline if it does not have its own
@@ -559,9 +500,9 @@ void ScrollingCoordinator::UpdateTouchEventTargetRectsIfNeeded(
void ScrollingCoordinator::Reset(LocalFrame* frame) {
for (const auto& scrollbar : horizontal_scrollbars_)
- GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
+ GraphicsLayer::UnregisterContentsLayer(scrollbar.value.get());
for (const auto& scrollbar : vertical_scrollbars_)
- GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
+ GraphicsLayer::UnregisterContentsLayer(scrollbar.value.get());
horizontal_scrollbars_.clear();
vertical_scrollbars_.clear();
@@ -636,9 +577,9 @@ void ScrollingCoordinator::WillBeDestroyed() {
page_ = nullptr;
for (const auto& scrollbar : horizontal_scrollbars_)
- GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
+ GraphicsLayer::UnregisterContentsLayer(scrollbar.value.get());
for (const auto& scrollbar : vertical_scrollbars_)
- GraphicsLayer::UnregisterContentsLayer(scrollbar.value->layer.get());
+ GraphicsLayer::UnregisterContentsLayer(scrollbar.value.get());
}
bool ScrollingCoordinator::CoordinatesScrollingForFrameView(
@@ -652,133 +593,6 @@ bool ScrollingCoordinator::CoordinatesScrollingForFrameView(
return layout_view->UsesCompositing();
}
-namespace {
-
-bool ScrollsWithRootFrame(LayoutObject* object) {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
-
- DCHECK(object);
- DCHECK(object->GetFrame());
-
- // TODO(bokan): Speculative fix for https://crbug.com/964293.
- if (!object || !object->GetNode())
- return true;
-
- const LocalFrame& frame = *object->GetFrame();
-
- // If we're in an iframe document, we need to determine if the containing
- // <iframe> element scrolls with the root frame.
- if (&frame != &frame.LocalFrameRoot()) {
- DCHECK(frame.GetDocument());
- DCHECK(frame.GetDocument()->LocalOwner());
- DCHECK(frame.GetDocument()->LocalOwner()->GetLayoutObject());
- return ScrollsWithRootFrame(
- frame.GetDocument()->LocalOwner()->GetLayoutObject());
- }
-
- DCHECK(object->EnclosingLayer());
- if (object->EnclosingLayer()->AncestorScrollingLayer() ==
- frame.ContentLayoutObject()->Layer())
- return true;
-
- // TODO(bokan): Returning false unconditionally here is actually wrong but we
- // do this because NonFastScrollableRegions are stored only on the layout and
- // visual viewport's scroll layers. This can lead to issues when subscroller
- // layers are scrolled (e.g. https://crbug.com/817600). These should really
- // be stored on the nearest ancestor ScrollNode, rather than the root
- // viewport. Should be addressed by https://crbug.com/864567.
- return false;
-}
-
-} // namespace
-
-void ScrollingCoordinator::ComputeShouldHandleScrollGestureOnMainThreadRegion(
- const LocalFrame* frame,
- Region* scrolling_region,
- Region* fixed_region) const {
- DCHECK(!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
-
- LocalFrameView* frame_view = frame->View();
- DCHECK(scrolling_region);
- DCHECK(fixed_region);
-
- if (!frame_view || frame_view->ShouldThrottleRendering() ||
- !frame_view->IsVisible()) {
- return;
- }
-
- LocalFrameView* local_root_view = frame->LocalFrameRoot().View();
-
- if (const LocalFrameView::ScrollableAreaSet* scrollable_areas =
- frame_view->ScrollableAreas()) {
- for (const ScrollableArea* scrollable_area : *scrollable_areas) {
- // Composited scrollable areas can be scrolled off the main thread.
- if (scrollable_area->UsesCompositedScrolling())
- continue;
-
- if (ScrollsWithRootFrame(scrollable_area->GetLayoutBox())) {
- scrolling_region->Unite(scrollable_area->ScrollableAreaBoundingBox());
- } else {
- fixed_region->Unite(local_root_view->DocumentToFrame(
- scrollable_area->ScrollableAreaBoundingBox()));
- }
- }
- }
-
- // We use GestureScrollBegin/Update/End for moving the resizer handle. So we
- // mark these small resizer areas as non-fast-scrollable to allow the scroll
- // gestures to be passed to main thread if they are targeting the resizer
- // area. (Resizing is done in EventHandler.cpp on main thread).
- if (const LocalFrameView::ResizerAreaSet* resizer_areas =
- frame_view->ResizerAreas()) {
- for (const LayoutBox* box : *resizer_areas) {
- PaintLayerScrollableArea* scrollable_area =
- box->Layer()->GetScrollableArea();
-
- IntRect bounds_in_frame = box->AbsoluteBoundingBoxRect();
- IntRect corner_in_frame =
- scrollable_area->ResizerCornerRect(bounds_in_frame, kResizerForTouch);
-
- IntRect corner_in_root_frame =
- EnclosingIntRect(scrollable_area->GetLayoutBox()->LocalToAbsoluteRect(
- PhysicalRect(corner_in_frame), kTraverseDocumentBoundaries));
-
- if (ScrollsWithRootFrame(scrollable_area->GetLayoutBox())) {
- scrolling_region->Unite(
- local_root_view->FrameToDocument(corner_in_root_frame));
- } else {
- fixed_region->Unite(corner_in_root_frame);
- }
- }
- }
-
- for (const auto& plugin : frame_view->Plugins()) {
- Element* element = plugin->GetElement();
- // Plugins can run script during layout so ensure the plugin wasn't removed
- // since being added to the Plugins set.
- if (!element->GetLayoutObject())
- continue;
-
- if (plugin->WantsWheelEvents()) {
- IntRect box = frame_view->ConvertToRootFrame(plugin->FrameRect());
- if (ScrollsWithRootFrame(element->GetLayoutObject())) {
- scrolling_region->Unite(local_root_view->FrameToDocument(box));
- } else {
- fixed_region->Unite(box);
- }
- }
- }
-
- const FrameTree& tree = frame->Tree();
- for (Frame* sub_frame = tree.FirstChild(); sub_frame;
- sub_frame = sub_frame->Tree().NextSibling()) {
- if (auto* sub_local_frame = DynamicTo<LocalFrame>(sub_frame)) {
- ComputeShouldHandleScrollGestureOnMainThreadRegion(
- sub_local_frame, scrolling_region, fixed_region);
- }
- }
-}
-
void ScrollingCoordinator::
FrameViewHasBackgroundAttachmentFixedObjectsDidChange(
LocalFrameView* frame_view) {
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 ce4b40dae01..30f3fd98391 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
@@ -38,15 +38,13 @@
namespace cc {
class AnimationHost;
-class Layer;
-class ScrollbarLayerInterface;
+class ScrollbarLayerBase;
} // namespace cc
namespace blink {
class CompositorAnimationTimeline;
class LocalFrame;
class LocalFrameView;
-class GraphicsLayer;
class Page;
class Region;
class ScrollableArea;
@@ -63,17 +61,8 @@ using ScrollbarId = uint64_t;
// compositor, as well as creating and managing scrollbar layers.
class CORE_EXPORT ScrollingCoordinator final
- : public GarbageCollectedFinalized<ScrollingCoordinator> {
+ : public GarbageCollected<ScrollingCoordinator> {
public:
- struct ScrollbarLayerGroup {
- // The compositor layer for the scrollbar. It can be one of a few
- // concrete types, so we store the base type.
- scoped_refptr<cc::Layer> layer;
- // An interface shared by all scrollbar layer types since we don't know
- // the concrete |layer| type.
- cc::ScrollbarLayerInterface* scrollbar_layer = nullptr;
- };
-
explicit ScrollingCoordinator(Page*);
~ScrollingCoordinator();
void Trace(blink::Visitor*);
@@ -110,7 +99,7 @@ class CORE_EXPORT ScrollingCoordinator final
// Should be called whenever the root layer for the given frame view changes.
void FrameViewRootLayerDidChange(LocalFrameView*);
- std::unique_ptr<ScrollbarLayerGroup> CreateSolidColorScrollbarLayer(
+ scoped_refptr<cc::ScrollbarLayerBase> CreateSolidColorScrollbarLayer(
ScrollbarOrientation,
int thumb_thickness,
int track_start,
@@ -185,15 +174,12 @@ class CORE_EXPORT ScrollingCoordinator final
bool should_scroll_on_main_thread_dirty_;
private:
- void SetShouldHandleScrollGestureOnMainThreadRegion(const Region&,
- GraphicsLayer*);
-
- void AddScrollbarLayerGroup(ScrollableArea*,
- ScrollbarOrientation,
- std::unique_ptr<ScrollbarLayerGroup>);
- ScrollbarLayerGroup* GetScrollbarLayerGroup(ScrollableArea*,
- ScrollbarOrientation);
- void RemoveScrollbarLayerGroup(ScrollableArea*, ScrollbarOrientation);
+ void AddScrollbarLayer(ScrollableArea*,
+ ScrollbarOrientation,
+ scoped_refptr<cc::ScrollbarLayerBase>);
+ cc::ScrollbarLayerBase* GetScrollbarLayer(ScrollableArea*,
+ ScrollbarOrientation);
+ void RemoveScrollbarLayer(ScrollableArea*, ScrollbarOrientation);
bool FrameScrollerIsDirty(LocalFrameView*) const;
@@ -201,8 +187,8 @@ class CORE_EXPORT ScrollingCoordinator final
std::unique_ptr<CompositorAnimationTimeline>
programmatic_scroll_animator_timeline_;
- using ScrollbarMap =
- HeapHashMap<Member<ScrollableArea>, std::unique_ptr<ScrollbarLayerGroup>>;
+ using ScrollbarMap = HeapHashMap<Member<ScrollableArea>,
+ scoped_refptr<cc::ScrollbarLayerBase>>;
ScrollbarMap horizontal_scrollbars_;
ScrollbarMap vertical_scrollbars_;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index d3bf6a5734c..4f6ce0a1149 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -66,14 +66,10 @@
namespace blink {
-class ScrollingCoordinatorTest
- : public testing::Test,
- public testing::WithParamInterface<bool>,
- private ScopedPaintNonFastScrollableRegionsForTest {
+class ScrollingCoordinatorTest : public testing::Test,
+ public testing::WithParamInterface<bool> {
public:
- ScrollingCoordinatorTest()
- : ScopedPaintNonFastScrollableRegionsForTest(GetParam()),
- base_url_("http://www.test.com/") {
+ ScrollingCoordinatorTest() : base_url_("http://www.test.com/") {
helper_.Initialize(nullptr, nullptr, nullptr, &ConfigureSettings);
GetWebView()->MainFrameWidget()->Resize(IntSize(320, 240));
@@ -118,12 +114,6 @@ class ScrollingCoordinatorTest
WebString::FromUTF8(file_name));
}
- cc::Layer* GetRootScrollLayer() {
- GraphicsLayer* layer =
- GetFrame()->View()->LayoutViewport()->LayerForScrolling();
- return layer ? layer->CcLayer() : nullptr;
- }
-
WebViewImpl* GetWebView() const { return helper_.GetWebView(); }
LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); }
frame_test_helpers::TestWebWidgetClient* GetWidgetClient() const {
@@ -132,6 +122,14 @@ class ScrollingCoordinatorTest
void LoadAhem() { helper_.LoadAhem(); }
+ bool HasMainThreadScrollingReasons(const GraphicsLayer& layer) const {
+ const auto* scroll = layer.GetPropertyTreeState()
+ .Transform()
+ .NearestScrollTranslationNode()
+ .ScrollNode();
+ return scroll->GetMainThreadScrollingReasons();
+ }
+
protected:
std::string base_url_;
@@ -158,10 +156,11 @@ TEST_P(ScrollingCoordinatorTest, fastScrollingByDefault) {
frame_view));
// Fast scrolling should be enabled by default.
- cc::Layer* root_scroll_layer = GetRootScrollLayer();
- ASSERT_TRUE(root_scroll_layer);
- ASSERT_TRUE(root_scroll_layer->scrollable());
- ASSERT_FALSE(root_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& root_scroll_graphics_layer =
+ *GetFrame()->View()->LayoutViewport()->LayerForScrolling();
+ EXPECT_FALSE(HasMainThreadScrollingReasons(root_scroll_graphics_layer));
+ EXPECT_TRUE(root_scroll_graphics_layer.CcLayer()->scrollable());
+
ASSERT_EQ(cc::EventListenerProperties::kNone,
GetWidgetClient()->EventListenerProperties(
cc::EventListenerClass::kTouchStartOrMove));
@@ -169,10 +168,11 @@ TEST_P(ScrollingCoordinatorTest, fastScrollingByDefault) {
GetWidgetClient()->EventListenerProperties(
cc::EventListenerClass::kMouseWheel));
- cc::Layer* inner_viewport_scroll_layer =
- page->GetVisualViewport().ScrollLayer()->CcLayer();
- ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
- ASSERT_FALSE(inner_viewport_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& inner_viewport_scroll_graphics_layer =
+ *page->GetVisualViewport().ScrollLayer();
+ EXPECT_FALSE(
+ HasMainThreadScrollingReasons(inner_viewport_scroll_graphics_layer));
+ EXPECT_TRUE(inner_viewport_scroll_graphics_layer.CcLayer()->scrollable());
}
TEST_P(ScrollingCoordinatorTest, fastFractionalScrollingDiv) {
@@ -214,10 +214,9 @@ TEST_P(ScrollingCoordinatorTest, fastScrollingForFixedPosition) {
NavigateTo(base_url_ + "fixed-position.html");
ForceFullCompositingUpdate();
- // Fixed position should not fall back to main thread scrolling.
- cc::Layer* root_scroll_layer = GetRootScrollLayer();
- ASSERT_TRUE(root_scroll_layer);
- ASSERT_FALSE(root_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& root_scroll_layer =
+ *GetFrame()->View()->LayoutViewport()->LayerForScrolling();
+ EXPECT_FALSE(HasMainThreadScrollingReasons(root_scroll_layer));
}
// Sticky constraints are stored on transform property tree nodes.
@@ -234,9 +233,9 @@ TEST_P(ScrollingCoordinatorTest, fastScrollingForStickyPosition) {
ForceFullCompositingUpdate();
// Sticky position should not fall back to main thread scrolling.
- cc::Layer* root_scroll_layer = GetRootScrollLayer();
- ASSERT_TRUE(root_scroll_layer);
- EXPECT_FALSE(root_scroll_layer->GetMainThreadScrollingReasons());
+ const auto& root_scroll_layer =
+ *GetFrame()->View()->LayoutViewport()->LayerForScrolling();
+ EXPECT_FALSE(HasMainThreadScrollingReasons(root_scroll_layer));
Document* document = GetFrame()->GetDocument();
{
@@ -455,9 +454,10 @@ TEST_P(ScrollingCoordinatorTest, clippedBodyTest) {
NavigateTo(base_url_ + "clipped-body.html");
ForceFullCompositingUpdate();
- cc::Layer* root_scroll_layer = GetRootScrollLayer();
- ASSERT_TRUE(root_scroll_layer);
- EXPECT_TRUE(root_scroll_layer->non_fast_scrollable_region().IsEmpty());
+ const auto* root_scroll_layer =
+ GetFrame()->View()->LayoutViewport()->LayerForScrolling();
+ EXPECT_TRUE(
+ root_scroll_layer->CcLayer()->non_fast_scrollable_region().IsEmpty());
}
TEST_P(ScrollingCoordinatorTest, touchAction) {
@@ -956,20 +956,6 @@ TEST_P(ScrollingCoordinatorTest, NonFastScrollableRegionsForPlugins) {
ForceFullCompositingUpdate();
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- Region scrolling;
- Region fixed;
- Page* page = GetFrame()->GetPage();
- page->GetScrollingCoordinator()
- ->ComputeShouldHandleScrollGestureOnMainThreadRegion(
- To<LocalFrame>(page->MainFrame()), &scrolling, &fixed);
-
- EXPECT_TRUE(scrolling.IsRect());
- EXPECT_TRUE(fixed.IsRect());
- EXPECT_EQ(scrolling.Rects().at(0), IntRect(0, 0, 300, 300));
- EXPECT_EQ(fixed.Rects().at(0), IntRect(0, 500, 200, 200));
- }
-
// The non-fixed plugin should create a non-fast scrollable region in the
// scrolling contents layer of the LayoutView.
auto* layout_viewport = GetFrame()->View()->LayoutViewport();
@@ -980,23 +966,13 @@ TEST_P(ScrollingCoordinatorTest, NonFastScrollableRegionsForPlugins) {
// The fixed plugin should create a non-fast scrollable region in a fixed
// cc::Layer.
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // The fixed non-fast region should be on the visual viewport's scrolling
- // layer. This is not correct in all cases and is a restriction of the
- // pre-PaintNonFsatScrollableRegions code.
- auto* non_fast_layer =
- GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
- EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
- gfx::Rect(0, 500, 200, 200));
- } else {
- auto* fixed = GetFrame()->GetDocument()->getElementById("fixed");
- auto* fixed_object = ToLayoutBox(fixed->GetLayoutObject());
- auto* fixed_graphics_layer =
- fixed_object->EnclosingLayer()->GraphicsLayerBacking(fixed_object);
- EXPECT_EQ(
- fixed_graphics_layer->CcLayer()->non_fast_scrollable_region().bounds(),
- gfx::Rect(0, 0, 200, 200));
- }
+ auto* fixed = GetFrame()->GetDocument()->getElementById("fixed");
+ auto* fixed_object = ToLayoutBox(fixed->GetLayoutObject());
+ auto* fixed_graphics_layer =
+ fixed_object->EnclosingLayer()->GraphicsLayerBacking(fixed_object);
+ EXPECT_EQ(
+ fixed_graphics_layer->CcLayer()->non_fast_scrollable_region().bounds(),
+ gfx::Rect(0, 0, 200, 200));
}
TEST_P(ScrollingCoordinatorTest, NonFastScrollableRegionWithBorder) {
@@ -1019,18 +995,8 @@ TEST_P(ScrollingCoordinatorTest, NonFastScrollableRegionWithBorder) {
)HTML");
ForceFullCompositingUpdate();
- // The non-fast scrollable regions are stored on different layers with and
- // without PaintNonFastScrollableRegions. This test is only interested in
- // the dimensions of the non-fast region generated.
- cc::Layer* non_fast_layer = nullptr;
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- Page* page = GetFrame()->GetPage();
- non_fast_layer = page->GetVisualViewport().ScrollLayer()->CcLayer();
- } else {
- non_fast_layer =
- GetFrame()->View()->LayoutViewport()->LayerForScrolling()->CcLayer();
- }
-
+ auto* non_fast_layer =
+ GetFrame()->View()->LayoutViewport()->LayerForScrolling()->CcLayer();
EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
gfx::Rect(0, 0, 120, 120));
}
@@ -1351,23 +1317,6 @@ TEST_P(ScrollingCoordinatorTest, NestedIFramesMainThreadScrollingRegion) {
ForceFullCompositingUpdate();
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- Region scrolling;
- Region fixed;
- Page* page = GetFrame()->GetPage();
- page->GetScrollingCoordinator()
- ->ComputeShouldHandleScrollGestureOnMainThreadRegion(
- To<LocalFrame>(page->MainFrame()), &scrolling, &fixed);
-
- EXPECT_TRUE(fixed.IsEmpty())
- << "Since the DIV will move when the main frame is scrolled, it should"
- " not be placed in the fixed region.";
-
- EXPECT_EQ(scrolling.Bounds(), IntRect(0, 1200, 65, 65))
- << "Since the DIV will move when the main frame is scrolled, it should "
- "be placed in the scrolling region.";
- }
-
auto* layout_viewport = GetFrame()->View()->LayoutViewport();
auto* mapping = layout_viewport->Layer()->GetCompositedLayerMapping();
auto* non_fast_layer = mapping->ScrollingContentsLayer()->CcLayer();
@@ -1432,46 +1381,12 @@ TEST_P(ScrollingCoordinatorTest, NestedFixedIFramesMainThreadScrollingRegion) {
ScrollOffset(0, 1000), kProgrammaticScroll);
ForceFullCompositingUpdate();
-
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- Region scrolling;
- Region fixed;
- Page* page = GetFrame()->GetPage();
- page->GetScrollingCoordinator()
- ->ComputeShouldHandleScrollGestureOnMainThreadRegion(
- To<LocalFrame>(page->MainFrame()), &scrolling, &fixed);
-
- EXPECT_TRUE(scrolling.IsEmpty())
- << "Since the DIV will not move when the "
- "main frame is scrolled, it should "
- "not be placed in the scrolling region.";
-
- EXPECT_EQ(fixed.Bounds(), IntRect(0, 20, 75, 75))
- << "Since the DIV not move when the main frame is scrolled, it should "
- "be placed in the scrolling region.";
- }
-
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // Since the main frame isn't scrollable, the NonFastScrollableRegions
- // should be stored on the visual viewport's scrolling layer, rather than
- // the main frame's scrolling contents layer. This is a restriction of the
- // pre-PaintNonFastScrollableRegions code which only stored non-fast regions
- // on one scrolling layer, and required using the visual viewport's
- // scrolling layer to correctly handle some fixed-position cases.
- auto* non_fast_layer =
- GetFrame()->GetPage()->GetVisualViewport().ScrollLayer()->CcLayer();
- EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
- gfx::Rect(0, 20, 75, 75));
- } else {
- // PaintNonFastScrollableRegions can put the non-fast scrollable region on
- // the fixed-position layer.
- auto* outer_iframe = GetFrame()->GetDocument()->getElementById("iframe");
- auto* outer_iframe_box = ToLayoutBox(outer_iframe->GetLayoutObject());
- auto* mapping = outer_iframe_box->Layer()->GetCompositedLayerMapping();
- auto* non_fast_layer = mapping->MainGraphicsLayer()->CcLayer();
- EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
- gfx::Rect(0, 0, 75, 75));
- }
+ auto* outer_iframe = GetFrame()->GetDocument()->getElementById("iframe");
+ auto* outer_iframe_box = ToLayoutBox(outer_iframe->GetLayoutObject());
+ auto* mapping = outer_iframe_box->Layer()->GetCompositedLayerMapping();
+ auto* non_fast_layer = mapping->MainGraphicsLayer()->CcLayer();
+ EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
+ gfx::Rect(0, 0, 75, 75));
}
TEST_P(ScrollingCoordinatorTest, IframeCompositedScrollingHideAndShow) {
@@ -1497,20 +1412,8 @@ TEST_P(ScrollingCoordinatorTest, IframeCompositedScrollingHideAndShow) {
ForceFullCompositingUpdate();
- cc::Layer* non_fast_layer = nullptr;
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // Since the main frame isn't scrollable, the NonFastScrollableRegions
- // should be stored on the visual viewport's scrolling layer, rather than
- // the main frame's scrolling contents layer. This is a restriction of the
- // pre-PaintNonFastScrollableRegions code which only stored non-fast regions
- // on one scrolling layer, and required using the visual viewport's
- // scrolling layer to correctly handle some fixed-position cases.
- Page* page = GetFrame()->GetPage();
- non_fast_layer = page->GetVisualViewport().ScrollLayer()->CcLayer();
- } else {
- non_fast_layer =
- GetFrame()->View()->LayoutViewport()->LayerForScrolling()->CcLayer();
- }
+ cc::Layer* non_fast_layer =
+ GetFrame()->View()->LayoutViewport()->LayerForScrolling()->CcLayer();
// Should have a NFSR initially.
EXPECT_EQ(non_fast_layer->non_fast_scrollable_region().bounds(),
@@ -1685,29 +1588,22 @@ TEST_P(ScrollingCoordinatorTest, UpdateUMAMetricUpdated) {
ForceFullCompositingUpdate();
histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 1);
- // A change to background color should not cause a scrolling update.
+ // A change to background color does not need to cause a scrolling update but,
+ // because hit test display items paint, we also cause a scrolling coordinator
+ // update when the background paints.
auto* background = GetFrame()->GetDocument()->getElementById("bg");
background->removeAttribute(html_names::kStyleAttr);
ForceFullCompositingUpdate();
- histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 1);
+ histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 2);
// Removing a scrollable area should cause a scrolling update.
auto* scroller = GetFrame()->GetDocument()->getElementById("scroller");
scroller->removeAttribute(html_names::kStyleAttr);
ForceFullCompositingUpdate();
- histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 2);
+ histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 3);
}
-// TODO(pdr): Replace this with ScrollingCoordinatorTest when
-// PaintNonFastScrollableRegions is launched.
-using PaintNonFastScrollableRegionsScrollingCoordinatorTest =
- ScrollingCoordinatorTest;
-INSTANTIATE_TEST_SUITE_P(All,
- PaintNonFastScrollableRegionsScrollingCoordinatorTest,
- ::testing::Values(true));
-
-TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
- NonCompositedNonFastScrollableRegion) {
+TEST_P(ScrollingCoordinatorTest, NonCompositedNonFastScrollableRegion) {
GetWebView()->GetPage()->GetSettings().SetPreferCompositingToLCDTextEnabled(
false);
LoadHTML(R"HTML(
@@ -1744,8 +1640,7 @@ TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 200, 200));
}
-TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
- NonCompositedResizerNonFastScrollableRegion) {
+TEST_P(ScrollingCoordinatorTest, NonCompositedResizerNonFastScrollableRegion) {
GetWebView()->GetPage()->GetSettings().SetPreferCompositingToLCDTextEnabled(
false);
LoadHTML(R"HTML(
@@ -1778,8 +1673,7 @@ TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
EXPECT_EQ(region.bounds(), gfx::Rect(66, 101, 14, 14));
}
-TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
- CompositedResizerNonFastScrollableRegion) {
+TEST_P(ScrollingCoordinatorTest, CompositedResizerNonFastScrollableRegion) {
LoadHTML(R"HTML(
<style>
#container { will-change: transform; }
@@ -1808,6 +1702,55 @@ TEST_P(PaintNonFastScrollableRegionsScrollingCoordinatorTest,
EXPECT_EQ(region.bounds(), gfx::Rect(-7, -7, 14, 14));
}
+TEST_P(ScrollingCoordinatorTest, TouchActionUpdatesOutsideInterestRect) {
+ LoadHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #scroller {
+ will-change: transform;
+ width: 200px;
+ height: 200px;
+ overflow-y: scroll;
+ }
+ .spacer {
+ height: 1000px;
+ }
+ #touchaction {
+ height: 100px;
+ background: yellow;
+ }
+ </style>
+ <div id="scroller">
+ <div class="spacer"></div>
+ <div class="spacer"></div>
+ <div class="spacer"></div>
+ <div class="spacer"></div>
+ <div class="spacer"></div>
+ <div id="touchaction">This should not scroll via touch.</div>
+ </div>
+ )HTML");
+
+ ForceFullCompositingUpdate();
+
+ auto* touch_action = GetFrame()->GetDocument()->getElementById("touchaction");
+ touch_action->setAttribute(html_names::kStyleAttr, "touch-action: none;");
+
+ ForceFullCompositingUpdate();
+
+ auto* scroller = GetFrame()->GetDocument()->getElementById("scroller");
+ scroller->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 5100),
+ kProgrammaticScroll);
+
+ ForceFullCompositingUpdate();
+
+ auto* scroller_box = ToLayoutBox(scroller->GetLayoutObject());
+ auto* mapping = scroller_box->Layer()->GetCompositedLayerMapping();
+ auto* cc_layer = mapping->ScrollingContentsLayer()->CcLayer();
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(0, 5000, 200, 100));
+}
+
class ScrollingCoordinatorTestWithAcceleratedContext
: public ScrollingCoordinatorTest {
public:
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index 54a7ccaa3d9..88d70ca6fa3 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -21,7 +21,7 @@ constexpr float kProximityRatio = 1.0 / 3.0;
} // namespace
// TODO(sunyunjia): Move the static functions to an anonymous namespace.
-SnapCoordinator::SnapCoordinator() : snap_container_map_() {}
+SnapCoordinator::SnapCoordinator() : snap_containers_() {}
SnapCoordinator::~SnapCoordinator() = default;
@@ -44,13 +44,46 @@ static LayoutBox* FindSnapContainer(const LayoutBox& snap_area) {
return box;
}
-void SnapCoordinator::SnapContainerDidChange(LayoutBox& snap_container,
- bool is_removed) {
- if (is_removed) {
- snap_container_map_.erase(&snap_container);
- return;
+static ScrollableArea* ScrollableAreaForSnapping(const LayoutBox& layout_box) {
+ return layout_box.IsLayoutView()
+ ? layout_box.GetFrameView()->GetScrollableArea()
+ : layout_box.GetScrollableArea();
+}
+
+// Snap types are categorized according to the spec
+// https://drafts.csswg.org/css-scroll-snap-1/#snap-axis
+static cc::ScrollSnapType GetPhysicalSnapType(const LayoutBox& snap_container) {
+ cc::ScrollSnapType scroll_snap_type =
+ snap_container.Style()->GetScrollSnapType();
+ if (scroll_snap_type.axis == cc::SnapAxis::kInline) {
+ if (snap_container.Style()->IsHorizontalWritingMode())
+ scroll_snap_type.axis = cc::SnapAxis::kX;
+ else
+ scroll_snap_type.axis = cc::SnapAxis::kY;
+ }
+ if (scroll_snap_type.axis == cc::SnapAxis::kBlock) {
+ if (snap_container.Style()->IsHorizontalWritingMode())
+ scroll_snap_type.axis = cc::SnapAxis::kY;
+ else
+ scroll_snap_type.axis = cc::SnapAxis::kX;
}
+ // Writing mode does not affect the cases where axis is kX, kY or kBoth.
+ return scroll_snap_type;
+}
+
+void SnapCoordinator::AddSnapContainer(LayoutBox& snap_container) {
+ snap_containers_.insert(&snap_container);
+}
+
+void SnapCoordinator::RemoveSnapContainer(LayoutBox& snap_container) {
+ // TODO(majidvp): The snap areas assigned to this container may need to be
+ // re-assigned. http://crbug.com/1007456
+ snap_container.ClearSnapAreas();
+ snap_container.SetNeedsPaintPropertyUpdate();
+ snap_containers_.erase(&snap_container);
+}
+void SnapCoordinator::SnapContainerDidChange(LayoutBox& snap_container) {
// Scroll snap properties have no effect on the document element instead they
// are propagated to (See Document::PropagateStyleToViewport) and handled by
// the LayoutView.
@@ -61,16 +94,15 @@ void SnapCoordinator::SnapContainerDidChange(LayoutBox& snap_container,
bool is_scroll_container =
snap_container.IsLayoutView() || snap_container.HasOverflowClip();
if (!is_scroll_container) {
- snap_container_map_.erase(&snap_container);
- snap_container.ClearSnapAreas();
- snap_container.SetNeedsPaintPropertyUpdate();
+ DCHECK(!ScrollableAreaForSnapping(snap_container));
+ DCHECK(!snap_containers_.Contains(&snap_container));
return;
}
// Note that even if scroll snap type is 'none' we continue to maintain its
// snap container entry as long as the element is a scroller. This is because
// while the scroller does not snap, it still captures the snap areas in its
- // subtree for whom it is the nearest ancestor scroll container per spec [1].
+ // subtree for whom it is the nearest ancestor scroll container per spec [1].
//
// [1] https://drafts.csswg.org/css-scroll-snap/#overview
@@ -112,47 +144,31 @@ void SnapCoordinator::SnapAreaDidChange(LayoutBox& snap_area,
}
void SnapCoordinator::UpdateAllSnapContainerData() {
- for (const auto& entry : snap_container_map_) {
- UpdateSnapContainerData(*entry.key);
- }
+ for (auto* container : snap_containers_)
+ UpdateSnapContainerData(*container);
}
-static ScrollableArea* ScrollableAreaForSnapping(const LayoutBox& layout_box) {
- return layout_box.IsLayoutView()
- ? layout_box.GetFrameView()->GetScrollableArea()
- : layout_box.GetScrollableArea();
-}
+void SnapCoordinator::UpdateSnapContainerData(LayoutBox& snap_container) {
-static cc::ScrollSnapType GetPhysicalSnapType(const LayoutBox& snap_container) {
- cc::ScrollSnapType scroll_snap_type =
- snap_container.Style()->GetScrollSnapType();
- if (scroll_snap_type.axis == cc::SnapAxis::kInline) {
- if (snap_container.Style()->IsHorizontalWritingMode())
- scroll_snap_type.axis = cc::SnapAxis::kX;
- else
- scroll_snap_type.axis = cc::SnapAxis::kY;
- }
- if (scroll_snap_type.axis == cc::SnapAxis::kBlock) {
- if (snap_container.Style()->IsHorizontalWritingMode())
- scroll_snap_type.axis = cc::SnapAxis::kY;
- else
- scroll_snap_type.axis = cc::SnapAxis::kX;
- }
- // Writing mode does not affect the cases where axis kX, kY or kBoth.
- return scroll_snap_type;
-}
+ ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
+ const auto* old_snap_container_data = scrollable_area->GetSnapContainerData();
+ auto snap_type = GetPhysicalSnapType(snap_container);
-void SnapCoordinator::UpdateSnapContainerData(LayoutBox& snap_container) {
- cc::SnapContainerData snap_container_data(
- GetPhysicalSnapType(snap_container));
+ // Scrollers that don't have any snap areas assigned to them and don't snap
+ // require no further processing. These are the most common types and thus
+ // returning as early as possible ensures efficiency.
+ if (!old_snap_container_data && snap_type.is_none)
+ return;
+
+ cc::SnapContainerData snap_container_data(snap_type);
+
+ DCHECK(scrollable_area);
+ DCHECK(snap_containers_.Contains(&snap_container));
// When snap type is 'none' we don't perform any snapping so there is no need
// to keep the area data up to date. So just update the type and skip updating
// areas as an optimization.
if (!snap_container_data.scroll_snap_type().is_none) {
- ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
- if (!scrollable_area)
- return;
FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
scrollable_area->MaximumScrollOffset());
snap_container_data.set_max_position(
@@ -210,11 +226,11 @@ void SnapCoordinator::UpdateSnapContainerData(LayoutBox& snap_container) {
}
}
- auto old_snap_container_data = GetSnapContainerData(snap_container);
- if (old_snap_container_data != snap_container_data)
+ if (!old_snap_container_data ||
+ *old_snap_container_data != snap_container_data) {
snap_container.SetNeedsPaintPropertyUpdate();
-
- snap_container_map_.Set(&snap_container, snap_container_data);
+ scrollable_area->SetSnapContainerData(snap_container_data);
+ }
}
static cc::ScrollSnapAlign GetPhysicalAlignment(
@@ -283,13 +299,14 @@ cc::SnapAreaData SnapCoordinator::CalculateSnapAreaData(
base::Optional<FloatPoint> SnapCoordinator::GetSnapPosition(
const LayoutBox& snap_container,
const cc::SnapSelectionStrategy& strategy) const {
- // const_cast is safe here because we only need to modify the type to match
- // the key type, not actually mutating the object.
- auto iter = snap_container_map_.find(&const_cast<LayoutBox&>(snap_container));
- if (iter == snap_container_map_.end())
+ const auto* optional_data =
+ snap_container.GetScrollableArea()
+ ? snap_container.GetScrollableArea()->GetSnapContainerData()
+ : nullptr;
+ if (!optional_data)
return base::nullopt;
- const cc::SnapContainerData& data = iter->value;
+ const cc::SnapContainerData& data = *optional_data;
if (!data.size())
return base::nullopt;
@@ -358,7 +375,7 @@ bool SnapCoordinator::PerformSnapping(
base::Optional<FloatPoint> snap_point =
GetSnapPosition(snap_container, strategy);
- if (!snap_point.has_value())
+ if (!snap_point)
return false;
scrollable_area->CancelScrollAnimation();
@@ -369,21 +386,10 @@ bool SnapCoordinator::PerformSnapping(
return true;
}
-base::Optional<cc::SnapContainerData> SnapCoordinator::GetSnapContainerData(
- const LayoutBox& snap_container) const {
- // const_cast is safe here because we only need to modify the type to match
- // the key type, not actually mutating the object.
- auto iter = snap_container_map_.find(&const_cast<LayoutBox&>(snap_container));
- if (iter != snap_container_map_.end()) {
- return iter->value;
- }
- return base::nullopt;
-}
-
#ifndef NDEBUG
void SnapCoordinator::ShowSnapAreaMap() {
- for (auto* const container : snap_container_map_.Keys())
+ for (auto* const container : snap_containers_)
ShowSnapAreasFor(container);
}
@@ -397,12 +403,12 @@ void SnapCoordinator::ShowSnapAreasFor(const LayoutBox* container) {
}
void SnapCoordinator::ShowSnapDataFor(const LayoutBox* snap_container) {
- // const_cast is safe here because we only need to modify the type to match
- // the key type, not actually mutating the object.
- auto iter = snap_container_map_.find(const_cast<LayoutBox*>(snap_container));
- if (iter == snap_container_map_.end())
- return;
- LOG(INFO) << iter->value;
+ const auto* optional_data =
+ ScrollableAreaForSnapping(*snap_container)
+ ? ScrollableAreaForSnapping(*snap_container)->GetSnapContainerData()
+ : nullptr;
+ if (optional_data)
+ LOG(INFO) << *optional_data;
}
#endif
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 295a5d2bcd7..349e1ba81b4 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
@@ -21,8 +21,11 @@ class LayoutBox;
// positions for a given snap container.
//
// Snap container:
-// An scroll container that has 'scroll-snap-type' value other
+// A scroll container that has 'scroll-snap-type' value other
// than 'none'.
+// However, we maintain a snap container entry for a scrollable area even if
+// its snap type is 'none'. This is because while the scroller does not snap,
+// it still captures the snap areas in its subtree.
// Snap area:
// A snap container's descendant that contributes snap positions. An element
// only contributes snap positions to its nearest ancestor (on the element’s
@@ -30,18 +33,17 @@ class LayoutBox;
//
// For more information see spec: https://drafts.csswg.org/css-snappoints/
class CORE_EXPORT SnapCoordinator final
- : public GarbageCollectedFinalized<SnapCoordinator> {
+ : public GarbageCollected<SnapCoordinator> {
public:
explicit SnapCoordinator();
~SnapCoordinator();
void Trace(blink::Visitor* visitor) {}
- void SnapContainerDidChange(LayoutBox&, bool is_removed);
- void SnapAreaDidChange(LayoutBox&, cc::ScrollSnapAlign);
+ void AddSnapContainer(LayoutBox& snap_container);
+ void RemoveSnapContainer(LayoutBox& snap_container);
- // Returns the SnapContainerData if the snap container has one.
- base::Optional<cc::SnapContainerData> GetSnapContainerData(
- const LayoutBox& snap_container) const;
+ void SnapContainerDidChange(LayoutBox&);
+ void SnapAreaDidChange(LayoutBox&, cc::ScrollSnapAlign);
// Calculate the SnapAreaData for the specific snap area in its snap
// container.
@@ -90,7 +92,7 @@ class CORE_EXPORT SnapCoordinator final
void UpdateSnapContainerData(LayoutBox&);
- HashMap<LayoutBox*, cc::SnapContainerData> snap_container_map_;
+ HashSet<LayoutBox*> snap_containers_;
DISALLOW_COPY_AND_ASSIGN(SnapCoordinator);
};
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
index 6a943ecebef..c0a66c46397 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
@@ -123,6 +123,13 @@ class SnapCoordinatorTest : public testing::Test,
GetDocument().View()->RunPostLifecycleSteps();
}
+ const cc::SnapContainerData* GetSnapContainerData(LayoutBox& layout_box) {
+ if (layout_box.GetScrollableArea()) {
+ return layout_box.GetScrollableArea()->GetSnapContainerData();
+ }
+ return nullptr;
+ }
+
std::unique_ptr<DummyPageHolder> page_holder_;
};
@@ -231,18 +238,17 @@ TEST_F(SnapCoordinatorTest, ViewpoertScrollSnapStyleComesFromDocumentElement) {
Element* body = GetDocument().body();
EXPECT_EQ(body, GetDocument().ViewportDefiningElement());
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> viewport_data =
- snap_coordinator->GetSnapContainerData(*GetDocument().GetLayoutView());
- EXPECT_TRUE(viewport_data.has_value());
- EXPECT_EQ(viewport_data.value().scroll_snap_type(),
+ const cc::SnapContainerData* viewport_data =
+ GetSnapContainerData(*GetDocument().GetLayoutView());
+ EXPECT_TRUE(viewport_data);
+ EXPECT_EQ(viewport_data->scroll_snap_type(),
cc::ScrollSnapType(false, cc::SnapAxis::kBoth,
cc::SnapStrictness::kMandatory));
- base::Optional<cc::SnapContainerData> body_data =
- snap_coordinator->GetSnapContainerData(*body->GetLayoutBox());
+ const cc::SnapContainerData* body_data =
+ GetSnapContainerData(*body->GetLayoutBox());
- EXPECT_FALSE(body_data.has_value());
+ EXPECT_FALSE(body_data);
}
TEST_F(SnapCoordinatorTest, LayoutViewCapturesWhenBodyElementViewportDefining) {
@@ -389,12 +395,11 @@ TEST_F(SnapCoordinatorTest, SnapDataCalculation) {
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
scrollable_area->MaximumScrollOffset());
@@ -423,12 +428,11 @@ TEST_F(SnapCoordinatorTest, ScrolledSnapDataCalculation) {
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
scrollable_area->MaximumScrollOffset());
@@ -483,11 +487,10 @@ TEST_F(SnapCoordinatorTest, ScrolledSnapDataCalculationOnViewport) {
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(kStyleAttr, "scroll-snap-align: start;");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*GetDocument().GetLayoutView());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*GetDocument().GetLayoutView());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
scrollable_area->MaximumScrollOffset());
@@ -518,11 +521,10 @@ TEST_F(SnapCoordinatorTest, SnapDataCalculationWithBoxModel) {
scroller_element->setAttribute(
kStyleAttr, "margin: 3px; border: 10px solid; padding: 4px;");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
@@ -561,11 +563,10 @@ TEST_F(SnapCoordinatorTest, NegativeMarginSnapDataCalculation) {
"scroll-snap-align: start; scroll-margin: -8px;");
UpdateAllLifecyclePhasesForTest();
Element* scroller_element = GetDocument().getElementById("scroller");
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
@@ -608,11 +609,10 @@ TEST_F(SnapCoordinatorTest, AsymmetricalSnapDataCalculation) {
scroll-padding-left: 16px;
)HTML");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
@@ -643,11 +643,10 @@ TEST_F(SnapCoordinatorTest, ScaledSnapDataCalculation) {
"scroll-snap-align: end; transform: scale(4, 4);");
UpdateAllLifecyclePhasesForTest();
Element* scroller_element = GetDocument().getElementById("scroller");
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
@@ -680,11 +679,10 @@ TEST_F(SnapCoordinatorTest, VerticalRlSnapDataCalculation) {
Element* scroller_element = GetDocument().getElementById("scroller");
scroller_element->setAttribute(kStyleAttr, "writing-mode: vertical-rl;");
UpdateAllLifecyclePhasesForTest();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<cc::SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- cc::SnapContainerData actual_container = data.value();
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+ cc::SnapContainerData actual_container = *data;
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
@@ -710,4 +708,24 @@ TEST_F(SnapCoordinatorTest, VerticalRlSnapDataCalculation) {
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-} // namespace
+TEST_F(SnapCoordinatorTest, ChangeOverflowToVisible) {
+ SetUpSingleSnapArea();
+ Element* scroller_element = GetDocument().getElementById("scroller");
+ const cc::SnapContainerData* data =
+ GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+
+ // Scroller should no longer be considered a snap container
+ scroller_element->setAttribute(kStyleAttr, "overflow : visible");
+ UpdateAllLifecyclePhasesForTest();
+ data = GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_FALSE(data);
+
+ // Scroller should be considered a snap container again
+ scroller_element->setAttribute(kStyleAttr, "overflow : scroll");
+ UpdateAllLifecyclePhasesForTest();
+ data = GetSnapContainerData(*scroller_element->GetLayoutBox());
+ EXPECT_TRUE(data);
+}
+
+} // namespace blink
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 ddf99f276a8..3d8b5cceabf 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
@@ -25,8 +25,8 @@ namespace blink {
namespace {
-bool ParseTargetTextIdentifier(const String& fragment,
- Vector<TextFragmentSelector>* out_selectors) {
+bool ParseTextDirective(const String& fragment,
+ Vector<TextFragmentSelector>* out_selectors) {
DCHECK(out_selectors);
size_t start_pos = 0;
@@ -74,26 +74,11 @@ bool CheckSecurityRestrictions(LocalFrame& frame,
} // namespace
-TextFragmentAnchor* TextFragmentAnchor::TryCreate(
- const KURL& url,
- LocalFrame& frame,
- bool same_document_navigation) {
- if (!CheckSecurityRestrictions(frame, same_document_navigation))
- return nullptr;
-
- Vector<TextFragmentSelector> selectors;
-
- if (!ParseTargetTextIdentifier(url.FragmentIdentifier(), &selectors))
- return nullptr;
-
- return MakeGarbageCollected<TextFragmentAnchor>(
- selectors, frame, TextFragmentFormat::PlainFragment);
-}
-
TextFragmentAnchor* TextFragmentAnchor::TryCreateFragmentDirective(
const KURL& url,
LocalFrame& frame,
- bool same_document_navigation) {
+ bool same_document_navigation,
+ bool should_scroll) {
DCHECK(RuntimeEnabledFeatures::TextFragmentIdentifiersEnabled(
frame.GetDocument()));
@@ -105,23 +90,23 @@ TextFragmentAnchor* TextFragmentAnchor::TryCreateFragmentDirective(
Vector<TextFragmentSelector> selectors;
- if (!ParseTargetTextIdentifier(frame.GetDocument()->GetFragmentDirective(),
- &selectors)) {
+ if (!ParseTextDirective(frame.GetDocument()->GetFragmentDirective(),
+ &selectors)) {
UseCounter::Count(frame.GetDocument(),
WebFeature::kInvalidFragmentDirective);
return nullptr;
}
- return MakeGarbageCollected<TextFragmentAnchor>(
- selectors, frame, TextFragmentFormat::FragmentDirective);
+ return MakeGarbageCollected<TextFragmentAnchor>(selectors, frame,
+ should_scroll);
}
TextFragmentAnchor::TextFragmentAnchor(
const Vector<TextFragmentSelector>& text_fragment_selectors,
LocalFrame& frame,
- const TextFragmentFormat fragment_format)
+ bool should_scroll)
: frame_(&frame),
- fragment_format_(fragment_format),
+ should_scroll_(should_scroll),
metrics_(MakeGarbageCollected<TextFragmentAnchorMetrics>(
frame_->GetDocument())) {
DCHECK(!text_fragment_selectors.IsEmpty());
@@ -148,12 +133,12 @@ bool TextFragmentAnchor::Invoke() {
return !dismissed_;
frame_->GetDocument()->Markers().RemoveMarkersOfTypes(
- DocumentMarker::MarkerTypes::TextMatch());
+ DocumentMarker::MarkerTypes::TextFragment());
if (user_scrolled_ && !did_scroll_into_view_)
metrics_->ScrollCancelled();
- first_match_needs_scroll_ = !user_scrolled_;
+ first_match_needs_scroll_ = should_scroll_ && !user_scrolled_;
{
// FindMatch might cause scrolling and set user_scrolled_ so reset it when
@@ -217,8 +202,8 @@ void TextFragmentAnchor::DidFindMatch(const EphemeralRangeInFlatTree& range) {
// therefore indicate that the page text has changed.
if (!frame_->GetDocument()
->Markers()
- .MarkersIntersectingRange(range,
- DocumentMarker::MarkerTypes::TextMatch())
+ .MarkersIntersectingRange(
+ range, DocumentMarker::MarkerTypes::TextFragment())
.IsEmpty()) {
return;
}
@@ -265,9 +250,7 @@ void TextFragmentAnchor::DidFindMatch(const EphemeralRangeInFlatTree& range) {
EphemeralRange dom_range =
EphemeralRange(ToPositionInDOMTree(range.StartPosition()),
ToPositionInDOMTree(range.EndPosition()));
- frame_->GetDocument()->Markers().AddTextMatchMarker(
- dom_range, TextMatchMarker::MatchStatus::kInactive);
- frame_->GetEditor().SetMarkedTextMatchesAreHighlighted(true);
+ frame_->GetDocument()->Markers().AddTextFragmentMarker(dom_range);
}
void TextFragmentAnchor::DidFindAmbiguousMatch() {
@@ -280,14 +263,12 @@ void TextFragmentAnchor::DidFinishSearch() {
metrics_->ReportMetrics();
- if (!did_find_match_)
+ if (!did_find_match_) {
dismissed_ = true;
- if (!did_find_match_ &&
- fragment_format_ == TextFragmentFormat::FragmentDirective) {
DCHECK(!element_fragment_anchor_);
- element_fragment_anchor_ =
- ElementFragmentAnchor::TryCreate(frame_->GetDocument()->Url(), *frame_);
+ element_fragment_anchor_ = ElementFragmentAnchor::TryCreate(
+ frame_->GetDocument()->Url(), *frame_, should_scroll_);
if (element_fragment_anchor_) {
// Schedule a frame so we can invoke the element anchor in
// PerformPreRafActions.
@@ -307,11 +288,10 @@ bool TextFragmentAnchor::Dismiss() {
if (!did_find_match_ || dismissed_)
return true;
- DCHECK(did_scroll_into_view_ || user_scrolled_);
+ DCHECK(!should_scroll_ || did_scroll_into_view_ || user_scrolled_);
frame_->GetDocument()->Markers().RemoveMarkersOfTypes(
- DocumentMarker::MarkerTypes::TextMatch());
- frame_->GetEditor().SetMarkedTextMatchesAreHighlighted(false);
+ DocumentMarker::MarkerTypes::TextFragment());
dismissed_ = true;
metrics_->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 b591a31603a..27d3da57a9a 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
@@ -20,40 +20,29 @@ namespace blink {
class LocalFrame;
class KURL;
-constexpr char kFragmentDirectivePrefix[] = "##";
+constexpr char kFragmentDirectivePrefix[] = ":~:";
// Subtract 1 because base::size includes the \0 string terminator.
constexpr size_t kFragmentDirectivePrefixStringLength =
base::size(kFragmentDirectivePrefix) - 1;
-// TODO(crbug/1007016): Remove support for the old prefix once we confirm the
-// new prefix choice.
-constexpr char kFragmentDirectiveNewPrefix[] = ":~:";
-// Subtract 1 because base::size includes the \0 string terminator.
-constexpr size_t kFragmentDirectiveNewPrefixStringLength =
- base::size(kFragmentDirectiveNewPrefix) - 1;
-constexpr char kTextFragmentIdentifierPrefix[] = "targetText=";
+constexpr char kTextFragmentIdentifierPrefix[] = "text=";
// Subtract 1 because base::size includes the \0 string terminator.
constexpr size_t kTextFragmentIdentifierPrefixStringLength =
base::size(kTextFragmentIdentifierPrefix) - 1;
-enum class TextFragmentFormat { PlainFragment, FragmentDirective };
-
class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
public TextFragmentFinder::Client {
public:
- static TextFragmentAnchor* TryCreate(const KURL& url,
- LocalFrame& frame,
- bool same_document_navigation);
-
static TextFragmentAnchor* TryCreateFragmentDirective(
const KURL& url,
LocalFrame& frame,
- bool same_document_navigation);
+ bool same_document_navigation,
+ bool should_scroll);
TextFragmentAnchor(
const Vector<TextFragmentSelector>& text_fragment_selectors,
LocalFrame& frame,
- const TextFragmentFormat fragment_format);
+ bool should_scroll);
~TextFragmentAnchor() override = default;
bool Invoke() override;
@@ -96,16 +85,16 @@ class CORE_EXPORT TextFragmentAnchor final : public FragmentAnchor,
// Whether we found a match. Used to determine if we should activate the
// element fragment anchor at the end of searching.
bool did_find_match_ = false;
- // Whether the text fragment anchor is specified as a regular URL fragment or
- // a fragment directive. Used to determine if we should activate the element
- // fragment anchor in the case where we don't find a match.
- const TextFragmentFormat fragment_format_;
// If the text fragment anchor is defined as a fragment directive and we don't
// find a match, we fall back to the element anchor if it is present.
Member<ElementFragmentAnchor> element_fragment_anchor_;
// Whether the text fragment anchor has been dismissed yet. This should be
// kept alive until dismissed so we can remove text highlighting.
bool dismissed_ = false;
+ // Whether we should scroll the anchor into view. This will be false for
+ // history navigations and reloads, where we want to restore the highlight but
+ // not scroll into view again.
+ bool should_scroll_ = false;
Member<TextFragmentAnchorMetrics> metrics_;
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
index f970d3b0443..ad8286e2ef0 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
index 9675345267d..31af760438c 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h
@@ -13,7 +13,7 @@ namespace blink {
// Helper class for TextFragmentAnchor that provides hooks for tracking and
// reporting usage and performance metrics to UMA.
class CORE_EXPORT TextFragmentAnchorMetrics final
- : public GarbageCollectedFinalized<TextFragmentAnchorMetrics> {
+ : public GarbageCollected<TextFragmentAnchorMetrics> {
public:
TextFragmentAnchorMetrics(Document* document);
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 ea873ec84e3..87885482259 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
@@ -48,10 +48,9 @@ class TextFragmentAnchorMetricsTest : public SimTest {
// Test UMA metrics collection
TEST_F(TextFragmentAnchorMetricsTest, UMAMetricsCollected) {
- SimRequest request(
- "https://example.com/test.html#targetText=test&targetText=cat",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test&targetText=cat");
+ SimRequest request("https://example.com/test.html#:~:text=test&text=cat",
+ "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test&text=cat");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -95,9 +94,8 @@ TEST_F(TextFragmentAnchorMetricsTest, UMAMetricsCollected) {
// Test UMA metrics collection when there is no match found
TEST_F(TextFragmentAnchorMetricsTest, NoMatchFound) {
- SimRequest request("https://example.com/test.html#targetText=cat",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=cat");
+ SimRequest request("https://example.com/test.html#:~:text=cat", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=cat");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -136,7 +134,7 @@ TEST_F(TextFragmentAnchorMetricsTest, NoMatchFound) {
0);
}
-// Test that we don't collect any metrics when there is no targetText
+// Test that we don't collect any metrics when there is no text directive
TEST_F(TextFragmentAnchorMetricsTest, NoTextFragmentAnchor) {
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -165,9 +163,8 @@ TEST_F(TextFragmentAnchorMetricsTest, NoTextFragmentAnchor) {
// Test that the correct metrics are collected when we found a match but didn't
// need to scroll.
TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<p>This is a test page</p>
@@ -202,10 +199,9 @@ TEST_F(TextFragmentAnchorMetricsTest, MatchFoundNoScroll) {
// Test that the ScrollCancelled metric gets reported when a user scroll cancels
// the scroll into view.
TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
- LoadURL("https://example.com/test.html#targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -257,9 +253,9 @@ TEST_F(TextFragmentAnchorMetricsTest, ScrollCancelled) {
// Test that the TapToDismiss feature gets use counted when the user taps to
// dismiss the text highlight
TEST_F(TextFragmentAnchorMetricsTest, TapToDismiss) {
- SimRequest request("https://example.com/test.html#targetText=test%20page",
+ SimRequest request("https://example.com/test.html#:~:text=test%20page",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test%20page");
+ LoadURL("https://example.com/test.html#:~:text=test%20page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -300,10 +296,10 @@ TEST_F(TextFragmentAnchorMetricsTest, InvalidFragmentDirective) {
{"#:~:element", kCounted},
{"#element:~:", kCounted},
{"#foo:~:bar", kCounted},
- {"#:~:utargetText=foo", kCounted},
- {"#:~:targetText=foo", kUncounted},
- {"#:~:targetText=foo&invalid", kCounted},
- {"#foo:~:targetText=foo", kUncounted}};
+ {"#:~:utext=foo", kCounted},
+ {"#:~:text=foo", kUncounted},
+ {"#:~:text=foo&invalid", kCounted},
+ {"#foo:~:text=foo", kUncounted}};
for (auto test_case : test_cases) {
String url = "https://example.com/test.html" + test_case.first;
@@ -345,37 +341,37 @@ INSTANTIATE_TEST_SUITE_P(,
testing::Values(false, true));
// Test that we correctly track failed vs. successful element-id lookups. We
-// only count these in cases where we don't have a targetText, when the REF is
-// enabled.
+// only count these in cases where we don't have a text directive, when the REF
+// is enabled.
TEST_P(TextFragmentRelatedMetricTest, ElementIdSuccessFailureCounts) {
const int kUncounted = 0;
const int kFound = 1;
const int kNotFound = 2;
// When the TextFragmentAnchors feature is on, we should avoid counting the
- // result of the element-id fragment if a targetText is successfully parsed.
- // If the feature is off we treat the targetText as an element-id and should
- // count the result.
+ // result of the element-id fragment if a text directive is successfully
+ // parsed. If the feature is off we treat the text directive as an element-id
+ // and should count the result.
const int kUncountedOrNotFound = GetParam() ? kUncounted : kNotFound;
const int kUncountedOrFound = GetParam() ? kUncounted : kFound;
// When the TextFragmentAnchors feature is on, we'll strip the fragment
- // directive (i.e. anything after ##) leaving just the element anchor.
+ // directive (i.e. anything after :~:) leaving just the element anchor.
const int kFoundIfDirectiveStripped = GetParam() ? kFound : kNotFound;
Vector<std::pair<String, int>> test_cases = {
{"", kUncounted},
{"#element", kFound},
{"#doesntExist", kNotFound},
- {"#element##foo", kFoundIfDirectiveStripped},
- {"#doesntexist##foo", kNotFound},
- {"##element", kUncountedOrNotFound},
- {"#element##targetText=doesntexist", kUncountedOrNotFound},
- {"#element##targetText=page", kUncountedOrNotFound},
- {"#targetText=doesntexist", kUncountedOrNotFound},
- {"#targetText=page", kUncountedOrNotFound},
- {"#targetText=name", kUncountedOrFound},
- {"#element##targetText=name", kUncountedOrFound}};
+ {"#element:~:foo", kFoundIfDirectiveStripped},
+ {"#doesntexist:~:foo", kNotFound},
+ {"##element", kNotFound},
+ {"#element:~:text=doesntexist", kUncountedOrNotFound},
+ {"#element:~:text=page", kUncountedOrNotFound},
+ {"#:~:text=doesntexist", kUncountedOrNotFound},
+ {"#:~:text=page", kUncountedOrNotFound},
+ {"#:~:text=name", kUncountedOrFound},
+ {"#element:~:text=name", kUncountedOrFound}};
const int kNotFoundSample = 0;
const int kFoundSample = 1;
@@ -395,8 +391,8 @@ TEST_P(TextFragmentRelatedMetricTest, ElementIdSuccessFailureCounts) {
request.Complete(R"HTML(
<!DOCTYPE html>
<p id="element">This is a test page</p>
- <p id="targetText=name">This is a test page</p>
- <p id="element##targetText=name">This is a test page</p>
+ <p id=":~:text=name">This is a test page</p>
+ <p id="element:~:text=name">This is a test page</p>
)HTML");
Compositor().BeginFrame();
@@ -439,79 +435,19 @@ TEST_P(TextFragmentRelatedMetricTest, ElementIdSuccessFailureCounts) {
}
}
-// Test that we correctly UseCount when we see a pound character '#' in the
-// fragment. We exclude the case where we see a ##targetText format
-// TextFragment so that we don't count it in uses of our own feature.
-TEST_P(TextFragmentRelatedMetricTest, DoubleHashUseCounter) {
- const int kUncounted = 0;
- const int kCounted = 1;
-
- // When the TextFragmentAnchors feature is on, the fragment directive is
- // stripped and we won't count it as a double-hash use case. When it's
- // off, we expect to count it.
- const int kCountedOnlyIfDisabled = GetParam() ? kUncounted : kCounted;
-
- Vector<std::pair<String, int>> test_cases = {
- {"", kUncounted},
- {"#element", kUncounted},
- {"#doesntExist", kUncounted},
- {"#element##foo", kCountedOnlyIfDisabled},
- {"#doesntexist##foo", kCountedOnlyIfDisabled},
- {"##element", kCountedOnlyIfDisabled},
- {"#element#", kCounted},
- {"#foo#bar#", kCounted},
- {"#foo%23", kUncounted},
- {"#element##targetText=doesntexist", kUncounted},
- {"#element##targetText=doesntexist#", kUncounted},
- {"#element##targetText=page", kUncounted},
- {"#element##targetText=page#", kUncounted},
- {"##targetText=doesntexist", kUncounted},
- {"##targetText=doesntexist#", kUncounted},
- {"##targetText=page", kUncounted},
- {"##targetText=page#", kUncounted},
- {"#targetText=doesntexist", kUncounted},
- {"#targetText=page", kUncounted}};
-
- for (auto test_case : test_cases) {
- String url = "https://example.com/test.html" + test_case.first;
- SimRequest request(url, "text/html");
- LoadURL(url);
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <p id="element">This is a test page</p>
- )HTML");
- Compositor().BeginFrame();
-
- RunAsyncMatchingTasks();
-
- bool is_use_counted =
- GetDocument().IsUseCounted(WebFeature::kFragmentDoubleHash);
- if (test_case.second == kCounted) {
- EXPECT_TRUE(is_use_counted)
- << "Expected to count double-hash but didn't in case: "
- << test_case.first;
- } else {
- EXPECT_FALSE(is_use_counted)
- << "Expected not to count double-hash but did in case: "
- << test_case.first;
- }
- }
-}
-
// Test counting occurrences of ~&~ in the URL fragment. Used for potentially
// using ~&~ as a delimiter. Can be removed once the feature ships.
TEST_P(TextFragmentRelatedMetricTest, TildeAmpersandTildeUseCounter) {
const int kUncounted = 0;
const int kCounted = 1;
- Vector<std::pair<String, int>> test_cases = {
- {"", kUncounted},
- {"#element", kUncounted},
- {"#doesntExist", kUncounted},
- {"#~&~element", kCounted},
- {"#element~&~", kCounted},
- {"#foo~&~bar", kCounted},
- {"#foo~&~targetText=foo", kCounted}};
+ Vector<std::pair<String, int>> test_cases = {{"", kUncounted},
+ {"#element", kUncounted},
+ {"#doesntExist", kUncounted},
+ {"#~&~element", kCounted},
+ {"#element~&~", kCounted},
+ {"#foo~&~bar", kCounted},
+ {"#foo~&~text=foo", kCounted}};
for (auto test_case : test_cases) {
String url = "https://example.com/test.html" + test_case.first;
@@ -543,14 +479,13 @@ TEST_P(TextFragmentRelatedMetricTest, TildeAtTildeUseCounter) {
const int kUncounted = 0;
const int kCounted = 1;
- Vector<std::pair<String, int>> test_cases = {
- {"", kUncounted},
- {"#element", kUncounted},
- {"#doesntExist", kUncounted},
- {"#~@~element", kCounted},
- {"#element~@~", kCounted},
- {"#foo~@~bar", kCounted},
- {"#foo~@~targetText=foo", kCounted}};
+ Vector<std::pair<String, int>> test_cases = {{"", kUncounted},
+ {"#element", kUncounted},
+ {"#doesntExist", kUncounted},
+ {"#~@~element", kCounted},
+ {"#element~@~", kCounted},
+ {"#foo~@~bar", kCounted},
+ {"#foo~@~text=foo", kCounted}};
for (auto test_case : test_cases) {
String url = "https://example.com/test.html" + test_case.first;
@@ -590,7 +525,7 @@ TEST_P(TextFragmentRelatedMetricTest, AmpersandDelimiterQuestionUseCounter) {
{"#&delimiter?element", kCounted},
{"#element&delimiter?", kCounted},
{"#foo&delimiter?bar", kCounted},
- {"#foo&delimiter?targetText=foo", kCounted}};
+ {"#foo&delimiter?text=foo", kCounted}};
for (auto test_case : test_cases) {
String url = "https://example.com/test.html" + test_case.first;
@@ -618,22 +553,21 @@ TEST_P(TextFragmentRelatedMetricTest, AmpersandDelimiterQuestionUseCounter) {
}
}
-// Test counting occurrences of non-targetText :~: in the URL fragment. Used to
+// Test counting occurrences of non-directive :~: in the URL fragment. Used to
// ensure :~: is web-compatible; can be removed once the feature ships.
TEST_P(TextFragmentRelatedMetricTest, NewDelimiterUseCounter) {
const int kUncounted = 0;
const int kCounted = 1;
- Vector<std::pair<String, int>> test_cases = {
- {"", kUncounted},
- {"#element", kUncounted},
- {"#doesntExist", kUncounted},
- {"#:~:element", kCounted},
- {"#element:~:", kCounted},
- {"#foo:~:bar", kCounted},
- {"#:~:utargetText=foo", kCounted},
- {"#:~:targetText=foo", kUncounted},
- {"#foo:~:targetText=foo", kUncounted}};
+ Vector<std::pair<String, int>> test_cases = {{"", kUncounted},
+ {"#element", kUncounted},
+ {"#doesntExist", kUncounted},
+ {"#:~:element", kCounted},
+ {"#element:~:", kCounted},
+ {"#foo:~:bar", kCounted},
+ {"#:~:utext=foo", kCounted},
+ {"#:~:text=foo", kUncounted},
+ {"#foo:~:text=foo", kUncounted}};
for (auto test_case : test_cases) {
String url = "https://example.com/test.html" + test_case.first;
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 65c60b96860..dbc344ba17c 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
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/location.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/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
@@ -78,9 +79,8 @@ class TextFragmentAnchorTest : public SimTest {
// Basic test case, ensure we scroll the matching text into view.
TEST_F(TextFragmentAnchorTest, BasicSmokeTest) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -108,9 +108,9 @@ TEST_F(TextFragmentAnchorTest, BasicSmokeTest) {
// Make sure a non-matching string doesn't cause scroll and the fragment is
// removed when completed.
TEST_F(TextFragmentAnchorTest, NonMatchingString) {
- SimRequest request("https://example.com/test.html#targetText=unicorn",
+ SimRequest request("https://example.com/test.html#:~:text=unicorn",
"text/html");
- LoadURL("https://example.com/test.html#targetText=unicorn");
+ LoadURL("https://example.com/test.html#:~:text=unicorn");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -137,46 +137,10 @@ TEST_F(TextFragmentAnchorTest, NonMatchingString) {
EXPECT_TRUE(GetDocument().Markers().Markers().IsEmpty());
}
-// If the targetText=... string matches an id, we should scroll using id
-// fragment semantics rather than doing a textual match.
-TEST_F(TextFragmentAnchorTest, IdFragmentTakesPrecedence) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test");
- request.Complete(R"HTML(
- <!DOCTYPE html>
- <style>
- body {
- height: 2200px;
- }
- p {
- position: absolute;
- top: 1000px;
- }
- div {
- position: absolute;
- top: 2000px;
- }
- </style>
- <p id="text">This is a test page</p>
- <div id="targetText=test">Some text</div>
- )HTML");
- Compositor().BeginFrame();
-
- RunAsyncMatchingTasks();
-
- Element& div = *GetDocument().getElementById("targetText=test");
-
- EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(div)))
- << "Should have scrolled <div> into view but didn't, scroll offset: "
- << LayoutViewport()->GetScrollOffset().ToString();
-}
-
// Ensure multiple matches will scroll the first into view.
TEST_F(TextFragmentAnchorTest, MultipleMatches) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -211,9 +175,8 @@ TEST_F(TextFragmentAnchorTest, MultipleMatches) {
// Ensure matching works inside nested blocks.
TEST_F(TextFragmentAnchorTest, NestedBlocks) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -241,13 +204,12 @@ TEST_F(TextFragmentAnchorTest, NestedBlocks) {
<< LayoutViewport()->GetScrollOffset().ToString();
}
-// Ensure multiple targetTexts are highlighted and the first is scrolled into
+// Ensure multiple texts are highlighted and the first is scrolled into
// view.
TEST_F(TextFragmentAnchorTest, MultipleTextFragments) {
- SimRequest request(
- "https://example.com/test.html#targetText=test&targetText=more",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test&targetText=more");
+ SimRequest request("https://example.com/test.html#:~:text=test&text=more",
+ "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test&text=more");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -279,12 +241,11 @@ TEST_F(TextFragmentAnchorTest, MultipleTextFragments) {
EXPECT_EQ(2u, GetDocument().Markers().Markers().size());
}
-// Ensure we scroll the second targetText into view if the first isn't found.
+// Ensure we scroll the second text into view if the first isn't found.
TEST_F(TextFragmentAnchorTest, FirstTextFragmentNotFound) {
- SimRequest request(
- "https://example.com/test.html#targetText=test&targetText=more",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test&targetText=more");
+ SimRequest request("https://example.com/test.html#:~:text=test&text=more",
+ "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test&text=more");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -316,13 +277,12 @@ TEST_F(TextFragmentAnchorTest, FirstTextFragmentNotFound) {
EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
}
-// Ensure we still scroll the first targetText into view if the second isn't
+// Ensure we still scroll the first text into view if the second isn't
// found.
TEST_F(TextFragmentAnchorTest, OnlyFirstTextFragmentFound) {
- SimRequest request(
- "https://example.com/test.html#targetText=test&targetText=more",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test&targetText=more");
+ SimRequest request("https://example.com/test.html#:~:text=test&text=more",
+ "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test&text=more");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -354,11 +314,11 @@ TEST_F(TextFragmentAnchorTest, OnlyFirstTextFragmentFound) {
TEST_F(TextFragmentAnchorTest, MultipleNonMatchingStrings) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=unicorn&targetText=cookie&targetText=cat",
+ "test.html#:~:text=unicorn&text=cookie&text=cat",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=unicorn&targetText=cookie&targetText=cat");
+ "test.html#:~:text=unicorn&text=cookie&text=cat");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -387,9 +347,9 @@ TEST_F(TextFragmentAnchorTest, MultipleNonMatchingStrings) {
// Test matching a text range within the same element
TEST_F(TextFragmentAnchorTest, SameElementTextRange) {
- SimRequest request("https://example.com/test.html#targetText=This,page",
+ SimRequest request("https://example.com/test.html#:~:text=This,page",
"text/html");
- LoadURL("https://example.com/test.html#targetText=This,page");
+ LoadURL("https://example.com/test.html#:~:text=This,page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -412,7 +372,7 @@ TEST_F(TextFragmentAnchorTest, SameElementTextRange) {
// Expect marker on "This is a test page".
auto* text = To<Text>(GetDocument().getElementById("text")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(19u, markers.at(0)->EndOffset());
@@ -420,9 +380,9 @@ TEST_F(TextFragmentAnchorTest, SameElementTextRange) {
// Test matching a text range across two neighboring elements
TEST_F(TextFragmentAnchorTest, NeighboringElementTextRange) {
- SimRequest request("https://example.com/test.html#targetText=test,paragraph",
+ SimRequest request("https://example.com/test.html#:~:text=test,paragraph",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test,paragraph");
+ LoadURL("https://example.com/test.html#:~:text=test,paragraph");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -446,7 +406,7 @@ TEST_F(TextFragmentAnchorTest, NeighboringElementTextRange) {
// Expect marker on "test page"
auto* text1 = To<Text>(GetDocument().getElementById("text1")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text1, DocumentMarker::MarkerTypes::TextMatch());
+ *text1, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(10u, markers.at(0)->StartOffset());
EXPECT_EQ(19u, markers.at(0)->EndOffset());
@@ -454,7 +414,7 @@ TEST_F(TextFragmentAnchorTest, NeighboringElementTextRange) {
// Expect marker on "with another paragraph"
auto* text2 = To<Text>(GetDocument().getElementById("text2")->firstChild());
markers = GetDocument().Markers().MarkersFor(
- *text2, DocumentMarker::MarkerTypes::TextMatch());
+ *text2, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(22u, markers.at(0)->EndOffset());
@@ -462,9 +422,9 @@ TEST_F(TextFragmentAnchorTest, NeighboringElementTextRange) {
// Test matching a text range from an element to a deeper nested element
TEST_F(TextFragmentAnchorTest, DifferentDepthElementTextRange) {
- SimRequest request("https://example.com/test.html#targetText=test,paragraph",
+ SimRequest request("https://example.com/test.html#:~:text=test,paragraph",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test,paragraph");
+ LoadURL("https://example.com/test.html#:~:text=test,paragraph");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -490,7 +450,7 @@ TEST_F(TextFragmentAnchorTest, DifferentDepthElementTextRange) {
// Expect marker on "test page"
auto* text1 = To<Text>(GetDocument().getElementById("text1")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text1, DocumentMarker::MarkerTypes::TextMatch());
+ *text1, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(10u, markers.at(0)->StartOffset());
EXPECT_EQ(19u, markers.at(0)->EndOffset());
@@ -498,7 +458,7 @@ TEST_F(TextFragmentAnchorTest, DifferentDepthElementTextRange) {
// Expect marker on "with another paragraph"
auto* text2 = To<Text>(GetDocument().getElementById("text2")->firstChild());
markers = GetDocument().Markers().MarkersFor(
- *text2, DocumentMarker::MarkerTypes::TextMatch());
+ *text2, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(22u, markers.at(0)->EndOffset());
@@ -506,9 +466,9 @@ TEST_F(TextFragmentAnchorTest, DifferentDepthElementTextRange) {
// Ensure that we don't match anything if endText is not found.
TEST_F(TextFragmentAnchorTest, TextRangeEndTextNotFound) {
- SimRequest request("https://example.com/test.html#targetText=test,cat",
+ SimRequest request("https://example.com/test.html#:~:text=test,cat",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test,cat");
+ LoadURL("https://example.com/test.html#:~:text=test,cat");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -534,11 +494,11 @@ TEST_F(TextFragmentAnchorTest, TextRangeEndTextNotFound) {
TEST_F(TextFragmentAnchorTest, MultipleTextRanges) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=test,with&targetText=paragraph,text",
+ "test.html#:~:text=test,with&text=paragraph,text",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=test,with&targetText=paragraph,text");
+ "test.html#:~:text=test,with&text=paragraph,text");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -564,7 +524,7 @@ TEST_F(TextFragmentAnchorTest, MultipleTextRanges) {
// Expect marker on "test page"
auto* text1 = To<Text>(GetDocument().getElementById("text1")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text1, DocumentMarker::MarkerTypes::TextMatch());
+ *text1, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(10u, markers.at(0)->StartOffset());
EXPECT_EQ(19u, markers.at(0)->EndOffset());
@@ -572,7 +532,7 @@ TEST_F(TextFragmentAnchorTest, MultipleTextRanges) {
// Expect markers on "with" and "paragraph of text"
auto* text2 = To<Text>(GetDocument().getElementById("text2")->firstChild());
markers = GetDocument().Markers().MarkersFor(
- *text2, DocumentMarker::MarkerTypes::TextMatch());
+ *text2, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(2u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(4u, markers.at(0)->EndOffset());
@@ -582,9 +542,9 @@ TEST_F(TextFragmentAnchorTest, MultipleTextRanges) {
// Ensure we scroll to the beginning of a text range larger than the viewport.
TEST_F(TextFragmentAnchorTest, DistantElementTextRange) {
- SimRequest request("https://example.com/test.html#targetText=test,paragraph",
+ SimRequest request("https://example.com/test.html#:~:text=test,paragraph",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test,paragraph");
+ LoadURL("https://example.com/test.html#:~:text=test,paragraph");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -609,9 +569,8 @@ TEST_F(TextFragmentAnchorTest, DistantElementTextRange) {
// Test a text range with both context terms in the same element.
TEST_F(TextFragmentAnchorTest, TextRangeWithContext) {
SimRequest request(
- "https://example.com/test.html#targetText=This-,is,test,-page",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=This-,is,test,-page");
+ "https://example.com/test.html#:~:text=This-,is,test,-page", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=This-,is,test,-page");
request.Complete(R"HTML(
<!DOCTYPE html>
<p id="text">This is a test page</p>
@@ -625,7 +584,7 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithContext) {
// Expect marker on "is a test".
auto* text = To<Text>(GetDocument().getElementById("text")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(5u, markers.at(0)->StartOffset());
EXPECT_EQ(14u, markers.at(0)->EndOffset());
@@ -634,9 +593,9 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithContext) {
// Ensure that we do not match a text range if the prefix is not found.
TEST_F(TextFragmentAnchorTest, PrefixNotFound) {
SimRequest request(
- "https://example.com/test.html#targetText=prefix-,is,test,-page",
+ "https://example.com/test.html#:~:text=prefix-,is,test,-page",
"text/html");
- LoadURL("https://example.com/test.html#targetText=prefix-,is,test,-page");
+ LoadURL("https://example.com/test.html#:~:text=prefix-,is,test,-page");
request.Complete(R"HTML(
<!DOCTYPE html>
<p id="text">This is a test page</p>
@@ -651,9 +610,9 @@ TEST_F(TextFragmentAnchorTest, PrefixNotFound) {
// Ensure that we do not match a text range if the suffix is not found.
TEST_F(TextFragmentAnchorTest, SuffixNotFound) {
SimRequest request(
- "https://example.com/test.html#targetText=This-,is,test,-suffix",
+ "https://example.com/test.html#:~:text=This-,is,test,-suffix",
"text/html");
- LoadURL("https://example.com/test.html#targetText=This-,is,test,-suffix");
+ LoadURL("https://example.com/test.html#:~:text=This-,is,test,-suffix");
request.Complete(R"HTML(
<!DOCTYPE html>
<p id="text">This is a test page</p>
@@ -668,11 +627,11 @@ TEST_F(TextFragmentAnchorTest, SuffixNotFound) {
// Test a text range with context terms in different elements
TEST_F(TextFragmentAnchorTest, TextRangeWithCrossElementContext) {
SimRequest request(
- "https://example.com/test.html#targetText=Header%202-,A,text,-Footer%201",
+ "https://example.com/test.html#:~:text=Header%202-,A,text,-Footer%201",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=Header%202-,A,text,-Footer%201");
+ "test.html#:~:text=Header%202-,A,text,-Footer%201");
request.Complete(R"HTML(
<!DOCTYPE html>
<h1>Header 1</h1>
@@ -694,7 +653,7 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithCrossElementContext) {
// Expect marker on the expected "A string of text".
auto* text = To<Text>(GetDocument().getElementById("expected")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(16u, markers.at(0)->EndOffset());
@@ -704,11 +663,11 @@ TEST_F(TextFragmentAnchorTest, TextRangeWithCrossElementContext) {
TEST_F(TextFragmentAnchorTest, CrossElementAndWhitespaceContext) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=List%202-,Cat,-Good%20cat",
+ "test.html#:~:text=List%202-,Cat,-Good%20cat",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=List%202-,Cat,-Good%20cat");
+ "test.html#:~:text=List%202-,Cat,-Good%20cat");
request.Complete(R"HTML(
<!DOCTYPE html>
<h1> List 1 </h1>
@@ -736,7 +695,7 @@ TEST_F(TextFragmentAnchorTest, CrossElementAndWhitespaceContext) {
// Expect marker on the expected "cat".
auto* text = To<Text>(GetDocument().getElementById("expected")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(3u, markers.at(0)->EndOffset());
@@ -746,11 +705,11 @@ TEST_F(TextFragmentAnchorTest, CrossElementAndWhitespaceContext) {
TEST_F(TextFragmentAnchorTest, CrossEmptySiblingAndParentElementContext) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=prefix-,match,-suffix",
+ "test.html#:~:text=prefix-,match,-suffix",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=prefix-,match,-suffix");
+ "test.html#:~:text=prefix-,match,-suffix");
request.Complete(R"HTML(
<!DOCTYPE html>
<div>
@@ -772,7 +731,7 @@ TEST_F(TextFragmentAnchorTest, CrossEmptySiblingAndParentElementContext) {
// Expect marker on "match".
auto* text = To<Text>(GetDocument().getElementById("expected")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(5u, markers.at(0)->EndOffset());
@@ -781,9 +740,9 @@ TEST_F(TextFragmentAnchorTest, CrossEmptySiblingAndParentElementContext) {
// Ensure we scroll to text when its prefix and suffix are out of view.
TEST_F(TextFragmentAnchorTest, DistantElementContext) {
SimRequest request(
- "https://example.com/test.html#targetText=Prefix-,Cats,-Suffix",
+ "https://example.com/test.html#:~:text=Prefix-,Cats,-Suffix",
"text/html");
- LoadURL("https://example.com/test.html#targetText=Prefix-,Cats,-Suffix");
+ LoadURL("https://example.com/test.html#:~:text=Prefix-,Cats,-Suffix");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -811,11 +770,11 @@ TEST_F(TextFragmentAnchorTest, DistantElementContext) {
TEST_F(TextFragmentAnchorTest, OneContextTerm) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=test-,page&targetText=page,-with%20real%20content",
+ "test.html#:~:text=test-,page&text=page,-with%20real%20content",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=test-,page&targetText=page,-with%20real%20content");
+ "test.html#:~:text=test-,page&text=page,-with%20real%20content");
request.Complete(R"HTML(
<!DOCTYPE html>
<p id="text1">This is a test page</p>
@@ -828,7 +787,7 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
// Expect marker on the first "page"
auto* text1 = To<Text>(GetDocument().getElementById("text1")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text1, DocumentMarker::MarkerTypes::TextMatch());
+ *text1, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(15u, markers.at(0)->StartOffset());
EXPECT_EQ(19u, markers.at(0)->EndOffset());
@@ -836,7 +795,7 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
// Expect marker on the second "page"
auto* text2 = To<Text>(GetDocument().getElementById("text2")->firstChild());
markers = GetDocument().Markers().MarkersFor(
- *text2, DocumentMarker::MarkerTypes::TextMatch());
+ *text2, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(6u, markers.at(0)->StartOffset());
EXPECT_EQ(10u, markers.at(0)->EndOffset());
@@ -844,10 +803,9 @@ TEST_F(TextFragmentAnchorTest, OneContextTerm) {
// Test that a user scroll cancels the scroll into view.
TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
- LoadURL("https://example.com/test.html#targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -883,7 +841,7 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
// Expect marker on "test"
auto* text = To<Text>(p.firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(10u, markers.at(0)->StartOffset());
EXPECT_EQ(14u, markers.at(0)->EndOffset());
@@ -893,12 +851,12 @@ TEST_F(TextFragmentAnchorTest, ScrollCancelled) {
// disabled in iframes by design, for security reasons.
TEST_F(TextFragmentAnchorTest, DisabledInIframes) {
SimRequest main_request("https://example.com/test.html", "text/html");
- SimRequest child_request("https://example.com/child.html#targetText=test",
+ SimRequest child_request("https://example.com/child.html#:~:text=test",
"text/html");
LoadURL("https://example.com/test.html");
main_request.Complete(R"HTML(
<!DOCTYPE html>
- <iframe id="iframe" src="child.html#targetText=test"></iframe>
+ <iframe id="iframe" src="child.html#:~:text=test"></iframe>
)HTML");
child_request.Complete(R"HTML(
@@ -927,7 +885,7 @@ TEST_F(TextFragmentAnchorTest, DisabledInIframes) {
// Similarly to the iframe case, we also want to prevent activating a text
// fragment anchor inside a window.opened window.
TEST_F(TextFragmentAnchorTest, DisabledInWindowOpen) {
- String destination = "https://example.com/child.html#targetText=test";
+ String destination = "https://example.com/child.html#:~:text=test";
SimRequest main_request("https://example.com/test.html", "text/html");
SimRequest child_request(destination, "text/html");
@@ -994,7 +952,7 @@ TEST_F(TextFragmentAnchorTest, DisabledInSamePageNavigation) {
ToScriptStateForMainWorld(GetDocument().GetFrame());
ScriptState::Scope entered_context_scope(script_state);
GetDocument().GetFrame()->DomWindow()->location()->setHash(
- script_state->GetIsolate(), "targetText=test", ASSERT_NO_EXCEPTION);
+ script_state->GetIsolate(), "text=test", ASSERT_NO_EXCEPTION);
RunAsyncMatchingTasks();
EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
@@ -1002,9 +960,8 @@ TEST_F(TextFragmentAnchorTest, DisabledInSamePageNavigation) {
// Ensure matching is case insensitive.
TEST_F(TextFragmentAnchorTest, CaseInsensitive) {
- SimRequest request("https://example.com/test.html#targetText=Test",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=Test");
+ SimRequest request("https://example.com/test.html#:~:text=Test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=Test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1032,10 +989,10 @@ TEST_F(TextFragmentAnchorTest, CaseInsensitive) {
// Test that the fragment anchor stays centered in view throughout loading.
TEST_F(TextFragmentAnchorTest, TargetStaysInView) {
- SimRequest main_request("https://example.com/test.html#targetText=test",
+ SimRequest main_request("https://example.com/test.html#:~:text=test",
"text/html");
SimRequest image_request("https://example.com/image.svg", "image/svg+xml");
- LoadURL("https://example.com/test.html#targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test");
main_request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1076,10 +1033,9 @@ TEST_F(TextFragmentAnchorTest, TargetStaysInView) {
// Test that overlapping text ranges results in only the first one highlighted
TEST_F(TextFragmentAnchorTest, OverlappingTextRanges) {
SimRequest request(
- "https://example.com/test.html#targetText=This,test&targetText=is,page",
+ "https://example.com/test.html#:~:text=This,test&text=is,page",
"text/html");
- LoadURL(
- "https://example.com/test.html#targetText=This,test&targetText=is,page");
+ LoadURL("https://example.com/test.html#:~:text=This,test&text=is,page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1102,18 +1058,17 @@ TEST_F(TextFragmentAnchorTest, OverlappingTextRanges) {
// Expect marker on "This is a test".
auto* text = To<Text>(GetDocument().getElementById("text")->firstChild());
DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
- *text, DocumentMarker::MarkerTypes::TextMatch());
+ *text, DocumentMarker::MarkerTypes::TextFragment());
ASSERT_EQ(1u, markers.size());
EXPECT_EQ(0u, markers.at(0)->StartOffset());
EXPECT_EQ(14u, markers.at(0)->EndOffset());
}
-// Test that the ##targetText fragment syntax works properly and is stripped
-// from the URL.
-TEST_F(TextFragmentAnchorTest, DoubleHashSyntax) {
- SimRequest request("https://example.com/test.html##targetText=test",
+// Test matching a space to &nbsp character.
+TEST_F(TextFragmentAnchorTest, SpaceMatchesNbsp) {
+ SimRequest request("https://example.com/test.html#:~:text=test%20page",
"text/html");
- LoadURL("https://example.com/test.html##targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test%20page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1125,93 +1080,101 @@ TEST_F(TextFragmentAnchorTest, DoubleHashSyntax) {
top: 1000px;
}
</style>
- <p id="text">This is a test page</p>
+ <p id="text">This is a test&nbsp;page</p>
)HTML");
Compositor().BeginFrame();
RunAsyncMatchingTasks();
- EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+ Element& p = *GetDocument().getElementById("text");
- EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html");
+ EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
+ << "<p> Element wasn't scrolled into view, viewport's scroll offset: "
+ << LayoutViewport()->GetScrollOffset().ToString();
+
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
}
-// Test that the ##targetText fragment directive is scrolled into view and is
-// stripped from the URL when there's also a valid element fragment.
-TEST_F(TextFragmentAnchorTest, DoubleHashWithElementFragment) {
- SimRequest request("https://example.com/test.html#element##targetText=test",
+// Test matching text with a CSS text transform.
+TEST_F(TextFragmentAnchorTest, CSSTextTransform) {
+ SimRequest request("https://example.com/test.html#:~:text=test%20page",
"text/html");
- LoadURL("https://example.com/test.html#element##targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test%20page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
- height: 2200px;
+ height: 1200px;
}
- #text {
+ p {
position: absolute;
top: 1000px;
- }
- #element {
- position: absolute;
- top: 2000px;
+ text-transform: uppercase;
}
</style>
<p id="text">This is a test page</p>
- <div id="element">Some text</div>
)HTML");
Compositor().BeginFrame();
RunAsyncMatchingTasks();
- EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html#element");
-
Element& p = *GetDocument().getElementById("text");
EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
<< "<p> Element wasn't scrolled into view, viewport's scroll offset: "
<< LayoutViewport()->GetScrollOffset().ToString();
+
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
}
-// A double-hash should be interpreted as a fragment directive and should be
-// stripped from the URL, even if it is not a targetText.
-TEST_F(TextFragmentAnchorTest, IdFragmentWithDoubleHash) {
- SimRequest request("https://example.com/test.html#element##id", "text/html");
- LoadURL("https://example.com/test.html#element##id");
+// Test that we scroll the element fragment into view if we don't find a match.
+TEST_F(TextFragmentAnchorTest, NoMatchFoundFallsBackToElementFragment) {
+ SimRequest request("https://example.com/test.html#element:~:text=cats",
+ "text/html");
+ LoadURL("https://example.com/test.html#element:~:text=cats");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
height: 2200px;
}
- p {
+ #text {
position: absolute;
top: 1000px;
}
- div {
+ #element {
position: absolute;
top: 2000px;
}
</style>
- <p id="element">This is a test page</p>
- <div id="element##id">Some text</div>
+ <p>This is a test page</p>
+ <div id="element">Some text</div>
)HTML");
Compositor().BeginFrame();
+ RunAsyncMatchingTasks();
+ // The TextFragmentAnchor needs another frame to invoke the element anchor
+ Compositor().BeginFrame();
RunAsyncMatchingTasks();
- Element& div = *GetDocument().getElementById("element");
+ EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html#element");
- EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(div)))
- << "Should have scrolled <div> into view but didn't, scroll offset: "
+ Element& p = *GetDocument().getElementById("element");
+
+ EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
+ << "<p> Element wasn't scrolled into view, viewport's scroll offset: "
<< LayoutViewport()->GetScrollOffset().ToString();
}
-// Test matching a space to &nbsp character.
-TEST_F(TextFragmentAnchorTest, SpaceMatchesNbsp) {
- SimRequest request("https://example.com/test.html#targetText=test%20page",
- "text/html");
- LoadURL("https://example.com/test.html#targetText=test%20page");
+// Test that we don't match partial words at the beginning or end of the text.
+TEST_F(TextFragmentAnchorTest, CheckForWordBoundary) {
+ SimRequest request(
+ "https://example.com/"
+ "test.html#:~:text=This%20is%20a%20te&tagetText=st%20page",
+ "text/html");
+ LoadURL(
+ "https://example.com/"
+ "test.html#:~:text=This%20is%20a%20te&tagetText=st%20page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1223,26 +1186,20 @@ TEST_F(TextFragmentAnchorTest, SpaceMatchesNbsp) {
top: 1000px;
}
</style>
- <p id="text">This is a test&nbsp;page</p>
+ <p id="text">This is a test page</p>
)HTML");
Compositor().BeginFrame();
-
RunAsyncMatchingTasks();
- Element& p = *GetDocument().getElementById("text");
-
- EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
- << "<p> Element wasn't scrolled into view, viewport's scroll offset: "
- << LayoutViewport()->GetScrollOffset().ToString();
-
- EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+ EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
+ EXPECT_TRUE(GetDocument().Markers().Markers().IsEmpty());
}
-// Test matching text with a CSS text transform.
-TEST_F(TextFragmentAnchorTest, CSSTextTransform) {
- SimRequest request("https://example.com/test.html#targetText=test%20page",
+// Test that we don't match partial words with context
+TEST_F(TextFragmentAnchorTest, CheckForWordBoundaryWithContext) {
+ SimRequest request("https://example.com/test.html#:~:text=est-,page",
"text/html");
- LoadURL("https://example.com/test.html#targetText=test%20page");
+ LoadURL("https://example.com/test.html#:~:text=est-,page");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1252,72 +1209,68 @@ TEST_F(TextFragmentAnchorTest, CSSTextTransform) {
p {
position: absolute;
top: 1000px;
- text-transform: uppercase;
}
</style>
<p id="text">This is a test page</p>
)HTML");
Compositor().BeginFrame();
-
RunAsyncMatchingTasks();
- Element& p = *GetDocument().getElementById("text");
-
- EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
- << "<p> Element wasn't scrolled into view, viewport's scroll offset: "
- << LayoutViewport()->GetScrollOffset().ToString();
-
- EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+ EXPECT_EQ(ScrollOffset(), LayoutViewport()->GetScrollOffset());
+ EXPECT_TRUE(GetDocument().Markers().Markers().IsEmpty());
}
-// Test that we scroll the element fragment into view if we don't find a match.
-TEST_F(TextFragmentAnchorTest, NoMatchFoundFallsBackToElementFragment) {
- SimRequest request("https://example.com/test.html#element##targetText=cats",
+// Test that we correctly match a whole word when it appears as a partial word
+// earlier in the page.
+TEST_F(TextFragmentAnchorTest, CheckForWordBoundaryWithPartialWord) {
+ SimRequest request("https://example.com/test.html#:~:text=tes,age",
"text/html");
- LoadURL("https://example.com/test.html#element##targetText=cats");
+ LoadURL("https://example.com/test.html#:~:text=tes,age");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
body {
- height: 2200px;
+ height: 1200px;
}
- #text {
+ #first {
position: absolute;
top: 1000px;
}
- #element {
+ #second {
position: absolute;
top: 2000px;
}
</style>
- <p>This is a test page</p>
- <div id="element">Some text</div>
+ <p id="first">This is a test page</p>
+ <p id="second">This is a tes age</p>
)HTML");
Compositor().BeginFrame();
RunAsyncMatchingTasks();
- // The TextFragmentAnchor needs another frame to invoke the element anchor
- Compositor().BeginFrame();
- RunAsyncMatchingTasks();
-
- EXPECT_EQ(GetDocument().Url(), "https://example.com/test.html#element");
-
- Element& p = *GetDocument().getElementById("element");
+ Element& p = *GetDocument().getElementById("second");
EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(p)))
- << "<p> Element wasn't scrolled into view, viewport's scroll offset: "
+ << "Should have scrolled <p> into view but didn't, scroll offset: "
<< LayoutViewport()->GetScrollOffset().ToString();
+
+ // Expect marker on only "tes age"
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+ DocumentMarkerVector markers = GetDocument().Markers().MarkersFor(
+ *To<Text>(p.firstChild()), DocumentMarker::MarkerTypes::TextFragment());
+ ASSERT_EQ(1u, markers.size());
+ EXPECT_EQ(10u, markers.at(0)->StartOffset());
+ EXPECT_EQ(17u, markers.at(0)->EndOffset());
}
// Test dismissing the text highlight with a click
TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithClick) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text",
+ "test.html#:~:text=test%20page&text=more%20text",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text");
+ "test.html#:~:text=test%20page&text=more%20text");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1353,11 +1306,11 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithClick) {
TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithTap) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text",
+ "test.html#:~:text=test%20page&text=more%20text",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text");
+ "test.html#:~:text=test%20page&text=more%20text");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1391,10 +1344,9 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightWithTap) {
// Test that we don't dismiss a text highlight before it's scrolled into view
TEST_F(TextFragmentAnchorTest, DismissTextHighlightOutOfView) {
- SimRequest request("https://example.com/test.html#targetText=test",
- "text/html");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
SimSubresourceRequest css_request("https://example.com/test.css", "text/css");
- LoadURL("https://example.com/test.html#targetText=test");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1434,11 +1386,11 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightOutOfView) {
TEST_F(TextFragmentAnchorTest, DismissTextHighlightInView) {
SimRequest request(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text",
+ "test.html#:~:text=test%20page&text=more%20text",
"text/html");
LoadURL(
"https://example.com/"
- "test.html#targetText=test%20page&targetText=more%20text");
+ "test.html#:~:text=test%20page&text=more%20text");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1469,9 +1421,8 @@ TEST_F(TextFragmentAnchorTest, DismissTextHighlightInView) {
// Test that the fragment directive delimiter :~: works properly and is stripped
// from the URL.
TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiter) {
- SimRequest request("https://example.com/test.html#:~:targetText=test",
- "text/html");
- LoadURL("https://example.com/test.html#:~:targetText=test");
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1497,9 +1448,9 @@ TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiter) {
// Test that a :~: fragment directive is scrolled into view and is stripped from
// the URL when there's also a valid element fragment.
TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiterWithElementFragment) {
- SimRequest request("https://example.com/test.html#element:~:targetText=test",
+ SimRequest request("https://example.com/test.html#element:~:text=test",
"text/html");
- LoadURL("https://example.com/test.html#element:~:targetText=test");
+ LoadURL("https://example.com/test.html#element:~:text=test");
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1532,7 +1483,7 @@ TEST_F(TextFragmentAnchorTest, FragmentDirectiveDelimiterWithElementFragment) {
}
// Test that a fragment directive is stripped from the URL even if it is not a
-// targetText.
+// text directive.
TEST_F(TextFragmentAnchorTest, IdFragmentWithFragmentDirective) {
SimRequest request("https://example.com/test.html#element:~:id", "text/html");
LoadURL("https://example.com/test.html#element:~:id");
@@ -1565,6 +1516,76 @@ TEST_F(TextFragmentAnchorTest, IdFragmentWithFragmentDirective) {
<< LayoutViewport()->GetScrollOffset().ToString();
}
+// Ensure we can match <text> inside of a <svg> element.
+TEST_F(TextFragmentAnchorTest, TextDirectiveInSvg) {
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ body {
+ height: 1200px;
+ }
+ svg {
+ position: absolute;
+ top: 1000px;
+ }
+ </style>
+ <svg><text id="text" x="0" y="15">This is a test page</text></svg>
+ )HTML");
+ Compositor().BeginFrame();
+
+ RunAsyncMatchingTasks();
+
+ Element& text = *GetDocument().getElementById("text");
+
+ EXPECT_TRUE(ViewportRect().Contains(BoundingRectInFrame(text)))
+ << "<text> Element wasn't scrolled into view, viewport's scroll offset: "
+ << LayoutViewport()->GetScrollOffset().ToString();
+
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+}
+
+// Ensure we restore the text highlight on page reload
+TEST_F(TextFragmentAnchorTest, HighlightOnReload) {
+ SimRequest request("https://example.com/test.html#:~:text=test", "text/html");
+ LoadURL("https://example.com/test.html#:~:text=test");
+ const String& html = R"HTML(
+ <!DOCTYPE html>
+ <style>
+ body {
+ height: 1200px;
+ }
+ p {
+ position: absolute;
+ top: 1000px;
+ }
+ </style>
+ <p id="text">This is a test page</p>
+ )HTML";
+ request.Complete(html);
+
+ Compositor().BeginFrame();
+ RunAsyncMatchingTasks();
+
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+
+ // Tap to dismiss the highlight.
+ SimulateClick(10, 10);
+ EXPECT_EQ(0u, GetDocument().Markers().Markers().size());
+
+ // Reload the page and expect the highlight to be restored.
+ SimRequest reload_request("https://example.com/test.html#:~:text=test",
+ "text/html");
+ MainFrame().StartReload(WebFrameLoadType::kReload);
+ reload_request.Complete(html);
+
+ Compositor().BeginFrame();
+ RunAsyncMatchingTasks();
+
+ EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
index edca62e1bc1..9e632ab8fdb 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/editing/iterators/character_iterator.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
+#include "third_party/blink/renderer/platform/text/text_boundaries.h"
namespace blink {
@@ -22,12 +23,54 @@ namespace {
const char kNoContext[] = "";
+// Determines whether the start and end positions of |range| are on word
+// boundaries.
+// TODO(crbug/924965): Determine how this should check node boundaries. This
+// treats node boundaries as word boundaries, for example "o" is a whole word
+// match in "f<i>o</i>o".
+bool IsWholeWordMatch(EphemeralRangeInFlatTree range) {
+ wtf_size_t start_position = range.StartPosition().OffsetInContainerNode();
+
+ if (start_position != 0) {
+ String start_text = range.StartPosition().AnchorNode()->textContent();
+ start_text.Ensure16Bit();
+ wtf_size_t word_start = FindWordStartBoundary(
+ start_text.Characters16(), start_text.length(), start_position);
+ if (word_start != start_position)
+ return false;
+ }
+
+ wtf_size_t end_position = range.EndPosition().OffsetInContainerNode();
+ String end_text = range.EndPosition().AnchorNode()->textContent();
+
+ if (end_position != end_text.length()) {
+ end_text.Ensure16Bit();
+ // We expect end_position to be a word boundary, and FindWordEndBoundary
+ // finds the next word boundary, so start from end_position - 1.
+ wtf_size_t word_end = FindWordEndBoundary(
+ end_text.Characters16(), end_text.length(), end_position - 1);
+ if (word_end != end_position)
+ return false;
+ }
+
+ return true;
+}
+
EphemeralRangeInFlatTree FindMatchInRange(String search_text,
PositionInFlatTree search_start,
PositionInFlatTree search_end) {
- const EphemeralRangeInFlatTree search_range(search_start, search_end);
- return FindBuffer::FindMatchInRange(search_range, search_text,
- kCaseInsensitive);
+ while (search_start < search_end) {
+ const EphemeralRangeInFlatTree search_range(search_start, search_end);
+ EphemeralRangeInFlatTree potential_match = FindBuffer::FindMatchInRange(
+ search_range, search_text, kCaseInsensitive);
+
+ if (potential_match.IsNull() || IsWholeWordMatch(potential_match))
+ return potential_match;
+
+ search_start = potential_match.EndPosition();
+ }
+
+ return EphemeralRangeInFlatTree();
}
PositionInFlatTree NextTextPosition(PositionInFlatTree position,
@@ -58,12 +101,18 @@ EphemeralRangeInFlatTree FindImmediateMatch(String search_text,
FindBuffer buffer(EphemeralRangeInFlatTree(search_start, search_end));
+ // TODO(nburris): FindBuffer will search the rest of the document for a match,
+ // but we only need to check for an immediate match, so we should stop
+ // searching if there's no immediate match.
std::unique_ptr<FindBuffer::Results> match_results =
buffer.FindMatches(search_text, kCaseInsensitive);
if (!match_results->IsEmpty() && match_results->front().start == 0u) {
- FindBuffer::BufferMatchResult match = match_results->front();
- return buffer.RangeFromBufferIndex(match.start, match.start + match.length);
+ FindBuffer::BufferMatchResult buffer_match = match_results->front();
+ EphemeralRangeInFlatTree match = buffer.RangeFromBufferIndex(
+ buffer_match.start, buffer_match.start + buffer_match.length);
+ if (IsWholeWordMatch(match))
+ return match;
}
return EphemeralRangeInFlatTree();
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
index bcc2ecc22d6..d0f16a67b87 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
@@ -10,7 +10,7 @@
namespace blink {
-// TextFragmentSelector represents a single targetText=... selector of a
+// TextFragmentSelector represents a single text=... selector of a
// TextFragmentAnchor, parsed into its components.
class CORE_EXPORT TextFragmentSelector final {
public:
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
index 046accf2a5b..6731310cfe6 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
@@ -15,7 +15,6 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/overscroll_controller.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/viewport_scroll_callback.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -199,20 +198,6 @@ Document* TopDocumentRootScrollerController::TopDocument() const {
return main_local_frame ? main_local_frame->GetDocument() : nullptr;
}
-void TopDocumentRootScrollerController::DidUpdateCompositing(
- const LocalFrameView& frame_view) {
- if (!page_)
- return;
-
- // The only other way to get here is from a local root OOPIF but we ignore
- // that case since the global root can't cross remote frames today.
- if (!frame_view.GetFrame().IsMainFrame())
- return;
-
- // Let the compositor-side counterpart know about this change.
- page_->GetChromeClient().RegisterViewportLayers();
-}
-
void TopDocumentRootScrollerController::DidDisposeScrollableArea(
ScrollableArea& area) {
if (!TopDocument() || !TopDocument()->View())
@@ -255,30 +240,6 @@ bool TopDocumentRootScrollerController::IsViewportScrollCallback(
return callback == viewport_apply_scroll_.Get();
}
-GraphicsLayer* TopDocumentRootScrollerController::RootScrollerLayer() const {
- ScrollableArea* area = GetScrollableArea(global_root_scroller_);
-
- if (!area)
- return nullptr;
-
- GraphicsLayer* graphics_layer = area->LayerForScrolling();
-
- // TODO(bokan): We should assert graphicsLayer here and
- // RootScrollerController should do whatever needs to happen to ensure
- // the root scroller gets composited.
-
- return graphics_layer;
-}
-
-GraphicsLayer* TopDocumentRootScrollerController::RootContainerLayer() const {
- ScrollableArea* area = GetScrollableArea(global_root_scroller_);
- return area ? area->LayerForContainer() : nullptr;
-}
-
-PaintLayer* TopDocumentRootScrollerController::RootScrollerPaintLayer() const {
- return root_scroller_util::PaintLayerForRootScroller(global_root_scroller_);
-}
-
Node* TopDocumentRootScrollerController::GlobalRootScroller() const {
return global_root_scroller_.Get();
}
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h
index aacb2b9127b..917d52f2c08 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h
@@ -15,8 +15,6 @@ namespace blink {
class LocalFrameView;
class Node;
class Page;
-class GraphicsLayer;
-class PaintLayer;
class RootFrameViewport;
class ScrollStateCallback;
class ScrollableArea;
@@ -35,10 +33,6 @@ class CORE_EXPORT TopDocumentRootScrollerController
void Trace(blink::Visitor*);
- // This class needs to be informed of changes to compositing so that it can
- // update the compositor when the effective root scroller changes.
- void DidUpdateCompositing(const LocalFrameView&);
-
// PaintLayerScrollableAreas need to notify this class when they're being
// disposed so that we can remove them as the root scroller.
void DidDisposeScrollableArea(ScrollableArea&);
@@ -55,14 +49,6 @@ class CORE_EXPORT TopDocumentRootScrollerController
// apply scroll. crbug.com/623079.
bool IsViewportScrollCallback(const ScrollStateCallback*) const;
- // Returns the GraphicsLayer for the global root scroller.
- GraphicsLayer* RootScrollerLayer() const;
-
- // Returns the GraphicsLayer for the global root scroll container.
- GraphicsLayer* RootContainerLayer() const;
-
- PaintLayer* RootScrollerPaintLayer() const;
-
// Returns the Node that's the global root scroller. See README.md for the
// difference between this and the root scroller types in
// RootScrollerController.
diff --git a/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc b/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
index 629825c5500..e711cfd709f 100644
--- a/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
@@ -75,7 +75,7 @@ TEST_F(SlotScopedTraversalTest, emptySlot) {
Element* host = GetDocument().QuerySelector("#host");
ShadowRoot* shadow_root = host->OpenShadowRoot();
- auto* slot = ToHTMLSlotElement(shadow_root->QuerySelector("slot"));
+ auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
EXPECT_EQ(nullptr, SlotScopedTraversal::FirstAssignedToSlot(*slot));
EXPECT_EQ(nullptr, SlotScopedTraversal::LastAssignedToSlot(*slot));
@@ -109,7 +109,7 @@ TEST_F(SlotScopedTraversalTest, simpleSlot) {
Element* inner1 = GetDocument().QuerySelector("#inner1");
Element* inner2 = GetDocument().QuerySelector("#inner2");
ShadowRoot* shadow_root = host->OpenShadowRoot();
- auto* slot = ToHTMLSlotElement(shadow_root->QuerySelector("slot"));
+ auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
EXPECT_EQ(inner1, SlotScopedTraversal::FirstAssignedToSlot(*slot));
EXPECT_EQ(inner2, SlotScopedTraversal::LastAssignedToSlot(*slot));
@@ -162,9 +162,9 @@ TEST_F(SlotScopedTraversalTest, multipleSlots) {
slot_element[2] = shadow_root->QuerySelector("#unnamedslot");
HTMLSlotElement* slot[3];
- slot[0] = ToHTMLSlotElement(slot_element[0]);
- slot[1] = ToHTMLSlotElement(slot_element[1]);
- slot[2] = ToHTMLSlotElement(slot_element[2]);
+ slot[0] = To<HTMLSlotElement>(slot_element[0]);
+ slot[1] = To<HTMLSlotElement>(slot_element[1]);
+ slot[2] = To<HTMLSlotElement>(slot_element[2]);
{
// <slot id='slot0'> : Expected assigned nodes: inner0, inner4
@@ -234,7 +234,7 @@ TEST_F(SlotScopedTraversalTest, shadowHostAtTopLevel) {
AttachOpenShadowRoot(*inner[i], shadow_html);
ShadowRoot* shadow_root = host->OpenShadowRoot();
- auto* slot = ToHTMLSlotElement(shadow_root->QuerySelector("slot"));
+ auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
switch (i) {
case 0: {
@@ -340,7 +340,7 @@ TEST_F(SlotScopedTraversalTest, shadowHostAtSecondLevel) {
}
ShadowRoot* shadow_root = host->OpenShadowRoot();
- auto* slot = ToHTMLSlotElement(shadow_root->QuerySelector("slot"));
+ auto* slot = To<HTMLSlotElement>(shadow_root->QuerySelector("slot"));
switch (i) {
case 0: {
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
index 4e3d023445f..424fc6a8a9f 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
@@ -254,8 +254,8 @@ bool ScrollInDirection(Node* container, SpatialNavigationDirection direction) {
int dx = 0;
int dy = 0;
- int pixels_per_line_step = ScrollableArea::PixelsPerLineStep(
- container->GetDocument().GetFrame()->View()->GetChromeClient());
+ int pixels_per_line_step =
+ ScrollableArea::PixelsPerLineStep(container->GetDocument().GetFrame());
switch (direction) {
case SpatialNavigationDirection::kLeft:
dx = -pixels_per_line_step;
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
index 4315f0eba48..57746336350 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -96,7 +96,6 @@ static void ConsiderForBestCandidate(SpatialNavigationDirection direction,
if (distance == kMaxDistance)
return;
-
if (distance < *best_distance && IsUnobscured(candidate)) {
*best_candidate = candidate;
*best_distance = distance;
@@ -139,12 +138,20 @@ bool SpatialNavigationController::HandleArrowKeyboardEvent(
if (direction == SpatialNavigationDirection::kNone)
return false;
+ // If the focus has already moved by a previous handler, return false.
+ const Element* focused = GetFocusedElement();
+ if (focused && focused != event->target()) {
+ // SpatNav does not need to handle this arrow key because
+ // the webpage had a key-handler that already moved focus.
+ return false;
+ }
+
// In focusless mode, the user must explicitly move focus in and out of an
// editable so we can avoid advancing interest and we should swallow the
// event. This prevents double-handling actions for things like search box
// suggestions.
if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) {
- if (Element* focused = GetFocusedElement()) {
+ if (focused) {
if (HasEditableStyle(*focused) || focused->IsTextControl())
return true;
}
@@ -466,8 +473,11 @@ void SpatialNavigationController::MoveInterestTo(Node* next_node) {
}
void SpatialNavigationController::DispatchMouseMoveAt(Element* element) {
- FloatPoint event_position =
- element ? RectInViewport(*element).Location() : FloatPoint(-1, -1);
+ FloatPoint event_position(-1, -1);
+ if (element) {
+ event_position = RectInViewport(*element).Location();
+ event_position.Move(1, 1);
+ }
// TODO(bokan): Can we get better screen coordinates?
FloatPoint event_position_screen = event_position;
@@ -639,7 +649,7 @@ SpatialNavigationController::GetSpatialNavigationHost() {
if (!frame)
return spatial_navigation_host_;
- frame->GetInterfaceProvider().GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
spatial_navigation_host_.BindNewPipeAndPassReceiver(
frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
}
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
index aa546d7feb7..3b90ab1e181 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_controller.h
@@ -24,8 +24,8 @@ struct PhysicalRect;
// Navigation is used to move and interact with a page in a purely directional
// way, e.g. keyboard arrows. We use the term "interest" to specify which
// element the user is currently on.
-class CORE_EXPORT SpatialNavigationController
- : public GarbageCollectedFinalized<SpatialNavigationController> {
+class CORE_EXPORT SpatialNavigationController final
+ : public GarbageCollected<SpatialNavigationController> {
public:
explicit SpatialNavigationController(Page& page);
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
index 88ac29f3a2b..b80b5d3cbce 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation_test.cc
@@ -771,8 +771,7 @@ TEST_F(FocuslessSpatialNavigationSimTest, OpenSelectPopup) {
)HTML");
Compositor().BeginFrame();
- HTMLSelectElement* select =
- ToHTMLSelectElement(GetDocument().getElementById("target"));
+ auto* select = To<HTMLSelectElement>(GetDocument().getElementById("target"));
SimulateKeyPress(ui::DomKey::ARROW_DOWN);
SpatialNavigationController& spat_nav_controller =
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 dfd2d508329..bd943ba6cb6 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -518,10 +518,11 @@ bool FindBestContextMenuCandidate(Node*& target_node,
subtargets, touch_adjustment::HybridDistanceFunction);
}
-LayoutSize GetHitTestRectForAdjustment(const LocalFrame& frame,
+LayoutSize GetHitTestRectForAdjustment(LocalFrame& frame,
const LayoutSize& touch_area) {
+ ChromeClient& chrome_client = frame.GetChromeClient();
float device_scale_factor =
- frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+ chrome_client.GetScreenInfo(frame).device_scale_factor;
// Check if zoom-for-dsf is enabled. If not, touch_area is in dip, so we don't
// need to convert max_size_in_dip to physical pixel.
if (frame.GetPage()->DeviceScaleFactorDeprecated() != 1)
diff --git a/chromium/third_party/blink/renderer/core/page/touch_adjustment.h b/chromium/third_party/blink/renderer/core/page/touch_adjustment.h
index 8b85a88bbfd..6134ac99b48 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_adjustment.h
+++ b/chromium/third_party/blink/renderer/core/page/touch_adjustment.h
@@ -49,8 +49,7 @@ bool FindBestContextMenuCandidate(Node*& target_node,
// touch_area is in root frame coordinates, which is in physical pixel when
// zoom-for-dsf is enabled, otherwise in dip (when page scale is 1).
CORE_EXPORT LayoutSize
-GetHitTestRectForAdjustment(const LocalFrame& frame,
- const LayoutSize& touch_area);
+GetHitTestRectForAdjustment(LocalFrame& frame, const LayoutSize& touch_area);
struct TouchAdjustmentResult {
uint32_t unique_event_id;
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 47ca38f757c..ff53ce8a2dc 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
@@ -12,15 +12,17 @@ namespace blink {
namespace {
-class MockChromeClient : public RenderingTestChromeClient {
+class FakeChromeClient : public RenderingTestChromeClient {
public:
- MockChromeClient() = default;
+ FakeChromeClient() = default;
void SetDeviceScaleFactor(float device_scale_factor) {
screen_info_.device_scale_factor = device_scale_factor;
}
- WebScreenInfo GetScreenInfo() const override { return screen_info_; }
+ WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+ return screen_info_;
+ }
private:
WebScreenInfo screen_info_;
@@ -32,11 +34,11 @@ class TouchAdjustmentTest : public RenderingTest {
protected:
TouchAdjustmentTest()
: RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
- chrome_client_(MakeGarbageCollected<MockChromeClient>()) {}
+ chrome_client_(MakeGarbageCollected<FakeChromeClient>()) {}
LocalFrame& GetFrame() const { return *GetDocument().GetFrame(); }
- MockChromeClient& GetChromeClient() const override { return *chrome_client_; }
+ FakeChromeClient& GetChromeClient() const override { return *chrome_client_; }
void SetZoomAndScale(float device_scale_factor,
float browser_zoom_factor,
@@ -53,7 +55,7 @@ class TouchAdjustmentTest : public RenderingTest {
const LayoutSize min_touch_area_dip_unscaled = LayoutSize(20, 20);
private:
- Persistent<MockChromeClient> chrome_client_;
+ Persistent<FakeChromeClient> chrome_client_;
float device_scale_factor_;
float page_scale_factor_;
diff --git a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
index 4e9cac17e36..df331109b61 100644
--- a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
@@ -42,7 +42,7 @@ class FrameOverlay;
class ValidationMessageOverlayDelegate;
class CORE_EXPORT ValidationMessageClientImpl final
- : public GarbageCollectedFinalized<ValidationMessageClientImpl>,
+ : public GarbageCollected<ValidationMessageClientImpl>,
public ValidationMessageClient,
private PopupOpeningObserver {
USING_GARBAGE_COLLECTED_MIXIN(ValidationMessageClientImpl);
diff --git a/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
index 9aac603cf0d..45dac9f4759 100644
--- a/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -40,15 +40,18 @@ class ValidationMessageChromeClient : public EmptyChromeClient {
EmptyChromeClient::Trace(visitor);
}
- void ScheduleAnimation(const LocalFrameView*) override {
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta delay = base::TimeDelta()) override {
// Need to pass LocalFrameView for the anchor element because the Frame for
// this overlay doesn't have an associated WebFrameWidget, which schedules
// animation.
- main_chrome_client_->ScheduleAnimation(anchor_view_);
+ main_chrome_client_->ScheduleAnimation(anchor_view_, delay);
}
- float WindowToViewportScalar(const float scalar_value) const override {
- return main_chrome_client_->WindowToViewportScalar(scalar_value);
+ float WindowToViewportScalar(LocalFrame* local_frame,
+ const float scalar_value) const override {
+ return main_chrome_client_->WindowToViewportScalar(local_frame,
+ scalar_value);
}
private:
diff --git a/chromium/third_party/blink/renderer/core/paint/BUILD.gn b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
index 1ca6694862b..335341d4569 100644
--- a/chromium/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
@@ -5,7 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("paint") {
- split_count = 2
sources = [
"applied_decoration_painter.cc",
"applied_decoration_painter.h",
@@ -64,6 +63,8 @@ blink_core_sources("paint") {
"compositing/paint_layer_compositor.h",
"css_mask_painter.cc",
"css_mask_painter.h",
+ "custom_scrollbar_theme.cc",
+ "custom_scrollbar_theme.h",
"decoration_info.h",
"details_marker_painter.cc",
"details_marker_painter.h",
@@ -199,8 +200,6 @@ blink_core_sources("paint") {
"scoped_svg_paint_state.h",
"scrollable_area_painter.cc",
"scrollable_area_painter.h",
- "scrollbar_painter.cc",
- "scrollbar_painter.h",
"selection_painting_utils.cc",
"selection_painting_utils.h",
"svg_container_painter.cc",
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 d1ba25c6d5e..284b3eaa1cd 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
@@ -69,9 +69,10 @@ void BlockPainter::Paint(const PaintInfo& paint_info) {
layout_block_.PaintObject(local_paint_info, paint_offset);
} else if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly &&
- // For now all scrollers with overlay scrollbars are self-painting
- // layers, so we don't need to traverse descendants here.
- original_phase != PaintPhase::kOverlayScrollbars) {
+ // For now all scrollers with overlay overflow controls are
+ // self-painting layers, so we don't need to traverse descendants
+ // here.
+ original_phase != PaintPhase::kOverlayOverflowControls) {
ScopedBoxContentsPaintState contents_paint_state(paint_state,
layout_block_);
layout_block_.PaintObject(contents_paint_state.GetPaintInfo(),
@@ -211,19 +212,16 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_block_.GetDocument())) {
- if (paint_info.phase == PaintPhase::kForeground) {
- scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
- layout_block_, paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- }
+ if (paint_info.phase == PaintPhase::kForeground) {
+ scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
+ layout_block_,
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
- // If we're *printing* the foreground, paint the URL.
- if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting()) {
- ObjectPainter(layout_block_)
- .AddPDFURLRectIfNeeded(paint_info, paint_offset);
+ // If we're *printing or creating a paint preview of* the foreground, paint
+ // the URL.
+ if (paint_phase == PaintPhase::kForeground &&
+ paint_info.ShouldAddUrlMetadata()) {
+ ObjectPainter(layout_block_).AddURLRectIfNeeded(paint_info, paint_offset);
}
// If we're painting our background (either 1. kBlockBackground - background
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
index 645f5be924a..a5328040310 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
@@ -98,30 +98,26 @@ void BoxPainter::PaintBoxDecorationBackground(
RecordHitTestData(paint_info, paint_rect, *background_client);
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- bool needs_scroll_hit_test = true;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
- // display items for composited scrollers because these display items are
- // only used to create non-fast scrollable regions for non-composited
- // scrollers. With CompositeAfterPaint, we always paint the scroll hit
- // test display items but ignore the non-fast region if the scroll was
- // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
- if (layout_box_.HasLayer() &&
- layout_box_.Layer()->GetCompositedLayerMapping() &&
- layout_box_.Layer()
- ->GetCompositedLayerMapping()
- ->HasScrollingLayer()) {
- needs_scroll_hit_test = false;
- }
+ bool needs_scroll_hit_test = true;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
+ // display items for composited scrollers because these display items are
+ // only used to create non-fast scrollable regions for non-composited
+ // scrollers. With CompositeAfterPaint, we always paint the scroll hit
+ // test display items but ignore the non-fast region if the scroll was
+ // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
+ if (layout_box_.HasLayer() &&
+ layout_box_.Layer()->GetCompositedLayerMapping() &&
+ layout_box_.Layer()->GetCompositedLayerMapping()->HasScrollingLayer()) {
+ needs_scroll_hit_test = false;
}
-
- // Record the scroll hit test after the non-scrolling background so
- // background squashing is not affected. Hit test order would be equivalent
- // if this were immediately before the non-scrolling background.
- if (!painting_scrolling_background && needs_scroll_hit_test)
- RecordScrollHitTestData(paint_info, *background_client);
}
+
+ // Record the scroll hit test after the non-scrolling background so
+ // background squashing is not affected. Hit test order would be equivalent
+ // if this were immediately before the non-scrolling background.
+ if (!painting_scrolling_background && needs_scroll_hit_test)
+ RecordScrollHitTestData(paint_info, *background_client);
}
bool BoxPainter::BackgroundIsKnownToBeOpaque(const PaintInfo& paint_info) {
@@ -317,8 +313,6 @@ void BoxPainter::RecordHitTestData(const PaintInfo& paint_info,
void BoxPainter::RecordScrollHitTestData(
const PaintInfo& paint_info,
const DisplayItemClient& background_client) {
- DCHECK(RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
-
// Hit test display items are only needed for compositing. This flag is used
// for for printing and drag images which do not need hit testing.
if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
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 ccf832a0888..597dbee509e 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
@@ -6,6 +6,7 @@
#include "base/optional.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/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
@@ -383,7 +384,8 @@ void DrawTiledBackground(GraphicsContext& context,
const FloatPoint& phase,
const FloatSize& tile_size,
SkBlendMode op,
- const FloatSize& repeat_spacing) {
+ const FloatSize& repeat_spacing,
+ bool has_filter_property) {
DCHECK(!tile_size.IsEmpty());
// Use the intrinsic size of the image if it has one, otherwise force the
@@ -418,7 +420,8 @@ void DrawTiledBackground(GraphicsContext& context,
// calculations up the stack.
visible_src_rect = FloatRect(RoundedIntRect(visible_src_rect));
context.DrawImage(image, Image::kSyncDecode, snapped_paint_rect,
- &visible_src_rect, op, kDoNotRespectImageOrientation);
+ &visible_src_rect, has_filter_property, op,
+ kDoNotRespectImageOrientation);
return;
}
@@ -555,20 +558,17 @@ inline bool PaintFastBottomLayer(Node* node,
// 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,
- composite_op);
-
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- if (info.image && info.image->IsImageResource()) {
- PaintTimingDetector::NotifyBackgroundImagePaint(
- node, image, To<StyleFetchedImage>(info.image.Get()),
- paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- }
+ context.DrawImageRRect(
+ image, Image::kSyncDecode, image_border, src_rect,
+ node && node->ComputedStyleRef().HasFilterInducingProperty(),
+ composite_op);
+
+ if (info.image && info.image->IsImageResource()) {
+ PaintTimingDetector::NotifyBackgroundImagePaint(
+ node, image, To<StyleFetchedImage>(info.image.Get()),
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
- if (node &&
- RuntimeEnabledFeatures::ElementTimingEnabled(&node->GetDocument()) &&
- info.image && info.image->IsImageResource()) {
+ if (node && info.image && info.image->IsImageResource()) {
LocalDOMWindow* window = node->GetDocument().domWindow();
DCHECK(window);
ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
@@ -686,21 +686,18 @@ void PaintFillLayerBackground(GraphicsContext& context,
inspector_paint_image_event::Data(
node, *info.image, FloatRect(image->Rect()),
FloatRect(scrolled_paint_rect)));
- DrawTiledBackground(context, image,
- FloatSize(geometry.UnsnappedDestRect().size),
- FloatRect(geometry.SnappedDestRect()), geometry.Phase(),
- FloatSize(geometry.TileSize()), composite_op,
- FloatSize(geometry.SpaceSize()));
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- if (info.image && info.image->IsImageResource()) {
- PaintTimingDetector::NotifyBackgroundImagePaint(
- node, image, To<StyleFetchedImage>(info.image.Get()),
- context.GetPaintController().CurrentPaintChunkProperties());
- }
+ DrawTiledBackground(
+ context, image, FloatSize(geometry.UnsnappedDestRect().size),
+ FloatRect(geometry.SnappedDestRect()), geometry.Phase(),
+ FloatSize(geometry.TileSize()), composite_op,
+ FloatSize(geometry.SpaceSize()),
+ node && node->ComputedStyleRef().HasFilterInducingProperty());
+ if (info.image && info.image->IsImageResource()) {
+ PaintTimingDetector::NotifyBackgroundImagePaint(
+ node, image, To<StyleFetchedImage>(info.image.Get()),
+ context.GetPaintController().CurrentPaintChunkProperties());
}
- if (node &&
- RuntimeEnabledFeatures::ElementTimingEnabled(&node->GetDocument()) &&
- info.image && info.image->IsImageResource()) {
+ if (node && info.image && info.image->IsImageResource()) {
LocalDOMWindow* window = node->GetDocument().domWindow();
DCHECK(window);
ImageElementTiming::From(*window).NotifyBackgroundImagePainted(
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_rects_cache.h b/chromium/third_party/blink/renderer/core/paint/clip_rects_cache.h
index 833c66d27e4..acc536bfbaf 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_rects_cache.h
+++ b/chromium/third_party/blink/renderer/core/paint/clip_rects_cache.h
@@ -16,16 +16,17 @@ namespace blink {
class PaintLayer;
enum ClipRectsCacheSlot {
- // Relative to the LayoutView's layer. Used for compositing overlap testing.
+ // Relative to the LayoutView's layer. Used for pre-CompositeAfterPaint
+ // compositing overlap testing.
// TODO(bokan): Overlap testing currently ignores the clip on the root layer.
// Overlap testing has some bugs when inside non-root layers which extend to
// the root layer when root-layer-scrolling is turned on unless we do this.
// crbug.com/783532.
kAbsoluteClipRectsIgnoringViewportClip,
- // Relative to painting ancestor. Used for SPv1 compositing.
+ // Relative to painting ancestor. Used for pre-CompositeAfterPaint
+ // compositing.
kPaintingClipRects,
- kPaintingClipRectsIgnoringOverflowClip,
kNumberOfClipRectsCacheSlots,
kUncachedClipRects,
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 7e5988ae91c..a5be48bf627 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
@@ -28,6 +28,7 @@
#include <memory>
#include "cc/layers/picture_layer.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/accessibility/apply_dark_mode.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -217,7 +218,6 @@ CompositedLayerMapping::~CompositedLayerMapping() {
}
UpdateOverflowControlsLayers(false, false, false);
- UpdateChildTransformLayer(false);
UpdateForegroundLayer(false);
UpdateMaskLayer(false);
UpdateScrollingLayers(false);
@@ -246,10 +246,6 @@ void CompositedLayerMapping::CreatePrimaryGraphicsLayer() {
owning_layer_.GetSquashingDisallowedReasons());
graphics_layer_->SetHitTestable(true);
- UpdateOpacity(GetLayoutObject().StyleRef());
- UpdateTransform(GetLayoutObject().StyleRef());
- UpdateLayerBlendMode(GetLayoutObject().StyleRef());
- UpdateIsRootForIsolatedGroup();
}
void CompositedLayerMapping::DestroyGraphicsLayers() {
@@ -258,47 +254,12 @@ void CompositedLayerMapping::DestroyGraphicsLayers() {
graphics_layer_ = nullptr;
foreground_layer_ = nullptr;
- child_transform_layer_ = nullptr;
mask_layer_ = nullptr;
scrolling_layer_ = nullptr;
scrolling_contents_layer_ = nullptr;
}
-void CompositedLayerMapping::UpdateOpacity(const ComputedStyle& style) {
- graphics_layer_->SetOpacity(CompositingOpacity(style.Opacity()));
-}
-
-void CompositedLayerMapping::UpdateTransform(const ComputedStyle& style) {
- // FIXME: This could use m_owningLayer.transform(), but that currently has
- // transform-origin baked into it, and we don't want that.
- TransformationMatrix t;
- if (owning_layer_.HasTransformRelatedProperty()) {
- style.ApplyTransform(
- t, LayoutSize(ToLayoutBox(GetLayoutObject()).PixelSnappedSize()),
- ComputedStyle::kExcludeTransformOrigin,
- ComputedStyle::kIncludeMotionPath,
- ComputedStyle::kIncludeIndependentTransformProperties);
- MakeMatrixRenderable(t, Compositor()->HasAcceleratedCompositing());
- }
-
- graphics_layer_->SetTransform(t);
-}
-
-void CompositedLayerMapping::UpdateLayerBlendMode(const ComputedStyle& style) {
- SetBlendMode(style.GetBlendMode());
-}
-
-void CompositedLayerMapping::UpdateIsRootForIsolatedGroup() {
- bool isolate = owning_layer_.ShouldIsolateCompositedDescendants();
-
- // non stacking context layers should never isolate
- DCHECK(owning_layer_.GetLayoutObject().StyleRef().IsStackingContext() ||
- !isolate);
-
- graphics_layer_->SetIsRootForIsolatedGroup(isolate);
-}
-
void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
bool& invalidate_graphics_layer,
bool& invalidate_scrolling_contents_layer) {
@@ -471,13 +432,6 @@ void CompositedLayerMapping::UpdateCompositingReasons() {
owning_layer_.GetSquashingDisallowedReasons());
}
-const PaintLayer* CompositedLayerMapping::CompositedClipParent() const {
- const PaintLayer* clip_parent = owning_layer_.ClipParent();
- return clip_parent ? clip_parent->EnclosingLayerWithCompositedLayerMapping(
- kIncludeSelf)
- : nullptr;
-}
-
bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
const PaintLayer* compositing_container) {
DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
@@ -515,11 +469,6 @@ bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
RequiresScrollCornerLayer()))
layer_config_changed = true;
- bool has_perspective = style.HasPerspective();
- bool needs_child_transform_layer = has_perspective && layout_object.IsBox();
- if (UpdateChildTransformLayer(needs_child_transform_layer))
- layer_config_changed = true;
-
if (UpdateSquashingLayers(!squashed_layers_.IsEmpty()))
layer_config_changed = true;
@@ -846,15 +795,6 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
DocumentLifecycle::kInCompositingUpdate);
- // Set transform property, if it is not animating. We have to do this here
- // because the transform is affected by the layer dimensions.
- if (!GetLayoutObject().StyleRef().IsRunningTransformAnimationOnCompositor())
- UpdateTransform(GetLayoutObject().StyleRef());
-
- // Set opacity, if it is not animating.
- if (!GetLayoutObject().StyleRef().IsRunningOpacityAnimationOnCompositor())
- UpdateOpacity(GetLayoutObject().StyleRef());
-
IntRect local_compositing_bounds;
IntRect relative_compositing_bounds;
PhysicalOffset offset_from_composited_ancestor;
@@ -881,11 +821,7 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
snapped_offset_from_composited_ancestor, squashed_layers_,
layers_needing_paint_invalidation);
- UpdateChildTransformLayerGeometry();
-
UpdateMaskLayerGeometry();
- UpdateTransformGeometry(snapped_offset_from_composited_ancestor,
- relative_compositing_bounds);
// TODO(yigu): Currently the decoration layer uses the same contentSize
// as the foreground layer. There are scenarios where the sizes could be
// different so the decoration layer size should be calculated separately.
@@ -897,8 +833,6 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
owning_layer_.GetScrollableArea()->ScrollsOverflow())
owning_layer_.GetScrollableArea()->PositionOverflowControls();
- UpdateLayerBlendMode(GetLayoutObject().StyleRef());
- UpdateIsRootForIsolatedGroup();
UpdateContentsRect();
UpdateBackgroundColor();
@@ -921,9 +855,6 @@ void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
UpdateContentsOpaque();
UpdateRasterizationPolicy();
UpdateAfterPartResize();
- UpdateRenderingContext();
- UpdateShouldFlattenTransform();
- UpdateChildrenTransform();
UpdateCompositingReasons();
}
@@ -934,8 +865,6 @@ void CompositedLayerMapping::UpdateMainGraphicsLayerGeometry(
GraphicsLayerUpdater::UpdateContext& update_context) {
FloatPoint old_position(graphics_layer_->GetPosition());
IntSize old_size(graphics_layer_->Size());
- // Previous offset of the LayoutObject relative to the main GraphicsLayer.
- IntSize old_object_offset = -graphics_layer_->OffsetFromLayoutObject();
FloatPoint new_position = FloatPoint(relative_compositing_bounds.Location() -
graphics_layer_parent_location);
@@ -951,22 +880,6 @@ void CompositedLayerMapping::UpdateMainGraphicsLayerGeometry(
graphics_layer_->SetPosition(new_position);
graphics_layer_->SetOffsetFromLayoutObject(-new_object_offset);
- IntSize obj_offset_delta = new_object_offset - old_object_offset;
- IntSize position_delta = RoundedIntSize(new_position - old_position);
- // Did our LayoutObject move in relation to the parent CLM's LayoutObject
- // (accounting for their respective offsets from the main GraphicsLayers)?
- IntSize layout_object_delta = position_delta + obj_offset_delta -
- update_context.parent_object_offset_delta;
- if (!layout_object_delta.IsZero()) {
- LocalFrameView* frame_view = layout_object.View()->GetFrameView();
- frame_view->GetLayoutShiftTracker().NotifyCompositedLayerMoved(
- layout_object,
- FloatRect(FloatPoint(), FloatSize(old_size - old_object_offset)),
- FloatRect(FloatPoint(layout_object_delta),
- FloatSize(new_size - new_object_offset)));
- }
- update_context.object_offset_delta = obj_offset_delta;
-
if (old_size != new_size)
graphics_layer_->SetSize(gfx::Size(new_size));
@@ -1064,18 +977,6 @@ void CompositedLayerMapping::UpdateOverflowControlsHostLayerGeometry(
overflow_controls_host_layer_->SetMasksToBounds(true);
}
-void CompositedLayerMapping::UpdateChildTransformLayerGeometry() {
- if (!child_transform_layer_)
- return;
-
- PhysicalRect border_box =
- ToLayoutBox(owning_layer_.GetLayoutObject()).PhysicalBorderBoxRect();
- border_box.Move(ContentOffsetInCompositingLayer());
- child_transform_layer_->SetSize(gfx::Size(border_box.PixelSnappedSize()));
- child_transform_layer_->SetOffsetFromLayoutObject(IntSize());
- child_transform_layer_->SetPosition(FloatPoint(border_box.offset));
-}
-
void CompositedLayerMapping::UpdateMaskLayerGeometry() {
if (!mask_layer_)
return;
@@ -1089,37 +990,6 @@ void CompositedLayerMapping::UpdateMaskLayerGeometry() {
graphics_layer_->OffsetFromLayoutObject());
}
-void CompositedLayerMapping::UpdateTransformGeometry(
- const IntPoint& snapped_offset_from_composited_ancestor,
- const IntRect& relative_compositing_bounds) {
- if (owning_layer_.HasTransformRelatedProperty()) {
- const LayoutRect border_box =
- ToLayoutBox(GetLayoutObject()).BorderBoxRect();
-
- // Get layout bounds in the coords of compositingContainer to match
- // relativeCompositingBounds.
- IntRect layer_bounds = PixelSnappedIntRect(
- PhysicalRect(owning_layer_.SubpixelAccumulation(), border_box.Size()));
- layer_bounds.MoveBy(snapped_offset_from_composited_ancestor);
-
- // Update properties that depend on layer dimensions
- FloatPoint3D transform_origin =
- ComputeTransformOrigin(IntRect(IntPoint(), layer_bounds.Size()));
-
- // |transformOrigin| is in the local space of this layer.
- // layerBounds - relativeCompositingBounds converts to the space of the
- // compositing bounds relative to the composited ancestor. This does not
- // apply to the z direction, since the page is 2D.
- FloatPoint3D composited_transform_origin(
- layer_bounds.X() - relative_compositing_bounds.X() +
- transform_origin.X(),
- layer_bounds.Y() - relative_compositing_bounds.Y() +
- transform_origin.Y(),
- transform_origin.Z());
- graphics_layer_->SetTransformOrigin(composited_transform_origin);
- }
-}
-
void CompositedLayerMapping::UpdateScrollingLayerGeometry(
const IntRect& local_compositing_bounds) {
if (!scrolling_layer_)
@@ -1133,11 +1003,8 @@ void CompositedLayerMapping::UpdateScrollingLayerGeometry(
// When a m_childTransformLayer exists, local content offsets for the
// m_scrollingLayer have already been applied. Otherwise, we apply them here.
IntSize local_content_offset(0, 0);
- if (!child_transform_layer_) {
- local_content_offset =
- RoundedIntPoint(owning_layer_.SubpixelAccumulation()) -
- local_compositing_bounds.Location();
- }
+ local_content_offset = RoundedIntPoint(owning_layer_.SubpixelAccumulation()) -
+ local_compositing_bounds.Location();
scrolling_layer_->SetPosition(
FloatPoint(overflow_clip_rect.Location() + local_content_offset));
@@ -1246,20 +1113,17 @@ void CompositedLayerMapping::UpdateInternalHierarchy() {
}
};
- update_bottom_layer(child_transform_layer_.get());
update_bottom_layer(scrolling_layer_.get());
// Now constructing the subtree for the overflow controls.
bottom_layer = graphics_layer_.get();
- // TODO(pdr): Ensure painting uses the correct GraphicsLayer when root layer
- // scrolls is enabled. crbug.com/638719
if (is_main_frame_layout_view_layer_ &&
!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
bottom_layer = GetLayoutObject()
.GetFrame()
->GetPage()
->GetVisualViewport()
- .ContainerLayer();
+ .RootGraphicsLayer();
}
update_bottom_layer(overflow_controls_host_layer_.get());
if (layer_for_horizontal_scrollbar_) {
@@ -1329,7 +1193,6 @@ void CompositedLayerMapping::UpdateDrawsContentAndPaintsHitTest() {
bool paints_hit_test =
has_painted_content || GetLayoutObject().HasEffectiveAllowedTouchAction();
bool paints_scroll_hit_test =
- RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled() &&
((owning_layer_.GetScrollableArea() &&
owning_layer_.GetScrollableArea()->ScrollsOverflow()) ||
(GetPluginContainer(GetLayoutObject()) &&
@@ -1379,36 +1242,6 @@ void CompositedLayerMapping::UpdateDrawsContentAndPaintsHitTest() {
mask_layer_->SetDrawsContent(true);
}
-void CompositedLayerMapping::UpdateChildrenTransform() {
- if (GraphicsLayer* child_transform_layer = ChildTransformLayer()) {
- child_transform_layer->SetTransform(OwningLayer().PerspectiveTransform());
- child_transform_layer->SetTransformOrigin(
- OwningLayer().PerspectiveOrigin());
- }
-
- UpdateShouldFlattenTransform();
-}
-
-bool CompositedLayerMapping::UpdateChildTransformLayer(
- bool needs_child_transform_layer) {
- bool layers_changed = false;
-
- if (needs_child_transform_layer) {
- if (!child_transform_layer_) {
- child_transform_layer_ =
- CreateGraphicsLayer(CompositingReason::kLayerForPerspective);
- child_transform_layer_->SetDrawsContent(false);
- layers_changed = true;
- }
- } else if (child_transform_layer_) {
- child_transform_layer_->RemoveFromParent();
- child_transform_layer_ = nullptr;
- layers_changed = true;
- }
-
- return layers_changed;
-}
-
bool CompositedLayerMapping::ToggleScrollbarLayerIfNeeded(
std::unique_ptr<GraphicsLayer>& layer,
bool needs_layer,
@@ -1578,10 +1411,6 @@ static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping,
DCHECK(mode);
if (((mode & kApplyToLayersAffectedByPreserve3D) ||
- (mode & kApplyToChildContainingLayers)) &&
- mapping->ChildTransformLayer())
- f(mapping->ChildTransformLayer());
- if (((mode & kApplyToLayersAffectedByPreserve3D) ||
(mode & kApplyToContentLayers) ||
(mode & kApplyToNonScrollingContentLayers)) &&
mapping->MainGraphicsLayer())
@@ -1624,62 +1453,6 @@ static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping,
f(mapping->DecorationOutlineLayer());
}
-struct UpdateRenderingContextFunctor {
- void operator()(GraphicsLayer* layer) const {
- layer->SetRenderingContext(rendering_context);
- }
- int rendering_context;
-};
-
-void CompositedLayerMapping::UpdateRenderingContext() {
- // All layers but the squashing layer (which contains 'alien' content) should
- // be included in this rendering context.
- int id = 0;
-
- // NB, it is illegal at this point to query an ancestor's compositing state.
- // Some compositing reasons depend on the compositing state of ancestors. So
- // if we want a rendering context id for the context root, we cannot ask for
- // the id of its associated cc::Layer now; it may not have one yet. We could
- // do a second pass after doing the compositing updates to get these ids, but
- // this would actually be harmful. We do not want to attach any semantic
- // meaning to the context id other than the fact that they group a number of
- // layers together for the sake of 3d sorting. So instead we will ask the
- // compositor to vend us an arbitrary, but consistent id.
- if (PaintLayer* root = owning_layer_.RenderingContextRoot()) {
- if (Node* node = root->GetLayoutObject().GetNode())
- id = static_cast<int>(PtrHash<Node>::GetHash(node));
- }
-
- UpdateRenderingContextFunctor functor = {id};
- ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(
- this, functor, kApplyToAllGraphicsLayers);
-}
-
-void CompositedLayerMapping::UpdateShouldFlattenTransform() {
- // TODO(trchen): Simplify logic here.
- //
- // The code here is equivalent to applying kApplyToLayersAffectedByPreserve3D
- // layer with the computed ShouldPreserve3D() value, then disable flattening
- // on kApplyToChildContainingLayers layers if the current layer has
- // perspective transform, then again disable flattening on main layer and
- // scrolling layer if we have scrolling layer. See crbug.com/521768.
- //
- // If we toggle flattening back and forth as said above, it will result in
- // unnecessary redrawing because the compositor doesn't have delayed
- // invalidation for this flag. See crbug.com/783614.
- bool is_flat = !owning_layer_.ShouldPreserve3D();
-
- if (GraphicsLayer* layer = ChildTransformLayer())
- layer->SetShouldFlattenTransform(false);
- if (GraphicsLayer* layer = ScrollingLayer())
- layer->SetShouldFlattenTransform(false);
- graphics_layer_->SetShouldFlattenTransform(is_flat && !HasScrollingLayer());
- if (GraphicsLayer* layer = ScrollingContentsLayer())
- layer->SetShouldFlattenTransform(is_flat && !HasChildTransformLayer());
- if (GraphicsLayer* layer = ForegroundLayer())
- layer->SetShouldFlattenTransform(is_flat);
-}
-
struct AnimatingData {
STACK_ALLOCATED();
@@ -1748,11 +1521,11 @@ bool CompositedLayerMapping::UpdateMaskLayer(bool needs_mask_layer) {
mask_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForMask);
mask_layer_->SetPaintingPhase(kGraphicsLayerPaintMask);
CompositorElementId element_id = CompositorElementIdFromUniqueObjectId(
- owning_layer_.GetLayoutObject().UniqueId(),
+ GetLayoutObject().UniqueId(),
CompositorElementIdNamespace::kEffectMask);
mask_layer_->SetElementId(element_id);
- mask_layer_->CcLayer()->SetLayerMaskType(
- cc::Layer::LayerMaskType::SINGLE_TEXTURE_MASK);
+ if (GetLayoutObject().HasBackdropFilter())
+ mask_layer_->CcLayer()->SetIsBackdropFilterMask(true);
layer_changed = true;
}
} else if (mask_layer_) {
@@ -1832,7 +1605,6 @@ bool CompositedLayerMapping::UpdateSquashingLayers(
if (!squashing_containment_layer_) {
squashing_containment_layer_ =
CreateGraphicsLayer(CompositingReason::kLayerForSquashingContainer);
- squashing_containment_layer_->SetShouldFlattenTransform(false);
layers_changed = true;
}
DCHECK(squashing_layer_);
@@ -1872,34 +1644,6 @@ CompositedLayerMapping::PaintingPhaseForPrimaryLayer() const {
return static_cast<GraphicsLayerPaintingPhase>(phase);
}
-float CompositedLayerMapping::CompositingOpacity(
- float layout_object_opacity) const {
- float final_opacity = layout_object_opacity;
-
- for (PaintLayer* curr = owning_layer_.Parent(); curr; curr = curr->Parent()) {
- // We only care about parents that are stacking contexts.
- // Recall that opacity creates stacking context.
- if (!curr->GetLayoutObject().StyleRef().IsStackingContext())
- continue;
-
- // If we found a composited layer, regardless of whether it actually
- // paints into it, we want to compute opacity relative to it. So we can
- // break here.
- //
- // FIXME: with grouped backings, a composited descendant will have to
- // continue past the grouped (squashed) layers that its parents may
- // contribute to. This whole confusion can be avoided by specifying
- // explicitly the composited ancestor where we would stop accumulating
- // opacity.
- if (curr->GetCompositingState() == kPaintsIntoOwnBacking)
- break;
-
- final_opacity *= curr->GetLayoutObject().StyleRef().Opacity();
- }
-
- return final_opacity;
-}
-
Color CompositedLayerMapping::LayoutObjectBackgroundColor() const {
const auto& object = GetLayoutObject();
auto background_color = object.ResolveColor(GetCSSPropertyBackgroundColor());
@@ -2010,6 +1754,10 @@ bool CompositedLayerMapping::ContainsPaintedContent() const {
// compositing saves a backing store.
bool CompositedLayerMapping::IsDirectlyCompositedImage() const {
DCHECK(GetLayoutObject().IsImage());
+
+ if (base::FeatureList::IsEnabled(features::kDisableDirectlyCompositedImages))
+ return false;
+
LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());
if (owning_layer_.HasBoxDecorationsOrBackground() ||
@@ -2120,7 +1868,7 @@ PhysicalRect CompositedLayerMapping::ContentsBox() const {
}
bool CompositedLayerMapping::NeedsToReparentOverflowControls() const {
- return owning_layer_.NeedsReorderOverlayScrollbars();
+ return owning_layer_.NeedsReorderOverlayOverflowControls();
}
GraphicsLayer* CompositedLayerMapping::DetachLayerForOverflowControls() {
@@ -2140,9 +1888,6 @@ GraphicsLayer* CompositedLayerMapping::ParentForSublayers() const {
if (scrolling_contents_layer_)
return scrolling_contents_layer_.get();
- if (child_transform_layer_)
- return child_transform_layer_.get();
-
return graphics_layer_.get();
}
@@ -2172,10 +1917,6 @@ GraphicsLayer* CompositedLayerMapping::ChildForSuperlayers() const {
return graphics_layer_.get();
}
-void CompositedLayerMapping::SetBlendMode(BlendMode blend_mode) {
- graphics_layer_->SetBlendMode(blend_mode);
-}
-
GraphicsLayerUpdater::UpdateType CompositedLayerMapping::UpdateTypeForChildren(
GraphicsLayerUpdater::UpdateType update_type) const {
if (pending_update_scope_ >= kGraphicsLayerUpdateSubtree)
@@ -2677,7 +2418,7 @@ void CompositedLayerMapping::SetOverlayScrollbarsHidden(bool hidden) {
void CompositedLayerMapping::GraphicsLayersDidChange() {
LocalFrameView* frame_view = GetLayoutObject().GetFrameView();
DCHECK(frame_view);
- frame_view->GraphicsLayersDidChange();
+ frame_view->SetForeignLayerListNeedsUpdate();
}
bool CompositedLayerMapping::PaintBlockedByDisplayLockIncludingAncestors(
@@ -2860,8 +2601,6 @@ String CompositedLayerMapping::DebugName(
")";
} else if (graphics_layer == foreground_layer_.get()) {
name = owning_layer_.DebugName() + " (foreground) Layer";
- } else if (graphics_layer == child_transform_layer_.get()) {
- name = "Child Transform Layer";
} else if (graphics_layer == mask_layer_.get()) {
name = "Mask Layer";
} else if (graphics_layer == layer_for_horizontal_scrollbar_.get()) {
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index f458e8b383c..40e892588b4 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -134,11 +134,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
GraphicsLayer* ChildForSuperlayers() const;
void SetSublayers(const GraphicsLayerVector&);
- bool HasChildTransformLayer() const { return child_transform_layer_.get(); }
- GraphicsLayer* ChildTransformLayer() const {
- return child_transform_layer_.get();
- }
-
GraphicsLayer* SquashingContainmentLayer() const {
return squashing_containment_layer_.get();
}
@@ -173,8 +168,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
void FinishAccumulatingSquashingLayers(
wtf_size_t next_squashed_layer_index,
Vector<PaintLayer*>& layers_needing_paint_invalidation);
- void UpdateRenderingContext();
- void UpdateShouldFlattenTransform();
void UpdateElementId();
// GraphicsLayerClient interface
@@ -228,8 +221,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
// We may similarly need to reattach the layer for outlines and decorations.
GraphicsLayer* DetachLayerForDecorationOutline();
- void UpdateBackdropFilters();
-
void SetBlendMode(BlendMode);
bool NeedsGraphicsLayerUpdate() {
@@ -266,8 +257,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const LayoutObject*,
unsigned max_squashed_layer_index);
- void UpdateScrollingBlockSelection();
-
// Returns whether an adjustment happend.
bool AdjustForCompositedScrolling(const GraphicsLayer*,
IntSize& offset) const;
@@ -334,9 +323,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
IntPoint graphics_layer_parent_location);
void UpdateChildTransformLayerGeometry();
void UpdateMaskLayerGeometry();
- void UpdateTransformGeometry(
- const IntPoint& snapped_offset_from_composited_ancestor,
- const IntRect& relative_compositing_bounds);
void UpdateForegroundLayerGeometry();
void UpdateDecorationOutlineLayerGeometry(
const IntSize& relative_compositing_bounds_size);
@@ -361,7 +347,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
void UpdateInternalHierarchy();
void UpdatePaintingPhases();
- bool UpdateChildTransformLayer(bool needs_child_transform_layer);
bool UpdateOverflowControlsLayers(bool needs_horizontal_scrollbar_layer,
bool needs_vertical_scrollbar_layer,
bool needs_scroll_corner_layer);
@@ -374,9 +359,7 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
bool UpdateScrollingLayers(bool scrolling_layers);
bool UpdateSquashingLayers(bool needs_squashing_layers);
void UpdateDrawsContentAndPaintsHitTest();
- void UpdateChildrenTransform();
void UpdateCompositedBounds();
- void UpdateSnapContainerData();
// Also sets subpixelAccumulation on the layer.
void ComputeBoundsOfOwningLayer(
@@ -391,12 +374,7 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
// Result is transform origin in pixels.
FloatPoint3D ComputeTransformOrigin(const IntRect& border_box) const;
- void UpdateOpacity(const ComputedStyle&);
void UpdateTransform(const ComputedStyle&);
- void UpdateLayerBlendMode(const ComputedStyle&);
- void UpdateIsRootForIsolatedGroup();
- // Return the opacity value that this layer should use for compositing.
- float CompositingOpacity(float layout_object_opacity) const;
bool PaintsChildren() const;
@@ -432,9 +410,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const Vector<GraphicsLayerPaintInfo>& layers,
GraphicsLayerPaintInfo&);
- const PaintLayer* CompositedClipParent() const;
- void UpdateClipInheritanceAncestor(const PaintLayer* compositing_container);
-
// Clear the groupedMapping entry on the layer at the given index, only if
// that layer does not appear earlier in the set of layers for this object.
bool InvalidateLayerIfNoPrecedingEntry(wtf_size_t);
@@ -448,8 +423,7 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
// looks like this:
//
// + graphics_layer_
- // + child_transform_layer_ [OPTIONAL]
- // | (scrolling_layer_ + scrolling_contents_layer_) [OPTIONAL]
+ // + (scrolling_layer_ + scrolling_contents_layer_) [OPTIONAL]
// | + overflow_controls_host_layer_ [OPTIONAL]
// | + layer_for_vertical_scrollbar_ [OPTIONAL]
// | + layer_for_horizontal_scrollbar_ [OPTIONAL]
@@ -460,9 +434,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
std::unique_ptr<GraphicsLayer> graphics_layer_;
- // Only used if we have perspective.
- std::unique_ptr<GraphicsLayer> child_transform_layer_;
-
// Only used if the layer is using composited scrolling.
std::unique_ptr<GraphicsLayer> scrolling_layer_;
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 785130b7594..91161e777b5 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
@@ -34,10 +34,6 @@ class CompositedLayerMappingTest : public RenderingTest {
.ComputeInterestRect(graphics_layer, previous_interest_rect);
}
- bool ShouldFlattenTransform(const GraphicsLayer& layer) const {
- return layer.ShouldFlattenTransform();
- }
-
bool InterestRectChangedEnoughToRepaint(const IntRect& previous_interest_rect,
const IntRect& new_interest_rect,
const IntSize& layer_size) {
@@ -520,31 +516,6 @@ TEST_F(CompositedLayerMappingTest, ClippedBigLayer) {
RecomputeInterestRect(paint_layer->GraphicsLayerBacking()));
}
-TEST_F(CompositedLayerMappingTest, ScrollContentsFlattenForScroller) {
- SetBodyInnerHTML(R"HTML(
- <style>div::-webkit-scrollbar{ width: 5px; }</style>
- <div id='scroller' style='width: 100px; height: 100px; overflow:
- scroll; will-change: transform'>
- <div style='width: 1000px; height: 1000px;'>Foo</div>Foo</div>
- )HTML");
-
- UpdateAllLifecyclePhasesForTest();
- Element* element = GetDocument().getElementById("scroller");
- PaintLayer* paint_layer =
- ToLayoutBoxModelObject(element->GetLayoutObject())->Layer();
- CompositedLayerMapping* composited_layer_mapping =
- paint_layer->GetCompositedLayerMapping();
-
- ASSERT_TRUE(composited_layer_mapping);
-
- EXPECT_FALSE(
- ShouldFlattenTransform(*composited_layer_mapping->MainGraphicsLayer()));
- EXPECT_FALSE(
- ShouldFlattenTransform(*composited_layer_mapping->ScrollingLayer()));
- EXPECT_TRUE(ShouldFlattenTransform(
- *composited_layer_mapping->ScrollingContentsLayer()));
-}
-
TEST_F(CompositedLayerMappingTest, InterestRectChangedEnoughToRepaintEmpty) {
IntSize layer_size(1000, 1000);
// Both empty means there is nothing to do.
@@ -1178,89 +1149,6 @@ TEST_F(CompositedLayerMappingTest,
EXPECT_FALSE(mapping->BackgroundPaintsOntoScrollingContentsLayer());
}
-TEST_F(CompositedLayerMappingTest,
- ScrollingLayerWithPerspectivePositionedCorrectly) {
- // Test positioning of a scrolling layer within an offset parent, both with
- // and without perspective.
- //
- // When a box shadow is used, the main graphics layer position is offset by
- // the shadow. The scrolling contents then need to be offset in the other
- // direction to compensate. To make this a little clearer, for the first
- // example here the layer positions are calculated as:
- //
- // graphics_layer_ x = left_pos - shadow_spread + shadow_x_offset
- // = 50 - 10 - 10
- // = 30
- //
- // graphics_layer_ y = top_pos - shadow_spread + shadow_y_offset
- // = 50 - 10 + 0
- // = 40
- //
- // contents x = 50 - graphics_layer_ x = 50 - 30 = 20
- // contents y = 50 - graphics_layer_ y = 50 - 40 = 10
- //
- // The reason that perspective matters is that it affects which 'contents'
- // layer is offset; child_transform_layer_ when using perspective, or
- // scrolling_layer_ when there is no perspective.
-
- SetBodyInnerHTML(R"HTML(
- <div id='scroller' style='position: absolute; top: 50px; left: 50px;
- width: 400px; height: 245px; overflow: auto; will-change: transform;
- box-shadow: -10px 0 0 10px; perspective: 1px;'>
- <div style='position: absolute; top: 50px; bottom: 0; width: 200px;
- height: 200px;'></div>
- </div>
- <div id='scroller2' style='position: absolute; top: 400px; left: 50px;
- width: 400px; height: 245px; overflow: auto; will-change: transform;
- box-shadow: -10px 0 0 10px;'>
- <div style='position: absolute; top: 50px; bottom: 0; width: 200px;
- height: 200px;'></div>
- </div>
- )HTML");
-
- auto* mapping = To<LayoutBlock>(GetLayoutObjectByElementId("scroller"))
- ->Layer()
- ->GetCompositedLayerMapping();
-
- auto* mapping2 = To<LayoutBlock>(GetLayoutObjectByElementId("scroller2"))
- ->Layer()
- ->GetCompositedLayerMapping();
-
- ASSERT_TRUE(mapping);
- ASSERT_TRUE(mapping2);
-
- // The perspective scroller should have a child transform containing the
- // positional offset, and a scrolling layer that has no offset.
-
- GraphicsLayer* scrolling_layer = mapping->ScrollingLayer();
- GraphicsLayer* child_transform_layer = mapping->ChildTransformLayer();
- GraphicsLayer* main_graphics_layer = mapping->MainGraphicsLayer();
-
- ASSERT_TRUE(scrolling_layer);
- ASSERT_TRUE(child_transform_layer);
-
- EXPECT_FLOAT_EQ(30, main_graphics_layer->GetPosition().x());
- EXPECT_FLOAT_EQ(40, main_graphics_layer->GetPosition().y());
- EXPECT_FLOAT_EQ(0, scrolling_layer->GetPosition().x());
- EXPECT_FLOAT_EQ(0, scrolling_layer->GetPosition().y());
- EXPECT_FLOAT_EQ(20, child_transform_layer->GetPosition().x());
- EXPECT_FLOAT_EQ(10, child_transform_layer->GetPosition().y());
-
- // The non-perspective scroller should have no child transform and the
- // offset on the scroller layer directly.
-
- GraphicsLayer* scrolling_layer2 = mapping2->ScrollingLayer();
- GraphicsLayer* main_graphics_layer2 = mapping2->MainGraphicsLayer();
-
- ASSERT_TRUE(scrolling_layer2);
- ASSERT_FALSE(mapping2->ChildTransformLayer());
-
- EXPECT_FLOAT_EQ(30, main_graphics_layer2->GetPosition().x());
- EXPECT_FLOAT_EQ(390, main_graphics_layer2->GetPosition().y());
- EXPECT_FLOAT_EQ(20, scrolling_layer2->GetPosition().x());
- EXPECT_FLOAT_EQ(10, scrolling_layer2->GetPosition().y());
-}
-
TEST_F(CompositedLayerMappingTest, StickyPositionMainThreadOffset) {
SetBodyInnerHTML(R"HTML(
<style>.composited { backface-visibility: hidden; }
@@ -1349,10 +1237,8 @@ TEST_F(CompositedLayerMappingTest,
sticky->Layer()->GetCompositedLayerMapping();
ASSERT_TRUE(mapping);
GraphicsLayer* main_graphics_layer = mapping->MainGraphicsLayer();
- GraphicsLayer* child_transform_layer = mapping->ChildTransformLayer();
ASSERT_TRUE(main_graphics_layer);
- ASSERT_TRUE(child_transform_layer);
auto* scroller =
To<LayoutBlock>(GetLayoutObjectByElementId("scroller"))->Layer();
@@ -1369,11 +1255,6 @@ TEST_F(CompositedLayerMappingTest,
// removed so that the compositor can take care of it.
EXPECT_FLOAT_EQ(0, main_graphics_layer->GetPosition().x());
EXPECT_FLOAT_EQ(0, main_graphics_layer->GetPosition().y());
-
- // The child transform layer for the perspective shifting should also not be
- // moved by the sticky offset.
- EXPECT_FLOAT_EQ(0, child_transform_layer->GetPosition().x());
- EXPECT_FLOAT_EQ(0, child_transform_layer->GetPosition().y());
}
TEST_F(CompositedLayerMappingTest,
@@ -1415,9 +1296,9 @@ TEST_F(CompositedLayerMappingTest,
// This test verifies layers with direct compositing reasons won't have
// transformed rasterization, i.e. should raster in local space.
SetBodyInnerHTML(R"HTML(
- <div id='target1' style='transform:translateZ(0);'>foo</div>
- <div id='target2' style='will-change:opacity;'>bar</div>
- <div id='target3' style='backface-visibility:hidden;'>ham</div>
+ <div id='target1' style='will-change: transform;'>foo</div>
+ <div id='target2' style='will-change: opacity;'>bar</div>
+ <div id='target3' style='backface-visibility: hidden;'>ham</div>
)HTML");
{
@@ -1658,11 +1539,10 @@ TEST_F(CompositedLayerMappingTest,
return;
SetHtmlInnerHTML(R"HTML(
- <div id=scroller style="transform: translateZ(0); overflow: scroll;
- width: 200px; height: 400px;">
- <div id=squashing
- style='width: 200px; height: 200px; position: relative; will-change:
-transform'></div>
+ <div id=scroller style="will-change: transform; overflow: scroll;
+ width: 200px; height: 400px;">
+ <div id=squashing style='width: 200px; height: 200px; position: relative;
+ will-change: transform'></div>
<div id=squashed style="width: 200px; height: 6000px; top: -100px;
position: relative;">
</div>
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
index fa99f9fff80..75dd0354f0f 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc
@@ -16,7 +16,6 @@
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
namespace blink {
-
static const LayoutBoxModelObject* ClippingContainerFromClipChainParent(
const PaintLayer* clip_chain_parent) {
return clip_chain_parent->GetLayoutObject().HasClipRelatedProperty()
@@ -194,7 +193,7 @@ void CompositingInputsUpdater::UpdateSelfAndDescendantsRecursively(
compositor->ClearCompositingInputsRoot();
}
-void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* layer,
+void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* const layer,
UpdateType& update_type,
AncestorInfo& info) {
LayoutBoxModelObject& layout_object = layer->GetLayoutObject();
@@ -208,7 +207,7 @@ void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* layer,
case kNotComposited:
break;
case kPaintsIntoOwnBacking:
- if (layer->GetLayoutObject().StyleRef().IsStackingContext())
+ if (style.IsStackingContext())
enclosing_stacking_composited_layer = layer;
break;
case kPaintsIntoGroupedBacking:
@@ -240,6 +239,9 @@ void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* layer,
info.needs_reparent_scroll = info.needs_reparent_scroll_for_fixed;
}
+ if (layout_object.ShouldApplyLayoutContainment())
+ info.nearest_contained_layout_layer = layer;
+
if (update_type == kForceUpdate)
UpdateAncestorDependentCompositingInputs(layer, info);
@@ -332,7 +334,7 @@ void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* layer,
info.needs_reparent_scroll_for_fixed = false;
}
- if (layer->GetLayoutObject().IsStickyPositioned())
+ if (layout_object.IsStickyPositioned())
info.is_under_position_sticky = true;
}
@@ -426,6 +428,8 @@ void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
properties.scroll_parent = info.scrolling_ancestor;
properties.is_under_position_sticky = info.is_under_position_sticky;
+ properties.nearest_contained_layout_layer =
+ info.nearest_contained_layout_layer;
layer->UpdateAncestorDependentCompositingInputs(properties);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
index 5c1f3a8f948..c4b49027154 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -53,6 +53,11 @@ class CompositingInputsUpdater {
PaintLayer* scrolling_ancestor = nullptr;
PaintLayer* scrolling_ancestor_for_absolute = nullptr;
PaintLayer* scrolling_ancestor_for_fixed = nullptr;
+
+ // The nearest layer up in the ancestor chain that has layout containment
+ // applied to it, including the self layer.
+ PaintLayer* nearest_contained_layout_layer = nullptr;
+
// These flags are set to true if a non-stacking context scroller
// is encountered, so that a descendant element won't inherit scroll
// translation from its compositing ancestor directly thus having to
@@ -76,7 +81,7 @@ class CompositingInputsUpdater {
AncestorInfo&);
// This method takes care of updating AncestorInfo taking into account the
// current value of AncestorInfo.
- void UpdateAncestorInfo(PaintLayer*, UpdateType&, AncestorInfo&);
+ void UpdateAncestorInfo(PaintLayer* const, UpdateType&, AncestorInfo&);
// Combine all reasons for compositing a layer into a single boolean value
bool LayerOrDescendantShouldBeComposited(PaintLayer*);
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
index 9e8aa067363..3d43a923ee3 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
@@ -165,7 +165,7 @@ TEST_F(CompositingInputsUpdaterTest, MaskAncestor) {
SetBodyInnerHTML(R"HTML(
<div id="parent" style="-webkit-mask-image: linear-gradient(black, white);">
<div id="child" style="width: 20px; height: 20px; will-change: transform">
- <div id="grandchild" style="position: relative";
+ <div id="grandchild" style="position: relative"></div>
</div>
</div>
)HTML");
@@ -182,4 +182,31 @@ TEST_F(CompositingInputsUpdaterTest, MaskAncestor) {
EXPECT_EQ(parent, grandchild->MaskAncestor());
}
+TEST_F(CompositingInputsUpdaterTest, LayoutContainmentLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <div id="parent" style="contain: layout">
+ <div id="child" style="width: 20px; height: 20px; will-change: transform">
+ <div id="grandchild" style="contain: layout; position: relative">
+ <div id="greatgrandchild" style="position: relative"></div>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ PaintLayer* parent =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("parent"))->Layer();
+ PaintLayer* child =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("child"))->Layer();
+ PaintLayer* grandchild =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("grandchild"))->Layer();
+ PaintLayer* greatgrandchild =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("greatgrandchild"))
+ ->Layer();
+
+ EXPECT_EQ(parent, parent->NearestContainedLayoutLayer());
+ EXPECT_EQ(parent, child->NearestContainedLayoutLayer());
+ EXPECT_EQ(grandchild, grandchild->NearestContainedLayoutLayer());
+ EXPECT_EQ(grandchild, greatgrandchild->NearestContainedLayoutLayer());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
index 915a5a0187b..d31bd3e8a32 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -173,9 +173,6 @@ CompositingLayerAssigner::GetReasonsPreventingSquashing(
if (layer->TransformAncestor() != squashing_layer.TransformAncestor())
return SquashingDisallowedReason::kTransformAncestorMismatch;
- if (layer->RenderingContextRoot() != squashing_layer.RenderingContextRoot())
- return SquashingDisallowedReason::kRenderingContextMismatch;
-
if (layer->HasFilterInducingProperty() ||
layer->FilterAncestor() != squashing_layer.FilterAncestor())
return SquashingDisallowedReason::kFilterMismatch;
@@ -208,6 +205,10 @@ CompositingLayerAssigner::GetReasonsPreventingSquashing(
layer->MaskAncestor() != squashing_layer.MaskAncestor())
return SquashingDisallowedReason::kMaskMismatch;
+ if (layer->NearestContainedLayoutLayer() !=
+ squashing_layer.NearestContainedLayoutLayer())
+ return SquashingDisallowedReason::kCrossesLayoutContainmentBoundary;
+
return SquashingDisallowedReason::kNone;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner_test.cc
index f191ecd0ba2..7cdb1c5cc0a 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner_test.cc
@@ -62,4 +62,34 @@ TEST_F(CompositedLayerAssignerTest, SquashingAcrossMaskDisallowed) {
EXPECT_EQ(kPaintsIntoOwnBacking, squashed->GetCompositingState());
}
+TEST_F(CompositedLayerAssignerTest,
+ SquashingAcrossLayoutContainmentDisallowed) {
+ SetBodyInnerHTML(R"HTML(
+ <div style="contain: layout">
+ <div style="width: 20px; height: 20px; will-change: transform"></div>
+ </div>
+ <div id="squashed" style="position: absolute; top: 0; width: 100px;
+ height: 100px; background: green"></div>
+ )HTML");
+ // #squashed should not be squashed after all, because of 'contain: layout' on
+ // #squashing.
+ PaintLayer* squashed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("squashed"))->Layer();
+ EXPECT_EQ(kPaintsIntoOwnBacking, squashed->GetCompositingState());
+}
+
+TEST_F(CompositedLayerAssignerTest,
+ SquashingAcrossSelfLayoutContainmentDisallowed) {
+ SetBodyInnerHTML(R"HTML(
+ <div style="width: 20px; height: 20px; will-change: transform"></div>
+ <div id="squashed" style="contain: layout; position: absolute; top: 0; width: 100px;
+ height: 100px; background: green"></div>
+ )HTML");
+ // #squashed should not be squashed after all, because of 'contain: layout' on
+ // #squahed.
+ PaintLayer* squashed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("squashed"))->Layer();
+ EXPECT_EQ(kPaintsIntoOwnBacking, squashed->GetCompositingState());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index ac10e987b43..1049487d987 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
@@ -4,14 +4,14 @@
#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
-#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/node.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/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -70,12 +70,6 @@ CompositingReasonFinder::PotentialCompositingReasonsFromStyle(
reasons |= CompositingReasonsForAnimation(style);
reasons |= CompositingReasonsForWillChange(style);
- if (style.UsedTransformStyle3D() == ETransformStyle3D::kPreserve3d)
- reasons |= CompositingReason::kPreserve3DWith3DDescendants;
-
- if (style.HasPerspective())
- reasons |= CompositingReason::kPerspectiveWith3DDescendants;
-
// If the implementation of CreatesGroup changes, we need to be aware of that
// in this part of code.
DCHECK((style.HasOpacity() || layout_object.HasMask() ||
@@ -124,7 +118,9 @@ CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties(
auto* layer = ToLayoutBoxModelObject(object).Layer();
if (layer->Has3DTransformedDescendant()) {
- if (style.HasPerspective())
+ // Perspective (specified either by perspective or transform properties)
+ // with 3d descendants need a render surface for flattening purposes.
+ if (style.HasPerspective() || style.Transform().HasPerspective())
reasons |= CompositingReason::kPerspectiveWith3DDescendants;
if (style.Preserves3D())
reasons |= CompositingReason::kPreserve3DWith3DDescendants;
@@ -133,12 +129,12 @@ CompositingReasons CompositingReasonFinder::DirectReasonsForPaintProperties(
if (RequiresCompositingForRootScroller(*layer))
reasons |= CompositingReason::kRootScroller;
- if (RequiresCompositingForScrollTimeline(*layer))
- reasons |= CompositingReason::kScrollTimelineTarget;
-
if (RequiresCompositingForScrollDependentPosition(*layer))
reasons |= CompositingReason::kScrollDependentPosition;
+ if (style.HasBackdropFilter())
+ reasons |= CompositingReason::kBackdropFilter;
+
return reasons;
}
@@ -148,7 +144,7 @@ bool CompositingReasonFinder::RequiresCompositingFor3DTransform(
// may have transforms, but the layoutObject may be an inline that doesn't
// support them.
return layout_object.HasTransformRelatedProperty() &&
- layout_object.StyleRef().Has3DTransform() &&
+ layout_object.StyleRef().Has3DTransformOperation() &&
// Don't composite "trivial" 3D transforms such as translateZ(0) on
// low-end devices. These devices are much more sensitive to memory
// and per-composited-layer commit overhead.
@@ -169,9 +165,6 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
if (RequiresCompositingForRootScroller(layer))
direct_reasons |= CompositingReason::kRootScroller;
- if (RequiresCompositingForScrollTimeline(layer))
- direct_reasons |= CompositingReason::kScrollTimelineTarget;
-
// Composite |layer| if it is inside of an ancestor scrolling layer, but that
// scrolling layer is not on the stacking context ancestor chain of |layer|.
// See the definition of the scrollParent property in Layer for more detail.
@@ -191,6 +184,15 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
layer.CompositingContainer()->GetLayoutObject().IsVideo())
direct_reasons |= CompositingReason::kVideoOverlay;
+ // Special case for immersive-ar DOM overlay mode, see also
+ // PaintLayerCompositor::ApplyXrImmersiveDomOverlayIfNeeded()
+ if (const Node* node = layer.GetLayoutObject().GetNode()) {
+ if (node->IsElementNode() && node->GetDocument().IsImmersiveArOverlay() &&
+ node == Fullscreen::FullscreenElementFrom(node->GetDocument())) {
+ direct_reasons |= CompositingReason::kImmersiveArOverlay;
+ }
+ }
+
if (layer.IsRootLayer() &&
(RequiresCompositingForScrollableFrame(*layout_object.View()) ||
layout_object.GetFrame()->IsLocalRoot())) {
@@ -254,15 +256,6 @@ bool CompositingReasonFinder::RequiresCompositingForRootScroller(
return layer.GetLayoutObject().IsGlobalRootScroller();
}
-bool CompositingReasonFinder::RequiresCompositingForScrollTimeline(
- const PaintLayer& layer) {
- // TODO(crbug.com/839341): Remove once we support main-thread AnimationWorklet
- // and don't need to promote the scroll-source.
- return layer.GetScrollableArea() && layer.GetLayoutObject().GetNode() &&
- ScrollTimeline::HasActiveScrollTimeline(
- layer.GetLayoutObject().GetNode());
-}
-
bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
const PaintLayer& layer) {
const auto& layout_object = layer.GetLayoutObject();
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 998c1495795..11e4288a051 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
@@ -41,7 +41,6 @@ class CORE_EXPORT CompositingReasonFinder {
const ComputedStyle&);
static bool RequiresCompositingFor3DTransform(const LayoutObject&);
static bool RequiresCompositingForRootScroller(const PaintLayer&);
- static bool RequiresCompositingForScrollTimeline(const PaintLayer&);
static bool RequiresCompositingForScrollDependentPosition(const PaintLayer&);
};
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
index b3ae10816e9..ccffedaebb5 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc
@@ -192,8 +192,14 @@ static CompositingReasons SubtreeReasonsForCompositing(
// there are descendant layers that will be affected by the preserve-3d or
// perspective.
if (has3d_transformed_descendants) {
- subtree_reasons |= layer->PotentialCompositingReasonsFromStyle() &
- CompositingReason::kCombo3DDescendants;
+ const ComputedStyle& style = layer->GetLayoutObject().StyleRef();
+ if (style.UsedTransformStyle3D() == ETransformStyle3D::kPreserve3d)
+ subtree_reasons |= CompositingReason::kPreserve3DWith3DDescendants;
+
+ // Perspective (specified either by perspective or transform properties)
+ // with 3d descendants need a render surface for flattening purposes.
+ if (style.HasPerspective() || style.Transform().HasPerspective())
+ subtree_reasons |= CompositingReason::kPerspectiveWith3DDescendants;
}
return subtree_reasons;
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index 3bca46be1f7..d82e4b1c18b 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -125,4 +125,44 @@ TEST_F(CompositingRequirementsUpdaterTest,
EXPECT_EQ(IntRect(0, 0, 100, 100), tracking->Invalidations()[0].rect);
}
+TEST_F(CompositingRequirementsUpdaterTest,
+ DontPromotePerspectiveOnlyTransform) {
+ ScopedCSSIndependentTransformPropertiesForTest feature_scope(true);
+
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <div id="perspective-no-3d-descendant"
+ style="transform:perspective(1px) scale(2)">
+ <div id="transform2d" style="transform:translate(1px, 2px);"></div>
+ </div>
+ <div id="perspective-with-3d-descendant"
+ style="transform:perspective(1px) scale(2)">
+ <div id="3d-descendant" style="rotate: 0 1 0 1deg;"></div>
+ </div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ // Perspective with descendant with only a 2d transform should not be layered
+ // (neither should the descendant).
+ EXPECT_FALSE(ToLayoutBoxModelObject(
+ GetLayoutObjectByElementId("perspective-no-3d-descendant"))
+ ->Layer()
+ ->GetCompositingState());
+ EXPECT_FALSE(ToLayoutBoxModelObject(GetLayoutObjectByElementId("transform2d"))
+ ->Layer()
+ ->GetCompositingReasons());
+
+ // Both the perspective and 3d descendant should be layered, the former for
+ // flattening purposes, as it contains 3d transformed content.
+ EXPECT_EQ(CompositingReason::kPerspectiveWith3DDescendants,
+ ToLayoutBoxModelObject(
+ GetLayoutObjectByElementId("perspective-with-3d-descendant"))
+ ->Layer()
+ ->GetCompositingReasons());
+ EXPECT_EQ(CompositingReason::k3DTransform,
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("3d-descendant"))
+ ->Layer()
+ ->GetCompositingReasons());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
index a7049abbf1a..2f0f3aa4c0a 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
@@ -24,50 +24,9 @@ String PointerAsString(const void* ptr) {
return ts.Release();
}
-FloatPoint ScrollPosition(const GraphicsLayer& layer) {
- if (const auto* scrollable_area =
- layer.Client().GetScrollableAreaForTesting(&layer)) {
- return scrollable_area->ScrollPosition();
- }
- return FloatPoint();
-}
-
-void AddFlattenInheritedTransformJSON(const GraphicsLayer* layer,
- JSONObject& json) {
- if (layer->Parent() && !layer->Parent()->ShouldFlattenTransform())
- json.SetBoolean("flattenInheritedTransform", false);
-}
-
-void AddTransformJSONProperties(const GraphicsLayer* layer,
- JSONObject& json,
- RenderingContextMap& rendering_context_map) {
- const TransformationMatrix& transform = layer->Transform();
- if (!transform.IsIdentity())
- json.SetArray("transform", TransformAsJSONArray(transform));
-
- if (!transform.IsIdentityOrTranslation()) {
- json.SetArray("origin",
- PointAsJSONArray(FloatPoint3D(layer->TransformOrigin())));
- }
-
- AddFlattenInheritedTransformJSON(layer, json);
-
- if (int rendering_context3d = layer->GetRenderingContext3D()) {
- auto it = rendering_context_map.find(rendering_context3d);
- int context_id = rendering_context_map.size() + 1;
- if (it == rendering_context_map.end())
- rendering_context_map.Set(rendering_context3d, context_id);
- else
- context_id = it->value;
-
- json.SetInteger("renderingContext", context_id);
- }
-}
-
std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
const GraphicsLayer* layer,
LayerTreeFlags flags,
- RenderingContextMap& rendering_context_map,
const FloatPoint& position) {
auto json = std::make_unique<JSONObject>();
@@ -93,17 +52,6 @@ std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
if (layer->Size() != gfx::Size())
json->SetArray("bounds", SizeAsJSONArray(IntSize(layer->Size())));
- if (layer->Opacity() != 1)
- json->SetDouble("opacity", layer->Opacity());
-
- if (layer->GetBlendMode() != BlendMode::kNormal) {
- json->SetString("blendMode", CompositeOperatorName(kCompositeSourceOver,
- layer->GetBlendMode()));
- }
-
- if (layer->IsRootForIsolatedGroup())
- json->SetBoolean("isolate", true);
-
if (layer->ContentsOpaque())
json->SetBoolean("contentsOpaque", true);
@@ -124,15 +72,6 @@ std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
Color(layer->BackgroundColor()).NameForLayoutTreeAsText());
}
- if (flags & kOutputAsLayerTree) {
- AddTransformJSONProperties(layer, *json, rendering_context_map);
- if (!layer->ShouldFlattenTransform())
- json->SetBoolean("shouldFlattenTransform", false);
- FloatPoint scroll_position(ScrollPosition(*layer));
- if (scroll_position != FloatPoint())
- json->SetArray("scrollPosition", PointAsJSONArray(scroll_position));
- }
-
if ((flags & kLayerTreeIncludesPaintInvalidations) &&
layer->Client().IsTrackingRasterInvalidations() &&
layer->GetRasterInvalidationTracking()) {
@@ -187,7 +126,7 @@ std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
if (layer->MaskLayer()) {
auto mask_layer_json = std::make_unique<JSONArray>();
mask_layer_json->PushObject(
- GraphicsLayerAsJSON(layer->MaskLayer(), flags, rendering_context_map,
+ GraphicsLayerAsJSON(layer->MaskLayer(), flags,
FloatPoint(layer->MaskLayer()->GetPosition())));
json->SetArray("maskLayer", std::move(mask_layer_json));
}
@@ -220,76 +159,82 @@ class LayersAsJSONArray {
// and the transform tree also as a JSON array.
std::unique_ptr<JSONObject> operator()(const GraphicsLayer& layer) {
auto json = std::make_unique<JSONObject>();
- Walk(layer, 0, FloatPoint());
+ Walk(layer);
json->SetArray("layers", std::move(layers_json_));
if (transforms_json_->size())
json->SetArray("transforms", std::move(transforms_json_));
return json;
}
- JSONObject* AddTransformJSON(int& transform_id) {
- auto transform_json = std::make_unique<JSONObject>();
- int parent_transform_id = transform_id;
- transform_id = next_transform_id_++;
- transform_json->SetInteger("id", transform_id);
- if (parent_transform_id)
- transform_json->SetInteger("parent", parent_transform_id);
- auto* result = transform_json.get();
- transforms_json_->PushObject(std::move(transform_json));
- return result;
- }
+ int AddTransformJSON(const TransformPaintPropertyNode& transform) {
+ auto it = transform_id_map_.find(&transform);
+ if (it != transform_id_map_.end())
+ return it->value;
+
+ int parent_id = 0;
+ if (transform.Parent())
+ parent_id = AddTransformJSON(*transform.Parent());
+ if (transform.IsIdentity() && !transform.RenderingContextId()) {
+ transform_id_map_.Set(&transform, parent_id);
+ return parent_id;
+ }
- void AddLayer(const GraphicsLayer& layer,
- int& transform_id,
- FloatPoint& position) {
- FloatPoint scroll_position = ScrollPosition(layer);
- if (scroll_position != FloatPoint()) {
- // Output scroll position as a transform.
- auto* scroll_translate_json = AddTransformJSON(transform_id);
- scroll_translate_json->SetArray(
- "transform", TransformAsJSONArray(TransformationMatrix().Translate(
- -scroll_position.X(), -scroll_position.Y())));
- AddFlattenInheritedTransformJSON(&layer, *scroll_translate_json);
+ auto transform_json = std::make_unique<JSONObject>();
+ int id = next_transform_id_++;
+ transform_json->SetInteger("id", id);
+ if (parent_id)
+ transform_json->SetInteger("parent", parent_id);
+
+ if (!transform.IsIdentity()) {
+ transform_json->SetArray("transform",
+ TransformAsJSONArray(transform.SlowMatrix()));
}
- if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D() ||
- layer.GetCompositingReasons() & CompositingReason::k3DTransform) {
- if (position != FloatPoint()) {
- // Output position offset as a transform.
- auto* position_translate_json = AddTransformJSON(transform_id);
- position_translate_json->SetArray(
- "transform", TransformAsJSONArray(TransformationMatrix().Translate(
- position.X(), position.Y())));
- AddFlattenInheritedTransformJSON(&layer, *position_translate_json);
- if (layer.Parent() && !layer.Parent()->ShouldFlattenTransform()) {
- position_translate_json->SetBoolean("flattenInheritedTransform",
- false);
- }
- position = FloatPoint();
- }
+ if (!transform.IsIdentityOr2DTranslation() &&
+ !transform.Matrix().IsIdentityOrTranslation())
+ transform_json->SetArray("origin", PointAsJSONArray(transform.Origin()));
- if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D()) {
- auto* transform_json = AddTransformJSON(transform_id);
- AddTransformJSONProperties(&layer, *transform_json,
- rendering_context_map_);
- }
+ if (!transform.FlattensInheritedTransform())
+ transform_json->SetBoolean("flattenInheritedTransform", false);
+
+ if (auto rendering_context = transform.RenderingContextId()) {
+ auto context_lookup_result =
+ rendering_context_map_.find(rendering_context);
+ int rendering_id = rendering_context_map_.size() + 1;
+ if (context_lookup_result == rendering_context_map_.end())
+ rendering_context_map_.Set(rendering_context, rendering_id);
+ else
+ rendering_id = context_lookup_result->value;
+
+ transform_json->SetInteger("renderingContext", rendering_id);
}
- auto json =
- GraphicsLayerAsJSON(&layer, flags_, rendering_context_map_, position);
- if (transform_id)
- json->SetInteger("transform", transform_id);
+ transforms_json_->PushObject(std::move(transform_json));
+ transform_id_map_.Set(&transform, id);
+ return id;
+ }
+
+ void AddLayer(const GraphicsLayer& layer) {
+ if (!layer.DrawsContent() && !(flags_ & kLayerTreeIncludesRootLayer))
+ return;
+
+ FloatPoint offset;
+ if (layer.HasLayerState())
+ offset = FloatPoint(layer.GetOffsetFromTransformNode());
+ auto json = GraphicsLayerAsJSON(&layer, flags_, offset);
+ if (layer.HasLayerState()) {
+ int transform_id =
+ AddTransformJSON(layer.GetPropertyTreeState().Transform());
+ if (transform_id)
+ json->SetInteger("transform", transform_id);
+ }
layers_json_->PushObject(std::move(json));
}
- void Walk(const GraphicsLayer& layer,
- int parent_transform_id,
- const FloatPoint& parent_position) {
- FloatPoint position = parent_position + FloatPoint(layer.GetPosition());
- int transform_id = parent_transform_id;
- AddLayer(layer, transform_id, position);
+ void Walk(const GraphicsLayer& layer) {
+ AddLayer(layer);
for (auto* const child : layer.Children())
- Walk(*child, transform_id, position);
+ Walk(*child);
}
private:
@@ -297,36 +242,26 @@ class LayersAsJSONArray {
int next_transform_id_;
RenderingContextMap rendering_context_map_;
std::unique_ptr<JSONArray> layers_json_;
+ HashMap<const TransformPaintPropertyNode*, int> transform_id_map_;
std::unique_ptr<JSONArray> transforms_json_;
};
-// This is the SPv1 version of ContentLayerClientImpl::LayerAsJSON().
-std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(
- const GraphicsLayer* layer,
- LayerTreeFlags flags,
- RenderingContextMap& rendering_context_map) {
- std::unique_ptr<JSONObject> json = GraphicsLayerAsJSON(
- layer, flags, rendering_context_map, FloatPoint(layer->GetPosition()));
-
- if (layer->Children().size()) {
- auto children_json = std::make_unique<JSONArray>();
- for (wtf_size_t i = 0; i < layer->Children().size(); i++) {
- children_json->PushObject(GraphicsLayerTreeAsJSON(
- layer->Children()[i], flags, rendering_context_map));
- }
- json->SetArray("children", std::move(children_json));
- }
-
- return json;
-}
-
} // namespace
std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(const GraphicsLayer* layer,
LayerTreeFlags flags) {
if (flags & kOutputAsLayerTree) {
- RenderingContextMap rendering_context_map;
- return GraphicsLayerTreeAsJSON(layer, flags, rendering_context_map);
+ std::unique_ptr<JSONObject> json =
+ GraphicsLayerAsJSON(layer, flags, FloatPoint(layer->GetPosition()));
+ if (layer->Children().size()) {
+ auto children_json = std::make_unique<JSONArray>();
+ for (wtf_size_t i = 0; i < layer->Children().size(); i++) {
+ children_json->PushObject(
+ GraphicsLayerTreeAsJSON(layer->Children()[i], flags));
+ }
+ json->SetArray("children", std::move(children_json));
+ }
+ return json;
}
return LayersAsJSONArray(flags)(*layer);
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 2dd7f75b6b8..595ca82a9d6 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
@@ -333,6 +333,10 @@ void PaintLayerCompositor::ApplyOverlayFullscreenVideoAdjustmentIfNeeded() {
if (!is_local_root || !video_layer)
return;
+ // Recursively invalidate the paint controllers and related state on the
+ // children being removed. This avoid stale references from display items back
+ // to the layout tree.
+ content_parent->SetNeedsDisplayRecursively();
content_parent->RemoveAllChildren();
content_parent->AddChild(video_layer);
}
@@ -721,14 +725,57 @@ GraphicsLayer* PaintLayerCompositor::RootGraphicsLayer() const {
return nullptr;
}
+GraphicsLayer* PaintLayerCompositor::GetXrImmersiveDomOverlayLayer() const {
+ // immersive-ar DOM overlay mode is very similar to fullscreen video, using
+ // the AR camera image instead of a video element as a background that's
+ // separately composited in the browser. The fullscreened DOM content is shown
+ // on top of that, same as HTML video controls.
+ //
+ // The normal fullscreen mode assumes an opaque background, and this doesn't
+ // work for this use case since this mode uses a transparent background, so
+ // the non-fullscreened content would remain visible. Fix this by ensuring
+ // that the fullscreened element has its own layer and using that layer as the
+ // paint root. (This is different from the fullscreen video overlay which
+ // detaches layers other than the video layer. The overall effect is the same,
+ // but it seems safer since it avoids unattached leftover layers.)
+ DCHECK(IsMainFrame());
+ DCHECK(layout_view_.GetDocument().IsImmersiveArOverlay());
+
+ Element* fullscreen_element =
+ Fullscreen::FullscreenElementFrom(layout_view_.GetDocument());
+ if (!fullscreen_element)
+ return nullptr;
+
+ LayoutBoxModelObject* box = fullscreen_element->GetLayoutBoxModelObject();
+ if (!box) {
+ // Currently, only HTML fullscreen elements are supported for this mode,
+ // not others such as SVG or MathML.
+ DVLOG(1) << "no LayoutBoxModelObject for element " << fullscreen_element;
+ return nullptr;
+ }
+
+ // The fullscreen element will be in its own layer due to
+ // CompositingReasonFinder treating this scenario as a direct_reason.
+ PaintLayer* layer = box->Layer();
+ DCHECK(layer);
+ GraphicsLayer* full_screen_layer = layer->GraphicsLayerBacking(box);
+ return full_screen_layer;
+}
+
GraphicsLayer* PaintLayerCompositor::PaintRootGraphicsLayer() const {
if (layout_view_.GetDocument().GetPage()->GetChromeClient().IsPopup())
return RootGraphicsLayer();
- // Start painting at the inner viewport container layer which is an ancestor
- // of both the main contents layers and the scrollbar layers.
- if (IsMainFrame() && GetVisualViewport().ContainerLayer())
- return GetVisualViewport().ContainerLayer();
+ if (IsMainFrame() && layout_view_.GetDocument().IsImmersiveArOverlay()) {
+ GraphicsLayer* overlay_layer = GetXrImmersiveDomOverlayLayer();
+ if (overlay_layer)
+ return overlay_layer;
+ }
+
+ // Start painting at the root graphics layer of the inner viewport which is an
+ // ancestor of both the main contents layers and the scrollbar layers.
+ if (IsMainFrame() && GetVisualViewport().RootGraphicsLayer())
+ return GetVisualViewport().RootGraphicsLayer();
return RootGraphicsLayer();
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
index 3769e52623a..82a4f4de5a4 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
@@ -129,7 +129,7 @@ class CORE_EXPORT PaintLayerCompositor {
// Returns the GraphicsLayer we should start painting from. This can differ
// from above in some cases, e.g. when the RootGraphicsLayer is detached and
- // swapped out for an overlay video layer.
+ // swapped out for an overlay video or immersive-ar DOM overlay layer.
GraphicsLayer* PaintRootGraphicsLayer() const;
static PaintLayerCompositor* FrameContentsCompositor(LayoutEmbeddedContent&);
@@ -203,6 +203,8 @@ class CORE_EXPORT PaintLayerCompositor {
GraphicsLayer* ParentForContentLayers(
GraphicsLayer* child_frame_parent_candidate = nullptr) const;
+ GraphicsLayer* GetXrImmersiveDomOverlayLayer() const;
+
LayoutView& layout_view_;
const bool has_accelerated_compositing_ = true;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.cc b/chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.cc
index b63377ff8c3..2ffee4a854e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.cc
+++ b/chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.cc
@@ -23,10 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_theme.h"
+#include "third_party/blink/renderer/core/paint/custom_scrollbar_theme.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_painter.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/paint/object_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -34,12 +36,12 @@
namespace blink {
-LayoutScrollbarTheme* LayoutScrollbarTheme::GetLayoutScrollbarTheme() {
- DEFINE_STATIC_LOCAL(LayoutScrollbarTheme, theme, ());
+CustomScrollbarTheme* CustomScrollbarTheme::GetCustomScrollbarTheme() {
+ DEFINE_STATIC_LOCAL(CustomScrollbarTheme, theme, ());
return &theme;
}
-void LayoutScrollbarTheme::ButtonSizesAlongTrackAxis(const Scrollbar& scrollbar,
+void CustomScrollbarTheme::ButtonSizesAlongTrackAxis(const Scrollbar& scrollbar,
int& before_size,
int& after_size) {
IntRect first_button = BackButtonRect(scrollbar, kBackButtonStartPart);
@@ -55,7 +57,7 @@ void LayoutScrollbarTheme::ButtonSizesAlongTrackAxis(const Scrollbar& scrollbar,
}
}
-bool LayoutScrollbarTheme::HasButtons(const Scrollbar& scrollbar) {
+bool CustomScrollbarTheme::HasButtons(const Scrollbar& scrollbar) {
int start_size;
int end_size;
ButtonSizesAlongTrackAxis(scrollbar, start_size, end_size);
@@ -64,27 +66,25 @@ bool LayoutScrollbarTheme::HasButtons(const Scrollbar& scrollbar) {
: scrollbar.Height());
}
-bool LayoutScrollbarTheme::HasThumb(const Scrollbar& scrollbar) {
+bool CustomScrollbarTheme::HasThumb(const Scrollbar& scrollbar) {
return TrackLength(scrollbar) - ThumbLength(scrollbar) >= 0;
}
-int LayoutScrollbarTheme::MinimumThumbLength(const Scrollbar& scrollbar) {
- return To<LayoutScrollbar>(scrollbar).MinimumThumbLength();
+int CustomScrollbarTheme::MinimumThumbLength(const Scrollbar& scrollbar) {
+ return To<CustomScrollbar>(scrollbar).MinimumThumbLength();
}
-IntRect LayoutScrollbarTheme::BackButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part_type,
- bool) {
- return To<LayoutScrollbar>(scrollbar).ButtonRect(part_type);
+IntRect CustomScrollbarTheme::BackButtonRect(const Scrollbar& scrollbar,
+ ScrollbarPart part_type) {
+ return To<CustomScrollbar>(scrollbar).ButtonRect(part_type);
}
-IntRect LayoutScrollbarTheme::ForwardButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part_type,
- bool) {
- return To<LayoutScrollbar>(scrollbar).ButtonRect(part_type);
+IntRect CustomScrollbarTheme::ForwardButtonRect(const Scrollbar& scrollbar,
+ ScrollbarPart part_type) {
+ return To<CustomScrollbar>(scrollbar).ButtonRect(part_type);
}
-IntRect LayoutScrollbarTheme::TrackRect(const Scrollbar& scrollbar, bool) {
+IntRect CustomScrollbarTheme::TrackRect(const Scrollbar& scrollbar) {
if (!HasButtons(scrollbar))
return scrollbar.FrameRect();
@@ -92,16 +92,16 @@ IntRect LayoutScrollbarTheme::TrackRect(const Scrollbar& scrollbar, bool) {
int end_length;
ButtonSizesAlongTrackAxis(scrollbar, start_length, end_length);
- return To<LayoutScrollbar>(scrollbar).TrackRect(start_length, end_length);
+ return To<CustomScrollbar>(scrollbar).TrackRect(start_length, end_length);
}
-IntRect LayoutScrollbarTheme::ConstrainTrackRectToTrackPieces(
+IntRect CustomScrollbarTheme::ConstrainTrackRectToTrackPieces(
const Scrollbar& scrollbar,
const IntRect& rect) {
- IntRect back_rect = To<LayoutScrollbar>(scrollbar).TrackPieceRectWithMargins(
+ IntRect back_rect = To<CustomScrollbar>(scrollbar).TrackPieceRectWithMargins(
kBackTrackPart, rect);
IntRect forward_rect =
- To<LayoutScrollbar>(scrollbar).TrackPieceRectWithMargins(
+ To<CustomScrollbar>(scrollbar).TrackPieceRectWithMargins(
kForwardTrackPart, rect);
IntRect result = rect;
if (scrollbar.Orientation() == kHorizontalScrollbar) {
@@ -114,63 +114,100 @@ IntRect LayoutScrollbarTheme::ConstrainTrackRectToTrackPieces(
return result;
}
-void LayoutScrollbarTheme::PaintScrollCorner(
+void CustomScrollbarTheme::PaintScrollCorner(
GraphicsContext& context,
const DisplayItemClient& display_item_client,
const IntRect& corner_rect,
WebColorScheme color_scheme) {
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, display_item_client, DisplayItem::kScrollbarCorner))
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, display_item_client,
+ DisplayItem::kScrollCorner))
return;
DrawingRecorder recorder(context, display_item_client,
- DisplayItem::kScrollbarCorner);
+ DisplayItem::kScrollCorner);
// FIXME: Implement.
context.FillRect(corner_rect, Color::kWhite);
}
-void LayoutScrollbarTheme::PaintScrollbarBackground(
+void CustomScrollbarTheme::PaintScrollbarBackground(
GraphicsContext& context,
const Scrollbar& scrollbar) {
- ScrollbarPainter(To<LayoutScrollbar>(scrollbar))
- .PaintPart(context, kScrollbarBGPart, scrollbar.FrameRect());
+ PaintPart(context, scrollbar, scrollbar.FrameRect(), kScrollbarBGPart);
}
-void LayoutScrollbarTheme::PaintTrackBackground(GraphicsContext& context,
+void CustomScrollbarTheme::PaintTrackBackground(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) {
- ScrollbarPainter(To<LayoutScrollbar>(scrollbar))
- .PaintPart(context, kTrackBGPart, rect);
+ PaintPart(context, scrollbar, rect, kTrackBGPart);
}
-void LayoutScrollbarTheme::PaintTrackPiece(GraphicsContext& context,
+void CustomScrollbarTheme::PaintTrackPiece(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect,
ScrollbarPart part) {
- ScrollbarPainter(To<LayoutScrollbar>(scrollbar))
- .PaintPart(context, part, rect);
+ PaintPart(context, scrollbar, rect, part);
}
-void LayoutScrollbarTheme::PaintButton(GraphicsContext& context,
+void CustomScrollbarTheme::PaintButton(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect,
ScrollbarPart part) {
- ScrollbarPainter(To<LayoutScrollbar>(scrollbar))
- .PaintPart(context, part, rect);
+ PaintPart(context, scrollbar, rect, part);
}
-void LayoutScrollbarTheme::PaintThumb(GraphicsContext& context,
+void CustomScrollbarTheme::PaintThumb(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) {
- ScrollbarPainter(To<LayoutScrollbar>(scrollbar))
- .PaintPart(context, kThumbPart, rect);
+ PaintPart(context, scrollbar, rect, kThumbPart);
}
-void LayoutScrollbarTheme::PaintTickmarks(GraphicsContext& context,
+void CustomScrollbarTheme::PaintTickmarks(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) {
ScrollbarTheme::DeprecatedStaticGetTheme().PaintTickmarks(context, scrollbar,
rect);
}
+void CustomScrollbarTheme::PaintIntoRect(
+ const LayoutCustomScrollbarPart& layout_custom_scrollbar_part,
+ GraphicsContext& graphics_context,
+ const PhysicalOffset& paint_offset,
+ const PhysicalRect& rect,
+ const CustomScrollbar* scrollbar) {
+ // Make sure our dimensions match the rect.
+ // TODO(crbug.com/856802): Setting these is a bad layering violation!
+ // Move these into layout stage.
+ const_cast<LayoutCustomScrollbarPart&>(layout_custom_scrollbar_part)
+ .SetLocation((rect.offset - paint_offset).ToLayoutPoint());
+ const_cast<LayoutCustomScrollbarPart&>(layout_custom_scrollbar_part)
+ .SetWidth(rect.size.width);
+ const_cast<LayoutCustomScrollbarPart&>(layout_custom_scrollbar_part)
+ .SetHeight(rect.size.height);
+ // TODO(crbug.com/856802): Move this into PaintPropertyTreeBuilder.
+ layout_custom_scrollbar_part.GetMutableForPainting()
+ .FirstFragment()
+ .SetPaintOffset((scrollbar ? PhysicalOffset(scrollbar->Location())
+ : PhysicalOffset()) +
+ layout_custom_scrollbar_part.PhysicalLocation());
+
+ PaintInfo paint_info(graphics_context, PixelSnappedIntRect(rect),
+ PaintPhase::kForeground, kGlobalPaintNormalPhase,
+ kPaintLayerNoFlag);
+ ObjectPainter(layout_custom_scrollbar_part)
+ .PaintAllPhasesAtomically(paint_info);
+}
+
+void CustomScrollbarTheme::PaintPart(GraphicsContext& context,
+ const Scrollbar& scrollbar,
+ const IntRect& rect,
+ ScrollbarPart part) {
+ const auto& custom_scrollbar = To<CustomScrollbar>(scrollbar);
+ const auto* part_layout_object = custom_scrollbar.GetPart(part);
+ if (!part_layout_object)
+ return;
+ PaintIntoRect(*part_layout_object, context,
+ PhysicalOffset(custom_scrollbar.Location()), PhysicalRect(rect),
+ &custom_scrollbar);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h b/chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.h
index 1e713d10e5e..ff04f124173 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h
+++ b/chromium/third_party/blink/renderer/core/paint/custom_scrollbar_theme.h
@@ -23,18 +23,22 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_THEME_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_THEME_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_CUSTOM_SCROLLBAR_THEME_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_CUSTOM_SCROLLBAR_THEME_H_
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
namespace blink {
+class CustomScrollbar;
+class LayoutCustomScrollbarPart;
class WebMouseEvent;
+struct PhysicalOffset;
+struct PhysicalRect;
-class LayoutScrollbarTheme final : public ScrollbarTheme {
+class CustomScrollbarTheme final : public ScrollbarTheme {
public:
- ~LayoutScrollbarTheme() override = default;
+ ~CustomScrollbarTheme() override = default;
int ScrollbarThickness(ScrollbarControlSize control_size) override {
return ScrollbarTheme::DeprecatedStaticGetTheme().ScrollbarThickness(
@@ -80,19 +84,21 @@ class LayoutScrollbarTheme final : public ScrollbarTheme {
int& before_size,
int& after_size);
- static LayoutScrollbarTheme* GetLayoutScrollbarTheme();
+ static CustomScrollbarTheme* GetCustomScrollbarTheme();
+
+ static void PaintIntoRect(const LayoutCustomScrollbarPart&,
+ GraphicsContext&,
+ const PhysicalOffset& paint_offset,
+ const PhysicalRect&,
+ const CustomScrollbar* = nullptr);
protected:
bool HasButtons(const Scrollbar&) override;
bool HasThumb(const Scrollbar&) override;
- IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect TrackRect(const Scrollbar&, bool painting = false) override;
+ IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect TrackRect(const Scrollbar&) override;
void PaintScrollbarBackground(GraphicsContext&, const Scrollbar&) override;
void PaintTrackBackground(GraphicsContext&,
@@ -111,10 +117,21 @@ class LayoutScrollbarTheme final : public ScrollbarTheme {
const Scrollbar&,
const IntRect&) override;
+ // The layout objects in the custom scrollbar create display items.
+ bool CreatesSingleDisplayItemForTrackAndButtons() const final {
+ return false;
+ }
+
IntRect ConstrainTrackRectToTrackPieces(const Scrollbar&,
const IntRect&) override;
+
+ private:
+ void PaintPart(GraphicsContext&,
+ const Scrollbar&,
+ const IntRect&,
+ ScrollbarPart);
};
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_SCROLLBAR_THEME_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_CUSTOM_SCROLLBAR_THEME_H_
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 d21714e413a..41bd8afeb85 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,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/document_marker_painter.h"
+#include "base/stl_util.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"
@@ -81,7 +82,7 @@ sk_sp<PaintRecord> RecordMarker(Color blink_color) {
flags.setAntiAlias(true);
flags.setColor(color);
flags.setShader(PaintShader::MakeLinearGradient(
- pts, colors, nullptr, ARRAY_SIZE(colors), SkTileMode::kClamp));
+ pts, colors, nullptr, base::size(colors), SkTileMode::kClamp));
PaintRecorder recorder;
recorder.beginRecording(kMarkerWidth, kMarkerHeight);
recorder.getRecordingCanvas()->drawOval(SkRect::MakeWH(2 * kR, 2 * kR),
@@ -234,7 +235,7 @@ void DocumentMarkerPainter::PaintDocumentMarker(
TextPaintStyle DocumentMarkerPainter::ComputeTextPaintStyleFrom(
const ComputedStyle& style,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
bool in_forced_colors_mode) {
const Color text_color = LayoutTheme::GetTheme().PlatformTextSearchColor(
marker.IsActiveMatch(), in_forced_colors_mode, style.UsedColorScheme());
diff --git a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h
index ba7f2bcc5b0..6920657f1dc 100644
--- a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h
@@ -15,7 +15,7 @@ class FloatRect;
class GraphicsContext;
class LayoutUnit;
class StyleableMarker;
-class TextMatchMarker;
+class TextMarkerBase;
struct TextPaintStyle;
struct PhysicalOffset;
struct PhysicalRect;
@@ -39,7 +39,7 @@ class DocumentMarkerPainter {
DocumentMarker::MarkerType marker_type,
const PhysicalRect& local_rect);
static TextPaintStyle ComputeTextPaintStyleFrom(const ComputedStyle& style,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
bool in_forced_colors_mode);
};
diff --git a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
index 5611e312646..4508072245b 100644
--- a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
@@ -78,18 +78,14 @@ void FileUploadControlPainter::PaintObject(const PaintInfo& paint_info,
paint_info.context.DrawBidiText(
font, text_run_paint_info,
FloatPoint(RoundToInt(text_x), RoundToInt(text_y)));
- if ((RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_file_upload_control_.GetDocument()))) {
- if (!font.ShouldSkipDrawing()) {
- ScopedPaintTimingDetectorBlockPaintHook
- scoped_paint_timing_detector_block_paint_hook;
- scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
- layout_file_upload_control_, paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- PaintTimingDetector::NotifyTextPaint(
- layout_file_upload_control_.FragmentsVisualRectBoundingBox());
- }
+ if (!font.ShouldSkipDrawing()) {
+ ScopedPaintTimingDetectorBlockPaintHook
+ scoped_paint_timing_detector_block_paint_hook;
+ scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
+ layout_file_upload_control_, paint_info.context.GetPaintController()
+ .CurrentPaintChunkProperties());
+ PaintTimingDetector::NotifyTextPaint(
+ layout_file_upload_control_.FragmentsVisualRectBoundingBox());
}
}
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 4c557678272..3eaac6137e5 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
@@ -48,8 +48,8 @@ Document* FirstMeaningfulPaintDetector::GetDocument() {
// First Meaningful Paint.
void FirstMeaningfulPaintDetector::MarkNextPaintAsMeaningfulIfNeeded(
const LayoutObjectCounter& counter,
- int contents_height_before_layout,
- int contents_height_after_layout,
+ double contents_height_before_layout,
+ double contents_height_after_layout,
int visible_height) {
if (network_quiet_reached_)
return;
@@ -60,10 +60,10 @@ void FirstMeaningfulPaintDetector::MarkNextPaintAsMeaningfulIfNeeded(
if (visible_height == 0)
return;
- double ratio_before = std::max(
- 1.0, static_cast<double>(contents_height_before_layout) / visible_height);
- double ratio_after = std::max(
- 1.0, static_cast<double>(contents_height_after_layout) / visible_height);
+ double ratio_before =
+ std::max(1.0, contents_height_before_layout / visible_height);
+ double ratio_after =
+ std::max(1.0, contents_height_after_layout / visible_height);
double significance = delta / ((ratio_before + ratio_after) / 2);
// If the page has many blank characters, the significance value is
diff --git a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
index 76b4f2b533c..a0c9db2c3f2 100644
--- a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h
@@ -26,7 +26,7 @@ class PaintTiming;
// seconds), and computes the layout-based First Meaningful Paint.
// See https://goo.gl/vpaxv6 and http://goo.gl/TEiMi4 for more details.
class CORE_EXPORT FirstMeaningfulPaintDetector
- : public GarbageCollectedFinalized<FirstMeaningfulPaintDetector> {
+ : public GarbageCollected<FirstMeaningfulPaintDetector> {
public:
static FirstMeaningfulPaintDetector& From(Document&);
@@ -34,8 +34,8 @@ class CORE_EXPORT FirstMeaningfulPaintDetector
virtual ~FirstMeaningfulPaintDetector() = default;
void MarkNextPaintAsMeaningfulIfNeeded(const LayoutObjectCounter&,
- int contents_height_before_layout,
- int contents_height_after_layout,
+ double contents_height_before_layout,
+ double contents_height_after_layout,
int visible_height);
void NotifyInputEvent();
void NotifyPaint();
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
index f847c968ea6..f8ce906dfa2 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_painter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
index b2f2f2021cb..dc2531bcd1b 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "cc/layers/layer.h"
+#include "components/viz/test/test_context_provider.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h"
@@ -16,8 +17,7 @@
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -33,14 +33,8 @@ class HTMLCanvasPainterTestForCAP : public PaintControllerPaintTest {
protected:
void SetUp() override {
- auto factory = [](FakeGLES2Interface* gl, bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- gl->SetIsContextLost(false);
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl);
- };
- SharedGpuContext::SetContextProviderFactoryForTesting(
- WTF::BindRepeating(factory, WTF::Unretained(&gl_)));
+ test_context_provider_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(test_context_provider_.get());
PaintControllerPaintTest::SetUp();
}
@@ -68,7 +62,7 @@ class HTMLCanvasPainterTestForCAP : public PaintControllerPaintTest {
}
private:
- FakeGLES2Interface gl_;
+ scoped_refptr<viz::TestContextProvider> test_context_provider_;
};
INSTANTIATE_CAP_TEST_SUITE_P(HTMLCanvasPainterTestForCAP);
@@ -91,7 +85,9 @@ TEST_P(HTMLCanvasPainterTestForCAP, Canvas2DLayerAppearsInLayerTree) {
ASSERT_TRUE(element->IsAccelerated());
// Force the page to paint.
- element->FinalizeFrame();
+ element->PreFinalizeFrame();
+ context->FinalizeFrame();
+ element->PostFinalizeFrame();
UpdateAllLifecyclePhasesForTest();
// Fetch the layer associated with the <canvas>, and check that it was
diff --git a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
index 136e504e4be..1db061a5ff6 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -60,10 +60,7 @@ ImageElementTiming& ImageElementTiming::From(LocalDOMWindow& window) {
}
ImageElementTiming::ImageElementTiming(LocalDOMWindow& window)
- : Supplement<LocalDOMWindow>(window) {
- DCHECK(RuntimeEnabledFeatures::ElementTimingEnabled(
- GetSupplementable()->document()));
-}
+ : Supplement<LocalDOMWindow>(window) {}
void ImageElementTiming::NotifyImageFinished(
const LayoutObject& layout_object,
@@ -151,11 +148,12 @@ void ImageElementTiming::NotifyImagePaintedInternal(
DCHECK(layout_object.GetDocument().GetSecurityOrigin());
// It's ok to expose rendering timestamp for data URIs so exclude those from
// the Timing-Allow-Origin check.
+ bool tainted = false;
if (!url.ProtocolIsData() &&
!Performance::PassesTimingAllowCheck(
cached_image.GetResponse(),
*layout_object.GetDocument().GetSecurityOrigin(),
- &layout_object.GetDocument())) {
+ &layout_object.GetDocument(), &tainted)) {
WindowPerformance* performance =
DOMWindowPerformance::performance(*GetSupplementable());
if (performance) {
diff --git a/chromium/third_party/blink/renderer/core/paint/image_element_timing.h b/chromium/third_party/blink/renderer/core/paint/image_element_timing.h
index 113c415d367..1f6ac8fbcd0 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_element_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/image_element_timing.h
@@ -26,7 +26,7 @@ class StyleFetchedImage;
// ImageElementTiming is responsible for tracking the paint timings for <img>
// elements for a given window.
class CORE_EXPORT ImageElementTiming final
- : public GarbageCollectedFinalized<ImageElementTiming>,
+ : public GarbageCollected<ImageElementTiming>,
public Supplement<LocalDOMWindow> {
USING_GARBAGE_COLLECTED_MIXIN(ImageElementTiming);
@@ -79,8 +79,7 @@ class CORE_EXPORT ImageElementTiming final
base::TimeTicks timestamp);
// Class containing information about image element timing.
- class ElementTimingInfo
- : public GarbageCollectedFinalized<ElementTimingInfo> {
+ class ElementTimingInfo final : public GarbageCollected<ElementTimingInfo> {
public:
ElementTimingInfo(const String& url,
const FloatRect& rect,
diff --git a/chromium/third_party/blink/renderer/core/paint/image_element_timing_test.cc b/chromium/third_party/blink/renderer/core/paint/image_element_timing_test.cc
index bebc1d83a24..32ce98ce500 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_element_timing_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_element_timing_test.cc
@@ -42,17 +42,21 @@ class ImageElementTimingTest : public testing::Test {
// the LayoutImage.
LayoutImage* SetImageResource(const char* id, int width, int height) {
ImageResourceContent* content = CreateImageForTest(width, height);
- auto* layout_image = ToLayoutImage(GetLayoutObjectById(id));
- layout_image->ImageResource()->SetImageResource(content);
- return layout_image;
+ if (auto* layout_image = ToLayoutImageOrNull(GetLayoutObjectById(id))) {
+ layout_image->ImageResource()->SetImageResource(content);
+ return layout_image;
+ }
+ return nullptr;
}
// Similar to above but for a LayoutSVGImage.
LayoutSVGImage* SetSVGImageResource(const char* id, int width, int height) {
ImageResourceContent* content = CreateImageForTest(width, height);
- auto* layout_image = ToLayoutSVGImage(GetLayoutObjectById(id));
- layout_image->ImageResource()->SetImageResource(content);
- return layout_image;
+ if (auto* layout_image = ToLayoutSVGImageOrNull(GetLayoutObjectById(id))) {
+ layout_image->ImageResource()->SetImageResource(content);
+ return layout_image;
+ }
+ return nullptr;
}
bool ImagesNotifiedContains(
@@ -156,6 +160,25 @@ TEST_F(ImageElementTimingTest, IgnoresUnmarkedElement) {
TEST_F(ImageElementTimingTest, ImageInsideSVG) {
frame_test_helpers::LoadHTMLString(
web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
+ <svg>
+ <foreignObject width="100" height="100">
+ <img elementtiming="image-inside-svg" id="target" style='width: 100px; height: 100px;'/>
+ </foreignObject>
+ </svg>
+ )HTML",
+ base_url_);
+ LayoutImage* layout_image = SetImageResource("target", 5, 5);
+ ASSERT_TRUE(layout_image);
+ UpdateAllLifecyclePhases();
+
+ // |layout_image| should have had its paint notified to ImageElementTiming.
+ EXPECT_TRUE(ImagesNotifiedContains(
+ std::make_pair(layout_image, layout_image->CachedImage())));
+}
+
+TEST_F(ImageElementTimingTest, ImageInsideNonRenderedSVG) {
+ frame_test_helpers::LoadHTMLString(
+ web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
<svg mask="url(#mask)">
<mask id="mask">
<foreignObject width="100" height="100">
@@ -166,13 +189,11 @@ TEST_F(ImageElementTimingTest, ImageInsideSVG) {
</svg>
)HTML",
base_url_);
- LayoutImage* layout_image = SetImageResource("target", 5, 5);
- ASSERT_TRUE(layout_image);
- UpdateAllLifecyclePhases();
- // |layout_image| should have had its paint notified to ImageElementTiming.
- EXPECT_TRUE(ImagesNotifiedContains(
- std::make_pair(layout_image, layout_image->CachedImage())));
+ // HTML inside foreignObject in a non-rendered SVG subtree should not generate
+ // layout objects. Generating layout objects for caused crashes
+ // (crbug.com/905850) as well as correctness issues.
+ EXPECT_FALSE(GetLayoutObjectById("target"));
}
TEST_F(ImageElementTimingTest, ImageRemoved) {
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 caef223f0cf..6f8d03d3cda 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
@@ -296,8 +296,7 @@ void ImageRecordsManager::OnImageLoaded(const RecordId& record_id,
DCHECK(!record->load_time.is_null());
} else {
Document* document = frame_view_->GetFrame().GetDocument();
- if (document && document->domWindow() &&
- RuntimeEnabledFeatures::ElementTimingEnabled(document)) {
+ if (document && document->domWindow()) {
record->load_time = ImageElementTiming::From(*document->domWindow())
.GetBackgroundImageLoadTime(style_image);
}
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 4e9c9e97d93..b18203fdb9e 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
@@ -200,7 +200,7 @@ class CORE_EXPORT ImageRecordsManager {
// See also:
// https://docs.google.com/document/d/1DRVd4a2VU8-yyWftgOparZF-sf16daf0vfbsHuz2rws/edit#heading=h.1k2rnrs6mdmt
class CORE_EXPORT ImagePaintTimingDetector final
- : public GarbageCollectedFinalized<ImagePaintTimingDetector> {
+ : public GarbageCollected<ImagePaintTimingDetector> {
friend class ImagePaintTimingDetectorTest;
public:
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 05b8b742da2..1fc70d472c2 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
@@ -33,13 +33,10 @@
namespace blink {
-class ImagePaintTimingDetectorTest
- : public testing::Test,
- private ScopedFirstContentfulPaintPlusPlusForTest {
+class ImagePaintTimingDetectorTest : public testing::Test {
public:
ImagePaintTimingDetectorTest()
- : ScopedFirstContentfulPaintPlusPlusForTest(true),
- test_task_runner_(
+ : test_task_runner_(
base::MakeRefCounted<base::TestMockTimeTaskRunner>()) {}
void SetUp() override {
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 fcb1e5af941..df912d05653 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/paint/image_painter.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+#include "third_party/blink/public/mojom/feature_policy/policy_value.mojom-blink.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"
@@ -244,11 +246,10 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
context.DrawImage(
image.get(), decode_mode, FloatRect(pixel_snapped_dest_rect), &src_rect,
+ layout_image_.StyleRef().HasFilterInducingProperty(),
SkBlendMode::kSrcOver,
LayoutObject::ShouldRespectImageOrientation(&layout_image_));
- if (RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_image_.GetDocument()) &&
- (IsHTMLImageElement(node) || IsHTMLVideoElement(node)) &&
+ if ((IsHTMLImageElement(node) || IsHTMLVideoElement(node)) &&
!context.ContextDisabled() && layout_image_.CachedImage() &&
layout_image_.CachedImage()->IsLoaded()) {
LocalDOMWindow* window = layout_image_.GetDocument().domWindow();
@@ -257,12 +258,9 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
&layout_image_, layout_image_.CachedImage(),
context.GetPaintController().CurrentPaintChunkProperties());
}
-
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- PaintTimingDetector::NotifyImagePaint(
- layout_image_, image->Size(), layout_image_.CachedImage(),
- context.GetPaintController().CurrentPaintChunkProperties());
- }
+ PaintTimingDetector::NotifyImagePaint(
+ layout_image_, image->Size(), layout_image_.CachedImage(),
+ context.GetPaintController().CurrentPaintChunkProperties());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
index 938fda8f211..b5e8d4e2095 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
@@ -25,21 +25,17 @@ void InlinePainter::Paint(const PaintInfo& paint_info) {
const auto& local_paint_info = paint_state.GetPaintInfo();
if (local_paint_info.phase == PaintPhase::kForeground &&
- local_paint_info.IsPrinting()) {
+ local_paint_info.ShouldAddUrlMetadata()) {
ObjectPainter(layout_inline_)
- .AddPDFURLRectIfNeeded(local_paint_info, paint_offset);
+ .AddURLRectIfNeeded(local_paint_info, paint_offset);
}
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_inline_.GetDocument())) {
- if (paint_info.phase == PaintPhase::kForeground) {
- scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
- layout_inline_, paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- }
+ if (paint_info.phase == PaintPhase::kForeground) {
+ scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
+ layout_inline_,
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
if (layout_inline_.IsInLayoutNGInlineFormattingContext()) {
@@ -50,7 +46,9 @@ void InlinePainter::Paint(const PaintInfo& paint_info) {
fragment->Offset();
if (fragment->PhysicalFragment().IsText()) {
- NGTextFragmentPainter(*fragment).Paint(paint_info, child_offset);
+ NGTextPainterCursor cursor(*fragment);
+ NGTextFragmentPainter<NGTextPainterCursor>(cursor).Paint(paint_info,
+ child_offset);
} else {
NGInlineBoxFragmentPainter(*fragment).Paint(paint_info, child_offset);
}
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 64c9cd83562..8f5cb403a0f 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
@@ -49,7 +49,8 @@ std::pair<unsigned, unsigned> GetTextMatchMarkerPaintOffsets(
const unsigned text_box_start =
text_box.Start() + text_box.GetLineLayoutItem().TextStartOffset();
- DCHECK_EQ(DocumentMarker::kTextMatch, marker.GetType());
+ DCHECK(marker.GetType() == DocumentMarker::kTextMatch ||
+ marker.GetType() == DocumentMarker::kTextFragment);
const unsigned start_offset = marker.StartOffset() > text_box_start
? marker.StartOffset() - text_box_start
: 0U;
@@ -478,7 +479,8 @@ InlineTextBoxPainter::PaintOffsets InlineTextBoxPainter::MarkerPaintStartAndEnd(
// Text match markers are painted differently (in an inline text box truncated
// by an ellipsis, they paint over the ellipsis) and so should not use this
// function.
- DCHECK_NE(DocumentMarker::kTextMatch, marker.GetType());
+ DCHECK(marker.GetType() != DocumentMarker::kTextMatch &&
+ marker.GetType() != DocumentMarker::kTextFragment);
DCHECK(inline_text_box_.Truncation() != kCFullTruncation);
DCHECK(inline_text_box_.Len());
@@ -594,13 +596,14 @@ void InlineTextBoxPainter::PaintDocumentMarkers(
inline_text_box_.PaintDocumentMarker(paint_info.context, box_origin,
marker, style, font, true);
break;
+ case DocumentMarker::kTextFragment:
case DocumentMarker::kTextMatch:
if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) {
- inline_text_box_.PaintTextMatchMarkerBackground(
- paint_info, box_origin, To<TextMatchMarker>(marker), style, font);
+ inline_text_box_.PaintTextMarkerBackground(
+ paint_info, box_origin, To<TextMarkerBase>(marker), style, font);
} else {
- inline_text_box_.PaintTextMatchMarkerForeground(
- paint_info, box_origin, To<TextMatchMarker>(marker), style, font);
+ inline_text_box_.PaintTextMarkerForeground(
+ paint_info, box_origin, To<TextMarkerBase>(marker), style, font);
}
break;
case DocumentMarker::kComposition:
@@ -825,13 +828,14 @@ void InlineTextBoxPainter::PaintStyleableMarkerUnderline(
inline_text_box_.LogicalHeight());
}
-void InlineTextBoxPainter::PaintTextMatchMarkerForeground(
+void InlineTextBoxPainter::PaintTextMarkerForeground(
const PaintInfo& paint_info,
const LayoutPoint& box_origin,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
const ComputedStyle& style,
const Font& font) {
- if (!InlineLayoutObject()
+ if (marker.GetType() == DocumentMarker::kTextMatch &&
+ !InlineLayoutObject()
.GetFrame()
->GetEditor()
.MarkedTextMatchesAreHighlighted())
@@ -866,13 +870,14 @@ void InlineTextBoxPainter::PaintTextMatchMarkerForeground(
inline_text_box_.Len(), text_style, kInvalidDOMNodeId);
}
-void InlineTextBoxPainter::PaintTextMatchMarkerBackground(
+void InlineTextBoxPainter::PaintTextMarkerBackground(
const PaintInfo& paint_info,
const LayoutPoint& box_origin,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
const ComputedStyle& style,
const Font& font) {
- if (!LineLayoutAPIShim::LayoutObjectFrom(inline_text_box_.GetLineLayoutItem())
+ if (marker.GetType() == DocumentMarker::kTextMatch &&
+ !LineLayoutAPIShim::LayoutObjectFrom(inline_text_box_.GetLineLayoutItem())
->GetFrame()
->GetEditor()
.MarkedTextMatchesAreHighlighted())
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 16fca0d2eeb..23284f73122 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
@@ -23,7 +23,7 @@ class LayoutObject;
class LayoutPoint;
class LayoutTextCombine;
class StyleableMarker;
-class TextMatchMarker;
+class TextMarkerBase;
enum class DocumentMarkerPaintPhase { kForeground, kBackground };
@@ -54,16 +54,16 @@ class InlineTextBoxPainter {
const ComputedStyle&,
const Font&,
bool grammar);
- void PaintTextMatchMarkerForeground(const PaintInfo&,
- const LayoutPoint& box_origin,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&);
- void PaintTextMatchMarkerBackground(const PaintInfo&,
- const LayoutPoint& box_origin,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&);
+ void PaintTextMarkerForeground(const PaintInfo&,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&);
+ void PaintTextMarkerBackground(const PaintInfo&,
+ const LayoutPoint& box_origin,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&);
private:
enum class PaintOptions { kNormal, kCombinedText };
diff --git a/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc b/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
index c2b36fbdbbf..9ef8d87e1c5 100644
--- a/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h"
-
+#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/paint/image_element_timing.h"
namespace blink {
@@ -123,10 +123,12 @@ void LargestContentfulPaintCalculator::UpdateLargestContentfulPaint(
const KURL& url = cached_image->Url();
auto* document = window_performance_->GetExecutionContext();
bool expose_paint_time_to_api = true;
+ bool tainted = false;
if (!url.ProtocolIsData() &&
- (!document || !Performance::PassesTimingAllowCheck(
- cached_image->GetResponse(),
- *document->GetSecurityOrigin(), document))) {
+ (!document ||
+ !Performance::PassesTimingAllowCheck(cached_image->GetResponse(),
+ *document->GetSecurityOrigin(),
+ document, &tainted))) {
expose_paint_time_to_api = false;
}
const String& image_url =
@@ -189,6 +191,9 @@ LargestContentfulPaintCalculator::TextCandidateTraceData() {
value->SetInteger("candidateIndex", ++count_candidates_);
value->SetBoolean("isMainFrame",
window_performance_->GetFrame()->IsMainFrame());
+ auto* document = window_performance_->DomWindow()->document();
+ value->SetString("navigationId",
+ IdentifiersFactory::LoaderId(document->Loader()));
return value;
}
@@ -201,6 +206,10 @@ LargestContentfulPaintCalculator::ImageCandidateTraceData() {
value->SetInteger("candidateIndex", ++count_candidates_);
value->SetBoolean("isMainFrame",
window_performance_->GetFrame()->IsMainFrame());
+ auto* document = window_performance_->DomWindow()->document();
+ value->SetString("navigationId",
+ IdentifiersFactory::LoaderId(document->Loader()));
+
return value;
}
@@ -210,6 +219,10 @@ LargestContentfulPaintCalculator::InvalidationTraceData() {
value->SetInteger("candidateIndex", ++count_candidates_);
value->SetBoolean("isMainFrame",
window_performance_->GetFrame()->IsMainFrame());
+ auto* document = window_performance_->DomWindow()->document();
+ value->SetString("navigationId",
+ IdentifiersFactory::LoaderId(document->Loader()));
+
return value;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h b/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h
index e1b005536b7..72de5f84b10 100644
--- a/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h
+++ b/chromium/third_party/blink/renderer/core/paint/largest_contentful_paint_calculator.h
@@ -15,7 +15,7 @@ namespace blink {
// image paint and the largest text paint and notifying WindowPerformance
// whenever a new LatestLargestContentfulPaint entry should be dispatched.
class CORE_EXPORT LargestContentfulPaintCalculator final
- : public GarbageCollectedFinalized<LargestContentfulPaintCalculator> {
+ : public GarbageCollected<LargestContentfulPaintCalculator> {
public:
explicit LargestContentfulPaintCalculator(WindowPerformance*);
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 6fbc6d27b34..3df1a8f2a29 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
@@ -76,7 +76,7 @@ void BuildBackplate(const InlineFlowBox* box,
} // anonymous namespace
-static void AddPDFURLRectsForInlineChildrenRecursively(
+static void AddURLRectsForInlineChildrenRecursively(
const LayoutObject& layout_object,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
@@ -85,9 +85,8 @@ static void AddPDFURLRectsForInlineChildrenRecursively(
if (!child->IsLayoutInline() ||
ToLayoutBoxModelObject(child)->HasSelfPaintingLayer())
continue;
- ObjectPainter(*child).AddPDFURLRectIfNeeded(paint_info, paint_offset);
- AddPDFURLRectsForInlineChildrenRecursively(*child, paint_info,
- paint_offset);
+ ObjectPainter(*child).AddURLRectIfNeeded(paint_info, paint_offset);
+ AddURLRectsForInlineChildrenRecursively(*child, paint_info, paint_offset);
}
}
@@ -101,9 +100,11 @@ bool LineBoxListPainter::ShouldPaint(const LayoutBoxModelObject& layout_object,
DCHECK(layout_object.IsLayoutBlock() ||
(layout_object.IsLayoutInline() && layout_object.HasLayer()));
- if (paint_info.phase == PaintPhase::kForeground && paint_info.IsPrinting())
- AddPDFURLRectsForInlineChildrenRecursively(layout_object, paint_info,
- paint_offset);
+ if (paint_info.phase == PaintPhase::kForeground &&
+ paint_info.ShouldAddUrlMetadata()) {
+ AddURLRectsForInlineChildrenRecursively(layout_object, paint_info,
+ paint_offset);
+ }
// If we have no lines then we have no work to do.
if (!line_box_list_.First())
@@ -132,14 +133,10 @@ void LineBoxListPainter::Paint(const LayoutBoxModelObject& layout_object,
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_object.GetDocument())) {
- if (paint_info.phase == PaintPhase::kForeground) {
- scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
- layout_object, paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- }
+ if (paint_info.phase == PaintPhase::kForeground) {
+ scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
+ layout_object,
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
// See if our root lines intersect with the dirty rect. If so, then we paint
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 5f3ae417fc5..32d808ae753 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
@@ -28,6 +28,7 @@
#include <memory>
#include <utility>
+#include "base/debug/stack_trace.h"
#include "base/memory/ptr_util.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
@@ -96,10 +97,6 @@ static CompositorElementId NewElementId() {
LinkHighlightImpl::LinkHighlightImpl(Node* node)
: node_(node),
- current_graphics_layer_(nullptr),
- is_scrolling_graphics_layer_(false),
- offset_from_transform_node_(FloatPoint()),
- geometry_needs_update_(false),
is_animating_(false),
start_time_(base::TimeTicks::Now()),
element_id_(NewElementId()) {
@@ -110,11 +107,13 @@ LinkHighlightImpl::LinkHighlightImpl(Node* node)
DCHECK(compositor_animation_);
compositor_animation_->SetAnimationDelegate(this);
compositor_animation_->AttachElement(element_id_);
- geometry_needs_update_ = true;
effect_ = EffectPaintPropertyNode::Create(
EffectPaintPropertyNode::Root(),
LinkHighlightEffectNodeState(kStartOpacity, element_id_));
+
+ SetPaintArtifactCompositorNeedsUpdate();
+
#if DCHECK_IS_ON()
effect_->SetDebugName("LinkHighlightEffect");
#endif
@@ -126,7 +125,6 @@ LinkHighlightImpl::~LinkHighlightImpl() {
compositor_animation_->SetAnimationDelegate(nullptr);
compositor_animation_.reset();
- ClearGraphicsLayerLinkHighlightPointer();
ReleaseResources();
}
@@ -136,162 +134,10 @@ void LinkHighlightImpl::ReleaseResources() {
if (auto* layout_object = node_->GetLayoutObject())
layout_object->SetNeedsPaintPropertyUpdate();
- else
- SetPaintArtifactCompositorNeedsUpdate();
-
- node_.Clear();
-}
-
-void LinkHighlightImpl::AttachLinkHighlightToCompositingLayer(
- const LayoutBoxModelObject& paint_invalidation_container) {
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
-
- GraphicsLayer* new_graphics_layer =
- paint_invalidation_container.Layer()->GraphicsLayerBacking(
- node_->GetLayoutObject());
- is_scrolling_graphics_layer_ = false;
- // FIXME: There should always be a GraphicsLayer. See crbug.com/431961.
- if (paint_invalidation_container.Layer()->NeedsCompositedScrolling() &&
- node_->GetLayoutObject() != &paint_invalidation_container) {
- is_scrolling_graphics_layer_ = true;
- }
- if (!new_graphics_layer) {
- ClearGraphicsLayerLinkHighlightPointer();
- return;
- }
-
- if (current_graphics_layer_ != new_graphics_layer) {
- if (current_graphics_layer_)
- ClearGraphicsLayerLinkHighlightPointer();
-
- current_graphics_layer_ = new_graphics_layer;
- current_graphics_layer_->AddLinkHighlight(this);
- }
-}
-
-static void AddQuadToPath(const FloatQuad& quad, Path& path) {
- // FIXME: Make this create rounded quad-paths, just like the axis-aligned
- // case.
- path.MoveTo(quad.P1());
- path.AddLineTo(quad.P2());
- path.AddLineTo(quad.P3());
- path.AddLineTo(quad.P4());
- path.CloseSubpath();
-}
-
-void LinkHighlightImpl::ComputeQuads(const Node& node,
- Vector<FloatQuad>& out_quads) const {
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
-
- if (!node.GetLayoutObject())
- return;
-
- LayoutObject* layout_object = node.GetLayoutObject();
-
- // For inline elements, absoluteQuads will return a line box based on the
- // line-height and font metrics, which is technically incorrect as replaced
- // elements like images should use their intristic height and expand the
- // linebox as needed. To get an appropriately sized highlight we descend
- // into the children and have them add their boxes.
- if (layout_object->IsLayoutInline()) {
- for (Node* child = LayoutTreeBuilderTraversal::FirstChild(node); child;
- child = LayoutTreeBuilderTraversal::NextSibling(*child))
- ComputeQuads(*child, out_quads);
- } else {
- // FIXME: this does not need to be absolute, just in the paint invalidation
- // container's space.
- layout_object->AbsoluteQuads(out_quads, kTraverseDocumentBoundaries);
- }
-}
-
-bool LinkHighlightImpl::ComputeHighlightLayerPathAndPosition(
- const LayoutBoxModelObject& paint_invalidation_container) {
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
-
- if (!node_ || !node_->GetLayoutObject() || !current_graphics_layer_)
- return false;
-
- // FIXME: This is defensive code to avoid crashes such as those described in
- // crbug.com/440887. This should be cleaned up once we fix the root cause of
- // of the paint invalidation container not being composited.
- if (!paint_invalidation_container.Layer()->GetCompositedLayerMapping() &&
- !paint_invalidation_container.Layer()->GroupedMapping())
- return false;
-
- // Get quads for node in absolute coordinates.
- Vector<FloatQuad> quads;
- ComputeQuads(*node_, quads);
- Path new_path;
-
- for (wtf_size_t quad_index = 0; quad_index < quads.size(); ++quad_index) {
- FloatQuad absolute_quad = quads[quad_index];
-
- // Scrolling content layers have the same offset from layout object as the
- // non-scrolling layers. Thus we need to adjust for their scroll offset.
- if (is_scrolling_graphics_layer_) {
- FloatPoint scroll_position = paint_invalidation_container.Layer()
- ->GetScrollableArea()
- ->ScrollPosition();
- absolute_quad.Move(ToScrollOffset(scroll_position));
- }
-
- absolute_quad.SetP1(FloatPoint(RoundedIntPoint(absolute_quad.P1())));
- absolute_quad.SetP2(FloatPoint(RoundedIntPoint(absolute_quad.P2())));
- absolute_quad.SetP3(FloatPoint(RoundedIntPoint(absolute_quad.P3())));
- absolute_quad.SetP4(FloatPoint(RoundedIntPoint(absolute_quad.P4())));
- FloatQuad transformed_quad =
- paint_invalidation_container.AbsoluteToLocalQuad(
- absolute_quad, kTraverseDocumentBoundaries);
-
- PaintLayer::MapQuadInPaintInvalidationContainerToBacking(
- paint_invalidation_container, transformed_quad);
-
- // Adjust for offset from LayoutObject.
- PhysicalOffset offset_to_backing =
- PhysicalOffset(-current_graphics_layer_->OffsetFromLayoutObject());
-
- transformed_quad.Move(FloatSize(offset_to_backing));
-
- // FIXME: for now, we'll only use rounded paths if we have a single node
- // quad. The reason for this is that we may sometimes get a chain of
- // adjacent boxes (e.g. for text nodes) which end up looking like sausage
- // links: these should ideally be merged into a single rect before creating
- // the path, but that's another CL.
- if (quads.size() == 1 && transformed_quad.IsRectilinear() &&
- !node_->GetDocument()
- .GetSettings()
- ->GetMockGestureTapHighlightsEnabled()) {
- FloatSize rect_rounding_radii(3, 3);
- new_path.AddRoundedRect(transformed_quad.BoundingBox(),
- rect_rounding_radii);
- } else {
- AddQuadToPath(transformed_quad, new_path);
- }
- }
-
- FloatRect bounding_rect = new_path.BoundingRect();
- new_path.Translate(-ToFloatSize(bounding_rect.Location()));
-
- DCHECK_EQ(1u, fragments_.size());
- fragments_[0].SetColor(
- node_->GetLayoutObject()->StyleRef().TapHighlightColor());
- auto* layer = fragments_[0].Layer();
-
- bool path_has_changed = new_path != fragments_[0].GetPath();
- if (path_has_changed) {
- fragments_[0].SetPath(new_path);
- layer->SetBounds(
- static_cast<gfx::Size>(EnclosingIntRect(bounding_rect).Size()));
- }
-
- layer->SetPosition(bounding_rect.Location());
- offset_from_transform_node_ =
- FloatPoint(current_graphics_layer_->GetOffsetFromTransformNode());
- offset_from_transform_node_.MoveBy(bounding_rect.Location());
SetPaintArtifactCompositorNeedsUpdate();
- return path_has_changed;
+ node_.Clear();
}
LinkHighlightImpl::LinkHighlightFragment::LinkHighlightFragment() {
@@ -374,23 +220,11 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
*curve, compositor_target_property::OPACITY, 0, 0);
compositor_animation_->AddKeyframeModel(std::move(keyframe_model));
-
- Invalidate();
-}
-
-void LinkHighlightImpl::ClearGraphicsLayerLinkHighlightPointer() {
- if (current_graphics_layer_) {
- current_graphics_layer_->RemoveLinkHighlight(this);
- current_graphics_layer_ = nullptr;
- }
}
-void LinkHighlightImpl::NotifyAnimationStarted(double, int) {}
-
void LinkHighlightImpl::NotifyAnimationFinished(double, int) {
// Since WebViewImpl may hang on to us for a while, make sure we
// release resources as soon as possible.
- ClearGraphicsLayerLinkHighlightPointer();
ReleaseResources();
// Reset the link highlight opacity to clean up after the animation now that
@@ -398,76 +232,45 @@ void LinkHighlightImpl::NotifyAnimationFinished(double, int) {
UpdateOpacity(kStartOpacity);
}
-void LinkHighlightImpl::UpdateGeometry() {
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
-
+void LinkHighlightImpl::UpdateBeforePrePaint() {
if (!node_ || !node_->GetLayoutObject() ||
- node_->GetLayoutObject()->GetFrameView()->ShouldThrottleRendering()) {
- ClearGraphicsLayerLinkHighlightPointer();
+ node_->GetLayoutObject()->GetFrameView()->ShouldThrottleRendering())
ReleaseResources();
- return;
- }
+}
- // To avoid unnecessary updates (e.g. other entities have requested animations
- // from our WebViewImpl), only proceed if we actually requested an update.
- if (!geometry_needs_update_)
+void LinkHighlightImpl::UpdateAfterPrePaint() {
+ if (!node_)
return;
- geometry_needs_update_ = false;
-
- const LayoutBoxModelObject& paint_invalidation_container =
- node_->GetLayoutObject()->ContainerForPaintInvalidation();
- AttachLinkHighlightToCompositingLayer(paint_invalidation_container);
- if (ComputeHighlightLayerPathAndPosition(paint_invalidation_container)) {
- // We only need to invalidate the layer if the highlight size has changed,
- // otherwise we can just re-position the layer without needing to
- // repaint.
- Layer()->SetNeedsDisplay();
-
- if (current_graphics_layer_) {
- IntRect rect = IntRect(IntPoint(), IntSize(Layer()->bounds()));
- current_graphics_layer_->TrackRasterInvalidation(
- *this, rect, PaintInvalidationReason::kFullLayer);
- }
- }
-}
-
-void LinkHighlightImpl::ClearCurrentGraphicsLayer() {
- current_graphics_layer_ = nullptr;
- geometry_needs_update_ = true;
-}
+ const auto* object = node_->GetLayoutObject();
+ DCHECK(object);
+ DCHECK(!object->GetFrameView()->ShouldThrottleRendering());
-void LinkHighlightImpl::Invalidate() {
- // Make sure we update geometry on the next callback from
- // WebViewImpl::layout().
- geometry_needs_update_ = true;
-}
+ size_t fragment_count = 0;
+ for (const auto* fragment = &object->FirstFragment(); fragment;
+ fragment = fragment->NextFragment())
+ ++fragment_count;
-cc::Layer* LinkHighlightImpl::Layer() {
- DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- DCHECK_EQ(1u, fragments_.size());
- return fragments_[0].Layer();
+ if (fragment_count != fragments_.size()) {
+ fragments_.resize(fragment_count);
+ SetPaintArtifactCompositorNeedsUpdate();
+ }
}
CompositorAnimation* LinkHighlightImpl::GetCompositorAnimation() const {
return compositor_animation_.get();
}
-const EffectPaintPropertyNode& LinkHighlightImpl::Effect() const {
- return *effect_;
-}
-
void LinkHighlightImpl::Paint(GraphicsContext& context) {
- DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
- if (!node_ || !node_->GetLayoutObject() ||
- node_->GetLayoutObject()->GetFrameView()->ShouldThrottleRendering()) {
- ReleaseResources();
+ if (!node_)
return;
- }
const auto* object = node_->GetLayoutObject();
+ DCHECK(object);
+ DCHECK(!object->GetFrameView()->ShouldThrottleRendering());
+
static const FloatSize rect_rounding_radii(3, 3);
- auto color = node_->GetLayoutObject()->StyleRef().TapHighlightColor();
+ auto color = object->StyleRef().TapHighlightColor();
// For now, we'll only use rounded rects if we have a single rect because
// otherwise we may sometimes get a chain of adjacent boxes (e.g. for text
@@ -495,13 +298,7 @@ void LinkHighlightImpl::Paint(GraphicsContext& context) {
new_path.AddRect(snapped_rect);
}
- if (index == fragments_.size()) {
- fragments_.emplace_back();
- // PaintArtifactCompositor needs update for the new cc::PictureLayer we
- // just created for the fragment.
- SetPaintArtifactCompositorNeedsUpdate();
- }
-
+ DCHECK_LT(index, fragments_.size());
auto& link_highlight_fragment = fragments_[index];
link_highlight_fragment.SetColor(color);
@@ -521,21 +318,15 @@ void LinkHighlightImpl::Paint(GraphicsContext& context) {
bounding_rect.Location(), property_tree_state);
}
- if (index < fragments_.size()) {
- fragments_.Shrink(index);
- // PaintArtifactCompositor needs update for the cc::PictureLayers we just
- // removed for the extra fragments.
- SetPaintArtifactCompositorNeedsUpdate();
- }
+ DCHECK_EQ(index, fragments_.size());
}
void LinkHighlightImpl::SetPaintArtifactCompositorNeedsUpdate() {
DCHECK(node_);
if (auto* frame_view = node_->GetDocument().View()) {
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- frame_view->SetPaintArtifactCompositorNeedsUpdate();
- else
- frame_view->GraphicsLayersDidChange();
+ frame_view->SetPaintArtifactCompositorNeedsUpdate();
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
+ frame_view->SetForeignLayerListNeedsUpdate();
}
}
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 8e751591b73..7d32caec420 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
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.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/link_highlight.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -47,13 +46,11 @@ class PictureLayer;
namespace blink {
+class EffectPaintPropertyNode;
class GraphicsContext;
-class GraphicsLayer;
-class LayoutBoxModelObject;
class Node;
-class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
- public CompositorAnimationDelegate,
+class CORE_EXPORT LinkHighlightImpl final : public CompositorAnimationDelegate,
public CompositorAnimationClient {
public:
explicit LinkHighlightImpl(Node*);
@@ -61,38 +58,22 @@ class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
void StartHighlightAnimationIfNeeded();
- // Recalculates |path_| based on |node_|'s geometry and updates the link
- // highlight layer. To avoid re-computing |path_|, a dirty bit is used
- // (see |geometry_needs_update_| and |Invalidate()|) which is based on raster
- // invalidation of the owning graphics layer.
- void UpdateGeometry();
-
// CompositorAnimationDelegate implementation.
- void NotifyAnimationStarted(double monotonic_time, int group) override;
+ void NotifyAnimationStarted(double monotonic_time, int group) override {}
void NotifyAnimationFinished(double monotonic_time, int group) override;
void NotifyAnimationAborted(double monotonic_time, int group) override {}
- // LinkHighlight implementation.
- void Invalidate() override;
- cc::Layer* Layer() override;
- void ClearCurrentGraphicsLayer() override;
- FloatPoint GetOffsetFromTransformNode() const override {
- return offset_from_transform_node_;
- }
-
// CompositorAnimationClient implementation.
CompositorAnimation* GetCompositorAnimation() const override;
- GraphicsLayer* CurrentGraphicsLayerForTesting() const {
- return current_graphics_layer_;
- }
-
Node* GetNode() const { return node_; }
CompositorElementId ElementIdForTesting() const { return element_id_; }
- const EffectPaintPropertyNode& Effect() const override;
+ const EffectPaintPropertyNode& Effect() const { return *effect_; }
+ void UpdateBeforePrePaint();
+ void UpdateAfterPrePaint();
void Paint(GraphicsContext&);
wtf_size_t FragmentCountForTesting() const { return fragments_.size(); }
@@ -101,18 +82,7 @@ class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
}
private:
- // TODO(crbug.com/967281): These NOINLINEs are for more accurate crash stack
- // in the crash reports.
- NOINLINE void ReleaseResources();
- NOINLINE void ComputeQuads(const Node&, Vector<FloatQuad>&) const;
-
- NOINLINE void AttachLinkHighlightToCompositingLayer(
- const LayoutBoxModelObject& paint_invalidation_container);
- NOINLINE void ClearGraphicsLayerLinkHighlightPointer();
- // This function computes the highlight path, and returns true if it has
- // changed size since the last call to this function.
- NOINLINE bool ComputeHighlightLayerPathAndPosition(
- const LayoutBoxModelObject&);
+ void ReleaseResources();
void SetPaintArtifactCompositorNeedsUpdate();
void UpdateOpacity(float opacity);
@@ -142,13 +112,9 @@ class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
Vector<LinkHighlightFragment> fragments_;
Persistent<Node> node_;
- GraphicsLayer* current_graphics_layer_;
- bool is_scrolling_graphics_layer_;
std::unique_ptr<CompositorAnimation> compositor_animation_;
scoped_refptr<EffectPaintPropertyNode> effect_;
- FloatPoint offset_from_transform_node_;
- bool geometry_needs_update_;
bool is_animating_;
base::TimeTicks start_time_;
CompositorElementId element_id_;
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
index 13405ba131e..575b45f83ee 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -41,11 +41,11 @@
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -112,6 +112,21 @@ class LinkHighlightImplTest : public testing::Test,
WebWidget::LifecycleUpdateReason::kTest);
}
+ LinkHighlight& GetLinkHighlight() {
+ return web_view_helper_.GetWebView()->GetPage()->GetLinkHighlight();
+ }
+
+ LinkHighlightImpl* GetLinkHighlightImpl() {
+ return GetLinkHighlight().impl_.get();
+ }
+
+ cc::AnimationHost* GetAnimationHost() {
+ EXPECT_EQ(
+ GetLinkHighlight().timeline_->GetAnimationTimeline()->animation_host(),
+ GetLinkHighlight().animation_host_);
+ return GetLinkHighlight().animation_host_;
+ }
+
frame_test_helpers::WebViewHelper web_view_helper_;
};
@@ -142,32 +157,28 @@ TEST_P(LinkHighlightImplTest, verifyWebViewImplIntegration) {
// Shouldn't crash.
web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
- const auto& highlights =
- web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
- EXPECT_TRUE(highlights.at(0));
- EXPECT_EQ(1u, highlights.at(0)->FragmentCountForTesting());
- EXPECT_TRUE(highlights.at(0)->LayerForTesting(0));
+ const auto* highlight = GetLinkHighlightImpl();
+ EXPECT_TRUE(highlight);
+ EXPECT_EQ(1u, highlight->FragmentCountForTesting());
+ EXPECT_TRUE(highlight->LayerForTesting(0));
// Find a target inside a scrollable div
touch_event.SetPositionInWidget(WebFloatPoint(20, 100));
web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
- ASSERT_TRUE(highlights.at(0));
+ ASSERT_TRUE(highlight);
// Enesure the timeline was added to a host.
- EXPECT_TRUE(!!web_view_impl->GetPage()
- ->GetLinkHighlights()
- .timeline_->GetAnimationTimeline()
- ->animation_host());
+ EXPECT_TRUE(GetAnimationHost());
// Don't highlight if no "hand cursor"
touch_event.SetPositionInWidget(
WebFloatPoint(20, 220)); // An A-link with cross-hair cursor.
web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
- ASSERT_EQ(0U, highlights.size());
+ EXPECT_FALSE(GetLinkHighlightImpl());
touch_event.SetPositionInWidget(WebFloatPoint(20, 260)); // A text input box.
web_view_impl->EnableTapHighlightAtPoint(GetTargetedEvent(touch_event));
- ASSERT_EQ(0U, highlights.size());
+ EXPECT_FALSE(GetLinkHighlightImpl());
}
TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
@@ -189,31 +200,16 @@ TEST_P(LinkHighlightImplTest, resetDuringNodeRemoval) {
ASSERT_TRUE(touch_node);
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- const auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
- ASSERT_EQ(1u, highlights.link_highlights_.size());
- ASSERT_TRUE(highlights.link_highlights_.at(0));
- EXPECT_EQ(touch_node, highlights.link_highlights_.at(0)->GetNode());
-
- GraphicsLayer* highlight_layer;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- highlight_layer =
- highlights.link_highlights_.at(0)->CurrentGraphicsLayerForTesting();
- ASSERT_TRUE(highlight_layer);
- EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0));
- }
+ const auto* highlight = GetLinkHighlightImpl();
+ ASSERT_TRUE(highlight);
+ EXPECT_EQ(touch_node, highlight->GetNode());
touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
UpdateAllLifecyclePhases();
- ASSERT_EQ(1u, highlights.link_highlights_.size());
- ASSERT_TRUE(highlights.link_highlights_.at(0));
- EXPECT_FALSE(highlights.link_highlights_.at(0)->GetNode());
-
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- EXPECT_EQ(0U, highlight_layer->GetLinkHighlights().size());
- EXPECT_FALSE(
- highlights.link_highlights_.at(0)->CurrentGraphicsLayerForTesting());
- }
+ ASSERT_EQ(highlight, GetLinkHighlightImpl());
+ ASSERT_TRUE(highlight);
+ EXPECT_FALSE(highlight->GetNode());
}
// A lifetime test: delete LayerTreeView while running LinkHighlights.
@@ -236,56 +232,7 @@ TEST_P(LinkHighlightImplTest, resetLayerTreeView) {
ASSERT_TRUE(touch_node);
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- const auto& highlights =
- web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
- ASSERT_TRUE(highlights.at(0));
-
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- GraphicsLayer* highlight_layer =
- highlights.at(0)->CurrentGraphicsLayerForTesting();
- ASSERT_TRUE(highlight_layer);
- EXPECT_TRUE(highlight_layer->GetLinkHighlights().at(0));
- }
-}
-
-TEST_P(LinkHighlightImplTest, HighlightInvalidation) {
- // This test requires GraphicsLayers which are not used in
- // CompositeAfterPaint.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
- WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
- web_view_impl->MainFrameWidget()->Resize(WebSize(640, 480));
- UpdateAllLifecyclePhases();
-
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
- WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- WebGestureDevice::kTouchscreen);
- touch_event.SetPositionInWidget(WebFloatPoint(20, 20));
- GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
- auto* touch_element = To<Element>(web_view_impl->BestTapNode(targeted_event));
- web_view_impl->EnableTapHighlightAtPoint(targeted_event);
-
- web_view_helper_.LocalMainFrame()
- ->GetFrameView()
- ->SetTracksPaintInvalidations(true);
-
- // Change the touched element's height to 12px.
- auto& style = touch_element->getAttribute(html_names::kStyleAttr);
- StringBuilder new_style;
- new_style.Append(style.GetString());
- new_style.Append("height: 12px;");
- touch_element->setAttribute(html_names::kStyleAttr,
- new_style.ToAtomicString());
- UpdateAllLifecyclePhases();
-
- const auto& highlights =
- web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
- auto* highlight_layer = highlights.at(0)->CurrentGraphicsLayerForTesting();
- const auto* tracking = highlight_layer->GetRasterInvalidationTracking();
- // The invalidation rect should fully cover the layer.
- EXPECT_EQ(tracking->Invalidations().back().rect, IntRect(0, 0, 200, 12));
+ ASSERT_TRUE(GetLinkHighlightImpl());
}
TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
@@ -314,8 +261,7 @@ TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
// The highlight should create one additional layer.
EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount());
- auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
- auto* highlight = highlights.link_highlights_.at(0).get();
+ const auto* highlight = GetLinkHighlightImpl();
ASSERT_TRUE(highlight);
// Check that the link highlight cc layer has a cc effect property tree node.
@@ -342,7 +288,7 @@ TEST_P(LinkHighlightImplTest, HighlightLayerEffectNode) {
// After starting the highlight animation the effect node's opacity should
// be 0.f as it will be overridden bt the animation but may become visible
// before the animation is destructed. See https://crbug.com/974160
- highlights.StartHighlightAnimationIfNeeded();
+ GetLinkHighlight().StartHighlightAnimationIfNeeded();
EXPECT_EQ(0.f, highlight->Effect().Opacity());
EXPECT_TRUE(highlight->Effect().HasActiveOpacityAnimation());
@@ -378,10 +324,7 @@ TEST_P(LinkHighlightImplTest, MultiColumn) {
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- const auto& highlights =
- web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
- EXPECT_EQ(1u, highlights.size());
- const auto* highlight = highlights.at(0).get();
+ const auto* highlight = GetLinkHighlightImpl();
ASSERT_TRUE(highlight);
// The link highlight cc effect node should correspond to the blink effect
@@ -405,124 +348,43 @@ TEST_P(LinkHighlightImplTest, MultiColumn) {
[highlight->ElementIdForTesting()]);
};
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // The highlight should create 2 additional layer, each for each fragment.
- EXPECT_EQ(layer_count_before_highlight + 2, ContentLayerCount());
- EXPECT_EQ(2u, highlight->FragmentCountForTesting());
- check_layer(highlight->LayerForTesting(0));
- check_layer(highlight->LayerForTesting(1));
- } else {
- // The highlight should create 1 additional layer covering both fragments.
- EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount());
- EXPECT_EQ(1u, highlight->FragmentCountForTesting());
- check_layer(highlight->LayerForTesting(0));
- }
+ // The highlight should create 2 additional layer, each for each fragment.
+ EXPECT_EQ(layer_count_before_highlight + 2, ContentLayerCount());
+ EXPECT_EQ(2u, highlight->FragmentCountForTesting());
+ check_layer(highlight->LayerForTesting(0));
+ check_layer(highlight->LayerForTesting(1));
- touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
+ Element* multicol = touch_node->parentElement();
+ EXPECT_EQ(50, multicol->OffsetHeight());
+ // Make multicol shorter to create 3 total columns for touch_node.
+ multicol->setAttribute(html_names::kStyleAttr, "height: 25px");
UpdateAllLifecyclePhases();
- // Removing the highlight layer should drop the cc layers for highlights.
- EXPECT_EQ(layer_count_before_highlight, ContentLayerCount());
-}
-
-class LinkHighlightSquashingImplTest : public testing::Test,
- public PaintTestConfigurations {
- protected:
- GestureEventWithHitTestResults GetTargetedEvent(
- WebGestureEvent& touch_event) {
- WebGestureEvent scaled_event = TransformWebGestureEvent(
- web_view_helper_.GetWebView()->MainFrameImpl()->GetFrameView(),
- touch_event);
- return web_view_helper_.GetWebView()
- ->GetPage()
- ->DeprecatedLocalMainFrame()
- ->GetEventHandler()
- .TargetGestureEvent(scaled_event, true);
- }
-
- void SetUp() override {
- // TODO(crbug.com/751425): We should use the mock functionality
- // via |web_view_helper_|.
- WebURL url = url_test_helpers::RegisterMockedURLLoadFromBase(
- WebString::FromUTF8("http://www.test.com/"), test::CoreTestDataPath(),
- WebString::FromUTF8("test_touch_link_highlight_squashing.html"));
- web_view_helper_.InitializeAndLoad(url.GetString().Utf8());
- }
-
- void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
-
- // Ensure we fully clean up while scoped settings are enabled. Without this,
- // garbage collection would occur after Scoped[setting]ForTest is out of
- // scope, so the settings would not apply in some destructors.
- web_view_helper_.Reset();
- ThreadState::Current()->CollectAllGarbageForTesting();
- }
-
- size_t ContentLayerCount() {
- // paint_artifact_compositor()->EnableExtraDataForTesting() should be called
- // before using this function.
- DCHECK(paint_artifact_compositor()->GetExtraDataForTesting());
- return paint_artifact_compositor()
- ->GetExtraDataForTesting()
- ->content_layers.size();
- }
-
- PaintArtifactCompositor* paint_artifact_compositor() {
- auto* local_frame_view = web_view_helper_.LocalMainFrame()->GetFrameView();
- return local_frame_view->GetPaintArtifactCompositor();
- }
-
- void UpdateAllLifecyclePhases() {
- web_view_helper_.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
- WebWidget::LifecycleUpdateReason::kTest);
- }
-
- frame_test_helpers::WebViewHelper web_view_helper_;
-};
-
-INSTANTIATE_PAINT_TEST_SUITE_P(LinkHighlightSquashingImplTest);
-
-TEST_P(LinkHighlightSquashingImplTest, SquashingLayer) {
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
- return;
-
- bool was_running_web_test = WebTestSupport::IsRunningWebTest();
- WebTestSupport::SetIsRunningWebTest(false);
- int page_width = 640;
- int page_height = 480;
- WebViewImpl* web_view_impl = web_view_helper_.GetWebView();
- web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height));
-
- paint_artifact_compositor()->EnableExtraDataForTesting();
+ ASSERT_EQ(&first_fragment, &touch_node->GetLayoutObject()->FirstFragment());
+ ASSERT_EQ(second_fragment, first_fragment.NextFragment());
+ const auto* third_fragment = second_fragment->NextFragment();
+ ASSERT_TRUE(third_fragment);
+ EXPECT_FALSE(third_fragment->NextFragment());
+
+ EXPECT_EQ(layer_count_before_highlight + 3, ContentLayerCount());
+ EXPECT_EQ(3u, highlight->FragmentCountForTesting());
+ check_layer(highlight->LayerForTesting(0));
+ check_layer(highlight->LayerForTesting(1));
+ check_layer(highlight->LayerForTesting(2));
+
+ // Make multicol taller to create only 1 column for touch_node.
+ multicol->setAttribute(html_names::kStyleAttr, "height: 100px");
UpdateAllLifecyclePhases();
- size_t layer_count_before_highlight = ContentLayerCount();
- WebGestureEvent touch_event(WebInputEvent::kGestureShowPress,
- WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- WebGestureDevice::kTouchscreen);
- touch_event.SetPositionInWidget(WebFloatPoint(100, 100));
-
- GestureEventWithHitTestResults targeted_event = GetTargetedEvent(touch_event);
- Node* touch_node = web_view_impl->BestTapNode(targeted_event);
- ASSERT_TRUE(touch_node);
+ ASSERT_EQ(&first_fragment, &touch_node->GetLayoutObject()->FirstFragment());
+ EXPECT_FALSE(first_fragment.NextFragment());
- web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- // The highlight should create one additional layer.
EXPECT_EQ(layer_count_before_highlight + 1, ContentLayerCount());
-
- auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
- auto* highlight = highlights.link_highlights_.at(0).get();
- ASSERT_TRUE(highlight);
-
- // Check that the link highlight cc layer has a cc effect property tree node.
EXPECT_EQ(1u, highlight->FragmentCountForTesting());
- auto* layer = highlight->LayerForTesting(0);
-
- EXPECT_EQ(gfx::Size(256, 256), layer->bounds());
+ check_layer(highlight->LayerForTesting(0));
- WebTestSupport::SetIsRunningWebTest(was_running_web_test);
+ touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
+ UpdateAllLifecyclePhases();
+ // Removing the highlight layer should drop the cc layers for highlights.
+ EXPECT_EQ(layer_count_before_highlight, ContentLayerCount());
}
} // namespace blink
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 5c2c56f4733..3d0509ef618 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
@@ -155,6 +155,13 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info) {
text_run.SetText(reversed_text.ToString());
}
+ if (style_category == LayoutListMarker::ListStyleCategory::kStaticString) {
+ // Don't add a suffix.
+ context.DrawText(font, text_run_paint_info, text_origin, kInvalidDOMNodeId);
+ context.GetPaintController().SetTextPainted();
+ return;
+ }
+
const UChar suffix =
list_marker_text::Suffix(layout_list_marker_.StyleRef().ListStyleType(),
layout_list_marker_.ListItem()->Value());
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 a33bba1354a..c5825ef4e94 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
@@ -276,8 +276,6 @@ void NGBoxFragmentPainter::PaintInternal(const PaintInfo& paint_info) {
void NGBoxFragmentPainter::RecordScrollHitTestData(
const PaintInfo& paint_info,
const DisplayItemClient& background_client) {
- DCHECK(RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
-
// Hit test display items are only needed for compositing. This flag is used
// for for printing and drag images which do not need hit testing.
if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
@@ -290,9 +288,8 @@ void NGBoxFragmentPainter::RecordScrollHitTestData(
// Only create scroll hit test data for objects that scroll.
const auto* layer = PhysicalFragment().Layer();
if (!layer || !layer->GetScrollableArea() ||
- !layer->GetScrollableArea()->ScrollsOverflow()) {
+ !layer->GetScrollableArea()->ScrollsOverflow())
return;
- }
// TODO(pdr): Break dependency on LayoutObject functionality.
const LayoutObject& layout_object = *box_fragment_.GetLayoutObject();
@@ -345,12 +342,15 @@ void NGBoxFragmentPainter::PaintObject(
return;
}
- if (paint_phase == PaintPhase::kMask && is_visible)
- return PaintMask(paint_info, paint_offset);
+ if (paint_phase == PaintPhase::kMask && is_visible) {
+ PaintMask(paint_info, paint_offset);
+ return;
+ }
- if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting()) {
+ if (paint_phase == PaintPhase::kForeground &&
+ paint_info.ShouldAddUrlMetadata()) {
NGFragmentPainter(box_fragment_, paint_fragment_)
- .AddPDFURLRectIfNeeded(paint_info, paint_offset);
+ .AddURLRectIfNeeded(paint_info, paint_offset);
}
if (paint_phase != PaintPhase::kSelfOutlineOnly &&
@@ -380,15 +380,13 @@ void NGBoxFragmentPainter::PaintObject(
PaintFloats(paint_info);
}
} else {
- if (paint_phase != PaintPhase::kFloat) {
+ if (paint_phase != PaintPhase::kFloat)
PaintBlockChildren(paint_info);
- }
if (paint_phase == PaintPhase::kFloat ||
paint_phase == PaintPhase::kSelection ||
- paint_phase == PaintPhase::kTextClip) {
+ paint_phase == PaintPhase::kTextClip)
PaintFloats(paint_info);
- }
}
}
@@ -506,6 +504,27 @@ void NGBoxFragmentPainter::PaintInlineFloatingChildren(
}
}
+void NGBoxFragmentPainter::PaintFloatingItems(const PaintInfo& paint_info) {
+ DCHECK(items_);
+ DCHECK(PhysicalFragment().HasFloatingDescendants());
+
+ for (const std::unique_ptr<NGFragmentItem>& item : items_->Items()) {
+ const NGPhysicalBoxFragment* child_fragment = item->BoxFragment();
+ if (!child_fragment || child_fragment->HasSelfPaintingLayer() ||
+ !child_fragment->IsFloating())
+ continue;
+ // TODO(kojii): The float is outside of the inline formatting context and
+ // that it maybe another NG inline formatting context, NG block layout, or
+ // legacy. NGBoxFragmentPainter can handle only the first case. In order
+ // to cover more tests for other two cases, we always fallback to legacy,
+ // which will forward back to NGBoxFragmentPainter if the float is for
+ // NGBoxFragmentPainter. We can shortcut this for the first case when
+ // we're more stable.
+ ObjectPainter(*child_fragment->GetLayoutObject())
+ .PaintAllPhasesAtomically(paint_info);
+ }
+}
+
void NGBoxFragmentPainter::PaintBlockFloatingChildren(
const NGPhysicalContainerFragment& container,
const PaintInfo& paint_info) {
@@ -526,9 +545,8 @@ void NGBoxFragmentPainter::PaintBlockFloatingChildren(
continue;
}
if (const auto* child_container =
- DynamicTo<NGPhysicalContainerFragment>(&child_fragment)) {
+ DynamicTo<NGPhysicalContainerFragment>(&child_fragment))
PaintBlockFloatingChildren(*child_container, paint_info);
- }
}
}
@@ -543,6 +561,10 @@ void NGBoxFragmentPainter::PaintFloats(const PaintInfo& paint_info) {
PaintInlineFloatingChildren(paint_fragment_->Children(), float_paint_info);
return;
}
+ if (items_) {
+ PaintFloatingItems(float_paint_info);
+ return;
+ }
PaintBlockFloatingChildren(PhysicalFragment(), float_paint_info);
}
@@ -629,28 +651,26 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
PhysicalFragment().EffectiveAllowedTouchAction()));
}
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- bool needs_scroll_hit_test = true;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
- // display items for composited scrollers because these display items are
- // only used to create non-fast scrollable regions for non-composited
- // scrollers. With CompositeAfterPaint, we always paint the scroll hit
- // test display items but ignore the non-fast region if the scroll was
- // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
- const auto* layer = PhysicalFragment().Layer();
- if (layer && layer->GetCompositedLayerMapping() &&
- layer->GetCompositedLayerMapping()->HasScrollingLayer()) {
- needs_scroll_hit_test = false;
- }
+ bool needs_scroll_hit_test = true;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
+ // display items for composited scrollers because these display items are
+ // only used to create non-fast scrollable regions for non-composited
+ // scrollers. With CompositeAfterPaint, we always paint the scroll hit
+ // test display items but ignore the non-fast region if the scroll was
+ // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
+ const auto* layer = PhysicalFragment().Layer();
+ if (layer && layer->GetCompositedLayerMapping() &&
+ layer->GetCompositedLayerMapping()->HasScrollingLayer()) {
+ needs_scroll_hit_test = false;
}
-
- // Record the scroll hit test after the non-scrolling background so
- // background squashing is not affected. Hit test order would be equivalent
- // if this were immediately before the non-scrolling background.
- if (!painting_scrolling_background && needs_scroll_hit_test)
- RecordScrollHitTestData(paint_info, *background_client);
}
+
+ // Record the scroll hit test after the non-scrolling background so
+ // background squashing is not affected. Hit test order would be equivalent
+ // if this were immediately before the non-scrolling background.
+ if (!painting_scrolling_background && needs_scroll_hit_test)
+ RecordScrollHitTestData(paint_info, *background_client);
}
// TODO(kojii): This logic is kept in sync with BoxPainter. Not much efforts to
@@ -767,13 +787,25 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackgroundWithRect(
}
if (box_decoration_data.ShouldPaintShadow()) {
- PaintInsetBoxShadowWithBorderRect(paint_info, paint_rect, style,
- border_edges.line_left,
- border_edges.line_right);
+ if (layout_box.IsTableCell()) {
+ PhysicalRect inner_rect = paint_rect;
+ inner_rect.Contract(layout_box.BorderBoxOutsets());
+ // PaintInsetBoxShadowWithInnerRect doesn't subtract borders before
+ // painting. We have to use it here after subtracting collapsed borders
+ // above. PaintInsetBoxShadowWithBorderRect below subtracts the borders
+ // specified on the style object, which doesn't account for border
+ // collapsing.
+ BoxPainterBase::PaintInsetBoxShadowWithInnerRect(paint_info, inner_rect,
+ style);
+ } else {
+ PaintInsetBoxShadowWithBorderRect(paint_info, paint_rect, style,
+ border_edges.line_left,
+ border_edges.line_right);
+ }
}
- // The theme will tell us whether or not we should also paint the CSS
- // border.
+ // The theme will tell us whether or not we should also paint the CSS
+ // border.
if (box_decoration_data.ShouldPaintBorder()) {
if (!theme_painted) {
theme_painted =
@@ -885,7 +917,7 @@ void NGBoxFragmentPainter::PaintInlineItems(
DCHECK(item);
switch (item->Type()) {
case NGFragmentItem::kText:
- PaintTextItem(*item, paint_info, paint_offset);
+ PaintTextItem(cursor, paint_info, paint_offset);
break;
case NGFragmentItem::kGeneratedText:
// TODO(kojii): Implement.
@@ -934,14 +966,10 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
const auto& layout_block = To<LayoutBlock>(*layout_object);
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_block.GetDocument())) {
- if (paint_info.phase == PaintPhase::kForeground) {
- scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
- layout_block, paint_info.context.GetPaintController()
- .CurrentPaintChunkProperties());
- }
+ if (paint_info.phase == PaintPhase::kForeground) {
+ scoped_paint_timing_detector_block_paint_hook.EmplaceIfNeeded(
+ layout_block,
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
if (paint_info.phase == PaintPhase::kForcedColorsModeBackplate &&
@@ -1094,14 +1122,15 @@ void NGBoxFragmentPainter::PaintTextChild(const NGPaintFragment& paint_fragment,
paint_info.phase != PaintPhase::kMask)
return;
- NGTextFragmentPainter text_painter(paint_fragment);
+ NGTextPainterCursor cursor(paint_fragment);
+ NGTextFragmentPainter<NGTextPainterCursor> text_painter(cursor);
text_painter.Paint(paint_info, paint_offset);
}
-void NGBoxFragmentPainter::PaintTextItem(const NGFragmentItem& item,
+void NGBoxFragmentPainter::PaintTextItem(const NGInlineCursor& cursor,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
- DCHECK_EQ(item.Type(), NGFragmentItem::kText);
+ DCHECK_EQ(cursor.CurrentItem()->Type(), NGFragmentItem::kText);
DCHECK(items_);
// Only paint during the foreground/selection phases.
@@ -1111,7 +1140,7 @@ void NGBoxFragmentPainter::PaintTextItem(const NGFragmentItem& item,
paint_info.phase != PaintPhase::kMask)
return;
- NGTextFragmentPainter text_painter(item, *items_);
+ NGTextFragmentPainter<NGInlineCursor> text_painter(cursor);
text_painter.Paint(paint_info, paint_offset);
}
@@ -1143,8 +1172,8 @@ NGBoxFragmentPainter::MoveTo NGBoxFragmentPainter::PaintBoxItem(
return kDontSkipChildren;
}
- // TODO(kojii): Implement.
- // NGInlineBoxFragmentPainter(*child).Paint(paint_info, paint_offset);
+ NGInlineBoxFragmentPainter(item, *child_fragment)
+ .Paint(paint_info, paint_offset);
return kDontSkipChildren;
}
@@ -1181,8 +1210,7 @@ bool NGBoxFragmentPainter::ShouldPaint(
const NGPhysicalBoxFragment& fragment = PhysicalFragment();
if (!fragment.IsInlineBox()) {
return paint_state.LocalRectIntersectsCullRect(
- ToLayoutBox(fragment.GetLayoutObject())
- ->PhysicalSelfVisualOverflowRect());
+ ToLayoutBox(fragment.GetLayoutObject())->PhysicalVisualOverflowRect());
}
NOTREACHED();
return false;
@@ -1242,6 +1270,8 @@ PhysicalRect NGBoxFragmentPainter::AdjustRectForScrolledContent(
}
LayoutRectOutsets NGBoxFragmentPainter::ComputeBorders() const {
+ if (box_fragment_.GetLayoutObject()->IsTableCell())
+ return ToLayoutBox(box_fragment_.GetLayoutObject())->BorderBoxOutsets();
return BoxStrutToLayoutRectOutsets(PhysicalFragment().BorderWidths());
}
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 6675bb4c57b..3eca53d29b5 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
@@ -22,6 +22,7 @@ class HitTestLocation;
class HitTestRequest;
class HitTestResult;
class NGFragmentItems;
+class NGInlineCursor;
class NGPhysicalFragment;
class ScopedPaintState;
struct PaintInfo;
@@ -101,7 +102,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintTextChild(const NGPaintFragment&,
const PaintInfo&,
const PhysicalOffset& paint_offset);
- void PaintTextItem(const NGFragmentItem& item,
+ void PaintTextItem(const NGInlineCursor& cursor,
const PaintInfo&,
const PhysicalOffset& paint_offset);
MoveTo PaintBoxItem(const NGFragmentItem& item,
@@ -109,6 +110,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const PhysicalOffset& paint_offset);
void PaintInlineFloatingChildren(NGPaintFragment::ChildList,
const PaintInfo&);
+ void PaintFloatingItems(const PaintInfo&);
void PaintBlockFloatingChildren(const NGPhysicalContainerFragment&,
const PaintInfo&);
void PaintFloats(const PaintInfo&);
@@ -208,8 +210,8 @@ inline NGBoxFragmentPainter::NGBoxFragmentPainter(
DCHECK(box.IsBox() || box.IsRenderedLegend());
#if DCHECK_IS_ON()
if (box.IsInlineBox()) {
- DCHECK(paint_fragment);
- DCHECK_EQ(&paint_fragment->PhysicalFragment(), &box);
+ if (paint_fragment)
+ DCHECK_EQ(&paint_fragment->PhysicalFragment(), &box);
} else if (box.ChildrenInline()) {
// If no children, there maybe or may not be NGPaintFragment.
// TODO(kojii): To be investigated if this correct or should be fixed.
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 657e70bc43f..3fcbfa66af4 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
@@ -21,31 +21,29 @@ void NGFragmentPainter::PaintOutline(const PaintInfo& paint_info,
if (!NGOutlineUtils::HasPaintedOutline(fragment.Style(), fragment.GetNode()))
return;
- // TODO(kojii): Eliminate paint_fragment_ if this is used for block-children
- if (!paint_fragment_)
- return;
-
Vector<PhysicalRect> outline_rects;
- paint_fragment_->AddSelfOutlineRects(
- &outline_rects, paint_offset,
+ fragment.AddSelfOutlineRects(
+ paint_offset,
fragment.GetLayoutObject()
- ->OutlineRectsShouldIncludeBlockVisualOverflow());
+ ->OutlineRectsShouldIncludeBlockVisualOverflow(),
+ &outline_rects);
+
if (outline_rects.IsEmpty())
return;
+ const DisplayItemClient& display_item_client = GetDisplayItemClient();
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, *paint_fragment_, paint_info.phase))
+ paint_info.context, display_item_client, paint_info.phase))
return;
- DrawingRecorder recorder(paint_info.context, *paint_fragment_,
+ DrawingRecorder recorder(paint_info.context, display_item_client,
paint_info.phase);
PaintOutlineRects(paint_info, outline_rects, fragment.Style());
}
-void NGFragmentPainter::AddPDFURLRectIfNeeded(
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- DCHECK(paint_info.IsPrinting());
+void NGFragmentPainter::AddURLRectIfNeeded(const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ DCHECK(paint_info.ShouldAddUrlMetadata());
// TODO(layout-dev): Should use break token when NG has its own tree building.
const NGPhysicalBoxFragment& fragment = PhysicalFragment();
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 f446c98780b..5d7cee1a9ed 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
@@ -27,8 +27,7 @@ class NGFragmentPainter : public ObjectPainterBase {
void PaintOutline(const PaintInfo&, const PhysicalOffset& paint_offset);
- void AddPDFURLRectIfNeeded(const PaintInfo&,
- const PhysicalOffset& paint_offset);
+ void AddURLRectIfNeeded(const PaintInfo&, const PhysicalOffset& paint_offset);
static bool ShouldRecordHitTestData(const PaintInfo&,
const NGPhysicalBoxFragment&);
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 739b8e0131d..b4f17e24a77 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
@@ -19,6 +19,25 @@
namespace blink {
+namespace {
+
+template <class Items>
+bool HasMultipleItems(const Items items) {
+ auto iter = items.begin();
+ DCHECK(iter != items.end());
+ return iter != items.end() && ++iter != items.end();
+}
+
+inline bool HasMultiplePaintFragments(const LayoutObject& layout_object) {
+ return HasMultipleItems(NGPaintFragment::InlineFragmentsFor(&layout_object));
+}
+
+inline bool HasMultipleFragmentItems(const LayoutObject& layout_object) {
+ return HasMultipleItems(NGFragmentItem::ItemsFor(layout_object));
+}
+
+} // namespace
+
const NGBorderEdges NGInlineBoxFragmentPainter::BorderEdges() const {
if (border_edges_.has_value())
return *border_edges_;
@@ -30,11 +49,14 @@ const NGBorderEdges NGInlineBoxFragmentPainter::BorderEdges() const {
void NGInlineBoxFragmentPainter::Paint(const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
const PhysicalOffset adjusted_paint_offset =
- paint_offset + inline_box_fragment_.Offset();
+ paint_offset + (inline_box_paint_fragment_
+ ? inline_box_paint_fragment_->Offset()
+ : inline_box_item_->Offset());
if (paint_info.phase == PaintPhase::kForeground)
PaintBackgroundBorderShadow(paint_info, adjusted_paint_offset);
- NGBoxFragmentPainter box_painter(inline_box_fragment_);
+ NGBoxFragmentPainter box_painter(PhysicalFragment(),
+ inline_box_paint_fragment_);
bool suppress_box_decoration_background = true;
box_painter.PaintObject(paint_info, adjusted_paint_offset,
suppress_box_decoration_background);
@@ -53,36 +75,38 @@ void NGInlineBoxFragmentPainterBase::PaintBackgroundBorderShadow(
// we do for LayoutObject. Querying Style each time is too costly.
bool should_paint_box_decoration_background =
inline_box_fragment_.GetLayoutObject()->HasBoxDecorationBackground() ||
- inline_box_fragment_.PhysicalFragment().UsesFirstLineStyle();
+ inline_box_fragment_.UsesFirstLineStyle();
if (!should_paint_box_decoration_background)
return;
+ const DisplayItemClient& display_item_client = GetDisplayItemClient();
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, inline_box_fragment_,
+ paint_info.context, display_item_client,
DisplayItem::kBoxDecorationBackground))
return;
- DrawingRecorder recorder(paint_info.context, inline_box_fragment_,
+ DrawingRecorder recorder(paint_info.context, display_item_client,
DisplayItem::kBoxDecorationBackground);
- PhysicalRect frame_rect = inline_box_fragment_.PhysicalFragment().LocalRect();
+ PhysicalRect frame_rect = inline_box_fragment_.LocalRect();
PhysicalOffset adjusted_paint_offset = paint_offset;
PhysicalRect adjusted_frame_rect(adjusted_paint_offset, frame_rect.size);
- NGPaintFragment::FragmentRange fragments =
- inline_box_fragment_.InlineFragmentsFor(
- inline_box_fragment_.GetLayoutObject());
- NGPaintFragment::FragmentRange::iterator iter = fragments.begin();
- DCHECK(iter != fragments.end());
+ DCHECK(inline_box_fragment_.GetLayoutObject());
+ const LayoutObject& layout_object = *inline_box_fragment_.GetLayoutObject();
bool object_has_multiple_boxes =
- iter != fragments.end() && ++iter != fragments.end();
+ inline_box_paint_fragment_ ? HasMultiplePaintFragments(layout_object)
+ : HasMultipleFragmentItems(layout_object);
// TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry.
BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>(
inline_box_fragment_.GetLayoutObject()));
- NGBoxFragmentPainter box_painter(inline_box_fragment_);
+ // TODO(kojii): not applicable for line box
+ NGBoxFragmentPainter box_painter(
+ To<NGPhysicalBoxFragment>(inline_box_fragment_),
+ inline_box_paint_fragment_);
const NGBorderEdges& border_edges = BorderEdges();
PaintBoxDecorationBackground(box_painter, paint_info, paint_offset,
adjusted_frame_rect, geometry,
@@ -94,20 +118,20 @@ void NGLineBoxFragmentPainter::PaintBackgroundBorderShadow(
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
DCHECK_EQ(paint_info.phase, PaintPhase::kForeground);
- DCHECK_EQ(inline_box_fragment_.PhysicalFragment().Type(),
- NGPhysicalFragment::kFragmentLineBox);
- DCHECK(NeedsPaint(inline_box_fragment_.PhysicalFragment()));
+ DCHECK_EQ(inline_box_fragment_.Type(), NGPhysicalFragment::kFragmentLineBox);
+ DCHECK(NeedsPaint(inline_box_fragment_));
if (line_style_ == style_ ||
line_style_.Visibility() != EVisibility::kVisible)
return;
+ const DisplayItemClient& display_item_client = GetDisplayItemClient();
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, inline_box_fragment_,
+ paint_info.context, display_item_client,
DisplayItem::kBoxDecorationBackground))
return;
- DrawingRecorder recorder(paint_info.context, inline_box_fragment_,
+ DrawingRecorder recorder(paint_info.context, display_item_client,
DisplayItem::kBoxDecorationBackground);
// Compute the content box for the `::first-line` box. It's different from
@@ -147,14 +171,14 @@ void NGInlineBoxFragmentPainterBase::ComputeFragmentOffsetOnLine(
LayoutUnit* total_width) const {
WritingMode writing_mode = inline_box_fragment_.Style().GetWritingMode();
NGPaintFragment::FragmentRange fragments =
- inline_box_fragment_.InlineFragmentsFor(
+ inline_box_paint_fragment_->InlineFragmentsFor(
inline_box_fragment_.GetLayoutObject());
LayoutUnit before;
LayoutUnit after;
bool before_self = true;
for (auto iter = fragments.begin(); iter != fragments.end(); ++iter) {
- if (*iter == &inline_box_fragment_) {
+ if (*iter == inline_box_paint_fragment_) {
before_self = false;
continue;
}
@@ -164,8 +188,7 @@ void NGInlineBoxFragmentPainterBase::ComputeFragmentOffsetOnLine(
after += NGFragment(writing_mode, iter->PhysicalFragment()).InlineSize();
}
- NGFragment logical_fragment(writing_mode,
- inline_box_fragment_.PhysicalFragment());
+ NGFragment logical_fragment(writing_mode, inline_box_fragment_);
*total_width = before + after + logical_fragment.InlineSize();
// We're iterating over the fragments in physical order before so we need to
@@ -229,30 +252,29 @@ NGInlineBoxFragmentPainterBase::GetBorderPaintType(
const PhysicalRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const {
- adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
- if (inline_box_fragment_.Parent() &&
- inline_box_fragment_.Style().HasBorderDecoration()) {
- const NinePieceImage& border_image =
- inline_box_fragment_.Style().BorderImage();
- StyleImage* border_image_source = border_image.GetImage();
- bool has_border_image =
- border_image_source && border_image_source->CanRender();
- if (has_border_image && !border_image_source->IsLoaded())
- return kDontPaintBorders;
-
- // The simple case is where we either have no border image or we are the
- // only box for this object. In those cases only a single call to draw is
- // required.
- if (!has_border_image || !object_has_multiple_boxes)
- return kPaintBordersWithoutClip;
-
- // We have a border image that spans multiple lines.
- adjusted_clip_rect = PixelSnappedIntRect(NGClipRectForNinePieceImageStrip(
- inline_box_fragment_.Style(), BorderEdges(), border_image,
- adjusted_frame_rect));
- return kPaintBordersWithClip;
+ const ComputedStyle& style = inline_box_fragment_.Style();
+ if (!style.HasBorderDecoration())
+ return kDontPaintBorders;
+
+ const NinePieceImage& border_image = style.BorderImage();
+ StyleImage* border_image_source = border_image.GetImage();
+ bool has_border_image =
+ border_image_source && border_image_source->CanRender();
+ if (has_border_image && !border_image_source->IsLoaded())
+ return kDontPaintBorders;
+
+ // The simple case is where we either have no border image or we are the
+ // only box for this object. In those cases only a single call to draw is
+ // required.
+ if (!has_border_image || !object_has_multiple_boxes) {
+ adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
+ return kPaintBordersWithoutClip;
}
- return kDontPaintBorders;
+
+ // We have a border image that spans multiple lines.
+ adjusted_clip_rect = PixelSnappedIntRect(NGClipRectForNinePieceImageStrip(
+ style, BorderEdges(), border_image, adjusted_frame_rect));
+ return kPaintBordersWithClip;
}
void NGInlineBoxFragmentPainterBase::PaintNormalBoxShadow(
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 935f725ad95..b4b4b851161 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
@@ -28,6 +28,7 @@ class NGInlineBoxFragmentPainterBase : public InlineBoxPainterBase {
LayoutUnit* total_width) const;
protected:
+ // Constructor for |NGPaintFragment|.
NGInlineBoxFragmentPainterBase(const NGPaintFragment& inline_box_fragment,
const LayoutObject& layout_object,
const ComputedStyle& style,
@@ -37,7 +38,32 @@ class NGInlineBoxFragmentPainterBase : public InlineBoxPainterBase {
layout_object.GeneratingNode(),
style,
line_style),
- inline_box_fragment_(inline_box_fragment) {}
+ inline_box_fragment_(inline_box_fragment.PhysicalFragment()),
+ inline_box_paint_fragment_(&inline_box_fragment) {}
+
+ // Constructor for |NGFragmentItem|.
+ NGInlineBoxFragmentPainterBase(
+ const NGFragmentItem& inline_box_item,
+ const NGPhysicalBoxFragment& inline_box_fragment,
+ const LayoutObject& layout_object,
+ const ComputedStyle& style,
+ const ComputedStyle& line_style)
+ : InlineBoxPainterBase(layout_object,
+ &layout_object.GetDocument(),
+ layout_object.GeneratingNode(),
+ style,
+ line_style),
+ inline_box_fragment_(inline_box_fragment),
+ inline_box_item_(&inline_box_item) {
+ DCHECK_EQ(inline_box_item.BoxFragment(), &inline_box_fragment);
+ }
+
+ const DisplayItemClient& GetDisplayItemClient() const {
+ if (inline_box_paint_fragment_)
+ return *inline_box_paint_fragment_;
+ DCHECK(inline_box_item_);
+ return *inline_box_item_;
+ }
const virtual NGBorderEdges BorderEdges() const = 0;
@@ -58,7 +84,9 @@ class NGInlineBoxFragmentPainterBase : public InlineBoxPainterBase {
void PaintBackgroundBorderShadow(const PaintInfo&,
const PhysicalOffset& paint_offset);
- const NGPaintFragment& inline_box_fragment_;
+ const NGPhysicalFragment& inline_box_fragment_;
+ const NGPaintFragment* inline_box_paint_fragment_ = nullptr;
+ const NGFragmentItem* inline_box_item_ = nullptr;
};
// Painter for LayoutNG inline box fragments. Delegates to NGBoxFragmentPainter
@@ -67,6 +95,7 @@ class NGInlineBoxFragmentPainter : public NGInlineBoxFragmentPainterBase {
STACK_ALLOCATED();
public:
+ // Constructor for |NGPaintFragment|.
NGInlineBoxFragmentPainter(const NGPaintFragment& inline_box_fragment)
: NGInlineBoxFragmentPainterBase(inline_box_fragment,
*inline_box_fragment.GetLayoutObject(),
@@ -78,12 +107,25 @@ class NGInlineBoxFragmentPainter : public NGInlineBoxFragmentPainterBase {
NGPhysicalFragment::NGBoxType::kInlineBox);
}
+ // Constructor for |NGFragmentItem|.
+ NGInlineBoxFragmentPainter(const NGFragmentItem& inline_box_item,
+ const NGPhysicalBoxFragment& inline_box_fragment)
+ : NGInlineBoxFragmentPainterBase(inline_box_item,
+ inline_box_fragment,
+ *inline_box_fragment.GetLayoutObject(),
+ inline_box_fragment.Style(),
+ inline_box_fragment.Style()) {
+ DCHECK_EQ(inline_box_fragment.Type(),
+ NGPhysicalFragment::NGFragmentType::kFragmentBox);
+ DCHECK_EQ(inline_box_fragment.BoxType(),
+ NGPhysicalFragment::NGBoxType::kInlineBox);
+ }
+
void Paint(const PaintInfo&, const PhysicalOffset& paint_offset);
private:
const NGPhysicalBoxFragment& PhysicalFragment() const {
- return static_cast<const NGPhysicalBoxFragment&>(
- inline_box_fragment_.PhysicalFragment());
+ return static_cast<const NGPhysicalBoxFragment&>(inline_box_fragment_);
}
const NGBorderEdges BorderEdges() const final;
@@ -136,8 +178,7 @@ class NGLineBoxFragmentPainter : public NGInlineBoxFragmentPainterBase {
}
const NGPhysicalLineBoxFragment& PhysicalFragment() const {
- return static_cast<const NGPhysicalLineBoxFragment&>(
- inline_box_fragment_.PhysicalFragment());
+ return static_cast<const NGPhysicalLineBoxFragment&>(inline_box_fragment_);
}
const NGBorderEdges BorderEdges() const final { return NGBorderEdges(); }
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 0fa85f928a6..0af714e8635 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.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_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
@@ -47,11 +48,9 @@ static_assert(sizeof(NGPaintFragment) == sizeof(SameSizeAsNGPaintFragment),
"NGPaintFragment should stay small.");
LogicalRect ComputeLogicalRectFor(const PhysicalRect& physical_rect,
- const NGPaintFragment& paint_fragment) {
- const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
- const TextDirection text_direction =
- paint_fragment.PhysicalFragment().ResolvedDirection();
- const PhysicalSize outer_size = paint_fragment.Size();
+ WritingMode writing_mode,
+ TextDirection text_direction,
+ const PhysicalSize& outer_size) {
const LogicalOffset logical_offset = physical_rect.offset.ConvertToLogical(
writing_mode, text_direction, outer_size, physical_rect.size);
const LogicalSize logical_size =
@@ -59,12 +58,28 @@ LogicalRect ComputeLogicalRectFor(const PhysicalRect& physical_rect,
return {logical_offset, logical_size};
}
+LogicalRect ComputeLogicalRectFor(const PhysicalRect& physical_rect,
+ const NGPaintFragment& paint_fragment) {
+ return ComputeLogicalRectFor(
+ physical_rect, paint_fragment.Style().GetWritingMode(),
+ paint_fragment.PhysicalFragment().ResolvedDirection(),
+ paint_fragment.Size());
+}
+
+LogicalRect ComputeLogicalRectFor(const PhysicalRect& physical_rect,
+ const NGInlineCursor& cursor) {
+ if (const NGPaintFragment* paint_fragment = cursor.CurrentPaintFragment())
+ return ComputeLogicalRectFor(physical_rect, *paint_fragment);
+
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ return ComputeLogicalRectFor(physical_rect, item.GetWritingMode(),
+ item.ResolvedDirection(), item.Size());
+}
+
PhysicalRect ComputePhysicalRectFor(const LogicalRect& logical_rect,
- const NGPaintFragment& paint_fragment) {
- const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
- const TextDirection text_direction =
- paint_fragment.PhysicalFragment().ResolvedDirection();
- const PhysicalSize outer_size = paint_fragment.Size();
+ WritingMode writing_mode,
+ TextDirection text_direction,
+ const PhysicalSize& outer_size) {
const PhysicalSize physical_size =
ToPhysicalSize(logical_rect.size, writing_mode);
const PhysicalOffset physical_offset = logical_rect.offset.ConvertToPhysical(
@@ -72,21 +87,36 @@ PhysicalRect ComputePhysicalRectFor(const LogicalRect& logical_rect,
return {physical_offset, physical_size};
}
+PhysicalRect ComputePhysicalRectFor(const LogicalRect& logical_rect,
+ const NGPaintFragment& paint_fragment) {
+ return ComputePhysicalRectFor(
+ logical_rect, paint_fragment.Style().GetWritingMode(),
+ paint_fragment.PhysicalFragment().ResolvedDirection(),
+ paint_fragment.Size());
+}
+
+PhysicalRect ComputePhysicalRectFor(const LogicalRect& logical_rect,
+ const NGInlineCursor& cursor) {
+ if (const NGPaintFragment* paint_fragment = cursor.CurrentPaintFragment())
+ return ComputePhysicalRectFor(logical_rect, *paint_fragment);
+ const NGFragmentItem& item = *cursor.CurrentItem();
+ return ComputePhysicalRectFor(logical_rect, item.GetWritingMode(),
+ item.ResolvedDirection(), item.Size());
+}
LogicalRect ExpandedSelectionRectForSoftLineBreakIfNeeded(
const LogicalRect& rect,
- const NGPaintFragment& paint_fragment,
+ const NGInlineCursor& cursor,
const LayoutSelectionStatus& selection_status) {
// Expand paint rect if selection covers multiple lines and
// this fragment is at the end of line.
if (selection_status.line_break == SelectSoftLineBreak::kNotSelected)
return rect;
- LayoutBlockFlow* layout_block_flow =
- paint_fragment.GetLayoutObject()->ContainingNGBlockFlow();
+ const LayoutBlockFlow* const layout_block_flow = cursor.GetLayoutBlockFlow();
if (layout_block_flow && layout_block_flow->ShouldTruncateOverflowingText())
return rect;
// Copy from InlineTextBoxPainter::PaintSelection.
- const LayoutUnit space_width(paint_fragment.Style().GetFont().SpaceWidth());
+ const LayoutUnit space_width(cursor.CurrentStyle().GetFont().SpaceWidth());
return {rect.offset,
{rect.size.inline_size + space_width, rect.size.block_size}};
}
@@ -94,6 +124,18 @@ LogicalRect ExpandedSelectionRectForSoftLineBreakIfNeeded(
// Expands selection height so that the selection rect fills entire line.
LogicalRect ExpandSelectionRectToLineHeight(
const LogicalRect& rect,
+ const LogicalRect& line_logical_rect) {
+ // Unite the rect only in the block direction.
+ const LayoutUnit selection_top =
+ std::min(rect.offset.block_offset, line_logical_rect.offset.block_offset);
+ const LayoutUnit selection_bottom =
+ std::max(rect.BlockEndOffset(), line_logical_rect.BlockEndOffset());
+ return {{rect.offset.inline_offset, selection_top},
+ {rect.size.inline_size, selection_bottom - selection_top}};
+}
+
+LogicalRect ExpandSelectionRectToLineHeight(
+ const LogicalRect& rect,
const NGPaintFragment& paint_fragment) {
// Compute the rect of the containing line box relative to |paint_fragment|.
const NGPaintFragment* current_line = paint_fragment.ContainerLineBox();
@@ -102,16 +144,18 @@ LogicalRect ExpandSelectionRectToLineHeight(
current_line->InlineOffsetToContainerBox() -
paint_fragment.InlineOffsetToContainerBox(),
current_line->Size());
- const LogicalRect line_logical_rect =
- ComputeLogicalRectFor(line_physical_rect, paint_fragment);
+ return ExpandSelectionRectToLineHeight(
+ rect, ComputeLogicalRectFor(line_physical_rect, paint_fragment));
+}
- // Unite the rect only in the block direction.
- LayoutUnit selection_top =
- std::min(rect.offset.block_offset, line_logical_rect.offset.block_offset);
- LayoutUnit selection_bottom =
- std::max(rect.BlockEndOffset(), line_logical_rect.BlockEndOffset());
- return {{rect.offset.inline_offset, selection_top},
- {rect.size.inline_size, selection_bottom - selection_top}};
+LogicalRect ExpandSelectionRectToLineHeight(const LogicalRect& rect,
+ const NGInlineCursor& cursor) {
+ NGInlineCursor line(cursor);
+ line.MoveToContainingLine();
+ const PhysicalRect line_physical_rect(
+ line.CurrentOffset() - cursor.CurrentOffset(), line.CurrentSize());
+ return ExpandSelectionRectToLineHeight(
+ rect, ComputeLogicalRectFor(line_physical_rect, cursor));
}
LogicalOffset ChildLogicalOffsetInParent(const NGPaintFragment& child) {
@@ -163,9 +207,8 @@ bool CanBeHitTestTargetPseudoNode(const Node& node) {
}
}
-bool IsLastBRInPage(const NGPhysicalTextFragment& text_fragment) {
- return text_fragment.GetLayoutObject()->IsBR() &&
- !text_fragment.GetLayoutObject()->NextInPreOrder();
+bool IsLastBRInPage(const LayoutObject& layout_object) {
+ return layout_object.IsBR() && !layout_object.NextInPreOrder();
}
const LayoutObject* ListMarkerFromMarkerOrMarkerContent(
@@ -183,6 +226,23 @@ const LayoutObject* ListMarkerFromMarkerOrMarkerContent(
return nullptr;
}
+// TODO(yosin): Move to "ng_selection_painter.cc"
+PhysicalRect ComputeLocalRect(const NGInlineCursor& cursor,
+ unsigned start_offset,
+ unsigned end_offset) {
+ DCHECK_LE(start_offset, end_offset);
+ if (const NGPaintFragment* paint_fragment = cursor.CurrentPaintFragment()) {
+ return To<NGPhysicalTextFragment>(paint_fragment->PhysicalFragment())
+ .LocalRect(start_offset, end_offset);
+ }
+ if (const NGFragmentItem* item = cursor.CurrentItem()) {
+ return item->LocalRect(cursor.Items().Text(item->UsesFirstLineStyle()),
+ start_offset, end_offset);
+ }
+ NOTREACHED();
+ return PhysicalRect();
+}
+
} // namespace
NGPaintFragment::NGPaintFragment(
@@ -407,6 +467,13 @@ bool NGPaintFragment::IsDescendantOfNotSelf(
return false;
}
+bool NGPaintFragment::IsEllipsis() const {
+ if (auto* text_fragment =
+ DynamicTo<NGPhysicalTextFragment>(PhysicalFragment()))
+ return text_fragment->IsEllipsis();
+ return false;
+}
+
bool NGPaintFragment::HasSelfPaintingLayer() const {
return PhysicalFragment().HasSelfPaintingLayer();
}
@@ -792,20 +859,6 @@ base::Optional<PhysicalRect> NGPaintFragment::LocalVisualRectFor(
return visual_rect;
}
-void NGPaintFragment::AddSelfOutlineRects(
- Vector<PhysicalRect>* outline_rects,
- const PhysicalOffset& additional_offset,
- NGOutlineType outline_type) const {
- DCHECK(outline_rects);
- const NGPhysicalFragment& fragment = PhysicalFragment();
- if (auto* box_fragment = DynamicTo<NGPhysicalBoxFragment>(fragment)) {
- if (NGOutlineUtils::IsInlineOutlineNonpaintingFragment(PhysicalFragment()))
- return;
- box_fragment->AddSelfOutlineRects(outline_rects, additional_offset,
- outline_type);
- }
-}
-
const NGPaintFragment* NGPaintFragment::ContainerLineBox() const {
DCHECK(PhysicalFragment().IsInline());
for (const NGPaintFragment* fragment :
@@ -825,6 +878,16 @@ NGPaintFragment* NGPaintFragment::FirstLineBox() const {
return nullptr;
}
+const NGPaintFragment* NGPaintFragment::Root() const {
+ DCHECK(PhysicalFragment().IsInline());
+ const NGPaintFragment* root = this;
+ for (const NGPaintFragment* fragment :
+ NGPaintFragmentTraversal::InclusiveAncestorsOf(*this)) {
+ root = fragment;
+ }
+ return root;
+}
+
void NGPaintFragment::DirtyLinesFromChangedChild(LayoutObject* child) {
if (!RuntimeEnabledFeatures::LayoutNGLineCacheEnabled())
return;
@@ -922,7 +985,7 @@ bool NGPaintFragment::TryMarkLastLineBoxDirtyFor(
void NGPaintFragment::SetShouldDoFullPaintInvalidationRecursively() {
if (LayoutObject* layout_object = GetMutableLayoutObject()) {
- layout_object->StyleRef().ClearCachedPseudoStyles();
+ layout_object->StyleRef().ClearCachedPseudoElementStyles();
layout_object->SetShouldDoFullPaintInvalidation();
}
for (NGPaintFragment* child : Children())
@@ -935,35 +998,36 @@ void NGPaintFragment::SetShouldDoFullPaintInvalidationForFirstLine() const {
if (NGPaintFragment* line_box = FirstLineBox()) {
line_box->SetShouldDoFullPaintInvalidationRecursively();
- GetLayoutObject()->StyleRef().ClearCachedPseudoStyles();
+ GetLayoutObject()->StyleRef().ClearCachedPseudoElementStyles();
GetMutableLayoutObject()->SetShouldDoFullPaintInvalidation();
}
}
-PhysicalRect NGPaintFragment::ComputeLocalSelectionRectForText(
- const LayoutSelectionStatus& selection_status) const {
- const auto& text_fragment = To<NGPhysicalTextFragment>(PhysicalFragment());
- PhysicalRect selection_rect =
- text_fragment.LocalRect(selection_status.start, selection_status.end);
- LogicalRect logical_rect = ComputeLogicalRectFor(selection_rect, *this);
+// TODO(yosin): We should move |ComputeLocalSelectionRectForText()| to
+// "ng_selection_painter.cc".
+PhysicalRect ComputeLocalSelectionRectForText(
+ const NGInlineCursor& cursor,
+ const LayoutSelectionStatus& selection_status) {
+ const PhysicalRect selection_rect =
+ ComputeLocalRect(cursor, selection_status.start, selection_status.end);
+ LogicalRect logical_rect = ComputeLogicalRectFor(selection_rect, cursor);
// Let LocalRect for line break have a space width to paint line break
// when it is only character in a line or only selected in a line.
- if (text_fragment.IsLineBreak() &&
- selection_status.start != selection_status.end &&
+ if (selection_status.start != selection_status.end && cursor.IsLineBreak() &&
// This is for old compatible that old doesn't paint last br in a page.
- !IsLastBRInPage(text_fragment)) {
+ !IsLastBRInPage(*cursor.CurrentLayoutObject())) {
DCHECK(!logical_rect.size.inline_size);
- logical_rect.size.inline_size = LayoutUnit(Style().GetFont().SpaceWidth());
+ logical_rect.size.inline_size =
+ LayoutUnit(cursor.CurrentStyle().GetFont().SpaceWidth());
}
const LogicalRect line_break_extended_rect =
- text_fragment.IsLineBreak()
- ? logical_rect
- : ExpandedSelectionRectForSoftLineBreakIfNeeded(logical_rect, *this,
- selection_status);
+ cursor.IsLineBreak() ? logical_rect
+ : ExpandedSelectionRectForSoftLineBreakIfNeeded(
+ logical_rect, cursor, selection_status);
const LogicalRect line_height_expanded_rect =
- ExpandSelectionRectToLineHeight(line_break_extended_rect, *this);
+ ExpandSelectionRectToLineHeight(line_break_extended_rect, cursor);
const PhysicalRect physical_rect =
- ComputePhysicalRectFor(line_height_expanded_rect, *this);
+ ComputePhysicalRectFor(line_height_expanded_rect, cursor);
return physical_rect;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index f20c7cf56a6..6458de136e1 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -18,6 +18,7 @@
namespace blink {
class NGBlockBreakToken;
+class NGInlineCursor;
struct LayoutSelectionStatus;
struct NGContainerInkOverflow;
enum class NGOutlineType;
@@ -130,13 +131,20 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
NGPaintFragment* NextSibling() const {
return FirstAlive(next_sibling_.get());
}
+ NGPaintFragment* NextForSameLayoutObject() const {
+ return next_for_same_layout_object_;
+ }
ChildList Children() const { return ChildList(FirstChild()); }
+ bool IsEllipsis() const;
// Note, as the name implies, |IsDescendantOfNotSelf| returns false for the
// same object. This is different from |LayoutObject::IsDescendant| but is
// same as |Node::IsDescendant|.
bool IsDescendantOfNotSelf(const NGPaintFragment&) const;
+ // Returns the root box containing this.
+ const NGPaintFragment* Root() const;
+
// Returns the first line box for a block-level container.
NGPaintFragment* FirstLineBox() const;
@@ -164,10 +172,6 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
void RecalcInlineChildrenInkOverflow() const;
- void AddSelfOutlineRects(Vector<PhysicalRect>*,
- const PhysicalOffset& offset,
- NGOutlineType) const;
-
// TODO(layout-dev): Implement when we have oveflow support.
// TODO(eae): Switch to using NG geometry types.
bool HasOverflowClip() const { return PhysicalFragment().HasOverflowClip(); }
@@ -177,8 +181,6 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
IntRect VisualRect() const override;
IntRect PartialInvalidationVisualRect() const override;
- PhysicalRect ComputeLocalSelectionRectForText(
- const LayoutSelectionStatus&) const;
PhysicalRect ComputeLocalSelectionRectForReplaced() const;
// Set ShouldDoFullPaintInvalidation flag in the corresponding LayoutObject.
@@ -209,6 +211,7 @@ class CORE_EXPORT NGPaintFragment : public RefCounted<NGPaintFragment>,
return offset_;
}
PhysicalSize Size() const { return PhysicalFragment().Size(); }
+ PhysicalRect Rect() const { return {Offset(), Size()}; }
// Converts the given point, relative to the fragment itself, into a position
// in DOM tree.
@@ -421,6 +424,10 @@ extern template class CORE_EXTERN_TEMPLATE_EXPORT
extern template class CORE_EXTERN_TEMPLATE_EXPORT
NGPaintFragment::List<NGPaintFragment::TraverseNextSibling>;
+PhysicalRect ComputeLocalSelectionRectForText(
+ const NGInlineCursor& cursor,
+ const LayoutSelectionStatus& selection_status);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
index 67b0de55ad3..4e26682fa4c 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
@@ -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 NGPaintFragmentTraversal_h
-#define NGPaintFragmentTraversal_h
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_TRAVERSAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_TRAVERSAL_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
@@ -203,4 +203,4 @@ class CORE_EXPORT NGPaintFragmentTraversal {
} // namespace blink
-#endif // NGPaintFragmentTraversal_h
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_TRAVERSAL_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 b174e9789c0..883a0eb6b79 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
@@ -12,6 +12,7 @@
#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_list_marker.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/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment.h"
@@ -52,6 +53,90 @@ Color SelectionBackgroundColor(const Document& document,
return color;
}
+// TODO(yosin): Remove |AsDisplayItemClient| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+inline const NGFragmentItem& AsDisplayItemClient(const NGInlineCursor& cursor) {
+ return *cursor.CurrentItem();
+}
+
+inline const NGPaintFragment& AsDisplayItemClient(
+ const NGTextPainterCursor& cursor) {
+ return cursor.PaintFragment();
+}
+
+// TODO(yosin): Remove |GetTextFragmentPaintInfo| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+inline NGTextFragmentPaintInfo GetTextFragmentPaintInfo(
+ const NGInlineCursor& cursor) {
+ return cursor.CurrentItem()->TextPaintInfo(cursor.Items());
+}
+
+inline NGTextFragmentPaintInfo GetTextFragmentPaintInfo(
+ const NGTextPainterCursor& cursor) {
+ return cursor.CurrentItem()->PaintInfo();
+}
+
+// TODO(yosin): Remove |GetLineLeftAndRightForOffsets| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+inline std::pair<LayoutUnit, LayoutUnit> GetLineLeftAndRightForOffsets(
+ const NGFragmentItem& text_item,
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) {
+ return text_item.LineLeftAndRightForOffsets(text, start_offset, end_offset);
+}
+
+inline std::pair<LayoutUnit, LayoutUnit> GetLineLeftAndRightForOffsets(
+ const NGPhysicalTextFragment& text_fragment,
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) {
+ return text_fragment.LineLeftAndRightForOffsets(start_offset, end_offset);
+}
+
+// TODO(yosin): Remove |ComputeLayoutSelectionStatus| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+inline LayoutSelectionStatus ComputeLayoutSelectionStatus(
+ const NGInlineCursor& cursor) {
+ return cursor.CurrentItem()
+ ->GetLayoutObject()
+ ->GetDocument()
+ .GetFrame()
+ ->Selection()
+ .ComputeLayoutSelectionStatus(cursor);
+}
+
+inline LayoutSelectionStatus ComputeLayoutSelectionStatus(
+ const NGTextPainterCursor& cursor) {
+ // Note:: Because of this function is hot, we should not use |NGInlineCursor|
+ // on paint fragment which requires traversing ancestors to root.
+ NGInlineCursor inline_cursor(cursor.RootPaintFragment());
+ inline_cursor.MoveTo(cursor.PaintFragment());
+ return cursor.CurrentItem()
+ ->GetLayoutObject()
+ ->GetDocument()
+ .GetFrame()
+ ->Selection()
+ .ComputeLayoutSelectionStatus(inline_cursor);
+}
+
+// TODO(yosin): Remove |ComputeLocalRect| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+inline PhysicalRect ComputeLocalRect(const NGFragmentItem& text_item,
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) {
+ return text_item.LocalRect(text, start_offset, end_offset);
+}
+
+inline PhysicalRect ComputeLocalRect(
+ const NGPhysicalTextFragment& text_fragment,
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) {
+ return text_fragment.LocalRect(start_offset, end_offset);
+}
+
DocumentMarkerVector ComputeMarkersToPaint(Node* node, bool is_ellipsis) {
// TODO(yoichio): Handle first-letter
auto* text_node = DynamicTo<Text>(node);
@@ -89,8 +174,8 @@ unsigned GetTextContentOffset(const Text& text, unsigned offset) {
// If "bar" is a TextFragment. That start(), end() {4, 7} correspond this
// offset. If a marker has StartOffset / EndOffset as {2, 6},
// ClampOffset returns{ 4,6 }, which represents "ba" on "foo_bar".
-unsigned ClampOffset(unsigned offset,
- const NGPhysicalTextFragment& text_fragment) {
+template <typename TextItem>
+unsigned ClampOffset(unsigned offset, const TextItem& text_fragment) {
return std::min(std::max(offset, text_fragment.StartOffset()),
text_fragment.EndOffset());
}
@@ -109,13 +194,14 @@ void PaintRect(GraphicsContext& context,
context.FillRect(pixel_snapped_rect, color);
}
-PhysicalRect MarkerRectForForeground(
- const NGPhysicalTextFragment& text_fragment,
- unsigned start_offset,
- unsigned end_offset) {
+template <typename TextItem>
+PhysicalRect MarkerRectForForeground(const TextItem& text_fragment,
+ StringView text,
+ unsigned start_offset,
+ unsigned end_offset) {
LayoutUnit start_position, end_position;
- std::tie(start_position, end_position) =
- text_fragment.LineLeftAndRightForOffsets(start_offset, end_offset);
+ std::tie(start_position, end_position) = GetLineLeftAndRightForOffsets(
+ text_fragment, text, start_offset, end_offset);
const LayoutUnit height = text_fragment.Size()
.ConvertToLogical(static_cast<WritingMode>(
@@ -125,8 +211,10 @@ PhysicalRect MarkerRectForForeground(
}
// Copied from InlineTextBoxPainter
+template <typename TextItem>
void PaintDocumentMarkers(GraphicsContext& context,
- const NGPhysicalTextFragment& text_fragment,
+ const TextItem& text_fragment,
+ StringView text,
const DocumentMarkerVector& markers_to_paint,
const PhysicalOffset& box_origin,
const ComputedStyle& style,
@@ -136,12 +224,12 @@ void PaintDocumentMarkers(GraphicsContext& context,
return;
DCHECK(text_fragment.GetNode());
- const auto& text = To<Text>(*text_fragment.GetNode());
+ const auto& text_node = To<Text>(*text_fragment.GetNode());
for (const DocumentMarker* marker : markers_to_paint) {
const unsigned marker_start_offset =
- GetTextContentOffset(text, marker->StartOffset());
+ GetTextContentOffset(text_node, marker->StartOffset());
const unsigned marker_end_offset =
- GetTextContentOffset(text, marker->EndOffset());
+ GetTextContentOffset(text_node, marker->EndOffset());
const unsigned paint_start_offset =
ClampOffset(marker_start_offset, text_fragment);
const unsigned paint_end_offset =
@@ -158,34 +246,36 @@ void PaintDocumentMarkers(GraphicsContext& context,
continue;
DocumentMarkerPainter::PaintDocumentMarker(
context, box_origin, style, marker->GetType(),
- MarkerRectForForeground(text_fragment, paint_start_offset,
+ MarkerRectForForeground(text_fragment, text, paint_start_offset,
paint_end_offset));
} break;
+ case DocumentMarker::kTextFragment:
case DocumentMarker::kTextMatch: {
- if (!text_fragment.GetNode()
+ if (marker->GetType() == DocumentMarker::kTextMatch &&
+ !text_fragment.GetNode()
->GetDocument()
.GetFrame()
->GetEditor()
.MarkedTextMatchesAreHighlighted())
break;
- const auto& text_match_marker = To<TextMatchMarker>(*marker);
+ const auto& text_marker = To<TextMarkerBase>(*marker);
if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) {
const Color color =
LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
- text_match_marker.IsActiveMatch(),
+ text_marker.IsActiveMatch(),
text_fragment.GetNode()->GetDocument().InForcedColorsMode(),
style.UsedColorScheme());
- PaintRect(
- context, PhysicalOffset(box_origin),
- text_fragment.LocalRect(paint_start_offset, paint_end_offset),
- color);
+ PaintRect(context, PhysicalOffset(box_origin),
+ ComputeLocalRect(text_fragment, text, paint_start_offset,
+ paint_end_offset),
+ color);
break;
}
const TextPaintStyle text_style =
DocumentMarkerPainter::ComputeTextPaintStyleFrom(
- style, text_match_marker,
+ style, text_marker,
text_fragment.GetNode()->GetDocument().InForcedColorsMode());
if (text_style.current_color == Color::kTransparent)
break;
@@ -199,17 +289,17 @@ void PaintDocumentMarkers(GraphicsContext& context,
case DocumentMarker::kSuggestion: {
const auto& styleable_marker = To<StyleableMarker>(*marker);
if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) {
- PaintRect(
- context, PhysicalOffset(box_origin),
- text_fragment.LocalRect(paint_start_offset, paint_end_offset),
- styleable_marker.BackgroundColor());
+ PaintRect(context, PhysicalOffset(box_origin),
+ ComputeLocalRect(text_fragment, text, paint_start_offset,
+ paint_end_offset),
+ styleable_marker.BackgroundColor());
break;
}
const SimpleFontData* font_data = style.GetFont().PrimaryFont();
DocumentMarkerPainter::PaintStyleableMarkerUnderline(
context, box_origin, styleable_marker, style,
- FloatRect(MarkerRectForForeground(text_fragment, paint_start_offset,
- paint_end_offset)),
+ FloatRect(MarkerRectForForeground(
+ text_fragment, text, paint_start_offset, paint_end_offset)),
LayoutUnit(font_data->GetFontMetrics().Height()));
} break;
@@ -222,23 +312,30 @@ void PaintDocumentMarkers(GraphicsContext& context,
} // namespace
-NGTextFragmentPainter::NGTextFragmentPainter(
- const NGPaintFragment& paint_fragment)
- : paint_fragment_(&paint_fragment),
- text_fragment_(
- &To<NGPhysicalTextFragment>(paint_fragment.PhysicalFragment())) {}
+const NGPaintFragment& NGTextPainterCursor::RootPaintFragment() const {
+ if (!root_paint_fragment_)
+ root_paint_fragment_ = paint_fragment_.Root();
+ return *root_paint_fragment_;
+}
+
+template <typename Cursor>
+NGTextFragmentPainter<Cursor>::NGTextFragmentPainter(const Cursor& cursor)
+ : cursor_(cursor) {}
-NGTextFragmentPainter::NGTextFragmentPainter(const NGFragmentItem& item,
- const NGFragmentItems& items)
- : item_(&item), items_(&items) {
- DCHECK_EQ(item.Type(), NGFragmentItem::kText);
+static PhysicalRect ComputeLocalSelectionRectForText(
+ const NGTextPainterCursor& cursor,
+ const LayoutSelectionStatus& selection_status) {
+ NGInlineCursor inline_cursor(cursor.RootPaintFragment());
+ inline_cursor.MoveTo(cursor.PaintFragment());
+ return ComputeLocalSelectionRectForText(inline_cursor, selection_status);
}
// Logic is copied from InlineTextBoxPainter::PaintSelection.
// |selection_start| and |selection_end| should be between
// [text_fragment.StartOffset(), text_fragment.EndOffset()].
+template <typename Cursor>
static void PaintSelection(GraphicsContext& context,
- const NGPaintFragment& paint_fragment,
+ const Cursor& cursor,
Node* node,
const Document& document,
const ComputedStyle& style,
@@ -248,15 +345,17 @@ static void PaintSelection(GraphicsContext& context,
const Color color =
SelectionBackgroundColor(document, style, node, text_color);
const PhysicalRect selection_rect =
- paint_fragment.ComputeLocalSelectionRectForText(selection_status);
+ ComputeLocalSelectionRectForText(cursor, selection_status);
PaintRect(context, box_rect.offset, selection_rect, color);
}
-void NGTextFragmentPainter::PaintSymbol(const LayoutObject* layout_object,
- const ComputedStyle& style,
- const PhysicalSize box_size,
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
+template <typename Cursor>
+void NGTextFragmentPainter<Cursor>::PaintSymbol(
+ const LayoutObject* layout_object,
+ const ComputedStyle& style,
+ const PhysicalSize box_size,
+ const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
PhysicalRect marker_rect(
LayoutListMarker::RelativeSymbolMarkerRect(style, box_size.width));
marker_rect.Move(paint_offset);
@@ -267,64 +366,27 @@ void NGTextFragmentPainter::PaintSymbol(const LayoutObject* layout_object,
// This is copied from InlineTextBoxPainter::PaintSelection() but lacks of
// ltr, expanding new line wrap or so which uses InlineTextBox functions.
-void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- if (UNLIKELY(item_)) {
- PaintItem(paint_info, paint_offset);
- return;
- }
- DCHECK(text_fragment_ && paint_fragment_);
-
+template <typename Cursor>
+void NGTextFragmentPainter<Cursor>::Paint(const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ const auto& text_item = *cursor_.CurrentItem();
// We can skip painting if the fragment (including selection) is invisible.
- if (!text_fragment_->Length())
+ if (!text_item.TextLength())
return;
- IntRect visual_rect = paint_fragment_->VisualRect();
+ const IntRect visual_rect = AsDisplayItemClient(cursor_).VisualRect();
if (visual_rect.IsEmpty())
return;
- if (!text_fragment_->TextShapeResult() &&
+ if (!text_item.TextShapeResult() &&
// A line break's selection tint is still visible.
- !text_fragment_->IsLineBreak())
- return;
-
- Paint(text_fragment_->PaintInfo(), text_fragment_->GetLayoutObject(),
- *paint_fragment_, text_fragment_->Style(),
- {paint_fragment_->Offset(), text_fragment_->Size()}, visual_rect,
- text_fragment_->IsEllipsis(),
- text_fragment_->TextType() == NGPhysicalTextFragment::kSymbolMarker,
- paint_info, paint_offset);
-}
-
-void NGTextFragmentPainter::PaintItem(const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- DCHECK(item_ && items_);
-
- if (!item_->TextLength())
- return;
- IntRect visual_rect = item_->VisualRect();
- if (visual_rect.IsEmpty())
+ !text_item.IsLineBreak())
return;
- NGTextFragmentPaintInfo fragment_paint_info = item_->TextPaintInfo(*items_);
- bool is_ellipsis = false; // TODO(kojii): Implement.
- bool is_symbol_marker = false; // TODO(kojii): Implement.
- Paint(fragment_paint_info, item_->GetLayoutObject(), *item_, item_->Style(),
- item_->Rect(), visual_rect, is_ellipsis, is_symbol_marker, paint_info,
- paint_offset);
-}
-
-void NGTextFragmentPainter::Paint(
- const NGTextFragmentPaintInfo& fragment_paint_info,
- const LayoutObject* layout_object,
- const DisplayItemClient& display_item_client,
- const ComputedStyle& style,
- PhysicalRect box_rect,
- const IntRect& visual_rect,
- bool is_ellipsis,
- bool is_symbol_marker,
- const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- DCHECK(layout_object);
+ const NGTextFragmentPaintInfo& fragment_paint_info =
+ GetTextFragmentPaintInfo(cursor_);
+ const LayoutObject* layout_object = text_item.GetLayoutObject();
+ const ComputedStyle& style = text_item.Style();
+ PhysicalRect box_rect = AsDisplayItemClient(cursor_).Rect();
const Document& document = layout_object->GetDocument();
const bool is_printing = paint_info.IsPrinting();
@@ -334,16 +396,9 @@ void NGTextFragmentPainter::Paint(
layout_object->IsSelected();
base::Optional<LayoutSelectionStatus> selection_status;
if (have_selection) {
- if (paint_fragment_) {
- selection_status =
- document.GetFrame()->Selection().ComputeLayoutSelectionStatus(
- *paint_fragment_);
- DCHECK_LE(selection_status->start, selection_status->end);
- have_selection = selection_status->start < selection_status->end;
- } else {
- // TODO(kojii): Implement without paint_fragment_
- have_selection = false;
- }
+ selection_status = ComputeLayoutSelectionStatus(cursor_);
+ DCHECK_LE(selection_status->start, selection_status->end);
+ have_selection = selection_status->start < selection_status->end;
}
if (!have_selection) {
// When only painting the selection, don't bother to paint if there is none.
@@ -351,8 +406,7 @@ void NGTextFragmentPainter::Paint(
return;
// Flow controls (line break, tab, <wbr>) need only selection painting.
- // TODO(kojii): Implement without text_fragment_.
- if (text_fragment_ && text_fragment_->IsFlowControl())
+ if (text_item.IsFlowControl())
return;
}
@@ -362,12 +416,13 @@ void NGTextFragmentPainter::Paint(
base::Optional<DrawingRecorder> recorder;
if (paint_info.phase != PaintPhase::kTextClip) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, display_item_client, paint_info.phase))
+ paint_info.context, AsDisplayItemClient(cursor_), paint_info.phase))
return;
- recorder.emplace(paint_info.context, display_item_client, paint_info.phase);
+ recorder.emplace(paint_info.context, AsDisplayItemClient(cursor_),
+ paint_info.phase);
}
- if (UNLIKELY(is_symbol_marker)) {
+ if (UNLIKELY(text_item.IsSymbolMarker())) {
// The NGInlineItem of marker might be Split(). So PaintSymbol only if the
// StartOffset is 0, or it might be painted several times.
if (!fragment_paint_info.from) {
@@ -411,24 +466,15 @@ void NGTextFragmentPainter::Paint(
// NGPaintFragment::ComputeLocalSelectionRectForText logical so that we can
// paint selection in same fliped dimention as NGTextPainter.
const DocumentMarkerVector& markers_to_paint =
- ComputeMarkersToPaint(node, is_ellipsis);
+ ComputeMarkersToPaint(node, text_item.IsEllipsis());
if (paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kTextClip && !is_printing) {
- if (text_fragment_) {
- PaintDocumentMarkers(context, *text_fragment_, markers_to_paint,
- box_rect.offset, style,
- DocumentMarkerPaintPhase::kBackground, nullptr);
- } else {
- // TODO(kojii): Implement without text_fragment_.
- }
-
+ PaintDocumentMarkers(context, text_item, fragment_paint_info.text,
+ markers_to_paint, box_rect.offset, style,
+ DocumentMarkerPaintPhase::kBackground, nullptr);
if (have_selection) {
- if (paint_fragment_) {
- PaintSelection(context, *paint_fragment_, node, document, style,
- selection_style.fill_color, box_rect, *selection_status);
- } else {
- // TODO(kojii): Implement without paint_fragment_.
- }
+ PaintSelection(context, cursor_, node, document, style,
+ selection_style.fill_color, box_rect, *selection_status);
}
}
@@ -471,7 +517,7 @@ void NGTextFragmentPainter::Paint(
if (style.TextDecorationsInEffect() != TextDecoration::kNone &&
// Ellipsis should not have text decorations. This is not defined, but 4
// impls do this.
- !is_ellipsis) {
+ !text_item.IsEllipsis()) {
PhysicalOffset local_origin = box_rect.offset;
LayoutUnit width = box_rect.Width();
const NGPhysicalBoxFragment* decorating_box = nullptr;
@@ -482,16 +528,12 @@ void NGTextFragmentPainter::Paint(
decoration_info, box_rect.offset, local_origin, width,
style.GetFontBaseline(), style, decorating_box_style);
- if (text_fragment_) {
- NGTextDecorationOffset decoration_offset(
- *decoration_info.style, *text_fragment_, decorating_box);
- text_painter.PaintDecorationsExceptLineThrough(
- decoration_offset, decoration_info, paint_info,
- style.AppliedTextDecorations(), text_style,
- &has_line_through_decoration);
- } else {
- // TODO(kojii): Implement without text_fragment_
- }
+ NGTextDecorationOffset decoration_offset(
+ *decoration_info.style, text_item.Style(), decorating_box);
+ text_painter.PaintDecorationsExceptLineThrough(
+ decoration_offset, decoration_info, paint_info,
+ style.AppliedTextDecorations(), text_style,
+ &has_line_through_decoration);
}
unsigned start_offset = fragment_paint_info.from;
@@ -528,13 +570,12 @@ void NGTextFragmentPainter::Paint(
if (paint_info.phase != PaintPhase::kForeground)
return;
- if (text_fragment_) {
- PaintDocumentMarkers(context, *text_fragment_, markers_to_paint,
- box_rect.offset, style,
- DocumentMarkerPaintPhase::kForeground, &text_painter);
- } else {
- // TODO(kojii): Implement without text_fragment_.
- }
+ PaintDocumentMarkers(context, text_item, fragment_paint_info.text,
+ markers_to_paint, box_rect.offset, style,
+ DocumentMarkerPaintPhase::kForeground, &text_painter);
}
+template class NGTextFragmentPainter<NGTextPainterCursor>;
+template class NGTextFragmentPainter<NGInlineCursor>;
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h
index 760f59e0bcf..6294fca3a61 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,8 @@
#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/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -14,33 +16,51 @@ namespace blink {
class ComputedStyle;
class DisplayItemClient;
class LayoutObject;
-class NGFragmentItem;
-class NGFragmentItems;
class NGPaintFragment;
-class NGPhysicalTextFragment;
+class NGInlineCursor;
struct NGTextFragmentPaintInfo;
struct PaintInfo;
struct PhysicalOffset;
struct PhysicalRect;
struct PhysicalSize;
+// The helper class for templatize |NGTextFragmentPainter|.
+// TODO(yosin): Remove |NGTextPainterCursor| once the transition to
+// |NGFragmentItem| is done. http://crbug.com/982194
+class NGTextPainterCursor {
+ STACK_ALLOCATED();
+
+ public:
+ explicit NGTextPainterCursor(const NGPaintFragment& paint_fragment)
+ : paint_fragment_(paint_fragment),
+ text_fragment_(
+ To<NGPhysicalTextFragment>(paint_fragment.PhysicalFragment())) {}
+
+ const NGPaintFragment& PaintFragment() const { return paint_fragment_; }
+ const NGPhysicalTextFragment* CurrentItem() const { return &text_fragment_; }
+ const NGPaintFragment& RootPaintFragment() const;
+
+ private:
+ const NGPaintFragment& paint_fragment_;
+ const NGPhysicalTextFragment& text_fragment_;
+ mutable const NGPaintFragment* root_paint_fragment_ = nullptr;
+};
+
// Text fragment painter for LayoutNG. Operates on NGPhysicalTextFragments and
// handles clipping, selection, etc. Delegates to NGTextPainter to paint the
// text itself.
+// TODO(yosin): We should make |NGTextFragmentPainter| non-template class onnce
+// we get rid of |NGPaintFragment|.
+template <typename Cursor>
class NGTextFragmentPainter {
STACK_ALLOCATED();
public:
- // TODO(kojii) : Remove | NGPaintFragment | once the transition is done.
- // crbug.com/982194
- explicit NGTextFragmentPainter(const NGPaintFragment&);
- NGTextFragmentPainter(const NGFragmentItem&, const NGFragmentItems&);
+ explicit NGTextFragmentPainter(const Cursor&);
void Paint(const PaintInfo&, const PhysicalOffset& paint_offset);
private:
- void PaintItem(const PaintInfo&, const PhysicalOffset& paint_offset);
-
void Paint(const NGTextFragmentPaintInfo& fragment_paint_info,
const LayoutObject* layout_object,
const DisplayItemClient& display_item_client,
@@ -58,13 +78,12 @@ class NGTextFragmentPainter {
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset);
- const NGPaintFragment* paint_fragment_ = nullptr;
- const NGPhysicalTextFragment* text_fragment_ = nullptr;
-
- const NGFragmentItem* item_ = nullptr;
- const NGFragmentItems* items_ = nullptr;
+ const Cursor& cursor_;
};
+extern template class NGTextFragmentPainter<NGTextPainterCursor>;
+extern template class NGTextFragmentPainter<NGInlineCursor>;
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_
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 3d26d5c778a..b903af4b71d 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
@@ -99,14 +99,14 @@ 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);
+ &draw_info.source, style.HasFilterInducingProperty());
} else if (draw_info.tile_rule.horizontal == kStretchImageRule &&
draw_info.tile_rule.vertical == kStretchImageRule) {
// Just do a scale.
// 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);
+ &draw_info.source, style.HasFilterInducingProperty());
} else {
// TODO(cavalcantii): see crbug.com/662513.
base::Optional<TileParameters> h_tile = ComputeTileParameters(
@@ -181,6 +181,8 @@ bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
document, 1, border_image_rect.size.ToLayoutSize()));
scoped_refptr<Image> image =
style_image->GetImage(observer, document, style, FloatSize(image_size));
+ if (!image)
+ return true;
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
index 6500d54223f..b8d0402919f 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
@@ -365,4 +365,15 @@ TEST_F(ObjectPaintInvalidatorTest, Selection) {
GetDocument().View()->SetTracksPaintInvalidations(false);
}
+// Passes if it does not crash.
+TEST_F(ObjectPaintInvalidatorTest, ZeroWidthForeignObject) {
+ SetBodyInnerHTML(R"HTML(
+ <svg style="backface-visibility: hidden;">
+ <foreignObject width=0 height=50>
+ <div style="position: relative">test</div>
+ </foreignObject>
+ </svg>
+ )HTML");
+}
+
} // namespace blink
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 fc4a390623b..42c8caf0167 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.cc
@@ -62,9 +62,9 @@ void ObjectPainter::PaintInlineChildrenOutlines(const PaintInfo& paint_info) {
}
}
-void ObjectPainter::AddPDFURLRectIfNeeded(const PaintInfo& paint_info,
- const PhysicalOffset& paint_offset) {
- DCHECK(paint_info.IsPrinting());
+void ObjectPainter::AddURLRectIfNeeded(const PaintInfo& paint_info,
+ const PhysicalOffset& paint_offset) {
+ DCHECK(paint_info.ShouldAddUrlMetadata());
if (layout_object_.IsElementContinuation() || !layout_object_.GetNode() ||
!layout_object_.GetNode()->IsLink() ||
layout_object_.StyleRef().Visibility() != EVisibility::kVisible)
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 12595d0c335..56b2afd380f 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.h
@@ -25,8 +25,7 @@ class ObjectPainter : public ObjectPainterBase {
void PaintOutline(const PaintInfo&, const PhysicalOffset& paint_offset);
void PaintInlineChildrenOutlines(const PaintInfo&);
- void AddPDFURLRectIfNeeded(const PaintInfo&,
- const PhysicalOffset& paint_offset);
+ void AddURLRectIfNeeded(const PaintInfo&, const PhysicalOffset& paint_offset);
// Paints the object atomically as if it created a new stacking context, for:
// - inline blocks, inline tables, inline-level replaced elements (Section
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 42e7d3b8363..09b8451ca1c 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
@@ -12,6 +12,7 @@ namespace blink {
using ::testing::MatchesRegex;
using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
void SetUpHTML(PaintAndRasterInvalidationTest& test) {
test.SetBodyInnerHTML(R"HTML(
@@ -873,26 +874,14 @@ TEST_P(PaintAndRasterInvalidationTest, SVGHiddenContainer) {
EXPECT_EQ(IntRect(55, 66, 7, 8), real_rect->FirstFragment().VisualRect());
// Should invalidate raster for real_rect only.
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // CAP creates composited layers for the rect and its mask.
- EXPECT_THAT(GetRasterInvalidationTracking(1)->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- real_rect, real_rect->DebugName(), IntRect(0, 0, 7, 8),
- PaintInvalidationReason::kFull}));
- EXPECT_THAT(GetRasterInvalidationTracking(2)->Invalidations(),
- UnorderedElementsAre(RasterInvalidationInfo{
- real_rect, real_rect->DebugName(), IntRect(0, 0, 7, 8),
- PaintInvalidationReason::kFull}));
- } else {
- EXPECT_THAT(GetRasterInvalidationTracking(1)->Invalidations(),
- UnorderedElementsAre(
- RasterInvalidationInfo{real_rect, real_rect->DebugName(),
- IntRect(155, 166, 7, 8),
- PaintInvalidationReason::kFull},
- RasterInvalidationInfo{real_rect, real_rect->DebugName(),
- IntRect(155, 166, 7, 8),
- PaintInvalidationReason::kFull}));
- }
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{real_rect, real_rect->DebugName(),
+ IntRect(155, 166, 7, 8),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{real_rect, real_rect->DebugName(),
+ IntRect(155, 166, 7, 8),
+ PaintInvalidationReason::kFull}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -1037,6 +1026,44 @@ TEST_P(PaintAndRasterInvalidationTest, ScrollingInvalidatesStickyOffset) {
EXPECT_EQ(PhysicalOffset(), inner->FirstFragment().PaintOffset());
}
+TEST_P(PaintAndRasterInvalidationTest, ResizeElementWhichHasNonCustomResizer) {
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ * { margin: 0;}
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ overflow: hidden;
+ resize: both;
+ }
+ </style>
+ <div id='target'></div>
+ )HTML");
+
+ auto* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
+
+ GetDocument().View()->SetTracksPaintInvalidations(true);
+
+ target->setAttribute(html_names::kStyleAttr, "width: 200px");
+ UpdateAllLifecyclePhasesForTest();
+
+ Vector<RasterInvalidationInfo> invalidations;
+ // This is for DisplayItem::kResizerScrollHitTest.
+ invalidations.push_back(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 0, 200, 100),
+ PaintInvalidationReason::kGeometry});
+ invalidations.push_back(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 0, 200, 100),
+ PaintInvalidationReason::kGeometry});
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAreArray(invalidations));
+
+ GetDocument().View()->SetTracksPaintInvalidations(false);
+}
+
class PaintInvalidatorTestClient : public RenderingTestChromeClient {
public:
void InvalidateRect(const IntRect&) override {
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 06aeff57eb7..6927f0aed5a 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_info.h
@@ -124,6 +124,9 @@ struct CORE_EXPORT PaintInfo {
}
bool IsPrinting() const { return global_paint_flags_ & kGlobalPaintPrinting; }
+ bool ShouldAddUrlMetadata() const {
+ return global_paint_flags_ & kGlobalPaintAddUrlMetadata;
+ }
DisplayItem::Type DisplayItemTypeForClipping() const {
return DisplayItem::PaintPhaseToClipType(phase);
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 1552e38d689..358f04b3639 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -16,6 +16,8 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
@@ -182,9 +184,10 @@ void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
context.painting_layer->SetNeedsPaintPhaseDescendantOutlines();
if (object.HasBoxDecorationBackground()
- // We also paint overflow controls in background phase.
- || (object.HasOverflowClip() &&
- ToLayoutBox(object).GetScrollableArea()->HasOverflowControls())) {
+ // We also paint non-overlay overflow controls in background phase.
+ || (object.HasOverflowClip() && ToLayoutBox(object)
+ .GetScrollableArea()
+ ->HasNonOverlayOverflowControls())) {
context.painting_layer->SetNeedsPaintPhaseDescendantBlockBackgrounds();
} else {
// Hit testing rects for touch action paint in the background phase.
@@ -198,7 +201,7 @@ void PaintInvalidator::UpdatePaintInvalidationContainer(
PaintInvalidatorContext& context) {
if (object.IsPaintInvalidationContainer()) {
context.paint_invalidation_container = ToLayoutBoxModelObject(&object);
- if (object.StyleRef().IsStackingContext())
+ if (object.StyleRef().IsStackingContext() || object.IsSVGRoot())
context.paint_invalidation_container_for_stacked_contents =
ToLayoutBoxModelObject(&object);
} else if (object.IsLayoutView()) {
@@ -278,7 +281,14 @@ void PaintInvalidator::UpdateVisualRect(const LayoutObject& object,
PropertyTreeState(*context.tree_builder_context_->current.transform,
*context.tree_builder_context_->current.clip,
*context.tree_builder_context_->current_effect),
- context.old_visual_rect, fragment_data.VisualRect());
+ context.old_visual_rect, fragment_data.VisualRect(),
+ // Don't report a diff for a LayoutView. Any paint offset translation
+ // it has was inherited from the parent frame, and movements of a
+ // frame relative to its parent are tracked in the parent frame's
+ // LayoutShiftTracker, not the child frame's.
+ object.IsLayoutView()
+ ? FloatSize()
+ : context.tree_builder_context_->paint_offset_delta);
}
void PaintInvalidator::UpdateEmptyVisualRectFlag(
@@ -326,6 +336,16 @@ bool PaintInvalidator::InvalidatePaint(
if (!object.ShouldCheckForPaintInvalidation() && !context.NeedsSubtreeWalk())
return false;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ object.GetFrame()->GetPage()->GetLinkHighlight().NeedsHighlightEffect(
+ object)) {
+ // We need to recollect the foreign layers for link highlight when the
+ // geometry of the highlights may change. CompositeAfterPaint doesn't
+ // need this because we collect foreign layers during
+ // LocalFrameView::PaintTree() which is not controlled by the flag.
+ object.GetFrameView()->SetForeignLayerListNeedsUpdate();
+ }
+
unsigned tree_builder_index = 0;
for (auto* fragment_data = &object.GetMutableForPainting().FirstFragment();
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 ffd38fd82f7..645ce72f1da 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -177,7 +177,7 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
needs_compositing_layer_assignment_(false),
descendant_needs_compositing_layer_assignment_(false),
has_self_painting_layer_descendant_(false),
- needs_reorder_overlay_scrollbars_(false),
+ needs_reorder_overlay_overflow_controls_(false),
#if DCHECK_IS_ON()
layer_list_mutation_allowed_(true),
#endif
@@ -227,7 +227,7 @@ PaintLayer::~PaintLayer() {
// PaintLayerScrollableArea::WillRemoveScrollbar() from dirtying the z-order
// list of the stacking context. If this layer is removed from the parent,
// the z-order list should have been invalidated in RemoveChild().
- needs_reorder_overlay_scrollbars_ = false;
+ needs_reorder_overlay_overflow_controls_ = false;
if (scrollable_area_)
scrollable_area_->Dispose();
@@ -446,49 +446,6 @@ void PaintLayer::UpdateTransform(const ComputedStyle* old_style,
frame_view->SetNeedsUpdateGeometries();
}
-static PaintLayer* EnclosingLayerForContainingBlock(PaintLayer* layer) {
- if (LayoutObject* containing_block =
- layer->GetLayoutObject().ContainingBlock())
- return containing_block->EnclosingLayer();
- return nullptr;
-}
-
-static const PaintLayer* EnclosingLayerForContainingBlock(
- const PaintLayer* layer) {
- if (const LayoutObject* containing_block =
- layer->GetLayoutObject().ContainingBlock())
- return containing_block->EnclosingLayer();
- return nullptr;
-}
-
-PaintLayer* PaintLayer::RenderingContextRoot() {
- PaintLayer* rendering_context = nullptr;
-
- if (ShouldPreserve3D())
- rendering_context = this;
-
- for (PaintLayer* current = EnclosingLayerForContainingBlock(this);
- current && current->ShouldPreserve3D();
- current = EnclosingLayerForContainingBlock(current))
- rendering_context = current;
-
- return rendering_context;
-}
-
-const PaintLayer* PaintLayer::RenderingContextRoot() const {
- const PaintLayer* rendering_context = nullptr;
-
- if (ShouldPreserve3D())
- rendering_context = this;
-
- for (const PaintLayer* current = EnclosingLayerForContainingBlock(this);
- current && current->ShouldPreserve3D();
- current = EnclosingLayerForContainingBlock(current))
- rendering_context = current;
-
- return rendering_context;
-}
-
TransformationMatrix PaintLayer::CurrentTransform() const {
if (TransformationMatrix* transform = Transform())
return *transform;
@@ -2987,12 +2944,9 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
}
bool PaintLayer::ShouldBeSelfPaintingLayer() const {
- // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
- // main-thread AnimationWorklet and don't need to promote the scroll-source.
return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
- (scrollable_area_ && scrollable_area_->HasOverlayScrollbars()) ||
- ScrollsOverflow() ||
- ScrollTimeline::HasActiveScrollTimeline(GetLayoutObject().GetNode());
+ (scrollable_area_ && scrollable_area_->HasOverlayOverflowControls()) ||
+ ScrollsOverflow();
}
void PaintLayer::UpdateSelfPaintingLayer() {
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 c816b6c02d4..2eb6f7ec6f6 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
@@ -343,8 +343,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
}
void UpdateTransformationMatrix();
- PaintLayer* RenderingContextRoot();
- const PaintLayer* RenderingContextRoot() const;
bool IsStackingContextWithNegativeZOrderChildren() const {
DCHECK(!stacking_node_ || GetLayoutObject().StyleRef().IsStackingContext());
@@ -749,7 +747,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
}
struct AncestorDependentCompositingInputs {
- public:
const PaintLayer* opacity_ancestor = nullptr;
const PaintLayer* transform_ancestor = nullptr;
const PaintLayer* filter_ancestor = nullptr;
@@ -777,6 +774,11 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// clipping logic.
const PaintLayer* clip_parent = nullptr;
+ // Nearest layer that has layout containment applied to its LayoutObject.
+ // Squashing is disallowed across contain layout boundaries to provide
+ // better isolation.
+ const PaintLayer* nearest_contained_layout_layer = nullptr;
+
// These two boxes do not include any applicable scroll offset of the
// root PaintLayer.
IntRect clipped_absolute_bounding_box;
@@ -853,6 +855,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
const PaintLayer* ClipParent() const {
return GetAncestorDependentCompositingInputs().clip_parent;
}
+ const PaintLayer* NearestContainedLayoutLayer() const {
+ return GetAncestorDependentCompositingInputs()
+ .nearest_contained_layout_layer;
+ }
const PaintLayer* ClipPathAncestor() const {
return GetAncestorDependentCompositingInputs().clip_path_ancestor;
}
@@ -880,9 +886,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
return has_self_painting_layer_descendant_;
}
- // See PaintLayerStackingNode::layer_to_overlay_scrollbars_painting_after_.
- bool NeedsReorderOverlayScrollbars() const {
- return needs_reorder_overlay_scrollbars_;
+ // See
+ // PaintLayerStackingNode::layer_to_overlay_overflow_controls_painting_after_.
+ bool NeedsReorderOverlayOverflowControls() const {
+ return needs_reorder_overlay_overflow_controls_;
}
// Returns true if there is a descendant with blend-mode that is
@@ -1277,8 +1284,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// PaintLayerPaintOrderIterator.
PaintLayerStackingNode* StackingNode() const { return stacking_node_.get(); }
- void SetNeedsReorderOverlayScrollbars(bool b) {
- needs_reorder_overlay_scrollbars_ = b;
+ void SetNeedsReorderOverlayOverflowControls(bool b) {
+ needs_reorder_overlay_overflow_controls_ = b;
}
// Self-painting layer is an optimization where we avoid the heavy Layer
@@ -1360,7 +1367,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
unsigned has_self_painting_layer_descendant_ : 1;
- unsigned needs_reorder_overlay_scrollbars_ : 1;
+ unsigned needs_reorder_overlay_overflow_controls_ : 1;
#if DCHECK_IS_ON()
mutable unsigned layer_list_mutation_allowed_ : 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 0f24a005540..90af3ca1350 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
@@ -48,7 +48,6 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
index e3b26f79ac6..ecf4b4e9a45 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -285,12 +285,7 @@ TEST_F(PaintLayerClipperTest, RoundedClipNested) {
EXPECT_EQ(PhysicalRect(0, 0, 500, 500), layer_bounds);
}
-// TODO(https://crbug.com/795645): This test is failing on the ChromeOS bot.
-#if defined(OS_CHROMEOS)
-TEST_F(PaintLayerClipperTest, DISABLED_ControlClipSelect) {
-#else
TEST_F(PaintLayerClipperTest, ControlClipSelect) {
-#endif
SetBodyInnerHTML(R"HTML(
<select id='target' style='position: relative; width: 100px;
background: none; border: none; padding: 0px 15px 0px 5px;'>
@@ -299,9 +294,8 @@ TEST_F(PaintLayerClipperTest, ControlClipSelect) {
</option>
</select>
)HTML");
- Element* target = GetDocument().getElementById("target");
- PaintLayer* target_paint_layer =
- ToLayoutBoxModelObject(target->GetLayoutObject())->Layer();
+ LayoutBox* target = ToLayoutBox(GetLayoutObjectByElementId("target"));
+ PaintLayer* target_paint_layer = target->Layer();
ClipRectsContext context(
GetDocument().GetLayoutView()->Layer(),
&GetDocument().GetLayoutView()->FirstFragment(), kUncachedClipRects,
@@ -315,14 +309,11 @@ TEST_F(PaintLayerClipperTest, ControlClipSelect) {
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
nullptr, layer_bounds, background_rect, foreground_rect);
-// The control clip for a select excludes the area for the down arrow.
-#if defined(OS_MACOSX)
- EXPECT_EQ(PhysicalRect(16, 9, 79, 13), foreground_rect.Rect());
-#elif defined(OS_WIN)
- EXPECT_EQ(PhysicalRect(17, 9, 60, 16), foreground_rect.Rect());
-#else
- EXPECT_EQ(PhysicalRect(17, 9, 60, 15), foreground_rect.Rect());
-#endif
+
+ PhysicalRect content_box_rect = target->PhysicalContentBoxRect();
+ EXPECT_GT(foreground_rect.Rect().X(),
+ content_box_rect.X() + target->Location().X());
+ EXPECT_LT(foreground_rect.Rect().Width(), content_box_rect.Width());
} // namespace blink
TEST_F(PaintLayerClipperTest, LayoutSVGRootChild) {
@@ -364,10 +355,9 @@ TEST_F(PaintLayerClipperTest, ContainPaintClip) {
PaintLayer* layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
- ClipRectsContext context(layer, &layer->GetLayoutObject().FirstFragment(),
- kPaintingClipRectsIgnoringOverflowClip,
- kIgnorePlatformOverlayScrollbarSize,
- kIgnoreOverflowClip);
+ ClipRectsContext context(
+ layer, &layer->GetLayoutObject().FirstFragment(), kPaintingClipRects,
+ kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);
PhysicalRect layer_bounds;
ClipRect background_rect, foreground_rect;
@@ -403,8 +393,8 @@ TEST_F(PaintLayerClipperTest, NestedContainPaintClip) {
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
ClipRectsContext context(
layer->Parent(), &layer->Parent()->GetLayoutObject().FirstFragment(),
- kPaintingClipRectsIgnoringOverflowClip,
- kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);
+ kPaintingClipRects, kIgnorePlatformOverlayScrollbarSize,
+ kIgnoreOverflowClip);
PhysicalRect layer_bounds;
ClipRect background_rect, foreground_rect;
@@ -648,10 +638,9 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithCSSClip) {
ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer();
PaintLayer* target =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
- ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(),
- kPaintingClipRectsIgnoringOverflowClip,
- kIgnorePlatformOverlayScrollbarSize,
- kIgnoreOverflowClip);
+ ClipRectsContext context(
+ root, &root->GetLayoutObject().FirstFragment(), kPaintingClipRects,
+ kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);
PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect());
PhysicalRect layer_bounds(infinite_rect);
ClipRect background_rect(infinite_rect);
@@ -684,10 +673,9 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithOverflowClip) {
ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer();
PaintLayer* target =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
- ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(),
- kPaintingClipRectsIgnoringOverflowClip,
- kIgnorePlatformOverlayScrollbarSize,
- kIgnoreOverflowClip);
+ ClipRectsContext context(
+ root, &root->GetLayoutObject().FirstFragment(), kPaintingClipRects,
+ kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);
PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect());
PhysicalRect layer_bounds(infinite_rect);
ClipRect background_rect(infinite_rect);
@@ -721,10 +709,9 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithBothClip) {
ToLayoutBoxModelObject(GetLayoutObjectByElementId("root"))->Layer();
PaintLayer* target =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
- ClipRectsContext context(root, &root->GetLayoutObject().FirstFragment(),
- kPaintingClipRectsIgnoringOverflowClip,
- kIgnorePlatformOverlayScrollbarSize,
- kIgnoreOverflowClip);
+ ClipRectsContext context(
+ root, &root->GetLayoutObject().FirstFragment(), kPaintingClipRects,
+ kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);
PhysicalRect infinite_rect(LayoutRect::InfiniteIntRect());
PhysicalRect layer_bounds(infinite_rect);
ClipRect background_rect(infinite_rect);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h
index 5bd84d94e03..19aa595c7b8 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_paint_order_iterator.h
@@ -57,11 +57,11 @@ class CORE_EXPORT PaintLayerPaintOrderIterator {
PaintLayer* Next();
- const Vector<PaintLayer*>* LayersPaintingOverlayScrollbarsAfter(
+ const Vector<PaintLayer*>* LayersPaintingOverlayOverflowControlsAfter(
const PaintLayer* layer) const {
return root_.stacking_node_
- ? root_.stacking_node_->LayersPaintingOverlayScrollbarsAfter(
- layer)
+ ? root_.stacking_node_
+ ->LayersPaintingOverlayOverflowControlsAfter(layer)
: nullptr;
}
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 23190ce43bc..51b5d4ec0e2 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
@@ -146,8 +146,8 @@ static bool ShouldCreateSubsequence(const PaintLayer& paint_layer,
if (painting_info.GetGlobalPaintFlags() &
kGlobalPaintFlattenCompositingLayers)
return false;
- if (paint_flags &
- (kPaintLayerPaintingOverlayScrollbars | kPaintLayerUncachedClipRects))
+ if (paint_flags & (kPaintLayerPaintingOverlayOverflowControls |
+ kPaintLayerUncachedClipRects))
return false;
return true;
@@ -337,8 +337,8 @@ PaintResult PaintLayerPainter::PaintLayerContents(
AdjustForPaintProperties(context, painting_info, paint_flags);
bool is_self_painting_layer = paint_layer_.IsSelfPaintingLayer();
- bool is_painting_overlay_scrollbars =
- paint_flags & kPaintLayerPaintingOverlayScrollbars;
+ bool is_painting_overlay_overflow_controls =
+ paint_flags & kPaintLayerPaintingOverlayOverflowControls;
bool is_painting_scrolling_content =
paint_flags & kPaintLayerPaintingCompositingScrollingPhase;
bool is_painting_composited_foreground =
@@ -355,7 +355,7 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// It is painted as part of the decoration phase which paints content that
// is not scrolled and should be above scrolled content.
bool should_paint_self_outline =
- is_self_painting_layer && !is_painting_overlay_scrollbars &&
+ is_self_painting_layer && !is_painting_overlay_overflow_controls &&
(is_painting_composited_decoration ||
(!is_painting_overflow_contents && !is_painting_mask)) &&
paint_layer_.GetLayoutObject().StyleRef().HasOutline();
@@ -415,12 +415,12 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// painting. Foreign content should never paint in this situation, as it
// is primary, not auxiliary.
!paint_layer_.IsUnderSVGHiddenContainer() && is_self_painting_layer &&
- !is_painting_overlay_scrollbars;
+ !is_painting_overlay_overflow_controls;
PaintLayerFragments layer_fragments;
if (should_paint_content || should_paint_self_outline ||
- is_painting_overlay_scrollbars) {
+ is_painting_overlay_overflow_controls) {
// Collect the fragments. This will compute the clip rectangles and paint
// offsets for each layer fragment.
paint_layer_.CollectFragments(
@@ -457,13 +457,14 @@ PaintResult PaintLayerPainter::PaintLayerContents(
(is_painting_root_layer &&
!(paint_flags & kPaintLayerPaintingSkipRootBackground)));
bool should_paint_neg_z_order_list =
- !is_painting_overlay_scrollbars &&
+ !is_painting_overlay_overflow_controls &&
(is_painting_scrolling_content ? is_painting_overflow_contents
: is_painting_composited_background);
bool should_paint_own_contents =
is_painting_composited_foreground && should_paint_content;
bool should_paint_normal_flow_and_pos_z_order_lists =
- is_painting_composited_foreground && !is_painting_overlay_scrollbars;
+ is_painting_composited_foreground &&
+ !is_painting_overlay_overflow_controls;
bool is_video = paint_layer_.GetLayoutObject().IsVideo();
base::Optional<ScopedPaintChunkProperties>
@@ -523,11 +524,11 @@ PaintResult PaintLayerPainter::PaintLayerContents(
}
if (paint_layer_.GetScrollableArea() &&
- paint_layer_.GetScrollableArea()->HasOverlayScrollbars()) {
- if (is_painting_overlay_scrollbars ||
- !paint_layer_.NeedsReorderOverlayScrollbars()) {
- PaintOverlayScrollbarsForFragments(layer_fragments, context,
- local_painting_info, paint_flags);
+ paint_layer_.GetScrollableArea()->HasOverlayOverflowControls()) {
+ if (is_painting_overlay_overflow_controls ||
+ !paint_layer_.NeedsReorderOverlayOverflowControls()) {
+ PaintOverlayOverflowControlsForFragments(
+ layer_fragments, context, local_painting_info, paint_flags);
}
}
@@ -538,12 +539,17 @@ PaintResult PaintLayerPainter::PaintLayerContents(
local_painting_info, paint_flags);
}
- if (!is_painting_overlay_scrollbars && paint_layer_.PaintsWithFilters() &&
- display_item_list_size_before_painting ==
- context.GetPaintController().NewDisplayItemList().size()) {
- // If a layer with filters painted nothing, we need to issue a no-op
- // display item to ensure the filters won't be ignored.
- PaintEmptyContentForFilters(context);
+ if (!is_painting_overlay_overflow_controls) {
+ // For filters, if the layer painted nothing, we need to issue a no-op
+ // display item to ensure the filters won't be ignored. For backdrop
+ // filters, we issue the display item regardless of other paintings to
+ // ensure correct bounds of the composited layer for the backdrop filter.
+ if ((paint_layer_.PaintsWithFilters() &&
+ display_item_list_size_before_painting ==
+ context.GetPaintController().NewDisplayItemList().size()) ||
+ paint_layer_.GetLayoutObject().HasBackdropFilter()) {
+ PaintEmptyContentForFilters(context);
+ }
}
} // FilterPainter block
@@ -654,14 +660,15 @@ PaintResult PaintLayerPainter::PaintChildren(
kMayBeClippedByCullRect)
result = kMayBeClippedByCullRect;
- if (const auto* layers_painting_overlay_scrollbars_after =
- iterator.LayersPaintingOverlayScrollbarsAfter(child)) {
- for (auto* reparent_scrollbar_layer :
- *layers_painting_overlay_scrollbars_after) {
- DCHECK(reparent_scrollbar_layer->NeedsReorderOverlayScrollbars());
- if (PaintLayerPainter(*reparent_scrollbar_layer)
+ if (const auto* layers_painting_overlay_overflow_controls_after =
+ iterator.LayersPaintingOverlayOverflowControlsAfter(child)) {
+ for (auto* reparent_overflow_controls_layer :
+ *layers_painting_overlay_overflow_controls_after) {
+ DCHECK(reparent_overflow_controls_layer
+ ->NeedsReorderOverlayOverflowControls());
+ if (PaintLayerPainter(*reparent_overflow_controls_layer)
.Paint(context, painting_info,
- kPaintLayerPaintingOverlayScrollbars) ==
+ kPaintLayerPaintingOverlayOverflowControls) ==
kMayBeClippedByCullRect)
result = kMayBeClippedByCullRect;
}
@@ -671,23 +678,24 @@ PaintResult PaintLayerPainter::PaintChildren(
return result;
}
-void PaintLayerPainter::PaintOverlayScrollbarsForFragments(
+void PaintLayerPainter::PaintOverlayOverflowControlsForFragments(
const PaintLayerFragments& layer_fragments,
GraphicsContext& context,
const PaintLayerPaintingInfo& painting_info,
PaintLayerFlags paint_flags) {
DCHECK(paint_layer_.GetScrollableArea() &&
- paint_layer_.GetScrollableArea()->HasOverlayScrollbars());
+ paint_layer_.GetScrollableArea()->HasOverlayOverflowControls());
- // We don't need to paint composited scrollbars.
+ // We don't need to paint composited overflow controls.
if (paint_layer_.GetScrollableArea()->HasLayerForHorizontalScrollbar() ||
- paint_layer_.GetScrollableArea()->HasLayerForVerticalScrollbar())
+ paint_layer_.GetScrollableArea()->HasLayerForVerticalScrollbar() ||
+ paint_layer_.GetScrollableArea()->HasLayerForScrollCorner())
return;
ForAllFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
if (!fragment.background_rect.IsEmpty()) {
- PaintFragmentWithPhase(PaintPhase::kOverlayScrollbars, fragment,
+ PaintFragmentWithPhase(PaintPhase::kOverlayOverflowControls, fragment,
context, fragment.background_rect,
painting_info, paint_flags);
}
@@ -776,7 +784,7 @@ void PaintLayerPainter::PaintForegroundForFragments(
local_painting_info, paint_flags);
}
- if (RuntimeEnabledFeatures::ForcedColorsEnabled()) {
+ if (paint_layer_.GetLayoutObject().GetDocument().InForcedColorsMode()) {
PaintForegroundForFragmentsWithPhase(
PaintPhase::kForcedColorsModeBackplate, layer_fragments, context,
local_painting_info, paint_flags);
@@ -855,13 +863,13 @@ void PaintLayerPainter::PaintMaskForFragments(
});
}
-void PaintLayerPainter::PaintOverlayScrollbars(
+void PaintLayerPainter::PaintOverlayOverflowControls(
GraphicsContext& context,
const CullRect& cull_rect,
const GlobalPaintFlags paint_flags) {
PaintLayerPaintingInfo painting_info(&paint_layer_, cull_rect, paint_flags,
PhysicalOffset());
- Paint(context, painting_info, kPaintLayerPaintingOverlayScrollbars);
+ Paint(context, painting_info, kPaintLayerPaintingOverlayOverflowControls);
}
void PaintLayerPainter::FillMaskingFragment(GraphicsContext& context,
@@ -879,7 +887,8 @@ void PaintLayerPainter::FillMaskingFragment(GraphicsContext& context,
// Generate a no-op DrawingDisplayItem to ensure a non-empty chunk for the
// filter without content.
void PaintLayerPainter::PaintEmptyContentForFilters(GraphicsContext& context) {
- DCHECK(paint_layer_.PaintsWithFilters());
+ DCHECK(paint_layer_.PaintsWithFilters() ||
+ paint_layer_.GetLayoutObject().HasBackdropFilter());
ScopedPaintChunkProperties paint_chunk_properties(
context.GetPaintController(),
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 a6777bc99aa..e61f2ceadc5 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
@@ -49,9 +49,9 @@ class CORE_EXPORT PaintLayerPainter {
const PaintLayerPaintingInfo&,
PaintLayerFlags);
- void PaintOverlayScrollbars(GraphicsContext&,
- const CullRect&,
- const GlobalPaintFlags);
+ void PaintOverlayOverflowControls(GraphicsContext&,
+ const CullRect&,
+ const GlobalPaintFlags);
// Returns true if the painted output of this PaintLayer and its children is
// invisible and therefore can't impact painted output.
@@ -94,10 +94,10 @@ class CORE_EXPORT PaintLayerPainter {
GraphicsContext&,
const PaintLayerPaintingInfo&,
PaintLayerFlags);
- void PaintOverlayScrollbarsForFragments(const PaintLayerFragments&,
- GraphicsContext&,
- const PaintLayerPaintingInfo&,
- PaintLayerFlags);
+ void PaintOverlayOverflowControlsForFragments(const PaintLayerFragments&,
+ GraphicsContext&,
+ const PaintLayerPaintingInfo&,
+ PaintLayerFlags);
void PaintMaskForFragments(const PaintLayerFragments&,
GraphicsContext&,
const PaintLayerPaintingInfo&,
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 ee0e5c9658c..e80c5ef9422 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
@@ -372,7 +372,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_FALSE(target_layer->NeedsRepaint());
EXPECT_TRUE(PaintWithoutCommit());
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled())
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
EXPECT_EQ(3, NumCachedNewItems());
else
EXPECT_EQ(2, NumCachedNewItems());
@@ -411,7 +411,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceRetainsPreviousPaintResult) {
// a partially painted layer will trigger repaint.
EXPECT_FALSE(target_layer->NeedsRepaint());
EXPECT_TRUE(PaintWithoutCommit());
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled())
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
EXPECT_EQ(3, NumCachedNewItems());
else
EXPECT_EQ(2, NumCachedNewItems());
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 2c5c0bc43a2..75dbb3da7c3 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
@@ -64,7 +64,7 @@ enum PaintLayerFlag {
kPaintLayerNoFlag = 0,
kPaintLayerHaveTransparency = 1,
kPaintLayerUncachedClipRects = 1 << 2,
- kPaintLayerPaintingOverlayScrollbars = 1 << 3,
+ kPaintLayerPaintingOverlayOverflowControls = 1 << 3,
kPaintLayerPaintingCompositingBackgroundPhase = 1 << 4,
kPaintLayerPaintingCompositingForegroundPhase = 1 << 5,
kPaintLayerPaintingCompositingMaskPhase = 1 << 6,
@@ -139,8 +139,8 @@ inline String PaintLayerFlagsToDebugString(PaintLayerFlags flags) {
append("kPaintLayerHaveTransparency");
if (flags & kPaintLayerUncachedClipRects)
append("kPaintLayerUncachedClipRects");
- if (flags & kPaintLayerPaintingOverlayScrollbars)
- append("kPaintLayerPaintingOverlayScrollbars");
+ if (flags & kPaintLayerPaintingOverlayOverflowControls)
+ append("kPaintLayerPaintingOverlayOverflowControls");
if (flags & kPaintLayerPaintingCompositingScrollingPhase)
append("kPaintLayerPaintingCompositingScrollingPhase");
if (flags & kPaintLayerPaintingOverflowContents)
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_resource_info.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_resource_info.h
index 9de93eca472..90aa4a4ee03 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_resource_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_resource_info.h
@@ -50,7 +50,7 @@ class PaintLayer;
// painting non-hardware accelerated filters (FilterEffect). Hardware
// accelerated CSS filters use CompositorFilterOperations, that is backed by cc.
class PaintLayerResourceInfo final
- : public GarbageCollectedFinalized<PaintLayerResourceInfo>,
+ : public GarbageCollected<PaintLayerResourceInfo>,
public SVGResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(PaintLayerResourceInfo);
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 61bb001e432..399087fa006 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
@@ -71,10 +71,10 @@
#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/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"
#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
@@ -84,13 +84,11 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/fragment_anchor.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
-#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
-#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
#include "third_party/blink/renderer/core/scroll/scroll_alignment.h"
@@ -128,6 +126,7 @@ PaintLayerScrollableArea::PaintLayerScrollableArea(PaintLayer& layer)
needs_relayout_(false),
had_horizontal_scrollbar_before_relayout_(false),
had_vertical_scrollbar_before_relayout_(false),
+ had_resizer_before_relayout_(false),
scroll_origin_changed_(false),
scrollbar_manager_(*this),
scroll_corner_(nullptr),
@@ -145,8 +144,9 @@ PaintLayerScrollableArea::PaintLayerScrollableArea(PaintLayer& layer)
GetScrollAnimator().SetCurrentOffset(scroll_offset_);
element->SetSavedLayerScrollOffset(ScrollOffset());
}
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled())
- UpdateResizerAreaSet();
+
+ GetLayoutBox()->GetDocument().GetSnapCoordinator().AddSnapContainer(
+ *GetLayoutBox());
}
PaintLayerScrollableArea::~PaintLayerScrollableArea() {
@@ -162,6 +162,9 @@ void PaintLayerScrollableArea::DidScroll(const FloatPoint& position) {
void PaintLayerScrollableArea::DisposeImpl() {
rare_data_.reset();
+ GetLayoutBox()->GetDocument().GetSnapCoordinator().RemoveSnapContainer(
+ *GetLayoutBox());
+
if (InResizeMode() && !GetLayoutBox()->DocumentBeingDestroyed()) {
if (LocalFrame* frame = GetLayoutBox()->GetFrame())
frame->GetEventHandler().ResizeScrollableAreaDestroyed();
@@ -185,13 +188,6 @@ void PaintLayerScrollableArea::DisposeImpl() {
element->SetSavedLayerScrollOffset(scroll_offset_);
}
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- if (LocalFrame* frame = GetLayoutBox()->GetFrame()) {
- if (LocalFrameView* frame_view = frame->View())
- frame_view->RemoveResizerArea(*GetLayoutBox());
- }
- }
-
// Note: it is not safe to call ScrollAnchor::clear if the document is being
// destroyed, because LayoutObjectChildList::removeChildNode skips the call to
// willBeRemovedFromTree,
@@ -315,6 +311,7 @@ IntRect PaintLayerScrollableArea::PaintLayerScrollableArea::CornerRect(
.GetPage()
->GetChromeClient()
.WindowToViewportScalar(
+ GetLayoutBox()->GetFrame(),
GetPageScrollbarTheme().ScrollbarThickness());
vertical_thickness = horizontal_thickness;
} else if (VerticalScrollbar() && !HorizontalScrollbar()) {
@@ -742,16 +739,6 @@ bool PaintLayerScrollableArea::ScrollbarsCanBeActive() const {
return !!frame_view->GetFrame().GetDocument();
}
-IntRect PaintLayerScrollableArea::ScrollableAreaBoundingBox() const {
- if (LocalFrame* frame = GetLayoutBox()->GetFrame()) {
- if (LocalFrameView* local_root = frame->LocalFrameRoot().View()) {
- return local_root->RootFrameToDocument(frame->View()->ConvertToRootFrame(
- GetLayoutBox()->AbsoluteBoundingBoxRect(0)));
- }
- }
- return IntRect();
-}
-
void PaintLayerScrollableArea::RegisterForAnimation() {
if (HasBeenDisposed())
return;
@@ -905,6 +892,10 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
UpdateScrollDimensions();
+ bool has_resizer = GetLayoutBox()->CanResize();
+ bool resizer_will_change = had_resizer_before_relayout_ != has_resizer;
+ had_resizer_before_relayout_ = has_resizer;
+
bool had_horizontal_scrollbar = HasHorizontalScrollbar();
bool had_vertical_scrollbar = HasVerticalScrollbar();
@@ -949,8 +940,7 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
}
}
- if (HasScrollbar())
- UpdateScrollCornerStyle();
+ UpdateScrollCornerStyle();
Layer()->UpdateSelfPaintingLayer();
@@ -1005,6 +995,8 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
}
}
}
+ } else if (!HasScrollbar() && resizer_will_change) {
+ Layer()->DirtyStackingContextZOrderLists();
}
{
@@ -1188,8 +1180,6 @@ void PaintLayerScrollableArea::UpdateAfterStyleChange(
ComputeScrollbarExistence(needs_horizontal_scrollbar,
needs_vertical_scrollbar, kForbidAddingAutoBars);
- if (!RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled())
- UpdateResizerAreaSet();
UpdateResizerStyle(old_style);
// Avoid some unnecessary computation if there were and will be no scrollbars.
@@ -1351,13 +1341,14 @@ static inline const LayoutObject& ScrollbarStyleSource(
// can scroll.
Element* body = doc.body();
if (body && body->GetLayoutObject() && body->GetLayoutObject()->IsBox() &&
- body->GetLayoutObject()->StyleRef().HasPseudoStyle(kPseudoIdScrollbar))
+ body->GetLayoutObject()->StyleRef().HasPseudoElementStyle(
+ kPseudoIdScrollbar))
return *body->GetLayoutObject();
// If the <body> didn't have a custom style, then the root element might.
Element* doc_element = doc.documentElement();
if (doc_element && doc_element->GetLayoutObject() &&
- doc_element->GetLayoutObject()->StyleRef().HasPseudoStyle(
+ doc_element->GetLayoutObject()->StyleRef().HasPseudoElementStyle(
kPseudoIdScrollbar))
return *doc_element->GetLayoutObject();
}
@@ -1375,9 +1366,9 @@ int PaintLayerScrollableArea::HypotheticalScrollbarThickness(
const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox());
bool has_custom_scrollbar_style =
- style_source.StyleRef().HasPseudoStyle(kPseudoIdScrollbar);
+ style_source.StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar);
if (has_custom_scrollbar_style) {
- return LayoutScrollbar::HypotheticalScrollbarThickness(
+ return CustomScrollbar::HypotheticalScrollbarThickness(
orientation, *GetLayoutBox(), style_source);
}
@@ -1394,7 +1385,7 @@ int PaintLayerScrollableArea::HypotheticalScrollbarThickness(
->GetDocument()
.GetPage()
->GetChromeClient()
- .WindowToViewportScalar(thickness);
+ .WindowToViewportScalar(GetLayoutBox()->GetFrame(), thickness);
}
bool PaintLayerScrollableArea::NeedsScrollbarReconstruction() const {
@@ -1404,7 +1395,7 @@ bool PaintLayerScrollableArea::NeedsScrollbarReconstruction() const {
const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox());
bool needs_custom =
style_source.IsBox() &&
- style_source.StyleRef().HasPseudoStyle(kPseudoIdScrollbar);
+ style_source.StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar);
Scrollbar* scrollbars[] = {HorizontalScrollbar(), VerticalScrollbar()};
@@ -1419,7 +1410,7 @@ bool PaintLayerScrollableArea::NeedsScrollbarReconstruction() const {
if (needs_custom) {
DCHECK(scrollbar->IsCustomScrollbar());
// We have a custom scrollbar with a stale m_owner.
- if (To<LayoutScrollbar>(scrollbar)->StyleSource()->GetLayoutObject() !=
+ if (To<CustomScrollbar>(scrollbar)->StyleSource()->GetLayoutObject() !=
style_source) {
return true;
}
@@ -1635,27 +1626,41 @@ int PaintLayerScrollableArea::HorizontalScrollbarHeight(
return HorizontalScrollbar()->ScrollbarThickness();
}
+const cc::SnapContainerData* PaintLayerScrollableArea::GetSnapContainerData()
+ const {
+ return RareData() && RareData()->snap_container_data_
+ ? &RareData()->snap_container_data_.value()
+ : nullptr;
+}
+
+void PaintLayerScrollableArea::SetSnapContainerData(
+ base::Optional<cc::SnapContainerData> data) {
+ EnsureRareData().snap_container_data_ = data;
+}
+
void PaintLayerScrollableArea::SnapAfterScrollbarScrolling(
ScrollbarOrientation orientation) {
- SnapCoordinator* snap_coordinator =
- GetLayoutBox()->GetDocument().GetSnapCoordinator();
- if (!snap_coordinator)
- return;
-
- snap_coordinator->SnapAtCurrentPosition(*GetLayoutBox(),
- orientation == kHorizontalScrollbar,
- orientation == kVerticalScrollbar);
+ GetLayoutBox()->GetDocument().GetSnapCoordinator().SnapAtCurrentPosition(
+ *GetLayoutBox(), orientation == kHorizontalScrollbar,
+ orientation == kVerticalScrollbar);
}
bool PaintLayerScrollableArea::HasOverflowControls() const {
// We do not need to check for ScrollCorner because it only exists iff there
// are scrollbars, see: |ScrollCornerRect| and |UpdateScrollCornerStyle|.
- // TODO(pdr, majinfeng1): Re-enable this DCHECK when https://crbug.com/999062
- // is resolved. This is temporarily disabled to prevent crashes.
- // DCHECK(!ScrollCorner() || HasScrollbar());
+ DCHECK(!ScrollCorner() || HasScrollbar());
return HasScrollbar() || GetLayoutBox()->CanResize();
}
+bool PaintLayerScrollableArea::HasOverlayOverflowControls() const {
+ return HasOverlayScrollbars() ||
+ (!HasScrollbar() && GetLayoutBox()->CanResize());
+}
+
+bool PaintLayerScrollableArea::HasNonOverlayOverflowControls() const {
+ return HasScrollbar() && !HasOverlayScrollbars();
+}
+
void PaintLayerScrollableArea::PositionOverflowControls() {
if (!HasOverflowControls())
return;
@@ -1684,21 +1689,23 @@ void PaintLayerScrollableArea::PositionOverflowControls() {
}
void PaintLayerScrollableArea::UpdateScrollCornerStyle() {
- if (!scroll_corner_ && !HasScrollbar())
- return;
- if (!scroll_corner_ && HasOverlayScrollbars())
+ if (!HasNonOverlayOverflowControls()) {
+ if (scroll_corner_) {
+ scroll_corner_->Destroy();
+ scroll_corner_ = nullptr;
+ }
return;
-
+ }
const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox());
scoped_refptr<ComputedStyle> corner =
GetLayoutBox()->HasOverflowClip()
- ? style_source.GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdScrollbarCorner),
+ ? style_source.GetUncachedPseudoElementStyle(
+ PseudoElementStyleRequest(kPseudoIdScrollbarCorner),
style_source.Style())
: scoped_refptr<ComputedStyle>(nullptr);
if (corner) {
if (!scroll_corner_) {
- scroll_corner_ = LayoutScrollbarPart::CreateAnonymous(
+ scroll_corner_ = LayoutCustomScrollbarPart::CreateAnonymous(
&GetLayoutBox()->GetDocument(), this);
}
scroll_corner_->SetStyle(std::move(corner));
@@ -1835,19 +1842,6 @@ bool PaintLayerScrollableArea::HitTestResizerInFragments(
return false;
}
-void PaintLayerScrollableArea::UpdateResizerAreaSet() {
- LocalFrame* frame = GetLayoutBox()->GetFrame();
- if (!frame)
- return;
- LocalFrameView* frame_view = frame->View();
- if (!frame_view)
- return;
- if (GetLayoutBox()->CanResize())
- frame_view->AddResizerArea(*GetLayoutBox());
- else
- frame_view->RemoveResizerArea(*GetLayoutBox());
-}
-
void PaintLayerScrollableArea::UpdateResizerStyle(
const ComputedStyle* old_style) {
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && old_style &&
@@ -1864,12 +1858,13 @@ void PaintLayerScrollableArea::UpdateResizerStyle(
const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox());
scoped_refptr<ComputedStyle> resizer =
GetLayoutBox()->HasOverflowClip()
- ? style_source.GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdResizer), style_source.Style())
+ ? style_source.GetUncachedPseudoElementStyle(
+ PseudoElementStyleRequest(kPseudoIdResizer),
+ style_source.Style())
: scoped_refptr<ComputedStyle>(nullptr);
if (resizer) {
if (!resizer_) {
- resizer_ = LayoutScrollbarPart::CreateAnonymous(
+ resizer_ = LayoutCustomScrollbarPart::CreateAnonymous(
&GetLayoutBox()->GetDocument(), this);
}
resizer_->SetStyle(std::move(resizer));
@@ -2079,7 +2074,7 @@ PhysicalRect PaintLayerScrollableArea::ScrollIntoView(
end_point = GetLayoutBox()
->GetDocument()
.GetSnapCoordinator()
- ->GetSnapPosition(*GetLayoutBox(), *strategy)
+ .GetSnapPosition(*GetLayoutBox(), *strategy)
.value_or(end_point);
new_scroll_offset = ScrollPositionToOffset(end_point);
@@ -2165,12 +2160,10 @@ void PaintLayerScrollableArea::UpdateScrollableAreaSet() {
// PaintPropertyTreeBuilder::updateScrollAndScrollTranslation).
GetLayoutBox()->SetNeedsPaintPropertyUpdate();
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // Scroll hit test display items depend on whether the box scrolls overflow.
- // The scroll hit test display items paint in the background phase
- // (see: BoxPainter::PaintBoxDecorationBackground).
- GetLayoutBox()->SetBackgroundNeedsFullPaintInvalidation();
- }
+ // Scroll hit test display items depend on whether the box scrolls overflow.
+ // The scroll hit test display items paint in the background phase
+ // (see: BoxPainter::PaintBoxDecorationBackground).
+ GetLayoutBox()->SetBackgroundNeedsFullPaintInvalidation();
if (scrolls_overflow_) {
DCHECK(CanHaveOverflowScrollbars(*GetLayoutBox()));
@@ -2242,7 +2235,7 @@ bool PaintLayerScrollableArea::ShouldScrollOnMainThread() const {
static bool LayerNodeMayNeedCompositedScrolling(const PaintLayer* layer) {
// Don't force composite scroll for select or text input elements.
if (Node* node = layer->GetLayoutObject().GetNode()) {
- if (IsHTMLSelectElement(node))
+ if (IsA<HTMLSelectElement>(node))
return false;
if (TextControlElement* text_control = EnclosingTextControl(node)) {
if (IsHTMLInputElement(text_control)) {
@@ -2261,13 +2254,8 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
if (CompositingReasonFinder::RequiresCompositingForRootScroller(*layer))
return true;
- // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
- // main-thread AnimationWorklet and don't need to promote the scroll-source.
- Node* node = layer->GetLayoutObject().GetNode();
- if (!layer->ScrollsOverflow() &&
- !ScrollTimeline::HasActiveScrollTimeline(node)) {
+ if (!layer->ScrollsOverflow())
return false;
- }
if (layer->Size().IsEmpty())
return false;
@@ -2291,10 +2279,7 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
true) &&
!layer->CompositesWithTransform() && !layer->CompositesWithOpacity();
- // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
- // main-thread AnimationWorklet and don't need to promote the scroll-source.
- if (!ScrollTimeline::HasActiveScrollTimeline(node) &&
- !layer_has_been_composited &&
+ if (!layer_has_been_composited &&
!layer->Compositor()->PreferCompositingToLCDTextEnabled() &&
!background_supports_lcd_text) {
if (layer->CompositesWithOpacity()) {
@@ -2357,8 +2342,9 @@ bool PaintLayerScrollableArea::VisualViewportSuppliesScrollbars() const {
}
bool PaintLayerScrollableArea::ScheduleAnimation() {
- if (ChromeClient* client = GetChromeClient()) {
- client->ScheduleAnimation(GetLayoutBox()->GetFrame()->View());
+ if (ChromeClient* client =
+ GetLayoutBox()->GetFrameView()->GetChromeClient()) {
+ client->ScheduleAnimation(GetLayoutBox()->GetFrameView());
return true;
}
return false;
@@ -2381,9 +2367,14 @@ PaintLayerScrollableArea::GetCompositorAnimationTimeline() const {
->GetCompositorAnimationTimeline();
}
-void PaintLayerScrollableArea::GetTickmarks(Vector<IntRect>& tickmarks) const {
+bool PaintLayerScrollableArea::HasTickmarks() const {
+ return layer_->IsRootLayer() && ToLayoutView(GetLayoutBox())->HasTickmarks();
+}
+
+Vector<IntRect> PaintLayerScrollableArea::GetTickmarks() const {
if (layer_->IsRootLayer())
- tickmarks = ToLayoutView(GetLayoutBox())->GetTickmarks();
+ return ToLayoutView(GetLayoutBox())->GetTickmarks();
+ return Vector<IntRect>();
}
void PaintLayerScrollableArea::ScrollbarManager::SetHasHorizontalScrollbar(
@@ -2434,10 +2425,10 @@ Scrollbar* PaintLayerScrollableArea::ScrollbarManager::CreateScrollbar(
const LayoutObject& style_source =
ScrollbarStyleSource(*ScrollableArea()->GetLayoutBox());
bool has_custom_scrollbar_style =
- style_source.StyleRef().HasPseudoStyle(kPseudoIdScrollbar);
+ style_source.StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar);
if (has_custom_scrollbar_style) {
DCHECK(style_source.GetNode() && style_source.GetNode()->IsElementNode());
- scrollbar = LayoutScrollbar::CreateCustomScrollbar(
+ scrollbar = CustomScrollbar::CreateCustomScrollbar(
ScrollableArea(), orientation, To<Element>(style_source.GetNode()));
} else {
ScrollbarControlSize scrollbar_size = kRegularScrollbar;
@@ -2652,7 +2643,7 @@ void PaintLayerScrollableArea::DidAddScrollbar(
void PaintLayerScrollableArea::WillRemoveScrollbar(
Scrollbar& scrollbar,
ScrollbarOrientation orientation) {
- if (layer_->NeedsReorderOverlayScrollbars()) {
+ if (layer_->NeedsReorderOverlayOverflowControls()) {
// Z-order of reparented scrollbar is updated along with the z-order lists.
DCHECK(scrollbar.IsOverlayScrollbar());
layer_->DirtyStackingContextZOrderLists();
@@ -2669,41 +2660,20 @@ void PaintLayerScrollableArea::WillRemoveScrollbar(
ScrollableArea::WillRemoveScrollbar(scrollbar, orientation);
}
-static IntRect ScrollControlVisualRect(const IntRect& scroll_control_rect,
- const LayoutBox& box,
- const PaintInvalidatorContext& context,
- const IntRect& previous_visual_rect) {
- IntRect visual_rect(scroll_control_rect);
-#if DCHECK_IS_ON()
- FindVisualRectNeedingUpdateScope finder(box, context, previous_visual_rect,
- visual_rect);
-#endif
- if (!context.NeedsVisualRectUpdate(box))
- return previous_visual_rect;
-
- // No need to apply any paint offset. Scroll controls paint in a different
- // transform space than their contained box (the scrollbarPaintOffset
- // transform node).
- return visual_rect;
-}
-
// Returns true if the scroll control is invalidated.
-static bool InvalidatePaintOfScrollControlIfNeeded(
+static bool ScrollControlNeedsPaintInvalidation(
const IntRect& new_visual_rect,
const IntRect& previous_visual_rect,
- bool needs_paint_invalidation,
- LayoutBox& box,
- const LayoutBoxModelObject& paint_invalidation_container) {
- bool should_invalidate_new_rect = needs_paint_invalidation;
- if (new_visual_rect != previous_visual_rect) {
- should_invalidate_new_rect = true;
- } else if (previous_visual_rect.IsEmpty()) {
+ bool needs_paint_invalidation) {
+ if (new_visual_rect != previous_visual_rect)
+ return true;
+ if (previous_visual_rect.IsEmpty()) {
DCHECK(new_visual_rect.IsEmpty());
// Do not issue an empty invalidation.
- should_invalidate_new_rect = false;
+ return false;
}
- return should_invalidate_new_rect;
+ return needs_paint_invalidation;
}
static IntRect InvalidatePaintOfScrollbarIfNeeded(
@@ -2711,29 +2681,25 @@ static IntRect InvalidatePaintOfScrollbarIfNeeded(
GraphicsLayer* graphics_layer,
bool& previously_was_overlay,
const IntRect& previous_visual_rect,
- bool needs_paint_invalidation_arg,
+ bool needs_paint_invalidation,
LayoutBox& box,
+ bool& box_geometry_has_been_invalidated,
const PaintInvalidatorContext& context) {
bool is_overlay = scrollbar && scrollbar->IsOverlayScrollbar();
IntRect new_visual_rect;
// Calculate visual rect of the scrollbar, except overlay composited
// scrollbars because we invalidate the graphics layer only.
- if (scrollbar && !(graphics_layer && is_overlay)) {
- new_visual_rect = ScrollControlVisualRect(scrollbar->FrameRect(), box,
- context, previous_visual_rect);
- }
+ // TODO(wangxianzhu): Investigate how non-empty visual rect of composited
+ // scrollbar affects GPU texture memory (http://crbug.com/1011996).
+ if (scrollbar && !(graphics_layer && is_overlay))
+ new_visual_rect = scrollbar->FrameRect();
- bool needs_paint_invalidation = needs_paint_invalidation_arg;
if (needs_paint_invalidation && graphics_layer) {
// If the scrollbar needs paint invalidation but didn't change location/size
// or the scrollbar is an overlay scrollbar (visual rect is empty),
// invalidating the graphics layer is enough (which has been done in
// ScrollableArea::setScrollbarNeedsPaintInvalidation()).
- // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate
- // the old and new location of the scrollbar on the box's paint invalidation
- // container to ensure newly expanded/shrunk areas of the box to be
- // invalidated.
needs_paint_invalidation = false;
DCHECK(!graphics_layer->PaintsContentOrHitTest() ||
graphics_layer->GetPaintController().GetPaintArtifact().IsEmpty());
@@ -2741,12 +2707,10 @@ static IntRect InvalidatePaintOfScrollbarIfNeeded(
// Invalidate the box's display item client if the box's padding box size is
// affected by change of the non-overlay scrollbar width. We detect change of
- // visual rect size instead of change of scrollbar width change, which may
- // have some false-positives (e.g. the scrollbar changed length but not width)
- // but won't invalidate more than expected because in the false-positive case
- // the box must have changed size and have been invalidated.
- const LayoutBoxModelObject& paint_invalidation_container =
- *context.paint_invalidation_container;
+ // visual rect size instead of change of scrollbar width, which may have some
+ // false-positives (e.g. the scrollbar changed length but not width) but won't
+ // invalidate more than expected because in the false-positive case the box
+ // must have changed size and have been invalidated.
IntSize new_scrollbar_used_space_in_box;
if (!is_overlay)
new_scrollbar_used_space_in_box = new_visual_rect.Size();
@@ -2756,28 +2720,28 @@ static IntRect InvalidatePaintOfScrollbarIfNeeded(
// The IsEmpty() check avoids invalidaiton in cases when the visual rect
// changes from (0,0 0x0) to (0,0 0x100).
- if (!(new_scrollbar_used_space_in_box.IsEmpty() &&
+ if (!box_geometry_has_been_invalidated &&
+ !(new_scrollbar_used_space_in_box.IsEmpty() &&
previous_scrollbar_used_space_in_box.IsEmpty()) &&
new_scrollbar_used_space_in_box != previous_scrollbar_used_space_in_box) {
context.painting_layer->SetNeedsRepaint();
ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
box, PaintInvalidationReason::kGeometry);
+ box_geometry_has_been_invalidated = true;
}
- bool invalidated = InvalidatePaintOfScrollControlIfNeeded(
- new_visual_rect, previous_visual_rect, needs_paint_invalidation, box,
- paint_invalidation_container);
-
previously_was_overlay = is_overlay;
- if (!invalidated || !scrollbar || graphics_layer)
+ if (!scrollbar || graphics_layer ||
+ !ScrollControlNeedsPaintInvalidation(
+ new_visual_rect, previous_visual_rect, needs_paint_invalidation))
return new_visual_rect;
context.painting_layer->SetNeedsRepaint();
ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
*scrollbar, PaintInvalidationReason::kScrollControl);
if (scrollbar->IsCustomScrollbar()) {
- To<LayoutScrollbar>(scrollbar)
+ To<CustomScrollbar>(scrollbar)
->InvalidateDisplayItemClientsOfScrollbarParts();
}
@@ -2787,37 +2751,40 @@ static IntRect InvalidatePaintOfScrollbarIfNeeded(
void PaintLayerScrollableArea::InvalidatePaintOfScrollControlsIfNeeded(
const PaintInvalidatorContext& context) {
LayoutBox& box = *GetLayoutBox();
+ bool box_geometry_has_been_invalidated = false;
SetHorizontalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
HorizontalScrollbar(), LayerForHorizontalScrollbar(),
horizontal_scrollbar_previously_was_overlay_,
horizontal_scrollbar_visual_rect_,
- HorizontalScrollbarNeedsPaintInvalidation(), box, context));
+ HorizontalScrollbarNeedsPaintInvalidation(), box,
+ box_geometry_has_been_invalidated, context));
SetVerticalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
VerticalScrollbar(), LayerForVerticalScrollbar(),
vertical_scrollbar_previously_was_overlay_,
vertical_scrollbar_visual_rect_,
- VerticalScrollbarNeedsPaintInvalidation(), box, context));
-
- IntRect scroll_corner_and_resizer_visual_rect =
- ScrollControlVisualRect(ScrollCornerAndResizerRect(), box, context,
- scroll_corner_and_resizer_visual_rect_);
- const LayoutBoxModelObject& paint_invalidation_container =
- *context.paint_invalidation_container;
- if (InvalidatePaintOfScrollControlIfNeeded(
+ VerticalScrollbarNeedsPaintInvalidation(), box,
+ box_geometry_has_been_invalidated, context));
+
+ IntRect scroll_corner_and_resizer_visual_rect = ScrollCornerAndResizerRect();
+ if (ScrollControlNeedsPaintInvalidation(
scroll_corner_and_resizer_visual_rect,
scroll_corner_and_resizer_visual_rect_,
- ScrollCornerNeedsPaintInvalidation(), box,
- paint_invalidation_container)) {
+ ScrollCornerNeedsPaintInvalidation())) {
SetScrollCornerAndResizerVisualRect(scroll_corner_and_resizer_visual_rect);
- if (LayoutScrollbarPart* scroll_corner = ScrollCorner()) {
+ if (LayoutCustomScrollbarPart* scroll_corner = ScrollCorner()) {
ObjectPaintInvalidator(*scroll_corner)
.InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
PaintInvalidationReason::kScrollControl);
}
- if (LayoutScrollbarPart* resizer = Resizer()) {
+ if (LayoutCustomScrollbarPart* resizer = Resizer()) {
ObjectPaintInvalidator(*resizer)
.InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
PaintInvalidationReason::kScrollControl);
+ } else if (!box_geometry_has_been_invalidated && box.CanResize() &&
+ !HasLayerForScrollCorner()) {
+ context.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
+ box, PaintInvalidationReason::kGeometry);
}
}
@@ -2847,9 +2814,9 @@ void PaintLayerScrollableArea::SetVerticalScrollbarVisualRect(
void PaintLayerScrollableArea::SetScrollCornerAndResizerVisualRect(
const IntRect& rect) {
scroll_corner_and_resizer_visual_rect_ = rect;
- if (LayoutScrollbarPart* scroll_corner = ScrollCorner())
+ if (LayoutCustomScrollbarPart* scroll_corner = ScrollCorner())
scroll_corner->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
- if (LayoutScrollbarPart* resizer = Resizer())
+ if (LayoutCustomScrollbarPart* resizer = Resizer())
resizer->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
}
@@ -2863,9 +2830,13 @@ void PaintLayerScrollableArea::DidScrollWithScrollbar(
WebInputEvent::Type type) {
WebFeature scrollbar_use_uma;
switch (part) {
- case kBackButtonStartPart:
- case kForwardButtonStartPart:
case kBackButtonEndPart:
+ case kForwardButtonStartPart:
+ UseCounter::Count(
+ GetLayoutBox()->GetDocument(),
+ WebFeature::kScrollbarUseScrollbarButtonReversedDirection);
+ U_FALLTHROUGH;
+ case kBackButtonStartPart:
case kForwardButtonEndPart:
scrollbar_use_uma =
(orientation == kVerticalScrollbar
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 786664f7680..dc9895c9284 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
@@ -62,7 +62,7 @@ enum ResizerHitTestType { kResizerForPointer, kResizerForTouch };
class ComputedStyle;
class HitTestResult;
class LayoutBox;
-class LayoutScrollbarPart;
+class LayoutCustomScrollbarPart;
struct PaintInvalidatorContext;
class PaintLayer;
class ScrollingCoordinator;
@@ -75,6 +75,8 @@ struct CORE_EXPORT PaintLayerScrollableAreaRareData {
PaintLayerScrollableAreaRareData();
StickyConstraintsMap sticky_constraints_map_;
+ base::Optional<cc::SnapContainerData> snap_container_data_;
+
DISALLOW_COPY_AND_ASSIGN(PaintLayerScrollableAreaRareData);
};
@@ -105,16 +107,16 @@ struct CORE_EXPORT PaintLayerScrollableAreaRareData {
// This only happens if the associated PaintLayer is itself composited.
//
//
-// ***** OVERLAY SCROLLBARS *****
-// Overlay scrollbars are painted on top of the box's content. As such they
-// don't use any space in the box. Software overlay scrollbars are painted by
-// PaintLayerPainter::paintOverlayScrollbars after all content as part of a
-// separate tree traversal. The reason for this 2nd traversal is that they need
-// to be painted on top of everything. Hardware accelerated overlay scrollbars
-// are painted by their associated GraphicsLayer that sets the paint flag
-// PaintLayerPaintingOverlayScrollbars.
+// ***** OVERLAY OVERFLOW CONTROLS *****
+// Overlay overflow controls are painted on top of the box's content. As such
+// they don't use any space in the box. Software overlay overflow controls are
+// painted by PaintLayerPainter::PaintOverlayOverflowControlsForFragments after
+// all content as part of a separate tree traversal. The reason for this 2nd
+// traversal is that they need to be painted on top of everything. Hardware
+// accelerated overlay overflow controls are painted into their associated
+// GraphicsLayers by CompositedLayerMapping::PaintScrollableArea.
class CORE_EXPORT PaintLayerScrollableArea final
- : public GarbageCollectedFinalized<PaintLayerScrollableArea>,
+ : public GarbageCollected<PaintLayerScrollableArea>,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(PaintLayerScrollableArea);
friend class Internals;
@@ -328,7 +330,6 @@ class CORE_EXPORT PaintLayerScrollableArea final
bool ScrollbarsCanBeActive() const override;
void ScrollbarVisibilityChanged() override;
void ScrollbarFrameRectChanged() override;
- IntRect ScrollableAreaBoundingBox() const override;
void RegisterForAnimation() override;
void DeregisterForAnimation() override;
bool UserInputScrollable(ScrollbarOrientation) const override;
@@ -338,7 +339,8 @@ class CORE_EXPORT PaintLayerScrollableArea final
WebColorScheme UsedColorScheme() const override;
cc::AnimationHost* GetCompositorAnimationHost() const override;
CompositorAnimationTimeline* GetCompositorAnimationTimeline() const override;
- void GetTickmarks(Vector<IntRect>&) const override;
+ bool HasTickmarks() const override;
+ Vector<IntRect> GetTickmarks() const override;
void VisibleSizeChanged();
@@ -382,11 +384,15 @@ class CORE_EXPORT PaintLayerScrollableArea final
// specific pseudo styles but there can still be a scroll corner control or
// resize control without these custom styled scrollbar parts.
bool HasOverflowControls() const;
+
+ bool HasOverlayOverflowControls() const;
+ bool HasNonOverlayOverflowControls() const;
+
bool HasOverflow() const {
return HasHorizontalOverflow() || HasVerticalOverflow();
}
- LayoutScrollbarPart* ScrollCorner() const { return scroll_corner_; }
+ LayoutCustomScrollbarPart* ScrollCorner() const { return scroll_corner_; }
void Resize(const IntPoint& pos, const LayoutSize& old_offset);
IntSize OffsetFromResizeCorner(const IntPoint& absolute_point) const;
@@ -443,7 +449,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
PaintLayer* Layer() const override;
- LayoutScrollbarPart* Resizer() const { return resizer_; }
+ LayoutCustomScrollbarPart* Resizer() const { return resizer_; }
IntRect RectForHorizontalScrollbar(const IntRect& border_box_rect) const;
IntRect RectForVerticalScrollbar(const IntRect& border_box_rect) const;
@@ -545,6 +551,9 @@ class CORE_EXPORT PaintLayerScrollableArea final
return scrolling_background_display_item_client_;
}
+ const cc::SnapContainerData* GetSnapContainerData() const override;
+ void SetSnapContainerData(base::Optional<cc::SnapContainerData>) override;
+
void DisposeImpl() override;
private:
@@ -587,8 +596,6 @@ class CORE_EXPORT PaintLayerScrollableArea final
LayoutSize MinimumSizeForResizing(float zoom_factor);
PhysicalRect LayoutContentRect(IncludeScrollbarsInRect) const;
- // See comments on isPointInResizeControl.
- void UpdateResizerAreaSet();
void UpdateResizerStyle(const ComputedStyle* old_style);
void UpdateScrollableAreaSet();
@@ -648,6 +655,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
unsigned needs_relayout_ : 1;
unsigned had_horizontal_scrollbar_before_relayout_ : 1;
unsigned had_vertical_scrollbar_before_relayout_ : 1;
+ unsigned had_resizer_before_relayout_ : 1;
unsigned scroll_origin_changed_ : 1;
// There are 6 possible combinations of writing mode and direction. Scroll
@@ -675,10 +683,10 @@ class CORE_EXPORT PaintLayerScrollableArea final
ScrollOffset scroll_offset_;
// LayoutObject to hold our custom scroll corner.
- LayoutScrollbarPart* scroll_corner_;
+ LayoutCustomScrollbarPart* scroll_corner_;
// LayoutObject to hold our custom resizer.
- LayoutScrollbarPart* resizer_;
+ LayoutCustomScrollbarPart* resizer_;
ScrollAnchor scroll_anchor_;
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 0a9abfba915..19565d06860 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
@@ -88,11 +88,12 @@ void PaintLayerStackingNode::DirtyZOrderLists() {
pos_z_order_list_.clear();
neg_z_order_list_.clear();
- for (auto& entry : layer_to_overlay_scrollbars_painting_after_.Values()) {
+ for (auto& entry :
+ layer_to_overlay_overflow_controls_painting_after_.Values()) {
for (PaintLayer* layer : entry)
- layer->SetNeedsReorderOverlayScrollbars(false);
+ layer->SetNeedsReorderOverlayOverflowControls(false);
}
- layer_to_overlay_scrollbars_painting_after_.clear();
+ layer_to_overlay_overflow_controls_painting_after_.clear();
z_order_lists_dirty_ = true;
@@ -154,7 +155,7 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
#endif
DCHECK(z_order_lists_dirty_);
- layer_.SetNeedsReorderOverlayScrollbars(false);
+ layer_.SetNeedsReorderOverlayOverflowControls(false);
for (PaintLayer* child = layer_.FirstChild(); child;
child = child->NextSibling())
CollectLayers(*child, nullptr);
@@ -196,7 +197,7 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
void PaintLayerStackingNode::CollectLayers(PaintLayer& paint_layer,
HighestLayers* highest_layers) {
- paint_layer.SetNeedsReorderOverlayScrollbars(false);
+ paint_layer.SetNeedsReorderOverlayOverflowControls(false);
if (paint_layer.IsInTopLayer())
return;
@@ -216,10 +217,10 @@ void PaintLayerStackingNode::CollectLayers(PaintLayer& paint_layer,
return;
base::Optional<HighestLayers> subtree_highest_layers;
- bool has_overlay_scrollbars =
+ bool has_overlay_overflow_controls =
paint_layer.GetScrollableArea() &&
- paint_layer.GetScrollableArea()->HasOverlayScrollbars();
- if (has_overlay_scrollbars)
+ paint_layer.GetScrollableArea()->HasOverlayOverflowControls();
+ if (has_overlay_overflow_controls)
subtree_highest_layers.emplace();
for (PaintLayer* child = paint_layer.FirstChild(); child;
@@ -228,7 +229,7 @@ void PaintLayerStackingNode::CollectLayers(PaintLayer& paint_layer,
: highest_layers);
}
- if (has_overlay_scrollbars) {
+ if (has_overlay_overflow_controls) {
const PaintLayer* layer_to_paint_overlay_scrollbars_after =
subtree_highest_layers->highest_in_flow_stacked;
if (object.CanContainFixedPositionObjects()) {
@@ -240,11 +241,11 @@ void PaintLayerStackingNode::CollectLayers(PaintLayer& paint_layer,
subtree_highest_layers->highest_absolute_position);
}
if (layer_to_paint_overlay_scrollbars_after) {
- layer_to_overlay_scrollbars_painting_after_
+ layer_to_overlay_overflow_controls_painting_after_
.insert(layer_to_paint_overlay_scrollbars_after, PaintLayers())
.stored_value->value.push_back(&paint_layer);
}
- paint_layer.SetNeedsReorderOverlayScrollbars(
+ paint_layer.SetNeedsReorderOverlayOverflowControls(
!!layer_to_paint_overlay_scrollbars_after);
if (highest_layers)
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 7f0f3c24c65..67f3632445a 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
@@ -115,15 +115,16 @@ class CORE_EXPORT PaintLayerStackingNode {
return neg_z_order_list_;
}
- const PaintLayers* LayersPaintingOverlayScrollbarsAfter(
+ const PaintLayers* LayersPaintingOverlayOverflowControlsAfter(
const PaintLayer* layer) const {
DCHECK(!z_order_lists_dirty_);
- auto it = layer_to_overlay_scrollbars_painting_after_.find(layer);
- return it == layer_to_overlay_scrollbars_painting_after_.end() ? nullptr
- : &it->value;
+ auto it = layer_to_overlay_overflow_controls_painting_after_.find(layer);
+ return it == layer_to_overlay_overflow_controls_painting_after_.end()
+ ? nullptr
+ : &it->value;
}
- void ClearNeedsReorderOverlayScrollbars();
+ void ClearNeedsReorderOverlayOverflowControls();
private:
void RebuildZOrderLists();
@@ -186,7 +187,7 @@ class CORE_EXPORT PaintLayerStackingNode {
// more than one scroller in the same stacking context with overlay
// scrollbars.
HashMap<const PaintLayer*, PaintLayers>
- layer_to_overlay_scrollbars_painting_after_;
+ layer_to_overlay_overflow_controls_painting_after_;
// Indicates whether the z-order lists above are dirty.
bool z_order_lists_dirty_ : 1;
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 4e1fc62e433..debe2d26191 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
@@ -429,333 +429,545 @@ TEST_P(PaintLayerTest, HasSelfPaintingParentNotSelfPainting) {
EXPECT_FALSE(child->HasSelfPaintingLayerDescendant());
}
-static const Vector<PaintLayer*>* LayersPaintingOverlayScrollbarsAfter(
+static const Vector<PaintLayer*>* LayersPaintingOverlayOverflowControlsAfter(
const PaintLayer* layer) {
return PaintLayerPaintOrderIterator(*layer->AncestorStackingContext(),
kPositiveZOrderChildren)
- .LayersPaintingOverlayScrollbarsAfter(layer);
+ .LayersPaintingOverlayOverflowControlsAfter(layer);
}
-TEST_P(PaintLayerTest, ReorderOverlayScrollbars_StackedWithInFlowDescendant) {
+// We need new enum and class to test the overlay overflow controls reordering,
+// but we don't move the tests related to the new class to the bottom, which is
+// behind all tests of the PaintLayerTest. Because it will make the git history
+// hard to track.
+enum OverlayType { kOverlayResizer, kOverlayScrollbars };
+
+class ReorderOverlayOverflowControlsTest
+ : public testing::WithParamInterface<std::tuple<unsigned, OverlayType>>,
+ private ScopedCompositeAfterPaintForTest,
+ public RenderingTest {
+ public:
+ ReorderOverlayOverflowControlsTest()
+ : ScopedCompositeAfterPaintForTest(std::get<0>(GetParam()) &
+ kCompositeAfterPaint),
+ RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
+ ~ReorderOverlayOverflowControlsTest() {
+ // Must destruct all objects before toggling back feature flags.
+ WebHeap::CollectAllGarbageForTesting();
+ }
+
+ OverlayType GetOverlayType() const { return std::get<1>(GetParam()); }
+
+ void InitOverflowStyle(const char* id) {
+ GetDocument().getElementById(id)->setAttribute(
+ html_names::kStyleAttr, GetOverlayType() == kOverlayScrollbars
+ ? "overflow : auto"
+ : "overflow: hidden; resize: both");
+ UpdateAllLifecyclePhasesForTest();
+ }
+
+ void SetUp() override {
+ EnableCompositing();
+ RenderingTest::SetUp();
+ }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ ReorderOverlayOverflowControlsTest,
+ ::testing::Combine(::testing::Values(0, kCompositeAfterPaint),
+ ::testing::Values(kOverlayScrollbars, kOverlayResizer)));
+
+TEST_P(ReorderOverlayOverflowControlsTest, StackedWithInFlowDescendant) {
SetBodyInnerHTML(R"HTML(
- <div id='parent' style='overflow: auto; position: relative;
- width: 100px; height: 100px'>
+ <style>
+ #parent {
+ position: relative;
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='parent'>
<div id='child' style='position: relative; height: 200px'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ if (GetOverlayType() == kOverlayScrollbars) {
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
+ } else {
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
+ Pointee(ElementsAre(parent)));
+ }
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_StackedWithOutOfFlowDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest, StackedWithOutOfFlowDescendant) {
SetBodyInnerHTML(R"HTML(
- <style>#child { width: 200px; height: 200px; }</style>
- <div id='parent' style='overflow: auto; position: relative; height: 100px'>
+ <style>
+ #child {
+ width: 200px;
+ height: 200px;
+ }
+ #parent {
+ position: relative;
+ height: 100px;
+ }
+ </style>
+ <div id='parent'>
<div id='child' style='position: absolute'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"position: absolute");
UpdateAllLifecyclePhasesForTest();
child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest, ReorderOverlayScrollbars_StackedWithZIndexDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest, StackedWithZIndexDescendant) {
SetBodyInnerHTML(R"HTML(
- <style>#child { position: absolute; width: 200px; height: 200px; }</style>
- <div id='parent' style='overflow: auto; position: relative; height: 100px'>
- <div id='child' style='position: absolute; z-index: 1;
- width: 200px; height: 200px'></div>
+ <style>
+ #parent {
+ position: relative;
+ height: 100px;
+ }
+ #child {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+ </style>
+ <div id='parent'>
+ <div id='child' style='z-index: 1'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"z-index: -1");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"z-index: 2");
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NestedStackedWithInFlowStackedChild) {
+TEST_P(ReorderOverlayOverflowControlsTest,
+ NestedStackedWithInFlowStackedChild) {
SetBodyInnerHTML(R"HTML(
- <div id='ancestor'
- style='overflow: auto; position: relative; height: 100px'>
- <div id='parent' style='overflow: auto; height: 200px'>
- <div id="child" style='position: relative; height: 300px'></div>
+ <style>
+ #ancestor {
+ position: relative;
+ height: 100px;
+ }
+ #parent {
+ height: 200px;
+ }
+ #child {
+ position: relative;
+ height: 300px;
+ }
+ </style>
+ <div id='ancestor'>
+ <div id='parent'>
+ <div id="child"></div>
</div>
</div>
)HTML");
+
+ InitOverflowStyle("ancestor");
+ InitOverflowStyle("parent");
+
auto* ancestor = GetPaintLayerByElementId("ancestor");
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(ancestor->NeedsReorderOverlayScrollbars());
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(ancestor->NeedsReorderOverlayOverflowControls());
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent, ancestor)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NestedStackedWithOutOfFlowStackedChild) {
+TEST_P(ReorderOverlayOverflowControlsTest,
+ NestedStackedWithOutOfFlowStackedChild) {
SetBodyInnerHTML(R"HTML(
- <div id='ancestor'
- style='overflow: auto; position: relative; height: 100px'>
- <div id='parent' style='overflow: auto; position: absolute;
- width: 200px; height: 200px'>
- <div id="child" style='position: absolute; width: 300px; height: 300px'>
+ <style>
+ #ancestor {
+ position: relative;
+ height: 100px;
+ }
+ #parent {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+ #child {
+ position: absolute;
+ width: 300px;
+ height: 300px;
+ }
+ </style>
+ <div id='ancestor'>
+ <div id='parent'>
+ <div id="child">
</div>
</div>
</div>
)HTML");
+
+ InitOverflowStyle("ancestor");
+ InitOverflowStyle("parent");
+
auto* ancestor = GetPaintLayerByElementId("ancestor");
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(ancestor->NeedsReorderOverlayScrollbars());
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(ancestor->NeedsReorderOverlayOverflowControls());
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent, ancestor)));
}
-TEST_P(PaintLayerTest, ReorderOverlayScrollbars_MultipleChildren) {
+TEST_P(ReorderOverlayOverflowControlsTest, MultipleChildren) {
SetBodyInnerHTML(R"HTML(
<style>
- div { width: 200px; height: 200px; }
- #parent { overflow: auto; width: 100px; height: 100px; }
+ div {
+ width: 200px;
+ height: 200px;
+ }
+ #parent {
+ width: 100px;
+ height: 100px;
+ }
+ #low-child {
+ position: absolute;
+ z-index: 1;
+ }
+ #middle-child {
+ position: relative;
+ z-index: 2;
+ }
+ #high-child {
+ position: absolute;
+ z-index: 3;
+ }
</style>
<div id='parent'>
- <div id="low-child" style='position: absolute; z-index: 1'></div>
- <div id="middle-child" style='position: relative; z-index: 2'></div>
- <div id="high-child" style='position: absolute; z-index: 3'></div>
+ <div id="low-child"></div>
+ <div id="middle-child"></div>
+ <div id="high-child"></div>
</div>
)HTML");
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* low_child = GetPaintLayerByElementId("low-child");
auto* middle_child = GetPaintLayerByElementId("middle-child");
auto* high_child = GetPaintLayerByElementId("high-child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(low_child));
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(low_child));
// The highest contained child by parent is middle_child because the
// absolute-position children are not contained.
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(middle_child),
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(middle_child),
Pointee(ElementsAre(parent)));
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(high_child));
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(high_child));
- GetDocument().getElementById("parent")->setAttribute(
- html_names::kStyleAttr, "position: absolute; z-index: 1");
+ std::string extra_style = GetOverlayType() == kOverlayScrollbars
+ ? "overflow: auto;"
+ : "overflow: hidden; resize: both;";
+ std::string new_style = extra_style + "position: absolute; z-index: 1";
+ GetDocument().getElementById("parent")->setAttribute(html_names::kStyleAttr,
+ new_style.c_str());
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(low_child));
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(middle_child));
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(high_child));
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(low_child));
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(middle_child));
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(high_child));
+ new_style = extra_style + "position: absolute;";
GetDocument().getElementById("parent")->setAttribute(html_names::kStyleAttr,
- "position: absolute");
+ new_style.c_str());
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(low_child));
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(middle_child));
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(high_child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(low_child));
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(middle_child));
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(high_child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NonStackedWithInFlowDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest, NonStackedWithInFlowDescendant) {
SetBodyInnerHTML(R"HTML(
- <div id='parent' style='overflow: auto; width: 100px; height: 100px'>
+ <style>
+ #parent {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='parent'>
<div id='child' style='position: relative; height: 200px'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ if (GetOverlayType() == kOverlayResizer) {
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
+ Pointee(ElementsAre(parent)));
+ } else {
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
+ }
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
GetDocument().getElementById("child")->setAttribute(
html_names::kStyleAttr, "position: relative; width: 200px; height: 80px");
UpdateAllLifecyclePhasesForTest();
child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NonStackedWithZIndexInFlowDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest,
+ NonStackedWithZIndexInFlowDescendant) {
SetBodyInnerHTML(R"HTML(
- <style>#child { position: relative; height: 200px; }</style>
- <div id='parent' style='overflow: auto; height: 100px'>
- <div id='child' style='z-index: 1'>
- </div>
+ <style>
+ #parent {
+ height: 100px;
+ }
+ #child {
+ position: relative;
+ height: 200px;
+ }
+ </style>
+ <div id='parent'>
+ <div id='child' style='z-index: 1'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"z-index: -1");
UpdateAllLifecyclePhasesForTest();
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
GetDocument().getElementById("child")->setAttribute(html_names::kStyleAttr,
"z-index: 2");
UpdateAllLifecyclePhasesForTest();
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NonStackedWithOutOfFlowDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest, NonStackedWithOutOfFlowDescendant) {
SetBodyInnerHTML(R"HTML(
- <div id='parent' style='overflow: auto; height: 100px'>
- <div id='child' style='position: absolute;
- width: 200px; height: 200px'></div>
+ <style>
+ #parent {
+ height: 100px;
+ }
+ #child {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ }
+ </style>
+ <div id='parent'>
+ <div id='child'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NonStackedWithNonStackedDescendant) {
+TEST_P(ReorderOverlayOverflowControlsTest, NonStackedWithNonStackedDescendant) {
SetBodyInnerHTML(R"HTML(
- <div id='parent' style='overflow: auto'>
- <div id='child' style='overflow: auto'></div>
+ <div id='parent'>
+ <div id='child'></div>
</div>
)HTML");
+
+ InitOverflowStyle("parent");
+ InitOverflowStyle("child");
+
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NestedNonStackedWithInFlowStackedChild) {
+TEST_P(ReorderOverlayOverflowControlsTest,
+ NestedNonStackedWithInFlowStackedChild) {
SetBodyInnerHTML(R"HTML(
- <div id='ancestor' style='overflow: auto; height: 100px'>
- <div id='parent' style='overflow: auto; height: 200px'>
- <div id="child" style='position: relative; height: 300px'></div>
+ <style>
+ #ancestor {
+ height: 100px;
+ }
+ #parent {
+ height: 200px;
+ }
+ #child {
+ position: relative;
+ height: 300px;
+ }
+ </style>
+ <div id='ancestor'>
+ <div id='parent'>
+ <div id='child'></div>
</div>
</div>
)HTML");
+
+ InitOverflowStyle("ancestor");
+ InitOverflowStyle("parent");
+
auto* ancestor = GetPaintLayerByElementId("ancestor");
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_TRUE(ancestor->NeedsReorderOverlayScrollbars());
- EXPECT_TRUE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_THAT(LayersPaintingOverlayScrollbarsAfter(child),
+ EXPECT_TRUE(ancestor->NeedsReorderOverlayOverflowControls());
+ EXPECT_TRUE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_THAT(LayersPaintingOverlayOverflowControlsAfter(child),
Pointee(ElementsAre(parent, ancestor)));
}
-TEST_P(PaintLayerTest,
- ReorderOverlayScrollbars_NestedNonStackedWithOutOfFlowStackedChild) {
+TEST_P(ReorderOverlayOverflowControlsTest,
+ NestedNonStackedWithOutOfFlowStackedChild) {
SetBodyInnerHTML(R"HTML(
- <div id='ancestor' style='overflow: auto; height: 100px'>
- <div id='parent' style='overflow: auto; height: 200px'>
- <div id="child" style='position: absolute; width: 300px; height: 300px'>
+ <style>
+ #ancestor {
+ height: 100px;
+ }
+ #parent {
+ height: 200px;
+ }
+ #child {
+ position: absolute;
+ width: 300px;
+ height: 300px;
+ }
+ </style>
+ <div id='ancestor'>
+ <div id='parent'>
+ <div id='child'>
</div>
</div>
</div>
)HTML");
+
+ InitOverflowStyle("ancestor");
+ InitOverflowStyle("parent");
+
auto* ancestor = GetPaintLayerByElementId("ancestor");
auto* parent = GetPaintLayerByElementId("parent");
auto* child = GetPaintLayerByElementId("child");
- EXPECT_FALSE(ancestor->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(parent->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(child->NeedsReorderOverlayScrollbars());
- EXPECT_FALSE(LayersPaintingOverlayScrollbarsAfter(child));
+ EXPECT_FALSE(ancestor->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(parent->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(child->NeedsReorderOverlayOverflowControls());
+ EXPECT_FALSE(LayersPaintingOverlayOverflowControlsAfter(child));
}
TEST_P(PaintLayerTest, SubsequenceCachingStackingContexts) {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_phase.h b/chromium/third_party/blink/renderer/core/paint/paint_phase.h
index cb244b57d3e..039da1239f3 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_phase.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_phase.h
@@ -92,7 +92,7 @@ enum class PaintPhase {
kDescendantOutlinesOnly,
// The below are auxiliary phases which are used to paint special effects.
- kOverlayScrollbars,
+ kOverlayOverflowControls,
kSelection,
kTextClip,
kMask,
@@ -134,9 +134,11 @@ enum GlobalPaintFlag {
// into the topmost layer.
kGlobalPaintFlattenCompositingLayers = 1 << 1,
// Used when printing in order to adapt the output to the medium, for
- // instance by not painting shadows and selections on text, and add
- // URL metadata for links.
- kGlobalPaintPrinting = 1 << 2
+ // instance by not painting shadows and selections on text.
+ kGlobalPaintPrinting = 1 << 2,
+ // Used when printing or painting a preview to in order to add URL
+ // metadata for links.
+ kGlobalPaintAddUrlMetadata = 1 << 3
};
typedef unsigned GlobalPaintFlags;
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 04c77decbcf..187443c16aa 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
@@ -10,7 +10,6 @@
#include "cc/input/overscroll_behavior.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
-#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -28,6 +27,7 @@
#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/svg_resources_cache.h"
+#include "third_party/blink/renderer/core/page/link_highlight.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
@@ -275,9 +275,6 @@ static bool NeedsScrollNode(const LayoutObject& object,
return true;
}
- if (direct_compositing_reasons & CompositingReason::kScrollTimelineTarget)
- return true;
-
return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow();
}
@@ -496,9 +493,14 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
const base::Optional<IntPoint>& paint_offset_translation) {
DCHECK(properties_);
+ FloatSize old_translation;
+ if (auto* translation = properties_->PaintOffsetTranslation()) {
+ old_translation = translation->Translation2D();
+ }
+
if (paint_offset_translation) {
- TransformPaintPropertyNode::State state{
- FloatSize(ToIntSize(*paint_offset_translation))};
+ FloatSize new_translation(ToIntSize(*paint_offset_translation));
+ TransformPaintPropertyNode::State state{new_translation};
state.flags.flattens_inherited_transform =
context_.current.should_flatten_inherited_transform;
state.flags.affected_by_outer_viewport_bounds_delta =
@@ -515,8 +517,11 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
properties_->PaintOffsetTranslation();
context_.fixed_position.transform = properties_->PaintOffsetTranslation();
}
+
+ context_.paint_offset_delta = old_translation - new_translation;
} else {
OnClear(properties_->ClearPaintOffsetTranslation());
+ context_.paint_offset_delta = FloatSize();
}
}
@@ -780,7 +785,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
// TODO(crbug.com/953322): We need to fix this to work with CAP as well.
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
effective_change_type ==
- PaintPropertyChangeType::kChangedOnlySimpleValues) {
+ PaintPropertyChangeType::kChangedOnlySimpleValues &&
+ properties_->Transform()->HasDirectCompositingReasons()) {
if (auto* paint_artifact_compositor =
object_.GetFrameView()->GetPaintArtifactCompositor()) {
bool updated = paint_artifact_compositor->DirectlyUpdateTransform(
@@ -1080,7 +1086,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
// TODO(crbug.com/953322): We need to fix this to work with CAP as well.
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
effective_change_type ==
- PaintPropertyChangeType::kChangedOnlySimpleValues) {
+ PaintPropertyChangeType::kChangedOnlySimpleValues &&
+ properties_->Effect()->HasDirectCompositingReasons()) {
if (auto* paint_artifact_compositor =
object_.GetFrameView()->GetPaintArtifactCompositor()) {
bool updated =
@@ -1144,7 +1151,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
static bool NeedsLinkHighlightEffect(const LayoutObject& object) {
auto* page = object.GetFrame()->GetPage();
- return page->GetLinkHighlights().NeedsHighlightEffect(object);
+ return page->GetLinkHighlight().NeedsHighlightEffect(object);
}
// TODO(crbug.com/900241): Remove this function and let the caller use
@@ -1865,10 +1872,12 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
static_cast<cc::OverscrollBehavior::OverscrollBehaviorType>(
box.StyleRef().OverscrollBehaviorY()));
- auto* snap_coordinator = box.GetDocument().GetSnapCoordinator();
- if (snap_coordinator) {
- state.snap_container_data = snap_coordinator->GetSnapContainerData(box);
- }
+ state.snap_container_data =
+ box.GetScrollableArea() &&
+ box.GetScrollableArea()->GetSnapContainerData()
+ ? base::Optional<cc::SnapContainerData>(
+ *box.GetScrollableArea()->GetSnapContainerData())
+ : base::nullopt;
OnUpdateScroll(properties_->UpdateScroll(*context_.current.scroll,
std::move(state)));
@@ -1927,15 +1936,20 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
state.direct_compositing_reasons =
full_context_.direct_compositing_reasons &
(CompositingReason::kRootScroller |
- CompositingReason::kScrollTimelineTarget);
+ CompositingReasonsForTransformProperty());
state.rendering_context_id = context_.current.rendering_context_id;
state.scroll = properties_->Scroll();
auto effective_change_type = properties_->UpdateScrollTranslation(
*context_.current.transform, std::move(state));
+ bool known_to_be_composited =
+ RuntimeEnabledFeatures::CompositeAfterPaintEnabled()
+ ? properties_->ScrollTranslation()->HasDirectCompositingReasons()
+ : box.GetScrollableArea()->NeedsCompositedScrolling();
// TODO(crbug.com/953322): We need to fix this to work with CAP as well.
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
effective_change_type ==
- PaintPropertyChangeType::kChangedOnlySimpleValues) {
+ PaintPropertyChangeType::kChangedOnlySimpleValues &&
+ known_to_be_composited) {
if (auto* paint_artifact_compositor =
object_.GetFrameView()->GetPaintArtifactCompositor()) {
bool updated =
@@ -2453,6 +2467,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
// Update of PaintOffsetTranslation is checked by
// FindPaintOffsetNeedingUpdateScope.
UpdatePaintOffsetTranslation(paint_offset_translation);
+ } else {
+ context_.paint_offset_delta = FloatSize();
}
#if DCHECK_IS_ON()
@@ -3085,6 +3101,14 @@ void PaintPropertyTreeBuilder::CreateFragmentContextsInFlowThread(
if (fragments_changed) {
object_.GetMutableForPainting().AddSubtreePaintPropertyUpdateReason(
SubtreePaintPropertyUpdateReason::kFragmentsChanged);
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
+ NeedsLinkHighlightEffect(object_)) {
+ // We need to recollect the foreign layers for link highlight for the
+ // changed fragments. CompositeAfterPaint doesn't need this because we
+ // collect foreign layers during LocalFrameView::PaintTree() which is not
+ // controlled by the flag.
+ object_.GetFrameView()->SetForeignLayerListNeedsUpdate();
+ }
}
}
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 483186a8166..812cb587cc8 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
@@ -109,6 +109,7 @@ struct PaintPropertyTreeBuilderFragmentContext {
// offset to paint at the desired place.
PhysicalOffset repeating_paint_offset_adjustment;
+ FloatSize paint_offset_delta;
PhysicalOffset old_paint_offset;
};
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 d503bffea88..10f3a5453b4 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
@@ -716,6 +716,29 @@ TEST_P(PaintPropertyTreeBuilderTest, Perspective3DTransformedDescendant) {
}
TEST_P(PaintPropertyTreeBuilderTest,
+ TransformPerspective3DTransformedDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <style> body { margin: 0 } </style>
+ <div id='perspective' style='transform: perspective(800px);'>
+ <div id='transform' style='margin-left: 50px; margin-top: 100px;
+ width: 400px; height: 300px;
+ transform: translate3d(123px, 456px, 789px)'>
+ </div>
+ </div>
+ )HTML");
+
+ Element* perspective = GetDocument().getElementById("perspective");
+ const ObjectPaintProperties* perspective_properties =
+ perspective->GetLayoutObject()->FirstFragment().PaintProperties();
+
+ EXPECT_TRUE(perspective_properties->Transform());
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ EXPECT_TRUE(
+ perspective_properties->Transform()->HasDirectCompositingReasons());
+ }
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
TransformNodeWithActiveAnimationHasDirectCompositingReason) {
LoadTestData("transform-animation.html");
EXPECT_TRUE(PaintPropertiesForElement("target")
@@ -6627,6 +6650,37 @@ TEST_P(PaintPropertyTreeBuilderTest, SimpleScrollChangeDoesNotCausePacUpdate) {
}
TEST_P(PaintPropertyTreeBuilderTest,
+ NonCompositedTransformChangeCausesPacUpdate) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #outer {
+ width: 100px;
+ height: 100px;
+ transform: translateY(0);
+ }
+ #inner {
+ width: 10px;
+ height: 10px;
+ will-change: transform;
+ }
+ </style>
+ <div id="outer">
+ <div id="inner"></div>
+ </div>
+ )HTML");
+
+ EXPECT_FALSE(
+ GetDocument().View()->GetPaintArtifactCompositor()->NeedsUpdate());
+
+ Element* outer = GetDocument().getElementById("outer");
+ outer->setAttribute(html_names::kStyleAttr, "transform: translateY(10px)");
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+
+ EXPECT_TRUE(
+ GetDocument().View()->GetPaintArtifactCompositor()->NeedsUpdate());
+}
+
+TEST_P(PaintPropertyTreeBuilderTest,
ColumnSpanAllUnderContainPaintAndClipPath) {
// This test doesn't apply in CompositeAfterPaint mode.
if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
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 8b0939364ac..f0f948558ed 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
@@ -945,7 +945,7 @@ TEST_P(PaintPropertyTreeUpdateTest, MenuListControlClipChange) {
EXPECT_NE(nullptr, select->FirstFragment().PaintProperties()->OverflowClip());
// Should not assert in FindPropertiesNeedingUpdate.
- ToHTMLSelectElement(select->GetNode())->setSelectedIndex(1);
+ To<HTMLSelectElement>(select->GetNode())->setSelectedIndex(1);
UpdateAllLifecyclePhasesForTest();
EXPECT_NE(nullptr, select->FirstFragment().PaintProperties()->OverflowClip());
}
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 f9736e5f46e..ffb1ae2133f 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.h
@@ -26,9 +26,8 @@ class LocalFrame;
// PaintTiming is responsible for tracking paint-related timings for a given
// document.
-class CORE_EXPORT PaintTiming final
- : public GarbageCollectedFinalized<PaintTiming>,
- public Supplement<Document> {
+class CORE_EXPORT PaintTiming final : public GarbageCollected<PaintTiming>,
+ public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(PaintTiming);
friend class FirstMeaningfulPaintDetector;
using ReportTimeCallback =
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 3a369e59a11..9a039a472ad 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
@@ -84,13 +84,7 @@ void PaintTimingDetector::NotifyPaintFinished() {
} else {
visualizer_.reset();
}
- if (text_paint_timing_detector_) {
- text_paint_timing_detector_->OnPaintFinished();
- if (text_paint_timing_detector_->FinishedReportingText()) {
- text_paint_timing_detector_->StopRecordEntries();
- text_paint_timing_detector_ = nullptr;
- }
- }
+ text_paint_timing_detector_->OnPaintFinished();
if (image_paint_timing_detector_) {
image_paint_timing_detector_->OnPaintFinished();
if (image_paint_timing_detector_->FinishedReportingImages())
@@ -154,8 +148,7 @@ void PaintTimingDetector::NotifyImageFinished(
void PaintTimingDetector::LayoutObjectWillBeDestroyed(
const LayoutObject& object) {
- if (text_paint_timing_detector_)
- text_paint_timing_detector_->LayoutObjectWillBeDestroyed(object);
+ text_paint_timing_detector_->LayoutObjectWillBeDestroyed(object);
if (image_paint_timing_detector_)
image_paint_timing_detector_->LayoutObjectWillBeDestroyed(object);
@@ -169,15 +162,14 @@ void PaintTimingDetector::NotifyImageRemoved(
}
}
-void PaintTimingDetector::StopRecordingIfNeeded() {
+void PaintTimingDetector::StopRecordingLargestContentfulPaint() {
DCHECK(frame_view_);
- if (text_paint_timing_detector_) {
- text_paint_timing_detector_->StopRecordingLargestTextPaint();
- if (!RuntimeEnabledFeatures::ElementTimingEnabled(
- frame_view_->GetFrame().GetDocument())) {
- text_paint_timing_detector_->StopRecordEntries();
- }
- }
+ // TextPaintTimingDetector is used for both Largest Contentful Paint and for
+ // Element Timing. Therefore, here we only want to stop recording Largest
+ // Contentful Paint.
+ text_paint_timing_detector_->StopRecordingLargestTextPaint();
+ // ImagePaintTimingDetector is currently only being used for
+ // LargestContentfulPaint.
if (image_paint_timing_detector_)
image_paint_timing_detector_->StopRecordEntries();
largest_contentful_paint_calculator_ = nullptr;
@@ -189,27 +181,24 @@ void PaintTimingDetector::NotifyInputEvent(WebInputEvent::Type type) {
WebInputEvent::IsPinchGestureEventType(type)) {
return;
}
- StopRecordingIfNeeded();
+ StopRecordingLargestContentfulPaint();
}
void PaintTimingDetector::NotifyScroll(ScrollType scroll_type) {
if (scroll_type != kUserScroll && scroll_type != kCompositorScroll)
return;
- StopRecordingIfNeeded();
+ StopRecordingLargestContentfulPaint();
}
bool PaintTimingDetector::NeedToNotifyInputOrScroll() const {
- return (text_paint_timing_detector_ &&
- text_paint_timing_detector_->IsRecording()) ||
+ DCHECK(text_paint_timing_detector_);
+ return text_paint_timing_detector_->IsRecordingLargestTextPaint() ||
(image_paint_timing_detector_ &&
image_paint_timing_detector_->IsRecording());
}
LargestContentfulPaintCalculator*
PaintTimingDetector::GetLargestContentfulPaintCalculator() {
- if (!RuntimeEnabledFeatures::LargestContentfulPaintEnabled())
- return nullptr;
-
if (largest_contentful_paint_calculator_)
return largest_contentful_paint_calculator_;
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 661f2bf636a..f27a0e04ce2 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
@@ -54,10 +54,10 @@ class PaintTimingCallbackManager : public GarbageCollectedMixin {
// An extra benefit of this design is that |LargestContentfulPaintCalculator|
// can thus hook to the end of the LIP and LTP's record assignments.
//
-// |GarbageCollectedFinalized| inheritance is required by the swap-time callback
+// |GarbageCollected| inheritance is required by the swap-time callback
// registration.
class PaintTimingCallbackManagerImpl final
- : public GarbageCollectedFinalized<PaintTimingCallbackManagerImpl>,
+ : public GarbageCollected<PaintTimingCallbackManagerImpl>,
public PaintTimingCallbackManager {
USING_GARBAGE_COLLECTED_MIXIN(PaintTimingCallbackManagerImpl);
@@ -156,6 +156,7 @@ class CORE_EXPORT PaintTimingDetector
const PropertyTreeState&) const;
TextPaintTimingDetector* GetTextPaintTimingDetector() const {
+ DCHECK(text_paint_timing_detector_);
return text_paint_timing_detector_;
}
ImagePaintTimingDetector* GetImagePaintTimingDetector() const {
@@ -177,12 +178,11 @@ class CORE_EXPORT PaintTimingDetector
void Trace(Visitor* visitor);
private:
- void StopRecordingIfNeeded();
+ void StopRecordingLargestContentfulPaint();
bool HasLargestImagePaintChanged(base::TimeTicks, uint64_t size) const;
bool HasLargestTextPaintChanged(base::TimeTicks, uint64_t size) const;
Member<LocalFrameView> frame_view_;
- // This member lives until the end of the paint phase after the largest text
- // paint is found.
+ // This member lives forever because it is also used for Text Element Timing.
Member<TextPaintTimingDetector> text_paint_timing_detector_;
// This member lives until the end of the paint phase after the largest
// image paint is found.
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_timing_test_helper.h b/chromium/third_party/blink/renderer/core/paint/paint_timing_test_helper.h
index 8d1dfb20eb2..e23dfda5dec 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing_test_helper.h
@@ -8,7 +8,7 @@ namespace blink {
// |ChromeClient::NotifySwapTime()|'s swap-time queueing and invoking for
// unit-tests. Find more details in |PaintTimingCallbackManager|.
class MockPaintTimingCallbackManager final
- : public GarbageCollectedFinalized<MockPaintTimingCallbackManager>,
+ : public GarbageCollected<MockPaintTimingCallbackManager>,
public PaintTimingCallbackManager {
USING_GARBAGE_COLLECTED_MIXIN(MockPaintTimingCallbackManager);
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 1d2e5f39ba1..702a1a8a317 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
@@ -392,6 +392,17 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
CompositingLayerPropertyUpdater::Update(object);
}
+LocalFrameView* FindWebViewPluginContentFrameView(
+ const LayoutEmbeddedContent& embedded_content) {
+ for (Frame* frame = embedded_content.GetFrame()->Tree().FirstChild(); frame;
+ frame = frame->Tree().NextSibling()) {
+ if (frame->IsLocalFrame() &&
+ To<LocalFrame>(frame)->OwnerLayoutObject() == &embedded_content)
+ return To<LocalFrame>(frame)->View();
+ }
+ return nullptr;
+}
+
void PrePaintTreeWalk::Walk(const LayoutObject& object) {
// We need to be careful not to have a reference to the parent context, since
// this reference will be to the context_storage_ memory which may be
@@ -470,18 +481,26 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object) {
if (object.IsLayoutEmbeddedContent()) {
const LayoutEmbeddedContent& layout_embedded_content =
ToLayoutEmbeddedContent(object);
- FrameView* frame_view = layout_embedded_content.ChildFrameView();
- if (auto* local_frame_view = DynamicTo<LocalFrameView>(frame_view)) {
+ if (auto* embedded_view =
+ layout_embedded_content.GetEmbeddedContentView()) {
if (context().tree_builder_context) {
auto& offset =
context().tree_builder_context->fragments[0].current.paint_offset;
offset += layout_embedded_content.ReplacedContentRect().offset;
- offset -= PhysicalOffset(local_frame_view->FrameRect().Location());
+ offset -= PhysicalOffset(embedded_view->FrameRect().Location());
offset = PhysicalOffset(RoundedIntPoint(offset));
}
- Walk(*local_frame_view);
+ if (embedded_view->IsLocalFrameView()) {
+ Walk(*To<LocalFrameView>(embedded_view));
+ } else if (embedded_view->IsPluginView()) {
+ // If it is a webview plugin, walk into the content frame view.
+ if (auto* plugin_content_frame_view =
+ FindWebViewPluginContentFrameView(layout_embedded_content))
+ Walk(*plugin_content_frame_view);
+ } else {
+ // We need to do nothing for RemoteFrameView. See crbug.com/579281.
+ }
}
- // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
}
object.NotifyDisplayLockDidPrePaint(DisplayLockLifecycleTarget::kChildren);
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 3f6d81c4e4d..37fb8cc0057 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
@@ -7,11 +7,11 @@
#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/core/paint/custom_scrollbar_theme.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_painter.h"
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
@@ -37,23 +37,20 @@ void ScrollableAreaPainter::PaintResizer(GraphicsContext& context,
abs_rect.MoveBy(paint_offset);
const auto& client = DisplayItemClientForCorner();
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- IntRect touch_rect = scrollable_area_->ResizerCornerRect(
- GetScrollableArea().GetLayoutBox()->PixelSnappedBorderBoxRect(
- scrollable_area_->Layer()->SubpixelAccumulation()),
- kResizerForTouch);
- touch_rect.MoveBy(paint_offset);
- ScrollHitTestDisplayItem::Record(context, client,
- DisplayItem::kResizerScrollHitTest,
- nullptr, touch_rect);
- }
+ IntRect touch_rect = scrollable_area_->ResizerCornerRect(
+ GetScrollableArea().GetLayoutBox()->PixelSnappedBorderBoxRect(
+ scrollable_area_->Layer()->SubpixelAccumulation()),
+ kResizerForTouch);
+ touch_rect.MoveBy(paint_offset);
+ ScrollHitTestDisplayItem::Record(
+ context, client, DisplayItem::kResizerScrollHitTest, nullptr, touch_rect);
if (const auto* resizer = GetScrollableArea().Resizer()) {
if (!cull_rect.Intersects(abs_rect))
return;
- ScrollbarPainter::PaintIntoRect(*resizer, context,
- PhysicalOffset(paint_offset),
- PhysicalRect(abs_rect));
+ CustomScrollbarTheme::PaintIntoRect(*resizer, context,
+ PhysicalOffset(paint_offset),
+ PhysicalRect(abs_rect));
return;
}
@@ -67,8 +64,7 @@ void ScrollableAreaPainter::PaintResizer(GraphicsContext& context,
// Draw a frame around the resizer (1px grey line) if there are any scrollbars
// present. Clipping will exclude the right and bottom edges of this frame.
- if (!GetScrollableArea().HasOverlayScrollbars() &&
- GetScrollableArea().HasScrollbar()) {
+ if (GetScrollableArea().HasNonOverlayOverflowControls()) {
GraphicsContextStateSaver state_saver(context);
context.Clip(abs_rect);
IntRect larger_corner = abs_rect;
@@ -143,10 +139,10 @@ void ScrollableAreaPainter::PaintOverflowControls(
box.StyleRef().Visibility() != EVisibility::kVisible)
return;
- // Overlay scrollbars are painted in the dedicated paint phase, and normal
- // scrollbars are painted in the background paint phase.
- if (GetScrollableArea().HasOverlayScrollbars()) {
- if (paint_info.phase != PaintPhase::kOverlayScrollbars)
+ // Overlay overflow controls are painted in the dedicated paint phase, and
+ // normal overflow controls are painted in the background paint phase.
+ if (GetScrollableArea().HasOverlayOverflowControls()) {
+ if (paint_info.phase != PaintPhase::kOverlayOverflowControls)
return;
} else if (!ShouldPaintSelfBlockBackground(paint_info.phase)) {
return;
@@ -204,9 +200,9 @@ void ScrollableAreaPainter::PaintScrollCorner(GraphicsContext& context,
if (const auto* scroll_corner = GetScrollableArea().ScrollCorner()) {
if (!cull_rect.Intersects(abs_rect))
return;
- ScrollbarPainter::PaintIntoRect(*scroll_corner, context,
- PhysicalOffset(paint_offset),
- PhysicalRect(abs_rect));
+ CustomScrollbarTheme::PaintIntoRect(*scroll_corner, context,
+ PhysicalOffset(paint_offset),
+ PhysicalRect(abs_rect));
return;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc
deleted file mode 100644
index 30bdae14ac6..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc
+++ /dev/null
@@ -1,53 +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/scrollbar_painter.h"
-
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-
-namespace blink {
-
-void ScrollbarPainter::PaintPart(GraphicsContext& graphics_context,
- ScrollbarPart part_type,
- const IntRect& rect) {
- const LayoutScrollbarPart* part_layout_object =
- layout_scrollbar_->GetPart(part_type);
- if (!part_layout_object)
- return;
- PaintIntoRect(*part_layout_object, graphics_context,
- PhysicalOffset(layout_scrollbar_->Location()),
- PhysicalRect(rect), layout_scrollbar_.Get());
-}
-
-void ScrollbarPainter::PaintIntoRect(
- const LayoutScrollbarPart& layout_scrollbar_part,
- GraphicsContext& graphics_context,
- const PhysicalOffset& paint_offset,
- const PhysicalRect& rect,
- const LayoutScrollbar* scrollbar) {
- // Make sure our dimensions match the rect.
- // TODO(crbug.com/856802): Setting these is a bad layering violation!
- // Move these into layout stage.
- const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
- .SetLocation((rect.offset - paint_offset).ToLayoutPoint());
- const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
- .SetWidth(rect.size.width);
- const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
- .SetHeight(rect.size.height);
- // TODO(crbug.com/856802): Move this into PaintPropertyTreeBuilder.
- layout_scrollbar_part.GetMutableForPainting().FirstFragment().SetPaintOffset(
- (scrollbar ? PhysicalOffset(scrollbar->Location()) : PhysicalOffset()) +
- layout_scrollbar_part.PhysicalLocation());
-
- PaintInfo paint_info(graphics_context, PixelSnappedIntRect(rect),
- PaintPhase::kForeground, kGlobalPaintNormalPhase,
- kPaintLayerNoFlag);
- ObjectPainter(layout_scrollbar_part).PaintAllPhasesAtomically(paint_info);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h
deleted file mode 100644
index cee75bea6bc..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h
+++ /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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_PAINTER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/scroll/scrollbar.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class GraphicsContext;
-class IntRect;
-class LayoutScrollbar;
-class LayoutScrollbarPart;
-struct PhysicalOffset;
-struct PhysicalRect;
-
-class ScrollbarPainter {
- STACK_ALLOCATED();
-
- public:
- explicit ScrollbarPainter(const LayoutScrollbar& layout_scrollbar)
- : layout_scrollbar_(&layout_scrollbar) {}
-
- void PaintPart(GraphicsContext&, ScrollbarPart, const IntRect&);
- static void PaintIntoRect(const LayoutScrollbarPart&,
- GraphicsContext&,
- const PhysicalOffset& paint_offset,
- const PhysicalRect&,
- const LayoutScrollbar* = nullptr);
-
- private:
- Member<const LayoutScrollbar> layout_scrollbar_;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollbarPainter);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_PAINTER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc b/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
index f5fe71f87af..98cd2b17a71 100644
--- a/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
+++ b/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
@@ -40,7 +40,7 @@ scoped_refptr<ComputedStyle> GetUncachedSelectionStyle(Node* node) {
if (root->IsUserAgent()) {
if (Element* shadow_host = node->OwnerShadowHost()) {
return shadow_host->StyleForPseudoElement(
- PseudoStyleRequest(kPseudoIdSelection));
+ PseudoElementStyleRequest(kPseudoIdSelection));
}
}
}
@@ -61,7 +61,8 @@ scoped_refptr<ComputedStyle> GetUncachedSelectionStyle(Node* node) {
return nullptr;
}
- return element->StyleForPseudoElement(PseudoStyleRequest(kPseudoIdSelection));
+ return element->StyleForPseudoElement(
+ PseudoElementStyleRequest(kPseudoIdSelection));
}
Color SelectionColor(const Document& document,
@@ -93,8 +94,10 @@ Color SelectionColor(const Document& document,
if (!LayoutTheme::GetTheme().SupportsSelectionForegroundColors())
return style.VisitedDependentColor(color_property);
return document.GetFrame()->Selection().FrameIsFocusedAndActive()
- ? LayoutTheme::GetTheme().ActiveSelectionForegroundColor()
- : LayoutTheme::GetTheme().InactiveSelectionForegroundColor();
+ ? LayoutTheme::GetTheme().ActiveSelectionForegroundColor(
+ style.UsedColorScheme())
+ : LayoutTheme::GetTheme().InactiveSelectionForegroundColor(
+ style.UsedColorScheme());
}
const ComputedStyle* SelectionPseudoStyle(Node* node) {
@@ -104,7 +107,7 @@ const ComputedStyle* SelectionPseudoStyle(Node* node) {
if (!element)
return nullptr;
return element->CachedStyleForPseudoElement(
- PseudoStyleRequest(kPseudoIdSelection));
+ PseudoElementStyleRequest(kPseudoIdSelection));
}
} // anonymous namespace
@@ -133,8 +136,10 @@ Color SelectionPaintingUtils::SelectionBackgroundColor(
}
return document.GetFrame()->Selection().FrameIsFocusedAndActive()
- ? LayoutTheme::GetTheme().ActiveSelectionBackgroundColor()
- : LayoutTheme::GetTheme().InactiveSelectionBackgroundColor();
+ ? LayoutTheme::GetTheme().ActiveSelectionBackgroundColor(
+ style.UsedColorScheme())
+ : LayoutTheme::GetTheme().InactiveSelectionBackgroundColor(
+ style.UsedColorScheme());
}
Color SelectionPaintingUtils::SelectionForegroundColor(
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
index 8d90950bd39..35f5c97991e 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -95,10 +95,10 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
SVGModelObjectPainter(layout_svg_container_)
.PaintOutline(paint_info_before_filtering);
- if (paint_info_before_filtering.IsPrinting() &&
+ if (paint_info_before_filtering.ShouldAddUrlMetadata() &&
paint_info_before_filtering.phase == PaintPhase::kForeground) {
ObjectPainter(layout_svg_container_)
- .AddPDFURLRectIfNeeded(paint_info_before_filtering, PhysicalOffset());
+ .AddURLRectIfNeeded(paint_info_before_filtering, PhysicalOffset());
}
}
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 20920bd8828..dbb5cd313db 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
@@ -78,10 +78,10 @@ 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);
- if (RuntimeEnabledFeatures::ElementTimingEnabled(
- &layout_svg_image_.GetDocument()) &&
- !paint_info.context.ContextDisabled() && image_resource->CachedImage() &&
+ paint_info.context.DrawImage(
+ image.get(), decode_mode, dest_rect, &src_rect,
+ layout_svg_image_.StyleRef().HasFilterInducingProperty());
+ if (!paint_info.context.ContextDisabled() && image_resource->CachedImage() &&
image_resource->CachedImage()->IsLoaded()) {
LocalDOMWindow* window = layout_svg_image_.GetDocument().domWindow();
DCHECK(window);
@@ -91,11 +91,9 @@ void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) {
paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled()) {
- PaintTimingDetector::NotifyImagePaint(
- layout_svg_image_, image->Size(), image_resource->CachedImage(),
- paint_info.context.GetPaintController().CurrentPaintChunkProperties());
- }
+ PaintTimingDetector::NotifyImagePaint(
+ layout_svg_image_, image->Size(), image_resource->CachedImage(),
+ paint_info.context.GetPaintController().CurrentPaintChunkProperties());
}
FloatSize SVGImagePainter::ComputeImageViewportSize() const {
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 e0c348ee30c..ea50d27ec60 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
@@ -130,7 +130,7 @@ void SVGInlineTextBoxPainter::PaintTextFragments(
bool should_paint_selection = ShouldPaintSelection(paint_info);
if (should_paint_selection) {
selection_style =
- parent_layout_object.GetCachedPseudoStyle(kPseudoIdSelection);
+ parent_layout_object.GetCachedPseudoElementStyle(kPseudoIdSelection);
if (selection_style) {
const SVGComputedStyle& svg_selection_style = selection_style->SvgStyle();
@@ -547,11 +547,13 @@ Vector<SVGTextFragmentWithRange> SVGInlineTextBoxPainter::CollectTextMatches(
const Vector<SVGTextFragmentWithRange> empty_text_match_list;
// SVG does not support grammar or spellcheck markers, so skip anything but
- // TextMatch.
- if (marker.GetType() != DocumentMarker::kTextMatch)
+ // TextMarkerBase types.
+ if (marker.GetType() != DocumentMarker::kTextMatch &&
+ marker.GetType() != DocumentMarker::kTextFragment)
return empty_text_match_list;
- if (!InlineLayoutObject()
+ if (marker.GetType() == DocumentMarker::kTextMatch &&
+ !InlineLayoutObject()
.GetFrame()
->GetEditor()
.MarkedTextMatchesAreHighlighted())
@@ -587,10 +589,10 @@ SVGInlineTextBoxPainter::CollectFragmentsInRange(int start_position,
return fragment_info_list;
}
-void SVGInlineTextBoxPainter::PaintTextMatchMarkerForeground(
+void SVGInlineTextBoxPainter::PaintTextMarkerForeground(
const PaintInfo& paint_info,
const LayoutPoint& point,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
const ComputedStyle& style,
const Font& font) {
const Vector<SVGTextFragmentWithRange> text_match_info_list =
@@ -634,10 +636,10 @@ void SVGInlineTextBoxPainter::PaintTextMatchMarkerForeground(
}
}
-void SVGInlineTextBoxPainter::PaintTextMatchMarkerBackground(
+void SVGInlineTextBoxPainter::PaintTextMarkerBackground(
const PaintInfo& paint_info,
const LayoutPoint& point,
- const TextMatchMarker& marker,
+ const TextMarkerBase& marker,
const ComputedStyle& style,
const Font& font) {
const Vector<SVGTextFragmentWithRange> text_match_info_list =
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 69e1fe53a13..323c1ec3abc 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
@@ -20,7 +20,7 @@ class LayoutSVGInlineText;
class ComputedStyle;
class SVGInlineTextBox;
struct SVGTextFragment;
-class TextMatchMarker;
+class TextMarkerBase;
class TextRun;
struct SVGTextFragmentWithRange {
@@ -43,16 +43,16 @@ class SVGInlineTextBoxPainter {
: svg_inline_text_box_(svg_inline_text_box) {}
void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintSelectionBackground(const PaintInfo&);
- void PaintTextMatchMarkerForeground(const PaintInfo&,
- const LayoutPoint&,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&);
- void PaintTextMatchMarkerBackground(const PaintInfo&,
- const LayoutPoint&,
- const TextMatchMarker&,
- const ComputedStyle&,
- const Font&);
+ void PaintTextMarkerForeground(const PaintInfo&,
+ const LayoutPoint&,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&);
+ void PaintTextMarkerBackground(const PaintInfo&,
+ const LayoutPoint&,
+ const TextMarkerBase&,
+ const ComputedStyle&,
+ const Font&);
private:
bool ShouldPaintSelection(const PaintInfo&) const;
diff --git a/chromium/third_party/blink/renderer/core/paint/text_element_timing.cc b/chromium/third_party/blink/renderer/core/paint/text_element_timing.cc
index 53caeae3f97..85f3e0d8fbd 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_element_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_element_timing.cc
@@ -34,10 +34,7 @@ TextElementTiming& TextElementTiming::From(LocalDOMWindow& window) {
TextElementTiming::TextElementTiming(LocalDOMWindow& window)
: Supplement<LocalDOMWindow>(window),
- performance_(DOMWindowPerformance::performance(window)) {
- DCHECK(RuntimeEnabledFeatures::ElementTimingEnabled(
- GetSupplementable()->document()));
-}
+ performance_(DOMWindowPerformance::performance(window)) {}
// static
FloatRect TextElementTiming::ComputeIntersectionRect(
@@ -54,34 +51,30 @@ FloatRect TextElementTiming::ComputeIntersectionRect(
&frame_view->GetFrame(), aggregated_visual_rect, property_tree_state);
}
-void TextElementTiming::OnTextObjectsPainted(
- const Deque<base::WeakPtr<TextRecord>>& text_nodes_painted) {
+bool TextElementTiming::CanReportElements() const {
DCHECK(performance_);
- // If the entries cannot be exposed via PerformanceObserver nor added to the
- // buffer, bail out.
- if (!performance_->HasObserverFor(PerformanceEntry::kElement) &&
- performance_->IsElementTimingBufferFull()) {
+ return performance_->HasObserverFor(PerformanceEntry::kElement) ||
+ !performance_->IsElementTimingBufferFull();
+}
+
+void TextElementTiming::OnTextObjectPainted(const TextRecord& record) {
+ Node* node = DOMNodeIds::NodeForId(record.node_id);
+ if (!node || node->IsInShadowTree())
return;
- }
- for (const auto record : text_nodes_painted) {
- Node* node = DOMNodeIds::NodeForId(record->node_id);
- if (!node || node->IsInShadowTree())
- continue;
- // Text aggregators should be Elements!
- DCHECK(node->IsElementNode());
- auto* element = To<Element>(node);
- const AtomicString& attr =
- element->FastGetAttribute(html_names::kElementtimingAttr);
- if (attr.IsEmpty())
- continue;
+ // Text aggregators should be Elements!
+ DCHECK(node->IsElementNode());
+ auto* element = To<Element>(node);
+ const AtomicString& attr =
+ element->FastGetAttribute(html_names::kElementtimingAttr);
+ if (attr.IsEmpty())
+ return;
- const AtomicString& id = element->GetIdAttribute();
- DEFINE_STATIC_LOCAL(const AtomicString, kTextPaint, ("text-paint"));
- performance_->AddElementTiming(
- kTextPaint, g_empty_string, record->element_timing_rect_,
- record->paint_time, base::TimeTicks(), attr, IntSize(), id, element);
- }
+ const AtomicString& id = element->GetIdAttribute();
+ DEFINE_STATIC_LOCAL(const AtomicString, kTextPaint, ("text-paint"));
+ performance_->AddElementTiming(
+ kTextPaint, g_empty_string, record.element_timing_rect_,
+ record.paint_time, base::TimeTicks(), attr, IntSize(), id, element);
}
void TextElementTiming::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/paint/text_element_timing.h b/chromium/third_party/blink/renderer/core/paint/text_element_timing.h
index f3a4c40902a..94b1e546741 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_element_timing.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_element_timing.h
@@ -23,7 +23,7 @@ class TextRecord;
// TextElementTiming is responsible for tracking the paint timings for groups of
// text nodes associated with elements of a given window.
class CORE_EXPORT TextElementTiming final
- : public GarbageCollectedFinalized<TextElementTiming>,
+ : public GarbageCollected<TextElementTiming>,
public Supplement<LocalDOMWindow> {
USING_GARBAGE_COLLECTED_MIXIN(TextElementTiming);
@@ -46,9 +46,11 @@ class CORE_EXPORT TextElementTiming final
const PropertyTreeState&,
const LocalFrameView*);
+ bool CanReportElements() const;
+
// Called when the swap promise queued by TextPaintTimingDetector has been
// resolved. Dispatches PerformanceElementTiming entries to WindowPerformance.
- void OnTextObjectsPainted(const Deque<base::WeakPtr<TextRecord>>&);
+ void OnTextObjectPainted(const TextRecord&);
void Trace(blink::Visitor* visitor) override;
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
index ae719505e1f..93c7e63670a 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.cc
@@ -112,8 +112,6 @@ void TextPaintTimingDetector::OnPaintFinished() {
void TextPaintTimingDetector::LayoutObjectWillBeDestroyed(
const LayoutObject& object) {
- if (!is_recording_)
- return;
if (records_manager_.IsKnownVisible(object)) {
records_manager_.RemoveVisibleRecord(object);
need_update_timing_at_frame_end_ = true;
@@ -130,11 +128,9 @@ void TextPaintTimingDetector::RegisterNotifySwapTime(
}
void TextPaintTimingDetector::ReportSwapTime(base::TimeTicks timestamp) {
- if (!is_recording_)
- return;
if (!records_manager_.HasTextElementTiming()) {
Document* document = frame_view_->GetFrame().GetDocument();
- if (document && RuntimeEnabledFeatures::ElementTimingEnabled(document)) {
+ if (document) {
LocalDOMWindow* window = document->domWindow();
if (window) {
records_manager_.SetTextElementTiming(
@@ -150,8 +146,6 @@ void TextPaintTimingDetector::ReportSwapTime(base::TimeTicks timestamp) {
bool TextPaintTimingDetector::ShouldWalkObject(
const LayoutBoxModelObject& object) const {
- if (!is_recording_)
- return false;
// TODO(crbug.com/933479): Use LayoutObject::GeneratingNode() to include
// anonymous objects' rect.
Node* node = object.GetNode();
@@ -161,12 +155,10 @@ bool TextPaintTimingDetector::ShouldWalkObject(
// shadow element or has no elementtiming attribute, then we should not record
// its text.
if (!records_manager_.IsRecordingLargestTextPaint() &&
- !TextElementTiming::NeededForElementTiming(*node))
+ !TextElementTiming::NeededForElementTiming(*node)) {
return false;
+ }
- DOMNodeId node_id = DOMNodeIds::ExistingIdForNode(node);
- if (node_id == kInvalidDOMNodeId)
- return true;
// This metric defines the size of a text block by its first size, so we
// should not walk the object if it has been recorded.
return !records_manager_.HasRecorded(object);
@@ -201,11 +193,6 @@ void TextPaintTimingDetector::RecordAggregatedText(
}
}
-void TextPaintTimingDetector::StopRecordEntries() {
- is_recording_ = false;
- records_manager_.CleanUp();
-}
-
void TextPaintTimingDetector::StopRecordingLargestTextPaint() {
records_manager_.CleanUpLargestTextPaint();
}
@@ -250,10 +237,14 @@ void TextRecordsManager::RemoveInvisibleRecord(const LayoutObject& object) {
void TextRecordsManager::AssignPaintTimeToQueuedRecords(
const base::TimeTicks& timestamp) {
- // If texts_queued_for_paint_time_.size == 0, it means the array has been
+ // If the number of TextRecords to be processed is 0, it means they have been
// consumed in a callback earlier than this one. That violates the assumption
// that only one or zero callback will be called after one OnPaintFinished.
- DCHECK_GT(texts_queued_for_paint_time_.size(), 0UL);
+ DCHECK_GT(texts_queued_for_paint_time_.size() +
+ size_zero_texts_queued_for_paint_time_.size(),
+ 0UL);
+ bool can_report_element_timing =
+ text_element_timing_ ? text_element_timing_->CanReportElements() : false;
for (auto iterator = texts_queued_for_paint_time_.begin();
iterator != texts_queued_for_paint_time_.end(); ++iterator) {
// The record may have been removed between the callback registration and
@@ -265,10 +256,17 @@ void TextRecordsManager::AssignPaintTimeToQueuedRecords(
}
DCHECK_EQ(record->paint_time, base::TimeTicks());
record->paint_time = timestamp;
+ if (can_report_element_timing)
+ text_element_timing_->OnTextObjectPainted(*record);
+ }
+ if (can_report_element_timing) {
+ for (const auto& record : size_zero_texts_queued_for_paint_time_) {
+ record->paint_time = timestamp;
+ text_element_timing_->OnTextObjectPainted(*record);
+ }
}
- if (text_element_timing_)
- text_element_timing_->OnTextObjectsPainted(texts_queued_for_paint_time_);
texts_queued_for_paint_time_.clear();
+ size_zero_texts_queued_for_paint_time_.clear();
if (ltp_manager_)
ltp_manager_->SetCachedResultInvalidated(true);
}
@@ -293,6 +291,20 @@ void TextRecordsManager::RecordVisibleObject(
visible_objects_.insert(&object, std::move(record));
}
+void TextRecordsManager::RecordInvisibleObject(const LayoutObject& object) {
+ invisible_objects_.insert(&object);
+ Node* node = object.GetNode();
+ DCHECK(node);
+ if (!TextElementTiming::NeededForElementTiming(*node))
+ return;
+ DOMNodeId node_id = DOMNodeIds::IdForNode(node);
+ DCHECK_NE(node_id, kInvalidDOMNodeId);
+ // Since it is invisible, the record will have a size of 0 and an empty rect.
+ std::unique_ptr<TextRecord> record =
+ std::make_unique<TextRecord>(node_id, 0, FloatRect());
+ size_zero_texts_queued_for_paint_time_.push_back(std::move(record));
+}
+
base::WeakPtr<TextRecord> LargestTextPaintManager::FindLargestPaintCandidate() {
if (!is_result_invalidated_ && cached_largest_paint_candidate_)
return cached_largest_paint_candidate_;
@@ -312,15 +324,7 @@ base::WeakPtr<TextRecord> LargestTextPaintManager::FindLargestPaintCandidate() {
TextRecordsManager::TextRecordsManager(
LocalFrameView* frame_view,
PaintTimingDetector* paint_timing_detector) {
- if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled())
- ltp_manager_.emplace(frame_view, paint_timing_detector);
-}
-
-void TextRecordsManager::CleanUp() {
- visible_objects_.clear();
- invisible_objects_.clear();
- texts_queued_for_paint_time_.clear();
- CleanUpLargestTextPaint();
+ ltp_manager_.emplace(frame_view, paint_timing_detector);
}
void TextRecordsManager::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
index 15f03be7058..500a3003a8c 100644
--- a/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
+++ b/chromium/third_party/blink/renderer/core/paint/text_paint_timing_detector.h
@@ -109,14 +109,13 @@ class CORE_EXPORT TextRecordsManager {
void RemoveVisibleRecord(const LayoutObject&);
void RemoveInvisibleRecord(const LayoutObject&);
- inline void RecordInvisibleObject(const LayoutObject& object) {
- invisible_objects_.insert(&object);
- }
void RecordVisibleObject(const LayoutObject&,
const uint64_t& visual_size,
const FloatRect& element_timing_rect);
+ void RecordInvisibleObject(const LayoutObject& object);
bool NeedMeausuringPaintTime() const {
- return !texts_queued_for_paint_time_.IsEmpty();
+ return !texts_queued_for_paint_time_.IsEmpty() ||
+ !size_zero_texts_queued_for_paint_time_.IsEmpty();
}
void AssignPaintTimeToQueuedRecords(const base::TimeTicks&);
@@ -133,7 +132,6 @@ class CORE_EXPORT TextRecordsManager {
return invisible_objects_.Contains(&object);
}
- void CleanUp();
void CleanUpLargestTextPaint();
bool HasTextElementTiming() const { return text_element_timing_; }
@@ -166,6 +164,11 @@ class CORE_EXPORT TextRecordsManager {
HashSet<const LayoutObject*> invisible_objects_;
Deque<base::WeakPtr<TextRecord>> texts_queued_for_paint_time_;
+ // These are text records created to notify Element Timing of texts which are
+ // first painted outside of the viewport. These have size 0 for the purpose of
+ // LCP computations, even if the size of the text itself is not 0. They are
+ // considered invisible objects by Largest Contentful Paint.
+ Deque<std::unique_ptr<TextRecord>> size_zero_texts_queued_for_paint_time_;
base::Optional<LargestTextPaintManager> ltp_manager_;
Member<TextElementTiming> text_element_timing_;
@@ -189,7 +192,7 @@ class CORE_EXPORT TextRecordsManager {
// See also:
// https://docs.google.com/document/d/1DRVd4a2VU8-yyWftgOparZF-sf16daf0vfbsHuz2rws/edit#heading=h.lvno2v283uls
class CORE_EXPORT TextPaintTimingDetector final
- : public GarbageCollectedFinalized<TextPaintTimingDetector> {
+ : public GarbageCollected<TextPaintTimingDetector> {
friend class TextPaintTimingDetectorTest;
public:
@@ -202,10 +205,7 @@ class CORE_EXPORT TextPaintTimingDetector final
const PropertyTreeState&);
void OnPaintFinished();
void LayoutObjectWillBeDestroyed(const LayoutObject&);
- void StopRecordEntries();
void StopRecordingLargestTextPaint();
- bool IsRecording() const { return is_recording_; }
- inline bool FinishedReportingText() const { return !is_recording_; }
void ResetCallbackManager(PaintTimingCallbackManager* manager) {
callback_manager_ = manager;
}
@@ -230,7 +230,6 @@ class CORE_EXPORT TextPaintTimingDetector final
// Make sure that at most one swap promise is ongoing.
bool awaiting_swap_promise_ = false;
- bool is_recording_ = true;
bool need_update_timing_at_frame_end_ = false;
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 87aa2a4e2a2..4cdf7c03b0f 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
@@ -17,13 +17,10 @@
namespace blink {
-class TextPaintTimingDetectorTest
- : public testing::Test,
- private ScopedFirstContentfulPaintPlusPlusForTest {
+class TextPaintTimingDetectorTest : public testing::Test {
public:
TextPaintTimingDetectorTest()
- : ScopedFirstContentfulPaintPlusPlusForTest(true),
- test_task_runner_(
+ : test_task_runner_(
base::MakeRefCounted<base::TestMockTimeTaskRunner>()) {}
void SetUp() override {
@@ -110,6 +107,10 @@ class TextPaintTimingDetectorTest
GetPaintTimingDetector().NotifyInputEvent(WebInputEvent::Type::kMouseDown);
}
+ void SimulateScroll() {
+ GetPaintTimingDetector().NotifyScroll(ScrollType::kUserScroll);
+ }
+
void InvokeCallback() {
DCHECK_GT(mock_callback_manager_->CountCallbacks(), 0u);
InvokeSwapTimeCallback(mock_callback_manager_);
@@ -742,4 +743,30 @@ TEST_F(TextPaintTimingDetectorTest, SameSizeShouldNotBeIgnored) {
EXPECT_EQ(CountRankingSetSize(), 4u);
}
+TEST_F(TextPaintTimingDetectorTest, VisibleTextAfterUserInput) {
+ SetBodyInnerHTML(R"HTML(
+ )HTML");
+ AppendDivElementToBody("text");
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ EXPECT_EQ(CountVisibleTexts(), 1u);
+ EXPECT_TRUE(GetLargestTextPaintManager());
+
+ SimulateInputEvent();
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ EXPECT_EQ(CountVisibleTexts(), 1u);
+}
+
+TEST_F(TextPaintTimingDetectorTest, VisibleTextAfterUserScroll) {
+ SetBodyInnerHTML(R"HTML(
+ )HTML");
+ AppendDivElementToBody("text");
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ EXPECT_EQ(CountVisibleTexts(), 1u);
+ EXPECT_TRUE(GetLargestTextPaintManager());
+
+ SimulateScroll();
+ UpdateAllLifecyclePhasesAndSimulateSwapTime();
+ EXPECT_EQ(CountVisibleTexts(), 1u);
+}
+
} // namespace blink
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 581ea5b6332..86492b3499f 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter.cc
@@ -160,6 +160,10 @@ bool ThemePainter::Paint(const LayoutObject& o,
// -webkit-appearance:push-button by default.
UseCounter::Count(doc,
WebFeature::kCSSValueAppearanceButtonForOtherButtons);
+ } else if (IsA<HTMLInputElement>(node) &&
+ To<HTMLInputElement>(node)->type() == input_type_names::kColor) {
+ // 'button' for input[type=color], of which default appearance is
+ // 'square-button', is not deprecated.
} else {
COUNT_APPEARANCE(doc, ButtonForNonButton);
COUNT_APPEARANCE(doc, ButtonForOthers);
@@ -171,9 +175,9 @@ bool ThemePainter::Paint(const LayoutObject& o,
To<Element>(node)->getAttribute(html_names::kTypeAttr);
// https://github.com/twbs/bootstrap/pull/29053
if (type == "button" || type == "reset" || type == "submit") {
- COUNT_APPEARANCE(doc, ButtonForBootstrapLooseSelector);
+ DEPRECATE_APPEARANCE(doc, ButtonForBootstrapLooseSelector);
} else {
- COUNT_APPEARANCE(doc, ButtonForOthers2);
+ DEPRECATE_APPEARANCE(doc, ButtonForOthers2);
}
}
}
@@ -220,7 +224,7 @@ bool ThemePainter::Paint(const LayoutObject& o,
}
case kMenulistPart:
COUNT_APPEARANCE(doc, MenuList);
- if (!IsHTMLSelectElement(node) && !IsMenulistInput(node))
+ if (!IsA<HTMLSelectElement>(node) && !IsMenulistInput(node))
DEPRECATE_APPEARANCE(doc, MenuListForOthers);
return PaintMenuList(node, o.GetDocument(), style, paint_info, r);
case kMeterPart:
@@ -394,7 +398,7 @@ bool ThemePainter::PaintDecorations(const Node* node,
switch (style.EffectiveAppearance()) {
case kMenulistButtonPart:
COUNT_APPEARANCE(document, MenuListButton);
- if (!IsHTMLSelectElement(node) && !IsMenulistInput(node))
+ if (!IsA<HTMLSelectElement>(node) && !IsMenulistInput(node))
DEPRECATE_APPEARANCE(document, MenuListButtonForOthers);
return PaintMenuListButton(node, document, style, paint_info, r);
case kTextFieldPart:
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 dffb3b45dfe..5d32376c5dc 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
@@ -226,7 +226,8 @@ bool ThemePainterDefault::PaintTextField(const Node* node,
// 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.dark_mode_settings().mode != DarkMode::kOff)
+ if (paint_info.context.dark_mode_settings().mode !=
+ DarkModeInversionAlgorithm::kOff)
return true;
ControlPart part = style.EffectiveAppearance();
@@ -310,8 +311,8 @@ void ThemePainterDefault::SetupMenuListArrow(
const int middle = rect.Y() + rect.Height() / 2;
extra_params.menu_list.arrow_y = middle;
- float arrow_box_width = theme_.ClampedMenuListArrowPaddingSize(
- document.View()->GetChromeClient(), style);
+ float arrow_box_width =
+ theme_.ClampedMenuListArrowPaddingSize(document.GetFrame(), style);
float arrow_scale_factor = arrow_box_width / theme_.MenuListArrowWidthInDIP();
if (UseMockTheme()) {
// The size and position of the drop-down button is different between
@@ -333,7 +334,7 @@ void ThemePainterDefault::SetupMenuListArrow(
} else {
// TODO(tkent): This should be 7.0 to match scroll bar buttons.
float arrow_size =
- (RuntimeEnabledFeatures::FormControlsRefreshEnabled() ? 12.0 : 6.0) *
+ (RuntimeEnabledFeatures::FormControlsRefreshEnabled() ? 8.0 : 6.0) *
arrow_scale_factor;
// Put the arrow at the center of paddingForArrow area.
// |arrowX| is the left position for Aura theme engine.
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm b/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
index e94235acb17..8f4ae94bc1d 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
@@ -53,6 +53,28 @@ void _NSDrawCarbonThemeListBox(NSRect frame,
namespace blink {
+class ScopedColorSchemeAppearance {
+ public:
+ ScopedColorSchemeAppearance(WebColorScheme color_scheme) {
+ if (@available(macOS 10.14, *)) {
+ old_appearance = [NSAppearance currentAppearance];
+ [NSAppearance
+ setCurrentAppearance:
+ [NSAppearance
+ appearanceNamed:color_scheme == WebColorScheme::kDark
+ ? NSAppearanceNameDarkAqua
+ : NSAppearanceNameAqua]];
+ }
+ }
+ ~ScopedColorSchemeAppearance() {
+ if (@available(macOS 10.14, *))
+ [NSAppearance setCurrentAppearance:old_appearance];
+ }
+
+ private:
+ NSAppearance* old_appearance;
+};
+
ThemePainterMac::ThemePainterMac(LayoutThemeMac& layout_theme)
: ThemePainter(), layout_theme_(layout_theme) {}
@@ -60,6 +82,7 @@ bool ThemePainterMac::PaintTextField(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
LocalCurrentGraphicsContext local_context(paint_info.context, r);
bool use_ns_text_field_cell =
@@ -97,6 +120,7 @@ bool ThemePainterMac::PaintCapsLockIndicator(const LayoutObject& o,
const IntRect& r) {
// This draws the caps lock indicator as it was done by
// WKDrawCapsLockIndicator.
+ ScopedColorSchemeAppearance appearance(o.StyleRef().UsedColorScheme());
LocalCurrentGraphicsContext local_context(paint_info.context, r);
CGContextRef c = local_context.CgContext();
CGMutablePathRef shape = CGPathCreateMutable();
@@ -160,6 +184,7 @@ bool ThemePainterMac::PaintTextArea(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
LocalCurrentGraphicsContext local_context(paint_info.context, r);
_NSDrawCarbonThemeListBox(
CGRect(r),
@@ -173,6 +198,7 @@ bool ThemePainterMac::PaintMenuList(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
layout_theme_.SetPopupButtonCellState(node, style, r);
NSPopUpButtonCell* popup_button = layout_theme_.PopupButton();
@@ -215,6 +241,8 @@ bool ThemePainterMac::PaintProgressBar(const LayoutObject& layout_object,
if (!layout_object.IsProgress())
return true;
+ ScopedColorSchemeAppearance appearance(
+ layout_object.StyleRef().UsedColorScheme());
const LayoutProgress& layout_progress = ToLayoutProgress(layout_object);
HIThemeTrackDrawInfo track_info;
track_info.version = 0;
@@ -266,6 +294,7 @@ bool ThemePainterMac::PaintMenuListButton(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
IntRect bounds =
IntRect(r.X() + style.BorderLeftWidth(), r.Y() + style.BorderTopWidth(),
r.Width() - style.BorderLeftWidth() - style.BorderRightWidth(),
@@ -322,6 +351,7 @@ bool ThemePainterMac::PaintMenuListButton(const Node* node,
bool ThemePainterMac::PaintSliderTrack(const LayoutObject& o,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(o.StyleRef().UsedColorScheme());
PaintSliderTicks(o, paint_info, r);
float zoom_level = o.StyleRef().EffectiveZoom();
@@ -418,6 +448,7 @@ bool ThemePainterMac::PaintSliderThumb(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
GraphicsContextStateSaver state_saver(paint_info.context);
float zoom_level = style.EffectiveZoom();
@@ -521,6 +552,7 @@ bool ThemePainterMac::PaintSearchField(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& r) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
LocalCurrentGraphicsContext local_context(paint_info.context, r);
NSSearchFieldCell* search = layout_theme_.Search();
@@ -560,6 +592,8 @@ bool ThemePainterMac::PaintSearchFieldCancelButton(
if (!cancel_button.GetNode())
return false;
+ ScopedColorSchemeAppearance appearance(
+ cancel_button.StyleRef().UsedColorScheme());
GraphicsContextStateSaver state_saver(paint_info.context);
float zoom_level = cancel_button.StyleRef().EffectiveZoom();
@@ -616,6 +650,7 @@ bool ThemePainterMac::PaintCheckbox(const Node* node,
const IntRect& zoomed_rect) {
BEGIN_BLOCK_OBJC_EXCEPTIONS
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
ControlStates states = LayoutTheme::ControlStatesForNode(node, style);
float zoom_factor = style.EffectiveZoom();
@@ -659,6 +694,7 @@ bool ThemePainterMac::PaintRadio(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& zoomed_rect) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
ControlStates states = LayoutTheme::ControlStatesForNode(node, style);
float zoom_factor = style.EffectiveZoom();
@@ -705,6 +741,7 @@ bool ThemePainterMac::PaintButton(const Node* node,
const IntRect& zoomed_rect) {
BEGIN_BLOCK_OBJC_EXCEPTIONS
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
ControlStates states = LayoutTheme::ControlStatesForNode(node, style);
float zoom_factor = style.EffectiveZoom();
@@ -781,6 +818,7 @@ bool ThemePainterMac::PaintInnerSpinButton(const Node* node,
const ComputedStyle& style,
const PaintInfo& paint_info,
const IntRect& zoomed_rect) {
+ ScopedColorSchemeAppearance appearance(style.UsedColorScheme());
ControlStates states = LayoutTheme::ControlStatesForNode(node, style);
float zoom_factor = style.EffectiveZoom();
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter.cc b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
index 19d1007cd11..69ff740fea8 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
@@ -38,15 +38,14 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
bool has_touch_action_rect = layout_view_.HasEffectiveAllowedTouchAction();
bool paints_scroll_hit_test =
- RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled() &&
- (layout_view_.GetScrollableArea() &&
- layout_view_.GetScrollableArea()->ScrollsOverflow());
+ layout_view_.GetScrollableArea() &&
+ layout_view_.GetScrollableArea()->ScrollsOverflow();
if (!layout_view_.HasBoxDecorationBackground() && !has_touch_action_rect &&
!paints_scroll_hit_test)
return;
// The background rect always includes at least the visible content size.
- IntRect background_rect(PixelSnappedIntRect(layout_view_.BackgroundRect()));
+ PhysicalRect background_rect(layout_view_.BackgroundRect());
// When printing, paint the entire unclipped scrolling content area.
if (paint_info.IsPrinting())
@@ -64,7 +63,7 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
// DocumentRect is relative to ScrollOrigin. Add ScrollOrigin to let it be
// in the space of ContentsProperties(). See ScrollTranslation in
// object_paint_properties.h for details.
- document_rect.MoveBy(layout_view_.ScrollOrigin());
+ document_rect.Move(PhysicalOffset(layout_view_.ScrollOrigin()));
background_rect.Unite(document_rect);
background_client = &layout_view_.GetScrollableArea()
->GetScrollingBackgroundDisplayItemClient();
@@ -75,41 +74,40 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
}
if (layout_view_.HasBoxDecorationBackground()) {
- PaintBoxDecorationBackgroundInternal(paint_info, background_rect,
- *background_client);
+ PaintBoxDecorationBackgroundInternal(
+ paint_info, PixelSnappedIntRect(background_rect), *background_client);
}
if (has_touch_action_rect) {
BoxPainter(layout_view_)
- .RecordHitTestData(paint_info, PhysicalRect(background_rect),
+ .RecordHitTestData(paint_info,
+ PhysicalRect(PixelSnappedIntRect(background_rect)),
*background_client);
}
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- bool needs_scroll_hit_test = true;
- if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
- // display items for composited scrollers because these display items are
- // only used to create non-fast scrollable regions for non-composited
- // scrollers. With CompositeAfterPaint, we always paint the scroll hit
- // test display items but ignore the non-fast region if the scroll was
- // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
- if (layout_view_.HasLayer() &&
- layout_view_.Layer()->GetCompositedLayerMapping() &&
- layout_view_.Layer()
- ->GetCompositedLayerMapping()
- ->HasScrollingLayer()) {
- needs_scroll_hit_test = false;
- }
+ bool needs_scroll_hit_test = true;
+ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // Pre-CompositeAfterPaint, there is no need to emit scroll hit test
+ // display items for composited scrollers because these display items are
+ // only used to create non-fast scrollable regions for non-composited
+ // scrollers. With CompositeAfterPaint, we always paint the scroll hit
+ // test display items but ignore the non-fast region if the scroll was
+ // composited in PaintArtifactCompositor::UpdateNonFastScrollableRegions.
+ if (layout_view_.HasLayer() &&
+ layout_view_.Layer()->GetCompositedLayerMapping() &&
+ layout_view_.Layer()
+ ->GetCompositedLayerMapping()
+ ->HasScrollingLayer()) {
+ needs_scroll_hit_test = false;
}
+ }
- // Record the scroll hit test after the non-scrolling background so
- // background squashing is not affected. Hit test order would be equivalent
- // if this were immediately before the non-scrolling background.
- if (paints_scroll_hit_test && !painting_scrolling_background &&
- needs_scroll_hit_test) {
- BoxPainter(layout_view_)
- .RecordScrollHitTestData(paint_info, *background_client);
- }
+ // Record the scroll hit test after the non-scrolling background so
+ // background squashing is not affected. Hit test order would be equivalent
+ // if this were immediately before the non-scrolling background.
+ if (paints_scroll_hit_test && !painting_scrolling_background &&
+ needs_scroll_hit_test) {
+ BoxPainter(layout_view_)
+ .RecordScrollHitTestData(paint_info, *background_client);
}
}
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
index df02d02ff3f..7897445c8cb 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observation.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
+#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
@@ -21,11 +22,26 @@ ResizeObservation::ResizeObservation(Element* target, ResizeObserver* observer)
}
bool ResizeObservation::ObservationSizeOutOfSync() {
- return element_size_changed_ && observation_size_ != ComputeTargetSize();
+ if (!element_size_changed_ || observation_size_ == ComputeTargetSize())
+ return false;
+
+ // Skip resize observations on locked elements.
+ if (UNLIKELY(
+ DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*target_))) {
+ return false;
+ }
+
+ return true;
}
void ResizeObservation::SetObservationSize(const LayoutSize& observation_size) {
observation_size_ = observation_size;
+
+ // Don't clear the dirty bit while locked. This allows us to make sure to
+ // compare sizes when becoming unlocked.
+ if (UNLIKELY(DisplayLockUtilities::IsInLockedSubtreeCrossingFrames(*target_)))
+ return;
+
element_size_changed_ = false;
}
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 047bd3dae98..572f88ee1c4 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
@@ -31,7 +31,7 @@ class CORE_EXPORT ResizeObserver final
public:
// This delegate is an internal (non-web-exposed) version of ResizeCallback.
- class Delegate : public GarbageCollectedFinalized<Delegate> {
+ class Delegate : public GarbageCollected<Delegate> {
public:
virtual ~Delegate() = default;
virtual void OnResize(
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
index d2cf42fd39d..e1ae935916c 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc
@@ -27,6 +27,14 @@ size_t ResizeObserverController::GatherObservations(size_t deeper_than) {
return shallowest;
}
+void ResizeObserverController::SetNeedsForcedResizeObservations() {
+ for (auto& observer : observers_) {
+ // Set ElementSizeChanged as a way of forcing the observer to check all
+ // observations.
+ observer->ElementSizeChanged();
+ }
+}
+
bool ResizeObserverController::SkippedObservations() {
for (auto& observer : observers_) {
if (observer->SkippedObservations())
diff --git a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
index 9cca2129b26..27511e15ddc 100644
--- a/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
+++ b/chromium/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
@@ -37,6 +37,8 @@ class ResizeObserverController final
void ClearObservations();
void ObserverChanged() { observers_changed_ = true; }
+ void SetNeedsForcedResizeObservations();
+
void Trace(blink::Visitor*);
// For testing only.
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 7c1c09e8b94..93eb2670e6b 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
@@ -55,9 +55,9 @@ TEST_F(SchedulingAffectingFeaturesTest, WebSocketStopsThrottling) {
testing::UnorderedElementsAre());
main_resource.Complete(
- "(<script>"
+ "<script>"
" var socket = new WebSocket(\"ws://www.example.com/websocket\");"
- "</script>)");
+ "</script>");
EXPECT_TRUE(PageScheduler()->OptedOutFromAggressiveThrottlingForTest());
EXPECT_THAT(
@@ -83,9 +83,9 @@ TEST_F(SchedulingAffectingFeaturesTest, WebRTCStopsThrottling) {
testing::UnorderedElementsAre());
main_resource.Complete(
- "(<script>"
+ "<script>"
" var data_channel = new RTCPeerConnection();"
- "</script>)");
+ "</script>");
EXPECT_TRUE(PageScheduler()->OptedOutFromAggressiveThrottlingForTest());
EXPECT_THAT(
@@ -173,9 +173,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_PageShow) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"pageshow\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -186,9 +186,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_PageHide) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"pagehide\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -199,9 +199,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_BeforeUnload) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"beforeunload\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -212,9 +212,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_Unload) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"unload\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -225,9 +225,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_Freeze) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"freeze\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -238,9 +238,9 @@ TEST_F(SchedulingAffectingFeaturesTest, EventListener_Resume) {
SimRequest main_resource("https://foo.com/", "text/html");
LoadURL("https://foo.com/");
main_resource.Complete(
- "(<script>"
+ "<script>"
" window.addEventListener(\"resume\", () => {}); "
- "</script>)");
+ "</script>");
EXPECT_THAT(GetNonTrivialMainFrameFeatures(),
testing::UnorderedElementsAre(
@@ -270,4 +270,17 @@ TEST_F(SchedulingAffectingFeaturesTest, Plugins) {
SchedulingPolicy::Feature::kContainsPlugins));
}
+TEST_F(SchedulingAffectingFeaturesTest, WebLocks) {
+ SimRequest main_resource("https://foo.com/", "text/html");
+ LoadURL("https://foo.com/");
+ main_resource.Complete(
+ "<script>"
+ " navigator.locks.request('my_resource', async lock => {}); "
+ "</script>");
+
+ EXPECT_THAT(
+ GetNonTrivialMainFrameFeatures(),
+ testing::UnorderedElementsAre(SchedulingPolicy::Feature::kWebLocks));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/BUILD.gn b/chromium/third_party/blink/renderer/core/script/BUILD.gn
index 80193dea9c3..c4d16409cd2 100644
--- a/chromium/third_party/blink/renderer/core/script/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/script/BUILD.gn
@@ -5,8 +5,6 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("script") {
- split_count = 5
-
sources = [
"classic_pending_script.cc",
"classic_pending_script.h",
diff --git a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
index e4bb75221db..5baad6fd19c 100644
--- a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
+++ b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
@@ -160,8 +160,8 @@ bool MaybeDisallowFetchForDocWrittenScript(FetchParameters& params,
// block more scripts than necessary.
if (params.Url().Protocol() != document.GetSecurityOrigin()->Protocol()) {
document.Loader()->DidObserveLoadingBehavior(
- WebLoadingBehaviorFlag::
- kWebLoadingBehaviorDocumentWriteBlockDifferentScheme);
+ LoadingBehaviorFlag::
+ kLoadingBehaviorDocumentWriteBlockDifferentScheme);
}
return false;
}
@@ -176,7 +176,7 @@ bool MaybeDisallowFetchForDocWrittenScript(FetchParameters& params,
// Recording this metric since an increase in number of reloads for pages
// where a script was blocked could be indicative of a page break.
document.Loader()->DidObserveLoadingBehavior(
- WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlockReload);
+ LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlockReload);
AddWarningHeader(&params);
return false;
}
@@ -185,11 +185,10 @@ bool MaybeDisallowFetchForDocWrittenScript(FetchParameters& params,
// that are eligible for blocking. Note that if there are multiple scripts
// the flag will be conveyed to the browser process only once.
document.Loader()->DidObserveLoadingBehavior(
- WebLoadingBehaviorFlag::kWebLoadingBehaviorDocumentWriteBlock);
+ LoadingBehaviorFlag::kLoadingBehaviorDocumentWriteBlock);
- if (!ShouldDisallowFetch(
- settings, GetNetworkStateNotifier().ConnectionType(),
- document.GetFrame()->Client()->GetEffectiveConnectionType())) {
+ if (!ShouldDisallowFetch(settings, GetNetworkStateNotifier().ConnectionType(),
+ GetNetworkStateNotifier().EffectiveType())) {
AddWarningHeader(&params);
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
index 4587ec362ad..69f964c7267 100644
--- a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
-#include "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/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
index 2bd8365bb0e..e46c3e69a88 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
@@ -493,6 +493,15 @@ bool HTMLParserScriptRunner::ExecuteScriptsWaitingForParsing() {
// document has finished parsing is still not empty, repeat these substeps
// again from substep 1.</spec>
}
+
+ // All scripts waiting for parsing have now executed (end of spec step 3),
+ // including any force deferred syncrhonous scripts. Now resume async
+ // script execution if it was suspended by force deferral.
+ if (suspended_async_script_execution_) {
+ DCHECK(force_deferred_scripts_.IsEmpty());
+ document_->GetScriptRunner()->SetForceDeferredExecution(false);
+ suspended_async_script_execution_ = false;
+ }
return true;
}
@@ -557,6 +566,10 @@ void HTMLParserScriptRunner::RequestForceDeferredScript(
// execute when the document has finished parsing associated with the Document
// of the parser that created the element.
force_deferred_scripts_.push_back(pending_script);
+ if (!suspended_async_script_execution_) {
+ document_->GetScriptRunner()->SetForceDeferredExecution(true);
+ suspended_async_script_execution_ = true;
+ }
}
// The initial steps for 'An end tag whose tag name is "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 a3f88c0dff3..d219180da29 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
@@ -53,7 +53,7 @@ class ScriptLoader;
//
// An HTMLParserScriptRunner is owned by its host, an HTMLDocumentParser.
class HTMLParserScriptRunner final
- : public GarbageCollectedFinalized<HTMLParserScriptRunner>,
+ : public GarbageCollected<HTMLParserScriptRunner>,
public PendingScriptClient,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(HTMLParserScriptRunner);
@@ -159,6 +159,11 @@ class HTMLParserScriptRunner final
// https://html.spec.whatwg.org/C/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing
HeapDeque<Member<PendingScript>> scripts_to_execute_after_parsing_;
+ // Whether this class has suspended async script execution. This will happen
+ // when |force_deferred_scripts_| is not empty in order to let the force
+ // deferred scripts execute before any async scripts.
+ bool suspended_async_script_execution_ = false;
+
DISALLOW_COPY_AND_ASSIGN(HTMLParserScriptRunner);
};
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 7fd3c88c790..0aed827a7c7 100644
--- a/chromium/third_party/blink/renderer/core/script/import_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/import_map.cc
@@ -18,12 +18,23 @@
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+// We implement two variants of specs:
+// - When |support_builtin_modules| is false, import maps without built-in
+// module & fallback supports are implemented.
+// This follows the ToT spec https://wicg.github.io/import-maps/, which is
+// marked by <spec> tags.
+// - When |support_builtin_modules| is true, import maps with built-in module &
+// fallback supports are implemented.
+// This basically follows the spec before
+// https://github.com/WICG/import-maps/pull/176, which is marked as
+// [Spec w/ Built-in].
+// This is needed for the fallback mechanism for built-in modules, which was
+// temporarily removed from the spec but is still implemented behind the flag.
+
namespace blink {
namespace {
-static const char kStdScheme[] = "std";
-
// TODO(https://crbug.com/928549): Audit and improve error messages throughout
// this file.
@@ -47,81 +58,69 @@ void AddIgnoredValueMessage(ConsoleLogger& logger,
// href="https://wicg.github.io/import-maps/#normalize-a-specifier-key">
String NormalizeSpecifierKey(const String& key_string,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger& logger) {
// <spec step="1">If specifierKey is the empty string, then:</spec>
- //
- // TODO(hiroshige): Implement this step explicitly. Anyway currently empty
- // strings are considered as invalid by ParsedSpecifier.
+ if (key_string.IsEmpty()) {
+ // <spec step="1.1">Report a warning to the console that specifier keys
+ // cannot be the empty string.</spec>
+ AddIgnoredKeyMessage(logger, key_string,
+ "specifier keys cannot be the empty string.");
+
+ // <spec step="1.2">Return null.</spec>
+ return String();
+ }
// <spec step="2">Let url be the result of parsing a URL-like import
// specifier, given specifierKey and baseURL.</spec>
- ParsedSpecifier key = ParsedSpecifier::Create(key_string, base_url);
+ ParsedSpecifier key =
+ ParsedSpecifier::Create(key_string, base_url, support_builtin_modules);
switch (key.GetType()) {
case ParsedSpecifier::Type::kInvalid:
- // TODO(hiroshige): According to the spec, this should be considered as a
- // bare specifier.
- AddIgnoredKeyMessage(logger, key_string, "Invalid key (invalid URL)");
- return String();
-
case ParsedSpecifier::Type::kBare:
// <spec step="4">Return specifierKey.</spec>
- return key.GetImportMapKeyString();
+ return key_string;
case ParsedSpecifier::Type::kURL:
- // <spec
- // href="https://wicg.github.io/import-maps/#parse-a-url-like-import-specifier"
- // step="4">If url’s scheme is either a fetch scheme or "std", then return
- // url.</spec>
- //
- // TODO(hiroshige): Perhaps we should move this into ParsedSpecifier.
- if (!SchemeRegistry::IsFetchScheme(key.GetUrl().Protocol()) &&
- key.GetUrl().Protocol() != kStdScheme) {
- AddIgnoredKeyMessage(logger, key_string,
- "Invalid key (non-fetch scheme)");
- return String();
- }
// <spec step="3">If url is not null, then return the serialization of
// url.</spec>
return key.GetImportMapKeyString();
}
}
-// Step 3.3 of
+// Step 2.4-2.7 of
// <specdef
// href="https://wicg.github.io/import-maps/#sort-and-normalize-a-specifier-map">
KURL NormalizeValue(const String& key,
const String& value_string,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger& logger) {
- // <spec step="3.3.2">Let addressURL be the result of parsing a URL-like
- // import specifier given potentialAddress and baseURL.</spec>
- ParsedSpecifier value = ParsedSpecifier::Create(value_string, base_url);
+ // <spec step="2.4">Let addressURL be the result of parsing a URL-like import
+ // specifier given value and baseURL.</spec>
+ ParsedSpecifier value =
+ ParsedSpecifier::Create(value_string, base_url, support_builtin_modules);
switch (value.GetType()) {
case ParsedSpecifier::Type::kInvalid:
- // <spec step="3.3.3">If addressURL is null, then:</spec>
+ // <spec step="2.5">If addressURL is null, then:</spec>
//
- // <spec step="3.3.3.1">Report a warning to the console that the address
- // was invalid.</spec>
+ // <spec step="2.5.1">Report a warning to the console that the address was
+ // invalid.</spec>
AddIgnoredValueMessage(logger, key, "Invalid URL: " + value_string);
- // <spec step="3.3.1.2">Continue.</spec>
+ // <spec step="2.5.2">Continue.</spec>
return NullURL();
case ParsedSpecifier::Type::kBare:
- // TODO(hiroshige): Switch this into aliasing with std: URLs.
- if (value.GetImportMapKeyString().StartsWith("@std/"))
- return KURL("import:" + value.GetImportMapKeyString());
-
- // Do not allow bare specifiers except for @std/.
AddIgnoredValueMessage(logger, key, "Bare specifier: " + value_string);
return NullURL();
case ParsedSpecifier::Type::kURL:
- // <spec step="3.3.4">If specifierKey ends with U+002F (/), and the
+ // <spec step="2.6">If specifierKey ends with U+002F (/), and the
// serialization of addressURL does not end with U+002F (/), then:</spec>
if (key.EndsWith("/") && !value.GetUrl().GetString().EndsWith("/")) {
- // <spec step="3.3.4.1">Report a warning to the console that an invalid
+ // <spec step="2.6.1">Report a warning to the console that an invalid
// address was given for the specifier key specifierKey; since
// specifierKey ended in a slash, so must the address.</spec>
AddIgnoredValueMessage(
@@ -129,12 +128,10 @@ KURL NormalizeValue(const String& key,
"Since specifierKey ended in a slash, so must the address: " +
value_string);
- // <spec step="3.3.4.2">Continue.</spec>
+ // <spec step="2.6.2">Continue.</spec>
return NullURL();
}
- // <spec step="3.3.5">Append addressURL to
- // validNormalizedAddresses.</spec>
return value.GetUrl();
}
}
@@ -150,6 +147,7 @@ KURL NormalizeValue(const String& key,
ImportMap* ImportMap::Parse(const Modulator& modulator,
const String& input,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger& logger,
ScriptValue* error_to_rethrow) {
DCHECK(error_to_rethrow);
@@ -161,7 +159,7 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
if (!parsed) {
*error_to_rethrow =
modulator.CreateSyntaxError("Failed to parse import map: invalid JSON");
- return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
+ return MakeGarbageCollected<ImportMap>();
}
// <spec step="2">If parsed is not a map, then throw a TypeError indicating
@@ -170,7 +168,7 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
if (!parsed_map) {
*error_to_rethrow =
modulator.CreateTypeError("Failed to parse import map: not an object");
- return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
+ return MakeGarbageCollected<ImportMap>();
}
// <spec step="3">Let sortedAndNormalizedImports be an empty map.</spec>
@@ -186,25 +184,109 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
*error_to_rethrow = modulator.CreateTypeError(
"Failed to parse import map: \"imports\" "
"top-level key must be a JSON object.");
- return MakeGarbageCollected<ImportMap>(modulator, SpecifierMap());
+ return MakeGarbageCollected<ImportMap>();
}
// <spec step="4.2">Set sortedAndNormalizedImports to the result of sorting
// and normalizing a specifier map given parsed["imports"] and
// baseURL.</spec>
- sorted_and_normalized_imports =
- SortAndNormalizeSpecifierMap(imports, base_url, logger);
+ sorted_and_normalized_imports = SortAndNormalizeSpecifierMap(
+ imports, base_url, support_builtin_modules, logger);
}
- // TODO(crbug.com/927181): Process "scopes" entry (Steps 5 and 6).
+ // <spec step="5">Let sortedAndNormalizedScopes be an empty map.</spec>
+ ScopeType sorted_and_normalized_scopes;
+
+ // <spec step="6">If parsed["scopes"] exists, then:</spec>
+ if (parsed_map->Get("scopes")) {
+ // <spec step="6.1">If parsed["scopes"] is not a map, then throw a TypeError
+ // 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.");
+ return MakeGarbageCollected<ImportMap>();
+ }
+
+ // <spec step="6.2">Set sortedAndNormalizedScopes to the result of sorting
+ // and normalizing scopes given parsed["scopes"] and baseURL.</spec>
+
+ // <specdef label="sort-and-normalize-scopes"
+ // href="https://wicg.github.io/import-maps/#sort-and-normalize-scopes">
+
+ // <spec label="sort-and-normalize-scopes" step="1">Let normalized be an
+ // empty map.</spec>
+ ScopeType normalized;
+
+ // <spec label="sort-and-normalize-scopes" step="2">For each scopePrefix →
+ // potentialSpecifierMap of originalMap,</spec>
+ for (wtf_size_t i = 0; i < scopes->size(); ++i) {
+ const JSONObject::Entry& entry = scopes->at(i);
+
+ JSONObject* specifier_map = scopes->GetJSONObject(entry.first);
+ if (!specifier_map) {
+ // <spec label="sort-and-normalize-scopes" step="2.1">If
+ // 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(
+ "Failed to parse import map: the value of the scope with prefix "
+ "\"" +
+ entry.first + "\" must be a JSON object.");
+ return MakeGarbageCollected<ImportMap>();
+ }
+
+ // <spec label="sort-and-normalize-scopes" step="2.2">Let scopePrefixURL
+ // be the result of parsing scopePrefix with baseURL as the base
+ // URL.</spec>
+ const KURL prefix_url(base_url, entry.first);
+
+ // <spec label="sort-and-normalize-scopes" step="2.3">If scopePrefixURL is
+ // failure, then:</spec>
+ if (!prefix_url.IsValid()) {
+ // <spec label="sort-and-normalize-scopes" step="2.3.1">Report a warning
+ // to the console that the scope prefix URL was not parseable.</spec>
+ logger.AddConsoleMessage(
+ mojom::ConsoleMessageSource::kOther,
+ mojom::ConsoleMessageLevel::kWarning,
+ "Ignored scope \"" + entry.first + "\": not parsable as a URL.");
+
+ // <spec label="sort-and-normalize-scopes" step="2.3.2">Continue.</spec>
+ continue;
+ }
+
+ // <spec label="sort-and-normalize-scopes" step="2.5">Let
+ // normalizedScopePrefix be the serialization of scopePrefixURL.</spec>
+ //
+ // <spec label="sort-and-normalize-scopes" step="2.6">Set
+ // normalized[normalizedScopePrefix] to the result of sorting and
+ // normalizing a specifier map given potentialSpecifierMap and
+ // baseURL.</spec>
+ sorted_and_normalized_scopes.push_back(std::make_pair(
+ prefix_url.GetString(),
+ SortAndNormalizeSpecifierMap(specifier_map, base_url,
+ support_builtin_modules, logger)));
+ }
+ // <spec label="sort-and-normalize-scopes" step="3">Return the result of
+ // sorting normalized, with an entry a being less than an entry b if a’s key
+ // is longer or code unit less than b’s key.</spec>
+ std::sort(sorted_and_normalized_scopes.begin(),
+ sorted_and_normalized_scopes.end(),
+ [](const ScopeEntryType& a, const ScopeEntryType& b) {
+ return CodeUnitCompareLessThan(b.first, a.first);
+ });
+ }
// TODO(hiroshige): Implement Step 7.
// <spec step="8">Return the import map whose imports are
// sortedAndNormalizedImports and whose scopes scopes are
// sortedAndNormalizedScopes.</spec>
- return MakeGarbageCollected<ImportMap>(modulator,
- sorted_and_normalized_imports);
+ return MakeGarbageCollected<ImportMap>(
+ modulator, support_builtin_modules,
+ std::move(sorted_and_normalized_imports),
+ std::move(sorted_and_normalized_scopes));
}
// <specdef
@@ -212,19 +294,19 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
const JSONObject* imports,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger& logger) {
// <spec step="1">Let normalized be an empty map.</spec>
SpecifierMap normalized;
- // <spec step="2">First, normalize all entries so that their values are lists.
- // For each specifierKey → value of originalMap,</spec>
+ // <spec step="2">For each specifierKey → value of originalMap,</spec>
for (wtf_size_t i = 0; i < imports->size(); ++i) {
const JSONObject::Entry& entry = imports->at(i);
// <spec step="2.1">Let normalizedSpecifierKey be the result of normalizing
// a specifier key given specifierKey and baseURL.</spec>
- const String normalized_specifier_key =
- NormalizeSpecifierKey(entry.first, base_url, logger);
+ const String normalized_specifier_key = NormalizeSpecifierKey(
+ entry.first, base_url, support_builtin_modules, logger);
// <spec step="2.2">If normalizedSpecifierKey is null, then continue.</spec>
if (normalized_specifier_key.IsEmpty())
@@ -233,44 +315,67 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
Vector<KURL> values;
switch (entry.second->GetType()) {
case JSONValue::ValueType::kTypeNull:
- // <spec step="2.4">Otherwise, if value is null, then set
- // normalized[normalizedSpecifierKey] to a new empty list.</spec>
+ if (!support_builtin_modules) {
+ // <spec step="2.3">If value is not a string, then:</spec>
+ //
+ // <spec step="2.3.1">Report a warning to the console that addresses
+ // must be strings.</spec>
+ AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
+
+ // <spec step="2.3.2">Continue.</spec>
+ continue;
+ }
+ // [Spec w/ Built-in] Otherwise, if value is null, then set
+ // normalized[normalizedSpecifierKey] to a new empty list.
break;
case JSONValue::ValueType::kTypeBoolean:
case JSONValue::ValueType::kTypeInteger:
case JSONValue::ValueType::kTypeDouble:
case JSONValue::ValueType::kTypeObject:
- // <spec step="2.6">Otherwise, report a warning to the console that
- // addresses must be strings, arrays, or null.</spec>
+ // <spec step="2.3">If value is not a string, then:</spec>
+ //
+ // <spec step="2.3.1">Report a warning to the console that addresses
+ // must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
+ // <spec step="2.3.2">Continue.</spec>
+ //
// By continuing here, we leave |normalized[normalized_specifier_key]|
// unset, and continue processing.
continue;
case JSONValue::ValueType::kTypeString: {
- // <spec step="2.3">If value is a string, then set
- // normalized[normalizedSpecifierKey] to «value».</spec>
+ // Steps 2.4-2.6 are implemented in NormalizeValue().
String value_string;
if (!imports->GetString(entry.first, &value_string)) {
AddIgnoredValueMessage(logger, entry.first,
"Internal error in GetString().");
break;
}
- KURL value =
- NormalizeValue(entry.first, value_string, base_url, logger);
+ KURL value = NormalizeValue(entry.first, value_string, base_url,
+ support_builtin_modules, logger);
- // <spec step="3.3.5">Append addressURL to
- // validNormalizedAddresses.</spec>
+ // <spec step="2.7">Set normalized[specifierKey] to addressURL.</spec>
if (value.IsValid())
values.push_back(value);
break;
}
case JSONValue::ValueType::kTypeArray: {
- // <spec step="2.5">Otherwise, if value is a list, then set
- // normalized[normalizedSpecifierKey] to value.</spec>
+ if (!support_builtin_modules) {
+ // <spec step="2.3">If value is not a string, then:</spec>
+ //
+ // <spec step="2.3.1">Report a warning to the console that addresses
+ // must be strings.</spec>
+ AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
+
+ // <spec step="2.3.2">Continue.</spec>
+ continue;
+ }
+
+ // [Spec w/ Built-in] Otherwise, if value is a list, then set
+ // normalized[normalizedSpecifierKey] to value.
JSONArray* array = imports->GetArray(entry.first);
if (!array) {
AddIgnoredValueMessage(logger, entry.first,
@@ -278,25 +383,21 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
break;
}
- // <spec step="3.3">For each potentialAddress of
- // potentialAddresses,</spec>
+ // <spec step="2">For each specifierKey → value of ...</spec>
for (wtf_size_t j = 0; j < array->size(); ++j) {
- // <spec step="3.3.1">If potentialAddress is not a string,
- // then:</spec>
+ // <spec step="2.3">If value is not a string, then:</spec>
String value_string;
if (!array->at(j)->AsString(&value_string)) {
- // <spec step="3.3.1.1">Report a warning to the console that the
- // contents of address arrays must be strings.</spec>
+ // <spec step="2.3.1">Report a warning to the console that addresses
+ // must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first,
"Non-string in the value.");
- // <spec step="3.3.1.2">Continue.</spec>
+ // <spec step="2.3.2">Continue.</spec>
continue;
}
- KURL value =
- NormalizeValue(entry.first, value_string, base_url, logger);
+ KURL value = NormalizeValue(entry.first, value_string, base_url,
+ support_builtin_modules, logger);
- // <spec step="3.3.5">Append addressURL to
- // validNormalizedAddresses.</spec>
if (value.IsValid())
values.push_back(value);
}
@@ -304,6 +405,10 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
}
}
+ if (!support_builtin_modules) {
+ DCHECK_LE(values.size(), 1u);
+ }
+
// TODO(hiroshige): Move these checks to resolution time.
if (values.size() > 2) {
AddIgnoredValueMessage(logger, entry.first,
@@ -323,8 +428,7 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
}
}
- // <spec step="3.4">Set normalized[specifierKey] to
- // validNormalizedAddresses.</spec>
+ // <spec step="2.7">Set normalized[specifierKey] to addressURL.</spec>
normalized.Set(normalized_specifier_key, values);
}
@@ -333,7 +437,8 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
// <specdef href="https://wicg.github.io/import-maps/#resolve-an-imports-match">
base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix(
- const ParsedSpecifier& parsed_specifier) const {
+ const ParsedSpecifier& parsed_specifier,
+ const SpecifierMap& specifier_map) const {
// Do not perform prefix match for non-bare specifiers.
if (parsed_specifier.GetType() != ParsedSpecifier::Type::kBare)
return base::nullopt;
@@ -352,8 +457,8 @@ base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix(
// https://github.com/WICG/import-maps/issues/102
base::Optional<MatchResult> best_match;
- // <spec step="1">For each specifierKey → addresses of specifierMap,</spec>
- for (auto it = imports_.begin(); it != imports_.end(); ++it) {
+ // <spec step="1">For each specifierKey → address of specifierMap,</spec>
+ for (auto it = specifier_map.begin(); it != specifier_map.end(); ++it) {
// <spec step="1.2">If specifierKey ends with U+002F (/) and
// normalizedSpecifier starts with specifierKey, then:</spec>
if (!it->key.EndsWith('/'))
@@ -373,26 +478,70 @@ base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix(
return best_match;
}
+ImportMap::ImportMap()
+ : support_builtin_modules_(false),
+ modulator_for_built_in_modules_(nullptr) {}
+
ImportMap::ImportMap(const Modulator& modulator_for_built_in_modules,
- const HashMap<String, Vector<KURL>>& imports)
- : imports_(imports),
+ bool support_builtin_modules,
+ SpecifierMap&& imports,
+ ScopeType&& scopes)
+ : imports_(std::move(imports)),
+ scopes_(std::move(scopes)),
+ support_builtin_modules_(support_builtin_modules),
modulator_for_built_in_modules_(&modulator_for_built_in_modules) {}
+// <specdef
+// href="https://wicg.github.io/import-maps/#resolve-a-module-specifier">
+base::Optional<KURL> ImportMap::Resolve(const ParsedSpecifier& parsed_specifier,
+ const KURL& base_url,
+ String* debug_message) const {
+ DCHECK(debug_message);
+
+ // <spec step="8">For each scopePrefix → scopeImports of importMap’s
+ // scopes,</spec>
+ for (const auto& entry : scopes_) {
+ // <spec step="8.1">If scopePrefix is baseURLString, or if scopePrefix ends
+ // with U+002F (/) and baseURLString starts with scopePrefix, then:</spec>
+ if (entry.first == base_url.GetString() ||
+ (entry.first.EndsWith("/") &&
+ base_url.GetString().StartsWith(entry.first))) {
+ // <spec step="8.1.1">Let scopeImportsMatch be the result of resolving an
+ // imports match given normalizedSpecifier and scopeImports.</spec>
+ base::Optional<KURL> scope_match =
+ ResolveImportsMatch(parsed_specifier, entry.second, debug_message);
+
+ // <spec step="8.1.2">If scopeImportsMatch is not null, then return
+ // scopeImportsMatch.</spec>
+ if (scope_match)
+ return scope_match;
+ }
+ }
+
+ // <spec step="9">Let topLevelImportsMatch be the result of resolving an
+ // imports match given normalizedSpecifier and importMap’s imports.</spec>
+ //
+ // <spec step="10">If topLevelImportsMatch is not null, then return
+ // topLevelImportsMatch.</spec>
+ return ResolveImportsMatch(parsed_specifier, imports_, debug_message);
+}
+
// <specdef href="https://wicg.github.io/import-maps/#resolve-an-imports-match">
base::Optional<KURL> ImportMap::ResolveImportsMatch(
const ParsedSpecifier& parsed_specifier,
+ const SpecifierMap& specifier_map,
String* debug_message) const {
DCHECK(debug_message);
const String key = parsed_specifier.GetImportMapKeyString();
- // <spec step="1.1">If specifierKey is normalizedSpecifier, then:</spec>
- MatchResult exact = imports_.find(key);
- if (exact != imports_.end()) {
+ // <spec step="1.1">If specifierKey is normalizedSpecifier, then ...</spec>
+ MatchResult exact = specifier_map.find(key);
+ if (exact != specifier_map.end()) {
return ResolveImportsMatchInternal(key, exact, debug_message);
}
// Step 1.2.
- if (auto prefix_match = MatchPrefix(parsed_specifier)) {
+ if (auto prefix_match = MatchPrefix(parsed_specifier, specifier_map)) {
return ResolveImportsMatchInternal(key, *prefix_match, debug_message);
}
@@ -407,77 +556,100 @@ base::Optional<KURL> ImportMap::ResolveImportsMatchInternal(
const String& key,
const MatchResult& matched,
String* debug_message) const {
- // <spec step="1.2.2.1">Let afterPrefix be the portion of normalizedSpecifier
- // after the initial specifierKey prefix.</spec>
- //
- // <spec step="1.2.3.1">Let afterPrefix be the portion of normalizedSpecifier
+ // <spec step="1.2.1">Let afterPrefix be the portion of normalizedSpecifier
// after the initial specifierKey prefix.</spec>
const String after_prefix = key.Substring(matched->key.length());
- // <spec step="1.1.3">If addresses’s size is 2, and addresses[0]'s scheme is
- // "std", and addresses[1]'s scheme is not "std", then:</spec>
- //
- // <spec step="1.2.3">If addresses’s size is 2, and addresses[0]'s scheme is
- // "std", and addresses[1]'s scheme is not "std", then:</spec>
- //
- // TODO(hiroshige): Add these checks here. Currently they are checked at
- // parsing.
-
for (const KURL& value : matched->value) {
- // <spec step="1.2.2.3">Let url be the result of parsing the concatenation
- // of the serialization of addresses[0] with afterPrefix.</spec>
+ // <spec step="1.1">If specifierKey is normalizedSpecifier, then return
+ // address.</spec>
//
- // <spec step="1.2.3.3">Let url0 be the result of parsing the concatenation
- // of the serialization of addresses[0] with afterPrefix; similarly, let
- // url1 be the result of parsing the concatenation of the serialization of
- // addresses[1] with afterPrefix.</spec>
+ // <spec step="1.2">If specifierKey ends with U+002F (/) and
+ // normalizedSpecifier starts with specifierKey, then:</spec>
//
- // TODO(hiroshige): Update this according to the spec.
+ // <spec step="1.2.3">Let url be the result of parsing afterPrefix relative
+ // to the base URL address.</spec>
const KURL url = after_prefix.IsEmpty() ? value : KURL(value, after_prefix);
- // <spec step="1.2.3.5">Return url0, if moduleMap[url0] exists; otherwise,
- // return url1.</spec>
+ // [Spec w/ Built-in] Return url0, if moduleMap[url0] exists; otherwise,
+ // return url1.
//
// Note: Here we filter out non-existing built-in modules in all cases.
- if (layered_api::ResolveFetchingURL(*modulator_for_built_in_modules_, url)
+ if (!support_builtin_modules_ ||
+ layered_api::ResolveFetchingURL(*modulator_for_built_in_modules_, url)
.IsValid()) {
*debug_message = "Import Map: \"" + key + "\" matches with \"" +
matched->key + "\" and is mapped to " +
url.ElidedString();
+
+ // <spec step="1.2.4">If url is failure, then return null.</spec>
+ //
+ // <spec step="1.2.5">Return url.</spec>
return url;
}
}
- // <spec step="1.1.1">If addresses’s size is 0, then throw a TypeError
- // indicating that normalizedSpecifier was mapped to no addresses.</spec>
+ // [Spec w/ Built-in] If addresses’s size is 0, then throw a TypeError
+ // indicating that normalizedSpecifier was mapped to no addresses.
*debug_message = "Import Map: \"" + key + "\" matches with \"" +
matched->key + "\" but fails to be mapped (no viable URLs)";
return NullURL();
}
-String ImportMap::ToString() const {
- StringBuilder builder;
+static void SpecifierMapToString(StringBuilder& builder,
+ bool support_builtin_modules,
+ const ImportMap::SpecifierMap& specifier_map) {
builder.Append("{");
bool is_first_key = true;
- for (const auto& it : imports_) {
+ for (const auto& it : specifier_map) {
if (!is_first_key)
builder.Append(",");
is_first_key = false;
- builder.Append("\n \"");
- builder.Append(it.key);
- builder.Append("\": [");
- bool is_first_value = true;
- for (const auto& v : it.value) {
- if (!is_first_value)
- builder.Append(",");
- is_first_value = false;
- builder.Append("\n \"");
- builder.Append(v.GetString());
- builder.Append("\"");
+ builder.Append(it.key.EncodeForDebugging());
+ builder.Append(":");
+ if (support_builtin_modules) {
+ builder.Append("[");
+ bool is_first_value = true;
+ for (const auto& v : it.value) {
+ if (!is_first_value)
+ builder.Append(",");
+ is_first_value = false;
+ builder.Append(v.GetString().EncodeForDebugging());
+ }
+ builder.Append("]");
+ } else {
+ if (it.value.size() == 0) {
+ builder.Append("[]");
+ } else {
+ DCHECK_EQ(it.value.size(), 1u);
+ builder.Append(it.value[0].GetString().EncodeForDebugging());
+ }
}
- builder.Append("\n ]");
}
- builder.Append("\n}\n");
+ builder.Append("}");
+}
+
+String ImportMap::ToString() const {
+ StringBuilder builder;
+ builder.Append("{\"imports\":");
+ SpecifierMapToString(builder, support_builtin_modules_, imports_);
+
+ builder.Append(",\"scopes\":{");
+
+ bool is_first_scope = true;
+ for (const auto& entry : scopes_) {
+ if (!is_first_scope)
+ builder.Append(",");
+ is_first_scope = false;
+ builder.Append(entry.first.EncodeForDebugging());
+ builder.Append(":");
+ SpecifierMapToString(builder, support_builtin_modules_, entry.second);
+ }
+
+ builder.Append("}");
+
+ builder.Append("}");
+
return builder.ToString();
}
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 240a2a3c5d1..cc38cf9c3e5 100644
--- a/chromium/third_party/blink/renderer/core/script/import_map.h
+++ b/chromium/third_party/blink/renderer/core/script/import_map.h
@@ -23,29 +23,15 @@ 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 GarbageCollectedFinalized<ImportMap> {
+class CORE_EXPORT ImportMap final : public GarbageCollected<ImportMap> {
public:
static ImportMap* Parse(const Modulator&,
const String& text,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger& logger,
ScriptValue* error_to_rethrow);
- ImportMap(const Modulator&, const HashMap<String, Vector<KURL>>& imports);
-
- // https://wicg.github.io/import-maps/#resolve-an-imports-match
- // Returns nullopt when not mapped by |this| import map (i.e. the import map
- // doesn't have corresponding keys).
- // Returns a null URL when resolution fails.
- base::Optional<KURL> ResolveImportsMatch(const ParsedSpecifier&,
- String* debug_message) const;
-
- String ToString() const;
-
- void Trace(Visitor*);
-
- private:
// <spec href="https://wicg.github.io/import-maps/#specifier-map">A specifier
// map is an ordered map from strings to lists of URLs.</spec>
//
@@ -53,11 +39,42 @@ class CORE_EXPORT ImportMap final
// are implemented differently from the spec.
using SpecifierMap = HashMap<String, Vector<KURL>>;
+ // <spec href="https://wicg.github.io/import-maps/#import-map-scopes">an
+ // ordered map of URLs to specifier maps.</spec>
+ using ScopeEntryType = std::pair<String, SpecifierMap>;
+ using ScopeType = Vector<ScopeEntryType>;
+
+ // Empty import map.
+ ImportMap();
+
+ ImportMap(const Modulator&,
+ bool support_builtin_modules,
+ SpecifierMap&& imports,
+ ScopeType&& scopes);
+
+ base::Optional<KURL> Resolve(const ParsedSpecifier&,
+ const KURL& base_url,
+ String* debug_message) const;
+
+ String ToString() const;
+
+ void Trace(Visitor*);
+
+ private:
using MatchResult = SpecifierMap::const_iterator;
- base::Optional<MatchResult> MatchPrefix(const ParsedSpecifier&) const;
+ // https://wicg.github.io/import-maps/#resolve-an-imports-match
+ // Returns nullopt when not mapped by |this| import map (i.e. the import map
+ // doesn't have corresponding keys).
+ // Returns a null URL when resolution fails.
+ base::Optional<KURL> ResolveImportsMatch(const ParsedSpecifier&,
+ const SpecifierMap&,
+ String* debug_message) const;
+ base::Optional<MatchResult> MatchPrefix(const ParsedSpecifier&,
+ const SpecifierMap&) const;
static SpecifierMap SortAndNormalizeSpecifierMap(const JSONObject* imports,
const KURL& base_url,
+ bool support_builtin_modules,
ConsoleLogger&);
base::Optional<KURL> ResolveImportsMatchInternal(
@@ -68,8 +85,10 @@ class CORE_EXPORT ImportMap final
// https://wicg.github.io/import-maps/#import-map-imports
SpecifierMap imports_;
- // TODO(crbug.com/927181): Implement
// https://wicg.github.io/import-maps/#import-map-scopes.
+ ScopeType scopes_;
+
+ const bool support_builtin_modules_;
Member<const Modulator> modulator_for_built_in_modules_;
};
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 b343b30e96c..5341b21cbc5 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
@@ -67,7 +67,7 @@ JSModuleScript* JSModuleScript::Create(
// <spec step="8.1">Set script's parse error to result[0].</spec>
v8::Local<v8::Value> error = exception_state.GetException();
exception_state.ClearException();
- script->SetParseErrorAndClearRecord(ScriptValue(script_state, error));
+ script->SetParseErrorAndClearRecord(ScriptValue(isolate, error));
// <spec step="8.2">Return script.</spec>
return script;
@@ -93,7 +93,7 @@ JSModuleScript* JSModuleScript::Create(
V8ThrowException::CreateTypeError(isolate, error_message);
// <spec step="9.2.2">Set script's parse error to error.</spec>
- script->SetParseErrorAndClearRecord(ScriptValue(script_state, error));
+ script->SetParseErrorAndClearRecord(ScriptValue(isolate, error));
// <spec step="9.2.3">Return script.</spec>
return script;
diff --git a/chromium/third_party/blink/renderer/core/script/layered_api.cc b/chromium/third_party/blink/renderer/core/script/layered_api.cc
index 04930def42f..6e999dd7008 100644
--- a/chromium/third_party/blink/renderer/core/script/layered_api.cc
+++ b/chromium/third_party/blink/renderer/core/script/layered_api.cc
@@ -19,10 +19,6 @@ namespace {
static const char kStdScheme[] = "std";
static const char kInternalScheme[] = "std-internal";
-static const char kImportScheme[] = "import";
-
-constexpr char kBuiltinSpecifierPrefix[] = "@std/";
-
constexpr char kTopLevelScriptPostfix[] = "/index.mjs";
const LayeredAPIResource* GetResourceFromPath(const Modulator& modulator,
@@ -46,10 +42,6 @@ String GetBuiltinPath(const KURL& url) {
if (url.ProtocolIs(kStdScheme))
return url.GetPath();
- const StringView prefix(kBuiltinSpecifierPrefix);
- if (url.ProtocolIs(kImportScheme) && url.GetPath().StartsWith(prefix))
- return url.GetPath().Substring(prefix.length());
-
return String();
}
@@ -57,8 +49,6 @@ String GetBuiltinPath(const KURL& url) {
KURL ResolveFetchingURL(const Modulator& modulator, const KURL& url) {
// <spec step="1">If url's scheme is not "std", return url.</spec>
// <spec step="2">Let path be url's path[0].</spec>
- // Note: Also accepts "import:@std/x".
- // See the comment at GetBuiltinPath() declaration.
String path = GetBuiltinPath(url);
if (path.IsNull())
return url;
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 2722f3a7971..0bd11bbb020 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
@@ -12,9 +12,8 @@
namespace blink {
-class MockScriptElementBase
- : public GarbageCollectedFinalized<MockScriptElementBase>,
- public ScriptElementBase {
+class MockScriptElementBase : public GarbageCollected<MockScriptElementBase>,
+ public ScriptElementBase {
USING_GARBAGE_COLLECTED_MIXIN(MockScriptElementBase);
public:
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.h b/chromium/third_party/blink/renderer/core/script/modulator.h
index e9d4f06d680..39b6255073c 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULATOR_H_
#include "base/single_thread_task_runner.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/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/module_record.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
@@ -40,7 +40,7 @@ class ScriptValue;
// module tree graph) load is complete and its corresponding entry is created in
// module map.
class CORE_EXPORT SingleModuleClient
- : public GarbageCollectedFinalized<SingleModuleClient>,
+ : public GarbageCollected<SingleModuleClient>,
public NameClient {
public:
virtual ~SingleModuleClient() = default;
@@ -54,9 +54,8 @@ class CORE_EXPORT SingleModuleClient
// A ModuleTreeClient is notified when a module script and its whole descendent
// tree load is complete.
-class CORE_EXPORT ModuleTreeClient
- : public GarbageCollectedFinalized<ModuleTreeClient>,
- public NameClient {
+class CORE_EXPORT ModuleTreeClient : public GarbageCollected<ModuleTreeClient>,
+ public NameClient {
public:
virtual ~ModuleTreeClient() = default;
virtual void Trace(Visitor* visitor) {}
@@ -95,7 +94,7 @@ enum class ModuleScriptCustomFetchType {
// https://html.spec.whatwg.org/C/#environment-settings-object
//
// A Modulator also serves as an entry point for various module spec algorithms.
-class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
+class CORE_EXPORT Modulator : public GarbageCollected<Modulator>,
public V8PerContextData::Data,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(Modulator);
@@ -121,6 +120,7 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
// "scripting is disabled for settings's responsible browsing context"
virtual bool IsScriptingDisabled() const = 0;
+ virtual bool ImportMapsEnabled() const = 0;
virtual bool BuiltInModuleInfraEnabled() const = 0;
virtual bool BuiltInModuleEnabled(layered_api::Module) const = 0;
virtual void BuiltInModuleUseCount(layered_api::Module) 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 cfc3cca29c6..b32a3eeb9ab 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
@@ -49,6 +49,10 @@ bool ModulatorImplBase::IsScriptingDisabled() const {
return !GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript);
}
+bool ModulatorImplBase::ImportMapsEnabled() const {
+ return RuntimeEnabledFeatures::ImportMapsEnabled(GetExecutionContext());
+}
+
bool ModulatorImplBase::BuiltInModuleInfraEnabled() const {
return RuntimeEnabledFeatures::BuiltInModuleInfraEnabled(
GetExecutionContext());
@@ -170,7 +174,7 @@ KURL ModulatorImplBase::ResolveModuleSpecifier(const String& specifier,
const KURL& base_url,
String* failure_reason) {
ParsedSpecifier parsed_specifier =
- ParsedSpecifier::Create(specifier, base_url);
+ ParsedSpecifier::Create(specifier, base_url, BuiltInModuleInfraEnabled());
if (!parsed_specifier.IsValid()) {
if (failure_reason) {
@@ -188,8 +192,8 @@ KURL ModulatorImplBase::ResolveModuleSpecifier(const String& specifier,
base::Optional<KURL> mapped_url;
if (import_map_) {
String import_map_debug_message;
- mapped_url = import_map_->ResolveImportsMatch(parsed_specifier,
- &import_map_debug_message);
+ mapped_url = import_map_->Resolve(parsed_specifier, base_url,
+ &import_map_debug_message);
// Output the resolution log. This is too verbose to be always shown, but
// will be helpful for Web developers (and also Chromium developers) for
@@ -217,13 +221,6 @@ KURL ModulatorImplBase::ResolveModuleSpecifier(const String& specifier,
return KURL();
case ParsedSpecifier::Type::kBare:
- // Allow |@std/x| specifiers if Layered API is enabled.
- if (BuiltInModuleInfraEnabled()) {
- if (parsed_specifier.GetImportMapKeyString().StartsWith("@std/")) {
- return KURL("import:" + parsed_specifier.GetImportMapKeyString());
- }
- }
-
// Reject bare specifiers as specced by the pre-ImportMap spec.
if (failure_reason) {
*failure_reason =
@@ -239,15 +236,17 @@ KURL ModulatorImplBase::ResolveModuleSpecifier(const String& specifier,
ScriptValue ModulatorImplBase::CreateTypeError(const String& message) const {
ScriptState::Scope scope(script_state_);
- ScriptValue error(script_state_, V8ThrowException::CreateTypeError(
- script_state_->GetIsolate(), message));
+ 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_, V8ThrowException::CreateSyntaxError(
- script_state_->GetIsolate(), message));
+ ScriptValue error(script_state_->GetIsolate(),
+ V8ThrowException::CreateSyntaxError(
+ script_state_->GetIsolate(), message));
return error;
}
@@ -255,7 +254,7 @@ ScriptValue ModulatorImplBase::CreateSyntaxError(const String& message) const {
void ModulatorImplBase::RegisterImportMap(const ImportMap* import_map,
ScriptValue error_to_rethrow) {
DCHECK(import_map);
- DCHECK(BuiltInModuleInfraEnabled());
+ DCHECK(ImportMapsEnabled());
// <spec step="7">If import map parse result’s error to rethrow is not null,
// then:</spec>
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 4f21e19afda..ce0267f4b81 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
@@ -41,6 +41,7 @@ class ModulatorImplBase : public Modulator {
bool IsScriptingDisabled() const override;
+ bool ImportMapsEnabled() const override;
bool BuiltInModuleInfraEnabled() const override;
bool BuiltInModuleEnabled(layered_api::Module) const override;
void BuiltInModuleUseCount(layered_api::Module) const override;
diff --git a/chromium/third_party/blink/renderer/core/script/module_map.cc b/chromium/third_party/blink/renderer/core/script/module_map.cc
index d38ecfd0038..4a984faacf5 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_map.cc
@@ -16,7 +16,7 @@ namespace blink {
// Entry struct represents a value in "module map" spec object.
// https://html.spec.whatwg.org/C/#module-map
-class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>,
+class ModuleMap::Entry final : public GarbageCollected<Entry>,
public NameClient,
public ModuleScriptLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ModuleMap::Entry);
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 479c0ac1e57..09c772807ed 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
@@ -103,7 +103,7 @@ class ModuleMapTestModulator final : public DummyModulator {
ScriptState* GetScriptState() override { return script_state_; }
class TestModuleScriptFetcher final
- : public GarbageCollectedFinalized<TestModuleScriptFetcher>,
+ : public GarbageCollected<TestModuleScriptFetcher>,
public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(TestModuleScriptFetcher);
@@ -148,7 +148,7 @@ class ModuleMapTestModulator final : public DummyModulator {
return Thread::Current()->GetTaskRunner().get();
}
- struct TestRequest final : public GarbageCollectedFinalized<TestRequest> {
+ struct TestRequest final : public GarbageCollected<TestRequest> {
TestRequest(const ModuleScriptCreationParams& params,
ModuleScriptFetcher::Client* client)
: params_(params), client_(client) {}
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver.h b/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
index 8833c5500f7..cf07f65dfd1 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver.h
@@ -23,7 +23,7 @@ class ModuleScript;
// ModuleRecordResolver, given a referrer and specifier, can look up the
// descendant.
class CORE_EXPORT ModuleRecordResolver
- : public GarbageCollectedFinalized<ModuleRecordResolver> {
+ : public GarbageCollected<ModuleRecordResolver> {
public:
virtual ~ModuleRecordResolver() = default;
virtual void Trace(Visitor* visitor) {}
diff --git a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
index 10070f04988..c1a021cda4a 100644
--- a/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/module_record_resolver_impl.h
@@ -51,8 +51,6 @@ class CORE_EXPORT ModuleRecordResolverImpl final
// Implements ContextLifecycleObserver:
void ContextDestroyed(ExecutionContext*) final;
- v8::Local<v8::Module> GetBoxedV8ModuleFromModuleScript(const ModuleScript*);
-
// Corresponds to the spec concept "referencingModule.[[HostDefined]]".
// crbug.com/725816 : ModuleRecord contains strong ref to v8::Module thus we
// should not use ModuleRecord as the map key. We currently rely on Detach()
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 2b1c7ca1e4f..21cfd612c98 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
@@ -97,7 +97,7 @@ ModuleScript* CreateTargetModuleScript(Modulator* modulator,
v8::Local<v8::Value> error =
V8ThrowException::CreateError(scope.GetIsolate(), "hoge");
module_script->SetParseErrorAndClearRecord(
- ScriptValue(scope.GetScriptState(), error));
+ ScriptValue(scope.GetIsolate(), error));
}
return module_script;
}
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 b742a278358..2da6b2d4965 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script.cc
@@ -50,27 +50,29 @@ void ModuleScript::SetParseErrorAndClearRecord(ScriptValue error) {
DCHECK(!error.IsEmpty());
record_.Clear();
- parse_error_.Set(error.GetIsolate(), error.V8Value());
+ parse_error_.Set(settings_object_->GetScriptState()->GetIsolate(),
+ error.V8Value());
}
ScriptValue ModuleScript::CreateParseError() const {
ScriptState* script_state = settings_object_->GetScriptState();
- v8::Isolate* isolate = script_state->GetIsolate();
ScriptState::Scope scope(script_state);
- ScriptValue error(script_state, parse_error_.NewLocal(isolate));
+ ScriptValue error(script_state->GetIsolate(), parse_error_.Get(script_state));
DCHECK(!error.IsEmpty());
return error;
}
void ModuleScript::SetErrorToRethrow(ScriptValue error) {
- error_to_rethrow_.Set(error.GetIsolate(), error.V8Value());
+ ScriptState* script_state = settings_object_->GetScriptState();
+ ScriptState::Scope scope(script_state);
+ error_to_rethrow_.Set(script_state->GetIsolate(), error.V8Value());
}
ScriptValue ModuleScript::CreateErrorToRethrow() const {
ScriptState* script_state = settings_object_->GetScriptState();
- v8::Isolate* isolate = script_state->GetIsolate();
ScriptState::Scope scope(script_state);
- ScriptValue error(script_state, error_to_rethrow_.NewLocal(isolate));
+ ScriptValue error(script_state->GetIsolate(),
+ error_to_rethrow_.Get(script_state));
DCHECK(!error.IsEmpty());
return error;
}
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 b949655a554..aabe3a6cb27 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_script.h
@@ -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/bindings/core/v8/world_safe_v8_reference.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/script.h"
@@ -115,10 +116,10 @@ class CORE_EXPORT ModuleScript : public Script {
// https://github.com/whatwg/html/pull/2991. This shouldn't cause any
// observable functional changes, and updating the classic script handling
// will require moderate code changes (e.g. to move compilation timing).
- TraceWrapperV8Reference<v8::Value> parse_error_;
+ WorldSafeV8Reference<v8::Value> parse_error_;
// https://html.spec.whatwg.org/C/#concept-script-error-to-rethrow
- TraceWrapperV8Reference<v8::Value> error_to_rethrow_;
+ WorldSafeV8Reference<v8::Value> error_to_rethrow_;
mutable HashMap<String, KURL> specifier_to_url_cache_;
KURL source_url_;
diff --git a/chromium/third_party/blink/renderer/core/script/parsed_specifier.cc b/chromium/third_party/blink/renderer/core/script/parsed_specifier.cc
index 5c25f66d8ae..81867f536d8 100644
--- a/chromium/third_party/blink/renderer/core/script/parsed_specifier.cc
+++ b/chromium/third_party/blink/renderer/core/script/parsed_specifier.cc
@@ -4,8 +4,18 @@
#include "third_party/blink/renderer/core/script/parsed_specifier.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+
namespace blink {
+namespace {
+
+static const char kStdScheme[] = "std";
+
+constexpr char kBuiltinSpecifierPrefix[] = "@std/";
+
+} // namespace
+
// <specdef href="https://html.spec.whatwg.org/#resolve-a-module-specifier">
// <specdef label="import-specifier"
// href="https://wicg.github.io/import-maps/#parse-a-url-like-import-specifier">
@@ -14,7 +24,22 @@ namespace blink {
// handle kBare cases properly, depending on contexts and whether import maps
// are enabled.
ParsedSpecifier ParsedSpecifier::Create(const String& specifier,
- const KURL& base_url) {
+ const KURL& base_url,
+ bool support_builtin_modules) {
+ if (support_builtin_modules) {
+ // Not spec'ed: we support @std/foo specifiers as an alias of std:foo.
+ const StringView prefix(kBuiltinSpecifierPrefix);
+ if (specifier.StartsWith(prefix)) {
+ StringBuilder url_string;
+ url_string.Append(kStdScheme);
+ url_string.Append(":");
+ url_string.Append(specifier.Substring(prefix.length()));
+ KURL url(NullURL(), url_string.ToString());
+ if (url.IsValid())
+ return ParsedSpecifier(url);
+ }
+ }
+
// <spec step="1">Apply the URL parser to specifier. If the result is not
// failure, return the result.</spec>
//
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..8225af4a91d 100644
--- a/chromium/third_party/blink/renderer/core/script/parsed_specifier.h
+++ b/chromium/third_party/blink/renderer/core/script/parsed_specifier.h
@@ -37,7 +37,9 @@ class ParsedSpecifier final {
// https://html.spec.whatwg.org/#resolve-a-module-specifier
// but doesn't reject bare specifiers, which should be rejected by callers
// if needed.
- static ParsedSpecifier Create(const String& specifier, const KURL& base_url);
+ static ParsedSpecifier Create(const String& specifier,
+ const KURL& base_url,
+ bool support_builtin_modules);
enum class Type { kInvalid, kBare, kURL };
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 5e762238a14..0d443f9b8f8 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,18 +18,21 @@ PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element,
const KURL& base_url) {
Document& element_document = element.GetDocument();
Document* context_document = element_document.ContextDocument();
- Modulator* modulator =
- Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
+ ScriptState* script_state =
+ ToScriptStateForMainWorld(context_document->GetFrame());
+ Modulator* modulator = Modulator::From(script_state);
ScriptValue error_to_rethrow;
ImportMap* import_map =
- ImportMap::Parse(*modulator, import_map_text, base_url, *context_document,
- &error_to_rethrow);
+ ImportMap::Parse(*modulator, import_map_text, base_url,
+ modulator->BuiltInModuleInfraEnabled(),
+ *context_document, &error_to_rethrow);
return MakeGarbageCollected<PendingImportMap>(
- element, import_map, error_to_rethrow, *context_document);
+ script_state, element, import_map, error_to_rethrow, *context_document);
}
-PendingImportMap::PendingImportMap(ScriptElementBase& element,
+PendingImportMap::PendingImportMap(ScriptState* script_state,
+ ScriptElementBase& element,
ImportMap* import_map,
ScriptValue error_to_rethrow,
const Document& original_context_document)
@@ -37,8 +40,8 @@ PendingImportMap::PendingImportMap(ScriptElementBase& element,
import_map_(import_map),
original_context_document_(&original_context_document) {
if (!error_to_rethrow.IsEmpty()) {
- ScriptState::Scope scope(error_to_rethrow.GetScriptState());
- error_to_rethrow_.Set(error_to_rethrow.GetIsolate(),
+ ScriptState::Scope scope(script_state);
+ error_to_rethrow_.Set(script_state->GetIsolate(),
error_to_rethrow.V8Value());
}
}
@@ -85,8 +88,11 @@ void PendingImportMap::RegisterImportMap() const {
ScriptState* script_state = modulator->GetScriptState();
ScriptState::Scope scope(script_state);
- ScriptValue error(script_state,
- error_to_rethrow_.NewLocal(script_state->GetIsolate()));
+ ScriptValue error;
+ if (!error_to_rethrow_.IsEmpty()) {
+ error = ScriptValue(script_state->GetIsolate(),
+ error_to_rethrow_.Get(script_state));
+ }
modulator->RegisterImportMap(import_map_, error);
// <spec step="9">If element is from an external file, then fire an event
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 3344fec9511..f4005bad221 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
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_IMPORT_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_IMPORT_MAP_H_
+#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/platform/bindings/trace_wrapper_v8_reference.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"
@@ -32,7 +32,7 @@ class ScriptValue;
// Note: Currently we only support inline import maps and PendingImportMap is
// always ready.
class CORE_EXPORT PendingImportMap final
- : public GarbageCollectedFinalized<PendingImportMap> {
+ : public GarbageCollected<PendingImportMap> {
public:
// https://wicg.github.io/import-maps/#create-an-import-map-parse-result
// for inline import maps.
@@ -40,7 +40,8 @@ class CORE_EXPORT PendingImportMap final
const String& import_map_text,
const KURL& base_url);
- PendingImportMap(ScriptElementBase&,
+ PendingImportMap(ScriptState* script_state,
+ ScriptElementBase&,
ImportMap*,
ScriptValue error_to_rethrow,
const Document& original_context_document);
@@ -57,7 +58,7 @@ class CORE_EXPORT PendingImportMap final
// 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.
- TraceWrapperV8Reference<v8::Value> error_to_rethrow_;
+ WorldSafeV8Reference<v8::Value> error_to_rethrow_;
// https://wicg.github.io/import-maps/#import-map-parse-result-settings-object
// The context document at the time when PrepareScript() is executed.
diff --git a/chromium/third_party/blink/renderer/core/script/pending_script.cc b/chromium/third_party/blink/renderer/core/script/pending_script.cc
index 5fefbfc1927..77275af086e 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.cc
@@ -59,6 +59,7 @@ PendingScript::PendingScript(ScriptElementBase* element,
starting_position_(starting_position),
virtual_time_pauser_(CreateWebScopedVirtualTimePauser(element)),
client_(nullptr),
+ original_element_document_(&element->GetDocument()),
original_context_document_(element->GetDocument().ContextDocument()),
created_during_document_write_(
element->GetDocument().IsInDocumentWrite()) {}
@@ -140,16 +141,22 @@ void PendingScript::ExecuteScriptBlock(const KURL& document_url) {
}
if (OriginalContextDocument() != context_document) {
- if (GetScriptType() == mojom::ScriptType::kModule) {
- // Do not execute module scripts if they are moved between documents.
- Dispose();
- return;
- }
+ // Do not execute scripts if they are moved between context documents.
+ Dispose();
+ return;
+ }
- // TODO(hiroshige): Also do not execute classic scripts.
- // https://crbug.com/721914
+ if (original_element_document_ != &element_->GetDocument()) {
+ // Do not execute scripts if they are moved between element documents (under
+ // the same context Document).
+
+ // We continue counting for a while to confirm that such cases are really
+ // rare on stable channel. https://crbug.com/721914
UseCounter::Count(context_document,
- WebFeature::kEvaluateScriptMovedBetweenDocuments);
+ WebFeature::kEvaluateScriptMovedBetweenElementDocuments);
+
+ Dispose();
+ return;
}
Script* script = GetSource(document_url);
@@ -291,6 +298,7 @@ void PendingScript::Trace(Visitor* visitor) {
visitor->Trace(element_);
visitor->Trace(client_);
visitor->Trace(original_context_document_);
+ visitor->Trace(original_element_document_);
}
bool PendingScript::IsControlledByScriptRunner() const {
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 8b880416817..8ba0a5d806a 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.h
@@ -27,7 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_SCRIPT_H_
#include "base/macros.h"
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/script.h"
@@ -61,9 +61,8 @@ class CORE_EXPORT PendingScriptClient : public GarbageCollectedMixin {
// When "script is ready"
// https://html.spec.whatwg.org/C/#the-script-is-ready,
// PendingScriptClient is notified.
-class CORE_EXPORT PendingScript
- : public GarbageCollectedFinalized<PendingScript>,
- public NameClient {
+class CORE_EXPORT PendingScript : public GarbageCollected<PendingScript>,
+ public NameClient {
public:
virtual ~PendingScript();
@@ -168,9 +167,10 @@ class CORE_EXPORT PendingScript
WebScopedVirtualTimePauser virtual_time_pauser_;
Member<PendingScriptClient> client_;
- // The context document at the time when PrepareScript() is executed.
- // This is only used to check whether the script element is moved between
- // documents and thus doesn't retain a strong reference.
+ // The context/element document at the time when PrepareScript() is executed.
+ // These are only used to check whether the script element is moved between
+ // documents and thus don't retain a strong references.
+ WeakMember<Document> original_element_document_;
WeakMember<Document> original_context_document_;
const bool created_during_document_write_;
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
index 81a02e5844e..6732ffd963f 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/index.mjs
@@ -9,10 +9,37 @@ import * as style from './style.mjs';
import {SwitchTrack} from './track.mjs';
const generateStyleSheet = style.styleSheetFactory();
+const generateMaterialStyleSheet = style.materialStyleSheetFactory();
// https://github.com/tkent-google/std-switch/issues/2
const STATE_ATTR = 'on';
+function parentOrHostElement(element) {
+ const parent = element.parentNode;
+ if (!parent) {
+ return null;
+ }
+ if (parent.nodeType === Node.ELEMENT_NODE) {
+ return parent;
+ }
+ if (parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
+ return parent.host;
+ }
+ return null;
+}
+
+function shouldUsePlatformTheme(element) {
+ for (; element; element = parentOrHostElement(element)) {
+ const themeValue = element.getAttribute('theme');
+ if (themeValue === 'match-platform') {
+ return true;
+ } else if (themeValue === 'platform-agnostic') {
+ return false;
+ }
+ }
+ return false;
+}
+
export class StdSwitchElement extends HTMLElement {
// TODO(tkent): The following should be |static fooBar = value;|
// after enabling babel-eslint.
@@ -27,6 +54,7 @@ export class StdSwitchElement extends HTMLElement {
#track;
#containerElement;
#inUserAction = false;
+ #shadowRoot;
constructor() {
super();
@@ -62,6 +90,11 @@ export class StdSwitchElement extends HTMLElement {
}
connectedCallback() {
+ // The element might have been disconnected when the callback is invoked.
+ if (!this.isConnected) {
+ return;
+ }
+
// TODO(tkent): We should not add tabindex attribute.
// https://github.com/w3c/webcomponents/issues/762
if (!this.hasAttribute('tabindex')) {
@@ -76,6 +109,15 @@ export class StdSwitchElement extends HTMLElement {
this.setAttribute('role', 'switch');
}
}
+
+ if (shouldUsePlatformTheme(this)) {
+ // TODO(tkent): Should we apply Cocoa-like on macOS and Fluent-like
+ // on Windows?
+ this.#shadowRoot.adoptedStyleSheets =
+ [generateStyleSheet(), generateMaterialStyleSheet()];
+ } else {
+ this.#shadowRoot.adoptedStyleSheets = [generateStyleSheet()];
+ }
}
formResetCallback() {
@@ -100,7 +142,7 @@ export class StdSwitchElement extends HTMLElement {
thumbElement.id = 'thumb';
thumbElement.part.add('thumb');
- root.adoptedStyleSheets = [generateStyleSheet()];
+ this.#shadowRoot = root;
};
#onClick = () => {
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs
index ba213120a90..ded00d06040 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/switch/style.mjs
@@ -11,6 +11,10 @@ const THUMB_WIDTH = '22px';
const THUMB_MARGIN_START = '2px';
const THUMB_MARGIN_END = '2px';
+const MATERIAL_THUMB_SIZE = '20px';
+const RIPPLE_COLOR = 'rgba(100,100,100,0.3)';
+const RIPPLE_MAX_SIZE = '48px';
+
// Returns a function returning a CSSStyleSheet().
// TODO(tkent): Share this stylesheet factory feature with elements/toast/.
export function styleSheetFactory() {
@@ -151,6 +155,122 @@ export function styleSheetFactory() {
};
}
+export function materialStyleSheetFactory() {
+ let styleSheet;
+ return () => {
+ if (!styleSheet) {
+ styleSheet = new CSSStyleSheet();
+ styleSheet.replaceSync(`
+:host {
+ block-size: 20px;
+ inline-size: 36px;
+}
+
+#track,
+:host(:active) #track {
+ background: rgba(0,0,0,0.4);
+ block-size: 14px;
+ border: none;
+ box-shadow: none;
+}
+
+:host([on]) #track,
+:host([on]:active) #track,
+:host([on]:focus) #track {
+ border: none;
+ box-shadow: none;
+}
+
+#trackFill,
+:host([on]:active) #trackFill {
+ background: rgba(63,81,181,0.5);
+}
+
+#thumb,
+:host(:focus) #thumb {
+ block-size: ${MATERIAL_THUMB_SIZE};
+ border-radius: calc(${MATERIAL_THUMB_SIZE} / 2);
+ border: none;
+ box-shadow: 0 1px 5px 0 rgba(0,0,0,0.6);
+ inline-size: ${MATERIAL_THUMB_SIZE};
+ margin-inline-start: -100%;
+}
+
+:host([on]) #thumb,
+:host([on]:focus) #thumb,
+:host([on]:not(:disabled):hover) #thumb {
+ background: rgb(63,81,181);
+ border: none;
+ margin-inline-start: calc(0px - 20px);
+}
+
+:host(:not(:disabled):hover) #thumb {
+ inline-size: ${MATERIAL_THUMB_SIZE};
+}
+
+/*
+ * Ripple effect
+ *
+ * Translucent circle is painted on the thumb if the element is :active or
+ * :focus-visible. It has
+ * - Size transition when it appears
+ * - Opacity transition when it disappears
+ * part(thumb)::before represents the former, and part(thumb)::after represents
+ * the latter.
+ */
+#thumb::before {
+ background: ${RIPPLE_COLOR};
+ block-size: 0px;
+ border-radius: 0px;
+ content: "";
+ display: inline-block;
+ inline-size: 0px;
+ left: calc(${MATERIAL_THUMB_SIZE} / 2);
+ position: relative;
+ top: calc(${MATERIAL_THUMB_SIZE} / 2);
+ transition: none;
+}
+
+:host(:active) #thumb::before,
+:host(:focus-visible) #thumb::before {
+ block-size: ${RIPPLE_MAX_SIZE};
+ border-radius: calc(${RIPPLE_MAX_SIZE} / 2);
+ inline-size: ${RIPPLE_MAX_SIZE};
+ left: calc((${MATERIAL_THUMB_SIZE} - ${RIPPLE_MAX_SIZE}) / 2);
+ top: calc((${MATERIAL_THUMB_SIZE} - ${RIPPLE_MAX_SIZE}) / 2);
+ transition: all linear 0.1s;
+}
+
+#thumb::after {
+ background: ${RIPPLE_COLOR};
+ block-size: ${RIPPLE_MAX_SIZE};
+ border-radius: calc(${RIPPLE_MAX_SIZE} / 2);
+ content: "";
+ display: inline-block;
+ inline-size: ${RIPPLE_MAX_SIZE};
+ left: calc((${MATERIAL_THUMB_SIZE} - ${RIPPLE_MAX_SIZE}) / 2);
+ opacity: 0;
+ position: relative;
+ /* Why 18px? */
+ top: calc((${MATERIAL_THUMB_SIZE} - ${RIPPLE_MAX_SIZE}) / 2 - 18px);
+ transition: opacity linear 0.3s;
+}
+
+:host(:active) #thumb::after,
+:host(:focus-visible) #thumb::after {
+ block-size: 0px;
+ content: "";
+ inline-size: 0px;
+ opacity: 1;
+ transition: none;
+}
+
+`);
+ }
+ return styleSheet;
+ };
+}
+
/**
* Add '$part-transitioning' part to the element if the element already has
* a part name.
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs
index 067a6e36d82..b9a67e460ec 100644
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/elements/virtual-scroller/visibility-manager.mjs
@@ -189,9 +189,8 @@ export class VisibilityManager {
// This should include all of the elements to be revealed and
// also 1 element above and below those (if such elements
// exist).
- const newObserved = new Set();
+ const newObserved = new Set(newRevealed);
if (newRevealed.size !== 0) {
- newObserved.add(...newRevealed);
const p = newBounds.low.previousElementSibling;
if (p) {
newObserved.add(p);
@@ -321,12 +320,8 @@ export class VisibilityManager {
*/
#unlock =
element => {
- element.displayLock.commit().catch(reason => {
- // Only warn if the unlocked failed and we should be revealed.
- if (this.#revealed.has(element)) {
- this.#logLockingError('Commit', reason, element);
- }
- });
+ element.removeAttribute('rendersubtree');
+ element.style.contentSize = '';
}
/**
@@ -337,19 +332,9 @@ export class VisibilityManager {
#hide =
element => {
this.#revealed.delete(element);
- element.displayLock
- .acquire({
- timeout: Infinity,
- activatable: true,
- size:
- [LOCKED_WIDTH_PX, this.#sizeManager.getHopefulSize(element)],
- })
- .catch(reason => {
- // Only warn if the lock failed and we should be locked.
- if (!this.#revealed.has(element)) {
- this.#logLockingError('Acquire', reason, element);
- }
- });
+ const size = this.#sizeManager.getHopefulSize(element);
+ element.setAttribute('rendersubtree', 'invisible activatable');
+ element.style.contentSize = `${LOCKED_WIDTH_PX}px ${size}px`;
}
/**
diff --git a/chromium/third_party/blink/renderer/core/script/script.h b/chromium/third_party/blink/renderer/core/script/script.h
index 22260298889..1f633a9e6b2 100644
--- a/chromium/third_party/blink/renderer/core/script/script.h
+++ b/chromium/third_party/blink/renderer/core/script/script.h
@@ -19,7 +19,7 @@ class SecurityOrigin;
class WorkerGlobalScope;
// https://html.spec.whatwg.org/C/#concept-script
-class CORE_EXPORT Script : public GarbageCollectedFinalized<Script> {
+class CORE_EXPORT Script : public GarbageCollected<Script> {
public:
virtual void Trace(Visitor* visitor) {}
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 13af863a133..a83eea44812 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -347,11 +348,11 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
if (!context_document->CanExecuteScripts(kAboutToExecuteScript))
return false;
- // Set |is_import_map| only if BuiltInModuleInfraEnabled().
+ // Set |is_import_map| only if ImportMapsEnabled().
if (is_import_map) {
Modulator* modulator = Modulator::From(
ToScriptStateForMainWorld(context_document->GetFrame()));
- if (!modulator->BuiltInModuleInfraEnabled())
+ if (!modulator->ImportMapsEnabled())
is_import_map = 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 0ac49da3bc0..22b68380c39 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.h
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.h
@@ -21,7 +21,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.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/core/core_export.h"
@@ -47,10 +47,9 @@ class Script;
class ScriptResource;
class Modulator;
-class CORE_EXPORT ScriptLoader final
- : public GarbageCollectedFinalized<ScriptLoader>,
- public PendingScriptClient,
- public NameClient {
+class CORE_EXPORT ScriptLoader final : public GarbageCollected<ScriptLoader>,
+ public PendingScriptClient,
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptLoader);
public:
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 c3e12f4ab8f..6965a18ccf6 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.cc
@@ -71,12 +71,6 @@ void ScriptRunner::PostTask(const base::Location& web_trace_location) {
}
void ScriptRunner::Suspend() {
-#ifndef NDEBUG
- // Resume will re-post tasks for all available scripts.
- number_of_extra_tasks_ += async_scripts_to_execute_soon_.size() +
- in_order_scripts_to_execute_soon_.size();
-#endif
-
is_suspended_ = true;
}
@@ -84,12 +78,27 @@ void ScriptRunner::Resume() {
DCHECK(is_suspended_);
is_suspended_ = false;
+ if (!IsExecutionSuspended())
+ PostTasksForReadyScripts(FROM_HERE);
+}
+
+void ScriptRunner::SetForceDeferredExecution(bool force_deferred) {
+ DCHECK(force_deferred != is_force_deferred_);
+
+ is_force_deferred_ = force_deferred;
+ if (!IsExecutionSuspended())
+ PostTasksForReadyScripts(FROM_HERE);
+}
+
+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(FROM_HERE);
+ PostTask(web_trace_location);
}
for (size_t i = 0; i < in_order_scripts_to_execute_soon_.size(); ++i) {
- PostTask(FROM_HERE);
+ PostTask(web_trace_location);
}
}
@@ -240,7 +249,7 @@ void ScriptRunner::ExecuteTask() {
whitelisted_stack_scope(
scheduler::CooperativeSchedulingManager::Instance());
- if (is_suspended_)
+ if (IsExecutionSuspended())
return;
if (ExecuteAsyncTask())
@@ -248,12 +257,6 @@ void ScriptRunner::ExecuteTask() {
if (ExecuteInOrderTask())
return;
-
-#ifndef NDEBUG
- // Extra tasks should be posted only when we resume after suspending. These
- // should all be accounted for in number_of_extra_tasks_.
- DCHECK_GT(number_of_extra_tasks_--, 0);
-#endif
}
void ScriptRunner::Trace(Visitor* visitor) {
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 75b69989ca9..ad3084aede0 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.h
@@ -41,9 +41,8 @@ class Document;
class PendingScript;
class ScriptLoader;
-class CORE_EXPORT ScriptRunner final
- : public GarbageCollectedFinalized<ScriptRunner>,
- public NameClient {
+class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
+ public NameClient {
public:
explicit ScriptRunner(Document*);
@@ -54,6 +53,7 @@ class CORE_EXPORT ScriptRunner final
}
void Suspend();
void Resume();
+ void SetForceDeferredExecution(bool force_deferred);
void NotifyScriptReady(PendingScript*);
static void MovePendingScript(Document&, Document&, ScriptLoader*);
@@ -69,6 +69,7 @@ class CORE_EXPORT ScriptRunner final
void ScheduleReadyInOrderScripts();
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.
@@ -80,6 +81,8 @@ class CORE_EXPORT ScriptRunner final
void ExecuteTask();
+ bool IsExecutionSuspended() { return is_suspended_ || is_force_deferred_; }
+
Member<Document> document_;
HeapDeque<Member<PendingScript>> pending_in_order_scripts_;
@@ -95,13 +98,11 @@ class CORE_EXPORT ScriptRunner final
bool is_suspended_ = false;
-#ifndef NDEBUG
- // We expect to have one posted task in flight for each script in either
- // .._to_be_executed_soon_ queue. This invariant will be temporarily violated
- // when the ScriptRunner is suspended. We'll use this variable to account &
- // check this invariant for debugging.
- int number_of_extra_tasks_ = 0;
-#endif
+ // Whether script execution is suspended due to there being force deferred
+ // scripts that have not yet been executed. This is expected to be in sync
+ // with HTMLParserScriptRunner::suspended_async_script_execution_.
+ bool is_force_deferred_ = false;
+
DISALLOW_COPY_AND_ASSIGN(ScriptRunner);
};
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 90de3ac1715..93fe88a8522 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
@@ -364,6 +364,56 @@ TEST_F(ScriptRunnerTest, ResumeAndSuspend_Async) {
EXPECT_THAT(order_, WhenSorted(ElementsAre(1, 2, 3)));
}
+TEST_F(ScriptRunnerTest, SetForceDeferredWithAddedAsyncScript) {
+ auto* pending_script1 = MockPendingScript::CreateAsync(document_);
+
+ QueueScriptForExecution(pending_script1);
+ NotifyScriptReady(pending_script1);
+ EXPECT_CALL(*pending_script1, ExecuteScriptBlock(_))
+ .WillOnce(InvokeWithoutArgs([this] { order_.push_back(1); }));
+ script_runner_->SetForceDeferredExecution(true);
+
+ // Adding new async script while deferred will cause another task to be
+ // posted for it when execution is unblocked.
+ auto* pending_script2 = MockPendingScript::CreateAsync(document_);
+ QueueScriptForExecution(pending_script2);
+ NotifyScriptReady(pending_script2);
+ EXPECT_CALL(*pending_script2, ExecuteScriptBlock(_))
+ .WillOnce(InvokeWithoutArgs([this] { order_.push_back(2); }));
+ // Unblock async scripts before the tasks posted in NotifyScriptReady() is
+ // executed, i.e. no RunUntilIdle() etc. in between.
+ script_runner_->SetForceDeferredExecution(false);
+ platform_->RunUntilIdle();
+ ASSERT_EQ(2u, order_.size());
+}
+
+TEST_F(ScriptRunnerTest, SetForceDeferredAndResumeAndSuspend) {
+ auto* pending_script1 = MockPendingScript::CreateAsync(document_);
+
+ QueueScriptForExecution(pending_script1);
+ NotifyScriptReady(pending_script1);
+
+ EXPECT_CALL(*pending_script1, ExecuteScriptBlock(_))
+ .WillOnce(InvokeWithoutArgs([this] { order_.push_back(1); }));
+
+ script_runner_->SetForceDeferredExecution(true);
+ platform_->RunSingleTask();
+ ASSERT_EQ(0u, order_.size());
+
+ script_runner_->Suspend();
+ platform_->RunSingleTask();
+ ASSERT_EQ(0u, order_.size());
+
+ // Resume will not execute script while still in ForceDeferred state.
+ script_runner_->Resume();
+ platform_->RunUntilIdle();
+ ASSERT_EQ(0u, order_.size());
+
+ script_runner_->SetForceDeferredExecution(false);
+ platform_->RunUntilIdle();
+ ASSERT_EQ(1u, order_.size());
+}
+
TEST_F(ScriptRunnerTest, LateNotifications) {
auto* pending_script1 = MockPendingScript::CreateInOrder(document_);
auto* pending_script2 = MockPendingScript::CreateInOrder(document_);
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 c3a815264c2..30c6c688f93 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
@@ -102,7 +102,7 @@ ValueWrapperSyntheticModuleScript::CreateWithError(
settings_object->GetModuleRecordResolver()->RegisterModuleScript(
value_wrapper_module_script);
value_wrapper_module_script->SetParseErrorAndClearRecord(
- ScriptValue(settings_object->GetScriptState(), error));
+ ScriptValue(settings_object->GetScriptState()->GetIsolate(), error));
// Step 7. "Return script."
// [spec text]
return value_wrapper_module_script;
diff --git a/chromium/third_party/blink/renderer/core/script/xml_parser_script_runner.h b/chromium/third_party/blink/renderer/core/script/xml_parser_script_runner.h
index ba652cd839f..9ed0ddc0baf 100644
--- a/chromium/third_party/blink/renderer/core/script/xml_parser_script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/xml_parser_script_runner.h
@@ -19,7 +19,7 @@ class XMLParserScriptRunnerHost;
//
// https://html.spec.whatwg.org/C/#parsing-xhtml-documents
class XMLParserScriptRunner final
- : public GarbageCollectedFinalized<XMLParserScriptRunner>,
+ : public GarbageCollected<XMLParserScriptRunner>,
public PendingScriptClient {
USING_GARBAGE_COLLECTED_MIXIN(XMLParserScriptRunner);
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 36ab94f52a5..9a177020a11 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
@@ -112,7 +112,7 @@ void ProgrammaticScrollAnimator::UpdateCompositorAnimations() {
return ResetAnimationState();
}
- if (compositor_animation_id_ &&
+ if (compositor_animation_id() &&
run_state_ != RunState::kRunningOnCompositor) {
// If the current run state is WaitingToSendToCompositor but we have a
// non-zero compositor animation id, there's a currently running
@@ -123,8 +123,6 @@ void ProgrammaticScrollAnimator::UpdateCompositorAnimations() {
RemoveAnimation();
- compositor_animation_id_ = 0;
- compositor_animation_group_id_ = 0;
if (run_state_ == RunState::kWaitingToCancelOnCompositor) {
ResetAnimationState();
return;
@@ -147,14 +145,9 @@ void ProgrammaticScrollAnimator::UpdateCompositorAnimations() {
auto animation = std::make_unique<CompositorKeyframeModel>(
*animation_curve_, compositor_target_property::SCROLL_OFFSET, 0, 0);
- int animation_id = animation->Id();
- int animation_group_id = animation->Group();
-
if (AddAnimation(std::move(animation))) {
sent_to_compositor = true;
run_state_ = RunState::kRunningOnCompositor;
- compositor_animation_id_ = animation_id;
- compositor_animation_group_id_ = animation_group_id;
}
}
@@ -178,9 +171,8 @@ void ProgrammaticScrollAnimator::LayerForCompositedScrollingDidChange(
// continue the animation on the main thread.
if (run_state_ == RunState::kRunningOnCompositor &&
!scrollable_area_->LayerForScrolling()) {
+ RemoveAnimation();
run_state_ = RunState::kRunningOnMainThread;
- compositor_animation_id_ = 0;
- compositor_animation_group_id_ = 0;
animation_curve_->SetInitialValue(
CompositorOffsetFromBlinkOffset(scrollable_area_->GetScrollOffset()));
scrollable_area_->RegisterForAnimation();
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 f254c6ffa06..71ddd056ea1 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator.cc
@@ -34,7 +34,6 @@
#include "base/memory/scoped_refptr.h"
#include "cc/animation/scroll_offset_animation_curve.h"
-#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
@@ -44,14 +43,6 @@
namespace blink {
-namespace {
-
-cc::PictureLayer* ToCcLayer(GraphicsLayer* layer) {
- return layer ? layer->CcLayer() : nullptr;
-}
-
-} // namespace
-
ScrollAnimatorBase* ScrollAnimatorBase::Create(
ScrollableArea* scrollable_area) {
if (scrollable_area && scrollable_area->ScrollAnimatorEnabled())
@@ -275,14 +266,6 @@ void ScrollAnimator::TickAnimation(double monotonic_time) {
NotifyOffsetChanged();
}
-void ScrollAnimator::PostAnimationCleanupAndReset() {
- // Remove the temporary main thread scrolling reason that was added while
- // main thread had scheduled an animation.
- RemoveMainThreadScrollingReason();
-
- ResetAnimationState();
-}
-
bool ScrollAnimator::SendAnimationToCompositor() {
if (scrollable_area_->ShouldScrollOnMainThread())
return false;
@@ -297,15 +280,9 @@ bool ScrollAnimator::SendAnimationToCompositor() {
// using the current time on main thread.
animation->SetStartTime(start_time_);
- int animation_id = animation->Id();
- int animation_group_id = animation->Group();
-
bool sent_to_compositor = AddAnimation(std::move(animation));
- if (sent_to_compositor) {
+ if (sent_to_compositor)
run_state_ = RunState::kRunningOnCompositor;
- compositor_animation_id_ = animation_id;
- compositor_animation_group_id_ = animation_group_id;
- }
return sent_to_compositor;
}
@@ -325,14 +302,14 @@ void ScrollAnimator::UpdateCompositorAnimations() {
ScrollAnimatorCompositorCoordinator::UpdateCompositorAnimations();
if (run_state_ == RunState::kPostAnimationCleanup) {
- PostAnimationCleanupAndReset();
+ ResetAnimationState();
return;
}
if (run_state_ == RunState::kWaitingToCancelOnCompositor) {
- DCHECK(compositor_animation_id_);
+ DCHECK(compositor_animation_id());
AbortAnimation();
- PostAnimationCleanupAndReset();
+ ResetAnimationState();
return;
}
@@ -342,7 +319,7 @@ void ScrollAnimator::UpdateCompositorAnimations() {
// because a main thread scrolling reason is added, and simply trying
// to ::sendAnimationToCompositor will fail and we will run on the main
// thread.
- ResetAnimationIds();
+ RemoveAnimation();
run_state_ = RunState::kWaitingToSendToCompositor;
}
@@ -352,7 +329,6 @@ void ScrollAnimator::UpdateCompositorAnimations() {
// Abort the running animation before a new one with an updated
// target is added.
AbortAnimation();
- ResetAnimationIds();
if (run_state_ != RunState::kRunningOnCompositorButNeedsAdjustment) {
// When in RunningOnCompositorButNeedsAdjustment, the call to
@@ -386,33 +362,6 @@ void ScrollAnimator::UpdateCompositorAnimations() {
if (running_on_main_thread)
run_state_ = RunState::kRunningOnMainThread;
}
-
- // Main thread should deal with the scroll animations it started.
- if (sent_to_compositor || running_on_main_thread)
- AddMainThreadScrollingReason();
- else
- RemoveMainThreadScrollingReason();
- }
-}
-
-void ScrollAnimator::AddMainThreadScrollingReason() {
- // Usually main thread scrolling reasons should be updated from
- // one frame to all its descendants. khandlingScrollFromMainThread
- // is a special case because its subframes cannot be scrolled
- // when the reason is set. When the subframes are ready to scroll
- // the reason has benn reset.
- if (cc::Layer* scroll_layer =
- ToCcLayer(GetScrollableArea()->LayerForScrolling())) {
- scroll_layer->AddMainThreadScrollingReasons(
- cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
- }
-}
-
-void ScrollAnimator::RemoveMainThreadScrollingReason() {
- if (cc::Layer* scroll_layer =
- ToCcLayer(GetScrollableArea()->LayerForScrolling())) {
- scroll_layer->ClearMainThreadScrollingReasons(
- cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
}
}
@@ -437,17 +386,12 @@ void ScrollAnimator::CancelAnimation() {
}
void ScrollAnimator::TakeOverCompositorAnimation() {
- if (run_state_ == RunState::kRunningOnCompositor ||
- run_state_ == RunState::kRunningOnCompositorButNeedsUpdate)
- RemoveMainThreadScrollingReason();
-
ScrollAnimatorCompositorCoordinator::TakeOverCompositorAnimation();
}
void ScrollAnimator::LayerForCompositedScrollingDidChange(
CompositorAnimationTimeline* timeline) {
- if (ReattachCompositorAnimationIfNeeded(timeline) && animation_curve_)
- AddMainThreadScrollingReason();
+ ReattachCompositorAnimationIfNeeded(timeline);
}
bool ScrollAnimator::RegisterAndScheduleAnimation() {
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_animator.h b/chromium/third_party/blink/renderer/core/scroll/scroll_animator.h
index 110333f0b9b..364beb8e667 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator.h
@@ -144,10 +144,6 @@ class CORE_EXPORT ScrollAnimator : public ScrollAnimatorBase {
bool RegisterAndScheduleAnimation();
void CreateAnimationCurve();
- void PostAnimationCleanupAndReset();
-
- void AddMainThreadScrollingReason();
- void RemoveMainThreadScrollingReason();
// Returns true if will animate to the given target offset. Returns false
// only when there is no animation running and we are not starting one
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.cc b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.cc
index 42332d21f89..821ff1aa700 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.cc
@@ -22,9 +22,9 @@ namespace blink {
ScrollAnimatorCompositorCoordinator::ScrollAnimatorCompositorCoordinator()
: element_id_(),
run_state_(RunState::kIdle),
+ impl_only_animation_takeover_(false),
compositor_animation_id_(0),
- compositor_animation_group_id_(0),
- impl_only_animation_takeover_(false) {
+ compositor_animation_group_id_(0) {
compositor_animation_ = CompositorAnimation::Create();
DCHECK(compositor_animation_);
compositor_animation_->SetAnimationDelegate(this);
@@ -38,14 +38,9 @@ void ScrollAnimatorCompositorCoordinator::Dispose() {
compositor_animation_.reset();
}
-void ScrollAnimatorCompositorCoordinator::ResetAnimationIds() {
- compositor_animation_id_ = 0;
- compositor_animation_group_id_ = 0;
-}
-
void ScrollAnimatorCompositorCoordinator::ResetAnimationState() {
run_state_ = RunState::kIdle;
- ResetAnimationIds();
+ RemoveAnimation();
}
bool ScrollAnimatorCompositorCoordinator::HasAnimationThatRequiresService()
@@ -73,7 +68,10 @@ bool ScrollAnimatorCompositorCoordinator::HasAnimationThatRequiresService()
bool ScrollAnimatorCompositorCoordinator::AddAnimation(
std::unique_ptr<CompositorKeyframeModel> keyframe_model) {
+ RemoveAnimation();
if (compositor_animation_->IsElementAttached()) {
+ compositor_animation_id_ = keyframe_model->Id();
+ compositor_animation_group_id_ = keyframe_model->Group();
compositor_animation_->AddKeyframeModel(std::move(keyframe_model));
return true;
}
@@ -81,13 +79,19 @@ bool ScrollAnimatorCompositorCoordinator::AddAnimation(
}
void ScrollAnimatorCompositorCoordinator::RemoveAnimation() {
- if (compositor_animation_->IsElementAttached())
+ if (compositor_animation_id_) {
compositor_animation_->RemoveKeyframeModel(compositor_animation_id_);
+ compositor_animation_id_ = 0;
+ compositor_animation_group_id_ = 0;
+ }
}
void ScrollAnimatorCompositorCoordinator::AbortAnimation() {
- if (compositor_animation_->IsElementAttached())
+ if (compositor_animation_id_) {
compositor_animation_->AbortKeyframeModel(compositor_animation_id_);
+ compositor_animation_id_ = 0;
+ compositor_animation_group_id_ = 0;
+ }
}
void ScrollAnimatorCompositorCoordinator::CancelAnimation() {
@@ -151,8 +155,10 @@ void ScrollAnimatorCompositorCoordinator::CompositorAnimationFinished(
if (compositor_animation_group_id_ != group_id)
return;
- compositor_animation_id_ = 0;
- compositor_animation_group_id_ = 0;
+ // TODO(crbug.com/992437) We should not need to remove completed animations
+ // however they are sometimes accidentally restarted if we don't explicitly
+ // remove them.
+ RemoveAnimation();
switch (run_state_) {
case RunState::kIdle:
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.h b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.h
index 814d08251be..32171ab4c9d 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_compositor_coordinator.h
@@ -31,7 +31,7 @@ class CompositorKeyframeModel;
// See ScrollAnimator.h for more information about scroll animations.
class CORE_EXPORT ScrollAnimatorCompositorCoordinator
- : public GarbageCollectedFinalized<ScrollAnimatorCompositorCoordinator>,
+ : public GarbageCollected<ScrollAnimatorCompositorCoordinator>,
private CompositorAnimationClient,
CompositorAnimationDelegate {
DISALLOW_COPY_AND_ASSIGN(ScrollAnimatorCompositorCoordinator);
@@ -123,7 +123,6 @@ class CORE_EXPORT ScrollAnimatorCompositorCoordinator
return impl_only_animation_adjustment_;
}
- void ResetAnimationIds();
bool AddAnimation(std::unique_ptr<CompositorKeyframeModel>);
void RemoveAnimation();
virtual void AbortAnimation();
@@ -159,6 +158,7 @@ class CORE_EXPORT ScrollAnimatorCompositorCoordinator
CompositorAnimation* GetCompositorAnimation() const override;
friend class Internals;
+ friend class TestScrollAnimator;
// TODO(ymalik): Tests are added as friends to access m_RunState. Use the
// runStateForTesting accessor instead.
FRIEND_TEST_ALL_PREFIXES(ScrollAnimatorTest, MainThreadStates);
@@ -176,8 +176,7 @@ class CORE_EXPORT ScrollAnimatorCompositorCoordinator
// the animation is present.
CompositorElementId element_id_;
RunState run_state_;
- int compositor_animation_id_;
- int compositor_animation_group_id_;
+ int compositor_animation_id() const { return compositor_animation_id_; }
// An adjustment to the scroll offset on the main thread that may affect
// impl-only scroll offset animations.
@@ -195,6 +194,9 @@ class CORE_EXPORT ScrollAnimatorCompositorCoordinator
// Accesses compositing state and should only be called when in or after
// DocumentLifecycle::LifecycleState::CompositingClean.
void TakeOverImplOnlyScrollOffsetAnimation();
+
+ int compositor_animation_id_;
+ int compositor_animation_group_id_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_test.cc b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
index c0eeeb94387..1ca0771d991 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_animator_test.cc
@@ -54,7 +54,7 @@ double NowTicksInSeconds(const base::TestMockTimeTaskRunner* task_runner) {
}
class MockScrollableAreaForAnimatorTest
- : public GarbageCollectedFinalized<MockScrollableAreaForAnimatorTest>,
+ : public GarbageCollected<MockScrollableAreaForAnimatorTest>,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(MockScrollableAreaForAnimatorTest);
@@ -78,7 +78,6 @@ class MockScrollableAreaForAnimatorTest
MOCK_CONST_METHOD1(VisibleContentRect, IntRect(IncludeScrollbarsInRect));
MOCK_CONST_METHOD0(ContentsSize, IntSize());
MOCK_CONST_METHOD0(ScrollbarsCanBeActive, bool());
- MOCK_CONST_METHOD0(ScrollableAreaBoundingBox, IntRect());
MOCK_METHOD0(RegisterForAnimation, void());
MOCK_METHOD0(ScheduleAnimation, bool());
MOCK_CONST_METHOD0(UsedColorScheme, WebColorScheme());
@@ -149,6 +148,8 @@ class MockScrollableAreaForAnimatorTest
mutable scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
};
+} // namespace
+
class TestScrollAnimator : public ScrollAnimator {
public:
TestScrollAnimator(ScrollableArea* scrollable_area,
@@ -177,8 +178,6 @@ class TestScrollAnimator : public ScrollAnimator {
bool should_send_to_compositor_ = false;
};
-} // namespace
-
static void Reset(ScrollAnimator& scroll_animator) {
scroll_animator.ScrollToOffsetWithoutAnimation(ScrollOffset());
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scroll_types.h b/chromium/third_party/blink/renderer/core/scroll/scroll_types.h
index b20c85b213a..ecda6b616c7 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scroll_types.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scroll_types.h
@@ -245,8 +245,6 @@ inline ScrollOffset ToScrollDelta(ScrollDirectionPhysical dir, float delta) {
: ScrollOffset(0, delta);
}
-typedef unsigned ScrollbarControlPartMask;
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLL_TYPES_H_
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 5e6db74afe5..ab7bdb48cc5 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_shift_tracker.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_timing_detector.h"
#include "third_party/blink/renderer/core/scroll/programmatic_scroll_animator.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
@@ -52,10 +53,11 @@
namespace blink {
-int ScrollableArea::PixelsPerLineStep(ChromeClient* host) {
- if (!host)
+int ScrollableArea::PixelsPerLineStep(LocalFrame* frame) {
+ if (!frame)
return kPixelsPerLineStep;
- return host->WindowToViewportScalar(kPixelsPerLineStep);
+ return frame->GetPage()->GetChromeClient().WindowToViewportScalar(
+ frame, kPixelsPerLineStep);
}
float ScrollableArea::MinFractionToStepWhenPaging() {
@@ -133,10 +135,6 @@ ProgrammaticScrollAnimator& ScrollableArea::GetProgrammaticScrollAnimator()
return *programmatic_scroll_animator_;
}
-GraphicsLayer* ScrollableArea::LayerForContainer() const {
- return LayerForScrolling() ? LayerForScrolling()->Parent() : nullptr;
-}
-
ScrollbarOrientation ScrollableArea::ScrollbarOrientationFromDirection(
ScrollDirectionPhysical direction) const {
return (direction == kScrollUp || direction == kScrollDown)
@@ -389,10 +387,7 @@ void ScrollableArea::ScrollOffsetChanged(const ScrollOffset& offset,
GetScrollOffset() - old_offset, scroll_type);
}
- if (GetLayoutBox() &&
- (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled() ||
- RuntimeEnabledFeatures::ElementTimingEnabled(
- &GetLayoutBox()->GetDocument()))) {
+ if (GetLayoutBox()) {
if (offset_changed && GetLayoutBox()->GetFrameView() &&
GetLayoutBox()
->GetFrameView()
@@ -754,7 +749,7 @@ ScrollOffset ScrollableArea::ClampScrollOffset(
}
int ScrollableArea::LineStep(ScrollbarOrientation) const {
- return PixelsPerLineStep(GetChromeClient());
+ return PixelsPerLineStep(GetLayoutBox()->GetFrame());
}
int ScrollableArea::PageStep(ScrollbarOrientation orientation) const {
@@ -824,7 +819,7 @@ CompositorElementId ScrollableArea::GetScrollbarElementId(
? CompositorElementIdNamespace::kHorizontalScrollbar
: CompositorElementIdNamespace::kVerticalScrollbar;
return CompositorElementIdFromUniqueObjectId(
- scrollable_element_id.GetInternalValue(), element_id_namespace);
+ scrollable_element_id.GetStableId(), element_id_namespace);
}
void ScrollableArea::OnScrollFinished() {
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 330a4c7d77f..b3066ee7056 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollable_area.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLLABLE_AREA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCROLL_SCROLLABLE_AREA_H_
+#include "cc/input/scroll_snap_data.h"
#include "third_party/blink/public/platform/web_color_scheme.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
@@ -54,6 +55,7 @@ class Document;
class GraphicsLayer;
class LayoutBox;
class LayoutObject;
+class LocalFrame;
class PaintLayer;
class ProgrammaticScrollAnimator;
class ScrollAnchor;
@@ -76,7 +78,7 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
public:
using ScrollCallback = base::OnceClosure;
- static int PixelsPerLineStep(ChromeClient*);
+ static int PixelsPerLineStep(LocalFrame*);
static float MinFractionToStepWhenPaging();
int MaxOverlapBetweenPages() const;
@@ -135,6 +137,10 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
void ContentAreaDidShow() const;
void ContentAreaDidHide() const;
+ virtual const cc::SnapContainerData* GetSnapContainerData() const {
+ return nullptr;
+ }
+ virtual void SetSnapContainerData(base::Optional<cc::SnapContainerData>) {}
virtual void SnapAfterScrollbarScrolling(ScrollbarOrientation) {}
void FinishCurrentScrollAnimations() const;
@@ -199,7 +205,8 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual bool IsScrollCornerVisible() const = 0;
virtual IntRect ScrollCornerRect() const = 0;
void SetScrollCornerNeedsPaintInvalidation();
- virtual void GetTickmarks(Vector<IntRect>&) const {}
+ virtual bool HasTickmarks() const { return false; }
+ virtual Vector<IntRect> GetTickmarks() const { return Vector<IntRect>(); }
// Convert points and rects between the scrollbar and its containing
// EmbeddedContentView. The client needs to implement these in order to be
@@ -284,10 +291,6 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual void ScrollbarStyleChanged() {}
virtual bool ScrollbarsCanBeActive() const = 0;
- // Returns the bounding box of this scrollable area, in the coordinate system
- // of the top-level FrameView's Document.
- virtual IntRect ScrollableAreaBoundingBox() const = 0;
-
virtual CompositorElementId GetCompositorElementId() const = 0;
virtual CompositorElementId GetScrollbarElementId(
@@ -336,7 +339,6 @@ class CORE_EXPORT ScrollableArea : public GarbageCollectedMixin {
MaximumScrollOffset(orientation));
}
- virtual GraphicsLayer* LayerForContainer() const;
virtual GraphicsLayer* LayerForScrolling() const { return nullptr; }
virtual GraphicsLayer* LayerForHorizontalScrollbar() const { return nullptr; }
virtual GraphicsLayer* LayerForVerticalScrollbar() const { return nullptr; }
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 aa45ab3cff5..a7216043fe7 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
@@ -29,7 +29,7 @@ using testing::Return;
class ScrollbarThemeWithMockInvalidation : public ScrollbarThemeMock {
public:
MOCK_CONST_METHOD0(ShouldRepaintAllPartsOnInvalidation, bool());
- MOCK_CONST_METHOD3(InvalidateOnThumbPositionChange,
+ MOCK_CONST_METHOD3(PartsToInvalidateOnThumbPositionChange,
ScrollbarPart(const Scrollbar&, float, float));
};
@@ -143,7 +143,7 @@ TEST_F(ScrollableAreaTest, InvalidatesNonCompositedScrollbarsWhenThumbMoves) {
ASSERT_FALSE(scrollable_area->HasLayerForHorizontalScrollbar());
EXPECT_CALL(theme, ShouldRepaintAllPartsOnInvalidation())
.WillRepeatedly(Return(false));
- EXPECT_CALL(theme, InvalidateOnThumbPositionChange(_, _, _))
+ EXPECT_CALL(theme, PartsToInvalidateOnThumbPositionChange(_, _, _))
.WillRepeatedly(Return(kNoPart));
// A scroll in each direction should only invalidate one scrollbar.
@@ -201,7 +201,7 @@ TEST_F(ScrollableAreaTest, InvalidatesCompositedScrollbarsIfPartsNeedRepaint) {
// First, we'll scroll horizontally, and the theme will require repainting
// the back button (i.e. the track).
- EXPECT_CALL(theme, InvalidateOnThumbPositionChange(_, _, _))
+ EXPECT_CALL(theme, PartsToInvalidateOnThumbPositionChange(_, _, _))
.WillOnce(Return(kBackButtonStartPart));
scrollable_area->SetScrollOffset(ScrollOffset(50, 0), kProgrammaticScroll);
EXPECT_TRUE(layer_for_horizontal_scrollbar.HasTrackedRasterInvalidations());
@@ -212,7 +212,7 @@ TEST_F(ScrollableAreaTest, InvalidatesCompositedScrollbarsIfPartsNeedRepaint) {
horizontal_scrollbar->ClearTrackNeedsRepaint();
// Next, we'll scroll vertically, but invalidate the thumb.
- EXPECT_CALL(theme, InvalidateOnThumbPositionChange(_, _, _))
+ EXPECT_CALL(theme, PartsToInvalidateOnThumbPositionChange(_, _, _))
.WillOnce(Return(kThumbPart));
scrollable_area->SetScrollOffset(ScrollOffset(50, 50), kProgrammaticScroll);
EXPECT_FALSE(layer_for_horizontal_scrollbar.HasTrackedRasterInvalidations());
@@ -226,7 +226,7 @@ TEST_F(ScrollableAreaTest, InvalidatesCompositedScrollbarsIfPartsNeedRepaint) {
// invalidations. Nonetheless the GraphicsLayer should be invalidated,
// because we still need to update the underlying layer (though no
// rasterization will be required).
- EXPECT_CALL(theme, InvalidateOnThumbPositionChange(_, _, _))
+ EXPECT_CALL(theme, PartsToInvalidateOnThumbPositionChange(_, _, _))
.Times(2)
.WillRepeatedly(Return(kNoPart));
scrollable_area->SetScrollOffset(ScrollOffset(70, 70), kProgrammaticScroll);
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
index 7aecdafef63..d17f3c56aa3 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.cc
@@ -32,7 +32,7 @@
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_scrollbar_overlay_color_theme.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/core/scroll/scrollable_area.h"
@@ -81,8 +81,10 @@ Scrollbar::Scrollbar(ScrollableArea* scrollable_area,
// sizing).
int thickness = theme_.ScrollbarThickness(control_size);
theme_scrollbar_thickness_ = thickness;
- if (chrome_client_)
- thickness = chrome_client_->WindowToViewportScalar(thickness);
+ if (chrome_client_) {
+ thickness = chrome_client_->WindowToViewportScalar(
+ scrollable_area_->GetLayoutBox()->GetFrame(), thickness);
+ }
frame_rect_ = IntRect(0, 0, thickness, thickness);
current_pos_ = ScrollableAreaCurrentPos();
@@ -111,9 +113,15 @@ ScrollbarOverlayColorTheme Scrollbar::GetScrollbarOverlayColorTheme() const {
: kScrollbarOverlayColorThemeDark;
}
-void Scrollbar::GetTickmarks(Vector<IntRect>& tickmarks) const {
+bool Scrollbar::HasTickmarks() const {
+ return orientation_ == kVerticalScrollbar && scrollable_area_ &&
+ scrollable_area_->HasTickmarks();
+}
+
+Vector<IntRect> Scrollbar::GetTickmarks() const {
if (scrollable_area_)
- scrollable_area_->GetTickmarks(tickmarks);
+ return scrollable_area_->GetTickmarks();
+ return Vector<IntRect>();
}
bool Scrollbar::IsScrollableAreaActive() const {
@@ -145,7 +153,8 @@ void Scrollbar::OffsetDidChange() {
current_pos_ = position;
ScrollbarPart invalid_parts =
- GetTheme().InvalidateOnThumbPositionChange(*this, old_position, position);
+ GetTheme().PartsToInvalidateOnThumbPositionChange(*this, old_position,
+ position);
SetNeedsPaintInvalidation(invalid_parts);
if (pressed_part_ == kThumbPart)
@@ -202,14 +211,7 @@ void Scrollbar::AutoscrollPressedPart(base::TimeDelta delay) {
}
// Handle the arrows and track by injecting a scroll update.
- if (IsScrollGestureInjectionEnabled()) {
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
- } else {
- scrollable_area_->UserScroll(
- PressedPartScrollGranularity(),
- ToScrollDelta(PressedPartScrollDirectionPhysical(), 1),
- ScrollableArea::ScrollCallback());
- }
+ InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
// Always start timer when user press on button since scrollable area maybe
// infinite scrolling.
@@ -284,12 +286,7 @@ void Scrollbar::MoveThumb(int pos, bool dragging_document) {
delta;
destination_position =
scrollable_area_->ClampScrollOffset(orientation_, destination_position);
- if (IsScrollGestureInjectionEnabled()) {
- InjectGestureScrollUpdateForThumbMove(destination_position);
- } else {
- scrollable_area_->SetScrollOffsetSingleAxis(
- orientation_, destination_position, kUserScroll);
- }
+ InjectGestureScrollUpdateForThumbMove(destination_position);
document_drag_pos_ = pos;
return;
}
@@ -318,12 +315,8 @@ void Scrollbar::MoveThumb(int pos, bool dragging_document) {
float new_offset = static_cast<float>(thumb_pos + delta) *
(max_offset - min_offset) / (track_len - thumb_len) +
min_offset;
- if (IsScrollGestureInjectionEnabled()) {
- InjectGestureScrollUpdateForThumbMove(new_offset);
- } else {
- scrollable_area_->SetScrollOffsetSingleAxis(orientation_, new_offset,
- kUserScroll);
- }
+
+ InjectGestureScrollUpdateForThumbMove(new_offset);
}
}
@@ -436,19 +429,13 @@ bool Scrollbar::HandleTapGesture() {
scrollable_area_) {
ScrollOffset delta = ToScrollDelta(PressedPartScrollDirectionPhysical(), 1);
if (DeltaWillScroll(delta)) {
- if (IsScrollGestureInjectionEnabled()) {
- // Taps perform a single scroll begin/update/end sequence of gesture
- // events. There's no autoscroll timer since long press is not treated
- // the same as holding a mouse down.
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollBegin);
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
- } else {
- scrollable_area_->UserScroll(
- PressedPartScrollGranularity(),
- ToScrollDelta(PressedPartScrollDirectionPhysical(), 1),
- ScrollableArea::ScrollCallback());
- }
+ // Taps perform a single scroll begin/update/end sequence of gesture
+ // events. There's no autoscroll timer since long press is not treated
+ // the same as holding a mouse down.
+ InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollBegin);
+ InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollUpdate);
+ InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
+
return true;
}
}
@@ -466,12 +453,7 @@ void Scrollbar::MouseMoved(const WebMouseEvent& evt) {
if (scrollable_area_) {
float destination_position =
drag_origin_ + scrollable_area_->MinimumScrollOffset(orientation_);
- if (IsScrollGestureInjectionEnabled()) {
- InjectGestureScrollUpdateForThumbMove(destination_position);
- } else {
- scrollable_area_->SetScrollOffsetSingleAxis(
- orientation_, destination_position, kUserScroll);
- }
+ InjectGestureScrollUpdateForThumbMove(destination_position);
}
} else {
MoveThumb(orientation_ == kHorizontalScrollbar
@@ -538,8 +520,7 @@ void Scrollbar::MouseUp(const WebMouseEvent& mouse_event) {
scrollable_area_->MouseExitedScrollbar(*this);
}
- if (IsScrollGestureInjectionEnabled())
- InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
+ InjectScrollGestureForPressedPart(WebInputEvent::kGestureScrollEnd);
}
}
@@ -580,10 +561,6 @@ void Scrollbar::MouseDown(const WebMouseEvent& evt) {
AutoscrollPressedPart(GetTheme().InitialAutoscrollTimerDelay());
}
-bool Scrollbar::IsScrollGestureInjectionEnabled() const {
- return base::FeatureList::IsEnabled(features::kScrollbarInjectScrollGestures);
-}
-
void Scrollbar::InjectScrollGestureForPressedPart(
WebInputEvent::Type gesture_type) {
ScrollOffset delta = ToScrollDelta(PressedPartScrollDirectionPhysical(), 1);
@@ -619,7 +596,6 @@ void Scrollbar::InjectGestureScrollUpdateForThumbMove(
void Scrollbar::InjectScrollGesture(WebInputEvent::Type gesture_type,
ScrollOffset delta,
ScrollGranularity granularity) {
- DCHECK(IsScrollGestureInjectionEnabled());
DCHECK(scrollable_area_);
if (gesture_type == WebInputEvent::Type::kGestureScrollEnd &&
@@ -695,7 +671,8 @@ int Scrollbar::ScrollbarThickness() const {
int thickness = Orientation() == kHorizontalScrollbar ? Height() : Width();
if (!thickness || !chrome_client_)
return thickness;
- return chrome_client_->WindowToViewportScalar(theme_scrollbar_thickness_);
+ return chrome_client_->WindowToViewportScalar(
+ scrollable_area_->GetLayoutBox()->GetFrame(), theme_scrollbar_thickness_);
}
bool Scrollbar::IsOverlayScrollbar() const {
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
index 3bbdbf610f8..811322d83cb 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar.h
@@ -47,7 +47,7 @@ class ScrollbarTheme;
class WebGestureEvent;
class WebMouseEvent;
-class CORE_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
+class CORE_EXPORT Scrollbar : public GarbageCollected<Scrollbar>,
public DisplayItemClient {
public:
// Theme object ownership remains with the caller and it must outlive the
@@ -79,7 +79,8 @@ class CORE_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
const IntRect& FrameRect() const { return frame_rect_; }
ScrollbarOverlayColorTheme GetScrollbarOverlayColorTheme() const;
- void GetTickmarks(Vector<IntRect>&) const;
+ bool HasTickmarks() const;
+ Vector<IntRect> GetTickmarks() const;
bool IsScrollableAreaActive() const;
IntPoint ConvertFromRootFrame(const IntPoint&) const;
@@ -161,8 +162,9 @@ class CORE_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
elastic_overscroll_ = elastic_overscroll;
}
- // Use setNeedsPaintInvalidation to cause the scrollbar (or parts thereof)
- // to repaint.
+ // Use SetNeedsPaintInvalidation to cause the scrollbar (or parts thereof)
+ // to repaint. Here "track" includes track, buttons and tickmarks, i.e. all
+ // things except the thumb.
bool TrackNeedsRepaint() const { return track_needs_repaint_; }
void ClearTrackNeedsRepaint() { track_needs_repaint_ = false; }
bool ThumbNeedsRepaint() const { return thumb_needs_repaint_; }
@@ -210,7 +212,6 @@ class CORE_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
void StopTimerIfNeeded();
void AutoscrollPressedPart(base::TimeDelta delay);
bool HandleTapGesture();
- bool IsScrollGestureInjectionEnabled() const;
void InjectScrollGestureForPressedPart(WebInputEvent::Type gesture_type);
void InjectGestureScrollUpdateForThumbMove(float single_axis_target_offset);
void InjectScrollGesture(WebInputEvent::Type type,
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
index 1d939bc608d..0088012e240 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.cc
@@ -86,6 +86,10 @@ gfx::Rect ScrollbarLayerDelegate::TrackRect() const {
return track_rect;
}
+bool ScrollbarLayerDelegate::SupportsDragSnapBack() const {
+ return theme_.SupportsDragSnapBack();
+}
+
gfx::Rect ScrollbarLayerDelegate::BackButtonRect() const {
IntRect back_button_rect =
theme_.BackButtonRect(*scrollbar_, blink::kBackButtonStartPart);
@@ -124,7 +128,7 @@ gfx::Rect ScrollbarLayerDelegate::NinePatchThumbAperture() const {
return theme_.NinePatchThumbAperture(*scrollbar_);
}
-bool ScrollbarLayerDelegate::HasTickmarks() const {
+bool ScrollbarLayerDelegate::ShouldPaint() const {
// TODO(crbug.com/860499): Remove this condition, it should not occur.
// Layers may exist and be painted for a |scrollbar_| that has had its
// ScrollableArea detached. This seems weird because if the area is detached
@@ -136,80 +140,45 @@ bool ScrollbarLayerDelegate::HasTickmarks() const {
// HasTickmarks can't be known and may change once the frame is unthrottled.
if (scrollbar_->GetScrollableArea()->IsThrottled())
return false;
+ return true;
+}
- Vector<IntRect> tickmarks;
- scrollbar_->GetTickmarks(tickmarks);
- return !tickmarks.IsEmpty();
+bool ScrollbarLayerDelegate::HasTickmarks() const {
+ return ShouldPaint() && scrollbar_->HasTickmarks();
}
void ScrollbarLayerDelegate::PaintPart(cc::PaintCanvas* canvas,
- cc::ScrollbarPart part,
- const gfx::Rect& content_rect) {
- PaintCanvasAutoRestore auto_restore(canvas, true);
- blink::Scrollbar& scrollbar = *scrollbar_;
-
- // TODO(crbug.com/860499): Remove this condition, it should not occur.
- // Layers may exist and be painted for a |scrollbar_| that has had its
- // ScrollableArea detached. This seems weird because if the area is detached
- // the layer should be destroyed but here we are.
- if (!scrollbar_->GetScrollableArea())
- return;
- // When the frame is throttled, the scrollbar will not be painted because
- // the frame has not had its lifecycle updated.
- if (scrollbar.GetScrollableArea()->IsThrottled())
+ cc::ScrollbarPart part) {
+ if (!ShouldPaint())
return;
- if (part == cc::THUMB) {
- ScopedScrollbarPainter painter(*canvas, device_scale_factor_);
- theme_.PaintThumb(painter.Context(), scrollbar, IntRect(content_rect));
- if (!theme_.ShouldRepaintAllPartsOnInvalidation())
- scrollbar.ClearThumbNeedsRepaint();
- return;
- }
-
- if (part == cc::TICKMARKS) {
- ScopedScrollbarPainter painter(*canvas, device_scale_factor_);
- theme_.PaintTickmarks(painter.Context(), scrollbar, IntRect(content_rect));
- return;
- }
-
- canvas->clipRect(gfx::RectToSkRect(content_rect));
ScopedScrollbarPainter painter(*canvas, device_scale_factor_);
- GraphicsContext& context = painter.Context();
-
- theme_.PaintScrollbarBackground(context, scrollbar);
-
- if (theme_.HasButtons(scrollbar)) {
- theme_.PaintButton(context, scrollbar,
- theme_.BackButtonRect(scrollbar, kBackButtonStartPart),
- kBackButtonStartPart);
- theme_.PaintButton(context, scrollbar,
- theme_.BackButtonRect(scrollbar, kBackButtonEndPart),
- kBackButtonEndPart);
- theme_.PaintButton(
- context, scrollbar,
- theme_.ForwardButtonRect(scrollbar, kForwardButtonStartPart),
- kForwardButtonStartPart);
- theme_.PaintButton(
- context, scrollbar,
- theme_.ForwardButtonRect(scrollbar, kForwardButtonEndPart),
- kForwardButtonEndPart);
+ // The canvas coordinate space is relative to the part's origin.
+ switch (part) {
+ case cc::THUMB: {
+ IntRect rect(IntPoint(),
+ UsesNinePatchThumbResource()
+ ? theme_.NinePatchThumbCanvasSize(*scrollbar_)
+ : theme_.ThumbRect(*scrollbar_).Size());
+ theme_.PaintThumb(painter.Context(), *scrollbar_, rect);
+ scrollbar_->ClearThumbNeedsRepaint();
+ break;
+ }
+ case cc::TRACK: {
+ theme_.PaintTrackAndButtonsForCompositor(painter.Context(), *scrollbar_);
+ theme_.PaintTickmarks(painter.Context(), *scrollbar_,
+ IntRect(TrackRect()));
+ scrollbar_->ClearTrackNeedsRepaint();
+ break;
+ }
+ case cc::TICKMARKS: {
+ IntRect rect(IntPoint(), theme_.TrackRect(*scrollbar_).Size());
+ theme_.PaintTickmarks(painter.Context(), *scrollbar_, rect);
+ break;
+ }
+ default:
+ NOTREACHED();
}
-
- IntRect track_paint_rect = theme_.TrackRect(scrollbar);
- theme_.PaintTrackBackground(context, scrollbar, track_paint_rect);
-
- if (theme_.HasThumb(scrollbar)) {
- theme_.PaintTrackPiece(painter.Context(), scrollbar, track_paint_rect,
- kForwardTrackPart);
- theme_.PaintTrackPiece(painter.Context(), scrollbar, track_paint_rect,
- kBackTrackPart);
- }
-
- theme_.PaintTickmarks(painter.Context(), scrollbar, track_paint_rect);
-
- if (!theme_.ShouldRepaintAllPartsOnInvalidation())
- scrollbar.ClearTrackNeedsRepaint();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
index 1f80dc65f34..c0136ed950d 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_layer_delegate.h
@@ -38,6 +38,7 @@ class CORE_EXPORT ScrollbarLayerDelegate : public cc::Scrollbar {
gfx::Point Location() const override;
int ThumbThickness() const override;
int ThumbLength() const override;
+ bool SupportsDragSnapBack() const override;
// Returns the track rect relative to the scrollbar's origin.
gfx::Rect TrackRect() const override;
@@ -51,15 +52,15 @@ class CORE_EXPORT ScrollbarLayerDelegate : public cc::Scrollbar {
float ThumbOpacity() const override;
bool NeedsPaintPart(cc::ScrollbarPart part) const override;
bool HasTickmarks() const override;
- void PaintPart(cc::PaintCanvas* canvas,
- cc::ScrollbarPart part,
- const gfx::Rect& content_rect) override;
+ void PaintPart(cc::PaintCanvas* canvas, cc::ScrollbarPart part) override;
bool UsesNinePatchThumbResource() const override;
gfx::Size NinePatchThumbCanvasSize() const override;
gfx::Rect NinePatchThumbAperture() const override;
private:
+ bool ShouldPaint() const;
+
// Accessed by main and compositor threads, e.g., the compositor thread
// checks |Orientation()|.
CrossThreadPersistent<blink::Scrollbar> scrollbar_;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_test_suite.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_test_suite.h
index 95766c57420..674935717fa 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_test_suite.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_test_suite.h
@@ -28,13 +28,15 @@ class MockPlatformChromeClient : public EmptyChromeClient {
void SetIsPopup(bool is_popup) { is_popup_ = is_popup; }
- float WindowToViewportScalar(const float) const override { return 0; }
+ float WindowToViewportScalar(LocalFrame*, const float) const override {
+ return 0;
+ }
private:
bool is_popup_;
};
-class MockScrollableArea : public GarbageCollectedFinalized<MockScrollableArea>,
+class MockScrollableArea : public GarbageCollected<MockScrollableArea>,
public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(MockScrollableArea);
@@ -65,7 +67,6 @@ class MockScrollableArea : public GarbageCollectedFinalized<MockScrollableArea>,
MOCK_CONST_METHOD0(EnclosingScrollableArea, ScrollableArea*());
MOCK_CONST_METHOD1(VisibleContentRect, IntRect(IncludeScrollbarsInRect));
MOCK_CONST_METHOD0(ContentsSize, IntSize());
- MOCK_CONST_METHOD0(ScrollableAreaBoundingBox, IntRect());
MOCK_CONST_METHOD0(LayerForHorizontalScrollbar, GraphicsLayer*());
MOCK_CONST_METHOD0(LayerForVerticalScrollbar, GraphicsLayer*());
MOCK_CONST_METHOD0(HorizontalScrollbar, Scrollbar*());
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
index f71b8891154..f4c406f87ac 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
@@ -57,88 +57,22 @@ static inline bool ShouldPaintScrollbarPart(const IntRect& part_rect,
return (!part_rect.IsEmpty()) || cull_rect.Intersects(part_rect);
}
-bool ScrollbarTheme::Paint(const Scrollbar& scrollbar,
+void ScrollbarTheme::Paint(const Scrollbar& scrollbar,
GraphicsContext& graphics_context,
const CullRect& cull_rect) {
- // Create the ScrollbarControlPartMask based on the cullRect
- ScrollbarControlPartMask scroll_mask = kNoPart;
-
- IntRect back_button_start_paint_rect;
- IntRect back_button_end_paint_rect;
- IntRect forward_button_start_paint_rect;
- IntRect forward_button_end_paint_rect;
- if (HasButtons(scrollbar)) {
- back_button_start_paint_rect =
- BackButtonRect(scrollbar, kBackButtonStartPart, true);
- if (ShouldPaintScrollbarPart(back_button_start_paint_rect, cull_rect))
- scroll_mask |= kBackButtonStartPart;
- back_button_end_paint_rect =
- BackButtonRect(scrollbar, kBackButtonEndPart, true);
- if (ShouldPaintScrollbarPart(back_button_end_paint_rect, cull_rect))
- scroll_mask |= kBackButtonEndPart;
- forward_button_start_paint_rect =
- ForwardButtonRect(scrollbar, kForwardButtonStartPart, true);
- if (ShouldPaintScrollbarPart(forward_button_start_paint_rect, cull_rect))
- scroll_mask |= kForwardButtonStartPart;
- forward_button_end_paint_rect =
- ForwardButtonRect(scrollbar, kForwardButtonEndPart, true);
- if (ShouldPaintScrollbarPart(forward_button_end_paint_rect, cull_rect))
- scroll_mask |= kForwardButtonEndPart;
- }
-
- IntRect start_track_rect;
- IntRect thumb_rect;
- IntRect end_track_rect;
- IntRect track_paint_rect = TrackRect(scrollbar, true);
- scroll_mask |= kTrackBGPart;
- bool thumb_present = HasThumb(scrollbar);
- if (thumb_present) {
- IntRect track = TrackRect(scrollbar);
- SplitTrack(scrollbar, track, start_track_rect, thumb_rect, end_track_rect);
- if (ShouldPaintScrollbarPart(thumb_rect, cull_rect))
- scroll_mask |= kThumbPart;
- if (ShouldPaintScrollbarPart(start_track_rect, cull_rect))
- scroll_mask |= kBackTrackPart;
- if (ShouldPaintScrollbarPart(end_track_rect, cull_rect))
- scroll_mask |= kForwardTrackPart;
- }
-
- // Paint the scrollbar background (only used by custom CSS scrollbars).
- PaintScrollbarBackground(graphics_context, scrollbar);
-
- // Paint the back and forward buttons.
- if (scroll_mask & kBackButtonStartPart)
- PaintButton(graphics_context, scrollbar, back_button_start_paint_rect,
- kBackButtonStartPart);
- if (scroll_mask & kBackButtonEndPart)
- PaintButton(graphics_context, scrollbar, back_button_end_paint_rect,
- kBackButtonEndPart);
- if (scroll_mask & kForwardButtonStartPart)
- PaintButton(graphics_context, scrollbar, forward_button_start_paint_rect,
- kForwardButtonStartPart);
- if (scroll_mask & kForwardButtonEndPart)
- PaintButton(graphics_context, scrollbar, forward_button_end_paint_rect,
- kForwardButtonEndPart);
-
- if (scroll_mask & kTrackBGPart)
- PaintTrackBackground(graphics_context, scrollbar, track_paint_rect);
-
- if ((scroll_mask & kForwardTrackPart) || (scroll_mask & kBackTrackPart)) {
- // Paint the track pieces above and below the thumb.
- if (scroll_mask & kBackTrackPart)
- PaintTrackPiece(graphics_context, scrollbar, start_track_rect,
- kBackTrackPart);
- if (scroll_mask & kForwardTrackPart)
- PaintTrackPiece(graphics_context, scrollbar, end_track_rect,
- kForwardTrackPart);
+ if (!ShouldPaintScrollbarPart(scrollbar.FrameRect(), cull_rect))
+ return;
+ PaintTrackAndButtons(graphics_context, scrollbar);
- PaintTickmarks(graphics_context, scrollbar, track_paint_rect);
+ if (scrollbar.HasTickmarks()) {
+ IntRect track_rect = TrackRect(scrollbar);
+ if (ShouldPaintScrollbarPart(track_rect, cull_rect))
+ PaintTickmarks(graphics_context, scrollbar, track_rect);
}
- if (scroll_mask & kThumbPart)
+ IntRect thumb_rect = ThumbRect(scrollbar);
+ if (HasThumb(scrollbar) && ShouldPaintScrollbarPart(thumb_rect, cull_rect))
PaintThumbWithOpacity(graphics_context, scrollbar, thumb_rect);
-
- return true;
}
ScrollbarPart ScrollbarTheme::HitTest(const Scrollbar& scrollbar,
@@ -195,12 +129,12 @@ void ScrollbarTheme::PaintScrollCorner(
if (corner_rect.IsEmpty())
return;
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, display_item_client, DisplayItem::kScrollbarCorner))
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, display_item_client,
+ DisplayItem::kScrollCorner))
return;
DrawingRecorder recorder(context, display_item_client,
- DisplayItem::kScrollbarCorner);
+ DisplayItem::kScrollCorner);
#if defined(OS_MACOSX)
context.FillRect(corner_rect, Color::kWhite);
#else
@@ -222,9 +156,7 @@ void ScrollbarTheme::PaintTickmarks(GraphicsContext& context,
if (rect.Height() <= 0 || rect.Width() <= 0)
return;
- // Get the tickmarks for the frameview.
- Vector<IntRect> tickmarks;
- scrollbar.GetTickmarks(tickmarks);
+ Vector<IntRect> tickmarks = scrollbar.GetTickmarks();
if (!tickmarks.size())
return;
@@ -237,10 +169,10 @@ void ScrollbarTheme::PaintTickmarks(GraphicsContext& context,
GraphicsContextStateSaver state_saver(context);
context.SetShouldAntialias(false);
- for (Vector<IntRect>::const_iterator i = tickmarks.begin();
- i != tickmarks.end(); ++i) {
+ for (const IntRect& tickmark : tickmarks) {
// Calculate how far down (in %) the tick-mark should appear.
- const float percent = static_cast<float>(i->Y()) / scrollbar.TotalSize();
+ const float percent =
+ static_cast<float>(tickmark.Y()) / scrollbar.TotalSize();
// Calculate how far down (in pixels) the tick-mark should appear.
const int y_pos = rect.Y() + (rect.Height() * percent);
@@ -394,33 +326,89 @@ bool ScrollbarTheme::MockScrollbarsEnabled() {
return g_mock_scrollbars_enabled_;
}
-DisplayItem::Type ScrollbarTheme::ButtonPartToDisplayItemType(
- ScrollbarPart part) {
- switch (part) {
- case kBackButtonStartPart:
- return DisplayItem::kScrollbarBackButtonStart;
- case kBackButtonEndPart:
- return DisplayItem::kScrollbarBackButtonEnd;
- case kForwardButtonStartPart:
- return DisplayItem::kScrollbarForwardButtonStart;
- case kForwardButtonEndPart:
- return DisplayItem::kScrollbarForwardButtonEnd;
- default:
- NOTREACHED();
- return DisplayItem::kScrollbarBackButtonStart;
+void ScrollbarTheme::PaintTrackAndButtons(GraphicsContext& context,
+ const Scrollbar& scrollbar) {
+ base::Optional<DrawingRecorder> recorder;
+ if (CreatesSingleDisplayItemForTrackAndButtons()) {
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ context, scrollbar, DisplayItem::kScrollbarTrackAndButtons))
+ return;
+ recorder.emplace(context, scrollbar,
+ DisplayItem::kScrollbarTrackAndButtons);
+ }
+
+ PaintScrollbarBackground(context, scrollbar);
+
+ if (HasButtons(scrollbar)) {
+ PaintButton(context, scrollbar,
+ BackButtonRect(scrollbar, kBackButtonStartPart),
+ kBackButtonStartPart);
+ PaintButton(context, scrollbar,
+ BackButtonRect(scrollbar, kBackButtonEndPart),
+ kBackButtonEndPart);
+ PaintButton(context, scrollbar,
+ ForwardButtonRect(scrollbar, kForwardButtonStartPart),
+ kForwardButtonStartPart);
+ PaintButton(context, scrollbar,
+ ForwardButtonRect(scrollbar, kForwardButtonEndPart),
+ kForwardButtonEndPart);
+ }
+
+ IntRect track_rect = TrackRect(scrollbar);
+ PaintTrackBackground(context, scrollbar, track_rect);
+
+ if (HasThumb(scrollbar)) {
+ IntRect start_track_rect;
+ IntRect thumb_rect;
+ IntRect end_track_rect;
+ SplitTrack(scrollbar, track_rect, start_track_rect, thumb_rect,
+ end_track_rect);
+ PaintTrackPiece(context, scrollbar, start_track_rect, kBackTrackPart);
+ PaintTrackPiece(context, scrollbar, end_track_rect, kForwardTrackPart);
}
}
-DisplayItem::Type ScrollbarTheme::TrackPiecePartToDisplayItemType(
- ScrollbarPart part) {
- switch (part) {
- case kBackTrackPart:
- return DisplayItem::kScrollbarBackTrack;
- case kForwardTrackPart:
- return DisplayItem::kScrollbarForwardTrack;
- default:
- NOTREACHED();
- return DisplayItem::kScrollbarBackTrack;
+void ScrollbarTheme::PaintTrackAndButtonsForCompositor(
+ GraphicsContext& context,
+ const Scrollbar& scrollbar) {
+ base::Optional<DrawingRecorder> recorder;
+ DCHECK(CreatesSingleDisplayItemForTrackAndButtons());
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ context, scrollbar, DisplayItem::kScrollbarTrackAndButtons))
+ return;
+ recorder.emplace(context, scrollbar, DisplayItem::kScrollbarTrackAndButtons);
+
+ // We paint compositor scrollbars in the space relative to the scrollbar's
+ // origin.
+ IntPoint offset = -scrollbar.Location();
+
+ if (HasButtons(scrollbar)) {
+ IntRect back_button_rect = BackButtonRect(scrollbar, kBackButtonStartPart);
+ back_button_rect.MoveBy(offset);
+ PaintButton(context, scrollbar, back_button_rect, kBackButtonStartPart);
+
+ IntRect forward_button_rect =
+ ForwardButtonRect(scrollbar, kForwardButtonEndPart);
+ forward_button_rect.MoveBy(offset);
+ PaintButton(context, scrollbar, forward_button_rect, kForwardButtonEndPart);
+
+ // Composited scrollbars don't have kBackButtonEndPart and
+ // kForwardButtonStartPart.
+ DCHECK(BackButtonRect(scrollbar, kBackButtonEndPart).IsEmpty());
+ DCHECK(ForwardButtonRect(scrollbar, kForwardButtonStartPart).IsEmpty());
+ }
+
+ IntRect track_rect = TrackRect(scrollbar);
+ track_rect.MoveBy(offset);
+ PaintTrackBackground(context, scrollbar, track_rect);
+
+ if (HasThumb(scrollbar)) {
+ // We don't repaint composited scrollbars on thumb position change, so
+ // the back track and forward track can't depend on thumb position. Just
+ // paint them on the whole track. All scrollbar themes for composited
+ // scrollbars know how to handle this case.
+ PaintTrackPiece(context, scrollbar, track_rect, kBackTrackPart);
+ PaintTrackPiece(context, scrollbar, track_rect, kForwardTrackPart);
}
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.h
index a47d221c175..cfe0407fa96 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme.h
@@ -48,13 +48,13 @@ class CORE_EXPORT ScrollbarTheme {
virtual ~ScrollbarTheme() = default;
// If true, then scrollbars with this theme will be painted every time
- // Scrollbar::setNeedsPaintInvalidation is called. If false, then only parts
+ // Scrollbar::SetNeedsPaintInvalidation is called. If false, then only parts
// which are explicitly invalidated will be repainted.
virtual bool ShouldRepaintAllPartsOnInvalidation() const { return true; }
virtual void UpdateEnabledState(const Scrollbar&) {}
- virtual bool Paint(const Scrollbar&, GraphicsContext&, const CullRect&);
+ void Paint(const Scrollbar&, GraphicsContext&, const CullRect&);
virtual ScrollbarPart HitTest(const Scrollbar&, const IntPoint&);
@@ -71,7 +71,6 @@ class CORE_EXPORT ScrollbarTheme {
return kWebScrollbarButtonsPlacementSingle;
}
- virtual bool SupportsControlTints() const { return false; }
virtual bool UsesOverlayScrollbars() const { return false; }
virtual void UpdateScrollbarOverlayColorTheme(const Scrollbar&) {}
@@ -83,11 +82,10 @@ class CORE_EXPORT ScrollbarTheme {
virtual bool ShouldDisableInvisibleScrollbars() const { return true; }
virtual bool InvalidateOnMouseEnterExit() { return false; }
- virtual bool InvalidateOnWindowActiveChange() const { return false; }
// Returns parts of the scrollbar which must be repainted following a change
// in the thumb position, given scroll positions before and after.
- virtual ScrollbarPart InvalidateOnThumbPositionChange(
+ virtual ScrollbarPart PartsToInvalidateOnThumbPositionChange(
const Scrollbar&,
float old_position,
float new_position) const {
@@ -114,6 +112,8 @@ class CORE_EXPORT ScrollbarTheme {
return false;
}
+ virtual bool SupportsDragSnapBack() const { return false; }
+
// The position of the thumb relative to the track.
int ThumbPosition(const Scrollbar& scrollbar) {
return ThumbPosition(scrollbar, scrollbar.CurrentPos());
@@ -136,13 +136,9 @@ class CORE_EXPORT ScrollbarTheme {
virtual bool HasButtons(const Scrollbar&) = 0;
virtual bool HasThumb(const Scrollbar&) = 0;
- virtual IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) = 0;
- virtual IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) = 0;
- virtual IntRect TrackRect(const Scrollbar&, bool painting = false) = 0;
+ virtual IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) = 0;
+ virtual IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) = 0;
+ virtual IntRect TrackRect(const Scrollbar&) = 0;
virtual IntRect ThumbRect(const Scrollbar&);
virtual int ThumbThickness(const Scrollbar&);
@@ -154,29 +150,9 @@ class CORE_EXPORT ScrollbarTheme {
IntRect& thumb,
IntRect& end_track);
- virtual void PaintScrollbarBackground(GraphicsContext&, const Scrollbar&) {}
- virtual void PaintTrackBackground(GraphicsContext&,
- const Scrollbar&,
- const IntRect&) {}
- virtual void PaintTrackPiece(GraphicsContext&,
- const Scrollbar&,
- const IntRect&,
- ScrollbarPart) {}
- virtual void PaintButton(GraphicsContext&,
- const Scrollbar&,
- const IntRect&,
- ScrollbarPart) {}
virtual void PaintThumb(GraphicsContext&, const Scrollbar&, const IntRect&) {}
- // Paint the thumb with ThumbOpacity() applied.
- virtual void PaintThumbWithOpacity(GraphicsContext& context,
- const Scrollbar& scrollbar,
- const IntRect& rect) {
- // By default this method just calls PaintThumb(). A theme with custom
- // ThumbOpacity() should override this method to apply the opacity.
- DCHECK_EQ(1.0f, ThumbOpacity(scrollbar));
- PaintThumb(context, scrollbar, rect);
- }
+ void PaintTrackAndButtonsForCompositor(GraphicsContext&, const Scrollbar&);
virtual int MaxOverlapBetweenPages() {
return std::numeric_limits<int>::max();
@@ -224,12 +200,37 @@ class CORE_EXPORT ScrollbarTheme {
protected:
virtual int TickmarkBorderWidth() { return 0; }
- static DisplayItem::Type ButtonPartToDisplayItemType(ScrollbarPart);
- static DisplayItem::Type TrackPiecePartToDisplayItemType(ScrollbarPart);
+ virtual void PaintScrollbarBackground(GraphicsContext&, const Scrollbar&) {}
+ virtual void PaintTrackBackground(GraphicsContext&,
+ const Scrollbar&,
+ const IntRect&) {}
+ virtual void PaintTrackPiece(GraphicsContext&,
+ const Scrollbar&,
+ const IntRect&,
+ ScrollbarPart) {}
+ virtual void PaintButton(GraphicsContext&,
+ const Scrollbar&,
+ const IntRect&,
+ ScrollbarPart) {}
+
+ void PaintTrackAndButtons(GraphicsContext&, const Scrollbar&);
+ virtual bool CreatesSingleDisplayItemForTrackAndButtons() const {
+ return true;
+ }
+
+ // Paint the thumb with ThumbOpacity() applied.
+ virtual void PaintThumbWithOpacity(GraphicsContext& context,
+ const Scrollbar& scrollbar,
+ const IntRect& rect) {
+ // By default this method just calls PaintThumb(). A theme with custom
+ // ThumbOpacity() should override this method to apply the opacity.
+ DCHECK_EQ(1.0f, ThumbOpacity(scrollbar));
+ PaintThumb(context, scrollbar, rect);
+ }
private:
- static ScrollbarTheme&
- NativeTheme(); // Must be implemented to return the correct theme subclass.
+ // Must be implemented to return the correct theme subclass.
+ static ScrollbarTheme& NativeTheme();
static bool g_mock_scrollbars_enabled_;
};
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
index 3befd2a1abc..f4f51699410 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h"
#include "build/build_config.h"
+#include "cc/input/scrollbar.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_rect.h"
@@ -147,6 +148,17 @@ ScrollbarTheme& ScrollbarTheme::NativeTheme() {
return theme;
}
+bool ScrollbarThemeAura::SupportsDragSnapBack() const {
+// Disable snapback on desktop Linux to better integrate with the desktop
+// behavior. Typically, Linux apps do not implement scrollbar snapback (this
+// is true for at least GTK and QT apps).
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ return false;
+#endif
+
+ return true;
+}
+
int ScrollbarThemeAura::ScrollbarThickness(ScrollbarControlSize control_size) {
// Horiz and Vert scrollbars are the same thickness.
// In unit tests we don't have the mock theme engine (because of layering
@@ -165,8 +177,7 @@ bool ScrollbarThemeAura::HasThumb(const Scrollbar& scrollbar) {
}
IntRect ScrollbarThemeAura::BackButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part,
- bool) {
+ ScrollbarPart part) {
// Windows and Linux just have single arrows.
if (part == kBackButtonEndPart)
return IntRect();
@@ -176,8 +187,7 @@ IntRect ScrollbarThemeAura::BackButtonRect(const Scrollbar& scrollbar,
}
IntRect ScrollbarThemeAura::ForwardButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part,
- bool) {
+ ScrollbarPart part) {
// Windows and Linux just have single arrows.
if (part == kForwardButtonStartPart)
return IntRect();
@@ -194,7 +204,7 @@ IntRect ScrollbarThemeAura::ForwardButtonRect(const Scrollbar& scrollbar,
return IntRect(x, y, size.Width(), size.Height());
}
-IntRect ScrollbarThemeAura::TrackRect(const Scrollbar& scrollbar, bool) {
+IntRect ScrollbarThemeAura::TrackRect(const Scrollbar& scrollbar) {
// The track occupies all space between the two buttons.
IntSize bs = ButtonSize(scrollbar);
if (scrollbar.Orientation() == kHorizontalScrollbar) {
@@ -236,14 +246,6 @@ void ScrollbarThemeAura::PaintTrackPiece(GraphicsContext& gc,
const Scrollbar& scrollbar,
const IntRect& rect,
ScrollbarPart part_type) {
- DisplayItem::Type display_item_type =
- TrackPiecePartToDisplayItemType(part_type);
- if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
- display_item_type))
- return;
-
- DrawingRecorder recorder(gc, scrollbar, display_item_type);
-
WebThemeEngine::State state = scrollbar.HoveredPart() == part_type
? WebThemeEngine::kStateHover
: WebThemeEngine::kStateNormal;
@@ -251,7 +253,7 @@ void ScrollbarThemeAura::PaintTrackPiece(GraphicsContext& gc,
if (UseMockTheme() && !scrollbar.Enabled())
state = WebThemeEngine::kStateDisabled;
- IntRect align_rect = TrackRect(scrollbar, false);
+ IntRect align_rect = TrackRect(scrollbar);
WebThemeEngine::ExtraParams extra_params;
extra_params.scrollbar_track.is_back = (part_type == kBackTrackPart);
extra_params.scrollbar_track.track_x = align_rect.X();
@@ -270,15 +272,10 @@ void ScrollbarThemeAura::PaintButton(GraphicsContext& gc,
const Scrollbar& scrollbar,
const IntRect& rect,
ScrollbarPart part) {
- DisplayItem::Type display_item_type = ButtonPartToDisplayItemType(part);
- if (DrawingRecorder::UseCachedDrawingIfPossible(gc, scrollbar,
- display_item_type))
- return;
PartPaintingParams params =
ButtonPartPaintingParams(scrollbar, scrollbar.CurrentPos(), part);
if (!params.should_paint)
return;
- DrawingRecorder recorder(gc, scrollbar, display_item_type);
WebThemeEngine::ExtraParams extra_params;
extra_params.scrollbar_button.zoom = scrollbar.EffectiveZoom();
@@ -320,7 +317,7 @@ bool ScrollbarThemeAura::ShouldRepaintAllPartsOnInvalidation() const {
return false;
}
-ScrollbarPart ScrollbarThemeAura::InvalidateOnThumbPositionChange(
+ScrollbarPart ScrollbarThemeAura::PartsToInvalidateOnThumbPositionChange(
const Scrollbar& scrollbar,
float old_position,
float new_position) const {
@@ -350,27 +347,15 @@ bool ScrollbarThemeAura::ShouldCenterOnThumb(const Scrollbar& scrollbar,
bool ScrollbarThemeAura::ShouldSnapBackToDragOrigin(
const Scrollbar& scrollbar,
const WebMouseEvent& event) {
-// Disable snapback on desktop Linux to better integrate with the desktop
-// behavior. Typically, Linux apps do not implement scrollbar snapback (this is
-// true for at least GTK and QT apps).
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS))
- return false;
-#endif
+ if (!SupportsDragSnapBack())
+ return false;
// There is a drag rect around the scrollbar outside of which the scrollbar
// thumb should snap back to its origin. This rect is infinitely large in
// the scrollbar's scrolling direction and an expansion of the scrollbar's
- // width or height in the non-scrolling direction.
-
- // Constants used to figure the how far out in the non-scrolling direction
- // should trigger the thumb to snap back to its origin. These calculations
- // are based on observing the behavior of the MSVC8 main window scrollbar +
- // some guessing/extrapolation.
- static const int kOffSideMultiplier = 8;
- static const int kDefaultWinScrollbarThickness = 17;
-
- // As only one axis triggers snapping back, the code below only uses the
- // thickness of the scrollbar for its calculations.
+ // width or height in the non-scrolling direction. As only one axis triggers
+ // snapping back, the code below only uses the thickness of the scrollbar for
+ // its calculations.
bool is_horizontal = scrollbar.Orientation() == kHorizontalScrollbar;
int thickness = is_horizontal ? TrackRect(scrollbar).Height()
: TrackRect(scrollbar).Width();
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
index 61188a174b2..27eab942320 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_aura.h
@@ -44,13 +44,9 @@ class CORE_EXPORT ScrollbarThemeAura : public ScrollbarTheme {
bool HasButtons(const Scrollbar&) override { return true; }
bool HasThumb(const Scrollbar&) override;
- IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect TrackRect(const Scrollbar&, bool painting = false) override;
+ IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect TrackRect(const Scrollbar&) override;
int MinimumThumbLength(const Scrollbar&) override;
void PaintTrackBackground(GraphicsContext&,
@@ -67,12 +63,17 @@ class CORE_EXPORT ScrollbarThemeAura : public ScrollbarTheme {
void PaintThumb(GraphicsContext&, const Scrollbar&, const IntRect&) override;
bool ShouldRepaintAllPartsOnInvalidation() const override;
- ScrollbarPart InvalidateOnThumbPositionChange(
+ ScrollbarPart PartsToInvalidateOnThumbPositionChange(
const Scrollbar&,
float old_position,
float new_position) const override;
bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&) override;
+
+ // During a thumb drag, if the pointer moves outside a certain threshold in
+ // the non-scrolling direction, the scroller is expected to "snap back" to the
+ // location where the drag first originated from.
+ bool SupportsDragSnapBack() const override;
bool ShouldSnapBackToDragOrigin(const Scrollbar&,
const WebMouseEvent&) override;
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
index 0365d27af36..69fdd4f8b56 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mac.h
@@ -44,8 +44,6 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
void RegisterScrollbar(Scrollbar&) override;
- bool SupportsControlTints() const override { return true; }
-
// On Mac, the painting code itself animates the opacity so there's no need
// to disable in order to make the scrollbars invisible. In fact,
// disabling/enabling causes invalidations which can cause endless loops as
@@ -62,7 +60,7 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&) override;
bool ShouldRepaintAllPartsOnInvalidation() const override { return false; }
- ScrollbarPart InvalidateOnThumbPositionChange(
+ ScrollbarPart PartsToInvalidateOnThumbPositionChange(
const Scrollbar&,
float old_position,
float new_position) const override;
@@ -75,9 +73,6 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
void SetNewPainterForScrollbar(Scrollbar&, ScrollbarPainter);
ScrollbarPainter PainterForScrollbar(const Scrollbar&) const;
- void PaintTrackBackground(GraphicsContext&,
- const Scrollbar&,
- const IntRect&) override;
void PaintThumb(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) override {
@@ -110,13 +105,9 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
virtual void UpdateButtonPlacement(WebScrollbarButtonsPlacement) {}
- IntRect TrackRect(const Scrollbar&, bool painting = false) override;
- IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
+ IntRect TrackRect(const Scrollbar&) override;
+ IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) override;
bool HasButtons(const Scrollbar&) override { return false; }
bool HasThumb(const Scrollbar&) override;
@@ -125,6 +116,9 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
int TickmarkBorderWidth() override { return 1; }
+ void PaintTrackBackground(GraphicsContext&,
+ const Scrollbar&,
+ const IntRect&) override;
void PaintThumbInternal(GraphicsContext&,
const Scrollbar&,
const IntRect&,
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 b1bdc89a705..afbc53a13ec 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
@@ -201,7 +201,7 @@ int ScrollbarThemeMac::ScrollbarPartToHIPressedState(ScrollbarPart part) {
}
}
-ScrollbarPart ScrollbarThemeMac::InvalidateOnThumbPositionChange(
+ScrollbarPart ScrollbarThemeMac::PartsToInvalidateOnThumbPositionChange(
const Scrollbar& scrollbar,
float old_position,
float new_position) const {
@@ -250,13 +250,6 @@ ScrollbarPainter ScrollbarThemeMac::PainterForScrollbar(
void ScrollbarThemeMac::PaintTrackBackground(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) {
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, scrollbar, DisplayItem::kScrollbarTrackBackground))
- return;
-
- DrawingRecorder recorder(context, scrollbar,
- DisplayItem::kScrollbarTrackBackground);
-
GraphicsContextStateSaver state_saver(context);
context.Translate(rect.X(), rect.Y());
LocalCurrentGraphicsContext local_context(context,
@@ -381,21 +374,18 @@ bool ScrollbarThemeMac::HasThumb(const Scrollbar& scrollbar) {
}
IntRect ScrollbarThemeMac::BackButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part,
- bool painting) {
+ ScrollbarPart part) {
DCHECK_EQ(ButtonsPlacement(), kWebScrollbarButtonsPlacementNone);
return IntRect();
}
IntRect ScrollbarThemeMac::ForwardButtonRect(const Scrollbar& scrollbar,
- ScrollbarPart part,
- bool painting) {
+ ScrollbarPart part) {
DCHECK_EQ(ButtonsPlacement(), kWebScrollbarButtonsPlacementNone);
return IntRect();
}
-IntRect ScrollbarThemeMac::TrackRect(const Scrollbar& scrollbar,
- bool painting) {
+IntRect ScrollbarThemeMac::TrackRect(const Scrollbar& scrollbar) {
DCHECK(!HasButtons(scrollbar));
return scrollbar.FrameRect();
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.cc
index 83d2f6c5a15..d52cfb61b40 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.cc
@@ -42,19 +42,13 @@ bool ScrollbarThemeMock::UsesOverlayScrollbars() const {
return RuntimeEnabledFeatures::OverlayScrollbarsEnabled();
}
-IntRect ScrollbarThemeMock::TrackRect(const Scrollbar& scrollbar, bool) {
+IntRect ScrollbarThemeMock::TrackRect(const Scrollbar& scrollbar) {
return scrollbar.FrameRect();
}
void ScrollbarThemeMock::PaintTrackBackground(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& track_rect) {
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, scrollbar, DisplayItem::kScrollbarTrackBackground))
- return;
-
- DrawingRecorder recorder(context, scrollbar,
- DisplayItem::kScrollbarTrackBackground);
context.FillRect(track_rect,
scrollbar.Enabled() ? Color::kLightGray : Color(0xFFE0E0E0));
}
@@ -77,11 +71,11 @@ void ScrollbarThemeMock::PaintScrollCorner(GraphicsContext& context,
const DisplayItemClient& scrollbar,
const IntRect& corner_rect,
WebColorScheme color_scheme) {
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- context, scrollbar, DisplayItem::kScrollbarCorner))
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, scrollbar,
+ DisplayItem::kScrollCorner))
return;
- DrawingRecorder recorder(context, scrollbar, DisplayItem::kScrollbarCorner);
+ DrawingRecorder recorder(context, scrollbar, DisplayItem::kScrollCorner);
context.FillRect(corner_rect, Color::kWhite);
}
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.h
index d869f786576..6304e95683d 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_mock.h
@@ -41,17 +41,13 @@ class CORE_EXPORT ScrollbarThemeMock : public ScrollbarTheme {
bool HasButtons(const Scrollbar&) override { return false; }
bool HasThumb(const Scrollbar&) override { return true; }
- IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool /*painting*/ = false) override {
+ IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) override {
return IntRect();
}
- IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool /*painting*/ = false) override {
+ IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) override {
return IntRect();
}
- IntRect TrackRect(const Scrollbar&, bool painting = false) override;
+ IntRect TrackRect(const Scrollbar&) override;
void PaintTrackBackground(GraphicsContext&,
const Scrollbar&,
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.cc b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.cc
index f4421ea27cb..5dc4d9b7157 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.cc
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.cc
@@ -47,6 +47,7 @@ ScrollbarThemeOverlay::ScrollbarThemeOverlay(int thumb_thickness,
scrollbar_margin_(scrollbar_margin),
allow_hit_test_(allow_hit_test),
color_(color),
+ is_mobile_theme_(false),
use_solid_color_(true) {}
ScrollbarThemeOverlay::ScrollbarThemeOverlay(int thumb_thickness,
@@ -56,13 +57,14 @@ ScrollbarThemeOverlay::ScrollbarThemeOverlay(int thumb_thickness,
thumb_thickness_(thumb_thickness),
scrollbar_margin_(scrollbar_margin),
allow_hit_test_(allow_hit_test),
+ is_mobile_theme_(false),
use_solid_color_(false) {}
bool ScrollbarThemeOverlay::ShouldRepaintAllPartsOnInvalidation() const {
return false;
}
-ScrollbarPart ScrollbarThemeOverlay::InvalidateOnThumbPositionChange(
+ScrollbarPart ScrollbarThemeOverlay::PartsToInvalidateOnThumbPositionChange(
const Scrollbar&,
float old_position,
float new_position) const {
@@ -121,19 +123,16 @@ bool ScrollbarThemeOverlay::HasThumb(const Scrollbar& scrollbar) {
return true;
}
-IntRect ScrollbarThemeOverlay::BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool) {
+IntRect ScrollbarThemeOverlay::BackButtonRect(const Scrollbar&, ScrollbarPart) {
return IntRect();
}
IntRect ScrollbarThemeOverlay::ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool) {
+ ScrollbarPart) {
return IntRect();
}
-IntRect ScrollbarThemeOverlay::TrackRect(const Scrollbar& scrollbar, bool) {
+IntRect ScrollbarThemeOverlay::TrackRect(const Scrollbar& scrollbar) {
IntRect rect = scrollbar.FrameRect();
if (scrollbar.Orientation() == kHorizontalScrollbar)
rect.InflateX(-scrollbar_margin_);
diff --git a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h
index 7ab2f4ad606..950d47d1091 100644
--- a/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h
+++ b/chromium/third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h
@@ -48,7 +48,7 @@ class CORE_EXPORT ScrollbarThemeOverlay : public ScrollbarTheme {
bool ShouldRepaintAllPartsOnInvalidation() const override;
- ScrollbarPart InvalidateOnThumbPositionChange(
+ ScrollbarPart PartsToInvalidateOnThumbPositionChange(
const Scrollbar&,
float old_position,
float new_position) const override;
@@ -64,13 +64,9 @@ class CORE_EXPORT ScrollbarThemeOverlay : public ScrollbarTheme {
bool HasButtons(const Scrollbar&) override { return false; }
bool HasThumb(const Scrollbar&) override;
- IntRect BackButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect ForwardButtonRect(const Scrollbar&,
- ScrollbarPart,
- bool painting = false) override;
- IntRect TrackRect(const Scrollbar&, bool painting = false) override;
+ IntRect BackButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect ForwardButtonRect(const Scrollbar&, ScrollbarPart) override;
+ IntRect TrackRect(const Scrollbar&) override;
int ThumbThickness(const Scrollbar&) override;
int ThumbThickness() { return thumb_thickness_; }
diff --git a/chromium/third_party/blink/renderer/core/streams/BUILD.gn b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
index e747d5e73ac..0b7a70071d4 100644
--- a/chromium/third_party/blink/renderer/core/streams/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/streams/BUILD.gn
@@ -27,12 +27,8 @@ blink_core_sources("streams") {
"readable_stream_default_reader.h",
"readable_stream_native.cc",
"readable_stream_native.h",
- "readable_stream_operations.cc",
- "readable_stream_operations.h",
"readable_stream_reader.cc",
"readable_stream_reader.h",
- "readable_stream_wrapper.cc",
- "readable_stream_wrapper.h",
"stream_algorithms.h",
"stream_promise_resolver.cc",
"stream_promise_resolver.h",
@@ -43,13 +39,9 @@ blink_core_sources("streams") {
"transform_stream_default_controller.cc",
"transform_stream_default_controller.h",
"transform_stream_default_controller_interface.h",
- "transform_stream_default_controller_wrapper.cc",
- "transform_stream_default_controller_wrapper.h",
"transform_stream_native.cc",
"transform_stream_native.h",
"transform_stream_transformer.h",
- "transform_stream_wrapper.cc",
- "transform_stream_wrapper.h",
"underlying_sink_base.h",
"underlying_source_base.cc",
"underlying_source_base.h",
@@ -63,7 +55,5 @@ blink_core_sources("streams") {
"writable_stream_default_writer.h",
"writable_stream_native.cc",
"writable_stream_native.h",
- "writable_stream_wrapper.cc",
- "writable_stream_wrapper.h",
]
}
diff --git a/chromium/third_party/blink/renderer/core/streams/ByteLengthQueuingStrategy.js b/chromium/third_party/blink/renderer/core/streams/ByteLengthQueuingStrategy.js
deleted file mode 100644
index f0a2771cd90..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/ByteLengthQueuingStrategy.js
+++ /dev/null
@@ -1,31 +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.
-
-// eslint-disable-next-line no-unused-vars
-(function(global, binding, v8) {
- 'use strict';
-
- const defineProperty = global.Object.defineProperty;
-
- class ByteLengthQueuingStrategy {
- constructor(options) {
- defineProperty(this, 'highWaterMark', {
- value: options.highWaterMark,
- enumerable: true,
- configurable: true,
- writable: true
- });
- }
- size(chunk) {
- return chunk.byteLength;
- }
- }
-
- defineProperty(global, 'ByteLengthQueuingStrategy', {
- value: ByteLengthQueuingStrategy,
- enumerable: false,
- configurable: true,
- writable: true
- });
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/CommonOperations.js b/chromium/third_party/blink/renderer/core/streams/CommonOperations.js
deleted file mode 100644
index 24dc719f2be..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/CommonOperations.js
+++ /dev/null
@@ -1,624 +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.
-
-// Implementation of functions that are shared between ReadableStream and
-// WritableStream.
-
-(function(global, binding, v8) {
- 'use strict';
-
- // Common private symbols. These correspond directly to internal slots in the
- // standard. "[[X]]" in the standard is spelt _X here.
- const _queue = v8.createPrivateSymbol('[[queue]]');
- const _queueTotalSize = v8.createPrivateSymbol('[[queueTotalSize]]');
-
- // A symbol to protect against double-resolution of promises. This
- // functionality is not explicit in the standard, but is implied in the way
- // the operations are defined.
- const _isSettled = v8.createPrivateSymbol('isSettled');
-
- // Javascript functions. It is important to use these copies for security and
- // robustness. See "V8 Extras Design Doc", section "Security Considerations".
- // https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA8Ec0/edit#heading=h.9yixony1a18r
- const Boolean = global.Boolean;
- const Number = global.Number;
- const Number_isFinite = Number.isFinite;
- const Number_isNaN = Number.isNaN;
-
- const RangeError = global.RangeError;
- const TypeError = global.TypeError;
- const TypeError_prototype = TypeError.prototype;
-
- const hasOwnProperty = v8.uncurryThis(global.Object.hasOwnProperty);
- const getPrototypeOf = global.Object.getPrototypeOf.bind(global.Object);
- const getOwnPropertyDescriptor =
- global.Object.getOwnPropertyDescriptor.bind(global.Object);
-
- const thenPromise = v8.uncurryThis(Promise.prototype.then);
-
- const JSON_parse = global.JSON.parse.bind(global.JSON);
- const JSON_stringify = global.JSON.stringify.bind(global.JSON);
-
- function hasOwnPropertyNoThrow(x, property) {
- // The cast of |x| to Boolean will eliminate undefined and null, which would
- // cause hasOwnProperty to throw a TypeError, as well as some other values
- // that can't be objects and so will fail the check anyway.
- return Boolean(x) && hasOwnProperty(x, property);
- }
-
- //
- // Assert is not normally enabled, to avoid the space and time overhead. To
- // enable, uncomment this definition and then in the file you wish to enable
- // asserts for, uncomment the assert statements and add this definition:
- // const assert = pred => binding.SimpleAssert(pred);
- //
- // binding.SimpleAssert = pred => {
- // if (pred) {
- // return;
- // }
- // v8.log('\n\n\n *** ASSERTION FAILURE ***\n\n');
- // v8.logStackTrace();
- // v8.log('**************************************************\n\n');
- // class StreamsAssertionError extends Error {}
- // throw new StreamsAssertionError('Streams Assertion Failure');
- // };
-
- //
- // Promise-manipulation functions
- //
-
- // Not exported.
- function streamInternalError() {
- throw new RangeError('Stream API Internal Error');
- }
-
- // For safety, this must always be used in place of calling v8.createPromise()
- // directly.
- function createPromise() {
- const p = v8.createPromise();
- p[_isSettled] = false;
- return p;
- }
-
- // Calling v8.rejectPromise() directly is very dangerous. Always use this
- // wrapper.
- function rejectPromise(p, reason) {
- if (!v8.isPromise(p)) {
- streamInternalError();
- }
-
- // assert(typeof p[_isSettled] === 'boolean',
- // 'Type(p.[[isSettled]]) is `"boolean"`');
-
- // Note that this makes the function a no-op for promises that were not
- // created via createPromise(). This is critical for security.
- if (p[_isSettled] !== false) {
- return;
- }
- p[_isSettled] = true;
-
- v8.rejectPromise(p, reason);
- }
-
- // This must always be used instead of Promise.reject().
- function createRejectedPromise(reason) {
- const p = createPromise();
- rejectPromise(p, reason);
- return p;
- }
-
- // Calling v8.resolvePromise() directly is very dangerous. Always use this
- // wrapper. If |value| is an object this will look up Object.prototype.then
- // and so may be re-entrant.
- function resolvePromise(p, value) {
- if (!v8.isPromise(p)) {
- streamInternalError();
- }
-
- // assert(typeof p[_isSettled] === 'boolean',
- // 'Type(p.[[isSettled]]) is `"boolean"`');
-
- // Note that this makes the function a no-op for promises that were not
- // created via createPromise(). This is critical for security.
- if (p[_isSettled] !== false) {
- return;
- }
- p[_isSettled] = true;
-
- v8.resolvePromise(p, value);
- }
-
- // This must always be used instead of Promise.resolve(). If |value| is an
- // object this will look up Object.prototype.then and so may be re-entrant.
- function createResolvedPromise(value) {
- if (v8.isPromise(value)) {
- // This case applies when an underlying method returns a promise. Promises
- // that are passed through in this way are not used with resolvePromise()
- // or rejectPromise().
- return value;
- }
- const p = createPromise();
- resolvePromise(p, value);
- return p;
- }
-
- function markPromiseAsHandled(p) {
- if (!v8.isPromise(p)) {
- streamInternalError();
- }
- v8.markPromiseAsHandled(p);
- }
-
- function promiseState(p) {
- if (!v8.isPromise(p)) {
- streamInternalError();
- }
- return v8.promiseState(p);
- }
-
- //
- // Queue-with-Sizes Operations
- //
- function DequeueValue(container) {
- // assert(
- // hasOwnProperty(container, _queue) &&
- // hasOwnProperty(container, _queueTotalSize),
- // '_container_ has [[queue]] and [[queueTotalSize]] internal slots.');
- // assert(container[_queue].length !== 0,
- // '_container_.[[queue]] is not empty.');
- const pair = container[_queue].shift();
- container[_queueTotalSize] -= pair.size;
- if (container[_queueTotalSize] < 0) {
- container[_queueTotalSize] = 0;
- }
- return pair.value;
- }
-
- function EnqueueValueWithSize(container, value, size) {
- // assert(
- // hasOwnProperty(container, _queue) &&
- // hasOwnProperty(container, _queueTotalSize),
- // '_container_ has [[queue]] and [[queueTotalSize]] internal 'slots.');
- size = Number(size);
- if (!IsFiniteNonNegativeNumber(size)) {
- throw new RangeError(binding.streamErrors.invalidSize);
- }
-
- container[_queue].push({value, size});
- container[_queueTotalSize] += size;
- }
-
- function PeekQueueValue(container) {
- // assert(
- // hasOwnProperty(container, _queue) &&
- // hasOwnProperty(container, _queueTotalSize),
- // '_container_ has [[queue]] and [[queueTotalSize]] internal slots.');
- // assert(container[_queue].length !== 0,
- // '_container_.[[queue]] is not empty.');
- const pair = container[_queue].peek();
- return pair.value;
- }
-
- function ResetQueue(container) {
- // assert(
- // hasOwnProperty(container, _queue) &&
- // hasOwnProperty(container, _queueTotalSize),
- // '_container_ has [[queue]] and [[queueTotalSize]] internal slots.');
- container[_queue] = new binding.SimpleQueue();
- container[_queueTotalSize] = 0;
- }
-
- // Not exported.
- function IsFiniteNonNegativeNumber(v) {
- return Number_isFinite(v) && v >= 0;
- }
-
- function ValidateAndNormalizeHighWaterMark(highWaterMark) {
- highWaterMark = Number(highWaterMark);
- if (Number_isNaN(highWaterMark)) {
- throw new RangeError(binding.streamErrors.invalidHWM);
- }
- if (highWaterMark < 0) {
- throw new RangeError(binding.streamErrors.invalidHWM);
- }
- return highWaterMark;
- }
-
- // Unlike the version in the standard, this implementation returns the
- // original function as-is if it is set. This means users of the return value
- // need to be careful to explicitly set |this| when calling it.
- function MakeSizeAlgorithmFromSizeFunction(size) {
- if (size === undefined) {
- return () => 1;
- }
-
- if (typeof size !== 'function') {
- throw new TypeError(binding.streamErrors.sizeNotAFunction);
- }
-
- return size;
- }
-
- //
- // Invoking functions.
- // These differ from the Invoke versions in the spec in that they take a fixed
- // number of arguments rather than a list, and also take a name to be used for
- // the function on error.
- //
-
- // Internal utility functions. Not exported.
- const callFunction = v8.uncurryThis(global.Function.prototype.call);
- const errTmplMustBeFunctionOrUndefined = name =>
- `${name} must be a function or undefined`;
- const Function_bind = v8.uncurryThis(global.Function.prototype.bind);
-
- function resolveMethod(O, P, nameForError) {
- const method = O[P];
-
- if (typeof method !== 'function' && typeof method !== 'undefined') {
- throw new TypeError(errTmplMustBeFunctionOrUndefined(nameForError));
- }
-
- return method;
- }
-
- function CreateAlgorithmFromUnderlyingMethod(
- underlyingObject, methodName, algoArgCount, methodNameForError) {
- // assert(underlyingObject !== undefined,
- // 'underlyingObject is not undefined.');
- // assert(IsPropertyKey(methodName),
- // '! IsPropertyKey(methodName) is true.');
- // assert(algoArgCount === 0 || algoArgCount === 1,
- // 'algoArgCount is 0 or 1.');
- // assert(
- // typeof methodNameForError === 'string',
- // 'methodNameForError is a string');
- const method =
- resolveMethod(underlyingObject, methodName, methodNameForError);
- // The implementation uses bound functions rather than lambdas where
- // possible to give the compiler the maximum opportunity to optimise.
- if (method === undefined) {
- return () => createResolvedPromise();
- }
-
- if (algoArgCount === 0) {
- return Function_bind(PromiseCall0, undefined, method, underlyingObject);
- }
-
- return Function_bind(PromiseCall1, undefined, method, underlyingObject);
- }
-
- function CreateAlgorithmFromUnderlyingMethodPassingController(
- underlyingObject, methodName, algoArgCount, controller,
- methodNameForError) {
- // assert(underlyingObject !== undefined,
- // 'underlyingObject is not undefined.');
- // assert(IsPropertyKey(methodName),
- // '! IsPropertyKey(methodName) is true.');
- // assert(algoArgCount === 0 || algoArgCount === 1,
- // 'algoArgCount is 0 or 1.');
- // assert(typeof controller === 'object', 'controller is an object');
- // assert(
- // typeof methodNameForError === 'string',
- // 'methodNameForError is a string');
- const method =
- resolveMethod(underlyingObject, methodName, methodNameForError);
- if (method === undefined) {
- return () => createResolvedPromise();
- }
-
- if (algoArgCount === 0) {
- return Function_bind(
- PromiseCall1, undefined, method, underlyingObject, controller);
- }
-
- return arg => PromiseCall2(method, underlyingObject, arg, controller);
- }
-
- // Modified from InvokeOrNoop in spec. Takes 1 argument.
- function CallOrNoop1(O, P, arg0, nameForError) {
- const method = resolveMethod(O, P, nameForError);
- if (method === undefined) {
- return undefined;
- }
-
- return callFunction(method, O, arg0);
- }
-
- function PromiseCall0(F, V) {
- // assert(typeof F === 'function', 'IsCallable(F) is true.');
- // assert(V !== undefined, 'V is not undefined.');
- try {
- return createResolvedPromise(callFunction(F, V));
- } catch (e) {
- return createRejectedPromise(e);
- }
- }
-
- function PromiseCall1(F, V, arg0) {
- // assert(typeof F === 'function', 'IsCallable(F) is true.');
- // assert(V !== undefined, 'V is not undefined.');
- try {
- return createResolvedPromise(callFunction(F, V, arg0));
- } catch (e) {
- return createRejectedPromise(e);
- }
- }
-
- function PromiseCall2(F, V, arg0, arg1) {
- // assert(typeof F === 'function', 'IsCallable(F) is true.');
- // assert(V !== undefined, 'V is not undefined.');
- try {
- return createResolvedPromise(callFunction(F, V, arg0, arg1));
- } catch (e) {
- return createRejectedPromise(e);
- }
- }
-
- // Functions for transferable streams. See design doc
- // https://docs.google.com/document/d/1_KuZzg5c3pncLJPFa8SuVm23AP4tft6mzPCL5at3I9M/edit
-
- const kPull = 1;
- const kCancel = 2;
- const kChunk = 3;
- const kClose = 4;
- const kAbort = 5;
- const kError = 6;
-
- function isATypeError(object) {
- // There doesn't appear to be a 100% reliable way to identify a TypeError
- // from JS.
- return object !== null && getPrototypeOf(object) === TypeError_prototype;
- }
-
- function isADOMException(object) {
- try {
- callFunction(binding.DOMException_name_get, object);
- return true;
- } catch (e) {
- return false;
- }
- }
-
- // We'd like to able to transfer TypeError exceptions, but we can't, so we
- // hack around it. packReason() is guaranteed not to throw and the object
- // produced is guaranteed to be serializable by postMessage().
- function packReason(reason) {
- switch (typeof reason) {
- case 'string':
- case 'number':
- case 'boolean':
- return {encoder: 'json', string: JSON_stringify(reason)};
-
- case 'object':
- try {
- if (isATypeError(reason)) {
- // "message" on TypeError is a normal property, meaning that if it
- // is set, it is set on the object itself. We can take advantage of
- // this to avoid executing user JavaScript in the case when the
- // TypeError was generated internally.
- let message;
- const descriptor = getOwnPropertyDescriptor(reason, 'message');
- if (descriptor) {
- message = descriptor.value;
- if (typeof message !== 'string') {
- message = undefined;
- }
- }
- return {encoder: 'typeerror', string: message};
- }
-
- if (isADOMException(reason)) {
- const message =
- callFunction(binding.DOMException_message_get, reason);
- const name = callFunction(binding.DOMException_name_get, reason);
- return {
- encoder: 'domexception',
- string: JSON_stringify({message, name})
- };
- }
-
- // JSON_stringify() is lossy, but it will serialise things that
- // postMessage() won't.
- return {encoder: 'json', string: JSON_stringify(reason)};
- } catch (e) {
- return {encoder: 'typeerror', string: 'Cannot transfer message'};
- }
-
- default:
- return {encoder: 'undefined', string: undefined};
- }
- }
-
- function unpackReason(packedReason) {
- const {encoder, string} = packedReason;
- switch (encoder) {
- case 'json':
- return JSON_parse(string);
-
- case 'typeerror':
- return new TypeError(string);
-
- case 'domexception':
- const {message, name} = JSON_parse(string);
- return new binding.DOMException(message, name);
-
- case 'undefined':
- return undefined;
- }
- }
-
- function CreateCrossRealmTransformWritable(port) {
- let backpressurePromise = createPromise();
-
- callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
- const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
- // assert(type === kPull || type === kCancel || type === kError);
- switch (type) {
- case kPull:
- // assert(backPressurePromise !== undefined);
- resolvePromise(backpressurePromise);
- backpressurePromise = undefined;
- break;
-
- case kCancel:
- case kError:
- binding.WritableStreamDefaultControllerErrorIfNeeded(
- controller, unpackReason(value));
- if (backpressurePromise !== undefined) {
- resolvePromise(backpressurePromise);
- backpressurePromise = undefined;
- }
- break;
- }
- });
-
- callFunction(
- binding.EventTarget_addEventListener, port, 'messageerror', () => {
- const error = new binding.DOMException('chunk could not be cloned',
- 'DataCloneError');
- callFunction(binding.MessagePort_postMessage, port,
- {type: kError, value: packReason(error)});
- callFunction(binding.MessagePort_close, port);
- binding.WritableStreamDefaultControllerErrorIfNeeded(controller,
- error);
- });
-
- callFunction(binding.MessagePort_start, port);
-
- function doWrite(chunk) {
- backpressurePromise = createPromise();
- try {
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kChunk, value: chunk});
- } catch (e) {
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kError, value: packReason(e)});
- callFunction(binding.MessagePort_close, port);
- throw e;
- }
- }
-
- const stream = binding.CreateWritableStream(
- () => undefined,
- chunk => {
- if (!backpressurePromise) {
- return PromiseCall1(doWrite, null, chunk);
- }
- return thenPromise(backpressurePromise, () => doWrite(chunk));
- },
- () => {
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kClose, value: undefined});
- callFunction(binding.MessagePort_close, port);
- return createResolvedPromise();
- },
- reason => {
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kAbort, value: packReason(reason)});
- callFunction(binding.MessagePort_close, port);
- return createResolvedPromise();
- });
-
- const controller = binding.getWritableStreamController(stream);
- return stream;
- }
-
- function CreateCrossRealmTransformReadable(port) {
- let backpressurePromise = createPromise();
- let finished = false;
-
- callFunction(binding.EventTarget_addEventListener, port, 'message', evt => {
- const {type, value} = callFunction(binding.MessageEvent_data_get, evt);
- // assert(type === kChunk || type === kClose || type === kAbort ||
- // type=kError);
- if (finished) {
- return;
- }
- switch (type) {
- case kChunk:
- binding.ReadableStreamDefaultControllerEnqueue(controller, value);
- resolvePromise(backpressurePromise);
- backpressurePromise = createPromise();
- break;
-
- case kClose:
- finished = true;
- binding.ReadableStreamDefaultControllerClose(controller);
- callFunction(binding.MessagePort_close, port);
- break;
-
- case kAbort:
- case kError:
- finished = true;
- binding.ReadableStreamDefaultControllerError(
- controller, unpackReason(value));
- callFunction(binding.MessagePort_close, port);
- break;
- }
- });
-
- callFunction(
- binding.EventTarget_addEventListener, port, 'messageerror', () => {
- const error = new binding.DOMException('chunk could not be cloned',
- 'DataCloneError');
- callFunction(binding.MessagePort_postMessage, port,
- {type: kError, value: packReason(error)});
- callFunction(binding.MessagePort_close, port);
- binding.ReadableStreamDefaultControllerError(controller, error);
- });
-
- callFunction(binding.MessagePort_start, port);
-
- const stream = binding.CreateReadableStream(
- () => undefined,
- () => {
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kPull, value: undefined});
- return backpressurePromise;
- },
- reason => {
- finished = true;
- callFunction(
- binding.MessagePort_postMessage, port,
- {type: kCancel, value: packReason(reason)});
- callFunction(binding.MessagePort_close, port);
- return createResolvedPromise();
- },
- /* highWaterMark = */ 0);
-
- const controller = binding.getReadableStreamController(stream);
- return stream;
- }
-
- binding.streamOperations = {
- _queue,
- _queueTotalSize,
- createPromise,
- createRejectedPromise,
- createResolvedPromise,
- hasOwnPropertyNoThrow,
- rejectPromise,
- resolvePromise,
- markPromiseAsHandled,
- promiseState,
- CreateAlgorithmFromUnderlyingMethod,
- CreateAlgorithmFromUnderlyingMethodPassingController,
- CreateCrossRealmTransformWritable,
- CreateCrossRealmTransformReadable,
- DequeueValue,
- EnqueueValueWithSize,
- PeekQueueValue,
- ResetQueue,
- ValidateAndNormalizeHighWaterMark,
- MakeSizeAlgorithmFromSizeFunction,
- CallOrNoop1,
- PromiseCall2
- };
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/CommonStrings.js b/chromium/third_party/blink/renderer/core/streams/CommonStrings.js
deleted file mode 100644
index 72395d75113..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/CommonStrings.js
+++ /dev/null
@@ -1,24 +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.
-
-// User-visible strings shared between ReadableStream and WritableStream.
-
-// eslint-disable-next-line no-unused-vars
-(function(global, binding, v8) {
- 'use strict';
-
- binding.streamErrors = {
- cannotTransferLockedStream: 'Cannot transfer a locked stream',
- cannotTransferContext: 'Cannot transfer from this context',
- illegalInvocation: 'Illegal invocation',
- illegalConstructor: 'Illegal constructor',
- invalidType: 'Invalid type is specified',
- invalidSize: 'The return value of a queuing strategy\'s size function ' +
- 'must be a finite, non-NaN, non-negative number',
- sizeNotAFunction: 'A queuing strategy\'s size property must be a function',
- invalidHWM:
- 'A queueing strategy\'s highWaterMark property must be a nonnegative, ' +
- 'non-NaN number',
- };
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/CountQueuingStrategy.js b/chromium/third_party/blink/renderer/core/streams/CountQueuingStrategy.js
deleted file mode 100644
index 93147c6060a..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/CountQueuingStrategy.js
+++ /dev/null
@@ -1,47 +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.
-
-// eslint-disable-next-line no-unused-vars
-(function(global, binding, v8) {
- 'use strict';
-
- const defineProperty = global.Object.defineProperty;
-
- class CountQueuingStrategy {
- constructor(options) {
- defineProperty(this, 'highWaterMark', {
- value: options.highWaterMark,
- enumerable: true,
- configurable: true,
- writable: true
- });
- }
-
- size() {
- return 1;
- }
- }
-
- defineProperty(global, 'CountQueuingStrategy', {
- value: CountQueuingStrategy,
- enumerable: false,
- configurable: true,
- writable: true
- });
-
- // Export a separate copy that doesn't need options objects and can't be
- // interfered with.
- class BuiltInCountQueuingStrategy {
- constructor(highWaterMark) {
- defineProperty(this, 'highWaterMark', {value: highWaterMark});
- }
-
- size() {
- return 1;
- }
- }
-
- binding.createBuiltInCountQueuingStrategy = highWaterMark =>
- new BuiltInCountQueuingStrategy(highWaterMark);
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/README.md b/chromium/third_party/blink/renderer/core/streams/README.md
index 1b845c20ec1..cdd66717e63 100644
--- a/chromium/third_party/blink/renderer/core/streams/README.md
+++ b/chromium/third_party/blink/renderer/core/streams/README.md
@@ -3,38 +3,7 @@
This directory contains the Blink implementation of [the WHATWG Streams
standard][1].
-We use [V8 extras][2] to implement it.
-
-There is also a new implementation that is written in C++ rather than
-JavaScript. It is currently off by default, behind the Blink "StreamsNative"
-feature. The following files are part of the new implementation:
-
- readable_stream_default_controller.idl
- readable_stream_default_controller_interface.cc
- readable_stream_default_controller_interface.h
- readable_stream_default_reader.h
- readable_stream_default_reader.idl
- readable_stream_native.cc
- readable_stream_native.h
- readable_stream_reader.cc
- readable_stream_reader.h
- writable_stream_default_controller.cc
- writable_stream_default_controller.h
- writable_stream_default_controller.idl
- writable_stream_default_writer.cc
- writable_stream_default_writer.h
- writable_stream_default_writer.idl
- writable_stream_native.cc
- writable_stream_native.h
- transferable_streams.cc
- transferable_streams.h
- transform_stream_default_controller.cc
- transform_stream_default_controller.h
- transform_stream_native.cc
- transform_stream_native.h
-
-See also [Streams C++ port design doc][3].
+See [Streams C++ port design doc][2].
[1]: https://streams.spec.whatwg.org/
-[2]: https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA8Ec0
-[3]: https://docs.google.com/document/d/1n0IIRmJb0R-DFc2IhhJfS2-LUwl6iKSBNaR0klr3o40/edit
+[2]: https://docs.google.com/document/d/1n0IIRmJb0R-DFc2IhhJfS2-LUwl6iKSBNaR0klr3o40/edit
diff --git a/chromium/third_party/blink/renderer/core/streams/ReadableStream.js b/chromium/third_party/blink/renderer/core/streams/ReadableStream.js
deleted file mode 100644
index b34ad33e09d..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/ReadableStream.js
+++ /dev/null
@@ -1,1145 +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.
-
-(function(global, binding, v8) {
- 'use strict';
-
- const _reader = v8.createPrivateSymbol('[[reader]]');
- const _storedError = v8.createPrivateSymbol('[[storedError]]');
- const _controller = v8.createPrivateSymbol('[[controller]]');
-
- const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]');
- const _ownerReadableStream =
- v8.createPrivateSymbol('[[ownerReadableStream]]');
-
- const _readRequests = v8.createPrivateSymbol('[[readRequests]]');
-
- const createWithExternalControllerSentinel =
- v8.createPrivateSymbol('flag for UA-created ReadableStream to pass');
-
- const _readableStreamBits =
- v8.createPrivateSymbol('bit field for [[state]] and [[disturbed]]');
- const DISTURBED = 0b1;
- // The 2nd and 3rd bit are for [[state]].
- const STATE_MASK = 0b110;
- const STATE_BITS_OFFSET = 1;
- const STATE_READABLE = 0;
- const STATE_CLOSED = 1;
- const STATE_ERRORED = 2;
-
- const _controlledReadableStream =
- v8.createPrivateSymbol('[[controlledReadableStream]]');
- const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]');
-
- const _readableStreamDefaultControllerBits = v8.createPrivateSymbol(
- 'bit field for [[started]], [[closeRequested]], [[pulling]], ' +
- '[[pullAgain]]');
- const internalReadableStreamSymbol = v8.createPrivateSymbol(
- 'internal ReadableStream in exposed ReadableStream interface');
- // Remove this once C++ code has been updated to use CreateReadableStream.
- const _strategySizeAlgorithm = v8.createPrivateSymbol(
- '[[strategySizeAlgorithm]]');
- const _pullAlgorithm = v8.createPrivateSymbol('[[pullAlgorithm]]');
- const _cancelAlgorithm = v8.createPrivateSymbol('[[cancelAlgorithm]]');
- const STARTED = 0b1;
- const CLOSE_REQUESTED = 0b10;
- const PULLING = 0b100;
- const PULL_AGAIN = 0b1000;
-
- const ObjectCreate = global.Object.create;
-
- const callFunction = v8.uncurryThis(global.Function.prototype.call);
- const applyFunction = v8.uncurryThis(global.Function.prototype.apply);
-
- const TypeError = global.TypeError;
- const RangeError = global.RangeError;
-
- const String = global.String;
-
- const Promise = global.Promise;
- const thenPromise = v8.uncurryThis(Promise.prototype.then);
-
- // From CommonOperations.js
- const {
- _queue,
- _queueTotalSize,
- createPromise,
- createRejectedPromise,
- createResolvedPromise,
- hasOwnPropertyNoThrow,
- rejectPromise,
- resolvePromise,
- markPromiseAsHandled,
- CallOrNoop1,
- CreateAlgorithmFromUnderlyingMethod,
- CreateAlgorithmFromUnderlyingMethodPassingController,
- CreateCrossRealmTransformReadable,
- CreateCrossRealmTransformWritable,
- DequeueValue,
- EnqueueValueWithSize,
- MakeSizeAlgorithmFromSizeFunction,
- ValidateAndNormalizeHighWaterMark,
- } = binding.streamOperations;
-
- const streamErrors = binding.streamErrors;
- const errEnqueueCloseRequestedStream =
- 'Cannot enqueue a chunk into a readable stream that is closed or ' +
- 'has been requested to be closed';
- const errCancelReleasedReader =
- 'This readable stream reader has been released and cannot be used ' +
- 'to cancel its previous owner stream';
- const errReadReleasedReader =
- 'This readable stream reader has been released and cannot be used ' +
- 'to read from its previous owner stream';
- const errCloseCloseRequestedStream =
- 'Cannot close a readable stream that has already been requested to ' +
- 'be closed';
- const errEnqueueClosedStream =
- 'Cannot enqueue a chunk into a closed readable stream';
- const errEnqueueErroredStream =
- 'Cannot enqueue a chunk into an errored readable stream';
- const errCloseClosedStream = 'Cannot close a closed readable stream';
- const errCloseErroredStream = 'Cannot close an errored readable stream';
- const errReaderConstructorBadArgument =
- 'ReadableStreamReader constructor argument is not a readable stream';
- const errReaderConstructorStreamAlreadyLocked =
- 'ReadableStreamReader constructor can only accept readable streams ' +
- 'that are not yet locked to a reader';
- const errReleaseReaderWithPendingRead =
- 'Cannot release a readable stream reader when it still has ' +
- 'outstanding read() calls that have not yet settled';
- const errReleasedReaderClosedPromise =
- 'This readable stream reader has been released and cannot be used ' +
- 'to monitor the stream\'s state';
-
- const errDestinationStreamClosed = 'Destination stream closed';
-
- let useCounted = false;
-
- class ReadableStream {
- // TODO(ricea): Remove |internalArgument| once
- // blink::ReadableStreamOperations has been updated to use
- // CreateReadableStream.
- constructor(underlyingSource = {}, strategy = {},
- internalArgument = undefined) {
- const createdByUA =
- internalArgument === createWithExternalControllerSentinel;
-
- if (!useCounted && !createdByUA) {
- binding.countUse('ReadableStreamConstructor');
- useCounted = true;
- }
-
- InitializeReadableStream(this);
- const size = strategy.size;
- let highWaterMark = strategy.highWaterMark;
- const type = underlyingSource.type;
- const typeString = String(type);
-
- if (typeString === 'bytes') {
- throw new RangeError('bytes type is not yet implemented');
- }
-
- if (type !== undefined) {
- throw new RangeError(streamErrors.invalidType);
- }
-
- const sizeAlgorithm = MakeSizeAlgorithmFromSizeFunction(size);
-
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
-
- highWaterMark = ValidateAndNormalizeHighWaterMark(highWaterMark);
- SetUpReadableStreamDefaultControllerFromUnderlyingSource(
- this, underlyingSource, highWaterMark, sizeAlgorithm);
- }
- }
-
- const ReadableStream_prototype = ReadableStream.prototype;
-
- function ReadableStreamPipeTo(
- readable, dest, preventClose, preventAbort, preventCancel) {
- // Callers of this function must ensure that the following invariants
- // are enforced:
- // assert(IsReadableStream(readable));
- // assert(binding.IsWritableStream(dest));
- // assert(!IsReadableStreamLocked(readable));
- // assert(!binding.IsWritableStreamLocked(dest));
-
- const reader = AcquireReadableStreamDefaultReader(readable);
- const writer = binding.AcquireWritableStreamDefaultWriter(dest);
- let shuttingDown = false;
- const promise = createPromise();
- let reading = false;
- let lastWrite;
-
- if (checkInitialState()) {
- // Need to detect closing and error when we are not reading.
- thenPromise(reader[_closedPromise], onReaderClosed, readableError);
- // Need to detect error when we are not writing.
- thenPromise(
- binding.getWritableStreamDefaultWriterClosedPromise(writer),
- undefined, writableError);
- pump();
- }
-
- // Checks the state of the streams and executes the shutdown handlers if
- // necessary. Returns true if piping can continue.
- function checkInitialState() {
- const state = ReadableStreamGetState(readable);
-
- // Both streams can be errored or closed. To perform the right action the
- // order of the checks must match the standard.
- if (state === STATE_ERRORED) {
- readableError(readable[_storedError]);
- return false;
- }
-
- if (binding.isWritableStreamErrored(dest)) {
- writableError(binding.getWritableStreamStoredError(dest));
- return false;
- }
-
- if (state === STATE_CLOSED) {
- readableClosed();
- return false;
- }
-
- if (binding.isWritableStreamClosingOrClosed(dest)) {
- writableStartedClosed();
- return false;
- }
-
- return true;
- }
-
- function pump() {
- if (shuttingDown) {
- return;
- }
- const desiredSize =
- binding.WritableStreamDefaultWriterGetDesiredSize(writer);
- if (desiredSize === null) {
- // This can happen if abort() is queued but not yet started when
- // pipeTo() is called. In that case [[storedError]] is not set yet, and
- // we need to wait until it is before we can cancel the pipe. Once
- // [[storedError]] has been set, the rejection handler set on the writer
- // closed promise above will detect it, so all we need to do here is
- // nothing.
- return;
- }
- if (desiredSize <= 0) {
- thenPromise(
- binding.getWritableStreamDefaultWriterReadyPromise(writer), pump,
- writableError);
- return;
- }
- reading = true;
- thenPromise(
- ReadableStreamDefaultReaderRead(reader), readFulfilled, readRejected);
- }
-
- function readFulfilled({value, done}) {
- reading = false;
- if (done) {
- readableClosed();
- return;
- }
- const write = binding.WritableStreamDefaultWriterWrite(writer, value);
- lastWrite = write;
- thenPromise(write, undefined, writableError);
- pump();
- }
-
- function readRejected() {
- reading = false;
- readableError(readable[_storedError]);
- }
-
- // If read() is in progress, then wait for it to tell us that the stream is
- // closed so that we write all the data before shutdown.
- function onReaderClosed() {
- if (!reading) {
- readableClosed();
- }
- }
-
- // These steps are from "Errors must be propagated forward" in the
- // standard.
- function readableError(error) {
- if (!preventAbort) {
- shutdownWithAction(
- binding.WritableStreamAbort, [dest, error], error, true);
- } else {
- shutdown(error, true);
- }
- }
-
- // These steps are from "Errors must be propagated backward".
- function writableError(error) {
- if (!preventCancel) {
- shutdownWithAction(
- ReadableStreamCancel, [readable, error], error, true);
- } else {
- shutdown(error, true);
- }
- }
-
- // These steps are from "Closing must be propagated forward".
- function readableClosed() {
- if (!preventClose) {
- shutdownWithAction(
- binding.WritableStreamDefaultWriterCloseWithErrorPropagation,
- [writer]);
- } else {
- shutdown();
- }
- }
-
- // These steps are from "Closing must be propagated backward".
- function writableStartedClosed() {
- const destClosed = new TypeError(errDestinationStreamClosed);
- if (!preventCancel) {
- shutdownWithAction(
- ReadableStreamCancel, [readable, destClosed], destClosed, true);
- } else {
- shutdown(destClosed, true);
- }
- }
-
- function shutdownWithAction(
- action, args, originalError = undefined, errorGiven = false) {
- if (shuttingDown) {
- return;
- }
- shuttingDown = true;
- let p;
- if (shouldWriteQueuedChunks()) {
- p = thenPromise(writeQueuedChunks(),
- () => applyFunction(action, undefined, args));
- } else {
- p = applyFunction(action, undefined, args);
- }
- thenPromise(
- p, () => finalize(originalError, errorGiven),
- newError => finalize(newError, true));
- }
-
- function shutdown(error = undefined, errorGiven = false) {
- if (shuttingDown) {
- return;
- }
- shuttingDown = true;
- if (shouldWriteQueuedChunks()) {
- thenPromise(writeQueuedChunks(), () => finalize(error, errorGiven));
- } else {
- finalize(error, errorGiven);
- }
- }
-
- function finalize(error, errorGiven) {
- binding.WritableStreamDefaultWriterRelease(writer);
- ReadableStreamReaderGenericRelease(reader);
- if (errorGiven) {
- rejectPromise(promise, error);
- } else {
- resolvePromise(promise, undefined);
- }
- }
-
- function shouldWriteQueuedChunks() {
- return binding.isWritableStreamWritable(dest) &&
- !binding.WritableStreamCloseQueuedOrInFlight(dest);
- }
-
- function writeQueuedChunks() {
- if (lastWrite) {
- // "Wait until every chunk that has been read has been written (i.e.
- // the corresponding promises have settled)"
- // This implies that we behave the same whether the promise fulfills or
- // rejects.
- return thenPromise(lastWrite, () => undefined, () => undefined);
- }
- return createResolvedPromise(undefined);
- }
-
- return promise;
- }
-
- //
- // Readable stream abstract operations
- //
-
- function AcquireReadableStreamDefaultReader(stream) {
- return new ReadableStreamDefaultReader(stream);
- }
-
- function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm) {
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
- if (sizeAlgorithm === undefined) {
- sizeAlgorithm = () => 1;
- }
- // assert(IsNonNegativeNumber(highWaterMark),
- // '! IsNonNegativeNumber(highWaterMark) is true.');
- const stream = ObjectCreate(ReadableStream_prototype);
- InitializeReadableStream(stream);
- const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
- SetUpReadableStreamDefaultController(
- stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm);
- return stream;
- }
-
- function InitializeReadableStream(stream) {
- stream[_readableStreamBits] = 0b0;
- ReadableStreamSetState(stream, STATE_READABLE);
- stream[_reader] = undefined;
- stream[_storedError] = undefined;
- }
-
- function IsReadableStream(x) {
- return hasOwnPropertyNoThrow(x, _controller);
- }
-
- function IsReadableStreamDisturbed(stream) {
- return stream[_readableStreamBits] & DISTURBED;
- }
-
- function IsReadableStreamLocked(stream) {
- return stream[_reader] !== undefined;
- }
-
- // TODO(domenic): cloneForBranch2 argument from spec not supported yet
- function ReadableStreamTee(stream) {
- const reader = AcquireReadableStreamDefaultReader(stream);
-
- let closedOrErrored = false;
- let canceled1 = false;
- let canceled2 = false;
- let reason1;
- let reason2;
- const cancelPromise = createPromise();
-
- function pullAlgorithm() {
- return thenPromise(
- ReadableStreamDefaultReaderRead(reader), ({value, done}) => {
- if (done && !closedOrErrored) {
- if (!canceled1) {
- ReadableStreamDefaultControllerClose(branch1controller);
- }
- if (!canceled2) {
- ReadableStreamDefaultControllerClose(branch2controller);
- }
- closedOrErrored = true;
- }
-
- if (closedOrErrored) {
- return;
- }
-
- // TODO(ricea): Implement these steps for cloning.
- //
- // vii. Let _value1_ and _value2_ be _value_.
- // viii. If _canceled2_ is false and _cloneForBranch2_ is true, set
- // value2 to ? StructuredDeserialize(? StructuredSerialize(value2),
- // the current Realm Record).
-
- if (!canceled1) {
- ReadableStreamDefaultControllerEnqueue(branch1controller, value);
- }
-
- if (!canceled2) {
- ReadableStreamDefaultControllerEnqueue(branch2controller, value);
- }
- });
- }
-
- function cancel1Algorithm(reason) {
- canceled1 = true;
- reason1 = reason;
- if (canceled2) {
- const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
- resolvePromise(cancelPromise, cancelResult);
- }
- return cancelPromise;
- }
-
- function cancel2Algorithm(reason) {
- canceled2 = true;
- reason2 = reason;
- if (canceled1) {
- const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
- resolvePromise(cancelPromise, cancelResult);
- }
- return cancelPromise;
- }
-
- const startAlgorithm = () => undefined;
-
- const branch1Stream = CreateReadableStream(
- startAlgorithm, pullAlgorithm, cancel1Algorithm);
- const branch2Stream = CreateReadableStream(
- startAlgorithm, pullAlgorithm, cancel2Algorithm);
- const branch1controller = branch1Stream[_controller];
- const branch2controller = branch2Stream[_controller];
-
- thenPromise(reader[_closedPromise], undefined, r => {
- if (closedOrErrored === true) {
- return;
- }
-
- ReadableStreamDefaultControllerError(branch1controller, r);
- ReadableStreamDefaultControllerError(branch2controller, r);
- closedOrErrored = true;
- });
-
- return [branch1Stream, branch2Stream];
- }
-
- //
- // Abstract Operations Used By Controllers
- //
-
- function ReadableStreamAddReadRequest(stream, forAuthorCode) {
- const promise = createPromise();
- stream[_reader][_readRequests].push({promise, forAuthorCode});
- return promise;
- }
-
- function ReadableStreamCancel(stream, reason) {
- stream[_readableStreamBits] |= DISTURBED;
-
- const state = ReadableStreamGetState(stream);
- if (state === STATE_CLOSED) {
- return createResolvedPromise(undefined);
- }
- if (state === STATE_ERRORED) {
- return createRejectedPromise(stream[_storedError]);
- }
-
- ReadableStreamClose(stream);
-
- const sourceCancelPromise =
- ReadableStreamDefaultControllerCancel(stream[_controller], reason);
- return thenPromise(sourceCancelPromise, () => undefined);
- }
-
- function ReadableStreamClose(stream) {
- ReadableStreamSetState(stream, STATE_CLOSED);
-
- const reader = stream[_reader];
- if (reader === undefined) {
- return;
- }
-
- if (IsReadableStreamDefaultReader(reader) === true) {
- reader[_readRequests].forEach(
- request =>
- resolvePromise(
- request.promise,
- ReadableStreamCreateReadResult(undefined, true,
- request.forAuthorCode)));
- reader[_readRequests] = new binding.SimpleQueue();
- }
-
- resolvePromise(reader[_closedPromise], undefined);
- }
-
- function ReadableStreamCreateReadResult(value, done, forAuthorCode) {
- // assert(typeof done === 'boolean', 'Type(_done_) is Boolean.');
- if (forAuthorCode) {
- return {value, done};
- }
- const obj = ObjectCreate(null);
- obj.value = value;
- obj.done = done;
- return obj;
- }
-
- function ReadableStreamError(stream, e) {
- ReadableStreamSetState(stream, STATE_ERRORED);
- stream[_storedError] = e;
-
- const reader = stream[_reader];
- if (reader === undefined) {
- return;
- }
-
- if (IsReadableStreamDefaultReader(reader) === true) {
- reader[_readRequests].forEach(request =>
- rejectPromise(request.promise, e));
- reader[_readRequests] = new binding.SimpleQueue();
- }
-
- rejectPromise(reader[_closedPromise], e);
- markPromiseAsHandled(reader[_closedPromise]);
- }
-
- function ReadableStreamFulfillReadRequest(stream, chunk, done) {
- const readRequest = stream[_reader][_readRequests].shift();
- resolvePromise(readRequest.promise,
- ReadableStreamCreateReadResult(chunk, done,
- readRequest.forAuthorCode));
- }
-
- function ReadableStreamGetNumReadRequests(stream) {
- const reader = stream[_reader];
- const readRequests = reader[_readRequests];
- return readRequests.length;
- }
-
- //
- // Class ReadableStreamDefaultReader
- //
-
- class ReadableStreamDefaultReader {
- constructor(stream) {
- // |stream| here can be either an external ReadableStream (i.e.,
- // IDL defined ReadableStream) or an internal ReadableStream (i.e.,
- // the class defined in this file). In the former case, the
- // internal stream is stored in [internalReadableStreamSymbol], so use it
- // from now on.
- if (stream[internalReadableStreamSymbol] !== undefined) {
- stream = stream[internalReadableStreamSymbol];
- }
-
- if (IsReadableStream(stream) === false) {
- throw new TypeError(errReaderConstructorBadArgument);
- }
- if (IsReadableStreamLocked(stream) === true) {
- throw new TypeError(errReaderConstructorStreamAlreadyLocked);
- }
-
- ReadableStreamReaderGenericInitialize(this, stream);
-
- this[_readRequests] = new binding.SimpleQueue();
- }
-
- get closed() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
-
- return this[_closedPromise];
- }
-
- cancel(reason) {
- if (IsReadableStreamDefaultReader(this) === false) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
-
- if (this[_ownerReadableStream] === undefined) {
- return createRejectedPromise(new TypeError(errCancelReleasedReader));
- }
-
- return ReadableStreamReaderGenericCancel(this, reason);
- }
-
- read() {
- if (IsReadableStreamDefaultReader(this) === false) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
-
- if (this[_ownerReadableStream] === undefined) {
- return createRejectedPromise(new TypeError(errReadReleasedReader));
- }
-
- return ReadableStreamDefaultReaderRead(this, true);
- }
-
- releaseLock() {
- if (IsReadableStreamDefaultReader(this) === false) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- if (this[_ownerReadableStream] === undefined) {
- return;
- }
-
- if (this[_readRequests].length > 0) {
- throw new TypeError(errReleaseReaderWithPendingRead);
- }
-
- ReadableStreamReaderGenericRelease(this);
- }
- }
-
- //
- // Readable Stream Reader Abstract Operations
- //
-
- function IsReadableStreamDefaultReader(x) {
- return hasOwnPropertyNoThrow(x, _readRequests);
- }
-
- function ReadableStreamReaderGenericCancel(reader, reason) {
- return ReadableStreamCancel(reader[_ownerReadableStream], reason);
- }
-
- function ReadableStreamReaderGenericInitialize(reader, stream) {
- reader[_ownerReadableStream] = stream;
- stream[_reader] = reader;
-
- switch (ReadableStreamGetState(stream)) {
- case STATE_READABLE:
- reader[_closedPromise] = createPromise();
- break;
- case STATE_CLOSED:
- reader[_closedPromise] = createResolvedPromise(undefined);
- break;
- case STATE_ERRORED:
- reader[_closedPromise] = createRejectedPromise(stream[_storedError]);
- markPromiseAsHandled(reader[_closedPromise]);
- break;
- }
- }
-
- function ReadableStreamReaderGenericRelease(reader) {
- if (ReadableStreamGetState(reader[_ownerReadableStream]) ===
- STATE_READABLE) {
- rejectPromise(
- reader[_closedPromise],
- new TypeError(errReleasedReaderClosedPromise));
- } else {
- reader[_closedPromise] =
- createRejectedPromise(new TypeError(errReleasedReaderClosedPromise));
- }
- markPromiseAsHandled(reader[_closedPromise]);
-
- reader[_ownerReadableStream][_reader] = undefined;
- reader[_ownerReadableStream] = undefined;
- }
-
- function ReadableStreamDefaultReaderRead(reader, forAuthorCode = false) {
- const stream = reader[_ownerReadableStream];
- stream[_readableStreamBits] |= DISTURBED;
-
- switch (ReadableStreamGetState(stream)) {
- case STATE_CLOSED:
- return createResolvedPromise(
- ReadableStreamCreateReadResult(undefined, true, forAuthorCode));
-
- case STATE_ERRORED:
- return createRejectedPromise(stream[_storedError]);
-
- default:
- return ReadableStreamDefaultControllerPull(stream[_controller],
- forAuthorCode);
- }
- }
-
- //
- // Class ReadableStreamDefaultController
- //
-
- class ReadableStreamDefaultController {
- constructor() {
- throw new TypeError(streamErrors.illegalConstructor);
- }
-
- get desiredSize() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- return ReadableStreamDefaultControllerGetDesiredSize(this);
- }
-
- close() {
- if (IsReadableStreamDefaultController(this) === false) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- if (ReadableStreamDefaultControllerCanCloseOrEnqueue(this) === false) {
- let errorDescription;
- if (this[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
- errorDescription = errCloseCloseRequestedStream;
- } else {
- const stream = this[_controlledReadableStream];
- switch (ReadableStreamGetState(stream)) {
- case STATE_ERRORED:
- errorDescription = errCloseErroredStream;
- break;
-
- case STATE_CLOSED:
- errorDescription = errCloseClosedStream;
- break;
- }
- }
- throw new TypeError(errorDescription);
- }
-
- return ReadableStreamDefaultControllerClose(this);
- }
-
- enqueue(chunk) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) {
- const stream = this[_controlledReadableStream];
- throw getReadableStreamEnqueueError(stream, this);
- }
-
- return ReadableStreamDefaultControllerEnqueue(this, chunk);
- }
-
- error(e) {
- if (IsReadableStreamDefaultController(this) === false) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- return ReadableStreamDefaultControllerError(this, e);
- }
- }
-
- const ReadableStreamDefaultController_prototype =
- ReadableStreamDefaultController.prototype;
-
- // [[CancelSteps]] in the standard.
- function ReadableStreamDefaultControllerCancel(controller, reason) {
- controller[_queue] = new binding.SimpleQueue();
- return controller[_cancelAlgorithm](reason);
- }
-
- // [[PullSteps]] in the standard.
- function ReadableStreamDefaultControllerPull(controller, forAuthorCode) {
- const stream = controller[_controlledReadableStream];
-
- if (controller[_queue].length > 0) {
- const chunk = DequeueValue(controller);
-
- if ((controller[_readableStreamDefaultControllerBits] &
- CLOSE_REQUESTED) &&
- controller[_queue].length === 0) {
- ReadableStreamClose(stream);
- } else {
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }
-
- return createResolvedPromise(
- ReadableStreamCreateReadResult(chunk, false, forAuthorCode));
- }
-
- const pendingPromise = ReadableStreamAddReadRequest(stream, forAuthorCode);
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- return pendingPromise;
- }
-
- //
- // Readable Stream Default Controller Abstract Operations
- //
-
- function IsReadableStreamDefaultController(x) {
- return hasOwnPropertyNoThrow(x, _controlledReadableStream);
- }
-
- function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
- const shouldPull =
- ReadableStreamDefaultControllerShouldCallPull(controller);
- if (shouldPull === false) {
- return;
- }
-
- if (controller[_readableStreamDefaultControllerBits] & PULLING) {
- controller[_readableStreamDefaultControllerBits] |= PULL_AGAIN;
- return;
- }
-
- controller[_readableStreamDefaultControllerBits] |= PULLING;
-
- thenPromise(
- controller[_pullAlgorithm](),
- () => {
- controller[_readableStreamDefaultControllerBits] &= ~PULLING;
-
- if (controller[_readableStreamDefaultControllerBits] & PULL_AGAIN) {
- controller[_readableStreamDefaultControllerBits] &= ~PULL_AGAIN;
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }
- },
- e => {
- ReadableStreamDefaultControllerError(controller, e);
- });
- }
-
- function ReadableStreamDefaultControllerShouldCallPull(controller) {
- if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) {
- return false;
- }
- if (!(controller[_readableStreamDefaultControllerBits] & STARTED)) {
- return false;
- }
-
- const stream = controller[_controlledReadableStream];
- if (IsReadableStreamLocked(stream) === true &&
- ReadableStreamGetNumReadRequests(stream) > 0) {
- return true;
- }
-
- const desiredSize =
- ReadableStreamDefaultControllerGetDesiredSize(controller);
- // assert(desiredSize !== null, '_desiredSize_ is not *null*.');
- return desiredSize > 0;
- }
-
- function ReadableStreamDefaultControllerClose(controller) {
- controller[_readableStreamDefaultControllerBits] |= CLOSE_REQUESTED;
-
- if (controller[_queue].length === 0) {
- ReadableStreamClose(controller[_controlledReadableStream]);
- }
- }
-
- function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
- const stream = controller[_controlledReadableStream];
-
- if (IsReadableStreamLocked(stream) === true &&
- ReadableStreamGetNumReadRequests(stream) > 0) {
- ReadableStreamFulfillReadRequest(stream, chunk, false);
- } else {
- let chunkSize;
-
- // TODO(ricea): Would it be more efficient if we avoided the
- // try ... catch when we're using the default strategy size algorithm?
- try {
- // Unlike other algorithms, strategySizeAlgorithm isn't indirected, so
- // we need to be careful with the |this| value.
- chunkSize = callFunction(controller[_strategySizeAlgorithm], undefined,
- chunk);
- } catch (chunkSizeE) {
- ReadableStreamDefaultControllerError(controller, chunkSizeE);
- throw chunkSizeE;
- }
-
- try {
- EnqueueValueWithSize(controller, chunk, chunkSize);
- } catch (enqueueE) {
- ReadableStreamDefaultControllerError(controller, enqueueE);
- throw enqueueE;
- }
- }
-
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }
-
- function ReadableStreamDefaultControllerError(controller, e) {
- const stream = controller[_controlledReadableStream];
- if (ReadableStreamGetState(stream) !== STATE_READABLE) {
- return;
- }
- controller[_queue] = new binding.SimpleQueue();
- ReadableStreamError(stream, e);
- }
-
- function ReadableStreamDefaultControllerGetDesiredSize(controller) {
- switch (ReadableStreamGetState(controller[_controlledReadableStream])) {
- case STATE_ERRORED:
- return null;
-
- case STATE_CLOSED:
- return 0;
-
- default:
- return controller[_strategyHWM] - controller[_queueTotalSize];
- }
- }
-
- function ReadableStreamDefaultControllerHasBackpressure(controller) {
- return !ReadableStreamDefaultControllerShouldCallPull(controller);
- }
-
- function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) {
- if (controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
- return false;
- }
- const state = ReadableStreamGetState(controller[_controlledReadableStream]);
- return state === STATE_READABLE;
- }
-
- function SetUpReadableStreamDefaultController(
- stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm) {
- controller[_controlledReadableStream] = stream;
- controller[_queue] = new binding.SimpleQueue();
- controller[_queueTotalSize] = 0;
- controller[_strategySizeAlgorithm] = sizeAlgorithm;
- controller[_strategyHWM] = highWaterMark;
- controller[_pullAlgorithm] = pullAlgorithm;
- controller[_cancelAlgorithm] = cancelAlgorithm;
- stream[_controller] = controller;
-
- thenPromise(createResolvedPromise(startAlgorithm()), () => {
- controller[_readableStreamDefaultControllerBits] |= STARTED;
- ReadableStreamDefaultControllerCallPullIfNeeded(controller);
- }, r => ReadableStreamDefaultControllerError(controller, r));
- }
-
- function SetUpReadableStreamDefaultControllerFromUnderlyingSource(
- stream, underlyingSource, highWaterMark, sizeAlgorithm) {
- const controller = ObjectCreate(ReadableStreamDefaultController_prototype);
- const startAlgorithm =
- () => CallOrNoop1(underlyingSource, 'start', controller,
- 'underlyingSource.start');
- const pullAlgorithm = CreateAlgorithmFromUnderlyingMethodPassingController(
- underlyingSource, 'pull', 0, controller, 'underlyingSource.pull');
- const cancelAlgorithm = CreateAlgorithmFromUnderlyingMethod(
- underlyingSource, 'cancel', 1, 'underlyingSource.cancel');
- SetUpReadableStreamDefaultController(
- stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
- highWaterMark, sizeAlgorithm);
- }
-
- //
- // Functions for transferable streams.
- //
-
- // The |port| which is passed to this function must be a MessagePort which is
- // attached by a MessageChannel to the |port| that will be passed to
- // ReadableStreamDeserialize.
- function ReadableStreamSerialize(readable, port) {
- // assert(IsReadableStream(readable),
- // `! IsReadableStream(_readable_) is true`);
- if (IsReadableStreamLocked(readable)) {
- throw new TypeError(streamErrors.cannotTransferLockedStream);
- }
-
- if (!binding.MessagePort_postMessage) {
- throw new TypeError(streamErrors.cannotTransferContext);
- }
-
- const writable = CreateCrossRealmTransformWritable(port);
- const promise =
- ReadableStreamPipeTo(readable, writable, false, false, false);
- markPromiseAsHandled(promise);
- }
-
- function ReadableStreamDeserialize(port) {
- return CreateCrossRealmTransformReadable(port);
- }
-
- //
- // Internal functions. Not part of the standard.
- //
-
- function ReadableStreamGetState(stream) {
- return (stream[_readableStreamBits] & STATE_MASK) >> STATE_BITS_OFFSET;
- }
-
- function ReadableStreamSetState(stream, state) {
- stream[_readableStreamBits] = (stream[_readableStreamBits] & ~STATE_MASK) |
- (state << STATE_BITS_OFFSET);
- }
-
- //
- // Functions exported for use by TransformStream. Not part of the standard.
- //
-
- function IsReadableStreamReadable(stream) {
- return ReadableStreamGetState(stream) === STATE_READABLE;
- }
-
- function IsReadableStreamClosed(stream) {
- return ReadableStreamGetState(stream) === STATE_CLOSED;
- }
-
- function IsReadableStreamErrored(stream) {
- return ReadableStreamGetState(stream) === STATE_ERRORED;
- }
-
- // Used internally by enqueue() and also by TransformStream.
- function getReadableStreamEnqueueError(stream, controller) {
- if (controller[_readableStreamDefaultControllerBits] & CLOSE_REQUESTED) {
- return new TypeError(errEnqueueCloseRequestedStream);
- }
-
- const state = ReadableStreamGetState(stream);
- if (state === STATE_ERRORED) {
- return new TypeError(errEnqueueErroredStream);
- }
- // assert(state === STATE_CLOSED, 'state is "closed"');
- return new TypeError(errEnqueueClosedStream);
- }
-
- //
- // Accessors used by TransformStream
- //
-
- function getReadableStreamController(stream) {
- // assert(
- // IsReadableStream(stream), '! IsReadableStream(stream) is true.');
- return stream[_controller];
- }
-
- function getReadableStreamStoredError(stream) {
- // assert(
- // IsReadableStream(stream), '! IsReadableStream(stream) is true.');
- return stream[_storedError];
- }
-
- // TODO(yhirano): Rename this to constructReadableStream.
- function createReadableStream(underlyingSource, strategy) {
- return new ReadableStream(underlyingSource, strategy);
- }
-
- // TODO(yhirano): Rename this to
- // constructReadableStreamWithExternalController.
- // TODO(ricea): Remove this once the C++ code switches to calling
- // CreateReadableStream().
- function createReadableStreamWithExternalController(
- underlyingSource, strategy) {
- return new ReadableStream(
- underlyingSource, strategy, createWithExternalControllerSentinel);
- }
-
- Object.assign(binding, {
- //
- // ReadableStream exports to Blink C++
- //
- AcquireReadableStreamDefaultReader,
- createReadableStream,
- createReadableStreamWithExternalController,
- IsReadableStream,
- IsReadableStreamDisturbed,
- IsReadableStreamLocked,
- IsReadableStreamReadable,
- IsReadableStreamClosed,
- IsReadableStreamErrored,
- IsReadableStreamDefaultReader,
- ReadableStreamDefaultReaderRead,
- ReadableStreamCancel,
- ReadableStreamTee,
- ReadableStreamPipeTo,
- ReadableStreamSerialize,
- ReadableStreamDeserialize,
- internalReadableStreamSymbol,
-
- //
- // Controller exports to Blink C++
- //
- ReadableStreamDefaultControllerClose,
- ReadableStreamDefaultControllerGetDesiredSize,
- ReadableStreamDefaultControllerEnqueue,
- ReadableStreamDefaultControllerError,
-
- //
- // Exports to TransformStream
- //
- CreateReadableStream,
- ReadableStreamDefaultControllerCanCloseOrEnqueue,
- ReadableStreamDefaultControllerHasBackpressure,
-
- getReadableStreamEnqueueError,
- getReadableStreamController,
- getReadableStreamStoredError,
- });
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/SimpleQueue.js b/chromium/third_party/blink/renderer/core/streams/SimpleQueue.js
deleted file mode 100644
index b1db33da7a3..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/SimpleQueue.js
+++ /dev/null
@@ -1,152 +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.
-
-// Queue implementation used by ReadableStream and WritableStream.
-
-(function(global, binding, v8) {
- 'use strict';
-
- const _front = v8.createPrivateSymbol('front');
- const _back = v8.createPrivateSymbol('back');
- const _cursor = v8.createPrivateSymbol('cursor');
- const _size = v8.createPrivateSymbol('size');
- const _elements = v8.createPrivateSymbol('elements');
- const _next = v8.createPrivateSymbol('next');
-
- // Take copies of global objects to protect against them being replaced.
- const RangeError = global.RangeError;
-
- // shift() and peek() can only be called on a non-empty queue. This function
- // throws an exception with the message mentioning |functionName| if |queue|
- // is empty.
- function requireNonEmptyQueue(queue, functionName) {
- if (queue[_size] === 0) {
- throw new RangeError(
- `${functionName}() must not be called on an empty queue`);
- }
- }
-
- // Simple queue structure. Avoids scalability issues with using
- // InternalPackedArray directly by using multiple arrays in a linked list and
- // keeping the array size bounded.
- const QUEUE_MAX_ARRAY_SIZE = 16384;
- class SimpleQueue {
- constructor() {
- // [_front] and [_back] are always defined.
- this[_front] = {
- [_elements]: new v8.InternalPackedArray(),
- [_next]: undefined,
- };
- this[_back] = this[_front];
- // The cursor is used to avoid calling InternalPackedArray.shift(). It
- // contains the index of the front element of the array inside the
- // frontmost node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE).
- this[_cursor] = 0;
- // When there is only one node, size === elements.length - cursor.
- this[_size] = 0;
- }
-
- get length() {
- return this[_size];
- }
-
- // For exception safety, this method is structured in order:
- // 1. Read state
- // 2. Calculate required state mutations
- // 3. Perform state mutations
- push(element) {
- const oldBack = this[_back];
- let newBack = oldBack;
- // assert(oldBack[_next] === undefined);
- if (oldBack[_elements].length === QUEUE_MAX_ARRAY_SIZE - 1) {
- newBack = {
- [_elements]: new v8.InternalPackedArray(),
- [_next]: undefined,
- };
- }
-
- // push() is the mutation most likely to throw an exception, so it
- // goes first.
- oldBack[_elements].push(element);
- if (newBack !== oldBack) {
- this[_back] = newBack;
- oldBack[_next] = newBack;
- }
- ++this[_size];
- }
-
- // Like push(), shift() follows the read -> calculate -> mutate pattern for
- // exception safety.
- shift() {
- requireNonEmptyQueue(this, 'shift');
-
- const oldFront = this[_front];
- let newFront = oldFront;
- const oldCursor = this[_cursor];
- let newCursor = oldCursor + 1;
-
- const elements = oldFront[_elements];
- const element = elements[oldCursor];
-
- if (newCursor === QUEUE_MAX_ARRAY_SIZE) {
- // assert(elements.length === QUEUE_MAX_ARRAY_SIZE);
- // assert(oldFront[_next] !== undefined);
- newFront = oldFront[_next];
- newCursor = 0;
- }
-
- // No mutations before this point.
- --this[_size];
- this[_cursor] = newCursor;
- if (oldFront !== newFront) {
- this[_front] = newFront;
- }
-
- // Permit shifted element to be garbage collected.
- elements[oldCursor] = undefined;
-
- return element;
- }
-
- // The tricky thing about forEach() is that it can be called
- // re-entrantly. The queue may be mutated inside the callback. It is easy to
- // see that push() within the callback has no negative effects since the end
- // of the queue is checked for on every iteration. If shift() is called
- // repeatedly within the callback then the next iteration may return an
- // element that has been removed. In this case the callback will be called
- // with undefined values until we either "catch up" with elements that still
- // exist or reach the back of the queue.
- forEach(callback) {
- let i = this[_cursor];
- let node = this[_front];
- let elements = node[_elements];
- while (i !== elements.length || node[_next] !== undefined) {
- if (i === elements.length) {
- // assert(node[_next] !== undefined);
- // assert(i === QUEUE_MAX_ARRAY_SIZE);
- node = node[_next];
- elements = node[_elements];
- i = 0;
- if (elements.length === 0) {
- break;
- }
- }
- callback(elements[i]);
- ++i;
- }
- }
-
- // Return the element that would be returned if shift() was called now,
- // without modifying the queue.
- peek() {
- requireNonEmptyQueue(this, 'peek');
-
- const front = this[_front];
- const cursor = this[_cursor];
- return front[_elements][cursor];
- }
- }
-
- binding.SimpleQueue = SimpleQueue;
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/TransformStream.js b/chromium/third_party/blink/renderer/core/streams/TransformStream.js
deleted file mode 100644
index 639be9b30f1..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/TransformStream.js
+++ /dev/null
@@ -1,498 +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.
-
-// Implementation of TransformStream for Blink. See
-// https://streams.spec.whatwg.org/#ts. The implementation closely follows the
-// standard, except where required for performance or integration with Blink.
-// In particular, classes, methods and abstract operations are implemented in
-// the same order as in the standard, to simplify side-by-side reading.
-
-(function(global, binding, v8) {
- 'use strict';
-
- // Private symbols. These correspond to the internal slots in the standard.
- // "[[X]]" in the standard is spelt _X in this implementation.
-
- const _backpressure = v8.createPrivateSymbol('[[backpressure]]');
- const _backpressureChangePromise =
- v8.createPrivateSymbol('[[backpressureChangePromise]]');
- const _readable = v8.createPrivateSymbol('[[readable]]');
- const _transformStreamController =
- v8.createPrivateSymbol('[[transformStreamController]]');
- const _writable = v8.createPrivateSymbol('[[writable]]');
- const _controlledTransformStream =
- v8.createPrivateSymbol('[[controlledTransformStream]]');
-
- // Unlike the version in the standard, the controller is passed to this.
- const _flushAlgorithm = v8.createPrivateSymbol('[[flushAlgorithm]]');
-
- // Unlike the version in the standard, the controller is passed in as the
- // second argument.
- const _transformAlgorithm = v8.createPrivateSymbol('[[transformAlgorithm]]');
-
- // Javascript functions. It is important to use these copies, as the ones on
- // the global object may have been overwritten. See "V8 Extras Design Doc",
- // section "Security Considerations".
- // https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA8Ec0/edit#heading=h.9yixony1a18r
- const ObjectCreate = global.Object.create;
-
- const TypeError = global.TypeError;
- const RangeError = global.RangeError;
-
- const Promise = global.Promise;
- const thenPromise = v8.uncurryThis(Promise.prototype.then);
-
- // From CommonOperations.js
- const {
- createPromise,
- createRejectedPromise,
- createResolvedPromise,
- hasOwnPropertyNoThrow,
- resolvePromise,
- CreateAlgorithmFromUnderlyingMethod,
- CallOrNoop1,
- MakeSizeAlgorithmFromSizeFunction,
- PromiseCall2,
- ValidateAndNormalizeHighWaterMark
- } = binding.streamOperations;
-
- // User-visible strings.
- const streamErrors = binding.streamErrors;
- const errStreamTerminated = 'The transform stream has been terminated';
-
- let useCounted = false;
-
- class TransformStream {
- constructor(transformer = {},
- writableStrategy = {}, readableStrategy = {}) {
- if (!useCounted) {
- binding.countUse('TransformStreamConstructor');
- useCounted = true;
- }
-
- const writableSizeFunction = writableStrategy.size;
- let writableHighWaterMark = writableStrategy.highWaterMark;
-
- const readableSizeFunction = readableStrategy.size;
- let readableHighWaterMark = readableStrategy.highWaterMark;
-
- // readable and writableType are extension points for future byte streams.
- const writableType = transformer.writableType;
- if (writableType !== undefined) {
- throw new RangeError(streamErrors.invalidType);
- }
-
- const writableSizeAlgorithm =
- MakeSizeAlgorithmFromSizeFunction(writableSizeFunction);
- if (writableHighWaterMark === undefined) {
- writableHighWaterMark = 1;
- }
- writableHighWaterMark =
- ValidateAndNormalizeHighWaterMark(writableHighWaterMark);
-
- const readableType = transformer.readableType;
- if (readableType !== undefined) {
- throw new RangeError(streamErrors.invalidType);
- }
-
- const readableSizeAlgorithm =
- MakeSizeAlgorithmFromSizeFunction(readableSizeFunction);
- if (readableHighWaterMark === undefined) {
- readableHighWaterMark = 0;
- }
- readableHighWaterMark =
- ValidateAndNormalizeHighWaterMark(readableHighWaterMark);
-
- const startPromise = createPromise();
- InitializeTransformStream(
- this, startPromise, writableHighWaterMark, writableSizeAlgorithm,
- readableHighWaterMark, readableSizeAlgorithm);
- SetUpTransformStreamDefaultControllerFromTransformer(this, transformer);
- const startResult = CallOrNoop1(
- transformer, 'start', this[_transformStreamController],
- 'transformer.start');
- resolvePromise(startPromise, startResult);
- }
-
- get readable() {
- if (!IsTransformStream(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- return this[_readable];
- }
-
- get writable() {
- if (!IsTransformStream(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- return this[_writable];
- }
- }
-
- const TransformStream_prototype = TransformStream.prototype;
-
- // The controller is passed to |transformAlgorithm| and |flushAlgorithm|,
- // unlike in the standard.
- function CreateTransformStream(
- startAlgorithm, transformAlgorithm, flushAlgorithm, writableHighWaterMark,
- writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) {
- if (writableHighWaterMark === undefined) {
- writableHighWaterMark = 1;
- }
- if (writableSizeAlgorithm === undefined) {
- writableSizeAlgorithm = () => 1;
- }
- if (readableHighWaterMark === undefined) {
- readableHighWaterMark = 0;
- }
- if (readableSizeAlgorithm === undefined) {
- readableSizeAlgorithm = () => 1;
- }
- // assert(
- // typeof writableHighWaterMark === 'number' &&
- // writableHighWaterMark >= 0,
- // '! IsNonNegativeNumber(_writableHighWaterMark_) is *true*');
- // assert(
- // typeof readableHighWaterMark === 'number' &&
- // readableHighWaterMark >= 0,
- // '! IsNonNegativeNumber(_readableHighWaterMark_) is true');
- const stream = ObjectCreate(TransformStream_prototype);
- const startPromise = createPromise();
- InitializeTransformStream(
- stream, startPromise, writableHighWaterMark, writableSizeAlgorithm,
- readableHighWaterMark, readableSizeAlgorithm);
- const controller = ObjectCreate(TransformStreamDefaultController_prototype);
- SetUpTransformStreamDefaultController(
- stream, controller, transformAlgorithm, flushAlgorithm);
- const startResult = startAlgorithm();
- resolvePromise(startPromise, startResult);
- return stream;
- }
-
- function InitializeTransformStream(
- stream, startPromise, writableHighWaterMark, writableSizeAlgorithm,
- readableHighWaterMark, readableSizeAlgorithm) {
- const startAlgorithm = () => startPromise;
- const writeAlgorithm = chunk =>
- TransformStreamDefaultSinkWriteAlgorithm(stream, chunk);
- const abortAlgorithm = reason =>
- TransformStreamDefaultSinkAbortAlgorithm(stream, reason);
- const closeAlgorithm = () =>
- TransformStreamDefaultSinkCloseAlgorithm(stream);
- stream[_writable] = binding.CreateWritableStream(
- startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm,
- writableHighWaterMark, writableSizeAlgorithm);
- const pullAlgorithm = () =>
- TransformStreamDefaultSourcePullAlgorithm(stream);
- const cancelAlgorithm = reason => {
- TransformStreamErrorWritableAndUnblockWrite(stream, reason);
- return createResolvedPromise(undefined);
- };
- stream[_readable] = binding.CreateReadableStream(
- startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark,
- readableSizeAlgorithm);
- stream[_backpressure] = undefined;
- stream[_backpressureChangePromise] = undefined;
- TransformStreamSetBackpressure(stream, true);
- stream[_transformStreamController] = undefined;
- }
-
- function IsTransformStream(x) {
- return hasOwnPropertyNoThrow(x, _transformStreamController);
- }
-
- function TransformStreamError(stream, e) {
- const readable = stream[_readable];
- // TODO(ricea): Remove this conditional once ReadableStream is updated.
- if (binding.IsReadableStreamReadable(readable)) {
- binding.ReadableStreamDefaultControllerError(
- binding.getReadableStreamController(readable), e);
- }
-
- TransformStreamErrorWritableAndUnblockWrite(stream, e);
- }
-
- function TransformStreamErrorWritableAndUnblockWrite(stream, e) {
- TransformStreamDefaultControllerClearAlgorithms(
- stream[_transformStreamController]);
- binding.WritableStreamDefaultControllerErrorIfNeeded(
- binding.getWritableStreamController(stream[_writable]), e);
-
- if (stream[_backpressure]) {
- TransformStreamSetBackpressure(stream, false);
- }
- }
-
- function TransformStreamSetBackpressure(stream, backpressure) {
- // assert(
- // stream[_backpressure] !== backpressure,
- // 'stream.[[backpressure]] is not backpressure');
-
- if (stream[_backpressureChangePromise] !== undefined) {
- resolvePromise(stream[_backpressureChangePromise], undefined);
- }
-
- stream[_backpressureChangePromise] = createPromise();
- stream[_backpressure] = backpressure;
- }
-
- class TransformStreamDefaultController {
- constructor() {
- throw new TypeError(streamErrors.illegalConstructor);
- }
-
- get desiredSize() {
- if (!IsTransformStreamDefaultController(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- const readableController = binding.getReadableStreamController(
- this[_controlledTransformStream][_readable]);
- return binding.ReadableStreamDefaultControllerGetDesiredSize(
- readableController);
- }
-
- enqueue(chunk) {
- if (!IsTransformStreamDefaultController(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- TransformStreamDefaultControllerEnqueue(this, chunk);
- }
-
- error(reason) {
- if (!IsTransformStreamDefaultController(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- TransformStreamDefaultControllerError(this, reason);
- }
-
- terminate() {
- if (!IsTransformStreamDefaultController(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
-
- TransformStreamDefaultControllerTerminate(this);
- }
- }
-
- const TransformStreamDefaultController_prototype =
- TransformStreamDefaultController.prototype;
-
- function IsTransformStreamDefaultController(x) {
- return hasOwnPropertyNoThrow(x, _controlledTransformStream);
- }
-
- function SetUpTransformStreamDefaultController(
- stream, controller, transformAlgorithm, flushAlgorithm) {
- // assert(
- // IsTransformStream(stream) === true,
- // '! IsTransformStream(_stream_) is *true*');
- // assert(
- // stream[_transformStreamController] === undefined,
- // '_stream_.[[transformStreamController]] is *undefined*');
- controller[_controlledTransformStream] = stream;
- stream[_transformStreamController] = controller;
- controller[_transformAlgorithm] = transformAlgorithm;
- controller[_flushAlgorithm] = flushAlgorithm;
- }
-
- function SetUpTransformStreamDefaultControllerFromTransformer(
- stream, transformer) {
- // assert(transformer !== undefined, '_transformer_ is not *undefined*');
- const controller = ObjectCreate(TransformStreamDefaultController_prototype);
- let transformAlgorithm;
- const transformMethod = transformer.transform;
- if (transformMethod !== undefined) {
- if (typeof transformMethod !== 'function') {
- throw new TypeError('transformer.transform is not a function');
- }
- transformAlgorithm = chunk =>
- PromiseCall2(transformMethod, transformer, chunk, controller);
- } else {
- transformAlgorithm = chunk => {
- try {
- TransformStreamDefaultControllerEnqueue(controller, chunk);
- return createResolvedPromise();
- } catch (resultValue) {
- return createRejectedPromise(resultValue);
- }
- };
- }
- const flushAlgorithm = CreateAlgorithmFromUnderlyingMethod(
- transformer, 'flush', 1, 'transformer.flush');
- SetUpTransformStreamDefaultController(
- stream, controller, transformAlgorithm, flushAlgorithm);
- }
-
- function TransformStreamDefaultControllerClearAlgorithms(controller) {
- controller[_transformAlgorithm] = undefined;
- controller[_flushAlgorithm] = undefined;
- }
-
- function TransformStreamDefaultControllerEnqueue(controller, chunk) {
- const stream = controller[_controlledTransformStream];
- const readableController =
- binding.getReadableStreamController(stream[_readable]);
-
- if (!binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
- readableController)) {
- throw binding.getReadableStreamEnqueueError(stream[_readable],
- readableController);
- }
-
- try {
- binding.ReadableStreamDefaultControllerEnqueue(readableController, chunk);
- } catch (e) {
- TransformStreamErrorWritableAndUnblockWrite(stream, e);
- throw binding.getReadableStreamStoredError(stream[_readable]);
- }
-
- const backpressure = binding.ReadableStreamDefaultControllerHasBackpressure(
- readableController);
- if (backpressure !== stream[_backpressure]) {
- // assert(backpressure, 'backpressure is true');
- TransformStreamSetBackpressure(stream, true);
- }
- }
-
- function TransformStreamDefaultControllerError(controller, e) {
- TransformStreamError(controller[_controlledTransformStream], e);
- }
-
- function TransformStreamDefaultControllerPerformTransform(controller, chunk) {
- const transformPromise = controller[_transformAlgorithm](chunk, controller);
- return thenPromise(transformPromise, undefined, r => {
- TransformStreamError(controller[_controlledTransformStream], r);
- throw r;
- });
- }
-
- function TransformStreamDefaultControllerTerminate(controller) {
- const stream = controller[_controlledTransformStream];
- const readableController =
- binding.getReadableStreamController(stream[_readable]);
-
- if (binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
- readableController)) {
- binding.ReadableStreamDefaultControllerClose(readableController);
- }
-
- const error = new TypeError(errStreamTerminated);
- TransformStreamErrorWritableAndUnblockWrite(stream, error);
- }
-
- function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) {
- // assert(
- // binding.isWritableStreamWritable(stream[_writable]),
- // `stream.[[writable]][[state]] is "writable"`);
-
- const controller = stream[_transformStreamController];
-
- if (stream[_backpressure]) {
- const backpressureChangePromise = stream[_backpressureChangePromise];
- // assert(
- // backpressureChangePromise !== undefined,
- // `backpressureChangePromise is not undefined`);
-
- return thenPromise(backpressureChangePromise, () => {
- const writable = stream[_writable];
- if (binding.isWritableStreamErroring(writable)) {
- throw binding.getWritableStreamStoredError(writable);
- }
- // assert(binding.isWritableStreamWritable(writable),
- // `state is "writable"`);
-
- return TransformStreamDefaultControllerPerformTransform(controller,
- chunk);
- });
- }
-
- return TransformStreamDefaultControllerPerformTransform(controller, chunk);
- }
-
- function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) {
- TransformStreamError(stream, reason);
- return createResolvedPromise();
- }
-
- function TransformStreamDefaultSinkCloseAlgorithm(stream) {
- const readable = stream[_readable];
- const controller = stream[_transformStreamController];
- const flushPromise = controller[_flushAlgorithm](controller);
- TransformStreamDefaultControllerClearAlgorithms(controller);
-
- return thenPromise(
- flushPromise,
- () => {
- if (binding.IsReadableStreamErrored(readable)) {
- throw binding.getReadableStreamStoredError(readable);
- }
-
- const readableController =
- binding.getReadableStreamController(readable);
- if (binding.ReadableStreamDefaultControllerCanCloseOrEnqueue(
- readableController)) {
- binding.ReadableStreamDefaultControllerClose(readableController);
- }
- },
- r => {
- TransformStreamError(stream, r);
- throw binding.getReadableStreamStoredError(readable);
- });
- }
-
- function TransformStreamDefaultSourcePullAlgorithm(stream) {
- // assert(stream[_backpressure], 'stream.[[backpressure]] is true');
- // assert(
- // stream[_backpressureChangePromise] !== undefined,
- // 'stream.[[backpressureChangePromise]] is not undefined');
-
- TransformStreamSetBackpressure(stream, false);
- return stream[_backpressureChangePromise];
- }
-
- // A wrapper for CreateTransformStream() with only the arguments that
- // blink::TransformStream needs. |transformAlgorithm| and |flushAlgorithm| are
- // passed the controller, unlike in the standard.
- function createTransformStreamSimple(transformAlgorithm, flushAlgorithm) {
- return CreateTransformStream(() => createResolvedPromise(),
- transformAlgorithm, flushAlgorithm);
- }
- function createTransformStream(
- transformer, writableStrategy, readableStrategy) {
- if (transformer === undefined) {
- transformer = ObjectCreate(null);
- }
- if (writableStrategy === undefined) {
- writableStrategy = ObjectCreate(null);
- }
- if (readableStrategy === undefined) {
- readableStrategy = ObjectCreate(null);
- }
- return new TransformStream(transformer, writableStrategy, readableStrategy);
- }
-
- function getTransformStreamReadable(stream) {
- return stream[_readable];
- }
-
- function getTransformStreamWritable(stream) {
- return stream[_writable];
- }
-
- //
- // Exports to Blink
- //
- Object.assign(binding, {
- createTransformStreamSimple,
- createTransformStream,
- TransformStreamDefaultControllerEnqueue,
- getTransformStreamReadable,
- getTransformStreamWritable
- });
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/WritableStream.js b/chromium/third_party/blink/renderer/core/streams/WritableStream.js
deleted file mode 100644
index 58e2d6ec05c..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/WritableStream.js
+++ /dev/null
@@ -1,1093 +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.
-
-// Implementation of WritableStream for Blink. See
-// https://streams.spec.whatwg.org/#ws. The implementation closely follows the
-// standard, except where required for performance or integration with Blink.
-// In particular, classes, methods and abstract operations are implemented in
-// the same order as in the standard, to simplify side-by-side reading.
-
-(function(global, binding, v8) {
- 'use strict';
-
- // Private symbols. These correspond to the internal slots in the standard.
- // "[[X]]" in the standard is spelt _X in this implementation.
-
- // TODO(ricea): Optimise [[closeRequest]] and [[inFlightCloseRequest]] into a
- // single slot + a flag to say which one is set at the moment.
- const _abortAlgorithm = v8.createPrivateSymbol('[[abortAlgorithm]]');
- const _closeAlgorithm = v8.createPrivateSymbol('[[closeAlgorithm]]');
- const _closeRequest = v8.createPrivateSymbol('[[closeRequest]]');
- const _inFlightWriteRequest =
- v8.createPrivateSymbol('[[inFlightWriteRequest]]');
- const _inFlightCloseRequest =
- v8.createPrivateSymbol('[[inFlightCloseRequest]]');
- const _pendingAbortRequest =
- v8.createPrivateSymbol('[[pendingAbortRequest]]');
- // Flags and state are combined into a single integer field for efficiency.
- const _stateAndFlags = v8.createPrivateSymbol('[[state]] and flags');
- const _storedError = v8.createPrivateSymbol('[[storedError]]');
- const _writableStreamController =
- v8.createPrivateSymbol('[[writableStreamController]]');
- const _writer = v8.createPrivateSymbol('[[writer]]');
- const _writeRequests = v8.createPrivateSymbol('[[writeRequests]]');
- const _closedPromise = v8.createPrivateSymbol('[[closedPromise]]');
- const _ownerWritableStream =
- v8.createPrivateSymbol('[[ownerWritableStream]]');
- const _readyPromise = v8.createPrivateSymbol('[[readyPromise]]');
- const _controlledWritableStream =
- v8.createPrivateSymbol('[[controlledWritableStream]]');
- const _started = v8.createPrivateSymbol('[[started]]');
- const _strategyHWM = v8.createPrivateSymbol('[[strategyHWM]]');
- const _strategySizeAlgorithm =
- v8.createPrivateSymbol('[[strategySizeAlgorithm]]');
- const _writeAlgorithm = v8.createPrivateSymbol('[[writeAlgorithm]]');
- const internalWritableStreamSymbol = v8.createPrivateSymbol(
- 'internal WritableStream in exposed WritableStream interface');
-
- // Numeric encodings of stream states. Stored in the _stateAndFlags slot.
- const WRITABLE = 0;
- const CLOSED = 1;
- const ERRORING = 2;
- const ERRORED = 3;
-
- // Mask to extract or assign states to _stateAndFlags.
- const STATE_MASK = 0xF;
-
- // Also stored in _stateAndFlags.
- const BACKPRESSURE_FLAG = 0x10;
-
- // Javascript functions. It is important to use these copies, as the ones on
- // the global object may have been overwritten. See "V8 Extras Design Doc",
- // section "Security Considerations".
- // https://docs.google.com/document/d/1AT5-T0aHGp7Lt29vPWFr2-qG8r3l9CByyvKwEuA8Ec0/edit#heading=h.9yixony1a18r
- const ObjectCreate = global.Object.create;
-
- const Function_call = v8.uncurryThis(global.Function.prototype.call);
-
- const TypeError = global.TypeError;
- const RangeError = global.RangeError;
-
- const Boolean = global.Boolean;
-
- const Promise = global.Promise;
- const thenPromise = v8.uncurryThis(Promise.prototype.then);
-
- // From CommonOperations.js
- const {
- _queue,
- _queueTotalSize,
- createPromise,
- createRejectedPromise,
- createResolvedPromise,
- hasOwnPropertyNoThrow,
- rejectPromise,
- resolvePromise,
- markPromiseAsHandled,
- promiseState,
- CreateAlgorithmFromUnderlyingMethod,
- CreateAlgorithmFromUnderlyingMethodPassingController,
- DequeueValue,
- EnqueueValueWithSize,
- MakeSizeAlgorithmFromSizeFunction,
- PeekQueueValue,
- ResetQueue,
- ValidateAndNormalizeHighWaterMark,
- CreateCrossRealmTransformReadable,
- CreateCrossRealmTransformWritable,
- CallOrNoop1,
- } = binding.streamOperations;
-
- // User-visible strings.
- const streamErrors = binding.streamErrors;
- const errWriterLockReleasedPrefix =
- 'This writable stream writer has been released and cannot be ';
- const errCloseCloseRequestedStream = 'Cannot close a writable stream that ' +
- 'has already been requested to be closed';
- const templateErrorCannotActionOnStateStream = (action, state) =>
- `Cannot ${action} a ${state} writable stream`;
- const errReleasedWriterClosedPromise = 'This writable stream writer has ' +
- 'been released and cannot be used to monitor the stream\'s state';
-
- // These verbs are used after errWriterLockReleasedPrefix
- const verbUsedToGetTheDesiredSize = 'used to get the desiredSize';
- const verbAborted = 'aborted';
- const verbClosed = 'closed';
- const verbWrittenTo = 'written to';
-
- // Utility functions (not from the standard).
- function createWriterLockReleasedError(verb) {
- return new TypeError(errWriterLockReleasedPrefix + verb);
- }
-
- const stateNames = {
- [CLOSED]: 'closed',
- [ERRORED]: 'errored'
- };
- function createCannotActionOnStateStreamError(action, state) {
- // assert(stateNames[state] !== undefined,
- // `name for state ${state} exists in stateNames`);
- return new TypeError(
- templateErrorCannotActionOnStateStream(action, stateNames[state]));
- }
-
- function rejectPromises(queue, e) {
- queue.forEach(promise => rejectPromise(promise, e));
- }
-
- class WritableStream {
- constructor(underlyingSink = {}, strategy = {}) {
- InitializeWritableStream(this);
- const size = strategy.size;
- let highWaterMark = strategy.highWaterMark;
- const type = underlyingSink.type;
- if (type !== undefined) {
- throw new RangeError(streamErrors.invalidType);
- }
- const sizeAlgorithm = MakeSizeAlgorithmFromSizeFunction(size);
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
- highWaterMark = ValidateAndNormalizeHighWaterMark(highWaterMark);
- SetUpWritableStreamDefaultControllerFromUnderlyingSink(
- this, underlyingSink, highWaterMark, sizeAlgorithm);
- }
- }
-
- const WritableStream_prototype = WritableStream.prototype;
-
- function createWritableStream(underlyingSink, strategy) {
- return new WritableStream(underlyingSink, strategy);
- }
-
- // General Writable Stream Abstract Operations
-
- function AcquireWritableStreamDefaultWriter(stream) {
- return new WritableStreamDefaultWriter(stream);
- }
-
- function CreateWritableStream(
- startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm,
- highWaterMark, sizeAlgorithm) {
- if (highWaterMark === undefined) {
- highWaterMark = 1;
- }
- if (sizeAlgorithm === undefined) {
- sizeAlgorithm = () => 1;
- }
- // assert(IsNonNegativeNumber(highWaterMark),
- // '! IsNonNegativeNumber(_highWaterMark_) is *true*.')
- const stream = ObjectCreate(WritableStream_prototype);
- InitializeWritableStream(stream);
- const controller = ObjectCreate(WritableStreamDefaultController_prototype);
- SetUpWritableStreamDefaultController(
- stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm,
- abortAlgorithm, highWaterMark, sizeAlgorithm);
- return stream;
- }
-
- function InitializeWritableStream(stream) {
- stream[_stateAndFlags] = WRITABLE;
- stream[_storedError] = undefined;
- stream[_writer] = undefined;
- stream[_writableStreamController] = undefined;
- stream[_inFlightWriteRequest] = undefined;
- stream[_closeRequest] = undefined;
- stream[_inFlightCloseRequest] = undefined;
- stream[_pendingAbortRequest] = undefined;
- stream[_writeRequests] = new binding.SimpleQueue();
- }
-
- function IsWritableStream(x) {
- return hasOwnPropertyNoThrow(x, _writableStreamController);
- }
-
- function IsWritableStreamLocked(stream) {
- // assert(IsWritableStream(stream),
- // '! IsWritableStream(stream) is true.');
- return stream[_writer] !== undefined;
- }
-
- function WritableStreamAbort(stream, reason) {
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === CLOSED || state === ERRORED) {
- return createResolvedPromise(undefined);
- }
- if (stream[_pendingAbortRequest] !== undefined) {
- return stream[_pendingAbortRequest].promise;
- }
-
- // assert(state === WRITABLE || state === ERRORING,
- // '_state_ is `"writable"` or `"erroring"`');
-
- const wasAlreadyErroring = state === ERRORING;
- if (wasAlreadyErroring) {
- reason = undefined;
- }
-
- const promise = createPromise();
- stream[_pendingAbortRequest] = {promise, reason, wasAlreadyErroring};
-
- if (!wasAlreadyErroring) {
- WritableStreamStartErroring(stream, reason);
- }
- return promise;
- }
-
- // Writable Stream Abstract Operations Used by Controllers
-
- function WritableStreamAddWriteRequest(stream) {
- // assert(IsWritableStreamLocked(stream),
- // '! IsWritableStreamLocked(writer) is true.');
- // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
- // 'stream.[[state]] is "writable".');
- const promise = createPromise();
- stream[_writeRequests].push(promise);
- return promise;
- }
-
- function WritableStreamDealWithRejection(stream, error) {
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === WRITABLE) {
- WritableStreamStartErroring(stream, error);
- return;
- }
-
- // assert(state === ERRORING, '_state_ is `"erroring"`');
- WritableStreamFinishErroring(stream);
- }
-
- function WritableStreamStartErroring(stream, reason) {
- // assert(stream[_storedError] === undefined,
- // '_stream_.[[storedError]] is *undefined*');
- // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
- // '_stream_.[[state]] is `"writable"`');
-
- const controller = stream[_writableStreamController];
- // assert(controller !== undefined, '_controller_ is not *undefined*');
-
- stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORING;
- stream[_storedError] = reason;
-
- const writer = stream[_writer];
- if (writer !== undefined) {
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
- }
-
- if (!WritableStreamHasOperationMarkedInFlight(stream) &&
- controller[_started]) {
- WritableStreamFinishErroring(stream);
- }
- }
-
- function WritableStreamFinishErroring(stream) {
- // assert((stream[_stateAndFlags] & STATE_MASK) === ERRORING,
- // '_stream_.[[state]] is `"erroring"`');
- // assert(!WritableStreamHasOperationMarkedInFlight(stream),
- // '! WritableStreamHasOperationMarkedInFlight(_stream_) is ' +
- // '*false*');
-
- stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | ERRORED;
-
- WritableStreamDefaultControllerErrorSteps(
- stream[_writableStreamController]);
-
- const storedError = stream[_storedError];
- rejectPromises(stream[_writeRequests], storedError);
- stream[_writeRequests] = new binding.SimpleQueue();
-
- if (stream[_pendingAbortRequest] === undefined) {
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
-
- const abortRequest = stream[_pendingAbortRequest];
- stream[_pendingAbortRequest] = undefined;
-
- if (abortRequest.wasAlreadyErroring === true) {
- rejectPromise(abortRequest.promise, storedError);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- return;
- }
-
- const promise = WritableStreamDefaultControllerAbortSteps(
- stream[_writableStreamController], abortRequest.reason);
-
- thenPromise(
- promise,
- () => {
- resolvePromise(abortRequest.promise, undefined);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- },
- reason => {
- rejectPromise(abortRequest.promise, reason);
- WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
- });
- }
-
- function WritableStreamFinishInFlightWrite(stream) {
- // assert(stream[_inFlightWriteRequest] !== undefined,
- // '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
- resolvePromise(stream[_inFlightWriteRequest], undefined);
- stream[_inFlightWriteRequest] = undefined;
- }
-
- function WritableStreamFinishInFlightWriteWithError(stream, error) {
- // assert(stream[_inFlightWriteRequest] !== undefined,
- // '_stream_.[[inFlightWriteRequest]] is not *undefined*.');
- rejectPromise(stream[_inFlightWriteRequest], error);
- stream[_inFlightWriteRequest] = undefined;
-
- // const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_stream_.[[state]] is `"writable"` or `"erroring"`');
-
- WritableStreamDealWithRejection(stream, error);
- }
-
- function WritableStreamFinishInFlightClose(stream) {
- // assert(stream[_inFlightCloseRequest] !== undefined,
- // '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
- resolvePromise(stream[_inFlightCloseRequest], undefined);
- stream[_inFlightCloseRequest] = undefined;
-
- const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_stream_.[[state]] is `"writable"` or `"erroring"`');
-
- if (state === ERRORING) {
- stream[_storedError] = undefined;
- if (stream[_pendingAbortRequest] !== undefined) {
- resolvePromise(stream[_pendingAbortRequest].promise, undefined);
- stream[_pendingAbortRequest] = undefined;
- }
- }
-
- stream[_stateAndFlags] = (stream[_stateAndFlags] & ~STATE_MASK) | CLOSED;
- const writer = stream[_writer];
- if (writer !== undefined) {
- resolvePromise(writer[_closedPromise], undefined);
- }
-
- // assert(stream[_pendingAbortRequest] === undefined,
- // '_stream_.[[pendingAbortRequest]] is *undefined*');
- // assert(stream[_storedError] === undefined,
- // '_stream_.[[storedError]] is *undefined*');
- }
-
- function WritableStreamFinishInFlightCloseWithError(stream, error) {
- // assert(stream[_inFlightCloseRequest] !== undefined,
- // '_stream_.[[inFlightCloseRequest]] is not *undefined*.');
- rejectPromise(stream[_inFlightCloseRequest], error);
- stream[_inFlightCloseRequest] = undefined;
-
- // const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_stream_.[[state]] is `"writable"` or `"erroring"`');
-
- if (stream[_pendingAbortRequest] !== undefined) {
- rejectPromise(stream[_pendingAbortRequest].promise, error);
- stream[_pendingAbortRequest] = undefined;
- }
-
- WritableStreamDealWithRejection(stream, error);
- }
-
- function WritableStreamCloseQueuedOrInFlight(stream) {
- return stream[_closeRequest] !== undefined ||
- stream[_inFlightCloseRequest] !== undefined;
- }
-
- function WritableStreamHasOperationMarkedInFlight(stream) {
- return stream[_inFlightWriteRequest] !== undefined ||
- stream[_inFlightCloseRequest] !== undefined;
- }
-
- function WritableStreamMarkCloseRequestInFlight(stream) {
- // assert(stream[_inFlightCloseRequest] === undefined,
- // '_stream_.[[inFlightCloseRequest]] is *undefined*.');
- // assert(stream[_closeRequest] !== undefined,
- // '_stream_.[[closeRequest]] is not *undefined*.');
- stream[_inFlightCloseRequest] = stream[_closeRequest];
- stream[_closeRequest] = undefined;
- }
-
- function WritableStreamMarkFirstWriteRequestInFlight(stream) {
- // assert(stream[_inFlightWriteRequest] === undefined,
- // '_stream_.[[inFlightWriteRequest]] is *undefined*.');
- // assert(stream[_writeRequests].length !== 0,
- // '_stream_.[[writeRequests]] is not empty.');
- const writeRequest = stream[_writeRequests].shift();
- stream[_inFlightWriteRequest] = writeRequest;
- }
-
- function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
- // assert((stream[_stateAndFlags] & STATE_MASK) === ERRORED,
- // '_stream_.[[state]] is `"errored"`');
-
- if (stream[_closeRequest] !== undefined) {
- // assert(stream[_inFlightCloseRequest] === undefined,
- // '_stream_.[[inFlightCloseRequest]] is *undefined*');
- rejectPromise(stream[_closeRequest], stream[_storedError]);
- stream[_closeRequest] = undefined;
- }
-
- const writer = stream[_writer];
- if (writer !== undefined) {
- rejectPromise(writer[_closedPromise], stream[_storedError]);
- markPromiseAsHandled(writer[_closedPromise]);
- }
- }
-
- function WritableStreamUpdateBackpressure(stream, backpressure) {
- // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
- // 'stream.[[state]] is "writable".');
- // assert(!WritableStreamCloseQueuedOrInFlight(stream),
- // 'WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
- const writer = stream[_writer];
- if (writer !== undefined &&
- backpressure !== Boolean(stream[_stateAndFlags] & BACKPRESSURE_FLAG)) {
- if (backpressure) {
- writer[_readyPromise] = createPromise();
- } else {
- // assert(!backpressure, '_backpressure_ is *false*.');
- resolvePromise(writer[_readyPromise], undefined);
- }
- }
- if (backpressure) {
- stream[_stateAndFlags] |= BACKPRESSURE_FLAG;
- } else {
- stream[_stateAndFlags] &= ~BACKPRESSURE_FLAG;
- }
- }
-
- //
- // Functions for transferable streams.
- //
-
- // The |port| which is passed to this function must be a MessagePort which is
- // attached by a MessageChannel to the |port| that will be passed to
- // WritableStreamDeserialize.
- function WritableStreamSerialize(writable, port) {
- // assert(IsWritableStream(writable),
- // `! IsWritableStream(_writable_) is true`);
- if (IsWritableStreamLocked(writable)) {
- throw new TypeError(streamErrors.cannotTransferLockedStream);
- }
-
- if (!binding.MessagePort_postMessage) {
- throw new TypeError(streamErrors.cannotTransferContext);
- }
-
- const readable = CreateCrossRealmTransformReadable(port);
- const promise =
- binding.ReadableStreamPipeTo(readable, writable, false, false, false);
- markPromiseAsHandled(promise);
- }
-
- function WritableStreamDeserialize(port) {
- return CreateCrossRealmTransformWritable(port);
- }
-
- // Functions to expose internals for ReadableStream.pipeTo. These are not
- // part of the standard.
- function isWritableStreamErrored(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return (stream[_stateAndFlags] & STATE_MASK) === ERRORED;
- }
-
- function isWritableStreamClosingOrClosed(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return WritableStreamCloseQueuedOrInFlight(stream) ||
- (stream[_stateAndFlags] & STATE_MASK) === CLOSED;
- }
-
- function getWritableStreamStoredError(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return stream[_storedError];
- }
-
- // Expose internals for TransformStream
- function isWritableStreamWritable(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return (stream[_stateAndFlags] & STATE_MASK) === WRITABLE;
- }
-
- function isWritableStreamErroring(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return (stream[_stateAndFlags] & STATE_MASK) === ERRORING;
- }
-
- function getWritableStreamController(stream) {
- // assert(
- // IsWritableStream(stream), '! IsWritableStream(stream) is true.');
- return stream[_writableStreamController];
- }
-
- class WritableStreamDefaultWriter {
- constructor(stream) {
- // |stream| here can be either an external WritableStream (i.e.,
- // IDL defined WritableStream) or an internal WritableStream (i.e.,
- // the class defined in this file). In the former case, the
- // internal stream is stored in [internalWritableStreamSymbol], so use it
- // from now on.
- if (stream[internalWritableStreamSymbol] !== undefined) {
- stream = stream[internalWritableStreamSymbol];
- }
- if (!IsWritableStream(stream)) {
- throw new TypeError(streamErrors.illegalConstructor);
- }
- if (IsWritableStreamLocked(stream)) {
- throw new TypeError(streamErrors.illegalConstructor);
- }
- this[_ownerWritableStream] = stream;
- stream[_writer] = this;
- const state = stream[_stateAndFlags] & STATE_MASK;
- switch (state) {
- case WRITABLE: {
- if (!WritableStreamCloseQueuedOrInFlight(stream) &&
- stream[_stateAndFlags] & BACKPRESSURE_FLAG) {
- this[_readyPromise] = createPromise();
- } else {
- this[_readyPromise] = createResolvedPromise(undefined);
- }
- this[_closedPromise] = createPromise();
- break;
- }
-
- case ERRORING: {
- this[_readyPromise] = createRejectedPromise(stream[_storedError]);
- markPromiseAsHandled(this[_readyPromise]);
- this[_closedPromise] = createPromise();
- break;
- }
-
- case CLOSED: {
- this[_readyPromise] = createResolvedPromise(undefined);
- this[_closedPromise] = createResolvedPromise(undefined);
- break;
- }
-
- default: {
- // assert(state === ERRORED, '_state_ is `"errored"`.');
- const storedError = stream[_storedError];
- this[_readyPromise] = createRejectedPromise(storedError);
- markPromiseAsHandled(this[_readyPromise]);
- this[_closedPromise] = createRejectedPromise(storedError);
- markPromiseAsHandled(this[_closedPromise]);
- break;
- }
- }
- }
-
- get closed() {
- if (!IsWritableStreamDefaultWriter(this)) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
- return this[_closedPromise];
- }
-
- get desiredSize() {
- if (!IsWritableStreamDefaultWriter(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
- if (this[_ownerWritableStream] === undefined) {
- throw createWriterLockReleasedError(verbUsedToGetTheDesiredSize);
- }
- return WritableStreamDefaultWriterGetDesiredSize(this);
- }
-
- get ready() {
- if (!IsWritableStreamDefaultWriter(this)) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
- return this[_readyPromise];
- }
-
- abort(reason) {
- if (!IsWritableStreamDefaultWriter(this)) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
- if (this[_ownerWritableStream] === undefined) {
- return createRejectedPromise(
- createWriterLockReleasedError(verbAborted));
- }
- return WritableStreamDefaultWriterAbort(this, reason);
- }
-
- close() {
- if (!IsWritableStreamDefaultWriter(this)) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
- const stream = this[_ownerWritableStream];
- if (stream === undefined) {
- return createRejectedPromise(createWriterLockReleasedError(verbClosed));
- }
- if (WritableStreamCloseQueuedOrInFlight(stream)) {
- return createRejectedPromise(
- new TypeError(errCloseCloseRequestedStream));
- }
- return WritableStreamDefaultWriterClose(this);
- }
-
- releaseLock() {
- if (!IsWritableStreamDefaultWriter(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
- const stream = this[_ownerWritableStream];
- if (stream === undefined) {
- return;
- }
- // assert(stream[_writer] !== undefined,
- // 'stream.[[writer]] is not undefined.');
- WritableStreamDefaultWriterRelease(this);
- }
-
- write(chunk) {
- if (!IsWritableStreamDefaultWriter(this)) {
- return createRejectedPromise(
- new TypeError(streamErrors.illegalInvocation));
- }
- if (this[_ownerWritableStream] === undefined) {
- return createRejectedPromise(
- createWriterLockReleasedError(verbWrittenTo));
- }
- return WritableStreamDefaultWriterWrite(this, chunk);
- }
- }
-
- // Writable Stream Writer Abstract Operations
-
- function IsWritableStreamDefaultWriter(x) {
- return hasOwnPropertyNoThrow(x, _ownerWritableStream);
- }
-
- function WritableStreamDefaultWriterAbort(writer, reason) {
- const stream = writer[_ownerWritableStream];
- // assert(stream !== undefined,
- // 'stream is not undefined.');
- return WritableStreamAbort(stream, reason);
- }
-
- function WritableStreamDefaultWriterClose(writer) {
- const stream = writer[_ownerWritableStream];
- // assert(stream !== undefined, 'stream is not undefined.');
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === CLOSED || state === ERRORED) {
- return createRejectedPromise(
- createCannotActionOnStateStreamError('close', state));
- }
-
- // assert(state === WRITABLE || state === ERRORING,
- // '_state_ is `"writable"` or `"erroring"`.');
- // assert(!WritableStreamCloseQueuedOrInFlight(stream),
- // '! WritableStreamCloseQueuedOrInFlight(_stream_) is *false*.');
- const promise = createPromise();
- stream[_closeRequest] = promise;
-
- if ((stream[_stateAndFlags] & BACKPRESSURE_FLAG) && state === WRITABLE) {
- resolvePromise(writer[_readyPromise], undefined);
- }
- WritableStreamDefaultControllerClose(stream[_writableStreamController]);
- return promise;
- }
-
- function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
- const stream = writer[_ownerWritableStream];
- // assert(stream !== undefined, 'stream is not undefined.');
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (WritableStreamCloseQueuedOrInFlight(stream) || state === CLOSED) {
- return createResolvedPromise(undefined);
- }
- if (state === ERRORED) {
- return createRejectedPromise(stream[_storedError]);
- }
-
- // assert(state === WRITABLE || state === ERRORING,
- // '_state_ is `"writable"` or `"erroring"`.');
-
- return WritableStreamDefaultWriterClose(writer);
- }
-
- function WritableStreamDefaultWriterEnsureClosedPromiseRejected(
- writer, error) {
- if (promiseState(writer[_closedPromise]) === v8.kPROMISE_PENDING) {
- rejectPromise(writer[_closedPromise], error);
- } else {
- writer[_closedPromise] = createRejectedPromise(error);
- }
- markPromiseAsHandled(writer[_closedPromise]);
- }
-
-
- function WritableStreamDefaultWriterEnsureReadyPromiseRejected(
- writer, error) {
- if (promiseState(writer[_readyPromise]) === v8.kPROMISE_PENDING) {
- rejectPromise(writer[_readyPromise], error);
- } else {
- writer[_readyPromise] = createRejectedPromise(error);
- }
- markPromiseAsHandled(writer[_readyPromise]);
- }
-
- function WritableStreamDefaultWriterGetDesiredSize(writer) {
- const stream = writer[_ownerWritableStream];
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED || state === ERRORING) {
- return null;
- }
- if (state === CLOSED) {
- return 0;
- }
- return WritableStreamDefaultControllerGetDesiredSize(
- stream[_writableStreamController]);
- }
-
- function WritableStreamDefaultWriterRelease(writer) {
- const stream = writer[_ownerWritableStream];
- // assert(stream !== undefined,
- // 'stream is not undefined.');
- // assert(stream[_writer] === writer,
- // 'stream.[[writer]] is writer.');
- const releasedError = new TypeError(errReleasedWriterClosedPromise);
- WritableStreamDefaultWriterEnsureReadyPromiseRejected(
- writer, releasedError);
- WritableStreamDefaultWriterEnsureClosedPromiseRejected(
- writer, releasedError);
- stream[_writer] = undefined;
- writer[_ownerWritableStream] = undefined;
- }
-
- function WritableStreamDefaultWriterWrite(writer, chunk) {
- const stream = writer[_ownerWritableStream];
- // assert(stream !== undefined, 'stream is not undefined.');
- const controller = stream[_writableStreamController];
- const chunkSize =
- WritableStreamDefaultControllerGetChunkSize(controller, chunk);
- if (stream !== writer[_ownerWritableStream]) {
- return createRejectedPromise(
- createWriterLockReleasedError(verbWrittenTo));
- }
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === ERRORED) {
- return createRejectedPromise(stream[_storedError]);
- }
- if (WritableStreamCloseQueuedOrInFlight(stream)) {
- return createRejectedPromise(new TypeError(
- templateErrorCannotActionOnStateStream('write to', 'closing')));
- }
- if (state === CLOSED) {
- return createRejectedPromise(
- createCannotActionOnStateStreamError('write to', CLOSED));
- }
- if (state === ERRORING) {
- return createRejectedPromise(stream[_storedError]);
- }
- // assert(state === WRITABLE, '_state_ is `"writable"`');
- const promise = WritableStreamAddWriteRequest(stream);
- WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
- return promise;
- }
-
- // Functions to expose internals for ReadableStream.pipeTo. These do not
- // appear in the standard.
- function getWritableStreamDefaultWriterClosedPromise(writer) {
- // assert(
- // IsWritableStreamDefaultWriter(writer),
- // 'writer is a WritableStreamDefaultWriter.');
- return writer[_closedPromise];
- }
-
- function getWritableStreamDefaultWriterReadyPromise(writer) {
- // assert(
- // IsWritableStreamDefaultWriter(writer),
- // 'writer is a WritableStreamDefaultWriter.');
- return writer[_readyPromise];
- }
-
- class WritableStreamDefaultController {
- constructor() {
- throw new TypeError(streamErrors.illegalConstructor);
- }
-
- error(e) {
- if (!IsWritableStreamDefaultController(this)) {
- throw new TypeError(streamErrors.illegalInvocation);
- }
- const state =
- this[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
- if (state !== WRITABLE) {
- return;
- }
- WritableStreamDefaultControllerError(this, e);
- }
- }
-
- const WritableStreamDefaultController_prototype =
- WritableStreamDefaultController.prototype;
-
- // Writable Stream Default Controller Internal Methods
-
- // TODO(ricea): Virtual dispatch via V8 Private Symbols seems to be difficult
- // or impossible, so use static dispatch for now. This will have to be fixed
- // when adding a byte controller.
- function WritableStreamDefaultControllerAbortSteps(controller, reason) {
- const result = controller[_abortAlgorithm](reason);
- WritableStreamDefaultControllerClearAlgorithms(controller);
- return result;
- }
-
- function WritableStreamDefaultControllerErrorSteps(controller) {
- ResetQueue(controller);
- }
-
- // Writable Stream Default Controller Abstract Operations
-
- function IsWritableStreamDefaultController(x) {
- return hasOwnPropertyNoThrow(x, _controlledWritableStream);
- }
-
- function SetUpWritableStreamDefaultController(
- stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm,
- abortAlgorithm, highWaterMark, sizeAlgorithm) {
- // assert(IsWritableStream(stream), '! IsWritableStream(_stream_) is
- // *true*.');
- // assert(stream[_writableStreamController] === undefined,
- // '_stream_.[[writableStreamController]] is *undefined*.');
- controller[_controlledWritableStream] = stream;
- stream[_writableStreamController] = controller;
- // These are just initialised to avoid triggering the assert() in
- // ResetQueue. They are overwritten by ResetQueue().
- controller[_queue] = undefined;
- controller[_queueTotalSize] = undefined;
- ResetQueue(controller);
- controller[_started] = false;
- controller[_strategySizeAlgorithm] = sizeAlgorithm;
- controller[_strategyHWM] = highWaterMark;
- controller[_writeAlgorithm] = writeAlgorithm;
- controller[_closeAlgorithm] = closeAlgorithm;
- controller[_abortAlgorithm] = abortAlgorithm;
- const backpressure =
- WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- const startResult = startAlgorithm();
- const startPromise = createResolvedPromise(startResult);
- thenPromise(
- startPromise,
- () => {
- // const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_stream_.[[state]] is `"writable"` or `"erroring"`');
- controller[_started] = true;
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- },
- r => {
- // const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_stream_.[[state]] is `"writable"` or `"erroring"`');
- controller[_started] = true;
- WritableStreamDealWithRejection(stream, r);
- });
- }
-
- function SetUpWritableStreamDefaultControllerFromUnderlyingSink(
- stream, underlyingSink, highWaterMark, sizeAlgorithm) {
- // assert(underlyingSink !== undefined, '_underlyingSink_ is not ' +
- // '*undefined*.');
- const controller = ObjectCreate(WritableStreamDefaultController_prototype);
- const startAlgorithm =
- () => CallOrNoop1(underlyingSink, 'start', controller,
- 'underlyingSink.start');
- const writeAlgorithm = CreateAlgorithmFromUnderlyingMethodPassingController(
- underlyingSink, 'write', 1, controller, 'underlyingSink.write');
- const closeAlgorithm = CreateAlgorithmFromUnderlyingMethod(
- underlyingSink, 'close', 0, 'underlyingSink.close');
- const abortAlgorithm = CreateAlgorithmFromUnderlyingMethod(
- underlyingSink, 'abort', 1, 'underlyingSink.abort');
- SetUpWritableStreamDefaultController(stream, controller, startAlgorithm,
- writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark,
- sizeAlgorithm);
- }
-
- function WritableStreamDefaultControllerClearAlgorithms(controller) {
- controller[_writeAlgorithm] = undefined;
- controller[_closeAlgorithm] = undefined;
- controller[_abortAlgorithm] = undefined;
- }
-
- function WritableStreamDefaultControllerClose(controller) {
- EnqueueValueWithSize(controller, 'close', 0);
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
-
- function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
- try {
- // Unlike other algorithms, strategySizeAlgorithm isn't indirected, so we
- // need to be careful with the |this| value.
- return Function_call(controller[_strategySizeAlgorithm], undefined,
- chunk);
- } catch (e) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, e);
- return 1;
- }
- }
-
- function WritableStreamDefaultControllerGetDesiredSize(controller) {
- return controller[_strategyHWM] - controller[_queueTotalSize];
- }
-
- function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
- const writeRecord = {chunk};
- try {
- EnqueueValueWithSize(controller, writeRecord, chunkSize);
- } catch (e) {
- WritableStreamDefaultControllerErrorIfNeeded(controller, e);
- return;
- }
- const stream = controller[_controlledWritableStream];
- if (!WritableStreamCloseQueuedOrInFlight(stream) &&
- (stream[_stateAndFlags] & STATE_MASK) === WRITABLE) {
- const backpressure =
- WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- }
-
- function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
- const stream = controller[_controlledWritableStream];
- if (!controller[_started]) {
- return;
- }
- if (stream[_inFlightWriteRequest] !== undefined) {
- return;
- }
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === CLOSED || state === ERRORED) {
- return;
- }
- if (state === ERRORING) {
- WritableStreamFinishErroring(stream);
- return;
- }
- if (controller[_queue].length === 0) {
- return;
- }
- const writeRecord = PeekQueueValue(controller);
- if (writeRecord === 'close') {
- WritableStreamDefaultControllerProcessClose(controller);
- } else {
- WritableStreamDefaultControllerProcessWrite(
- controller, writeRecord.chunk);
- }
- }
-
- function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
- const state =
- controller[_controlledWritableStream][_stateAndFlags] & STATE_MASK;
- if (state === WRITABLE) {
- WritableStreamDefaultControllerError(controller, error);
- }
- }
-
- function WritableStreamDefaultControllerProcessClose(controller) {
- const stream = controller[_controlledWritableStream];
- WritableStreamMarkCloseRequestInFlight(stream);
- DequeueValue(controller);
- // assert(controller[_queue].length === 0,
- // 'controller.[[queue]] is empty.');
- const sinkClosePromise = controller[_closeAlgorithm]();
- WritableStreamDefaultControllerClearAlgorithms(controller);
- thenPromise(
- sinkClosePromise, () => WritableStreamFinishInFlightClose(stream),
- reason => WritableStreamFinishInFlightCloseWithError(stream, reason));
- }
-
- function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
- const stream = controller[_controlledWritableStream];
- WritableStreamMarkFirstWriteRequestInFlight(stream);
- const sinkWritePromise = controller[_writeAlgorithm](chunk);
- thenPromise(
- sinkWritePromise,
- () => {
- WritableStreamFinishInFlightWrite(stream);
- const state = stream[_stateAndFlags] & STATE_MASK;
- // assert(state === WRITABLE || state === ERRORING,
- // '_state_ is `"writable"` or `"erroring"`');
- DequeueValue(controller);
- if (!WritableStreamCloseQueuedOrInFlight(stream) &&
- state === WRITABLE) {
- const backpressure =
- WritableStreamDefaultControllerGetBackpressure(controller);
- WritableStreamUpdateBackpressure(stream, backpressure);
- }
- WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
- },
- reason => {
- const state = stream[_stateAndFlags] & STATE_MASK;
- if (state === WRITABLE) {
- WritableStreamDefaultControllerClearAlgorithms(controller);
- }
- WritableStreamFinishInFlightWriteWithError(stream, reason);
- });
- }
-
- function WritableStreamDefaultControllerGetBackpressure(controller) {
- const desiredSize =
- WritableStreamDefaultControllerGetDesiredSize(controller);
- return desiredSize <= 0;
- }
-
- function WritableStreamDefaultControllerError(controller, error) {
- const stream = controller[_controlledWritableStream];
- // assert((stream[_stateAndFlags] & STATE_MASK) === WRITABLE,
- // '_stream_.[[state]] is `"writable"`.');
- WritableStreamDefaultControllerClearAlgorithms(controller);
- WritableStreamStartErroring(stream, error);
- }
-
- Object.assign(binding, {
- // Exports for ReadableStream
- AcquireWritableStreamDefaultWriter,
- IsWritableStream,
- isWritableStreamClosingOrClosed,
- isWritableStreamErrored,
- isWritableStreamWritable,
- IsWritableStreamLocked,
- WritableStreamAbort,
- WritableStreamCloseQueuedOrInFlight,
- WritableStreamDefaultWriterCloseWithErrorPropagation,
- getWritableStreamDefaultWriterClosedPromise,
- WritableStreamDefaultWriterGetDesiredSize,
- getWritableStreamDefaultWriterReadyPromise,
- WritableStreamDefaultWriterRelease,
- WritableStreamDefaultWriterWrite,
- getWritableStreamStoredError,
-
- // Exports for blink
- createWritableStream,
- internalWritableStreamSymbol,
- WritableStreamSerialize,
- WritableStreamDeserialize,
-
- // Additional exports for TransformStream
- CreateWritableStream,
- WritableStream,
- WritableStreamDefaultControllerErrorIfNeeded,
- isWritableStreamErroring,
- getWritableStreamController,
-
- // Exports for CreateCrossRealmTransformWritable in CommonOperations.js
- WritableStreamDefaultControllerClose,
- });
-});
diff --git a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
index aae8fb8bc29..e5ea5c46b42 100644
--- a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
+++ b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
@@ -81,7 +81,7 @@ ByteLengthQueuingStrategy::~ByteLengthQueuingStrategy() = default;
ScriptValue ByteLengthQueuingStrategy::highWaterMark(
ScriptState* script_state) const {
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
high_water_mark_.NewLocal(script_state->GetIsolate()));
}
@@ -89,7 +89,7 @@ ScriptValue ByteLengthQueuingStrategy::size(ScriptState* script_state) const {
// We don't cache the result because normally this method will only be called
// once anyway.
return ScriptValue(
- script_state,
+ script_state->GetIsolate(),
ByteLengthQueuingStrategySizeFunction::CreateFunction(script_state));
}
diff --git a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
index af68396eb0e..193a1809f48 100644
--- a/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
+++ b/chromium/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
@@ -6,7 +6,6 @@
[
Exposed=(Window,Worker,Worklet),
- RuntimeEnabled=StreamsNative,
ConstructorCallWith=ScriptState,
Constructor([PermissiveDictionaryConversion] QueuingStrategyInit init)
] interface ByteLengthQueuingStrategy {
diff --git a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
index 2b1aa3b9c24..601fecf4ab0 100644
--- a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
+++ b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
@@ -52,7 +52,7 @@ CountQueuingStrategy::~CountQueuingStrategy() = default;
ScriptValue CountQueuingStrategy::highWaterMark(
ScriptState* script_state) const {
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
high_water_mark_.NewLocal(script_state->GetIsolate()));
}
@@ -60,7 +60,7 @@ ScriptValue CountQueuingStrategy::size(ScriptState* script_state) const {
// We don't cache the result because normally this method will only be called
// once anyway.
return ScriptValue(
- script_state,
+ script_state->GetIsolate(),
CountQueuingStrategySizeFunction::CreateFunction(script_state));
}
diff --git a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
index 02cfe7a9715..bf838cd2c29 100644
--- a/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
+++ b/chromium/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
@@ -6,7 +6,6 @@
[
Exposed=(Window,Worker,Worklet),
- RuntimeEnabled=StreamsNative,
ConstructorCallWith=ScriptState,
Constructor([PermissiveDictionaryConversion] QueuingStrategyInit init)
] interface CountQueuingStrategy {
diff --git a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.cc b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
index ff297a10f65..44d9914b791 100644
--- a/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
+++ b/chromium/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
@@ -609,7 +609,7 @@ CORE_EXPORT void PipeThroughExtractReadableWritable(
return;
}
*writable_stream = dom_writable;
- *readable_stream = ScriptValue(script_state, readable);
+ *readable_stream = ScriptValue(script_state->GetIsolate(), readable);
}
CORE_EXPORT WritableStream* PipeToCheckSourceAndDestination(
@@ -699,7 +699,7 @@ ScriptValue CallTeeAndReturnBranchArray(ScriptState* script_state,
exception_state.RethrowV8Exception(block.Exception());
return ScriptValue();
}
- return ScriptValue(script_state, array);
+ return ScriptValue(script_state->GetIsolate(), array);
}
void ScriptValueToObject(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.cc b/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.cc
index 3130e85f1c2..1fcd96a1cda 100644
--- a/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.cc
+++ b/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.cc
@@ -23,7 +23,7 @@ bool IsFiniteNonNegativeNumber(double v) {
} // namespace
class QueueWithSizes::ValueSizePair final
- : public GarbageCollectedFinalized<ValueSizePair> {
+ : public GarbageCollected<ValueSizePair> {
public:
ValueSizePair(v8::Local<v8::Value> value, double size, v8::Isolate* isolate)
: value_(isolate, value), size_(size) {}
diff --git a/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.h b/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.h
index e7816465787..c114ea75be3 100644
--- a/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.h
+++ b/chromium/third_party/blink/renderer/core/streams/queue_with_sizes.h
@@ -22,7 +22,7 @@ class Visitor;
// container, but require it to have a QueueWithSizes member.
// https://streams.spec.whatwg.org/#queue-with-sizes
class CORE_EXPORT QueueWithSizes final
- : public GarbageCollectedFinalized<QueueWithSizes> {
+ : public GarbageCollected<QueueWithSizes> {
public:
QueueWithSizes();
~QueueWithSizes();
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 e1088481c4a..3f6b455234b 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -5,54 +5,42 @@
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
ReadableStream* ReadableStream::Create(ScriptState* script_state,
ExceptionState& exception_state) {
- return Create(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return Create(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ReadableStream* ReadableStream::Create(ScriptState* script_state,
ScriptValue underlying_source,
ExceptionState& exception_state) {
- return Create(
- script_state, underlying_source,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return Create(script_state, underlying_source,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ReadableStream* ReadableStream::Create(ScriptState* script_state,
ScriptValue underlying_source,
ScriptValue strategy,
ExceptionState& exception_state) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return ReadableStreamNative::Create(script_state, underlying_source,
- strategy, exception_state);
- }
-
- return ReadableStreamWrapper::Create(script_state, underlying_source,
- strategy, exception_state);
+ return ReadableStreamNative::Create(script_state, underlying_source, strategy,
+ exception_state);
}
ReadableStream* ReadableStream::CreateWithCountQueueingStrategy(
ScriptState* script_state,
UnderlyingSourceBase* underlying_source,
size_t high_water_mark) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return ReadableStreamNative::CreateWithCountQueueingStrategy(
- script_state, underlying_source, high_water_mark);
- }
-
- // TODO(ricea): Select implementation based on StreamsNative feature here.
- return ReadableStreamWrapper::CreateWithCountQueueingStrategy(
+ return ReadableStreamNative::CreateWithCountQueueingStrategy(
script_state, underlying_source, high_water_mark);
}
@@ -60,13 +48,7 @@ ReadableStream* ReadableStream::CreateWithCountQueueingStrategy(
ReadableStream* ReadableStream::Deserialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return ReadableStreamNative::Deserialize(script_state, port,
- exception_state);
- }
-
- return ReadableStreamWrapper::Deserialize(script_state, port,
- exception_state);
+ return ReadableStreamNative::Deserialize(script_state, port, exception_state);
}
} // namespace blink
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 72134c6bf78..84093c6cd52 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.h
@@ -31,7 +31,7 @@ class CORE_EXPORT ReadableStream : public ScriptWrappable {
// directly.
//
// TODO(ricea): Remove this when the V8 Extras implementation is removed.
- class ReadHandle : public GarbageCollectedFinalized<ReadHandle> {
+ class ReadHandle : public GarbageCollected<ReadHandle> {
public:
ReadHandle() = default;
virtual ~ReadHandle() = default;
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream.idl b/chromium/third_party/blink/renderer/core/streams/readable_stream.idl
index 847d6fa8a33..4f8b6d86570 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream.idl
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream.idl
@@ -5,8 +5,7 @@
// https://streams.spec.whatwg.org/#rs-class
[
Exposed=(Window,Worker,Worklet),
- // TODO(yhirano): Remove CustomConstructor. See https://crbug.com/906476.
- CustomConstructor(optional any underlyingSource, optional any strategy),
+ Constructor(optional any underlyingSource, optional any strategy),
RaisesException=Constructor,
ConstructorCallWith=ScriptState
] interface ReadableStream {
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
index 653cab070a3..f87d888c343 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller.cc
@@ -70,7 +70,8 @@ void ReadableStreamDefaultController::close(ScriptState* script_state,
void ReadableStreamDefaultController::enqueue(ScriptState* script_state,
ExceptionState& exception_state) {
enqueue(script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
exception_state);
}
@@ -90,8 +91,8 @@ void ReadableStreamDefaultController::enqueue(ScriptState* script_state,
}
void ReadableStreamDefaultController::error(ScriptState* script_state) {
- error(script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ error(script_state, ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())));
}
void ReadableStreamDefaultController::error(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
index c803bc81784..d1b9b523f11 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.cc
@@ -7,7 +7,6 @@
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream_default_controller.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -16,110 +15,12 @@ namespace blink {
namespace {
-class ReadableStreamDefaultControllerWrapper final
- : public ReadableStreamDefaultControllerInterface {
- public:
- explicit ReadableStreamDefaultControllerWrapper(ScriptState* script_state,
- ScriptValue controller)
- : ReadableStreamDefaultControllerInterface(script_state),
- js_controller_(script_state->GetIsolate(), controller.V8Value()) {
- js_controller_.SetPhantom();
- }
-
- // Users of the ReadableStreamDefaultControllerWrapper can call this to note
- // that the stream has been canceled and thus they don't anticipate using the
- // ReadableStreamDefaultControllerWrapper anymore.
- // (close/desiredSize/enqueue/error will become no-ops afterward.)
- void NoteHasBeenCanceled() override { js_controller_.Clear(); }
-
- void Close() override {
- ScriptState* script_state = script_state_;
- // This will assert that the context is valid; do not call this method when
- // the context is invalidated.
- ScriptState::Scope scope(script_state);
- v8::Isolate* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Value> controller = js_controller_.NewLocal(isolate);
- if (controller.IsEmpty())
- return;
-
- v8::Local<v8::Value> args[] = {controller};
- v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDefaultControllerClose", args);
- js_controller_.Clear();
- result.ToLocalChecked();
- }
-
- double DesiredSize() const override {
- ScriptState* script_state = script_state_;
- // This will assert that the context is valid; do not call this method when
- // the context is invalidated.
- ScriptState::Scope scope(script_state);
- v8::Isolate* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Value> controller = js_controller_.NewLocal(isolate);
- if (controller.IsEmpty())
- return 0;
-
- v8::Local<v8::Value> args[] = {controller};
- v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDefaultControllerGetDesiredSize", args);
-
- return result.ToLocalChecked().As<v8::Number>()->Value();
- }
-
- void Enqueue(v8::Local<v8::Value> js_chunk) const override {
- ScriptState* script_state = script_state_;
- // This will assert that the context is valid; do not call this method when
- // the context is invalidated.
- ScriptState::Scope scope(script_state);
- v8::Isolate* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Value> controller = js_controller_.NewLocal(isolate);
- if (controller.IsEmpty())
- return;
-
- v8::Local<v8::Value> args[] = {controller, js_chunk};
- v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDefaultControllerEnqueue", args);
- result.ToLocalChecked();
- }
-
- void Error(v8::Local<v8::Value> js_error) override {
- ScriptState* script_state = script_state_;
- // This will assert that the context is valid; do not call this method when
- // the context is invalidated.
- ScriptState::Scope scope(script_state);
- v8::Isolate* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Value> controller = js_controller_.NewLocal(isolate);
- if (controller.IsEmpty())
- return;
-
- v8::Local<v8::Value> args[] = {controller, js_error};
- v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDefaultControllerError", args);
- js_controller_.Clear();
- result.ToLocalChecked();
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(script_state_);
- ReadableStreamDefaultControllerInterface::Trace(visitor);
- }
-
- private:
- ScopedPersistent<v8::Value> js_controller_;
-};
-
class ReadableStreamDefaultControllerNative final
: public ReadableStreamDefaultControllerInterface {
public:
explicit ReadableStreamDefaultControllerNative(ScriptState* script_state,
ScriptValue controller)
: ReadableStreamDefaultControllerInterface(script_state) {
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
-
v8::Local<v8::Object> controller_object =
controller.V8Value().As<v8::Object>();
controller_ = V8ReadableStreamDefaultController::ToImpl(controller_object);
@@ -189,12 +90,7 @@ class ReadableStreamDefaultControllerNative final
ReadableStreamDefaultControllerInterface*
ReadableStreamDefaultControllerInterface::Create(ScriptState* script_state,
ScriptValue controller) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return MakeGarbageCollected<ReadableStreamDefaultControllerNative>(
- script_state, controller);
- }
-
- return MakeGarbageCollected<ReadableStreamDefaultControllerWrapper>(
+ return MakeGarbageCollected<ReadableStreamDefaultControllerNative>(
script_state, controller);
}
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
index eb8b3bbfab5..6699e7151fd 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h
@@ -15,8 +15,7 @@ class ScriptState;
class Visitor;
class CORE_EXPORT ReadableStreamDefaultControllerInterface
- : public GarbageCollectedFinalized<
- ReadableStreamDefaultControllerInterface> {
+ : public GarbageCollected<ReadableStreamDefaultControllerInterface> {
public:
static ReadableStreamDefaultControllerInterface* Create(
ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_reader.idl b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_reader.idl
index 1a1fee364af..63deec74de4 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_reader.idl
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_reader.idl
@@ -7,7 +7,6 @@
// https://streams.spec.whatwg.org/#default-reader-class-definition
[
Exposed=(Window,Worker,Worklet),
- RuntimeEnabled=StreamsNative,
RaisesException=Constructor,
ConstructorCallWith=ScriptState,
Constructor(ReadableStream stream)
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
index 632ea367d68..6442127072a 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.cc
@@ -41,8 +41,8 @@ namespace blink {
// TODO(ricea): Create internal versions of ReadableStreamDefaultReader::Read()
// and WritableStreamDefaultWriter::Write() to bypass promise creation and so
// reduce the number of allocations on the hot path.
-class ReadableStreamNative::PipeToEngine
- : public GarbageCollectedFinalized<PipeToEngine> {
+class ReadableStreamNative::PipeToEngine final
+ : public GarbageCollected<PipeToEngine> {
public:
PipeToEngine(ScriptState* script_state, PipeOptions pipe_options)
: script_state_(script_state), pipe_options_(pipe_options) {}
@@ -599,7 +599,7 @@ class ReadableStreamNative::PipeToEngine
};
class ReadableStreamNative::TeeEngine final
- : public GarbageCollectedFinalized<TeeEngine> {
+ : public GarbageCollected<TeeEngine> {
public:
TeeEngine() = default;
@@ -965,8 +965,9 @@ ReadableStreamNative* ReadableStreamNative::Create(
ScriptValue underlying_source,
ScriptValue strategy,
ExceptionState& exception_state) {
- auto* stream = MakeGarbageCollected<ReadableStreamNative>(
- script_state, underlying_source, strategy, false, exception_state);
+ auto* stream = MakeGarbageCollected<ReadableStreamNative>();
+ stream->InitInternal(script_state, underlying_source, strategy, false,
+ exception_state);
if (exception_state.HadException()) {
return nullptr;
}
@@ -1001,9 +1002,12 @@ ReadableStreamNative* ReadableStreamNative::CreateWithCountQueueingStrategy(
v8::Local<v8::Value> underlying_source_v8 =
ToV8(underlying_source, script_state);
- auto* stream = MakeGarbageCollected<ReadableStreamNative>(
- script_state, ScriptValue(script_state, underlying_source_v8),
- ScriptValue(script_state, strategy_object), true, exception_state);
+ auto* stream = MakeGarbageCollected<ReadableStreamNative>();
+ stream->InitInternal(
+ script_state,
+ ScriptValue(script_state->GetIsolate(), underlying_source_v8),
+ ScriptValue(script_state->GetIsolate(), strategy_object), true,
+ exception_state);
if (exception_state.HadException()) {
exception_state.ClearException();
@@ -1058,99 +1062,6 @@ ReadableStreamNative* ReadableStreamNative::Create(
ReadableStreamNative::ReadableStreamNative() = default;
-ReadableStreamNative::ReadableStreamNative(ScriptState* script_state,
- ScriptValue raw_underlying_source,
- ScriptValue raw_strategy,
- bool created_by_ua,
- ExceptionState& exception_state) {
- if (!created_by_ua) {
- // TODO(ricea): Move this to IDL once blink::ReadableStreamOperations is
- // no longer using the public constructor.
- UseCounter::Count(ExecutionContext::From(script_state),
- WebFeature::kReadableStreamConstructor);
- }
-
- // https://streams.spec.whatwg.org/#rs-constructor
- // 1. Perform ! InitializeReadableStream(this).
- Initialize(this);
-
- // The next part of this constructor corresponds to the object conversions
- // that are implicit in the definition in the standard.
- DCHECK(!raw_underlying_source.IsEmpty());
- DCHECK(!raw_strategy.IsEmpty());
-
- auto context = script_state->GetContext();
- auto* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Object> underlying_source;
- ScriptValueToObject(script_state, raw_underlying_source, &underlying_source,
- exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 2. Let size be ? GetV(strategy, "size").
- // 3. Let highWaterMark be ? GetV(strategy, "highWaterMark").
- StrategyUnpacker strategy_unpacker(script_state, raw_strategy,
- exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 4. Let type be ? GetV(underlyingSource, "type").
- v8::TryCatch try_catch(isolate);
- v8::Local<v8::Value> type;
- if (!underlying_source->Get(context, V8AtomicString(isolate, "type"))
- .ToLocal(&type)) {
- exception_state.RethrowV8Exception(try_catch.Exception());
- return;
- }
-
- if (!type->IsUndefined()) {
- // 5. Let typeString be ? ToString(type).
- v8::Local<v8::String> type_string;
- if (!type->ToString(context).ToLocal(&type_string)) {
- exception_state.RethrowV8Exception(try_catch.Exception());
- return;
- }
-
- // 6. If typeString is "bytes",
- if (type_string == V8AtomicString(isolate, "bytes")) {
- // TODO(ricea): Implement bytes type.
- exception_state.ThrowRangeError("bytes type is not yet implemented");
- return;
- }
-
- // 8. Otherwise, throw a RangeError exception.
- exception_state.ThrowRangeError("Invalid type is specified");
- return;
- }
-
- // 7. Otherwise, if type is undefined,
- // a. Let sizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(size).
- auto* size_algorithm =
- strategy_unpacker.MakeSizeAlgorithm(script_state, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- DCHECK(size_algorithm);
-
- // b. If highWaterMark is undefined, let highWaterMark be 1.
- // c. Set highWaterMark to ? ValidateAndNormalizeHighWaterMark(
- // highWaterMark).
- double high_water_mark =
- strategy_unpacker.GetHighWaterMark(script_state, 1, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 4. Perform ? SetUpReadableStreamDefaultControllerFromUnderlyingSource
- // (this, underlyingSource, highWaterMark, sizeAlgorithm).
- ReadableStreamDefaultController::SetUpFromUnderlyingSource(
- script_state, this, underlying_source, high_water_mark, size_algorithm,
- exception_state);
-}
-
ReadableStreamNative::~ReadableStreamNative() = default;
bool ReadableStreamNative::locked(ScriptState* script_state,
@@ -1162,10 +1073,10 @@ bool ReadableStreamNative::locked(ScriptState* script_state,
ScriptPromise ReadableStreamNative::cancel(ScriptState* script_state,
ExceptionState& exception_state) {
- return cancel(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return cancel(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ScriptPromise ReadableStreamNative::cancel(ScriptState* script_state,
@@ -1195,7 +1106,7 @@ ScriptValue ReadableStreamNative::getReader(ScriptState* script_state,
return ScriptValue();
}
- return ScriptValue(script_state, ToV8(reader, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(reader, script_state));
}
ScriptValue ReadableStreamNative::getReader(ScriptState* script_state,
@@ -1216,10 +1127,10 @@ ScriptValue ReadableStreamNative::getReader(ScriptState* script_state,
ScriptValue ReadableStreamNative::pipeThrough(ScriptState* script_state,
ScriptValue transform_stream,
ExceptionState& exception_state) {
- return pipeThrough(
- script_state, transform_stream,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return pipeThrough(script_state, transform_stream,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
// https://streams.spec.whatwg.org/#rs-pipe-through
@@ -1239,8 +1150,6 @@ ScriptValue ReadableStreamNative::pipeThrough(ScriptState* script_state,
PipeOptions pipe_options;
UnpackPipeOptions(script_state, options, &pipe_options, exception_state);
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
-
// This cast is safe because the following code will only be run when the
// native version of WritableStream is in use.
WritableStreamNative* writable_native =
@@ -1263,10 +1172,10 @@ ScriptValue ReadableStreamNative::pipeThrough(ScriptState* script_state,
ScriptPromise ReadableStreamNative::pipeTo(ScriptState* script_state,
ScriptValue destination,
ExceptionState& exception_state) {
- return pipeTo(
- script_state, destination,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return pipeTo(script_state, destination,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ScriptPromise ReadableStreamNative::pipeTo(ScriptState* script_state,
@@ -1283,8 +1192,6 @@ ScriptPromise ReadableStreamNative::pipeTo(ScriptState* script_state,
PipeOptions pipe_options;
UnpackPipeOptions(script_state, options, &pipe_options, exception_state);
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
-
// This cast is safe because the following code will only be run when the
// native version of WritableStream is in use.
WritableStreamNative* destination_native =
@@ -1298,6 +1205,102 @@ ScriptValue ReadableStreamNative::tee(ScriptState* script_state,
return CallTeeAndReturnBranchArray(script_state, this, exception_state);
}
+// Unlike in the standard, this is defined as a separate method from the
+// constructor. This prevents problems when garbage collection happens
+// re-entrantly during construction.
+void ReadableStreamNative::InitInternal(ScriptState* script_state,
+ ScriptValue raw_underlying_source,
+ ScriptValue raw_strategy,
+ bool created_by_ua,
+ ExceptionState& exception_state) {
+ if (!created_by_ua) {
+ // TODO(ricea): Move this to IDL once blink::ReadableStreamOperations is
+ // no longer using the public constructor.
+ UseCounter::Count(ExecutionContext::From(script_state),
+ WebFeature::kReadableStreamConstructor);
+ }
+
+ // https://streams.spec.whatwg.org/#rs-constructor
+ // 1. Perform ! InitializeReadableStream(this).
+ Initialize(this);
+
+ // The next part of this constructor corresponds to the object conversions
+ // that are implicit in the definition in the standard.
+ DCHECK(!raw_underlying_source.IsEmpty());
+ DCHECK(!raw_strategy.IsEmpty());
+
+ auto context = script_state->GetContext();
+ auto* isolate = script_state->GetIsolate();
+
+ v8::Local<v8::Object> underlying_source;
+ ScriptValueToObject(script_state, raw_underlying_source, &underlying_source,
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 2. Let size be ? GetV(strategy, "size").
+ // 3. Let highWaterMark be ? GetV(strategy, "highWaterMark").
+ StrategyUnpacker strategy_unpacker(script_state, raw_strategy,
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 4. Let type be ? GetV(underlyingSource, "type").
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::Value> type;
+ if (!underlying_source->Get(context, V8AtomicString(isolate, "type"))
+ .ToLocal(&type)) {
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ return;
+ }
+
+ if (!type->IsUndefined()) {
+ // 5. Let typeString be ? ToString(type).
+ v8::Local<v8::String> type_string;
+ if (!type->ToString(context).ToLocal(&type_string)) {
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ return;
+ }
+
+ // 6. If typeString is "bytes",
+ if (type_string == V8AtomicString(isolate, "bytes")) {
+ // TODO(ricea): Implement bytes type.
+ exception_state.ThrowRangeError("bytes type is not yet implemented");
+ return;
+ }
+
+ // 8. Otherwise, throw a RangeError exception.
+ exception_state.ThrowRangeError("Invalid type is specified");
+ return;
+ }
+
+ // 7. Otherwise, if type is undefined,
+ // a. Let sizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(size).
+ auto* size_algorithm =
+ strategy_unpacker.MakeSizeAlgorithm(script_state, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+ DCHECK(size_algorithm);
+
+ // b. If highWaterMark is undefined, let highWaterMark be 1.
+ // c. Set highWaterMark to ? ValidateAndNormalizeHighWaterMark(
+ // highWaterMark).
+ double high_water_mark =
+ strategy_unpacker.GetHighWaterMark(script_state, 1, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 4. Perform ? SetUpReadableStreamDefaultControllerFromUnderlyingSource
+ // (this, underlyingSource, highWaterMark, sizeAlgorithm).
+ ReadableStreamDefaultController::SetUpFromUnderlyingSource(
+ script_state, this, underlying_source, high_water_mark, size_algorithm,
+ exception_state);
+}
+
//
// Readable stream abstract operations
//
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
index ee1b87d9d9b..34017596c8b 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_native.h
@@ -67,13 +67,6 @@ class ReadableStreamNative : public ReadableStream {
ReadableStreamNative();
- // https://streams.spec.whatwg.org/#rs-constructor
- ReadableStreamNative(ScriptState*,
- ScriptValue raw_underlying_source,
- ScriptValue raw_strategy,
- bool created_by_ua,
- ExceptionState&);
-
~ReadableStreamNative() override;
// https://streams.spec.whatwg.org/#rs-constructor
@@ -208,6 +201,13 @@ class ReadableStreamNative : public ReadableStream {
class ReadHandleImpl;
class TeeEngine;
+ // https://streams.spec.whatwg.org/#rs-constructor
+ void InitInternal(ScriptState*,
+ ScriptValue raw_underlying_source,
+ ScriptValue raw_strategy,
+ bool created_by_ua,
+ ExceptionState&);
+
// https://streams.spec.whatwg.org/#initialize-readable-stream
static void Initialize(ReadableStreamNative*);
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc
deleted file mode 100644
index 3012abf2d46..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-
-#include <utility>
-
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_message_port.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-namespace {
-
-base::Optional<bool> BooleanOperationWithRethrow(
- ScriptState* script_state,
- ScriptValue value,
- const char* operation,
- ExceptionState& exception_state) {
- DCHECK(!value.IsEmpty());
-
- if (!value.IsObject())
- return false;
-
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {value.V8Value()};
- v8::Local<v8::Value> local_value;
-
- if (!V8ScriptRunner::CallExtra(script_state, operation, args)
- .ToLocal(&local_value)) {
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- exception_state.RethrowV8Exception(block.Exception());
- return base::nullopt;
- }
-
- DCHECK(!block.HasCaught());
- return local_value->BooleanValue(script_state->GetIsolate());
-}
-
-// Performs |operation| on |value|, catching any exceptions. This is for use in
-// DCHECK(). It is unsafe for general use because it ignores errors. Returns
-// |fallback_value|, which must be chosen so that the DCHECK() passed if an
-// exception was thrown, so that the behaviour matches a release build.
-bool BooleanOperationForDCheck(ScriptState* script_state,
- ScriptValue value,
- const char* operation,
- bool fallback_value) {
- v8::Local<v8::Value> args[] = {value.V8Value()};
- v8::Local<v8::Value> result_value;
- v8::TryCatch block(script_state->GetIsolate());
- if (V8ScriptRunner::CallExtra(script_state, operation, args)
- .ToLocal(&result_value)) {
- DCHECK(!block.HasCaught());
- return result_value->BooleanValue(script_state->GetIsolate());
- }
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- return fallback_value;
-}
-
-// Performs IsReadableStreamDefaultReader(value), catching exceptions. Should
-// only be used in DCHECK(). Returns true on exception.
-bool IsDefaultReaderForDCheck(ScriptState* script_state, ScriptValue value) {
- return BooleanOperationForDCheck(script_state, value,
- "IsReadableStreamDefaultReader", true);
-}
-
-} // namespace
-
-ScriptValue ReadableStreamOperations::CreateReadableStream(
- ScriptState* script_state,
- UnderlyingSourceBase* underlying_source,
- ScriptValue strategy) {
- ScriptState::Scope scope(script_state);
-
- v8::Local<v8::Value> js_underlying_source =
- ToV8(underlying_source, script_state);
- v8::Local<v8::Value> js_strategy = strategy.V8Value();
- v8::Local<v8::Value> args[] = {js_underlying_source, js_strategy};
- return ScriptValue(
- script_state,
- V8ScriptRunner::CallExtra(
- script_state, "createReadableStreamWithExternalController", args));
-}
-
-ScriptValue ReadableStreamOperations::CreateReadableStream(
- ScriptState* script_state,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState& exception_state) {
- ScriptState::Scope scope(script_state);
-
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {underlying_source.V8Value(),
- strategy.V8Value()};
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state, "createReadableStream", args)
- .ToLocal(&result)) {
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- return ScriptValue(script_state, result);
-}
-
-ScriptValue ReadableStreamOperations::CreateCountQueuingStrategy(
- ScriptState* script_state,
- size_t high_water_mark) {
- ScriptState::Scope scope(script_state);
-
- v8::Local<v8::Value> args[] = {
- v8::Number::New(script_state->GetIsolate(), high_water_mark)};
- return ScriptValue(
- script_state,
- V8ScriptRunner::CallExtra(script_state,
- "createBuiltInCountQueuingStrategy", args));
-}
-
-ScriptValue ReadableStreamOperations::GetReader(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
-
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- ScriptValue result(
- script_state,
- V8ScriptRunner::CallExtra(script_state,
- "AcquireReadableStreamDefaultReader", args));
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- DCHECK(!result.IsEmpty() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- return result;
-}
-
-base::Optional<bool> ReadableStreamOperations::IsReadableStream(
- ScriptState* script_state,
- ScriptValue value,
- ExceptionState& exception_state) {
- return BooleanOperationWithRethrow(script_state, value, "IsReadableStream",
- exception_state);
-}
-
-bool ReadableStreamOperations::IsReadableStreamForDCheck(
- ScriptState* script_state,
- ScriptValue value) {
- return BooleanOperationForDCheck(script_state, value, "IsReadableStream",
- true);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsDisturbed(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationWithRethrow(
- script_state, stream, "IsReadableStreamDisturbed", exception_state);
-}
-
-bool ReadableStreamOperations::IsDisturbedForDCheck(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationForDCheck(script_state, stream,
- "IsReadableStreamDisturbed", false);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsLocked(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationWithRethrow(script_state, stream,
- "IsReadableStreamLocked", exception_state);
-}
-
-bool ReadableStreamOperations::IsLockedForDCheck(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationForDCheck(script_state, stream,
- "IsReadableStreamLocked", false);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsReadable(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationWithRethrow(
- script_state, stream, "IsReadableStreamReadable", exception_state);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsClosed(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationWithRethrow(script_state, stream,
- "IsReadableStreamClosed", exception_state);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsErrored(
- ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- return BooleanOperationWithRethrow(
- script_state, stream, "IsReadableStreamErrored", exception_state);
-}
-
-base::Optional<bool> ReadableStreamOperations::IsReadableStreamDefaultReader(
- ScriptState* script_state,
- ScriptValue value,
- ExceptionState& exception_state) {
- return BooleanOperationWithRethrow(
- script_state, value, "IsReadableStreamDefaultReader", exception_state);
-}
-
-ScriptPromise ReadableStreamOperations::DefaultReaderRead(
- ScriptState* script_state,
- ScriptValue reader) {
- DCHECK(IsDefaultReaderForDCheck(script_state, reader));
-
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {reader.V8Value()};
- v8::MaybeLocal<v8::Value> maybe_result = V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDefaultReaderRead", args);
- if (maybe_result.IsEmpty()) {
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- return ScriptPromise::Reject(script_state, block.Exception());
- }
- return ScriptPromise::Cast(script_state, maybe_result.ToLocalChecked());
-}
-
-ScriptValue ReadableStreamOperations::Tee(ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& exception_state) {
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- DCHECK(!IsLockedForDCheck(script_state, stream));
-
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- v8::Local<v8::Value> result;
- if (!V8ScriptRunner::CallExtra(script_state, "ReadableStreamTee", args)
- .ToLocal(&result)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- return ScriptValue(script_state, result);
-}
-
-void ReadableStreamOperations::Serialize(ScriptState* script_state,
- ScriptValue stream,
- MessagePort* port,
- ExceptionState& exception_state) {
- DCHECK(port);
- DCHECK(IsReadableStreamForDCheck(script_state, stream));
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> port_v8_value = ToV8(port, script_state);
- DCHECK(!port_v8_value.IsEmpty());
- v8::Local<v8::Value> args[] = {stream.V8Value(), port_v8_value};
- ScriptValue result(
- script_state,
- V8ScriptRunner::CallExtra(script_state, "ReadableStreamSerialize", args));
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- return;
-}
-
-ScriptValue ReadableStreamOperations::Deserialize(
- ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- DCHECK(port);
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- auto* isolate = script_state->GetIsolate();
- v8::TryCatch block(isolate);
- v8::Local<v8::Value> port_v8 = ToV8(port, script_state);
- DCHECK(!port_v8.IsEmpty());
- v8::Local<v8::Value> args[] = {port_v8};
- ScriptValue result(script_state,
- V8ScriptRunner::CallExtra(
- script_state, "ReadableStreamDeserialize", args));
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- if (result.IsEmpty()) {
- DCHECK(isolate->IsExecutionTerminating());
- return ScriptValue();
- }
- DCHECK(IsReadableStreamForDCheck(script_state, result));
- return result;
-}
-
-ScriptPromise ReadableStreamOperations::Cancel(
- ScriptState* script_state,
- ScriptValue stream,
- ScriptValue reason,
- ExceptionState& exception_state) {
- v8::Local<v8::Value> args[] = {stream.V8Value(), reason.V8Value()};
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state, "ReadableStreamCancel", args)
- .ToLocal(&result)) {
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- return ScriptPromise(script_state, result);
-}
-
-ScriptPromise ReadableStreamOperations::PipeTo(
- ScriptState* script_state,
- ScriptValue stream,
- ScriptValue destination,
- ScriptValue options,
- ExceptionState& exception_state) {
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> result;
- v8::Isolate* isolate = script_state->GetIsolate();
- v8::Local<v8::Boolean> prevent_close;
- v8::Local<v8::Boolean> prevent_abort;
- v8::Local<v8::Boolean> prevent_cancel;
-
- if (options.IsUndefined()) {
- // All values default to false.
- prevent_close = v8::Boolean::New(isolate, false);
- prevent_abort = v8::Boolean::New(isolate, false);
- prevent_cancel = v8::Boolean::New(isolate, false);
- } else {
- v8::Local<v8::Context> context = script_state->GetContext();
- v8::Local<v8::Object> v8_options;
- if (!options.V8Value()->ToObject(context).ToLocal(&v8_options)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- v8::Local<v8::Value> prevent_close_v, prevent_abort_v, prevent_cancel_v;
- if (!v8_options->Get(context, V8String(isolate, "preventClose"))
- .ToLocal(&prevent_close_v)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- if (!v8_options->Get(context, V8String(isolate, "preventAbort"))
- .ToLocal(&prevent_abort_v)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- if (!v8_options->Get(context, V8String(isolate, "preventCancel"))
- .ToLocal(&prevent_cancel_v)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- prevent_close = prevent_close_v->ToBoolean(isolate);
- prevent_abort = prevent_abort_v->ToBoolean(isolate);
- prevent_cancel = prevent_cancel_v->ToBoolean(isolate);
- }
-
- v8::Local<v8::Value> args[] = {stream.V8Value(), destination.V8Value(),
- prevent_close, prevent_abort, prevent_cancel};
- if (!V8ScriptRunner::CallExtra(script_state, "ReadableStreamPipeTo", args)
- .ToLocal(&result)) {
- DCHECK(block.HasCaught() ||
- script_state->GetIsolate()->IsExecutionTerminating());
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
-
- return ScriptPromise(script_state, result);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h
deleted file mode 100644
index 92ed0ec6dac..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_OPERATIONS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_OPERATIONS_H_
-
-#include "base/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/core_export.h"
-
-namespace blink {
-
-class UnderlyingSourceBase;
-class ExceptionState;
-class MessagePort;
-class ScriptState;
-
-// This class has various methods for ReadableStream[Reader] implemented with
-// V8 Extras.
-//
-// DEPRECATED: None of these functions work correctly with the new C++
-// implementation of ReadableStream. Use the ReadableStream API directly
-// instead.
-//
-// All methods should be called in an appropriate V8 context. All ScriptValue
-// arguments must not be empty.
-//
-// Boolean methods return an optional bool, where an empty value indicates that
-// Javascript failed to return a value (ie. an exception occurred). Exceptions
-// are not caught, so that they can be handled by user Javascript. This implicit
-// exception passing is error-prone and bad.
-//
-// In methods which take an ExceptionState& parameter, exception passing is
-// explicit. Callers must check exception_state.HadException() on
-// return. Although these methods return base::nullopt if and only if an
-// exception was thrown, outside of unit tests exception_state should always be
-// used to determine failure.
-//
-// TODO(ricea): Add ExceptionState arguments to the rest of the non-Promise
-// methods to make exception passing explicit. https://crbug.com/853189.
-class CORE_EXPORT ReadableStreamOperations {
- STATIC_ONLY(ReadableStreamOperations);
-
- public:
- // createReadableStreamWithExternalController
- // Instantiates ReadableStream defined in the script and returns it.
- // If the caller supplies an invalid strategy (e.g. one that returns
- // negative sizes, or doesn't have appropriate properties), or an exception
- // occurs for another reason, this will return an empty value.
- static ScriptValue CreateReadableStream(ScriptState*,
- UnderlyingSourceBase*,
- ScriptValue strategy);
-
- // createReadableStream
- // Instantiates ReadableStream defined in the script and returns it.
- static ScriptValue CreateReadableStream(ScriptState*,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState& exception_state);
-
- // createBuiltInCountQueuingStrategy
- // If the constructor throws, this will return an empty value.
- static ScriptValue CreateCountQueuingStrategy(ScriptState*,
- size_t high_water_mark);
-
- // AcquireReadableStreamDefaultReader
- // This function assumes |IsReadableStream(stream)|.
- static ScriptValue GetReader(ScriptState*,
- ScriptValue stream,
- ExceptionState&);
-
- // IsReadableStream, exception-catching version. Exceptions will be passed to
- // |exception_state|.
- static base::Optional<bool> IsReadableStream(ScriptState*,
- ScriptValue,
- ExceptionState& exception_state);
-
- // Performs IsReadableStream.
- // Catches exceptions, and returns false if there are any. Should only be used
- // in a DCHECK statement that passes when the return value is true.
- static bool IsReadableStreamForDCheck(ScriptState*, ScriptValue);
-
- // IsReadableStreamDisturbed.
- // This function assumes |IsReadableStream(stream)|.
- static base::Optional<bool> IsDisturbed(ScriptState*,
- ScriptValue stream,
- ExceptionState& exception_state);
-
- // Performs IsReadableStreamDisturbed.
- // Catches exceptions, and returns false if there are any. Should only be used
- // in a DCHECK statement that passes when the return value is false.
- static bool IsDisturbedForDCheck(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamLocked.
- // This function assumes |IsReadableStream(stream)|.
- static base::Optional<bool> IsLocked(ScriptState*,
- ScriptValue stream,
- ExceptionState&);
-
- // Performs IsReadableStreamLocked.
- // Catches exceptions, and returns false if there are any. Should only be used
- // in a DCHECK statement that passes when the return value is false.
- static bool IsLockedForDCheck(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamReadable.
- // This function assumes |IsReadableStream(stream)|.
- static base::Optional<bool> IsReadable(ScriptState*,
- ScriptValue stream,
- ExceptionState& exception_state);
-
- // IsReadableStreamClosed.
- // This function assumes |IsReadableStream(stream)|.
- static base::Optional<bool> IsClosed(ScriptState*,
- ScriptValue stream,
- ExceptionState& exception_state);
-
- // IsReadableStreamErrored.
- // This function assumes |IsReadableStream(stream)|.
- static base::Optional<bool> IsErrored(ScriptState*,
- ScriptValue stream,
- ExceptionState& exception_state);
-
- // IsReadableStreamDefaultReader.
- static base::Optional<bool> IsReadableStreamDefaultReader(
- ScriptState*,
- ScriptValue,
- ExceptionState& exception_state);
-
- // ReadableStreamDefaultReaderRead
- // This function assumes |IsReadableStreamDefaultReader(reader)|.
- // If an exception occurs, returns a rejected promise.
- static ScriptPromise DefaultReaderRead(ScriptState*, ScriptValue reader);
-
- // ReadableStreamTee
- // This function assumes |IsReadableStream(stream)| and |!IsLocked(stream)|
- static ScriptValue Tee(ScriptState*, ScriptValue stream, ExceptionState&);
-
- // ReadableStreamSerialize. The MessagePort passed in must be one half of a
- // MessageChannel. The other half can later be passed to Deserialize to
- // produce an equivalent ReadableStream in a different context.
- static void Serialize(ScriptState*,
- ScriptValue stream,
- MessagePort* port,
- ExceptionState&);
-
- // ReadableStreamDeserialize returns a new ReadableStream in the current
- // context given a MessagePort which is bound to one which was previously
- // passed to Serialize().
- static ScriptValue Deserialize(ScriptState*, MessagePort*, ExceptionState&);
-
- // ReadableStreamCancel
- // This function assumes |IsReadableStream(stream)|
- static ScriptPromise Cancel(ScriptState*,
- ScriptValue stream,
- ScriptValue reason,
- ExceptionState& exception_state);
-
- // ReadableStreamPipeTo
- // This function assumes |IsReadableStream(stream)|, |!IsLocked(stream)|,
- // |IsWritableStream(destination)| and |!IsLocked(destination)|.
- static ScriptPromise PipeTo(ScriptState*,
- ScriptValue stream,
- ScriptValue destination,
- ScriptValue options,
- ExceptionState& exception_state);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_OPERATIONS_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
deleted file mode 100644
index 3defe075f0c..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
+++ /dev/null
@@ -1,627 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/messaging/message_channel.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
-#include "third_party/blink/renderer/core/streams/test_underlying_source.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-class ReadableStreamOperationsTestNotReached : public ScriptFunction {
- public:
- static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
- ReadableStreamOperationsTestNotReached* self =
- MakeGarbageCollected<ReadableStreamOperationsTestNotReached>(
- script_state);
- return self->BindToV8Function();
- }
-
- explicit ReadableStreamOperationsTestNotReached(ScriptState* script_state)
- : ScriptFunction(script_state) {}
-
- private:
- ScriptValue Call(ScriptValue) override;
-};
-
-ScriptValue ReadableStreamOperationsTestNotReached::Call(ScriptValue) {
- EXPECT_TRUE(false) << "'Unreachable' code was reached";
- return ScriptValue();
-}
-
-class Iteration final : public GarbageCollectedFinalized<Iteration> {
- public:
- Iteration() : is_set_(false), is_done_(false), is_valid_(true) {}
-
- void Set(ScriptState* script_state, ScriptValue v) {
- DCHECK(!v.IsEmpty());
- is_set_ = true;
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> value;
- v8::Local<v8::Value> item = v.V8Value();
- if (!item->IsObject() ||
- !V8UnpackIteratorResult(script_state, item.As<v8::Object>(), &is_done_)
- .ToLocal(&value)) {
- is_valid_ = false;
- return;
- }
- value_ = ToCoreString(
- value->ToString(script_state->GetContext()).ToLocalChecked());
- }
-
- bool IsSet() const { return is_set_; }
- bool IsDone() const { return is_done_; }
- bool IsValid() const { return is_valid_; }
- const String& Value() const { return value_; }
-
- void Trace(blink::Visitor* visitor) {}
-
- private:
- bool is_set_;
- bool is_done_;
- bool is_valid_;
- String value_;
-};
-
-class ReaderFunction : public ScriptFunction {
- public:
- static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
- Iteration* iteration) {
- ReaderFunction* self =
- MakeGarbageCollected<ReaderFunction>(script_state, iteration);
- return self->BindToV8Function();
- }
-
- ReaderFunction(ScriptState* script_state, Iteration* iteration)
- : ScriptFunction(script_state), iteration_(iteration) {}
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(iteration_);
- ScriptFunction::Trace(visitor);
- }
-
- private:
- ScriptValue Call(ScriptValue value) override {
- iteration_->Set(GetScriptState(), value);
- return value;
- }
-
- Member<Iteration> iteration_;
-};
-
-// Returns the internal V8 Extras implementation of a ReadableStream object.
-// Requires StreamsNative feature to be off.
-ScriptValue CheckedGetInternalStream(ScriptState* script_state,
- ReadableStream* readable_stream) {
- CHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
- ReadableStreamWrapper* readable_stream_wrapper =
- static_cast<ReadableStreamWrapper*>(readable_stream);
- return readable_stream_wrapper->GetInternalStream(script_state);
-}
-
-ScriptValue CheckedGetInternalStream(ScriptState* script_state,
- ScriptValue stream) {
- ReadableStream* readable_stream =
- V8ReadableStream::ToImpl(stream.V8Value().As<v8::Object>());
- return CheckedGetInternalStream(script_state, readable_stream);
-}
-
-TEST(ReadableStreamOperationsTest, IsReadableStream) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Undefined(scope.GetIsolate())),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(),
- ScriptValue::CreateNull(scope.GetScriptState()),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Object::New(scope.GetIsolate())),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
- EXPECT_FALSE(stream.IsEmpty());
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), stream, ASSERT_NO_EXCEPTION)
- .value_or(false));
- ASSERT_TRUE(V8ReadableStream::HasInstance(stream.V8Value().As<v8::Object>(),
- scope.GetIsolate()));
-
- ScriptValue internal_stream =
- CheckedGetInternalStream(scope.GetScriptState(), stream);
- ASSERT_FALSE(internal_stream.IsEmpty());
- EXPECT_TRUE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION)
- .value_or(false));
-}
-
-TEST(ReadableStreamOperationsTest, IsReadableStreamDefaultReaderInvalid) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Undefined(scope.GetIsolate())),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(),
- ScriptValue::CreateNull(scope.GetScriptState()),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Object::New(scope.GetIsolate())),
- ASSERT_NO_EXCEPTION)
- .value_or(true));
- ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
- ASSERT_FALSE(stream.IsEmpty());
-
- EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), stream, ASSERT_NO_EXCEPTION)
- .value_or(true));
-}
-
-TEST(ReadableStreamOperationsTest, GetReader) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* stream =
- ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(stream);
-
- ScriptValue internal_stream =
- CheckedGetInternalStream(scope.GetScriptState(), stream);
- ASSERT_FALSE(internal_stream.IsEmpty());
-
- EXPECT_EQ(ReadableStreamOperations::IsLocked(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- ScriptValue reader;
- reader = ReadableStreamOperations::GetReader(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION);
- ASSERT_FALSE(reader.IsEmpty());
- EXPECT_EQ(ReadableStreamOperations::IsLocked(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION),
- base::make_optional(true));
-
- EXPECT_EQ(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- EXPECT_EQ(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION),
- base::make_optional(true));
-
- // Already locked!
- DummyExceptionStateForTesting exception_state;
- reader = ReadableStreamOperations::GetReader(
- scope.GetScriptState(), internal_stream, exception_state);
- EXPECT_TRUE(exception_state.HadException());
- EXPECT_TRUE(reader.IsEmpty());
-}
-
-TEST(ReadableStreamOperationsTest, IsDisturbed) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* stream =
- ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(stream);
-
- ScriptValue internal_stream =
- CheckedGetInternalStream(scope.GetScriptState(), stream);
- EXPECT_EQ(ReadableStreamOperations::IsDisturbed(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION),
- base::make_optional(false));
-
- stream->cancel(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
-
- EXPECT_EQ(ReadableStreamOperations::IsDisturbed(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION),
- base::make_optional(true));
-}
-
-TEST(ReadableStreamOperationsTest, Read) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- ScriptValue reader =
- EvalWithPrintingError(&scope,
- "var controller;"
- "function start(c) { controller = c; }"
- "new ReadableStream({start}).getReader()");
- EXPECT_FALSE(reader.IsEmpty());
- ASSERT_TRUE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION)
- .value_or(false));
-
- Iteration* it1 = MakeGarbageCollected<Iteration>();
- Iteration* it2 = MakeGarbageCollected<Iteration>();
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it2),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
-
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_FALSE(it1->IsSet());
- EXPECT_FALSE(it2->IsSet());
-
- ASSERT_FALSE(
- EvalWithPrintingError(&scope, "controller.enqueue('hello')").IsEmpty());
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(it1->IsSet());
- EXPECT_TRUE(it1->IsValid());
- EXPECT_FALSE(it1->IsDone());
- EXPECT_EQ("hello", it1->Value());
- EXPECT_FALSE(it2->IsSet());
-
- ASSERT_FALSE(EvalWithPrintingError(&scope, "controller.close()").IsEmpty());
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(it1->IsSet());
- EXPECT_TRUE(it1->IsValid());
- EXPECT_FALSE(it1->IsDone());
- EXPECT_EQ("hello", it1->Value());
- EXPECT_TRUE(it2->IsSet());
- EXPECT_TRUE(it2->IsValid());
- EXPECT_TRUE(it2->IsDone());
-}
-
-TEST(ReadableStreamOperationsTest,
- CreateReadableStreamWithCustomUnderlyingSourceAndStrategy) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* underlying_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
-
- ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
- scope.GetScriptState(), 10);
- ASSERT_FALSE(strategy.IsEmpty());
-
- ScriptValue stream = ReadableStreamOperations::CreateReadableStream(
- scope.GetScriptState(), underlying_source, strategy);
- ASSERT_FALSE(stream.IsEmpty());
-
- EXPECT_EQ(10, underlying_source->DesiredSize());
-
- underlying_source->Enqueue(ScriptValue::From(scope.GetScriptState(), "a"));
- EXPECT_EQ(9, underlying_source->DesiredSize());
-
- underlying_source->Enqueue(ScriptValue::From(scope.GetScriptState(), "b"));
- EXPECT_EQ(8, underlying_source->DesiredSize());
-
- ScriptValue reader;
- reader = ReadableStreamOperations::GetReader(scope.GetScriptState(), stream,
- ASSERT_NO_EXCEPTION);
- ASSERT_FALSE(reader.IsEmpty());
-
- Iteration* it1 = MakeGarbageCollected<Iteration>();
- Iteration* it2 = MakeGarbageCollected<Iteration>();
- Iteration* it3 = MakeGarbageCollected<Iteration>();
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it2),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it3),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
-
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-
- EXPECT_EQ(10, underlying_source->DesiredSize());
-
- EXPECT_TRUE(it1->IsSet());
- EXPECT_TRUE(it1->IsValid());
- EXPECT_FALSE(it1->IsDone());
- EXPECT_EQ("a", it1->Value());
-
- EXPECT_TRUE(it2->IsSet());
- EXPECT_TRUE(it2->IsValid());
- EXPECT_FALSE(it2->IsDone());
- EXPECT_EQ("b", it2->Value());
-
- EXPECT_FALSE(it3->IsSet());
-
- underlying_source->Close();
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-
- EXPECT_TRUE(it3->IsSet());
- EXPECT_TRUE(it3->IsValid());
- EXPECT_TRUE(it3->IsDone());
-}
-
-TEST(ReadableStreamOperationsTest, IsReadable) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
-
- auto* readable =
- ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(readable);
-
- auto* closing_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* closed = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), closing_source, 0);
- ASSERT_TRUE(closed);
- closing_source->Close();
-
- auto* erroring_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* errored = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), erroring_source, 0);
- ASSERT_TRUE(errored);
- erroring_source->Error(
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
-
- EXPECT_EQ(ReadableStreamOperations::IsReadable(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), readable),
- ASSERT_NO_EXCEPTION),
- base::make_optional(true));
- EXPECT_EQ(ReadableStreamOperations::IsReadable(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), closed),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- EXPECT_EQ(ReadableStreamOperations::IsReadable(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), errored),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
-}
-
-TEST(ReadableStreamOperationsTest, IsClosed) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
-
- ReadableStream* readable =
- ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(readable);
-
- auto* closing_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* closed = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), closing_source, 0);
- ASSERT_TRUE(closed);
- closing_source->Close();
-
- auto* erroring_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* errored = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), erroring_source, 0);
- ASSERT_TRUE(errored);
- erroring_source->Error(
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
-
- EXPECT_EQ(ReadableStreamOperations::IsClosed(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), readable),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- EXPECT_EQ(ReadableStreamOperations::IsClosed(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), closed),
- ASSERT_NO_EXCEPTION),
- base::make_optional(true));
- EXPECT_EQ(ReadableStreamOperations::IsClosed(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), errored),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
-}
-
-TEST(ReadableStreamOperationsTest, IsErrored) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
-
- auto* readable =
- ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
- ASSERT_TRUE(readable);
-
- auto* closing_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- ReadableStream* closed = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), closing_source, 0);
- ASSERT_TRUE(closed);
- closing_source->Close();
-
- auto* erroring_source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* errored = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), erroring_source, 0);
- ASSERT_TRUE(errored);
- erroring_source->Error(
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate())));
-
- EXPECT_EQ(ReadableStreamOperations::IsErrored(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), readable),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- EXPECT_EQ(ReadableStreamOperations::IsErrored(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), closed),
- ASSERT_NO_EXCEPTION),
- base::make_optional(false));
- EXPECT_EQ(ReadableStreamOperations::IsErrored(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), errored),
- ASSERT_NO_EXCEPTION),
- base::make_optional(true));
-}
-
-TEST(ReadableStreamOperationsTest, Tee) {
- ScopedStreamsNativeForTest enabled(false);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- v8::Local<v8::Context> context = scope.GetScriptState()->GetContext();
- NonThrowableExceptionState exception_state;
- auto* source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), source, 0);
- ASSERT_TRUE(stream);
-
- ScriptValue result = ReadableStreamOperations::Tee(
- scope.GetScriptState(),
- CheckedGetInternalStream(scope.GetScriptState(), stream),
- exception_state);
- ASSERT_FALSE(result.IsEmpty());
- ASSERT_TRUE(result.IsObject());
-
- v8::Local<v8::Value> v8_branch1, v8_branch2;
- ASSERT_TRUE(
- result.V8Value().As<v8::Object>()->Get(context, 0).ToLocal(&v8_branch1));
- ASSERT_TRUE(
- result.V8Value().As<v8::Object>()->Get(context, 1).ToLocal(&v8_branch2));
-
- ScriptValue new1(scope.GetScriptState(), v8_branch1);
- ScriptValue new2(scope.GetScriptState(), v8_branch2);
-
- ASSERT_TRUE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), new1, ASSERT_NO_EXCEPTION)
- .value_or(true));
- ASSERT_TRUE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), new2, ASSERT_NO_EXCEPTION)
- .value_or(true));
-
- ScriptValue reader1 = ReadableStreamOperations::GetReader(
- scope.GetScriptState(), new1, exception_state);
- ScriptValue reader2 = ReadableStreamOperations::GetReader(
- scope.GetScriptState(), new2, exception_state);
-
- ASSERT_FALSE(reader1.IsEmpty());
- ASSERT_FALSE(reader2.IsEmpty());
-
- Iteration* it1 = MakeGarbageCollected<Iteration>();
- Iteration* it2 = MakeGarbageCollected<Iteration>();
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader1)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it1),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader2)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it2),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
-
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_FALSE(it1->IsSet());
- EXPECT_FALSE(it2->IsSet());
-
- source->Enqueue(ScriptValue(scope.GetScriptState(),
- V8String(scope.GetIsolate(), "hello")));
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-
- EXPECT_TRUE(it1->IsSet());
- EXPECT_TRUE(it1->IsValid());
- EXPECT_FALSE(it1->IsDone());
- EXPECT_EQ("hello", it1->Value());
- EXPECT_TRUE(it2->IsSet());
- EXPECT_TRUE(it2->IsValid());
- EXPECT_FALSE(it2->IsDone());
- EXPECT_EQ("hello", it2->Value());
-}
-
-TEST(ReadableStreamOperationsTest, Serialize) {
- ScopedStreamsNativeForTest streams_native_enabled(false);
- ScopedTransferableStreamsForTest transferable_streams_enabled(true);
-
- V8TestingScope scope;
- TryCatchScope try_catch_scope(scope.GetIsolate());
- auto* source =
- MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
- auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
- scope.GetScriptState(), source, 0);
- ASSERT_TRUE(stream);
-
- source->Enqueue(ScriptValue(scope.GetScriptState(),
- V8String(scope.GetIsolate(), "hello")));
- ScriptValue internal_stream =
- CheckedGetInternalStream(scope.GetScriptState(), stream);
- auto* channel =
- MakeGarbageCollected<MessageChannel>(scope.GetExecutionContext());
- ReadableStreamOperations::Serialize(scope.GetScriptState(), internal_stream,
- channel->port1(), ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(ReadableStreamOperations::IsLocked(
- scope.GetScriptState(), internal_stream, ASSERT_NO_EXCEPTION));
- ScriptValue transferred = ReadableStreamOperations::Deserialize(
- scope.GetScriptState(), channel->port2(), ASSERT_NO_EXCEPTION);
- ASSERT_FALSE(transferred.IsEmpty());
- ScriptValue reader = ReadableStreamOperations::GetReader(
- scope.GetScriptState(), transferred, ASSERT_NO_EXCEPTION);
- ASSERT_FALSE(reader.IsEmpty());
- Iteration* it = MakeGarbageCollected<Iteration>();
- ReadableStreamOperations::DefaultReaderRead(scope.GetScriptState(), reader)
- .Then(ReaderFunction::CreateFunction(scope.GetScriptState(), it),
- ReadableStreamOperationsTestNotReached::CreateFunction(
- scope.GetScriptState()));
- // Let the message pass through the MessagePort.
- test::RunPendingTasks();
- // Let the Read promise resolve.
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
-
- EXPECT_TRUE(it->IsSet());
- EXPECT_TRUE(it->IsValid());
- EXPECT_FALSE(it->IsDone());
- EXPECT_EQ("hello", it->Value());
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
index 66b5a1a999b..efc14b76763 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_reader.cc
@@ -19,7 +19,6 @@ ReadableStreamReader* ReadableStreamReader::Create(
ScriptState* script_state,
ReadableStream* stream,
ExceptionState& exception_state) {
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
auto* stream_native = static_cast<ReadableStreamNative*>(stream);
auto* reader = MakeGarbageCollected<ReadableStreamReader>(
script_state, stream_native, exception_state);
@@ -58,9 +57,9 @@ ScriptPromise ReadableStreamReader::closed(ScriptState* script_state) const {
}
ScriptPromise ReadableStreamReader::cancel(ScriptState* script_state) {
- return cancel(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ return cancel(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())));
}
ScriptPromise ReadableStreamReader::cancel(ScriptState* script_state,
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 2217f829919..84c0d971273 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
@@ -29,9 +29,9 @@ namespace blink {
namespace {
// Web platform tests test ReadableStream more thoroughly from scripts.
-class ReadableStreamTest : public testing::TestWithParam<bool> {
+class ReadableStreamTest : public testing::Test {
public:
- ReadableStreamTest() : feature_(GetParam()) {}
+ ReadableStreamTest() {}
base::Optional<String> ReadAll(V8TestingScope& scope,
ReadableStream* stream) {
@@ -40,7 +40,6 @@ class ReadableStreamTest : public testing::TestWithParam<bool> {
v8::Local<v8::Context> context = script_state->GetContext();
v8::Local<v8::Value> v8_stream = ToV8(stream, context->Global(), isolate);
v8::Local<v8::Object> global = context->Global();
-
bool set_result = false;
if (!global->Set(context, V8String(isolate, "stream"), v8_stream)
.To(&set_result)) {
@@ -92,12 +91,9 @@ readAll(stream);
NOTREACHED();
return base::nullopt;
}
-
- private:
- ScopedStreamsNativeForTest feature_;
};
-TEST_P(ReadableStreamTest, CreateWithoutArguments) {
+TEST_F(ReadableStreamTest, CreateWithoutArguments) {
V8TestingScope scope;
ReadableStream* stream =
@@ -106,14 +102,14 @@ TEST_P(ReadableStreamTest, CreateWithoutArguments) {
ASSERT_FALSE(scope.GetExceptionState().HadException());
}
-TEST_P(ReadableStreamTest, CreateWithUnderlyingSourceOnly) {
+TEST_F(ReadableStreamTest, CreateWithUnderlyingSourceOnly) {
V8TestingScope scope;
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
ScriptValue js_underlying_source = ScriptValue(
- scope.GetScriptState(),
+ scope.GetIsolate(),
ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
- scope.GetScriptState()->GetIsolate()));
+ scope.GetIsolate()));
EXPECT_FALSE(underlying_source->IsStartCalled());
@@ -125,14 +121,14 @@ TEST_P(ReadableStreamTest, CreateWithUnderlyingSourceOnly) {
EXPECT_TRUE(underlying_source->IsStartCalled());
}
-TEST_P(ReadableStreamTest, CreateWithFullArguments) {
+TEST_F(ReadableStreamTest, CreateWithFullArguments) {
V8TestingScope scope;
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
ScriptValue js_underlying_source = ScriptValue(
- scope.GetScriptState(),
+ scope.GetIsolate(),
ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
- scope.GetScriptState()->GetIsolate()));
+ scope.GetIsolate()));
ScriptValue js_empty_strategy = EvalWithPrintingError(&scope, "{}");
ASSERT_FALSE(js_empty_strategy.IsEmpty());
ReadableStream* stream =
@@ -143,14 +139,14 @@ TEST_P(ReadableStreamTest, CreateWithFullArguments) {
EXPECT_TRUE(underlying_source->IsStartCalled());
}
-TEST_P(ReadableStreamTest, CreateWithPathologicalStrategy) {
+TEST_F(ReadableStreamTest, CreateWithPathologicalStrategy) {
V8TestingScope scope;
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(scope.GetScriptState());
ScriptValue js_underlying_source = ScriptValue(
- scope.GetScriptState(),
+ scope.GetIsolate(),
ToV8(underlying_source, scope.GetScriptState()->GetContext()->Global(),
- scope.GetScriptState()->GetIsolate()));
+ scope.GetIsolate()));
ScriptValue js_pathological_strategy =
EvalWithPrintingError(&scope, "({get size() { throw Error('e'); }})");
ASSERT_FALSE(js_pathological_strategy.IsEmpty());
@@ -164,16 +160,16 @@ TEST_P(ReadableStreamTest, CreateWithPathologicalStrategy) {
}
// Testing getReader, locked, IsLocked and IsDisturbed.
-TEST_P(ReadableStreamTest, GetReader) {
+TEST_F(ReadableStreamTest, GetReader) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
+ v8::Isolate* isolate = scope.GetIsolate();
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state);
- ScriptValue js_underlying_source =
- ScriptValue(script_state,
- ToV8(underlying_source, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
+ ScriptValue js_underlying_source = ScriptValue(
+ isolate,
+ ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
ReadableStream* stream = ReadableStream::Create(
script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream);
@@ -216,16 +212,16 @@ TEST_P(ReadableStreamTest, GetReader) {
base::make_optional(true));
}
-TEST_P(ReadableStreamTest, Cancel) {
+TEST_F(ReadableStreamTest, Cancel) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
+ v8::Isolate* isolate = scope.GetIsolate();
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state);
- ScriptValue js_underlying_source =
- ScriptValue(script_state,
- ToV8(underlying_source, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
+ ScriptValue js_underlying_source = ScriptValue(
+ isolate,
+ ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
ReadableStream* stream = ReadableStream::Create(
script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream);
@@ -241,16 +237,16 @@ TEST_P(ReadableStreamTest, Cancel) {
EXPECT_FALSE(underlying_source->IsCancelledWithNull());
}
-TEST_P(ReadableStreamTest, CancelWithNull) {
+TEST_F(ReadableStreamTest, CancelWithNull) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
+ v8::Isolate* isolate = scope.GetIsolate();
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state);
- ScriptValue js_underlying_source =
- ScriptValue(script_state,
- ToV8(underlying_source, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
+ ScriptValue js_underlying_source = ScriptValue(
+ isolate,
+ ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
ReadableStream* stream = ReadableStream::Create(
script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream);
@@ -259,10 +255,8 @@ TEST_P(ReadableStreamTest, CancelWithNull) {
EXPECT_FALSE(underlying_source->IsCancelledWithUndefined());
EXPECT_FALSE(underlying_source->IsCancelledWithNull());
- stream->cancel(
- script_state,
- ScriptValue(script_state, v8::Null(script_state->GetIsolate())),
- ASSERT_NO_EXCEPTION);
+ stream->cancel(script_state, ScriptValue(isolate, v8::Null(isolate)),
+ ASSERT_NO_EXCEPTION);
EXPECT_TRUE(underlying_source->IsCancelled());
EXPECT_FALSE(underlying_source->IsCancelledWithUndefined());
@@ -271,24 +265,22 @@ TEST_P(ReadableStreamTest, CancelWithNull) {
// TODO(yhirano): Write tests for pipeThrough and pipeTo.
-TEST_P(ReadableStreamTest, Tee) {
+TEST_F(ReadableStreamTest, Tee) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
+ v8::Isolate* isolate = scope.GetIsolate();
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state);
- ScriptValue js_underlying_source =
- ScriptValue(script_state,
- ToV8(underlying_source, script_state->GetContext()->Global(),
- script_state->GetIsolate()));
+ ScriptValue js_underlying_source = ScriptValue(
+ isolate,
+ ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
ReadableStream* stream = ReadableStream::Create(
script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream);
- underlying_source->Enqueue(
- ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
- underlying_source->Enqueue(
- ScriptValue(script_state, V8String(script_state->GetIsolate(), ", bye")));
+ underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+ underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
underlying_source->Close();
ReadableStream* branch1 = nullptr;
@@ -324,7 +316,7 @@ TEST_P(ReadableStreamTest, Tee) {
EXPECT_EQ(*result2, "hello, bye");
}
-TEST_P(ReadableStreamTest, Close) {
+TEST_F(ReadableStreamTest, Close) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
ExceptionState& exception_state = scope.GetExceptionState();
@@ -353,9 +345,10 @@ TEST_P(ReadableStreamTest, Close) {
base::make_optional(false));
}
-TEST_P(ReadableStreamTest, Error) {
+TEST_F(ReadableStreamTest, Error) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
+ v8::Isolate* isolate = scope.GetIsolate();
ExceptionState& exception_state = scope.GetExceptionState();
auto* underlying_source =
@@ -372,8 +365,7 @@ TEST_P(ReadableStreamTest, Error) {
EXPECT_EQ(stream->IsErrored(script_state, exception_state),
base::make_optional(false));
- underlying_source->Error(
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ underlying_source->Error(ScriptValue(isolate, v8::Undefined(isolate)));
EXPECT_EQ(stream->IsReadable(script_state, exception_state),
base::make_optional(false));
@@ -383,7 +375,7 @@ TEST_P(ReadableStreamTest, Error) {
base::make_optional(true));
}
-TEST_P(ReadableStreamTest, LockAndDisturb) {
+TEST_F(ReadableStreamTest, LockAndDisturb) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
ExceptionState& exception_state = scope.GetExceptionState();
@@ -409,11 +401,12 @@ TEST_P(ReadableStreamTest, LockAndDisturb) {
base::make_optional(true));
}
-TEST_P(ReadableStreamTest, Serialize) {
+TEST_F(ReadableStreamTest, Serialize) {
ScopedTransferableStreamsForTest enabled(true);
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
+ auto* isolate = scope.GetIsolate();
auto* underlying_source =
MakeGarbageCollected<TestUnderlyingSource>(script_state);
@@ -431,17 +424,15 @@ TEST_P(ReadableStreamTest, Serialize) {
script_state, channel->port2(), ASSERT_NO_EXCEPTION);
ASSERT_TRUE(transferred);
- underlying_source->Enqueue(
- ScriptValue(script_state, V8String(script_state->GetIsolate(), "hello")));
- underlying_source->Enqueue(
- ScriptValue(script_state, V8String(script_state->GetIsolate(), ", bye")));
+ underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, "hello")));
+ underlying_source->Enqueue(ScriptValue(isolate, V8String(isolate, ", bye")));
underlying_source->Close();
EXPECT_EQ(ReadAll(scope, transferred),
base::make_optional<String>("hello, bye"));
}
-TEST_P(ReadableStreamTest, GetReadHandle) {
+TEST_F(ReadableStreamTest, GetReadHandle) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
auto* isolate = scope.GetIsolate();
@@ -450,13 +441,13 @@ TEST_P(ReadableStreamTest, GetReadHandle) {
MakeGarbageCollected<TestUnderlyingSource>(script_state);
ScriptValue js_underlying_source = ScriptValue(
- script_state,
+ isolate,
ToV8(underlying_source, script_state->GetContext()->Global(), isolate));
ReadableStream* stream = ReadableStream::Create(
script_state, js_underlying_source, ASSERT_NO_EXCEPTION);
ASSERT_TRUE(stream);
- ScriptValue abc = ScriptValue(script_state, V8String(isolate, "abc"));
+ ScriptValue abc = ScriptValue(isolate, V8String(isolate, "abc"));
underlying_source->Enqueue(abc);
underlying_source->Close();
@@ -521,8 +512,6 @@ TEST_P(ReadableStreamTest, GetReadHandle) {
EXPECT_TRUE(done);
}
-INSTANTIATE_TEST_SUITE_P(, ReadableStreamTest, ::testing::Values(false, true));
-
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc
deleted file mode 100644
index 592654eb501..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.cc
+++ /dev/null
@@ -1,439 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_readable_stream.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
-#include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-
-namespace blink {
-
-class ReadableStreamWrapper::ReadHandleImpl final
- : public ReadableStream::ReadHandle {
- public:
- ReadHandleImpl(v8::Isolate* isolate, v8::Local<v8::Value> reader)
- : reader_(isolate, reader) {}
-
- ~ReadHandleImpl() override = default;
-
- ScriptPromise Read(ScriptState* script_state) override {
- return ReadableStreamOperations::DefaultReaderRead(
- script_state,
- ScriptValue(script_state,
- reader_.NewLocal(script_state->GetIsolate())));
- }
-
- void Trace(Visitor* visitor) override {
- visitor->Trace(reader_);
- ReadHandle::Trace(visitor);
- }
-
- private:
- TraceWrapperV8Reference<v8::Value> reader_;
-};
-
-void ReadableStreamWrapper::Init(ScriptState* script_state,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState& exception_state) {
- ScriptValue value = ReadableStreamOperations::CreateReadableStream(
- script_state, underlying_source, strategy, exception_state);
- if (exception_state.HadException())
- return;
-
- DCHECK(value.IsObject());
- InitWithInternalStream(script_state, value.V8Value().As<v8::Object>(),
- exception_state);
-}
-
-void ReadableStreamWrapper::InitWithInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Object> object,
- ExceptionState& exception_state) {
- DCHECK(ReadableStreamOperations::IsReadableStreamForDCheck(
- script_state, ScriptValue(script_state, object)));
- object_.Set(script_state->GetIsolate(), object);
-
- v8::Isolate* isolate = script_state->GetIsolate();
- v8::TryCatch block(isolate);
- v8::Local<v8::Value> wrapper = ToV8(this, script_state);
- if (wrapper.IsEmpty()) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- v8::Local<v8::Context> context = script_state->GetContext();
- v8::Local<v8::Object> bindings =
- context->GetExtrasBindingObject().As<v8::Object>();
- v8::Local<v8::Value> symbol_value;
- if (!bindings->Get(context, V8String(isolate, "internalReadableStreamSymbol"))
- .ToLocal(&symbol_value)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- if (wrapper.As<v8::Object>()
- ->Set(context, symbol_value.As<v8::Symbol>(), object)
- .IsNothing()) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-}
-
-ReadableStreamWrapper* ReadableStreamWrapper::Create(
- ScriptState* script_state,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState& exception_state) {
- auto* stream = MakeGarbageCollected<ReadableStreamWrapper>();
- stream->Init(script_state, underlying_source, strategy, exception_state);
- if (exception_state.HadException())
- return nullptr;
- return stream;
-}
-
-ReadableStreamWrapper* ReadableStreamWrapper::CreateFromInternalStream(
- ScriptState* script_state,
- ScriptValue object,
- ExceptionState& exception_state) {
- DCHECK(object.IsObject());
- return CreateFromInternalStream(
- script_state, object.V8Value().As<v8::Object>(), exception_state);
-}
-
-ReadableStreamWrapper* ReadableStreamWrapper::CreateFromInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Object> object,
- ExceptionState& exception_state) {
- auto* stream = MakeGarbageCollected<ReadableStreamWrapper>();
- stream->InitWithInternalStream(script_state, object, exception_state);
- if (exception_state.HadException())
- return nullptr;
- return stream;
-}
-
-ReadableStreamWrapper* ReadableStreamWrapper::CreateWithCountQueueingStrategy(
- ScriptState* script_state,
- UnderlyingSourceBase* underlying_source,
- size_t high_water_mark) {
- v8::TryCatch block(script_state->GetIsolate());
- ScriptValue strategy =
- ReadableStreamOperations::CreateCountQueuingStrategy(script_state, 0);
- if (strategy.IsEmpty())
- return nullptr;
-
- ScriptValue value = ReadableStreamOperations::CreateReadableStream(
- script_state, underlying_source, strategy);
- if (value.IsEmpty())
- return nullptr;
-
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kConstructionContext,
- "ReadableStream");
- DCHECK(value.V8Value()->IsObject());
- auto* stream = CreateFromInternalStream(script_state, value, exception_state);
- if (exception_state.HadException())
- exception_state.ClearException();
- return stream;
-}
-
-void ReadableStreamWrapper::Trace(Visitor* visitor) {
- visitor->Trace(object_);
- ReadableStream::Trace(visitor);
-}
-
-ScriptPromise ReadableStreamWrapper::cancel(ScriptState* script_state,
- ExceptionState& exception_state) {
- return cancel(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
-}
-
-bool ReadableStreamWrapper::locked(ScriptState* script_state,
- ExceptionState& exception_state) const {
- auto result = IsLocked(script_state, exception_state);
-
- return !result || *result;
-}
-
-ScriptPromise ReadableStreamWrapper::cancel(ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) {
- if (locked(script_state, exception_state) &&
- !exception_state.HadException()) {
- exception_state.ThrowTypeError("Cannot cancel a locked stream");
- }
-
- if (exception_state.HadException())
- return ScriptPromise();
-
- return ReadableStreamOperations::Cancel(
- script_state, GetInternalStream(script_state), reason, exception_state);
-}
-
-ScriptValue ReadableStreamWrapper::getReader(ScriptState* script_state,
- ExceptionState& exception_state) {
- return ReadableStreamOperations::GetReader(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-ScriptValue ReadableStreamWrapper::getReader(ScriptState* script_state,
- ScriptValue options,
- ExceptionState& exception_state) {
- GetReaderValidateOptions(script_state, options, exception_state);
- if (exception_state.HadException()) {
- return ScriptValue();
- }
- return ReadableStreamOperations::GetReader(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-ScriptValue ReadableStreamWrapper::pipeThrough(
- ScriptState* script_state,
- ScriptValue transform_stream,
- ExceptionState& exception_state) {
- return pipeThrough(
- script_state, transform_stream,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
-}
-
-// https://streams.spec.whatwg.org/#rs-pipe-through
-ScriptValue ReadableStreamWrapper::pipeThrough(
- ScriptState* script_state,
- ScriptValue transform_stream,
- ScriptValue options,
- ExceptionState& exception_state) {
- ScriptValue readable;
- WritableStream* writable = nullptr;
- PipeThroughExtractReadableWritable(script_state, this, transform_stream,
- &readable, &writable, exception_state);
- if (exception_state.HadException()) {
- return ScriptValue();
- }
-
- DCHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
-
- // This cast is safe because the following code will only be run when the
- // native version of WritableStream is not in use.
- WritableStreamWrapper* writable_wrapper =
- static_cast<WritableStreamWrapper*>(writable);
-
- // 8. Let _promise_ be ! ReadableStreamPipeTo(*this*, _writable_,
- // _preventClose_, _preventAbort_, _preventCancel_,
- // _signal_).
-
- ScriptPromise promise = ReadableStreamOperations::PipeTo(
- script_state, GetInternalStream(script_state),
- writable_wrapper->GetInternalStream(script_state), options,
- exception_state);
- if (exception_state.HadException()) {
- return ScriptValue();
- }
-
- // 9. Set _promise_.[[PromiseIsHandled]] to *true*.
- promise.MarkAsHandled();
-
- // 10. Return _readable_.
- return readable;
-}
-
-ScriptPromise ReadableStreamWrapper::pipeTo(ScriptState* script_state,
- ScriptValue destination,
- ExceptionState& exception_state) {
- return pipeTo(
- script_state, destination,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
-}
-
-ScriptPromise ReadableStreamWrapper::pipeTo(ScriptState* script_state,
- ScriptValue destination_value,
- ScriptValue options,
- ExceptionState& exception_state) {
- WritableStream* destination = PipeToCheckSourceAndDestination(
- script_state, this, destination_value, exception_state);
- if (exception_state.HadException()) {
- return ScriptPromise();
- }
- DCHECK(destination);
-
- DCHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
-
- // This cast is safe because the following code will only be run when the
- // native version of WritableStream is not in use.
- WritableStreamWrapper* destination_wrapper =
- static_cast<WritableStreamWrapper*>(destination);
-
- return ReadableStreamOperations::PipeTo(
- script_state, GetInternalStream(script_state),
- destination_wrapper->GetInternalStream(script_state), options,
- exception_state);
-}
-
-ScriptValue ReadableStreamWrapper::tee(ScriptState* script_state,
- ExceptionState& exception_state) {
- return CallTeeAndReturnBranchArray(script_state, this, exception_state);
-}
-
-void ReadableStreamWrapper::Tee(ScriptState* script_state,
- ReadableStream** branch1,
- ReadableStream** branch2,
- ExceptionState& exception_state) {
- v8::Local<v8::Context> context = script_state->GetContext();
-
- if (locked(script_state, exception_state) &&
- !exception_state.HadException()) {
- exception_state.ThrowTypeError("The stream is already locked.");
- }
-
- if (exception_state.HadException())
- return;
-
- ScriptValue tee_result = ReadableStreamOperations::Tee(
- script_state, GetInternalStream(script_state), exception_state);
- if (tee_result.IsEmpty())
- return;
-
- DCHECK(!exception_state.HadException());
- DCHECK(tee_result.V8Value()->IsArray());
-
- v8::Local<v8::Array> branches = tee_result.V8Value().As<v8::Array>();
- v8::Local<v8::Value> v8_branch1, v8_branch2;
- v8::TryCatch block(script_state->GetIsolate());
-
- if (!branches->Get(context, 0).ToLocal(&v8_branch1)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- if (!branches->Get(context, 1).ToLocal(&v8_branch2)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- DCHECK(v8_branch1->IsObject());
- DCHECK(v8_branch2->IsObject());
-
- ReadableStreamWrapper* temp_branch1 =
- MakeGarbageCollected<ReadableStreamWrapper>();
- ReadableStreamWrapper* temp_branch2 =
- MakeGarbageCollected<ReadableStreamWrapper>();
-
- temp_branch1->InitWithInternalStream(
- script_state, v8_branch1.As<v8::Object>(), exception_state);
- if (exception_state.HadException())
- return;
-
- temp_branch2->InitWithInternalStream(
- script_state, v8_branch2.As<v8::Object>(), exception_state);
- if (exception_state.HadException())
- return;
-
- *branch1 = temp_branch1;
- *branch2 = temp_branch2;
-}
-
-ReadableStream::ReadHandle* ReadableStreamWrapper::GetReadHandle(
- ScriptState* script_state,
- ExceptionState& exception_state) {
- ScriptValue reader = ReadableStreamOperations::GetReader(
- script_state, GetInternalStream(script_state), exception_state);
- if (exception_state.HadException()) {
- return nullptr;
- }
- return MakeGarbageCollected<ReadHandleImpl>(script_state->GetIsolate(),
- reader.V8Value());
-}
-
-base::Optional<bool> ReadableStreamWrapper::IsLocked(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- return ReadableStreamOperations::IsLocked(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-base::Optional<bool> ReadableStreamWrapper::IsDisturbed(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- return ReadableStreamOperations::IsDisturbed(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-base::Optional<bool> ReadableStreamWrapper::IsReadable(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- return ReadableStreamOperations::IsReadable(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-base::Optional<bool> ReadableStreamWrapper::IsClosed(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- return ReadableStreamOperations::IsClosed(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-base::Optional<bool> ReadableStreamWrapper::IsErrored(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- return ReadableStreamOperations::IsErrored(
- script_state, GetInternalStream(script_state), exception_state);
-}
-
-void ReadableStreamWrapper::LockAndDisturb(ScriptState* script_state,
- ExceptionState& exception_state) {
- ScriptState::Scope scope(script_state);
-
- const base::Optional<bool> is_locked =
- IsLocked(script_state, exception_state);
- if (!is_locked || is_locked.value())
- return;
-
- ScriptValue reader = getReader(script_state, exception_state);
- if (reader.IsEmpty())
- return;
-
- ScriptPromise promise =
- ReadableStreamOperations::DefaultReaderRead(script_state, reader);
- promise.MarkAsHandled();
-}
-
-void ReadableStreamWrapper::Serialize(ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- ReadableStreamOperations::Serialize(
- script_state, GetInternalStream(script_state), port, exception_state);
-}
-
-// static
-ReadableStreamWrapper* ReadableStreamWrapper::Deserialize(
- ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- // We need to execute V8 Extras JavaScript to create the new ReadableStream.
- // We will not run author code.
- v8::Isolate::AllowJavascriptExecutionScope allow_js(
- script_state->GetIsolate());
- ScriptValue internal_stream = ReadableStreamOperations::Deserialize(
- script_state, port, exception_state);
- if (exception_state.HadException())
- return nullptr;
- return CreateFromInternalStream(script_state, internal_stream,
- exception_state);
-}
-
-ScriptValue ReadableStreamWrapper::GetInternalStream(
- ScriptState* script_state) const {
- return ScriptValue(script_state,
- object_.NewLocal(script_state->GetIsolate()));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.h
deleted file mode 100644
index de06dee68fc..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_wrapper.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
-
-#include "base/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-// This is an implementation of the corresponding IDL interface.
-class CORE_EXPORT ReadableStreamWrapper : public ReadableStream {
- public:
- // Call one of Init functions before using the instance.
- ReadableStreamWrapper() = default;
- ~ReadableStreamWrapper() override = default;
-
- // If an error happens, |exception_state.HadException()| will be true, and
- // |this| will not be usable after that.
- void Init(ScriptState*,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState& exception_state);
- void InitWithInternalStream(ScriptState*,
- v8::Local<v8::Object> object,
- ExceptionState& exception_state);
-
- // Create* functions call Init* internally and returns null when an error
- // happens.
- static ReadableStreamWrapper* Create(ScriptState*,
- ScriptValue underlying_source,
- ScriptValue strategy,
- ExceptionState&);
- static ReadableStreamWrapper* CreateFromInternalStream(
- ScriptState*,
- v8::Local<v8::Object> object,
- ExceptionState&);
- static ReadableStreamWrapper* CreateFromInternalStream(ScriptState*,
- ScriptValue object,
- ExceptionState&);
- // This function doesn't take ExceptionState because the caller cannot have
- // one. Returns null when an error happens.
- static ReadableStreamWrapper* CreateWithCountQueueingStrategy(
- ScriptState*,
- UnderlyingSourceBase* underlying_source,
- size_t high_water_mark);
-
- void Trace(Visitor* visitor) override;
-
- // IDL defined functions
- bool locked(ScriptState*, ExceptionState&) const override;
- ScriptPromise cancel(ScriptState*, ExceptionState&) override;
- ScriptPromise cancel(ScriptState*,
- ScriptValue reason,
- ExceptionState&) override;
- ScriptValue getReader(ScriptState*, ExceptionState&) override;
- ScriptValue getReader(ScriptState*,
- ScriptValue options,
- ExceptionState&) override;
- ScriptValue pipeThrough(ScriptState*,
- ScriptValue transform_stream,
- ExceptionState&) override;
- ScriptValue pipeThrough(ScriptState*,
- ScriptValue transform_stream,
- ScriptValue options,
- ExceptionState&) override;
- ScriptPromise pipeTo(ScriptState*,
- ScriptValue destination,
- ExceptionState&) override;
- ScriptPromise pipeTo(ScriptState*,
- ScriptValue destination,
- ScriptValue options,
- ExceptionState&) override;
- ScriptValue tee(ScriptState*, ExceptionState&) override;
-
- void Tee(ScriptState*,
- ReadableStream** branch1,
- ReadableStream** branch2,
- ExceptionState&) override;
-
- ReadHandle* GetReadHandle(ScriptState*, ExceptionState&) override;
-
- base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const override;
- base::Optional<bool> IsDisturbed(ScriptState*,
- ExceptionState&) const override;
- base::Optional<bool> IsReadable(ScriptState*, ExceptionState&) const override;
- base::Optional<bool> IsClosed(ScriptState*, ExceptionState&) const override;
- base::Optional<bool> IsErrored(ScriptState*, ExceptionState&) const override;
-
- // Makes this stream locked and disturbed.
- void LockAndDisturb(ScriptState*, ExceptionState&) override;
-
- // Serialize this stream to |port|. The stream will be locked by this
- // operation.
- void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
-
- // Given a |port| which is entangled with a MessagePort that was previously
- // passed to Serialize(), returns a new ReadableStreamWrapper which behaves
- // like it was the original.
- static ReadableStreamWrapper* Deserialize(ScriptState*,
- MessagePort* port,
- ExceptionState&);
-
- ScriptValue GetInternalStream(ScriptState* script_state) const;
-
- // In some cases we are known to fail to trace the stream correctly. In such
- // cases |object_| will be silently gone. This function is for detecting the
- // issue. Use this function at places where an actual crash happens. Do not
- // use this function to write "just in case" code.
- bool IsBroken() const override { return object_.IsEmpty(); }
-
- private:
- class ReadHandleImpl;
-
- TraceWrapperV8Reference<v8::Object> object_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_WRAPPER_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/stream_algorithms.h b/chromium/third_party/blink/renderer/core/streams/stream_algorithms.h
index 242a3102877..839ccd74464 100644
--- a/chromium/third_party/blink/renderer/core/streams/stream_algorithms.h
+++ b/chromium/third_party/blink/renderer/core/streams/stream_algorithms.h
@@ -22,8 +22,7 @@ class Visitor;
// https://streams.spec.whatwg.org/#rs-default-controller-internal-slots.
// Subclasses may refer to JavaScript functions and so objects of this type must
// always be reachable by V8's garbage collector.
-class StrategySizeAlgorithm
- : public GarbageCollectedFinalized<StrategySizeAlgorithm> {
+class StrategySizeAlgorithm : public GarbageCollected<StrategySizeAlgorithm> {
public:
virtual ~StrategySizeAlgorithm() = default;
@@ -38,8 +37,7 @@ class StrategySizeAlgorithm
// method of the underlying object. These differ from other underlying
// algorithms in that they can throw synchronously. Objects of this
// type must always be reachable by V8's garbage collector.
-class StreamStartAlgorithm
- : public GarbageCollectedFinalized<StreamStartAlgorithm> {
+class StreamStartAlgorithm : public GarbageCollected<StreamStartAlgorithm> {
public:
virtual ~StreamStartAlgorithm() = default;
@@ -52,7 +50,7 @@ class StreamStartAlgorithm
// Promise. This is used as the type for all the algorithms in the standard that
// do not use StrategySizeAlgorithm or StreamStartAlgorithm. Objects of this
// type must always be reachable by V8's garbage collector.
-class StreamAlgorithm : public GarbageCollectedFinalized<StreamAlgorithm> {
+class StreamAlgorithm : public GarbageCollected<StreamAlgorithm> {
public:
virtual ~StreamAlgorithm() = default;
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 3e6ecf29a3a..02a7014e9b7 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
@@ -21,8 +21,8 @@ class Visitor;
// need to be stored somewhere: promises on the stack should generally use
// v8::Local<v8::Promise>, or ScriptPromise if they are to be returned to the
// bindings code.
-class CORE_EXPORT StreamPromiseResolver
- : public GarbageCollectedFinalized<StreamPromiseResolver> {
+class CORE_EXPORT StreamPromiseResolver final
+ : public GarbageCollected<StreamPromiseResolver> {
public:
// Implements "a promise rejected with" from the INFRA standard.
// https://www.w3.org/2001/tag/doc/promises-guide/#a-promise-rejected-with
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 82efecbc340..c99ce6d5983 100644
--- a/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -121,7 +121,7 @@ void PackAndPostMessage(ScriptState* script_state,
v8::Local<v8::Object> packed = CreateKeyValueObject(
isolate, "t", v8::Number::New(isolate, static_cast<int>(type)), "v",
value);
- port->postMessage(script_state, ScriptValue(script_state, packed),
+ port->postMessage(script_state, ScriptValue(isolate, packed),
PostMessageOptions::Create(), exception_state);
}
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 3811b0541e5..e8f7de583f5 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
@@ -49,7 +49,7 @@ TEST(TransferableStreamsTest, SmokeTest) {
.V8Value()
.As<v8::Object>());
- writer->write(script_state, ScriptValue::CreateNull(script_state));
+ writer->write(script_state, ScriptValue::CreateNull(scope.GetIsolate()));
class ExpectNullResponse : public ScriptFunction {
public:
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
index a88a0ef416e..be4455296b6 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream.cc
@@ -8,12 +8,10 @@
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/transform_stream_native.h"
#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_wrapper.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
+#include "third_party/blink/renderer/core/streams/writable_stream.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/visitor.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -26,7 +24,7 @@ TransformStream::~TransformStream() = default;
TransformStream* TransformStream::Create(ScriptState* script_state,
ExceptionState& exception_state) {
- ScriptValue undefined(script_state,
+ ScriptValue undefined(script_state->GetIsolate(),
v8::Undefined(script_state->GetIsolate()));
return Create(script_state, undefined, undefined, undefined, exception_state);
}
@@ -35,7 +33,7 @@ TransformStream* TransformStream::Create(
ScriptState* script_state,
ScriptValue transform_stream_transformer,
ExceptionState& exception_state) {
- ScriptValue undefined(script_state,
+ ScriptValue undefined(script_state->GetIsolate(),
v8::Undefined(script_state->GetIsolate()));
return Create(script_state, transform_stream_transformer, undefined,
undefined, exception_state);
@@ -46,7 +44,7 @@ TransformStream* TransformStream::Create(
ScriptValue transform_stream_transformer,
ScriptValue writable_strategy,
ExceptionState& exception_state) {
- ScriptValue undefined(script_state,
+ ScriptValue undefined(script_state->GetIsolate(),
v8::Undefined(script_state->GetIsolate()));
return Create(script_state, transform_stream_transformer, writable_strategy,
undefined, exception_state);
@@ -59,15 +57,9 @@ TransformStream* TransformStream::Create(ScriptState* script_state,
ExceptionState& exception_state) {
auto* ts = MakeGarbageCollected<TransformStream>();
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- TransformStreamNative::InitFromJS(
- script_state, transformer, writable_strategy, readable_strategy,
- &ts->readable_, &ts->writable_, exception_state);
- } else {
- TransformStreamWrapper::InitFromJS(
- script_state, transformer, writable_strategy, readable_strategy,
- &ts->readable_, &ts->writable_, exception_state);
- }
+ TransformStreamNative::InitFromJS(
+ script_state, transformer, writable_strategy, readable_strategy,
+ &ts->readable_, &ts->writable_, exception_state);
if (exception_state.HadException()) {
return nullptr;
@@ -79,13 +71,8 @@ TransformStream* TransformStream::Create(ScriptState* script_state,
void TransformStream::Init(TransformStreamTransformer* transformer,
ScriptState* script_state,
ExceptionState& exception_state) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- TransformStreamNative::Init(script_state, transformer, &readable_,
- &writable_, exception_state);
- } else {
- TransformStreamWrapper::Init(script_state, transformer, &readable_,
- &writable_, exception_state);
- }
+ TransformStreamNative::Init(script_state, transformer, &readable_, &writable_,
+ exception_state);
if (exception_state.HadException()) {
return;
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream.h b/chromium/third_party/blink/renderer/core/streams/transform_stream.h
index b46bde0d83a..11d95149e66 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream.h
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/member.h"
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc
deleted file mode 100644
index c4216100976..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-
-namespace blink {
-
-TransformStreamDefaultControllerWrapper::
- TransformStreamDefaultControllerWrapper(ScriptState* script_state,
- v8::Local<v8::Value> controller)
- : script_state_(script_state), controller_(controller) {
- DCHECK(controller->IsObject());
-}
-
-void TransformStreamDefaultControllerWrapper::Enqueue(
- v8::Local<v8::Value> chunk,
- ExceptionState& exception_state) {
- DCHECK(controller_->IsObject());
- v8::Local<v8::Value> args[] = {controller_, chunk};
- v8::TryCatch block(script_state_->GetIsolate());
- V8ScriptRunner::CallExtra(script_state_,
- "TransformStreamDefaultControllerEnqueue", args);
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h
deleted file mode 100644
index 7c60936a570..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-// Implementation of TransformStreamDefaultControllerInterface for the V8 Extras
-// implementation of Streams.
-class CORE_EXPORT TransformStreamDefaultControllerWrapper final
- : public TransformStreamDefaultControllerInterface {
- STACK_ALLOCATED();
-
- public:
- TransformStreamDefaultControllerWrapper(ScriptState*,
- v8::Local<v8::Value> controller);
-
- void Enqueue(v8::Local<v8::Value> chunk, ExceptionState&) override;
-
- private:
- Member<ScriptState> script_state_;
- v8::Local<v8::Value> controller_;
-
- DISALLOW_COPY_AND_ASSIGN(TransformStreamDefaultControllerWrapper);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_DEFAULT_CONTROLLER_WRAPPER_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
index 073efffc0cc..1e604893be8 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.cc
@@ -151,9 +151,9 @@ void TransformStreamNative::InitFromJS(ScriptState* script_state,
Member<ReadableStream>* readable,
Member<WritableStream>* writable,
ExceptionState& exception_state) {
- const auto* stream = MakeGarbageCollected<TransformStreamNative>(
- script_state, raw_transformer, raw_writable_strategy,
- raw_readable_strategy, exception_state);
+ auto* stream = MakeGarbageCollected<TransformStreamNative>();
+ stream->InitInternal(script_state, raw_transformer, raw_writable_strategy,
+ raw_readable_strategy, exception_state);
*readable = stream->readable_;
*writable = stream->writable_;
// We no longer need a direct reference to |stream|.
@@ -255,149 +255,6 @@ TransformStreamNative* TransformStreamNative::Create(
// This constructor is only used internally.
TransformStreamNative::TransformStreamNative() = default;
-TransformStreamNative::TransformStreamNative(ScriptState* script_state,
- ScriptValue raw_transformer,
- ScriptValue raw_writable_strategy,
- ScriptValue raw_readable_strategy,
- ExceptionState& exception_state) {
- // TODO(ricea): Move this to IDL.
- UseCounter::Count(ExecutionContext::From(script_state),
- WebFeature::kTransformStreamConstructor);
-
- DCHECK(!raw_transformer.IsEmpty());
- DCHECK(!raw_writable_strategy.IsEmpty());
- DCHECK(!raw_readable_strategy.IsEmpty());
-
- auto context = script_state->GetContext();
- auto* isolate = script_state->GetIsolate();
-
- // https://streams.spec.whatwg.org/#ts-constructor
- // Perform the "transformer = {}" step from the function signature.
- v8::Local<v8::Object> transformer;
- ScriptValueToObject(script_state, raw_transformer, &transformer,
- exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // Perform the "writableStrategy = {}" step from the function signature, and
- // 1. Let writableSizeFunction be ? GetV(writableStrategy, "size").
- // 2. Let writableHighWaterMark be ? GetV(writableStrategy, "highWaterMark").
- StrategyUnpacker writable_strategy_unpacker(
- script_state, raw_writable_strategy, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // Perform the "readableStrategy = {}" step from the function signature, and
- // 3. Let readableSizeFunction be ? GetV(readableStrategy, "size").
- // 4. Let readableHighWaterMark be ? GetV(readableStrategy, "highWaterMark").
- StrategyUnpacker readable_strategy_unpacker(
- script_state, raw_readable_strategy, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- v8::TryCatch try_catch(isolate);
-
- // 5. Let writableType be ? GetV(transformer, "writableType").
- v8::Local<v8::Value> writable_type;
- if (!transformer->Get(context, V8AtomicString(isolate, "writableType"))
- .ToLocal(&writable_type)) {
- exception_state.RethrowV8Exception(try_catch.Exception());
- return;
- }
-
- // 6. If writableType is not undefined, throw a RangeError exception.
- if (!writable_type->IsUndefined()) {
- exception_state.ThrowRangeError("Invalid writableType was specified");
- return;
- }
-
- // 7. Let writableSizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(
- // writableSizeFunction).
- auto* writable_size_algorithm = writable_strategy_unpacker.MakeSizeAlgorithm(
- script_state, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 8. If writableHighWaterMark is undefined, set writableHighWaterMark to 1.
- // 9. Set writableHighWaterMark to ? ValidateAndNormalizeHighWaterMark(
- // writableHighWaterMark).
- double writable_high_water_mark = writable_strategy_unpacker.GetHighWaterMark(
- script_state, 1, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 10. Let readableType be ? GetV(transformer, "readableType").
- v8::Local<v8::Value> readable_type;
- if (!transformer->Get(context, V8AtomicString(isolate, "readableType"))
- .ToLocal(&readable_type)) {
- exception_state.RethrowV8Exception(try_catch.Exception());
- return;
- }
-
- // 11. If readableType is not undefined, throw a RangeError exception.
- if (!readable_type->IsUndefined()) {
- exception_state.ThrowRangeError("Invalid readableType was specified");
- return;
- }
-
- // 12. Let readableSizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(
- // readableSizeFunction).
- auto* readable_size_algorithm = readable_strategy_unpacker.MakeSizeAlgorithm(
- script_state, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 13. If readableHighWaterMark is undefined, set readableHighWaterMark to 0.
- // 14. Set readableHighWaterMark be ? ValidateAndNormalizeHighWaterMark(
- // readableHighWaterMark).
- double readable_high_water_mark = readable_strategy_unpacker.GetHighWaterMark(
- script_state, 0, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 15. Let startPromise be a new promise.
- auto* start_promise =
- MakeGarbageCollected<StreamPromiseResolver>(script_state);
-
- // 16. Perform ! InitializeTransformStream(this, startPromise,
- // writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark,
- // readableSizeAlgorithm).
- Initialize(script_state, this, start_promise, writable_high_water_mark,
- writable_size_algorithm, readable_high_water_mark,
- readable_size_algorithm);
-
- // 17. Perform ? SetUpTransformStreamDefaultControllerFromTransformer(this,
- // transformer).
- const auto controller_value =
- TransformStreamDefaultController::SetUpFromTransformer(
- script_state, this, transformer, exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 18. Let startResult be ? InvokeOrNoop(transformer, "start", « this.
- // [[transformStreamController]] »).
- v8::MaybeLocal<v8::Value> start_result_maybe =
- CallOrNoop1(script_state, transformer, "start", "transformer.start",
- controller_value, exception_state);
- v8::Local<v8::Value> start_result;
- if (!start_result_maybe.ToLocal(&start_result)) {
- CHECK(exception_state.HadException());
- return;
- }
- DCHECK(!exception_state.HadException());
-
- // 19. Resolve startPromise with startResult.
- start_promise->Resolve(script_state, start_result);
-}
-
void TransformStreamNative::Trace(Visitor* visitor) {
visitor->Trace(backpressure_change_promise_);
visitor->Trace(readable_);
@@ -737,6 +594,151 @@ class TransformStreamNative::DefaultSourceCancelAlgorithm final
Member<TransformStreamNative> stream_;
};
+// This is split out from the constructor in this implementation as calling
+// JavaScript from inside a C++ constructor can cause GC problems.
+void TransformStreamNative::InitInternal(ScriptState* script_state,
+ ScriptValue raw_transformer,
+ ScriptValue raw_writable_strategy,
+ ScriptValue raw_readable_strategy,
+ ExceptionState& exception_state) {
+ // TODO(ricea): Move this to IDL.
+ UseCounter::Count(ExecutionContext::From(script_state),
+ WebFeature::kTransformStreamConstructor);
+
+ DCHECK(!raw_transformer.IsEmpty());
+ DCHECK(!raw_writable_strategy.IsEmpty());
+ DCHECK(!raw_readable_strategy.IsEmpty());
+
+ auto context = script_state->GetContext();
+ auto* isolate = script_state->GetIsolate();
+
+ // https://streams.spec.whatwg.org/#ts-constructor
+ // Perform the "transformer = {}" step from the function signature.
+ v8::Local<v8::Object> transformer;
+ ScriptValueToObject(script_state, raw_transformer, &transformer,
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // Perform the "writableStrategy = {}" step from the function signature, and
+ // 1. Let writableSizeFunction be ? GetV(writableStrategy, "size").
+ // 2. Let writableHighWaterMark be ? GetV(writableStrategy, "highWaterMark").
+ StrategyUnpacker writable_strategy_unpacker(
+ script_state, raw_writable_strategy, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // Perform the "readableStrategy = {}" step from the function signature, and
+ // 3. Let readableSizeFunction be ? GetV(readableStrategy, "size").
+ // 4. Let readableHighWaterMark be ? GetV(readableStrategy, "highWaterMark").
+ StrategyUnpacker readable_strategy_unpacker(
+ script_state, raw_readable_strategy, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ v8::TryCatch try_catch(isolate);
+
+ // 5. Let writableType be ? GetV(transformer, "writableType").
+ v8::Local<v8::Value> writable_type;
+ if (!transformer->Get(context, V8AtomicString(isolate, "writableType"))
+ .ToLocal(&writable_type)) {
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ return;
+ }
+
+ // 6. If writableType is not undefined, throw a RangeError exception.
+ if (!writable_type->IsUndefined()) {
+ exception_state.ThrowRangeError("Invalid writableType was specified");
+ return;
+ }
+
+ // 7. Let writableSizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(
+ // writableSizeFunction).
+ auto* writable_size_algorithm = writable_strategy_unpacker.MakeSizeAlgorithm(
+ script_state, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 8. If writableHighWaterMark is undefined, set writableHighWaterMark to 1.
+ // 9. Set writableHighWaterMark to ? ValidateAndNormalizeHighWaterMark(
+ // writableHighWaterMark).
+ double writable_high_water_mark = writable_strategy_unpacker.GetHighWaterMark(
+ script_state, 1, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 10. Let readableType be ? GetV(transformer, "readableType").
+ v8::Local<v8::Value> readable_type;
+ if (!transformer->Get(context, V8AtomicString(isolate, "readableType"))
+ .ToLocal(&readable_type)) {
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ return;
+ }
+
+ // 11. If readableType is not undefined, throw a RangeError exception.
+ if (!readable_type->IsUndefined()) {
+ exception_state.ThrowRangeError("Invalid readableType was specified");
+ return;
+ }
+
+ // 12. Let readableSizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(
+ // readableSizeFunction).
+ auto* readable_size_algorithm = readable_strategy_unpacker.MakeSizeAlgorithm(
+ script_state, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 13. If readableHighWaterMark is undefined, set readableHighWaterMark to 0.
+ // 14. Set readableHighWaterMark be ? ValidateAndNormalizeHighWaterMark(
+ // readableHighWaterMark).
+ double readable_high_water_mark = readable_strategy_unpacker.GetHighWaterMark(
+ script_state, 0, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 15. Let startPromise be a new promise.
+ auto* start_promise =
+ MakeGarbageCollected<StreamPromiseResolver>(script_state);
+
+ // 16. Perform ! InitializeTransformStream(this, startPromise,
+ // writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark,
+ // readableSizeAlgorithm).
+ Initialize(script_state, this, start_promise, writable_high_water_mark,
+ writable_size_algorithm, readable_high_water_mark,
+ readable_size_algorithm);
+
+ // 17. Perform ? SetUpTransformStreamDefaultControllerFromTransformer(this,
+ // transformer).
+ const auto controller_value =
+ TransformStreamDefaultController::SetUpFromTransformer(
+ script_state, this, transformer, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 18. Let startResult be ? InvokeOrNoop(transformer, "start", « this.
+ // [[transformStreamController]] »).
+ v8::MaybeLocal<v8::Value> start_result_maybe =
+ CallOrNoop1(script_state, transformer, "start", "transformer.start",
+ controller_value, exception_state);
+ v8::Local<v8::Value> start_result;
+ if (!start_result_maybe.ToLocal(&start_result)) {
+ CHECK(exception_state.HadException());
+ return;
+ }
+ DCHECK(!exception_state.HadException());
+
+ // 19. Resolve startPromise with startResult.
+ start_promise->Resolve(script_state, start_result);
+}
+
void TransformStreamNative::Initialize(
ScriptState* script_state,
TransformStreamNative* stream,
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.h
index e8275c0619b..a0af686866f 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_native.h
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_native.h
@@ -87,6 +87,14 @@ class CORE_EXPORT TransformStreamNative final
class DefaultSourcePullAlgorithm;
class DefaultSourceCancelAlgorithm;
+ // Performs the functions performed by the constructor in the standard.
+ // https://streams.spec.whatwg.org/#ts-constructor
+ void InitInternal(ScriptState*,
+ ScriptValue raw_transformer,
+ ScriptValue raw_writable_strategy,
+ ScriptValue raw_readable_strategy,
+ ExceptionState&);
+
// https://streams.spec.whatwg.org/#initialize-transform-stream
static void Initialize(ScriptState*,
TransformStreamNative*,
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc
index 3cf0af4e5ca..173e331d57a 100644
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/transform_stream_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/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/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -22,7 +23,6 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
@@ -32,9 +32,9 @@ namespace {
using ::testing::_;
using ::testing::Mock;
-class TransformStreamTest : public ::testing::TestWithParam<bool> {
+class TransformStreamTest : public ::testing::Test {
public:
- TransformStreamTest() : feature_(GetParam()) {}
+ TransformStreamTest() {}
TransformStream* Stream() const { return stream_; }
@@ -66,7 +66,6 @@ class TransformStreamTest : public ::testing::TestWithParam<bool> {
private:
Persistent<TransformStream> stream_;
- ScopedStreamsNativeForTest feature_;
};
class IdentityTransformer final : public TransformStreamTransformer {
@@ -119,14 +118,14 @@ class MockTransformStreamTransformer : public TransformStreamTransformer {
};
// If this doesn't work then nothing else will.
-TEST_P(TransformStreamTest, Construct) {
+TEST_F(TransformStreamTest, Construct) {
V8TestingScope scope;
Init(MakeGarbageCollected<IdentityTransformer>(scope.GetScriptState()),
scope.GetScriptState(), ASSERT_NO_EXCEPTION);
EXPECT_TRUE(Stream());
}
-TEST_P(TransformStreamTest, Accessors) {
+TEST_F(TransformStreamTest, Accessors) {
V8TestingScope scope;
Init(MakeGarbageCollected<IdentityTransformer>(scope.GetScriptState()),
scope.GetScriptState(), ASSERT_NO_EXCEPTION);
@@ -136,7 +135,7 @@ TEST_P(TransformStreamTest, Accessors) {
EXPECT_TRUE(writable);
}
-TEST_P(TransformStreamTest, TransformIsCalled) {
+TEST_F(TransformStreamTest, TransformIsCalled) {
V8TestingScope scope;
auto* mock = MakeGarbageCollected<MockTransformStreamTransformer>(
scope.GetScriptState());
@@ -157,7 +156,7 @@ TEST_P(TransformStreamTest, TransformIsCalled) {
Mock::AllowLeak(mock);
}
-TEST_P(TransformStreamTest, FlushIsCalled) {
+TEST_F(TransformStreamTest, FlushIsCalled) {
V8TestingScope scope;
auto* mock = MakeGarbageCollected<MockTransformStreamTransformer>(
scope.GetScriptState());
@@ -176,118 +175,47 @@ TEST_P(TransformStreamTest, FlushIsCalled) {
Mock::AllowLeak(mock);
}
-class ExpectNotReached : public ScriptFunction {
- public:
- static v8::Local<v8::Function> Create(ScriptState* script_state) {
- auto* self = MakeGarbageCollected<ExpectNotReached>(script_state);
- return self->BindToV8Function();
- }
-
- explicit ExpectNotReached(ScriptState* script_state)
- : ScriptFunction(script_state) {}
-
- private:
- ScriptValue Call(ScriptValue) override {
- ADD_FAILURE() << "ExpectNotReached was reached";
- return ScriptValue();
- }
-};
-
-// Fails the test if the iterator passed to the function does not have a value
-// of exactly |expected|.
-class ExpectChunkIsString : public ScriptFunction {
- public:
- static v8::Local<v8::Function> Create(ScriptState* script_state,
- const String& expected,
- bool* called) {
- auto* self = MakeGarbageCollected<ExpectChunkIsString>(script_state,
- expected, called);
- return self->BindToV8Function();
- }
-
- ExpectChunkIsString(ScriptState* script_state,
- const String& expected,
- bool* called)
- : ScriptFunction(script_state), expected_(expected), called_(called) {}
-
- private:
- ScriptValue Call(ScriptValue value) override {
- *called_ = true;
- if (!value.IsObject()) {
- ADD_FAILURE() << "iterator must be an object";
- return ScriptValue();
- }
- bool done = false;
- auto* script_state = GetScriptState();
- auto chunk = V8UnpackIteratorResult(
- script_state,
- value.V8Value()->ToObject(script_state->GetContext()).ToLocalChecked(),
- &done);
- EXPECT_FALSE(done);
- EXPECT_FALSE(chunk.IsEmpty());
- EXPECT_EQ(ToCoreStringWithUndefinedOrNullCheck(chunk.ToLocalChecked()),
- expected_);
- return ScriptValue();
- }
-
- String expected_;
- bool* called_;
-};
-
-class ExpectTypeError : public ScriptFunction {
- public:
- static v8::Local<v8::Function> Create(ScriptState* script_state,
- const String& message,
- bool* called) {
- auto* self =
- MakeGarbageCollected<ExpectTypeError>(script_state, message, called);
- return self->BindToV8Function();
- }
-
- ExpectTypeError(ScriptState* script_state,
- const String& message,
- bool* called)
- : ScriptFunction(script_state), message_(message), called_(called) {}
-
- private:
- ScriptValue Call(ScriptValue value) override {
- *called_ = true;
- EXPECT_TRUE(IsTypeError(GetScriptState(), value, message_));
- return ScriptValue();
+bool IsIteratorForStringMatching(ScriptState* script_state,
+ ScriptValue value,
+ const String& expected) {
+ if (!value.IsObject()) {
+ return false;
}
+ bool done = false;
+ auto chunk = V8UnpackIteratorResult(
+ script_state,
+ value.V8Value()->ToObject(script_state->GetContext()).ToLocalChecked(),
+ &done);
+ if (done || chunk.IsEmpty())
+ return false;
+ return ToCoreStringWithUndefinedOrNullCheck(chunk.ToLocalChecked()) ==
+ expected;
+}
- static bool IsTypeError(ScriptState* script_state,
- ScriptValue value,
- const String& message) {
- v8::Local<v8::Object> object;
- if (!value.V8Value()
- ->ToObject(script_state->GetContext())
- .ToLocal(&object)) {
- return false;
- }
- if (!object->IsNativeError())
- return false;
- return Has(script_state, object, "name", "TypeError") &&
- Has(script_state, object, "message", message);
+bool IsTypeError(ScriptState* script_state,
+ ScriptValue value,
+ const String& message) {
+ v8::Local<v8::Object> object;
+ if (!value.V8Value()->ToObject(script_state->GetContext()).ToLocal(&object)) {
+ return false;
}
+ if (!object->IsNativeError())
+ return false;
- static bool Has(ScriptState* script_state,
- v8::Local<v8::Object> object,
- const String& key,
- const String& value) {
- auto context = script_state->GetContext();
- auto* isolate = script_state->GetIsolate();
+ const auto& Has = [script_state, object](const String& key,
+ const String& value) -> bool {
v8::Local<v8::Value> actual;
- return object->Get(context, V8AtomicString(isolate, key))
+ return object
+ ->Get(script_state->GetContext(),
+ V8AtomicString(script_state->GetIsolate(), key))
.ToLocal(&actual) &&
ToCoreStringWithUndefinedOrNullCheck(actual) == value;
- }
+ };
- String message_;
- bool* called_;
-};
+ return Has("name", "TypeError") && Has("message", message);
+}
-TEST_P(TransformStreamTest, EnqueueFromTransform) {
+TEST_F(TransformStreamTest, EnqueueFromTransform) {
V8TestingScope scope;
auto* script_state = scope.GetScriptState();
Init(MakeGarbageCollected<IdentityTransformer>(scope.GetScriptState()),
@@ -302,15 +230,13 @@ TEST_P(TransformStreamTest, EnqueueFromTransform) {
ReadableStream* readable = Stream()->Readable();
auto* read_handle =
readable->GetReadHandle(script_state, ASSERT_NO_EXCEPTION);
- bool chunk_seen = false;
- read_handle->Read(script_state)
- .Then(ExpectChunkIsString::Create(script_state, "a", &chunk_seen),
- ExpectNotReached::Create(script_state));
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(chunk_seen);
+ ScriptPromiseTester tester(script_state, read_handle->Read(script_state));
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsFulfilled());
+ EXPECT_TRUE(IsIteratorForStringMatching(script_state, tester.Value(), "a"));
}
-TEST_P(TransformStreamTest, EnqueueFromFlush) {
+TEST_F(TransformStreamTest, EnqueueFromFlush) {
class EnqueueFromFlushTransformer : public TransformStreamTransformer {
public:
explicit EnqueueFromFlushTransformer(ScriptState* script_state)
@@ -346,15 +272,13 @@ TEST_P(TransformStreamTest, EnqueueFromFlush) {
ReadableStream* readable = Stream()->Readable();
auto* read_handle =
readable->GetReadHandle(script_state, ASSERT_NO_EXCEPTION);
- bool chunkSeen = false;
- read_handle->Read(script_state)
- .Then(ExpectChunkIsString::Create(script_state, "a", &chunkSeen),
- ExpectNotReached::Create(script_state));
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(chunkSeen);
+ ScriptPromiseTester tester(script_state, read_handle->Read(script_state));
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsFulfilled());
+ EXPECT_TRUE(IsIteratorForStringMatching(script_state, tester.Value(), "a"));
}
-TEST_P(TransformStreamTest, ThrowFromTransform) {
+TEST_F(TransformStreamTest, ThrowFromTransform) {
static constexpr char kMessage[] = "errorInTransform";
class ThrowFromTransformTransformer : public TransformStreamTransformer {
public:
@@ -393,22 +317,19 @@ TEST_P(TransformStreamTest, ThrowFromTransform) {
ReadableStream* readable = Stream()->Readable();
auto* read_handle =
readable->GetReadHandle(script_state, ASSERT_NO_EXCEPTION);
- bool readableTypeErrorThrown = false;
- bool writableTypeErrorThrown = false;
- read_handle->Read(script_state)
- .Then(ExpectNotReached::Create(script_state),
- ExpectTypeError::Create(script_state, kMessage,
- &readableTypeErrorThrown));
- ScriptPromise::Cast(script_state, promise)
- .Then(ExpectNotReached::Create(script_state),
- ExpectTypeError::Create(script_state, kMessage,
- &writableTypeErrorThrown));
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(readableTypeErrorThrown);
- EXPECT_TRUE(writableTypeErrorThrown);
+ ScriptPromiseTester read_tester(script_state,
+ read_handle->Read(script_state));
+ read_tester.WaitUntilSettled();
+ EXPECT_TRUE(read_tester.IsRejected());
+ EXPECT_TRUE(IsTypeError(script_state, read_tester.Value(), kMessage));
+ ScriptPromiseTester write_tester(script_state,
+ ScriptPromise::Cast(script_state, promise));
+ write_tester.WaitUntilSettled();
+ EXPECT_TRUE(write_tester.IsRejected());
+ EXPECT_TRUE(IsTypeError(script_state, write_tester.Value(), kMessage));
}
-TEST_P(TransformStreamTest, ThrowFromFlush) {
+TEST_F(TransformStreamTest, ThrowFromFlush) {
static constexpr char kMessage[] = "errorInFlush";
class ThrowFromFlushTransformer : public TransformStreamTransformer {
public:
@@ -445,22 +366,19 @@ TEST_P(TransformStreamTest, ThrowFromFlush) {
ReadableStream* readable = Stream()->Readable();
auto* read_handle =
readable->GetReadHandle(script_state, ASSERT_NO_EXCEPTION);
- bool readableTypeErrorThrown = false;
- bool writableTypeErrorThrown = false;
- read_handle->Read(script_state)
- .Then(ExpectNotReached::Create(script_state),
- ExpectTypeError::Create(script_state, kMessage,
- &readableTypeErrorThrown));
- ScriptPromise::Cast(script_state, promise)
- .Then(ExpectNotReached::Create(script_state),
- ExpectTypeError::Create(script_state, kMessage,
- &writableTypeErrorThrown));
- v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
- EXPECT_TRUE(readableTypeErrorThrown);
- EXPECT_TRUE(writableTypeErrorThrown);
+ ScriptPromiseTester read_tester(script_state,
+ read_handle->Read(script_state));
+ read_tester.WaitUntilSettled();
+ EXPECT_TRUE(read_tester.IsRejected());
+ EXPECT_TRUE(IsTypeError(script_state, read_tester.Value(), kMessage));
+ ScriptPromiseTester write_tester(script_state,
+ ScriptPromise::Cast(script_state, promise));
+ write_tester.WaitUntilSettled();
+ EXPECT_TRUE(write_tester.IsRejected());
+ EXPECT_TRUE(IsTypeError(script_state, write_tester.Value(), kMessage));
}
-TEST_P(TransformStreamTest, CreateFromReadableWritablePair) {
+TEST_F(TransformStreamTest, CreateFromReadableWritablePair) {
V8TestingScope scope;
ReadableStream* readable =
ReadableStream::Create(scope.GetScriptState(), ASSERT_NO_EXCEPTION);
@@ -471,7 +389,5 @@ TEST_P(TransformStreamTest, CreateFromReadableWritablePair) {
EXPECT_EQ(writable, transform.Writable());
}
-INSTANTIATE_TEST_SUITE_P(, TransformStreamTest, ::testing::Values(false, true));
-
} // namespace
} // namespace blink
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 bb4bb041dbd..cbbb5b350a5 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
@@ -14,6 +14,7 @@
namespace blink {
class ExceptionState;
+class ScriptState;
class TransformStreamDefaultControllerInterface;
class Visitor;
@@ -27,7 +28,7 @@ class Visitor;
// uncollectable cycles implementations must not directly or indirectly strongly
// reference any JS object.
class CORE_EXPORT TransformStreamTransformer
- : public GarbageCollectedFinalized<TransformStreamTransformer> {
+ : public GarbageCollected<TransformStreamTransformer> {
public:
TransformStreamTransformer() = default;
virtual ~TransformStreamTransformer() = default;
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc b/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc
deleted file mode 100644
index 5069438a9ac..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/transform_stream_wrapper.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.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_script_runner.h"
-#include "third_party/blink/renderer/core/streams/readable_stream.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_wrapper.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_wrapper.h"
-#include "third_party/blink/renderer/core/streams/transform_stream_transformer.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/heap/visitor.h"
-
-namespace blink {
-
-// Base class for FlushAlgorithm and TransformAlgorithm. Contains common
-// construction code and members.
-class TransformStreamWrapper::Algorithm : public ScriptFunction {
- public:
- // This is templated just to avoid having two identical copies of the
- // function.
- template <typename T>
- static v8::Local<v8::Function> Create(TransformStreamTransformer* transformer,
- ScriptState* script_state,
- ExceptionState& exception_state) {
- auto* algorithm =
- MakeGarbageCollected<T>(transformer, script_state, exception_state);
- return algorithm->BindToV8Function();
- }
-
- Algorithm(TransformStreamTransformer* transformer,
- ScriptState* script_state,
- ExceptionState& exception_state)
- : ScriptFunction(script_state),
- transformer_(transformer),
- interface_name_(exception_state.InterfaceName()),
- property_name_(exception_state.PropertyName()) {}
-
- void Trace(Visitor* visitor) override {
- visitor->Trace(transformer_);
- ScriptFunction::Trace(visitor);
- }
-
- protected:
- // AlgorithmScope holds the stack-allocated objects used by the CallRaw()
- // methods for FlushAlgorithm and TransformAlgorithm.
- class AlgorithmScope {
- STACK_ALLOCATED();
-
- public:
- AlgorithmScope(Algorithm* owner,
- const v8::FunctionCallbackInfo<v8::Value>& info,
- v8::Local<v8::Value> controller)
- : controller_(owner->GetScriptState(), controller),
- exception_state_(owner->GetScriptState()->GetIsolate(),
- // Using the original context would result in every
- // exception claiming to have happened during
- // construction. Since that is not helpful, don't
- // annotate exceptions with where we think they came
- // from.
- ExceptionState::kUnknownContext,
- owner->interface_name_,
- owner->property_name_),
- reject_promise_scope_(info, exception_state_) {}
-
- TransformStreamDefaultControllerInterface* GetController() {
- return &controller_;
- }
-
- ExceptionState* GetExceptionState() { return &exception_state_; }
-
- private:
- TransformStreamDefaultControllerWrapper controller_;
- ExceptionState exception_state_;
- ExceptionToRejectPromiseScope reject_promise_scope_;
- };
-
- Member<TransformStreamTransformer> transformer_;
- const char* const interface_name_;
- const char* const property_name_;
-};
-
-class TransformStreamWrapper::FlushAlgorithm
- : public TransformStreamWrapper::Algorithm {
- protected:
- using Algorithm::Algorithm;
-
- private:
- void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
- DCHECK_EQ(info.Length(), 1);
- AlgorithmScope algorithm_scope(this, info, info[0]);
- ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
-
- transformer_->Flush(algorithm_scope.GetController(), exception_state);
- if (exception_state.HadException())
- return;
- V8SetReturnValue(info,
- ScriptPromise::CastUndefined(GetScriptState()).V8Value());
- }
-};
-
-class TransformStreamWrapper::TransformAlgorithm
- : public TransformStreamWrapper::Algorithm {
- protected:
- using Algorithm::Algorithm;
-
- private:
- void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& info) override {
- DCHECK_EQ(info.Length(), 2);
- AlgorithmScope algorithm_scope(this, info, info[1]);
- ExceptionState& exception_state = *algorithm_scope.GetExceptionState();
-
- transformer_->Transform(info[0], algorithm_scope.GetController(),
- exception_state);
- if (exception_state.HadException())
- return;
- V8SetReturnValue(info,
- ScriptPromise::CastUndefined(GetScriptState()).V8Value());
- }
-};
-
-// static
-void TransformStreamWrapper::InitFromJS(ScriptState* script_state,
- ScriptValue transformer,
- ScriptValue writable_strategy,
- ScriptValue readable_strategy,
- Member<ReadableStream>* readable,
- Member<WritableStream>* writable,
- ExceptionState& exception_state) {
- DCHECK(!RuntimeEnabledFeatures::StreamsNativeEnabled());
-
- v8::Local<v8::Value> args[] = {transformer.V8Value(),
- writable_strategy.V8Value(),
- readable_strategy.V8Value()};
- v8::Local<v8::Value> stream;
- {
- v8::TryCatch block(script_state->GetIsolate());
- if (!V8ScriptRunner::CallExtra(script_state, "createTransformStream", args)
- .ToLocal(&stream)) {
- DCHECK(block.HasCaught());
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- }
- DCHECK(stream->IsObject());
- InitInternal(script_state, stream.As<v8::Object>(), readable, writable,
- exception_state);
-}
-
-// static
-void TransformStreamWrapper::Init(ScriptState* script_state,
- TransformStreamTransformer* transformer,
- Member<ReadableStream>* readable,
- Member<WritableStream>* writable,
- ExceptionState& exception_state) {
- auto transform_algorithm = Algorithm::Create<TransformAlgorithm>(
- transformer, script_state, exception_state);
- auto flush_algorithm = Algorithm::Create<FlushAlgorithm>(
- transformer, script_state, exception_state);
- v8::Local<v8::Value> args[] = {transform_algorithm, flush_algorithm};
- v8::Local<v8::Value> stream;
- {
- v8::TryCatch block(script_state->GetIsolate());
- if (!V8ScriptRunner::CallExtra(script_state, "createTransformStreamSimple",
- args)
- .ToLocal(&stream)) {
- DCHECK(block.HasCaught());
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- }
- DCHECK(stream->IsObject());
- InitInternal(script_state, stream.As<v8::Object>(), readable, writable,
- exception_state);
-}
-
-// static
-void TransformStreamWrapper::InitInternal(ScriptState* script_state,
- v8::Local<v8::Object> stream,
- Member<ReadableStream>* readable_out,
- Member<WritableStream>* writable_out,
- ExceptionState& exception_state) {
- v8::Local<v8::Value> readable, writable;
- v8::Local<v8::Value> args[] = {stream};
- v8::TryCatch block(script_state->GetIsolate());
- if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamReadable",
- args)
- .ToLocal(&readable)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
- if (!V8ScriptRunner::CallExtra(script_state, "getTransformStreamWritable",
- args)
- .ToLocal(&writable)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- DCHECK(readable->IsObject());
- *readable_out = ReadableStreamWrapper::CreateFromInternalStream(
- script_state, readable.As<v8::Object>(), exception_state);
-
- if (!*readable_out)
- return;
-
- DCHECK(writable->IsObject());
- *writable_out = WritableStreamWrapper::CreateFromInternalStream(
- script_state, writable.As<v8::Object>(), exception_state);
-
- return;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h b/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
deleted file mode 100644
index f0668dffaad..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/transform_stream_wrapper.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-class ExceptionState;
-class ReadableStream;
-class ScriptState;
-class TransformStreamTransformer;
-class WritableStream;
-
-// Helpers to create a TransformStream using V8 Extras. This is not a subclass
-// of TransformStream, because it is only needed during creation of the object.
-class TransformStreamWrapper {
- STATIC_ONLY(TransformStreamWrapper);
-
- public:
- // Creates a (readable, writable) pair from JS objects.
- static void InitFromJS(ScriptState*,
- ScriptValue transformer,
- ScriptValue writable_strategy,
- ScriptValue readable_strategy,
- Member<ReadableStream>*,
- Member<WritableStream>*,
- ExceptionState&);
-
- // Creates a (readable, writable) pair from a C++ object.
- static void Init(ScriptState*,
- TransformStreamTransformer*,
- Member<ReadableStream>*,
- Member<WritableStream>*,
- ExceptionState&);
-
- private:
- class Algorithm;
- class FlushAlgorithm;
- class TransformAlgorithm;
-
- // Creates a (readable, writable) pair from an internal V8 Extras
- // TransformStream object.
- static void InitInternal(ScriptState*,
- v8::Local<v8::Object> stream,
- Member<ReadableStream>*,
- Member<WritableStream>*,
- ExceptionState&);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_TRANSFORM_STREAM_WRAPPER_H_
diff --git a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
index f8a7f42b210..7afa0b62b5b 100644
--- a/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
+++ b/chromium/third_party/blink/renderer/core/streams/underlying_source_base.cc
@@ -45,7 +45,8 @@ ScriptPromise UnderlyingSourceBase::Cancel(ScriptState* script_state,
}
ScriptValue UnderlyingSourceBase::type(ScriptState* script_state) const {
- return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+ return ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate()));
}
void UnderlyingSourceBase::ContextDestroyed(ExecutionContext*) {
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 f0817bf8400..930dbcf62db 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -4,65 +4,46 @@
#include "third_party/blink/renderer/core/streams/writable_stream.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/streams/writable_stream_native.h"
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
WritableStream* WritableStream::Create(ScriptState* script_state,
ExceptionState& exception_state) {
- return Create(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return Create(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
WritableStream* WritableStream::Create(ScriptState* script_state,
ScriptValue underlying_sink,
ExceptionState& exception_state) {
- return Create(
- script_state, underlying_sink,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return Create(script_state, underlying_sink,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
WritableStream* WritableStream::Create(ScriptState* script_state,
ScriptValue underlying_sink,
ScriptValue strategy,
ExceptionState& exception_state) {
- WritableStream* stream = nullptr;
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- stream = MakeGarbageCollected<WritableStreamNative>(
- script_state, underlying_sink, strategy, exception_state);
- } else {
- auto* stream_wrapper = MakeGarbageCollected<WritableStreamWrapper>();
- stream = stream_wrapper;
- stream_wrapper->Init(script_state, underlying_sink, strategy,
- exception_state);
- }
- if (exception_state.HadException())
- return nullptr;
-
- return stream;
+ return WritableStreamNative::Create(script_state, underlying_sink, strategy,
+ exception_state);
}
WritableStream* WritableStream::CreateWithCountQueueingStrategy(
ScriptState* script_state,
UnderlyingSinkBase* underlying_sink,
size_t high_water_mark) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return WritableStreamNative::CreateWithCountQueueingStrategy(
- script_state, underlying_sink, high_water_mark);
- }
-
- return WritableStreamWrapper::CreateWithCountQueueingStrategy(
+ return WritableStreamNative::CreateWithCountQueueingStrategy(
script_state, underlying_sink, high_water_mark);
}
@@ -70,12 +51,7 @@ WritableStream* WritableStream::CreateWithCountQueueingStrategy(
WritableStream* WritableStream::Deserialize(ScriptState* script_state,
MessagePort* port,
ExceptionState& exception_state) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return WritableStreamNative::Deserialize(script_state, port,
- exception_state);
- }
- return WritableStreamWrapper::Deserialize(script_state, port,
- exception_state);
+ return WritableStreamNative::Deserialize(script_state, port, exception_state);
}
} // namespace blink
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 cbc4f61654b..047b661982f 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.h
@@ -5,16 +5,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_H_
+#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "v8/include/v8.h"
namespace blink {
+class ExceptionState;
class MessagePort;
+class ScriptState;
class UnderlyingSinkBase;
// This is an implementation of the corresponding IDL interface.
@@ -32,6 +32,10 @@ class CORE_EXPORT WritableStream : public ScriptWrappable {
ScriptValue underlying_sink,
ScriptValue strategy,
ExceptionState&);
+
+ // Creates a WritableStream from C++. If |high_water_mark| is set to 0 then
+ // piping to this writable stream will not work, because there will always be
+ // backpressure. Usually 1 is the right choice.
static WritableStream* CreateWithCountQueueingStrategy(
ScriptState*,
UnderlyingSinkBase*,
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream.idl b/chromium/third_party/blink/renderer/core/streams/writable_stream.idl
index 798ebcb228a..a1d17bb7350 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream.idl
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream.idl
@@ -5,8 +5,7 @@
// https://streams.spec.whatwg.org/#ws-class
[
Exposed=(Window,Worker,Worklet),
- // TODO(yhirano): Remove CustomConstructor. See https://crbug.com/906476.
- CustomConstructor(optional any underlyingSink, optional any strategy),
+ Constructor(optional any underlyingSink, optional any strategy),
MeasureAs=WritableStreamConstructor,
RaisesException=Constructor,
ConstructorCallWith=ScriptState
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
index 08652a65c0a..da6e722d56b 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
@@ -25,8 +25,8 @@ WritableStreamDefaultController::WritableStreamDefaultController()
: queue_(MakeGarbageCollected<QueueWithSizes>()) {}
void WritableStreamDefaultController::error(ScriptState* script_state) {
- error(script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ error(script_state, ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())));
}
void WritableStreamDefaultController::error(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
index 887c41e2080..583bb6fd1ce 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
@@ -87,7 +87,7 @@ class WritableStreamDefaultController final : public ScriptWrappable {
double chunk_size);
// https://streams.spec.whatwg.org/#writable-stream-default-controller-error
- // TODO(yhirano): Make this private once we ship StreamsNative.
+ // TODO(ricea): Make this private.
static void Error(ScriptState*,
WritableStreamDefaultController*,
v8::Local<v8::Value> error);
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.cc
index 3c08c0267cc..641a4cd2b1b 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.cc
@@ -6,47 +6,18 @@
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream_default_controller.h"
#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
namespace {
-class WritableStreamDefaultControllerWrapper final
- : public WritableStreamDefaultControllerInterface {
- public:
- explicit WritableStreamDefaultControllerWrapper(ScriptValue controller)
- : controller_(controller.GetIsolate(), controller.V8Value()) {}
-
- void Error(ScriptState* script_state,
- v8::Local<v8::Value> js_error) override {
- v8::Isolate* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Value> controller = controller_.NewLocal(isolate);
- v8::Local<v8::Value> args[] = {controller, js_error};
- v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallExtra(
- script_state, "WritableStreamDefaultControllerError", args);
- result.ToLocalChecked();
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(controller_);
- WritableStreamDefaultControllerInterface::Trace(visitor);
- }
-
- private:
- TraceWrapperV8Reference<v8::Value> controller_;
-};
-
class WritableStreamDefaultControllerNative final
: public WritableStreamDefaultControllerInterface {
public:
explicit WritableStreamDefaultControllerNative(ScriptValue controller) {
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
DCHECK(controller.IsObject());
controller_ = V8WritableStreamDefaultController::ToImpl(
controller.V8Value().As<v8::Object>());
@@ -75,12 +46,7 @@ WritableStreamDefaultControllerInterface::
WritableStreamDefaultControllerInterface*
WritableStreamDefaultControllerInterface::Create(ScriptValue controller) {
- if (RuntimeEnabledFeatures::StreamsNativeEnabled()) {
- return MakeGarbageCollected<WritableStreamDefaultControllerNative>(
- controller);
- }
-
- return MakeGarbageCollected<WritableStreamDefaultControllerWrapper>(
+ return MakeGarbageCollected<WritableStreamDefaultControllerNative>(
controller);
}
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h
index f403214811d..ae0563a4f9a 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_controller_interface.h
@@ -16,8 +16,7 @@ namespace blink {
class Visitor;
class CORE_EXPORT WritableStreamDefaultControllerInterface
- : public GarbageCollectedFinalized<
- WritableStreamDefaultControllerInterface> {
+ : public GarbageCollected<WritableStreamDefaultControllerInterface> {
public:
WritableStreamDefaultControllerInterface();
virtual ~WritableStreamDefaultControllerInterface();
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 0d78ec2429f..6b3580919a5 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
@@ -66,7 +66,6 @@ WritableStreamDefaultWriter* WritableStreamDefaultWriter::Create(
ScriptState* script_state,
WritableStream* stream,
ExceptionState& exception_state) {
- DCHECK(RuntimeEnabledFeatures::StreamsNativeEnabled());
auto* writer = MakeGarbageCollected<WritableStreamDefaultWriter>(
script_state, static_cast<WritableStreamNative*>(stream),
exception_state);
@@ -200,7 +199,7 @@ ScriptValue WritableStreamDefaultWriter::desiredSize(
}
// 3. Return ! WritableStreamDefaultWriterGetDesiredSize(this).
- return ScriptValue(script_state, GetDesiredSize(isolate, this));
+ return ScriptValue(isolate, GetDesiredSize(isolate, this));
}
ScriptPromise WritableStreamDefaultWriter::ready(
@@ -211,9 +210,9 @@ ScriptPromise WritableStreamDefaultWriter::ready(
}
ScriptPromise WritableStreamDefaultWriter::abort(ScriptState* script_state) {
- return abort(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ return abort(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())));
}
ScriptPromise WritableStreamDefaultWriter::abort(ScriptState* script_state,
@@ -277,9 +276,9 @@ void WritableStreamDefaultWriter::releaseLock(ScriptState* script_state) {
}
ScriptPromise WritableStreamDefaultWriter::write(ScriptState* script_state) {
- return write(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())));
+ return write(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())));
}
ScriptPromise WritableStreamDefaultWriter::write(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
index 0bed52d63e6..68cf0dd6a55 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_default_writer.idl
@@ -7,7 +7,6 @@
// https://streams.spec.whatwg.org/#default-writer-class-definition
[
Exposed=(Window,Worker,Worklet),
- RuntimeEnabled=StreamsNative,
RaisesException=Constructor,
ConstructorCallWith=ScriptState,
Constructor(WritableStream stream)
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
index 913ddadae5a..e75d0da754c 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.cc
@@ -34,7 +34,7 @@ namespace blink {
// The PendingAbortRequest type corresponds to the Record {[[promise]],
// [[reason]], [[wasAlreadyErroring]]} from the standard.
class WritableStreamNative::PendingAbortRequest final
- : public GarbageCollectedFinalized<PendingAbortRequest> {
+ : public GarbageCollected<PendingAbortRequest> {
public:
PendingAbortRequest(v8::Isolate* isolate,
StreamPromiseResolver* promise,
@@ -64,74 +64,21 @@ class WritableStreamNative::PendingAbortRequest final
DISALLOW_COPY_AND_ASSIGN(PendingAbortRequest);
};
-WritableStreamNative::WritableStreamNative() = default;
-
-WritableStreamNative::WritableStreamNative(ScriptState* script_state,
- ScriptValue raw_underlying_sink,
- ScriptValue raw_strategy,
- ExceptionState& exception_state) {
- // The first parts of this constructor correspond to the object conversions
- // that are implicit in the definition in the standard:
- // https://streams.spec.whatwg.org/#ws-constructor
- DCHECK(!raw_underlying_sink.IsEmpty());
- DCHECK(!raw_strategy.IsEmpty());
-
- auto context = script_state->GetContext();
- auto* isolate = script_state->GetIsolate();
-
- v8::Local<v8::Object> underlying_sink;
- ScriptValueToObject(script_state, raw_underlying_sink, &underlying_sink,
- exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 2. Let size be ? GetV(strategy, "size").
- // 3. Let highWaterMark be ? GetV(strategy, "highWaterMark").
- StrategyUnpacker strategy_unpacker(script_state, raw_strategy,
- exception_state);
- if (exception_state.HadException()) {
- return;
- }
-
- // 4. Let type be ? GetV(underlyingSink, "type").
- v8::TryCatch try_catch(isolate);
- v8::Local<v8::Value> type;
- if (!underlying_sink->Get(context, V8AtomicString(isolate, "type"))
- .ToLocal(&type)) {
- exception_state.RethrowV8Exception(try_catch.Exception());
- return;
- }
-
- // 5. If type is not undefined, throw a RangeError exception.
- if (!type->IsUndefined()) {
- exception_state.ThrowRangeError("Invalid type is specified");
- return;
- }
-
- // 6. Let sizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(size).
- auto* size_algorithm =
- strategy_unpacker.MakeSizeAlgorithm(script_state, exception_state);
- if (exception_state.HadException()) {
- return;
- }
- DCHECK(size_algorithm);
-
- // 7. If highWaterMark is undefined, let highWaterMark be 1.
- // 8. Set highWaterMark to ? ValidateAndNormalizeHighWaterMark(highWaterMark).
- double high_water_mark =
- strategy_unpacker.GetHighWaterMark(script_state, 1, exception_state);
+WritableStreamNative* WritableStreamNative::Create(
+ ScriptState* script_state,
+ ScriptValue raw_underlying_sink,
+ ScriptValue raw_strategy,
+ ExceptionState& exception_state) {
+ auto* stream = MakeGarbageCollected<WritableStreamNative>();
+ stream->InitInternal(script_state, raw_underlying_sink, raw_strategy,
+ exception_state);
if (exception_state.HadException()) {
- return;
+ return nullptr;
}
-
- // 9. Perform ? SetUpWritableStreamDefaultControllerFromUnderlyingSink(this,
- // underlyingSink, highWaterMark, sizeAlgorithm).
- WritableStreamDefaultController::SetUpFromUnderlyingSink(
- script_state, this, underlying_sink, high_water_mark, size_algorithm,
- exception_state);
+ return stream;
}
+WritableStreamNative::WritableStreamNative() = default;
WritableStreamNative::~WritableStreamNative() = default;
bool WritableStreamNative::locked(ScriptState* script_state,
@@ -143,10 +90,10 @@ bool WritableStreamNative::locked(ScriptState* script_state,
ScriptPromise WritableStreamNative::abort(ScriptState* script_state,
ExceptionState& exception_state) {
- return abort(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return abort(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ScriptPromise WritableStreamNative::abort(ScriptState* script_state,
@@ -179,7 +126,7 @@ ScriptValue WritableStreamNative::getWriter(ScriptState* script_state,
// This call to ToV8() is only reached directly from JavaScript, and so
// shouldn't be called while the execution context is being shutdown and so
// shouldn't fail.
- return ScriptValue(script_state, ToV8(writer, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(writer, script_state));
}
// General Writable Stream Abstract Operations
@@ -241,8 +188,9 @@ WritableStreamNative* WritableStreamNative::CreateWithCountQueueingStrategy(
ExceptionState exception_state(script_state->GetIsolate(),
ExceptionState::kConstructionContext,
"WritableStream");
- auto* stream = MakeGarbageCollected<WritableStreamNative>(
- script_state, underlying_sink_value, strategy_value, exception_state);
+ auto* stream = MakeGarbageCollected<WritableStreamNative>();
+ stream->InitInternal(script_state, underlying_sink_value, strategy_value,
+ exception_state);
if (exception_state.HadException())
return nullptr;
return stream;
@@ -789,6 +737,74 @@ void WritableStreamNative::Trace(Visitor* visitor) {
WritableStream::Trace(visitor);
}
+// This is not implemented inside the constructor in C++, because calling into
+// JavaScript from the constructor can cause GC problems.
+void WritableStreamNative::InitInternal(ScriptState* script_state,
+ ScriptValue raw_underlying_sink,
+ ScriptValue raw_strategy,
+ ExceptionState& exception_state) {
+ // The first parts of this constructor implementation correspond to the object
+ // conversions that are implicit in the definition in the standard:
+ // https://streams.spec.whatwg.org/#ws-constructor
+ DCHECK(!raw_underlying_sink.IsEmpty());
+ DCHECK(!raw_strategy.IsEmpty());
+
+ auto context = script_state->GetContext();
+ auto* isolate = script_state->GetIsolate();
+
+ v8::Local<v8::Object> underlying_sink;
+ ScriptValueToObject(script_state, raw_underlying_sink, &underlying_sink,
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 2. Let size be ? GetV(strategy, "size").
+ // 3. Let highWaterMark be ? GetV(strategy, "highWaterMark").
+ StrategyUnpacker strategy_unpacker(script_state, raw_strategy,
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 4. Let type be ? GetV(underlyingSink, "type").
+ v8::TryCatch try_catch(isolate);
+ v8::Local<v8::Value> type;
+ if (!underlying_sink->Get(context, V8AtomicString(isolate, "type"))
+ .ToLocal(&type)) {
+ exception_state.RethrowV8Exception(try_catch.Exception());
+ return;
+ }
+
+ // 5. If type is not undefined, throw a RangeError exception.
+ if (!type->IsUndefined()) {
+ exception_state.ThrowRangeError("Invalid type is specified");
+ return;
+ }
+
+ // 6. Let sizeAlgorithm be ? MakeSizeAlgorithmFromSizeFunction(size).
+ auto* size_algorithm =
+ strategy_unpacker.MakeSizeAlgorithm(script_state, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+ DCHECK(size_algorithm);
+
+ // 7. If highWaterMark is undefined, let highWaterMark be 1.
+ // 8. Set highWaterMark to ? ValidateAndNormalizeHighWaterMark(highWaterMark).
+ double high_water_mark =
+ strategy_unpacker.GetHighWaterMark(script_state, 1, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+
+ // 9. Perform ? SetUpWritableStreamDefaultControllerFromUnderlyingSink(this,
+ // underlyingSink, highWaterMark, sizeAlgorithm).
+ WritableStreamDefaultController::SetUpFromUnderlyingSink(
+ script_state, this, underlying_sink, high_water_mark, size_algorithm,
+ exception_state);
+}
+
bool WritableStreamNative::HasOperationMarkedInFlight(
const WritableStreamNative* stream) {
// https://streams.spec.whatwg.org/#writable-stream-has-operation-marked-in-flight
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
index e37cac9a68c..164da7afd5f 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_native.h
@@ -33,6 +33,12 @@ class CORE_EXPORT WritableStreamNative : public WritableStream {
kErrored,
};
+ // https://streams.spec.whatwg.org/#ws-constructor
+ static WritableStreamNative* Create(ScriptState*,
+ ScriptValue raw_underlying_sink,
+ ScriptValue raw_strategy,
+ ExceptionState&);
+
// https://streams.spec.whatwg.org/#create-writable-stream
// Unlike in the standard, |high_water_mark| and |size_algorithm| are
// required parameters.
@@ -50,15 +56,8 @@ class CORE_EXPORT WritableStreamNative : public WritableStream {
UnderlyingSinkBase*,
size_t high_water_mark);
- // Used by Create().
+ // Called by Create().
WritableStreamNative();
-
- // Used when creating a stream from JavaScript.
- // https://streams.spec.whatwg.org/#ws-constructor
- WritableStreamNative(ScriptState*,
- ScriptValue raw_underlying_sink,
- ScriptValue raw_strategy,
- ExceptionState&);
~WritableStreamNative() override;
// IDL defined functions
@@ -201,6 +200,13 @@ class CORE_EXPORT WritableStreamNative : public WritableStream {
class PendingAbortRequest;
+ // Used when creating a stream from JavaScript. Called from Create().
+ // https://streams.spec.whatwg.org/#ws-constructor
+ void InitInternal(ScriptState*,
+ ScriptValue raw_underlying_sink,
+ ScriptValue raw_strategy,
+ ExceptionState&);
+
// https://streams.spec.whatwg.org/#writable-stream-has-operation-marked-in-flight
static bool HasOperationMarkedInFlight(const WritableStreamNative*);
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
index e87946d1063..ff643d0511b 100644
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -21,16 +21,7 @@ namespace blink {
namespace {
-// Web platform tests test WritableStream more thoroughly from scripts.
-class WritableStreamTest : public testing::TestWithParam<bool> {
- public:
- WritableStreamTest() : feature_(GetParam()) {}
-
- private:
- ScopedStreamsNativeForTest feature_;
-};
-
-TEST_P(WritableStreamTest, CreateWithoutArguments) {
+TEST(WritableStreamTest, CreateWithoutArguments) {
V8TestingScope scope;
WritableStream* stream =
@@ -40,7 +31,7 @@ TEST_P(WritableStreamTest, CreateWithoutArguments) {
}
// Testing getWriter, locked and IsLocked.
-TEST_P(WritableStreamTest, GetWriter) {
+TEST(WritableStreamTest, GetWriter) {
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
@@ -52,14 +43,14 @@ TEST_P(WritableStreamTest, GetWriter) {
EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION),
base::make_optional(false));
- ScriptValue writer = stream->getWriter(script_state, ASSERT_NO_EXCEPTION);
+ stream->getWriter(script_state, ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream->locked(script_state, ASSERT_NO_EXCEPTION));
EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION),
base::make_optional(true));
}
-TEST_P(WritableStreamTest, Serialize) {
+TEST(WritableStreamTest, Serialize) {
ScopedTransferableStreamsForTest enable_transferable_streams(true);
V8TestingScope scope;
@@ -111,8 +102,6 @@ underlying_sink)JS";
EXPECT_EQ(ToCoreString(result.As<v8::String>()), "a");
}
-INSTANTIATE_TEST_SUITE_P(, WritableStreamTest, ::testing::Values(false, true));
-
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
deleted file mode 100644
index 6e6ffcd7ab3..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/streams/writable_stream_wrapper.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_writable_stream.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-void WritableStreamWrapper::Init(ScriptState* script_state,
- ScriptValue underlying_sink,
- ScriptValue strategy,
- ExceptionState& exception_state) {
- v8::Local<v8::Object> internal_stream;
- v8::TryCatch block(script_state->GetIsolate());
-
- if (!CreateInternalStream(script_state, underlying_sink.V8Value(),
- strategy.V8Value())
- .ToLocal(&internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-
- if (!InitInternal(script_state, internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return;
- }
-}
-
-WritableStreamWrapper* WritableStreamWrapper::CreateFromInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Object> internal_stream,
- ExceptionState& exception_state) {
- v8::TryCatch block(script_state->GetIsolate());
- auto* stream = MakeGarbageCollected<WritableStreamWrapper>();
- if (!stream->InitInternal(script_state, internal_stream)) {
- exception_state.RethrowV8Exception(block.Exception());
- return nullptr;
- }
- return stream;
-}
-
-WritableStreamWrapper* WritableStreamWrapper::CreateWithCountQueueingStrategy(
- ScriptState* script_state,
- UnderlyingSinkBase* underlying_sink,
- size_t high_water_mark) {
- ScriptValue strategy = ReadableStreamOperations::CreateCountQueuingStrategy(
- script_state, high_water_mark);
- if (strategy.IsEmpty())
- return nullptr;
-
- auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink);
- auto* stream = MakeGarbageCollected<WritableStreamWrapper>();
-
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kConstructionContext,
- "WritableStream");
- stream->Init(script_state, underlying_sink_value, strategy, exception_state);
- if (exception_state.HadException())
- return nullptr;
- return stream;
-}
-
-bool WritableStreamWrapper::InitInternal(
- ScriptState* script_state,
- v8::Local<v8::Object> internal_stream) {
- v8::Isolate* isolate = script_state->GetIsolate();
-
-#if DCHECK_IS_ON()
- v8::Local<v8::Value> args[] = {internal_stream};
- v8::Local<v8::Value> result_value;
-
- if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStream", args)
- .ToLocal(&result_value)) {
- DLOG(FATAL) << "Failing to call IsWritableStream for DCHECK.";
- return false;
- }
- DCHECK(result_value->BooleanValue(isolate));
-#endif // DCHECK_IS_ON()
-
- internal_stream_.Set(isolate, internal_stream);
-
- v8::Local<v8::Value> wrapper = ToV8(this, script_state);
- if (wrapper.IsEmpty())
- return false;
-
- v8::Local<v8::Context> context = script_state->GetContext();
- v8::Local<v8::Object> bindings =
- context->GetExtrasBindingObject().As<v8::Object>();
- v8::Local<v8::Value> symbol_value;
- if (!bindings->Get(context, V8String(isolate, "internalWritableStreamSymbol"))
- .ToLocal(&symbol_value)) {
- return false;
- }
-
- if (wrapper.As<v8::Object>()
- ->Set(context, symbol_value.As<v8::Symbol>(),
- internal_stream_.NewLocal(isolate))
- .IsNothing()) {
- return false;
- }
-
- return true;
-}
-
-v8::MaybeLocal<v8::Object> WritableStreamWrapper::CreateInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Value> underlying_sink,
- v8::Local<v8::Value> strategy) {
- v8::Local<v8::Value> args[] = {underlying_sink, strategy};
- v8::Local<v8::Value> stream;
-
- if (!V8ScriptRunner::CallExtra(script_state, "createWritableStream", args)
- .ToLocal(&stream)) {
- return v8::MaybeLocal<v8::Object>();
- }
-
- DCHECK(stream->IsObject());
- return v8::MaybeLocal<v8::Object>(stream.As<v8::Object>());
-}
-
-void WritableStreamWrapper::Trace(Visitor* visitor) {
- visitor->Trace(internal_stream_);
- ScriptWrappable::Trace(visitor);
-}
-
-bool WritableStreamWrapper::locked(ScriptState* script_state,
- ExceptionState& exception_state) const {
- auto result = IsLocked(script_state, exception_state);
-
- return !result || *result;
-}
-
-ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
- ExceptionState& exception_state) {
- return abort(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
-}
-
-ScriptPromise WritableStreamWrapper::abort(ScriptState* script_state,
- ScriptValue reason,
- ExceptionState& exception_state) {
- if (locked(script_state, exception_state) &&
- !exception_state.HadException()) {
- exception_state.ThrowTypeError("Cannot abort a locked stream");
- return ScriptPromise();
- }
-
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate()), reason.V8Value()};
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state, "WritableStreamAbort", args)
- .ToLocal(&result)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptPromise();
- }
- return ScriptPromise(script_state, result);
-}
-
-ScriptValue WritableStreamWrapper::getWriter(ScriptState* script_state,
- ExceptionState& exception_state) {
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate())};
- v8::Local<v8::Value> result;
-
- if (!V8ScriptRunner::CallExtra(script_state,
- "AcquireWritableStreamDefaultWriter", args)
- .ToLocal(&result)) {
- exception_state.RethrowV8Exception(block.Exception());
- return ScriptValue();
- }
- return ScriptValue(script_state, result);
-}
-
-base::Optional<bool> WritableStreamWrapper::IsLocked(
- ScriptState* script_state,
- ExceptionState& exception_state) const {
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> args[] = {
- internal_stream_.NewLocal(script_state->GetIsolate())};
- v8::Local<v8::Value> result_value;
-
- if (!V8ScriptRunner::CallExtra(script_state, "IsWritableStreamLocked", args)
- .ToLocal(&result_value)) {
- exception_state.RethrowV8Exception(block.Exception());
- return base::nullopt;
- }
- return result_value->BooleanValue(script_state->GetIsolate());
-}
-
-void WritableStreamWrapper::Serialize(ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- DCHECK(port);
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- v8::TryCatch block(script_state->GetIsolate());
- v8::Local<v8::Value> port_v8_value = ToV8(port, script_state);
- DCHECK(!port_v8_value.IsEmpty());
- v8::Local<v8::Value> args[] = {GetInternalStream(script_state).V8Value(),
- port_v8_value};
- V8ScriptRunner::CallExtra(script_state, "WritableStreamSerialize", args);
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- }
-}
-
-// static
-WritableStreamWrapper* WritableStreamWrapper::Deserialize(
- ScriptState* script_state,
- MessagePort* port,
- ExceptionState& exception_state) {
- // We need to execute V8 Extras JavaScript to create the new WritableStream.
- // We will not run author code.
- auto* isolate = script_state->GetIsolate();
- v8::Isolate::AllowJavascriptExecutionScope allow_js(isolate);
- DCHECK(port);
- DCHECK(RuntimeEnabledFeatures::TransferableStreamsEnabled());
- v8::TryCatch block(isolate);
- v8::Local<v8::Value> port_v8 = ToV8(port, script_state);
- DCHECK(!port_v8.IsEmpty());
- v8::Local<v8::Value> args[] = {port_v8};
- ScriptValue internal_stream(
- script_state, V8ScriptRunner::CallExtra(
- script_state, "WritableStreamDeserialize", args));
- if (block.HasCaught()) {
- exception_state.RethrowV8Exception(block.Exception());
- return nullptr;
- }
- DCHECK(!internal_stream.IsEmpty());
- return CreateFromInternalStream(script_state, internal_stream,
- exception_state);
-}
-
-ScriptValue WritableStreamWrapper::GetInternalStream(
- ScriptState* script_state) const {
- return ScriptValue(script_state,
- internal_stream_.NewLocal(script_state->GetIsolate()));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h b/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
deleted file mode 100644
index 658c6d10225..00000000000
--- a/chromium/third_party/blink/renderer/core/streams/writable_stream_wrapper.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_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/streams/writable_stream.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-class MessagePort;
-class WritableStreamWrapper;
-
-// This is an implementation of the WritableStream interface that delegates to
-// the V8 Extras implementation.
-class CORE_EXPORT WritableStreamWrapper final : public WritableStream {
- public:
- // Call one of Init functions before using the instance.
- WritableStreamWrapper() = default;
- ~WritableStreamWrapper() override = default;
-
- // If an error happens, |exception_state.HadException()| will be true, and
- // |this| will not be usable after that.
- void Init(ScriptState*,
- ScriptValue underlying_sink,
- ScriptValue strategy,
- ExceptionState& exception_state);
-
- static WritableStreamWrapper* CreateFromInternalStream(
- ScriptState* script_state,
- ScriptValue internal_stream,
- ExceptionState& exception_state) {
- DCHECK(internal_stream.IsObject());
- return CreateFromInternalStream(script_state,
- internal_stream.V8Value().As<v8::Object>(),
- exception_state);
- }
- static WritableStreamWrapper* CreateFromInternalStream(
- ScriptState*,
- v8::Local<v8::Object> internal_stream,
- ExceptionState&);
-
- static WritableStreamWrapper* CreateWithCountQueueingStrategy(
- ScriptState*,
- UnderlyingSinkBase*,
- size_t high_water_mark);
-
- void Trace(Visitor* visitor) override;
-
- // IDL defined functions
- bool locked(ScriptState*, ExceptionState&) const override;
- ScriptPromise abort(ScriptState*, ExceptionState&) override;
- ScriptPromise abort(ScriptState*,
- ScriptValue reason,
- ExceptionState&) override;
- ScriptValue getWriter(ScriptState*, ExceptionState&) override;
-
- base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const override;
-
- // Serialize this stream to |port|. The stream will be locked by this
- // operation.
- void Serialize(ScriptState*, MessagePort* port, ExceptionState&) override;
-
- // Given a |port| which is entangled with a MessagePort that was previously
- // passed to Serialize(), returns a new WritableStreamWrapper which behaves
- // like it was the original.
- static WritableStreamWrapper* Deserialize(ScriptState*,
- MessagePort* port,
- ExceptionState&);
-
- ScriptValue GetInternalStream(ScriptState*) const;
-
- private:
- bool InitInternal(ScriptState*, v8::Local<v8::Object> internal_stream);
-
- static v8::MaybeLocal<v8::Object> CreateInternalStream(
- ScriptState* script_state,
- v8::Local<v8::Value> underlying_sink,
- v8::Local<v8::Value> strategy);
-
- TraceWrapperV8Reference<v8::Object> internal_stream_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_WRITABLE_STREAM_WRAPPER_H_
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style.cc b/chromium/third_party/blink/renderer/core/style/computed_style.cc
index db2d1c0d11f..b2d7aebe43d 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.cc
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.cc
@@ -54,6 +54,7 @@
#include "third_party/blink/renderer/core/style/shadow_list.h"
#include "third_party/blink/renderer/core/style/style_difference.h"
#include "third_party/blink/renderer/core/style/style_fetched_image.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
#include "third_party/blink/renderer/core/style/style_image.h"
#include "third_party/blink/renderer/core/style/style_inherited_variables.h"
#include "third_party/blink/renderer/core/style/style_non_inherited_variables.h"
@@ -173,23 +174,23 @@ ALWAYS_INLINE ComputedStyle::ComputedStyle(const ComputedStyle& o)
RefCounted<ComputedStyle>(),
svg_style_(o.svg_style_) {}
-static bool PseudoStylesEqual(const ComputedStyle& old_style,
- const ComputedStyle& new_style) {
- if (!old_style.HasAnyPublicPseudoStyles() &&
- !new_style.HasAnyPublicPseudoStyles())
+static bool PseudoElementStylesEqual(const ComputedStyle& old_style,
+ const ComputedStyle& new_style) {
+ if (!old_style.HasAnyPseudoElementStyles() &&
+ !new_style.HasAnyPseudoElementStyles())
return true;
for (PseudoId pseudo_id = kFirstPublicPseudoId;
pseudo_id < kFirstInternalPseudoId;
pseudo_id = static_cast<PseudoId>(pseudo_id + 1)) {
- if (!old_style.HasPseudoStyle(pseudo_id) &&
- !new_style.HasPseudoStyle(pseudo_id))
+ if (!old_style.HasPseudoElementStyle(pseudo_id) &&
+ !new_style.HasPseudoElementStyle(pseudo_id))
continue;
const ComputedStyle* new_pseudo_style =
- new_style.GetCachedPseudoStyle(pseudo_id);
+ new_style.GetCachedPseudoElementStyle(pseudo_id);
if (!new_pseudo_style)
return false;
const ComputedStyle* old_pseudo_style =
- old_style.GetCachedPseudoStyle(pseudo_id);
+ old_style.GetCachedPseudoElementStyle(pseudo_id);
if (old_pseudo_style && *old_pseudo_style != *new_pseudo_style)
return false;
}
@@ -204,8 +205,8 @@ bool ComputedStyle::NeedsReattachLayoutTree(const ComputedStyle* old_style,
return true;
if (old_style->Display() != new_style->Display())
return true;
- if (old_style->HasPseudoStyle(kPseudoIdFirstLetter) !=
- new_style->HasPseudoStyle(kPseudoIdFirstLetter))
+ if (old_style->HasPseudoElementStyle(kPseudoIdFirstLetter) !=
+ new_style->HasPseudoElementStyle(kPseudoIdFirstLetter))
return true;
if (!old_style->ContentDataEquivalent(*new_style))
return true;
@@ -215,8 +216,7 @@ bool ComputedStyle::NeedsReattachLayoutTree(const ComputedStyle* old_style,
// so that if line-clamping changes then the LayoutObject needs to be
// recreated.
if (RuntimeEnabledFeatures::WebkitBoxLayoutUsesFlexLayoutEnabled() &&
- (new_style->Display() == EDisplay::kWebkitBox ||
- new_style->Display() == EDisplay::kWebkitInlineBox) &&
+ (new_style->IsDeprecatedWebkitBox()) &&
(old_style->HasLineClamp() != new_style->HasLineClamp() &&
new_style->BoxOrient() == EBoxOrient::kVertical)) {
return true;
@@ -232,8 +232,8 @@ bool ComputedStyle::NeedsReattachLayoutTree(const ComputedStyle* old_style,
// LayoutNG needs an anonymous inline wrapper if ::first-line is applied.
// Also see |LayoutBlockFlow::NeedsAnonymousInlineWrapper()|.
- if (new_style->HasPseudoStyle(kPseudoIdFirstLine) &&
- !old_style->HasPseudoStyle(kPseudoIdFirstLine))
+ if (new_style->HasPseudoElementStyle(kPseudoIdFirstLine) &&
+ !old_style->HasPseudoElementStyle(kPseudoIdFirstLine))
return true;
return false;
@@ -256,8 +256,9 @@ ComputedStyle::Difference ComputedStyle::ComputeDifference(
// See external/wpt/css/css-pseudo/first-line-change-inline-color*.html.
auto inherited_first_line_style_diff = Difference::kEqual;
if (const ComputedStyle* cached_inherited_first_line_style =
- old_style->GetCachedPseudoStyle(kPseudoIdFirstLineInherited)) {
- DCHECK(!new_style->GetCachedPseudoStyle(kPseudoIdFirstLineInherited));
+ old_style->GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited)) {
+ DCHECK(
+ !new_style->GetCachedPseudoElementStyle(kPseudoIdFirstLineInherited));
inherited_first_line_style_diff =
ComputeDifferenceIgnoringInheritedFirstLineStyle(
*cached_inherited_first_line_style, *new_style);
@@ -288,13 +289,13 @@ ComputedStyle::ComputeDifferenceIgnoringInheritedFirstLineStyle(
return Difference::kIndependentInherited;
if (non_inherited_equal) {
DCHECK(old_style == new_style);
- if (PseudoStylesEqual(old_style, new_style))
+ if (PseudoElementStylesEqual(old_style, new_style))
return Difference::kEqual;
- return Difference::kPseudoStyle;
+ return Difference::kPseudoElementStyle;
}
- if (new_style.HasAnyPublicPseudoStyles() ||
- old_style.HasAnyPublicPseudoStyles())
- return Difference::kPseudoStyle;
+ if (new_style.HasAnyPseudoElementStyles() ||
+ old_style.HasAnyPseudoElementStyles())
+ return Difference::kPseudoElementStyle;
return Difference::kNonInherited;
}
@@ -474,14 +475,15 @@ bool ComputedStyle::operator==(const ComputedStyle& o) const {
return InheritedEqual(o) && NonInheritedEqual(o);
}
-const ComputedStyle* ComputedStyle::GetCachedPseudoStyle(PseudoId pid) const {
- if (!cached_pseudo_styles_ || !cached_pseudo_styles_->size())
+const ComputedStyle* ComputedStyle::GetCachedPseudoElementStyle(
+ PseudoId pid) const {
+ if (!cached_pseudo_element_styles_ || !cached_pseudo_element_styles_->size())
return nullptr;
if (StyleType() != kPseudoIdNone)
return nullptr;
- for (const auto& pseudo_style : *cached_pseudo_styles_) {
+ for (const auto& pseudo_style : *cached_pseudo_element_styles_) {
if (pseudo_style->StyleType() == pid)
return pseudo_style.get();
}
@@ -489,17 +491,17 @@ const ComputedStyle* ComputedStyle::GetCachedPseudoStyle(PseudoId pid) const {
return nullptr;
}
-const ComputedStyle* ComputedStyle::AddCachedPseudoStyle(
+const ComputedStyle* ComputedStyle::AddCachedPseudoElementStyle(
scoped_refptr<const ComputedStyle> pseudo) const {
DCHECK(pseudo);
DCHECK_GT(pseudo->StyleType(), kPseudoIdNone);
const ComputedStyle* result = pseudo.get();
- if (!cached_pseudo_styles_)
- cached_pseudo_styles_ = std::make_unique<PseudoStyleCache>();
+ if (!cached_pseudo_element_styles_)
+ cached_pseudo_element_styles_ = std::make_unique<PseudoElementStyleCache>();
- cached_pseudo_styles_->push_back(std::move(pseudo));
+ cached_pseudo_element_styles_->push_back(std::move(pseudo));
return result;
}
@@ -604,7 +606,7 @@ StyleDifference ComputedStyle::VisualInvalidationDiff(
if (DiffNeedsPaintInvalidationSubtree(other))
diff.SetNeedsPaintInvalidationSubtree();
else
- AdjustDiffForNeedsPaintInvalidationObject(other, diff);
+ AdjustDiffForNeedsPaintInvalidationObject(other, diff, document);
if (DiffNeedsVisualRectUpdate(other))
diff.SetNeedsVisualRectUpdate();
@@ -768,7 +770,8 @@ bool ComputedStyle::DiffNeedsPaintInvalidationSubtree(
void ComputedStyle::AdjustDiffForNeedsPaintInvalidationObject(
const ComputedStyle& other,
- StyleDifference& diff) const {
+ StyleDifference& diff,
+ const Document& document) const {
if (ComputedStyleBase::DiffNeedsPaintInvalidationObject(*this, other) ||
!BorderVisuallyEqual(other) || !RadiiEqual(other))
diff.SetNeedsPaintInvalidationObject();
@@ -781,7 +784,8 @@ void ComputedStyle::AdjustDiffForNeedsPaintInvalidationObject(
if (PaintImagesInternal()) {
for (const auto& image : *PaintImagesInternal()) {
DCHECK(image);
- if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other)) {
+ if (DiffNeedsPaintInvalidationObjectForPaintImage(*image, other,
+ document)) {
diff.SetNeedsPaintInvalidationObject();
return;
}
@@ -810,7 +814,8 @@ void ComputedStyle::AdjustDiffForBackgroundVisuallyEqual(
bool ComputedStyle::DiffNeedsPaintInvalidationObjectForPaintImage(
const StyleImage& image,
- const ComputedStyle& other) const {
+ const ComputedStyle& other,
+ const Document& document) const {
// https://crbug.com/835589: early exit when paint target is associated with
// a link.
if (InsideLink() != EInsideLink::kNotInsideLink)
@@ -821,14 +826,15 @@ bool ComputedStyle::DiffNeedsPaintInvalidationObjectForPaintImage(
// NOTE: If the invalidation properties vectors are null, we are invalid as
// we haven't yet been painted (and can't provide the invalidation
// properties yet).
- if (!value->NativeInvalidationProperties() ||
- !value->CustomInvalidationProperties())
+ if (!value->NativeInvalidationProperties(document) ||
+ !value->CustomInvalidationProperties(document))
return true;
- if (!PropertiesEqual(*value->NativeInvalidationProperties(), other))
+ if (!PropertiesEqual(*value->NativeInvalidationProperties(document), other))
return true;
- if (!CustomPropertiesEqual(*value->CustomInvalidationProperties(), other))
+ if (!CustomPropertiesEqual(*value->CustomInvalidationProperties(document),
+ other))
return true;
return false;
@@ -942,6 +948,23 @@ void ComputedStyle::AddPaintImage(StyleImage* image) {
MutablePaintImagesInternal()->push_back(image);
}
+bool ComputedStyle::HasCSSPaintImagesUsingCustomProperty(
+ const AtomicString& custom_property_name,
+ const Document& document) const {
+ if (PaintImagesInternal()) {
+ for (const auto& image : *PaintImagesInternal()) {
+ DCHECK(image);
+ // IsPaintImage is true for CSS Paint images only, please refer to the
+ // constructor of StyleGeneratedImage.
+ if (image->IsPaintImage()) {
+ return To<StyleGeneratedImage>(image.Get())
+ ->IsUsingCustomProperty(custom_property_name, document);
+ }
+ }
+ }
+ return false;
+}
+
void ComputedStyle::AddCursor(StyleImage* image,
bool hot_spot_specified,
const IntPoint& hot_spot) {
@@ -1291,6 +1314,9 @@ void ComputedStyle::SetColor(const Color& v) {
SetIsColorInternalText(false);
SetColorInternal(v);
}
+void ComputedStyle::ResolveInternalTextColor(const Color& v) {
+ SetColorInternal(v);
+}
static FloatRoundedRect::Radii CalcRadiiFor(const LengthSize& top_left,
const LengthSize& top_right,
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 00f9cb65281..68258db9b52 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.h
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.h
@@ -89,7 +89,7 @@ class StyleResolver;
class StyleSelfAlignmentData;
class TransformationMatrix;
-typedef Vector<scoped_refptr<const ComputedStyle>, 4> PseudoStyleCache;
+typedef Vector<scoped_refptr<const ComputedStyle>, 4> PseudoElementStyleCache;
namespace css_longhand {
@@ -143,7 +143,7 @@ class WebkitTextStrokeColor;
//
// In addition to storing the computed value of every CSS property,
// ComputedStyle also contains various internal style information. Examples
-// include cached_pseudo_styles_ (for storing pseudo element styles) and
+// include cached_pseudo_element_styles_ (for storing pseudo element styles) and
// has_simple_underline_ (cached indicator flag of text-decoration). These are
// stored on ComputedStyle for two reasons:
//
@@ -279,7 +279,8 @@ class ComputedStyle : public ComputedStyleBase,
// <script>
// getComputedStyle(div, "::before").color // still green.
// </script>
- mutable std::unique_ptr<PseudoStyleCache> cached_pseudo_styles_;
+ mutable std::unique_ptr<PseudoElementStyleCache>
+ cached_pseudo_element_styles_;
DataRef<SVGComputedStyle> svg_style_;
@@ -308,7 +309,7 @@ class ComputedStyle : public ComputedStyleBase,
// Find out how two ComputedStyles differ. Used for figuring out if style
// recalc needs to propagate style changes down the tree. The constants are
// listed in increasing severity. E.g. kInherited also means we need to update
- // pseudo elements (kPseudoStyle).
+ // pseudo elements (kPseudoElementStyle).
enum class Difference {
// The ComputedStyle objects have the same computed style. The might have
// some different extra flags which means we still need to replace the old
@@ -319,7 +320,7 @@ class ComputedStyle : public ComputedStyleBase,
kNonInherited,
// Pseudo element style is different which means we have to update pseudo
// element existence and computed style.
- kPseudoStyle,
+ kPseudoElementStyle,
// Inherited properties are different which means we need to recalc style
// for children. Only independent properties changed which means we can
// inherit by cloning the exiting ComputedStyle for children an set modified
@@ -382,12 +383,12 @@ class ComputedStyle : public ComputedStyleBase,
}
void SetStyleType(PseudoId style_type) { SetStyleTypeInternal(style_type); }
- const ComputedStyle* GetCachedPseudoStyle(PseudoId) const;
- const ComputedStyle* AddCachedPseudoStyle(
+ const ComputedStyle* GetCachedPseudoElementStyle(PseudoId) const;
+ const ComputedStyle* AddCachedPseudoElementStyle(
scoped_refptr<const ComputedStyle>) const;
- void ClearCachedPseudoStyles() const {
- if (cached_pseudo_styles_)
- cached_pseudo_styles_->clear();
+ void ClearCachedPseudoElementStyles() const {
+ if (cached_pseudo_element_styles_)
+ cached_pseudo_element_styles_->clear();
}
/**
@@ -487,7 +488,7 @@ class ComputedStyle : public ComputedStyleBase,
// border-image-source
StyleImage* BorderImageSource() const { return BorderImage().GetImage(); }
- void SetBorderImageSource(StyleImage*);
+ CORE_EXPORT void SetBorderImageSource(StyleImage*);
// border-image-width
const BorderImageLengthBox& BorderImageWidth() const {
@@ -941,6 +942,7 @@ class ComputedStyle : public ComputedStyleBase,
// color
void SetColor(const Color&);
+ void ResolveInternalTextColor(const Color&);
// line-height
Length LineHeight() const;
@@ -1197,6 +1199,16 @@ class ComputedStyle : public ComputedStyleBase,
void ClearIncrementDirectives();
void ClearResetDirectives();
+ bool IsDeprecatedWebkitBox() const {
+ return Display() == EDisplay::kWebkitBox ||
+ Display() == EDisplay::kWebkitInlineBox;
+ }
+ bool IsDeprecatedFlexboxUsingFlexLayout() const {
+ return IsDeprecatedWebkitBox() &&
+ RuntimeEnabledFeatures::WebkitBoxLayoutUsesFlexLayoutEnabled() &&
+ (!HasLineClamp() || BoxOrient() == EBoxOrient::kHorizontal);
+ }
+
// Variables.
bool HasVariables() const;
CORE_EXPORT StyleInheritedVariables* InheritedVariables() const;
@@ -1252,24 +1264,20 @@ class ComputedStyle : public ComputedStyleBase,
// Flex utility functions.
bool ResolvedIsColumnFlexDirection() const {
- if (Display() == EDisplay::kWebkitBox ||
- Display() == EDisplay::kWebkitInlineBox) {
+ if (IsDeprecatedWebkitBox())
return BoxOrient() == EBoxOrient::kVertical;
- }
return FlexDirection() == EFlexDirection::kColumn ||
FlexDirection() == EFlexDirection::kColumnReverse;
}
bool ResolvedIsColumnReverseFlexDirection() const {
- if (Display() == EDisplay::kWebkitBox ||
- Display() == EDisplay::kWebkitInlineBox) {
+ if (IsDeprecatedWebkitBox()) {
return BoxOrient() == EBoxOrient::kVertical &&
BoxDirection() == EBoxDirection::kReverse;
}
return FlexDirection() == EFlexDirection::kColumnReverse;
}
bool ResolvedIsRowReverseFlexDirection() const {
- if (Display() == EDisplay::kWebkitBox ||
- Display() == EDisplay::kWebkitInlineBox) {
+ if (IsDeprecatedWebkitBox()) {
return BoxOrient() == EBoxOrient::kHorizontal &&
BoxDirection() == EBoxDirection::kReverse;
}
@@ -1280,17 +1288,13 @@ class ComputedStyle : public ComputedStyleBase,
return DataEquivalent(BoxReflect(), other.BoxReflect());
}
float ResolvedFlexGrow(const ComputedStyle& box_style) const {
- if (box_style.Display() == EDisplay::kWebkitBox ||
- box_style.Display() == EDisplay::kWebkitInlineBox) {
+ if (box_style.IsDeprecatedWebkitBox())
return BoxFlex() > 0 ? BoxFlex() : 0.0f;
- }
return FlexGrow();
}
float ResolvedFlexShrink(const ComputedStyle& box_style) const {
- if (box_style.Display() == EDisplay::kWebkitBox ||
- box_style.Display() == EDisplay::kWebkitInlineBox) {
+ if (box_style.IsDeprecatedWebkitBox())
return BoxFlex() > 0 ? BoxFlex() : 0.0f;
- }
return FlexShrink();
}
@@ -2092,7 +2096,6 @@ class ComputedStyle : public ComputedStyleBase,
bool IsDisplayFlexibleOrGridBox() const {
return IsDisplayFlexibleBox(Display()) || IsDisplayGridBox(Display());
}
- bool IsDisplayFlexibleBox() const { return IsDisplayFlexibleBox(Display()); }
bool IsDisplayLayoutCustomBox() const {
return IsDisplayLayoutCustomBox(Display());
}
@@ -2217,9 +2220,12 @@ class ComputedStyle : public ComputedStyleBase,
return TableLayout() == ETableLayout::kFixed && !LogicalWidth().IsAuto();
}
- // Filter/transform utility functions.
- bool Has3DTransform() const {
- return Transform().Has3DOperation() ||
+ // Returns true if the computed style contains a 3D transform operation.
+ // This can be individual operations from the transform property, or
+ // individual values from translate/rotate/scale properties. Note that
+ // perspective is omitted, since it does not by itself specify a 3D transform.
+ bool Has3DTransformOperation() const {
+ return Transform().HasNonPerspective3DOperation() ||
(Translate() && Translate()->Z() != 0) ||
(Rotate() && (Rotate()->X() != 0 || Rotate()->Y() != 0)) ||
(Scale() && Scale()->Z() != 1);
@@ -2304,7 +2310,13 @@ class ComputedStyle : public ComputedStyleBase,
}
// Paint utility functions.
- void AddPaintImage(StyleImage*);
+ CORE_EXPORT void AddPaintImage(StyleImage*);
+
+ // Returns true if any property has an <image> value that is a CSS paint
+ // function that is using a given custom property.
+ bool HasCSSPaintImagesUsingCustomProperty(
+ const AtomicString& custom_property_name,
+ const Document&) const;
// FIXME: reflections should belong to this helper function but they are
// currently handled through their self-painting layers. So the layout code
@@ -2333,11 +2345,10 @@ class ComputedStyle : public ComputedStyleBase,
return IsStackingContext() || GetPosition() != EPosition::kStatic;
}
- // Pseudo-styles
- bool HasAnyPublicPseudoStyles() const;
- bool HasPseudoStyle(PseudoId) const;
- void SetHasPseudoStyle(PseudoId);
- bool HasPseudoElementStyle() const;
+ // Pseudo element styles.
+ bool HasAnyPseudoElementStyles() const;
+ bool HasPseudoElementStyle(PseudoId) const;
+ void SetHasPseudoElementStyle(PseudoId);
// Note: CanContainAbsolutePositionObjects should return true if
// CanContainFixedPositionObjects. We currently never use this value
@@ -2475,7 +2486,7 @@ class ComputedStyle : public ComputedStyleBase,
InterpolationQuality GetInterpolationQuality() const;
bool CanGeneratePseudoElement(PseudoId pseudo) const {
- if (!HasPseudoStyle(pseudo))
+ if (!HasPseudoElementStyle(pseudo))
return false;
if (Display() == EDisplay::kNone)
return false;
@@ -2761,10 +2772,11 @@ class ComputedStyle : public ComputedStyleBase,
const ComputedStyle& other) const;
bool DiffNeedsPaintInvalidationSubtree(const ComputedStyle& other) const;
void AdjustDiffForNeedsPaintInvalidationObject(const ComputedStyle& other,
- StyleDifference&) const;
- bool DiffNeedsPaintInvalidationObjectForPaintImage(
- const StyleImage&,
- const ComputedStyle& other) const;
+ StyleDifference&,
+ const Document&) const;
+ bool DiffNeedsPaintInvalidationObjectForPaintImage(const StyleImage&,
+ const ComputedStyle& other,
+ const Document&) const;
bool DiffNeedsVisualRectUpdate(const ComputedStyle& other) const;
CORE_EXPORT void UpdatePropertySpecificDifferences(const ComputedStyle& other,
StyleDifference&) const;
@@ -2875,17 +2887,17 @@ inline float ComputedStyle::EffectiveZoom() const {
return InternalEffectiveZoom();
}
-inline bool ComputedStyle::HasAnyPublicPseudoStyles() const {
- return PseudoBitsInternal() != kPseudoIdNone;
+inline bool ComputedStyle::HasAnyPseudoElementStyles() const {
+ return !!PseudoBitsInternal();
}
-inline bool ComputedStyle::HasPseudoStyle(PseudoId pseudo) const {
+inline bool ComputedStyle::HasPseudoElementStyle(PseudoId pseudo) const {
DCHECK(pseudo >= kFirstPublicPseudoId);
DCHECK(pseudo < kFirstInternalPseudoId);
return (1 << (pseudo - kFirstPublicPseudoId)) & PseudoBitsInternal();
}
-inline void ComputedStyle::SetHasPseudoStyle(PseudoId pseudo) {
+inline void ComputedStyle::SetHasPseudoElementStyle(PseudoId pseudo) {
DCHECK(pseudo >= kFirstPublicPseudoId);
DCHECK(pseudo < kFirstInternalPseudoId);
// TODO: Fix up this code. It is hard to understand.
@@ -2893,10 +2905,6 @@ inline void ComputedStyle::SetHasPseudoStyle(PseudoId pseudo) {
PseudoBitsInternal() | 1 << (pseudo - kFirstPublicPseudoId)));
}
-inline bool ComputedStyle::HasPseudoElementStyle() const {
- return PseudoBitsInternal() & kElementPseudoIdMask;
-}
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_H_
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 36e484b99f7..dec1ac57118 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
@@ -34,7 +34,7 @@
name: "ScrollAnchorDisablingPropertyChanged",
fields_to_diff: ["width", "min-width", "max-width", "height", "min-height", "max-height", "margin-top", "margin-left", "margin-right", "margin-bottom",
"left", "right", "top", "bottom", "padding-top",
- "padding-left", "padding-right", "padding-bottom"],
+ "padding-left", "padding-right", "padding-bottom", "content-size"],
methods_to_diff: [
{
method: "GetPosition()",
@@ -134,7 +134,7 @@
field_dependencies: ["filter"]
},
{
- method: "HasPseudoStyle(kPseudoIdScrollbar)",
+ method: "HasPseudoElementStyle(kPseudoIdScrollbar)",
field_dependencies: ["StyleType"]
},
{
@@ -215,7 +215,11 @@
methods_to_diff: [
{
method: "ListStyleType()",
- field_dependencies: ["list-style-type"]
+ field_dependencies: ["ListStyleType"]
+ },
+ {
+ method: "ListStyleStringValue()",
+ field_dependencies: ["ListStyleStringValue"]
},
{
method: "ListStylePosition()",
@@ -228,7 +232,7 @@
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"],
+ "justify-self", "contain", "content-size"],
methods_to_diff: [
{
method: "VerticalAlign()",
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 5b8ddb37dfa..d30a53586d4 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
@@ -989,5 +989,37 @@
default_value: "false",
custom_compare: true,
},
+ {
+ name: "ListStyleType",
+ inherited: true,
+ field_template: "keyword",
+ type_name: "EListStyleType",
+ keywords: [
+ "disc", "circle", "square", "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",
+ "string",
+ ],
+ default_value: "disc",
+ },
+ {
+ name: "ListStyleStringValue",
+ inherited: true,
+ field_template: "external",
+ field_group: "*",
+ type_name: "AtomicString",
+ include_paths: ["third_party/blink/renderer/platform/wtf/text/atomic_string.h"],
+ default_value: "g_null_atom",
+ },
],
}
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 0c048fa0e02..9facd9e542b 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
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
@@ -127,16 +128,16 @@ TEST(ComputedStyleTest, LayoutContainmentStackingContext) {
TEST(ComputedStyleTest, FirstPublicPseudoStyle) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
- style->SetHasPseudoStyle(kPseudoIdFirstLine);
- EXPECT_TRUE(style->HasPseudoStyle(kPseudoIdFirstLine));
- EXPECT_TRUE(style->HasAnyPublicPseudoStyles());
+ style->SetHasPseudoElementStyle(kPseudoIdFirstLine);
+ EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdFirstLine));
+ EXPECT_TRUE(style->HasAnyPseudoElementStyles());
}
-TEST(ComputedStyleTest, LastPublicPseudoStyle) {
+TEST(ComputedStyleTest, LastPublicPseudoElementStyle) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
- style->SetHasPseudoStyle(kPseudoIdScrollbar);
- EXPECT_TRUE(style->HasPseudoStyle(kPseudoIdScrollbar));
- EXPECT_TRUE(style->HasAnyPublicPseudoStyles());
+ style->SetHasPseudoElementStyle(kPseudoIdScrollbar);
+ EXPECT_TRUE(style->HasPseudoElementStyle(kPseudoIdScrollbar));
+ EXPECT_TRUE(style->HasAnyPseudoElementStyles());
}
TEST(ComputedStyleTest,
@@ -535,4 +536,53 @@ TEST(ComputedStyleTest, ApplyColorSchemeLightOnDark) {
EXPECT_EQ(WebColorScheme::kLight, style->UsedColorScheme());
}
+TEST(ComputedStyleTest, ApplyInternalLightDarkColor) {
+ ScopedCSSColorSchemeForTest scoped_property_enabled(true);
+
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_ =
+ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr);
+ const ComputedStyle* initial = &ComputedStyle::InitialStyle();
+
+ auto* ua_context = MakeGarbageCollected<CSSParserContext>(
+ kUASheetMode, SecureContextMode::kInsecureContext);
+ const CSSValue* internal_light_dark = CSSParser::ParseSingleValue(
+ CSSPropertyID::kColor, "-internal-light-dark-color(black, white)",
+ ua_context);
+
+ dummy_page_holder_->GetDocument().GetSettings()->SetPreferredColorScheme(
+ PreferredColorScheme::kDark);
+ StyleResolverState state(dummy_page_holder_->GetDocument(),
+ *dummy_page_holder_->GetDocument().documentElement(),
+ initial, initial);
+
+ StyleResolver& resolver =
+ dummy_page_holder_->GetDocument().EnsureStyleResolver();
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ state.SetStyle(style);
+
+ CSSValueList* dark_value = CSSValueList::CreateSpaceSeparated();
+ dark_value->Append(*CSSIdentifierValue::Create(CSSValueID::kDark));
+
+ CSSValueList* light_value = CSSValueList::CreateSpaceSeparated();
+ light_value->Append(*CSSIdentifierValue::Create(CSSValueID::kLight));
+
+ CSSPropertyRef scheme_property("color-scheme", state.GetDocument());
+ CSSPropertyRef color_property("color", state.GetDocument());
+
+ To<Longhand>(color_property.GetProperty())
+ .ApplyValue(state, *internal_light_dark);
+ To<Longhand>(scheme_property.GetProperty()).ApplyValue(state, *dark_value);
+ if (!RuntimeEnabledFeatures::CSSCascadeEnabled())
+ resolver.ApplyCascadedColorValue(state);
+ EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor()));
+
+ To<Longhand>(color_property.GetProperty())
+ .ApplyValue(state, *internal_light_dark);
+ To<Longhand>(scheme_property.GetProperty()).ApplyValue(state, *light_value);
+ if (!RuntimeEnabledFeatures::CSSCascadeEnabled())
+ resolver.ApplyCascadedColorValue(state);
+ EXPECT_EQ(Color::kBlack, style->VisitedDependentColor(GetCSSPropertyColor()));
+}
+
} // namespace blink
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 fd4dc064548..0c70934146f 100644
--- a/chromium/third_party/blink/renderer/core/style/content_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/content_data.cc
@@ -77,7 +77,7 @@ LayoutObject* ImageContentData::CreateLayoutObject(
const ComputedStyle& pseudo_style,
LegacyLayout) const {
LayoutImage* image = LayoutImage::CreateAnonymous(pseudo);
- image->SetPseudoStyle(&pseudo_style);
+ image->SetPseudoElementStyle(&pseudo_style);
if (image_) {
image->SetImageResource(
MakeGarbageCollected<LayoutImageResourceStyleImage>(image_.Get()));
@@ -98,7 +98,7 @@ LayoutObject* TextContentData::CreateLayoutObject(
LegacyLayout legacy) const {
LayoutObject* layout_object =
LayoutTextFragment::CreateAnonymous(pseudo, text_.Impl(), legacy);
- layout_object->SetPseudoStyle(&pseudo_style);
+ layout_object->SetPseudoElementStyle(&pseudo_style);
return layout_object;
}
@@ -117,7 +117,7 @@ LayoutObject* CounterContentData::CreateLayoutObject(
const ComputedStyle& pseudo_style,
LegacyLayout) const {
LayoutObject* layout_object = new LayoutCounter(pseudo, *counter_);
- layout_object->SetPseudoStyle(&pseudo_style);
+ layout_object->SetPseudoElementStyle(&pseudo_style);
return layout_object;
}
@@ -126,7 +126,7 @@ LayoutObject* QuoteContentData::CreateLayoutObject(
const ComputedStyle& pseudo_style,
LegacyLayout) const {
LayoutObject* layout_object = new LayoutQuote(pseudo, quote_);
- layout_object->SetPseudoStyle(&pseudo_style);
+ 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 6ec82543c40..871d045f718 100644
--- a/chromium/third_party/blink/renderer/core/style/content_data.h
+++ b/chromium/third_party/blink/renderer/core/style/content_data.h
@@ -40,7 +40,7 @@ class LayoutObject;
enum class LegacyLayout;
class PseudoElement;
-class ContentData : public GarbageCollectedFinalized<ContentData> {
+class ContentData : public GarbageCollected<ContentData> {
public:
static ContentData* Create(StyleImage*);
static ContentData* Create(const String&);
diff --git a/chromium/third_party/blink/renderer/core/style/counter_content.h b/chromium/third_party/blink/renderer/core/style/counter_content.h
index 9bd35e967c4..49f86a5c6bf 100644
--- a/chromium/third_party/blink/renderer/core/style/counter_content.h
+++ b/chromium/third_party/blink/renderer/core/style/counter_content.h
@@ -37,7 +37,9 @@ class CounterContent {
CounterContent(const AtomicString& identifier,
EListStyleType style,
const AtomicString& separator)
- : identifier_(identifier), list_style_(style), separator_(separator) {}
+ : identifier_(identifier), list_style_(style), separator_(separator) {
+ DCHECK_NE(style, EListStyleType::kString);
+ }
const AtomicString& Identifier() const { return identifier_; }
EListStyleType ListStyle() const { return list_style_; }
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 10f8dfb4a9d..48733f4ef48 100644
--- a/chromium/third_party/blink/renderer/core/style/filter_operation.h
+++ b/chromium/third_party/blink/renderer/core/style/filter_operation.h
@@ -45,9 +45,7 @@ class SVGResourceClient;
// CSS Filters
-class CORE_EXPORT FilterOperation
- : public GarbageCollectedFinalized<FilterOperation> {
-
+class CORE_EXPORT FilterOperation : public GarbageCollected<FilterOperation> {
public:
enum OperationType {
REFERENCE, // url(#somefilter)
diff --git a/chromium/third_party/blink/renderer/core/style/shape_value.h b/chromium/third_party/blink/renderer/core/style/shape_value.h
index 8a7253e3205..6cfb86cfe5b 100644
--- a/chromium/third_party/blink/renderer/core/style/shape_value.h
+++ b/chromium/third_party/blink/renderer/core/style/shape_value.h
@@ -38,7 +38,7 @@
namespace blink {
-class ShapeValue final : public GarbageCollectedFinalized<ShapeValue> {
+class ShapeValue final : public GarbageCollected<ShapeValue> {
public:
enum ShapeValueType {
// The Auto value is defined by a null ShapeValue*
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 e697847e9e8..9326b428efd 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
@@ -139,14 +139,11 @@ void StyleFetchedImage::ImageNotifyFinished(ImageResourceContent*) {
if (document_ && image.IsSVGImage())
ToSVGImage(image).UpdateUseCounters(*document_);
-
- image_->UpdateImageAnimationPolicy();
}
- if (document_ && RuntimeEnabledFeatures::ElementTimingEnabled(document_)) {
- if (LocalDOMWindow* window = document_->domWindow()) {
+ if (document_) {
+ if (LocalDOMWindow* window = document_->domWindow())
ImageElementTiming::From(*window).NotifyBackgroundImageFinished(this);
- }
}
// Oilpan: do not prolong the Document's lifetime.
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 416dd860103..f8abe6869c3 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
@@ -61,8 +61,6 @@ class StyleFetchedImage final : public StyleImage,
bool HasIntrinsicSize() const override;
void AddClient(ImageResourceObserver*) override;
void RemoveClient(ImageResourceObserver*) override;
- void ImageNotifyFinished(ImageResourceContent*) override;
- bool GetImageAnimationPolicy(ImageAnimationPolicy&) override;
String DebugName() const override { return "StyleFetchedImage"; }
scoped_refptr<Image> GetImage(const ImageResourceObserver&,
const Document&,
@@ -81,6 +79,10 @@ class StyleFetchedImage final : public StyleImage,
bool IsEqual(const StyleImage&) const override;
void Dispose();
+ // ImageResourceObserver overrides
+ void ImageNotifyFinished(ImageResourceContent*) override;
+ bool GetImageAnimationPolicy(ImageAnimationPolicy&) override;
+
Member<ImageResourceContent> image_;
Member<const Document> document_;
const KURL url_;
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 4437ffa9edf..99055c04962 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
@@ -85,6 +85,7 @@ class StyleFetchedImageSet final : public StyleImage,
bool IsEqual(const StyleImage& other) const override;
void Dispose();
+ // ImageResourceObserver overrides
String DebugName() const override { return "StyleFetchedImageSet"; }
Member<ImageResourceContent> best_fit_image_;
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 cb6edac48ae..dda3c293924 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
@@ -78,6 +78,13 @@ void StyleGeneratedImage::RemoveClient(ImageResourceObserver* observer) {
image_generator_value_->RemoveClient(observer);
}
+bool StyleGeneratedImage::IsUsingCustomProperty(
+ const AtomicString& custom_property_name,
+ const Document& document) const {
+ return image_generator_value_->IsUsingCustomProperty(custom_property_name,
+ document);
+}
+
scoped_refptr<Image> StyleGeneratedImage::GetImage(
const ImageResourceObserver& observer,
const Document& document,
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 503bbc7e485..24fc4bb0ad8 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
@@ -60,6 +60,9 @@ class CORE_EXPORT StyleGeneratedImage final : public StyleImage {
const FloatSize& target_size) const override;
bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
+ bool IsUsingCustomProperty(const AtomicString& custom_property_name,
+ const Document&) const;
+
void Trace(blink::Visitor*) override;
private:
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 68897cdc48e..ddf24cf7428 100644
--- a/chromium/third_party/blink/renderer/core/style/style_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_image.h
@@ -45,7 +45,7 @@ typedef void* WrappedImagePtr;
// This class represents a CSS <image> value in ComputedStyle. The underlying
// object can be an image, a gradient or anything else defined as an <image>
// value.
-class CORE_EXPORT StyleImage : public GarbageCollectedFinalized<StyleImage> {
+class CORE_EXPORT StyleImage : public GarbageCollected<StyleImage> {
public:
virtual ~StyleImage() = default;
diff --git a/chromium/third_party/blink/renderer/core/svg/BUILD.gn b/chromium/third_party/blink/renderer/core/svg/BUILD.gn
index 3fd476d8cd6..5e0e345b2e7 100644
--- a/chromium/third_party/blink/renderer/core/svg/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/svg/BUILD.gn
@@ -5,17 +5,10 @@
import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("svg") {
- # Split into multiple static libraries on Windows official builds, where we
- # run into a 2GB max size limit.
- if (is_win && is_official_build) {
- split_count = 5
- } else {
- split_count = 1
- }
-
sources = [
"animation/smil_animation_sandwich.cc",
"animation/smil_animation_sandwich.h",
+ "animation/smil_repeat_count.h",
"animation/smil_time.cc",
"animation/smil_time.h",
"animation/smil_time_container.cc",
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc b/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
index 62e4e780d37..2c14dfd26f2 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
@@ -31,7 +31,20 @@
namespace blink {
-SMILAnimationSandwich::SMILAnimationSandwich() {}
+namespace {
+
+struct PriorityCompare {
+ PriorityCompare(SMILTime elapsed) : elapsed_(elapsed) {}
+ bool operator()(const Member<SVGSMILElement>& a,
+ const Member<SVGSMILElement>& b) {
+ return b->IsHigherPriorityThan(a, elapsed_);
+ }
+ SMILTime elapsed_;
+};
+
+} // namespace
+
+SMILAnimationSandwich::SMILAnimationSandwich() = default;
void SMILAnimationSandwich::Schedule(SVGSMILElement* animation) {
DCHECK(!sandwich_.Contains(animation));
@@ -42,90 +55,90 @@ void SMILAnimationSandwich::Unschedule(SVGSMILElement* animation) {
auto* position = std::find(sandwich_.begin(), sandwich_.end(), animation);
DCHECK(sandwich_.end() != position);
sandwich_.erase(position);
+ if (animation == ResultElement())
+ animation->ClearAnimatedType();
}
void SMILAnimationSandwich::Reset() {
- for (SVGSMILElement* animation : sandwich_) {
+ if (SVGSMILElement* result_element = ResultElement())
+ result_element->ClearAnimatedType();
+ for (SVGSMILElement* animation : sandwich_)
animation->Reset();
- }
}
-void SMILAnimationSandwich::UpdateTiming(double elapsed) {
- if (!std::is_sorted(sandwich_.begin(), sandwich_.end(),
- PriorityCompare(elapsed))) {
- std::sort(sandwich_.begin(), sandwich_.end(), PriorityCompare(elapsed));
- }
-
- active_.Shrink(0);
- active_.ReserveCapacity(sandwich_.size());
- for (const auto& it_animation : sandwich_) {
- SVGSMILElement* animation = it_animation.Get();
+void SMILAnimationSandwich::UpdateTiming(SMILTime elapsed) {
+ for (const auto& animation : sandwich_) {
DCHECK(animation->HasValidTarget());
- if (animation->NeedsToProgress(elapsed)) {
- animation->Progress(elapsed);
- active_.push_back(animation);
- } else if (animation->IsContributing(elapsed)) {
- active_.push_back(animation);
- } else {
- animation->ClearAnimatedType();
- }
+ if (!animation->NeedsIntervalUpdate(elapsed))
+ continue;
+ animation->UpdateInterval(elapsed);
}
}
-SMILTime SMILAnimationSandwich::NextInterestingTime(
- SMILTime document_time) const {
- SMILTime interesting_time = SMILTime::Indefinite();
- for (const auto& it_animation : sandwich_) {
- SVGSMILElement* animation = it_animation.Get();
- interesting_time = std::min(interesting_time,
- animation->NextInterestingTime(document_time));
+SMILTime SMILAnimationSandwich::NextIntervalTime(
+ SMILTime presentation_time) const {
+ SMILTime interval_time = SMILTime::Indefinite();
+ for (const auto& animation : sandwich_) {
+ interval_time =
+ std::min(interval_time, animation->NextIntervalTime(presentation_time));
}
- return interesting_time;
+ return interval_time;
}
-SMILTime SMILAnimationSandwich::GetNextFireTime() const {
- SMILTime earliest_fire_time = SMILTime::Unresolved();
- for (const auto& it_animation : sandwich_) {
- SVGSMILElement* animation = it_animation.Get();
-
- SMILTime next_fire_time = animation->NextProgressTime();
- if (next_fire_time.IsFinite())
- earliest_fire_time = std::min(next_fire_time, earliest_fire_time);
+SMILTime SMILAnimationSandwich::NextProgressTime(
+ SMILTime presentation_time) const {
+ SMILTime earliest_progress_time = SMILTime::Unresolved();
+ for (const auto& animation : sandwich_) {
+ earliest_progress_time = std::min(
+ earliest_progress_time, animation->NextProgressTime(presentation_time));
+ if (earliest_progress_time <= presentation_time)
+ break;
}
- return earliest_fire_time;
+ return earliest_progress_time;
}
-void SMILAnimationSandwich::UpdateSyncBases(double elapsed) {
- for (auto& animation : active_) {
- animation->UpdateSyncBases();
- }
+void SMILAnimationSandwich::UpdateActiveStateAndOrder(
+ SMILTime presentation_time) {
+ for (auto& animation : sandwich_)
+ animation->UpdateActiveState(presentation_time);
- for (auto& animation : active_) {
- animation->UpdateNextProgressTime(elapsed);
+ if (!std::is_sorted(sandwich_.begin(), sandwich_.end(),
+ PriorityCompare(presentation_time))) {
+ std::sort(sandwich_.begin(), sandwich_.end(),
+ PriorityCompare(presentation_time));
}
+}
+
+SVGSMILElement* SMILAnimationSandwich::ResultElement() const {
+ return !active_.IsEmpty() ? active_.front() : nullptr;
+}
- auto* it = active_.begin();
- while (it != active_.end()) {
- auto* scheduled = it->Get();
- if (scheduled->IsContributing(elapsed)) {
- it++;
+void SMILAnimationSandwich::UpdateActiveAnimationStack(
+ SMILTime presentation_time) {
+ SVGSMILElement* old_result_element = ResultElement();
+ active_.Shrink(0);
+ active_.ReserveCapacity(sandwich_.size());
+ // Build the contributing/active sandwich.
+ for (auto& animation : sandwich_) {
+ if (!animation->IsContributing(presentation_time))
continue;
- }
- scheduled->ClearAnimatedType();
- it = active_.erase(it);
+ animation->UpdateProgressState(presentation_time);
+ active_.push_back(animation);
}
+ // If we switched result element, clear the old one.
+ if (old_result_element && old_result_element != ResultElement())
+ old_result_element->ClearAnimatedType();
}
SVGSMILElement* SMILAnimationSandwich::ApplyAnimationValues() {
- if (active_.IsEmpty())
+ SVGSMILElement* result_element = ResultElement();
+ if (!result_element)
return nullptr;
- // Results are accumulated to the first animation that animates and
- // contributes to a particular element/attribute pair.
+
// Only reset the animated type to the base value once for
// the lowest priority animation that animates and
// contributes to a particular element/attribute pair.
- SVGSMILElement* result_element = active_.front();
result_element->ResetAnimatedType();
// Animations have to be applied lowest to highest prio.
@@ -144,10 +157,8 @@ SVGSMILElement* SMILAnimationSandwich::ApplyAnimationValues() {
sandwich_it++) {
(*sandwich_it)->UpdateAnimatedValue(result_element);
}
- active_.Shrink(0);
result_element->ApplyResultsToTarget();
-
return result_element;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h b/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
index 8ddd73d9ff8..3abdcb60b4a 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
@@ -33,49 +33,105 @@
namespace blink {
-struct PriorityCompare {
- PriorityCompare(double elapsed) : elapsed_(elapsed) {}
- bool operator()(const Member<SVGSMILElement>& a,
- const Member<SVGSMILElement>& b) {
- // FIXME: This should also consider possible timing relations between the
- // elements.
- SMILTime a_begin = a->IntervalBegin();
- SMILTime b_begin = b->IntervalBegin();
- // Frozen elements need to be prioritized based on their previous interval.
- a_begin = a->IsFrozen() && elapsed_ < a_begin ? a->PreviousIntervalBegin()
- : a_begin;
- b_begin = b->IsFrozen() && elapsed_ < b_begin ? b->PreviousIntervalBegin()
- : b_begin;
- if (a_begin == b_begin)
- return a->DocumentOrderIndex() < b->DocumentOrderIndex();
- return a_begin < b_begin;
- }
- double elapsed_;
-};
-
+// This class implements/helps with implementing the "sandwich model" from SMIL.
+// https://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-AnimationSandwichModel
+//
+// A "sandwich" contains all the animation elements (actually timed elements in
+// our case because of how we handle <discard>) that targets a specific
+// attribute (or property) on a certain element.
+//
+// Consider the following simple example:
+//
+// <svg>
+// <rect id="foo" width="100" height="100" fill="yellow">
+// <set id="s1" attributeName="fill" to="blue" begin="1s; 3s" dur="1s"/>
+// <set id="s2" attributeName="fill" to="lightblue" begin="1.5s" dur="2s"/>
+// </rect>
+// </svg>
+//
+// In this case there is only one sandwich: <#foo, "fill">
+//
+// The sandwich is priority-sorted with the priority being derived from when
+// the currently active interval began - later is higher. In the above example
+// there are three intervals: [1s 2s) and [3s 4s) for the first <set> element
+// (in tree-order) and [1.5s 3.5s) for the second <set> element. The animation
+// elements are only active within the intervals defined (no fill="freeze").
+//
+// When the first interval of the first <set> starts (at 1s), it is the only
+// active animation and thus the only one to apply. When the second interval
+// starts (at 1.5s) its animation gets a higher priority and replaces the lower
+// priority animation from the first <set>. The first <set> then ends at 2s,
+// leaving the second <set> as the only active animation. When the first <set>
+// then starts again at 3s it gets a higher priority because of the later begin
+// time and replaces the animation from the second <set>. When the second <set>
+// ends at 3.5s nothing changes because the first <set> is still active. When
+// the second <set> ends again at 4s, no animation apply and the target reverts
+// to the base value (yellow) again.
+//
+// Schematically (right hand side exclusive):
+//
+// 0s -> 1s: No animations apply (fill=yellow)
+// Sandwich order: (s1) (s2) [both inactive]
+// 1s -> 1.5s: The first <set> apply (fill=blue)
+// Sandwich order: s1 (s2) [only s1 active]
+// 1.5s -> 2s: The second <set> apply (fill=lightblue)
+// Sandwich order: s1 s2
+// 2s -> 3s: The second <set> apply (fill=lightblue)
+// Sandwich order: (s1) s2
+// 3s -> 3.5s: The first <set> apply (fill=blue)
+// Sandwich order: s2 s1
+// 3.5s -> 4s: The first <set> apply (fill=blue)
+// Sandwich order: (s2) s1
+// 4s -> ...: No animations apply (fill=yellow)
+//
+// -----
+//
+// Implementation details:
+//
+// UpdateTiming() handles updates to interval and transitions the active state.
+//
+// UpdateActiveStateAndOrder() handles the sorting described above and updates
+// the active state of the elements in the sandwich.
+//
+// UpdateActiveAnimationStack() constructs a vector containing only the active
+// elements.
+//
+// ApplyAnimationValues() computes the actual animation value based on the
+// vector of active elements and applies it to the target element.
+//
class SMILAnimationSandwich : public GarbageCollected<SMILAnimationSandwich> {
public:
using ScheduledVector = HeapVector<Member<SVGSMILElement>>;
- explicit SMILAnimationSandwich();
+ SMILAnimationSandwich();
void Schedule(SVGSMILElement* animation);
void Unschedule(SVGSMILElement* animation);
void Reset();
- void UpdateTiming(double elapsed);
- void UpdateSyncBases(double elapsed);
+ void UpdateTiming(SMILTime presentation_time);
+ void UpdateActiveStateAndOrder(SMILTime presentation_time);
+ void UpdateActiveAnimationStack(SMILTime presentation_time);
SVGSMILElement* ApplyAnimationValues();
- SMILTime NextInterestingTime(SMILTime) const;
- SMILTime GetNextFireTime() const;
+ SMILTime NextIntervalTime(SMILTime presentation_time) const;
+ SMILTime NextProgressTime(SMILTime presentation_time) const;
bool IsEmpty() { return sandwich_.IsEmpty(); }
void Trace(blink::Visitor*);
private:
- // The list stored here is always sorted.
+ // Results are accumulated to the first animation element that animates and
+ // contributes to a particular element/attribute pair. We refer to this as
+ // the "result element".
+ SVGSMILElement* ResultElement() const;
+
+ // All the animation (really: timed) elements that make up the sandwich,
+ // sorted according to priority.
ScheduledVector sandwich_;
+ // The currently active animation elements in the sandwich. Retains the
+ // ordering of elements from |sandwich_| when created. This is the animation
+ // elements from which the animation value is computed.
ScheduledVector active_;
};
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_repeat_count.h b/chromium/third_party/blink/renderer/core/svg/animation/smil_repeat_count.h
new file mode 100644
index 00000000000..23d1f4810e3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_repeat_count.h
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_REPEAT_COUNT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_REPEAT_COUNT_H_
+
+#include <cmath>
+#include <limits>
+
+#include "base/logging.h"
+
+namespace blink {
+
+// Representation of the value from the 'repeatCount' SMIL attribute.
+//
+// "Unspecified" is used to indicate that the attribute is not specified.
+// "Invalid" is used to indicate that the attribute may have changed and needs
+// to be reparsed.
+class SMILRepeatCount {
+ public:
+ static SMILRepeatCount Unspecified() {
+ return SMILRepeatCount(std::numeric_limits<double>::quiet_NaN());
+ }
+ static SMILRepeatCount Indefinite() {
+ return SMILRepeatCount(std::numeric_limits<double>::infinity());
+ }
+ static SMILRepeatCount Numeric(double value) {
+ DCHECK(std::isfinite(value));
+ DCHECK_GT(value, 0);
+ return SMILRepeatCount(value);
+ }
+ static SMILRepeatCount Invalid() {
+ return SMILRepeatCount(-std::numeric_limits<double>::infinity());
+ }
+
+ bool IsValid() const {
+ return value_ != -std::numeric_limits<double>::infinity();
+ }
+ bool IsUnspecified() const {
+ DCHECK(IsValid());
+ return std::isnan(value_);
+ }
+ bool IsIndefinite() const {
+ DCHECK(IsValid());
+ return std::isinf(value_);
+ }
+ double NumericValue() const {
+ DCHECK(!IsUnspecified());
+ DCHECK(!IsIndefinite());
+ DCHECK(IsValid());
+ return value_;
+ }
+
+ private:
+ explicit SMILRepeatCount(double value) : value_(value) {}
+
+ double value_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_REPEAT_COUNT_H_
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time.cc b/chromium/third_party/blink/renderer/core/svg/animation/smil_time.cc
index d1cd1e39016..c06489cbb29 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time.cc
@@ -25,16 +25,19 @@
#include "third_party/blink/renderer/core/svg/animation/smil_time.h"
-#include <float.h>
+#include "third_party/blink/renderer/core/svg/animation/smil_repeat_count.h"
namespace blink {
-SMILTime operator*(const SMILTime& a, const SMILTime& b) {
- // Equal operators have to be used instead of negation here to make NaN work
- // as well.
- if (a.Value() == 0 || b.Value() == 0)
- return SMILTime(0);
- return a.Value() * b.Value();
+SMILTime SMILTime::Repeat(SMILRepeatCount repeat_count) const {
+ DCHECK(repeat_count.IsValid());
+ if (repeat_count.IsIndefinite() || repeat_count.IsUnspecified())
+ return Indefinite();
+ return time_ * repeat_count.NumericValue();
+}
+
+std::ostream& operator<<(std::ostream& os, SMILTime time) {
+ return os << time.InSecondsF() << " s";
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time.h b/chromium/third_party/blink/renderer/core/svg/animation/smil_time.h
index 4dd9c43976e..b4fec36d9ef 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time.h
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time.h
@@ -26,6 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_H_
+#include <ostream>
+
+#include "base/time/time.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_traits.h"
@@ -33,139 +36,175 @@
namespace blink {
+class SMILRepeatCount;
+struct SMILInterval;
+
+// SMILTime is used as both a time and time delta in the SMIL animation
+// code. It is a small wrapper around TimeDelta that adds two sentinel values
+// for SMIL concepts: "indefinite" and "unresolved".
+//
+// For ordering, the special values have the properties that:
+//
+// <finite SMILTime> < SMILTime::Indefinite() < SMILTime::Unresolved()
+//
+// SMILTime::Earliest() and SMILTime::Latest() are smallest and largest finite
+// time values respectively and sort accordingly.
+//
+// Addition and subtraction follow the semantics defined for computations of
+// active duration (https://www.w3.org/TR/SMIL3/smil-timing.html#q78).
class SMILTime {
DISALLOW_NEW();
public:
- SMILTime() : time_(0) {}
- SMILTime(double time) : time_(time) {}
+ constexpr SMILTime() = default;
+
+ static constexpr SMILTime Unresolved() { return base::TimeDelta::Max(); }
+ static constexpr SMILTime Indefinite() {
+ return base::TimeDelta::Max() - base::TimeDelta::FromMicroseconds(1);
+ }
+ static constexpr SMILTime Latest() {
+ return base::TimeDelta::Max() - base::TimeDelta::FromMicroseconds(2);
+ }
+ static constexpr SMILTime Earliest() { return base::TimeDelta::Min(); }
+ static constexpr SMILTime Epsilon() {
+ return base::TimeDelta::FromMicroseconds(1);
+ }
+ static constexpr SMILTime FromSecondsD(double seconds) {
+ return std::min(SMILTime(base::TimeDelta::FromSecondsD(seconds)), Latest());
+ }
+ static constexpr SMILTime FromMicroseconds(int64_t us) {
+ return std::min(SMILTime(base::TimeDelta::FromMicroseconds(us)), Latest());
+ }
- static SMILTime Unresolved() {
- return std::numeric_limits<double>::quiet_NaN();
+ // Used for computing progress. Don't use for anything else.
+ double InternalValueAsDouble() const { return time_.InMicrosecondsF(); }
+ double InSecondsF() const { return time_.InSecondsF(); }
+ int64_t InMicroseconds() const { return time_.InMicroseconds(); }
+
+ bool IsFinite() const { return *this < Indefinite(); }
+ bool IsIndefinite() const { return *this == Indefinite(); }
+ bool IsUnresolved() const { return *this == Unresolved(); }
+
+ SMILTime Repeat(SMILRepeatCount repeat_count) const;
+
+ SMILTime operator+(SMILTime other) const {
+ if (!IsFinite())
+ return time_;
+ if (!other.IsFinite())
+ return other;
+ SMILTime result(time_ + other.time_);
+ return result.IsFinite() ? result : Latest();
+ }
+ SMILTime operator-(SMILTime other) const {
+ if (!IsFinite())
+ return time_;
+ if (!other.IsFinite())
+ return other;
+ SMILTime result(time_ - other.time_);
+ return result.IsFinite() ? result : Latest();
}
- static SMILTime Indefinite() {
- return std::numeric_limits<double>::infinity();
+ SMILTime operator-() const { return -time_; }
+ // Division and /modulo are used primarily for computing interval
+ // progress/repeats.
+ int64_t operator/(SMILTime other) const {
+ DCHECK(IsFinite());
+ DCHECK(other.IsFinite());
+ return time_ / other.time_;
+ }
+ SMILTime operator%(SMILTime other) const {
+ DCHECK(IsFinite());
+ DCHECK(other.IsFinite());
+ return SMILTime(time_ % other.time_);
}
- double Value() const { return time_; }
+ bool operator==(SMILTime other) const { return time_ == other.time_; }
+ explicit operator bool() const { return IsFinite() && !time_.is_zero(); }
+ bool operator!=(SMILTime other) const { return time_ != other.time_; }
- bool IsFinite() const { return std::isfinite(time_); }
- bool IsIndefinite() const { return std::isinf(time_); }
- bool IsUnresolved() const { return std::isnan(time_); }
+ // Ordering of SMILTimes has to follow: finite < indefinite < unresolved. We
+ // set this up by assigning consecutive sentinel values for the two latter
+ // (see above).
+ bool operator>(SMILTime other) const { return time_ > other.time_; }
+ bool operator<(SMILTime other) const { return time_ < other.time_; }
+ bool operator>=(SMILTime other) const { return time_ >= other.time_; }
+ bool operator<=(SMILTime other) const { return time_ <= other.time_; }
private:
- double time_;
+ constexpr SMILTime(base::TimeDelta time) : time_(time) {}
+
+ base::TimeDelta time_;
+};
+
+std::ostream& operator<<(std::ostream& os, SMILTime time);
+
+// What generated a SMILTime.
+enum class SMILTimeOrigin {
+ kAttribute, // 'begin' / 'end' attribute
+ kScript, // beginElementAt / endElementAt
+ kSyncBase, // Sync-base
+ kRepeat, // Repeat event
+ kEvent, // DOM event
+ kLinkActivation, // Link activation (Click on link referring to timed
+ // element.)
};
class SMILTimeWithOrigin {
DISALLOW_NEW();
public:
- enum Origin { kParserOrigin, kScriptOrigin };
-
- SMILTimeWithOrigin() : origin_(kParserOrigin) {}
-
- SMILTimeWithOrigin(const SMILTime& time, Origin origin)
+ SMILTimeWithOrigin(const SMILTime& time, SMILTimeOrigin origin)
: time_(time), origin_(origin) {}
const SMILTime& Time() const { return time_; }
- bool OriginIsScript() const { return origin_ == kScriptOrigin; }
- bool HasSameOrigin(SMILTimeWithOrigin other) const {
- return origin_ == other.origin_;
- }
+ SMILTimeOrigin Origin() const { return origin_; }
private:
SMILTime time_;
- Origin origin_;
+ SMILTimeOrigin origin_;
};
+inline bool operator<(const SMILTimeWithOrigin& a,
+ const SMILTimeWithOrigin& b) {
+ return a.Time() < b.Time();
+}
+
+// An interval of SMILTimes.
+// "...the begin time of the interval is included in the interval, but the end
+// time is excluded from the interval."
+// (https://www.w3.org/TR/SMIL3/smil-timing.html#q101)
struct SMILInterval {
DISALLOW_NEW();
- SMILInterval() = default;
- SMILInterval(const SMILTime& begin, const SMILTime& end)
+ constexpr SMILInterval(const SMILTime& begin, const SMILTime& end)
: begin(begin), end(end) {}
+ static constexpr SMILInterval Unresolved() {
+ return {SMILTime::Unresolved(), SMILTime::Unresolved()};
+ }
+
+ bool IsResolved() const { return begin.IsFinite(); }
+ bool BeginsAfter(SMILTime time) const { return time < begin; }
+ bool BeginsBefore(SMILTime time) const { return !BeginsAfter(time); }
+ bool EndsAfter(SMILTime time) const {
+ DCHECK(IsResolved());
+ return time < end;
+ }
+ bool EndsBefore(SMILTime time) const { return !EndsAfter(time); }
+ bool Contains(SMILTime time) const {
+ return BeginsBefore(time) && EndsAfter(time);
+ }
+
SMILTime begin;
SMILTime end;
};
-inline bool operator==(const SMILTime& a, const SMILTime& b) {
- return (a.IsUnresolved() && b.IsUnresolved()) || a.Value() == b.Value();
-}
-inline bool operator!(const SMILTime& a) {
- return !a.IsFinite() || !a.Value();
-}
-inline bool operator!=(const SMILTime& a, const SMILTime& b) {
- return !operator==(a, b);
-}
-
-// Ordering of SMILTimes has to follow: finite < indefinite (Inf) < unresolved
-// (NaN). The first comparison is handled by IEEE754 but NaN values must be
-// checked explicitly to guarantee that unresolved is ordered correctly too.
-inline bool operator>(const SMILTime& a, const SMILTime& b) {
- return a.IsUnresolved() || (a.Value() > b.Value());
-}
-inline bool operator<(const SMILTime& a, const SMILTime& b) {
- return operator>(b, a);
-}
-inline bool operator>=(const SMILTime& a, const SMILTime& b) {
- return operator>(a, b) || operator==(a, b);
-}
-inline bool operator<=(const SMILTime& a, const SMILTime& b) {
- return operator<(a, b) || operator==(a, b);
-}
-inline bool operator<(const SMILTimeWithOrigin& a,
- const SMILTimeWithOrigin& b) {
- return a.Time() < b.Time();
+inline bool operator==(const SMILInterval& a, const SMILInterval& b) {
+ return a.begin == b.begin && a.end == b.end;
}
-inline SMILTime operator+(const SMILTime& a, const SMILTime& b) {
- return a.Value() + b.Value();
-}
-inline SMILTime operator-(const SMILTime& a, const SMILTime& b) {
- return a.Value() - b.Value();
-}
-// So multiplying times does not make too much sense but SMIL defines it for
-// duration * repeatCount
-SMILTime operator*(const SMILTime&, const SMILTime&);
-
inline bool operator!=(const SMILInterval& a, const SMILInterval& b) {
- // Compare the "raw" values since the operator!= for SMILTime always return
- // true for non-finite times.
- return a.begin.Value() != b.begin.Value() || a.end.Value() != b.end.Value();
+ return !(a == b);
}
-struct SMILTimeHash {
- STATIC_ONLY(SMILTimeHash);
- static unsigned GetHash(const SMILTime& key) {
- return WTF::FloatHash<double>::GetHash(key.Value());
- }
- static bool Equal(const SMILTime& a, const SMILTime& b) {
- return WTF::FloatHash<double>::Equal(a.Value(), b.Value());
- }
- static const bool safe_to_compare_to_empty_or_deleted = true;
-};
-
} // namespace blink
-namespace WTF {
-
-template <>
-struct DefaultHash<blink::SMILTime> {
- typedef blink::SMILTimeHash Hash;
-};
-
-template <>
-struct HashTraits<blink::SMILTime> : GenericHashTraits<blink::SMILTime> {
- static blink::SMILTime EmptyValue() { return blink::SMILTime::Unresolved(); }
- static void ConstructDeletedValue(blink::SMILTime& slot, bool) {
- slot = -std::numeric_limits<double>::infinity();
- }
- static bool IsDeletedValue(blink::SMILTime value) {
- return value == -std::numeric_limits<double>::infinity();
- }
-};
-
-} // namespace WTF
-
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_H_
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
index adb44a842ad..703ab57894c 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
@@ -40,18 +40,35 @@
namespace blink {
+class ScheduledAnimationsMutationsForbidden {
+ STACK_ALLOCATED();
+
+ public:
+ explicit ScheduledAnimationsMutationsForbidden(
+ SMILTimeContainer* time_container)
+#if DCHECK_IS_ON()
+ : flag_reset_(&time_container->prevent_scheduled_animations_changes_,
+ true)
+#endif
+ {
+ }
+
+ private:
+#if DCHECK_IS_ON()
+ base::AutoReset<bool> flag_reset_;
+#endif
+};
+
static constexpr base::TimeDelta kAnimationPolicyOnceDuration =
base::TimeDelta::FromSeconds(3);
SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner)
- : presentation_time_(0),
- reference_time_(0),
- latest_update_time_(0),
- frame_scheduling_state_(kIdle),
+ : frame_scheduling_state_(kIdle),
started_(false),
paused_(false),
document_order_indexes_dirty_(false),
intervals_dirty_(true),
+ is_updating_intervals_(false),
wakeup_timer_(
owner.GetDocument().GetTaskRunner(TaskType::kInternalDefault),
this,
@@ -66,9 +83,7 @@ SMILTimeContainer::~SMILTimeContainer() {
CancelAnimationFrame();
CancelAnimationPolicyTimer();
DCHECK(!wakeup_timer_.IsActive());
-#if DCHECK_IS_ON()
- DCHECK(!prevent_scheduled_animations_changes_);
-#endif
+ DCHECK(ScheduledAnimationsMutationsAllowed());
}
void SMILTimeContainer::Schedule(SVGSMILElement* animation,
@@ -77,10 +92,7 @@ void SMILTimeContainer::Schedule(SVGSMILElement* animation,
DCHECK_EQ(animation->TimeContainer(), this);
DCHECK(target);
DCHECK(animation->HasValidTarget());
-
-#if DCHECK_IS_ON()
- DCHECK(!prevent_scheduled_animations_changes_);
-#endif
+ DCHECK(ScheduledAnimationsMutationsAllowed());
// Separate out Discard and AnimateMotion
QualifiedName name = (animation->HasTagName(svg_names::kAnimateMotionTag) ||
@@ -95,20 +107,13 @@ void SMILTimeContainer::Schedule(SVGSMILElement* animation,
sandwich = MakeGarbageCollected<SMILAnimationSandwich>();
sandwich->Schedule(animation);
-
- SMILTime next_fire_time = animation->NextProgressTime();
- if (next_fire_time.IsFinite())
- NotifyIntervalsChanged();
}
void SMILTimeContainer::Unschedule(SVGSMILElement* animation,
SVGElement* target,
const QualifiedName& attribute_name) {
DCHECK_EQ(animation->TimeContainer(), this);
-
-#if DCHECK_IS_ON()
- DCHECK(!prevent_scheduled_animations_changes_);
-#endif
+ DCHECK(ScheduledAnimationsMutationsAllowed());
// Separate out Discard and AnimateMotion
QualifiedName name = (animation->HasTagName(svg_names::kAnimateMotionTag) ||
@@ -136,32 +141,38 @@ bool SMILTimeContainer::HasPendingSynchronization() const {
wakeup_timer_.IsActive() && wakeup_timer_.NextFireInterval().is_zero();
}
-void SMILTimeContainer::NotifyIntervalsChanged() {
- intervals_dirty_ = true;
+void SMILTimeContainer::ScheduleIntervalUpdate() {
+ // We're inside a call to UpdateIntervals() (or resetting the timeline), so
+ // we don't need to request an update - that will happen after the regular
+ // update has finished (if needed).
+ if (is_updating_intervals_)
+ return;
if (!IsStarted())
return;
- // Schedule updateAnimations() to be called asynchronously so multiple
- // intervals can change with updateAnimations() only called once at the end.
+ // Schedule UpdateAnimations...() to be called asynchronously so multiple
+ // intervals can change with UpdateAnimations...() only called once at the
+ // end.
if (HasPendingSynchronization())
return;
CancelAnimationFrame();
- ScheduleWakeUp(0, kSynchronizeAnimations);
+ ScheduleWakeUp(base::TimeDelta(), kSynchronizeAnimations);
}
-double SMILTimeContainer::Elapsed() const {
+SMILTime SMILTimeContainer::Elapsed() const {
if (!IsStarted())
- return 0;
+ return SMILTime();
if (IsPaused())
return presentation_time_;
- double elapsed = presentation_time_ + (GetDocument()
- .Timeline()
- .CurrentTimeInternal()
- .value_or(base::TimeDelta())
- .InSecondsF() -
- reference_time_);
- DCHECK_GE(elapsed, 0.0);
+ base::TimeDelta time_offset =
+ GetDocument().Timeline().CurrentTimeInternal().value_or(
+ base::TimeDelta()) -
+ reference_time_;
+ DCHECK_GE(time_offset, base::TimeDelta());
+ SMILTime elapsed = presentation_time_ +
+ SMILTime::FromMicroseconds(time_offset.InMicroseconds());
+ DCHECK_GE(elapsed, SMILTime());
return elapsed;
}
@@ -179,16 +190,13 @@ void SMILTimeContainer::ResetDocumentTime() {
SynchronizeToDocumentTimeline();
}
-double SMILTimeContainer::CurrentDocumentTime() const {
+SMILTime SMILTimeContainer::CurrentDocumentTime() const {
return latest_update_time_;
}
void SMILTimeContainer::SynchronizeToDocumentTimeline() {
- reference_time_ = GetDocument()
- .Timeline()
- .CurrentTimeInternal()
- .value_or(base::TimeDelta())
- .InSecondsF();
+ reference_time_ = GetDocument().Timeline().CurrentTimeInternal().value_or(
+ base::TimeDelta());
}
bool SMILTimeContainer::IsPaused() const {
@@ -245,13 +253,16 @@ void SMILTimeContainer::Unpause() {
return;
SynchronizeToDocumentTimeline();
- ScheduleWakeUp(0, kSynchronizeAnimations);
+ ScheduleWakeUp(base::TimeDelta(), kSynchronizeAnimations);
}
-void SMILTimeContainer::SetElapsed(double elapsed) {
+void SMILTimeContainer::SetElapsed(SMILTime elapsed) {
presentation_time_ = elapsed;
- // If the document hasn't finished loading, |m_presentationTime| will be
+ if (!GetDocument().IsActive())
+ return;
+
+ // If the document hasn't finished loading, |presentation_time_| will be
// used as the start time to seek to once it's possible.
if (!IsStarted())
return;
@@ -264,30 +275,35 @@ void SMILTimeContainer::SetElapsed(double elapsed) {
if (!IsPaused())
SynchronizeToDocumentTimeline();
-#if DCHECK_IS_ON()
- prevent_scheduled_animations_changes_ = true;
-#endif
- for (const auto& sandwich : scheduled_animations_) {
- sandwich.value->Reset();
+ // If we are rewinding the timeline, we need to start from 0 and then move
+ // forward to the new presentation time. If we're moving forward we can just
+ // perform the update in the normal fashion.
+ if (elapsed < latest_update_time_) {
+ base::AutoReset<bool> updating_intervals_scope(&is_updating_intervals_,
+ true);
+ ScheduledAnimationsMutationsForbidden scope(this);
+ for (auto& sandwich : scheduled_animations_.Values())
+ sandwich->Reset();
+
+ latest_update_time_ = SMILTime();
}
-#if DCHECK_IS_ON()
- prevent_scheduled_animations_changes_ = false;
-#endif
+ // We need to set this to make sure we update the active state of the timed
+ // elements.
intervals_dirty_ = true;
- latest_update_time_ = 0;
UpdateAnimationsAndScheduleFrameIfNeeded(elapsed);
}
-void SMILTimeContainer::ScheduleAnimationFrame(double delay_time) {
- DCHECK(std::isfinite(delay_time));
+void SMILTimeContainer::ScheduleAnimationFrame(base::TimeDelta delay_time) {
DCHECK(IsTimelineRunning());
DCHECK(!wakeup_timer_.IsActive());
+ DCHECK(GetDocument().IsActive());
- if (delay_time < DocumentTimeline::kMinimumDelay) {
+ const base::TimeDelta kLocalMinimumDelay =
+ base::TimeDelta::FromSecondsD(DocumentTimeline::kMinimumDelay);
+ if (delay_time < kLocalMinimumDelay) {
ServiceOnNextFrame();
} else {
- ScheduleWakeUp(delay_time - DocumentTimeline::kMinimumDelay,
- kFutureAnimationFrame);
+ ScheduleWakeUp(delay_time - kLocalMinimumDelay, kFutureAnimationFrame);
}
}
@@ -297,24 +313,28 @@ void SMILTimeContainer::CancelAnimationFrame() {
}
void SMILTimeContainer::ScheduleWakeUp(
- double delay_time,
+ base::TimeDelta delay_time,
FrameSchedulingState frame_scheduling_state) {
DCHECK(frame_scheduling_state == kSynchronizeAnimations ||
frame_scheduling_state == kFutureAnimationFrame);
- wakeup_timer_.StartOneShot(base::TimeDelta::FromSecondsD(delay_time),
- FROM_HERE);
+ wakeup_timer_.StartOneShot(delay_time, FROM_HERE);
frame_scheduling_state_ = frame_scheduling_state;
}
void SMILTimeContainer::WakeupTimerFired(TimerBase*) {
DCHECK(frame_scheduling_state_ == kSynchronizeAnimations ||
frame_scheduling_state_ == kFutureAnimationFrame);
- if (frame_scheduling_state_ == kFutureAnimationFrame) {
+ FrameSchedulingState previous_frame_scheduling_state =
+ frame_scheduling_state_;
+ frame_scheduling_state_ = kIdle;
+ // TODO(fs): The timeline should not be running if we're in an inactive
+ // document, so this should be turned into a DCHECK.
+ if (!GetDocument().IsActive())
+ return;
+ if (previous_frame_scheduling_state == kFutureAnimationFrame) {
DCHECK(IsTimelineRunning());
- frame_scheduling_state_ = kIdle;
ServiceOnNextFrame();
} else {
- frame_scheduling_state_ = kIdle;
UpdateAnimationsAndScheduleFrameIfNeeded(Elapsed());
}
}
@@ -399,8 +419,11 @@ void SMILTimeContainer::ServiceOnNextFrame() {
void SMILTimeContainer::ServiceAnimations() {
if (frame_scheduling_state_ != kAnimationFrame)
return;
-
frame_scheduling_state_ = kIdle;
+ // TODO(fs): The timeline should not be running if we're in an inactive
+ // document, so this should be turned into a DCHECK.
+ if (!GetDocument().IsActive())
+ return;
UpdateAnimationsAndScheduleFrameIfNeeded(Elapsed());
}
@@ -415,39 +438,42 @@ bool SMILTimeContainer::CanScheduleFrame(SMILTime earliest_fire_time) const {
}
void SMILTimeContainer::UpdateAnimationsAndScheduleFrameIfNeeded(
- double elapsed) {
- if (!GetDocument().IsActive())
- return;
+ SMILTime elapsed) {
+ DCHECK(GetDocument().IsActive());
+ DCHECK(!wakeup_timer_.IsActive());
UpdateAnimationTimings(elapsed);
ApplyAnimationValues(elapsed);
- SMILTime earliest_fire_time = SMILTime::Unresolved();
- for (auto& sandwich : scheduled_animations_) {
- SMILTime next_fire_time = sandwich.value->GetNextFireTime();
- if (next_fire_time.IsFinite())
- earliest_fire_time = std::min(next_fire_time, earliest_fire_time);
+ SMILTime next_progress_time = SMILTime::Unresolved();
+ for (auto& sandwich : scheduled_animations_.Values()) {
+ next_progress_time =
+ std::min(next_progress_time, sandwich->NextProgressTime(elapsed));
+ if (next_progress_time <= elapsed)
+ break;
}
+ DCHECK(!wakeup_timer_.IsActive());
- if (!CanScheduleFrame(earliest_fire_time))
+ if (!CanScheduleFrame(next_progress_time))
return;
- double delay_time = earliest_fire_time.Value() - elapsed;
- ScheduleAnimationFrame(delay_time);
+ SMILTime delay_time = next_progress_time - elapsed;
+ DCHECK(delay_time.IsFinite());
+ ScheduleAnimationFrame(
+ base::TimeDelta::FromMicroseconds(delay_time.InMicroseconds()));
}
// A helper function to fetch the next interesting time after document_time
-SMILTime SMILTimeContainer::NextInterestingTime(SMILTime document_time) const {
- DCHECK(document_time.IsFinite());
- DCHECK(document_time >= 0.0);
- SMILTime next_interesting_time = SMILTime::Indefinite();
- for (const auto& entry : scheduled_animations_) {
- const auto* sandwich = entry.value.Get();
- SMILTime interesting_time = sandwich->NextInterestingTime(document_time);
- next_interesting_time = std::min(next_interesting_time, interesting_time);
+SMILTime SMILTimeContainer::NextIntervalTime(SMILTime presentation_time) const {
+ DCHECK_GE(presentation_time, SMILTime());
+ SMILTime next_interval_time = SMILTime::Indefinite();
+ for (const auto& sandwich : scheduled_animations_) {
+ next_interval_time =
+ std::min(next_interval_time,
+ sandwich.value->NextIntervalTime(presentation_time));
}
- DCHECK(!next_interesting_time.IsFinite() ||
- document_time < next_interesting_time);
- return next_interesting_time;
+ DCHECK(!next_interval_time.IsFinite() ||
+ presentation_time < next_interval_time);
+ return next_interval_time;
}
void SMILTimeContainer::RemoveUnusedKeys() {
@@ -461,88 +487,69 @@ void SMILTimeContainer::RemoveUnusedKeys() {
}
void SMILTimeContainer::UpdateIntervals(SMILTime document_time) {
- // This Shrink should free up the memory from the previous
- // run in this loop. Otherwise it won't do anything.
DCHECK(document_time.IsFinite());
- DCHECK(document_time >= 0.0);
+ DCHECK_GE(document_time, SMILTime());
+
+ base::AutoReset<bool> updating_intervals_scope(&is_updating_intervals_, true);
do {
intervals_dirty_ = false;
- active_sandwiches_.Shrink(0);
- for (auto& entry : scheduled_animations_) {
- auto* sandwich = entry.value.Get();
- sandwich->UpdateTiming(document_time.Value());
- if (!sandwich->IsEmpty()) {
- active_sandwiches_.push_back(sandwich);
- }
- }
+ for (auto& sandwich : scheduled_animations_.Values())
+ sandwich->UpdateTiming(document_time);
- for (auto& sandwich : active_sandwiches_)
- sandwich->UpdateSyncBases(document_time.Value());
+ for (auto& sandwich : scheduled_animations_.Values())
+ sandwich->UpdateActiveStateAndOrder(document_time);
} while (intervals_dirty_);
}
-void SMILTimeContainer::UpdateAnimationTimings(SMILTime elapsed) {
+void SMILTimeContainer::UpdateAnimationTimings(SMILTime presentation_time) {
DCHECK(GetDocument().IsActive());
-#if DCHECK_IS_ON()
- // This boolean will catch any attempts to schedule/unschedule
- // scheduledAnimations during this critical section. Similarly, any elements
- // removed will unschedule themselves, so this will catch modification of
- // animationsToApply.
- base::AutoReset<bool> no_scheduled_animations_change_scope(
- &prevent_scheduled_animations_changes_, true);
-#endif
+ ScheduledAnimationsMutationsForbidden scope(this);
if (document_order_indexes_dirty_)
UpdateDocumentOrderIndexes();
RemoveUnusedKeys();
- // Don't update if it's a duplicate.
- if (elapsed == latest_update_time_ && elapsed != 0.0) {
- return;
- }
-
if (intervals_dirty_)
UpdateIntervals(latest_update_time_);
- active_sandwiches_.ReserveCapacity(scheduled_animations_.size());
- while (latest_update_time_ < elapsed) {
- const SMILTime interesting_time = NextInterestingTime(latest_update_time_);
- latest_update_time_ = std::min(elapsed, interesting_time).Value();
-
- UpdateIntervals(latest_update_time_);
+ while (latest_update_time_ < presentation_time) {
+ const SMILTime interval_time = NextIntervalTime(latest_update_time_);
+ if (interval_time <= presentation_time) {
+ latest_update_time_ = interval_time;
+ UpdateIntervals(latest_update_time_);
+ } else {
+ latest_update_time_ = presentation_time;
+ }
}
}
-void SMILTimeContainer::ApplyAnimationValues(double elapsed) {
-#if DCHECK_IS_ON()
- prevent_scheduled_animations_changes_ = true;
-#endif
+void SMILTimeContainer::ApplyAnimationValues(SMILTime elapsed) {
HeapVector<Member<SVGSMILElement>> animations_to_apply;
- for (auto& sandwich : active_sandwiches_) {
- if (SVGSMILElement* animation = sandwich->ApplyAnimationValues())
- animations_to_apply.push_back(animation);
+ {
+ ScheduledAnimationsMutationsForbidden scope(this);
+ for (auto& sandwich : scheduled_animations_.Values()) {
+ sandwich->UpdateActiveAnimationStack(elapsed);
+ if (SVGSMILElement* animation = sandwich->ApplyAnimationValues())
+ animations_to_apply.push_back(animation);
+ }
}
- active_sandwiches_.Shrink(0);
- if (animations_to_apply.IsEmpty()) {
-#if DCHECK_IS_ON()
- prevent_scheduled_animations_changes_ = false;
-#endif
+ if (animations_to_apply.IsEmpty())
return;
- }
// Everything bellow handles "discard" elements.
UseCounter::Count(&GetDocument(), WebFeature::kSVGSMILAnimationAppliedEffect);
- std::sort(animations_to_apply.begin(), animations_to_apply.end(),
- PriorityCompare(elapsed));
-
-#if DCHECK_IS_ON()
- prevent_scheduled_animations_changes_ = false;
-#endif
+ // Sort by location in the document. (Should be based on the target rather
+ // than the timed element, but often enough they will order the same.)
+ std::sort(
+ animations_to_apply.begin(), animations_to_apply.end(),
+ [](const Member<SVGSMILElement>& a, const Member<SVGSMILElement>& b) {
+ return a->DocumentOrderIndex() < b->DocumentOrderIndex();
+ });
for (const auto& timed_element : animations_to_apply) {
if (timed_element->isConnected() && timed_element->IsSVGDiscardElement()) {
@@ -564,14 +571,13 @@ void SMILTimeContainer::ApplyAnimationValues(double elapsed) {
}
void SMILTimeContainer::AdvanceFrameForTesting() {
- const double kInitialFrameDelay = 0.025;
- SetElapsed(Elapsed() + kInitialFrameDelay);
+ const SMILTime kFrameDuration = SMILTime::FromSecondsD(0.025);
+ SetElapsed(Elapsed() + kFrameDuration);
}
void SMILTimeContainer::Trace(blink::Visitor* visitor) {
visitor->Trace(scheduled_animations_);
visitor->Trace(owner_svg_element_);
- visitor->Trace(active_sandwiches_);
}
} // namespace blink
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 b29d061cb22..f735bcdebe0 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
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_CONTAINER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_CONTAINER_H_
+#include "base/time/time.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h"
#include "third_party/blink/renderer/platform/graphics/image_animation_policy.h"
@@ -43,7 +44,7 @@ class SMILTime;
class SVGElement;
class SVGSVGElement;
-class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
+class SMILTimeContainer final : public GarbageCollected<SMILTimeContainer> {
public:
// Sorted list
using AnimationId = std::pair<WeakMember<SVGElement>, QualifiedName>;
@@ -54,12 +55,14 @@ class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
void Schedule(SVGSMILElement*, SVGElement*, const QualifiedName&);
void Unschedule(SVGSMILElement*, SVGElement*, const QualifiedName&);
- void NotifyIntervalsChanged();
+
+ void MarkIntervalsDirty() { intervals_dirty_ = true; }
+ void ScheduleIntervalUpdate();
// Returns the time we are currently updating.
- double Elapsed() const;
+ SMILTime Elapsed() const;
// Returns the current time in the document.
- double CurrentDocumentTime() const;
+ SMILTime CurrentDocumentTime() const;
bool IsPaused() const;
bool IsStarted() const;
@@ -67,7 +70,7 @@ class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
void Start();
void Pause();
void Unpause();
- void SetElapsed(double);
+ void SetElapsed(SMILTime);
void ServiceAnimations();
bool HasAnimations() const;
@@ -103,7 +106,7 @@ class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
bool IsTimelineRunning() const;
void SynchronizeToDocumentTimeline();
- void ScheduleAnimationFrame(double delay_time);
+ void ScheduleAnimationFrame(base::TimeDelta delay_time);
void CancelAnimationFrame();
void WakeupTimerFired(TimerBase*);
void ScheduleAnimationPolicyTimer();
@@ -112,14 +115,14 @@ class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
ImageAnimationPolicy AnimationPolicy() const;
bool HandleAnimationPolicy(AnimationPolicyOnceAction);
bool CanScheduleFrame(SMILTime earliest_fire_time) const;
- void UpdateAnimationsAndScheduleFrameIfNeeded(double elapsed);
+ void UpdateAnimationsAndScheduleFrameIfNeeded(SMILTime elapsed);
void RemoveUnusedKeys();
void UpdateIntervals(SMILTime);
- SMILTime NextInterestingTime(SMILTime) const;
+ SMILTime NextIntervalTime(SMILTime elapsed) const;
void UpdateAnimationTimings(SMILTime elapsed);
- void ApplyAnimationValues(double elapsed);
+ void ApplyAnimationValues(SMILTime elapsed);
void ServiceOnNextFrame();
- void ScheduleWakeUp(double delay_time, FrameSchedulingState);
+ void ScheduleWakeUp(base::TimeDelta delay_time, FrameSchedulingState);
bool HasPendingSynchronization() const;
void UpdateDocumentOrderIndexes();
@@ -129,31 +132,43 @@ class SMILTimeContainer : public GarbageCollectedFinalized<SMILTimeContainer> {
// The latest "restart" time for the time container's timeline. If the
// timeline has not been manipulated (seeked, paused) this will be zero.
- double presentation_time_;
- // The time on the document timeline corresponding to |m_presentationTime|.
- double reference_time_;
- // The state all svg_smil_elements should be at.
- double latest_update_time_;
+ SMILTime presentation_time_;
+ // The state all SVGSMILElements should be at.
+ SMILTime latest_update_time_;
+ // The time on the document timeline corresponding to |presentation_time_|.
+ base::TimeDelta reference_time_;
FrameSchedulingState frame_scheduling_state_;
- bool started_; // The timeline has been started.
- bool paused_; // The timeline is paused.
+ bool started_ : 1; // The timeline has been started.
+ bool paused_ : 1; // The timeline is paused.
- bool document_order_indexes_dirty_;
- bool intervals_dirty_;
+ bool document_order_indexes_dirty_ : 1;
+ bool intervals_dirty_ : 1;
+ bool is_updating_intervals_;
TaskRunnerTimer<SMILTimeContainer> wakeup_timer_;
TaskRunnerTimer<SMILTimeContainer> animation_policy_once_timer_;
AnimationsMap scheduled_animations_;
- HeapVector<Member<SMILAnimationSandwich>> active_sandwiches_;
Member<SVGSVGElement> owner_svg_element_;
#if DCHECK_IS_ON()
+ friend class ScheduledAnimationsMutationsForbidden;
+ // This boolean will catch any attempts to mutate (schedule/unschedule)
+ // |scheduled_animations_| when it is set to true.
bool prevent_scheduled_animations_changes_ = false;
#endif
+
+ bool ScheduledAnimationsMutationsAllowed() const {
+#if DCHECK_IS_ON()
+ return !prevent_scheduled_animations_changes_;
+#else
+ return true;
+#endif
+ }
};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SMIL_TIME_CONTAINER_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 e54e6d9b2fa..d21c530d1b1 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
@@ -27,6 +27,7 @@
#include <algorithm>
+#include "base/auto_reset.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -48,8 +49,25 @@
namespace blink {
+namespace {
+
+// Compute the next time an interval with a certain (non-zero) simple duration
+// will repeat, relative to a certain presentation time.
+SMILTime ComputeNextRepeatTime(SMILTime interval_begin,
+ SMILTime simple_duration,
+ SMILTime presentation_time) {
+ DCHECK(simple_duration);
+ DCHECK_LE(interval_begin, presentation_time);
+ SMILTime time_in_interval = presentation_time - interval_begin;
+ SMILTime time_until_next_repeat =
+ simple_duration - (time_in_interval % simple_duration);
+ return presentation_time + time_until_next_repeat;
+}
+
+} // namespace
+
// This is used for duration type time values that can't be negative.
-static const double kInvalidCachedTime = -1.;
+static constexpr SMILTime kInvalidCachedTime = SMILTime::Earliest();
class ConditionEventListener final : public NativeEventListener {
public:
@@ -57,11 +75,15 @@ class ConditionEventListener final : public NativeEventListener {
SVGSMILElement::Condition* condition)
: animation_(animation), condition_(condition) {}
- bool Matches(const EventListener& other) const override;
-
void DisconnectAnimation() { animation_ = nullptr; }
- void Invoke(ExecutionContext*, Event*) override;
+ void Invoke(ExecutionContext*, Event*) override {
+ if (!animation_)
+ return;
+ animation_->AddInstanceTimeAndUpdate(
+ condition_->GetBeginOrEnd(),
+ animation_->Elapsed() + condition_->Offset(), SMILTimeOrigin::kEvent);
+ }
void Trace(blink::Visitor* visitor) override {
visitor->Trace(animation_);
@@ -69,40 +91,11 @@ class ConditionEventListener final : public NativeEventListener {
NativeEventListener::Trace(visitor);
}
- bool IsConditionEventListener() const override { return true; }
-
private:
Member<SVGSMILElement> animation_;
Member<SVGSMILElement::Condition> condition_;
};
-template <>
-struct DowncastTraits<ConditionEventListener> {
- static bool AllowFrom(const EventListener& event_listener) {
- const NativeEventListener* native_event_listener =
- DynamicTo<NativeEventListener>(event_listener);
- return native_event_listener &&
- native_event_listener->IsConditionEventListener();
- }
-};
-
-bool ConditionEventListener::Matches(const EventListener& listener) const {
- if (const ConditionEventListener* condition_event_listener =
- DynamicTo<ConditionEventListener>(listener)) {
- return animation_ == condition_event_listener->animation_ &&
- condition_ == condition_event_listener->condition_;
- }
- return false;
-}
-
-void ConditionEventListener::Invoke(ExecutionContext*, Event* event) {
- if (!animation_)
- return;
- animation_->IntervalIsDirty();
- animation_->AddInstanceTime(condition_->GetBeginOrEnd(),
- animation_->Elapsed() + condition_->Offset());
-}
-
SVGSMILElement::Condition::Condition(Type type,
BeginOrEnd begin_or_end,
const AtomicString& base_id,
@@ -127,15 +120,14 @@ void SVGSMILElement::Condition::Trace(blink::Visitor* visitor) {
void SVGSMILElement::Condition::ConnectSyncBase(SVGSMILElement& timed_element) {
DCHECK(!base_id_.IsEmpty());
DCHECK_EQ(type_, kSyncBase);
+ DCHECK(!base_element_);
auto* svg_smil_element =
DynamicTo<SVGSMILElement>(SVGURIReference::ObserveTarget(
base_id_observer_, timed_element.GetTreeScope(), base_id_,
WTF::BindRepeating(&SVGSMILElement::BuildPendingResource,
WrapWeakPersistent(&timed_element))));
- if (!svg_smil_element) {
- base_element_ = nullptr;
+ if (!svg_smil_element)
return;
- }
base_element_ = svg_smil_element;
svg_smil_element->AddSyncBaseDependent(timed_element);
}
@@ -154,22 +146,21 @@ void SVGSMILElement::Condition::ConnectEventBase(
SVGSMILElement& timed_element) {
DCHECK_EQ(type_, kEventBase);
DCHECK(!base_element_);
- Element* target;
+ DCHECK(!event_listener_);
+ SVGElement* target;
if (base_id_.IsEmpty()) {
target = timed_element.targetElement();
} else {
- target = SVGURIReference::ObserveTarget(
+ target = DynamicTo<SVGElement>(SVGURIReference::ObserveTarget(
base_id_observer_, timed_element.GetTreeScope(), base_id_,
WTF::BindRepeating(&SVGSMILElement::BuildPendingResource,
- WrapWeakPersistent(&timed_element)));
+ WrapWeakPersistent(&timed_element))));
}
- auto* svg_element = DynamicTo<SVGElement>(target);
- if (!svg_element)
+ if (!target)
return;
- DCHECK(!event_listener_);
event_listener_ =
MakeGarbageCollected<ConditionEventListener>(&timed_element, this);
- base_element_ = svg_element;
+ base_element_ = target;
base_element_->addEventListener(name_, event_listener_, false);
timed_element.AddReferenceTo(base_element_);
}
@@ -191,27 +182,26 @@ SVGSMILElement::SVGSMILElement(const QualifiedName& tag_name, Document& doc)
SVGTests(this),
attribute_name_(AnyQName()),
target_element_(nullptr),
- sync_base_conditions_connected_(false),
+ conditions_connected_(false),
has_end_event_conditions_(false),
is_waiting_for_first_interval_(true),
is_scheduled_(false),
- interval_(SMILInterval(SMILTime::Unresolved(), SMILTime::Unresolved())),
- previous_interval_begin_(SMILTime::Unresolved()),
+ interval_(SMILInterval::Unresolved()),
+ previous_interval_(SMILInterval::Unresolved()),
+ next_interval_time_(SMILTime::Earliest()),
active_state_(kInactive),
restart_(kRestartAlways),
fill_(kFillRemove),
- last_percent_(0),
- last_repeat_(0),
- next_progress_time_(0),
+ last_progress_{0.0f, 0},
document_order_index_(0),
cached_dur_(kInvalidCachedTime),
cached_repeat_dur_(kInvalidCachedTime),
- cached_repeat_count_(kInvalidCachedTime),
+ cached_repeat_count_(SMILRepeatCount::Invalid()),
cached_min_(kInvalidCachedTime),
cached_max_(kInvalidCachedTime),
- interval_has_changed_(false) {
- ResolveFirstInterval();
-}
+ interval_has_changed_(false),
+ instance_lists_have_changed_(false),
+ is_notifying_dependents_(false) {}
SVGSMILElement::~SVGSMILElement() = default;
@@ -220,16 +210,9 @@ void SVGSMILElement::ClearResourceAndEventBaseReferences() {
RemoveAllOutgoingReferences();
}
-void SVGSMILElement::ClearConditions() {
- DisconnectSyncBaseConditions();
- DisconnectEventBaseConditions();
- conditions_.clear();
-}
-
void SVGSMILElement::BuildPendingResource() {
ClearResourceAndEventBaseReferences();
- DisconnectEventBaseConditions();
- DisconnectSyncBaseConditions();
+ DisconnectConditions();
if (!isConnected()) {
// Reset the target element if we are no longer in the document.
@@ -249,8 +232,7 @@ void SVGSMILElement::BuildPendingResource() {
if (svg_target && !svg_target->isConnected())
svg_target = nullptr;
- if (svg_target != targetElement())
- SetTargetElement(svg_target);
+ SetTargetElement(svg_target);
if (svg_target) {
// Register us with the target in the dependencies map. Any change of
@@ -258,30 +240,25 @@ void SVGSMILElement::BuildPendingResource() {
// react to it.
AddReferenceTo(svg_target);
}
- ConnectSyncBaseConditions();
- ConnectEventBaseConditions();
+ ConnectConditions();
}
-static inline void ClearTimesWithDynamicOrigins(
- Vector<SMILTimeWithOrigin>& time_list) {
+static inline void RemoveInstanceTimesWithOrigin(
+ Vector<SMILTimeWithOrigin>& time_list,
+ SMILTimeOrigin origin) {
for (int i = time_list.size() - 1; i >= 0; --i) {
- if (time_list[i].OriginIsScript())
+ if (time_list[i].Origin() == origin)
time_list.EraseAt(i);
}
}
void SVGSMILElement::Reset() {
- ClearAnimatedType();
-
active_state_ = kInactive;
is_waiting_for_first_interval_ = true;
- interval_.begin = SMILTime::Unresolved();
- interval_.end = SMILTime::Unresolved();
- previous_interval_begin_ = SMILTime::Unresolved();
- last_percent_ = 0;
- last_repeat_ = 0;
- next_progress_time_ = 0;
- ResolveFirstInterval();
+ interval_ = SMILInterval::Unresolved();
+ previous_interval_ = SMILInterval::Unresolved();
+ next_interval_time_ = SMILTime::Earliest();
+ last_progress_ = {0.0f, 0};
}
Node::InsertionNotificationRequest SVGSMILElement::InsertedInto(
@@ -307,17 +284,12 @@ Node::InsertionNotificationRequest SVGSMILElement::InsertedInto(
// "If no attribute is present, the default begin value (an offset-value of 0)
// must be evaluated."
- if (!FastHasAttribute(svg_names::kBeginAttr))
- begin_times_.push_back(SMILTimeWithOrigin());
-
- if (is_waiting_for_first_interval_)
- ResolveFirstInterval();
-
- if (time_container_)
- time_container_->NotifyIntervalsChanged();
+ if (!FastHasAttribute(svg_names::kBeginAttr) && begin_times_.IsEmpty()) {
+ begin_times_.push_back(
+ SMILTimeWithOrigin(SMILTime(), SMILTimeOrigin::kAttribute));
+ }
BuildPendingResource();
-
return kInsertionDone;
}
@@ -347,9 +319,9 @@ SMILTime SVGSMILElement::ParseOffsetValue(const String& data) {
result = parse.Left(parse.length() - 1).ToDouble(&ok);
else
result = parse.ToDouble(&ok);
- if (!ok || !SMILTime(result).IsFinite())
+ if (!ok)
return SMILTime::Unresolved();
- return result;
+ return SMILTime::FromSecondsD(result);
}
SMILTime SVGSMILElement::ParseClockValue(const String& data) {
@@ -380,37 +352,38 @@ SMILTime SVGSMILElement::ParseClockValue(const String& data) {
if (!ok)
return SMILTime::Unresolved();
result += parse.Substring(3).ToDouble(&ok);
- } else
+ } else {
return ParseOffsetValue(parse);
+ }
- if (!ok || !SMILTime(result).IsFinite())
+ if (!ok)
return SMILTime::Unresolved();
- return result;
+ return SMILTime::FromSecondsD(result);
}
bool SVGSMILElement::ParseCondition(const String& value,
BeginOrEnd begin_or_end) {
String parse_string = value.StripWhiteSpace();
- double sign = 1.;
+ bool is_negated = false;
bool ok;
wtf_size_t pos = parse_string.find('+');
if (pos == kNotFound) {
pos = parse_string.find('-');
- if (pos != kNotFound)
- sign = -1.;
+ is_negated = pos != kNotFound;
}
String condition_string;
- SMILTime offset = 0;
- if (pos == kNotFound)
+ SMILTime offset;
+ if (pos == kNotFound) {
condition_string = parse_string;
- else {
+ } else {
condition_string = parse_string.Left(pos).StripWhiteSpace();
String offset_string = parse_string.Substring(pos + 1).StripWhiteSpace();
offset = ParseOffsetValue(offset_string);
if (offset.IsUnresolved())
return false;
- offset = offset * sign;
+ if (is_negated)
+ offset = -offset;
}
if (condition_string.IsEmpty())
return false;
@@ -418,9 +391,9 @@ bool SVGSMILElement::ParseCondition(const String& value,
String base_id;
String name_string;
- if (pos == kNotFound)
+ if (pos == kNotFound) {
name_string = condition_string;
- else {
+ } else {
base_id = condition_string.Left(pos);
name_string = condition_string.Substring(pos + 1);
}
@@ -466,22 +439,29 @@ void SVGSMILElement::ParseBeginOrEnd(const String& parse_string,
begin_or_end == kBegin ? begin_times_ : end_times_;
if (begin_or_end == kEnd)
has_end_event_conditions_ = false;
- HashSet<SMILTime> existing;
- for (const auto& instance_time : time_list) {
- if (!instance_time.Time().IsUnresolved())
- existing.insert(instance_time.Time());
- }
+
+ // Remove any previously added offset-values.
+ // TODO(fs): Ought to remove instance times originating from sync-bases,
+ // events etc. as well if those conditions are no longer in the attribute.
+ RemoveInstanceTimesWithOrigin(time_list, SMILTimeOrigin::kAttribute);
+
Vector<String> split_string;
parse_string.Split(';', split_string);
for (const auto& item : split_string) {
SMILTime value = ParseClockValue(item);
if (value.IsUnresolved()) {
ParseCondition(item, begin_or_end);
- } else if (!existing.Contains(value)) {
+ } else {
time_list.push_back(
- SMILTimeWithOrigin(value, SMILTimeWithOrigin::kParserOrigin));
+ SMILTimeWithOrigin(value, SMILTimeOrigin::kAttribute));
}
}
+ // "If no attribute is present, the default begin value (an offset-value of 0)
+ // must be evaluated."
+ if (begin_or_end == kBegin && parse_string.IsNull()) {
+ begin_times_.push_back(
+ SMILTimeWithOrigin(SMILTime(), SMILTimeOrigin::kAttribute));
+ }
std::sort(time_list.begin(), time_list.end());
}
@@ -495,9 +475,13 @@ void SVGSMILElement::ParseAttribute(const AttributeModificationParams& params) {
}
ParseBeginOrEnd(value.GetString(), kBegin);
if (isConnected()) {
- ConnectSyncBaseConditions();
- ConnectEventBaseConditions();
- BeginListChanged(Elapsed());
+ ConnectConditions();
+ instance_lists_have_changed_ = true;
+ InstanceListChanged();
+ if (time_container_) {
+ time_container_->MarkIntervalsDirty();
+ time_container_->ScheduleIntervalUpdate();
+ }
}
AnimationAttributeChanged();
} else if (name == svg_names::kEndAttr) {
@@ -507,9 +491,13 @@ void SVGSMILElement::ParseAttribute(const AttributeModificationParams& params) {
}
ParseBeginOrEnd(value.GetString(), kEnd);
if (isConnected()) {
- ConnectSyncBaseConditions();
- ConnectEventBaseConditions();
- EndListChanged(Elapsed());
+ ConnectConditions();
+ instance_lists_have_changed_ = true;
+ InstanceListChanged();
+ if (time_container_) {
+ time_container_->MarkIntervalsDirty();
+ time_container_->ScheduleIntervalUpdate();
+ }
}
AnimationAttributeChanged();
} else if (name == svg_names::kOnbeginAttr) {
@@ -541,7 +529,7 @@ void SVGSMILElement::SvgAttributeChanged(const QualifiedName& attr_name) {
} else if (attr_name == svg_names::kRepeatDurAttr) {
cached_repeat_dur_ = kInvalidCachedTime;
} else if (attr_name == svg_names::kRepeatCountAttr) {
- cached_repeat_count_ = kInvalidCachedTime;
+ cached_repeat_count_ = SMILRepeatCount::Invalid();
} else if (attr_name == svg_names::kMinAttr) {
cached_min_ = kInvalidCachedTime;
} else if (attr_name == svg_names::kMaxAttr) {
@@ -560,68 +548,65 @@ void SVGSMILElement::SvgAttributeChanged(const QualifiedName& attr_name) {
AnimationAttributeChanged();
}
-void SVGSMILElement::ConnectSyncBaseConditions() {
- if (sync_base_conditions_connected_)
- DisconnectSyncBaseConditions();
- sync_base_conditions_connected_ = true;
+void SVGSMILElement::ConnectConditions() {
+ if (conditions_connected_)
+ DisconnectConditions();
for (Condition* condition : conditions_) {
if (condition->GetType() == Condition::kSyncBase)
condition->ConnectSyncBase(*this);
+ else if (condition->GetType() == Condition::kEventBase)
+ condition->ConnectEventBase(*this);
}
+ conditions_connected_ = true;
}
-void SVGSMILElement::DisconnectSyncBaseConditions() {
- if (!sync_base_conditions_connected_)
+void SVGSMILElement::DisconnectConditions() {
+ if (!conditions_connected_)
return;
- sync_base_conditions_connected_ = false;
for (Condition* condition : conditions_) {
if (condition->GetType() == Condition::kSyncBase)
condition->DisconnectSyncBase(*this);
+ else if (condition->GetType() == Condition::kEventBase)
+ condition->DisconnectEventBase(*this);
}
+ conditions_connected_ = false;
}
-void SVGSMILElement::ConnectEventBaseConditions() {
- DisconnectEventBaseConditions();
- for (Condition* condition : conditions_) {
- if (condition->GetType() == Condition::kEventBase)
- condition->ConnectEventBase(*this);
- }
-}
-
-void SVGSMILElement::DisconnectEventBaseConditions() {
- for (Condition* condition : conditions_) {
- if (condition->GetType() == Condition::kEventBase)
- condition->DisconnectEventBase(*this);
- }
+void SVGSMILElement::ClearConditions() {
+ DisconnectConditions();
+ conditions_.clear();
}
void SVGSMILElement::SetTargetElement(SVGElement* target) {
+ if (target == target_element_)
+ return;
WillChangeAnimationTarget();
-
- // Clear values that may depend on the previous target.
- if (target_element_)
- DisconnectSyncBaseConditions();
-
- // If the animation state is not Inactive, always reset to a clear state
- // before leaving the old target element.
- if (GetActiveState() != kInactive)
- EndedActiveInterval();
-
target_element_ = target;
DidChangeAnimationTarget();
-
- // If the animation is scheduled and there's an active interval, then
- // revalidate the animation value.
- if (GetActiveState() != kInactive && is_scheduled_)
- StartedActiveInterval();
}
SMILTime SVGSMILElement::Elapsed() const {
- return time_container_ ? time_container_->Elapsed() : 0;
+ return time_container_ ? time_container_->Elapsed() : SMILTime();
+}
+
+SMILTime SVGSMILElement::BeginTimeForPrioritization(
+ SMILTime presentation_time) const {
+ if (GetActiveState() == kFrozen) {
+ if (interval_.BeginsAfter(presentation_time))
+ return previous_interval_.begin;
+ }
+ return interval_.begin;
}
-bool SVGSMILElement::IsFrozen() const {
- return GetActiveState() == kFrozen;
+bool SVGSMILElement::IsHigherPriorityThan(const SVGSMILElement* other,
+ SMILTime presentation_time) const {
+ // FIXME: This should also consider possible timing relations between the
+ // elements.
+ SMILTime this_begin = BeginTimeForPrioritization(presentation_time);
+ SMILTime other_begin = other->BeginTimeForPrioritization(presentation_time);
+ if (this_begin == other_begin)
+ return DocumentOrderIndex() > other->DocumentOrderIndex();
+ return this_begin > other_begin;
}
SMILTime SVGSMILElement::Dur() const {
@@ -629,7 +614,8 @@ SMILTime SVGSMILElement::Dur() const {
return cached_dur_;
const AtomicString& value = FastGetAttribute(svg_names::kDurAttr);
SMILTime clock_value = ParseClockValue(value);
- return cached_dur_ = clock_value <= 0 ? SMILTime::Unresolved() : clock_value;
+ return cached_dur_ =
+ clock_value <= SMILTime() ? SMILTime::Unresolved() : clock_value;
}
SMILTime SVGSMILElement::RepeatDur() const {
@@ -637,28 +623,29 @@ SMILTime SVGSMILElement::RepeatDur() const {
return cached_repeat_dur_;
const AtomicString& value = FastGetAttribute(svg_names::kRepeatDurAttr);
SMILTime clock_value = ParseClockValue(value);
- cached_repeat_dur_ = clock_value <= 0 ? SMILTime::Unresolved() : clock_value;
+ cached_repeat_dur_ =
+ clock_value <= SMILTime() ? SMILTime::Unresolved() : clock_value;
return cached_repeat_dur_;
}
-// So a count is not really a time but let just all pretend we did not notice.
-SMILTime SVGSMILElement::RepeatCount() const {
- if (cached_repeat_count_ != kInvalidCachedTime)
- return cached_repeat_count_;
- SMILTime computed_repeat_count = SMILTime::Unresolved();
- const AtomicString& value = FastGetAttribute(svg_names::kRepeatCountAttr);
- if (!value.IsNull()) {
- DEFINE_STATIC_LOCAL(const AtomicString, indefinite_value, ("indefinite"));
- if (value == indefinite_value) {
- computed_repeat_count = SMILTime::Indefinite();
- } else {
- bool ok;
- double result = value.ToDouble(&ok);
- if (ok && result > 0)
- computed_repeat_count = result;
- }
+static SMILRepeatCount ParseRepeatCount(const AtomicString& value) {
+ if (value.IsNull())
+ return SMILRepeatCount::Unspecified();
+ if (value == "indefinite")
+ return SMILRepeatCount::Indefinite();
+ bool ok;
+ double result = value.ToDouble(&ok);
+ if (ok && result > 0)
+ return SMILRepeatCount::Numeric(result);
+ return SMILRepeatCount::Unspecified();
+}
+
+SMILRepeatCount SVGSMILElement::RepeatCount() const {
+ if (!cached_repeat_count_.IsValid()) {
+ cached_repeat_count_ =
+ ParseRepeatCount(FastGetAttribute(svg_names::kRepeatCountAttr));
}
- cached_repeat_count_ = computed_repeat_count;
+ DCHECK(cached_repeat_count_.IsValid());
return cached_repeat_count_;
}
@@ -667,7 +654,7 @@ SMILTime SVGSMILElement::MaxValue() const {
return cached_max_;
const AtomicString& value = FastGetAttribute(svg_names::kMaxAttr);
SMILTime result = ParseClockValue(value);
- return cached_max_ = (result.IsUnresolved() || result <= 0)
+ return cached_max_ = (result.IsUnresolved() || result <= SMILTime())
? SMILTime::Indefinite()
: result;
}
@@ -677,7 +664,9 @@ SMILTime SVGSMILElement::MinValue() const {
return cached_min_;
const AtomicString& value = FastGetAttribute(svg_names::kMinAttr);
SMILTime result = ParseClockValue(value);
- return cached_min_ = (result.IsUnresolved() || result < 0) ? 0 : result;
+ return cached_min_ = (result.IsUnresolved() || result < SMILTime())
+ ? SMILTime()
+ : result;
}
SMILTime SVGSMILElement::SimpleDuration() const {
@@ -693,7 +682,7 @@ static void InsertSortedAndUnique(Vector<SMILTimeWithOrigin>& list,
break;
// If they share both time and origin, we don't need to add it,
// we just need to react.
- if (position->HasSameOrigin(time))
+ if (position->Origin() == time.Origin())
return;
}
list.insert(position - list.begin(), time);
@@ -701,23 +690,27 @@ static void InsertSortedAndUnique(Vector<SMILTimeWithOrigin>& list,
void SVGSMILElement::AddInstanceTime(BeginOrEnd begin_or_end,
SMILTime time,
- SMILTimeWithOrigin::Origin origin) {
- SMILTime current_presentation_time =
- time_container_ ? time_container_->CurrentDocumentTime() : 0;
- DCHECK(!current_presentation_time.IsUnresolved());
- SMILTimeWithOrigin time_with_origin(time, origin);
+ SMILTimeOrigin origin) {
+ Vector<SMILTimeWithOrigin>& list =
+ begin_or_end == kBegin ? begin_times_ : end_times_;
+ InsertSortedAndUnique(list, SMILTimeWithOrigin(time, origin));
+ instance_lists_have_changed_ = true;
+}
+
+void SVGSMILElement::AddInstanceTimeAndUpdate(BeginOrEnd begin_or_end,
+ SMILTime time,
+ SMILTimeOrigin origin) {
// Ignore new instance times for 'end' if the element is not active
// and the origin is script.
if (begin_or_end == kEnd && GetActiveState() == kInactive &&
- time_with_origin.OriginIsScript())
+ origin == SMILTimeOrigin::kScript)
return;
- Vector<SMILTimeWithOrigin>& list =
- begin_or_end == kBegin ? begin_times_ : end_times_;
- InsertSortedAndUnique(list, time_with_origin);
- if (begin_or_end == kBegin)
- BeginListChanged(current_presentation_time);
- else
- EndListChanged(current_presentation_time);
+ AddInstanceTime(begin_or_end, time, origin);
+ InstanceListChanged();
+ if (time_container_) {
+ time_container_->MarkIntervalsDirty();
+ time_container_->ScheduleIntervalUpdate();
+ }
}
SMILTime SVGSMILElement::FindInstanceTime(BeginOrEnd begin_or_end,
@@ -753,26 +746,31 @@ SMILTime SVGSMILElement::FindInstanceTime(BeginOrEnd begin_or_end,
SMILTime SVGSMILElement::RepeatingDuration() const {
// Computing the active duration
// http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur
- SMILTime repeat_count = RepeatCount();
+ SMILRepeatCount repeat_count = RepeatCount();
SMILTime repeat_dur = RepeatDur();
SMILTime simple_duration = SimpleDuration();
if (!simple_duration ||
- (repeat_dur.IsUnresolved() && repeat_count.IsUnresolved()))
+ (repeat_dur.IsUnresolved() && repeat_count.IsUnspecified()))
return simple_duration;
repeat_dur = std::min(repeat_dur, SMILTime::Indefinite());
- SMILTime repeat_count_duration = simple_duration * repeat_count;
+ SMILTime repeat_count_duration = simple_duration.Repeat(repeat_count);
if (!repeat_count_duration.IsUnresolved())
return std::min(repeat_dur, repeat_count_duration);
return repeat_dur;
}
-SMILTime SVGSMILElement::ResolveActiveEnd(SMILTime resolved_begin,
- SMILTime resolved_end) const {
+SMILTime SVGSMILElement::ResolveActiveEnd(SMILTime resolved_begin) const {
+ SMILTime resolved_end = FindInstanceTime(kEnd, resolved_begin, false);
+ if (resolved_end.IsUnresolved()) {
+ // If we have no pending end conditions, don't generate a new interval.
+ if (!end_times_.IsEmpty() && !has_end_event_conditions_)
+ return SMILTime::Unresolved();
+ }
// Computing the active duration
// http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur
SMILTime preliminary_active_duration;
if (!resolved_end.IsUnresolved() && Dur().IsUnresolved() &&
- RepeatDur().IsUnresolved() && RepeatCount().IsUnresolved())
+ RepeatDur().IsUnresolved() && RepeatCount().IsUnspecified())
preliminary_active_duration = resolved_end - resolved_begin;
else if (!resolved_end.IsFinite())
preliminary_active_duration = RepeatingDuration();
@@ -785,252 +783,242 @@ SMILTime SVGSMILElement::ResolveActiveEnd(SMILTime resolved_begin,
if (min_value > max_value) {
// Ignore both.
// http://www.w3.org/TR/2001/REC-smil-animation-20010904/#MinMax
- min_value = 0;
+ min_value = SMILTime();
max_value = SMILTime::Indefinite();
}
return resolved_begin +
std::min(max_value, std::max(min_value, preliminary_active_duration));
}
-SMILInterval SVGSMILElement::ResolveInterval(
- IntervalSelector interval_selector) const {
- bool first = interval_selector == kFirstInterval;
- // See the pseudocode in http://www.w3.org/TR/SMIL3/smil-timing.html#q90.
- auto constexpr infinity = std::numeric_limits<double>::infinity();
- SMILTime begin_after = first ? -infinity : interval_.end;
- SMILTime last_interval_temp_end = infinity;
+SMILInterval SVGSMILElement::ResolveInterval(SMILTime begin_after,
+ SMILTime end_after) const {
+ // Simplified version of the pseudocode in
+ // http://www.w3.org/TR/SMIL3/smil-timing.html#q90.
while (true) {
- bool equals_minimum_ok = !first || interval_.end > interval_.begin;
- SMILTime temp_begin =
- FindInstanceTime(kBegin, begin_after, equals_minimum_ok);
+ SMILTime temp_begin = FindInstanceTime(kBegin, begin_after, true);
if (temp_begin.IsUnresolved())
break;
- SMILTime temp_end;
- if (end_times_.IsEmpty())
- temp_end = ResolveActiveEnd(temp_begin, SMILTime::Indefinite());
- else {
- temp_end = FindInstanceTime(kEnd, temp_begin, true);
- if ((first && temp_begin == temp_end &&
- temp_end == last_interval_temp_end) ||
- (!first && temp_end == interval_.end))
- temp_end = FindInstanceTime(kEnd, temp_begin, false);
- if (temp_end.IsUnresolved()) {
- if (!end_times_.IsEmpty() && !has_end_event_conditions_)
- break;
- }
- temp_end = ResolveActiveEnd(temp_begin, temp_end);
- }
- if (!first || (temp_end > 0 || (!temp_begin.Value() && !temp_end.Value())))
+ SMILTime temp_end = ResolveActiveEnd(temp_begin);
+ if (temp_end.IsUnresolved())
+ break;
+ // Don't allow the interval to end in the past.
+ if (temp_end > end_after) {
+ DCHECK(!temp_begin.IsIndefinite());
return SMILInterval(temp_begin, temp_end);
+ }
begin_after = temp_end;
- last_interval_temp_end = temp_end;
}
- return SMILInterval(SMILTime::Unresolved(), SMILTime::Unresolved());
+ return SMILInterval::Unresolved();
}
-void SVGSMILElement::ResolveFirstInterval() {
- SMILInterval first_interval = ResolveInterval(kFirstInterval);
- DCHECK(!first_interval.begin.IsIndefinite());
-
- if (!first_interval.begin.IsUnresolved() && first_interval != interval_) {
- interval_ = first_interval;
- NotifyDependentsIntervalChanged(interval_);
- next_progress_time_ = next_progress_time_.IsUnresolved()
- ? interval_.begin
- : std::min(next_progress_time_, interval_.begin);
+void SVGSMILElement::SetNewInterval(const SMILInterval& interval,
+ SMILTime presentation_time) {
+ interval_ = interval;
+ next_interval_time_ = ComputeNextIntervalTime(presentation_time);
+ NotifyDependentsOnNewInterval(interval_);
+}
- if (time_container_)
- time_container_->NotifyIntervalsChanged();
- }
+void SVGSMILElement::SetNewIntervalEnd(SMILTime new_end,
+ SMILTime presentation_time) {
+ interval_.end = new_end;
+ next_interval_time_ = ComputeNextIntervalTime(presentation_time);
+ NotifyDependentsOnNewInterval(interval_);
}
-base::Optional<SMILInterval> SVGSMILElement::ResolveNextInterval() {
- SMILInterval next_interval = ResolveInterval(kNextInterval);
- DCHECK(!next_interval.begin.IsIndefinite());
+SMILTime SVGSMILElement::NextIntervalTime(SMILTime presentation_time) const {
+ if (presentation_time < next_interval_time_)
+ return next_interval_time_;
+ return SMILTime::Unresolved();
+}
- if (!next_interval.begin.IsUnresolved() &&
- next_interval.begin != interval_.begin) {
- return next_interval;
+SMILTime SVGSMILElement::ComputeNextIntervalTime(
+ SMILTime presentation_time) const {
+ DCHECK_GE(presentation_time, SMILTime());
+ SMILTime next_interval_time = SMILTime::Unresolved();
+ if (interval_.BeginsAfter(presentation_time)) {
+ next_interval_time = interval_.begin;
+ } else if (interval_.EndsAfter(presentation_time)) {
+ if (SMILTime simple_duration = SimpleDuration()) {
+ SMILTime next_repeat_time = ComputeNextRepeatTime(
+ interval_.begin, simple_duration, presentation_time);
+ DCHECK(next_repeat_time.IsFinite());
+ next_interval_time = std::min(next_repeat_time, interval_.end);
+ } else {
+ next_interval_time = interval_.end;
+ }
}
-
- return base::nullopt;
+ return std::min(next_interval_time,
+ FindInstanceTime(kBegin, presentation_time, false));
}
-SMILTime SVGSMILElement::NextInterestingTime(SMILTime document_time) const {
- DCHECK(document_time.IsFinite());
- DCHECK(0.0 <= document_time);
- const double dt = document_time.Value();
- SMILTime next_interesting_interval_time = SMILTime::Indefinite();
- if (dt < interval_.begin) {
- next_interesting_interval_time = interval_.begin;
- } else if (dt < interval_.end) {
- next_interesting_interval_time = interval_.end;
- SMILTime simple_duration = SimpleDuration();
- if (simple_duration.IsFinite()) {
- unsigned next_repeat = CalculateAnimationRepeat(dt) + 1;
- SMILTime repeat_time = interval_.begin + simple_duration * next_repeat;
- if (repeat_time.IsFinite() && dt < repeat_time) {
- next_interesting_interval_time =
- std::min(next_interesting_interval_time, repeat_time);
- }
+void SVGSMILElement::InstanceListChanged() {
+ DCHECK(instance_lists_have_changed_);
+ SMILTime current_presentation_time =
+ time_container_ ? time_container_->CurrentDocumentTime() : SMILTime();
+ DCHECK(!current_presentation_time.IsUnresolved());
+ UpdateInterval(current_presentation_time);
+ if (interval_has_changed_) {
+ if (GetActiveState() == kActive &&
+ interval_.BeginsAfter(current_presentation_time)) {
+ active_state_ = DetermineActiveState(current_presentation_time);
+ if (GetActiveState() != kActive)
+ EndedActiveInterval();
}
+ interval_has_changed_ = false;
}
- // TODO(edvardt): This is a vile hack.
- // Removing 0.5ms, which is less than the minimum precision time.
- //
- // Removing this will break most repeatn-* tests, and
- // most tests with onmouse syncbases. These are a few:
- // svg/animations/reapeatn-*
- // external/wpt/svg/animations/scripted/onhover-syncbases.html
- // external/wpt/svg/animations/slider-switch.html
- // These break because the updates land ON THE SAME TIMES as the
- // instance times. And the animation cannot then get a new interval
- // from that instance time.
- const float half_ms = 0.0005;
- const SMILTime instance_time = FindInstanceTime(kBegin, dt, false) - half_ms;
- if (dt < instance_time) {
- return std::min(next_interesting_interval_time, instance_time);
- }
- return next_interesting_interval_time;
-}
-
-SMILTime SVGSMILElement::NextProgressTime() const {
- return next_progress_time_;
-}
-
-void SVGSMILElement::BeginListChanged(SMILTime event_time) {
- if (is_waiting_for_first_interval_) {
- ResolveFirstInterval();
- } else if (GetRestart() != kRestartNever) {
- SMILTime new_begin = FindInstanceTime(kBegin, event_time, true);
- if (new_begin.IsFinite() &&
- (interval_.end <= event_time || new_begin < interval_.begin)) {
- // Begin time changed, re-resolve the interval.
- SMILTime old_begin = interval_.begin;
- interval_.end = event_time;
- interval_ = ResolveInterval(kNextInterval);
- DCHECK(!interval_.begin.IsUnresolved());
- if (interval_.begin != old_begin) {
- if (GetActiveState() == kActive && interval_.begin > event_time) {
- active_state_ = DetermineActiveState(event_time);
- if (GetActiveState() != kActive)
- EndedActiveInterval();
- }
- NotifyDependentsIntervalChanged(interval_);
- }
- }
+}
+
+void SVGSMILElement::DiscardOrRevalidateCurrentInterval(
+ SMILTime presentation_time) {
+ if (!interval_.IsResolved())
+ return;
+ // If the current interval has not yet started, discard it and re-resolve.
+ if (interval_.BeginsAfter(presentation_time)) {
+ interval_ = SMILInterval::Unresolved();
+ return;
}
- next_progress_time_ = Elapsed();
- if (time_container_)
- time_container_->NotifyIntervalsChanged();
-}
-
-void SVGSMILElement::EndListChanged(SMILTime) {
- SMILTime elapsed = Elapsed();
- if (is_waiting_for_first_interval_) {
- ResolveFirstInterval();
- } else if (elapsed < interval_.end && interval_.begin.IsFinite()) {
- SMILTime new_end = FindInstanceTime(kEnd, interval_.begin, false);
- if (new_end < interval_.end) {
- new_end = ResolveActiveEnd(interval_.begin, new_end);
- if (new_end != interval_.end) {
- interval_.end = new_end;
- NotifyDependentsIntervalChanged(interval_);
- }
+ // If we have a current interval but it has not yet ended, re-resolve the
+ // end time.
+ if (interval_.EndsAfter(presentation_time)) {
+ SMILTime new_end = ResolveActiveEnd(interval_.begin);
+ if (new_end.IsUnresolved()) {
+ // No active duration, discard the current interval.
+ interval_ = SMILInterval::Unresolved();
+ return;
}
+ if (new_end != interval_.end)
+ SetNewIntervalEnd(new_end, presentation_time);
}
- next_progress_time_ = elapsed;
-
- if (time_container_)
- time_container_->NotifyIntervalsChanged();
}
-base::Optional<SMILInterval> SVGSMILElement::CheckForNewRestartInterval(
- double elapsed) {
- DCHECK(!is_waiting_for_first_interval_);
- DCHECK(elapsed >= interval_.begin);
-
+bool SVGSMILElement::HandleIntervalRestart(SMILTime presentation_time) {
Restart restart = GetRestart();
- if (restart == kRestartNever)
- return base::nullopt;
-
- base::Optional<SMILInterval> modified;
- if (elapsed < interval_.end && restart == kRestartAlways) {
+ if (!is_waiting_for_first_interval_ && restart == kRestartNever)
+ return false;
+ if (!interval_.IsResolved() || interval_.EndsBefore(presentation_time))
+ return true;
+ if (restart == kRestartAlways) {
SMILTime next_begin = FindInstanceTime(kBegin, interval_.begin, false);
- if (next_begin < interval_.end) {
- modified = interval_;
- modified->end = next_begin;
+ if (interval_.EndsAfter(next_begin)) {
+ SetNewIntervalEnd(next_begin, presentation_time);
+ return interval_.EndsBefore(presentation_time);
}
}
+ return false;
+}
- if ((modified && elapsed >= modified->end) ||
- (!modified && elapsed >= interval_.end)) {
- modified = ResolveNextInterval();
+void SVGSMILElement::UpdateInterval(SMILTime presentation_time) {
+ if (instance_lists_have_changed_) {
+ instance_lists_have_changed_ = false;
+ DiscardOrRevalidateCurrentInterval(presentation_time);
}
-
- return modified;
+ if (!HandleIntervalRestart(presentation_time))
+ return;
+ SMILTime begin_after =
+ !is_waiting_for_first_interval_ && interval_.IsResolved()
+ ? interval_.end
+ : SMILTime::Earliest();
+ SMILInterval next_interval = ResolveInterval(begin_after, presentation_time);
+ // It's the same interval that we resolved before. Do nothing.
+ if (next_interval == interval_)
+ return;
+ if (interval_.IsResolved())
+ previous_interval_ = interval_;
+ // If there are no more intervals to resolve, we have to wait for an event to
+ // occur in order to get a new instance time.
+ if (!next_interval.IsResolved()) {
+ interval_ = next_interval;
+ next_interval_time_ = SMILTime::Unresolved();
+ return;
+ }
+ SetNewInterval(next_interval, presentation_time);
+ interval_has_changed_ = true;
}
-unsigned SVGSMILElement::CalculateAnimationRepeat(double elapsed) const {
- const SMILTime simple_duration = SimpleDuration();
- if (simple_duration.IsIndefinite() || !simple_duration)
- return 0;
- DCHECK(simple_duration.IsFinite());
- DCHECK(interval_.begin.IsFinite());
-
- double active_time = std::max(elapsed - interval_.begin.Value(), 0.0);
- SMILTime repeating_duration = RepeatingDuration();
- if (elapsed >= interval_.end || active_time > repeating_duration) {
- if (!repeating_duration.IsFinite())
- return 0;
- unsigned repeat = static_cast<unsigned>(repeating_duration.Value() /
- simple_duration.Value());
- if (!fmod(repeating_duration.Value(), simple_duration.Value()))
- return repeat - 1;
- return repeat;
+void SVGSMILElement::AddedToTimeContainer() {
+ DCHECK(time_container_);
+ SMILTime current_presentation_time = time_container_->CurrentDocumentTime();
+ UpdateInterval(current_presentation_time);
+
+ if (IntervalBegin() <= current_presentation_time ||
+ NextProgressTime(current_presentation_time).IsFinite()) {
+ time_container_->MarkIntervalsDirty();
+ time_container_->ScheduleIntervalUpdate();
}
- unsigned repeat =
- static_cast<unsigned>(active_time / simple_duration.Value());
- return repeat;
+
+ // If there's an active interval, then revalidate the animation value.
+ if (GetActiveState() != kInactive)
+ StartedActiveInterval();
}
-float SVGSMILElement::CalculateAnimationPercent(double elapsed) const {
- SMILTime simple_duration = SimpleDuration();
- if (simple_duration.IsIndefinite()) {
- return 0.f;
- }
- if (!simple_duration) {
- return 1.f;
- }
- DCHECK(simple_duration.IsFinite());
- DCHECK(interval_.begin.IsFinite());
+void SVGSMILElement::RemovedFromTimeContainer() {
+ DCHECK(time_container_);
+ // If the element is active reset to a clear state.
+ if (GetActiveState() != kInactive)
+ EndedActiveInterval();
+}
+
+const SMILInterval& SVGSMILElement::GetActiveInterval(SMILTime elapsed) const {
+ // If there's no current interval, return the previous interval.
+ if (!interval_.IsResolved())
+ return previous_interval_;
+ // If there's a previous interval and the current interval hasn't begun yet,
+ // return the previous interval.
+ if (previous_interval_.IsResolved() && interval_.BeginsAfter(elapsed))
+ return previous_interval_;
+ return interval_;
+}
- SMILTime repeating_duration = RepeatingDuration();
- double active_time = elapsed - interval_.begin.Value();
- if (elapsed >= interval_.end || active_time > repeating_duration) {
+SVGSMILElement::ProgressState SVGSMILElement::CalculateProgressState(
+ SMILTime presentation_time) const {
+ const SMILTime simple_duration = SimpleDuration();
+ if (simple_duration.IsIndefinite())
+ return {0.0f, 0};
+ if (!simple_duration)
+ return {1.0f, 0};
+ DCHECK(simple_duration.IsFinite());
+ const SMILInterval& active_interval = GetActiveInterval(presentation_time);
+ DCHECK(active_interval.IsResolved());
+ const SMILTime active_time = presentation_time - active_interval.begin;
+ const SMILTime repeating_duration = RepeatingDuration();
+ int64_t repeat;
+ SMILTime simple_time;
+ if (presentation_time >= active_interval.end ||
+ active_time > repeating_duration) {
// Use the interval to compute the interval position if we've passed the
// interval end, otherwise use the "repeating duration". This prevents a
// stale interval (with for instance an 'indefinite' end) from yielding an
// invalid interval position.
- double last_active_duration;
- if (elapsed >= interval_.end)
- last_active_duration = interval_.end.Value() - interval_.begin.Value();
- else
- last_active_duration = repeating_duration.Value();
- double percent = last_active_duration / simple_duration.Value();
- percent = percent - floor(percent);
- float epsilon = std::numeric_limits<float>::epsilon();
- if (percent < epsilon || 1 - percent < epsilon)
- return 1.0f;
- return clampTo<float>(percent);
+ SMILTime last_active_duration =
+ presentation_time >= active_interval.end
+ ? active_interval.end - active_interval.begin
+ : repeating_duration;
+ if (!last_active_duration.IsFinite())
+ return {0.0f, 0};
+ // If the repeat duration is a multiple of the simple duration, we should
+ // use a progress value of 1.0, otherwise we should return a value that is
+ // within the interval (< 1.0), so subtract the smallest representable time
+ // delta in that case.
+ repeat = last_active_duration / simple_duration;
+ simple_time = last_active_duration % simple_duration;
+ if (simple_time) {
+ simple_time = simple_time - SMILTime::Epsilon();
+ } else {
+ simple_time = simple_duration;
+ repeat--;
+ }
+ } else {
+ repeat = active_time / simple_duration;
+ simple_time = active_time % simple_duration;
}
- double simple_time = fmod(active_time, simple_duration.Value());
- return clampTo<float>(simple_time / simple_duration.Value());
+ return {clampTo<float>(simple_time.InternalValueAsDouble() /
+ simple_duration.InternalValueAsDouble()),
+ clampTo<unsigned>(repeat)};
}
-SMILTime SVGSMILElement::CalculateNextProgressTime(double elapsed) const {
+SMILTime SVGSMILElement::NextProgressTime(SMILTime presentation_time) const {
if (GetActiveState() == kActive) {
// If duration is indefinite the value does not actually change over time.
// Same is true for <set>.
@@ -1040,26 +1028,28 @@ SMILTime SVGSMILElement::CalculateNextProgressTime(double elapsed) const {
// We are supposed to do freeze semantics when repeating ends, even if the
// element is still active.
// Take care that we get a timer callback at that point.
- if (elapsed < repeating_duration_end &&
- repeating_duration_end < interval_.end &&
+ if (presentation_time < repeating_duration_end &&
+ interval_.EndsAfter(repeating_duration_end) &&
repeating_duration_end.IsFinite())
return repeating_duration_end;
return interval_.end;
}
- return elapsed + 0.025;
+ return presentation_time;
}
- return interval_.begin >= elapsed ? interval_.begin : SMILTime::Unresolved();
+ return interval_.begin >= presentation_time ? interval_.begin
+ : SMILTime::Unresolved();
}
SVGSMILElement::ActiveState SVGSMILElement::DetermineActiveState(
SMILTime elapsed) const {
- if (elapsed >= interval_.begin && elapsed < interval_.end)
+ if (interval_.Contains(elapsed))
return kActive;
-
+ if (is_waiting_for_first_interval_)
+ return kInactive;
return Fill() == kFillFreeze ? kFrozen : kInactive;
}
-bool SVGSMILElement::IsContributing(double elapsed) const {
+bool SVGSMILElement::IsContributing(SMILTime elapsed) const {
// Animation does not contribute during the active time if it is past its
// repeating duration and has fill=remove.
return (GetActiveState() == kActive &&
@@ -1068,181 +1058,150 @@ bool SVGSMILElement::IsContributing(double elapsed) const {
GetActiveState() == kFrozen;
}
-// The first part of the processing of the animation,
-// this checks if there are any further calculations needed
-// to continue and makes sure the intervals are correct.
-bool SVGSMILElement::NeedsToProgress(double elapsed) {
- // Check we're connected to something.
+bool SVGSMILElement::NeedsIntervalUpdate(SMILTime elapsed) const {
+ // Check we're connected to something and that our conditions have been
+ // "connected".
DCHECK(time_container_);
- // Check that we have some form of start or are prepared to find it.
- DCHECK(is_waiting_for_first_interval_ || interval_.begin.IsFinite());
-
- if (!sync_base_conditions_connected_)
- ConnectSyncBaseConditions();
-
- // Check if we need updating, otherwise just return.
- if (!interval_.begin.IsFinite()) {
- DCHECK_EQ(GetActiveState(), kInactive);
- next_progress_time_ = SMILTime::Unresolved();
- return false;
- }
-
- if (elapsed < interval_.begin) {
- DCHECK_NE(GetActiveState(), kActive);
- next_progress_time_ = interval_.begin;
- return false;
- }
-
- if (is_waiting_for_first_interval_) {
- is_waiting_for_first_interval_ = false;
- ResolveFirstInterval();
- }
- return true;
+ DCHECK(conditions_connected_);
+ return elapsed >= next_interval_time_;
}
-void SVGSMILElement::TriggerPendingEvents(double elapsed) {
- if (GetActiveState() == kInactive)
- ScheduleEvent(event_type_names::kBeginEvent);
-
- if (CalculateAnimationRepeat(elapsed))
- ScheduleEvent(event_type_names::kRepeatEvent);
-
- if (GetActiveState() == kInactive || GetActiveState() == kFrozen)
- ScheduleEvent(event_type_names::kEndEvent);
-}
-
-void SVGSMILElement::UpdateSyncBases() {
- if (!interval_has_changed_)
- return;
+void SVGSMILElement::UpdateActiveState(SMILTime elapsed) {
+ const bool was_active = GetActiveState() == kActive;
+ active_state_ = DetermineActiveState(elapsed);
+ const bool is_active = GetActiveState() == kActive;
+ const bool interval_restart =
+ interval_has_changed_ && previous_interval_.end == interval_.begin;
interval_has_changed_ = false;
- NotifyDependentsIntervalChanged(interval_);
- next_progress_time_ = next_progress_time_.IsUnresolved()
- ? interval_.begin
- : std::min(next_progress_time_, interval_.begin);
-}
-
-void SVGSMILElement::UpdateNextProgressTime(double elapsed) {
- next_progress_time_ = CalculateNextProgressTime(elapsed);
-}
-
-void SVGSMILElement::Progress(double elapsed) {
- float percent = CalculateAnimationPercent(elapsed);
- unsigned repeat = CalculateAnimationRepeat(elapsed);
-
- base::Optional<SMILInterval> new_interval =
- CheckForNewRestartInterval(elapsed);
-
- // This boolean is quite intricate. (Bug 379751)
- //
- // If we get a new interval we send all events
- bool interval_did_start_or_end = (new_interval && *new_interval != interval_);
-
- // This catches a tricky edge case where the interval began and ended
- // on the same frame. So we check if the interval has passed, and
- // that it's not the same interval as it was last time.
- bool new_begin_time =
- (!previous_interval_begin_.IsUnresolved() &&
- interval_.begin != previous_interval_begin_ && interval_.end <= elapsed);
- if (new_begin_time) {
- previous_interval_begin_ = interval_.begin;
- interval_did_start_or_end = true;
- }
-
- if (new_interval) {
- previous_interval_begin_ = interval_.begin;
- interval_ = *new_interval;
- interval_has_changed_ = true;
+ if ((was_active && !is_active) || interval_restart) {
+ ScheduleEvent(event_type_names::kEndEvent);
+ EndedActiveInterval();
}
- ActiveState old_active_state = GetActiveState();
- active_state_ = DetermineActiveState(elapsed);
-
if (IsContributing(elapsed)) {
- if (old_active_state == kInactive || interval_did_start_or_end) {
+ if (!was_active || interval_restart) {
ScheduleEvent(event_type_names::kBeginEvent);
StartedActiveInterval();
}
- if (repeat && repeat != last_repeat_) {
- last_repeat_ = repeat;
- NotifyDependentsIntervalChanged(interval_);
+ ProgressState progress_state = CalculateProgressState(elapsed);
+ if (progress_state.repeat &&
+ progress_state.repeat != last_progress_.repeat) {
+ NotifyDependentsOnRepeat(progress_state.repeat, elapsed);
ScheduleRepeatEvents();
}
-
- last_percent_ = percent;
+ next_interval_time_ = ComputeNextIntervalTime(elapsed);
+ last_progress_ = progress_state;
}
+}
- if ((old_active_state == kActive && GetActiveState() != kActive) ||
- interval_did_start_or_end) {
- ScheduleEvent(event_type_names::kEndEvent);
- EndedActiveInterval();
- }
+void SVGSMILElement::UpdateProgressState(SMILTime presentation_time) {
+ last_progress_ = CalculateProgressState(presentation_time);
}
-void SVGSMILElement::NotifyDependentsIntervalChanged(
+struct SVGSMILElement::NotifyDependentsInfo {
+ explicit NotifyDependentsInfo(const SMILInterval& interval)
+ : origin(SMILTimeOrigin::kSyncBase),
+ repeat_nr(0),
+ begin(interval.begin),
+ end(interval.end) {}
+ NotifyDependentsInfo(unsigned repeat_nr, SMILTime repeat_time)
+ : origin(SMILTimeOrigin::kRepeat),
+ repeat_nr(repeat_nr),
+ begin(repeat_time),
+ end(SMILTime::Unresolved()) {}
+
+ SMILTimeOrigin origin;
+ unsigned repeat_nr;
+ SMILTime begin; // repeat time if origin == kRepeat
+ SMILTime end;
+};
+
+void SVGSMILElement::NotifyDependentsOnNewInterval(
const SMILInterval& interval) {
- DCHECK(interval.begin.IsFinite());
- // |loopBreaker| is used to avoid infinite recursions which may be caused by:
- // |notifyDependentsIntervalChanged| -> |createInstanceTimesFromSyncBase| ->
- // |add{Begin,End}Time| -> |{begin,end}TimeChanged| ->
- // |notifyDependentsIntervalChanged|
- //
- // As the set here records SVGSMILElements on the stack, it is acceptable to
- // use a HashSet of untraced heap references -- any conservative GC which
- // strikes before unwinding will find these elements on the stack.
- DEFINE_STATIC_LOCAL(HashSet<UntracedMember<SVGSMILElement>>, loop_breaker,
- ());
- if (!loop_breaker.insert(this).is_new_entry)
- return;
+ DCHECK(interval.IsResolved());
+ NotifyDependents(NotifyDependentsInfo(interval));
+}
- for (SVGSMILElement* element : sync_base_dependents_)
- element->CreateInstanceTimesFromSyncBase(this, interval);
+void SVGSMILElement::NotifyDependentsOnRepeat(unsigned repeat_nr,
+ SMILTime repeat_time) {
+ DCHECK(repeat_nr);
+ DCHECK(repeat_time.IsFinite());
+ NotifyDependents(NotifyDependentsInfo(repeat_nr, repeat_time));
+}
- loop_breaker.erase(this);
+void SVGSMILElement::NotifyDependents(const NotifyDependentsInfo& info) {
+ // Avoid infinite recursion which may be caused by:
+ // |NotifyDependents| -> |CreateInstanceTimesFromSyncBase| ->
+ // |AddInstanceTime| -> |InstanceListChanged| -> |NotifyDependents|
+ if (is_notifying_dependents_)
+ return;
+ base::AutoReset<bool> reentrancy_guard(&is_notifying_dependents_, true);
+ for (SVGSMILElement* element : sync_base_dependents_)
+ element->CreateInstanceTimesFromSyncBase(this, info);
}
void SVGSMILElement::CreateInstanceTimesFromSyncBase(
SVGSMILElement* timed_element,
- const SMILInterval& new_interval) {
+ const NotifyDependentsInfo& info) {
// FIXME: To be really correct, this should handle updating exising interval
// by changing the associated times instead of creating new ones.
+ bool instance_lists_changed = false;
for (Condition* condition : conditions_) {
- if (condition->IsSyncBaseFor(timed_element)) {
- // TODO(edvardt): This is a lot of string compares, which is slow, it
- // might be a good idea to change it for an enum and maybe make Condition
- // into a union?
- DCHECK(condition->GetName() == "begin" || condition->GetName() == "end" ||
- condition->GetName() == "repeat");
-
- // No nested time containers in SVG, no need for crazy time space
- // conversions. Phew!
- SMILTime time = SMILTime::Unresolved();
+ if (!condition->IsSyncBaseFor(timed_element))
+ continue;
+ // TODO(edvardt): This is a lot of string compares, which is slow, it
+ // might be a good idea to change it for an enum and maybe make Condition
+ // into a union?
+ DCHECK(condition->GetName() == "begin" || condition->GetName() == "end" ||
+ condition->GetName() == "repeat");
+
+ // No nested time containers in SVG, no need for crazy time space
+ // conversions. Phew!
+ SMILTime time = SMILTime::Unresolved();
+ if (info.origin == SMILTimeOrigin::kSyncBase) {
if (condition->GetName() == "begin") {
- time = new_interval.begin + condition->Offset();
+ time = info.begin + condition->Offset();
} else if (condition->GetName() == "end") {
- time = new_interval.end + condition->Offset();
- } else if (condition->Repeat()) {
- if (timed_element->last_repeat_ == condition->Repeat()) {
- // If the STAPIT algorithm works, the current document
- // time will be accurate. So this event should be sent
- // correctly.
- SMILTime base_time =
- time_container_ ? time_container_->CurrentDocumentTime() : 0;
- time = base_time + condition->Offset();
- }
+ time = info.end + condition->Offset();
}
- if (!time.IsFinite())
+ } else {
+ DCHECK_EQ(info.origin, SMILTimeOrigin::kRepeat);
+ if (info.repeat_nr != condition->Repeat())
continue;
- AddInstanceTime(condition->GetBeginOrEnd(), time);
+ time = info.begin + condition->Offset();
}
+ if (!time.IsFinite())
+ continue;
+ AddInstanceTime(condition->GetBeginOrEnd(), time, info.origin);
+ instance_lists_changed = true;
}
+
+ // No instance times were added.
+ if (!instance_lists_changed)
+ return;
+
+ // We need to check/update the intervals.
+ if (time_container_)
+ time_container_->MarkIntervalsDirty();
+
+ // We're currently sending notifications for, and thus updating, this element
+ // so let that update handle the new instance times.
+ if (is_notifying_dependents_)
+ return;
+
+ InstanceListChanged();
+ if (time_container_)
+ time_container_->ScheduleIntervalUpdate();
}
void SVGSMILElement::AddSyncBaseDependent(SVGSMILElement& animation) {
sync_base_dependents_.insert(&animation);
- if (interval_.begin.IsFinite())
- animation.CreateInstanceTimesFromSyncBase(this, interval_);
+ if (!interval_.IsResolved())
+ return;
+ animation.CreateInstanceTimesFromSyncBase(this,
+ NotifyDependentsInfo(interval_));
}
void SVGSMILElement::RemoveSyncBaseDependent(SVGSMILElement& animation) {
@@ -1250,12 +1209,16 @@ void SVGSMILElement::RemoveSyncBaseDependent(SVGSMILElement& animation) {
}
void SVGSMILElement::BeginByLinkActivation() {
- AddInstanceTime(kBegin, Elapsed());
+ AddInstanceTimeAndUpdate(kBegin, Elapsed(), SMILTimeOrigin::kLinkActivation);
+}
+
+void SVGSMILElement::StartedActiveInterval() {
+ is_waiting_for_first_interval_ = false;
}
void SVGSMILElement::EndedActiveInterval() {
- ClearTimesWithDynamicOrigins(begin_times_);
- ClearTimesWithDynamicOrigins(end_times_);
+ RemoveInstanceTimesWithOrigin(begin_times_, SMILTimeOrigin::kScript);
+ RemoveInstanceTimesWithOrigin(end_times_, SMILTimeOrigin::kScript);
}
void SVGSMILElement::ScheduleRepeatEvents() {
@@ -1278,7 +1241,7 @@ void SVGSMILElement::DispatchPendingEvent(const AtomicString& event_type) {
DispatchEvent(*Event::Create(event_type));
}
-bool SVGSMILElement::HasValidTarget() {
+bool SVGSMILElement::HasValidTarget() const {
return targetElement() && targetElement()->InActiveDocument();
}
@@ -1288,6 +1251,7 @@ void SVGSMILElement::WillChangeAnimationTarget() {
DCHECK(time_container_);
DCHECK(target_element_);
time_container_->Unschedule(this, target_element_, attribute_name_);
+ RemovedFromTimeContainer();
is_scheduled_ = false;
}
@@ -1296,6 +1260,7 @@ void SVGSMILElement::DidChangeAnimationTarget() {
if (!time_container_ || !HasValidTarget())
return;
time_container_->Schedule(this, target_element_, attribute_name_);
+ AddedToTimeContainer();
is_scheduled_ = true;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.h b/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
index a93c4bb60d9..11ea52a41e8 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_ANIMATION_SVG_SMIL_ELEMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/svg/animation/smil_repeat_count.h"
#include "third_party/blink/renderer/core/svg/animation/smil_time.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_tests.h"
@@ -54,7 +55,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
- virtual bool HasValidTarget();
+ virtual bool HasValidTarget() const;
virtual void AnimationAttributeChanged() = 0;
SMILTimeContainer* TimeContainer() const { return time_container_.Get(); }
@@ -74,26 +75,28 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
SMILTime Dur() const;
SMILTime RepeatDur() const;
- SMILTime RepeatCount() const;
+ SMILRepeatCount RepeatCount() const;
SMILTime MaxValue() const;
SMILTime MinValue() const;
SMILTime Elapsed() const;
SMILTime IntervalBegin() const { return interval_.begin; }
- SMILTime PreviousIntervalBegin() const { return previous_interval_begin_; }
SMILTime SimpleDuration() const;
- bool NeedsToProgress(double elapsed);
- void Progress(double elapsed);
- void TriggerPendingEvents(double elapsed);
- void UpdateSyncBases();
- void UpdateNextProgressTime(double elapsed);
+ bool NeedsIntervalUpdate(SMILTime elapsed) const;
+ void UpdateInterval(SMILTime presentation_time);
+ void UpdateActiveState(SMILTime elapsed);
+ void UpdateProgressState(SMILTime presentation_time);
+ bool IsHigherPriorityThan(const SVGSMILElement* other,
+ SMILTime presentation_time) const;
- SMILTime NextInterestingTime(SMILTime) const;
- SMILTime NextProgressTime() const;
+ SMILTime NextIntervalTime(SMILTime presentation_time) const;
+ SMILTime ComputeNextIntervalTime(SMILTime presentation_time) const;
+ SMILTime NextProgressTime(SMILTime elapsed) const;
void UpdateAnimatedValue(SVGSMILElement* result_element) {
- UpdateAnimation(last_percent_, last_repeat_, result_element);
+ UpdateAnimation(last_progress_.progress, last_progress_.repeat,
+ result_element);
}
void Reset();
@@ -101,8 +104,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
static SMILTime ParseClockValue(const String&);
static SMILTime ParseOffsetValue(const String&);
- bool IsContributing(double elapsed) const;
- bool IsFrozen() const;
+ bool IsContributing(SMILTime elapsed) const;
unsigned DocumentOrderIndex() const { return document_order_index_; }
void SetDocumentOrderIndex(unsigned index) { document_order_index_ = index; }
@@ -114,20 +116,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
// Returns true if this animation "sets" the
// value of the animation. Thus all previous
// animations are rendered useless.
- virtual bool OverwritesUnderlyingAnimationValue() = 0;
-
- bool AnimatedTypeIsLocked() const { return animated_property_locked_; }
- void LockAnimatedType() {
- DCHECK(!animated_property_locked_);
- animated_property_locked_ = true;
- }
- void UnlockAnimatedType() {
- DCHECK(animated_property_locked_);
- animated_property_locked_ = false;
- }
-
- void ConnectSyncBaseConditions();
- void ConnectEventBaseConditions();
+ virtual bool OverwritesUnderlyingAnimationValue() const = 0;
void ScheduleEvent(const AtomicString& event_type);
void ScheduleRepeatEvents();
@@ -142,15 +131,7 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
protected:
enum BeginOrEnd { kBegin, kEnd };
- void IntervalIsDirty() {
- interval_.begin = 0.0;
- interval_.end = 0.0;
- }
-
- void AddInstanceTime(
- BeginOrEnd,
- SMILTime,
- SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::kParserOrigin);
+ void AddInstanceTimeAndUpdate(BeginOrEnd, SMILTime, SMILTimeOrigin);
void SetInactive() { active_state_ = kInactive; }
@@ -160,6 +141,8 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
virtual void WillChangeAnimationTarget();
virtual void DidChangeAnimationTarget();
+ virtual void StartedActiveInterval();
+
QualifiedName attribute_name_;
private:
@@ -167,7 +150,6 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
void ClearResourceAndEventBaseReferences();
void ClearConditions();
- virtual void StartedActiveInterval() = 0;
void EndedActiveInterval();
virtual void UpdateAnimation(float percent,
unsigned repeat,
@@ -180,24 +162,28 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
SMILTime FindInstanceTime(BeginOrEnd,
SMILTime minimum_time,
bool equals_minimum_ok) const;
-
- enum IntervalSelector { kFirstInterval, kNextInterval };
-
- SMILInterval ResolveInterval(IntervalSelector) const;
- void ResolveFirstInterval();
- base::Optional<SMILInterval> ResolveNextInterval();
- SMILTime ResolveActiveEnd(SMILTime resolved_begin,
- SMILTime resolved_end) const;
+ SMILTime BeginTimeForPrioritization(SMILTime presentation_time) const;
+
+ SMILInterval ResolveInterval(SMILTime begin_after, SMILTime end_after) const;
+ // Check if the current interval is still current, and apply restart
+ // semantics. Returns true if a new interval should be resolved.
+ bool HandleIntervalRestart(SMILTime presentation_time);
+ void DiscardOrRevalidateCurrentInterval(SMILTime presentation_time);
+ SMILTime ResolveActiveEnd(SMILTime resolved_begin) const;
SMILTime RepeatingDuration() const;
+ const SMILInterval& GetActiveInterval(SMILTime elapsed) const;
+ void SetNewInterval(const SMILInterval&, SMILTime presentation_time);
+ void SetNewIntervalEnd(SMILTime new_end, SMILTime presentation_time);
- base::Optional<SMILInterval> CheckForNewRestartInterval(double elapsed);
- void BeginListChanged(SMILTime event_time);
- void EndListChanged(SMILTime event_time);
+ void AddInstanceTime(BeginOrEnd begin_or_end,
+ SMILTime time,
+ SMILTimeOrigin origin);
+ void InstanceListChanged();
// This represents conditions on elements begin or end list that need to be
// resolved on runtime, for example
// <animate begin="otherElement.begin + 8s; button.click" ... />
- class Condition : public GarbageCollectedFinalized<Condition> {
+ class Condition final : public GarbageCollected<Condition> {
public:
enum Type { kEventBase, kSyncBase, kAccessKey };
@@ -240,12 +226,19 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
bool ParseCondition(const String&, BeginOrEnd begin_or_end);
void ParseBeginOrEnd(const String&, BeginOrEnd begin_or_end);
- void DisconnectSyncBaseConditions();
- void DisconnectEventBaseConditions();
+ void ConnectConditions();
+ void DisconnectConditions();
+
+ void AddedToTimeContainer();
+ void RemovedFromTimeContainer();
- void NotifyDependentsIntervalChanged(const SMILInterval& interval);
+ void NotifyDependentsOnNewInterval(const SMILInterval& interval);
+ void NotifyDependentsOnRepeat(unsigned repeat_nr, SMILTime repeat_time);
+
+ struct NotifyDependentsInfo;
+ void NotifyDependents(const NotifyDependentsInfo& info);
void CreateInstanceTimesFromSyncBase(SVGSMILElement* timed_element,
- const SMILInterval& interval);
+ const NotifyDependentsInfo& info);
void AddSyncBaseDependent(SVGSMILElement&);
void RemoveSyncBaseDependent(SVGSMILElement&);
@@ -255,15 +248,18 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
return static_cast<ActiveState>(active_state_);
}
ActiveState DetermineActiveState(SMILTime elapsed) const;
- float CalculateAnimationPercent(double elapsed) const;
- unsigned CalculateAnimationRepeat(double elapsed) const;
- SMILTime CalculateNextProgressTime(double elapsed) const;
+
+ struct ProgressState {
+ float progress;
+ unsigned repeat;
+ };
+ ProgressState CalculateProgressState(SMILTime presentation_time) const;
Member<SVGElement> target_element_;
Member<IdTargetObserver> target_id_observer_;
HeapVector<Member<Condition>> conditions_;
- bool sync_base_conditions_connected_;
+ bool conditions_connected_;
bool has_end_event_conditions_;
bool is_waiting_for_first_interval_;
@@ -278,30 +274,28 @@ class CORE_EXPORT SVGSMILElement : public SVGElement, public SVGTests {
// This is the upcoming or current interval
SMILInterval interval_;
-
- SMILTime previous_interval_begin_;
+ // This is the previous interval. It should always be non-overlapping and
+ // "before" |interval_|.
+ SMILInterval previous_interval_;
+ SMILTime next_interval_time_;
unsigned active_state_ : 2;
unsigned restart_ : 2;
unsigned fill_ : 1;
- float last_percent_;
- unsigned last_repeat_;
-
- SMILTime next_progress_time_;
+ ProgressState last_progress_;
Member<SMILTimeContainer> time_container_;
unsigned document_order_index_;
- Vector<unsigned> repeat_event_count_list_;
-
mutable SMILTime cached_dur_;
mutable SMILTime cached_repeat_dur_;
- mutable SMILTime cached_repeat_count_;
+ mutable SMILRepeatCount cached_repeat_count_;
mutable SMILTime cached_min_;
mutable SMILTime cached_max_;
- bool animated_property_locked_;
bool interval_has_changed_;
+ bool instance_lists_have_changed_;
+ bool is_notifying_dependents_;
friend class ConditionEventListener;
};
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 04786c3dfaa..2a93c180670 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
@@ -676,6 +676,8 @@ void SVGImage::AdvanceAnimationForTesting() {
base::TimeTicks current_animation_time =
page_->Animator().Clock().CurrentTime();
page_->Animator().Clock().ResetTimeForTesting();
+ if (root_element->TimeContainer()->IsStarted())
+ root_element->TimeContainer()->ResetDocumentTime();
page_->Animator().ServiceScriptedAnimations(
root_element->GetDocument().Timeline().ZeroTime() +
base::TimeDelta::FromSecondsD(root_element->getCurrentTime()));
@@ -850,7 +852,7 @@ String SVGImage::FilenameExtension() const {
}
DarkModeClassification SVGImage::CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) {
classifier->SetImageType(DarkModeImageClassifier::ImageType::kSvg);
return DarkModeClassification::kNotClassified;
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 e9daf5d3d97..8dd7b4acf3e 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
@@ -125,7 +125,7 @@ class CORE_EXPORT SVGImage final : public Image {
PaintImage PaintImageForCurrentFrame() override;
DarkModeClassification CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) override;
protected:
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
index 838942772ea..eba9f3feaef 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
@@ -91,7 +91,8 @@ void SVGImageChromeClient::RestoreAnimationIfNeeded() {
image_->RestoreAnimation();
}
-void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*) {
+void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta fire_time) {
// Because a single SVGImage can be shared by multiple pages, we can't key
// our svg image layout on the page's real animation frame. Therefore, we
// run this fake animation timer to trigger layout in SVGImages. The name,
@@ -103,11 +104,11 @@ void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*) {
// animations, but prefer a fixed, jittery, frame-delay if there're any
// animations. Checking for pending/active animations could be more
// stringent.
- base::TimeDelta fire_time;
if (image_->MaybeAnimated()) {
if (IsSuspended())
return;
- fire_time = kAnimationFrameDelay;
+ if (fire_time.is_zero())
+ fire_time = kAnimationFrameDelay;
}
animation_timer_->StartOneShot(fire_time, FROM_HERE);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
index ead7000f099..6460951775f 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
@@ -56,7 +56,8 @@ class CORE_EXPORT SVGImageChromeClient final : public EmptyChromeClient {
private:
void ChromeDestroyed() override;
void InvalidateRect(const IntRect&) override;
- void ScheduleAnimation(const LocalFrameView*) override;
+ void ScheduleAnimation(const LocalFrameView*,
+ base::TimeDelta = base::TimeDelta()) override;
void SetTimer(std::unique_ptr<TimerBase>);
TimerBase* GetTimerForTesting() const { return animation_timer_.get(); }
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 2d9a8e7ab3b..1e617991b62 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
@@ -89,9 +89,10 @@ class SVGImageForContainer final : public Image {
PaintImage PaintImageForCurrentFrame() override;
DarkModeClassification CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) override {
- return image_->CheckTypeSpecificConditionsForDarkMode(src_rect, classifier);
+ return image_->CheckTypeSpecificConditionsForDarkMode(dest_rect,
+ classifier);
}
protected:
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 7b4d572f1a1..c471081dd1f 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
@@ -93,7 +93,7 @@ class SVGImageTest : public testing::Test {
private:
class PauseControlImageObserver
- : public GarbageCollectedFinalized<PauseControlImageObserver>,
+ : public GarbageCollected<PauseControlImageObserver>,
public ImageObserver {
USING_GARBAGE_COLLECTED_MIXIN(PauseControlImageObserver);
diff --git a/chromium/third_party/blink/renderer/core/svg/linear_gradient_attributes.h b/chromium/third_party/blink/renderer/core/svg/linear_gradient_attributes.h
index f42ab8ecc9d..0669fbb991d 100644
--- a/chromium/third_party/blink/renderer/core/svg/linear_gradient_attributes.h
+++ b/chromium/third_party/blink/renderer/core/svg/linear_gradient_attributes.h
@@ -92,8 +92,8 @@ struct LinearGradientAttributes : GradientAttributes {
};
// Wrapper object for the LinearGradientAttributes part object.
-class LinearGradientAttributesWrapper
- : public GarbageCollectedFinalized<LinearGradientAttributesWrapper> {
+class LinearGradientAttributesWrapper final
+ : public GarbageCollected<LinearGradientAttributesWrapper> {
public:
LinearGradientAttributesWrapper() = default;
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_property.h b/chromium/third_party/blink/renderer/core/svg/properties/svg_property.h
index 516ed392275..00a712e7757 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_property.h
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_property.h
@@ -41,7 +41,7 @@ namespace blink {
class SVGElement;
class SVGAnimationElement;
-class SVGPropertyBase : public GarbageCollectedFinalized<SVGPropertyBase> {
+class SVGPropertyBase : public GarbageCollected<SVGPropertyBase> {
public:
// Properties do not have a primitive type by default
typedef void PrimitiveType;
diff --git a/chromium/third_party/blink/renderer/core/svg/radial_gradient_attributes.h b/chromium/third_party/blink/renderer/core/svg/radial_gradient_attributes.h
index 7f54ba023be..3947fe58940 100644
--- a/chromium/third_party/blink/renderer/core/svg/radial_gradient_attributes.h
+++ b/chromium/third_party/blink/renderer/core/svg/radial_gradient_attributes.h
@@ -114,8 +114,8 @@ struct RadialGradientAttributes final : GradientAttributes {
};
// Wrapper object for the RadialGradientAttributes part object.
-class RadialGradientAttributesWrapper
- : public GarbageCollectedFinalized<RadialGradientAttributesWrapper> {
+class RadialGradientAttributesWrapper final
+ : public GarbageCollected<RadialGradientAttributesWrapper> {
public:
RadialGradientAttributesWrapper() = default;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
index f44723cbf89..ab8b85d32f4 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
@@ -48,8 +48,6 @@
namespace blink {
-using namespace html_names;
-
SVGAElement::SVGAElement(Document& document)
: SVGGraphicsElement(svg_names::kATag, document),
SVGURIReference(this),
@@ -140,8 +138,8 @@ void SVGAElement::DefaultEventHandler(Event& event) {
&GetDocument(), ResourceRequest(GetDocument().CompleteURL(url)));
frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(&event));
frame_request.SetTriggeringEventInfo(
- event.isTrusted() ? WebTriggeringEventInfo::kFromTrustedEvent
- : WebTriggeringEventInfo::kFromUntrustedEvent);
+ event.isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
+ : TriggeringEventInfo::kFromUntrustedEvent);
frame_request.GetResourceRequest().SetHasUserGesture(
LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
@@ -183,7 +181,7 @@ bool SVGAElement::ShouldHaveFocusAppearance() const {
}
bool SVGAElement::IsURLAttribute(const Attribute& attribute) const {
- return attribute.GetName().LocalName() == kHrefAttr ||
+ return attribute.GetName().LocalName() == html_names::kHrefAttr ||
SVGGraphicsElement::IsURLAttribute(attribute);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
index 8096b369441..bad29363c2a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -203,19 +203,23 @@ void SVGAnimateElement::ClearTargetProperty() {
css_property_id_ = CSSPropertyID::kInvalid;
}
-AnimatedPropertyType SVGAnimateElement::GetAnimatedPropertyType() {
- if (!targetElement())
- return kAnimatedUnknown;
- ResolveTargetProperty();
- return type_;
+void SVGAnimateElement::UpdateTargetProperty() {
+ if (SVGElement* target = targetElement())
+ ResolveTargetProperty();
+ else
+ ClearTargetProperty();
+}
+
+AnimatedPropertyType SVGAnimateElement::GetAnimatedPropertyType() const {
+ // TODO(fs): Should be possible to DCHECK targetElement() here instead.
+ return !targetElement() ? kAnimatedUnknown : type_;
}
-bool SVGAnimateElement::HasValidTarget() {
+bool SVGAnimateElement::HasValidTarget() const {
if (!SVGAnimationElement::HasValidTarget())
return false;
if (AttributeName() == AnyQName())
return false;
- ResolveTargetProperty();
if (type_ == kAnimatedUnknown)
return false;
// Always animate CSS properties using the ApplyCSSAnimation code path,
@@ -227,8 +231,7 @@ bool SVGAnimateElement::HasValidTarget() {
}
bool SVGAnimateElement::ShouldApplyAnimation(
- const SVGElement& target_element,
- const QualifiedName& attribute_name) {
+ const SVGElement& target_element) const {
return target_element.parentNode() && HasValidTarget();
}
@@ -416,24 +419,20 @@ bool SVGAnimateElement::CalculateFromAndByValues(const String& from_string,
}
void SVGAnimateElement::ResetAnimatedType() {
- ResolveTargetProperty();
-
SVGElement* target_element = targetElement();
- const QualifiedName& attribute_name = AttributeName();
-
- if (!ShouldApplyAnimation(*target_element, attribute_name))
+ if (!ShouldApplyAnimation(*target_element))
return;
if (IsAnimatingSVGDom()) {
// SVG DOM animVal animation code-path.
animated_value_ = target_property_->CreateAnimatedValue();
DCHECK_EQ(animated_value_->GetType(), type_);
- target_element->SetAnimatedAttribute(attribute_name, animated_value_);
+ target_element->SetAnimatedAttribute(AttributeName(), animated_value_);
return;
}
DCHECK(IsAnimatingCSSProperty());
// Presentation attributes which has an SVG DOM representation should use the
// "SVG DOM" code-path (above.)
- DCHECK(SVGElement::IsAnimatableCSSProperty(attribute_name));
+ DCHECK(SVGElement::IsAnimatableCSSProperty(AttributeName()));
// CSS properties animation code-path.
String base_value = ComputeCSSPropertyValue(target_element, css_property_id_);
@@ -444,19 +443,13 @@ void SVGAnimateElement::ClearAnimatedType() {
if (!animated_value_)
return;
- // The animated property lock is held for the "result animation" (see
- // SMILTimeContainer::updateAnimations()) while we're processing an animation
- // group. We will very likely crash later if we clear the animated type while
- // the lock is held. See crbug.com/581546.
- DCHECK(!AnimatedTypeIsLocked());
-
SVGElement* target_element = targetElement();
if (!target_element) {
animated_value_.Clear();
return;
}
- bool should_apply = ShouldApplyAnimation(*target_element, AttributeName());
+ bool should_apply = ShouldApplyAnimation(*target_element);
if (IsAnimatingCSSProperty()) {
// CSS properties animation code-path.
if (should_apply) {
@@ -477,7 +470,6 @@ void SVGAnimateElement::ClearAnimatedType() {
}
animated_value_.Clear();
- ClearTargetProperty();
}
void SVGAnimateElement::ApplyResultsToTarget() {
@@ -489,7 +481,7 @@ void SVGAnimateElement::ApplyResultsToTarget() {
return;
SVGElement* target_element = targetElement();
- if (!ShouldApplyAnimation(*target_element, AttributeName()))
+ if (!ShouldApplyAnimation(*target_element))
return;
// We do update the style and the animation property independent of each
@@ -520,7 +512,7 @@ void SVGAnimateElement::ApplyResultsToTarget() {
}
}
-bool SVGAnimateElement::AnimatedPropertyTypeSupportsAddition() {
+bool SVGAnimateElement::AnimatedPropertyTypeSupportsAddition() const {
// http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties.
switch (GetAnimatedPropertyType()) {
case kAnimatedBoolean:
@@ -534,7 +526,7 @@ bool SVGAnimateElement::AnimatedPropertyTypeSupportsAddition() {
}
}
-bool SVGAnimateElement::IsAdditive() {
+bool SVGAnimateElement::IsAdditive() const {
if (GetAnimationMode() == kByAnimation ||
GetAnimationMode() == kFromByAnimation) {
if (!AnimatedPropertyTypeSupportsAddition())
@@ -556,39 +548,46 @@ float SVGAnimateElement::CalculateDistance(const String& from_string,
void SVGAnimateElement::WillChangeAnimationTarget() {
SVGAnimationElement::WillChangeAnimationTarget();
- if (targetElement())
- ClearAnimatedType();
+ // Should be cleared by the above.
+ DCHECK(!animated_value_);
+ ResetCachedAnimationState();
}
void SVGAnimateElement::DidChangeAnimationTarget() {
+ // Call this before calling the super-class, because it will check
+ // HasValidTarget() which depends on the animation type being resolved.
+ UpdateTargetProperty();
SVGAnimationElement::DidChangeAnimationTarget();
- ResetAnimatedPropertyType();
}
void SVGAnimateElement::SetAttributeName(const QualifiedName& attribute_name) {
+ if (attribute_name == attribute_name_)
+ return;
WillChangeAnimationTarget();
attribute_name_ = attribute_name;
DidChangeAnimationTarget();
}
-void SVGAnimateElement::SetAttributeType(const AtomicString& attribute_type) {
+void SVGAnimateElement::SetAttributeType(
+ const AtomicString& attribute_type_string) {
+ AttributeType attribute_type = kAttributeTypeAuto;
+ if (attribute_type_string == "CSS")
+ attribute_type = kAttributeTypeCSS;
+ else if (attribute_type_string == "XML")
+ attribute_type = kAttributeTypeXML;
+ if (attribute_type == attribute_type_)
+ return;
WillChangeAnimationTarget();
- if (attribute_type == "CSS")
- attribute_type_ = kAttributeTypeCSS;
- else if (attribute_type == "XML")
- attribute_type_ = kAttributeTypeXML;
- else
- attribute_type_ = kAttributeTypeAuto;
+ attribute_type_ = attribute_type;
DidChangeAnimationTarget();
}
-void SVGAnimateElement::ResetAnimatedPropertyType() {
+void SVGAnimateElement::ResetCachedAnimationState() {
DCHECK(!animated_value_);
InvalidatedValuesCache();
from_property_.Clear();
to_property_.Clear();
to_at_end_of_duration_property_.Clear();
- ClearTargetProperty();
}
void SVGAnimateElement::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.h b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.h
index 094435aef5d..5bd334bb7ed 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_element.h
@@ -49,11 +49,11 @@ class CORE_EXPORT SVGAnimateElement : public SVGAnimationElement {
bool IsSVGAnimationAttributeSettingJavaScriptURL(
const Attribute&) const override;
- AnimatedPropertyType GetAnimatedPropertyType();
- bool AnimatedPropertyTypeSupportsAddition();
+ AnimatedPropertyType GetAnimatedPropertyType() const;
+ bool AnimatedPropertyTypeSupportsAddition() const;
protected:
- bool HasValidTarget() override;
+ bool HasValidTarget() const override;
void WillChangeAnimationTarget() final;
void DidChangeAnimationTarget() final;
@@ -73,7 +73,7 @@ class CORE_EXPORT SVGAnimateElement : public SVGAnimationElement {
void ApplyResultsToTarget() final;
float CalculateDistance(const String& from_string,
const String& to_string) final;
- bool IsAdditive() final;
+ bool IsAdditive() const final;
void ParseAttribute(const AttributeModificationParams&) override;
@@ -90,10 +90,9 @@ class CORE_EXPORT SVGAnimateElement : public SVGAnimationElement {
stringsShouldNotSupportAddition);
private:
- void ResetAnimatedPropertyType();
+ void ResetCachedAnimationState();
- bool ShouldApplyAnimation(const SVGElement& target_element,
- const QualifiedName& attribute_name);
+ bool ShouldApplyAnimation(const SVGElement& target_element) const;
void SetAttributeType(const AtomicString&);
@@ -102,6 +101,7 @@ class CORE_EXPORT SVGAnimateElement : public SVGAnimationElement {
virtual void ResolveTargetProperty();
void ClearTargetProperty();
+ void UpdateTargetProperty();
virtual SVGPropertyBase* CreatePropertyForAnimation(const String&) const;
SVGPropertyBase* CreatePropertyForAttributeAnimation(const String&) const;
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 c0c87d99464..d2815ff4b99 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
@@ -64,7 +64,7 @@ SVGAnimateMotionElement::SVGAnimateMotionElement(Document& document)
SVGAnimateMotionElement::~SVGAnimateMotionElement() = default;
-bool SVGAnimateMotionElement::HasValidTarget() {
+bool SVGAnimateMotionElement::HasValidTarget() const {
return SVGAnimationElement::HasValidTarget() &&
TargetCanHaveMotionTransform(*targetElement());
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.h b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.h
index 2b0eba2a85b..6ccda146b8a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_motion_element.h
@@ -36,7 +36,7 @@ class SVGAnimateMotionElement final : public SVGAnimationElement {
void UpdateAnimationPath();
private:
- bool HasValidTarget() override;
+ bool HasValidTarget() const override;
void ParseAttribute(const AttributeModificationParams&) override;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.cc
index c7a94f334bf..e1a894240c9 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.cc
@@ -33,7 +33,7 @@ SVGAnimateTransformElement::SVGAnimateTransformElement(Document& document)
: SVGAnimateElement(svg_names::kAnimateTransformTag, document),
transform_type_(SVGTransformType::kUnknown) {}
-bool SVGAnimateTransformElement::HasValidTarget() {
+bool SVGAnimateTransformElement::HasValidTarget() const {
if (!SVGAnimateElement::HasValidTarget())
return false;
if (GetAttributeType() == kAttributeTypeCSS)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.h b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.h
index 102b4c3f065..8260fab0a19 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animate_transform_element.h
@@ -35,7 +35,7 @@ class SVGAnimateTransformElement final : public SVGAnimateElement {
explicit SVGAnimateTransformElement(Document&);
private:
- bool HasValidTarget() override;
+ bool HasValidTarget() const override;
void ParseAttribute(const AttributeModificationParams&) override;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer_optional_integer.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer_optional_integer.h
index 97a6a6e584e..c637a4f1a08 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer_optional_integer.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer_optional_integer.h
@@ -44,7 +44,7 @@ namespace blink {
// |secondInteger| are used.
// For example, see SVGFEDropShadowElement::stdDeviation{X,Y}()
class SVGAnimatedIntegerOptionalInteger
- : public GarbageCollectedFinalized<SVGAnimatedIntegerOptionalInteger>,
+ : public GarbageCollected<SVGAnimatedIntegerOptionalInteger>,
public SVGAnimatedPropertyCommon<SVGIntegerOptionalInteger> {
USING_GARBAGE_COLLECTED_MIXIN(SVGAnimatedIntegerOptionalInteger);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_number_optional_number.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_number_optional_number.h
index b18b31d9592..dc7a84f099f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_number_optional_number.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_number_optional_number.h
@@ -44,7 +44,7 @@ namespace blink {
// are used.
// For example, see SVGFEDropShadowElement::stdDeviation{X,Y}()
class SVGAnimatedNumberOptionalNumber
- : public GarbageCollectedFinalized<SVGAnimatedNumberOptionalNumber>,
+ : public GarbageCollected<SVGAnimatedNumberOptionalNumber>,
public SVGAnimatedPropertyCommon<SVGNumberOptionalNumber> {
USING_GARBAGE_COLLECTED_MIXIN(SVGAnimatedNumberOptionalNumber);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_path.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_path.h
index efc6874414b..13f336eb678 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_path.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_path.h
@@ -36,7 +36,7 @@
namespace blink {
-class SVGAnimatedPath final : public GarbageCollectedFinalized<SVGAnimatedPath>,
+class SVGAnimatedPath final : public GarbageCollected<SVGAnimatedPath>,
public SVGAnimatedProperty<SVGPath> {
USING_GARBAGE_COLLECTED_MIXIN(SVGAnimatedPath);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_point_list.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_point_list.h
index d6af8b6b992..5cc6fbf57ef 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_point_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_point_list.h
@@ -37,7 +37,7 @@
namespace blink {
class SVGAnimatedPointList final
- : public GarbageCollectedFinalized<SVGAnimatedPointList>,
+ : public GarbageCollected<SVGAnimatedPointList>,
public SVGAnimatedProperty<SVGPointList> {
USING_GARBAGE_COLLECTED_MIXIN(SVGAnimatedPointList);
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 ea0042e8e6b..0040d0a602e 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
@@ -249,11 +249,11 @@ float SVGAnimationElement::getStartTime(ExceptionState& exception_state) const {
"No current interval.");
return 0;
}
- return clampTo<float>(start_time.Value());
+ return clampTo<float>(start_time.InSecondsF());
}
float SVGAnimationElement::getCurrentTime() const {
- return clampTo<float>(Elapsed().Value());
+ return clampTo<float>(Elapsed().InSecondsF());
}
float SVGAnimationElement::getSimpleDuration(
@@ -264,18 +264,19 @@ float SVGAnimationElement::getSimpleDuration(
"No simple duration defined.");
return 0;
}
- return clampTo<float>(duration.Value());
+ return clampTo<float>(duration.InSecondsF());
}
void SVGAnimationElement::beginElementAt(float offset) {
DCHECK(std::isfinite(offset));
- AddInstanceTime(kBegin, Elapsed() + offset,
- SMILTimeWithOrigin::kScriptOrigin);
+ AddInstanceTimeAndUpdate(kBegin, Elapsed() + SMILTime::FromSecondsD(offset),
+ SMILTimeOrigin::kScript);
}
void SVGAnimationElement::endElementAt(float offset) {
DCHECK(std::isfinite(offset));
- AddInstanceTime(kEnd, Elapsed() + offset, SMILTimeWithOrigin::kScriptOrigin);
+ AddInstanceTimeAndUpdate(kEnd, Elapsed() + SMILTime::FromSecondsD(offset),
+ SMILTimeOrigin::kScript);
}
void SVGAnimationElement::UpdateAnimationMode() {
@@ -329,7 +330,7 @@ String SVGAnimationElement::FromValue() const {
return FastGetAttribute(svg_names::kFromAttr);
}
-bool SVGAnimationElement::IsAdditive() {
+bool SVGAnimationElement::IsAdditive() const {
DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum"));
const AtomicString& value = FastGetAttribute(svg_names::kAdditiveAttr);
return value == sum || GetAnimationMode() == kByAnimation;
@@ -408,9 +409,9 @@ float SVGAnimationElement::CalculatePercentForSpline(
gfx::CubicBezier bezier = key_splines_[spline_index];
SMILTime duration = SimpleDuration();
if (!duration.IsFinite())
- duration = 100.0;
+ duration = SMILTime::FromSecondsD(100.0);
return clampTo<float>(
- bezier.SolveWithEpsilon(percent, SolveEpsilon(duration.Value())));
+ bezier.SolveWithEpsilon(percent, SolveEpsilon(duration.InSecondsF())));
}
float SVGAnimationElement::CalculatePercentFromKeyPoints(float percent) const {
@@ -528,6 +529,8 @@ void SVGAnimationElement::CurrentValuesForValuesAnimation(
}
void SVGAnimationElement::StartedActiveInterval() {
+ SVGSMILElement::StartedActiveInterval();
+
animation_valid_ = false;
if (!IsValid() || !HasValidTarget())
@@ -640,7 +643,7 @@ void SVGAnimationElement::UpdateAnimation(float percent,
CalculateAnimatedValue(effective_percent, repeat_count, result_element);
}
-bool SVGAnimationElement::OverwritesUnderlyingAnimationValue() {
+bool SVGAnimationElement::OverwritesUnderlyingAnimationValue() const {
return !IsAdditive() && !IsAccumulated() &&
GetAnimationMode() != kToAnimation &&
GetAnimationMode() != kByAnimation &&
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.h b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.h
index 3df1f11d0b2..92721a9317a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.h
@@ -69,12 +69,12 @@ class CORE_EXPORT SVGAnimationElement : public SVGSMILElement {
DEFINE_ATTRIBUTE_EVENT_LISTENER(end, kEndEvent)
DEFINE_ATTRIBUTE_EVENT_LISTENER(repeat, kRepeatEvent)
- virtual bool IsAdditive();
+ virtual bool IsAdditive() const;
bool IsAccumulated() const;
AnimationMode GetAnimationMode() const { return animation_mode_; }
CalcMode GetCalcMode() const { return calc_mode_; }
- bool OverwritesUnderlyingAnimationValue() override;
+ bool OverwritesUnderlyingAnimationValue() const override;
template <typename AnimatedType>
void AnimateDiscreteType(float percentage,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_attribute_names.json5 b/chromium/third_party/blink/renderer/core/svg/svg_attribute_names.json5
index a91c1f4d601..38fae5f226a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_attribute_names.json5
+++ b/chromium/third_party/blink/renderer/core/svg/svg_attribute_names.json5
@@ -14,6 +14,7 @@
"animate",
"attributeName",
"attributeType",
+ "autofocus",
"azimuth",
"baseFrequency",
"baseline-shift",
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_discard_element.h b/chromium/third_party/blink/renderer/core/svg/svg_discard_element.h
index 8b7b026349b..dffcf520f9b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_discard_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_discard_element.h
@@ -49,9 +49,8 @@ class SVGDiscardElement final : public SVGSMILElement {
void ApplyResultsToTarget() override {}
void AnimationAttributeChanged() override {}
- bool OverwritesUnderlyingAnimationValue() override { return false; }
+ bool OverwritesUnderlyingAnimationValue() const override { return false; }
- void StartedActiveInterval() override {}
void UpdateAnimation(float percent,
unsigned repeat,
SVGSMILElement* result_element) override {}
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 7972d0aff3a..abce5e913f8 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
@@ -35,8 +35,8 @@ class SVGElement;
class SVGSVGElement;
class SubtreeLayoutScope;
-class SVGDocumentExtensions
- : public GarbageCollectedFinalized<SVGDocumentExtensions> {
+class SVGDocumentExtensions final
+ : public GarbageCollected<SVGDocumentExtensions> {
public:
explicit SVGDocumentExtensions(Document*);
~SVGDocumentExtensions();
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 ced9ad46fe5..c38dc8b3d8b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.cc
@@ -49,6 +49,7 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h"
+#include "third_party/blink/renderer/core/layout/svg/transform_helper.h"
#include "third_party/blink/renderer/core/svg/properties/svg_property.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/core/svg/svg_element_rare_data.h"
@@ -59,14 +60,10 @@
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/core/xml_names.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
-using namespace html_names;
-using namespace svg_names;
-
SVGElement::SVGElement(const QualifiedName& tag_name,
Document& document,
ConstructionType construction_type)
@@ -297,76 +294,13 @@ bool SVGElement::HasTransform(
HasSVGRareData());
}
-static inline bool TransformUsesBoxSize(const ComputedStyle& style) {
- if ((style.TransformOriginX().IsPercent() ||
- style.TransformOriginY().IsPercent()) &&
- style.RequireTransformOrigin(ComputedStyle::kIncludeTransformOrigin,
- ComputedStyle::kExcludeMotionPath))
- return true;
- if (style.Transform().DependsOnBoxSize())
- return true;
- if (style.Translate() && style.Translate()->DependsOnBoxSize())
- return true;
- if (style.HasOffset())
- return true;
- return false;
-}
-
-FloatRect ComputeSVGTransformReferenceBox(const LayoutObject& layout_object) {
- const ComputedStyle& style = layout_object.StyleRef();
- FloatRect reference_box;
- if (style.TransformBox() == ETransformBox::kFillBox) {
- reference_box = layout_object.ObjectBoundingBox();
- } else {
- DCHECK_EQ(style.TransformBox(), ETransformBox::kViewBox);
- SVGLengthContext length_context(
- DynamicTo<SVGElement>(layout_object.GetNode()));
- FloatSize viewport_size;
- length_context.DetermineViewport(viewport_size);
- reference_box.SetSize(viewport_size);
- }
- const float zoom = style.EffectiveZoom();
- if (zoom != 1)
- reference_box.Scale(zoom);
- return reference_box;
-}
-
AffineTransform SVGElement::CalculateTransform(
ApplyMotionTransform apply_motion_transform) const {
- const ComputedStyle* style =
- GetLayoutObject() ? GetLayoutObject()->Style() : nullptr;
+ const LayoutObject* layout_object = GetLayoutObject();
- // If CSS property was set, use that, otherwise fallback to attribute (if
- // set).
AffineTransform matrix;
- if (style && style->HasTransform()) {
- if (TransformUsesBoxSize(*style))
- UseCounter::Count(GetDocument(), WebFeature::kTransformUsesBoxSizeOnSVG);
-
- // CSS transforms operate with pre-scaled lengths. To make this work with
- // SVG (which applies the zoom factor globally, at the root level) we
- //
- // * pre-scale the reference box (to bring it into the same space as the
- // other CSS values) (Handled by ComputeSVGTransformReferenceBox)
- // * invert the zoom factor (to effectively compute the CSS transform
- // under a 1.0 zoom)
- //
- // Note: objectBoundingBox is an emptyRect for elements like pattern or
- // clipPath. See
- // https://svgwg.org/svg2-draft/coords.html#ObjectBoundingBoxUnits
- TransformationMatrix transform;
- FloatRect reference_box =
- ComputeSVGTransformReferenceBox(*GetLayoutObject());
- style->ApplyTransform(
- transform, reference_box, ComputedStyle::kIncludeTransformOrigin,
- ComputedStyle::kIncludeMotionPath,
- ComputedStyle::kIncludeIndependentTransformProperties);
- const float zoom = style->EffectiveZoom();
- if (zoom != 1)
- transform.Zoom(1 / zoom);
- // Flatten any 3D transform.
- matrix = transform.ToAffineTransform();
- }
+ if (layout_object && layout_object->StyleRef().HasTransform())
+ matrix = TransformHelper::ComputeTransform(*layout_object);
// Apply any "motion transform" contribution if requested (and existing.)
if (apply_motion_transform == kIncludeMotionTransform && HasSVGRareData())
@@ -380,12 +314,12 @@ Node::InsertionNotificationRequest SVGElement::InsertedInto(
Element::InsertedInto(root_parent);
UpdateRelativeLengthsInformation();
- const AtomicString& nonce_value = FastGetAttribute(kNonceAttr);
+ const AtomicString& nonce_value = FastGetAttribute(html_names::kNonceAttr);
if (!nonce_value.IsEmpty()) {
setNonce(nonce_value);
if (InActiveDocument() &&
GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy()) {
- setAttribute(kNonceAttr, g_empty_atom);
+ setAttribute(html_names::kNonceAttr, g_empty_atom);
}
}
return kInsertionDone;
@@ -440,64 +374,64 @@ CSSPropertyID SVGElement::CssPropertyIdForSVGAttributeName(
// This is a list of all base CSS and SVG CSS properties which are exposed
// as SVG XML attributes
const QualifiedName* const attr_names[] = {
- &kAlignmentBaselineAttr,
- &kBaselineShiftAttr,
- &kBufferedRenderingAttr,
- &kClipAttr,
- &kClipPathAttr,
- &kClipRuleAttr,
+ &svg_names::kAlignmentBaselineAttr,
+ &svg_names::kBaselineShiftAttr,
+ &svg_names::kBufferedRenderingAttr,
+ &svg_names::kClipAttr,
+ &svg_names::kClipPathAttr,
+ &svg_names::kClipRuleAttr,
&svg_names::kColorAttr,
- &kColorInterpolationAttr,
- &kColorInterpolationFiltersAttr,
- &kColorRenderingAttr,
- &kCursorAttr,
+ &svg_names::kColorInterpolationAttr,
+ &svg_names::kColorInterpolationFiltersAttr,
+ &svg_names::kColorRenderingAttr,
+ &svg_names::kCursorAttr,
&svg_names::kDirectionAttr,
- &kDisplayAttr,
- &kDominantBaselineAttr,
- &kFillAttr,
- &kFillOpacityAttr,
- &kFillRuleAttr,
- &kFilterAttr,
- &kFloodColorAttr,
- &kFloodOpacityAttr,
- &kFontFamilyAttr,
- &kFontSizeAttr,
- &kFontStretchAttr,
- &kFontStyleAttr,
- &kFontVariantAttr,
- &kFontWeightAttr,
- &kImageRenderingAttr,
- &kLetterSpacingAttr,
- &kLightingColorAttr,
- &kMarkerEndAttr,
- &kMarkerMidAttr,
- &kMarkerStartAttr,
- &kMaskAttr,
- &kMaskTypeAttr,
- &kOpacityAttr,
- &kOverflowAttr,
- &kPaintOrderAttr,
- &kPointerEventsAttr,
- &kShapeRenderingAttr,
- &kStopColorAttr,
- &kStopOpacityAttr,
- &kStrokeAttr,
- &kStrokeDasharrayAttr,
- &kStrokeDashoffsetAttr,
- &kStrokeLinecapAttr,
- &kStrokeLinejoinAttr,
- &kStrokeMiterlimitAttr,
- &kStrokeOpacityAttr,
- &kStrokeWidthAttr,
- &kTextAnchorAttr,
- &kTextDecorationAttr,
- &kTextRenderingAttr,
- &kTransformOriginAttr,
- &kUnicodeBidiAttr,
- &kVectorEffectAttr,
- &kVisibilityAttr,
- &kWordSpacingAttr,
- &kWritingModeAttr,
+ &svg_names::kDisplayAttr,
+ &svg_names::kDominantBaselineAttr,
+ &svg_names::kFillAttr,
+ &svg_names::kFillOpacityAttr,
+ &svg_names::kFillRuleAttr,
+ &svg_names::kFilterAttr,
+ &svg_names::kFloodColorAttr,
+ &svg_names::kFloodOpacityAttr,
+ &svg_names::kFontFamilyAttr,
+ &svg_names::kFontSizeAttr,
+ &svg_names::kFontStretchAttr,
+ &svg_names::kFontStyleAttr,
+ &svg_names::kFontVariantAttr,
+ &svg_names::kFontWeightAttr,
+ &svg_names::kImageRenderingAttr,
+ &svg_names::kLetterSpacingAttr,
+ &svg_names::kLightingColorAttr,
+ &svg_names::kMarkerEndAttr,
+ &svg_names::kMarkerMidAttr,
+ &svg_names::kMarkerStartAttr,
+ &svg_names::kMaskAttr,
+ &svg_names::kMaskTypeAttr,
+ &svg_names::kOpacityAttr,
+ &svg_names::kOverflowAttr,
+ &svg_names::kPaintOrderAttr,
+ &svg_names::kPointerEventsAttr,
+ &svg_names::kShapeRenderingAttr,
+ &svg_names::kStopColorAttr,
+ &svg_names::kStopOpacityAttr,
+ &svg_names::kStrokeAttr,
+ &svg_names::kStrokeDasharrayAttr,
+ &svg_names::kStrokeDashoffsetAttr,
+ &svg_names::kStrokeLinecapAttr,
+ &svg_names::kStrokeLinejoinAttr,
+ &svg_names::kStrokeMiterlimitAttr,
+ &svg_names::kStrokeOpacityAttr,
+ &svg_names::kStrokeWidthAttr,
+ &svg_names::kTextAnchorAttr,
+ &svg_names::kTextDecorationAttr,
+ &svg_names::kTextRenderingAttr,
+ &svg_names::kTransformOriginAttr,
+ &svg_names::kUnicodeBidiAttr,
+ &svg_names::kVectorEffectAttr,
+ &svg_names::kVisibilityAttr,
+ &svg_names::kWordSpacingAttr,
+ &svg_names::kWritingModeAttr,
};
for (size_t i = 0; i < base::size(attr_names); i++) {
CSSPropertyID property_id = cssPropertyID(attr_names[i]->LocalName());
@@ -729,59 +663,59 @@ AnimatedPropertyType SVGElement::AnimatedPropertyTypeForCSSAttribute(
const AnimatedPropertyType prop_type;
};
const AttrToTypeEntry attr_to_types[] = {
- {kAlignmentBaselineAttr, kAnimatedString},
- {kBaselineShiftAttr, kAnimatedString},
- {kBufferedRenderingAttr, kAnimatedString},
- {kClipPathAttr, kAnimatedString},
- {kClipRuleAttr, kAnimatedString},
+ {svg_names::kAlignmentBaselineAttr, kAnimatedString},
+ {svg_names::kBaselineShiftAttr, kAnimatedString},
+ {svg_names::kBufferedRenderingAttr, kAnimatedString},
+ {svg_names::kClipPathAttr, kAnimatedString},
+ {svg_names::kClipRuleAttr, kAnimatedString},
{svg_names::kColorAttr, kAnimatedColor},
- {kColorInterpolationAttr, kAnimatedString},
- {kColorInterpolationFiltersAttr, kAnimatedString},
- {kColorRenderingAttr, kAnimatedString},
- {kCursorAttr, kAnimatedString},
- {kDisplayAttr, kAnimatedString},
- {kDominantBaselineAttr, kAnimatedString},
- {kFillAttr, kAnimatedColor},
- {kFillOpacityAttr, kAnimatedNumber},
- {kFillRuleAttr, kAnimatedString},
- {kFilterAttr, kAnimatedString},
- {kFloodColorAttr, kAnimatedColor},
- {kFloodOpacityAttr, kAnimatedNumber},
- {kFontFamilyAttr, kAnimatedString},
- {kFontSizeAttr, kAnimatedLength},
- {kFontStretchAttr, kAnimatedString},
- {kFontStyleAttr, kAnimatedString},
- {kFontVariantAttr, kAnimatedString},
- {kFontWeightAttr, kAnimatedString},
- {kImageRenderingAttr, kAnimatedString},
- {kLetterSpacingAttr, kAnimatedLength},
- {kLightingColorAttr, kAnimatedColor},
- {kMarkerEndAttr, kAnimatedString},
- {kMarkerMidAttr, kAnimatedString},
- {kMarkerStartAttr, kAnimatedString},
- {kMaskAttr, kAnimatedString},
- {kMaskTypeAttr, kAnimatedString},
- {kOpacityAttr, kAnimatedNumber},
- {kOverflowAttr, kAnimatedString},
- {kPaintOrderAttr, kAnimatedString},
- {kPointerEventsAttr, kAnimatedString},
- {kShapeRenderingAttr, kAnimatedString},
- {kStopColorAttr, kAnimatedColor},
- {kStopOpacityAttr, kAnimatedNumber},
- {kStrokeAttr, kAnimatedColor},
- {kStrokeDasharrayAttr, kAnimatedLengthList},
- {kStrokeDashoffsetAttr, kAnimatedLength},
- {kStrokeLinecapAttr, kAnimatedString},
- {kStrokeLinejoinAttr, kAnimatedString},
- {kStrokeMiterlimitAttr, kAnimatedNumber},
- {kStrokeOpacityAttr, kAnimatedNumber},
- {kStrokeWidthAttr, kAnimatedLength},
- {kTextAnchorAttr, kAnimatedString},
- {kTextDecorationAttr, kAnimatedString},
- {kTextRenderingAttr, kAnimatedString},
- {kVectorEffectAttr, kAnimatedString},
- {kVisibilityAttr, kAnimatedString},
- {kWordSpacingAttr, kAnimatedLength},
+ {svg_names::kColorInterpolationAttr, kAnimatedString},
+ {svg_names::kColorInterpolationFiltersAttr, kAnimatedString},
+ {svg_names::kColorRenderingAttr, kAnimatedString},
+ {svg_names::kCursorAttr, kAnimatedString},
+ {svg_names::kDisplayAttr, kAnimatedString},
+ {svg_names::kDominantBaselineAttr, kAnimatedString},
+ {svg_names::kFillAttr, kAnimatedColor},
+ {svg_names::kFillOpacityAttr, kAnimatedNumber},
+ {svg_names::kFillRuleAttr, kAnimatedString},
+ {svg_names::kFilterAttr, kAnimatedString},
+ {svg_names::kFloodColorAttr, kAnimatedColor},
+ {svg_names::kFloodOpacityAttr, kAnimatedNumber},
+ {svg_names::kFontFamilyAttr, kAnimatedString},
+ {svg_names::kFontSizeAttr, kAnimatedLength},
+ {svg_names::kFontStretchAttr, kAnimatedString},
+ {svg_names::kFontStyleAttr, kAnimatedString},
+ {svg_names::kFontVariantAttr, kAnimatedString},
+ {svg_names::kFontWeightAttr, kAnimatedString},
+ {svg_names::kImageRenderingAttr, kAnimatedString},
+ {svg_names::kLetterSpacingAttr, kAnimatedLength},
+ {svg_names::kLightingColorAttr, kAnimatedColor},
+ {svg_names::kMarkerEndAttr, kAnimatedString},
+ {svg_names::kMarkerMidAttr, kAnimatedString},
+ {svg_names::kMarkerStartAttr, kAnimatedString},
+ {svg_names::kMaskAttr, kAnimatedString},
+ {svg_names::kMaskTypeAttr, kAnimatedString},
+ {svg_names::kOpacityAttr, kAnimatedNumber},
+ {svg_names::kOverflowAttr, kAnimatedString},
+ {svg_names::kPaintOrderAttr, kAnimatedString},
+ {svg_names::kPointerEventsAttr, kAnimatedString},
+ {svg_names::kShapeRenderingAttr, kAnimatedString},
+ {svg_names::kStopColorAttr, kAnimatedColor},
+ {svg_names::kStopOpacityAttr, kAnimatedNumber},
+ {svg_names::kStrokeAttr, kAnimatedColor},
+ {svg_names::kStrokeDasharrayAttr, kAnimatedLengthList},
+ {svg_names::kStrokeDashoffsetAttr, kAnimatedLength},
+ {svg_names::kStrokeLinecapAttr, kAnimatedString},
+ {svg_names::kStrokeLinejoinAttr, kAnimatedString},
+ {svg_names::kStrokeMiterlimitAttr, kAnimatedNumber},
+ {svg_names::kStrokeOpacityAttr, kAnimatedNumber},
+ {svg_names::kStrokeWidthAttr, kAnimatedLength},
+ {svg_names::kTextAnchorAttr, kAnimatedString},
+ {svg_names::kTextDecorationAttr, kAnimatedString},
+ {svg_names::kTextRenderingAttr, kAnimatedString},
+ {svg_names::kVectorEffectAttr, kAnimatedString},
+ {svg_names::kVisibilityAttr, kAnimatedString},
+ {svg_names::kWordSpacingAttr, kAnimatedLength},
};
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);
@@ -1066,10 +1000,8 @@ const ComputedStyle* SVGElement::EnsureComputedStyle(
return Element::EnsureComputedStyle(pseudo_element_specifier);
const ComputedStyle* parent_style = nullptr;
- if (Element* parent = ParentOrShadowHostElement()) {
- if (LayoutObject* layout_object = parent->GetLayoutObject())
- parent_style = layout_object->Style();
- }
+ if (ContainerNode* parent = LayoutTreeBuilderTraversal::Parent(*this))
+ parent_style = parent->EnsureComputedStyle();
return SvgRareData()->OverrideComputedStyle(this, parent_style);
}
@@ -1230,7 +1162,7 @@ bool SVGElement::IsAnimatableAttribute(const QualifiedName& name) const {
svg_names::kZAttr,
}));
- if (name == kClassAttr)
+ if (name == html_names::kClassAttr)
return true;
return animatable_attributes.Contains(name);
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 a139aa8b988..256997ed321 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_element.h
@@ -37,7 +37,6 @@ namespace blink {
class AffineTransform;
class Document;
-class FloatRect;
class SVGAnimatedPropertyBase;
class SubtreeLayoutScope;
class SVGAnimatedString;
@@ -334,8 +333,6 @@ struct SVGAttributeHashTranslator {
}
};
-FloatRect ComputeSVGTransformReferenceBox(const LayoutObject&);
-
DEFINE_ELEMENT_TYPE_CASTS(SVGElement, IsSVGElement());
template <>
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 4478f9dd6e7..06932283686 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
@@ -31,8 +31,7 @@ namespace blink {
class SVGResourceClient;
-class SVGElementRareData
- : public GarbageCollectedFinalized<SVGElementRareData> {
+class SVGElementRareData final : public GarbageCollected<SVGElementRareData> {
public:
SVGElementRareData()
: corresponding_element_(nullptr),
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.cc
index 6ccb144d5c6..676129d2787 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.cc
@@ -125,6 +125,21 @@ void SVGForeignObjectElement::SvgAttributeChanged(
LayoutObject* SVGForeignObjectElement::CreateLayoutObject(const ComputedStyle&,
LegacyLayout) {
+ // Suppress foreignObject LayoutObjects in SVG hidden containers.
+ // LayoutSVGHiddenContainers does not allow the subtree to be rendered, but
+ // allow LayoutObject descendants to be created. That will causes crashes in
+ // the layout code if object creation is not inhibited for foreignObject
+ // subtrees (https://crbug.com/1027905).
+ // Note that we currently do not support foreignObject instantiation via
+ // <use>, and attachShadow is not allowed on SVG elements, hence it is safe to
+ // use parentElement() here.
+ for (Element* ancestor = parentElement();
+ ancestor && ancestor->IsSVGElement();
+ ancestor = ancestor->parentElement()) {
+ if (ancestor->GetLayoutObject() &&
+ ancestor->GetLayoutObject()->IsSVGHiddenContainer())
+ return nullptr;
+ }
return new LayoutSVGForeignObject(this);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element_test.cc b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element_test.cc
new file mode 100644
index 00000000000..42d0805ac57
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element_test.cc
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/svg/svg_foreign_object_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/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+class SVGForeignObjectElementTest : public PageTestBase {};
+
+TEST_F(SVGForeignObjectElementTest, NoLayoutObjectInNonRendered) {
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <svg>
+ <pattern>
+ <foreignObject id="fo"></foreignObject>
+ </pattern>
+ </svg>
+ )HTML");
+
+ UpdateAllLifecyclePhasesForTest();
+
+ Element* foreign_object = GetDocument().getElementById("fo");
+ EXPECT_FALSE(foreign_object->GetLayoutObject());
+
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ LayoutObject* layout_object =
+ foreign_object->CreateLayoutObject(*style, LegacyLayout::kAuto);
+ EXPECT_FALSE(layout_object);
+}
+
+TEST_F(SVGForeignObjectElementTest, ReferenceForeignObjectInNonRenderedCrash) {
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ div { writing-mode: vertical-rl; }
+ div > svg { float: right; }
+ </style>
+ <svg>
+ <radialGradient id="gradient">
+ <pattern>
+ <foreignObject>
+ <div id="foRoot">
+ <svg><rect fill="url(#gradient)" /></svg>
+ </div>
+ </foreignObject>
+ </pattern>
+ </radialGradient>
+ </svg>
+ )HTML");
+
+ // This should not trigger any DCHECK failures or crashes.
+ UpdateAllLifecyclePhasesForTest();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_image_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_image_element.cc
index ca72c644339..2cf3d0214b3 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_image_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_image_element.cc
@@ -223,9 +223,9 @@ const AtomicString SVGImageElement::ImageSourceURL() const {
}
void SVGImageElement::DidMoveToNewDocument(Document& old_document) {
- GetImageLoader().UpdateFromElement(ImageLoader::kUpdateIgnorePreviousError);
GetImageLoader().ElementDidMoveToNewDocument();
SVGGraphicsElement::DidMoveToNewDocument(old_document);
+ GetImageLoader().UpdateFromElement(ImageLoader::kUpdateIgnorePreviousError);
}
} // 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 7bf0b3aa4c5..21c8ca6a5ca 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_resource.h
@@ -59,7 +59,7 @@ class TreeScope;
//
// <event> -> SVG...Element -> SVGResource -> SVGResourceClient(0..N)
//
-class SVGResource : public GarbageCollectedFinalized<SVGResource> {
+class SVGResource : public GarbageCollected<SVGResource> {
public:
virtual ~SVGResource();
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
index 452445198a4..81beaf48b07 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_static_string_list.h
@@ -43,9 +43,8 @@ class SVGElement;
// SVGStringList property implementations for SVGTests properties.
// Inherits SVGAnimatedPropertyBase to enable XML attribute synchronization, but
// this is never animated.
-class SVGStaticStringList final
- : public GarbageCollectedFinalized<SVGStaticStringList>,
- public SVGAnimatedPropertyBase {
+class SVGStaticStringList final : public GarbageCollected<SVGStaticStringList>,
+ public SVGAnimatedPropertyBase {
USING_GARBAGE_COLLECTED_MIXIN(SVGStaticStringList);
public:
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 c559f9d8bbd..3326341fa5a 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
@@ -559,13 +559,12 @@ bool SVGSVGElement::animationsPaused() const {
}
float SVGSVGElement::getCurrentTime() const {
- return clampTo<float>(time_container_->Elapsed());
+ return clampTo<float>(time_container_->Elapsed().InSecondsF());
}
void SVGSVGElement::setCurrentTime(float seconds) {
DCHECK(std::isfinite(seconds));
- seconds = max(seconds, 0.0f);
- time_container_->SetElapsed(seconds);
+ time_container_->SetElapsed(SMILTime::FromSecondsD(std::max(seconds, 0.0f)));
}
bool SVGSVGElement::SelfHasRelativeLengths() const {
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 ebf436c91f4..f6fbe0c93a4 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
@@ -18,8 +18,8 @@ class TreeScope;
// This class keeps track of SVG resources and pending references to such for a
// TreeScope. It's per-TreeScope because that matches the lookup scope of an
// element's id (which is used to identify a resource.)
-class SVGTreeScopeResources
- : public GarbageCollectedFinalized<SVGTreeScopeResources> {
+class SVGTreeScopeResources final
+ : public GarbageCollected<SVGTreeScopeResources> {
public:
explicit SVGTreeScopeResources(TreeScope*);
~SVGTreeScopeResources();
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 2dbf14262ca..078fbe957c5 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
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/svg/svg_use_element.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -203,7 +204,20 @@ void SVGUseElement::UpdateTargetReference() {
FetchParameters params(ResourceRequest(element_url_), options);
params.MutableResourceRequest().SetMode(
network::mojom::RequestMode::kSameOrigin);
- DocumentResource::FetchSVGDocument(params, GetDocument().Fetcher(), this);
+ ResourceFetcher* fetcher = GetDocument().Fetcher();
+ if (base::FeatureList::IsEnabled(
+ features::kHtmlImportsRequestInitiatorLock)) {
+ // For @imports from HTML imported Documents, we use the
+ // context document for getting origin and ResourceFetcher to use the
+ // main Document's origin, while using the element document for
+ // CompleteURL() to use imported Documents' base URLs.
+ if (!GetDocument().ContextDocument()) {
+ ClearResource();
+ return;
+ }
+ fetcher = GetDocument().ContextDocument()->Fetcher();
+ }
+ DocumentResource::FetchSVGDocument(params, fetcher, this);
}
void SVGUseElement::SvgAttributeChanged(const QualifiedName& attr_name) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
index 6b8dee6edc7..41867c78786 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
@@ -30,7 +30,7 @@ class SVGRect;
class SVGTransformList;
class SVGViewElement;
-class SVGViewSpec final : public GarbageCollectedFinalized<SVGViewSpec> {
+class SVGViewSpec final : public GarbageCollected<SVGViewSpec> {
public:
static SVGViewSpec* CreateFromFragment(const String&);
static SVGViewSpec* CreateForViewElement(const SVGViewElement&);
diff --git a/chromium/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html b/chromium/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
index 105278fad24..5c1879faf1c 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/composited_selection_bounds_split_layer.html
@@ -9,7 +9,7 @@
}
.composited {
- transform: translateZ(0);
+ will-change: transform;
}
</style>
<div id="layer1" class="composited">The quick brown fox</div>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/compositor-worker-basic.html b/chromium/third_party/blink/renderer/core/testing/data/compositor-worker-basic.html
deleted file mode 100644
index ca8b76065d0..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/compositor-worker-basic.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE HTML>
-<style>
-#proxied {
- width: 50px;
- height: 50px;
- background: papayawhip;
-}
-#proxied-scroller {
- width: 100px;
- height: 100px;
- overflow: scroll;
- border: 1px solid black;
-}
-#scrolled {
- width: 50px;
- height: 1000px;
- background: papayawhip;
-}
-#tall {
- width: 50px;
- height: 2000px;
- background: papayawhip;
-}
-
-</style>
-<div id="proxied-transform"></div>
-<div id="proxied-opacity"></div>
-<div id="proxied-transform-and-opacity"></div> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/testing/data/editable_elements.html b/chromium/third_party/blink/renderer/core/testing/data/editable_elements.html
index 9fdd82d21b4..4a44087e4b2 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/editable_elements.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/editable_elements.html
@@ -1,9 +1,12 @@
<!DOCTYPE html>
<body>
- <input autofocus>
+ <input>
<input>
<input>
<input type="number">
<p contenteditable="true">blabla</p>
- <button>
+ <button></button>
+ <script>
+ document.querySelector('input').focus();
+ </script>
</body>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/fullscreen_style.html b/chromium/third_party/blink/renderer/core/testing/data/fullscreen_style.html
index a1c95d0cd51..126feb5b27a 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/fullscreen_style.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/fullscreen_style.html
@@ -10,7 +10,7 @@
margin: 0px;
}
- body:-webkit-full-screen-ancestor > :not(:-webkit-full-screen-ancestor):not(:-webkit-full-screen) {
+ body:-webkit-full-screen-ancestor > :not(:-webkit-full-screen-ancestor):not(:fullscreen) {
display: none!important
}
diff --git a/chromium/third_party/blink/renderer/core/testing/data/fullscreen_video.html b/chromium/third_party/blink/renderer/core/testing/data/fullscreen_video.html
index 55382798d99..7ff4c5c0099 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/fullscreen_video.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/fullscreen_video.html
@@ -1,4 +1,8 @@
<!DOCTYPE html>
-<body>
- <video src="test.webm" id="video" autoplay controls/>
+<body style="border: 10px solid red">
+ "Body text"
+ <video src="test.webm" id="video" autoplay controls></video>
+ <div id="other" style="will-change: transform; transform: translate(1px, 1px);">
+ "Other text"
+ </div>
</body>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/rgm_test.html b/chromium/third_party/blink/renderer/core/testing/data/rgm_test.html
index 9c0ea9f2d8d..1e4e9a2e846 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/rgm_test.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/rgm_test.html
@@ -2,7 +2,7 @@
div {
border-style:solid;
border-width:1px;
- transform:translate3d(0, 0, 0);
+ will-change:transform;
position:relative;
padding:5px 0px;
width:500px;
diff --git a/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight.html b/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight.html
index 9254ca5b07d..b559dea797b 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight.html
@@ -29,10 +29,14 @@
<div style="position: absolute; left: 20px; top: 260px; width: 200px;">
<input type="text"> <!-- This will have an I-beam cursor. -->
</div>
- <div style="position: absolute; left: 20px; top: 300px; width: 400px; height: 50px; columns: 2">
+ <style>
+ #multicol { position: absolute; left: 20px; top: 300px; width: 400px; height: 50px; columns: 2; column-fill: auto; }
+ </style>
+ <div id="multicol">
<a href="http://www.test.com">
- <div style="display: inline-block; width: 200px; height: 50px">Link in column 1</div>
- <div style="display: inline-block; width: 200px; height: 50px">Link in column 2</div>
+ <div style="display: inline-block; width: 200px; height: 25px">Link part 1</div>
+ <div style="display: inline-block; width: 200px; height: 25px">Link part 2</div>
+ <div style="display: inline-block; width: 200px; height: 25px">Link part 3</div>
</a>
</div>
</body>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html b/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html
deleted file mode 100644
index a2f5d90ef50..00000000000
--- a/chromium/third_party/blink/renderer/core/testing/data/test_touch_link_highlight_squashing.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-
-<style>
- .abs {
- position: absolute;
- top: 5;
- left: 5;
- width: 512px;
- height: 512px;
- }
-
- #target {
- display: block;
- transform: scale(0.5);
- transform-origin: left top;
- background-color: green;
- }
-</style>
-<div class=abs style="will-change: transform; pointer-events: none;"></div>
-<a class=abs id=target href="javascript:void(0)"></a>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/webxr_overlay.html b/chromium/third_party/blink/renderer/core/testing/data/webxr_overlay.html
new file mode 100644
index 00000000000..a4352873ee6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/webxr_overlay.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<body style="border: 10px solid red">
+ "Body text"
+ <div id="overlay">
+ "Overlay text"
+ <div id="inner" style="will-change: transform;
+ transform: translate(20px, 20px);
+ background: blue;
+ width: 150px;
+ height: 50px">
+ "Inner text"
+ </div>
+ </div>
+ <div id="other" style="will-change: transform; transform: translate(1px, 1px);">
+ "Other text"
+ </div>
+</body>
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 368c08dd3a3..c7024908e52 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
@@ -297,8 +297,11 @@ void DictionaryTest::GetDerivedDerivedInternals(
void DictionaryTest::Trace(blink::Visitor* visitor) {
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_member_);
visitor->Trace(event_target_or_null_member_);
+ visitor->Trace(any_member_);
visitor->Trace(callback_function_member_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h b/chromium/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h
index 6e0d0881917..f00a018aaa2 100644
--- a/chromium/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h
@@ -9,7 +9,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-blink.h"
#include "third_party/blink/renderer/core/testing/test_document_interface_broker.h"
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 7ab91689ad0..c9db16d8f17 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -59,6 +59,10 @@ bool DummyModulator::IsScriptingDisabled() const {
return false;
}
+bool DummyModulator::ImportMapsEnabled() const {
+ return false;
+}
+
bool DummyModulator::BuiltInModuleInfraEnabled() const {
return false;
}
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 6d9ec5c7b44..8b862e3eb36 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -35,6 +35,7 @@ class DummyModulator : public Modulator {
V8CacheOptions GetV8CacheOptions() const override;
bool IsScriptingDisabled() const override;
+ bool ImportMapsEnabled() const override;
bool BuiltInModuleInfraEnabled() const override;
bool BuiltInModuleEnabled(blink::layered_api::Module) const override;
void BuiltInModuleUseCount(blink::layered_api::Module) const override;
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
new file mode 100644
index 00000000000..f7abdf58df4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/testing/fake_local_frame_host.h"
+
+#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink.h"
+
+namespace blink {
+
+void FakeLocalFrameHost::Init(blink::AssociatedInterfaceProvider* provider) {
+ provider->OverrideBinderForTesting(
+ mojom::blink::LocalFrameHost::Name_,
+ base::BindRepeating(&FakeLocalFrameHost::BindFrameHostReceiver,
+ base::Unretained(this)));
+}
+
+void FakeLocalFrameHost::EnterFullscreen(
+ mojom::blink::FullscreenOptionsPtr options) {}
+
+void FakeLocalFrameHost::ExitFullscreen() {}
+
+void FakeLocalFrameHost::FullscreenStateChanged(bool is_fullscreen) {}
+
+void FakeLocalFrameHost::BindFrameHostReceiver(
+ mojo::ScopedInterfaceEndpointHandle handle) {
+ receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::blink::LocalFrameHost>(
+ std::move(handle)));
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..d3bf0d0d8ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_FAKE_LOCAL_FRAME_HOST_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_FAKE_LOCAL_FRAME_HOST_H_
+
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
+
+namespace blink {
+
+// This class implements a LocalFrameHost that can be attached to the
+// AssociatedInterfaceProvider so that it will be called when the renderer
+// normally sends a request to the browser process. But for a unittest
+// setup it can be intercepted by this class.
+class FakeLocalFrameHost : public mojom::blink::LocalFrameHost {
+ public:
+ FakeLocalFrameHost() = default;
+
+ void Init(blink::AssociatedInterfaceProvider* provider);
+ void EnterFullscreen(mojom::blink::FullscreenOptionsPtr options) override;
+ void ExitFullscreen() override;
+ void FullscreenStateChanged(bool is_fullscreen) override;
+
+ private:
+ void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
+
+ mojo::AssociatedReceiver<mojom::blink::LocalFrameHost> receiver_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_FAKE_LOCAL_FRAME_HOST_H_
diff --git a/chromium/third_party/blink/renderer/core/testing/internal_settings.cc b/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
index 5598ba3e5d8..6bd20dd6ee8 100644
--- a/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
@@ -400,15 +400,15 @@ void InternalSettings::setDisplayModeOverride(const String& display_mode,
InternalSettingsGuardForSettings();
String token = display_mode.StripWhiteSpace();
- WebDisplayMode mode = kWebDisplayModeBrowser;
+ auto mode = blink::mojom::DisplayMode::kBrowser;
if (token == "browser") {
- mode = kWebDisplayModeBrowser;
+ mode = blink::mojom::DisplayMode::kBrowser;
} else if (token == "minimal-ui") {
- mode = kWebDisplayModeMinimalUi;
+ mode = blink::mojom::DisplayMode::kMinimalUi;
} else if (token == "standalone") {
- mode = kWebDisplayModeStandalone;
+ mode = blink::mojom::DisplayMode::kStandalone;
} else if (token == "fullscreen") {
- mode = kWebDisplayModeFullscreen;
+ mode = blink::mojom::DisplayMode::kFullscreen;
} else {
exception_state.ThrowDOMException(
DOMExceptionCode::kSyntaxError,
diff --git a/chromium/third_party/blink/renderer/core/testing/internal_settings.h b/chromium/third_party/blink/renderer/core/testing/internal_settings.h
index bc47e065cc4..dd572cfb684 100644
--- a/chromium/third_party/blink/renderer/core/testing/internal_settings.h
+++ b/chromium/third_party/blink/renderer/core/testing/internal_settings.h
@@ -27,7 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNAL_SETTINGS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNAL_SETTINGS_H_
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/renderer/core/editing/editing_behavior_types.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/testing/internal_settings_generated.h"
@@ -67,7 +67,7 @@ class InternalSettings final : public InternalSettingsGenerated,
IntSize original_text_autosizing_window_size_override_;
float original_accessibility_font_scale_factor_;
String original_media_type_override_;
- WebDisplayMode original_display_mode_override_;
+ blink::mojom::DisplayMode original_display_mode_override_;
bool original_mock_scrollbars_enabled_;
bool original_mock_gesture_tap_highlights_enabled_;
bool lang_attribute_aware_form_control_ui_enabled_;
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.cc b/chromium/third_party/blink/renderer/core/testing/internals.cc
index 650d8615dd3..4abceb2a8bc 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internals.cc
@@ -178,7 +178,7 @@
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/text/layout_locale.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#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 "v8/include/v8.h"
@@ -847,7 +847,7 @@ void Internals::endColorChooser(Element* element) {
bool Internals::hasAutofocusRequest(Document* document) {
if (!document)
document = document_;
- return document->AutofocusElement();
+ return document->HasAutofocusCandidates();
}
bool Internals::hasAutofocusRequest() {
@@ -1324,7 +1324,7 @@ String Internals::suggestedValue(Element* element,
if (auto* textarea = ToHTMLTextAreaElementOrNull(*element))
return textarea->SuggestedValue();
- if (auto* select = ToHTMLSelectElementOrNull(*element))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*element))
return select->SuggestedValue();
return suggested_value;
@@ -1347,7 +1347,7 @@ void Internals::setSuggestedValue(Element* element,
if (auto* textarea = ToHTMLTextAreaElementOrNull(*element))
textarea->SetSuggestedValue(value);
- if (auto* select = ToHTMLSelectElementOrNull(*element))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*element))
select->SetSuggestedValue(value);
}
@@ -1377,7 +1377,7 @@ void Internals::setAutofilledValue(Element* element,
*Event::CreateBubble(event_type_names::kKeyup));
}
- if (auto* select = ToHTMLSelectElementOrNull(*element))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*element))
select->setValue(value, true /* send_events */);
To<HTMLFormControlElement>(element)->SetAutofillState(
@@ -1798,9 +1798,9 @@ static void AccumulateTouchActionRectList(
const cc::TouchActionRegion& touch_action_region =
graphics_layer->CcLayer()->touch_action_region();
if (!touch_action_region.GetAllRegions().IsEmpty()) {
- const auto& layer_position = graphics_layer->CcLayer()->position();
+ const auto& layer_position = graphics_layer->GetOffsetFromTransformNode();
const auto& layer_bounds = graphics_layer->CcLayer()->bounds();
- IntRect layer_rect(layer_position.x(), layer_position.y(),
+ IntRect layer_rect(layer_position.X(), layer_position.Y(),
layer_bounds.width(), layer_bounds.height());
Vector<IntRect> layer_hit_test_rects;
@@ -2226,44 +2226,32 @@ DOMRectList* Internals::nonFastScrollableRects(
frame->View()->UpdateAllLifecyclePhases(
DocumentLifecycle::LifecycleUpdateReason::kTest);
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- auto* pac = document->View()->GetPaintArtifactCompositor();
- auto* layer_tree_host = pac->RootLayer()->layer_tree_host();
- // Ensure |cc::TransformTree| has updated the correct ToScreen transforms.
- layer_tree_host->UpdateLayers();
-
- 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) {
- gfx::RectF layer_rect(non_fast_rect);
-
- // Map |layer_rect| into screen space.
- layer_rect.Offset(layer->offset_to_transform_parent());
- auto& transform_tree =
- layer->layer_tree_host()->property_trees()->transform_tree;
- transform_tree.UpdateTransforms(layer->transform_tree_index());
- const gfx::Transform& to_screen =
- transform_tree.ToScreen(layer->transform_tree_index());
- to_screen.TransformRect(&layer_rect);
-
- layer_non_fast_scrollable_rects.push_back(
- IntRect(ToEnclosingRect(layer_rect)));
- }
+ auto* pac = document->View()->GetPaintArtifactCompositor();
+ auto* layer_tree_host = pac->RootLayer()->layer_tree_host();
+ // Ensure |cc::TransformTree| has updated the correct ToScreen transforms.
+ layer_tree_host->UpdateLayers();
+
+ 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) {
+ gfx::RectF layer_rect(non_fast_rect);
+
+ // Map |layer_rect| into screen space.
+ layer_rect.Offset(layer->offset_to_transform_parent());
+ auto& transform_tree =
+ layer->layer_tree_host()->property_trees()->transform_tree;
+ transform_tree.UpdateTransforms(layer->transform_tree_index());
+ const gfx::Transform& to_screen =
+ transform_tree.ToScreen(layer->transform_tree_index());
+ to_screen.TransformRect(&layer_rect);
+
+ layer_non_fast_scrollable_rects.push_back(
+ IntRect(ToEnclosingRect(layer_rect)));
}
-
- return DOMRectList::Create(layer_non_fast_scrollable_rects);
}
- GraphicsLayer* layer = frame->View()->LayoutViewport()->LayerForScrolling();
- if (!layer)
- return DOMRectList::Create();
- const cc::Region& region = layer->CcLayer()->non_fast_scrollable_region();
- Vector<IntRect> rects;
- rects.ReserveCapacity(region.GetRegionComplexity());
- for (const gfx::Rect& rect : region)
- rects.push_back(IntRect(rect));
- return DOMRectList::Create(rects);
+ return DOMRectList::Create(layer_non_fast_scrollable_rects);
}
void Internals::evictAllResources() const {
@@ -2947,34 +2935,34 @@ String Internals::selectMenuListText(HTMLSelectElement* select) {
bool Internals::isSelectPopupVisible(Node* node) {
DCHECK(node);
- if (auto* select = ToHTMLSelectElementOrNull(*node))
+ if (auto* select = DynamicTo<HTMLSelectElement>(*node))
return select->PopupIsVisible();
return false;
}
bool Internals::selectPopupItemStyleIsRtl(Node* node, int item_index) {
- if (!node || !IsHTMLSelectElement(*node))
+ auto* select = DynamicTo<HTMLSelectElement>(node);
+ if (!select)
return false;
- HTMLSelectElement& select = ToHTMLSelectElement(*node);
if (item_index < 0 ||
- static_cast<wtf_size_t>(item_index) >= select.GetListItems().size())
+ static_cast<wtf_size_t>(item_index) >= select->GetListItems().size())
return false;
const ComputedStyle* item_style =
- select.ItemComputedStyle(*select.GetListItems()[item_index]);
+ select->ItemComputedStyle(*select->GetListItems()[item_index]);
return item_style && item_style->Direction() == TextDirection::kRtl;
}
int Internals::selectPopupItemStyleFontHeight(Node* node, int item_index) {
- if (!node || !IsHTMLSelectElement(*node))
+ auto* select = DynamicTo<HTMLSelectElement>(node);
+ if (!select)
return false;
- HTMLSelectElement& select = ToHTMLSelectElement(*node);
if (item_index < 0 ||
- static_cast<wtf_size_t>(item_index) >= select.GetListItems().size())
+ static_cast<wtf_size_t>(item_index) >= select->GetListItems().size())
return false;
const ComputedStyle* item_style =
- select.ItemComputedStyle(*select.GetListItems()[item_index]);
+ select->ItemComputedStyle(*select->GetListItems()[item_index]);
if (item_style) {
const SimpleFontData* font_data = item_style->GetFont().PrimaryFont();
@@ -3017,13 +3005,6 @@ void Internals::forceCompositingUpdate(Document* document,
DocumentLifecycle::LifecycleUpdateReason::kTest);
}
-void Internals::setZoomFactor(float factor) {
- if (!GetFrame())
- return;
-
- GetFrame()->SetPageZoomFactor(factor);
-}
-
void Internals::setShouldRevealPassword(Element* element,
bool reveal,
ExceptionState& exception_state) {
@@ -3056,7 +3037,7 @@ class AddOneFunction : public ScriptFunction {
int32_t int_value =
static_cast<int32_t>(v8_value.As<v8::Integer>()->Value());
return ScriptValue(
- GetScriptState(),
+ GetScriptState()->GetIsolate(),
v8::Integer::New(GetScriptState()->GetIsolate(), int_value + 1));
}
};
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.h b/chromium/third_party/blink/renderer/core/testing/internals.h
index eed62606697..9260ce143dc 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.h
+++ b/chromium/third_party/blink/renderer/core/testing/internals.h
@@ -466,8 +466,6 @@ class Internals final : public ScriptWrappable {
void forceCompositingUpdate(Document*, ExceptionState&);
- void setZoomFactor(float);
-
void setShouldRevealPassword(Element*, bool, ExceptionState&);
ScriptPromise createResolvedPromise(ScriptState*, ScriptValue);
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.idl b/chromium/third_party/blink/renderer/core/testing/internals.idl
index 6de35f8b605..c11085d3878 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.idl
+++ b/chromium/third_party/blink/renderer/core/testing/internals.idl
@@ -303,8 +303,6 @@
[RaisesException] void forceCompositingUpdate(Document document);
- void setZoomFactor(float factor);
-
[RaisesException] void setShouldRevealPassword(Element element, boolean reveal);
[CallWith=ScriptState] Promise<any> createResolvedPromise(any value);
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 b2a1e9b6013..26cd0cad4a2 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
@@ -16,10 +16,9 @@
namespace blink {
-class NullExecutionContext
- : public GarbageCollectedFinalized<NullExecutionContext>,
- public SecurityContext,
- public ExecutionContext {
+class NullExecutionContext : public GarbageCollected<NullExecutionContext>,
+ public SecurityContext,
+ public ExecutionContext {
USING_GARBAGE_COLLECTED_MIXIN(NullExecutionContext);
public:
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 8a4a4d817fb..40d7b51cbc1 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
@@ -13,12 +13,27 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
namespace blink {
+namespace {
+
+Element* GetOrCreateElement(ContainerNode* parent,
+ const HTMLQualifiedName& tag_name) {
+ HTMLCollection* elements = parent->getElementsByTagNameNS(
+ tag_name.NamespaceURI(), tag_name.LocalName());
+ if (!elements->IsEmpty())
+ return elements->item(0);
+ return parent->ownerDocument()->CreateRawElement(
+ tag_name, CreateElementFlags::ByCreateElement());
+}
+
+} // namespace
+
PageTestBase::PageTestBase() = default;
PageTestBase::~PageTestBase() = default;
@@ -140,6 +155,16 @@ void PageTestBase::SetHtmlInnerHTML(const std::string& html_content) {
UpdateAllLifecyclePhasesForTest();
}
+void PageTestBase::InsertStyleElement(const std::string& style_rules) {
+ Element* const head =
+ GetOrCreateElement(&GetDocument(), html_names::kHeadTag);
+ DCHECK_EQ(head, GetOrCreateElement(&GetDocument(), html_names::kHeadTag));
+ Element* const style = GetDocument().CreateRawElement(
+ html_names::kStyleTag, CreateElementFlags::ByCreateElement());
+ style->setTextContent(String(style_rules.data(), style_rules.size()));
+ head->appendChild(style);
+}
+
void PageTestBase::NavigateTo(const KURL& url,
const String& feature_policy_header,
const String& csp_header) {
diff --git a/chromium/third_party/blink/renderer/core/testing/page_test_base.h b/chromium/third_party/blink/renderer/core/testing/page_test_base.h
index b15cbd7957e..0a76feffafa 100644
--- a/chromium/third_party/blink/renderer/core/testing/page_test_base.h
+++ b/chromium/third_party/blink/renderer/core/testing/page_test_base.h
@@ -41,6 +41,10 @@ class PageTestBase : public testing::Test {
void SetBodyInnerHTML(const String&);
void SetHtmlInnerHTML(const std::string&);
+ // Insert STYLE element with |style_rules|, no need to have "<style>", into
+ // HEAD.
+ void InsertStyleElement(const std::string& style_rules);
+
// Navigate to |url| providing an empty response but
// URL and security origin of the Document will be set to |url|.
void NavigateTo(const KURL& url,
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
index 7f838c53d19..10e3081087e 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -31,18 +31,18 @@ SimCompositor::~SimCompositor() {
void SimCompositor::SetWebView(
WebViewImpl& web_view,
- content::LayerTreeView& layer_tree_view,
+ cc::LayerTreeHost& layer_tree_host,
frame_test_helpers::TestWebViewClient& view_client,
frame_test_helpers::TestWebWidgetClient& widget_client) {
web_view_ = &web_view;
- layer_tree_view_ = &layer_tree_view;
+ layer_tree_host_ = &layer_tree_host;
test_web_view_client_ = &view_client;
test_web_widget_client_ = &widget_client;
}
SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) {
DCHECK(web_view_);
- DCHECK(!layer_tree_view_->layer_tree_host()->defer_main_frame_update());
+ DCHECK(!layer_tree_host_->defer_main_frame_update());
// Verify that the need for a BeginMainFrame has been registered, and would
// have caused the compositor to schedule one if we were using its scheduler.
DCHECK(NeedsBeginFrame());
@@ -55,8 +55,8 @@ SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) {
SimCanvas::Commands commands;
paint_commands_ = &commands;
- layer_tree_view_->layer_tree_host()->Composite(last_frame_time_,
- /*raster=*/false);
+ layer_tree_host_->Composite(last_frame_time_,
+ /*raster=*/false);
paint_commands_ = nullptr;
return commands;
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
index 5e885e92ea9..3f60923634a 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -7,7 +7,6 @@
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
-#include "content/renderer/compositor/layer_tree_view.h"
#include "content/test/stub_layer_tree_view_delegate.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/testing/sim/sim_canvas.h"
@@ -32,7 +31,7 @@ class SimCompositor final : public content::StubLayerTreeViewDelegate {
~SimCompositor() override;
// This compositor should be given to the WebViewImpl passed to SetWebView.
- content::LayerTreeView& layer_tree_view() { return *layer_tree_view_; }
+ cc::LayerTreeHost& layer_tree_host() { return *layer_tree_host_; }
// When the compositor asks for a main frame, this WebViewImpl will have its
// lifecycle updated and be painted.
@@ -43,7 +42,7 @@ class SimCompositor final : public content::StubLayerTreeViewDelegate {
// pass it here explicitly to provide type safety, though it is the client
// available on the WebViewImpl as well.
void SetWebView(WebViewImpl&,
- content::LayerTreeView&,
+ cc::LayerTreeHost&,
frame_test_helpers::TestWebViewClient&,
frame_test_helpers::TestWebWidgetClient&);
@@ -67,25 +66,21 @@ class SimCompositor final : public content::StubLayerTreeViewDelegate {
// requet for BeginFrame() was made, vs an implicit one by making changes
// to the compositor's state.
bool NeedsBeginFrame() const {
- cc::LayerTreeHost* layer_tree_host = layer_tree_view_->layer_tree_host();
return test_web_widget_client_->AnimationScheduled() ||
- layer_tree_host->RequestedMainFramePendingForTesting();
+ layer_tree_host_->RequestedMainFramePendingForTesting();
}
// Returns true if commits are deferred in the compositor. Since these tests
// use synchronous compositing through BeginFrame(), the deferred state has no
// real effect.
bool DeferMainFrameUpdate() const {
- return layer_tree_view_->layer_tree_host()->defer_main_frame_update();
+ return layer_tree_host_->defer_main_frame_update();
}
// Returns true if a selection is set on the compositor.
bool HasSelection() const {
- return layer_tree_view_->layer_tree_host()->selection() !=
- cc::LayerSelection();
+ return layer_tree_host_->selection() != cc::LayerSelection();
}
// Returns the background color set on the compositor.
- SkColor background_color() {
- return layer_tree_view_->layer_tree_host()->background_color();
- }
+ SkColor background_color() { return layer_tree_host_->background_color(); }
base::TimeTicks LastFrameTime() const { return last_frame_time_; }
@@ -98,7 +93,7 @@ class SimCompositor final : public content::StubLayerTreeViewDelegate {
void DidBeginMainFrame() override { web_view_->DidBeginFrame(); }
WebViewImpl* web_view_ = nullptr;
- content::LayerTreeView* layer_tree_view_ = nullptr;
+ cc::LayerTreeHost* layer_tree_host_ = nullptr;
frame_test_helpers::TestWebViewClient* test_web_view_client_ = nullptr;
frame_test_helpers::TestWebWidgetClient* test_web_widget_client_ = nullptr;
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 f0bd794a2ba..45c09a90c91 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
@@ -64,7 +64,7 @@ void SimTest::SetUp() {
web_view_helper_->Initialize(web_frame_client_.get(), web_view_client_.get(),
web_widget_client_.get());
- compositor_->SetWebView(WebView(), *web_widget_client_->layer_tree_view(),
+ compositor_->SetWebView(WebView(), *web_widget_client_->layer_tree_host(),
*web_view_client_, *web_widget_client_);
page_->SetPage(WebView().GetPage());
}
diff --git a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
index 854ed6aec7d..9dea9b5950b 100644
--- a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
+++ b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.cc
@@ -35,31 +35,41 @@ void NotifyTimezoneChangeOnWorkerThread(WorkerThread* worker_thread) {
NotifyTimezoneChangeToV8(worker_thread->GlobalScope()->GetIsolate());
}
-void SetIcuTimeZoneAndNotifyV8(const String& timezone_id) {
+String GetTimezoneId(const icu::TimeZone& timezone) {
+ icu::UnicodeString unicode_timezone_id;
+ timezone.getID(unicode_timezone_id);
+ return String(icu::toUCharPtr(unicode_timezone_id.getBuffer()),
+ static_cast<unsigned>(unicode_timezone_id.length()));
+}
+
+String GetCurrentTimezoneId() {
+ std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createDefault());
+ CHECK(timezone);
+ return GetTimezoneId(*timezone.get());
+}
+
+bool SetIcuTimeZoneAndNotifyV8(const String& timezone_id) {
DCHECK(!timezone_id.IsEmpty());
- DCHECK(timezone_id.ContainsOnlyASCIIOrEmpty());
- icu::TimeZone* timezone = icu::TimeZone::createTimeZone(
- icu::UnicodeString(timezone_id.Ascii().data(), -1, US_INV));
- icu::TimeZone::adoptDefault(timezone);
+ std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone(
+ icu::UnicodeString(timezone_id.Ascii().data(), -1, US_INV)));
+ CHECK(timezone);
+
+ if (*timezone == icu::TimeZone::getUnknown())
+ return false;
+
+ icu::TimeZone::adoptDefault(timezone.release());
NotifyTimezoneChangeToV8(V8PerIsolateData::MainThreadIsolate());
WorkerThread::CallOnAllWorkerThreads(&NotifyTimezoneChangeOnWorkerThread,
TaskType::kInternalDefault);
-}
-
-String GetCurrentTimezone() {
- std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createDefault());
- icu::UnicodeString unicode_timezone_id;
- timezone->getID(unicode_timezone_id);
- return String(icu::toUCharPtr(unicode_timezone_id.getBuffer()),
- static_cast<unsigned>(unicode_timezone_id.length()));
+ return true;
}
} // namespace
TimeZoneController::TimeZoneController() {
DCHECK(IsMainThread());
- host_timezone_id_ = GetCurrentTimezone();
+ host_timezone_id_ = GetCurrentTimezoneId();
}
TimeZoneController::~TimeZoneController() = default;
@@ -93,7 +103,10 @@ TimeZoneController::SetTimeZoneOverride(const String& timezone_id) {
return nullptr;
}
- SetIcuTimeZoneAndNotifyV8(timezone_id);
+ if (!SetIcuTimeZoneAndNotifyV8(timezone_id)) {
+ VLOG(1) << "Invalid override timezone id: " << timezone_id;
+ return nullptr;
+ }
instance().has_timezone_id_override_ = true;
@@ -101,6 +114,11 @@ TimeZoneController::SetTimeZoneOverride(const String& timezone_id) {
}
// static
+bool TimeZoneController::HasTimeZoneOverride() {
+ return instance().has_timezone_id_override_;
+}
+
+// static
void TimeZoneController::ClearTimeZoneOverride() {
DCHECK(instance().has_timezone_id_override_);
diff --git a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.h b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.h
index 86d9d01c4a0..89978bdf38c 100644
--- a/chromium/third_party/blink/renderer/core/timezone/timezone_controller.h
+++ b/chromium/third_party/blink/renderer/core/timezone/timezone_controller.h
@@ -41,6 +41,8 @@ class CORE_EXPORT TimeZoneController final
static std::unique_ptr<TimeZoneOverride> SetTimeZoneOverride(
const String& timezone_id);
+ static bool HasTimeZoneOverride();
+
private:
TimeZoneController();
static TimeZoneController& instance();
diff --git a/chromium/third_party/blink/renderer/core/timing/internals_profiler.cc b/chromium/third_party/blink/renderer/core/timing/internals_profiler.cc
new file mode 100644
index 00000000000..688de617a0b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/internals_profiler.cc
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/timing/internals_profiler.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+#include "v8/include/v8-profiler.h"
+
+namespace blink {
+
+void InternalsProfiler::collectSample(ScriptState* script_state, Internals&) {
+ v8::CpuProfiler::CollectSample(script_state->GetIsolate());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/internals_profiler.h b/chromium/third_party/blink/renderer/core/timing/internals_profiler.h
new file mode 100644
index 00000000000..1dcaf63a8f2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/internals_profiler.h
@@ -0,0 +1,24 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_INTERNALS_PROFILER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_INTERNALS_PROFILER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class Internals;
+class ScriptState;
+
+class InternalsProfiler {
+ STATIC_ONLY(InternalsProfiler);
+
+ public:
+ static void collectSample(ScriptState*, Internals&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_INTERNALS_PROFILER_H_
diff --git a/chromium/third_party/blink/renderer/core/timing/internals_profiler.idl b/chromium/third_party/blink/renderer/core/timing/internals_profiler.idl
new file mode 100644
index 00000000000..36e45565635
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/internals_profiler.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ ImplementedAs=InternalsProfiler
+]
+partial interface Internals {
+ // Collects a sample for all profilers attached to the invoker's isolate.
+ [CallWith=ScriptState] void collectSample();
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.idl b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
index 54cdaef5c43..0d3ae7b0cb1 100644
--- a/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
+++ b/chromium/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// https://github.com/WICG/LargestContentfulPaint
-[Exposed=Window, RuntimeEnabled=LargestContentfulPaint]
+[Exposed=Window]
interface LargestContentfulPaint : PerformanceEntry {
readonly attribute DOMHighResTimeStamp renderTime;
readonly attribute DOMHighResTimeStamp loadTime;
diff --git a/chromium/third_party/blink/renderer/core/timing/layout_shift.idl b/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
index 53b66c623c2..2170984ff92 100644
--- a/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
+++ b/chromium/third_party/blink/renderer/core/timing/layout_shift.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// https://wicg.github.io/layout-instability/#sec-layout-shift
-[Exposed=Window, RuntimeEnabled=LayoutInstabilityAPI]
+[Exposed=Window]
interface LayoutShift : PerformanceEntry {
readonly attribute double value;
readonly attribute boolean hadRecentInput;
diff --git a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl
new file mode 100644
index 00000000000..c2b4a4be92f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl
@@ -0,0 +1,12 @@
+// 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://github.com/ulan/javascript-agent-memory/blob/master/explainer.md
+
+// The result of performance.measureMemory().
+dictionary MeasureMemory {
+ required MeasureMemoryEntry total;
+ MeasureMemoryEntry current;
+ sequence<MeasureMemoryEntry> other;
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_entry.idl b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_entry.idl
new file mode 100644
index 00000000000..cc49ed29f66
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_entry.idl
@@ -0,0 +1,11 @@
+// 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://github.com/ulan/javascript-agent-memory/blob/master/explainer.md
+
+// A single entry of performance.measureMemory() result.
+dictionary MeasureMemoryEntry {
+ unsigned long long jsMemoryEstimate;
+ sequence<unsigned long long> jsMemoryRange;
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.idl b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.idl
new file mode 100644
index 00000000000..d4ed317aff5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.idl
@@ -0,0 +1,10 @@
+// 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://github.com/ulan/javascript-agent-memory/blob/master/explainer.md
+
+// Options for performance.measureMemory().
+dictionary MeasureMemoryOptions {
+ boolean detailed;
+};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.cc b/chromium/third_party/blink/renderer/core/timing/performance.cc
index 08e1d7e5766..aad39caf68f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance.cc
@@ -37,6 +37,7 @@
#include "base/time/default_tick_clock.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"
#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/core/dom/document.h"
@@ -50,6 +51,7 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/timing/largest_contentful_paint.h"
#include "third_party/blink/renderer/core/timing/layout_shift.h"
+#include "third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.h"
#include "third_party/blink/renderer/core/timing/performance_element_timing.h"
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/core/timing/performance_long_task_timing.h"
@@ -65,6 +67,7 @@
#include "third_party/blink/renderer/core/timing/profiler_init_options.h"
#include "third_party/blink/renderer/core/timing/time_clamper.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.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/loader/fetch/resource_timing_info.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -140,6 +143,21 @@ MemoryInfo* Performance::memory() const {
return nullptr;
}
+ScriptPromise Performance::measureMemory(ScriptState* script_state,
+ MeasureMemoryOptions* options) const {
+ v8::Isolate* isolate = script_state->GetIsolate();
+ v8::Local<v8::Context> context = script_state->GetContext();
+ v8::Local<v8::Promise> promise;
+ v8::MaybeLocal<v8::Promise> maybe_promise = isolate->MeasureMemory(
+ context, options && options->hasDetailed() && options->detailed()
+ ? v8::MeasureMemoryMode::kDetailed
+ : v8::MeasureMemoryMode::kSummary);
+ if (!maybe_promise.ToLocal(&promise)) {
+ return ScriptPromise();
+ }
+ return ScriptPromise(script_state, promise);
+}
+
DOMHighResTimeStamp Performance::timeOrigin() const {
DCHECK(!time_origin_.is_null());
return unified_clock_->GetUnixAtZeroMonotonic() +
@@ -335,12 +353,16 @@ void Performance::setResourceTimingBufferSize(unsigned size) {
bool Performance::PassesTimingAllowCheck(
const ResourceResponse& response,
const SecurityOrigin& initiator_security_origin,
- ExecutionContext* context) {
+ ExecutionContext* context,
+ bool* tainted) {
+ DCHECK(tainted);
const KURL& response_url = response.ResponseUrl();
scoped_refptr<const SecurityOrigin> resource_origin =
SecurityOrigin::Create(response_url);
- if (resource_origin->IsSameSchemeHostPort(&initiator_security_origin))
+ if (!*tainted &&
+ resource_origin->IsSameSchemeHostPort(&initiator_security_origin))
return true;
+ *tainted = true;
const AtomicString& timing_allow_origin_string =
response.HttpHeaderField(http_names::kTimingAllowOrigin);
@@ -380,14 +402,17 @@ bool Performance::AllowsTimingRedirect(
const ResourceResponse& final_response,
const SecurityOrigin& initiator_security_origin,
ExecutionContext* context) {
- if (!PassesTimingAllowCheck(final_response, initiator_security_origin,
- context))
- return false;
+ bool tainted = false;
for (const ResourceResponse& response : redirect_chain) {
- if (!PassesTimingAllowCheck(response, initiator_security_origin, context))
+ if (!PassesTimingAllowCheck(response, initiator_security_origin, context,
+ &tainted))
return false;
}
+ if (!PassesTimingAllowCheck(final_response, initiator_security_origin,
+ context, &tainted)) {
+ return false;
+ }
return true;
}
@@ -419,8 +444,9 @@ WebResourceTimingInfo Performance::GenerateResourceTiming(
result.timing = final_response.GetResourceLoadTiming();
result.response_end = info.LoadResponseEnd();
+ bool tainted = false;
result.allow_timing_details = PassesTimingAllowCheck(
- final_response, destination_origin, &context_for_use_counter);
+ final_response, destination_origin, &context_for_use_counter, &tainted);
const Vector<ResourceResponse>& redirect_chain = info.RedirectChain();
if (!redirect_chain.IsEmpty()) {
@@ -618,23 +644,19 @@ UserTiming& Performance::GetUserTiming() {
PerformanceMark* Performance::mark(ScriptState* script_state,
const AtomicString& mark_name,
- ExceptionState& exception_state) {
- return mark(script_state, mark_name, nullptr, exception_state);
-}
-
-PerformanceMark* Performance::mark(ScriptState* script_state,
- const AtomicString& mark_name,
PerformanceMarkOptions* mark_options,
ExceptionState& exception_state) {
+ if (mark_options &&
+ (mark_options->hasStartTime() || mark_options->hasDetail())) {
+ UseCounter::Count(GetExecutionContext(), WebFeature::kUserTimingL3);
+ }
PerformanceMark* performance_mark = GetUserTiming().CreatePerformanceMark(
script_state, mark_name, mark_options, exception_state);
if (performance_mark) {
GetUserTiming().AddMarkToPerformanceTimeline(*performance_mark);
NotifyObserversOfEntry(*performance_mark);
}
- if (RuntimeEnabledFeatures::CustomUserTimingEnabled())
- return performance_mark;
- return nullptr;
+ return performance_mark;
}
void Performance::clearMarks(const AtomicString& mark_name) {
@@ -695,77 +717,58 @@ PerformanceMeasure* Performance::MeasureInternal(
base::Optional<String> end_mark,
ExceptionState& exception_state) {
DCHECK(!start_or_options.IsNull());
- if (RuntimeEnabledFeatures::CustomUserTimingEnabled()) {
- // An empty option is treated with no difference as null, undefined.
- if (start_or_options.IsPerformanceMeasureOptions() &&
- !IsMeasureOptionsEmpty(
- *start_or_options.GetAsPerformanceMeasureOptions())) {
- // measure("name", { start, end }, *)
- if (end_mark) {
- exception_state.ThrowTypeError(
- "If a non-empty PerformanceMeasureOptions object was passed, "
- "|end_mark| must not be passed.");
- return nullptr;
- }
- const PerformanceMeasureOptions* options =
- start_or_options.GetAsPerformanceMeasureOptions();
- if (!options->hasStart() && !options->hasEnd()) {
- exception_state.ThrowTypeError(
- "If a non-empty PerformanceMeasureOptions object was passed, at "
- "least one of its 'start' or 'end' properties must be present.");
- return nullptr;
- }
-
- if (options->hasStart() && options->hasDuration() && options->hasEnd()) {
- exception_state.ThrowTypeError(
- "If a non-empty PerformanceMeasureOptions object was passed, it "
- "must not have all of its 'start', 'duration', and 'end' "
- "properties defined");
- return nullptr;
- }
-
- base::Optional<double> duration = base::nullopt;
- if (options->hasDuration()) {
- duration = options->duration();
- }
+ // An empty option is treated with no difference as null, undefined.
+ if (start_or_options.IsPerformanceMeasureOptions() &&
+ !IsMeasureOptionsEmpty(
+ *start_or_options.GetAsPerformanceMeasureOptions())) {
+ UseCounter::Count(GetExecutionContext(), WebFeature::kUserTimingL3);
+ // measure("name", { start, end }, *)
+ if (end_mark) {
+ exception_state.ThrowTypeError(
+ "If a non-empty PerformanceMeasureOptions object was passed, "
+ "|end_mark| must not be passed.");
+ return nullptr;
+ }
+ const PerformanceMeasureOptions* options =
+ start_or_options.GetAsPerformanceMeasureOptions();
+ if (!options->hasStart() && !options->hasEnd()) {
+ exception_state.ThrowTypeError(
+ "If a non-empty PerformanceMeasureOptions object was passed, at "
+ "least one of its 'start' or 'end' properties must be present.");
+ return nullptr;
+ }
- return MeasureWithDetail(script_state, measure_name, options->start(),
- std::move(duration), options->end(),
- options->detail(), exception_state);
+ if (options->hasStart() && options->hasDuration() && options->hasEnd()) {
+ exception_state.ThrowTypeError(
+ "If a non-empty PerformanceMeasureOptions object was passed, it "
+ "must not have all of its 'start', 'duration', and 'end' "
+ "properties defined");
+ return nullptr;
}
- // measure("name", "mark1", *)
- StringOrDouble converted_start;
- if (start_or_options.IsString()) {
- converted_start =
- StringOrDouble::FromString(start_or_options.GetAsString());
+
+ base::Optional<double> duration = base::nullopt;
+ if (options->hasDuration()) {
+ duration = options->duration();
}
- // We let |end_mark| behave the same whether it's empty, undefined or null
- // in JS, as long as |end_mark| is null in C++.
- return MeasureWithDetail(
- script_state, measure_name, converted_start,
- /* duration = */ base::nullopt,
- end_mark ? StringOrDouble::FromString(*end_mark)
- : NativeValueTraits<StringOrDouble>::NullValue(),
- ScriptValue::CreateNull(script_state), exception_state);
- }
- // For consistency with UserTimingL2: the L2 API took |start| as a string,
- // so any object passed in became a string '[object, object]', null became
- // string 'null'.
+
+ return MeasureWithDetail(script_state, measure_name, options->start(),
+ std::move(duration), options->end(),
+ options->detail(), exception_state);
+ }
+ // measure("name", "mark1", *)
StringOrDouble converted_start;
- if (!start_or_options.IsPerformanceMeasureOptions()) {
- // |start_or_options| is not nullable.
- DCHECK(start_or_options.IsString());
+ if (start_or_options.IsString()) {
converted_start =
StringOrDouble::FromString(start_or_options.GetAsString());
}
-
- MeasureWithDetail(script_state, measure_name, converted_start,
- /* duration = */ base::nullopt,
- end_mark ? StringOrDouble::FromString(*end_mark)
- : NativeValueTraits<StringOrDouble>::NullValue(),
- ScriptValue::CreateNull(script_state), exception_state);
- // Return nullptr to distinguish from L3.
- return nullptr;
+ // We let |end_mark| behave the same whether it's empty, undefined or null
+ // in JS, as long as |end_mark| is null in C++.
+ return MeasureWithDetail(
+ script_state, measure_name, converted_start,
+ /* duration = */ base::nullopt,
+ end_mark ? StringOrDouble::FromString(*end_mark)
+ : NativeValueTraits<StringOrDouble>::NullValue(),
+ ScriptValue::CreateNull(script_state->GetIsolate()), exception_state);
}
PerformanceMeasure* Performance::MeasureWithDetail(
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.h b/chromium/third_party/blink/renderer/core/timing/performance.h
index 57cd33a236e..3edacae329f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance.h
@@ -62,6 +62,7 @@ class PerformanceMarkOptions;
class ExceptionState;
class LargestContentfulPaint;
class LayoutShift;
+class MeasureMemoryOptions;
class MemoryInfo;
class PerformanceElementTiming;
class PerformanceEventTiming;
@@ -97,6 +98,8 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
virtual PerformanceTiming* timing() const;
virtual PerformanceNavigation* navigation() const;
virtual MemoryInfo* memory() const;
+ virtual ScriptPromise measureMemory(ScriptState*,
+ MeasureMemoryOptions*) const;
virtual void UpdateLongTaskInstrumentation() {}
@@ -185,10 +188,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
PerformanceMark* mark(ScriptState*,
const AtomicString& mark_name,
- ExceptionState&);
-
- PerformanceMark* mark(ScriptState*,
- const AtomicString& mark_name,
PerformanceMarkOptions* mark_options,
ExceptionState&);
@@ -268,7 +267,8 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
// TODO(npm): is the AtomicString parameter here actually needed?
static bool PassesTimingAllowCheck(const ResourceResponse&,
const SecurityOrigin&,
- ExecutionContext*);
+ ExecutionContext*,
+ bool* tainted);
static bool AllowsTimingRedirect(const Vector<ResourceResponse>&,
const ResourceResponse&,
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.idl b/chromium/third_party/blink/renderer/core/timing/performance.idl
index 0ff54833101..a093c44a4b8 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance.idl
@@ -58,28 +58,21 @@ interface Performance : EventTarget {
// User Timing
// https://w3c.github.io/user-timing/#extensions-performance-interface
- // We use the returned value for feature detection:
- // * L2 API returns null but this is a bug: crbug.com/914441.
- // * L3 API returns the created entry.
- [MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMark? mark(DOMString markName);
- // TODO(maxlg): PerformanceMarkOptions will be changed to optional after L3 is default to be enabled.
- [MeasureAs=UserTiming, CallWith=ScriptState, RuntimeEnabled=CustomUserTiming, RaisesException] PerformanceMark? mark(DOMString markName, PerformanceMarkOptions markOptions);
+ // TODO(https://crbug.com/996275): Once our IDL parser supports it, we need
+ // to supply a default-value of '{}' to markOptions.
+ [MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions);
[MeasureAs=UserTiming] void clearMarks(optional DOMString markName);
-
- // Doing either of the following requires enabling CustomUserTiming:
- // * passing PerformanceMeasureOptions to |startOrOptions|
- // * passing timestamps to |startOrOptions| or |end|
- // We use the returned value for feature detection:
- // * L2 API returns null but this is a bug: crbug.com/914441.
- // * L3 API returns the created entry.
- // https://w3c.github.io/user-timing/#extensions-performance-interface
- [MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMeasure? measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrOptions, optional DOMString end);
+ // TODO(https://crbug.com/996275): Once our IDL parser supports it, we need
+ // to supply a default-value of '{}' to startOrOptions.
+ [MeasureAs=UserTiming, CallWith=ScriptState, RaisesException] PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrOptions, optional DOMString end);
[MeasureAs=UserTiming] void clearMeasures(optional DOMString measureName);
// TODO(foolip): There is no spec for the Memory Info API, see blink-dev:
// https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
[Exposed=Window, Measure] readonly attribute MemoryInfo memory;
+ [Exposed=(Window,Worker), CallWith=ScriptState, RuntimeEnabled=MeasureMemory] Promise<MeasureMemory> measureMemory(optional MeasureMemoryOptions options);
+
// JS Self-Profiling API
// https://github.com/WICG/js-self-profiling/
[MeasureAs=JSSelfProfiling, CallWith=ScriptState, RuntimeEnabled=ExperimentalJSProfiler, RaisesException] Promise<Profiler> profile(ProfilerInitOptions options);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_element_timing.idl b/chromium/third_party/blink/renderer/core/timing/performance_element_timing.idl
index ca4cc5f6e23..a577f0b806f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_element_timing.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_element_timing.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// https://wicg.github.io/element-timing/#sec-performance-element-timing
-[Exposed=Window, RuntimeEnabled=ElementTiming]
+[Exposed=Window]
interface PerformanceElementTiming : PerformanceEntry {
readonly attribute DOMHighResTimeStamp renderTime;
readonly attribute DOMHighResTimeStamp loadTime;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
index 06d932dac1f..8fdafa99cff 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
@@ -23,21 +23,10 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming(
const SubTaskAttribution::EntriesVector& sub_task_attributions)
: PerformanceEntry(name, start_time, end_time) {
// Only one possible container type exists currently: "iframe".
- if (RuntimeEnabledFeatures::LongTaskV2Enabled()) {
- for (auto&& it : sub_task_attributions) {
- TaskAttributionTiming* attribution_entry = TaskAttributionTiming::Create(
- it->subTaskName(), "iframe", culprit_frame_src, culprit_frame_id,
- culprit_frame_name, it->highResStartTime(),
- it->highResStartTime() + it->highResDuration(), it->scriptURL());
- attribution_.push_back(*attribution_entry);
- }
- } else {
- // Only one possible task type exists currently: "script".
- TaskAttributionTiming* attribution_entry =
- TaskAttributionTiming::Create("unknown", "iframe", culprit_frame_src,
- culprit_frame_id, culprit_frame_name);
- attribution_.push_back(*attribution_entry);
- }
+ TaskAttributionTiming* attribution_entry =
+ TaskAttributionTiming::Create("unknown", "iframe", culprit_frame_src,
+ culprit_frame_id, culprit_frame_name);
+ attribution_.push_back(*attribution_entry);
}
PerformanceLongTaskTiming::~PerformanceLongTaskTiming() = default;
@@ -56,7 +45,7 @@ TaskAttributionVector PerformanceLongTaskTiming::attribution() const {
void PerformanceLongTaskTiming::BuildJSONValue(V8ObjectBuilder& builder) const {
PerformanceEntry::BuildJSONValue(builder);
- Vector<ScriptValue> attribution;
+ HeapVector<ScriptValue> attribution;
for (unsigned i = 0; i < attribution_.size(); i++) {
attribution.push_back(
attribution_[i]->toJSONForBinding(builder.GetScriptState()));
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 8e52412fbb4..aea244d9897 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -81,16 +81,16 @@ PerformanceEntryType PerformanceMark::EntryTypeEnum() const {
ScriptValue PerformanceMark::detail(ScriptState* script_state) {
v8::Isolate* isolate = script_state->GetIsolate();
if (!serialized_detail_)
- return ScriptValue(script_state, v8::Null(isolate));
+ return ScriptValue(isolate, v8::Null(isolate));
auto result = deserialized_detail_map_.insert(
script_state, TraceWrapperV8Reference<v8::Value>());
TraceWrapperV8Reference<v8::Value>& relevant_data =
result.stored_value->value;
if (!result.is_new_entry)
- return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+ return ScriptValue(isolate, relevant_data.NewLocal(isolate));
v8::Local<v8::Value> value = serialized_detail_->Deserialize(isolate);
relevant_data.Set(isolate, value);
- return ScriptValue(script_state, value);
+ return ScriptValue(isolate, value);
}
void PerformanceMark::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_mark.idl b/chromium/third_party/blink/renderer/core/timing/performance_mark.idl
index b5cd0ae3197..b13216c38c4 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_mark.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_mark.idl
@@ -30,5 +30,5 @@
ConstructorCallWith=ScriptState,
RaisesException=Constructor]
interface PerformanceMark : PerformanceEntry {
- [CallWith=ScriptState, RuntimeEnabled=CustomUserTiming] readonly attribute any detail;
+ [CallWith=ScriptState] readonly attribute any detail;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_measure.cc b/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
index e3880e4c31c..dab264ca566 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
@@ -47,16 +47,16 @@ PerformanceMeasure* PerformanceMeasure::Create(
ScriptValue PerformanceMeasure::detail(ScriptState* script_state) {
v8::Isolate* isolate = script_state->GetIsolate();
if (!serialized_detail_)
- return ScriptValue(script_state, v8::Null(isolate));
+ return ScriptValue(isolate, v8::Null(isolate));
auto result = deserialized_detail_map_.insert(
script_state, TraceWrapperV8Reference<v8::Value>());
TraceWrapperV8Reference<v8::Value>& relevant_data =
result.stored_value->value;
if (!result.is_new_entry)
- return ScriptValue(script_state, relevant_data.NewLocal(isolate));
+ return ScriptValue(isolate, relevant_data.NewLocal(isolate));
v8::Local<v8::Value> value = serialized_detail_->Deserialize(isolate);
relevant_data.Set(isolate, value);
- return ScriptValue(script_state, value);
+ return ScriptValue(isolate, value);
}
AtomicString PerformanceMeasure::entryType() const {
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_measure.idl b/chromium/third_party/blink/renderer/core/timing/performance_measure.idl
index 2ee528c54cf..51c94f8967f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_measure.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance_measure.idl
@@ -27,5 +27,5 @@
[Exposed=(Window,Worker)]
interface PerformanceMeasure : PerformanceEntry {
- [CallWith=ScriptState, RuntimeEnabled=CustomUserTiming] readonly attribute any detail;
+ [CallWith=ScriptState] readonly attribute any detail;
};
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 992b20f201c..1113d681553 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -57,17 +57,13 @@ Vector<AtomicString> PerformanceObserver::supportedEntryTypes(
Vector<AtomicString> supportedEntryTypes;
auto* execution_context = ExecutionContext::From(script_state);
if (execution_context->IsDocument()) {
- if (RuntimeEnabledFeatures::ElementTimingEnabled(execution_context))
- supportedEntryTypes.push_back(performance_entry_names::kElement);
+ 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::kFirstInput);
- if (RuntimeEnabledFeatures::LargestContentfulPaintEnabled()) {
- supportedEntryTypes.push_back(
- performance_entry_names::kLargestContentfulPaint);
- }
- if (RuntimeEnabledFeatures::LayoutInstabilityAPIEnabled(execution_context))
- supportedEntryTypes.push_back(performance_entry_names::kLayoutShift);
+ supportedEntryTypes.push_back(
+ performance_entry_names::kLargestContentfulPaint);
+ supportedEntryTypes.push_back(performance_entry_names::kLayoutShift);
supportedEntryTypes.push_back(performance_entry_names::kLongtask);
}
supportedEntryTypes.push_back(performance_entry_names::kMark);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
index 2ffba14396b..0a9598dbd5c 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/performance_entry_names.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_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"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -358,7 +359,7 @@ void PerformanceResourceTiming::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.AddNumber("encodedBodySize", encodedBodySize());
builder.AddNumber("decodedBodySize", decodedBodySize());
- Vector<ScriptValue> server_timing;
+ HeapVector<ScriptValue> server_timing;
server_timing.ReserveCapacity(server_timing_.size());
for (unsigned i = 0; i < server_timing_.size(); i++) {
server_timing.push_back(
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 1c726e0d81d..72e08386078 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_test.cc
@@ -175,9 +175,15 @@ TEST_F(PerformanceTest, AllowsTimingRedirect) {
*security_origin.get(),
GetExecutionContext()));
- // When cross-origin redirect opts in.
+ // When cross-origin redirect opts in, but the final response doesn't.
redirect_chain.back().SetHttpHeaderField(http_names::kTimingAllowOrigin,
origin_domain);
+ EXPECT_FALSE(AllowsTimingRedirect(redirect_chain, final_response,
+ *security_origin.get(),
+ GetExecutionContext()));
+ // When cross-origin redirect opts in, and the final response has as well.
+ final_response.SetHttpHeaderField(http_names::kTimingAllowOrigin,
+ origin_domain);
EXPECT_TRUE(AllowsTimingRedirect(redirect_chain, final_response,
*security_origin.get(),
GetExecutionContext()));
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 ddabb647b80..597cd102ca1 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
@@ -115,8 +115,8 @@ PerformanceMark* UserTiming::CreatePerformanceMark(
start = performance_->now();
}
- ScriptValue detail = ScriptValue::CreateNull(script_state);
- if (RuntimeEnabledFeatures::CustomUserTimingEnabled() && mark_options)
+ ScriptValue detail = ScriptValue::CreateNull(script_state->GetIsolate());
+ if (mark_options)
detail = mark_options->detail();
bool is_worker_global_scope =
diff --git a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
index 3ed5fab503d..88547546bda 100644
--- a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
@@ -14,16 +14,12 @@ TaskAttributionTiming::TaskAttributionTiming(const AtomicString& name,
const String& container_type,
const String& container_src,
const String& container_id,
- const String& container_name,
- double start_time,
- double finish_time,
- const String& script_url)
- : PerformanceEntry(name, start_time, finish_time),
+ const String& container_name)
+ : PerformanceEntry(name, 0.0, 0.0),
container_type_(container_type),
container_src_(container_src),
container_id_(container_id),
- container_name_(container_name),
- script_url_(script_url) {}
+ container_name_(container_name) {}
TaskAttributionTiming::~TaskAttributionTiming() = default;
@@ -35,10 +31,6 @@ PerformanceEntryType TaskAttributionTiming::EntryTypeEnum() const {
return PerformanceEntry::EntryType::kTaskAttribution;
}
-String TaskAttributionTiming::scriptURL() const {
- return script_url_;
-}
-
String TaskAttributionTiming::containerType() const {
return container_type_;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
index 2d9b0fccf1b..41b6c10a3e7 100644
--- a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
@@ -16,29 +16,13 @@ class TaskAttributionTiming final : public PerformanceEntry {
DEFINE_WRAPPERTYPEINFO();
public:
- // Used when the LongTaskV2 flag is enabled.
- static TaskAttributionTiming* Create(const AtomicString& type,
- const String& container_type,
- const String& container_src,
- const String& container_id,
- const String& container_name,
- double start_time,
- double finish_time,
- const String& script_url) {
- return MakeGarbageCollected<TaskAttributionTiming>(
- type, container_type, container_src, container_id, container_name,
- start_time, finish_time, script_url);
- }
-
- // Used when the LongTaskV2 flag is disabled.
static TaskAttributionTiming* Create(const AtomicString& type,
const String& container_type,
const String& container_src,
const String& container_id,
const String& container_name) {
return MakeGarbageCollected<TaskAttributionTiming>(
- type, container_type, container_src, container_id, container_name, 0.0,
- 0.0, g_empty_string);
+ type, container_type, container_src, container_id, container_name);
}
AtomicString entryType() const override;
@@ -48,7 +32,6 @@ class TaskAttributionTiming final : public PerformanceEntry {
String containerSrc() const;
String containerId() const;
String containerName() const;
- String scriptURL() const;
void Trace(blink::Visitor*) override;
@@ -56,10 +39,7 @@ class TaskAttributionTiming final : public PerformanceEntry {
const String& container_type,
const String& container_src,
const String& container_id,
- const String& container_name,
- double start_time,
- double finish_time,
- const String& script_url);
+ const String& container_name);
~TaskAttributionTiming() override;
private:
@@ -69,7 +49,6 @@ class TaskAttributionTiming final : public PerformanceEntry {
String container_src_;
String container_id_;
String container_name_;
- String script_url_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.idl b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.idl
index aeb42ed0e94..4867f191eb7 100644
--- a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.idl
+++ b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.idl
@@ -5,7 +5,6 @@
// https://w3c.github.io/longtasks/#sec-TaskAttributionTiming
[Exposed=Window]
interface TaskAttributionTiming : PerformanceEntry {
- [RuntimeEnabled=LongTaskV2] readonly attribute DOMString scriptURL;
readonly attribute DOMString containerType;
readonly attribute DOMString containerSrc;
readonly attribute DOMString containerId;
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 5ae9d4aa1ba..ab312f52427 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.cc
@@ -396,7 +396,6 @@ void WindowPerformance::AddElementTiming(const AtomicString& name,
const IntSize& intrinsic_size,
const AtomicString& id,
Element* element) {
- DCHECK(RuntimeEnabledFeatures::ElementTimingEnabled(GetExecutionContext()));
PerformanceElementTiming* entry = PerformanceElementTiming::Create(
name, url, rect, MonotonicTimeToDOMHighResTimeStamp(start_time),
MonotonicTimeToDOMHighResTimeStamp(load_time), identifier,
@@ -425,8 +424,6 @@ void WindowPerformance::DispatchFirstInputTiming(
void WindowPerformance::AddLayoutShiftValue(double value,
bool input_detected,
base::TimeTicks input_timestamp) {
- DCHECK(RuntimeEnabledFeatures::LayoutInstabilityAPIEnabled(
- GetExecutionContext()));
auto* entry = MakeGarbageCollected<LayoutShift>(
now(), value, input_detected,
input_detected ? MonotonicTimeToDOMHighResTimeStamp(input_timestamp)
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 8fe7b9568fd..5e7bf3f5a45 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
@@ -205,12 +205,12 @@ TEST_F(WindowPerformanceTest, EnsureEntryListOrder) {
DummyExceptionStateForTesting exception_state;
test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
for (int i = 0; i < 8; i++) {
- performance_->mark(scope.GetScriptState(), AtomicString::Number(i),
+ performance_->mark(scope.GetScriptState(), AtomicString::Number(i), nullptr,
exception_state);
}
test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
for (int i = 8; i < 17; i++) {
- performance_->mark(scope.GetScriptState(), AtomicString::Number(i),
+ performance_->mark(scope.GetScriptState(), AtomicString::Number(i), nullptr,
exception_state);
}
PerformanceEntryVector entries = performance_->getEntries();
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 6409e93fff0..a746409eacf 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
@@ -318,7 +318,7 @@ ScriptValue TrustedTypePolicyFactory::getTypeMapping(ScriptState* script_state,
}
}
- return ScriptValue(script_state, top);
+ return ScriptValue(script_state->GetIsolate(), top);
}
void TrustedTypePolicyFactory::CountTrustedTypeAssignmentError() {
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 78113b80cae..8791c6b4a03 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
@@ -290,9 +290,12 @@ String GetStringFromTrustedHTML(const String& string,
}
if (result->toString().IsNull()) {
- TrustedTypeFail(kTrustedHTMLAssignmentAndDefaultPolicyFailed,
- execution_context, exception_state, string);
- return g_empty_string;
+ if (TrustedTypeFail(kTrustedHTMLAssignmentAndDefaultPolicyFailed,
+ execution_context, exception_state, string)) {
+ return g_empty_string;
+ } else {
+ return string;
+ }
}
return result->toString();
@@ -346,9 +349,12 @@ String GetStringFromTrustedScript(const String& potential_script,
}
if (result->toString().IsNull()) {
- TrustedTypeFail(kTrustedScriptAssignmentAndDefaultPolicyFailed,
- execution_context, exception_state, potential_script);
- return g_empty_string;
+ if (TrustedTypeFail(kTrustedScriptAssignmentAndDefaultPolicyFailed,
+ execution_context, exception_state, potential_script)) {
+ return g_empty_string;
+ } else {
+ return potential_script;
+ }
}
return result->toString();
@@ -390,9 +396,12 @@ String GetStringFromTrustedScriptURL(
}
if (result->toString().IsNull()) {
- TrustedTypeFail(kTrustedScriptURLAssignmentAndDefaultPolicyFailed,
- execution_context, exception_state, string);
- return g_empty_string;
+ if (TrustedTypeFail(kTrustedScriptURLAssignmentAndDefaultPolicyFailed,
+ execution_context, exception_state, string)) {
+ return g_empty_string;
+ } else {
+ return string;
+ }
}
return result->toString();
@@ -430,9 +439,12 @@ String GetStringFromTrustedURL(USVStringOrTrustedURL string_or_trusted_url,
}
if (result->toString().IsNull()) {
- TrustedTypeFail(kTrustedURLAssignmentAndDefaultPolicyFailed,
- execution_context, exception_state, string);
- return g_empty_string;
+ if (TrustedTypeFail(kTrustedURLAssignmentAndDefaultPolicyFailed,
+ execution_context, exception_state, string)) {
+ return g_empty_string;
+ } else {
+ return string;
+ }
}
return result->toString();
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 3806eb812f5..c2542925c69 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
@@ -33,8 +33,9 @@ class CORE_EXPORT DOMArrayBuffer final : public DOMArrayBufferBase {
static DOMArrayBuffer* Create(scoped_refptr<SharedBuffer>);
static DOMArrayBuffer* Create(const Vector<base::span<const char>>&);
- // Only for use by XMLHttpRequest::responseArrayBuffer and
- // Internals::serializeObject.
+ // Only for use by XMLHttpRequest::responseArrayBuffer,
+ // Internals::serializeObject, and
+ // FetchDataLoaderAsArrayBuffer::OnStateChange.
static DOMArrayBuffer* CreateUninitializedOrNull(unsigned num_elements,
unsigned element_byte_size);
diff --git a/chromium/third_party/blink/renderer/core/workers/BUILD.gn b/chromium/third_party/blink/renderer/core/workers/BUILD.gn
index 171e54f2770..a68fb8a29ba 100644
--- a/chromium/third_party/blink/renderer/core/workers/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/workers/BUILD.gn
@@ -48,8 +48,6 @@ blink_core_sources("workers") {
"threaded_worklet_messaging_proxy.h",
"threaded_worklet_object_proxy.cc",
"threaded_worklet_object_proxy.h",
- "worker_animation_frame_provider.cc",
- "worker_animation_frame_provider.h",
"worker_backing_thread.cc",
"worker_backing_thread.h",
"worker_backing_thread_startup_data.h",
diff --git a/chromium/third_party/blink/renderer/core/workers/README.md b/chromium/third_party/blink/renderer/core/workers/README.md
index 8e1d5616b92..dacae194165 100644
--- a/chromium/third_party/blink/renderer/core/workers/README.md
+++ b/chromium/third_party/blink/renderer/core/workers/README.md
@@ -79,7 +79,97 @@ Note that, where off-the-main-thread top-level fetch is NOT enabled
(e.g. classic workers), the worker scripts are fetched on the main thread and
thus WorkerOrWorkletGlobalScope and the worker thread are not involved.
+# Metrics
+
+## UseCounter
+
+[UseCounter](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/instrumentation/use_counter.h)
+is available in all workers and worklets. The count mechanism varies based on
+worker and worklet types as follows.
+
+- Dedicated Workers and Worklets: A feature use in a dedicated worker or worklet
+is propagated to the parent document, and then recorded in the document's
+UseCounter. For nested dedicated workers, a feature use is propagated up to the
+ancestor document via parent workers.
+- Shared Workers: A feature use in a shared worker is propagated to all
+documents connected to the shared worker via mojo calls, and then recorded in
+their UseCounter.
+- Service Workers: A feature use in a service worker is propagated to all
+documents and workers being controlled by the service worker via mojo calls, and
+then recorded in their UseCounter. When a feature use occurs before the service
+worker finishes installing, the feature use is stored in service worker storage.
+It is read whenever the installed service worker is started. See
+[content/browser/service_worker/README.md](/content/browser/service_worker/README.md)
+for details.
+
+`WorkerOrWorkletGlobalScope::CountUse()` is the common entry point. For more
+details, see [Design of UseCounter for
+workers](https://docs.google.com/document/d/1VyYZnhjBdk-MzCRAcX37TM5-yjwTY40U_J9rWnEAo8c/edit?usp=sharing)
+and [crbug 376039](https://bugs.chromium.org/p/chromium/issues/detail?id=376039).
+
+There are some fundamental metrics.
+
+- [WorkerStart](https://www.chromestatus.com/metrics/feature/timeline/popularity/4)
+: Counts of `new DedicatedWorker()` calls in `Document` and
+`DedicatedWorkerGlobalScope`.
+- [NestedDedicatedWorker](https://www.chromestatus.com/metrics/feature/timeline/popularity/2499)
+: Counts of `new DedicatedWorker()` calls in `DedicatedWorkerGlobalScope`.
+- [SharedWorkerStart](https://www.chromestatus.com/metrics/feature/timeline/popularity/5)
+: Counts of `new SharedWorker()` calls in `Document`.
+- [WorkletAddModule](https://www.chromestatus.com/metrics/feature/timeline/popularity/2364)
+: Counts of `Worklet#addModule()` calls in `Document`. This includes all worklet
+types. Each worklet type has its own counter, too.
+
+## UMA
+
+The UMA data is internal-only.
+
+- WorkerThread.ExitCode : Records the exit code of `WorkerThread`.
+
+# Tests
+
+When you add a new worker or worklet type, please consider adding tests in
+following files and directories to check integration with the underlying worker
+and worklet infrastructure.
+
+- Web Platform Tests
+ - [workers/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/workers/)
+ - [worklets/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/worklets/)
+- Web tests
+ - [webexposed/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/webexposed/)
+ - [workers/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/http/tests/workers/)
+ - [worklet/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/http/tests/worklet/)
+- Unit tests
+ - [content/browser/worker_host/](https://cs.chromium.org/chromium/src/content/browser/worker_host/)
+ - [content/renderer/worker/](https://cs.chromium.org/chromium/src/content/renderer/worker/)
+ - [third_party/blink/renderer/core/workers/](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/workers/)
+- Browser tests
+ - [chrome/browser/chrome_worker_browsertest.cc](https://cs.chromium.org/chromium/src/chrome/browser/chrome_worker_browsertest.cc)
+ - [content/browser/worker_host/worker_browsertest.cc](https://cs.chromium.org/chromium/src/content/browser/worker_host/worker_browsertest.cc)
+
+Workers and worklets interact with various features. You should also add tests
+in the following files and directories to avoid breakage.
+
+- Web Platform Tests
+ - [content-security-policy/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/content-security-policy/)
+ - [fetch/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/fetch/)
+ - [mixed-content/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/mixed-content/)
+ - [performance-timeline/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/performance-timeline/)
+ - [referrer-policy/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/referrer-policy/)
+ - [resource-timing/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/resource-timing/)
+ - [secure-contexts/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/secure-contexts/)
+ - [service-workers/service-worker/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/service-workers/service-worker/)
+ - [upgrade-insecure-requests/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/upgrade-insecure-requests/)
+ - [websockets/](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/websockets/)
+- Browser tests
+ - [chrome/browser/chrome_do_not_track_browsertest.cc](https://cs.chromium.org/chromium/src/chrome/browser/chrome_do_not_track_browsertest.cc)
+ - [chrome/browser/chrome_worker_browsertest.cc](https://cs.chromium.org/chromium/src/chrome/browser/chrome_worker_browsertest.cc)
+ - [chrome/browser/extensions/api/web_request/web_request_apitest.cc](https://cs.chromium.org/chromium/src/chrome/browser/extensions/api/web_request/web_request_apitest.cc)
+ - [chrome/browser/ssl/ssl_browsertest.cc](https://cs.chromium.org/chromium/src/chrome/browser/ssl/ssl_browsertest.cc)
+ - [chrome/browser/subresource_filter/subresource_filter_browsertest.cc](https://cs.chromium.org/chromium/src/chrome/browser/subresource_filter/subresource_filter_browsertest.cc)
+
# References
- [WorkerGlobalScope Initialization](https://docs.google.com/document/d/1JCv8TD2nPLNC2iRCp_D1OM4I3uTS0HoEobuTymaMqgw/edit?usp=sharing) (April 1, 2019)
- [Worker / Worklet Internals](https://docs.google.com/presentation/d/1GZJ3VnLIO_Pw0jr9nRw6_-trg68ol-AkliMxJ6jo6Bo/edit?usp=sharing) (April 19, 2018)
+- [Design of UseCounter for workers](https://docs.google.com/document/d/1VyYZnhjBdk-MzCRAcX37TM5-yjwTY40U_J9rWnEAo8c/edit?usp=sharing) (Feb 14, 2017)
diff --git a/chromium/third_party/blink/renderer/core/workers/abstract_worker.h b/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
index 7b210225c3b..aa6cd7d6d24 100644
--- a/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/abstract_worker.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_ABSTRACT_WORKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_ABSTRACT_WORKER_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
index eabed31b623..b0d498d03b7 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -12,11 +12,12 @@
#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h"
#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
#include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom-blink.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_fetch_client_settings_object.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.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/events/message_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -172,7 +173,7 @@ void DedicatedWorker::Dispose() {
void DedicatedWorker::postMessage(ScriptState* script_state,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
PostMessageOptions* options = PostMessageOptions::Create();
if (!transfer.IsEmpty())
@@ -247,9 +248,7 @@ void DedicatedWorker::Start() {
credentials_mode,
WebSecurityOrigin(
outside_fetch_client_settings_object_->GetSecurityOrigin()),
- outside_fetch_client_settings_object_->GetReferrerPolicy(),
- KURL(outside_fetch_client_settings_object_->GetOutgoingReferrer()),
- outside_fetch_client_settings_object_->GetInsecureRequestsPolicy(),
+ WebFetchClientSettingsObject(*outside_fetch_client_settings_object_),
blob_url_token.PassPipe());
// Continue in OnScriptLoadStarted() or OnScriptLoadStartFailed().
return;
@@ -362,13 +361,6 @@ void DedicatedWorker::DispatchErrorEventForScriptFetchFailure() {
DispatchEvent(*Event::CreateCancelable(event_type_names::kError));
}
-WorkerClients* DedicatedWorker::CreateWorkerClients() {
- auto* worker_clients = MakeGarbageCollected<WorkerClients>();
- CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
- *worker_clients);
- return worker_clients;
-}
-
std::unique_ptr<WebContentSettingsClient>
DedicatedWorker::CreateWebContentSettingsClient() {
std::unique_ptr<WebContentSettingsClient> content_settings_client;
@@ -466,8 +458,9 @@ DedicatedWorker::CreateGlobalScopeCreationParams(
GetExecutionContext()->GetContentSecurityPolicy()->Headers(),
referrer_policy, GetExecutionContext()->GetSecurityOrigin(),
GetExecutionContext()->IsSecureContext(),
- GetExecutionContext()->GetHttpsState(), CreateWorkerClients(),
- CreateWebContentSettingsClient(), response_address_space,
+ GetExecutionContext()->GetHttpsState(),
+ MakeGarbageCollected<WorkerClients>(), CreateWebContentSettingsClient(),
+ response_address_space,
OriginTrialContext::GetTokens(GetExecutionContext()).get(),
parent_devtools_token, std::move(settings), kV8CacheOptionsDefault,
nullptr /* worklet_module_responses_map */,
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
index 4e56d500d12..a3291d7dec8 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -7,7 +7,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h"
+#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_dedicated_worker.h"
#include "third_party/blink/public/platform/web_dedicated_worker_host_factory_client.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -32,7 +32,6 @@ class ExecutionContext;
class PostMessageOptions;
class ScriptState;
class WorkerClassicScriptLoader;
-class WorkerClients;
// Implementation of the Worker interface defined in the WebWorker HTML spec:
// https://html.spec.whatwg.org/C/#worker
@@ -66,7 +65,7 @@ class CORE_EXPORT DedicatedWorker final
void postMessage(ScriptState*,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(ScriptState*,
const ScriptValue& message,
@@ -112,7 +111,6 @@ class CORE_EXPORT DedicatedWorker final
network::mojom::ReferrerPolicy,
base::Optional<network::mojom::IPAddressSpace> response_address_space);
scoped_refptr<WebWorkerFetchContext> CreateWebWorkerFetchContext();
- WorkerClients* CreateWorkerClients();
// May return nullptr.
std::unique_ptr<WebContentSettingsClient> CreateWebContentSettingsClient();
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
index 515a9893a31..ab71b225d29 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -37,13 +37,13 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
+#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
#include "third_party/blink/renderer/core/messaging/post_message_options.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/modulator.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_thread.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
@@ -64,6 +64,8 @@ DedicatedWorkerGlobalScope* DedicatedWorkerGlobalScope::Create(
base::TimeTicks time_origin) {
std::unique_ptr<Vector<String>> outside_origin_trial_tokens =
std::move(creation_params->origin_trial_tokens);
+ BeginFrameProviderParams begin_frame_provider_params =
+ creation_params->begin_frame_provider_params;
// Off-the-main-thread worker script fetch:
// Initialize() is called after script fetch.
@@ -71,7 +73,7 @@ DedicatedWorkerGlobalScope* DedicatedWorkerGlobalScope::Create(
OffMainThreadWorkerScriptFetchOption::kEnabled) {
return MakeGarbageCollected<DedicatedWorkerGlobalScope>(
std::move(creation_params), thread, time_origin,
- std::move(outside_origin_trial_tokens));
+ std::move(outside_origin_trial_tokens), begin_frame_provider_params);
}
// Legacy on-the-main-thread worker script fetch (to be removed):
@@ -82,7 +84,7 @@ DedicatedWorkerGlobalScope* DedicatedWorkerGlobalScope::Create(
*creation_params->response_address_space;
auto* global_scope = MakeGarbageCollected<DedicatedWorkerGlobalScope>(
std::move(creation_params), thread, time_origin,
- std::move(outside_origin_trial_tokens));
+ std::move(outside_origin_trial_tokens), begin_frame_provider_params);
// Pass dummy CSP headers here as it is superseded by outside's CSP headers in
// Initialize().
// Pass dummy origin trial tokens here as it is already set to outside's
@@ -100,8 +102,15 @@ DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
DedicatedWorkerThread* thread,
base::TimeTicks time_origin,
- std::unique_ptr<Vector<String>> outside_origin_trial_tokens)
- : WorkerGlobalScope(std::move(creation_params), thread, time_origin) {
+ std::unique_ptr<Vector<String>> outside_origin_trial_tokens,
+ const BeginFrameProviderParams& begin_frame_provider_params)
+ : WorkerGlobalScope(std::move(creation_params), thread, time_origin),
+ animation_frame_provider_(
+ MakeGarbageCollected<WorkerAnimationFrameProvider>(
+ this,
+ begin_frame_provider_params)) {
+ CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(*this);
+
// Dedicated workers don't need to pause after script fetch.
ReadyToRunWorkerScript();
// Inherit the outside's origin trial tokens.
@@ -199,8 +208,6 @@ void DedicatedWorkerGlobalScope::FetchAndRunModuleScript(
// "worker" otherwise."
mojom::RequestContextType destination = mojom::RequestContextType::WORKER;
- Modulator* modulator = Modulator::From(ScriptController()->GetScriptState());
-
// Step 13: "... Fetch a module worker script graph given url, outside
// settings, destination, the value of the credentials member of options, and
// inside settings."
@@ -208,7 +215,8 @@ void DedicatedWorkerGlobalScope::FetchAndRunModuleScript(
outside_resource_timing_notifier, destination,
credentials_mode,
ModuleScriptCustomFetchType::kWorkerConstructor,
- MakeGarbageCollected<WorkerModuleTreeClient>(modulator));
+ MakeGarbageCollected<WorkerModuleTreeClient>(
+ ScriptController()->GetScriptState()));
}
const String DedicatedWorkerGlobalScope::name() const {
@@ -217,7 +225,7 @@ const String DedicatedWorkerGlobalScope::name() const {
void DedicatedWorkerGlobalScope::postMessage(ScriptState* script_state,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
PostMessageOptions* options = PostMessageOptions::Create();
if (!transfer.IsEmpty())
@@ -270,9 +278,17 @@ void DedicatedWorkerGlobalScope::DidFetchClassicScript(
// Step 12. "If the algorithm asynchronously completes with null, then:"
if (classic_script_loader->Failed()) {
// Step 12.1. "Queue a task to fire an event named error at worker."
+ // DidFailToFetchClassicScript() will asynchronously fire the event.
+ ReportingProxy().DidFailToFetchClassicScript();
+
// Step 12.2. "Run the environment discarding steps for inside settings."
+ // Do nothing because the HTML spec doesn't define these steps for web
+ // workers.
+
+ // Schedule worker termination.
+ close();
+
// Step 12.3. "Return."
- ReportingProxy().DidFailToFetchClassicScript();
return;
}
ReportingProxy().DidFetchScript();
@@ -304,12 +320,36 @@ void DedicatedWorkerGlobalScope::DidFetchClassicScript(
classic_script_loader->ReleaseCachedMetadata(), stack_id);
}
+int DedicatedWorkerGlobalScope::requestAnimationFrame(
+ V8FrameRequestCallback* callback,
+ ExceptionState& exception_state) {
+ auto* frame_callback =
+ MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
+ callback);
+ frame_callback->SetUseLegacyTimeBase(false);
+
+ int ret = animation_frame_provider_->RegisterCallback(frame_callback);
+
+ if (ret == WorkerAnimationFrameProvider::kInvalidCallbackId) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "requestAnimationFrame not supported in this Worker.");
+ }
+
+ return ret;
+}
+
+void DedicatedWorkerGlobalScope::cancelAnimationFrame(int id) {
+ animation_frame_provider_->CancelCallback(id);
+}
+
DedicatedWorkerObjectProxy& DedicatedWorkerGlobalScope::WorkerObjectProxy()
const {
return static_cast<DedicatedWorkerThread*>(GetThread())->WorkerObjectProxy();
}
void DedicatedWorkerGlobalScope::Trace(blink::Visitor* visitor) {
+ visitor->Trace(animation_frame_provider_);
WorkerGlobalScope::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
index ef1d83729c3..c75483c4874 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_GLOBAL_SCOPE_H_
#include <memory>
+#include "third_party/blink/renderer/core/animation_frame/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
@@ -64,7 +65,8 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
std::unique_ptr<GlobalScopeCreationParams>,
DedicatedWorkerThread*,
base::TimeTicks time_origin,
- std::unique_ptr<Vector<String>> outside_origin_trial_tokens);
+ std::unique_ptr<Vector<String>> outside_origin_trial_tokens,
+ const BeginFrameProviderParams& begin_frame_provider_params);
~DedicatedWorkerGlobalScope() override;
@@ -75,6 +77,13 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
// (via WorkerOrWorkletGlobalScope -> EventTargetWithInlineData).
const AtomicString& InterfaceName() const override;
+ // RequestAnimationFrame
+ int requestAnimationFrame(V8FrameRequestCallback* callback, ExceptionState&);
+ void cancelAnimationFrame(int id);
+ WorkerAnimationFrameProvider* GetAnimationFrameProvider() {
+ return animation_frame_provider_;
+ }
+
// Implements WorkerGlobalScope.
void Initialize(const KURL& response_url,
network::mojom::ReferrerPolicy response_referrer_policy,
@@ -97,7 +106,7 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
const String name() const;
void postMessage(ScriptState*,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(ScriptState*,
const ScriptValue& message,
@@ -116,6 +125,8 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
const v8_inspector::V8StackTraceId& stack_id);
DedicatedWorkerObjectProxy& WorkerObjectProxy() const;
+
+ Member<WorkerAnimationFrameProvider> animation_frame_provider_;
};
template <>
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl
index 4adb13fbd9c..034a5e4790b 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl
@@ -41,6 +41,11 @@
void close();
+ // AnimationFrameProvider mixin
+ // https://html.spec.whatwg.org/C/#animation-frames
+ [RaisesException] long requestAnimationFrame(FrameRequestCallback callback);
+ void cancelAnimationFrame(long handle);
+
attribute EventHandler onmessage;
attribute EventHandler onmessageerror;
};
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 0347fe0d0c6..c43b26d59c8 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
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
-#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
index 27cabe55159..0ad228d9b6d 100644
--- a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
+++ b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
@@ -8,6 +8,7 @@
#include "base/feature_list.h"
#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
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 b77a367682f..6b3e731dc50 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
@@ -9,12 +9,12 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
-#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
-#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
+#include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
+#include "services/service_manager/public/mojom/interface_provider.mojom-blink-forward.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h"
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.cc b/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
index ecc4c906a41..39256203da2 100644
--- a/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
+++ b/chromium/third_party/blink/renderer/core/workers/installed_scripts_manager.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
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 7f21620bb10..bdb32e3d1c6 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,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_INSTALLED_SCRIPTS_MANAGER_H_
#include "base/optional.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.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"
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 84734915fc3..eab3581aa94 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
@@ -20,7 +20,7 @@ namespace blink {
// Represents a set of task runners of the parent execution context, or default
// task runners for the current thread if no execution context is available.
class CORE_EXPORT ParentExecutionContextTaskRunners final
- : public GarbageCollectedFinalized<ParentExecutionContextTaskRunners>,
+ : public GarbageCollected<ParentExecutionContextTaskRunners>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(ParentExecutionContextTaskRunners);
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 a59696a2edb..9b69f968620 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -33,6 +33,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/common/blob/blob_utils.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"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/messaging/message_channel.h"
@@ -46,8 +47,29 @@
namespace blink {
-inline SharedWorker::SharedWorker(ExecutionContext* context)
- : AbstractWorker(context), is_being_connected_(false) {}
+namespace {
+
+void RecordSharedWorkerUsage(Document* document) {
+ UseCounter::Count(document, WebFeature::kSharedWorkerStart);
+
+ // Don't record the use counter if the frame is same-origin to the top frame,
+ // or if we can't tell whether the frame was ever cross-origin or not.
+ if (!document->TopFrameOrigin() ||
+ document->TopFrameOrigin()->CanAccess(document->GetSecurityOrigin())) {
+ return;
+ }
+
+ UseCounter::Count(document, WebFeature::kThirdPartySharedWorker);
+}
+
+} // namespace
+
+SharedWorker::SharedWorker(ExecutionContext* context)
+ : AbstractWorker(context),
+ is_being_connected_(false),
+ feature_handle_for_scheduler_(context->GetScheduler()->RegisterFeature(
+ SchedulingPolicy::Feature::kSharedWorker,
+ {SchedulingPolicy::RecordMetricsForBackForwardCache()})) {}
SharedWorker* SharedWorker::Create(ExecutionContext* context,
const String& url,
@@ -55,7 +77,12 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
- UseCounter::Count(context, WebFeature::kSharedWorkerStart);
+ // We don't currently support nested workers, so workers can only be created
+ // from documents.
+ Document* document = To<Document>(context);
+ DCHECK(document);
+
+ RecordSharedWorkerUsage(document);
SharedWorker* worker = MakeGarbageCollected<SharedWorker>(context);
worker->UpdateStateIfNeeded();
@@ -64,9 +91,6 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
worker->port_ = channel->port1();
MessagePortChannel remote_port = channel->port2()->Disentangle();
- // We don't currently support nested workers, so workers can only be created
- // from documents.
- Document* document = To<Document>(context);
if (!document->GetSecurityOrigin()->CanAccessSharedWorkers()) {
exception_state.ThrowSecurityError(
"Access to shared workers is denied to origin '" +
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 f47d2a5e6af..75d750959d2 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.h
@@ -36,6 +36,7 @@
#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"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
@@ -73,6 +74,8 @@ class CORE_EXPORT SharedWorker final
private:
Member<MessagePort> port_;
bool is_being_connected_;
+ FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
+ feature_handle_for_scheduler_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
index fea6b94aeb4..1214ae54826 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_client_holder.cc
@@ -36,6 +36,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom-blink.h"
#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom-blink.h"
#include "third_party/blink/public/platform/web_content_security_policy.h"
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 258cf5e118e..af9da612a49 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
@@ -38,8 +38,8 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
-#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
-#include "third_party/blink/public/mojom/worker/shared_worker_client.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/worker/shared_worker_client.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -61,7 +61,7 @@ class SharedWorker;
// SharedWorkerClientHolder is a per-Document object and owned by Document via
// Supplement<Document>.
class CORE_EXPORT SharedWorkerClientHolder final
- : public GarbageCollectedFinalized<SharedWorkerClientHolder>,
+ : public GarbageCollected<SharedWorkerClientHolder>,
public Supplement<Document>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(SharedWorkerClientHolder);
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.cc
index 5e67fd0a6a6..05990b05e3d 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-blink.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h
index 856298fdaf0..4c343ab537b 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-blink.h"
+#include "third_party/blink/public/mojom/worker/worker_content_settings_proxy.mojom-blink-forward.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/platform/weborigin/security_origin.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
index bae9c53d4bb..008ff1ba127 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
+#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -75,6 +76,8 @@ void SharedWorkerGlobalScope::Initialize(
const Vector<CSPHeaderAndType>& response_csp_headers,
const Vector<String>* response_origin_trial_tokens,
int64_t appcache_id) {
+ CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(*this);
+
// Step 12.3. "Set worker global scope's url to response's url."
InitializeURL(response_url);
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
index e259234fbe3..1a8f0f9a527 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
@@ -18,7 +18,7 @@ class WebSharedWorkerImpl;
// and owned by WebSharedWorkerImpl on the main thread, accessed from a worker
// thread, and destroyed on the main thread.
class SharedWorkerReportingProxy final
- : public GarbageCollectedFinalized<SharedWorkerReportingProxy>,
+ : public GarbageCollected<SharedWorkerReportingProxy>,
public WorkerReportingProxy {
public:
SharedWorkerReportingProxy(WebSharedWorkerImpl*,
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h b/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h
index b5c0674a8db..a6136d72b52 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_MESSAGING_PROXY_BASE_H_
#include "base/optional.h"
-#include "third_party/blink/public/mojom/devtools/console_message.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/core/frame/web_feature_forward.h"
#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
@@ -42,7 +42,7 @@ struct GlobalScopeCreationParams;
// living on the worker thread (e.g., WorkerGlobalScope) but the parent object
// can be destroyed before the completion of worker thread termination.
class CORE_EXPORT ThreadedMessagingProxyBase
- : public GarbageCollectedFinalized<ThreadedMessagingProxyBase> {
+ : public GarbageCollected<ThreadedMessagingProxyBase> {
public:
virtual ~ThreadedMessagingProxyBase();
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 0ee2070f801..7574f3054ed 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
@@ -30,8 +30,8 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "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/threadable_loader.h"
@@ -53,7 +53,7 @@ class ExecutionContext;
class TextResourceDecoder;
class CORE_EXPORT WorkerClassicScriptLoader final
- : public GarbageCollectedFinalized<WorkerClassicScriptLoader>,
+ : public GarbageCollected<WorkerClassicScriptLoader>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(WorkerClassicScriptLoader);
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h b/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
index 3eb6d845757..f165f7a8a36 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
@@ -16,7 +16,7 @@
namespace blink {
-class ClientImpl final : public GarbageCollectedFinalized<ClientImpl>,
+class ClientImpl final : public GarbageCollected<ClientImpl>,
public ModuleScriptFetcher::Client {
USING_GARBAGE_COLLECTED_MIXIN(ClientImpl);
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 10f2de79d8e..7ca3f27951b 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
@@ -282,27 +282,6 @@ bool WorkerGlobalScope::FetchClassicImportedScript(
KURL* out_response_url,
String* out_source_code,
std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data) {
- // InstalledScriptsManager is now used only for starting installed service
- // workers.
- // TODO(nhiroki): Consider moving this into ServiceWorkerGlobalScope.
- InstalledScriptsManager* installed_scripts_manager =
- GetThread()->GetInstalledScriptsManager();
- if (installed_scripts_manager &&
- installed_scripts_manager->IsScriptInstalled(script_url)) {
- DCHECK(IsServiceWorkerGlobalScope());
- std::unique_ptr<InstalledScriptsManager::ScriptData> script_data =
- installed_scripts_manager->GetScriptData(script_url);
- if (!script_data)
- return false;
- *out_response_url = script_url;
- *out_source_code = script_data->TakeSourceText();
- *out_cached_meta_data = script_data->TakeMetaData();
- // TODO(shimazu): Add appropriate probes for inspector.
- return true;
- }
-
- // If the script wasn't provided by the InstalledScriptsManager, load from
- // ResourceLoader.
ExecutionContext* execution_context = GetExecutionContext();
WorkerClassicScriptLoader* classic_script_loader =
MakeGarbageCollected<WorkerClassicScriptLoader>();
@@ -489,10 +468,6 @@ WorkerGlobalScope::WorkerGlobalScope(
timers_(GetTaskRunner(TaskType::kJavascriptTimer)),
time_origin_(time_origin),
font_selector_(MakeGarbageCollected<OffscreenFontSelector>(this)),
- animation_frame_provider_(
- MakeGarbageCollected<WorkerAnimationFrameProvider>(
- this,
- creation_params->begin_frame_provider_params)),
script_eval_state_(ScriptEvalState::kPauseAfterFetch) {
InstanceCounters::IncrementCounter(
InstanceCounters::kWorkerGlobalScopeCounter);
@@ -561,28 +536,6 @@ void WorkerGlobalScope::queueMicrotask(V8VoidFunction* callback) {
WrapPersistent(callback), nullptr));
}
-int WorkerGlobalScope::requestAnimationFrame(V8FrameRequestCallback* callback,
- ExceptionState& exception_state) {
- auto* frame_callback =
- MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
- callback);
- frame_callback->SetUseLegacyTimeBase(true);
-
- int ret = animation_frame_provider_->RegisterCallback(frame_callback);
-
- if (ret == WorkerAnimationFrameProvider::kInvalidCallbackId) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kNotSupportedError,
- "requestAnimationFrame not supported in this Worker.");
- }
-
- return ret;
-}
-
-void WorkerGlobalScope::cancelAnimationFrame(int id) {
- animation_frame_provider_->CancelCallback(id);
-}
-
void WorkerGlobalScope::SetWorkerSettings(
std::unique_ptr<WorkerSettings> worker_settings) {
worker_settings_ = std::move(worker_settings);
@@ -605,7 +558,6 @@ void WorkerGlobalScope::Trace(blink::Visitor* visitor) {
visitor->Trace(timers_);
visitor->Trace(pending_error_events_);
visitor->Trace(font_selector_);
- visitor->Trace(animation_frame_provider_);
visitor->Trace(trusted_types_);
visitor->Trace(worker_script_);
WorkerOrWorkletGlobalScope::Trace(visitor);
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 1a07a8847ef..0c6b99bd5a9 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
@@ -28,12 +28,12 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_GLOBAL_SCOPE_H_
#include <memory>
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "services/service_manager/public/mojom/interface_provider.mojom-blink-forward.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/script/script_type.mojom-blink.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"
#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
@@ -43,7 +43,6 @@
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
-#include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_settings.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -60,6 +59,7 @@ class ConsoleMessage;
class ExceptionState;
class FetchClientSettingsObjectSnapshot;
class FontFaceSet;
+class InstalledScriptsManager;
class OffscreenFontSelector;
class WorkerResourceTimingNotifier;
class StringOrTrustedScriptURL;
@@ -191,6 +191,10 @@ class CORE_EXPORT WorkerGlobalScope
void Trace(blink::Visitor*) override;
+ virtual InstalledScriptsManager* GetInstalledScriptsManager() {
+ return nullptr;
+ }
+
// TODO(fserb): This can be removed once we WorkerGlobalScope implements
// FontFaceSource on the IDL.
FontFaceSet* fonts();
@@ -198,17 +202,8 @@ class CORE_EXPORT WorkerGlobalScope
// https://html.spec.whatwg.org/C/#windoworworkerglobalscope-mixin
void queueMicrotask(V8VoidFunction*);
- int requestAnimationFrame(V8FrameRequestCallback* callback, ExceptionState&);
- void cancelAnimationFrame(int id);
-
- WorkerAnimationFrameProvider* GetAnimationFrameProvider() {
- return animation_frame_provider_;
- }
-
TrustedTypePolicyFactory* GetTrustedTypes() const override;
- TrustedTypePolicyFactory* trustedTypesWorkers() const {
- return GetTrustedTypes();
- }
+ TrustedTypePolicyFactory* trustedTypes() const { return GetTrustedTypes(); }
protected:
WorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
@@ -219,6 +214,12 @@ class CORE_EXPORT WorkerGlobalScope
void ExceptionThrown(ErrorEvent*) override;
void RemoveURLFromMemoryCache(const KURL&) final;
+ virtual bool FetchClassicImportedScript(
+ const KURL& script_url,
+ KURL* out_response_url,
+ String* out_source_code,
+ std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data);
+
// Notifies that the top-level worker script is ready to evaluate.
// Worker top-level script is evaluated after it is fetched and
// ReadyToRunWorkerScript() is called.
@@ -236,12 +237,6 @@ class CORE_EXPORT WorkerGlobalScope
// Used for importScripts().
void ImportScriptsInternal(const Vector<String>& urls, ExceptionState&);
- bool FetchClassicImportedScript(
- const KURL& script_url,
- KURL* out_response_url,
- String* out_source_code,
- std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data);
-
// ExecutionContext
EventTarget* ErrorEventTarget() final { return this; }
@@ -266,25 +261,25 @@ class CORE_EXPORT WorkerGlobalScope
int last_pending_error_event_id_ = 0;
Member<OffscreenFontSelector> font_selector_;
- Member<WorkerAnimationFrameProvider> animation_frame_provider_;
service_manager::InterfaceProvider interface_provider_;
blink::BrowserInterfaceBrokerProxy browser_interface_broker_proxy_;
- // State transition about worker-toplevel script evaluation.
+ // State transition about worker top-level script evaluation.
enum class ScriptEvalState {
- // Initial state: ReadyToRunWorkerScript() is not yet called.
- // Worker top-level script fetch might or might not completed, and even when
- // the fetch completes in this state, script evaluation will be deferred to
- // when ReadyToRunWorkerScript() is called later.
+ // Initial state: ReadyToRunWorkerScript() was not yet called.
+ // Worker top-level script fetch might or might not be completed, and even
+ // when the fetch completes in this state, script evaluation will be
+ // deferred to when ReadyToRunWorkerScript() is called later.
kPauseAfterFetch,
- // ReadyToRunWorkerScript() is already called.
+ // ReadyToRunWorkerScript() was already called.
kReadyToEvaluate,
- // The worker top-level script is evaluated.
+ // The worker top-level script was evaluated.
kEvaluated,
};
ScriptEvalState script_eval_state_;
+
Member<Script> worker_script_;
base::Optional<v8_inspector::V8StackTraceId> stack_id_;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
index 23fb81b3dae..a6d5607ff13 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worker_global_scope.idl
@@ -68,18 +68,13 @@
[Replaceable] readonly attribute DOMString origin;
void queueMicrotask(VoidFunction callback);
- // AnimationFrameProvider mixin
- // https://html.spec.whatwg.org/C/#animation-frames
- [RaisesException] long requestAnimationFrame(FrameRequestCallback callback);
- void cancelAnimationFrame(long handle);
-
// FontFaceSource
// https://drafts.csswg.org/css-font-loading-3/#font-face-source
// TODO(fserb): temporarly until we can enable the interface below.
readonly attribute FontFaceSet fonts;
// TrustedTypes API: http://github.com/wicg/trusted-types
- [RuntimeEnabled=TrustedDOMTypes, Unforgeable] readonly attribute TrustedTypePolicyFactory TrustedTypesWorkers;
+ [RuntimeEnabled=TrustedDOMTypes, Unforgeable] readonly attribute TrustedTypePolicyFactory trustedTypes;
};
WorkerGlobalScope includes WindowOrWorkerGlobalScope;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.cc b/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.cc
index 09c770c4a15..8c75b65c884 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.cc
@@ -12,24 +12,33 @@
namespace blink {
-WorkerModuleTreeClient::WorkerModuleTreeClient(Modulator* modulator)
- : modulator_(modulator) {}
+WorkerModuleTreeClient::WorkerModuleTreeClient(ScriptState* script_state)
+ : script_state_(script_state) {}
// A partial implementation of the "Processing model" algorithm in the HTML
// WebWorker spec:
// https://html.spec.whatwg.org/C/#worker-processing-model
void WorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
ModuleScript* module_script) {
- auto* execution_context =
- ExecutionContext::From(modulator_->GetScriptState());
- auto* worker_global_scope = To<WorkerGlobalScope>(execution_context);
+ auto* worker_global_scope =
+ To<WorkerGlobalScope>(ExecutionContext::From(script_state_));
blink::WorkerReportingProxy& worker_reporting_proxy =
worker_global_scope->ReportingProxy();
+ // Step 12. "If the algorithm asynchronously completes with null, then:"
if (!module_script) {
- // Step 12: "If the algorithm asynchronously completes with null, queue
- // a task to fire an event named error at worker, and return."
+ // Step 12.1. "Queue a task to fire an event named error at worker."
+ // DidFailToFetchModuleScript() will asynchronously fire the event.
worker_reporting_proxy.DidFailToFetchModuleScript();
+
+ // Step 12.2. "Run the environment discarding steps for inside settings."
+ // Do nothing because the HTML spec doesn't define these steps for web
+ // workers.
+
+ // Schedule worker termination.
+ worker_global_scope->close();
+
+ // Step 12.3. "Return."
return;
}
worker_reporting_proxy.DidFetchScript();
@@ -42,7 +51,7 @@ void WorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
}
void WorkerModuleTreeClient::Trace(blink::Visitor* visitor) {
- visitor->Trace(modulator_);
+ visitor->Trace(script_state_);
ModuleTreeClient::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.h b/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.h
index f8fb089433d..e96559501b5 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_module_tree_client.h
@@ -12,11 +12,12 @@
namespace blink {
class ModuleScript;
+class ScriptState;
// A ModuleTreeClient that lives on the worker context's thread.
class CORE_EXPORT WorkerModuleTreeClient final : public ModuleTreeClient {
public:
- explicit WorkerModuleTreeClient(Modulator*);
+ explicit WorkerModuleTreeClient(ScriptState*);
// Implements ModuleTreeClient.
void NotifyModuleTreeLoadFinished(ModuleScript*) final;
@@ -24,7 +25,7 @@ class CORE_EXPORT WorkerModuleTreeClient final : public ModuleTreeClient {
void Trace(blink::Visitor*) override;
private:
- Member<Modulator> modulator_;
+ Member<ScriptState> script_state_;
};
} // namespace blink
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 bb65fed1a7c..48fa7913cae 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
@@ -276,6 +276,9 @@ void WorkerOrWorkletGlobalScope::InitializeWebFetchContextIfNeeded() {
ResourceFetcher* WorkerOrWorkletGlobalScope::EnsureFetcher() {
DCHECK(IsContextThread());
+ // Worklets don't support subresource fetch.
+ DCHECK(IsWorkerGlobalScope());
+
if (inside_settings_resource_fetcher_)
return inside_settings_resource_fetcher_;
@@ -337,6 +340,8 @@ ResourceFetcher* WorkerOrWorkletGlobalScope::CreateFetcherInternal(
ResourceFetcher* WorkerOrWorkletGlobalScope::Fetcher() const {
DCHECK(IsContextThread());
+ // Worklets don't support subresource fetch.
+ DCHECK(IsWorkerGlobalScope());
DCHECK(inside_settings_resource_fetcher_);
return inside_settings_resource_fetcher_;
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
index 7f8c77b5c2b..ff29486b4a1 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
@@ -7,7 +7,7 @@
#include <bitset>
#include "base/single_thread_task_runner.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -103,6 +103,8 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
// Returns nullptr if this global scope is a WorkletGlobalScope
virtual WorkerNavigator* navigator() const { return nullptr; }
+ // 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();
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_reporting_proxy.h b/chromium/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
index 3f702ac14d9..dfedeec02fd 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_reporting_proxy.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_REPORTING_PROXY_H_
#include <memory>
-#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.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/frame/web_feature_forward.h"
@@ -74,17 +74,13 @@ class CORE_EXPORT WorkerReportingProxy {
// via ResourceLoader. Called before WillEvaluateClassicScript().
virtual void DidLoadClassicScript() {}
- // Invoked when it's failed to load the worker's main script on the worker
- // thread.
- virtual void DidFailToLoadClassicScript() {}
-
// Invoked on success to fetch the worker's main classic/module script from
// network. This is not called when the script is loaded from
// InstalledScriptsManager.
virtual void DidFetchScript() {}
- // Invoked on failure to fetch the worker's classic script from network. This
- // is not called when the script is loaded from InstalledScriptsManager.
+ // Invoked on failure to fetch the worker's classic script (either from
+ // network or InstalledScriptsManager).
virtual void DidFailToFetchClassicScript() {}
// Invoked on failure to fetch the worker's module script (either from network
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 b4785ee3f50..d16b0ea72e4 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -74,6 +74,18 @@ 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() {
@@ -140,7 +152,9 @@ class WorkerThread::InterruptData {
WorkerThread::~WorkerThread() {
DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
MutexLocker lock(ThreadSetMutex());
- DCHECK(WorkerThreads().Contains(this));
+ DCHECK(InitializingWorkerThreads().Contains(this) ||
+ WorkerThreads().Contains(this));
+ InitializingWorkerThreads().erase(this);
WorkerThreads().erase(this);
DCHECK(child_threads_.IsEmpty());
@@ -289,18 +303,8 @@ void WorkerThread::TerminateAllWorkersForTesting() {
// Keep this lock to prevent WorkerThread instances from being destroyed.
MutexLocker lock(ThreadSetMutex());
- HashSet<WorkerThread*> threads = WorkerThreads();
-
- 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();
+ TerminateThreadsInSet(InitializingWorkerThreads());
+ TerminateThreadsInSet(WorkerThreads());
}
void WorkerThread::WillProcessTask(const base::PendingTask& pending_task) {
@@ -374,7 +378,12 @@ WorkerInspectorController* WorkerThread::GetWorkerInspectorController() {
unsigned WorkerThread::WorkerThreadCount() {
MutexLocker lock(ThreadSetMutex());
- return WorkerThreads().size();
+ return InitializingWorkerThreads().size() + WorkerThreads().size();
+}
+
+HashSet<WorkerThread*>& WorkerThread::InitializingWorkerThreads() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
+ return threads;
}
HashSet<WorkerThread*>& WorkerThread::WorkerThreads() {
@@ -453,7 +462,7 @@ WorkerThread::WorkerThread(WorkerReportingProxy& worker_reporting_proxy,
shutdown_event_(RefCountedWaitableEvent::Create()) {
DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
MutexLocker lock(ThreadSetMutex());
- WorkerThreads().insert(this);
+ InitializingWorkerThreads().insert(this);
}
void WorkerThread::ScheduleToTerminateScriptExecution() {
@@ -584,6 +593,14 @@ void WorkerThread::InitializeOnWorkerThread(
return;
}
+ {
+ MutexLocker lock(ThreadSetMutex());
+ DCHECK(InitializingWorkerThreads().Contains(this));
+ DCHECK(!WorkerThreads().Contains(this));
+ InitializingWorkerThreads().erase(this);
+ WorkerThreads().insert(this);
+ }
+
// It is important that no code is run on the Isolate between
// initializing InspectorTaskRunner and pausing on start.
// Otherwise, InspectorTaskRunner might interrupt isolate execution
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 bd46163012d..f84c2a3d4c5 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.h
@@ -35,7 +35,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/thread_annotations.h"
#include "base/unguessable_token.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread_type.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -57,7 +57,6 @@ namespace blink {
class ConsoleMessageStorage;
class InspectorTaskRunner;
-class InstalledScriptsManager;
class WorkerBackingThread;
class WorkerInspectorController;
class WorkerOrWorkletGlobalScope;
@@ -187,6 +186,8 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
// Runs |function| with |parameters| on each worker thread, and
// adds the current WorkerThread* as the first parameter |function|.
+ // This only calls |function| for threads for which Start() was already
+ // called.
template <typename FunctionType, typename... Parameters>
static void CallOnAllWorkerThreads(FunctionType function,
TaskType task_type,
@@ -212,11 +213,6 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
return parent_thread_default_task_runner_;
}
- // For ServiceWorkerScriptStreaming. Returns nullptr otherwise.
- virtual InstalledScriptsManager* GetInstalledScriptsManager() {
- return nullptr;
- }
-
scheduler::WorkerScheduler* GetScheduler();
// Returns a task runner bound to the per-global-scope scheduler's task queue.
@@ -226,6 +222,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
// function can be called on both the main thread and the worker thread.
// You must not call this after Terminate() is called.
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType type) {
+ DCHECK(worker_scheduler_);
return worker_scheduler_->GetTaskRunner(type);
}
@@ -273,7 +270,11 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
FRIEND_TEST_ALL_PREFIXES(WorkerThreadTest,
Terminate_WhileDebuggerTaskIsRunning);
+ // Contains threads which are created but haven't started.
+ static HashSet<WorkerThread*>& InitializingWorkerThreads();
+ // Contains threads which have started.
static HashSet<WorkerThread*>& WorkerThreads();
+ // This mutex guards both WorkerThreads() and InitializingWorkerThreads().
static Mutex& ThreadSetMutex();
// Represents the state of this worker thread.
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc b/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
index f2830066597..2023f78d5ba 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/synchronization/waitable_event.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
@@ -276,7 +277,8 @@ TEST_F(WorkerThreadTest, SyncTerminate_OnIdle) {
// idle.
worker_thread_->WaitForInit();
- WorkerThread::TerminateAllWorkersForTesting();
+ worker_thread_->TerminateForTesting();
+ worker_thread_->WaitForShutdownForTesting();
// The worker thread may gracefully shut down before forcible termination
// runs.
@@ -302,12 +304,13 @@ TEST_F(WorkerThreadTest, SyncTerminate_ImmediatelyAfterStart) {
// There are two possible cases depending on timing:
// (1) If the thread hasn't been initialized on the worker thread yet,
- // TerminateAllWorkersForTesting() should wait for initialization and shut
- // down the thread immediately after that.
+ // TerminateForTesting() should wait for initialization and shut down the
+ // thread immediately after that.
// (2) If the thread has already been initialized on the worker thread,
- // TerminateAllWorkersForTesting() should synchronously forcibly terminates
- // the worker execution.
- WorkerThread::TerminateAllWorkersForTesting();
+ // TerminateForTesting() should synchronously forcibly terminates the worker
+ // script execution.
+ worker_thread_->TerminateForTesting();
+ worker_thread_->WaitForShutdownForTesting();
ExitCode exit_code = GetExitCode();
EXPECT_TRUE(ExitCode::kGracefullyTerminated == exit_code ||
ExitCode::kSyncForciblyTerminated == exit_code);
@@ -342,9 +345,9 @@ TEST_F(WorkerThreadTest, SyncTerminate_WhileTaskIsRunning) {
StartWithSourceCodeNotToFinish();
reporting_proxy_->WaitUntilScriptEvaluation();
- // TerminateAllWorkersForTesting() synchronously terminates the worker
- // execution.
- WorkerThread::TerminateAllWorkersForTesting();
+ // TerminateForTesting() synchronously terminates the worker script execution.
+ worker_thread_->TerminateForTesting();
+ worker_thread_->WaitForShutdownForTesting();
EXPECT_EQ(ExitCode::kSyncForciblyTerminated, GetExitCode());
}
@@ -361,9 +364,10 @@ TEST_F(WorkerThreadTest,
EXPECT_TRUE(IsForcibleTerminationTaskScheduled());
EXPECT_EQ(ExitCode::kNotTerminated, GetExitCode());
- // TerminateAllWorkersForTesting() should overtake the scheduled forcible
- // termination task.
- WorkerThread::TerminateAllWorkersForTesting();
+ // TerminateForTesting() should overtake the scheduled forcible termination
+ // task.
+ worker_thread_->TerminateForTesting();
+ worker_thread_->WaitForShutdownForTesting();
EXPECT_FALSE(IsForcibleTerminationTaskScheduled());
EXPECT_EQ(ExitCode::kSyncForciblyTerminated, GetExitCode());
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.cc b/chromium/third_party/blink/renderer/core/workers/worklet.cc
index 23f73cff032..1195b520b15 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.cc
@@ -44,13 +44,13 @@ void Worklet::Dispose() {
// https://drafts.css-houdini.org/worklets/#dom-worklet-addmodule
ScriptPromise Worklet::addModule(ScriptState* script_state,
const String& module_url,
- const WorkletOptions* options) {
+ const WorkletOptions* options,
+ ExceptionState& exception_state) {
DCHECK(IsMainThread());
if (!GetExecutionContext()) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kInvalidStateError,
- "This frame is already detached"));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "This frame is already detached");
+ return ScriptPromise();
}
UseCounter::Count(GetExecutionContext(),
mojom::WebFeature::kWorkletAddModule);
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.h b/chromium/third_party/blink/renderer/core/workers/worklet.h
index f0a802bf6e6..e37bb631ef5 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.h
@@ -38,7 +38,8 @@ class CORE_EXPORT Worklet : public ScriptWrappable,
// addModule() imports ES6 module scripts.
ScriptPromise addModule(ScriptState*,
const String& module_url,
- const WorkletOptions*);
+ const WorkletOptions*,
+ ExceptionState&);
// ContextLifecycleObserver
void ContextDestroyed(ExecutionContext*) override;
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.idl b/chromium/third_party/blink/renderer/core/workers/worklet.idl
index 018d604f8ac..91fe709474d 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.idl
@@ -7,5 +7,5 @@
[
SecureContext
] interface Worklet {
- [CallWith=ScriptState] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options);
+ [CallWith=ScriptState, RaisesException] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options);
};
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
index 5e09dc109b8..8076e3c4162 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.cc
@@ -228,13 +228,11 @@ void WorkletGlobalScope::FetchAndInvokeScript(
// moduleURLRecord, moduleResponsesMap, credentialOptions, outsideSettings,
// and insideSettings when it asynchronously completes."
- Modulator* modulator = Modulator::From(ScriptController()->GetScriptState());
-
// Step 3 to 5 are implemented in
// WorkletModuleTreeClient::NotifyModuleTreeLoadFinished.
- WorkletModuleTreeClient* client =
- MakeGarbageCollected<WorkletModuleTreeClient>(
- modulator, std::move(outside_settings_task_runner), pending_tasks);
+ auto* client = MakeGarbageCollected<WorkletModuleTreeClient>(
+ ScriptController()->GetScriptState(),
+ std::move(outside_settings_task_runner), pending_tasks);
// TODO(nhiroki): Pass an appropriate destination defined in each worklet
// spec (e.g., "paint worklet", "audio worklet") (https://crbug.com/843980,
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 2e95cd12bf4..12f66911dc9 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
@@ -32,8 +32,8 @@ namespace blink {
// across worklet threads. All access to this class should be mutex-guarded,
// and any data passed in or read out is copied to ensure that this object's
// internal state can be safely destructed from the main thread.
-class CORE_EXPORT WorkletModuleResponsesMap
- : public GarbageCollectedFinalized<WorkletModuleResponsesMap> {
+class CORE_EXPORT WorkletModuleResponsesMap final
+ : public GarbageCollected<WorkletModuleResponsesMap> {
public:
WorkletModuleResponsesMap() = default;
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
index 7cda3b97f80..00c0eaf8334 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/workers/worklet_module_tree_client.h"
#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/core/script/module_script.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
@@ -14,10 +15,10 @@
namespace blink {
WorkletModuleTreeClient::WorkletModuleTreeClient(
- Modulator* modulator,
+ ScriptState* script_state,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks)
- : modulator_(modulator),
+ : script_state_(script_state),
outside_settings_task_runner_(std::move(outside_settings_task_runner)),
pending_tasks_(pending_tasks) {}
@@ -29,45 +30,57 @@ void WorkletModuleTreeClient::NotifyModuleTreeLoadFinished(
// TODO(nhiroki): Call reporting proxy functions appropriately (e.g.,
// DidFailToFetchModuleScript(), WillEvaluateModuleScript()).
+ // "Note: Specifically, if a script fails to parse or fails to load over the
+ // network, it will reject the promise. If the script throws an error while
+ // first evaluating the promise it will resolve as classes may have been
+ // registered correctly."
+ // https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
+ //
+ // When a network failure happens, |module_script| should be nullptr, and the
+ // case will be handled by the step 3.
+ // When a parse failure happens, |module_script| has an error to rethrow, and
+ // the case will be handled by the step 4.
+
+ // Step 3: "If script is null, then queue a task on outsideSettings's
+ // responsible event loop to run these steps:"
if (!module_script) {
- // Step 3: "If script is null, then queue a task on outsideSettings's
- // responsible event loop to run these steps:"
- // The steps are implemented in WorkletPendingTasks::Abort().
+ // Null |error_to_rethrow| will be replaced with AbortError.
PostCrossThreadTask(
*outside_settings_task_runner_, FROM_HERE,
CrossThreadBindOnce(&WorkletPendingTasks::Abort,
- WrapCrossThreadPersistent(pending_tasks_.Get())));
+ WrapCrossThreadPersistent(pending_tasks_.Get()),
+ /*error_to_rethrow=*/nullptr));
return;
}
- // "Note: Specifically, if a script fails to parse or fails to load over the
- // network, it will reject the promise. If the script throws an error while
- // first evaluating the promise it will resolve as classes may have been
- // registered correctly."
- // https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
- //
- // When a network failure happens, |module_script| should be nullptr and the
- // case should already be handled above.
- //
- // Check whether a syntax error happens.
+ // Step 4: "If script's error to rethrow is not null, then queue a task on
+ // outsideSettings's responsible event loop given script's error to rethrow to
+ // run these steps:
if (module_script->HasErrorToRethrow()) {
+ ScriptState::Scope scope(script_state_);
PostCrossThreadTask(
*outside_settings_task_runner_, FROM_HERE,
- CrossThreadBindOnce(&WorkletPendingTasks::Abort,
- WrapCrossThreadPersistent(pending_tasks_.Get())));
+ CrossThreadBindOnce(
+ &WorkletPendingTasks::Abort,
+ WrapCrossThreadPersistent(pending_tasks_.Get()),
+ SerializedScriptValue::SerializeAndSwallowExceptions(
+ script_state_->GetIsolate(),
+ module_script->CreateErrorToRethrow().V8Value())));
return;
}
- // Step 4: "Run a module script given script."
- ScriptValue error = modulator_->ExecuteModule(
- module_script, Modulator::CaptureEvalErrorFlag::kReport);
+ // Step 5: "Run a module script given script."
+ ScriptValue error =
+ Modulator::From(script_state_)
+ ->ExecuteModule(module_script,
+ Modulator::CaptureEvalErrorFlag::kReport);
- WorkletGlobalScope* global_scope = To<WorkletGlobalScope>(
- ExecutionContext::From(modulator_->GetScriptState()));
+ auto* global_scope =
+ To<WorkletGlobalScope>(ExecutionContext::From(script_state_));
global_scope->ReportingProxy().DidEvaluateModuleScript(error.IsEmpty());
- // Step 5: "Queue a task on outsideSettings's responsible event loop to run
+ // Step 6: "Queue a task on outsideSettings's responsible event loop to run
// these steps:"
// The steps are implemented in WorkletPendingTasks::DecrementCounter().
PostCrossThreadTask(
@@ -77,7 +90,7 @@ void WorkletModuleTreeClient::NotifyModuleTreeLoadFinished(
}
void WorkletModuleTreeClient::Trace(blink::Visitor* visitor) {
- visitor->Trace(modulator_);
+ visitor->Trace(script_state_);
ModuleTreeClient::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.h b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.h
index 371e0449c53..deb69727b20 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_tree_client.h
@@ -13,12 +13,13 @@
namespace blink {
class ModuleScript;
+class ScriptState;
// A ModuleTreeClient that lives on the worklet context's thread.
class WorkletModuleTreeClient final : public ModuleTreeClient {
public:
WorkletModuleTreeClient(
- Modulator*,
+ ScriptState*,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*);
@@ -28,7 +29,7 @@ class WorkletModuleTreeClient final : public ModuleTreeClient {
void Trace(blink::Visitor*) override;
private:
- Member<Modulator> modulator_;
+ Member<ScriptState> script_state_;
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner_;
CrossThreadPersistent<WorkletPendingTasks> pending_tasks_;
};
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
index 6bf787cce1f..2b967c9669e 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/workers/worklet_pending_tasks.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/workers/worklet.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -22,18 +23,35 @@ void WorkletPendingTasks::InitializeCounter(int counter) {
counter_ = counter;
}
-void WorkletPendingTasks::Abort() {
+void WorkletPendingTasks::Abort(
+ scoped_refptr<SerializedScriptValue> error_to_rethrow) {
DCHECK(IsMainThread());
+ // This function can be called from the following steps. See
+ // WorkletModuleTreeClient::NotifyModuleTreeLoadFinished().
+ //
// Step 3: "If script is null, then queue a task on outsideSettings's
// responsible event loop to run these steps:"
// 1: "If pendingTaskStruct's counter is not -1, then run these steps:"
// 1: "Set pendingTaskStruct's counter to -1."
// 2: "Reject promise with an "AbortError" DOMException."
+ //
+ // Step 4: "If script's error to rethrow is not null, then queue a task on
+ // outsideSettings's responsible event loop given script's error to rethrow to
+ // run these steps:
+ // 1: "If pendingTaskStruct's counter is not -1, then run these steps:"
+ // 1: "Set pendingTaskStruct's counter to -1."
+ // 2: "Reject promise with error to rethrow."
if (counter_ != -1) {
counter_ = -1;
worklet_->FinishPendingTasks(this);
- resolver_->Reject(
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
+ if (error_to_rethrow) {
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ resolver_->Reject(error_to_rethrow->Deserialize(
+ resolver_->GetScriptState()->GetIsolate()));
+ } else {
+ resolver_->Reject(
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.h b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.h
index c511d1437a2..8fcfa797ef8 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.h
@@ -11,6 +11,7 @@
namespace blink {
+class SerializedScriptValue;
class Worklet;
// Implementation of the "pending tasks struct":
@@ -31,7 +32,7 @@ class CORE_EXPORT WorkletPendingTasks final
void InitializeCounter(int counter);
// Sets |counter_| to -1 and rejects the promise.
- void Abort();
+ void Abort(scoped_refptr<SerializedScriptValue> error_to_rethrow);
// Decrements |counter_| and resolves the promise if the counter becomes 0.
void DecrementCounter();
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 3f3f6ea0649..2a6e70e49f0 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
@@ -53,7 +53,7 @@ struct CORE_EXPORT EvaluationContext {
bool had_type_conversion_error;
};
-class CORE_EXPORT ParseNode : public GarbageCollectedFinalized<ParseNode> {
+class CORE_EXPORT ParseNode : public GarbageCollected<ParseNode> {
public:
virtual ~ParseNode() = default;
virtual void Trace(blink::Visitor* visitor) {}
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 7082de8e115..5883c899481 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_step.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_step.h
@@ -57,7 +57,7 @@ class Step final : public ParseNode {
kSelfAxis
};
- class NodeTest : public GarbageCollectedFinalized<NodeTest> {
+ class NodeTest final : public GarbageCollected<NodeTest> {
public:
enum Kind {
kTextNodeTest,
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_value.h b/chromium/third_party/blink/renderer/core/xml/xpath_value.h
index 3a3e523b775..a416d3ca875 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_value.h
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_value.h
@@ -37,7 +37,7 @@ namespace xpath {
struct EvaluationContext;
-class ValueData : public GarbageCollectedFinalized<ValueData> {
+class ValueData final : public GarbageCollected<ValueData> {
public:
ValueData() : node_set_(NodeSet::Create()) {}
explicit ValueData(const NodeSet& node_set)
diff --git a/chromium/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc b/chromium/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
index f92ccdd36d2..40f5bb28189 100644
--- a/chromium/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xsl_style_sheet_libxslt.cc
@@ -23,6 +23,7 @@
#include <libxml/uri.h>
#include <libxslt/xsltutils.h>
+#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/transform_source.h"
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 2463ca0f268..dbaee701aa8 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
@@ -31,6 +31,7 @@
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_document_or_string_or_form_data_or_url_search_params.h"
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h"
@@ -231,7 +232,7 @@ bool ValidateOpenArguments(const AtomicString& method,
} // namespace
class XMLHttpRequest::BlobLoader final
- : public GarbageCollectedFinalized<XMLHttpRequest::BlobLoader>,
+ : public GarbageCollected<XMLHttpRequest::BlobLoader>,
public FileReaderLoaderClient {
public:
BlobLoader(XMLHttpRequest* xhr, scoped_refptr<BlobDataHandle> handle)
@@ -304,18 +305,6 @@ Document* XMLHttpRequest::GetDocument() const {
return To<Document>(GetExecutionContext());
}
-const SecurityOrigin* XMLHttpRequest::GetSecurityOrigin() const {
- return isolated_world_security_origin_
- ? isolated_world_security_origin_.get()
- : GetExecutionContext()->GetSecurityOrigin();
-}
-
-SecurityOrigin* XMLHttpRequest::GetMutableSecurityOrigin() {
- return isolated_world_security_origin_
- ? isolated_world_security_origin_.get()
- : GetExecutionContext()->GetMutableSecurityOrigin();
-}
-
XMLHttpRequest::State XMLHttpRequest::readyState() const {
return state_;
}
@@ -708,7 +697,7 @@ void XMLHttpRequest::open(const AtomicString& method,
if (url_.ProtocolIs("blob")) {
GetExecutionContext()->GetPublicURLManager().Resolve(
- url_, MakeRequest(&blob_url_loader_factory_));
+ url_, blob_url_loader_factory_.InitWithNewPipeAndPassReceiver());
}
async_ = async;
@@ -1047,12 +1036,15 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
// We also remember whether upload events should be allowed for this request
// in case the upload listeners are added after the request is started.
upload_events_allowed_ =
- GetSecurityOrigin()->CanRequest(url_) || upload_events ||
- !cors::IsCorsSafelistedMethod(method_) ||
+ GetExecutionContext()->GetSecurityOrigin()->CanRequest(url_) ||
+ (isolated_world_security_origin_ &&
+ isolated_world_security_origin_->CanRequest(url_)) ||
+ upload_events || !cors::IsCorsSafelistedMethod(method_) ||
!cors::ContainsOnlyCorsSafelistedHeaders(request_headers_);
ResourceRequest request(url_);
- request.SetRequestorOrigin(GetSecurityOrigin());
+ request.SetRequestorOrigin(GetExecutionContext()->GetSecurityOrigin());
+ request.SetIsolatedWorldOrigin(isolated_world_security_origin_);
request.SetHttpMethod(method_);
request.SetRequestContext(mojom::RequestContextType::XML_HTTP_REQUEST);
request.SetMode(upload_events
@@ -1064,7 +1056,6 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
request.SetSkipServiceWorker(is_isolated_world_);
request.SetExternalRequestStateFromRequestorAddressSpace(
execution_context.GetSecurityContext().AddressSpace());
- request.SetShouldAlsoUseFactoryBoundOriginForCors(is_isolated_world_);
probe::WillLoadXHR(&execution_context, method_, url_, async_, http_body.get(),
request_headers_, with_credentials_);
@@ -1082,9 +1073,10 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
resource_loader_options.initiator_info.name =
fetch_initiator_type_names::kXmlhttprequest;
if (blob_url_loader_factory_) {
- resource_loader_options.url_loader_factory = base::MakeRefCounted<
- base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>(
- std::move(blob_url_loader_factory_));
+ resource_loader_options.url_loader_factory =
+ base::MakeRefCounted<base::RefCountedData<
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>>>(
+ std::move(blob_url_loader_factory_));
}
// When responseType is set to "blob", we redirect the downloaded data to a
@@ -1155,7 +1147,9 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
forbidden_syncxhr_pagedismissal_histogram.Count(pagedismissal);
HandleNetworkError();
ThrowForLoadFailureIfNeeded(exception_state,
- "Synchronous XHR in page dismissal.");
+ "Synchronous XHR in page dismissal. See "
+ "https://www.chromestatus.com/feature/"
+ "4664843055398912 for more details.");
return;
} else {
UseCounter::Count(&execution_context,
@@ -1491,8 +1485,9 @@ String XMLHttpRequest::getAllResponseHeaders() const {
// TODO: Consider removing canLoadLocalResources() call.
// crbug.com/567527
if (FetchUtils::IsForbiddenResponseHeaderName(it->key) &&
- !GetSecurityOrigin()->CanLoadLocalResources())
+ !GetExecutionContext()->GetSecurityOrigin()->CanLoadLocalResources()) {
continue;
+ }
if (response_.GetType() == network::mojom::FetchResponseType::kCors &&
!cors::IsCorsSafelistedResponseHeader(it->key) &&
@@ -1527,7 +1522,7 @@ const AtomicString& XMLHttpRequest::getResponseHeader(
// See comment in getAllResponseHeaders above.
if (FetchUtils::IsForbiddenResponseHeaderName(name) &&
- !GetSecurityOrigin()->CanLoadLocalResources()) {
+ !GetExecutionContext()->GetSecurityOrigin()->CanLoadLocalResources()) {
LogConsoleError(GetExecutionContext(),
"Refused to get unsafe header \"" + name + "\"");
return g_null_atom;
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 5a9ea79bcee..3208c78a41a 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
@@ -26,6 +26,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/document_parser_client.h"
@@ -175,12 +176,6 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
Document* GetDocument() const;
- // Returns the SecurityOrigin of the isolated world if the XMLHttpRequest was
- // created in an isolated world. Otherwise, returns the SecurityOrigin of the
- // execution context.
- const SecurityOrigin* GetSecurityOrigin() const;
- SecurityOrigin* GetMutableSecurityOrigin();
-
void DidSendData(uint64_t bytes_sent,
uint64_t total_bytes_to_be_sent) override;
void DidReceiveResponse(uint64_t identifier,
@@ -300,7 +295,8 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
Member<XMLHttpRequestUpload> upload_;
KURL url_;
- network::mojom::blink::URLLoaderFactoryPtr blob_url_loader_factory_;
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>
+ blob_url_loader_factory_;
AtomicString method_;
HTTPHeaderMap request_headers_;
// Not converted to ASCII lowercase. Must be lowered later or compared
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
index fdc728e9dfc..906a2463029 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h
@@ -50,7 +50,7 @@ class XMLHttpRequest;
// - ProgressEvent means an event using the ProgressEvent interface defined in
// the spec.
class XMLHttpRequestProgressEventThrottle final
- : public GarbageCollectedFinalized<XMLHttpRequestProgressEventThrottle>,
+ : public GarbageCollected<XMLHttpRequestProgressEventThrottle>,
public TimerBase {
// Need to promptly stop this timer when it is deemed finalizable.
USING_PRE_FINALIZER(XMLHttpRequestProgressEventThrottle, Stop);
diff --git a/chromium/third_party/blink/renderer/devtools/.eslintignore b/chromium/third_party/blink/renderer/devtools/.eslintignore
index bc46ff03a58..9e04d37dc16 100644
--- a/chromium/third_party/blink/renderer/devtools/.eslintignore
+++ b/chromium/third_party/blink/renderer/devtools/.eslintignore
@@ -1,6 +1,9 @@
// Do not use glob pattern, this file is used by PRESUBMIT.py
// to ignore these same files/folders for clang-format
front_end/.eslintrc.js
+front_end/InspectorBackendCommands.js
+front_end/SupportedCSSProperties.js
+front_end/accessibility/ARIAProperties.js
front_end/audits_worker/lighthouse/
front_end/audits/lighthouse/
front_end/cm/
@@ -9,7 +12,6 @@ front_end/cm_modes/
front_end/cm_web_modes/
front_end/diff/diff_match_patch.js
front_end/formatter_worker/acorn/
-front_end/terminal/xterm.js/
front_end/protocol_externs.js
front_end/javascript_metadata/NativeFunctions.js
-scripts/
+scripts/ \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/.eslintrc.js b/chromium/third_party/blink/renderer/devtools/.eslintrc.js
index 10cc7cb5d68..3dc9c0161af 100644
--- a/chromium/third_party/blink/renderer/devtools/.eslintrc.js
+++ b/chromium/third_party/blink/renderer/devtools/.eslintrc.js
@@ -1,16 +1,11 @@
module.exports = {
- "root": true,
+ 'root': true,
- "env": {
- "browser": true,
- "es6": true
- },
+ 'env': {'browser': true, 'es6': true},
- "parserOptions": {
- "ecmaVersion": 9
- },
+ 'parserOptions': {'ecmaVersion': 9, 'sourceType': 'module'},
- /**
+ /**
* ESLint rules
*
* All available rules: http://eslint.org/docs/rules/
@@ -19,112 +14,95 @@ module.exports = {
* "rule-name", [severity, { opts }]
* Severity: 2 == error, 1 == warning, 0 == off.
*/
- "rules": {
- /**
+ 'rules': {
+ /**
* Enforced rules
*/
- // syntax preferences
- "quotes": [2, "single", {
- "avoidEscape": true,
- "allowTemplateLiterals": true
- }],
- "semi": 2,
- "no-extra-semi": 2,
- "comma-style": [2, "last"],
- "wrap-iife": [2, "inside"],
- "spaced-comment": [2, "always", {
- "markers": ["*"]
- }],
- "eqeqeq": [2],
- "accessor-pairs": [2, {
- "getWithoutSet": false,
- "setWithoutGet": false
- }],
- "curly": [2, "multi-or-nest", "consistent"],
- "new-parens": 2,
- "func-call-spacing": 2,
- "arrow-parens": [2, "as-needed"],
+ // syntax preferences
+ 'quotes': [2, 'single', {'avoidEscape': true, 'allowTemplateLiterals': true}],
+ 'semi': 2,
+ 'no-extra-semi': 2,
+ 'comma-style': [2, 'last'],
+ 'wrap-iife': [2, 'inside'],
+ 'spaced-comment': [2, 'always', {'markers': ['*']}],
+ 'eqeqeq': [2],
+ 'accessor-pairs': [2, {'getWithoutSet': false, 'setWithoutGet': false}],
+ 'curly': 2,
+ 'new-parens': 2,
+ 'func-call-spacing': 2,
+ 'arrow-parens': [2, 'as-needed'],
- // anti-patterns
- "no-with": 2,
- "no-multi-str": 2,
- "no-caller": 2,
- "no-implied-eval": 2,
- "no-labels": 2,
- "no-new-object": 2,
- "no-octal-escape": 2,
- "no-self-compare": 2,
- "no-shadow-restricted-names": 2,
- "no-cond-assign": 2,
- "no-debugger": 2,
- "no-console": [2, { "allow": ["assert", "context", "error", "timeStamp", "time", "timeEnd", "warn"] }],
- "no-dupe-keys": 2,
- "no-duplicate-case": 2,
- "no-empty-character-class": 2,
- "no-unreachable": 2,
- "no-unsafe-negation": 2,
- "radix": 2,
- "valid-typeof": 2,
- "no-var": 2,
- "prefer-const": 2,
- "no-unused-vars": [2, { "args": "none", "vars": "local" }],
+ // anti-patterns
+ 'no-with': 2,
+ 'no-multi-str': 2,
+ 'no-caller': 2,
+ 'no-implied-eval': 2,
+ 'no-labels': 2,
+ 'no-new-object': 2,
+ 'no-octal-escape': 2,
+ 'no-self-compare': 2,
+ 'no-shadow-restricted-names': 2,
+ 'no-cond-assign': 2,
+ 'no-debugger': 2,
+ 'no-console': [2, {'allow': ['assert', 'context', 'error', 'timeStamp', 'time', 'timeEnd', 'warn']}],
+ 'no-dupe-keys': 2,
+ 'no-duplicate-case': 2,
+ 'no-empty-character-class': 2,
+ 'no-unreachable': 2,
+ 'no-unsafe-negation': 2,
+ 'radix': 2,
+ 'valid-typeof': 2,
+ 'no-var': 2,
+ 'prefer-const': 2,
+ 'no-unused-vars': [2, {'args': 'none', 'vars': 'local'}],
- // es2015 features
- "require-yield": 2,
- "template-curly-spacing": [2, "never"],
+ // es2015 features
+ 'require-yield': 2,
+ 'template-curly-spacing': [2, 'never'],
- // spacing details
- "space-infix-ops": 2,
- "space-in-parens": [2, "never"],
- "space-before-function-paren": [2, {
- "anonymous": "never",
- "named": "never",
- "asyncArrow": "always"
- }],
- "no-whitespace-before-property": 2,
- "keyword-spacing": [2, {
- "overrides": {
- "if": {"after": true},
- "else": {"after": true},
- "for": {"after": true},
- "while": {"after": true},
- "do": {"after": true},
- "switch": {"after": true},
- "return": {"after": true}
- }
- }],
- "arrow-spacing": [2, {
- "after": true,
- "before": true
- }],
+ // spacing details
+ 'space-infix-ops': 2,
+ 'space-in-parens': [2, 'never'],
+ 'space-before-function-paren': [2, {'anonymous': 'never', 'named': 'never', 'asyncArrow': 'always'}],
+ 'no-whitespace-before-property': 2,
+ 'keyword-spacing': [
+ 2, {
+ 'overrides': {
+ 'if': {'after': true},
+ 'else': {'after': true},
+ 'for': {'after': true},
+ 'while': {'after': true},
+ 'do': {'after': true},
+ 'switch': {'after': true},
+ 'return': {'after': true}
+ }
+ }
+ ],
+ 'arrow-spacing': [2, {'after': true, 'before': true}],
- // file whitespace
- "no-multiple-empty-lines": [2, {"max": 2}],
- "no-mixed-spaces-and-tabs": 2,
- "no-trailing-spaces": 2,
- "linebreak-style": [ 2, "unix" ],
+ // file whitespace
+ 'no-multiple-empty-lines': [2, {'max': 2}],
+ 'no-mixed-spaces-and-tabs': 2,
+ 'no-trailing-spaces': 2,
+ 'linebreak-style': [2, 'unix'],
- /**
+ /**
* Disabled, aspirational rules
*/
- "indent": [0, 2, { "SwitchCase": 1, "CallExpression": {"arguments": 2}, "MemberExpression": 2 }],
+ 'indent': [0, 2, {'SwitchCase': 1, 'CallExpression': {'arguments': 2}, 'MemberExpression': 2}],
- // brace-style is disabled, as eslint cannot enforce 1tbs as default, but allman for functions
- "brace-style": [0, "allman", { "allowSingleLine": true }],
+ // brace-style is disabled, as eslint cannot enforce 1tbs as default, but allman for functions
+ 'brace-style': [0, 'allman', {'allowSingleLine': true}],
- // key-spacing is disabled, as some objects use value-aligned spacing, some not.
- "key-spacing": [0, {
- "beforeColon": false,
- "afterColon": true,
- "align": "value"
- }],
- // quote-props is diabled, as property quoting styles are too varied to enforce.
- "quote-props": [0, "as-needed"],
+ // key-spacing is disabled, as some objects use value-aligned spacing, some not.
+ 'key-spacing': [0, {'beforeColon': false, 'afterColon': true, 'align': 'value'}],
+ // quote-props is diabled, as property quoting styles are too varied to enforce.
+ 'quote-props': [0, 'as-needed'],
- // no-implicit-globals will prevent accidental globals
- "no-implicit-globals": [0]
- }
+ // no-implicit-globals will prevent accidental globals
+ 'no-implicit-globals': [0]
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/BUILD.gn b/chromium/third_party/blink/renderer/devtools/BUILD.gn
index b4108caa9df..0127da1e2e1 100644
--- a/chromium/third_party/blink/renderer/devtools/BUILD.gn
+++ b/chromium/third_party/blink/renderer/devtools/BUILD.gn
@@ -6,1492 +6,1844 @@ import("//build/config/features.gni")
import("//third_party/blink/public/public_features.gni")
import("//third_party/blink/renderer/core/core.gni")
-all_devtools_files = [
- "front_end/accessibility/AccessibilityModel.js",
- "front_end/accessibility/accessibilityNode.css",
- "front_end/accessibility/AccessibilityNodeView.js",
- "front_end/accessibility/accessibilityProperties.css",
- "front_end/accessibility/AccessibilitySidebarView.js",
- "front_end/accessibility/AccessibilityStrings.js",
- "front_end/accessibility/ARIAAttributesView.js",
- "front_end/accessibility/ARIAMetadata.js",
- "front_end/accessibility/axBreadcrumbs.css",
- "front_end/accessibility/AXBreadcrumbsPane.js",
- "front_end/accessibility/module.json",
- "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js",
- "front_end/accessibility_test_runner/module.json",
- "front_end/animation/AnimationGroupPreviewUI.js",
- "front_end/animation/AnimationModel.js",
- "front_end/animation/animationScreenshotPopover.css",
- "front_end/animation/AnimationScreenshotPopover.js",
- "front_end/animation/animationTimeline.css",
- "front_end/animation/AnimationTimeline.js",
- "front_end/animation/AnimationUI.js",
- "front_end/animation/module.json",
- "front_end/application_test_runner/AppcacheTestRunner.js",
- "front_end/application_test_runner/CacheStorageTestRunner.js",
- "front_end/application_test_runner/IndexedDBTestRunner.js",
- "front_end/application_test_runner/module.json",
- "front_end/application_test_runner/ResourcesTestRunner.js",
- "front_end/application_test_runner/ResourceTreeTestRunner.js",
- "front_end/application_test_runner/ServiceWorkersTestRunner.js",
- "front_end/audits_worker.js",
- "front_end/audits_worker.json",
- "front_end/audits_worker/AuditsService.js",
- "front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js",
- "front_end/audits_worker/module.json",
- "front_end/audits/AuditsPanel.js",
- "front_end/audits/AuditsController.js",
- "front_end/audits/AuditsReportSelector.js",
- "front_end/audits/AuditsReportRenderer.js",
- "front_end/audits/AuditsStartView.js",
- "front_end/audits/AuditsProtocolService.js",
- "front_end/audits/AuditsStatusView.js",
- "front_end/audits/auditsDialog.css",
- "front_end/audits/auditsStartView.css",
- "front_end/audits/auditsPanel.css",
- "front_end/audits/RadioSetting.js",
- "front_end/audits/lighthouse/report.css",
- "front_end/audits/lighthouse/report.js",
- "front_end/audits/lighthouse/report-generator.js",
- "front_end/audits/lighthouse/template.html",
- "front_end/audits/lighthouse/templates.html",
- "front_end/audits/module.json",
- "front_end/audits_test_runner/AuditsTestRunner.js",
- "front_end/audits_test_runner/module.json",
- "front_end/axe_core_test_runner/AxeCoreTestRunner.js",
- "front_end/axe_core_test_runner/module.json",
- "front_end/bindings/BlackboxManager.js",
- "front_end/bindings/BreakpointManager.js",
- "front_end/bindings/CompilerScriptMapping.js",
- "front_end/bindings/ContentProviderBasedProject.js",
- "front_end/bindings/CSSWorkspaceBinding.js",
- "front_end/bindings/DebuggerWorkspaceBinding.js",
- "front_end/bindings/DefaultScriptMapping.js",
- "front_end/bindings/FileUtils.js",
- "front_end/bindings/LiveLocation.js",
- "front_end/bindings/module.json",
- "front_end/bindings/NetworkProject.js",
- "front_end/bindings/PresentationConsoleMessageHelper.js",
- "front_end/bindings/ResourceMapping.js",
- "front_end/bindings/ResourceScriptMapping.js",
- "front_end/bindings/ResourceUtils.js",
- "front_end/bindings/SASSSourceMapping.js",
- "front_end/bindings/StylesSourceMapping.js",
- "front_end/bindings/TempFile.js",
- "front_end/bindings_test_runner/AutomappingTestRunner.js",
- "front_end/bindings_test_runner/BindingsTestRunner.js",
- "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js",
- "front_end/bindings_test_runner/module.json",
- "front_end/bindings_test_runner/PersistenceTestRunner.js",
- "front_end/bindings_test_runner/OverridesTestRunner.js",
- "front_end/browser_debugger/DOMBreakpointsSidebarPane.js",
- "front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js",
- "front_end/browser_debugger/ObjectEventListenersSidebarPane.js",
- "front_end/browser_debugger/XHRBreakpointsSidebarPane.js",
- "front_end/browser_debugger/domBreakpointsSidebarPane.css",
- "front_end/browser_debugger/eventListenerBreakpoints.css",
- "front_end/browser_debugger/module.json",
- "front_end/browser_debugger/xhrBreakpointsSidebarPane.css",
- "front_end/browser_sdk/LogManager.js",
- "front_end/browser_sdk/module.json",
- "front_end/changes/ChangesHighlighter.js",
- "front_end/changes/changesView.css",
- "front_end/changes/ChangesView.js",
- "front_end/changes/changesSidebar.css",
- "front_end/changes/ChangesSidebar.js",
- "front_end/changes/module.json",
- "front_end/cm/active-line.js",
- "front_end/cm/brace-fold.js",
- "front_end/cm/closebrackets.js",
- "front_end/cm/codemirror.css",
- "front_end/cm/codemirror.js",
- "front_end/cm/comment.js",
- "front_end/cm/foldcode.js",
- "front_end/cm/foldgutter.js",
- "front_end/cm/mark-selection.js",
- "front_end/cm/matchbrackets.js",
- "front_end/cm/module.json",
- "front_end/cm/multiplex.js",
- "front_end/cm/overlay.js",
- "front_end/cm_headless/headlesscodemirror.js",
- "front_end/cm_headless/module.json",
- "front_end/cm_modes/clike.js",
- "front_end/cm_modes/clojure.js",
- "front_end/cm_modes/coffeescript.js",
- "front_end/cm_modes/DefaultCodeMirrorMimeMode.js",
- "front_end/cm_modes/jsx.js",
- "front_end/cm_modes/livescript.js",
- "front_end/cm_modes/markdown.js",
- "front_end/cm_modes/module.json",
- "front_end/cm_modes/php.js",
- "front_end/cm_modes/python.js",
- "front_end/cm_modes/shell.js",
- "front_end/cm_modes/stylus.js",
- "front_end/cm_web_modes/css.js",
- "front_end/cm_web_modes/htmlembedded.js",
- "front_end/cm_web_modes/htmlmixed.js",
- "front_end/cm_web_modes/javascript.js",
- "front_end/cm_web_modes/xml.js",
- "front_end/color_picker/ContrastDetails.js",
- "front_end/color_picker/ContrastInfo.js",
- "front_end/color_picker/ContrastOverlay.js",
- "front_end/color_picker/module.json",
- "front_end/color_picker/spectrum.css",
- "front_end/color_picker/Spectrum.js",
- "front_end/common/CharacterIdMap.js",
- "front_end/common/Color.js",
- "front_end/common/Console.js",
- "front_end/common/ContentProvider.js",
- "front_end/common/module.json",
- "front_end/common/ModuleExtensionInterfaces.js",
- "front_end/common/Object.js",
- "front_end/common/OutputStream.js",
- "front_end/common/ParsedURL.js",
- "front_end/common/Progress.js",
- "front_end/common/ResourceType.js",
- "front_end/common/SegmentedRange.js",
- "front_end/common/Settings.js",
- "front_end/common/StaticContentProvider.js",
- "front_end/common/TextDictionary.js",
- "front_end/common/Throttler.js",
- "front_end/common/Trie.js",
- "front_end/common/UIString.js",
- "front_end/common/Worker.js",
- "front_end/components/DockController.js",
- "front_end/components/ImagePreview.js",
- "front_end/components/imagePreview.css",
- "front_end/components/JSPresentationUtils.js",
- "front_end/components/Linkifier.js",
- "front_end/components/TargetDetachedDialog.js",
- "front_end/components/Reload.js",
- "front_end/components/jsUtils.css",
- "front_end/components/module.json",
- "front_end/console/ConsoleContextSelector.js",
- "front_end/console/ConsoleFilter.js",
- "front_end/console/ConsoleSidebar.js",
- "front_end/console/ConsolePanel.js",
- "front_end/console/ConsolePinPane.js",
- "front_end/console/ConsolePrompt.js",
- "front_end/console/consoleView.css",
- "front_end/console/consoleContextSelector.css",
- "front_end/console/consolePinPane.css",
- "front_end/console/consolePrompt.css",
- "front_end/console/consoleSidebar.css",
- "front_end/console/ConsoleView.js",
- "front_end/console/ConsoleViewMessage.js",
- "front_end/console/ConsoleViewport.js",
- "front_end/console/module.json",
- "front_end/console_counters/errorWarningCounter.css",
- "front_end/console_counters/module.json",
- "front_end/console_counters/WarningErrorCounter.js",
- "front_end/console_test_runner/ConsoleTestRunner.js",
- "front_end/console_test_runner/module.json",
- "front_end/cookie_table/CookiesTable.js",
- "front_end/cookie_table/module.json",
- "front_end/coverage/coverageListView.css",
- "front_end/coverage/CoverageDecorationManager.js",
- "front_end/coverage/CoverageListView.js",
- "front_end/coverage/CoverageModel.js",
- "front_end/coverage/coverageView.css",
- "front_end/coverage/CoverageView.js",
- "front_end/coverage/module.json",
- "front_end/coverage_test_runner/CoverageTestRunner.js",
- "front_end/coverage_test_runner/module.json",
- "front_end/cpu_profiler_test_runner/module.json",
- "front_end/cpu_profiler_test_runner/ProfilerTestRunner.js",
- "front_end/data_grid/dataGrid.css",
- "front_end/data_grid/DataGrid.js",
- "front_end/data_grid/module.json",
- "front_end/data_grid/ShowMoreDataGridNode.js",
- "front_end/data_grid/SortableDataGrid.js",
- "front_end/data_grid/ViewportDataGrid.js",
- "front_end/data_grid_test_runner/DataGridTestRunner.js",
- "front_end/data_grid_test_runner/module.json",
- "front_end/device_mode_test_runner/DeviceModeTestRunner.js",
- "front_end/device_mode_test_runner/module.json",
- "front_end/devices/DevicesView.js",
- "front_end/devices/devicesView.css",
- "front_end/devices/module.json",
- "front_end/diff/diff_match_patch.js",
- "front_end/diff/Diff.js",
- "front_end/diff/module.json",
- "front_end/dom_extension/DOMExtension.js",
- "front_end/dom_extension/module.json",
- "front_end/elements/breadcrumbs.css",
- "front_end/elements/classesPaneWidget.css",
- "front_end/elements/ClassesPaneWidget.js",
- "front_end/elements/ColorSwatchPopoverIcon.js",
- "front_end/elements/ComputedStyleModel.js",
- "front_end/elements/computedStyleSidebarPane.css",
- "front_end/elements/computedStyleWidgetTree.css",
- "front_end/elements/ComputedStyleWidget.js",
- "front_end/elements/DOMLinkifier.js",
- "front_end/elements/domLinkifier.css",
- "front_end/elements/DOMPath.js",
- "front_end/elements/ElementsBreadcrumbs.js",
- "front_end/elements/elementsPanel.css",
- "front_end/elements/ElementsPanel.js",
- "front_end/elements/ElementsSidebarPane.js",
- "front_end/elements/elementStatePaneWidget.css",
- "front_end/elements/ElementStatePaneWidget.js",
- "front_end/elements/ElementsTreeElement.js",
- "front_end/elements/ElementsTreeElementHighlighter.js",
- "front_end/elements/elementsTreeOutline.css",
- "front_end/elements/ElementsTreeOutline.js",
- "front_end/elements/EventListenersWidget.js",
- "front_end/elements/InspectElementModeController.js",
- "front_end/elements/MarkerDecorator.js",
- "front_end/elements/metricsSidebarPane.css",
- "front_end/elements/MetricsSidebarPane.js",
- "front_end/elements/nodeStackTraceWidget.css",
- "front_end/elements/NodeStackTraceWidget.js",
- "front_end/elements/module.json",
- "front_end/elements/platformFontsWidget.css",
- "front_end/elements/PlatformFontsWidget.js",
- "front_end/elements/propertiesWidget.css",
- "front_end/elements/PropertiesWidget.js",
- "front_end/elements/StylePropertyHighlighter.js",
- "front_end/elements/stylesSectionTree.css",
- "front_end/elements/stylesSidebarPane.css",
- "front_end/elements/StylesSidebarPane.js",
- "front_end/elements/StylePropertyTreeElement.js",
- "front_end/elements_test_runner/EditDOMTestRunner.js",
- "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js",
- "front_end/elements_test_runner/ElementsTestRunner.js",
- "front_end/elements_test_runner/module.json",
- "front_end/elements_test_runner/SetOuterHTMLTestRunner.js",
- "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js",
- "front_end/emulated_devices/module.json",
- "front_end/emulation/AdvancedApp.js",
- "front_end/emulation/DeviceModeModel.js",
- "front_end/emulation/deviceModeToolbar.css",
- "front_end/emulation/DeviceModeToolbar.js",
- "front_end/emulation/deviceModeView.css",
- "front_end/emulation/DeviceModeView.js",
- "front_end/emulation/DeviceModeWrapper.js",
- "front_end/emulation/devicesSettingsTab.css",
- "front_end/emulation/DevicesSettingsTab.js",
- "front_end/emulation/EmulatedDevices.js",
- "front_end/emulation/geolocationsSettingsTab.css",
- "front_end/emulation/GeolocationsSettingsTab.js",
- "front_end/emulation/inspectedPagePlaceholder.css",
- "front_end/emulation/InspectedPagePlaceholder.js",
- "front_end/emulation/mediaQueryInspector.css",
- "front_end/emulation/MediaQueryInspector.js",
- "front_end/emulation/module.json",
- "front_end/emulation/sensors.css",
- "front_end/emulation/SensorsView.js",
- "front_end/event_listeners/EventListenersUtils.js",
- "front_end/event_listeners/eventListenersView.css",
- "front_end/event_listeners/EventListenersView.js",
- "front_end/event_listeners/module.json",
- "front_end/extensions/ExtensionAPI.js",
- "front_end/extensions/ExtensionPanel.js",
- "front_end/extensions/ExtensionServer.js",
- "front_end/extensions/ExtensionTraceProvider.js",
- "front_end/extensions/ExtensionView.js",
- "front_end/extensions/module.json",
- "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js",
- "front_end/extensions_test_runner/ExtensionsTestRunner.js",
- "front_end/extensions_test_runner/module.json",
- "front_end/formatter/FormatterWorkerPool.js",
- "front_end/formatter/module.json",
- "front_end/formatter/ScriptFormatter.js",
- "front_end/formatter_worker.js",
- "front_end/formatter_worker.json",
- "front_end/formatter_worker/AcornTokenizer.js",
- "front_end/formatter_worker/CSSFormatter.js",
- "front_end/formatter_worker/CSSRuleParser.js",
- "front_end/formatter_worker/ESTreeWalker.js",
- "front_end/formatter_worker/FormattedContentBuilder.js",
- "front_end/formatter_worker/FormatterWorker.js",
- "front_end/formatter_worker/HTMLFormatter.js",
- "front_end/formatter_worker/IdentityFormatter.js",
- "front_end/formatter_worker/JavaScriptFormatter.js",
- "front_end/formatter_worker/JavaScriptOutline.js",
- "front_end/formatter_worker/RelaxedJSONParser.js",
- "front_end/formatter_worker/acorn/acorn.js",
- "front_end/formatter_worker/acorn/acorn_loose.js",
- "front_end/formatter_worker/module.json",
- "front_end/har_importer/HARFormat.js",
- "front_end/har_importer/HARImporter.js",
- "front_end/har_importer/module.json",
- "front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js",
- "front_end/heap_profiler_test_runner/module.json",
- "front_end/heap_snapshot_model/HeapSnapshotModel.js",
- "front_end/heap_snapshot_model/module.json",
- "front_end/heap_snapshot_worker.js",
- "front_end/heap_snapshot_worker.json",
- "front_end/heap_snapshot_worker/AllocationProfile.js",
- "front_end/heap_snapshot_worker/HeapSnapshot.js",
- "front_end/heap_snapshot_worker/HeapSnapshotLoader.js",
- "front_end/heap_snapshot_worker/HeapSnapshotWorker.js",
- "front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js",
- "front_end/heap_snapshot_worker/module.json",
- "front_end/help/Help.js",
- "front_end/help/module.json",
- "front_end/help/releaseNote.css",
- "front_end/help/ReleaseNoteText.js",
- "front_end/help/ReleaseNoteView.js",
- "front_end/host/InspectorFrontendHost.js",
- "front_end/host/InspectorFrontendHostAPI.js",
- "front_end/host/module.json",
- "front_end/host/Platform.js",
- "front_end/host/ResourceLoader.js",
- "front_end/host/UserMetrics.js",
- "front_end/inline_editor/bezierEditor.css",
- "front_end/inline_editor/BezierEditor.js",
- "front_end/inline_editor/bezierSwatch.css",
- "front_end/inline_editor/BezierUI.js",
- "front_end/inline_editor/colorSwatch.css",
- "front_end/inline_editor/ColorSwatch.js",
- "front_end/inline_editor/cssShadowEditor.css",
- "front_end/inline_editor/CSSShadowEditor.js",
- "front_end/inline_editor/CSSShadowModel.js",
- "front_end/inline_editor/cssShadowSwatch.css",
- "front_end/inline_editor/module.json",
- "front_end/inline_editor/swatchPopover.css",
- "front_end/inline_editor/SwatchPopoverHelper.js",
- "front_end/inspector.js",
- "front_end/inspector.json",
- "front_end/inspector_main/InspectorMain.js",
- "front_end/inspector_main/module.json",
- "front_end/inspector_main/nodeIcon.css",
- "front_end/inspector_main/renderingOptions.css",
- "front_end/inspector_main/RenderingOptions.js",
- "front_end/integration_test_runner.js",
- "front_end/integration_test_runner.json",
- "front_end/javascript_metadata/module.json",
- "front_end/javascript_metadata/NativeFunctions.js",
- "front_end/javascript_metadata/JavaScriptMetadata.js",
- "front_end/js_main/JsMain.js",
- "front_end/js_main/module.json",
- "front_end/js_profiler/module.json",
- "front_end/layer_viewer/layerDetailsView.css",
- "front_end/layer_viewer/LayerDetailsView.js",
- "front_end/layer_viewer/layers3DView.css",
- "front_end/layer_viewer/Layers3DView.js",
- "front_end/layer_viewer/LayerTreeOutline.js",
- "front_end/layer_viewer/LayerViewHost.js",
- "front_end/layer_viewer/module.json",
- "front_end/layer_viewer/paintProfiler.css",
- "front_end/layer_viewer/PaintProfilerView.js",
- "front_end/layer_viewer/TransformController.js",
- "front_end/layers/LayerPaintProfilerView.js",
- "front_end/layers/LayersPanel.js",
- "front_end/layers/LayerTreeModel.js",
- "front_end/layers/module.json",
- "front_end/layers_test_runner/LayersTestRunner.js",
- "front_end/layers_test_runner/module.json",
- "front_end/main/ExecutionContextSelector.js",
- "front_end/main/Main.js",
- "front_end/main/module.json",
- "front_end/main/SimpleApp.js",
- "front_end/protocol_monitor/ProtocolMonitor.js",
- "front_end/protocol_monitor/protocolMonitor.css",
- "front_end/protocol_monitor/module.json",
- "front_end/mobile_throttling/MobileThrottlingSelector.js",
- "front_end/mobile_throttling/module.json",
- "front_end/mobile_throttling/NetworkPanelIndicator.js",
- "front_end/mobile_throttling/NetworkThrottlingSelector.js",
- "front_end/mobile_throttling/ThrottlingManager.js",
- "front_end/mobile_throttling/ThrottlingPresets.js",
- "front_end/mobile_throttling/throttlingSettingsTab.css",
- "front_end/mobile_throttling/ThrottlingSettingsTab.js",
- "front_end/ndb_app.json",
- "front_end/network/binaryResourceView.css",
- "front_end/network/blockedURLsPane.css",
- "front_end/network/BinaryResourceView.js",
- "front_end/network/BlockedURLsPane.js",
- "front_end/network/eventSourceMessagesView.css",
- "front_end/network/EventSourceMessagesView.js",
- "front_end/network/HARWriter.js",
- "front_end/network/module.json",
- "front_end/network/networkConfigView.css",
- "front_end/network/NetworkConfigView.js",
- "front_end/network/NetworkDataGridNode.js",
- "front_end/network/NetworkItemView.js",
- "front_end/network/networkLogView.css",
- "front_end/network/NetworkLogView.js",
- "front_end/network/NetworkLogViewColumns.js",
- "front_end/network/NetworkFrameGrouper.js",
- "front_end/network/networkManageCustomHeadersView.css",
- "front_end/network/NetworkManageCustomHeadersView.js",
- "front_end/network/NetworkOverview.js",
- "front_end/network/networkPanel.css",
- "front_end/network/NetworkPanel.js",
- "front_end/network/NetworkSearchScope.js",
- "front_end/network/NetworkTimeCalculator.js",
- "front_end/network/networkTimingTable.css",
- "front_end/network/networkWaterfallColumn.css",
- "front_end/network/NetworkWaterfallColumn.js",
- "front_end/network/requestCookiesView.css",
- "front_end/network/RequestCookiesView.js",
- "front_end/network/requestHeadersTree.css",
- "front_end/network/requestHeadersView.css",
- "front_end/network/RequestHeadersView.js",
- "front_end/network/requestHTMLView.css",
- "front_end/network/RequestHTMLView.js",
- "front_end/network/RequestPreviewView.js",
- "front_end/network/RequestResponseView.js",
- "front_end/network/RequestTimingView.js",
- "front_end/network/ResourceWebSocketFrameView.js",
- "front_end/network/signedExchangeInfoTree.css",
- "front_end/network/signedExchangeInfoView.css",
- "front_end/network/SignedExchangeInfoView.js",
- "front_end/network/webSocketFrameView.css",
- "front_end/network_test_runner/module.json",
- "front_end/network_test_runner/NetworkTestRunner.js",
- "front_end/network_test_runner/ProductRegistryTestRunner.js",
- "front_end/node_debugger/module.json",
- "front_end/node_main/NodeConnectionsPanel.js",
- "front_end/node_main/nodeConnectionsPanel.css",
- "front_end/node_main/NodeMain.js",
- "front_end/node_main/module.json",
- "front_end/object_ui/customPreviewComponent.css",
- "front_end/object_ui/CustomPreviewComponent.js",
- "front_end/object_ui/JavaScriptAutocomplete.js",
- "front_end/object_ui/JavaScriptREPL.js",
- "front_end/object_ui/module.json",
- "front_end/object_ui/objectPopover.css",
- "front_end/object_ui/ObjectPopoverHelper.js",
- "front_end/object_ui/objectPropertiesSection.css",
- "front_end/object_ui/ObjectPropertiesSection.js",
- "front_end/object_ui/objectValue.css",
- "front_end/object_ui/RemoteObjectPreviewFormatter.js",
- "front_end/perf_ui/ChartViewport.js",
- "front_end/perf_ui/FilmStripView.js",
- "front_end/perf_ui/FlameChart.js",
- "front_end/perf_ui/GCActionDelegate.js",
- "front_end/perf_ui/LineLevelProfile.js",
- "front_end/perf_ui/LiveHeapProfile.js",
- "front_end/perf_ui/NetworkPriorities.js",
- "front_end/perf_ui/OverviewGrid.js",
- "front_end/perf_ui/PieChart.js",
- "front_end/perf_ui/TimelineGrid.js",
- "front_end/perf_ui/TimelineOverviewPane.js",
- "front_end/perf_ui/chartViewport.css",
- "front_end/perf_ui/filmStripView.css",
- "front_end/perf_ui/flameChart.css",
- "front_end/perf_ui/module.json",
- "front_end/perf_ui/overviewGrid.css",
- "front_end/perf_ui/pieChart.css",
- "front_end/perf_ui/timelineGrid.css",
- "front_end/perf_ui/timelineOverviewInfo.css",
- "front_end/performance_monitor/PerformanceMonitor.js",
- "front_end/performance_monitor/performanceMonitor.css",
- "front_end/performance_monitor/module.json",
- "front_end/performance_test_runner/module.json",
- "front_end/performance_test_runner/TimelineDataTestRunner.js",
- "front_end/performance_test_runner/TimelineTestRunner.js",
- "front_end/persistence/Automapping.js",
- "front_end/persistence/editFileSystemView.css",
- "front_end/persistence/EditFileSystemView.js",
- "front_end/persistence/FileSystemWorkspaceBinding.js",
- "front_end/persistence/IsolatedFileSystem.js",
- "front_end/persistence/IsolatedFileSystemManager.js",
- "front_end/persistence/module.json",
- "front_end/persistence/NetworkPersistenceManager.js",
- "front_end/persistence/Persistence.js",
- "front_end/persistence/PersistenceActions.js",
- "front_end/persistence/PersistenceUtils.js",
- "front_end/persistence/PlatformFileSystem.js",
- "front_end/persistence/workspaceSettingsTab.css",
- "front_end/persistence/WorkspaceSettingsTab.js",
- "front_end/platform/module.json",
- "front_end/platform/utilities.js",
- "front_end/product_registry/BadgePool.js",
- "front_end/product_registry/ProductRegistry.js",
- "front_end/product_registry/badge.css",
- "front_end/product_registry/module.json",
- "front_end/product_registry/popup.css",
- "front_end/product_registry_impl/module.json",
- "front_end/product_registry_impl/ProductRegistryImpl.js",
- "front_end/product_registry_impl/ProductRegistryData.js",
- "front_end/product_registry_impl/sha1/sha1.js",
- "front_end/profiler/BottomUpProfileDataGrid.js",
- "front_end/profiler/CPUProfileFlameChart.js",
- "front_end/profiler/CPUProfileView.js",
- "front_end/profiler/heapProfiler.css",
- "front_end/profiler/HeapProfileView.js",
- "front_end/profiler/HeapProfilerPanel.js",
- "front_end/profiler/HeapSnapshotDataGrids.js",
- "front_end/profiler/HeapSnapshotGridNodes.js",
- "front_end/profiler/HeapSnapshotProxy.js",
- "front_end/profiler/HeapSnapshotView.js",
- "front_end/profiler/HeapTimelineOverview.js",
- "front_end/profiler/IsolateSelector.js",
- "front_end/profiler/LiveHeapProfileView.js",
- "front_end/profiler/liveHeapProfile.css",
- "front_end/profiler/module.json",
- "front_end/profiler/ProfileDataGrid.js",
- "front_end/profiler/ProfileHeader.js",
- "front_end/profiler/profileLauncherView.css",
- "front_end/profiler/ProfileLauncherView.js",
- "front_end/profiler/ProfileType.js",
- "front_end/profiler/profilesPanel.css",
- "front_end/profiler/ProfilesPanel.js",
- "front_end/profiler/profilesSidebarTree.css",
- "front_end/profiler/ProfileTypeRegistry.js",
- "front_end/profiler/ProfileView.js",
- "front_end/profiler/TopDownProfileDataGrid.js",
- "front_end/protocol/NodeURL.js",
- "front_end/protocol/InspectorBackend.js",
- "front_end/protocol/module.json",
- "front_end/quick_open/CommandMenu.js",
- "front_end/quick_open/filteredListWidget.css",
- "front_end/quick_open/FilteredListWidget.js",
- "front_end/quick_open/HelpQuickOpen.js",
- "front_end/quick_open/QuickOpen.js",
- "front_end/quick_open/module.json",
- "front_end/resources/ApplicationCacheModel.js",
- "front_end/resources/ApplicationCacheItemsView.js",
- "front_end/resources/ApplicationPanelSidebar.js",
- "front_end/resources/appManifestView.css",
- "front_end/resources/AppManifestView.js",
- "front_end/resources/BackgroundServiceModel.js",
- "front_end/resources/backgroundServiceView.css",
- "front_end/resources/BackgroundServiceView.js",
- "front_end/resources/clearStorageView.css",
- "front_end/resources/ClearStorageView.js",
- "front_end/resources/CookieItemsView.js",
- "front_end/resources/DatabaseModel.js",
- "front_end/resources/DatabaseQueryView.js",
- "front_end/resources/DatabaseTableView.js",
- "front_end/resources/DOMStorageItemsView.js",
- "front_end/resources/DOMStorageModel.js",
- "front_end/resources/IndexedDBModel.js",
- "front_end/resources/indexedDBViews.css",
- "front_end/resources/IndexedDBViews.js",
- "front_end/resources/module.json",
- "front_end/resources/resourcesPanel.css",
- "front_end/resources/ResourcesPanel.js",
- "front_end/resources/ResourcesSection.js",
- "front_end/resources/resourcesSidebar.css",
- "front_end/resources/serviceWorkerCacheViews.css",
- "front_end/resources/ServiceWorkerCacheViews.js",
- "front_end/resources/serviceWorkersView.css",
- "front_end/resources/ServiceWorkersView.js",
- "front_end/resources/StorageItemsView.js",
- "front_end/Runtime.js",
- "front_end/shell.json",
- "front_end/screencast/InputModel.js",
- "front_end/screencast/module.json",
- "front_end/screencast/ScreencastApp.js",
- "front_end/screencast/screencastView.css",
- "front_end/screencast/ScreencastView.js",
- "front_end/sdk/ChildTargetManager.js",
- "front_end/sdk/Connections.js",
- "front_end/sdk/ConsoleModel.js",
- "front_end/sdk/ContentProviders.js",
- "front_end/sdk/CookieModel.js",
- "front_end/sdk/CookieParser.js",
- "front_end/sdk/CPUProfileDataModel.js",
- "front_end/sdk/CPUProfilerModel.js",
- "front_end/sdk/CSSMatchedStyles.js",
- "front_end/sdk/CSSMedia.js",
- "front_end/sdk/CSSMetadata.js",
- "front_end/sdk/CSSModel.js",
- "front_end/sdk/CSSProperty.js",
- "front_end/sdk/CSSRule.js",
- "front_end/sdk/CSSStyleDeclaration.js",
- "front_end/sdk/CSSStyleSheetHeader.js",
- "front_end/sdk/DOMDebuggerModel.js",
- "front_end/sdk/DebuggerModel.js",
- "front_end/sdk/DOMModel.js",
- "front_end/sdk/EmulationModel.js",
- "front_end/sdk/FilmStripModel.js",
- "front_end/sdk/HARLog.js",
- "front_end/sdk/HeapProfilerModel.js",
- "front_end/sdk/IsolateManager.js",
- "front_end/sdk/LayerTreeBase.js",
- "front_end/sdk/LogModel.js",
- "front_end/sdk/module.json",
- "front_end/sdk/NetworkLog.js",
- "front_end/sdk/NetworkManager.js",
- "front_end/sdk/NetworkRequest.js",
- "front_end/sdk/OverlayModel.js",
- "front_end/sdk/PaintProfiler.js",
- "front_end/sdk/PerformanceMetricsModel.js",
- "front_end/sdk/ProfileTreeModel.js",
- "front_end/sdk/RemoteObject.js",
- "front_end/sdk/Resource.js",
- "front_end/sdk/ResourceTreeModel.js",
- "front_end/sdk/RuntimeModel.js",
- "front_end/sdk/ScreenCaptureModel.js",
- "front_end/sdk/Script.js",
- "front_end/sdk/SecurityOriginManager.js",
- "front_end/sdk/ServerTiming.js",
- "front_end/sdk/ServiceWorkerCacheModel.js",
- "front_end/sdk/ServiceWorkerManager.js",
- "front_end/sdk/SourceMap.js",
- "front_end/sdk/SourceMapManager.js",
- "front_end/sdk/Target.js",
- "front_end/sdk/TargetManager.js",
- "front_end/sdk/TracingManager.js",
- "front_end/sdk/TracingModel.js",
- "front_end/sdk_test_runner/module.json",
- "front_end/sdk_test_runner/PageMockTestRunner.js",
- "front_end/search/module.json",
- "front_end/search/SearchConfig.js",
- "front_end/search/searchResultsPane.css",
- "front_end/search/SearchResultsPane.js",
- "front_end/search/searchView.css",
- "front_end/search/SearchView.js",
- "front_end/security/lockIcon.css",
- "front_end/security/mainView.css",
- "front_end/security/module.json",
- "front_end/security/originView.css",
- "front_end/security/SecurityModel.js",
- "front_end/security/SecurityPanel.js",
- "front_end/security/sidebar.css",
- "front_end/security_test_runner/module.json",
- "front_end/security_test_runner/SecurityTestRunner.js",
- "front_end/services/module.json",
- "front_end/services/ServiceManager.js",
- "front_end/settings/frameworkBlackboxSettingsTab.css",
- "front_end/settings/FrameworkBlackboxSettingsTab.js",
- "front_end/settings/module.json",
- "front_end/settings/settingsScreen.css",
- "front_end/settings/SettingsScreen.js",
- "front_end/snippets/module.json",
- "front_end/snippets/ScriptSnippetFileSystem.js",
- "front_end/snippets/SnippetsQuickOpen.js",
- "front_end/source_frame/BinaryResourceViewFactory.js",
- "front_end/source_frame/fontView.css",
- "front_end/source_frame/FontView.js",
- "front_end/source_frame/imageView.css",
- "front_end/source_frame/jsonView.css",
- "front_end/source_frame/JSONView.js",
- "front_end/source_frame/ImageView.js",
- "front_end/source_frame/messagesPopover.css",
- "front_end/source_frame/module.json",
- "front_end/source_frame/PreviewFactory.js",
- "front_end/source_frame/resourceSourceFrame.css",
- "front_end/source_frame/ResourceSourceFrame.js",
- "front_end/source_frame/SourceCodeDiff.js",
- "front_end/source_frame/SourceFrame.js",
- "front_end/source_frame/SourcesTextEditor.js",
- "front_end/source_frame/xmlTree.css",
- "front_end/source_frame/xmlView.css",
- "front_end/source_frame/XMLView.js",
- "front_end/sources/AddSourceMapURLDialog.js",
- "front_end/sources/breakpointEditDialog.css",
- "front_end/sources/BreakpointEditDialog.js",
- "front_end/sources/callStackSidebarPane.css",
- "front_end/sources/CallStackSidebarPane.js",
- "front_end/sources/CSSPlugin.js",
- "front_end/sources/DebuggerPlugin.js",
- "front_end/sources/dialog.css",
- "front_end/sources/debuggerPausedMessage.css",
- "front_end/sources/DebuggerPausedMessage.js",
- "front_end/sources/EditingLocationHistoryManager.js",
- "front_end/sources/FilePathScoreFunction.js",
- "front_end/sources/FilteredUISourceCodeListProvider.js",
- "front_end/sources/GoToLineQuickOpen.js",
- "front_end/sources/GutterDiffPlugin.js",
- "front_end/sources/InplaceFormatterEditorAction.js",
- "front_end/sources/javaScriptBreakpointsSidebarPane.css",
- "front_end/sources/JavaScriptBreakpointsSidebarPane.js",
- "front_end/sources/JavaScriptCompilerPlugin.js",
- "front_end/sources/module.json",
- "front_end/sources/navigatorTree.css",
- "front_end/sources/navigatorView.css",
- "front_end/sources/NavigatorView.js",
- "front_end/sources/OpenFileQuickOpen.js",
- "front_end/sources/OutlineQuickOpen.js",
- "front_end/sources/scopeChainSidebarPane.css",
- "front_end/sources/ScopeChainSidebarPane.js",
- "front_end/sources/ScriptFormatterEditorAction.js",
- "front_end/sources/ScriptOriginPlugin.js",
- "front_end/sources/SearchSourcesView.js",
- "front_end/sources/SimpleHistoryManager.js",
- "front_end/sources/SnippetsPlugin.js",
- "front_end/sources/SourceFormatter.js",
- "front_end/sources/SourceMapNamesResolver.js",
- "front_end/sources/SourcesNavigator.js",
- "front_end/sources/sourcesPanel.css",
- "front_end/sources/SourcesPanel.js",
- "front_end/sources/SourcesSearchScope.js",
- "front_end/sources/sourcesView.css",
- "front_end/sources/SourcesView.js",
- "front_end/sources/UISourceCodeFrame.js",
- "front_end/sources/TabbedEditorContainer.js",
- "front_end/sources/threadsSidebarPane.css",
- "front_end/sources/ThreadsSidebarPane.js",
- "front_end/sources/watchExpressionsSidebarPane.css",
- "front_end/sources/WatchExpressionsSidebarPane.js",
- "front_end/sources_test_runner/AutocompleteTestRunner.js",
- "front_end/sources_test_runner/DebuggerTestRunner.js",
- "front_end/sources_test_runner/EditorTestRunner.js",
- "front_end/sources_test_runner/LiveEditTestRunner.js",
- "front_end/sources_test_runner/SearchTestRunner.js",
- "front_end/sources_test_runner/SourcesTestRunner.js",
- "front_end/sources_test_runner/module.json",
- "front_end/terminal/module.json",
- "front_end/terminal/terminal.css",
- "front_end/terminal/TerminalWidget.js",
- "front_end/terminal/xterm.js/addons/fit/fit.js",
- "front_end/terminal/xterm.js/build/xterm.css",
- "front_end/terminal/xterm.js/build/xterm.js",
- "front_end/test_runner/module.json",
- "front_end/test_runner/TestRunner.js",
- "front_end/text_editor/autocompleteTooltip.css",
- "front_end/text_editor/cmdevtools.css",
- "front_end/text_editor/CodeMirrorTextEditor.js",
- "front_end/text_editor/CodeMirrorUtils.js",
- "front_end/text_editor/module.json",
- "front_end/text_editor/TextEditorAutocompleteController.js",
- "front_end/text_utils/module.json",
- "front_end/text_utils/Text.js",
- "front_end/text_utils/TextRange.js",
- "front_end/text_utils/TextUtils.js",
- "front_end/timeline_model/module.json",
- "front_end/timeline_model/TimelineFrameModel.js",
- "front_end/timeline_model/TimelineIRModel.js",
- "front_end/timeline_model/TimelineJSProfile.js",
- "front_end/timeline_model/TimelineModel.js",
- "front_end/timeline_model/TimelineModelFilter.js",
- "front_end/timeline_model/TimelineProfileTree.js",
- "front_end/timeline_model/TracingLayerTree.js",
- "front_end/timeline/CountersGraph.js",
- "front_end/timeline/EventsTimelineTreeView.js",
- "front_end/timeline/ExtensionTracingSession.js",
- "front_end/timeline/historyToolbarButton.css",
- "front_end/timeline/invalidationsTree.css",
- "front_end/timeline/module.json",
- "front_end/timeline/PerformanceModel.js",
- "front_end/timeline/TimelineController.js",
- "front_end/timeline/TimelineDetailsView.js",
- "front_end/timeline/TimelineEventOverview.js",
- "front_end/timeline/TimelineFilters.js",
- "front_end/timeline/TimelineFlameChartDataProvider.js",
- "front_end/timeline/TimelineFlameChartNetworkDataProvider.js",
- "front_end/timeline/timelineFlamechartPopover.css",
- "front_end/timeline/TimelineFlameChartView.js",
- "front_end/timeline/timelineHistoryManager.css",
- "front_end/timeline/TimelineHistoryManager.js",
- "front_end/timeline/TimelineLayersView.js",
- "front_end/timeline/TimelineLoader.js",
- "front_end/timeline/timelinePaintProfiler.css",
- "front_end/timeline/TimelinePaintProfilerView.js",
- "front_end/timeline/timelinePanel.css",
- "front_end/timeline/TimelinePanel.js",
- "front_end/timeline/timelineStatusDialog.css",
- "front_end/timeline/TimelineTreeView.js",
- "front_end/timeline/TimelineUIUtils.js",
- "front_end/toolbox_bootstrap/module.json",
- "front_end/toolbox_bootstrap/Toolbox.js",
- "front_end/toolbox.js",
- "front_end/toolbox.json",
- "front_end/ui/ActionRegistry.js",
- "front_end/ui/ARIAUtils.js",
- "front_end/ui/checkboxTextLabel.css",
- "front_end/ui/closeButton.css",
- "front_end/ui/confirmDialog.css",
- "front_end/ui/Context.js",
- "front_end/ui/ContextMenu.js",
- "front_end/ui/dialog.css",
- "front_end/ui/Dialog.js",
- "front_end/ui/SyntaxHighlighter.js",
- "front_end/ui/dropTarget.css",
- "front_end/ui/DropTarget.js",
- "front_end/ui/emptyWidget.css",
- "front_end/ui/EmptyWidget.js",
- "front_end/ui/filter.css",
- "front_end/ui/FilterBar.js",
- "front_end/ui/FilterSuggestionBuilder.js",
- "front_end/ui/ForwardedInputEventHandler.js",
- "front_end/ui/Fragment.js",
- "front_end/ui/Geometry.js",
- "front_end/ui/glassPane.css",
- "front_end/ui/GlassPane.js",
- "front_end/ui/HistoryInput.js",
- "front_end/ui/Icon.js",
- "front_end/ui/infobar.css",
- "front_end/ui/Infobar.js",
- "front_end/ui/inlineButton.css",
- "front_end/ui/InplaceEditor.js",
- "front_end/ui/inspectorCommon.css",
- "front_end/ui/inspectorStyle.css",
- "front_end/ui/inspectorSyntaxHighlight.css",
- "front_end/ui/inspectorSyntaxHighlightDark.css",
- "front_end/ui/InspectorView.js",
- "front_end/ui/inspectorViewTabbedPane.css",
- "front_end/ui/KeyboardShortcut.js",
- "front_end/ui/ListControl.js",
- "front_end/ui/ListModel.js",
- "front_end/ui/listWidget.css",
- "front_end/ui/ListWidget.js",
- "front_end/ui/module.json",
- "front_end/ui/Panel.js",
- "front_end/ui/popover.css",
- "front_end/ui/Popover.js",
- "front_end/ui/progressIndicator.css",
- "front_end/ui/ProgressIndicator.js",
- "front_end/ui/radioButton.css",
- "front_end/ui/reportView.css",
- "front_end/ui/ReportView.js",
- "front_end/ui/ResizerWidget.js",
- "front_end/ui/RemoteDebuggingTerminatedScreen.js",
- "front_end/ui/remoteDebuggingTerminatedScreen.css",
- "front_end/ui/rootView.css",
- "front_end/ui/RootView.js",
- "front_end/ui/searchableView.css",
- "front_end/ui/SearchableView.js",
- "front_end/ui/segmentedButton.css",
- "front_end/ui/SegmentedButton.js",
- "front_end/ui/SettingsUI.js",
- "front_end/ui/ShortcutRegistry.js",
- "front_end/ui/ShortcutsScreen.js",
- "front_end/ui/slider.css",
- "front_end/ui/smallBubble.css",
- "front_end/ui/softContextMenu.css",
- "front_end/ui/SoftContextMenu.js",
- "front_end/ui/SoftDropDown.js",
- "front_end/ui/softDropDown.css",
- "front_end/ui/softDropDownButton.css",
- "front_end/ui/splitWidget.css",
- "front_end/ui/SplitWidget.js",
- "front_end/ui/suggestBox.css",
- "front_end/ui/SuggestBox.js",
- "front_end/ui/tabbedPane.css",
- "front_end/ui/TabbedPane.js",
- "front_end/ui/TargetCrashedScreen.js",
- "front_end/ui/targetCrashedScreen.css",
- "front_end/ui/textButton.css",
- "front_end/ui/TextEditor.js",
- "front_end/ui/textPrompt.css",
- "front_end/ui/TextPrompt.js",
- "front_end/ui/ThrottledWidget.js",
- "front_end/ui/toolbar.css",
- "front_end/ui/Toolbar.js",
- "front_end/ui/tooltip.css",
- "front_end/ui/Tooltip.js",
- "front_end/ui/treeoutline.css",
- "front_end/ui/treeoutline.js",
- "front_end/ui/UIUtils.js",
- "front_end/ui/View.js",
- "front_end/ui/viewContainers.css",
- "front_end/ui/Widget.js",
- "front_end/ui/XElement.js",
- "front_end/ui/XLink.js",
- "front_end/ui/XWidget.js",
- "front_end/ui/ZoomManager.js",
- "front_end/web_audio/AudioContextContentBuilder.js",
- "front_end/web_audio/audioContextSelector.css",
- "front_end/web_audio/AudioContextSelector.js",
- "front_end/web_audio/module.json",
- "front_end/web_audio/webAudio.css",
- "front_end/web_audio/WebAudioModel.js",
- "front_end/web_audio/WebAudioView.js",
- "front_end/web_audio/graph_visualizer/Types.js",
- "front_end/web_audio/graph_visualizer/GraphStyle.js",
- "front_end/web_audio/graph_visualizer/GraphManager.js",
- "front_end/web_audio/graph_visualizer/NodeRendererUtility.js",
- "front_end/web_audio/graph_visualizer/NodeView.js",
- "front_end/web_audio/graph_visualizer/EdgeView.js",
- "front_end/web_audio/graph_visualizer/GraphView.js",
- "front_end/worker_main/WorkerMain.js",
- "front_end/worker_main/module.json",
- "front_end/worker_service/module.json",
- "front_end/worker_service/ServiceDispatcher.js",
- "front_end/workspace/FileManager.js",
- "front_end/workspace/module.json",
- "front_end/workspace/UISourceCode.js",
- "front_end/workspace/Workspace.js",
- "front_end/workspace_diff/WorkspaceDiff.js",
- "front_end/workspace_diff/module.json",
-]
-
-devtools_test_files = [
- "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js",
- "front_end/accessibility_test_runner/module.json",
- "front_end/application_test_runner/AppcacheTestRunner.js",
- "front_end/application_test_runner/CacheStorageTestRunner.js",
- "front_end/application_test_runner/IndexedDBTestRunner.js",
- "front_end/application_test_runner/module.json",
- "front_end/application_test_runner/ResourcesTestRunner.js",
- "front_end/application_test_runner/ResourceTreeTestRunner.js",
- "front_end/application_test_runner/ServiceWorkersTestRunner.js",
- "front_end/audits_test_runner/AuditsTestRunner.js",
- "front_end/audits_test_runner/module.json",
- "front_end/axe_core_test_runner/AxeCoreTestRunner.js",
- "front_end/axe_core_test_runner/module.json",
- "front_end/bindings_test_runner/AutomappingTestRunner.js",
- "front_end/bindings_test_runner/BindingsTestRunner.js",
- "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js",
- "front_end/bindings_test_runner/module.json",
- "front_end/bindings_test_runner/OverridesTestRunner.js",
- "front_end/bindings_test_runner/PersistenceTestRunner.js",
- "front_end/console_test_runner/ConsoleTestRunner.js",
- "front_end/console_test_runner/module.json",
- "front_end/coverage_test_runner/CoverageTestRunner.js",
- "front_end/coverage_test_runner/module.json",
- "front_end/cpu_profiler_test_runner/module.json",
- "front_end/cpu_profiler_test_runner/ProfilerTestRunner.js",
- "front_end/data_grid_test_runner/DataGridTestRunner.js",
- "front_end/data_grid_test_runner/module.json",
- "front_end/device_mode_test_runner/DeviceModeTestRunner.js",
- "front_end/device_mode_test_runner/module.json",
- "front_end/elements_test_runner/EditDOMTestRunner.js",
- "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js",
- "front_end/elements_test_runner/ElementsTestRunner.js",
- "front_end/elements_test_runner/module.json",
- "front_end/elements_test_runner/SetOuterHTMLTestRunner.js",
- "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js",
- "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js",
- "front_end/extensions_test_runner/ExtensionsTestRunner.js",
- "front_end/extensions_test_runner/module.json",
- "front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js",
- "front_end/heap_profiler_test_runner/module.json",
- "front_end/integration_test_runner.html",
- "front_end/integration_test_runner.js",
- "front_end/integration_test_runner.json",
- "front_end/layers_test_runner/LayersTestRunner.js",
- "front_end/layers_test_runner/module.json",
- "front_end/network_test_runner/module.json",
- "front_end/network_test_runner/NetworkTestRunner.js",
- "front_end/network_test_runner/ProductRegistryTestRunner.js",
- "front_end/performance_test_runner/module.json",
- "front_end/performance_test_runner/TimelineDataTestRunner.js",
- "front_end/performance_test_runner/TimelineTestRunner.js",
- "front_end/sdk_test_runner/module.json",
- "front_end/sdk_test_runner/PageMockTestRunner.js",
- "front_end/security_test_runner/module.json",
- "front_end/security_test_runner/SecurityTestRunner.js",
- "front_end/sources_test_runner/AutocompleteTestRunner.js",
- "front_end/sources_test_runner/DebuggerTestRunner.js",
- "front_end/sources_test_runner/EditorTestRunner.js",
- "front_end/sources_test_runner/LiveEditTestRunner.js",
- "front_end/sources_test_runner/module.json",
- "front_end/sources_test_runner/SearchTestRunner.js",
- "front_end/sources_test_runner/SourcesTestRunner.js",
- "front_end/test_runner/module.json",
- "front_end/test_runner/TestRunner.js",
-]
-
-devtools_embedder_scripts = [
- "front_end/devtools_compatibility.js",
- "front_end/Tests.js",
-]
-
-devtools_emulated_devices_images = [
- "front_end/emulated_devices/google-nexus-5-horizontal-default-1x.png",
- "front_end/emulated_devices/google-nexus-5-horizontal-default-2x.png",
- "front_end/emulated_devices/google-nexus-5-horizontal-keyboard-1x.png",
- "front_end/emulated_devices/google-nexus-5-horizontal-keyboard-2x.png",
- "front_end/emulated_devices/google-nexus-5-horizontal-navigation-1x.png",
- "front_end/emulated_devices/google-nexus-5-horizontal-navigation-2x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-default-1x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-default-2x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-keyboard-1x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-keyboard-2x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-navigation-1x.png",
- "front_end/emulated_devices/google-nexus-5-vertical-navigation-2x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-default-1x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-default-2x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-keyboard-1x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-keyboard-2x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-navigation-1x.png",
- "front_end/emulated_devices/google-nexus-5x-horizontal-navigation-2x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-default-1x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-default-2x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-keyboard-1x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-keyboard-2x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-navigation-1x.png",
- "front_end/emulated_devices/google-nexus-5x-vertical-navigation-2x.png",
- "front_end/emulated_devices/iPad-landscape.svg",
- "front_end/emulated_devices/iPad-portrait.svg",
- "front_end/emulated_devices/iPhone5-landscape.svg",
- "front_end/emulated_devices/iPhone5-portrait.svg",
- "front_end/emulated_devices/iPhone6-landscape.svg",
- "front_end/emulated_devices/iPhone6-portrait.svg",
- "front_end/emulated_devices/iPhone6Plus-landscape.svg",
- "front_end/emulated_devices/iPhone6Plus-portrait.svg",
- "front_end/emulated_devices/Nexus5X-landscape.svg",
- "front_end/emulated_devices/Nexus5X-portrait.svg",
- "front_end/emulated_devices/Nexus6P-landscape.svg",
- "front_end/emulated_devices/Nexus6P-portrait.svg",
-]
-
-devtools_image_files = [
- "front_end/Images/accelerometer-back.svg",
- "front_end/Images/accelerometer-bottom.png",
- "front_end/Images/accelerometer-front.svg",
- "front_end/Images/accelerometer-left.png",
- "front_end/Images/accelerometer-right.png",
- "front_end/Images/accelerometer-top.png",
- "front_end/Images/audits_logo.svg",
- "front_end/Images/breakpoint.svg",
- "front_end/Images/breakpointConditional.svg",
- "front_end/Images/checkboxCheckmark.svg",
- "front_end/Images/checker.png",
- "front_end/Images/chevrons.svg",
- "front_end/Images/chromeDisabledSelect.png",
- "front_end/Images/chromeDisabledSelect_2x.png",
- "front_end/Images/chromeLeft.png",
- "front_end/Images/chromeMiddle.png",
- "front_end/Images/chromeRight.png",
- "front_end/Images/chromeSelect.png",
- "front_end/Images/chromeSelect_2x.png",
- "front_end/Images/errorWave.svg",
- "front_end/Images/ic_info_black_18dp.svg",
- "front_end/Images/ic_warning_black_18dp.svg",
- "front_end/Images/largeIcons.svg",
- "front_end/Images/mediumIcons.svg",
- "front_end/Images/navigationControls.png",
- "front_end/Images/navigationControls_2x.png",
- "front_end/Images/nodeIcon.png",
- "front_end/Images/popoverArrows.png",
- "front_end/Images/profileGroupIcon.png",
- "front_end/Images/profileIcon.png",
- "front_end/Images/profileSmallIcon.png",
- "front_end/Images/radioDot.png",
- "front_end/Images/resizeDiagonal.png",
- "front_end/Images/resizeDiagonal_2x.png",
- "front_end/Images/resizeHorizontal.png",
- "front_end/Images/resizeHorizontal_2x.png",
- "front_end/Images/resizeVertical.png",
- "front_end/Images/resizeVertical_2x.png",
- "front_end/Images/resourceCSSIcon.png",
- "front_end/Images/resourceDocumentIcon.png",
- "front_end/Images/resourceDocumentIconSmall.png",
- "front_end/Images/resourceJSIcon.png",
- "front_end/Images/resourcePlainIcon.png",
- "front_end/Images/resourcePlainIconSmall.png",
- "front_end/Images/resourcesTimeGraphIcon.png",
- "front_end/Images/searchNext.png",
- "front_end/Images/searchPrev.png",
- "front_end/Images/securityIcons.svg",
- "front_end/Images/speech.png",
- "front_end/Images/smallIcons.svg",
- "front_end/Images/toolbarResizerVertical.png",
- "front_end/Images/touchCursor.png",
- "front_end/Images/touchCursor_2x.png",
- "front_end/Images/treeoutlineTriangles.svg",
- "front_end/Images/whatsnew.png",
-]
-
-resources_out_dir = "$root_out_dir/resources/inspector"
-
-generated_scripts = [
- "$resources_out_dir/InspectorBackendCommands.js",
- "$resources_out_dir/SupportedCSSProperties.js",
-]
-
-generated_aria_properties =
- [ "$resources_out_dir/accessibility/ARIAProperties.js" ]
-
-application_templates = [
- "front_end/devtools_app.html",
- "front_end/inspector.html",
- "front_end/integration_test_runner.html",
- "front_end/js_app.html",
- "front_end/ndb_app.html",
- "front_end/node_app.html",
- "front_end/toolbox.html",
- "front_end/worker_app.html",
-]
-
-generated_applications = [
- "$resources_out_dir/audits_worker.js",
- "$resources_out_dir/devtools_app.html",
- "$resources_out_dir/devtools_app.js",
- "$resources_out_dir/formatter_worker.js",
- "$resources_out_dir/heap_snapshot_worker.js",
- "$resources_out_dir/inspector.html",
- "$resources_out_dir/inspector.js",
- "$resources_out_dir/js_app.html",
- "$resources_out_dir/js_app.js",
- "$resources_out_dir/node_app.html",
- "$resources_out_dir/node_app.js",
- "$resources_out_dir/shell.js",
- "$resources_out_dir/toolbox.html",
- "$resources_out_dir/toolbox.js",
- "$resources_out_dir/worker_app.html",
- "$resources_out_dir/worker_app.js",
-]
-
-generated_non_autostart_non_remote_modules = [
- "$resources_out_dir/animation/animation_module.js",
- "$resources_out_dir/audits/audits_module.js",
- "$resources_out_dir/browser_debugger/browser_debugger_module.js",
- "$resources_out_dir/changes/changes_module.js",
- "$resources_out_dir/protocol_monitor/protocol_monitor_module.js",
- "$resources_out_dir/cm/cm_module.js",
- "$resources_out_dir/color_picker/color_picker_module.js",
- "$resources_out_dir/console/console_module.js",
- "$resources_out_dir/cookie_table/cookie_table_module.js",
- "$resources_out_dir/coverage/coverage_module.js",
- "$resources_out_dir/data_grid/data_grid_module.js",
- "$resources_out_dir/devices/devices_module.js",
- "$resources_out_dir/diff/diff_module.js",
- "$resources_out_dir/elements/elements_module.js",
- "$resources_out_dir/event_listeners/event_listeners_module.js",
- "$resources_out_dir/formatter/formatter_module.js",
- "$resources_out_dir/har_importer/har_importer_module.js",
- "$resources_out_dir/heap_snapshot_model/heap_snapshot_model_module.js",
- "$resources_out_dir/help/help_module.js",
- "$resources_out_dir/inline_editor/inline_editor_module.js",
- "$resources_out_dir/javascript_metadata/javascript_metadata_module.js",
- "$resources_out_dir/js_profiler/js_profiler_module.js",
- "$resources_out_dir/layer_viewer/layer_viewer_module.js",
- "$resources_out_dir/layers/layers_module.js",
- "$resources_out_dir/network/network_module.js",
- "$resources_out_dir/node_debugger/node_debugger_module.js",
- "$resources_out_dir/object_ui/object_ui_module.js",
- "$resources_out_dir/perf_ui/perf_ui_module.js",
- "$resources_out_dir/performance_monitor/performance_monitor_module.js",
- "$resources_out_dir/profiler/profiler_module.js",
- "$resources_out_dir/quick_open/quick_open_module.js",
- "$resources_out_dir/resources/resources_module.js",
- "$resources_out_dir/search/search_module.js",
- "$resources_out_dir/security/security_module.js",
- "$resources_out_dir/settings/settings_module.js",
- "$resources_out_dir/snippets/snippets_module.js",
- "$resources_out_dir/source_frame/source_frame_module.js",
- "$resources_out_dir/sources/sources_module.js",
- "$resources_out_dir/text_editor/text_editor_module.js",
- "$resources_out_dir/timeline_model/timeline_model_module.js",
- "$resources_out_dir/timeline/timeline_module.js",
- "$resources_out_dir/web_audio/web_audio_module.js",
- "$resources_out_dir/workspace_diff/workspace_diff_module.js",
-]
-
-generated_remote_modules = [
- "$resources_out_dir/accessibility/accessibility_module.js",
- "$resources_out_dir/audits_worker/audits_worker_module.js",
- "$resources_out_dir/cm_modes/cm_modes_module.js",
- "$resources_out_dir/emulated_devices/emulated_devices_module.js",
- "$resources_out_dir/product_registry_impl/product_registry_impl_module.js",
-]
-
-generated_test_modules = [
- "$resources_out_dir/accessibility_test_runner/accessibility_test_runner_module.js",
- "$resources_out_dir/application_test_runner/application_test_runner_module.js",
- "$resources_out_dir/audits_test_runner/audits_test_runner_module.js",
- "$resources_out_dir/axe_core_test_runner/axe_core_test_runner_module.js",
- "$resources_out_dir/bindings_test_runner/bindings_test_runner_module.js",
- "$resources_out_dir/console_test_runner/console_test_runner_module.js",
- "$resources_out_dir/coverage_test_runner/coverage_test_runner_module.js",
- "$resources_out_dir/cpu_profiler_test_runner/cpu_profiler_test_runner_module.js",
- "$resources_out_dir/data_grid_test_runner/data_grid_test_runner_module.js",
- "$resources_out_dir/device_mode_test_runner/device_mode_test_runner_module.js",
- "$resources_out_dir/elements_test_runner/elements_test_runner_module.js",
- "$resources_out_dir/extensions_test_runner/extensions_test_runner_module.js",
- "$resources_out_dir/heap_profiler_test_runner/heap_profiler_test_runner_module.js",
- "$resources_out_dir/heap_snapshot_worker/heap_snapshot_worker_module.js",
- "$resources_out_dir/integration_test_runner.html",
- "$resources_out_dir/integration_test_runner.js",
- "$resources_out_dir/layers_test_runner/layers_test_runner_module.js",
- "$resources_out_dir/network_test_runner/network_test_runner_module.js",
- "$resources_out_dir/performance_test_runner/performance_test_runner_module.js",
- "$resources_out_dir/sdk_test_runner/sdk_test_runner_module.js",
- "$resources_out_dir/security_test_runner/security_test_runner_module.js",
- "$resources_out_dir/sources_test_runner/sources_test_runner_module.js",
-]
-
-devtools_applications = [
- "audits_worker",
- "devtools_app",
- "formatter_worker",
- "heap_snapshot_worker",
- "inspector",
- "integration_test_runner",
- "js_app",
- "ndb_app",
- "node_app",
- "shell",
- "toolbox",
- "worker_app",
-]
-
-#-------------------------------------------------------------------------------
-
-visibility = [ "//third_party/blink/*" ]
-
-group("devtools_all_files") {
- data = all_devtools_files
- deps = [
- ":devtools_frontend_resources_data",
+if (!external_devtools_frontend) {
+ all_devtools_files = [
+ "front_end/accessibility/AccessibilityModel.js",
+ "front_end/accessibility/accessibilityNode.css",
+ "front_end/accessibility/AccessibilityNodeView.js",
+ "front_end/accessibility/accessibilityProperties.css",
+ "front_end/accessibility/AccessibilitySidebarView.js",
+ "front_end/accessibility/AccessibilityStrings.js",
+ "front_end/accessibility/ARIAAttributesView.js",
+ "front_end/accessibility/ARIAMetadata.js",
+ "front_end/accessibility/axBreadcrumbs.css",
+ "front_end/accessibility/AXBreadcrumbsPane.js",
+ "front_end/accessibility/module.json",
+ "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js",
+ "front_end/accessibility_test_runner/module.json",
+ "front_end/animation/AnimationGroupPreviewUI.js",
+ "front_end/animation/AnimationModel.js",
+ "front_end/animation/animationScreenshotPopover.css",
+ "front_end/animation/AnimationScreenshotPopover.js",
+ "front_end/animation/animationTimeline.css",
+ "front_end/animation/AnimationTimeline.js",
+ "front_end/animation/AnimationUI.js",
+ "front_end/animation/module.json",
+ "front_end/application_test_runner/AppcacheTestRunner.js",
+ "front_end/application_test_runner/CacheStorageTestRunner.js",
+ "front_end/application_test_runner/IndexedDBTestRunner.js",
+ "front_end/application_test_runner/module.json",
+ "front_end/application_test_runner/ResourcesTestRunner.js",
+ "front_end/application_test_runner/ResourceTreeTestRunner.js",
+ "front_end/application_test_runner/ServiceWorkersTestRunner.js",
+ "front_end/audits_worker.js",
+ "front_end/audits_worker.json",
+ "front_end/audits_worker/AuditsService.js",
+ "front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js",
+ "front_end/audits_worker/module.json",
+ "front_end/audits/AuditsPanel.js",
+ "front_end/audits/AuditsController.js",
+ "front_end/audits/AuditsReportSelector.js",
+ "front_end/audits/AuditsReportRenderer.js",
+ "front_end/audits/AuditsStartView.js",
+ "front_end/audits/AuditsProtocolService.js",
+ "front_end/audits/AuditsStatusView.js",
+ "front_end/audits/auditsDialog.css",
+ "front_end/audits/auditsStartView.css",
+ "front_end/audits/auditsPanel.css",
+ "front_end/audits/RadioSetting.js",
+ "front_end/audits/lighthouse/report.css",
+ "front_end/audits/lighthouse/report.js",
+ "front_end/audits/lighthouse/report-generator.js",
+ "front_end/audits/lighthouse/template.html",
+ "front_end/audits/lighthouse/templates.html",
+ "front_end/audits/module.json",
+ "front_end/audits_test_runner/AuditsTestRunner.js",
+ "front_end/audits_test_runner/module.json",
+ "front_end/axe_core_test_runner/AxeCoreTestRunner.js",
+ "front_end/axe_core_test_runner/module.json",
+ "front_end/bindings/module.json",
+ "front_end/bindings_test_runner/AutomappingTestRunner.js",
+ "front_end/bindings_test_runner/BindingsTestRunner.js",
+ "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js",
+ "front_end/bindings_test_runner/module.json",
+ "front_end/bindings_test_runner/PersistenceTestRunner.js",
+ "front_end/bindings_test_runner/OverridesTestRunner.js",
+ "front_end/browser_debugger/DOMBreakpointsSidebarPane.js",
+ "front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js",
+ "front_end/browser_debugger/ObjectEventListenersSidebarPane.js",
+ "front_end/browser_debugger/XHRBreakpointsSidebarPane.js",
+ "front_end/browser_debugger/domBreakpointsSidebarPane.css",
+ "front_end/browser_debugger/eventListenerBreakpoints.css",
+ "front_end/browser_debugger/module.json",
+ "front_end/browser_debugger/xhrBreakpointsSidebarPane.css",
+ "front_end/browser_sdk/module.json",
+ "front_end/css_overview/cssOverview.css",
+ "front_end/css_overview/cssOverviewStartView.css",
+ "front_end/css_overview/cssOverviewProcessingView.css",
+ "front_end/css_overview/cssOverviewCompletedView.css",
+ "front_end/css_overview/CSSOverviewController.js",
+ "front_end/css_overview/CSSOverviewStartView.js",
+ "front_end/css_overview/CSSOverviewProcessingView.js",
+ "front_end/css_overview/CSSOverviewCompletedView.js",
+ "front_end/css_overview/CSSOverviewModel.js",
+ "front_end/css_overview/CSSOverviewSidebarPanel.js",
+ "front_end/css_overview/cssOverviewSidebarPanel.css",
+ "front_end/css_overview/CSSOverviewPanel.js",
+ "front_end/css_overview/module.json",
+ "front_end/changes/ChangesHighlighter.js",
+ "front_end/changes/changesView.css",
+ "front_end/changes/ChangesView.js",
+ "front_end/changes/changesSidebar.css",
+ "front_end/changes/ChangesSidebar.js",
+ "front_end/changes/module.json",
+ "front_end/cm/active-line.js",
+ "front_end/cm/brace-fold.js",
+ "front_end/cm/closebrackets.js",
+ "front_end/cm/codemirror.css",
+ "front_end/cm/codemirror.js",
+ "front_end/cm/comment.js",
+ "front_end/cm/foldcode.js",
+ "front_end/cm/foldgutter.js",
+ "front_end/cm/mark-selection.js",
+ "front_end/cm/matchbrackets.js",
+ "front_end/cm/module.json",
+ "front_end/cm/multiplex.js",
+ "front_end/cm/overlay.js",
+ "front_end/cm_headless/headlesscodemirror.js",
+ "front_end/cm_headless/module.json",
+ "front_end/cm_modes/clike.js",
+ "front_end/cm_modes/clojure.js",
+ "front_end/cm_modes/coffeescript.js",
+ "front_end/cm_modes/DefaultCodeMirrorMimeMode.js",
+ "front_end/cm_modes/jsx.js",
+ "front_end/cm_modes/livescript.js",
+ "front_end/cm_modes/markdown.js",
+ "front_end/cm_modes/module.json",
+ "front_end/cm_modes/php.js",
+ "front_end/cm_modes/python.js",
+ "front_end/cm_modes/shell.js",
+ "front_end/cm_modes/stylus.js",
+ "front_end/cm_web_modes/css.js",
+ "front_end/cm_web_modes/htmlembedded.js",
+ "front_end/cm_web_modes/htmlmixed.js",
+ "front_end/cm_web_modes/javascript.js",
+ "front_end/cm_web_modes/xml.js",
+ "front_end/color_picker/ContrastDetails.js",
+ "front_end/color_picker/ContrastInfo.js",
+ "front_end/color_picker/ContrastOverlay.js",
+ "front_end/color_picker/module.json",
+ "front_end/color_picker/spectrum.css",
+ "front_end/color_picker/Spectrum.js",
+ "front_end/common/module.json",
+ "front_end/components/imagePreview.css",
+ "front_end/components/jsUtils.css",
+ "front_end/components/module.json",
+ "front_end/console/ConsoleContextSelector.js",
+ "front_end/console/ConsoleFilter.js",
+ "front_end/console/ConsoleSidebar.js",
+ "front_end/console/ConsolePanel.js",
+ "front_end/console/ConsolePinPane.js",
+ "front_end/console/ConsolePrompt.js",
+ "front_end/console/consoleView.css",
+ "front_end/console/consoleContextSelector.css",
+ "front_end/console/consolePinPane.css",
+ "front_end/console/consolePrompt.css",
+ "front_end/console/consoleSidebar.css",
+ "front_end/console/ConsoleView.js",
+ "front_end/console/ConsoleViewMessage.js",
+ "front_end/console/ConsoleViewport.js",
+ "front_end/console/module.json",
+ "front_end/console_counters/errorWarningCounter.css",
+ "front_end/console_counters/module.json",
+ "front_end/console_test_runner/ConsoleTestRunner.js",
+ "front_end/console_test_runner/module.json",
+ "front_end/cookie_table/CookiesTable.js",
+ "front_end/cookie_table/module.json",
+ "front_end/coverage/coverageListView.css",
+ "front_end/coverage/CoverageDecorationManager.js",
+ "front_end/coverage/CoverageListView.js",
+ "front_end/coverage/CoverageModel.js",
+ "front_end/coverage/coverageView.css",
+ "front_end/coverage/CoverageView.js",
+ "front_end/coverage/module.json",
+ "front_end/coverage_test_runner/CoverageTestRunner.js",
+ "front_end/coverage_test_runner/module.json",
+ "front_end/cpu_profiler_test_runner/module.json",
+ "front_end/cpu_profiler_test_runner/ProfilerTestRunner.js",
+ "front_end/dagre_layout/dagre.js",
+ "front_end/dagre_layout/module.json",
+ "front_end/data_grid/dataGrid.css",
+ "front_end/data_grid/DataGrid.js",
+ "front_end/data_grid/module.json",
+ "front_end/data_grid/ShowMoreDataGridNode.js",
+ "front_end/data_grid/SortableDataGrid.js",
+ "front_end/data_grid/ViewportDataGrid.js",
+ "front_end/data_grid_test_runner/DataGridTestRunner.js",
+ "front_end/data_grid_test_runner/module.json",
+ "front_end/device_mode_test_runner/DeviceModeTestRunner.js",
+ "front_end/device_mode_test_runner/module.json",
+ "front_end/devices/DevicesView.js",
+ "front_end/devices/devicesView.css",
+ "front_end/devices/module.json",
+ "front_end/diff/diff_match_patch.js",
+ "front_end/diff/Diff.js",
+ "front_end/diff/module.json",
+ "front_end/dom_extension/module.json",
+ "front_end/elements/breadcrumbs.css",
+ "front_end/elements/classesPaneWidget.css",
+ "front_end/elements/ClassesPaneWidget.js",
+ "front_end/elements/ColorSwatchPopoverIcon.js",
+ "front_end/elements/ComputedStyleModel.js",
+ "front_end/elements/computedStyleSidebarPane.css",
+ "front_end/elements/computedStyleWidgetTree.css",
+ "front_end/elements/ComputedStyleWidget.js",
+ "front_end/elements/DOMLinkifier.js",
+ "front_end/elements/domLinkifier.css",
+ "front_end/elements/DOMPath.js",
+ "front_end/elements/ElementsBreadcrumbs.js",
+ "front_end/elements/elementsPanel.css",
+ "front_end/elements/ElementsPanel.js",
+ "front_end/elements/ElementsSidebarPane.js",
+ "front_end/elements/elementStatePaneWidget.css",
+ "front_end/elements/ElementStatePaneWidget.js",
+ "front_end/elements/ElementsTreeElement.js",
+ "front_end/elements/ElementsTreeElementHighlighter.js",
+ "front_end/elements/elementsTreeOutline.css",
+ "front_end/elements/ElementsTreeOutline.js",
+ "front_end/elements/EventListenersWidget.js",
+ "front_end/elements/InspectElementModeController.js",
+ "front_end/elements/MarkerDecorator.js",
+ "front_end/elements/metricsSidebarPane.css",
+ "front_end/elements/MetricsSidebarPane.js",
+ "front_end/elements/nodeStackTraceWidget.css",
+ "front_end/elements/NodeStackTraceWidget.js",
+ "front_end/elements/module.json",
+ "front_end/elements/platformFontsWidget.css",
+ "front_end/elements/PlatformFontsWidget.js",
+ "front_end/elements/propertiesWidget.css",
+ "front_end/elements/PropertiesWidget.js",
+ "front_end/elements/StylePropertyHighlighter.js",
+ "front_end/elements/stylesSectionTree.css",
+ "front_end/elements/stylesSidebarPane.css",
+ "front_end/elements/StylesSidebarPane.js",
+ "front_end/elements/StylePropertyTreeElement.js",
+ "front_end/elements_test_runner/EditDOMTestRunner.js",
+ "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js",
+ "front_end/elements_test_runner/ElementsTestRunner.js",
+ "front_end/elements_test_runner/module.json",
+ "front_end/elements_test_runner/SetOuterHTMLTestRunner.js",
+ "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js",
+ "front_end/emulated_devices/module.json",
+ "front_end/emulation/AdvancedApp.js",
+ "front_end/emulation/DeviceModeModel.js",
+ "front_end/emulation/deviceModeToolbar.css",
+ "front_end/emulation/DeviceModeToolbar.js",
+ "front_end/emulation/deviceModeView.css",
+ "front_end/emulation/DeviceModeView.js",
+ "front_end/emulation/DeviceModeWrapper.js",
+ "front_end/emulation/devicesSettingsTab.css",
+ "front_end/emulation/DevicesSettingsTab.js",
+ "front_end/emulation/EmulatedDevices.js",
+ "front_end/emulation/geolocationsSettingsTab.css",
+ "front_end/emulation/GeolocationsSettingsTab.js",
+ "front_end/emulation/inspectedPagePlaceholder.css",
+ "front_end/emulation/InspectedPagePlaceholder.js",
+ "front_end/emulation/mediaQueryInspector.css",
+ "front_end/emulation/MediaQueryInspector.js",
+ "front_end/emulation/module.json",
+ "front_end/emulation/sensors.css",
+ "front_end/emulation/SensorsView.js",
+ "front_end/event_listeners/EventListenersUtils.js",
+ "front_end/event_listeners/eventListenersView.css",
+ "front_end/event_listeners/EventListenersView.js",
+ "front_end/event_listeners/module.json",
+ "front_end/extensions/module.json",
+ "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js",
+ "front_end/extensions_test_runner/ExtensionsTestRunner.js",
+ "front_end/extensions_test_runner/module.json",
+ "front_end/formatter/FormatterWorkerPool.js",
+ "front_end/formatter/module.json",
+ "front_end/formatter/ScriptFormatter.js",
+ "front_end/formatter_worker.js",
+ "front_end/formatter_worker.json",
+ "front_end/formatter_worker/AcornTokenizer.js",
+ "front_end/formatter_worker/CSSFormatter.js",
+ "front_end/formatter_worker/CSSRuleParser.js",
+ "front_end/formatter_worker/ESTreeWalker.js",
+ "front_end/formatter_worker/FormattedContentBuilder.js",
+ "front_end/formatter_worker/FormatterWorker.js",
+ "front_end/formatter_worker/HTMLFormatter.js",
+ "front_end/formatter_worker/IdentityFormatter.js",
+ "front_end/formatter_worker/JavaScriptFormatter.js",
+ "front_end/formatter_worker/JavaScriptOutline.js",
+ "front_end/formatter_worker/RelaxedJSONParser.js",
+ "front_end/formatter_worker/acorn/acorn.js",
+ "front_end/formatter_worker/acorn/acorn_loose.js",
+ "front_end/formatter_worker/module.json",
+ "front_end/har_importer/HARFormat.js",
+ "front_end/har_importer/HARImporter.js",
+ "front_end/har_importer/module.json",
+ "front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js",
+ "front_end/heap_profiler_test_runner/module.json",
+ "front_end/heap_snapshot_model/HeapSnapshotModel.js",
+ "front_end/heap_snapshot_model/module.json",
+ "front_end/heap_snapshot_worker.js",
+ "front_end/heap_snapshot_worker.json",
+ "front_end/heap_snapshot_worker/AllocationProfile.js",
+ "front_end/heap_snapshot_worker/HeapSnapshot.js",
+ "front_end/heap_snapshot_worker/HeapSnapshotLoader.js",
+ "front_end/heap_snapshot_worker/HeapSnapshotWorker.js",
+ "front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js",
+ "front_end/heap_snapshot_worker/module.json",
+ "front_end/help/Help.js",
+ "front_end/help/module.json",
+ "front_end/help/releaseNote.css",
+ "front_end/help/ReleaseNoteText.js",
+ "front_end/help/ReleaseNoteView.js",
+ "front_end/host/module.json",
+ "front_end/inline_editor/bezierEditor.css",
+ "front_end/inline_editor/BezierEditor.js",
+ "front_end/inline_editor/bezierSwatch.css",
+ "front_end/inline_editor/BezierUI.js",
+ "front_end/inline_editor/colorSwatch.css",
+ "front_end/inline_editor/ColorSwatch.js",
+ "front_end/inline_editor/cssShadowEditor.css",
+ "front_end/inline_editor/CSSShadowEditor.js",
+ "front_end/inline_editor/CSSShadowModel.js",
+ "front_end/inline_editor/cssShadowSwatch.css",
+ "front_end/inline_editor/module.json",
+ "front_end/inline_editor/swatchPopover.css",
+ "front_end/inline_editor/SwatchPopoverHelper.js",
+ "front_end/inspector.js",
+ "front_end/inspector.json",
+ "front_end/inspector_main/InspectorMain.js",
+ "front_end/inspector_main/module.json",
+ "front_end/inspector_main/nodeIcon.css",
+ "front_end/inspector_main/renderingOptions.css",
+ "front_end/inspector_main/RenderingOptions.js",
+ "front_end/integration_test_runner.js",
+ "front_end/integration_test_runner.json",
+ "front_end/javascript_metadata/module.json",
+ "front_end/javascript_metadata/NativeFunctions.js",
+ "front_end/javascript_metadata/JavaScriptMetadata.js",
+ "front_end/js_main/JsMain.js",
+ "front_end/js_main/module.json",
+ "front_end/js_profiler/module.json",
+ "front_end/layer_viewer/layerDetailsView.css",
+ "front_end/layer_viewer/LayerDetailsView.js",
+ "front_end/layer_viewer/layers3DView.css",
+ "front_end/layer_viewer/Layers3DView.js",
+ "front_end/layer_viewer/LayerTreeOutline.js",
+ "front_end/layer_viewer/LayerViewHost.js",
+ "front_end/layer_viewer/module.json",
+ "front_end/layer_viewer/paintProfiler.css",
+ "front_end/layer_viewer/PaintProfilerView.js",
+ "front_end/layer_viewer/TransformController.js",
+ "front_end/layers/LayerPaintProfilerView.js",
+ "front_end/layers/LayersPanel.js",
+ "front_end/layers/LayerTreeModel.js",
+ "front_end/layers/module.json",
+ "front_end/layers_test_runner/LayersTestRunner.js",
+ "front_end/layers_test_runner/module.json",
+ "front_end/main/ExecutionContextSelector.js",
+ "front_end/main/Main.js",
+ "front_end/main/module.json",
+ "front_end/main/SimpleApp.js",
+ "front_end/protocol_monitor/ProtocolMonitor.js",
+ "front_end/protocol_monitor/protocolMonitor.css",
+ "front_end/protocol_monitor/module.json",
+ "front_end/mobile_throttling/MobileThrottlingSelector.js",
+ "front_end/mobile_throttling/module.json",
+ "front_end/mobile_throttling/NetworkPanelIndicator.js",
+ "front_end/mobile_throttling/NetworkThrottlingSelector.js",
+ "front_end/mobile_throttling/ThrottlingManager.js",
+ "front_end/mobile_throttling/ThrottlingPresets.js",
+ "front_end/mobile_throttling/throttlingSettingsTab.css",
+ "front_end/mobile_throttling/ThrottlingSettingsTab.js",
+ "front_end/media/eventDisplayTable.css",
+ "front_end/media/EventDisplayTable.js",
+ "front_end/media/MainView.js",
+ "front_end/media/MediaTable.js",
+ "front_end/media/PlayerDetailView.js",
+ "front_end/media/playerListView.css",
+ "front_end/media/PlayerListView.js",
+ "front_end/media/module.json",
+ "front_end/media/MediaModel.js",
+ "front_end/media/mediaView.css",
+ "front_end/ndb_app.json",
+ "front_end/network/binaryResourceView.css",
+ "front_end/network/blockedURLsPane.css",
+ "front_end/network/BinaryResourceView.js",
+ "front_end/network/BlockedURLsPane.js",
+ "front_end/network/eventSourceMessagesView.css",
+ "front_end/network/EventSourceMessagesView.js",
+ "front_end/network/HARWriter.js",
+ "front_end/network/module.json",
+ "front_end/network/networkConfigView.css",
+ "front_end/network/NetworkConfigView.js",
+ "front_end/network/NetworkDataGridNode.js",
+ "front_end/network/NetworkItemView.js",
+ "front_end/network/networkLogView.css",
+ "front_end/network/NetworkLogView.js",
+ "front_end/network/NetworkLogViewColumns.js",
+ "front_end/network/NetworkFrameGrouper.js",
+ "front_end/network/networkManageCustomHeadersView.css",
+ "front_end/network/NetworkManageCustomHeadersView.js",
+ "front_end/network/NetworkOverview.js",
+ "front_end/network/networkPanel.css",
+ "front_end/network/NetworkPanel.js",
+ "front_end/network/NetworkSearchScope.js",
+ "front_end/network/NetworkTimeCalculator.js",
+ "front_end/network/networkTimingTable.css",
+ "front_end/network/networkWaterfallColumn.css",
+ "front_end/network/NetworkWaterfallColumn.js",
+ "front_end/network/requestCookiesView.css",
+ "front_end/network/RequestCookiesView.js",
+ "front_end/network/requestHeadersTree.css",
+ "front_end/network/requestHeadersView.css",
+ "front_end/network/RequestHeadersView.js",
+ "front_end/network/requestHTMLView.css",
+ "front_end/network/RequestHTMLView.js",
+ "front_end/network/requestInitiatorView.css",
+ "front_end/network/RequestInitiatorView.js",
+ "front_end/network/RequestPreviewView.js",
+ "front_end/network/RequestResponseView.js",
+ "front_end/network/RequestTimingView.js",
+ "front_end/network/ResourceWebSocketFrameView.js",
+ "front_end/network/signedExchangeInfoTree.css",
+ "front_end/network/signedExchangeInfoView.css",
+ "front_end/network/SignedExchangeInfoView.js",
+ "front_end/network/webSocketFrameView.css",
+ "front_end/network_test_runner/module.json",
+ "front_end/network_test_runner/NetworkTestRunner.js",
+ "front_end/network_test_runner/ProductRegistryTestRunner.js",
+ "front_end/node_debugger/module.json",
+ "front_end/node_main/NodeConnectionsPanel.js",
+ "front_end/node_main/nodeConnectionsPanel.css",
+ "front_end/node_main/NodeMain.js",
+ "front_end/node_main/module.json",
+ "front_end/object_ui/customPreviewComponent.css",
+ "front_end/object_ui/CustomPreviewComponent.js",
+ "front_end/object_ui/JavaScriptAutocomplete.js",
+ "front_end/object_ui/JavaScriptREPL.js",
+ "front_end/object_ui/module.json",
+ "front_end/object_ui/objectPopover.css",
+ "front_end/object_ui/ObjectPopoverHelper.js",
+ "front_end/object_ui/objectPropertiesSection.css",
+ "front_end/object_ui/ObjectPropertiesSection.js",
+ "front_end/object_ui/objectValue.css",
+ "front_end/object_ui/RemoteObjectPreviewFormatter.js",
+ "front_end/perf_ui/ChartViewport.js",
+ "front_end/perf_ui/FilmStripView.js",
+ "front_end/perf_ui/FlameChart.js",
+ "front_end/perf_ui/GCActionDelegate.js",
+ "front_end/perf_ui/LineLevelProfile.js",
+ "front_end/perf_ui/LiveHeapProfile.js",
+ "front_end/perf_ui/NetworkPriorities.js",
+ "front_end/perf_ui/OverviewGrid.js",
+ "front_end/perf_ui/PieChart.js",
+ "front_end/perf_ui/TimelineGrid.js",
+ "front_end/perf_ui/TimelineOverviewPane.js",
+ "front_end/perf_ui/chartViewport.css",
+ "front_end/perf_ui/filmStripView.css",
+ "front_end/perf_ui/flameChart.css",
+ "front_end/perf_ui/module.json",
+ "front_end/perf_ui/overviewGrid.css",
+ "front_end/perf_ui/pieChart.css",
+ "front_end/perf_ui/timelineGrid.css",
+ "front_end/perf_ui/timelineOverviewInfo.css",
+ "front_end/performance_monitor/PerformanceMonitor.js",
+ "front_end/performance_monitor/performanceMonitor.css",
+ "front_end/performance_monitor/module.json",
+ "front_end/performance_test_runner/module.json",
+ "front_end/performance_test_runner/TimelineDataTestRunner.js",
+ "front_end/performance_test_runner/TimelineTestRunner.js",
+ "front_end/persistence/editFileSystemView.css",
+ "front_end/persistence/module.json",
+ "front_end/persistence/workspaceSettingsTab.css",
+ "front_end/platform/module.json",
+ "front_end/product_registry/BadgePool.js",
+ "front_end/product_registry/ProductRegistry.js",
+ "front_end/product_registry/badge.css",
+ "front_end/product_registry/module.json",
+ "front_end/product_registry/popup.css",
+ "front_end/product_registry_impl/module.json",
+ "front_end/product_registry_impl/ProductRegistryImpl.js",
+ "front_end/product_registry_impl/ProductRegistryData.js",
+ "front_end/product_registry_impl/sha1/sha1.js",
+ "front_end/profiler/BottomUpProfileDataGrid.js",
+ "front_end/profiler/CPUProfileFlameChart.js",
+ "front_end/profiler/CPUProfileView.js",
+ "front_end/profiler/heapProfiler.css",
+ "front_end/profiler/HeapProfileView.js",
+ "front_end/profiler/HeapProfilerPanel.js",
+ "front_end/profiler/HeapSnapshotDataGrids.js",
+ "front_end/profiler/HeapSnapshotGridNodes.js",
+ "front_end/profiler/HeapSnapshotProxy.js",
+ "front_end/profiler/HeapSnapshotView.js",
+ "front_end/profiler/HeapTimelineOverview.js",
+ "front_end/profiler/IsolateSelector.js",
+ "front_end/profiler/LiveHeapProfileView.js",
+ "front_end/profiler/liveHeapProfile.css",
+ "front_end/profiler/module.json",
+ "front_end/profiler/ProfileDataGrid.js",
+ "front_end/profiler/ProfileHeader.js",
+ "front_end/profiler/profileLauncherView.css",
+ "front_end/profiler/ProfileLauncherView.js",
+ "front_end/profiler/ProfileType.js",
+ "front_end/profiler/profilesPanel.css",
+ "front_end/profiler/ProfilesPanel.js",
+ "front_end/profiler/profilesSidebarTree.css",
+ "front_end/profiler/ProfileTypeRegistry.js",
+ "front_end/profiler/ProfileView.js",
+ "front_end/profiler/TopDownProfileDataGrid.js",
+ "front_end/protocol/module.json",
+ "front_end/quick_open/CommandMenu.js",
+ "front_end/quick_open/filteredListWidget.css",
+ "front_end/quick_open/FilteredListWidget.js",
+ "front_end/quick_open/HelpQuickOpen.js",
+ "front_end/quick_open/QuickOpen.js",
+ "front_end/quick_open/module.json",
+ "front_end/resources/ApplicationCacheModel.js",
+ "front_end/resources/ApplicationCacheItemsView.js",
+ "front_end/resources/ApplicationPanelSidebar.js",
+ "front_end/resources/appManifestView.css",
+ "front_end/resources/AppManifestView.js",
+ "front_end/resources/BackgroundServiceModel.js",
+ "front_end/resources/backgroundServiceView.css",
+ "front_end/resources/BackgroundServiceView.js",
+ "front_end/resources/clearStorageView.css",
+ "front_end/resources/ClearStorageView.js",
+ "front_end/resources/CookieItemsView.js",
+ "front_end/resources/cookieItemsView.css",
+ "front_end/resources/DatabaseModel.js",
+ "front_end/resources/DatabaseQueryView.js",
+ "front_end/resources/DatabaseTableView.js",
+ "front_end/resources/DOMStorageItemsView.js",
+ "front_end/resources/DOMStorageModel.js",
+ "front_end/resources/IndexedDBModel.js",
+ "front_end/resources/indexedDBViews.css",
+ "front_end/resources/IndexedDBViews.js",
+ "front_end/resources/module.json",
+ "front_end/resources/resourcesPanel.css",
+ "front_end/resources/ResourcesPanel.js",
+ "front_end/resources/ResourcesSection.js",
+ "front_end/resources/resourcesSidebar.css",
+ "front_end/resources/serviceWorkerCacheViews.css",
+ "front_end/resources/ServiceWorkerCacheViews.js",
+ "front_end/resources/serviceWorkersView.css",
+ "front_end/resources/ServiceWorkersView.js",
+ "front_end/resources/StorageItemsView.js",
+ "front_end/shell.json",
+ "front_end/screencast/InputModel.js",
+ "front_end/screencast/module.json",
+ "front_end/screencast/ScreencastApp.js",
+ "front_end/screencast/screencastView.css",
+ "front_end/screencast/ScreencastView.js",
+ "front_end/sdk/module.json",
+ "front_end/sdk_test_runner/module.json",
+ "front_end/sdk_test_runner/PageMockTestRunner.js",
+ "front_end/search/module.json",
+ "front_end/search/SearchConfig.js",
+ "front_end/search/searchResultsPane.css",
+ "front_end/search/SearchResultsPane.js",
+ "front_end/search/searchView.css",
+ "front_end/search/SearchView.js",
+ "front_end/security/lockIcon.css",
+ "front_end/security/mainView.css",
+ "front_end/security/module.json",
+ "front_end/security/originView.css",
+ "front_end/security/SecurityModel.js",
+ "front_end/security/SecurityPanel.js",
+ "front_end/security/sidebar.css",
+ "front_end/security_test_runner/module.json",
+ "front_end/security_test_runner/SecurityTestRunner.js",
+ "front_end/services/module.json",
+ "front_end/settings/frameworkBlackboxSettingsTab.css",
+ "front_end/settings/FrameworkBlackboxSettingsTab.js",
+ "front_end/settings/module.json",
+ "front_end/settings/settingsScreen.css",
+ "front_end/settings/SettingsScreen.js",
+ "front_end/snippets/module.json",
+ "front_end/snippets/ScriptSnippetFileSystem.js",
+ "front_end/snippets/SnippetsQuickOpen.js",
+ "front_end/source_frame/BinaryResourceViewFactory.js",
+ "front_end/source_frame/fontView.css",
+ "front_end/source_frame/FontView.js",
+ "front_end/source_frame/imageView.css",
+ "front_end/source_frame/jsonView.css",
+ "front_end/source_frame/JSONView.js",
+ "front_end/source_frame/ImageView.js",
+ "front_end/source_frame/messagesPopover.css",
+ "front_end/source_frame/module.json",
+ "front_end/source_frame/PreviewFactory.js",
+ "front_end/source_frame/resourceSourceFrame.css",
+ "front_end/source_frame/ResourceSourceFrame.js",
+ "front_end/source_frame/SourceCodeDiff.js",
+ "front_end/source_frame/SourceFrame.js",
+ "front_end/source_frame/SourcesTextEditor.js",
+ "front_end/source_frame/xmlTree.css",
+ "front_end/source_frame/xmlView.css",
+ "front_end/source_frame/XMLView.js",
+ "front_end/sources/AddSourceMapURLDialog.js",
+ "front_end/sources/breakpointEditDialog.css",
+ "front_end/sources/BreakpointEditDialog.js",
+ "front_end/sources/callStackSidebarPane.css",
+ "front_end/sources/CallStackSidebarPane.js",
+ "front_end/sources/CSSPlugin.js",
+ "front_end/sources/DebuggerPlugin.js",
+ "front_end/sources/dialog.css",
+ "front_end/sources/debuggerPausedMessage.css",
+ "front_end/sources/DebuggerPausedMessage.js",
+ "front_end/sources/EditingLocationHistoryManager.js",
+ "front_end/sources/FilePathScoreFunction.js",
+ "front_end/sources/FilteredUISourceCodeListProvider.js",
+ "front_end/sources/GoToLineQuickOpen.js",
+ "front_end/sources/GutterDiffPlugin.js",
+ "front_end/sources/InplaceFormatterEditorAction.js",
+ "front_end/sources/javaScriptBreakpointsSidebarPane.css",
+ "front_end/sources/JavaScriptBreakpointsSidebarPane.js",
+ "front_end/sources/JavaScriptCompilerPlugin.js",
+ "front_end/sources/module.json",
+ "front_end/sources/navigatorTree.css",
+ "front_end/sources/navigatorView.css",
+ "front_end/sources/NavigatorView.js",
+ "front_end/sources/OpenFileQuickOpen.js",
+ "front_end/sources/OutlineQuickOpen.js",
+ "front_end/sources/scopeChainSidebarPane.css",
+ "front_end/sources/ScopeChainSidebarPane.js",
+ "front_end/sources/ScriptFormatterEditorAction.js",
+ "front_end/sources/ScriptOriginPlugin.js",
+ "front_end/sources/SearchSourcesView.js",
+ "front_end/sources/SimpleHistoryManager.js",
+ "front_end/sources/SnippetsPlugin.js",
+ "front_end/sources/SourceFormatter.js",
+ "front_end/sources/SourceMapNamesResolver.js",
+ "front_end/sources/SourcesNavigator.js",
+ "front_end/sources/sourcesPanel.css",
+ "front_end/sources/SourcesPanel.js",
+ "front_end/sources/SourcesSearchScope.js",
+ "front_end/sources/sourcesView.css",
+ "front_end/sources/SourcesView.js",
+ "front_end/sources/UISourceCodeFrame.js",
+ "front_end/sources/TabbedEditorContainer.js",
+ "front_end/sources/threadsSidebarPane.css",
+ "front_end/sources/ThreadsSidebarPane.js",
+ "front_end/sources/watchExpressionsSidebarPane.css",
+ "front_end/sources/WatchExpressionsSidebarPane.js",
+ "front_end/sources_test_runner/AutocompleteTestRunner.js",
+ "front_end/sources_test_runner/DebuggerTestRunner.js",
+ "front_end/sources_test_runner/EditorTestRunner.js",
+ "front_end/sources_test_runner/LiveEditTestRunner.js",
+ "front_end/sources_test_runner/SearchTestRunner.js",
+ "front_end/sources_test_runner/SourcesTestRunner.js",
+ "front_end/sources_test_runner/module.json",
+ "front_end/test_runner/module.json",
+ "front_end/test_runner/TestRunner.js",
+ "front_end/text_editor/autocompleteTooltip.css",
+ "front_end/text_editor/cmdevtools.css",
+ "front_end/text_editor/CodeMirrorTextEditor.js",
+ "front_end/text_editor/CodeMirrorUtils.js",
+ "front_end/text_editor/module.json",
+ "front_end/text_editor/TextEditorAutocompleteController.js",
+ "front_end/text_utils/module.json",
+ "front_end/text_utils/Text.js",
+ "front_end/text_utils/TextRange.js",
+ "front_end/text_utils/TextUtils.js",
+ "front_end/timeline_model/module.json",
+ "front_end/timeline_model/TimelineFrameModel.js",
+ "front_end/timeline_model/TimelineIRModel.js",
+ "front_end/timeline_model/TimelineJSProfile.js",
+ "front_end/timeline_model/TimelineModel.js",
+ "front_end/timeline_model/TimelineModelFilter.js",
+ "front_end/timeline_model/TimelineProfileTree.js",
+ "front_end/timeline_model/TracingLayerTree.js",
+ "front_end/timeline/CountersGraph.js",
+ "front_end/timeline/EventsTimelineTreeView.js",
+ "front_end/timeline/ExtensionTracingSession.js",
+ "front_end/timeline/historyToolbarButton.css",
+ "front_end/timeline/invalidationsTree.css",
+ "front_end/timeline/module.json",
+ "front_end/timeline/PerformanceModel.js",
+ "front_end/timeline/TimelineController.js",
+ "front_end/timeline/TimelineDetailsView.js",
+ "front_end/timeline/TimelineEventOverview.js",
+ "front_end/timeline/TimelineFilters.js",
+ "front_end/timeline/TimelineFlameChartDataProvider.js",
+ "front_end/timeline/TimelineFlameChartNetworkDataProvider.js",
+ "front_end/timeline/timelineFlamechartPopover.css",
+ "front_end/timeline/TimelineFlameChartView.js",
+ "front_end/timeline/timelineHistoryManager.css",
+ "front_end/timeline/TimelineHistoryManager.js",
+ "front_end/timeline/TimelineLayersView.js",
+ "front_end/timeline/TimelineLoader.js",
+ "front_end/timeline/timelinePaintProfiler.css",
+ "front_end/timeline/TimelinePaintProfilerView.js",
+ "front_end/timeline/timelinePanel.css",
+ "front_end/timeline/TimelinePanel.js",
+ "front_end/timeline/timelineStatusDialog.css",
+ "front_end/timeline/TimelineTreeView.js",
+ "front_end/timeline/TimelineUIUtils.js",
+ "front_end/timeline/UIDevtoolsController.js",
+ "front_end/timeline/UIDevtoolsUtils.js",
+ "front_end/toolbox_bootstrap/module.json",
+ "front_end/toolbox_bootstrap/Toolbox.js",
+ "front_end/toolbox.js",
+ "front_end/toolbox.json",
+ "front_end/ui/checkboxTextLabel.css",
+ "front_end/ui/closeButton.css",
+ "front_end/ui/confirmDialog.css",
+ "front_end/ui/dialog.css",
+ "front_end/ui/dropTarget.css",
+ "front_end/ui/emptyWidget.css",
+ "front_end/ui/filter.css",
+ "front_end/ui/glassPane.css",
+ "front_end/ui/infobar.css",
+ "front_end/ui/inlineButton.css",
+ "front_end/ui/inspectorCommon.css",
+ "front_end/ui/inspectorStyle.css",
+ "front_end/ui/inspectorSyntaxHighlight.css",
+ "front_end/ui/inspectorSyntaxHighlightDark.css",
+ "front_end/ui/inspectorViewTabbedPane.css",
+ "front_end/ui/listWidget.css",
+ "front_end/ui/module.json",
+ "front_end/ui/popover.css",
+ "front_end/ui/progressIndicator.css",
+ "front_end/ui/radioButton.css",
+ "front_end/ui/reportView.css",
+ "front_end/ui/remoteDebuggingTerminatedScreen.css",
+ "front_end/ui/rootView.css",
+ "front_end/ui/searchableView.css",
+ "front_end/ui/segmentedButton.css",
+ "front_end/ui/slider.css",
+ "front_end/ui/smallBubble.css",
+ "front_end/ui/softContextMenu.css",
+ "front_end/ui/softDropDown.css",
+ "front_end/ui/softDropDownButton.css",
+ "front_end/ui/splitWidget.css",
+ "front_end/ui/suggestBox.css",
+ "front_end/ui/tabbedPane.css",
+ "front_end/ui/targetCrashedScreen.css",
+ "front_end/ui/textButton.css",
+ "front_end/ui/textPrompt.css",
+ "front_end/ui/toolbar.css",
+ "front_end/ui/tooltip.css",
+ "front_end/ui/treeoutline.css",
+ "front_end/ui/viewContainers.css",
+ "front_end/web_audio/AudioContextContentBuilder.js",
+ "front_end/web_audio/audioContextSelector.css",
+ "front_end/web_audio/AudioContextSelector.js",
+ "front_end/web_audio/module.json",
+ "front_end/web_audio/webAudio.css",
+ "front_end/web_audio/WebAudioModel.js",
+ "front_end/web_audio/WebAudioView.js",
+ "front_end/web_audio/graph_visualizer/Types.js",
+ "front_end/web_audio/graph_visualizer/GraphStyle.js",
+ "front_end/web_audio/graph_visualizer/GraphManager.js",
+ "front_end/web_audio/graph_visualizer/NodeRendererUtility.js",
+ "front_end/web_audio/graph_visualizer/NodeView.js",
+ "front_end/web_audio/graph_visualizer/EdgeView.js",
+ "front_end/web_audio/graph_visualizer/GraphView.js",
+ "front_end/worker_main/WorkerMain.js",
+ "front_end/worker_main/module.json",
+ "front_end/worker_service/module.json",
+ "front_end/worker_service/ServiceDispatcher.js",
+ "front_end/workspace/module.json",
+ "front_end/workspace_diff/WorkspaceDiff.js",
+ "front_end/workspace_diff/module.json",
]
-}
-devtools_frontend_resources_deps = [
- ":aria_properties",
- ":build_release_devtools",
- ":copy_embedder_scripts",
- ":copy_emulated_devices_images",
- ":copy_htaccess",
- ":copy_inspector_images",
- ":devtools_extension_api",
- ":frontend_protocol_sources",
- ":supported_css_properties",
-]
-
-if (debug_devtools) {
- devtools_frontend_resources_deps += [
- ":build_debug_devtools",
- ":copy_aria_properties",
- ":copy_generated_scripts",
+ lighthouse_locale_files = [
+ "front_end/audits_worker/lighthouse/locales/ar-XB.json",
+ "front_end/audits_worker/lighthouse/locales/ar.json",
+ "front_end/audits_worker/lighthouse/locales/bg.json",
+ "front_end/audits_worker/lighthouse/locales/ca.json",
+ "front_end/audits_worker/lighthouse/locales/cs.json",
+ "front_end/audits_worker/lighthouse/locales/da.json",
+ "front_end/audits_worker/lighthouse/locales/de.json",
+ "front_end/audits_worker/lighthouse/locales/el.json",
+ "front_end/audits_worker/lighthouse/locales/en-GB.json",
+ "front_end/audits_worker/lighthouse/locales/en-US.json",
+ "front_end/audits_worker/lighthouse/locales/en-XA.json",
+ "front_end/audits_worker/lighthouse/locales/en-XL.json",
+ "front_end/audits_worker/lighthouse/locales/es-419.json",
+ "front_end/audits_worker/lighthouse/locales/es.json",
+ "front_end/audits_worker/lighthouse/locales/fi.json",
+ "front_end/audits_worker/lighthouse/locales/fil.json",
+ "front_end/audits_worker/lighthouse/locales/fr.json",
+ "front_end/audits_worker/lighthouse/locales/he.json",
+ "front_end/audits_worker/lighthouse/locales/hi.json",
+ "front_end/audits_worker/lighthouse/locales/hr.json",
+ "front_end/audits_worker/lighthouse/locales/hu.json",
+ "front_end/audits_worker/lighthouse/locales/id.json",
+ "front_end/audits_worker/lighthouse/locales/it.json",
+ "front_end/audits_worker/lighthouse/locales/ja.json",
+ "front_end/audits_worker/lighthouse/locales/ko.json",
+ "front_end/audits_worker/lighthouse/locales/lt.json",
+ "front_end/audits_worker/lighthouse/locales/lv.json",
+ "front_end/audits_worker/lighthouse/locales/nl.json",
+ "front_end/audits_worker/lighthouse/locales/no.json",
+ "front_end/audits_worker/lighthouse/locales/pl.json",
+ "front_end/audits_worker/lighthouse/locales/pt-PT.json",
+ "front_end/audits_worker/lighthouse/locales/pt.json",
+ "front_end/audits_worker/lighthouse/locales/ro.json",
+ "front_end/audits_worker/lighthouse/locales/ru.json",
+ "front_end/audits_worker/lighthouse/locales/sk.json",
+ "front_end/audits_worker/lighthouse/locales/sl.json",
+ "front_end/audits_worker/lighthouse/locales/sr-Latn.json",
+ "front_end/audits_worker/lighthouse/locales/sr.json",
+ "front_end/audits_worker/lighthouse/locales/sv.json",
+ "front_end/audits_worker/lighthouse/locales/ta.json",
+ "front_end/audits_worker/lighthouse/locales/te.json",
+ "front_end/audits_worker/lighthouse/locales/th.json",
+ "front_end/audits_worker/lighthouse/locales/tr.json",
+ "front_end/audits_worker/lighthouse/locales/uk.json",
+ "front_end/audits_worker/lighthouse/locales/vi.json",
+ "front_end/audits_worker/lighthouse/locales/zh-HK.json",
+ "front_end/audits_worker/lighthouse/locales/zh-TW.json",
+ "front_end/audits_worker/lighthouse/locales/zh.json",
]
-}
-
-group("devtools_frontend_resources") {
- public_deps = devtools_frontend_resources_deps
-}
-# Do not use this unless you need unpacked devtools at runtime.
-group("devtools_frontend_resources_data") {
- data_deps = devtools_frontend_resources_deps
-}
+ all_devtools_files += lighthouse_locale_files
-copy("copy_embedder_scripts") {
- sources = devtools_embedder_scripts
- outputs = [
- "$resources_out_dir/{{source_file_part}}",
+ all_devtools_modules = [
+ "front_end/console_counters/console_counters.js",
+ "front_end/console_counters/WarningErrorCounter.js",
+ "front_end/extensions/extensions.js",
+ "front_end/extensions/ExtensionAPI.js",
+ "front_end/extensions/ExtensionPanel.js",
+ "front_end/extensions/ExtensionServer.js",
+ "front_end/extensions/ExtensionTraceProvider.js",
+ "front_end/extensions/ExtensionView.js",
+ "front_end/browser_sdk/browser_sdk.js",
+ "front_end/browser_sdk/LogManager.js",
+ "front_end/persistence/persistence.js",
+ "front_end/persistence/WorkspaceSettingsTab.js",
+ "front_end/persistence/PlatformFileSystem.js",
+ "front_end/persistence/PersistenceUtils.js",
+ "front_end/persistence/PersistenceImpl.js",
+ "front_end/persistence/PersistenceActions.js",
+ "front_end/persistence/NetworkPersistenceManager.js",
+ "front_end/persistence/IsolatedFileSystemManager.js",
+ "front_end/persistence/IsolatedFileSystem.js",
+ "front_end/persistence/FileSystemWorkspaceBinding.js",
+ "front_end/persistence/EditFileSystemView.js",
+ "front_end/persistence/Automapping.js",
+ "front_end/components/components.js",
+ "front_end/components/TargetDetachedDialog.js",
+ "front_end/components/Reload.js",
+ "front_end/components/Linkifier.js",
+ "front_end/components/JSPresentationUtils.js",
+ "front_end/components/ImagePreview.js",
+ "front_end/components/DockController.js",
+ "front_end/bindings/bindings.js",
+ "front_end/bindings/TempFile.js",
+ "front_end/bindings/StylesSourceMapping.js",
+ "front_end/bindings/SASSSourceMapping.js",
+ "front_end/bindings/ResourceUtils.js",
+ "front_end/bindings/ResourceScriptMapping.js",
+ "front_end/bindings/ResourceMapping.js",
+ "front_end/bindings/PresentationConsoleMessageHelper.js",
+ "front_end/bindings/NetworkProject.js",
+ "front_end/bindings/LiveLocation.js",
+ "front_end/bindings/FileUtils.js",
+ "front_end/bindings/DefaultScriptMapping.js",
+ "front_end/bindings/DebuggerWorkspaceBinding.js",
+ "front_end/bindings/CSSWorkspaceBinding.js",
+ "front_end/bindings/ContentProviderBasedProject.js",
+ "front_end/bindings/CompilerScriptMapping.js",
+ "front_end/bindings/BreakpointManager.js",
+ "front_end/bindings/BlackboxManager.js",
+ "front_end/workspace/workspace.js",
+ "front_end/workspace/WorkspaceImpl.js",
+ "front_end/workspace/UISourceCode.js",
+ "front_end/workspace/FileManager.js",
+ "front_end/services/services.js",
+ "front_end/services/ServiceManager.js",
+ "front_end/sdk/sdk.js",
+ "front_end/sdk/TracingModel.js",
+ "front_end/sdk/TracingManager.js",
+ "front_end/sdk/TargetManager.js",
+ "front_end/sdk/Target.js",
+ "front_end/sdk/SourceMapManager.js",
+ "front_end/sdk/SourceMap.js",
+ "front_end/sdk/ServiceWorkerManager.js",
+ "front_end/sdk/ServiceWorkerCacheModel.js",
+ "front_end/sdk/ServerTiming.js",
+ "front_end/sdk/SecurityOriginManager.js",
+ "front_end/sdk/SDKModel.js",
+ "front_end/sdk/Script.js",
+ "front_end/sdk/ScreenCaptureModel.js",
+ "front_end/sdk/RuntimeModel.js",
+ "front_end/sdk/ResourceTreeModel.js",
+ "front_end/sdk/Resource.js",
+ "front_end/sdk/RemoteObject.js",
+ "front_end/sdk/ProfileTreeModel.js",
+ "front_end/sdk/PerformanceMetricsModel.js",
+ "front_end/sdk/PaintProfiler.js",
+ "front_end/sdk/OverlayModel.js",
+ "front_end/sdk/NetworkRequest.js",
+ "front_end/sdk/NetworkManager.js",
+ "front_end/sdk/NetworkLog.js",
+ "front_end/sdk/LogModel.js",
+ "front_end/sdk/LayerTreeBase.js",
+ "front_end/sdk/IsolateManager.js",
+ "front_end/sdk/HeapProfilerModel.js",
+ "front_end/sdk/HARLog.js",
+ "front_end/sdk/FilmStripModel.js",
+ "front_end/sdk/EmulationModel.js",
+ "front_end/sdk/DOMModel.js",
+ "front_end/sdk/DOMDebuggerModel.js",
+ "front_end/sdk/DebuggerModel.js",
+ "front_end/sdk/CSSStyleSheetHeader.js",
+ "front_end/sdk/CSSStyleDeclaration.js",
+ "front_end/sdk/CSSRule.js",
+ "front_end/sdk/CSSProperty.js",
+ "front_end/sdk/CSSModel.js",
+ "front_end/sdk/CSSMetadata.js",
+ "front_end/sdk/CSSMedia.js",
+ "front_end/sdk/CSSMatchedStyles.js",
+ "front_end/sdk/CPUProfilerModel.js",
+ "front_end/sdk/CPUProfileDataModel.js",
+ "front_end/sdk/CookieParser.js",
+ "front_end/sdk/CookieModel.js",
+ "front_end/sdk/CompilerSourceMappingContentProvider.js",
+ "front_end/sdk/ConsoleModel.js",
+ "front_end/sdk/Connections.js",
+ "front_end/sdk/ChildTargetManager.js",
+ "front_end/protocol/protocol.js",
+ "front_end/protocol/NodeURL.js",
+ "front_end/protocol/InspectorBackend.js",
+ "front_end/host/host.js",
+ "front_end/host/UserMetrics.js",
+ "front_end/host/ResourceLoader.js",
+ "front_end/host/Platform.js",
+ "front_end/host/InspectorFrontendHost.js",
+ "front_end/host/InspectorFrontendHostAPI.js",
+ "front_end/dom_extension/DOMExtension.js",
+ "front_end/root.js",
+ "front_end/Runtime.js",
+ "front_end/platform/utilities.js",
+ "front_end/ui/ARIAUtils.js",
+ "front_end/ui/ZoomManager.js",
+ "front_end/ui/XWidget.js",
+ "front_end/ui/XLink.js",
+ "front_end/ui/XElement.js",
+ "front_end/ui/Widget.js",
+ "front_end/ui/View.js",
+ "front_end/ui/ViewManager.js",
+ "front_end/ui/UIUtils.js",
+ "front_end/ui/ui.js",
+ "front_end/ui/Treeoutline.js",
+ "front_end/ui/Tooltip.js",
+ "front_end/ui/Toolbar.js",
+ "front_end/ui/ThrottledWidget.js",
+ "front_end/ui/TextPrompt.js",
+ "front_end/ui/TextEditor.js",
+ "front_end/ui/TargetCrashedScreen.js",
+ "front_end/ui/TabbedPane.js",
+ "front_end/ui/SyntaxHighlighter.js",
+ "front_end/ui/SuggestBox.js",
+ "front_end/ui/SplitWidget.js",
+ "front_end/ui/SoftDropDown.js",
+ "front_end/ui/SoftContextMenu.js",
+ "front_end/ui/ShortcutsScreen.js",
+ "front_end/ui/ShortcutRegistry.js",
+ "front_end/ui/SettingsUI.js",
+ "front_end/ui/SegmentedButton.js",
+ "front_end/ui/SearchableView.js",
+ "front_end/ui/RootView.js",
+ "front_end/ui/ResizerWidget.js",
+ "front_end/ui/ReportView.js",
+ "front_end/ui/RemoteDebuggingTerminatedScreen.js",
+ "front_end/ui/ProgressIndicator.js",
+ "front_end/ui/PopoverHelper.js",
+ "front_end/ui/Panel.js",
+ "front_end/ui/ListWidget.js",
+ "front_end/ui/ListModel.js",
+ "front_end/ui/ListControl.js",
+ "front_end/ui/KeyboardShortcut.js",
+ "front_end/ui/InspectorView.js",
+ "front_end/ui/InplaceEditor.js",
+ "front_end/ui/Infobar.js",
+ "front_end/ui/Icon.js",
+ "front_end/ui/HistoryInput.js",
+ "front_end/ui/GlassPane.js",
+ "front_end/ui/Geometry.js",
+ "front_end/ui/Fragment.js",
+ "front_end/ui/ForwardedInputEventHandler.js",
+ "front_end/ui/FilterSuggestionBuilder.js",
+ "front_end/ui/FilterBar.js",
+ "front_end/ui/EmptyWidget.js",
+ "front_end/ui/DropTarget.js",
+ "front_end/ui/Dialog.js",
+ "front_end/ui/ContextMenu.js",
+ "front_end/ui/Context.js",
+ "front_end/ui/ARIAUtils.js",
+ "front_end/ui/ActionRegistry.js",
+ "front_end/ui/Action.js",
+ "front_end/ui/ActionDelegate.js",
+ "front_end/ui/ContextFlavorListener.js",
+ "front_end/root.js",
+ "front_end/common/common.js",
+ "front_end/common/App.js",
+ "front_end/common/AppProvider.js",
+ "front_end/common/CharacterIdMap.js",
+ "front_end/common/Color.js",
+ "front_end/common/ContentProvider.js",
+ "front_end/common/EventTarget.js",
+ "front_end/common/JavaScriptMetaData.js",
+ "front_end/common/Linkifier.js",
+ "front_end/common/Object.js",
+ "front_end/common/Console.js",
+ "front_end/common/ParsedURL.js",
+ "front_end/common/Progress.js",
+ "front_end/common/QueryParamHandler.js",
+ "front_end/common/ResourceType.js",
+ "front_end/common/Revealer.js",
+ "front_end/common/Runnable.js",
+ "front_end/common/SegmentedRange.js",
+ "front_end/common/Settings.js",
+ "front_end/common/StaticContentProvider.js",
+ "front_end/common/StringOutputStream.js",
+ "front_end/common/TextDictionary.js",
+ "front_end/common/Throttler.js",
+ "front_end/common/Trie.js",
+ "front_end/common/UIString.js",
+ "front_end/common/Worker.js",
]
-}
-copy("copy_htaccess") {
- sources = [
- "htaccess",
+ devtools_test_files = [
+ "//third_party/axe-core/axe.js",
+ "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js",
+ "front_end/accessibility_test_runner/module.json",
+ "front_end/application_test_runner/AppcacheTestRunner.js",
+ "front_end/application_test_runner/CacheStorageTestRunner.js",
+ "front_end/application_test_runner/IndexedDBTestRunner.js",
+ "front_end/application_test_runner/module.json",
+ "front_end/application_test_runner/ResourcesTestRunner.js",
+ "front_end/application_test_runner/ResourceTreeTestRunner.js",
+ "front_end/application_test_runner/ServiceWorkersTestRunner.js",
+ "front_end/audits_test_runner/AuditsTestRunner.js",
+ "front_end/audits_test_runner/module.json",
+ "front_end/axe_core_test_runner/AxeCoreTestRunner.js",
+ "front_end/axe_core_test_runner/module.json",
+ "front_end/bindings_test_runner/AutomappingTestRunner.js",
+ "front_end/bindings_test_runner/BindingsTestRunner.js",
+ "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js",
+ "front_end/bindings_test_runner/module.json",
+ "front_end/bindings_test_runner/OverridesTestRunner.js",
+ "front_end/bindings_test_runner/PersistenceTestRunner.js",
+ "front_end/console_test_runner/ConsoleTestRunner.js",
+ "front_end/console_test_runner/module.json",
+ "front_end/coverage_test_runner/CoverageTestRunner.js",
+ "front_end/coverage_test_runner/module.json",
+ "front_end/cpu_profiler_test_runner/module.json",
+ "front_end/cpu_profiler_test_runner/ProfilerTestRunner.js",
+ "front_end/data_grid_test_runner/DataGridTestRunner.js",
+ "front_end/data_grid_test_runner/module.json",
+ "front_end/device_mode_test_runner/DeviceModeTestRunner.js",
+ "front_end/device_mode_test_runner/module.json",
+ "front_end/elements_test_runner/EditDOMTestRunner.js",
+ "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js",
+ "front_end/elements_test_runner/ElementsTestRunner.js",
+ "front_end/elements_test_runner/module.json",
+ "front_end/elements_test_runner/SetOuterHTMLTestRunner.js",
+ "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js",
+ "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js",
+ "front_end/extensions_test_runner/ExtensionsTestRunner.js",
+ "front_end/extensions_test_runner/module.json",
+ "front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js",
+ "front_end/heap_profiler_test_runner/module.json",
+ "front_end/integration_test_runner.html",
+ "front_end/integration_test_runner.js",
+ "front_end/integration_test_runner.json",
+ "front_end/layers_test_runner/LayersTestRunner.js",
+ "front_end/layers_test_runner/module.json",
+ "front_end/network_test_runner/module.json",
+ "front_end/network_test_runner/NetworkTestRunner.js",
+ "front_end/network_test_runner/ProductRegistryTestRunner.js",
+ "front_end/performance_test_runner/module.json",
+ "front_end/performance_test_runner/TimelineDataTestRunner.js",
+ "front_end/performance_test_runner/TimelineTestRunner.js",
+ "front_end/sdk_test_runner/module.json",
+ "front_end/sdk_test_runner/PageMockTestRunner.js",
+ "front_end/security_test_runner/module.json",
+ "front_end/security_test_runner/SecurityTestRunner.js",
+ "front_end/sources_test_runner/AutocompleteTestRunner.js",
+ "front_end/sources_test_runner/DebuggerTestRunner.js",
+ "front_end/sources_test_runner/EditorTestRunner.js",
+ "front_end/sources_test_runner/LiveEditTestRunner.js",
+ "front_end/sources_test_runner/module.json",
+ "front_end/sources_test_runner/SearchTestRunner.js",
+ "front_end/sources_test_runner/SourcesTestRunner.js",
+ "front_end/test_runner/module.json",
+ "front_end/test_runner/TestRunner.js",
]
- outputs = [
- "$resources_out_dir/.htaccess",
+
+ devtools_embedder_scripts = [
+ "front_end/devtools_compatibility.js",
+ "front_end/Tests.js",
]
-}
-copy("copy_inspector_images") {
- sources = devtools_image_files
- outputs = [
- "$resources_out_dir/Images/{{source_file_part}}",
+ devtools_emulated_devices_images = [
+ "front_end/emulated_devices/google-nexus-5-horizontal-default-1x.png",
+ "front_end/emulated_devices/google-nexus-5-horizontal-default-2x.png",
+ "front_end/emulated_devices/google-nexus-5-horizontal-keyboard-1x.png",
+ "front_end/emulated_devices/google-nexus-5-horizontal-keyboard-2x.png",
+ "front_end/emulated_devices/google-nexus-5-horizontal-navigation-1x.png",
+ "front_end/emulated_devices/google-nexus-5-horizontal-navigation-2x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-default-1x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-default-2x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-keyboard-1x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-keyboard-2x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-navigation-1x.png",
+ "front_end/emulated_devices/google-nexus-5-vertical-navigation-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-default-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-default-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-keyboard-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-keyboard-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-navigation-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-horizontal-navigation-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-default-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-default-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-keyboard-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-keyboard-2x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-navigation-1x.png",
+ "front_end/emulated_devices/google-nexus-5x-vertical-navigation-2x.png",
+ "front_end/emulated_devices/iPad-landscape.svg",
+ "front_end/emulated_devices/iPad-portrait.svg",
+ "front_end/emulated_devices/iPhone5-landscape.svg",
+ "front_end/emulated_devices/iPhone5-portrait.svg",
+ "front_end/emulated_devices/iPhone6-landscape.svg",
+ "front_end/emulated_devices/iPhone6-portrait.svg",
+ "front_end/emulated_devices/iPhone6Plus-landscape.svg",
+ "front_end/emulated_devices/iPhone6Plus-portrait.svg",
+ "front_end/emulated_devices/Nexus5X-landscape.svg",
+ "front_end/emulated_devices/Nexus5X-portrait.svg",
+ "front_end/emulated_devices/Nexus6P-landscape.svg",
+ "front_end/emulated_devices/Nexus6P-portrait.svg",
]
-}
-copy("copy_emulated_devices_images") {
- sources = devtools_emulated_devices_images
- outputs = [
- "$resources_out_dir/emulated_devices/{{source_file_part}}",
+ devtools_image_files = [
+ "front_end/Images/accelerometer-back.svg",
+ "front_end/Images/accelerometer-bottom.png",
+ "front_end/Images/accelerometer-front.svg",
+ "front_end/Images/accelerometer-left.png",
+ "front_end/Images/accelerometer-right.png",
+ "front_end/Images/accelerometer-top.png",
+ "front_end/Images/audits_logo.svg",
+ "front_end/Images/breakpoint.svg",
+ "front_end/Images/breakpointConditional.svg",
+ "front_end/Images/checkboxCheckmark.svg",
+ "front_end/Images/checker.png",
+ "front_end/Images/chevrons.svg",
+ "front_end/Images/chromeDisabledSelect.png",
+ "front_end/Images/chromeDisabledSelect_2x.png",
+ "front_end/Images/chromeLeft.png",
+ "front_end/Images/chromeMiddle.png",
+ "front_end/Images/chromeRight.png",
+ "front_end/Images/chromeSelect.png",
+ "front_end/Images/chromeSelect_2x.png",
+ "front_end/Images/errorWave.svg",
+ "front_end/Images/ic_info_black_18dp.svg",
+ "front_end/Images/ic_warning_black_18dp.svg",
+ "front_end/Images/largeIcons.svg",
+ "front_end/Images/mediumIcons.svg",
+ "front_end/Images/navigationControls.png",
+ "front_end/Images/navigationControls_2x.png",
+ "front_end/Images/nodeIcon.png",
+ "front_end/Images/popoverArrows.png",
+ "front_end/Images/profileGroupIcon.png",
+ "front_end/Images/profileIcon.png",
+ "front_end/Images/profileSmallIcon.png",
+ "front_end/Images/radioDot.png",
+ "front_end/Images/resizeDiagonal.png",
+ "front_end/Images/resizeDiagonal_2x.png",
+ "front_end/Images/resizeHorizontal.png",
+ "front_end/Images/resizeHorizontal_2x.png",
+ "front_end/Images/resizeVertical.png",
+ "front_end/Images/resizeVertical_2x.png",
+ "front_end/Images/resourceCSSIcon.png",
+ "front_end/Images/resourceDocumentIcon.png",
+ "front_end/Images/resourceDocumentIconSmall.png",
+ "front_end/Images/resourceJSIcon.png",
+ "front_end/Images/resourcePlainIcon.png",
+ "front_end/Images/resourcePlainIconSmall.png",
+ "front_end/Images/resourcesTimeGraphIcon.png",
+ "front_end/Images/searchNext.png",
+ "front_end/Images/searchPrev.png",
+ "front_end/Images/securityIcons.svg",
+ "front_end/Images/speech.png",
+ "front_end/Images/smallIcons.svg",
+ "front_end/Images/toolbarResizerVertical.png",
+ "front_end/Images/touchCursor.png",
+ "front_end/Images/touchCursor_2x.png",
+ "front_end/Images/treeoutlineTriangles.svg",
+ "front_end/Images/whatsnew.png",
]
-}
-action("generate_devtools_grd") {
- script = "scripts/build/generate_devtools_grd.py"
+ resources_out_dir = "$root_out_dir/resources/inspector"
- deps = [
- ":devtools_frontend_resources",
+ generated_scripts = [
+ "$resources_out_dir/InspectorBackendCommands.js",
+ "$resources_out_dir/SupportedCSSProperties.js",
]
- grd_files =
- generated_applications + generated_non_autostart_non_remote_modules +
- devtools_embedder_scripts +
- [ "$resources_out_dir/devtools_extension_api.js" ]
+ generated_aria_properties =
+ [ "$resources_out_dir/accessibility/ARIAProperties.js" ]
- # Bundle remote modules in ChromeOS.
- if (is_chromeos) {
- grd_files += generated_remote_modules + devtools_emulated_devices_images
- }
+ application_templates = [
+ "front_end/devtools_app.html",
+ "front_end/inspector.html",
+ "front_end/integration_test_runner.html",
+ "front_end/js_app.html",
+ "front_end/ndb_app.html",
+ "front_end/node_app.html",
+ "front_end/toolbox.html",
+ "front_end/worker_app.html",
+ ]
- inputs = grd_files + devtools_image_files
- outfile = "$root_gen_dir/devtools/devtools_resources.grd"
- outputs = [
- outfile,
+ copied_devtools_modules = [
+ "$resources_out_dir/console_counters/console_counters.js",
+ "$resources_out_dir/console_counters/WarningErrorCounter.js",
+ "$resources_out_dir/extensions/extensions.js",
+ "$resources_out_dir/extensions/ExtensionAPI.js",
+ "$resources_out_dir/extensions/ExtensionPanel.js",
+ "$resources_out_dir/extensions/ExtensionServer.js",
+ "$resources_out_dir/extensions/ExtensionTraceProvider.js",
+ "$resources_out_dir/extensions/ExtensionView.js",
+ "$resources_out_dir/browser_sdk/browser_sdk.js",
+ "$resources_out_dir/browser_sdk/LogManager.js",
+ "$resources_out_dir/persistence/persistence.js",
+ "$resources_out_dir/persistence/WorkspaceSettingsTab.js",
+ "$resources_out_dir/persistence/PlatformFileSystem.js",
+ "$resources_out_dir/persistence/PersistenceUtils.js",
+ "$resources_out_dir/persistence/PersistenceImpl.js",
+ "$resources_out_dir/persistence/PersistenceActions.js",
+ "$resources_out_dir/persistence/NetworkPersistenceManager.js",
+ "$resources_out_dir/persistence/IsolatedFileSystemManager.js",
+ "$resources_out_dir/persistence/IsolatedFileSystem.js",
+ "$resources_out_dir/persistence/FileSystemWorkspaceBinding.js",
+ "$resources_out_dir/persistence/EditFileSystemView.js",
+ "$resources_out_dir/persistence/Automapping.js",
+ "$resources_out_dir/components/components.js",
+ "$resources_out_dir/components/TargetDetachedDialog.js",
+ "$resources_out_dir/components/Reload.js",
+ "$resources_out_dir/components/Linkifier.js",
+ "$resources_out_dir/components/JSPresentationUtils.js",
+ "$resources_out_dir/components/ImagePreview.js",
+ "$resources_out_dir/components/DockController.js",
+ "$resources_out_dir/bindings/bindings.js",
+ "$resources_out_dir/bindings/TempFile.js",
+ "$resources_out_dir/bindings/StylesSourceMapping.js",
+ "$resources_out_dir/bindings/SASSSourceMapping.js",
+ "$resources_out_dir/bindings/ResourceUtils.js",
+ "$resources_out_dir/bindings/ResourceScriptMapping.js",
+ "$resources_out_dir/bindings/ResourceMapping.js",
+ "$resources_out_dir/bindings/PresentationConsoleMessageHelper.js",
+ "$resources_out_dir/bindings/NetworkProject.js",
+ "$resources_out_dir/bindings/LiveLocation.js",
+ "$resources_out_dir/bindings/FileUtils.js",
+ "$resources_out_dir/bindings/DefaultScriptMapping.js",
+ "$resources_out_dir/bindings/DebuggerWorkspaceBinding.js",
+ "$resources_out_dir/bindings/CSSWorkspaceBinding.js",
+ "$resources_out_dir/bindings/ContentProviderBasedProject.js",
+ "$resources_out_dir/bindings/CompilerScriptMapping.js",
+ "$resources_out_dir/bindings/BreakpointManager.js",
+ "$resources_out_dir/bindings/BlackboxManager.js",
+ "$resources_out_dir/workspace/workspace.js",
+ "$resources_out_dir/workspace/WorkspaceImpl.js",
+ "$resources_out_dir/workspace/UISourceCode.js",
+ "$resources_out_dir/workspace/FileManager.js",
+ "$resources_out_dir/services/services.js",
+ "$resources_out_dir/services/ServiceManager.js",
+ "$resources_out_dir/sdk/sdk.js",
+ "$resources_out_dir/sdk/TracingModel.js",
+ "$resources_out_dir/sdk/TracingManager.js",
+ "$resources_out_dir/sdk/TargetManager.js",
+ "$resources_out_dir/sdk/Target.js",
+ "$resources_out_dir/sdk/SourceMapManager.js",
+ "$resources_out_dir/sdk/SourceMap.js",
+ "$resources_out_dir/sdk/ServiceWorkerManager.js",
+ "$resources_out_dir/sdk/ServiceWorkerCacheModel.js",
+ "$resources_out_dir/sdk/ServerTiming.js",
+ "$resources_out_dir/sdk/SecurityOriginManager.js",
+ "$resources_out_dir/sdk/SDKModel.js",
+ "$resources_out_dir/sdk/Script.js",
+ "$resources_out_dir/sdk/ScreenCaptureModel.js",
+ "$resources_out_dir/sdk/RuntimeModel.js",
+ "$resources_out_dir/sdk/ResourceTreeModel.js",
+ "$resources_out_dir/sdk/Resource.js",
+ "$resources_out_dir/sdk/RemoteObject.js",
+ "$resources_out_dir/sdk/ProfileTreeModel.js",
+ "$resources_out_dir/sdk/PerformanceMetricsModel.js",
+ "$resources_out_dir/sdk/PaintProfiler.js",
+ "$resources_out_dir/sdk/OverlayModel.js",
+ "$resources_out_dir/sdk/NetworkRequest.js",
+ "$resources_out_dir/sdk/NetworkManager.js",
+ "$resources_out_dir/sdk/NetworkLog.js",
+ "$resources_out_dir/sdk/LogModel.js",
+ "$resources_out_dir/sdk/LayerTreeBase.js",
+ "$resources_out_dir/sdk/IsolateManager.js",
+ "$resources_out_dir/sdk/HeapProfilerModel.js",
+ "$resources_out_dir/sdk/HARLog.js",
+ "$resources_out_dir/sdk/FilmStripModel.js",
+ "$resources_out_dir/sdk/EmulationModel.js",
+ "$resources_out_dir/sdk/DOMModel.js",
+ "$resources_out_dir/sdk/DOMDebuggerModel.js",
+ "$resources_out_dir/sdk/DebuggerModel.js",
+ "$resources_out_dir/sdk/CSSStyleSheetHeader.js",
+ "$resources_out_dir/sdk/CSSStyleDeclaration.js",
+ "$resources_out_dir/sdk/CSSRule.js",
+ "$resources_out_dir/sdk/CSSProperty.js",
+ "$resources_out_dir/sdk/CSSModel.js",
+ "$resources_out_dir/sdk/CSSMetadata.js",
+ "$resources_out_dir/sdk/CSSMedia.js",
+ "$resources_out_dir/sdk/CSSMatchedStyles.js",
+ "$resources_out_dir/sdk/CPUProfilerModel.js",
+ "$resources_out_dir/sdk/CPUProfileDataModel.js",
+ "$resources_out_dir/sdk/CookieParser.js",
+ "$resources_out_dir/sdk/CookieModel.js",
+ "$resources_out_dir/sdk/CompilerSourceMappingContentProvider.js",
+ "$resources_out_dir/sdk/ConsoleModel.js",
+ "$resources_out_dir/sdk/Connections.js",
+ "$resources_out_dir/sdk/ChildTargetManager.js",
+ "$resources_out_dir/protocol/protocol.js",
+ "$resources_out_dir/protocol/NodeURL.js",
+ "$resources_out_dir/protocol/InspectorBackend.js",
+ "$resources_out_dir/host/host.js",
+ "$resources_out_dir/host/UserMetrics.js",
+ "$resources_out_dir/host/ResourceLoader.js",
+ "$resources_out_dir/host/Platform.js",
+ "$resources_out_dir/host/InspectorFrontendHost.js",
+ "$resources_out_dir/host/InspectorFrontendHostAPI.js",
+ "$resources_out_dir/dom_extension/DOMExtension.js",
+ "$resources_out_dir/root.js",
+ "$resources_out_dir/Runtime.js",
+ "$resources_out_dir/platform/utilities.js",
+ "$resources_out_dir/ui/ui.js",
+ "$resources_out_dir/common/common.js",
+ "$resources_out_dir/ui/ZoomManager.js",
+ "$resources_out_dir/ui/XWidget.js",
+ "$resources_out_dir/ui/XLink.js",
+ "$resources_out_dir/ui/XElement.js",
+ "$resources_out_dir/ui/Widget.js",
+ "$resources_out_dir/ui/View.js",
+ "$resources_out_dir/ui/ViewManager.js",
+ "$resources_out_dir/ui/UIUtils.js",
+ "$resources_out_dir/ui/Treeoutline.js",
+ "$resources_out_dir/ui/Tooltip.js",
+ "$resources_out_dir/ui/Toolbar.js",
+ "$resources_out_dir/ui/ThrottledWidget.js",
+ "$resources_out_dir/ui/TextPrompt.js",
+ "$resources_out_dir/ui/TextEditor.js",
+ "$resources_out_dir/ui/TargetCrashedScreen.js",
+ "$resources_out_dir/ui/TabbedPane.js",
+ "$resources_out_dir/ui/SyntaxHighlighter.js",
+ "$resources_out_dir/ui/SuggestBox.js",
+ "$resources_out_dir/ui/SplitWidget.js",
+ "$resources_out_dir/ui/SoftDropDown.js",
+ "$resources_out_dir/ui/SoftContextMenu.js",
+ "$resources_out_dir/ui/ShortcutsScreen.js",
+ "$resources_out_dir/ui/ShortcutRegistry.js",
+ "$resources_out_dir/ui/SettingsUI.js",
+ "$resources_out_dir/ui/SegmentedButton.js",
+ "$resources_out_dir/ui/SearchableView.js",
+ "$resources_out_dir/ui/RootView.js",
+ "$resources_out_dir/ui/ResizerWidget.js",
+ "$resources_out_dir/ui/ReportView.js",
+ "$resources_out_dir/ui/RemoteDebuggingTerminatedScreen.js",
+ "$resources_out_dir/ui/ProgressIndicator.js",
+ "$resources_out_dir/ui/PopoverHelper.js",
+ "$resources_out_dir/ui/Panel.js",
+ "$resources_out_dir/ui/ListWidget.js",
+ "$resources_out_dir/ui/ListModel.js",
+ "$resources_out_dir/ui/ListControl.js",
+ "$resources_out_dir/ui/KeyboardShortcut.js",
+ "$resources_out_dir/ui/InspectorView.js",
+ "$resources_out_dir/ui/InplaceEditor.js",
+ "$resources_out_dir/ui/Infobar.js",
+ "$resources_out_dir/ui/Icon.js",
+ "$resources_out_dir/ui/HistoryInput.js",
+ "$resources_out_dir/ui/GlassPane.js",
+ "$resources_out_dir/ui/Geometry.js",
+ "$resources_out_dir/ui/Fragment.js",
+ "$resources_out_dir/ui/ForwardedInputEventHandler.js",
+ "$resources_out_dir/ui/FilterSuggestionBuilder.js",
+ "$resources_out_dir/ui/FilterBar.js",
+ "$resources_out_dir/ui/EmptyWidget.js",
+ "$resources_out_dir/ui/DropTarget.js",
+ "$resources_out_dir/ui/Dialog.js",
+ "$resources_out_dir/ui/ContextMenu.js",
+ "$resources_out_dir/ui/Context.js",
+ "$resources_out_dir/ui/ARIAUtils.js",
+ "$resources_out_dir/ui/ActionRegistry.js",
+ "$resources_out_dir/ui/Action.js",
+ "$resources_out_dir/ui/ActionDelegate.js",
+ "$resources_out_dir/ui/ContextFlavorListener.js",
+ "$resources_out_dir/common/App.js",
+ "$resources_out_dir/common/AppProvider.js",
+ "$resources_out_dir/common/CharacterIdMap.js",
+ "$resources_out_dir/common/Color.js",
+ "$resources_out_dir/common/ContentProvider.js",
+ "$resources_out_dir/common/EventTarget.js",
+ "$resources_out_dir/common/JavaScriptMetaData.js",
+ "$resources_out_dir/common/Linkifier.js",
+ "$resources_out_dir/common/Object.js",
+ "$resources_out_dir/common/Console.js",
+ "$resources_out_dir/common/ParsedURL.js",
+ "$resources_out_dir/common/Progress.js",
+ "$resources_out_dir/common/QueryParamHandler.js",
+ "$resources_out_dir/common/ResourceType.js",
+ "$resources_out_dir/common/Revealer.js",
+ "$resources_out_dir/common/Runnable.js",
+ "$resources_out_dir/common/SegmentedRange.js",
+ "$resources_out_dir/common/Settings.js",
+ "$resources_out_dir/common/StaticContentProvider.js",
+ "$resources_out_dir/common/StringOutputStream.js",
+ "$resources_out_dir/common/TextDictionary.js",
+ "$resources_out_dir/common/Throttler.js",
+ "$resources_out_dir/common/Trie.js",
+ "$resources_out_dir/common/UIString.js",
+ "$resources_out_dir/common/Worker.js",
]
- relative_path_dirs = [
- resources_out_dir,
- "front_end",
+ generated_applications = [
+ "$resources_out_dir/audits_worker.js",
+ "$resources_out_dir/devtools_app.html",
+ "$resources_out_dir/devtools_app.js",
+ "$resources_out_dir/formatter_worker.js",
+ "$resources_out_dir/heap_snapshot_worker.js",
+ "$resources_out_dir/inspector.html",
+ "$resources_out_dir/inspector.js",
+ "$resources_out_dir/js_app.html",
+ "$resources_out_dir/js_app.js",
+ "$resources_out_dir/node_app.html",
+ "$resources_out_dir/node_app.js",
+ "$resources_out_dir/shell.js",
+ "$resources_out_dir/toolbox.html",
+ "$resources_out_dir/toolbox.js",
+ "$resources_out_dir/worker_app.html",
+ "$resources_out_dir/worker_app.js",
]
- args = rebase_path(grd_files, root_build_dir) + [ "--relative_path_dirs" ] +
- rebase_path(relative_path_dirs, root_build_dir) +
- [
- "--images",
- rebase_path("front_end/Images", root_build_dir),
- "--output",
- rebase_path(outfile, root_build_dir),
- ]
-}
+ generated_non_autostart_non_remote_modules = [
+ "$resources_out_dir/animation/animation_module.js",
+ "$resources_out_dir/audits/audits_module.js",
+ "$resources_out_dir/browser_debugger/browser_debugger_module.js",
+ "$resources_out_dir/changes/changes_module.js",
+ "$resources_out_dir/protocol_monitor/protocol_monitor_module.js",
+ "$resources_out_dir/css_overview/css_overview_module.js",
+ "$resources_out_dir/cm/cm_module.js",
+ "$resources_out_dir/color_picker/color_picker_module.js",
+ "$resources_out_dir/console/console_module.js",
+ "$resources_out_dir/cookie_table/cookie_table_module.js",
+ "$resources_out_dir/coverage/coverage_module.js",
+ "$resources_out_dir/data_grid/data_grid_module.js",
+ "$resources_out_dir/devices/devices_module.js",
+ "$resources_out_dir/diff/diff_module.js",
+ "$resources_out_dir/elements/elements_module.js",
+ "$resources_out_dir/event_listeners/event_listeners_module.js",
+ "$resources_out_dir/formatter/formatter_module.js",
+ "$resources_out_dir/har_importer/har_importer_module.js",
+ "$resources_out_dir/heap_snapshot_model/heap_snapshot_model_module.js",
+ "$resources_out_dir/help/help_module.js",
+ "$resources_out_dir/inline_editor/inline_editor_module.js",
+ "$resources_out_dir/javascript_metadata/javascript_metadata_module.js",
+ "$resources_out_dir/js_profiler/js_profiler_module.js",
+ "$resources_out_dir/layer_viewer/layer_viewer_module.js",
+ "$resources_out_dir/layers/layers_module.js",
+ "$resources_out_dir/media/media_module.js",
+ "$resources_out_dir/network/network_module.js",
+ "$resources_out_dir/node_debugger/node_debugger_module.js",
+ "$resources_out_dir/object_ui/object_ui_module.js",
+ "$resources_out_dir/perf_ui/perf_ui_module.js",
+ "$resources_out_dir/performance_monitor/performance_monitor_module.js",
+ "$resources_out_dir/profiler/profiler_module.js",
+ "$resources_out_dir/quick_open/quick_open_module.js",
+ "$resources_out_dir/resources/resources_module.js",
+ "$resources_out_dir/search/search_module.js",
+ "$resources_out_dir/security/security_module.js",
+ "$resources_out_dir/settings/settings_module.js",
+ "$resources_out_dir/snippets/snippets_module.js",
+ "$resources_out_dir/source_frame/source_frame_module.js",
+ "$resources_out_dir/sources/sources_module.js",
+ "$resources_out_dir/text_editor/text_editor_module.js",
+ "$resources_out_dir/timeline_model/timeline_model_module.js",
+ "$resources_out_dir/timeline/timeline_module.js",
+ "$resources_out_dir/web_audio/web_audio_module.js",
+ "$resources_out_dir/workspace_diff/workspace_diff_module.js",
+ ]
-action("devtools_extension_api") {
- script = "scripts/build/generate_devtools_extension_api.py"
+ generated_remote_modules = [
+ "$resources_out_dir/accessibility/accessibility_module.js",
+ "$resources_out_dir/audits_worker/audits_worker_module.js",
+ "$resources_out_dir/cm_modes/cm_modes_module.js",
+ "$resources_out_dir/dagre_layout/dagre_layout_module.js",
+ "$resources_out_dir/emulated_devices/emulated_devices_module.js",
+ "$resources_out_dir/product_registry_impl/product_registry_impl_module.js",
+ ]
- devtools_extension_api_files = [ "front_end/extensions/ExtensionAPI.js" ]
- inputs = devtools_extension_api_files
- outputs = [
- "$resources_out_dir/devtools_extension_api.js",
+ generated_test_modules = [
+ "$resources_out_dir/accessibility_test_runner/accessibility_test_runner_module.js",
+ "$resources_out_dir/application_test_runner/application_test_runner_module.js",
+ "$resources_out_dir/audits_test_runner/audits_test_runner_module.js",
+ "$resources_out_dir/axe_core_test_runner/axe_core_test_runner_module.js",
+ "$resources_out_dir/bindings_test_runner/bindings_test_runner_module.js",
+ "$resources_out_dir/console_test_runner/console_test_runner_module.js",
+ "$resources_out_dir/coverage_test_runner/coverage_test_runner_module.js",
+ "$resources_out_dir/cpu_profiler_test_runner/cpu_profiler_test_runner_module.js",
+ "$resources_out_dir/data_grid_test_runner/data_grid_test_runner_module.js",
+ "$resources_out_dir/device_mode_test_runner/device_mode_test_runner_module.js",
+ "$resources_out_dir/elements_test_runner/elements_test_runner_module.js",
+ "$resources_out_dir/extensions_test_runner/extensions_test_runner_module.js",
+ "$resources_out_dir/heap_profiler_test_runner/heap_profiler_test_runner_module.js",
+ "$resources_out_dir/heap_snapshot_worker/heap_snapshot_worker_module.js",
+ "$resources_out_dir/integration_test_runner.html",
+ "$resources_out_dir/integration_test_runner.js",
+ "$resources_out_dir/layers_test_runner/layers_test_runner_module.js",
+ "$resources_out_dir/network_test_runner/network_test_runner_module.js",
+ "$resources_out_dir/performance_test_runner/performance_test_runner_module.js",
+ "$resources_out_dir/sdk_test_runner/sdk_test_runner_module.js",
+ "$resources_out_dir/security_test_runner/security_test_runner_module.js",
+ "$resources_out_dir/sources_test_runner/sources_test_runner_module.js",
]
- args = rebase_path(outputs, root_build_dir) +
- rebase_path(devtools_extension_api_files, root_build_dir)
-}
+ devtools_applications = [
+ "audits_worker",
+ "devtools_app",
+ "formatter_worker",
+ "heap_snapshot_worker",
+ "inspector",
+ "integration_test_runner",
+ "js_app",
+ "ndb_app",
+ "node_app",
+ "shell",
+ "toolbox",
+ "worker_app",
+ ]
-action("supported_css_properties") {
- script = "scripts/build/generate_supported_css.py"
+ #-------------------------------------------------------------------------------
- inputs = [
- "../core/css/css_properties.json5",
- ]
+ visibility = [ "//third_party/blink/*" ]
- outputs = [
- "$resources_out_dir/SupportedCSSProperties.js",
+ group("devtools_all_files") {
+ data = all_devtools_files + all_devtools_modules
+ deps = [
+ ":devtools_frontend_resources_data",
+ ]
+ }
+
+ devtools_frontend_resources_deps = [
+ ":aria_properties",
+ ":build_release_devtools",
+ ":copy_embedder_scripts",
+ ":copy_emulated_devices_images",
+ ":copy_htaccess",
+ ":copy_inspector_images",
+ ":copy_lighthouse_locale_files",
+ ":devtools_extension_api",
+ ":frontend_protocol_sources",
+ ":supported_css_properties",
+ ":copy_devtools_modules",
]
- args =
- rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
-}
+ if (debug_devtools) {
+ devtools_frontend_resources_deps += [
+ ":build_debug_devtools",
+ ":copy_aria_properties",
+ ":copy_generated_scripts",
+ ]
+ }
-action("aria_properties") {
- script = "scripts/build/generate_aria.py"
+ group("devtools_frontend_resources") {
+ public_deps = devtools_frontend_resources_deps
+ }
- inputs = [
- "../core/html/aria_properties.json5",
- ]
+ # Do not use this unless you need unpacked devtools at runtime.
+ group("devtools_frontend_resources_data") {
+ data_deps = devtools_frontend_resources_deps
+ }
- outputs = [
- "$resources_out_dir/accessibility/ARIAProperties.js",
- ]
+ copy("copy_embedder_scripts") {
+ sources = devtools_embedder_scripts
+ outputs = [
+ "$resources_out_dir/{{source_file_part}}",
+ ]
+ }
- args =
- rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
-}
+ copy("copy_htaccess") {
+ sources = [
+ "htaccess",
+ ]
+ outputs = [
+ "$resources_out_dir/.htaccess",
+ ]
+ }
-action("frontend_protocol_sources") {
- script = "scripts/build/code_generator_frontend.py"
- deps = [
- "../core/inspector:protocol_version",
- ]
- inputs = [
- "$blink_core_output_dir/inspector/protocol.json",
- ]
- outputs = [
- "$resources_out_dir/InspectorBackendCommands.js",
- ]
+ copy("copy_inspector_images") {
+ sources = devtools_image_files
+ outputs = [
+ "$resources_out_dir/Images/{{source_file_part}}",
+ ]
+ }
- args = rebase_path(inputs, root_build_dir) + [
- "--output_js_dir",
- rebase_path(resources_out_dir, root_build_dir),
- ]
-}
+ copy("copy_emulated_devices_images") {
+ sources = devtools_emulated_devices_images
+ outputs = [
+ "$resources_out_dir/emulated_devices/{{source_file_part}}",
+ ]
+ }
-action("build_release_devtools") {
- script = "scripts/build/build_release_applications.py"
+ copy("copy_lighthouse_locale_files") {
+ sources = lighthouse_locale_files
+ outputs = [
+ "$resources_out_dir/audits_worker/lighthouse/locales/{{source_file_part}}",
+ ]
+ }
- deps = [
- ":aria_properties",
- ":frontend_protocol_sources",
- ":supported_css_properties",
- ]
+ action("generate_devtools_grd") {
+ script = "scripts/build/generate_devtools_grd.py"
- helper_scripts = [
- "scripts/build/modular_build.py",
- "scripts/build/rjsmin.py",
- ]
+ deps = [
+ ":devtools_frontend_resources",
+ ]
- inputs = helper_scripts + all_devtools_files + devtools_test_files +
- generated_scripts + generated_aria_properties + application_templates
- outputs =
- generated_applications + generated_non_autostart_non_remote_modules +
- generated_remote_modules + generated_test_modules
-
- args = devtools_applications + [
- "--input_path",
- rebase_path("front_end", root_build_dir),
- "--output_path",
- rebase_path(resources_out_dir, root_build_dir),
- ]
-}
+ grd_files =
+ copied_devtools_modules + generated_applications +
+ generated_non_autostart_non_remote_modules + devtools_embedder_scripts +
+ [
+ "$resources_out_dir/devtools_extension_api.js",
+ "$resources_out_dir/SupportedCSSProperties.js",
+ "$resources_out_dir/InspectorBackendCommands.js",
+ ]
+
+ # Bundle remote modules in ChromeOS.
+ if (is_chromeos) {
+ grd_files += generated_remote_modules + devtools_emulated_devices_images +
+ lighthouse_locale_files
+ }
+
+ inputs = grd_files + devtools_image_files
+ outfile = "$root_gen_dir/devtools/devtools_resources.grd"
+ outputs = [
+ outfile,
+ ]
+
+ relative_path_dirs = [
+ resources_out_dir,
+ "front_end",
+ ]
+
+ args = rebase_path(grd_files, root_build_dir) + [ "--relative_path_dirs" ] +
+ rebase_path(relative_path_dirs, root_build_dir) +
+ [
+ "--images",
+ rebase_path("front_end/Images", root_build_dir),
+ "--output",
+ rebase_path(outfile, root_build_dir),
+ ]
+ }
+
+ action("devtools_extension_api") {
+ script = "scripts/build/generate_devtools_extension_api.py"
-if (debug_devtools) {
- resources_out_debug_dir = "$root_out_dir/resources/inspector/debug"
+ devtools_extension_api_files = [ "front_end/extensions/ExtensionAPI.js" ]
+ inputs = devtools_extension_api_files
+ outputs = [
+ "$resources_out_dir/devtools_extension_api.js",
+ ]
+
+ args = rebase_path(outputs, root_build_dir) +
+ rebase_path(devtools_extension_api_files, root_build_dir)
+ }
- action("build_debug_devtools") {
- script = "scripts/build/build_debug_applications.py"
+ action("supported_css_properties") {
+ script = "scripts/build/generate_supported_css.py"
+
+ inputs = [
+ "//third_party/blink/renderer/core/css/css_properties.json5",
+ ]
- inputs = all_devtools_files + application_templates
outputs = [
- "$resources_out_debug_dir/devtools_app.html",
- "$resources_out_debug_dir/inspector.html",
- "$resources_out_debug_dir/integration_test_runner.html",
- "$resources_out_debug_dir/js_app.html",
- "$resources_out_debug_dir/ndb_app.html",
- "$resources_out_debug_dir/node_app.html",
- "$resources_out_debug_dir/toolbox.html",
- "$resources_out_debug_dir/worker_app.html",
+ "$resources_out_dir/SupportedCSSProperties.js",
]
- args = [
- "--input_path",
- rebase_path("front_end", root_build_dir),
- "--output_path",
- rebase_path(resources_out_debug_dir, root_build_dir),
+ args = rebase_path(inputs, root_build_dir) +
+ rebase_path(outputs, root_build_dir)
+ }
+
+ action("aria_properties") {
+ script = "scripts/build/generate_aria.py"
+
+ inputs = [
+ "//third_party/blink/renderer/core/html/aria_properties.json5",
+ ]
+
+ outputs = [
+ "$resources_out_dir/accessibility/ARIAProperties.js",
]
+
+ args = rebase_path(inputs, root_build_dir) +
+ rebase_path(outputs, root_build_dir)
}
- copy("copy_generated_scripts") {
+ action("frontend_protocol_sources") {
+ script = "scripts/build/code_generator_frontend.py"
deps = [
- ":build_debug_devtools",
- ":frontend_protocol_sources",
- ":supported_css_properties",
+ "//third_party/blink/renderer/core/inspector:protocol_version",
+ ]
+ inputs = [
+ "$blink_core_output_dir/inspector/protocol.json",
]
- sources = generated_scripts
outputs = [
- "$resources_out_debug_dir/{{source_file_part}}",
+ "$resources_out_dir/InspectorBackendCommands.js",
]
+
+ args = rebase_path(inputs, root_build_dir) + [
+ "--output_js_dir",
+ rebase_path(resources_out_dir, root_build_dir),
+ ]
}
- copy("copy_aria_properties") {
+ action("build_release_devtools") {
+ script = "scripts/build/build_release_applications.py"
+
deps = [
":aria_properties",
- ":build_debug_devtools",
+ ":frontend_protocol_sources",
+ ":supported_css_properties",
]
- sources = generated_aria_properties
+ helper_scripts = [
+ "scripts/build/modular_build.py",
+ "scripts/build/rjsmin.py",
+ ]
- outputs = [
- "$resources_out_debug_dir/accessibility/{{source_file_part}}",
+ inputs =
+ helper_scripts + all_devtools_files + devtools_test_files +
+ generated_scripts + generated_aria_properties + application_templates
+ outputs =
+ generated_applications + generated_non_autostart_non_remote_modules +
+ generated_remote_modules + generated_test_modules
+
+ args = devtools_applications + [
+ "--input_path",
+ rebase_path("front_end", root_build_dir),
+ "--output_path",
+ rebase_path(resources_out_dir, root_build_dir),
+ ]
+ }
+
+ action("copy_devtools_modules") {
+ script = "scripts/build/copy_devtools_modules.py"
+
+ deps = [
+ ":build_release_devtools",
]
+
+ inputs = all_devtools_modules
+ outputs = copied_devtools_modules
+
+ args = all_devtools_modules + [
+ "--input_path",
+ rebase_path(".", root_build_dir),
+ "--output_path",
+ rebase_path(resources_out_dir, root_build_dir),
+ ]
}
-}
-group("devtools_closure_compile") {
- data = [
- # Needed for isolate script to execute.
- "front_end/",
- "scripts/build/",
- "scripts/closure/",
- "scripts/compile_frontend.py",
- "scripts/dependency_preprocessor.py",
- "scripts/jsdoc_validator/",
- "scripts/special_case_namespaces.json",
- "scripts/utils.py",
- "//testing/scripts/common.py",
- "//testing/scripts/run_devtools_check.py",
- "//testing/xvfb.py",
- "//third_party/blink/renderer/core/inspector/browser_protocol.pdl",
- "//third_party/inspector_protocol/pdl.py",
- "//v8/include/js_protocol.pdl",
- ]
-}
+ if (debug_devtools) {
+ resources_out_debug_dir = "$root_out_dir/resources/inspector/debug"
+
+ action("build_debug_devtools") {
+ script = "scripts/build/build_debug_applications.py"
+
+ inputs = all_devtools_files + application_templates
+ outputs = [
+ "$resources_out_debug_dir/devtools_app.html",
+ "$resources_out_debug_dir/inspector.html",
+ "$resources_out_debug_dir/integration_test_runner.html",
+ "$resources_out_debug_dir/js_app.html",
+ "$resources_out_debug_dir/ndb_app.html",
+ "$resources_out_debug_dir/node_app.html",
+ "$resources_out_debug_dir/toolbox.html",
+ "$resources_out_debug_dir/worker_app.html",
+ ]
+
+ args = [
+ "--input_path",
+ rebase_path("front_end", root_build_dir),
+ "--output_path",
+ rebase_path(resources_out_debug_dir, root_build_dir),
+ ]
+ }
-if (is_linux && !is_chromeos) {
- group("devtools_eslint") {
+ copy("copy_generated_scripts") {
+ deps = [
+ ":build_debug_devtools",
+ ":frontend_protocol_sources",
+ ":supported_css_properties",
+ ]
+ sources = generated_scripts
+ outputs = [
+ "$resources_out_debug_dir/{{source_file_part}}",
+ ]
+ }
+
+ copy("copy_aria_properties") {
+ deps = [
+ ":aria_properties",
+ ":build_debug_devtools",
+ ]
+
+ sources = generated_aria_properties
+
+ outputs = [
+ "$resources_out_debug_dir/accessibility/{{source_file_part}}",
+ ]
+ }
+ }
+
+ group("devtools_closure_compile") {
data = [
# Needed for isolate script to execute.
- ".eslintignore",
- ".eslintrc.js",
"front_end/",
- "scripts/lint_javascript.py",
- "scripts/local_node.py",
+ "scripts/build/",
+ "scripts/closure/",
+ "scripts/compile_frontend.py",
+ "scripts/dependency_preprocessor.py",
+ "scripts/jsdoc_validator/",
+ "scripts/special_case_namespaces.json",
+ "scripts/utils.py",
"//testing/scripts/common.py",
"//testing/scripts/run_devtools_check.py",
"//testing/xvfb.py",
- "//third_party/devtools-node-modules/",
- "//third_party/node/node.py",
- "//third_party/node/linux/node-linux-x64/",
+ "//third_party/blink/renderer/core/inspector/browser_protocol.pdl",
+ "//third_party/inspector_protocol/pdl.py",
+ "//v8/include/js_protocol.pdl",
]
}
+
+ if (is_linux && !is_chromeos) {
+ group("devtools_eslint") {
+ data = [
+ # Needed for isolate script to execute.
+ ".eslintignore",
+ ".eslintrc.js",
+ "front_end/",
+ "scripts/lint_javascript.py",
+ "scripts/devtools_paths.py",
+ "//testing/scripts/common.py",
+ "//testing/scripts/run_devtools_check.py",
+ "//testing/xvfb.py",
+ "//third_party/devtools-node-modules/",
+ "//third_party/node/node.py",
+ "//third_party/node/linux/node-linux-x64/",
+ ]
+ }
+ }
}
diff --git a/chromium/third_party/blink/renderer/devtools/OWNERS b/chromium/third_party/blink/renderer/devtools/OWNERS
index 147b931745f..f49aea94794 100644
--- a/chromium/third_party/blink/renderer/devtools/OWNERS
+++ b/chromium/third_party/blink/renderer/devtools/OWNERS
@@ -1,6 +1,11 @@
+aerotwist@chromium.org
+bmeurer@chromium.org
dgozman@chromium.org
-pfeldman@chromium.org
-lushnikov@chromium.org
einbinder@chromium.org
+lomitch@microsoft.com
luoe@chromium.org
+lushnikov@chromium.org
+pfeldman@chromium.org
+yangguo@chromium.org
+
per-file BUILD.gn=*
diff --git a/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py b/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py
index 1166bdb4bb6..5c3c6ae7bb3 100644
--- a/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py
+++ b/chromium/third_party/blink/renderer/devtools/PRESUBMIT.py
@@ -25,7 +25,7 @@
# 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.
-"""DevTools JSDoc validator presubmit script
+"""DevTools presubmit script
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
@@ -50,7 +50,7 @@ def _CheckFormat(input_api, output_api):
original_sys_path = sys.path
try:
sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")]
- import local_node
+ import devtools_paths
finally:
sys.path = original_sys_path
@@ -77,11 +77,7 @@ def _CheckFormat(input_api, output_api):
# Use eslint to autofix the braces.
# Also fix semicolon to avoid confusing clang-format.
- eslint_process = popen([
- local_node.node_path(), local_node.eslint_path(),
- '--no-eslintrc', '--fix', '--env=es6', '--parser-options=ecmaVersion:9',
- '--rule={"curly": [2, "multi-or-nest", "consistent"], "semi": 2}'
- ] + affected_files)
+ eslint_process = popen([devtools_paths.node_path(), devtools_paths.eslint_path(), '--config', '.eslintrc.js', '--fix'] + affected_files)
eslint_process.communicate()
# Need to run clang-format again to align the braces
@@ -117,18 +113,14 @@ def _CheckDevtoolsLocalization(input_api, output_api): # pylint: disable=invali
def _CheckDevtoolsStyle(input_api, output_api):
- affected_front_end_files = _getAffectedFrontEndFiles(input_api)
- if len(affected_front_end_files) > 0:
- lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "lint_javascript.py")
- process = input_api.subprocess.Popen(
- [input_api.python_executable, lint_path] + affected_front_end_files,
- stdout=input_api.subprocess.PIPE,
- stderr=input_api.subprocess.STDOUT)
- out, _ = process.communicate()
- if process.returncode != 0:
- return [output_api.PresubmitError(out)]
- return [output_api.PresubmitNotifyResult(out)]
- return []
+ lint_path = input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts", "lint_javascript.py")
+ process = input_api.subprocess.Popen([input_api.python_executable, lint_path],
+ stdout=input_api.subprocess.PIPE,
+ stderr=input_api.subprocess.STDOUT)
+ out, _ = process.communicate()
+ if process.returncode != 0:
+ return [output_api.PresubmitError(out)]
+ return [output_api.PresubmitNotifyResult(out)]
def _CompileDevtoolsFrontend(input_api, output_api):
@@ -236,11 +228,11 @@ def _checkWithNodeScript(input_api, output_api, script_path, script_arguments=No
original_sys_path = sys.path
try:
sys.path = sys.path + [input_api.os_path.join(input_api.PresubmitLocalPath(), "scripts")]
- import local_node
+ import devtools_paths
finally:
sys.path = original_sys_path
- node_path = local_node.node_path()
+ node_path = devtools_paths.node_path()
if script_arguments is None:
script_arguments = []
diff --git a/chromium/third_party/blink/renderer/devtools/docs/langpacks/README.md b/chromium/third_party/blink/renderer/devtools/docs/langpacks/README.md
new file mode 100644
index 00000000000..065125b528d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/docs/langpacks/README.md
@@ -0,0 +1,6 @@
+Localization FAQs
+
+- [How to add a localizable string?](adding_strings.md)
+- [What are the localization APIs?](localization_apis.md)
+- [How to add descriptive information to GRDP messages?](grdp_files.md)
+- [How to prevent specific terms being localized?](locked_terms.md) \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/docs/langpacks/adding_strings.md b/chromium/third_party/blink/renderer/devtools/docs/langpacks/adding_strings.md
new file mode 100644
index 00000000000..471581e0a49
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/docs/langpacks/adding_strings.md
@@ -0,0 +1,116 @@
+When you introduce a new UI string or modify an existing one that will be displayed to the users, or remove a string that is localized, follow these steps so that it can be localized.
+
+**Table of Contents**
+- [Adding a string](#adding-a-string)
+ - [Frontend source code](#frontend-source-code)
+ - [Frontend GRDP file](#frontend-grdp-file)
+- [Modifying a string](#modifying-a-string)
+- [Removing a string](#removing-a-string)
+- [Adding a GRD file](#adding-a-grd-file)
+
+## Adding a string
+Before proceeding, make sure you know the different [[localization APIs|]] and know which one you should use.
+
+### Frontend source code
+
+1. Wrap your string with the appropriate localization API for your use case, for example, `` ls`Add breakpoint` ``.
+
+2. If your string contains variables, consider the following cases:
+ 1. Directly substitute variables, as how you would normally inject variables into a template literal with `${}`, **only if** your variable satisfies one of the following
+
+ 1. If the variable is a number, e.g. `` ls`${renderedWidth} \xd7 ${renderedHeight} pixels` ``
+ 2. or if your variable is a string that likely doesn't need to be localized (for example, DOM, or a url),
+
+ 3. or if it's a string that is already localized somewhere (for example, Console and other tool titles)
+
+ 2. Localize your variable with `ls`, then do variable substitution in your template literal, for example
+
+ ```javascript
+ const title = ls`New Tool`
+ const message = ls`Click ${title} for more details`
+ ```
+
+3. Make sure your string is localizable:
+
+ 1. Do not assume word order by using concatenation. Use the whole string.
+ - ❌ `` ls`Add` + ls`breakpoint` `` --> ✅ `` ls`Add breakpoint` ``
+ 2. Variable substitution over concatenation. This is so that the translators can adjust variable order based on what works in another language. For example:
+ ```javascript
+ // ❌
+ ls`Check ` + title + ls` for more information.`
+ // ✅
+ ls`Check ${title} for more information.`
+ ```
+ 3. Only inject variables when necessary, i.e., do not extract common substrings from similar messages.
+ - Example: <https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_content_best_practices#Idiom>
+ 4. Prefer simple strings whenever possible. Try to move conditionals out of the string. For example:
+
+ ```javascript
+ // ❌
+ ls`Reveal${destination ? ls` in ${destination}` : ``}`
+ // ✅
+ destination ? ls`Reveal in ${destination}` : ls`Reveal`
+ ```
+ 5. When your string contains plurals, make sure you pluralize by pulling conditionals outside of the string. This is because in other languages, plurals can be different from English ones. For example:
+
+ ```javascript
+ // ❌
+ ls`${count} insertion${count !== 1 ? `s` : ``}`
+ // ✅
+ if (count === 0)
+ ls`No insertion`
+ else if (count === 1)
+ ls`1 insertion`
+ else
+ ls`${count} insertions`
+ ```
+ 6. In general, a complete sentence is preferred. This usually increases the localizability of a string, as the translators have the context of the string. For example:
+ ```javascript
+ // ❌
+ let description = ls`first part`
+ if (condition)
+ description += ls` second part`
+ // ✅
+ let description
+ if (condition)
+ description = ls`first part second part`
+ else
+ description = ls`first part`
+ ```
+ 7. If your string contains leading or trailing white space, it's usually an indication that it's half of a sentence. This decreases localizability as it's essentially concatenating. Modify it so that it doesn't contain leading or trailing white space anymore if you can.
+ 8. Do not use nested template literals. This is due to a limitation of the release minifier. For more info see https://crbug.com/973285.
+ ```javascript
+ // ❌
+ UI.Fragment.build`<a>${ls`Learn more`}</a>`
+ // ✅
+ const link = ls`Learn more`
+ UI.Fragment.build`<a>${link}</a>`
+ ```
+ 9. What kinds of terms should be localized?
+ ```
+ // ❌
+ Numbers: 1, 1.23, 1.2e3, etc.
+ Application data: error codes, enums, database names, rgba, urls, etc.
+ // ✅
+ Words and sentences
+ Punctuation
+ Units of measurement: kb/s, mph, etc.
+ ```
+
+### Frontend GRDP file
+1. Run any of the following commands to have new strings automatically added to the corresponding grdp file:
+ - `git cl presubmit --upload`, or
+ - `node scripts/check_localizable_resources.js --autofix` under the devtools folder
+2. Manually add information to the new grdp message. See [[Adding Descriptive Information to GRDP Messages|]].
+
+## Modifying a string
+Follow the above steps.
+
+## Removing a string
+Just remove the string from the frontend and it will be automatically removed by the presubmit script.
+
+## Adding a new GRD file
+This is a rare case, but if a new GRD file is introduced, please read the guidance here:
+* https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide
+* https://cs.chromium.org/chromium/src/tools/gritsettings/README.md.
+ * Note that you need to add the grd file to translation_expecations.pyl. If you don't an error will occur when Google's translation pipeline runs. \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/docs/langpacks/grdp_files.md b/chromium/third_party/blink/renderer/devtools/docs/langpacks/grdp_files.md
new file mode 100644
index 00000000000..89d66ba050d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/docs/langpacks/grdp_files.md
@@ -0,0 +1,41 @@
+Descriptive information in .grdp messages can improve localizability as it will provide more context to the translators.
+
+Types of descriptive information:
+- [Description](#Description)
+- [Placeholder name and example](#Placeholder)
+
+## Description
+**Good description**:
+```html
+ <message name="IDS_DEVTOOLS_04efed137e5da6d8b456e83d87915f16" desc="Tooltip text that appears when hovering over the 'Focusable' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
+ If true, this element can receive focus.
+ </message>
+```
+
+**Bad description**:
+```html
+ <message name="IDS_DEVTOOLS_04efed137e5da6d8b456e83d87915f16" desc="Elements pane 'Focusable' tooltip">
+ If true, this element can receive focus.
+ </message>
+```
+
+### Process to add descriptions
+1. Locate the string in the source code
+2. Figure out where/how the string shows up in which tool from the content of source code
+3. Write a description. See below for guidelines on what to add.
+
+### What information should I provide in the message description?
+- Where is the text located? (e.g. button, title, link, pull-down menu in the Sources pane)
+- What triggers the string and/or what is the result? What page or text comes before and after?
+- What do the placeholders stand for? Will this message replace a placeholder in another message? Do they need to be arranged in a certain way?
+- Is this a verb or a noun? If it's an adjective, what does it refer to?
+- Who is the message intended for (e.g. accessible label)?
+
+## Placeholder
+- If the auto-generated `<ph>` tag name is not descriptive, change it to something that explains what the placeholder is used for. Use all uppercase letters connected by underscores.
+- Placeholder tag names under the same message tag cannot be the same.
+- Use `<ex></ex>` to add an example to a placeholder. Text between `<ex>` will be used as an example for the placeholder content.
+- Example:
+```xml
+Hey <ph name="USER_NAME">$1<ex>Joe</ex></ph>, you have <ph name="COUNT"><ex>10</ex>$2</ph> messages.
+``` \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/docs/langpacks/localization_apis.md b/chromium/third_party/blink/renderer/devtools/docs/langpacks/localization_apis.md
new file mode 100644
index 00000000000..fb579c36935
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/docs/langpacks/localization_apis.md
@@ -0,0 +1,44 @@
+Localizable strings in the DevTools frontend need to be wrapped in localization calls. This guide walks you through a few choices.
+
+## ls tagged template literal [preferred]
+Template literal prefixed with `ls` that returns a translation string. Use on string with or without substitution and return a translation string. To substitute variable, wrap it with `${}`, e.g. ``` ls`Hi ${name}` ```.
+
+`ls` is generally preferred as it's more readable. The only thing to pay attention to is that all the variables will be converted to string, so if you want to format the variable in a specific way, you have to manually do it. Example:
+
+```javascript
+const progress = 0.734156;
+ls`${Number.parseFloat(progress).toPrecision(2)}% done`;
+```
+
+## Common.UIString(string, variable1, variable2, ...) [deprecated]
+Functionally equivalent to `ls` as it also returns a translation string. To substitute variables, use formatters (%s, %d, %.1f, %.2f, and so on) inside the string as the first argument, and use variables as the rest of the call arguments. Example: `Common.UIString('Hi %s, you have %d unread messages', name, count)`.
+
+If you want to format a float with a specific precision, use a float formatter with precision (e.g. %.1f, %.2f), e.g. `Common.UIString('Default: %.1f', defaultValue)`. This is the only case where `Common.UIString` may be more preferable, but of course you can write/use a precision conversion function and call it in `ls`.
+
+## UI.formatLocalized(string, [...])
+This call returns a **span element**, not a string. It is used when you want to construct a DOM element with a localizable string, or localizable content that contains some other DOM element. Use the %s formatter inside the localizable string, which is the first argument, and use a list of strings or DOM elements as the second argument. When %s is replaced by a string, it's added as text to the DOM element. For example:
+
+```javascript
+// Create a span element with localizable string
+reasonElement = UI.formatLocalized('Element has empty alt text.', []);
+
+// Element with localizable content containing two DOM elements that are buttons
+const recordButton = UI.createInlineButton(UI.Toolbar.createActionButton(this._toggleRecordAction));
+const reloadButton = UI.createInlineButton(UI.Toolbar.createActionButtonForId('coverage.start-with-reload'));
+message = UI.formatLocalized(
+ 'Click the record button %s to start capturing coverage.\nClick the reload button %s to reload and start capturing coverage.',
+ [recordButton, reloadButton]);
+
+// Element with error message text and a link
+UI.formatLocalized('%s. Read % for more.', [errorMessage, link])
+```
+
+## Common.UIStringFormat(string)
+This call creates a **formatter** that takes a set number of variables and substitute them in. Call `format(var1, var2, ...)` on the formatter. If you need to use the same format for different variables repeatedly, use this function to save redundant code.
+
+```javascript
+// Format minute to 1 decimal place
+const minutesFormat = new Common.UIStringFormat('%.1f min');
+
+minutesFormat.format(1.256); // --> '1.2 min'
+``` \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/docs/langpacks/locked_terms.md b/chromium/third_party/blink/renderer/devtools/docs/langpacks/locked_terms.md
new file mode 100644
index 00000000000..c25f80d1d4d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/docs/langpacks/locked_terms.md
@@ -0,0 +1,25 @@
+##How to prevent a term being localized?
+If a string contains some terms that should not be localized, they should be wrapped inside placeholder tags `<ph name="LOCKED_[1-9]"></ph>` in the .grdp file. The number after `LOCKED_` starts from 1, and increments when a single string has more then 1 terms that should not be localized.
+
+**example:**
+Frontend javascript file
+```javascript
+ls`You can log your messages using console.log() in the DevTools console.`
+```
+
+Frontend .grdp file
+(`console.log()` and `DevTools` should not be translated)
+```html
+ <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc="Text show up in the information bar in the DevTools">
+ You can log your messages using <ph name="LOCKED_1">console.log()</ph> in the <ph name="LOCKED_2">DevTools</ph> console.
+ </message>
+```
+
+##What should not be localized?
+In general, branding related terms and code snippets are the ones to look for.
+
+Some examples:
+- **Brandings:**
+Lighthouse, GitHub, DevTools, Chrome Data Saver, Safari, BlackBerry Z30, Kindle Fire HDX, Pixel 2, Microsoft Lumia 550
+- **Code snippets:**
+localhost:9229, console.clear(), --memlog=all, url:a.com
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg b/chromium/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
index 1ac81398ebb..45cb0a90a71 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="110" height="110"><defs><linearGradient id="y" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#a"/><linearGradient id="a"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="A" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#b"/><linearGradient id="b"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient></defs><path d="M0 20.995c0-.55.456-.995.995-.995h8.01c.55 0 .995.455.995.995v8.01c0 .549-.456.995-.995.995H.995C.445 30 0 29.544 0 29.004zm5.123 4.744C7.691 25.312 8.75 24.546 8.75 22h-1.5c0 1.62-.44 1.939-2.373 2.26-2.568.429-3.627 1.194-3.627 3.74h1.5c0-1.62.44-1.937 2.373-2.26zM23.65 27.21l-1.44-2.03L21 26.39 23.55 30 30 22.33 28.88 21z"/><path d="M6.5 46c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1" fill="#bababa"/><path d="M5.75 42.75L2.25 46l3.5 3.25" fill="none" stroke="#bababa" stroke-width="1.5"/><path d="M27.5 42.43l-.93-.93L24 44.07l-2.57-2.57-.93.93L23.07 45l-2.57 2.57.93.93L24 45.93l2.57 2.57.93-.93L24.93 45l2.57-2.57z" fill-opacity=".24"/><path d="M27.5 41.93l-.93-.93L24 43.57 21.43 41l-.93.93 2.57 2.57-2.57 2.57.93.93L24 45.43 26.57 48l.93-.93-2.57-2.57 2.57-2.57z" fill="#676767"/><path d="M43.25 20c-.7 0-1.25.5-1.25 1.25v7.5c0 .7.5 1.25 1.25 1.25h3.5c.7 0 1.25-.5 1.25-1.25v-7.5c0-.7-.5-1.25-1.25-1.25zM43 21h4v7h-4zm2 7.25c.4 0 .75.3.75.75 0 .4-.3.75-.75.75-.4 0-.75-.3-.75-.75 0-.4.3-.75.75-.75z"/><g transform="translate(40 40)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#c)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><path d="M3 3l4 4M7 3L3 7" stroke="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><path d="M4.5 61.3l4 3.7-4 3.7v-1.2H1.425l.075-5h3z" fill="#adf2ad" stroke="#007200"/><g transform="translate(20 60)"><path transform="translate(-140)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z" fill="url(#e)"/><path d="M9.5 5.05A4.494 4.494 0 0 1 4.95 9.5 4.494 4.494 0 0 1 .5 4.95 4.494 4.494 0 0 1 5.05.5C7.54.53 9.53 2.56 9.5 5.05z" fill="#00be00"/><path transform="translate(-140)" d="M145.08.53c1.97.02 3.55 1.06 3.54 2.32-.01 1.26-1.62 2.26-3.59 2.24-1.97-.02-3.55-1.06-3.54-2.32.01-1.26 1.62-2.26 3.59-2.24z" fill="url(#f)"/><path transform="translate(-140)" d="M144.98 9.41c1.66.02 3.01-.68 3.02-1.56.01-.88-1.33-1.61-2.98-1.63-1.66-.02-3.01.68-3.02 1.56-.01.88 1.33 1.61 2.98 1.63z" fill="url(#g)"/><defs><linearGradient id="h"><stop stop-color="#00d600" stop-opacity="0" offset="0"/><stop stop-color="#d8fc7b" stop-opacity=".81" offset="1"/></linearGradient><linearGradient id="i"><stop stop-color="#00ba00" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="j"><stop stop-color="#00a104" offset="0"/><stop stop-color="#00c605" offset="1"/></linearGradient><linearGradient id="g" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.0048 .4396 .78038 .00853 65.608 -94.834)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="f" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(.00687 -.62923 .9267 .01012 47.871 147.44)" gradientUnits="userSpaceOnUse" xlink:href="#i"/><linearGradient id="e" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.01507 1.3791 -1.3006 -.0142 282.66 -312.8)" gradientUnits="userSpaceOnUse" xlink:href="#j"/></defs></g><g transform="translate(40 60)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><path d="M3.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53H3.41V7.6h.66V3.99h-.66v-.53h2.22V7.6z" fill="#fff"/><defs><linearGradient id="l"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="k" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#l"/></defs></g><path d="M60.45 20.467v9.079h5.373l3.582-4.54-3.582-4.539z" fill="#698cfe" stroke="#4073f4" stroke-width=".908"/><path d="M60.45 40.467v9.08h5.372l3.581-4.54-3.581-4.54z" fill="#ef9d0d" stroke="#a36c01" stroke-width=".908"/><g transform="translate(60 60)"><path d="M5 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="#e5a600"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#ffbd00"/><path transform="translate(-160)" d="M165.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#m)"/><path transform="translate(-160)" d="M164.99 9.42c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#n)"/><defs><linearGradient id="o"><stop stop-color="#ffa801" stop-opacity="0" offset="0"/><stop stop-color="#f0fb3d" offset="1"/></linearGradient><linearGradient id="p"><stop stop-color="#ffbd00" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="n" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 84.444 -93.924)" gradientUnits="userSpaceOnUse" xlink:href="#o"/><linearGradient id="m" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 69.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#p"/></defs></g><g transform="translate(0 80)"><path transform="translate(-120)" d="M125 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="url(#q)"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#d00"/><path transform="translate(-120)" d="M125.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#r)"/><path transform="translate(-120)" d="M125.03 9.47c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#s)"/><defs><linearGradient id="t"><stop stop-color="red" stop-opacity="0" offset="0"/><stop stop-color="#f0cb68" stop-opacity=".71" offset="1"/></linearGradient><linearGradient id="u"><stop stop-color="#e60000" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="v"><stop stop-color="#a10000" offset="0"/><stop stop-color="#c60000" offset="1"/></linearGradient><linearGradient id="s" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 44.488 -93.88)" gradientUnits="userSpaceOnUse" xlink:href="#t"/><linearGradient id="r" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 29.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#u"/><linearGradient id="q" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 1.3793 -1.3008 0 259.08 -314.35)" gradientUnits="userSpaceOnUse" xlink:href="#v"/></defs></g><path d="M20 80h10v10H20z" fill="none"/><path d="M27.5 82.5V80H20v7.5h2.5V90H30v-7.5zM21 81h5.5v5.5H21zm2.5 6.5h4v-4H29V89h-5.5z"/><path d="M23.5 87.5h4v-4H29V89h-5.5z" fill-opacity=".25"/><g fill="#acf2ae" stroke="#007200" stroke-width="2.577"><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z"/><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M149.5 5.05a4.494 4.494 0 0 1-4.55 4.45 4.494 4.494 0 0 1-4.45-4.55A4.494 4.494 0 0 1 145.05.5c2.49.03 4.48 2.06 4.45 4.55z"/></g><path d="M48.313 82.5L45.21 86l-3.102-3.5h1.24v-1.92h3.723v1.92z" fill="#adf2ad" stroke="#007200"/><path d="M66.537 88.514a1.314 1.314 0 0 1-1.335 1.295 1.313 1.313 0 0 1-1.306-1.324 1.314 1.314 0 0 1 1.335-1.294c.731.009 1.315.6 1.307 1.323z" fill="#acf2ae" stroke="#007200" stroke-width=".753"/><path d="M62.108 83.5l3.102-2.982 3.102 2.982h-1.24v2h-3.723v-2z" fill="#adf2ad" stroke="#007200"/><path d="M83.25 21.75l3.5 3.25-3.5 3.25" fill="none" stroke="#367cf1" stroke-width="1.5"/><path d="M86 40l-5 5 5 5v-2h3v-6h-3zM84 60l5 5-5 5.022v-2.045L81 68v-6h3z" fill="#4688f1"/><path d="M84.5 88l3.5-6h-7M7 104.5L2 101v7M24 100l4 7h-8"/><path d="M43.25 102.75l3.5 3.25-3.5 3.25" fill="none" stroke="#939393" stroke-width="1.5"/><path d="M61 109l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M61 109l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M63.75 102.75h2.5v2.5l-.5 1.75h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><path d="M64 103h2v2.25l-.5 1.75h-1l-.5-1.75V103m0 5h2v1h-2" fill="#fff"/><text style="line-height:0%" x="3.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="3.051" y="118.387" style="line-height:1.25" font-size="8">a</tspan></text><text style="line-height:0%" x="23.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="23.051" y="118.387" style="line-height:1.25" font-size="8">b</tspan></text><text style="line-height:0%" x="43.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="43.051" y="118.387" style="line-height:1.25" font-size="8">c</tspan></text><text style="line-height:0%" x="63.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="63.051" y="118.387" style="line-height:1.25" font-size="8">d</tspan></text><text style="line-height:0%" x="83.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="83.051" y="118.387" style="line-height:1.25" font-size="8">e</tspan></text><text style="line-height:0%" x="-7.026" y="107.818" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.026" y="107.818" style="line-height:1.25" font-size="8">1</tspan></text><text style="line-height:0%" x="-6.819" y="87.88" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.819" y="87.88" style="line-height:1.25" font-size="8">2</tspan></text><text style="line-height:0%" x="-6.756" y="67.992" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.756" y="67.992" style="line-height:1.25" font-size="8">3</tspan></text><text style="line-height:0%" x="-6.917" y="47.994" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.917" y="47.994" style="line-height:1.25" font-size="8">4</tspan></text><text style="line-height:0%" x="-7.108" y="28.056" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.108" y="28.056" style="line-height:1.25" font-size="8">5</tspan></text><circle cx="3" cy="3" r="2.5" transform="matrix(1.13208 0 0 1.13208 81.604 102.604)" fill="#00bcd4" stroke="#000" stroke-width=".3"/><path d="M5 0a5 5 0 1 0 0 10A5 5 0 0 0 5 0zm.048.721c1.083 0 2.179.4 3.005 1.226a4.234 4.234 0 0 1 0 5.986L5.048 4.952l-2.98-3.005A4.18 4.18 0 0 1 5.047.721z"/><text style="line-height:0%" x="-6.68" y="8" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.68" y="8" style="line-height:1.25" font-size="8">6</tspan></text><path d="M17.601-2.913h16.232v16.232H17.601z" fill="none"/><path d="M21.11 5.556L20 6.667 23.334 10 30 3.334l-1.11-1.111-5.556 5.555z" fill-rule="evenodd"/><path d="M44.954 8.42a3.467 3.467 0 0 1-3.462-3.46c0-.678.2-1.309.531-1.84l4.77 4.77c-.531.338-1.162.53-1.84.53m3.462-3.46c0 .676-.2 1.307-.53 1.838l-4.77-4.77a3.405 3.405 0 0 1 1.839-.53 3.467 3.467 0 0 1 3.461 3.461M45 .005a5 5 0 1 0 0 10 5 5 0 0 0 0-10"/><path d="M68.875 2.219L63.344 7.78l-.407-.406L61.844 8.5l1.5 1.5L70 3.344l-1.125-1.125z" fill-rule="evenodd"/><text style="line-height:0%" x="103.739" y="118.482" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="103.739" y="118.482" style="line-height:1.25" font-size="8">f</tspan></text><g transform="translate(100 100)" mask="url(#w)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="w"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/></mask></g><g transform="translate(100 80)" mask="url(#x)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#y)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="x"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22V7.6z"/></mask></g><g transform="translate(100 60)" mask="url(#z)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#A)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="z"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/></mask></g><g><path d="M105.1 40.267a4.835 4.835 0 0 0-4.833 4.833 4.835 4.835 0 0 0 4.833 4.833 4.835 4.835 0 0 0 4.833-4.833 4.835 4.835 0 0 0-4.833-4.833zm0 1.45c.802 0 1.45.647 1.45 1.45 0 .802-.648 1.45-1.45 1.45-.802 0-1.45-.648-1.45-1.45 0-.803.648-1.45 1.45-1.45zm0 6.863a3.48 3.48 0 0 1-2.9-1.556c.014-.962 1.933-1.489 2.9-1.489.962 0 2.885.527 2.9 1.489a3.48 3.48 0 0 1-2.9 1.556z"/><path d="M99.3 39.3h11.6v11.6H99.3z" fill="none"/></g><path d="M105 22.528l-4 4.43.94 1.042 3.06-3.382L108.06 28l.94-1.041z"/><path d="M76.448 14.99h17.528v19.416H76.448z" fill="none"/><path d="M88.06 3.06L85 6.113 81.94 3.06 81 4l4 4 4-4z"/></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="130" height="110"><defs><linearGradient id="y" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#a"/><linearGradient id="a"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="A" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#b"/><linearGradient id="b"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient></defs><path d="M0 20.995c0-.55.456-.995.995-.995h8.01c.55 0 .995.455.995.995v8.01c0 .549-.456.995-.995.995H.995C.445 30 0 29.544 0 29.004zm5.123 4.744C7.691 25.312 8.75 24.546 8.75 22h-1.5c0 1.62-.44 1.939-2.373 2.26-2.568.429-3.627 1.194-3.627 3.74h1.5c0-1.62.44-1.937 2.373-2.26zM23.65 27.21l-1.44-2.03L21 26.39 23.55 30 30 22.33 28.88 21z"/><path d="M6.5 46c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1" fill="#bababa"/><path d="M5.75 42.75L2.25 46l3.5 3.25" fill="none" stroke="#bababa" stroke-width="1.5"/><path d="M27.5 42.43l-.93-.93L24 44.07l-2.57-2.57-.93.93L23.07 45l-2.57 2.57.93.93L24 45.93l2.57 2.57.93-.93L24.93 45l2.57-2.57z" fill-opacity=".24"/><path d="M27.5 41.93l-.93-.93L24 43.57 21.43 41l-.93.93 2.57 2.57-2.57 2.57.93.93L24 45.43 26.57 48l.93-.93-2.57-2.57 2.57-2.57z" fill="#676767"/><path d="M43.25 20c-.7 0-1.25.5-1.25 1.25v7.5c0 .7.5 1.25 1.25 1.25h3.5c.7 0 1.25-.5 1.25-1.25v-7.5c0-.7-.5-1.25-1.25-1.25zM43 21h4v7h-4zm2 7.25c.4 0 .75.3.75.75 0 .4-.3.75-.75.75-.4 0-.75-.3-.75-.75 0-.4.3-.75.75-.75z"/><g transform="translate(40 40)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#c)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><path d="M3 3l4 4M7 3L3 7" stroke="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><path d="M4.5 61.3l4 3.7-4 3.7v-1.2H1.425l.075-5h3z" fill="#adf2ad" stroke="#007200"/><g transform="translate(20 60)"><path transform="translate(-140)" d="M144.95 10A5.002 5.002 0 01140 4.95 5.002 5.002 0 01145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 01-5.05 4.95z" fill="url(#e)"/><path d="M9.5 5.05A4.494 4.494 0 014.95 9.5 4.494 4.494 0 01.5 4.95 4.494 4.494 0 015.05.5C7.54.53 9.53 2.56 9.5 5.05z" fill="#00be00"/><path transform="translate(-140)" d="M145.08.53c1.97.02 3.55 1.06 3.54 2.32-.01 1.26-1.62 2.26-3.59 2.24-1.97-.02-3.55-1.06-3.54-2.32.01-1.26 1.62-2.26 3.59-2.24z" fill="url(#f)"/><path transform="translate(-140)" d="M144.98 9.41c1.66.02 3.01-.68 3.02-1.56.01-.88-1.33-1.61-2.98-1.63-1.66-.02-3.01.68-3.02 1.56-.01.88 1.33 1.61 2.98 1.63z" fill="url(#g)"/><defs><linearGradient id="h"><stop stop-color="#00d600" stop-opacity="0" offset="0"/><stop stop-color="#d8fc7b" stop-opacity=".81" offset="1"/></linearGradient><linearGradient id="i"><stop stop-color="#00ba00" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="j"><stop stop-color="#00a104" offset="0"/><stop stop-color="#00c605" offset="1"/></linearGradient><linearGradient id="g" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.0048 .4396 .78038 .00853 65.608 -94.834)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="f" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(.00687 -.62923 .9267 .01012 47.871 147.44)" gradientUnits="userSpaceOnUse" xlink:href="#i"/><linearGradient id="e" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.01507 1.3791 -1.3006 -.0142 282.66 -312.8)" gradientUnits="userSpaceOnUse" xlink:href="#j"/></defs></g><g transform="translate(40 60)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><path d="M3.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 01-.42-.71zm1.7 5.46h.67v.53H3.41V7.6h.66V3.99h-.66v-.53h2.22V7.6z" fill="#fff"/><defs><linearGradient id="l"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="k" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#l"/></defs></g><path d="M60.45 20.467v9.079h5.373l3.582-4.54-3.582-4.539z" fill="#698cfe" stroke="#4073f4" stroke-width=".908"/><path d="M60.45 40.467v9.08h5.372l3.581-4.54-3.581-4.54z" fill="#ef9d0d" stroke="#a36c01" stroke-width=".908"/><g transform="translate(60 60)"><path d="M5 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="#e5a600"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#ffbd00"/><path transform="translate(-160)" d="M165.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#m)"/><path transform="translate(-160)" d="M164.99 9.42c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#n)"/><defs><linearGradient id="o"><stop stop-color="#ffa801" stop-opacity="0" offset="0"/><stop stop-color="#f0fb3d" offset="1"/></linearGradient><linearGradient id="p"><stop stop-color="#ffbd00" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="n" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 84.444 -93.924)" gradientUnits="userSpaceOnUse" xlink:href="#o"/><linearGradient id="m" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 69.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#p"/></defs></g><g transform="translate(0 80)"><path transform="translate(-120)" d="M125 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="url(#q)"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#d00"/><path transform="translate(-120)" d="M125.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#r)"/><path transform="translate(-120)" d="M125.03 9.47c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#s)"/><defs><linearGradient id="t"><stop stop-color="red" stop-opacity="0" offset="0"/><stop stop-color="#f0cb68" stop-opacity=".71" offset="1"/></linearGradient><linearGradient id="u"><stop stop-color="#e60000" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="v"><stop stop-color="#a10000" offset="0"/><stop stop-color="#c60000" offset="1"/></linearGradient><linearGradient id="s" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 44.488 -93.88)" gradientUnits="userSpaceOnUse" xlink:href="#t"/><linearGradient id="r" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 29.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#u"/><linearGradient id="q" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 1.3793 -1.3008 0 259.08 -314.35)" gradientUnits="userSpaceOnUse" xlink:href="#v"/></defs></g><path d="M20 80h10v10H20z" fill="none"/><path d="M27.5 82.5V80H20v7.5h2.5V90H30v-7.5zM21 81h5.5v5.5H21zm2.5 6.5h4v-4H29V89h-5.5z"/><path d="M23.5 87.5h4v-4H29V89h-5.5z" fill-opacity=".25"/><g fill="#acf2ae" stroke="#007200" stroke-width="2.577"><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M144.95 10A5.002 5.002 0 01140 4.95 5.002 5.002 0 01145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 01-5.05 4.95z"/><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M149.5 5.05a4.494 4.494 0 01-4.55 4.45 4.494 4.494 0 01-4.45-4.55A4.494 4.494 0 01145.05.5c2.49.03 4.48 2.06 4.45 4.55z"/></g><path d="M48.313 82.5L45.21 86l-3.102-3.5h1.24v-1.92h3.723v1.92z" fill="#adf2ad" stroke="#007200"/><path d="M66.537 88.514a1.314 1.314 0 01-1.335 1.295 1.313 1.313 0 01-1.306-1.324 1.314 1.314 0 011.335-1.294c.731.009 1.315.6 1.307 1.323z" fill="#acf2ae" stroke="#007200" stroke-width=".753"/><path d="M62.108 83.5l3.102-2.982 3.102 2.982h-1.24v2h-3.723v-2z" fill="#adf2ad" stroke="#007200"/><path d="M83.25 21.75l3.5 3.25-3.5 3.25" fill="none" stroke="#367cf1" stroke-width="1.5"/><path d="M86 40l-5 5 5 5v-2h3v-6h-3zM84 60l5 5-5 5.022v-2.045L81 68v-6h3z" fill="#4688f1"/><path d="M84.5 88l3.5-6h-7M7 104.5L2 101v7M24 100l4 7h-8"/><path d="M43.25 102.75l3.5 3.25-3.5 3.25" fill="none" stroke="#939393" stroke-width="1.5"/><path d="M61 109l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M61 109l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M63.75 102.75h2.5v2.5l-.5 1.75h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><path d="M64 103h2v2.25l-.5 1.75h-1l-.5-1.75V103m0 5h2v1h-2" fill="#fff"/><text style="line-height:0%" x="3.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="3.051" y="118.387" style="line-height:1.25" font-size="8">a</tspan></text><text style="line-height:0%" x="23.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="23.051" y="118.387" style="line-height:1.25" font-size="8">b</tspan></text><text style="line-height:0%" x="43.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="43.051" y="118.387" style="line-height:1.25" font-size="8">c</tspan></text><text style="line-height:0%" x="63.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="63.051" y="118.387" style="line-height:1.25" font-size="8">d</tspan></text><text style="line-height:0%" x="83.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="83.051" y="118.387" style="line-height:1.25" font-size="8">e</tspan></text><text style="line-height:0%" x="-7.026" y="107.818" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.026" y="107.818" style="line-height:1.25" font-size="8">1</tspan></text><text style="line-height:0%" x="-6.819" y="87.88" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.819" y="87.88" style="line-height:1.25" font-size="8">2</tspan></text><text style="line-height:0%" x="-6.756" y="67.992" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.756" y="67.992" style="line-height:1.25" font-size="8">3</tspan></text><text style="line-height:0%" x="-6.917" y="47.994" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.917" y="47.994" style="line-height:1.25" font-size="8">4</tspan></text><text style="line-height:0%" x="-7.108" y="28.056" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.108" y="28.056" style="line-height:1.25" font-size="8">5</tspan></text><circle cx="3" cy="3" r="2.5" transform="matrix(1.13208 0 0 1.13208 81.604 102.604)" fill="#00bcd4" stroke="#000" stroke-width=".3"/><path d="M5 0a5 5 0 100 10A5 5 0 005 0zm.048.721c1.083 0 2.179.4 3.005 1.226a4.234 4.234 0 010 5.986L5.048 4.952l-2.98-3.005A4.18 4.18 0 015.047.721z"/><text style="line-height:0%" x="-6.68" y="8" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.68" y="8" style="line-height:1.25" font-size="8">6</tspan></text><path d="M17.601-2.913h16.232v16.232H17.601z" fill="none"/><path d="M21.11 5.556L20 6.667 23.334 10 30 3.334l-1.11-1.111-5.556 5.555z" fill-rule="evenodd"/><path d="M44.954 8.42a3.467 3.467 0 01-3.462-3.46c0-.678.2-1.309.531-1.84l4.77 4.77c-.531.338-1.162.53-1.84.53m3.462-3.46c0 .676-.2 1.307-.53 1.838l-4.77-4.77a3.405 3.405 0 011.839-.53 3.467 3.467 0 013.461 3.461M45 .005a5 5 0 100 10 5 5 0 000-10"/><path d="M68.875 2.219L63.344 7.78l-.407-.406L61.844 8.5l1.5 1.5L70 3.344l-1.125-1.125z" fill-rule="evenodd"/><text style="line-height:0%" x="103.739" y="118.482" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="103.739" y="118.482" style="line-height:1.25" font-size="8">f</tspan></text><g transform="translate(100 100)" mask="url(#w)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="w"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/></mask></g><g transform="translate(100 80)" mask="url(#x)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#y)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="x"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 01-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22V7.6z"/></mask></g><g transform="translate(100 60)" mask="url(#z)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#A)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="z"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/></mask></g><g><path d="M105.1 40.267a4.835 4.835 0 00-4.833 4.833 4.835 4.835 0 004.833 4.833 4.835 4.835 0 004.833-4.833 4.835 4.835 0 00-4.833-4.833zm0 1.45c.802 0 1.45.647 1.45 1.45 0 .802-.648 1.45-1.45 1.45-.802 0-1.45-.648-1.45-1.45 0-.803.648-1.45 1.45-1.45zm0 6.863a3.48 3.48 0 01-2.9-1.556c.014-.962 1.933-1.489 2.9-1.489.962 0 2.885.527 2.9 1.489a3.48 3.48 0 01-2.9 1.556z"/><path d="M99.3 39.3h11.6v11.6H99.3z" fill="none"/></g><path d="M105 22.528l-4 4.43.94 1.042 3.06-3.382L108.06 28l.94-1.041z"/><path d="M76.448 14.99h17.528v19.416H76.448z" fill="none"/><path d="M88.06 3.06L85 6.113 81.94 3.06 81 4l4 4 4-4zM102 2h2v6h-2z"/><a><path d="M106 2h2v6h-2z"/></a><text style="line-height:0%" x="122.66" y="117.219" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="122.66" y="117.219" style="line-height:1.25" font-size="8">g</tspan></text><path d="M128 5l-6 3V2zM128 26.5l-1.5 1.5-1.5-1.5-1.5 1.5-1.5-1.5 1.5-1.5-1.5-1.5 1.5-1.5 1.5 1.5 1.5-1.5 1.5 1.5-1.5 1.5z"/></svg> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
index 8504ee280c8..2fc263cc199 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
@@ -1,13 +1,13 @@
{
"securityIcons.svg": "27676f7c1f1542659c7c49a8052259dc",
+ "accelerometer-back.svg": "342973eb940ef43b409b28c2c6b0d520",
"largeIcons.svg": "faf26930e93e7525a3cbcc595527662c",
- "breakpoint.svg": "69cd92d807259c022791112809b97799",
"breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28",
"checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
"errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
- "smallIcons.svg": "19940dda6f171380bfd7d04d0061b44c",
+ "smallIcons.svg": "ed10eae550f101ce8d1cc9e26dd8a33d",
"mediumIcons.svg": "9cb32f670ba43a7ab424eab281043e6b",
- "accelerometer-back.svg": "342973eb940ef43b409b28c2c6b0d520",
+ "breakpoint.svg": "69cd92d807259c022791112809b97799",
"treeoutlineTriangles.svg": "2d26ab85d919f83d5021f2f385dffd0b",
"chevrons.svg": "79b4b527771e30b6388ce664077b3409",
"audits_logo.svg": "3a4893bd2ef5bb233e924f15e51af69a",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
index ab48f6664d0..3a8a9ef7443 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
@@ -8,11 +8,11 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="110"
+ width="130"
height="110"
id="svg4185"
version="1.1"
- inkscape:version="0.92.2pre0 (973e216, 2017-07-25)"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="smallIcons.svg"
inkscape:export-filename="/Users/pfeldman/code/chromium/src/third_party/WebKit/Source/devtools/front_end/Images/smallIcons_2x.png"
inkscape:export-xdpi="180"
@@ -78,16 +78,16 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:window-width="1272"
- inkscape:window-height="1006"
+ inkscape:window-width="1432"
+ inkscape:window-height="1419"
id="namedview4455"
showgrid="true"
- inkscape:zoom="7.4167646"
- inkscape:cx="72.154899"
- inkscape:cy="32.871453"
- inkscape:window-x="768"
- inkscape:window-y="0"
- inkscape:window-maximized="0"
+ inkscape:zoom="5.2444445"
+ inkscape:cx="94.607116"
+ inkscape:cy="82.226632"
+ inkscape:window-x="4002"
+ inkscape:window-y="1063"
+ inkscape:window-maximized="1"
inkscape:current-layer="svg4185">
<inkscape:grid
type="xygrid"
@@ -1046,4 +1046,61 @@
inkscape:connector-curvature="0"
d="M 88.06,3.059999 85,6.113332 81.94,3.059999 l -0.94,0.94 4,4 4,-4 z"
id="path3974" />
+ <path
+ style="stroke-width:0.02383474"
+ d=""
+ id="path5923"
+ inkscape:connector-curvature="0" />
+ <path
+ style="stroke-width:0.02383474"
+ d=""
+ id="path5925"
+ inkscape:connector-curvature="0" />
+ <path
+ style="stroke-width:0.02383474"
+ d=""
+ id="path5927"
+ inkscape:connector-curvature="0" />
+ <rect
+ id="rect5943"
+ width="2"
+ height="6"
+ x="102"
+ y="1.9999998"
+ style="stroke-width:1.13202608" />
+ <a
+ id="a6015">
+ <rect
+ style="stroke-width:1.13202608"
+ y="2"
+ x="106"
+ height="6"
+ width="2"
+ id="rect5943-5" />
+ </a>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cccccc;fill-opacity:1;stroke:none"
+ x="122.66023"
+ y="117.2188"
+ id="text5191-77-3-3"><tspan
+ sodipodi:role="line"
+ id="tspan5193-6-6-5"
+ x="122.66023"
+ y="117.2188"
+ style="font-size:8px;line-height:1.25;font-family:sans-serif">g</tspan></text>
+ <path
+ inkscape:transform-center-x="0.029808665"
+ inkscape:transform-center-y="-0.33844643"
+ d="m 128,5 -6,3 V 2 Z"
+ id="path6489"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ inkscape:transform-center-x="0.34573841"
+ inkscape:transform-center-y="-0.78316773"
+ d="M 128,26.5 126.5,28 125,26.5 123.5,28 122,26.5 123.5,25 122,23.5 l 1.5,-1.5 1.5,1.5 1.5,-1.5 1.5,1.5 -1.5,1.5 z"
+ id="path6495"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccc" />
</svg>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png b/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png
index 397d4aa9ade..1d81b8f63e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Images/whatsnew.png
Binary files differ
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
index 3e6552b0917..e958c077a00 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
@@ -27,17 +27,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.
*/
-// This gets all concatenated module descriptors in the release mode.
-const allDescriptors = [];
-let applicationDescriptor;
const _loadedScripts = {};
-// FIXME: This is a workaround to force Closure compiler provide
-// the standard ES6 runtime for all modules. This should be removed
-// once Closure provides standard externs for Map et al.
-for (const k of []) { // eslint-disable-line
-}
-
(function() {
const baseUrl = self.location ? self.location.origin + self.location.pathname : '';
self._importScriptPathPrefix = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);
@@ -48,24 +39,25 @@ const REMOTE_MODULE_FALLBACK_REVISION = '@010ddcfda246975d194964ccf20038ebbdec60
/**
* @unrestricted
*/
-var Runtime = class { // eslint-disable-line
+class Runtime {
/**
- * @param {!Array.<!Runtime.ModuleDescriptor>} descriptors
+ * @param {!Array.<!ModuleDescriptor>} descriptors
*/
constructor(descriptors) {
/** @type {!Array<!Runtime.Module>} */
this._modules = [];
/** @type {!Object<string, !Runtime.Module>} */
this._modulesMap = {};
- /** @type {!Array<!Runtime.Extension>} */
+ /** @type {!Array<!Extension>} */
this._extensions = [];
/** @type {!Object<string, !function(new:Object)>} */
this._cachedTypeClasses = {};
- /** @type {!Object<string, !Runtime.ModuleDescriptor>} */
+ /** @type {!Object<string, !ModuleDescriptor>} */
this._descriptorsMap = {};
- for (let i = 0; i < descriptors.length; ++i)
+ for (let i = 0; i < descriptors.length; ++i) {
this._registerModule(descriptors[i]);
+ }
}
/**
@@ -88,16 +80,19 @@ var Runtime = class { // eslint-disable-line
* @param {Event} e
*/
function onreadystatechange(e) {
- if (xhr.readyState !== XMLHttpRequest.DONE)
+ if (xhr.readyState !== XMLHttpRequest.DONE) {
return;
+ }
// DevTools Proxy server can mask 404s as 200s, check the body to be sure
const status = /^HTTP\/1.1 404/.test(e.target.response) ? 404 : xhr.status;
if ([0, 200, 304].indexOf(status) === -1) // Testing harness file:/// results in 0.
+ {
reject(new Error('While loading from url ' + url + ' server responded with a status of ' + status));
- else
+ } else {
fulfill(e.target.response);
+ }
}
xhr.send(null);
}
@@ -111,8 +106,9 @@ var Runtime = class { // eslint-disable-line
return Runtime.loadResourcePromise(url).catch(err => {
const urlWithFallbackVersion = url.replace(/@[0-9a-f]{40}/, REMOTE_MODULE_FALLBACK_REVISION);
// TODO(phulce): mark fallbacks in module.json and modify build script instead
- if (urlWithFallbackVersion === url || !url.includes('audits_worker_module'))
+ if (urlWithFallbackVersion === url || !url.includes('audits_worker_module')) {
throw err;
+ }
return Runtime.loadResourcePromise(urlWithFallbackVersion);
});
}
@@ -123,33 +119,53 @@ var Runtime = class { // eslint-disable-line
* @return {string}
*/
static normalizePath(path) {
- if (path.indexOf('..') === -1 && path.indexOf('.') === -1)
+ if (path.indexOf('..') === -1 && path.indexOf('.') === -1) {
return path;
+ }
const normalizedSegments = [];
const segments = path.split('/');
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];
- if (segment === '.')
+ if (segment === '.') {
continue;
- else if (segment === '..')
+ } else if (segment === '..') {
normalizedSegments.pop();
- else if (segment)
+ } else if (segment) {
normalizedSegments.push(segment);
+ }
}
let normalizedPath = normalizedSegments.join('/');
- if (normalizedPath[normalizedPath.length - 1] === '/')
+ if (normalizedPath[normalizedPath.length - 1] === '/') {
return normalizedPath;
- if (path[0] === '/' && normalizedPath)
+ }
+ if (path[0] === '/' && normalizedPath) {
normalizedPath = '/' + normalizedPath;
+ }
if ((path[path.length - 1] === '/') || (segments[segments.length - 1] === '.') ||
- (segments[segments.length - 1] === '..'))
+ (segments[segments.length - 1] === '..')) {
normalizedPath = normalizedPath + '/';
+ }
return normalizedPath;
}
/**
+ * @param {string} scriptName
+ * @param {string=} base
+ * @return {string}
+ */
+ static getResourceURL(scriptName, base) {
+ const sourceURL = (base || self._importScriptPathPrefix) + scriptName;
+ const schemaIndex = sourceURL.indexOf('://') + 3;
+ let pathIndex = sourceURL.indexOf('/', schemaIndex);
+ if (pathIndex === -1) {
+ pathIndex = sourceURL.length;
+ }
+ return sourceURL.substring(0, pathIndex) + Runtime.normalizePath(sourceURL.substring(pathIndex));
+ }
+
+ /**
* @param {!Array.<string>} scriptNames
* @param {string=} base
* @return {!Promise.<undefined>}
@@ -163,16 +179,11 @@ var Runtime = class { // eslint-disable-line
let scriptToEval = 0;
for (let i = 0; i < scriptNames.length; ++i) {
const scriptName = scriptNames[i];
- let sourceURL = (base || self._importScriptPathPrefix) + scriptName;
-
- const schemaIndex = sourceURL.indexOf('://') + 3;
- let pathIndex = sourceURL.indexOf('/', schemaIndex);
- if (pathIndex === -1)
- pathIndex = sourceURL.length;
- sourceURL = sourceURL.substring(0, pathIndex) + Runtime.normalizePath(sourceURL.substring(pathIndex));
+ const sourceURL = Runtime.getResourceURL(scriptName, base);
- if (_loadedScripts[sourceURL])
+ if (_loadedScripts[sourceURL]) {
continue;
+ }
urls.push(sourceURL);
const loadResourcePromise =
base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
@@ -244,38 +255,40 @@ var Runtime = class { // eslint-disable-line
* @return {!Promise.<undefined>}
*/
static async startApplication(appName) {
- console.timeStamp('Runtime.startApplication');
+ console.timeStamp('Root.Runtime.startApplication');
const allDescriptorsByName = {};
- for (let i = 0; i < allDescriptors.length; ++i) {
- const d = allDescriptors[i];
+ for (let i = 0; i < Root.allDescriptors.length; ++i) {
+ const d = Root.allDescriptors[i];
allDescriptorsByName[d['name']] = d;
}
- if (!applicationDescriptor) {
+ if (!Root.applicationDescriptor) {
let data = await Runtime.loadResourcePromise(appName + '.json');
- applicationDescriptor = JSON.parse(data);
- let descriptor = applicationDescriptor;
+ Root.applicationDescriptor = JSON.parse(data);
+ let descriptor = Root.applicationDescriptor;
while (descriptor.extends) {
data = await Runtime.loadResourcePromise(descriptor.extends + '.json');
descriptor = JSON.parse(data);
- applicationDescriptor.modules = descriptor.modules.concat(applicationDescriptor.modules);
+ Root.applicationDescriptor.modules = descriptor.modules.concat(Root.applicationDescriptor.modules);
}
}
- const configuration = applicationDescriptor.modules;
+ const configuration = Root.applicationDescriptor.modules;
const moduleJSONPromises = [];
const coreModuleNames = [];
for (let i = 0; i < configuration.length; ++i) {
const descriptor = configuration[i];
const name = descriptor['name'];
const moduleJSON = allDescriptorsByName[name];
- if (moduleJSON)
+ if (moduleJSON) {
moduleJSONPromises.push(Promise.resolve(moduleJSON));
- else
+ } else {
moduleJSONPromises.push(Runtime.loadResourcePromise(name + '/module.json').then(JSON.parse.bind(JSON)));
- if (descriptor['type'] === 'autostart')
+ }
+ if (descriptor['type'] === 'autostart') {
coreModuleNames.push(name);
+ }
}
const moduleDescriptors = await Promise.all(moduleJSONPromises);
@@ -286,8 +299,9 @@ var Runtime = class { // eslint-disable-line
moduleDescriptors[i].remote = configuration[i]['type'] === 'remote';
}
self.runtime = new Runtime(moduleDescriptors);
- if (coreModuleNames)
+ if (coreModuleNames) {
await self.runtime._loadAutoStartModules(coreModuleNames);
+ }
Runtime._appStartedPromiseCallback();
}
@@ -296,7 +310,7 @@ var Runtime = class { // eslint-disable-line
* @return {!Promise.<undefined>}
*/
static startWorker(appName) {
- return Runtime.startApplication(appName).then(sendWorkerReady);
+ return Root.Runtime.startApplication(appName).then(sendWorkerReady);
function sendWorkerReady() {
self.postMessage('workerReady');
@@ -332,8 +346,9 @@ var Runtime = class { // eslint-disable-line
}
static _assert(value, message) {
- if (value)
+ if (value) {
return;
+ }
Runtime._originalAssert.call(Runtime._console, value, message + ' ' + new Error().stack);
}
@@ -350,19 +365,24 @@ var Runtime = class { // eslint-disable-line
*/
static _isDescriptorEnabled(descriptor) {
const activatorExperiment = descriptor['experiment'];
- if (activatorExperiment === '*')
+ if (activatorExperiment === '*') {
return Runtime.experiments.supportEnabled();
+ }
if (activatorExperiment && activatorExperiment.startsWith('!') &&
- Runtime.experiments.isEnabled(activatorExperiment.substring(1)))
+ Runtime.experiments.isEnabled(activatorExperiment.substring(1))) {
return false;
+ }
if (activatorExperiment && !activatorExperiment.startsWith('!') &&
- !Runtime.experiments.isEnabled(activatorExperiment))
+ !Runtime.experiments.isEnabled(activatorExperiment)) {
return false;
+ }
const condition = descriptor['condition'];
- if (condition && !condition.startsWith('!') && !Runtime.queryParam(condition))
+ if (condition && !condition.startsWith('!') && !Runtime.queryParam(condition)) {
return false;
- if (condition && condition.startsWith('!') && Runtime.queryParam(condition.substring(1)))
+ }
+ if (condition && condition.startsWith('!') && Runtime.queryParam(condition.substring(1))) {
return false;
+ }
return true;
}
@@ -372,8 +392,9 @@ var Runtime = class { // eslint-disable-line
*/
static resolveSourceURL(path) {
let sourceURL = self.location.href;
- if (self.location.search)
+ if (self.location.search) {
sourceURL = sourceURL.replace(self.location.search, '');
+ }
sourceURL = sourceURL.substring(0, sourceURL.lastIndexOf('/') + 1) + path;
return '\n/*# sourceURL=' + sourceURL + ' */';
}
@@ -387,12 +408,21 @@ var Runtime = class { // eslint-disable-line
useTestBase() {
Runtime._remoteBase = 'http://localhost:8000/inspector-sources/';
- if (Runtime.queryParam('debugFrontend'))
+ if (Runtime.queryParam('debugFrontend')) {
Runtime._remoteBase += 'debug/';
+ }
+ }
+
+ /**
+ * @param {string} moduleName
+ * @return {!Runtime.Module}
+ */
+ module(moduleName) {
+ return this._modulesMap[moduleName];
}
/**
- * @param {!Runtime.ModuleDescriptor} descriptor
+ * @param {!ModuleDescriptor} descriptor
*/
_registerModule(descriptor) {
const module = new Runtime.Module(this, descriptor);
@@ -414,39 +444,44 @@ var Runtime = class { // eslint-disable-line
*/
_loadAutoStartModules(moduleNames) {
const promises = [];
- for (let i = 0; i < moduleNames.length; ++i)
+ for (let i = 0; i < moduleNames.length; ++i) {
promises.push(this.loadModulePromise(moduleNames[i]));
+ }
return Promise.all(promises);
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Extension} extension
* @param {?function(function(new:Object)):boolean} predicate
* @return {boolean}
*/
_checkExtensionApplicability(extension, predicate) {
- if (!predicate)
+ if (!predicate) {
return false;
+ }
const contextTypes = extension.descriptor().contextTypes;
- if (!contextTypes)
+ if (!contextTypes) {
return true;
+ }
for (let i = 0; i < contextTypes.length; ++i) {
const contextType = this._resolve(contextTypes[i]);
const isMatching = !!contextType && predicate(contextType);
- if (isMatching)
+ if (isMatching) {
return true;
+ }
}
return false;
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Extension} extension
* @param {?Object} context
* @return {boolean}
*/
isExtensionApplicableToContext(extension, context) {
- if (!context)
+ if (!context) {
return true;
+ }
return this._checkExtensionApplicability(extension, isInstanceOf);
/**
@@ -459,13 +494,14 @@ var Runtime = class { // eslint-disable-line
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Extension} extension
* @param {!Set.<!Function>=} currentContextTypes
* @return {boolean}
*/
isExtensionApplicableToContextTypes(extension, currentContextTypes) {
- if (!extension.descriptor().contextTypes)
+ if (!extension.descriptor().contextTypes) {
return true;
+ }
return this._checkExtensionApplicability(extension, currentContextTypes ? isContextTypeKnown : null);
@@ -482,26 +518,28 @@ var Runtime = class { // eslint-disable-line
* @param {*} type
* @param {?Object=} context
* @param {boolean=} sortByTitle
- * @return {!Array.<!Runtime.Extension>}
+ * @return {!Array.<!Extension>}
*/
extensions(type, context, sortByTitle) {
return this._extensions.filter(filter).sort(sortByTitle ? titleComparator : orderComparator);
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Extension} extension
* @return {boolean}
*/
function filter(extension) {
- if (extension._type !== type && extension._typeClass() !== type)
+ if (extension._type !== type && extension._typeClass() !== type) {
return false;
- if (!extension.enabled())
+ }
+ if (!extension.enabled()) {
return false;
+ }
return !context || extension.isApplicable(context);
}
/**
- * @param {!Runtime.Extension} extension1
- * @param {!Runtime.Extension} extension2
+ * @param {!Extension} extension1
+ * @param {!Extension} extension2
* @return {number}
*/
function orderComparator(extension1, extension2) {
@@ -511,8 +549,8 @@ var Runtime = class { // eslint-disable-line
}
/**
- * @param {!Runtime.Extension} extension1
- * @param {!Runtime.Extension} extension2
+ * @param {!Extension} extension1
+ * @param {!Extension} extension2
* @return {number}
*/
function titleComparator(extension1, extension2) {
@@ -525,7 +563,7 @@ var Runtime = class { // eslint-disable-line
/**
* @param {*} type
* @param {?Object=} context
- * @return {?Runtime.Extension}
+ * @return {?Extension}
*/
extension(type, context) {
return this.extensions(type, context)[0] || null;
@@ -547,10 +585,12 @@ var Runtime = class { // eslint-disable-line
if (!this._cachedTypeClasses[typeName]) {
const path = typeName.split('.');
let object = self;
- for (let i = 0; object && (i < path.length); ++i)
+ for (let i = 0; object && (i < path.length); ++i) {
object = object[path[i]];
- if (object)
+ }
+ if (object) {
this._cachedTypeClasses[typeName] = /** @type function(new:Object) */ (object);
+ }
}
return this._cachedTypeClasses[typeName] || null;
}
@@ -562,14 +602,15 @@ var Runtime = class { // eslint-disable-line
*/
sharedInstance(constructorFunction) {
if (Runtime._instanceSymbol in constructorFunction &&
- Object.getOwnPropertySymbols(constructorFunction).includes(Runtime._instanceSymbol))
+ Object.getOwnPropertySymbols(constructorFunction).includes(Runtime._instanceSymbol)) {
return constructorFunction[Runtime._instanceSymbol];
+ }
const instance = new constructorFunction();
constructorFunction[Runtime._instanceSymbol] = instance;
return instance;
}
-};
+}
/** @type {!URLSearchParams} */
Runtime._queryParamsObject = new URLSearchParams(Runtime.queryParamsString());
@@ -594,7 +635,7 @@ Runtime._platform = '';
/**
* @unrestricted
*/
-Runtime.ModuleDescriptor = class {
+class ModuleDescriptor {
constructor() {
/**
* @type {string}
@@ -602,7 +643,7 @@ Runtime.ModuleDescriptor = class {
this.name;
/**
- * @type {!Array.<!Runtime.ExtensionDescriptor>}
+ * @type {!Array.<!RuntimeExtensionDescriptor>}
*/
this.extensions;
@@ -626,12 +667,14 @@ Runtime.ModuleDescriptor = class {
*/
this.remote;
}
-};
+}
+// This class is named like this, because we already have an "ExtensionDescriptor" in the externs
+// These two do not share the same structure
/**
* @unrestricted
*/
-Runtime.ExtensionDescriptor = class {
+class RuntimeExtensionDescriptor {
constructor() {
/**
* @type {string}
@@ -653,28 +696,28 @@ Runtime.ExtensionDescriptor = class {
*/
this.contextTypes;
}
-};
+}
/**
* @unrestricted
*/
-Runtime.Module = class {
+class Module {
/**
* @param {!Runtime} manager
- * @param {!Runtime.ModuleDescriptor} descriptor
+ * @param {!ModuleDescriptor} descriptor
*/
constructor(manager, descriptor) {
this._manager = manager;
this._descriptor = descriptor;
this._name = descriptor.name;
- /** @type {!Array<!Runtime.Extension>} */
+ /** @type {!Array<!Extension>} */
this._extensions = [];
- /** @type {!Map<string, !Array<!Runtime.Extension>>} */
+ /** @type {!Map<string, !Array<!Extension>>} */
this._extensionsByClassName = new Map();
- const extensions = /** @type {?Array.<!Runtime.ExtensionDescriptor>} */ (descriptor.extensions);
+ const extensions = /** @type {?Array.<!RuntimeExtensionDescriptor>} */ (descriptor.extensions);
for (let i = 0; extensions && i < extensions.length; ++i) {
- const extension = new Runtime.Extension(this, extensions[i]);
+ const extension = new Extension(this, extensions[i]);
this._manager._extensions.push(extension);
this._extensions.push(extension);
}
@@ -702,8 +745,9 @@ Runtime.Module = class {
resource(name) {
const fullName = this._name + '/' + name;
const content = Runtime.cachedResources[fullName];
- if (!content)
+ if (!content) {
throw new Error(fullName + ' not preloaded. Check module.json');
+ }
return content;
}
@@ -711,16 +755,19 @@ Runtime.Module = class {
* @return {!Promise.<undefined>}
*/
_loadPromise() {
- if (!this.enabled())
+ if (!this.enabled()) {
return Promise.reject(new Error('Module ' + this._name + ' is not enabled'));
+ }
- if (this._pendingLoadPromise)
+ if (this._pendingLoadPromise) {
return this._pendingLoadPromise;
+ }
const dependencies = this._descriptor.dependencies;
const dependencyPromises = [];
- for (let i = 0; dependencies && i < dependencies.length; ++i)
+ for (let i = 0; dependencies && i < dependencies.length; ++i) {
dependencyPromises.push(this._manager._modulesMap[dependencies[i]]._loadPromise());
+ }
this._pendingLoadPromise = Promise.all(dependencyPromises)
.then(this._loadResources.bind(this))
@@ -736,8 +783,9 @@ Runtime.Module = class {
*/
_loadResources() {
const resources = this._descriptor['resources'];
- if (!resources || !resources.length)
+ if (!resources || !resources.length) {
return Promise.resolve();
+ }
const promises = [];
for (let i = 0; i < resources.length; ++i) {
const url = this._modularizeURL(resources[i]);
@@ -751,8 +799,9 @@ Runtime.Module = class {
* @return {!Promise.<undefined>}
*/
_loadScripts() {
- if (!this._descriptor.scripts || !this._descriptor.scripts.length)
+ if (!this._descriptor.scripts || !this._descriptor.scripts.length) {
return Promise.resolve();
+ }
// Module namespaces.
// NOTE: Update scripts/special_case_namespaces.json if you add a special cased namespace.
@@ -791,6 +840,16 @@ Runtime.Module = class {
}
/**
+ * @param {string} resourceName
+ * @return {!Promise.<string>}
+ */
+ fetchResource(resourceName) {
+ const base = this._remoteBase();
+ const sourceURL = Runtime.getResourceURL(this._modularizeURL(resourceName), base);
+ return base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
+ }
+
+ /**
* @param {string} value
* @return {string}
*/
@@ -802,16 +861,15 @@ Runtime.Module = class {
return base + this._modularizeURL(url);
}
}
-};
+}
/**
* @unrestricted
*/
-Runtime.Extension = class {
- /**
+class Extension { /**
* @param {!Runtime.Module} module
- * @param {!Runtime.ExtensionDescriptor} descriptor
+ * @param {!RuntimeExtensionDescriptor} descriptor
*/
constructor(module, descriptor) {
this._module = module;
@@ -852,8 +910,9 @@ Runtime.Extension = class {
* @return {?function(new:Object)}
*/
_typeClass() {
- if (!this._hasTypeClass)
+ if (!this._hasTypeClass) {
return null;
+ }
return this._module._manager._resolve(this._type.substring(1));
}
@@ -884,13 +943,16 @@ Runtime.Extension = class {
*/
_createInstance() {
const className = this._className || this._factoryName;
- if (!className)
+ if (!className) {
throw new Error('Could not instantiate extension with no class');
+ }
const constructorFunction = self.eval(/** @type {string} */ (className));
- if (!(constructorFunction instanceof Function))
+ if (!(constructorFunction instanceof Function)) {
throw new Error('Could not instantiate: ' + className);
- if (this._className)
+ }
+ if (this._className) {
return this._module._manager.sharedInstance(constructorFunction);
+ }
return new constructorFunction(this);
}
@@ -899,8 +961,9 @@ Runtime.Extension = class {
*/
title() {
const title = this._descriptor['title-' + Runtime._platform] || this._descriptor['title'];
- if (title && Runtime._l10nCallback)
+ if (title && Runtime._l10nCallback) {
return Runtime._l10nCallback(title);
+ }
return title;
}
@@ -910,20 +973,22 @@ Runtime.Extension = class {
*/
hasContextType(contextType) {
const contextTypes = this.descriptor().contextTypes;
- if (!contextTypes)
+ if (!contextTypes) {
return false;
+ }
for (let i = 0; i < contextTypes.length; ++i) {
- if (contextType === this._module._manager._resolve(contextTypes[i]))
+ if (contextType === this._module._manager._resolve(contextTypes[i])) {
return true;
+ }
}
return false;
}
-};
+}
/**
* @unrestricted
*/
-Runtime.ExperimentsSupport = class {
+class ExperimentsSupport {
constructor() {
this._supportEnabled = Runtime.queryParam('experiments') !== null;
this._experiments = [];
@@ -940,8 +1005,9 @@ Runtime.ExperimentsSupport = class {
const result = [];
for (let i = 0; i < this._experiments.length; i++) {
const experiment = this._experiments[i];
- if (!this._enabledTransiently[experiment.name])
+ if (!this._enabledTransiently[experiment.name]) {
result.push(experiment);
+ }
}
return result;
}
@@ -957,8 +1023,9 @@ Runtime.ExperimentsSupport = class {
* @param {!Object} value
*/
_setExperimentsSetting(value) {
- if (!self.localStorage)
+ if (!self.localStorage) {
return;
+ }
self.localStorage['experiments'] = JSON.stringify(value);
}
@@ -981,14 +1048,18 @@ Runtime.ExperimentsSupport = class {
this._checkExperiment(experimentName);
// Check for explicitly disabled experiments first - the code could call setEnable(false) on the experiment enabled
// by default and we should respect that.
- if (Runtime._experimentsSetting()[experimentName] === false)
+ if (Runtime._experimentsSetting()[experimentName] === false) {
return false;
- if (this._enabledTransiently[experimentName])
+ }
+ if (this._enabledTransiently[experimentName]) {
return true;
- if (this._serverEnabled.has(experimentName))
+ }
+ if (this._serverEnabled.has(experimentName)) {
return true;
- if (!this.supportEnabled())
+ }
+ if (!this.supportEnabled()) {
return false;
+ }
return !!Runtime._experimentsSetting()[experimentName];
}
@@ -1044,8 +1115,9 @@ Runtime.ExperimentsSupport = class {
const cleanedUpExperimentSetting = {};
for (let i = 0; i < this._experiments.length; ++i) {
const experimentName = this._experiments[i].name;
- if (experimentsSetting[experimentName])
+ if (experimentsSetting[experimentName]) {
cleanedUpExperimentSetting[experimentName] = true;
+ }
}
this._setExperimentsSetting(cleanedUpExperimentSetting);
}
@@ -1056,12 +1128,12 @@ Runtime.ExperimentsSupport = class {
_checkExperiment(experimentName) {
Runtime._assert(this._experimentNames[experimentName], 'Unknown experiment ' + experimentName);
}
-};
+}
/**
* @unrestricted
*/
-Runtime.Experiment = class {
+class Experiment {
/**
* @param {!Runtime.ExperimentsSupport} experiments
* @param {string} name
@@ -1088,10 +1160,10 @@ Runtime.Experiment = class {
setEnabled(enabled) {
this._experiments.setEnabled(this.name, enabled);
}
-};
+}
// This must be constructed after the query parameters have been parsed.
-Runtime.experiments = new Runtime.ExperimentsSupport();
+Runtime.experiments = new ExperimentsSupport();
/** @type {Function} */
Runtime._appStartedPromiseCallback;
@@ -1107,36 +1179,40 @@ Runtime._remoteBase;
(function validateRemoteBase() {
if (location.href.startsWith('devtools://devtools/bundled/') && Runtime.queryParam('remoteBase')) {
const versionMatch = /\/serve_file\/(@[0-9a-zA-Z]+)\/?$/.exec(Runtime.queryParam('remoteBase'));
- if (versionMatch)
+ if (versionMatch) {
Runtime._remoteBase = `${location.origin}/remote/serve_file/${versionMatch[1]}/`;
+ }
}
})();
+self.Root = self.Root || {};
+Root = Root || {};
-/**
- * @interface
- */
-function ServicePort() {
-}
-
-ServicePort.prototype = {
- /**
- * @param {function(string)} messageHandler
- * @param {function(string)} closeHandler
- */
- setHandlers(messageHandler, closeHandler) {},
+// This gets all concatenated module descriptors in the release mode.
+Root.allDescriptors = [];
- /**
- * @param {string} message
- * @return {!Promise<boolean>}
- */
- send(message) {},
+Root.applicationDescriptor = undefined;
- /**
- * @return {!Promise<boolean>}
- */
- close() {}
-};
+/** @constructor */
+Root.Runtime = Runtime;
/** @type {!Runtime} */
-var runtime; // eslint-disable-line
+Root.runtime;
+
+/** @constructor */
+Root.Runtime.ModuleDescriptor = ModuleDescriptor;
+
+/** @constructor */
+Root.Runtime.ExtensionDescriptor = RuntimeExtensionDescriptor;
+
+/** @constructor */
+Root.Runtime.Extension = Extension;
+
+/** @constructor */
+Root.Runtime.Module = Module;
+
+/** @constructor */
+Root.Runtime.ExperimentsSupport = ExperimentsSupport;
+
+/** @constructor */
+Root.Runtime.Experiment = Experiment; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Tests.js b/chromium/third_party/blink/renderer/devtools/front_end/Tests.js
index 33dc3a008ea..c9e71390505 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Tests.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Tests.js
@@ -67,10 +67,11 @@
* @param {string} message Failure description.
*/
TestSuite.prototype.fail = function(message) {
- if (this.controlTaken_)
+ if (this.controlTaken_) {
this.reportFailure_(message);
- else
+ } else {
throw message;
+ }
};
/**
@@ -82,8 +83,9 @@
TestSuite.prototype.assertEquals = function(expected, actual, opt_message) {
if (expected !== actual) {
let message = 'Expected: \'' + expected + '\', but was \'' + actual + '\'';
- if (opt_message)
+ if (opt_message) {
message = opt_message + '(' + message + ')';
+ }
this.fail(message);
}
};
@@ -147,8 +149,9 @@
const methodName = args.shift();
try {
this[methodName].apply(this, args);
- if (!this.controlTaken_)
+ if (!this.controlTaken_) {
this.reportOk_();
+ }
} catch (e) {
this.reportFailure_(e);
}
@@ -177,16 +180,18 @@
*/
TestSuite.prototype.addSniffer = function(receiver, methodName, override, opt_sticky) {
const orig = receiver[methodName];
- if (typeof orig !== 'function')
+ if (typeof orig !== 'function') {
this.fail('Cannot find method to override: ' + methodName);
+ }
const test = this;
receiver[methodName] = function(var_args) {
let result;
try {
result = orig.apply(this, arguments);
} finally {
- if (!opt_sticky)
+ if (!opt_sticky) {
receiver[methodName] = orig;
+ }
}
// In case of exception the override won't be called.
try {
@@ -223,8 +228,9 @@
}
function onSchedule() {
- if (scheduleShouldFail)
+ if (scheduleShouldFail) {
test.fail('Unexpected Throttler.schedule');
+ }
}
checkState();
@@ -347,8 +353,9 @@
// frontend is being loaded.
TestSuite.prototype.testPauseWhenLoadingDevTools = function() {
const debuggerModel = SDK.targetManager.mainTarget().model(SDK.DebuggerModel);
- if (debuggerModel.debuggerPausedDetails)
+ if (debuggerModel.debuggerPausedDetails) {
return;
+ }
this.showPanel('sources').then(function() {
// Script execution can already be paused.
@@ -430,8 +437,9 @@
const test = this;
function finishRequest(request, finishTime) {
- if (!request.responseHeadersText)
+ if (!request.responseHeadersText) {
test.fail('Failure: resource does not have response headers text');
+ }
const index = request.responseHeadersText.indexOf('Date:');
test.assertEquals(
112, request.responseHeadersText.substring(index).length, 'Incorrect response headers text length');
@@ -501,8 +509,9 @@
test.assertTrue(request.timing.pushEnd < request.endTime, 'pushEnd should be before endTime');
test.assertTrue(request.startTime < request.timing.pushEnd, 'pushEnd should be after startTime');
}
- if (!--pendingRequestCount)
+ if (!--pendingRequestCount) {
test.releaseControl();
+ }
}
this.addSniffer(SDK.NetworkDispatcher.prototype, '_finishNetworkRequest', finishRequest, true);
@@ -518,15 +527,17 @@
return SDK.consoleModel.messages().filter(a => a.source !== SDK.ConsoleMessage.MessageSource.Violation);
}
- if (filteredMessages().length === 1)
+ if (filteredMessages().length === 1) {
firstConsoleMessageReceived.call(this, null);
- else
+ } else {
SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
+ }
function firstConsoleMessageReceived(event) {
- if (event && event.data.source === SDK.ConsoleMessage.MessageSource.Violation)
+ if (event && event.data.source === SDK.ConsoleMessage.MessageSource.Violation) {
return;
+ }
SDK.consoleModel.removeEventListener(SDK.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);
this.evaluateInConsole_('clickLink();', didClickLink.bind(this));
}
@@ -585,8 +596,9 @@
function onConsoleMessage(event) {
const message = event.data.messageText;
- if (message !== 'connected')
+ if (message !== 'connected') {
this.fail('Unexpected message: ' + message);
+ }
this.releaseControl();
}
};
@@ -594,8 +606,9 @@
TestSuite.prototype.testSharedWorkerNetworkPanel = function() {
this.takeControl();
this.showPanel('network').then(() => {
- if (!document.querySelector('#network-container'))
+ if (!document.querySelector('#network-container')) {
this.fail('unable to find #network-container');
+ }
this.releaseControl();
});
};
@@ -608,8 +621,9 @@
TestSuite.prototype.waitForDebuggerPaused = function() {
const debuggerModel = SDK.targetManager.mainTarget().model(SDK.DebuggerModel);
- if (debuggerModel.debuggerPausedDetails)
+ if (debuggerModel.debuggerPausedDetails) {
return;
+ }
this.takeControl();
this._waitForScriptPause(this.releaseControl.bind(this));
@@ -709,8 +723,9 @@
signalToShowAutofill();
}
// This log comes from the browser unittest code.
- if (message === 'didShowSuggestions')
+ if (message === 'didShowSuggestions') {
selectTopAutoFill();
+ }
}
this.takeControl();
@@ -734,10 +749,10 @@
this.assertEquals(119, event.data.keyCode);
this.assertEquals(0, event.data.modifiers);
this.assertEquals('', event.data.code);
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyUp, this);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyUp, this);
SDK.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent(
{type: 'keyUp', key: 'F8', code: 'F8', windowsVirtualKeyCode: 119, nativeVirtualKeyCode: 119});
}
@@ -750,8 +765,8 @@
this.releaseControl();
}
this.takeControl();
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this);
SDK.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent(
{type: 'rawKeyDown', key: 'F8', windowsVirtualKeyCode: 119, nativeVirtualKeyCode: 119});
};
@@ -765,7 +780,7 @@
// Check that showing the certificate viewer does not crash, crbug.com/954874
TestSuite.prototype.testShowCertificate = function() {
- InspectorFrontendHost.showCertificateViewer([
+ Host.InspectorFrontendHost.showCertificateViewer([
'MIIFIDCCBAigAwIBAgIQE0TsEu6R8FUHQv+9fE7j8TANBgkqhkiG9w0BAQsF' +
'ADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp' +
'Y2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4X' +
@@ -929,10 +944,11 @@
const color = [0, 0, 0];
color[count % 3] = 255;
div.style.backgroundColor = 'rgb(' + color.join(',') + ')';
- if (++count > 10)
+ if (++count > 10) {
requestAnimationFrame(callback);
- else
+ } else {
requestAnimationFrame(frame);
+ }
}
}
@@ -951,8 +967,9 @@
function loadFrameImages(frames) {
const readyImages = [];
- for (const frame of frames)
+ for (const frame of frames) {
frame.imageDataPromise().then(onGotImageData);
+ }
function onGotImageData(data) {
const image = new Image();
@@ -963,8 +980,9 @@
function onLoad(event) {
readyImages.push(event.target);
- if (readyImages.length === frames.length)
+ if (readyImages.length === frames.length) {
validateImagesAndCompleteTest(readyImages);
+ }
}
}
@@ -983,14 +1001,15 @@
ctx.drawImage(image, 0, 0);
const data = ctx.getImageData(0, 0, 1, 1);
const color = Array.prototype.join.call(data.data, ',');
- if (data.data[0] > 200)
+ if (data.data[0] > 200) {
redCount++;
- else if (data.data[1] > 200)
+ } else if (data.data[1] > 200) {
greenCount++;
- else if (data.data[2] > 200)
+ } else if (data.data[2] > 200) {
blueCount++;
- else
+ } else {
test.fail('Unexpected color: ' + color);
+ }
}
test.assertTrue(redCount && greenCount && blueCount, 'Color sanity check failed');
test.releaseControl();
@@ -1014,8 +1033,8 @@
}
function reset() {
- Runtime.experiments.clearForTest();
- InspectorFrontendHost.getPreferences(gotPreferences);
+ Root.Runtime.experiments.clearForTest();
+ Host.InspectorFrontendHost.getPreferences(gotPreferences);
}
function gotPreferences(prefs) {
@@ -1037,10 +1056,11 @@
const test = this;
test.takeControl();
const messages = SDK.consoleModel.messages();
- if (messages.length === 1)
+ if (messages.length === 1) {
checkMessages();
- else
+ } else {
SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, checkMessages.bind(this), this);
+ }
function checkMessages() {
const messages = SDK.consoleModel.messages();
@@ -1059,8 +1079,9 @@
const consoleView = Console.ConsoleView.instance();
const selector = consoleView._consoleContextSelector;
const values = [];
- for (const item of selector._items)
+ for (const item of selector._items) {
values.push(selector.titleFor(item));
+ }
test.assertEquals('top', values[0]);
test.assertEquals('Simple content script', values[1]);
test.releaseControl();
@@ -1082,8 +1103,9 @@
let count = 0;
function onResponseReceived(event) {
const networkRequest = event.data;
- if (!networkRequest.url().startsWith('http'))
+ if (!networkRequest.url().startsWith('http')) {
return;
+ }
switch (++count) {
case 1: // Original redirect
test.assertEquals(301, networkRequest.statusCode);
@@ -1121,18 +1143,20 @@
const messages = SDK.consoleModel.messages();
for (let i = 0; i < messages.length; ++i) {
const text = messages[i].messageText;
- if (text === 'PASS')
+ if (text === 'PASS') {
return;
- else if (/^FAIL/.test(text))
- this.fail(text); // This will throw.
+ } else if (/^FAIL/.test(text)) {
+ this.fail(text);
+ } // This will throw.
}
// Neither PASS nor FAIL, so wait for more messages.
function onConsoleMessage(event) {
const text = event.data.messageText;
- if (text === 'PASS')
+ if (text === 'PASS') {
this.releaseControl();
- else if (/^FAIL/.test(text))
+ } else if (/^FAIL/.test(text)) {
this.fail(text);
+ }
}
SDK.consoleModel.addEventListener(SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
@@ -1206,7 +1230,7 @@
};
TestSuite.prototype.enableExperiment = function(name) {
- Runtime.experiments.enableForTest(name);
+ Root.Runtime.experiments.enableForTest(name);
};
TestSuite.prototype.checkInputEventsPresent = function() {
@@ -1216,24 +1240,29 @@
const input = asyncEvents.get(TimelineModel.TimelineModel.AsyncEventGroup.input) || [];
const prefix = 'InputLatency::';
for (const e of input) {
- if (!e.name.startsWith(prefix))
+ if (!e.name.startsWith(prefix)) {
continue;
- if (e.steps.length < 2)
+ }
+ if (e.steps.length < 2) {
continue;
+ }
if (e.name.startsWith(prefix + 'Mouse') &&
- typeof TimelineModel.TimelineData.forEvent(e.steps[0]).timeWaitingForMainThread !== 'number')
+ typeof TimelineModel.TimelineData.forEvent(e.steps[0]).timeWaitingForMainThread !== 'number') {
throw `Missing timeWaitingForMainThread on ${e.name}`;
+ }
expectedEvents.delete(e.name.substr(prefix.length));
}
- if (expectedEvents.size)
+ if (expectedEvents.size) {
throw 'Some expected events are not found: ' + Array.from(expectedEvents.keys()).join(',');
+ }
};
TestSuite.prototype.testInspectedElementIs = async function(nodeName) {
this.takeControl();
await self.runtime.loadModulePromise('elements');
- if (!Elements.ElementsPanel._firstInspectElementNodeNameForTest)
+ if (!Elements.ElementsPanel._firstInspectElementNodeNameForTest) {
await new Promise(f => this.addSniffer(Elements.ElementsPanel, '_firstInspectElementCompletedForTest', f));
+ }
this.assertEquals(nodeName, Elements.ElementsPanel._firstInspectElementNodeNameForTest);
this.releaseControl();
};
@@ -1374,8 +1403,9 @@
const headersArray = [];
for (const name in headers) {
const nameLower = name.toLowerCase();
- if (loggedHeaders.has(nameLower))
+ if (loggedHeaders.has(nameLower)) {
headersArray.push(nameLower);
+ }
}
headersArray.sort();
test.assertEquals(expectedHeaders.join(', '), headersArray.join(', '));
@@ -1407,6 +1437,7 @@
baseURL + 'echoheader?Cookie', undefined, 200, ['cache-control'], 'devtools-test-cookie=same-site-cookie');
await testCase('data:text/html,<body>hello</body>', undefined, 200, [], '<body>hello</body>');
await testCase(fileURL, undefined, 200, [], '<html>\n<body>\nDummy page.\n</body>\n</html>\n');
+ await testCase(fileURL + 'thisfileshouldnotbefound', undefined, 404, [], '');
this.releaseControl();
};
@@ -1419,15 +1450,18 @@
function onRequestUpdated(event) {
const request = event.data;
- if (request.resourceType() !== Common.resourceTypes.WebSocket)
+ if (request.resourceType() !== Common.resourceTypes.WebSocket) {
return;
- if (!request.requestHeadersText())
+ }
+ if (!request.requestHeadersText()) {
return;
+ }
let actualUserAgent = 'no user-agent header';
for (const {name, value} of request.requestHeaders()) {
- if (name.toLowerCase() === 'user-agent')
+ if (name.toLowerCase() === 'user-agent') {
actualUserAgent = value;
+ }
}
this.assertEquals(testUserAgent, actualUserAgent);
this.releaseControl();
@@ -1445,8 +1479,9 @@
*/
TestSuite.prototype.uiSourceCodesToString_ = function(uiSourceCodes) {
const names = [];
- for (let i = 0; i < uiSourceCodes.length; i++)
+ for (let i = 0; i < uiSourceCodes.length; i++) {
names.push('"' + uiSourceCodes[i].url() + '"');
+ }
return names.join(',');
};
@@ -1532,10 +1567,11 @@
const test = this;
function waitForAllScripts() {
- if (test._scriptsAreParsed(expectedScripts))
+ if (test._scriptsAreParsed(expectedScripts)) {
callback();
- else
+ } else {
test.addSniffer(UI.panels.sources.sourcesView(), '_addUISourceCode', waitForAllScripts);
+ }
}
waitForAllScripts();
@@ -1545,10 +1581,11 @@
checkTargets.call(this);
function checkTargets() {
- if (SDK.targetManager.targets().length >= n)
+ if (SDK.targetManager.targets().length >= n) {
callback.call(null);
- else
+ } else {
this.addSniffer(SDK.TargetManager.prototype, 'createTarget', checkTargets.bind(this));
+ }
}
};
@@ -1557,10 +1594,11 @@
checkForExecutionContexts.call(this);
function checkForExecutionContexts() {
- if (runtimeModel.executionContexts().length >= n)
+ if (runtimeModel.executionContexts().length >= n) {
callback.call(null);
- else
+ } else {
this.addSniffer(SDK.RuntimeModel.prototype, '_executionContextCreated', checkForExecutionContexts.bind(this));
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAAttributesView.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAAttributesView.js
index a8a61db6912..f5a000bce35 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAAttributesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAAttributesView.js
@@ -19,14 +19,16 @@ Accessibility.ARIAAttributesPane = class extends Accessibility.AccessibilitySubP
setNode(node) {
super.setNode(node);
this._treeOutline.removeChildren();
- if (!this.node())
+ if (!this.node()) {
return;
+ }
const target = this.node().domModel().target();
const attributes = node.attributes();
for (let i = 0; i < attributes.length; ++i) {
const attribute = attributes[i];
- if (Accessibility.ARIAAttributesPane._attributes.indexOf(attribute.name) < 0)
+ if (Accessibility.ARIAAttributesPane._attributes.indexOf(attribute.name) < 0) {
continue;
+ }
this._treeOutline.appendChild(new Accessibility.ARIAAttributesTreeElement(this, attribute, target));
}
@@ -76,7 +78,7 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
_populateListItem() {
this.listItemElement.removeChildren();
this.appendNameElement(this._attribute.name);
- this.listItemElement.createChild('span', 'separator').textContent = ':\u00A0';
+ this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
this.appendAttributeValueElement(this._attribute.value);
}
@@ -103,8 +105,9 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_mouseClick(event) {
- if (event.target === this.listItemElement)
+ if (event.target === this.listItemElement) {
return;
+ }
event.consume(true);
@@ -114,8 +117,9 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
_startEditing() {
const valueElement = this._valueElement;
- if (UI.isBeingEdited(valueElement))
+ if (UI.isBeingEdited(valueElement)) {
return;
+ }
const previousContent = valueElement.textContent;
@@ -140,8 +144,9 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
}
_removePrompt() {
- if (!this._prompt)
+ if (!this._prompt) {
return;
+ }
this._prompt.detach();
delete this._prompt;
}
@@ -154,8 +159,9 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
this._removePrompt();
// Make the changes to the attribute
- if (userInput !== previousContent)
+ if (userInput !== previousContent) {
this._parentPane.node().setAttributeValue(this._attribute.name, userInput);
+ }
}
_editingCancelled() {
@@ -168,8 +174,9 @@ Accessibility.ARIAAttributesTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_editingValueKeyDown(previousContent, event) {
- if (event.handled)
+ if (event.handled) {
return;
+ }
if (isEnterKey(event)) {
this._editingCommitted(event.target.textContent, previousContent);
@@ -210,8 +217,9 @@ Accessibility.ARIAAttributesPane.ARIAAttributePrompt = class extends UI.TextProm
*/
_buildPropertyCompletions(expression, prefix, force) {
prefix = prefix.toLowerCase();
- if (!prefix && !force && (this._isEditingName || expression))
+ if (!prefix && !force && (this._isEditingName || expression)) {
return Promise.resolve([]);
+ }
return Promise.resolve(this._ariaCompletions.filter(value => value.startsWith(prefix)).map(c => ({text: c})));
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAMetadata.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAMetadata.js
index 8038ae03084..46a19abab18 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAMetadata.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/ARIAMetadata.js
@@ -12,8 +12,9 @@ Accessibility.ARIAMetadata = class {
/** @type {!Map<string, !Accessibility.ARIAMetadata.Attribute>} */
this._attributes = new Map();
- if (config)
+ if (config) {
this._initialize(config);
+ }
}
/**
@@ -24,8 +25,9 @@ Accessibility.ARIAMetadata = class {
const booleanEnum = ['true', 'false'];
for (const attributeConfig of attributes) {
- if (attributeConfig.type === 'boolean')
+ if (attributeConfig.type === 'boolean') {
attributeConfig.enum = booleanEnum;
+ }
this._attributes.set(attributeConfig.name, new Accessibility.ARIAMetadata.Attribute(attributeConfig));
}
@@ -38,11 +40,13 @@ Accessibility.ARIAMetadata = class {
* @return {!Array<string>}
*/
valuesForProperty(property) {
- if (this._attributes.has(property))
+ if (this._attributes.has(property)) {
return this._attributes.get(property).getEnum();
+ }
- if (property === 'role')
+ if (property === 'role') {
return this._roleNames;
+ }
return [];
}
@@ -52,8 +56,9 @@ Accessibility.ARIAMetadata = class {
* @return {!Accessibility.ARIAMetadata}
*/
Accessibility.ariaMetadata = function() {
- if (!Accessibility.ARIAMetadata._instance)
+ if (!Accessibility.ARIAMetadata._instance) {
Accessibility.ARIAMetadata._instance = new Accessibility.ARIAMetadata(Accessibility.ARIAMetadata._config || null);
+ }
return Accessibility.ARIAMetadata._instance;
};
@@ -68,8 +73,9 @@ Accessibility.ARIAMetadata.Attribute = class {
/** @type {!Array<string>} */
this._enum = [];
- if ('enum' in config)
+ if ('enum' in config) {
this._enum = config.enum;
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AXBreadcrumbsPane.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AXBreadcrumbsPane.js
index 9075c5e80eb..fada19f65b4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AXBreadcrumbsPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AXBreadcrumbsPane.js
@@ -36,10 +36,11 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @override
*/
focus() {
- if (this._inspectedNodeBreadcrumb)
+ if (this._inspectedNodeBreadcrumb) {
this._inspectedNodeBreadcrumb.nodeElement().focus();
- else
+ } else {
this.element.focus();
+ }
}
/**
@@ -52,8 +53,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
this._rootElement.removeChildren();
- if (!axNode)
+ if (!axNode) {
return;
+ }
const ancestorChain = [];
let ancestor = axNode;
@@ -68,10 +70,11 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
let parent = null;
for (ancestor of ancestorChain) {
breadcrumb = new Accessibility.AXBreadcrumb(ancestor, depth, (ancestor === axNode));
- if (parent)
+ if (parent) {
parent.appendChild(breadcrumb);
- else
+ } else {
this._rootElement.appendChild(breadcrumb.element());
+ }
parent = breadcrumb;
depth++;
}
@@ -91,12 +94,14 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
parentBreadcrumb.appendChild(childBreadcrumb);
// In most cases there will be no children here, but there are some special cases.
- for (const child of axNode.children())
+ for (const child of axNode.children()) {
append(childBreadcrumb, child, localDepth + 1);
+ }
}
- for (const child of axNode.children())
+ for (const child of axNode.children()) {
append(this._inspectedNodeBreadcrumb, child, depth);
+ }
}
/**
@@ -110,23 +115,28 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @param {!Event} event
*/
_onKeyDown(event) {
- if (!this._preselectedBreadcrumb)
+ if (!this._preselectedBreadcrumb) {
return;
- if (!event.composedPath().some(element => element === this._preselectedBreadcrumb.element()))
+ }
+ if (!event.composedPath().some(element => element === this._preselectedBreadcrumb.element())) {
return;
- if (event.shiftKey || event.metaKey || event.ctrlKey)
+ }
+ if (event.shiftKey || event.metaKey || event.ctrlKey) {
return;
+ }
let handled = false;
- if ((event.key === 'ArrowUp' || event.key === 'ArrowLeft') && !event.altKey)
+ if ((event.key === 'ArrowUp' || event.key === 'ArrowLeft') && !event.altKey) {
handled = this._preselectPrevious();
- else if ((event.key === 'ArrowDown' || event.key === 'ArrowRight') && !event.altKey)
+ } else if ((event.key === 'ArrowDown' || event.key === 'ArrowRight') && !event.altKey) {
handled = this._preselectNext();
- else if (isEnterKey(event))
+ } else if (isEnterKey(event)) {
handled = this._inspectDOMNode(this._preselectedBreadcrumb.axNode());
+ }
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -134,8 +144,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
*/
_preselectPrevious() {
const previousBreadcrumb = this._preselectedBreadcrumb.previousBreadcrumb();
- if (!previousBreadcrumb)
+ if (!previousBreadcrumb) {
return false;
+ }
this._setPreselectedBreadcrumb(previousBreadcrumb);
return true;
}
@@ -145,8 +156,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
*/
_preselectNext() {
const nextBreadcrumb = this._preselectedBreadcrumb.nextBreadcrumb();
- if (!nextBreadcrumb)
+ if (!nextBreadcrumb) {
return false;
+ }
this._setPreselectedBreadcrumb(nextBreadcrumb);
return true;
}
@@ -155,19 +167,23 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @param {?Accessibility.AXBreadcrumb} breadcrumb
*/
_setPreselectedBreadcrumb(breadcrumb) {
- if (breadcrumb === this._preselectedBreadcrumb)
+ if (breadcrumb === this._preselectedBreadcrumb) {
return;
+ }
const hadFocus = this.element.hasFocus();
- if (this._preselectedBreadcrumb)
+ if (this._preselectedBreadcrumb) {
this._preselectedBreadcrumb.setPreselected(false, hadFocus);
+ }
- if (breadcrumb)
+ if (breadcrumb) {
this._preselectedBreadcrumb = breadcrumb;
- else
+ } else {
this._preselectedBreadcrumb = this._inspectedNodeBreadcrumb;
+ }
this._preselectedBreadcrumb.setPreselected(true, hadFocus);
- if (!breadcrumb && hadFocus)
+ if (!breadcrumb && hadFocus) {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
}
/**
@@ -187,8 +203,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
return;
}
const breadcrumb = breadcrumbElement.breadcrumb;
- if (!breadcrumb.isDOMNode())
+ if (!breadcrumb.isDOMNode()) {
return;
+ }
this._setHoveredBreadcrumb(breadcrumb);
}
@@ -196,8 +213,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @param {!Event} event
*/
_onFocusOut(event) {
- if (!this._preselectedBreadcrumb || event.target !== this._preselectedBreadcrumb.nodeElement())
+ if (!this._preselectedBreadcrumb || event.target !== this._preselectedBreadcrumb.nodeElement()) {
return;
+ }
this._setPreselectedBreadcrumb(null);
}
@@ -217,8 +235,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
breadcrumb.nodeElement().focus();
return;
}
- if (!breadcrumb.isDOMNode())
+ if (!breadcrumb.isDOMNode()) {
return;
+ }
this._inspectDOMNode(breadcrumb.axNode());
}
@@ -226,11 +245,13 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @param {?Accessibility.AXBreadcrumb} breadcrumb
*/
_setHoveredBreadcrumb(breadcrumb) {
- if (breadcrumb === this._hoveredBreadcrumb)
+ if (breadcrumb === this._hoveredBreadcrumb) {
return;
+ }
- if (this._hoveredBreadcrumb)
+ if (this._hoveredBreadcrumb) {
this._hoveredBreadcrumb.setHovered(false);
+ }
if (breadcrumb) {
breadcrumb.setHovered(true);
@@ -247,8 +268,9 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
* @return {boolean}
*/
_inspectDOMNode(axNode) {
- if (!axNode.isDOMNode())
+ if (!axNode.isDOMNode()) {
return false;
+ }
axNode.deferredDOMNode().resolve(domNode => {
this._axSidebarView.setNode(domNode, true /* fromAXTree */);
@@ -263,18 +285,21 @@ Accessibility.AXBreadcrumbsPane = class extends Accessibility.AccessibilitySubPa
*/
_contextMenuEventFired(event) {
const breadcrumbElement = event.target.enclosingNodeOrSelfWithClass('ax-breadcrumb');
- if (!breadcrumbElement)
+ if (!breadcrumbElement) {
return;
+ }
const axNode = breadcrumbElement.breadcrumb.axNode();
- if (!axNode.isDOMNode() || !axNode.deferredDOMNode())
+ if (!axNode.isDOMNode() || !axNode.deferredDOMNode()) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
contextMenu.viewSection().appendItem(ls`Scroll into view`, () => {
axNode.deferredDOMNode().resolvePromise().then(domNode => {
- if (!domNode)
+ if (!domNode) {
return;
+ }
domNode.scrollIntoView();
});
});
@@ -327,16 +352,18 @@ Accessibility.AXBreadcrumb = class {
} else {
this._appendRoleElement(this._axNode.role());
if (this._axNode.name() && this._axNode.name().value) {
- this._nodeWrapper.createChild('span', 'separator').textContent = '\u00A0';
+ this._nodeWrapper.createChild('span', 'separator').textContent = '\xA0';
this._appendNameElement(/** @type {string} */ (this._axNode.name().value));
}
}
- if (this._axNode.hasOnlyUnloadedChildren())
+ if (this._axNode.hasOnlyUnloadedChildren()) {
this._nodeElement.classList.add('children-unloaded');
+ }
- if (!this._axNode.isDOMNode())
+ if (!this._axNode.isDOMNode()) {
this._nodeElement.classList.add('no-dom-node');
+ }
}
/**
@@ -383,21 +410,25 @@ Accessibility.AXBreadcrumb = class {
* @param {boolean} selectedByUser
*/
setPreselected(preselected, selectedByUser) {
- if (this._preselected === preselected)
+ if (this._preselected === preselected) {
return;
+ }
this._preselected = preselected;
this._nodeElement.classList.toggle('preselected', preselected);
- if (preselected)
+ if (preselected) {
this._nodeElement.setAttribute('tabIndex', 0);
- else
+ } else {
this._nodeElement.setAttribute('tabIndex', -1);
+ }
if (this._preselected) {
- if (selectedByUser)
+ if (selectedByUser) {
this._nodeElement.focus();
- if (!this._inspected)
+ }
+ if (!this._inspected) {
this._axNode.highlightDOMNode();
- else
+ } else {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
}
}
@@ -405,8 +436,9 @@ Accessibility.AXBreadcrumb = class {
* @param {boolean} hovered
*/
setHovered(hovered) {
- if (this._hovered === hovered)
+ if (this._hovered === hovered) {
return;
+ }
this._hovered = hovered;
this._nodeElement.classList.toggle('hovered', hovered);
if (this._hovered) {
@@ -440,11 +472,13 @@ Accessibility.AXBreadcrumb = class {
* @return {?Accessibility.AXBreadcrumb}
*/
nextBreadcrumb() {
- if (this._children.length)
+ if (this._children.length) {
return this._children[0];
+ }
const nextSibling = this.element().nextSibling;
- if (nextSibling)
+ if (nextSibling) {
return nextSibling.breadcrumb;
+ }
return null;
}
@@ -453,8 +487,9 @@ Accessibility.AXBreadcrumb = class {
*/
previousBreadcrumb() {
const previousSibling = this.element().previousSibling;
- if (previousSibling)
+ if (previousSibling) {
return previousSibling.breadcrumb;
+ }
return this._parent;
}
@@ -473,8 +508,9 @@ Accessibility.AXBreadcrumb = class {
* @param {?Protocol.Accessibility.AXValue} role
*/
_appendRoleElement(role) {
- if (!role)
+ if (!role) {
return;
+ }
const roleElement = createElementWithClass('span', 'monospace');
roleElement.classList.add(Accessibility.AXBreadcrumb.RoleStyles[role.type]);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityModel.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityModel.js
index 9d64b087e0b..7e84997fa8c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityModel.js
@@ -24,8 +24,9 @@ Accessibility.AccessibilityNode = class {
this._deferredDOMNode = null;
}
this._ignored = payload.ignored;
- if (this._ignored && 'ignoredReasons' in payload)
+ if (this._ignored && 'ignoredReasons' in payload) {
this._ignoredReasons = payload.ignoredReasons;
+ }
this._role = payload.role || null;
this._name = payload.name || null;
@@ -70,14 +71,16 @@ Accessibility.AccessibilityNode = class {
coreProperties() {
const properties = [];
- if (this._name)
+ if (this._name) {
properties.push(/** @type {!Protocol.Accessibility.AXProperty} */ ({name: 'name', value: this._name}));
+ }
if (this._description) {
properties.push(
/** @type {!Protocol.Accessibility.AXProperty} */ ({name: 'description', value: this._description}));
}
- if (this._value)
+ if (this._value) {
properties.push(/** @type {!Protocol.Accessibility.AXProperty} */ ({name: 'value', value: this._value}));
+ }
return properties;
}
@@ -146,8 +149,9 @@ Accessibility.AccessibilityNode = class {
}
highlightDOMNode() {
- if (!this.deferredDOMNode())
+ if (!this.deferredDOMNode()) {
return;
+ }
// Highlight node in page.
this.deferredDOMNode().highlight();
@@ -158,13 +162,15 @@ Accessibility.AccessibilityNode = class {
*/
children() {
const children = [];
- if (!this._childIds)
+ if (!this._childIds) {
return children;
+ }
for (const childId of this._childIds) {
const child = this._accessibilityModel.axNodeForId(childId);
- if (child)
+ if (child) {
children.push(child);
+ }
}
return children;
@@ -174,8 +180,9 @@ Accessibility.AccessibilityNode = class {
* @return {number}
*/
numChildren() {
- if (!this._childIds)
+ if (!this._childIds) {
return 0;
+ }
return this._childIds.length;
}
@@ -183,8 +190,9 @@ Accessibility.AccessibilityNode = class {
* @return {boolean}
*/
hasOnlyUnloadedChildren() {
- if (!this._childIds || !this._childIds.length)
+ if (!this._childIds || !this._childIds.length) {
return false;
+ }
return !this._childIds.some(id => this._accessibilityModel.axNodeForId(id) !== undefined);
}
@@ -197,18 +205,22 @@ Accessibility.AccessibilityNode = class {
*/
printSelfAndChildren(inspectedNode, leadingSpace) {
let string = leadingSpace || '';
- if (this._role)
+ if (this._role) {
string += this._role.value;
- else
+ } else {
string += '<no role>';
+ }
string += (this._name ? ' ' + this._name.value : '');
string += ' ' + this._id;
- if (this._domNode)
+ if (this._domNode) {
string += ' (' + this._domNode.nodeName() + ')';
- if (this === inspectedNode)
+ }
+ if (this === inspectedNode) {
string += ' *';
- for (const child of this.children())
+ }
+ for (const child of this.children()) {
string += '\n' + child.printSelfAndChildren(inspectedNode, (leadingSpace || '') + ' ');
+ }
return string;
}
};
@@ -239,15 +251,18 @@ Accessibility.AccessibilityModel = class extends SDK.SDKModel {
*/
async requestPartialAXTree(node) {
const payloads = await this._agent.getPartialAXTree(node.id, undefined, undefined, true);
- if (!payloads)
+ if (!payloads) {
return;
+ }
- for (const payload of payloads)
+ for (const payload of payloads) {
new Accessibility.AccessibilityNode(this, payload);
+ }
for (const axNode of this._axIdToAXNode.values()) {
- for (const axChild of axNode.children())
+ for (const axChild of axNode.children()) {
axChild._setParentNode(axNode);
+ }
}
}
@@ -272,8 +287,9 @@ Accessibility.AccessibilityModel = class extends SDK.SDKModel {
* @return {?Accessibility.AccessibilityNode}
*/
axNodeForDOMNode(domNode) {
- if (!domNode)
+ if (!domNode) {
return null;
+ }
return this._backendDOMNodeIdToAXNode.get(domNode.backendNodeId());
}
@@ -291,8 +307,9 @@ Accessibility.AccessibilityModel = class extends SDK.SDKModel {
*/
logTree(inspectedNode) {
let rootNode = inspectedNode;
- while (rootNode.parentNode())
+ while (rootNode.parentNode()) {
rootNode = rootNode.parentNode();
+ }
console.log(rootNode.printSelfAndChildren(inspectedNode)); // eslint-disable-line no-console
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
index 28996aaca96..26862daf37c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
@@ -18,6 +18,7 @@ Accessibility.AXNodeSubPane = class extends Accessibility.AccessibilitySubPane {
this.element.classList.add('accessibility-computed');
this.registerRequiredCSS('accessibility/accessibilityNode.css');
+ this._treeOutline.setFocusable(true);
}
/**
@@ -25,8 +26,9 @@ Accessibility.AXNodeSubPane = class extends Accessibility.AccessibilitySubPane {
* @override
*/
setAXNode(axNode) {
- if (this._axNode === axNode)
+ if (this._axNode === axNode) {
return;
+ }
this._axNode = axNode;
const treeOutline = this._treeOutline;
@@ -60,10 +62,12 @@ Accessibility.AXNodeSubPane = class extends Accessibility.AccessibilitySubPane {
property, /** @type {!Accessibility.AccessibilityNode} */ (axNode)));
}
const ignoredReasonsArray = /** @type {!Array<!Protocol.Accessibility.AXProperty>} */ (axNode.ignoredReasons());
- for (const reason of ignoredReasonsArray)
+ for (const reason of ignoredReasonsArray) {
addIgnoredReason(reason);
- if (!ignoredReasons.firstChild())
+ }
+ if (!ignoredReasons.firstChild()) {
ignoredReasons.element.classList.add('hidden');
+ }
return;
}
this.element.classList.remove('ax-ignored-node-pane');
@@ -82,13 +86,20 @@ Accessibility.AXNodeSubPane = class extends Accessibility.AccessibilitySubPane {
property, /** @type {!Accessibility.AccessibilityNode} */ (axNode)));
}
- for (const property of axNode.coreProperties())
+ for (const property of axNode.coreProperties()) {
addProperty(property);
+ }
const roleProperty = /** @type {!Protocol.Accessibility.AXProperty} */ ({name: 'role', value: axNode.role()});
addProperty(roleProperty);
- for (const property of /** @type {!Array.<!Protocol.Accessibility.AXProperty>} */ (axNode.properties()))
+ for (const property of /** @type {!Array.<!Protocol.Accessibility.AXProperty>} */ (axNode.properties())) {
addProperty(property);
+ }
+
+ const firstNode = treeOutline.firstChild();
+ if (firstNode) {
+ firstNode.select(/* omitFocus= */ true, /* selectedByUser= */ false);
+ }
}
/**
@@ -122,10 +133,11 @@ Accessibility.AXNodePropertyTreeElement = class extends UI.TreeElement {
static createSimpleValueElement(type, value) {
let valueElement;
const AXValueType = Protocol.Accessibility.AXValueType;
- if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString)
+ if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) {
valueElement = createElement('span');
- else
+ } else {
valueElement = createElementWithClass('span', 'monospace');
+ }
let valueText;
const isStringProperty = type && Accessibility.AXNodePropertyTreeElement.StringProperties.has(type);
if (isStringProperty) {
@@ -136,8 +148,9 @@ Accessibility.AXNodePropertyTreeElement = class extends UI.TreeElement {
valueText = String(value);
}
- if (type && type in Accessibility.AXNodePropertyTreeElement.TypeStyles)
+ if (type && type in Accessibility.AXNodePropertyTreeElement.TypeStyles) {
valueElement.classList.add(Accessibility.AXNodePropertyTreeElement.TypeStyles[type]);
+ }
valueElement.setTextContentTruncatedIfNeeded(valueText || '');
@@ -228,10 +241,11 @@ Accessibility.AXNodePropertyTreeElement = class extends UI.TreeElement {
}
value.relatedNodes.forEach(this.appendRelatedNode, this);
- if (value.relatedNodes.length <= 3)
+ if (value.relatedNodes.length <= 3) {
this.expand();
- else
+ } else {
this.collapse();
+ }
}
};
@@ -272,7 +286,6 @@ Accessibility.AXNodePropertyTreePropertyElement = class extends Accessibility.AX
this._property = property;
this.toggleOnClick = true;
- this.selectable = false;
this.listItemElement.classList.add('property');
}
@@ -289,7 +302,7 @@ Accessibility.AXNodePropertyTreePropertyElement = class extends Accessibility.AX
this.appendNameElement(this._property.name);
- this.listItemElement.createChild('span', 'separator').textContent = ':\u00A0';
+ this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
this.appendValueElement(this._property.value);
}
@@ -306,7 +319,6 @@ Accessibility.AXValueSourceTreeElement = class extends Accessibility.AXNodePrope
constructor(source, axNode) {
super(axNode);
this._source = source;
- this.selectable = false;
}
/**
@@ -339,20 +351,22 @@ Accessibility.AXValueSourceTreeElement = class extends Accessibility.AXNodePrope
if (idrefs.length === 1) {
const idref = idrefs[0];
const matchingNode = relatedNodes.find(node => node.idref === idref);
- if (matchingNode)
+ if (matchingNode) {
this.appendRelatedNodeWithIdref(matchingNode, 0, idref);
- else
+ } else {
this.listItemElement.appendChild(new Accessibility.AXRelatedNodeElement({idref: idref}).render());
+ }
} else {
// TODO(aboxhall): exclamation mark if not idreflist type
for (let i = 0; i < idrefs.length; ++i) {
const idref = idrefs[i];
const matchingNode = relatedNodes.find(node => node.idref === idref);
- if (matchingNode)
+ if (matchingNode) {
this.appendRelatedNodeWithIdref(matchingNode, i, idref);
- else
+ } else {
this.appendChild(new Accessibility.AXRelatedNodeSourceTreeElement({idref: idref}));
+ }
}
}
}
@@ -366,16 +380,18 @@ Accessibility.AXValueSourceTreeElement = class extends Accessibility.AXNodePrope
const numNodes = relatedNodes.length;
if (value.type === Protocol.Accessibility.AXValueType.IdrefList ||
- value.type === Protocol.Accessibility.AXValueType.Idref)
+ value.type === Protocol.Accessibility.AXValueType.Idref) {
this.appendIDRefValueElement(value);
- else
+ } else {
super.appendRelatedNodeListValueElement(value);
+ }
- if (numNodes <= 3)
+ if (numNodes <= 3) {
this.expand();
- else
+ } else {
this.collapse();
+ }
}
/**
@@ -428,16 +444,17 @@ Accessibility.AXValueSourceTreeElement = class extends Accessibility.AXNodePrope
this.appendSourceNameElement(this._source);
- this.listItemElement.createChild('span', 'separator').textContent = ':\u00a0';
+ this.listItemElement.createChild('span', 'separator').textContent = ':\xA0';
if (this._source.attributeValue) {
this.appendValueElement(this._source.attributeValue);
- this.listItemElement.createTextChild('\u00a0');
+ this.listItemElement.createTextChild('\xA0');
} else if (this._source.nativeSourceValue) {
this.appendValueElement(this._source.nativeSourceValue);
- this.listItemElement.createTextChild('\u00a0');
- if (this._source.value)
+ this.listItemElement.createTextChild('\xA0');
+ if (this._source.value) {
this.appendValueElement(this._source.value);
+ }
} else if (this._source.value) {
this.appendValueElement(this._source.value);
} else {
@@ -447,8 +464,9 @@ Accessibility.AXValueSourceTreeElement = class extends Accessibility.AXNodePrope
this.listItemElement.classList.add('ax-value-source-unused');
}
- if (this._source.value && this._source.superseded)
+ if (this._source.value && this._source.superseded) {
this.listItemElement.classList.add('ax-value-source-superseded');
+ }
}
};
@@ -465,7 +483,7 @@ Accessibility.AXRelatedNodeSourceTreeElement = class extends UI.TreeElement {
this._value = value;
this._axRelatedNodeElement = new Accessibility.AXRelatedNodeElement(node, value);
- this.selectable = false;
+ this.selectable = true;
}
/**
@@ -473,14 +491,23 @@ Accessibility.AXRelatedNodeSourceTreeElement = class extends UI.TreeElement {
*/
onattach() {
this.listItemElement.appendChild(this._axRelatedNodeElement.render());
- if (!this._value)
+ if (!this._value) {
return;
+ }
if (this._value.text) {
this.listItemElement.appendChild(Accessibility.AXNodePropertyTreeElement.createSimpleValueElement(
Protocol.Accessibility.AXValueType.ComputedString, this._value.text));
}
}
+
+ /**
+ * @override
+ */
+ onenter() {
+ this._axRelatedNodeElement.revealNode();
+ return true;
+ }
};
/**
@@ -520,6 +547,13 @@ Accessibility.AXRelatedNodeElement = class {
return element;
}
+
+ /**
+ * Attempts to cause the node referred to by the related node to be selected in the tree.
+ */
+ revealNode() {
+ this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
+ }
};
/**
@@ -547,10 +581,10 @@ Accessibility.AXNodeIgnoredReasonTreeElement = class extends Accessibility.AXNod
let reasonElement = null;
switch (reason) {
case 'activeModalDialog':
- reasonElement = UI.formatLocalized('Element is hidden by active modal dialog:\u00a0', []);
+ reasonElement = UI.formatLocalized('Element is hidden by active modal dialog:\xA0', []);
break;
case 'ancestorIsLeafNode':
- reasonElement = UI.formatLocalized('Ancestor\'s children are all presentational:\u00a0', []);
+ reasonElement = UI.formatLocalized('Ancestor\'s children are all presentational:\xA0', []);
break;
case 'ariaHiddenElement': {
const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
@@ -560,7 +594,7 @@ Accessibility.AXNodeIgnoredReasonTreeElement = class extends Accessibility.AXNod
case 'ariaHiddenSubtree': {
const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
const trueSpan = createElement('span', 'source-code').textContent = 'true';
- reasonElement = UI.formatLocalized('%s is %s on ancestor:\u00a0', [ariaHiddenSpan, trueSpan]);
+ reasonElement = UI.formatLocalized('%s is %s on ancestor:\xA0', [ariaHiddenSpan, trueSpan]);
break;
}
case 'emptyAlt':
@@ -573,16 +607,16 @@ Accessibility.AXNodeIgnoredReasonTreeElement = class extends Accessibility.AXNod
reasonElement = UI.formatLocalized('Element is inert.', []);
break;
case 'inertSubtree':
- reasonElement = UI.formatLocalized('Element is in an inert subtree from\u00a0', []);
+ reasonElement = UI.formatLocalized('Element is in an inert subtree from\xA0', []);
break;
case 'inheritsPresentation':
- reasonElement = UI.formatLocalized('Element inherits presentational role from\u00a0', []);
+ reasonElement = UI.formatLocalized('Element inherits presentational role from\xA0', []);
break;
case 'labelContainer':
- reasonElement = UI.formatLocalized('Part of label element:\u00a0', []);
+ reasonElement = UI.formatLocalized('Part of label element:\xA0', []);
break;
case 'labelFor':
- reasonElement = UI.formatLocalized('Label for\u00a0', []);
+ reasonElement = UI.formatLocalized('Label for\xA0', []);
break;
case 'notRendered':
reasonElement = UI.formatLocalized('Element is not rendered.', []);
@@ -599,14 +633,15 @@ Accessibility.AXNodeIgnoredReasonTreeElement = class extends Accessibility.AXNod
reasonElement = UI.formatLocalized('Element is presentational.', []);
break;
case 'staticTextUsedAsNameFor':
- reasonElement = UI.formatLocalized('Static text node is used as name for\u00a0', []);
+ reasonElement = UI.formatLocalized('Static text node is used as name for\xA0', []);
break;
case 'uninteresting':
reasonElement = UI.formatLocalized('Element not interesting for accessibility.', []);
break;
}
- if (reasonElement)
+ if (reasonElement) {
reasonElement.classList.add('ax-reason');
+ }
return reasonElement;
}
@@ -621,7 +656,8 @@ Accessibility.AXNodeIgnoredReasonTreeElement = class extends Accessibility.AXNod
this.listItemElement.appendChild(this._reasonElement);
const value = this._property.value;
- if (value.type === Protocol.Accessibility.AXValueType.Idref)
+ if (value.type === Protocol.Accessibility.AXValueType.Idref) {
this.appendRelatedNodeListValueElement(value);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilitySidebarView.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilitySidebarView.js
index 21da831a55a..510cd545536 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilitySidebarView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilitySidebarView.js
@@ -50,20 +50,24 @@ Accessibility.AccessibilitySidebarView = class extends UI.ThrottledWidget {
* @param {?Accessibility.AccessibilityNode} axNode
*/
accessibilityNodeCallback(axNode) {
- if (!axNode)
+ if (!axNode) {
return;
+ }
this._axNode = axNode;
- if (axNode.isDOMNode())
+ if (axNode.isDOMNode()) {
this._sidebarPaneStack.showView(this._ariaSubPane, this._axNodeSubPane);
- else
+ } else {
this._sidebarPaneStack.removeView(this._ariaSubPane);
+ }
- if (this._axNodeSubPane)
+ if (this._axNodeSubPane) {
this._axNodeSubPane.setAXNode(axNode);
- if (this._breadcrumbsSubPane)
+ }
+ if (this._breadcrumbsSubPane) {
this._breadcrumbsSubPane.setAXNode(axNode);
+ }
}
/**
@@ -76,8 +80,9 @@ Accessibility.AccessibilitySidebarView = class extends UI.ThrottledWidget {
this._axNodeSubPane.setNode(node);
this._ariaSubPane.setNode(node);
this._breadcrumbsSubPane.setNode(node);
- if (!node)
+ if (!node) {
return Promise.resolve();
+ }
const accessibilityModel = node.domModel().target().model(Accessibility.AccessibilityModel);
accessibilityModel.clear();
return accessibilityModel.requestPartialAXTree(node).then(() => {
@@ -129,11 +134,13 @@ Accessibility.AccessibilitySidebarView = class extends UI.ThrottledWidget {
* @param {!Common.Event} event
*/
_onAttrChange(event) {
- if (!this.node())
+ if (!this.node()) {
return;
+ }
const node = event.data.node;
- if (this.node() !== node)
+ if (this.node() !== node) {
return;
+ }
this.update();
}
@@ -141,11 +148,13 @@ Accessibility.AccessibilitySidebarView = class extends UI.ThrottledWidget {
* @param {!Common.Event} event
*/
_onNodeChange(event) {
- if (!this.node())
+ if (!this.node()) {
return;
+ }
const node = event.data;
- if (this.node() !== node)
+ if (this.node() !== node) {
return;
+ }
this.update();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
index 5d87553d29a..d0b6aca39b6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp
@@ -99,9 +99,6 @@
<message name="IDS_DEVTOOLS_46a64c89d66d278297b6346c60f67e2c" desc="Tooltip text that appears when hovering over the 'Value description' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
A human-readable version of the value of a range widget (where necessary).
</message>
- <message name="IDS_DEVTOOLS_49ee3087348e8d44e1feda1917443987" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Name
- </message>
<message name="IDS_DEVTOOLS_4ada42850cc2d4e41f3da5254ec2feee" desc="Reason element in Accessibility Node View of the Accessibility panel">
Element is inert.
</message>
@@ -150,12 +147,6 @@
<message name="IDS_DEVTOOLS_674d8a03d6bb22d48dff01565c2b10a3" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
Owns
</message>
- <message name="IDS_DEVTOOLS_689202409e48743b914713f96d93947c" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Value
- </message>
- <message name="IDS_DEVTOOLS_6a26f548831e6a8c26bfbbd9f6ec61e0" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Help
- </message>
<message name="IDS_DEVTOOLS_73f3b04d99cdbbfb2045ad2285986d77" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
Maximum value
</message>
@@ -195,9 +186,6 @@
<message name="IDS_DEVTOOLS_91b442d385b54e1418d81adc34871053" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
Selected
</message>
- <message name="IDS_DEVTOOLS_939aaa05e0943b39eab3a34fd609384d" desc="A context menu item in the AXBreadcrumbs Pane of the Accessibility panel">
- Scroll into view
- </message>
<message name="IDS_DEVTOOLS_953f80ed9077d40149a8e68448f09e47" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
From label (wrapped)
</message>
@@ -243,9 +231,6 @@
<message name="IDS_DEVTOOLS_a858dfbc32e2169e89668adf8e997f6f" desc="Text in Accessibility Node View of the Accessibility panel">
No accessibility node
</message>
- <message name="IDS_DEVTOOLS_abbd64f40c34c537d3a571af068fce29" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Orientation
- </message>
<message name="IDS_DEVTOOLS_aff2b966e54c2212e86343d2bb8d3f88" desc="Reason element in Accessibility Node View of the Accessibility panel">
Part of label element: '''
</message>
@@ -261,9 +246,6 @@
<message name="IDS_DEVTOOLS_b459bb2b480be9a5043f103bbc2f1d49" desc="Tooltip text that appears when hovering over the 'Checked' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
Whether this checkbox, radio button or tree item is checked, unchecked, or mixed (e.g. has both checked and un-checked children).
</message>
- <message name="IDS_DEVTOOLS_b5a7adde1af5c87d7fd797b6245c2a39" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Description
- </message>
<message name="IDS_DEVTOOLS_b651efdb98a5d6bd2b3935d0c3f4a5e2" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
Required
</message>
@@ -273,9 +255,6 @@
<message name="IDS_DEVTOOLS_b9db1026019a8730b64397052a61ded0" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
Atomic (live regions)
</message>
- <message name="IDS_DEVTOOLS_b9f5c797ebbf55adccdd8539a65a0241" desc="Accessibility attribute name that appears under the Computed Properties section in the Accessibility pane of the Elements pane">
- Disabled
- </message>
<message name="IDS_DEVTOOLS_bb129d779ae1ffda5fda12070a4a142b" desc="Tooltip text that appears when hovering over the 'From caption' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
Value from figcaption element.
</message>
@@ -342,9 +321,6 @@
<message name="IDS_DEVTOOLS_e0dcc9aef6db5e61e4102efdf5d54378" desc="Text in Accessibility Node View of the Accessibility panel">
Invalid source.
</message>
- <message name="IDS_DEVTOOLS_e0e4fc6213e8b3593495a7260c3a4c2e" desc="Title of the 'Accessibility' tool in the sidebar of the elements tool">
- Accessibility
- </message>
<message name="IDS_DEVTOOLS_e1312fc3ec5859447389668b721d932f" desc="Tooltip text that appears when hovering over the 'Pressed' attribute name under the Computed Properties section in the Accessibility pane of the Elements pane">
Whether this toggle button is currently in a pressed state.
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js
index 6da6959fff1..244fb7a7ff0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js
@@ -44,8 +44,9 @@ AccessibilityTestRunner.dumpAccessibilityNode = function(accessibilityNode) {
if (accessibilityNode.properties()) {
for (const property of accessibilityNode.properties()) {
- if ('value' in property)
+ if ('value' in property) {
builder.push(property.name + '="' + property.value.value + '"');
+ }
}
}
@@ -66,8 +67,9 @@ AccessibilityTestRunner.findARIAAttributeTreeElement = function(attribute) {
const childNodes = treeOutline._rootElement._children;
for (const treeElement of childNodes) {
- if (treeElement._attribute.name === attribute)
+ if (treeElement._attribute.name === attribute) {
return treeElement;
+ }
}
return null;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationGroupPreviewUI.js b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationGroupPreviewUI.js
index 3ec7be4dd8e..61fb6ac864a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationGroupPreviewUI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationGroupPreviewUI.js
@@ -32,8 +32,9 @@ Animation.AnimationGroupPreviewUI = class {
let duration = 0;
for (const anim of this._model.animations()) {
const animDuration = anim.source().delay() + anim.source().duration();
- if (animDuration > duration)
+ if (animDuration > duration) {
duration = animDuration;
+ }
}
return duration;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationModel.js b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationModel.js
index 0d4001c6e7d..837dbd4e25f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationModel.js
@@ -24,8 +24,9 @@ Animation.AnimationModel = class extends SDK.SDKModel {
const resourceTreeModel = /** @type {!SDK.ResourceTreeModel} */ (target.model(SDK.ResourceTreeModel));
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.MainFrameNavigated, this._reset, this);
const screenCaptureModel = target.model(SDK.ScreenCaptureModel);
- if (screenCaptureModel)
+ if (screenCaptureModel) {
this._screenshotCapture = new Animation.AnimationModel.ScreenshotCapture(this, screenCaptureModel);
+ }
}
_reset() {
@@ -55,8 +56,9 @@ Animation.AnimationModel = class extends SDK.SDKModel {
*/
animationStarted(payload) {
// We are not interested in animations without effect or target.
- if (!payload.source || !payload.source.backendNodeId)
+ if (!payload.source || !payload.source.backendNodeId) {
return;
+ }
const animation = Animation.AnimationModel.Animation.parsePayload(this, payload);
@@ -65,8 +67,9 @@ Animation.AnimationModel = class extends SDK.SDKModel {
this._pendingAnimations.remove(animation.id());
} else {
this._animationsById.set(animation.id(), animation);
- if (this._pendingAnimations.indexOf(animation.id()) === -1)
+ if (this._pendingAnimations.indexOf(animation.id()) === -1) {
this._pendingAnimations.push(animation.id());
+ }
}
this._flushPendingAnimationsIfNeeded();
@@ -74,12 +77,14 @@ Animation.AnimationModel = class extends SDK.SDKModel {
_flushPendingAnimationsIfNeeded() {
for (const id of this._pendingAnimations) {
- if (!this._animationsById.get(id))
+ if (!this._animationsById.get(id)) {
return;
+ }
}
- while (this._pendingAnimations.length)
+ while (this._pendingAnimations.length) {
this._matchExistingGroups(this._createGroupFromPendingAnimations());
+ }
}
/**
@@ -98,8 +103,9 @@ Animation.AnimationModel = class extends SDK.SDKModel {
if (!matchedGroup) {
this._animationGroups.set(incomingGroup.id(), incomingGroup);
- if (this._screenshotCapture)
+ if (this._screenshotCapture) {
this._screenshotCapture.captureScreenshots(incomingGroup.finiteDuration(), incomingGroup._screenshots);
+ }
}
this.dispatchEventToListeners(Animation.AnimationModel.Events.AnimationGroupStarted, matchedGroup || incomingGroup);
return !!matchedGroup;
@@ -114,10 +120,11 @@ Animation.AnimationModel = class extends SDK.SDKModel {
const remainingAnimations = [];
for (const id of this._pendingAnimations) {
const anim = this._animationsById.get(id);
- if (anim.startTime() === groupedAnimations[0].startTime())
+ if (anim.startTime() === groupedAnimations[0].startTime()) {
groupedAnimations.push(anim);
- else
+ } else {
remainingAnimations.push(id);
+ }
}
this._pendingAnimations = remainingAnimations;
return new Animation.AnimationModel.AnimationGroup(this, groupedAnimations[0].id(), groupedAnimations);
@@ -152,14 +159,16 @@ Animation.AnimationModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
resumeModel() {
- if (!this._enabled)
+ if (!this._enabled) {
return Promise.resolve();
+ }
return this._agent.enable();
}
ensureEnabled() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._agent.enable();
this._enabled = true;
}
@@ -258,8 +267,9 @@ Animation.AnimationModel.Animation = class {
* @return {number}
*/
endTime() {
- if (!this.source().iterations)
+ if (!this.source().iterations) {
return Infinity;
+ }
return this.startTime() + this.source().delay() + this.source().duration() * this.source().iterations() +
this.source().endDelay();
}
@@ -299,8 +309,9 @@ Animation.AnimationModel.Animation = class {
*/
overlaps(animation) {
// Infinite animations
- if (!this.source().iterations() || !animation.source().iterations())
+ if (!this.source().iterations() || !animation.source().iterations()) {
return true;
+ }
const firstAnimation = this.startTime() < animation.startTime() ? this : animation;
const secondAnimation = firstAnimation === this ? animation : this;
@@ -325,12 +336,13 @@ Animation.AnimationModel.Animation = class {
*/
_updateNodeStyle(duration, delay, node) {
let animationPrefix;
- if (this.type() === Animation.AnimationModel.Animation.Type.CSSTransition)
+ if (this.type() === Animation.AnimationModel.Animation.Type.CSSTransition) {
animationPrefix = 'transition-';
- else if (this.type() === Animation.AnimationModel.Animation.Type.CSSAnimation)
+ } else if (this.type() === Animation.AnimationModel.Animation.Type.CSSAnimation) {
animationPrefix = 'animation-';
- else
+ } else {
return;
+ }
const cssModel = node.domModel().cssModel();
cssModel.setEffectivePropertyValueForNode(node.id, animationPrefix + 'duration', duration + 'ms');
@@ -372,8 +384,9 @@ Animation.AnimationModel.AnimationEffect = class {
constructor(animationModel, payload) {
this._animationModel = animationModel;
this._payload = payload;
- if (payload.keyframesRule)
+ if (payload.keyframesRule) {
this._keyframesRule = new Animation.AnimationModel.KeyframesRule(payload.keyframesRule);
+ }
this._delay = this._payload.delay;
this._duration = this._payload.duration;
}
@@ -404,8 +417,9 @@ Animation.AnimationModel.AnimationEffect = class {
*/
iterations() {
// Animations with zero duration, zero delays and infinite iterations can't be shown.
- if (!this.delay() && !this.endDelay() && !this.duration())
+ if (!this.delay() && !this.endDelay() && !this.duration()) {
return 0;
+ }
return this._payload.iterations || Infinity;
}
@@ -434,8 +448,9 @@ Animation.AnimationModel.AnimationEffect = class {
* @return {!Promise.<!SDK.DOMNode>}
*/
node() {
- if (!this._deferredNode)
+ if (!this._deferredNode) {
this._deferredNode = new SDK.DeferredDOMNode(this._animationModel.target(), this.backendNodeId());
+ }
return this._deferredNode.resolvePromise();
}
@@ -611,8 +626,9 @@ Animation.AnimationModel.AnimationGroup = class {
*/
finiteDuration() {
let maxDuration = 0;
- for (let i = 0; i < this._animations.length; ++i)
+ for (let i = 0; i < this._animations.length; ++i) {
maxDuration = Math.max(maxDuration, this._animations[i]._finiteDuration());
+ }
return maxDuration;
}
@@ -634,8 +650,9 @@ Animation.AnimationModel.AnimationGroup = class {
* @param {boolean} paused
*/
togglePause(paused) {
- if (paused === this._paused)
+ if (paused === this._paused) {
return;
+ }
this._paused = paused;
this._animationModel._agent.setPaused(this._animationIds(), paused);
}
@@ -646,8 +663,9 @@ Animation.AnimationModel.AnimationGroup = class {
currentTimePromise() {
let longestAnim = null;
for (const anim of this._animations) {
- if (!longestAnim || anim.endTime() > longestAnim.endTime())
+ if (!longestAnim || anim.endTime() > longestAnim.endTime()) {
longestAnim = anim;
+ }
}
return this._animationModel._agent.getCurrentTime(longestAnim.id()).then(currentTime => currentTime || 0);
}
@@ -662,19 +680,22 @@ Animation.AnimationModel.AnimationGroup = class {
* @return {string}
*/
function extractId(anim) {
- if (anim.type() === Animation.AnimationModel.Animation.Type.WebAnimation)
+ if (anim.type() === Animation.AnimationModel.Animation.Type.WebAnimation) {
return anim.type() + anim.id();
- else
+ } else {
return anim._cssId();
+ }
}
- if (this._animations.length !== group._animations.length)
+ if (this._animations.length !== group._animations.length) {
return false;
+ }
const left = this._animations.map(extractId).sort();
const right = group._animations.map(extractId).sort();
for (let i = 0; i < left.length; i++) {
- if (left[i] !== right[i])
+ if (left[i] !== right[i]) {
return false;
+ }
}
return true;
}
@@ -766,8 +787,9 @@ Animation.AnimationModel.ScreenshotCapture = class {
this._endTime = endTime;
}
- if (this._capturing)
+ if (this._capturing) {
return;
+ }
this._capturing = true;
this._screenCaptureModel.startScreencast(
'jpeg', 80, undefined, 300, 2, this._screencastFrame.bind(this), visible => {});
@@ -786,18 +808,21 @@ Animation.AnimationModel.ScreenshotCapture = class {
return request.endTime >= now;
}
- if (!this._capturing)
+ if (!this._capturing) {
return;
+ }
const now = window.performance.now();
this._requests = this._requests.filter(isAnimating);
- for (const request of this._requests)
+ for (const request of this._requests) {
request.screenshots.push(base64Data);
+ }
}
_stopScreencast() {
- if (!this._capturing)
+ if (!this._capturing) {
return;
+ }
delete this._stopTimer;
delete this._endTime;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationScreenshotPopover.js b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationScreenshotPopover.js
index a8894217ec6..0d9d3cf25bb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationScreenshotPopover.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationScreenshotPopover.js
@@ -46,15 +46,17 @@ Animation.AnimationScreenshotPopover = class extends UI.VBox {
return;
}
this._showFrame = !this._showFrame;
- if (!this._showFrame)
+ if (!this._showFrame) {
return;
+ }
const numFrames = this._frames.length;
this._frames[this._currentFrame % numFrames].style.display = 'none';
this._currentFrame++;
this._frames[(this._currentFrame) % numFrames].style.display = 'block';
- if (this._currentFrame % numFrames === numFrames - 1)
+ if (this._currentFrame % numFrames === numFrames - 1) {
this._endDelay = 50;
+ }
this._progressBar.style.width = (this._currentFrame % numFrames + 1) / numFrames * 100 + '%';
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationTimeline.js b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationTimeline.js
index fdf877e9943..e2b3c012cf0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationTimeline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationTimeline.js
@@ -41,16 +41,18 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @override
*/
wasShown() {
- for (const animationModel of SDK.targetManager.models(Animation.AnimationModel))
+ for (const animationModel of SDK.targetManager.models(Animation.AnimationModel)) {
this._addEventListeners(animationModel);
+ }
}
/**
* @override
*/
willHide() {
- for (const animationModel of SDK.targetManager.models(Animation.AnimationModel))
+ for (const animationModel of SDK.targetManager.models(Animation.AnimationModel)) {
this._removeEventListeners(animationModel);
+ }
this._popoverHelper.hidePopover();
}
@@ -59,8 +61,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @param {!Animation.AnimationModel} animationModel
*/
modelAdded(animationModel) {
- if (this.isShowing())
+ if (this.isShowing()) {
this._addEventListeners(animationModel);
+ }
}
/**
@@ -91,8 +94,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
}
_nodeChanged() {
- for (const nodeUI of this._nodesMap.values())
+ for (const nodeUI of this._nodesMap.values()) {
nodeUI._nodeChanged();
+ }
}
/**
@@ -166,28 +170,32 @@ Animation.AnimationTimeline = class extends UI.VBox {
*/
_getPopoverRequest(event) {
const element = event.target;
- if (!element.isDescendant(this._previewContainer))
+ if (!element.isDescendant(this._previewContainer)) {
return null;
+ }
return {
box: event.target.boxInWindow(),
show: popover => {
let animGroup;
for (const group of this._previewMap.keysArray()) {
- if (this._previewMap.get(group).element === element.parentElement)
+ if (this._previewMap.get(group).element === element.parentElement) {
animGroup = group;
+ }
}
console.assert(animGroup);
const screenshots = animGroup.screenshots();
- if (!screenshots.length)
+ if (!screenshots.length) {
return Promise.resolve(false);
+ }
let fulfill;
const promise = new Promise(x => fulfill = x);
- if (!screenshots[0].complete)
+ if (!screenshots[0].complete) {
screenshots[0].onload = onFirstScreenshotLoaded.bind(null, screenshots);
- else
+ } else {
onFirstScreenshotLoaded(screenshots);
+ }
return promise;
/**
@@ -213,11 +221,13 @@ Animation.AnimationTimeline = class extends UI.VBox {
*/
_setPlaybackRate(playbackRate) {
this._playbackRate = playbackRate;
- for (const animationModel of SDK.targetManager.models(Animation.AnimationModel))
+ for (const animationModel of SDK.targetManager.models(Animation.AnimationModel)) {
animationModel.setPlaybackRate(this._allPaused ? 0 : this._playbackRate);
+ }
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AnimationsPlaybackRateChanged);
- if (this._scrubberPlayer)
+ if (this._scrubberPlayer) {
this._scrubberPlayer.playbackRate = this._effectivePlaybackRate();
+ }
this._updatePlaybackControls();
}
@@ -230,12 +240,13 @@ Animation.AnimationTimeline = class extends UI.VBox {
}
_controlButtonToggle() {
- if (this._controlState === Animation.AnimationTimeline._ControlState.Play)
+ if (this._controlState === Animation.AnimationTimeline._ControlState.Play) {
this._togglePause(false);
- else if (this._controlState === Animation.AnimationTimeline._ControlState.Replay)
+ } else if (this._controlState === Animation.AnimationTimeline._ControlState.Replay) {
this._replay();
- else
+ } else {
this._togglePause(true);
+ }
}
_updateControlButton() {
@@ -270,15 +281,17 @@ Animation.AnimationTimeline = class extends UI.VBox {
*/
_togglePause(pause) {
this._selectedGroup.togglePause(pause);
- if (this._scrubberPlayer)
+ if (this._scrubberPlayer) {
this._scrubberPlayer.playbackRate = this._effectivePlaybackRate();
+ }
this._previewMap.get(this._selectedGroup).element.classList.toggle('paused', pause);
this._updateControlButton();
}
_replay() {
- if (!this._selectedGroup)
+ if (!this._selectedGroup) {
return;
+ }
this._selectedGroup.seekTo(0);
this._animateTime(0);
this._updateControlButton();
@@ -307,8 +320,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
this._duration = this._defaultDuration;
this._timelineScrubber.classList.add('hidden');
delete this._selectedGroup;
- if (this._scrubberPlayer)
+ if (this._scrubberPlayer) {
this._scrubberPlayer.cancel();
+ }
delete this._scrubberPlayer;
this._currentTime.textContent = '';
this._updateControlButton();
@@ -316,13 +330,15 @@ Animation.AnimationTimeline = class extends UI.VBox {
_reset() {
this._clearTimeline();
- if (this._allPaused)
+ if (this._allPaused) {
this._togglePauseAll();
- else
+ } else {
this._setPlaybackRate(this._playbackRate);
+ }
- for (const group of this._groupBuffer)
+ for (const group of this._groupBuffer) {
group.release();
+ }
this._groupBuffer = [];
this._previewMap.clear();
this._previewContainer.removeChildren();
@@ -350,10 +366,11 @@ Animation.AnimationTimeline = class extends UI.VBox {
}
if (this._previewMap.get(group)) {
- if (this._selectedGroup === group)
+ if (this._selectedGroup === group) {
this._syncScrubber();
- else
+ } else {
this._previewMap.get(group).replay();
+ }
return;
}
this._groupBuffer.sort(startTimeComparator);
@@ -417,8 +434,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
this._selectedGroup = group;
this._previewMap.forEach(applySelectionClass, this);
this.setDuration(Math.max(500, group.finiteDuration() + 100));
- for (const anim of group.animations())
+ for (const anim of group.animations()) {
this._addAnimation(anim);
+ }
this.scheduleRedraw();
this._timelineScrubber.classList.remove('hidden');
this._togglePause(false);
@@ -436,8 +454,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
function nodeResolved(node) {
nodeUI.nodeResolved(node);
uiAnimation.setNode(node);
- if (node)
+ if (node) {
node[this._symbol] = nodeUI;
+ }
}
let nodeUI = this._nodesMap.get(animation.source().backendNodeId());
@@ -458,8 +477,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
*/
_nodeRemoved(event) {
const node = event.data.node;
- if (node[this._symbol])
+ if (node[this._symbol]) {
node[this._symbol].nodeRemoved();
+ }
}
_renderGrid() {
@@ -490,10 +510,12 @@ Animation.AnimationTimeline = class extends UI.VBox {
scheduleRedraw() {
this._renderQueue = [];
- for (const ui of this._uiAnimations)
+ for (const ui of this._uiAnimations) {
this._renderQueue.push(ui);
- if (this._redrawing)
+ }
+ if (this._redrawing) {
return;
+ }
this._redrawing = true;
this._renderGrid();
this._animationsContainer.window().requestAnimationFrame(this._render.bind(this));
@@ -503,12 +525,14 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @param {number=} timestamp
*/
_render(timestamp) {
- while (this._renderQueue.length && (!timestamp || window.performance.now() - timestamp < 50))
+ while (this._renderQueue.length && (!timestamp || window.performance.now() - timestamp < 50)) {
this._renderQueue.shift().redraw();
- if (this._renderQueue.length)
+ }
+ if (this._renderQueue.length) {
this._animationsContainer.window().requestAnimationFrame(this._render.bind(this));
- else
+ } else {
delete this._redrawing;
+ }
}
/**
@@ -518,8 +542,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
this._cachedTimelineWidth = Math.max(0, this._animationsContainer.offsetWidth - this._timelineControlsWidth) || 0;
this._cachedTimelineHeight = this._animationsContainer.offsetHeight;
this.scheduleRedraw();
- if (this._scrubberPlayer)
+ if (this._scrubberPlayer) {
this._syncScrubber();
+ }
delete this._gridOffsetLeft;
}
@@ -548,8 +573,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
}
_syncScrubber() {
- if (!this._selectedGroup)
+ if (!this._selectedGroup) {
return;
+ }
this._selectedGroup.currentTimePromise()
.then(this._animateTime.bind(this))
.then(this._updateControlButton.bind(this));
@@ -559,8 +585,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @param {number} currentTime
*/
_animateTime(currentTime) {
- if (this._scrubberPlayer)
+ if (this._scrubberPlayer) {
this._scrubberPlayer.cancel();
+ }
this._scrubberPlayer = this._timelineScrubber.animate(
[{transform: 'translateX(0px)'}, {transform: 'translateX(' + this.width() + 'px)'}],
@@ -582,13 +609,15 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @param {number} timestamp
*/
_updateScrubber(timestamp) {
- if (!this._scrubberPlayer)
+ if (!this._scrubberPlayer) {
return;
+ }
this._currentTime.textContent = Number.millisToString(this._scrubberPlayer.currentTime);
- if (this._scrubberPlayer.playState === 'pending' || this._scrubberPlayer.playState === 'running')
+ if (this._scrubberPlayer.playState === 'pending' || this._scrubberPlayer.playState === 'running') {
this.element.window().requestAnimationFrame(this._updateScrubber.bind(this));
- else if (this._scrubberPlayer.playState === 'finished')
+ } else if (this._scrubberPlayer.playState === 'finished') {
this._currentTime.textContent = '';
+ }
}
/**
@@ -596,12 +625,14 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @return {boolean}
*/
_repositionScrubber(event) {
- if (!this._selectedGroup)
+ if (!this._selectedGroup) {
return false;
+ }
// Seek to current mouse position.
- if (!this._gridOffsetLeft)
+ if (!this._gridOffsetLeft) {
this._gridOffsetLeft = this._grid.totalOffsetLeft() + 10;
+ }
const seekTime = Math.max(0, event.x - this._gridOffsetLeft) / this.pixelMsRatio();
this._selectedGroup.seekTo(seekTime);
this._togglePause(true);
@@ -618,8 +649,9 @@ Animation.AnimationTimeline = class extends UI.VBox {
* @return {boolean}
*/
_scrubberDragStart(event) {
- if (!this._scrubberPlayer || !this._selectedGroup)
+ if (!this._scrubberPlayer || !this._selectedGroup) {
return false;
+ }
this._originalScrubberTime = this._scrubberPlayer.currentTime;
this._timelineScrubber.classList.remove('animation-timeline-end');
@@ -686,8 +718,9 @@ Animation.AnimationTimeline.NodeUI = class {
this._node = node;
this._nodeChanged();
Common.Linkifier.linkify(node).then(link => this._description.appendChild(link));
- if (!node.ownerDocument)
+ if (!node.ownerDocument) {
this.nodeRemoved();
+ }
}
/**
@@ -727,11 +760,13 @@ Animation.AnimationTimeline.StepTimingFunction = class {
*/
static parse(text) {
let match = text.match(/^steps\((\d+), (start|middle)\)$/);
- if (match)
+ if (match) {
return new Animation.AnimationTimeline.StepTimingFunction(parseInt(match[1], 10), match[2]);
+ }
match = text.match(/^steps\((\d+)\)$/);
- if (match)
+ if (match) {
return new Animation.AnimationTimeline.StepTimingFunction(parseInt(match[1], 10), 'end');
+ }
return null;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationUI.js b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationUI.js
index 8c6ebc40ad0..9a3028ce1d3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationUI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/AnimationUI.js
@@ -15,8 +15,9 @@ Animation.AnimationUI = class {
this._timeline = timeline;
this._parentElement = parentElement;
- if (this._animation.source().keyframesRule())
+ if (this._animation.source().keyframesRule()) {
this._keyframes = this._animation.source().keyframesRule().keyframes();
+ }
this._nameElement = parentElement.createChild('div', 'animation-name');
this._nameElement.textContent = this._animation.name();
@@ -81,8 +82,9 @@ Animation.AnimationUI = class {
*/
_drawAnimationLine(iteration, parentElement) {
const cache = this._cachedElements[iteration];
- if (!cache.animationLine)
+ if (!cache.animationLine) {
cache.animationLine = this._createLine(parentElement, 'animation-line');
+ }
cache.animationLine.setAttribute(
'x2',
(this._duration() * this._timeline.pixelMsRatio() + Animation.AnimationUI.Options.AnimationMargin).toFixed(2));
@@ -133,21 +135,24 @@ Animation.AnimationUI = class {
circle.style.stroke = this._color;
circle.setAttribute('r', Animation.AnimationUI.Options.AnimationMargin / 2);
- if (keyframeIndex <= 0)
+ if (keyframeIndex <= 0) {
circle.style.fill = this._color;
+ }
this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
- if (!attachEvents)
+ if (!attachEvents) {
return;
+ }
let eventType;
- if (keyframeIndex === 0)
+ if (keyframeIndex === 0) {
eventType = Animation.AnimationUI.MouseEvents.StartEndpointMove;
- else if (keyframeIndex === -1)
+ } else if (keyframeIndex === -1) {
eventType = Animation.AnimationUI.MouseEvents.FinishEndpointMove;
- else
+ } else {
eventType = Animation.AnimationUI.MouseEvents.KeyframeMove;
+ }
UI.installDragHandle(
circle, this._mouseDown.bind(this, eventType, keyframeIndex), this._mouseMove.bind(this),
this._mouseUp.bind(this), 'ew-resize');
@@ -198,8 +203,9 @@ Animation.AnimationUI = class {
group.removeChildren();
/** @const */ const offsetMap = {'start': 0, 'middle': 0.5, 'end': 1};
/** @const */ const offsetWeight = offsetMap[stepFunction.stepAtPosition];
- for (let i = 0; i < stepFunction.steps; i++)
+ for (let i = 0; i < stepFunction.steps; i++) {
createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color);
+ }
}
}
@@ -222,21 +228,25 @@ Animation.AnimationUI = class {
}
this._renderIteration(this._activeIntervalGroup, 0);
- if (!this._tailGroup)
+ if (!this._tailGroup) {
this._tailGroup = this._activeIntervalGroup.createSVGChild('g', 'animation-tail-iterations');
+ }
const iterationWidth = this._duration() * this._timeline.pixelMsRatio();
let iteration;
for (iteration = 1;
iteration < this._animation.source().iterations() && iterationWidth * (iteration - 1) < this._timeline.width();
- iteration++)
+ iteration++) {
this._renderIteration(this._tailGroup, iteration);
- while (iteration < this._cachedElements.length)
+ }
+ while (iteration < this._cachedElements.length) {
this._cachedElements.pop().group.remove();
+ }
}
_renderTransition() {
- if (!this._cachedElements[0])
+ if (!this._cachedElements[0]) {
this._cachedElements[0] = {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null};
+ }
this._drawAnimationLine(0, this._activeIntervalGroup);
this._renderKeyframe(
0, 0, this._activeIntervalGroup, Animation.AnimationUI.Options.AnimationMargin,
@@ -266,8 +276,9 @@ Animation.AnimationUI = class {
Animation.AnimationUI.Options.AnimationMargin;
const width = this._duration() * (this._offset(i + 1) - this._offset(i)) * this._timeline.pixelMsRatio();
this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyframes[i].easing());
- if (i || (!i && iteration === 0))
+ if (i || (!i && iteration === 0)) {
this._drawPoint(iteration, group, leftDistance, i, iteration === 0);
+ }
}
this._drawPoint(
iteration, group,
@@ -281,8 +292,9 @@ Animation.AnimationUI = class {
_delay() {
let delay = this._animation.source().delay();
if (this._mouseEventType === Animation.AnimationUI.MouseEvents.AnimationDrag ||
- this._mouseEventType === Animation.AnimationUI.MouseEvents.StartEndpointMove)
+ this._mouseEventType === Animation.AnimationUI.MouseEvents.StartEndpointMove) {
delay += this._movementInMs;
+ }
// FIXME: add support for negative start delay
return Math.max(0, delay);
}
@@ -292,10 +304,11 @@ Animation.AnimationUI = class {
*/
_duration() {
let duration = this._animation.source().duration();
- if (this._mouseEventType === Animation.AnimationUI.MouseEvents.FinishEndpointMove)
+ if (this._mouseEventType === Animation.AnimationUI.MouseEvents.FinishEndpointMove) {
duration += this._movementInMs;
- else if (this._mouseEventType === Animation.AnimationUI.MouseEvents.StartEndpointMove)
- duration -= Math.max(this._movementInMs, -this._animation.source().delay()); // Cannot have negative delay
+ } else if (this._mouseEventType === Animation.AnimationUI.MouseEvents.StartEndpointMove) {
+ duration -= Math.max(this._movementInMs, -this._animation.source().delay());
+ } // Cannot have negative delay
return Math.max(0, duration);
}
@@ -320,16 +333,19 @@ Animation.AnimationUI = class {
* @param {!Event} event
*/
_mouseDown(mouseEventType, keyframeIndex, event) {
- if (event.buttons === 2)
+ if (event.buttons === 2) {
return false;
- if (this._svg.enclosingNodeOrSelfWithClass('animation-node-removed'))
+ }
+ if (this._svg.enclosingNodeOrSelfWithClass('animation-node-removed')) {
return false;
+ }
this._mouseEventType = mouseEventType;
this._keyframeMoved = keyframeIndex;
this._downMouseX = event.clientX;
event.consume(true);
- if (this._node)
+ if (this._node) {
Common.Revealer.reveal(this._node);
+ }
return true;
}
@@ -338,8 +354,9 @@ Animation.AnimationUI = class {
*/
_mouseMove(event) {
this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
- if (this._delay() + this._duration() > this._timeline.duration() * 0.8)
+ if (this._delay() + this._duration() > this._timeline.duration() * 0.8) {
this._timeline.setDuration(this._timeline.duration() * 1.2);
+ }
this.redraw();
}
@@ -350,10 +367,11 @@ Animation.AnimationUI = class {
this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
// Commit changes
- if (this._mouseEventType === Animation.AnimationUI.MouseEvents.KeyframeMove)
+ if (this._mouseEventType === Animation.AnimationUI.MouseEvents.KeyframeMove) {
this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved));
- else
+ } else {
this._animation.setTiming(this._duration(), this._delay());
+ }
this._movementInMs = 0;
this.redraw();
@@ -371,8 +389,9 @@ Animation.AnimationUI = class {
* @param {?SDK.RemoteObject} remoteObject
*/
function showContextMenu(remoteObject) {
- if (!remoteObject)
+ if (!remoteObject) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
contextMenu.appendApplicableItems(remoteObject);
contextMenu.show();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
index a91ddaeccf0..284c67b8076 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/animation/animation_strings.grdp
@@ -15,9 +15,6 @@
<message name="IDS_DEVTOOLS_5fe41afb268c87f4f56027023d3e6406" desc="Text in Animation Timeline of the Animation Inspector">
<ph name="PLAYBACKRATE______">$1s<ex>50</ex></ph>%
</message>
- <message name="IDS_DEVTOOLS_81aa2078d1eceede831b2976dbf32e62" desc="Tooltip text that appears when hovering over the largeicon clear button in the Animation Timeline of the Animation Inspector">
- Clear all
- </message>
<message name="IDS_DEVTOOLS_96952fa958a61d47ed4dee3f2c3dee64" desc="Tooltip text that appears when hovering over largeicon pause button in Animation Timeline of the Animation Inspector">
Pause all
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/AppcacheTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/AppcacheTestRunner.js
index 14b40892ea5..85f26f98350 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/AppcacheTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/AppcacheTestRunner.js
@@ -74,13 +74,15 @@ ApplicationTestRunner.dumpApplicationCacheTree = function() {
};
ApplicationTestRunner.frameIdToString = function(frameId) {
- if (!ApplicationTestRunner.framesByFrameId)
+ if (!ApplicationTestRunner.framesByFrameId) {
ApplicationTestRunner.framesByFrameId = {};
+ }
let frame = TestRunner.resourceTreeModel.frameForId(frameId);
- if (!frame)
+ if (!frame) {
frame = ApplicationTestRunner.framesByFrameId[frameId];
+ }
ApplicationTestRunner.framesByFrameId[frameId] = frame;
return frame.name;
@@ -102,8 +104,9 @@ ApplicationTestRunner.dumpApplicationCacheModel = function() {
const model = UI.panels.resources._sidebar._applicationCacheModel;
const frameIds = [];
- for (const frameId in model._manifestURLsByFrame)
+ for (const frameId in model._manifestURLsByFrame) {
frameIds.push(frameId);
+ }
function compareFunc(a, b) {
return ApplicationTestRunner.frameIdToString(a).localeCompare(ApplicationTestRunner.frameIdToString(b));
@@ -153,8 +156,9 @@ ApplicationTestRunner.startApplicationCacheStatusesRecording = function() {
record.manifestURL = manifestURL;
record.status = status;
- if (!ApplicationTestRunner.applicationCacheStatusesRecords[frameId])
+ if (!ApplicationTestRunner.applicationCacheStatusesRecords[frameId]) {
ApplicationTestRunner.applicationCacheStatusesRecords[frameId] = [];
+ }
ApplicationTestRunner.applicationCacheStatusesRecords[frameId].push(record);
@@ -162,8 +166,9 @@ ApplicationTestRunner.startApplicationCacheStatusesRecording = function() {
ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId]) {
ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].count--;
- if (!ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].count)
+ if (!ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].count) {
ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId].callback();
+ }
}
}
@@ -179,8 +184,9 @@ ApplicationTestRunner.ensureFrameStatusEventsReceived = function(frameId, count,
return;
}
- if (!ApplicationTestRunner.awaitedFrameStatusEventsCount)
+ if (!ApplicationTestRunner.awaitedFrameStatusEventsCount) {
ApplicationTestRunner.awaitedFrameStatusEventsCount = {};
+ }
ApplicationTestRunner.awaitedFrameStatusEventsCount[frameId] = {count: eventsLeft, callback: callback};
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/CacheStorageTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/CacheStorageTestRunner.js
index 6f8f6b97e7e..adc77c08624 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/CacheStorageTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/CacheStorageTestRunner.js
@@ -28,10 +28,11 @@ ApplicationTestRunner.dumpCacheTreeNoRefresh = async function(pathFilter) {
}
UI.panels.resources._sidebar.cacheStorageListTreeElement.expand();
- if (!pathFilter)
+ if (!pathFilter) {
TestRunner.addResult('Dumping CacheStorage tree:');
- else
+ } else {
TestRunner.addResult('Dumping CacheStorage tree with URL path filter string "' + pathFilter + '"');
+ }
const cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement;
@@ -45,8 +46,9 @@ ApplicationTestRunner.dumpCacheTreeNoRefresh = async function(pathFilter) {
TestRunner.addResult(' cache: ' + cacheTreeElement.title);
let view = cacheTreeElement._view;
- if (!view)
+ if (!view) {
cacheTreeElement.onselect(false);
+ }
view = cacheTreeElement._view;
await view._updateData(true);
if (cacheTreeElement._view._entriesForTest.length === 0) {
@@ -89,26 +91,30 @@ ApplicationTestRunner.dumpCachedEntryContentNoRefresh = async function(cacheName
for (let i = 0; i < cachesTreeElement.childCount(); ++i) {
const cacheTreeElement = cachesTreeElement.childAt(i);
- if (cacheTreeElement.title.split(' ')[0] !== cacheName)
+ if (cacheTreeElement.title.split(' ')[0] !== cacheName) {
continue;
+ }
let view = cacheTreeElement._view;
- if (!view)
+ if (!view) {
cacheTreeElement.onselect(false);
+ }
view = cacheTreeElement._view;
await view._updateData(true);
const promiseDumpContent = new Promise(resolve => {
view._model.loadCacheData(view._cache, 0, 50, '', async function(entries, totalCount) {
for (const entry of entries) {
- if (entry.requestURL !== requestUrl)
+ if (entry.requestURL !== requestUrl) {
continue;
+ }
const request = view._createRequest(entry);
if (request.requestHeaders().length) {
TestRunner.addResult(' the original request has headers; query with headers? ' + withHeader);
- if (!withHeader)
+ if (!withHeader) {
request.setRequestHeaders([]);
+ }
}
const contentObject = await view._requestContent(request);
const content = contentObject.content;
@@ -124,18 +130,20 @@ ApplicationTestRunner.dumpCachedEntryContentNoRefresh = async function(cacheName
ApplicationTestRunner.deleteCacheFromInspector = async function(cacheName, optionalEntry) {
UI.panels.resources._sidebar.cacheStorageListTreeElement.expand();
- if (optionalEntry)
+ if (optionalEntry) {
TestRunner.addResult('Deleting CacheStorage entry ' + optionalEntry + ' in cache ' + cacheName);
- else
+ } else {
TestRunner.addResult('Deleting CacheStorage cache ' + cacheName);
+ }
const cachesTreeElement = UI.panels.resources._sidebar.cacheStorageListTreeElement;
let promise = TestRunner.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, '_updateCacheNames');
UI.panels.resources._sidebar.cacheStorageListTreeElement._refreshCaches();
await promise;
- if (!cachesTreeElement.childCount())
+ if (!cachesTreeElement.childCount()) {
throw 'Error: Could not find CacheStorage cache ' + cacheName;
+ }
for (let i = 0; i < cachesTreeElement.childCount(); i++) {
@@ -143,8 +151,9 @@ ApplicationTestRunner.deleteCacheFromInspector = async function(cacheName, optio
const title = cacheTreeElement.title;
const elementCacheName = title.substring(0, title.lastIndexOf(' - '));
- if (elementCacheName !== cacheName)
+ if (elementCacheName !== cacheName) {
continue;
+ }
if (!optionalEntry) {
promise = TestRunner.addSnifferPromise(SDK.ServiceWorkerCacheModel.prototype, '_cacheRemoved');
@@ -156,17 +165,19 @@ ApplicationTestRunner.deleteCacheFromInspector = async function(cacheName, optio
promise = TestRunner.addSnifferPromise(Resources.ServiceWorkerCacheView.prototype, '_updateDataCallback');
let view = cacheTreeElement._view;
- if (!view)
+ if (!view) {
cacheTreeElement.onselect(false);
- else
+ } else {
view._updateData(true);
+ }
view = cacheTreeElement._view;
await promise;
const entry = view._entriesForTest.find(entry => entry.requestURL === optionalEntry);
- if (!entry)
+ if (!entry) {
throw 'Error: Could not find cache entry to delete: ' + optionalEntry;
+ }
await view._model.deleteCacheEntry(view._cache, entry.requestURL);
return;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/IndexedDBTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/IndexedDBTestRunner.js
index 9cb4080c83e..d85b66c974e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/IndexedDBTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/IndexedDBTestRunner.js
@@ -51,8 +51,9 @@ ApplicationTestRunner.dumpObjectStores = function() {
TestRunner.addResult(' Object store: ' + objectStoreTreeElement.title);
const entries = objectStoreTreeElement._view._entries;
TestRunner.addResult(' Number of entries: ' + entries.length);
- for (let j = 0; j < entries.length; ++j)
+ for (let j = 0; j < entries.length; ++j) {
TestRunner.addResult(' Key = ' + entries[j].key._value + ', value = ' + entries[j].value);
+ }
for (let k = 0; k < objectStoreTreeElement.childCount(); ++k) {
const indexTreeElement = objectStoreTreeElement.childAt(k);
@@ -60,8 +61,9 @@ ApplicationTestRunner.dumpObjectStores = function() {
indexTreeElement.onselect(false);
const entries = indexTreeElement._view._entries;
TestRunner.addResult(' Number of entries: ' + entries.length);
- for (let j = 0; j < entries.length; ++j)
+ for (let j = 0; j < entries.length; ++j) {
TestRunner.addResult(' Key = ' + entries[j].primaryKey._value + ', value = ' + entries[j].value);
+ }
}
}
};
@@ -76,8 +78,9 @@ ApplicationTestRunner.evaluateWithCallback = function(frameId, methodName, param
callbacks[callbackId] = callback;
let parametersString = 'dispatchCallback.bind(this, "' + callbackIdPrefix + callbackId + '")';
- for (let i = 0; i < parameters.length; ++i)
+ for (let i = 0; i < parameters.length; ++i) {
parametersString += ', ' + JSON.stringify(parameters[i]);
+ }
const requestString = methodName + '(' + parametersString + ')';
TestRunner.evaluateInPageAnonymously(requestString);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js
index 9a13b23e6d7..eb4345922dc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourceTreeTestRunner.js
@@ -11,10 +11,11 @@ ApplicationTestRunner.dumpResources = function(formatter) {
const results = [];
function formatterWrapper(resource) {
- if (formatter)
+ if (formatter) {
results.push({resource: resource, text: formatter(resource)});
- else
+ } else {
results.push({resource: resource, text: resource.url});
+ }
}
TestRunner.resourceTreeModel.forAllResources(formatterWrapper);
@@ -25,8 +26,9 @@ ApplicationTestRunner.dumpResources = function(formatter) {
results.sort(comparator);
- for (let i = 0; i < results.length; ++i)
+ for (let i = 0; i < results.length; ++i) {
TestRunner.addResult(results[i].text);
+ }
};
ApplicationTestRunner.dumpResourcesURLMap = function() {
@@ -38,32 +40,37 @@ ApplicationTestRunner.dumpResourcesURLMap = function() {
}
function comparator(result1, result2) {
- if (result1.url > result2.url)
+ if (result1.url > result2.url) {
return 1;
+ }
- if (result2.url > result1.url)
+ if (result2.url > result1.url) {
return -1;
+ }
return 0;
}
results.sort(comparator);
- for (let i = 0; i < results.length; ++i)
+ for (let i = 0; i < results.length; ++i) {
TestRunner.addResult(results[i].url + ' == ' + results[i].resource.url);
+ }
};
ApplicationTestRunner.dumpResourcesTree = function() {
function dump(treeItem, prefix) {
- if (typeof treeItem._resetBubble === 'function')
+ if (typeof treeItem._resetBubble === 'function') {
treeItem._resetBubble();
+ }
TestRunner.addResult(prefix + treeItem.listItemElement.textContent);
treeItem.expand();
const children = treeItem.children();
- for (let i = 0; children && i < children.length; ++i)
+ for (let i = 0; children && i < children.length; ++i) {
dump(children[i], prefix + ' ');
+ }
}
dump(UI.panels.resources._sidebar._resourcesSection._treeElement, '');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourcesTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourcesTestRunner.js
index 39454032944..cc92123c8ea 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourcesTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ResourcesTestRunner.js
@@ -29,10 +29,11 @@ ApplicationTestRunner.requestURLComparer = function(r1, r2) {
};
ApplicationTestRunner.runAfterCachedResourcesProcessed = function(callback) {
- if (!TestRunner.resourceTreeModel._cachedResourcesProcessed)
+ if (!TestRunner.resourceTreeModel._cachedResourcesProcessed) {
TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, callback);
- else
+ } else {
callback();
+ }
};
ApplicationTestRunner.runAfterResourcesAreFinished = function(resourceURLs, callback) {
@@ -42,8 +43,9 @@ ApplicationTestRunner.runAfterResourcesAreFinished = function(resourceURLs, call
for (const url of resourceURLsMap) {
const resource = ApplicationTestRunner.resourceMatchingURL(url);
- if (resource)
+ if (resource) {
resourceURLsMap.delete(url);
+ }
}
if (!resourceURLsMap.size) {
@@ -54,16 +56,18 @@ ApplicationTestRunner.runAfterResourcesAreFinished = function(resourceURLs, call
checkResources();
- if (resourceURLsMap.size)
+ if (resourceURLsMap.size) {
TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.ResourceAdded, checkResources);
+ }
};
ApplicationTestRunner.showResource = function(resourceURL, callback) {
let reported = false;
function callbackWrapper(sourceFrame) {
- if (reported)
+ if (reported) {
return;
+ }
callback(sourceFrame);
reported = true;
@@ -72,16 +76,18 @@ ApplicationTestRunner.showResource = function(resourceURL, callback) {
function showResourceCallback() {
const resource = ApplicationTestRunner.resourceMatchingURL(resourceURL);
- if (!resource)
+ if (!resource) {
return;
+ }
UI.panels.resources.showResource(resource, 1);
const sourceFrame = UI.panels.resources._resourceViewForResource(resource);
- if (sourceFrame.loaded)
+ if (sourceFrame.loaded) {
callbackWrapper(sourceFrame);
- else
+ } else {
TestRunner.addSniffer(sourceFrame, 'setContent', callbackWrapper.bind(null, sourceFrame));
+ }
}
ApplicationTestRunner.runAfterResourcesAreFinished([resourceURL], showResourceCallback);
@@ -110,8 +116,9 @@ ApplicationTestRunner.waitForCookies = function() {
ApplicationTestRunner.dumpCookieDomains = function() {
const cookieListChildren = UI.panels.resources._sidebar.cookieListTreeElement.children();
TestRunner.addResult('Available cookie domains:');
- for (const child of cookieListChildren)
+ for (const child of cookieListChildren) {
TestRunner.addResult(child._cookieDomain);
+ }
};
ApplicationTestRunner.dumpCookies = function() {
@@ -123,8 +130,9 @@ ApplicationTestRunner.dumpCookies = function() {
TestRunner.addResult('Visible cookies');
for (const item of UI.panels.resources._cookieView._cookiesTable._data) {
const cookies = item.cookies || [];
- for (const cookie of cookies)
+ for (const cookie of cookies) {
TestRunner.addResult(`${cookie.name()}=${cookie.value()}`);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js
index 385c14212aa..c2639b6592f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/application_test_runner/ServiceWorkersTestRunner.js
@@ -42,8 +42,9 @@ ApplicationTestRunner.dumpServiceWorkersView = function() {
return swView._currentWorkersView._sectionList.childTextNodes()
.concat(swView._otherWorkersView._sectionList.childTextNodes())
.map(function(node) {
- if (node.textContent === 'Received ' + (new Date(0)).toLocaleString())
+ if (node.textContent === 'Received ' + (new Date(0)).toLocaleString()) {
return 'Invalid scriptResponseTime (unix epoch)';
+ }
return node.textContent.replace(/Received.*/, 'Received').replace(/#\d+/, '#N');
})
.join('\n');
@@ -51,8 +52,9 @@ ApplicationTestRunner.dumpServiceWorkersView = function() {
ApplicationTestRunner.deleteServiceWorkerRegistration = function(scope) {
TestRunner.serviceWorkerManager.registrations().valuesArray().map(function(registration) {
- if (registration.scopeURL === scope)
+ if (registration.scopeURL === scope) {
TestRunner.serviceWorkerManager.deleteRegistration(registration.id);
+ }
});
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsController.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsController.js
index 1ab901a13e9..23b2b997782 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsController.js
@@ -13,8 +13,9 @@ Audits.AuditController = class extends Common.Object {
protocolService.registerStatusCallback(
message => this.dispatchEventToListeners(Audits.Events.AuditProgressChanged, {message}));
- for (const preset of Audits.Presets)
+ for (const preset of Audits.Presets) {
preset.setting.addChangeListener(this.recomputePageAuditability.bind(this));
+ }
SDK.targetManager.observeModels(SDK.ServiceWorkerManager, this);
SDK.targetManager.addEventListener(
@@ -26,8 +27,9 @@ Audits.AuditController = class extends Common.Object {
* @param {!SDK.ServiceWorkerManager} serviceWorkerManager
*/
modelAdded(serviceWorkerManager) {
- if (this._manager)
+ if (this._manager) {
return;
+ }
this._manager = serviceWorkerManager;
this._serviceWorkerListeners = [
@@ -45,8 +47,9 @@ Audits.AuditController = class extends Common.Object {
* @param {!SDK.ServiceWorkerManager} serviceWorkerManager
*/
modelRemoved(serviceWorkerManager) {
- if (this._manager !== serviceWorkerManager)
+ if (this._manager !== serviceWorkerManager) {
return;
+ }
Common.EventTarget.removeEventListeners(this._serviceWorkerListeners);
this._manager = null;
@@ -57,22 +60,26 @@ Audits.AuditController = class extends Common.Object {
* @return {boolean}
*/
_hasActiveServiceWorker() {
- if (!this._manager)
+ if (!this._manager) {
return false;
+ }
const mainTarget = this._manager.target();
- if (!mainTarget)
+ if (!mainTarget) {
return false;
+ }
const inspectedURL = mainTarget.inspectedURL().asParsedURL();
const inspectedOrigin = inspectedURL && inspectedURL.securityOrigin();
for (const registration of this._manager.registrations().values()) {
- if (registration.securityOrigin !== inspectedOrigin)
+ if (registration.securityOrigin !== inspectedOrigin) {
continue;
+ }
for (const version of registration.versions.values()) {
- if (version.controlledClients.length > 1)
+ if (version.controlledClients.length > 1) {
return true;
+ }
}
}
@@ -90,8 +97,9 @@ Audits.AuditController = class extends Common.Object {
* @return {?string}
*/
_unauditablePageMessage() {
- if (!this._manager)
+ if (!this._manager) {
return null;
+ }
const mainTarget = this._manager.target();
const inspectedURL = mainTarget && mainTarget.inspectedURL();
@@ -111,8 +119,9 @@ Audits.AuditController = class extends Common.Object {
const runtimeModel = mainTarget.model(SDK.RuntimeModel);
const executionContext = runtimeModel && runtimeModel.defaultExecutionContext();
let inspectedURL = mainTarget.inspectedURL();
- if (!executionContext)
+ if (!executionContext) {
return inspectedURL;
+ }
// Evaluate location.href for a more specific URL than inspectedURL provides so that SPA hash navigation routes
// will be respected and audited.
@@ -146,8 +155,9 @@ Audits.AuditController = class extends Common.Object {
// DevTools handles all the emulation. This tells Lighthouse to not bother with emulation.
deviceScreenEmulationMethod: 'provided'
};
- for (const runtimeSetting of Audits.RuntimeSettings)
+ for (const runtimeSetting of Audits.RuntimeSettings) {
runtimeSetting.setFlags(flags, runtimeSetting.setting.get());
+ }
return flags;
}
@@ -157,8 +167,9 @@ Audits.AuditController = class extends Common.Object {
getCategoryIDs() {
const categoryIDs = [];
for (const preset of Audits.Presets) {
- if (preset.setting.get())
+ if (preset.setting.get()) {
categoryIDs.push(preset.configID);
+ }
}
return categoryIDs;
}
@@ -168,8 +179,9 @@ Audits.AuditController = class extends Common.Object {
* @return {!Promise<string>}
*/
async getInspectedURL(options) {
- if (options && options.force || !this._inspectedURL)
+ if (options && options.force || !this._inspectedURL) {
this._inspectedURL = await this._evaluateInspectedURL();
+ }
return this._inspectedURL;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsPanel.js
index afb78b4ee6f..75eeb92bc4a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsPanel.js
@@ -40,8 +40,9 @@ Audits.AuditsPanel = class extends UI.Panel {
*/
_refreshStartAuditUI(evt) {
// PageAuditabilityChanged fires multiple times during an audit, which we want to ignore.
- if (this._isLHAttached)
+ if (this._isLHAttached) {
return;
+ }
this._unauditableExplanation = evt.data.helpText;
this._startView.setUnauditableExplanation(evt.data.helpText);
@@ -94,8 +95,9 @@ Audits.AuditsPanel = class extends UI.Panel {
this._startView.show(this.contentElement);
this._startView.setUnauditableExplanation(this._unauditableExplanation);
this._startView.setStartButtonEnabled(!this._unauditableExplanation);
- if (!this._unauditableExplanation)
+ if (!this._unauditableExplanation) {
this._startView.focusStartButton();
+ }
this._newButton.setEnabled(false);
this._refreshToolbarUI();
@@ -145,10 +147,11 @@ Audits.AuditsPanel = class extends UI.Panel {
const dom = new DOM(/** @type {!Document} */ (this._auditResultsElement.ownerDocument));
const renderer = new Audits.ReportRenderer(dom);
- const templatesHTML = Runtime.cachedResources['audits/lighthouse/templates.html'];
+ const templatesHTML = Root.Runtime.cachedResources['audits/lighthouse/templates.html'];
const templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html');
- if (!templatesDOM)
+ if (!templatesDOM) {
return;
+ }
renderer.setTemplateContext(templatesDOM);
const el = renderer.renderReport(lighthouseResult, reportContainer);
@@ -181,8 +184,9 @@ Audits.AuditsPanel = class extends UI.Panel {
* @param {!ReportRenderer.RunnerResultArtifacts=} artifacts
*/
_buildReportUI(lighthouseResult, artifacts) {
- if (lighthouseResult === null)
+ if (lighthouseResult === null) {
return;
+ }
const optionElement = new Audits.ReportSelector.Item(
lighthouseResult, () => this._renderReport(lighthouseResult, artifacts), this._renderStartView.bind(this));
@@ -196,13 +200,15 @@ Audits.AuditsPanel = class extends UI.Panel {
*/
_handleDrop(dataTransfer) {
const items = dataTransfer.items;
- if (!items.length)
+ if (!items.length) {
return;
+ }
const item = items[0];
if (item.kind === 'file') {
const entry = items[0].webkitGetAsEntry();
- if (!entry.isFile)
+ if (!entry.isFile) {
return;
+ }
entry.file(file => {
const reader = new FileReader();
reader.onload = () => this._loadedFromFile(/** @type {string} */ (reader.result));
@@ -216,8 +222,9 @@ Audits.AuditsPanel = class extends UI.Panel {
*/
_loadedFromFile(report) {
const data = JSON.parse(report);
- if (!data['lighthouseVersion'])
+ if (!data['lighthouseVersion']) {
return;
+ }
this._buildReportUI(/** @type {!ReportRenderer.ReportJSON} */ (data));
}
@@ -241,8 +248,9 @@ Audits.AuditsPanel = class extends UI.Panel {
throw error;
}
- if (!lighthouseResponse)
+ if (!lighthouseResponse) {
throw new Error('Auditing failed to produce a result');
+ }
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AuditsFinished);
@@ -250,8 +258,9 @@ Audits.AuditsPanel = class extends UI.Panel {
this._buildReportUI(lighthouseResponse.lhr, lighthouseResponse.artifacts);
} catch (err) {
await this._resetEmulationAndProtocolConnection();
- if (err instanceof Error)
+ if (err instanceof Error) {
this._statusView.renderBugReport(err);
+ }
}
}
@@ -290,8 +299,9 @@ Audits.AuditsPanel = class extends UI.Panel {
emulationModel.deviceOutlineSetting().set(true);
for (const device of Emulation.EmulatedDevicesList.instance().standard()) {
- if (device.title === 'Nexus 5X')
+ if (device.title === 'Nexus 5X') {
emulationModel.emulate(Emulation.DeviceModeModel.Type.Device, device, device.modes[0], 1);
+ }
}
}
@@ -300,8 +310,9 @@ Audits.AuditsPanel = class extends UI.Panel {
}
async _resetEmulationAndProtocolConnection() {
- if (!this._isLHAttached)
+ if (!this._isLHAttached) {
return;
+ }
this._isLHAttached = false;
await this._protocolService.detach();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsProtocolService.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsProtocolService.js
index 67f7f9e1cf6..6f31a5f0ae3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsProtocolService.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsProtocolService.js
@@ -54,7 +54,7 @@ Audits.ProtocolService = class extends Common.Object {
}
/**
- * @param {!Object} message
+ * @param {(!Object|string)} message
*/
_dispatchProtocolMessage(message) {
this._send('dispatchProtocolMessage', {message: JSON.stringify(message)});
@@ -62,8 +62,9 @@ Audits.ProtocolService = class extends Common.Object {
_initWorker() {
this._backendPromise = Services.serviceManager.createAppService('audits_worker', 'AuditsService').then(backend => {
- if (this._backend)
+ if (this._backend) {
return;
+ }
this._backend = backend;
this._backend.on('statusUpdate', result => this._status(result.message));
this._backend.on('sendProtocolMessage', result => this._sendProtocolMessage(result.message));
@@ -83,8 +84,9 @@ Audits.ProtocolService = class extends Common.Object {
* @return {!Promise<!ReportRenderer.RunnerResult>}
*/
_send(method, params) {
- if (!this._backendPromise)
+ if (!this._backendPromise) {
this._initWorker();
+ }
return this._backendPromise.then(_ => this._backend.send(method, params));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportRenderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportRenderer.js
index f3f1edf2ac3..958c4469a7d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportRenderer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportRenderer.js
@@ -11,14 +11,16 @@ Audits.ReportRenderer = class extends ReportRenderer {
* @param {!ReportRenderer.RunnerResultArtifacts=} artifacts
*/
static addViewTraceButton(el, artifacts) {
- if (!artifacts || !artifacts.traces || !artifacts.traces.defaultPass)
+ if (!artifacts || !artifacts.traces || !artifacts.traces.defaultPass) {
return;
+ }
const container = el.querySelector('.lh-audit-group');
const columnsEl = container.querySelector('.lh-columns');
// There will be no columns if just the PWA category.
- if (!columnsEl)
+ if (!columnsEl) {
return;
+ }
const defaultPassTrace = artifacts.traces.defaultPass;
const timelineButton = UI.createTextButton(Common.UIString('View Trace'), onViewTraceClick, 'view-trace');
@@ -41,16 +43,19 @@ Audits.ReportRenderer = class extends ReportRenderer {
for (const origElement of el.getElementsByClassName('lh-node')) {
/** @type {!DetailsRenderer.NodeDetailsJSON} */
const detailsItem = origElement.dataset;
- if (!detailsItem.path)
+ if (!detailsItem.path) {
continue;
+ }
const nodeId = await domModel.pushNodeByPathToFrontend(detailsItem.path);
- if (!nodeId)
+ if (!nodeId) {
continue;
+ }
const node = domModel.nodeForId(nodeId);
- if (!node)
+ if (!node) {
continue;
+ }
const element = await Common.Linkifier.linkify(node, {tooltip: detailsItem.snippet});
origElement.title = '';
@@ -63,8 +68,9 @@ Audits.ReportRenderer = class extends ReportRenderer {
* @param {!Element} el
*/
static handleDarkMode(el) {
- if (UI.themeSupport.themeName() === 'dark')
+ if (UI.themeSupport.themeName() === 'dark') {
el.classList.add('dark');
+ }
}
};
@@ -124,19 +130,21 @@ Audits.ReportUIFeatures = class extends ReportUIFeatures {
const clonedReport = document.querySelector('.lh-root').cloneNode(true /* deep */);
const printWindow = window.open('', '_blank', 'channelmode=1,status=1,resizable=1');
const style = printWindow.document.createElement('style');
- style.textContent = Runtime.cachedResources['audits/lighthouse/report.css'];
+ style.textContent = Root.Runtime.cachedResources['audits/lighthouse/report.css'];
printWindow.document.head.appendChild(style);
printWindow.document.body.replaceWith(clonedReport);
// Linkified nodes are shadow elements, which aren't exposed via `cloneNode`.
await Audits.ReportRenderer.linkifyNodeDetails(clonedReport);
- if (this._beforePrint)
+ if (this._beforePrint) {
this._beforePrint();
+ }
printWindow.focus();
printWindow.print();
printWindow.close();
- if (this._afterPrint)
+ if (this._afterPrint) {
this._afterPrint();
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportSelector.js
index 43f959a7b1d..4ac9fd45fe9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsReportSelector.js
@@ -6,8 +6,7 @@ Audits.ReportSelector = class {
constructor(renderNewAuditView) {
this._renderNewAuditView = renderNewAuditView;
this._newAuditItem = createElement('option');
- this._comboBox = new UI.ToolbarComboBox(this._handleChange.bind(this), 'audits-report');
- this._comboBox.setTitle(ls`Reports`);
+ this._comboBox = new UI.ToolbarComboBox(this._handleChange.bind(this), ls`Reports`, 'audits-report');
this._comboBox.setMaxWidth(180);
this._comboBox.setMinWidth(140);
this._itemByOptionElement = new Map();
@@ -29,10 +28,11 @@ Audits.ReportSelector = class {
*/
_handleChange(event) {
const item = this._selectedItem();
- if (item)
+ if (item) {
item.select();
- else
+ } else {
this._renderNewAuditView();
+ }
}
/**
@@ -80,8 +80,9 @@ Audits.ReportSelector = class {
clearAll() {
for (const elem of this._comboBox.options()) {
- if (elem === this._newAuditItem)
+ if (elem === this._newAuditItem) {
continue;
+ }
this._itemByOptionElement.get(elem).delete();
this._itemByOptionElement.delete(elem);
@@ -124,8 +125,9 @@ Audits.ReportSelector.Item = class {
}
delete() {
- if (this._element)
+ if (this._element) {
this._element.remove();
+ }
this._showLandingCallback();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStartView.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStartView.js
index 736a8364416..f26f26e42b9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStartView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStartView.js
@@ -23,8 +23,9 @@ Audits.StartView = class extends UI.Widget {
*/
_populateRuntimeSettingAsRadio(settingName, label, parentElement) {
const runtimeSetting = Audits.RuntimeSettings.find(item => item.setting.name === settingName);
- if (!runtimeSetting || !runtimeSetting.options)
+ if (!runtimeSetting || !runtimeSetting.options) {
throw new Error(`${settingName} is not a setting with options`);
+ }
const control = new Audits.RadioSetting(runtimeSetting.options, runtimeSetting.setting, runtimeSetting.description);
parentElement.appendChild(control.element);
@@ -37,8 +38,9 @@ Audits.StartView = class extends UI.Widget {
*/
_populateRuntimeSettingAsCheckbox(settingName, parentElement) {
const runtimeSetting = Audits.RuntimeSettings.find(item => item.setting.name === settingName);
- if (!runtimeSetting || !runtimeSetting.title)
+ if (!runtimeSetting || !runtimeSetting.title) {
throw new Error(`${settingName} is not a setting with a title`);
+ }
runtimeSetting.setting.setTitle(runtimeSetting.title);
const control = new UI.ToolbarSettingCheckbox(runtimeSetting.setting, runtimeSetting.description);
@@ -62,6 +64,8 @@ Audits.StartView = class extends UI.Widget {
row.title = preset.description;
row.appendChild(checkbox.element);
}
+ UI.ARIAUtils.markAsGroup(categoryFormElements);
+ UI.ARIAUtils.setAccessibleName(categoryFormElements, ls`Audits`);
// Populate the throttling
const throttlingFormElements = fragment.$('throttling-form-elements');
@@ -148,18 +152,21 @@ Audits.StartView = class extends UI.Widget {
* @param {boolean} isEnabled
*/
setStartButtonEnabled(isEnabled) {
- if (this._helpText)
+ if (this._helpText) {
this._helpText.classList.toggle('hidden', isEnabled);
+ }
- if (this._startButton)
+ if (this._startButton) {
this._startButton.disabled = !isEnabled;
+ }
}
/**
* @param {?string} text
*/
setUnauditableExplanation(text) {
- if (this._helpText)
+ if (this._helpText) {
this._helpText.textContent = text;
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStatusView.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStatusView.js
index 59dc63852d4..c8a67a5afe4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStatusView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/AuditsStatusView.js
@@ -96,8 +96,9 @@ Audits.StatusView = class {
}
hide() {
- if (this._dialog.isShowing())
+ if (this._dialog.isShowing()) {
this._dialog.hide();
+ }
}
/**
@@ -111,8 +112,9 @@ Audits.StatusView = class {
* @param {?string} message
*/
updateStatus(message) {
- if (!message || !this._statusText)
+ if (!message || !this._statusText) {
return;
+ }
if (message.startsWith('Cancel')) {
this._commitTextChange(Common.UIString('Cancelling\u2026'));
@@ -142,8 +144,9 @@ Audits.StatusView = class {
* @return {string}
*/
_getMessageForPhase(phase) {
- if (phase.message)
- return Common.UIString(phase.message);
+ if (phase.message) {
+ return phase.message;
+ }
const deviceType = Audits.RuntimeSettings.find(item => item.setting.name === 'audits.device_type').setting.get();
const throttling = Audits.RuntimeSettings.find(item => item.setting.name === 'audits.throttling').setting.get();
@@ -151,7 +154,7 @@ Audits.StatusView = class {
return item.deviceType === deviceType && item.throttling === throttling;
});
- return match ? ls`${match.message}` : ls`Lighthouse is loading your page`;
+ return match ? match.message : ls`Lighthouse is loading your page`;
}
/**
@@ -163,15 +166,17 @@ Audits.StatusView = class {
}
_resetProgressBarClasses() {
- if (!this._progressBar)
+ if (!this._progressBar) {
return;
+ }
this._progressBar.className = 'audits-progress-bar';
}
_scheduleFastFactCheck() {
- if (!this._currentPhase || this._scheduledFastFactTimeout)
+ if (!this._currentPhase || this._scheduledFastFactTimeout) {
return;
+ }
this._scheduledFastFactTimeout = setTimeout(() => {
this._updateFastFactIfNecessary();
@@ -183,10 +188,12 @@ Audits.StatusView = class {
_updateFastFactIfNecessary() {
const now = performance.now();
- if (now - this._textChangedAt < Audits.StatusView.fastFactRotationInterval)
+ if (now - this._textChangedAt < Audits.StatusView.fastFactRotationInterval) {
return;
- if (!this._fastFactsQueued.length)
+ }
+ if (!this._fastFactsQueued.length) {
return;
+ }
const fastFactIndex = Math.floor(Math.random() * this._fastFactsQueued.length);
this._scheduleTextChange(ls`\ud83d\udca1 ${this._fastFactsQueued[fastFactIndex]}`);
@@ -197,8 +204,9 @@ Audits.StatusView = class {
* @param {string} text
*/
_commitTextChange(text) {
- if (!this._statusText)
+ if (!this._statusText) {
return;
+ }
this._textChangedAt = performance.now();
this._statusText.textContent = text;
}
@@ -207,8 +215,9 @@ Audits.StatusView = class {
* @param {string} text
*/
_scheduleTextChange(text) {
- if (this._scheduledTextChangeTimeout)
+ if (this._scheduledTextChangeTimeout) {
clearTimeout(this._scheduledTextChangeTimeout);
+ }
const msSinceLastChange = performance.now() - this._textChangedAt;
const msToTextChange = Audits.StatusView.minimumTextVisibilityDuration - msSinceLastChange;
@@ -297,14 +306,14 @@ Audits.StatusView.StatusPhases = [
{
id: 'gathering',
progressBarClass: 'gathering',
- message: 'Lighthouse is gathering information about the page to compute your score.',
+ message: ls`Lighthouse is gathering information about the page to compute your score.`,
statusMessagePrefix: 'Gathering',
order: 20,
},
{
id: 'auditing',
progressBarClass: 'auditing',
- message: 'Almost there! Lighthouse is now generating your report.',
+ message: ls`Almost there! Lighthouse is now generating your report.`,
statusMessagePrefix: 'Auditing',
order: 30,
}
@@ -315,42 +324,42 @@ Audits.StatusView.LoadingMessages = [
{
deviceType: 'mobile',
throttling: 'on',
- message: 'Lighthouse is loading your page with throttling to measure performance on a mobile device on 3G.',
+ message: ls`Lighthouse is loading your page with throttling to measure performance on a mobile device on 3G.`,
},
{
deviceType: 'desktop',
throttling: 'on',
- message: 'Lighthouse is loading your page with throttling to measure performance on a slow desktop on 3G.',
+ message: ls`Lighthouse is loading your page with throttling to measure performance on a slow desktop on 3G.`,
},
{
deviceType: 'mobile',
throttling: 'off',
- message: 'Lighthouse is loading your page with mobile emulation.',
+ message: ls`Lighthouse is loading your page with mobile emulation.`,
},
{
deviceType: 'desktop',
throttling: 'off',
- message: 'Lighthouse is loading your page.',
+ message: ls`Lighthouse is loading your page.`,
},
];
Audits.StatusView.FastFacts = [
- '1MB takes a minimum of 5 seconds to download on a typical 3G connection [Source: WebPageTest and DevTools 3G definition].',
- 'Rebuilding Pinterest pages for performance increased conversion rates by 15% [Source: WPO Stats]',
- 'BBC has seen a loss of 10% of their users for every extra second of page load [Source: WPO Stats]',
- 'By reducing the response size of JSON needed for displaying comments, Instagram saw increased impressions [Source: WPO Stats]',
- 'Walmart saw a 1% increase in revenue for every 100ms improvement in page load [Source: WPO Stats]',
- 'If a site takes >1 second to become interactive, users lose attention, and their perception of completing the page task is broken [Source: Google Developers Blog]',
- '75% of global mobile users in 2016 were on 2G or 3G [Source: GSMA Mobile]',
- 'The average user device costs less than 200 USD. [Source: International Data Corporation]',
- '53% of all site visits are abandoned if page load takes more than 3 seconds [Source: Google DoubleClick blog]',
- '19 seconds is the average time a mobile web page takes to load on a 3G connection [Source: Google DoubleClick blog]',
- '14 seconds is the average time a mobile web page takes to load on a 4G connection [Source: Google DoubleClick blog]',
- '70% of mobile pages take nearly 7 seconds for the visual content above the fold to display on the screen. [Source: Think with Google]',
- 'As page load time increases from one second to seven seconds, the probability of a mobile site visitor bouncing increases 113%. [Source: Think with Google]',
- 'As the number of elements on a page increases from 400 to 6,000, the probability of conversion drops 95%. [Source: Think with Google]',
- '70% of mobile pages weigh over 1MB, 36% over 2MB, and 12% over 4MB. [Source: Think with Google]',
- 'Lighthouse only simulates mobile performance; to measure performance on a real device, try WebPageTest.org [Source: Lighthouse team]',
+ ls`1MB takes a minimum of 5 seconds to download on a typical 3G connection [Source: WebPageTest and DevTools 3G definition].`,
+ ls`Rebuilding Pinterest pages for performance increased conversion rates by 15% [Source: WPO Stats]`,
+ ls`BBC has seen a loss of 10% of their users for every extra second of page load [Source: WPO Stats]`,
+ ls`By reducing the response size of JSON needed for displaying comments, Instagram saw increased impressions [Source: WPO Stats]`,
+ ls`Walmart saw a 1% increase in revenue for every 100ms improvement in page load [Source: WPO Stats]`,
+ ls`If a site takes >1 second to become interactive, users lose attention, and their perception of completing the page task is broken [Source: Google Developers Blog]`,
+ ls`75% of global mobile users in 2016 were on 2G or 3G [Source: GSMA Mobile]`,
+ ls`The average user device costs less than 200 USD. [Source: International Data Corporation]`,
+ ls`53% of all site visits are abandoned if page load takes more than 3 seconds [Source: Google DoubleClick blog]`,
+ ls`19 seconds is the average time a mobile web page takes to load on a 3G connection [Source: Google DoubleClick blog]`,
+ ls`14 seconds is the average time a mobile web page takes to load on a 4G connection [Source: Google DoubleClick blog]`,
+ ls`70% of mobile pages take nearly 7 seconds for the visual content above the fold to display on the screen. [Source: Think with Google]`,
+ ls`As page load time increases from one second to seven seconds, the probability of a mobile site visitor bouncing increases 113%. [Source: Think with Google]`,
+ ls`As the number of elements on a page increases from 400 to 6,000, the probability of conversion drops 95%. [Source: Think with Google]`,
+ ls`70% of mobile pages weigh over 1MB, 36% over 2MB, and 12% over 4MB. [Source: Think with Google]`,
+ ls`Lighthouse only simulates mobile performance; to measure performance on a real device, try WebPageTest.org [Source: Lighthouse team]`,
];
/** @const */
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/RadioSetting.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/RadioSetting.js
index ddc84f55af6..bbe09e5e453 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/RadioSetting.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/RadioSetting.js
@@ -27,8 +27,9 @@ Audits.RadioSetting = class {
`;
this.element.appendChild(fragment.element());
- if (option.title)
+ if (option.title) {
UI.Tooltip.install(fragment.$('label'), option.title);
+ }
const radioElement = fragment.$('input');
radioElement.addEventListener('change', this._valueChanged.bind(this));
this._radioElements.push(radioElement);
@@ -57,8 +58,9 @@ Audits.RadioSetting = class {
* @param {!Event} event
*/
_valueChanged(event) {
- if (this._ignoreChangeEvents)
+ if (this._ignoreChangeEvents) {
return;
+ }
const selectedRadio = this._radioElements.find(radio => radio.checked);
this._setting.set(selectedRadio.value);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
index 2ee87303b6b..bebdb98b781 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/audits_strings.grdp
@@ -12,56 +12,53 @@
<message name="IDS_DEVTOOLS_0f39dfdd740bf99080ca83e56e2cfb4c" desc="Text in Audits Status View">
💡 <ph name="THIS__FASTFACTSQUEUED_FASTFACTINDEX_">$1s<ex>75% of global mobile users in 2016 were on 2G or 3G [Source: GSMA Mobile]</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_1076f1bac69647c846ac3b822b133518" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ The average user device costs less than 200 USD. [Source: <ph name="LOCKED_1">International Data Corporation</ph>]
+ </message>
<message name="IDS_DEVTOOLS_1421c82f3616812789ac346b1638e39d" desc="Text of audits start button in Audits Start View">
Run audits
</message>
- <message name="IDS_DEVTOOLS_1583d36995134f9120fac115c08e0174" desc="Text in Audits Status View">
- Loading…
- </message>
<message name="IDS_DEVTOOLS_15a895a381c23eff5397d8b1f318a726" desc="Text in Audits Controller">
No network or CPU throttling used. (Useful when not evaluating performance)
</message>
<message name="IDS_DEVTOOLS_161bf73e31de6b8e3d856815473cbe1c" desc="Text of the timeline button in Audits Report Renderer">
View Trace
</message>
+ <message name="IDS_DEVTOOLS_169ece87d3c6b79c2c8d69892927857c" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 19 seconds is the average time a mobile web page takes to load on a 3G connection [Source: <ph name="LOCKED_1">Google DoubleClick blog</ph>]
+ </message>
<message name="IDS_DEVTOOLS_17de62900ceac9101c8814b4c4874328" desc="Text in Audits Controller">
Apply mobile emulation during auditing
</message>
<message name="IDS_DEVTOOLS_193c4edb3ab576449959f6710e017a49" desc="Text in Audits Controller">
- Typical DevTools throttling, with actual traffic shaping and CPU slowdown applied
- </message>
- <message name="IDS_DEVTOOLS_1c481aa99d081c32182011a758f73d33" desc="Text in Audits Status View">
- <ph name="MATCH_MESSAGE">$1s<ex>Lighthouse is loading your page.</ex></ph>
+ Typical <ph name="LOCKED_1">DevTools</ph> throttling, with actual traffic shaping and CPU slowdown applied
</message>
<message name="IDS_DEVTOOLS_2046d43f4cc1f59c06f764da2ca2355a" desc="Status text in the Audits panel">
The print popup window is open. Please close it to continue.
</message>
- <message name="IDS_DEVTOOLS_2310408a63388fe57e3a4177168a8798" desc="Text in Audits Controller">
- Desktop
+ <message name="IDS_DEVTOOLS_24e8ca2483129261096ba8ba0fbcd247" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 70% of mobile pages take nearly 7 seconds for the visual content above the fold to display on the screen. [Source: <ph name="LOCKED_1">Think with Google</ph>]
</message>
<message name="IDS_DEVTOOLS_2a96c07a6c11ca7add2b1ffde86efe25" desc="Text in Audits Controller">
- Can only audit HTTP/HTTPS pages and Chrome extensions. Navigate to a different page to start an audit.
+ Can only audit HTTP/HTTPS pages and <ph name="LOCKED_1">Chrome</ph> extensions. Navigate to a different page to start an audit.
</message>
<message name="IDS_DEVTOOLS_39680b3025b1f8d881f9d983623bf071" desc="Text in Audits Status View">
- Lighthouse is loading your page
+ <ph name="LOCKED_1">Lighthouse</ph> is loading your page
</message>
<message name="IDS_DEVTOOLS_3b7e043f46813f1d8ffbd462eb77fb6c" desc="Text in Audits Controller">
How long does this app take to show content and become usable
</message>
- <message name="IDS_DEVTOOLS_3e3f8a3abd60f2389b744ca8ed0aa4d9" desc="Text in Audits Controller">
- No throttling
- </message>
<message name="IDS_DEVTOOLS_3ee3aab0791156ff1d5e0481ed4589b2" desc="Text in Audits Controller">
Applied Slow 4G, 4x CPU Slowdown
</message>
- <message name="IDS_DEVTOOLS_41fdb410354e76ef7674f98e1cc84c8f" desc="Text in Audits Start View labeling throttling configration control group">
- Throttling
+ <message name="IDS_DEVTOOLS_47e2dbd37d8d524f5c4105a96db27b59" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 75% of global mobile users in 2016 were on 2G or 3G [Source: <ph name="LOCKED_1">GSMA Mobile</ph>]
</message>
<message name="IDS_DEVTOOLS_48d24d11c7c71282366fe2007d4cee3b" desc="Text in Audits Controller">
Throttling is simulated, resulting in faster audit runs with similar measurement accuracy
</message>
<message name="IDS_DEVTOOLS_4ab5093468559edd5940ac59f1c6ac02" desc="Text in Audits Status View">
- Try to navigate to the URL in a fresh Chrome profile without any other tabs or extensions open and try again.
+ Try to navigate to the URL in a fresh <ph name="LOCKED_1">Chrome</ph> profile without any other tabs or extensions open and try again.
</message>
<message name="IDS_DEVTOOLS_55f562701dc2cc775f9adc0478644b2a" desc="Tooltip text that appears when hovering over the largeicon add button in the Audits Panel">
Perform an audit…
@@ -69,6 +66,15 @@
<message name="IDS_DEVTOOLS_56395991012586c2067aa7bcb5905b50" desc="Text in Audits Panel">
Cancelling
</message>
+ <message name="IDS_DEVTOOLS_56846b99d193dbbd252ddca10d29aff4" desc="Text when lighthouse is loading the page in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> is loading your page with throttling to measure performance on a mobile device on 3G.
+ </message>
+ <message name="IDS_DEVTOOLS_5a73519018eaaacb7882caf8f0971ac1" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 1MB takes a minimum of 5 seconds to download on a typical 3G connection [Source: <ph name="LOCKED_1">WebPageTest</ph> and <ph name="LOCKED_2">DevTools</ph> 3G definition].
+ </message>
+ <message name="IDS_DEVTOOLS_5f0c08bc61549e7455c9e8b46bfe9aa9" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 70% of mobile pages weigh over 1MB, 36% over 2MB, and 12% over 4MB. [Source: <ph name="LOCKED_1">Think with Google</ph>]
+ </message>
<message name="IDS_DEVTOOLS_64a64ca70e7a909a5a96c07082070bfc" desc="Text of a DOM element in Audits Status View">
Ah, sorry! We ran into an error.
</message>
@@ -84,38 +90,59 @@
<message name="IDS_DEVTOOLS_67aa731132e0e7bbabb1b3d3c363e7d6" desc="Help text in Audits Controller">
Multiple tabs are being controlled by the same service worker. Close your other tabs on the same origin to audit this page.
</message>
+ <message name="IDS_DEVTOOLS_6e394d18cb68d551f58fa35f4dfc70bb" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ As page load time increases from one second to seven seconds, the probability of a mobile site visitor bouncing increases 113%. [Source: <ph name="LOCKED_1">Think with Google</ph>]
+ </message>
<message name="IDS_DEVTOOLS_72c4a2e545d220fd8c9ead876a59a89d" desc="Text in Audits Controller">
Is this page optimized for search engine results ranking
</message>
+ <message name="IDS_DEVTOOLS_73351c316c7866b1c5730af9c82b5ab3" desc="Text when lighthouse is loading the page in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> is loading your page with throttling to measure performance on a slow desktop on 3G.
+ </message>
+ <message name="IDS_DEVTOOLS_7387b82b5b5cbc317147961ff45142c5" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ Walmart saw a 1% increase in revenue for every 100ms improvement in page load [Source: <ph name="LOCKED_1">WPO Stats</ph>]
+ </message>
+ <message name="IDS_DEVTOOLS_77d52e376f0c781e4f0d908f6d0b7ff2" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> only simulates mobile performance; to measure performance on a real device, try WebPageTest.org [Source: <ph name="LOCKED_2">Lighthouse</ph> team]
+ </message>
+ <message name="IDS_DEVTOOLS_78b8123c78d60b80d6a09618ad56c2cb" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ Rebuilding Pinterest pages for performance increased conversion rates by 15% [Source: <ph name="LOCKED_1">WPO Stats</ph>]
+ </message>
<message name="IDS_DEVTOOLS_7bd1e4f7363173e2c8329551ca4d38cc" desc="New audit item label in Audits Report Selector">
(new audit)
</message>
- <message name="IDS_DEVTOOLS_87d17f4624a514e81dc7c8e016a7405c" desc="Text in Audits Controller">
- Mobile
- </message>
<message name="IDS_DEVTOOLS_88450f419690173d62fb0a30fb29a951" desc="Text in Audits Status View">
Auditing <ph name="PAGEHOST">$1s<ex>github.com</ex></ph>
</message>
<message name="IDS_DEVTOOLS_8eb7115e5b4ba55f56931ec24c789f9e" desc="Text in Audits Status View">
- Lighthouse is warming up…
+ <ph name="LOCKED_1">Lighthouse</ph> is warming up…
</message>
<message name="IDS_DEVTOOLS_8fe967af0fb77d0261a6ead91bcd607f" desc="Text in Audits Controller">
Reset storage (localStorage, IndexedDB, etc) before auditing. (Good for performance &amp; PWA testing)
</message>
- <message name="IDS_DEVTOOLS_9446a98ad14416153cc4d45ab8b531bf" desc="Text in Audits Controller">
- Performance
+ <message name="IDS_DEVTOOLS_9103edac10b1749db57ca27386ff29dc" desc="Text when lighthouse is loading the page in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> is loading your page.
+ </message>
+ <message name="IDS_DEVTOOLS_93c09fb3e06297a9b9504113fa5915ea" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ BBC has seen a loss of 10% of their users for every extra second of page load [Source: <ph name="LOCKED_1">WPO Stats</ph>]
+ </message>
+ <message name="IDS_DEVTOOLS_a3456af9cc3d7cf0c2e288f889f050b7" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ If a site takes &gt;1 second to become interactive, users lose attention, and their perception of completing the page task is broken [Source: <ph name="LOCKED_1">Google Developers Blog</ph>]
+ </message>
+ <message name="IDS_DEVTOOLS_a99169b94755be554b65f8dcc2c2b842" desc="Text in the pop-up dialog when lighthouse is gathering information in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> is gathering information about the page to compute your score.
</message>
<message name="IDS_DEVTOOLS_b002a564ceda05dbdf012a48a145d0d3" desc="Status header in the Audits panel">
Printing
</message>
- <message name="IDS_DEVTOOLS_b06c94565d768dd75535120f2f8482a7" desc="Text in Audits Start View">
+ <message name="IDS_DEVTOOLS_b06c94565d768dd75535120f2f8482a7" desc="Text in Audits Start View labeling audit configuraion control group">
Audits
</message>
<message name="IDS_DEVTOOLS_b1b01acb63f79615b05f6d816705d7d3" desc="Text in Audits Controller">
Does this page meet the standard of a Progressive Web App
</message>
- <message name="IDS_DEVTOOLS_bc28aa52ba5b534ad9d198157c375d67" desc="Text in Audits Controller">
- Clear storage
+ <message name="IDS_DEVTOOLS_b29bb7427a05d89f1dae6ab5459e2d5c" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ By reducing the response size of JSON needed for displaying comments, Instagram saw increased impressions [Source: <ph name="LOCKED_1">WPO Stats</ph>]
</message>
<message name="IDS_DEVTOOLS_bcf2457dd80557dd7ebdc1504b6149e6" desc="Text in Audits Controller">
Does this page follow best practices for modern web development
@@ -126,8 +153,8 @@
<message name="IDS_DEVTOOLS_c91c7b93c28cd18741b71f727ee81ee3" desc="Title of combo box in audits report selector">
Reports
</message>
- <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc="Text in Audits Start View">
- Learn more
+ <message name="IDS_DEVTOOLS_d2f618fd63c7c2028cd527f60e761bc6" desc="Text when lighthouse is loading the page in the Audits panel">
+ <ph name="LOCKED_1">Lighthouse</ph> is loading your page with mobile emulation.
</message>
<message name="IDS_DEVTOOLS_d88946b678e4c2f251d4e292e8142291" desc="Text in Audits Controller">
SEO
@@ -135,16 +162,25 @@
<message name="IDS_DEVTOOLS_deeacee140c7d3a451440dd0e206e256" desc="Text in Audits Start View">
Identify and fix common problems that affect your site&apos;s performance, accessibility, and user experience.
</message>
- <message name="IDS_DEVTOOLS_e0ac20adce6ffee48c7151b070aa5737" desc="Text in Audits Start View labeling device configration control group">
- Device
+ <message name="IDS_DEVTOOLS_e339ef3bcd3e92466fa83dc21e690a5b" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ As the number of elements on a page increases from 400 to 6,000, the probability of conversion drops 95%. [Source: <ph name="LOCKED_1">Think with Google</ph>]
</message>
<message name="IDS_DEVTOOLS_e499f5109f685235e6280179fe22beec" desc="Text that appears when user drag and drop something (for example, a file) in Audits Panel">
Drop audit file here
</message>
- <message name="IDS_DEVTOOLS_ea4788705e6873b424c65e91c2846b19" desc="Text of the cancel button in Audits Status View">
- Cancel
+ <message name="IDS_DEVTOOLS_e8e1638b0449b103a9fdcee6c12d700c" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 14 seconds is the average time a mobile web page takes to load on a 4G connection [Source: <ph name="LOCKED_1">Google DoubleClick blog</ph>]
+ </message>
+ <message name="IDS_DEVTOOLS_e9fe69c2de7c38bbe442e38780d20081" desc="Fast fact in the pop-up dialog when lighthouse is running in the Audits panel">
+ 53% of all site visits are abandoned if page load takes more than 3 seconds [Source: <ph name="LOCKED_1">Google DoubleClick blog</ph>]
</message>
<message name="IDS_DEVTOOLS_ea60ba1496b05c6a5816fb75d0665c8d" desc="Text of a DOM element in Audits Status View">
- If this issue is reproducible, please report it at the Lighthouse GitHub repo.
+ If this issue is reproducible, please report it at the <ph name="LOCKED_1">Lighthouse</ph> <ph name="LOCKED_2">GitHub</ph> repo.
+ </message>
+ <message name="IDS_DEVTOOLS_f3ddea8173e7a06f7a6a5dadc234fd3d" desc="Text in the pop-up dialog when lighthouse is auditing in the Audits panel">
+ Almost there! <ph name="LOCKED_1">Lighthouse</ph> is now generating your report.
+ </message>
+ <message name="IDS_DEVTOOLS_fad0ce221c826eede253cb0956ca0700" desc="A search term referring to the linting application named Lighthouse that can be entered in the command menu">
+ <ph name="LOCKED_1">lighthouse</ph>
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report-generator.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report-generator.js
index 829a1b19191..289d2393440 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report-generator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report-generator.js
@@ -8,14 +8,14 @@
/**
* @fileoverview Instead of loading report assets form the filesystem, in Devtools we must load
- * them via Runtime.cachedResources. We use this module to shim
+ * them via Root.Runtime.cachedResources. We use this module to shim
* lighthouse-core/report/html/html-report-assets.js in Devtools.
*/
-/* global Runtime */
+/* global Root */
-// @ts-ignore: Runtime exists in Devtools.
-const cachedResources = Runtime.cachedResources;
+// @ts-ignore: Root.Runtime exists in Devtools.
+const cachedResources = Root.Runtime.cachedResources;
// Getters are necessary because the DevTools bundling processes
// resources after this module is resolved. These properties are not
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.css b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.css
index 880c39b1659..e6d40ba60ff 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.css
@@ -262,6 +262,10 @@
.lh-devtools.lh-root {
height: 100%;
}
+.lh-devtools.lh-root img {
+ /* Override devtools default 'min-width: 0' so svg without size in a flexbox isn't collapsed. */
+ min-width: auto;
+}
.lh-devtools .lh-container {
overflow-y: scroll;
height: calc(100% - var(--topbar-height));
@@ -1161,11 +1165,6 @@
width: var(--gauge-wrapper-width);
}
-.lh-scores-header .lh-gauge--pwa__wrapper {
- /* Can remove when this bug is resolved: https://bugs.chromium.org/p/chromium/issues/detail?id=942097 */
- will-change: transform;
-}
-
.lh-scorescale {
display: inline-flex;
margin: 12px auto 0 auto;
@@ -1391,6 +1390,11 @@
display: block;
}
+.lh-unknown pre {
+ overflow: scroll;
+ border: solid 1px var(--color-gray-200);
+}
+
.lh-text__url > a {
color: inherit;
text-decoration: none;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.js b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.js
index 0dff90994f1..0f63105b259 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/report.js
@@ -192,7 +192,7 @@ class Util {
*/
static formatNumber(number, granularity = 0.1) {
const coarseValue = Math.round(number / granularity) * granularity;
- return coarseValue.toLocaleString(Util.numberDateLocale);
+ return Util.numberFormatter.format(coarseValue);
}
/**
@@ -201,8 +201,7 @@ class Util {
* @return {string}
*/
static formatBytesToKB(size, granularity = 0.1) {
- const kbs = (Math.round(size / 1024 / granularity) * granularity)
- .toLocaleString(Util.numberDateLocale);
+ const kbs = Util.numberFormatter.format(Math.round(size / 1024 / granularity) * granularity);
return `${kbs}${NBSP}KB`;
}
@@ -213,7 +212,7 @@ class Util {
*/
static formatMilliseconds(ms, granularity = 10) {
const coarseTime = Math.round(ms / granularity) * granularity;
- return `${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}ms`;
+ return `${Util.numberFormatter.format(coarseTime)}${NBSP}ms`;
}
/**
@@ -223,7 +222,7 @@ class Util {
*/
static formatSeconds(ms, granularity = 0.1) {
const coarseTime = Math.round(ms / 1000 / granularity) * granularity;
- return `${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}s`;
+ return `${Util.numberFormatter.format(coarseTime)}${NBSP}s`;
}
/**
@@ -281,6 +280,73 @@ class Util {
}
/**
+ * Split a string by markdown code spans (enclosed in `backticks`), splitting
+ * into segments that were enclosed in backticks (marked as `isCode === true`)
+ * and those that outside the backticks (`isCode === false`).
+ * @param {string} text
+ * @return {Array<{isCode: true, text: string}|{isCode: false, text: string}>}
+ */
+ static splitMarkdownCodeSpans(text) {
+ /** @type {Array<{isCode: true, text: string}|{isCode: false, text: string}>} */
+ const segments = [];
+
+ // Split on backticked code spans.
+ const parts = text.split(/`(.*?)`/g);
+ for (let i = 0; i < parts.length; i ++) {
+ const text = parts[i];
+
+ // Empty strings are an artifact of splitting, not meaningful.
+ if (!text) continue;
+
+ // Alternates between plain text and code segments.
+ const isCode = i % 2 !== 0;
+ segments.push({
+ isCode,
+ text,
+ });
+ }
+
+ return segments;
+ }
+
+ /**
+ * Split a string on markdown links (e.g. [some link](https://...)) into
+ * segments of plain text that weren't part of a link (marked as
+ * `isLink === false`), and segments with text content and a URL that did make
+ * up a link (marked as `isLink === true`).
+ * @param {string} text
+ * @return {Array<{isLink: true, text: string, linkHref: string}|{isLink: false, text: string}>}
+ */
+ static splitMarkdownLink(text) {
+ /** @type {Array<{isLink: true, text: string, linkHref: string}|{isLink: false, text: string}>} */
+ const segments = [];
+
+ const parts = text.split(/\[([^\]]+?)\]\((https?:\/\/.*?)\)/g);
+ while (parts.length) {
+ // Shift off the same number of elements as the pre-split and capture groups.
+ const [preambleText, linkText, linkHref] = parts.splice(0, 3);
+
+ if (preambleText) { // Skip empty text as it's an artifact of splitting, not meaningful.
+ segments.push({
+ isLink: false,
+ text: preambleText,
+ });
+ }
+
+ // Append link if there are any.
+ if (linkText && linkHref) {
+ segments.push({
+ isLink: true,
+ text: linkText,
+ linkHref,
+ });
+ }
+ }
+
+ return segments;
+ }
+
+ /**
* @param {URL} parsedUrl
* @param {{numPathParts?: number, preserveQuery?: boolean, preserveHost?: boolean}=} options
* @return {string}
@@ -489,10 +555,11 @@ class Util {
* @param {LH.Locale} locale
*/
static setNumberDateLocale(locale) {
- Util.numberDateLocale = locale;
-
// When testing, use a locale with more exciting numeric formatting
- if (Util.numberDateLocale === 'en-XA') Util.numberDateLocale = 'de';
+ if (locale === 'en-XA') locale = 'de';
+
+ Util.numberDateLocale = locale;
+ Util.numberFormatter = new Intl.NumberFormat(locale);
}
/**
@@ -552,6 +619,12 @@ class Util {
Util.numberDateLocale = 'en';
/**
+ * This value stays in sync with Util.numberDateLocale.
+ * @type {Intl.NumberFormat}
+ */
+Util.numberFormatter = new Intl.NumberFormat(Util.numberDateLocale);
+
+/**
* Report-renderer-specific strings.
* @type {LH.I18NRendererStrings}
*/
@@ -626,7 +699,7 @@ if (typeof module !== 'undefined' && module.exports) {
*/
'use strict';
-/* globals URL self */
+/* globals URL self Util */
/** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElementByTagName */
@@ -727,52 +800,47 @@ class DOM {
convertMarkdownLinkSnippets(text) {
const element = this.createElement('span');
- // Split on markdown links (e.g. [some link](https://...)).
- const parts = text.split(/\[([^\]]*?)\]\((https?:\/\/.*?)\)/g);
-
- while (parts.length) {
- // Pop off the same number of elements as there are capture groups.
- const [preambleText, linkText, linkHref] = parts.splice(0, 3);
- element.appendChild(this._document.createTextNode(preambleText));
-
- // Append link if there are any.
- if (linkText && linkHref) {
- const url = new URL(linkHref);
+ for (const segment of Util.splitMarkdownLink(text)) {
+ if (!segment.isLink) {
+ // Plain text segment.
+ element.appendChild(this._document.createTextNode(segment.text));
+ continue;
+ }
- const DEVELOPERS_GOOGLE_ORIGIN = 'https://developers.google.com';
- if (url.origin === DEVELOPERS_GOOGLE_ORIGIN) {
- url.searchParams.set('utm_source', 'lighthouse');
- url.searchParams.set('utm_medium', this._lighthouseChannel);
- }
+ // Otherwise, append any links found.
+ const url = new URL(segment.linkHref);
- const a = this.createElement('a');
- a.rel = 'noopener';
- a.target = '_blank';
- a.textContent = linkText;
- a.href = url.href;
- element.appendChild(a);
+ const DOCS_ORIGINS = ['https://developers.google.com', 'https://web.dev'];
+ if (DOCS_ORIGINS.includes(url.origin)) {
+ url.searchParams.set('utm_source', 'lighthouse');
+ url.searchParams.set('utm_medium', this._lighthouseChannel);
}
+
+ const a = this.createElement('a');
+ a.rel = 'noopener';
+ a.target = '_blank';
+ a.textContent = segment.text;
+ a.href = url.href;
+ element.appendChild(a);
}
return element;
}
/**
- * @param {string} text
+ * @param {string} markdownText
* @return {Element}
*/
- convertMarkdownCodeSnippets(text) {
+ convertMarkdownCodeSnippets(markdownText) {
const element = this.createElement('span');
- const parts = text.split(/`(.*?)`/g); // Split on markdown code slashes
- while (parts.length) {
- // Pop off the same number of elements as there are capture groups.
- const [preambleText, codeText] = parts.splice(0, 2);
- element.appendChild(this._document.createTextNode(preambleText));
- if (codeText) {
+ for (const segment of Util.splitMarkdownCodeSpans(markdownText)) {
+ if (segment.isCode) {
const pre = this.createElement('code');
- pre.textContent = codeText;
+ pre.textContent = segment.text;
element.appendChild(pre);
+ } else {
+ element.appendChild(this._document.createTextNode(segment.text));
}
}
@@ -836,27 +904,18 @@ if (typeof module !== 'undefined' && module.exports) {
}
;
/*
-Details Element Polyfill 2.2.0
-Copyright © 2018 Javan Makhmali
+Details Element Polyfill 2.4.0
+Copyright © 2019 Javan Makhmali
*/
(function() {
"use strict";
var element = document.createElement("details");
- element.innerHTML = "<summary>a</summary>b";
- element.setAttribute("style", "position: absolute; left: -9999px");
+ var elementIsNative = typeof HTMLDetailsElement != "undefined" && element instanceof HTMLDetailsElement;
var support = {
- open: "open" in element && elementExpands(),
+ open: "open" in element || elementIsNative,
toggle: "ontoggle" in element
};
- function elementExpands() {
- (document.body || document.documentElement).appendChild(element);
- var closedHeight = element.offsetHeight;
- element.open = true;
- var openedHeight = element.offsetHeight;
- element.parentNode.removeChild(element);
- return closedHeight != openedHeight;
- }
- var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\ndetails > summary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\ndetails[open] > summary::before {\n content: "▼";\n}\n';
+ var styles = '\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n';
var _ref = [], forEach = _ref.forEach, slice = _ref.slice;
if (!support.open) {
polyfillStyles();
@@ -946,7 +1005,7 @@ Copyright © 2018 Javan Makhmali
forEach.call(mutations, function(mutation) {
var target = mutation.target, attributeName = mutation.attributeName;
if (target.tagName == "DETAILS" && attributeName == "open") {
- triggerToggle(toggle);
+ triggerToggle(target);
}
});
}).observe(document.documentElement, {
@@ -1018,7 +1077,7 @@ Copyright © 2018 Javan Makhmali
}
function triggerToggle(element) {
var event = document.createEvent("Event");
- event.initEvent("toggle", true, false);
+ event.initEvent("toggle", false, false);
element.dispatchEvent(event);
}
function findElementsWithTagName(root, tagName) {
@@ -1104,9 +1163,9 @@ class DetailsRenderer {
return null;
default: {
- // @ts-ignore tsc thinks this unreachable, but ts-ignore for error message just in case.
- const detailsType = details.type;
- throw new Error(`Unknown type: ${detailsType}`);
+ // @ts-ignore tsc thinks this is unreachable, but be forward compatible
+ // with new unexpected detail types.
+ return this._renderUnknown(details.type, details);
}
}
}
@@ -1230,6 +1289,22 @@ class DetailsRenderer {
}
/**
+ * @param {string} type
+ * @param {*} value
+ */
+ _renderUnknown(type, value) {
+ // eslint-disable-next-line no-console
+ console.error(`Unknown details type: ${type}`, value);
+ const element = this._dom.createElement('details', 'lh-unknown');
+ this._dom.createChildOf(element, 'summary').textContent =
+ `We don't know how to render audit details of type \`${type}\`. ` +
+ 'The Lighthouse version that collected this data is likely newer than the Lighthouse ' +
+ 'version of the report renderer. Expand for the raw JSON.';
+ this._dom.createChildOf(element, 'pre').textContent = JSON.stringify(value, null, 2);
+ return element;
+ }
+
+ /**
* Render a details item value for embedding in a table. Renders the value
* based on the heading's valueType, unless the value itself has a `type`
* property to override it.
@@ -1259,7 +1334,7 @@ class DetailsRenderer {
return this.renderTextURL(value.value);
}
default: {
- throw new Error(`Unknown valueType: ${value.type}`);
+ return this._renderUnknown(value.type, value);
}
}
}
@@ -1308,7 +1383,7 @@ class DetailsRenderer {
}
}
default: {
- throw new Error(`Unknown valueType: ${heading.valueType}`);
+ return this._renderUnknown(heading.valueType, value);
}
}
}
@@ -2201,11 +2276,11 @@ class ReportUIFeatures {
this._document = this._dom.document();
/** @type {ParentNode} */
this._templateContext = this._dom.document();
+ /** @type {DropDown} */
+ this._dropDown = new DropDown(this._dom);
/** @type {boolean} */
this._copyAttempt = false;
/** @type {HTMLElement} */
- this.toolsButton; // eslint-disable-line no-unused-expressions
- /** @type {HTMLElement} */
this.topbarEl; // eslint-disable-line no-unused-expressions
/** @type {HTMLElement} */
this.scoreScaleEl; // eslint-disable-line no-unused-expressions
@@ -2216,11 +2291,8 @@ class ReportUIFeatures {
this.onMediaQueryChange = this.onMediaQueryChange.bind(this);
this.onCopy = this.onCopy.bind(this);
- this.onToolsButtonClick = this.onToolsButtonClick.bind(this);
- this.onToolAction = this.onToolAction.bind(this);
- this.onKeyDown = this.onKeyDown.bind(this);
+ this.onDropDownMenuClick = this.onDropDownMenuClick.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
- this.onChevronClick = this.onChevronClick.bind(this);
this.collapseAllDetails = this.collapseAllDetails.bind(this);
this.expandAllDetails = this.expandAllDetails.bind(this);
this._toggleDarkTheme = this._toggleDarkTheme.bind(this);
@@ -2236,7 +2308,7 @@ class ReportUIFeatures {
this.json = report;
this._setupMediaQueryListeners();
- this._setupToolsButton();
+ this._dropDown.setup(this.onDropDownMenuClick);
this._setupThirdPartyFilter();
this._setUpCollapseDetailsAfterPrinting();
this._resetUIState();
@@ -2360,14 +2432,6 @@ class ReportUIFeatures {
root.classList.toggle('lh-narrow', mql.matches);
}
- _setupToolsButton() {
- this.toolsButton = this._dom.find('.lh-tools__button', this._document);
- this.toolsButton.addEventListener('click', this.onToolsButtonClick);
-
- const dropdown = this._dom.find('.lh-tools__dropdown', this._document);
- dropdown.addEventListener('click', this.onToolAction);
- }
-
_setupThirdPartyFilter() {
// Some audits should not display the third party filter option.
const thirdPartyFilterAuditExclusions = [
@@ -2526,37 +2590,13 @@ class ReportUIFeatures {
}
}
- onChevronClick() {
- const toggle = this._dom.find('.lh-config__settings-toggle', this._document);
-
- if (toggle.hasAttribute('open')) {
- toggle.removeAttribute('open');
- } else {
- toggle.setAttribute('open', 'true');
- }
- }
-
- closeToolsDropdown() {
- this.toolsButton.classList.remove('active');
- }
-
- /**
- * Click handler for tools button.
- * @param {Event} e
- */
- onToolsButtonClick(e) {
- e.preventDefault();
- this.toolsButton.classList.toggle('active');
- this._document.addEventListener('keydown', this.onKeyDown);
- }
-
/**
* Resets the state of page before capturing the page for export.
* When the user opens the exported HTML page, certain UI elements should
* be in their closed state (not opened) and the templates should be unstamped.
*/
_resetUIState() {
- this.closeToolsDropdown();
+ this._dropDown.close();
this._dom.resetTemplates();
}
@@ -2564,7 +2604,7 @@ class ReportUIFeatures {
* Handler for tool button.
* @param {Event} e
*/
- onToolAction(e) {
+ onDropDownMenuClick(e) {
e.preventDefault();
const el = /** @type {?Element} */ (e.target);
@@ -2579,12 +2619,10 @@ class ReportUIFeatures {
break;
case 'print-summary':
this.collapseAllDetails();
- this.closeToolsDropdown();
this._print();
break;
case 'print-expanded':
this.expandAllDetails();
- this.closeToolsDropdown();
this._print();
break;
case 'save-json': {
@@ -2618,8 +2656,7 @@ class ReportUIFeatures {
}
}
- this.closeToolsDropdown();
- this._document.removeEventListener('keydown', this.onKeyDown);
+ this._dropDown.close();
}
_print() {
@@ -2627,23 +2664,13 @@ class ReportUIFeatures {
}
/**
- * Keydown handler for the document.
- * @param {KeyboardEvent} e
- */
- onKeyDown(e) {
- if (e.keyCode === 27) { // ESC
- this.closeToolsDropdown();
- }
- }
-
- /**
* Keyup handler for the document.
* @param {KeyboardEvent} e
*/
onKeyUp(e) {
// Ctrl+P - Expands audit details when user prints via keyboard shortcut.
if ((e.ctrlKey || e.metaKey) && e.keyCode === 80) {
- this.closeToolsDropdown();
+ this._dropDown.close();
}
}
@@ -2807,6 +2834,196 @@ class ReportUIFeatures {
}
}
+class DropDown {
+ /**
+ * @param {DOM} dom
+ */
+ constructor(dom) {
+ /** @type {DOM} */
+ this._dom = dom;
+ /** @type {HTMLElement} */
+ this._toggleEl; // eslint-disable-line no-unused-expressions
+ /** @type {HTMLElement} */
+ this._menuEl; // eslint-disable-line no-unused-expressions
+
+ this.onDocumentKeyDown = this.onDocumentKeyDown.bind(this);
+ this.onToggleClick = this.onToggleClick.bind(this);
+ this.onToggleKeydown = this.onToggleKeydown.bind(this);
+ this.onMenuKeydown = this.onMenuKeydown.bind(this);
+
+ this._getNextMenuItem = this._getNextMenuItem.bind(this);
+ this._getNextSelectableNode = this._getNextSelectableNode.bind(this);
+ this._getPreviousMenuItem = this._getPreviousMenuItem.bind(this);
+ }
+
+ /**
+ * @param {function(MouseEvent): any} menuClickHandler
+ */
+ setup(menuClickHandler) {
+ this._toggleEl = this._dom.find('.lh-tools__button', this._dom.document());
+ this._toggleEl.addEventListener('click', this.onToggleClick);
+ this._toggleEl.addEventListener('keydown', this.onToggleKeydown);
+
+ this._menuEl = this._dom.find('.lh-tools__dropdown', this._dom.document());
+ this._menuEl.addEventListener('keydown', this.onMenuKeydown);
+ this._menuEl.addEventListener('click', menuClickHandler);
+ }
+
+ close() {
+ this._toggleEl.classList.remove('active');
+ this._toggleEl.setAttribute('aria-expanded', 'false');
+ if (this._menuEl.contains(this._dom.document().activeElement)) {
+ // Refocus on the tools button if the drop down last had focus
+ this._toggleEl.focus();
+ }
+ this._dom.document().removeEventListener('keydown', this.onDocumentKeyDown);
+ }
+
+ /**
+ * @param {HTMLElement} firstFocusElement
+ */
+ open(firstFocusElement) {
+ if (this._toggleEl.classList.contains('active')) {
+ // If the drop down is already open focus on the element
+ firstFocusElement.focus();
+ } else {
+ // Wait for drop down transition to complete so options are focusable.
+ this._menuEl.addEventListener('transitionend', () => {
+ firstFocusElement.focus();
+ }, {once: true});
+ }
+
+ this._toggleEl.classList.add('active');
+ this._toggleEl.setAttribute('aria-expanded', 'true');
+ this._dom.document().addEventListener('keydown', this.onDocumentKeyDown);
+ }
+
+ /**
+ * Click handler for tools button.
+ * @param {Event} e
+ */
+ onToggleClick(e) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+
+ if (this._toggleEl.classList.contains('active')) {
+ this.close();
+ } else {
+ this.open(this._getNextMenuItem());
+ }
+ }
+
+ /**
+ * Handler for tool button.
+ * @param {KeyboardEvent} e
+ */
+ onToggleKeydown(e) {
+ switch (e.code) {
+ case 'ArrowUp':
+ e.preventDefault();
+ this.open(this._getPreviousMenuItem());
+ break;
+ case 'ArrowDown':
+ case 'Enter':
+ case ' ':
+ e.preventDefault();
+ this.open(this._getNextMenuItem());
+ break;
+ default:
+ // no op
+ }
+ }
+
+ /**
+ * Handler for tool DropDown.
+ * @param {KeyboardEvent} e
+ */
+ onMenuKeydown(e) {
+ const el = /** @type {?HTMLElement} */ (e.target);
+
+ switch (e.code) {
+ case 'ArrowUp':
+ e.preventDefault();
+ this._getPreviousMenuItem(el).focus();
+ break;
+ case 'ArrowDown':
+ e.preventDefault();
+ this._getNextMenuItem(el).focus();
+ break;
+ case 'Home':
+ e.preventDefault();
+ this._getNextMenuItem().focus();
+ break;
+ case 'End':
+ e.preventDefault();
+ this._getPreviousMenuItem().focus();
+ break;
+ default:
+ // no op
+ }
+ }
+
+ /**
+ * Keydown handler for the document.
+ * @param {KeyboardEvent} e
+ */
+ onDocumentKeyDown(e) {
+ if (e.keyCode === 27) { // ESC
+ this.close();
+ }
+ }
+
+ /**
+ * @param {Array<Node>} allNodes
+ * @param {?Node=} startNode
+ * @returns {Node}
+ */
+ _getNextSelectableNode(allNodes, startNode) {
+ const nodes = allNodes.filter((node) => {
+ if (!(node instanceof HTMLElement)) {
+ return false;
+ }
+
+ // 'Save as Gist' option may be disabled.
+ if (node.hasAttribute('disabled')) {
+ return false;
+ }
+
+ // 'Save as Gist' option may have display none.
+ if (window.getComputedStyle(node).display === 'none') {
+ return false;
+ }
+
+ return true;
+ });
+
+ let nextIndex = startNode ? (nodes.indexOf(startNode) + 1) : 0;
+ if (nextIndex >= nodes.length) {
+ nextIndex = 0;
+ }
+
+ return nodes[nextIndex];
+ }
+
+ /**
+ * @param {?Element=} startEl
+ * @returns {HTMLElement}
+ */
+ _getNextMenuItem(startEl) {
+ const nodes = Array.from(this._menuEl.childNodes);
+ return /** @type {HTMLElement} */ (this._getNextSelectableNode(nodes, startEl));
+ }
+
+ /**
+ * @param {?Element=} startEl
+ * @returns {HTMLElement}
+ */
+ _getPreviousMenuItem(startEl) {
+ const nodes = Array.from(this._menuEl.childNodes).reverse();
+ return /** @type {HTMLElement} */ (this._getNextSelectableNode(nodes, startEl));
+ }
+}
+
if (typeof module !== 'undefined' && module.exports) {
module.exports = ReportUIFeatures;
} else {
@@ -3410,8 +3627,8 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
// Metric descriptions toggle.
const toggleTmpl = this.dom.cloneTemplate('#tmpl-lh-metrics-toggle', this.templateContext);
- const toggleEl = this.dom.find('.lh-metrics-toggle', toggleTmpl);
- metricAuditsEl.append(...toggleEl.childNodes);
+ const _toggleEl = this.dom.find('.lh-metrics-toggle', toggleTmpl);
+ metricAuditsEl.append(..._toggleEl.childNodes);
const metricAudits = category.auditRefs.filter(audit => audit.group === 'metrics');
const keyMetrics = metricAudits.filter(a => a.weight >= 3);
@@ -3810,6 +4027,7 @@ class ReportRenderer {
const el = this._dom.cloneTemplate('#tmpl-lh-topbar', this._templateContext);
const metadataUrl = /** @type {HTMLAnchorElement} */ (this._dom.find('.lh-topbar__url', el));
metadataUrl.href = metadataUrl.textContent = report.finalUrl;
+ metadataUrl.title = report.finalUrl;
return el;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/template.html b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/template.html
index 491925c6bb5..e5950a40bd2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/template.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/template.html
@@ -19,7 +19,7 @@ limitations under the License.
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
- <link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAADjklEQVR4AWI08P/HQEvAQrxSQKvlECfLFYXx75xCY2qmh89GbNvOMjb3v9jOOlxnFWxj206ebQ3b7q6q+z1rNagu8/zvPSZACAABpeUAA0miMgU7SA7JjCraFGwZwECOwvL75dWjsKgWBKtx0jvWo+vkBAFbACCkByMP6nMn48+AVgXB2fzSCwsv22/lMGlUhmJ0AE7BH8dyUUDbUEgN6RzJRSeaPxhdRYR0Inel+7Hd5lBiFpkMAxACc0394//9C4voFHDiAAGLpuOXebdfdHfctgwJKaZRLRKy6ItrSis6RBnVBgGtbHyKTEmJHQoEXoBCE5BCrDeA2ogMUIGDAKEBDEhUqwgMqBYDjW4DQzmuffVdqff42/ZQYYqVcMXGZsMPyCsH3lyJSetxvEaxAQXdjR1HjfwCdIS7lo2DZke26Qe+MXO12OWkGT0O6oE7vMGkMnkYw4aN1KQgMKExhXqswfiov4+a7MQ11XPnbr/5qpKlgACAAQj94Lu271bN9DUecQasIZlNzG72llRAAKJiAi+/BSHrSFjRvQhg3DEKEqJh08tsmLTx597+f6enr4cc2Zpk57pihfX24dW7RHcOLLUbJYhJSl0ErQCI9BVXH/XrO97QasuvQQSiECa0BrQCIIJp6X9T/r8QG6L71WYSqCoIIGo2BZDUBnS/D9EA9Nun1iYvbM0MFExIDQRoKFatc1Z6zrm5uWeObJotq0BGV9FuQBWq5a4Fw3PPz848rZHstZSuA5FWAFSMP2nOppOOGpl6qh9PCSg0IFyHKjSQyDNQHTru2t75NOEe0fsf246oAmFkI6vCdnWvbQFQFCKx8vCswV8TrDLiDLgH4Nr7RAtNsrC9d8sfk7b8ls4igdNy8CQKAISlsB0FjZfd3Lfp155tf8fKI4BxZZIj/oTdVEAIAcJFOCmzauHG71I7/rdreUAgAqpDP05fDARCAQQARwEIBQSVxq0FyaLvZZtevpHa8WHw8cft6cpxlq8eAJtIhnSbWDf951yx3y13OqUuu5qyGgkxCgGFh9cDihDGbTa6BqvT1lWmrav3bmt2ZMJ4mU6TGgIC4DBzcv/JqAau1WhzSt3x9Ixk/4Jk/8J4ZrrViFMA4W6A7+WK8xcVjvyrOmVD0FbAXokcT48r+xVqLKvuJYbmpNadnlp3mpufJHOe/GXktM+r09bT8kEdq9BRYAbGSgzP7ll82U71Mc+ZFooXgwAAAABJRU5ErkJggg==">
+ <link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEhklEQVR4AWJxL/BhIAesev1U5tcflpncgNrKIsqNIwzC9feMpDUzs70kOczMzMzJJcxwCTMzncPMnOwtzBwzMzPb0vRfeZPp0VhPS5I39V5fdiXV1/VD+9QC7OVn9BsyH1XIoEI1PfmJvLFowVV564+34DFUHudbmfDh4kVXh//7XwE+WjS/YfXZe3yr4j2rqj1AIhSB7hZ8ZtPZu/zw8cK523U4wE1/rvPfWrz4zs0m9ZdC9yUJAlASdBAgocRegfF/f3/h/PuaFsxMdwjAR0vm1+06eMMfIrhLqTWqdH4EumU2SPfMhigJAlRQbZrgrRsl9U+Y2DYDFCz3ILC9kiAiqSrMwbWT0nceEnR+9Kggc2zjOJCASDENkg0a5HfZZgDP81CM3CrQs2Z1+o7DJ6ePr8sK0AOCHv5Jjdt3evyYSaZ351VIStIxPRAUtrBYbxC6w+BZ0ivVSBKkIhJhemSyZpfB00EiPO2VjzYkxhcqXQqCWCShGplvi3y0QxqbuBurMjyJeWnkHZuAEgIQGsUBqwrfjZ+IlBgKyRJzVVYF8O6qFWdh86YzQzMrZigYmxAyfvHgLZQ/LC1CbeniW2Hkqr/PH16SgvGuf2/uzNMBwJA/njxizGPtSyAf7EziJCMGRDRdhoAC4PL1A/SrKQMAAQkEfpJAcRQdrBJ7gNwjSpJsdwK+CANBkqa1LgQB4IicV9nYUct7gaxuDJUErQIiEAiMxLVOFlKzIktPpT0ggpdpC/8YAHnxbgkUY4tAAFSR7AAXNyAAWHJrA/kHGjzg5nleuwFO7Nd/IoDw4Pm58+4jNLmYG0wRA5bErc2Mr3Y+dXTDW1VvwqbJkzMCHQ4S1GTCBOIgUHJrGdEwqzR+jAp/o2qAZelUDoQnruEEdDclJI6576AlNVfc+22XN/+Y1vnJD0Yind6UpEEvn/Hqq15EYjCW7jZCJEpnNvDgkyelDjs106kuux2AAXCSobULOWP8mLhYlpoDMK4qAFXJGk+grtH8YXVz5KJblqaG1+VUdTc0I290bmUQAriGITRbdQnom0aoFj8kx1+wMD2ifncAXUQE4SkDqN1hE0jEophs1SUwZAOhUAiMCLwRtamtTZtbbmZErSAUHbSysaoEmnrsakiMiUAURi283gN6wans9oX8rOCrj7/JP35DFD+iQ7Au/K2KE1jzx6ujjUnXFH9KjEq6ZlhsTBICrNLJf47Pv/pkHzvup1w4dmUbEei0+bcXRqJuh5kVARQ8byyYxOwNGr7A87xh1tp8sGT+uMInrwi++Xj7TQz2d27NvwEkrOflAFQGIDA5khASBCGdO2/Z/MnLPwYfv5TFhjW7QhVKAB6afwe2LpFlFsCnlQEosgQgDsdOG1/LKeNqJS4JCSPJ/i+TakwEARor7gER1Iva5JmPOJK0RUqmoPnnlzFCtmIAhAAQEIQRgDaiYPIauNXcnDlRIrWNFY3hm7PG9YRqr7IV7HrCgAC17befjEvRq2nGhAHtBqDpOuI/I1diUUAMYIxEdyejBJqLnNoszGZtfiX/CztGv2mq+sdaAAAAAElFTkSuQmCC">
<title>Lighthouse Report</title>
<style>/*%%LIGHTHOUSE_CSS%%*/</style>
</head>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/templates.html b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/templates.html
index a418bf9f1fb..57462c176ad 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/templates.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits/lighthouse/templates.html
@@ -245,6 +245,7 @@ limitations under the License.
width: var(--topbar-logo-size);
height: var(--topbar-logo-size);
user-select: none;
+ flex: none;
}
.lh-topbar__logo .shape {
fill: var(--report-text-color);
@@ -254,6 +255,9 @@ limitations under the License.
margin: var(--topbar-padding);
text-decoration: none;
color: var(--report-text-color);
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
}
.lh-tools {
@@ -355,33 +359,56 @@ limitations under the License.
</style>
<div class="lh-topbar">
- <!-- Flat Lighthouse logo. -->
- <svg class="lh-topbar__logo" viewBox="0 0 192 192">
+ <!-- Lighthouse logo. -->
+ <svg class="lh-topbar__logo" viewBox="0 0 24 24">
+ <defs>
+ <linearGradient x1="57.456%" y1="13.086%" x2="18.259%" y2="72.322%" id="lh-topbar__logo--a">
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
+ </linearGradient>
+ <linearGradient x1="100%" y1="50%" x2="0%" y2="50%" id="lh-topbar__logo--b">
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
+ </linearGradient>
+ <linearGradient x1="58.764%" y1="65.756%" x2="36.939%" y2="50.14%" id="lh-topbar__logo--c">
+ <stop stop-color="#262626" stop-opacity=".1" offset="0%"/>
+ <stop stop-color="#262626" stop-opacity="0" offset="100%"/>
+ </linearGradient>
+ <linearGradient x1="41.635%" y1="20.358%" x2="72.863%" y2="85.424%" id="lh-topbar__logo--d">
+ <stop stop-color="#FFF" stop-opacity=".1" offset="0%"/>
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%"/>
+ </linearGradient>
+ </defs>
<g fill="none" fill-rule="evenodd">
- <path d="M0 0h192v192H0z"/>
- <path class="shape" d="M67.705 179.352l2.603-20.82 49.335-16.39 4.652 37.21A87.893 87.893 0 0 1 96 184a87.893 87.893 0 0 1-28.295-4.648zM52.44 172.48C25.894 157.328 8 128.754 8 96 8 47.399 47.399 8 96 8s88 39.399 88 88c0 32.754-17.894 61.328-44.44 76.48L130 96h6V80h-8V48L96 28 64 48v32h-8v16h6l-9.56 76.48zM113.875 96l2.882 23.05-43.318 14.433L78.125 96h35.75zM80 80V56.868l16-10 16 10V80H80z"/>
+ <path d="M12 3l4.125 2.625v3.75H18v2.25h-1.688l1.5 9.375H6.188l1.5-9.375H6v-2.25h1.875V5.648L12 3zm2.201 9.938L9.54 14.633 9 18.028l5.625-2.062-.424-3.028zM12.005 5.67l-1.88 1.207v2.498h3.75V6.86l-1.87-1.19z" fill="#F44B21"/>
+ <path fill="#FFF" d="M14.201 12.938L9.54 14.633 9 18.028l5.625-2.062z"/>
+ <path d="M6 18c-2.042 0-3.95-.01-5.813 0l1.5-9.375h4.326L6 18z" fill="url(#lh-topbar__logo--a)" fill-rule="nonzero" transform="translate(6 3)"/>
+ <path fill="#FFF176" fill-rule="nonzero" d="M13.875 9.375v-2.56l-1.87-1.19-1.88 1.207v2.543z"/>
+ <path fill="url(#lh-topbar__logo--b)" fill-rule="nonzero" d="M0 6.375h6v2.25H0z" transform="translate(6 3)"/>
+ <path fill="url(#lh-topbar__logo--c)" fill-rule="nonzero" d="M6 6.375H1.875v-3.75L6 0z" transform="translate(6 3)"/>
+ <path fill="url(#lh-topbar__logo--d)" fill-rule="nonzero" d="M6 0l4.125 2.625v3.75H12v2.25h-1.688l1.5 9.375H.188l1.5-9.375H0v-2.25h1.875V2.648z" transform="translate(6 3)"/>
</g>
</svg>
<a href="" class="lh-topbar__url" target="_blank" rel="noopener"></a>
<div class="lh-tools">
- <button class="report-icon report-icon--share lh-tools__button" title="Tools menu" aria-label="Toggle report tools menu">
+ <button id="lh-tools-button" class="report-icon report-icon--share lh-tools__button" title="Tools menu" aria-label="Toggle report tools menu" aria-haspopup="menu" aria-expanded="false" aria-controls="lh-tools-dropdown">
<svg width="100%" height="100%" viewBox="0 0 24 24">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</button>
- <div class="lh-tools__dropdown">
+ <div id="lh-tools-dropdown" role="menu" class="lh-tools__dropdown" aria-labelledby="lh-tools-button">
<!-- TODO(i18n): localize tools dropdown -->
- <a href="#" class="report-icon report-icon--print" data-action="print-summary">Print Summary</a>
- <a href="#" class="report-icon report-icon--print" data-action="print-expanded">Print Expanded</a>
- <a href="#" class="report-icon report-icon--copy" data-action="copy">Copy JSON</a>
- <a href="#" class="report-icon report-icon--download" data-action="save-html">Save as HTML</a>
- <a href="#" class="report-icon report-icon--download" data-action="save-json">Save as JSON</a>
- <a href="#" class="report-icon report-icon--open lh-tools--viewer" data-action="open-viewer">Open in Viewer</a>
- <a href="#" class="report-icon report-icon--open lh-tools--gist" data-action="save-gist">Save as Gist</a>
- <a href="#" class="report-icon report-icon--dark" data-action="toggle-dark">Toggle Dark Theme</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--print" data-action="print-summary">Print Summary</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--print" data-action="print-expanded">Print Expanded</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--copy" data-action="copy">Copy JSON</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--download" data-action="save-html">Save as HTML</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--download" data-action="save-json">Save as JSON</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--open lh-tools--viewer" data-action="open-viewer">Open in Viewer</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--open lh-tools--gist" data-action="save-gist">Save as Gist</a>
+ <a role="menuitem" tabindex="-1" href="#" class="report-icon report-icon--dark" data-action="toggle-dark">Toggle Dark Theme</a>
</div>
</div>
</div>
@@ -390,29 +417,6 @@ limitations under the License.
<!-- Lighthouse header -->
<template id="tmpl-lh-heading">
<style>
-/*
- TODO: Enable animating the clouds
- .lh-lighthouse__clouds {
- animation: panacross 30s linear infinite;
- animation-play-state: paused;
- }
- @keyframes panacross {
- 0% { transform: translateX(0px); }
- 77% { transform: translateX(-680px); }
- 77.0001% { transform: translateX(195px); }
- 100% { transform: translateX(0px); }
- } */
-
- .score100 .lh-header-bg {
- background-color: hsl(234, 64%, 19%);
- }
- .score100 .lh-metadata, .score100 .lh-toolbar__metadata, .score100 .lh-product-info {
- color: #fff;
- }
- .score100 .lh-config {
- color: #eee;
- }
-
/* CSS Fireworks. Originally by Eddie Lin
https://codepen.io/paulirish/pen/yEVMbP
*/
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_test_runner/AuditsTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/audits_test_runner/AuditsTestRunner.js
index 78af5c4598f..d595cf6903e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits_test_runner/AuditsTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_test_runner/AuditsTestRunner.js
@@ -81,8 +81,9 @@ AuditsTestRunner.forcePageAuditabilityCheck = function() {
* @return {string}
*/
AuditsTestRunner._checkboxStateLabel = function(checkboxContainer) {
- if (!checkboxContainer)
+ if (!checkboxContainer) {
return 'missing';
+ }
const label = checkboxContainer.textElement.textContent;
const checkedLabel = checkboxContainer.checkboxElement.checked ? 'x' : ' ';
@@ -94,8 +95,9 @@ AuditsTestRunner._checkboxStateLabel = function(checkboxContainer) {
* @return {string}
*/
AuditsTestRunner._buttonStateLabel = function(button) {
- if (!button)
+ if (!button) {
return 'missing';
+ }
const enabledLabel = button.disabled ? 'disabled' : 'enabled';
const hiddenLabel = window.getComputedStyle(button).getPropertyValue('visibility');
@@ -112,8 +114,9 @@ AuditsTestRunner.dumpStartAuditState = function() {
});
const helpText = containerElement.querySelector('.audits-help-text');
- if (!helpText.classList.contains('hidden'))
+ if (!helpText.classList.contains('hidden')) {
TestRunner.addResult(`Help text: ${helpText.textContent}`);
+ }
TestRunner.addResult(AuditsTestRunner._buttonStateLabel(AuditsTestRunner.getRunButton()));
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker.js b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker.js
index 059a2e09e2f..f6813c6f108 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker.js
@@ -1,7 +1,9 @@
// 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.
+self.importScripts('platform/utilities.js');
// Release build has Runtime.js bundled.
-if (!self.Runtime)
+if (!self.Root || !self.Root.Runtime) {
self.importScripts('Runtime.js');
-Runtime.startWorker('audits_worker');
+}
+Root.Runtime.startWorker('audits_worker');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/AuditsService.js b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/AuditsService.js
index 45a27ea6c0f..a66191cba96 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/AuditsService.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/AuditsService.js
@@ -5,6 +5,7 @@
/**
* @interface
*/
+// eslint-disable-next-line
const LighthousePort = class {
/**
* @param {!string} eventName, 'message', 'close'
@@ -41,7 +42,7 @@ var AuditsService = class { // eslint-disable-line
* @return {!Promise<!ReportRenderer.RunnerResult>}
*/
start(params) {
- if (Runtime.queryParam('isUnderTest')) {
+ if (Root.Runtime.queryParam('isUnderTest')) {
this._disableLoggingForTest();
params.flags.maxWaitForLoad = 2 * 1000;
}
@@ -110,10 +111,12 @@ var AuditsService = class { // eslint-disable-line
* @param {function(string|undefined)} cb
*/
on(eventName, cb) {
- if (eventName === 'message')
+ if (eventName === 'message') {
this._onMessage = cb;
- if (eventName === 'close')
+ }
+ if (eventName === 'close') {
this._onClose = cb;
+ }
}
_disableLoggingForTest() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/README.chromium b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/README.chromium
index 1b58f4c94f8..accd67d7aad 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/README.chromium
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/README.chromium
@@ -6,3 +6,7 @@ Security Critical: no
This directory contains Chromium's version of lighthouse with tests, demo and sources removed.
+The locales/ folder is not bundled with audits_worker_module.js. Instead, the files are hosted separately
+on the remote server. The appropriate locale file will be fetched and its content registered with lighthouse
+before running audits.
+More info on the lighthouse localization process: https://docs.google.com/document/d/1jnt3BqKB-4q3AE94UWFA0Gqspx8Sd_jivlB7gQMlmfk/edit \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js
index 954aadb1bfb..a0a63a25096 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/lighthouse-dt-bundle.js
@@ -1,4 +1,4 @@
-// lighthouse, browserified. 5.2.0 (651028676d93ff0089970a8d37f8b4b4904d18de)
+// lighthouse, browserified. 5.5.0 (33af3dbb7c10890c9d9e67e16af4968b7c49206c)
require=function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o;}return r;}()({"../audits/accessibility/accesskeys":[function(require,module,exports){
(function(__filename){
@@ -24,7 +24,7 @@ failureTitle:'`[accesskey]` values are not unique',
description:'Access keys let users quickly focus a part of the page. For proper '+
'navigation, each access key must be unique. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/accesskeys?application=lighthouse).'};
+'[Learn more](https://web.dev/accesskeys/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -48,7 +48,7 @@ module.exports=Accesskeys;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/accesskeys.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-allowed-attr":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-allowed-attr":[function(require,module,exports){
(function(__filename){
@@ -73,7 +73,7 @@ failureTitle:'`[aria-*]` attributes do not match their roles',
description:'Each ARIA `role` supports a specific subset of `aria-*` attributes. '+
'Mismatching these invalidates the `aria-*` attributes. [Learn '+
-'more](https://dequeuniversity.com/rules/axe/3.1/aria-allowed-attr?application=lighthouse).'};
+'more](https://web.dev/aria-allowed-attr/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -97,7 +97,7 @@ module.exports=ARIAAllowedAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-allowed-attr.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-required-attr":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-required-attr":[function(require,module,exports){
(function(__filename){
@@ -121,7 +121,7 @@ title:'`[role]`s have all required `[aria-*]` attributes',
failureTitle:'`[role]`s do not have all required `[aria-*]` attributes',
description:'Some ARIA roles have required attributes that describe the state '+
-'of the element to screen readers. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-attr?application=lighthouse).'};
+'of the element to screen readers. [Learn more](https://web.dev/aria-required-attr/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -145,7 +145,7 @@ module.exports=ARIARequiredAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-required-attr.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-required-children":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-required-children":[function(require,module,exports){
(function(__filename){
@@ -165,14 +165,15 @@ const i18n=require('../../lib/i18n/i18n.js');
const UIStrings={
-title:'Elements with `[role]` that require specific children `[role]`s, are present',
+title:'Elements with an ARIA `[role]` that require children to contain a specific '+
+'`[role]` have all required children.',
-failureTitle:'Elements with `[role]` that require specific children `[role]`s, '+
-'are missing.',
+failureTitle:'Elements with an ARIA `[role]` that require children to contain a specific '+
+'`[role]` are missing some or all of those required children.',
description:'Some ARIA parent roles must contain specific child roles to perform '+
'their intended accessibility functions. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-children?application=lighthouse).'};
+'[Learn more](https://web.dev/aria-required-children/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -196,7 +197,7 @@ module.exports=AriaRequiredChildren;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-required-children.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-required-parent":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-required-parent":[function(require,module,exports){
(function(__filename){
@@ -222,7 +223,7 @@ failureTitle:'`[role]`s are not contained by their required parent element',
description:'Some ARIA child roles must be contained by specific parent roles to '+
'properly perform their intended accessibility functions. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-parent?application=lighthouse).'};
+'[Learn more](https://web.dev/aria-required-parent/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -246,7 +247,7 @@ module.exports=AriaRequiredParent;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-required-parent.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-roles":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-roles":[function(require,module,exports){
(function(__filename){
@@ -271,7 +272,7 @@ failureTitle:'`[role]` values are not valid',
description:'ARIA roles must have valid values in order to perform their '+
'intended accessibility functions. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-roles?application=lighthouse).'};
+'[Learn more](https://web.dev/aria-roles/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -295,7 +296,7 @@ module.exports=AriaRoles;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-roles.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-valid-attr-value":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-valid-attr-value":[function(require,module,exports){
(function(__filename){
@@ -320,7 +321,7 @@ failureTitle:'`[aria-*]` attributes do not have valid values',
description:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
'attributes with invalid values. [Learn '+
-'more](https://dequeuniversity.com/rules/axe/3.1/aria-valid-attr-value?application=lighthouse).'};
+'more](https://web.dev/aria-valid-attr-value/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -344,7 +345,7 @@ module.exports=ARIAValidAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-valid-attr-value.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/aria-valid-attr":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/aria-valid-attr":[function(require,module,exports){
(function(__filename){
@@ -369,7 +370,7 @@ failureTitle:'`[aria-*]` attributes are not valid or misspelled',
description:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
'attributes with invalid names. [Learn '+
-'more](https://dequeuniversity.com/rules/axe/3.1/aria-valid-attr?application=lighthouse).'};
+'more](https://web.dev/aria-valid-attr/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -393,7 +394,7 @@ module.exports=ARIAValidAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/aria-valid-attr.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/audio-caption":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/audio-caption":[function(require,module,exports){
(function(__filename){
@@ -420,7 +421,7 @@ failureTitle:'`<audio>` elements are missing a `<track>` element with '+
description:'Captions make audio elements usable for deaf or hearing-impaired users, '+
'providing critical information such as who is talking, what they\'re saying, '+
'and other non-speech information. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/audio-caption?application=lighthouse).'};
+'[Learn more](https://web.dev/audio-caption/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -444,7 +445,7 @@ module.exports=AudioCaption;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/audio-caption.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/button-name":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/button-name":[function(require,module,exports){
(function(__filename){
@@ -469,7 +470,7 @@ failureTitle:'Buttons do not have an accessible name',
description:'When a button doesn\'t have an accessible name, screen readers announce it '+
'as "button", making it unusable for users who rely on screen readers. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/button-name?application=lighthouse).'};
+'[Learn more](https://web.dev/button-name/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -493,7 +494,7 @@ module.exports=ButtonName;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/button-name.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/bypass":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/bypass":[function(require,module,exports){
(function(__filename){
@@ -519,7 +520,7 @@ failureTitle:'The page does not contain a heading, skip link, or landmark region
description:'Adding ways to bypass repetitive content lets keyboard users navigate the '+
'page more efficiently. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/bypass?application=lighthouse).'};
+'[Learn more](https://web.dev/bypass/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -543,7 +544,7 @@ module.exports=Bypass;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/bypass.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/color-contrast":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/color-contrast":[function(require,module,exports){
(function(__filename){
@@ -569,7 +570,7 @@ failureTitle:'Background and foreground colors do not have a '+
'sufficient contrast ratio.',
description:'Low-contrast text is difficult or impossible for many users to read. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/color-contrast?application=lighthouse).'};
+'[Learn more](https://web.dev/color-contrast/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -593,7 +594,7 @@ module.exports=ColorContrast;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/color-contrast.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/definition-list":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/definition-list":[function(require,module,exports){
(function(__filename){
@@ -620,7 +621,7 @@ failureTitle:'`<dl>`\'s do not contain only properly-ordered `<dt>` and `<dd>` '
description:'When definition lists are not properly marked up, screen readers may produce '+
'confusing or inaccurate output. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/definition-list?application=lighthouse).'};
+'[Learn more](https://web.dev/definition-list/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -644,7 +645,7 @@ module.exports=DefinitionList;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/definition-list.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/dlitem":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/dlitem":[function(require,module,exports){
(function(__filename){
@@ -669,7 +670,7 @@ failureTitle:'Definition list items are not wrapped in `<dl>` elements',
description:'Definition list items (`<dt>` and `<dd>`) must be wrapped in a '+
'parent `<dl>` element to ensure that screen readers can properly announce them. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/dlitem?application=lighthouse).'};
+'[Learn more](https://web.dev/dlitem/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -693,7 +694,7 @@ module.exports=DLItem;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/dlitem.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/document-title":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/document-title":[function(require,module,exports){
(function(__filename){
@@ -718,7 +719,7 @@ failureTitle:'Document doesn\'t have a `<title>` element',
description:'The title gives screen reader users an overview of the page, and search '+
'engine users rely on it heavily to determine if a page is relevant to their search. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/title).'};
+'[Learn more](https://web.dev/document-title/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -742,7 +743,7 @@ module.exports=DocumentTitle;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/document-title.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/duplicate-id":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/duplicate-id":[function(require,module,exports){
(function(__filename){
@@ -767,7 +768,7 @@ failureTitle:'`[id]` attributes on the page are not unique',
description:'The value of an id attribute must be unique to prevent '+
'other instances from being overlooked by assistive technologies. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/duplicate-id?application=lighthouse).'};
+'[Learn more](https://web.dev/duplicate-id/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -791,7 +792,7 @@ module.exports=DuplicateId;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/duplicate-id.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/frame-title":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/frame-title":[function(require,module,exports){
(function(__filename){
@@ -815,7 +816,7 @@ title:'`<frame>` or `<iframe>` elements have a title',
failureTitle:'`<frame>` or `<iframe>` elements do not have a title',
description:'Screen reader users rely on frame titles to describe the contents of frames. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/frame-title?application=lighthouse).'};
+'[Learn more](https://web.dev/frame-title/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -839,7 +840,7 @@ module.exports=FrameTitle;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/frame-title.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/html-has-lang":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/html-has-lang":[function(require,module,exports){
(function(__filename){
@@ -866,7 +867,7 @@ description:'If a page doesn\'t specify a lang attribute, a screen reader assume
'that the page is in the default language that the user chose when setting up the '+
'screen reader. If the page isn\'t actually in the default language, then the screen '+
'reader might not announce the page\'s text correctly. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/html-has-lang?application=lighthouse).'};
+'[Learn more](https://web.dev/html-has-lang/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -890,7 +891,7 @@ module.exports=HTMLHasLang;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/html-has-lang.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/html-lang-valid":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/html-lang-valid":[function(require,module,exports){
(function(__filename){
@@ -916,7 +917,7 @@ failureTitle:'`<html>` element does not have a valid value for '+
description:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
'helps screen readers announce text properly. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/valid-lang?application=lighthouse).'};
+'[Learn more](https://web.dev/html-lang-valid/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -940,7 +941,7 @@ module.exports=HTMLLangValid;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/html-lang-valid.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/image-alt":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/image-alt":[function(require,module,exports){
(function(__filename){
@@ -965,7 +966,7 @@ failureTitle:'Image elements do not have `[alt]` attributes',
description:'Informative elements should aim for short, descriptive alternate text. '+
'Decorative elements can be ignored with an empty alt attribute. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/image-alt?application=lighthouse).'};
+'[Learn more](https://web.dev/image-alt/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -989,7 +990,7 @@ module.exports=ImageAlt;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/image-alt.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/input-image-alt":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/input-image-alt":[function(require,module,exports){
(function(__filename){
@@ -1014,7 +1015,7 @@ failureTitle:'`<input type="image">` elements do not have `[alt]` text',
description:'When an image is being used as an `<input>` button, providing alternative '+
'text can help screen reader users understand the purpose of the button. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/input-image-alt?application=lighthouse).'};
+'[Learn more](https://web.dev/input-image-alt/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1038,7 +1039,7 @@ module.exports=InputImageAlt;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/input-image-alt.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/label":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/label":[function(require,module,exports){
(function(__filename){
@@ -1063,7 +1064,7 @@ failureTitle:'Form elements do not have associated labels',
description:'Labels ensure that form controls are announced properly by assistive '+
'technologies, like screen readers. [Learn '+
-'more](https://dequeuniversity.com/rules/axe/3.1/label?application=lighthouse).'};
+'more](https://web.dev/label/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1087,7 +1088,7 @@ module.exports=Label;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/label.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/layout-table":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/layout-table":[function(require,module,exports){
(function(__filename){
@@ -1116,7 +1117,7 @@ failureTitle:'Presentational `<table>` elements do not avoid using `<th>`, '+
description:'A table being used for layout purposes should not include data elements, '+
'such as the th or caption elements or the summary attribute, because this can '+
'create a confusing experience for screen reader users. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/layout-table?application=lighthouse).'};
+'[Learn more](https://web.dev/layout-table/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1140,7 +1141,7 @@ module.exports=LayoutTable;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/layout-table.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/link-name":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/link-name":[function(require,module,exports){
(function(__filename){
@@ -1166,7 +1167,7 @@ failureTitle:'Links do not have a discernible name',
description:'Link text (and alternate text for images, when used as links) that is '+
'discernible, unique, and focusable improves the navigation experience for '+
'screen reader users. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/link-name?application=lighthouse).'};
+'[Learn more](https://web.dev/link-name/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1190,7 +1191,7 @@ module.exports=LinkName;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/link-name.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/listitem":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/listitem":[function(require,module,exports){
(function(__filename){
@@ -1216,7 +1217,7 @@ failureTitle:'List items (`<li>`) are not contained within `<ul>` '+
description:'Screen readers require list items (`<li>`) to be contained within a '+
'parent `<ul>` or `<ol>` to be announced properly. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/listitem?application=lighthouse).'};
+'[Learn more](https://web.dev/listitem/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1240,7 +1241,7 @@ module.exports=ListItem;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/listitem.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/list":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/list":[function(require,module,exports){
(function(__filename){
@@ -1267,7 +1268,7 @@ failureTitle:'Lists do not contain only `<li>` elements and script '+
description:'Screen readers have a specific way of announcing lists. Ensuring proper list '+
'structure aids screen reader output. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/list?application=lighthouse).'};
+'[Learn more](https://web.dev/list/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1291,7 +1292,7 @@ module.exports=List;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/list.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/manual/custom-controls-labels":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/manual/custom-controls-labels":[function(require,module,exports){
@@ -1313,7 +1314,7 @@ class CustomControlsLabels extends ManualAudit{
static get meta(){
return Object.assign({
id:'custom-controls-labels',
-description:'Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+description:'Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://web.dev/custom-controls-labels/).',
title:'Custom controls have associated labels'},
super.partialMeta);
}}
@@ -1343,7 +1344,7 @@ class CustomControlsRoles extends ManualAudit{
static get meta(){
return Object.assign({
id:'custom-controls-roles',
-description:'Custom interactive controls have appropriate ARIA roles. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+description:'Custom interactive controls have appropriate ARIA roles. [Learn more](https://web.dev/custom-control-roles/).',
title:'Custom controls have ARIA roles'},
super.partialMeta);
}}
@@ -1373,7 +1374,7 @@ class FocusTraps extends ManualAudit{
static get meta(){
return Object.assign({
id:'focus-traps',
-description:'A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+description:'A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://web.dev/focus-traps/).',
title:'User focus is not accidentally trapped in a region'},
super.partialMeta);
}}
@@ -1403,7 +1404,7 @@ class FocusableControls extends ManualAudit{
static get meta(){
return Object.assign({
id:'focusable-controls',
-description:'Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+description:'Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://web.dev/focusable-controls/).',
title:'Interactive controls are keyboard focusable'},
super.partialMeta);
}}
@@ -1433,7 +1434,7 @@ class HeadingLevels extends ManualAudit{
static get meta(){
return Object.assign({
id:'heading-levels',
-description:'Headings are used to create an outline for the page and heading levels are not skipped. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
+description:'Headings are used to create an outline for the page and heading levels are not skipped. [Learn more](https://web.dev/heading-levels/).',
title:'Headings don\'t skip levels'},
super.partialMeta);
}}
@@ -1463,7 +1464,7 @@ class InteractiveElementAffordance extends ManualAudit{
static get meta(){
return Object.assign({
id:'interactive-element-affordance',
-description:'Interactive elements, such as links and buttons, should indicate their state and be distinguishable from non-interactive elements. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#interactive_elements_like_links_and_buttons_should_indicate_their_purpose_and_state).',
+description:'Interactive elements, such as links and buttons, should indicate their state and be distinguishable from non-interactive elements. [Learn more](https://web.dev/interactive-element-affordance/).',
title:'Interactive elements indicate their purpose and state'},
super.partialMeta);
}}
@@ -1493,7 +1494,7 @@ class LogicalTabOrder extends ManualAudit{
static get meta(){
return Object.assign({
id:'logical-tab-order',
-description:'Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+description:'Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://web.dev/logical-tab-order/).',
title:'The page has a logical tab order'},
super.partialMeta);
}}
@@ -1523,7 +1524,7 @@ class ManagedFocus extends ManualAudit{
static get meta(){
return Object.assign({
id:'managed-focus',
-description:'If new content, such as a dialog, is added to the page, the user\'s focus is directed to it. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+description:'If new content, such as a dialog, is added to the page, the user\'s focus is directed to it. [Learn more](https://web.dev/managed-focus/).',
title:'The user\'s focus is directed to new content added to the page'},
super.partialMeta);
}}
@@ -1554,7 +1555,7 @@ class OffscreenContentHidden extends ManualAudit{
static get meta(){
return Object.assign({
id:'offscreen-content-hidden',
-description:'Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+description:'Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://web.dev/offscreen-content-hidden/).',
title:'Offscreen content is hidden from assistive technology'},
super.partialMeta);
}}
@@ -1584,7 +1585,7 @@ class UseLandmarks extends ManualAudit{
static get meta(){
return Object.assign({
id:'use-landmarks',
-description:'Landmark elements (<main>, <nav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
+description:'Landmark elements (<main>, <nav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://web.dev/use-landmarks/).',
title:'HTML5 landmark elements are used to improve navigation'},
super.partialMeta);
}}
@@ -1614,7 +1615,7 @@ class VisualOrderFollowsDOM extends ManualAudit{
static get meta(){
return Object.assign({
id:'visual-order-follows-dom',
-description:'DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+description:'DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://web.dev/visual-order-follows-dom/).',
title:'Visual order on the page follows DOM order'},
super.partialMeta);
}}
@@ -1648,7 +1649,7 @@ failureTitle:'The document uses `<meta http-equiv="refresh">`',
description:'Users do not expect a page to refresh automatically, and doing so will move '+
'focus back to the top of the page. This may create a frustrating or '+
'confusing experience. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/meta-refresh?application=lighthouse).'};
+'[Learn more](https://web.dev/meta-refresh/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1672,7 +1673,7 @@ module.exports=MetaRefresh;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/meta-refresh.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/meta-viewport":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/meta-viewport":[function(require,module,exports){
(function(__filename){
@@ -1699,7 +1700,7 @@ failureTitle:'`[user-scalable="no"]` is used in the `<meta name="viewport">` '+
description:'Disabling zooming is problematic for users with low vision who rely on '+
'screen magnification to properly see the contents of a web page. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/meta-viewport?application=lighthouse).'};
+'[Learn more](https://web.dev/meta-viewport/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1723,7 +1724,7 @@ module.exports=MetaViewport;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/meta-viewport.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/object-alt":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/object-alt":[function(require,module,exports){
(function(__filename){
@@ -1748,7 +1749,7 @@ failureTitle:'`<object>` elements do not have `[alt]` text',
description:'Screen readers cannot translate non-text content. Adding alt text to '+
'`<object>` elements helps screen readers convey meaning to users. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/object-alt?application=lighthouse).'};
+'[Learn more](https://web.dev/object-alt/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1772,7 +1773,7 @@ module.exports=ObjectAlt;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/object-alt.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/tabindex":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/tabindex":[function(require,module,exports){
(function(__filename){
@@ -1797,7 +1798,7 @@ failureTitle:'Some elements have a `[tabindex]` value greater than 0',
description:'A value greater than 0 implies an explicit navigation ordering. '+
'Although technically valid, this often creates frustrating experiences '+
-'for users who rely on assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/3.1/tabindex?application=lighthouse).'};
+'for users who rely on assistive technologies. [Learn more](https://web.dev/tabindex/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1821,7 +1822,7 @@ module.exports=TabIndex;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/tabindex.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/td-headers-attr":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/td-headers-attr":[function(require,module,exports){
(function(__filename){
@@ -1841,16 +1842,16 @@ const i18n=require('../../lib/i18n/i18n.js');
const UIStrings={
-title:'Cells in a `<table>` element that use the `[headers]` attribute only refer '+
-'to other cells of that same table.',
+title:'Cells in a `<table>` element that use the `[headers]` attribute refer '+
+'to table cells within the same table.',
-failureTitle:'Cells in a `<table>` element that use the `[headers]` '+
-'attribute refers to other cells of that same table.',
+failureTitle:'Cells in a `<table>` element that use the `[headers]` attribute refer '+
+'to an element `id` not found within the same table.',
description:'Screen readers have features to make navigating tables easier. Ensuring '+
'`<td>` cells using the `[headers]` attribute only refer to other cells in the same '+
'table may improve the experience for screen reader users. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/td-headers-attr?application=lighthouse).'};
+'[Learn more](https://web.dev/td-headers-attr/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1874,7 +1875,7 @@ module.exports=TDHeadersAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/td-headers-attr.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/th-has-data-cells":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/th-has-data-cells":[function(require,module,exports){
(function(__filename){
@@ -1902,7 +1903,7 @@ failureTitle:'`<th>` elements and elements with '+
description:'Screen readers have features to make navigating tables easier. Ensuring '+
'table headers always refer to some set of cells may improve the experience for screen '+
'reader users. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/th-has-data-cells?application=lighthouse).'};
+'[Learn more](https://web.dev/th-has-data-cells/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1926,7 +1927,7 @@ module.exports=THHasDataCells;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/th-has-data-cells.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/valid-lang":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/valid-lang":[function(require,module,exports){
(function(__filename){
@@ -1951,7 +1952,7 @@ failureTitle:'`[lang]` attributes do not have a valid value',
description:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
'on elements helps ensure that text is pronounced correctly by a screen reader. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/valid-lang?application=lighthouse).'};
+'[Learn more](https://web.dev/valid-lang/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -1975,7 +1976,7 @@ module.exports=ValidLang;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/valid-lang.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/video-caption":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/video-caption":[function(require,module,exports){
(function(__filename){
@@ -2001,7 +2002,7 @@ failureTitle:'`<video>` elements do not contain a `<track>` element '+
description:'When a video provides a caption it is easier for deaf and hearing impaired '+
'users to access its information. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/video-caption?application=lighthouse).'};
+'[Learn more](https://web.dev/video-caption/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -2025,7 +2026,7 @@ module.exports=VideoCaption;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/video-caption.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/accessibility/video-description":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/accessibility/video-description":[function(require,module,exports){
(function(__filename){
@@ -2051,7 +2052,7 @@ failureTitle:'`<video>` elements do not contain a `<track>` element with '+
description:'Audio descriptions provide relevant information for videos that dialogue '+
'cannot, such as facial expressions and scenes. '+
-'[Learn more](https://dequeuniversity.com/rules/axe/3.1/video-description?application=lighthouse).'};
+'[Learn more](https://web.dev/video-description/).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -2075,7 +2076,7 @@ module.exports=VideoDescription;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/video-description.js");
-},{"../../lib/i18n/i18n.js":68,"./axe-audit.js":2}],"../audits/apple-touch-icon":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./axe-audit.js":2}],"../audits/apple-touch-icon":[function(require,module,exports){
(function(__filename){
@@ -2097,9 +2098,9 @@ title:'Provides a valid `apple-touch-icon`',
failureTitle:'Does not provide a valid `apple-touch-icon`',
-description:'For ideal appearance on iOS when users add to the home screen, define an '+
-'apple-touch-icon. It must point to a non-transparent 192px (or 180px) square PNG. '+
-'[Learn More](https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/).',
+description:'For ideal appearance on iOS when users add a progressive web app to the home '+
+'screen, define an `apple-touch-icon`. It must point to a non-transparent 192px (or 180px) '+
+'square PNG. [Learn More](https://web.dev/apple-touch-icon/).',
precomposedWarning:'`apple-touch-icon-precomposed` is out of date; '+
'`apple-touch-icon` is preferred.'};
@@ -2150,7 +2151,7 @@ module.exports=AppleTouchIcon;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/apple-touch-icon.js");
-},{"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/bootup-time":[function(require,module,exports){
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/bootup-time":[function(require,module,exports){
(function(__filename){
@@ -2174,7 +2175,7 @@ failureTitle:'Reduce JavaScript execution time',
description:'Consider reducing the time spent parsing, compiling, and executing JS. '+
'You may find delivering smaller JS payloads helps with this. [Learn '+
-'more](https://developers.google.com/web/tools/lighthouse/audits/bootup).',
+'more](https://web.dev/bootup-time).',
columnTotal:'Total CPU Time',
@@ -2354,7 +2355,7 @@ module.exports=BootupTime;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/bootup-time.js");
-},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":33,"../lib/i18n/i18n.js":68,"../lib/network-request.js":76,"../lib/tracehouse/task-groups.js":85,"./audit.js":3}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){
+},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":34,"../lib/i18n/i18n.js":67,"../lib/network-request.js":76,"../lib/tracehouse/task-groups.js":85,"./audit.js":3}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){
(function(__filename){
@@ -2376,7 +2377,7 @@ title:'Use video formats for animated content',
description:'Large GIFs are inefficient for delivering animated content. Consider using '+
'MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save '+
-'network bytes. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/replace-animated-gifs-with-video/)'};
+'network bytes. [Learn more](https://web.dev/efficient-animated-content)'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -2450,7 +2451,7 @@ module.exports=EfficientAnimatedContent;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/network-request.js":76,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/network-request.js":76,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){
(function(__filename){
@@ -2477,7 +2478,7 @@ title:'Defer offscreen images',
description:
'Consider lazy-loading offscreen and hidden images after all critical resources have '+
'finished loading to lower time to interactive. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/offscreen-images).'};
+'[Learn more](https://web.dev/offscreen-images).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -2697,7 +2698,7 @@ module.exports=OffscreenImages;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/offscreen-images.js");
-},{"../../computed/metrics/interactive.js":18,"../../computed/trace-of-tab.js":38,"../../lib/i18n/i18n.js":68,"../../lib/sentry.js":79,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){
+},{"../../computed/metrics/interactive.js":18,"../../computed/trace-of-tab.js":39,"../../lib/i18n/i18n.js":67,"../../lib/sentry.js":79,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){
(function(__filename){
@@ -2736,7 +2737,7 @@ title:'Eliminate render-blocking resources',
description:'Resources are blocking the first paint of your page. Consider '+
'delivering critical JS/CSS inline and deferring all non-critical '+
-'JS/styles. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/blocking-resources).'};
+'JS/styles. [Learn more](https://web.dev/render-blocking-resources).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -2934,7 +2935,7 @@ module.exports=RenderBlockingResources;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js");
-},{"../../computed/load-simulator.js":10,"../../computed/metrics/first-contentful-paint.js":15,"../../computed/trace-of-tab.js":38,"../../lib/dependency-graph/base-node.js":57,"../../lib/i18n/i18n.js":68,"../../lib/network-request.js":76,"../audit.js":3,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){
+},{"../../computed/load-simulator.js":10,"../../computed/metrics/first-contentful-paint.js":15,"../../computed/trace-of-tab.js":39,"../../lib/dependency-graph/base-node.js":58,"../../lib/i18n/i18n.js":67,"../../lib/network-request.js":76,"../audit.js":3,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){
(function(__filename){
@@ -2956,7 +2957,7 @@ failureTitle:'Avoid enormous network payloads',
description:
'Large network payloads cost users real money and are highly correlated with '+
'long load times. [Learn '+
-'more](https://developers.google.com/web/tools/lighthouse/audits/network-payloads).',
+'more](https://web.dev/total-byte-weight).',
displayValue:'Total size was {totalBytes, number, bytes}\xa0KB'};
@@ -3054,7 +3055,7 @@ module.exports=TotalByteWeight;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/total-byte-weight.js");
-},{"../../computed/network-records.js":33,"../../lib/i18n/i18n.js":68,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unminified-css":[function(require,module,exports){
+},{"../../computed/network-records.js":34,"../../lib/i18n/i18n.js":67,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unminified-css":[function(require,module,exports){
(function(__filename){
@@ -3073,7 +3074,7 @@ const UIStrings={
title:'Minify CSS',
description:'Minifying CSS files can reduce network payload sizes. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/minify-css).'};
+'[Learn more](https://web.dev/unminified-css).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -3175,7 +3176,7 @@ module.exports=UnminifiedCSS;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/unminified-css.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/minification-estimator.js":74,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/unminified-javascript":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/minification-estimator.js":74,"./byte-efficiency-audit.js":4,"./unused-css-rules.js":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/unminified-javascript":[function(require,module,exports){
(function(__filename){
@@ -3193,7 +3194,7 @@ const UIStrings={
title:'Minify JavaScript',
description:'Minifying JavaScript files can reduce payload sizes and script parse time. '+
-'[Learn more](https://developers.google.com/speed/docs/insights/MinifyResources).'};
+'[Learn more](https://web.dev/unminified-javascript).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -3297,7 +3298,7 @@ module.exports=UnminifiedJavaScript;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/unminified-javascript.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/minification-estimator.js":74,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/minification-estimator.js":74,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){
(function(__filename){
@@ -3315,12 +3316,14 @@ title:'Remove unused CSS',
description:'Remove dead rules from stylesheets and defer the loading of CSS not used for '+
'above-the-fold content to reduce unnecessary bytes consumed by network activity. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/unused-css).'};
+'[Learn more](https://web.dev/unused-css-rules).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
-const IGNORE_THRESHOLD_IN_BYTES=2048;
+
+
+const IGNORE_THRESHOLD_IN_BYTES=10*1024;
const PREVIEW_LENGTH=100;
@@ -3346,6 +3349,10 @@ requiredArtifacts:['CSSUsage','URL','devtoolsLogs','traces']};
static indexStylesheetsById(styles,networkRecords){
const indexedNetworkRecords=networkRecords.
+
+
+
+filter(record=>record.resourceSize>0).
reduce((indexed,record)=>{
indexed[record.url]=record;
return indexed;
@@ -3492,7 +3499,7 @@ module.exports=UnusedCSSRules;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/unused-css-rules.js");
-},{"../../lib/i18n/i18n.js":68,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-javascript":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/unused-javascript":[function(require,module,exports){
(function(__filename){
@@ -3630,7 +3637,7 @@ module.exports=UnusedJavaScript;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/unused-javascript.js");
-},{"../../lib/i18n/i18n.js":68,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-long-cache-ttl":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-long-cache-ttl":[function(require,module,exports){
(function(__filename){
@@ -3656,7 +3663,7 @@ failureTitle:'Serve static assets with an efficient cache policy',
description:
'A long cache lifetime can speed up repeat visits to your page. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/cache-policy).',
+'[Learn more](https://web.dev/uses-long-cache-ttl).',
displayValue:`{itemCount, plural,
=1 {1 resource found}
@@ -3937,7 +3944,7 @@ module.exports=CacheHeaders;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js");
-},{"../../computed/network-records.js":33,"../../lib/i18n/i18n.js":68,"../../lib/network-request.js":76,"../../lib/statistics.js":82,"../../lib/url-shim.js":"url","../audit.js":3,"assert":92,"parse-cache-control":142}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){
+},{"../../computed/network-records.js":34,"../../lib/i18n/i18n.js":67,"../../lib/network-request.js":76,"../../lib/statistics.js":82,"../../lib/url-shim.js":"url","../audit.js":3,"assert":92,"parse-cache-control":139}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){
(function(__filename){
@@ -3959,7 +3966,7 @@ const UIStrings={
title:'Efficiently encode images',
description:'Optimized images load faster and consume less cellular data. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/optimize-images).'};
+'[Learn more](https://web.dev/uses-optimized-images).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -4076,7 +4083,7 @@ module.exports=UsesOptimizedImages;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-responsive-images":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-responsive-images":[function(require,module,exports){
(function(__filename){
@@ -4105,7 +4112,7 @@ title:'Properly size images',
description:
'Serve images that are appropriately-sized to save cellular data '+
'and improve load time. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/oversized-images).'};
+'[Learn more](https://web.dev/uses-responsive-images).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -4222,7 +4229,7 @@ module.exports=UsesResponsiveImages;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/sentry.js":79,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/sentry.js":79,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){
(function(__filename){
@@ -4245,7 +4252,7 @@ title:'Enable text compression',
description:'Text-based resources should be served with compression (gzip, deflate or'+
' brotli) to minimize total network bytes.'+
-' [Learn more](https://developers.google.com/web/tools/lighthouse/audits/text-compression).'};
+' [Learn more](https://web.dev/uses-text-compression).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -4326,7 +4333,7 @@ module.exports=ResponsesAreCompressed;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/uses-text-compression.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-webp-images":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/byte-efficiency/uses-webp-images":[function(require,module,exports){
(function(__filename){
@@ -4348,7 +4355,7 @@ title:'Serve images in next-gen formats',
description:'Image formats like JPEG 2000, JPEG XR, and WebP often provide better '+
'compression than PNG or JPEG, which means faster downloads and less data consumption. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/webp).'};
+'[Learn more](https://web.dev/uses-webp-images).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -4464,7 +4471,8 @@ module.exports=UsesWebPImages;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/byte-efficiency/uses-webp-images.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/content-width":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","./byte-efficiency-audit.js":4}],"../audits/content-width":[function(require,module,exports){
+(function(__filename){
@@ -4473,6 +4481,27 @@ module.exports.UIStrings=UIStrings;
'use strict';
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Content is sized correctly for the viewport',
+
+failureTitle:'Content is not sized correctly for the viewport',
+
+description:'If the width of your app\'s content doesn\'t match the width '+
+'of the viewport, your app might not be optimized for mobile screens. '+
+'[Learn more](https://web.dev/content-width).',
+
+
+
+
+
+explanation:'The viewport size of {innerWidth}px does not match the window '+
+'size of {outerWidth}px.'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class ContentWidth extends Audit{
@@ -4481,11 +4510,9 @@ class ContentWidth extends Audit{
static get meta(){
return{
id:'content-width',
-title:'Content is sized correctly for the viewport',
-failureTitle:'Content is not sized correctly for the viewport',
-description:'If the width of your app\'s content doesn\'t match the width '+
-'of the viewport, your app might not be optimized for mobile screens. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/content-sized-correctly-for-viewport).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['ViewportDimensions','TestedAsMobileDevice']};
}
@@ -4500,37 +4527,32 @@ const viewportWidth=artifacts.ViewportDimensions.innerWidth;
const windowWidth=artifacts.ViewportDimensions.outerWidth;
const widthsMatch=viewportWidth===windowWidth;
-if(IsMobile){
-return{
-score:Number(widthsMatch),
-explanation:this.createExplanation(widthsMatch,artifacts.ViewportDimensions)};
-
-}else{
+if(!IsMobile){
return{
score:1,
notApplicable:true};
}
-}
-
-
-
-
-
-static createExplanation(match,artifact){
-if(match){
-return'';
+let explanation='';
+if(!widthsMatch){
+explanation=str_(UIStrings.explanation,
+{innerWidth:artifacts.ViewportDimensions.innerWidth,
+outerWidth:artifacts.ViewportDimensions.outerWidth});
}
-return'The viewport size is '+artifact.innerWidth+'px, '+
-'whereas the window size is '+artifact.outerWidth+'px.';
+return{
+score:Number(widthsMatch),
+explanation};
+
}}
module.exports=ContentWidth;
+module.exports.UIStrings=UIStrings;
-},{"./audit.js":3}],"../audits/critical-request-chains":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/content-width.js");
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/critical-request-chains":[function(require,module,exports){
(function(__filename){
@@ -4545,13 +4567,13 @@ const ComputedChains=require('../computed/critical-request-chains.js');
const UIStrings={
-title:'Minimize Critical Requests Depth',
+title:'Avoid chaining critical requests',
description:'The Critical Request Chains below show you what resources are '+
'loaded with a high priority. Consider reducing '+
'the length of chains, reducing the download size of resources, or '+
'deferring the download of unnecessary resources to improve page load. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/critical-request-chains).',
+'[Learn more](https://web.dev/critical-request-chains).',
displayValue:`{itemCount, plural,
=1 {1 chain found}
@@ -4758,7 +4780,7 @@ module.exports=CriticalRequestChains;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/critical-request-chains.js");
-},{"../computed/critical-request-chains.js":9,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/deprecations":[function(require,module,exports){
+},{"../computed/critical-request-chains.js":9,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/deprecations":[function(require,module,exports){
(function(__filename){
@@ -4783,7 +4805,7 @@ title:'Avoids deprecated APIs',
failureTitle:'Uses deprecated APIs',
description:'Deprecated APIs will eventually be removed from the browser. '+
-'[Learn more](https://www.chromestatus.com/features#deprecated).',
+'[Learn more](https://web.dev/deprecations).',
displayValue:`{itemCount, plural,
=1 {1 warning found}
@@ -4829,7 +4851,7 @@ lineNumber:log.entry.lineNumber};
const headings=[
-{key:'value',itemType:'code',text:str_(UIStrings.columnDeprecate)},
+{key:'value',itemType:'text',text:str_(UIStrings.columnDeprecate)},
{key:'url',itemType:'url',text:str_(i18n.UIStrings.columnURL)},
{key:'lineNumber',itemType:'text',text:str_(UIStrings.columnLine)}];
@@ -4855,7 +4877,7 @@ module.exports=Deprecations;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/deprecations.js");
-},{"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/diagnostics":[function(require,module,exports){
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/diagnostics":[function(require,module,exports){
@@ -4935,7 +4957,7 @@ items:[diagnostics]}};
module.exports=Diagnostics;
-},{"../computed/main-thread-tasks.js":12,"../computed/network-analysis.js":32,"../computed/network-records.js":33,"../lib/dependency-graph/simulator/network-analyzer.js":62,"./audit.js":3}],"../audits/dobetterweb/appcache-manifest":[function(require,module,exports){
+},{"../computed/main-thread-tasks.js":12,"../computed/network-analysis.js":33,"../computed/network-records.js":34,"../lib/dependency-graph/simulator/network-analyzer.js":63,"./audit.js":3}],"../audits/dobetterweb/appcache-manifest":[function(require,module,exports){
(function(__filename){
@@ -4959,7 +4981,10 @@ title:'Avoids Application Cache',
failureTitle:'Uses Application Cache',
description:'Application Cache is deprecated. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).',
+'[Learn more](https://web.dev/appcache-manifest).',
+
+
+
displayValue:'Found "{AppCacheManifest}"'};
@@ -4985,13 +5010,16 @@ requiredArtifacts:['AppCacheManifest']};
static audit(artifacts){
-const usingAppcache=artifacts.AppCacheManifest!==null;
-const displayValue=usingAppcache?
-str_(UIStrings.displayValue,{AppCacheManifest:artifacts.AppCacheManifest}):'';
+if(artifacts.AppCacheManifest!==null){
return{
-score:usingAppcache?0:1,
-displayValue};
+score:0,
+displayValue:str_(UIStrings.displayValue,{AppCacheManifest:artifacts.AppCacheManifest})};
+
+}
+
+return{
+score:1};
}}
@@ -5000,7 +5028,7 @@ module.exports=AppCacheManifestAttr;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/appcache-manifest.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/dobetterweb/doctype":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/dobetterweb/doctype":[function(require,module,exports){
(function(__filename){
@@ -5019,8 +5047,8 @@ title:'Page has the HTML doctype',
failureTitle:'Page lacks the HTML doctype, thus triggering quirks-mode',
description:'Specifying a doctype prevents the browser '+
-'from switching to quirks-mode. Read more on the '+
-'[MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)',
+'from switching to quirks-mode. '+
+'[Learn more](https://web.dev/doctype).',
explanationNoDoctype:'Document must contain a doctype',
@@ -5098,7 +5126,7 @@ module.exports=Doctype;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/doctype.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/dobetterweb/dom-size":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/dobetterweb/dom-size":[function(require,module,exports){
(function(__filename){
@@ -5118,22 +5146,15 @@ const Audit=require('../audit.js');
const Util=require('../../report/html/renderer/util.js');
const i18n=require('../../lib/i18n/i18n.js');
-const MAX_DOM_ELEMENTS=1500;
-const MAX_DOM_TREE_WIDTH=60;
-const MAX_DOM_TREE_DEPTH=32;
-
const UIStrings={
title:'Avoids an excessive DOM size',
failureTitle:'Avoid an excessive DOM size',
-description:'Browser engineers recommend pages contain fewer than '+
-`~${MAX_DOM_ELEMENTS.toLocaleString()} DOM elements. The sweet spot is a tree `+
-`depth < ${MAX_DOM_TREE_DEPTH} elements and fewer than ${MAX_DOM_TREE_WIDTH} `+
-'children/parent element. A large DOM can increase memory usage, cause longer '+
+description:'A large DOM will increase memory usage, cause longer '+
'[style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), '+
-'and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://developers.google.com/web/tools/lighthouse/audits/dom-size).',
+'and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://web.dev/dom-size).',
columnStatistic:'Statistic',
@@ -5157,10 +5178,6 @@ const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class DOMSize extends Audit{
-static get MAX_DOM_ELEMENTS(){
-return MAX_DOM_ELEMENTS;
-}
-
@@ -5251,7 +5268,7 @@ module.exports=DOMSize;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/dom-size.js");
-},{"../../lib/i18n/i18n.js":68,"../../report/html/renderer/util.js":88,"../audit.js":3}],"../audits/dobetterweb/external-anchors-use-rel-noopener":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../report/html/renderer/util.js":88,"../audit.js":3}],"../audits/dobetterweb/external-anchors-use-rel-noopener":[function(require,module,exports){
(function(__filename){
@@ -5272,7 +5289,10 @@ failureTitle:'Links to cross-origin destinations are unsafe',
description:'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve '+
'performance and prevent security vulnerabilities. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).',
+'[Learn more](https://web.dev/external-anchors-use-rel-noopener).',
+
+
+
warning:'Unable to determine the destination for anchor ({anchorHTML}). '+
'If not used as a hyperlink, consider removing target=_blank.',
@@ -5354,7 +5374,7 @@ module.exports=ExternalAnchorsUseRelNoopenerAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/dobetterweb/geolocation-on-start":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/dobetterweb/geolocation-on-start":[function(require,module,exports){
(function(__filename){
@@ -5380,7 +5400,7 @@ failureTitle:'Requests the geolocation permission on page load',
description:'Users are mistrustful of or confused by sites that request their '+
'location without context. Consider tying the request to a user action instead. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).'};
+'[Learn more](https://web.dev/geolocation-on-start).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -5430,7 +5450,7 @@ module.exports=GeolocationOnStart;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/geolocation-on-start.js");
-},{"../../lib/i18n/i18n.js":68,"../violation-audit.js":7}],"../audits/dobetterweb/js-libraries":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../violation-audit.js":7}],"../audits/dobetterweb/js-libraries":[function(require,module,exports){
(function(__filename){
@@ -5451,9 +5471,7 @@ const UIStrings={
title:'Detected JavaScript libraries',
-description:'All front-end JavaScript libraries detected on the page.',
-
-columnName:'Name',
+description:'All front-end JavaScript libraries detected on the page. [Learn more](https://web.dev/js-libraries).',
columnVersion:'Version'};
@@ -5488,7 +5506,7 @@ npm:stack.npm}));
const headings=[
-{key:'name',itemType:'text',text:str_(UIStrings.columnName)},
+{key:'name',itemType:'text',text:str_(i18n.UIStrings.columnName)},
{key:'version',itemType:'text',text:str_(UIStrings.columnVersion)}];
const details=Audit.makeTableDetails(headings,libDetails,{});
@@ -5504,7 +5522,7 @@ module.exports=JsLibrariesAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/js-libraries.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/dobetterweb/no-document-write":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/dobetterweb/no-document-write":[function(require,module,exports){
(function(__filename){
@@ -5516,6 +5534,24 @@ module.exports.UIStrings=UIStrings;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
'use strict';
const ViolationAudit=require('../violation-audit.js');
@@ -5529,7 +5565,7 @@ failureTitle:'Uses `document.write()`',
description:'For users on slow connections, external scripts dynamically injected via '+
'`document.write()` can delay page load by tens of seconds. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).'};
+'[Learn more](https://web.dev/no-document-write).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -5577,7 +5613,7 @@ module.exports=NoDocWriteAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/no-document-write.js");
-},{"../../lib/i18n/i18n.js":68,"../violation-audit.js":7}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../violation-audit.js":7}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){
(function(__filename){
@@ -5609,7 +5645,7 @@ failureTitle:'Includes front-end JavaScript libraries'+
description:'Some third-party scripts may contain known security vulnerabilities '+
'that are easily identified and exploited by attackers. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).',
+'[Learn more](https://web.dev/no-vulnerable-libraries).',
displayValue:`{itemCount, plural,
=1 {1 vulnerability detected}
@@ -5824,7 +5860,7 @@ module.exports=NoVulnerableLibrariesAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js");
-},{"../../../third-party/snyk/snapshot.json":182,"../../lib/i18n/i18n.js":68,"../../lib/sentry.js":79,"../audit.js":3,"semver":166}],"../audits/dobetterweb/notification-on-start":[function(require,module,exports){
+},{"../../../third-party/snyk/snapshot.json":183,"../../lib/i18n/i18n.js":67,"../../lib/sentry.js":79,"../audit.js":3,"semver":163}],"../audits/dobetterweb/notification-on-start":[function(require,module,exports){
(function(__filename){
@@ -5850,7 +5886,7 @@ failureTitle:'Requests the notification permission on page load',
description:'Users are mistrustful of or confused by sites that request to send '+
'notifications without context. Consider tying the request to user gestures '+
-'instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/notifications-on-load).'};
+'instead. [Learn more](https://web.dev/notification-on-start).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -5898,7 +5934,7 @@ module.exports=NotificationOnStart;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/notification-on-start.js");
-},{"../../lib/i18n/i18n.js":68,"../violation-audit.js":7}],"../audits/dobetterweb/password-inputs-can-be-pasted-into":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../violation-audit.js":7}],"../audits/dobetterweb/password-inputs-can-be-pasted-into":[function(require,module,exports){
(function(__filename){
@@ -5917,7 +5953,7 @@ title:'Allows users to paste into password fields',
failureTitle:'Prevents users to paste into password fields',
description:'Preventing password pasting undermines good security policy. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/password-pasting).',
+'[Learn more](https://web.dev/password-inputs-can-be-pasted-into).',
columnFailingElem:'Failing Elements'};
@@ -5972,7 +6008,7 @@ module.exports=PasswordInputsCanBePastedIntoAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/dobetterweb/uses-http2":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/dobetterweb/uses-http2":[function(require,module,exports){
(function(__filename){
@@ -5999,7 +6035,7 @@ title:'Uses HTTP/2 for its own resources',
failureTitle:'Does not use HTTP/2 for all of its resources',
description:'HTTP/2 offers many benefits over HTTP/1.1, including binary headers, '+
-'multiplexing, and server push. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http2).',
+'multiplexing, and server push. [Learn more](https://web.dev/uses-http2).',
displayValue:`{itemCount, plural,
=1 {1 request not served via HTTP/2}
@@ -6087,7 +6123,7 @@ module.exports=UsesHTTP2Audit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/uses-http2.js");
-},{"../../computed/network-records.js":33,"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/dobetterweb/uses-passive-event-listeners":[function(require,module,exports){
+},{"../../computed/network-records.js":34,"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/dobetterweb/uses-passive-event-listeners":[function(require,module,exports){
(function(__filename){
@@ -6113,7 +6149,7 @@ failureTitle:'Does not use passive listeners to improve scrolling performance',
description:'Consider marking your touch and wheel event listeners as `passive` '+
'to improve your page\'s scroll performance. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners).'};
+'[Learn more](https://web.dev/uses-passive-event-listeners).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -6161,7 +6197,7 @@ module.exports=PassiveEventsAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js");
-},{"../../lib/i18n/i18n.js":68,"../violation-audit.js":7}],"../audits/errors-in-console":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../violation-audit.js":7}],"../audits/errors-in-console":[function(require,module,exports){
(function(__filename){
@@ -6175,6 +6211,7 @@ module.exports.UIStrings=UIStrings;
+const log=require('lighthouse-logger');
const Audit=require('./audit.js');
const i18n=require('../lib/i18n/i18n.js');
@@ -6185,13 +6222,16 @@ title:'No browser errors logged to the console',
failureTitle:'Browser errors were logged to the console',
description:'Errors logged to the console indicate unresolved problems. '+
-'They can come from network request failures and other browser concerns.',
+'They can come from network request failures and other browser concerns. '+
+'[Learn more](https://web.dev/errors-in-console)',
columnDesc:'Description'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+
+
class ErrorLogs extends Audit{
@@ -6207,10 +6247,42 @@ requiredArtifacts:['ConsoleMessages','RuntimeExceptions']};
}
+static defaultOptions(){
+return{};
+}
+
-static audit(artifacts){
+
+
+
+
+static filterAccordingToOptions(items,options){
+const{ignoredPatterns,...restOfOptions}=options;
+const otherOptionKeys=Object.keys(restOfOptions);
+if(otherOptionKeys.length)log.warn(this.meta.id,'Unrecognized options',otherOptionKeys);
+if(!ignoredPatterns)return items;
+
+return items.filter(({description})=>{
+if(!description)return true;
+for(const pattern of ignoredPatterns){
+if(pattern instanceof RegExp&&pattern.test(description))return false;
+if(typeof pattern==='string'&&description.includes(pattern))return false;
+}
+
+return true;
+});
+}
+
+
+
+
+
+
+static audit(artifacts,context){
+const auditOptions=context.options;
+
const consoleEntries=artifacts.ConsoleMessages;
const runtimeExceptions=artifacts.RuntimeExceptions;
@@ -6237,7 +6309,10 @@ url:entry.exceptionDetails.url};
});
-const tableRows=consoleRows.concat(runtimeExRows);
+const tableRows=ErrorLogs.filterAccordingToOptions(
+consoleRows.concat(runtimeExRows),
+auditOptions).
+sort((a,b)=>(a.description||'').localeCompare(b.description||''));
const headings=[
@@ -6260,7 +6335,7 @@ module.exports=ErrorLogs;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/errors-in-console.js");
-},{"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/final-screenshot":[function(require,module,exports){
+},{"../lib/i18n/i18n.js":67,"./audit.js":3,"lighthouse-logger":125}],"../audits/final-screenshot":[function(require,module,exports){
@@ -6317,7 +6392,7 @@ data:finalScreenshot.datauri}};
module.exports=FinalScreenshot;
-},{"../computed/screenshots.js":36,"../computed/trace-of-tab.js":38,"../lib/lh-error.js":72,"./audit.js":3}],"../audits/font-display":[function(require,module,exports){
+},{"../computed/screenshots.js":37,"../computed/trace-of-tab.js":39,"../lib/lh-error.js":72,"./audit.js":3}],"../audits/font-display":[function(require,module,exports){
(function(__filename){
@@ -6344,7 +6419,10 @@ failureTitle:'Ensure text remains visible during webfont load',
description:
'Leverage the font-display CSS feature to ensure text is user-visible while '+
'webfonts are loading. '+
-'[Learn more](https://developers.google.com/web/updates/2016/02/font-display).',
+'[Learn more](https://web.dev/font-display).',
+
+
+
undeclaredFontURLWarning:'Lighthouse was unable to automatically check the font-display value '+
'for the following URL: {fontURL}.'};
@@ -6482,7 +6560,7 @@ module.exports=FontDisplay;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/font-display.js");
-},{"../computed/network-records.js":33,"../lib/i18n/i18n.js":68,"../lib/sentry.js":79,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/image-aspect-ratio":[function(require,module,exports){
+},{"../computed/network-records.js":34,"../lib/i18n/i18n.js":67,"../lib/sentry.js":79,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/image-aspect-ratio":[function(require,module,exports){
(function(__filename){
@@ -6508,7 +6586,10 @@ title:'Displays images with correct aspect ratio',
failureTitle:'Displays images with incorrect aspect ratio',
description:'Image display dimensions should match natural aspect ratio. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/aspect-ratio).',
+'[Learn more](https://web.dev/image-aspect-ratio).',
+
+
+
warningCompute:'Invalid image sizing information {url}',
@@ -6620,7 +6701,8 @@ module.exports=ImageAspectRatio;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/image-aspect-ratio.js");
-},{"../lib/i18n/i18n.js":68,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/installable-manifest":[function(require,module,exports){
+},{"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/installable-manifest":[function(require,module,exports){
+(function(__filename){
@@ -6630,6 +6712,20 @@ module.exports.UIStrings=UIStrings;
const MultiCheckAudit=require('./multi-check-audit.js');
const ManifestValues=require('../computed/manifest-values.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Web app manifest meets the installability requirements',
+
+failureTitle:'Web app manifest does not meet the installability requirements',
+
+description:'Browsers can proactively prompt users to add your app to their homescreen, '+
+'which can lead to higher engagement. '+
+'[Learn more](https://web.dev/installable-manifest).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -6652,11 +6748,9 @@ class InstallableManifest extends MultiCheckAudit{
static get meta(){
return{
id:'installable-manifest',
-title:'Web app manifest meets the installability requirements',
-failureTitle:'Web app manifest does not meet the installability requirements',
-description:'Browsers can proactively prompt users to add your app to their homescreen, '+
-'which can lead to higher engagement. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/install-prompt).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['URL','WebAppManifest']};
}
@@ -6715,8 +6809,10 @@ manifestValues};
module.exports=InstallableManifest;
+module.exports.UIStrings=UIStrings;
-},{"../computed/manifest-values.js":13,"./multi-check-audit.js":6}],"../audits/is-on-https":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/installable-manifest.js");
+},{"../computed/manifest-values.js":13,"../lib/i18n/i18n.js":67,"./multi-check-audit.js":6}],"../audits/is-on-https":[function(require,module,exports){
(function(__filename){
@@ -6740,7 +6836,7 @@ description:'All sites should be protected with HTTPS, even ones that don\'t han
'sensitive data. HTTPS prevents intruders from tampering with or passively listening '+
'in on the communications between your app and your users, and is a prerequisite for '+
'HTTP/2 and many new web platform APIs. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/https).',
+'[Learn more](https://web.dev/is-on-https).',
displayValue:`{itemCount, plural,
=1 {1 insecure request found}
@@ -6819,7 +6915,7 @@ module.exports=HTTPS;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/is-on-https.js");
-},{"../computed/network-records.js":33,"../lib/i18n/i18n.js":68,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/load-fast-enough-for-pwa":[function(require,module,exports){
+},{"../computed/network-records.js":34,"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/load-fast-enough-for-pwa":[function(require,module,exports){
(function(__filename){
@@ -6850,12 +6946,16 @@ title:'Page load is fast enough on mobile networks',
failureTitle:'Page load is not fast enough on mobile networks',
-description:'A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).',
+description:'A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://web.dev/load-fast-enough-for-pwa).',
displayValueText:'Interactive at {timeInMs, number, seconds}\xa0s',
displayValueTextWithOverride:'Interactive on simulated mobile network at '+
-'{timeInMs, number, seconds}\xa0s'};
+'{timeInMs, number, seconds}\xa0s',
+
+explanationLoadSlow:'Your page loads too slowly and is not interactive within 10 seconds. '+
+'Look at the opportunities and diagnostics in the "Performance" section to learn how to '+
+'improve.'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -6909,9 +7009,7 @@ let displayValue;
let explanation;
if(!score){
displayValue=str_(displayValueTemplate,{timeInMs:tti.timing});
-explanation='Your page loads too slowly and is not interactive within 10 seconds. '+
-'Look at the opportunities and diagnostics in the "Performance" section to learn how to '+
-'improve.';
+explanation=str_(UIStrings.explanationLoadSlow);
}
return{
@@ -6927,7 +7025,7 @@ module.exports=LoadFastEnough4Pwa;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/load-fast-enough-for-pwa.js");
-},{"../computed/metrics/interactive.js":18,"../config/constants.js":45,"../lib/i18n/i18n.js":68,"./audit.js":3,"lodash.isequal":129}],"../audits/main-thread-tasks":[function(require,module,exports){
+},{"../computed/metrics/interactive.js":18,"../config/constants.js":46,"../lib/i18n/i18n.js":67,"./audit.js":3,"lodash.isequal":126}],"../audits/main-thread-tasks":[function(require,module,exports){
@@ -7015,7 +7113,8 @@ title:'Minimizes main-thread work',
failureTitle:'Minimize main-thread work',
description:'Consider reducing the time spent parsing, compiling and executing JS. '+
-'You may find delivering smaller JS payloads helps with this.',
+'You may find delivering smaller JS payloads helps with this. '+
+'[Learn more](https://web.dev/mainthread-work-breakdown)',
columnCategory:'Category'};
@@ -7126,7 +7225,8 @@ module.exports=MainThreadWorkBreakdown;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/mainthread-work-breakdown.js");
-},{"../computed/main-thread-tasks.js":12,"../lib/i18n/i18n.js":68,"../lib/tracehouse/task-groups.js":85,"./audit.js":3}],"../audits/manual/pwa-cross-browser":[function(require,module,exports){
+},{"../computed/main-thread-tasks.js":12,"../lib/i18n/i18n.js":67,"../lib/tracehouse/task-groups.js":85,"./audit.js":3}],"../audits/manual/pwa-cross-browser":[function(require,module,exports){
+(function(__filename){
@@ -7136,6 +7236,17 @@ module.exports.UIStrings=UIStrings;
'use strict';
const ManualAudit=require('./manual-audit.js');
+const i18n=require('../../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Site works cross-browser',
+
+description:'To reach the most number of users, sites should work across '+
+'every major browser. [Learn more](https://web.dev/pwa-cross-browser).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7148,16 +7259,19 @@ class PWACrossBrowser extends ManualAudit{
static get meta(){
return Object.assign({
id:'pwa-cross-browser',
-description:'To reach the most number of users, sites should work across '+
-'every major browser. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#site-works-cross-browser).',
-title:'Site works cross-browser'},
+title:str_(UIStrings.title),
+description:str_(UIStrings.description)},
super.partialMeta);
}}
module.exports=PWACrossBrowser;
+module.exports.UIStrings=UIStrings;
+
-},{"./manual-audit.js":5}],"../audits/manual/pwa-each-page-has-url":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/manual/pwa-cross-browser.js");
+},{"../../lib/i18n/i18n.js":67,"./manual-audit.js":5}],"../audits/manual/pwa-each-page-has-url":[function(require,module,exports){
+(function(__filename){
@@ -7166,6 +7280,17 @@ module.exports=PWACrossBrowser;
'use strict';
const ManualAudit=require('./manual-audit.js');
+const i18n=require('../../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Each page has a URL',
+
+description:'Ensure individual pages are deep linkable via URL and that URLs are '+
+'unique for the purpose of shareability on social media. [Learn more](https://web.dev/pwa-each-page-has-url).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7178,16 +7303,18 @@ class PWAEachPageHasURL extends ManualAudit{
static get meta(){
return Object.assign({
id:'pwa-each-page-has-url',
-description:'Ensure individual pages are deep linkable via the URLs and that URLs are '+
-'unique for the purpose of shareability on social media. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#each-page-has-a-url).',
-title:'Each page has a URL'},
+title:str_(UIStrings.title),
+description:str_(UIStrings.description)},
super.partialMeta);
}}
module.exports=PWAEachPageHasURL;
+module.exports.UIStrings=UIStrings;
-},{"./manual-audit.js":5}],"../audits/manual/pwa-page-transitions":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/manual/pwa-each-page-has-url.js");
+},{"../../lib/i18n/i18n.js":67,"./manual-audit.js":5}],"../audits/manual/pwa-page-transitions":[function(require,module,exports){
+(function(__filename){
@@ -7196,6 +7323,17 @@ module.exports=PWAEachPageHasURL;
'use strict';
const ManualAudit=require('./manual-audit.js');
+const i18n=require('../../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Page transitions don\'t feel like they block on the network',
+
+description:'Transitions should feel snappy as you tap around, even on a slow network. '+
+'This experience is key to a user\'s perception of performance. [Learn more](https://web.dev/pwa-page-transitions).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7208,16 +7346,17 @@ class PWAPageTransitions extends ManualAudit{
static get meta(){
return Object.assign({
id:'pwa-page-transitions',
-description:'Transitions should feel snappy as you tap around, even on a slow network, a '+
-'key to perceived performance. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#page-transitions-dont-feel-like-they-block-on-the-network).',
-title:'Page transitions don\'t feel like they block on the network'},
+title:str_(UIStrings.title),
+description:str_(UIStrings.description)},
super.partialMeta);
}}
module.exports=PWAPageTransitions;
+module.exports.UIStrings=UIStrings;
-},{"./manual-audit.js":5}],"../audits/metrics/estimated-input-latency":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/manual/pwa-page-transitions.js");
+},{"../../lib/i18n/i18n.js":67,"./manual-audit.js":5}],"../audits/metrics/estimated-input-latency":[function(require,module,exports){
(function(__filename){
@@ -7237,7 +7376,7 @@ title:'Estimated Input Latency',
description:'Estimated Input Latency is an estimate of how long your app takes to respond to '+
'user input, in milliseconds, during the busiest 5s window of page load. If your '+
'latency is higher than 50 ms, users may perceive your app as laggy. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/estimated-input-latency).'};
+'[Learn more](https://web.dev/estimated-input-latency).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7297,7 +7436,7 @@ module.exports=EstimatedInputLatency;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/estimated-input-latency.js");
-},{"../../computed/metrics/estimated-input-latency.js":14,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/first-contentful-paint-3g":[function(require,module,exports){
+},{"../../computed/metrics/estimated-input-latency.js":14,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/first-contentful-paint-3g":[function(require,module,exports){
@@ -7363,7 +7502,7 @@ displayValue:`${metricResult.timing}\xa0ms`};
module.exports=FirstContentfulPaint3G;
-},{"../../computed/metrics/first-contentful-paint.js":15,"../../config/constants.js":45,"../audit.js":3}],"../audits/metrics/first-contentful-paint":[function(require,module,exports){
+},{"../../computed/metrics/first-contentful-paint.js":15,"../../config/constants.js":46,"../audit.js":3}],"../audits/metrics/first-contentful-paint":[function(require,module,exports){
(function(__filename){
@@ -7381,7 +7520,7 @@ const UIStrings={
title:'First Contentful Paint',
description:'First Contentful Paint marks the time at which the first text or image is '+
-`painted. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint).`};
+`painted. [Learn more](https://web.dev/first-contentful-paint).`};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7440,7 +7579,7 @@ module.exports=FirstContentfulPaint;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/first-contentful-paint.js");
-},{"../../computed/metrics/first-contentful-paint.js":15,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/first-cpu-idle":[function(require,module,exports){
+},{"../../computed/metrics/first-contentful-paint.js":15,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/first-cpu-idle":[function(require,module,exports){
(function(__filename){
@@ -7458,8 +7597,7 @@ const UIStrings={
title:'First CPU Idle',
description:'First CPU Idle marks the first time at which the page\'s main thread is '+
-'quiet enough to handle input. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-interactive).'};
+'quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7521,7 +7659,7 @@ module.exports=FirstCPUIdle;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/first-cpu-idle.js");
-},{"../../computed/metrics/first-cpu-idle.js":16,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/first-meaningful-paint":[function(require,module,exports){
+},{"../../computed/metrics/first-cpu-idle.js":16,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/first-meaningful-paint":[function(require,module,exports){
(function(__filename){
@@ -7539,7 +7677,7 @@ const UIStrings={
title:'First Meaningful Paint',
description:'First Meaningful Paint measures when the primary content of a page is '+
-'visible. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint).'};
+'visible. [Learn more](https://web.dev/first-meaningful-paint).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7601,7 +7739,7 @@ module.exports=FirstMeaningfulPaint;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/first-meaningful-paint.js");
-},{"../../computed/metrics/first-meaningful-paint.js":17,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/interactive":[function(require,module,exports){
+},{"../../computed/metrics/first-meaningful-paint.js":17,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/interactive":[function(require,module,exports){
(function(__filename){
@@ -7619,7 +7757,7 @@ const UIStrings={
title:'Time to Interactive',
description:'Time to interactive is the amount of time it takes for the page to become fully '+
-'interactive. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/consistently-interactive).'};
+'interactive. [Learn more](https://web.dev/interactive).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7696,7 +7834,7 @@ module.exports=InteractiveMetric;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/interactive.js");
-},{"../../computed/metrics/interactive.js":18,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/max-potential-fid":[function(require,module,exports){
+},{"../../computed/metrics/interactive.js":18,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/max-potential-fid":[function(require,module,exports){
(function(__filename){
@@ -7776,7 +7914,7 @@ module.exports=MaxPotentialFID;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/max-potential-fid.js");
-},{"../../computed/metrics/max-potential-fid.js":28,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/speed-index":[function(require,module,exports){
+},{"../../computed/metrics/max-potential-fid.js":29,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/speed-index":[function(require,module,exports){
(function(__filename){
@@ -7794,7 +7932,7 @@ const UIStrings={
title:'Speed Index',
description:'Speed Index shows how quickly the contents of a page are visibly populated. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index).'};
+'[Learn more](https://web.dev/speed-index).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -7855,7 +7993,7 @@ module.exports=SpeedIndex;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/speed-index.js");
-},{"../../computed/metrics/speed-index.js":30,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics/total-blocking-time":[function(require,module,exports){
+},{"../../computed/metrics/speed-index.js":31,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics/total-blocking-time":[function(require,module,exports){
(function(__filename){
@@ -7942,7 +8080,7 @@ module.exports=TotalBlockingTime;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/metrics/total-blocking-time.js");
-},{"../../computed/metrics/total-blocking-time.js":31,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/metrics":[function(require,module,exports){
+},{"../../computed/metrics/total-blocking-time.js":32,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/metrics":[function(require,module,exports){
@@ -7955,6 +8093,7 @@ const TraceOfTab=require('../computed/trace-of-tab.js');
const Speedline=require('../computed/speedline.js');
const FirstContentfulPaint=require('../computed/metrics/first-contentful-paint.js');
const FirstMeaningfulPaint=require('../computed/metrics/first-meaningful-paint.js');
+const LargestContentfulPaint=require('../computed/metrics/largest-contentful-paint.js');
const FirstCPUIdle=require('../computed/metrics/first-cpu-idle.js');
const Interactive=require('../computed/metrics/interactive.js');
const SpeedIndex=require('../computed/metrics/speed-index.js');
@@ -7992,7 +8131,6 @@ const metricComputationData={trace,devtoolsLog,settings:context.settings};
-
const requestOrUndefined=(Artifact,artifact)=>{
return Artifact.request(artifact,context).catch(_=>undefined);
};
@@ -8001,6 +8139,7 @@ const traceOfTab=await TraceOfTab.request(trace,context);
const speedline=await Speedline.request(trace,context);
const firstContentfulPaint=await FirstContentfulPaint.request(metricComputationData,context);
const firstMeaningfulPaint=await FirstMeaningfulPaint.request(metricComputationData,context);
+const largestContentfulPaint=await requestOrUndefined(LargestContentfulPaint,metricComputationData);
const firstCPUIdle=await requestOrUndefined(FirstCPUIdle,metricComputationData);
const interactive=await requestOrUndefined(Interactive,metricComputationData);
const speedIndex=await requestOrUndefined(SpeedIndex,metricComputationData);
@@ -8014,6 +8153,8 @@ firstContentfulPaint:firstContentfulPaint.timing,
firstContentfulPaintTs:firstContentfulPaint.timestamp,
firstMeaningfulPaint:firstMeaningfulPaint.timing,
firstMeaningfulPaintTs:firstMeaningfulPaint.timestamp,
+largestContentfulPaint:largestContentfulPaint&&largestContentfulPaint.timing,
+largestContentfulPaintTs:largestContentfulPaint&&largestContentfulPaint.timestamp,
firstCPUIdle:firstCPUIdle&&firstCPUIdle.timing,
firstCPUIdleTs:firstCPUIdle&&firstCPUIdle.timestamp,
interactive:interactive&&interactive.timing,
@@ -8033,6 +8174,8 @@ observedFirstContentfulPaint:traceOfTab.timings.firstContentfulPaint,
observedFirstContentfulPaintTs:traceOfTab.timestamps.firstContentfulPaint,
observedFirstMeaningfulPaint:traceOfTab.timings.firstMeaningfulPaint,
observedFirstMeaningfulPaintTs:traceOfTab.timestamps.firstMeaningfulPaint,
+observedLargestContentfulPaint:traceOfTab.timings.largestContentfulPaint,
+observedLargestContentfulPaintTs:traceOfTab.timestamps.largestContentfulPaint,
observedTraceEnd:traceOfTab.timings.traceEnd,
observedTraceEndTs:traceOfTab.timestamps.traceEnd,
observedLoad:traceOfTab.timings.load,
@@ -8060,7 +8203,7 @@ metrics[key]=Math.round(value);
const details={
type:'debugdata',
-items:[metrics]};
+items:[metrics,{lcpInvalidated:traceOfTab.lcpInvalidated}]};
return{
@@ -8108,9 +8251,13 @@ details};
+
+
+
+
module.exports=Metrics;
-},{"../computed/metrics/estimated-input-latency.js":14,"../computed/metrics/first-contentful-paint.js":15,"../computed/metrics/first-cpu-idle.js":16,"../computed/metrics/first-meaningful-paint.js":17,"../computed/metrics/interactive.js":18,"../computed/metrics/speed-index.js":30,"../computed/metrics/total-blocking-time.js":31,"../computed/speedline.js":37,"../computed/trace-of-tab.js":38,"./audit.js":3}],"../audits/mixed-content":[function(require,module,exports){
+},{"../computed/metrics/estimated-input-latency.js":14,"../computed/metrics/first-contentful-paint.js":15,"../computed/metrics/first-cpu-idle.js":16,"../computed/metrics/first-meaningful-paint.js":17,"../computed/metrics/interactive.js":18,"../computed/metrics/largest-contentful-paint.js":28,"../computed/metrics/speed-index.js":31,"../computed/metrics/total-blocking-time.js":32,"../computed/speedline.js":38,"../computed/trace-of-tab.js":39,"./audit.js":3}],"../audits/mixed-content":[function(require,module,exports){
@@ -8262,7 +8409,7 @@ details};
module.exports=MixedContent;
-},{"../computed/network-records.js":33,"../lib/url-shim.js":"url","../report/html/renderer/util.js":88,"./audit.js":3}],"../audits/network-requests":[function(require,module,exports){
+},{"../computed/network-records.js":34,"../lib/url-shim.js":"url","../report/html/renderer/util.js":88,"./audit.js":3}],"../audits/network-requests":[function(require,module,exports){
@@ -8364,7 +8511,7 @@ details:tableDetails};
module.exports=NetworkRequests;
-},{"../computed/network-records.js":33,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/network-rtt":[function(require,module,exports){
+},{"../computed/network-records.js":34,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/network-rtt":[function(require,module,exports){
(function(__filename){
@@ -8448,7 +8595,7 @@ module.exports=NetworkRTT;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/network-rtt.js");
-},{"../computed/network-analysis.js":32,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/network-server-latency":[function(require,module,exports){
+},{"../computed/network-analysis.js":33,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/network-server-latency":[function(require,module,exports){
(function(__filename){
@@ -8531,7 +8678,8 @@ module.exports=NetworkServerLatency;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/network-server-latency.js");
-},{"../computed/network-analysis.js":32,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/offline-start-url":[function(require,module,exports){
+},{"../computed/network-analysis.js":33,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/offline-start-url":[function(require,module,exports){
+(function(__filename){
@@ -8540,6 +8688,25 @@ module.exports.UIStrings=UIStrings;
'use strict';
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'`start_url` responds with a 200 when offline',
+
+failureTitle:'`start_url` does not respond with a 200 when offline',
+
+description:'A service worker enables your web app to be reliable in unpredictable '+
+'network conditions. [Learn more](https://web.dev/offline-start-url).',
+
+
+
+
+warningCantStart:'Lighthouse couldn\'t read the `start_url` from the manifest. As a result, '+
+'the `start_url` was assumed to be the document\'s URL. Error message: \'{manifestWarning}\'.'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class OfflineStartUrl extends Audit{
@@ -8548,9 +8715,9 @@ class OfflineStartUrl extends Audit{
static get meta(){
return{
id:'offline-start-url',
-title:'start_url responds with a 200 when offline',
-failureTitle:'start_url does not respond with a 200 when offline',
-description:'A service worker enables your web app to be reliable in unpredictable network conditions. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-200-when-offline).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['WebAppManifest','StartUrl']};
}
@@ -8566,8 +8733,7 @@ const warnings=[];
const manifest=artifacts.WebAppManifest;
if(manifest&&manifest.value&&manifest.value.start_url.warning){
const manifestWarning=manifest.value.start_url.warning;
-warnings.push('We couldn\'t read the start_url from the manifest. As a result, the '+
-`start_url was assumed to be the document's URL. Error message: '${manifestWarning}'.`);
+warnings.push(str_(UIStrings.warningCantStart,{manifestWarning}));
}
const hasOfflineStartUrl=artifacts.StartUrl.statusCode===200;
@@ -8581,8 +8747,10 @@ warnings};
module.exports=OfflineStartUrl;
+module.exports.UIStrings=UIStrings;
-},{"./audit.js":3}],"../audits/performance-budget":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/offline-start-url.js");
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/performance-budget":[function(require,module,exports){
(function(__filename){
@@ -8593,6 +8761,8 @@ module.exports=OfflineStartUrl;
const Audit=require('./audit.js');
const ResourceSummary=require('../computed/resource-summary.js');
+const MainResource=require('../computed/main-resource.js');
+const Budget=require('../config/budget.js');
const i18n=require('../lib/i18n/i18n.js');
const UIStrings={
@@ -8707,7 +8877,14 @@ return(b.sizeOverBudget||0)-(a.sizeOverBudget||0);
static async audit(artifacts,context){
const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
const summary=await ResourceSummary.request({devtoolsLog,URL:artifacts.URL},context);
-const budget=context.settings.budgets?context.settings.budgets[0]:undefined;
+const mainResource=await MainResource.request({URL:artifacts.URL,devtoolsLog},context);
+
+
+const budgets=Array.from(context.settings.budgets||[]);
+
+const budget=budgets?budgets.reverse().find(b=>{
+return Budget.urlMatchesPattern(mainResource.url,b.path);
+}):undefined;
if(!budget){
return{
@@ -8736,7 +8913,7 @@ module.exports=ResourceBudget;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/performance-budget.js");
-},{"../computed/resource-summary.js":35,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/predictive-perf":[function(require,module,exports){
+},{"../computed/main-resource.js":11,"../computed/resource-summary.js":36,"../config/budget.js":42,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/predictive-perf":[function(require,module,exports){
@@ -8841,6 +9018,7 @@ items:[values]}};
module.exports=PredictivePerf;
},{"../computed/metrics/lantern-estimated-input-latency.js":19,"../computed/metrics/lantern-first-contentful-paint.js":20,"../computed/metrics/lantern-first-cpu-idle.js":21,"../computed/metrics/lantern-first-meaningful-paint.js":22,"../computed/metrics/lantern-interactive.js":23,"../computed/metrics/lantern-speed-index.js":26,"../report/html/renderer/util.js":88,"./audit.js":3}],"../audits/redirects-http":[function(require,module,exports){
+(function(__filename){
@@ -8849,6 +9027,19 @@ module.exports=PredictivePerf;
'use strict';
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Redirects HTTP traffic to HTTPS',
+
+failureTitle:'Does not redirect HTTP traffic to HTTPS',
+
+description:'If you\'ve already set up HTTPS, make sure that you redirect all HTTP '+
+'traffic to HTTPS in order to enable secure web features for all your users. [Learn more](https://web.dev/redirects-http).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class RedirectsHTTP extends Audit{
@@ -8857,10 +9048,9 @@ class RedirectsHTTP extends Audit{
static get meta(){
return{
id:'redirects-http',
-title:'Redirects HTTP traffic to HTTPS',
-failureTitle:'Does not redirect HTTP traffic to HTTPS',
-description:'If you\'ve already set up HTTPS, make sure that you redirect all HTTP '+
-'traffic to HTTPS. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-redirects-to-https).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['HTTPRedirect']};
}
@@ -8877,8 +9067,10 @@ score:Number(artifacts.HTTPRedirect.value)};
module.exports=RedirectsHTTP;
+module.exports.UIStrings=UIStrings;
-},{"./audit.js":3}],"../audits/redirects":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/redirects-http.js");
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/redirects":[function(require,module,exports){
(function(__filename){
@@ -8899,7 +9091,7 @@ const UIStrings={
title:'Avoid multiple page redirects',
-description:'Redirects introduce additional delays before the page can be loaded. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/redirects).'};
+description:'Redirects introduce additional delays before the page can be loaded. [Learn more](https://web.dev/redirects).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -9008,7 +9200,7 @@ module.exports=Redirects;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/redirects.js");
-},{"../computed/main-resource.js":11,"../computed/metrics/lantern-interactive.js":23,"../computed/network-records.js":33,"../computed/trace-of-tab.js":38,"../lib/i18n/i18n.js":68,"./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/resource-summary":[function(require,module,exports){
+},{"../computed/main-resource.js":11,"../computed/metrics/lantern-interactive.js":23,"../computed/network-records.js":34,"../computed/trace-of-tab.js":39,"../lib/i18n/i18n.js":67,"./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/resource-summary":[function(require,module,exports){
(function(__filename){
@@ -9028,8 +9220,9 @@ title:'Keep request counts low and transfer sizes small',
description:'To set budgets for the quantity and size of page resources,'+
' add a budget.json file. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).',
-displayValue:`{requestCount, plural, =1 {1 request} other {# requests}}`+
-` • { byteCount, number, bytes } KB`};
+displayValue:`{requestCount, plural, `+
+`=1 {1 request • {byteCount, number, bytes} KB} `+
+`other {# requests • {byteCount, number, bytes} KB}}`};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -9115,7 +9308,7 @@ module.exports=ResourceSummary;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/resource-summary.js");
-},{"../computed/resource-summary.js":35,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/screenshot-thumbnails":[function(require,module,exports){
+},{"../computed/resource-summary.js":36,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/screenshot-thumbnails":[function(require,module,exports){
@@ -9265,7 +9458,7 @@ items:thumbnails}};
module.exports=ScreenshotThumbnails;
-},{"../computed/metrics/interactive.js":18,"../computed/speedline.js":37,"../lib/lh-error.js":72,"./audit.js":3,"jpeg-js":125}],"../audits/seo/canonical":[function(require,module,exports){
+},{"../computed/metrics/interactive.js":18,"../computed/speedline.js":38,"../lib/lh-error.js":72,"./audit.js":3,"jpeg-js":122}],"../audits/seo/canonical":[function(require,module,exports){
(function(__filename){
@@ -9286,16 +9479,31 @@ title:'Document has a valid `rel=canonical`',
failureTitle:'Document does not have a valid `rel=canonical`',
description:'Canonical links suggest which URL to show in search results. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).',
+'[Learn more](https://web.dev/canonical).',
+
+
+
explanationConflict:'Multiple conflicting URLs ({urlList})',
+
+
+
explanationInvalid:'Invalid URL ({url})',
+
+
+
explanationRelative:'Relative URL ({url})',
+
+
+
explanationPointsElsewhere:'Points to another `hreflang` location ({url})',
+
+
+
explanationDifferentDomain:'Points to a different domain ({url})',
explanationRoot:'Points to the domain\'s root URL (the homepage), '+
@@ -9432,7 +9640,7 @@ explanation:str_(UIStrings.explanationPointsElsewhere,{url:baseURL.href})};
if(!URL.rootDomainsMatch(canonicalURL,baseURL)){
return{
score:0,
-explanation:str_(UIStrings.explanationDifferentDomain,{url:canonicalURL})};
+explanation:str_(UIStrings.explanationDifferentDomain,{url:canonicalURL.href})};
}
@@ -9485,7 +9693,7 @@ module.exports=Canonical;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/canonical.js");
-},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/font-size":[function(require,module,exports){
+},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/font-size":[function(require,module,exports){
(function(__filename){
@@ -9508,7 +9716,7 @@ title:'Document uses legible font sizes',
failureTitle:'Document doesn\'t use legible font sizes',
-description:'Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/font-sizes).',
+description:'Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://web.dev/font-size).',
displayValue:'{decimalProportion, number, extendedPercent} legible text',
@@ -9831,7 +10039,7 @@ module.exports=FontSize;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/font-size.js");
-},{"../../computed/viewport-meta.js":40,"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/hreflang":[function(require,module,exports){
+},{"../../computed/viewport-meta.js":41,"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/hreflang":[function(require,module,exports){
(function(global,__filename){
@@ -9853,7 +10061,7 @@ failureTitle:'Document doesn\'t have a valid `hreflang`',
description:'hreflang links tell search engines what version of a page they should '+
'list in search results for a given language or region. [Learn more]'+
-'(https://developers.google.com/web/tools/lighthouse/audits/hreflang).'};
+'(https://web.dev/hreflang).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -9951,7 +10159,7 @@ module.exports=Hreflang;
module.exports.UIStrings=UIStrings;
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{},"/lighthouse-core/audits/seo/hreflang.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3,"axe-core/lib/core/utils/valid-langs.js":96}],"../audits/seo/http-status-code":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3,"axe-core/lib/core/utils/valid-langs.js":96}],"../audits/seo/http-status-code":[function(require,module,exports){
(function(__filename){
@@ -9973,8 +10181,7 @@ title:'Page has successful HTTP status code',
failureTitle:'Page has unsuccessful HTTP status code',
description:'Pages with unsuccessful HTTP status codes may not be indexed properly. '+
-'[Learn more]'+
-'(https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).'};
+'[Learn more](https://web.dev/http-status-code).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -10025,7 +10232,7 @@ module.exports=HTTPStatusCode;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/http-status-code.js");
-},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/seo/is-crawlable":[function(require,module,exports){
+},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/seo/is-crawlable":[function(require,module,exports){
(function(__filename){
@@ -10053,8 +10260,7 @@ title:'Page isn’t blocked from indexing',
failureTitle:'Page is blocked from indexing',
description:'Search engines are unable to include your pages in search results '+
-'if they don\'t have permission to crawl them. [Learn '+
-'more](https://developers.google.com/web/tools/lighthouse/audits/indexing).'};
+'if they don\'t have permission to crawl them. [Learn more](https://web.dev/is-crawable).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -10179,7 +10385,7 @@ module.exports=IsCrawlable;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/is-crawlable.js");
-},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3,"robots-parser":164}],"../audits/seo/link-text":[function(require,module,exports){
+},{"../../computed/main-resource.js":11,"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3,"robots-parser":161}],"../audits/seo/link-text":[function(require,module,exports){
(function(__filename){
@@ -10226,7 +10432,26 @@ const BLOCKLIST=new Set([
'este',
'enlace',
'este enlace',
-'empezar']);
+'empezar',
+
+'clique aqui',
+'inicio',
+'início',
+'ir',
+'mais informação',
+'mais informações',
+'mais',
+'veja mais',
+
+'여기',
+'여기를 클릭',
+'클릭',
+'링크',
+'자세히',
+'자세히 보기',
+'계속',
+'이동',
+'전체 보기']);
const i18n=require('../../lib/i18n/i18n.js');
@@ -10237,7 +10462,7 @@ title:'Links have descriptive text',
failureTitle:'Links do not have descriptive text',
description:'Descriptive link text helps search engines understand your content. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text).',
+'[Learn more](https://web.dev/link-text).',
displayValue:`{itemCount, plural,
=1 {1 link found}
@@ -10312,7 +10537,7 @@ module.exports=LinkText;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/link-text.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/manual/structured-data":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/manual/structured-data":[function(require,module,exports){
(function(__filename){
@@ -10326,7 +10551,7 @@ const i18n=require('../../../lib/i18n/i18n.js');
const UIStrings={
-description:'Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://developers.google.com/search/docs/guides/mark-up-content).',
+description:'Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://web.dev/structured-data).',
title:'Structured data is valid'};
@@ -10354,7 +10579,7 @@ module.exports=StructuredData;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/manual/structured-data.js");
-},{"../../../lib/i18n/i18n.js":68,"../../manual/manual-audit.js":5}],"../audits/seo/meta-description":[function(require,module,exports){
+},{"../../../lib/i18n/i18n.js":67,"../../manual/manual-audit.js":5}],"../audits/seo/meta-description":[function(require,module,exports){
(function(__filename){
@@ -10374,7 +10599,7 @@ failureTitle:'Document does not have a meta description',
description:'Meta descriptions may be included in search results to concisely summarize '+
'page content. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/description).',
+'[Learn more](https://web.dev/meta-description).',
explanation:'Description text is empty.'};
@@ -10425,7 +10650,7 @@ module.exports=Description;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/meta-description.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],"../audits/seo/plugins":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],"../audits/seo/plugins":[function(require,module,exports){
(function(__filename){
@@ -10470,7 +10695,7 @@ failureTitle:'Document uses plugins',
description:'Search engines can\'t index plugin content, and '+
'many devices restrict plugins or don\'t support them. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/plugins).'};
+'[Learn more](https://web.dev/plugins).'};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -10599,7 +10824,7 @@ module.exports=Plugins;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/plugins.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/robots-txt":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/robots-txt":[function(require,module,exports){
(function(__filename){
@@ -10643,9 +10868,12 @@ title:'robots.txt is valid',
failureTitle:'robots.txt is not valid',
description:'If your robots.txt file is malformed, crawlers may not be able to understand '+
-'how you want your website to be crawled or indexed.',
+'how you want your website to be crawled or indexed. [Learn more](https://web.dev/robots-txt).',
+
-displayValueHttpBadCode:'request for robots.txt returned HTTP status: {statusCode}',
+
+
+displayValueHttpBadCode:'Request for robots.txt returned HTTP status: {statusCode}',
displayValueValidationError:`{itemCount, plural,
=1 {1 error found}
@@ -10856,7 +11084,7 @@ module.exports=RobotsTxt;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/robots-txt.js");
-},{"../../lib/i18n/i18n.js":68,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/tap-targets":[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../../lib/url-shim.js":"url","../audit.js":3}],"../audits/seo/tap-targets":[function(require,module,exports){
(function(__filename){
@@ -10888,12 +11116,10 @@ title:'Tap targets are sized appropriately',
failureTitle:'Tap targets are not sized appropriately',
-description:'Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://developers.google.com/web/fundamentals/accessibility/accessible-styles#multi-device_responsive_design).',
+description:'Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://web.dev/tap-targets).',
tapTargetHeader:'Tap Target',
-sizeHeader:'Size',
-
overlappingTargetHeader:'Overlapping Target',
@@ -11163,7 +11389,7 @@ const tableItems=getTableItems(overlapFailuresForDisplay);
const headings=[
{key:'tapTarget',itemType:'node',text:str_(UIStrings.tapTargetHeader)},
-{key:'size',itemType:'text',text:str_(UIStrings.sizeHeader)},
+{key:'size',itemType:'text',text:str_(i18n.UIStrings.columnSize)},
{key:'overlappingTarget',itemType:'node',text:str_(UIStrings.overlappingTargetHeader)}];
@@ -11228,7 +11454,8 @@ module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/seo/tap-targets.js");
-},{"../../computed/viewport-meta.js":40,"../../lib/i18n/i18n.js":68,"../../lib/rect-helpers.js":78,"../../lib/tappable-rects.js":83,"../audit.js":3}],"../audits/service-worker":[function(require,module,exports){
+},{"../../computed/viewport-meta.js":41,"../../lib/i18n/i18n.js":67,"../../lib/rect-helpers.js":78,"../../lib/tappable-rects.js":83,"../audit.js":3}],"../audits/service-worker":[function(require,module,exports){
+(function(__filename){
@@ -11238,6 +11465,39 @@ module.exports.UIStrings=UIStrings;
const URL=require('../lib/url-shim.js');
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Registers a service worker that controls page and `start_url`',
+
+failureTitle:'Does not register a service worker that controls page and `start_url`',
+
+description:'The service worker is the technology that enables your app to use many '+
+'Progressive Web App features, such as offline, add to homescreen, and push '+
+'notifications. [Learn more](https://web.dev/service-worker).',
+
+
+
+
+explanationOutOfScope:'This origin has one or more service workers, however the page '+
+'({pageUrl}) is not in scope.',
+
+explanationNoManifest:'This page is controlled by a service worker, however '+
+'no `start_url` was found because no manifest was fetched.',
+
+explanationBadManifest:'This page is controlled by a service worker, however '+
+'no `start_url` was found because manifest failed to parse as valid JSON',
+
+
+
+
+
+explanationBadStartUrl:'This page is controlled by a service worker, however '+
+'the `start_url` ({startUrl}) is not in the service worker\'s scope ({scopeUrl})'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class ServiceWorker extends Audit{
@@ -11246,11 +11506,9 @@ class ServiceWorker extends Audit{
static get meta(){
return{
id:'service-worker',
-title:'Registers a service worker that controls page and start_url',
-failureTitle:'Does not register a service worker that controls page and start_url',
-description:'The service worker is the technology that enables your app to use many '+
-'Progressive Web App features, such as offline, add to homescreen, and push '+
-'notifications. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/registered-service-worker).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['URL','ServiceWorker','WebAppManifest']};
}
@@ -11301,15 +11559,15 @@ return pageControllingScope;
static checkStartUrl(manifest,scopeUrl){
if(!manifest){
-return'no start_url was found because no manifest was fetched';
+return str_(UIStrings.explanationNoManifest);
}
if(!manifest.value){
-return'no start_url was found because manifest failed to parse as valid JSON';
+return str_(UIStrings.explanationBadManifest);
}
const startUrl=manifest.value.start_url.value;
if(!startUrl.startsWith(scopeUrl)){
-return`the start_url ("${startUrl}") is not in the service worker's scope ("${scopeUrl}")`;
+return str_(UIStrings.explanationBadStartUrl,{startUrl,scopeUrl});
}
}
@@ -11334,7 +11592,7 @@ registrations,pageUrl);
if(!controllingScopeUrl){
return{
score:0,
-explanation:`This origin has one or more service workers, however the page ("${pageUrl.href}") is not in scope.`};
+explanation:str_(UIStrings.explanationOutOfScope,{pageUrl:pageUrl.href})};
}
@@ -11343,7 +11601,7 @@ controllingScopeUrl);
if(startUrlFailure){
return{
score:0,
-explanation:`This page is controlled by a service worker, however ${startUrlFailure}.`};
+explanation:startUrlFailure};
}
@@ -11355,8 +11613,11 @@ score:1};
module.exports=ServiceWorker;
+module.exports.UIStrings=UIStrings;
-},{"../lib/url-shim.js":"url","./audit.js":3}],"../audits/splash-screen":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/service-worker.js");
+},{"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3}],"../audits/splash-screen":[function(require,module,exports){
+(function(__filename){
@@ -11366,6 +11627,20 @@ module.exports=ServiceWorker;
const MultiCheckAudit=require('./multi-check-audit.js');
const ManifestValues=require('../computed/manifest-values.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Configured for a custom splash screen',
+
+failureTitle:'Is not configured for a custom splash screen',
+
+description:'A themed splash screen ensures a high-quality experience when '+
+'users launch your app from their homescreens. [Learn '+
+'more](https://web.dev/splash-screen).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -11387,11 +11662,9 @@ class SplashScreen extends MultiCheckAudit{
static get meta(){
return{
id:'splash-screen',
-title:'Configured for a custom splash screen',
-failureTitle:'Is not configured for a custom splash screen',
-description:'A themed splash screen ensures a high-quality experience when '+
-'users launch your app from their homescreens. [Learn '+
-'more](https://developers.google.com/web/tools/lighthouse/audits/custom-splash-screen).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['WebAppManifest']};
}
@@ -11442,8 +11715,11 @@ manifestValues};
module.exports=SplashScreen;
+module.exports.UIStrings=UIStrings;
-},{"../computed/manifest-values.js":13,"./multi-check-audit.js":6}],"../audits/themed-omnibox":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/splash-screen.js");
+},{"../computed/manifest-values.js":13,"../lib/i18n/i18n.js":67,"./multi-check-audit.js":6}],"../audits/themed-omnibox":[function(require,module,exports){
+(function(__filename){
@@ -11454,6 +11730,19 @@ module.exports=SplashScreen;
const MultiCheckAudit=require('./multi-check-audit.js');
const ManifestValues=require('../computed/manifest-values.js');
const cssParsers=require('cssstyle/lib/parsers');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Sets a theme color for the address bar.',
+
+failureTitle:'Does not set a theme color for the address bar.',
+
+description:'The browser address bar can be themed to match your site. '+
+'[Learn more](https://web.dev/themed-omnibox).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
@@ -11472,10 +11761,9 @@ class ThemedOmnibox extends MultiCheckAudit{
static get meta(){
return{
id:'themed-omnibox',
-title:'Sets an address-bar theme color',
-failureTitle:'Does not set an address-bar theme color',
-description:'The browser address bar can be themed to match your site. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/address-bar).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['WebAppManifest','MetaElements']};
}
@@ -11494,6 +11782,7 @@ return cssParsers.valueType(color)===cssParsers.TYPES.COLOR;
static assessMetaThemecolor(themeColorMeta,failures){
if(!themeColorMeta){
+
failures.push('No `<meta name="theme-color">` tag found');
}else if(!ThemedOmnibox.isValidColor(themeColorMeta.content||'')){
failures.push('The theme-color meta tag did not contain a valid CSS color');
@@ -11539,8 +11828,10 @@ themeColor:themeColorMeta&&themeColorMeta.content||null};
module.exports=ThemedOmnibox;
+module.exports.UIStrings=UIStrings;
-},{"../computed/manifest-values.js":13,"./multi-check-audit.js":6,"cssstyle/lib/parsers":105}],"../audits/third-party-summary":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/themed-omnibox.js");
+},{"../computed/manifest-values.js":13,"../lib/i18n/i18n.js":67,"./multi-check-audit.js":6,"cssstyle/lib/parsers":105}],"../audits/third-party-summary":[function(require,module,exports){
(function(__filename){
@@ -11559,7 +11850,9 @@ const MainThreadTasks=require('../computed/main-thread-tasks.js');
const UIStrings={
-title:'Third-Party Usage',
+title:'Minimize third-party usage',
+
+failureTitle:'Reduce the impact of third-party code',
description:'Third-party code can significantly impact load performance. '+
'Limit the number of redundant third-party providers and try to load third-party code after '+
@@ -11567,17 +11860,18 @@ description:'Third-party code can significantly impact load performance. '+
columnThirdParty:'Third-Party',
-columnMainThreadTime:'Main Thread Time',
+columnBlockingTime:'Main-Thread Blocking Time',
-displayValue:`{itemCount, plural,
- =1 {1 Third-Party Found}
- other {# Third-Parties Found}
- }`};
+displayValue:'Third-party code blocked the main thread for '+
+`{timeInMs, number, milliseconds}\xa0ms`};
const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+const PASS_THRESHOLD_IN_MS=250;
+
+
class ThirdPartySummary extends Audit{
@@ -11587,8 +11881,8 @@ static get meta(){
return{
id:'third-party-summary',
title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
description:str_(UIStrings.description),
-scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
requiredArtifacts:['traces','devtoolsLogs']};
}
@@ -11618,12 +11912,13 @@ return undefined;
static getSummaryByEntity(networkRecords,mainThreadTasks,cpuMultiplier){
const entities=new Map();
+const defaultEntityStat={mainThreadTime:0,blockingTime:0,transferSize:0};
for(const request of networkRecords){
const entity=ThirdPartySummary.getEntitySafe(request.url);
if(!entity)continue;
-const entityStats=entities.get(entity)||{mainThreadTime:0,transferSize:0};
+const entityStats=entities.get(entity)||{...defaultEntityStat};
entityStats.transferSize+=request.transferSize;
entities.set(entity,entityStats);
}
@@ -11635,8 +11930,14 @@ const attributeableURL=BootupTime.getAttributableURLForTask(task,jsURLs);
const entity=ThirdPartySummary.getEntitySafe(attributeableURL);
if(!entity)continue;
-const entityStats=entities.get(entity)||{mainThreadTime:0,transferSize:0};
-entityStats.mainThreadTime+=task.selfTime*cpuMultiplier;
+const entityStats=entities.get(entity)||{...defaultEntityStat};
+const taskDuration=task.selfTime*cpuMultiplier;
+
+entityStats.mainThreadTime+=taskDuration;
+
+
+
+entityStats.blockingTime+=Math.max(taskDuration-50,0);
entities.set(entity,entityStats);
}
@@ -11661,15 +11962,10 @@ const summaryByEntity=ThirdPartySummary.getSummaryByEntity(networkRecords,tasks,
const summary={wastedBytes:0,wastedMs:0};
-
-
-
-const computeSortValue=stats=>stats.transferSize/1024+stats.mainThreadTime;
-
const results=Array.from(summaryByEntity.entries()).
map(([entity,stats])=>{
summary.wastedBytes+=stats.transferSize;
-summary.wastedMs+=stats.mainThreadTime;
+summary.wastedMs+=stats.blockingTime;
return{
entity:{
@@ -11678,18 +11974,20 @@ text:entity.name,
url:entity.homepage||''},
transferSize:stats.transferSize,
-mainThreadTime:stats.mainThreadTime};
+mainThreadTime:stats.mainThreadTime,
+blockingTime:stats.blockingTime};
}).
-sort((a,b)=>computeSortValue(b)-computeSortValue(a));
+
+sort((a,b)=>b.blockingTime-a.blockingTime||b.transferSize-a.transferSize);
const headings=[
{key:'entity',itemType:'link',text:str_(UIStrings.columnThirdParty)},
{key:'transferSize',granularity:1,itemType:'bytes',
text:str_(i18n.UIStrings.columnSize)},
-{key:'mainThreadTime',granularity:1,itemType:'ms',
-text:str_(UIStrings.columnMainThreadTime)}];
+{key:'blockingTime',granularity:1,itemType:'ms',
+text:str_(UIStrings.columnBlockingTime)}];
if(!results.length){
@@ -11700,8 +11998,10 @@ notApplicable:true};
}
return{
-score:Number(results.length===0),
-displayValue:str_(UIStrings.displayValue,{itemCount:results.length}),
+score:Number(summary.wastedMs<=PASS_THRESHOLD_IN_MS),
+displayValue:str_(UIStrings.displayValue,{
+timeInMs:summary.wastedMs}),
+
details:Audit.makeTableDetails(headings,results,summary)};
}}
@@ -11711,7 +12011,7 @@ module.exports=ThirdPartySummary;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/third-party-summary.js");
-},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":33,"../lib/i18n/i18n.js":68,"./audit.js":3,"./bootup-time.js":"../audits/bootup-time","third-party-web/httparchive-nostats-subset":172}],"../audits/time-to-first-byte":[function(require,module,exports){
+},{"../computed/main-thread-tasks.js":12,"../computed/network-records.js":34,"../lib/i18n/i18n.js":67,"./audit.js":3,"./bootup-time.js":"../audits/bootup-time","third-party-web/httparchive-nostats-subset":169}],"../audits/time-to-first-byte":[function(require,module,exports){
(function(__filename){
@@ -11731,7 +12031,7 @@ title:'Server response times are low (TTFB)',
failureTitle:'Reduce server response times (TTFB)',
description:'Time To First Byte identifies the time at which your server sends a response.'+
-' [Learn more](https://developers.google.com/web/tools/lighthouse/audits/ttfb).',
+' [Learn more](https://web.dev/time-to-first-byte).',
displayValue:`Root document took {timeInMs, number, milliseconds}\xa0ms`};
@@ -11801,7 +12101,7 @@ module.exports=TTFBMetric;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/time-to-first-byte.js");
-},{"../computed/main-resource.js":11,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/user-timings":[function(require,module,exports){
+},{"../computed/main-resource.js":11,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/user-timings":[function(require,module,exports){
(function(__filename){
@@ -11820,15 +12120,13 @@ title:'User Timing marks and measures',
description:'Consider instrumenting your app with the User Timing API to measure your '+
'app\'s real-world performance during key user experiences. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/user-timing).',
+'[Learn more](https://web.dev/user-timings).',
displayValue:`{itemCount, plural,
=1 {1 user timing}
other {# user timings}
}`,
-columnName:'Name',
-
columnType:'Type',
columnStartTime:'Start Time',
@@ -11901,7 +12199,7 @@ return 1;
const headings=[
-{key:'name',itemType:'text',text:str_(UIStrings.columnName)},
+{key:'name',itemType:'text',text:str_(i18n.UIStrings.columnName)},
{key:'timingType',itemType:'text',text:str_(UIStrings.columnType)},
{key:'startTime',itemType:'ms',granularity:0.01,
text:str_(UIStrings.columnStartTime)},
@@ -11934,7 +12232,7 @@ module.exports=UserTimings;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/user-timings.js");
-},{"../computed/user-timings.js":39,"../lib/i18n/i18n.js":68,"./audit.js":3}],"../audits/uses-rel-preconnect":[function(require,module,exports){
+},{"../computed/user-timings.js":40,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/uses-rel-preconnect":[function(require,module,exports){
(function(__filename){
@@ -11965,8 +12263,11 @@ const UIStrings={
title:'Preconnect to required origins',
description:
-'Consider adding preconnect or dns-prefetch resource hints to establish early '+
-`connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).`,
+'Consider adding `preconnect` or `dns-prefetch` resource hints to establish early '+
+`connections to important third-party origins. [Learn more](https://web.dev/uses-rel-preconnect).`,
+
+
+
crossoriginWarning:'A preconnect <link> was found for "{securityOrigin}" but was not used '+
'by the browser. Check that you are using the `crossorigin` attribute properly.'};
@@ -12143,7 +12444,7 @@ module.exports=UsesRelPreconnectAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/uses-rel-preconnect.js");
-},{"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/network-records.js":33,"../lib/i18n/i18n.js":68,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/uses-rel-preload":[function(require,module,exports){
+},{"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/network-records.js":34,"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/uses-rel-preload":[function(require,module,exports){
(function(__filename){
@@ -12165,8 +12466,11 @@ const UIStrings={
title:'Preload key requests',
-description:'Consider using <link rel=preload> to prioritize fetching resources that are '+
-'currently requested later in page load. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/preload).',
+description:'Consider using `<link rel=preload>` to prioritize fetching resources that are '+
+'currently requested later in page load. [Learn more](https://web.dev/uses-rel-preload).',
+
+
+
crossoriginWarning:'A preload <link> was found for "{preloadURL}" but was not used '+
'by the browser. Check that you are using the `crossorigin` attribute properly.'};
@@ -12386,7 +12690,8 @@ module.exports=UsesRelPreloadAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/uses-rel-preload.js");
-},{"../computed/critical-request-chains.js":9,"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/page-dependency-graph.js":34,"../lib/i18n/i18n.js":68,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/viewport":[function(require,module,exports){
+},{"../computed/critical-request-chains.js":9,"../computed/load-simulator.js":10,"../computed/main-resource.js":11,"../computed/page-dependency-graph.js":35,"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3,"./byte-efficiency/byte-efficiency-audit.js":4}],"../audits/viewport":[function(require,module,exports){
+(function(__filename){
@@ -12396,6 +12701,22 @@ module.exports.UIStrings=UIStrings;
const Audit=require('./audit.js');
const ComputedViewportMeta=require('../computed/viewport-meta.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Has a `<meta name="viewport">` tag with `width` or `initial-scale`',
+
+failureTitle:'Does not have a `<meta name="viewport">` tag with `width` '+
+'or `initial-scale`',
+
+description:'Add a `<meta name="viewport">` tag to optimize your app for mobile screens. '+
+'[Learn more](https://web.dev/viewport).',
+
+explanationNoTag:'No `<meta name="viewport">` tag found'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class Viewport extends Audit{
@@ -12404,11 +12725,9 @@ class Viewport extends Audit{
static get meta(){
return{
id:'viewport',
-title:'Has a `<meta name="viewport">` tag with `width` or `initial-scale`',
-failureTitle:'Does not have a `<meta name="viewport">` tag with `width` '+
-'or `initial-scale`',
-description:'Add a viewport meta tag to optimize your app for mobile screens. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/has-viewport-meta-tag).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['MetaElements']};
}
@@ -12424,7 +12743,7 @@ const viewportMeta=await ComputedViewportMeta.request(artifacts.MetaElements,con
if(!viewportMeta.hasViewportTag){
return{
score:0,
-explanation:'No viewport meta tag found'};
+explanation:str_(UIStrings.explanationNoTag)};
}
@@ -12436,8 +12755,11 @@ warnings:viewportMeta.parserWarnings};
module.exports=Viewport;
+module.exports.UIStrings=UIStrings;
-},{"../computed/viewport-meta.js":40,"./audit.js":3}],"../audits/without-javascript":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/viewport.js");
+},{"../computed/viewport-meta.js":41,"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/without-javascript":[function(require,module,exports){
+(function(__filename){
@@ -12446,6 +12768,22 @@ module.exports=Viewport;
'use strict';
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Contains some content when JavaScript is not available',
+
+failureTitle:'Does not provide fallback content when JavaScript is not available',
+
+description:'Your app should display some content when JavaScript is disabled, even if '+
+'it\'s just a warning to the user that JavaScript is required to use the app. '+
+'[Learn more](https://web.dev/without-javascript).',
+
+explanation:'The page body should render some content if its scripts are not available.'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class WithoutJavaScript extends Audit{
@@ -12454,11 +12792,9 @@ class WithoutJavaScript extends Audit{
static get meta(){
return{
id:'without-javascript',
-title:'Contains some content when JavaScript is not available',
-failureTitle:'Does not provide fallback content when JavaScript is not available',
-description:'Your app should display some content when JavaScript is disabled, even if '+
-'it\'s just a warning to the user that JavaScript is required to use the app. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/no-js).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['HTMLWithoutJavaScript']};
}
@@ -12474,7 +12810,7 @@ const artifact=artifacts.HTMLWithoutJavaScript;
if(artifact.bodyText.trim()===''&&!artifact.hasNoScript){
return{
score:0,
-explanation:'The page body should render some content if its scripts are not available.'};
+explanation:str_(UIStrings.explanation)};
}
@@ -12485,8 +12821,11 @@ score:1};
module.exports=WithoutJavaScript;
+module.exports.UIStrings=UIStrings;
-},{"./audit.js":3}],"../audits/works-offline":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/without-javascript.js");
+},{"../lib/i18n/i18n.js":67,"./audit.js":3}],"../audits/works-offline":[function(require,module,exports){
+(function(__filename){
@@ -12496,6 +12835,28 @@ module.exports=WithoutJavaScript;
const URL=require('../lib/url-shim.js');
const Audit=require('./audit.js');
+const i18n=require('../lib/i18n/i18n.js');
+
+const UIStrings={
+
+title:'Current page responds with a 200 when offline',
+
+failureTitle:'Current page does not respond with a 200 when offline',
+
+description:'If you\'re building a Progressive Web App, consider using a service worker '+
+'so that your app can work offline. '+
+'[Learn more](https://web.dev/works-offline).',
+
+
+
+
+
+warningNoLoad:'The page may not be loading offline because your test URL '+
+`({requested}) was redirected to "{final}". `+
+'Try testing the second URL directly.'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
class WorksOffline extends Audit{
@@ -12504,11 +12865,9 @@ class WorksOffline extends Audit{
static get meta(){
return{
id:'works-offline',
-title:'Current page responds with a 200 when offline',
-failureTitle:'Current page does not respond with a 200 when offline',
-description:'If you\'re building a Progressive Web App, consider using a service worker '+
-'so that your app can work offline. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-200-when-offline).',
+title:str_(UIStrings.title),
+failureTitle:str_(UIStrings.failureTitle),
+description:str_(UIStrings.description),
requiredArtifacts:['Offline','URL']};
}
@@ -12522,9 +12881,8 @@ const warnings=[];
const passed=artifacts.Offline===200;
if(!passed&&
!URL.equalWithExcludedFragments(artifacts.URL.requestedUrl,artifacts.URL.finalUrl)){
-warnings.push('You may be not loading offline because your test URL '+
-`(${artifacts.URL.requestedUrl}) was redirected to "${artifacts.URL.finalUrl}". `+
-'Try testing the second URL directly.');
+warnings.push(str_(UIStrings.warningNoLoad,
+{requested:artifacts.URL.requestedUrl,final:artifacts.URL.finalUrl}));
}
return{
@@ -12535,8 +12893,10 @@ warnings};
module.exports=WorksOffline;
+module.exports.UIStrings=UIStrings;
-},{"../lib/url-shim.js":"url","./audit.js":3}],"../gather/gatherers/accessibility":[function(require,module,exports){
+}).call(this,"/lighthouse-core/audits/works-offline.js");
+},{"../lib/i18n/i18n.js":67,"../lib/url-shim.js":"url","./audit.js":3}],"../gather/gatherers/accessibility":[function(require,module,exports){
@@ -12639,7 +12999,7 @@ return returnedValue;
module.exports=Accessibility;
-},{"../../lib/page-functions.js":77,"./gatherer.js":53}],"../gather/gatherers/anchor-elements":[function(require,module,exports){
+},{"../../lib/page-functions.js":77,"./gatherer.js":54}],"../gather/gatherers/anchor-elements":[function(require,module,exports){
@@ -12721,7 +13081,7 @@ return driver.evaluateAsync(expression,{useIsolation:true});
module.exports=AnchorElements;
-},{"../../lib/page-functions.js":77,"./gatherer.js":53}],"../gather/gatherers/cache-contents":[function(require,module,exports){
+},{"../../lib/page-functions.js":77,"./gatherer.js":54}],"../gather/gatherers/cache-contents":[function(require,module,exports){
@@ -12782,7 +13142,7 @@ return cacheUrls;
module.exports=CacheContents;
-},{"./gatherer.js":53}],"../gather/gatherers/console-messages":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/console-messages":[function(require,module,exports){
@@ -12838,7 +13198,7 @@ return this._logEntries;
module.exports=ConsoleMessages;
-},{"./gatherer.js":53}],"../gather/gatherers/css-usage":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/css-usage":[function(require,module,exports){
@@ -12899,7 +13259,7 @@ stylesheets:Array.from(dedupedStylesheets.values())};
module.exports=CSSUsage;
-},{"./gatherer.js":53}],"../gather/gatherers/dobetterweb/appcache":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/dobetterweb/appcache":[function(require,module,exports){
@@ -12926,7 +13286,7 @@ then(node=>node&&node.getAttribute('manifest'));
module.exports=AppCacheManifest;
-},{"../gatherer.js":53}],"../gather/gatherers/dobetterweb/doctype":[function(require,module,exports){
+},{"../gatherer.js":54}],"../gather/gatherers/dobetterweb/doctype":[function(require,module,exports){
@@ -12964,7 +13324,7 @@ return driver.evaluateAsync(`(${getDoctype.toString()}())`);
module.exports=Doctype;
-},{"../gatherer.js":53}],"../gather/gatherers/dobetterweb/domstats":[function(require,module,exports){
+},{"../gatherer.js":54}],"../gather/gatherers/dobetterweb/domstats":[function(require,module,exports){
@@ -13127,7 +13487,7 @@ return results;
module.exports=DOMStats;
-},{"../../../lib/page-functions.js":77,"../gatherer.js":53}],"../gather/gatherers/dobetterweb/optimized-images":[function(require,module,exports){
+},{"../../../lib/page-functions.js":77,"../gatherer.js":54}],"../gather/gatherers/dobetterweb/optimized-images":[function(require,module,exports){
@@ -13140,6 +13500,7 @@ module.exports=DOMStats;
'use strict';
+const log=require('lighthouse-logger');
const Gatherer=require('../gatherer.js');
const URL=require('../../../lib/url-shim.js');
const NetworkRequest=require('../../../lib/network-request.js');
@@ -13254,6 +13615,8 @@ const stats=await this.calculateImageStats(driver,record);
const image={failed:false,...stats,...record};
results.push(image);
}catch(err){
+log.warn('optimized-images',err.message);
+
Sentry.captureException(err,{
@@ -13297,7 +13660,7 @@ return results;
module.exports=OptimizedImages;
-},{"../../../lib/network-request.js":76,"../../../lib/sentry.js":79,"../../../lib/url-shim.js":"url","../../driver.js":51,"../gatherer.js":53}],"../gather/gatherers/dobetterweb/password-inputs-with-prevented-paste":[function(require,module,exports){
+},{"../../../lib/network-request.js":76,"../../../lib/sentry.js":79,"../../../lib/url-shim.js":"url","../../driver.js":52,"../gatherer.js":54,"lighthouse-logger":125}],"../gather/gatherers/dobetterweb/password-inputs-with-prevented-paste":[function(require,module,exports){
@@ -13344,7 +13707,7 @@ return passContext.driver.evaluateAsync(`(() => {
module.exports=PasswordInputsWithPreventedPaste;
-},{"../../../lib/page-functions.js":77,"../gatherer.js":53}],"../gather/gatherers/dobetterweb/response-compression":[function(require,module,exports){
+},{"../../../lib/page-functions.js":77,"../gatherer.js":54}],"../gather/gatherers/dobetterweb/response-compression":[function(require,module,exports){
(function(Buffer){
@@ -13470,7 +13833,7 @@ return record;
module.exports=ResponseCompression;
}).call(this,require("buffer").Buffer);
-},{"../../../lib/network-request.js":76,"../../../lib/sentry.js":79,"../../../lib/url-shim.js":"url","../gatherer.js":53,"buffer":102,"zlib":100}],"../gather/gatherers/dobetterweb/tags-blocking-first-paint":[function(require,module,exports){
+},{"../../../lib/network-request.js":76,"../../../lib/sentry.js":79,"../../../lib/url-shim.js":"url","../gatherer.js":54,"buffer":102,"zlib":100}],"../gather/gatherers/dobetterweb/tags-blocking-first-paint":[function(require,module,exports){
@@ -13663,7 +14026,7 @@ return TagsBlockingFirstPaint.findBlockingTags(passContext.driver,loadData.netwo
module.exports=TagsBlockingFirstPaint;
-},{"../../driver.js":51,"../gatherer.js":53}],"../gather/gatherers/html-without-javascript":[function(require,module,exports){
+},{"../../driver.js":52,"../gatherer.js":54}],"../gather/gatherers/html-without-javascript":[function(require,module,exports){
@@ -13721,7 +14084,7 @@ hasNoScript};
module.exports=HTMLWithoutJavaScript;
-},{"./gatherer.js":53}],"../gather/gatherers/http-redirect":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/http-redirect":[function(require,module,exports){
@@ -13768,7 +14131,64 @@ value:isHttps};
module.exports=HTTPRedirect;
-},{"./gatherer.js":53}],"../gather/gatherers/image-elements":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/iframe-elements":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Gatherer=require('./gatherer.js');
+const pageFunctions=require('../../lib/page-functions.js');
+
+
+
+
+
+
+
+function collectIFrameElements(){
+
+const iFrameElements=getElementsInDocument('iframe');
+return iFrameElements.map(node=>{
+const clientRect=node.getBoundingClientRect();
+const{top,bottom,left,right,width,height}=clientRect;
+return{
+id:node.id,
+src:node.src,
+clientRect:{top,bottom,left,right,width,height},
+
+isPositionFixed:isPositionFixed(node)};
+
+});
+}
+
+class IFrameElements extends Gatherer{
+
+
+
+
+
+async afterPass(passContext){
+const driver=passContext.driver;
+
+const expression=`(() => {
+ ${pageFunctions.getOuterHTMLSnippetString};
+ ${pageFunctions.getElementsInDocumentString};
+ ${pageFunctions.isPositionFixedString};
+ return (${collectIFrameElements})();
+ })()`;
+
+
+const iframeElements=await driver.evaluateAsync(expression,{useIsolation:true});
+return iframeElements;
+}}
+
+
+module.exports=IFrameElements;
+
+},{"../../lib/page-functions.js":77,"./gatherer.js":54}],"../gather/gatherers/image-elements":[function(require,module,exports){
@@ -13901,6 +14321,12 @@ img.src=url;
}
class ImageElements extends Gatherer{
+constructor(){
+super();
+
+this._naturalSizeCache=new Map();
+}
+
@@ -13908,11 +14334,16 @@ class ImageElements extends Gatherer{
async fetchElementWithSizeInformation(driver,element){
const url=JSON.stringify(element.src);
+if(this._naturalSizeCache.has(url)){
+return Object.assign(element,this._naturalSizeCache.get(url));
+}
+
try{
driver.setNextProtocolTimeout(250);
const size=await driver.evaluateAsync(`(${determineNaturalSize.toString()})(${url})`);
+this._naturalSizeCache.set(url,size);
return Object.assign(element,size);
}catch(_){
@@ -13989,7 +14420,7 @@ return imageUsage;
module.exports=ImageElements;
-},{"../../lib/page-functions.js":77,"../driver.js":51,"./gatherer.js":53}],"../gather/gatherers/js-usage":[function(require,module,exports){
+},{"../../lib/page-functions.js":77,"../driver.js":52,"./gatherer.js":54}],"../gather/gatherers/js-usage":[function(require,module,exports){
@@ -14027,7 +14458,7 @@ return coverageResponse.result;
module.exports=JsUsage;
-},{"./gatherer.js":53}],"../gather/gatherers/link-elements":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/link-elements":[function(require,module,exports){
@@ -14039,8 +14470,9 @@ const Gatherer=require('./gatherer.js');
const URL=require('../../lib/url-shim.js').URL;
const NetworkAnalyzer=require('../../lib/dependency-graph/simulator/network-analyzer.js');
const LinkHeader=require('http-link-header');
-const getElementsInDocumentString=require('../../lib/page-functions.js').
-getElementsInDocumentString;
+const{getElementsInDocumentString}=require('../../lib/page-functions.js');
+
+
@@ -14072,6 +14504,36 @@ if(value==='use-credentials')return'use-credentials';
return null;
}
+
+
+
+
+function getLinkElementsInDOM(){
+
+
+const browserElements=getElementsInDocument('link');
+
+const linkElements=[];
+
+for(const link of browserElements){
+
+
+if(!(link instanceof HTMLLinkElement))continue;
+
+linkElements.push({
+rel:link.rel,
+href:link.href,
+hrefRaw:link.href,
+hreflang:link.hreflang,
+as:link.as,
+crossOrigin:link.crossOrigin,
+source:link.closest('head')?'head':'body'});
+
+}
+
+return linkElements;
+}
+
class LinkElements extends Gatherer{
@@ -14082,18 +14544,9 @@ static getLinkElementsInDOM(passContext){
return passContext.driver.evaluateAsync(`(() => {
${getElementsInDocumentString};
+ ${getLinkElementsInDOM};
- return getElementsInDocument('link').map(link => {
- return {
- rel: link.rel,
- href: link.href,
- hrefRaw: link.href,
- hreflang: link.hreflang,
- as: link.as,
- crossOrigin: link.crossOrigin,
- source: link.closest('head') ? 'head' : 'body',
- };
- });
+ return getLinkElementsInDOM();
})()`,{useIsolation:true});
}
@@ -14150,7 +14603,37 @@ return linkElements;
module.exports=LinkElements;
-},{"../../lib/dependency-graph/simulator/network-analyzer.js":62,"../../lib/page-functions.js":77,"../../lib/url-shim.js":"url","./gatherer.js":53,"http-link-header":109}],"../gather/gatherers/meta-elements":[function(require,module,exports){
+},{"../../lib/dependency-graph/simulator/network-analyzer.js":63,"../../lib/page-functions.js":77,"../../lib/url-shim.js":"url","./gatherer.js":54,"http-link-header":109}],"../gather/gatherers/main-document-content":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Gatherer=require('./gatherer.js');
+const NetworkAnalyzer=require('../../lib/dependency-graph/simulator/network-analyzer.js');
+
+
+
+
+class MainDocumentContent extends Gatherer{
+
+
+
+
+
+async afterPass(passContext,loadData){
+const mainResource=NetworkAnalyzer.findMainDocument(loadData.networkRecords,passContext.url);
+
+const driver=passContext.driver;
+return driver.getRequestContent(mainResource.requestId);
+}}
+
+
+module.exports=MainDocumentContent;
+
+},{"../../lib/dependency-graph/simulator/network-analyzer.js":63,"./gatherer.js":54}],"../gather/gatherers/meta-elements":[function(require,module,exports){
@@ -14186,7 +14669,7 @@ return driver.evaluateAsync(`(() => {
module.exports=MetaElements;
-},{"../../lib/page-functions.js":77,"./gatherer.js":53}],"../gather/gatherers/mixed-content":[function(require,module,exports){
+},{"../../lib/page-functions.js":77,"./gatherer.js":54}],"../gather/gatherers/mixed-content":[function(require,module,exports){
(function(Buffer){
@@ -14310,7 +14793,7 @@ return{url:passContext.url};
module.exports=MixedContent;
}).call(this,require("buffer").Buffer);
-},{"../../lib/url-shim.js":"url","../driver.js":51,"./gatherer.js":53,"buffer":102}],"../gather/gatherers/offline":[function(require,module,exports){
+},{"../../lib/url-shim.js":"url","../driver.js":52,"./gatherer.js":54,"buffer":102}],"../gather/gatherers/offline":[function(require,module,exports){
@@ -14326,6 +14809,9 @@ class Offline extends Gatherer{
beforePass(passContext){
+
+
+
return passContext.driver.goOffline();
}
@@ -14334,20 +14820,19 @@ return passContext.driver.goOffline();
-afterPass(passContext,loadData){
+async afterPass(passContext,loadData){
const navigationRecord=loadData.networkRecords.filter(record=>{
return URL.equalWithExcludedFragments(record.url,passContext.url)&&
record.fetchedViaServiceWorker;
}).pop();
-return passContext.driver.goOnline(passContext).
-then(_=>navigationRecord?navigationRecord.statusCode:-1);
+return navigationRecord?navigationRecord.statusCode:-1;
}}
module.exports=Offline;
-},{"../../lib/url-shim.js":"url","./gatherer.js":53}],"../gather/gatherers/runtime-exceptions":[function(require,module,exports){
+},{"../../lib/url-shim.js":"url","./gatherer.js":54}],"../gather/gatherers/runtime-exceptions":[function(require,module,exports){
@@ -14397,7 +14882,7 @@ return this._exceptions;
module.exports=RuntimeExceptions;
-},{"./gatherer.js":53}],"../gather/gatherers/script-elements":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/script-elements":[function(require,module,exports){
@@ -14426,6 +14911,7 @@ return scripts.map(script=>{
return{
type:script.type||null,
src:script.src||null,
+id:script.id||null,
async:script.async,
defer:script.defer,
source:script.closest('head')?'head':'body',
@@ -14481,6 +14967,7 @@ scripts.push({
devtoolsNodePath:'',
type:null,
src:record.url,
+id:null,
async:false,
defer:false,
source:'network',
@@ -14497,7 +14984,7 @@ return scripts;
module.exports=ScriptElements;
-},{"../../lib/dependency-graph/simulator/network-analyzer.js":62,"../../lib/network-request.js":76,"../../lib/page-functions.js":77,"./gatherer.js":53}],"../gather/gatherers/seo/embedded-content":[function(require,module,exports){
+},{"../../lib/dependency-graph/simulator/network-analyzer.js":63,"../../lib/network-request.js":76,"../../lib/page-functions.js":77,"./gatherer.js":54}],"../gather/gatherers/seo/embedded-content":[function(require,module,exports){
@@ -14540,7 +15027,7 @@ return passContext.driver.evaluateAsync(expression);
module.exports=EmbeddedContent;
-},{"../../../lib/page-functions.js":77,"../gatherer.js":53}],"../gather/gatherers/seo/font-size":[function(require,module,exports){
+},{"../../../lib/page-functions.js":77,"../gatherer.js":54}],"../gather/gatherers/seo/font-size":[function(require,module,exports){
@@ -14705,7 +15192,7 @@ if(directRule)return directRule;
-function getEffectiveFontRule({inlineStyle,matchedCSSRules,inherited}){
+function getEffectiveFontRule({attributesStyle,inlineStyle,matchedCSSRules,inherited}){
if(hasFontSizeDeclaration(inlineStyle))return{type:'Inline',...inlineStyle};
@@ -14714,6 +15201,9 @@ const matchedRule=findMostSpecificMatchedCSSRule(matchedCSSRules);
if(matchedRule)return matchedRule;
+if(hasFontSizeDeclaration(attributesStyle))return{type:'Attributes',...attributesStyle};
+
+
const inheritedRule=findInheritedCSSRule(inherited);
if(inheritedRule)return inheritedRule;
@@ -14903,7 +15393,7 @@ module.exports.TEXT_NODE_TYPE=TEXT_NODE_TYPE;
module.exports.computeSelectorSpecificity=computeSelectorSpecificity;
module.exports.getEffectiveFontRule=getEffectiveFontRule;
-},{"../../../lib/sentry.js":79,"../gatherer.js":53}],"../gather/gatherers/seo/robots-txt":[function(require,module,exports){
+},{"../../../lib/sentry.js":79,"../gatherer.js":54}],"../gather/gatherers/seo/robots-txt":[function(require,module,exports){
@@ -14944,7 +15434,7 @@ return passContext.driver.evaluateAsync(`(${getRobotsTxtContent.toString()}())`)
module.exports=RobotsTxt;
-},{"../gatherer.js":53}],"../gather/gatherers/seo/tap-targets":[function(require,module,exports){
+},{"../gatherer.js":54}],"../gather/gatherers/seo/tap-targets":[function(require,module,exports){
@@ -15281,7 +15771,7 @@ return passContext.driver.evaluateAsync(expression,{useIsolation:true});
module.exports=TapTargets;
-},{"../../../lib/page-functions.js":77,"../../../lib/rect-helpers.js":78,"../gatherer.js":53}],"../gather/gatherers/service-worker":[function(require,module,exports){
+},{"../../../lib/page-functions.js":77,"../../../lib/rect-helpers.js":78,"../gatherer.js":54}],"../gather/gatherers/service-worker":[function(require,module,exports){
@@ -15309,7 +15799,170 @@ registrations};
module.exports=ServiceWorker;
-},{"./gatherer.js":53}],"../gather/gatherers/start-url":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/source-maps":[function(require,module,exports){
+(function(Buffer){
+
+
+
+
+
+'use strict';
+
+
+
+const Gatherer=require('./gatherer.js');
+const URL=require('../../lib/url-shim.js');
+
+
+
+
+
+
+
+
+
+
+async function fetchSourceMap(url){
+
+const response=await fetch(url);
+if(response.ok){
+return response.text();
+}else{
+throw new Error(`Received status code ${response.status} for ${url}`);
+}
+}
+
+
+
+
+class SourceMaps extends Gatherer{
+constructor(){
+super();
+
+this._scriptParsedEvents=[];
+this.onScriptParsed=this.onScriptParsed.bind(this);
+}
+
+
+
+
+
+
+async fetchSourceMapInPage(driver,sourceMapUrl){
+driver.setNextProtocolTimeout(1500);
+
+const sourceMapJson=
+await driver.evaluateAsync(`(${fetchSourceMap})(${JSON.stringify(sourceMapUrl)})`);
+return JSON.parse(sourceMapJson);
+}
+
+
+
+
+
+parseSourceMapFromDataUrl(sourceMapURL){
+const buffer=Buffer.from(sourceMapURL.split(',')[1],'base64');
+return JSON.parse(buffer.toString());
+}
+
+
+
+
+onScriptParsed(event){
+if(event.sourceMapURL){
+this._scriptParsedEvents.push(event);
+}
+}
+
+
+
+
+async beforePass(passContext){
+const driver=passContext.driver;
+driver.on('Debugger.scriptParsed',this.onScriptParsed);
+await driver.sendCommand('Debugger.enable');
+}
+
+
+
+
+
+
+_resolveUrl(url,base){
+try{
+return new URL(url,base).href;
+}catch(e){
+return;
+}
+}
+
+
+
+
+
+
+async _retrieveMapFromScriptParsedEvent(driver,event){
+if(!event.sourceMapURL){
+throw new Error('precondition failed: event.sourceMapURL should exist');
+}
+
+
+
+const isSourceMapADataUri=event.sourceMapURL.startsWith('data:');
+const scriptUrl=event.url;
+const rawSourceMapUrl=isSourceMapADataUri?
+event.sourceMapURL:
+this._resolveUrl(event.sourceMapURL,event.url);
+
+if(!rawSourceMapUrl){
+return{
+scriptUrl,
+errorMessage:`Could not resolve map url: ${event.sourceMapURL}`};
+
+}
+
+
+const sourceMapUrl=isSourceMapADataUri?undefined:rawSourceMapUrl;
+
+try{
+const map=isSourceMapADataUri?
+this.parseSourceMapFromDataUrl(rawSourceMapUrl):
+await this.fetchSourceMapInPage(driver,rawSourceMapUrl);
+return{
+scriptUrl,
+sourceMapUrl,
+map};
+
+}catch(err){
+return{
+scriptUrl,
+sourceMapUrl,
+errorMessage:err.toString()};
+
+}
+}
+
+
+
+
+
+async afterPass(passContext){
+const driver=passContext.driver;
+
+driver.off('Debugger.scriptParsed',this.onScriptParsed);
+await driver.sendCommand('Debugger.disable');
+
+const eventProcessPromises=this._scriptParsedEvents.
+map(event=>this._retrieveMapFromScriptParsedEvent(driver,event));
+
+return Promise.all(eventProcessPromises);
+}}
+
+
+module.exports=SourceMaps;
+
+}).call(this,require("buffer").Buffer);
+},{"../../lib/url-shim.js":"url","./gatherer.js":54,"buffer":102}],"../gather/gatherers/start-url":[function(require,module,exports){
@@ -15328,15 +15981,31 @@ class StartUrl extends Gatherer{
async afterPass(passContext){
+
+await passContext.driver.goOffline();
+const result=await this._determineStartUrlAvailability(passContext);
+await passContext.driver.goOnline(passContext);
+
+return result;
+}
+
+
+
+
+
+
+async _determineStartUrlAvailability(passContext){
const manifest=passContext.baseArtifacts.WebAppManifest;
const startUrlInfo=this._readManifestStartUrl(manifest);
if(startUrlInfo.isReadFailure){
return{statusCode:-1,explanation:startUrlInfo.reason};
}
-return this._attemptStartURLFetch(passContext.driver,startUrlInfo.startUrl).catch(()=>{
-return{statusCode:-1,explanation:'Unable to fetch start URL via service worker.'};
-});
+try{
+return await this._attemptStartURLFetch(passContext.driver,startUrlInfo.startUrl);
+}catch(err){
+return{statusCode:-1,explanation:'Error while fetching start_url via service worker.'};
+}
}
@@ -15371,7 +16040,7 @@ _attemptStartURLFetch(driver,startUrl){
const timeoutPromise=new Promise(resolve=>
setTimeout(
-()=>resolve({statusCode:-1,explanation:'Timed out waiting for fetched start_url.'}),
+()=>resolve({statusCode:-1,explanation:'Timed out waiting for start_url to respond.'}),
3000));
@@ -15389,7 +16058,7 @@ driver.off('Network.responseReceived',onResponseReceived);
if(!response.fromServiceWorker){
return resolve({
statusCode:-1,
-explanation:'Unable to fetch start URL via service worker.'});
+explanation:'The start_url did respond, but not via a service worker.'});
}
@@ -15405,7 +16074,7 @@ then(()=>Promise.race([fetchPromise,timeoutPromise]));
module.exports=StartUrl;
-},{"./gatherer.js":53}],"../gather/gatherers/viewport-dimensions":[function(require,module,exports){
+},{"./gatherer.js":54}],"../gather/gatherers/viewport-dimensions":[function(require,module,exports){
@@ -15458,7 +16127,7 @@ return dimensions;
module.exports=ViewportDimensions;
-},{"./gatherer.js":53}],1:[function(require,module,exports){
+},{"./gatherer.js":54}],1:[function(require,module,exports){
@@ -15469,6 +16138,7 @@ module.exports=ViewportDimensions;
const lighthouse=require('../lighthouse-core/index.js');
const RawProtocol=require('../lighthouse-core/gather/connections/raw.js');
const log=require('lighthouse-logger');
+const{registerLocaleData,lookupLocale}=require('../lighthouse-core/lib/i18n/i18n.js');
@@ -15513,7 +16183,9 @@ if(typeof module!=='undefined'&&module.exports){
module.exports={
runLighthouseInWorker,
-listenForStatus};
+listenForStatus,
+registerLocaleData,
+lookupLocale};
}
@@ -15524,9 +16196,13 @@ if(typeof self!=='undefined'){
self.runLighthouseInWorker=runLighthouseInWorker;
self.listenForStatus=listenForStatus;
+
+self.registerLocaleData=registerLocaleData;
+
+self.lookupLocale=lookupLocale;
}
-},{"../lighthouse-core/gather/connections/raw.js":49,"../lighthouse-core/index.js":54,"lighthouse-logger":128}],2:[function(require,module,exports){
+},{"../lighthouse-core/gather/connections/raw.js":50,"../lighthouse-core/index.js":55,"../lighthouse-core/lib/i18n/i18n.js":67,"lighthouse-logger":125}],2:[function(require,module,exports){
(function(__filename){
@@ -15618,7 +16294,7 @@ module.exports=AxeAudit;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/audits/accessibility/axe-audit.js");
-},{"../../lib/i18n/i18n.js":68,"../audit.js":3}],3:[function(require,module,exports){
+},{"../../lib/i18n/i18n.js":67,"../audit.js":3}],3:[function(require,module,exports){
@@ -16002,8 +16678,10 @@ return networkRecord.transferSize||0;
const transferSize=networkRecord.transferSize||0;
-const resourceSize=networkRecord.resourceSize;
-const compressionRatio=resourceSize!==undefined?transferSize/resourceSize:1;
+const resourceSize=networkRecord.resourceSize||0;
+
+const compressionRatio=Number.isFinite(resourceSize)&&resourceSize>0?
+transferSize/resourceSize:1;
return Math.round(totalBytes*compressionRatio);
}
}
@@ -16148,7 +16826,7 @@ throw new Error('audit_ unimplemented');
module.exports=UnusedBytes;
}).call(this,"/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js");
-},{"../../computed/load-simulator.js":10,"../../computed/metrics/lantern-interactive.js":23,"../../computed/network-records.js":33,"../../computed/page-dependency-graph.js":34,"../../lib/i18n/i18n.js":68,"../../lib/statistics.js":82,"../audit.js":3}],5:[function(require,module,exports){
+},{"../../computed/load-simulator.js":10,"../../computed/metrics/lantern-interactive.js":23,"../../computed/network-records.js":34,"../../computed/page-dependency-graph.js":35,"../../lib/i18n/i18n.js":67,"../../lib/statistics.js":82,"../audit.js":3}],5:[function(require,module,exports){
@@ -16243,6 +16921,7 @@ items:[detailsItem]};
if(result.failures.length>0){
return{
score:0,
+
explanation:`Failures: ${result.failures.join(',\n')}.`,
details};
@@ -16362,7 +17041,7 @@ return Object.assign(computableArtifact,{request});
module.exports=makeComputedArtifact;
-},{"../lib/arbitrary-equality-map.js":55,"lighthouse-logger":128}],9:[function(require,module,exports){
+},{"../lib/arbitrary-equality-map.js":56,"lighthouse-logger":125}],9:[function(require,module,exports){
@@ -16531,7 +17210,7 @@ return CriticalRequestChains.extractChain(networkRecords,mainResource);
module.exports=makeComputedArtifact(CriticalRequestChains);
-},{"../lib/network-request.js":76,"./computed-artifact.js":8,"./main-resource.js":11,"./network-records.js":33,"assert":92}],10:[function(require,module,exports){
+},{"../lib/network-request.js":76,"./computed-artifact.js":8,"./main-resource.js":11,"./network-records.js":34,"assert":92}],10:[function(require,module,exports){
@@ -16624,7 +17303,7 @@ return lanternData;
module.exports=makeComputedArtifact(LoadSimulator);
-},{"../config/constants.js":45,"../lib/dependency-graph/simulator/simulator.js":63,"./computed-artifact.js":8,"./network-analysis.js":32}],11:[function(require,module,exports){
+},{"../config/constants.js":46,"../lib/dependency-graph/simulator/simulator.js":64,"./computed-artifact.js":8,"./network-analysis.js":33}],11:[function(require,module,exports){
@@ -16660,7 +17339,7 @@ return mainResource;
module.exports=makeComputedArtifact(MainResource);
-},{"../lib/dependency-graph/simulator/network-analyzer.js":62,"./computed-artifact.js":8,"./network-records.js":33}],12:[function(require,module,exports){
+},{"../lib/dependency-graph/simulator/network-analyzer.js":63,"./computed-artifact.js":8,"./network-records.js":34}],12:[function(require,module,exports){
@@ -16686,7 +17365,7 @@ return MainThreadTasks_.getMainThreadTasks(mainThreadEvents,timestamps.traceEnd)
module.exports=makeComputedArtifact(MainThreadTasks);
-},{"../lib/tracehouse/main-thread-tasks.js":84,"./computed-artifact.js":8,"./trace-of-tab.js":38}],13:[function(require,module,exports){
+},{"../lib/tracehouse/main-thread-tasks.js":84,"./computed-artifact.js":8,"./trace-of-tab.js":39}],13:[function(require,module,exports){
@@ -16805,7 +17484,7 @@ allChecks:remainingChecks};
module.exports=makeComputedArtifact(ManifestValues);
-},{"../lib/icons.js":70,"./computed-artifact.js":8}],14:[function(require,module,exports){
+},{"../lib/icons.js":69,"./computed-artifact.js":8}],14:[function(require,module,exports){
@@ -16881,7 +17560,7 @@ timing:EstimatedInputLatency.calculateRollingWindowEIL(events)});
module.exports=makeComputedArtifact(EstimatedInputLatency);
-},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-estimated-input-latency.js":19,"./metric.js":29}],15:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-estimated-input-latency.js":19,"./metric.js":30}],15:[function(require,module,exports){
@@ -16919,7 +17598,7 @@ timestamp:traceOfTab.timestamps.firstContentfulPaint};
module.exports=makeComputedArtifact(FirstContentfulPaint);
-},{"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./metric.js":29}],16:[function(require,module,exports){
+},{"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./metric.js":30}],16:[function(require,module,exports){
@@ -17135,7 +17814,7 @@ timestamp:valueInMs*1000+navStart});
module.exports=makeComputedArtifact(FirstCPUIdle);
-},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-first-cpu-idle.js":21,"./metric.js":29}],17:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-first-cpu-idle.js":21,"./metric.js":30}],17:[function(require,module,exports){
@@ -17178,7 +17857,7 @@ timestamp:traceOfTab.timestamps.firstMeaningfulPaint};
module.exports=makeComputedArtifact(FirstMeaningfulPaint);
-},{"../../lib/lh-error.js":72,"../computed-artifact.js":8,"./lantern-first-meaningful-paint.js":22,"./metric.js":29}],18:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../computed-artifact.js":8,"./lantern-first-meaningful-paint.js":22,"./metric.js":30}],18:[function(require,module,exports){
@@ -17369,7 +18048,7 @@ module.exports=makeComputedArtifact(Interactive);
-},{"../../lib/lh-error.js":72,"../../lib/network-recorder.js":75,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-interactive.js":23,"./metric.js":29}],19:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../../lib/network-recorder.js":75,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-interactive.js":23,"./metric.js":30}],19:[function(require,module,exports){
@@ -17472,7 +18151,7 @@ return events.sort((a,b)=>a.start-b.start);
module.exports=makeComputedArtifact(LanternEstimatedInputLatency);
-},{"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"./estimated-input-latency.js":14,"./lantern-first-meaningful-paint.js":22,"./lantern-metric.js":25}],20:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"./estimated-input-latency.js":14,"./lantern-first-meaningful-paint.js":22,"./lantern-metric.js":25}],20:[function(require,module,exports){
@@ -17673,7 +18352,7 @@ node=>node.hasRenderBlockingPriority());
module.exports=makeComputedArtifact(LanternFirstContentfulPaint);
-},{"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"./lantern-metric.js":25}],21:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"./lantern-metric.js":25}],21:[function(require,module,exports){
@@ -17746,7 +18425,7 @@ return super.compute_(data,context);
module.exports=makeComputedArtifact(LanternFirstCPUIdle);
-},{"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"./first-cpu-idle.js":16,"./lantern-interactive.js":23}],22:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"./first-cpu-idle.js":16,"./lantern-interactive.js":23}],22:[function(require,module,exports){
@@ -17938,7 +18617,7 @@ reduce((max,x)=>Math.max(max||0,x||0),0);
module.exports=makeComputedArtifact(LanternInteractive);
-},{"../../lib/dependency-graph/base-node.js":57,"../../lib/network-request.js":76,"../computed-artifact.js":8,"./lantern-first-meaningful-paint.js":22,"./lantern-metric.js":25}],24:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../../lib/network-request.js":76,"../computed-artifact.js":8,"./lantern-first-meaningful-paint.js":22,"./lantern-metric.js":25}],24:[function(require,module,exports){
@@ -18028,7 +18707,7 @@ map(([_,timing])=>timing);
module.exports=makeComputedArtifact(LanternMaxPotentialFID);
-},{"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./lantern-metric.js":25}],25:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./lantern-metric.js":25}],25:[function(require,module,exports){
@@ -18181,7 +18860,7 @@ return this.computeMetricWithGraphs(data,context);
module.exports=LanternMetricArtifact;
-},{"../../lib/dependency-graph/base-node.js":57,"../../lib/network-request.js":76,"../load-simulator.js":10,"../page-dependency-graph.js":34,"../trace-of-tab.js":38}],26:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../../lib/network-request.js":76,"../load-simulator.js":10,"../page-dependency-graph.js":35,"../trace-of-tab.js":39}],26:[function(require,module,exports){
@@ -18329,7 +19008,7 @@ return totalWeightedTime/totalWeight;
module.exports=makeComputedArtifact(LanternSpeedIndex);
-},{"../../config/constants.js":45,"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"../speedline.js":37,"./lantern-first-contentful-paint.js":20,"./lantern-metric.js":25}],27:[function(require,module,exports){
+},{"../../config/constants.js":46,"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"../speedline.js":38,"./lantern-first-contentful-paint.js":20,"./lantern-metric.js":25}],27:[function(require,module,exports){
@@ -18452,7 +19131,50 @@ return events;
module.exports=makeComputedArtifact(LanternTotalBlockingTime);
-},{"../../lib/dependency-graph/base-node.js":57,"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./lantern-interactive.js":23,"./lantern-metric.js":25,"./total-blocking-time.js":31}],28:[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node.js":58,"../computed-artifact.js":8,"./lantern-first-contentful-paint.js":20,"./lantern-interactive.js":23,"./lantern-metric.js":25,"./total-blocking-time.js":32}],28:[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const makeComputedArtifact=require('../computed-artifact.js');
+const ComputedMetric=require('./metric.js');
+const LHError=require('../../lib/lh-error.js');
+
+class LargestContentfulPaint extends ComputedMetric{
+
+
+
+
+
+
+static computeSimulatedMetric(data,context){
+throw new Error('Unimplemented');
+}
+
+
+
+
+
+static async computeObservedMetric(data){
+const{traceOfTab}=data;
+if(!traceOfTab.timestamps.largestContentfulPaint){
+throw new LHError(LHError.errors.NO_LCP);
+}
+
+return{
+
+timing:traceOfTab.timings.largestContentfulPaint,
+timestamp:traceOfTab.timestamps.largestContentfulPaint};
+
+}}
+
+
+module.exports=makeComputedArtifact(LargestContentfulPaint);
+
+},{"../../lib/lh-error.js":72,"../computed-artifact.js":8,"./metric.js":30}],29:[function(require,module,exports){
@@ -18499,7 +19221,7 @@ timing:Math.max(...events.map(evt=>evt.duration),16)});
module.exports=makeComputedArtifact(MaxPotentialFID);
-},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-max-potential-fid.js":24,"./metric.js":29}],29:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./lantern-max-potential-fid.js":24,"./metric.js":30}],30:[function(require,module,exports){
@@ -18573,7 +19295,7 @@ throw new TypeError(`Unrecognized throttling method: ${settings.throttlingMethod
module.exports=ComputedMetric;
-},{"../../lib/tracehouse/trace-processor.js":86,"../network-records.js":33,"../trace-of-tab.js":38}],30:[function(require,module,exports){
+},{"../../lib/tracehouse/trace-processor.js":86,"../network-records.js":34,"../trace-of-tab.js":39}],31:[function(require,module,exports){
@@ -18611,7 +19333,7 @@ return Promise.resolve({timing,timestamp});
module.exports=makeComputedArtifact(SpeedIndex);
-},{"../computed-artifact.js":8,"../speedline.js":37,"./lantern-speed-index.js":26,"./metric.js":29}],31:[function(require,module,exports){
+},{"../computed-artifact.js":8,"../speedline.js":38,"./lantern-speed-index.js":26,"./metric.js":30}],32:[function(require,module,exports){
@@ -18727,7 +19449,7 @@ interactiveTimeMs)};
module.exports=makeComputedArtifact(TotalBlockingTime);
-},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./interactive.js":18,"./lantern-total-blocking-time.js":27,"./metric.js":29}],32:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"../../lib/tracehouse/trace-processor.js":86,"../computed-artifact.js":8,"./interactive.js":18,"./lantern-total-blocking-time.js":27,"./metric.js":30}],33:[function(require,module,exports){
@@ -18793,7 +19515,7 @@ return{throughput,...rttAndServerResponseTime};
module.exports=makeComputedArtifact(NetworkAnalysis);
-},{"../lib/dependency-graph/simulator/network-analyzer.js":62,"./computed-artifact.js":8,"./network-records.js":33}],33:[function(require,module,exports){
+},{"../lib/dependency-graph/simulator/network-analyzer.js":63,"./computed-artifact.js":8,"./network-records.js":34}],34:[function(require,module,exports){
@@ -18816,7 +19538,7 @@ return NetworkRecorder.recordsFromLogs(devtoolsLog);
module.exports=makeComputedArtifact(NetworkRecords);
-},{"../lib/network-recorder.js":75,"./computed-artifact.js":8}],34:[function(require,module,exports){
+},{"../lib/network-recorder.js":75,"./computed-artifact.js":8}],35:[function(require,module,exports){
@@ -19190,7 +19912,7 @@ module.exports=makeComputedArtifact(PageDependencyGraph);
-},{"../lib/dependency-graph/cpu-node.js":58,"../lib/dependency-graph/network-node.js":59,"../lib/dependency-graph/simulator/network-analyzer.js":62,"../lib/network-request.js":76,"../lib/tracehouse/trace-processor.js":86,"./computed-artifact.js":8,"./network-records.js":33,"./trace-of-tab.js":38}],35:[function(require,module,exports){
+},{"../lib/dependency-graph/cpu-node.js":59,"../lib/dependency-graph/network-node.js":60,"../lib/dependency-graph/simulator/network-analyzer.js":63,"../lib/network-request.js":76,"../lib/tracehouse/trace-processor.js":86,"./computed-artifact.js":8,"./network-records.js":34,"./trace-of-tab.js":39}],36:[function(require,module,exports){
@@ -19276,7 +19998,7 @@ return ResourceSummary.summarize(networkRecords,mainResource.url);
module.exports=makeComputedArtifact(ResourceSummary);
-},{"../lib/url-shim.js":"url","./computed-artifact.js":8,"./main-resource.js":11,"./network-records.js":33}],36:[function(require,module,exports){
+},{"../lib/url-shim.js":"url","./computed-artifact.js":8,"./main-resource.js":11,"./network-records.js":34}],37:[function(require,module,exports){
@@ -19307,7 +20029,7 @@ datauri:`data:image/jpeg;base64,${evt.args.snapshot}`};
module.exports=makeComputedArtifact(Screenshots);
-},{"./computed-artifact.js":8}],37:[function(require,module,exports){
+},{"./computed-artifact.js":8}],38:[function(require,module,exports){
@@ -19363,7 +20085,7 @@ return speedline;
module.exports=makeComputedArtifact(Speedline);
-},{"../lib/lh-error.js":72,"./computed-artifact.js":8,"./trace-of-tab.js":38,"speedline-core":168}],38:[function(require,module,exports){
+},{"../lib/lh-error.js":72,"./computed-artifact.js":8,"./trace-of-tab.js":39,"speedline-core":165}],39:[function(require,module,exports){
@@ -19430,7 +20152,7 @@ timestamps:{...timestamps,firstContentfulPaint:firstContentfulPaintTs}};
module.exports=makeComputedArtifact(TraceOfTab);
-},{"../lib/lh-error.js":72,"../lib/tracehouse/trace-processor.js":86,"./computed-artifact.js":8}],39:[function(require,module,exports){
+},{"../lib/lh-error.js":72,"../lib/tracehouse/trace-processor.js":86,"./computed-artifact.js":8}],40:[function(require,module,exports){
@@ -19515,7 +20237,7 @@ return userTimings;
module.exports=makeComputedArtifact(UserTimings);
-},{"./computed-artifact.js":8,"./trace-of-tab.js":38}],40:[function(require,module,exports){
+},{"./computed-artifact.js":8,"./trace-of-tab.js":39}],41:[function(require,module,exports){
@@ -19573,7 +20295,7 @@ module.exports=makeComputedArtifact(ViewportMeta);
-},{"./computed-artifact.js":8,"metaviewport-parser":132}],41:[function(require,module,exports){
+},{"./computed-artifact.js":8,"metaviewport-parser":129}],42:[function(require,module,exports){
@@ -19676,6 +20398,98 @@ budget};
+static throwInvalidPathError(path,error){
+throw new Error(`Invalid path ${path}. ${error}\n`+
+`'Path' should be specified using the 'robots.txt' format.\n`+
+`Learn more about the 'robots.txt' format here:\n`+
+`https://developers.google.com/search/reference/robots_txt#url-matching-based-on-path-values`);
+}
+
+
+
+
+
+
+
+
+static validatePath(path){
+if(path===undefined){
+return undefined;
+}else if(typeof path!=='string'){
+this.throwInvalidPathError(path,`Path should be a string.`);
+return;
+}else if(!path.startsWith('/')){
+this.throwInvalidPathError(path,`Path should start with '/'.`);
+}else if((path.match(/\*/g)||[]).length>1){
+this.throwInvalidPathError(path,`Path should only contain one '*'.`);
+}else if((path.match(/\$/g)||[]).length>1){
+this.throwInvalidPathError(path,`Path should only contain one '$' character.`);
+}else if(path.includes('$')&&!path.endsWith('$')){
+this.throwInvalidPathError(path,`'$' character should only occur at end of path.`);
+}
+return path;
+}
+
+
+
+
+
+
+
+
+
+static urlMatchesPattern(url,pattern='/'){
+const urlObj=new URL(url);
+const urlPath=urlObj.pathname+urlObj.search;
+
+const hasWildcard=pattern.includes('*');
+const hasDollarSign=pattern.includes('$');
+
+
+
+
+
+
+
+
+
+if(!hasWildcard&&!hasDollarSign){
+return urlPath.startsWith(pattern);
+
+
+
+
+
+}else if(!hasWildcard&&hasDollarSign){
+return urlPath===pattern.slice(0,-1);
+
+
+
+
+
+
+}else if(hasWildcard&&!hasDollarSign){
+const[beforeWildcard,afterWildcard]=pattern.split('*');
+const remainingUrl=urlPath.slice(beforeWildcard.length);
+return urlPath.startsWith(beforeWildcard)&&remainingUrl.includes(afterWildcard);
+
+
+
+
+
+
+}else if(hasWildcard&&hasDollarSign){
+const[beforeWildcard,afterWildcard]=pattern.split('*');
+const urlEnd=urlPath.slice(beforeWildcard.length);
+return urlPath.startsWith(beforeWildcard)&&urlEnd.endsWith(afterWildcard.slice(0,-1));
+}
+return false;
+}
+
+
+
+
+
static validateTimingBudget(timingBudget){
const{metric,budget,tolerance,...invalidRest}=timingBudget;
Budget.assertNoExcessProperties(invalidRest,'Timing Budget');
@@ -19723,9 +20537,11 @@ const budgets=budgetJson.map((b,index)=>{
const budget={};
-const{resourceSizes,resourceCounts,timings,...invalidRest}=b;
+const{path,resourceSizes,resourceCounts,timings,...invalidRest}=b;
Budget.assertNoExcessProperties(invalidRest,'Budget');
+budget.path=Budget.validatePath(path);
+
if(isArrayOfUnknownObjects(resourceSizes)){
budget.resourceSizes=resourceSizes.map(Budget.validateResourceBudget);
Budget.assertNoDuplicateStrings(budget.resourceSizes.map(r=>r.resourceType),
@@ -19759,7 +20575,7 @@ return budgets;
module.exports=Budget;
-},{}],42:[function(require,module,exports){
+},{}],43:[function(require,module,exports){
(function(process,__dirname){
@@ -19973,7 +20789,7 @@ resolveModule};
}).call(this,require('_process'),"/lighthouse-core/config");
-},{"../audits/audit.js":3,"../runner.js":90,"_process":145,"path":143}],43:[function(require,module,exports){
+},{"../audits/audit.js":3,"../runner.js":90,"_process":142,"path":140}],44:[function(require,module,exports){
@@ -20198,7 +21014,7 @@ groups:ConfigPlugin._parseGroups(pluginGroupsJson,pluginName)};
module.exports=ConfigPlugin;
-},{}],44:[function(require,module,exports){
+},{}],45:[function(require,module,exports){
(function(__dirname){
@@ -21026,7 +21842,7 @@ return fullPasses;
module.exports=Config;
}).call(this,"/lighthouse-core/config");
-},{"../runner.js":90,"./../lib/i18n/i18n.js":68,"./budget.js":41,"./config-helpers.js":42,"./config-plugin.js":43,"./constants.js":45,"./default-config.js":46,"./full-config.js":47,"lighthouse-logger":128,"lodash.isequal":129,"path":143}],45:[function(require,module,exports){
+},{"../runner.js":90,"./../lib/i18n/i18n.js":67,"./budget.js":42,"./config-helpers.js":43,"./config-plugin.js":44,"./constants.js":46,"./default-config.js":47,"./full-config.js":48,"lighthouse-logger":125,"lodash.isequal":126,"path":140}],46:[function(require,module,exports){
@@ -21072,7 +21888,7 @@ cpuSlowdownMultiplier:4}};
const defaultSettings={
output:'json',
-maxWaitForFcp:15*1000,
+maxWaitForFcp:30*1000,
maxWaitForLoad:45*1000,
throttlingMethod:'simulate',
throttling:throttling.mobileSlow4G,
@@ -21122,7 +21938,7 @@ defaultPassConfig,
nonSimulatedPassConfigOverrides};
-},{}],46:[function(require,module,exports){
+},{}],47:[function(require,module,exports){
(function(__filename){
@@ -21221,6 +22037,15 @@ seoCrawlingGroupTitle:'Crawling and Indexing',
seoCrawlingGroupDescription:'To appear in search results, crawlers need access to your app.',
+pwaCategoryTitle:'Progressive Web App',
+
+pwaCategoryDescription:'These checks validate the aspects of a Progressive Web App. '+
+'[Learn more](https://developers.google.com/web/progressive-web-apps/checklist).',
+
+pwaCategoryManualDescription:'These checks are required by the baseline '+
+'[PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are '+
+'not automatically checked by Lighthouse. They do not affect your score but it\'s important that you verify them manually.',
+
bestPracticesCategoryTitle:'Best Practices',
pwaFastReliableGroupTitle:'Fast and reliable',
@@ -21252,6 +22077,8 @@ gatherers:[
'link-elements',
'meta-elements',
'script-elements',
+'iframe-elements',
+'main-document-content',
'dobetterweb/appcache',
'dobetterweb/doctype',
'dobetterweb/domstats',
@@ -21633,11 +22460,9 @@ auditRefs:[
'pwa':{
-title:'Progressive Web App',
-description:'These checks validate the aspects of a Progressive Web App. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist).',
-manualDescription:'These checks are required by the baseline '+
-'[PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are '+
-'not automatically checked by Lighthouse. They do not affect your score but it\'s important that you verify them manually.',
+title:str_(UIStrings.pwaCategoryTitle),
+description:str_(UIStrings.pwaCategoryDescription),
+manualDescription:str_(UIStrings.pwaCategoryManualDescription),
auditRefs:[
{id:'load-fast-enough-for-pwa',weight:7,group:'pwa-fast-reliable'},
@@ -21673,7 +22498,7 @@ get:()=>UIStrings});
}).call(this,"/lighthouse-core/config/default-config.js");
-},{"../lib/i18n/i18n.js":68,"./constants.js":45}],47:[function(require,module,exports){
+},{"../lib/i18n/i18n.js":67,"./constants.js":46}],48:[function(require,module,exports){
@@ -21708,7 +22533,7 @@ auditRefs:[
module.exports=fullConfig;
-},{}],48:[function(require,module,exports){
+},{}],49:[function(require,module,exports){
@@ -21766,13 +22591,14 @@ return Promise.reject(new Error('Not implemented'));
-sendCommand(method,...paramArgs){
+
+sendCommand(method,sessionId,...paramArgs){
const params=paramArgs.length?paramArgs[0]:undefined;
log.formatProtocol('method => browser',{method,params},'verbose');
const id=++this._lastCommandId;
-const message=JSON.stringify({id,method,params});
+const message=JSON.stringify({id,sessionId,method,params});
this.sendRawMessage(message);
return new Promise(resolve=>{
@@ -21828,7 +22654,7 @@ const callback=this._callbacks.get(object.id);
if(callback){
this._callbacks.delete(object.id);
-return callback.resolve(Promise.resolve().then(_=>{
+callback.resolve(Promise.resolve().then(_=>{
if(object.error){
log.formatProtocol('method <= browser ERR',{method:callback.method},'error');
throw LHError.fromProtocolMessage(callback.method,object.error);
@@ -21871,7 +22697,7 @@ this._eventEmitter=null;
module.exports=Connection;
-},{"../../lib/lh-error.js":72,"events":108,"lighthouse-logger":128}],49:[function(require,module,exports){
+},{"../../lib/lh-error.js":72,"events":108,"lighthouse-logger":125}],50:[function(require,module,exports){
@@ -21931,7 +22757,7 @@ this._port.send(message);
module.exports=RawConnection;
-},{"./connection.js":48}],50:[function(require,module,exports){
+},{"./connection.js":49}],51:[function(require,module,exports){
@@ -21988,7 +22814,7 @@ this._messages.push(message);
module.exports=DevtoolsLog;
-},{}],51:[function(require,module,exports){
+},{}],52:[function(require,module,exports){
(function(Buffer){
@@ -21999,7 +22825,7 @@ module.exports=DevtoolsLog;
const NetworkRecorder=require('../lib/network-recorder.js');
const emulation=require('../lib/emulation.js');
-const Element=require('../lib/element.js');
+const LHElement=require('../lib/lh-element.js');
const LHError=require('../lib/lh-error.js');
const NetworkRequest=require('../lib/network-request.js');
const EventEmitter=require('events').EventEmitter;
@@ -22061,21 +22887,8 @@ this._networkStatusMonitor=null;
this._monitoredUrl=null;
-
-
-
-
-
-
-
-this._targetProxyMessageId=0;
-
this.on('Target.attachedToTarget',event=>{
-this._handleTargetAttached(event,[]).catch(this._handleEventError);
-});
-
-this.on('Target.receivedMessageFromTarget',event=>{
-this._handleReceivedMessageFromTarget(event,[]).catch(this._handleEventError);
+this._handleTargetAttached(event).catch(this._handleEventError);
});
@@ -22243,10 +23056,12 @@ this._eventEmitter.removeListener(eventName,cb);
-_shouldToggleDomain(domain,enable){
-const enabledCount=this._domainEnabledCounts.get(domain)||0;
+
+_shouldToggleDomain(domain,sessionId,enable){
+const key=domain+(sessionId||'');
+const enabledCount=this._domainEnabledCounts.get(key)||0;
const newCount=enabledCount+(enable?1:-1);
-this._domainEnabledCounts.set(domain,Math.max(0,newCount));
+this._domainEnabledCounts.set(key,Math.max(0,newCount));
if(enable&&newCount===1||!enable&&newCount===0){
@@ -22295,61 +23110,29 @@ log.error('Driver','Unhandled event error',error.message);
-
-async _handleReceivedMessageFromTarget(event,parentSessionIds){
-const{targetId,sessionId,message}=event;
-
-const protocolMessage=JSON.parse(message);
-
-
-if('id'in protocolMessage)return;
-
-
-
-const sessionIdPath=[sessionId,...parentSessionIds];
-
-if(protocolMessage.method==='Target.receivedMessageFromTarget'){
-
-await this._handleReceivedMessageFromTarget(protocolMessage.params,sessionIdPath);
-}
-
-if(protocolMessage.method==='Target.attachedToTarget'){
-
-await this._handleTargetAttached(protocolMessage.params,sessionIdPath);
-}
-
-if(protocolMessage.method.startsWith('Network')){
-this._handleProtocolEvent({...protocolMessage,source:{targetId,sessionId}});
-}
-}
-
-
-
-
-
-async _handleTargetAttached(event,parentSessionIds){
-const sessionIdPath=[event.sessionId,...parentSessionIds];
-
+async _handleTargetAttached(event){
if(event.targetInfo.type!=='iframe'){
-await this.sendMessageToTarget(sessionIdPath,'Runtime.runIfWaitingForDebugger');
+await this.sendCommandToSession('Runtime.runIfWaitingForDebugger',event.sessionId);
return;
}
-await this.sendMessageToTarget(sessionIdPath,'Network.enable');
+await this.sendCommandToSession('Network.enable',event.sessionId);
-await this.sendMessageToTarget(sessionIdPath,'Target.setAutoAttach',{
+
+await this.sendCommandToSession('Target.setAutoAttach',event.sessionId,{
autoAttach:true,
+flatten:true,
waitForDebuggerOnStart:true});
-await this.sendMessageToTarget(sessionIdPath,'Runtime.runIfWaitingForDebugger');
+await this.sendCommandToSession('Runtime.runIfWaitingForDebugger',event.sessionId);
}
@@ -22362,38 +23145,7 @@ await this.sendMessageToTarget(sessionIdPath,'Runtime.runIfWaitingForDebugger');
-sendMessageToTarget(sessionIdPath,method,...params){
-this._targetProxyMessageId++;
-
-let payload={
-sessionId:sessionIdPath[0],
-message:JSON.stringify({id:this._targetProxyMessageId,method,params:params[0]})};
-
-
-for(const sessionId of sessionIdPath.slice(1)){
-this._targetProxyMessageId++;
-payload={
-sessionId,
-message:JSON.stringify({
-id:this._targetProxyMessageId,
-method:'Target.sendMessageToTarget',
-params:payload})};
-
-
-}
-
-return this.sendCommand('Target.sendMessageToTarget',payload);
-}
-
-
-
-
-
-
-
-
-
-sendCommand(method,...params){
+sendCommandToSession(method,sessionId,...params){
const timeout=this._nextProtocolTimeout;
this._nextProtocolTimeout=DEFAULT_PROTOCOL_TIMEOUT;
return new Promise(async(resolve,reject)=>{
@@ -22405,7 +23157,7 @@ LHError.errors.PROTOCOL_TIMEOUT,
reject(err);
},timeout);
try{
-const result=await this._innerSendCommand(method,...params);
+const result=await this._innerSendCommand(method,sessionId,...params);
resolve(result);
}catch(err){
reject(err);
@@ -22422,16 +23174,28 @@ clearTimeout(asyncTimeout);
+sendCommand(method,...params){
+return this.sendCommandToSession(method,undefined,...params);
+}
+
+
+
+
+
+
+
+
-_innerSendCommand(method,...params){
+
+_innerSendCommand(method,sessionId,...params){
const domainCommand=/^(\w+)\.(enable|disable)$/.exec(method);
if(domainCommand){
const enable=domainCommand[2]==='enable';
-if(!this._shouldToggleDomain(domainCommand[1],enable)){
+if(!this._shouldToggleDomain(domainCommand[1],sessionId,enable)){
return Promise.resolve();
}
}
-return this._connection.sendCommand(method,...params);
+return this._connection.sendCommand(method,sessionId,...params);
}
@@ -22521,7 +23285,11 @@ this.setNextProtocolTimeout(timeout);
const response=await this.sendCommand('Runtime.evaluate',evaluationParams);
if(response.exceptionDetails){
-return Promise.reject(new Error(`Evaluation exception: ${response.exceptionDetails.text}`));
+
+const errorMessage=response.exceptionDetails.exception?
+response.exceptionDetails.exception.description:
+response.exceptionDetails.text;
+return Promise.reject(new Error(`Evaluation exception: ${errorMessage}`));
}
if(response.result===undefined){
@@ -23121,6 +23889,7 @@ await this._clearIsolatedContextId();
await this.sendCommand('Target.setAutoAttach',{
+flatten:true,
autoAttach:true,
waitForDebuggerOnStart:true});
@@ -23130,7 +23899,7 @@ await this.sendCommand('Page.enable');
await this.sendCommand('Page.setLifecycleEventsEnabled',{enabled:true});
await this.sendCommand('Emulation.setScriptExecutionDisabled',{value:disableJS});
-const waitforPageNavigateCmd=this._innerSendCommand('Page.navigate',{url});
+const waitforPageNavigateCmd=this._innerSendCommand('Page.navigate',undefined,{url});
if(waitForNavigated){
await this._waitForFrameNavigated();
@@ -23230,7 +23999,7 @@ selector});
if(targetNode.nodeId===0){
return null;
}
-return new Element(targetNode,this);
+return new LHElement(targetNode,this);
}
@@ -23250,7 +24019,7 @@ selector});
const elementList=[];
targetNodeList.nodeIds.forEach(nodeId=>{
if(nodeId!==0){
-elementList.push(new Element({nodeId},this));
+elementList.push(new LHElement({nodeId},this));
}
});
return elementList;
@@ -23266,7 +24035,7 @@ getElementsInDocument(pierce=true){
return this.getNodesInDocument(pierce).
then(nodes=>nodes.
filter(node=>node.nodeType===1).
-map(node=>new Element({nodeId:node.nodeId},this)));
+map(node=>new LHElement({nodeId:node.nodeId},this)));
}
@@ -23356,7 +24125,7 @@ this.off('Tracing.dataCollected',dataListener);
resolve({traceEvents});
});
-return this.sendCommand('Tracing.end').catch(reject);
+this.sendCommand('Tracing.end').catch(reject);
});
}
@@ -23573,7 +24342,7 @@ await this.sendCommand('Page.enable');
module.exports=Driver;
}).call(this,require("buffer").Buffer);
-},{"../config/constants.js":45,"../lib/element.js":65,"../lib/emulation.js":66,"../lib/lh-error.js":72,"../lib/network-recorder.js":75,"../lib/network-request.js":76,"../lib/page-functions.js":77,"../lib/url-shim.js":"url","./connections/connection.js":48,"./devtools-log.js":50,"buffer":102,"events":108,"lighthouse-logger":128}],52:[function(require,module,exports){
+},{"../config/constants.js":46,"../lib/emulation.js":66,"../lib/lh-element.js":71,"../lib/lh-error.js":72,"../lib/network-recorder.js":75,"../lib/network-request.js":76,"../lib/page-functions.js":77,"../lib/url-shim.js":"url","./connections/connection.js":49,"./devtools-log.js":51,"buffer":102,"events":108,"lighthouse-logger":125}],53:[function(require,module,exports){
@@ -23585,7 +24354,7 @@ const log=require('lighthouse-logger');
const manifestParser=require('../lib/manifest-parser.js');
const stacksGatherer=require('../lib/stack-collector.js');
const LHError=require('../lib/lh-error.js');
-const URL=require('../lib/url-shim.js');
+const NetworkAnalyzer=require('../lib/dependency-graph/simulator/network-analyzer.js');
const NetworkRecorder=require('../lib/network-recorder.js');
const constants=require('../config/constants.js');
const i18n=require('../lib/i18n/i18n.js');
@@ -23711,13 +24480,7 @@ log.timeEnd(status);
-
-static getNetworkError(url,networkRecords){
-const mainRecord=networkRecords.find(record=>{
-
-return URL.equalWithExcludedFragments(record.url,url);
-});
-
+static getNetworkError(mainRecord){
if(!mainRecord){
return new LHError(LHError.errors.NO_DOCUMENT_REQUEST);
}else if(mainRecord.failed){
@@ -23749,29 +24512,28 @@ LHError.errors.ERRORED_DOCUMENT_REQUEST,
-static getInterstitialError(networkRecords){
+
+static getInterstitialError(mainRecord,networkRecords){
+
+if(!mainRecord)return undefined;
+
const interstitialRequest=networkRecords.
find(record=>record.documentURL.startsWith('chrome-error://'));
if(!interstitialRequest)return undefined;
-const pageNetworkRecords=networkRecords.
-filter(record=>!URL.NON_NETWORK_PROTOCOLS.includes(record.protocol)&&
-!record.documentURL.startsWith('chrome-error://'));
-
-if(!pageNetworkRecords.some(record=>record.failed))return undefined;
+if(!mainRecord.failed)return undefined;
-const insecureRequest=pageNetworkRecords.find(record=>
-record.failed&&record.localizedFailDescription.startsWith('net::ERR_CERT'));
-if(insecureRequest){
+if(mainRecord.localizedFailDescription.startsWith('net::ERR_CERT')){
return new LHError(LHError.errors.INSECURE_DOCUMENT_REQUEST,{securityMessages:
-insecureRequest.localizedFailDescription});
+mainRecord.localizedFailDescription});
}
+
return new LHError(LHError.errors.CHROME_INTERSTITIAL_ERROR);
}
@@ -23784,8 +24546,15 @@ return new LHError(LHError.errors.CHROME_INTERSTITIAL_ERROR);
static getPageLoadError(passContext,loadData,navigationError){
-const networkError=GatherRunner.getNetworkError(passContext.url,loadData.networkRecords);
-const interstitialError=GatherRunner.getInterstitialError(loadData.networkRecords);
+const{networkRecords}=loadData;
+
+let mainRecord;
+try{
+mainRecord=NetworkAnalyzer.findMainDocument(networkRecords,passContext.url);
+}catch(_){}
+
+const networkError=GatherRunner.getNetworkError(mainRecord);
+const interstitialError=GatherRunner.getInterstitialError(mainRecord,networkRecords);
if(!passContext.driver.online)return;
@@ -24245,7 +25014,7 @@ return GatherRunner.collectArtifacts(gathererResults);
module.exports=GatherRunner;
-},{"../config/constants.js":45,"../lib/i18n/i18n.js":68,"../lib/lh-error.js":72,"../lib/manifest-parser.js":73,"../lib/network-recorder.js":75,"../lib/stack-collector.js":80,"../lib/url-shim.js":"url","lighthouse-logger":128}],53:[function(require,module,exports){
+},{"../config/constants.js":46,"../lib/dependency-graph/simulator/network-analyzer.js":63,"../lib/i18n/i18n.js":67,"../lib/lh-error.js":72,"../lib/manifest-parser.js":73,"../lib/network-recorder.js":75,"../lib/stack-collector.js":80,"lighthouse-logger":125}],54:[function(require,module,exports){
@@ -24306,7 +25075,7 @@ afterPass(passContext,loadData){}}
module.exports=Gatherer;
-},{}],54:[function(require,module,exports){
+},{}],55:[function(require,module,exports){
@@ -24378,7 +25147,7 @@ lighthouse.NetworkRecords=require('./computed/network-records.js');
module.exports=lighthouse;
-},{"./audits/audit.js":3,"./computed/network-records.js":33,"./config/config.js":44,"./gather/connections/cri.js":101,"./gather/driver.js":51,"./gather/gatherers/gatherer.js":53,"./runner.js":90,"lighthouse-logger":128}],55:[function(require,module,exports){
+},{"./audits/audit.js":3,"./computed/network-records.js":34,"./config/config.js":45,"./gather/connections/cri.js":101,"./gather/driver.js":52,"./gather/gatherers/gatherer.js":54,"./runner.js":90,"lighthouse-logger":125}],56:[function(require,module,exports){
@@ -24461,7 +25230,7 @@ return isEqual(objA,objB);
module.exports=ArbitraryEqualityMap;
-},{"lodash.isequal":129}],56:[function(require,module,exports){
+},{"lodash.isequal":126}],57:[function(require,module,exports){
(function(process){
@@ -24757,7 +25526,7 @@ stringifyReplacer};
}).call(this,require('_process'));
-},{"../computed/load-simulator.js":10,"../computed/network-analysis.js":32,"../lib/lh-error.js":72,"./dependency-graph/simulator/simulator.js":63,"./lantern-trace-saver.js":71,"./traces/pwmetrics-events.js":87,"_process":145,"fs":101,"lighthouse-logger":128,"mkdirp":101,"path":143,"rimraf":101,"stream":170}],57:[function(require,module,exports){
+},{"../computed/load-simulator.js":10,"../computed/network-analysis.js":33,"../lib/lh-error.js":72,"./dependency-graph/simulator/simulator.js":64,"./lantern-trace-saver.js":70,"./traces/pwmetrics-events.js":87,"_process":142,"fs":101,"lighthouse-logger":125,"mkdirp":101,"path":140,"rimraf":101,"stream":167}],58:[function(require,module,exports){
@@ -25072,7 +25841,7 @@ CPU:'cpu'};
module.exports=BaseNode;
-},{}],58:[function(require,module,exports){
+},{}],59:[function(require,module,exports){
@@ -25160,7 +25929,7 @@ return new CPUNode(this._event,this._childEvents);
module.exports=CPUNode;
-},{"./base-node.js":57}],59:[function(require,module,exports){
+},{"./base-node.js":58}],60:[function(require,module,exports){
@@ -25244,7 +26013,7 @@ return node;
module.exports=NetworkNode;
-},{"../network-request.js":76,"./base-node.js":57}],60:[function(require,module,exports){
+},{"../network-request.js":76,"./base-node.js":58}],61:[function(require,module,exports){
@@ -25415,7 +26184,7 @@ this._connectionsInUse.delete(connection);
}};
-},{"./network-analyzer.js":62,"./tcp-connection.js":64}],61:[function(require,module,exports){
+},{"./network-analyzer.js":63,"./tcp-connection.js":65}],62:[function(require,module,exports){
@@ -25490,7 +26259,7 @@ DNSCache.RTT_MULTIPLIER=DNS_RESOLUTION_RTT_MULTIPLIER;
module.exports=DNSCache;
-},{}],62:[function(require,module,exports){
+},{}],63:[function(require,module,exports){
@@ -25967,7 +26736,7 @@ module.exports=NetworkAnalyzer;
-},{"../../network-request.js":76,"../../url-shim.js":"url"}],63:[function(require,module,exports){
+},{"../../network-request.js":76,"../../url-shim.js":"url"}],64:[function(require,module,exports){
@@ -26478,7 +27247,7 @@ module.exports=Simulator;
-},{"../../../config/constants.js":45,"../base-node.js":57,"./connection-pool.js":60,"./dns-cache.js":61,"./tcp-connection.js":64}],64:[function(require,module,exports){
+},{"../../../config/constants.js":46,"../base-node.js":58,"./connection-pool.js":61,"./dns-cache.js":62,"./tcp-connection.js":65}],65:[function(require,module,exports){
@@ -26686,80 +27455,7 @@ module.exports=TcpConnection;
-},{}],65:[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Driver=require('../gather/driver.js');
-
-class Element{
-
-
-
-
-constructor(element,driver){
-if(!element||!driver){
-throw Error('Driver and element required to create Element');
-}
-this.driver=driver;
-this.element=element;
-}
-
-
-
-
-
-getAttribute(name){
-return this.driver.
-sendCommand('DOM.getAttributes',{
-nodeId:this.element.nodeId}).
-
-
-
-
-then(resp=>{
-const attrIndex=resp.attributes.indexOf(name);
-if(attrIndex===-1){
-return null;
-}
-
-return resp.attributes[attrIndex+1];
-});
-}
-
-
-
-
-getNodeId(){
-return this.element.nodeId;
-}
-
-
-
-
-
-getProperty(propName){
-return this.driver.
-sendCommand('DOM.resolveNode',{
-nodeId:this.element.nodeId}).
-
-then(resp=>{
-if(!resp.object.objectId){
-return null;
-}
-return this.driver.getObjectProperty(resp.object.objectId,propName);
-}).
-catch(()=>null);
-}}
-
-
-module.exports=Element;
-
-},{"../gather/driver.js":51}],66:[function(require,module,exports){
+},{}],66:[function(require,module,exports){
@@ -26928,1870 +27624,6 @@ DESKTOP_USERAGENT};
},{}],67:[function(require,module,exports){
-module.exports={
-"lighthouse-core/audits/accessibility/accesskeys.js | description":{
-"message":"Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://dequeuniversity.com/rules/axe/3.1/accesskeys?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/accesskeys.js | failureTitle":{
-"message":"`[accesskey]` values are not unique",
-"description":"Title of an accesibility audit that evaluates if the ARIA HTML attributes are misaligned with the aria-role HTML attribute specificed on the element, such mismatches are invalid. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/accesskeys.js | title":{
-"message":"`[accesskey]` values are unique",
-"description":"Title of an accesibility audit that evaluates if the accesskey HTML attribute values are unique across all elements. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-allowed-attr.js | description":{
-"message":"Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-allowed-attr?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle":{
-"message":"`[aria-*]` attributes do not match their roles",
-"description":"Title of an accesibility audit that evaluates if the ARIA HTML attributes are misaligned with the aria-role HTML attribute specificed on the element, such mismatches are invalid. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-allowed-attr.js | title":{
-"message":"`[aria-*]` attributes match their roles",
-"description":"Title of an accesibility audit that evaluates if the ARIA HTML attributes are misaligned with the aria-role HTML attribute specificed on the element, such mismatches are invalid. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-required-attr.js | description":{
-"message":"Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-attr?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle":{
-"message":"`[role]`s do not have all required `[aria-*]` attributes",
-"description":"Title of an accesibility audit that evaluates if all elements with the aria-role attribute have the other corresponding ARIA attributes set as well. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-required-attr.js | title":{
-"message":"`[role]`s have all required `[aria-*]` attributes",
-"description":"Title of an accesibility audit that evaluates if all elements with the aria-role attribute have the other corresponding ARIA attributes set as well. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-required-children.js | description":{
-"message":"Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-children?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle":{
-"message":"Elements with `[role]` that require specific children `[role]`s, are missing.",
-"description":"Title of an accesibility audit that evaluates if the elements with an aria-role that require child elements have the required children. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-required-children.js | title":{
-"message":"Elements with `[role]` that require specific children `[role]`s, are present",
-"description":"Title of an accesibility audit that evaluates if the elements with an aria-role that require child elements have the required children. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-required-parent.js | description":{
-"message":"Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-required-parent?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle":{
-"message":"`[role]`s are not contained by their required parent element",
-"description":"Title of an accesibility audit that evaluates valid aria-role usage. Some ARIA roles require that elements must be a child of specific parent element. This audit checks that when those roles are used, the element with the role is in fact a child of the required parent. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-required-parent.js | title":{
-"message":"`[role]`s are contained by their required parent element",
-"description":"Title of an accesibility audit that evaluates valid aria-role usage. Some ARIA roles require that elements must be a child of specific parent element. This audit checks that when those roles are used, the element with the role is in fact a child of the required parent. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-roles.js | description":{
-"message":"ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-roles?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-roles.js | failureTitle":{
-"message":"`[role]` values are not valid",
-"description":"Title of an accesibility audit that evaluates if all elements have valid aria-role HTML attributes. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-roles.js | title":{
-"message":"`[role]` values are valid",
-"description":"Title of an accesibility audit that evaluates if all elements have valid aria-role HTML attributes. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description":{
-"message":"Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid values. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-valid-attr-value?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle":{
-"message":"`[aria-*]` attributes do not have valid values",
-"description":"Title of an accesibility audit that evaluates if all elements that have an ARIA HTML attribute have a valid value for that attribute. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title":{
-"message":"`[aria-*]` attributes have valid values",
-"description":"Title of an accesibility audit that evaluates if all elements that have an ARIA HTML attribute have a valid value for that attribute. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr.js | description":{
-"message":"Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid names. [Learn more](https://dequeuniversity.com/rules/axe/3.1/aria-valid-attr?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle":{
-"message":"`[aria-*]` attributes are not valid or misspelled",
-"description":"Title of an accesibility audit that evaluates if all elements with ARIA HTML attributes have spelled the name of attribute correctly. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/aria-valid-attr.js | title":{
-"message":"`[aria-*]` attributes are valid and not misspelled",
-"description":"Title of an accesibility audit that evaluates if all elements with ARIA HTML attributes have spelled the name of attribute correctly. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/audio-caption.js | description":{
-"message":"Captions make audio elements usable for deaf or hearing-impaired users, providing critical information such as who is talking, what they're saying, and other non-speech information. [Learn more](https://dequeuniversity.com/rules/axe/3.1/audio-caption?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/audio-caption.js | failureTitle":{
-"message":"`<audio>` elements are missing a `<track>` element with `[kind=\"captions\"]`.",
-"description":"Title of an accesibility audit that evaluates if all audio elements have a track element that has captions for screen readers. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/audio-caption.js | title":{
-"message":"`<audio>` elements contain a `<track>` element with `[kind=\"captions\"]`",
-"description":"Title of an accesibility audit that evaluates if all audio elements have a track element that has captions for screen readers. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader":{
-"message":"Failing Elements",
-"description":"Label of a table column that identifies HTML elements that have failed an audit."},
-
-"lighthouse-core/audits/accessibility/button-name.js | description":{
-"message":"When a button doesn't have an accessible name, screen readers announce it as \"button\", making it unusable for users who rely on screen readers. [Learn more](https://dequeuniversity.com/rules/axe/3.1/button-name?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/button-name.js | failureTitle":{
-"message":"Buttons do not have an accessible name",
-"description":"Title of an accesibility audit that evaluates if all button elements have names accessible to screen readers. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/button-name.js | title":{
-"message":"Buttons have an accessible name",
-"description":"Title of an accesibility audit that evaluates if all button elements have names accessible to screen readers. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/bypass.js | description":{
-"message":"Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more](https://dequeuniversity.com/rules/axe/3.1/bypass?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/bypass.js | failureTitle":{
-"message":"The page does not contain a heading, skip link, or landmark region",
-"description":"Title of an accesibility audit that evaluates if the page has elements that let screen reader users skip over repetitive content. `heading`, `skip link`, and `landmark region` are technical terms for the elements that enable quick page navigation. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/bypass.js | title":{
-"message":"The page contains a heading, skip link, or landmark region",
-"description":"Title of an accesibility audit that evaluates if the page has elements that let screen reader users skip over repetitive content. `heading`, `skip link`, and `landmark region` are technical terms for the elements that enable quick page navigation. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/color-contrast.js | description":{
-"message":"Low-contrast text is difficult or impossible for many users to read. [Learn more](https://dequeuniversity.com/rules/axe/3.1/color-contrast?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/color-contrast.js | failureTitle":{
-"message":"Background and foreground colors do not have a sufficient contrast ratio.",
-"description":"Title of an accesibility audit that evaluates if all foreground colors are distinct enough from their background colors to be legible for users. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/color-contrast.js | title":{
-"message":"Background and foreground colors have a sufficient contrast ratio",
-"description":"Title of an accesibility audit that evaluates if all foreground colors are distinct enough from their background colors to be legible for users. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/definition-list.js | description":{
-"message":"When definition lists are not properly marked up, screen readers may produce confusing or inaccurate output. [Learn more](https://dequeuniversity.com/rules/axe/3.1/definition-list?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/definition-list.js | failureTitle":{
-"message":"`<dl>`'s do not contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements.",
-"description":"Title of an accesibility audit that evaluates if all the definition list elements have valid markup for screen readers. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/definition-list.js | title":{
-"message":"`<dl>`'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements.",
-"description":"Title of an accesibility audit that evaluates if all the definition list elements have valid markup for screen readers. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/dlitem.js | description":{
-"message":"Definition list items (`<dt>` and `<dd>`) must be wrapped in a parent `<dl>` element to ensure that screen readers can properly announce them. [Learn more](https://dequeuniversity.com/rules/axe/3.1/dlitem?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/dlitem.js | failureTitle":{
-"message":"Definition list items are not wrapped in `<dl>` elements",
-"description":"Title of an accesibility audit that evaluates if all definition list item elements (`<dt>`/`<dd>`) have a definition list parent element (`<dl>`). This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/dlitem.js | title":{
-"message":"Definition list items are wrapped in `<dl>` elements",
-"description":"Title of an accesibility audit that evaluates if all definition list item elements (`<dt>`/`<dd>`) have a definition list parent element (`<dl>`). This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/document-title.js | description":{
-"message":"The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/title).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/document-title.js | failureTitle":{
-"message":"Document doesn't have a `<title>` element",
-"description":"Title of an accesibility audit that evaluates if the page has a <title> element that describes the page. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/document-title.js | title":{
-"message":"Document has a `<title>` element",
-"description":"Title of an accesibility audit that evaluates if the page has a <title> element that describes the page. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/duplicate-id.js | description":{
-"message":"The value of an id attribute must be unique to prevent other instances from being overlooked by assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/3.1/duplicate-id?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle":{
-"message":"`[id]` attributes on the page are not unique",
-"description":"Title of an accesibility audit that evaluates if there are any duplicate id HTML attributes on the page. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/duplicate-id.js | title":{
-"message":"`[id]` attributes on the page are unique",
-"description":"Title of an accesibility audit that evaluates if there are any duplicate id HTML attributes on the page. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/frame-title.js | description":{
-"message":"Screen reader users rely on frame titles to describe the contents of frames. [Learn more](https://dequeuniversity.com/rules/axe/3.1/frame-title?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/frame-title.js | failureTitle":{
-"message":"`<frame>` or `<iframe>` elements do not have a title",
-"description":"Title of an accesibility audit that evaluates if all `<frame>` and `<iframe>` elements on the page have a title HTML attribute to describe their contents. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/frame-title.js | title":{
-"message":"`<frame>` or `<iframe>` elements have a title",
-"description":"Title of an accesibility audit that evaluates if all `<frame>` and `<iframe>` elements on the page have a title HTML attribute to describe their contents. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/html-has-lang.js | description":{
-"message":"If a page doesn't specify a lang attribute, a screen reader assumes that the page is in the default language that the user chose when setting up the screen reader. If the page isn't actually in the default language, then the screen reader might not announce the page's text correctly. [Learn more](https://dequeuniversity.com/rules/axe/3.1/html-has-lang?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle":{
-"message":"`<html>` element does not have a `[lang]` attribute",
-"description":"Title of an accesibility audit that evaluates if the root HTML tag has a lang attribute identifying the page's language. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/html-has-lang.js | title":{
-"message":"`<html>` element has a `[lang]` attribute",
-"description":"Title of an accesibility audit that evaluates if the root HTML tag has a lang attribute identifying the page's language. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/html-lang-valid.js | description":{
-"message":"Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) helps screen readers announce text properly. [Learn more](https://dequeuniversity.com/rules/axe/3.1/valid-lang?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle":{
-"message":"`<html>` element does not have a valid value for its `[lang]` attribute.",
-"description":"Title of an accesibility audit that evaluates if the value for root HTML tag's lang attribute is a valid BCP 47 language. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/html-lang-valid.js | title":{
-"message":"`<html>` element has a valid value for its `[lang]` attribute",
-"description":"Title of an accesibility audit that evaluates if the value for root HTML tag's lang attribute is a valid BCP 47 language. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/image-alt.js | description":{
-"message":"Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://dequeuniversity.com/rules/axe/3.1/image-alt?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/image-alt.js | failureTitle":{
-"message":"Image elements do not have `[alt]` attributes",
-"description":"Title of an accesibility audit that evaluates if all image elements have the alt HTML attribute to describe their contents. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/image-alt.js | title":{
-"message":"Image elements have `[alt]` attributes",
-"description":"Title of an accesibility audit that evaluates if all image elements have the alt HTML attribute to describe their contents. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/input-image-alt.js | description":{
-"message":"When an image is being used as an `<input>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn more](https://dequeuniversity.com/rules/axe/3.1/input-image-alt?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle":{
-"message":"`<input type=\"image\">` elements do not have `[alt]` text",
-"description":"Title of an accesibility audit that evaluates if all input elements of type image have an alt HTML attribute to describe their contents. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/input-image-alt.js | title":{
-"message":"`<input type=\"image\">` elements have `[alt]` text",
-"description":"Title of an accesibility audit that evaluates if all input elements of type image have an alt HTML attribute to describe their contents. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/label.js | description":{
-"message":"Labels ensure that form controls are announced properly by assistive technologies, like screen readers. [Learn more](https://dequeuniversity.com/rules/axe/3.1/label?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/label.js | failureTitle":{
-"message":"Form elements do not have associated labels",
-"description":"Title of an accesibility audit that evaluates if all form elements have corresponding label elements. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/label.js | title":{
-"message":"Form elements have associated labels",
-"description":"Title of an accesibility audit that evaluates if all form elements have corresponding label elements. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/layout-table.js | description":{
-"message":"A table being used for layout purposes should not include data elements, such as the th or caption elements or the summary attribute, because this can create a confusing experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/3.1/layout-table?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/layout-table.js | failureTitle":{
-"message":"Presentational `<table>` elements do not avoid using `<th>`, `<caption>` or the `[summary]` attribute.",
-"description":"Title of an accesibility audit that evaluates if a table intended for layout contains data annotations as it can be confusing for screen readers. This is evaluated by checking if tables with the ARIA role of `presentation` or `none` contain any data elements such as table headers (`<th>`). This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/layout-table.js | title":{
-"message":"Presentational `<table>` elements avoid using `<th>`, `<caption>` or the `[summary]` attribute.",
-"description":"Title of an accesibility audit that evaluates if a table intended for layout contains data annotations as it can be confusing for screen readers. This is evaluated by checking if tables with the ARIA role of `presentation` or `none` contain any data elements such as table headers (`<th>`). This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/link-name.js | description":{
-"message":"Link text (and alternate text for images, when used as links) that is discernible, unique, and focusable improves the navigation experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/3.1/link-name?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/link-name.js | failureTitle":{
-"message":"Links do not have a discernible name",
-"description":"Title of an accesibility audit that evaluates if all link elements have a non-generic name to screen readers. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/link-name.js | title":{
-"message":"Links have a discernible name",
-"description":"Title of an accesibility audit that evaluates if all link elements have a non-generic name to screen readers. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/list.js | description":{
-"message":"Screen readers have a specific way of announcing lists. Ensuring proper list structure aids screen reader output. [Learn more](https://dequeuniversity.com/rules/axe/3.1/list?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/list.js | failureTitle":{
-"message":"Lists do not contain only `<li>` elements and script supporting elements (`<script>` and `<template>`).",
-"description":"Title of an accesibility audit that evaluates if all list elements have a valid structure containing only list items. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/list.js | title":{
-"message":"Lists contain only `<li>` elements and script supporting elements (`<script>` and `<template>`).",
-"description":"Title of an accesibility audit that evaluates if all list elements have a valid structure containing only list items. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/listitem.js | description":{
-"message":"Screen readers require list items (`<li>`) to be contained within a parent `<ul>` or `<ol>` to be announced properly. [Learn more](https://dequeuniversity.com/rules/axe/3.1/listitem?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/listitem.js | failureTitle":{
-"message":"List items (`<li>`) are not contained within `<ul>` or `<ol>` parent elements.",
-"description":"Title of an accesibility audit that evaluates if any list item elements do not have list parent elements. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/listitem.js | title":{
-"message":"List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements",
-"description":"Title of an accesibility audit that evaluates if any list item elements do not have list parent elements. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/meta-refresh.js | description":{
-"message":"Users do not expect a page to refresh automatically, and doing so will move focus back to the top of the page. This may create a frustrating or confusing experience. [Learn more](https://dequeuniversity.com/rules/axe/3.1/meta-refresh?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle":{
-"message":"The document uses `<meta http-equiv=\"refresh\">`",
-"description":"Title of an accesibility audit that evaluates if the page uses a meta tag that refreshes the page automatically. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/meta-refresh.js | title":{
-"message":"The document does not use `<meta http-equiv=\"refresh\">`",
-"description":"Title of an accesibility audit that evaluates if the page uses a meta tag that refreshes the page automatically. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/meta-viewport.js | description":{
-"message":"Disabling zooming is problematic for users with low vision who rely on screen magnification to properly see the contents of a web page. [Learn more](https://dequeuniversity.com/rules/axe/3.1/meta-viewport?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle":{
-"message":"`[user-scalable=\"no\"]` is used in the `<meta name=\"viewport\">` element or the `[maximum-scale]` attribute is less than 5.",
-"description":"Title of an accesibility audit that evaluates if the page has limited the scaling properties of the page in a way that harms users with low vision. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/meta-viewport.js | title":{
-"message":"`[user-scalable=\"no\"]` is not used in the `<meta name=\"viewport\">` element and the `[maximum-scale]` attribute is not less than 5.",
-"description":"Title of an accesibility audit that evaluates if the page has limited the scaling properties of the page in a way that harms users with low vision. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/object-alt.js | description":{
-"message":"Screen readers cannot translate non-text content. Adding alt text to `<object>` elements helps screen readers convey meaning to users. [Learn more](https://dequeuniversity.com/rules/axe/3.1/object-alt?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/object-alt.js | failureTitle":{
-"message":"`<object>` elements do not have `[alt]` text",
-"description":"Title of an accesibility audit that evaluates if all object elements have an alt HTML attribute that describes their contents. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/object-alt.js | title":{
-"message":"`<object>` elements have `[alt]` text",
-"description":"Title of an accesibility audit that evaluates if all object elements have an alt HTML attribute that describes their contents. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/tabindex.js | description":{
-"message":"A value greater than 0 implies an explicit navigation ordering. Although technically valid, this often creates frustrating experiences for users who rely on assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/3.1/tabindex?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/tabindex.js | failureTitle":{
-"message":"Some elements have a `[tabindex]` value greater than 0",
-"description":"Title of an accesibility audit that evaluates if any elements have custom tabindex HTML attributes that might frustrate users of assitive technology. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/tabindex.js | title":{
-"message":"No element has a `[tabindex]` value greater than 0",
-"description":"Title of an accesibility audit that evaluates if any elements have custom tabindex HTML attributes that might frustrate users of assitive technology. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/td-headers-attr.js | description":{
-"message":"Screen readers have features to make navigating tables easier. Ensuring `<td>` cells using the `[headers]` attribute only refer to other cells in the same table may improve the experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/3.1/td-headers-attr?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle":{
-"message":"Cells in a `<table>` element that use the `[headers]` attribute refers to other cells of that same table.",
-"description":"Title of an accesibility audit that evaluates if all table cell elements in a table that use the headers HTML attribute use it correctly to refer to cells within the same table. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/td-headers-attr.js | title":{
-"message":"Cells in a `<table>` element that use the `[headers]` attribute only refer to other cells of that same table.",
-"description":"Title of an accesibility audit that evaluates if all table cell elements in a table that use the headers HTML attribute use it correctly to refer to cells within the same table. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/th-has-data-cells.js | description":{
-"message":"Screen readers have features to make navigating tables easier. Ensuring table headers always refer to some set of cells may improve the experience for screen reader users. [Learn more](https://dequeuniversity.com/rules/axe/3.1/th-has-data-cells?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle":{
-"message":"`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` do not have data cells they describe.",
-"description":"Title of an accesibility audit that evaluates if all table header elements have children. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/th-has-data-cells.js | title":{
-"message":"`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` have data cells they describe.",
-"description":"Title of an accesibility audit that evaluates if all table header elements have children. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/valid-lang.js | description":{
-"message":"Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) on elements helps ensure that text is pronounced correctly by a screen reader. [Learn more](https://dequeuniversity.com/rules/axe/3.1/valid-lang?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/valid-lang.js | failureTitle":{
-"message":"`[lang]` attributes do not have a valid value",
-"description":"Title of an accesibility audit that evaluates if all lang HTML attributes are valid BCP 47 languages. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/valid-lang.js | title":{
-"message":"`[lang]` attributes have a valid value",
-"description":"Title of an accesibility audit that evaluates if all lang HTML attributes are valid BCP 47 languages. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/video-caption.js | description":{
-"message":"When a video provides a caption it is easier for deaf and hearing impaired users to access its information. [Learn more](https://dequeuniversity.com/rules/axe/3.1/video-caption?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/video-caption.js | failureTitle":{
-"message":"`<video>` elements do not contain a `<track>` element with `[kind=\"captions\"]`.",
-"description":"Title of an accesibility audit that evaluates if all video elements contain a child track element that has captions describing their audio. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/video-caption.js | title":{
-"message":"`<video>` elements contain a `<track>` element with `[kind=\"captions\"]`",
-"description":"Title of an accesibility audit that evaluates if all video elements contain a child track element that has captions describing their audio. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/accessibility/video-description.js | description":{
-"message":"Audio descriptions provide relevant information for videos that dialogue cannot, such as facial expressions and scenes. [Learn more](https://dequeuniversity.com/rules/axe/3.1/video-description?application=lighthouse).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/accessibility/video-description.js | failureTitle":{
-"message":"`<video>` elements do not contain a `<track>` element with `[kind=\"description\"]`.",
-"description":"Title of an accesibility audit that evaluates if all video elements have child track elements that contain a description of the video content. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed."},
-
-"lighthouse-core/audits/accessibility/video-description.js | title":{
-"message":"`<video>` elements contain a `<track>` element with `[kind=\"description\"]`",
-"description":"Title of an accesibility audit that evaluates if all video elements have child track elements that contain a description of the video content. This title is descriptive of the successful state and is shown to users when no user action is required."},
-
-"lighthouse-core/audits/apple-touch-icon.js | description":{
-"message":"For ideal appearance on iOS when users add to the home screen, define an apple-touch-icon. It must point to a non-transparent 192px (or 180px) square PNG. [Learn More](https://developers.google.com/web/fundamentals/design-and-ux/browser-customization/).",
-"description":"Description of a Lighthouse audit that tells the user what having a valid apple-touch-icon does. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. \"apple-touch-icon\" is an HTML attribute value and should not be translated."},
-
-"lighthouse-core/audits/apple-touch-icon.js | failureTitle":{
-"message":"Does not provide a valid `apple-touch-icon`",
-"description":"Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page does not contain a valid iOS touch icon. \"apple-touch-icon\" is an HTML attribute value and should not be translated."},
-
-"lighthouse-core/audits/apple-touch-icon.js | precomposedWarning":{
-"message":"`apple-touch-icon-precomposed` is out of date; `apple-touch-icon` is preferred.",
-"description":"Warning that HTML attribute `apple-touch-icon-precomposed` should not be used in favor of `apple-touch-icon`. \"apple-touch-icon-precomposed\" and \"apple-touch-icon\" are HTML attribute values and should not be translated."},
-
-"lighthouse-core/audits/apple-touch-icon.js | title":{
-"message":"Provides a valid `apple-touch-icon`",
-"description":"Title of a Lighthouse audit that tells the user that their site contains a vaild touch icon. This descriptive title is shown when the page contains a valid iOS touch icon. \"apple-touch-icon\" is an HTML attribute value and should not be translated."},
-
-"lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning":{
-"message":"Chrome extensions negatively affected this page's load performance. Try auditing the page in incognito mode or from a Chrome profile without extensions.",
-"description":"A message displayed in a Lighthouse audit result warning that Chrome extensions on the user's system substantially affected Lighthouse's measurements and instructs the user on how to run again without those extensions."},
-
-"lighthouse-core/audits/bootup-time.js | columnScriptEval":{
-"message":"Script Evaluation",
-"description":"Label for a time column in a data table; entries will be the number of milliseconds spent evaluating script for every script loaded by the page."},
-
-"lighthouse-core/audits/bootup-time.js | columnScriptParse":{
-"message":"Script Parse",
-"description":"Label for a time column in a data table; entries will be the number of milliseconds spent parsing script files for every script loaded by the page."},
-
-"lighthouse-core/audits/bootup-time.js | columnTotal":{
-"message":"Total CPU Time",
-"description":"Label for the total time column in a data table; entries will be the number of milliseconds spent executing per resource loaded by the page."},
-
-"lighthouse-core/audits/bootup-time.js | description":{
-"message":"Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/bootup).",
-"description":"Description of a Lighthouse audit that tells the user that they should reduce the amount of time spent executing javascript and one method of doing so. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/bootup-time.js | failureTitle":{
-"message":"Reduce JavaScript execution time",
-"description":"Title of a diagnostic audit that provides detail on the time spent executing javascript files during the load. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/bootup-time.js | title":{
-"message":"JavaScript execution time",
-"description":"Title of a diagnostic audit that provides detail on the time spent executing javascript files during the load. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description":{
-"message":"Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/replace-animated-gifs-with-video/)",
-"description":"Description of a Lighthouse audit that tells the user *why* they should use video instead of GIF format for delivering animated content. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title":{
-"message":"Use video formats for animated content",
-"description":"Imperative title of a Lighthouse audit that tells the user to use video formats rather than animated GIFs, which are wasteful. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/offscreen-images.js | description":{
-"message":"Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/offscreen-images).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should defer loading offscreen images. Offscreen images are images located outside of the visible browser viewport. As they are unseen by the user and slow down page load, they should be loaded later, closer to when the user is going to see them. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/offscreen-images.js | title":{
-"message":"Defer offscreen images",
-"description":"Imperative title of a Lighthouse audit that tells the user to defer loading offscreen images. Offscreen images are images located outside of the visible browser viewport. As they are unseen by the user and slow down page load, they should be loaded later, closer to when the user is going to see them. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description":{
-"message":"Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/blocking-resources).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce or remove network resources that block the initial render of the page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title":{
-"message":"Eliminate render-blocking resources",
-"description":"Imperative title of a Lighthouse audit that tells the user to reduce or remove network resources that block the initial render of the page. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description":{
-"message":"Large network payloads cost users real money and are highly correlated with long load times. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/network-payloads).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce the size of the network resources required by the page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue":{
-"message":"Total size was {totalBytes, number, bytes} KB",
-"description":"Used to summarize the total byte size of the page and all its network requests. The `{totalBytes}` placeholder will be replaced with the total byte sizes, shown in kilobytes (e.g. 142 KB)"},
-
-"lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle":{
-"message":"Avoid enormous network payloads",
-"description":"Title of a diagnostic audit that provides detail on large network resources required during page load. 'Payloads' is roughly equivalent to 'resources'. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title":{
-"message":"Avoids enormous network payloads",
-"description":"Title of a diagnostic audit that provides detail on large network resources required during page load. 'Payloads' is roughly equivalent to 'resources'. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/byte-efficiency/unminified-css.js | description":{
-"message":"Minifying CSS files can reduce network payload sizes. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/minify-css).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should minify (remove whitespace) the page's CSS code. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/unminified-css.js | title":{
-"message":"Minify CSS",
-"description":"Imperative title of a Lighthouse audit that tells the user to minify (remove whitespace) the page's CSS code. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description":{
-"message":"Minifying JavaScript files can reduce payload sizes and script parse time. [Learn more](https://developers.google.com/speed/docs/insights/MinifyResources).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should minify the page’s JS code to reduce file size. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title":{
-"message":"Minify JavaScript",
-"description":"Imperative title of a Lighthouse audit that tells the user to minify the page’s JS code to reduce file size. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description":{
-"message":"Remove dead rules from stylesheets and defer the loading of CSS not used for above-the-fold content to reduce unnecessary bytes consumed by network activity. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/unused-css).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should defer loading any content in CSS that isn’t needed at page load. This is displayed after a user expands the section to see more. No word length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title":{
-"message":"Remove unused CSS",
-"description":"Imperative title of a Lighthouse audit that tells the user to remove content from their CSS that isn’t needed immediately and instead load that content at a later time. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/unused-javascript.js | description":{
-"message":"Remove unused JavaScript to reduce bytes consumed by network activity.",
-"description":"Description of a Lighthouse audit that tells the user *why* they should remove JavaScript that is never needed/evaluated by the browser. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/unused-javascript.js | title":{
-"message":"Remove unused JavaScript",
-"description":"Imperative title of a Lighthouse audit that tells the user to remove JavaScript that is never evaluated during page load. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description":{
-"message":"A long cache lifetime can speed up repeat visits to your page. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/cache-policy).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to adopt a long cache lifetime policy. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 resource found}\n other {# resources found}\n }",
-"description":"[ICU Syntax] Label for the audit identifying network resources with inefficient cache values. Clicking this will expand the audit to show the resources."},
-
-"lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle":{
-"message":"Serve static assets with an efficient cache policy",
-"description":"Title of a diagnostic audit that provides details on the any page resources that could have been served with more efficient cache policies. Cache refers to browser disk cache, which keeps old versions of network resources around for future use. This imperative title is shown to users when there is a significant amount of assets served with poor cache policies."},
-
-"lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title":{
-"message":"Uses efficient cache policy on static assets",
-"description":"Title of a diagnostic audit that provides detail on the cache policy applies to the page's static assets. Cache refers to browser disk cache, which keeps old versions of network resources around for future use. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description":{
-"message":"Optimized images load faster and consume less cellular data. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/optimize-images).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to efficiently encode images. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title":{
-"message":"Efficiently encode images",
-"description":"Imperative title of a Lighthouse audit that tells the user to encode images with optimization (better compression). This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description":{
-"message":"Serve images that are appropriately-sized to save cellular data and improve load time. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/oversized-images).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to serve appropriately sized images. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title":{
-"message":"Properly size images",
-"description":"Imperative title of a Lighthouse audit that tells the user to resize images to match the display dimensions. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description":{
-"message":"Text-based resources should be served with compression (gzip, deflate or brotli) to minimize total network bytes. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/text-compression).",
-"description":"Description of a Lighthouse audit that tells the user *why* their text-based resources should be served with compression (like gzip). This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title":{
-"message":"Enable text compression",
-"description":"Imperative title of a Lighthouse audit that tells the user to enable text compression (like gzip) in order to enhance the performance of a page. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description":{
-"message":"Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/webp).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should use newer and more efficient image formats. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title":{
-"message":"Serve images in next-gen formats",
-"description":"Imperative title of a Lighthouse audit that tells the user to serve images in newer and more efficient image formats in order to enhance the performance of a page. A non-modern image format was designed 20+ years ago. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/critical-request-chains.js | description":{
-"message":"The Critical Request Chains below show you what resources are loaded with a high priority. Consider reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/critical-request-chains).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce the depth of critical network requests to enhance initial load of a page . This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/critical-request-chains.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 chain found}\n other {# chains found}\n }",
-"description":"[ICU Syntax] Label for an audit identifying the number of sequences of dependent network requests used to load the page."},
-
-"lighthouse-core/audits/critical-request-chains.js | title":{
-"message":"Minimize Critical Requests Depth",
-"description":"Imperative title of a Lighthouse audit that tells the user to reduce the depth of critical network requests to enhance initial load of a page. Critical request chains are series of dependent network requests that are important for page rendering. For example, here's a 4-request-deep chain: The biglogo.jpg image is required, but is requested via the styles.css style code, which is requested by the initialize.js javascript, which is requested by the page's HTML. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/deprecations.js | columnDeprecate":{
-"message":"Deprecation / Warning",
-"description":"Header of the table column which displays the warning message describing use of a deprecated API by code running in the web page."},
-
-"lighthouse-core/audits/deprecations.js | columnLine":{
-"message":"Line",
-"description":"Table column header for line of code (eg. 432) that is using a deprecated API."},
-
-"lighthouse-core/audits/deprecations.js | description":{
-"message":"Deprecated APIs will eventually be removed from the browser. [Learn more](https://www.chromestatus.com/features#deprecated).",
-"description":"Description of a Lighthouse audit that tells the user why they should not use deprecated APIs on their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/deprecations.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 warning found}\n other {# warnings found}\n }",
-"description":"[ICU Syntax] Label for the audit identifying the number of warnings generated by using deprecated APIs."},
-
-"lighthouse-core/audits/deprecations.js | failureTitle":{
-"message":"Uses deprecated APIs",
-"description":"Title of a Lighthouse audit that provides detail on the use of deprecated APIs. This descriptive title is shown to users when the page uses deprecated APIs."},
-
-"lighthouse-core/audits/deprecations.js | title":{
-"message":"Avoids deprecated APIs",
-"description":"Title of a Lighthouse audit that provides detail on the use of deprecated APIs. This descriptive title is shown to users when the page does not use deprecated APIs."},
-
-"lighthouse-core/audits/dobetterweb/appcache-manifest.js | description":{
-"message":"Application Cache is deprecated. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).",
-"description":"Description of a Lighthouse audit that tells the user why they should not use the Application Cache API. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue":{
-"message":"Found \"{AppCacheManifest}\"",
-"description":"Label for the audit identifying uses of the Application Cache."},
-
-"lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle":{
-"message":"Uses Application Cache",
-"description":"Title of a Lighthouse audit that provides detail on the use of the Application Cache API. This descriptive title is shown to users when they do use the Application Cache API, which is considered bad practice."},
-
-"lighthouse-core/audits/dobetterweb/appcache-manifest.js | title":{
-"message":"Avoids Application Cache",
-"description":"Title of a Lighthouse audit that provides detail on the use of the Application Cache API. This descriptive title is shown to users when they do not use the Application Cache API."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | description":{
-"message":"Specifying a doctype prevents the browser from switching to quirks-mode. Read more on the [MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)",
-"description":"Description of a Lighthouse audit that tells the user why they should define an HTML doctype. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype":{
-"message":"Doctype name must be the lowercase string `html`",
-"description":"Explanatory message stating that the doctype is set, but is not \"html\" and is therefore invalid."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype":{
-"message":"Document must contain a doctype",
-"description":"Explanatory message stating that the document has no doctype."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId":{
-"message":"Expected publicId to be an empty string",
-"description":"Explanatory message stating that the publicId field is not empty."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId":{
-"message":"Expected systemId to be an empty string",
-"description":"Explanatory message stating that the systemId field is not empty."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | failureTitle":{
-"message":"Page lacks the HTML doctype, thus triggering quirks-mode",
-"description":"Title of a Lighthouse audit that provides detail on the doctype of a page. This descriptive title is shown to users when the page's doctype is not set to HTML."},
-
-"lighthouse-core/audits/dobetterweb/doctype.js | title":{
-"message":"Page has the HTML doctype",
-"description":"Title of a Lighthouse audit that provides detail on the doctype of a page. This descriptive title is shown to users when the pages's doctype is set to HTML."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | columnElement":{
-"message":"Element",
-"description":"Table column header for the DOM element. Each DOM element is described with its HTML representation."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic":{
-"message":"Statistic",
-"description":"Table column header for the type of statistic. These statistics describe how big the DOM is (count of DOM elements, children, depth)."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | columnValue":{
-"message":"Value",
-"description":"Table column header for the observed value of the DOM statistic."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | description":{
-"message":"Browser engineers recommend pages contain fewer than ~1,500 DOM elements. The sweet spot is a tree depth < 32 elements and fewer than 60 children/parent element. A large DOM can increase memory usage, cause longer [style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://developers.google.com/web/tools/lighthouse/audits/dom-size).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce the size of the web page's DOM. The size of a DOM is characterized by the total number of DOM elements and greatest DOM depth. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 element}\n other {# elements}\n }",
-"description":"[ICU Syntax] Label for an audit identifying the number of DOM elements found in the page."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle":{
-"message":"Avoid an excessive DOM size",
-"description":"Title of a diagnostic audit that provides detail on the size of the web page's DOM. The size of a DOM is characterized by the total number of DOM elements and greatest DOM depth. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth":{
-"message":"Maximum DOM Depth",
-"description":"Label for the numeric value of the maximum depth in the page's DOM tree."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements":{
-"message":"Total DOM Elements",
-"description":"Label for the total number of DOM elements found in the page."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth":{
-"message":"Maximum Child Elements",
-"description":"Label for the numeric value of the maximum number of children any DOM element in the page has. The element described will have the most children in the page."},
-
-"lighthouse-core/audits/dobetterweb/dom-size.js | title":{
-"message":"Avoids an excessive DOM size",
-"description":"Title of a diagnostic audit that provides detail on the size of the web page's DOM. The size of a DOM is characterized by the total number of DOM elements and greatest DOM depth. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel":{
-"message":"Rel",
-"description":"Label for a column in a data table; entries will be the values of the html \"rel\" attribute from link in a page."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget":{
-"message":"Target",
-"description":"Label for a column in a data table; entries will be the target attribute of a link. Each entry is either an empty string or a string like `_blank`."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description":{
-"message":"Add `rel=\"noopener\"` or `rel=\"noreferrer\"` to any external links to improve performance and prevent security vulnerabilities. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).",
-"description":"Description of a Lighthouse audit that tells the user why and how they should secure cross-origin links. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle":{
-"message":"Links to cross-origin destinations are unsafe",
-"description":"Title of a Lighthouse audit that provides detail on the cross-origin links that the web page contains, and whether the links can be considered safe. This descriptive title is shown to users when not all links can be considered safe."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title":{
-"message":"Links to cross-origin destinations are safe",
-"description":"Title of a Lighthouse audit that provides detail on the cross-origin links that the web page contains, and whether the links can be considered safe. This descriptive title is shown to users when all links are safe."},
-
-"lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning":{
-"message":"Unable to determine the destination for anchor ({anchorHTML}). If not used as a hyperlink, consider removing target=_blank.",
-"description":"Warning that some links' destinations cannot be determined and therefore the audit cannot evaluate the link's safety."},
-
-"lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description":{
-"message":"Users are mistrustful of or confused by sites that request their location without context. Consider tying the request to a user action instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).",
-"description":"Description of a Lighthouse audit that tells the user why they should not ask for geolocation permissions on load. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle":{
-"message":"Requests the geolocation permission on page load",
-"description":"Title of a Lighthouse audit that provides detail on geolocation permissions requests. This descriptive title is shown to users when the page does ask for geolocation permissions on load."},
-
-"lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title":{
-"message":"Avoids requesting the geolocation permission on page load",
-"description":"Title of a Lighthouse audit that provides detail on geolocation permission requests while the page is loading. This descriptive title is shown to users when the page does not ask for geolocation permissions on load."},
-
-"lighthouse-core/audits/dobetterweb/js-libraries.js | columnName":{
-"message":"Name",
-"description":"Label for a column in a data table; entries will be the names of the detected Javascript libraries."},
-
-"lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion":{
-"message":"Version",
-"description":"Label for a column in a data table; entries will be the version numbers of the detected Javascript libraries."},
-
-"lighthouse-core/audits/dobetterweb/js-libraries.js | description":{
-"message":"All front-end JavaScript libraries detected on the page.",
-"description":"Description of a Lighthouse audit that tells the user what this audit is detecting. This is displayed after a user expands the section to see more. No character length limits."},
-
-"lighthouse-core/audits/dobetterweb/js-libraries.js | title":{
-"message":"Detected JavaScript libraries",
-"description":"Title of a Lighthouse audit that provides detail on the Javascript libraries that are used on the page."},
-
-"lighthouse-core/audits/dobetterweb/no-document-write.js | description":{
-"message":"For users on slow connections, external scripts dynamically injected via `document.write()` can delay page load by tens of seconds. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).",
-"description":"Description of a Lighthouse audit that tells the user why they should avoid `document.write`. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle":{
-"message":"Uses `document.write()`",
-"description":"Title of a Lighthouse audit that provides detail on the page's use of the `document.write` API. This descriptive title is shown to users when the page does use `document.write`."},
-
-"lighthouse-core/audits/dobetterweb/no-document-write.js | title":{
-"message":"Avoids `document.write()`",
-"description":"Title of a Lighthouse audit that provides detail on the page's use of the `document.write` API. This descriptive title is shown to users when the page does not use `document.write`."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity":{
-"message":"Highest Severity",
-"description":"Label for a column in a data table; entries will be the severity of the vulnerabilities found within a Javascript library."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion":{
-"message":"Library Version",
-"description":"Label for a column in a data table; entries will be the version numbers of the Javascript libraries found."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln":{
-"message":"Vulnerability Count",
-"description":"Label for a column in a data table; entries will be the counts of JavaScript-library vulnerabilities found."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description":{
-"message":"Some third-party scripts may contain known security vulnerabilities that are easily identified and exploited by attackers. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).",
-"description":"Description of a Lighthouse audit that tells the user why they should be concerned about the third party Javascript libraries that they use. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 vulnerability detected}\n other {# vulnerabilities detected}\n }",
-"description":"[ICU Syntax] Label for the audit identifying the number of vulnerable Javascript libraries found."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle":{
-"message":"Includes front-end JavaScript libraries with known security vulnerabilities",
-"description":"Title of a Lighthouse audit that provides detail on Javascript libraries the page uses. This descriptive title is shown to users when some detected Javascript libraries have known security vulnerabilities."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh":{
-"message":"High",
-"description":"Table row value for the severity of a high impact, or dangerous Javascript vulnerability. Part of a ranking scale in the form: low, medium, high."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow":{
-"message":"Low",
-"description":"Table row value for the severity of a small, or low impact Javascript vulnerability. Part of a ranking scale in the form: low, medium, high."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium":{
-"message":"Medium",
-"description":"Table row value for the severity of a Javascript vulnerability. Part of a ranking scale in the form: low, medium, high."},
-
-"lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title":{
-"message":"Avoids front-end JavaScript libraries with known security vulnerabilities",
-"description":"Title of a Lighthouse audit that provides detail on Javascript libraries the page uses. This descriptive title is shown to users when all Javascript libraries are free of known security vulnerabilities."},
-
-"lighthouse-core/audits/dobetterweb/notification-on-start.js | description":{
-"message":"Users are mistrustful of or confused by sites that request to send notifications without context. Consider tying the request to user gestures instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/notifications-on-load).",
-"description":"Description of a Lighthouse audit that tells the user why they should not ask for notification permission on load. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle":{
-"message":"Requests the notification permission on page load",
-"description":"Title of a Lighthouse audit that provides detail on the page's notification permission requests. This descriptive title is shown to users when the page does ask for notification permission on load."},
-
-"lighthouse-core/audits/dobetterweb/notification-on-start.js | title":{
-"message":"Avoids requesting the notification permission on page load",
-"description":"Title of a Lighthouse audit that provides detail on the page's notification permission requests. This descriptive title is shown to users when the page does not ask for notification permission on load."},
-
-"lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem":{
-"message":"Failing Elements",
-"description":"Table column header for the HTML elements that do not allow pasting of content."},
-
-"lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description":{
-"message":"Preventing password pasting undermines good security policy. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/password-pasting).",
-"description":"Description of a Lighthouse audit that tells the user why they should allow pasting of content into password fields. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle":{
-"message":"Prevents users to paste into password fields",
-"description":"Title of a Lighthouse audit that provides detail on the ability to paste into password fields. This descriptive title is shown to users when the page does not allow pasting of content into password fields."},
-
-"lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title":{
-"message":"Allows users to paste into password fields",
-"description":"Title of a Lighthouse audit that provides detail on the ability to paste into password fields. This descriptive title is shown to users when the page allows pasting of content into password fields."},
-
-"lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol":{
-"message":"Protocol",
-"description":"Label for a column in a data table; entries in the column will be the HTTP Protocol used to make a network request."},
-
-"lighthouse-core/audits/dobetterweb/uses-http2.js | description":{
-"message":"HTTP/2 offers many benefits over HTTP/1.1, including binary headers, multiplexing, and server push. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http2).",
-"description":"Description of a Lighthouse audit that tells the user why they should use HTTP/2. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 request not served via HTTP/2}\n other {# requests not served via HTTP/2}\n }",
-"description":"[ICU Syntax] Label identifying the number of network requests that were not served with HTTP/2."},
-
-"lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle":{
-"message":"Does not use HTTP/2 for all of its resources",
-"description":"Title of a Lighthouse audit that provides detail on whether the webpage uses HTTP/2 for resources it requests over the network. This descriptive title is shown to users when the page does not use HTTP/2 for its requests."},
-
-"lighthouse-core/audits/dobetterweb/uses-http2.js | title":{
-"message":"Uses HTTP/2 for its own resources",
-"description":"Title of a Lighthouse audit that provides detail on whether the webpage uses HTTP/2 for resources it requests over the network. This descriptive title is shown to users when the page uses HTTP/2 for its requests."},
-
-"lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description":{
-"message":"Consider marking your touch and wheel event listeners as `passive` to improve your page's scroll performance. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners).",
-"description":"Description of a Lighthouse audit that tells the user why they should use passive event listeners on the page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle":{
-"message":"Does not use passive listeners to improve scrolling performance",
-"description":"Title of a Lighthouse audit that provides detail on the page's use of passive event listeners used to improve the scrolling performance of the page. This descriptive title is shown to users when the page does not use passive listeners."},
-
-"lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title":{
-"message":"Uses passive listeners to improve scrolling performance",
-"description":"Title of a Lighthouse audit that provides detail on the page's use of passive event listeners used to improve the scrolling performance of the page. This descriptive title is shown to users when the page does use passive listeners."},
-
-"lighthouse-core/audits/errors-in-console.js | columnDesc":{
-"message":"Description",
-"description":"Label for a column in a data table; entries in the column will be the descriptions of logged browser errors."},
-
-"lighthouse-core/audits/errors-in-console.js | description":{
-"message":"Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns.",
-"description":"Description of a Lighthouse audit that tells the user why errors being logged to the devtools console are a cause for concern and so should be fixed. This is displayed after a user expands the section to see more. No character length limits."},
-
-"lighthouse-core/audits/errors-in-console.js | failureTitle":{
-"message":"Browser errors were logged to the console",
-"description":"Title of a Lighthouse audit that provides detail on browser errors. This descriptive title is shown to users when browser errors occurred and were logged into the devtools console."},
-
-"lighthouse-core/audits/errors-in-console.js | title":{
-"message":"No browser errors logged to the console",
-"description":"Title of a Lighthouse audit that provides detail on browser errors. This descriptive title is shown to users when no browser errors were logged into the devtools console."},
-
-"lighthouse-core/audits/font-display.js | description":{
-"message":"Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. [Learn more](https://developers.google.com/web/updates/2016/02/font-display).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should use the font-display CSS feature. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/font-display.js | failureTitle":{
-"message":"Ensure text remains visible during webfont load",
-"description":"Title of a diagnostic audit that provides detail on the load of the page's webfonts. Often the text is invisible for seconds before the webfont resource is loaded. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/font-display.js | title":{
-"message":"All text remains visible during webfont loads",
-"description":"Title of a diagnostic audit that provides detail on if all the text on a webpage was visible while the page was loading its webfonts. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/font-display.js | undeclaredFontURLWarning":{
-"message":"Lighthouse was unable to automatically check the font-display value for the following URL: {fontURL}.",
-"description":"A warning message that is shown when Lighthouse couldn't automatically check some of the page's fonts and that the user will need to manually check it."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | columnActual":{
-"message":"Aspect Ratio (Actual)",
-"description":"Label for a column in a data table; entries in the column will be the numeric aspect ratio of the raw (actual) image."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed":{
-"message":"Aspect Ratio (Displayed)",
-"description":"Label for a column in a data table; entries in the column will be the numeric aspect ratio of an image as displayed in a web page."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | description":{
-"message":"Image display dimensions should match natural aspect ratio. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/aspect-ratio).",
-"description":"Description of a Lighthouse audit that tells the user why they should maintain the correct aspect ratios for all images. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | failureTitle":{
-"message":"Displays images with incorrect aspect ratio",
-"description":"Title of a Lighthouse audit that provides detail on the aspect ratios of all images on the page. This descriptive title is shown to users when not all images use correct aspect ratios."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | title":{
-"message":"Displays images with correct aspect ratio",
-"description":"Title of a Lighthouse audit that provides detail on the aspect ratios of all images on the page. This descriptive title is shown to users when all images use correct aspect ratios."},
-
-"lighthouse-core/audits/image-aspect-ratio.js | warningCompute":{
-"message":"Invalid image sizing information {url}",
-"description":"Warning that the size information for an image was nonsensical. `url` will be replaced with the url of that image."},
-
-"lighthouse-core/audits/is-on-https.js | columnInsecureURL":{
-"message":"Insecure URL",
-"description":"Label for a column in a data table; entries in the column will be the URLs of insecure (non-HTTPS) network requests."},
-
-"lighthouse-core/audits/is-on-https.js | description":{
-"message":"All sites should be protected with HTTPS, even ones that don't handle sensitive data. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/https).",
-"description":"Description of a Lighthouse audit that tells the user *why* HTTPS use is important. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/is-on-https.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 insecure request found}\n other {# insecure requests found}\n }",
-"description":"[ICU Syntax] Label identifying the number of insecure network requests found by an audit of a web page."},
-
-"lighthouse-core/audits/is-on-https.js | failureTitle":{
-"message":"Does not use HTTPS",
-"description":"Title of a Lighthouse audit that provides detail on the useage of HTTPS on a page. This descriptive title is shown to users when some, or all, requests on the page use HTTP instead of HTTPS."},
-
-"lighthouse-core/audits/is-on-https.js | title":{
-"message":"Uses HTTPS",
-"description":"Title of a Lighthouse audit that provides detail on the useage of HTTPS on a page. This descriptive title is shown to users when all requests on a page are fufilled using HTTPS."},
-
-"lighthouse-core/audits/load-fast-enough-for-pwa.js | description":{
-"message":"A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to load fast enough on mobile networks. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText":{
-"message":"Interactive at {timeInMs, number, seconds} s",
-"description":"Label for the audit identifying the time it took for the page to become interactive."},
-
-"lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride":{
-"message":"Interactive on simulated mobile network at {timeInMs, number, seconds} s",
-"description":"Label for the audit identifying the time it took for the page to become interactive on a mobile network."},
-
-"lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle":{
-"message":"Page load is not fast enough on mobile networks",
-"description":"Imperative title of a Lighthouse audit that tells the user that their page has loaded fast enough to be considered a Progressive Web App. This imperative title is shown to users when the web page has loaded too slowly to be considered a Progressive Web App."},
-
-"lighthouse-core/audits/load-fast-enough-for-pwa.js | title":{
-"message":"Page load is fast enough on mobile networks",
-"description":"Imperative title of a Lighthouse audit that tells the user that their page has loaded fast enough to be considered a Progressive Web App. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory":{
-"message":"Category",
-"description":"Label for the Main Thread Category column in data tables, rows will have a main thread Category and main thread Task Name."},
-
-"lighthouse-core/audits/mainthread-work-breakdown.js | description":{
-"message":"Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this.",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce JS execution times. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle":{
-"message":"Minimize main-thread work",
-"description":"Title of a diagnostic audit that provides detail on the main thread work the browser did to load the page. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/mainthread-work-breakdown.js | title":{
-"message":"Minimizes main-thread work",
-"description":"Title of a diagnostic audit that provides detail on the main thread work the browser did to load the page. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/metrics/estimated-input-latency.js | description":{
-"message":"Estimated Input Latency is an estimate of how long your app takes to respond to user input, in milliseconds, during the busiest 5s window of page load. If your latency is higher than 50 ms, users may perceive your app as laggy. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/estimated-input-latency).",
-"description":"Description of the Estimated Input Latency metric that estimates the amount of time, in milliseconds, that the app takes to respond to user input. This description is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/estimated-input-latency.js | title":{
-"message":"Estimated Input Latency",
-"description":"The name of the metric that marks the estimated time between the page receiving input (a user clicking, tapping, or typing) and the page responding. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/first-contentful-paint.js | description":{
-"message":"First Contentful Paint marks the time at which the first text or image is painted. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint).",
-"description":"Description of the First Contentful Paint (FCP) metric, which marks the time at which the first text or image is painted by the browser. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/first-contentful-paint.js | title":{
-"message":"First Contentful Paint",
-"description":"The name of the metric that marks the time at which the first text or image is painted by the browser. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/first-cpu-idle.js | description":{
-"message":"First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-interactive).",
-"description":"Description of the First CPU Idle metric, which marks the time at which the page has displayed content and the CPU is not busy executing the page's scripts. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/first-cpu-idle.js | title":{
-"message":"First CPU Idle",
-"description":"The name of the metric that marks when the page has displayed content and the CPU is not busy executing the page's scripts. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/first-meaningful-paint.js | description":{
-"message":"First Meaningful Paint measures when the primary content of a page is visible. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint).",
-"description":"Description of the First Meaningful Paint (FMP) metric, which marks the time at which a majority of the content has been painted by the browser. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/first-meaningful-paint.js | title":{
-"message":"First Meaningful Paint",
-"description":"The name of the metric that marks the time at which a majority of the content has been painted by the browser. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/interactive.js | description":{
-"message":"Time to interactive is the amount of time it takes for the page to become fully interactive. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/consistently-interactive).",
-"description":"Description of the Time to Interactive (TTI) metric, which evaluates when a page has completed its primary network activity and main thread work. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/interactive.js | title":{
-"message":"Time to Interactive",
-"description":"The name of the metric that marks the time at which the page is fully loaded and is able to quickly respond to user input (clicks, taps, and keypresses feel responsive). Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/max-potential-fid.js | description":{
-"message":"The maximum potential First Input Delay that your users could experience is the duration, in milliseconds, of the longest task. [Learn more](https://developers.google.com/web/updates/2018/05/first-input-delay).",
-"description":"Description of the Maximum Potential First Input Delay metric that marks the maximum estimated time between the page receiving input (a user clicking, tapping, or typing) and the page responding. This description is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/max-potential-fid.js | title":{
-"message":"Max Potential First Input Delay",
-"description":"The name of the metric \"Maximum Potential First Input Delay\" that marks the maximum estimated time between the page receiving input (a user clicking, tapping, or typing) and the page responding. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/speed-index.js | description":{
-"message":"Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index).",
-"description":"Description of the Speed Index metric, which summarizes how quickly the page looked visually complete. This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/metrics/speed-index.js | title":{
-"message":"Speed Index",
-"description":"The name of the metric that summarizes how quickly the page looked visually complete. The name of this metric is largely abstract and can be loosely translated. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/metrics/total-blocking-time.js | description":{
-"message":"Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds.",
-"description":"Description of the Total Blocking Time (TBT) metric, which calculates the total duration of blocking time for a web page. Blocking times are time periods when the page would be blocked (prevented) from responding to user input (clicks, taps, and keypresses will feel slow to respond). This is displayed within a tooltip when the user hovers on the metric name to see more. No character length limits."},
-
-"lighthouse-core/audits/metrics/total-blocking-time.js | title":{
-"message":"Total Blocking Time",
-"description":"The name of a metric that calculates the total duration of blocking time for a web page. Blocking times are time periods when the page would be blocked (prevented) from responding to user input (clicks, taps, and keypresses will feel slow to respond). Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit."},
-
-"lighthouse-core/audits/network-rtt.js | description":{
-"message":"Network round trip times (RTT) have a large impact on performance. If the RTT to an origin is high, it's an indication that servers closer to the user could improve performance. [Learn more](https://hpbn.co/primer-on-latency-and-bandwidth/).",
-"description":"Description of a Lighthouse audit that tells the user that a high network round trip time (RTT) can effect their website's performance because the server is physically far away from them thus making the RTT high. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/network-rtt.js | title":{
-"message":"Network Round Trip Times",
-"description":"Descriptive title of a Lighthouse audit that tells the user the round trip times to each origin the page connected to. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/network-server-latency.js | description":{
-"message":"Server latencies can impact web performance. If the server latency of an origin is high, it's an indication the server is overloaded or has poor backend performance. [Learn more](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall).",
-"description":"Description of a Lighthouse audit that tells the user that server latency can effect their website's performance negatively. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/network-server-latency.js | title":{
-"message":"Server Backend Latencies",
-"description":"Descriptive title of a Lighthouse audit that tells the user the server latencies observed from each origin the page connected to. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/performance-budget.js | columnOverBudget":{
-"message":"Over Budget",
-"description":"Label for a column in a data table; entries will be how much the quantity or size of network requests exceeded a predetermined budget."},
-
-"lighthouse-core/audits/performance-budget.js | description":{
-"message":"Keep the quantity and size of network requests under the targets set by the provided performance budget. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).",
-"description":"Description of a Lighthouse audit where a user sets budgets for the quantity and size of page resources. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/performance-budget.js | requestCountOverBudget":{
-"message":"{count, plural,\n =1 {1 request}\n other {# requests}\n }",
-"description":"[ICU Syntax] Entry in a data table identifying the number of network requests of a particular type. Count will be a whole number. String should be as short as possible to be able to fit well into the table."},
-
-"lighthouse-core/audits/performance-budget.js | title":{
-"message":"Performance budget",
-"description":"Title of a Lighthouse audit that compares the size and quantity of page resources against targets set by the user. These targets are thought of as \"performance budgets\" because these metrics impact page performance (i.e. how quickly a page loads)."},
-
-"lighthouse-core/audits/redirects.js | description":{
-"message":"Redirects introduce additional delays before the page can be loaded. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/redirects).",
-"description":"Description of a Lighthouse audit that tells users why they should reduce the number of server-side redirects on their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/redirects.js | title":{
-"message":"Avoid multiple page redirects",
-"description":"Imperative title of a Lighthouse audit that tells the user to eliminate the redirects taken through multiple URLs to load the page. This is shown in a list of audits that Lighthouse generates."},
-
-"lighthouse-core/audits/resource-summary.js | description":{
-"message":"To set budgets for the quantity and size of page resources, add a budget.json file. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets).",
-"description":"Description of a Lighthouse audit that tells the user that they can setup a budgets for the quantity and size of page resources. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/resource-summary.js | displayValue":{
-"message":"{requestCount, plural, =1 {1 request} other {# requests}} • { byteCount, number, bytes } KB",
-"description":"[ICU Syntax] Label for an audit identifying the number of requests and kilobytes used to load the page."},
-
-"lighthouse-core/audits/resource-summary.js | title":{
-"message":"Keep request counts low and transfer sizes small",
-"description":"Imperative title of a Lighthouse audit that tells the user to minimize the size and quantity of resources used to load the page."},
-
-"lighthouse-core/audits/seo/canonical.js | description":{
-"message":"Canonical links suggest which URL to show in search results. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to have a valid rel=canonical link. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationConflict":{
-"message":"Multiple conflicting URLs ({urlList})",
-"description":"Explanatory message stating that there was a failure in an audit caused by multiple URLs conflicting with each other. \"urlList\" will be replaced by a list of URLs (e.g. https://example.com, https://example2.com, etc )."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain":{
-"message":"Points to a different domain ({url})",
-"description":"Explanatory message stating that there was a failure in an audit caused by a URL pointing to a different domain. \"url\" will be replaced by the invalid URL (e.g. https://example.com)."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationInvalid":{
-"message":"Invalid URL ({url})",
-"description":"Explanatory message stating that there was a failure in an audit caused by a URL being invalid. \"url\" will be replaced by the invalid URL (e.g. https://example.com)."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere":{
-"message":"Points to another `hreflang` location ({url})",
-"description":"Explanatory message stating that there was a failure in an audit caused by a URL pointing to a different hreflang than the current context. \"url\" will be replaced by the invalid URL (e.g. https://example.com). 'hreflang' is an HTML attribute and should not be translated."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationRelative":{
-"message":"Relative URL ({url})",
-"description":"Explanatory message stating that there was a failure in an audit caused by a URL being relative instead of absolute. \"url\" will be replaced by the invalid URL (e.g. https://example.com)."},
-
-"lighthouse-core/audits/seo/canonical.js | explanationRoot":{
-"message":"Points to the domain's root URL (the homepage), instead of an equivalent page of content",
-"description":"Explanatory message stating that the page's canonical URL was pointing to the domain's root URL, which is a common mistake. \"points\" refers to the action of the 'rel=canonical' referencing another link. \"root\" refers to the starting/home page of the website. \"domain\" refers to the registered domain name of the website."},
-
-"lighthouse-core/audits/seo/canonical.js | failureTitle":{
-"message":"Document does not have a valid `rel=canonical`",
-"description":"Title of a Lighthouse audit that provides detail on a page's rel=canonical link. This descriptive title is shown to users when the rel=canonical link is invalid and should be fixed. \"rel=canonical\" is an HTML attribute and value and so should not be translated."},
-
-"lighthouse-core/audits/seo/canonical.js | title":{
-"message":"Document has a valid `rel=canonical`",
-"description":"Title of a Lighthouse audit that provides detail on a page's rel=canonical link. This descriptive title is shown to users when the rel=canonical link is valid. \"rel=canonical\" is an HTML attribute and value and so should not be translated."},
-
-"lighthouse-core/audits/seo/font-size.js | description":{
-"message":"Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/font-sizes).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to use a larger font size. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/font-size.js | displayValue":{
-"message":"{decimalProportion, number, extendedPercent} legible text",
-"description":"Label for the audit identifying font sizes that are too small."},
-
-"lighthouse-core/audits/seo/font-size.js | explanationViewport":{
-"message":"Text is illegible because there's no viewport meta tag optimized for mobile screens.",
-"description":"Explanatory message stating that there was a failure in an audit caused by a missing page viewport meta tag configuration. \"viewport\" and \"meta\" are HTML terms and should not be translated."},
-
-"lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer":{
-"message":"{decimalProportion, number, extendedPercent} of text is too small (based on {decimalProportionVisited, number, extendedPercent} sample).",
-"description":"Explanatory message stating that there was a failure in an audit caused by a certain percentage of the text on the page being too small, based on a sample size of text that was less than 100% of the text on the page. \"decimalProportion\" will be replaced by a percentage between 0 and 100%."},
-
-"lighthouse-core/audits/seo/font-size.js | failureTitle":{
-"message":"Document doesn't use legible font sizes",
-"description":"Title of a Lighthouse audit that provides detail on the font sizes used on the page. This descriptive title is shown to users when there is a font that may be too small to be read by users."},
-
-"lighthouse-core/audits/seo/font-size.js | title":{
-"message":"Document uses legible font sizes",
-"description":"Title of a Lighthouse audit that provides detail on the font sizes used on the page. This descriptive title is shown to users when the fonts used on the page are large enough to be considered legible."},
-
-"lighthouse-core/audits/seo/hreflang.js | description":{
-"message":"hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/hreflang).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to have an hreflang link on their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. \"hreflang\" is an HTML attribute and should not be translated."},
-
-"lighthouse-core/audits/seo/hreflang.js | failureTitle":{
-"message":"Document doesn't have a valid `hreflang`",
-"description":"Title of a Lighthouse audit that provides detail on the `hreflang` attribute on a page. This descriptive title is shown when the page's `hreflang` attribute is not valid and needs to be fixed. \"hreflang\" is an HTML attribute and should not be translated."},
-
-"lighthouse-core/audits/seo/hreflang.js | title":{
-"message":"Document has a valid `hreflang`",
-"description":"Title of a Lighthouse audit that provides detail on the `hreflang` attribute on a page. This descriptive title is shown when the page's `hreflang` attribute is configured correctly. \"hreflang\" is an HTML attribute and should not be translated."},
-
-"lighthouse-core/audits/seo/http-status-code.js | description":{
-"message":"Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to serve pages with a valid HTTP status code. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/http-status-code.js | failureTitle":{
-"message":"Page has unsuccessful HTTP status code",
-"description":"Descriptive title of a Lighthouse audit that provides detail on the HTTP status code a page responds with. This descriptive title is shown when the page responds to requests with an HTTP status code that indicates the request was unsuccessful."},
-
-"lighthouse-core/audits/seo/http-status-code.js | title":{
-"message":"Page has successful HTTP status code",
-"description":"Title of a Lighthouse audit that provides detail on the HTTP status code a page responds with. This descriptive title is shown when the page has responded with a valid HTTP status code."},
-
-"lighthouse-core/audits/seo/is-crawlable.js | description":{
-"message":"Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/indexing).",
-"description":"Description of a Lighthouse audit that tells the user *why* allowing search-engine crawling of their page is beneficial. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/is-crawlable.js | failureTitle":{
-"message":"Page is blocked from indexing",
-"description":"Title of a Lighthouse audit that provides detail on if search-engine crawlers are blocked from indexing the page. This title is shown when the page has been configured to block indexing and therefore cannot be indexed by search engines."},
-
-"lighthouse-core/audits/seo/is-crawlable.js | title":{
-"message":"Page isn’t blocked from indexing",
-"description":"Title of a Lighthouse audit that provides detail on if search-engine crawlers are blocked from indexing the page. This title is shown when the page is not blocked from indexing and can be crawled."},
-
-"lighthouse-core/audits/seo/link-text.js | description":{
-"message":"Descriptive link text helps search engines understand your content. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to have descriptive text on the links in their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/link-text.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 link found}\n other {# links found}\n }",
-"description":"[ICU Syntax] Label for the audit identifying the number of links found. \"link\" here refers to the links in a web page to other web pages."},
-
-"lighthouse-core/audits/seo/link-text.js | failureTitle":{
-"message":"Links do not have descriptive text",
-"description":"Title of a Lighthouse audit that tests if each link on a page contains a sufficient description of what a user will find when they click it. Generic, non-descriptive text like \"click here\" doesn't give an indication of what the link leads to. This descriptive title is shown when one or more links on the page contain generic, non-descriptive text."},
-
-"lighthouse-core/audits/seo/link-text.js | title":{
-"message":"Links have descriptive text",
-"description":"Title of a Lighthouse audit that tests if each link on a page contains a sufficient description of what a user will find when they click it. Generic, non-descriptive text like \"click here\" doesn't give an indication of what the link leads to. This descriptive title is shown when all links on the page have sufficient textual descriptions."},
-
-"lighthouse-core/audits/seo/manual/structured-data.js | description":{
-"message":"Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://developers.google.com/search/docs/guides/mark-up-content).",
-"description":"Description of a Lighthouse audit that provides detail on the structured data in a page. \"Structured data\" is a standardized data format on a page that helps a search engine categorize and understand its contents. This description is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/manual/structured-data.js | title":{
-"message":"Structured data is valid",
-"description":"Title of a Lighthouse audit that prompts users to manually check their page for valid structured data. \"Structured data\" is a standardized data format on a page that helps a search engine categorize and understand its contents."},
-
-"lighthouse-core/audits/seo/meta-description.js | description":{
-"message":"Meta descriptions may be included in search results to concisely summarize page content. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/description).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to have meta descriptions on their page. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/meta-description.js | explanation":{
-"message":"Description text is empty.",
-"description":"Explanatory message stating that there was a failure in an audit caused by the page's meta description text being empty."},
-
-"lighthouse-core/audits/seo/meta-description.js | failureTitle":{
-"message":"Document does not have a meta description",
-"description":"Title of a Lighthouse audit that provides detail on the web page's document meta description. This descriptive title is shown when the document does not have a meta description. \"meta\" should be left untranslated because it refers to an HTML element."},
-
-"lighthouse-core/audits/seo/meta-description.js | title":{
-"message":"Document has a meta description",
-"description":"Title of a Lighthouse audit that provides detail on the web page's document meta description. This descriptive title is shown when the document has a meta description. \"meta\" should be left untranslated because it refers to an HTML element."},
-
-"lighthouse-core/audits/seo/plugins.js | description":{
-"message":"Search engines can't index plugin content, and many devices restrict plugins or don't support them. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/plugins).",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to avoid using browser plugins in their content. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/plugins.js | failureTitle":{
-"message":"Document uses plugins",
-"description":"Descriptive title of a Lighthouse audit that provides detail on the browser plugins used by the page. This title is shown when there is plugin content on the page."},
-
-"lighthouse-core/audits/seo/plugins.js | title":{
-"message":"Document avoids plugins",
-"description":"Title of a Lighthouse audit that provides detail on the browser plugins used by the page. This descriptive title is shown when there is no plugin content on the page that would restrict search indexing."},
-
-"lighthouse-core/audits/seo/robots-txt.js | description":{
-"message":"If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed.",
-"description":"Description of a Lighthouse audit that tells the user *why* they need to have a valid robots.txt file. Note: \"robots.txt\" is a canonical filename and should not be translated. This is displayed after a user expands the section to see more. No character length limits."},
-
-"lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode":{
-"message":"request for robots.txt returned HTTP status: {statusCode}",
-"description":"Label for the audit identifying that the robots.txt request has returned a specific HTTP status code. Note: \"robots.txt\" is a canonical filename and should not be translated. \"statusCode\" will be replaced with a 3 digit integer which represents the status of the HTTP connectiong for this page."},
-
-"lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError":{
-"message":"{itemCount, plural,\n =1 {1 error found}\n other {# errors found}\n }",
-"description":"[ICU Syntax] Label for the audit identifying the number of errors that occured while validating the robots.txt file. \"itemCount\" will be replaced by the integer count of errors encountered."},
-
-"lighthouse-core/audits/seo/robots-txt.js | explanation":{
-"message":"Lighthouse was unable to download a robots.txt file",
-"description":"Explanatory message stating that there was a failure in an audit caused by Lighthouse not being able to download the robots.txt file for the site. Note: \"robots.txt\" is a canonical filename and should not be translated."},
-
-"lighthouse-core/audits/seo/robots-txt.js | failureTitle":{
-"message":"robots.txt is not valid",
-"description":"Title of a Lighthouse audit that provides detail on the site's robots.txt file. Note: \"robots.txt\" is a canonical filename and should not be translated. This descriptive title is shown when the robots.txt file is misconfigured, which makes the page hard or impossible to scan via web crawler."},
-
-"lighthouse-core/audits/seo/robots-txt.js | title":{
-"message":"robots.txt is valid",
-"description":"Title of a Lighthouse audit that provides detail on the site's robots.txt file. Note: \"robots.txt\" is a canonical filename and should not be translated. This descriptive title is shown when the robots.txt file is present and configured correctly."},
-
-"lighthouse-core/audits/seo/tap-targets.js | description":{
-"message":"Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://developers.google.com/web/fundamentals/accessibility/accessible-styles#multi-device_responsive_design).",
-"description":"Description of a Lighthouse audit that tells the user why buttons and links need to be big enough and what 'big enough' means. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/seo/tap-targets.js | displayValue":{
-"message":"{decimalProportion, number, percent} appropriately sized tap targets",
-"description":"Explanatory message stating that a certain percentage of the tap targets (like buttons and links) on the page are of an appropriately large size."},
-
-"lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized":{
-"message":"Tap targets are too small because there's no viewport meta tag optimized for mobile screens",
-"description":"Explanatory message stating that there was a failure in an audit caused by the viewport meta tag not being optimized for mobile screens, which caused tap targets like buttons and links to be too small to tap on."},
-
-"lighthouse-core/audits/seo/tap-targets.js | failureTitle":{
-"message":"Tap targets are not sized appropriately",
-"description":"Descriptive title of a Lighthouse audit that provides detail on whether tap targets (like buttons and links) on a page are big enough so they can easily be tapped on a mobile device. This descriptive title is shown when tap targets are not easy to tap on."},
-
-"lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader":{
-"message":"Overlapping Target",
-"description":"Label of a table column that identifies a tap target (like a link or button) that overlaps with another tap target."},
-
-"lighthouse-core/audits/seo/tap-targets.js | sizeHeader":{
-"message":"Size",
-"description":"Label of a table column that specifies the size of tap targets like buttons and links."},
-
-"lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader":{
-"message":"Tap Target",
-"description":"Label of a table column that identifies tap targets (like buttons and links) that have failed the audit and aren't easy to tap on."},
-
-"lighthouse-core/audits/seo/tap-targets.js | title":{
-"message":"Tap targets are sized appropriately",
-"description":"Title of a Lighthouse audit that provides detail on whether tap targets (like buttons and links) on a page are big enough so they can easily be tapped on a mobile device. This descriptive title is shown when tap targets are easy to tap on."},
-
-"lighthouse-core/audits/third-party-summary.js | columnMainThreadTime":{
-"message":"Main Thread Time",
-"description":"Label for a table column that displays how much time each row spent executing on the main thread, entries will be the number of milliseconds spent."},
-
-"lighthouse-core/audits/third-party-summary.js | columnThirdParty":{
-"message":"Third-Party",
-"description":"Label for a table column that displays the name of a third-party provider that potentially links to their website."},
-
-"lighthouse-core/audits/third-party-summary.js | description":{
-"message":"Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).",
-"description":"Description of a Lighthouse audit that identifies the code on the page that the user doesn't control. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/third-party-summary.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 Third-Party Found}\n other {# Third-Parties Found}\n }",
-"description":"Summary text for the result of a Lighthouse audit that identifies the code on the page that the user doesn't control. This text summarizes the number of distinct entities that were found on the page."},
-
-"lighthouse-core/audits/third-party-summary.js | title":{
-"message":"Third-Party Usage",
-"description":"Title of a Lighthouse audit that identifies the code on the page that the user doesn't control. This is shown in a list of audits that Lighthouse generates."},
-
-"lighthouse-core/audits/time-to-first-byte.js | description":{
-"message":"Time To First Byte identifies the time at which your server sends a response. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/ttfb).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should reduce the amount of time it takes their server to start responding to requests. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/time-to-first-byte.js | displayValue":{
-"message":"Root document took {timeInMs, number, milliseconds} ms",
-"description":"Used to summarize the total Time to First Byte duration for the primary HTML response. The `{timeInMs}` placeholder will be replaced with the time duration, shown in milliseconds (e.g. 210 ms)"},
-
-"lighthouse-core/audits/time-to-first-byte.js | failureTitle":{
-"message":"Reduce server response times (TTFB)",
-"description":"Title of a diagnostic audit that provides detail on how long it took from starting a request to when the server started responding. This imperative title is shown to users when there is a significant amount of execution time that could be reduced."},
-
-"lighthouse-core/audits/time-to-first-byte.js | title":{
-"message":"Server response times are low (TTFB)",
-"description":"Title of a diagnostic audit that provides detail on how long it took from starting a request to when the server started responding. This descriptive title is shown to users when the amount is acceptable and no user action is required."},
-
-"lighthouse-core/audits/user-timings.js | columnDuration":{
-"message":"Duration",
-"description":"Label for the Duration column in the User Timing event data table. User Timing API entries are added by the developer of the web page. Durations are only provided for 'Measure' entries. Durations are the number of total number milliseconds from Start Time to their ending point. e.g. '2,020.64 ms'"},
-
-"lighthouse-core/audits/user-timings.js | columnName":{
-"message":"Name",
-"description":"Label for the Name column in the User Timing event data table. User Timing API entries are added by the developer of the web page. An example user timing event name: 'pageload_logoimage_done'"},
-
-"lighthouse-core/audits/user-timings.js | columnStartTime":{
-"message":"Start Time",
-"description":"Label for the Start Time column in the User Timing event data table. User Timing API entries are added by the developer of the web page. Start Times are the number of milliseconds since the page started loading, e.g. '380.26 ms'"},
-
-"lighthouse-core/audits/user-timings.js | columnType":{
-"message":"Type",
-"description":"Label for the Type column in the User Timing event data table. User Timing API entries are added by the developer of the web page. The only possible types are 'Mark' and Measure'."},
-
-"lighthouse-core/audits/user-timings.js | description":{
-"message":"Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/user-timing).",
-"description":"Description of a Lighthouse audit that tells the user they may want to use the User Timing API to help measure the performance of aspects of their page load and interaction. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/user-timings.js | displayValue":{
-"message":"{itemCount, plural,\n =1 {1 user timing}\n other {# user timings}\n }",
-"description":"[ICU Syntax] Label for an audit identifying the number of User Timing timestamps present in the page."},
-
-"lighthouse-core/audits/user-timings.js | title":{
-"message":"User Timing marks and measures",
-"description":"Descriptive title of a diagnostic audit that provides details on any timestamps generated by the page. User Timing refers to the 'User Timing API', which enables a website to record specific times as 'marks', or spans of time as 'measures'."},
-
-"lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning":{
-"message":"A preconnect <link> was found for \"{securityOrigin}\" but was not used by the browser. Check that you are using the `crossorigin` attribute properly.",
-"description":"A warning message that is shown when the user tried to follow the advice of the audit, but it's not working as expected. Forgetting to set the `crossorigin` HTML attribute, or setting it to an incorrect value, on the link is a common mistake when adding preconnect links."},
-
-"lighthouse-core/audits/uses-rel-preconnect.js | description":{
-"message":"Consider adding preconnect or dns-prefetch resource hints to establish early connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).",
-"description":"Description of a Lighthouse audit that tells the user how to connect early to third-party domains that will be used to load page resources. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/uses-rel-preconnect.js | title":{
-"message":"Preconnect to required origins",
-"description":"Imperative title of a Lighthouse audit that tells the user to connect early to internet domains that will be used to load page resources. Origin is the correct term, however 'domain name' could be used if neccsesary. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning":{
-"message":"A preload <link> was found for \"{preloadURL}\" but was not used by the browser. Check that you are using the `crossorigin` attribute properly.",
-"description":"A warning message that is shown when the user tried to follow the advice of the audit, but it's not working as expected. Forgetting to set the `crossorigin` HTML attribute, or setting it to an incorrect value, on the link is a common mistake when adding preload links."},
-
-"lighthouse-core/audits/uses-rel-preload.js | description":{
-"message":"Consider using <link rel=preload> to prioritize fetching resources that are currently requested later in page load. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/preload).",
-"description":"Description of a Lighthouse audit that tells the user *why* they should preload important network requests. The associated network requests are started halfway through pageload (or later) but should be started at the beginning. This is displayed after a user expands the section to see more. No character length limits. '<link rel=preload>' is the html code the user would include in their page and shouldn't be translated. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/audits/uses-rel-preload.js | title":{
-"message":"Preload key requests",
-"description":"Imperative title of a Lighthouse audit that tells the user to use <link rel=preload> to initiate important network requests earlier during page load. This is displayed in a list of audit titles that Lighthouse generates."},
-
-"lighthouse-core/config/default-config.js | a11yAriaGroupDescription":{
-"message":"These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader.",
-"description":"Description of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria- HTML attributes have been used properly."},
-
-"lighthouse-core/config/default-config.js | a11yAriaGroupTitle":{
-"message":"ARIA",
-"description":"Title of the ARIA validity section within the Accessibility category. Within this section are audits with descriptive titles that highlight if whether all the aria- HTML attributes have been used properly."},
-
-"lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription":{
-"message":"These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments.",
-"description":"Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video."},
-
-"lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle":{
-"message":"Audio and video",
-"description":"Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to provide alternative content for audio and video."},
-
-"lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription":{
-"message":"These items highlight common accessibility best practices.",
-"description":"Description of the best practices section within the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices."},
-
-"lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle":{
-"message":"Best practices",
-"description":"Title of the best practices section of the Accessibility category. Within this section are audits with descriptive titles that highlight common accessibility best practices."},
-
-"lighthouse-core/config/default-config.js | a11yCategoryDescription":{
-"message":"These checks highlight opportunities to [improve the accessibility of your web app](https://developers.google.com/web/fundamentals/accessibility). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged.",
-"description":"Description of the Accessibility category. This is displayed at the top of a list of audits focused on making web content accessible to all users. No character length limits. 'improve the accessibility of your web app' becomes link text to additional documentation."},
-
-"lighthouse-core/config/default-config.js | a11yCategoryManualDescription":{
-"message":"These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review).",
-"description":"Description of the Accessibility manual checks category. This description is displayed above a list of accessibility audits that currently have no automated test and so must be verified manually by the user. No character length limits. 'conducting an accessibility review' becomes link text to additional documentation."},
-
-"lighthouse-core/config/default-config.js | a11yCategoryTitle":{
-"message":"Accessibility",
-"description":"Title of the Accessibility category of audits. This section contains audits focused on making web content accessible to all users. Also used as a label of a score gauge; try to limit to 20 characters."},
-
-"lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription":{
-"message":"These are opportunities to improve the legibility of your content.",
-"description":"Description of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing."},
-
-"lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle":{
-"message":"Contrast",
-"description":"Title of the color contrast section within the Accessibility category. Within this section are audits with descriptive titles that highlight the color and vision aspects of the page's accessibility that are passing or failing."},
-
-"lighthouse-core/config/default-config.js | a11yLanguageGroupDescription":{
-"message":"These are opportunities to improve the interpretation of your content by users in different locales.",
-"description":"Description of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page."},
-
-"lighthouse-core/config/default-config.js | a11yLanguageGroupTitle":{
-"message":"Internationalization and localization",
-"description":"Title of the language section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the language has been annotated in the correct HTML attributes on the page."},
-
-"lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription":{
-"message":"These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader.",
-"description":"Description of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader."},
-
-"lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle":{
-"message":"Names and labels",
-"description":"Title of the HTML element naming section within the Accessibility category. Within this section are audits with descriptive titles that highlight if the non-textual HTML elements on the page have names discernible by a screen reader."},
-
-"lighthouse-core/config/default-config.js | a11yNavigationGroupDescription":{
-"message":"These are opportunities to improve keyboard navigation in your application.",
-"description":"Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation."},
-
-"lighthouse-core/config/default-config.js | a11yNavigationGroupTitle":{
-"message":"Navigation",
-"description":"Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve keyboard navigation."},
-
-"lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription":{
-"message":"These are opportunities to to improve the experience of reading tabular or list data using assistive technology, like a screen reader.",
-"description":"Description of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology."},
-
-"lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle":{
-"message":"Tables and lists",
-"description":"Title of the navigation section within the Accessibility category. Within this section are audits with descriptive titles that highlight opportunities to improve the experience of reading tabular or list data using assistive technology."},
-
-"lighthouse-core/config/default-config.js | bestPracticesCategoryTitle":{
-"message":"Best Practices",
-"description":"Title of the Best Practices category of audits. This is displayed at the top of a list of audits focused on topics related to following web development best practices and accepted guidelines. Also used as a label of a score gauge; try to limit to 20 characters."},
-
-"lighthouse-core/config/default-config.js | budgetsGroupDescription":{
-"message":"Performance budgets set standards for the performance of your site.",
-"description":"Description of the Budgets section of the Performance category. Within this section the budget results are displayed."},
-
-"lighthouse-core/config/default-config.js | budgetsGroupTitle":{
-"message":"Budgets",
-"description":"Title of the Budgets section of the Performance Category. 'Budgets' refers to a budget (like a financial budget), but applied to the amount of resources on a page, rather than money."},
-
-"lighthouse-core/config/default-config.js | diagnosticsGroupDescription":{
-"message":"More information about the performance of your application. These numbers don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score.",
-"description":"Description of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on a web page's load performance characteristics. Within this section, the user may read the details and deduce additional actions they could take to improve performance."},
-
-"lighthouse-core/config/default-config.js | diagnosticsGroupTitle":{
-"message":"Diagnostics",
-"description":"Title of the diagnostics section of the Performance category. Within this section are audits with non-imperative titles that provide more detail on the page's page load performance characteristics. Whereas the 'Opportunities' suggest an action along with expected time savings, diagnostics do not. Within this section, the user may read the details and deduce additional actions they could take."},
-
-"lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription":{
-"message":"The most critical aspect of performance is how quickly pixels are rendered onscreen. Key metrics: First Contentful Paint, First Meaningful Paint",
-"description":"Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage."},
-
-"lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle":{
-"message":"First Paint Improvements",
-"description":"Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the time of the first initial render of the webpage."},
-
-"lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription":{
-"message":"These suggestions can help your page load faster. They don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score.",
-"description":"Description of the opportunity section of the Performance category. 'Suggestions' could also be 'recommendations'. Within this section are audits with imperative titles that suggest actions the user can take to improve the loading performance of their web page."},
-
-"lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle":{
-"message":"Opportunities",
-"description":"Title of the opportunity section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the loading performance of their web page. 'Suggestion'/'Optimization'/'Recommendation' are reasonable synonyms for 'opportunity' in this case."},
-
-"lighthouse-core/config/default-config.js | metricGroupTitle":{
-"message":"Metrics",
-"description":"Title of the speed metrics section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds."},
-
-"lighthouse-core/config/default-config.js | overallImprovementsGroupDescription":{
-"message":"Enhance the overall loading experience, so the page is responsive and ready to use as soon as possible. Key metrics: Time to Interactive, Speed Index",
-"description":"Description of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page."},
-
-"lighthouse-core/config/default-config.js | overallImprovementsGroupTitle":{
-"message":"Overall Improvements",
-"description":"Title of an opportunity sub-section of the Performance category. Within this section are audits with imperative titles that suggest actions the user can take to improve the overall loading performance of their web page."},
-
-"lighthouse-core/config/default-config.js | performanceCategoryTitle":{
-"message":"Performance",
-"description":"Title of the Performance category of audits. Equivalent to 'Web performance', this term is inclusive of all web page speed and loading optimization topics. Also used as a label of a score gauge; try to limit to 20 characters."},
-
-"lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle":{
-"message":"Fast and reliable",
-"description":"Title of the Fast and Reliable section of the web app category. Within this section are audits that check if the web site loaded quickly and can reliably load even if the internet connection is very slow or goes offline."},
-
-"lighthouse-core/config/default-config.js | pwaInstallableGroupTitle":{
-"message":"Installable",
-"description":"Title of the Installable section of the web app category. Within this section are audits that check if Chrome supports installing the web site as an app on their device."},
-
-"lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle":{
-"message":"PWA Optimized",
-"description":"Title of the \"PWA Optimized\" section of the web app category. Within this section are audits that check if the developer has taken advantage of features to make their web page more enjoyable and engaging for the user."},
-
-"lighthouse-core/config/default-config.js | seoCategoryDescription":{
-"message":"These checks ensure that your page is optimized for search engine results ranking. There are additional factors Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769).",
-"description":"Description of the Search Engine Optimization (SEO) category. This is displayed at the top of a list of audits focused on optimizing a website for indexing by search engines. No character length limits. 'Learn More' becomes link text to additional documentation."},
-
-"lighthouse-core/config/default-config.js | seoCategoryManualDescription":{
-"message":"Run these additional validators on your site to check additional SEO best practices.",
-"description":"Description of the Search Engine Optimization (SEO) manual checks category, the additional validators must be run by hand in order to check all SEO best practices. This is displayed at the top of a list of manually run audits focused on optimizing a website for indexing by search engines. No character length limits."},
-
-"lighthouse-core/config/default-config.js | seoCategoryTitle":{
-"message":"SEO",
-"description":"Title of the Search Engine Optimization (SEO) category of audits. This is displayed at the top of a list of audits focused on topics related to optimizing a website for indexing by search engines. Also used as a label of a score gauge; try to limit to 20 characters."},
-
-"lighthouse-core/config/default-config.js | seoContentGroupDescription":{
-"message":"Format your HTML in a way that enables crawlers to better understand your app’s content.",
-"description":"Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots."},
-
-"lighthouse-core/config/default-config.js | seoContentGroupTitle":{
-"message":"Content Best Practices",
-"description":"Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website content more easily understood by search engine crawler bots."},
-
-"lighthouse-core/config/default-config.js | seoCrawlingGroupDescription":{
-"message":"To appear in search results, crawlers need access to your app.",
-"description":"Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers."},
-
-"lighthouse-core/config/default-config.js | seoCrawlingGroupTitle":{
-"message":"Crawling and Indexing",
-"description":"Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight ways to make a website accessible to search engine crawlers."},
-
-"lighthouse-core/config/default-config.js | seoMobileGroupDescription":{
-"message":"Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/).",
-"description":"Description of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices."},
-
-"lighthouse-core/config/default-config.js | seoMobileGroupTitle":{
-"message":"Mobile Friendly",
-"description":"Title of the navigation section within the Search Engine Optimization (SEO) category. Within this section are audits with descriptive titles that highlight opportunities to make a page more usable on mobile devices."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnCacheTTL":{
-"message":"Cache TTL",
-"description":"Label for a column in a data table; entries will be the time to live value of the cache header on a web resource."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnLocation":{
-"message":"Location",
-"description":"Label for a column in a data table; entries will be the location of a specific line of code in a file, in the format \"line: 102\"."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnRequests":{
-"message":"Requests",
-"description":"Label for a column in a data table; entries will be the number of network requests done by a webpage."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnResourceType":{
-"message":"Resource Type",
-"description":"Label for a column in a data table; entries will be types of resources loaded over the network, e.g. \"Scripts\", \"Third-Party\", \"Stylesheet\"."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnSize":{
-"message":"Size",
-"description":"Label for a column in a data table; entries will be the size of a web resource in kilobytes."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnTimeSpent":{
-"message":"Time Spent",
-"description":"Label for a column in a data table; entries will be the number of milliseconds spent during a particular activity."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnTransferSize":{
-"message":"Transfer Size",
-"description":"Label for a column in a data table; entries will be the number of kilobytes transferred to load a set of files."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnURL":{
-"message":"URL",
-"description":"Label for a column in a data table; entries will be the URL of a web resource"},
-
-"lighthouse-core/lib/i18n/i18n.js | columnWastedBytes":{
-"message":"Potential Savings",
-"description":"Label for a column in a data table; entries will be the number of kilobytes the user could reduce their page by if they implemented the suggestions."},
-
-"lighthouse-core/lib/i18n/i18n.js | columnWastedMs":{
-"message":"Potential Savings",
-"description":"Label for a column in a data table; entries will be the number of milliseconds the user could reduce page load by if they implemented the suggestions."},
-
-"lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings":{
-"message":"Potential savings of {wastedBytes, number, bytes} KB",
-"description":"Label shown per-audit to show how many bytes smaller the page could be if the user implemented the suggestions. The `{wastedBytes}` placeholder will be replaced with the number of bytes, shown in kilobytes (e.g. 148 KB)"},
-
-"lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings":{
-"message":"Potential savings of {wastedMs, number, milliseconds} ms",
-"description":"Label shown per-audit to show how many milliseconds faster the page load could be if the user implemented the suggestions. The `{wastedMs}` placeholder will be replaced with the time duration, shown in milliseconds (e.g. 140 ms)"},
-
-"lighthouse-core/lib/i18n/i18n.js | documentResourceType":{
-"message":"Document",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Document' resources loaded by a web page."},
-
-"lighthouse-core/lib/i18n/i18n.js | fontResourceType":{
-"message":"Font",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Font' resources loaded by a web page."},
-
-"lighthouse-core/lib/i18n/i18n.js | imageResourceType":{
-"message":"Image",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Image' resources loaded by a web page."},
-
-"lighthouse-core/lib/i18n/i18n.js | mediaResourceType":{
-"message":"Media",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Media' resources loaded by a web page. 'Media' refers to audio and video files."},
-
-"lighthouse-core/lib/i18n/i18n.js | ms":{
-"message":"{timeInMs, number, milliseconds} ms",
-"description":"Used to show the duration in milliseconds that something lasted. The `{timeInMs}` placeholder will be replaced with the time duration, shown in milliseconds (e.g. 63 ms)"},
-
-"lighthouse-core/lib/i18n/i18n.js | otherResourceType":{
-"message":"Other",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all resources loaded by a web page that don't fit into the categories of Document, Script, Stylesheet, Image, Media, & Font."},
-
-"lighthouse-core/lib/i18n/i18n.js | scriptResourceType":{
-"message":"Script",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Script' resources loaded by a web page. 'Script' refers to JavaScript or other files that are executable by a browser."},
-
-"lighthouse-core/lib/i18n/i18n.js | seconds":{
-"message":"{timeInMs, number, seconds} s",
-"description":"Used to show the duration in seconds that something lasted. The {timeInMs} placeholder will be replaced with the time duration, shown in seconds (e.g. 5.2 s)"},
-
-"lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType":{
-"message":"Stylesheet",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all 'Stylesheet' resources loaded by a web page. 'Stylesheet' refers to CSS stylesheets."},
-
-"lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType":{
-"message":"Third-party",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all third-party resources loaded by a web page. 'Third-party resources are items loaded from URLs that aren't controlled by the owner of the web page."},
-
-"lighthouse-core/lib/i18n/i18n.js | totalResourceType":{
-"message":"Total",
-"description":"Label for a row in a data table; entries will be the total number and byte size of all resources loaded by a web page."},
-
-"lighthouse-core/lib/lh-error.js | badTraceRecording":{
-"message":"Something went wrong with recording the trace over your page load. Please run Lighthouse again. ({errorCode})",
-"description":"Error message explaining that the network trace was not able to be recorded for the Lighthouse run."},
-
-"lighthouse-core/lib/lh-error.js | criTimeout":{
-"message":"Timeout waiting for initial Debugger Protocol connection.",
-"description":"Error message explaining that Lighthouse timed out while waiting for the initial connection to the Chrome Devtools protocol."},
-
-"lighthouse-core/lib/lh-error.js | didntCollectScreenshots":{
-"message":"Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. ({errorCode})",
-"description":"Error message explaining that the Lighthouse run was not able to collect screenshots through Chrome."},
-
-"lighthouse-core/lib/lh-error.js | dnsFailure":{
-"message":"DNS servers could not resolve the provided domain.",
-"description":"Error message explaining that the requested page could not be resolved by the DNS server."},
-
-"lighthouse-core/lib/lh-error.js | erroredRequiredArtifact":{
-"message":"Required {artifactName} gatherer encountered an error: {errorMessage}",
-"description":"Error message explaning that there was an error while trying to collect a resource that was required for testing. \"artifactName\" will be replaced with the name of the resource that wasn't collected; \"errorMessage\" will be replaced with a string description of the error that occurred."},
-
-"lighthouse-core/lib/lh-error.js | internalChromeError":{
-"message":"An internal Chrome error occurred. Please restart Chrome and try re-running Lighthouse.",
-"description":"Error message explaining that Chrome has encountered an error during the Lighthouse run, and that Chrome should be restarted."},
-
-"lighthouse-core/lib/lh-error.js | missingRequiredArtifact":{
-"message":"Required {artifactName} gatherer did not run.",
-"description":"Error message explaning that a resource that was required for testing was never collected. \"artifactName\" will be replaced with the name of the resource that wasn't collected."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailed":{
-"message":"Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests.",
-"description":"Error message explaining that Lighthouse could not load the requested URL and the steps that might be taken to fix the unreliability."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailedHung":{
-"message":"Lighthouse was unable to reliably load the URL you requested because the page stopped responding.",
-"description":"Error message explaining that Lighthouse couldn't complete because the page has stopped responding to its instructions."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure":{
-"message":"The URL you have provided does not have a valid security certificate. {securityMessages}",
-"description":"Error message explaining that the security certificate of the page Lighthouse observed was invalid, so the URL cannot be accessed. securityMessages will be replaced with one or more strings from the browser explaining what was insecure about the page load."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial":{
-"message":"Chrome prevented page load with an interstitial. Make sure you are testing the correct URL and that the server is properly responding to all requests.",
-"description":"Error message explaining that Chrome prevented the page from loading and displayed an interstitial screen instead, so the URL cannot be accessed."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails":{
-"message":"Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Details: {errorDetails})",
-"description":"Error message explaining that Lighthouse could not load the requested URL and the steps that might be taken to fix the unreliability."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode":{
-"message":"Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Status code: {statusCode})",
-"description":"Error message explaining that Lighthouse could not load the requested URL and the steps that might be taken to fix the unreliability."},
-
-"lighthouse-core/lib/lh-error.js | pageLoadTookTooLong":{
-"message":"Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse. ({errorCode})",
-"description":"Error message explaining that the page loaded too slowly to perform a Lighthouse run."},
-
-"lighthouse-core/lib/lh-error.js | protocolTimeout":{
-"message":"Waiting for DevTools protocol response has exceeded the allotted time. (Method: {protocolMethod})",
-"description":"Error message explaining that the Chrome Devtools protocol has exceeded the maximum timeout allowed."},
-
-"lighthouse-core/lib/lh-error.js | requestContentTimeout":{
-"message":"Fetching resource content has exceeded the allotted time",
-"description":"Error message explaining that fetching the resources of the webpage has taken longer than the maximum time."},
-
-"lighthouse-core/lib/lh-error.js | urlInvalid":{
-"message":"The URL you have provided appears to be invalid.",
-"description":"Error message explaining that the provided URL Lighthouse points to is not valid, and cannot be loaded."},
-
-"lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip":{
-"message":"Show audits",
-"description":"The tooltip text on an expandable chevron icon. Clicking the icon expands a section to reveal a list of audit results that was hidden by default."},
-
-"lighthouse-core/report/html/renderer/util.js | crcInitialNavigation":{
-"message":"Initial Navigation",
-"description":"String of text shown in a graphical representation of the flow of network requests for the web page. This label represents the initial network request that fetches an HTML page. This navigation may be redirected (eg. Initial navigation to http://example.com redirects to https://www.example.com)."},
-
-"lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel":{
-"message":"Maximum critical path latency:",
-"description":"Label of value shown in the summary of critical request chains. Refers to the total amount of time (milliseconds) of the longest critical path chain/sequence of network requests. Example value: 2310 ms"},
-
-"lighthouse-core/report/html/renderer/util.js | errorLabel":{
-"message":"Error!",
-"description":"A label, shown next to an audit title or metric title, indicating that there was an error computing it. The user can hover on the label to reveal a tooltip with the extended error message. Translation should be short (< 20 characters)."},
-
-"lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo":{
-"message":"Report error: no audit information",
-"description":"An error string displayed next to a particular audit when it has errored, but not provided any specific error message."},
-
-"lighthouse-core/report/html/renderer/util.js | labDataTitle":{
-"message":"Lab Data",
-"description":"Title of the lab data section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. \"Lab\" is an abbreviated form of \"laboratory\", and refers to the fact that the data is from a controlled test of a website, not measurements from real users visiting that site."},
-
-"lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription":{
-"message":"[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.",
-"description":"Explanation shown to users below performance results to inform them that the test was done with a 4G network connection and to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. 'Lighthouse' becomes link text to additional documentation."},
-
-"lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle":{
-"message":"Additional items to manually check",
-"description":"Section heading shown above a list of audits that were not computed by Lighthouse. They serve as a list of suggestions for the user to go and manually check. For example, Lighthouse can't automate testing cross-browser compatibility, so that is listed within this section, so the user is reminded to test it themselves. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list."},
-
-"lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle":{
-"message":"Not applicable",
-"description":"Section heading shown above a list of audits that do not apply to the page. For example, if an audit is 'Are images optimized?', but the page has no images on it, the audit will be marked as not applicable. This is neither passing or failing. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list."},
-
-"lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel":{
-"message":"Opportunity",
-"description":"Column heading label for the listing of opportunity audits. Each audit title represents an opportunity. There are only 2 columns, so no strict character limit."},
-
-"lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel":{
-"message":"Estimated Savings",
-"description":"Column heading label for the estimated page load savings of opportunity audits. Estimated Savings is the total amount of time (in seconds) that Lighthouse computed could be reduced from the total page load time, if the suggested action is taken. There are only 2 columns, so no strict character limit."},
-
-"lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle":{
-"message":"Passed audits",
-"description":"Section heading shown above a list of audits that are passing. 'Passed' here refers to a passing grade. This section is collapsed by default, as the user should be focusing on the failed audits instead. Users can click this heading to reveal the list."},
-
-"lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel":{
-"message":"Collapse snippet",
-"description":"Label for button that only shows a few lines of the snippet when clicked"},
-
-"lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel":{
-"message":"Expand snippet",
-"description":"Label for button that shows all lines of the snippet when clicked"},
-
-"lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel":{
-"message":"Show 3rd-party resources",
-"description":"This label is for a checkbox above a table of items loaded by a web page. The checkbox is used to show or hide third-party (or \"3rd-party\") resources in the table, where \"third-party resources\" refers to items loaded by a web page from URLs that aren't controlled by the owner of the web page."},
-
-"lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage":{
-"message":"There were issues affecting this run of Lighthouse:",
-"description":"Label shown preceding any important warnings that may have invalidated the entire report. For example, if the user has Chrome extensions installed, they may add enough performance overhead that Lighthouse's performance metrics are unreliable. If shown, this will be displayed at the top of the report UI."},
-
-"lighthouse-core/report/html/renderer/util.js | varianceDisclaimer":{
-"message":"Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted).",
-"description":"Disclaimer shown to users below the metric values (First Contentful Paint, Time to Interactive, etc) to warn them that the numbers they see will likely change slightly the next time they run Lighthouse."},
-
-"lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle":{
-"message":"Passed audits but with warnings",
-"description":"Section heading shown above a list of passed audits that contain warnings. Audits under this section do not negatively impact the score, but Lighthouse has generated some potentially actionable suggestions that should be reviewed. This section is expanded by default and displays after the failing audits."},
-
-"lighthouse-core/report/html/renderer/util.js | warningHeader":{
-"message":"Warnings: ",
-"description":"This label is shown above a bulleted list of warnings. It is shown directly below an audit that produced warnings. Warnings describe situations the user should be aware of, as Lighthouse was unable to complete all the work required on this audit. For example, The 'Unable to decode image (biglogo.jpg)' warning may show up below an image encoding audit."},
-
-"stack-packs/packs/wordpress.js | efficient_animated_content":{
-"message":"Consider uploading your GIF to a service which will make it available to embed as an HTML5 video.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by encoding animated images as video, in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | offscreen_images":{
-"message":"Install a [lazy-load WordPress plugin](https://wordpress.org/plugins/search/lazy+load/) that provides the ability to defer any offscreen images, or switch to a theme that provides that functionality. Also consider using [the AMP plugin](https://wordpress.org/plugins/amp/).",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by lazy loading images that are initially offscreen in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | render_blocking_resources":{
-"message":"There are a number of WordPress plugins that can help you [inline critical assets](https://wordpress.org/plugins/search/critical+css/) or [defer less important resources](https://wordpress.org/plugins/search/defer+css+javascript/). Beware that optimizations provided by these plugins may break features of your theme or plugins, so you will likely need to make code changes.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by reducing the amount of render blocking resources present on their page, in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | time_to_first_byte":{
-"message":"Themes, plugins, and server specifications all contribute to server response time. Consider finding a more optimized theme, carefully selecting an optimization plugin, and/or upgrading your server.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve the time to first byte speed metric, in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | total_byte_weight":{
-"message":"Consider showing excerpts in your post lists (e.g. via the more tag), reducing the number of posts shown on a given page, breaking your long posts into multiple pages, or using a plugin to lazy-load comments.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve site loading performance by reducing the total bytes delivered by their page in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | unminified_css":{
-"message":"A number of [WordPress plugins](https://wordpress.org/plugins/search/minify+css/) can speed up your site by concatenating, minifying, and compressing your styles. You may also want to use a build process to do this minification up-front if possible.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by minifying their CSS files in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | unminified_javascript":{
-"message":"A number of [WordPress plugins](https://wordpress.org/plugins/search/minify+javascript/) can speed up your site by concatenating, minifying, and compressing your scripts. You may also want to use a build process to do this minification up front if possible.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by minifying their Javascript files in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | unused_css_rules":{
-"message":"Consider reducing, or switching, the number of [WordPress plugins](https://wordpress.org/plugins/) loading unused CSS in your page. To identify plugins that are adding extraneous CSS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plugin responsible from the URL of the stylesheet. Look out for plugins that have many stylesheets in the list which have a lot of red in code coverage. A plugin should only enqueue a stylesheet if it is actually used on the page.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by removing unused CSS, in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | unused_javascript":{
-"message":"Consider reducing, or switching, the number of [WordPress plugins](https://wordpress.org/plugins/) loading unused JavaScript in your page. To identify plugins that are adding extraneous JS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plugin responsible from the URL of the script. Look out for plugins that have many scripts in the list which have a lot of red in code coverage. A plugin should only enqueue a script if it is actually used on the page.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by removing unused Javascript files in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | uses_long_cache_ttl":{
-"message":"Read about [Browser Caching in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching).",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve their site by enabling long caching in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | uses_optimized_images":{
-"message":"Consider using an [image optimization WordPress plugin](https://wordpress.org/plugins/search/optimize+images/) that compresses your images while retaining quality.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve site performance by optimizing images, in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | uses_responsive_images":{
-"message":"Upload images directly through the [media library](https://codex.wordpress.org/Media_Library_Screen) to ensure that the required image sizes are available, and then insert them from the media library or use the image widget to ensure the optimal image sizes are used (including those for the responsive breakpoints). Avoid using `Full Size` images unless the dimensions are adequate for their usage. [Learn More](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size).",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance by using responsive images in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | uses_text_compression":{
-"message":"You can enable text compression in your web server configuration.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve performance via enabling text compression in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."},
-
-"stack-packs/packs/wordpress.js | uses_webp_images":{
-"message":"Consider using a [plugin](https://wordpress.org/plugins/search/convert+webp/) or service that will automatically convert your uploaded images to the optimal formats.",
-"description":"Additional description of a Lighthouse audit that tells the user how they can improve image loading by using webp in the context of the Wordpress CMS platform. This is displayed after a user expands the section to see more. No character length limits. Links in (parenthesis) become link texts to additional documentation."}};
-
-
-
-},{}],68:[function(require,module,exports){
(function(__filename,__dirname){
@@ -28804,10 +27636,12 @@ const path=require('path');
const isDeepEqual=require('lodash.isequal');
const log=require('lighthouse-logger');
const MessageFormat=require('intl-messageformat').default;
-const MessageParser=require('intl-messageformat-parser');
const lookupClosestLocale=require('lookup-closest-locale');
const LOCALES=require('./locales.js');
+
+
+
const LH_ROOT=path.join(__dirname,'../../../');
const MESSAGE_INSTANCE_ID_REGEX=/(.* \| .*) # (\d+)$/;
@@ -28816,16 +27650,24 @@ const MESSAGE_INSTANCE_ID_QUICK_REGEX=/ # \d+$/;
(()=>{
-try{
+
+
+
+require('intl-pluralrules');
+
const IntlPolyfill=require('intl');
+
if(!IntlPolyfill.NumberFormat)return;
+
+const minimumLocales=['en','es','ru','zh'];
+const supportedLocales=Intl.NumberFormat.supportedLocalesOf(minimumLocales);
+
+if(supportedLocales.length!==minimumLocales.length){
Intl.NumberFormat=IntlPolyfill.NumberFormat;
Intl.DateTimeFormat=IntlPolyfill.DateTimeFormat;
-}catch(_){
-log.warn('i18n','Failed to install `intl` polyfill');
}
})();
@@ -28860,6 +27702,8 @@ columnRequests:'Requests',
columnTransferSize:'Transfer Size',
+columnName:'Name',
+
totalResourceType:'Total',
documentResourceType:'Document',
@@ -28922,37 +27766,106 @@ return closestLocale||'en';
-function _preprocessMessageValues(icuMessage,values={}){
-const clonedValues=JSON.parse(JSON.stringify(values));
-const parsed=MessageParser.parse(icuMessage);
-parsed.elements.
-filter(el=>el.type==='argumentElement').
-forEach(el=>{
-if(el.id&&el.id in values===false){
-throw new Error(`ICU Message contains a value reference ("${el.id}") that wasn't provided`);
+
+
+
+
+
+
+
+
+
+
+
+
+
+function collectAllCustomElementsFromICU(icuElements,seenElementsById=new Map()){
+for(const el of icuElements){
+
+if(el.type!=='argumentElement')continue;
+
+seenElementsById.set(el.id,el);
+
+
+if(!el.format||el.format.type!=='pluralFormat')continue;
+
+for(const option of el.format.options){
+
+collectAllCustomElementsFromICU(option.value.elements,seenElementsById);
}
-});
+}
+
+return seenElementsById;
+}
+
+
+
+
+
+
+
+
+
+
+function _preformatValues(icuMessage,messageFormatter,values){
+const elementMap=collectAllCustomElementsFromICU(messageFormatter.getAst().elements);
+const argumentElements=[...elementMap.values()];
-parsed.elements.
-filter(el=>el.format&&el.format.style==='milliseconds').
+const formattedValues={};
-forEach(el=>clonedValues[el.id]=Math.round(clonedValues[el.id]/10)*10);
+for(const{id,format}of argumentElements){
+
+if(id&&id in values===false){
+throw new Error(`ICU Message "${icuMessage}" contains a value reference ("${id}") `+
+`that wasn't provided`);
+}
+
+const value=values[id];
-parsed.elements.
-filter(el=>el.format&&el.format.style==='seconds'&&el.id==='timeInMs').
+if(!format||format.type!=='numberFormat'){
+formattedValues[id]=value;
+continue;
+}
-forEach(el=>clonedValues[el.id]=Math.round(clonedValues[el.id]/100)/10);
+if(typeof value!=='number'){
+throw new Error(`ICU Message "${icuMessage}" contains a numeric reference ("${id}") `+
+'but provided value was not a number');
+}
-parsed.elements.
-filter(el=>el.format&&el.format.style==='bytes').
+if(format.style==='milliseconds'){
-forEach(el=>clonedValues[el.id]=clonedValues[el.id]/1024);
+formattedValues[id]=Math.round(value/10)*10;
+}else if(format.style==='seconds'&&id==='timeInMs'){
-return clonedValues;
+formattedValues[id]=Math.round(value/100)/10;
+}else if(format.style==='bytes'){
+
+formattedValues[id]=value/1024;
+}else{
+
+formattedValues[id]=value;
+}
+}
+
+
+for(const valueId of Object.keys(values)){
+if(valueId in formattedValues)continue;
+
+
+if(valueId==='errorCode'){
+formattedValues.errorCode=values.errorCode;
+continue;
+}
+
+throw new Error(`Provided value "${valueId}" does not match any placeholder in `+
+`ICU message "${icuMessage}"`);
+}
+
+return formattedValues;
}
@@ -28974,24 +27887,38 @@ const _ICUMsgNotFoundMsg='ICU message not found in destination locale';
-function _formatIcuMessage(locale,icuMessageId,fallbackMessage,values){
+function _formatIcuMessage(locale,icuMessageId,uiStringMessage,values={}){
const localeMessages=LOCALES[locale];
if(!localeMessages)throw new Error(`Unsupported locale '${locale}'`);
+let localeMessage=localeMessages[icuMessageId]&&localeMessages[icuMessageId].message;
+
-const localeMessage=localeMessages[icuMessageId]&&localeMessages[icuMessageId].message;
+if(!localeMessage&&uiStringMessage){
+
+localeMessage=uiStringMessage;
+
+
+if(!LOCALES.en[icuMessageId]||localeMessage!==LOCALES.en[icuMessageId].message){
+log.warn('i18n',`Message "${icuMessageId}" does not match its 'en' counterpart. `+
+`Run 'i18n' to update.`);
+}
+}
+
+if(!localeMessage){
+throw new Error(_ICUMsgNotFoundMsg);
+}
-const messageForMessageFormat=localeMessage||fallbackMessage;
-if(messageForMessageFormat===undefined)throw new Error(_ICUMsgNotFoundMsg);
const localeForMessageFormat=locale==='en-XA'||locale==='en-XL'?'de-DE':locale;
-const valuesForMessageFormat=_preprocessMessageValues(messageForMessageFormat,values);
+const formatter=new MessageFormat(localeMessage,localeForMessageFormat,formats);
-const formatter=new MessageFormat(messageForMessageFormat,localeForMessageFormat,formats);
-const formattedString=formatter.format(valuesForMessageFormat);
-return{formattedString,icuMessage:messageForMessageFormat};
+const valuesForMessageFormat=_preformatValues(localeMessage,formatter,values);
+
+const formattedString=formatter.format(valuesForMessageFormat);
+return{formattedString,icuMessage:localeMessage};
}
@@ -29034,11 +27961,20 @@ return strings;
+
+
+
function createMessageInstanceIdFn(filename,fileStrings){
const mergedStrings={...UIStrings,...fileStrings};
+
+
+
+
+
+
const getMessageInstanceIdFn=(icuMessage,values)=>{
const keyname=Object.keys(mergedStrings).find(key=>mergedStrings[key]===icuMessage);
if(!keyname)throw new Error(`Could not locate: ${icuMessage}`);
@@ -29164,6 +28100,19 @@ replaceInObject(inputObject,icuMessagePaths);
return icuMessagePaths;
}
+
+
+
+
+
+
+
+
+
+function registerLocaleData(locale,lhlMessages){
+LOCALES[locale]=lhlMessages;
+}
+
module.exports={
_formatPathAsString,
_ICUMsgNotFoundMsg,
@@ -29174,11 +28123,13 @@ createMessageInstanceIdFn,
getFormatted,
getFormattedFromIdAndValues,
replaceIcuMessageInstanceIds,
-isIcuMessage};
+isIcuMessage,
+collectAllCustomElementsFromICU,
+registerLocaleData};
}).call(this,"/lighthouse-core/lib/i18n/i18n.js","/lighthouse-core/lib/i18n");
-},{"./locales.js":69,"intl":101,"intl-messageformat":116,"intl-messageformat-parser":114,"lighthouse-logger":128,"lodash.isequal":129,"lookup-closest-locale":130,"path":143}],69:[function(require,module,exports){
+},{"./locales.js":68,"intl":101,"intl-messageformat":119,"intl-pluralrules":101,"lighthouse-logger":125,"lodash.isequal":126,"lookup-closest-locale":127,"path":140}],68:[function(require,module,exports){
@@ -29197,9 +28148,12 @@ isIcuMessage};
+
+
+
const locales={
-'en-US':require('./en-US.json'),
-'en':require('./en-US.json'),
+'en-US':require('./locales/en-US.json'),
+'en':require('./locales/en-US.json'),
'en-AU':require('./locales/en-GB.json'),
@@ -29292,7 +28246,7 @@ const locales={
module.exports=locales;
-},{"./en-US.json":67,"./locales/ar-XB.json":101,"./locales/ar.json":101,"./locales/bg.json":101,"./locales/ca.json":101,"./locales/cs.json":101,"./locales/da.json":101,"./locales/de.json":101,"./locales/el.json":101,"./locales/en-GB.json":101,"./locales/en-XA.json":101,"./locales/en-XL.json":101,"./locales/es-419.json":101,"./locales/es.json":101,"./locales/fi.json":101,"./locales/fil.json":101,"./locales/fr.json":101,"./locales/he.json":101,"./locales/hi.json":101,"./locales/hr.json":101,"./locales/hu.json":101,"./locales/id.json":101,"./locales/it.json":101,"./locales/ja.json":101,"./locales/ko.json":101,"./locales/lt.json":101,"./locales/lv.json":101,"./locales/nl.json":101,"./locales/no.json":101,"./locales/pl.json":101,"./locales/pt-PT.json":101,"./locales/pt.json":101,"./locales/ro.json":101,"./locales/ru.json":101,"./locales/sk.json":101,"./locales/sl.json":101,"./locales/sr-Latn.json":101,"./locales/sr.json":101,"./locales/sv.json":101,"./locales/ta.json":101,"./locales/te.json":101,"./locales/th.json":101,"./locales/tr.json":101,"./locales/uk.json":101,"./locales/vi.json":101,"./locales/zh-HK.json":101,"./locales/zh-TW.json":101,"./locales/zh.json":101}],70:[function(require,module,exports){
+},{"./locales/ar-XB.json":101,"./locales/ar.json":101,"./locales/bg.json":101,"./locales/ca.json":101,"./locales/cs.json":101,"./locales/da.json":101,"./locales/de.json":101,"./locales/el.json":101,"./locales/en-GB.json":101,"./locales/en-US.json":101,"./locales/en-XA.json":101,"./locales/en-XL.json":101,"./locales/es-419.json":101,"./locales/es.json":101,"./locales/fi.json":101,"./locales/fil.json":101,"./locales/fr.json":101,"./locales/he.json":101,"./locales/hi.json":101,"./locales/hr.json":101,"./locales/hu.json":101,"./locales/id.json":101,"./locales/it.json":101,"./locales/ja.json":101,"./locales/ko.json":101,"./locales/lt.json":101,"./locales/lv.json":101,"./locales/nl.json":101,"./locales/no.json":101,"./locales/pl.json":101,"./locales/pt-PT.json":101,"./locales/pt.json":101,"./locales/ro.json":101,"./locales/ru.json":101,"./locales/sk.json":101,"./locales/sl.json":101,"./locales/sr-Latn.json":101,"./locales/sr.json":101,"./locales/sv.json":101,"./locales/ta.json":101,"./locales/te.json":101,"./locales/th.json":101,"./locales/tr.json":101,"./locales/uk.json":101,"./locales/vi.json":101,"./locales/zh-HK.json":101,"./locales/zh-TW.json":101,"./locales/zh.json":101}],69:[function(require,module,exports){
@@ -29366,7 +28320,7 @@ doExist,
pngSizedAtLeast};
-},{"./url-shim.js":"url"}],71:[function(require,module,exports){
+},{"./url-shim.js":"url"}],70:[function(require,module,exports){
@@ -29574,7 +28528,80 @@ simulationNamesToIgnore:[
convertNodeTimingsToTrace};
-},{}],72:[function(require,module,exports){
+},{}],71:[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Driver=require('../gather/driver.js');
+
+class LHElement{
+
+
+
+
+constructor(element,driver){
+if(!element||!driver){
+throw Error('Driver and element required to create Element');
+}
+this.driver=driver;
+this.element=element;
+}
+
+
+
+
+
+getAttribute(name){
+return this.driver.
+sendCommand('DOM.getAttributes',{
+nodeId:this.element.nodeId}).
+
+
+
+
+then(resp=>{
+const attrIndex=resp.attributes.indexOf(name);
+if(attrIndex===-1){
+return null;
+}
+
+return resp.attributes[attrIndex+1];
+});
+}
+
+
+
+
+getNodeId(){
+return this.element.nodeId;
+}
+
+
+
+
+
+getProperty(propName){
+return this.driver.
+sendCommand('DOM.resolveNode',{
+nodeId:this.element.nodeId}).
+
+then(resp=>{
+if(!resp.object.objectId){
+return null;
+}
+return this.driver.getObjectProperty(resp.object.objectId,propName);
+}).
+catch(()=>null);
+}}
+
+
+module.exports=LHElement;
+
+},{"../gather/driver.js":52}],72:[function(require,module,exports){
(function(__filename){
@@ -29588,18 +28615,36 @@ const i18n=require('./i18n/i18n.js');
const UIStrings={
+
+
+
didntCollectScreenshots:`Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. ({errorCode})`,
+
+
+
badTraceRecording:'Something went wrong with recording the trace over your page load. Please run Lighthouse again. ({errorCode})',
+
+
+
pageLoadTookTooLong:'Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse. ({errorCode})',
pageLoadFailed:'Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests.',
+
+
+
pageLoadFailedWithStatusCode:'Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Status code: {statusCode})',
+
+
+
pageLoadFailedWithDetails:'Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Details: {errorDetails})',
+
+
+
pageLoadFailedInsecure:'The URL you have provided does not have a valid security certificate. {securityMessages}',
pageLoadFailedInterstitial:'Chrome prevented page load with an interstitial. Make sure you are testing the correct URL and that the server is properly responding to all requests.',
@@ -29610,6 +28655,9 @@ requestContentTimeout:'Fetching resource content has exceeded the allotted time'
urlInvalid:'The URL you have provided appears to be invalid.',
+
+
+
protocolTimeout:'Waiting for DevTools protocol response has exceeded the allotted time. (Method: {protocolMethod})',
dnsFailure:'DNS servers could not resolve the provided domain.',
@@ -29618,8 +28666,15 @@ pageLoadFailedHung:'Lighthouse was unable to reliably load the URL you requested
criTimeout:'Timeout waiting for initial Debugger Protocol connection.',
+
+
+
missingRequiredArtifact:'Required {artifactName} gatherer did not run.',
+
+
+
+
erroredRequiredArtifact:'Required {artifactName} gatherer encountered an error: {errorMessage}'};
@@ -29651,6 +28706,7 @@ super(errorDefinition.code);
this.name='LHError';
this.code=errorDefinition.code;
+
this.friendlyMessage=str_(errorDefinition.message,{errorCode:this.code,...properties});
this.lhrRuntimeError=!!errorDefinition.lhrRuntimeError;
if(properties)Object.assign(this,properties);
@@ -29802,6 +28858,10 @@ NO_FMP:{
code:'NO_FMP',
message:UIStrings.badTraceRecording},
+NO_LCP:{
+code:'NO_LCP',
+message:UIStrings.badTraceRecording},
+
FMP_TOO_LATE_FOR_FCPUI:{code:'FMP_TOO_LATE_FOR_FCPUI',message:UIStrings.pageLoadTookTooLong},
@@ -29934,7 +28994,7 @@ module.exports=LighthouseError;
module.exports.UIStrings=UIStrings;
}).call(this,"/lighthouse-core/lib/lh-error.js");
-},{"./i18n/i18n.js":68}],73:[function(require,module,exports){
+},{"./i18n/i18n.js":67}],73:[function(require,module,exports){
@@ -30639,7 +29699,7 @@ this._recordsById=new Map();
getInflightRecords(){
-return this._records.filter(record=>!NetworkRecorder.isNetworkRecordFinished(record));
+return this._records.filter(record=>!record.finished);
}
getRecords(){
@@ -30663,24 +29723,35 @@ return super.once(event,listener);
}
isIdle(){
-return!!this._getActiveIdlePeriod(0);
+return this._isActiveIdlePeriod(0);
}
is2Idle(){
-return!!this._getActiveIdlePeriod(2);
+return this._isActiveIdlePeriod(2);
}
-_getActiveIdlePeriod(allowedRequests){
-const quietPeriods=NetworkRecorder.findNetworkQuietPeriods(this._records,allowedRequests);
-return quietPeriods.find(period=>!Number.isFinite(period.end));
+
+
+
+_isActiveIdlePeriod(allowedRequests){
+let inflightRequests=0;
+
+for(let i=0;i<this._records.length;i++){
+const record=this._records[i];
+if(record.finished)continue;
+if(IGNORED_NETWORK_SCHEMES.includes(record.parsedURL.scheme))continue;
+inflightRequests++;
+}
+
+return inflightRequests<=allowedRequests;
}
_emitNetworkStatus(){
-const zeroQuiet=this._getActiveIdlePeriod(0);
-const twoQuiet=this._getActiveIdlePeriod(2);
+const zeroQuiet=this.isIdle();
+const twoQuiet=this.is2Idle();
if(twoQuiet&&zeroQuiet){
log.verbose('NetworkRecorder','network fully-quiet');
@@ -30703,28 +29774,6 @@ this.emit('networkbusy');
-static _isQUICAndFinished(record){
-const isQUIC=record.responseHeaders&&record.responseHeaders.
-some(header=>header.name.toLowerCase()==='alt-svc'&&/quic/.test(header.value));
-const receivedHeaders=record.timing&&record.timing.receiveHeadersEnd>0;
-return!!(isQUIC&&receivedHeaders&&record.endTime);
-}
-
-
-
-
-
-static isNetworkRecordFinished(record){
-return record.finished||
-NetworkRecorder._isQUICAndFinished(record);
-}
-
-
-
-
-
-
-
static findNetworkQuietPeriods(networkRecords,allowedConcurrentRequests,endTime=Infinity){
@@ -30739,7 +29788,7 @@ return;
timeBoundaries.push({time:record.startTime*1000,isStart:true});
-if(NetworkRecorder.isNetworkRecordFinished(record)){
+if(record.finished){
timeBoundaries.push({time:record.endTime*1000,isStart:false});
}
});
@@ -30809,11 +29858,12 @@ this._emitNetworkStatus();
onRequestWillBeSent(event){
const data=event.params;
-const originalRequest=this._findRealRequestAndSetSource(data.requestId,event.source);
+const originalRequest=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!originalRequest){
const request=new NetworkRequest();
request.onRequestWillBeSent(data);
+request.sessionId=event.sessionId;
this.onRequestStarted(request);
return;
}
@@ -30849,7 +29899,7 @@ this.onRequestFinished(originalRequest);
onRequestServedFromCache(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onRequestServedFromCache();
}
@@ -30859,7 +29909,7 @@ request.onRequestServedFromCache();
onResponseReceived(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onResponseReceived(data);
}
@@ -30869,7 +29919,7 @@ request.onResponseReceived(data);
onDataReceived(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onDataReceived(data);
}
@@ -30879,7 +29929,7 @@ request.onDataReceived(data);
onLoadingFinished(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onLoadingFinished(data);
this.onRequestFinished(request);
@@ -30890,7 +29940,7 @@ this.onRequestFinished(request);
onLoadingFailed(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onLoadingFailed(data);
this.onRequestFinished(request);
@@ -30901,7 +29951,7 @@ this.onRequestFinished(request);
onResourceChangedPriority(event){
const data=event.params;
-const request=this._findRealRequestAndSetSource(data.requestId,event.source);
+const request=this._findRealRequestAndSetSession(data.requestId,event.sessionId);
if(!request)return;
request.onResourceChangedPriority(data);
}
@@ -30933,7 +29983,7 @@ default:return;}
-_findRealRequestAndSetSource(requestId,source){
+_findRealRequestAndSetSession(requestId,sessionId){
let request=this._recordsById.get(requestId);
if(!request||!request.isValid)return undefined;
@@ -30941,7 +29991,8 @@ while(request.redirectDestination){
request=request.redirectDestination;
}
-request.setSource(source);
+request.setSession(sessionId);
+
return request;
}
@@ -30998,7 +30049,7 @@ return records;
module.exports=NetworkRecorder;
-},{"./network-request.js":76,"events":108,"lighthouse-logger":128}],76:[function(require,module,exports){
+},{"./network-request.js":76,"events":108,"lighthouse-logger":125}],76:[function(require,module,exports){
(function(global){
@@ -31134,12 +30185,6 @@ this.frameId='';
-this.targetId=undefined;
-
-
-
-
-
this.sessionId=undefined;
this.isLinkPreload=false;
}
@@ -31276,14 +30321,8 @@ this._updateResponseReceivedTimeIfNecessary();
-setSource(source){
-if(source){
-this.targetId=source.targetId;
-this.sessionId=source.sessionId;
-}else{
-this.targetId=undefined;
-this.sessionId=undefined;
-}
+setSession(sessionId){
+this.sessionId=sessionId;
}
@@ -31716,6 +30755,43 @@ return parts.join(' > ');
+function isPositionFixed(element){
+
+
+
+
+
+function getStyleAttrValue(element,attr){
+
+return element.style[attr]||window.getComputedStyle(element)[attr];
+}
+
+
+const htmlEl=document.querySelector('html');
+if(htmlEl.scrollHeight<=htmlEl.clientHeight||
+!['scroll','auto','visible'].includes(getStyleAttrValue(htmlEl,'overflowY'))){
+return false;
+}
+
+let currentEl=element;
+while(currentEl){
+const position=getStyleAttrValue(currentEl,'position');
+if(position==='fixed'||position==='sticky'){
+return true;
+}
+currentEl=currentEl.parentElement;
+}
+return false;
+}
+
+
+
+
+
+
+
+
+
function getNodeLabel(node){
@@ -31762,7 +30838,8 @@ getNodePathString:getNodePath.toString(),
getNodeSelectorString:getNodeSelector.toString(),
getNodeSelector:getNodeSelector,
getNodeLabel:getNodeLabel,
-getNodeLabelString:getNodeLabel.toString()};
+getNodeLabelString:getNodeLabel.toString(),
+isPositionFixedString:isPositionFixed.toString()};
},{}],78:[function(require,module,exports){
@@ -32142,7 +31219,7 @@ log.warn(
module.exports=sentryDelegate;
-},{"lighthouse-logger":128,"raven":101}],80:[function(require,module,exports){
+},{"lighthouse-logger":125,"raven":101}],80:[function(require,module,exports){
@@ -32159,7 +31236,7 @@ module.exports=sentryDelegate;
'use strict';
-const libDetectorSource="var UNKNOWN_VERSION = null;\nvar d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests = {\n\n 'GWT': {\n icon: 'gwt',\n url: 'http://www.gwtproject.org/',\n test: function(win) {\n // pretty complicated, many possible tell tales\n var doc = win.document,\n hasHistFrame = doc.getElementById('__gwt_historyFrame'),\n hasGwtUid = doc.gwt_uid,\n hasBodyListener = doc.body.__listener,\n hasBodyEventBits = doc.body.__eventBits,\n hasModules = win.__gwt_activeModules,\n hasJsonP = win.__gwt_jsonp__,\n hasRootWinApp = win.__gwt_scriptsLoaded || win.__gwt_stylesLoaded || win.__gwt_activeModules;\n\n // use the many possible indicators\n if(hasHistFrame || hasGwtUid || hasBodyListener || hasBodyEventBits || hasModules || hasJsonP || hasRootWinApp) {\n\n // carefully look at frames, but only if certain is GWT frame\n var frames = doc.getElementsByTagName('iframe'),\n gwtVersion = UNKNOWN_VERSION;\n for(var n=0; n<frames.length; n++) {\n // catch security access errors\n try {\n var hasNegativeTabIndex = frames[n].tabIndex < 0; // on for GWT\n if(hasNegativeTabIndex && frames[n].contentWindow && frames[n].contentWindow.$gwt_version) {\n gwtVersion = frames[n].contentWindow.$gwt_version;\n break;\n }\n }\n catch(e) {}\n }\n\n if(gwtVersion=='0.0.999') {\n gwtVersion = 'Google Internal';\n }\n\n return { version: gwtVersion };\n }\n return false;\n }\n },\n\n 'Ink': {\n icon: 'ink',\n url: 'http://ink.sapo.pt/',\n test: function(win) {\n if (win.Ink && win.Ink.createModule) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Vaadin': {\n icon: 'vaadin',\n url: 'https://vaadin.com/',\n test: function(win) {\n if (win.vaadin && win.vaadin.registerWidgetset) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Bootstrap': {\n icon: 'bootstrap',\n url: 'http://getbootstrap.com/',\n npm: 'bootstrap',\n // look for a function Boostrap has added to jQuery - regex for BS 2 & 3\n test: function(win) {\n var jQueryAvailable = win.$ && win.$.fn,\n RE_PREFIX_V2 = '\\\\$this\\\\.data\\\\((?:\\'|\")',\n RE_PREFIX_V3 = '\\\\$this\\\\.data\\\\((?:\\'|\")(?:bs\\\\.){1}',\n bootstrapComponents = [\n 'affix', 'alert', 'button', 'carousel', 'collapse', 'dropdown',\n 'modal', 'popover', 'scrollspy', 'tab', 'tooltip'\n ];\n\n if(jQueryAvailable) {\n var bootstrapVersion;\n\n bootstrapComponents.some(function(component) {\n if(win.$.fn[component]) {\n // Bootstrap >= 3.2.0 detection\n if(win.$.fn[component].Constructor && win.$.fn[component].Constructor.VERSION) {\n bootstrapVersion = win.$.fn[component].Constructor.VERSION;\n return true;\n // Bootstrap >= 2.0.0 and <= 3.1.0 detection\n } else if(new RegExp(RE_PREFIX_V3 + component).test(win.$.fn[component].toString())) {\n bootstrapVersion = '>= 3.0.0 & <= 3.1.1';\n return true;\n // Bootstrap < 3.1.0 detection\n } else if(new RegExp(RE_PREFIX_V2 + component).test(win.$.fn[component].toString())) {\n bootstrapVersion = '>= 2.0.0 & <= 2.3.2';\n return true;\n }\n }\n\n return false;\n });\n\n if (bootstrapVersion) {\n return { version: bootstrapVersion };\n }\n }\n\n return false;\n }\n },\n\n 'Zurb': {\n icon: 'zurb',\n url: 'https://foundation.zurb.com/',\n npm: 'foundation-sites',\n test: function(win) {\n if(win.Foundation && win.Foundation.Toggler) {\n return { version: win.Foundation.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Polymer': {\n icon: 'polymer',\n url: 'https://www.polymer-project.org/',\n npm: '@polymer/polymer',\n test: function(win) {\n if(win.Polymer && win.Polymer.dom) {\n return { version: win.Polymer.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Highcharts': {\n icon: 'highcharts',\n url: 'http://www.highcharts.com',\n npm: 'highcharts',\n test: function(win) {\n if(win.Highcharts && win.Highcharts.Point) {\n return { version: win.Highcharts.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'InfoVis': {\n icon: 'jit',\n url: 'http://philogb.github.com/jit/',\n test: function test(win) {\n if(win.$jit && win.$jit.PieChart) {\n return { version: win.$jit.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'FlotCharts': {\n icon: 'flotcharts',\n url: 'http://www.flotcharts.org/',\n npm: 'flot',\n test: function(win) {\n if(win.$ && win.$.plot) {\n return { version: win.$.plot.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'CreateJS': {\n icon: 'createjs',\n url: 'https://createjs.com/',\n npm: 'createjs',\n test: function(win) {\n if(win.createjs && win.createjs.promote) {\n return { version: UNKNOWN_VERSION}; // no version info available\n }\n return false;\n }\n },\n\n 'Google Maps': {\n icon: 'gmaps',\n url: 'https://developers.google.com/maps/',\n test: function(win) {\n if (win.google && win.google.maps) {\n return { version: win.google.maps.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'jQuery': {\n icon: 'jquery',\n url: 'http://jquery.com',\n npm: 'jquery',\n test: function(win) {\n var jq = win.jQuery || win.$;\n if (jq && jq.fn) {\n return { version: jq.fn.jquery.replace(/[^\\d+\\.+]/g, '') || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'jQuery UI': {\n icon: 'jquery_ui',\n url: 'http://jqueryui.com',\n npm: 'jquery-ui',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if(jq && jq.fn && jq.fn.jquery && jq.ui) {\n var plugins = 'accordion,datepicker,dialog,draggable,droppable,progressbar,resizable,selectable,slider,menu,grid,tabs'.split(','), concat = [];\n for (var i=0; i < plugins.length; i++) { if(jq.ui[plugins[i]]) concat.push(plugins[i].substr(0,1).toUpperCase() + plugins[i].substr(1)); }\n return { version: jq.ui.version || UNKNOWN_VERSION, details: concat.length ? 'Plugins used: '+concat.join(',') : '' };\n }\n return false;\n }\n },\n\n 'Dojo': {\n icon: 'dojo',\n url: 'http://dojotoolkit.org',\n npm: 'dojo',\n test: function(win) {\n if(win.dojo && win.dojo.delegate) {\n var version = win.dojo.version ? win.dojo.version.toString() : UNKNOWN_VERSION;\n return { version: version, details: 'Details: '+(win.dijit ? 'Uses Dijit' : 'none') };\n }\n return false;\n }\n },\n\n 'Prototype': {\n icon: 'prototype',\n url: 'http://prototypejs.org',\n test: function(win) {\n if(win.Prototype && win.Prototype.BrowserFeatures) {\n return { version: win.Prototype.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Scriptaculous': {\n icon: 'scriptaculous',\n url: 'http://script.aculo.us',\n test: function(win) {\n if(win.Scriptaculous && win.Scriptaculous.load) {\n return { version: win.Scriptaculous.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'MooTools': {\n icon: 'mootools',\n url: 'https://mootools.net/',\n test: function(win) {\n if(win.MooTools && win.MooTools.build) {\n return { version: win.MooTools.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Spry': {\n icon: 'spry',\n url: 'http://labs.adobe.com/technologies/spry',\n test: function(win) {\n if (win.Spry && win.Spry.Data) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'YUI 2': {\n icon: 'yui',\n url: 'http://developer.yahoo.com/yui/2/',\n test: function(win) {\n if (win.YAHOO && win.YAHOO.util) {\n return { version: win.YAHOO.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'YUI 3': {\n icon: 'yui3',\n url: 'https://yuilibrary.com/',\n npm: 'yui',\n test: function(win) {\n if (win.YUI && win.YUI.Env) {\n return { version: win.YUI.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Qooxdoo': {\n icon: 'qooxdoo',\n url: 'http://www.qooxdoo.org/',\n npm: 'qooxdoo',\n test: function(win) {\n if(win.qx && win.qx.Bootstrap) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Ext JS': {\n icon: 'extjs',\n url: 'https://www.sencha.com/products/extjs/',\n test: function(win) {\n if (win.Ext && win.Ext.versions) {\n return { version: win.Ext.versions.core.version };\n }\n else if(win.Ext) {\n return { version: win.Ext.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'base2': {\n icon: 'base2',\n url: 'http://code.google.com/p/base2',\n test: function(win) {\n if(win.base2 && win.base2.dom) {\n return { version: win.base2.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Closure Library': {\n icon: 'closure',\n url: 'https://developers.google.com/closure/library/',\n npm: 'google-closure-library',\n test: function(win) {\n if(win.goog && win.goog.provide) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Rapha&euml;l': {\n icon: 'raphael',\n url: 'http://dmitrybaranovskiy.github.io/raphael/',\n test: function(win) {\n if (win.Raphael && win.Raphael.circle) {\n return { version: win.Raphael.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'React': {\n icon: 'react',\n url: 'https://reactjs.org/',\n npm: 'react',\n test: function(win) {\n function isMatch(node) {\n return node!=null && node._reactRootContainer!=null;\n }\n function nodeFilter(node) {\n return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var reactRoot = document.getElementById('react-root');\n var altHasReact = document.querySelector('*[data-reactroot]');\n var bodyReactRoot = isMatch(document.body) || isMatch(document.body.firstElementChild);\n var hasReactRoot = bodyReactRoot|| document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode() != null;\n if (hasReactRoot || reactRoot && reactRoot.innerText.length > 0 || altHasReact || win.React && win.React.Component) {\n return { version: win.React && win.React.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Next.js': {\n icon: 'next',\n url: 'https://nextjs.org/',\n npm: 'next',\n test: function(win) {\n if (win.__NEXT_DATA__ && win.__NEXT_DATA__.buildId) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Preact': {\n icon: 'preact',\n url: 'https://preactjs.com/',\n npm: 'preact',\n test: function(win) {\n var expando = typeof Symbol!='undefined' && Symbol.for && Symbol.for('preactattr');\n function isMatch(node) {\n return node._component!=null || node.__preactattr_!=null || expando && node[expando]!=null;\n }\n function getMatch(node) {\n return node!=null && isMatch(node) && node;\n }\n function nodeFilter(node) {\n return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var preactRoot = getMatch(document.body) || getMatch(document.body.firstElementChild);\n if (!preactRoot) {\n preactRoot = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode();\n }\n if (preactRoot || win.preact) {\n var version = UNKNOWN_VERSION;\n if (expando && preactRoot && preactRoot[expando]!=null) {\n version = '7';\n }\n return { version: version };\n }\n return false;\n }\n },\n\n 'Modernizr': {\n icon: 'modernizr',\n url: 'https://modernizr.com/',\n npm: 'modernizr',\n test: function(win) {\n if (win.Modernizr && win.Modernizr.addTest) {\n return { version: win.Modernizr._version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Processing.js': {\n icon: 'processingjs',\n url: 'http://processingjs.org',\n npm: 'processing-js',\n test: function(win) {\n if(win.Processing && win.Processing.box) {\n return { version: Processing.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Backbone': {\n icon: 'backbone',\n url: 'http://backbonejs.org/',\n npm: 'backbone',\n test: function(win) {\n if (win.Backbone && win.Backbone.Model.extend) {\n return {version: win.Backbone.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Leaflet': {\n icon: 'leaflet',\n url: 'http://leafletjs.com',\n npm: 'leaflet',\n test: function(win) {\n // Leaflet 3.1 uses L.Marker and L.VERSION; later versions use L.marker and L.version\n if (win.L && win.L.GeoJSON && (win.L.marker || win.L.Marker)) {\n return { version: win.L.version || win.L.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Mapbox': {\n icon: 'mapbox',\n url: 'https://www.mapbox.com/',\n npm: 'mapbox-gl',\n test: function(win) {\n if (win.L && win.L.mapbox && win.L.mapbox.geocoder) {\n return { version: win.L.mapbox.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Lo-Dash': {\n icon: 'lodash',\n url: 'https://lodash.com/',\n npm: 'lodash',\n test: function(win) {\n var _ = typeof (_ = win._) == 'function' && _,\n chain = typeof (chain = _ && _.chain) == 'function' && chain,\n wrapper = (chain || _ || function() { return {}; })(1);\n\n if (_ && wrapper.__wrapped__) {\n return { version: _.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Underscore': {\n icon: 'underscore',\n url: 'http://underscorejs.org/',\n npm: 'underscore',\n test: function(win) {\n if (win._ && typeof win._.tap === 'function' &&\n !d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests['Lo-Dash'].test(win)) {\n return {version: win._.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Sammy': {\n icon: 'sammy',\n url: 'http://sammyjs.org',\n test: function(win) {\n if (win.Sammy && win.Sammy.Application.curry) {\n return {version: win.Sammy.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Rico': {\n icon: 'rico',\n url: 'http://openrico.sourceforge.net/examples/index.html',\n test: function(win) {\n if (win.Rico && window.Rico.checkIfComplete) {\n return {version: win.Rico.Version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'MochiKit': {\n icon: 'mochikit',\n url: 'https://mochi.github.io/mochikit/',\n test: function(win) {\n if (win.MochiKit && win.MochiKit.Base.module) {\n return {version: MochiKit.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'gRapha&euml;l': {\n icon: 'graphael',\n url: 'https://github.com/DmitryBaranovskiy/g.raphael',\n test: function(win) {\n if (win.Raphael && win.Raphael.fn.g) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Glow': {\n icon: 'glow',\n url: 'http://www.bbc.co.uk/glow/',\n test: function(win) {\n if (win.gloader && win.gloader.getRequests) {\n return {version: UNKNOWN_VERSION};\n }\n else if (win.glow && win.glow.dom) {\n return {version: win.glow.VERSION || UNKNOWN_VERSION};\n }\n else if (win.Glow) {\n return {version: win.Glow.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Socket.IO': {\n icon: 'socketio', // currently has no icon\n url: 'https://socket.io/',\n npm: 'socket.io',\n test: function(win) {\n // version 0.6.2 uses only io.Socket; more recent versions also have io.sockets\n if (win.io && (win.io.sockets || win.io.Socket)) {\n return {version: win.io.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Mustache': {\n icon: 'mustache',\n url: 'http://mustache.github.io/',\n npm: 'mustache',\n test: function(win) {\n if (win.Mustache && win.Mustache.to_html) {\n return {version: win.Mustache.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Fabric.js': {\n icon: 'icon38', // currently has no icon\n url: 'http://fabricjs.com/',\n npm: 'fabric',\n test: function(win) {\n if (win.fabric && win.fabric.util) {\n return {version: win.fabric.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'FuseJS': {\n icon: 'fusejs',\n url: 'http://fusejs.io/',\n npm: 'fuse.js',\n test: function(win) {\n if (win.Fuse) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Tween.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://github.com/tweenjs/tween.js',\n npm: 'tween.js',\n test: function(win) {\n if (win.TWEEN && win.TWEEN.Easing) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'SproutCore': {\n icon: 'sproutcore',\n url: 'http://sproutcore.com/',\n test: function(win) {\n if (win.SC && win.SC.Application) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Zepto.js': {\n icon: 'zepto',\n url: 'http://zeptojs.com',\n npm: 'zepto',\n test: function(win) {\n if (win.Zepto && win.Zepto.fn) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'three.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://threejs.org/',\n npm: 'three',\n test: function(win) {\n if (win.THREE && win.THREE.REVISION) {\n return {version: 'r' + win.THREE.REVISION};\n }\n else if (win.THREE) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'PhiloGL': {\n icon: 'philogl',\n url: 'http://www.senchalabs.org/philogl/',\n npm: 'philogl',\n test: function(win) {\n if (win.PhiloGL && win.PhiloGL.Camera) {\n return {version: win.PhiloGL.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'CamanJS': {\n icon: 'camanjs',\n url: 'http://camanjs.com/',\n npm: 'caman',\n test: function(win) {\n if (win.Caman && win.Caman.version) {\n return {version: win.Caman.version.release};\n }\n else if (win.Caman) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'yepnope': {\n icon: 'yepnope',\n url: 'http://yepnopejs.com/',\n test: function(win) {\n if (win.yepnope && win.yepnope.injectJs) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'LABjs': {\n icon: 'icon38',\n url: 'https://github.com/getify/LABjs',\n test: function(win) {\n if (win.$LAB && win.$LAB.setOptions) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Head JS': {\n icon: 'headjs',\n url: 'http://headjs.com/',\n npm: 'headjs',\n test: function(win) {\n if (win.head && win.head.js) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'ControlJS': {\n icon: 'icon38',\n url: 'http://stevesouders.com/controljs/',\n test: function(win) {\n if (win.CJS && win.CJS.start) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'RequireJS': {\n icon: 'requirejs',\n url: 'http://requirejs.org/',\n npm: 'requirejs',\n test: function(win) {\n var req = win.require || win.requirejs;\n if (req && (req.load || (req.s && req.s.contexts && req.s.contexts._ && (req.s.contexts._.loaded || req.s.contexts._.load)))) {\n return { version: req.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'RightJS': {\n icon: 'rightjs',\n url: 'http://rightjs.org/',\n test: function(win) {\n if (win.RightJS && win.RightJS.isNode) {\n return { version: win.RightJS.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'jQuery Tools': {\n icon: 'jquerytools',\n url: 'http://jquerytools.github.io/',\n test: function(win) {\n var jq = win.jQuery || win.$;\n if(jq && jq.tools) {\n return { version: jq.tools.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Pusher': {\n icon: 'pusher',\n url: 'https://pusher.com/docs/',\n npm: 'pusher-js',\n test: function(win) {\n if(win.Pusher && win.Pusher.Channel) {\n return { version: win.Pusher.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Paper.js': {\n icon: 'paperjs',\n url: 'http://paperjs.org/',\n npm: 'paper',\n test: function(win) {\n if(win.paper && win.paper.Point) {\n return { version: win.paper.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Swiffy': {\n icon: 'icon38',\n url: 'https://developers.google.com/swiffy/',\n test: function(win) {\n if(win.swiffy && win.swiffy.Stage) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Move': {\n icon: 'move',\n url: 'https://github.com/rsms/move',\n npm: 'move',\n test: function(win) {\n if(win.move && win.move.compile) {\n return { version: win.move.version() || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'AmplifyJS': {\n icon: 'amplifyjs',\n url: 'http://amplifyjs.com/',\n npm: 'amplifyjs',\n test: function(win) {\n if(win.amplify && win.amplify.publish) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Popcorn.js': {\n icon: 'popcornjs',\n url: 'https://github.com/mozilla/popcorn-js/',\n test: function(win) {\n if (win.Popcorn && win.Popcorn.Events) {\n return { version: win.Popcorn.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'D3': {\n icon: 'd3',\n url: 'https://d3js.org/',\n npm: 'd3',\n test: function(win) {\n if (win.d3 && win.d3.select) {\n return { version: win.d3.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Handlebars': {\n icon: 'handlebars',\n url: 'http://handlebarsjs.com/',\n npm: 'handlebars',\n test: function(win) {\n if(win.Handlebars && win.Handlebars.compile) {\n return { version: win.Handlebars.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Knockout': {\n icon: 'knockout',\n url: 'http://knockoutjs.com/',\n npm: 'knockout',\n test: function(win) {\n if (win.ko && win.ko.applyBindings) {\n return { version: win.ko.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Spine': {\n icon: 'icon38',\n url: 'http://spine.github.io/',\n test: function(win) {\n if (win.Spine && win.Spine.Controller) {\n return {version: win.Spine.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'jQuery Mobile': {\n icon: 'jquery_mobile',\n url: 'http://jquerymobile.com/',\n npm: 'jquery-mobile',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if(jq && jq.fn && jq.fn.jquery && jq.mobile) {\n return { version: jq.mobile.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'WebFont Loader': {\n icon: 'icon38',\n url: 'https://github.com/typekit/webfontloader',\n npm: 'webfontloader',\n test: function(win) {\n if(win.WebFont && win.WebFont.load) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Angular': {\n icon: 'angular',\n url: 'https://angular.io/',\n npm: '@angular/core',\n test: function(win) {\n var ngVersion = win.document.querySelector('[ng-version]');\n if (ngVersion) {\n return { version: ngVersion.getAttribute('ng-version') || UNKNOWN_VERSION };\n }\n else if (win.ng && win.ng.probe instanceof Function) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'AngularJS': {\n icon: 'angularjs',\n url: 'https://angularjs.org/',\n npm: 'angular',\n test: function(win) {\n var ng = win.angular;\n if(ng && ng.version && ng.version.full) {\n return { version: ng.version.full };\n }\n else if (ng) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Ember.js': {\n icon: 'emberjs',\n url: 'https://emberjs.com/',\n npm: 'ember-source',\n test: function(win) {\n var ember = win.Ember || win.Em;\n if (ember && ember.propertyDidChange) {\n return { version: ember.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Hammer.js': {\n icon: 'hammerjs',\n url: 'http://eightmedia.github.io/hammer.js/',\n npm: 'hammerjs',\n test: function(win) {\n if(win.Hammer && win.Hammer.Pinch) {\n // Hammer.VERSION available in 1.0.10+\n return { version: win.Hammer.VERSION || \"&lt; 1.0.10\" };\n }\n return false;\n }\n },\n\n 'Visibility.js': {\n icon: 'icon38',\n url: 'https://github.com/ai/visibilityjs',\n npm: 'visibilityjs',\n test: function(win) {\n if(win.Visibility && win.Visibility.every) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Velocity.js': {\n icon: 'icon38',\n url: 'http://velocityjs.org/',\n npm: 'velocity-animate',\n test: function(win) {\n var jq = win.jQuery || win.$,\n velocity = jq ? jq.Velocity : win.Velocity;\n\n if(velocity && velocity.RegisterEffect && velocity.version) {\n return {\n version:\n velocity.version.major + \".\" +\n velocity.version.minor + \".\" +\n velocity.version.patch\n };\n }\n else if (velocity && velocity.RegisterEffect) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'IfVisible.js': {\n icon: 'icon38',\n url: 'http://serkanyersen.github.io/ifvisible.js/',\n npm: 'ifvisible.js',\n test: function(win) {\n var iv = win.ifvisible;\n if(iv && iv.__ceGUID === \"ifvisible.object.event.identifier\") {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Pixi.js': {\n icon: 'pixi',\n url: 'http://www.pixijs.com/',\n npm: 'pixi.js',\n test: function(win) {\n var px = win.PIXI;\n if(px && px.WebGLRenderer && px.VERSION) {\n // version 4.4.3 returns simply \"4.4.3\"; version 1.5.2 returns \"v1.5.2\"\n return { version: px.VERSION.replace('v', '') || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'DC.js': {\n icon: 'dcjs',\n url: 'http://dc-js.github.io/dc.js/',\n npm: 'dc',\n test: function(win) {\n var dc = win.dc;\n if(dc && dc.registerChart) {\n return { version: dc.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'GreenSock JS': {\n icon: 'greensock',\n url: 'https://greensock.com/gsap',\n npm: 'gsap',\n test: function(win) {\n if (win.TweenMax && win.TweenMax.pauseAll) {\n return { version: win.TweenMax.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'FastClick': {\n icon: 'fastclick',\n url: 'https://github.com/ftlabs/fastclick',\n npm: 'fastclick',\n test: function(win) {\n if(win.FastClick && win.FastClick.notNeeded) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Isotope': {\n icon: 'isotope',\n url: 'https://isotope.metafizzy.co/',\n npm: 'isotope-layout',\n test: function(win) {\n if(win.Isotope || (win.$ != null && win.$.Isotope)) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Marionette': {\n icon: 'marionette',\n url: 'https://marionettejs.com/',\n npm: 'backbone.marionette',\n test: function(win) {\n if(win.Marionette && win.Marionette.Application) {\n return { version: win.Marionette.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Can': {\n icon: 'canjs',\n url: 'https://canjs.com/',\n npm: 'can',\n test: function (win) {\n if (win.can && win.can.Construct) {\n return { version: win.can.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Vue': {\n icon: 'vue',\n url: 'https://vuejs.org/',\n npm: 'vue',\n test: function(win) {\n function isVueNode(node) {\n return node.__vue__ != null ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var hasVueNode = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, isVueNode).nextNode() !== null;\n if (hasVueNode) {\n return { version: win.Vue && win.Vue.version || UNKNOWN_VERSION }\n }\n return false;\n }\n },\n 'Nuxt.js': {\n icon: 'nuxt',\n url: 'https://nuxtjs.org/',\n npm: 'nuxt',\n test: function(win) {\n if ((win.__NUXT__ && win.__NUXT__.data != null) || win.$nuxt) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Two': {\n icon: 'two',\n url: 'https://two.js.org/',\n npm: 'two.js',\n test: function(win) {\n if (win.Two && win.Two.Utils) {\n return { version: win.Two.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Brewser': {\n icon: 'brewser',\n url: 'https://robertpataki.github.io/brewser/',\n npm: 'brewser',\n test: function(win) {\n if(win.BREWSER && win.BREWSER.ua) {\n return { version: BREWSER.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Material Design Lite': {\n icon: 'mdl',\n url: 'https://getmdl.io/',\n npm: 'material-design-lite',\n test: function(win) {\n if(win.componentHandler && win.componentHandler.upgradeElement) {\n return { version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Kendo UI': {\n icon: 'kendoui',\n url: 'https://github.com/telerik/kendo-ui-core',\n npm: 'kendo-ui-core',\n test: function(win) {\n if (win.kendo && win.kendo.View && win.kendo.View.extend) {\n return {version: win.kendo.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Matter.js': {\n icon: 'matter-js',\n url: 'http://brm.io/matter-js/',\n npm: 'matter-js',\n test: function(win) {\n if (win.Matter && win.Matter.Engine) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Riot': {\n icon: 'riot',\n url: 'http://riotjs.com/',\n npm: 'riot',\n test: function(win) {\n if (win.riot && win.riot.mixin) {\n return { version: win.riot.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Sea.js': {\n icon: 'icon38',\n url: 'https://seajs.github.io/seajs/docs/',\n npm: 'seajs',\n test: function(win) {\n if(win.seajs && win.seajs.use) {\n return { version: win.seajs.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Moment.js': {\n icon: 'momentjs',\n url: 'http://momentjs.com/',\n npm: 'moment',\n test: function(win) {\n if(win.moment && (win.moment.isMoment || win.moment.lang)) {\n // version 1.0.0 has neither \"isMoment\" nor \"version\"\n return { version: win.moment.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Moment Timezone': {\n icon: 'momentjs',\n url: 'http://momentjs.com/timezone/',\n npm: 'moment-timezone',\n test: function(win) {\n if (win.moment && win.moment.tz) {\n return { version: win.moment.tz.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'ScrollMagic': {\n icon: 'scrollmagic',\n url: 'http://scrollmagic.io/',\n npm: 'scrollmagic',\n test: function(win) {\n if (win.ScrollMagic && win.ScrollMagic.Controller) {\n return {version: ScrollMagic.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'SWFObject': {\n icon: 'icon38', // currently has no icon\n url: 'https://github.com/swfobject/swfobject',\n test: function(win) {\n if (win.swfobject && win.swfobject.embedSWF) {\n // 2.x - exact version only for 2.3\n return { version: win.swfobject.version || UNKNOWN_VERSION };\n } else if(win.deconcept && win.deconcept.SWFObject) {\n // 1.x\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'FlexSlider': {\n icon: 'icon38', // currently has no icon\n url: 'https://woocommerce.com/flexslider/',\n npm: 'flexslider',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if (jq && jq.fn && jq.fn.jquery && jq.flexslider){\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'SPF': {\n icon: 'icon38', // currently has no icon\n url: 'https://youtube.github.io/spfjs/',\n npm: 'spf',\n test: function(win) {\n if (win.spf && win.spf.init) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Numeral.js': {\n icon: 'icon38', // currently has no icon\n url: 'http://numeraljs.com/',\n npm: 'numeraljs',\n test: function(win) {\n if (win.numeral && win.isNumeral) {\n return { version: win.numeral.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'boomerang.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://soasta.github.io/boomerang/',\n npm: 'boomerangjs',\n test: function(win) {\n if (win.BOOMR && win.BOOMR.utils && win.BOOMR.init) {\n return { version: win.BOOMR.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Framer': {\n icon: 'framer',\n url: 'https://framer.com/',\n npm: 'framerjs',\n test: function(win) {\n if (win.Framer && win.Framer.Layer) {\n return { version: win.Framer.Version.build || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Marko': {\n icon: 'marko',\n url: 'https://markojs.com/',\n npm: 'marko',\n test: function (win) {\n var selector = '[data-marko-key], [data-marko]';\n var markoElement = document.querySelector(selector);\n if (markoElement) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'AMP': {\n icon: 'amp',\n url: 'https://ampproject.org/',\n npm: null,\n test: function (win) {\n var version = win.document.documentElement.getAttribute(\"amp-version\");\n return version ? { version: version } : false;\n }\n },\n 'Gatsby': {\n icon: 'gatsby',\n url: 'https://www.gatsbyjs.org/',\n npm: 'gatsby',\n test: function (win) {\n if (document.getElementById('___gatsby')) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Shopify': {\n icon: 'shopify',\n url: 'https://www.shopify.com/',\n npm: null,\n test: function (win) {\n if (win.Shopify && win.Shopify.shop) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'WordPress': {\n icon: 'wordpress',\n url: 'https://wordpress.org/',\n npm: null,\n test: function (win) {\n const hasAPILinkElem = !!document.querySelector('link[rel=\"https://api.w.org/\"]');\n const hasWPIncludes = !!document.querySelectorAll('link[href*=\"wp-includes\"], script[src*=\"wp-includes\"]').length;\n \n if (!hasAPILinkElem && !hasWPIncludes) return false;\n \n const generatorMeta = document.querySelector('meta[name=generator][content^=\"WordPress\"]')\n const version = generatorMeta ? generatorMeta.getAttribute(\"content\").replace(/^\\w+\\s/,'') : UNKNOWN_VERSION;\n return { version };\n }\n },\n 'Wix': {\n icon: 'wix',\n url: 'https://www.wix.com/',\n npm: null,\n test: function (win) {\n if (win.wixBiSession) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Workbox': {\n icon: 'workbox',\n url: 'https://developers.google.com/web/tools/workbox/',\n npm: 'workbox-sw',\n test: async function (win) {\n var nav = win.navigator;\n // Service Workers not supported\n if (!('serviceWorker' in nav)) {\n return false;\n }\n return nav.serviceWorker.getRegistration()\n .then(function(registration) {\n var scriptURL = nav.serviceWorker.controller.scriptURL;\n return fetch(scriptURL, { credentials: 'include',\n headers: { 'service-worker': 'script' }\n })\n .then(function(response) {\n return response.text();\n })\n .then(function(scriptContent) {\n var workboxRegExp = /new Workbox|new workbox|workbox\\.precaching\\.|workbox\\.strategies/gm;\n if (workboxRegExp.test(scriptContent)) {\n // Adapted from\n // https://github.com/semver/semver/issues/232#issue-48635632\n var semVerRegExp = /workbox.*?\\b((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?)\\b/gim;\n var matches = semVerRegExp.exec(scriptContent);\n var version = UNKNOWN_VERSION;\n if (Array.isArray(matches) && matches.length > 1 && matches[1]) {\n version = matches[1];\n }\n return { version: version };\n }\n return false;\n });\n }).catch(function(exception) {\n return false;\n });\n }\n }\n};\n";
+const libDetectorSource="var UNKNOWN_VERSION = null;\nvar d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests = {\n\n 'GWT': {\n icon: 'gwt',\n url: 'http://www.gwtproject.org/',\n test: function(win) {\n // pretty complicated, many possible tell tales\n var doc = win.document,\n hasHistFrame = doc.getElementById('__gwt_historyFrame'),\n hasGwtUid = doc.gwt_uid,\n hasBodyListener = doc.body.__listener,\n hasBodyEventBits = doc.body.__eventBits,\n hasModules = win.__gwt_activeModules,\n hasJsonP = win.__gwt_jsonp__,\n hasRootWinApp = win.__gwt_scriptsLoaded || win.__gwt_stylesLoaded || win.__gwt_activeModules;\n\n // use the many possible indicators\n if(hasHistFrame || hasGwtUid || hasBodyListener || hasBodyEventBits || hasModules || hasJsonP || hasRootWinApp) {\n\n // carefully look at frames, but only if certain is GWT frame\n var frames = doc.getElementsByTagName('iframe'),\n gwtVersion = UNKNOWN_VERSION;\n for(var n=0; n<frames.length; n++) {\n // catch security access errors\n try {\n var hasNegativeTabIndex = frames[n].tabIndex < 0; // on for GWT\n if(hasNegativeTabIndex && frames[n].contentWindow && frames[n].contentWindow.$gwt_version) {\n gwtVersion = frames[n].contentWindow.$gwt_version;\n break;\n }\n }\n catch(e) {}\n }\n\n if(gwtVersion=='0.0.999') {\n gwtVersion = 'Google Internal';\n }\n\n return { version: gwtVersion };\n }\n return false;\n }\n },\n\n 'Ink': {\n icon: 'ink',\n url: 'http://ink.sapo.pt/',\n test: function(win) {\n if (win.Ink && win.Ink.createModule) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Vaadin': {\n icon: 'vaadin',\n url: 'https://vaadin.com/',\n test: function(win) {\n if (win.vaadin && win.vaadin.registerWidgetset) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Bootstrap': {\n icon: 'bootstrap',\n url: 'http://getbootstrap.com/',\n npm: 'bootstrap',\n // look for a function Boostrap has added to jQuery - regex for BS 2 & 3\n test: function(win) {\n var jQueryAvailable = win.$ && win.$.fn,\n RE_PREFIX_V2 = '\\\\$this\\\\.data\\\\((?:\\'|\")',\n RE_PREFIX_V3 = '\\\\$this\\\\.data\\\\((?:\\'|\")(?:bs\\\\.){1}',\n bootstrapComponents = [\n 'affix', 'alert', 'button', 'carousel', 'collapse', 'dropdown',\n 'modal', 'popover', 'scrollspy', 'tab', 'tooltip'\n ];\n\n if(jQueryAvailable) {\n var bootstrapVersion;\n\n bootstrapComponents.some(function(component) {\n if(win.$.fn[component]) {\n // Bootstrap >= 3.2.0 detection\n if(win.$.fn[component].Constructor && win.$.fn[component].Constructor.VERSION) {\n bootstrapVersion = win.$.fn[component].Constructor.VERSION;\n return true;\n // Bootstrap >= 2.0.0 and <= 3.1.0 detection\n } else if(new RegExp(RE_PREFIX_V3 + component).test(win.$.fn[component].toString())) {\n bootstrapVersion = '>= 3.0.0 & <= 3.1.1';\n return true;\n // Bootstrap < 3.1.0 detection\n } else if(new RegExp(RE_PREFIX_V2 + component).test(win.$.fn[component].toString())) {\n bootstrapVersion = '>= 2.0.0 & <= 2.3.2';\n return true;\n }\n }\n\n return false;\n });\n\n if (bootstrapVersion) {\n return { version: bootstrapVersion };\n }\n }\n\n return false;\n }\n },\n\n 'Zurb': {\n icon: 'zurb',\n url: 'https://foundation.zurb.com/',\n npm: 'foundation-sites',\n test: function(win) {\n if(win.Foundation && win.Foundation.Toggler) {\n return { version: win.Foundation.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Polymer': {\n icon: 'polymer',\n url: 'https://www.polymer-project.org/',\n npm: '@polymer/polymer',\n test: function(win) {\n if(win.Polymer && win.Polymer.dom) {\n return { version: win.Polymer.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Highcharts': {\n icon: 'highcharts',\n url: 'http://www.highcharts.com',\n npm: 'highcharts',\n test: function(win) {\n if(win.Highcharts && win.Highcharts.Point) {\n return { version: win.Highcharts.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'InfoVis': {\n icon: 'jit',\n url: 'http://philogb.github.com/jit/',\n test: function test(win) {\n if(win.$jit && win.$jit.PieChart) {\n return { version: win.$jit.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'FlotCharts': {\n icon: 'flotcharts',\n url: 'http://www.flotcharts.org/',\n npm: 'flot',\n test: function(win) {\n if(win.$ && win.$.plot) {\n return { version: win.$.plot.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'CreateJS': {\n icon: 'createjs',\n url: 'https://createjs.com/',\n npm: 'createjs',\n test: function(win) {\n if(win.createjs && win.createjs.promote) {\n return { version: UNKNOWN_VERSION}; // no version info available\n }\n return false;\n }\n },\n\n 'Google Maps': {\n icon: 'gmaps',\n url: 'https://developers.google.com/maps/',\n test: function(win) {\n if (win.google && win.google.maps) {\n return { version: win.google.maps.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'jQuery': {\n icon: 'jquery',\n url: 'http://jquery.com',\n npm: 'jquery',\n test: function(win) {\n var jq = win.jQuery || win.$;\n if (jq && jq.fn && jq.fn.jquery) {\n return { version: jq.fn.jquery.replace(/[^\\d+\\.+]/g, '') || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'jQuery (Fast path)': {\n icon: 'jquery',\n url: 'http://jquery.com',\n npm: 'jquery',\n test: function (win) {\n var jq = win.jQuery || win.$;\n if (jq && jq.fn) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'jQuery UI': {\n icon: 'jquery_ui',\n url: 'http://jqueryui.com',\n npm: 'jquery-ui',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if(jq && jq.fn && jq.fn.jquery && jq.ui) {\n var plugins = 'accordion,datepicker,dialog,draggable,droppable,progressbar,resizable,selectable,slider,menu,grid,tabs'.split(','), concat = [];\n for (var i=0; i < plugins.length; i++) { if(jq.ui[plugins[i]]) concat.push(plugins[i].substr(0,1).toUpperCase() + plugins[i].substr(1)); }\n return { version: jq.ui.version || UNKNOWN_VERSION, details: concat.length ? 'Plugins used: '+concat.join(',') : '' };\n }\n return false;\n }\n },\n\n 'Dojo': {\n icon: 'dojo',\n url: 'http://dojotoolkit.org',\n npm: 'dojo',\n test: function(win) {\n if(win.dojo && win.dojo.delegate) {\n var version = win.dojo.version ? win.dojo.version.toString() : UNKNOWN_VERSION;\n return { version: version, details: 'Details: '+(win.dijit ? 'Uses Dijit' : 'none') };\n }\n return false;\n }\n },\n\n 'Prototype': {\n icon: 'prototype',\n url: 'http://prototypejs.org',\n test: function(win) {\n if(win.Prototype && win.Prototype.BrowserFeatures) {\n return { version: win.Prototype.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Scriptaculous': {\n icon: 'scriptaculous',\n url: 'http://script.aculo.us',\n test: function(win) {\n if(win.Scriptaculous && win.Scriptaculous.load) {\n return { version: win.Scriptaculous.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'MooTools': {\n icon: 'mootools',\n url: 'https://mootools.net/',\n test: function(win) {\n if(win.MooTools && win.MooTools.build) {\n return { version: win.MooTools.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Spry': {\n icon: 'spry',\n url: 'http://labs.adobe.com/technologies/spry',\n test: function(win) {\n if (win.Spry && win.Spry.Data) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'YUI 2': {\n icon: 'yui',\n url: 'http://developer.yahoo.com/yui/2/',\n test: function(win) {\n if (win.YAHOO && win.YAHOO.util) {\n return { version: win.YAHOO.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'YUI 3': {\n icon: 'yui3',\n url: 'https://yuilibrary.com/',\n npm: 'yui',\n test: function(win) {\n if (win.YUI && win.YUI.Env) {\n return { version: win.YUI.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Qooxdoo': {\n icon: 'qooxdoo',\n url: 'http://www.qooxdoo.org/',\n npm: 'qooxdoo',\n test: function(win) {\n if(win.qx && win.qx.Bootstrap) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Ext JS': {\n icon: 'extjs',\n url: 'https://www.sencha.com/products/extjs/',\n test: function(win) {\n if (win.Ext && win.Ext.versions) {\n return { version: win.Ext.versions.core.version };\n }\n else if(win.Ext) {\n return { version: win.Ext.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'base2': {\n icon: 'base2',\n url: 'http://code.google.com/p/base2',\n test: function(win) {\n if(win.base2 && win.base2.dom) {\n return { version: win.base2.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Closure Library': {\n icon: 'closure',\n url: 'https://developers.google.com/closure/library/',\n npm: 'google-closure-library',\n test: function(win) {\n if(win.goog && win.goog.provide) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Rapha&euml;l': {\n icon: 'raphael',\n url: 'http://dmitrybaranovskiy.github.io/raphael/',\n test: function(win) {\n if (win.Raphael && win.Raphael.circle) {\n return { version: win.Raphael.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'React': {\n icon: 'react',\n url: 'https://reactjs.org/',\n npm: 'react',\n test: function(win) {\n function isMatch(node) {\n return node!=null && node._reactRootContainer!=null;\n }\n function nodeFilter(node) {\n return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var reactRoot = document.getElementById('react-root');\n var altHasReact = document.querySelector('*[data-reactroot]');\n var bodyReactRoot = isMatch(document.body) || isMatch(document.body.firstElementChild);\n var hasReactRoot = bodyReactRoot|| document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode() != null;\n if (hasReactRoot || reactRoot && reactRoot.innerText.length > 0 || altHasReact || win.React && win.React.Component) {\n return { version: win.React && win.React.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'React (Fast path)': {\n icon: 'react',\n url: 'https://reactjs.org/',\n npm: 'react',\n test: function (win) {\n function isMatch(node) {\n return node != null && node._reactRootContainer != null;\n }\n var reactRoot = document.getElementById('react-root');\n var altHasReact = document.querySelector('*[data-reactroot]');\n var hasReactRoot = isMatch(document.body) || isMatch(document.body.firstElementChild);\n if (hasReactRoot || reactRoot || altHasReact || win.React) {\n return { version: win.React && win.React.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Next.js': {\n icon: 'next',\n url: 'https://nextjs.org/',\n npm: 'next',\n test: function(win) {\n if (win.__NEXT_DATA__ && win.__NEXT_DATA__.buildId) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Next.js (Fast path)': {\n icon: 'next',\n url: 'https://nextjs.org/',\n npm: 'next',\n test: function (win) {\n if (win.__NEXT_DATA__) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Preact': {\n icon: 'preact',\n url: 'https://preactjs.com/',\n npm: 'preact',\n test: function(win) {\n var expando = typeof Symbol!='undefined' && Symbol.for && Symbol.for('preactattr');\n function isMatch(node) {\n return node._component!=null || node.__preactattr_!=null || expando && node[expando]!=null;\n }\n function getMatch(node) {\n return node!=null && isMatch(node) && node;\n }\n function nodeFilter(node) {\n return isMatch(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var preactRoot = getMatch(document.body) || getMatch(document.body.firstElementChild);\n if (!preactRoot) {\n preactRoot = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, nodeFilter).nextNode();\n }\n if (preactRoot || win.preact) {\n var version = UNKNOWN_VERSION;\n if (expando && preactRoot && preactRoot[expando]!=null) {\n version = '7';\n }\n return { version: version };\n }\n return false;\n }\n },\n\n 'Preact (Fast path)': {\n icon: 'preact',\n url: 'https://preactjs.com/',\n npm: 'preact',\n test: function (win) {\n function isMatch(node) {\n return node._component != null || node.__preactattr_ != null;\n }\n function getMatch(node) {\n return node != null && isMatch(node);\n }\n var preactRoot = getMatch(document.body) || getMatch(document.body.firstElementChild);\n if (preactRoot || win.preact) {\n var version = UNKNOWN_VERSION;\n return { version: version };\n }\n return false;\n }\n },\n\n 'Modernizr': {\n icon: 'modernizr',\n url: 'https://modernizr.com/',\n npm: 'modernizr',\n test: function(win) {\n if (win.Modernizr && win.Modernizr.addTest) {\n return { version: win.Modernizr._version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Processing.js': {\n icon: 'processingjs',\n url: 'http://processingjs.org',\n npm: 'processing-js',\n test: function(win) {\n if(win.Processing && win.Processing.box) {\n return { version: Processing.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Backbone': {\n icon: 'backbone',\n url: 'http://backbonejs.org/',\n npm: 'backbone',\n test: function(win) {\n if (win.Backbone && win.Backbone.Model.extend) {\n return {version: win.Backbone.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Leaflet': {\n icon: 'leaflet',\n url: 'http://leafletjs.com',\n npm: 'leaflet',\n test: function(win) {\n // Leaflet 3.1 uses L.Marker and L.VERSION; later versions use L.marker and L.version\n if (win.L && win.L.GeoJSON && (win.L.marker || win.L.Marker)) {\n return { version: win.L.version || win.L.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Mapbox': {\n icon: 'mapbox',\n url: 'https://www.mapbox.com/',\n npm: 'mapbox-gl',\n test: function(win) {\n if (win.L && win.L.mapbox && win.L.mapbox.geocoder) {\n return { version: win.L.mapbox.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Lo-Dash': {\n icon: 'lodash',\n url: 'https://lodash.com/',\n npm: 'lodash',\n test: function(win) {\n var _ = typeof (_ = win._) == 'function' && _,\n chain = typeof (chain = _ && _.chain) == 'function' && chain,\n wrapper = (chain || _ || function() { return {}; })(1);\n\n if (_ && wrapper.__wrapped__) {\n return { version: _.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Underscore': {\n icon: 'underscore',\n url: 'http://underscorejs.org/',\n npm: 'underscore',\n test: function(win) {\n if (win._ && typeof win._.tap === 'function' &&\n !d41d8cd98f00b204e9800998ecf8427e_LibraryDetectorTests['Lo-Dash'].test(win)) {\n return {version: win._.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Sammy': {\n icon: 'sammy',\n url: 'http://sammyjs.org',\n test: function(win) {\n if (win.Sammy && win.Sammy.Application.curry) {\n return {version: win.Sammy.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Rico': {\n icon: 'rico',\n url: 'http://openrico.sourceforge.net/examples/index.html',\n test: function(win) {\n if (win.Rico && window.Rico.checkIfComplete) {\n return {version: win.Rico.Version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'MochiKit': {\n icon: 'mochikit',\n url: 'https://mochi.github.io/mochikit/',\n test: function(win) {\n if (win.MochiKit && win.MochiKit.Base.module) {\n return {version: MochiKit.VERSION || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'gRapha&euml;l': {\n icon: 'graphael',\n url: 'https://github.com/DmitryBaranovskiy/g.raphael',\n test: function(win) {\n if (win.Raphael && win.Raphael.fn.g) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Glow': {\n icon: 'glow',\n url: 'http://www.bbc.co.uk/glow/',\n test: function(win) {\n if (win.gloader && win.gloader.getRequests) {\n return {version: UNKNOWN_VERSION};\n }\n else if (win.glow && win.glow.dom) {\n return {version: win.glow.VERSION || UNKNOWN_VERSION};\n }\n else if (win.Glow) {\n return {version: win.Glow.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Socket.IO': {\n icon: 'socketio', // currently has no icon\n url: 'https://socket.io/',\n npm: 'socket.io',\n test: function(win) {\n // version 0.6.2 uses only io.Socket; more recent versions also have io.sockets\n if (win.io && (win.io.sockets || win.io.Socket)) {\n return {version: win.io.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Mustache': {\n icon: 'mustache',\n url: 'http://mustache.github.io/',\n npm: 'mustache',\n test: function(win) {\n if (win.Mustache && win.Mustache.to_html) {\n return {version: win.Mustache.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Fabric.js': {\n icon: 'icon38', // currently has no icon\n url: 'http://fabricjs.com/',\n npm: 'fabric',\n test: function(win) {\n if (win.fabric && win.fabric.util) {\n return {version: win.fabric.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'FuseJS': {\n icon: 'fusejs',\n url: 'http://fusejs.io/',\n npm: 'fuse.js',\n test: function(win) {\n if (win.Fuse) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Tween.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://github.com/tweenjs/tween.js',\n npm: 'tween.js',\n test: function(win) {\n if (win.TWEEN && win.TWEEN.Easing) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'SproutCore': {\n icon: 'sproutcore',\n url: 'http://sproutcore.com/',\n test: function(win) {\n if (win.SC && win.SC.Application) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Zepto.js': {\n icon: 'zepto',\n url: 'http://zeptojs.com',\n npm: 'zepto',\n test: function(win) {\n if (win.Zepto && win.Zepto.fn) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'three.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://threejs.org/',\n npm: 'three',\n test: function(win) {\n if (win.THREE && win.THREE.REVISION) {\n return {version: 'r' + win.THREE.REVISION};\n }\n else if (win.THREE) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'PhiloGL': {\n icon: 'philogl',\n url: 'http://www.senchalabs.org/philogl/',\n npm: 'philogl',\n test: function(win) {\n if (win.PhiloGL && win.PhiloGL.Camera) {\n return {version: win.PhiloGL.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'CamanJS': {\n icon: 'camanjs',\n url: 'http://camanjs.com/',\n npm: 'caman',\n test: function(win) {\n if (win.Caman && win.Caman.version) {\n return {version: win.Caman.version.release};\n }\n else if (win.Caman) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'yepnope': {\n icon: 'yepnope',\n url: 'http://yepnopejs.com/',\n test: function(win) {\n if (win.yepnope && win.yepnope.injectJs) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'LABjs': {\n icon: 'icon38',\n url: 'https://github.com/getify/LABjs',\n test: function(win) {\n if (win.$LAB && win.$LAB.setOptions) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'Head JS': {\n icon: 'headjs',\n url: 'http://headjs.com/',\n npm: 'headjs',\n test: function(win) {\n if (win.head && win.head.js) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'ControlJS': {\n icon: 'icon38',\n url: 'http://stevesouders.com/controljs/',\n test: function(win) {\n if (win.CJS && win.CJS.start) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'RequireJS': {\n icon: 'requirejs',\n url: 'http://requirejs.org/',\n npm: 'requirejs',\n test: function(win) {\n var req = win.require || win.requirejs;\n if (req && (req.load || (req.s && req.s.contexts && req.s.contexts._ && (req.s.contexts._.loaded || req.s.contexts._.load)))) {\n return { version: req.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'RightJS': {\n icon: 'rightjs',\n url: 'http://rightjs.org/',\n test: function(win) {\n if (win.RightJS && win.RightJS.isNode) {\n return { version: win.RightJS.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'jQuery Tools': {\n icon: 'jquerytools',\n url: 'http://jquerytools.github.io/',\n test: function(win) {\n var jq = win.jQuery || win.$;\n if(jq && jq.tools) {\n return { version: jq.tools.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Pusher': {\n icon: 'pusher',\n url: 'https://pusher.com/docs/',\n npm: 'pusher-js',\n test: function(win) {\n if(win.Pusher && win.Pusher.Channel) {\n return { version: win.Pusher.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Paper.js': {\n icon: 'paperjs',\n url: 'http://paperjs.org/',\n npm: 'paper',\n test: function(win) {\n if(win.paper && win.paper.Point) {\n return { version: win.paper.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Swiffy': {\n icon: 'icon38',\n url: 'https://developers.google.com/swiffy/',\n test: function(win) {\n if(win.swiffy && win.swiffy.Stage) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Move': {\n icon: 'move',\n url: 'https://github.com/rsms/move',\n npm: 'move',\n test: function(win) {\n if(win.move && win.move.compile) {\n return { version: win.move.version() || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'AmplifyJS': {\n icon: 'amplifyjs',\n url: 'http://amplifyjs.com/',\n npm: 'amplifyjs',\n test: function(win) {\n if(win.amplify && win.amplify.publish) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Popcorn.js': {\n icon: 'popcornjs',\n url: 'https://github.com/mozilla/popcorn-js/',\n test: function(win) {\n if (win.Popcorn && win.Popcorn.Events) {\n return { version: win.Popcorn.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'D3': {\n icon: 'd3',\n url: 'https://d3js.org/',\n npm: 'd3',\n test: function(win) {\n if (win.d3 && win.d3.select) {\n return { version: win.d3.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Handlebars': {\n icon: 'handlebars',\n url: 'http://handlebarsjs.com/',\n npm: 'handlebars',\n test: function(win) {\n if(win.Handlebars && win.Handlebars.compile) {\n return { version: win.Handlebars.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Knockout': {\n icon: 'knockout',\n url: 'http://knockoutjs.com/',\n npm: 'knockout',\n test: function(win) {\n if (win.ko && win.ko.applyBindings) {\n return { version: win.ko.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Spine': {\n icon: 'icon38',\n url: 'http://spine.github.io/',\n test: function(win) {\n if (win.Spine && win.Spine.Controller) {\n return {version: win.Spine.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n\n 'jQuery Mobile': {\n icon: 'jquery_mobile',\n url: 'http://jquerymobile.com/',\n npm: 'jquery-mobile',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if(jq && jq.fn && jq.fn.jquery && jq.mobile) {\n return { version: jq.mobile.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'WebFont Loader': {\n icon: 'icon38',\n url: 'https://github.com/typekit/webfontloader',\n npm: 'webfontloader',\n test: function(win) {\n if(win.WebFont && win.WebFont.load) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Angular': {\n icon: 'angular',\n url: 'https://angular.io/',\n npm: '@angular/core',\n test: function(win) {\n var ngVersion = win.document.querySelector('[ng-version]');\n if (ngVersion) {\n return { version: ngVersion.getAttribute('ng-version') || UNKNOWN_VERSION };\n }\n else if (win.ng && win.ng.probe instanceof Function) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'AngularJS': {\n icon: 'angularjs',\n url: 'https://angularjs.org/',\n npm: 'angular',\n test: function(win) {\n var ng = win.angular;\n if(ng && ng.version && ng.version.full) {\n return { version: ng.version.full };\n }\n else if (ng) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Ember.js': {\n icon: 'emberjs',\n url: 'https://emberjs.com/',\n npm: 'ember-source',\n test: function(win) {\n var ember = win.Ember || win.Em;\n if (ember && ember.GUID_KEY) {\n return { version: ember.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Ember.js (Fast path)': {\n icon: 'emberjs',\n url: 'https://emberjs.com/',\n npm: 'ember-source',\n test: function (win) {\n var ember = win.Ember || win.Em;\n if (ember) {\n return { version: ember.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Hammer.js': {\n icon: 'hammerjs',\n url: 'http://eightmedia.github.io/hammer.js/',\n npm: 'hammerjs',\n test: function(win) {\n if(win.Hammer && win.Hammer.Pinch) {\n // Hammer.VERSION available in 1.0.10+\n return { version: win.Hammer.VERSION || \"&lt; 1.0.10\" };\n }\n return false;\n }\n },\n\n 'Visibility.js': {\n icon: 'icon38',\n url: 'https://github.com/ai/visibilityjs',\n npm: 'visibilityjs',\n test: function(win) {\n if(win.Visibility && win.Visibility.every) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'Velocity.js': {\n icon: 'icon38',\n url: 'http://velocityjs.org/',\n npm: 'velocity-animate',\n test: function(win) {\n var jq = win.jQuery || win.$,\n velocity = jq ? jq.Velocity : win.Velocity;\n\n if(velocity && velocity.RegisterEffect && velocity.version) {\n return {\n version:\n velocity.version.major + \".\" +\n velocity.version.minor + \".\" +\n velocity.version.patch\n };\n }\n else if (velocity && velocity.RegisterEffect) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n\n 'IfVisible.js': {\n icon: 'icon38',\n url: 'http://serkanyersen.github.io/ifvisible.js/',\n npm: 'ifvisible.js',\n test: function(win) {\n var iv = win.ifvisible;\n if(iv && iv.__ceGUID === \"ifvisible.object.event.identifier\") {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Pixi.js': {\n icon: 'pixi',\n url: 'http://www.pixijs.com/',\n npm: 'pixi.js',\n test: function(win) {\n var px = win.PIXI;\n if(px && px.WebGLRenderer && px.VERSION) {\n // version 4.4.3 returns simply \"4.4.3\"; version 1.5.2 returns \"v1.5.2\"\n return { version: px.VERSION.replace('v', '') || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'DC.js': {\n icon: 'dcjs',\n url: 'http://dc-js.github.io/dc.js/',\n npm: 'dc',\n test: function(win) {\n var dc = win.dc;\n if(dc && dc.registerChart) {\n return { version: dc.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'GreenSock JS': {\n icon: 'greensock',\n url: 'https://greensock.com/gsap',\n npm: 'gsap',\n test: function(win) {\n if (win.TweenMax && win.TweenMax.pauseAll) {\n return { version: win.TweenMax.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'FastClick': {\n icon: 'fastclick',\n url: 'https://github.com/ftlabs/fastclick',\n npm: 'fastclick',\n test: function(win) {\n if(win.FastClick && win.FastClick.notNeeded) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Isotope': {\n icon: 'isotope',\n url: 'https://isotope.metafizzy.co/',\n npm: 'isotope-layout',\n test: function(win) {\n if(win.Isotope || (win.$ != null && win.$.Isotope)) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Marionette': {\n icon: 'marionette',\n url: 'https://marionettejs.com/',\n npm: 'backbone.marionette',\n test: function(win) {\n if(win.Marionette && win.Marionette.Application) {\n return { version: win.Marionette.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Can': {\n icon: 'canjs',\n url: 'https://canjs.com/',\n npm: 'can',\n test: function (win) {\n if (win.can && win.can.Construct) {\n return { version: win.can.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Vue': {\n icon: 'vue',\n url: 'https://vuejs.org/',\n npm: 'vue',\n test: function(win) {\n function isVueNode(node) {\n return node.__vue__ != null ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n }\n var hasVueNode = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, isVueNode).nextNode() !== null;\n if (hasVueNode) {\n return { version: win.Vue && win.Vue.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Vue (Fast path)': {\n icon: 'vue',\n url: 'https://vuejs.org/',\n npm: 'vue',\n test: function (win) {\n if (win.Vue) {\n return { version: win.Vue && win.Vue.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Nuxt.js': {\n icon: 'nuxt',\n url: 'https://nuxtjs.org/',\n npm: 'nuxt',\n test: function(win) {\n if ((win.__NUXT__ && win.__NUXT__.data != null) || win.$nuxt) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Nuxt.js (Fast path)': {\n icon: 'nuxt',\n url: 'https://nuxtjs.org/',\n npm: 'nuxt',\n test: function (win) {\n if (win.__NUXT__ || win.$nuxt) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Two': {\n icon: 'two',\n url: 'https://two.js.org/',\n npm: 'two.js',\n test: function(win) {\n if (win.Two && win.Two.Utils) {\n return { version: win.Two.Version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Brewser': {\n icon: 'brewser',\n url: 'https://robertpataki.github.io/brewser/',\n npm: 'brewser',\n test: function(win) {\n if(win.BREWSER && win.BREWSER.ua) {\n return { version: BREWSER.VERSION || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Material Design Lite': {\n icon: 'mdl',\n url: 'https://getmdl.io/',\n npm: 'material-design-lite',\n test: function(win) {\n if(win.componentHandler && win.componentHandler.upgradeElement) {\n return { version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Kendo UI': {\n icon: 'kendoui',\n url: 'https://github.com/telerik/kendo-ui-core',\n npm: 'kendo-ui-core',\n test: function(win) {\n if (win.kendo && win.kendo.View && win.kendo.View.extend) {\n return {version: win.kendo.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Matter.js': {\n icon: 'matter-js',\n url: 'http://brm.io/matter-js/',\n npm: 'matter-js',\n test: function(win) {\n if (win.Matter && win.Matter.Engine) {\n return {version: UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'Riot': {\n icon: 'riot',\n url: 'http://riotjs.com/',\n npm: 'riot',\n test: function(win) {\n if (win.riot && win.riot.mixin) {\n return { version: win.riot.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Sea.js': {\n icon: 'icon38',\n url: 'https://seajs.github.io/seajs/docs/',\n npm: 'seajs',\n test: function(win) {\n if(win.seajs && win.seajs.use) {\n return { version: win.seajs.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Moment.js': {\n icon: 'momentjs',\n url: 'http://momentjs.com/',\n npm: 'moment',\n test: function(win) {\n if(win.moment && (win.moment.isMoment || win.moment.lang)) {\n // version 1.0.0 has neither \"isMoment\" nor \"version\"\n return { version: win.moment.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Moment Timezone': {\n icon: 'momentjs',\n url: 'http://momentjs.com/timezone/',\n npm: 'moment-timezone',\n test: function(win) {\n if (win.moment && win.moment.tz) {\n return { version: win.moment.tz.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'ScrollMagic': {\n icon: 'scrollmagic',\n url: 'http://scrollmagic.io/',\n npm: 'scrollmagic',\n test: function(win) {\n if (win.ScrollMagic && win.ScrollMagic.Controller) {\n return {version: ScrollMagic.version || UNKNOWN_VERSION};\n }\n return false;\n }\n },\n 'SWFObject': {\n icon: 'icon38', // currently has no icon\n url: 'https://github.com/swfobject/swfobject',\n test: function(win) {\n if (win.swfobject && win.swfobject.embedSWF) {\n // 2.x - exact version only for 2.3\n return { version: win.swfobject.version || UNKNOWN_VERSION };\n } else if(win.deconcept && win.deconcept.SWFObject) {\n // 1.x\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'FlexSlider': {\n icon: 'icon38', // currently has no icon\n url: 'https://woocommerce.com/flexslider/',\n npm: 'flexslider',\n test: function(win) {\n var jq = win.jQuery || win.$ || win.$jq || win.$j;\n if (jq && jq.fn && jq.fn.jquery && jq.flexslider){\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'SPF': {\n icon: 'icon38', // currently has no icon\n url: 'https://youtube.github.io/spfjs/',\n npm: 'spf',\n test: function(win) {\n if (win.spf && win.spf.init) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Numeral.js': {\n icon: 'icon38', // currently has no icon\n url: 'http://numeraljs.com/',\n npm: 'numeraljs',\n test: function(win) {\n if (win.numeral && win.isNumeral) {\n return { version: win.numeral.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'boomerang.js': {\n icon: 'icon38', // currently has no icon\n url: 'https://soasta.github.io/boomerang/',\n npm: 'boomerangjs',\n test: function(win) {\n if (win.BOOMR && win.BOOMR.utils && win.BOOMR.init) {\n return { version: win.BOOMR.version || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Framer': {\n icon: 'framer',\n url: 'https://framer.com/',\n npm: 'framerjs',\n test: function(win) {\n if (win.Framer && win.Framer.Layer) {\n return { version: win.Framer.Version.build || UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Marko': {\n icon: 'marko',\n url: 'https://markojs.com/',\n npm: 'marko',\n test: function (win) {\n var selector = '[data-marko-key], [data-marko]';\n var markoElement = document.querySelector(selector);\n if (markoElement) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'AMP': {\n icon: 'amp',\n url: 'https://ampproject.org/',\n npm: null,\n test: function (win) {\n var version = win.document.documentElement.getAttribute(\"amp-version\");\n return version ? { version: version } : false;\n }\n },\n 'Gatsby': {\n icon: 'gatsby',\n url: 'https://www.gatsbyjs.org/',\n npm: 'gatsby',\n test: function (win) {\n if (document.getElementById('___gatsby')) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Shopify': {\n icon: 'shopify',\n url: 'https://www.shopify.com/',\n npm: null,\n test: function (win) {\n if (win.Shopify && win.Shopify.shop) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Magento': {\n icon: 'magento',\n url: 'https://magento.com/',\n npm: null,\n test: function (win) {\n // Same detecton used in Magento 2 DevTools: https://github.com/magento/m2-devtools\n const reRequireScript = /\\/static(?:\\/version\\d+)?\\/frontend\\/.+\\/.+\\/requirejs\\/require(?:\\.min)?\\.js/;\n const scripts = Array.from(document.querySelectorAll('script[src]') || []);\n if (scripts.some(s => reRequireScript.test(s.src))) {\n return { version: 2 }; // Magento 1 is no longer supported and this only verifies version 2\n }\n \n return false;\n }\n },\n 'WordPress': {\n icon: 'wordpress',\n url: 'https://wordpress.org/',\n npm: null,\n test: function (win) {\n const hasAPILinkElem = !!document.querySelector('link[rel=\"https://api.w.org/\"]');\n const hasWPIncludes = !!document.querySelectorAll('link[href*=\"wp-includes\"], script[src*=\"wp-includes\"]').length;\n\n if (!hasAPILinkElem && !hasWPIncludes) return false;\n\n const generatorMeta = document.querySelector('meta[name=generator][content^=\"WordPress\"]');\n const version = generatorMeta ? generatorMeta.getAttribute(\"content\").replace(/^\\w+\\s/,'') : UNKNOWN_VERSION;\n return { version };\n }\n },\n 'Wix': {\n icon: 'wix',\n url: 'https://www.wix.com/',\n npm: null,\n test: function (win) {\n if (win.wixBiSession) {\n return { version: UNKNOWN_VERSION };\n }\n return false;\n }\n },\n 'Workbox': {\n icon: 'workbox',\n url: 'https://developers.google.com/web/tools/workbox/',\n npm: 'workbox-sw',\n test: async function (win) {\n var nav = win.navigator;\n // Service Workers not supported\n if (!('serviceWorker' in nav)) {\n return false;\n }\n return nav.serviceWorker.getRegistration()\n .then(function(registration) {\n var scriptURL = nav.serviceWorker.controller.scriptURL;\n return fetch(scriptURL, { credentials: 'include',\n headers: { 'service-worker': 'script' }\n })\n .then(function(response) {\n return response.text();\n })\n .then(function(scriptContent) {\n var workboxRegExp = /new Workbox|new workbox|workbox\\.precaching\\.|workbox\\.strategies/gm;\n if (workboxRegExp.test(scriptContent)) {\n // Adapted from\n // https://github.com/semver/semver/issues/232#issue-48635632\n var semVerRegExp = /workbox.*?\\b((0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?)\\b/gim;\n var matches = semVerRegExp.exec(scriptContent);\n var version = UNKNOWN_VERSION;\n if (Array.isArray(matches) && matches.length > 1 && matches[1]) {\n version = matches[1];\n }\n return { version: version };\n }\n return false;\n });\n }).catch(function(exception) {\n return false;\n });\n }\n }\n};\n";
@@ -32249,9 +31326,27 @@ const log=require('lighthouse-logger');
-const stackPacksToInclude=[{
+const stackPacksToInclude=[
+{
packId:'wordpress',
-requiredStacks:['js:wordpress']}];
+requiredStacks:['js:wordpress']},
+
+{
+packId:'react',
+requiredStacks:['js:react']},
+
+{
+packId:'angular',
+requiredStacks:['js:@angular/core']},
+
+{
+packId:'amp',
+requiredStacks:['js:amp']},
+
+{
+packId:'magento',
+requiredStacks:['js:magento']}];
+
@@ -32293,7 +31388,7 @@ module.exports={
getStackPacks};
-},{"../../stack-packs/index.js":180,"lighthouse-logger":128}],82:[function(require,module,exports){
+},{"../../stack-packs/index.js":177,"lighthouse-logger":125}],82:[function(require,module,exports){
@@ -32526,107 +31621,352 @@ const{taskGroups,taskNameToGroup}=require('./task-groups.js');
+
class MainThreadTasks{
-static _createNewTaskNode(event,parent){
+static _createNewTaskNode(event,endEvent){
+const isCompleteEvent=event.ph==='X'&&!endEvent;
+const isStartEndEventPair=event.ph==='B'&&endEvent&&endEvent.ph==='E';
+if(!isCompleteEvent&&!isStartEndEventPair){
+throw new Error('Invalid parameters for _createNewTaskNode');
+}
+
+const startTime=event.ts;
+const endTime=endEvent?endEvent.ts:event.ts+Number(event.dur||0);
+
const newTask={
event,
-startTime:event.ts,
-endTime:event.ph==='X'?event.ts+Number(event.dur||0):NaN,
-parent:parent,
-children:[],
+startTime,
+endTime,
+duration:endTime-startTime,
+unbounded:false,
+parent:undefined,
+children:[],
attributableURLs:[],
group:taskGroups.other,
-duration:NaN,
selfTime:NaN};
-if(parent){
-parent.children.push(newTask);
+return newTask;
}
-return newTask;
+
+
+
+
+
+
+
+static _assignAllTimersUntilTs(
+currentTask,
+stopTs,
+priorTaskData,
+reverseEventsQueue)
+{
+while(reverseEventsQueue.length){
+const nextTimerInstallEvent=reverseEventsQueue.pop();
+
+if(!nextTimerInstallEvent)break;
+
+
+if(nextTimerInstallEvent.ts>stopTs){
+reverseEventsQueue.push(nextTimerInstallEvent);
+break;
+}
+
+
+if(nextTimerInstallEvent.ts<currentTask.startTime){
+continue;
}
+const timerId=nextTimerInstallEvent.args.data.timerId;
+priorTaskData.timers.set(timerId,currentTask);
+}
+}
+
-static _createTasksFromEvents(mainThreadEvents,priorTaskData,traceEndTs){
+
+
+
+
+
+
+
+
+
+
+
+
+static _createTasksFromStartAndEndEvents(taskStartEvents,taskEndEvents,traceEndTs){
const tasks=[];
-let currentTask;
-for(const event of mainThreadEvents){
-if(event.name==='TimerInstall'&&currentTask){
+const taskEndEventsReverseQueue=taskEndEvents.slice().reverse();
+for(let i=0;i<taskStartEvents.length;i++){
+const taskStartEvent=taskStartEvents[i];
+if(taskStartEvent.ph==='X'){
-const timerId=event.args.data.timerId;
-priorTaskData.timers.set(timerId,currentTask);
+tasks.push(MainThreadTasks._createNewTaskNode(taskStartEvent));
+continue;
+}
+
+
+let matchedEventIndex=-1;
+let matchingNestedEventCount=0;
+let matchingNestedEventIndex=i+1;
+
+
+
+
+
+for(let j=taskEndEventsReverseQueue.length-1;j>=0;j--){
+const endEvent=taskEndEventsReverseQueue[j];
+
+for(;matchingNestedEventIndex<taskStartEvents.length;matchingNestedEventIndex++){
+if(taskStartEvents[matchingNestedEventIndex].ts>=endEvent.ts)break;
+
+if(taskStartEvents[matchingNestedEventIndex].name===taskStartEvent.name){
+matchingNestedEventCount++;
+}
+}
+
+
+if(endEvent.name!==taskStartEvent.name)continue;
+
+if(endEvent.ts<taskStartEvent.ts)continue;
+
+
+if(matchingNestedEventCount>0){
+
+matchingNestedEventCount--;
+continue;
}
-if(event.ph!=='X'&&event.ph!=='B'&&event.ph!=='E')continue;
+matchedEventIndex=j;
+break;
+}
+
+
+let taskEndEvent;
+let unbounded=false;
+if(matchedEventIndex===-1){
+
+
+taskEndEvent={ph:'E',ts:traceEndTs};
+unbounded=true;
+}else if(matchedEventIndex===taskEndEventsReverseQueue.length-1){
+
+
+taskEndEvent=taskEndEventsReverseQueue.pop();
+}else{
+taskEndEvent=taskEndEventsReverseQueue.splice(matchedEventIndex,1)[0];
+}
+
+const task=MainThreadTasks._createNewTaskNode(taskStartEvent,taskEndEvent);
+task.unbounded=unbounded;
+tasks.push(task);
+}
+
+if(taskEndEventsReverseQueue.length){
+throw new Error(
+`Fatal trace logic error - ${taskEndEventsReverseQueue.length} unmatched end events`);
+
+}
+
+return tasks;
+}
+
+
+
+
+
+
+
+
+
+
+static _createTaskRelationships(sortedTasks,timerInstallEvents,priorTaskData){
+
+let currentTask;
+
+const timerInstallEventsReverseQueue=timerInstallEvents.slice().reverse();
+
+for(let i=0;i<sortedTasks.length;i++){
+let nextTask=sortedTasks[i];
+
+
while(
currentTask&&
Number.isFinite(currentTask.endTime)&&
-currentTask.endTime<=event.ts)
+currentTask.endTime<=nextTask.startTime)
{
+MainThreadTasks._assignAllTimersUntilTs(
+currentTask,
+currentTask.endTime,
+priorTaskData,
+timerInstallEventsReverseQueue);
+
currentTask=currentTask.parent;
}
-if(!currentTask){
-if(event.ph==='E'){
-throw new Error('Fatal trace logic error - unexpected end event');
-}
+if(currentTask){
+if(nextTask.endTime>currentTask.endTime){
+const timeDelta=nextTask.endTime-currentTask.endTime;
-currentTask=MainThreadTasks._createNewTaskNode(event);
-tasks.push(currentTask);
-continue;
+if(timeDelta<1000){
+
+currentTask.endTime=nextTask.endTime;
+currentTask.duration+=timeDelta;
+}else if(nextTask.unbounded){
+
+nextTask.endTime=currentTask.endTime;
+nextTask.duration=nextTask.endTime-nextTask.startTime;
+}else if(
+nextTask.startTime-currentTask.startTime<1000&&
+!currentTask.children.length)
+{
+
+
+
+
+
+
+
+
+const actualParentTask=nextTask;
+const actualChildTask=currentTask;
+
+
+
+const grandparentTask=currentTask.parent;
+if(grandparentTask){
+const lastGrandparentChildIndex=grandparentTask.children.length-1;
+if(grandparentTask.children[lastGrandparentChildIndex]!==actualChildTask){
+
+
+throw new Error('Fatal trace logic error - impossible children');
}
-if(event.ph==='X'||event.ph==='B'){
+grandparentTask.children.pop();
+grandparentTask.children.push(actualParentTask);
+}
-const newTask=MainThreadTasks._createNewTaskNode(event,currentTask);
-tasks.push(newTask);
-currentTask=newTask;
+actualParentTask.parent=grandparentTask;
+actualParentTask.startTime=actualChildTask.startTime;
+actualParentTask.duration=actualParentTask.endTime-actualParentTask.startTime;
+currentTask=actualParentTask;
+nextTask=actualChildTask;
}else{
-if(currentTask.event.ph!=='B'){
-throw new Error(
-`Fatal trace logic error - expected start event, got ${currentTask.event.ph}`);
+
+
+
+
+
+
+
+const error=new Error('Fatal trace logic error - child cannot end after parent');
+error.timeDelta=timeDelta;
+error.nextTaskEvent=nextTask.event;
+error.nextTaskEndTime=nextTask.endTime;
+error.currentTaskEvent=currentTask.event;
+error.currentTaskEndTime=currentTask.endTime;
+throw error;
+}
}
+nextTask.parent=currentTask;
+currentTask.children.push(nextTask);
+MainThreadTasks._assignAllTimersUntilTs(
+currentTask,
+nextTask.startTime,
+priorTaskData,
+timerInstallEventsReverseQueue);
-currentTask.endTime=event.ts;
-currentTask=currentTask.parent;
}
+
+currentTask=nextTask;
}
+if(currentTask){
+MainThreadTasks._assignAllTimersUntilTs(
+currentTask,
+currentTask.endTime,
+priorTaskData,
+timerInstallEventsReverseQueue);
-while(currentTask&&!Number.isFinite(currentTask.endTime)){
+}
+}
-currentTask.endTime=traceEndTs;
-currentTask=currentTask.parent;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static _createTasksFromEvents(mainThreadEvents,priorTaskData,traceEndTs){
+
+const taskStartEvents=[];
+
+const taskEndEvents=[];
+
+const timerInstallEvents=[];
+
+
+for(const event of mainThreadEvents){
+if(event.ph==='X'||event.ph==='B')taskStartEvents.push(event);
+if(event.ph==='E')taskEndEvents.push(event);
+if(event.name==='TimerInstall')timerInstallEvents.push(event);
}
-return tasks;
+const tasks=MainThreadTasks._createTasksFromStartAndEndEvents(
+taskStartEvents,
+taskEndEvents,
+traceEndTs);
+
+
+
+const sortedTasks=tasks.sort(
+(taskA,taskB)=>taskA.startTime-taskB.startTime||taskB.duration-taskA.duration);
+
+
+
+MainThreadTasks._createTaskRelationships(sortedTasks,timerInstallEvents,priorTaskData);
+
+
+return sortedTasks.sort(
+(taskA,taskB)=>taskA.startTime-taskB.startTime||taskB.duration-taskA.duration);
+
}
@@ -32642,7 +31982,6 @@ throw new Error('Fatal trace logic error - child cannot end after parent');
const childTime=task.children.
map(child=>MainThreadTasks._computeRecursiveSelfTime(child,task)).
reduce((sum,child)=>sum+child,0);
-task.duration=task.endTime-task.startTime;
task.selfTime=task.duration-childTime;
return task.duration;
}
@@ -32699,6 +32038,7 @@ attributableURLs.push(url);
task.attributableURLs=attributableURLs;
task.children.forEach(child=>
MainThreadTasks._computeRecursiveAttributableURLs(child,attributableURLs,priorTaskData));
+
}
@@ -32716,10 +32056,14 @@ task.children.forEach(child=>MainThreadTasks._computeRecursiveTaskGroup(child,ta
-static getMainThreadTasks(traceEvents,traceEndTs){
+static getMainThreadTasks(mainThreadEvents,traceEndTs){
const timers=new Map();
const priorTaskData={timers};
-const tasks=MainThreadTasks._createTasksFromEvents(traceEvents,priorTaskData,traceEndTs);
+const tasks=MainThreadTasks._createTasksFromEvents(
+mainThreadEvents,
+priorTaskData,
+traceEndTs);
+
for(const task of tasks){
@@ -32931,7 +32275,111 @@ ACCEPTABLE_NAVIGATION_URL_REGEX.test(event.args.data.documentLoaderURL));
-static _filteredStableSort(traceEvents,filter){
+
+
+
+
+
+
+
+
+
+
+
+
+
+static _sortTimestampEventGroup(
+tsGroupIndices,
+timestampSortedIndices,
+indexOfTsGroupIndicesStart,
+traceEvents)
+{
+
+
+
+
+
+
+
+
+
+
+
+
+const lookupArrayIndexByTsIndex=i=>timestampSortedIndices[i];
+
+const lookupEventByTsIndex=i=>traceEvents[lookupArrayIndexByTsIndex(i)];
+
+
+const eEventIndices=[];
+
+const bxEventIndices=[];
+
+const otherEventIndices=[];
+
+for(const tsIndex of tsGroupIndices){
+
+const arrayIndex=lookupArrayIndexByTsIndex(tsIndex);
+const event=lookupEventByTsIndex(tsIndex);
+if(event.ph==='E')eEventIndices.push(arrayIndex);else
+if(event.ph==='X'||event.ph==='B')bxEventIndices.push(arrayIndex);else
+otherEventIndices.push(arrayIndex);
+}
+
+
+const effectiveDuration=new Map();
+for(const index of bxEventIndices){
+const event=traceEvents[index];
+if(event.ph==='X'){
+effectiveDuration.set(index,event.dur);
+}else{
+
+let duration=Number.MAX_SAFE_INTEGER;
+
+let additionalNestedEventsWithSameName=0;
+const startIndex=indexOfTsGroupIndicesStart+tsGroupIndices.length;
+for(let j=startIndex;j<timestampSortedIndices.length;j++){
+const potentialMatchingEvent=lookupEventByTsIndex(j);
+const eventMatches=potentialMatchingEvent.name===event.name&&
+potentialMatchingEvent.pid===event.pid&&
+potentialMatchingEvent.tid===event.tid;
+
+
+if(!eventMatches)continue;
+
+if(potentialMatchingEvent.ph==='E'&&additionalNestedEventsWithSameName===0){
+
+duration=potentialMatchingEvent.ts-event.ts;
+break;
+}else if(potentialMatchingEvent.ph==='E'){
+
+additionalNestedEventsWithSameName--;
+}else if(potentialMatchingEvent.ph==='B'){
+
+additionalNestedEventsWithSameName++;
+}
+}
+
+effectiveDuration.set(index,duration);
+}
+}
+
+bxEventIndices.sort((indexA,indexB)=>(effectiveDuration.get(indexB)||0)-(
+effectiveDuration.get(indexA)||0)||indexA-indexB);
+
+otherEventIndices.sort((indexA,indexB)=>indexA-indexB);
+
+return[...eEventIndices,...bxEventIndices,...otherEventIndices];
+}
+
+
+
+
+
+
+
+
+static filteredTraceSort(traceEvents,filter){
const indices=[];
for(let srcIndex=0;srcIndex<traceEvents.length;srcIndex++){
@@ -32941,10 +32389,32 @@ indices.push(srcIndex);
}
-indices.sort((indexA,indexB)=>{
-const result=traceEvents[indexA].ts-traceEvents[indexB].ts;
-return result?result:indexA-indexB;
-});
+indices.sort((indexA,indexB)=>traceEvents[indexA].ts-traceEvents[indexB].ts);
+
+
+for(let i=0;i<indices.length-1;i++){
+const ts=traceEvents[indices[i]].ts;
+const tsGroupIndices=[i];
+for(let j=i+1;j<indices.length;j++){
+if(traceEvents[indices[j]].ts!==ts)break;
+tsGroupIndices.push(j);
+}
+
+
+if(tsGroupIndices.length===1)continue;
+
+
+const finalIndexOrder=TraceProcessor._sortTimestampEventGroup(
+tsGroupIndices,
+indices,
+i,
+traceEvents);
+
+indices.splice(i,finalIndexOrder.length,...finalIndexOrder);
+
+
+i+=tsGroupIndices.length-1;
+}
const sorted=[];
@@ -33218,7 +32688,7 @@ evt.name===SCHEDULABLE_TASK_TITLE_ALT3;
static computeTraceOfTab(trace){
-const keyEvents=this._filteredStableSort(trace.traceEvents,e=>{
+const keyEvents=this.filteredTraceSort(trace.traceEvents,e=>{
return e.cat.includes('blink.user_timing')||
e.cat.includes('loading')||
e.cat.includes('devtools.timeline')||
@@ -33264,6 +32734,28 @@ log.verbose('trace-of-tab','No `firstMeaningfulPaintCandidate` events found in t
firstMeaningfulPaint=lastCandidate;
}
+
+
+
+let largestContentfulPaint;
+let lcpInvalidated=false;
+
+for(let i=frameEvents.length-1;i>=0;i--){
+const e=frameEvents[i];
+
+if(e.ts<=navigationStart.ts)break;
+
+if(e.name==='largestContentfulPaint::Invalidate'){
+lcpInvalidated=true;
+break;
+}
+
+if(e.name!=='largestContentfulPaint::Candidate')continue;
+
+largestContentfulPaint=e;
+break;
+}
+
const load=frameEvents.find(e=>e.name==='loadEventEnd'&&e.ts>navigationStart.ts);
const domContentLoaded=frameEvents.find(
e=>e.name==='domContentLoadedEventEnd'&&e.ts>navigationStart.ts);
@@ -33272,7 +32764,7 @@ e=>e.name==='domContentLoadedEventEnd'&&e.ts>navigationStart.ts);
const processEvents=TraceProcessor.
-_filteredStableSort(trace.traceEvents,e=>e.pid===mainFrameIds.pid);
+filteredTraceSort(trace.traceEvents,e=>e.pid===mainFrameIds.pid);
const mainThreadEvents=processEvents.
filter(e=>e.tid===mainFrameIds.tid);
@@ -33291,6 +32783,7 @@ navigationStart:navigationStart.ts,
firstPaint:getTimestamp(firstPaint),
firstContentfulPaint:getTimestamp(firstContentfulPaint),
firstMeaningfulPaint:getTimestamp(firstMeaningfulPaint),
+largestContentfulPaint:getTimestamp(largestContentfulPaint),
traceEnd:fakeEndOfTraceEvt.ts,
load:getTimestamp(load),
domContentLoaded:getTimestamp(domContentLoaded)};
@@ -33306,6 +32799,7 @@ navigationStart:0,
firstPaint:maybeGetTiming(timestamps.firstPaint),
firstContentfulPaint:maybeGetTiming(timestamps.firstContentfulPaint),
firstMeaningfulPaint:maybeGetTiming(timestamps.firstMeaningfulPaint),
+largestContentfulPaint:maybeGetTiming(timestamps.largestContentfulPaint),
traceEnd:getTiming(timestamps.traceEnd),
load:maybeGetTiming(timestamps.load),
domContentLoaded:maybeGetTiming(timestamps.domContentLoaded)};
@@ -33321,9 +32815,11 @@ navigationStartEvt:navigationStart,
firstPaintEvt:firstPaint,
firstContentfulPaintEvt:firstContentfulPaint,
firstMeaningfulPaintEvt:firstMeaningfulPaint,
+largestContentfulPaintEvt:largestContentfulPaint,
loadEvt:load,
domContentLoadedEvt:domContentLoaded,
-fmpFellBack};
+fmpFellBack,
+lcpInvalidated};
}}
@@ -33338,7 +32834,7 @@ module.exports=TraceProcessor;
-},{"lighthouse-logger":128}],87:[function(require,module,exports){
+},{"lighthouse-logger":125}],87:[function(require,module,exports){
@@ -33543,7 +33039,7 @@ return fakeEvents;
module.exports=Metrics;
-},{"lighthouse-logger":128}],88:[function(require,module,exports){
+},{"lighthouse-logger":125}],88:[function(require,module,exports){
@@ -33738,7 +33234,7 @@ return rating;
static formatNumber(number,granularity=0.1){
const coarseValue=Math.round(number/granularity)*granularity;
-return coarseValue.toLocaleString(Util.numberDateLocale);
+return Util.numberFormatter.format(coarseValue);
}
@@ -33747,8 +33243,7 @@ return coarseValue.toLocaleString(Util.numberDateLocale);
static formatBytesToKB(size,granularity=0.1){
-const kbs=(Math.round(size/1024/granularity)*granularity).
-toLocaleString(Util.numberDateLocale);
+const kbs=Util.numberFormatter.format(Math.round(size/1024/granularity)*granularity);
return`${kbs}${NBSP}KB`;
}
@@ -33759,7 +33254,7 @@ return`${kbs}${NBSP}KB`;
static formatMilliseconds(ms,granularity=10){
const coarseTime=Math.round(ms/granularity)*granularity;
-return`${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}ms`;
+return`${Util.numberFormatter.format(coarseTime)}${NBSP}ms`;
}
@@ -33769,7 +33264,7 @@ return`${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}ms`;
static formatSeconds(ms,granularity=0.1){
const coarseTime=Math.round(ms/1000/granularity)*granularity;
-return`${coarseTime.toLocaleString(Util.numberDateLocale)}${NBSP}s`;
+return`${Util.numberFormatter.format(coarseTime)}${NBSP}s`;
}
@@ -33831,6 +33326,73 @@ return parts.join(' ');
+
+
+static splitMarkdownCodeSpans(text){
+
+const segments=[];
+
+
+const parts=text.split(/`(.*?)`/g);
+for(let i=0;i<parts.length;i++){
+const text=parts[i];
+
+
+if(!text)continue;
+
+
+const isCode=i%2!==0;
+segments.push({
+isCode,
+text});
+
+}
+
+return segments;
+}
+
+
+
+
+
+
+
+
+
+static splitMarkdownLink(text){
+
+const segments=[];
+
+const parts=text.split(/\[([^\]]+?)\]\((https?:\/\/.*?)\)/g);
+while(parts.length){
+
+const[preambleText,linkText,linkHref]=parts.splice(0,3);
+
+if(preambleText){
+segments.push({
+isLink:false,
+text:preambleText});
+
+}
+
+
+if(linkText&&linkHref){
+segments.push({
+isLink:true,
+text:linkText,
+linkHref});
+
+}
+}
+
+return segments;
+}
+
+
+
+
+
+
static getURLDisplayName(parsedUrl,options){
options=options||{numPathParts:undefined,preserveQuery:undefined,
@@ -34035,10 +33597,11 @@ summary:`${deviceEmulation}, ${summary}`};
static setNumberDateLocale(locale){
-Util.numberDateLocale=locale;
+if(locale==='en-XA')locale='de';
-if(Util.numberDateLocale==='en-XA')Util.numberDateLocale='de';
+Util.numberDateLocale=locale;
+Util.numberFormatter=new Intl.NumberFormat(locale);
}
@@ -34101,6 +33664,12 @@ Util.numberDateLocale='en';
+Util.numberFormatter=new Intl.NumberFormat(Util.numberDateLocale);
+
+
+
+
+
Util.UIStrings={
varianceDisclaimer:'Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted).',
@@ -34699,7 +34268,7 @@ return /\.js$/.test(f)&&!ignoredFiles.includes(f);
static getGathererList(){
const fileList=[
-...["accessibility.js","anchor-elements.js","cache-contents.js","console-messages.js","css-usage.js","dobetterweb","gatherer.js","html-without-javascript.js","http-redirect.js","image-elements.js","js-usage.js","link-elements.js","meta-elements.js","mixed-content.js","offline.js","runtime-exceptions.js","script-elements.js","seo","service-worker.js","start-url.js","viewport-dimensions.js"],
+...["accessibility.js","anchor-elements.js","cache-contents.js","console-messages.js","css-usage.js","dobetterweb","gatherer.js","html-without-javascript.js","http-redirect.js","iframe-elements.js","image-elements.js","js-usage.js","link-elements.js","main-document-content.js","meta-elements.js","mixed-content.js","offline.js","runtime-exceptions.js","script-elements.js","seo","service-worker.js","source-maps.js","start-url.js","viewport-dimensions.js"],
...["embedded-content.js","font-size.js","robots-txt.js","tap-targets.js"].map(f=>`seo/${f}`),
...["appcache.js","doctype.js","domstats.js","optimized-images.js","password-inputs-with-prevented-paste.js","response-compression.js","tags-blocking-first-paint.js"].
map(f=>`dobetterweb/${f}`)];
@@ -34726,7 +34295,7 @@ return path.join(process.cwd(),'latest-run');
module.exports=Runner;
}).call(this,require('_process'));
-},{"../package.json":179,"./audits/audit.js":3,"./gather/driver.js":51,"./gather/gather-runner.js":52,"./lib/asset-saver.js":56,"./lib/i18n/i18n.js":68,"./lib/lh-error.js":72,"./lib/sentry.js":79,"./lib/stack-packs.js":81,"./lib/url-shim.js":"url","./report/report-generator.js":89,"./scoring.js":91,"_process":145,"lighthouse-logger":128,"lodash.isequal":129,"path":143}],91:[function(require,module,exports){
+},{"../package.json":176,"./audits/audit.js":3,"./gather/driver.js":52,"./gather/gather-runner.js":53,"./lib/asset-saver.js":57,"./lib/i18n/i18n.js":67,"./lib/lh-error.js":72,"./lib/sentry.js":79,"./lib/stack-packs.js":81,"./lib/url-shim.js":"url","./report/report-generator.js":89,"./scoring.js":91,"_process":142,"lighthouse-logger":125,"lodash.isequal":126,"path":140}],91:[function(require,module,exports){
@@ -35937,7 +35506,7 @@ return Object.prototype.hasOwnProperty.call(obj,prop);
}
}).call(this,require('_process'),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{"./support/isBuffer":94,"_process":145,"inherits":93}],96:[function(require,module,exports){
+},{"./support/isBuffer":94,"_process":142,"inherits":93}],96:[function(require,module,exports){
const langs=[
'aa',
@@ -44658,7 +44227,7 @@ this._error('Failed to reset stream');
exports.Zlib=Zlib;
}).call(this,require('_process'),require("buffer").Buffer);
-},{"_process":145,"assert":92,"buffer":102,"pako/lib/zlib/constants":136,"pako/lib/zlib/deflate.js":138,"pako/lib/zlib/inflate.js":101,"pako/lib/zlib/zstream":141}],100:[function(require,module,exports){
+},{"_process":142,"assert":92,"buffer":102,"pako/lib/zlib/constants":133,"pako/lib/zlib/deflate.js":135,"pako/lib/zlib/inflate.js":101,"pako/lib/zlib/zstream":138}],100:[function(require,module,exports){
(function(process){
'use strict';
@@ -45270,7 +44839,7 @@ util.inherits(DeflateRaw,Zlib);
util.inherits(InflateRaw,Zlib);
util.inherits(Unzip,Zlib);
}).call(this,require('_process'));
-},{"./binding":99,"_process":145,"assert":92,"buffer":102,"stream":170,"util":178}],101:[function(require,module,exports){
+},{"./binding":99,"_process":142,"assert":92,"buffer":102,"stream":167,"util":175}],101:[function(require,module,exports){
arguments[4][98][0].apply(exports,arguments);
},{"dup":98}],102:[function(require,module,exports){
(function(Buffer){
@@ -47164,7 +46733,7 @@ return Object.prototype.toString.call(o);
}
}).call(this,{"isBuffer":require("../../is-buffer/index.js")});
-},{"../../is-buffer/index.js":123}],104:[function(require,module,exports){
+},{"../../is-buffer/index.js":120}],104:[function(require,module,exports){
module.exports=[
"aliceblue",
"antiquewhite",
@@ -48204,7 +47773,7 @@ return window.localStorage;
}
}).call(this,require('_process'));
-},{"./debug":107,"_process":145}],107:[function(require,module,exports){
+},{"./debug":107,"_process":142}],107:[function(require,module,exports){
@@ -48408,7 +47977,7 @@ if(val instanceof Error)return val.stack||val.message;
return val;
}
-},{"ms":133}],108:[function(require,module,exports){
+},{"ms":130}],108:[function(require,module,exports){
@@ -49240,7 +48809,7 @@ return refs.join(', ');
module.exports=Link;
}).call(this,{"isBuffer":require("../../is-buffer/index.js")});
-},{"../../is-buffer/index.js":123,"./trim":110,"querystring":148}],110:[function(require,module,exports){
+},{"../../is-buffer/index.js":120,"./trim":110,"querystring":145}],110:[function(require,module,exports){
module.exports=function trim(value){
return value.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,'');
};
@@ -49481,20 +49050,19 @@ arguments[4][93][0].apply(exports,arguments);
},{"dup":93}],114:[function(require,module,exports){
'use strict';
-exports=module.exports=require('./lib/parser')['default'];
-exports['default']=exports;
+var parser=require('./lib/parser');
-},{"./lib/parser":115}],115:[function(require,module,exports){
-"use strict";
+module.exports=parser;
+module.exports['default']=parser;
-exports["default"]=function(){
-"use strict";
+},{"./lib/parser":115}],115:[function(require,module,exports){
+"use strict";
function peg$subclass(child,parent){
function ctor(){this.constructor=child;}
@@ -49516,11 +49084,117 @@ Error.captureStackTrace(this,peg$SyntaxError);
peg$subclass(peg$SyntaxError,Error);
-function peg$parse(input){
-var options=arguments.length>1?arguments[1]:{},
-parser=this,
+peg$SyntaxError.buildMessage=function(expected,found){
+var DESCRIBE_EXPECTATION_FNS={
+literal:function(expectation){
+return"\""+literalEscape(expectation.text)+"\"";
+},
+
+"class":function(expectation){
+var escapedParts="",
+i;
+
+for(i=0;i<expectation.parts.length;i++){
+escapedParts+=expectation.parts[i]instanceof Array?
+classEscape(expectation.parts[i][0])+"-"+classEscape(expectation.parts[i][1]):
+classEscape(expectation.parts[i]);
+}
+
+return"["+(expectation.inverted?"^":"")+escapedParts+"]";
+},
+
+any:function(expectation){
+return"any character";
+},
+
+end:function(expectation){
+return"end of input";
+},
+
+other:function(expectation){
+return expectation.description;
+}};
+
+
+function hex(ch){
+return ch.charCodeAt(0).toString(16).toUpperCase();
+}
+
+function literalEscape(s){
+return s.
+replace(/\\/g,'\\\\').
+replace(/"/g,'\\"').
+replace(/\0/g,'\\0').
+replace(/\t/g,'\\t').
+replace(/\n/g,'\\n').
+replace(/\r/g,'\\r').
+replace(/[\x00-\x0F]/g,function(ch){return'\\x0'+hex(ch);}).
+replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch){return'\\x'+hex(ch);});
+}
+
+function classEscape(s){
+return s.
+replace(/\\/g,'\\\\').
+replace(/\]/g,'\\]').
+replace(/\^/g,'\\^').
+replace(/-/g,'\\-').
+replace(/\0/g,'\\0').
+replace(/\t/g,'\\t').
+replace(/\n/g,'\\n').
+replace(/\r/g,'\\r').
+replace(/[\x00-\x0F]/g,function(ch){return'\\x0'+hex(ch);}).
+replace(/[\x10-\x1F\x7F-\x9F]/g,function(ch){return'\\x'+hex(ch);});
+}
+
+function describeExpectation(expectation){
+return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
+}
+
+function describeExpected(expected){
+var descriptions=new Array(expected.length),
+i,j;
+
+for(i=0;i<expected.length;i++){
+descriptions[i]=describeExpectation(expected[i]);
+}
+
+descriptions.sort();
-peg$FAILED={},
+if(descriptions.length>0){
+for(i=1,j=1;i<descriptions.length;i++){
+if(descriptions[i-1]!==descriptions[i]){
+descriptions[j]=descriptions[i];
+j++;
+}
+}
+descriptions.length=j;
+}
+
+switch(descriptions.length){
+case 1:
+return descriptions[0];
+
+case 2:
+return descriptions[0]+" or "+descriptions[1];
+
+default:
+return descriptions.slice(0,-1).join(", ")+
+", or "+
+descriptions[descriptions.length-1];}
+
+}
+
+function describeFound(found){
+return found?"\""+literalEscape(found)+"\"":"end of input";
+}
+
+return"Expected "+describeExpected(expected)+" but "+describeFound(found)+" found.";
+};
+
+function peg$parse(input,options){
+options=options!==void 0?options:{};
+
+var peg$FAILED={},
peg$startRuleFunctions={start:peg$parsestart},
peg$startRuleFunction=peg$parsestart,
@@ -49532,19 +49206,10 @@ elements:elements,
location:location()};
},
-peg$c1=function(text){
-var string='',
-i,j,outerLen,inner,innerLen;
-
-for(i=0,outerLen=text.length;i<outerLen;i+=1){
-inner=text[i];
-
-for(j=0,innerLen=inner.length;j<innerLen;j+=1){
-string+=inner[j];
-}
-}
-
-return string;
+peg$c1=function(chunks){
+return chunks.reduce(function(all,chunk){
+return all.concat(chunk);
+},[]).join('');
},
peg$c2=function(messageText){
return{
@@ -49553,15 +49218,14 @@ value:messageText,
location:location()};
},
-peg$c3=/^[^ \t\n\r,.+={}#]/,
-peg$c4={type:"class",value:"[^ \\t\\n\\r,.+={}#]",description:"[^ \\t\\n\\r,.+={}#]"},
-peg$c5="{",
-peg$c6={type:"literal",value:"{",description:"\"{\""},
-peg$c7=",",
-peg$c8={type:"literal",value:",",description:"\",\""},
-peg$c9="}",
-peg$c10={type:"literal",value:"}",description:"\"}\""},
-peg$c11=function(id,format){
+peg$c3=function(chars){return chars.join('');},
+peg$c4="{",
+peg$c5=peg$literalExpectation("{",false),
+peg$c6=",",
+peg$c7=peg$literalExpectation(",",false),
+peg$c8="}",
+peg$c9=peg$literalExpectation("}",false),
+peg$c10=function(id,format){
return{
type:'argumentElement',
id:id,
@@ -49569,22 +49233,22 @@ format:format&&format[2],
location:location()};
},
-peg$c12="number",
-peg$c13={type:"literal",value:"number",description:"\"number\""},
-peg$c14="date",
-peg$c15={type:"literal",value:"date",description:"\"date\""},
-peg$c16="time",
-peg$c17={type:"literal",value:"time",description:"\"time\""},
-peg$c18=function(type,style){
+peg$c11="number",
+peg$c12=peg$literalExpectation("number",false),
+peg$c13="date",
+peg$c14=peg$literalExpectation("date",false),
+peg$c15="time",
+peg$c16=peg$literalExpectation("time",false),
+peg$c17=function(type,style){
return{
type:type+'Format',
style:style&&style[2],
location:location()};
},
-peg$c19="plural",
-peg$c20={type:"literal",value:"plural",description:"\"plural\""},
-peg$c21=function(pluralStyle){
+peg$c18="plural",
+peg$c19=peg$literalExpectation("plural",false),
+peg$c20=function(pluralStyle){
return{
type:pluralStyle.type,
ordinal:false,
@@ -49593,9 +49257,9 @@ options:pluralStyle.options,
location:location()};
},
-peg$c22="selectordinal",
-peg$c23={type:"literal",value:"selectordinal",description:"\"selectordinal\""},
-peg$c24=function(pluralStyle){
+peg$c21="selectordinal",
+peg$c22=peg$literalExpectation("selectordinal",false),
+peg$c23=function(pluralStyle){
return{
type:pluralStyle.type,
ordinal:true,
@@ -49604,18 +49268,18 @@ options:pluralStyle.options,
location:location()};
},
-peg$c25="select",
-peg$c26={type:"literal",value:"select",description:"\"select\""},
-peg$c27=function(options){
+peg$c24="select",
+peg$c25=peg$literalExpectation("select",false),
+peg$c26=function(options){
return{
type:'selectFormat',
options:options,
location:location()};
},
-peg$c28="=",
-peg$c29={type:"literal",value:"=",description:"\"=\""},
-peg$c30=function(selector,pattern){
+peg$c27="=",
+peg$c28=peg$literalExpectation("=",false),
+peg$c29=function(selector,pattern){
return{
type:'optionalFormatPattern',
selector:selector,
@@ -49623,12 +49287,12 @@ value:pattern,
location:location()};
},
-peg$c31="offset:",
-peg$c32={type:"literal",value:"offset:",description:"\"offset:\""},
-peg$c33=function(number){
+peg$c30="offset:",
+peg$c31=peg$literalExpectation("offset:",false),
+peg$c32=function(number){
return number;
},
-peg$c34=function(offset,options){
+peg$c33=function(offset,options){
return{
type:'pluralFormat',
offset:offset,
@@ -49636,45 +49300,51 @@ options:options,
location:location()};
},
-peg$c35={type:"other",description:"whitespace"},
-peg$c36=/^[ \t\n\r]/,
-peg$c37={type:"class",value:"[ \\t\\n\\r]",description:"[ \\t\\n\\r]"},
-peg$c38={type:"other",description:"optionalWhitespace"},
-peg$c39=/^[0-9]/,
-peg$c40={type:"class",value:"[0-9]",description:"[0-9]"},
-peg$c41=/^[0-9a-f]/i,
-peg$c42={type:"class",value:"[0-9a-f]i",description:"[0-9a-f]i"},
-peg$c43="0",
-peg$c44={type:"literal",value:"0",description:"\"0\""},
-peg$c45=/^[1-9]/,
-peg$c46={type:"class",value:"[1-9]",description:"[1-9]"},
-peg$c47=function(digits){
+peg$c34=peg$otherExpectation("whitespace"),
+peg$c35=/^[ \t\n\r]/,
+peg$c36=peg$classExpectation([" ","\t","\n","\r"],false,false),
+peg$c37=peg$otherExpectation("optionalWhitespace"),
+peg$c38=/^[0-9]/,
+peg$c39=peg$classExpectation([["0","9"]],false,false),
+peg$c40=/^[0-9a-f]/i,
+peg$c41=peg$classExpectation([["0","9"],["a","f"]],false,true),
+peg$c42="0",
+peg$c43=peg$literalExpectation("0",false),
+peg$c44=/^[1-9]/,
+peg$c45=peg$classExpectation([["1","9"]],false,false),
+peg$c46=function(digits){
return parseInt(digits,10);
},
-peg$c48=/^[^{}\\\0-\x1F \t\n\r]/,
-peg$c49={type:"class",value:"[^{}\\\\\\0-\\x1F\\x7f \\t\\n\\r]",description:"[^{}\\\\\\0-\\x1F\\x7f \\t\\n\\r]"},
-peg$c50="\\\\",
-peg$c51={type:"literal",value:"\\\\",description:"\"\\\\\\\\\""},
-peg$c52=function(){return'\\';},
-peg$c53="\\#",
-peg$c54={type:"literal",value:"\\#",description:"\"\\\\#\""},
-peg$c55=function(){return'\\#';},
-peg$c56="\\{",
-peg$c57={type:"literal",value:"\\{",description:"\"\\\\{\""},
-peg$c58=function(){return'\u007B';},
-peg$c59="\\}",
-peg$c60={type:"literal",value:"\\}",description:"\"\\\\}\""},
-peg$c61=function(){return'\u007D';},
-peg$c62="\\u",
-peg$c63={type:"literal",value:"\\u",description:"\"\\\\u\""},
-peg$c64=function(digits){
+peg$c47="'",
+peg$c48=peg$literalExpectation("'",false),
+peg$c49=/^[ \t\n\r,.+={}#]/,
+peg$c50=peg$classExpectation([" ","\t","\n","\r",",",".","+","=","{","}","#"],false,false),
+peg$c51=peg$anyExpectation(),
+peg$c52=function(char){return char;},
+peg$c53=function(sequence){return sequence;},
+peg$c54=/^[^{}\\\0-\x1F\x7F \t\n\r]/,
+peg$c55=peg$classExpectation(["{","}","\\",["\0","\x1F"],"\x7F"," ","\t","\n","\r"],true,false),
+peg$c56="\\\\",
+peg$c57=peg$literalExpectation("\\\\",false),
+peg$c58=function(){return'\\';},
+peg$c59="\\#",
+peg$c60=peg$literalExpectation("\\#",false),
+peg$c61=function(){return'\\#';},
+peg$c62="\\{",
+peg$c63=peg$literalExpectation("\\{",false),
+peg$c64=function(){return'\u007B';},
+peg$c65="\\}",
+peg$c66=peg$literalExpectation("\\}",false),
+peg$c67=function(){return'\u007D';},
+peg$c68="\\u",
+peg$c69=peg$literalExpectation("\\u",false),
+peg$c70=function(digits){
return String.fromCharCode(parseInt(digits,16));
},
-peg$c65=function(chars){return chars.join('');},
peg$currPos=0,
peg$savedPos=0,
-peg$posDetailsCache=[{line:1,column:1,seenCR:false}],
+peg$posDetailsCache=[{line:1,column:1}],
peg$maxFailPos=0,
peg$maxFailExpected=[],
peg$silentFails=0,
@@ -49697,27 +49367,44 @@ function location(){
return peg$computeLocation(peg$savedPos,peg$currPos);
}
-function expected(description){
-throw peg$buildException(
-null,
-[{type:"other",description:description}],
+function expected(description,location){
+location=location!==void 0?location:peg$computeLocation(peg$savedPos,peg$currPos);
+
+throw peg$buildStructuredError(
+[peg$otherExpectation(description)],
input.substring(peg$savedPos,peg$currPos),
-peg$computeLocation(peg$savedPos,peg$currPos));
+location);
}
-function error(message){
-throw peg$buildException(
-message,
-null,
-input.substring(peg$savedPos,peg$currPos),
-peg$computeLocation(peg$savedPos,peg$currPos));
+function error(message,location){
+location=location!==void 0?location:peg$computeLocation(peg$savedPos,peg$currPos);
+throw peg$buildSimpleError(message,location);
+}
+
+function peg$literalExpectation(text,ignoreCase){
+return{type:"literal",text:text,ignoreCase:ignoreCase};
+}
+
+function peg$classExpectation(parts,inverted,ignoreCase){
+return{type:"class",parts:parts,inverted:inverted,ignoreCase:ignoreCase};
+}
+
+function peg$anyExpectation(){
+return{type:"any"};
+}
+
+function peg$endExpectation(){
+return{type:"end"};
+}
+
+function peg$otherExpectation(description){
+return{type:"other",description:description};
}
function peg$computePosDetails(pos){
-var details=peg$posDetailsCache[pos],
-p,ch;
+var details=peg$posDetailsCache[pos],p;
if(details){
return details;
@@ -49730,23 +49417,15 @@ p--;
details=peg$posDetailsCache[p];
details={
line:details.line,
-column:details.column,
-seenCR:details.seenCR};
+column:details.column};
while(p<pos){
-ch=input.charAt(p);
-if(ch==="\n"){
-if(!details.seenCR){details.line++;}
-details.column=1;
-details.seenCR=false;
-}else if(ch==="\r"||ch==="\u2028"||ch==="\u2029"){
+if(input.charCodeAt(p)===10){
details.line++;
details.column=1;
-details.seenCR=true;
}else{
details.column++;
-details.seenCR=false;
}
p++;
@@ -49786,71 +49465,13 @@ peg$maxFailExpected=[];
peg$maxFailExpected.push(expected);
}
-function peg$buildException(message,expected,found,location){
-function cleanupExpected(expected){
-var i=1;
-
-expected.sort(function(a,b){
-if(a.description<b.description){
-return-1;
-}else if(a.description>b.description){
-return 1;
-}else{
-return 0;
-}
-});
-
-while(i<expected.length){
-if(expected[i-1]===expected[i]){
-expected.splice(i,1);
-}else{
-i++;
-}
-}
-}
-
-function buildMessage(expected,found){
-function stringEscape(s){
-function hex(ch){return ch.charCodeAt(0).toString(16).toUpperCase();}
-
-return s.
-replace(/\\/g,'\\\\').
-replace(/"/g,'\\"').
-replace(/\x08/g,'\\b').
-replace(/\t/g,'\\t').
-replace(/\n/g,'\\n').
-replace(/\f/g,'\\f').
-replace(/\r/g,'\\r').
-replace(/[\x00-\x07\x0B\x0E\x0F]/g,function(ch){return'\\x0'+hex(ch);}).
-replace(/[\x10-\x1F\x80-\xFF]/g,function(ch){return'\\x'+hex(ch);}).
-replace(/[\u0100-\u0FFF]/g,function(ch){return'\\u0'+hex(ch);}).
-replace(/[\u1000-\uFFFF]/g,function(ch){return'\\u'+hex(ch);});
-}
-
-var expectedDescs=new Array(expected.length),
-expectedDesc,foundDesc,i;
-
-for(i=0;i<expected.length;i++){
-expectedDescs[i]=expected[i].description;
-}
-
-expectedDesc=expected.length>1?
-expectedDescs.slice(0,-1).join(", ")+
-" or "+
-expectedDescs[expected.length-1]:
-expectedDescs[0];
-
-foundDesc=found?"\""+stringEscape(found)+"\"":"end of input";
-
-return"Expected "+expectedDesc+" but "+foundDesc+" found.";
-}
-
-if(expected!==null){
-cleanupExpected(expected);
+function peg$buildSimpleError(message,location){
+return new peg$SyntaxError(message,null,null,location);
}
+function peg$buildStructuredError(expected,found,location){
return new peg$SyntaxError(
-message!==null?message:buildMessage(expected,found),
+peg$SyntaxError.buildMessage(expected,found),
expected,
found,
location);
@@ -49988,32 +49609,16 @@ s0=peg$parsenumber();
if(s0===peg$FAILED){
s0=peg$currPos;
s1=[];
-if(peg$c3.test(input.charAt(peg$currPos))){
-s2=input.charAt(peg$currPos);
-peg$currPos++;
-}else{
-s2=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c4);}
-}
-if(s2!==peg$FAILED){
+s2=peg$parsequoteEscapedChar();
while(s2!==peg$FAILED){
s1.push(s2);
-if(peg$c3.test(input.charAt(peg$currPos))){
-s2=input.charAt(peg$currPos);
-peg$currPos++;
-}else{
-s2=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c4);}
-}
-}
-}else{
-s1=peg$FAILED;
+s2=peg$parsequoteEscapedChar();
}
if(s1!==peg$FAILED){
-s0=input.substring(s0,peg$currPos);
-}else{
-s0=s1;
+peg$savedPos=s0;
+s1=peg$c3(s1);
}
+s0=s1;
}
return s0;
@@ -50024,11 +49629,11 @@ var s0,s1,s2,s3,s4,s5,s6,s7,s8;
s0=peg$currPos;
if(input.charCodeAt(peg$currPos)===123){
-s1=peg$c5;
+s1=peg$c4;
peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c6);}
+if(peg$silentFails===0){peg$fail(peg$c5);}
}
if(s1!==peg$FAILED){
s2=peg$parse_();
@@ -50039,11 +49644,11 @@ s4=peg$parse_();
if(s4!==peg$FAILED){
s5=peg$currPos;
if(input.charCodeAt(peg$currPos)===44){
-s6=peg$c7;
+s6=peg$c6;
peg$currPos++;
}else{
s6=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c8);}
+if(peg$silentFails===0){peg$fail(peg$c7);}
}
if(s6!==peg$FAILED){
s7=peg$parse_();
@@ -50071,15 +49676,15 @@ if(s5!==peg$FAILED){
s6=peg$parse_();
if(s6!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===125){
-s7=peg$c9;
+s7=peg$c8;
peg$currPos++;
}else{
s7=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c10);}
+if(peg$silentFails===0){peg$fail(peg$c9);}
}
if(s7!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c11(s3,s5);
+s1=peg$c10(s3,s5);
s0=s1;
}else{
peg$currPos=s0;
@@ -50134,28 +49739,28 @@ function peg$parsesimpleFormat(){
var s0,s1,s2,s3,s4,s5,s6;
s0=peg$currPos;
-if(input.substr(peg$currPos,6)===peg$c12){
-s1=peg$c12;
+if(input.substr(peg$currPos,6)===peg$c11){
+s1=peg$c11;
peg$currPos+=6;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c13);}
+if(peg$silentFails===0){peg$fail(peg$c12);}
}
if(s1===peg$FAILED){
-if(input.substr(peg$currPos,4)===peg$c14){
-s1=peg$c14;
+if(input.substr(peg$currPos,4)===peg$c13){
+s1=peg$c13;
peg$currPos+=4;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c15);}
+if(peg$silentFails===0){peg$fail(peg$c14);}
}
if(s1===peg$FAILED){
-if(input.substr(peg$currPos,4)===peg$c16){
-s1=peg$c16;
+if(input.substr(peg$currPos,4)===peg$c15){
+s1=peg$c15;
peg$currPos+=4;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c17);}
+if(peg$silentFails===0){peg$fail(peg$c16);}
}
}
}
@@ -50164,11 +49769,11 @@ s2=peg$parse_();
if(s2!==peg$FAILED){
s3=peg$currPos;
if(input.charCodeAt(peg$currPos)===44){
-s4=peg$c7;
+s4=peg$c6;
peg$currPos++;
}else{
s4=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c8);}
+if(peg$silentFails===0){peg$fail(peg$c7);}
}
if(s4!==peg$FAILED){
s5=peg$parse_();
@@ -50194,7 +49799,7 @@ s3=null;
}
if(s3!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c18(s1,s3);
+s1=peg$c17(s1,s3);
s0=s1;
}else{
peg$currPos=s0;
@@ -50216,22 +49821,22 @@ function peg$parsepluralFormat(){
var s0,s1,s2,s3,s4,s5;
s0=peg$currPos;
-if(input.substr(peg$currPos,6)===peg$c19){
-s1=peg$c19;
+if(input.substr(peg$currPos,6)===peg$c18){
+s1=peg$c18;
peg$currPos+=6;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c20);}
+if(peg$silentFails===0){peg$fail(peg$c19);}
}
if(s1!==peg$FAILED){
s2=peg$parse_();
if(s2!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===44){
-s3=peg$c7;
+s3=peg$c6;
peg$currPos++;
}else{
s3=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c8);}
+if(peg$silentFails===0){peg$fail(peg$c7);}
}
if(s3!==peg$FAILED){
s4=peg$parse_();
@@ -50239,7 +49844,7 @@ if(s4!==peg$FAILED){
s5=peg$parsepluralStyle();
if(s5!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c21(s5);
+s1=peg$c20(s5);
s0=s1;
}else{
peg$currPos=s0;
@@ -50269,22 +49874,22 @@ function peg$parseselectOrdinalFormat(){
var s0,s1,s2,s3,s4,s5;
s0=peg$currPos;
-if(input.substr(peg$currPos,13)===peg$c22){
-s1=peg$c22;
+if(input.substr(peg$currPos,13)===peg$c21){
+s1=peg$c21;
peg$currPos+=13;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c23);}
+if(peg$silentFails===0){peg$fail(peg$c22);}
}
if(s1!==peg$FAILED){
s2=peg$parse_();
if(s2!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===44){
-s3=peg$c7;
+s3=peg$c6;
peg$currPos++;
}else{
s3=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c8);}
+if(peg$silentFails===0){peg$fail(peg$c7);}
}
if(s3!==peg$FAILED){
s4=peg$parse_();
@@ -50292,7 +49897,7 @@ if(s4!==peg$FAILED){
s5=peg$parsepluralStyle();
if(s5!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c24(s5);
+s1=peg$c23(s5);
s0=s1;
}else{
peg$currPos=s0;
@@ -50322,22 +49927,22 @@ function peg$parseselectFormat(){
var s0,s1,s2,s3,s4,s5,s6;
s0=peg$currPos;
-if(input.substr(peg$currPos,6)===peg$c25){
-s1=peg$c25;
+if(input.substr(peg$currPos,6)===peg$c24){
+s1=peg$c24;
peg$currPos+=6;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c26);}
+if(peg$silentFails===0){peg$fail(peg$c25);}
}
if(s1!==peg$FAILED){
s2=peg$parse_();
if(s2!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===44){
-s3=peg$c7;
+s3=peg$c6;
peg$currPos++;
}else{
s3=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c8);}
+if(peg$silentFails===0){peg$fail(peg$c7);}
}
if(s3!==peg$FAILED){
s4=peg$parse_();
@@ -50354,7 +49959,7 @@ s5=peg$FAILED;
}
if(s5!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c27(s5);
+s1=peg$c26(s5);
s0=s1;
}else{
peg$currPos=s0;
@@ -50386,11 +49991,11 @@ var s0,s1,s2,s3;
s0=peg$currPos;
s1=peg$currPos;
if(input.charCodeAt(peg$currPos)===61){
-s2=peg$c28;
+s2=peg$c27;
peg$currPos++;
}else{
s2=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c29);}
+if(peg$silentFails===0){peg$fail(peg$c28);}
}
if(s2!==peg$FAILED){
s3=peg$parsenumber();
@@ -50418,7 +50023,7 @@ return s0;
}
function peg$parseoptionalFormatPattern(){
-var s0,s1,s2,s3,s4,s5,s6,s7,s8;
+var s0,s1,s2,s3,s4,s5,s6;
s0=peg$currPos;
s1=peg$parse_();
@@ -50428,29 +50033,25 @@ if(s2!==peg$FAILED){
s3=peg$parse_();
if(s3!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===123){
-s4=peg$c5;
+s4=peg$c4;
peg$currPos++;
}else{
s4=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c6);}
+if(peg$silentFails===0){peg$fail(peg$c5);}
}
if(s4!==peg$FAILED){
-s5=peg$parse_();
+s5=peg$parsemessageFormatPattern();
if(s5!==peg$FAILED){
-s6=peg$parsemessageFormatPattern();
-if(s6!==peg$FAILED){
-s7=peg$parse_();
-if(s7!==peg$FAILED){
if(input.charCodeAt(peg$currPos)===125){
-s8=peg$c9;
+s6=peg$c8;
peg$currPos++;
}else{
-s8=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c10);}
+s6=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c9);}
}
-if(s8!==peg$FAILED){
+if(s6!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c30(s2,s6);
+s1=peg$c29(s2,s5);
s0=s1;
}else{
peg$currPos=s0;
@@ -50476,14 +50077,6 @@ s0=peg$FAILED;
peg$currPos=s0;
s0=peg$FAILED;
}
-}else{
-peg$currPos=s0;
-s0=peg$FAILED;
-}
-}else{
-peg$currPos=s0;
-s0=peg$FAILED;
-}
return s0;
}
@@ -50492,12 +50085,12 @@ function peg$parseoffset(){
var s0,s1,s2,s3;
s0=peg$currPos;
-if(input.substr(peg$currPos,7)===peg$c31){
-s1=peg$c31;
+if(input.substr(peg$currPos,7)===peg$c30){
+s1=peg$c30;
peg$currPos+=7;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c32);}
+if(peg$silentFails===0){peg$fail(peg$c31);}
}
if(s1!==peg$FAILED){
s2=peg$parse_();
@@ -50505,7 +50098,7 @@ if(s2!==peg$FAILED){
s3=peg$parsenumber();
if(s3!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c33(s3);
+s1=peg$c32(s3);
s0=s1;
}else{
peg$currPos=s0;
@@ -50546,7 +50139,7 @@ s3=peg$FAILED;
}
if(s3!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c34(s1,s3);
+s1=peg$c33(s1,s3);
s0=s1;
}else{
peg$currPos=s0;
@@ -50569,22 +50162,22 @@ var s0,s1;
peg$silentFails++;
s0=[];
-if(peg$c36.test(input.charAt(peg$currPos))){
+if(peg$c35.test(input.charAt(peg$currPos))){
s1=input.charAt(peg$currPos);
peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c37);}
+if(peg$silentFails===0){peg$fail(peg$c36);}
}
if(s1!==peg$FAILED){
while(s1!==peg$FAILED){
s0.push(s1);
-if(peg$c36.test(input.charAt(peg$currPos))){
+if(peg$c35.test(input.charAt(peg$currPos))){
s1=input.charAt(peg$currPos);
peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c37);}
+if(peg$silentFails===0){peg$fail(peg$c36);}
}
}
}else{
@@ -50593,7 +50186,7 @@ s0=peg$FAILED;
peg$silentFails--;
if(s0===peg$FAILED){
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c35);}
+if(peg$silentFails===0){peg$fail(peg$c34);}
}
return s0;
@@ -50618,7 +50211,7 @@ s0=s1;
peg$silentFails--;
if(s0===peg$FAILED){
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c38);}
+if(peg$silentFails===0){peg$fail(peg$c37);}
}
return s0;
@@ -50627,12 +50220,12 @@ return s0;
function peg$parsedigit(){
var s0;
-if(peg$c39.test(input.charAt(peg$currPos))){
+if(peg$c38.test(input.charAt(peg$currPos))){
s0=input.charAt(peg$currPos);
peg$currPos++;
}else{
s0=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c40);}
+if(peg$silentFails===0){peg$fail(peg$c39);}
}
return s0;
@@ -50641,12 +50234,12 @@ return s0;
function peg$parsehexDigit(){
var s0;
-if(peg$c41.test(input.charAt(peg$currPos))){
+if(peg$c40.test(input.charAt(peg$currPos))){
s0=input.charAt(peg$currPos);
peg$currPos++;
}else{
s0=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c42);}
+if(peg$silentFails===0){peg$fail(peg$c41);}
}
return s0;
@@ -50657,21 +50250,21 @@ var s0,s1,s2,s3,s4,s5;
s0=peg$currPos;
if(input.charCodeAt(peg$currPos)===48){
-s1=peg$c43;
+s1=peg$c42;
peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c44);}
+if(peg$silentFails===0){peg$fail(peg$c43);}
}
if(s1===peg$FAILED){
s1=peg$currPos;
s2=peg$currPos;
-if(peg$c45.test(input.charAt(peg$currPos))){
+if(peg$c44.test(input.charAt(peg$currPos))){
s3=input.charAt(peg$currPos);
peg$currPos++;
}else{
s3=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c46);}
+if(peg$silentFails===0){peg$fail(peg$c45);}
}
if(s3!==peg$FAILED){
s4=[];
@@ -50699,51 +50292,154 @@ s1=s2;
}
if(s1!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c47(s1);
+s1=peg$c46(s1);
}
s0=s1;
return s0;
}
-function peg$parsechar(){
-var s0,s1,s2,s3,s4,s5,s6,s7;
+function peg$parsequoteEscapedChar(){
+var s0,s1,s2;
-if(peg$c48.test(input.charAt(peg$currPos))){
-s0=input.charAt(peg$currPos);
+s0=peg$currPos;
+s1=peg$currPos;
+peg$silentFails++;
+if(input.charCodeAt(peg$currPos)===39){
+s2=peg$c47;
+peg$currPos++;
+}else{
+s2=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c48);}
+}
+if(s2===peg$FAILED){
+if(peg$c49.test(input.charAt(peg$currPos))){
+s2=input.charAt(peg$currPos);
peg$currPos++;
}else{
+s2=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c50);}
+}
+}
+peg$silentFails--;
+if(s2===peg$FAILED){
+s1=void 0;
+}else{
+peg$currPos=s1;
+s1=peg$FAILED;
+}
+if(s1!==peg$FAILED){
+if(input.length>peg$currPos){
+s2=input.charAt(peg$currPos);
+peg$currPos++;
+}else{
+s2=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c51);}
+}
+if(s2!==peg$FAILED){
+peg$savedPos=s0;
+s1=peg$c52(s2);
+s0=s1;
+}else{
+peg$currPos=s0;
+s0=peg$FAILED;
+}
+}else{
+peg$currPos=s0;
s0=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c49);}
}
if(s0===peg$FAILED){
s0=peg$currPos;
-if(input.substr(peg$currPos,2)===peg$c50){
-s1=peg$c50;
-peg$currPos+=2;
+if(input.charCodeAt(peg$currPos)===39){
+s1=peg$c47;
+peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c51);}
+if(peg$silentFails===0){peg$fail(peg$c48);}
}
if(s1!==peg$FAILED){
+s2=peg$parseescape();
+if(s2!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c52();
-}
+s1=peg$c53(s2);
s0=s1;
+}else{
+peg$currPos=s0;
+s0=peg$FAILED;
+}
+}else{
+peg$currPos=s0;
+s0=peg$FAILED;
+}
+}
+
+return s0;
+}
+
+function peg$parseapostrophe(){
+var s0;
+
+if(input.charCodeAt(peg$currPos)===39){
+s0=peg$c47;
+peg$currPos++;
+}else{
+s0=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c48);}
+}
+
+return s0;
+}
+
+function peg$parseescape(){
+var s0;
+
+if(peg$c49.test(input.charAt(peg$currPos))){
+s0=input.charAt(peg$currPos);
+peg$currPos++;
+}else{
+s0=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c50);}
+}
if(s0===peg$FAILED){
+s0=peg$parseapostrophe();
+}
+
+return s0;
+}
+
+function peg$parsechar(){
+var s0,s1,s2,s3,s4,s5,s6,s7;
+
s0=peg$currPos;
-if(input.substr(peg$currPos,2)===peg$c53){
-s1=peg$c53;
-peg$currPos+=2;
+if(input.charCodeAt(peg$currPos)===39){
+s1=peg$c47;
+peg$currPos++;
}else{
s1=peg$FAILED;
-if(peg$silentFails===0){peg$fail(peg$c54);}
+if(peg$silentFails===0){peg$fail(peg$c48);}
}
if(s1!==peg$FAILED){
+s2=peg$parseapostrophe();
+if(s2!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c55();
-}
+s1=peg$c53(s2);
s0=s1;
+}else{
+peg$currPos=s0;
+s0=peg$FAILED;
+}
+}else{
+peg$currPos=s0;
+s0=peg$FAILED;
+}
+if(s0===peg$FAILED){
+if(peg$c54.test(input.charAt(peg$currPos))){
+s0=input.charAt(peg$currPos);
+peg$currPos++;
+}else{
+s0=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c55);}
+}
if(s0===peg$FAILED){
s0=peg$currPos;
if(input.substr(peg$currPos,2)===peg$c56){
@@ -50782,6 +50478,34 @@ s1=peg$FAILED;
if(peg$silentFails===0){peg$fail(peg$c63);}
}
if(s1!==peg$FAILED){
+peg$savedPos=s0;
+s1=peg$c64();
+}
+s0=s1;
+if(s0===peg$FAILED){
+s0=peg$currPos;
+if(input.substr(peg$currPos,2)===peg$c65){
+s1=peg$c65;
+peg$currPos+=2;
+}else{
+s1=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c66);}
+}
+if(s1!==peg$FAILED){
+peg$savedPos=s0;
+s1=peg$c67();
+}
+s0=s1;
+if(s0===peg$FAILED){
+s0=peg$currPos;
+if(input.substr(peg$currPos,2)===peg$c68){
+s1=peg$c68;
+peg$currPos+=2;
+}else{
+s1=peg$FAILED;
+if(peg$silentFails===0){peg$fail(peg$c69);}
+}
+if(s1!==peg$FAILED){
s2=peg$currPos;
s3=peg$currPos;
s4=peg$parsehexDigit();
@@ -50817,7 +50541,7 @@ s2=s3;
}
if(s2!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c64(s2);
+s1=peg$c70(s2);
s0=s1;
}else{
peg$currPos=s0;
@@ -50832,6 +50556,7 @@ s0=peg$FAILED;
}
}
}
+}
return s0;
}
@@ -50852,7 +50577,7 @@ s1=peg$FAILED;
}
if(s1!==peg$FAILED){
peg$savedPos=s0;
-s1=peg$c65(s1);
+s1=peg$c3(s1);
}
s0=s1;
@@ -50865,11 +50590,10 @@ if(peg$result!==peg$FAILED&&peg$currPos===input.length){
return peg$result;
}else{
if(peg$result!==peg$FAILED&&peg$currPos<input.length){
-peg$fail({type:"end",description:"end of input"});
+peg$fail(peg$endExpectation());
}
-throw peg$buildException(
-null,
+throw peg$buildStructuredError(
peg$maxFailExpected,
peg$maxFailPos<input.length?input.charAt(peg$maxFailPos):null,
peg$maxFailPos<input.length?
@@ -50879,86 +50603,73 @@ peg$computeLocation(peg$maxFailPos,peg$maxFailPos));
}
}
-return{
+module.exports={
SyntaxError:peg$SyntaxError,
parse:peg$parse};
-}();
-
},{}],116:[function(require,module,exports){
-
-
-'use strict';
-
-var IntlMessageFormat=require('./lib/main')['default'];
-
-
-
-require('./lib/locales');
-
-
-
-
-exports=module.exports=IntlMessageFormat;
-exports['default']=exports;
-
-},{"./lib/locales":98,"./lib/main":121}],117:[function(require,module,exports){
-
-
-
+"use strict";
-"use strict";
-exports["default"]=Compiler;
+var __extends=this&&this.__extends||function(){
+var extendStatics=function(d,b){
+extendStatics=Object.setPrototypeOf||
+{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b;}||
+function(d,b){for(var p in b)if(b.hasOwnProperty(p))d[p]=b[p];};
+return extendStatics(d,b);
+};
+return function(d,b){
+extendStatics(d,b);
+function __(){this.constructor=d;}
+d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __());
+};
+}();
+Object.defineProperty(exports,"__esModule",{value:true});
+var Compiler=function(){
+function Compiler(locales,formats,formatters){
+this.locales=[];
+this.formats={
+number:{},
+date:{},
+time:{}};
-function Compiler(locales,formats,pluralFn){
+this.pluralNumberFormat=null;
+this.currentPlural=null;
+this.pluralStack=[];
this.locales=locales;
this.formats=formats;
-this.pluralFn=pluralFn;
+this.formatters=formatters;
}
-
Compiler.prototype.compile=function(ast){
this.pluralStack=[];
this.currentPlural=null;
this.pluralNumberFormat=null;
-
return this.compileMessage(ast);
};
-
Compiler.prototype.compileMessage=function(ast){
+var _this=this;
if(!(ast&&ast.type==='messageFormatPattern')){
throw new Error('Message AST is not of type: "messageFormatPattern"');
}
-
-var elements=ast.elements,
-pattern=[];
-
-var i,len,element;
-
-for(i=0,len=elements.length;i<len;i+=1){
-element=elements[i];
-
-switch(element.type){
-case'messageTextElement':
-pattern.push(this.compileMessageText(element));
-break;
-
-case'argumentElement':
-pattern.push(this.compileArgument(element));
-break;
-
-default:
-throw new Error('Message element does not have a valid type');}
-
+var elements=ast.elements;
+var pattern=elements.
+filter(function(el){
+return el.type==='messageTextElement'||el.type==='argumentElement';
+}).
+map(function(el){
+return el.type==='messageTextElement'?
+_this.compileMessageText(el):
+_this.compileArgument(el);
+});
+if(pattern.length!==elements.length){
+throw new Error('Message element does not have a valid type');
}
-
return pattern;
};
-
Compiler.prototype.compileMessageText=function(element){
@@ -50969,531 +50680,412 @@ if(this.currentPlural&&/(^|[^\\])#/g.test(element.value)){
if(!this.pluralNumberFormat){
this.pluralNumberFormat=new Intl.NumberFormat(this.locales);
}
-
-return new PluralOffsetString(
-this.currentPlural.id,
-this.currentPlural.format.offset,
-this.pluralNumberFormat,
-element.value);
+return new PluralOffsetString(this.currentPlural.id,this.currentPlural.format.offset,this.pluralNumberFormat,element.value);
}
-
return element.value.replace(/\\#/g,'#');
};
-
Compiler.prototype.compileArgument=function(element){
-var format=element.format;
-
+var format=element.format,id=element.id;
+var formatters=this.formatters;
if(!format){
-return new StringFormat(element.id);
+return new StringFormat(id);
}
-
-var formats=this.formats,
-locales=this.locales,
-pluralFn=this.pluralFn,
-options;
-
+var _a=this,formats=_a.formats,locales=_a.locales;
switch(format.type){
case'numberFormat':
-options=formats.number[format.style];
return{
-id:element.id,
-format:new Intl.NumberFormat(locales,options).format};
-
+id:id,
+format:formatters.getNumberFormat(locales,formats.number[format.style]).format};
case'dateFormat':
-options=formats.date[format.style];
return{
-id:element.id,
-format:new Intl.DateTimeFormat(locales,options).format};
-
+id:id,
+format:formatters.getDateTimeFormat(locales,formats.date[format.style]).format};
case'timeFormat':
-options=formats.time[format.style];
return{
-id:element.id,
-format:new Intl.DateTimeFormat(locales,options).format};
-
+id:id,
+format:formatters.getDateTimeFormat(locales,formats.time[format.style]).format};
case'pluralFormat':
-options=this.compileOptions(element);
-return new PluralFormat(
-element.id,format.ordinal,format.offset,options,pluralFn);
-
+return new PluralFormat(id,format.offset,this.compileOptions(element),formatters.getPluralRules(locales,{
+type:format.ordinal?'ordinal':'cardinal'}));
case'selectFormat':
-options=this.compileOptions(element);
-return new SelectFormat(element.id,options);
-
+return new SelectFormat(id,this.compileOptions(element));
default:
throw new Error('Message element does not have a valid format type');}
};
-
Compiler.prototype.compileOptions=function(element){
-var format=element.format,
-options=format.options,
-optionsHash={};
-
+var _this=this;
+var format=element.format;
+var options=format.options;
this.pluralStack.push(this.currentPlural);
this.currentPlural=format.type==='pluralFormat'?element:null;
+var optionsHash=options.reduce(function(all,option){
-var i,len,option;
-
-for(i=0,len=options.length;i<len;i+=1){
-option=options[i];
-
-
-optionsHash[option.selector]=this.compileMessage(option.value);
-}
-
+all[option.selector]=_this.compileMessage(option.value);
+return all;
+},{});
this.currentPlural=this.pluralStack.pop();
-
return optionsHash;
};
+return Compiler;
+}();
+exports.default=Compiler;
-
-
-function StringFormat(id){
+var Formatter=function(){
+function Formatter(id){
this.id=id;
}
-
+return Formatter;
+}();
+var StringFormat=function(_super){
+__extends(StringFormat,_super);
+function StringFormat(){
+return _super!==null&&_super.apply(this,arguments)||this;
+}
StringFormat.prototype.format=function(value){
if(!value&&typeof value!=='number'){
return'';
}
-
return typeof value==='string'?value:String(value);
};
-
-function PluralFormat(id,useOrdinal,offset,options,pluralFn){
+return StringFormat;
+}(Formatter);
+var PluralFormat=function(){
+function PluralFormat(id,offset,options,pluralRules){
this.id=id;
-this.useOrdinal=useOrdinal;
this.offset=offset;
this.options=options;
-this.pluralFn=pluralFn;
+this.pluralRules=pluralRules;
}
-
PluralFormat.prototype.getOption=function(value){
var options=this.options;
-
var option=options['='+value]||
-options[this.pluralFn(value-this.offset,this.useOrdinal)];
-
+options[this.pluralRules.select(value-this.offset)];
return option||options.other;
};
-
+return PluralFormat;
+}();
+var PluralOffsetString=function(_super){
+__extends(PluralOffsetString,_super);
function PluralOffsetString(id,offset,numberFormat,string){
-this.id=id;
-this.offset=offset;
-this.numberFormat=numberFormat;
-this.string=string;
+var _this=_super.call(this,id)||this;
+_this.offset=offset;
+_this.numberFormat=numberFormat;
+_this.string=string;
+return _this;
}
-
PluralOffsetString.prototype.format=function(value){
var number=this.numberFormat.format(value-this.offset);
-
return this.string.
replace(/(^|[^\\])#/g,'$1'+number).
replace(/\\#/g,'#');
};
-
+return PluralOffsetString;
+}(Formatter);
+exports.PluralOffsetString=PluralOffsetString;
+var SelectFormat=function(){
function SelectFormat(id,options){
this.id=id;
this.options=options;
}
-
SelectFormat.prototype.getOption=function(value){
var options=this.options;
return options[value]||options.other;
};
+return SelectFormat;
+}();
+exports.SelectFormat=SelectFormat;
+function isSelectOrPluralFormat(f){
+return!!f.options;
+}
+exports.isSelectOrPluralFormat=isSelectOrPluralFormat;
-
-},{}],118:[function(require,module,exports){
-
-
+},{}],117:[function(require,module,exports){
+"use strict";
+var __extends=this&&this.__extends||function(){
+var extendStatics=function(d,b){
+extendStatics=Object.setPrototypeOf||
+{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b;}||
+function(d,b){for(var p in b)if(b.hasOwnProperty(p))d[p]=b[p];};
+return extendStatics(d,b);
+};
+return function(d,b){
+extendStatics(d,b);
+function __(){this.constructor=d;}
+d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __());
+};
+}();
+var __assign=this&&this.__assign||function(){
+__assign=Object.assign||function(t){
+for(var s,i=1,n=arguments.length;i<n;i++){
+s=arguments[i];
+for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))
+t[p]=s[p];
+}
+return t;
+};
+return __assign.apply(this,arguments);
+};
+Object.defineProperty(exports,"__esModule",{value:true});
-"use strict";
-var src$utils$$=require("./utils"),src$es5$$=require("./es5"),src$compiler$$=require("./compiler"),intl$messageformat$parser$$=require("intl-messageformat-parser");
-exports["default"]=MessageFormat;
+var compiler_1=require("./compiler");
+function resolveLocale(locales){
+if(typeof locales==='string'){
+locales=[locales];
+}
+try{
+return Intl.NumberFormat.supportedLocalesOf(locales,{
-function MessageFormat(message,locales,formats){
+localeMatcher:'best fit'})[
+0];
+}
+catch(e){
+return IntlMessageFormat.defaultLocale;
+}
+}
+function formatPatterns(pattern,values){
+var result='';
+for(var _i=0,pattern_1=pattern;_i<pattern_1.length;_i++){
+var part=pattern_1[_i];
-var ast=typeof message==='string'?
-MessageFormat.__parse(message):message;
+if(typeof part==='string'){
+result+=part;
+continue;
+}
+var id=part.id;
-if(!(ast&&ast.type==='messageFormatPattern')){
-throw new TypeError('A message must be provided as a String or AST.');
+if(!(values&&id in values)){
+throw new FormatError("A value must be provided for: "+id,id);
}
+var value=values[id];
-formats=this._mergeFormats(MessageFormat.formats,formats);
+if(compiler_1.isSelectOrPluralFormat(part)){
+result+=formatPatterns(part.getOption(value),values);
+}else
+{
+result+=part.format(value);
+}
+}
+return result;
+}
+function mergeConfig(c1,c2){
+if(!c2){
+return c1;
+}
+return __assign({},c1||{},c2||{},Object.keys(c1).reduce(function(all,k){
+all[k]=__assign({},c1[k],c2[k]||{});
+return all;
+},{}));
+}
+function mergeConfigs(defaultConfig,configs){
+if(!configs){
+return defaultConfig;
+}
+return Object.keys(defaultConfig).reduce(function(all,k){
+all[k]=mergeConfig(defaultConfig[k],configs[k]);
+return all;
+},__assign({},defaultConfig));
+}
+var FormatError=function(_super){
+__extends(FormatError,_super);
+function FormatError(msg,variableId){
+var _this=_super.call(this,msg)||this;
+_this.variableId=variableId;
+return _this;
+}
+return FormatError;
+}(Error);
+function createDefaultFormatters(){
+return{
+getNumberFormat:function(){
+var _a;
+var args=[];
+for(var _i=0;_i<arguments.length;_i++){
+args[_i]=arguments[_i];
+}
+return new((_a=Intl.NumberFormat).bind.apply(_a,[void 0].concat(args)))();
+},
+getDateTimeFormat:function(){
+var _a;
+var args=[];
+for(var _i=0;_i<arguments.length;_i++){
+args[_i]=arguments[_i];
+}
+return new((_a=Intl.DateTimeFormat).bind.apply(_a,[void 0].concat(args)))();
+},
+getPluralRules:function(){
+var _a;
+var args=[];
+for(var _i=0;_i<arguments.length;_i++){
+args[_i]=arguments[_i];
+}
+return new((_a=Intl.PluralRules).bind.apply(_a,[void 0].concat(args)))();
+}};
+}
+exports.createDefaultFormatters=createDefaultFormatters;
+var IntlMessageFormat=function(){
+function IntlMessageFormat(message,locales,overrideFormats,opts){
+var _this=this;
+if(locales===void 0){locales=IntlMessageFormat.defaultLocale;}
+this.format=function(values){
+try{
+return formatPatterns(_this.pattern,values);
+}
+catch(e){
+if(e.variableId){
+throw new Error("The intl string context variable '"+e.variableId+"' was not provided to the string '"+_this.message+"'");
+}else
+{
+throw e;
+}
+}
+};
+if(typeof message==='string'){
+if(!IntlMessageFormat.__parse){
+throw new TypeError('IntlMessageFormat.__parse must be set to process `message` of type `string`');
+}
-src$es5$$.defineProperty(this,'_locale',{value:this._resolveLocale(locales)});
+this.ast=IntlMessageFormat.__parse(message);
+}else
+{
+this.ast=message;
+}
+this.message=message;
+if(!(this.ast&&this.ast.type==='messageFormatPattern')){
+throw new TypeError('A message must be provided as a String or AST.');
+}
+var formats=mergeConfigs(IntlMessageFormat.formats,overrideFormats);
+this.locale=resolveLocale(locales||[]);
+var formatters=opts&&opts.formatters||createDefaultFormatters();
-var pluralFn=this._findPluralRuleFunction(this._locale);
-var pattern=this._compilePattern(ast,locales,formats,pluralFn);
+this.pattern=new compiler_1.default(locales,formats,formatters).compile(this.ast);
-var messageFormat=this;
-this.format=function(values){
-try{
-return messageFormat._format(pattern,values);
-}catch(e){
-if(e.variableId){
-throw new Error(
-'The intl string context variable \''+e.variableId+'\''+
-' was not provided to the string \''+message+'\'');
-}else{
-throw e;
-}
}
+IntlMessageFormat.prototype.resolvedOptions=function(){
+return{locale:this.locale};
};
-}
-
-
+IntlMessageFormat.prototype.getAst=function(){
+return this.ast;
+};
+IntlMessageFormat.defaultLocale='en';
+IntlMessageFormat.__parse=undefined;
-src$es5$$.defineProperty(MessageFormat,'formats',{
-enumerable:true,
-value:{
+IntlMessageFormat.formats={
number:{
-'currency':{
+currency:{
style:'currency'},
-
-'percent':{
+percent:{
style:'percent'}},
-
date:{
-'short':{
+short:{
month:'numeric',
day:'numeric',
year:'2-digit'},
-
-'medium':{
+medium:{
month:'short',
day:'numeric',
year:'numeric'},
-
-'long':{
+long:{
month:'long',
day:'numeric',
year:'numeric'},
-
-'full':{
+full:{
weekday:'long',
month:'long',
day:'numeric',
year:'numeric'}},
-
time:{
-'short':{
+short:{
hour:'numeric',
minute:'numeric'},
-
-'medium':{
+medium:{
hour:'numeric',
minute:'numeric',
second:'numeric'},
-
-'long':{
+long:{
hour:'numeric',
minute:'numeric',
second:'numeric',
timeZoneName:'short'},
-
-'full':{
+full:{
hour:'numeric',
minute:'numeric',
second:'numeric',
-timeZoneName:'short'}}}});
-
-
-
-
-
-
-src$es5$$.defineProperty(MessageFormat,'__localeData__',{value:src$es5$$.objCreate(null)});
-src$es5$$.defineProperty(MessageFormat,'__addLocaleData',{value:function(data){
-if(!(data&&data.locale)){
-throw new Error(
-'Locale data provided to IntlMessageFormat is missing a '+
-'`locale` property');
-
-}
-
-MessageFormat.__localeData__[data.locale.toLowerCase()]=data;
-}});
-
-
-src$es5$$.defineProperty(MessageFormat,'__parse',{value:intl$messageformat$parser$$["default"].parse});
-
-
-
-src$es5$$.defineProperty(MessageFormat,'defaultLocale',{
-enumerable:true,
-writable:true,
-value:undefined});
-
-
-MessageFormat.prototype.resolvedOptions=function(){
-
-return{
-locale:this._locale};
-
-};
-
-MessageFormat.prototype._compilePattern=function(ast,locales,formats,pluralFn){
-var compiler=new src$compiler$$["default"](locales,formats,pluralFn);
-return compiler.compile(ast);
-};
-
-MessageFormat.prototype._findPluralRuleFunction=function(locale){
-var localeData=MessageFormat.__localeData__;
-var data=localeData[locale.toLowerCase()];
-
-
-
-while(data){
-if(data.pluralRuleFunction){
-return data.pluralRuleFunction;
-}
-
-data=data.parentLocale&&localeData[data.parentLocale.toLowerCase()];
-}
-
-throw new Error(
-'Locale data added to IntlMessageFormat is missing a '+
-'`pluralRuleFunction` for :'+locale);
-
-};
-
-MessageFormat.prototype._format=function(pattern,values){
-var result='',
-i,len,part,id,value,err;
-
-for(i=0,len=pattern.length;i<len;i+=1){
-part=pattern[i];
-
-
-if(typeof part==='string'){
-result+=part;
-continue;
-}
-
-id=part.id;
-
-
-if(!(values&&src$utils$$.hop.call(values,id))){
-err=new Error('A value must be provided for: '+id);
-err.variableId=id;
-throw err;
-}
-
-value=values[id];
-
-
-
-
-if(part.options){
-result+=this._format(part.getOption(value),values);
-}else{
-result+=part.format(value);
-}
-}
-
-return result;
-};
-
-MessageFormat.prototype._mergeFormats=function(defaults,formats){
-var mergedFormats={},
-type,mergedType;
+timeZoneName:'short'}}};
-for(type in defaults){
-if(!src$utils$$.hop.call(defaults,type)){continue;}
-mergedFormats[type]=mergedType=src$es5$$.objCreate(defaults[type]);
-if(formats&&src$utils$$.hop.call(formats,type)){
-src$utils$$.extend(mergedType,formats[type]);
-}
-}
-
-return mergedFormats;
-};
-
-MessageFormat.prototype._resolveLocale=function(locales){
-if(typeof locales==='string'){
-locales=[locales];
-}
-
-
-locales=(locales||[]).concat(MessageFormat.defaultLocale);
-
-var localeData=MessageFormat.__localeData__;
-var i,len,localeParts,data;
-
-
-
-
-
-
-for(i=0,len=locales.length;i<len;i+=1){
-localeParts=locales[i].toLowerCase().split('-');
-
-while(localeParts.length){
-data=localeData[localeParts.join('-')];
-if(data){
-
-
-return data.locale;
-}
-
-localeParts.pop();
-}
-}
-
-var defaultLocale=locales.pop();
-throw new Error(
-'No locale data has been added to IntlMessageFormat for: '+
-locales.join(', ')+', or the default locale: '+defaultLocale);
-
-};
-
-
-},{"./compiler":117,"./es5":120,"./utils":122,"intl-messageformat-parser":114}],119:[function(require,module,exports){
-
-"use strict";
-exports["default"]={"locale":"en","pluralRuleFunction":function(n,ord){var s=String(n).split("."),v0=!s[1],t0=Number(s[0])==n,n10=t0&&s[0].slice(-1),n100=t0&&s[0].slice(-2);if(ord)return n10==1&&n100!=11?"one":n10==2&&n100!=12?"two":n10==3&&n100!=13?"few":"other";return n==1&&v0?"one":"other";}};
-
-
-},{}],120:[function(require,module,exports){
-
-
-
-
-
-
-
-
-"use strict";
-var src$utils$$=require("./utils");
-
-
-
-
-var realDefineProp=function(){
-try{return!!Object.defineProperty({},'a',{});}
-catch(e){return false;}
+return IntlMessageFormat;
}();
+exports.IntlMessageFormat=IntlMessageFormat;
+exports.default=IntlMessageFormat;
-var es3=!realDefineProp&&!Object.prototype.__defineGetter__;
-
-var defineProperty=realDefineProp?Object.defineProperty:
-function(obj,name,desc){
-
-if('get'in desc&&obj.__defineGetter__){
-obj.__defineGetter__(name,desc.get);
-}else if(!src$utils$$.hop.call(obj,name)||'value'in desc){
-obj[name]=desc.value;
-}
-};
-
-var objCreate=Object.create||function(proto,props){
-var obj,k;
-
-function F(){}
-F.prototype=proto;
-obj=new F();
-
-for(k in props){
-if(src$utils$$.hop.call(props,k)){
-defineProperty(obj,k,props[k]);
-}
-}
-
-return obj;
-};
-
-exports.defineProperty=defineProperty,exports.objCreate=objCreate;
-
-
-},{"./utils":122}],121:[function(require,module,exports){
-
-
+},{"./compiler":116}],118:[function(require,module,exports){
"use strict";
-var src$core$$=require("./core"),src$en$$=require("./en");
-
-src$core$$["default"].__addLocaleData(src$en$$["default"]);
-src$core$$["default"].defaultLocale='en';
-
-exports["default"]=src$core$$["default"];
-
-
-},{"./core":118,"./en":119}],122:[function(require,module,exports){
+function __export(m){
+for(var p in m)if(!exports.hasOwnProperty(p))exports[p]=m[p];
+}
+Object.defineProperty(exports,"__esModule",{value:true});
+var intl_messageformat_parser_1=require("intl-messageformat-parser");
+var core_1=require("./core");
+core_1.default.__parse=intl_messageformat_parser_1.default.parse;
+__export(require("./core"));
+exports.default=core_1.default;
+},{"./core":117,"intl-messageformat-parser":114}],119:[function(require,module,exports){
+'use strict';
+var IntlMessageFormat=require('./dist').default;
-"use strict";
-exports.extend=extend;
-var hop=Object.prototype.hasOwnProperty;
-
-function extend(obj){
-var sources=Array.prototype.slice.call(arguments,1),
-i,len,source,key;
-
-for(i=0,len=sources.length;i<len;i+=1){
-source=sources[i];
-if(!source){continue;}
-
-for(key in source){
-if(hop.call(source,key)){
-obj[key]=source[key];
-}
-}
-}
-return obj;
-}
-exports.hop=hop;
+exports=module.exports=IntlMessageFormat;
+exports['default']=exports;
-},{}],123:[function(require,module,exports){
+},{"./dist":118}],120:[function(require,module,exports){
@@ -51516,14 +51108,14 @@ function isSlowBuffer(obj){
return typeof obj.readFloatLE==='function'&&typeof obj.slice==='function'&&isBuffer(obj.slice(0,0));
}
-},{}],124:[function(require,module,exports){
+},{}],121:[function(require,module,exports){
var toString={}.toString;
module.exports=Array.isArray||function(arr){
return toString.call(arr)=='[object Array]';
};
-},{}],125:[function(require,module,exports){
+},{}],122:[function(require,module,exports){
var encode=require('./lib/encoder'),
decode=require('./lib/decoder');
@@ -51532,7 +51124,7 @@ encode:encode,
decode:decode};
-},{"./lib/decoder":126,"./lib/encoder":127}],126:[function(require,module,exports){
+},{"./lib/decoder":123,"./lib/encoder":124}],123:[function(require,module,exports){
(function(Buffer){
@@ -52522,7 +52114,7 @@ return image;
}
}).call(this,require("buffer").Buffer);
-},{"buffer":102}],127:[function(require,module,exports){
+},{"buffer":102}],124:[function(require,module,exports){
(function(Buffer){
@@ -53292,7 +52884,7 @@ return ctx.getImageData(0,0,cvs.width,cvs.height);
}
}).call(this,require("buffer").Buffer);
-},{"buffer":102}],128:[function(require,module,exports){
+},{"buffer":102}],125:[function(require,module,exports){
(function(process){
@@ -53537,7 +53129,7 @@ Log.getTimeEntries=()=>marky.getEntries();
module.exports=Log;
}).call(this,require('_process'));
-},{"_process":145,"debug":106,"events":108,"marky":131}],129:[function(require,module,exports){
+},{"_process":142,"debug":106,"events":108,"marky":128}],126:[function(require,module,exports){
(function(global){
@@ -55389,7 +54981,7 @@ return false;
module.exports=isEqual;
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{}],130:[function(require,module,exports){
+},{}],127:[function(require,module,exports){
@@ -55406,7 +54998,7 @@ current.pop();
}
};
-},{}],131:[function(require,module,exports){
+},{}],128:[function(require,module,exports){
'use strict';
Object.defineProperty(exports,'__esModule',{value:true});
@@ -55486,7 +55078,7 @@ exports.getEntries=function(){return entries;};
exports.clear=function(){entries=[];};
}
-},{}],132:[function(require,module,exports){
+},{}],129:[function(require,module,exports){
exports.getRenderingDataFromViewport=function(viewportProperties,uaDeviceWidth,uaDeviceHeight,uaMaxZoom,uaMinZoom){
var vw=uaDeviceWidth/100;
@@ -55829,7 +55421,7 @@ exports.expectedValues={
"viewport-fit":["auto","cover"]};
-},{}],133:[function(require,module,exports){
+},{}],130:[function(require,module,exports){
@@ -55983,7 +55575,7 @@ return Math.floor(ms/n)+' '+name;
return Math.ceil(ms/n)+' '+name+'s';
}
-},{}],134:[function(require,module,exports){
+},{}],131:[function(require,module,exports){
'use strict';
@@ -56090,7 +55682,7 @@ exports.assign(exports,fnUntyped);
exports.setTyped(TYPED_OK);
-},{}],135:[function(require,module,exports){
+},{}],132:[function(require,module,exports){
'use strict';
@@ -56143,7 +55735,7 @@ return s1|s2<<16|0;
module.exports=adler32;
-},{}],136:[function(require,module,exports){
+},{}],133:[function(require,module,exports){
'use strict';
@@ -56213,7 +55805,7 @@ Z_DEFLATED:8};
-},{}],137:[function(require,module,exports){
+},{}],134:[function(require,module,exports){
'use strict';
@@ -56274,7 +55866,7 @@ return crc^-1;
module.exports=crc32;
-},{}],138:[function(require,module,exports){
+},{}],135:[function(require,module,exports){
'use strict';
@@ -58150,7 +57742,7 @@ exports.deflateInfo='pako deflate (from Nodeca project)';
-},{"../utils/common":134,"./adler32":135,"./crc32":137,"./messages":139,"./trees":140}],139:[function(require,module,exports){
+},{"../utils/common":131,"./adler32":132,"./crc32":134,"./messages":136,"./trees":137}],136:[function(require,module,exports){
'use strict';
@@ -58184,7 +57776,7 @@ module.exports={
'-6':'incompatible version'};
-},{}],140:[function(require,module,exports){
+},{}],137:[function(require,module,exports){
'use strict';
@@ -59408,7 +59000,7 @@ exports._tr_flush_block=_tr_flush_block;
exports._tr_tally=_tr_tally;
exports._tr_align=_tr_align;
-},{"../utils/common":134}],141:[function(require,module,exports){
+},{"../utils/common":131}],138:[function(require,module,exports){
'use strict';
@@ -59457,7 +59049,7 @@ this.adler=0;
module.exports=ZStream;
-},{}],142:[function(require,module,exports){
+},{}],139:[function(require,module,exports){
module.exports=function parseCacheControl(field){
if(typeof field!=='string'){
@@ -59496,7 +59088,7 @@ catch(err){}
return err?null:header;
};
-},{}],143:[function(require,module,exports){
+},{}],140:[function(require,module,exports){
(function(process){
@@ -59802,7 +59394,7 @@ return str.substr(start,len);
}).call(this,require('_process'));
-},{"_process":145}],144:[function(require,module,exports){
+},{"_process":142}],141:[function(require,module,exports){
(function(process){
'use strict';
@@ -59850,7 +59442,7 @@ fn.apply(null,args);
}).call(this,require('_process'));
-},{"_process":145}],145:[function(require,module,exports){
+},{"_process":142}],142:[function(require,module,exports){
var process=module.exports={};
@@ -60036,7 +59628,7 @@ throw new Error('process.chdir is not supported');
};
process.umask=function(){return 0;};
-},{}],146:[function(require,module,exports){
+},{}],143:[function(require,module,exports){
@@ -60122,7 +59714,7 @@ var isArray=Array.isArray||function(xs){
return Object.prototype.toString.call(xs)==='[object Array]';
};
-},{}],147:[function(require,module,exports){
+},{}],144:[function(require,module,exports){
@@ -60209,16 +59801,16 @@ if(Object.prototype.hasOwnProperty.call(obj,key))res.push(key);
return res;
};
-},{}],148:[function(require,module,exports){
+},{}],145:[function(require,module,exports){
'use strict';
exports.decode=exports.parse=require('./decode');
exports.encode=exports.stringify=require('./encode');
-},{"./decode":146,"./encode":147}],149:[function(require,module,exports){
+},{"./decode":143,"./encode":144}],146:[function(require,module,exports){
module.exports=require('./lib/_stream_duplex.js');
-},{"./lib/_stream_duplex.js":150}],150:[function(require,module,exports){
+},{"./lib/_stream_duplex.js":147}],147:[function(require,module,exports){
@@ -60350,7 +59942,7 @@ this.end();
pna.nextTick(cb,err);
};
-},{"./_stream_readable":152,"./_stream_writable":154,"core-util-is":103,"inherits":113,"process-nextick-args":144}],151:[function(require,module,exports){
+},{"./_stream_readable":149,"./_stream_writable":151,"core-util-is":103,"inherits":113,"process-nextick-args":141}],148:[function(require,module,exports){
@@ -60398,7 +59990,7 @@ Transform.call(this,options);
PassThrough.prototype._transform=function(chunk,encoding,cb){
cb(null,chunk);
};
-},{"./_stream_transform":153,"core-util-is":103,"inherits":113}],152:[function(require,module,exports){
+},{"./_stream_transform":150,"core-util-is":103,"inherits":113}],149:[function(require,module,exports){
(function(process,global){
@@ -61420,7 +61012,7 @@ if(xs[i]===x)return i;
return-1;
}
}).call(this,require('_process'),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{"./_stream_duplex":150,"./internal/streams/BufferList":155,"./internal/streams/destroy":156,"./internal/streams/stream":157,"_process":145,"core-util-is":103,"events":108,"inherits":113,"isarray":124,"process-nextick-args":144,"safe-buffer":165,"string_decoder/":158,"util":98}],153:[function(require,module,exports){
+},{"./_stream_duplex":147,"./internal/streams/BufferList":152,"./internal/streams/destroy":153,"./internal/streams/stream":154,"_process":142,"core-util-is":103,"events":108,"inherits":113,"isarray":121,"process-nextick-args":141,"safe-buffer":162,"string_decoder/":155,"util":98}],150:[function(require,module,exports){
@@ -61635,7 +61227,7 @@ if(stream._transformState.transforming)throw new Error('Calling transform done w
return stream.push(null);
}
-},{"./_stream_duplex":150,"core-util-is":103,"inherits":113}],154:[function(require,module,exports){
+},{"./_stream_duplex":147,"core-util-is":103,"inherits":113}],151:[function(require,module,exports){
(function(process,global,setImmediate){
@@ -62325,7 +61917,7 @@ this.end();
cb(err);
};
}).call(this,require('_process'),typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{},require("timers").setImmediate);
-},{"./_stream_duplex":150,"./internal/streams/destroy":156,"./internal/streams/stream":157,"_process":145,"core-util-is":103,"inherits":113,"process-nextick-args":144,"safe-buffer":165,"timers":175,"util-deprecate":176}],155:[function(require,module,exports){
+},{"./_stream_duplex":147,"./internal/streams/destroy":153,"./internal/streams/stream":154,"_process":142,"core-util-is":103,"inherits":113,"process-nextick-args":141,"safe-buffer":162,"timers":172,"util-deprecate":173}],152:[function(require,module,exports){
'use strict';
function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}
@@ -62405,7 +61997,7 @@ var obj=util.inspect({length:this.length});
return this.constructor.name+' '+obj;
};
}
-},{"safe-buffer":165,"util":98}],156:[function(require,module,exports){
+},{"safe-buffer":162,"util":98}],153:[function(require,module,exports){
'use strict';
@@ -62480,10 +62072,10 @@ module.exports={
destroy:destroy,
undestroy:undestroy};
-},{"process-nextick-args":144}],157:[function(require,module,exports){
+},{"process-nextick-args":141}],154:[function(require,module,exports){
module.exports=require('events').EventEmitter;
-},{"events":108}],158:[function(require,module,exports){
+},{"events":108}],155:[function(require,module,exports){
@@ -62780,10 +62372,10 @@ return buf.toString(this.encoding);
function simpleEnd(buf){
return buf&&buf.length?this.write(buf):'';
}
-},{"safe-buffer":165}],159:[function(require,module,exports){
+},{"safe-buffer":162}],156:[function(require,module,exports){
module.exports=require('./readable').PassThrough;
-},{"./readable":160}],160:[function(require,module,exports){
+},{"./readable":157}],157:[function(require,module,exports){
exports=module.exports=require('./lib/_stream_readable.js');
exports.Stream=exports;
exports.Readable=exports;
@@ -62792,13 +62384,13 @@ exports.Duplex=require('./lib/_stream_duplex.js');
exports.Transform=require('./lib/_stream_transform.js');
exports.PassThrough=require('./lib/_stream_passthrough.js');
-},{"./lib/_stream_duplex.js":150,"./lib/_stream_passthrough.js":151,"./lib/_stream_readable.js":152,"./lib/_stream_transform.js":153,"./lib/_stream_writable.js":154}],161:[function(require,module,exports){
+},{"./lib/_stream_duplex.js":147,"./lib/_stream_passthrough.js":148,"./lib/_stream_readable.js":149,"./lib/_stream_transform.js":150,"./lib/_stream_writable.js":151}],158:[function(require,module,exports){
module.exports=require('./readable').Transform;
-},{"./readable":160}],162:[function(require,module,exports){
+},{"./readable":157}],159:[function(require,module,exports){
module.exports=require('./lib/_stream_writable.js');
-},{"./lib/_stream_writable.js":154}],163:[function(require,module,exports){
+},{"./lib/_stream_writable.js":151}],160:[function(require,module,exports){
var URL=require('url').URL;
@@ -63221,13 +62813,13 @@ return this._sitemaps.slice(0);
module.exports=Robots;
-},{"url":"url"}],164:[function(require,module,exports){
+},{"url":"url"}],161:[function(require,module,exports){
var Robots=require('./Robots');
module.exports=function(url,contents){
return new Robots(url,contents);
};
-},{"./Robots":163}],165:[function(require,module,exports){
+},{"./Robots":160}],162:[function(require,module,exports){
var buffer=require('buffer');
var Buffer=buffer.Buffer;
@@ -63291,7 +62883,7 @@ throw new TypeError('Argument must be a number');
return buffer.SlowBuffer(size);
};
-},{"buffer":102}],166:[function(require,module,exports){
+},{"buffer":102}],163:[function(require,module,exports){
(function(process){
exports=module.exports=SemVer;
@@ -64778,7 +64370,7 @@ return parse(match[1]+
}
}).call(this,require('_process'));
-},{"_process":145}],167:[function(require,module,exports){
+},{"_process":142}],164:[function(require,module,exports){
(function(Buffer){
'use strict';
@@ -65020,7 +64612,7 @@ create:frame};
}).call(this,require("buffer").Buffer);
-},{"buffer":102,"fs":101,"jpeg-js":125}],168:[function(require,module,exports){
+},{"buffer":102,"fs":101,"jpeg-js":122}],165:[function(require,module,exports){
'use strict';
const frame=require('./frame');
@@ -65090,7 +64682,7 @@ return calculateValues(frames,data);
});
};
-},{"./frame":167,"./speed-index":169}],169:[function(require,module,exports){
+},{"./frame":164,"./speed-index":166}],166:[function(require,module,exports){
'use strict';
const imageSSIM=require('image-ssim');
@@ -65362,7 +64954,7 @@ calculatePerceptualProgress,
calculateSpeedIndexes};
-},{"image-ssim":112}],170:[function(require,module,exports){
+},{"image-ssim":112}],167:[function(require,module,exports){
@@ -65491,17 +65083,20 @@ dest.emit('pipe',source);
return dest;
};
-},{"events":108,"inherits":113,"readable-stream/duplex.js":149,"readable-stream/passthrough.js":159,"readable-stream/readable.js":160,"readable-stream/transform.js":161,"readable-stream/writable.js":162}],171:[function(require,module,exports){
-module.exports=[{"name":"Google Analytics","company":"Google","homepage":"https://www.google.com/analytics/analytics/","categories":["analytics"],"domains":["www.google-analytics.com","ssl.google-analytics.com","google-analytics.com","urchin.com"]},{"name":"Facebook","homepage":"https://www.facebook.com","categories":["social"],"domains":["www.facebook.com","connect.facebook.net","staticxx.facebook.com","static.xx.fbcdn.net","m.facebook.com","atlassbx.com","fbcdn-photos-e-a.akamaihd.net","23.62.3.183","akamai.net","akamaiedge.net","akamaitechnologies.com","akamaitechnologies.fr","akamaized.net","edgefcs.net","edgekey.net","edgesuite.net","srip.net","cquotient.com","demandware.net","platform-lookaside.fbsbx.com"]},{"name":"Google CDN","company":"Google","homepage":"https://developers.google.com/speed/libraries/","categories":["library"],"domains":["ajax.googleapis.com","www.gstatic.com","commondatastorage.googleapis.com"]},{"name":"Google/Doubleclick Ads","company":"Google","homepage":"https://www.doubleclickbygoogle.com/","categories":["ad"],"domains":["pagead2.googlesyndication.com","tpc.googlesyndication.com","googleads.g.doubleclick.net","securepubads.g.doubleclick.net","cm.g.doubleclick.net","s0.2mdn.net","stats.g.doubleclick.net","survey.g.doubleclick.net","fls.doubleclick.net","ad.doubleclick.net","www.googleadservices.com","adservice.google.se","adservice.google.com","adservice.google.de","www.googletagservices.com"]},{"name":"Google Tag Manager","company":"Google","homepage":"https://marketingplatform.google.com/about/tag-manager/","categories":["tag-manager"],"domains":["www.googletagmanager.com"]},{"name":"Other Google APIs/SDKs","company":"Google","homepage":"https://developers.google.com/apis-explorer/#p/","categories":["utility"],"domains":["www.google.com","apis.google.com","cse.google.com","translate.googleapis.com","storage.googleapis.com","imasdk.googleapis.com","lh3.googleusercontent.com","calendar.google.com","pay.google.com","news.google.com","payments.google.com","clients2.google.com"]},{"name":"Twitter","homepage":"https://twitter.com","categories":["social"],"domains":["platform.twitter.com","cdn.syndication.twimg.com","twitpic.com","vine.co"]},{"name":"Yandex Metrica","company":"Yandex","homepage":"https://metrica.yandex.com/about?","categories":["analytics"],"domains":["mc.yandex.ru","d31j93rd8oukbv.cloudfront.net"]},{"name":"jQuery CDN","homepage":"https://code.jquery.com/","categories":["library"],"domains":["code.jquery.com"]},{"name":"AddThis","homepage":"http://www.addthis.com/","categories":["social"],"domains":["s7.addthis.com","addthiscdn.com","addthisedge.com","r.dlx.addthis.com","su.addthis.com","x.dlx.addthis.com"]},{"name":"Google Maps","company":"Google","homepage":"https://www.google.com/maps","categories":["utility"],"domains":["maps-api-ssl.google.com","maps.google.com","maps.gstatic.com","maps.googleapis.com","mts.googleapis.com"]},{"name":"Hotjar","homepage":"https://www.hotjar.com/","categories":["analytics"],"domains":["script.hotjar.com","static.hotjar.com","in.hotjar.com","vc.hotjar.io","vars.hotjar.com"]},{"name":"Cloudflare CDN","homepage":"https://cdnjs.com/","categories":["library"],"domains":["cdnjs.cloudflare.com","amp.cloudflare.com"]},{"name":"WordPress","company":"Automattic","homepage":"https://wp.com/","categories":["hosting"],"domains":["s0.wp.com","s2.wp.com","s.w.org","wordpress.com","stats.wp.com"]},{"name":"Shopify","homepage":"https://www.shopify.com/","categories":["hosting"],"domains":["cdn.shopify.com","productreviews.shopifycdn.com","shopifyapps.com"]},{"name":"Criteo","homepage":"https://www.criteo.com/","categories":["ad"],"domains":["static.criteo.net","bidder.criteo.com","emailretargeting.com"]},{"name":"ZenDesk","homepage":"https://zendesk.com/","categories":["customer-success"],"domains":["assets.zendesk.com","static.zdassets.com","v2.zopim.com"]},{"name":"Tawk.to","homepage":"https://www.tawk.to/","categories":["customer-success"],"domains":["embed.tawk.to"]},{"name":"AMP","homepage":"https://www.ampproject.org/","categories":["content"],"domains":["cdn.ampproject.org"]},{"name":"Wix","homepage":"https://www.wix.com/","categories":["hosting"],"domains":["static.parastorage.com","static.wixstatic.com","www.wix.com"]},{"name":"Squarespace","homepage":"https://www.squarespace.com/","categories":["hosting"],"domains":["static.squarespace.com","static1.squarespace.com"]},{"name":"YouTube","homepage":"https://youtube.com","categories":["video"],"domains":["www.youtube.com","s.ytimg.com","yt3.ggpht.com","youtube-nocookie.com"]},{"name":"Jivochat","homepage":"https://www.jivochat.com/","categories":["customer-success"],"domains":["cdn-ca.jivosite.com","code.jivosite.com"]},{"name":"Amazon Web Services","homepage":"https://aws.amazon.com/s3/","categories":["other"],"domains":["s3.amazonaws.com","amazonwebservices.com","api-cdn.amazon.com","ecx.images-amazon.com","elasticbeanstalk.com","amazonwebapps.com","ws.amazon.co.uk","payments-amazon.com"]},{"name":"Adobe Tag Manager","company":"Adobe","homepage":"https://www.adobe.com/experience-platform/","categories":["tag-manager"],"domains":["assets.adobedtm.com","dpm.demdex.net","sync-tm.everesttech.net"]},{"name":"PIXNET","homepage":"https://www.pixnet.net/","categories":["social"],"domains":["front.pixfs.net","falcon-asset.pixfs.net","pixgame-asset.pixfs.net"]},{"name":"JSDelivr CDN","homepage":"https://www.jsdelivr.com/","categories":["library"],"domains":["cdn.jsdelivr.net"]},{"name":"Yandex Ads","company":"Yandex","homepage":"https://yandex.com/adv/","categories":["ad"],"domains":["an.yandex.ru"]},{"name":"Yandex Share","company":"Yandex","homepage":"https://yastatic.net/share2/share.js","categories":["social"],"domains":["yastatic.net"]},{"name":"Yandex APIs","company":"Yandex","homepage":"https://yandex.ru/","categories":["utility"],"domains":["api-maps.yandex.ru","money.yandex.ru"]},{"name":"Salesforce","homepage":"https://www.salesforce.com/products/marketing-cloud/","categories":["analytics"],"domains":["cdn.krxd.net","beacon.krxd.net","consumer.krxd.net","usermatch.krxd.net"]},{"name":"Sumo","homepage":"https://sumo.com/","categories":["marketing"],"domains":["sumo.b-cdn.net","load.sumo.com","load.sumome.com"]},{"name":"Beeketing","homepage":"https://beeketing.com/","categories":["marketing"],"domains":["sdk-cdn.beeketing.com","sdk.beeketing.com"]},{"name":"FontAwesome CDN","homepage":"https://fontawesome.com/","categories":["library"],"domains":["use.fontawesome.com"]},{"name":"ShareThis","homepage":"https://www.sharethis.com/","categories":["social"],"domains":["w.sharethis.com","ws.sharethis.com","t.sharethis.com"]},{"name":"Hatena Blog","homepage":"https://hatenablog.com/","categories":["hosting"],"domains":["cdn.blog.st-hatena.com","cdn.pool.st-hatena.com","cdn7.www.st-hatena.com","s.hatena.ne.jp","b.st-hatena.com"]},{"name":"Mailchimp","homepage":"https://mailchimp.com/","categories":["marketing"],"domains":["downloads.mailchimp.com","chimpstatic.com","list-manage.com"]},{"name":"Amazon Ads","homepage":"https://ad.amazon.com/","categories":["ad"],"domains":["s.amazon-adsystem.com","c.amazon-adsystem.com","aax.amazon-adsystem.com","z-na.amazon-adsystem.com"]},{"name":"Sentry","homepage":"https://sentry.io/","categories":["utility"],"domains":["cdn.ravenjs.com","browser.sentry-cdn.com","getsentry.com"]},{"name":"Pinterest","homepage":"https://pinterest.com/","categories":["social"],"domains":["assets.pinterest.com","pinimg.com","ct.pinterest.com"]},{"name":"Hubspot","homepage":"https://hubspot.com/","categories":["marketing"],"domains":["forms.hubspot.com","js.hsforms.net","js.hs-analytics.net","hscollectedforms.net","hscta.net","hsleadflows.net","js.leadin.com","hs-scripts.com","hsstatic.net","hubspot.net"]},{"name":"LinkedIn","homepage":"https://www.linkedin.com/","categories":["social"],"domains":["platform.linkedin.com","bizographics.com","slideshare.com","slidesharecdn.com"]},{"name":"Taboola","homepage":"https://www.taboola.com/","categories":["ad"],"domains":["cdn.taboola.com","trc.taboola.com","vidstat.taboola.com","taboolasyndication.com"]},{"name":"Intercom","homepage":"https://www.intercom.com/","categories":["customer-success"],"domains":["js.intercomcdn.com"]},{"name":"Histats","homepage":"http://histats.com/","categories":["analytics"],"domains":["s10.histats.com"]},{"name":"Optimizely","homepage":"https://www.optimizely.com/","categories":["analytics"],"domains":["cdn.optimizely.com","cdn-pci.optimizely.com","logx.optimizely.com","cdn3.optimizely.com"]},{"name":"Moat","homepage":"https://moat.com/","categories":["ad"],"domains":["z.moatads.com","moatpixel.com","px.moatads.com","geo.moatads.com","sejs.moatads.com","mb.moatads.com","v4.moatads.com"]},{"name":"Tealium","homepage":"https://tealium.com/","categories":["tag-manager"],"domains":["tags.tiqcdn.com","tealium.hs.llnwd.net","aniview.com","delvenetworks.com","link.videoplatform.limelight.com"]},{"name":"Distil Networks","homepage":"https://www.distilnetworks.com/","categories":["utility"],"domains":["n-cdn.areyouahuman.com"]},{"name":"Scorecard Research","homepage":"https://www.scorecardresearch.com/","categories":["ad"],"domains":["sb.scorecardresearch.com"]},{"name":"Blogger","homepage":"http://www.blogger.com/","categories":["hosting"],"domains":["1.bp.blogspot.com","www.blogger.com","images-blogger-opensocial.googleusercontent.com"]},{"name":"Wistia","homepage":"https://wistia.com/","categories":["video"],"domains":["fast.wistia.com","fast.wistia.net"]},{"name":"LiveChat","homepage":"https://www.livechatinc.com/","categories":["customer-success"],"domains":["cdn.livechatinc.com","secure.livechatinc.com"]},{"name":"Adobe TypeKit","company":"Adobe","homepage":"https://fonts.adobe.com/","categories":["library"],"domains":["use.typekit.net","typekit.com","p.typekit.net"]},{"name":"Shareaholic","homepage":"https://www.shareaholic.com/","categories":["social"],"domains":["dsms0mj1bbhn4.cloudfront.net","shareaholic.com"]},{"name":"OneSignal","homepage":"https://onesignal.com/","categories":["utility"],"domains":["cdn.onesignal.com"]},{"name":"Cookiebot","homepage":"https://www.cookiebot.com/","categories":["utility"],"domains":["consent.cookiebot.com"]},{"name":"Tumblr","homepage":"https://tumblr.com/","categories":["social"],"domains":["assets.tumblr.com","static.tumblr.com"]},{"name":"Cloudflare","homepage":"https://www.cloudflare.com/website-optimization/","categories":["utility"],"domains":["ajax.cloudflare.com"]},{"name":"Integral Ad Science","homepage":"https://integralads.com/uk/","categories":["ad"],"domains":["pixel.adsafeprotected.com","static.adsafeprotected.com","fw.adsafeprotected.com","cdn.adsafeprotected.com","dt.adsafeprotected.com","iasds01.com"]},{"name":"PayPal","homepage":"https://paypal.com","categories":["utility"],"domains":["www.paypalobjects.com","paypal.com"]},{"name":"Segment","homepage":"https://segment.com/","categories":["analytics"],"domains":["cdn.segment.com","api.segment.io"]},{"name":"Baidu Analytics","homepage":"https://tongji.baidu.com/web/welcome/login","categories":["analytics"],"domains":["hm.baidu.com"]},{"name":"Dealer","homepage":"https://www.dealer.com/","categories":["hosting"],"domains":["static.dealer.com"]},{"name":"Olark","homepage":"https://www.olark.com/","categories":["customer-success"],"domains":["static.olark.com"]},{"name":"VK","homepage":"https://vk.com/","categories":["social"],"domains":["vk.com"]},{"name":"OpenX","homepage":"https://www.openx.com/","categories":["ad"],"domains":["uk-ads.openx.net","us-ads.openx.net","33across-d.openx.net","rtb.openx.net","us-u.openx.net","eu-u.openx.net","u.openx.net","deliverimp.com","jump-time.net","openxadexchange.com","servedbyopenx.com"]},{"name":"Lucky Orange","homepage":"https://www.luckyorange.com/","categories":["analytics"],"domains":["d10lpsik1i8c69.cloudfront.net","luckyorange.com","luckyorange.net"]},{"name":"OptinMonster","homepage":"https://optinmonster.com/","categories":["marketing"],"domains":["a.optmstr.com","api.opmnstr.com","a.optmnstr.com"]},{"name":"Snapchat","homepage":"https://www.snapchat.com","categories":["analytics"],"domains":["tr.snapchat.com","sc-static.net"]},{"name":"33 Across","homepage":"https://33across.com/","categories":["ad"],"domains":["sic.33across.com","cdn-sic.33across.com"]},{"name":"Ensighten","homepage":"https://www.ensighten.com/","categories":["tag-manager"],"domains":["nexus.ensighten.com"]},{"name":"WordAds","company":"Automattic","homepage":"https://wordads.co/","categories":["ad"],"domains":["s.pubmine.com"]},{"name":"Snowplow","homepage":"https://snowplowanalytics.com/","categories":["analytics"],"domains":["d32hwlnfiv2gyn.cloudfront.net"]},{"name":"Brightcove","homepage":"https://www.brightcove.com/en/","categories":["video"],"domains":["vjs.zencdn.net","players.brightcove.net","brightcove.com"]},{"name":"Drift","homepage":"https://www.drift.com/","categories":["marketing"],"domains":["js.driftt.com","api.drift.com"]},{"name":"Microsoft Hosted Libs","company":"Microsoft","categories":["library"],"domains":["ajax.aspnetcdn.com"]},{"name":"Stripe","homepage":"https://stripe.com","categories":["utility"],"domains":["m.stripe.network","js.stripe.com","stripecdn.com"]},{"name":"Parking Crew","homepage":"http://parkingcrew.net/","categories":["other"],"domains":["d1lxhc4jvstzrp.cloudfront.net","parkingcrew.net"]},{"name":"Popads","homepage":"https://www.popads.net/","categories":["ad"],"domains":["serve.popads.net","c1.popads.net"]},{"name":"DigiTrust","homepage":"http://www.digitru.st/","categories":["analytics"],"domains":["cdn.digitru.st"]},{"name":"Mixpanel","homepage":"https://mixpanel.com/","categories":["analytics"],"domains":["cdn.mxpnl.com","mixpanel.com"]},{"name":"MediaVine","homepage":"https://www.mediavine.com/","categories":["ad"],"domains":["scripts.mediavine.com","video.mediavine.com"]},{"name":"FullStory","categories":["analytics"],"domains":["fullstory.com","rs.fullstory.com"]},{"name":"Sizmek","homepage":"https://www.sizmek.com/","categories":["ad"],"domains":["secure-ds.serving-sys.com","ds.serving-sys.com","peer39.net","bs.serving-sys.com"]},{"name":"CDK Dealer Management","company":"CDK Global","homepage":"https://www.cdkglobal.com/us","categories":["hosting"],"domains":["media-cf.assets-cdk.com"]},{"name":"Quantcast","homepage":"https://www.quantcast.com","categories":["analytics"],"domains":["pixel.quantserve.com","secure.quantserve.com","rules.quantcount.com","brtstats.com","ntv.io","semantictec.com"]},{"name":"Pubmatic","homepage":"https://pubmatic.com/","categories":["ad"],"domains":["image6.pubmatic.com","ads.pubmatic.com","image2.pubmatic.com","simage2.pubmatic.com","image4.pubmatic.com","simage4.pubmatic.com"]},{"name":"RD Station","homepage":"https://www.rdstation.com/en/","categories":["marketing"],"domains":["d335luupugsy2.cloudfront.net"]},{"name":"MGID","homepage":"https://www.mgid.com/","categories":["ad"],"domains":["servicer.mgid.com","dt07.net"]},{"name":"Media.net","homepage":"https://www.media.net/","categories":["ad"],"domains":["contextual.media.net","mnet-ad.net"]},{"name":"New Relic","homepage":"https://newrelic.com/","categories":["utility"],"domains":["js-agent.newrelic.com","bam.nr-data.net"]},{"name":"Rubicon Project","homepage":"https://rubiconproject.com/","categories":["ad"],"domains":["pixel.rubiconproject.com","fastlane.rubiconproject.com","secure-assets.rubiconproject.com","eus.rubiconproject.com","pixel-us-east.rubiconproject.com","token.rubiconproject.com","ads.rubiconproject.com","chango.com","fimserve.com"]},{"name":"VWO","homepage":"https://vwo.com","categories":["analytics"],"domains":["dev.visualwebsiteoptimizer.com"]},{"name":"Keen","company":"Keen","homepage":"https://keen.io/","categories":["analytics"],"domains":["d26b395fwzu5fz.cloudfront.net","keen.io"]},{"name":"Adroll","homepage":"https://www.adroll.com/","categories":["ad"],"domains":["d.adroll.com","s.adroll.com"]},{"name":"Unpkg","homepage":"https://unpkg.com","categories":["library"],"domains":["unpkg.com"]},{"name":"Parse.ly","categories":["analytics"],"domains":["d1z2jf7jlzjs58.cloudfront.net","parsely.com"]},{"name":"Searchanise","categories":["analytics"],"domains":["www.searchanise.com"]},{"name":"AppNexus","homepage":"https://www.appnexus.com/","categories":["ad"],"domains":["acdn.adnxs.com","secure.adnxs.com","ctasnet.com","ib.adnxs.com"]},{"name":"uLogin","categories":["other"],"domains":["ulogin.ru"]},{"name":"fam","company":"Fing Co Ltd.","homepage":"http://admin.fam-ad.com/report/","categories":["ad"],"domains":["fam-ad.com","img.fam-ad.com"]},{"name":"Yandex CDN","company":"Yandex","homepage":"https://yandex.ru/","categories":["library"],"domains":["yandex.st"]},{"name":"Albacross","homepage":"https://albacross.com/","categories":["marketing"],"domains":["serve.albacross.com"]},{"name":"CreateJS CDN","homepage":"http://code.createjs.com/","categories":["library"],"domains":["code.createjs.com"]},{"name":"Help Scout","homepage":"https://www.helpscout.net/","categories":["customer-success"],"domains":["djtflbt20bdde.cloudfront.net","beacon-v2.helpscout.net"]},{"name":"AppDynamics","homepage":"https://www.appdynamics.com/","categories":["utility"],"domains":["cdn.appdynamics.com","d3tjaysgumg9lf.cloudfront.net","eum-appdynamics.com"]},{"name":"Siteimprove","categories":["utility"],"domains":["siteimprove.com","siteimproveanalytics.com"]},{"name":"DoubleVerify","homepage":"https://www.doubleverify.com/","categories":["ad"],"domains":["cdn.doubleverify.com","rtb0.doubleverify.com","rtbcdn.doubleverify.com","dvtps.com","tm.iqfp1.com"]},{"name":"AOL / Oath / Verizon Media","homepage":"https://www.oath.com/","categories":["ad"],"domains":["pixel.advertising.com","dtm.advertising.com","tag.sp.advertising.com","service.sp.advertising.com","adtech.advertising.com","aol.co.uk","aol.com","aolcdn.com","blogsmithmedia.com","mighty.aol.net","tacoda.net","consent.cmp.oath.com"]},{"name":"Alexa","homepage":"https://www.alexa.com/","categories":["analytics"],"domains":["d31qbv1cthcecs.cloudfront.net"]},{"name":"SessionCam","company":"ServiceTick","categories":["analytics"],"domains":["d2oh4tlt9mrke9.cloudfront.net","sessioncam.com"]},{"name":"Foursixty","categories":["customer-success"],"domains":["foursixty.com"]},{"name":"Listrak","homepage":"https://www.listrak.com/","categories":["marketing"],"domains":["cdn.listrakbi.com","s1.listrakbi.com","listrak.com"]},{"name":"mPulse","homepage":"https://developer.akamai.com/akamai-mpulse","categories":["analytics"],"domains":["c.go-mpulse.net","0211c83c.akstat.io","mpstat.us","mpulse.net"]},{"name":"Opentag","company":"Qubit","categories":["tag-manager"],"domains":["d3c3cq33003psk.cloudfront.net","opentag-stats.qutics.com"]},{"name":"Market GID","homepage":"https://www.marketgid.com/","categories":["ad"],"domains":["jsc.marketgid.com"]},{"name":"Freshdesk","homepage":"https://freshdesk.com/","categories":["customer-success"],"domains":["d36mpcpuzc4ztk.cloudfront.net"]},{"name":"IBM Digital Analytics","company":"IBM","categories":["analytics"],"domains":["cmcore.com","coremetrics.com","data.coremetrics.com","data.coremetrics.eu","data.de.coremetrics.com","iocdn.coremetrics.com","libs.coremetrics.com","libs.de.coremetrics.com","s81c.com","tmscdn.coremetrics.com","tmscdn.de.coremetrics.com","unica.com"]},{"name":"Usabilla","homepage":"https://usabilla.com","categories":["analytics"],"domains":["w.usabilla.com","d6tizftlrpuof.cloudfront.net"]},{"name":"Bugsnag","categories":["utility"],"domains":["d2wy8f7a9ursnm.cloudfront.net","notify.bugsnag.com"]},{"name":"AddShoppers","categories":["social"],"domains":["addshoppers.com","d3rr3d0n31t48m.cloudfront.net","shop.pe"]},{"name":"Po.st","company":"RadiumOne","categories":["utility"],"domains":["po.st"]},{"name":"Disqus","homepage":"http://disqus.com/","categories":["social"],"domains":["c.disquscdn.com","disqus.com"]},{"name":"PhotoBucket","categories":["content"],"domains":["photobucket.com"]},{"name":"GitHub","categories":["utility"],"domains":["cdn.rawgit.com"]},{"name":"Bootstrap CDN","homepage":"https://www.bootstrapcdn.com/","categories":["library"],"domains":["maxcdn.bootstrapcdn.com","stackpath.bootstrapcdn.com"]},{"name":"Radar","company":"Cedexis","homepage":"https://www.cedexis.com/radar/","categories":["analytics"],"domains":["radar.cedexis.com","rpt.cedexis.com","2-01-49cd-0002.cdx.cedexis.net","a-cedexis.msedge.net","bench.cedexis-test.com","cedexis-radar.net","cedexis-test01.insnw.net","cedexis.leasewebcdn.com","cedexisakamaitest.azureedge.net","cedexispub.cdnetworks.net","cs600.wac.alphacdn.net","cs600.wpc.edgecastdns.net","global2.cmdolb.com","img-cedexis.mncdn.com","zn3vgszfh.fastestcdn.net","edgecastcdn.net"]},{"name":"SnapWidget","categories":["content"],"domains":["snapwidget.com"]},{"name":"Media Math","homepage":"http://www.mediamath.com/","categories":["ad"],"domains":["mathid.mathtag.com","mathads.com","sync.mathtag.com","pixel.mathtag.com"]},{"name":"ClickDesk","categories":["customer-success"],"domains":["clickdesk.com","d1gwclp1pmzk26.cloudfront.net"]},{"name":"Google Plus","company":"Google","categories":["social"],"domains":["plus.google.com"]},{"name":"LinkedIn Ads","categories":["ad"],"domains":["ads.linkedin.com","snap.licdn.com","www.linkedin.com"]},{"name":"Madison Logic","categories":["marketing"],"domains":["ml314.com"]},{"name":"Smarter Click","categories":["ad"],"domains":["smarterclick.co.uk","smct.co"]},{"name":"Bing Ads","homepage":"https://bingads.microsoft.com","categories":["ad"],"domains":["bat.bing.com","c.bing.com","bat.r.msn.com","ajax.microsoft.com","msads.net","msecnd.net","s-msft.com","s-msn.com","windows.net"]},{"name":"Fresh Relevance","categories":["analytics"],"domains":["d1y9qtn9cuc3xw.cloudfront.ne","d1y9qtn9cuc3xw.cloudfront.net","d81mfvml8p5ml.cloudfront.net","dkpklk99llpj0.cloudfront.net","freshrelevance.com"]},{"name":"Browsealoud","homepage":"https://www.texthelp.com/en-gb/products/browsealoud/","categories":["other"],"domains":["www.browsealoud.com","texthelp.com"]},{"name":"Qubit Deliver","company":"Qubit","categories":["analytics"],"domains":["d1m54pdnjzjnhe.cloudfront.net","d22rutvoghj3db.cloudfront.net","dd6zx4ibq538k.cloudfront.net"]},{"name":"Crazy Egg","homepage":"https://www.crazyegg.com/","categories":["analytics"],"domains":["dnn506yrbagrg.cloudfront.net","cetrk.com","crazyegg.com","hellobar.com"]},{"name":"Vox Media","homepage":"https://www.voxmedia.com/","categories":["content"],"domains":["cdn.vox-cdn.com","voxmedia.com"]},{"name":"SaleCycle","categories":["ad"],"domains":["d16fk4ms6rqz1v.cloudfront.net","d22j4fzzszoii2.cloudfront.net","d30ke5tqu2tkyx.cloudfront.net","salecycle.com"]},{"name":"Sidecar","categories":["other"],"domains":["d3v27wwd40f0xu.cloudfront.net","getsidecar.com"]},{"name":"Concert","homepage":"https://concert.io/","categories":["ad"],"domains":["cdn.concert.io"]},{"name":"Kaizen Platform","categories":["analytics"],"domains":["cdn.kaizenplatform.net","log-v4.kaizenplatform.net"]},{"name":"unpkg","categories":["utility"],"domains":["npmcdn.com"]},{"name":"Edge Web Fonts","company":"Adobe Systems","categories":["library"],"domains":["use.edgefonts.net"]},{"name":"The Trade Desk","homepage":"https://www.thetradedesk.com/","categories":["ad"],"domains":["js.adsrvr.org","match.adsrvr.org","d1eoo1tco6rr5e.cloudfront.net","snap.adsrvr.org"]},{"name":"Ipify","homepage":"https://www.ipify.org","categories":["utility"],"domains":["api.ipify.org","geo.ipify.org"]},{"name":"Permutive","categories":["ad"],"domains":["d3alqb8vzo7fun.cloudfront.net","permutive.com"]},{"name":"Pingdom RUM","homepage":"https://www.pingdom.com/product/performance-monitoring/","categories":["analytics"],"domains":["rum-static.pingdom.net","rum-collector-2.pingdom.net"]},{"name":"Clicktripz","categories":["content"],"domains":["static.clicktripz.com","www.clicktripz.com"]},{"name":"Talkable","categories":["ad"],"domains":["d2jjzw81hqbuqv.cloudfront.net","www.talkable.com"]},{"name":"GoSquared","homepage":"https://www.gosquared.com","categories":["analytics"],"domains":["data.gosquared.com","d1l6p2sc9645hc.cloudfront.net","data2.gosquared.com"]},{"name":"Republer","categories":["ad"],"domains":["sync.republer.com"]},{"name":"TrackJS","categories":["analytics"],"domains":["d2zah9y47r7bi2.cloudfront.net","usage.trackjs.com"]},{"name":"Vimeo","homepage":"http://vimeo.com/","categories":["video"],"domains":["f.vimeocdn.com","player.vimeo.com"]},{"name":"Yieldify","categories":["ad"],"domains":["d33wq5gej88ld6.cloudfront.net","dwmvwp56lzq5t.cloudfront.net","geo.yieldifylabs.com","yieldify.com"]},{"name":"DialogTech SourceTrak","company":"DialogTech","categories":["ad"],"domains":["d31y97ze264gaa.cloudfront.net"]},{"name":"Twitter Online Conversion Tracking","company":"Twitter","categories":["ad"],"domains":["static.ads-twitter.com","analytics.twitter.com"]},{"name":"CleverTap","categories":["analytics"],"domains":["d2r1yp2w7bby2u.cloudfront.net"]},{"name":"Omniconvert","categories":["analytics"],"domains":["d2tgfbvjf3q6hn.cloudfront.net","d3vbj265bmdenw.cloudfront.net","omniconvert.com"]},{"name":"Underdog Media","categories":["ad"],"domains":["udmserve.net","underdog.media"]},{"name":"[24]7","categories":["customer-success"],"domains":["247-inc.net","247inc.net","d1af033869koo7.cloudfront.net"]},{"name":"Reflektion","categories":["analytics"],"domains":["d26opx5dl8t69i.cloudfront.net","reflektion.com"]},{"name":"Auto Link Maker","company":"Apple","categories":["ad"],"domains":["autolinkmaker.itunes.apple.com"]},{"name":"Friendbuy","categories":["ad"],"domains":["djnf6e5yyirys.cloudfront.net","friendbuy.com"]},{"name":"Opinion Stage","categories":["analytics"],"domains":["www.opinionstage.com"]},{"name":"LongTail Ad Solutions","categories":["ad"],"domains":["jwpcdn.com","jwplatform.com","jwplayer.com","jwpltx.com","jwpsrv.com","longtailvideo.com"]},{"name":"Marketo","homepage":"https://www.marketo.com","categories":["analytics"],"domains":["munchkin.marketo.net","marketo.com","mktoresp.com"]},{"name":"Sourcepoint","categories":["ad"],"domains":["d2lv4zbk7v5f93.cloudfront.net","d3qxwzhswv93jk.cloudfront.net","www.decenthat.com","www.fallingfalcon.com"]},{"name":"Net Reviews","categories":["analytics"],"domains":["www.avis-verifies.com"]},{"name":"Tag Inspector","company":"InfoTrust","categories":["analytics"],"domains":["d22xmn10vbouk4.cloudfront.net"]},{"name":"Polldaddy","company":"Automattic","categories":["analytics"],"domains":["polldaddy.com"]},{"name":"Freespee","categories":["customer-success"],"domains":["analytics.freespee.com"]},{"name":"KISSmetrics","categories":["analytics"],"domains":["doug1izaerwt3.cloudfront.net","dsyszv14g9ymi.cloudfront.net","kissmetrics.com"]},{"name":"Adthink","company":"Adthink Media","categories":["ad"],"domains":["d.adxcore.com","dcoengine.com"]},{"name":"Extole","categories":["ad"],"domains":["extole.com","origin.extole.io"]},{"name":"AnswerDash","categories":["customer-success"],"domains":["p1.answerdash.com"]},{"name":"Cookie-Script.com","categories":["utility"],"domains":["cookie-script.com"]},{"name":"Fastly Insights","homepage":"https://insights.fastlylabs.com","categories":["analytics"],"domains":["www.fastly-insights.com"]},{"name":"Amplitude Mobile Analytics","company":"Amplitude","categories":["analytics"],"domains":["amplitude.com","d24n15hnbwhuhn.cloudfront.net"]},{"name":"MLveda","categories":["utility"],"domains":["www.mlveda.com"]},{"name":"CNET Content Solutions","company":"CBS Interactive","categories":["content"],"domains":["cdn.cnetcontent.com","cnetcontent.com","ws.cnetcontent.com"]},{"name":"Browser-Update.org","categories":["other"],"domains":["browser-update.org"]},{"name":"Triblio","categories":["marketing"],"domains":["tribl.io"]},{"name":"Fonecall","categories":["analytics"],"domains":["web-call-analytics.com"]},{"name":"LoyaltyLion","categories":["ad"],"domains":["dg1f2pfrgjxdq.cloudfront.net","loyaltylion.com"]},{"name":"StatCounter","categories":["analytics"],"domains":["statcounter.com"]},{"name":"Curalate","categories":["marketing"],"domains":["curalate.com","d116tqlcqfmz3v.cloudfront.net"]},{"name":"piano","categories":["ad"],"domains":["tinypass.com","www.npttech.com"]},{"name":"UpSellit","categories":["analytics"],"domains":["www.upsellit.com"]},{"name":"Soundest","categories":["ad"],"domains":["soundest.net","soundestlink.com"]},{"name":"Micropat","categories":["social"],"domains":["addtoany.com"]},{"name":"Weebly","homepage":"https://www.weebly.com/","categories":["hosting"],"domains":["editmysite.com"]},{"name":"Tynt","company":"33 Across","categories":["ad"],"domains":["tynt.com"]},{"name":"Datacamp","categories":["utility"],"domains":["cdn77.org"]},{"name":"Treasure Data","categories":["analytics"],"domains":["treasuredata.com"]},{"name":"Nielsen NetRatings SiteCensus","company":"The Nielsen Company","homepage":"http://www.nielsen-online.com/intlpage.html","categories":["analytics"],"domains":["imrworldwide.com"]},{"name":"iubenda","categories":["utility"],"domains":["www.iubenda.com"]},{"name":"Yotpo","homepage":"https://www.yotpo.com/","categories":["marketing"],"domains":["yotpo.com"]},{"name":"Privy","categories":["ad"],"domains":["privy.com","privymktg.com"]},{"name":"VigLink","categories":["ad"],"domains":["viglink.com"]},{"name":"Kakao","categories":["social"],"domains":["daum.net","daumcdn.net"]},{"name":"Chartbeat","categories":["analytics"],"domains":["chartbeat.com","chartbeat.net"]},{"name":"Klaviyo","categories":["ad"],"domains":["klaviyo.com"]},{"name":"BrightTag / Signal","company":"Signal","homepage":"https://www.signal.co","categories":["tag-manager"],"domains":["btstatic.com","thebrighttag.com"]},{"name":"fluct","categories":["ad"],"domains":["adingo.jp"]},{"name":"AudienceSearch","company":"Intimate Merger","categories":["ad"],"domains":["im-apps.net"]},{"name":"Inspectlet","categories":["analytics"],"domains":["inspectlet.com"]},{"name":"Skimbit","categories":["ad"],"domains":["redirectingat.com","skimresources.com","skimresources.net"]},{"name":"DTSCOUT","categories":["ad"],"domains":["dtscout.com"]},{"name":"Rambler","company":"Rambler & Co","categories":["utility"],"domains":["rambler.ru"]},{"name":"Bigcommerce","categories":["marketing"],"domains":["bigcommerce.com"]},{"name":"Tidio Live Chat","company":"Tidio","homepage":"https://www.tidiochat.com/en/","categories":["customer-success"],"domains":["tidiochat.com"]},{"name":"CallRail","categories":["analytics"],"domains":["callrail.com"]},{"name":"Teads","categories":["ad"],"domains":["teads.tv"]},{"name":"Instagram","homepage":"https://www.instagram.com","categories":["social"],"domains":["scontent.cdninstagram.com","instagram.com"]},{"name":"Fastly","categories":["utility"],"domains":["fastly.net"]},{"name":"MailMunch","categories":["ad"],"domains":["mailmunch.co"]},{"name":"LivePerson","categories":["customer-success"],"homepage":"https://www.liveperson.com/","domains":["liveperson.com","liveperson.net","look.io","lpsnmedia.net"]},{"name":"Monotype","categories":["library"],"domains":["fonts.com","fonts.net"]},{"name":"Outbrain","homepage":"https://www.outbrain.com/","categories":["ad"],"domains":["outbrain.com","visualrevenue.com"]},{"name":"Pure Chat","categories":["customer-success"],"domains":["purechat.com"]},{"name":"LiveJournal","categories":["social"],"domains":["livejournal.com","livejournal.net"]},{"name":"PushCrew","categories":["ad"],"domains":["pushcrew.com"]},{"name":"Index Exchange","company":"WPP","categories":["ad"],"domains":["casalemedia.com","indexww.com"]},{"name":"StickyADS.tv","categories":["ad"],"domains":["stickyadstv.com"]},{"name":"GumGum","categories":["ad"],"domains":["gumgum.com"]},{"name":"AB Tasty","categories":["analytics"],"domains":["abtasty.com","d1447tq2m68ekg.cloudfront.net"]},{"name":"Trust Pilot","categories":["analytics"],"domains":["trustpilot.com"]},{"name":"Embedly","categories":["content"],"domains":["embed.ly","embedly.com"]},{"name":"Adform","categories":["ad"],"domains":["adform.net","adformdsp.net"]},{"name":"sovrn","categories":["ad"],"domains":["lijit.com"]},{"name":"iPerceptions","categories":["customer-success"],"domains":["iperceptions.com"]},{"name":"Cxense","categories":["ad"],"domains":["cxense.com","cxpublic.com","emediate.dk","emediate.eu"]},{"name":"Bold Commerce","categories":["utility"],"domains":["boldapps.net","shappify-cdn.com","shappify.com"]},{"name":"Marchex","categories":["analytics"],"domains":["marchex.io","voicestar.com"]},{"name":"BlueKai","company":"Oracle","categories":["ad"],"domains":["bkrtx.com","bluekai.com"]},{"name":"PubNation","categories":["ad"],"domains":["pubnation.com"]},{"name":"Infolinks","categories":["ad"],"domains":["infolinks.com"]},{"name":"Ezoic","categories":["analytics"],"domains":["ezoic.net"]},{"name":"Sharethrough","categories":["ad"],"domains":["sharethrough.com"]},{"name":"Ve","company":"Ve Interactive","categories":["marketing"],"domains":["veinteractive.com"]},{"name":"Roxr Software","categories":["analytics"],"domains":["getclicky.com"]},{"name":"LiveTex","categories":["customer-success"],"domains":["livetex.ru"]},{"name":"Crowd Control","company":"Lotame","categories":["ad"],"domains":["crwdcntrl.net"]},{"name":"Digital ad Consortium","categories":["ad"],"domains":["impact-ad.jp"]},{"name":"GetSiteControl","company":"GetWebCraft","categories":["utility"],"domains":["getsitecontrol.com"]},{"name":"Mapbox","categories":["utility"],"domains":["mapbox.com"]},{"name":"Adloox","categories":["ad"],"domains":["adlooxtracking.com"]},{"name":"Nosto","categories":["analytics"],"domains":["nosto.com"]},{"name":"Gigya","categories":["analytics"],"domains":["gigya.com"]},{"name":"Heap","categories":["analytics"],"domains":["heapanalytics.com"]},{"name":"ExoClick","categories":["ad"],"domains":["exoclick.com"]},{"name":"OpenTable","company":"Priceline Group","categories":["content"],"domains":["opentable.co.uk","opentable.com","www.toptable.co.uk"]},{"name":"iBillboard","categories":["ad"],"domains":["ibillboard.com"]},{"name":"Microad","categories":["ad"],"domains":["microad.jp"]},{"name":"Rakuten Marketing","company":"Rakuten","categories":["ad"],"domains":["rakuten-static.com","rmtag.com"]},{"name":"JuicyAds","categories":["ad"],"domains":["juicyads.com"]},{"name":"Mouseflow","categories":["analytics"],"domains":["mouseflow.com"]},{"name":"Swiftype","categories":["utility"],"domains":["swiftype.com","swiftypecdn.com"]},{"name":"Yahoo!","homepage":"https://www.yahoo.com/","categories":["ad"],"domains":["ads.yahoo.com","analytics.yahoo.com","bluelithium.com","hostingprod.com","lexity.com","yahoo.net","yahooapis.com","yimg.com","zenfs.com","geo.yahoo.com"]},{"name":"etracker","categories":["analytics"],"domains":["etracker.de","www.etracker.com"]},{"name":"Accuweather","categories":["content"],"domains":["accuweather.com"]},{"name":"Feefo.com","company":"Feefo","categories":["analytics"],"domains":["feefo.com"]},{"name":"Smart AdServer","categories":["ad"],"domains":["sasqos.com","smartadserver.com"]},{"name":"Medium","categories":["content"],"domains":["medium.com"]},{"name":"Trusted Shops","categories":["utility"],"domains":["trustedshops.com"]},{"name":"Constant Contact","categories":["ad"],"domains":["ctctcdn.com"]},{"name":"AdMatic","categories":["ad"],"domains":["admatic.com.tr"]},{"name":"Unbounce","categories":["ad"],"domains":["d2xxq4ijfwetlm.cloudfront.net","d9hhrg4mnvzow.cloudfront.net","ubembed.com","unbounce.com"]},{"name":"Evidon","categories":["analytics"],"domains":["evidon.com"]},{"name":"SmartAdServer","categories":["ad"],"domains":["sascdn.com","securite.01net.com"]},{"name":"Gemius","categories":["ad"],"domains":["gemius.pl"]},{"name":"SocialShopWave","categories":["social"],"domains":["socialshopwave.com"]},{"name":"Sift Science","categories":["utility"],"domains":["siftscience.com"]},{"name":"Affirm","categories":["utility"],"domains":["affirm.com"]},{"name":"Admixer for Publishers","company":"Admixer","categories":["ad"],"domains":["admixer.net"]},{"name":"LKQD","categories":["ad"],"domains":["lkqd.net"]},{"name":"Hotmart","homepage":"https://www.hotmart.com/","categories":["content"],"domains":["launchermodule.hotmart.com"]},{"name":"Secomapp","categories":["utility"],"domains":["secomapp.com"]},{"name":"Sortable","categories":["ad"],"domains":["deployads.com"]},{"name":"Bazaarvoice","categories":["analytics"],"domains":["bazaarvoice.com","feedmagnet.com"]},{"name":"Seznam","categories":["utility"],"domains":["imedia.cz"]},{"name":"Vidible","categories":["ad"],"domains":["vidible.tv"]},{"name":"Affiliate Window","company":"Digital Window","categories":["ad"],"domains":["dwin1.com"]},{"name":"OptiMonk","categories":["ad"],"domains":["optimonk.com"]},{"name":"Refersion","categories":["ad"],"domains":["refersion.com"]},{"name":"Pagely","categories":["other"],"domains":["optnmstr.com"]},{"name":"BounceX","categories":["analytics"],"homepage":"https://www.bouncex.com/","domains":["bounceexchange.com","events.bouncex.net"]},{"name":"TrafficStars","categories":["ad"],"domains":["trafficstars.com","tsyndicate.com"]},{"name":"SnapEngage","categories":["customer-success"],"domains":["snapengage.com"]},{"name":"Esri ArcGIS","company":"Esri","categories":["utility"],"domains":["arcgis.com","arcgisonline.com"]},{"name":"ForeSee","company":"Answers","categories":["analytics"],"domains":["4seeresults.com","answerscloud.com","foresee.com","foreseeresults.com"]},{"name":"TagCommander","categories":["tag-manager"],"domains":["commander1.com","tagcommander.com"]},{"name":"Convert Insights","categories":["analytics"],"domains":["convertexperiments.com"]},{"name":"iovation","categories":["utility"],"domains":["iesnare.com"]},{"name":"Clicktale","categories":["analytics"],"domains":["clicktale.net","clicktalecdn.sslcs.cdngc.net"]},{"name":"Comm100","categories":["customer-success"],"domains":["comm100.com"]},{"name":"Yieldmo","categories":["ad"],"domains":["yieldmo.com"]},{"name":"IPONWEB","categories":["ad"],"domains":["company-target.com","liadm.com","p161.net","pool.udsp.iponweb.net"]},{"name":"Nend","categories":["ad"],"domains":["nend.net"]},{"name":"Perfect Market","categories":["ad"],"domains":["perfectmarket.com"]},{"name":"Fraudlogix","categories":["utility"],"domains":["yabidos.com"]},{"name":"Symantec","categories":["utility"],"domains":["extended-validation-ssl.websecurity.symantec.com","norton.com","symantec.com","symcb.com","symcd.com"]},{"name":"Bizible","categories":["ad"],"domains":["bizible.com"]},{"name":"Between Digital","categories":["ad"],"domains":["betweendigital.com"]},{"name":"Maxymiser","categories":["analytics"],"domains":["maxymiser.net"]},{"name":"Branch Metrics","categories":["ad"],"domains":["app.link","branch.io"]},{"name":"Tradelab","categories":["ad"],"domains":["tradelab.fr"]},{"name":"Digioh","categories":["ad"],"domains":["lightboxcdn.com"]},{"name":"Tail Target","company":"Tail","categories":["ad"],"domains":["tailtarget.com"]},{"name":"GetResponse","categories":["ad"],"domains":["getresponse.com"]},{"name":"OwnerIQ","categories":["ad"],"domains":["owneriq.net"]},{"name":"Dynamic Yield","categories":["customer-success"],"domains":["dynamicyield.com"]},{"name":"Fort Awesome","categories":["library"],"domains":["fortawesome.com"]},{"name":"Clerk.io ApS","categories":["analytics"],"domains":["clerk.io"]},{"name":"Adyoulike","categories":["ad"],"domains":["adyoulike.com","adyoulike.net","omnitagjs.com"]},{"name":"iAdvize SAS","categories":["customer-success"],"domains":["iadvize.com"]},{"name":"Ecwid","categories":["hosting"],"domains":["d3fi9i0jj23cau.cloudfront.net","d3j0zfs7paavns.cloudfront.net","ecwid.com","shopsettings.com"]},{"name":"issuu","categories":["content"],"domains":["issuu.com","isu.pub"]},{"name":"Effective Measure","categories":["ad"],"domains":["effectivemeasure.net"]},{"name":"Geniee","categories":["ad"],"domains":["cs.gssprt.jp","genieessp.jp","genieesspv.jp","gssprt.jp","href.asia"]},{"name":"Bronto Software","categories":["marketing"],"domains":["bm23.com","bronto.com","brontops.com"]},{"name":"eBay","categories":["ad"],"domains":["ebay.com","ebayimg.com","fetchback.com"]},{"name":"Elastic Ad","categories":["ad"],"domains":["elasticad.net"]},{"name":"PowerReviews","categories":["analytics"],"domains":["powerreviews.com"]},{"name":"Okas Concepts","categories":["utility"],"domains":["okasconcepts.com"]},{"name":"Media Management Technologies","categories":["ad"],"domains":["speedshiftmedia.com"]},{"name":"Blindado","categories":["utility"],"domains":["siteblindado.com"]},{"name":"Nativo","categories":["ad"],"domains":["postrelease.com"]},{"name":"Autopilot","categories":["ad"],"domains":["autopilothq.com"]},{"name":"Picreel","categories":["analytics"],"domains":["pcrl.co","picreel.com"]},{"name":"Celtra","categories":["ad"],"domains":["celtra.com"]},{"name":"UserReport","categories":["analytics"],"domains":["userreport.com"]},{"name":"Adverline Board","company":"Adverline","categories":["ad"],"domains":["adnext.fr","adverline.com"]},{"name":"The ADEX","categories":["ad"],"domains":["theadex.com"]},{"name":"Mather Economics","categories":["analytics"],"domains":["matheranalytics.com"]},{"name":"Decibel Insight","categories":["analytics"],"domains":["decibelinsight.net"]},{"name":"Revcontent","categories":["content"],"domains":["revcontent.com"]},{"name":"LightWidget","categories":["utility"],"domains":["lightwidget.com"]},{"name":"Wishpond Technologies","categories":["marketing"],"domains":["wishpond.com","wishpond.net"]},{"name":"Riskified","categories":["utility"],"domains":["riskified.com"]},{"name":"Kaltura Video Platform","company":"Kaltura","categories":["content"],"domains":["cdnsecakmi.kaltura.com"]},{"name":"TRUSTe","categories":["utility"],"domains":["truste.com"]},{"name":"Navegg","categories":["ad"],"domains":["navdmp.com"]},{"name":"LoopMe","categories":["ad"],"domains":["loopme.biz","loopme.com","loopme.me","vntsm.com"]},{"name":"Weborama","categories":["ad"],"domains":["weborama.com","weborama.fr"]},{"name":"Polar Mobile Group","categories":["ad"],"domains":["mediavoice.com","polarmobile.com"]},{"name":"Interpublic Group","categories":["ad"],"domains":["mbww.com"]},{"name":"Sekindo","categories":["content"],"domains":["sekindo.com"]},{"name":"WebEngage","categories":["customer-success"],"domains":["d23nd6ymopvz52.cloudfront.net","d3701cc9l7v9a6.cloudfront.net","webengage.co","webengage.com"]},{"name":"Cross Pixel Media","categories":["ad"],"domains":["crsspxl.com"]},{"name":"plista","categories":["ad"],"domains":["plista.com"]},{"name":"Kampyle","categories":["analytics"],"domains":["kampyle.com"]},{"name":"Tribal Fusion","company":"Exponential Interactive","categories":["ad"],"domains":["tribalfusion.com"]},{"name":"Gleam","categories":["marketing"],"domains":["gleam.io"]},{"name":"Forensiq","categories":["utility"],"domains":["fqtag.com"]},{"name":"Audience 360","company":"Datapoint Media","categories":["ad"],"domains":["dpmsrv.com"]},{"name":"Flowplayer","categories":["content"],"domains":["flowplayer.org"]},{"name":"Sooqr Search","company":"Sooqr","categories":["utility"],"domains":["sooqr.com"]},{"name":"MaxCDN Enterprise","company":"MaxCDN","categories":["utility"],"domains":["netdna-cdn.com","netdna-ssl.com"]},{"name":"Shopgate","categories":["utility"],"domains":["shopgate.com"]},{"name":"BoldChat","company":"LogMeIn","categories":["customer-success"],"domains":["boldchat.com"]},{"name":"smartclip","categories":["ad"],"domains":["smartclip.net"]},{"name":"rewardStyle.com","categories":["ad"],"domains":["rewardstyle.com"]},{"name":"Chitika","categories":["ad"],"domains":["chitika.net"]},{"name":"WisePops","categories":["utility"],"domains":["wisepops.com"]},{"name":"Monetate","categories":["analytics"],"domains":["monetate.net"]},{"name":"SpotXchange","categories":["ad"],"domains":["spotx.tv","spotxcdn.com","spotxchange.com"]},{"name":"Zanox","categories":["ad"],"domains":["zanox.com","zanox.ws"]},{"name":"SublimeSkinz","categories":["ad"],"domains":["ayads.co"]},{"name":"Adocean","company":"Gemius","categories":["ad"],"domains":["adocean.pl"]},{"name":"Meetrics","categories":["ad"],"domains":["meetrics.net","mxcdn.net","research.de.com"]},{"name":"Booking.com","categories":["content"],"domains":["bstatic.com"]},{"name":"Sparkflow","company":"Intercept Interactive","categories":["ad"],"domains":["sparkflow.net"]},{"name":"Lytics","categories":["ad"],"domains":["lytics.io"]},{"name":"ResponsiveVoice","categories":["other"],"domains":["responsivevoice.org"]},{"name":"Ooyala","categories":["ad"],"domains":["ooyala.com"]},{"name":"Snacktools","categories":["ad"],"domains":["bannersnack.com"]},{"name":"linkpulse","categories":["analytics"],"domains":["lp4.io"]},{"name":"Tencent","categories":["content"],"domains":["qq.com","ywxi.net"]},{"name":"Rocket Fuel","categories":["ad"],"domains":["rfihub.com","rfihub.net","ru4.com"]},{"name":"Adnium","categories":["ad"],"domains":["adnium.com"]},{"name":"Appier","categories":["ad"],"domains":["appier.net"]},{"name":"Stackla PTY","categories":["social"],"domains":["stackla.com"]},{"name":"Hupso Website Analyzer","company":"Hupso","categories":["analytics"],"domains":["hupso.com"]},{"name":"ReadSpeaker","homepage":"https://www.readspeaker.com","categories":["other"],"domains":["sf1-eu.readspeaker.com"]},{"name":"ShopiMind","company":"ShopIMind","categories":["ad"],"domains":["shopimind.com"]},{"name":"DialogTech","categories":["ad"],"domains":["dialogtech.com"]},{"name":"FoxyCart","categories":["utility"],"domains":["foxycart.com"]},{"name":"Neodata","categories":["ad"],"domains":["neodatagroup.com"]},{"name":"WebpageFX","categories":["ad"],"domains":["leadmanagerfx.com"]},{"name":"Smart Insight Tracking","company":"Emarsys","categories":["analytics"],"domains":["scarabresearch.com"]},{"name":"Feedbackify","company":"InsideMetrics","categories":["analytics"],"domains":["feedbackify.com"]},{"name":"Survicate","categories":["analytics"],"domains":["survicate.com"]},{"name":"Aggregate Knowledge","company":"Neustar","categories":["ad"],"domains":["agkn.com"]},{"name":"Exponea","categories":["analytics"],"domains":["exponea.com"]},{"name":"eXelate","categories":["ad"],"domains":["exelator.com"]},{"name":"Adition","homepage":"https://www.adition.com","categories":["ad"],"domains":["dsp.adfarm1.adition.com"]},{"name":"Highcharts","categories":["utility"],"domains":["highcharts.com"]},{"name":"FirstImpression","categories":["ad"],"domains":["firstimpression.io"]},{"name":"LiveHelpNow","categories":["customer-success"],"domains":["livehelpnow.net"]},{"name":"SearchSpring","categories":["utility"],"domains":["searchspring.net"]},{"name":"Pardot","categories":["marketing"],"domains":["pardot.com"]},{"name":"JustPremium Ads","company":"JustPremium","categories":["ad"],"domains":["justpremium.com"]},{"name":"DMD Marketing","homepage":"https://www.dmdconnects.com/","categories":["ad"],"domains":["medtargetsystem.com"]},{"name":"The Hut Group","categories":["content"],"domains":["thcdn.com"]},{"name":"Cloudinary","categories":["content"],"domains":["cloudinary.com"]},{"name":"Technorati","company":"Synacor","categories":["ad"],"domains":["technoratimedia.com"]},{"name":"Github","categories":["utility"],"domains":["github.com","github.io","raw.githubusercontent.com"]},{"name":"Bootstrap Chinese network","categories":["library"],"domains":["bootcss.com"]},{"name":"Typepad","categories":["hosting"],"domains":["typepad.com"]},{"name":"Keywee","categories":["ad"],"domains":["keywee.co"]},{"name":"Skype","categories":["other"],"domains":["skype.com"]},{"name":"Opta","company":"Perform Group","categories":["content"],"domains":["opta.net"]},{"name":"Livefyre","categories":["content"],"domains":["fyre.co","livefyre.com"]},{"name":"ReTargeter","categories":["ad"],"domains":["retargeter.com"]},{"name":"TruConversion","categories":["analytics"],"domains":["truconversion.com"]},{"name":"fifty-five","categories":["ad"],"domains":["55labs.com"]},{"name":"Time","categories":["content"],"domains":["timeinc.net"]},{"name":"Pixlee","categories":["social"],"domains":["pixlee.com"]},{"name":"Reevoo","categories":["analytics"],"domains":["reevoo.com"]},{"name":"Accordant Media","categories":["ad"],"domains":["segment.a3cloud.net"]},{"name":"Evergage","categories":["analytics"],"domains":["evergage.com"]},{"name":"Exponential Interactive","categories":["ad"],"domains":["exponential.com"]},{"name":"Best Of Media S.A.","categories":["content"],"domains":["servebom.com"]},{"name":"Steelhouse","categories":["ad"],"domains":["steelhousemedia.com"]},{"name":"Dailymotion","categories":["content"],"domains":["ad.pxlad.io","dm.gg","dmcdn.net","sublimevideo.net","www.dailymotion.com"]},{"name":"TripleLift","categories":["ad"],"domains":["3lift.com"]},{"name":"DemandBase","categories":["marketing"],"domains":["demandbase.com"]},{"name":"One by AOL","company":"AOL","categories":["ad"],"domains":["adtech.de","adtechjp.com"]},{"name":"Adkontekst","categories":["ad"],"domains":["adkontekst.pl"]},{"name":"Profitshare","categories":["ad"],"domains":["profitshare.ro"]},{"name":"Drip","company":"The Numa Group","categories":["ad"],"domains":["getdrip.com"]},{"name":"Ghostery Enterprise","company":"Ghostery","categories":["marketing"],"domains":["betrad.com"]},{"name":"Socialphotos","categories":["social"],"domains":["slpht.com"]},{"name":"SoundCloud","homepage":"https://www.soundcloud.com/","categories":["content"],"domains":["widget.sndcdn.com","soundcloud.com","stratus.sc"]},{"name":"Rackspace","categories":["hosting"],"domains":["rackcdn.com","rackspacecloud.com","raxcdn.com","websitetestlink.com"]},{"name":"NetAffiliation","company":"Kwanco","categories":["ad"],"domains":["metaffiliation.com"]},{"name":"CPEx","categories":["content"],"domains":["cpex.cz"]},{"name":"Sweet Tooth","categories":["ad"],"domains":["sweettooth.io"]},{"name":"Playbuzz","categories":["hosting"],"domains":["playbuzz.com"]},{"name":"Civic","categories":["hosting"],"domains":["civiccomputing.com"]},{"name":"Sajari Pty","categories":["utility"],"domains":["sajari.com"]},{"name":"PerimeterX Bot Defender","company":"PerimeterX","categories":["utility"],"domains":["perimeterx.net","pxi.pub"]},{"name":"Marketplace Web Service","company":"Amazon","categories":["other"],"domains":["ssl-images-amazon.com"]},{"name":"Ambassador","categories":["ad"],"domains":["getambassador.com"]},{"name":"Pictela (AOL)","categories":["analytics"],"domains":["pictela.net"]},{"name":"AdSniper","categories":["ad"],"domains":["adsniper.ru","sniperlog.ru"]},{"name":"Adscale","categories":["ad"],"domains":["adscale.de"]},{"name":"Signyfyd","categories":["utility"],"domains":["signifyd.com"]},{"name":"Connatix","categories":["ad"],"domains":["connatix.com"]},{"name":"Zarget","categories":["analytics"],"domains":["zarget.com"]},{"name":"Woopra","categories":["analytics"],"domains":["woopra.com"]},{"name":"Infinity Tracking","categories":["analytics"],"domains":["infinity-tracking.net"]},{"name":"ResponseTap","categories":["analytics"],"domains":["adinsight.com","responsetap.com"]},{"name":"Sirv","categories":["other"],"domains":["sirv.com"]},{"name":"Salesforce.com","categories":["ad"],"domains":["force.com","salesforce.com","secure.force.com"]},{"name":"Conversant Tag Manager","company":"Conversant","categories":["tag-manager"],"domains":["mplxtms.com"]},{"name":"Petametrics","categories":["analytics"],"domains":["petametrics.com"]},{"name":"BannerFlow","company":"Nordic Factory Solutions","categories":["ad"],"domains":["bannerflow.com"]},{"name":"Pixalate","categories":["utility"],"domains":["adrta.com"]},{"name":"reEmbed","categories":["other"],"domains":["reembed.com"]},{"name":"FreakOut","categories":["ad"],"domains":["fout.jp"]},{"name":"VoiceFive","categories":["analytics"],"domains":["voicefive.com"]},{"name":"Impact Radius","categories":["ad"],"domains":["7eer.net","a.impactradius-go.com","d3cxv97fi8q177.cloudfront.net","impactradius-event.com","microsoft-uk.evyy.net","ojrq.net"]},{"name":"AWeber","categories":["ad"],"domains":["aweber.com"]},{"name":"Simpli.fi","categories":["ad"],"domains":["simpli.fi"]},{"name":"Unruly Media","categories":["ad"],"domains":["unrulymedia.com"]},{"name":"Hola Networks","categories":["other"],"domains":["h-cdn.com"]},{"name":"Customer.io","categories":["ad"],"domains":["customer.io"]},{"name":"Delta Projects AB","categories":["ad"],"domains":["de17a.com"]},{"name":"Advance Magazine Group","categories":["content"],"domains":["condenast.co.uk","condenastdigital.com","condenet.com"]},{"name":"Key CDN","categories":["utility"],"domains":["kxcdn.com"]},{"name":"ThreatMetrix","categories":["utility"],"domains":["online-metrix.net"]},{"name":"Adtech (AOL)","categories":["ad"],"domains":["adtechus.com"]},{"name":"News","categories":["social"],"domains":["news-static.com","news.com.au","newsanalytics.com.au","newsapi.com.au","newscdn.com.au","newsdata.com.au","newsdiscover.com.au"]},{"name":"AvantLink","categories":["ad"],"domains":["avmws.com"]},{"name":"CyberSource (Visa)","categories":["utility"],"domains":["authorize.net"]},{"name":"Vibrant Media","categories":["ad"],"domains":["intellitxt.com","picadmedia.com"]},{"name":"FLXone","company":"Teradata","categories":["ad"],"domains":["d2hlpp31teaww3.cloudfront.net","flx1.com","pangolin.blue"]},{"name":"Adobe Marketing Cloud","company":"Adobe Systems","categories":["ad"],"domains":["adobetag.com"]},{"name":"WebSpectator","categories":["ad"],"domains":["webspectator.com"]},{"name":"Intercept Interactive","categories":["ad"],"domains":["undertone.com"]},{"name":"Simplicity Marketing","categories":["ad"],"domains":["flashtalking.com"]},{"name":"AdRiver","categories":["ad"],"domains":["adriver.ru"]},{"name":"Mobify","categories":["utility"],"domains":["mobify.com","mobify.net"]},{"name":"Apester","categories":["analytics"],"domains":["apester.com","qmerce.com"]},{"name":"Covert Pics","categories":["content"],"domains":["covet.pics"]},{"name":"CleverDATA","categories":["ad"],"domains":["1dmp.io"]},{"name":"SecuredVisit","company":"4Cite Marketing","categories":["ad"],"domains":["securedvisit.com"]},{"name":"SlimCut Media Outstream","company":"SlimCut Media","categories":["ad"],"domains":["freeskreen.com"]},{"name":"Exactag","categories":["ad"],"domains":["exactag.com"]},{"name":"Postcode Anywhere (Holdings)","categories":["utility"],"domains":["postcodeanywhere.co.uk"]},{"name":"Flickr","categories":["content"],"domains":["flickr.com","staticflickr.com"]},{"name":"bRealTime","categories":["ad"],"domains":["brealtime.com"]},{"name":"Research Online","company":"Skills Development Scotland","categories":["content"],"domains":["www.researchonline.org.uk"]},{"name":"Swoop","categories":["ad"],"domains":["swoop.com"]},{"name":"Widespace","homepage":"https://www.widespace.com","categories":["ad"],"domains":["sync.widespace.com"]},{"name":"Eyeota","categories":["ad"],"domains":["eyeota.net"]},{"name":"Pagefair","categories":["ad"],"domains":["pagefair.com","pagefair.net"]},{"name":"Wow Analytics","categories":["analytics"],"domains":["wowanalytics.co.uk"]},{"name":"Rakuten LinkShare","company":"Rakuten","categories":["ad"],"domains":["linksynergy.com"]},{"name":"Transifex","categories":["utility"],"domains":["transifex.com"]},{"name":"Ziff Davis Tech","categories":["ad"],"domains":["adziff.com","zdbb.net"]},{"name":"Betgenius","company":"Genius Sports","categories":["content"],"domains":["connextra.com"]},{"name":"AIR.TV","categories":["ad"],"domains":["air.tv"]},{"name":"MaxMind","categories":["utility"],"domains":["maxmind.com"]},{"name":"Expedia","categories":["content"],"domains":["travel-assets.com","trvl-media.com","www.trvl-px.com","www.uciservice.com"]},{"name":"ContextWeb","categories":["ad"],"domains":["contextweb.com"]},{"name":"Pusher","homepage":"https://pusher.com/","categories":["utility"],"domains":["stats.pusher.com","pusherapp.com"]},{"name":"LeasdBoxer","company":"LeadBoxer","categories":["ad"],"domains":["leadboxer.com"]},{"name":"SkyScanner","categories":["content"],"domains":["api.skyscanner.net"]},{"name":"WalkMe","categories":["customer-success"],"domains":["walkme.com"]},{"name":"AdTrue","company":"FPT AdTrue","categories":["ad"],"domains":["adtrue.com"]},{"name":"Resonance Insights","categories":["analytics"],"domains":["res-x.com"]},{"name":"Hull.js","categories":["utility"],"domains":["hull.io","hullapp.io"]},{"name":"Video Media Groep","categories":["ad"],"domains":["inpagevideo.nl","vmg.host"]},{"name":"MonetizeMore","categories":["ad"],"domains":["m2.ai"]},{"name":"Fanplayr","categories":["analytics"],"domains":["d38nbbai6u794i.cloudfront.net","fanplayr.com"]},{"name":"Onet","categories":["ad"],"domains":["onet.pl"]},{"name":"Boomtrain","categories":["ad"],"domains":["boomtrain.com","boomtrain.net"]},{"name":"Proper Media","categories":["content"],"domains":["proper.io"]},{"name":"StumbleUpon","categories":["content"],"domains":["stumble-upon.com","stumbleupon.com"]},{"name":"Zmags","categories":["marketing"],"domains":["zmags.com"]},{"name":"Vee24","categories":["customer-success"],"domains":["vee24.com"]},{"name":"Sailthru","categories":["analytics"],"domains":["sail-horizon.com","sail-personalize.com","sail-track.com"]},{"name":"Klevu Search","company":"Klevu","categories":["utility"],"domains":["klevu.com"]},{"name":"Cedato","categories":["ad"],"domains":["algovid.com","vdoserv.com"]},{"name":"Trip Advisor","categories":["content"],"domains":["tacdn.com","tripadvisor.co.uk","tripadvisor.com","viator.com","www.jscache.com","www.tamgrt.com"]},{"name":"Captify Media","categories":["ad"],"domains":["cpx.to"]},{"name":"Yottaa","categories":["hosting"],"domains":["yottaa.com","yottaa.net"]},{"name":"PERFORM","categories":["content"],"domains":["performgroup.com"]},{"name":"Vindico","company":"Viant","categories":["ad"],"domains":["vindicosuite.com"]},{"name":"Snack Media","categories":["content"],"domains":["snack-media.com"]},{"name":"FuelX","categories":["ad"],"domains":["fuelx.com"]},{"name":"OnScroll","categories":["ad"],"domains":["onscroll.com"]},{"name":"Alliance for Audited Media","categories":["ad"],"domains":["aamsitecertifier.com"]},{"name":"ShopRunner","categories":["content"],"domains":["s-9.us","shoprunner.com"]},{"name":"Janrain","categories":["analytics"],"domains":["d3hmp0045zy3cs.cloudfront.net","janrain.com","janrainbackplane.com","rpxnow.com"]},{"name":"AliveChat","company":"AYU Technology Solutions","categories":["customer-success"],"domains":["websitealive.com","websitealive7.com"]},{"name":"SpringServer","categories":["ad"],"domains":["springserve.com"]},{"name":"Global-e","categories":["hosting"],"domains":["global-e.com"]},{"name":"cloudIQ","categories":["analytics"],"domains":["cloud-iq.com"]},{"name":"ZEDO","categories":["ad"],"domains":["zedo.com"]},{"name":"Forter","categories":["utility"],"domains":["forter.com"]},{"name":"Silverpop","company":"IBM","categories":["ad"],"domains":["mkt51.net","mkt61.net","mkt912.com","mkt922.com","mkt932.com","mkt941.com","pages01.net","pages02.net","pages03.net","pages04.net","pages05.net"]},{"name":"Polyfill service","company":"Polyfill.io","categories":["other"],"domains":["polyfill.io"]},{"name":"epoq internet services","categories":["analytics"],"domains":["epoq.de"]},{"name":"CDN.net","categories":["utility"],"domains":["uk.cdn-net.com"]},{"name":"Kameleoon","categories":["analytics"],"domains":["kameleoon.com"]},{"name":"Council ad Network","categories":["ad"],"domains":["counciladvertising.net"]},{"name":"Oracle Recommendations On Demand","company":"Oracle","categories":["analytics"],"domains":["atgsvcs.com"]},{"name":"Viacom","categories":["content"],"domains":["mtvnservices.com"]},{"name":"Optimove","company":"Mobius Solutions","categories":["analytics"],"domains":["optimove.net"]},{"name":"Cookie Reports","categories":["utility"],"domains":["cookiereports.com"]},{"name":"Storygize","categories":["ad"],"domains":["www.storygize.net"]},{"name":"Revolver Maps","categories":["analytics"],"domains":["revolvermaps.com"]},{"name":"Reactful","categories":["analytics"],"domains":["reactful.com"]},{"name":"NaviStone","categories":["ad"],"domains":["murdoog.com"]},{"name":"Vertical Mass","categories":["ad"],"domains":["vmweb.net"]},{"name":"Conversant","categories":["analytics"],"domains":["dotomi.com","dtmpub.com","emjcd.com","fastclick.net","mediaplex.com","www.tqlkg.com"]},{"name":"BlueCava","categories":["ad"],"domains":["bluecava.com"]},{"name":"VidPulse","categories":["analytics"],"domains":["vidpulse.com"]},{"name":"LoginRadius","categories":["social"],"domains":["loginradius.com"]},{"name":"Byside","homepage":"http://www.byside.com","categories":["analytics"],"domains":["byce2.byside.com","wce2.byside.com"]},{"name":"MailPlus","categories":["ad"],"domains":["mailplus.nl"]},{"name":"Touch Commerce","categories":["customer-success"],"domains":["inq.com","touchcommerce.com"]},{"name":"Netlify","homepage":"https://www.netlify.com/","categories":["utility"],"domains":["netlify.com","cloud.netlifyusercontent.com"]},{"name":"Kargo","categories":["marketing"],"domains":["kargo.com"]},{"name":"SurveyMonkey","categories":["analytics"],"domains":["surveymonkey.com"]},{"name":"User Replay","categories":["analytics"],"domains":["userreplay.net"]},{"name":"Catchpoint","homepage":"https://www.catchpoint.com/","categories":["analytics"],"domains":["3gl.net"]},{"name":"Conversio","categories":["ad"],"domains":["conversio.com"]},{"name":"AdvertServe","categories":["ad"],"domains":["advertserve.com"]},{"name":"PrintFriendly","categories":["utility"],"domains":["printfriendly.com"]},{"name":"Mopinion","categories":["analytics"],"domains":["mopinion.com"]},{"name":"Barilliance","categories":["analytics"],"domains":["barilliance.net","dn3y71tq7jf07.cloudfront.net"]},{"name":"Flockler","categories":["ad"],"domains":["flockler.com"]},{"name":"Attribution","categories":["ad"],"domains":["attributionapp.com"]},{"name":"Vergic AB","categories":["customer-success"],"domains":["psplugin.com"]},{"name":"CANDDi","company":"Campaign and Digital Intelligence","categories":["ad"],"domains":["canddi.com"]},{"name":"PebblePost","categories":["ad"],"domains":["pbbl.co"]},{"name":"Braintree Payments","company":"Paypal","categories":["utility"],"domains":["braintreegateway.com"]},{"name":"InSkin Media","categories":["ad"],"domains":["inskinad.com","inskinmedia.com"]},{"name":"StreamRail","categories":["ad"],"domains":["streamrail.com","streamrail.net"]},{"name":"Site24x7 Real User Monitoring","company":"Site24x7","categories":["analytics"],"domains":["site24x7rum.com"]},{"name":"YoYo","categories":["utility"],"domains":["goadservices.com"]},{"name":"Adunity","categories":["ad"],"domains":["adunity.com"]},{"name":"PlayAd Media Group","categories":["ad"],"domains":["youplay.se"]},{"name":"BuySellAds","categories":["ad"],"domains":["buysellads.com"]},{"name":"Moovweb","categories":["utility"],"domains":["moovweb.net"]},{"name":"Bookatable","categories":["content"],"domains":["bookatable.com","livebookings.com"]},{"name":"Raygun","categories":["utility"],"domains":["raygun.io"]},{"name":"Sociomantic Labs","company":"DunnHumby","categories":["ad"],"domains":["sociomantic.com"]},{"name":"Borderfree","company":"pitney bowes","categories":["utility"],"domains":["borderfree.com","fiftyone.com"]},{"name":"Dynamic Converter","categories":["utility"],"domains":["dynamicconverter.com"]},{"name":"C3 Metrics","categories":["analytics"],"domains":["c3tag.com"]},{"name":"eGain","categories":["analytics"],"domains":["analytics-egain.com","egain.com"]},{"name":"TechTarget","categories":["content"],"domains":["techtarget.com","ttgtmedia.com"]},{"name":"Adobe Scene7","company":"Adobe Systems","categories":["content"],"domains":["everestads.net","everestjs.net","scene7.com","wwwimages.adobe.com"]},{"name":"HotelsCombined","categories":["content"],"domains":["datahc.com"]},{"name":"StackAdapt","categories":["ad"],"domains":["stackadapt.com"]},{"name":"The Publisher Desk","categories":["ad"],"domains":["206ads.com","publisherdesk.com"]},{"name":"Ekm Systems","categories":["analytics"],"domains":["ekmpinpoint.co.uk","ekmsecure.com","globalstats.ekmsecure.com"]},{"name":"DistroScale","categories":["ad"],"domains":["jsrdn.com"]},{"name":"Knight Lab","company":"Northwestern University","categories":["utility"],"domains":["knightlab.com"]},{"name":"Vergic Engage Platform","company":"Vergic","categories":["customer-success"],"domains":["vergic.com"]},{"name":"AdCurve","categories":["ad"],"domains":["shop2market.com"]},{"name":"StackExchange","categories":["social"],"domains":["sstatic.net"]},{"name":"MathJax","categories":["utility"],"domains":["mathjax.org"]},{"name":"RebelMouse","categories":["ad"],"domains":["rbl.ms","www.rebelmouse.com"]},{"name":"ShopStorm","categories":["utility"],"domains":["shopstorm.com"]},{"name":"Ad6Media","categories":["ad"],"domains":["ad6media.fr"]},{"name":"OCSP","company":"GoDaddy","categories":["utility"],"domains":["ocsp.godaddy.com","seal.godaddy.com"]},{"name":"Bluecore","categories":["analytics"],"domains":["www.bluecore.com"]},{"name":"Cachefly","categories":["utility"],"domains":["cachefly.net"]},{"name":"Nanorep","company":"Nanorep Technologies","categories":["customer-success"],"domains":["nanorep.com"]},{"name":"AdSpruce","categories":["ad"],"domains":["adspruce.com"]},{"name":"content.ad","categories":["ad"],"domains":["content.ad"]},{"name":"Improve Digital","categories":["ad"],"domains":["360yield.com"]},{"name":"Fastest Forward","categories":["analytics"],"domains":["gaug.es"]},{"name":"RichRelevance","categories":["analytics"],"domains":["richrelevance.com"]},{"name":"ARM","categories":["analytics"],"domains":["tag4arm.com"]},{"name":"Webtrends","categories":["analytics"],"domains":["d1q62gfb8siqnm.cloudfront.net","webtrends.com","webtrendslive.com"]},{"name":"Click4Assistance","categories":["customer-success"],"domains":["click4assistance.co.uk"]},{"name":"Realytics","categories":["analytics"],"domains":["dcniko1cv0rz.cloudfront.net","realytics.net"]},{"name":"Xaxis","homepage":"https://www.xaxis.com/","categories":["ad"],"domains":["t.mookie1.com","247realmedia.com","gmads.net","odr.mookie1.com"]},{"name":"UPS i-parcel","company":"UPS","categories":["other"],"domains":["i-parcel.com"]},{"name":"Qualtrics","categories":["analytics"],"domains":["qualtrics.com"]},{"name":"Adobe Test & Target","company":"Adobe Systems","categories":["analytics"],"domains":["tt.omtrdc.net"]}];
-},{}],172:[function(require,module,exports){
+},{"events":108,"inherits":113,"readable-stream/duplex.js":146,"readable-stream/passthrough.js":156,"readable-stream/readable.js":157,"readable-stream/transform.js":158,"readable-stream/writable.js":159}],168:[function(require,module,exports){
+module.exports=[{"name":"Google Analytics","company":"Google","homepage":"https://www.google.com/analytics/analytics/","categories":["analytics"],"domains":["*.google-analytics.com","*.urchin.com"],"examples":["www.google-analytics.com","ssl.google-analytics.com"]},{"name":"Facebook","homepage":"https://www.facebook.com","categories":["social"],"domains":["*.atlassbx.com","*.facebook.com","*.fbsbx.com","fbcdn-photos-e-a.akamaihd.net","*.facebook.net","*.fbcdn.net"],"examples":["www.facebook.com","connect.facebook.net","staticxx.facebook.com","static.xx.fbcdn.net","m.facebook.com","an.facebook.com","platform-lookaside.fbsbx.com"]},{"name":"Google CDN","company":"Google","homepage":"https://developers.google.com/speed/libraries/","categories":["cdn"],"domains":["ajax.googleapis.com","commondatastorage.googleapis.com","www.gstatic.com"]},{"name":"Google/Doubleclick Ads","company":"Google","homepage":"https://www.doubleclickbygoogle.com/","categories":["ad"],"domains":["adservice.google.com","adservice.google.com.au","adservice.google.com.sg","adservice.google.com.br","adservice.google.com.ua","adservice.google.co.uk","adservice.google.co.jp","adservice.google.co.in","adservice.google.co.kr","adservice.google.co.id","adservice.google.co.nz","adservice.google.ie","adservice.google.se","adservice.google.de","adservice.google.ca","adservice.google.be","adservice.google.es","adservice.google.ch","adservice.google.fr","adservice.google.nl","*.googleadservices.com","*.googlesyndication.com","*.googletagservices.com","*.2mdn.net","*.doubleclick.net"],"examples":["pagead2.googlesyndication.com","tpc.googlesyndication.com","ade.googlesyndication.com","googleads.g.doubleclick.net","googleads4.g.doubleclick.net","securepubads.g.doubleclick.net","pubads.g.doubleclick.net","static.doubleclick.net","cm.g.doubleclick.net","bid.g.doubleclick.net","s0.2mdn.net","stats.g.doubleclick.net","survey.g.doubleclick.net","fls.doubleclick.net","ad.doubleclick.net","www.googleadservices.com","https://www.googletagservices.com/tag/js/gpt.js"]},{"name":"Google Tag Manager","company":"Google","homepage":"https://marketingplatform.google.com/about/tag-manager/","categories":["tag-manager"],"domains":["*.googletagmanager.com"],"examples":["www.googletagmanager.com"]},{"name":"Other Google APIs/SDKs","company":"Google","homepage":"https://developers.google.com/apis-explorer/#p/","categories":["utility"],"domains":["accounts.google.com","apis.google.com","calendar.google.com","clients2.google.com","cse.google.com","news.google.com","pay.google.com","payments.google.com","play.google.com","smartlock.google.com","www.google.com","www.google.de","www.google.co.jp","www.google.com.au","www.google.co.uk","www.google.ie","www.google.com.sg","www.google.co.in","www.google.com.br","www.google.ca","www.google.co.kr","www.google.co.nz","www.google.co.id","www.google.fr","www.google.be","www.google.com.ua","www.google.nl","www.google.ru","www.google.se","imasdk.googleapis.com","storage.googleapis.com","translate.googleapis.com","lh3.googleusercontent.com","csi.gstatic.com"]},{"name":"YouTube","homepage":"https://youtube.com","categories":["video"],"domains":["*.ggpht.com","*.youtube-nocookie.com","*.youtube.com","*.ytimg.com"],"examples":["www.youtube.com","s.ytimg.com","yt3.ggpht.com","img.youtube.com","fcmatch.youtube.com"]},{"name":"Google Maps","company":"Google","homepage":"https://www.google.com/maps","categories":["utility"],"domains":["maps.google.com","maps-api-ssl.google.com","maps.googleapis.com","mts.googleapis.com","maps.gstatic.com"]},{"name":"Twitter","homepage":"https://twitter.com","categories":["social"],"domains":["*.vine.co","*.twimg.com","*.twitpic.com","platform.twitter.com","syndication.twitter.com"],"examples":["cdn.syndication.twimg.com","abs.twimg.com","pbs.twimg.com"]},{"name":"Yandex Metrica","company":"Yandex","homepage":"https://metrica.yandex.com/about?","categories":["analytics"],"domains":["d31j93rd8oukbv.cloudfront.net","mc.yandex.ru"]},{"name":"jQuery CDN","homepage":"https://code.jquery.com/","categories":["cdn"],"domains":["*.jquery.com"],"examples":["code.jquery.com"]},{"name":"Hotjar","homepage":"https://www.hotjar.com/","categories":["analytics"],"domains":["*.hotjar.com","*.hotjar.io"],"examples":["script.hotjar.com","static.hotjar.com","in.hotjar.com","vc.hotjar.io","vars.hotjar.com"]},{"name":"AddThis","homepage":"http://www.addthis.com/","categories":["social"],"domains":["*.addthis.com","*.addthiscdn.com","*.addthisedge.com"],"examples":["s7.addthis.com","r.dlx.addthis.com","su.addthis.com","x.dlx.addthis.com"]},{"name":"WordPress","company":"Automattic","homepage":"https://wp.com/","categories":["hosting"],"domains":["*.wordpress.com","s0.wp.com","s2.wp.com","*.w.org","c0.wp.com","s1.wp.com","widgets.wp.com"],"examples":["s.w.org"]},{"name":"Cloudflare CDN","homepage":"https://cdnjs.com/","categories":["cdn"],"domains":["amp.cloudflare.com","cdnjs.cloudflare.com"]},{"name":"Shopify","homepage":"https://www.shopify.com/","categories":["hosting"],"domains":["*.shopify.com","*.shopifyapps.com","*.shopifycdn.com"],"examples":["cdn.shopify.com","productreviews.shopifycdn.com"]},{"name":"ZenDesk","homepage":"https://zendesk.com/","categories":["customer-success"],"domains":["*.zdassets.com","*.zendesk.com","*.zopim.com"],"examples":["assets.zendesk.com","static.zdassets.com","v2.zopim.com"]},{"name":"Criteo","homepage":"https://www.criteo.com/","categories":["ad"],"domains":["*.criteo.com","*.emailretargeting.com","*.criteo.net"],"examples":["static.criteo.net","bidder.criteo.com","dis.criteo.com","gum.criteo.com","sslwidget.criteo.com","dis.us.criteo.com"]},{"name":"Pubmatic","homepage":"https://pubmatic.com/","categories":["ad"],"domains":["*.pubmatic.com"],"examples":["image6.pubmatic.com","ads.pubmatic.com","image2.pubmatic.com","simage2.pubmatic.com","image4.pubmatic.com","simage4.pubmatic.com","image5.pubmatic.com","hbopenbid.pubmatic.com"]},{"name":"Tawk.to","homepage":"https://www.tawk.to/","categories":["customer-success"],"domains":["*.tawk.to"],"examples":["embed.tawk.to"]},{"name":"AMP","homepage":"https://amp.dev/","categories":["content"],"domains":["*.ampproject.org"],"examples":["cdn.ampproject.org"]},{"name":"Wix","homepage":"https://www.wix.com/","categories":["hosting"],"domains":["*.parastorage.com","*.wix.com","*.wixstatic.com","*.wixapps.net"],"examples":["static.parastorage.com","static.wixstatic.com","www.wix.com","instagram.codev.wixapps.net"]},{"name":"Squarespace","homepage":"https://www.squarespace.com/","categories":["hosting"],"domains":["*.squarespace.com"],"examples":["static.squarespace.com","static1.squarespace.com"]},{"name":"Amazon Web Services","homepage":"https://aws.amazon.com/s3/","categories":["other"],"domains":["*.amazon.com","*.amazonaws.com","*.amazonwebapps.com","*.amazonwebservices.com","*.elasticbeanstalk.com","*.images-amazon.com","*.amazon.co.uk"],"examples":["s3.amazonaws.com","us-east-1.amazonaws.com","api-cdn.amazon.com","ecx.images-amazon.com","ws.amazon.co.uk"]},{"name":"ShareThis","homepage":"https://www.sharethis.com/","categories":["social"],"domains":["*.sharethis.com"],"examples":["w.sharethis.com","ws.sharethis.com","t.sharethis.com"]},{"name":"Vimeo","homepage":"http://vimeo.com/","categories":["video"],"domains":["*.vimeo.com","*.vimeocdn.com"],"examples":["f.vimeocdn.com","player.vimeo.com","i.vimeocdn.com"]},{"name":"JSDelivr CDN","homepage":"https://www.jsdelivr.com/","categories":["cdn"],"domains":["*.jsdelivr.net"],"examples":["cdn.jsdelivr.net"]},{"name":"Adobe Tag Manager","company":"Adobe","homepage":"https://www.adobe.com/experience-platform/","categories":["tag-manager"],"domains":["*.adobedtm.com","*.demdex.net","*.everesttech.net"],"examples":["assets.adobedtm.com","sync-tm.everesttech.net","cm.everesttech.net"]},{"name":"Jivochat","homepage":"https://www.jivochat.com/","categories":["customer-success"],"domains":["*.jivosite.com"],"examples":["cdn-ca.jivosite.com","code.jivosite.com"]},{"name":"PIXNET","homepage":"https://www.pixnet.net/","categories":["social"],"domains":["*.pixfs.net"],"examples":["front.pixfs.net","falcon-asset.pixfs.net","pixgame-asset.pixfs.net"]},{"name":"Yandex Share","company":"Yandex","homepage":"https://yastatic.net/share2/share.js","categories":["social"],"domains":["*.yastatic.net"]},{"name":"Scorecard Research","homepage":"https://www.scorecardresearch.com/","categories":["ad"],"domains":["*.scorecardresearch.com"],"examples":["sb.scorecardresearch.com","sa.scorecardresearch.com","b.scorecardresearch.com"]},{"name":"Rubicon Project","homepage":"https://rubiconproject.com/","categories":["ad"],"domains":["*.chango.com","*.fimserve.com","*.rubiconproject.com"],"examples":["pixel.rubiconproject.com","fastlane.rubiconproject.com","secure-assets.rubiconproject.com","eus.rubiconproject.com","pixel-us-east.rubiconproject.com","token.rubiconproject.com","ads.rubiconproject.com"]},{"name":"FontAwesome CDN","homepage":"https://fontawesome.com/","categories":["cdn"],"domains":["*.fontawesome.com"],"examples":["use.fontawesome.com"]},{"name":"Cloudflare","homepage":"https://www.cloudflare.com/website-optimization/","categories":["utility"],"domains":["ajax.cloudflare.com"]},{"name":"Blogger","homepage":"http://www.blogger.com/","categories":["hosting"],"domains":["*.blogblog.com","*.blogger.com","*.blogspot.com","images-blogger-opensocial.googleusercontent.com"],"examples":["1.bp.blogspot.com","www.blogger.com"]},{"name":"Salesforce","homepage":"https://www.salesforce.com/products/marketing-cloud/","categories":["analytics"],"domains":["*.krxd.net"],"examples":["cdn.krxd.net","beacon.krxd.net","consumer.krxd.net","usermatch.krxd.net"]},{"name":"Yandex Ads","company":"Yandex","homepage":"https://yandex.com/adv/","categories":["ad"],"domains":["an.yandex.ru"]},{"name":"Tynt","company":"33 Across","categories":["ad"],"domains":["*.tynt.com"]},{"name":"Yandex APIs","company":"Yandex","homepage":"https://yandex.ru/","categories":["utility"],"domains":["api-maps.yandex.ru","money.yandex.ru"]},{"name":"Micropat","categories":["social"],"domains":["*.addtoany.com"]},{"name":"Hubspot","homepage":"https://hubspot.com/","categories":["marketing"],"domains":["*.hs-scripts.com","*.hubspot.com","*.leadin.com","*.hs-analytics.net","*.hscollectedforms.net","*.hscta.net","*.hsforms.net","*.hsleadflows.net","*.hsstatic.net","*.hubspot.net"],"examples":["forms.hubspot.com","js.hsforms.net","js.hs-analytics.net","js.leadin.com"]},{"name":"Sumo","homepage":"https://sumo.com/","categories":["marketing"],"domains":["*.sumo.com","*.sumome.com","sumo.b-cdn.net"],"examples":["sumo.b-cdn.net","load.sumo.com","load.sumome.com"]},{"name":"Beeketing","homepage":"https://beeketing.com/","categories":["marketing"],"domains":["*.beeketing.com"],"examples":["sdk-cdn.beeketing.com","sdk.beeketing.com"]},{"name":"Mailchimp","homepage":"https://mailchimp.com/","categories":["marketing"],"domains":["*.chimpstatic.com","*.list-manage.com","*.mailchimp.com"],"examples":["downloads.mailchimp.com"]},{"name":"Media.net","homepage":"https://www.media.net/","categories":["ad"],"domains":["*.media.net","*.mnet-ad.net"],"examples":["contextual.media.net","cdnwest-xch.media.net","hbx.media.net","cs.media.net","hblg.media.net"]},{"name":"Skimbit","categories":["ad"],"domains":["*.redirectingat.com","*.skimresources.com","*.skimresources.net"]},{"name":"Moat","homepage":"https://moat.com/","categories":["ad"],"domains":["*.moatads.com","*.moatpixel.com"],"examples":["z.moatads.com","px.moatads.com","geo.moatads.com","sejs.moatads.com","mb.moatads.com","v4.moatads.com"]},{"name":"AppNexus","homepage":"https://www.appnexus.com/","categories":["ad"],"domains":["*.adnxs.com","*.ctasnet.com"],"examples":["acdn.adnxs.com","secure.adnxs.com","ib.adnxs.com","sharethrough.adnxs.com","cdn.adnxs.com","vcdn.adnxs.com"]},{"name":"VK","homepage":"https://vk.com/","categories":["social"],"domains":["*.vk.com"]},{"name":"LiveChat","homepage":"https://www.livechatinc.com/","categories":["customer-success"],"domains":["*.livechatinc.com"],"examples":["cdn.livechatinc.com","secure.livechatinc.com"]},{"name":"OneSignal","homepage":"https://onesignal.com/","categories":["utility"],"domains":["*.onesignal.com"],"examples":["cdn.onesignal.com","https://onesignal.com/api/v1/sync/"]},{"name":"WordAds","company":"Automattic","homepage":"https://wordads.co/","categories":["ad"],"domains":["*.pubmine.com"],"examples":["s.pubmine.com"]},{"name":"Integral Ad Science","homepage":"https://integralads.com/uk/","categories":["ad"],"domains":["*.adsafeprotected.com","*.iasds01.com"],"examples":["pixel.adsafeprotected.com","static.adsafeprotected.com","fw.adsafeprotected.com","cdn.adsafeprotected.com","dt.adsafeprotected.com"]},{"name":"Amazon Ads","homepage":"https://ad.amazon.com/","categories":["ad"],"domains":["*.amazon-adsystem.com"],"examples":["s.amazon-adsystem.com","c.amazon-adsystem.com","aax.amazon-adsystem.com","z-na.amazon-adsystem.com","fls-na.amazon-adsystem.com","aax-us-east.amazon-adsystem.com","ir-na.amazon-adsystem.com"]},{"name":"Yahoo!","homepage":"https://www.yahoo.com/","categories":["ad"],"domains":["*.bluelithium.com","*.hostingprod.com","*.lexity.com","*.yahoo.com","*.yahooapis.com","*.yimg.com","*.yimg.jp","*.zenfs.com","*.yahoo.net"],"examples":["ads.yahoo.com","analytics.yahoo.com","geo.yahoo.com","udc.yahoo.com","ganon.yahoo.com","ads.yap.yahoo.com"]},{"name":"Hatena Blog","homepage":"https://hatenablog.com/","categories":["hosting"],"domains":["*.st-hatena.com","*.hatena.ne.jp"],"examples":["cdn.blog.st-hatena.com","cdn.pool.st-hatena.com","cdn7.www.st-hatena.com","s.hatena.ne.jp","b.st-hatena.com"]},{"name":"Pinterest","homepage":"https://pinterest.com/","categories":["social"],"domains":["*.pinimg.com","*.pinterest.com"],"examples":["assets.pinterest.com","ct.pinterest.com","log.pinterest.com"]},{"name":"LinkedIn","homepage":"https://www.linkedin.com/","categories":["social"],"domains":["*.bizographics.com","platform.linkedin.com","*.slideshare.com","*.slidesharecdn.com"]},{"name":"Stripe","homepage":"https://stripe.com","categories":["utility"],"domains":["*.stripe.com","*.stripecdn.com","*.stripe.network"],"examples":["m.stripe.network","js.stripe.com"]},{"name":"Taboola","homepage":"https://www.taboola.com/","categories":["ad"],"domains":["*.taboola.com","*.taboolasyndication.com"],"examples":["cdn.taboola.com","trc.taboola.com","vidstat.taboola.com","images.taboola.com"]},{"name":"Weebly","homepage":"https://www.weebly.com/","categories":["hosting"],"domains":["*.editmysite.com"]},{"name":"Bing Ads","homepage":"https://bingads.microsoft.com","categories":["ad"],"domains":["*.bing.com","*.microsoft.com","*.msn.com","*.s-msft.com","*.s-msn.com","*.msads.net","*.msecnd.net","*.windows.net"],"examples":["bat.bing.com","c.bing.com","bat.r.msn.com","ajax.microsoft.com"]},{"name":"Intercom","homepage":"https://www.intercom.com","categories":["customer-success"],"domains":["*.intercomcdn.com","*.intercom.io"],"examples":["js.intercomcdn.com","api-iam.intercom.io","widget.intercom.io","nexus-websocket-a.intercom.io"]},{"name":"Crazy Egg","homepage":"https://www.crazyegg.com/","categories":["analytics"],"domains":["*.cetrk.com","*.crazyegg.com","*.hellobar.com","dnn506yrbagrg.cloudfront.net"]},{"name":"Amazon Pay","homepage":"https://pay.amazon.com","categories":["utility"],"domains":["payments.amazon.com","*.payments-amazon.com"]},{"name":"Histats","homepage":"http://histats.com/","categories":["analytics"],"domains":["*.histats.com"],"examples":["s10.histats.com"]},{"name":"Adform","categories":["ad"],"domains":["*.adform.net","*.adformdsp.net"]},{"name":"Datacamp","categories":["utility"],"domains":["*.cdn77.org"]},{"name":"Tealium","homepage":"https://tealium.com/","categories":["tag-manager"],"domains":["*.aniview.com","*.delvenetworks.com","*.limelight.com","*.tiqcdn.com","*.llnwd.net","*.tealiumiq.com"],"examples":["tags.tiqcdn.com","tealium.hs.llnwd.net","link.videoplatform.limelight.com","datacloud.tealiumiq.com"]},{"name":"Optimizely","homepage":"https://www.optimizely.com/","categories":["analytics"],"domains":["*.optimizely.com"],"examples":["cdn.optimizely.com","cdn-pci.optimizely.com","logx.optimizely.com","cdn3.optimizely.com"]},{"name":"Yotpo","homepage":"https://www.yotpo.com/","categories":["marketing"],"domains":["*.yotpo.com"]},{"name":"Trust Pilot","categories":["analytics"],"domains":["*.trustpilot.com"]},{"name":"Privy","categories":["ad"],"domains":["*.privy.com","*.privymktg.com"]},{"name":"Baidu Analytics","homepage":"https://tongji.baidu.com/web/welcome/login","categories":["analytics"],"domains":["*.baidu.com"],"examples":["hm.baidu.com"]},{"name":"Wistia","homepage":"https://wistia.com/","categories":["video"],"domains":["*.wistia.com","embedwistia-a.akamaihd.net","*.wistia.net"],"examples":["fast.wistia.com","fast.wistia.net","distillery.wistia.com","pipedream.wistia.com"]},{"name":"iubenda","categories":["utility"],"domains":["*.iubenda.com"],"examples":["www.iubenda.com"]},{"name":"Nielsen NetRatings SiteCensus","company":"The Nielsen Company","homepage":"http://www.nielsen-online.com/intlpage.html","categories":["analytics"],"domains":["*.imrworldwide.com"]},{"name":"BrightTag / Signal","company":"Signal","homepage":"https://www.signal.co","categories":["tag-manager"],"domains":["*.btstatic.com","*.thebrighttag.com"]},{"name":"mPulse","homepage":"https://developer.akamai.com/akamai-mpulse","categories":["analytics"],"domains":["*.akstat.io","*.go-mpulse.net","*.mpulse.net","*.mpstat.us"],"examples":["c.go-mpulse.net","0211c83c.akstat.io"]},{"name":"PayPal","homepage":"https://paypal.com","categories":["utility"],"domains":["*.paypal.com","*.paypalobjects.com"],"examples":["www.paypalobjects.com"]},{"name":"Sentry","homepage":"https://sentry.io/","categories":["utility"],"domains":["*.getsentry.com","*.ravenjs.com","*.sentry-cdn.com"],"examples":["cdn.ravenjs.com","browser.sentry-cdn.com"]},{"name":"Cookiebot","homepage":"https://www.cookiebot.com/","categories":["utility"],"domains":["*.cookiebot.com"],"examples":["consent.cookiebot.com"]},{"name":"Distil Networks","homepage":"https://www.distilnetworks.com/","categories":["utility"],"domains":["*.areyouahuman.com"],"examples":["n-cdn.areyouahuman.com"]},{"name":"Adobe TypeKit","company":"Adobe","homepage":"https://fonts.adobe.com/","categories":["cdn"],"domains":["*.typekit.com","*.typekit.net"],"examples":["use.typekit.net","p.typekit.net"]},{"name":"Kakao","categories":["social"],"domains":["*.daum.net","*.daumcdn.net"]},{"name":"Bold Commerce","categories":["utility"],"domains":["*.shappify-cdn.com","*.shappify.com","*.boldapps.net"]},{"name":"Akamai","homepage":"https://www.akamai.com/","categories":["cdn"],"domains":["23.62.3.183","*.akamaitechnologies.com","*.akamaitechnologies.fr","*.akamai.net","*.akamaiedge.net","*.akamaihd.net","*.akamaized.net","*.edgefcs.net","*.edgekey.net","edgesuite.net","*.srip.net"]},{"name":"Segment","homepage":"https://segment.com/","categories":["analytics"],"domains":["*.segment.com","*.segment.io"],"examples":["cdn.segment.com","api.segment.io"]},{"name":"District M","categories":["ad"],"domains":["*.districtm.io"]},{"name":"Bigcommerce","categories":["marketing"],"domains":["*.bigcommerce.com"]},{"name":"Dealer","homepage":"https://www.dealer.com/","categories":["hosting"],"domains":["*.dealer.com"],"examples":["static.dealer.com"]},{"name":"Klaviyo","categories":["ad"],"domains":["*.klaviyo.com"]},{"name":"Rambler","company":"Rambler & Co","categories":["utility"],"domains":["*.rambler.ru"]},{"name":"Tumblr","homepage":"https://tumblr.com/","categories":["social"],"domains":["*.tumblr.com"],"examples":["assets.tumblr.com","static.tumblr.com"]},{"name":"Snapchat","homepage":"https://www.snapchat.com","categories":["analytics"],"domains":["*.snapchat.com","*.sc-static.net"],"examples":["tr.snapchat.com"]},{"name":"VigLink","categories":["ad"],"domains":["*.viglink.com"]},{"name":"StatCounter","categories":["analytics"],"domains":["*.statcounter.com"]},{"name":"TrustArc","homepage":"https://www.trustarc.com/","categories":["utility"],"domains":["*.trustarc.com"],"examples":["choices.trustarc.com","consent.trustarc.com"]},{"name":"Tidio Live Chat","company":"Tidio","homepage":"https://www.tidiochat.com/en/","categories":["customer-success"],"domains":["*.tidiochat.com"]},{"name":"DoubleVerify","homepage":"https://www.doubleverify.com/","categories":["ad"],"domains":["*.doubleverify.com","*.dvtps.com","*.iqfp1.com"],"examples":["cdn.doubleverify.com","cdn3.doubleverify.com","tps.doubleverify.com","tps712.doubleverify.com","tps714.doubleverify.com","tps706.doubleverify.com","tps700.doubleverify.com","tps707.doubleverify.com","rtb2.doubleverify.com","rtb0.doubleverify.com","rtbcdn.doubleverify.com","tps11020.doubleverify.com","tm.iqfp1.com"]},{"name":"Instagram","homepage":"https://www.instagram.com","categories":["social"],"domains":["*.cdninstagram.com","*.instagram.com"],"examples":["scontent.cdninstagram.com"]},{"name":"OptinMonster","homepage":"https://optinmonster.com/","categories":["marketing"],"domains":["*.opmnstr.com","*.optmnstr.com","*.optmstr.com"],"examples":["a.optmstr.com","api.opmnstr.com","a.optmnstr.com"]},{"name":"Evidon","categories":["analytics"],"domains":["*.evidon.com"]},{"name":"Lucky Orange","homepage":"https://www.luckyorange.com/","categories":["analytics"],"domains":["*.luckyorange.com","d10lpsik1i8c69.cloudfront.net","*.luckyorange.net"]},{"name":"Gemius","categories":["ad"],"domains":["*.gemius.pl"]},{"name":"Olark","homepage":"https://www.olark.com/","categories":["customer-success"],"domains":["*.olark.com"],"examples":["static.olark.com"]},{"name":"CallRail","categories":["analytics"],"domains":["*.callrail.com"]},{"name":"Mixpanel","homepage":"https://mixpanel.com/","categories":["analytics"],"domains":["*.mixpanel.com","*.mxpnl.com"],"examples":["cdn.mxpnl.com"]},{"name":"OpenX","homepage":"https://www.openx.com/","categories":["ad"],"domains":["*.deliverimp.com","*.openxadexchange.com","*.servedbyopenx.com","*.jump-time.net","*.openx.net"],"examples":["uk-ads.openx.net","us-ads.openx.net","33across-d.openx.net","rtb.openx.net","us-u.openx.net","eu-u.openx.net","u.openx.net"]},{"name":"CreateJS CDN","homepage":"http://code.createjs.com/","categories":["cdn"],"domains":["*.createjs.com"],"examples":["code.createjs.com"]},{"name":"Chartbeat","categories":["analytics"],"domains":["*.chartbeat.com","*.chartbeat.net"]},{"name":"Sizmek","homepage":"https://www.sizmek.com/","categories":["ad"],"domains":["*.serving-sys.com","*.peer39.net"],"examples":["secure-ds.serving-sys.com","ds.serving-sys.com","bs.serving-sys.com"]},{"name":"FullStory","categories":["analytics"],"domains":["*.fullstory.com"],"examples":["rs.fullstory.com"]},{"name":"Snowplow","homepage":"https://snowplowanalytics.com/","categories":["analytics"],"domains":["d32hwlnfiv2gyn.cloudfront.net"]},{"name":"Brightcove","homepage":"https://www.brightcove.com/en/","categories":["video"],"domains":["*.brightcove.com","*.brightcove.net","*.zencdn.net"],"examples":["vjs.zencdn.net","players.brightcove.net"]},{"name":"GoDaddy","homepage":"https://www.godaddy.com/","categories":["utility"],"domains":["*.godaddy.com","*.wsimg.com"],"examples":["ocsp.godaddy.com","seal.godaddy.com"]},{"name":"Inspectlet","categories":["analytics"],"domains":["*.inspectlet.com"]},{"name":"Teads","categories":["ad"],"domains":["*.teads.tv"]},{"name":"New Relic","homepage":"https://newrelic.com/","categories":["utility"],"domains":["*.newrelic.com","*.nr-data.net"],"examples":["js-agent.newrelic.com","bam.nr-data.net"]},{"name":"Ensighten","homepage":"https://www.ensighten.com/","categories":["tag-manager"],"domains":["*.ensighten.com"],"examples":["nexus.ensighten.com"]},{"name":"Parking Crew","homepage":"http://parkingcrew.net/","categories":["other"],"domains":["d1lxhc4jvstzrp.cloudfront.net","*.parkingcrew.net"]},{"name":"Azure Web Services","company":"Microsoft","categories":["cdn"],"domains":["*.azurewebsites.net","*.azureedge.net","*.msedge.net"]},{"name":"BlueKai","company":"Oracle","categories":["ad"],"domains":["*.bkrtx.com","*.bluekai.com"]},{"name":"Treasure Data","categories":["analytics"],"domains":["*.treasuredata.com"]},{"name":"Drift","homepage":"https://www.drift.com/","categories":["marketing"],"domains":["*.drift.com","*.driftt.com"],"examples":["js.driftt.com","api.drift.com"]},{"name":"MGID","homepage":"https://www.mgid.com/","categories":["ad"],"domains":["*.mgid.com","*.dt07.net"],"examples":["servicer.mgid.com"]},{"name":"Microsoft Hosted Libs","company":"Microsoft","categories":["cdn"],"domains":["*.aspnetcdn.com"],"examples":["ajax.aspnetcdn.com"]},{"name":"33 Across","homepage":"https://33across.com/","categories":["ad"],"domains":["*.33across.com"],"examples":["sic.33across.com","cdn-sic.33across.com"]},{"name":"Monotype","categories":["cdn"],"domains":["*.fonts.com","*.fonts.net"]},{"name":"DTSCOUT","categories":["ad"],"domains":["*.dtscout.com"]},{"name":"WordPress Site Stats","company":"Automattic","homepage":"https://wp.com/","categories":["analytics"],"domains":["pixel.wp.com","stats.wp.com"]},{"name":"Mapbox","categories":["utility"],"domains":["*.mapbox.com"]},{"name":"MediaVine","homepage":"https://www.mediavine.com/","categories":["ad"],"domains":["*.mediavine.com"],"examples":["scripts.mediavine.com","video.mediavine.com"]},{"name":"Shareaholic","homepage":"https://www.shareaholic.com/","categories":["social"],"domains":["*.shareaholic.com","dsms0mj1bbhn4.cloudfront.net"]},{"name":"Dataxu","categories":["marketing"],"domains":["*.w55c.net"]},{"name":"MailMunch","categories":["ad"],"domains":["*.mailmunch.co"]},{"name":"Cxense","categories":["ad"],"domains":["*.cxense.com","*.cxpublic.com","*.emediate.dk","*.emediate.eu"]},{"name":"Marchex","categories":["analytics"],"domains":["*.voicestar.com","*.marchex.io"]},{"name":"Fastly","categories":["utility"],"domains":["*.fastly.net"]},{"name":"Unpkg","homepage":"https://unpkg.com","categories":["cdn"],"domains":["*.unpkg.com"]},{"name":"LivePerson","categories":["customer-success"],"homepage":"https://www.liveperson.com/","domains":["*.liveperson.com","*.look.io","*.liveperson.net","*.lpsnmedia.net"]},{"name":"SoundCloud","homepage":"https://www.soundcloud.com/","categories":["content"],"domains":["*.sndcdn.com","*.soundcloud.com","*.stratus.sc"],"examples":["widget.sndcdn.com"]},{"name":"VWO","homepage":"https://vwo.com","categories":["analytics"],"domains":["*.visualwebsiteoptimizer.com"],"examples":["dev.visualwebsiteoptimizer.com"]},{"name":"StickyADS.tv","categories":["ad"],"domains":["*.stickyadstv.com"]},{"name":"PushCrew","categories":["ad"],"domains":["*.pushcrew.com"]},{"name":"Embedly","categories":["content"],"domains":["*.embedly.com","*.embed.ly"]},{"name":"CDK Dealer Management","company":"CDK Global","homepage":"https://www.cdkglobal.com/us","categories":["hosting"],"domains":["*.assets-cdk.com"],"examples":["media-cf.assets-cdk.com"]},{"name":"Popads","homepage":"https://www.popads.net/","categories":["ad"],"domains":["*.popads.net"],"examples":["serve.popads.net","c1.popads.net"]},{"name":"FreakOut","categories":["ad"],"domains":["*.fout.jp"]},{"name":"SnapWidget","categories":["content"],"domains":["*.snapwidget.com"]},{"name":"Pure Chat","categories":["customer-success"],"domains":["*.purechat.com"]},{"name":"Outbrain","homepage":"https://www.outbrain.com/","categories":["ad"],"domains":["*.outbrain.com","*.outbrainimg.com","*.visualrevenue.com"]},{"name":"RD Station","homepage":"https://www.rdstation.com/en/","categories":["marketing"],"domains":["d335luupugsy2.cloudfront.net"]},{"name":"LiveJournal","categories":["social"],"domains":["*.livejournal.com","*.livejournal.net"]},{"name":"ContactAtOnce","homepage":"https://www.contactatonce.com/","categories":["customer-success"],"domains":["*.contactatonce.com"],"examples":["tag.contactatonce.com","agentpresence.contactatonce.com"]},{"name":"Ezoic","categories":["analytics"],"domains":["*.ezoic.net"]},{"name":"AB Tasty","categories":["analytics"],"domains":["*.abtasty.com","d1447tq2m68ekg.cloudfront.net"]},{"name":"Quantcast","homepage":"https://www.quantcast.com","categories":["analytics"],"domains":["*.brtstats.com","*.quantcount.com","*.quantserve.com","*.semantictec.com","*.ntv.io"],"examples":["pixel.quantserve.com","secure.quantserve.com","cms.quantserve.com","rules.quantcount.com"]},{"name":"DigiTrust","homepage":"http://www.digitru.st/","categories":["analytics"],"domains":["*.digitru.st"],"examples":["cdn.digitru.st"]},{"name":"LongTail Ad Solutions","categories":["ad"],"domains":["*.jwpcdn.com","*.jwplatform.com","*.jwplayer.com","*.jwpltx.com","*.jwpsrv.com","*.longtailvideo.com"]},{"name":"Parse.ly","categories":["analytics"],"domains":["*.parsely.com","d1z2jf7jlzjs58.cloudfront.net"]},{"name":"Index Exchange","company":"WPP","categories":["ad"],"domains":["*.casalemedia.com","*.indexww.com"]},{"name":"Clicktripz","categories":["content"],"domains":["*.clicktripz.com"],"examples":["static.clicktripz.com","www.clicktripz.com"]},{"name":"Ve","company":"Ve Interactive","categories":["marketing"],"domains":["*.veinteractive.com"]},{"name":"Adloox","categories":["ad"],"domains":["*.adlooxtracking.com"]},{"name":"GumGum","categories":["ad"],"domains":["*.gumgum.com"]},{"name":"Digital ad Consortium","categories":["ad"],"domains":["*.impact-ad.jp"]},{"name":"Amplitude Mobile Analytics","company":"Amplitude","categories":["analytics"],"domains":["*.amplitude.com","d24n15hnbwhuhn.cloudfront.net"]},{"name":"Adobe Business Catalyst","homepage":"https://www.businesscatalyst.com/","categories":["hosting"],"domains":["*.businesscatalyst.com"]},{"name":"LightWidget","categories":["utility"],"domains":["*.lightwidget.com"]},{"name":"Spotify","homepage":"https://www.spotify.com/","categories":["content"],"domains":["*.scdn.co","*.spotify.com"],"examples":["open.spotify.com","open.scdn.co","i.scdn.co"]},{"name":"SmartAdServer","categories":["ad"],"domains":["*.01net.com","*.sascdn.com"],"examples":["securite.01net.com"]},{"name":"Adroll","homepage":"https://www.adroll.com/","categories":["ad"],"domains":["*.adroll.com"],"examples":["d.adroll.com","s.adroll.com"]},{"name":"PureCars","homepage":"https://www.purecars.com/","categories":["marketing"],"domains":["*.purecars.com"],"examples":["cdn.purecars.com"]},{"name":"Keen","company":"Keen","homepage":"https://keen.io/","categories":["analytics"],"domains":["*.keen.io","d26b395fwzu5fz.cloudfront.net"]},{"name":"Infolinks","categories":["ad"],"domains":["*.infolinks.com"]},{"name":"Unbounce","categories":["ad"],"domains":["*.ubembed.com","*.unbounce.com","d2xxq4ijfwetlm.cloudfront.net","d9hhrg4mnvzow.cloudfront.net"]},{"name":"Roxr Software","categories":["analytics"],"domains":["*.getclicky.com"]},{"name":"OpenTable","company":"Priceline Group","categories":["content"],"domains":["*.opentable.com","*.opentable.co.uk","*.toptable.co.uk"],"examples":["www.toptable.co.uk"]},{"name":"uLogin","categories":["other"],"domains":["*.ulogin.ru"]},{"name":"Searchanise","categories":["analytics"],"domains":["*.searchanise.com"],"examples":["www.searchanise.com"]},{"name":"Gigya","categories":["analytics"],"domains":["*.gigya.com"]},{"name":"Net Reviews","categories":["analytics"],"domains":["*.avis-verifies.com"],"examples":["www.avis-verifies.com"]},{"name":"Booking.com","categories":["content"],"domains":["*.bstatic.com"]},{"name":"Disqus","homepage":"http://disqus.com/","categories":["social"],"domains":["*.disqus.com","*.disquscdn.com"],"examples":["c.disquscdn.com"]},{"name":"Tray Commerce","homepage":"https://www.tray.com.br/","categories":["marketing"],"domains":["*.tcdn.com.br"],"examples":["images.tcdn.com.br"]},{"name":"Crowd Control","company":"Lotame","categories":["ad"],"domains":["*.crwdcntrl.net"]},{"name":"Intent Media","homepage":"https://intent.com/","categories":["ad"],"domains":["*.intentmedia.net"]},{"name":"issuu","categories":["content"],"domains":["*.issuu.com","*.isu.pub"]},{"name":"Salesforce Commerce Cloud","homepage":"https://www.salesforce.com/products/commerce-cloud/overview/","categories":["hosting"],"domains":["*.cquotient.com","*.demandware.net","demandware.edgesuite.net"]},{"name":"sovrn","categories":["ad"],"domains":["*.lijit.com"]},{"name":"JuicyAds","categories":["ad"],"domains":["*.juicyads.com"]},{"name":"Sharethrough","categories":["ad"],"domains":["*.sharethrough.com"]},{"name":"Heap","categories":["analytics"],"domains":["*.heapanalytics.com"]},{"name":"LiveTex","categories":["customer-success"],"domains":["*.livetex.ru"]},{"name":"Nosto","categories":["analytics"],"domains":["*.nosto.com"]},{"name":"fluct","categories":["ad"],"domains":["*.adingo.jp"]},{"name":"Smart AdServer","categories":["ad"],"domains":["*.sasqos.com","*.smartadserver.com"]},{"name":"fam","company":"Fing Co Ltd.","homepage":"http://admin.fam-ad.com/report/","categories":["ad"],"domains":["*.fam-ad.com"],"examples":["img.fam-ad.com"]},{"name":"ExoClick","categories":["ad"],"domains":["*.exoclick.com"]},{"name":"BannerFlow","company":"Nordic Factory Solutions","categories":["ad"],"domains":["*.bannerflow.com"]},{"name":"iPerceptions","categories":["customer-success"],"domains":["*.iperceptions.com"]},{"name":"Albacross","homepage":"https://albacross.com/","categories":["marketing"],"domains":["*.albacross.com"],"examples":["serve.albacross.com"]},{"name":"RevJet","homepage":"https://www.revjet.com/","categories":["ad"],"domains":["*.revjet.com"],"examples":["pix.revjet.com","ads.revjet.com"]},{"name":"Trusted Shops","categories":["utility"],"domains":["*.trustedshops.com"]},{"name":"MaxCDN Enterprise","company":"MaxCDN","categories":["utility"],"domains":["*.netdna-cdn.com","*.netdna-ssl.com"]},{"name":"etracker","categories":["analytics"],"domains":["*.etracker.com","*.etracker.de"],"examples":["www.etracker.com"]},{"name":"Yandex CDN","company":"Yandex","homepage":"https://yandex.ru/","categories":["cdn"],"domains":["*.yandex.st"]},{"name":"LKQD","categories":["ad"],"domains":["*.lkqd.net"]},{"name":"Sift Science","categories":["utility"],"domains":["*.siftscience.com"]},{"name":"Help Scout","homepage":"https://www.helpscout.net/","categories":["customer-success"],"domains":["djtflbt20bdde.cloudfront.net","*.helpscout.net"],"examples":["beacon-v2.helpscout.net"]},{"name":"Seznam","categories":["utility"],"domains":["*.imedia.cz"]},{"name":"Vidible","categories":["ad"],"domains":["*.vidible.tv"]},{"name":"Media Math","homepage":"http://www.mediamath.com/","categories":["ad"],"domains":["*.mathads.com","*.mathtag.com"],"examples":["mathid.mathtag.com","sync.mathtag.com","pixel.mathtag.com"]},{"name":"Simplicity Marketing","categories":["ad"],"domains":["*.flashtalking.com"]},{"name":"Mouseflow","categories":["analytics"],"domains":["*.mouseflow.com"]},{"name":"Siteimprove","categories":["utility"],"domains":["*.siteimprove.com","*.siteimproveanalytics.com"]},{"name":"GetSiteControl","company":"GetWebCraft","categories":["utility"],"domains":["*.getsitecontrol.com"]},{"name":"AOL / Oath / Verizon Media","homepage":"https://www.oath.com/","categories":["ad"],"domains":["*.advertising.com","*.aol.com","*.aolcdn.com","*.blogsmithmedia.com","*.oath.com","*.aol.net","*.tacoda.net","*.aol.co.uk"],"examples":["pixel.advertising.com","dtm.advertising.com","tag.sp.advertising.com","service.sp.advertising.com","adtech.advertising.com","adaptv.advertising.com","mighty.aol.net","consent.cmp.oath.com"]},{"name":"Accuweather","categories":["content"],"domains":["*.accuweather.com"]},{"name":"Feefo.com","company":"Feefo","categories":["analytics"],"domains":["*.feefo.com"]},{"name":"Constant Contact","categories":["ad"],"domains":["*.ctctcdn.com"]},{"name":"Rakuten Marketing","company":"Rakuten","categories":["ad"],"domains":["*.rakuten-static.com","*.rmtag.com"]},{"name":"TrafficStars","categories":["ad"],"domains":["*.trafficstars.com","*.tsyndicate.com"]},{"name":"ForeSee","company":"Answers","categories":["analytics"],"domains":["*.4seeresults.com","*.answerscloud.com","*.foresee.com","*.foreseeresults.com"]},{"name":"Swiftype","categories":["utility"],"domains":["*.swiftype.com","*.swiftypecdn.com"]},{"name":"Bazaarvoice","categories":["analytics"],"domains":["*.bazaarvoice.com","*.feedmagnet.com"]},{"name":"SocialShopWave","categories":["social"],"domains":["*.socialshopwave.com"]},{"name":"Bootstrap CDN","homepage":"https://www.bootstrapcdn.com/","categories":["cdn"],"domains":["*.bootstrapcdn.com"],"examples":["maxcdn.bootstrapcdn.com","stackpath.bootstrapcdn.com"]},{"name":"SessionCam","company":"ServiceTick","categories":["analytics"],"domains":["*.sessioncam.com","d2oh4tlt9mrke9.cloudfront.net"]},{"name":"AppDynamics","homepage":"https://www.appdynamics.com/","categories":["utility"],"domains":["*.appdynamics.com","*.eum-appdynamics.com","d3tjaysgumg9lf.cloudfront.net"],"examples":["cdn.appdynamics.com"]},{"name":"Adyoulike","categories":["ad"],"domains":["*.adyoulike.com","*.omnitagjs.com","*.adyoulike.net"]},{"name":"Affirm","categories":["utility"],"domains":["*.affirm.com"]},{"name":"Sortable","categories":["ad"],"domains":["*.deployads.com"]},{"name":"Neodata","categories":["ad"],"domains":["*.neodatagroup.com"]},{"name":"Adnium","categories":["ad"],"domains":["*.adnium.com"]},{"name":"AdScore","homepage":"https://www.adscore.com/","categories":["ad"],"domains":["*.adsco.re"],"examples":["c.adsco.re"]},{"name":"Comm100","categories":["customer-success"],"domains":["*.comm100.com"]},{"name":"Medium","categories":["content"],"domains":["*.medium.com"]},{"name":"Esri ArcGIS","company":"Esri","categories":["utility"],"domains":["*.arcgis.com","*.arcgisonline.com"]},{"name":"iBillboard","categories":["ad"],"domains":["*.ibillboard.com"]},{"name":"Hotmart","homepage":"https://www.hotmart.com/","categories":["content"],"domains":["*.hotmart.com"],"examples":["launchermodule.hotmart.com"]},{"name":"Secomapp","categories":["utility"],"domains":["*.secomapp.com"]},{"name":"AdMatic","categories":["ad"],"domains":["*.admatic.com.tr"]},{"name":"Dailymotion","categories":["content"],"domains":["*.dailymotion.com","*.dmxleo.com","*.dm.gg","*.pxlad.io","*.dmcdn.net","*.sublimevideo.net"],"examples":["ad.pxlad.io","www.dailymotion.com"]},{"name":"Foursixty","categories":["customer-success"],"domains":["*.foursixty.com"]},{"name":"OptiMonk","categories":["ad"],"domains":["*.optimonk.com"]},{"name":"Refersion","categories":["ad"],"domains":["*.refersion.com"]},{"name":"Pardot","categories":["marketing"],"domains":["*.pardot.com"]},{"name":"GitHub","categories":["utility"],"domains":["*.rawgit.com"],"examples":["cdn.rawgit.com"]},{"name":"Alexa","homepage":"https://www.alexa.com/","categories":["analytics"],"domains":["*.alexametrics.com","d31qbv1cthcecs.cloudfront.net"],"examples":["certify.alexametrics.com"]},{"name":"Bugsnag","categories":["utility"],"domains":["*.bugsnag.com","d2wy8f7a9ursnm.cloudfront.net"],"examples":["notify.bugsnag.com"]},{"name":"ResponsiveVoice","categories":["other"],"domains":["*.responsivevoice.org"]},{"name":"ContentSquare","categories":["analytics"],"domains":["d1m6l9dfulcyw7.cloudfront.net","*.content-square.net","*.contentsquare.net"]},{"name":"BounceX","categories":["analytics"],"homepage":"https://www.bouncex.com/","domains":["*.bounceexchange.com","*.bouncex.net"],"examples":["events.bouncex.net"]},{"name":"Tencent","categories":["content"],"domains":["*.qq.com","*.ywxi.net"]},{"name":"TagCommander","categories":["tag-manager"],"domains":["*.commander1.com","*.tagcommander.com"]},{"name":"Between Digital","categories":["ad"],"domains":["*.betweendigital.com"]},{"name":"Tribal Fusion","company":"Exponential Interactive","categories":["ad"],"domains":["*.tribalfusion.com"]},{"name":"iovation","categories":["utility"],"domains":["*.iesnare.com"]},{"name":"Auto Link Maker","company":"Apple","categories":["ad"],"domains":["*.apple.com"],"examples":["autolinkmaker.itunes.apple.com"]},{"name":"SnapEngage","categories":["customer-success"],"domains":["*.snapengage.com"]},{"name":"iAdvize SAS","categories":["customer-success"],"domains":["*.iadvize.com"]},{"name":"Listrak","homepage":"https://www.listrak.com/","categories":["marketing"],"domains":["*.listrak.com","*.listrakbi.com"],"examples":["cdn.listrakbi.com","s1.listrakbi.com"]},{"name":"Branch Metrics","categories":["ad"],"domains":["*.branch.io","*.app.link"]},{"name":"Admixer for Publishers","company":"Admixer","categories":["ad"],"domains":["*.admixer.net"]},{"name":"Tail Target","company":"Tail","categories":["ad"],"domains":["*.tailtarget.com"]},{"name":"Clicktale","categories":["analytics"],"domains":["*.cdngc.net","*.clicktale.net"],"examples":["clicktalecdn.sslcs.cdngc.net"]},{"name":"Maxymiser","categories":["analytics"],"domains":["*.maxymiser.net"]},{"name":"Marketo","homepage":"https://www.marketo.com","categories":["analytics"],"domains":["*.marketo.com","*.mktoresp.com","*.marketo.net"],"examples":["munchkin.marketo.net"]},{"name":"Bizible","categories":["ad"],"domains":["*.bizible.com","*.bizibly.com"]},{"name":"LoyaltyLion","categories":["ad"],"domains":["*.loyaltylion.com","*.loyaltylion.net","dg1f2pfrgjxdq.cloudfront.net"]},{"name":"Convert Insights","categories":["analytics"],"domains":["*.convertexperiments.com"]},{"name":"Opentag","company":"Qubit","categories":["tag-manager"],"domains":["*.qutics.com","d3c3cq33003psk.cloudfront.net"],"examples":["opentag-stats.qutics.com"]},{"name":"Adverline Board","company":"Adverline","categories":["ad"],"domains":["*.adverline.com","*.adnext.fr"]},{"name":"Optanon","homepage":"https://www.cookielaw.org/","categories":["utility"],"domains":["*.onetrust.com","*.cookielaw.org"],"examples":["cdn.cookielaw.org","geolocation.onetrust.com"]},{"name":"Adocean","company":"Gemius","categories":["ad"],"domains":["*.adocean.pl"]},{"name":"Po.st","company":"RadiumOne","categories":["utility"],"domains":["*.po.st"]},{"name":"Yieldmo","categories":["ad"],"domains":["*.yieldmo.com"]},{"name":"Market GID","homepage":"https://www.marketgid.com/","categories":["ad"],"domains":["*.marketgid.com"],"examples":["jsc.marketgid.com"]},{"name":"TRUSTe","categories":["utility"],"domains":["*.truste.com"]},{"name":"One by AOL","company":"AOL","categories":["ad"],"domains":["*.adtechjp.com","*.adtech.de"]},{"name":"Affiliate Window","company":"Digital Window","categories":["ad"],"domains":["*.dwin1.com"]},{"name":"Pagely","categories":["other"],"domains":["*.optnmstr.com"]},{"name":"Perfect Market","categories":["ad"],"domains":["*.perfectmarket.com"]},{"name":"Symantec","categories":["utility"],"domains":["*.norton.com","*.symantec.com","*.symcb.com","*.symcd.com"],"examples":["extended-validation-ssl.websecurity.symantec.com"]},{"name":"piano","categories":["ad"],"domains":["*.npttech.com","*.tinypass.com"],"examples":["www.npttech.com"]},{"name":"Elastic Ad","categories":["ad"],"domains":["*.elasticad.net"]},{"name":"Freshdesk","homepage":"https://freshdesk.com/","categories":["customer-success"],"domains":["d36mpcpuzc4ztk.cloudfront.net"]},{"name":"IPONWEB","categories":["ad"],"domains":["*.company-target.com","*.liadm.com","*.iponweb.net","*.p161.net"],"examples":["pool.udsp.iponweb.net"]},{"name":"Ecwid","categories":["hosting"],"domains":["*.ecwid.com","*.shopsettings.com","d3fi9i0jj23cau.cloudfront.net","d3j0zfs7paavns.cloudfront.net"]},{"name":"Digioh","categories":["ad"],"domains":["*.lightboxcdn.com"]},{"name":"Fort Awesome","categories":["cdn"],"domains":["*.fortawesome.com"]},{"name":"Nend","categories":["ad"],"domains":["*.nend.net"]},{"name":"Bronto Software","categories":["marketing"],"domains":["*.bm23.com","*.bronto.com","*.brontops.com"]},{"name":"TrackJS","categories":["analytics"],"domains":["*.trackjs.com","d2zah9y47r7bi2.cloudfront.net"],"examples":["usage.trackjs.com"]},{"name":"Dynamic Yield","categories":["customer-success"],"domains":["*.dynamicyield.com"]},{"name":"Clerk.io ApS","categories":["analytics"],"domains":["*.clerk.io"]},{"name":"IBM Digital Analytics","company":"IBM","categories":["analytics"],"domains":["*.cmcore.com","coremetrics.com","data.coremetrics.com","data.de.coremetrics.com","libs.de.coremetrics.com","tmscdn.de.coremetrics.com","iocdn.coremetrics.com","libs.coremetrics.com","tmscdn.coremetrics.com","*.s81c.com","*.unica.com","*.coremetrics.eu"],"examples":["data.coremetrics.eu"]},{"name":"Usabilla","homepage":"https://usabilla.com","categories":["analytics"],"domains":["*.usabilla.com","d6tizftlrpuof.cloudfront.net"],"examples":["w.usabilla.com"]},{"name":"Meetrics","categories":["ad"],"domains":["*.de.com","*.meetrics.net","*.mxcdn.net"],"examples":["research.de.com"]},{"name":"Forensiq","categories":["utility"],"domains":["*.fqtag.com"]},{"name":"Revolver Maps","categories":["analytics"],"domains":["*.revolvermaps.com"]},{"name":"Monetate","categories":["analytics"],"domains":["*.monetate.net"]},{"name":"Fraudlogix","categories":["utility"],"domains":["*.yabidos.com"]},{"name":"Mather Economics","categories":["analytics"],"domains":["*.matheranalytics.com"]},{"name":"Blindado","categories":["utility"],"domains":["*.siteblindado.com"]},{"name":"UserReport","categories":["analytics"],"domains":["*.userreport.com"]},{"name":"OwnerIQ","categories":["ad"],"domains":["*.owneriq.net"]},{"name":"CPEx","categories":["content"],"domains":["*.cpex.cz"]},{"name":"eBay","categories":["ad"],"domains":["*.ebay.com","*.ebayimg.com","*.fetchback.com"]},{"name":"Skype","categories":["other"],"domains":["*.skype.com"]},{"name":"DialogTech","categories":["ad"],"domains":["*.dialogtech.com"]},{"name":"WebsiteBuilder.com","homepage":"https://www.websitebuilder.com","categories":["hosting"],"domains":["*.mywebsitebuilder.com"]},{"name":"iZooto","homepage":"https://www.izooto.com","categories":["marketing"],"domains":["*.izooto.com"],"examples":["cdn.izooto.com"]},{"name":"AddEvent","categories":["utility"],"domains":["*.addevent.com"],"examples":["www.addevent.com"]},{"name":"GetResponse","categories":["ad"],"domains":["*.getresponse.com"]},{"name":"Twitch","homepage":"https://twitch.tv/","categories":["video"],"domains":["*.twitch.tv"],"examples":["player.twitch.tv"]},{"name":"Radar","company":"Cedexis","homepage":"https://www.cedexis.com/radar/","categories":["analytics"],"domains":["*.cedexis-test.com","*.cedexis.com","*.cmdolb.com","cedexis.leasewebcdn.com","*.cedexis-radar.net","*.cedexis.net","cedexis-test01.insnw.net","cedexisakamaitest.azureedge.net","cedexispub.cdnetworks.net","cs600.wac.alphacdn.net","cs600.wpc.edgecastdns.net","global2.cmdolb.com","img-cedexis.mncdn.com","a-cedexis.msedge.net","zn3vgszfh.fastestcdn.net"],"examples":["radar.cedexis.com","rpt.cedexis.com","2-01-49cd-0002.cdx.cedexis.net","bench.cedexis-test.com"]},{"name":"Smart Insight Tracking","company":"Emarsys","categories":["analytics"],"domains":["*.scarabresearch.com"]},{"name":"Polar","homepage":"https://polar.me/","categories":["ad"],"domains":["*.polarmobile.ca","*.mediaeverywhere.com","*.mediavoice.com","*.plrsrvcs.com","*.polarcdn-engine.com","*.polarcdn-meraxes.com","*.polarcdn-pentos.com","*.polarcdn-static.com","*.polarcdn-terrax.com","*.polarcdn.com","*.polarmobile.com","*.poweredbypolar.com","*.mediaconductor.me","*.polaracademy.me"]},{"name":"AudienceSearch","company":"Intimate Merger","categories":["ad"],"domains":["*.im-apps.net"]},{"name":"Autopilot","categories":["ad"],"domains":["*.autopilothq.com"]},{"name":"Rackspace","categories":["hosting"],"domains":["*.rackcdn.com","*.rackspacecloud.com","*.raxcdn.com","*.websitetestlink.com"]},{"name":"PowerReviews","categories":["analytics"],"domains":["*.powerreviews.com"]},{"name":"Rocket Fuel","categories":["ad"],"domains":["*.rfihub.com","*.ru4.com","*.rfihub.net","*.ad1x.com"]},{"name":"Okas Concepts","categories":["utility"],"domains":["*.okasconcepts.com"]},{"name":"Madison Logic","categories":["marketing"],"domains":["*.ml314.com"]},{"name":"Celtra","categories":["ad"],"domains":["*.celtra.com"]},{"name":"Snacktools","categories":["ad"],"domains":["*.bannersnack.com"]},{"name":"ClickDesk","categories":["customer-success"],"domains":["*.clickdesk.com","d1gwclp1pmzk26.cloudfront.net"]},{"name":"F@N Communications","homepage":"https://www.fancs.com/","categories":["ad"],"domains":["*.ladsp.com"],"examples":["px.ladsp.com"]},{"name":"Tradelab","categories":["ad"],"domains":["*.tradelab.fr"]},{"name":"CleverDATA","categories":["ad"],"domains":["*.1dmp.io"]},{"name":"Media Management Technologies","categories":["ad"],"domains":["*.speedshiftmedia.com"]},{"name":"Wishpond Technologies","categories":["marketing"],"domains":["*.wishpond.com","*.wishpond.net"]},{"name":"Reviews.co.uk","categories":["analytics"],"domains":["*.reviews.co.uk"]},{"name":"Adobe Scene7","company":"Adobe Systems","categories":["content"],"domains":["wwwimages.adobe.com","*.scene7.com","*.everestads.net","*.everestjs.net"]},{"name":"Permutive","categories":["ad"],"domains":["*.permutive.com","d3alqb8vzo7fun.cloudfront.net"]},{"name":"plista","categories":["ad"],"domains":["*.plista.com"]},{"name":"Kampyle","categories":["analytics"],"domains":["*.kampyle.com"]},{"name":"LinkedIn Ads","categories":["ad"],"domains":["*.licdn.com","ads.linkedin.com","www.linkedin.com"],"examples":["snap.licdn.com"]},{"name":"Survicate","categories":["analytics"],"domains":["*.survicate.com"]},{"name":"Nativo","categories":["ad"],"domains":["*.postrelease.com"]},{"name":"Decibel Insight","categories":["analytics"],"domains":["*.decibelinsight.net"]},{"name":"Github","categories":["utility"],"domains":["*.github.com","*.githubusercontent.com","*.github.io"],"examples":["raw.githubusercontent.com"]},{"name":"WebEngage","categories":["customer-success"],"domains":["*.webengage.co","*.webengage.com","d23nd6ymopvz52.cloudfront.net","d3701cc9l7v9a6.cloudfront.net"]},{"name":"Geniee","categories":["ad"],"domains":["*.href.asia","*.genieessp.jp","*.genieesspv.jp","*.gssprt.jp"],"examples":["cs.gssprt.jp"]},{"name":"The Trade Desk","homepage":"https://www.thetradedesk.com/","categories":["ad"],"domains":["d1eoo1tco6rr5e.cloudfront.net","*.adsrvr.org"],"examples":["js.adsrvr.org","match.adsrvr.org","insight.adsrvr.org","usw-lax.adsrvr.org","data.adsrvr.org","snap.adsrvr.org"]},{"name":"Lytics","categories":["ad"],"domains":["*.lytics.io"]},{"name":"rewardStyle.com","categories":["ad"],"domains":["*.rewardstyle.com"]},{"name":"Kaltura Video Platform","company":"Kaltura","categories":["content"],"domains":["*.kaltura.com"],"examples":["cdnsecakmi.kaltura.com"]},{"name":"WisePops","categories":["utility"],"domains":["*.wisepops.com"]},{"name":"Picreel","categories":["analytics"],"domains":["*.pcrl.co","*.picreel.com"]},{"name":"Riskified","categories":["utility"],"domains":["*.riskified.com"]},{"name":"Supership","homepage":"https://supership.jp/","categories":["ad"],"domains":["*.socdm.com"]},{"name":"Google Plus","company":"Google","categories":["social"],"domains":["plus.google.com"]},{"name":"Yieldify","categories":["ad"],"domains":["*.yieldify.com","*.yieldifylabs.com","d33wq5gej88ld6.cloudfront.net","dwmvwp56lzq5t.cloudfront.net"],"examples":["geo.yieldifylabs.com"]},{"name":"Smarter Click","categories":["ad"],"domains":["*.smct.co","*.smarterclick.co.uk"]},{"name":"Evergage","categories":["analytics"],"domains":["*.evergage.com","*.evgnet.com"],"examples":["cdn.evgnet.com"]},{"name":"SaleCycle","categories":["ad"],"domains":["*.salecycle.com","d16fk4ms6rqz1v.cloudfront.net","d22j4fzzszoii2.cloudfront.net","d30ke5tqu2tkyx.cloudfront.net"]},{"name":"Zanox","categories":["ad"],"domains":["*.zanox.com","*.zanox.ws"]},{"name":"AddShoppers","categories":["social"],"domains":["*.addshoppers.com","d3rr3d0n31t48m.cloudfront.net","*.shop.pe"]},{"name":"Interpublic Group","categories":["ad"],"domains":["*.mbww.com"]},{"name":"Qualaroo","categories":["analytics"],"domains":["*.qualaroo.com"]},{"name":"BoldChat","company":"LogMeIn","categories":["customer-success"],"domains":["*.boldchat.com"]},{"name":"Effective Measure","categories":["ad"],"domains":["*.effectivemeasure.net"]},{"name":"LoopMe","categories":["ad"],"domains":["*.loopme.biz","*.loopme.com","*.vntsm.com","*.loopme.me"]},{"name":"Sooqr Search","company":"Sooqr","categories":["utility"],"domains":["*.sooqr.com"]},{"name":"smartclip","categories":["ad"],"domains":["*.smartclip.net"]},{"name":"Cloudinary","categories":["content"],"domains":["*.cloudinary.com"]},{"name":"Gleam","categories":["marketing"],"domains":["*.gleam.io"]},{"name":"Revcontent","categories":["content"],"domains":["*.revcontent.com"]},{"name":"Browsealoud","homepage":"https://www.texthelp.com/en-gb/products/browsealoud/","categories":["other"],"domains":["*.browsealoud.com","*.texthelp.com"],"examples":["www.browsealoud.com"]},{"name":"Ooyala","categories":["ad"],"domains":["*.ooyala.com"]},{"name":"Intercept Interactive","categories":["ad"],"domains":["*.undertone.com"]},{"name":"Appier","categories":["ad"],"domains":["*.appier.net"]},{"name":"SublimeSkinz","categories":["ad"],"domains":["*.ayads.co"]},{"name":"KISSmetrics","categories":["analytics"],"domains":["*.kissmetrics.com","doug1izaerwt3.cloudfront.net","dsyszv14g9ymi.cloudfront.net"]},{"name":"Pixlee","categories":["social"],"domains":["*.pixlee.com"]},{"name":"NetFlix","categories":["content"],"domains":["*.nflxext.com","*.nflximg.net"]},{"name":"Shopgate","categories":["utility"],"domains":["*.shopgate.com"]},{"name":"Highcharts","categories":["utility"],"domains":["*.highcharts.com"]},{"name":"Audience 360","company":"Datapoint Media","categories":["ad"],"domains":["*.dpmsrv.com"]},{"name":"Bootstrap Chinese network","categories":["cdn"],"domains":["*.bootcss.com"]},{"name":"Sparkflow","company":"Intercept Interactive","categories":["ad"],"domains":["*.sparkflow.net"]},{"name":"Flowplayer","categories":["content"],"domains":["*.flowplayer.org"]},{"name":"Fresh Relevance","categories":["analytics"],"domains":["*.freshrelevance.com","*.cloudfront.ne","d1y9qtn9cuc3xw.cloudfront.net","d81mfvml8p5ml.cloudfront.net","dkpklk99llpj0.cloudfront.net"],"examples":["d1y9qtn9cuc3xw.cloudfront.ne"]},{"name":"WebpageFX","categories":["ad"],"domains":["*.leadmanagerfx.com"]},{"name":"Simpli.fi","categories":["ad"],"domains":["*.simpli.fi"]},{"name":"Omniconvert","categories":["analytics"],"domains":["*.omniconvert.com","d2tgfbvjf3q6hn.cloudfront.net","d3vbj265bmdenw.cloudfront.net"]},{"name":"Adscale","categories":["ad"],"domains":["*.adscale.de"]},{"name":"Covert Pics","categories":["content"],"domains":["*.covet.pics"]},{"name":"Curalate","categories":["marketing"],"domains":["*.curalate.com","d116tqlcqfmz3v.cloudfront.net"]},{"name":"ReadSpeaker","homepage":"https://www.readspeaker.com","categories":["other"],"domains":["*.readspeaker.com"],"examples":["sf1-eu.readspeaker.com"]},{"name":"Stackla PTY","categories":["social"],"domains":["*.stackla.com"]},{"name":"SpotXchange","categories":["ad"],"domains":["*.spotxcdn.com","*.spotxchange.com","*.spotx.tv"]},{"name":"Qubit Deliver","company":"Qubit","categories":["analytics"],"domains":["d1m54pdnjzjnhe.cloudfront.net","d22rutvoghj3db.cloudfront.net","dd6zx4ibq538k.cloudfront.net"]},{"name":"Opta","company":"Perform Group","categories":["content"],"domains":["*.opta.net"]},{"name":"Unruly Media","categories":["ad"],"domains":["*.unrulymedia.com"]},{"name":"Quantum Metric","homepage":"https://www.quantummetric.com/","categories":["analytics"],"domains":["*.quantummetric.com"]},{"name":"Weborama","categories":["ad"],"domains":["*.weborama.com","*.weborama.fr"]},{"name":"Republer","categories":["ad"],"domains":["*.republer.com"],"examples":["sync.republer.com"]},{"name":"Vox Media","homepage":"https://www.voxmedia.com/","categories":["content"],"domains":["*.vox-cdn.com","*.voxmedia.com"],"examples":["cdn.vox-cdn.com"]},{"name":"FoxyCart","categories":["utility"],"domains":["*.foxycart.com"]},{"name":"Adition","homepage":"https://www.adition.com","categories":["ad"],"domains":["*.adition.com"],"examples":["dsp.adfarm1.adition.com"]},{"name":"LiveHelpNow","categories":["customer-success"],"domains":["*.livehelpnow.net"]},{"name":"DemandBase","categories":["marketing"],"domains":["*.demandbase.com"]},{"name":"Concert","homepage":"https://concert.io/","categories":["ad"],"domains":["*.concert.io"],"examples":["cdn.concert.io"]},{"name":"TINT","categories":["content"],"domains":["*.71n7.com","d33w9bm0n1egwm.cloudfront.net","d36hc0p18k1aoc.cloudfront.net","d3l7tj34e9fc43.cloudfront.net"],"examples":["www.71n7.com"]},{"name":"Arbor","company":"LiveRamp","categories":["other"],"domains":["*.pippio.com"]},{"name":"Vidyard","homepage":"https://www.vidyard.com/","categories":["utility"],"domains":["*.vidyard.com"]},{"name":"linkpulse","categories":["analytics"],"domains":["*.lp4.io"]},{"name":"Edge Web Fonts","company":"Adobe Systems","categories":["cdn"],"domains":["*.edgefonts.net"],"examples":["use.edgefonts.net"]},{"name":"ShopiMind","company":"ShopIMind","categories":["ad"],"domains":["*.shopimind.com"]},{"name":"Feedbackify","company":"InsideMetrics","categories":["analytics"],"domains":["*.feedbackify.com"]},{"name":"Sidecar","categories":["other"],"domains":["*.getsidecar.com","d3v27wwd40f0xu.cloudfront.net"]},{"name":"SearchSpring","categories":["utility"],"domains":["*.searchspring.net"]},{"name":"DMD Marketing","homepage":"https://www.dmdconnects.com/","categories":["ad"],"domains":["*.medtargetsystem.com"]},{"name":"C3 Metrics","categories":["analytics"],"domains":["*.c3tag.com"]},{"name":"FirstImpression","categories":["ad"],"domains":["*.firstimpression.io"]},{"name":"GetIntent RTBSuite","company":"GetIntent","categories":["ad"],"domains":["*.adhigh.net"]},{"name":"unpkg","categories":["utility"],"domains":["*.npmcdn.com"]},{"name":"PerimeterX Bot Defender","company":"PerimeterX","categories":["utility"],"domains":["*.perimeterx.net","*.pxi.pub"]},{"name":"JustPremium Ads","company":"JustPremium","categories":["ad"],"domains":["*.justpremium.com"]},{"name":"Talkable","categories":["ad"],"domains":["*.talkable.com","d2jjzw81hqbuqv.cloudfront.net"],"examples":["www.talkable.com"]},{"name":"Steelhouse","categories":["ad"],"domains":["*.steelhousemedia.com"]},{"name":"Adtech (AOL)","categories":["ad"],"domains":["*.adtechus.com"]},{"name":"Technorati","company":"Synacor","categories":["ad"],"domains":["*.technoratimedia.com"]},{"name":"Drip","company":"The Numa Group","categories":["ad"],"domains":["*.getdrip.com"]},{"name":"VoiceFive","categories":["analytics"],"domains":["*.voicefive.com"]},{"name":"Adkontekst","categories":["ad"],"domains":["*.adkontekst.pl"]},{"name":"Cedato","categories":["ad"],"domains":["*.algovid.com","*.vdoserv.com"]},{"name":"TripAdvisor","categories":["content"],"domains":["*.jscache.com","*.tacdn.com","*.tamgrt.com","*.tripadvisor.com","*.viator.com","*.tripadvisor.co.uk"],"examples":["www.jscache.com","www.tamgrt.com"]},{"name":"Typepad","categories":["hosting"],"domains":["*.typepad.com"]},{"name":"Silverpop","company":"IBM","categories":["ad"],"domains":["*.mkt912.com","*.mkt922.com","*.mkt932.com","*.mkt941.com","*.mkt51.net","*.mkt61.net","*.pages01.net","*.pages02.net","*.pages03.net","*.pages04.net","*.pages05.net"]},{"name":"Attentive","homepage":"https://attentivemobile.com/","categories":["ad"],"domains":["*.attn.tv","*.attentivemobile.com"]},{"name":"Salesforce.com","categories":["ad"],"domains":["*.force.com","*.salesforce.com"],"examples":["secure.force.com"]},{"name":"WebSpectator","categories":["ad"],"domains":["*.webspectator.com"]},{"name":"Kaizen Platform","categories":["analytics"],"domains":["*.kaizenplatform.net"],"examples":["cdn.kaizenplatform.net","log-v4.kaizenplatform.net"]},{"name":"Global-e","categories":["hosting"],"domains":["*.global-e.com"]},{"name":"TruConversion","categories":["analytics"],"domains":["*.truconversion.com"]},{"name":"White Ops","categories":["utility"],"domains":["*.acexedge.com","*.tagsrvcs.com"]},{"name":"Accordant Media","categories":["ad"],"domains":["*.a3cloud.net"],"examples":["segment.a3cloud.net"]},{"name":"Keywee","categories":["ad"],"domains":["*.keywee.co"]},{"name":"Hupso Website Analyzer","company":"Hupso","categories":["analytics"],"domains":["*.hupso.com"]},{"name":"ThreatMetrix","categories":["utility"],"domains":["*.online-metrix.net"]},{"name":"eXelate","categories":["ad"],"domains":["*.exelator.com"]},{"name":"Delta Projects AB","categories":["ad"],"domains":["*.de17a.com"]},{"name":"Profitshare","categories":["ad"],"domains":["*.profitshare.ro"]},{"name":"TubeMogul","categories":["ad"],"domains":["*.tubemogul.com"]},{"name":"Ipify","homepage":"https://www.ipify.org","categories":["utility"],"domains":["*.ipify.org"],"examples":["api.ipify.org","geo.ipify.org"]},{"name":"Marketplace Web Service","company":"Amazon","categories":["other"],"domains":["*.ssl-images-amazon.com"]},{"name":"Key CDN","categories":["utility"],"domains":["*.kxcdn.com"]},{"name":"The ADEX","categories":["ad"],"domains":["*.theadex.com"]},{"name":"ZEDO","categories":["ad"],"domains":["*.zedo.com"]},{"name":"Sajari Pty","categories":["utility"],"domains":["*.sajari.com"]},{"name":"The Hut Group","categories":["content"],"domains":["*.thcdn.com"]},{"name":"Signyfyd","categories":["utility"],"domains":["*.signifyd.com"]},{"name":"Apester","categories":["analytics"],"domains":["*.apester.com","*.qmerce.com"]},{"name":"mParticle","homepage":"https://www.mparticle.com/","categories":["utility"],"domains":["*.mparticle.com"],"examples":["jssdks.mparticle.com","identity.mparticle.com"]},{"name":"AdSniper","categories":["ad"],"domains":["*.adsniper.ru","*.sniperlog.ru"]},{"name":"Time","categories":["content"],"domains":["*.timeinc.net"]},{"name":"SurveyMonkey","categories":["analytics"],"domains":["*.surveymonkey.com"]},{"name":"GIPHY","categories":["content"],"domains":["*.giphy.com"]},{"name":"Socialphotos","categories":["social"],"domains":["*.slpht.com"]},{"name":"Livefyre","categories":["content"],"domains":["*.fyre.co","*.livefyre.com"]},{"name":"Civic","categories":["hosting"],"domains":["*.civiccomputing.com"]},{"name":"Auth0","homepage":"https://auth0.com/","categories":["utility"],"domains":["*.auth0.com"],"examples":["cdn.auth0.com"]},{"name":"Flickr","categories":["content"],"domains":["*.flickr.com","*.staticflickr.com"]},{"name":"Reevoo","categories":["analytics"],"domains":["*.reevoo.com"]},{"name":"Sirv","categories":["other"],"domains":["*.sirv.com"]},{"name":"Underdog Media","categories":["ad"],"domains":["*.underdog.media","*.udmserve.net"]},{"name":"Petametrics","categories":["analytics"],"domains":["*.petametrics.com"]},{"name":"Sweet Tooth","categories":["ad"],"domains":["*.sweettooth.io"]},{"name":"Hola Networks","categories":["other"],"domains":["*.h-cdn.com"]},{"name":"Verizon Digital Media CDN","homepage":"https://www.verizondigitalmedia.com/","categories":["cdn"],"domains":["*.edgecastcdn.net","*.edgecastdns.net"]},{"name":"Zarget","categories":["analytics"],"domains":["*.zarget.com"]},{"name":"ResponseTap","categories":["analytics"],"domains":["*.adinsight.com","*.responsetap.com"]},{"name":"ReTargeter","categories":["ad"],"domains":["*.retargeter.com"]},{"name":"Yottaa","categories":["hosting"],"domains":["*.yottaa.com","*.yottaa.net"]},{"name":"Connatix","categories":["ad"],"domains":["*.connatix.com"]},{"name":"Klevu Search","company":"Klevu","categories":["utility"],"domains":["*.klevu.com"]},{"name":"Best Of Media S.A.","categories":["content"],"domains":["*.servebom.com"]},{"name":"AdTrue","company":"FPT AdTrue","categories":["ad"],"domains":["*.adtrue.com"]},{"name":"Customer.io","categories":["ad"],"domains":["*.customer.io"]},{"name":"Advance Magazine Group","categories":["content"],"domains":["*.condenastdigital.com","*.condenet.com","*.condenast.co.uk"]},{"name":"StreamRail","categories":["ad"],"domains":["*.streamrail.com","*.streamrail.net"]},{"name":"Opinion Stage","categories":["analytics"],"domains":["*.opinionstage.com"],"examples":["www.opinionstage.com"]},{"name":"CleverTap","categories":["analytics"],"domains":["d2r1yp2w7bby2u.cloudfront.net"]},{"name":"Fanplayr","categories":["analytics"],"domains":["*.fanplayr.com","d38nbbai6u794i.cloudfront.net"]},{"name":"Calendly","categories":["other"],"domains":["*.calendly.com"]},{"name":"Adobe Test & Target","company":"Adobe Systems","categories":["analytics"],"domains":["*.omtrdc.net"],"examples":["tt.omtrdc.net"]},{"name":"Navegg","categories":["ad"],"domains":["*.navdmp.com"]},{"name":"Sekindo","categories":["content"],"domains":["*.sekindo.com"]},{"name":"Conversio","categories":["ad"],"domains":["*.conversio.com"]},{"name":"CyberSource (Visa)","categories":["utility"],"domains":["*.authorize.net"]},{"name":"Pixalate","categories":["utility"],"domains":["*.adrta.com"]},{"name":"Reviews.io","categories":["analytics"],"domains":["*.reviews.io"]},{"name":"NetAffiliation","company":"Kwanco","categories":["ad"],"domains":["*.metaffiliation.com"]},{"name":"FuelX","categories":["ad"],"domains":["*.fuelx.com"]},{"name":"Touch Commerce","categories":["customer-success"],"domains":["*.inq.com","*.touchcommerce.com"]},{"name":"TripleLift","categories":["ad"],"domains":["*.3lift.com"]},{"name":"Ambassador","categories":["ad"],"domains":["*.getambassador.com"]},{"name":"epoq internet services","categories":["analytics"],"domains":["*.epoq.de"]},{"name":"Woopra","categories":["analytics"],"domains":["*.woopra.com"]},{"name":"Playbuzz","categories":["hosting"],"domains":["*.playbuzz.com"]},{"name":"Exponential Interactive","categories":["ad"],"domains":["*.exponential.com"]},{"name":"JustUno","categories":["ad"],"domains":["*.justuno.com"]},{"name":"Widespace","homepage":"https://www.widespace.com","categories":["ad"],"domains":["*.widespace.com"],"examples":["sync.widespace.com"]},{"name":"VisScore","categories":["analytics"],"domains":["*.visscore.com","d2hkbi3gan6yg6.cloudfront.net"]},{"name":"AWeber","categories":["ad"],"domains":["*.aweber.com"]},{"name":"AvantLink","categories":["ad"],"domains":["*.avmws.com"]},{"name":"Conversant Tag Manager","company":"Conversant","categories":["tag-manager"],"domains":["*.mplxtms.com"]},{"name":"Postcode Anywhere (Holdings)","categories":["utility"],"domains":["*.postcodeanywhere.co.uk"]},{"name":"Conversant","categories":["analytics"],"domains":["*.dotomi.com","*.dtmpub.com","*.emjcd.com","mediaplex.com","*.tqlkg.com","*.fastclick.net"],"examples":["www.tqlkg.com"]},{"name":"FLXone","company":"Teradata","categories":["ad"],"domains":["*.pangolin.blue","*.flx1.com","d2hlpp31teaww3.cloudfront.net"]},{"name":"Infinity Tracking","categories":["analytics"],"domains":["*.infinity-tracking.net"]},{"name":"reEmbed","categories":["other"],"domains":["*.reembed.com"]},{"name":"Kameleoon","categories":["analytics"],"domains":["*.kameleoon.com"]},{"name":"Impact Radius","categories":["ad"],"domains":["*.impactradius-event.com","*.impactradius-go.com","*.7eer.net","d3cxv97fi8q177.cloudfront.net","*.evyy.net","*.ojrq.net"],"examples":["a.impactradius-go.com","microsoft-uk.evyy.net"]},{"name":"Heroku","categories":["other"],"domains":["*.herokuapp.com"]},{"name":"AdsWizz","categories":["ad"],"domains":["*.adswizz.com"]},{"name":"MaxMind","categories":["utility"],"domains":["*.maxmind.com"]},{"name":"Pusher","homepage":"https://pusher.com/","categories":["utility"],"domains":["*.pusher.com","*.pusherapp.com"],"examples":["stats.pusher.com"]},{"name":"Admitad","categories":["ad"],"domains":["*.lenmit.com"]},{"name":"AdsNative","categories":["ad"],"domains":["*.adsnative.com"]},{"name":"Viacom","categories":["content"],"domains":["*.mtvnservices.com"]},{"name":"Cookie-Script.com","categories":["utility"],"domains":["*.cookie-script.com"]},{"name":"MonetizeMore","categories":["ad"],"domains":["*.m2.ai"]},{"name":"Mediahawk","categories":["analytics"],"domains":["*.mediahawk.co.uk"]},{"name":"GoSquared","homepage":"https://www.gosquared.com","categories":["analytics"],"domains":["*.gosquared.com","d1l6p2sc9645hc.cloudfront.net"],"examples":["data.gosquared.com","data2.gosquared.com"]},{"name":"Datonics","categories":["ad"],"domains":["*.pro-market.net"],"examples":["pbid.pro-market.net"]},{"name":"Adobe Marketing Cloud","company":"Adobe Systems","categories":["ad"],"domains":["*.adobetag.com"]},{"name":"News","categories":["social"],"domains":["*.news.com.au","*.newsanalytics.com.au","*.newsapi.com.au","*.newscdn.com.au","*.newsdata.com.au","*.newsdiscover.com.au","*.news-static.com"]},{"name":"Experian Cross-Channel Marketing Platform","company":"Experian","categories":["marketing"],"domains":["*.eccmp.com","*.ccmp.eu"]},{"name":"SkyScanner","categories":["content"],"domains":["*.skyscanner.net"],"examples":["api.skyscanner.net"]},{"name":"Vibrant Media","categories":["ad"],"domains":["*.intellitxt.com","*.picadmedia.com"]},{"name":"Mobify","categories":["utility"],"domains":["*.mobify.com","*.mobify.net"]},{"name":"Bookatable","categories":["content"],"domains":["*.bookatable.com","*.livebookings.com"]},{"name":"SecuredVisit","company":"4Cite Marketing","categories":["ad"],"domains":["*.securedvisit.com"]},{"name":"[24]7","categories":["customer-success"],"domains":["*.247-inc.net","*.247inc.net","d1af033869koo7.cloudfront.net"]},{"name":"Transifex","categories":["utility"],"domains":["*.transifex.com"]},{"name":"Tagboard","categories":["social"],"domains":["*.tagboard.com"]},{"name":"Council ad Network","categories":["ad"],"domains":["*.counciladvertising.net"]},{"name":"WalkMe","categories":["customer-success"],"domains":["*.walkme.com"]},{"name":"Betgenius","company":"Genius Sports","categories":["content"],"domains":["*.connextra.com"]},{"name":"Exactag","categories":["ad"],"domains":["*.exactag.com"]},{"name":"Knight Lab","company":"Northwestern University","categories":["utility"],"domains":["*.knightlab.com"]},{"name":"Reflektion","categories":["analytics"],"domains":["*.reflektion.com","d26opx5dl8t69i.cloudfront.net"]},{"name":"Expedia","categories":["content"],"domains":["*.travel-assets.com","*.trvl-media.com","*.trvl-px.com","*.uciservice.com"],"examples":["www.trvl-px.com","www.uciservice.com"]},{"name":"Performio","categories":["ad"],"domains":["*.performax.cz"],"examples":["ut.performax.cz"]},{"name":"Janrain","categories":["analytics"],"domains":["*.janrain.com","*.janrainbackplane.com","*.rpxnow.com","d3hmp0045zy3cs.cloudfront.net"]},{"name":"Resonance Insights","categories":["analytics"],"domains":["*.res-x.com"]},{"name":"cloudIQ","categories":["analytics"],"domains":["*.cloud-iq.com"]},{"name":"Snack Media","categories":["content"],"domains":["*.snack-media.com"]},{"name":"Ekm Systems","categories":["analytics"],"domains":["*.ekmsecure.com","*.ekmpinpoint.co.uk"],"examples":["globalstats.ekmsecure.com"]},{"name":"Wow Analytics","categories":["analytics"],"domains":["*.wowanalytics.co.uk"]},{"name":"AdvertServe","categories":["ad"],"domains":["*.advertserve.com"]},{"name":"Pingdom RUM","homepage":"https://www.pingdom.com/product/performance-monitoring/","categories":["analytics"],"domains":["*.pingdom.net"],"examples":["rum-static.pingdom.net","rum-collector-2.pingdom.net"]},{"name":"DialogTech SourceTrak","company":"DialogTech","categories":["ad"],"domains":["d31y97ze264gaa.cloudfront.net"]},{"name":"bRealTime","categories":["ad"],"domains":["*.brealtime.com"]},{"name":"Tag Inspector","company":"InfoTrust","categories":["analytics"],"domains":["d22xmn10vbouk4.cloudfront.net"]},{"name":"Zmags","categories":["marketing"],"domains":["*.zmags.com"]},{"name":"LeasdBoxer","company":"LeadBoxer","categories":["ad"],"domains":["*.leadboxer.com"]},{"name":"Friendbuy","categories":["ad"],"domains":["*.friendbuy.com","djnf6e5yyirys.cloudfront.net"]},{"name":"Acceptable Ads","homepage":"https://acceptableads.com/","categories":["ad"],"domains":["*.aaxads.com","*.aaxdetect.com"]},{"name":"Onet","categories":["ad"],"domains":["*.onet.pl"]},{"name":"Netlify","homepage":"https://www.netlify.com/","categories":["utility"],"domains":["*.netlify.com","*.netlifyusercontent.com"],"examples":["cloud.netlifyusercontent.com"]},{"name":"Twitter Online Conversion Tracking","company":"Twitter","categories":["ad"],"domains":["*.ads-twitter.com","analytics.twitter.com"],"examples":["static.ads-twitter.com"]},{"name":"AdRiver","categories":["ad"],"domains":["*.adriver.ru"]},{"name":"Proper Media","categories":["content"],"domains":["*.proper.io"]},{"name":"Storygize","categories":["ad"],"domains":["*.storygize.net"],"examples":["www.storygize.net"]},{"name":"Oracle Recommendations On Demand","company":"Oracle","categories":["analytics"],"domains":["*.atgsvcs.com"]},{"name":"Raygun","categories":["utility"],"domains":["*.raygun.io"]},{"name":"Rakuten LinkShare","company":"Rakuten","categories":["ad"],"domains":["*.linksynergy.com"]},{"name":"BlueCava","categories":["ad"],"domains":["*.bluecava.com"]},{"name":"Hull.js","categories":["utility"],"domains":["*.hull.io","*.hullapp.io"]},{"name":"PERFORM","categories":["content"],"domains":["*.performgroup.com"]},{"name":"Moxie","homepage":"https://www.gomoxie.com/","categories":["utility"],"domains":["*.gomoxie.solutions"]},{"name":"Vee24","categories":["customer-success"],"domains":["*.vee24.com"]},{"name":"Aggregate Knowledge","company":"Neustar","categories":["ad"],"domains":["*.agkn.com"]},{"name":"Cookie Reports","categories":["utility"],"domains":["*.cookiereports.com"]},{"name":"PlayAd Media Group","categories":["ad"],"domains":["*.youplay.se"]},{"name":"Exponea","categories":["analytics"],"domains":["*.exponea.com"]},{"name":"AIR.TV","categories":["ad"],"domains":["*.air.tv"]},{"name":"SlimCut Media Outstream","company":"SlimCut Media","categories":["ad"],"domains":["*.freeskreen.com"]},{"name":"Mopinion","categories":["analytics"],"domains":["*.mopinion.com"]},{"name":"Dynamic Converter","categories":["utility"],"domains":["*.dynamicconverter.com"]},{"name":"Remintrex","company":"SmartUp Venture","categories":["ad"],"domains":["*.remintrex.com"]},{"name":"Attribution","categories":["ad"],"domains":["*.attributionapp.com"]},{"name":"Browser-Update.org","categories":["other"],"domains":["*.browser-update.org"]},{"name":"Sailthru","categories":["analytics"],"domains":["*.sail-horizon.com","*.sail-personalize.com","*.sail-track.com"]},{"name":"AnswerDash","categories":["customer-success"],"domains":["*.answerdash.com"],"examples":["p1.answerdash.com"]},{"name":"Ziff Davis Tech","categories":["ad"],"domains":["*.adziff.com","*.zdbb.net"]},{"name":"Adthink","company":"Adthink Media","categories":["ad"],"domains":["*.adxcore.com","*.dcoengine.com"],"examples":["d.adxcore.com"]},{"name":"Site24x7 Real User Monitoring","company":"Site24x7","categories":["analytics"],"domains":["*.site24x7rum.com"]},{"name":"SpringServer","categories":["ad"],"domains":["*.springserve.com"]},{"name":"Freespee","categories":["customer-success"],"domains":["*.freespee.com"],"examples":["analytics.freespee.com"]},{"name":"VidPulse","categories":["analytics"],"domains":["*.vidpulse.com"]},{"name":"InAuth","categories":["utility"],"homepage":"https://www.inauth.com/","domains":["*.cdn-net.com"],"examples":["uk.cdn-net.com"]},{"name":"MLveda","categories":["utility"],"domains":["*.mlveda.com"],"examples":["www.mlveda.com"]},{"name":"Microad","categories":["ad"],"domains":["*.microad.jp"]},{"name":"ShopRunner","categories":["content"],"domains":["*.shoprunner.com","*.s-9.us"]},{"name":"Reactful","categories":["analytics"],"domains":["*.reactful.com"]},{"name":"Vergic AB","categories":["customer-success"],"domains":["*.psplugin.com"]},{"name":"Alliance for Audited Media","categories":["ad"],"domains":["*.aamsitecertifier.com"]},{"name":"Forter","categories":["utility"],"domains":["*.forter.com"]},{"name":"Swoop","categories":["ad"],"domains":["*.swoop.com"]},{"name":"Gfycat","company":"Gycat","categories":["utility"],"domains":["*.gfycat.com"]},{"name":"Optimove","company":"Mobius Solutions","categories":["analytics"],"domains":["*.optimove.net"]},{"name":"LoginRadius","categories":["social"],"domains":["*.loginradius.com"]},{"name":"Flockler","categories":["ad"],"domains":["*.flockler.com"]},{"name":"Moovweb","categories":["utility"],"domains":["*.moovweb.net"]},{"name":"Cachefly","categories":["utility"],"domains":["*.cachefly.net"]},{"name":"emetriq","homepage":"https://www.emetriq.com/","categories":["ad"],"domains":["*.emetriq.de","*.xplosion.de"]},{"name":"CANDDi","company":"Campaign and Digital Intelligence","categories":["ad"],"domains":["*.canddi.com"]},{"name":"Braintree Payments","company":"Paypal","categories":["utility"],"domains":["*.braintreegateway.com"]},{"name":"Meltwater Group","categories":["customer-success"],"domains":["*.meltwaternews.com"]},{"name":"Video Media Groep","categories":["ad"],"domains":["*.vmg.host","*.inpagevideo.nl"]},{"name":"Polldaddy","company":"Automattic","categories":["analytics"],"domains":["polldaddy.com"]},{"name":"Triblio","categories":["marketing"],"domains":["*.tribl.io"]},{"name":"Wufoo","categories":["utility"],"domains":["*.wufoo.com"]},{"name":"User Replay","categories":["analytics"],"domains":["*.userreplay.net"]},{"name":"Barilliance","categories":["analytics"],"domains":["*.barilliance.net","dn3y71tq7jf07.cloudfront.net"]},{"name":"Boomtrain","categories":["ad"],"domains":["*.boomtrain.com","*.boomtrain.net"]},{"name":"Extole","categories":["ad"],"domains":["*.extole.com","*.extole.io"],"examples":["origin.extole.io"]},{"name":"infogr.am","categories":["utility"],"domains":["*.infogr.am","*.jifo.co"]},{"name":"Catchpoint","homepage":"https://www.catchpoint.com/","categories":["analytics"],"domains":["*.3gl.net"]},{"name":"InSkin Media","categories":["ad"],"domains":["*.inskinad.com","*.inskinmedia.com"]},{"name":"Kargo","categories":["marketing"],"domains":["*.kargo.com"]},{"name":"Byside","homepage":"http://www.byside.com","categories":["analytics"],"domains":["*.byside.com"],"examples":["byce2.byside.com","wce2.byside.com"]},{"name":"CNET Content Solutions","company":"CBS Interactive","categories":["content"],"domains":["*.cnetcontent.com"],"examples":["cdn.cnetcontent.com","ws.cnetcontent.com"]},{"name":"HotelsCombined","categories":["content"],"domains":["*.datahc.com"]},{"name":"Hawk Search","categories":["utility"],"domains":["*.hawksearch.com"]},{"name":"Vergic Engage Platform","company":"Vergic","categories":["customer-success"],"domains":["*.vergic.com"]},{"name":"Vertical Mass","categories":["ad"],"domains":["*.vmweb.net"]},{"name":"ShopStorm","categories":["utility"],"domains":["*.shopstorm.com"]},{"name":"Borderfree","company":"pitney bowes","categories":["utility"],"domains":["*.borderfree.com","*.fiftyone.com"]},{"name":"Fonecall","categories":["analytics"],"domains":["*.web-call-analytics.com"]},{"name":"PebblePost","categories":["ad"],"domains":["*.pbbl.co"]},{"name":"DemandJump","categories":["analytics"],"domains":["*.demandjump.com"]},{"name":"Kiosked","categories":["ad"],"domains":["*.kiosked.com"]},{"name":"Ad6Media","categories":["ad"],"domains":["*.ad6media.fr"]},{"name":"The Publisher Desk","categories":["ad"],"domains":["*.206ads.com","*.publisherdesk.com"]},{"name":"Ghostery Enterprise","company":"Ghostery","categories":["marketing"],"domains":["*.betrad.com"]},{"name":"content.ad","categories":["ad"],"domains":["*.content.ad"]},{"name":"Innovid","categories":["ad"],"homepage":"https://www.innovid.com/","domains":["*.innovid.com"],"examples":["ag.innovid.com","rtr.innovid.com"]},{"name":"RightNow Service Cloud","company":"Oracle","categories":["customer-success"],"domains":["*.rightnowtech.com","*.rnengage.com"]},{"name":"Polyfill service","company":"Polyfill.io","categories":["other"],"domains":["*.polyfill.io"]},{"name":"Prezi","categories":["utility"],"domains":["*.prezi.com"]},{"name":"Sourcepoint","categories":["ad"],"domains":["*.decenthat.com","*.fallingfalcon.com","*.summerhamster.com","d2lv4zbk7v5f93.cloudfront.net","d3qxwzhswv93jk.cloudfront.net"],"examples":["www.decenthat.com","www.fallingfalcon.com","www.summerhamster.com"]},{"name":"PowerFront","categories":["hosting"],"domains":["*.inside-graph.com"]},{"name":"Bidswitch","homepage":"https://www.bidswitch.com/","categories":["ad"],"domains":["*.bidswitch.net"],"examples":["x.bidswitch.net"]},{"name":"Bet365","categories":["ad"],"domains":["*.bet365affiliates.com"]},{"name":"RichRelevance","categories":["analytics"],"domains":["*.richrelevance.com"]},{"name":"Elecard StreamEye","company":"Elecard","categories":["other"],"domains":["*.streameye.net"]},{"name":"NaviStone","categories":["ad"],"domains":["*.murdoog.com"]},{"name":"MailPlus","categories":["ad"],"domains":["*.mailplus.nl"]},{"name":"Cross Pixel Media","categories":["ad"],"domains":["*.crsspxl.com"]},{"name":"TurnTo","homepage":"https://www.turntonetworks.com/","categories":["utility"],"domains":["*.turnto.com"]},{"name":"Connexity","homepage":"http://connexity.com/","categories":["analytics"],"domains":["*.connexity.net"]},{"name":"Iterate","homepage":"https://iteratehq.com/","categories":["analytics"],"domains":["*.iteratehq.com"]},{"name":"OnScroll","categories":["ad"],"domains":["*.onscroll.com"]},{"name":"Web Dissector","company":"Beijing Gridsum Technologies","categories":["analytics"],"domains":["*.gridsumdissector.com","*.webdissector.com"],"examples":["www.webdissector.com"]},{"name":"Bluecore","categories":["analytics"],"domains":["*.bluecore.com"],"examples":["www.bluecore.com"]},{"name":"Flipboard","categories":["social"],"domains":["*.flipboard.com"]},{"name":"UPS i-parcel","company":"UPS","categories":["other"],"domains":["*.i-parcel.com"]},{"name":"TechTarget","categories":["content"],"domains":["*.techtarget.com","*.ttgtmedia.com"]},{"name":"Realytics","categories":["analytics"],"domains":["dcniko1cv0rz.cloudfront.net","*.realytics.net"]},{"name":"Dropbox","categories":["utility"],"domains":["*.dropboxusercontent.com"]},{"name":"StumbleUpon","categories":["content"],"domains":["*.stumble-upon.com","*.stumbleupon.com"]},{"name":"ReCollect","categories":["utility"],"domains":["*.recollect.net"]},{"name":"AdSpruce","categories":["ad"],"domains":["*.adspruce.com"]},{"name":"RebelMouse","categories":["ad"],"domains":["*.rebelmouse.com","*.rbl.ms"],"examples":["www.rebelmouse.com"]},{"name":"Intilery","categories":["customer-success"],"domains":["*.intilery-analytics.com"]},{"name":"Adunity","categories":["ad"],"domains":["*.adunity.com"]},{"name":"UpSellit","categories":["analytics"],"domains":["*.upsellit.com"],"examples":["www.upsellit.com"]},{"name":"AdSupply","categories":["ad"],"domains":["*.doublepimp.com"]},{"name":"Better Business Bureau","categories":["analytics"],"domains":["*.bbb.org"]},{"name":"Spot.IM","categories":["social"],"domains":["*.spot.im"]},{"name":"Improve Digital","categories":["ad"],"domains":["*.360yield.com"]},{"name":"Sociomantic Labs","company":"DunnHumby","categories":["ad"],"domains":["*.sociomantic.com"]},{"name":"MathJax","categories":["utility"],"domains":["*.mathjax.org"]},{"name":"Qualtrics","categories":["analytics"],"domains":["*.qualtrics.com"]},{"name":"ConvertMedia","categories":["ad"],"domains":["*.admailtiser.com","*.basebanner.com","*.cmbestsrv.com","*.vidfuture.com","*.zorosrv.com"],"examples":["www.cmbestsrv.com"]},{"name":"Soundest","categories":["ad"],"domains":["*.soundestlink.com","*.soundest.net"]},{"name":"Xaxis","homepage":"https://www.xaxis.com/","categories":["ad"],"domains":["*.247realmedia.com","*.mookie1.com","*.gmads.net"],"examples":["t.mookie1.com","odr.mookie1.com"]},{"name":"Research Online","company":"Skills Development Scotland","categories":["content"],"domains":["*.org.uk"],"examples":["www.researchonline.org.uk"]},{"name":"DistroScale","categories":["ad"],"domains":["*.jsrdn.com"]},{"name":"StackExchange","categories":["social"],"domains":["*.sstatic.net"]},{"name":"BuySellAds","categories":["ad"],"domains":["*.buysellads.com"]},{"name":"Reklama","categories":["ad"],"domains":["*.o2.pl","*.wp.pl"],"examples":["dot.wp.pl","px.o2.pl","px.wp.pl"]},{"name":"eGain","categories":["analytics"],"domains":["*.analytics-egain.com","*.egain.com"]},{"name":"Sonobi","categories":["ad"],"domains":["*.sonobi.com"]},{"name":"AliveChat","company":"AYU Technology Solutions","categories":["customer-success"],"domains":["*.websitealive.com","*.websitealive7.com"]},{"name":"Zolando","categories":["content"],"domains":["*.ztat.net"]},{"name":"AdCurve","categories":["ad"],"domains":["*.shop2market.com"]},{"name":"Pagefair","categories":["ad"],"domains":["*.pagefair.com","*.pagefair.net"]},{"name":"StackAdapt","categories":["ad"],"domains":["*.stackadapt.com"]},{"name":"United Internet","categories":["hosting"],"domains":["*.uicdn.com"]},{"name":"Nanorep","company":"Nanorep Technologies","categories":["customer-success"],"domains":["*.nanorep.com"]},{"name":"Fastest Forward","categories":["analytics"],"domains":["*.gaug.es"]},{"name":"Ceros","categories":["other"],"domains":["ceros.com","view.ceros.com"]},{"name":"Investis","categories":["utility"],"domains":["*.investis.com"]},{"name":"Channel.me","categories":["customer-success"],"domains":["*.channel.me"]},{"name":"ARM","categories":["analytics"],"domains":["*.tag4arm.com"]},{"name":"Webtrends","categories":["analytics"],"domains":["*.webtrends.com","*.webtrendslive.com","d1q62gfb8siqnm.cloudfront.net"]},{"name":"Scoota","categories":["ad"],"domains":["*.rockabox.co","*.scoota.co","d31i2625d5nv27.cloudfront.net","dyjnzf8evxrp2.cloudfront.net"]},{"name":"TrafficJunky","homepage":"https://www.trafficjunky.com/","categories":["ad"],"domains":["*.contentabc.com","*.trafficjunky.net"],"examples":["ads2.contentabc.com","hw-cdn.contentabc.com","media.trafficjunky.net","ads.trafficjunky.net","hw-cdn.trafficjunky.net"]},{"name":"PrintFriendly","categories":["utility"],"domains":["*.printfriendly.com"]},{"name":"Datawrapper","categories":["utility"],"domains":["*.datawrapper.de","*.dwcdn.net"],"examples":["www.datawrapper.de"]},{"name":"Click4Assistance","categories":["customer-success"],"domains":["*.click4assistance.co.uk"]},{"name":"Glassdoor","categories":["content"],"domains":["*.glassdoor.com"]},{"name":"Highwinds","categories":["utility"],"domains":["*.hwcdn.net"]},{"name":"YoYo","categories":["utility"],"domains":["*.goadservices.com"]},{"name":"Webtrekk","categories":["analytics"],"domains":["*.wbtrk.net","*.webtrekk-asia.net","*.webtrekk.net","*.wt-eu02.net"]},{"name":"Fastly Insights","homepage":"https://insights.fastlylabs.com","categories":["analytics"],"domains":["*.fastly-insights.com"],"examples":["www.fastly-insights.com"]},{"name":"HP Optimost","company":"Hewlett-Packard Development Company","categories":["marketing"],"domains":["*.hp.com","d2uncb19xzxhzx.cloudfront.net"],"examples":["by.marketinghub.hp.com","marketinghub.hp.com"]},{"name":"Eyeota","categories":["ad"],"domains":["*.eyeota.net"]},{"name":"PhotoBucket","categories":["content"],"domains":["*.photobucket.com"]},{"name":"ContextWeb","categories":["ad"],"domains":["*.contextweb.com"]},{"name":"Captify Media","categories":["ad"],"domains":["*.cpx.to"]},{"name":"Intent IQ","categories":["ad"],"domains":["*.intentiq.com"]},{"name":"Vindico","company":"Viant","categories":["ad"],"domains":["*.vindicosuite.com"]},{"name":"Pictela (AOL)","categories":["analytics"],"domains":["*.pictela.net"]},{"name":"PubNation","categories":["ad"],"domains":["*.pubnation.com"]},{"name":"Freshchat","homepage":"https://www.freshworks.com/live-chat-software/","categories":["utility"],"domains":["*.freshchat.com"]},{"name":"Bridgewell DSP","homepage":"https://www.bridgewell.com/","categories":["ad"],"domains":["*.scupio.com"],"examples":["img.scupio.com"]},{"name":"PageSense","homepage":"https://www.zoho.com/pagesense/","categories":["analytics"],"domains":["*.pagesense.io"],"examples":["cdn.pagesense.io"]},{"name":"Wicked Reports","homepage":"https://www.wickedreports.com/","categories":["marketing"],"domains":["*.wickedreports.com"],"examples":["widget.wickedreports.com"]},{"name":"Pendo","homepage":"https://www.pendo.io","categories":["analytics"],"domains":["*.pendo.io"],"examples":["app.pendo.io"]},{"name":"Dynatrace","categories":["analytics"],"domains":["*.ruxit.com","js-cdn.dynatrace.com"]},{"name":"Click Guardian","homepage":"https://www.clickguardian.co.uk/","categories":["advertising"],"domains":["*.clickguardian.app","*.clickguardian.co.uk"],"examples":["v2.clickguardian.app","protection.clickguardian.co.uk"]}];
+},{}],169:[function(require,module,exports){
module.exports=require("./lib/subsets/httparchive-nostats.js");
-},{"./lib/subsets/httparchive-nostats.js":174}],173:[function(require,module,exports){
-const DOMAIN_IN_URL_REGEX=/:\/\/(.*?)(\/|$)/;
-const DOMAIN_CHARACTERS=/[a-z0-9.-]+\.[a-z0-9]+/i;
+},{"./lib/subsets/httparchive-nostats.js":171}],170:[function(require,module,exports){
+const DOMAIN_IN_URL_REGEX=/:\/\/(\S*?)(:\d+)?(\/|$)/;
+const DOMAIN_CHARACTERS=/([a-z0-9.-]+\.[a-z0-9]+|localhost)/i;
+const IP_REGEX=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
const ROOT_DOMAIN_REGEX=/[^.]+\.([^.]+|(gov|com|co|ne)\.\w{2})$/i;
function getDomainFromOriginOrURL(originOrURL){
+if(typeof originOrURL!=='string')return null;
+if(originOrURL.length>10000||originOrURL.startsWith('data:'))return null;
if(DOMAIN_IN_URL_REGEX.test(originOrURL))return originOrURL.match(DOMAIN_IN_URL_REGEX)[1];
if(DOMAIN_CHARACTERS.test(originOrURL))return originOrURL.match(DOMAIN_CHARACTERS)[0];
throw new Error(`Unable to find domain in "${originOrURL}"`);
@@ -65509,6 +65104,8 @@ throw new Error(`Unable to find domain in "${originOrURL}"`);
function getRootDomain(originOrURL){
const domain=getDomainFromOriginOrURL(originOrURL);
+if(!domain)return null;
+if(IP_REGEX.test(domain))return domain;
const match=domain.match(ROOT_DOMAIN_REGEX);
return match&&match[0]||domain;
}
@@ -65516,6 +65113,7 @@ return match&&match[0]||domain;
function getEntityInDataset(entityByDomain,entityByRootDomain,originOrURL){
const domain=getDomainFromOriginOrURL(originOrURL);
const rootDomain=getRootDomain(domain);
+if(!domain||!rootDomain)return undefined;
if(entityByDomain.has(domain))return entityByDomain.get(domain);
if(entityByRootDomain.has(rootDomain))return entityByRootDomain.get(rootDomain);
return undefined;
@@ -65535,10 +65133,9 @@ entity.averageExecutionTime=entity.totalExecutionTime/entity.totalOccurrences;
for(const domain of entity.domains){
if(entityByDomain.has(domain))throw new Error(`Duplicate domain ${domain}`);
entityByDomain.set(domain,entity);
+
const rootDomain=getRootDomain(domain);
-if(entityByRootDomain.has(rootDomain)&&entityByRootDomain.get(rootDomain)!==entity){
-entityByRootDomain.set(rootDomain,false);
-}else{
+if(domain.startsWith('*.')){
entityByRootDomain.set(rootDomain,entity);
}
}
@@ -65554,12 +65151,12 @@ return{getEntity,getRootDomain,entities};
module.exports={createAPIFromDataset};
-},{}],174:[function(require,module,exports){
+},{}],171:[function(require,module,exports){
const{createAPIFromDataset}=require('../create-entity-finder-api.js');
const entities=require('../../dist/entities-httparchive-nostats.json');
module.exports=createAPIFromDataset(entities);
-},{"../../dist/entities-httparchive-nostats.json":171,"../create-entity-finder-api.js":173}],175:[function(require,module,exports){
+},{"../../dist/entities-httparchive-nostats.json":168,"../create-entity-finder-api.js":170}],172:[function(require,module,exports){
(function(setImmediate,clearImmediate){
var nextTick=require('process/browser.js').nextTick;
var apply=Function.prototype.apply;
@@ -65638,7 +65235,7 @@ exports.clearImmediate=typeof clearImmediate==="function"?clearImmediate:functio
delete immediateIds[id];
};
}).call(this,require("timers").setImmediate,require("timers").clearImmediate);
-},{"process/browser.js":145,"timers":175}],176:[function(require,module,exports){
+},{"process/browser.js":142,"timers":172}],173:[function(require,module,exports){
(function(global){
@@ -65709,15 +65306,15 @@ return String(val).toLowerCase()==='true';
}
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{}],177:[function(require,module,exports){
+},{}],174:[function(require,module,exports){
arguments[4][94][0].apply(exports,arguments);
-},{"dup":94}],178:[function(require,module,exports){
+},{"dup":94}],175:[function(require,module,exports){
arguments[4][95][0].apply(exports,arguments);
-},{"./support/isBuffer":177,"_process":145,"dup":95,"inherits":113}],179:[function(require,module,exports){
+},{"./support/isBuffer":174,"_process":142,"dup":95,"inherits":113}],176:[function(require,module,exports){
module.exports={
-"version":"5.2.0"};
+"version":"5.5.0"};
-},{}],180:[function(require,module,exports){
+},{}],177:[function(require,module,exports){
@@ -65728,12 +65325,231 @@ module.exports={
const stackPacks=[
-require('./packs/wordpress.js')];
+require('./packs/wordpress.js'),
+require('./packs/react.js'),
+require('./packs/angular.js'),
+require('./packs/amp.js'),
+require('./packs/magento.js')];
module.exports=stackPacks;
-},{"./packs/wordpress.js":181}],181:[function(require,module,exports){
+},{"./packs/amp.js":178,"./packs/angular.js":179,"./packs/magento.js":180,"./packs/react.js":181,"./packs/wordpress.js":182}],178:[function(require,module,exports){
+(function(__filename){
+
+
+
+
+
+
+
+'use strict';
+
+const i18n=require('../../lighthouse-core/lib/i18n/i18n.js');
+
+const ampIcon=`data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"%3E%3Cpath d="M171.887 116.28l-53.696 89.36h-9.728l9.617-58.227-30.2.047a4.852 4.852 0 01-4.855-4.855c0-1.152 1.07-3.102 1.07-3.102l53.52-89.254 9.9.043-9.86 58.317 30.413-.043a4.852 4.852 0 014.855 4.855c0 1.088-.427 2.044-1.033 2.854l.004.004zM128 0C57.306 0 0 57.3 0 128s57.306 128 128 128 128-57.306 128-128S198.7 0 128 0z" fill="%230379c4" fill-rule="evenodd"/%3E%3C/svg%3E`;
+
+const UIStrings={
+
+uses_webp_images:'Consider displaying all your `amp-img` components in WebP formats while specifying an appropriate fallback for other browsers. [Learn more](https://amp.dev/documentation/components/amp-img/#example:-specifying-a-fallback-image).',
+
+offscreen_images:'Ensure that you are you using valid `amp-img` tags for your images which automatically lazy-load outside the first viewport. [Learn more](https://amp.dev/documentation/guides-and-tutorials/develop/media_iframes_3p/?format=websites#images).',
+
+render_blocking_resources:'Use tools such as [AMP Optimizer](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer) to [server-side render AMP layouts](https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/server-side-rendering/).',
+
+unminified_css:'Refer to the [AMP documentation](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/style_pages/) to ensure all your styles are supported.',
+
+efficient_animated_content:'For animated content, use [amp-anim](https://amp.dev/documentation/components/amp-anim/) to minimize CPU usage while the content remains offscreen.',
+
+uses_responsive_images:'The `amp-img` element supports the `srcset` attribute to specify which image assets to use based on the screen size. [Learn more](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+
+module.exports={
+id:'amp',
+iconDataURL:ampIcon,
+title:'AMP',
+descriptions:{
+'uses-webp-images':str_(UIStrings.uses_webp_images),
+'offscreen-images':str_(UIStrings.offscreen_images),
+'render-blocking-resources':str_(UIStrings.render_blocking_resources),
+'unminified-css':str_(UIStrings.unminified_css),
+'efficient-animated-content':str_(UIStrings.efficient_animated_content),
+'uses-responsive-images':str_(UIStrings.uses_responsive_images)}};
+
+
+module.exports.UIStrings=UIStrings;
+
+}).call(this,"/stack-packs/packs/amp.js");
+},{"../../lighthouse-core/lib/i18n/i18n.js":67}],179:[function(require,module,exports){
+(function(__filename){
+
+
+
+
+
+
+
+'use strict';
+
+const i18n=require('../../lighthouse-core/lib/i18n/i18n.js');
+
+const angularIcon=`data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 250"%3E%3Cpath fill="%23dd0031" d="M125 30L31.9 63.2l14.2 123.1L125 230l78.9-43.7 14.2-123.1z"/%3E%3Cpath fill="%23c3002f" d="M125 30v22.2-.1V230l78.9-43.7 14.2-123.1L125 30z"/%3E%3Cpath d="M125 52.1L66.8 182.6h21.7l11.7-29.2h49.4l11.7 29.2H183L125 52.1zm17 83.3h-34l17-40.9 17 40.9z" fill="%23fff"/%3E%3C/svg%3E`;
+
+const UIStrings={
+
+total_byte_weight:'Apply [route-level code-splitting](https://web.dev/route-level-code-splitting-in-angular/) to minimize the size of your JavaScript bundles. Also, consider precaching assets with the [Angular service worker](https://web.dev/precaching-with-the-angular-service-worker/).',
+
+unminified_warning:'If you are using Angular CLI, ensure that builds are generated in production mode. [Learn more](https://angular.io/guide/deployment#enable-runtime-production-mode).',
+
+unused_javascript:'If you are using Angular CLI, include source maps into your production build to inspect your bundles. [Learn more](https://angular.io/guide/deployment#inspect-the-bundles).',
+
+uses_responsive_images:'Consider using the `BreakpointObserver` utility in the Component Dev Kit (CDK) to manage image breakpoints. [Learn more](https://material.angular.io/cdk/layout/overview).',
+
+uses_rel_preload:'Preload routes ahead of time to speed up navigation. [Learn more](https://web.dev/route-preloading-in-angular/).',
+
+dom_size:'Consider virtual scrolling with the Component Dev Kit (CDK) if very large lists are being rendered. [Learn more](https://web.dev/virtualize-lists-with-angular-cdk/).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+
+module.exports={
+id:'angular',
+iconDataURL:angularIcon,
+title:'Angular',
+descriptions:{
+'total-byte-weight':str_(UIStrings.total_byte_weight),
+'unminified-css':str_(UIStrings.unminified_warning),
+'unminified-javascript':str_(UIStrings.unminified_warning),
+'unused-javascript':str_(UIStrings.unused_javascript),
+'uses-responsive-images':str_(UIStrings.uses_responsive_images),
+'uses-rel-preload':str_(UIStrings.uses_rel_preload),
+'dom-size':str_(UIStrings.dom_size)}};
+
+
+module.exports.UIStrings=UIStrings;
+
+}).call(this,"/stack-packs/packs/angular.js");
+},{"../../lighthouse-core/lib/i18n/i18n.js":67}],180:[function(require,module,exports){
+(function(__filename){
+
+
+
+
+
+
+
+'use strict';
+
+const i18n=require('../../lighthouse-core/lib/i18n/i18n.js');
+
+const magentoIcon=`data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" fill="%23f26322" viewBox="0 0 1000 1000"%3E%3Cpath d="M916.9 267.4v465.3l-111.3 67.4V331.4l-1.5-.9-303.9-189-304.6 189.2-1.2.8V799L83.1 732.6V267.4l.7-.4L500.3 10l416 257 .6.4zM560.7 468.5v383.3L500.3 890l-61-38.2V306.7l-136 84.3v476.6l197 122.5 196.4-122.5V391l-136-84.3v161.8z"/%3E%3C/svg%3E`;
+
+const UIStrings={
+
+uses_webp_images:'Consider searching the [Magento Marketplace](https://marketplace.magento.com/catalogsearch/result/?q=webp) for a variety of third-party extensions to leverage newer image formats.',
+
+offscreen_images:'Consider modifying your product and catalog templates to make use of the web platform\'s [lazy loading](https://web.dev/native-lazy-loading) feature.',
+
+disable_bundling:'Disable Magento\'s built-in [JavaScript bundling and minification](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html), and consider using [baler](https://github.com/magento/baler/) instead.',
+
+unminified_css:'Enable the "Minify CSS Files" option in your store\'s Developer settings. [Learn more](https://devdocs.magento.com/guides/v2.3/performance-best-practices/configuration.html?itm_source=devdocs&itm_medium=search_page&itm_campaign=federated_search&itm_term=minify%20css%20files).',
+
+unminified_javascript:'Use [Terser](https://www.npmjs.com/package/terser) to minify all JavaScript assets outfrom from static content deployment, and disable the built-in minification feature.',
+
+unused_javascript:'Disable Magento\'s built-in [JavaScript bundling](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html).',
+
+uses_optimized_images:'Consider searching the [Magento Marketplace](https://marketplace.magento.com/catalogsearch/result/?q=optimize%20image) for a variety of third party extensions to optimize images.',
+
+time_to_first_byte:'Use Magento\'s [Varnish integration](https://devdocs.magento.com/guides/v2.3/config-guide/varnish/config-varnish.html).',
+
+uses_rel_preconnect:'Preconnect or dns-prefetch resource hints can be added by [modifying a themes\'s layout](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html).',
+
+uses_rel_preload:'`<link rel=preload>` tags can be added by [modifying a themes\'s layout](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html).',
+
+critical_request_chains:'If you are not bundling your JavaScript assets, consider using [baler](https://github.com/magento/baler).',
+
+font_display:'Specify `@font-display` when [defining custom fonts](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/using-fonts.html).'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+
+module.exports={
+id:'magento',
+iconDataURL:magentoIcon,
+title:'Magento',
+descriptions:{
+'uses-webp-images':str_(UIStrings.uses_webp_images),
+'offscreen-images':str_(UIStrings.offscreen_images),
+'total-byte-weight':str_(UIStrings.disable_bundling),
+'render-blocking-resources':str_(UIStrings.disable_bundling),
+'unminified-css':str_(UIStrings.unminified_css),
+'unminified-javascript':str_(UIStrings.unminified_javascript),
+'unused-javascript':str_(UIStrings.unused_javascript),
+'uses-optimized-images':str_(UIStrings.uses_optimized_images),
+'time-to-first-byte':str_(UIStrings.time_to_first_byte),
+'uses-rel-preconnect':str_(UIStrings.uses_rel_preconnect),
+'uses-rel-preload':str_(UIStrings.uses_rel_preload),
+'critical-request-chains':str_(UIStrings.critical_request_chains),
+'font-display':str_(UIStrings.font_display)}};
+
+
+module.exports.UIStrings=UIStrings;
+
+}).call(this,"/stack-packs/packs/magento.js");
+},{"../../lighthouse-core/lib/i18n/i18n.js":67}],181:[function(require,module,exports){
+(function(__filename){
+
+
+
+
+
+
+
+'use strict';
+
+const i18n=require('../../lighthouse-core/lib/i18n/i18n.js');
+
+const reactIcon=`data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"%3E %3Cg fill="%2361DAFB"%3E%3Cpath d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/%3E %3Ccircle cx="420.9" cy="296.5" r="45.7"/%3E %3Cpath d="M520.5 78.1z"/%3E%3C/g%3E%3C/svg%3E`;
+
+const UIStrings={
+
+unminified_css:'If your build system minifies your CSS files automatically, ensure that you are deploying the production build of your application. You can check this with the React Developer Tools extension. [Learn more](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build).',
+
+unminified_javascript:'If your build system minifies your JS files automatically, ensure that you are deploying the production build of your application. You can check this with the React Developer Tools extension. [Learn more](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build).',
+
+unused_javascript:'If you are not server-side rendering, [split your JavaScript bundles](https://web.dev/code-splitting-suspense/) with `React.lazy()`. Otherwise, code-split using a third-party library such as [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/).',
+
+time_to_first_byte:'If you are server-side rendering any React components, consider using `renderToNodeStream()` or `renderToStaticNodeStream()` to allow the client to receive and hydrate different parts of the markup instead of all at once. [Learn more](https://reactjs.org/docs/react-dom-server.html#rendertonodestream).',
+
+redirects:'If you are using React Router, minimize usage of the `<Redirect>` component for [route navigations](https://reacttraining.com/react-router/web/api/Redirect).',
+
+user_timings:'Use the React DevTools Profiler, which makes use of the Profiler API, to measure the rendering performance of your components. [Learn more.](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)',
+
+dom_size:'Consider using a “windowing” library like `react-window` to minimize the number of DOM nodes created if you are rendering many repeated elements on the page. [Learn more](https://web.dev/virtualize-long-lists-react-window/). Also, minimize unecessary re-renders using [shouldComponentUpdate](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent), or [React.memo](https://reactjs.org/docs/react-api.html#reactmemo) and [skip effects](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) only until certain dependencies have changed if you are using the Effect hook to improve runtime performance.'};
+
+
+const str_=i18n.createMessageInstanceIdFn(__filename,UIStrings);
+
+module.exports={
+id:'react',
+iconDataURL:reactIcon,
+title:'React',
+descriptions:{
+'unminified-css':str_(UIStrings.unminified_css),
+'unminified-javascript':str_(UIStrings.unminified_javascript),
+'unused-javascript':str_(UIStrings.unused_javascript),
+'time-to-first-byte':str_(UIStrings.time_to_first_byte),
+'redirects':str_(UIStrings.redirects),
+'user-timings':str_(UIStrings.user_timings),
+'dom-size':str_(UIStrings.dom_size)}};
+
+
+module.exports.UIStrings=UIStrings;
+
+}).call(this,"/stack-packs/packs/react.js");
+},{"../../lighthouse-core/lib/i18n/i18n.js":67}],182:[function(require,module,exports){
(function(__filename){
@@ -65805,29 +65621,32 @@ descriptions:{
module.exports.UIStrings=UIStrings;
}).call(this,"/stack-packs/packs/wordpress.js");
-},{"../../lighthouse-core/lib/i18n/i18n.js":68}],182:[function(require,module,exports){
+},{"../../lighthouse-core/lib/i18n/i18n.js":67}],183:[function(require,module,exports){
module.exports={
"npm":{
"angular":[
+{"id":"SNYK-JS-ANGULAR-471885","severity":"medium","semver":{"vulnerable":["<1.6.3"]}},
+{"id":"SNYK-JS-ANGULAR-471882","severity":"medium","semver":{"vulnerable":["<1.6.5"]}},
+{"id":"SNYK-JS-ANGULAR-471879","severity":"medium","semver":{"vulnerable":["<1.6.0-rc.0"]}},
{"id":"npm:angular:20180202","severity":"medium","semver":{"vulnerable":["<1.6.9"]}},
{"id":"npm:angular:20171018","severity":"medium","semver":{"vulnerable":["<1.6.7"]}},
-{"id":"npm:angular:20160527","severity":"medium","semver":{"vulnerable":["<1.2.30 >=1.0.0"]}},
-{"id":"npm:angular:20160122","severity":"medium","semver":{"vulnerable":["<1.5.0-rc.2 >=1.3.0"]}},
+{"id":"npm:angular:20160527","severity":"medium","semver":{"vulnerable":[">=1.0.0 <1.2.30"]}},
+{"id":"npm:angular:20160122","severity":"medium","semver":{"vulnerable":[">=1.3.0 <1.5.0-rc.2"]}},
{"id":"npm:angular:20140608","severity":"low","semver":{"vulnerable":["<1.3.0"]}},
{"id":"npm:angular:20131113","severity":"high","semver":{"vulnerable":["<1.2.2"]}},
{"id":"npm:angular:20140908","severity":"medium","semver":{"vulnerable":["<1.3.0-rc.4"]}},
-{"id":"npm:angular:20161101","severity":"medium","semver":{"vulnerable":["<1.5.9 >=1.5.0"]}},
+{"id":"npm:angular:20161101","severity":"medium","semver":{"vulnerable":[">=1.5.0 <1.5.9"]}},
{"id":"npm:angular:20150909","severity":"high","semver":{"vulnerable":["<1.5.0-beta.2"]}},
{"id":"npm:angular:20151205","severity":"medium","semver":{"vulnerable":["<1.5.0-rc.0"]}},
{"id":"npm:angular:20151130","severity":"medium","semver":{"vulnerable":["<1.4.10"]}},
-{"id":"npm:angular:20130622","severity":"medium","semver":{"vulnerable":["<1.2.0 >=1.0.0"]}},
-{"id":"npm:angular:20150807-1","severity":"medium","semver":{"vulnerable":["<1.5.0-beta.0 >=1.3.1"]}},
-{"id":"npm:angular:20150807","severity":"high","semver":{"vulnerable":["<1.5.0-beta.0 >=1.0.0"]}},
+{"id":"npm:angular:20130622","severity":"medium","semver":{"vulnerable":[">=1.0.0 <1.2.0"]}},
+{"id":"npm:angular:20150807-1","severity":"medium","semver":{"vulnerable":[">=1.3.1 <1.5.0-beta.0"]}},
+{"id":"npm:angular:20150807","severity":"high","semver":{"vulnerable":[">=1.0.0 <1.5.0-beta.0"]}},
{"id":"npm:angular:20150315","severity":"medium","semver":{"vulnerable":["<1.6.1"]}},
{"id":"npm:angular:20150310","severity":"high","semver":{"vulnerable":["<1.5.0-beta.2"]}},
{"id":"npm:angular:20141104","severity":"medium","semver":{"vulnerable":["<1.3.2"]}},
-{"id":"npm:angular:20130621","severity":"medium","semver":{"vulnerable":["<=1.1.5"]}},
-{"id":"npm:angular:20140909","severity":"high","semver":{"vulnerable":["<1.2.24 >=1.2.19"]}},
+{"id":"npm:angular:20130621","severity":"medium","semver":{"vulnerable":["<1.2.0"]}},
+{"id":"npm:angular:20140909","severity":"high","semver":{"vulnerable":[">=1.2.19 <1.2.24"]}},
{"id":"npm:angular:20130625","severity":"high","semver":{"vulnerable":["<1.1.5"]}}],
"backbone":[
@@ -65844,9 +65663,11 @@ module.exports={
{"id":"npm:bootstrap:20120510","severity":"medium","semver":{"vulnerable":["<2.1.0"]}}],
"dojo":[
+{"id":"SNYK-JS-DOJO-174934","severity":"medium","semver":{"vulnerable":[">=1.0.0 <1.0.3",">=1.1.0 <1.1.2",">=1.2.0 <1.2.4",">=1.3.0 <1.3.3",">=1.4.0 <1.4.2"]}},
+{"id":"SNYK-JS-DOJO-174933","severity":"medium","semver":{"vulnerable":["<1.2.0"]}},
{"id":"SNYK-JS-DOJO-72305","severity":"medium","semver":{"vulnerable":["<1.14"]}},
{"id":"npm:dojo:20180818","severity":"medium","semver":{"vulnerable":["<1.10.10 || >=1.11.0 <1.11.6 || >=1.12.0 <1.12.4 || >=1.13.0 <1.13.1"]}},
-{"id":"npm:dojo:20160523","severity":"medium","semver":{"vulnerable":["<= 1.0.0"]}},
+{"id":"npm:dojo:20160523","severity":"medium","semver":{"vulnerable":["<1.1.0"]}},
{"id":"npm:dojo:20100614-6","severity":"medium","semver":{"vulnerable":["<1.4.2"]}},
{"id":"npm:dojo:20100614","severity":"high","semver":{"vulnerable":[">=0.4 <0.4.4 || >=1.0 <1.0.3 || >=1.1 <1.1.2 || >=1.2 <1.2.4 || >=1.3 <1.3.3 || >=1.4 <1.4.2"]}},
{"id":"npm:dojo:20090409","severity":"medium","semver":{"vulnerable":["<1.1"]}}],
@@ -65856,8 +65677,12 @@ module.exports={
{"id":"npm:foundation-sites:20150619","severity":"medium","semver":{"vulnerable":["<5.5.3"]}},
{"id":"npm:foundation-sites:20120717","severity":"medium","semver":{"vulnerable":["<3.0.6 >=3.0.0"]}}],
+"google-closure-library":[
+{"id":"SNYK-JS-GOOGLECLOSURELIBRARY-174519","severity":"medium","semver":{"vulnerable":[">=20190121.0.0 <20190301.0.0"]}}],
+
"handlebars":[
-{"id":"SNYK-JS-HANDLEBARS-174183","severity":"high","semver":{"vulnerable":[">=4.1.0 <4.1.2","<4.0.14"]}},
+{"id":"SNYK-JS-HANDLEBARS-469063","severity":"high","semver":{"vulnerable":["<4.3.0"]}},
+{"id":"SNYK-JS-HANDLEBARS-174183","severity":"high","semver":{"vulnerable":["<3.0.7",">=4.1.0 <4.1.2","<4.0.14"]}},
{"id":"SNYK-JS-HANDLEBARS-173692","severity":"high","semver":{"vulnerable":["<4.0.13"]}},
{"id":"npm:handlebars:20151207","severity":"medium","semver":{"vulnerable":["<4.0.0"]}},
{"id":"npm:handlebars:20110425","severity":"medium","semver":{"vulnerable":["<=1.0.0-beta.3"]}}],
@@ -65867,25 +65692,27 @@ module.exports={
"jquery":[
{"id":"SNYK-JS-JQUERY-174006","severity":"medium","semver":{"vulnerable":["<3.4.0"]}},
-{"id":"npm:jquery:20160529","severity":"low","semver":{"vulnerable":["=3.0.0-rc1"]}},
+{"id":"npm:jquery:20160529","severity":"low","semver":{"vulnerable":[">=3.0.0-rc1 <3.0.0"]}},
{"id":"npm:jquery:20150627","severity":"medium","semver":{"vulnerable":["<1.12.2",">=1.12.3 <2.2.2",">=2.2.3 <3.0.0"]}},
{"id":"npm:jquery:20140902","severity":"medium","semver":{"vulnerable":[">=1.4.2 <1.6.2"]}},
{"id":"npm:jquery:20120206","severity":"medium","semver":{"vulnerable":[">=1.7.1 <1.9.0"]}},
{"id":"npm:jquery:20110606","severity":"medium","semver":{"vulnerable":["<1.6.3"]}}],
"jquery-mobile":[
+{"id":"SNYK-JS-JQUERYMOBILE-174599","severity":"medium","semver":{"vulnerable":["<=1.5.0-alpha.1"]}},
{"id":"npm:jquery-mobile:20120802","severity":"medium","semver":{"vulnerable":["<1.2.0"]}}],
"jquery-ui":[
{"id":"npm:jquery-ui:20121127","severity":"medium","semver":{"vulnerable":["<1.10.0"]}},
{"id":"npm:jquery-ui:20100903","severity":"medium","semver":{"vulnerable":["<1.10.0"]}},
-{"id":"npm:jquery-ui:20160721","severity":"high","semver":{"vulnerable":["<=1.11.4"]}}],
+{"id":"npm:jquery-ui:20160721","severity":"high","semver":{"vulnerable":["<1.12.0"]}}],
"knockout":[
{"id":"npm:knockout:20180213","severity":"medium","semver":{"vulnerable":["<3.5.0-beta"]}},
{"id":"npm:knockout:20130701","severity":"medium","semver":{"vulnerable":["<3.0.0 >=2.1.0-pre"]}}],
"lodash":[
+{"id":"SNYK-JS-LODASH-450202","severity":"high","semver":{"vulnerable":["<4.17.12"]}},
{"id":"SNYK-JS-LODASH-73639","severity":"medium","semver":{"vulnerable":["<4.17.11"]}},
{"id":"SNYK-JS-LODASH-73638","severity":"high","semver":{"vulnerable":["<4.17.11"]}},
{"id":"npm:lodash:20180130","severity":"medium","semver":{"vulnerable":["<4.17.5"]}}],
@@ -65893,7 +65720,7 @@ module.exports={
"moment":[
{"id":"npm:moment:20170905","severity":"low","semver":{"vulnerable":["<2.19.3"]}},
{"id":"npm:moment:20161019","severity":"medium","semver":{"vulnerable":["<2.15.2"]}},
-{"id":"npm:moment:20160126","severity":"medium","semver":{"vulnerable":["<=2.11.1"]}}],
+{"id":"npm:moment:20160126","severity":"medium","semver":{"vulnerable":["<2.11.2"]}}],
"mustache":[
{"id":"npm:mustache:20151207","severity":"medium","semver":{"vulnerable":["<2.2.1"]}},
@@ -65914,7 +65741,7 @@ module.exports={
{"id":"npm:vue:20170829","severity":"medium","semver":{"vulnerable":["<2.4.3"]}},
{"id":"npm:vue:20170401","severity":"medium","semver":{"vulnerable":["<2.3.0-beta.1"]}},
{"id":"npm:vue:20180802","severity":"medium","semver":{"vulnerable":["<2.5.17"]}},
-{"id":"npm:vue:20180222","severity":"low","semver":{"vulnerable":["<=2.5.14"]}}],
+{"id":"npm:vue:20180222","severity":"low","semver":{"vulnerable":["<2.5.14"]}}],
"yui":[
{"id":"npm:yui:20130604","severity":"medium","semver":{"vulnerable":[">=3.0.0 <3.10.1 || =3.10.2"]}},
@@ -65960,6 +65787,7 @@ if(url.endsWith('/'))url=url.replace(/\/$/,'');
return url.replace(/^chrome:\/\/chrome\//,'chrome://');
}
+
class URLShim extends URL{
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar-XB.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar-XB.json
new file mode 100644
index 00000000000..e295430266b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar-XB.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "‏‮Access‬‏ ‏‮keys‬‏ ‏‮let‬‏ ‏‮users‬‏ ‏‮quickly‬‏ ‏‮focus‬‏ ‏‮a‬‏ ‏‮part‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮page‬‏. ‏‮For‬‏ ‏‮proper‬‏ ‏‮navigation‬‏, ‏‮each‬‏ ‏‮access‬‏ ‏‮key‬‏ ‏‮must‬‏ ‏‮be‬‏ ‏‮unique‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` ‏‮values‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮unique‬‏"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` ‏‮values‬‏ ‏‮are‬‏ ‏‮unique‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "‏‮Each‬‏ ‏‮ARIA‬‏ `role` ‏‮supports‬‏ ‏‮a‬‏ ‏‮specific‬‏ ‏‮subset‬‏ ‏‮of‬‏ `aria-*` ‏‮attributes‬‏. ‏‮Mismatching‬‏ ‏‮these‬‏ ‏‮invalidates‬‏ ‏‮the‬‏ `aria-*` ‏‮attributes‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮match‬‏ ‏‮their‬‏ ‏‮roles‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮match‬‏ ‏‮their‬‏ ‏‮roles‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "‏‮Some‬‏ ‏‮ARIA‬‏ ‏‮roles‬‏ ‏‮have‬‏ ‏‮required‬‏ ‏‮attributes‬‏ ‏‮that‬‏ ‏‮describe‬‏ ‏‮the‬‏ ‏‮state‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮element‬‏ ‏‮to‬‏ ‏‮screen‬‏ ‏‮readers‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`‏‮s‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮all‬‏ ‏‮required‬‏ `[aria-*]` ‏‮attributes‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`‏‮s‬‏ ‏‮have‬‏ ‏‮all‬‏ ‏‮required‬‏ `[aria-*]` ‏‮attributes‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "‏‮Some‬‏ ‏‮ARIA‬‏ ‏‮parent‬‏ ‏‮roles‬‏ ‏‮must‬‏ ‏‮contain‬‏ ‏‮specific‬‏ ‏‮child‬‏ ‏‮roles‬‏ ‏‮to‬‏ ‏‮perform‬‏ ‏‮their‬‏ ‏‮intended‬‏ ‏‮accessibility‬‏ ‏‮functions‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "‏‮Elements‬‏ ‏‮with‬‏ ‏‮an‬‏ ‏‮ARIA‬‏ `[role]` ‏‮that‬‏ ‏‮require‬‏ ‏‮children‬‏ ‏‮to‬‏ ‏‮contain‬‏ ‏‮a‬‏ ‏‮specific‬‏ `[role]` ‏‮are‬‏ ‏‮missing‬‏ ‏‮some‬‏ ‏‮or‬‏ ‏‮all‬‏ ‏‮of‬‏ ‏‮those‬‏ ‏‮required‬‏ ‏‮children‬‏."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "‏‮Elements‬‏ ‏‮with‬‏ ‏‮an‬‏ ‏‮ARIA‬‏ `[role]` ‏‮that‬‏ ‏‮require‬‏ ‏‮children‬‏ ‏‮to‬‏ ‏‮contain‬‏ ‏‮a‬‏ ‏‮specific‬‏ `[role]` ‏‮have‬‏ ‏‮all‬‏ ‏‮required‬‏ ‏‮children‬‏."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "‏‮Some‬‏ ‏‮ARIA‬‏ ‏‮child‬‏ ‏‮roles‬‏ ‏‮must‬‏ ‏‮be‬‏ ‏‮contained‬‏ ‏‮by‬‏ ‏‮specific‬‏ ‏‮parent‬‏ ‏‮roles‬‏ ‏‮to‬‏ ‏‮properly‬‏ ‏‮perform‬‏ ‏‮their‬‏ ‏‮intended‬‏ ‏‮accessibility‬‏ ‏‮functions‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`‏‮s‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮contained‬‏ ‏‮by‬‏ ‏‮their‬‏ ‏‮required‬‏ ‏‮parent‬‏ ‏‮element‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`‏‮s‬‏ ‏‮are‬‏ ‏‮contained‬‏ ‏‮by‬‏ ‏‮their‬‏ ‏‮required‬‏ ‏‮parent‬‏ ‏‮element‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "‏‮ARIA‬‏ ‏‮roles‬‏ ‏‮must‬‏ ‏‮have‬‏ ‏‮valid‬‏ ‏‮values‬‏ ‏‮in‬‏ ‏‮order‬‏ ‏‮to‬‏ ‏‮perform‬‏ ‏‮their‬‏ ‏‮intended‬‏ ‏‮accessibility‬‏ ‏‮functions‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` ‏‮values‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮valid‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` ‏‮values‬‏ ‏‮are‬‏ ‏‮valid‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "‏‮Assistive‬‏ ‏‮technologies‬‏, ‏‮like‬‏ ‏‮screen‬‏ ‏‮readers‬‏, ‏‮can‬‏'‏‮t‬‏ ‏‮interpret‬‏ ‏‮ARIA‬‏ ‏‮attributes‬‏ ‏‮with‬‏ ‏‮invalid‬‏ ‏‮values‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮valid‬‏ ‏‮values‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮have‬‏ ‏‮valid‬‏ ‏‮values‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "‏‮Assistive‬‏ ‏‮technologies‬‏, ‏‮like‬‏ ‏‮screen‬‏ ‏‮readers‬‏, ‏‮can‬‏'‏‮t‬‏ ‏‮interpret‬‏ ‏‮ARIA‬‏ ‏‮attributes‬‏ ‏‮with‬‏ ‏‮invalid‬‏ ‏‮names‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮valid‬‏ ‏‮or‬‏ ‏‮misspelled‬‏"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` ‏‮attributes‬‏ ‏‮are‬‏ ‏‮valid‬‏ ‏‮and‬‏ ‏‮not‬‏ ‏‮misspelled‬‏"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "‏‮Captions‬‏ ‏‮make‬‏ ‏‮audio‬‏ ‏‮elements‬‏ ‏‮usable‬‏ ‏‮for‬‏ ‏‮deaf‬‏ ‏‮or‬‏ ‏‮hearing‬‏-‏‮impaired‬‏ ‏‮users‬‏, ‏‮providing‬‏ ‏‮critical‬‏ ‏‮information‬‏ ‏‮such‬‏ ‏‮as‬‏ ‏‮who‬‏ ‏‮is‬‏ ‏‮talking‬‏, ‏‮what‬‏ ‏‮they‬‏'‏‮re‬‏ ‏‮saying‬‏, ‏‮and‬‏ ‏‮other‬‏ ‏‮non‬‏-‏‮speech‬‏ ‏‮information‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` ‏‮elements‬‏ ‏‮are‬‏ ‏‮missing‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` ‏‮elements‬‏ ‏‮contain‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "‏‮Failing‬‏ ‏‮Elements‬‏"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "‏‮When‬‏ ‏‮a‬‏ ‏‮button‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮have‬‏ ‏‮an‬‏ ‏‮accessible‬‏ ‏‮name‬‏, ‏‮screen‬‏ ‏‮readers‬‏ ‏‮announce‬‏ ‏‮it‬‏ ‏‮as‬‏ \"‏‮button‬‏\", ‏‮making‬‏ ‏‮it‬‏ ‏‮unusable‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮who‬‏ ‏‮rely‬‏ ‏‮on‬‏ ‏‮screen‬‏ ‏‮readers‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "‏‮Buttons‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮an‬‏ ‏‮accessible‬‏ ‏‮name‬‏"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "‏‮Buttons‬‏ ‏‮have‬‏ ‏‮an‬‏ ‏‮accessible‬‏ ‏‮name‬‏"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "‏‮Adding‬‏ ‏‮ways‬‏ ‏‮to‬‏ ‏‮bypass‬‏ ‏‮repetitive‬‏ ‏‮content‬‏ ‏‮lets‬‏ ‏‮keyboard‬‏ ‏‮users‬‏ ‏‮navigate‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮more‬‏ ‏‮efficiently‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "‏‮The‬‏ ‏‮page‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮contain‬‏ ‏‮a‬‏ ‏‮heading‬‏, ‏‮skip‬‏ ‏‮link‬‏, ‏‮or‬‏ ‏‮landmark‬‏ ‏‮region‬‏"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "‏‮The‬‏ ‏‮page‬‏ ‏‮contains‬‏ ‏‮a‬‏ ‏‮heading‬‏, ‏‮skip‬‏ ‏‮link‬‏, ‏‮or‬‏ ‏‮landmark‬‏ ‏‮region‬‏"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "‏‮Low‬‏-‏‮contrast‬‏ ‏‮text‬‏ ‏‮is‬‏ ‏‮difficult‬‏ ‏‮or‬‏ ‏‮impossible‬‏ ‏‮for‬‏ ‏‮many‬‏ ‏‮users‬‏ ‏‮to‬‏ ‏‮read‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "‏‮Background‬‏ ‏‮and‬‏ ‏‮foreground‬‏ ‏‮colors‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮sufficient‬‏ ‏‮contrast‬‏ ‏‮ratio‬‏."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "‏‮Background‬‏ ‏‮and‬‏ ‏‮foreground‬‏ ‏‮colors‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮sufficient‬‏ ‏‮contrast‬‏ ‏‮ratio‬‏"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "‏‮When‬‏ ‏‮definition‬‏ ‏‮lists‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮properly‬‏ ‏‮marked‬‏ ‏‮up‬‏, ‏‮screen‬‏ ‏‮readers‬‏ ‏‮may‬‏ ‏‮produce‬‏ ‏‮confusing‬‏ ‏‮or‬‏ ‏‮inaccurate‬‏ ‏‮output‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`'‏‮s‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮contain‬‏ ‏‮only‬‏ ‏‮properly‬‏-‏‮ordered‬‏ `<dt>` ‏‮and‬‏ `<dd>` ‏‮groups‬‏, `<script>` ‏‮or‬‏ `<template>` ‏‮elements‬‏."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`'‏‮s‬‏ ‏‮contain‬‏ ‏‮only‬‏ ‏‮properly‬‏-‏‮ordered‬‏ `<dt>` ‏‮and‬‏ `<dd>` ‏‮groups‬‏, `<script>` ‏‮or‬‏ `<template>` ‏‮elements‬‏."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "‏‮Definition‬‏ ‏‮list‬‏ ‏‮items‬‏ (`<dt>` ‏‮and‬‏ `<dd>`) ‏‮must‬‏ ‏‮be‬‏ ‏‮wrapped‬‏ ‏‮in‬‏ ‏‮a‬‏ ‏‮parent‬‏ `<dl>` ‏‮element‬‏ ‏‮to‬‏ ‏‮ensure‬‏ ‏‮that‬‏ ‏‮screen‬‏ ‏‮readers‬‏ ‏‮can‬‏ ‏‮properly‬‏ ‏‮announce‬‏ ‏‮them‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "‏‮Definition‬‏ ‏‮list‬‏ ‏‮items‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮wrapped‬‏ ‏‮in‬‏ `<dl>` ‏‮elements‬‏"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "‏‮Definition‬‏ ‏‮list‬‏ ‏‮items‬‏ ‏‮are‬‏ ‏‮wrapped‬‏ ‏‮in‬‏ `<dl>` ‏‮elements‬‏"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "‏‮The‬‏ ‏‮title‬‏ ‏‮gives‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏ ‏‮an‬‏ ‏‮overview‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮page‬‏, ‏‮and‬‏ ‏‮search‬‏ ‏‮engine‬‏ ‏‮users‬‏ ‏‮rely‬‏ ‏‮on‬‏ ‏‮it‬‏ ‏‮heavily‬‏ ‏‮to‬‏ ‏‮determine‬‏ ‏‮if‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮relevant‬‏ ‏‮to‬‏ ‏‮their‬‏ ‏‮search‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮have‬‏ ‏‮a‬‏ `<title>` ‏‮element‬‏"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "‏‮Document‬‏ ‏‮has‬‏ ‏‮a‬‏ `<title>` ‏‮element‬‏"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "‏‮The‬‏ ‏‮value‬‏ ‏‮of‬‏ ‏‮an‬‏ ‏‮id‬‏ ‏‮attribute‬‏ ‏‮must‬‏ ‏‮be‬‏ ‏‮unique‬‏ ‏‮to‬‏ ‏‮prevent‬‏ ‏‮other‬‏ ‏‮instances‬‏ ‏‮from‬‏ ‏‮being‬‏ ‏‮overlooked‬‏ ‏‮by‬‏ ‏‮assistive‬‏ ‏‮technologies‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]` ‏‮attributes‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮unique‬‏"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]` ‏‮attributes‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮are‬‏ ‏‮unique‬‏"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮reader‬‏ ‏‮users‬‏ ‏‮rely‬‏ ‏‮on‬‏ ‏‮frame‬‏ ‏‮titles‬‏ ‏‮to‬‏ ‏‮describe‬‏ ‏‮the‬‏ ‏‮contents‬‏ ‏‮of‬‏ ‏‮frames‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` ‏‮or‬‏ `<iframe>` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮title‬‏"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` ‏‮or‬‏ `<iframe>` ‏‮elements‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮title‬‏"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "‏‮If‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮specify‬‏ ‏‮a‬‏ ‏‮lang‬‏ ‏‮attribute‬‏, ‏‮a‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮assumes‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮default‬‏ ‏‮language‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮user‬‏ ‏‮chose‬‏ ‏‮when‬‏ ‏‮setting‬‏ ‏‮up‬‏ ‏‮the‬‏ ‏‮screen‬‏ ‏‮reader‬‏. ‏‮If‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮isn‬‏'‏‮t‬‏ ‏‮actually‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮default‬‏ ‏‮language‬‏, ‏‮then‬‏ ‏‮the‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮might‬‏ ‏‮not‬‏ ‏‮announce‬‏ ‏‮the‬‏ ‏‮page‬‏'‏‮s‬‏ ‏‮text‬‏ ‏‮correctly‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` ‏‮element‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ `[lang]` ‏‮attribute‬‏"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` ‏‮element‬‏ ‏‮has‬‏ ‏‮a‬‏ `[lang]` ‏‮attribute‬‏"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "‏‮Specifying‬‏ ‏‮a‬‏ ‏‮valid‬‏ [‏‮BCP‬‏ 47 ‏‮language‬‏](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ‏‮helps‬‏ ‏‮screen‬‏ ‏‮readers‬‏ ‏‮announce‬‏ ‏‮text‬‏ ‏‮properly‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` ‏‮element‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ ‏‮value‬‏ ‏‮for‬‏ ‏‮its‬‏ `[lang]` ‏‮attribute‬‏."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` ‏‮element‬‏ ‏‮has‬‏ ‏‮a‬‏ ‏‮valid‬‏ ‏‮value‬‏ ‏‮for‬‏ ‏‮its‬‏ `[lang]` ‏‮attribute‬‏"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "‏‮Informative‬‏ ‏‮elements‬‏ ‏‮should‬‏ ‏‮aim‬‏ ‏‮for‬‏ ‏‮short‬‏, ‏‮descriptive‬‏ ‏‮alternate‬‏ ‏‮text‬‏. ‏‮Decorative‬‏ ‏‮elements‬‏ ‏‮can‬‏ ‏‮be‬‏ ‏‮ignored‬‏ ‏‮with‬‏ ‏‮an‬‏ ‏‮empty‬‏ ‏‮alt‬‏ ‏‮attribute‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "‏‮Image‬‏ ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ `[alt]` ‏‮attributes‬‏"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "‏‮Image‬‏ ‏‮elements‬‏ ‏‮have‬‏ `[alt]` ‏‮attributes‬‏"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "‏‮When‬‏ ‏‮an‬‏ ‏‮image‬‏ ‏‮is‬‏ ‏‮being‬‏ ‏‮used‬‏ ‏‮as‬‏ ‏‮an‬‏ `<input>` ‏‮button‬‏, ‏‮providing‬‏ ‏‮alternative‬‏ ‏‮text‬‏ ‏‮can‬‏ ‏‮help‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏ ‏‮understand‬‏ ‏‮the‬‏ ‏‮purpose‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮button‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ `[alt]` ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` ‏‮elements‬‏ ‏‮have‬‏ `[alt]` ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "‏‮Labels‬‏ ‏‮ensure‬‏ ‏‮that‬‏ ‏‮form‬‏ ‏‮controls‬‏ ‏‮are‬‏ ‏‮announced‬‏ ‏‮properly‬‏ ‏‮by‬‏ ‏‮assistive‬‏ ‏‮technologies‬‏, ‏‮like‬‏ ‏‮screen‬‏ ‏‮readers‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "‏‮Form‬‏ ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮associated‬‏ ‏‮labels‬‏"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "‏‮Form‬‏ ‏‮elements‬‏ ‏‮have‬‏ ‏‮associated‬‏ ‏‮labels‬‏"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "‏‮A‬‏ ‏‮table‬‏ ‏‮being‬‏ ‏‮used‬‏ ‏‮for‬‏ ‏‮layout‬‏ ‏‮purposes‬‏ ‏‮should‬‏ ‏‮not‬‏ ‏‮include‬‏ ‏‮data‬‏ ‏‮elements‬‏, ‏‮such‬‏ ‏‮as‬‏ ‏‮the‬‏ ‏‮th‬‏ ‏‮or‬‏ ‏‮caption‬‏ ‏‮elements‬‏ ‏‮or‬‏ ‏‮the‬‏ ‏‮summary‬‏ ‏‮attribute‬‏, ‏‮because‬‏ ‏‮this‬‏ ‏‮can‬‏ ‏‮create‬‏ ‏‮a‬‏ ‏‮confusing‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "‏‮Presentational‬‏ `<table>` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮avoid‬‏ ‏‮using‬‏ `<th>`, `<caption>` ‏‮or‬‏ ‏‮the‬‏ `[summary]` ‏‮attribute‬‏."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "‏‮Presentational‬‏ `<table>` ‏‮elements‬‏ ‏‮avoid‬‏ ‏‮using‬‏ `<th>`, `<caption>` ‏‮or‬‏ ‏‮the‬‏ `[summary]` ‏‮attribute‬‏."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "‏‮Link‬‏ ‏‮text‬‏ (‏‮and‬‏ ‏‮alternate‬‏ ‏‮text‬‏ ‏‮for‬‏ ‏‮images‬‏, ‏‮when‬‏ ‏‮used‬‏ ‏‮as‬‏ ‏‮links‬‏) ‏‮that‬‏ ‏‮is‬‏ ‏‮discernible‬‏, ‏‮unique‬‏, ‏‮and‬‏ ‏‮focusable‬‏ ‏‮improves‬‏ ‏‮the‬‏ ‏‮navigation‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "‏‮Links‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮discernible‬‏ ‏‮name‬‏"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "‏‮Links‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮discernible‬‏ ‏‮name‬‏"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮readers‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮specific‬‏ ‏‮way‬‏ ‏‮of‬‏ ‏‮announcing‬‏ ‏‮lists‬‏. ‏‮Ensuring‬‏ ‏‮proper‬‏ ‏‮list‬‏ ‏‮structure‬‏ ‏‮aids‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮output‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "‏‮Lists‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮contain‬‏ ‏‮only‬‏ `<li>` ‏‮elements‬‏ ‏‮and‬‏ ‏‮script‬‏ ‏‮supporting‬‏ ‏‮elements‬‏ (`<script>` ‏‮and‬‏ `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "‏‮Lists‬‏ ‏‮contain‬‏ ‏‮only‬‏ `<li>` ‏‮elements‬‏ ‏‮and‬‏ ‏‮script‬‏ ‏‮supporting‬‏ ‏‮elements‬‏ (`<script>` ‏‮and‬‏ `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮readers‬‏ ‏‮require‬‏ ‏‮list‬‏ ‏‮items‬‏ (`<li>`) ‏‮to‬‏ ‏‮be‬‏ ‏‮contained‬‏ ‏‮within‬‏ ‏‮a‬‏ ‏‮parent‬‏ `<ul>` ‏‮or‬‏ `<ol>` ‏‮to‬‏ ‏‮be‬‏ ‏‮announced‬‏ ‏‮properly‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "‏‮List‬‏ ‏‮items‬‏ (`<li>`) ‏‮are‬‏ ‏‮not‬‏ ‏‮contained‬‏ ‏‮within‬‏ `<ul>` ‏‮or‬‏ `<ol>` ‏‮parent‬‏ ‏‮elements‬‏."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "‏‮List‬‏ ‏‮items‬‏ (`<li>`) ‏‮are‬‏ ‏‮contained‬‏ ‏‮within‬‏ `<ul>` ‏‮or‬‏ `<ol>` ‏‮parent‬‏ ‏‮elements‬‏"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "‏‮Users‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮expect‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮to‬‏ ‏‮refresh‬‏ ‏‮automatically‬‏, ‏‮and‬‏ ‏‮doing‬‏ ‏‮so‬‏ ‏‮will‬‏ ‏‮move‬‏ ‏‮focus‬‏ ‏‮back‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮top‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮page‬‏. ‏‮This‬‏ ‏‮may‬‏ ‏‮create‬‏ ‏‮a‬‏ ‏‮frustrating‬‏ ‏‮or‬‏ ‏‮confusing‬‏ ‏‮experience‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "‏‮The‬‏ ‏‮document‬‏ ‏‮uses‬‏ `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "‏‮The‬‏ ‏‮document‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮use‬‏ `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "‏‮Disabling‬‏ ‏‮zooming‬‏ ‏‮is‬‏ ‏‮problematic‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮with‬‏ ‏‮low‬‏ ‏‮vision‬‏ ‏‮who‬‏ ‏‮rely‬‏ ‏‮on‬‏ ‏‮screen‬‏ ‏‮magnification‬‏ ‏‮to‬‏ ‏‮properly‬‏ ‏‮see‬‏ ‏‮the‬‏ ‏‮contents‬‏ ‏‮of‬‏ ‏‮a‬‏ ‏‮web‬‏ ‏‮page‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` ‏‮is‬‏ ‏‮used‬‏ ‏‮in‬‏ ‏‮the‬‏ `<meta name=\"viewport\">` ‏‮element‬‏ ‏‮or‬‏ ‏‮the‬‏ `[maximum-scale]` ‏‮attribute‬‏ ‏‮is‬‏ ‏‮less‬‏ ‏‮than‬‏ 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` ‏‮is‬‏ ‏‮not‬‏ ‏‮used‬‏ ‏‮in‬‏ ‏‮the‬‏ `<meta name=\"viewport\">` ‏‮element‬‏ ‏‮and‬‏ ‏‮the‬‏ `[maximum-scale]` ‏‮attribute‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮less‬‏ ‏‮than‬‏ 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮readers‬‏ ‏‮cannot‬‏ ‏‮translate‬‏ ‏‮non‬‏-‏‮text‬‏ ‏‮content‬‏. ‏‮Adding‬‏ ‏‮alt‬‏ ‏‮text‬‏ ‏‮to‬‏ `<object>` ‏‮elements‬‏ ‏‮helps‬‏ ‏‮screen‬‏ ‏‮readers‬‏ ‏‮convey‬‏ ‏‮meaning‬‏ ‏‮to‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ `[alt]` ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` ‏‮elements‬‏ ‏‮have‬‏ `[alt]` ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "‏‮A‬‏ ‏‮value‬‏ ‏‮greater‬‏ ‏‮than‬‏ 0 ‏‮implies‬‏ ‏‮an‬‏ ‏‮explicit‬‏ ‏‮navigation‬‏ ‏‮ordering‬‏. ‏‮Although‬‏ ‏‮technically‬‏ ‏‮valid‬‏, ‏‮this‬‏ ‏‮often‬‏ ‏‮creates‬‏ ‏‮frustrating‬‏ ‏‮experiences‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮who‬‏ ‏‮rely‬‏ ‏‮on‬‏ ‏‮assistive‬‏ ‏‮technologies‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "‏‮Some‬‏ ‏‮elements‬‏ ‏‮have‬‏ ‏‮a‬‏ `[tabindex]` ‏‮value‬‏ ‏‮greater‬‏ ‏‮than‬‏ 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "‏‮No‬‏ ‏‮element‬‏ ‏‮has‬‏ ‏‮a‬‏ `[tabindex]` ‏‮value‬‏ ‏‮greater‬‏ ‏‮than‬‏ 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮readers‬‏ ‏‮have‬‏ ‏‮features‬‏ ‏‮to‬‏ ‏‮make‬‏ ‏‮navigating‬‏ ‏‮tables‬‏ ‏‮easier‬‏. ‏‮Ensuring‬‏ `<td>` ‏‮cells‬‏ ‏‮using‬‏ ‏‮the‬‏ `[headers]` ‏‮attribute‬‏ ‏‮only‬‏ ‏‮refer‬‏ ‏‮to‬‏ ‏‮other‬‏ ‏‮cells‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮same‬‏ ‏‮table‬‏ ‏‮may‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "‏‮Cells‬‏ ‏‮in‬‏ ‏‮a‬‏ `<table>` ‏‮element‬‏ ‏‮that‬‏ ‏‮use‬‏ ‏‮the‬‏ `[headers]` ‏‮attribute‬‏ ‏‮refer‬‏ ‏‮to‬‏ ‏‮an‬‏ ‏‮element‬‏ `id` ‏‮not‬‏ ‏‮found‬‏ ‏‮within‬‏ ‏‮the‬‏ ‏‮same‬‏ ‏‮table‬‏."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "‏‮Cells‬‏ ‏‮in‬‏ ‏‮a‬‏ `<table>` ‏‮element‬‏ ‏‮that‬‏ ‏‮use‬‏ ‏‮the‬‏ `[headers]` ‏‮attribute‬‏ ‏‮refer‬‏ ‏‮to‬‏ ‏‮table‬‏ ‏‮cells‬‏ ‏‮within‬‏ ‏‮the‬‏ ‏‮same‬‏ ‏‮table‬‏."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "‏‮Screen‬‏ ‏‮readers‬‏ ‏‮have‬‏ ‏‮features‬‏ ‏‮to‬‏ ‏‮make‬‏ ‏‮navigating‬‏ ‏‮tables‬‏ ‏‮easier‬‏. ‏‮Ensuring‬‏ ‏‮table‬‏ ‏‮headers‬‏ ‏‮always‬‏ ‏‮refer‬‏ ‏‮to‬‏ ‏‮some‬‏ ‏‮set‬‏ ‏‮of‬‏ ‏‮cells‬‏ ‏‮may‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮screen‬‏ ‏‮reader‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` ‏‮elements‬‏ ‏‮and‬‏ ‏‮elements‬‏ ‏‮with‬‏ `[role=\"columnheader\"/\"rowheader\"]` ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮data‬‏ ‏‮cells‬‏ ‏‮they‬‏ ‏‮describe‬‏."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` ‏‮elements‬‏ ‏‮and‬‏ ‏‮elements‬‏ ‏‮with‬‏ `[role=\"columnheader\"/\"rowheader\"]` ‏‮have‬‏ ‏‮data‬‏ ‏‮cells‬‏ ‏‮they‬‏ ‏‮describe‬‏."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "‏‮Specifying‬‏ ‏‮a‬‏ ‏‮valid‬‏ [‏‮BCP‬‏ 47 ‏‮language‬‏](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ‏‮on‬‏ ‏‮elements‬‏ ‏‮helps‬‏ ‏‮ensure‬‏ ‏‮that‬‏ ‏‮text‬‏ ‏‮is‬‏ ‏‮pronounced‬‏ ‏‮correctly‬‏ ‏‮by‬‏ ‏‮a‬‏ ‏‮screen‬‏ ‏‮reader‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` ‏‮attributes‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ ‏‮value‬‏"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` ‏‮attributes‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ ‏‮value‬‏"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "‏‮When‬‏ ‏‮a‬‏ ‏‮video‬‏ ‏‮provides‬‏ ‏‮a‬‏ ‏‮caption‬‏ ‏‮it‬‏ ‏‮is‬‏ ‏‮easier‬‏ ‏‮for‬‏ ‏‮deaf‬‏ ‏‮and‬‏ ‏‮hearing‬‏ ‏‮impaired‬‏ ‏‮users‬‏ ‏‮to‬‏ ‏‮access‬‏ ‏‮its‬‏ ‏‮information‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮contain‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` ‏‮elements‬‏ ‏‮contain‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "‏‮Audio‬‏ ‏‮descriptions‬‏ ‏‮provide‬‏ ‏‮relevant‬‏ ‏‮information‬‏ ‏‮for‬‏ ‏‮videos‬‏ ‏‮that‬‏ ‏‮dialogue‬‏ ‏‮cannot‬‏, ‏‮such‬‏ ‏‮as‬‏ ‏‮facial‬‏ ‏‮expressions‬‏ ‏‮and‬‏ ‏‮scenes‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` ‏‮elements‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮contain‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` ‏‮elements‬‏ ‏‮contain‬‏ ‏‮a‬‏ `<track>` ‏‮element‬‏ ‏‮with‬‏ `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "‏‮For‬‏ ‏‮ideal‬‏ ‏‮appearance‬‏ ‏‮on‬‏ ‏‮iOS‬‏ ‏‮when‬‏ ‏‮users‬‏ ‏‮add‬‏ ‏‮a‬‏ ‏‮progressive‬‏ ‏‮web‬‏ ‏‮app‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮home‬‏ ‏‮screen‬‏, ‏‮define‬‏ ‏‮an‬‏ `apple-touch-icon`. ‏‮It‬‏ ‏‮must‬‏ ‏‮point‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮non‬‏-‏‮transparent‬‏ 192‏‮px‬‏ (‏‮or‬‏ 180‏‮px‬‏) ‏‮square‬‏ ‏‮PNG‬‏. [‏‮Learn‬‏ ‏‮More‬‏](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮provide‬‏ ‏‮a‬‏ ‏‮valid‬‏ `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` ‏‮is‬‏ ‏‮out‬‏ ‏‮of‬‏ ‏‮date‬‏; `apple-touch-icon` ‏‮is‬‏ ‏‮preferred‬‏."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "‏‮Provides‬‏ ‏‮a‬‏ ‏‮valid‬‏ `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "‏‮Chrome‬‏ ‏‮extensions‬‏ ‏‮negatively‬‏ ‏‮affected‬‏ ‏‮this‬‏ ‏‮page‬‏'‏‮s‬‏ ‏‮load‬‏ ‏‮performance‬‏. ‏‮Try‬‏ ‏‮auditing‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮in‬‏ ‏‮incognito‬‏ ‏‮mode‬‏ ‏‮or‬‏ ‏‮from‬‏ ‏‮a‬‏ ‏‮Chrome‬‏ ‏‮profile‬‏ ‏‮without‬‏ ‏‮extensions‬‏."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "‏‮Script‬‏ ‏‮Evaluation‬‏"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "‏‮Script‬‏ ‏‮Parse‬‏"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "‏‮Total‬‏ ‏‮CPU‬‏ ‏‮Time‬‏"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮reducing‬‏ ‏‮the‬‏ ‏‮time‬‏ ‏‮spent‬‏ ‏‮parsing‬‏, ‏‮compiling‬‏, ‏‮and‬‏ ‏‮executing‬‏ ‏‮JS‬‏. ‏‮You‬‏ ‏‮may‬‏ ‏‮find‬‏ ‏‮delivering‬‏ ‏‮smaller‬‏ ‏‮JS‬‏ ‏‮payloads‬‏ ‏‮helps‬‏ ‏‮with‬‏ ‏‮this‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "‏‮Reduce‬‏ ‏‮JavaScript‬‏ ‏‮execution‬‏ ‏‮time‬‏"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "‏‮JavaScript‬‏ ‏‮execution‬‏ ‏‮time‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "‏‮Large‬‏ ‏‮GIFs‬‏ ‏‮are‬‏ ‏‮inefficient‬‏ ‏‮for‬‏ ‏‮delivering‬‏ ‏‮animated‬‏ ‏‮content‬‏. ‏‮Consider‬‏ ‏‮using‬‏ ‏‮MPEG‬‏4/‏‮WebM‬‏ ‏‮videos‬‏ ‏‮for‬‏ ‏‮animations‬‏ ‏‮and‬‏ ‏‮PNG‬‏/‏‮WebP‬‏ ‏‮for‬‏ ‏‮static‬‏ ‏‮images‬‏ ‏‮instead‬‏ ‏‮of‬‏ ‏‮GIF‬‏ ‏‮to‬‏ ‏‮save‬‏ ‏‮network‬‏ ‏‮bytes‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "‏‮Use‬‏ ‏‮video‬‏ ‏‮formats‬‏ ‏‮for‬‏ ‏‮animated‬‏ ‏‮content‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮lazy‬‏-‏‮loading‬‏ ‏‮offscreen‬‏ ‏‮and‬‏ ‏‮hidden‬‏ ‏‮images‬‏ ‏‮after‬‏ ‏‮all‬‏ ‏‮critical‬‏ ‏‮resources‬‏ ‏‮have‬‏ ‏‮finished‬‏ ‏‮loading‬‏ ‏‮to‬‏ ‏‮lower‬‏ ‏‮time‬‏ ‏‮to‬‏ ‏‮interactive‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "‏‮Defer‬‏ ‏‮offscreen‬‏ ‏‮images‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "‏‮Resources‬‏ ‏‮are‬‏ ‏‮blocking‬‏ ‏‮the‬‏ ‏‮first‬‏ ‏‮paint‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮page‬‏. ‏‮Consider‬‏ ‏‮delivering‬‏ ‏‮critical‬‏ ‏‮JS‬‏/‏‮CSS‬‏ ‏‮inline‬‏ ‏‮and‬‏ ‏‮deferring‬‏ ‏‮all‬‏ ‏‮non‬‏-‏‮critical‬‏ ‏‮JS‬‏/‏‮styles‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "‏‮Eliminate‬‏ ‏‮render‬‏-‏‮blocking‬‏ ‏‮resources‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "‏‮Large‬‏ ‏‮network‬‏ ‏‮payloads‬‏ ‏‮cost‬‏ ‏‮users‬‏ ‏‮real‬‏ ‏‮money‬‏ ‏‮and‬‏ ‏‮are‬‏ ‏‮highly‬‏ ‏‮correlated‬‏ ‏‮with‬‏ ‏‮long‬‏ ‏‮load‬‏ ‏‮times‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "‏‮Total‬‏ ‏‮size‬‏ ‏‮was‬‏ {totalBytes, number, bytes} ‏‮KB‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "‏‮Avoid‬‏ ‏‮enormous‬‏ ‏‮network‬‏ ‏‮payloads‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮enormous‬‏ ‏‮network‬‏ ‏‮payloads‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "‏‮Minifying‬‏ ‏‮CSS‬‏ ‏‮files‬‏ ‏‮can‬‏ ‏‮reduce‬‏ ‏‮network‬‏ ‏‮payload‬‏ ‏‮sizes‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "‏‮Minify‬‏ ‏‮CSS‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "‏‮Minifying‬‏ ‏‮JavaScript‬‏ ‏‮files‬‏ ‏‮can‬‏ ‏‮reduce‬‏ ‏‮payload‬‏ ‏‮sizes‬‏ ‏‮and‬‏ ‏‮script‬‏ ‏‮parse‬‏ ‏‮time‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "‏‮Minify‬‏ ‏‮JavaScript‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "‏‮Remove‬‏ ‏‮dead‬‏ ‏‮rules‬‏ ‏‮from‬‏ ‏‮stylesheets‬‏ ‏‮and‬‏ ‏‮defer‬‏ ‏‮the‬‏ ‏‮loading‬‏ ‏‮of‬‏ ‏‮CSS‬‏ ‏‮not‬‏ ‏‮used‬‏ ‏‮for‬‏ ‏‮above‬‏-‏‮the‬‏-‏‮fold‬‏ ‏‮content‬‏ ‏‮to‬‏ ‏‮reduce‬‏ ‏‮unnecessary‬‏ ‏‮bytes‬‏ ‏‮consumed‬‏ ‏‮by‬‏ ‏‮network‬‏ ‏‮activity‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "‏‮Remove‬‏ ‏‮unused‬‏ ‏‮CSS‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "‏‮Remove‬‏ ‏‮unused‬‏ ‏‮JavaScript‬‏ ‏‮to‬‏ ‏‮reduce‬‏ ‏‮bytes‬‏ ‏‮consumed‬‏ ‏‮by‬‏ ‏‮network‬‏ ‏‮activity‬‏."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "‏‮Remove‬‏ ‏‮unused‬‏ ‏‮JavaScript‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "‏‮A‬‏ ‏‮long‬‏ ‏‮cache‬‏ ‏‮lifetime‬‏ ‏‮can‬‏ ‏‮speed‬‏ ‏‮up‬‏ ‏‮repeat‬‏ ‏‮visits‬‏ ‏‮to‬‏ ‏‮your‬‏ ‏‮page‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮resource‬‏ ‏‮found‬‏}zero{# ‏‮resources‬‏ ‏‮found‬‏}two{# ‏‮resources‬‏ ‏‮found‬‏}few{# ‏‮resources‬‏ ‏‮found‬‏}many{# ‏‮resources‬‏ ‏‮found‬‏}other{# ‏‮resources‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "‏‮Serve‬‏ ‏‮static‬‏ ‏‮assets‬‏ ‏‮with‬‏ ‏‮an‬‏ ‏‮efficient‬‏ ‏‮cache‬‏ ‏‮policy‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "‏‮Uses‬‏ ‏‮efficient‬‏ ‏‮cache‬‏ ‏‮policy‬‏ ‏‮on‬‏ ‏‮static‬‏ ‏‮assets‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "‏‮Optimized‬‏ ‏‮images‬‏ ‏‮load‬‏ ‏‮faster‬‏ ‏‮and‬‏ ‏‮consume‬‏ ‏‮less‬‏ ‏‮cellular‬‏ ‏‮data‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "‏‮Efficiently‬‏ ‏‮encode‬‏ ‏‮images‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "‏‮Serve‬‏ ‏‮images‬‏ ‏‮that‬‏ ‏‮are‬‏ ‏‮appropriately‬‏-‏‮sized‬‏ ‏‮to‬‏ ‏‮save‬‏ ‏‮cellular‬‏ ‏‮data‬‏ ‏‮and‬‏ ‏‮improve‬‏ ‏‮load‬‏ ‏‮time‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "‏‮Properly‬‏ ‏‮size‬‏ ‏‮images‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "‏‮Text‬‏-‏‮based‬‏ ‏‮resources‬‏ ‏‮should‬‏ ‏‮be‬‏ ‏‮served‬‏ ‏‮with‬‏ ‏‮compression‬‏ (‏‮gzip‬‏, ‏‮deflate‬‏ ‏‮or‬‏ ‏‮brotli‬‏) ‏‮to‬‏ ‏‮minimize‬‏ ‏‮total‬‏ ‏‮network‬‏ ‏‮bytes‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "‏‮Enable‬‏ ‏‮text‬‏ ‏‮compression‬‏"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "‏‮Image‬‏ ‏‮formats‬‏ ‏‮like‬‏ ‏‮JPEG‬‏ 2000, ‏‮JPEG‬‏ ‏‮XR‬‏, ‏‮and‬‏ ‏‮WebP‬‏ ‏‮often‬‏ ‏‮provide‬‏ ‏‮better‬‏ ‏‮compression‬‏ ‏‮than‬‏ ‏‮PNG‬‏ ‏‮or‬‏ ‏‮JPEG‬‏, ‏‮which‬‏ ‏‮means‬‏ ‏‮faster‬‏ ‏‮downloads‬‏ ‏‮and‬‏ ‏‮less‬‏ ‏‮data‬‏ ‏‮consumption‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "‏‮Serve‬‏ ‏‮images‬‏ ‏‮in‬‏ ‏‮next‬‏-‏‮gen‬‏ ‏‮formats‬‏"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "‏‮If‬‏ ‏‮the‬‏ ‏‮width‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮app‬‏'‏‮s‬‏ ‏‮content‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮match‬‏ ‏‮the‬‏ ‏‮width‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮viewport‬‏, ‏‮your‬‏ ‏‮app‬‏ ‏‮might‬‏ ‏‮not‬‏ ‏‮be‬‏ ‏‮optimized‬‏ ‏‮for‬‏ ‏‮mobile‬‏ ‏‮screens‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "‏‮The‬‏ ‏‮viewport‬‏ ‏‮size‬‏ ‏‮of‬‏ {innerWidth}‏‮px‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮match‬‏ ‏‮the‬‏ ‏‮window‬‏ ‏‮size‬‏ ‏‮of‬‏ {outerWidth}‏‮px‬‏."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "‏‮Content‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮sized‬‏ ‏‮correctly‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮viewport‬‏"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "‏‮Content‬‏ ‏‮is‬‏ ‏‮sized‬‏ ‏‮correctly‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮viewport‬‏"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "‏‮The‬‏ ‏‮Critical‬‏ ‏‮Request‬‏ ‏‮Chains‬‏ ‏‮below‬‏ ‏‮show‬‏ ‏‮you‬‏ ‏‮what‬‏ ‏‮resources‬‏ ‏‮are‬‏ ‏‮loaded‬‏ ‏‮with‬‏ ‏‮a‬‏ ‏‮high‬‏ ‏‮priority‬‏. ‏‮Consider‬‏ ‏‮reducing‬‏ ‏‮the‬‏ ‏‮length‬‏ ‏‮of‬‏ ‏‮chains‬‏, ‏‮reducing‬‏ ‏‮the‬‏ ‏‮download‬‏ ‏‮size‬‏ ‏‮of‬‏ ‏‮resources‬‏, ‏‮or‬‏ ‏‮deferring‬‏ ‏‮the‬‏ ‏‮download‬‏ ‏‮of‬‏ ‏‮unnecessary‬‏ ‏‮resources‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮page‬‏ ‏‮load‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮chain‬‏ ‏‮found‬‏}zero{# ‏‮chains‬‏ ‏‮found‬‏}two{# ‏‮chains‬‏ ‏‮found‬‏}few{# ‏‮chains‬‏ ‏‮found‬‏}many{# ‏‮chains‬‏ ‏‮found‬‏}other{# ‏‮chains‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "‏‮Minimize‬‏ ‏‮Critical‬‏ ‏‮Requests‬‏ ‏‮Depth‬‏"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "‏‮Deprecation‬‏ / ‏‮Warning‬‏"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "‏‮Line‬‏"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "‏‮Deprecated‬‏ ‏‮APIs‬‏ ‏‮will‬‏ ‏‮eventually‬‏ ‏‮be‬‏ ‏‮removed‬‏ ‏‮from‬‏ ‏‮the‬‏ ‏‮browser‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮warning‬‏ ‏‮found‬‏}zero{# ‏‮warnings‬‏ ‏‮found‬‏}two{# ‏‮warnings‬‏ ‏‮found‬‏}few{# ‏‮warnings‬‏ ‏‮found‬‏}many{# ‏‮warnings‬‏ ‏‮found‬‏}other{# ‏‮warnings‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "‏‮Uses‬‏ ‏‮deprecated‬‏ ‏‮APIs‬‏"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮deprecated‬‏ ‏‮APIs‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "‏‮Application‬‏ ‏‮Cache‬‏ ‏‮is‬‏ ‏‮deprecated‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "‏‮Found‬‏ \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "‏‮Uses‬‏ ‏‮Application‬‏ ‏‮Cache‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮Application‬‏ ‏‮Cache‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "‏‮Specifying‬‏ ‏‮a‬‏ ‏‮doctype‬‏ ‏‮prevents‬‏ ‏‮the‬‏ ‏‮browser‬‏ ‏‮from‬‏ ‏‮switching‬‏ ‏‮to‬‏ ‏‮quirks‬‏-‏‮mode‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "‏‮Doctype‬‏ ‏‮name‬‏ ‏‮must‬‏ ‏‮be‬‏ ‏‮the‬‏ ‏‮lowercase‬‏ ‏‮string‬‏ `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "‏‮Document‬‏ ‏‮must‬‏ ‏‮contain‬‏ ‏‮a‬‏ ‏‮doctype‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "‏‮Expected‬‏ ‏‮publicId‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮an‬‏ ‏‮empty‬‏ ‏‮string‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "‏‮Expected‬‏ ‏‮systemId‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮an‬‏ ‏‮empty‬‏ ‏‮string‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "‏‮Page‬‏ ‏‮lacks‬‏ ‏‮the‬‏ ‏‮HTML‬‏ ‏‮doctype‬‏, ‏‮thus‬‏ ‏‮triggering‬‏ ‏‮quirks‬‏-‏‮mode‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "‏‮Page‬‏ ‏‮has‬‏ ‏‮the‬‏ ‏‮HTML‬‏ ‏‮doctype‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "‏‮Element‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "‏‮Statistic‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "‏‮Value‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "‏‮Browser‬‏ ‏‮engineers‬‏ ‏‮recommend‬‏ ‏‮pages‬‏ ‏‮contain‬‏ ‏‮fewer‬‏ ‏‮than‬‏ ~1,500 ‏‮DOM‬‏ ‏‮elements‬‏. ‏‮The‬‏ ‏‮sweet‬‏ ‏‮spot‬‏ ‏‮is‬‏ ‏‮a‬‏ ‏‮tree‬‏ ‏‮depth‬‏ < 32 ‏‮elements‬‏ ‏‮and‬‏ ‏‮fewer‬‏ ‏‮than‬‏ 60 ‏‮children‬‏/‏‮parent‬‏ ‏‮element‬‏. ‏‮A‬‏ ‏‮large‬‏ ‏‮DOM‬‏ ‏‮can‬‏ ‏‮increase‬‏ ‏‮memory‬‏ ‏‮usage‬‏, ‏‮cause‬‏ ‏‮longer‬‏ [‏‮style‬‏ ‏‮calculations‬‏](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), ‏‮and‬‏ ‏‮produce‬‏ ‏‮costly‬‏ [‏‮layout‬‏ ‏‮reflows‬‏](https://developers.google.com/speed/articles/reflow). [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮element‬‏}zero{# ‏‮elements‬‏}two{# ‏‮elements‬‏}few{# ‏‮elements‬‏}many{# ‏‮elements‬‏}other{# ‏‮elements‬‏}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "‏‮Avoid‬‏ ‏‮an‬‏ ‏‮excessive‬‏ ‏‮DOM‬‏ ‏‮size‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "‏‮Maximum‬‏ ‏‮DOM‬‏ ‏‮Depth‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "‏‮Total‬‏ ‏‮DOM‬‏ ‏‮Elements‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "‏‮Maximum‬‏ ‏‮Child‬‏ ‏‮Elements‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮an‬‏ ‏‮excessive‬‏ ‏‮DOM‬‏ ‏‮size‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "‏‮Rel‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "‏‮Target‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "‏‮Add‬‏ `rel=\"noopener\"` ‏‮or‬‏ `rel=\"noreferrer\"` ‏‮to‬‏ ‏‮any‬‏ ‏‮external‬‏ ‏‮links‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮performance‬‏ ‏‮and‬‏ ‏‮prevent‬‏ ‏‮security‬‏ ‏‮vulnerabilities‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "‏‮Links‬‏ ‏‮to‬‏ ‏‮cross‬‏-‏‮origin‬‏ ‏‮destinations‬‏ ‏‮are‬‏ ‏‮unsafe‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "‏‮Links‬‏ ‏‮to‬‏ ‏‮cross‬‏-‏‮origin‬‏ ‏‮destinations‬‏ ‏‮are‬‏ ‏‮safe‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "‏‮Unable‬‏ ‏‮to‬‏ ‏‮determine‬‏ ‏‮the‬‏ ‏‮destination‬‏ ‏‮for‬‏ ‏‮anchor‬‏ ({anchorHTML}). ‏‮If‬‏ ‏‮not‬‏ ‏‮used‬‏ ‏‮as‬‏ ‏‮a‬‏ ‏‮hyperlink‬‏, ‏‮consider‬‏ ‏‮removing‬‏ ‏‮target‬‏=_‏‮blank‬‏."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "‏‮Users‬‏ ‏‮are‬‏ ‏‮mistrustful‬‏ ‏‮of‬‏ ‏‮or‬‏ ‏‮confused‬‏ ‏‮by‬‏ ‏‮sites‬‏ ‏‮that‬‏ ‏‮request‬‏ ‏‮their‬‏ ‏‮location‬‏ ‏‮without‬‏ ‏‮context‬‏. ‏‮Consider‬‏ ‏‮tying‬‏ ‏‮the‬‏ ‏‮request‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮user‬‏ ‏‮action‬‏ ‏‮instead‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "‏‮Requests‬‏ ‏‮the‬‏ ‏‮geolocation‬‏ ‏‮permission‬‏ ‏‮on‬‏ ‏‮page‬‏ ‏‮load‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮requesting‬‏ ‏‮the‬‏ ‏‮geolocation‬‏ ‏‮permission‬‏ ‏‮on‬‏ ‏‮page‬‏ ‏‮load‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "‏‮Version‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "‏‮All‬‏ ‏‮front‬‏-‏‮end‬‏ ‏‮JavaScript‬‏ ‏‮libraries‬‏ ‏‮detected‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "‏‮Detected‬‏ ‏‮JavaScript‬‏ ‏‮libraries‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "‏‮For‬‏ ‏‮users‬‏ ‏‮on‬‏ ‏‮slow‬‏ ‏‮connections‬‏, ‏‮external‬‏ ‏‮scripts‬‏ ‏‮dynamically‬‏ ‏‮injected‬‏ ‏‮via‬‏ `document.write()` ‏‮can‬‏ ‏‮delay‬‏ ‏‮page‬‏ ‏‮load‬‏ ‏‮by‬‏ ‏‮tens‬‏ ‏‮of‬‏ ‏‮seconds‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "‏‮Uses‬‏ `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "‏‮Avoids‬‏ `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "‏‮Highest‬‏ ‏‮Severity‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "‏‮Library‬‏ ‏‮Version‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "‏‮Vulnerability‬‏ ‏‮Count‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "‏‮Some‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮scripts‬‏ ‏‮may‬‏ ‏‮contain‬‏ ‏‮known‬‏ ‏‮security‬‏ ‏‮vulnerabilities‬‏ ‏‮that‬‏ ‏‮are‬‏ ‏‮easily‬‏ ‏‮identified‬‏ ‏‮and‬‏ ‏‮exploited‬‏ ‏‮by‬‏ ‏‮attackers‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮vulnerability‬‏ ‏‮detected‬‏}zero{# ‏‮vulnerabilities‬‏ ‏‮detected‬‏}two{# ‏‮vulnerabilities‬‏ ‏‮detected‬‏}few{# ‏‮vulnerabilities‬‏ ‏‮detected‬‏}many{# ‏‮vulnerabilities‬‏ ‏‮detected‬‏}other{# ‏‮vulnerabilities‬‏ ‏‮detected‬‏}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "‏‮Includes‬‏ ‏‮front‬‏-‏‮end‬‏ ‏‮JavaScript‬‏ ‏‮libraries‬‏ ‏‮with‬‏ ‏‮known‬‏ ‏‮security‬‏ ‏‮vulnerabilities‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "‏‮High‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "‏‮Low‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "‏‮Medium‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮front‬‏-‏‮end‬‏ ‏‮JavaScript‬‏ ‏‮libraries‬‏ ‏‮with‬‏ ‏‮known‬‏ ‏‮security‬‏ ‏‮vulnerabilities‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "‏‮Users‬‏ ‏‮are‬‏ ‏‮mistrustful‬‏ ‏‮of‬‏ ‏‮or‬‏ ‏‮confused‬‏ ‏‮by‬‏ ‏‮sites‬‏ ‏‮that‬‏ ‏‮request‬‏ ‏‮to‬‏ ‏‮send‬‏ ‏‮notifications‬‏ ‏‮without‬‏ ‏‮context‬‏. ‏‮Consider‬‏ ‏‮tying‬‏ ‏‮the‬‏ ‏‮request‬‏ ‏‮to‬‏ ‏‮user‬‏ ‏‮gestures‬‏ ‏‮instead‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "‏‮Requests‬‏ ‏‮the‬‏ ‏‮notification‬‏ ‏‮permission‬‏ ‏‮on‬‏ ‏‮page‬‏ ‏‮load‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "‏‮Avoids‬‏ ‏‮requesting‬‏ ‏‮the‬‏ ‏‮notification‬‏ ‏‮permission‬‏ ‏‮on‬‏ ‏‮page‬‏ ‏‮load‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "‏‮Failing‬‏ ‏‮Elements‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "‏‮Preventing‬‏ ‏‮password‬‏ ‏‮pasting‬‏ ‏‮undermines‬‏ ‏‮good‬‏ ‏‮security‬‏ ‏‮policy‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "‏‮Prevents‬‏ ‏‮users‬‏ ‏‮to‬‏ ‏‮paste‬‏ ‏‮into‬‏ ‏‮password‬‏ ‏‮fields‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "‏‮Allows‬‏ ‏‮users‬‏ ‏‮to‬‏ ‏‮paste‬‏ ‏‮into‬‏ ‏‮password‬‏ ‏‮fields‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "‏‮Protocol‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "‏‮HTTP‬‏/2 ‏‮offers‬‏ ‏‮many‬‏ ‏‮benefits‬‏ ‏‮over‬‏ ‏‮HTTP‬‏/1.1, ‏‮including‬‏ ‏‮binary‬‏ ‏‮headers‬‏, ‏‮multiplexing‬‏, ‏‮and‬‏ ‏‮server‬‏ ‏‮push‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮request‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}zero{# ‏‮requests‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}two{# ‏‮requests‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}few{# ‏‮requests‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}many{# ‏‮requests‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}other{# ‏‮requests‬‏ ‏‮not‬‏ ‏‮served‬‏ ‏‮via‬‏ ‏‮HTTP‬‏/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮use‬‏ ‏‮HTTP‬‏/2 ‏‮for‬‏ ‏‮all‬‏ ‏‮of‬‏ ‏‮its‬‏ ‏‮resources‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "‏‮Uses‬‏ ‏‮HTTP‬‏/2 ‏‮for‬‏ ‏‮its‬‏ ‏‮own‬‏ ‏‮resources‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮marking‬‏ ‏‮your‬‏ ‏‮touch‬‏ ‏‮and‬‏ ‏‮wheel‬‏ ‏‮event‬‏ ‏‮listeners‬‏ ‏‮as‬‏ `passive` ‏‮to‬‏ ‏‮improve‬‏ ‏‮your‬‏ ‏‮page‬‏'‏‮s‬‏ ‏‮scroll‬‏ ‏‮performance‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮use‬‏ ‏‮passive‬‏ ‏‮listeners‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮scrolling‬‏ ‏‮performance‬‏"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "‏‮Uses‬‏ ‏‮passive‬‏ ‏‮listeners‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮scrolling‬‏ ‏‮performance‬‏"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "‏‮Description‬‏"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "‏‮Errors‬‏ ‏‮logged‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮console‬‏ ‏‮indicate‬‏ ‏‮unresolved‬‏ ‏‮problems‬‏. ‏‮They‬‏ ‏‮can‬‏ ‏‮come‬‏ ‏‮from‬‏ ‏‮network‬‏ ‏‮request‬‏ ‏‮failures‬‏ ‏‮and‬‏ ‏‮other‬‏ ‏‮browser‬‏ ‏‮concerns‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "‏‮Browser‬‏ ‏‮errors‬‏ ‏‮were‬‏ ‏‮logged‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮console‬‏"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "‏‮No‬‏ ‏‮browser‬‏ ‏‮errors‬‏ ‏‮logged‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮console‬‏"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "‏‮Leverage‬‏ ‏‮the‬‏ ‏‮font‬‏-‏‮display‬‏ ‏‮CSS‬‏ ‏‮feature‬‏ ‏‮to‬‏ ‏‮ensure‬‏ ‏‮text‬‏ ‏‮is‬‏ ‏‮user‬‏-‏‮visible‬‏ ‏‮while‬‏ ‏‮webfonts‬‏ ‏‮are‬‏ ‏‮loading‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "‏‮Ensure‬‏ ‏‮text‬‏ ‏‮remains‬‏ ‏‮visible‬‏ ‏‮during‬‏ ‏‮webfont‬‏ ‏‮load‬‏"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "‏‮All‬‏ ‏‮text‬‏ ‏‮remains‬‏ ‏‮visible‬‏ ‏‮during‬‏ ‏‮webfont‬‏ ‏‮loads‬‏"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮automatically‬‏ ‏‮check‬‏ ‏‮the‬‏ ‏‮font‬‏-‏‮display‬‏ ‏‮value‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮following‬‏ ‏‮URL‬‏: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "‏‮Aspect‬‏ ‏‮Ratio‬‏ (‏‮Actual‬‏)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "‏‮Aspect‬‏ ‏‮Ratio‬‏ (‏‮Displayed‬‏)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "‏‮Image‬‏ ‏‮display‬‏ ‏‮dimensions‬‏ ‏‮should‬‏ ‏‮match‬‏ ‏‮natural‬‏ ‏‮aspect‬‏ ‏‮ratio‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "‏‮Displays‬‏ ‏‮images‬‏ ‏‮with‬‏ ‏‮incorrect‬‏ ‏‮aspect‬‏ ‏‮ratio‬‏"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "‏‮Displays‬‏ ‏‮images‬‏ ‏‮with‬‏ ‏‮correct‬‏ ‏‮aspect‬‏ ‏‮ratio‬‏"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "‏‮Invalid‬‏ ‏‮image‬‏ ‏‮sizing‬‏ ‏‮information‬‏ {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "‏‮Browsers‬‏ ‏‮can‬‏ ‏‮proactively‬‏ ‏‮prompt‬‏ ‏‮users‬‏ ‏‮to‬‏ ‏‮add‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮to‬‏ ‏‮their‬‏ ‏‮homescreen‬‏, ‏‮which‬‏ ‏‮can‬‏ ‏‮lead‬‏ ‏‮to‬‏ ‏‮higher‬‏ ‏‮engagement‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "‏‮Web‬‏ ‏‮app‬‏ ‏‮manifest‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮meet‬‏ ‏‮the‬‏ ‏‮installability‬‏ ‏‮requirements‬‏"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "‏‮Web‬‏ ‏‮app‬‏ ‏‮manifest‬‏ ‏‮meets‬‏ ‏‮the‬‏ ‏‮installability‬‏ ‏‮requirements‬‏"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "‏‮Insecure‬‏ ‏‮URL‬‏"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "‏‮All‬‏ ‏‮sites‬‏ ‏‮should‬‏ ‏‮be‬‏ ‏‮protected‬‏ ‏‮with‬‏ ‏‮HTTPS‬‏, ‏‮even‬‏ ‏‮ones‬‏ ‏‮that‬‏ ‏‮don‬‏'‏‮t‬‏ ‏‮handle‬‏ ‏‮sensitive‬‏ ‏‮data‬‏. ‏‮HTTPS‬‏ ‏‮prevents‬‏ ‏‮intruders‬‏ ‏‮from‬‏ ‏‮tampering‬‏ ‏‮with‬‏ ‏‮or‬‏ ‏‮passively‬‏ ‏‮listening‬‏ ‏‮in‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮communications‬‏ ‏‮between‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮and‬‏ ‏‮your‬‏ ‏‮users‬‏, ‏‮and‬‏ ‏‮is‬‏ ‏‮a‬‏ ‏‮prerequisite‬‏ ‏‮for‬‏ ‏‮HTTP‬‏/2 ‏‮and‬‏ ‏‮many‬‏ ‏‮new‬‏ ‏‮web‬‏ ‏‮platform‬‏ ‏‮APIs‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮insecure‬‏ ‏‮request‬‏ ‏‮found‬‏}zero{# ‏‮insecure‬‏ ‏‮requests‬‏ ‏‮found‬‏}two{# ‏‮insecure‬‏ ‏‮requests‬‏ ‏‮found‬‏}few{# ‏‮insecure‬‏ ‏‮requests‬‏ ‏‮found‬‏}many{# ‏‮insecure‬‏ ‏‮requests‬‏ ‏‮found‬‏}other{# ‏‮insecure‬‏ ‏‮requests‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮use‬‏ ‏‮HTTPS‬‏"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "‏‮Uses‬‏ ‏‮HTTPS‬‏"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "‏‮A‬‏ ‏‮fast‬‏ ‏‮page‬‏ ‏‮load‬‏ ‏‮over‬‏ ‏‮a‬‏ ‏‮cellular‬‏ ‏‮network‬‏ ‏‮ensures‬‏ ‏‮a‬‏ ‏‮good‬‏ ‏‮mobile‬‏ ‏‮user‬‏ ‏‮experience‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "‏‮Interactive‬‏ ‏‮at‬‏ {timeInMs, number, seconds} ‏‮s‬‏"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "‏‮Interactive‬‏ ‏‮on‬‏ ‏‮simulated‬‏ ‏‮mobile‬‏ ‏‮network‬‏ ‏‮at‬‏ {timeInMs, number, seconds} ‏‮s‬‏"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "‏‮Your‬‏ ‏‮page‬‏ ‏‮loads‬‏ ‏‮too‬‏ ‏‮slowly‬‏ ‏‮and‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮interactive‬‏ ‏‮within‬‏ 10 ‏‮seconds‬‏. ‏‮Look‬‏ ‏‮at‬‏ ‏‮the‬‏ ‏‮opportunities‬‏ ‏‮and‬‏ ‏‮diagnostics‬‏ ‏‮in‬‏ ‏‮the‬‏ \"‏‮Performance‬‏\" ‏‮section‬‏ ‏‮to‬‏ ‏‮learn‬‏ ‏‮how‬‏ ‏‮to‬‏ ‏‮improve‬‏."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "‏‮Page‬‏ ‏‮load‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮fast‬‏ ‏‮enough‬‏ ‏‮on‬‏ ‏‮mobile‬‏ ‏‮networks‬‏"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "‏‮Page‬‏ ‏‮load‬‏ ‏‮is‬‏ ‏‮fast‬‏ ‏‮enough‬‏ ‏‮on‬‏ ‏‮mobile‬‏ ‏‮networks‬‏"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "‏‮Category‬‏"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮reducing‬‏ ‏‮the‬‏ ‏‮time‬‏ ‏‮spent‬‏ ‏‮parsing‬‏, ‏‮compiling‬‏ ‏‮and‬‏ ‏‮executing‬‏ ‏‮JS‬‏. ‏‮You‬‏ ‏‮may‬‏ ‏‮find‬‏ ‏‮delivering‬‏ ‏‮smaller‬‏ ‏‮JS‬‏ ‏‮payloads‬‏ ‏‮helps‬‏ ‏‮with‬‏ ‏‮this‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "‏‮Minimize‬‏ ‏‮main‬‏-‏‮thread‬‏ ‏‮work‬‏"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "‏‮Minimizes‬‏ ‏‮main‬‏-‏‮thread‬‏ ‏‮work‬‏"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "‏‮To‬‏ ‏‮reach‬‏ ‏‮the‬‏ ‏‮most‬‏ ‏‮number‬‏ ‏‮of‬‏ ‏‮users‬‏, ‏‮sites‬‏ ‏‮should‬‏ ‏‮work‬‏ ‏‮across‬‏ ‏‮every‬‏ ‏‮major‬‏ ‏‮browser‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "‏‮Site‬‏ ‏‮works‬‏ ‏‮cross‬‏-‏‮browser‬‏"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "‏‮Ensure‬‏ ‏‮individual‬‏ ‏‮pages‬‏ ‏‮are‬‏ ‏‮deep‬‏ ‏‮linkable‬‏ ‏‮via‬‏ ‏‮URL‬‏ ‏‮and‬‏ ‏‮that‬‏ ‏‮URLs‬‏ ‏‮are‬‏ ‏‮unique‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮purpose‬‏ ‏‮of‬‏ ‏‮shareability‬‏ ‏‮on‬‏ ‏‮social‬‏ ‏‮media‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "‏‮Each‬‏ ‏‮page‬‏ ‏‮has‬‏ ‏‮a‬‏ ‏‮URL‬‏"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "‏‮Transitions‬‏ ‏‮should‬‏ ‏‮feel‬‏ ‏‮snappy‬‏ ‏‮as‬‏ ‏‮you‬‏ ‏‮tap‬‏ ‏‮around‬‏, ‏‮even‬‏ ‏‮on‬‏ ‏‮a‬‏ ‏‮slow‬‏ ‏‮network‬‏. ‏‮This‬‏ ‏‮experience‬‏ ‏‮is‬‏ ‏‮key‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮user‬‏'‏‮s‬‏ ‏‮perception‬‏ ‏‮of‬‏ ‏‮performance‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "‏‮Page‬‏ ‏‮transitions‬‏ ‏‮don‬‏'‏‮t‬‏ ‏‮feel‬‏ ‏‮like‬‏ ‏‮they‬‏ ‏‮block‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮network‬‏"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "‏‮Estimated‬‏ ‏‮Input‬‏ ‏‮Latency‬‏ ‏‮is‬‏ ‏‮an‬‏ ‏‮estimate‬‏ ‏‮of‬‏ ‏‮how‬‏ ‏‮long‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮takes‬‏ ‏‮to‬‏ ‏‮respond‬‏ ‏‮to‬‏ ‏‮user‬‏ ‏‮input‬‏, ‏‮in‬‏ ‏‮milliseconds‬‏, ‏‮during‬‏ ‏‮the‬‏ ‏‮busiest‬‏ 5‏‮s‬‏ ‏‮window‬‏ ‏‮of‬‏ ‏‮page‬‏ ‏‮load‬‏. ‏‮If‬‏ ‏‮your‬‏ ‏‮latency‬‏ ‏‮is‬‏ ‏‮higher‬‏ ‏‮than‬‏ 50 ‏‮ms‬‏, ‏‮users‬‏ ‏‮may‬‏ ‏‮perceive‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮as‬‏ ‏‮laggy‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "‏‮Estimated‬‏ ‏‮Input‬‏ ‏‮Latency‬‏"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "‏‮First‬‏ ‏‮Contentful‬‏ ‏‮Paint‬‏ ‏‮marks‬‏ ‏‮the‬‏ ‏‮time‬‏ ‏‮at‬‏ ‏‮which‬‏ ‏‮the‬‏ ‏‮first‬‏ ‏‮text‬‏ ‏‮or‬‏ ‏‮image‬‏ ‏‮is‬‏ ‏‮painted‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "‏‮First‬‏ ‏‮Contentful‬‏ ‏‮Paint‬‏"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "‏‮First‬‏ ‏‮CPU‬‏ ‏‮Idle‬‏ ‏‮marks‬‏ ‏‮the‬‏ ‏‮first‬‏ ‏‮time‬‏ ‏‮at‬‏ ‏‮which‬‏ ‏‮the‬‏ ‏‮page‬‏'‏‮s‬‏ ‏‮main‬‏ ‏‮thread‬‏ ‏‮is‬‏ ‏‮quiet‬‏ ‏‮enough‬‏ ‏‮to‬‏ ‏‮handle‬‏ ‏‮input‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "‏‮First‬‏ ‏‮CPU‬‏ ‏‮Idle‬‏"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "‏‮First‬‏ ‏‮Meaningful‬‏ ‏‮Paint‬‏ ‏‮measures‬‏ ‏‮when‬‏ ‏‮the‬‏ ‏‮primary‬‏ ‏‮content‬‏ ‏‮of‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮visible‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "‏‮First‬‏ ‏‮Meaningful‬‏ ‏‮Paint‬‏"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "‏‮Time‬‏ ‏‮to‬‏ ‏‮interactive‬‏ ‏‮is‬‏ ‏‮the‬‏ ‏‮amount‬‏ ‏‮of‬‏ ‏‮time‬‏ ‏‮it‬‏ ‏‮takes‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮to‬‏ ‏‮become‬‏ ‏‮fully‬‏ ‏‮interactive‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "‏‮Time‬‏ ‏‮to‬‏ ‏‮Interactive‬‏"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "‏‮The‬‏ ‏‮maximum‬‏ ‏‮potential‬‏ ‏‮First‬‏ ‏‮Input‬‏ ‏‮Delay‬‏ ‏‮that‬‏ ‏‮your‬‏ ‏‮users‬‏ ‏‮could‬‏ ‏‮experience‬‏ ‏‮is‬‏ ‏‮the‬‏ ‏‮duration‬‏, ‏‮in‬‏ ‏‮milliseconds‬‏, ‏‮of‬‏ ‏‮the‬‏ ‏‮longest‬‏ ‏‮task‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "‏‮Max‬‏ ‏‮Potential‬‏ ‏‮First‬‏ ‏‮Input‬‏ ‏‮Delay‬‏"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "‏‮Speed‬‏ ‏‮Index‬‏ ‏‮shows‬‏ ‏‮how‬‏ ‏‮quickly‬‏ ‏‮the‬‏ ‏‮contents‬‏ ‏‮of‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮are‬‏ ‏‮visibly‬‏ ‏‮populated‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "‏‮Speed‬‏ ‏‮Index‬‏"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "‏‮Sum‬‏ ‏‮of‬‏ ‏‮all‬‏ ‏‮time‬‏ ‏‮periods‬‏ ‏‮between‬‏ ‏‮FCP‬‏ ‏‮and‬‏ ‏‮Time‬‏ ‏‮to‬‏ ‏‮Interactive‬‏, ‏‮when‬‏ ‏‮task‬‏ ‏‮length‬‏ ‏‮exceeded‬‏ 50‏‮ms‬‏, ‏‮expressed‬‏ ‏‮in‬‏ ‏‮milliseconds‬‏."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "‏‮Total‬‏ ‏‮Blocking‬‏ ‏‮Time‬‏"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "‏‮Network‬‏ ‏‮round‬‏ ‏‮trip‬‏ ‏‮times‬‏ (‏‮RTT‬‏) ‏‮have‬‏ ‏‮a‬‏ ‏‮large‬‏ ‏‮impact‬‏ ‏‮on‬‏ ‏‮performance‬‏. ‏‮If‬‏ ‏‮the‬‏ ‏‮RTT‬‏ ‏‮to‬‏ ‏‮an‬‏ ‏‮origin‬‏ ‏‮is‬‏ ‏‮high‬‏, ‏‮it‬‏'‏‮s‬‏ ‏‮an‬‏ ‏‮indication‬‏ ‏‮that‬‏ ‏‮servers‬‏ ‏‮closer‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮user‬‏ ‏‮could‬‏ ‏‮improve‬‏ ‏‮performance‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "‏‮Network‬‏ ‏‮Round‬‏ ‏‮Trip‬‏ ‏‮Times‬‏"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "‏‮Server‬‏ ‏‮latencies‬‏ ‏‮can‬‏ ‏‮impact‬‏ ‏‮web‬‏ ‏‮performance‬‏. ‏‮If‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮latency‬‏ ‏‮of‬‏ ‏‮an‬‏ ‏‮origin‬‏ ‏‮is‬‏ ‏‮high‬‏, ‏‮it‬‏'‏‮s‬‏ ‏‮an‬‏ ‏‮indication‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮is‬‏ ‏‮overloaded‬‏ ‏‮or‬‏ ‏‮has‬‏ ‏‮poor‬‏ ‏‮backend‬‏ ‏‮performance‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "‏‮Server‬‏ ‏‮Backend‬‏ ‏‮Latencies‬‏"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "‏‮A‬‏ ‏‮service‬‏ ‏‮worker‬‏ ‏‮enables‬‏ ‏‮your‬‏ ‏‮web‬‏ ‏‮app‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮reliable‬‏ ‏‮in‬‏ ‏‮unpredictable‬‏ ‏‮network‬‏ ‏‮conditions‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ‏‮does‬‏ ‏‮not‬‏ ‏‮respond‬‏ ‏‮with‬‏ ‏‮a‬‏ 200 ‏‮when‬‏ ‏‮offline‬‏"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` ‏‮responds‬‏ ‏‮with‬‏ ‏‮a‬‏ 200 ‏‮when‬‏ ‏‮offline‬‏"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "‏‮Lighthouse‬‏ ‏‮couldn‬‏'‏‮t‬‏ ‏‮read‬‏ ‏‮the‬‏ `start_url` ‏‮from‬‏ ‏‮the‬‏ ‏‮manifest‬‏. ‏‮As‬‏ ‏‮a‬‏ ‏‮result‬‏, ‏‮the‬‏ `start_url` ‏‮was‬‏ ‏‮assumed‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮the‬‏ ‏‮document‬‏'‏‮s‬‏ ‏‮URL‬‏. ‏‮Error‬‏ ‏‮message‬‏: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "‏‮Over‬‏ ‏‮Budget‬‏"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "‏‮Keep‬‏ ‏‮the‬‏ ‏‮quantity‬‏ ‏‮and‬‏ ‏‮size‬‏ ‏‮of‬‏ ‏‮network‬‏ ‏‮requests‬‏ ‏‮under‬‏ ‏‮the‬‏ ‏‮targets‬‏ ‏‮set‬‏ ‏‮by‬‏ ‏‮the‬‏ ‏‮provided‬‏ ‏‮performance‬‏ ‏‮budget‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 ‏‮request‬‏}zero{# ‏‮requests‬‏}two{# ‏‮requests‬‏}few{# ‏‮requests‬‏}many{# ‏‮requests‬‏}other{# ‏‮requests‬‏}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "‏‮Performance‬‏ ‏‮budget‬‏"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "‏‮If‬‏ ‏‮you‬‏'‏‮ve‬‏ ‏‮already‬‏ ‏‮set‬‏ ‏‮up‬‏ ‏‮HTTPS‬‏, ‏‮make‬‏ ‏‮sure‬‏ ‏‮that‬‏ ‏‮you‬‏ ‏‮redirect‬‏ ‏‮all‬‏ ‏‮HTTP‬‏ ‏‮traffic‬‏ ‏‮to‬‏ ‏‮HTTPS‬‏ ‏‮in‬‏ ‏‮order‬‏ ‏‮to‬‏ ‏‮enable‬‏ ‏‮secure‬‏ ‏‮web‬‏ ‏‮features‬‏ ‏‮for‬‏ ‏‮all‬‏ ‏‮your‬‏ ‏‮users‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮redirect‬‏ ‏‮HTTP‬‏ ‏‮traffic‬‏ ‏‮to‬‏ ‏‮HTTPS‬‏"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "‏‮Redirects‬‏ ‏‮HTTP‬‏ ‏‮traffic‬‏ ‏‮to‬‏ ‏‮HTTPS‬‏"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "‏‮Redirects‬‏ ‏‮introduce‬‏ ‏‮additional‬‏ ‏‮delays‬‏ ‏‮before‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮can‬‏ ‏‮be‬‏ ‏‮loaded‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "‏‮Avoid‬‏ ‏‮multiple‬‏ ‏‮page‬‏ ‏‮redirects‬‏"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "‏‮To‬‏ ‏‮set‬‏ ‏‮budgets‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮quantity‬‏ ‏‮and‬‏ ‏‮size‬‏ ‏‮of‬‏ ‏‮page‬‏ ‏‮resources‬‏, ‏‮add‬‏ ‏‮a‬‏ ‏‮budget‬‏.‏‮json‬‏ ‏‮file‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 ‏‮request‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}zero{# ‏‮requests‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}two{# ‏‮requests‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}few{# ‏‮requests‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}many{# ‏‮requests‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}other{# ‏‮requests‬‏ • {byteCount, number, bytes} ‏‮KB‬‏}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "‏‮Keep‬‏ ‏‮request‬‏ ‏‮counts‬‏ ‏‮low‬‏ ‏‮and‬‏ ‏‮transfer‬‏ ‏‮sizes‬‏ ‏‮small‬‏"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "‏‮Canonical‬‏ ‏‮links‬‏ ‏‮suggest‬‏ ‏‮which‬‏ ‏‮URL‬‏ ‏‮to‬‏ ‏‮show‬‏ ‏‮in‬‏ ‏‮search‬‏ ‏‮results‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "‏‮Multiple‬‏ ‏‮conflicting‬‏ ‏‮URLs‬‏ ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "‏‮Points‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮different‬‏ ‏‮domain‬‏ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "‏‮Invalid‬‏ ‏‮URL‬‏ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "‏‮Points‬‏ ‏‮to‬‏ ‏‮another‬‏ `hreflang` ‏‮location‬‏ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "‏‮Relative‬‏ ‏‮URL‬‏ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "‏‮Points‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮domain‬‏'‏‮s‬‏ ‏‮root‬‏ ‏‮URL‬‏ (‏‮the‬‏ ‏‮homepage‬‏), ‏‮instead‬‏ ‏‮of‬‏ ‏‮an‬‏ ‏‮equivalent‬‏ ‏‮page‬‏ ‏‮of‬‏ ‏‮content‬‏"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "‏‮Document‬‏ ‏‮has‬‏ ‏‮a‬‏ ‏‮valid‬‏ `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "‏‮Font‬‏ ‏‮sizes‬‏ ‏‮less‬‏ ‏‮than‬‏ 12‏‮px‬‏ ‏‮are‬‏ ‏‮too‬‏ ‏‮small‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮legible‬‏ ‏‮and‬‏ ‏‮require‬‏ ‏‮mobile‬‏ ‏‮visitors‬‏ ‏‮to‬‏ “‏‮pinch‬‏ ‏‮to‬‏ ‏‮zoom‬‏” ‏‮in‬‏ ‏‮order‬‏ ‏‮to‬‏ ‏‮read‬‏. ‏‮Strive‬‏ ‏‮to‬‏ ‏‮have‬‏ >60% ‏‮of‬‏ ‏‮page‬‏ ‏‮text‬‏ ≥12‏‮px‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} ‏‮legible‬‏ ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "‏‮Text‬‏ ‏‮is‬‏ ‏‮illegible‬‏ ‏‮because‬‏ ‏‮there‬‏'‏‮s‬‏ ‏‮no‬‏ ‏‮viewport‬‏ ‏‮meta‬‏ ‏‮tag‬‏ ‏‮optimized‬‏ ‏‮for‬‏ ‏‮mobile‬‏ ‏‮screens‬‏."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} ‏‮of‬‏ ‏‮text‬‏ ‏‮is‬‏ ‏‮too‬‏ ‏‮small‬‏ (‏‮based‬‏ ‏‮on‬‏ {decimalProportionVisited, number, extendedPercent} ‏‮sample‬‏)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮use‬‏ ‏‮legible‬‏ ‏‮font‬‏ ‏‮sizes‬‏"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "‏‮Document‬‏ ‏‮uses‬‏ ‏‮legible‬‏ ‏‮font‬‏ ‏‮sizes‬‏"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "‏‮hreflang‬‏ ‏‮links‬‏ ‏‮tell‬‏ ‏‮search‬‏ ‏‮engines‬‏ ‏‮what‬‏ ‏‮version‬‏ ‏‮of‬‏ ‏‮a‬‏ ‏‮page‬‏ ‏‮they‬‏ ‏‮should‬‏ ‏‮list‬‏ ‏‮in‬‏ ‏‮search‬‏ ‏‮results‬‏ ‏‮for‬‏ ‏‮a‬‏ ‏‮given‬‏ ‏‮language‬‏ ‏‮or‬‏ ‏‮region‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮doesn‬‏'‏‮t‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "‏‮Document‬‏ ‏‮has‬‏ ‏‮a‬‏ ‏‮valid‬‏ `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "‏‮Pages‬‏ ‏‮with‬‏ ‏‮unsuccessful‬‏ ‏‮HTTP‬‏ ‏‮status‬‏ ‏‮codes‬‏ ‏‮may‬‏ ‏‮not‬‏ ‏‮be‬‏ ‏‮indexed‬‏ ‏‮properly‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "‏‮Page‬‏ ‏‮has‬‏ ‏‮unsuccessful‬‏ ‏‮HTTP‬‏ ‏‮status‬‏ ‏‮code‬‏"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "‏‮Page‬‏ ‏‮has‬‏ ‏‮successful‬‏ ‏‮HTTP‬‏ ‏‮status‬‏ ‏‮code‬‏"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "‏‮Search‬‏ ‏‮engines‬‏ ‏‮are‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮include‬‏ ‏‮your‬‏ ‏‮pages‬‏ ‏‮in‬‏ ‏‮search‬‏ ‏‮results‬‏ ‏‮if‬‏ ‏‮they‬‏ ‏‮don‬‏'‏‮t‬‏ ‏‮have‬‏ ‏‮permission‬‏ ‏‮to‬‏ ‏‮crawl‬‏ ‏‮them‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "‏‮Page‬‏ ‏‮is‬‏ ‏‮blocked‬‏ ‏‮from‬‏ ‏‮indexing‬‏"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "‏‮Page‬‏ ‏‮isn‬‏’‏‮t‬‏ ‏‮blocked‬‏ ‏‮from‬‏ ‏‮indexing‬‏"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "‏‮Descriptive‬‏ ‏‮link‬‏ ‏‮text‬‏ ‏‮helps‬‏ ‏‮search‬‏ ‏‮engines‬‏ ‏‮understand‬‏ ‏‮your‬‏ ‏‮content‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮link‬‏ ‏‮found‬‏}zero{# ‏‮links‬‏ ‏‮found‬‏}two{# ‏‮links‬‏ ‏‮found‬‏}few{# ‏‮links‬‏ ‏‮found‬‏}many{# ‏‮links‬‏ ‏‮found‬‏}other{# ‏‮links‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "‏‮Links‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮descriptive‬‏ ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "‏‮Links‬‏ ‏‮have‬‏ ‏‮descriptive‬‏ ‏‮text‬‏"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "‏‮Run‬‏ ‏‮the‬‏ [‏‮Structured‬‏ ‏‮Data‬‏ ‏‮Testing‬‏ ‏‮Tool‬‏](https://search.google.com/structured-data/testing-tool/) ‏‮and‬‏ ‏‮the‬‏ [‏‮Structured‬‏ ‏‮Data‬‏ ‏‮Linter‬‏](http://linter.structured-data.org/) ‏‮to‬‏ ‏‮validate‬‏ ‏‮structured‬‏ ‏‮data‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "‏‮Structured‬‏ ‏‮data‬‏ ‏‮is‬‏ ‏‮valid‬‏"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "‏‮Meta‬‏ ‏‮descriptions‬‏ ‏‮may‬‏ ‏‮be‬‏ ‏‮included‬‏ ‏‮in‬‏ ‏‮search‬‏ ‏‮results‬‏ ‏‮to‬‏ ‏‮concisely‬‏ ‏‮summarize‬‏ ‏‮page‬‏ ‏‮content‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "‏‮Description‬‏ ‏‮text‬‏ ‏‮is‬‏ ‏‮empty‬‏."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮meta‬‏ ‏‮description‬‏"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "‏‮Document‬‏ ‏‮has‬‏ ‏‮a‬‏ ‏‮meta‬‏ ‏‮description‬‏"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "‏‮Search‬‏ ‏‮engines‬‏ ‏‮can‬‏'‏‮t‬‏ ‏‮index‬‏ ‏‮plugin‬‏ ‏‮content‬‏, ‏‮and‬‏ ‏‮many‬‏ ‏‮devices‬‏ ‏‮restrict‬‏ ‏‮plugins‬‏ ‏‮or‬‏ ‏‮don‬‏'‏‮t‬‏ ‏‮support‬‏ ‏‮them‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "‏‮Document‬‏ ‏‮uses‬‏ ‏‮plugins‬‏"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "‏‮Document‬‏ ‏‮avoids‬‏ ‏‮plugins‬‏"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "‏‮If‬‏ ‏‮your‬‏ ‏‮robots‬‏.‏‮txt‬‏ ‏‮file‬‏ ‏‮is‬‏ ‏‮malformed‬‏, ‏‮crawlers‬‏ ‏‮may‬‏ ‏‮not‬‏ ‏‮be‬‏ ‏‮able‬‏ ‏‮to‬‏ ‏‮understand‬‏ ‏‮how‬‏ ‏‮you‬‏ ‏‮want‬‏ ‏‮your‬‏ ‏‮website‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮crawled‬‏ ‏‮or‬‏ ‏‮indexed‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "‏‮Request‬‏ ‏‮for‬‏ ‏‮robots‬‏.‏‮txt‬‏ ‏‮returned‬‏ ‏‮HTTP‬‏ ‏‮status‬‏: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 ‏‮error‬‏ ‏‮found‬‏}zero{# ‏‮errors‬‏ ‏‮found‬‏}two{# ‏‮errors‬‏ ‏‮found‬‏}few{# ‏‮errors‬‏ ‏‮found‬‏}many{# ‏‮errors‬‏ ‏‮found‬‏}other{# ‏‮errors‬‏ ‏‮found‬‏}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮download‬‏ ‏‮a‬‏ ‏‮robots‬‏.‏‮txt‬‏ ‏‮file‬‏"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "‏‮robots‬‏.‏‮txt‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮valid‬‏"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "‏‮robots‬‏.‏‮txt‬‏ ‏‮is‬‏ ‏‮valid‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "‏‮Interactive‬‏ ‏‮elements‬‏ ‏‮like‬‏ ‏‮buttons‬‏ ‏‮and‬‏ ‏‮links‬‏ ‏‮should‬‏ ‏‮be‬‏ ‏‮large‬‏ ‏‮enough‬‏ (48‏‮x‬‏48‏‮px‬‏), ‏‮and‬‏ ‏‮have‬‏ ‏‮enough‬‏ ‏‮space‬‏ ‏‮around‬‏ ‏‮them‬‏, ‏‮to‬‏ ‏‮be‬‏ ‏‮easy‬‏ ‏‮enough‬‏ ‏‮to‬‏ ‏‮tap‬‏ ‏‮without‬‏ ‏‮overlapping‬‏ ‏‮onto‬‏ ‏‮other‬‏ ‏‮elements‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} ‏‮appropriately‬‏ ‏‮sized‬‏ ‏‮tap‬‏ ‏‮targets‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "‏‮Tap‬‏ ‏‮targets‬‏ ‏‮are‬‏ ‏‮too‬‏ ‏‮small‬‏ ‏‮because‬‏ ‏‮there‬‏'‏‮s‬‏ ‏‮no‬‏ ‏‮viewport‬‏ ‏‮meta‬‏ ‏‮tag‬‏ ‏‮optimized‬‏ ‏‮for‬‏ ‏‮mobile‬‏ ‏‮screens‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "‏‮Tap‬‏ ‏‮targets‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮sized‬‏ ‏‮appropriately‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "‏‮Overlapping‬‏ ‏‮Target‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "‏‮Tap‬‏ ‏‮Target‬‏"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "‏‮Tap‬‏ ‏‮targets‬‏ ‏‮are‬‏ ‏‮sized‬‏ ‏‮appropriately‬‏"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "‏‮The‬‏ ‏‮service‬‏ ‏‮worker‬‏ ‏‮is‬‏ ‏‮the‬‏ ‏‮technology‬‏ ‏‮that‬‏ ‏‮enables‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮to‬‏ ‏‮use‬‏ ‏‮many‬‏ ‏‮Progressive‬‏ ‏‮Web‬‏ ‏‮App‬‏ ‏‮features‬‏, ‏‮such‬‏ ‏‮as‬‏ ‏‮offline‬‏, ‏‮add‬‏ ‏‮to‬‏ ‏‮homescreen‬‏, ‏‮and‬‏ ‏‮push‬‏ ‏‮notifications‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "‏‮This‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮controlled‬‏ ‏‮by‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏, ‏‮however‬‏ ‏‮no‬‏ `start_url` ‏‮was‬‏ ‏‮found‬‏ ‏‮because‬‏ ‏‮manifest‬‏ ‏‮failed‬‏ ‏‮to‬‏ ‏‮parse‬‏ ‏‮as‬‏ ‏‮valid‬‏ ‏‮JSON‬‏"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "‏‮This‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮controlled‬‏ ‏‮by‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏, ‏‮however‬‏ ‏‮the‬‏ `start_url` ({startUrl}) ‏‮is‬‏ ‏‮not‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮service‬‏ ‏‮worker‬‏'‏‮s‬‏ ‏‮scope‬‏ ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "‏‮This‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮controlled‬‏ ‏‮by‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏, ‏‮however‬‏ ‏‮no‬‏ `start_url` ‏‮was‬‏ ‏‮found‬‏ ‏‮because‬‏ ‏‮no‬‏ ‏‮manifest‬‏ ‏‮was‬‏ ‏‮fetched‬‏."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "‏‮This‬‏ ‏‮origin‬‏ ‏‮has‬‏ ‏‮one‬‏ ‏‮or‬‏ ‏‮more‬‏ ‏‮service‬‏ ‏‮workers‬‏, ‏‮however‬‏ ‏‮the‬‏ ‏‮page‬‏ ({pageUrl}) ‏‮is‬‏ ‏‮not‬‏ ‏‮in‬‏ ‏‮scope‬‏."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮register‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏ ‏‮that‬‏ ‏‮controls‬‏ ‏‮page‬‏ ‏‮and‬‏ `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "‏‮Registers‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏ ‏‮that‬‏ ‏‮controls‬‏ ‏‮page‬‏ ‏‮and‬‏ `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "‏‮A‬‏ ‏‮themed‬‏ ‏‮splash‬‏ ‏‮screen‬‏ ‏‮ensures‬‏ ‏‮a‬‏ ‏‮high‬‏-‏‮quality‬‏ ‏‮experience‬‏ ‏‮when‬‏ ‏‮users‬‏ ‏‮launch‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮from‬‏ ‏‮their‬‏ ‏‮homescreens‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "‏‮Is‬‏ ‏‮not‬‏ ‏‮configured‬‏ ‏‮for‬‏ ‏‮a‬‏ ‏‮custom‬‏ ‏‮splash‬‏ ‏‮screen‬‏"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "‏‮Configured‬‏ ‏‮for‬‏ ‏‮a‬‏ ‏‮custom‬‏ ‏‮splash‬‏ ‏‮screen‬‏"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "‏‮The‬‏ ‏‮browser‬‏ ‏‮address‬‏ ‏‮bar‬‏ ‏‮can‬‏ ‏‮be‬‏ ‏‮themed‬‏ ‏‮to‬‏ ‏‮match‬‏ ‏‮your‬‏ ‏‮site‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮set‬‏ ‏‮a‬‏ ‏‮theme‬‏ ‏‮color‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮address‬‏ ‏‮bar‬‏."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "‏‮Sets‬‏ ‏‮a‬‏ ‏‮theme‬‏ ‏‮color‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮address‬‏ ‏‮bar‬‏."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "‏‮Main‬‏-‏‮Thread‬‏ ‏‮Blocking‬‏ ‏‮Time‬‏"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "‏‮Third‬‏-‏‮Party‬‏"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "‏‮Third‬‏-‏‮party‬‏ ‏‮code‬‏ ‏‮can‬‏ ‏‮significantly‬‏ ‏‮impact‬‏ ‏‮load‬‏ ‏‮performance‬‏. ‏‮Limit‬‏ ‏‮the‬‏ ‏‮number‬‏ ‏‮of‬‏ ‏‮redundant‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮providers‬‏ ‏‮and‬‏ ‏‮try‬‏ ‏‮to‬‏ ‏‮load‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮code‬‏ ‏‮after‬‏ ‏‮your‬‏ ‏‮page‬‏ ‏‮has‬‏ ‏‮primarily‬‏ ‏‮finished‬‏ ‏‮loading‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "‏‮Third‬‏-‏‮party‬‏ ‏‮code‬‏ ‏‮blocked‬‏ ‏‮the‬‏ ‏‮main‬‏ ‏‮thread‬‏ ‏‮for‬‏ {timeInMs, number, milliseconds} ‏‮ms‬‏"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "‏‮Reduce‬‏ ‏‮the‬‏ ‏‮impact‬‏ ‏‮of‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮code‬‏"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "‏‮Third‬‏-‏‮Party‬‏ ‏‮usage‬‏"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "‏‮Time‬‏ ‏‮To‬‏ ‏‮First‬‏ ‏‮Byte‬‏ ‏‮identifies‬‏ ‏‮the‬‏ ‏‮time‬‏ ‏‮at‬‏ ‏‮which‬‏ ‏‮your‬‏ ‏‮server‬‏ ‏‮sends‬‏ ‏‮a‬‏ ‏‮response‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "‏‮Root‬‏ ‏‮document‬‏ ‏‮took‬‏ {timeInMs, number, milliseconds} ‏‮ms‬‏"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "‏‮Reduce‬‏ ‏‮server‬‏ ‏‮response‬‏ ‏‮times‬‏ (‏‮TTFB‬‏)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "‏‮Server‬‏ ‏‮response‬‏ ‏‮times‬‏ ‏‮are‬‏ ‏‮low‬‏ (‏‮TTFB‬‏)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "‏‮Duration‬‏"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "‏‮Start‬‏ ‏‮Time‬‏"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "‏‮Type‬‏"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮instrumenting‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮with‬‏ ‏‮the‬‏ ‏‮User‬‏ ‏‮Timing‬‏ ‏‮API‬‏ ‏‮to‬‏ ‏‮measure‬‏ ‏‮your‬‏ ‏‮app‬‏'‏‮s‬‏ ‏‮real‬‏-‏‮world‬‏ ‏‮performance‬‏ ‏‮during‬‏ ‏‮key‬‏ ‏‮user‬‏ ‏‮experiences‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ‏‮user‬‏ ‏‮timing‬‏}zero{# ‏‮user‬‏ ‏‮timings‬‏}two{# ‏‮user‬‏ ‏‮timings‬‏}few{# ‏‮user‬‏ ‏‮timings‬‏}many{# ‏‮user‬‏ ‏‮timings‬‏}other{# ‏‮user‬‏ ‏‮timings‬‏}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "‏‮User‬‏ ‏‮Timing‬‏ ‏‮marks‬‏ ‏‮and‬‏ ‏‮measures‬‏"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "‏‮A‬‏ ‏‮preconnect‬‏ <link> ‏‮was‬‏ ‏‮found‬‏ ‏‮for‬‏ \"{securityOrigin}\" ‏‮but‬‏ ‏‮was‬‏ ‏‮not‬‏ ‏‮used‬‏ ‏‮by‬‏ ‏‮the‬‏ ‏‮browser‬‏. ‏‮Check‬‏ ‏‮that‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮using‬‏ ‏‮the‬‏ `crossorigin` ‏‮attribute‬‏ ‏‮properly‬‏."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮adding‬‏ `preconnect` ‏‮or‬‏ `dns-prefetch` ‏‮resource‬‏ ‏‮hints‬‏ ‏‮to‬‏ ‏‮establish‬‏ ‏‮early‬‏ ‏‮connections‬‏ ‏‮to‬‏ ‏‮important‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮origins‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "‏‮Preconnect‬‏ ‏‮to‬‏ ‏‮required‬‏ ‏‮origins‬‏"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "‏‮A‬‏ ‏‮preload‬‏ <link> ‏‮was‬‏ ‏‮found‬‏ ‏‮for‬‏ \"{preloadURL}\" ‏‮but‬‏ ‏‮was‬‏ ‏‮not‬‏ ‏‮used‬‏ ‏‮by‬‏ ‏‮the‬‏ ‏‮browser‬‏. ‏‮Check‬‏ ‏‮that‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮using‬‏ ‏‮the‬‏ `crossorigin` ‏‮attribute‬‏ ‏‮properly‬‏."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "‏‮Consider‬‏ ‏‮using‬‏ `<link rel=preload>` ‏‮to‬‏ ‏‮prioritize‬‏ ‏‮fetching‬‏ ‏‮resources‬‏ ‏‮that‬‏ ‏‮are‬‏ ‏‮currently‬‏ ‏‮requested‬‏ ‏‮later‬‏ ‏‮in‬‏ ‏‮page‬‏ ‏‮load‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "‏‮Preload‬‏ ‏‮key‬‏ ‏‮requests‬‏"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "‏‮Add‬‏ ‏‮a‬‏ `<meta name=\"viewport\">` ‏‮tag‬‏ ‏‮to‬‏ ‏‮optimize‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮for‬‏ ‏‮mobile‬‏ ‏‮screens‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "‏‮No‬‏ `<meta name=\"viewport\">` ‏‮tag‬‏ ‏‮found‬‏"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ `<meta name=\"viewport\">` ‏‮tag‬‏ ‏‮with‬‏ `width` ‏‮or‬‏ `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "‏‮Has‬‏ ‏‮a‬‏ `<meta name=\"viewport\">` ‏‮tag‬‏ ‏‮with‬‏ `width` ‏‮or‬‏ `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "‏‮Your‬‏ ‏‮app‬‏ ‏‮should‬‏ ‏‮display‬‏ ‏‮some‬‏ ‏‮content‬‏ ‏‮when‬‏ ‏‮JavaScript‬‏ ‏‮is‬‏ ‏‮disabled‬‏, ‏‮even‬‏ ‏‮if‬‏ ‏‮it‬‏'‏‮s‬‏ ‏‮just‬‏ ‏‮a‬‏ ‏‮warning‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮user‬‏ ‏‮that‬‏ ‏‮JavaScript‬‏ ‏‮is‬‏ ‏‮required‬‏ ‏‮to‬‏ ‏‮use‬‏ ‏‮the‬‏ ‏‮app‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "‏‮The‬‏ ‏‮page‬‏ ‏‮body‬‏ ‏‮should‬‏ ‏‮render‬‏ ‏‮some‬‏ ‏‮content‬‏ ‏‮if‬‏ ‏‮its‬‏ ‏‮scripts‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮available‬‏."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "‏‮Does‬‏ ‏‮not‬‏ ‏‮provide‬‏ ‏‮fallback‬‏ ‏‮content‬‏ ‏‮when‬‏ ‏‮JavaScript‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮available‬‏"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "‏‮Contains‬‏ ‏‮some‬‏ ‏‮content‬‏ ‏‮when‬‏ ‏‮JavaScript‬‏ ‏‮is‬‏ ‏‮not‬‏ ‏‮available‬‏"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "‏‮If‬‏ ‏‮you‬‏'‏‮re‬‏ ‏‮building‬‏ ‏‮a‬‏ ‏‮Progressive‬‏ ‏‮Web‬‏ ‏‮App‬‏, ‏‮consider‬‏ ‏‮using‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮worker‬‏ ‏‮so‬‏ ‏‮that‬‏ ‏‮your‬‏ ‏‮app‬‏ ‏‮can‬‏ ‏‮work‬‏ ‏‮offline‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "‏‮Current‬‏ ‏‮page‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮respond‬‏ ‏‮with‬‏ ‏‮a‬‏ 200 ‏‮when‬‏ ‏‮offline‬‏"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "‏‮Current‬‏ ‏‮page‬‏ ‏‮responds‬‏ ‏‮with‬‏ ‏‮a‬‏ 200 ‏‮when‬‏ ‏‮offline‬‏"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "‏‮The‬‏ ‏‮page‬‏ ‏‮may‬‏ ‏‮not‬‏ ‏‮be‬‏ ‏‮loading‬‏ ‏‮offline‬‏ ‏‮because‬‏ ‏‮your‬‏ ‏‮test‬‏ ‏‮URL‬‏ ({requested}) ‏‮was‬‏ ‏‮redirected‬‏ ‏‮to‬‏ \"{final}\". ‏‮Try‬‏ ‏‮testing‬‏ ‏‮the‬‏ ‏‮second‬‏ ‏‮URL‬‏ ‏‮directly‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮usage‬‏ ‏‮of‬‏ ‏‮ARIA‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮application‬‏ ‏‮which‬‏ ‏‮may‬‏ ‏‮enhance‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮of‬‏ ‏‮assistive‬‏ ‏‮technology‬‏, ‏‮like‬‏ ‏‮a‬‏ ‏‮screen‬‏ ‏‮reader‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "‏‮ARIA‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮provide‬‏ ‏‮alternative‬‏ ‏‮content‬‏ ‏‮for‬‏ ‏‮audio‬‏ ‏‮and‬‏ ‏‮video‬‏. ‏‮This‬‏ ‏‮may‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮with‬‏ ‏‮hearing‬‏ ‏‮or‬‏ ‏‮vision‬‏ ‏‮impairments‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "‏‮Audio‬‏ ‏‮and‬‏ ‏‮video‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮items‬‏ ‏‮highlight‬‏ ‏‮common‬‏ ‏‮accessibility‬‏ ‏‮best‬‏ ‏‮practices‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "‏‮Best‬‏ ‏‮practices‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "‏‮These‬‏ ‏‮checks‬‏ ‏‮highlight‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ [‏‮improve‬‏ ‏‮the‬‏ ‏‮accessibility‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮web‬‏ ‏‮app‬‏](https://developers.google.com/web/fundamentals/accessibility). ‏‮Only‬‏ ‏‮a‬‏ ‏‮subset‬‏ ‏‮of‬‏ ‏‮accessibility‬‏ ‏‮issues‬‏ ‏‮can‬‏ ‏‮be‬‏ ‏‮automatically‬‏ ‏‮detected‬‏ ‏‮so‬‏ ‏‮manual‬‏ ‏‮testing‬‏ ‏‮is‬‏ ‏‮also‬‏ ‏‮encouraged‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "‏‮These‬‏ ‏‮items‬‏ ‏‮address‬‏ ‏‮areas‬‏ ‏‮which‬‏ ‏‮an‬‏ ‏‮automated‬‏ ‏‮testing‬‏ ‏‮tool‬‏ ‏‮cannot‬‏ ‏‮cover‬‏. ‏‮Learn‬‏ ‏‮more‬‏ ‏‮in‬‏ ‏‮our‬‏ ‏‮guide‬‏ ‏‮on‬‏ [‏‮conducting‬‏ ‏‮an‬‏ ‏‮accessibility‬‏ ‏‮review‬‏](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "‏‮Accessibility‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮legibility‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮content‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "‏‮Contrast‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮interpretation‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮content‬‏ ‏‮by‬‏ ‏‮users‬‏ ‏‮in‬‏ ‏‮different‬‏ ‏‮locales‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "‏‮Internationalization‬‏ ‏‮and‬‏ ‏‮localization‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮semantics‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮controls‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮application‬‏. ‏‮This‬‏ ‏‮may‬‏ ‏‮enhance‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮for‬‏ ‏‮users‬‏ ‏‮of‬‏ ‏‮assistive‬‏ ‏‮technology‬‏, ‏‮like‬‏ ‏‮a‬‏ ‏‮screen‬‏ ‏‮reader‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "‏‮Names‬‏ ‏‮and‬‏ ‏‮labels‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮keyboard‬‏ ‏‮navigation‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮application‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "‏‮Navigation‬‏"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮are‬‏ ‏‮opportunities‬‏ ‏‮to‬‏ ‏‮to‬‏ ‏‮improve‬‏ ‏‮the‬‏ ‏‮experience‬‏ ‏‮of‬‏ ‏‮reading‬‏ ‏‮tabular‬‏ ‏‮or‬‏ ‏‮list‬‏ ‏‮data‬‏ ‏‮using‬‏ ‏‮assistive‬‏ ‏‮technology‬‏, ‏‮like‬‏ ‏‮a‬‏ ‏‮screen‬‏ ‏‮reader‬‏."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "‏‮Tables‬‏ ‏‮and‬‏ ‏‮lists‬‏"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "‏‮Best‬‏ ‏‮Practices‬‏"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "‏‮Performance‬‏ ‏‮budgets‬‏ ‏‮set‬‏ ‏‮standards‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮performance‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮site‬‏."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "‏‮Budgets‬‏"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "‏‮More‬‏ ‏‮information‬‏ ‏‮about‬‏ ‏‮the‬‏ ‏‮performance‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮application‬‏. ‏‮These‬‏ ‏‮numbers‬‏ ‏‮don‬‏'‏‮t‬‏ [‏‮directly‬‏ ‏‮affect‬‏](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) ‏‮the‬‏ ‏‮Performance‬‏ ‏‮score‬‏."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "‏‮Diagnostics‬‏"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "‏‮The‬‏ ‏‮most‬‏ ‏‮critical‬‏ ‏‮aspect‬‏ ‏‮of‬‏ ‏‮performance‬‏ ‏‮is‬‏ ‏‮how‬‏ ‏‮quickly‬‏ ‏‮pixels‬‏ ‏‮are‬‏ ‏‮rendered‬‏ ‏‮onscreen‬‏. ‏‮Key‬‏ ‏‮metrics‬‏: ‏‮First‬‏ ‏‮Contentful‬‏ ‏‮Paint‬‏, ‏‮First‬‏ ‏‮Meaningful‬‏ ‏‮Paint‬‏"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "‏‮First‬‏ ‏‮Paint‬‏ ‏‮Improvements‬‏"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "‏‮These‬‏ ‏‮suggestions‬‏ ‏‮can‬‏ ‏‮help‬‏ ‏‮your‬‏ ‏‮page‬‏ ‏‮load‬‏ ‏‮faster‬‏. ‏‮They‬‏ ‏‮don‬‏'‏‮t‬‏ [‏‮directly‬‏ ‏‮affect‬‏](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) ‏‮the‬‏ ‏‮Performance‬‏ ‏‮score‬‏."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "‏‮Opportunities‬‏"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "‏‮Metrics‬‏"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "‏‮Enhance‬‏ ‏‮the‬‏ ‏‮overall‬‏ ‏‮loading‬‏ ‏‮experience‬‏, ‏‮so‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮responsive‬‏ ‏‮and‬‏ ‏‮ready‬‏ ‏‮to‬‏ ‏‮use‬‏ ‏‮as‬‏ ‏‮soon‬‏ ‏‮as‬‏ ‏‮possible‬‏. ‏‮Key‬‏ ‏‮metrics‬‏: ‏‮Time‬‏ ‏‮to‬‏ ‏‮Interactive‬‏, ‏‮Speed‬‏ ‏‮Index‬‏"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "‏‮Overall‬‏ ‏‮Improvements‬‏"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "‏‮Performance‬‏"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "‏‮These‬‏ ‏‮checks‬‏ ‏‮validate‬‏ ‏‮the‬‏ ‏‮aspects‬‏ ‏‮of‬‏ ‏‮a‬‏ ‏‮Progressive‬‏ ‏‮Web‬‏ ‏‮App‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "‏‮These‬‏ ‏‮checks‬‏ ‏‮are‬‏ ‏‮required‬‏ ‏‮by‬‏ ‏‮the‬‏ ‏‮baseline‬‏ [‏‮PWA‬‏ ‏‮Checklist‬‏](https://developers.google.com/web/progressive-web-apps/checklist) ‏‮but‬‏ ‏‮are‬‏ ‏‮not‬‏ ‏‮automatically‬‏ ‏‮checked‬‏ ‏‮by‬‏ ‏‮Lighthouse‬‏. ‏‮They‬‏ ‏‮do‬‏ ‏‮not‬‏ ‏‮affect‬‏ ‏‮your‬‏ ‏‮score‬‏ ‏‮but‬‏ ‏‮it‬‏'‏‮s‬‏ ‏‮important‬‏ ‏‮that‬‏ ‏‮you‬‏ ‏‮verify‬‏ ‏‮them‬‏ ‏‮manually‬‏."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "‏‮Progressive‬‏ ‏‮Web‬‏ ‏‮App‬‏"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "‏‮Fast‬‏ ‏‮and‬‏ ‏‮reliable‬‏"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "‏‮Installable‬‏"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "‏‮PWA‬‏ ‏‮Optimized‬‏"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "‏‮These‬‏ ‏‮checks‬‏ ‏‮ensure‬‏ ‏‮that‬‏ ‏‮your‬‏ ‏‮page‬‏ ‏‮is‬‏ ‏‮optimized‬‏ ‏‮for‬‏ ‏‮search‬‏ ‏‮engine‬‏ ‏‮results‬‏ ‏‮ranking‬‏. ‏‮There‬‏ ‏‮are‬‏ ‏‮additional‬‏ ‏‮factors‬‏ ‏‮Lighthouse‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮check‬‏ ‏‮that‬‏ ‏‮may‬‏ ‏‮affect‬‏ ‏‮your‬‏ ‏‮search‬‏ ‏‮ranking‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "‏‮Run‬‏ ‏‮these‬‏ ‏‮additional‬‏ ‏‮validators‬‏ ‏‮on‬‏ ‏‮your‬‏ ‏‮site‬‏ ‏‮to‬‏ ‏‮check‬‏ ‏‮additional‬‏ ‏‮SEO‬‏ ‏‮best‬‏ ‏‮practices‬‏."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "‏‮SEO‬‏"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "‏‮Format‬‏ ‏‮your‬‏ ‏‮HTML‬‏ ‏‮in‬‏ ‏‮a‬‏ ‏‮way‬‏ ‏‮that‬‏ ‏‮enables‬‏ ‏‮crawlers‬‏ ‏‮to‬‏ ‏‮better‬‏ ‏‮understand‬‏ ‏‮your‬‏ ‏‮app‬‏’‏‮s‬‏ ‏‮content‬‏."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "‏‮Content‬‏ ‏‮Best‬‏ ‏‮Practices‬‏"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "‏‮To‬‏ ‏‮appear‬‏ ‏‮in‬‏ ‏‮search‬‏ ‏‮results‬‏, ‏‮crawlers‬‏ ‏‮need‬‏ ‏‮access‬‏ ‏‮to‬‏ ‏‮your‬‏ ‏‮app‬‏."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "‏‮Crawling‬‏ ‏‮and‬‏ ‏‮Indexing‬‏"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "‏‮Make‬‏ ‏‮sure‬‏ ‏‮your‬‏ ‏‮pages‬‏ ‏‮are‬‏ ‏‮mobile‬‏ ‏‮friendly‬‏ ‏‮so‬‏ ‏‮users‬‏ ‏‮don‬‏’‏‮t‬‏ ‏‮have‬‏ ‏‮to‬‏ ‏‮pinch‬‏ ‏‮or‬‏ ‏‮zoom‬‏ ‏‮in‬‏ ‏‮order‬‏ ‏‮to‬‏ ‏‮read‬‏ ‏‮the‬‏ ‏‮content‬‏ ‏‮pages‬‏. [‏‮Learn‬‏ ‏‮more‬‏](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "‏‮Mobile‬‏ ‏‮Friendly‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "‏‮Cache‬‏ ‏‮TTL‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "‏‮Location‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "‏‮Name‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "‏‮Requests‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "‏‮Resource‬‏ ‏‮Type‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "‏‮Size‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "‏‮Time‬‏ ‏‮Spent‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "‏‮Transfer‬‏ ‏‮Size‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "‏‮URL‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "‏‮Potential‬‏ ‏‮Savings‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "‏‮Potential‬‏ ‏‮Savings‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "‏‮Potential‬‏ ‏‮savings‬‏ ‏‮of‬‏ {wastedBytes, number, bytes} ‏‮KB‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "‏‮Potential‬‏ ‏‮savings‬‏ ‏‮of‬‏ {wastedMs, number, milliseconds} ‏‮ms‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "‏‮Document‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "‏‮Font‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "‏‮Image‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "‏‮Media‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ‏‮ms‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "‏‮Other‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "‏‮Script‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} ‏‮s‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "‏‮Stylesheet‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "‏‮Third‬‏-‏‮party‬‏"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "‏‮Total‬‏"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "‏‮Something‬‏ ‏‮went‬‏ ‏‮wrong‬‏ ‏‮with‬‏ ‏‮recording‬‏ ‏‮the‬‏ ‏‮trace‬‏ ‏‮over‬‏ ‏‮your‬‏ ‏‮page‬‏ ‏‮load‬‏. ‏‮Please‬‏ ‏‮run‬‏ ‏‮Lighthouse‬‏ ‏‮again‬‏. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "‏‮Timeout‬‏ ‏‮waiting‬‏ ‏‮for‬‏ ‏‮initial‬‏ ‏‮Debugger‬‏ ‏‮Protocol‬‏ ‏‮connection‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "‏‮Chrome‬‏ ‏‮didn‬‏'‏‮t‬‏ ‏‮collect‬‏ ‏‮any‬‏ ‏‮screenshots‬‏ ‏‮during‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮load‬‏. ‏‮Please‬‏ ‏‮make‬‏ ‏‮sure‬‏ ‏‮there‬‏ ‏‮is‬‏ ‏‮content‬‏ ‏‮visible‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏, ‏‮and‬‏ ‏‮then‬‏ ‏‮try‬‏ ‏‮re‬‏-‏‮running‬‏ ‏‮Lighthouse‬‏. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "‏‮DNS‬‏ ‏‮servers‬‏ ‏‮could‬‏ ‏‮not‬‏ ‏‮resolve‬‏ ‏‮the‬‏ ‏‮provided‬‏ ‏‮domain‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "‏‮Required‬‏ {artifactName} ‏‮gatherer‬‏ ‏‮encountered‬‏ ‏‮an‬‏ ‏‮error‬‏: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "‏‮An‬‏ ‏‮internal‬‏ ‏‮Chrome‬‏ ‏‮error‬‏ ‏‮occurred‬‏. ‏‮Please‬‏ ‏‮restart‬‏ ‏‮Chrome‬‏ ‏‮and‬‏ ‏‮try‬‏ ‏‮re‬‏-‏‮running‬‏ ‏‮Lighthouse‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "‏‮Required‬‏ {artifactName} ‏‮gatherer‬‏ ‏‮did‬‏ ‏‮not‬‏ ‏‮run‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮reliably‬‏ ‏‮load‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮you‬‏ ‏‮requested‬‏. ‏‮Make‬‏ ‏‮sure‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮testing‬‏ ‏‮the‬‏ ‏‮correct‬‏ ‏‮URL‬‏ ‏‮and‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮is‬‏ ‏‮properly‬‏ ‏‮responding‬‏ ‏‮to‬‏ ‏‮all‬‏ ‏‮requests‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮reliably‬‏ ‏‮load‬‏ ‏‮the‬‏ ‏‮URL‬‏ ‏‮you‬‏ ‏‮requested‬‏ ‏‮because‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮stopped‬‏ ‏‮responding‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "‏‮The‬‏ ‏‮URL‬‏ ‏‮you‬‏ ‏‮have‬‏ ‏‮provided‬‏ ‏‮does‬‏ ‏‮not‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮valid‬‏ ‏‮security‬‏ ‏‮certificate‬‏. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "‏‮Chrome‬‏ ‏‮prevented‬‏ ‏‮page‬‏ ‏‮load‬‏ ‏‮with‬‏ ‏‮an‬‏ ‏‮interstitial‬‏. ‏‮Make‬‏ ‏‮sure‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮testing‬‏ ‏‮the‬‏ ‏‮correct‬‏ ‏‮URL‬‏ ‏‮and‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮is‬‏ ‏‮properly‬‏ ‏‮responding‬‏ ‏‮to‬‏ ‏‮all‬‏ ‏‮requests‬‏."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮reliably‬‏ ‏‮load‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮you‬‏ ‏‮requested‬‏. ‏‮Make‬‏ ‏‮sure‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮testing‬‏ ‏‮the‬‏ ‏‮correct‬‏ ‏‮URL‬‏ ‏‮and‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮is‬‏ ‏‮properly‬‏ ‏‮responding‬‏ ‏‮to‬‏ ‏‮all‬‏ ‏‮requests‬‏. (‏‮Details‬‏: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "‏‮Lighthouse‬‏ ‏‮was‬‏ ‏‮unable‬‏ ‏‮to‬‏ ‏‮reliably‬‏ ‏‮load‬‏ ‏‮the‬‏ ‏‮page‬‏ ‏‮you‬‏ ‏‮requested‬‏. ‏‮Make‬‏ ‏‮sure‬‏ ‏‮you‬‏ ‏‮are‬‏ ‏‮testing‬‏ ‏‮the‬‏ ‏‮correct‬‏ ‏‮URL‬‏ ‏‮and‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮server‬‏ ‏‮is‬‏ ‏‮properly‬‏ ‏‮responding‬‏ ‏‮to‬‏ ‏‮all‬‏ ‏‮requests‬‏. (‏‮Status‬‏ ‏‮code‬‏: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "‏‮Your‬‏ ‏‮page‬‏ ‏‮took‬‏ ‏‮too‬‏ ‏‮long‬‏ ‏‮to‬‏ ‏‮load‬‏. ‏‮Please‬‏ ‏‮follow‬‏ ‏‮the‬‏ ‏‮opportunities‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮report‬‏ ‏‮to‬‏ ‏‮reduce‬‏ ‏‮your‬‏ ‏‮page‬‏ ‏‮load‬‏ ‏‮time‬‏, ‏‮and‬‏ ‏‮then‬‏ ‏‮try‬‏ ‏‮re‬‏-‏‮running‬‏ ‏‮Lighthouse‬‏. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "‏‮Waiting‬‏ ‏‮for‬‏ ‏‮DevTools‬‏ ‏‮protocol‬‏ ‏‮response‬‏ ‏‮has‬‏ ‏‮exceeded‬‏ ‏‮the‬‏ ‏‮allotted‬‏ ‏‮time‬‏. (‏‮Method‬‏: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "‏‮Fetching‬‏ ‏‮resource‬‏ ‏‮content‬‏ ‏‮has‬‏ ‏‮exceeded‬‏ ‏‮the‬‏ ‏‮allotted‬‏ ‏‮time‬‏"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "‏‮The‬‏ ‏‮URL‬‏ ‏‮you‬‏ ‏‮have‬‏ ‏‮provided‬‏ ‏‮appears‬‏ ‏‮to‬‏ ‏‮be‬‏ ‏‮invalid‬‏."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "‏‮Show‬‏ ‏‮audits‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "‏‮Initial‬‏ ‏‮Navigation‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "‏‮Maximum‬‏ ‏‮critical‬‏ ‏‮path‬‏ ‏‮latency‬‏:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "‏‮Error‬‏!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "‏‮Report‬‏ ‏‮error‬‏: ‏‮no‬‏ ‏‮audit‬‏ ‏‮information‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "‏‮Lab‬‏ ‏‮Data‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[‏‮Lighthouse‬‏](https://developers.google.com/web/tools/lighthouse/) ‏‮analysis‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮current‬‏ ‏‮page‬‏ ‏‮on‬‏ ‏‮an‬‏ ‏‮emulated‬‏ ‏‮mobile‬‏ ‏‮network‬‏. ‏‮Values‬‏ ‏‮are‬‏ ‏‮estimated‬‏ ‏‮and‬‏ ‏‮may‬‏ ‏‮vary‬‏."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "‏‮Additional‬‏ ‏‮items‬‏ ‏‮to‬‏ ‏‮manually‬‏ ‏‮check‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "‏‮Not‬‏ ‏‮applicable‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "‏‮Opportunity‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "‏‮Estimated‬‏ ‏‮Savings‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "‏‮Passed‬‏ ‏‮audits‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "‏‮Collapse‬‏ ‏‮snippet‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "‏‮Expand‬‏ ‏‮snippet‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "‏‮Show‬‏ 3‏‮rd‬‏-‏‮party‬‏ ‏‮resources‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "‏‮There‬‏ ‏‮were‬‏ ‏‮issues‬‏ ‏‮affecting‬‏ ‏‮this‬‏ ‏‮run‬‏ ‏‮of‬‏ ‏‮Lighthouse‬‏:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "‏‮Values‬‏ ‏‮are‬‏ ‏‮estimated‬‏ ‏‮and‬‏ ‏‮may‬‏ ‏‮vary‬‏. ‏‮The‬‏ ‏‮performance‬‏ ‏‮score‬‏ ‏‮is‬‏ [‏‮based‬‏ ‏‮only‬‏ ‏‮on‬‏ ‏‮these‬‏ ‏‮metrics‬‏](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "‏‮Passed‬‏ ‏‮audits‬‏ ‏‮but‬‏ ‏‮with‬‏ ‏‮warnings‬‏"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "‏‮Warnings‬‏: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "‏‮Consider‬‏ ‏‮uploading‬‏ ‏‮your‬‏ ‏‮GIF‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮service‬‏ ‏‮which‬‏ ‏‮will‬‏ ‏‮make‬‏ ‏‮it‬‏ ‏‮available‬‏ ‏‮to‬‏ ‏‮embed‬‏ ‏‮as‬‏ ‏‮an‬‏ ‏‮HTML‬‏5 ‏‮video‬‏."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "‏‮Install‬‏ ‏‮a‬‏ [‏‮lazy‬‏-‏‮load‬‏ ‏‮WordPress‬‏ ‏‮plugin‬‏](https://wordpress.org/plugins/search/lazy+load/) ‏‮that‬‏ ‏‮provides‬‏ ‏‮the‬‏ ‏‮ability‬‏ ‏‮to‬‏ ‏‮defer‬‏ ‏‮any‬‏ ‏‮offscreen‬‏ ‏‮images‬‏, ‏‮or‬‏ ‏‮switch‬‏ ‏‮to‬‏ ‏‮a‬‏ ‏‮theme‬‏ ‏‮that‬‏ ‏‮provides‬‏ ‏‮that‬‏ ‏‮functionality‬‏. ‏‮Also‬‏ ‏‮consider‬‏ ‏‮using‬‏ [‏‮the‬‏ ‏‮AMP‬‏ ‏‮plugin‬‏](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "‏‮There‬‏ ‏‮are‬‏ ‏‮a‬‏ ‏‮number‬‏ ‏‮of‬‏ ‏‮WordPress‬‏ ‏‮plugins‬‏ ‏‮that‬‏ ‏‮can‬‏ ‏‮help‬‏ ‏‮you‬‏ [‏‮inline‬‏ ‏‮critical‬‏ ‏‮assets‬‏](https://wordpress.org/plugins/search/critical+css/) ‏‮or‬‏ [‏‮defer‬‏ ‏‮less‬‏ ‏‮important‬‏ ‏‮resources‬‏](https://wordpress.org/plugins/search/defer+css+javascript/). ‏‮Beware‬‏ ‏‮that‬‏ ‏‮optimizations‬‏ ‏‮provided‬‏ ‏‮by‬‏ ‏‮these‬‏ ‏‮plugins‬‏ ‏‮may‬‏ ‏‮break‬‏ ‏‮features‬‏ ‏‮of‬‏ ‏‮your‬‏ ‏‮theme‬‏ ‏‮or‬‏ ‏‮plugins‬‏, ‏‮so‬‏ ‏‮you‬‏ ‏‮will‬‏ ‏‮likely‬‏ ‏‮need‬‏ ‏‮to‬‏ ‏‮make‬‏ ‏‮code‬‏ ‏‮changes‬‏."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "‏‮Themes‬‏, ‏‮plugins‬‏, ‏‮and‬‏ ‏‮server‬‏ ‏‮specifications‬‏ ‏‮all‬‏ ‏‮contribute‬‏ ‏‮to‬‏ ‏‮server‬‏ ‏‮response‬‏ ‏‮time‬‏. ‏‮Consider‬‏ ‏‮finding‬‏ ‏‮a‬‏ ‏‮more‬‏ ‏‮optimized‬‏ ‏‮theme‬‏, ‏‮carefully‬‏ ‏‮selecting‬‏ ‏‮an‬‏ ‏‮optimization‬‏ ‏‮plugin‬‏, ‏‮and‬‏/‏‮or‬‏ ‏‮upgrading‬‏ ‏‮your‬‏ ‏‮server‬‏."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "‏‮Consider‬‏ ‏‮showing‬‏ ‏‮excerpts‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮post‬‏ ‏‮lists‬‏ (‏‮e‬‏.‏‮g‬‏. ‏‮via‬‏ ‏‮the‬‏ ‏‮more‬‏ ‏‮tag‬‏), ‏‮reducing‬‏ ‏‮the‬‏ ‏‮number‬‏ ‏‮of‬‏ ‏‮posts‬‏ ‏‮shown‬‏ ‏‮on‬‏ ‏‮a‬‏ ‏‮given‬‏ ‏‮page‬‏, ‏‮breaking‬‏ ‏‮your‬‏ ‏‮long‬‏ ‏‮posts‬‏ ‏‮into‬‏ ‏‮multiple‬‏ ‏‮pages‬‏, ‏‮or‬‏ ‏‮using‬‏ ‏‮a‬‏ ‏‮plugin‬‏ ‏‮to‬‏ ‏‮lazy‬‏-‏‮load‬‏ ‏‮comments‬‏."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "‏‮A‬‏ ‏‮number‬‏ ‏‮of‬‏ [‏‮WordPress‬‏ ‏‮plugins‬‏](https://wordpress.org/plugins/search/minify+css/) ‏‮can‬‏ ‏‮speed‬‏ ‏‮up‬‏ ‏‮your‬‏ ‏‮site‬‏ ‏‮by‬‏ ‏‮concatenating‬‏, ‏‮minifying‬‏, ‏‮and‬‏ ‏‮compressing‬‏ ‏‮your‬‏ ‏‮styles‬‏. ‏‮You‬‏ ‏‮may‬‏ ‏‮also‬‏ ‏‮want‬‏ ‏‮to‬‏ ‏‮use‬‏ ‏‮a‬‏ ‏‮build‬‏ ‏‮process‬‏ ‏‮to‬‏ ‏‮do‬‏ ‏‮this‬‏ ‏‮minification‬‏ ‏‮up‬‏-‏‮front‬‏ ‏‮if‬‏ ‏‮possible‬‏."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "‏‮A‬‏ ‏‮number‬‏ ‏‮of‬‏ [‏‮WordPress‬‏ ‏‮plugins‬‏](https://wordpress.org/plugins/search/minify+javascript/) ‏‮can‬‏ ‏‮speed‬‏ ‏‮up‬‏ ‏‮your‬‏ ‏‮site‬‏ ‏‮by‬‏ ‏‮concatenating‬‏, ‏‮minifying‬‏, ‏‮and‬‏ ‏‮compressing‬‏ ‏‮your‬‏ ‏‮scripts‬‏. ‏‮You‬‏ ‏‮may‬‏ ‏‮also‬‏ ‏‮want‬‏ ‏‮to‬‏ ‏‮use‬‏ ‏‮a‬‏ ‏‮build‬‏ ‏‮process‬‏ ‏‮to‬‏ ‏‮do‬‏ ‏‮this‬‏ ‏‮minification‬‏ ‏‮up‬‏ ‏‮front‬‏ ‏‮if‬‏ ‏‮possible‬‏."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "‏‮Consider‬‏ ‏‮reducing‬‏, ‏‮or‬‏ ‏‮switching‬‏, ‏‮the‬‏ ‏‮number‬‏ ‏‮of‬‏ [‏‮WordPress‬‏ ‏‮plugins‬‏](https://wordpress.org/plugins/) ‏‮loading‬‏ ‏‮unused‬‏ ‏‮CSS‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮page‬‏. ‏‮To‬‏ ‏‮identify‬‏ ‏‮plugins‬‏ ‏‮that‬‏ ‏‮are‬‏ ‏‮adding‬‏ ‏‮extraneous‬‏ ‏‮CSS‬‏, ‏‮try‬‏ ‏‮running‬‏ [‏‮code‬‏ ‏‮coverage‬‏](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ‏‮in‬‏ ‏‮Chrome‬‏ ‏‮DevTools‬‏. ‏‮You‬‏ ‏‮can‬‏ ‏‮identify‬‏ ‏‮the‬‏ ‏‮theme‬‏/‏‮plugin‬‏ ‏‮responsible‬‏ ‏‮from‬‏ ‏‮the‬‏ ‏‮URL‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮stylesheet‬‏. ‏‮Look‬‏ ‏‮out‬‏ ‏‮for‬‏ ‏‮plugins‬‏ ‏‮that‬‏ ‏‮have‬‏ ‏‮many‬‏ ‏‮stylesheets‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮list‬‏ ‏‮which‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮lot‬‏ ‏‮of‬‏ ‏‮red‬‏ ‏‮in‬‏ ‏‮code‬‏ ‏‮coverage‬‏. ‏‮A‬‏ ‏‮plugin‬‏ ‏‮should‬‏ ‏‮only‬‏ ‏‮enqueue‬‏ ‏‮a‬‏ ‏‮stylesheet‬‏ ‏‮if‬‏ ‏‮it‬‏ ‏‮is‬‏ ‏‮actually‬‏ ‏‮used‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "‏‮Consider‬‏ ‏‮reducing‬‏, ‏‮or‬‏ ‏‮switching‬‏, ‏‮the‬‏ ‏‮number‬‏ ‏‮of‬‏ [‏‮WordPress‬‏ ‏‮plugins‬‏](https://wordpress.org/plugins/) ‏‮loading‬‏ ‏‮unused‬‏ ‏‮JavaScript‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮page‬‏. ‏‮To‬‏ ‏‮identify‬‏ ‏‮plugins‬‏ ‏‮that‬‏ ‏‮are‬‏ ‏‮adding‬‏ ‏‮extraneous‬‏ ‏‮JS‬‏, ‏‮try‬‏ ‏‮running‬‏ [‏‮code‬‏ ‏‮coverage‬‏](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ‏‮in‬‏ ‏‮Chrome‬‏ ‏‮DevTools‬‏. ‏‮You‬‏ ‏‮can‬‏ ‏‮identify‬‏ ‏‮the‬‏ ‏‮theme‬‏/‏‮plugin‬‏ ‏‮responsible‬‏ ‏‮from‬‏ ‏‮the‬‏ ‏‮URL‬‏ ‏‮of‬‏ ‏‮the‬‏ ‏‮script‬‏. ‏‮Look‬‏ ‏‮out‬‏ ‏‮for‬‏ ‏‮plugins‬‏ ‏‮that‬‏ ‏‮have‬‏ ‏‮many‬‏ ‏‮scripts‬‏ ‏‮in‬‏ ‏‮the‬‏ ‏‮list‬‏ ‏‮which‬‏ ‏‮have‬‏ ‏‮a‬‏ ‏‮lot‬‏ ‏‮of‬‏ ‏‮red‬‏ ‏‮in‬‏ ‏‮code‬‏ ‏‮coverage‬‏. ‏‮A‬‏ ‏‮plugin‬‏ ‏‮should‬‏ ‏‮only‬‏ ‏‮enqueue‬‏ ‏‮a‬‏ ‏‮script‬‏ ‏‮if‬‏ ‏‮it‬‏ ‏‮is‬‏ ‏‮actually‬‏ ‏‮used‬‏ ‏‮on‬‏ ‏‮the‬‏ ‏‮page‬‏."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "‏‮Read‬‏ ‏‮about‬‏ [‏‮Browser‬‏ ‏‮Caching‬‏ ‏‮in‬‏ ‏‮WordPress‬‏](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "‏‮Consider‬‏ ‏‮using‬‏ ‏‮an‬‏ [‏‮image‬‏ ‏‮optimization‬‏ ‏‮WordPress‬‏ ‏‮plugin‬‏](https://wordpress.org/plugins/search/optimize+images/) ‏‮that‬‏ ‏‮compresses‬‏ ‏‮your‬‏ ‏‮images‬‏ ‏‮while‬‏ ‏‮retaining‬‏ ‏‮quality‬‏."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "‏‮Upload‬‏ ‏‮images‬‏ ‏‮directly‬‏ ‏‮through‬‏ ‏‮the‬‏ [‏‮media‬‏ ‏‮library‬‏](https://codex.wordpress.org/Media_Library_Screen) ‏‮to‬‏ ‏‮ensure‬‏ ‏‮that‬‏ ‏‮the‬‏ ‏‮required‬‏ ‏‮image‬‏ ‏‮sizes‬‏ ‏‮are‬‏ ‏‮available‬‏, ‏‮and‬‏ ‏‮then‬‏ ‏‮insert‬‏ ‏‮them‬‏ ‏‮from‬‏ ‏‮the‬‏ ‏‮media‬‏ ‏‮library‬‏ ‏‮or‬‏ ‏‮use‬‏ ‏‮the‬‏ ‏‮image‬‏ ‏‮widget‬‏ ‏‮to‬‏ ‏‮ensure‬‏ ‏‮the‬‏ ‏‮optimal‬‏ ‏‮image‬‏ ‏‮sizes‬‏ ‏‮are‬‏ ‏‮used‬‏ (‏‮including‬‏ ‏‮those‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮responsive‬‏ ‏‮breakpoints‬‏). ‏‮Avoid‬‏ ‏‮using‬‏ `Full Size` ‏‮images‬‏ ‏‮unless‬‏ ‏‮the‬‏ ‏‮dimensions‬‏ ‏‮are‬‏ ‏‮adequate‬‏ ‏‮for‬‏ ‏‮their‬‏ ‏‮usage‬‏. [‏‮Learn‬‏ ‏‮More‬‏](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "‏‮You‬‏ ‏‮can‬‏ ‏‮enable‬‏ ‏‮text‬‏ ‏‮compression‬‏ ‏‮in‬‏ ‏‮your‬‏ ‏‮web‬‏ ‏‮server‬‏ ‏‮configuration‬‏."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "‏‮Consider‬‏ ‏‮using‬‏ ‏‮a‬‏ [‏‮plugin‬‏](https://wordpress.org/plugins/search/convert+webp/) ‏‮or‬‏ ‏‮service‬‏ ‏‮that‬‏ ‏‮will‬‏ ‏‮automatically‬‏ ‏‮convert‬‏ ‏‮your‬‏ ‏‮uploaded‬‏ ‏‮images‬‏ ‏‮to‬‏ ‏‮the‬‏ ‏‮optimal‬‏ ‏‮formats‬‏."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar.json
new file mode 100644
index 00000000000..1b7d16c1567
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ar.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "تتيح مفاتيح الوصول للمستخدمين التركيز بسرعة على جزء من الصفحة. للانتقال إلى الموضع الصحيح من الصفحة، يجب أن يكون كل مفتاح وصول فريدًا. [مزيد من المعلومات](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "قيم `[accesskey]` هي غير فريدة"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "قيم `[accesskey]` فريدة"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "يوفّر كل دور ARIA `role` مجموعة فرعية محددة من سمات `aria-*`. يؤدي عدم تطابق هذه الأدوار إلى إبطال السمات `aria-*`. [مزيد من المعلومات](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "سمات `[aria-*]` لا تتطابق مع أدوارها"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "سمات `[aria-*]` هي مطابقة لأدوارها"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "تتطلّب بعض أدوار ARIA تزويد برامج قراءة الشاشة بسمات تصف حالة العنصر. [مزيد من المعلومات](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` لا تحتوي على جميع سمات`[aria-*]` المطلوبة"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` تحتوي على جميع سمات `[aria-*]` المطلوبة"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "يجب أن تحتوي بعض أدوار ARIA الرئيسية على أدوار ثانوية محدّدة لأداء وظائف إمكانية الوصول المقصودة. [مزيد من المعلومات](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "العناصر التي تتضمن ARIA `[role]` والتي تتطلب عناصر ثانوية للاحتواء على `[role]` محدد تفقد بعض هذه العناصر الثانوية المطلوبة أو جميعها."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "العناصر التي تتضمن ARIA `[role]` والتي تتطلب عناصر ثانوية للاحتواء على `[role]` محدد تشتمل على جميع العناصر الثانوية المطلوبة."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "يجب أن يتم تضمين بعض أدوار ثانوية ARIA ضمن أدوار رئيسية محدّدة لتنفيذ وظائف إمكانية الوصول المقصودة بشكل صحيح. [مزيد من المعلومات](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` غير مضمّنة في العنصر الرئيسي المطلوب"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` مضمّنة في العنصر الرئيسي المطلوب"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "يجب أن تحتوي أدوار ARIA على قيم صالحة لتنفيذ وظائف إمكانية الوصول المقصودة. [مزيد من المعلومات](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "قيم `[role]` هي غير صالحة"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "قيم `[role]` هي صالحة"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "لا يمكن لتقنيات المساعدة، مثل برامج قراءة الشاشة، تفسير سمات ARIA باستخدام قيم غير صحيحة. [مزيد من المعلومات](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "سمات `[aria-*]` لا تحتوي على قيم صحيحة"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "سمات `[aria-*]` تحتوي على قيم صالحة"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "لا يمكن لتقنيات المساعدة، مثل برامج قراءة الشاشة، تفسير سمات ARIA بأسماء غير صحيحة. [مزيد من المعلومات](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "سمات `[aria-*]` هي غير صالحة أو بها أخطاء إملائية"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "سمات `[aria-*]` هي صالحة وليس بها أخطاء إملائية"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "تجعل مقاطع الشرح العناصر الصوتية قابلة للاستخدام للمستخدمين الصُم أو الذين يعانون من إعاقة سمعية، ما يوفّر معلومات مهمة، مثل الشخص المتحدث والحوار الذي يدور ومعلومات أخرى بخلاف الكلام. [مزيد من المعلومات](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "عناصر `<audio>` لا تتضمّن عنصر `<track>` مع `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "العناصر `<audio>` تحتوي على عنصر `<track>` مع `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "العناصر التي رسبت في عملية التدقيق"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "عند عدم احتواء زر على اسم يمكن الوصول إليه، تعلن برامج قراءة الشاشة بأنه \"زر\"، ما يجعله غير قابل للاستخدام بالنسبة إلى المستخدمين الذين يعتمدون على برامج قراءة الشاشة. [مزيد من المعلومات](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "عدم احتواء الأزرار على اسم يمكن الوصول إليه"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "احتواء الأزرار على اسم الوصول"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "تؤدي إضافة طرق لتخطي المحتوى المكرّر إلى السماح لمستخدمي لوحة المفاتيح بالتنقل في الصفحة بكفاءة أكبر. [مزيد من المعلومات](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "عدم احتواء الصفحة على عنوان أو رابط تخطٍ أو منطقة معالم"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "احتواء الصفحة على عنوان أو رابط تخطٍ أو منطقة معالم"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "إنّ عملية قراءة النص المنخفض التباين تُعتبر صعبة أو مستحيلة بالنسبة إلى العديد من المستخدمين. [مزيد من المعلومات](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "عدم احتواء الخلفية وألوان الخلفية على نسبة تباين كافية"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "تمييز الخلفية والألوان الخلفية بنسبة تباين كافية"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "عندما لا يتم ترميز قوائم التعريفات بشكل صحيح، قد تقدم برامج قراءة الشاشة نتائج غير واضحة أو غير دقيقة. [مزيد من المعلومات](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` لا تحتوي على مجموعات `<dt>` و`<dd>` المرتبة بشكلٍ صحيح فقط، أو العناصر `<script>` أو `<template>`"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` تحتوي على مجموعات `<dt>` و`<dd>` المرتبة بشكلٍ صحيح فقط، أو العناصر `<script>` أو `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "يجب إدراج عناصر قائمة التعريفات (`<dt>` و`<dd>`) في عنصر رئيسي `<dl>` وذلك لضمان إعلان برامج قراءة الشاشة عنها بشكل صحيح. [مزيد من المعلومات](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "عناصر قائمة التعريفات غير مضّمنة في عناصر `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "عناصر قائمة التعريفات مضمّنة في عناصر `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "يمنح العنوان مستخدمي برامج قراءة الشاشة نظرة عامة حول الصفحة، ويعتمد مستخدمو محرك البحث على هذا بشكل كبير لتحديد ما إذا كانت الصفحة ذات صلة ببحثهم أو لا. [مزيد من المعلومات](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "المستند لا يحتوي على عنصر `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "المستند يحتوي على عنصر `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "يجب أن تكون قيمة سمة رقم التعريف فريدة لكي لا تتغاضى تقنيات المساعدة عن الأمثلة الأخرى. [مزيد من المعلومات](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "سمات `[id]` في الصفحة هي غير فريدة"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "سمات `[id]` في الصفحة هي فريدة"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "يعتمد مستخدمو برامج قراءة الشاشة على عناوين الإطارات لوصف محتوى الإطارات. [مزيد من المعلومات](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "عناصر `<frame>` أو `<iframe>` لا تحتوي على عنوان"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "عناصر `<frame>` أو `<iframe>` تحتوي على عنوان"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "في حال لم تحدّد الصفحة سمة اللغة، يفترض قارئ الشاشة أن تكون الصفحة باللغة التلقائية التي اختارها المستخدم عند إعداد قارئ الشاشة. في حال لم تكن الصفحة باللغة التلقائية، قد لا يُعلِن قارئ الشاشة عن نص الصفحة بشكل صحيح. [مزيد من المعلومات](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "العنصر `<html>` لا يحتوي على سمة `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "عنصر `<html>` يحتوي على سمة `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "يؤدي تحديد [لغة BCP 47 ](https://www.w3.org/International/questions/qa-choosing-language-tags#question) صحيحة إلى مساعدة برامج قراءة الشاشة على الإعلان عن النص بشكلٍ صحيح. [مزيد من المعلومات](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "العنصر `<html>` لا يحتوي على قيمة صالحة للسمة `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "عنصر `<html>` يحتوي على قيمة صحيحة لسمة `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "يجب أن تهدف العناصر الإعلامية إلى نص وصفي بديل وقصير. يمكن تجاهل العناصر الزخرفية بسمة النص البديل الفارغة. [مزيد من المعلومات](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "عناصر الصور لا تحتوي على سمات `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "عناصر الصور تحتوي على سمات `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "عند استخدام صورة كزر `<input>`، يمكن أن يساعد توفير نص بديل مستخدمي قارئ الشاشة على فهم الغرض من الزر. [مزيد من المعلومات](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "عناصر `<input type=\"image\">` لا تحتوي على نص `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "عناصر `<input type=\"image\">` تحتوي على نص `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "تضمن التصنيفات الإعلان عن عناصر التحكّم بالنموذج بشكل صحيح من خلال التقنيات المساعدة، مثل برامج قراءة الشاشة. [مزيد من المعلومات](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "عدم احتواء عناصر النموذج على تصنيفات مرتبطة"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "احتواء عناصر النموذج على التصنيفات المرتبطة"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "يجب ألا يشتمل الجدول المُستخدم لأغراض التنسيق على عناصر البيانات، مثل عناصر الشرح أو سمة الملخّص، لأن ذلك يمكن أن ينشئ تجربة محيرة لمستخدمي برامج قراءة الشاشة. [مزيد من المعلومات](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "لا تتجنّب عناصر `<table>` للعرض التقديمي استخدام `<th>` أو `<caption>` أو السمة `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "تتجنّب عناصر `<table>` للعرض التقديمي استخدام `<th>` أو `<caption>` أو السمة `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "إنّ نص الرابط (والنص البديل للصور، عند استخدامه كروابط) الذي يُعد مميّزًا وفريدًا وقابلاً للتركيز يحسّن تجربة التنقل لمستخدمي برامج قراءة الشاشة. [مزيد من المعلومات](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "عدم احتواء الروابط على اسم مميّز"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "احتواء الروابط على اسم مميز"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "تعتمد برامج قراءة الشاشة على طريقة محدّدة للإعلان عن القوائم. يؤدي ضمان بنية القائمة المناسبة إلى المساعدة على الاستماع إلى قارئ الشاشة. [مزيد من المعلومات](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "القوائم لا تحتوي على عناصر `<li>` وعناصر دعم النص البرمجي (`<script>` و`<template>`) فقط."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "القوائم تحتوي على عناصر `<li>` وعناصر دعم النص البرمجي (`<script>` و`<template>`) فقط."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "تتطلّب برامج قراءة الشاشة عناصر قائمة (`<li>`) يجب تضمينها في عنصر رئيسي `<ul>` أو `<ol>` حتى يتم الإعلان عنها بشكلٍ صحيح. [مزيد من المعلومات](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "عناصر القائمة (`<li>`) غير مضمّنة في العناصر الرئيسية `<ul>` أو `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "عناصر القائمة (`<li>`) مُضمَّنة في العناصر الرئيسية `<ul>` أو `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "لا يتوقع المستخدمون إعادة تحميل الصفحة تلقائيًا. وإذا تمت إعادة التحميل التلقائية، سيتحوّل تركيز المستخدمين إلى أعلى الصفحة. وقد ينشأ عن ذلك تجربة محبطة ومربكة. [مزيد من المعلومات](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "المستند يستخدم `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "المستند لا يستخدم `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "يسبب إيقاف ميزة التكبير/التصغير مشكلة بالنسبة إلى المستخدمين ضعاف البصر الذين يعتمدون على ميزة تكبير الشاشة لرؤية محتوى صفحة الويب بشكل صحيح. [مزيد من المعلومات](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "يتم استخدام `[user-scalable=\"no\"]` في العنصر `<meta name=\"viewport\">` أو السمة `[maximum-scale]` هي أقل من 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` غير مستخدم في العنصر `<meta name=\"viewport\">` والسمة `[maximum-scale]` لا تقلّ عن 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "لا يمكن لبرامج قراءة الشاشة ترجمة المحتوى غير النصي. تؤدي إضافة نص بديل إلى عناصر `<object>` إلى مساعدة برامج قراءة الشاشة على نقل المعنى إلى المستخدمين. [مزيد من المعلومات](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "عناصر `<object>` لا تحتوي على نص `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "عناصر `<object>` تحتوي على نص `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "تشير القيمة الأكبر من 0 إلى وجود طلب تنقل صريح. على الرغم من أن ذلك صحيح تقنيًّا، غالبًا ما يؤدي ذلك إلى إنشاء تجارب محبطة للمستخدمين الذين يعتمدون على التقنيات المساعدة. [مزيد من المعلومات](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "بعض العناصر تحتوي على قيمة `[tabindex]` أكبر من 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "لا يتوفّر عنصر له قيمة `[tabindex]` أكبر من 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "تحتوي برامج قراءة الشاشة على ميزات لتسهيل التنقل بين الجداول. يمكن تحسين تجربة استخدام برامج قراءة الشاشة من خلال ضمان إشارة الخلايا `<td>` التي تستخدم السمة `[headers]` إلى خلايا أخرى في الجدول نفسه فقط. [مزيد من المعلومات](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "الخلايا الواردة في عنصر `<table>` التي تستخدم السمة `[headers]` تشير إلى عنصر `id` لم يتم العثور عليه في الجدول نفسه."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "الخلايا الواردة في عنصر `<table>` التي تستخدم السمة `[headers]` تشير إلى خلايا الجدول في الجدول نفسه."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "تحتوي برامج قراءة الشاشة على ميزات لتسهيل التنقل بين الجداول. قد يؤدي ضمان أن عناوين الجداول تشير دائمًا إلى بعض مجموعات الخلايا إلى تحسين تجربة مستخدمي برامج قراءة الشاشة. [مزيد من المعلومات](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "عناصر `<th>` وعناصر `[role=\"columnheader\"/\"rowheader\"]` لا تحتوي على خلايا البيانات التي يتم وصفها."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "عناصر `<th>` وعناصر `[role=\"columnheader\"/\"rowheader\"]` تحتوي على خلايا البيانات التي يتم وصفها"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "يؤدي تحديد [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) صحيحة على العناصر إلى مساعدة قارئ الشاشة على نطق النص بشكلٍ صحيح. [مزيد من المعلومات](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "سمات `[lang]` لا تحتوي على قيمة صالحة"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "سمات `[lang]` تحتوي على قيمة صالحة"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "عندما يقدم الفيديو شرحًا، يَسهُل على المستخدمين الصُم والذين يعانون من إعاقة سمعية فهم مضمونه. [مزيد من المعلومات](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "عناصر `<video>` لا تحتوي على عنصر `<track>` مع `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "العناصر `<video>` تحتوي على عنصر `<track>` مع `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "توفّر الأوصاف الصوتية معلومات ذات صلة للفيديوهات التي لا يمكن إجراء الحوار بها، مثل تعبيرات الوجه وأجواء الإضاءة. [مزيد من المعلومات](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "عناصر `<video>` لا تحتوي على عنصر `<track>` مع `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "العناصر `<video>` تحتوي على عنصر `<track>` مع `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "للحصول على المظهر المثالي على نظام التشغيل iOS عند إضافة المستخدمين تطبيق ويب تقدّمي إلى الشاشة الرئيسية، يمكنك تحديد `apple-touch-icon`. يجب أن تشير هذه السمة إلى مربع غير شفاف بتنسيق PNG مقاسه 192 بكسل (أو 180 بكسل). [مزيد من المعلومات](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "لا يتم تقديم رمز `apple-touch-icon` صالح"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "سمة `apple-touch-icon-precomposed` هي قديمة، ويُفضّل استخدام سمة `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "يتم تقديم رمز `apple-touch-icon` صالح"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "أثّرت \"إضافات Chrome\" بشكلٍ سلبي في أداء التحميل لهذه الصفحة. ويمكنك تجربة تدقيق الصفحة في وضع التصفُّح المُتخفّي أو من ملف شخصي على Chrome بدون الإضافات."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "تقييم النص البرمجي"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "تحليل النص البرمجي"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "الوقت الإجمالي لوحدة المعالجة المركزية"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "يمكنك تقليل الوقت المستغرق في تحليل جافا سكريبت وإنشائها وتنفيذها. قد يتبين لك أن تسليم أحمال جافا سكريبت بحجم أصغر يساعد على ذلك. [مزيد من المعلومات](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "تقليل وقت تنفيذ جافا سكريبت"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "وقت تنفيذ جافا سكريبت"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "ملفات GIF الكبيرة غير كافية لعرض محتوى صور متحركة. يمكنك استخدام فيديوهات MPEG4/WebM للصور المتحركة وملفات PNG/WebP للصور الثابتة بدلاً من ملف GIF لحفظ وحدات البايت للشبكة. [مزيد من المعلومات](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "استخدام تنسيقات الفيديو لمحتوى الصور المتحركة"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "يمكنك إجراء تحميل بطيء للصور الموجودة خارج الشاشة والصور المخفية بعد الانتهاء من تحميل جميع الموارد المهمة من أجل تقليص وقت التفاعل. [مزيد من المعلومات](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "تأجيل الصور خارج الشاشة"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "تحظر الموارد سرعة عرض الصفحة لصفحتك. ويمكنك تضمين عناصر جافا سكريبت/CSS المهمة وتأجيل جميع الأنماط/عناصر جافا سكريبت غير المهمة. [مزيد من المعلومات](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "استبعاد موارد حظر العرض"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "تُكلِّف أحمال الشبكة الكبيرة المستخدمين الكثير من الأموال وترتبط مباشرةً بأوقات التحميل الطويلة. [مزيد من المعلومات](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "كان إجمالي الحجم {totalBytes, number, bytes} كيلوبايت."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "تجنُّب الأحمال الضخمة للشبكة"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "تجنُّب الأحمال الضخمة للشبكة"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "يمكن أن يؤدي تصغير ملفات CSS إلى تقليل أحجام حمولة الشبكة. [مزيد من المعلومات](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "تصغير CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "يمكن أن يؤدي تصغير ملفات جافا سكريبت إلى تقليل أحجام الأحمال ووقت تحليل النص البرمجي. [مزيد من المعلومات](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "تصغير جافا سكريبت"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "يمكنك إزالة القواعد الضارة من أوراق الأنماط وتأجيل تحميل خدمة CSS غير المستخدمة في محتوى الجزء المرئي من الصفحة للحد من وحدات البايت غير الضرورية المستهلكة من خلال نشاط الشبكة. [مزيد من المعلومات](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "إزالة خدمة CSS غير المُستخدَمة"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "يمكنك إزالة جافا سكريبت غير المُستخدَم لتقليل وحدات البايت التي يستهلكها نشاط الشبكة."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "إزالة جافا سكريبت غير المستخدم"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "يمكن لفترة التخزين المؤقت الطويلة تسريع عملية تكرار الزيارات إلى صفحتك. [مزيد من المعلومات](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم العثور على مورد واحد}zero{تم العثور على # مورد}two{تم العثور على مورديْنِ (#)}few{تم العثور على # موارد}many{تم العثور على # موردًا}other{تم العثور على # مورد}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "عرض الأصول الثابتة من خلال سياسة ذاكرة التخزين المؤقت الفعالة"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "استخدام سياسة ذاكرة التخزين المؤقت الفعالة على الأصول الثابتة"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "يتم تحميل الصور المحسَّنة بشكلٍ أسرع وتستهلك بيانات أقل لشبكة الجوّال. [مزيد من المعلومات](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "تشفير الصور بكفاءة"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "يمكنك عرض صور بحجم مناسب لحفظ بيانات شبكة الجوّال وتحسين وقت التحميل. [مزيد من المعلومات](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "الصور ذات الحجم المناسب"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "يجب عرض الموارد المستندة إلى النص باستخدام الضغط (gzip أو الانكماش أو brotli) لتقليل إجمالي وحدات البايت للشبكة. [مزيد من المعلومات](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "تفعيل ضغط النص"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "غالبًا ما توفِّر تنسيقات الصور، مثل JPEG 2000 وJPEG XR وWebP، ضغطًا أفضل من تنسيق PNG أو JPEG، وهذا يعني تنزيلاً أسرع واستهلاكًا أقل للبيانات. [مزيد من المعلومات](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "عرض الصور بتنسيقات الجيل القادم"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "في حال كان عرض محتوى التطبيق لا يتطابق مع عرض إطار العرض، قد لا يتم تحسين تطبيقك لشاشات الجوّال. [مزيد من المعلومات](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "لا يتطابق حجم إطار العرض {innerWidth} بكسل مع حجم النافذة {outerWidth} بكسل."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "عدم تحديد حجم المحتوى بشكلٍ صحيح لإطار العرض"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "تحديد حجم المحتوى بشكلٍ صحيح لإطار العرض"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "توضح لك \"سلاسل الطلبات المهمة\" أدناه الموارد التي تم تحميلها بأولوية عالية. ويمكنك تقليل طول السلاسل أو تقليل حجم تنزيل الموارد أو تأجيل تنزيل الموارد غير الضرورية لتحسين تحميل الصفحة. [مزيد من المعلومات](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم العثور على سلسلة واحدة}zero{تم العثور على # سلسلة}two{تم العثور على سلسلتيْنِ (#)}few{تم العثور على # سلاسل}many{تم العثور على # سلسلةً}other{تم العثور على # سلسلة}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "تقليل عمق الطلبات المهمة"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "إيقاف / تحذير"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "السطر"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "ستتم في النهاية إزالة واجهات برمجة التطبيقات المتوقفة من المتصفح. [مزيد من المعلومات](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم العثور على تحذير واحد}zero{تم العثور على # تحذير}two{تم العثور على تحذيرين (#)}few{تم العثور على # تحذيرات}many{تم العثور على # تحذيرًا}other{تم العثور على # تحذير}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "يتم استخدام واجهات برمجة التطبيقات المتوقفة"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "يتم تجنّب واجهات برمجة التطبيقات المتوقفة"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "تم إيقاف ذاكرة التخزين المؤقت للتطبيق. [مزيد من المعلومات](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "تم العثور على \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "يتم استخدام ذاكرة التخزين المؤقت للتطبيق"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "يتم تجنُب ذاكرة التخزين المؤقت للتطبيق"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "يؤدي تحديد doctype إلى منع المتصفح من التبديل إلى وضع Quirks. [مزيد من المعلومات](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "يجب أن يكون اسم DOCTYPE هو سلسلة الأحرف الصغيرة `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "يجب أن يحتوي المستند على DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "من الممكن أن تكون publicId المتوقعة سلسلة فارغة"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "من الممكن أن تكون systemId المتوقعة سلسلة فارغة"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "تفتقر الصفحة إلى HTML DOCTYPE، مما يؤدي إلى تشغيل وضع Quirks"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "الصفحة تحتوي على HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "العنصر"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "الإحصائية"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "القيمة"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "ينصح مهندسو المتصفّح بأن تحتوي الصفحات على أقل من 1500 عنصر DOM تقريبًا. من المفضّل أن يقلّ عمق الشجرة عن 32 عنصرًا وألّا يزيد عن 60 عنصرًا فرعيًا/رئيسيًا. يمكن أن يزيد حجم DOM الكبير من استخدام الذاكرة، ويتسبب في إجراء [حسابات نمطية](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) أطول، وينتج عنه [عمليات مُكلفة لإعادة عرض التنسيق](https://developers.google.com/speed/articles/reflow). [مزيد من المعلومات](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{عنصر واحد}zero{# عنصر}two{عنصرين (#)}few{# عناصر}many{# عنصرًا}other{# عنصر}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "تجنُب حجم DOM الزائد"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "الحد الأقصى لعمق DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "إجمالي عدد عناصر DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "الحد الأقصى من عناصر الأطفال"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "تجنُب حجم DOM الزائد"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "السمة المُستهدَفة"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "يمكنك إضافة `rel=\"noopener\"` أو `rel=\"noreferrer\"` إلى أي روابط خارجية لتحسين الأداء ومنع الثغرات الأمنية. [مزيد من المعلومات](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "الروابط إلى وجهات مشتركة المصدر هي غير آمنة"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "الروابط إلى وجهات مشتركة المصدر هي آمنة"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "يتعذّر تحديد الوجهة لإعلان ثابت {anchorHTML}). في حال عدم استخدامه كرابط تشعبي، يمكنك إزالة target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "لا يثق المستخدمون في المواقع الإلكترونية التي تطلب مواقعهم الجغرافية بدون سياق أو قد يؤدي ذلك إلى إرباكهم. يمكنك ربط الطلب بإجراء المستخدم بدلاً من ذلك. [مزيد من المعلومات](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "يتم طلب إذن رصد الموقع الجغرافي عند تحميل الصفحة"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "يتم تجنُب طلب إذن رصد الموقع الجغرافي عند تحميل الصفحة"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "الإصدار"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "تم رصد جميع مكتبات الواجهة الأمامية جافا سكريبت في الصفحة. [مزيد من المعلومات](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "مكتبات جافا سكريبت التي تم رصدها"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "بالنسبة إلى المستخدمين الذين لديهم اتصالات بطيئة، يمكن للبرامج النصية الخارجية التي يتم إدخالها ديناميكيًا عبر `document.write()` تأخير تحميل الصفحة لمدة ثوانٍ متعددة. [مزيد من المعلومات](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "يتم استخدام `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "يتم تجنُب `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "أعلى نسبة خطورة"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "إصدار المكتبة"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "عدد الثغرات"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "قد تحتوي بعض البرامج النصية للجهات الخارجية على ثغرات أمنية معروفة يمكن للمهاجمين تحديدها واستغلالها بسهولة. [مزيد من المعلومات](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم رصد ثغرة واحدة}zero{تم رصد # ثغرة}two{تم رصد ثغرتين (#)}few{تم رصد # ثغرات}many{تم رصد # ثغرةً}other{تم رصد # ثغرة}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "يتم تضمين مكتبات الواجهة الأمامية جافا سكريبت ذات الثغرات الأمنية المعروفة"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "مرتفع"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "منخفض"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "متوسط"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "يتم تجنُب مكتبات الواجهة الأمامية جافا سكريبت ذات الثغرات الأمنية المعروفة"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "لا يثق المستخدمون في المواقع الإلكترونية التي تطلب إرسال الإشعارات بدون سياق أو قد يؤدي ذلك إلى إرباكهم. يمكنك ربط الطلب بإيماءات المستخدم بدلاً من ذلك. [مزيد من المعلومات](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "يتم طلب إذن الإشعار عند تحميل الصفحة"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "يتم تجنُّب طلب إذن الإشعار عند تحميل الصفحة"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "العناصر التي لا تسمح بلصق المحتوى"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "يؤدي منع لصق كلمة المرور إلى تقويض سياسة الأمان الجيدة. [مزيد من المعلومات](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "يتم منع المستخدمين من اللصق في حقول كلمات المرور"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "يتم السماح للمستخدمين باللصق في حقول كلمات المرور"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "البروتوكول"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "يوفّر HTTP/2 العديد من المزايا على HTTP/1.1، بما في ذلك عناوين البرامج الثنائية وعملية مضاعفة توجيه الإشارات ودفع الخادم. [مزيد من المعلومات](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{لم يتم عرض طلب واحد عبر HTTP/2}zero{لم يتم عرض # طلب عبر HTTP/2}two{لم يتم عرض طلبين (#) عبر HTTP/2}few{لم يتم عرض # طلبات عبر HTTP/2}many{لم يتم عرض # طلبًا عبر HTTP/2}other{لم يتم عرض # طلب عبر HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "لا تستخدم صفحة الويب HTTP/2 لجميع مواردها"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "تستخدم صفحة الويب HTTP/2 لمواردها الخاصة"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "يمكنك وضع علامة على \"أدوات معالجة أحداث لمس الشاشة وتحريك الماوس\" بصفتها `passive` لتحسين عملية التنقل في صفحتك. [مزيد من المعلومات](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "لا يتم استخدام أدوات معالجة الحدث السلبية لتحسين عملية التنقل في الصفحة"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "يتم استخدام أدوات معالجة الحدث السلبية لتحسين أداء التمرير"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "الوصف"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "تشير الأخطاء التي تم تسجيلها في وحدة التحكّم إلى مشاكل لم يتم حلها. قد تنتج هذه المشاكل من إخفاقات طلب الشبكة ومشاكل أخرى تتعلق بالمتصفّح. [مزيد من المعلومات](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "تم تسجيل أخطاء المتصفح في وحدة التحكّم"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "لم يتم تسجيل أخطاء المتصفح في وحدة التحكّم"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "يمكنك الاستفادة من ميزة CSS لعرض الخطوط لضمان أن يكون النص مرئيًا للمستخدم أثناء تحميل خطوط موقع ويب. [مزيد من المعلومات](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "التأكد من بقاء النص مرئيًا أثناء تحميل خط موقع ويب"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "تظل جميع النصوص مرئية أثناء تحميل خط موقع ويب"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "لم يتمكّن Lighthouse من التحقّق تلقائيًا من قيمة عرض الخط لعنوان URL التالي: {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "نسبة العرض إلى الارتفاع (الفعلية)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "نسبة العرض إلى الارتفاع (معروضة)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "يجب أن تتوافق أبعاد عرض الصورة مع نسبة العرض إلى الارتفاع الطبيعية. [مزيد من المعلومات](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "يتم عرض الصور مع نسبة عرض إلى ارتفاع غير صحيحة"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "يتم عرض الصور مع نسبة العرض إلى الارتفاع الصحيحة"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "معلومات تغيير حجم الصورة غير صالحة {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "يمكن للمتصفحات أن تطلب من المستخدمين بشكل مسبق إضافة تطبيقك إلى الشاشة الرئيسية، ويمكن بذلك زيادة التفاعل. [مزيد من المعلومات](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "عدم استيفاء بيان تطبيق الويب متطلبات التثبيت"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "استيفاء بيان تطبيق الويب متطلبات التثبيت"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "عنوان URL غير آمن"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "يجب حماية جميع المواقع الإلكترونية باستخدام HTTPS، حتى تلك المواقع التي لا تتعامل مع البيانات الحساسة. يمنع HTTPS الدخلاء من العبث بالاتصالات بين تطبيقك والمستخدمين أو الاستماع إليها بشكل سلبي، وهو شرط مسبق لـ HTTP/2 والعديد من واجهات برمجة تطبيقات الأنظمة الأساسية للويب الجديدة. [مزيد من المعلومات](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم العثور على طلب غير آمن واحد}zero{تم العثور على # طلب غير آمن}two{تم العثور على طلبين غير آمنين (#)}few{تم العثور على # طلبات غير آمنة}many{تم العثور على # طلبًا غير آمن}other{تم العثور على # طلب غير آمن}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "لا يتم استخدام HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "يتم استخدام HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "إنّ تحميل الصفحات بشكل سريع عبر شبكة الجوّال يضمن توفير تجربة استخدام عالية الجودة. [مزيد من المعلومات](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "الوقت التفاعلي {timeInMs, number, seconds} ثانية"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "الوقت التفاعلي على شبكة الجوّال التي تمت محاكاتها لمدة {timeInMs, number, seconds}  ثانية"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "تحميل الصفحة بطيء جدًا وليس تفاعليًا خلال 10 ثوانٍ. يُرجى الاطّلاع على الفرص وبيانات التشخيص في قسم \"الأداء\" للتعرُّف على طريقة التحسين."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "تحميل الصفحة على شبكات الجوّال ليس سريعًا بشكلٍ كافٍ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "تحميل الصفحة سريع بشكلٍ كافٍ في شبكات الجوّال"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "الفئة"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "يمكنك تقليل الوقت المستغرق في تحليل جافا سكريبت وإنشائه وتنفيذه. قد يتبين لك أن تسليم أحمال جافا سكريبت بحجم أصغر يساعد على ذلك. [مزيد من المعلومات](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "تقليل سلسلة العمل الرئيسية"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "تقليل سلسلة العمل الرئيسية"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "للوصول إلى أكبر عدد من المستخدمين، يجب استخدام المواقع الإلكترونية على كل متصفح رئيسي. [مزيد من المعلومات](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "الموقع الإلكتروني يعمل عبر المتصفح"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "يُرجى التأكّد من أن الصفحات الفردية قابلة للربط بشكلٍ كبير عبر عنوان URL وأن عناوين URL فريدة لغرض إمكانية المشاركة على وسائل التواصل الاجتماعي. [مزيد من المعلومات](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "كل صفحة تحتوي على عنوان URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "من المفترض إجراء عمليات النقل بسرعة عند النقر حولها، حتى على شبكة بطيئة. هذه التجربة هي عنصر أساسي لإدراك مستخدم لمستوى الأداء. [مزيد من المعلومات](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "عمليات نقل الصفحة لا تبدو أنها محظورة على الشبكة"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "إن \"وقت الاستجابة المقدر للإدخال\" هو تقدير لطول المدة التي يستغرقها تطبيقك للاستجابة لإدخال المستخدم بالمللي ثانية، وذلك أثناء الثواني الخمس الأكثر انشغالاً في فترة تحميل الصفحة. وفي حال كان وقت الاستجابة أكثر من 50 مللي ثانية، يمكن للمستخدمين اعتبار تطبيقك بأنه بطيء في التفاعل. [مزيد من المعلومات](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "وقت الاستجابة المُقدّر للإدخال"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "تحدد \"سرعة عرض المحتوى على الصفحة\" الوقت الذي يُعرَض فيه أول صورة أو نص. [مزيد من المعلومات](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "تشير \"وحدة المعالجة المركزية الأولى الخاملة\" إلى المرة الأولى التي يتوفر فيها وقت كافٍ للعملية الرئيسية للصفحة حتى تعالج إدخالات المستخدم. [مزيد من المعلومات](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "وحدة المعالجة المركزية الأولى الخاملة"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "تقيس \"سرعة عرض أوّل محتوى مفيد على الصفحة\" الوقت الذي يكون فيه المحتوى الأساسي لصفحة مرئيًا. [مزيد من المعلومات](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "وقت التفاعل هو مقدار الوقت المستغرق حتى تصبح الصفحة تفاعلية بالكامل. [مزيد من المعلومات](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "وقت التفاعل"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "الحد الأقصى المحتمل من \"مهلة الاستجابة لأوّل إدخال\" الذي قد يواجهه المستخدمون هو المدة بالمللي ثانية لأطول مهمة. [مزيد من المعلومات](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "الحد الأقصى المحتمل من مهلة الاستجابة لأوّل إدخال"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "يوضح مؤشر السرعة وتيرة تعبئة محتوى الصفحة على شاشة المستخدم. [مزيد من المعلومات](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "مؤشر السرعة"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "مجموع جميع الفترات الزمنية بين \"سرعة عرض المحتوى على الصفحة\" و\"وقت التفاعل\"، عندما تتجاوز مدة المهمة 50 مللي ثانية، معبرًا عنها بالمللي ثانية."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "إجمالي حظر الوقت"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "تؤثر مُدد الإرسال والاستقبال للشبكة تأثيرًا كبيرًا في مستوى الأداء. في حال كانت مدة الإرسال والاستقبال كبيرة، يشير ذلك إلى احتمال تحسّن أداء الخوادم الأقرب إلى المستخدم. [مزيد من المعلومات](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "أوقات إرسال واستقبال الشبكة"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "قد تؤثر أوقات استجابة الخادم في أداء الويب. في حال كان وقت استجابة الخادم للأصل طويلاً، هذه إشارة إلى أنه تم تحميل الخادم بشكلٍ زائد أو مستوى أدائه ضعيف في الخلفية. [مزيد من المعلومات](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "أوقات الاستجابة لواجهة الخادم الخلفية"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "يمكّن مشغّل الخدمات تطبيق الويب من أن يصبح موثوقًا به في ظروف الشبكة التي لا يمكن التنبؤ بها. [مزيد من المعلومات](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` لا تستجيب باستخدام رمز 200 عند عدم الاتصال بالإنترنت"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` يستجيب باستخدام رمز 200 عند عدم الاتصال بالإنترنت"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "تعذّر على Lighthouse قراءة `start_url` من البيان. ونتيجة لذلك، كان من المفترض أن يكون `start_url` هو عنوان URL للمستند. رسالة خطأ: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "تجاوز الميزانية"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "يمكنك الحفاظ على كمية طلبات الشبكة وحجمها ضمن الاستهدافات المحدّدة في ميزانية الأداء المقدّمة. [مزيد من المعلومات](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{طلب واحد}zero{# طلب}two{طلبان (#)}few{# طلبات}many{# طلبًا}other{# طلب}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "ميزانية الأداء"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "في حال أعددت HTTPS مسبقًا، تأكّد من إعادة توجيه جميع زيارات HTTP إلى HTTPS من أجل تفعيل ميزات الويب الآمنة لجميع المستخدمين. [مزيد من المعلومات](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "عدم إعادة توجيه زيارات HTTP إلى HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "إعادة توجيه زيارات HTTP إلى HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "تؤدي عمليات إعادة التوجيه إلى حدوث تأخيرات إضافية قبل أن يتم تحميل الصفحة. [مزيد من المعلومات](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "تجنُب عمليات إعادة توجيه الصفحات المتعددة"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "لضبط ميزانيات لكمية موارد الصفحة وحجمها، يمكنك إضافة ملف budget.json. [مزيد من المعلومات](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{طلب واحد • {byteCount, number, bytes} كيلوبايت}zero{# طلب • {byteCount, number, bytes} كيلوبايت}two{طلبان (#) • {byteCount, number, bytes} كيلوبايت}few{# طلبات • {byteCount, number, bytes} كيلوبايت}many{# طلبًا • {byteCount, number, bytes} كيلوبايت}other{# طلب • {byteCount, number, bytes} كيلوبايت}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "الحفاظ على انخفاض عدد الطلبات ونقل الأحجام الصغيرة"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "تقترح الروابط الأساسية عنوان URL للعرض في نتائج البحث. [مزيد من المعلومات](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "تتعدّد عناوين URL المتضاربة ({urlList})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "يشير عنوان URL إلى نطاق مختلف ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "عنوان URL غير صالح ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "يشير عنوان URL إلى موقع جغرافي `hreflang` آخر ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "عنوان URL هو نسبي ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "يشير إلى عنوان URL الجذر للنطاق (الصفحة الرئيسية)، بدلاً من صفحة مكافئة للمحتوى"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "المستند لا يحتوي على سمة `rel=canonical` صالحة"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "المستند يحتوي على سمة `rel=canonical` صالحة"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "أحجام الخطوط الأقل من 12 بكسل صغيرة جدًا بحيث لا يمكن قراءتها بسهولة وتتطلب من مستخدمي الجوّال \"تحريك الإصبعين للتكبير أو التصغير\" من أجل قراءتها. يمكنك بذل قصارى جهدك للحصول على نسبة أكبر من 60% من نص الصفحة بمقدار أكبر من أو يساوي 12 بكسل. [مزيد من المعلومات](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "نص {decimalProportion, number, extendedPercent} قابل للقراءة"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "النص غير مقروء لأنه لا تتوفّر علامة وصفية لإطار العرض محسنة لشاشات الجوّال."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "نسبة {decimalProportion, number, extendedPercent} من النص هي صغيرة جدًا (استنادًا إلى نموذج {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "لا يستخدم المستند أحجام الخطوط القابلة للقراءة"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "يستخدم المستند أحجام الخط القابلة للقراءة"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "تخبر روابط hreflang محركات البحث عن إصدار الصفحة الذي يجب إدراجه في نتائج البحث للغة أو منطقة معيّنة. [مزيد من المعلومات](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "المستند لا يحتوي على سمة `hreflang` صالحة"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "المستند يحتوي على سمة `hreflang` صالحة"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "قد لا تتم فهرسة الصفحات التي تتضمّن رموز حالة HTTP غير صالحة بشكلٍ صحيح. [مزيد من المعلومات](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "تحتوي الصفحة على رمز حالة HTTP غير صالح"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "تحتوي الصفحة على رمز حالة HTTP صالح"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "يتعذّر على محركات البحث تضمين صفحاتك في نتائج البحث في حال عدم حصولها على إذن للزحف إلى هذه الصفحات. [مزيد من المعلومات](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "يتم حظر الصفحة من الفهرسة"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "الصفحة ليست محظورة من الفهرسة"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "يساعد نص الرابط الوصفي محركات البحث على فهم المحتوى. [مزيد من المعلومات](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{تم العثور على رابط واحد}zero{تم العثور على # رابط}two{تم العثور على رابطين (#)}few{تم العثور على # روابط}many{تم العثور على # رابطًا}other{تم العثور على # رابط}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "عدم احتواء الروابط على نص وصفي"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "تحتوي الروابط على نص وصفي"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "يمكنك تشغيل [أداة اختبار البيانات المنظَّمة](https://search.google.com/structured-data/testing-tool/) و[Linter للبيانات المنظَّمة](http://linter.structured-data.org/) للتحقّق من البيانات المنظَّمة. [مزيد من المعلومات](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "البيانات المنظَّمة صالحة"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "قد يتم تضمين الأوصاف التعريفية في نتائج البحث لتلخيص محتوى الصفحة بإيجاز. [مزيد من المعلومات](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "نص الوصف فارغ."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "لا يحتوي المستند على وصف تعريفي"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "يحتوي المستند على وصف تعريفي"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "لا يمكن لمحركات البحث فهرسة محتوى مكون إضافي وتحظر العديد من الأجهزة استخدام المكونات الإضافية أو لا توفّرها. [مزيد من المعلومات](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "يستخدم المستند مكونات إضافية"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "يتجنّب المستند المكونات الإضافية"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "في حال كان ملف robots.txt مكتوبًا بصيغة غير صحيحة، يمكن ألا تفهم برامج الزحف كيف تريد أن يتم الزحف إلى موقعك الإلكتروني أو أن تتم فهرسته. [مزيد من المعلومات](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "الطلب لملف robots.txt عرض حالة HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{تم العثور على خطأ واحد}zero{تم العثور على # خطأ}two{تم العثور على خطأين (#)}few{تم العثور على # أخطاء}many{تم العثور على # خطأً}other{تم العثور على # خطأ}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "تعذّر على Lighthouse تنزيل ملف robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "ملف \"robots.txt\" غير صالح"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "ملف \"robots.txt\" صالح"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "يجب أن تكون العناصر التفاعلية، مثل الأزرار والروابط، كبيرة بشكلٍ كافٍ (48 × 48 بكسل) وأن تحيط بها مساحة كافية ليكون من السهل النقر عليها بدون النقر على أي عناصر أخرى. [مزيد من المعلومات](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "تم تحديد حجم {decimalProportion, number, percent} لأهداف النقر بشكلٍ مناسب"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "أهداف النقر صغيرة جدًا لأنه لا تتوفّر علامة وصفية لإطار العرض محسنة لشاشات الجوّال."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "لم يتم تحديد حجم أهداف النقر بشكل مناسب"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "استهداف متداخِل"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "هدف النقر"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "يتم تحديد حجم أهداف النقر بشكل مناسب"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "مشغّل الخدمات هو التكنولوجيا التي تمكّن تطبيقك من استخدام ميزات عديدة من \"تطبيق الويب التقدّمي\"، مثل الاستجابة عند عدم الاتصال بالإنترنت والإضافة إلى الشاشة الرئيسية والإشعارات الفورية. [مزيد من المعلومات](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "يتحكم مشغّل الخدمات في هذه الصفحة، ومع ذلك لم يتم العثور على `start_url` بسبب تعذّر تحليل البيان كملف JSON صالح"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "يتحكم مشغّل الخدمات في هذه الصفحة، ومع ذلك لا يتوفر `start_url` ({startUrl}) في نطاق مشغّل الخدمات ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "يتحكم مشغّل الخدمات في هذه الصفحة، ومع ذلك لم يتم العثور على `start_url` لأنه لم يتم جلب أي بيان."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "تحتوي نقطة الانطلاق هذه على مشغّل خدمات واحد أو أكثر، ولكن لا يوجد مشغّل يتحكم في الصفحة ({pageUrl})."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "عدم تسجيل مشغّل الخدمات الذي يتحكّم في صفحة و`start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "تسجيل مشغّل الخدمات الذي يتحكّم في صفحة و`start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "تضمن شاشة البداية المميزة توفير تجربة عالية الجودة عند إطلاق المستخدمين تطبيقك من الشاشات الرئيسية. [مزيد من المعلومات](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "عدم الضبط لشاشة بداية مخصّصة"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "تم الضبط لشاشة البداية المخصّصة"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "يمكن تصميم شريط العناوين للمتصفح لمطابقة موقعك الإلكتروني. [مزيد من المعلومات](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "عدم ضبط لون تصميم لشريط العناوين"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "ضبط لون تصميم لشريط العناوين"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "وقت حظر سلسلة المحادثات الأساسية"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "الجهة الخارجية"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "يمكن أن يؤثر الرمز البرمجي الخاصّ بالجهة الخارجية بشكل كبير في أداء التحميل. يمكنك تحديد عدد مقدِّمي الخدمة للجهات الخارجية المتكرّرين ومحاولة تحميل الرمز البرمجي الخاص بالجهة الخارجية بعد انتهاء تحميل صفحتك بشكل أساسي. [مزيد من المعلومات](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "لقد حظر رمز الجهة الخارجية سلسلة المحادثات الرئيسية لمدة {timeInMs, number, milliseconds} مللي ثانية"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "تقليل تأثير رمز الجهة الخارجية"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "استخدام جهة خارجية"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "يحدّد \"وقت وصول أول بايت\" الوقت الذي يُرسل فيه الخادم استجابة. [مزيد من المعلومات](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "استغرق مستند الجذر {timeInMs, number, milliseconds} مللي ثانية"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "تقليل أوقات استجابة الخادم (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "أوقات استجابة الخادم منخفضة (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "المدة"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "وقت البدء"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "النوع"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "يمكنك توجيه تطبيقك باستخدام \"واجهة برمجة التطبيقات لأوقات المستخدم\" لقياس الأداء الفعلي العالمي لتطبيقك أثناء التجارب الأساسية للمستخدمين. [مزيد من المعلومات](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{وقت واحد للمستخدم}zero{# وقت للمستخدم}two{وقتا (#) المستخدم}few{# أوقات للمستخدم}many{# وقتًا للمستخدم}other{# وقت للمستخدم}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "علامات أوقات المستخدم وقياساتها"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "تم العثور على <link> للربط المسبق لـ \"{securityOrigin}\"، ولكن لم يتم استخدامه من خلال المتصفح. يُرجى التحقّق من استخدام السمة `crossorigin` بشكل صحيح."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "يمكنك إضافة تعديلات المورد `preconnect` أو `dns-prefetch` لإنشاء اتصالات مبكرة بأصول مهمة تابعة لجهة خارجية. [مزيد من المعلومات](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "الاتصال المسبق للأصول المطلوبة"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "تم العثور على <link> للتحميل المسبق لـ \"{preloadURL}\"، ولكن لم يتم استخدامه من خلال المتصفح. يُرجى التحقّق من استخدام السمة `crossorigin` بشكل صحيح."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "يمكنك استخدام `<link rel=preload>` لتحديد أولويات جلب الموارد المطلوبة حاليًا في وقتٍ لاحق في تحميل الصفحة. [مزيد من المعلومات](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "التحميل المسبق للطلبات الأساسية"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "يُرجى إضافة علامة `<meta name=\"viewport\">` لتحسين تطبيقك لشاشات الجوّال. [مزيد من المعلومات](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "لم يتم العثور على علامة `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "عدم الاحتواء على علامة `<meta name=\"viewport\">` مع `width` أو `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "تضمين علامة `<meta name=\"viewport\">` مع `width` أو `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "يجب أن يعرض تطبيقك بعض المحتوى عند إيقاف جافا سكريبت، حتى في حال كان مجرد تحذير للمستخدم يشير إلى ضرورة وجود جافا سكريبت لاستخدام التطبيق. [مزيد من المعلومات](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "يجب أن يعرض نص الصفحة بعض المحتوى في حالة عدم توفر النصوص البرمجية."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "عدم تقديم المحتوى الاحتياطي عند عدم توفر جافا سكريبت"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "تضمين بعض المحتوى عند عدم توفّر جافا سكريبت"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "في حال كنت تنشئ \"تطبيق ويب تقدّمي\"، يمكنك استخدام مشغّل الخدمات حتى يتمكّن التطبيق من العمل بلا اتصال بالإنترنت. [مزيد من المعلومات](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "الصفحة الحالية لا تستجيب باستخدام رمز 200 عند عدم الاتصال بالإنترنت"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "الصفحة الحالية تستجيب باستخدام رمز 200 عند عدم الاتصال بالإنترنت"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "قد لا يتم تحميل الصفحة بلا اتصال بالإنترنت لأنه تمت إعادة توجيه عنوان URL للاختبار ({requested}) إلى \"{final}\". ويمكنك محاولة اختبار عنوان URL الثاني مباشرة."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "هذه هي فرص لتحسين استخدام ARIA في تطبيقك، ما قد يحسّن تجربة مستخدمي التكنولوجيا المساعدة، مثل قارئ الشاشة."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "هذه الفرص تتيح توفير محتوى بديل للصوت والفيديو. قد يحسّن ذلك التجربة للمستخدمين الذين يعانون من إعاقات سمعية أو بصرية."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "الصوت والفيديو"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "تحدّد هذه العناصر أفضل الممارسات الشائعة المتعلقة بإمكانية الوصول."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "أفضل الممارسات"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "تحدّد عمليات التحقق هذه الفرص التي تتيح [تحسين إمكانية الوصول إلى تطبيق الويب](https://developers.google.com/web/fundamentals/accessibility). ولا يمكن إجراء رصد تلقائي إلّا لمجموعة فرعية من مشاكل إمكانية الوصول، لذلك يُنصح أيضًا باستخدام الاختبار اليدوي."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "تعالج هذه العناصر المناطق التي يتعذر على أداة الاختبار التلقائية تغطيتها. تعرّف على مزيد من المعلومات في دليلنا حول [مراجعة إمكانية الوصول](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "إمكانية الوصول"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "هذه هي فرص لتحسين سهولة قراءة المحتوى."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "التباين"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "هذه هي فرص لتحسين تفسير المحتوى من خلال المستخدمين بلغات مختلفة."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "التدويل والأقلمة"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "هذه هي فرص لتحسين دلالات عناصر التحكُّم في التطبيق. قد يحسّن ذلك من تجربة مستخدمي التكنولوجيا المساعدة، مثل قارئ الشاشة."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "الأسماء والتصنيفات"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "هذه الفرص تتيح لك تحسين التنقل باستخدام لوحة المفاتيح في تطبيقك."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "التنقل"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "هذه الفرص تتسح تحسين تجربة قراءة بيانات القائمة أو الجدول باستخدام التكنولوجيا المساعدة، مثل قارئ الشاشة."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "الجداول والقوائم"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "أفضل الممارسات"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "تضبط ميزانيات الأداء معايير لأداء موقعك الإلكتروني."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "الميزانيات"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "مزيد من المعلومات حول أداء تطبيقك لا تؤثر هذه الأرقام [ بشكل مباشر في ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) نتيجة الأداء."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "بيانات التشخيص"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "يمثل الجانب الأكثر أهمية للأداء مدى السرعة التي يتم بها عرض وحدات البكسل على الشاشة. المقاييس الرئيسية: First Contentful Paint وFirst Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "تحسينات العرض الأول"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "يمكن أن تساعد هذه الاقتراحات على تحميل صفحتك بشكل أسرع. لا تؤثر هذه الاقتراحات [بشكل مباشر](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) في نتيجة الأداء."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "فرص تحسين الأداء"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "المقاييس"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "يمكنك تحسين تجربة التحميل العامة لتصبح هذه الصفحة سريعة الاستجابة وجاهزة للاستخدام في أقرب وقت ممكن. المقاييس الأساسية: وقت التفاعل ومؤشر السرعة."
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "التحسينات العامة"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "الأداء"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "تعمل هذه العمليات على التحقق من جوانب \"تطبيق الويب التقدّمي\". [مزيد من المعلومات](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "يُطلب إجراء عمليات التحقّق هذه من خلال المرجع [قائمة التحقق PWA](https://developers.google.com/web/progressive-web-apps/checklist)، ولكن لم يتم التحقُّق منها تلقائيًا من خلال Lighthouse. لا تؤثر عمليات التحقق هذه في نتيجتك، ولكن من المهم أنك تتحقق منها يدويًا."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "تطبيق الويب التقدّمي"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "سريع وموثوق"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "القسم القابل للتثبيت"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "تحسين PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "تضمن عمليات التحقّق هذه تحسين أداء صفحتك لتظهر في ترتيب نتائج محرّك البحث. هناك عوامل إضافية لا يتحقّق منها Lighthouse قد تؤثر في ترتيب نتائج البحث. [مزيد من المعلومات](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "تشغيل أدوات التحقُّق الإضافية هذه على موقعك الإلكتروني للتحقُّق من أفضل ممارسات تحسين محركات البحث الإضافية."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "تحسين محركات البحث"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "يمكنك تنسيق HTML بطريقة تتيح لبرامج الزحف فهم محتوى تطبيقك بشكلٍ أفضل."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "أفضل ممارسات المحتوى"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "للظهور في نتائج البحث، تحتاج برامج الزحف إلى الوصول إلى تطبيقك."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "الزحف والفهرسة"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "يُرجى التأكّد من أن صفحاتك متوافقة مع الجوّال، حتى لا يحتاج المستخدمون إلى التصغير أو التكبير من أجل الاطّلاع على صفحات المحتوى. [مزيد من المعلومات](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "متوافق مع الجوّال"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "ذاكرة التخزين المؤقت TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "الموقع الجغرافي"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "الاسم"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "الطلبات"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "نوع المورد"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "الحجم"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "الوقت المستغرَق"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "حجم النقل"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "عنوان URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "التوفيرات المحتملة"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "التوفيرات المحتملة"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "التوفيرات المحتملة من {wastedBytes, number, bytes}  كيلوبايت"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "التوفيرات المحتملة من {wastedMs, number, milliseconds} مللي ثانية"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "المستند"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "الخط"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "الصورة"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "الوسائط"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} مللي ثانية"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "غير ذلك"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "النص البرمجي"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} ثانية"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "ورقة الأنماط"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "الجهة الخارجية"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "الإجمالي"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "حدث خطأ أثناء تسجيل التتبع عند تحميل صفحتك. يُرجى تشغيل Lighthouse مرة أخرى. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "مهلة انتظار ربط بروتوكول برنامج تصحيح الخلل الأول."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "لم يجمع Chrome أي لقطات شاشة خلال عملية تحميل الصفحة. يُرجى التأكّد من توفّر محتوى مرئي على الصفحة، ثم محاولة إعادة تشغيل Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "تعذّر على خوادم نظام أسماء النطاقات حل مشكلة النطاق المُقدّم."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "واجهت عملية التجميع {artifactName} المطلوبة خطأً: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "حدث خطأ في متصفّح Chrome الداخلي. يُرجى إعادة تشغيل Chrome ومحاولة إعادة تشغيل Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "كان من المطلوب تجميع {artifactName} ولكن لم يتم تنفيذ ذلك."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "لم يتمكّن Lighthouse من تحميل الصفحة المطلوبة بشكل موثوق. يمكنك التأكُّد من اختبار عنوان URL الصحيح وأن الخادم يستجيب بشكل صحيح لجميع الطلبات."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "لم يتمكّن Lighthouse من تحميل عنوان URL الذي طلبته بشكل موثوق لأن الصفحة توقفت عن الاستجابة."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "لا يحتوي عنوان URL الذي قدمته على شهادة أمان صالحة. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "منَع Chrome تحميل صفحة مع محتوى بيني. عليك التأكّد من اختبار عنوان URL الصحيح وأن الخادم يستجيب بشكل صحيح لجميع الطلبات."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "لم يتمكّن Lighthouse من تحميل الصفحة المطلوبة بشكل موثوق. عليك التأكّد من اختبار عنوان URL الصحيح وأن الخادم يستجيب بشكل صحيح لجميع الطلبات. (التفاصيل: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "لم يتمكّن Lighthouse من تحميل الصفحة المطلوبة بشكل موثوق. عليك التأكّد من اختبار عنوان URL الصحيح وأن الخادم يستجيب بشكل صحيح لجميع الطلبات. (رمز الحالة: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "استغرق تحميل الصفحة وقتًا طويلاً. يُرجى اتّباع الفرص الواردة في التقرير لتقليل وقت تحميل الصفحة، ثم محاولة إعادة تشغيل Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "لقد تجاوز وقت انتظار استجابة بروتوكول DevTools الوقت المخصص. (الطريقة: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "تجاوز جلب محتوى المورد الوقت المخصّص"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "يبدو أن عنوان URL الذي قدمته غير صحيح."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "عرض عمليات التدقيق"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "التنقل الأوّلي"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "الحد الأقصى لوقت استجابة المسار المهم:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "خطأ!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "الإبلاغ عن خطأ: لا تتوفَّر معلومات تدقيق"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "بيانات المختبَر"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "أجرت أداة [Lighthouse](https://developers.google.com/web/tools/lighthouse/) تحليلًا للصفحة الحالية على شبكة الجوّال في وضع المحاكاة. القيم تقديرية وقابلة للتغيير."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "عناصر إضافية للتحقُّق يدويًا"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "غير سارٍ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "فرصة تحسين الأداء"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "التوفيرات المُقدرة"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "اجتياز عمليات التدقيق بنجاح"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "تصغير المقتطف"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "توسيع المقتطف"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "عرض موارد الجهات الخارجية"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "حدثت مشاكل تؤثر في تشغيل Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "القيم تقديرية وقابلة للتغيير. نتيجة الأداء [مستندة إلى هذه المقاييس فقط](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "عمليات التدقيق التي تم اجتيازها، ولكن تتضمّن التحذيرات"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "التحذيرات: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "يمكنك تحميل ملف GIF إلى خدمة ستتيح تضمينه باعتباره فيديو HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "يمكنك تثبيت [مكون WordPress الإضافي للتحميل الكسول](https://wordpress.org/plugins/search/lazy+load/) الذي يوفر القدرة على تأجيل أي صور خارج الشاشة، أو التبديل إلى تصميم يوفِّر هذه القدرة الوظيفية. يمكنك أيضًا استخدام [مكون AMP الإضافي](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "هناك عدد من مكونات WordPress الإضافية التي يمكنها مساعدتك على [تضمين مواد العرض المهمة](https://wordpress.org/plugins/search/critical+css/) أو [تأجيل موارد أقل أهمية](https://wordpress.org/plugins/search/defer+css+javascript/). عليك توخي الحذر من أن التحسينات التي توفرها هذه الإضافات قد توقف ميزات التصميم أو المكونات الإضافية، لذلك ستحتاج على الأرجح إلى إجراء تغييرات في الرمز البرمجي."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "تساهم التصاميم والمكونات الإضافية ومواصفات الخادم في تحسين وقت استجابة الخادم. يمكنك البحث عن تصميم مُحسّن أكثر و/أو اختيار مكون إضافي للتحسين و/أو ترقية الخادم."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "يمكنك عرض مقتطفات في قوائم مشاركاتك (مثلاً عبر العلامة \"المزيد\")، أو تقليل عدد المشاركات المعروضة في صفحة معينة، أو تقسيم مشاركاتك الطويلة إلى صفحات متعددة، أو استخدام مكون إضافي لتحميل التعليقات ذات التحميل الكسول."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "يمكن لعدد من [مكونات WordPress الإضافية](https://wordpress.org/plugins/search/minify+css/) زيادة سرعة موقعك الإلكتروني من خلال ربط الأنماط وتصغيرها وضغطها. يمكنك أيضًا استخدام عملية إنشاء الموقع الإلكتروني لإزالة البيانات غير الضرورية بشكل مسبق إذا أمكن ذلك."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "يمكن لعدد من [مكونات WordPress الإضافية ](https://wordpress.org/plugins/search/minify+javascript/) زيادة سرعة موقعك الإلكتروني من خلال ربط النصوص البرمجية وتصغيرها وضغطها. يمكنك أيضًا استخدام عملية إنشاء الموقع الإلكتروني لإزالة البيانات غير الضرورية بشكل مسبق إذا أمكن ذلك."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "يمكنك تقليل عدد [مكونات WordPress الإضافية](https://wordpress.org/plugins/) التي تُحمِّل خدمة CSS غير المُستخدَمة في صفحتك أو تبديلها. لتحديد المكونات الإضافية التي تضيف CSS دخيلة، يمكنك محاولة تشغيل [تغطية الرمز البرمجي](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) في Chrome DevTools. يمكنك تحديد التصميم/المكون الإضافي المسؤول عن عنوان URL لورقة الأنماط. يمكنك البحث عن المكونات الإضافية التي تحتوي على العديد من أوراق الأنماط في القائمة والتي تحتوي على الكثير من اللون الأحمر في تغطية الرمز البرمجي. يجب أن يدرِج المكون الإضافي ورقة أنماط فقط في حال تم استخدامه في الصفحة فعليًا."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "يمكنك تقليل عدد [مكونات WordPress الإضافية](https://wordpress.org/plugins/) التي تُحمِّل لغة جافا سكريبت غير المُستخدَمة في صفحتك أو تبديلها. لتحديد المكونات الإضافية التي تضيف لغة جافا سكريبت دخيلة، يمكنك محاولة تشغيل [تغطية الرمز البرمجي](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) في Chrome DevTools. يمكنك تحديد التصميم/المكون الإضافي المسؤول عن عنوان URL للنص البرمجي. يمكنك البحث عن المكونات الإضافية التي تحتوي على العديد من النصوص البرمجية في القائمة والتي تحتوي على الكثير من اللون الأحمر في تغطية الرمز البرمجي. يجب أن يدرِج المكون الإضافي نصًا برمجيًا فقط في حال تم استخدامه في الصفحة فعليًا."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "يمكنك الاطّلاع على [ذاكرة التخزين المؤقت للمتصفّح في WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "يمكنك استخدام [مكون WordPress الإضافي لتحسين الصورة](https://wordpress.org/plugins/search/optimize+images/) الذي يضغط صورك مع المحافظة على الجودة."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "يمكنك تحميل الصور مباشرةً من خلال [مكتبة الوسائط](https://codex.wordpress.org/Media_Library_Screen) للتأكّد من توفّر أحجام الصور المطلوبة، ثم إدراجها من مكتبة الوسائط أو استخدام أداة الصورة لضمان استخدام أفضل حجم للصورة (بما في ذلك تلك الخاصة بنقاط فاصلة متجاوبة). يمكنك تجنب استخدام صور `Full Size` إلا إذا كانت الأبعاد كافية لاستخدامها. [مزيد من المعلومات](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "يمكنك تفعيل ضغط النص في إعداد خادم الويب."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "يمكنك استخدام [مكون إضافي](https://wordpress.org/plugins/search/convert+webp/) أو خدمة تتيح لك تحويل صورك المحمَّلة إلى أفضل التنسيقات تلقائيًا."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/bg.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/bg.json
new file mode 100644
index 00000000000..65eeca5ea57
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/bg.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Клавишите за достъп дават възможност на потребителите бързо да преместят фокуса към определена част от страницата. За правилно навигиране всеки клавиш за достъп трябва да е уникален. [Научете повече](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Някои стойности на `[accesskey]` не са уникални"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Стойностите за `[accesskey]` са уникални"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Всеки елемент ARIA `role` поддържа конкретен поднабор от атрибути `aria-*`. При несъответствие атрибутите `aria-*` ще станат невалидни. [Научете повече](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Някои атрибути `[aria-*]` не съответстват на ролите си"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Атрибутите `[aria-*]` съответстват на ролите си"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Някои роли на ARIA имат задължителни атрибути, от които екранните четци получават описание на състоянието на съответния елемент. [Научете повече](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Някои елементи `[role]` нямат всички задължителни атрибути `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Елементите `[role]` имат всички задължителни атрибути `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Някои родителски роли на ARIA трябва да съдържат конкретни дъщерни роли, за да изпълняват функциите за достъпност, за които са предназначени. [Научете повече](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Някои елементи с ARIA роля `[role]`, за които се изисква дъщерните им елементи да включват конкретна роля `[role]`, не съдържат някои или всички такива задължителни дъщерни елементи."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Елементите с ARIA роля `[role]`, за които се изисква дъщерните им елементи да включват конкретна роля `[role]`, съдържат всички задължителни дъщерни елементи."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Някои дъщерни роли на ARIA трябва да се съдържат в конкретни родителски роли, за да изпълняват правилно функциите за достъпност, за които са предназначени. [Научете повече](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Някои елементи `[role]` не се съдържат в задължителния за тях родителски елемент"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Елементите `[role]` се съдържат в задължителния за тях родителски елемент"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Ролите на ARIA трябва да имат валидни стойности, за да изпълняват функциите за достъпност, за които са предназначени. [Научете повече](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Някои стойности на `[role]` не са валидни"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Стойностите на `[role]` са валидни"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Помощните технологии, като например екранни четци, не могат да интерпретират атрибути на ARIA с невалидни стойности. [Научете повече](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Някои атрибути `[aria-*]` нямат валидни стойности"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Атрибутите `[aria-*]` имат валидни стойности"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Помощните технологии, като например екранни четци, не могат да интерпретират атрибути на ARIA с невалидни имена. [Научете повече](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Някои атрибути `[aria-*]` не са валидни или са изписани неправилно"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Атрибутите `[aria-*]` са валидни и са изписани правилно"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Надписите правят аудиоелементите използваеми за потребителите със слухови увреждания, като предоставят важна информация, например кой говори и какво казва, както и друга информация, несвързана с речта. [Научете повече](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "За някои елементи `<audio>` липсва елемент `<track>` с `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Елементите `<audio>` съдържат елемент `<track>` с `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Елементи с грешки"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Когато даден бутон няма достъпно име, той ще бъде прочитан като „бутон“ от екранните четци и съответно ще бъде неизползваем за потребителите им. [Научете повече](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Бутоните нямат достъпни имена"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Бутоните имат достъпни имена"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Добавянето на начини за заобикаляне на повтарящото се съдържание дава възможност на потребителите, използващи клавиатура, да навигират по-ефективно в страницата. [Научете повече](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Страницата не съдържа заглавие, връзка за пропускане или участък с ориентир"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Страницата съдържа заглавие, връзка за пропускане или участък с ориентир"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Четенето на текст с нисък контраст е трудно или невъзможно за много потребители. [Научете повече](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Коефициентът на контрастност между цветовете на заден и преден план не е достатъчно голям."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Коефициентът на контрастност между цветовете на заден и преден план е достатъчно голям"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Когато списъците с определения не са маркирани правилно, екранните четци може да предоставят объркваща или неточна информация. [Научете повече](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Елементите `<dl>` не съдържат само правилно подредени групи `<dt>` и `<dd>` и елементи `<script>` или `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Елементите `<dl>` съдържат само правилно подредени групи `<dt>` и `<dd>` и елементи `<script>` или `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Списъчните елементи за определение (`<dt>` и `<dd>`) трябва да бъдат обвити в родителски елемент `<dl>`, за да бъдат прочетени правилно от екранните четци. [Научете повече](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Някои списъчни елементи за определение не са обвити в елементи `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Списъчните елементи за определение са обвити в елементи `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Заглавието дава възможност на потребителите на екранни четци да добият обща представа за страницата, а потребителите на търсещи машини разчитат на него в голяма степен, за да определят дали страницата е подходяща за търсенето им. [Научете повече](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Документът няма елемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Документът има елемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Стойността на всеки атрибут id трябва да е уникална, за да се предотврати пропускането на други екземпляри от страна на помощните технологии. [Научете повече](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Някои атрибути `[id]` на страницата не са уникални"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Атрибутите `[id]` на страницата са уникални"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Потребителите на екранни четци очакват заглавието на рамката да описва съдържанието й. [Научете повече](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Някои елементи `<frame>` или `<iframe>` нямат заглавие"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Елементите `<frame>` или `<iframe>` имат заглавие"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ако за дадена страница не е посочен атрибут lang, екранният четец приема, че тя е написана на стандартния език, който потребителят е избрал при настройването му. Ако страницата всъщност не е на стандартния език, екранният четец може да не прочете текста й правилно. [Научете повече](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Елементът `<html>` няма атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Елементът `<html>` има атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Посочването на валиден [език по BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) помага на екранните четци да четат текста правилно. [Научете повече](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Елементът `<html>` няма валидна стойност за атрибута `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Елементът `<html>` има валидна стойност за атрибута `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Информативните елементи трябва да имат кратък, описателен алтернативен текст. При декоративните елементи атрибутът alt може да бъде оставен без стойност. [Научете повече](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Някои графични елементи нямат атрибути `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Графичните елементи имат атрибути `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Когато за бутон от тип `<input>` се използва изображение, предоставянето на алтернативен текст помага на потребителите на екранни четци да разберат за какво служи бутонът. [Научете повече](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Някои елементи `<input type=\"image\">` нямат алтернативен текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Елементите `<input type=\"image\">` имат алтернативен текст (`[alt]`)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Етикетите дават възможност на помощните технологии, като например екранни четци, да четат правилно контролите във формуляри. [Научете повече](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Някои елементи на формуляра нямат свързани етикети"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Елементите на формуляра имат свързани етикети"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Ако дадена таблица се използва само за оформление, тя не трябва да съдържа елементи с данни, като например елементите th или caption или атрибута summary, тъй като това може да създаде объркване за потребителите на екранни четци. [Научете повече](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Презентационните елементи `<table>` използват `<th>`, `<caption>` или атрибута `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Презентационните елементи `<table>` не използват `<th>`, `<caption>` или атрибута `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Текстът на връзките (и алтернативният текст за изображения, когато се използват за връзки), който е различим, уникален и дава възможност фокусът да бъде поставен върху него, подобрява навигирането за потребителите на екранни четци. [Научете повече](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Някои връзки нямат отличително име"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Връзките имат отличителни имена"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Екранните четци съобщават съдържанието на списъците по специфичен начин. Правилното структуриране на списъците улеснява четенето им от екранните четци. [Научете повече](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Някои списъци не съдържат само елементи `<li>` и елементи за поддръжка на скриптове (`<script>` и `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Списъците съдържат само елементи `<li>` и елементи за поддръжка на скриптове (`<script>` и `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Екранните четци изискват списъчните елементи (`<li>`) да се съдържат в родителски елемент `<ul>` или `<ol>`, за да бъдат прочетени правилно. [Научете повече](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Някои списъчни елементи (`<li>`) не се съдържат в родителски елементи `<ul>` или `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Списъчните елементи (`<li>`) се съдържат в родителски елементи `<ul>` или `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Потребителите не очакват страницата да се опресни автоматично и ако това се случи, фокусът ще бъде върнат в горната й част. Това може да бъде дразнещо или объркващо за потребителите. [Научете повече](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Документът използва `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Документът не използва `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Невъзможността за промяна на мащаба създава проблем за потребителите със слабо зрение, които разчитат на увеличението на екрана, за да виждат добре съдържанието на уеб страниците. [Научете повече](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` се използва в елемента `<meta name=\"viewport\">` или стойността на атрибута `[maximum-scale]` е по-малка от 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` не се използва в елемента `<meta name=\"viewport\">` и стойността на атрибута `[maximum-scale]` не е по-малка от 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Екранните четци не могат да интерпретират нетекстово съдържание. Добавянето на алтернативен текст към елементите `<object>` помага на екранните четци да предават смисъла им на потребителите. [Научете повече](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Някои елементи `<object>` нямат алтернативен текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Елементите `<object>` имат алтернативен текст (`[alt]`)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Ако стойността е по-голяма от 0, значи се използва изричен ред на навигиране. Въпреки че е технически валидно, това често създава неудобства за потребителите, които разчитат на помощни технологии. [Научете повече](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Някои елементи имат атрибут `[tabindex]` със стойност, по-голяма от 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Никой от елементите няма атрибут `[tabindex]` със стойност, по-голяма от 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Екранните четци имат функции за улесняване на навигирането в таблици. Когато клетките от типа `<td>`, използващи атрибута `[headers]`, сочат само към други клетки от същата таблица, това може да подобри практическата работа за потребителите на екранни четци. [Научете повече](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Някои клетки в елемент `<table>`, които използват атрибута `[headers]`, сочат към елемент `id`, който не бе намерен в същата таблица."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Клетките в елемент `<table>`, които използват атрибута `[headers]`, сочат към клетки от същата таблица."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Екранните четци имат функции за улесняване на навигирането в таблици. Когато всички заглавки в таблицата сочат към някакъв набор от клетки, това може да подобри практическата работа за потребителите на екранни четци. [Научете повече](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Някои елементи `<th>` и елементи с `[role=\"columnheader\"/\"rowheader\"]` нямат клетки с данни, за които служат като описание."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Елементите `<th>` и тези с `[role=\"columnheader\"/\"rowheader\"]` имат клетки с данни, за които служат като описание."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Посочването на валиден [език по BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) за елементите дава възможност на екранните четци да произнасят текста правилно. [Научете повече](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Някои атрибути `[lang]` нямат валидна стойност"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Атрибутите `[lang]` имат валидна стойност"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Наличието на надпис за даден видеоклип улеснява достъпа до съответната информация за потребителите със слухови увреждания. [Научете повече](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Някои елементи `<video>` не съдържат елемент `<track>` с `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Елементите `<video>` съдържат елемент `<track>` с `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Аудиоописанията предоставят полезна информация за видеоклиповете (например за обстановката и изражението на лицата на героите), която потребителите не биха могли да разберат от диалога. [Научете повече](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Някои елементи `<video>` не съдържат елемент `<track>` с `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Елементите `<video>` съдържат елемент `<track>` с `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "За най-добро изобразяване под iOS, когато потребителите добавят прогресивно уеб приложение (PWA) към началния екран, дефинирайте атрибут `apple-touch-icon`. Той трябва да сочи към непрозрачен квадратен PNG файл със страна от 192 (или 180) пиксела. [Научете повече](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Не осигурява валиден атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Атрибутът `apple-touch-icon-precomposed` не е актуален, препоръчва се `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Съдържа валиден атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Зареждането на тази страница се забавя от разширения за Chrome. Опитайте да я проверите в режим „инкогнито“ или от потребителски профил в Chrome без инсталирани разширения."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Проверка на скрипта"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Синтактичен анализ на скрипта"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Общо процесорно време"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Препоръчваме да намалите времето, прекарвано в синтактичен анализ, компилиране и изпълнение на JS. Използването на JS ресурси с по-малък размер може да помогне за това. [Научете повече](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Намалете времето за изпълнение на JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Време за изпълнение на JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Големите GIF файлове не са ефективни за показване на анимирано съдържание. Вместо това препоръчваме да използвате видеоклипове във формат MPEG4/WebM за анимации и PNG/WebP за статични изображения, за да намалите преноса на данни. [Научете повече](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Използвайте видеоформати за анимираното съдържание"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "За да намалите времето до интерактивност, препоръчваме скритите изображения и тези извън видимата част на екрана да се зареждат след всички критични ресурси. [Научете повече](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Отложете зареждането на изображенията извън видимата част на екрана"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ресурси блокират първото изобразяване на страницата ви. Препоръчваме да вградите критичните JS/CSS елементи и да отложите зареждането на всички некритични стилове или JS код. [Научете повече](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Елиминирайте ресурсите, които блокират изобразяването"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Мрежовите ресурси с голям размер струват пари на потребителите и са тясно свързани с бавното зареждане. [Научете повече](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Общият размер бе {totalBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Не използвайте мрежови ресурси с голям размер"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Не се използват мрежови ресурси с голям размер"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Минимизирането на файловете със CSS може да намали размера на мрежовите ресурси. [Научете повече](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Минимизирайте CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Минимизирането на файловете с JavaScript може да намали размера на ресурсите и времето за синтактичен анализ на скрипта. [Научете повече](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Минимизирайте JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Премахнете ненужните правила от стиловите листове и отложете зареждането на CSS кода, който не се използва за съдържанието на видимата на екрана част от страницата, за да намалите ненужния пренос на данни в мрежата. [Научете повече](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Премахнете неизползвания CSS код"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Премахнете неизползвания JavaScript, за да намалите преноса на данни при мрежовата активност."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Премахнете неизползвания JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Продължителното съхраняване в кеша може да ускори повторните посещения на страницата ви. [Научете повече](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Намерен е 1 ресурс}other{Намерени са # ресурса}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Използвайте ефективни правила за кеша, за да улесните показването на статичните активи"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Използват се ефективни правила за кеширане на статичните активи"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Оптимизираните изображения се зареждат по-бързо и използват по-малко мобилни данни. [Научете повече](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Кодирайте изображенията ефективно"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Показвайте правилно оразмерени изображения, за да пестите мобилни данни и да ускорите зареждането. [Научете повече](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Оразмерете изображенията правилно"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "При показването на текстови ресурси трябва да се използва компресиране (gzip, deflate или brotli), за да се намали общият пренос на данни. [Научете повече](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Активирайте компресирането на текста"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Графични формати, като JPEG 2000, JPEG XR и WebP, често осигуряват по-ефективно компресиране от PNG или JPEG. Това означава по-бързо изтегляне и използване на по-малко данни. [Научете повече](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Използвайте съвременни формати за показване на изображения"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ако ширината на съдържанието на приложението ви не съответства на тази на прозоречния изглед, приложението ви може да не е оптимизирано за мобилни екрани. [Научете повече](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Размерът на прозоречния изглед ({innerWidth} пкс) не съответства на размера на прозореца ({outerWidth} пкс)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Съдържанието не е оразмерено правилно за прозоречния изглед"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Съдържанието е оразмерено правилно за прозоречния изглед"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Веригите от критични заявки по-долу ви показват кои ресурси се зареждат с висок приоритет. За да ускорите зареждането на страницата, препоръчваме да скъсите веригите, да намалите размера за изтегляне на ресурсите или да отложите изтеглянето на ненужните от тях. [Научете повече](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Намерена е 1 верига}other{Намерени са # вериги}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Намалете дълбочината на критичните заявки"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Оттегляне/предупреждение"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Ред"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Оттеглените приложни програмни интерфейси (API) след време ще бъдат премахнати от браузъра. [Научете повече](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Открито бе 1 предупреждение}other{Открити бяха # предупреждения}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Използва оттеглени приложни програмни интерфейси (API)"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Избягва оттеглени API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Кешът на приложенията е оттеглен. [Научете повече](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Намерихме {AppCacheManifest}"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Използва кеша на приложенията"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Избягва кеша на приложенията"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Посочването на doctype не позволява на браузъра да премине в режим на обратна съвместимост. [Научете повече](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Името за doctype трябва да е низът `html` с малки букви"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Документът трябва да съдържа doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "За полето publicId се очакваше да бъде празен низ"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "За полето systemId се очакваше да бъде празен низ"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "На страницата липсва doctype на HTML, което задейства режим на обратна съвместимост"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Страницата съдържа doctype на HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Елемент"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Статистически данни"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Стойност"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Браузърните инженери препоръчват страниците да съдържат под 1500 елемента в DOM. Най-добре е йерархичната структура да не е по-дълбока от 32 нива и всеки родителски елемент да има по-малко от 60 дъщерни. Големият размер на DOM може да доведе до използване на повече памет, удължаване на [стиловите изчисления](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) и забавяне поради [преоформяне](https://developers.google.com/speed/articles/reflow). [Научете повече](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 елемент}other{# елемента}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Не използвайте DOM с твърде голям размер"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Максимална дълбочина на DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Общ брой елементи в DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Максимален брой дъщерни елементи"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Не се използва DOM с твърде голям размер"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Добавете `rel=\"noopener\"` или `rel=\"noreferrer\"` към връзките към външни сайтове, за да подобрите ефективността и да избегнете уязвимости в сигурността. [Научете повече](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Връзките към външни дестинации не са безопасни"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Връзките към външни дестинации са безопасни"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Не можахме да определим дестинацията за котвата ({anchorHTML}). Ако не се използва като хипервръзка, бихте могли да премахнете target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Потребителите се объркват или нямат доверие на сайтове, които искат да узнаят местоположението им без контекст. Вместо това бихте могли да обвържете заявката към действие на потребителя. [Научете повече](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Иска разрешение за геолокация при зареждането на страницата"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Избягва да иска разрешение за геолокация при зареждането на страницата"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Версия"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Всички библиотеки на JavaScript за предния слой, открити на страницата. [Научете повече](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Открити библиотеки на JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "За потребителите с бавни връзки външните скриптове, вмъквани динамично чрез `document.write()`, могат да забавят зареждането на страницата с десетки секунди. [Научете повече](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Използва `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Избягва `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Най-високо ниво на сериозност"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Версия на библиотеката"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Брой уязвимости"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Някои скриптове на трети страни може да съдържат известни уязвимости в сигурността, които лесно се откриват и използват от атакуващите. [Научете повече](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Открита е 1 уязвимост}other{Открити са # уязвимости}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Включва библиотеки на JavaScript за предния слой, съдържащи известни уязвимости в сигурността"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Високо"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Ниско"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Средно"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Избягва библиотеки на JavaScript за предния слой, съдържащи известни уязвимости в сигурността"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Потребителите се объркват или нямат доверие на сайтове, които искат да изпращат известия без контекст. Вместо това бихте могли да обвържете заявката към жестове на потребителя. [Научете повече](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Иска разрешение за известяване при зареждането на страницата"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Избягва да иска разрешение за известяване при зареждането на страницата"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Елементи с грешки"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Забраната на поставянето на пароли неутрализира добра практика за сигурност. [Научете повече](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Не позволява на потребителите да поставят в полетата за парола"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Разрешава на потребителите да поставят в полетата за парола"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Протокол"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 предлага много предимства спрямо HTTP/1.1, включително заглавки в двоичен формат, мултиплексиране и самостоятелно изпращане на информация от сървъра. [Научете повече](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 заявка не е обслужена през HTTP/2}other{# заявки не са обслужени през HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Не използва HTTP/2 за всичките си ресурси"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Използва HTTP/2 за собствените си ресурси"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "За да подобрите ефективността на страницата си при превъртане, бихте могли да означите като `passive` приемателите си на събития, свързани с докосване и с колелцето на мишката. [Научете повече](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Не използва пасивни приематели на събития за подобряване на ефективността при превъртане"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Използва пасивни приематели на събития за подобряване на ефективността при превъртане"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Описание"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Грешките, записани в конзолата, показват нерешени проблеми. Те може да се дължат на неуспешни заявки за мрежата и други проблеми в браузъра. [Научете повече](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "В конзолата бяха записани грешки в браузъра"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "В конзолата не бяха записани грешки в браузъра"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Използвайте функцията font-display на CSS, така че текстът да е видим за потребителите, докато уеб шрифтовете се зареждат. [Научете повече](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Уверете се, че текстът остава видим при зареждането на уеб шрифтовете"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Целият текст остава видим при зареждането на уеб шрифтовете"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse не успя да провери автоматично стойността на font-display за следния URL адрес: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Съотношение (действително)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Съотношение (показвано)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Размерите за показване на изображението трябва да съответстват на естественото съотношение. [Научете повече](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Показва изображения с неправилно съотношение"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Показва изображенията с правилно съотношение"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Информацията за размера на изображението е невалидна: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Браузърите могат проактивно да подканват потребителите да добавят приложението ви към началния екран, което може да повиши ангажираността. [Научете повече](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Манифестът на уеб приложението не отговаря на изискванията за възможност за инсталиране"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Манифестът на уеб приложението отговаря на изискванията за възможност за инсталиране"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Несигурен URL адрес"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Всички сайтове трябва да бъдат защитени с HTTPS, дори онези, които не работят с поверителни данни. HTTPS не позволява на външни лица да променят или подслушват комуникацията между приложението ви и потребителите и е задължително условие за HTTP/2 и множество нови приложни програмни интерфейси (API) за платформи в мрежата. [Научете повече](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Установена е 1 незащитена заявка}other{Установени са # незащитени заявки}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Не използва HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Използва HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Бързото зареждане на страниците през мобилни мрежи осигурява добра практическа работа за потребителите на мобилни устройства. [Научете повече](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Интерактивна след {timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Интерактивност при симулирана мобилна мрежа след {timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Страницата се зарежда прекалено бавно и не е интерактивна в рамките на 10 секунди. За да научите как да я подобрите, разгледайте възможностите и диагностичните данни в секцията „Ефективност“."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Страницата не се зарежда достатъчно бързо през мобилни мрежи"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Страницата се зарежда достатъчно бързо през мобилни мрежи"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Категория"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Препоръчваме да намалите времето, прекарвано в синтактичен анализ, компилиране и изпълнение на JS. Използването на JS ресурси с по-малък размер може да помогне за това. [Научете повече](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Сведете до минимум работата по основната нишка"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Работата по основната нишка е сведена до минимум"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "За да достигнат до възможно най-много потребители, сайтовете трябва да работят във всички основни браузъри. [Научете повече](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Сайтът работи в различни браузъри"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Oтделните страници трябва да могат да се свързват пряко чрез URL адрес, а URL адресите трябва да са уникални, за да се даде възможност за споделянето им в социалните медии. [Научете повече](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Всяка страница има URL адрес"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Дори когато мрежата е бавна, преходите при докосване на различни елементи трябва да са бързи – така у потребителите се създава усещане за добра ефективност. [Научете повече](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Преходите между страниците не създават усещане за забавяне на мрежата"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Приблизителното забавяне при входящо действие показва приблизително колко време (в милисекунди) е необходимо на приложението ви, за да реагира на входящо потребителско действие по време на най-натоварения 5-секунден период от зареждането на страницата. Ако забавянето е над 50 милисекунди, приложението ви може да се стори бавно на потребителите. [Научете повече](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Прогнозно забавяне при входящо действие"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Показателят „Първо изобразяване на съдържание (FCP)“ указва след колко време се изобразява първият текстов или графичен елемент. [Научете повече](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Първо изобразяване на съдържание"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Показателят „Първи момент на неактивност на процесора“ указва първия момент, в който основната нишка на страницата е достатъчно свободна, за да обработва входящи действия. [Научете повече](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Първи момент на неактивност на процесора"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Показателят „Първо значимо изобразяване“ измерва времето, за което основното съдържание на страницата става видимо. [Научете повече](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Първо значимо изобразяване"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Времето до интерактивност показва след колко време страницата става напълно интерактивна. [Научете повече](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Време до интерактивност"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Максималното потенциално забавяне при първото взаимодействие на потребителите е продължителността в милисекунди на най-времеемката задача. [Научете повече](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Макс. потенц. забавяне при 1. взаимодействие"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Индексът на скоростта показва колко бързо се постига визуална завършеност на страницата. [Научете повече](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Индекс на скоростта"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Сумата от всички интервали от време между FCP и „Време до интерактивност“, когато задачата е траела над 50 мсек, изразена в милисекунди."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Общо време на блокиране"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Времето за осъществяване на двупосочна комуникация в мрежата оказва голямо влияние върху ефективността. Ако двупосочната комуникация с източника отнема дълго време, това означава, че разположени по-близо до потребителя сървъри биха подобрили ефективността. [Научете повече](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Време за двупосочна комуникация в мрежата"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Забавянията на сървъра могат да повлияят на ефективността на уебсайта. Голямото забавяне при източника указва, че сървърът е претоварен или задният слой не работи достатъчно ефективно. [Научете повече](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Забавяния в задния слой на сървъра"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Файлът service worker дава възможност на уеб приложението ви да работи надеждно при непредсказуеми условия в мрежата. [Научете повече](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` не отговаря с код 200, когато е офлайн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` отговаря с код 200, когато е офлайн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse не можа да прочете `start_url` от манифеста. В резултат на това бе предположено, че URL адресът на документа изпълнява функцията на `start_url`. Съобщение за грешка: „{manifestWarning}“."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Надхвърля бюджета"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Поддържайте количеството и обема на мрежовите заявки под целевите стойности в посочения бюджет за ефективността. [Научете повече](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 заявка}other{# заявки}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Бюджет за ефективността"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ако вече сте настроили HTTPS, целият HTTP трафик трябва да се пренасочва към HTTPS, така че функциите за сигурност в мрежата да са активирани за всичките ви потребители. [Научете повече](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP трафикът не се пренасочва към HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP трафикът се пренасочва към HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Пренасочванията водят до допълнително забавяне на зареждането на страницата. [Научете повече](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Не използвайте пренасочвания през няколко страници"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "За да определите бюджети за количеството и размера на ресурсите на страницата, добавете файл budget.json. [Научете повече](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 заявка • {byteCount, number, bytes} КБ}other{# заявки • {byteCount, number, bytes} КБ}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Поддържайте малък брой заявки и неголям обем на прехвърляните данни"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Каноничните връзки указват кой URL адрес да се показва в резултатите от търсенето. [Научете повече](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Множество несъвместими URL адреси ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Сочи към друг домейн ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Невалиден URL адрес ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Сочи към местоположение с друг атрибут `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Относителен URL адрес ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Води до основния URL адрес (началната страница) на домейна вместо до еквивалентна страница със съдържание"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Документът няма валидна връзка от тип `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Документът има валиден атрибут `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Шрифтовете с размер под 12 пиксела са твърде малки и се налага посетителите от мобилни устройства да увеличат мащаба с разтваряне на пръсти, за да прочетат текста. Старайте се над 60% от текста на страницата да е с размер поне 12 пиксела. [Научете повече](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} от текста е четлив"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Текстът не е четлив, тъй като няма мета маркер viewport, оптимизиран за мобилни екрани."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} от текста е твърде малък (въз основа на извадка от {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "В документа не се използва шрифт с четлив размер"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "В документа се използва шрифт с четлив размер"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Връзките от типа hreflang указват на търсещите машини коя версия на страницата да бъде включена в резултатите от търсенето за даден език или регион. [Научете повече](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Документът няма валиден атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Документът има валиден атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Страниците с невалиден HTTP код на състоянието може да не бъдат индексирани правилно. [Научете повече](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Страницата има невалиден HTTP код на състоянието"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Страницата има валиден HTTP код на състоянието"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Търсещите машини не могат да включат страниците ви в резултатите от търсенето, ако нямат разрешение за обхождането им. [Научете повече](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Индексирането на страницата е блокирано"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Индексирането на страницата не е блокирано"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Описателният текст на връзките помага на търсещите машини да разберат съдържанието ви. [Научете повече](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Открита е 1 връзка}other{Открити са # връзки}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Текстът на връзките не е описателен"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Текстът на връзките е описателен"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Стартирайте [инструмента за тестване на структурирани данни](https://search.google.com/structured-data/testing-tool/) и [анализатора на структурирани данни](http://linter.structured-data.org/), за да проверите структурираните данни. [Научете повече](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Структурираните данни са валидни"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Мета описанията може да бъдат включени в резултатите от търсенето, за да се предостави сбито обобщение на съдържанието на страницата. [Научете повече](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Липсва текст на описанието."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Документът няма мета описание"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Документът има мета описание"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Търсещите машини не могат да индексират съдържание с приставки. Много устройства ограничават приставките или не ги поддържат. [Научете повече](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "В документа се използват приставки"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Използването на приставки се избягва в документа"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ако файлът ви robots.txt не е форматиран правилно, роботите може да не могат да разберат как искате да бъде обходен или индексиран уебсайтът ви. [Научете повече](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "При заявката за robots.txt бе върнат следният HTTP код на състоянието: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Открита е 1 грешка}other{Открити са # грешки}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse не успя да изтегли файла robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Файлът robots.txt не е валиден"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Файлът robots.txt е валиден"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Интерактивните елементи, като бутони и връзки, трябва да са достатъчно големи (48 x 48 пиксела) и с достатъчно пространство около тях, за да се докосват лесно, без да се застъпват с други елементи. [Научете повече](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} от целевите зони за докосване са оразмерени правилно"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Целевите зони за докосване са твърде малки, тъй като няма мета маркер viewport, оптимизиран за мобилни екрани"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Целевите зони за докосване не са оразмерени правилно"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Припокриваща се целева зона"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Целева зона за докосване"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Целевите зони за докосване са оразмерени правилно"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service worker е технологията, която дава възможност на приложението ви да използва много от функциите на прогресивните уеб приложения (PWA), като например работа офлайн, добавяне към началния екран и насочени известия. [Научете повече](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Тази страница е контролирана от service worker, но не бе намерен параметър `start_url`, тъй като при синтактичния анализ бе установено, че манифестът не е във валиден формат JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Тази страница се контролира от файл service worker, но `start_url` ({startUrl}) не е в обхвата му ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Тази страница се контролира от service worker, но не бе намерен параметър `start_url`, тъй като не бе извлечен манифест."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Този източник има един или повече файлове service worker, но страницата ({pageUrl}) не е в обхвата им."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Няма регистриран service worker, който контролира страницата и `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Регистриран е service worker, който контролира страницата и `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Тематичният първоначален екран гарантира висококачествена практическа работа, когато потребителите стартират приложението ви от началния екран. [Научете повече](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Няма персонализиран първоначален екран"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Има персонализиран първоначален екран"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Адресната лента на браузъра може да бъде тематична, за да съответства на сайта ви. [Научете повече](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Не е зададен тематичен цвят за адресната лента."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Зададен е тематичен цвят за адресната лента."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Време на блокиране на основната нишка"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Трета страна"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Кодът от трети страни може сериозно да повлияе върху скоростта на зареждане. Ограничете броя на излишните доставчици трети страни и опитайте да зареждате кода от трети страни, след като основното зареждане на страницата ви е приключило. [Научете повече](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Код от трети страни блокира основната нишка за {timeInMs, number, milliseconds} мсек"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Намалете влиянието на кода от трети страни"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Използване на код от трети страни"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Показателят „Време до първия байт“ указва след колко време сървърът изпраща отговор. [Научете повече](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "За основния документ бяха необходими {timeInMs, number, milliseconds} мсек"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Намалете времето за отговор от сървъра (време до първия байт)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Сървърът отговаря бързо (време до първия байт)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Продължителност"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Начален час"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Тип"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Препоръчваме да използвате API за разбивка на потребителските времена за приложението си, за да измервате действителната му ефективност по време на ключови аспекти от практическата работа на потребителите. [Научете повече](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 потребителско време}other{# потребителски времена}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Точки и измервания в разбивката на потребителските времена"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Намерен бе елемент <link> за предварително свързване за {securityOrigin}, който обаче не бе използван от браузъра. Проверете дали използвате правилно атрибута `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Препоръчваме да добавите подсказки `preconnect` или `dns-prefetch` за ресурсите с цел ранно установяване на връзка с важни източници от трети страни. [Научете повече](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Осигурете предварително свързване с необходимите източници"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Намерен бе елемент <link> за предварително зареждане за {preloadURL}, който обаче не бе използван от браузъра. Проверете дали използвате правилно атрибута `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Препоръчваме да използвате `<link rel=preload>`, за да укажете по-ранно извличане на ресурсите, които понастоящем се заявяват на по-късен етап от зареждането на страницата. [Научете повече](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Задайте ключовите заявки да се зареждат предварително"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Добавете маркер `<meta name=\"viewport\">`, за да оптимизирате приложението си за мобилни екрани. [Научете повече](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Не бе намерен маркер `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Няма маркер `<meta name=\"viewport\">` с атрибут `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Има маркер `<meta name=\"viewport\">` с атрибут `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Когато JavaScript е деактивиран, в приложението ви трябва да се показва някакво съдържание, дори да е само предупреждение към потребителя, че за използване на приложението се изисква JavaScript. [Научете повече](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "В основната част на страницата трябва да се изобразява съдържание, ако скриптовете ѝ не могат да бъдат заредени."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Не предоставя резервно съдържание, когато JavaScript не е налице"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Показва се част от съдържанието, когато JavaScript не е налице"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ако създавате прогресивно уеб приложение (PWA), добре е да използвате service worker, за да може то да работи офлайн. [Научете повече](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Текущата страница не отговаря с код 200, когато е офлайн"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Текущата страница отговаря с код 200, когато е офлайн"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Страницата може да не се зарежда офлайн, тъй като тестовият ви URL адрес ({requested}) бе пренасочен към {final}. Опитайте се да тествате втория URL адрес директно."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Това са възможности за подобряване на използването на ARIA в приложението ви. Така може да подобрите практическата работа за потребителите на помощни технологии, като например екранни четци."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Това са възможности да предоставите алтернативно съдържание за аудио- и видеоелементите. Така може да подобрите практическата работа за потребители със слухови или зрителни нарушения."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Аудио и видео"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Тези елементи открояват често използвани най-добри практики за достъпност."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Най-добри практики"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Тези проверки открояват възможности за [подобряване на достъпността на уеб приложението ви](https://developers.google.com/web/fundamentals/accessibility). Само определени проблеми с достъпността могат да бъдат открити автоматично. Затова ръчното тестване също е препоръчително."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Тези проверки покриват области, които са извън обхвата на автоматичните инструменти за тестване. Научете повече в ръководството ни за [извършване на преглед на достъпността](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Достъпност"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Това са възможности за подобряване на четливостта на съдържанието ви."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Контраст"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Това са възможности да направите съдържанието си по-разбираемо за потребителите, използващи други езици."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Интернационализация и локализация"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Това са възможности за подобряване на семантиката на контролите в приложението ви. Така може да подобрите практическата работа за потребителите на помощни технологии, като например екранни четци."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Имена и етикети"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Това са възможности за подобряване на навигирането с клавиатура в приложението ви."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Навигация"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Това са възможности да улесните четенето на данни в таблици или списъци посредством помощни технологии, като например екранни четци."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Таблици и списъци"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Най-добри практики"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Бюджетите за ефективността задават стандарти за ефективността на сайта ви."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Бюджети"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Повече информация за ефективността на приложението ви. Тези стойности не се [отразяват директно](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) върху рейтинга за ефективността."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Диагностика"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Най-критичният аспект на ефективността е времето, за което пикселите се изобразяват на екрана. Ключови показатели: първо изобразяване на съдържание, първо значимо изобразяване"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Подобрения, свързани с първото изобразяване"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Тези предложения може да ускорят зареждането на страницата ви. Те не се [отразяват директно](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) върху рейтинга за ефективността."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Възможности"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Показатели"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Подобрете зареждането като цяло, така че страницата да реагира бързо и да е готова за използване възможно най-скоро. Ключови показатели: време до интерактивност, индекс на скоростта"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Цялостни подобрения"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Ефективност"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Тези проверки са свързани с аспектите на прогресивните уеб приложения (PWA). [Научете повече](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Тези проверки са задължителни според отправния [контролен списък за PWA](https://developers.google.com/web/progressive-web-apps/checklist), но не се извършват автоматично от Lighthouse. Те не се отразяват на резултата ви, но е важно да ги потвърдите ръчно."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Прогресивно уеб приложение (PWA)"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Бързина и надеждност"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Възможност за инсталиране"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Оптимизиране за PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Тези проверки показват дали страницата ви е оптимизирана така, че да се класира в резултатите от търсещите машини. Lighthouse не проверява някои допълнителни фактори, които може да повлияят на класирането в резултатите от търсенето. [Научете повече](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Стартирайте тези допълнителни инструменти на сайта си, за да проверите дали е съобразен с други най-добри практики за SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Форматирайте HTML кода си по начин, който дава възможност на роботите да разберат по-добре съдържанието на приложението ви."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Най-добри практики за съдържанието"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "За да се показва приложението ви в резултатите от търсенето, роботите се нуждаят от достъп до него."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Обхождане и индексиране"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Уверете се, че страниците ви са удобни за мобилни устройства, така че да не е необходимо потребителите да събират пръсти или да увеличават мащаба, за да прочетат съдържанието. [Научете повече](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Удобство за мобилни устройства"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Време на валидност на кеша"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Местоположение"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Име"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Заявки"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Тип ресурс"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Размер"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Прекарано време"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Размер на прехвърлянето"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL адрес"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Потенциална икономия"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Потенциална икономия"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Потенциално спестяване на {wastedBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Потенциално спестяване на {wastedMs, number, milliseconds} мсек"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Документ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Шрифт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Изображение"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Мултимедия"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} мсек"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Друго"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Скрипт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Стилов лист"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Трети страни"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Общо"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Нещо се обърка при записването на трасирането за зареждането на страницата ви. Моля, стартирайте отново Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Времето за изчакване изтече при първоначалното свързване с протокола за инструмента за откриване и отстраняване на грешки."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome не събра екранни снимки при зареждането на страницата. Моля, уверете се, че на нея има видимо съдържание, и опитайте отново да стартирате Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS сървърите не можаха да преобразуват предоставения домейн."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "В задължителния механизъм за събиране на {artifactName} възникна грешка: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Възникна вътрешна грешка в Chrome. Моля, рестартирайте браузъра и опитайте отново да стартирате Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Задължителният механизъм за събиране на {artifactName} не се изпълни."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse не успя надеждно да зареди заявената от вас страница. Уверете се, че тествате точния URL адрес и че сървърът отговаря правилно на всички заявки."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse не успя надеждно да зареди заявения от вас URL адрес, тъй като страницата спря да реагира."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Посоченият от вас URL адрес няма валиден сертификат за сигурност. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome не допусна зареждане на страница със заставка. Уверете се, че тествате точния URL адрес и че сървърът отговаря правилно на всички заявки."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse не успя надеждно да зареди заявената от вас страница. Уверете се, че тествате точния URL адрес и че сървърът отговаря правилно на всички заявки. (Подробности: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse не успя надеждно да зареди заявената от вас страница. Уверете се, че тествате точния URL адрес и че сървърът отговаря правилно на всички заявки. (Код на състоянието: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Зареждането на страницата бе твърде бавно. Моля, използвайте посочените в отчета възможности за ускоряване на зареждането ѝ, след което опитайте отново да стартирате Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Предвиденото време за изчакване на отговор от протокола DevTools бе превишено. (Метод: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Предвиденото време за извличане на съдържанието на ресурсите бе превишено"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Предоставеният от вас URL адрес изглежда невалиден."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Показване на проверките"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Първоначална навигация"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Максимално забавяне в критичния път:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Грешка!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Грешка в отчета: няма информация за проверката"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Данни от контролиран тест"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Анализът с [Lighthouse](https://developers.google.com/web/tools/lighthouse/) на текущата страница бе извършен през емулирана мобилна мрежа. Стойностите са приблизителни и може да варират."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Допълнителни елементи, които да проверите ръчно"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Не е приложимо"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Възможност"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Прогнозна икономия"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Успешно преминати проверки"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Свиване на фрагмента"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Разгъване на фрагмента"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Показване на ресурсите от трети страни"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Възникнаха проблеми при изготвянето на този отчет от Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Стойностите са приблизителни и може да варират. Рейтингът за ефективността [се базира само на тези показатели](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Проверките бяха преминати успешно, но има предупреждения"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Предупреждения: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Добре е да качите GIF файла си в услуга, която ще даде възможност да бъде вграден като видеоклип с HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Инсталирайте [приставка за WordPress за забавено зареждане](https://wordpress.org/plugins/search/lazy+load/), която дава възможност за отлагане на зареждането на изображенията извън видимата част на екрана, или преминете към тема с такава функционалност. Можете също да използвате [приставката за AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Има различни приставки за WordPress, с чиято помощ можете [да вградите важни активи](https://wordpress.org/plugins/search/critical+css/) или [да отложите зареждането на не толкова важни ресурси](https://wordpress.org/plugins/search/defer+css+javascript/). Имайте предвид, че оптимизациите, извършвани чрез тези приставки, може да възпрепятстват работата на функциите на темата ви или други приставки, така че вероятно ще се наложи да промените кода."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Времето за реакция на сървъра зависи от спецификациите му, темите и приставките. Добре е да намерите по-оптимизирана тема, внимателно да изберете приставка за оптимизиране и/или да надстроите сървъра си."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Обмислете възможността да показвате извадки в списъците си с публикации (напр. чрез маркера more), да намалите броя на публикациите, извеждани на дадена страница, да разделите дългите публикации на няколко страници или да използвате приставка, която да забави зареждането на коментарите."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Има различни [приставки за WordPress](https://wordpress.org/plugins/search/minify+css/), които могат да подобрят скоростта на сайта ви чрез обединяване, минимизиране и компресиране на стиловете. Добре е също при възможност да използвате компилиране, за да извършите това минимизиране предварително."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Има различни [приставки за WordPress](https://wordpress.org/plugins/search/minify+javascript/), които могат да подобрят скоростта на сайта ви чрез обединяване, минимизиране и компресиране на скриптовете. Добре е също при възможност да използвате компилиране, за да извършите това минимизиране предварително."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Добре е да намалите броя на [приставките за WordPress](https://wordpress.org/plugins/), които зареждат неизползван CSS код в страницата ви, или да ги замените с други. За да откриете приставките, които добавят ненужен CSS код, стартирайте инструмента за [покритие на кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в Chrome DevTools. Можете да намерите проблемната тема/приставка в URL адреса на листа със стилове. Търсете приставки с много листове със стилове в списъка, за които преобладава червеният цвят в диаграмата на инструмента. Даден лист със стилове трябва да бъде поставен в опашката на приставка само ако действително се използва в страницата."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Добре е да намалите броя на [приставките за WordPress](https://wordpress.org/plugins/), които зареждат неизползван JavaScript код в страницата ви, или да ги замените с други. За да откриете приставките, които добавят ненужен JS код, стартирайте инструмента за [покритие на кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в Chrome DevTools. Можете да намерите проблемната тема/приставка в URL адреса на скрипта. Търсете приставки с много скриптове в списъка, за които преобладава червеният цвят в диаграмата на инструмента. Даден скрипт трябва да бъде поставен в опашката на приставка само ако действително се използва в страницата."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Прочетете за [кеширането в браузъра при WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Добре е да използвате [приставка за WordPress за оптимизиране на изображенията](https://wordpress.org/plugins/search/optimize+images/), която компресира графичните ви файлове, като същевременно запазва качеството им."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Качвайте изображенията директно чрез [мултимедийната библиотека](https://codex.wordpress.org/Media_Library_Screen), за да разполагате с графични файлове с необходимите размери, и след това ги вмъквайте от библиотеката или използвайте приспособлението за изображения, така че да се използват файловете с оптимални размери (включително за адаптивните гранични точки). Избягвайте използването на пълноразмерни изображения (`Full Size`), освен ако размерите са подходящи за съответното предназначение. [Научете повече](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Можете да активирате компресирането на текста в конфигурацията на уеб сървъра си."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Добре е да използвате [приставка](https://wordpress.org/plugins/search/convert+webp/) или услуга за автоматично преобразуване на качените изображения в оптималния формат."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ca.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ca.json
new file mode 100644
index 00000000000..78c72aed431
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ca.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Les tecles d'accés permeten als usuaris posar el focus ràpidament en una part de la pàgina. Perquè es puguin desplaçar correctament, cada tecla d'accés ha de ser única. [Obtén més informació](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Els valors de l'atribut `[accesskey]` no són únics"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Els valors de l'atribut `[accesskey]` són únics"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Cada element `role` d'ARIA admet un subconjunt específic d'atributs `aria-*`. Si no coincideixen, els atributs `aria-*` queden invalidats. [Obtén més informació](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Els atributs `[aria-*]` no coincideixen amb les seves funcions"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Els atributs `[aria-*]` coincideixen amb les seves funcions"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Algunes funcions d'ARIA tenen atributs obligatoris que descriuen l'estat de l'element als lectors de pantalla. [Obtén més informació](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Els atributs `[role]` no tenen tots els atributs `[aria-*]` obligatoris"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Els elements amb l'atribut `[role]` tenen tots els atributs `[aria-*]` obligatoris"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Algunes funcions dels elements ARIA superiors han d'incloure funcions concretes dels elements secundaris perquè puguin dur a terme les funcions d'accessibilitat per a les quals s'han dissenyat. [Obtén més informació](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Els elements amb un `[role]` ARIA que requereixen que els elements secundaris continguin un atribut `[role]` específic no tenen alguns o tots els elements secundaris requerits."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Els elements amb un ARIA `[role]` que requereixen que els elements secundaris continguin un atribut `[role]` específic tenen tots els elements secundaris requerits."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Les funcions de determinats elements superiors han d'incloure algunes funcions dels elements ARIA secundaris perquè puguin dur a terme les funcions d'accessibilitat per a les quals s'han dissenyat. [Obtén més informació](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Els atributs `[role]` no s'inclouen a l'element superior obligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Els atributs `[role]` s'inclouen a l'element superior obligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Les funcions dels elements ARIA han de tenir valors vàlids perquè puguin dur a terme les funcions d'accessibilitat per a les quals s'han dissenyat. [Obtén més informació](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Els valors de l'atribut `[role]` no són vàlids"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Els valors de l'atribut `[role]` són vàlids"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Les tecnologies d'assistència, com ara els lectors de pantalla, no poden interpretar els atributs ARIA que tenen valors que no són vàlids. [Obtén més informació](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Els atributs `[aria-*]` no tenen valors vàlids"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Els atributs `[aria-*]` tenen valors vàlids"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Les tecnologies d'assistència, com ara els lectors de pantalla, no poden interpretar els atributs ARIA que tenen noms que no són vàlids. [Obtén més informació](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Els atributs `[aria-*]` no són vàlids o estan mal escrits"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Els atributs `[aria-*]` són vàlids i estan ben escrits"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Els subtítols permeten que els usuaris sords o amb discapacitat auditiva utilitzin els elements d'àudio. Així obtenen informació essencial, com ara qui parla, què diu i altres dades no verbals. [Obtén més informació](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Als elements `<audio>` els falta un element `<track>` amb `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Els elements `<audio>` contenen un element `<track>` amb `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elements amb errors"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Si un botó no té un nom accessible, els lectors de pantalla el llegeixen com a \"botó\", de manera que queda inservible per als usuaris que depenen d'aquesta tecnologia. [Obtén més informació](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Els botons no tenen un nom accessible"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Els botons tenen noms accessibles"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Si s'afegeixen maneres d'evitar el contingut repetitiu, els usuaris del teclat poden navegar per la pàgina de manera més eficaç. [Obtén més informació](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "La pàgina no conté un encapçalament, un enllaç d'omissió o una regió de referència"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "La pàgina conté un encapçalament, un enllaç d'omissió o una regió de referència"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "El text amb contrast baix resulta difícil o impossible de llegir per a molts usuaris. [Obtén més informació](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "La relació de contrast dels colors de primer i de segon pla no és suficient."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "La relació de contrast dels colors de primer i de segon pla és suficient"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Si el marcatge de les llistes de definició no és correcte, és possible que els lectors de pantalla sonin de manera confusa o inexacta. [Obtén més informació](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Els elements `<dl>` no contenen només grups de `<dt>` i `<dd>` ordenats correctament, o bé elements `<script>` o `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Els elements `<dl>` contenen només grups de `<dt>` i `<dd>` ordenats correctament, o bé elements `<script>` o `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Els elements de la llista de definicions (`<dt>` i `<dd>`) han d'estar tancats dins d'un element `<dl>` superior per garantir que els lectors de pantalla els puguin pronunciar correctament. [Obtén més informació](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Els elements de la llista de definicions estan tancats entre elements `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Els elements de la llista de definicions estan tancats entre elements `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "El títol proporciona als usuaris de lectors de pantalla un resum de la pàgina. A més, els usuaris de motors de cerca depenen en gran mesura d'aquest títol per determinar si una pàgina és rellevant per a la seva cerca. [Obtén més informació](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "El document no té cap element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "El document té un element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "El valor d'un atribut d'identificador ha de ser únic per impedir que les tecnologies d'assistència no passin per alt altres instàncies. [Obtén més informació](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Els atributs `[id]` de la pàgina no són únics"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Els atributs `[id]` de la pàgina són únics"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Els usuaris de lectors de pantalla depenen dels títols dels marcs perquè en descriguin el contingut. [Obtén més informació](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Els elements `<frame>` o `<iframe>` no tenen títol"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Els elements `<frame>` o `<iframe>` tenen un títol"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Si en una pàgina no s'especifica un atribut d'idioma, els lectors de pantalla suposen que la pàgina està escrita en l'idioma predeterminat que l'usuari ha triat en configurar el lector de pantalla. Si està escrita en un altre idioma, és possible que el lector de pantalla no en llegeixi el text correctament. [Obtén més informació](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "L'element `<html>` no té un atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "L'element `<html>` té un atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Si especifiques un [idioma vàlid d'acord amb l'estàndard BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), ajudes a fer que els lectors de pantalla pronunciïn el text correctament. [Obtén més informació](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "L'element `<html>` no té un valor vàlid per a l'atribut `[lang]` corresponent."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "L'element `<html>` té un valor vàlid per a l'atribut `[lang]` corresponent"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Els elements informatius han d'utilitzar text alternatiu que sigui breu i descriptiu. Els elements decoratius es poden ignorar amb un atribut alt buit. [Obtén més informació](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Els elements d'imatge no tenen atributs `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Els elements d'imatge tenen atributs `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Si s'utilitza una imatge per al botó `<input>`, el text alternatiu pot ajudar els usuaris dels lectors de pantalla a entendre la funció del botó. [Obtén més informació](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Els elements `<input type=\"image\">` no tenen text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Els elements `<input type=\"image\">` tenen text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Les etiquetes garanteixen que les tecnologies d'assistència, com ara els lectors de pantalla, puguin llegir correctament els controls dels formularis. [Obtén més informació](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Els elements de formulari no tenen etiquetes associades"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Els elements de formulari tenen etiquetes associades"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Una taula que s'utilitza per al disseny no pot incloure elements de dades, com ara un superíndex, elements de subtítols o l'atribut de resum, ja que es pot crear una experiència confusa per als usuaris de lectors de pantalla. [Obtén més informació](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Els elements `<table>` per a presentacions no eviten utilitzar `<th>`, `<caption>` ni l'atribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Els elements `<table>` per a presentacions eviten utilitzar `<th>`, `<caption>` o l'atribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Si el text dels enllaços (així com el text alternatiu per a les imatges, quan s'utilitzen com a enllaços) és discernible, únic i permet que s'hi posi el focus, millora l'experiència de navegació dels usuaris de lectors de pantalla. [Obtén més informació](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Els enllaços no tenen noms que es puguin distingir"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Els enllaços tenen noms que es poden distingir"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Els lectors de pantalla tenen una manera específica de llegir les llistes. Estructurar-les correctament millora la manera com els lectors de pantalla sonen. [Obtén més informació](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Les llistes no contenen només elements`<li>` i elements que admeten scripts (`<script>` i `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Les llistes contenen només elements `<li>` i elements que admeten scripts (`<script>` i `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Els lectors de pantalla requereixen que els elements de llista (`<li>`) estiguin inclosos dins d'un element `<ul>` o `<ol>` superior per poder llegir-los correctament. [Obtén més informació](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Alguns elements de llista (`<li>`) no estan inclosos entre elements `<ul>` o `<ol>` superiors."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Alguns elements de llista (`<li>`) estan inclosos entre elements `<ul>` o `<ol>` superiors"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Els usuaris no esperen que una pàgina s'actualitzi automàticament. En fer-ho, el focus torna a la part superior de la pàgina i els usuaris es poden sentir frustrats i confosos. [Obtén més informació](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "El document utilitza la metaetiqueta `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "El document no utilitza `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Desactivar el zoom pot ser un problema per als usuaris amb visió reduïda que necessiten ampliar la pantalla per veure correctament el contingut d'una pàgina web. [Obtén més informació](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "L'atribut `[user-scalable=\"no\"]` s'utilitza a l'element `<meta name=\"viewport\">` o l'atribut `[maximum-scale]` és inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "L'atribut `[user-scalable=\"no\"]` no s'utilitza a l'element `<meta name=\"viewport\">` i l'atribut `[maximum-scale]` no és inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Els lectors de pantalla no poden traduir contingut que no sigui text. Si afegeixes text alternatiu als elements `<object>`, ajudes els lectors de pantalla a transmetre el significat als usuaris. [Obtén més informació](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Els elements `<object>` no tenen text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Els elements `<object>` tenen text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Un valor superior a 0 implica una ordenació explícita de navegació. Tècnicament és vàlid, però sol suposar experiències frustrants per als usuaris que depenen de les tecnologies d'assistència. [Obtén més informació](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Alguns elements tenen un valor `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Cap element no té un valor `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Els lectors de pantalla inclouen funcions perquè sigui més fàcil navegar per les taules. Assegura't que les cel·les `<td>` que fan servir l'atribut `[headers]` només facin referència a altres cel·les de la mateixa taula. Això pot millorar l'experiència dels usuaris de lectors de pantalla. [Obtén més informació](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Les cel·les d'un element `<table>` que fan servir l'atribut `[headers]` fan referència a un element `id` que no és a la mateixa taula."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Les cel·les d'un element `<table>` que fan servir l'atribut `[headers]` fan referència a cel·les de taula incloses a la mateixa taula."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Els lectors de pantalla inclouen funcions perquè sigui més fàcil navegar per les taules. Assegura't que els encapçalaments de les taules facin sempre referència a un conjunt de cel·les. Això pot millorar l'experiència dels usuaris de lectors de pantalla. [Obtén més informació](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Els elements `<th>` i els que inclouen l'atribut `[role=\"columnheader\"/\"rowheader\"]` no tenen les cel·les de dades que descriuen."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Els elements `<th>` i els que inclouen l'atribut `[role=\"columnheader\"/\"rowheader\"]` tenen les cel·les de dades que descriuen."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Si especifiques un [idioma vàlid d'acord amb l'estàndard BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) als elements, permets que els lectors de pantalla pronunciïn el text correctament. [Obtén més informació](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Els atributs `[lang]` no tenen un valor vàlid"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Els atributs `[lang]` tenen un valor vàlid"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Si un vídeo ofereix subtítols, permet que els usuaris sords o amb discapacitat auditiva accedeixin a la informació més fàcilment. [Obtén més informació](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Els elements `<video>` no contenen cap element `<track>` amb `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Els elements `<video>` contenen un element `<track>` amb `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Les audiodescripcions proporcionen informació rellevant dels vídeos que els diàlegs no poden oferir, com ara les expressions facials i les escenes. [Obtén més informació](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Els elements `<video>` no contenen cap element `<track>` amb `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Els elements `<video>` contenen un element `<track>` amb `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Perquè l'aspecte a iOS sigui l'ideal quan els usuaris afegeixin una aplicació web progressiva a la pantalla d'inici, defineix un atribut `apple-touch-icon`. Ha de dirigir a una imatge PNG quadrada de 192 píxels o de 180 píxels que no sigui transparent. [Obtén més informació](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "No conté un atribut `apple-touch-icon` vàlid"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "L'atribut `apple-touch-icon-precomposed` no està actualitzat. És preferible l'atribut `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Proporciona una `apple-touch-icon` vàlida"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Les extensions de Chrome han afectat negativament el rendiment de càrrega de la pàgina. Audita la pàgina en mode d'incògnit o des d'un perfil de Chrome sense extensions."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Avaluació de scripts"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Anàlisi de scripts"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Temps total de la CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Et recomanem que redueixis el temps dedicat a analitzar, compilar i executar JavaScript. Et pot ajudar utilitzar càrregues útils de JavaScript més petites. [Obtén més informació](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Redueix el temps d'execució de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Temps d'execució de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Els GIF grans no són eficients per publicar contingut animat. A fi d'estalviar bytes a la xarxa, pots substituir els GIF per vídeos MPEG4/WebM en el cas de les animacions i per PNG/WebP en el cas de les imatges estàtiques. [Més informació](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Utilitza formats de vídeo per al contingut animat"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Et recomanem que utilitzis la càrrega diferida de les imatges amagades i que no es mostren a la pantalla un cop s'acabin de carregar tots els recursos essencials a fi de reduir el temps necessari perquè la pàgina sigui interactiva. [Obtén més informació](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Ajorna les imatges fora de pantalla"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Els recursos estan bloquejant la primera renderització de la pàgina. Et recomanem que publiquis els fitxers JavaScript o CSS inserits que siguin essencials i ajornis tots els estils i els fitxers JavaScript que no ho siguin. [Obtén més informació](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimina els recursos que bloquegen la renderització"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Si la càrrega útil de la xarxa és molt gran, els usuaris consumeixen més dades mòbils i els temps de càrrega són més llargs. [Obtén més informació](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Mida total: {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evita càrregues útils de xarxa enormes"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evita càrregues útils de xarxa enormes"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Reduir els fitxers CSS pot disminuir les mides de càrrega útil a la xarxa. [Obtén més informació](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Redueix els CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Reduir els fitxers JavaScript pot disminuir les mides de càrrega i els temps d'anàlisi de scripts. [Obtén més informació](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Redueix els fitxers JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Per reduir els bytes que es consumeixen de manera innecessària durant l'activitat de la xarxa, suprimeix dels fulls d'estil les regles que no s'utilitzin i ajorna la càrrega dels CSS que no es facin servir per al contingut de la part superior visible. [Obtén més informació](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Suprimeix els CSS no utilitzats"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Suprimeix els fitxers JavaScript que no s'utilitzen per reduir els bytes que es consumeixen durant l'activitat de la xarxa."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Suprimeix els fitxers JavaScript no utilitzats"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Si la memòria cau té una vida llarga, es poden accelerar les visites repetides a la teva pàgina. [Obtén més informació](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 recurs}other{S'han trobat # recursos}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Publica recursos estàtics amb una política de memòria cau eficient"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Utilitza una política de memòria cau eficient per als recursos estàtics"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Les imatges optimitzades es carreguen més ràpidament i utilitzen menys dades mòbils. [Obtén més informació](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifica les imatges amb eficiència"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Publica imatges amb la mida correcta per estalviar dades mòbils i millorar el temps de càrrega. [Obtén més informació](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Adapta la mida de les imatges"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Els recursos basats en text s'han de publicar comprimits (gzip, deflate o brotli) per minimitzar el total de bytes a la xarxa. [Obtén més informació](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Activa la compressió de text"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Els formats d'imatge com JPEG 2000, JPEG XR i WebP solen oferir millors resultats de compressió que PNG o JPEG. Això implica baixades més ràpides i menys consum de dades. [Obtén més informació](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Publica imatges en format d'última generació"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Si l'amplada del contingut de l'aplicació no coincideix amb l'amplada de la finestra gràfica, és possible que l'aplicació no s'optimitzi per a pantalles de dispositius mòbils. [Obtén més informació](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "La mida de la finestra gràfica ({innerWidth} píxels) no coincideix amb la mida de la finestra ({outerWidth} píxels)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "El contingut no té la mida correcta per a la finestra gràfica"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "El contingut té la mida correcta per a la finestra gràfica"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Les cadenes de sol·licituds essencials de sota et mostren quins recursos es carreguen amb prioritat alta. Et recomanem que escurcis les cadenes, redueixis la mida de baixada dels recursos o ajornis la baixada de recursos innecessaris per millorar la càrrega de pàgines. [Obtén més informació](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 cadena}other{S'han trobat # cadenes}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimitza la profunditat de les sol·licituds crítiques"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Desactivació/advertiment"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Línia"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Les API obsoletes s'acabaran suprimint del navegador. [Obtén més informació](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 advertiment}other{S'han trobat # advertiments}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Utilitza API obsoletes"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita les API obsoletes"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "La memòria cau de l'aplicació està obsoleta. [Obtén més informació](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "S'ha trobat \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Utilitza la memòria cau de l'aplicació"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita la memòria cau de l'aplicació"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Especificar un tipus de document impedeix que el navegador canviï a mode Quirks. [Obtén més informació](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "El nom del tipus de document ha de ser la cadena en minúscules `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "El document ha de contenir un tipus de document"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Està previst que el camp publicId sigui una cadena buida"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Està previst que el camp systemId sigui una cadena buida"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "La pàgina no té el tipus de document HTML i, per tant, activa el mode Quirks"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "La pàgina té el tipus de document HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Estadística"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Els enginyers de navegadors recomanen que les pàgines continguin menys d'uns 1.500 elements DOM. La situació ideal és una profunditat d'arbre de menys de 32 elements i de menys de 60 elements superiors o secundaris. Un DOM gran pot augmentar l'ús de la memòria, provocar [càlculs d'estil](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) més llargs i produir [reinicis de reflux del disseny](https://developers.google.com/speed/articles/reflow) costosos. [Obtén més informació](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{Un element}other{# elements}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evita una mida de DOM excessiva"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profunditat màxima de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total d'elements de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Nombre màxim d'elements secundaris"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evita una mida excessiva de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Objectiu"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Afegeix `rel=\"noopener\"` o `rel=\"noreferrer\"` a qualsevol enllaç extern per millorar-ne el rendiment i evitar vulnerabilitats de seguretat. [Obtén més informació](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Els enllaços a destinacions de diversos orígens no són segurs"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Els enllaços a destinacions de diversos orígens són segurs"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "No es pot determinar la destinació de l'ancoratge ({anchorHTML}). Si no s'utilitza com a enllaç, et recomanem que suprimeixis target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Els usuaris reaccionen amb desconfiança i desconcert davant dels llocs web que els sol·liciten la ubicació sense context. Et recomanem que vinculis la sol·licitud a una acció de l'usuari. [Obtén més informació](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Sol·licita el permís de geolocalització en carregar la pàgina"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita sol·licitar el permís de geolocalització en carregar la pàgina"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versió"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Totes les biblioteques de JavaScript d'interfície detectades a la pàgina. [Obtén més informació](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Biblioteques de JavaScript detectades"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Per als usuaris amb connexions lentes, els scripts externs inserits dinàmicament mitjançant `document.write()` poden retardar la càrrega de la pàgina unes dècimes de segon. [Obtén més informació](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Utilitza `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evita `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Gravetat més alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versió de la biblioteca"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Recompte de vulnerabilitats"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Alguns scripts de tercers poden contenir vulnerabilitats de seguretat que els atacants identifiquen i exploten fàcilment. [Obtén més informació](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha detectat 1 vulnerabilitat}other{S'han detectat # vulnerabilitats}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Inclou biblioteques de JavaScript d'interfície amb vulnerabilitats de seguretat conegudes"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Baixa"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Mitjana"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita les biblioteques de JavaScript d'interfície amb vulnerabilitats de seguretat conegudes"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Els usuaris reaccionen amb desconfiança i desconcert davant dels llocs web que sol·liciten enviar notificacions sense context. Et recomanem que vinculis la sol·licitud als gestos de l'usuari. [Obtén més informació](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Sol·licita el permís de notificació en carregar la pàgina"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita sol·licitar el permís de notificació en carregar la pàgina"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elements amb errors"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Impedir enganxar la contrasenya va en detriment d'una bona política de seguretat. [Obtén més informació](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Evita que els usuaris enganxin contingut als camps de contrasenya"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permet que els usuaris enganxin contingut als camps de contrasenya"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ofereix molts avantatges respecte a HTTP/1.1, com ara capçaleres binàries, multiplexatge i tramesa automàtica de servidor. [Obtén més informació](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{No s'ha atès 1 sol·licitud mitjançant HTTP/2}other{No s'han atès # sol·licituds mitjançant HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "No utilitza HTTP/2 per a tots els recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Utilitza HTTP/2 per als recursos propis"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Per millorar el rendiment del desplaçament de la pàgina, et recomanem que defineixis els detectors d'esdeveniments de roda de desplaçament com a `passive`. [Obtén més informació](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "No utilitza detectors passius per millorar el rendiment del desplaçament"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Utilitza detectors passius per millorar el rendiment del desplaçament"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descripció"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Els errors registrats a la consola indiquen problemes pendents de resoldre. Poden provenir d'errors de sol·licitud de la xarxa i d'altres problemes del navegador. [Més informació](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Els errors del navegador s'han registrat a la consola"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "No s'ha registrat cap error del navegador a la consola"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Aprofita la funció CSS que permet mostrar els tipus de lletra per assegurar-te que els usuaris puguin veure el text mentre es carreguen els tipus de lletra per a llocs web. [Obtén més informació](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Assegura't que el text continuï visible durant la càrrega dels tipus de lletra per a llocs web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Tot el text continua visible durant les càrregues dels tipus de lletra per a llocs web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse no ha pogut comprovar automàticament el valor que permet mostrar els tipus de lletra de l'URL següent: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Relació d'aspecte (real)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Relació d'aspecte (mostrada)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Les dimensions de visualització de la imatge han de coincidir amb la relació d'aspecte natural. [Obtén més informació](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Mostra les imatges amb una relació d'aspecte incorrecta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Mostra les imatges amb una relació d'aspecte correcta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "La informació sobre la mida de la imatge no és vàlida: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Els navegadors poden demanar de manera proactiva als usuaris que afegeixin la teva aplicació a la pantalla d'inici, cosa que permet que hi interaccionin més. [Obtén més informació](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "El fitxer de manifest de l'aplicació web no compleix els requisits d'instal·lació"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "El fitxer de manifest de l'aplicació web compleix els requisits d'instal·lació"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL no segur"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Tots els llocs web haurien d'estar protegits amb HTTPS, fins i tot els que no gestionen dades sensibles. L'HTTPS evita que intrusos manipulin o escoltin passivament les comunicacions entre la teva aplicació i els usuaris, i és un requisit previ per a HTTP/2 i per a moltes API de plataforma web noves. [Obtén més informació](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 sol·licitud no segura}other{S'han trobat # sol·licituds no segures}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "No utilitza HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Utilitza HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Carregar les pàgines ràpidament mitjançant una xarxa mòbil garanteix una experiència satisfactòria per als usuaris de mòbils. [Obtén més informació](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Ha tardat {timeInMs, number, seconds} segons a fer-se interactiva"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Ha tardat {timeInMs, number, seconds} segons a fer-se interactiva a la xarxa mòbil"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "La pàgina es carrega massa lentament i no es torna interactiva al cap de 10 segons. Consulta les seccions Oportunitats i Diagnòstic de la categoria Rendiment per obtenir informació sobre com es pot millorar."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "La pàgina no es carrega amb prou rapidesa a les xarxes mòbils"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "La pàgina es carrega amb prou rapidesa a les xarxes mòbils"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoria"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Et recomanem que redueixis el temps dedicat a analitzar, compilar i executar JavaScript. Et pot ajudar utilitzar càrregues útils de JavaScript més petites. [Més informació](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimitza el treball al fil principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimitza el treball al fil principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Per arribar al major nombre d'usuaris possible, els llocs web han de funcionar en tots els navegadors principals. [Obtén més informació](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "El lloc web funciona en diversos navegadors"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Comprova que l'URL de cada pàgina sigui un enllaç profund i únic per poder compartir-lo als mitjans socials. [Obtén més informació](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Cada pàgina té un URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Les transicions en navegar per l'aplicació han de ser àgils, fins i tot en xarxes lentes. És una experiència clau en la percepció del rendiment per part de l'usuari. [Obtén més informació](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "No sembla que les transicions entre pàgines es bloquegin a la xarxa"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "La latència estimada d'una acció és un càlcul de quant tarda en mil·lisegons la teva aplicació a respondre a una acció de l'usuari durant el període de 5 segons amb més càrregues de pàgines. Si la latència és superior a 50 ms, és possible que els usuaris considerin que l'aplicació és lenta. [Obtén més informació](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latència estimada de les accions"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "La mètrica Primera renderització de contingut marca el moment en què es renderitza el primer text o la primera imatge. [Obtén més informació](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Primera renderització de contingut"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "La mètrica Primera inactivitat de la CPU marca el primer moment en què el fil principal de la pàgina està suficientment inactiu per gestionar accions. [Obtén més informació](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primera inactivitat de la CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "La mètrica Primera renderització significativa mesura el moment en què el contingut principal d'una pàgina és visible. [Obtén més informació](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Primera renderització significativa"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "La mètrica Temps fins que és interactiva és el que tarda la pàgina a fer-se completament interactiva. [Obtén més informació](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Temps fins que és interactiva"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "El retard potencial màxim respecte a la primera interacció que els usuaris es poden trobar és la durada, en mil·lisegons, de la tasca més llarga. [Obtén més informació](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Retard potencial màxim respecte a la primera interacció"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "L'índex de velocitat mostra la rapidesa amb què s'emplena el contingut d'una pàgina. [Obtén més informació](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Índex de velocitat"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "La suma de tots els períodes de temps entre l'FCP i el Temps fins que és interactiva, quan la llargada de la tasca ha superat els 50 ms, expressada en mil·lisegons."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Durada total del bloqueig"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Els temps d'anada i tornada a la xarxa afecten considerablement el rendiment. Si el temps d'anada i tornada a un origen és llarg, indica que els servidors de més a prop de l'usuari podrien millorar el rendiment. [Obtén més informació](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Temps d'anada i tornada a la xarxa"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Les latències del servidor poden afectar el rendiment web. Si són llargues en un origen, indiquen que el servidor està sobrecarregat o que té un rendiment dorsal deficient. [Obtén més informació](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latències dorsals del servidor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Els Service Workers permeten que la teva aplicació sigui fiable en condicions imprevisibles de la xarxa. [Obtén més informació](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` no respon amb un codi 200 quan no hi ha connexió"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` respon amb un codi 200 quan no hi ha connexió"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse no ha pogut llegir l'atribut `start_url` del fitxer de manifest, de manera que s'ha donat per fet que `start_url` era l'URL del document. Missatge d'error: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Per sobre del pressupost"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Manté la quantitat i la mida de les sol·licituds de xarxa ajustades als objectius establerts al pressupost de rendiment que s'ha proporcionat. [Obtén més informació](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 sol·licitud}other{# sol·licituds}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Pressupost de rendiment"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Si ja has configurat el format HTTPS, assegura't de redirigir tot el trànsit HTTP cap a HTTPS per activar funcions web segures per a tots els usuaris. [Obtén més informació](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "No redirigeix el trànsit HTTP cap a HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirigeix el trànsit HTTP cap a HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "La mètrica Redireccions introdueix retards addicionals abans de poder carregar la pàgina. [Obtén més informació](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evita les redireccions múltiples a pàgines"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Per definir els pressupostos de la quantitat i la mida dels recursos de la pàgina, afegeix un fitxer budget.json. [Obtén més informació](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 sol·licitud • {byteCount, number, bytes} kB}other{# sol·licituds • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Mantén els recomptes de les sol·licituds baixos i les mides de les transferències petites"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Els enllaços canònics suggereixen quins URL s'han de mostrar als resultats de cerca. [Obtén més informació](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Hi ha diversos URL en conflicte ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Dirigeix a un altre domini ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL no vàlid ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Dirigeix a una altra ubicació de tipus \"`hreflang`\" ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relatiu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Apunta a l'URL arrel (la pàgina d'inici) del domini en lloc d'apuntar a una pàgina equivalent de contingut"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "El document no té un valor `rel=canonical` vàlid"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "El document té un valor `rel=canonical` vàlid"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Les lletres amb una mida inferior als 12 píxels són massa petites i obliguen els usuaris de mòbils a \"pinçar per fer zoom\" a fi d'ampliar el text i poder llegir-lo. Intenta que la mida de més del 60% del text de la pàgina sigui igual o superior a 12 píxels. [Obtén més informació](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "El {decimalProportion, number, extendedPercent} del text és llegible"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "El text és il·legible perquè no hi ha cap metaetiqueta de finestra gràfica optimitzada per a pantalles de dispositius mòbils."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "El {decimalProportion, number, extendedPercent} del text és massa petit (d'acord amb una mostra del {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "El document no utilitza lletres amb mides llegibles"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "El document utilitza lletres amb mides llegibles"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Els enllaços de tipus \"hreflang\" informen els motors de cerca de quina versió d'una pàgina han d'incloure als resultats de cerca per a una regió o un idioma concrets. [Obtén més informació](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "El document no té un valor `hreflang` vàlid"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "El document té un valor `hreflang` vàlid"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "És possible que les pàgines amb codi d'estat HTTP incorrecte no s'indexin correctament. [Obtén més informació](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "El codi d'estat HTTP de la pàgina no és correcte"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "El codi d'estat HTTP de la pàgina és correcte"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Si els motors de cerca no tenen permís per rastrejar les teves pàgines, no les poden incloure als resultats de cerca. [Obtén més informació](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "La pàgina està configurada per bloquejar la indexació"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "La indexació no està bloquejada en aquesta pàgina"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "El text descriptiu dels enllaços ajuda els motors de cerca a entendre el contingut. [Obtén més informació](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 enllaç}other{S'han trobat # enllaços}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Els enllaços no tenen text descriptiu"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Els enllaços tenen text descriptiu"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Executa l'[eina de proves de dades estructurades](https://search.google.com/structured-data/testing-tool/) i l'[eina Structured Data Linter](http://linter.structured-data.org/) per validar aquest tipus de dades. [Obtén més informació](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Les dades estructurades són vàlides"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "És possible que s'incloguin metadescripcions als resultats de cerca per resumir breument el contingut de la pàgina. [Obtén més informació](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "El text de la descripció és buit."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "El document no té cap metadescripció"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "El document té una metadescripció"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Els motors de cerca no poden indexar el contingut dels connectors. A més, molts dispositius restringeixen els correctors o no els admeten. [Obtén més informació](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "El document utilitza connectors"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "El document evita els connectors"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Si el format del fitxer robots.txt no és correcte, és possible que els rastrejadors no puguin entendre com vols que rastregin o indexin el lloc web. [Obtén més informació](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "La sol·licitud del fitxer robots.txt ha tornat l'estat HTTP següent: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{S'ha trobat 1 error}other{S'han trobat # errors}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse no ha pogut baixar el fitxer robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "El fitxer robots.txt no és vàlid"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "El fitxer robots.txt és vàlid"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Els elements interactius, com ara els botons i els enllaços, han de ser prou grans (48 x 48 píxels) i han de tenir prou espai al voltant perquè els usuaris els puguin tocar sense que se superposin a altres elements. [Obtén més informació](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "El {decimalProportion, number, percent} de les mides dels objectius tàctils és correcte"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Els elements tàctils són massa petits perquè no hi ha cap metaetiqueta de finestra gràfica optimitzada per a pantalles de mòbil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "La mida dels elements tàctils no és correcta"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Objectiu superposat"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Element tàctil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "La mida dels elements tàctils és correcta"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "El Service Worker és la tecnologia que fa possible que la teva aplicació utilitzi moltes funcions d'aplicació web progressiva, com ara funcionar sense connexió, poder afegir-se a la pàgina d'inici i mostrar notificacions automàtiques. [Obtén més informació](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Tot i que un Service Worker controla aquesta pàgina, no s'ha trobat cap atribut `start_url` perquè el fitxer de manifest no s'ha pogut analitzar com a format JSON vàlid"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Tot i que un Service Worker controla aquesta pàgina, l'atribut `start_url` ({startUrl}) no és a l'abast del Service Worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Tot i que un Service Worker controla aquesta pàgina, no s'ha trobat cap `start_url` perquè no s'ha obtingut cap fitxer de manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Aquest origen té un Service Worker o més, però la pàgina ({pageUrl}) està fora de l'abast."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "No registra cap Service Worker que controli la pàgina i l'atribut `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registra un Service Worker que controla la pàgina i l'atribut `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Utilitzar una pantalla inicial temàtica garanteix una experiència d'alta qualitat quan els usuaris inicien l'aplicació des de la pantalla d'inici. [Obtén més informació](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "No està configurat per a una pantalla inicial personalitzada"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Està configurat per a una pantalla inicial personalitzada"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Es pot aplicar un tema a la barra d'adreces del navegador perquè faci joc amb el teu lloc web. [Obtén més informació](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "No estableix un color temàtic per a la barra d'adreces."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Estableix un color temàtic per a la barra d'adreces."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Temps de bloqueig del fil principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tercers"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "El codi de tercers pot afectar significativament el rendiment de la càrrega. Limita el nombre de proveïdors externs redundants i prova de carregar codi de tercers quan la càrrega principal de la pàgina ha finalitzat. [Obtén més informació](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "El codi de tercers ha bloquejat el fil principal durant {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Redueix l'impacte del codi de tercers"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Ús de tercers"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "La mètrica Temps fins al primer byte identifica el moment en què el teu servidor envia una resposta. [Obtén més informació](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "El document arrel ha tardat {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Redueix els temps de resposta del servidor (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Els temps de resposta del servidor són baixos (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Durada"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Hora d'inici"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipus"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Et recomanem que utilitzis l'API Temps d'usuari amb la teva aplicació per mesurar-ne el rendiment al món real durant experiències clau dels usuaris. [Obtén més informació](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 temps d'usuari}other{# temps d'usuari}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Marques i mesures de Temps d'usuari"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "S'ha trobat un element <link> de connexió prèvia per a \"{securityOrigin}\", però el navegador no l'ha utilitzat. Comprova que estiguis utilitzant correctament l'atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Et recomanem que afegeixis suggeriments de recursos `preconnect` o `dns-prefetch` per establir connexions anticipades a orígens importants de tercers. [Obtén més informació](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Connecta't prèviament als orígens necessaris"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "S'ha trobat un element <link> de càrrega prèvia per a \"{preloadURL}\", però el navegador no l'ha utilitzat. Comprova que estiguis utilitzant correctament l'atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Et recomanem que utilitzis `<link rel=preload>` per prioritzar l'obtenció de recursos que en aquests moments se sol·liciten en un moment posterior de la càrrega de pàgines. [Obtén més informació](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Carrega prèviament les sol·licituds de clau"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Afegeix una etiqueta `<meta name=\"viewport\">` a fi d'optimitzar l'aplicació per a pantalles de dispositius mòbils. [Obtén més informació](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "No s'ha trobat cap etiqueta `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "No té una etiqueta `<meta name=\"viewport\">` amb l'atribut `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Té una etiqueta `<meta name=\"viewport\">` amb l'atribut `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "L'aplicació ha de mostrar algun tipus de contingut quan JavaScript estigui desactivat, encara que només sigui per avisar l'usuari que es requereix JavaScript per utilitzar l'aplicació. [Obtén més informació](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "El cos de la pàgina ha de renderitzar algun tipus de contingut si els scripts no estan disponibles."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "No proporciona contingut alternatiu quan JavaScript no està disponible"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Inclou algun tipus de contingut quan JavaScript no està disponible"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Si vols crear una aplicació web progressiva, considera la possibilitat d'utilitzar un Service Worker perquè l'aplicació funcioni sense connexió. [Obtén més informació](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "La pàgina actual no respon amb un codi 200 quan no hi ha connexió"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "La pàgina actual respon amb un codi 200 quan no hi ha connexió"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "És possible que la pàgina no es carregui sense connexió perquè l'URL de prova ({requested}) s'ha redirigit cap a \"{final}\". Prova el segon URL directament."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Aquí tens recomanacions per millorar l'ús dels elements d'ARIA a l'aplicació. També poden millorar l'experiència dels usuaris de tecnologia d'assistència (per exemple, de lectors de pantalla)."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Aquí tens recomanacions per proporcionar contingut alternatiu d'àudio i vídeo. També poden millorar l'experiència dels usuaris amb discapacitat auditiva o visual."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Àudio i vídeo"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Aquests elements destaquen les pràctiques recomanades més habituals pel que fa a l'accessibilitat."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Pràctiques recomanades"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Aquestes comprovacions destaquen les oportunitats per [millorar l'accessibilitat de l'aplicació web](https://developers.google.com/web/fundamentals/accessibility). Només poden detectar un subconjunt de problemes d'accessibilitat automàticament, de manera que et recomanem que també hi facis proves manuals."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Aquests elements tracten àrees que les eines de proves automatitzades no poden cobrir. Obtén més informació a la nostra guia sobre [com es duen a terme ressenyes d'accessibilitat](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accessibilitat"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Aquí tens idees per millorar la llegibilitat del contingut."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Aquí tens recomanacions per millorar la interpretació del contingut per part dels usuaris de diferents configuracions regionals."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalització i localització"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Aquí tens recomanacions per millorar la semàntica dels controls a l'aplicació. També poden millorar l'experiència dels usuaris de tecnologia d'assistència (per exemple, de lectors de pantalla)."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Noms i etiquetes"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Aquí tens recomanacions per millorar la navegació amb el teclat a l'aplicació."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navegació"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Aquí tens recomanacions per millorar la lectura de dades de taules o llistes utilitzant la tecnologia d'assistència (per exemple, lectors de pantalla)."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Taules i llistes"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Pràctiques recomanades"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Els pressupostos de rendiment estableixen uns estàndards per al rendiment del teu lloc web."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Pressupostos"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Més informació sobre el rendiment de la teva aplicació. Aquests números no [afecten directament](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) el resultat del rendiment."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnòstic"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "L'aspecte més crític del rendiment és la velocitat amb què es renderitzen els píxels en pantalla. Mètriques clau: Primera renderització de contigut, Primera renderització significativa"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Millores de la primera renderització"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Aquests suggeriments poden ajudar la pàgina a carregar-se més de pressa. No [afecten directament](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) el resultat del rendiment."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunitats"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Mètriques"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Millora l'experiència general de càrrega, de manera que la pàgina respongui i estigui preparada per utilitzar-se al més aviat possible. Mètriques clau: Temps fins que és interactiva, Índex de velocitat"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Millores generals"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Rendiment"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Aquestes validacions verifiquen els aspectes de les aplicacions web progressives. [Obtén més informació](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "La [llista de comprovació de referència per a aplicacions web progressives](https://developers.google.com/web/progressive-web-apps/checklist) requereix aquestes validacions, però Lighthouse no les verifica automàticament. Tot i que no afecten la teva puntuació, és important que les verifiquis manualment."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Aplicació web progressiva"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Ràpid i fiable"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Es pot instal·lar"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimitzat per a PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Aquestes comprovacions garanteixen que la pàgina estigui optimitzada per classificar els resultats del motor de cerca. Hi ha factors addicionals que Lighthouse no comprova i que és possible que afectin la teva classificació a les cerques. [Obtén més informació](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Executa aquestes validacions addicionals al lloc web per comprovar les pràctiques addicionals recomanades per a SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Dona a l'HTML un format que permeti als rastrejadors entendre millor el contingut de l'aplicació."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Pràctiques recomanades pel que fa al contingut"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Perquè l'aplicació es mostri als resultats de cerca, els rastrejadors necessiten tenir-hi accés."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Rastreig i indexació"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Comprova que les pàgines estiguin adaptades per a mòbils, de manera que els usuaris no hagin de pinçar o ampliar les pàgines de contingut per poder llegir-les. [Obtén més informació](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Adaptació per a mòbils"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL de la memòria cau"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Ubicació"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nom"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Sol·licituds"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipus de recurs"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Mida"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Temps invertit"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Mida de la transferència"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Possible estalvi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Possible estalvi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Possible estalvi de {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Possible estalvi de {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Tipus de lletra"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imatge"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Multimèdia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Altres"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Full d'estil"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tercers"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Hi ha hagut un problema en gravar la traça sobre la càrrega de la pàgina. Torna a executar Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "S'ha esgotat el temps d'espera de la connexió inicial del protocol de depuració."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome no ha recollit cap captura de pantalla mentre es carregava la pàgina. Comprova que hi hagi contingut visible a la pàgina i, a continuació, prova d'executar Lighthouse de nou. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Els servidors DNS no han pogut resoldre el domini proporcionat."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "El recopilador del recurs {artifactName} requerit ha detectat un error: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "S'ha produït un error intern de Chrome. Reinicia el navegador i prova d'executar Lighthouse de nou."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "El recopilador obligatori {artifactName} no s'ha executat."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse no ha pogut carregar de manera fiable la pàgina que has sol·licitat. Assegura't que estiguis fent la prova de l'URL correcte i que el servidor estigui responent correctament a totes les sol·licituds."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Com que la pàgina ha deixat de respondre, Lighthouse no ha pogut carregar de manera fiable l'URL que has sol·licitat."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "L'URL que has proporcionat no té un certificat de seguretat vàlid. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome ha evitat la càrrega de la pàgina amb una pantalla intersticial. Assegura't que estiguis fent la prova de l'URL correcte i que el servidor estigui responent correctament a totes les sol·licituds."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse no ha pogut carregar de manera fiable la pàgina que has sol·licitat. Assegura't que estiguis fent la prova de l'URL correcte i que el servidor estigui responent correctament a totes les sol·licituds. (Detalls: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse no ha pogut carregar de manera fiable la pàgina que has sol·licitat. Assegura't que estiguis fent la prova de l'URL correcte i que el servidor estigui responent correctament a totes les sol·licituds. (Codi d'estat: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "La pàgina ha tardat massa temps a carregar-se. Segueix les opcions indicades a l'informe per reduir el temps de càrrega de la pàgina i, a continuació, prova d'executar Lighthouse de nou. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "S'ha superat el temps assignat per rebre una resposta del protocol de DevTools. (Mètode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "S'ha superat el temps assignat per obtenir el contingut dels recursos"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Sembla que l'URL que has proporcionat no és vàlid."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostra les auditories"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navegació inicial"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latència de camí crítica màxima:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Error de l'informe: no hi ha informació d'auditoria"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dades de laboratori"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Anàlisi amb [Lighthouse](https://developers.google.com/web/tools/lighthouse/) de la pàgina actual mitjançant una xarxa mòbil emulada. Els valors són estimacions i poden variar."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Elements addicionals per comprovar manualment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "No aplicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunitat"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estalvi estimat"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditories aprovades"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Replega el fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Desplega el fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostra els recursos de tercers"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Hi ha hagut problemes que afecten aquesta execució de Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Els valors són estimacions i poden variar. El resultat del rendiment [només es basa en aquestes mètriques](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Auditories aprovades però amb advertiments"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Advertiments: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Pots pujar el GIF en un servei que permeti inserir-lo en un vídeo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instal·la un [connector de WordPress de càrrega diferida](https://wordpress.org/plugins/search/lazy+load/) que t'ofereixi la possibilitat d'ajornar les imatges fora de pantalla o canviar a un tema que t'ofereixi aquesta funció. També pots fer servir [el connector AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Hi ha diversos connectors de WordPress que et poden ajudar a [inserir recursos essencials](https://wordpress.org/plugins/search/critical+css/) o a [ajornar els recursos menys importants](https://wordpress.org/plugins/search/defer+css+javascript/). Tingues en compte que les optimitzacions que proporcionen aquests connectors poden afectar les funcions del tema o dels connectors, de manera que és possible que hagis de fer canvis al codi."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Els temes, els connectors i les especificacions del servidor contribueixen al temps de resposta del servidor. Pots buscar un tema més optimitzat, seleccionar amb cura un connector d'optimització o actualitzar el servidor."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Pots mostrar extractes a les llistes de publicacions (per exemple, amb l'etiqueta més), reduir el nombre de publicacions que es mostren en una pàgina concreta, tallar les publicacions llargues en diverses pàgines o fer servir un connector per als comentaris de càrrega diferida."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Hi ha diversos [connectors de WordPress](https://wordpress.org/plugins/search/minify+css/) que poden accelerar el teu lloc web. Per fer-ho, concatenen, redueixen i comprimeixen els estils. També et recomanem que utilitzis un procés de compilació per fer aquesta minimització de manera anticipada, si és possible."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Hi ha diversos [connectors de WordPress](https://wordpress.org/plugins/search/minify+javascript/) que poden accelerar el teu lloc web. Per fer-ho, concatenen, redueixen i comprimeixen els scripts. També et recomanem que utilitzis un procés de compilació per fer aquesta minimització de manera anticipada, si és possible."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Pots reduir o canviar el nombre de [connectors de WordPress](https://wordpress.org/plugins/) que carreguen fitxers CSS no utilitzats a la pàgina. Per identificar els connectors que afegeixen fitxers CSS externs, prova d'executar la [cobertura de codi](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) a Chrome DevTools. Pots identificar el tema o el connector responsable a partir de l'URL del full d'estil. Cerca connectors que tinguin molts fulls d'estil a la llista amb molt vermell a la cobertura de codi. Un connector només hauria de tenir un full d'estil a la cua si es fa servir a la pàgina."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Pots reduir o canviar el nombre de [connectors de WordPress](https://wordpress.org/plugins/) que carreguen fitxers JavaScript no utilitzats a la pàgina. Per identificar els connectors que afegeixen fitxers JavaScript externs, prova d'executar la [cobertura de codi](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) a Chrome DevTools. Pots identificar el tema o el connector responsable a partir de l'URL de l'script. Cerca connectors que tinguin molts scripts a la llista amb molt vermell a la cobertura de codi. Un connector només hauria de tenir un script a la cua si es fa servir a la pàgina."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Obtén informació sobre la [memòria cau del navegador a WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Pots utilitzar un [connector de WordPress d'optimització d'imatges](https://wordpress.org/plugins/search/optimize+images/) per comprimir les imatges sense perdre qualitat."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Penja imatges directament mitjançant la [biblioteca multimèdia](https://codex.wordpress.org/Media_Library_Screen) per garantir que les mides de la imatge necessàries estiguin disponibles i, a continuació, insereix-les des de la biblioteca multimèdia o fes servir el widget per garantir que es fan servir les mides de la imatge òptimes (incloses les dels punts de ruptura responsius). Evita utilitzar imatges de `Full Size`, tret que les dimensions siguin les adequades per a l'ús que se'n farà. [Obtén més informació](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Pots activar la compressió de text a la configuració del servidor web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Pots fer servir un [connector](https://wordpress.org/plugins/search/convert+webp/) o un servei que converteixi automàticament les imatges penjades als formats òptims."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/cs.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/cs.json
new file mode 100644
index 00000000000..3da90d9fb9f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/cs.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Přístupové klávesy uživatelům umožňují rychleji vybrat část stránky. Aby navigace fungovala správně, musí být každá přístupová klávesa jedinečná. [Další informace](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Hodnoty atributů `[accesskey]` nejsou jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Hodnoty `[accesskey]` jsou unikátní"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Každá položka ARIA `role` podporuje konkrétní podmnožinu atributů `aria-*`. Nesprávné přiřazení atributy `aria-*` zneplatní. [Další informace](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributy `[aria-*]` neodpovídají svým rolím"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributy `[aria-*]` odpovídají příslušným rolím"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Některé role ARIA mají povinné atributy, které čtečkám obrazovek popisují stav prvku. [Další informace](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Prvky s atributy `[role]` nemají všechny povinné atributy `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Prvky s atributy `[role]` mají všechny povinné atributy `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Některé nadřazené role ARIA musejí kvůli poskytovaní správných funkcí přístupnosti obsahovat určité podřízené role. [Další informace](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "V prvcích s atributem ARIA `[role]`, jejichž podřízené prvky musí obsahovat konkrétní atribut `[role]`, některé z těchto povinných podřízených prvků chybí."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Prvky s atributem ARIA `[role]`, jejichž podřízené prvky musí obsahovat konkrétní atribut `[role]`, obsahují všechny povinné podřízené prvky."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Aby poskytovaly správné funkce přístupnosti, musejí být některé podřízené role ARIA umístěny v konkrétních nadřazených rolích. [Další informace](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Prvky s atributem `[role]` nejsou umístěny v požadovaném nadřazeném prvku"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Prvky s atributy `[role]`jsou umístěny v požadovaném nadřazeném prvku"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Aby role ARIA poskytovaly správné funkce přístupnosti, musejí mít platné hodnoty. [Další informace](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Hodnoty atributů `[role]` nejsou platné"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Hodnoty atributů `[role]` jsou platné"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Asistenční technologie, jako jsou čtečky obrazovek, atributy ARIA s neplatnými hodnotami nedokážou interpretovat. [Další informace](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atributy `[aria-*]` nemají platné hodnoty"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atributy `[aria-*]` mají platné hodnoty"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Asistenční technologie, jako jsou čtečky obrazovek, atributy ARIA s neplatnými názvy nedokážou interpretovat. [Další informace](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributy `[aria-*]` nejsou platné nebo v nich jsou překlepy"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributy `[aria-*]` jsou platné a nejsou v nich překlepy"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Titulky umožňují sluchově postiženým uživatelům používat zvukové prvky tím, že jim poskytují kritické informace (například kdo mluví a co říká nebo další informace nesouvisející s řečí). [Další informace](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "V prvcích `<audio>` chybí prvek `<track>` s atributem `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Prvky `<audio>` obsahují prvek `<track>` s atributem `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Prvky, které neprošly"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Když tlačítko nemá přístupný název, čtečky obrazovek ho oznamují jako „tlačítko“ a pro jejich uživatele je tak v podstatě nepoužitelné. [Další informace](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Tlačítka nemají přístupné názvy"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Tlačítka mají přístupné názvy"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Když přidáte možnosti obejití repetitivního obsahu, umožníte tím efektivnější procházení stránky pomocí klávesnice. [Další informace](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Stránka neobsahuje nadpis, odkaz k přeskočení ani orientační bod regionu"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Stránka obsahuje nadpis, odkaz k přeskočení nebo orientační bod regionu"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Text s nízkým kontrastem je pro mnoho uživatelů obtížně čitelný nebo nečitelný. [Další informace](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Barvy pozadí a popředí nemají dostatečný kontrastní poměr."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Barvy pozadí a popředí mají dostatečný kontrastní poměr"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Když seznamy definic nejsou správně označené, čtečky obrazovek mohou generovat matoucí nebo nepřesný výstup. [Další informace](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Prvky `<dl>` neobsahují jen správně seřazené skupiny prvků `<dt>` a `<dd>` nebo prvky `<script>` či `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Prvky `<dl>` neobsahují jen správně seřazené skupiny prvků `<dt>` a `<dd>` nebo prvky `<script>` či `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Aby mohly čtečky obrazovek správně oznamovat položky seznamů definic (`<dt>` a `<dd>`), musejí být tyto položky umístěny v nadřazeném prvku `<dl>`. [Další informace](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Položky seznamu definic nejsou umístěny v prvcích `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Položky seznamu definic jsou umístěny v prvcích `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Název (title) uživatelům čteček obrazovek poskytuje souhrnné informace o stránce a uživatelé vyhledávačů se podle něj rozhodují, zda je stránka pro jejich vyhledávání relevantní. [Další informace](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument neobsahuje prvek `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument obsahuje prvek `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Aby asistenční technologie nepřehlédly další výskyty, hodnota atributu id musí být jedinečná. [Další informace](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atributy `[id]` na stránce nejsou jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atributy `[id]` na stránce jsou jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Čtečky obrazovek obvykle k popisu obsahu rámců používají jejich atributy title. [Další informace](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Prvky `<frame>` nebo `<iframe>` nemají atribut title"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Prvky `<frame>` a `<iframe>` mají atribut title"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Pokud stránka neuvádí atribut lang, čtečky obrazovky předpokládají, že je ve výchozím jazyce, který uživatel zvolil při nastavování čtečky obrazovky. Pokud stránka ve skutečnosti ve výchozím jazyce není, čtečka obrazovky text nemusí přečíst správně. [Další informace](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Prvek `<html>` nemá atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Prvek `<html>` má atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Zadáním platného [jazyka BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) pomůžete čtečkám obrazovek správně oznamovat text. [Další informace](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Prvek `<html>` nemá platnou hodnotu atributu `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Prvek `<html>` má atribut `[lang]` s platnou hodnotou"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informativní prvky by měly mít krátký, popisný alternativní text. Dekorativní prvky lze ignorovat pomocí prázdného atributu alt. [Další informace](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Prvky obrázků nemají atributy `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Prvky obrázků mají atributy `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Když je jako tlačítko `<input>` použit obrázek, uvedení alternativního textu pomůže uživatelům čteček obrazovek porozumět účelu tlačítka. [Další informace](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Prvky `<input type=\"image\">` nemají text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Prvky `<input type=\"image\">` mají text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Štítky zajišťují, aby asistenční technologie (například čtečky obrazovek) správně oznamovaly ovládací prvky formulářů. [Další informace](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "K prvkům formulářů nejsou přidružené štítky"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "K prvkům formulářů jsou přidružené štítky"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabulka použitá pro účely rozvržení by neměla obsahovat datové prvky, jako jsou prvky th nebo caption ani atribut summary. Pro uživatele čteček obrazovek to může být matoucí. [Další informace](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Prezentační prvky `<table>` obsahují prvky `<th>` či `<caption>` nebo atribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Prezentační prvky `<table>` neobsahují prvky `<th>` a `<caption>`ani atribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Text odkazů (a náhradní text obrázků, když jsou použité jako odkazy), který je rozeznatelný a jedinečný a který lze vybrat, uživatelům čteček obrazovek usnadňuje procházení stránek. [Další informace](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Odkazy nemají rozeznatelné názvy"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Odkazy mají rozeznatelné názvy"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Čtečky obrazovek oznamují seznamy speciálním způsobem. Použitím správné struktury seznamu pomůžete čtečkám obrazovek s výstupem. [Další informace](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Seznamy neobsahují výhradně prvky `<li>` a prvky, které podporují skripty (`<script>` a `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Seznamy obsahují výhradně prvky `<li>` a prvky, které podporují skripty (`<script>` a `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Aby čtečky obrazovek prvky `<li>` a `<ul>` oznamovaly správně, musejí být tyto prvky umístěny v nadřazených položkách (`<ol>`). [Další informace](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Položky seznamů (`<li>`) nejsou umístěny v nadřazených prvcích `<ul>` nebo `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Položky seznamu (`<li>`) jsou umístěny v nadřazených prvcích `<ul>` nebo `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Uživatelé neočekávají, že se stránka bude automaticky obnovovat. Při automatickém obnovení se prohlížeč vrátí zpět na začátek stránky. Může to vést k nepříjemnému nebo matoucímu chování při procházení. [Další informace](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "V dokumentu je použita metaznačka `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "V dokumentu není použita metaznačka `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Deaktivace změny velikosti zobrazení je problematická pro slabozraké uživatele, kteří jsou při prohlížení obsahu webové stránky závislí na přiblížení obrazovky. [Další informace](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "V prvku `[user-scalable=\"no\"]` je použit atribut `<meta name=\"viewport\">` nebo je atribut `[maximum-scale]` menší než 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "V prvku `[user-scalable=\"no\"]` není použit atribut `<meta name=\"viewport\">` a atribut `[maximum-scale]` není menší než 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Čtečky obrazovek nedokážou přeložit obsah jiného typu, než je text. Když k prvkům `<object>` přidáte alternativní text, čtečky obrazovek budou moci předat uživatelům význam. [Další informace](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Prvky `<object>` nemají text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Prvky `<object>` mají text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Hodnota větší než 0 naznačuje explicitní řazení navigace. Ačkoli je platná, často vede k chování, které je pro uživatele závislé na asistenčních technologiích nepříjemné. [Další informace](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Některé prvky mají hodnotu `[tabindex]` větší než 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Žádný prvek nemá hodnotu `[tabindex]` větší než 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Čtečky obrazovek mají funkce, které usnadňují procházení tabulek. Když zajistíte, aby buňky `<td>` s atributem `[headers]` odkazovaly pouze na jiné buňky ve stejné tabulce, můžete tím uživatelům čteček obrazovek usnadnit používání. [Další informace](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Buňky v prvku `<table>`, které mají atribut `[headers]`, odkazují na prvek `id`, který se nenachází ve stejné tabulce."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Buňky v prvku `<table>`, které mají atribut `[headers]`, odkazují na buňky ve stejné tabulce."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Čtečky obrazovek mají funkce, které usnadňují procházení tabulek. Když zajistíte, aby záhlaví tabulek vždy odkazovala na nějakou množinu buněk, bude pro uživatele čteček obrazovek procházení stránky snazší. [Další informace](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Prvky `<th>` a prvky s atributem `[role=\"columnheader\"/\"rowheader\"]` nemají datové buňky, které popisují."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Prvky `<th>` a prvky s atributem `[role=\"columnheader\"/\"rowheader\"]` mají datové buňky, které popisují."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Pokud je u prvků uveden platný [jazyk BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) pomůže to zajistit, aby čtečky obrazovek text četly správně. [Další informace](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atributy `[lang]` nemají platnou hodnotu"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributy `[lang]` mají platnou hodnotu"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Když jsou u videa k dispozici titulky, je pro sluchově postižené uživatele snazší využít informace ve videu. [Další informace](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Prvky `<video>` neobsahují prvek `<track>` s atributem `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Prvky `<video>` obsahují prvek `<track>` s atributem `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Zvukové popisy u videí poskytují relevantní informace, které nejsou patrné z dialogů, jako jsou například výrazy v obličejích a popisy scén. [Další informace](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Prvky `<video>` neobsahují prvek `<track>` s atributem `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Prvky `<video>` obsahují prvek `<track>` s atributem `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Pro ideální vzhled po přidání progresivní webové aplikace na plochu v systému iOS definujte atribut `apple-touch-icon`. Musí odkazovat na neprůhledný čtvercový obrázek PNG se stranami o délce 192 px (nebo 180 px). [Další informace](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Neobsahuje platný atribut `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Atribut `apple-touch-icon-precomposed` je zastaralý. Je preferován atribut `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Obsahuje platný atribut `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Rychlost načítání této stránky byla negativně ovlivněna rozšířeními pro Chrome. Zkuste stránku zkontrolovat v anonymním režimu nebo profilu Chromu bez rozšíření."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Vyhodnocování skriptů"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analýza skriptů"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Celková doba využití procesoru"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Pokuste se zkrátit dobu analyzování, kompilování a spouštění JavaScriptu. Mohlo by pomoci odesílat menší soubory JavaScript. [Další informace](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Zkraťte dobu provádění JavaScriptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Doba provádění JavaScriptu"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Velké soubory GIF nejsou efektivní k zobrazování animovaného obsahu. Zvažte, zda byste namísto souborů GIF nemohli pro animace použít videa MPEG4/WebM a pro statické obrázky soubory PNG/WebP. Snížíte tak množství přenášených dat. [Další informace](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Pro animovaný obsah používejte formáty videa"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Zvažte možnost načítat obrázky mimo obrazovku a skryté obrázky „líně“ až po načtení všech kritických zdrojů, abyste zkrátili dobu k dosažení interaktivnosti. [Další informace](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Odložte načítání obrázků mimo obrazovku"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "První vykreslení stránky blokují zdroje. Zvažte, zda byste kriticky důležité zdroje JavaScript a CSS nemohli poskytovat přímo v kódu a stahování veškerého nekritického JavaScriptu a stylů odložit. [Další informace](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Eliminujte zdroje, které blokují vykreslení"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Přenášení velkého množství dat po síti je pro uživatele finančně nákladné a obvykle vede k pomalému načítání. [Další informace](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Celková velikost byla {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Předejděte přenášení enormního množství dat"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Nepřenáší enormní množství dat"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minifikací souborů CSS lze snížit množství přenášených dat. [Další informace](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minifikujte kód CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minifikací souborů JavaScript lze snížit množství přenášených dat a zrychlit analýzu skriptů. [Další informace](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minifikujte JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Odstraňte ze šablon stylů nepoužívaná pravidla a odložte načítání stylů CSS, které se nepoužívají pro obsah zobrazený bez posouvání, abyste snížili množství nepotřebných dat využívaných síťovou aktivitou. [Další informace](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Odstraňte nepoužívané styly CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Odstraněním nepoužívaného JavaScriptu zmenšíte množství přenášených dat."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Odstraňte nepoužívaný JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Dlouhá platnost mezipaměti může zrychlit opakované návštěvy stránky. [Další informace](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Byl nalezen 1 zdroj}few{Byly nalezeny # zdroje}many{Bylo nalezeno # zdroje}other{Bylo nalezeno # zdrojů}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Statické podklady zobrazujte s efektivními zásadami pro mezipaměť"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Používá u statických podkladů efektivní zásady pro mezipaměť"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimalizované obrázky se načítají rychle a spotřebovávají méně mobilních dat. [Další informace](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Používejte efektivní kódování obrázků"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Zobrazujte obrázky s vhodnou velikostí, abyste ušetřili mobilní data a zrychlili načítání. [Další informace](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Používejte správnou velikost obrázků"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Textové zdroje by se měly odesílat komprimované (gzip, deflate nebo brotli), aby se minimalizovalo množství přenášených dat. [Další informace](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Zapněte kompresi textu"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formáty obrázků JPEG 2000, JPEG XR a WebP často poskytují lepší kompresi než formáty PNG a JPEG, což znamená rychlejší stahování a menší spotřebu dat. [Další informace](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Zobrazujte obrázky ve formátech nové generace"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Pokud se šířka obsahu aplikace neshoduje se šířkou zobrazované oblasti, aplikace nemusí být optimalizována pro obrazovky mobilních telefonů. [Další informace](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Velikost zobrazované oblasti {innerWidth} px se neshoduje s velikostí okna {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Obsah nemá správnou velikost pro zobrazovanou oblast"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Obsah má správnou velikost pro zobrazovanou oblast"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Řetězce kritických požadavků níže ukazují, které zdroje se načítají s vysokou prioritou. Zvažte, zda byste načítání stránky nemohli vylepšit tím, že řetězce zkrátíte, zmenšíte zdroje nebo odložíte stahování zdrojů, které nejsou nezbytné. [Další informace](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Byl nalezen 1 řetězec}few{Byly nalezeny # řetězce}many{Bylo nalezeno # řetězce}other{Bylo nalezeno # řetězců}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimalizujte hloubku kritických požadavků"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Ukončení podpory / upozornění"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Řádek"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Zastaralá rozhraní API budou z prohlížeče v budoucnu odstraněna. [Další informace](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Bylo nalezeno 1 upozornění}few{Byla nalezena # upozornění}many{Bylo nalezeno # upozornění}other{Bylo nalezeno # upozornění}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Používá zastaralá rozhraní API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Nepoužívá zastaralá rozhraní API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Mezipaměť aplikace je zastaralá technologie. [Další informace](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Nalezeno „{AppCacheManifest}“"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Používá mezipaměť aplikace"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Nepoužívá mezipaměť aplikace"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Zadáním typu dokumentu (DOCTYPE) předejdete přechodu prohlížeče do adaptivního režimu. [Další informace](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Název typu dokumentu (DOCTYPE) musí být řetězec `html` psaný malými písmeny"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument musí obsahovat deklaraci typu dokumentu DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "V poli publicId je očekáván prázdný řetězec"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "V poli systemId je očekáván prázdný řetězec"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Na stránce není deklarace typu dokumentu (DOCTYPE) HTML, proto se aktivuje adaptivní režim"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Stránka má deklaraci typu dokumentu (DOCTYPE) HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Prvek"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Hodnota"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Vývojáři prohlížečů doporučují, aby stránky obsahovaly méně než cca. 1 500 prvků modelu DOM. Ideálně by hloubka stromu měla být menší než 32 prvků a každý nadřazený prvek by měl mít méně než 60 podřízených prvků. Velký model DOM může vést k většímu využití paměti, delším [výpočtům stylů](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) a náročným [přeformátováváním rozvržení](https://developers.google.com/speed/articles/reflow). [Další informace](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 prvek}few{# prvky}many{# prvku}other{# prvků}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Nepoužívejte příliš velký model DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximální hloubka modelu DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Celkový počet prvků DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximální počet podřízených prvků"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Nepoužívá příliš velký model DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cíl"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Ke všem externím odkazům přidejte atribut `rel=\"noopener\"` nebo `rel=\"noreferrer\"`. Stránku tím zrychlíte a předejdete ohrožení zabezpečení. [Další informace](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Odkazy na cíle v jiných doménách nejsou bezpečné"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Odkazy na cíle v jiných doménách jsou bezpečné"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nepodařilo se určit cíl ukotvení ({anchorHTML}). Pokud tento prvek nepoužíváte jako hypertextový odkaz, zvažte odstranění atributu target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Vůči webům, které bez kontextu žádají o polohu, mohou být uživatelé nedůvěřiví nebo z nich mohou být zmateni. Zvažte možnost spojit tuto žádost s akcí uživatele. [Další informace](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Žádá při načtení stránky o oprávnění ke geolokaci"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Nežádá při načtení stránky o oprávnění ke geolokaci"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Verze"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Všechny frontendové javascriptové knihovny zjištěné na stránce. [Další informace](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Byly zjištěny javascriptové knihovny"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "U uživatelů s pomalým připojením mohou externí skripty vkládané metodou zpozdit `document.write()` načtení stránky o desítky sekund. [Další informace](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Používá metodu `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Nepoužívá metodu `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Největší závažnost"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Verze knihovny"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Počet chyb zabezpečení"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Některé skripty třetích stran mohou obsahovat známé chyby zabezpečení, které útočníci mohou snadno odhalit a zneužít. [Další informace](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Byla zjištěna jedna chyba zabezpečení}few{Byly zjištěny # chyby zabezpečení}many{Bylo zjištěno # chyby zabezpečení}other{Bylo zjištěno # chyb zabezpečení}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Zahrnuje frontendové javascriptové knihovny se známými chybami zabezpečení"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Vysoká"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Nízká"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Střední"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Nepoužívá frontendové javascriptové knihovny se známými chybami zabezpečení"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Vůči webům, které bez kontextu žádají o oprávnění odesílat oznámení, mohou být uživatelé nedůvěřiví nebo z nich mohou být zmateni. Zvažte možnost spojit tuto žádost s gesty uživatele. [Další informace](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Žádá při načtení stránky o oprávnění zobrazovat oznámení"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Nežádá při načtení stránky o oprávnění zobrazovat oznámení"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Prvky, které neprošly"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Blokování vkládání hesel je v rozporu s dobrými bezpečnostními zásadami. [Další informace](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Brání uživatelům ve vkládání obsahu do polí pro hesla"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Povoluje uživatelům vkládání obsahu do polí pro hesla"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Protokol HTTP/2 oproti protokolu HTTP/1.1 nabízí mnoho výhod, včetně binárních záhlaví, multiplexingu a přenášení metodou push ze serveru. [Další informace](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 požadavek nebyl realizován pomocí protokolu HTTP/2}few{# požadavky nebyly realizovány pomocí protokolu HTTP/2}many{# požadavku nebylo realizováno pomocí protokolu HTTP/2}other{# požadavků nebylo realizováno pomocí protokolu HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nepoužívá pro všechny zdroje protokol HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Pro vlastní zdroje používá protokol HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Zvažte označení posluchačů událostí dotyku a kolečka jako pasivních (`passive`), aby se stránka posouvala plynuleji. [Další informace](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nepoužívá pasivní posluchače, které zlepšují posouvání"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Používá pasivní posluchače, které zlepšují posouvání"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Popis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Chyby zaprotokolované do konzole ukazují na nevyřešené problémy. Mohou pocházet ze selhání síťových požadavků nebo jiných problémů v prohlížeči. [Další informace](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Do konzole byly zaprotokolovány chyby prohlížeče"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Do konzole nebyly zaprotokolovány žádné chyby prohlížeče"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Pomocí funkce font-display stylů CSS zajistěte, aby byl text při načítání webfontů viditelný uživatelům. [Další informace](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Zajistěte, aby text při načítání webfontů zůstal viditelný"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Při načítání webfontů zůstává veškerý text viditelný"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Nástroj Lighthouse nemohl automaticky zkontrolovat hodnotu font-display pro následující adresu URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Poměr stran (skutečný)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Poměr stran (zobrazený)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Zobrazované rozměry obrázků by měly odpovídat přirozenému poměru stran. [Další informace](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Zobrazuje obrázky s nesprávným poměrem stran"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Zobrazuje obrázky se správným poměrem stran"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Neplatné informace o velikosti obrázku {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Prohlížeče mohou uživatele aktivně vyzývat, aby si vaši aplikaci přidali na plochu, což může vést k vyšší míře interakce. [Další informace](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifest webové aplikace nesplňuje instalační požadavky"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifest webové aplikace splňuje instalační požadavky"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nezabezpečená adresa URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Všechny weby (včetně těch, které nepracují s citlivými daty), by měly být chráněny protokolem HTTPS. Protokol HTTPS útočníkům zabraňuje v manipulaci s komunikací mezi vaší aplikací a uživateli (nebo v jejím pasivním poslechu) a je nezbytný pro HTTP/2 a mnoho nových webových rozhraní API. [Další informace](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Byl nalezen 1 nezabezpečený požadavek}few{Byly nalezeny # nezabezpečené požadavky}many{Bylo nalezeno # nezabezpečeného požadavku}other{Bylo nalezeno # nezabezpečených požadavků}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nepoužívá protokol HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Používá protokol HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Rychlé načítání stránky přes mobilní síť zajišťuje dobrý dojem pro uživatele mobilních zařízení. [Další informace](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktivní za {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "V simulované mobilní síti je stránka interaktivní za {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Vaše stránka se načítá příliš pomalu a neumožňuje interakci do 10 sekund. Podívejte se na příležitosti a diagnostiku v sekci Výkon, abyste zjistili, jak stránku vylepšit."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Stránka se v mobilních sítích nenačítá dostatečně rychle"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Stránka se v mobilních sítích načítá dostatečně rychle"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Pokuste se zkrátit dobu analyzování, kompilování a spouštění JavaScriptu. Mohlo by pomoci odesílat menší soubory JavaScript. [Další informace](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimalizujte práci v hlavním podprocesu"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimalizuje práci v hlavním podprocesu"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Chcete-li zasáhnout co největší počet uživatelů, měly by webové stránky fungovat ve všech nejpoužívanějších prohlížečích. [Další informace](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Web funguje v různých prohlížečích"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Zajistěte, aby na jednotlivé stránky bylo možné přidat přímý odkaz prostřednictvím adresy URL a aby s ohledem na možnost sdílení na sociálních sítích byly adresy URL jedinečné. [Další informace](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Každá stránka má adresu URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Přechody by měly být plynulé i v pomalé síti. Je to velmi důležité pro dobrý uživatelský pocit. [Další informace](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Přechody na jiné stránky nepůsobí zabržděně"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Odhadovaná latence vstupu udává, jak dlouho (v milisekundách) bude aplikaci během nejvytíženějších pěti sekund při načítání stránky odhadem trvat reakce na uživatelský vstup. Pokud je latence větší než 50 ms, mohou uživatelé chování aplikace vnímat jako přerušované. [Další informace](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Odhadovaná latence vstupu"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "První vykreslení obsahu je okamžik vykreslení prvního textu nebo obrázku. [Další informace](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "První vykreslení obsahu"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "První nečinnost procesoru udává čas, kdy je hlavní podproces stránky dostatečně nečinný na to, aby bylo možné zpracovat vstup. [Další informace](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "První nečinnost procesoru"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "První smysluplné vykreslení udává, kdy začne být viditelný primární obsah stránky. [Další informace](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "První smysluplné vykreslení"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Doba do interaktivity udává, jak dlouho trvá, než stránka začne být plně interaktivní. [Další informace](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Doba do interaktivity"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Maximální potenciální prodleva prvního vstupu, kterou by uživatelé mohli pocítit, je trvání nejdelší úlohy (v milisekundách). [Další informace](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maximální potenciální prodleva prvního vstupu"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Index rychlosti ukazuje, jak rychle se viditelně vyplní obsah stránky. [Další informace](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Index rychlosti"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Součet všech dob (uvedený v milisekundách) mezi prvním vykreslením obsahu a dobou do interaktivity, u nichž délka úlohy překročila 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Celková doba blokování"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Na výkon má velký vliv doba odezvy sítě. Pokud je doba odezvy připojení ke zdroji vysoká, značí to, že by se výkon mohl zlepšit při použití serverů méně vzdálených od uživatele. [Další informace](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Doby odezvy sítě"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Na výkon webu může mít dopad latence serverů. Vysoká latence serveru značí, že je server přetížen nebo že backend není dostatečně výkonný. [Další informace](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latence backendu na serveru"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Soubor service worker vaší webové aplikaci umožňuje, aby byla spolehlivá i za nepředvídatelného stavu sítě. [Další informace](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "V režimu offline `start_url` nereaguje stavovým kódem 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "V režimu offline `start_url` reaguje stavovým kódem 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Nástroji Lighthouse se v manifestu nepodařilo přečíst atribut `start_url`. Proto se předpokládá, že adresou URL dokumentu je `start_url`. Chybová zpráva: {manifestWarning}"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Nad rozpočet"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Udržujte množství a velikost síťových požadavků pod cílovými hodnotami, které udává poskytnutý rozpočet výkonu. [Další informace](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 požadavek}few{# požadavky}many{# požadavku}other{# požadavků}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Rozpočete výkonu"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Pokud jste protokol HTTPS už nastavili, nezapomeňte veškerý provoz přes protokol HTTP přesměrovat na HTTPS, aby všichni vaši uživatelé měli k dispozici funkce zabezpečeného webu. [Další informace](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nepřesměrovává provoz přes protokol HTTP na HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Přesměrovává provoz přes protokol HTTP na HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Přesměrování způsobují další prodlevy před načtením stránky. [Další informace](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Nepoužívejte několik přesměrování stránky"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Chcete-li nastavit rozpočet pro množství a velikost zdrojů na stránce, přidejte soubor budget.json. [Další informace](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 požadavek • {byteCount, number, bytes} kB}few{# požadavky • {byteCount, number, bytes} kB}many{# požadavku • {byteCount, number, bytes} kB}other{# požadavků • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Používejte málo požadavků a malé velikosti přenosů"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Odkazy na kanonické verze slouží jako návrhy, které adresy URL se mají zobrazovat ve výsledcích vyhledávání. [Další informace](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Několik konfliktních adres URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Odkazuje na jinou doménu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Neplatná adresa URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Odkazuje na jiné umístění `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativní adresa URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Neodkazuje na ekvivalentní obsahovou stránku, ale na kořenovou adresu URL domény (domovskou stránku)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument nemá platný atribut `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument má platný odkaz `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Písma menší než 12 px jsou příliš malá na to, aby byla čitelná. Návštěvníci na mobilních zařízeních je kvůli čtení musí zvětšit roztažením prstů. Snažte se, aby více než 60 % textu na stránce mělo velikosti alespoň 12 px. [Další informace](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "Podíl čitelného textu: {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text není čitelný, protože není k dispozici metaznačka viewport optimalizovaná pro obrazovky mobilních zařízení."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Podíl příliš malého textu: {decimalProportion, number, extendedPercent} (posuzovaný vzorek: {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "V dokumentu nejsou použity čitelné velikosti písma"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "V dokumentu jsou použity čitelné velikosti písma"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Odkazy hreflang sdělují vyhledávačům, kterou verzi stránky mají uvádět ve výsledcích vyhledávání pro určitý jazyk či oblast. [Další informace](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument nemá platný atribut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument má platný atribut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Stránky s neúspěšnými stavovými kódy HTTP nemusejí být správně indexovány. [Další informace](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Stránka má neúspěšný stavový kód HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Stránka má úspěšný stavový kód HTTP"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Pokud vyhledávače nemají oprávnění procházet vaše stránky, nemohou je zahrnout do výsledků vyhledávání. [Další informace](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Indexování stránky je blokováno"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indexování stránky není blokováno"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Popisný text odkazů pomáhá vyhledávačům porozumět vašemu obsahu. [Další informace](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Byl nalezen 1 odkaz}few{Byly nalezeny # odkazy}many{Bylo nalezeno # odkazu}other{Bylo nalezeno # odkazů}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Odkazy nemají popisný text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Odkazy mají popisný text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Chcete-li ověřit strukturovaná data, spusťte [nástroj na testování strukturovaných dat](https://search.google.com/structured-data/testing-tool/) a [nástroj Structured Data Linter](http://linter.structured-data.org/). [Další informace](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturovaná data jsou platná"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Obsah metaznaček „description“ může být zahrnut ve výsledcích vyhledávání jako stručný souhrn obsahu stránky. [Další informace](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Popisný text je prázdný."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument nemá metaznačku „description“"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument má metaznačku „description“"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Vyhledávače obsah pluginů nedokážou indexovat a na mnoha zařízeních jsou pluginy zakázány nebo nejsou podporovány. [Další informace](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument používá pluginy"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "V dokumentu nejsou použity pluginy"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Pokud soubor robots.txt nemá správný formát, prohledávače nemusejí být schopné zjistit, jak váš web mají procházet nebo indexovat. [Další informace](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Na žádost o soubor robots.txt byl vrácen tento stav HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Byla nalezena 1 chyba}few{Byly nalezeny # chyby}many{Bylo nalezeno # chyby}other{Bylo nalezeno # chyb}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Nástroji Lighthouse se nepodařilo načíst soubor robots.txt."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Soubor robots.txt není platný"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Soubor robots.txt je platný"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktivní prvky, jako jsou tlačítka a odkazy, by měly být dostatečně velké (48 × 48 px) a mělo by okolo nich být dost místa na to, aby se na ně dalo dostatečně snadno klepnout bez přesahování do dalších prvků. [Další informace](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Podíl dostatečně velkých dotykových prvků: {decimalProportion, number, percent}"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Dotykové prvky jsou příliš malé, protože není k dispozici metaznačka viewport optimalizovaná pro obrazovky mobilních zařízení."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Dotykové prvky nejsou dostatečně velké"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Překrývající se cíl"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Dotykový prvek"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Dotykové prvky jsou dostatečně velké"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service worker je technologie, která aplikaci umožňuje využívat mnoho funkcí progresivní webové aplikace, jako je režim offline, přidání na plochu nebo oznámení push. [Další informace](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Tuto stránku ovládá soubor service worker, nebyl ale nalezen atribut `start_url`, protože se manifest nepodařilo analyzovat jako platný soubor JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Tuto stránku ovládá soubor service worker, ale atribut `start_url` ({startUrl}) pod soubor service worker ({scopeUrl}) nespadá."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Tuto stránku ovládá soubor service worker, ale atribut `start_url` nebyl nalezen, protože nebyl načten žádný manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Tento zdroj má jeden či více souborů service worker, ale stránka ({pageUrl}) pod něj nespadá."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Neregistruje soubor service worker, který ovládá stránku a `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registruje soubor service worker, který ovládá stránku a atribut `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Stylová úvodní obrazovka zajišťuje kvalitní uživatelský dojem při spuštění aplikace z plochy. [Další informace](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Není nakonfigurována vlastní úvodní obrazovka"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Je nakonfigurována vlastní úvodní obrazovka"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Motiv adresního řádku prohlížeče lze přizpůsobit motivu vašeho webu. [Další informace](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nenastavuje barvu motivu adresního řádku."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Nastavuje barvu motivu adresního řádku."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Doba blokování hlavního podprocesu"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Třetí strana"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kód třetích stran může mít významný dopad na rychlost načítání. Omezte počet redundantních externích poskytovatelů a snažte se kód třetích stran načítat až poté, co se dokončí načtení vaší stránky. [Další informace](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kód třetí strany na {timeInMs, number, milliseconds} ms zablokoval hlavní podproces"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Snižte vliv kódu třetích stran"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Použití zdrojů od třetích stran"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Doba do načtení prvního bajtu udává, jak dlouho vašemu serveru trvá, než odešle odpověď. [Další informace](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Hlavní dokument trval {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Zkraťte doby odezvy serverů (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Doby odezvy serveru jsou krátké (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trvání"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Čas zahájení"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Typ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Zkuste v aplikaci pomocí rozhraní User Timing API implementovat měření reálného výkonu při událostech zásadních pro uživatelský dojem. [Další informace](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 časování uživatelů}few{# časování uživatelů}many{# časování uživatelů}other{# časování uživatelů}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Hodnoty časování uživatelů"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Byl nalezen prvek <link> k předběžnému připojení ke zdroji {securityOrigin}, ale prohlížeč jej nepoužil. Zkontrolujte, zda správně používáte atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Zvažte přidání signálů `preconnect` nebo `dns-prefetch`, aby bylo možné včas se připojit k důležitým zdrojům třetích stran. [Další informace](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "K potřebným zdrojům se připojujte předem"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Byl nalezen prvek <link> k předběžnému načtení adresy {preloadURL}, ale prohlížeč jej nepoužil. Zkontrolujte, zda správně používáte atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Zvažte použití značky `<link rel=preload>` k prioritnímu načtení zdrojů, o které se nyní žádá později během načítání stránky. [Další informace](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Klíčové požadavky načítejte předběžně"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Chcete-li aplikaci optimalizovat pro obrazovky mobilních zařízení, přidejte značku `<meta name=\"viewport\">`. [Další informace](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nebyla nalezena značka `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Neobsahuje značku `<meta name=\"viewport\">` s atributem `width` nebo `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Obsahuje značku `<meta name=\"viewport\">` s atributem `width` nebo `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Vaše aplikace by měla zobrazovat nějaký obsah, i v případě, že bude JavaScript zakázaný, i kdyby to mělo být jen upozornění pro uživatele, že k použití aplikace je potřeba JavaScript. [Další informace](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Pokud nejsou k dispozici skripty stránky, v hlavní části stránky by se měl vykreslit nějaký obsah."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Neposkytuje záložní obsah, když není k dispozici JavaScript"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Obsahuje určitý obsah, když není k dispozici JavaScript"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Pokud vytváříte progresivní webovou aplikaci, doporučujeme použít soubor service worker, aby aplikace fungovala i offline. [Další informace](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Stávající stránka nereaguje stavovým kódem 200, když je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Stávající stránka reaguje stavovým kódem 200, když je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Stránka se v režimu offline nemusí načíst, protože testovací adresa URL ({requested}) byla přesměrována na adresu „{final}“. Zkuste druhou adresu otestovat přímo."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení používání specifikace ARIA ve vaší aplikaci, které mohou zlepšit prostředí pro uživatele asistenčních technologií, jako jsou čtečky obrazovek."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Toto jsou příležitosti k poskytnutí alternativního obsahu pro zvuky a videa. Mohou zlepšit prostředí pro sluchově nebo zrakově postižené uživatele."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Zvuk a video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Tyto položky upozorňují na běžné doporučené postupy v oblasti přístupnosti."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Rady a tipy pro odpovídání na recenze"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Tyto kontroly odhalují příležitosti ke [zlepšení přístupnosti webové aplikace](https://developers.google.com/web/fundamentals/accessibility). Automaticky lze odhalit jen část problémů s přístupností, proto obsah doporučujeme otestovat i ručně."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Tyto položky se týkají oblastí, které v současné době automatické testování nedokáže pokrýt. Další informace najdete v průvodci [provedením kontroly přístupnosti](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Přístupnost"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení čitelnosti obsahu."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení interpretace vašeho obsahu u uživatelů různých jazyků."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizace a lokalizace"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení sémantiky ovládacích prvků v aplikaci. Mohou zlepšit prostředí pro uživatele asistenčních technologií, jako jsou například čtečky obrazovek."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Názvy a štítky"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení navigace pomocí klávesnice v aplikaci."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigace"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Toto jsou příležitosti ke zlepšení dojmu při čtení tabulek nebo seznamů pomocí asistenčních technologií, jako je čtečka obrazovky."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabulky a seznamy"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Doporučené postupy"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Výkonové rozpočty nastavují standard pro výkon vašeho webu."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Rozpočty"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Další informace o výkonu vaší aplikace. Tyto hodnoty nemají [přímý vliv](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na skóre výkonu."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Nejkritičtějším aspektem výkonu je rychlost vykreslení pixelů na obrazovce. Klíčové metriky: První vykreslení obsahu, První smysluplné vykreslení"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Vylepšení prvního vykreslení"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Tyto návrhy vám mohou pomoci zrychlit načítání stránky. Na skóre výkonu nemají [přímý vliv](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Příležitosti"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metriky"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Vylepšete celkové chování při načítání, aby byla stránka co nejdříve responzivní a připravena k používání. Klíčové metriky: Doba dosažení interaktivity, Index rychlosti"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Celková vylepšení"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Výkon"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Tyto kontroly vyhodnocují aspekty progresivní webové aplikace. [Další informace](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Tyto kontroly vyžaduje základní [kontrolní seznam aplikace PWA](https://developers.google.com/web/progressive-web-apps/checklist), ale nástroj Lighthouse je automaticky neprovádí. Na vaše skóre vliv nemají, ale je důležité, abyste je ověřili ručně."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresivní webová aplikace"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rychlé a spolehlivé"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Instalovatelné"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimalizováno pro PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Tyto kontroly zajišťují, aby vaše stránka byla optimalizovaná pro hodnocení výsledků ve vyhledávačích. Na hodnocení ve vyhledávání mohou mít vliv i další faktory, které nástroj Lighthouse nekontroluje. [Další informace](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Chcete-li zkontrolovat dodržování dalších doporučených postupů pro SEO, spusťte pro svůj web tyto další validátory."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Naformátujte soubor HTML způsobem, který umožní prohledávačům lépe porozumět obsahu vaší aplikace."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Doporučené postupy pro obsah"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Aby se vaše aplikace mohla zobrazovat ve výsledcích vyhledávání, prohledávače k ní musí mít přístup."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Procházení a indexování"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Zajistěte, aby stránky byly optimalizovány pro mobily a aby uživatelé nemuseli obsah stránky zvětšovat. [Další informace](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Optimalizováno pro mobily"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Hodnota TTL (Time to Live) mezipaměti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Místo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Název"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Požadavky"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Typ zdroje"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Velikost"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Strávený čas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Velikost přenosu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Možná úspora"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Možná úspora"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Lze uspořit {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Lze uspořit {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Písmo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Obrázek"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Média"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Jiné"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Šablona stylů"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Třetí strana"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Celkem"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Při pořizování záznamu trasování během načítání stránky se něco pokazilo. Spusťte nástroj Lighthouse znovu. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Při čekání na počáteční připojení pomocí ladicího protokolu vypršel časový limit."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome při načítání stránky nezískal žádné snímky obrazovky. Zkontrolujte, zda je na stránce vidět nějaký obsah, a poté nástroj Lighthouse zkuste spustit znovu. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Servery DNS zadanou doménu nedokázaly přeložit."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Při získávání povinného zdroje {artifactName} došlo k chybě: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Došlo k interní chybě Chromu. Restartujte Chrome a zkuste nástroj Lighthouse spustit znovu."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Požadovaný shromažďovací nástroj zdroje {artifactName} se nespustil."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Nástroji Lighthouse se požadovanou stránku nepodařilo spolehlivě načíst. Zkontrolujte, zda testujete správnou adresu URL a zda server správně odpovídá na všechny požadavky."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Nástroj Lighthouse adresu URL nemohl spolehlivě načíst, protože stránka přestala reagovat."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Adresa URL, kterou jste zadali, nemá platný bezpečnostní certifikát. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome zabránil načtení stránky a zobrazil vsunutou obrazovku. Zkontrolujte, zda testujete správnou adresu URL a zda server správně odpovídá na všechny požadavky."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Nástroji Lighthouse se požadovanou stránku nepodařilo spolehlivě načíst. Zkontrolujte, zda testujete správnou adresu URL a zda server správně odpovídá na všechny požadavky. (Podrobnosti: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Nástroji Lighthouse se požadovanou stránku nepodařilo spolehlivě načíst. Zkontrolujte, zda testujete správnou adresu URL a zda server správně odpovídá na všechny požadavky. (Stavový kód: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Načtení stránky trvalo příliš dlouho. Podle návrhů v přehledu zkraťte dobu načítání stránky a poté nástroj Lighthouse zkuste spustit znovu. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Při čekání na odpověď protokolu DevTools byla překročena přidělená doba. (Metoda: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Při načítání obsahu zdroje byla překročena přidělená doba"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Adresa URL, kterou jste poskytli, se zdá být neplatná."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Zobrazit audity"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Počáteční navigace"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximální latence kritické trasy:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Chyba!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Chyba přehledu: žádné informace o auditu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratorní data"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analýza aktuální stránky pomocí nástroje [Lighthouse](https://developers.google.com/web/tools/lighthouse/) v emulované mobilní síti. Hodnoty jsou odhady a mohou se lišit."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Další položky k ruční kontrole"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Není relevantní"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Příležitost"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Odhadovaná úspora"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Úspěšné audity"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Sbalit úryvek"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Rozbalit úryvek"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Zobrazit zdroje třetích stran"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Při tomto spuštění nástroje Lighthouse se vyskytly problémy:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Hodnoty jsou odhady a mohou se lišit. Skóre výkonu [vychází pouze z těchto metrik](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Úspěšné audity s upozorněními"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Upozornění: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Zvažte nahrání souboru GIF do služby, pomocí které ho bude možné vložit jako video HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Nainstalujte [plugin služby WordPress pro líné načítání](https://wordpress.org/plugins/search/lazy+load/), který umožňuje odložit načítání obrázků mimo obrazovku, nebo přejděte na motiv, který tuto funkci poskytuje. Zvažte také použití [pluginu AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "K dispozici je celá řada pluginů služby WordPress, které vám pomohou [vložit kritické podklady přímo do kódu](https://wordpress.org/plugins/search/critical+css/) nebo [odložit načítání méně důležitých zdrojů](https://wordpress.org/plugins/search/defer+css+javascript/). Upozorňujeme, že optimalizace pomocí těchto pluginů může narušit funkčnost vašeho motivu nebo pluginů. V kódu proto pravděpodobně budete muset provést změny."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Na reakční dobu serveru mají vliv motivy, pluginy a specifikace serverů. Zvažte vyhledání optimalizovaného motivu, pečlivý výběr optimalizačního pluginu či upgradování serveru."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Zvažte zobrazování ukázek v seznamech příspěvků (např. prostřednictvím značky k načtení dalšího obsahu), snížení počtu příspěvků zobrazených na jedné stránce, rozdělení dlouhých příspěvků na několik stránek nebo použití pluginu k línému načítání komentářů."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "K dispozici je celá řada [pluginů služby WordPress](https://wordpress.org/plugins/search/minify+css/), které web mohou zrychlit zřetězením, minifikací a komprimací stylů. Pokud je to možné, můžete minifikaci provést také předem pomocí procesu sestavení."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "K dispozici je celá řada [pluginů služby WordPress](https://wordpress.org/plugins/search/minify+javascript/), které váš web mohou zrychlit zřetězením, minifikací a zkomprimováním skriptů. Pokud je to možné, můžete minifikaci provést také předem pomocí procesu sestavení."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Zvažte snížení počtu [pluginů služby WordPress](https://wordpress.org/plugins/), které na stránce načítají nevyužité styly CSS. Pluginy, které přidávají nadbytečné styly CSS, můžete vyhledat pomocí funkce [Coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) v nástrojích pro vývojáře v Chromu. Odpovědný motiv či plugin můžete identifikovat podle adresy URL šablony stylů. Hledejte pluginy, které v seznamu mají mnoho šablon stylů, u nichž je při použití funkce Coverage velké množství kódu označeno červeně. Plugin by měl šablonu stylů do fronty zařadit jen v případě, že je na stránce opravdu použita."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Zvažte snížení počtu [pluginů služby WordPress](https://wordpress.org/plugins/), které na stránce načítají nepoužívaný kód JavaScript. Pluginy, které přidávají nadbytečný javascriptový kód, můžete vyhledat pomocí funkce [Coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) v nástrojích pro vývojáře v Chromu. Odpovědný motiv či plugin poznáte podle adresy URL skriptu. Hledejte pluginy, které v seznamu mají mnoho skriptů, u nichž je při použití funkce Coverage velké množství kódu označeno červeně. Plugin by měl skript do fronty zařadit jen v případě, že se na stránce opravdu používá."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Přečtěte si o [ukládání do mezipaměti prohlížeče ve službě WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Zvažte použití [pluginu služby WordPress na optimalizaci obrázků](https://wordpress.org/plugins/search/optimize+images/), který obrázky komprimuje, přičemž zachová jejich kvalitu."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Nahrajte obrázky přímo prostřednictvím [mediální knihovny](https://codex.wordpress.org/Media_Library_Screen), abyste zajistili dostupnost potřebných velikostí obrázků, a poté je vložte z mediální knihovny, případně použití optimálních velikostí obrázků zajistěte pomocí widgetu pro obrázky (včetně obrázků pro responzivní dělicí body). Obrázky v této velikosti: `Full Size` používejte pouze v případě, že jsou jejich rozměry adekvátní k použití. [Další informace](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Můžete v konfiguraci webového serveru zapnout kompresi textu."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Zvažte použití [pluginu](https://wordpress.org/plugins/search/convert+webp/) nebo služby, která nahrané obrázky automaticky převede na optimální formáty."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/da.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/da.json
new file mode 100644
index 00000000000..24412e17f19
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/da.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Med adgangsnøgler kan brugerne hurtigt fokusere på dele af siden. Hver nøgle skal være unik for at navigere korrekt. [Få flere oplysninger](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]`-værdierne er ikke unikke"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`-værdier er unikke"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Hver ARIA-`role` understøtter en bestemt delmængde af `aria-*`-attributter. Hvis der opstår uoverensstemmelser, gøres `aria-*`-attributterne ugyldige. [Få flere oplysninger](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]`-attributterne stemmer ikke overens med deres roller"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]`-attributterne stemmer overens med deres roller"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Nogle ARIA-roller har obligatoriske attributter, der beskriver elementets tilstand for skærmlæsere. [Få flere oplysninger](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`-elementerne har ikke alle de obligatoriske `[aria-*]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`-elementerne har alle obligatoriske `[aria-*]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Nogle overordnede ARIA-roller skal indeholde bestemte underordnede roller for at udføre deres tilsigtede hjælpefunktioner [Få flere oplysninger](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementer med ARIA-rollen `[role]`, der kræver underordnede elementer med en bestemt `[role]`, mangler nogle eller alle disse påkrævede underordnede elementer."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementer med ARIA-rollen `[role]`, der kræver underordnede elementer med en bestemt `[role]`, har alle de påkrævede underordnede elementer."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Nogle underordnede ARIA-roller skal indgå i bestemte overordnede roller for at udføre deres tilsigtede hjælpefunktioner korrekt. [Få flere oplysninger](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`-elementerne indgår ikke i deres påkrævede overordnede element"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`-elementerne indgår i deres påkrævede overordnede element"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA-roller skal have gyldige værdier for at udføre deres tilsigtede hjælpefunktioner. [Få flere oplysninger](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]`-værdierne er ikke gyldige"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]`-værdierne er gyldige"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Hjælpeteknologier som f.eks. skærmlæsere kan ikke fortolke ARIA-attributter med ugyldige værdier. [Få flere oplysninger](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]`-attributterne har ikke gyldige værdier"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]`-attributterne har gyldige værdier"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Hjælpeteknologier som f.eks. skærmlæsere kan ikke fortolke ARIA-attributter med ugyldige navne. [Få flere oplysninger](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]`-attributterne er ikke gyldige eller er stavet forkert"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]`-attributterne er gyldige og er stavet korrekt"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Undertekster hjælper døve og hørehæmmede med at forstå lydelementer, idet de giver vigtige oplysninger som f.eks., hvem der taler, hvad de siger, og andre oplysninger, som ikke er relateret til tale. [Få flere oplysninger](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>`-elementerne mangler et `<track>`-element med `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>`-elementerne indeholder et `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementer, der ikke bestod gennemgangen"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Hvis en knap ikke har et tilgængeligt navn, oplæser skærmlæsere knappen som \"knap\", hvilket gør den ubrugelig for brugere, der anvender skærmlæsere. [Få flere oplysninger](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Knapperne har ikke et tilgængeligt navn"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Knapperne har et tilgængeligt navn"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Tastaturbrugere kan nemmere finde rundt på siden, når der tilføjes metoder til tilsidesættelse af gentagelser. [Få flere oplysninger](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Siden indeholder hverken en heading, et skip link eller en landmark region"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Siden indeholder en heading, et skip link eller en landmark region"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Tekst med lav kontrast er for mange brugere svær eller umulig at læse. [Få flere oplysninger](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Farverne i baggrunden og forgrunden har ikke nok kontrastforhold."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Farverne i baggrunden og forgrunden har nok kontrastforhold"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Hvis lister over definitioner ikke opmærkes korrekt, kan skærmlæseres oplæsning være forvirrende og forkert. [Få flere oplysninger](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`-elementerne indeholder ikke udelukkende korrekt organiserede `<dt>`- og `<dd>`-grupper, `<script>` eller `<template>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`-elementerne indeholder kun korrekt organiserede `<dt>`- og `<dd>`-grupper, `<script>` eller `<template>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Elementer med lister over definitioner (`<dt>` og `<dd>`) skal indkapsles af et overordnet `<dl>`-element for at sikre, at skærmlæsere kan læse dem op korrekt. [Få flere oplysninger](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Elementer med lister over definitioner er ikke indkapslet af `<dl>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Elementer med lister over definitioner er indkapslet af `<dl>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Titlen giver brugere af skærmlæsere et overblik over siden, og brugere af søgemaskiner skal bruge den til at afgøre, om en side er relevant for deres søgning. [Få flere oplysninger](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumentet har ikke et `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumentet har et `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Værdien af en id-attribut skal være unik for at forhindre andre forekomster i at blive overset af hjælpeteknologier. [Få flere oplysninger](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]`-attributterne på siden er ikke unikke"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]`-attributterne på siden er unikke"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Brugere af skærmlæsere har brug for skærmtitler, der beskriver indholdet på skærmen. [Få flere oplysninger](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>`- eller `<iframe>`-elementerne har ikke en titel"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>`- eller `<iframe>`-elementerne har en titel"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Hvis siden ikke angiver en \"lang\"-attribut, antager en skærmlæser, at siden vises på det standardsprog, som brugeren valgte ved konfigurationen af sin skærmlæser. Hvis siden ikke vises på standardsproget, oplæser skærmlæseren muligvis ikke teksten på siden korrekt. [Få flere oplysninger](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-elementet har ikke en `[lang]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-elementet har en `[lang]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Hjælp skærmlæsere med at oplæse tekst korrekt ved at angive et gyldigt [BCP 47-sprog](https://www.w3.org/International/questions/qa-choosing-language-tags#question). [Få flere oplysninger](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-elementet har ikke en gyldig værdi for sin `[lang]`-attribut."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>`-elementet har en gyldig værdi for `[lang]`-attributten"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informative elementer bør anvende en kort, beskrivende alternativ tekst. Dekorative elementer kan ignoreres med en tom alt-attribut. [Få flere oplysninger](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Billedelementerne har ikke `[alt]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Billedelementerne indeholder `[alt]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Når et billede bruges som en `<input>`-knap, kan alternativ tekst hjælpe brugere af skærmlæsere med at forstå knappens formål. [Få flere oplysninger](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">`-elementerne har ikke `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">`-elementerne har `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etiketter sikrer, at formularstyring oplæses korrekt af hjælpeteknologier som f.eks. skærmlæsere. [Få flere oplysninger](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Formularelementerne har ikke tilknyttede etiketter"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Formularelementerne har tilknyttede etiketter"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "En tabel, der bruges til layoutformål, bør ikke indeholde dataelementer som f.eks. th- eller tekstelementer eller oversigtsattributten, da dette kan forvirre brugere af skærmlæsere. [Få flere oplysninger](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "`<table>`-præsentationselementerne undgår ikke at bruge `<th>`, `<caption>` eller attributten `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "`<table>`-præsentationselementerne undgår at bruge `<th>`, `<caption>` eller attributten `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Linktekst (og alternativ tekst til billeder, når de bruges som links), der er skelnelig, unik og fokuserbar, gør det nemmere for brugere af skærmlæsere at finde rundt. [Få flere oplysninger](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Linkene har ikke skelnelige navne"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Linkene har skelnelige navne"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Skærmlæsere oplæser lister på en bestemt måde. Du kan forbedre skærmlæsernes output ved at angive en ordentlig listestruktur. [Få flere oplysninger](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listerne indeholder ikke kun `<li>`-elementer og elementer, der understøtter scripts (`<script>` og `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listerne indeholder kun `<li>`-elementer og elementer, der understøtter scripts (`<script>` og `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Skærmlæsere kræver, at listeelementer (`<li>`) indgår i et overordnet `<ul>`- eller `<ol>`-element for at blive oplæst korrekt. [Få flere oplysninger](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Listeelementerne (`<li>`) indgår ikke i de overordnede `<ul>`- eller `<ol>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Listeelementerne (`<li>`) indgår i de overordnede `<ul>`- eller `<ol>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Brugere forventer ikke, at en side opdateres automatisk, og automatisk opdatering flytter fokus tilbage til toppen af siden. Dette kan være frustrerende og forvirrende for brugerne. [Få flere oplysninger](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumentet bruger `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumentet bruger ikke `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Hvis zoom deaktiveres, kan det skabe problemer for svagtseende brugere, der har brug for skærmforstørrelse til at se indholdet på en webside. [Få flere oplysninger](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` anvendes i elementet `<meta name=\"viewport\">`, eller attributten `[maximum-scale]` er mindre end 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` anvendes ikke i `<meta name=\"viewport\">`-elementet, og attributten `[maximum-scale]` er ikke mindre end 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Skærmlæsere kan ikke oversætte indhold, som ikke er tekst. Du kan føje alternativ tekst til `<object>`-elementer for at hjælpe skærmlæsere med at formidle meningen til brugerne. [Få flere oplysninger](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>`-elementerne har ikke `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>`-elementerne har `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "En værdi over 0 antyder en utvetydig sortering af navigation. Selvom dette teknisk er gyldigt, skaber det ofte en frustrerende oplevelse for brugere, der anvender hjælpeteknologier. [Få flere oplysninger](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Nogle elementer har en `[tabindex]`-værdi, som er større end 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Ingen af elementerne har en `[tabindex]`-værdi, der overstiger 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Skærmlæsere har funktioner, der gør det nemmere at finde rundt i tabeller. Du kan give brugere af skærmlæsere en bedre oplevelse ved at sikre, at `<td>`-celler, der anvender attributten `[headers]`, kun henviser til andre celler i samme tabel. [Få flere oplysninger](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Celler i et `<table>`-element, der anvender attributten `[headers]`, henviser til et element `id`, som ikke findes i samme tabel."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Celler i et `<table>`-element, der anvender attributten `[headers]`, henviser til tabelceller i den samme tabel."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Skærmlæsere har funktioner, der gør det nemmere at finde rundt i tabeller. Du kan give brugere af skærmlæsere en bedre oplevelse ved at sikre, at tabeloverskrifter altid henviser til nogle cellesæt. [Få flere oplysninger](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>`-elementerne og elementerne med `[role=\"columnheader\"/\"rowheader\"]` indeholder ikke de dataceller, de beskriver."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>`-elementerne og elementer med `[role=\"columnheader\"/\"rowheader\"]` indeholder de dataceller, de beskriver."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Hjælp med at sikre, at tekst udtales korrekt af skærmlæsere, ved at angive et gyldigt [BCP 47-sprog](https://www.w3.org/International/questions/qa-choosing-language-tags#question) for elementer. [Få flere oplysninger](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]`-attributterne har ikke en gyldig værdi"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]`-attributterne har en gyldig værdi"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Det er nemmere for døve og hørehæmmede at få adgang til en videos oplysninger, hvis videoen tilbyder undertekster. [Få flere oplysninger](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>`-elementerne indeholder ikke et `<track>`-element med `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>`-elementerne indeholder et `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Lydbeskrivelser giver relevante oplysninger om videoer, som ikke fremgår af dialogen, f.eks. ansigtsudtryk og scener. [Få flere oplysninger](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>`-elementerne indeholder ikke et `<track>`-element med `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>`-elementerne indeholder et `<track>`-element med `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Angiv et `apple-touch-icon` for at optimere iOS-brugerfladen, når brugere føjer en progressiv app til startskærmen. Det skal føre til en ikke-transparent firkantet PNG på 192 px (eller 180 px). [Få flere oplysninger](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Angiver ikke en gyldig `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` er forældet, og `apple-touch-icon` foretrækkes."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Angiver et gyldigt `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome-udvidelser påvirkede denne sides indlæsning negativt. Prøv at revidere siden i inkognitotilstand eller fra en Chrome-profil uden udvidelser."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Scriptevaluering"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Scriptparsing"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Samlet CPU-tid"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Overvej at reducere den tid, der bruges på at parse, kompilere og udføre JavaScript. Levering af mindre JavaScript-datapakker kan hjælpe med dette. [Få flere oplysninger](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reducer udførelsestiden for JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Udførelsestid for JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Store giffer er mindre effektive til at levere animeret indhold. Du kan også overveje at bruge MPEG4-/WebM-videoer til animationer og PNG/WebP til statiske billeder i stedet for giffer for at spare netværksbytes. [Få flere oplysninger](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Brug videoformater til animeret indhold"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Overvej at udskyde indlæsningen af skjulte billeder og billeder, der ikke er på skærmen, til efter alle kritiske ressourcer er blevet indlæst for at reducere den tid, der går, inden siden bliver interaktiv. [Få flere oplysninger](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Udskyd billeder, der ikke er på skærmen"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ressourcer blokerer for første visning af din side. Overvej at levere kritisk JavaScript/CSS indlejret og udskyde alle ikke-kritiske JavaScript-elementer/typografier. [Få flere oplysninger](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Fjern ressourcer til blokering af gengivelse"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Store datapakker på netværk koster brugerne mange penge og er forbundet med lang indlæsningstid. [Få flere oplysninger](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Den samlede størrelse var {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Undgå kæmpe datapakker på netværk"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Undgår kæmpe datapakker på netværk"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Formindskelse af CSS-filer kan reducere størrelsen på datapakker på netværk. [Få flere oplysninger](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Formindsk CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Formindskelse af JavaScript-filer kan reducere størrelsen på datapakker og varigheden af scriptparsing. [Få flere oplysninger](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Formindsk JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Skær ned på unødvendigt forbrug af bytes i forbindelse med netværksaktivitet ved at fjerne forældede regler fra typografiark og udskyde indlæsning af CSS, der ikke bruges til indhold over skillelinjen. [Få flere oplysninger](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Fjern CSS, som ikke bruges"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Fjern JavaScript, der ikke bruges, for at skære ned på antallet af bytes, der anvendes ved netværksaktivitet."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Fjern JavaScript, som ikke bruges"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "En lang cachelevetid kan gøre indlæsningen hurtigere for tilbagevendende besøgende på din side. [Få flere oplysninger](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Der blev fundet 1 ressource}one{Der blev fundet # ressource}other{Der blev fundet # ressourcer}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Vis statiske aktiver med en effektiv cachepolitik"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Anvender effektiv cachepolitik på statiske aktiver"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimerede billeder indlæses hurtigere og bruger mindre mobildata. [Få flere oplysninger](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Kryptér billeder effektivt"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Vis billeder i korrekte størrelser for at spare mobildata og forbedre indlæsningstiden. [Få flere oplysninger](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Brug korrekte billedstørrelser"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstbaserede ressourcer bør vises i komprimeret format (gzip, Deflate eller Brotli), så netværkets samlede antal bytes formindskes. [Få flere oplysninger](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Aktivér tekstkomprimering"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Billedformater såsom JPEG 2000, JPEG XR og WebP giver ofte en bedre komprimering end PNG og JPEG, hvilket betyder hurtigere downloads og mindre dataforbrug. [Få flere oplysninger](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Vis billeder i formater af næste generation"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Hvis bredden på indholdet i din app ikke stemmer overens med bredden på din visning, bliver din app muligvis ikke optimeret til mobilskærme. [Få flere oplysninger](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Visningens størrelse på {innerWidth} px stemmer ikke overens med vinduets størrelse på {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Indholdet har ikke den rigtige størrelse til visningen"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Indholdet har den rigtige størrelse til visningen"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Kæderne med kritiske anmodninger nedenfor viser dig, hvilke ressourcer der indlæses med høj prioritet. Overvej at reducere kædernes længde, så ressourcernes downloadstørrelse bliver mindre, eller at udskyde download af unødvendige ressourcer, så sideindlæsningen forbedres. [Få flere oplysninger](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Der blev fundet 1 kæde}one{Der blev fundet # kæde}other{Der blev fundet # kæder}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimer dybden for kritiske anmodninger"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Udfasning/advarsel"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linje"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Udfasede API'er fjernes med tiden fra browseren. [Få flere oplysninger](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 advarsel blev fundet}one{# advarsel blev fundet}other{# advarsler blev fundet}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Bruger udfasede API'er"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Undgår udfasede API'er"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache er udfaset. [Få flere oplysninger](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" blev fundet"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Bruger Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Undgår Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Når der angives en dokumenttype, forhindres browseren i at skifte til quirks-tilstand. [Få flere oplysninger](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Navnet på dokumenttypen skal være en `html`-streng med små bogstaver"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumentet skal indeholde en doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "En tom streng var forventet for publicId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "En tom streng var forventet for systemId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Siden mangler dokumenttypen HTML og aktiverer derfor quirks-tilstand"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Siden har dokumenttypen HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistik"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Værdi"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Browserudviklere anbefaler, at sider højst indeholder 1.500 DOM-elementer. Det bedste er en træstrukturdybde med under 32 elementer og færre end 60 underordnede/overordnede elementer. En stor DOM kan øge hukommelsesforbruget, medføre længere [beregninger af typografi](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) og resultere i dyre [omformateringer af layout](https://developers.google.com/speed/articles/reflow). [Få flere oplysninger](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}one{# element}other{# elementer}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Undgå en overdreven DOM-størrelse"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimal DOM-dybde"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Samlet antal DOM-elementer"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Højeste antal underordnede elementer"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Undgår en overdreven DOM-størrelse"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Mål"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Føj `rel=\"noopener\"` eller `rel=\"noreferrer\"` til alle eksterne links for at forbedre ydeevnen og forhindre sikkerhedssårbarheder. [Få flere oplysninger](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links til destinationer af anden oprindelse er ikke sikre"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links til destinationer af anden oprindelse er sikre"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Destinationen for ankeret ({anchorHTML}) kunne ikke identificeres. Hvis det ikke bruges som hyperlink, bør du overveje at fjerne target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Brugere er mistænksomme over for eller forvirres af websites, der anmoder om deres placering uden sammenhæng. Overvej at knytte anmodningen til en brugerhandling i stedet for. [Få flere oplysninger](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Anmoder om tilladelse til geoplacering ved indlæsning af siden"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Undgår at anmode om tilladelse til geoplacering ved indlæsning af siden"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Alle JavaScript-biblioteker i frontend, der registreres på siden. [Få flere oplysninger](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Registrerede JavaScript-biblioteker"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Eksterne scripts, der indsættes dynamisk via `document.write()`, kan forsinke sideindlæsningen med flere sekunder for brugere med langsomme forbindelser. [Få flere oplysninger](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Bruger `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Undgår `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Størst omfang"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Biblioteksversion"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Antal sårbarheder"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Nogle scripts fra tredjeparter kan indeholde kendte sikkerhedssårbarheder, som let kan identificeres og udnyttes af hackere. [Få flere oplysninger](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 sårbarhed blev registreret}one{# sårbarhed blev registreret}other{# sårbarheder blev registreret}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Indeholder JavaScript-biblioteker i frontend med kendte sikkerhedssårbarheder"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Høj"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Lavt"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Middel"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Undgår frontend JavaScript-biblioteker med kendte sikkerhedssårbarheder"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Brugere er mistænksomme over for eller forvirres af websites, der anmoder om at sende notifikationer uden sammenhæng. Overvej at knytte anmodningen til brugerbevægelser i stedet for. [Få flere oplysninger](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Anmoder om tilladelse til notifikationer ved indlæsning af siden"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Undgår at anmode om tilladelse til notifikationer ved indlæsning af siden"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementer, der ikke bestod gennemgangen"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "En god sikkerhedspolitik undermineres ved at forhindre indsættelse af adgangskoder. [Få flere oplysninger](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Forhindrer brugere i at indsætte indhold i adgangskodefelter"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Tillader, at brugere indsætter indhold i adgangskodefelter"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 tilbyder mange fordele i forhold til HTTP/1.1, herunder binære headers, multipleksing og server push. [Få flere oplysninger](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 anmodning blev ikke leveret via HTTP/2}one{# anmodning blev ikke leveret via HTTP/2}other{# anmodninger blev ikke leveret via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Anvender ikke HTTP/2 til alle sine ressourcer"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Anvender HTTP/2 til egne ressourcer"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Overvej at markere hændelsesfunktionerne for tryk og hjul som `passive` for at forbedre effektiviteten ved rulning på siden. [Få flere oplysninger](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Anvender ikke passive hændelsesfunktioner til at forbedre rulning"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Anvender passive hændelsesfunktioner til at forbedre rulning"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Beskrivelse"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Fejl, der er logført i konsollen, angiver uløste problemer. De kan stamme fra mislykkede netværksanmodninger og andre browserproblemer. [Få flere oplysninger](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Der blev logført browserfejl i konsollen"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Der blev ikke logført nogen browserfejl i konsollen"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Udnyt CSS-funktionen til skrifttypevisning for at sikre, at teksten kan ses af brugerne, mens webfonts indlæses. [Få flere oplysninger](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Sørg for, at tekst forbliver synlig under indlæsning af webfont"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Al tekst forbliver synlig under indlæsning af webfont"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse kunne ikke automatisk tjekke visningsværdien for skrifttyper for den følgende webadresse: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Billedformat (faktisk)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Billedformat (vist)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Størrelsen for billedvisningen bør matche det naturlige billedformat. [Få flere oplysninger](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Viser billeder med forkert billedformat"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Viser billeder med korrekt billedformat"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Oplysningerne om billedstørrelse er ikke gyldige {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browsere kan proaktivt bede brugere om at føje din app til deres startskærm, hvilket kan medføre større interaktion. [Få flere oplysninger](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Webappens manifest opfylder ikke kravene til installation"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Webappens manifest opfylder kravene til installation"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Usikker webadresse"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Alle websites bør beskyttes med HTTPS, selv websites, der ikke håndterer følsomme oplysninger. HTTPS forhindrer uvedkommende i at manipulere med eller passivt lytte med på kommunikationen mellem din app og dine brugere og er en forudsætning for HTTP/2 og mange nye webplatform-API'er. [Få flere oplysninger](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 usikker anmodning blev fundet}one{# usikker anmodning blev fundet}other{# usikre anmodninger blev fundet}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Anvender ikke HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Bruger HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Hurtig sideindlæsning via mobilnetværk sikrer en god oplevelse for mobilbrugere. [Få flere oplysninger](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktiv efter {timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktiv på simuleret mobilnetværk efter {timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Din side indlæser for langsomt og bliver ikke interaktiv inden for 10 sekunder. Se mulighederne og diagnostik i sektionen \"Effektivitet\" for at finde ud af, hvordan du forbedrer den."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Sideindlæsning er ikke hurtig nok på mobilnetværk"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Sideindlæsning er hurtig nok på mobilnetværk"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategori"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Overvej at reducere den tid, der bruges på at parse, kompilere og udføre JavaScript. Levering af mindre JavaScript-datapakker kan hjælpe med dette. [Få flere oplysninger](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Formindsk primært trådarbejde"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Formindsker primært trådarbejde"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Websites bør fungere på alle populære browsere, så de når ud til flest mulige brugere. [Få flere oplysninger](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Websitet fungerer i forskellige browsere"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Sørg for, at der kan føjes et dybt link til individuelle sider via en webadresse, og at denne webadresse er unik, så den kan deles på sociale medier. [Få flere oplysninger](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Hver side har en webadresse"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Overgange bør være hurtige, når der trykkes på forskellige elementer, også selvom netværket er langsomt. Det er afgørende for brugerens opfattelse af effektiviteten. [Få flere oplysninger](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Det føles ikke som om sideovergange blokeres på netværket"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Estimeret inputforsinkelse er en anslået værdi af, hvor længe din app er om at reagere på brugerinput i millisekunder i det travleste femsekundersvindue under en sideindlæsning. Hvis din forsinkelse er længere end 50 ms, kan brugerne opfatte din app som langsom. [Få flere oplysninger](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Estimeret inputforsinkelse"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Første visning af indhold markerer tidspunktet, hvor den første tekst eller det første billede vises. [Få flere oplysninger](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Første udfyldning af indhold"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Første stillestående CPU markerer det tidspunkt, hvor sidens primære tråd er stabil nok til at behandle input. [Få flere oplysninger](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Første stillestående CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Første meningsfulde visning måler, hvornår det primære indhold på en side kan ses. [Få flere oplysninger](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Første betydningsfulde udfyldning"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Tid inden interaktiv tilstand er den mængde tid, det tager, før siden er helt interaktiv. [Få flere oplysninger](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tid inden interaktiv tilstand"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Den maksimale potentielle ventetid efter første input, som dine brugere kan opleve, er varigheden i millisekunder af den længste proces. [Få flere oplysninger](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks. potentiel ventetid efter første input"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Hastighedsindekset viser, hvor hurtigt indholdet på en side er visuelt udfyldt. [Få flere oplysninger](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Hastighedsindeks"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Summen af alle tidsrum mellem første visning af indhold og tid inden interaktiv tilstand, når proceslængden overstiger 50 ms, udtrykt i millisekunder."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Samlet blokeringstid"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Netværkets pingtid har stor indflydelse på ydeevnen. Hvis pingtiden til et oprindelsespunkt er lang, er det tegn på, at servere, der er tættere på brugeren, kan forbedre ydeevnen. [Få flere oplysninger](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Pingtider for netværk"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Serverforsinkelser kan have indvirkning på websitets ydeevne. Hvis serverforsinkelsen for et oprindelsespunkt er høj, er det tegn på, at serveren er overbelastet, eller at backend-ydeevnen er dårlig. [Få flere oplysninger](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Forsinkelser for serverens backend"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "En scripttjeneste gør din webapp pålidelig ved uforudseelige netværksforhold. [Få flere oplysninger](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` svarer ikke med en 200-kode, når det er offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` svarer med 200-kode, når det er offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse kunne ikke læse `start_url` fra manifestet. `start_url` blev derfor betragtet som dokumentets webadresse. Fejlmeddelelse: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Over budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Sørg for, at antallet af og størrelsen på netværksanmodningerne ikke overskrider målene i det angivne budget for ydeevne. [Få flere oplysninger](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 anmodning}one{# anmodning}other{# anmodninger}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Budget for ydeevne"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Hvis du allerede har konfigureret HTTPS, skal du sørge for at omdirigere al HTTP-trafik, så alle dine brugere får sikre webfunktioner. [Få flere oplysninger](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Omdirigerer ikke HTTP-trafik til HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Omdirigerer HTTP-trafik til HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Omdirigeringer medfører yderligere forsinkelser, inden siden kan indlæses. [Få flere oplysninger](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Undgå mange sideomdirigeringer"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Tilføj en budget.json-fil for at angive budgetter for antallet af og størrelsen på sideressourcer. [Få flere oplysninger](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 anmodning • {byteCount, number, bytes} kB}one{# anmodning • {byteCount, number, bytes} kB}other{# anmodninger • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Sørg for, at antallet af anmodninger er lavt, og at overførslerne ikke er for store"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanoniske links foreslår, hvilken webadresse der skal vises i søgeresultater. [Få flere oplysninger](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Flere webadresser ({urlList}) er modstridende"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Peger på et andet domæne ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Ugyldig webadresse ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Peger på en anden placering for `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativ webadresse ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Peger på domænets rodwebadresse (startsiden) i stedet for en tilsvarende side med indhold"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumentet har ikke et gyldigt `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumentet har et gyldigt `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Skriftstørrelser på mindre end 12 pixel er for små til at være læselige og kræver, at mobilbrugere \"kniber fingrene sammen for at zoome\" for at læse teksten. Du bør bestræbe dig på at gøre over 60 % af sideteksten større end eller lig med 12 pixel. [Få flere oplysninger](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} læselig tekst"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Teksten er ulæselig, fordi der ikke er et viewport-metatag, som er optimeret til mobilskærme."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} af teksten er for lille (baseret på et eksempel på {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumentet bruger ikke læselige skriftstørrelser"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumentet anvender læselige skriftstørrelser"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang-links fortæller søgemaskiner, hvilken version af en side de skal angive på listen over søgeresultater for et vilkårligt sprog eller område. [Få flere oplysninger](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumentet har ikke en gyldig `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumentet har et gyldigt `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Sider med ugyldige HTTP-statuskoder indekseres muligvis ikke korrekt. [Få flere oplysninger](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "HTTP-statuskoden for siden er ugyldig"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "HTTP-statuskoden for siden er gyldig"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Søgemaskiner kan ikke medtage dine sider i søgeresultater, hvis de ikke har tilladelse til at crawle dem. [Få flere oplysninger](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Siden er blokeret for indeksering"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Siden er ikke blokeret for indeksering"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Beskrivende linktekst hjælper søgemaskiner med at forstå dit indhold. [Få flere oplysninger](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Der blev fundet 1 link}one{Der blev fundet # link}other{Der blev fundet # links}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linkene har ikke beskrivende tekst"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linkene har beskrivende tekst"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Kør [testværktøjet til strukturerede data](https://search.google.com/structured-data/testing-tool/) og [Structured Data Linter](http://linter.structured-data.org/) for at validere strukturerede data. [Få flere oplysninger](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "De strukturerede data er gyldige"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metabeskrivelser kan medtages i søgeresultater for kortfattet at opsummere sideindhold. [Få flere oplysninger](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Beskrivelsesteksten er tom."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumentet har ikke en metabeskrivelse"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumentet har en metabeskrivelse"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Søgemaskiner kan ikke indeksere indhold i plugins, og mange enheder begrænser plugins eller understøtter dem ikke. [Få flere oplysninger](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumentet bruger plugins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumentet undgår plugins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Hvis din robots.txt-fil indeholder fejl, kan crawlere muligvis ikke forstå, hvordan du vil have dit website crawlet eller indekseret. [Få flere oplysninger](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Anmodningen om robots.txt returnerede følgende HTTP-status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Der blev fundet 1 fejl}one{Der blev fundet # fejl}other{Der blev fundet # fejl}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse kunne ikke downloade en robots.txt-fil"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt er ikke gyldig"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt er gyldig"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktive elementer som f.eks. knapper og links skal være store nok (48 x 48 px) og have tilstrækkelig plads omkring sig for at gøre det let at trykke på dem uden at overlappe andre elementer. [Få flere oplysninger](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} trykbare elementer med passende størrelse"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Trykbare elementer er for små, fordi der ikke er et viewport-metatag, som er optimeret til mobilskærme"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Trykbare elementer har ikke en passende størrelse"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Overlappende mål"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Trykbart element"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Trykbare elementer har en passende størrelse"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Scripttjenesten er den teknologi, der gør det muligt for din app at bruge mange funktioner til progressive webapps, f.eks. offline, tilføjelse på startskærme og push-notifikationer. [Få flere oplysninger](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Denne side styres af en scripttjeneste, men der blev ikke fundet noget `start_url`, fordi manifestet ikke kunne parse den som en gyldig JSON-fil"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Denne side styres af en scripttjeneste, men `start_url` ({startUrl}) er ikke omfattet af scripttjenesten ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Denne side styres af en scripttjeneste, men der blev ikke fundet nogen `start_url`, da der ikke blev hentet noget manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Dette website har én eller flere scripttjenester, men siden ({pageUrl}) er ikke omfattet af disse."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Registrerer ikke en scripttjeneste, der styrer siden og `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registrerer en scripttjeneste, der styrer siden og `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "En splash-skærm med tema sikrer, at brugerne får en god oplevelse, når de starter din app på deres startskærm. [Få flere oplysninger](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Websitet er ikke konfigureret til en tilpasset splash-skærm"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigureret til en tilpasset splash-skærm"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Der kan angives et tema for browserens adresselinje, som matcher dit website. [Få flere oplysninger](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Angiver ikke en temafarve til adresselinjen."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Angiver en temafarve til adresselinjen."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tidspunkt for blokering af den primære tråd"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tredjepart"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kode fra tredjeparter kan have en væsentlig indvirkning på indlæsningen. Begræns antallet af overflødige tredjepartsudbydere, og prøv at indlæse kode fra tredjeparter, når indlæsningen af siden næsten er færdig. [Få flere oplysninger](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Tredjepartskode blokerede den primære tråd i {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reducer virkningen af tredjepartskode"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Tredjepartsbrug"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "TTFB (Time To First Byte) identificerer tidspunktet for, hvornår din server sender et svar. [Få flere oplysninger](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Roddokumentet tog {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reducer serversvartider (TTFB, Time To First Byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Serversvartiderne er korte (TTFB, Time To First Byte)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Varighed"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Starttidspunkt"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Du kan også vælge at bruge User Timing API som værktøj til din app for at måle appens ydeevne i den virkelige verden i forbindelse med vigtige brugeroplevelser. [Få flere oplysninger](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 brugstid}one{# brugstid}other{# brugstider}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Brugstider markerer og måler"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Der blev fundet et <link>, der kan oprette forbindelse på forhånd for \"{securityOrigin}\", men det blev ikke brugt af browseren. Tjek, at du bruger attributten `crossorigin` korrekt."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Overvej at tilføje ressourcehints til `preconnect` eller `dns-prefetch` for at oprette tidlige forbindelser til vigtige tredjepartswebsites. [Få flere oplysninger](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Opret forbindelse på forhånd til påkrævede websites"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Der blev fundet et <link> til forudindlæsning for \"{preloadURL}\", men det blev ikke brugt af browseren. Tjek, at du bruger attributten `crossorigin` korrekt."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Overvej at bruge `<link rel=preload>` til at prioritere hentning af ressourcer, der er anmodet om senere i sideindlæsningen. [Få flere oplysninger](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Forudindlæs vigtige anmodninger"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Tilføj et `<meta name=\"viewport\">`-tag for at optimere din app til mobilskærme. [Få flere oplysninger](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Der blev ikke fundet noget `<meta name=\"viewport\">`-tag"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Der ikke noget `<meta name=\"viewport\">`-tag med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Der er et `<meta name=\"viewport\">`-tag med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Din app bør vise noget indhold, når JavaScript er deaktiveret, også selvom det bare er en advarsel til brugeren om, at JavaScript er påkrævet for at bruge appen. [Få flere oplysninger](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Teksten på siden bør gengive noget indhold, hvis dens script ikke er tilgængelig."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Angiver ikke reserveindhold, når JavaScript ikke er tilgængelig"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Indeholder noget indhold, når JavaScript ikke er tilgængelig"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Hvis du er ved at udvikle en progressiv webapp, kan du overveje at bruge en scripttjeneste, så din app kan fungere offline. [Få flere oplysninger](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Den aktuelle side svarer ikke med en 200-kode, når den er offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Den aktuelle side svarer med en 200-kode, når den er offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Siden indlæser muligvis ikke offline, da din testwebadresse ({requested}) blev omdirigeret til \"{final}\". Prøv at teste den anden webadresse direkte."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Disse er muligheder for at forbedre brugen af ARIA i din app, hvilket kan forbedre oplevelsen for brugere af hjælpeteknologi, f.eks. skærmlæsere."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Disse er muligheder for at angive alternativt indhold for lyd og video. Dette kan forbedre oplevelsen for brugere med nedsat hørelse eller syn."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Lyd og video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Disse elementer fremhæver almindelige optimale løsninger for hjælpefunktioner."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Optimale løsninger"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Disse kontroller fremhæver muligheder for at [forbedre tilgængeligheden af din webapp](https://developers.google.com/web/fundamentals/accessibility). Det er kun visse tilgængelighedsproblemer, der kan registreres automatisk, og derfor anbefales det også at teste manuelt."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Disse elementer omhandler områder, som et automatisk testværktøj ikke kan dække. Få flere oplysninger ved at læse vores vejledning i, hvordan du [udfører en gennemgang af hjælpefunktioner](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Hjælpefunktioner"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Disse er muligheder for at forbedre forståelsen af dit indhold."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Disse er muligheder for at gøre det nemmere for brugere med forskellige landestandarder at forstå dit indhold."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisering og lokalisering"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Disse er muligheder for at forbedre semantikken i styringen af din app. De kan forbedre oplevelsen for brugere af hjælpeteknologi, f.eks. skærmlæsere."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Navne og etiketter"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Disse er muligheder for at forbedre tastaturnavigation i din app."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Disse er muligheder for at forbedre oplevelsen af oplæste tabel- eller listedata ved hjælp af hjælpeteknologi som f.eks. en skærmlæser."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabeller og lister"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Optimale løsninger"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Budgetter for ydeevne angiver standarder for dit websites ydeevne."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgetter"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Få flere oplysninger om din apps ydeevne. Resultatet [påvirkes ikke direkte](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) af disse tal."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostik"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Det vigtigste aspekt af effektivitet er, hvor hurtigt pixels gengives på skærmen. Vigtige metrics: Første udfyldning af indhold, Første betydningsfulde udfyldning"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Forbedringer af første udfyldning"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Disse forslag kan være med til at forbedre indlæsningstiden for din side. De [berører ikke direkte](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) resultatet."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Muligheder"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrics"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Gør den overordnede indlæsning bedre, så siden hurtigst muligt bliver responsiv og klar til brug. Vigtige metrics: Tid inden interaktiv tilstand, Hastighedsindeks"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Overordnede forbedringer"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Effektivitet"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Disse tjek validerer aspekterne af en progressiv webapp. [Få flere oplysninger](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Disse tjek kræves af den grundlæggende [tjekliste til progressive webapps](https://developers.google.com/web/progressive-web-apps/checklist), men de udføres ikke automatisk af Lighthouse. De påvirker ikke dine resultater, men det er vigtigt, at du bekræfter dem manuelt."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressiv webapp"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Hurtig og pålidelig"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Websitet kan installeres"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA-optimeret"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Disse kontroller sikrer, at din side er optimeret i forhold til rangering i søgemaskineresultater. Der findes andre faktorer, som Lighthouse ikke tjekker, og som kan påvirke din rangering i søgninger. [Få flere oplysninger](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Kør disse yderligere valideringer på dit website for at tjekke andre optimale SEO-løsninger."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatér din HTML på en sådan måde, at den gør det lettere for crawlere at forstå indholdet i din app."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Optimale løsninger for indhold"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Hvis dit website skal vises i søgeresultater, skal crawlere have adgang til din app."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawl og indeksering"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Sørg for, at dine sider er mobilvenlige, så brugere ikke behøver at knibe fingrene sammen eller zoome ind for at se indholdet. [Få flere oplysninger](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobilvenlig"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache-TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Placering"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Navn"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Anmodninger"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Ressourcetype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Størrelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tidsforbrug"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Overførselsstørrelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "Webadresse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potentiel besparelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potentiel besparelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potentiel besparelse på {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potentiel besparelse på {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Skrifttype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Billede"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Medier"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Andet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Typografiark"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tredjepart"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "I alt"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Der opstod en fejl ved registreringen af din sideindlæsning. Kør Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Der opstod timeout under ventetiden til den indledende forbindelse til Debugger-protokollen."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome indsamlede ikke nogen screenshots under sideindlæsningen. Sørg for, at der er synligt indhold på siden, og prøv derefter at køre Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-serverne kunne ikke løse problemet med det angivne domæne."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Der opstod en fejl i den obligatoriske {artifactName}-indsamler: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Der opstod en intern Chrome-fejl. Genstart Chrome, og prøv at køre Lighthouse igen."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Den obligatoriske {artifactName}-indsamler blev ikke kørt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse kunne ikke indlæse den side, du anmodede om. Sørg for at teste den rigtige webadresse, og tjek, at serveren svarer korrekt på alle anmodninger."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse kunne ikke indlæse den webadresse, du anmodede om, da siden stoppede med at svare."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Den webadresse, du har angivet, har ikke et gyldigt sikkerhedscertifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome forhindrede indlæsning af en side med en mellemliggende annonce. Sørg for, at du tester den rigtige webadresse, og tjek, at serveren svarer korrekt på alle anmodninger."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse kunne ikke indlæse den side, du anmodede om. Sørg for, at du tester den rigtige webadresse, og tjek, at serveren svarer korrekt på alle anmodninger. (Info: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse kunne ikke indlæse den side, du anmodede om. Sørg for, at du tester den rigtige webadresse, og tjek, at serveren svarer korrekt på alle anmodninger. (Statuskode: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Det tog for lang tid at indlæse siden. Benyt mulighederne i rapporten for at reducere indlæsningstiden for din side. Prøv derefter at køre Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools-protokollen har overskredet den tilladte ventetid for svar. (Metode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Hentning af ressourceindhold har taget længere tid end tilladt"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Den angivne webadresse lader til at være ugyldig."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Se revisioner"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Indledende navigation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimal forsinkelse for kritisk sti:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Der opstod en fejl"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Rapportfejl: Der er ingen revisionsoplysninger"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratoriedata"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/)-analyse af den aktuelle side på et emuleret mobilnetværk. Værdierne er estimater og kan variere."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Yderligere elementer, der skal tjekkes manuelt"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Ikke relevant"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Mulighed"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estimeret tidsbesparelse"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Beståede revisioner"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Skjul uddrag"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Udvid uddrag"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Vis ressourcer fra tredjeparter"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Der blev registreret problemer, som påvirkede denne kørsel af Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Værdierne er estimater og kan variere. Resultatet er [kun baseret på disse metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Bestod revisioner, men med advarsler"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Advarsler! "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Overvej at uploade din gif til en tjeneste, hvor den kan integreres som en HTML5-video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installer et [WordPress-plugin til udskudt indlæsning](https://wordpress.org/plugins/search/lazy+load/), der gør det muligt at udskyde eventuelle billeder, som ikke er på skærmen, eller skifte til et tema, der leverer denne funktionalitet. Overvej også at bruge [AMP-pluginnet](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Der er en række WordPress-plugins, som kan hjælpe dig med at [indlejre vigtige aktiver](https://wordpress.org/plugins/search/critical+css/) eller [udskyde mindre vigtige ressourcer](https://wordpress.org/plugins/search/defer+css+javascript/). Vær opmærksom på, at optimeringer via disse plugins kan ødelægge funktioner i dine temaer og plugins. Du bliver derfor sandsynligvis nødt til at foretage kodeændringer."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Temaer, plugins og serverspecifikationer påvirker alle serverens svartid. Overvej at finde et mere optimeret tema, vælge et plugin til optimering og/eller opgradere din server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Overvej at vise uddrag på dine opslagslister (f.eks. via tagget Mere), reducere antallet af viste opslag på en given side, opdele dine lange opslag i flere sider eller bruge et plugin til at indlæse kommentarer langsomt."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "En række [WordPress-plugins](https://wordpress.org/plugins/search/minify+css/) kan gøre dit website hurtigere ved at sammenkæde, formindske og komprimere dine typografier. Det kan også være en god idé at bruge en buildproces til at udføre denne formindskelse på forhånd, hvis det er muligt."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "En række [WordPress-plugins](https://wordpress.org/plugins/search/minify+javascript/) kan gøre dit website hurtigere ved at sammenkæde, formindske og komprimere dine scripts. Det kan også være en god idé at bruge en buildproces til at udføre denne formindskelse på forhånd, hvis det er muligt."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Overvej at reducere eller ændre antallet af [WordPress-plugins](https://wordpress.org/plugins/), der indlæser ubrugt CSS på din side. Hvis du vil identificere plugins, der tilføjer irrelevant CSS, kan du prøve at køre [kodedækning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chrome DevTools. Du kan identificere det problematiske tema/plugin via webadressen for typografiarket. Kig efter plugins med mange typografiark på listen, som indeholder meget rødt i kodedækningen. Et plugin bør kun sætte et typografiark i kø, hvis det rent faktisk anvendes på siden."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Overvej at reducere eller ændre antallet af [WordPress-plugins](https://wordpress.org/plugins/), der indlæser ubrugt JavaScript på din side. Hvis du vil identificere plugins, der tilføjer irrelevant JavaScript, kan du prøve at køre [kodedækning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chrome DevTools. Du kan identificere det problematiske tema/plugin via webadressen for scriptet. Kig efter plugins med mange scripts på listen, som indeholder meget rødt i kodedækningen. Et plugin bør kun sætte et script i kø, hvis det rent faktisk anvendes på siden."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Læs om [browserens cachelagring i WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Overvej at bruge et [WordPress-plugin til billedoptimering](https://wordpress.org/plugins/search/optimize+images/), der komprimerer dine billeder uden at gå på kompromis med kvaliteten."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Upload billeder direkte via [mediesamlingen](https://codex.wordpress.org/Media_Library_Screen) for at sikre, at de påkrævede billedstørrelser er tilgængelige, og indsæt dem derefter fra mediesamlingen, eller brug billedwidgetten til at sikre, at de optimale billedstørrelser anvendes (inklusive dem til responsive skillepunkter). Undgå at bruge billeder i `Full Size`, medmindre dimensionerne er passende til brugen. [Få flere oplysninger](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Du kan aktivere tekstkomprimering ved konfigurationen af din webserver."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Overvej at bruge et [plugin](https://wordpress.org/plugins/search/convert+webp/) eller en tjeneste, der automatisk konverterer dine uploadede billeder til deres optimale formater."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/de.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/de.json
new file mode 100644
index 00000000000..580319f16a9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/de.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Anhand von Tastenkombinationen können Nutzer schnell einen Bereich der Seite in den Fokus rücken. Damit die Navigation wie vorgesehen funktioniert, muss jede Tastenkombination eindeutig sein. [Weitere Informationen.](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]`-Werte sind nicht eindeutig"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`-Werte sind eindeutig"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Jede ARIA-`role` unterstützt eine bestimmte Auswahl an `aria-*`-Attributen. Wenn sie jedoch falsch zugeordnet sind, werden die `aria-*`-Attribute ungültig. [Weitere Informationen.](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]`-Attribute stimmen nicht mit ihren Rollen überein"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]`-Attribute entsprechen ihren Rollen"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Für einige ARIA-Rollen sind Attribute erforderlich, die Screenreadern den Zustand des Elements beschreiben. [Weitere Informationen.](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`-Elemente weisen nicht alle erforderlichen `[aria-*]`-Attribute auf"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`-Elemente verfügen über alle erforderlichen `[aria-*]`-Attribute"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Einige übergeordnete ARIA-Rollen müssen bestimmte untergeordnete Rollen enthalten, damit sie die beabsichtigten Hilfsfunktionen erfüllen können. [Weitere Informationen.](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Den Elementen mit einer ARIA-`[role]`, deren untergeordnete Elemente eine bestimmte `[role]` enthalten müssen, fehlen einige oder alle dieser erforderlichen untergeordneten Elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Die Elemente mit einer ARIA-`[role]`, deren untergeordnete Elemente eine bestimmte `[role]` enthalten müssen, haben alle erforderlichen untergeordneten Elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Einige untergeordnete ARIA-Rollen müssen in bestimmten übergeordneten Rollen enthalten sein, damit sie die beabsichtigten Hilfsfunktionen erfüllen können. [Weitere Informationen.](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`-Elemente sind nicht ihren jeweils erforderlichen übergeordneten Elementen untergeordnet"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`-Elemente sind ihren jeweils erforderlichen übergeordneten Elementen untergeordnet"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Für ARIA-Rollen müssen gültige Werte angegeben sein, damit sie die beabsichtigten Hilfsfunktionen erfüllen können. [Weitere Informationen.](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]`-Werte sind ungültig"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]`-Werte sind gültig"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Hilfstechnologien wie Screenreader können ARIA-Attribute mit ungültigen Werten nicht interpretieren. [Weitere Informationen.](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]`-Attribute weisen keine gültigen Werte auf"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]`-Attribute weisen gültige Werte auf"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Hilfstechnologien wie Screenreader können ARIA-Attribute mit ungültigen Namen nicht interpretieren. [Weitere Informationen.](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]`-Attribute sind ungültig oder falsch geschrieben"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]`-Attribute sind gültig und richtig geschrieben"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Durch Untertitel sind Audioelemente auch für Gehörlose und Hörgeschädigte nutzbar, da sie wichtige Informationen zur sprechenden Person und zum Inhalt des Gesprächs sowie andere nonverbale Informationen enthalten. [Weitere Informationen.](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Den `<audio>`-Elementen fehlt ein `<track>`-Element mit `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>`-Elemente enthalten ein `<track>`-Element mit `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Fehlerhafte Elemente"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Wenn eine Schaltfläche keinen zugänglichen Namen hat, wird sie von Screenreadern als \"Schaltfläche\" angesagt, was sie für Nutzer, die auf Screenreader angewiesen sind, unbrauchbar macht. [Weitere Informationen.](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Schaltflächen haben keinen für Screenreader zugänglichen Namen"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Die Namen der Schaltflächen sind für Screenreader zugänglich"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Wenn Tastaturnutzer Inhalte umgehen können, die sich wiederholen, sorgt das für eine effizientere Navigation. [Weitere Informationen.](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Die Seite enthält keine Überschrift, keinen Link zum Überspringen und keinen Landmark-Bereich"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Die Seite enthält eine Überschrift, einen Link zum Überspringen oder einen Landmark-Bereich"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Text mit geringem Kontrast ist für viele Nutzer schlecht oder gar nicht lesbar. [Weitere Informationen.](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Das Kontrastverhältnis von Hintergrund- und Vordergrundfarben ist nicht ausreichend."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Das Kontrastverhältnis von Hintergrund- und Vordergrundfarben ist ausreichend"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Wenn Definitionslisten nicht korrekt mit Markup versehen sind, geben Screenreader unter Umständen verwirrende oder falsche Inhalte aus. [Weitere Informationen.](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`-Elemente enthalten nicht nur richtig angeordnete Gruppen aus `<dt>`- und `<dd>`-Elementen, `<script>`- oder `<template>`-Elemente."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Alle Gruppen aus `<dt>`- und `<dd>`-Elementen sowie `<script>`- oder `<template>`-Elemente, die in `<dl>`-Elementen enthalten sind, sind richtig angeordnet."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Definitionslistenelemente (`<dt>` und `<dd>`) müssen in ein übergeordnetes `<dl>`-Element eingefasst sein, damit sie von Screenreadern richtig angesagt werden können. [Weitere Informationen.](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Definitionslistenelemente sind nicht in `<dl>`-Elemente eingefasst"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Definitionslistenelemente sind in `<dl>`-Elemente eingefasst"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Anhand des Titels wissen Screenreader-Nutzer, worum es auf der Seite geht. Außerdem entscheiden Nutzer von Suchmaschinen auf der Grundlage des Titels, ob eine Seite für ihre Suche relevant ist. [Weitere Informationen.](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument hat kein `<title>`-Element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument enthält ein `<title>`-Element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Der Wert eines ID-Attributs muss eindeutig sein, damit andere Instanzen nicht von Hilfstechnologien übersehen werden. [Weitere Informationen.](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]`-Attribute auf der Seite sind nicht eindeutig"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]`-Attribute auf der Seite sind eindeutig"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Nutzer von Screenreadern sind auf Frametitel angewiesen, die die Frameinhalte beschreiben. [Weitere Informationen.](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>`- oder `<iframe>`-Elemente haben keinen Titel"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>`- oder `<iframe>`-Elemente verfügen über einen Titel"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Wenn auf einer Seite kein lang-Attribut angegeben ist, nimmt ein Screenreader an, dass es sich um die Standardsprache handelt, die der Nutzer beim Einrichten des Screenreaders ausgewählt hat. Wenn die Sprache jedoch nicht der Standardsprache entspricht, gibt der Screenreader den Inhalt der Seite möglicherweise falsch aus. [Weitere Informationen.](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-Element enthält kein `[lang]`-Attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-Element hat ein `[lang]`-Attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Durch Angabe einer gültigen [Sprache gemäß BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) kann der Text von einem Screenreader korrekt wiedergegeben werden. [Weitere Informationen.](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-Element weist keinen gültigen Wert für sein `[lang]`-Attribut auf."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Das `<html>`-Element hat einen gültigen Wert für sein `[lang]`-Attribut"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informative Elemente sollten einen kurzen, beschreibenden alternativen Text haben. Dekorative Elemente können mit einem leeren ALT-Attribut ignoriert werden. [Weitere Informationen.](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Bildelemente haben keine `[alt]`-Attribute"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Bildelemente verfügen über `[alt]`-Attribute"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Wenn ein Bild als `<input>`-Schaltfläche verwendet wird, kann die Angabe von alternativem Text Screenreader-Nutzern helfen, den Zweck der Schaltfläche besser zu verstehen. [Weitere Informationen.](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">`-Elemente verfügen nicht über `[alt]`-Text"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">`-Elemente verfügen über `[alt]`-Text"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Durch Labels wird gewährleistet, dass Steuerelemente für Formulare von Hilfstechnologien wie Screenreadern richtig angesagt werden. [Weitere Informationen.](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Die Formularelemente sind nicht mit Labels verknüpft"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Formularelemente sind mit Labels verknüpft"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Eine für Layoutzwecke verwendete Tabelle sollte keine Datenelemente wie \"th\"- bzw. \"caption\"-Elemente oder das \"summary\"-Attribut enthalten, weil dies für Nutzer von Screenreadern verwirrend sein kann. [Weitere Informationen.](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "`<table>`-Präsentationselemente verwenden `<th>`, `<caption>` oder das `[summary]`-Attribut."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "`<table>`-Präsentationselemente enthalten keine `<th>`-, `<caption>`- oder `[summary]`-Attribute."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Linktext, der leicht erkennbar, eindeutig und fokussierbar ist, verbessert die Navigation für Screenreader-Nutzer. Dies gilt auch für alternativen Text für Bilder, die als Links verwendet werden. [Weitere Informationen.](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Links haben keinen leicht erkennbaren Namen"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Links haben einen leicht erkennbaren Namen"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Screenreader sagen Listen auf bestimmte Art und Weise an. Eine korrekte Listenstruktur gewährleistet, dass der Screenreader sie richtig ausgibt. [Weitere Informationen.](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listen enthalten nicht nur `<li>`-Elemente und Elemente zur Skriptunterstützung (`<script>` sowie `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listen enthalten nur `<li>`-Elemente und Elemente zur Skriptunterstützung (`<script>` sowie `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Listenelemente (`<li>`) müssen sich in einem übergeordneten `<ul>`- oder `<ol>`-Element befinden, damit Screenreader sie richtig ansagen können. [Weitere Informationen.](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Listenelemente (`<li>`) befinden sich nicht in übergeordneten `<ul>`- oder `<ol>`-Elementen."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Listenelemente (`<li>`) befinden sich in übergeordneten `<ul>`- oder `<ol>`-Elementen"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Nutzer rechnen nicht damit, dass eine Seite automatisch aktualisiert wird. Außerdem wird dadurch der Fokus wieder auf den Seitenanfang verschoben. Das kann für den Nutzer frustrierend oder verwirrend sein. [Weitere Informationen.](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Im Dokument wird `<meta http-equiv=\"refresh\">` verwendet"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dieses Dokument verwendet `<meta http-equiv=\"refresh\">` nicht"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Wenn Sie die Zoomfunktion deaktivieren, haben Nutzer mit eingeschränktem Sehvermögen, die auf die Bildschirmvergrößerung angewiesen sind, Probleme, den Inhalt einer Webseite zu sehen. [Weitere Informationen.](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` wird im `<meta name=\"viewport\">`-Element verwendet oder das `[maximum-scale]`-Attribut ist kleiner als 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` wird nicht im `<meta name=\"viewport\">`-Element verwendet und das `[maximum-scale]`-Attribut ist nicht kleiner als 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Screenreader können lediglich Textinhalte interpretieren. Wenn Sie `<object>`-Elementen Alt-Text hinzufügen, können Screenreader-Nutzer besser verstehen, was diese Elemente darstellen. [Weitere Informationen.](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>`-Elemente verfügen nicht über `[alt]`-Text"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>`-Elemente verfügen über `[alt]`-Text"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Ein Wert größer als 0 impliziert eine explizite Navigationsanordnung. Das ist zwar technisch möglich; aber für Nutzer, die auf Hilfstechnologien angewiesen sind, ist dies häufig frustrierend. [Weitere Informationen.](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Der `[tabindex]`-Wert einiger Elemente ist größer als 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Kein Element hat einen `[tabindex]`-Wert größer als 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Screenreader bieten Funktionen, die die Navigation in Tabellen vereinfachen. Wenn Sie dafür sorgen, dass `<td>`-Zellen, die das `[headers]`-Attribut verwenden, nur auf andere Zellen in derselben Tabelle verweisen, kann dies für Screenreader-Nutzer hilfreich sein. [Weitere Informationen.](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Zellen in einem \"`<table>`\"-Element, die das Attribut \"`[headers]`\" enthalten, verweisen auf ein \"`id`\"-Element, das sich nicht in derselben Tabelle befindet."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Zellen in einem \"`<table>`\"-Element, die das Attribut \"`[headers]`\" enthalten, verweisen auf Zellen in derselben Tabelle."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Screenreader bieten Funktionen, die die Navigation in Tabellen vereinfachen. Wenn Sie dafür sorgen, dass Tabellenüberschriften immer auf eine Auswahl von Zellen verweisen, kann dies für Screenreader-Nutzer hilfreich sein. [Weitere Informationen.](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Für `<th>`-Elemente und Elemente mit `[role=\"columnheader\"/\"rowheader\"]` sind keine Datenzellen vorhanden, die sie beschreiben."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Für `<th>`-Elemente und Elemente mit `[role=\"columnheader\"/\"rowheader\"]` sind Datenzellen vorhanden, die sie beschreiben."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Durch Angabe einer gültigen [Sprache gemäß BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) in Elementen kann der Text von einem Screenreader korrekt ausgesprochen werden. [Weitere Informationen.](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]`-Attribute weisen keinen gültigen Wert auf"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]`-Attribute weisen einen gültigen Wert auf"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Wenn ein Video Untertitel enthält, können gehörlose und hörgeschädigte Nutzer die Informationen im Video besser verstehen. [Weitere Informationen.](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>`-Elemente enthalten kein `<track>`-Element mit `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>`-Elemente enthalten ein `<track>`-Element mit `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audiobeschreibungen enthalten relevante Informationen für Videos, die aus dem Dialog nicht ersichtlich sind, z. B. Gesichtsausdrücke und Schauplätze. [Weitere Informationen.](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>`-Elemente enthalten kein `<track>`-Element mit `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>`-Elemente enthalten ein `<track>`-Element mit `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Definieren Sie ein `apple-touch-icon` für eine ideale Darstellung unter iOS, wenn Nutzer die progressive Web-App dem Startbildschirm hinzufügen. Es muss auf eine nicht transparente, quadratische PNG-Datei mit 192 px (oder 180 px) verweisen. [Weitere Informationen.](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Hat kein gültiges `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` ist veraltet; `apple-touch-icon` wird bevorzugt."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Enthält ein gültiges `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome-Erweiterungen haben die Ladegeschwindigkeit dieser Seite beeinträchtigt. Versuchen Sie, die Seite im Inkognito-Modus oder mit einem Chrome-Profil ohne Erweiterungen zu überprüfen."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Skriptauswertung"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Parsen von Skripten"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "CPU-Zeit insgesamt"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Versuchen Sie, die Zeit für das Parsen, Kompilieren und Ausführen von JavaScript zu reduzieren. Die Bereitstellung kleinerer JS-Nutzlasten kann dabei helfen. [Weitere Informationen.](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Ausführungszeit von JavaScript reduzieren"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript-Ausführungszeit"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Große GIF-Dateien sind nur bedingt für die Auslieferung animierter Inhalte geeignet. Sie können stattdessen MPEG4- oder WebM-Videos für Animationen und PNG oder WebP für statische Bilder verwenden und so die Netzwerk-Datenmenge reduzieren. [Weitere Informationen](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Videoformate für animierte Inhalte verwenden"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Wenn Sie nicht sichtbare und versteckte Bilder erst laden lassen, nachdem alle wichtigen Ressourcen geladen wurden, können Sie die Zeit bis zur Interaktivität reduzieren. [Weitere Informationen.](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Nicht sichtbare Bilder aufschieben"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ressourcen blockieren den First Paint Ihrer Seite. Versuchen Sie, wichtiges JS und wichtige CSS inline anzugeben und alle nicht kritischen JS und Stile aufzuschieben. [Weitere Informationen.](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Ressourcen beseitigen, die das Rendering blockieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Große Netzwerknutzlasten kosten Nutzer bares Geld und hängen eng mit langen Ladezeiten zusammen. [Weitere Informationen.](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Die Gesamtgröße war {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Sehr große Netzwerknutzlasten vermeiden"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Vermeidet sehr große Netzwerknutzlasten"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Durch die Komprimierung von CSS-Dateien können Netzwerknutzlasten verkleinert werden. [Weitere Informationen.](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSS komprimieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Durch die Komprimierung von JavaScript-Dateien können Nutzlastgrößen und die Zeit zum Parsen von Skripts reduziert werden. [Weitere Informationen.](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScript komprimieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Sie können ungültige Regeln aus Stylesheets entfernen und das Laden von CSS aufschieben, die nicht für ohne Scrollen sichtbare Inhalte verwendet werden, um unnötigen Datenverbrauch durch Netzwerkaktivität zu vermeiden. [Weitere Informationen.](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Nicht verwendete CSS entfernen"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Entfernen Sie nicht verwendetes JavaScript, um die Datenmenge bei Netzwerkaktivitäten zu reduzieren."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Nicht genutztes JavaScript entfernen"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Eine lange Lebensdauer des Cache kann wiederholte Besuche Ihrer Seite beschleunigen. [Weitere Informationen.](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Ressource gefunden}other{# Ressourcen gefunden}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Statische Inhalte mit einer effizienten Cache-Richtlinie bereitstellen"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Verwendet eine effiziente Cache-Richtlinie für statische Inhalte"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimierte Bilder werden schneller geladen und verbrauchen weniger mobile Daten. [Weitere Informationen.](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Bilder effizient codieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Stellen Sie Bilder bereit, die eine angemessene Größe haben, um mobile Daten zu sparen und die Ladezeit zu verbessern. [Weitere Informationen.](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Bilder richtig dimensionieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Textbasierte Ressourcen sollten mit Komprimierung (gzip, Deflate oder Brotli) ausgeliefert werden, um die Datenmenge im Netzwerk insgesamt zu minimieren. [Weitere Informationen.](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Textkomprimierung aktivieren"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Bildformate wie JPEG 2000, JPEG XR und WebP bieten oft eine bessere Komprimierung als PNG oder JPEG, was schnellere Downloads und einen geringeren Datenverbrauch ermöglicht. [Weitere Informationen.](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Bilder in modernen Formaten bereitstellen"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Wenn die Breite Ihrer App-Inhalte nicht mit der des Darstellungsbereichs übereinstimmt, ist Ihre App möglicherweise nicht für Bildschirme von Mobilgeräten optimiert. [Weitere Informationen.](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Die Größe des Darstellungsbereichs von {innerWidth} Pixeln stimmt nicht mit der Fenstergröße von {outerWidth} Pixeln überein."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Inhalt hat nicht die richtige Größe für den Darstellungsbereich"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Inhalt hat die richtige Größe für den Darstellungsbereich"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "In den unten aufgeführten Ketten kritischer Anfragen können Sie sehen, welche Ressourcen mit einer hohen Priorität geladen werden. Versuchen Sie, die Ketten zu verkürzen, die Downloadgröße von Ressourcen zu reduzieren oder das Herunterladen unnötiger Ressourcen aufzuschieben, um den Seitenaufbau zu beschleunigen. [Weitere Informationen.](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Kette gefunden}other{# Ketten gefunden}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Tiefe kritischer Anforderungen minimieren"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Veraltet/Warnung"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Zeile"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Veraltete APIs werden aus dem Browser entfernt. [Weitere Informationen.](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Warnung gefunden}other{# Warnungen gefunden}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Verwendet veraltete APIs"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Vermeidet veraltete APIs"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache ist veraltet. [Weitere Informationen.](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" gefunden"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Verwendet Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Vermeidet Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Wenn Sie einen DOCTYPE festlegen, hindern Sie den Browser daran, zum Quirks-Modus zu wechseln. [Weitere Informationen.](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE-Name muss dieser String sein (in Kleinbuchstaben): `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument muss einen DOCTYPE enthalten"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "PublicId sollte ein leerer String sein"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "SystemId sollte ein leerer String sein"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Seite verfügt nicht über den HTML-DOCTYPE und startet daher den Quirks-Modus"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Seite verfügt über den HTML-DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistik"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Wert"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Laut der Empfehlung von Browserentwicklern sollten Seiten nicht mehr als ungefähr 1.500 DOM-Elemente enthalten. Die ideale Strukturtiefe liegt bei unter 32 Elementen und weniger als 60 unter- und übergeordneten Elementen. Ein großes DOM kann zu hohem Speicherverbrauch, langwierigen [Stilberechnungen](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) und kostspieligen [dynamischen Umbrüchen im Layout](https://developers.google.com/speed/articles/reflow) führen. [Weitere Informationen.](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Element}other{# Elemente}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Übermäßige DOM-Größe vermeiden"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximale DOM-Tiefe"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM-Elemente insgesamt"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximale Anzahl von untergeordneten Elementen"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Vermeidet eine übermäßige DOM-Größe"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Ziel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Fügen Sie beliebigen externen Links `rel=\"noopener\"` oder `rel=\"noreferrer\"` hinzu, um die Leistung zu verbessern und Sicherheitslücken zu vermeiden. [Weitere Informationen.](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links zu ursprungsübergreifenden Zielen sind unsicher"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links zu ursprungsübergreifenden Zielen sind sicher"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Ziel für Anker ({anchorHTML}) kann nicht bestimmt werden. Wenn dies nicht als Hyperlink genutzt wird, sollten Sie target=_blank entfernen."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Nutzer sind misstrauisch oder verwirrt, wenn Websites den Standort ohne Begründung anfordern. Versuchen Sie stattdessen, die Anforderung mit einer Nutzeraktion zu verbinden. [Weitere Informationen.](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Fordert die Berechtigung zur Standortbestimmung beim Seitenaufbau an"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Fordert während des Seitenaufbaus keine Berechtigung zur Standortbestimmung an"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Alle Front-End-JavaScript-Bibliotheken auf der Seite wurden erkannt. [Weitere Informationen.](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript-Bibliotheken erkannt"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Für Nutzer mit langsamen Verbindungen können externe Skripts, die dynamisch über `document.write()` eingefügt werden, den Seitenaufbau um einige Sekunden verzögern. [Weitere Informationen.](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Verwendet `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Verwendet kein `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Höchster Schweregrad"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bibliotheksversion"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Anzahl der Sicherheitslücken"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Einige Skripts von Drittanbietern können bekannte Sicherheitslücken enthalten, die von Angreifern leicht zu identifizieren und zu missbrauchen sind. [Weitere Informationen.](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Sicherheitslücke erkannt}other{# Sicherheitslücken erkannt}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Enthält Front-End-JavaScript-Bibliotheken mit bekannten Sicherheitslücken"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Hoch"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Niedrig"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Mittel"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Vermeidet Front-End-JavaScript-Bibliotheken mit bekannten Sicherheitslücken"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Nutzer sind misstrauisch oder verwirrt, wenn Websites die Berechtigung zum Senden von Benachrichtigungen ohne Begründung anfordern. Versuchen Sie stattdessen, die Anforderung mit Touch-Gesten zu verbinden. [Weitere Informationen.](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Fordert die Benachrichtigungsberechtigung beim Seitenaufbau an"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Fordert während des Seitenaufbaus keine Benachrichtigungsberechtigung an"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Fehlerhafte Elemente"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Das Einfügen von Passwörtern sollte entsprechend guten Sicherheitsrichtlinien zulässig sein. [Weitere Informationen.](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Hindert Nutzer daran, Inhalte in Passwortfelder einzufügen"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Erlaubt Nutzern, Inhalte in Passwortfelder einzufügen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokoll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 bietet gegenüber HTTP/1.1 viele Vorteile, wie z. B. Binärkopfzeilen, Multiplexing und Server-Push. [Weitere Informationen.](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{Ressourcen für 1 Anfrage nicht über HTTP/2 bereitgestellt}other{Ressourcen für # Anfragen nicht über HTTP/2 bereitgestellt}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Verwendet HTTP/2 nicht für alle Ressourcen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Verwendet HTTP/2 für eigene Ressourcen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Wenn Sie Ihre Ereignis-Listener für Tipp- und Mausradbewegungen als `passive` markieren, können Sie damit die Scrollleistung Ihrer Seite verbessern. [Weitere Informationen.](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Verwendet keine passiven Listener zur Verbesserung der Scrollleistung"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Verwendet passive Listener zur Verbesserung der Scrollleistung"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Beschreibung"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "In der Konsole protokollierte Fehler weisen auf ungelöste Probleme hin. Sie können durch fehlgeschlagene Netzwerkanfragen und andere Browser-Probleme verursacht werden. [Weitere Informationen](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Es wurden Browserfehler in der Konsole protokolliert"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Es wurden keine Browserfehler in der Konsole protokolliert"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Verwenden Sie die CSS-Funktion font-display, damit der Text für Nutzer sichtbar ist, während Webfonts geladen werden. [Weitere Informationen.](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Darauf achten, dass der Text während der Webfont-Ladevorgänge sichtbar bleibt"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Der gesamte Text bleibt während der Webfont-Ladevorgänge sichtbar"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Für die folgende URL konnte Lighthouse den Schriftart-Anzeigewert nicht automatisch prüfen: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Seitenverhältnis (Original)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Seitenverhältnis (angezeigt)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Die Bildgröße sollte dem natürlichen Seitenverhältnis entsprechen. [Weitere Informationen.](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Zeigt Bilder mit einem falschen Seitenverhältnis an"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Zeigt Bilder mit einem korrekten Seitenverhältnis an"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Ungültige Informationen zur Bildgröße: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browser können Nutzer direkt dazu auffordern, Ihre Web-App zum Startbildschirm hinzuzufügen. Das kann zu mehr Engagement führen. [Weitere Informationen.](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Das Manifest der Web-App erfüllt die Anforderungen an die Installierbarkeit nicht"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Das Manifest der Web-App erfüllt die Anforderungen an die Installierbarkeit"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Unsichere URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Alle Websites sollten durch HTTPS geschützt werden – selbst wenn sie keine vertraulichen Daten enthalten. HTTPS verhindert, dass andere Personen die Website manipulieren oder die Kommunikation zwischen Ihrer App und Ihren Nutzern mitverfolgen können. Dieses Protokoll ist eine Voraussetzung für HTTP/2 sowie für viele neue Webplattform-APIs. [Weitere Informationen.](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 unsichere Anfrage gefunden}other{# unsichere Anfragen gefunden}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Verwendet nicht HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Verwendet HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Ein schneller Seitenaufbau über ein Mobilfunknetz sorgt dafür, dass die Seite für Nutzer auf Mobilgeräten angenehm zu bedienen ist. [Weitere Informationen.](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktiv nach {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Im simulierten Mobilfunknetz interaktiv nach {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Ihre Seite lädt zu langsam und es dauert länger als 10 Sekunden, bis sie interaktiv ist. Im Abschnitt \"Leistung\" finden Sie Empfehlungen und Diagnosedaten, die Ihnen helfen können, Ihre Seite zu optimieren."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Seitenaufbau in Mobilfunknetzen ist nicht schnell genug"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Seitenaufbau in Mobilfunknetzen ist schnell genug"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Versuchen Sie, die Zeit für das Parsen, Kompilieren und Ausführen von JavaScript zu reduzieren. Die Bereitstellung kleinerer JS-Nutzlasten kann dabei helfen. [Weitere Informationen](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Aufwand für Hauptthread minimieren"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimiert den Aufwand für den Hauptthread"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Damit Sie möglichst viele Nutzer erreichen können, sollte Ihre Website mit allen gängigen Browsern kompatibel sein. [Weitere Informationen.](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Website funktioniert auf verschiedenen Browsern"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Für die einzelnen Seiten sollten Deeplinks erstellt werden können. Achten Sie darauf, dass die entsprechenden URLs eindeutig sind, sodass sich die Seiten in sozialen Netzwerken leichter teilen lassen. [Weitere Informationen.](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Jede Seite hat eine URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Übergänge sollten sich auch bei einer langsamen Netzwerkverbindung schnell anfühlen. Dies trägt beim Nutzer erheblich zur wahrgenommenen Leistung bei. [Weitere Informationen.](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Seitenübergänge vermitteln nicht das Gefühl von übermäßigen Ladezeiten"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Die geschätzte Eingabelatenz ist eine Schätzung dessen, wie viele Millisekunden Ihre App benötigt, um während des 5-s-Fensters mit der stärksten Auslastung beim Seitenaufbau auf Nutzereingaben zu reagieren. Wenn die Latenz bei Ihnen über 50 ms beträgt, empfinden Nutzer Ihre App möglicherweise als langsam. [Weitere Informationen.](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Geschätzte Eingabelatenz"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First Contentful Paint gibt an, wann der erste Text oder das erste Bild gezeichnet wird. [Weitere Informationen.](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Erste Inhalte gezeichnet"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Der Messwert \"Erster CPU-Leerlauf\" gibt an, wann die Aktivität des Hauptthreads der Seite das erste Mal gering genug ist, um Eingaben zu verarbeiten. [Weitere Informationen.](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Erster CPU-Leerlauf"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "\"Inhalte weitgehend gezeichnet\" gibt an, wann die Hauptinhalte einer Seite sichtbar sind. [Weitere Informationen.](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Inhalte weitgehend gezeichnet"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Die Zeit bis Interaktivität entspricht der Zeit, die vergeht, bis die Seite vollständig interaktiv ist. [Weitere Informationen.](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Zeit bis Interaktivität"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Der maximale potenzielle First Input Delay, der bei Ihren Nutzern auftreten kann, entspricht der Dauer der längsten Aufgabe in Millisekunden. [Weitere Informationen.](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maximaler potenzieller First Input Delay"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Der Geschwindigkeitsindex gibt an, wie schnell die Inhalte einer Seite sichtbar dargestellt werden. [Weitere Informationen.](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Geschwindigkeitsindex"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Summe aller Zeiträume (in Millisekunden) zwischen FCP und Zeit bis Interaktivität, wenn die Aufgabendauer 50 ms überschreitet."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Gesamtdauer der Blockierung"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Die Netzwerk-Umlaufzeit (RTT, Round Trip Time) hat großen Einfluss auf die Leistung. Wenn die RTT zu einem Ursprung hoch ausfällt, weist dies darauf hin, dass die Leistung mit Servern verbessert werden kann, die sich näher beim Nutzer befinden. [Weitere Informationen.](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Netzwerk-Umlaufzeit"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Serverlatenzen können die Leistung im Web beeinträchtigen. Wenn die Serverlatenz eines Ursprungs hoch ist, weist dies darauf hin, dass der Server überlastet ist oder eine schlechte Back-End-Leistung bietet. [Weitere Informationen.](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Server-Back-End-Latenzen"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Mithilfe eines Service Workers kann Ihre Web-App auch bei schlechten Netzwerkbedingungen zuverlässig funktionieren. [Weitere Informationen.](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` reagiert im Offlinemodus nicht mit dem HTTP-Statuscode 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` reagiert im Offlinemodus mit dem HTTP-Status 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse konnte die `start_url` nicht im Manifest abrufen. Daher wurde angenommen, dass es sich bei der `start_url` um die URL des Dokuments handelt. Fehlermeldung: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Über dem Budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Die Anzahl und Größe der Netzwerkanfragen sollten unter den Zielvorgaben des Leistungsbudgets liegen. [Weitere Informationen.](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 Anfrage}other{# Anfragen}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Leistungsbudget"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Wenn Sie HTTPS bereits eingerichtet haben, sollten Sie den gesamten HTTP-Traffic auf HTTPS weiterleiten, damit für alle Ihre Nutzer sichere Webfunktionen aktiviert sind. [Weitere Informationen.](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP-Traffic wird nicht auf HTTPS weitergeleitet"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP-Traffic wird auf HTTPS weitergeleitet"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Weiterleitungen führen zu zusätzlichen Verzögerungen, bevor die Seite geladen werden kann. [Weitere Informationen.](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Mehrere Weiterleitungen auf die Seite vermeiden"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Fügen Sie zum Einrichten von Budgets für die Anzahl und Größe von Seitenressourcen eine budget.json-Datei hinzu. [Weitere Informationen.](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 Anfrage • {byteCount, number, bytes} KB}other{# Anfragen • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Halten Sie die Anfrageanzahl niedrig und die Übertragungsgröße gering"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Über kanonische Links wird angegeben, welche URL in den Suchergebnissen angezeigt werden soll. [Weitere Informationen.](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Mehrere in Konflikt stehende URLs ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Verweist auf eine andere Domain ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Ungültige URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Verweist auf einen anderen `hreflang`-Speicherort ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relative URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Verweist auf die Stamm-URL (die Startseite) der Domain statt auf eine identische Inhaltsseite"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument enthält kein gültiges `rel=canonical`-Element"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument enthält ein gültiges `rel=canonical`-Element"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Schriftgrößen von weniger als 12 px sind zu klein und deshalb nicht gut lesbar, sodass Nutzer von Mobilgeräten den Text per Fingerbewegung heranzoomen müssen. Mindestens 60 % des Texts auf der Seite sollten deshalb eine Schriftgröße von mindestens 12 px haben. [Weitere Informationen.](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} gut lesbarer Text"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text ist nicht lesbar, weil kein Meta-Tag für den Darstellungsbereich vorhanden ist, das für Bildschirme von Mobilgeräten optimiert ist."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} des Texts ist zu klein (auf Grundlage einer Stichprobengröße von {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokument enthält keine gut lesbaren Schriftgrößen"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokument enthält gut lesbare Schriftgrößen"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Anhand von \"hreflang\"-Links können Suchmaschinen ermitteln, welche Version einer Seite sie in den Suchergebnissen für eine bestimmte Sprache oder Region anzeigen sollen. [Weitere Informationen.](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument enthält kein gültiges `hreflang`-Element"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument enthält ein gültiges `hreflang`-Element"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Seiten mit ungültigen HTTP-Statuscodes werden möglicherweise nicht richtig indexiert. [Weitere Informationen.](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Seite hat keinen gültigen HTTP-Statuscode"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Seite hat einen gültigen HTTP-Statuscode"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Suchmaschinen können Ihre Seiten nicht in die Suchergebnisse aufnehmen, wenn sie nicht dazu berechtigt sind, sie zu crawlen. [Weitere Informationen.](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Seite ist von Indexierung ausgeschlossen"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Seite ist nicht von Indexierung ausgeschlossen"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Mit beschreibendem Linktext können Suchmaschinen Ihre Inhalte besser verstehen. [Weitere Informationen.](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Link gefunden}other{# Links gefunden}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Links enthalten keinen beschreibenden Text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Links haben beschreibenden Text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Sie können das [Testtool für strukturierte Daten](https://search.google.com/structured-data/testing-tool/) und den [Lint für strukturierte Daten](http://linter.structured-data.org/) ausführen, um strukturierte Daten zu validieren. [Weitere Informationen.](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturierte Daten sind gültig"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Meta-Beschreibungen können in die Suchergebnisse aufgenommen werden, um die Seiteninhalte kurz zusammenzufassen. [Weitere Informationen.](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Beschreibungstext ist leer."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument enthält keine Meta-Beschreibung"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument enthält eine Meta-Beschreibung"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Suchmaschinen können keine Plug-in-Inhalte indexieren, und auf vielen Geräten werden Plug-ins eingeschränkt oder nicht unterstützt. [Weitere Informationen.](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument verwendet Plug-ins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument verwendet keine Plug-ins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Wenn Ihre robots.txt-Datei fehlerhaft ist, können Crawler möglicherweise nicht nachvollziehen, wie Ihre Website gecrawlt oder indexiert werden soll. [Weitere Informationen.](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt-Anfrage hat diesen HTTP-Status zurückgegeben: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 Fehler gefunden}other{# Fehler gefunden}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse konnte keine robots.txt-Datei herunterladen"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt ist ungültig"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt ist gültig"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktive Elemente wie Schaltflächen und Links sollten groß genug sein (48 x 48 px) und genügend Platz um sich herum haben, um einfach angetippt werden zu können. Dabei sollten sie sich aber nicht mit anderen Elementen überschneiden. [Weitere Informationen.](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} der Tippziele haben eine passende Größe"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Die Tippziele sind zu klein, weil kein Meta-Tag für den Darstellungsbereich vorhanden ist, das für Bildschirme von Mobilgeräten optimiert ist"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Größe von Tippzielen ist nicht richtig eingestellt"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Sich überschneidendes Ziel"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Tippziel"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Größe von Tippzielen ist richtig eingestellt"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Der Service Worker ermöglicht es Ihrer App, viele der Funktionen von progressiven Web-Apps zu nutzen, beispielsweise den Offlinemodus, das Hinzufügen zum Startbildschirm und Push-Benachrichtigungen. [Weitere Informationen.](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Diese Seite wird von einem Service Worker kontrolliert. Es wurde jedoch keine `start_url` gefunden, weil das Manifest nicht als gültige JSON-Datei geparst werden konnte."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Diese Seite wird zwar von einem Service Worker kontrolliert, die `start_url` ({startUrl}) liegt jedoch nicht in dessen Zuständigkeitsbereich ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Diese Seite wird zwar von einem Service Worker kontrolliert, es wurde jedoch keine `start_url` gefunden, da kein Manifest abgerufen wurde."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Dieser Ursprung verfügt über mindestens einen Service Worker. Die Seite ({pageUrl}) liegt jedoch nicht in dessen Zuständigkeitsbereich."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Es wurde kein Service Worker erkannt, der die Seite und `start_url` kontrolliert"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Es wurde ein Service Worker erkannt, der die Seite und `start_url` kontrolliert."
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Wenn Sie Ihren Startbildschirm gemäß dem Design Ihrer App gestalten, vermitteln Sie den Nutzern schon beim Ladevorgang einen hochwertigen Eindruck. [Weitere Informationen.](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nicht für einen benutzerdefinierten Startbildschirm konfiguriert"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfiguriert für einen benutzerdefinierten Startbildschirm"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Die Adressleiste des Browsers kann an das Design Ihrer Website angepasst werden. [Weitere Informationen.](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Legt keine Designfarbe für die Adressleiste fest."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Legt eine Designfarbe für die Adressleiste fest."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Dauer der Blockierung des Hauptthreads"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Drittanbieter"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Code von Drittanbietern kann die Ladegeschwindigkeit erheblich beeinträchtigen. Beschränken Sie die Zahl redundanter Drittanbieter und versuchen Sie, solchen Code erst nachträglich zu laden. [Weitere Informationen.](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Code von Drittanbietern hat den Hauptthread {timeInMs, number, milliseconds} ms lang blockiert"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Die Auswirkungen von Drittanbieter-Code minimieren"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Nutzung von Drittanbieter-Code"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "TTFB (Time To First Byte) erkennt den Zeitpunkt, zu dem Ihr Server eine Antwort sendet. [Weitere Informationen.](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Stammdokument brauchte {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Serverantwortzeiten reduzieren (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Serverantwortzeiten sind niedrig (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Dauer"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Beginn"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Typ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Sie können die User Timing API in Ihre App integrieren. Damit lässt sich die Leistung Ihrer App während wichtiger Nutzerinteraktionen in der Praxis messen. [Weitere Informationen.](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 Nutzertiming}other{# Nutzertimings}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Markierungen und Messungen für das Nutzertiming"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Für {securityOrigin} wurde ein <link> zur Vorverbindung gefunden, der jedoch vom Browser nicht verwendet wurde. Überprüfen Sie, ob das `crossorigin`-Attribut richtig verwendet wird."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Wenn Sie Hinweise auf Ressourcen als `preconnect` oder `dns-prefetch` hinzufügen, können Sie möglichst frühzeitig eine Verbindung zu wichtigen Drittanbieterursprüngen herstellen. [Weitere Informationen.](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Vorverbindung zu erforderlichen Ursprüngen aufbauen"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Ein <link>-Element zum Vorabladen wurde für {preloadURL} gefunden, aber nicht vom Browser verwendet. Überprüfen Sie, ob das `crossorigin`-Attribut richtig verwendet wird."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Mit `<link rel=preload>` können Sie das Abrufen von Ressourcen priorisieren, die derzeit beim Seitenaufbau erst später angefordert werden. [Weitere Informationen.](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Wichtige Anforderungen vorab laden"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Fügen Sie ein `<meta name=\"viewport\">`-Tag hinzu, um Ihre App für Bildschirme von Mobilgeräten zu optimieren. [Weitere Informationen.](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Kein `<meta name=\"viewport\">`-Tag gefunden"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Hat kein `<meta name=\"viewport\">`-Tag mit `width` oder `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Hat ein `<meta name=\"viewport\">`-Tag mit `width` oder `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Wenn JavaScript deaktiviert ist, sollte Ihre App dennoch einige Inhalte darstellen – auch wenn es sich dabei nur um eine Warnung handelt, dass die App JavaScript benötigt. [Weitere Informationen](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Die Body der Seite sollte einige Inhalte rendern, wenn ihre Skripts nicht verfügbar sind."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Liefert keinen Fallback-Content, wenn JavaScript nicht verfügbar ist"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Enthält einige Inhalte, wenn JavaScript nicht verfügbar ist"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Wenn Sie eine progressive Web-App entwickeln, sollten Sie einen Service Worker verwenden, damit Ihre App auch offline funktioniert. [Weitere Informationen.](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Aktuelle Seite reagiert im Offlinemodus nicht mit dem HTTP-Statuscode 200"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Aktuelle Seite reagiert im Offlinemodus mit dem HTTP-Statuscode 200"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Die Seite lädt im Offlinemodus möglicherweise nicht, weil Ihre Test-URL ({requested}) auf \"{final}\" weitergeleitet wurde. Versuchen Sie, die zweite URL direkt zu testen."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Anhand dieser Möglichkeiten können Sie die Nutzung von ARIA in Ihrer Anwendung verbessern, wovon Nutzer von Hilfstechnologien wie Screenreadern unter Umständen profitieren."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Hier finden Sie Möglichkeiten, um Alternativen für Audio- und Videoinhalte anzubieten. Dies kann die Nutzung für Personen mit eingeschränktem Hör- und Sehvermögen verbessern."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio und Video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Hier finden Sie häufig genutzte Best Practices für Barrierefreiheit."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Mit diesen Prüfungen erfahren Sie, [wie Sie die Barrierefreiheit Ihrer Web-App verbessern](https://developers.google.com/web/fundamentals/accessibility). Nur bestimmte Probleme mit der Barrierefreiheit können durch automatisierte Tests erkannt werden. Deshalb ist es empfehlenswert, zusätzlich manuelle Tests durchzuführen."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Diese Prüfungen sind für Bereiche vorgesehen, für die automatische Testtools nicht geeignet sind. Weitere Informationen finden Sie in unserem Leitfaden zur [Durchführung einer Prüfung auf Barrierefreiheit](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Barrierefreiheit"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Anhand dieser Möglichkeiten können Sie die Lesbarkeit Ihrer Inhalte verbessern."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Damit können Sie dafür sorgen, dass Ihre Inhalte in verschiedenen Sprachen besser verstanden werden."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisierung und Lokalisierung"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Anhand dieser Möglichkeiten können Sie die Semantik der Steuerelemente Ihrer Anwendung verbessern. Dies kommt Nutzern von Hilfstechnologien wie Screenreadern zugute."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Namen und Labels"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Hier finden Sie Möglichkeiten, die Tastaturnavigation in Ihrer App zu verbessern."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Hier finden Sie Möglichkeiten, um das Lesen von Daten in Tabellen oder Listen mit Hilfstechnologie wie Screenreadern zu verbessern."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabellen und Listen"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Mithilfe von Leistungsbudgets werden Standards für die Leistung Ihrer Website definiert."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgets"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Weitere Informationen zur Leistung Ihrer App finden Sie hier. Diese Angaben haben keinen [direkten Einfluss](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) auf die Leistungsbewertung."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnose"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Der wichtigste Faktor bei der Leistung ist, wie schnell Pixel auf dem Bildschirm gerendert werden. Wichtige Messwerte: \"Erste Inhalte gezeichnet\", \"Inhalte weitgehend gezeichnet\""
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Verbesserungen beim Zeichnen der ersten Inhalte"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Mithilfe diese Empfehlungen lässt sich die Ladezeit Ihrer Seite möglicherweise verkürzen. Sie haben keinen [direkten Einfluss](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) auf die Leistungsbewertung."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Empfehlungen"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Messwerte"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Hier können Sie die Ladezeiten verkürzen, damit die Seite so schnell wie möglich reagiert und Einsatzbereit ist. Wichtige Messwerte: \"Zeit bis Interaktivität\", \"Geschwindigkeitsindex\""
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Allgemeine Verbesserungen"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Leistung"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Diese Prüfungen dienen dazu, die einzelnen Aspekte einer progressiven Web-App zu überprüfen. [Weitere Informationen](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Diese Prüfungen sind laut der grundlegenden [PWA-Checkliste](https://developers.google.com/web/progressive-web-apps/checklist) erforderlich, werden von Lighthouse jedoch nicht automatisch durchgeführt. Sie haben zwar keine Auswirkung auf Ihre Leistungsbewertung, aber es ist wichtig, sie manuell durchzuführen."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web-App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Schnell und zuverlässig"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Installierbar"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA-optimiert"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Mit diesen Prüfungen ist gewährleistet, dass Ihre Seite für das Ergebnis-Ranking von Suchmaschinen optimiert ist. Darüber hinaus gibt es aber auch noch andere Faktoren, die sich auf das Such-Ranking Ihrer Seite auswirken können und die Lighthouse nicht berücksichtigt. [Weitere Informationen.](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Sie können diese zusätzlichen Validierungen für Ihre Website ausführen, um weitere Best Practices für die SEO zu prüfen."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatieren Sie Ihren HTML-Code so, dass Crawler den Inhalt Ihrer App besser verstehen."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Best Practices für Inhalte"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Damit Ihre Website in den Suchergebnissen angezeigt werden kann, benötigen Crawler Zugriff auf Ihre App."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawling und Indexierung"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Achten Sie darauf, dass Ihre Seiten für Mobilgeräte optimiert sind, damit Nutzer problemlos Inhalte lesen können, ohne mit den Fingern heranzoomen zu müssen. [Weitere Informationen.](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Für Mobilgeräte optimiert"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache-TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Position"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Name"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Anfragen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Ressourcentyp"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Größe"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Zeitaufwand"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Übertragungsgröße"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Mögliche Einsparungen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Mögliche Einsparungen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Mögliche Einsparung von {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Mögliche Einsparung von {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Schriftart"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Bild"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Medien"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Sonstige"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Drittanbieter"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Gesamt"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Beim Aufzeichnen des Trace über Ihren Seitenaufbau ist ein Problem aufgetreten. Bitte führen Sie Lighthouse noch einmal aus. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Zeitüberschreitung beim Warten auf die ursprüngliche Verbindung zum Debugger-Protokoll."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Beim Seitenaufbau wurden von Chrome keine Screenshots erfasst. Achten Sie darauf, dass auf der Seite Inhalte sichtbar sind, und versuchen Sie dann, Lighthouse noch einmal auszuführen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Die angegebene Domain konnte von den DNS-Servern nicht aufgelöst werden."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Beim erforderlichen {artifactName}-Gatherer ist ein Fehler aufgetreten: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Ein interner Chrome-Fehler ist aufgetreten. Starten Sie Chrome neu und versuchen Sie anschließend, Lighthouse noch einmal auszuführen."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Erforderlicher {artifactName}-Gatherer wurde nicht ausgeführt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Die von Ihnen angeforderte Seite konnte von Lighthouse nicht zuverlässig geladen werden. Überprüfen Sie, ob Sie die richtige URL testen und der Server auf alle Anfragen angemessen reagiert."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Die angeforderte URL konnte von Lighthouse nicht zuverlässig geladen werden, weil die Seite nicht mehr reagiert hat."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Die von Ihnen angegebene URL hat kein gültiges Sicherheitszertifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome hat den Seitenaufbau mit einem Interstitial verhindert. Überprüfen Sie, ob Sie die richtige URL testen und der Server auf alle Anfragen angemessen reagiert."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Die von Ihnen angeforderte Seite konnte von Lighthouse nicht zuverlässig geladen werden. Überprüfen Sie, ob Sie die richtige URL testen und der Server auf alle Anfragen angemessen reagiert. (Details: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Die von Ihnen angeforderte Seite konnte von Lighthouse nicht zuverlässig geladen werden. Überprüfen Sie, ob Sie die richtige URL testen und der Server auf alle Anfragen angemessen reagiert. (Statuscode: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Das Laden Ihrer Seite hat zu lange gedauert. Nutzen Sie die Tipps im Bericht, um die Seitenladezeit zu verringern, und versuchen Sie anschließend noch einmal, Lighthouse auszuführen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Die maximal zulässige Antwortzeit des DevTools-Protokolls wurde überschritten. (Methode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Die maximal zulässige Zeit für das Abrufen von Ressourceninhalten wurde überschritten"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Die von Ihnen angegebene URL scheint ungültig zu sein."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Überprüfungen ansehen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Anfangsnavigation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximale Latenz für kritischen Pfad:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Fehler."
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Fehler gemeldet: keine Informationen zur Überprüfung"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Labdaten"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/)-Analyse der aktuellen Seite in einem emulierten Mobilfunknetz. Die Werte sind Schätzungen und können variieren."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Zusätzliche Elemente zur manuellen Überprüfung"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nicht zutreffend"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Empfehlung"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Geschätzte Einsparung"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Bestandene Prüfungen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Snippet minimieren"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Snippet maximieren"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Drittanbieter-Ressourcen anzeigen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Einige Probleme haben diese Ausführung von Lighthouse beeinträchtigt:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Die Werte sind Schätzungen und können variieren. Die Leistungsbewertung [basiert nur auf diesen Messwerten](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Bestandene Prüfungen mit Warnungen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Warnungen: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Sie haben die Möglichkeit, Ihr GIF bei einem Dienst hochzuladen, der dafür sorgt, dass es als HTML5-Video eingebettet werden kann."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Sie können ein [Lazy-Loading-Plug-in für WordPress](https://wordpress.org/plugins/search/lazy+load/) installieren, mit dem Sie nicht sichtbare Bilder aufschieben. Alternativ können Sie auch zu einem Design wechseln, das diese Funktion bietet. Sie sollten sich auch überlegen, [das AMP-Plug-in](https://wordpress.org/plugins/amp/) zu verwenden."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Es gibt eine Reihe von WordPress-Plug-ins, mit denen Sie [wichtige Assets einbetten](https://wordpress.org/plugins/search/critical+css/) oder [weniger wichtige Ressourcen aufschieben](https://wordpress.org/plugins/search/defer+css+javascript/) können. Beachten Sie, dass über diese Plug-ins bereitgestellte Optimierungen dazu führen können, dass Ihre Designs oder Plug-ins nicht funktionieren. Daher müssen Sie wahrscheinlich Änderungen am Code vornehmen."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Sowohl Designs, Plug-ins als auch Serverspezifikationen tragen zur Serverantwortzeit bei. Versuchen Sie, ein noch weiter optimiertes Design zu finden, wählen Sie ein geeignetes Optimierungs-Plug-in aus und/oder upgraden Sie Ihren Server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Sie haben die Möglichkeit, Auszüge in Ihrer Beitragsliste einzublenden (z. B. über das Tag \"Mehr\"), die Anzahl der Beiträge auf einer Seite zu verringern, lange Beiträge auf mehrere Seiten aufzuteilen oder ein Plug-in für das Lazy Loading von Kommentaren zu verwenden."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Ihre Website lässt sich mit einer Reihe von [WordPress-Plug-ins](https://wordpress.org/plugins/search/minify+css/) beschleunigen, durch die Ihre Stile verkettet und komprimiert werden. Sofern möglich, können Sie diese Komprimierung auch im Voraus über einen Build-Prozess vornehmen."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Ihre Website lässt sich mit einer Reihe von [WordPress-Plug-ins](https://wordpress.org/plugins/search/minify+javascript/) beschleunigen, durch die Ihre Skripts verkettet und komprimiert werden. Sofern möglich, können Sie diese Komprimierung auch im Voraus über einen Build-Prozess vornehmen."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Prüfen Sie, ob Sie [WordPress-Plug-ins](https://wordpress.org/plugins/), über die nicht verwendete CSS auf Ihre Seite geladen werden, entfernen oder durch alternative Plug-ins ersetzen können. Wenn Sie die Plug-ins ermitteln möchten, über die irrelevante CSS hinzugefügt werden, können Sie das Prüftool zur [Codeabdeckung](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in den Chrome-Entwicklertools verwenden. Das entsprechende Design/Plug-in können Sie anhand der URL des Stylesheets erkennen. Suchen Sie in der Liste nach Plug-ins mit vielen Stylesheets, bei denen im Prüftool zur Codeabdeckung viel nicht verwendeter Code (markiert in Rot) angezeigt wird. Ein Stylesheet sollte nur dann in ein Plug-in aufgenommen werden, wenn es auch tatsächlich auf der Seite verwendet wird."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Prüfen Sie, ob Sie [WordPress-Plug-ins](https://wordpress.org/plugins/), über die nicht verwendete JavaScript-Dateien auf Ihre Seite geladen werden, entfernen oder durch alternative Plug-ins ersetzen können. Wenn Sie die Plug-ins ermitteln möchten, über die irrelevante JavaScript-Dateien hinzugefügt werden, können Sie das Prüftool zur [Codeabdeckung](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in den Chrome-Entwicklertools verwenden. Das entsprechende Design/Plug-in können Sie anhand der URL des Skripts erkennen. Suchen Sie in der Liste nach Plug-ins mit vielen Skripts, bei denen im Prüftool zur Codeabdeckung viel nicht verwendeter Code (markiert in Rot) angezeigt wird. Ein Skript sollte nur dann in ein Plug-in aufgenommen werden, wenn es auch tatsächlich auf der Seite verwendet wird."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Hier erhalten Sie Informationen zum [Browser-Caching in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Sie haben die Möglichkeit, ein [WordPress-Plug-in für die Bildoptimierung](https://wordpress.org/plugins/search/optimize+images/) zu verwenden, durch das Ihre Bilder komprimiert werden, die Qualität jedoch gleich bleibt."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Sie haben die Möglichkeit, Bilder direkt über die [Medienbibliothek](https://codex.wordpress.org/Media_Library_Screen) hochzuladen, damit die erforderlichen Bildgrößen verfügbar sind. Die Bilder können Sie dann aus der Medienbibliothek einfügen oder auch das Bild-Widget nutzen, damit die optimalen Bildgrößen verwendet werden (einschließlich derjenigen für die responsiven Haltepunkte). Bilder in `Full Size` sollten nur verwendet werden, wenn die Abmessungen für die entsprechende Nutzung geeignet sind. [Weitere Informationen.](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Sie können die Textkomprimierung in der Konfiguration Ihres Webservers aktivieren."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Sie haben die Möglichkeit, Ihre hochgeladenen Bilder mithilfe eines [Plug-ins](https://wordpress.org/plugins/search/convert+webp/) oder eines Dienstes automatisch in das optimale Format zu konvertieren."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/el.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/el.json
new file mode 100644
index 00000000000..cd392d2077b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/el.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Τα πλήκτρα πρόσβασης επιτρέπουν στους χρήστες να εστιάσουν γρήγορα σε ένα τμήμα της σελίδας. Για σωστή πλοήγηση, κάθε πλήκτρο πρόσβασης πρέπει να είναι μοναδικό. [Μάθετε περισσότερα](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Οι τιμές `[accesskey]` δεν είναι μοναδικές"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` τιμές είναι μοναδικές"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Κάθε στοιχείο ARIA `role` υποστηρίζει ένα συγκεκριμένο υποσύνολο χαρακτηριστικών `aria-*`. Η λανθασμένη αντιστοίχισή τους καθιστά μη έγκυρα τα χαρακτηριστικά `aria-*`. [Μάθετε περισσότερα](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` δεν αντιστοιχούν στους ρόλους τους"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` αντιστοιχούν στους ρόλους τους"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Ορισμένοι ρόλοι ARIA έχουν απαιτούμενα χαρακτηριστικά που περιγράφουν την κατάσταση του στοιχείου στους αναγνώστες οθόνης. [Μάθετε περισσότερα](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Τα στοιχεία `[role]` δεν έχουν όλα τα απαιτούμενα χαρακτηριστικά `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Τα στοιχεία `[role]` έχουν όλα τα απαιτούμενα χαρακτηριστικά `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Ορισμένοι γονικοί ρόλοι ARIA πρέπει να περιέχουν συγκεκριμένους θυγατρικούς ρόλους, για να μπορούν να εκτελέσουν τις προβλεπόμενες λειτουργίες προσβασιμότητας. [Μάθετε περισσότερα](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Λείπουν από τα στοιχεία με ARIA `[role]`, τα οποία απαιτούν από τα θυγατρικά στοιχεία να περιέχουν ένα συγκεκριμένο `[role]`, ορισμένα ή όλα τα απαιτούμενα θυγατρικά στοιχεία."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Τα στοιχεία με ARIA `[role]`, τα οποία απαιτούν από τα θυγατρικά στοιχεία να περιέχουν ένα συγκεκριμένο `[role]`, έχουν όλα τα απαιτούμενα θυγατρικά στοιχεία."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Ορισμένοι θυγατρικοί ρόλοι ARIA πρέπει να περιέχονται σε συγκεκριμένους γονικούς ρόλους, για να μπορούν να εκτελέσουν σωστά τις προβλεπόμενες λειτουργίες προσβασιμότητας. [Μάθετε περισσότερα](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Τα στοιχεία `[role]` δεν περιλαμβάνονται στο απαιτούμενο γονικό στοιχείο τους"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Τα στοιχεία `[role]` περιλαμβάνονται στο απαιτούμενο γονικό στοιχείο τους"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Οι ρόλοι ARIA πρέπει να έχουν έγκυρες τιμές, για να μπορούν να εκτελέσουν τις προβλεπόμενες λειτουργίες προσβασιμότητας. [Μάθετε περισσότερα](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Οι τιμές `[role]` δεν είναι έγκυρες"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Οι τιμές `[role]` είναι έγκυρες"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Οι τεχνολογίες υποβοήθησης χρηστών, όπως οι αναγνώστες οθόνης, δεν μπορούν να ερμηνεύσουν τα χαρακτηριστικά ARIA με μη έγκυρες τιμές. [Μάθετε περισσότερα](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` δεν έχουν έγκυρες τιμές"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` έχουν έγκυρες τιμές"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Οι τεχνολογίες υποβοήθησης χρηστών, όπως οι αναγνώστες οθόνης, δεν μπορούν να ερμηνεύσουν τα χαρακτηριστικά ARIA με μη έγκυρα ονόματα. [Μάθετε περισσότερα](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` δεν είναι έγκυρα ή έχουν ορθογραφικά λάθη"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Τα χαρακτηριστικά `[aria-*]` είναι έγκυρα και δεν έχουν ορθογραφικά λάθη"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Οι υπότιτλοι καθιστούν τα στοιχεία ήχου προσβάσιμα από τους χρήστες που είναι κωφοί ή έχουν προβλήματα ακοής, καθώς παρέχουν σημαντικές πληροφορίες όπως το ποιος μιλάει, το τι λέει και άλλες μη λεκτικές πληροφορίες. [Μάθετε περισσότερα](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Λείπει ένα στοιχείο `<track>` με `[kind=\"captions\"]` από τα στοιχεία `<audio>`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Τα στοιχεία `<audio>` περιέχουν ένα στοιχείο `<track>` με `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Στοιχεία που απέτυχαν"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Όταν ένα κουμπί δεν έχει προσβάσιμο όνομα, οι αναγνώστες οθόνης το εκφωνούν ως \"κουμπί\", με αποτέλεσμα να μην μπορεί να χρησιμοποιηθεί από τους χρήστες που βασίζονται στους αναγνώστες οθόνης. [Μάθετε περισσότερα](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Τα κουμπιά δεν έχουν προσβάσιμο όνομα"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Τα κουμπιά έχουν προσβάσιμο όνομα"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Η προσθήκη τρόπων για την παράκαμψη του επαναλαμβανόμενου περιεχομένου επιτρέπει στους χρήστες του πληκτρολογίου να πλοηγούνται πιο αποτελεσματικά στη σελίδα. [Μάθετε περισσότερα](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Η σελίδα δεν περιέχει κεφαλίδα, σύνδεσμο παράβλεψης ή περιοχή ορόσημου"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Η σελίδα περιέχει κεφαλίδα, σύνδεσμο παράβλεψης ή περιοχή ορόσημου"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Ένα κείμενο χαμηλής αντίθεσης είναι δύσκολο ή αδύνατο να αναγνωστεί. [Μάθετε περισσότερα](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Τα χρώματα παρασκηνίου και προσκηνίου δεν έχουν επαρκή αναλογία αντίθεσης."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Τα χρώματα παρασκηνίου και προσκηνίου έχουν επαρκή αναλογία αντίθεσης"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Όταν οι λίστες ορισμών δεν επισημαίνονται σωστά, οι αναγνώστες οθόνης μπορεί να παράγουν συγκεχυμένα ή ανακριβή αποτελέσματα. [Μάθετε περισσότερα](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Τα στοιχεία `<dl>` δεν περιέχουν μόνο σωστά ταξινομημένες ομάδες `<dt>` και `<dd>` ή στοιχεία `<script>` ή `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Τα στοιχεία `<dl>` περιέχουν μόνο σωστά ταξινομημένες ομάδες `<dt>` και `<dd>` ή στοιχεία `<script>` ή `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Τα στοιχεία λίστας ορισμών (`<dt>` και `<dd>`) πρέπει να περιτυλίγονται σε ένα γονικό στοιχείο `<dl>`, ώστε οι αναγνώστες οθόνης να μπορούν να τα εκφωνήσουν σωστά. [Μάθετε περισσότερα](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Τα στοιχεία της λίστας ορισμών δεν περιτυλίγονται σε στοιχεία `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Τα στοιχεία της λίστας ορισμών περιτυλίγονται σε στοιχεία `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Για τους χρήστες ενός αναγνώστη οθόνης, ο τίτλος λειτουργεί ως επισκόπηση της σελίδας. Για τους χρήστες μιας μηχανής αναζήτησης, ο τίτλος τούς επιτρέπει να αποφασίσουν εάν μια σελίδα είναι σχετική με την αναζήτησή τους. [Μάθετε περισσότερα](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Το έγγραφο δεν έχει ένα στοιχείο `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Το έγγραφο έχει ένα στοιχείο `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Η τιμή ενός χαρακτηριστικού αναγνωριστικού (id) πρέπει να είναι μοναδική, ώστε οι τεχνολογίες υποβοήθησης χρηστών να μην παραβλέπουν τις άλλες παρουσίες. [Μάθετε περισσότερα](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Τα χαρακτηριστικά `[id]` στη σελίδα δεν είναι μοναδικά"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Τα χαρακτηριστικά `[id]` στη σελίδα είναι μοναδικά"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Οι χρήστες ενός αναγνώστη οθόνης βασίζονται στους τίτλους των πλαισίων για την περιγραφή του περιεχομένου των πλαισίων. [Μάθετε περισσότερα](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Τα στοιχεία `<frame>` ή `<iframe>` δεν έχουν τίτλο"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Τα στοιχεία `<frame>` ή `<iframe>` έχουν έναν τίτλο"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Εάν μια σελίδα δεν προσδιορίζει κάποιο χαρακτηριστικό γλώσσας, ο αναγνώστης οθόνης υποθέτει ότι η σελίδα εμφανίζεται στην προεπιλεγμένη γλώσσα που επέλεξε ο χρήστης κατά τη ρύθμιση του αναγνώστη οθόνης. Εάν η σελίδα δεν εμφανίζεται στην προεπιλεγμένη γλώσσα, τότε ο αναγνώστης οθόνης μπορεί να μην εκφωνήσει σωστά το κείμενο της σελίδας. [Μάθετε περισσότερα](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Το στοιχείο `<html>` δεν έχει ένα χαρακτηριστικό `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Το στοιχείο `<html>` έχει ένα χαρακτηριστικό `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ο ορισμός μιας έγκυρης [γλώσσας BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) βοηθά τους αναγνώστες οθόνης να εκφωνούν σωστά το κείμενο. [Μάθετε περισσότερα](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Το στοιχείο `<html>` δεν έχει μια έγκυρη τιμή για το χαρακτηριστικό `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Το στοιχείο `<html>` έχει μια έγκυρη τιμή για το χαρακτηριστικό `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Τα πληροφοριακά στοιχεία πρέπει να στοχεύουν σε σύντομο και περιγραφικό εναλλακτικό κείμενο. Τα διακοσμητικά στοιχεία μπορούν να παραβλεφθούν με ένα κενό χαρακτηριστικό alt. [Μάθετε περισσότερα](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Τα στοιχεία εικόνας δεν έχουν χαρακτηριστικά `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Τα στοιχεία εικόνας έχουν χαρακτηριστικά `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Όταν μια εικόνα χρησιμοποιείται ως κουμπί `<input>`, η παροχή εναλλακτικού κειμένου μπορεί να βοηθήσει τους χρήστες του αναγνώστη οθόνης να κατανοήσουν τον σκοπό του κουμπιού. [Μάθετε περισσότερα](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Τα στοιχεία `<input type=\"image\">` δεν έχουν κείμενο `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Τα στοιχεία `<input type=\"image\">` έχουν κείμενο `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Οι ετικέτες διασφαλίζουν ότι οι τεχνολογίες υποβοήθησης χρηστών, όπως οι αναγνώστες οθόνης, εκφωνούν σωστά τα στοιχεία ελέγχου φορμών. [Μάθετε περισσότερα](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Τα στοιχεία φρόμας δεν έχουν συσχετισμένες ετικέτες"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Τα στοιχεία φόρμας έχουν συσχετισμένες ετικέτες"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Ένας πίνακας που χρησιμοποιείται για σκοπούς διάταξης δεν πρέπει να περιλαμβάνει στοιχεία δεδομένων, όπως τα στοιχεία th ή caption ή το χαρακτηριστικό summary, επειδή αυτό μπορεί να προκαλέσει σύγχυση στους χρήστες του αναγνώστη οθόνης. [Μάθετε περισσότερα](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Τα στοιχεία παρουσίασης `<table>` δεν αποφεύγουν τη χρήση των ετικετών `<th>` ή `<caption>` ή του χαρακτηριστικού `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Τα στοιχεία παρουσίασης `<table>` αποφεύγουν τη χρήση των ετικετών `<th>` ή `<caption>` ή του χαρακτηριστικού `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Το κείμενο συνδέσμων (και το εναλλακτικό κείμενο για εικόνες όταν χρησιμοποιούνται ως σύνδεσμοι) που είναι διακριτό, μοναδικό και έχει δυνατότητα εστίασης βελτιώνει την εμπειρία πλοήγησης για τους χρήστες των αναγνωστών οθόνης. [Μάθετε περισσότερα](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Οι σύνδεσμοι δεν έχουν διακριτό όνομα"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Οι σύνδεσμοι έχουν διακριτό όνομα"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Οι αναγνώστες οθόνης έχουν έναν συγκεκριμένο τρόπο εκφώνησης των λιστών. Η χρήση κατάλληλης δομής για τις λίστες βοηθά στην αποτελεσματικότερη λειτουργία των αναγνωστών οθόνης. [Μάθετε περισσότερα](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Οι λίστες δεν περιέχουν μόνο στοιχεία `<li>` και στοιχεία υποστήριξης σεναρίων (`<script>` και `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Οι λίστες περιέχουν μόνο στοιχεία `<li>` και στοιχεία υποστήριξης σεναρίων (`<script>` και `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Για τη σωστή εκφώνηση των στοιχείων λίστας (`<li>`) από τους αναγνώστες οθόνης, τα στοιχεία πρέπει να περιέχονται σε ένα γονικό `<ul>` ή `<ol>`. [Μάθετε περισσότερα](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Τα στοιχεία λίστας (`<li>`) δεν περιλαμβάνονται στα γονικά στοιχεία `<ul>` ή `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Τα στοιχεία λίστας (`<li>`) περιλαμβάνονται στα γονικά στοιχεία `<ul>` ή `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Οι χρήστες δεν περιμένουν ότι μια σελίδα θα ανανεωθεί αυτόματα και η εστίαση θα επιστρέψει στην κορυφή της σελίδας. Αυτό μπορεί να δημιουργήσει δυσαρέσκεια ή σύγχυση. [Μάθετε περισσότερα](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Το έγγραφο χρησιμοποιεί μια ετικέτα `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Το έγγραφο δεν χρησιμοποιεί `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Η απενεργοποίηση της δυνατότητας εστίασης αποτελεί πρόβλημα για τους χρήστες με περιορισμένη όραση που βασίζονται στη μεγέθυνση οθόνης για να βλέπουν σωστά τα περιεχόμενα μιας ιστοσελίδας. [Μάθετε περισσότερα](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "To χαρακτηριστικό `[user-scalable=\"no\"]` χρησιμοποιείται στο στοιχείο `<meta name=\"viewport\">` ή το χαρακτηριστικό `[maximum-scale]` έχει τιμή μικρότερη από 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "To χαρακτηριστικό `[user-scalable=\"no\"]` δεν χρησιμοποιείται στο στοιχείο `<meta name=\"viewport\">` και το χαρακτηριστικό `[maximum-scale]` δεν έχει τιμή μικρότερη από 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Οι αναγνώστες οθόνης δεν μπορούν να μεταφράσουν περιεχόμενο που δεν είναι κείμενο. Η προσθήκη εναλλακτικού κειμένου στα στοιχεία `<object>` βοηθά τους αναγνώστες οθόνης να αποδίδουν το νόημα στους χρήστες. [Μάθετε περισσότερα](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Τα στοιχεία `<object>` δεν έχουν κείμενο `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Τα στοιχεία `<object>` έχουν κείμενο `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Μια τιμή μεγαλύτερη από 0 υποδηλώνει μια ρητή σειρά πλοήγησης. Εάν και ορθό από τεχνικής άποψης, αυτό συχνά επηρεάζει αρνητικά την εμπειρία των χρηστών που βασίζονται στις τεχνολογίες υποβοήθησης. [Μάθετε περισσότερα](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Ορισμένα στοιχεία έχουν μια τιμή `[tabindex]` μεγαλύτερη από 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Κανένα στοιχείο δεν έχει τιμή `[tabindex]` μεγαλύτερη από 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Οι αναγνώστες οθόνης έχουν λειτουργίες που διευκολύνουν την πλοήγηση στους πίνακες. Διασφαλίζοντας ότι τα κελιά `<td>` που χρησιμοποιούν το χαρακτηριστικό `[headers]` παραπέμπουν μόνο σε άλλα κελιά στον ίδιο πίνακα, μπορείτε να βελτιώσετε την εμπειρία των χρηστών των αναγνωστών οθόνης. [Μάθετε περισσότερα](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Τα κελιά σε ένα στοιχείο `<table>` που χρησιμοποιούν το χαρακτηριστικό `[headers]` παραπέμπουν σε ένα στοιχείο `id` που δεν βρίσκεται στον ίδιο πίνακα."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Τα κελιά σε ένα στοιχείο `<table>` που χρησιμοποιούν το χαρακτηριστικό `[headers]` παραπέμπουν σε κελιά εντός του ίδιου πίνακα."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Οι αναγνώστες οθόνης έχουν λειτουργίες που διευκολύνουν την πλοήγηση στους πίνακες. Διασφαλίζοντας ότι οι κεφαλίδες πίνακα παραπέμπουν πάντα σε ένα σύνολο κελιών του πίνακα, μπορείτε να βελτιώσετε την εμπειρία των χρηστών των αναγνωστών οθόνης. [Μάθετε περισσότερα](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Τα στοιχεία `<th>` και τα στοιχεία με `[role=\"columnheader\"/\"rowheader\"]` δεν έχουν τα κελιά δεδομένων που περιγράφουν."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Τα στοιχεία `<th>` και τα στοιχεία με `[role=\"columnheader\"/\"rowheader\"]` έχουν τα κελιά δεδομένων που περιγράφουν."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ο ορισμός μιας έγκυρης [γλώσσας BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) στα στοιχεία συμβάλλει στο να διασφαλιστεί ότι ο αναγνώστης οθόνης θα εκφωνήσει σωστά το κείμενο. [Μάθετε περισσότερα](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Τα χαρακτηριστικά `[lang]` δεν έχουν έγκυρη τιμή"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Τα χαρακτηριστικά `[lang]` έχουν μια έγκυρη τιμή"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Όταν ένα βίντεο περιέχει υπότιτλους, διευκολύνεται η πρόσβαση των χρηστών που είναι κωφοί ή έχουν προβλήματα ακοής στις πληροφορίες που περιέχει. [Μάθετε περισσότερα](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Τα στοιχεία `<video>` δεν περιέχουν ένα στοιχείο `<track>` με `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Τα στοιχεία `<video>` περιέχουν ένα στοιχείο `<track>` με `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Οι ηχητικές περιγραφές παρέχουν πληροφορίες για τα βίντεο, οι οποίες δεν μπορούν να αποδοθούν μέσω των διαλόγων, όπως οι εκφράσεις προσώπου και το σκηνικό δράσης. [Μάθετε περισσότερα](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Τα στοιχεία `<video>` δεν περιέχουν ένα στοιχείο `<track>` με `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Τα στοιχεία `<video>` περιέχουν ένα στοιχείο `<track>` με `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Για ιδανική εμφάνιση στο iOS όταν οι χρήστες προσθέτουν μια προηγμένη εφαρμογή ιστού στην αρχική οθόνη, ορίστε ένα `apple-touch-icon`. Το εικονίδιο πρέπει να παραπέμπει σε μια μη διαφανή, τετράγωνη εικόνα PNG 192px (ή 180px). [Μάθετε περισσότερα](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Δεν παρέχει ένα έγκυρο `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Το `apple-touch-icon-precomposed` δεν είναι ενημερωμένο. Συνιστάται η χρήση του `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Παρέχει ένα έγκυρο `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Οι επεκτάσεις του Chrome επηρέασαν αρνητικά την απόδοση φόρτωσης αυτής της σελίδας. Δοκιμάστε να ελέγξετε τη σελίδα σε κατάσταση ανώνυμης περιήγησης ή από ένα προφίλ του Chrome χωρίς επεκτάσεις."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Αξιολόγηση σεναρίου"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Ανάλυση σεναρίου"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Συνολικός χρόνος CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο να ελαττώσετε τον χρόνο ανάλυσης, σύνθεσης και εκτέλεσης JS. Μπορεί να διαπιστώσετε ότι η προβολή μικρότερων φορτίων δεδομένων JS συμβάλλει προς αυτή την κατεύθυνση. [Μάθετε περισσότερα](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Μείωση χρόνου εκτέλεσης JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Χρόνος εκτέλεσης JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Οι μεγάλες εικόνες GIF δεν είναι αποδοτικές για την προβολή περιεχομένου κινούμενων εικόνων. Εξετάστε το ενδεχόμενο, αντί για τη χρήση εικόνων GIF, να χρησιμοποιείτε βίντεο MPEG4/WebM για τις κινούμενες εικόνες και εικόνες PNG/WebP για τις στατικές εικόνες, ώστε να εξοικονομήσετε byte δικτύου. [Μαθετε περισσότερα](https://web.dev/efficient-animated-content)."
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Χρήση μορφών βίντεο για περιεχόμενο κινούμενων εικόνων"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο αργής φόρτωσης των εικόνων εκτός οθόνης και των κρυφών εικόνων μετά τη φόρτωση όλων των κρίσιμων πόρων. Με αυτό τον τρόπο, μπορεί να ελλατώθεί ο χρόνος μετάβασης σε κατάσταση αλληλεπίδρασης. [Μάθετε περισσότερα](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Καθυστέρηση φόρτωσης εικόνων εκτός οθόνης"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Υπάρχουν πόροι οι οποίοι αποκλείουν την πρώτη μορφή της σελίδας σας. Εξετάστε το ενδεχόμενο τα κρίσιμα JS/CSS να προβάλλονται ενσωματωμένα και τα μη κρίσιμα JS/στιλ να φορτώνονται αργότερα. [Μάθετε περισσότερα](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Εξάλειψη πόρων που αποκλείουν την απόδοση"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Τα μεγάλα φορτία δικτύου συνεπάγονται οικονομικό κόστος για τους χρήστες και σχετίζονται σε μεγάλο βαθμό με εκτενείς χρόνους φόρτωσης. [Μάθετε περισσότερα](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Το συνολικό μέγεθος ήταν {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Αποφύγετε τα πολύ μεγάλα φορτία δεδομένων δικτύου"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Αποφεύγει τα πολύ μεγάλα φορτία δεδομένων δικτύου"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "H ελαχιστοποίηση των αρχείων CSS μπορεί να μειώσει τα μεγέθη φορτίων δικτύου. [Μάθετε περισσότερα](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Ελαχιστοποίηση CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Η ελαχιστοποίηση των αρχείων JavaScript μπορεί να ελαττώσει το φορτίο, τα μεγέθη και τον χρόνο ανάλυσης σεναρίων. [Μάθετε περισσότερα](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Ελαχιστοποίηση JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Καταργήστε τους ανενεργούς κανόνες από τα φύλλα στιλ και αναβάλετε τη φόρτωση των CSS που δεν χρησιμοποιούνται για το περιεχόμενο στο πάνω μέρος της σελίδας, για να ελαττώσετε τα περιττά byte που καταναλώνονται από τη δραστηριότητα δικτύου. [Μάθετε περισσότερα](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Κατάργηση CSS που δεν χρησιμοποιείται"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Καταργήστε τυχόν JavaScript που δεν χρησιμοποιείται, για να ελαττώσετε τα byte που καταναλώνονται από τη δραστηριότητα δικτύου."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Κατάργηση JavaScript που δεν χρησιμοποιείται"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Η μεγάλη διάρκεια ζωής της κρυφής μνήμης μπορεί να επιταχύνει τις επαναλαμβανόμενες επισκέψεις στη σελίδα σας. [Μάθετε περισσότερα](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 πόρος}other{Βρέθηκαν # πόροι}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Προβολή στατικών στοιχείων με επαρκή πολιτική κρυφής μνήμης"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Χρησιμοποιεί αποδοτική πολιτική κρυφής μνήμης σε στατικά στοιχεία"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Οι βελτιστοποιημένες εικόνες φορτώνονται πιο γρήγορα και καταναλώνουν λιγότερα δεδομένα κινητής τηλεφωνίας. [Μάθετε περισσότερα](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Αποδοτική κωδικοποίηση εικόνων"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Συνιστάται η προβολή εικόνων κατάλληλου μεγέθους για την εξοικονόμηση δεδομένων κινητής τηλεφωνίας και τη βελτίωση του χρόνου φόρτωσης. [Μάθετε περισσότερα](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Κατάλληλη προσαρμογή μεγέθους εικόνων"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Η προβολή των βασιζόμενων σε κείμενο πόρων πρέπει να γίνεται με συμπίεση (gzip, deflate ή brotli), ώστε να ελαχιστοποιείται ο συνολικός όγκος byte δικτύου. [Μάθετε περισσότερα](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Ενεργοποίηση συμπίεσης κειμένου"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Οι μορφές εικόνας JPEG 2000, JPEG XR και WebP συχνά παρέχουν καλύτερη συμπίεση από ό,τι οι μορφές PNG και JPEG. Αυτό σημαίνει γρηγορότερες λήψεις και μικρότερη κατανάλωση δεδομένων. [Μάθετε περισσότερα](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Προβολή εικόνων σε μορφές επόμενης γενιάς"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Εάν το πλάτος του περιεχομένου της εφαρμογής σας δεν αντιστοιχεί στο πλάτος της θύρας προβολής, η εφαρμογή σας ενδέχεται να μην είναι βελτιστοποιημένη για οθόνες κινητών συσκευών. [Μάθετε περισσότερα](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Το μέγεθος {innerWidth}px της θύρας προβολής δεν αντιστοιχεί στο μέγεθος {outerWidth}px του παραθύρου."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Το μέγεθος του περιεχομένου δεν προσαρμόζεται σωστά για τη θύρα προβολής"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Το μέγεθος του περιεχομένου έχει προσαρμοστεί σωστά για τη θύρα προβολής"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Στις ακόλουθες αλυσίδες κρίσιμων αιτημάτων φαίνεται ποιοι πόροι φορτώνονται με υψηλή προτεραιότητα. Για τη βελτίωση της φόρτωσης των σελίδων, εξετάστε το ενδεχόμενο μείωσης του μεγέθους των αλυσίδων, μείωσης του μεγέθους λήψης πόρων ή καθυστέρησης λήψης των μη απαραίτητων πόρων. [Μάθετε περισσότερα](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 αλυσίδα}other{Βρέθηκαν # αλυσίδες}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Ελαχιστοποίηση βάθους κρίσιμων αιτημάτων"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Κατάργηση / Προειδοποίηση"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Γραμμή"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Τα καταργημένα API θα αφαιρεθούν κάποια στιγμή από το πρόγραμμα περιήγησης. [Μάθετε περισσότερα](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 προειδοποίηση}other{Βρέθηκαν # προειδοποιήσεις}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Χρησιμοποιεί καταργημένα API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Αποφυγή καταργημένων API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Η κρυφή μνήμη εφαρμογής έχει καταργηθεί. [Μάθετε περισσότερα](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Βρέθηκε \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Χρησιμοποιεί προσωρινή μνήμη εφαρμογής"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Αποφυγή προσωρινής μνήμης εφαρμογής"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Ο ορισμός ενός τύπου εγγράφου (doctype) εμποδίζει τη μετάβαση του προγράμματος περιήγησης στη λειτουργία ιδιαιτεροτήτων. [Μάθετε περισσότερα](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Το όνομα τύπου εγγράφου (doctype) πρέπει να είναι μια συμβολοσειρά `html` με πεζούς χαρακτήρες."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Το έγγραφο πρέπει να περιέχει έναν τύπο εγγράφου (doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Το αναγνωριστικό publicId αναμενόταν να είναι μια κενή συμβολοσειρά"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Το αναγνωριστικό systemId αναμενόταν να είναι μια κενή συμβολοσειρά"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Από τη σελίδα λείπει ο τύπος εγγράφου (doctype) HTML, με αποτέλεσμα να ενεργοποιείται η λειτουργία ιδιαιτεροτήτων (quirks-mode)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Η σελίδα έχει τύπο εγγράφου (doctype) HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Στοιχείο"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Στατιστικό στοιχείο"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Τιμή"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Οι μηχανικοί προγραμμάτων περιήγησης συνιστούν οι σελίδες να περιέχουν λιγότερα από 1.500 στοιχεία DOM. Το ιδανικό είναι μια δενδρική δομή με βάθος έως 32 στοιχεία και λιγότερα από 60 θυγατρικά/γονικά στοιχεία. Ένα μεγάλο DOM μπορεί να αυξήσει τη χρήση της μνήμης, να προκαλέσει [υπολογισμούς στιλ](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) μεγαλύτερης διάρκειας και να δημιουργήσει [ανανεώσεις ροών διάταξης](https://developers.google.com/speed/articles/reflow) υψηλού κόστους. [Μάθετε περισσότερα](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 στοιχείο}other{# στοιχεία}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Αποφύγετε τα υπερβολικά μεγάλα μεγέθη DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Μέγιστο βάθος DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Σύνολο στοιχείων DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Μέγιστος αριθμός θυγατρικών στοιχείων"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Αποφεύγει τα υπερβολικά μεγάλα μεγέθη DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Στόχος"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Προσθέστε ένα στοιχείο `rel=\"noopener\"` ή `rel=\"noreferrer\"` στους εξωτερικούς συνδέσμους για να βελτιώσετε την απόδοση και να αποφύγετε τις ευπάθειες ασφάλειας. [Μάθετε περισσότερα](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Οι σύνδεσμοι με προορισμούς διασταυρούμενων προελεύσεων δεν είναι ασφαλείς"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Οι σύνδεσμοι με προορισμούς διασταυρούμενων προελεύσεων είναι ασφαλείς"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Δεν ήταν δυνατός ο προσδιορισμός του προορισμού για την αγκύρωση ({anchorHTML}). Εάν δεν χρησιμοποιείται ως υπερσύνδεσμος, εξετάστε το ενδεχόμενο να καταργήσετε το χαρακτηριστικό target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Οι ιστότοποι που απαιτούν τη γνωστοποίηση τοποθεσίας χωρίς προφανή αιτία προκαλούν σύγχυση ή φαίνονται ύποπτοι στους χρήστες. Συνιστάται τα αιτήματα να συνδέονται με τις ενέργειες των χρηστών. [Μάθετε περισσότερα](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Αίτημα για άδεια εντοπισμού γεωγραφικής τοποθεσίας κατά τη φόρτωση σελίδων"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Αποφυγή αιτήματος για άδεια εντοπισμού γεωγραφικής τοποθεσίας κατά τη φόρτωση σελίδων"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Έκδοση"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Όλες οι βιβλιοθήκες JavaScript διεπαφής εντοπίστηκαν στη σελίδα. [Μάθετε περισσότερα](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Εντοπίστηκαν βιβλιοθήκες JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Για τους χρήστες με αργές συνδέσεις, η δυναμική ενσωμάτωση εξωτερικών σεναρίων μέσω `document.write()` μπορεί να καθυστερήσει τη φόρτωση των σελίδων για δεκάδες δευτερόλεπτα. [Μάθετε περισσότερα](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Χρησιμοποιεί `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Αποφυγή `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Υψηλότερη σοβαρότητα"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Έκδοση βιβλιοθήκης"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Πλήθος ευπαθειών"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Ορισμένα σενάρια τρίτων μπορεί να έχουν γνωστές ευπάθειες ασφάλειας τις οποίες μπορούν εύκολα να εντοπίσουν και να εκμεταλλευτούν οι επίδοξοι εισβολείς. [Μάθετε περισσότερα](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Εντοπίστηκε 1 ευπάθεια}other{Εντοπίστηκαν # ευπάθειες}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Συμπερίληψη βιβλιοθηκών JavaScript διεπαφής με γνωστές ευπάθειες ασφάλειας"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Υψηλή"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Χαμηλή"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Μέτρια"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Αποφυγή όλων των βιβλιοθηκών JavaScript διεπαφής με γνωστές ευπάθειες ασφάλειας"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Οι ιστότοποι που απαιτούν την αποστολή ειδοποιήσεων χωρίς προφανή αιτία προκαλούν σύγχυση ή φαίνονται ύποπτοι στους χρήστες. Συνιστάται τα αιτήματα να συνδέονται με τις κινήσεις των χρηστών. [Μάθετε περισσότερα](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Αίτημα για άδεια ειδοποίησης κατά τη φόρτωση σελίδων"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Αποφυγή αιτήματος για άδεια ειδοποίησης κατά τη φόρτωση σελίδων"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Στοιχεία που απέτυχαν"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Η απαγόρευση της επικόλλησης κωδικών πρόσβασης υπονομεύει την ορθή πολιτική ασφάλειας. [Μάθετε περισσότερα](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Εμποδίζει την επικόλληση στα πεδία κωδικών πρόσβασης από τους χρήστες"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Επιτρέπει την επικόλληση στα πεδία κωδικών πρόσβασης από τους χρήστες"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Πρωτόκολλο"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Το HTTP/2 παρέχει περισσότερα πλεονεκτήματα σε σχέση με το HTTP/1.1, όπως οι δυαδικές κεφαλίδες, η πολυπλεξία και η λειτουργία αποστολής push από διακομιστή. [Μάθετε περισσότερα](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 αίτημα δεν εξυπηρετήθηκε μεσω HTTP/2}other{# αιτήματα δεν εξυπηρετήθηκαν μέσω HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Δεν χρησιμοποιεί HTTP/2 για όλους τους πόρους της"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Χρησιμοποιεί HTTP/2 για τους πόρους της"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο να επισημάνετε τις λειτουργίες επεξεργασίας συμβάντων αφής και χρήσης τροχού κύλισης ως `passive` για να βελτιώσετε την απόδοση κύλισης της σελίδας σας. [Μάθετε περισσότερα](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Δεν χρησιμοποιεί παθητικές λειτουργίες επεξεργασίας συμβάντων για τη βελτίωση της απόδοσης κύλισης"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Χρησιμοποιεί παθητικές λειτουργίες επεξεργασίας συμβάντων για τη βελτίωση της απόδοσης κύλισης"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Περιγραφή"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Τα σφάλματα που έχουν καταγραφεί στην κονσόλα υποδεικνύουν ότι υπάρχουν προβλήματα τα οποία δεν έχουν επιλυθεί. Μπορεί να σχετίζονται με σφάλματα αιτημάτων δικτύου ή με άλλα ζητήματα του προγράμματος περιήγησης. [Μάθετε περισσότερα](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Έχουν καταγραφεί σφάλματα προγράμματος περιήγησης στην κονσόλα"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Δεν έχουν καταγραφεί σφάλματα προγράμματος περιήγησης στην κονσόλα"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Αξιοποιήστε τη λειτουργία CSS προβολής γραμματοσειρών (font-display), για να διασφαλίσετε ότι το κείμενο είναι ορατό στους χρήστες κατά τη φόρτωση των γραμματοσειρών ιστοτόπου. [Μάθετε περισσότερα](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Βεβαιωθείτε ότι το κείμενο παραμένει ορατό κατά τη διάρκεια της φόρτωσης γραμματοσειράς ιστοτόπου"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Όλο το κείμενο παραμένει ορατό κατά τη διάρκεια φορτώσεων γραμματοσειράς ιστοτόπου"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Το Lighthouse δεν μπόρεσε να ελέγξει αυτόματα την τιμή προβολής γραμματοσειράς (font-display) για το ακόλουθο URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Λόγος διαστάσεων (Πραγματικός)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Λόγος διαστάσεων (Προβολή)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Οι διαστάσεις προβολής των εικόνων πρέπει να συμφωνούν με τον φυσικό λόγο διαστάσεων. [Μάθετε περισσότερα](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Προβάλλει τις εικόνες με εσφαλμένο λόγο διαστάσεων"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Προβάλλει τις εικόνες με τον σωστό λόγο διαστάσεων"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Μη έγκυρες πληροφορίες διαστάσεων εικόνας {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Τα προγράμματα περιήγησης μπορούν προληπτικά να ζητήσουν από τους χρήστες να προσθέσουν την εφαρμογή σας στην αρχική οθόνη τους, το οποίο μπορεί να οδηγήσει σε μεγαλύτερη αφοσίωση. [Μάθετε περισσότερα](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Το μανιφέστο της εφαρμογής ιστού δεν ικανοποιεί τις απαιτήσεις εγκαταστασιμότητας"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Το μανιφέστο εφαρμογής ιστού ικανοποιεί τις απαιτήσεις εγκαταστασιμότητας"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Μη ασφαλές URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Όλοι οι ιστότοποι πρέπει να προστατεύονται με HTTPS, ακόμα και αν δεν χειρίζονται ευαίσθητα δεδομένα. Το HTTPS εμποδίζει τους εισβολείς από την αλλοίωση ή την παθητική ακρόαση των επικοινωνιών μεταξύ της εφαρμογής και των χρηστών σας. Επιπλέον, αποτελεί προαπαιτούμενο για το HTTP/2 και πολλά νέα API πλατφορών ιστού. [Μάθετε περισσότερα](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 μη ασφαλές αίτημα}other{Βρέθηκαν # μη ασφαλή αιτήματα}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Δεν χρησιμοποιεί HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Χρησιμοποιεί HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Η γρήγορη φόρτωση των σελίδων μέσω ενός δικτύου κινητής τηλεφωνίας διασφαλίζει μια καλή εμπειρία για τους χρήστες κινητών. [Μάθετε περισσότερα](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Διαδραστική σε {timeInMs, number, seconds} δ."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Διαδραστική σε προσομοιωμένο δίκτυο κινητής τηλεφωνίας σε {timeInMs, number, seconds} δ."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Η σελίδα σας φορτώνεται πολύ αργά και δεν μπορείτε να αλληλεπιδράσετε μαζί της εντός 10 δευτερολέπτων. Δείτε τις ευκαιρίες και τα διαγνωστικά στοιχεία στην ενότητα Απόδοση για να μάθετε πώς μπορείτε να βελτιώσετε την απόδοση."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Η φόρτωση σελίδας δεν είναι αρκετά γρήγορη σε δίκτυα κινητής τηλεφωνίας"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Η φόρτωση σελίδας είναι αρκετά γρήγορη σε δίκτυα κινητής τηλεφωνίας"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Κατηγορία"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο να μειώσετε τον χρόνο ανάλυσης, σύνθεσης και εκτέλεσης JS. Μπορεί να διαπιστώσετε ότι η προβολή μικρότερων φορτίων δεδομένων JS συμβάλλει προς αυτή την κατεύθυνση. [Μάθετε περισσότερα](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Ελαχιστοποίηση εργασίας κύριου νήματος"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Ελαχιστοποιεί την εργασία κύριου νήματος"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Για να προσελκύσουν τον μεγαλύτερο δυνατό αριθμό χρηστών, οι ιστότοποι θα πρέπει να λειτουργούν σε κάθε κύριο πρόγραμμα περιήγησης. [Μάθετε περισσότερα](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Ο ιστότοπος λειτουργεί σε διαφορετικά προγράμματα περιήγησης"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Βεβαιωθείτε ότι οι μεμονωμένες σελίδες υποστηρίζουν συνδέσμους σε βάθος μέσω URL και ότι τα URL είναι μοναδικά με σκοπό την κοινή χρήση σε μέσα κοινωνικής δικτύωσης. [Μάθετε περισσότερα](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Κάθε σελίδα έχει URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Οι μεταβάσεις θα πρέπει να έχουν γρήγορη αίσθηση καθώς πατάτε σε διάφορα σημεία, ακόμη και σε ένα αργό δίκτυο. Αυτή η εμπειρία αποτελεί το κλειδί για την απόδοση που αντιλαμβάνεται ένας χρήστης. [Μάθετε περισσότερα](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Οι μεταβάσεις σελίδας δεν δίνουν την αίσθηση ότι καθυστερούν στο δίκτυο"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Ο εκτιμώμενος λανθάνων χρόνος στοιχείων εισόδου αποτελεί εκτίμηση του χρόνου που απαιτείται, σε χιλιοστά του δευτερολέπτου, προκειμένου η εφαρμογή σας να ανταποκριθεί στα στοιχεία εισόδου χρήστη στο διάστημα των 5 δευτερολέπτων με τον μεγαλύτερο φόρτο κατά τη φόρτωση της σελίδας. Εάν ο λανθάνων χρόνος είναι μεγαλύτερος από 50 χιλιοστά δευτερολέπτου, οι χρήστες μπορεί να θεωρήσουν ότι η εφαρμογή σας είναι αργή. [Μάθετε περισσότερα](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Εκτιμώμενος λανθάνων χρόνος στοιχείων εισόδου"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Η πρώτη μορφή με περιεχόμενο υποδεικνύει πότε σχεδιάζεται το πρώτο κείμενο ή η πρώτη εικόνα. [Μάθετε περισσότερα](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Πρώτη μορφή με περιεχόμενο"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Η πρώτη αδράνεια CPU υποδεικνύει πότε είναι η πρώτη φορά που η δραστηριότητα του κύριου νήματος της σελίδας είναι τόσο χαμηλή ώστε να διαχειριστεί στοιχεία εισόδου. [Μάθετε περισσότερα](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Πρώτη αδράνεια CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Η πρώτη χρήσιμη μορφή υπολογίζει πότε καθίσταται ορατό το κύριο περιεχόμενο μιας σελίδας. [Μάθετε περισσότερα](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Πρώτη χρήσιμη μορφή"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Ο χρόνος για αλληλεπίδραση είναι το χρονικό διάστημα που απαιτείται προκειμένου η σελίδα να γίνει πλήρως διαδραστική. [Μάθετε περισσότερα](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Χρόνος για Αλληλεπίδραση"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Η μέγιστη δυνητική καθυστέρηση πρώτης εισόδου που θα μπορούσαν να αντιμετωπίσουν οι χρήστες είναι η διάρκεια, σε χιλιοστά δευτερολέπτου, της πιο χρονοβόρας εργασίας. [Μάθετε περισσότερα](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Μέγ. δυνατή καθυστέρηση πρώτης εισόδου"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Το ευρετήριο ταχύτητας δηλώνει πόσο γρήγορα γίνεται ορατό το περιεχόμενο μιας σελίδας. [Μάθετε περισσότερα](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Ευρετήριο ταχύτητας"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Η συνολική διάρκεια, σε χιλιοστά δευτερολέπτου, των χρονικών διαστημάτων από την πρώτη μορφή με περιεχόμενο μέχρι τον χρόνο για αλληλεπίδραση, όταν η διάρκεια της εργασίας υπερβαίνει τα 50 χιλιοστά δευτερολέπτου."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Συνολικός χρόνος αποκλεισμού"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Οι χρόνοι αποστολής και επιστροφής δικτύου (RTT) έχουν μεγάλο αντίκτυπο στην απόδοση. Εάν ο χρόνος RTT προς μια προέλευση είναι υψηλός, αυτό σημαίνει ότι η χρήση διακομιστών πιο κοντά στον χρήστη θα μπορούσε να βελτιώσει την απόδοση. [Μάθετε περισσότερα](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Χρόνοι αποστολής και επιστροφής δικτύου"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Οι λανθάνοντες χρόνοι των διακομιστών μπορούν να επηρεάσουν την απόδοση στον ιστό. Εάν ο λανθάνων χρόνος του διακομιστή μιας προέλευσης είναι υψηλός, αυτό αποτελεί ένδειξη ότι ο διακομιστής είναι υπερφορτωμένος ή ότι έχει ανεπαρκές σύστημα υποστήριξης. [Μάθετε περισσότερα](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Λανθάνοντες χρόνοι συστημάτων υποστήριξης διακομιστή"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Ένα service worker επιτρέπει στην εφαρμογή ιστού σας να είναι πιο αξιόπιστη όταν εκτελείται σε απρόβλεπτες συνθήκες δικτύου. [Μάθετε περισσότερα](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "Το `start_url` δεν αποκρίνεται με κωδικό 200 όταν είναι εκτός σύνδεσης"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "Το `start_url` αποκρίνεται με κωδικό 200 όταν είναι εκτός σύνδεσης"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Το Lighthouse δεν μπόρεσε να διαβάσει το `start_url` από το μανιφέστο. Επομένως, το `start_url` θεωρήθηκε ότι είναι το URL του εγγράφου. Μήνυμα σφάλματος: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Υπέρβαση προϋπολογισμού"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Διατηρήστε την ποσότητα και το μέγεθος των αιτημάτων δικτύου εντός των στόχων που ορίζονται από τον παρεχόμενο προϋπολογισμό απόδοσης. [Μάθετε περισσότερα](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 αίτημα}other{# αιτήματα}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Προϋπολογισμός απόδοσης"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Αν έχετε ήδη ρυθμίσει το HTTPS, βεβαιωθείτε ότι ανακατευθύνετε όλη την επισκεψιμότητα HTTP σε HTTPS, προκειμένου να ενεργοποιήσετε ασφαλείς λειτουργίες ιστού για όλους τους χρήστες σας. [Μάθετε περισσότερα](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Δεν ανακατευθύνσει την επισκεψιμότητα HTTP σε HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Ανακατευθύνει την επισκεψιμότητα HTTP σε HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Οι ανακατευθύνσεις προκαλούν πρόσθετες καθυστερήσεις στη φόρτωση της σελίδας. [Μάθετε περισσότερα](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Αποφυγή ανακατευθύνσεων πολλών σελίδων"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Για τον ορισμό προϋπολογισμών για την ποσότητα και το μέγεθος των πόρων μιας σελίδας, προσθέστε ένα αρχείο budget.json. [Μάθετε περισσότερα](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 αίτημα • {byteCount, number, bytes} KB}other{# αιτήματα • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Φροντίστε να διατηρείτε το πλήθος των αιτημάτων χαμηλό και το μέγεθος των μεταφορών μικρό"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Οι κανονικοί σύνδεσμοι προτείνουν το URL που πρέπει να εμφανιστεί στα αποτελέσματα αναζήτησης. [Μάθετε περισσότερα](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Πολλά URL σε διένεξη ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Παραπέμπει σε διαφορετικό τομέα ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Μη έγκυρο URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Παραπέμπει σε μια άλλη τοποθεσία `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Σχετικό URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Παραπέμπει στο ριζικό URL του τομέα (την αρχική σελίδα), αντί για μια αντίστοιχη σελίδα περιεχομένου"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Το έγγραφο δεν έχει ένα έγκυρο `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Το έγγραφο έχει ένα έγκυρο `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Τα μεγέθη γραμματοσειράς κάτω από 12px είναι πολύ μικρά για να είναι ευανάγνωστα, με αποτέλεσμα οι επισκέπτες από κινητά να χρειάζεται να μεγεθύνουν με τα δάχτυλά τους τη σελίδα για να διαβάσουν το περιεχόμενο. Προσπαθήστε πάνω από το 60% του κειμένου της σελίδας να έχει μέγεθος μεγαλύτερο από ή ίσο με 12px. [Μάθετε περισσότερα](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} ευανάγνωστο κείμενο"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Το κείμενο είναι δυσανάγνωστο επειδή δεν υπάρχει βελτιστοποιημένη μεταετικέτα θύρα προβολής για οθόνες κινητών."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} του κειμένου είναι πολύ μικρό (βάσει ενός δείγματος {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Το έγγραφο δεν χρησιμοποιεί ευανάγνωστα μεγέθη γραμματοσειράς"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Το έγγραφο χρησιμοποιεί ευανάγνωστα μεγέθη γραμματοσειράς"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Οι σύνδεσμοι hreflang ενημερώνουν τις μηχανές αναζήτησης σχετικά με την έκδοση σελίδας που πρέπει να αναφέρουν στα αποτελέσματα αναζήτησης για μια συγκεκριμένη γλώσσα ή περιοχή. [Μάθετε περισσότερα](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Το έγγραφο δεν έχει ένα έγκυρο `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Το έγγραφο έχει ένα έγκυρο `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Οι σελίδες με ανεπιτυχείς κωδικούς κατάστασης HTTP μπορεί να μην ευρετηριαστούν σωστά. [Μάθετε περισσότερα](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Η σελίδα αποκρίνεται με ανεπιτυχή κωδικό κατάστασης HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Η σελίδα αποκρίνεται με επιτυχή κωδικό κατάστασης HTTP"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Οι μηχανές αναζήτησης δεν μπορούν να συμπεριλάβουν τις σελίδες σας στα αποτελέσματα αναζήτησης, εάν δεν έχουν άδεια για την εκτέλεση ανίχνευσης σε αυτές. [Μάθετε περισσότερα](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Η σελίδα αποκλείεται από την ευρετηρίαση"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Η σελίδα δεν αποκλείεται από την ευρετηρίαση"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Το περιγραφικό κείμενο συνδέσμων βοηθά τις μηχανές αναζήτησης να κατανοήσουν το περιεχόμενό σας. [Μάθετε περισσότερα](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 σύνδεσμος}other{Βρέθηκαν # σύνδεσμοι}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Οι σύνδεσμοι δεν έχουν περιγραφικό κείμενο"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Οι σύνδεσμοι έχουν περιγραφικό κείμενο"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Εκτελέστε το [Εργαλείο δοκιμής δομημένων δεδομένων](https://search.google.com/structured-data/testing-tool/) και το [Structured Data Linter](http://linter.structured-data.org/) για να επικυρώσετε τα δομημένα δεδομένα. [Μάθετε περισσότερα](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Τα δομημένα δεδομένα είναι έγκυρα"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Οι περιγραφές μεταδεδομένων μπορούν να συμπεριληφθούν στα αποτελέσματα αναζήτησης για τη συνόψιση του περιεχομένου των σελίδων. [Μάθετε περισσότερα](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Το κείμενο περιγραφής είναι κενό."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Το έγγραφο δεν έχει περιγραφή μεταδεδομένων"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Το έγγραφο έχει περιγραφή μεταδεδομένων"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Οι μηχανές αναζήτησης δεν μπορούν να ευρετηριάσουν το περιεχόμενο των προσθηκών, ενώ πολλές συσκευές περιορίζουν ή δεν υποστηρίζουν τις προσθήκες. [Μάθετε περισσότερα](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Το έγγραφο χρησιμοποιεί προσθήκες"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Το έγγραφο αποφεύγει τις προσθήκες"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Εάν το αρχείο σας robots.txt έχει εσφαλμένη μορφή, οι ανιχνευτές ενδεχομένως να μην μπορούν να κατανοήσουν με ποιον τρόπο θέλετε να γίνεται η ανίχνευση ή καταλογοποίηση του ιστοτόπου σας. [Μάθετε περισσότερα](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Το αίτημα για το αρχείο robots.txt επέστρεψε τον κωδικό κατάστασης HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Βρέθηκε 1 σφάλμα}other{Βρέθηκαν # σφάλματα}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Το Lighthouse δεν ήταν δυνατό να κατεβάσει ένα αρχείο robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Το αρχείο robots.txt δεν είναι έγκυρο"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Το αρχείο robots.txt είναι έγκυρο"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Τα στοιχεία αλληλεπίδρασης, όπως είναι τα κουμπιά και οι σύνδεσμοι, πρέπει να είναι αρκετά μεγάλα (48x48px) και με επαρκή χώρο γύρω τους, ώστε να μπορούν να πατηθούν εύκολα από τους χρήστες χωρίς να επικαλύπτουν άλλα στοιχεία. [Μάθετε περισσότερα](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Το {decimalProportion, number, percent} των επιλεγόμενων με πάτημα στοιχείων έχουν κατάλληλο μέγεθος"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Τα στοιχεία που επιλέγονται με πάτημα είναι υπερβολικά μικρά γιατί δεν υπάρχει βελτιστοποιημένη μεταετικέτα θύρας προβολής για οθόνες κινητών"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Τα στοιχεία που επιλέγονται με πάτημα δεν έχουν κατάλληλο μέγεθος"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Αλληλεπικαλυπτόμενο στοιχείο επιλογής με πάτημα"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Στοιχείο επιλογής με πάτημα"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Τα στοιχεία που επιλέγονται με πάτημα έχουν το κατάλληλο μέγεθος"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Το service worker είναι η τεχνολογία που επιτρέπει στην εφαρμογή σας να χρησιμοποιεί πολλές λειτουργίες προηγμένων εφαρμογών ιστού, όπως η λειτουργία εκτός σύνδεσης, η προσθήκη στην αρχική οθόνη και οι ειδοποιήσεις push. [Μάθετε περισσότερα](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Αυτή η σελίδα ελέγχεται από ένα service worker, αλλά δεν βρέθηκε κανένα `start_url` επειδή το μανιφέστο απέτυχε να αναλυθεί ως έγκυρο JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Αυτή η σελίδα ελέγχεται από ένα service worker, αλλά το `start_url` ({startUrl}) δεν βρίσκεται στο εύρος του service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Αυτή η σελίδα ελέγχεται από ένα service worker, αλλά δεν βρέθηκε κανένα `start_url` επειδή δεν έγινε λήψη μανιφέστου."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Αυτή η προέλευση διαθέτει ένα περισσότερα service worker, αλλά η σελίδα ({pageUrl}) βρίσκεται εκτός εύρους."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Δεν καταγράφει service worker που ελέγχει τη σελίδα και το `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Καταγράφει ένα service worker που ελέγχει μια σελίδα και το `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Μια θεματική οθόνη εκκίνησης διασφαλίζει μια εμπειρία υψηλής ποιότητας όταν οι χρήστες εκκινούν την εφαρμογή σας από την αρχική οθόνη τους. [Μάθετε περισσότερα](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Δεν έχει διαμορφωθεί για προσαρμοσμένη οθόνη εκκίνησης"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Διαμορφώνεται από προσαρμοσμένη οθόνη εκκίνησης"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Μπορείτε να προσθέσετε ένα θέμα στη γραμμή διευθύνσεων του προγράμματος περιήγησης ώστε να ταιριάζει με τον ιστότοπό σας. [Μάθετε περισσότερα](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Δεν ορίζει ένα χρώμα θέματος για τη γραμμή διευθύνσεων."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Ορίζει ένα χρώμα θέματος για τη γραμμή διευθύνσεων."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Χρόνος αποκλεισμού κύριου νήματος"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Τρίτο μέρος"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Ο κώδικας τρίτων παρόχων μπορεί να επηρεάσει σημαντικά την απόδοση φόρτωσης. Περιορίστε τον αριθμό των περιττών τρίτων παρόχων και προσπαθήστε η φόρτωση του κώδικα τρίτων παρόχων να γίνεται αφού πρώτα έχει ολοκληρωθεί η φόρτωση της σελίδας σας. [Μάθετε περισσότερα](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Ο κώδικας τρίτου μέρους απέκλεισε το κύριο νήμα για {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Μείωση αντίκτυπου του κώδικα τρίτου μέρους"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Χρήση κώδικα τρίτου μέρους"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Ο χρόνος μέχρι το πρώτο byte προσδιορίζει τον χρόνο που χρειάζεται για την αποστολή μιας απόκρισης από τον διακομιστή σας. [Μάθετε περισσότερα](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Το ριζικό έγγραφο χρειάστηκε {timeInMs, number, milliseconds} χλστ.δ."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Μείωση χρόνων απόκρισης διακομιστή (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Οι χρόνοι απόκρισης διακομιστή είναι χαμηλοί (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Διάρκεια"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Ώρα έναρξης"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Τύπος"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο να προσθέσετε στην εφαρμογή σας το API χρόνων χρήστη (User Timing API) για να μετράτε την πραγματική απόδοση της εφαρμογής σας κατά τη διάρκεια σημαντικών εμπειριών χρήστη. [Μάθετε περισσότερα](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 χρόνος χρήστη}other{# χρόνοι χρήστη}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Ενδείξεις και μετρήσεις Χρόνων χρήστη"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Βρέθηκε ένα <link> προσύνδεσης για το {securityOrigin}, αλλά δεν χρησιμοποιήθηκε από το πρόγραμμα περιήγησης. Ελέγξτε ότι χρησιμοποιείτε σωστά το χαρακτηριστικό `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο προσθήκης υποδείξεων πόρων `preconnect` ή `dns-prefetch`, για να δημιουργήσετε πρώιμες συνδέσεις σε σημαντικές προελεύσεις τρίτους μέρους. [Μάθετε περισσότερα](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Προσύνδεση σε απαιτούμενες προελεύσεις"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Βρέθηκε ένα <link> προφόρτωσης για το {preloadURL}, αλλά δεν χρησιμοποιήθηκε από το πρόγραμμα περιήγησης. Ελέγξτε ότι χρησιμοποιείτε σωστά το χαρακτηριστικό `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Εξετάστε το ενδεχόμενο χρήσης του `<link rel=preload>` για την προτεραιοποίηση της ανάκτησης των πόρων που τώρα ζητούνται αργότερα κατά τη φόρτωση της σελίδας. [Μάθετε περισσότερα](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Σημαντικά αιτήματα προφόρτωσης"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Προσθέστε μια ετικέτα `<meta name=\"viewport\">` για να βελτιστοποιήσετε την εφαρμογή σας για οθόνες κινητών συσκευών. [Μάθετε περισσότερα](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Δεν βρέθηκε ετικέτα `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Δεν έχει ετικέτα `<meta name=\"viewport\">` με `width` ή `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Έχει ετικέτα `<meta name=\"viewport\">` με `width` ή `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Η εφαρμογή σας θα πρέπει να εμφανίζει κάποιο περιεχόμενο όταν η JavaScript είναι απενεργοποιημένη, ακόμη και αν είναι απλώς μια προειδοποίηση που ενημερώνει τον χρήστη ότι η JavaScript είναι απαραίτητη για τη χρήση της εφαρμογής. [Μάθετε περισσότερα](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Το σώμα της σελίδας θα πρέπει να αποδίδει κάποιο περιεχόμενο αν τα σενάριά του δεν είναι διαθέσιμα."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Δεν παρέχει εναλλακτικό περιεχόμενο όταν η JavaScript δεν είναι διαθέσιμη"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Περιλαμβάνει κάποιο περιεχόμενο όταν η JavaScript δεν είναι διαθέσιμη"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Εάν δημιουργείτε μια προηγμένη εφαρμογή ιστού, εξετάστε το ενδεχόμενο χρήσης ενός service worker ώστε η εφαρμογή σας να μπορεί να λειτουργεί εκτός σύνδεσης. [Μάθετε περισσότερα](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Η τρέχουσα σελίδα δεν αποκρίνεται με κωδικό 200 όταν είναι εκτός σύνδεσης"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Η τρέχουσα σελίδα αποκρίνεται με κωδικό 200 όταν είναι εκτός σύνδεσης"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Αυτή η σελίδα μπορεί να μην φορτώνεται εκτός σύνδεσης επειδή το URL δοκιμής σας ({requested}) ανακατευθύνθηκε στο \"{final}\". Προσπαθήστε να δοκιμάσετε απευθείας το δεύτερο URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε τη χρήση των ARIA στην εφαρμογή σας, κάνοντας καλύτερη την εμπειρία χρήστη σε τεχνολογίες για άτομα με ειδικές ανάγκες, όπως στον αναγνώστη οθόνης."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να παρέχετε εναλλακτικό περιεχόμενο για ήχο και βίντεο. Αυτό μπορεί να βελτιώσει την εμπειρία για χρήστες με προβλήματα ακοής ή όρασης."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Ήχος και βίντεο"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Αυτά τα στοιχεία επισημαίνουν συνήθεις βέλτιστες πρακτικές για την προσβασιμότητα."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Βέλτιστες πρακτικές"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Αυτοί οι έλεγχοι επισημαίνουν ευκαιρίες για τη [βελτίωση της προσβασιμότητας της εφαρμογής ιστού σας](https://developers.google.com/web/fundamentals/accessibility). Μόνο ένα μέρος των ζητημάτων προσβασιμότητας μπορεί να εντοπιστεί αυτόματα. Ως εκ τούτου, συνιστάται να προβείτε και σε μη αυτόματες δοκιμές."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Αυτά τα στοιχεία σχετίζονται με τομείς τους οποίους δεν μπορεί να καλύψει ένα εργαλείο αυτοματοποιημένων δοκιμών. Μάθετε περισσότερα στον οδηγό μας σχετικά με τη [διεξαγωγή ενός ελέγχου προσβασιμότητας](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Προσβασιμότητα"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε την αναγνωσιμότητα του περιεχομένου σας."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Αντίθεση"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε την ερμηνεία του περιεχομένου σας από χρήστες με διαφορετικές τοπικές ρυθμίσεις."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Διεθνοποίηση και τοπική προσαρμογή"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε τη σημασιολογία των στοιχείων ελέγχου στην εφαρμογή σας. Αυτό μπορεί να κάνει καλύτερη την εμπειρία για τους χρήστες τεχνολογίας για άτομα με ειδικές ανάγκες, όπως του αναγνώστη οθόνης."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Ονόματα και ετικέτες"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε την πλοήγηση με πληκτρολόγιο στην εφαρμογή σας."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Πλοήγηση"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Αυτές είναι ευκαιρίες να βελτιώσετε την εμπειρία ανάγνωσης δεδομένων σε πίνακες ή λίστες με τη χρήση τεχνολογίας για άτομα με ειδικές ανάγκες, όπως του αναγνώστη οθόνης."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Πίνακες και λίστες"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Βέλτιστες πρακτικές"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Οι προϋπολογισμοί απόδοσης θέτουν τα πρότυπα για την απόδοση του ιστοτόπου σας."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Προϋπολογισμοί"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Περισσότερες πληροφορίες σχετικά με την απόδοση της εφαρμογής σας. Αυτά τα δεδομένα δεν [επηρεάζουν άμεσα](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) τη βαθμολογία απόδοσης."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Διαγνωστικά στοιχεία"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Η πιο σημαντική πτυχή της απόδοσης είναι η ταχύτητα με την οποία αποδίδονται τα pixel στην οθόνη. Σημαντικές μετρήσεις: Πρώτη μορφή με περιεχόμενο, Πρώτη χρήσιμη μορφή"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Βελτιώσεις πρώτης μορφής"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Αυτές οι προτάσεις μπορούν να βοηθήσουν στην ταχύτερη φόρτωση της σελίδας σας. Δεν [επηρεάζουν άμεσα](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) τη βαθμολογία απόδοσης."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Ευκαιρίες"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Μετρήσεις"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Βελτιώστε τη συνολική εμπειρία φόρτωσης, για να μπορεί η σελίδα να ανταποκρίνεται και να είναι έτοιμη για χρήση το συντομότερο δυνατό. Σημαντικές μετρήσεις: Χρόνος για Αλληλεπίδραση, Ευρετήριο ταχύτητας"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Συνολικές βελτιώσεις"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Απόδοση"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Αυτοί οι έλεγχοι επαληθεύουν τα στοιχεία μιας προηγμένης εφαρμογής ιστού. [Μάθετε περισσότερα](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Αυτοί οι έλεγχοι απαιτούνται από τη [Λίστα ελέγχου PWA](https://developers.google.com/web/progressive-web-apps/checklist) σημείου αναφοράς αλλά δεν ελέγχονται αυτόματα από το Lighthouse. Δεν επηρεάζουν τη βαθμολογία σας αλλά είναι σημαντικό να τους επαληθεύσετε με μη αυτόματο τρόπο."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Προηγμένη εφαρμογή ιστού"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Γρήγορος και αξιόπιστος"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Δυνατότητα εγκατάστασης"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Με βελτιστοποίηση PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Αυτοί οι έλεγχοι διασφαλίζουν ότι η σελίδα σας είναι βελτιστοποιημένη για κατάταξη στα αποτελέσματα μηχανών αναζήτησης. Υπάρχουν επιπλέον παράγοντες που δεν ελέγχονται από το Lighthouse και μπορεί να επηρεάσουν την κατάταξη της σελίδας σας στην αναζήτηση. [Μάθετε περισσότερα](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Εκτελέστε αυτά τα πρόσθετα εργαλεία επικύρωσης, για να ελέγξετε περισσότερες βέλτιστες πρακτικές SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Μορφοποιήστε το HTML με τρόπο που να επιτρέπει στους ανιχνευτές να κατανοούν καλύτερα το περιεχόμενο της εφαρμογής σας."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Βέλτιστες πρακτικές περιεχομένου"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Για να εμφανίζεται στα αποτελέσματα αναζήτησης, οι ανιχνευτές χρειάζονται πρόσβαση στην εφαρμογή σας."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Ανίχνευση και δημιουργία ευρετηρίου"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Βεβαιωθείτε ότι οι σελίδες σας είναι κατάλληλα διαμορφωμένες για κινητά, ώστε οι χρήστες να μην χρειάζεται να πλησιάζουν τα δάχτυλά τους ή να κάνουν μεγέθυνση για να διαβάζουν τις σελίδες περιεχομένου. [Μάθετε περισσότερα](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Φιλική προς κινητά"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL κρυφής μνήμης"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Τοποθεσία"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Όνομα"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Αιτήματα"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Τύπος πόρου"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Μέγεθος"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Χρόνος χρήσης"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Μέγεθος μεταφοράς"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Δυνητικές εξοικονομήσεις"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Δυνητικές εξοικονομήσεις"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Δυνηητική εξοικονόμηση {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Δυνητική εξοικονόμηση {wastedMs, number, milliseconds} χλστ.δ."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Έγγραφο"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Γραμματοσειρά"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Εικόνα"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Μέσα"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} χλστ.δ."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Άλλο"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Σενάριο"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} δ."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Φύλλο στιλ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Τρίτο μέρος"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Σύνολο"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Παρουσιάστηκε κάποιο πρόβλημα με την εγγραφή του ίχνους κατά τη φόρτωση της σελίδας σας. Εκτελέστε ξανά το Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Λήξη χρονικού ορίου κατά την αναμονή για αρχική σύνδεση του πρωτοκόλλου εργαλείου εντοπισμού σφαλμάτων."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Το Chrome δεν συγκέντρωσε στιγμιότυπα οθόνης κατά τη φόρτωση της σελίδας. Βεβαιωθείτε ότι υπάρχει ορατό περιεχόμενο στη σελίδα και έπειτα δοκιμάστε να εκτελέσετε ξανά το Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Οι διακομιστές DNS δεν ήταν δυνατό να επιλύσουν τον παρεχόμενο τομέα."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Παρουσιάστηκε κάποιο σφάλμα στη λειτουργία συγκέντρωσης για τον απαιτούμενο πόρο {artifactName}: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Προέκυψε εσωτερικό σφάλμα Chrome. Επανεκκινήστε το Chrome και δοκιμάστε να εκτελέσετε ξανά το Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Δεν εκτελέστηκε η λειτουργία συγκέντρωσης για τον απαιτούμενο πόρο {artifactName}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Το Lighthouse δεν ήταν δυνατό να φορτώσει με αξιοπιστία τη σελίδα που ζητήσατε. Βεβαιωθείτε ότι ελέγχετε το σωστό URL και ότι ο διακομιστής ανταποκρίνεται σωστά σε όλα τα αιτήματα."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Το Lighthouse δεν ήταν δυνατό να φορτώσει με αξιοπιστία το URL που ζητήσατε, επειδή η σελίδα σταμάτησε να ανταποκρίνεται."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Το URL που παρείχατε δεν έχει ένα έγκυρο πιστοποιητικό ασφάλειας. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Το Chrome εμπόδισε την εμφάνιση μιας σελίδας με παρενθετική διαφήμιση. Βεβαιωθείτε ότι ελέγχετε το σωστό URL και ότι ο διακομιστής αποκρίνεται σωστά σε όλα τα αιτήματα."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Το Lighthouse δεν μπόρεσε να φορτώσει με αξιοπιστία τη σελίδα που ζητήσατε. Βεβαιωθείτε ότι ελέγχετε το σωστό URL και ότι ο διακομιστής αποκρίνεται σωστά σε όλα τα αιτήματα. (Λεπτομέρειες: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Το Lighthouse δεν μπόρεσε να φορτώσει με αξιοπιστία τη σελίδα που ζητήσατε. Βεβαιωθείτε ότι ελέγχετε το σωστό URL και ότι ο διακομιστής αποκρίνεται σωστά σε όλα τα αιτήματα. (Κωδικός κατάστασης: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Χρειάστηκε υπερβολικά πολύς χρόνος για τη φόρτωση της σελίδας σας. Συμβουλευτείτε τις ευκαιρίες στην αναφορά, για να μειώσετε τον χρόνο φόρτωσης της σελίδας, και έπειτα δοκιμάστε να εκτελέσετε ξανά το Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Η αναμονή για απόκριση του πρωτοκόλλου DevTools έχει υπερβεί τον μέγιστο επιτρεπόμενο χρόνο. (Μέθοδος: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Η λήψη περιεχομένου πόρων έχει υπερβεί τον εκχωρημένο χρόνο"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Το URL που παρείχατε φαίνεται ότι δεν είναι έγκυρο."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Εμφάνιση ελέγχων"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Αρχική πλοήγηση"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Μέγιστος λανθάνων χρόνος κρίσιμης διαδρομής:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Σφάλμα!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Σφάλμα αναφοράς: Δεν υπάρχουν πληροφορίες ελέγχου"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Εργαστηριακά δεδομένα"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Ανάλυση της τρέχουσας σελίδας από το [Lighthouse](https://developers.google.com/web/tools/lighthouse/) σε ένα προσομειωμένο δίκτυο κινητής τηλεφωνίας. Οι τιμές είναι κατ' εκτίμηση και μπορεί να διαφέρουν."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Επιπλέον στοιχεία για μη αυτόματο έλεγχο"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Δεν ισχύει"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Ευκαιρία"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Εκτιμώμενες εξοικονομήσεις"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Έλεγχοι που ολοκληρώθηκαν επιτυχώς"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Σύμπτυξη αποσπάσματος"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Ανάπτυξη αποσπάσματος"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Εμφάνιση πόρων τρίτων"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Παρουσιάστηκαν ορισμένα ζητήματα τα οποία επηρεάζουν αυτήν την εκτέλεση του Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Οι τιμές είναι κατ' εκτίμηση και μπορεί να διαφέρουν. Η βαθμολογία απόδοσης [βασίζεται σε αυτές τις μετρήσεις](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Έλεγχοι που ολοκληρώθηκαν αλλά με προειδοποιήσεις"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Προειδοποιήσεις: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Εξετάστε το ενδεχόμενο μεταφόρτωσης του GIF σε μια υπηρεσία η οποία θα το διαθέσει για ενσωμάτωση ως βίντεο HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Εγκαταστήστε μια προσθήκη [WordPress αργής φόρτωσης](https://wordpress.org/plugins/search/lazy+load/) η οποία παρέχει τη δυνατότητα αναβολής φόρτωσης των εικόνων εκτός οθόνης. Εναλλακτικά, χρησιμοποιήστε ένα θέμα που παρέχει αυτή τη δυνατότητα. Εξετάστε επίσης το ενδεχόμενο χρήσης της [προσθήκης AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Υπάρχουν διάφορες προσθήκες WordPress που μπορούν να σας βοηθήσουν στην [ενσωμάτωση των σημαντικών στοιχείων](https://wordpress.org/plugins/search/critical+css/) ή στην [καθυστέρηση των λιγότερο σημαντικών πόρων](https://wordpress.org/plugins/search/defer+css+javascript/). Λάβετε υπόψη ότι οι βελτιστοποιήσεις που παρέχονται από αυτές τις προσθήκες ενδέχεται να προκαλέσουν προβλήματα στις λειτουργίες των θεμάτων ή των προσθηκών σας. Ως εκ τούτου, είναι πιθανό να χρειαστεί να κάνετε αλλαγές στον κώδικα."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Τα θέματα, οι προσθήκες και οι προδιαγραφές διακομιστή συμβάλλουν στον χρόνο απόκρισης του διακομιστή. Αν θέλετε, μπορείτε να ψάξετε για ένα περισσότερο βελτιστοποιημένο θέμα, να επιλέξετε προσεκτικά μια προσθήκη βελτιστοποίησης ή/και να αναβαθμίσετε τον διακομιστή σας."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Εξετάστε το ενδεχόμενο εμφάνισης αποσπασμάτων στις λίστες αναρτήσεών σας (π.χ. μέσω της ετικέτας \"περισσότερες\"), μειώνοντας τον αριθμό των αναρτήσεων που εμφανίζονται σε μια συγκεκριμένη σελίδα, χωρίζοντας τις μεγάλες αναρτήσεις σε πολλές σελίδες ή χρησιμοποιώντας μια προσθήκη για φόρτωση με καθυστέρηση των σχολίων."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Μερικές [προσθήκες WordPress](https://wordpress.org/plugins/search/minify+css/) μπορούν να επιταχύνουν τον ιστότοπό σας συνενώνοντας, ελαχιστοποιώντας και συμπιέζοντας τα στιλ σας. Μπορείτε επίσης να χρησιμοποιήσετε μια διεργασία δόμησης για την εκ των προτέρων πραγματοποίηση αυτής της ελαχιστοποίησης, εφόσον υπάρχει αυτή η δυνατότητα."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Μερικές [προσθήκες WordPress](https://wordpress.org/plugins/search/minify+javascript/) μπορούν να επιταχύνουν τον ιστότοπό σας συνενώνοντας, ελαχιστοποιώντας και συμπιέζοντας τα σενάριά σας. Μπορείτε επίσης να χρησιμοποιήσετε μια διεργασία δόμησης για την εκ των προτέρων πραγματοποίηση αυτής της ελαχιστοποίησης, εφόσον υπάρχει αυτή η δυνατότητα."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Εξετάστε το ενδεχόμενο μείωσης ή αλλαγής των [προσθηκών WordPress](https://wordpress.org/plugins/) που φορτώνουν μη χρησιμοποιούμενα CSS στη σελίδα σας. Για να προσδιορίσετε τις προσθήκες που προσθέτουν περιττό κώδικα CSS, δοκιμάστε να εκτελέσετε [κάλυψη κώδικα](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) στο Chrome DevTools. Μπορείτε να προσδιορίσετε το θέμα ή την προσθήκη που ευθύνεται μέσω του URL του φύλλου στιλ. Αναζητήστε προσθήκες που διαθέτουν πολλά φύλλα στιλ στη λίστα, στα οποία ένα μεγάλο μέρος της κάλυψης κώδικα έχει κόκκινο χρώμα. Μια προσθήκη θα πρέπει να τοποθετεί στην ουρά ένα φύλλο στιλ, μόνο αν χρησιμοποιείται στη σελίδα."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Εξετάστε το ενδεχόμενο μείωσης ή αλλαγής των [προσθηκών WordPress](https://wordpress.org/plugins/) που φορτώνουν μη χρησιμοποιούμενη JavaScript στη σελίδα σας. Για να προσδιορίσετε τις προσθήκες που προσθέτουν περιττό κώδικα JS, δοκιμάστε να εκτελέσετε [κάλυψη κώδικα](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) στο Chrome DevTools. Μπορείτε να προσδιορίσετε το θέμα ή την προσθήκη που ευθύνεται μέσω του URL του σεναρίου. Αναζητήστε προσθήκες που διαθέτουν πολλά σενάρια στη λίστα, στα οποία ένα μεγάλο μέρος της κάλυψης κώδικα έχει κόκκινο χρώμα. Μια προσθήκη θα πρέπει να τοποθετεί στην ουρά ένα σενάριο μόνο αν χρησιμοποιείται στη σελίδα."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Διαβάστε σχετικά με την [Κρυφή μνήμη προγράμματος περιήγησης στο WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Εξετάστε το ενδεχόμενο να χρησιμοποιήσετε μια [προσθήκη βελτιστοποίησης εικόνων WordPress](https://wordpress.org/plugins/search/optimize+images/) που συμπιέζει τις εικόνες διατηρώντας όμως την ποιότητά τους."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Ανεβάστε εικόνες απευθείας μέσω της [βιβλιοθήκης μέσων](https://codex.wordpress.org/Media_Library_Screen) για να διασφαλίσετε ότι τα απαιτούμενα μεγέθη εικόνων είναι διαθέσιμα. Στη συνέχεια, μπορείτε να τις εισαγάγετε από τη βιβλιοθήκη μέσων ή να χρησιμοποιήσετε το γραφικό στοιχείο εικόνων για να διασφαλίσετε ότι χρησιμοποιούνται τα βέλτιστα μεγέθη (συμπεριλαμβανομένων αυτών για τα αποκριτικά σημεία διακοπής). Αποφύγετε τη χρήση εικόνων `Full Size`, εκτός αν οι διαστάσεις είναι κατάλληλες για τη χρήση τους. [Μάθετε περισσότερα](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Μπορείτε να ενεργοποιήσετε τη συμπίεση κειμένου στη διαμόρφωση του διακομιστή ιστού σας."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Εξετάστε το ενδεχόμενο να χρησιμοποιήσετε μια [προσθήκη](https://wordpress.org/plugins/search/convert+webp/) ή μια υπηρεσία που θα μετατρέπει αυτόματα τις μεταφορτωμένες εικόνες σας στη βέλτιστη μορφή."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-GB.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-GB.json
new file mode 100644
index 00000000000..3e0ec2bfef7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-GB.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` values are not unique"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` values are unique"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn more](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` attributes do not match their roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` attributes match their roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`s do not have all required `[aria-*]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`s have all required `[aria-*]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` are missing some or all of those required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`s are not contained by their required parent element"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`s are contained by their required parent element"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` values are not valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` values are valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Assistive technologies, such as screen readers, can't interpret ARIA attributes with invalid values. [Learn more](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` attributes do not have valid values"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` attributes have valid values"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Assistive technologies, such as screen readers, can't interpret ARIA attributes with invalid names. [Learn more](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` attributes are not valid or misspelled"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` attributes are valid and not misspelled"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Captions make audio elements usable for deaf or hearing-impaired users, providing critical information such as who is talking, what they're saying and other non-speech information. [Learn more](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` elements are missing a `<track>` element with `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` elements contain a `<track>` element with `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Failing elements"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "When a button doesn't have an accessible name, screen readers announce it as 'button', making it unusable for users who rely on screen readers. [Learn more](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Buttons do not have an accessible name"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Buttons have an accessible name"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "The page does not contain a heading, skip link or landmark region"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "The page contains a heading, skip link or landmark region"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Low-contrast text is difficult or impossible for many users to read. [Learn more](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Background and foreground colours do not have a sufficient contrast ratio."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Background and foreground colours have a sufficient contrast ratio"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "When definition lists are not properly marked up, screen readers may produce confusing or inaccurate output. [Learn more](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`'s do not contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Definition list items (`<dt>` and `<dd>`) must be wrapped in a parent `<dl>` element to ensure that screen readers can properly announce them. [Learn more](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Definition list items are not wrapped in `<dl>` elements"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Definition list items are wrapped in `<dl>` elements"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Document doesn't have a `<title>` element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Document has a `<title>` element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "The value of an ID attribute must be unique to prevent other instances from being overlooked by assistive technologies. [Learn more](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]` attributes on the page are not unique"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]` attributes on the page are unique"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Screen reader users rely on frame titles to describe the contents of frames. [Learn more](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` or `<iframe>` elements do not have a title"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` or `<iframe>` elements have a title"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "If a page doesn't specify a lang attribute, a screen reader assumes that the page is in the default language that the user chose when setting up the screen reader. If the page isn't actually in the default language, then the screen reader might not announce the page's text correctly. [Learn more](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` element does not have a `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` element has a `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) helps screen readers announce text properly. [Learn more](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` element does not have a valid value for its `[lang]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` element has a valid value for its `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informative elements should aim for short, descriptive alternative text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Image elements do not have `[alt]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Image elements have `[alt]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "When an image is being used as an `<input>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn more](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` elements do not have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` elements have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Labels ensure that form controls are announced properly by assistive technologies, such as screen readers. [Learn more](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Form elements do not have associated labels"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Form elements have associated labels"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "A table being used for layout purposes should not include data elements, such as the caption elements or the summary attribute, because this can create a confusing experience for screen reader users. [Learn more](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Presentational `<table>` elements do not avoid using `<th>`, `<caption>` or the `[summary]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Presentational `<table>` elements avoid using `<th>`, `<caption>` or the `[summary]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Link text (and alternative text for images, when used as links) that is discernible, unique and focusable improves the navigation experience for screen reader users. [Learn more](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Links do not have a discernible name"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Links have a discernible name"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Screen readers have a specific way of announcing lists. Ensuring proper list structure aids screen reader output. [Learn more](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Lists do not contain only `<li>` elements and script supporting elements (`<script>` and `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Lists contain only `<li>` elements and script supporting elements (`<script>` and `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Screen readers require list items (`<li>`) to be contained within a parent `<ul>` or `<ol>` to be announced properly. [Learn more](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "List items (`<li>`) are not contained within `<ul>` or `<ol>` parent elements."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Users do not expect a page to refresh automatically, and doing so will move focus back to the top of the page. This may create a frustrating or confusing experience. [Learn more](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "The document uses `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "The document does not use `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Disabling zooming is problematic for users with low vision who rely on screen magnification to properly see the contents of a web page. [Learn more](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` is used in the `<meta name=\"viewport\">` element or the `[maximum-scale]` attribute is less than 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` is not used in the `<meta name=\"viewport\">` element and the `[maximum-scale]` attribute is not less than 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Screen readers cannot translate non-text content. Adding alt text to `<object>` elements helps screen readers convey meaning to users. [Learn more](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` elements do not have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` elements have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "A value greater than 0 implies an explicit navigation ordering. Although technically valid, this often creates frustrating experiences for users who rely on assistive technologies. [Learn more](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Some elements have a `[tabindex]` value greater than 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "No element has a `[tabindex]` value greater than 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Screen readers have features to make navigating tables easier. Ensuring `<td>` cells using the `[headers]` attribute only refer to other cells in the same table may improve the experience for screen reader users. [Learn more](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to an element `id` not found within the same table."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Screen readers have features to make navigating tables easier. Ensuring that table headers always refer to some set of cells may improve the experience for screen reader users. [Learn more](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` do not have data cells they describe."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` have data cells they describe."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) on elements helps ensure that text is pronounced correctly by a screen reader. [Learn more](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` attributes do not have a valid value"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` attributes have a valid value"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "When a video provides a caption it is easier for deaf and hearing-impaired users to access its information. [Learn more](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` elements do not contain a `<track>` element with `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` elements contain a `<track>` element with `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audio descriptions provide relevant information for videos that dialogue cannot, such as facial expressions and scenes. [Learn more](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` elements do not contain a `<track>` element with `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` elements contain a `<track>` element with `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "For ideal appearance on iOS when users add a progressive web app to the home screen, define an `apple-touch-icon`. It must point to a non-transparent 192px (or 180px) square PNG. [Learn More](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Does not provide a valid `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` is out of date; `apple-touch-icon` is preferred."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Provides a valid `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome extensions negatively affected this page's load performance. Try auditing the page in incognito mode or from a Chrome profile without extensions."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Script Evaluation"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Script Parse"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Total CPU Time"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduce JavaScript execution time"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript execution time"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Use video formats for animated content"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Consider lazy loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. [Learn more](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Defer off-screen images"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles. [Learn more](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Eliminate render-blocking resources"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Large network payloads cost users real money and are highly correlated with long load times. [Learn more](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Total size was {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Avoid enormous network payloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Avoids enormous network payloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minifying CSS files can reduce network payload sizes. [Learn more](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minify CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minifying JavaScript files can reduce payload sizes and script parse time. [Learn more](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minify JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Remove dead rules from style sheets and defer the loading of CSS not used for above-the-fold content to reduce unnecessary bytes consumed by network activity. [Learn more](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Remove unused CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Remove unused JavaScript to reduce bytes consumed by network activity."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Remove unused JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "A long cache lifetime can speed up repeat visits to your page. [Learn more](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 resource found}other{# resources found}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Serve static assets with an efficient cache policy"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Uses efficient cache policy on static assets"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimised images load faster and consume less mobile data. [Learn more](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Efficiently encode images"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Serve images that are appropriately-sized to save mobile data and improve load time. [Learn more](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Properly size images"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Text-based resources should be served with compression (gzip, deflate or brotli) to minimise total network bytes. [Learn more](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Enable text compression"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Image formats like JPEG 2000, JPEG XR and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Serve images in next-gen formats"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "If the width of your app's content doesn't match the width of the viewport, your app might not be optimised for mobile screens. [Learn more](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "The viewport size of {innerWidth}px does not match the window size of {outerWidth}px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Content is not sized correctly for the viewport"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Content is sized correctly for the viewport"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "The critical request chains below show you what resources are loaded with a high priority. Consider reducing the length of chains, reducing the download size of resources or deferring the download of unnecessary resources to improve page load. [Learn more](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 chain found}other{# chains found}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimise Critical Requests Depth"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Deprecation/Warning"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Line"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Deprecated APIs will eventually be removed from the browser. [Learn more](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 warning found}other{# warnings found}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Uses deprecated APIs"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Avoids deprecated APIs"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application cache is deprecated. [Learn more](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Found '{AppCacheManifest}'"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Uses application cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Avoids application cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Specifying a DOCTYPE prevents the browser from switching to quirks mode. [Learn more](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype name must be the lowercase string `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Document must contain a doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Expected publicId to be an empty string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Expected systemId to be an empty string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Page lacks the HTML doctype, thus triggering quirks mode"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Page has the HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistic"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Value"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Browser engineers recommend pages contain fewer than ~1,500 DOM elements. The sweet spot is a tree depth < 32 elements and fewer than 60 children/parent element. A large DOM can increase memory usage, cause longer [style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}other{# elements}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Avoid an excessive DOM size"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximum DOM Depth"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total DOM Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximum Child Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Avoids an excessive DOM size"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Add `rel=\"noopener\"` or `rel=\"noreferrer\"` to any external links to improve performance and prevent security vulnerabilities. [Learn more](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links to cross-origin destinations are unsafe"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links to cross-origin destinations are safe"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Unable to determine the destination for anchor ({anchorHTML}). If not used as a hyperlink, consider removing target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Users are mistrustful of or confused by sites that request their location without context. Consider tying the request to a user action instead. [Learn more](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Requests the geolocation permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Avoids requesting the geolocation permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "All front-end JavaScript libraries detected on the page. [Learn more](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Detected JavaScript libraries"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "For users on slow connections, external scripts dynamically injected via `document.write()` can delay page load by tens of seconds. [Learn more](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Uses `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Avoids `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Highest Severity"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Library version"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Vulnerability count"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Some third-party scripts may contain known security vulnerabilities that are easily identified and exploited by attackers. [Learn more](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vulnerability detected}other{# vulnerabilities detected}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Includes front-end JavaScript libraries with known security vulnerabilities"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "High"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Low"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Medium"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Avoids front-end JavaScript libraries with known security vulnerabilities"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Users are mistrustful of or confused by sites that request to send notifications without context. Consider tying the request to user gestures instead. [Learn more](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Requests the notification permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Avoids requesting the notification permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Failing Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Preventing password pasting undermines good security policy. [Learn more](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Prevents users to paste into password fields"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Allows users to paste into password fields"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 offers many benefits over HTTP/1.1, including binary headers, multiplexing and server push. [Learn more](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 request not served via HTTP/2}other{# requests not served via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Does not use HTTP/2 for all of its resources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Uses HTTP/2 for its own resources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Consider marking your touch and wheel event listeners as `passive` to improve your page's scroll performance. [Learn more](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Does not use passive listeners to improve scrolling performance"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Uses passive listeners to improve scrolling performance"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Description"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns. [Learn more](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Browser errors were logged to the console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "No browser errors logged to the console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. [Learn more](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Ensure text remains visible during webfont load"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "All text remains visible during webfont loads"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse was unable to automatically check the font-display value for the following URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Aspect ratio (actual)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Aspect ratio (displayed)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Image display dimensions should match natural aspect ratio. [Learn more](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Displays images with incorrect aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Displays images with correct aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Invalid image sizing information {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browsers can proactively prompt users to add your app to their home screen, which can lead to higher engagement. [Learn more](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Web app manifest does not meet the installability requirements"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Web app manifest meets the installability requirements"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Insecure URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "All sites should be protected with HTTPS, even ones that don't handle sensitive data. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 insecure request found}other{# insecure requests found}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Does not use HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Uses HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "A fast page load over a mobile network ensures a good mobile user experience. [Learn more](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactive at {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactive on simulated mobile network at {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Your page loads too slowly and is not interactive within 10 seconds. Look at the opportunities and diagnostics in the 'Performance' section to learn how to improve."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Page load is not fast enough on mobile networks"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Page load is fast enough on mobile networks"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Category"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimise main-thread work"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimises main-thread work"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "To reach the most users, sites should work across every major browser. [Learn more](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Site works cross-browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Ensure individual pages are deep linkable via URL and that URLs are unique for the purpose of shareability on social media. [Learn more](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Each page has a URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Transitions should feel snappy as you tap around, even on a slow network. This experience is key to a user's perception of performance. [Learn more](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Page transitions don't feel like they block on the network"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Estimated input latency is an estimate of how long your app takes to respond to user input, in milliseconds, during the busiest 5s window of page load. If your latency is higher than 50 ms, users may perceive your app as laggy. [Learn more](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Estimated Input Latency"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First contentful paint marks the time at which the first text or image is painted. [Learn more](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "First CPU Idle"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "First meaningful paint measures when the primary content of a page is visible. [Learn more](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Time to interactive is the amount of time it takes for the page to become fully interactive. [Learn more](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Time to Interactive"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "The maximum potential first input delay that your users could experience is the duration, in milliseconds, of the longest task. [Learn more](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max potential first input delay"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Speed Index"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total blocking time"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Network round trip times (RTT) have a large impact on performance. If the RTT to an origin is high, it's an indication that servers closer to the user could improve performance. [Learn more](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Network Return Times"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Server latencies can impact web performance. If the server latency of an origin is high, it's an indication that the server is overloaded or has poor back-end performance. [Learn more](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Server Back-end Latencies"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "A service worker enables your web app to be reliable in unpredictable network conditions. [Learn more](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` does not respond with a 200 when offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responds with a 200 when offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse couldn't read the `start_url` from the manifest. As a result, the `start_url` was assumed to be the document's URL. Error message: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Over budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Keep the quantity and size of network requests under the targets set by the provided performance budget. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 request}other{# requests}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Performance budget"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "If you've already set up HTTPS, make sure that you redirect all HTTP traffic to HTTPS in order to enable secure web features for all your users. [Learn more](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Does not redirect HTTP traffic to HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirects HTTP traffic to HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Redirects introduce additional delays before the page can be loaded. [Learn more](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Avoid multiple page redirects"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "To set budgets for the quantity and size of page resources, add a budget.json file. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 request • {byteCount, number, bytes} KB}other{# requests • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Keep request counts low and transfer sizes small"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Canonical links suggest which URL to show in search results. [Learn more](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Multiple conflicting URLs ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Points to a different domain ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Invalid URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Points to another `hreflang` location ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relative URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Points to the domain's root URL (the home page), instead of an equivalent page of content"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Document does not have a valid `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Document has a valid `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Font sizes less than 12px are too small to be legible and require mobile visitors to 'pinch to zoom' in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} legible text"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text is illegible because there's no viewport meta tag optimised for mobile screens."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} of text is too small (based on {decimalProportionVisited, number, extendedPercent} sample)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Document doesn't use legible font sizes"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Document uses legible font sizes"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Document doesn't have a valid `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Document has a valid `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Page has unsuccessful HTTP status code"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Page has successful HTTP status code"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Page is blocked from indexing"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Page isn’t blocked from indexing"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Descriptive link text helps search engines understand your content. [Learn more](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link found}other{# links found}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Links do not have descriptive text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Links have descriptive text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Structured data is valid"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Meta descriptions may be included in search results to concisely summarise page content. [Learn more](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Description text is empty."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Document does not have a meta description"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Document has a meta description"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Search engines can't index plug-in content, and many devices restrict plug-ins or don't support them. [Learn more](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Document uses plugins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Document avoids plugins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed. [Learn more](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Request for robots.txt returned HTTP status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 error found}other{# errors found}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse was unable to download a robots.txt file"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt is not valid"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt is valid"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interactive elements such as buttons and links should be large enough (48 x 48px) and have enough space around them to be easy enough to tap without overlapping onto other elements. [Learn more](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} appropriately sized tap targets"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Tap targets are too small because there's no viewport meta tag optimised for mobile screens"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Tap targets are not sized appropriately"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Overlapping target"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Tap target"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Tap targets are sized appropriately"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "The service worker is the technology that enables your app to use many progressive web app features, such as offline, add to home screen and push notifications. [Learn more](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "This page is controlled by a service worker, however no `start_url` was found because manifest failed to parse as valid JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "This page is controlled by a service worker, however the `start_url` ({startUrl}) is not in the service worker's scope ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "This page is controlled by a service worker, however no `start_url` was found because no manifest was fetched."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "This origin has one or more service workers, however the page ({pageUrl}) is not in scope."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Does not register a service worker that controls page and `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registers a service worker that controls page and `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "A themed splash screen ensures a high-quality experience when users launch your app from their home screens. [Learn more](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Is not configured for a custom splash screen"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configured for a custom splash screen"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "The browser address bar can be themed to match your site. [Learn more](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Does not set a theme colour for the address bar."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Sets a theme colour for the address bar."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Main-thread blocking time"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Third-party"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Third-party code blocked the main thread for {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduce the impact of third-party code"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Third-party usage"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Time to first byte identifies the time at which your server sends a response. [Learn more](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Root document took {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduce server response times (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Server response times are low (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duration"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Start Time"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences. [Learn more](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 user timing}other{# user timings}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing marks and measures"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "A preconnect <link> was found for '{securityOrigin}' but was not used by the browser. Check that you are using the `crossorigin` attribute properly."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Consider adding `preconnect` or `dns-prefetch` resource hints to establish early connections to important third-party origins. [Learn more](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Pre-connect to required origins"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "A preload <link> was found for '{preloadURL}' but was not used by the browser. Check that you are using the `crossorigin` attribute properly."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Consider using `<link rel=preload>` to prioritise fetching resources that are currently requested later in page load. [Learn more](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Pre-load key requests"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Add a `<meta name=\"viewport\">` tag to optimise your app for mobile screens. [Learn more](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "No `<meta name=\"viewport\">` tag found"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Does not have a `<meta name=\"viewport\">` tag with `width` or `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Has a `<meta name=\"viewport\">` tag with `width` or `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Your app should display some content when JavaScript is disabled, even if it's just a warning to the user that JavaScript is required to use the app. [Learn more](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "The page body should render some content if its scripts are not available."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Does not provide fallback content when JavaScript is not available"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Contains some content when JavaScript is not available"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "If you're building a progressive web app, consider using a service worker so that your app can work offline. [Learn more](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Current page does not respond with a 200 when offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Current page responds with a 200 when offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "The page may not be loading offline because your test URL ({requested}) was redirected to '{final}'. Try testing the second URL directly."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, such as a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio and video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "These items highlight common accessibility best practices."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Best practices"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "These checks highlight opportunities to [improve the accessibility of your web app](https://developers.google.com/web/fundamentals/accessibility). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accessibility"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "These are opportunities to improve the legibility of your content."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "These are opportunities to improve the interpretation of your content by users in different locales."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisation and localisation"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, such as a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Names and labels"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "These are opportunities to improve keyboard navigation in your application."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "These are opportunities to improve the experience of reading tabular or list data using assistive technology, such as a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tables and lists"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Performance budgets set standards for the performance of your site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgets"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "More information about the performance of your application. These numbers don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the performance score."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostics"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "The most critical aspect of performance is how quickly pixels are rendered onscreen. Key metrics: First Contentful Paint, First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "First Paint Improvements"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "These suggestions can help your page load faster. They don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the performance score."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Opportunities"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrics"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Enhance the overall loading experience, so the page is responsive and ready to use as soon as possible. Key metrics: Time to Interactive, Speed Index"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Overall Improvements"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performance"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "These checks validate the aspects of a progressive web app. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "These checks are required by the baseline [PWA checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are not automatically checked by Lighthouse. They do not affect your score but it's important that you verify them manually."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "progressive web app"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Fast and reliable"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Installable"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA Optimised"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "These checks ensure that your page is optimised for search engine results ranking. There are additional factors that Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Run these additional validators on your site to check additional SEO best practices."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Format your HTML in a way that enables crawlers to better understand your app’s content."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Content Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "To appear in search results, crawlers need access to your app."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawling and Indexing"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Make sure that your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobile friendly"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Location"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Name"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Requests"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Resource type"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Size"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Time Spent"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Transfer size"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potential savings"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potential Savings"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potential savings of {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potential savings of {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Image"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Other"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Third-party"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Something went wrong with recording the trace over your page load. Please run Lighthouse again. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Timeout waiting for initial Debugger Protocol connection."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome didn't collect any screenshots during the page load. Please make sure that there is content visible on the page, and then try re-running Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS servers could not resolve the provided domain."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Required {artifactName} gatherer encountered an error: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "An internal Chrome error occurred. Please restart Chrome and try re-running Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Required {artifactName} gatherer did not run."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse was unable to reliably load the page that you requested. Make sure that you are testing the correct URL and that the server is properly responding to all requests."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse was unable to reliably load the URL that you requested because the page stopped responding."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "The URL you have provided does not have a valid security certificate. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome prevented page load with an interstitial. Make sure that you are testing the correct URL and that the server is properly responding to all requests."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse was unable to reliably load the page that you requested. Make sure that you are testing the correct URL and that the server is properly responding to all requests. (Details: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse was unable to reliably load the page that you requested. Make sure that you are testing the correct URL and that the server is properly responding to all requests. (Status code: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Waiting for DevTools protocol response has exceeded the allotted time. (Method: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Fetching resource content has exceeded the allotted time"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "The URL that you have provided appears to be invalid."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Show audits"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Initial Navigation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximum critical path latency:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Report error: no audit information"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Lab Data"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Additional items to manually check"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Not applicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Opportunity"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estimated Savings"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Passed audits"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Collapse snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Expand snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Show 3rd-party resources"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "There were issues affecting this run of Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Passed audits but with warnings"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Warnings: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Consider uploading your GIF to a service which will make it available to embed as an HTML5 video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Install a [lazy load WordPress plug-in](https://wordpress.org/plugins/search/lazy+load/) that provides the ability to defer any offscreen images, or switch to a theme that provides that functionality. Also consider using [the AMP plug-in](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "There are a number of WordPress plug-ins that can help you [inline critical assets](https://wordpress.org/plugins/search/critical+css/) or [defer less important resources](https://wordpress.org/plugins/search/defer+css+javascript/). Beware that optimisations provided by these plug-ins may break features of your theme or plug-ins, so you will likely need to make code changes."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Themes, plug-ins and server specifications all contribute to server response time. Consider finding a more optimised theme, carefully selecting an optimisation plug-in, and/or upgrading your server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Consider showing excerpts in your post lists (e.g. via the more tag), reducing the number of posts shown on a given page, breaking your long posts into multiple pages, or using a plug-in to lazy-load comments."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "A number of [WordPress plug-ins](https://wordpress.org/plugins/search/minify+css/) can speed up your site by concatenating, minifying and compressing your styles. You may also want to use a build process to do this minification up-front if possible."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "A number of [WordPress plug-ins](https://wordpress.org/plugins/search/minify+javascript/) can speed up your site by concatenating, minifying and compressing your scripts. You may also want to use a build process to do this minification up front if possible."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Consider reducing, or switching, the number of [WordPress plug-ins](https://wordpress.org/plugins/) loading unused CSS in your page. To identify plug-ins that are adding extraneous CSS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plug-in responsible from the URL of the stylesheet. Look out for plug-ins that have many stylesheets in the list which have a lot of red in code coverage. A plug-in should only enqueue a stylesheet if it is actually used on the page."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Consider reducing, or switching, the number of [WordPress plug-ins](https://wordpress.org/plugins/) loading unused JavaScript in your page. To identify plug-ins that are adding extraneous JS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plug-in responsible from the URL of the script. Look out for plug-ins that have many scripts in the list which have a lot of red in code coverage. A plug-in should only enqueue a script if it is actually used on the page."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Read about [browser caching in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Consider using an [image optimisation WordPress plug-in](https://wordpress.org/plugins/search/optimize+images/) that compresses your images while retaining quality."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Upload images directly through the [media library](https://codex.wordpress.org/Media_Library_Screen) to ensure that the required image sizes are available, and then insert them from the media library or use the image widget to ensure that the optimal image sizes are used (including those for the responsive breakpoints). Avoid using `Full Size` images unless the dimensions are adequate for their usage. [Learn more](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "You can enable text compression in your web server configuration."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Consider using a [plug-in](https://wordpress.org/plugins/search/convert+webp/) or service that will automatically convert your uploaded images to the optimal formats."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-US.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-US.json
new file mode 100644
index 00000000000..41c76964da0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-US.json
@@ -0,0 +1,1634 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Access keys let users quickly focus a part of the page. For proper navigation, each access key must be unique. [Learn more](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` values are not unique"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` values are unique"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Each ARIA `role` supports a specific subset of `aria-*` attributes. Mismatching these invalidates the `aria-*` attributes. [Learn more](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` attributes do not match their roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` attributes match their roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Some ARIA roles have required attributes that describe the state of the element to screen readers. [Learn more](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`s do not have all required `[aria-*]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`s have all required `[aria-*]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Some ARIA parent roles must contain specific child roles to perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` are missing some or all of those required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Some ARIA child roles must be contained by specific parent roles to properly perform their intended accessibility functions. [Learn more](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`s are not contained by their required parent element"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`s are contained by their required parent element"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA roles must have valid values in order to perform their intended accessibility functions. [Learn more](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` values are not valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` values are valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid values. [Learn more](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` attributes do not have valid values"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` attributes have valid values"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Assistive technologies, like screen readers, can't interpret ARIA attributes with invalid names. [Learn more](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` attributes are not valid or misspelled"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` attributes are valid and not misspelled"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Captions make audio elements usable for deaf or hearing-impaired users, providing critical information such as who is talking, what they're saying, and other non-speech information. [Learn more](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` elements are missing a `<track>` element with `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` elements contain a `<track>` element with `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Failing Elements"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "When a button doesn't have an accessible name, screen readers announce it as \"button\", making it unusable for users who rely on screen readers. [Learn more](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Buttons do not have an accessible name"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Buttons have an accessible name"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Adding ways to bypass repetitive content lets keyboard users navigate the page more efficiently. [Learn more](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "The page does not contain a heading, skip link, or landmark region"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "The page contains a heading, skip link, or landmark region"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Low-contrast text is difficult or impossible for many users to read. [Learn more](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Background and foreground colors do not have a sufficient contrast ratio."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Background and foreground colors have a sufficient contrast ratio"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "When definition lists are not properly marked up, screen readers may produce confusing or inaccurate output. [Learn more](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`'s do not contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` or `<template>` elements."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Definition list items (`<dt>` and `<dd>`) must be wrapped in a parent `<dl>` element to ensure that screen readers can properly announce them. [Learn more](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Definition list items are not wrapped in `<dl>` elements"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Definition list items are wrapped in `<dl>` elements"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "The title gives screen reader users an overview of the page, and search engine users rely on it heavily to determine if a page is relevant to their search. [Learn more](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Document doesn't have a `<title>` element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Document has a `<title>` element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "The value of an id attribute must be unique to prevent other instances from being overlooked by assistive technologies. [Learn more](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]` attributes on the page are not unique"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]` attributes on the page are unique"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Screen reader users rely on frame titles to describe the contents of frames. [Learn more](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` or `<iframe>` elements do not have a title"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` or `<iframe>` elements have a title"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "If a page doesn't specify a lang attribute, a screen reader assumes that the page is in the default language that the user chose when setting up the screen reader. If the page isn't actually in the default language, then the screen reader might not announce the page's text correctly. [Learn more](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` element does not have a `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` element has a `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) helps screen readers announce text properly. [Learn more](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` element does not have a valid value for its `[lang]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` element has a valid value for its `[lang]` attribute"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Image elements do not have `[alt]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Image elements have `[alt]` attributes"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "When an image is being used as an `<input>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn more](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` elements do not have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` elements have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Labels ensure that form controls are announced properly by assistive technologies, like screen readers. [Learn more](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Form elements do not have associated labels"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Form elements have associated labels"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "A table being used for layout purposes should not include data elements, such as the th or caption elements or the summary attribute, because this can create a confusing experience for screen reader users. [Learn more](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Presentational `<table>` elements do not avoid using `<th>`, `<caption>` or the `[summary]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Presentational `<table>` elements avoid using `<th>`, `<caption>` or the `[summary]` attribute."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Link text (and alternate text for images, when used as links) that is discernible, unique, and focusable improves the navigation experience for screen reader users. [Learn more](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Links do not have a discernible name"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Links have a discernible name"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Screen readers have a specific way of announcing lists. Ensuring proper list structure aids screen reader output. [Learn more](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Lists do not contain only `<li>` elements and script supporting elements (`<script>` and `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Lists contain only `<li>` elements and script supporting elements (`<script>` and `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Screen readers require list items (`<li>`) to be contained within a parent `<ul>` or `<ol>` to be announced properly. [Learn more](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "List items (`<li>`) are not contained within `<ul>` or `<ol>` parent elements."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Users do not expect a page to refresh automatically, and doing so will move focus back to the top of the page. This may create a frustrating or confusing experience. [Learn more](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "The document uses `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "The document does not use `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Disabling zooming is problematic for users with low vision who rely on screen magnification to properly see the contents of a web page. [Learn more](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` is used in the `<meta name=\"viewport\">` element or the `[maximum-scale]` attribute is less than 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` is not used in the `<meta name=\"viewport\">` element and the `[maximum-scale]` attribute is not less than 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Screen readers cannot translate non-text content. Adding alt text to `<object>` elements helps screen readers convey meaning to users. [Learn more](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` elements do not have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` elements have `[alt]` text"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "A value greater than 0 implies an explicit navigation ordering. Although technically valid, this often creates frustrating experiences for users who rely on assistive technologies. [Learn more](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Some elements have a `[tabindex]` value greater than 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "No element has a `[tabindex]` value greater than 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Screen readers have features to make navigating tables easier. Ensuring `<td>` cells using the `[headers]` attribute only refer to other cells in the same table may improve the experience for screen reader users. [Learn more](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to an element `id` not found within the same table."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Screen readers have features to make navigating tables easier. Ensuring table headers always refer to some set of cells may improve the experience for screen reader users. [Learn more](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` do not have data cells they describe."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` elements and elements with `[role=\"columnheader\"/\"rowheader\"]` have data cells they describe."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) on elements helps ensure that text is pronounced correctly by a screen reader. [Learn more](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` attributes do not have a valid value"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` attributes have a valid value"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "When a video provides a caption it is easier for deaf and hearing impaired users to access its information. [Learn more](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` elements do not contain a `<track>` element with `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` elements contain a `<track>` element with `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audio descriptions provide relevant information for videos that dialogue cannot, such as facial expressions and scenes. [Learn more](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` elements do not contain a `<track>` element with `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` elements contain a `<track>` element with `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "For ideal appearance on iOS when users add a progressive web app to the home screen, define an `apple-touch-icon`. It must point to a non-transparent 192px (or 180px) square PNG. [Learn More](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Does not provide a valid `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` is out of date; `apple-touch-icon` is preferred."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Provides a valid `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome extensions negatively affected this page's load performance. Try auditing the page in incognito mode or from a Chrome profile without extensions."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Script Evaluation"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Script Parse"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Total CPU Time"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduce JavaScript execution time"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript execution time"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Large GIFs are inefficient for delivering animated content. Consider using MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save network bytes. [Learn more](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Use video formats for animated content"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. [Learn more](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Defer offscreen images"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles. [Learn more](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Eliminate render-blocking resources"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Large network payloads cost users real money and are highly correlated with long load times. [Learn more](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Total size was {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Avoid enormous network payloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Avoids enormous network payloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minifying CSS files can reduce network payload sizes. [Learn more](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minify CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minifying JavaScript files can reduce payload sizes and script parse time. [Learn more](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minify JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Remove dead rules from stylesheets and defer the loading of CSS not used for above-the-fold content to reduce unnecessary bytes consumed by network activity. [Learn more](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Remove unused CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Remove unused JavaScript to reduce bytes consumed by network activity."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Remove unused JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "A long cache lifetime can speed up repeat visits to your page. [Learn more](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 resource found}\n other {# resources found}\n }"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Serve static assets with an efficient cache policy"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Uses efficient cache policy on static assets"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimized images load faster and consume less cellular data. [Learn more](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Efficiently encode images"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Serve images that are appropriately-sized to save cellular data and improve load time. [Learn more](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Properly size images"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Text-based resources should be served with compression (gzip, deflate or brotli) to minimize total network bytes. [Learn more](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Enable text compression"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. [Learn more](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Serve images in next-gen formats"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "If the width of your app's content doesn't match the width of the viewport, your app might not be optimized for mobile screens. [Learn more](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "The viewport size of {innerWidth}px does not match the window size of {outerWidth}px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Content is not sized correctly for the viewport"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Content is sized correctly for the viewport"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "The Critical Request Chains below show you what resources are loaded with a high priority. Consider reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load. [Learn more](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 chain found}\n other {# chains found}\n }"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Avoid chaining critical requests"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Deprecation / Warning"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Line"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Deprecated APIs will eventually be removed from the browser. [Learn more](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 warning found}\n other {# warnings found}\n }"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Uses deprecated APIs"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Avoids deprecated APIs"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache is deprecated. [Learn more](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Found \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Uses Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Avoids Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Specifying a doctype prevents the browser from switching to quirks-mode. [Learn more](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype name must be the lowercase string `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Document must contain a doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Expected publicId to be an empty string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Expected systemId to be an empty string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Page lacks the HTML doctype, thus triggering quirks-mode"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Page has the HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistic"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Value"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "A large DOM will increase memory usage, cause longer [style calculations](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), and produce costly [layout reflows](https://developers.google.com/speed/articles/reflow). [Learn more](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 element}\n other {# elements}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Avoid an excessive DOM size"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximum DOM Depth"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total DOM Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximum Child Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Avoids an excessive DOM size"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Add `rel=\"noopener\"` or `rel=\"noreferrer\"` to any external links to improve performance and prevent security vulnerabilities. [Learn more](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links to cross-origin destinations are unsafe"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links to cross-origin destinations are safe"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Unable to determine the destination for anchor ({anchorHTML}). If not used as a hyperlink, consider removing target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Users are mistrustful of or confused by sites that request their location without context. Consider tying the request to a user action instead. [Learn more](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Requests the geolocation permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Avoids requesting the geolocation permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "All front-end JavaScript libraries detected on the page. [Learn more](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Detected JavaScript libraries"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "For users on slow connections, external scripts dynamically injected via `document.write()` can delay page load by tens of seconds. [Learn more](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Uses `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Avoids `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Highest Severity"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Library Version"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Vulnerability Count"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Some third-party scripts may contain known security vulnerabilities that are easily identified and exploited by attackers. [Learn more](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 vulnerability detected}\n other {# vulnerabilities detected}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Includes front-end JavaScript libraries with known security vulnerabilities"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "High"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Low"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Medium"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Avoids front-end JavaScript libraries with known security vulnerabilities"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Users are mistrustful of or confused by sites that request to send notifications without context. Consider tying the request to user gestures instead. [Learn more](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Requests the notification permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Avoids requesting the notification permission on page load"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Failing Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Preventing password pasting undermines good security policy. [Learn more](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Prevents users to paste into password fields"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Allows users to paste into password fields"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 offers many benefits over HTTP/1.1, including binary headers, multiplexing, and server push. [Learn more](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 request not served via HTTP/2}\n other {# requests not served via HTTP/2}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Does not use HTTP/2 for all of its resources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Uses HTTP/2 for its own resources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Consider marking your touch and wheel event listeners as `passive` to improve your page's scroll performance. [Learn more](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Does not use passive listeners to improve scrolling performance"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Uses passive listeners to improve scrolling performance"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Description"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Errors logged to the console indicate unresolved problems. They can come from network request failures and other browser concerns. [Learn more](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Browser errors were logged to the console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "No browser errors logged to the console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Leverage the font-display CSS feature to ensure text is user-visible while webfonts are loading. [Learn more](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Ensure text remains visible during webfont load"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "All text remains visible during webfont loads"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse was unable to automatically check the font-display value for the following URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Aspect Ratio (Actual)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Aspect Ratio (Displayed)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Image display dimensions should match natural aspect ratio. [Learn more](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Displays images with incorrect aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Displays images with correct aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Invalid image sizing information {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browsers can proactively prompt users to add your app to their homescreen, which can lead to higher engagement. [Learn more](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Web app manifest does not meet the installability requirements"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Web app manifest meets the installability requirements"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Insecure URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "All sites should be protected with HTTPS, even ones that don't handle sensitive data. HTTPS prevents intruders from tampering with or passively listening in on the communications between your app and your users, and is a prerequisite for HTTP/2 and many new web platform APIs. [Learn more](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 insecure request found}\n other {# insecure requests found}\n }"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Does not use HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Uses HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactive at {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactive on simulated mobile network at {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Your page loads too slowly and is not interactive within 10 seconds. Look at the opportunities and diagnostics in the \"Performance\" section to learn how to improve."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Page load is not fast enough on mobile networks"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Page load is fast enough on mobile networks"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Category"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimize main-thread work"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimizes main-thread work"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "To reach the most number of users, sites should work across every major browser. [Learn more](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Site works cross-browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Ensure individual pages are deep linkable via URL and that URLs are unique for the purpose of shareability on social media. [Learn more](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Each page has a URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Transitions should feel snappy as you tap around, even on a slow network. This experience is key to a user's perception of performance. [Learn more](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Page transitions don't feel like they block on the network"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Estimated Input Latency is an estimate of how long your app takes to respond to user input, in milliseconds, during the busiest 5s window of page load. If your latency is higher than 50 ms, users may perceive your app as laggy. [Learn more](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Estimated Input Latency"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First Contentful Paint marks the time at which the first text or image is painted. [Learn more](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "First CPU Idle"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "First Meaningful Paint measures when the primary content of a page is visible. [Learn more](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Time to interactive is the amount of time it takes for the page to become fully interactive. [Learn more](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Time to Interactive"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "The maximum potential First Input Delay that your users could experience is the duration, in milliseconds, of the longest task. [Learn more](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max Potential First Input Delay"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Speed Index shows how quickly the contents of a page are visibly populated. [Learn more](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Speed Index"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total Blocking Time"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Network round trip times (RTT) have a large impact on performance. If the RTT to an origin is high, it's an indication that servers closer to the user could improve performance. [Learn more](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Network Round Trip Times"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Server latencies can impact web performance. If the server latency of an origin is high, it's an indication the server is overloaded or has poor backend performance. [Learn more](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Server Backend Latencies"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "A service worker enables your web app to be reliable in unpredictable network conditions. [Learn more](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` does not respond with a 200 when offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responds with a 200 when offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse couldn't read the `start_url` from the manifest. As a result, the `start_url` was assumed to be the document's URL. Error message: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Over Budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Keep the quantity and size of network requests under the targets set by the provided performance budget. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count, plural,\n =1 {1 request}\n other {# requests}\n }"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Performance budget"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "If you've already set up HTTPS, make sure that you redirect all HTTP traffic to HTTPS in order to enable secure web features for all your users. [Learn more](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Does not redirect HTTP traffic to HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirects HTTP traffic to HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Redirects introduce additional delays before the page can be loaded. [Learn more](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Avoid multiple page redirects"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "To set budgets for the quantity and size of page resources, add a budget.json file. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount, plural, =1 {1 request • {byteCount, number, bytes} KB} other {# requests • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Keep request counts low and transfer sizes small"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Canonical links suggest which URL to show in search results. [Learn more](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Multiple conflicting URLs ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Points to a different domain ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Invalid URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Points to another `hreflang` location ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relative URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Points to the domain's root URL (the homepage), instead of an equivalent page of content"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Document does not have a valid `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Document has a valid `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Font sizes less than 12px are too small to be legible and require mobile visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. [Learn more](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} legible text"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text is illegible because there's no viewport meta tag optimized for mobile screens."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} of text is too small (based on {decimalProportionVisited, number, extendedPercent} sample)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Document doesn't use legible font sizes"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Document uses legible font sizes"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Document doesn't have a valid `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Document has a valid `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Pages with unsuccessful HTTP status codes may not be indexed properly. [Learn more](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Page has unsuccessful HTTP status code"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Page has successful HTTP status code"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Search engines are unable to include your pages in search results if they don't have permission to crawl them. [Learn more](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Page is blocked from indexing"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Page isn’t blocked from indexing"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Descriptive link text helps search engines understand your content. [Learn more](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 link found}\n other {# links found}\n }"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Links do not have descriptive text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Links have descriptive text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Structured data is valid"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Meta descriptions may be included in search results to concisely summarize page content. [Learn more](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Description text is empty."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Document does not have a meta description"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Document has a meta description"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Search engines can't index plugin content, and many devices restrict plugins or don't support them. [Learn more](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Document uses plugins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Document avoids plugins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "If your robots.txt file is malformed, crawlers may not be able to understand how you want your website to be crawled or indexed. [Learn more](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Request for robots.txt returned HTTP status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount, plural,\n =1 {1 error found}\n other {# errors found}\n }"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse was unable to download a robots.txt file"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt is not valid"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt is valid"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interactive elements like buttons and links should be large enough (48x48px), and have enough space around them, to be easy enough to tap without overlapping onto other elements. [Learn more](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} appropriately sized tap targets"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Tap targets are too small because there's no viewport meta tag optimized for mobile screens"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Tap targets are not sized appropriately"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Overlapping Target"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Tap Target"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Tap targets are sized appropriately"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "The service worker is the technology that enables your app to use many Progressive Web App features, such as offline, add to homescreen, and push notifications. [Learn more](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "This page is controlled by a service worker, however no `start_url` was found because manifest failed to parse as valid JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "This page is controlled by a service worker, however the `start_url` ({startUrl}) is not in the service worker's scope ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "This page is controlled by a service worker, however no `start_url` was found because no manifest was fetched."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "This origin has one or more service workers, however the page ({pageUrl}) is not in scope."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Does not register a service worker that controls page and `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registers a service worker that controls page and `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "A themed splash screen ensures a high-quality experience when users launch your app from their homescreens. [Learn more](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Is not configured for a custom splash screen"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configured for a custom splash screen"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "The browser address bar can be themed to match your site. [Learn more](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Does not set a theme color for the address bar."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Sets a theme color for the address bar."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Main-Thread Blocking Time"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Third-Party"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Third-party code blocked the main thread for {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduce the impact of third-party code"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Minimize third-party usage"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Time To First Byte identifies the time at which your server sends a response. [Learn more](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Root document took {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduce server response times (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Server response times are low (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duration"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Start Time"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Consider instrumenting your app with the User Timing API to measure your app's real-world performance during key user experiences. [Learn more](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 user timing}\n other {# user timings}\n }"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing marks and measures"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "A preconnect <link> was found for \"{securityOrigin}\" but was not used by the browser. Check that you are using the `crossorigin` attribute properly."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Consider adding `preconnect` or `dns-prefetch` resource hints to establish early connections to important third-party origins. [Learn more](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Preconnect to required origins"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "A preload <link> was found for \"{preloadURL}\" but was not used by the browser. Check that you are using the `crossorigin` attribute properly."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Consider using `<link rel=preload>` to prioritize fetching resources that are currently requested later in page load. [Learn more](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Preload key requests"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Add a `<meta name=\"viewport\">` tag to optimize your app for mobile screens. [Learn more](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "No `<meta name=\"viewport\">` tag found"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Does not have a `<meta name=\"viewport\">` tag with `width` or `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Has a `<meta name=\"viewport\">` tag with `width` or `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Your app should display some content when JavaScript is disabled, even if it's just a warning to the user that JavaScript is required to use the app. [Learn more](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "The page body should render some content if its scripts are not available."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Does not provide fallback content when JavaScript is not available"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Contains some content when JavaScript is not available"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "If you're building a Progressive Web App, consider using a service worker so that your app can work offline. [Learn more](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Current page does not respond with a 200 when offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Current page responds with a 200 when offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "The page may not be loading offline because your test URL ({requested}) was redirected to \"{final}\". Try testing the second URL directly."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "These are opportunities to improve the usage of ARIA in your application which may enhance the experience for users of assistive technology, like a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "These are opportunities to provide alternative content for audio and video. This may improve the experience for users with hearing or vision impairments."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio and video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "These items highlight common accessibility best practices."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Best practices"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "These checks highlight opportunities to [improve the accessibility of your web app](https://developers.google.com/web/fundamentals/accessibility). Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "These items address areas which an automated testing tool cannot cover. Learn more in our guide on [conducting an accessibility review](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accessibility"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "These are opportunities to improve the legibility of your content."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "These are opportunities to improve the interpretation of your content by users in different locales."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalization and localization"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "These are opportunities to improve the semantics of the controls in your application. This may enhance the experience for users of assistive technology, like a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Names and labels"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "These are opportunities to improve keyboard navigation in your application."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "These are opportunities to to improve the experience of reading tabular or list data using assistive technology, like a screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tables and lists"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Performance budgets set standards for the performance of your site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgets"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "More information about the performance of your application. These numbers don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostics"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "The most critical aspect of performance is how quickly pixels are rendered onscreen. Key metrics: First Contentful Paint, First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "First Paint Improvements"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "These suggestions can help your page load faster. They don't [directly affect](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) the Performance score."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Opportunities"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrics"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Enhance the overall loading experience, so the page is responsive and ready to use as soon as possible. Key metrics: Time to Interactive, Speed Index"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Overall Improvements"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performance"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "These checks validate the aspects of a Progressive Web App. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "These checks are required by the baseline [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are not automatically checked by Lighthouse. They do not affect your score but it's important that you verify them manually."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Fast and reliable"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Installable"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA Optimized"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "These checks ensure that your page is optimized for search engine results ranking. There are additional factors Lighthouse does not check that may affect your search ranking. [Learn more](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Run these additional validators on your site to check additional SEO best practices."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Format your HTML in a way that enables crawlers to better understand your app’s content."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Content Best Practices"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "To appear in search results, crawlers need access to your app."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawling and Indexing"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Make sure your pages are mobile friendly so users don’t have to pinch or zoom in order to read the content pages. [Learn more](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobile Friendly"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Location"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Name"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Requests"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Resource Type"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Size"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Time Spent"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Transfer Size"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potential Savings"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potential Savings"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potential savings of {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potential savings of {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Image"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Other"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Third-party"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Something went wrong with recording the trace over your page load. Please run Lighthouse again. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Timeout waiting for initial Debugger Protocol connection."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS servers could not resolve the provided domain."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Required {artifactName} gatherer encountered an error: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "An internal Chrome error occurred. Please restart Chrome and try re-running Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Required {artifactName} gatherer did not run."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse was unable to reliably load the URL you requested because the page stopped responding."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "The URL you have provided does not have a valid security certificate. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome prevented page load with an interstitial. Make sure you are testing the correct URL and that the server is properly responding to all requests."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Details: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse was unable to reliably load the page you requested. Make sure you are testing the correct URL and that the server is properly responding to all requests. (Status code: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Waiting for DevTools protocol response has exceeded the allotted time. (Method: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Fetching resource content has exceeded the allotted time"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "The URL you have provided appears to be invalid."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Show audits"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Initial Navigation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximum critical path latency:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Report error: no audit information"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Lab Data"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Additional items to manually check"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Not applicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Opportunity"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estimated Savings"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Passed audits"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Collapse snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Expand snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Show 3rd-party resources"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "There were issues affecting this run of Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Values are estimated and may vary. The performance score is [based only on these metrics](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Passed audits but with warnings"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Warnings: "
+ },
+ "stack-packs/packs/amp.js | efficient_animated_content": {
+ "message": "For animated content, use [amp-anim](https://amp.dev/documentation/components/amp-anim/) to minimize CPU usage while the content remains offscreen."
+ },
+ "stack-packs/packs/amp.js | offscreen_images": {
+ "message": "Ensure that you are you using valid `amp-img` tags for your images which automatically lazy-load outside the first viewport. [Learn more](https://amp.dev/documentation/guides-and-tutorials/develop/media_iframes_3p/?format=websites#images)."
+ },
+ "stack-packs/packs/amp.js | render_blocking_resources": {
+ "message": "Use tools such as [AMP Optimizer](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer) to [server-side render AMP layouts](https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/server-side-rendering/)."
+ },
+ "stack-packs/packs/amp.js | unminified_css": {
+ "message": "Refer to the [AMP documentation](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/style_pages/) to ensure all your styles are supported."
+ },
+ "stack-packs/packs/amp.js | uses_responsive_images": {
+ "message": "The `amp-img` element supports the `srcset` attribute to specify which image assets to use based on the screen size. [Learn more](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/)."
+ },
+ "stack-packs/packs/amp.js | uses_webp_images": {
+ "message": "Consider displaying all your `amp-img` components in WebP formats while specifying an appropriate fallback for other browsers. [Learn more](https://amp.dev/documentation/components/amp-img/#example:-specifying-a-fallback-image)."
+ },
+ "stack-packs/packs/angular.js | dom_size": {
+ "message": "Consider virtual scrolling with the Component Dev Kit (CDK) if very large lists are being rendered. [Learn more](https://web.dev/virtualize-lists-with-angular-cdk/)."
+ },
+ "stack-packs/packs/angular.js | total_byte_weight": {
+ "message": "Apply [route-level code-splitting](https://web.dev/route-level-code-splitting-in-angular/) to minimize the size of your JavaScript bundles. Also, consider precaching assets with the [Angular service worker](https://web.dev/precaching-with-the-angular-service-worker/)."
+ },
+ "stack-packs/packs/angular.js | unminified_warning": {
+ "message": "If you are using Angular CLI, ensure that builds are generated in production mode. [Learn more](https://angular.io/guide/deployment#enable-runtime-production-mode)."
+ },
+ "stack-packs/packs/angular.js | unused_javascript": {
+ "message": "If you are using Angular CLI, include source maps into your production build to inspect your bundles. [Learn more](https://angular.io/guide/deployment#inspect-the-bundles)."
+ },
+ "stack-packs/packs/angular.js | uses_rel_preload": {
+ "message": "Preload routes ahead of time to speed up navigation. [Learn more](https://web.dev/route-preloading-in-angular/)."
+ },
+ "stack-packs/packs/angular.js | uses_responsive_images": {
+ "message": "Consider using the `BreakpointObserver` utility in the Component Dev Kit (CDK) to manage image breakpoints. [Learn more](https://material.angular.io/cdk/layout/overview)."
+ },
+ "stack-packs/packs/magento.js | critical_request_chains": {
+ "message": "If you are not bundling your JavaScript assets, consider using [baler](https://github.com/magento/baler)."
+ },
+ "stack-packs/packs/magento.js | disable_bundling": {
+ "message": "Disable Magento's built-in [JavaScript bundling and minification](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html), and consider using [baler](https://github.com/magento/baler/) instead."
+ },
+ "stack-packs/packs/magento.js | font_display": {
+ "message": "Specify `@font-display` when [defining custom fonts](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/using-fonts.html)."
+ },
+ "stack-packs/packs/magento.js | offscreen_images": {
+ "message": "Consider modifying your product and catalog templates to make use of the web platform's [lazy loading](https://web.dev/native-lazy-loading) feature."
+ },
+ "stack-packs/packs/magento.js | time_to_first_byte": {
+ "message": "Use Magento's [Varnish integration](https://devdocs.magento.com/guides/v2.3/config-guide/varnish/config-varnish.html)."
+ },
+ "stack-packs/packs/magento.js | unminified_css": {
+ "message": "Enable the \"Minify CSS Files\" option in your store's Developer settings. [Learn more](https://devdocs.magento.com/guides/v2.3/performance-best-practices/configuration.html?itm_source=devdocs&itm_medium=search_page&itm_campaign=federated_search&itm_term=minify%20css%20files)."
+ },
+ "stack-packs/packs/magento.js | unminified_javascript": {
+ "message": "Use [Terser](https://www.npmjs.com/package/terser) to minify all JavaScript assets outfrom from static content deployment, and disable the built-in minification feature."
+ },
+ "stack-packs/packs/magento.js | unused_javascript": {
+ "message": "Disable Magento's built-in [JavaScript bundling](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html)."
+ },
+ "stack-packs/packs/magento.js | uses_optimized_images": {
+ "message": "Consider searching the [Magento Marketplace](https://marketplace.magento.com/catalogsearch/result/?q=optimize%20image) for a variety of third party extensions to optimize images."
+ },
+ "stack-packs/packs/magento.js | uses_rel_preconnect": {
+ "message": "Preconnect or dns-prefetch resource hints can be added by [modifying a themes's layout](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html)."
+ },
+ "stack-packs/packs/magento.js | uses_rel_preload": {
+ "message": "`<link rel=preload>` tags can be added by [modifying a themes's layout](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html)."
+ },
+ "stack-packs/packs/magento.js | uses_webp_images": {
+ "message": "Consider searching the [Magento Marketplace](https://marketplace.magento.com/catalogsearch/result/?q=webp) for a variety of third-party extensions to leverage newer image formats."
+ },
+ "stack-packs/packs/react.js | dom_size": {
+ "message": "Consider using a “windowing” library like `react-window` to minimize the number of DOM nodes created if you are rendering many repeated elements on the page. [Learn more](https://web.dev/virtualize-long-lists-react-window/). Also, minimize unecessary re-renders using [shouldComponentUpdate](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [PureComponent](https://reactjs.org/docs/react-api.html#reactpurecomponent), or [React.memo](https://reactjs.org/docs/react-api.html#reactmemo) and [skip effects](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) only until certain dependencies have changed if you are using the Effect hook to improve runtime performance."
+ },
+ "stack-packs/packs/react.js | redirects": {
+ "message": "If you are using React Router, minimize usage of the `<Redirect>` component for [route navigations](https://reacttraining.com/react-router/web/api/Redirect)."
+ },
+ "stack-packs/packs/react.js | time_to_first_byte": {
+ "message": "If you are server-side rendering any React components, consider using `renderToNodeStream()` or `renderToStaticNodeStream()` to allow the client to receive and hydrate different parts of the markup instead of all at once. [Learn more](https://reactjs.org/docs/react-dom-server.html#rendertonodestream)."
+ },
+ "stack-packs/packs/react.js | unminified_css": {
+ "message": "If your build system minifies your CSS files automatically, ensure that you are deploying the production build of your application. You can check this with the React Developer Tools extension. [Learn more](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build)."
+ },
+ "stack-packs/packs/react.js | unminified_javascript": {
+ "message": "If your build system minifies your JS files automatically, ensure that you are deploying the production build of your application. You can check this with the React Developer Tools extension. [Learn more](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build)."
+ },
+ "stack-packs/packs/react.js | unused_javascript": {
+ "message": "If you are not server-side rendering, [split your JavaScript bundles](https://web.dev/code-splitting-suspense/) with `React.lazy()`. Otherwise, code-split using a third-party library such as [loadable-components](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/)."
+ },
+ "stack-packs/packs/react.js | user_timings": {
+ "message": "Use the React DevTools Profiler, which makes use of the Profiler API, to measure the rendering performance of your components. [Learn more.](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)"
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Consider uploading your GIF to a service which will make it available to embed as an HTML5 video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Install a [lazy-load WordPress plugin](https://wordpress.org/plugins/search/lazy+load/) that provides the ability to defer any offscreen images, or switch to a theme that provides that functionality. Also consider using [the AMP plugin](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "There are a number of WordPress plugins that can help you [inline critical assets](https://wordpress.org/plugins/search/critical+css/) or [defer less important resources](https://wordpress.org/plugins/search/defer+css+javascript/). Beware that optimizations provided by these plugins may break features of your theme or plugins, so you will likely need to make code changes."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Themes, plugins, and server specifications all contribute to server response time. Consider finding a more optimized theme, carefully selecting an optimization plugin, and/or upgrading your server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Consider showing excerpts in your post lists (e.g. via the more tag), reducing the number of posts shown on a given page, breaking your long posts into multiple pages, or using a plugin to lazy-load comments."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "A number of [WordPress plugins](https://wordpress.org/plugins/search/minify+css/) can speed up your site by concatenating, minifying, and compressing your styles. You may also want to use a build process to do this minification up-front if possible."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "A number of [WordPress plugins](https://wordpress.org/plugins/search/minify+javascript/) can speed up your site by concatenating, minifying, and compressing your scripts. You may also want to use a build process to do this minification up front if possible."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Consider reducing, or switching, the number of [WordPress plugins](https://wordpress.org/plugins/) loading unused CSS in your page. To identify plugins that are adding extraneous CSS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plugin responsible from the URL of the stylesheet. Look out for plugins that have many stylesheets in the list which have a lot of red in code coverage. A plugin should only enqueue a stylesheet if it is actually used on the page."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Consider reducing, or switching, the number of [WordPress plugins](https://wordpress.org/plugins/) loading unused JavaScript in your page. To identify plugins that are adding extraneous JS, try running [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. You can identify the theme/plugin responsible from the URL of the script. Look out for plugins that have many scripts in the list which have a lot of red in code coverage. A plugin should only enqueue a script if it is actually used on the page."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Read about [Browser Caching in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Consider using an [image optimization WordPress plugin](https://wordpress.org/plugins/search/optimize+images/) that compresses your images while retaining quality."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Upload images directly through the [media library](https://codex.wordpress.org/Media_Library_Screen) to ensure that the required image sizes are available, and then insert them from the media library or use the image widget to ensure the optimal image sizes are used (including those for the responsive breakpoints). Avoid using `Full Size` images unless the dimensions are adequate for their usage. [Learn More](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "You can enable text compression in your web server configuration."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Consider using a [plugin](https://wordpress.org/plugins/search/convert+webp/) or service that will automatically convert your uploaded images to the optimal formats."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XA.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XA.json
new file mode 100644
index 00000000000..1d48a064020
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XA.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "[Åççéšš ķéýš ļéţ ûšéŕš qûîçķļý ƒöçûš å þåŕţ öƒ ţĥé þåĝé. Föŕ þŕöþéŕ ñåvîĝåţîöñ, éåçĥ åççéšš ķéý mûšţ бé ûñîqûé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/accesskeys/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "[ᐅ`[accesskey]`ᐊ våļûéš åŕé ñöţ ûñîqûé one two three four five six]"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "[ᐅ`[accesskey]`ᐊ våļûéš åŕé ûñîqûé one two three four five]"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "[Éåçĥ ÅŔÎÅ ᐅ`role`ᐊ šûþþöŕţš å šþéçîƒîç šûбšéţ öƒ ᐅ`aria-*`ᐊ åţţŕîбûţéš. Mîšmåţçĥîñĝ ţĥéšé îñvåļîðåţéš ţĥé ᐅ`aria-*`ᐊ åţţŕîбûţéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-allowed-attr/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš ðö ñöţ måţçĥ ţĥéîŕ ŕöļéš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš måţçĥ ţĥéîŕ ŕöļéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "[Šömé ÅŔÎÅ ŕöļéš ĥåvé ŕéqûîŕéð åţţŕîбûţéš ţĥåţ ðéšçŕîбé ţĥé šţåţé öƒ ţĥé éļéméñţ ţö šçŕééñ ŕéåðéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-required-attr/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "[ᐅ`[role]`ᐊš ðö ñöţ ĥåvé åļļ ŕéqûîŕéð ᐅ`[aria-*]`ᐊ åţţŕîбûţéš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "[ᐅ`[role]`ᐊš ĥåvé åļļ ŕéqûîŕéð ᐅ`[aria-*]`ᐊ åţţŕîбûţéš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "[Šömé ÅŔÎÅ þåŕéñţ ŕöļéš mûšţ çöñţåîñ šþéçîƒîç çĥîļð ŕöļéš ţö þéŕƒöŕm ţĥéîŕ îñţéñðéð åççéššîбîļîţý ƒûñçţîöñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-required-children/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "[Éļéméñţš ŵîţĥ åñ ÅŔÎÅ ᐅ`[role]`ᐊ ţĥåţ ŕéqûîŕé çĥîļðŕéñ ţö çöñţåîñ å šþéçîƒîç ᐅ`[role]`ᐊ åŕé mîššîñĝ šömé öŕ åļļ öƒ ţĥöšé ŕéqûîŕéð çĥîļðŕéñ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "[Éļéméñţš ŵîţĥ åñ ÅŔÎÅ ᐅ`[role]`ᐊ ţĥåţ ŕéqûîŕé çĥîļðŕéñ ţö çöñţåîñ å šþéçîƒîç ᐅ`[role]`ᐊ ĥåvé åļļ ŕéqûîŕéð çĥîļðŕéñ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "[Šömé ÅŔÎÅ çĥîļð ŕöļéš mûšţ бé çöñţåîñéð бý šþéçîƒîç þåŕéñţ ŕöļéš ţö þŕöþéŕļý þéŕƒöŕm ţĥéîŕ îñţéñðéð åççéššîбîļîţý ƒûñçţîöñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-required-parent/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "[ᐅ`[role]`ᐊš åŕé ñöţ çöñţåîñéð бý ţĥéîŕ ŕéqûîŕéð þåŕéñţ éļéméñţ one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "[ᐅ`[role]`ᐊš åŕé çöñţåîñéð бý ţĥéîŕ ŕéqûîŕéð þåŕéñţ éļéméñţ one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "[ÅŔÎÅ ŕöļéš mûšţ ĥåvé våļîð våļûéš îñ öŕðéŕ ţö þéŕƒöŕm ţĥéîŕ îñţéñðéð åççéššîбîļîţý ƒûñçţîöñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-roles/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "[ᐅ`[role]`ᐊ våļûéš åŕé ñöţ våļîð one two three four five]"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "[ᐅ`[role]`ᐊ våļûéš åŕé våļîð one two three four five]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "[Åššîšţîvé ţéçĥñöļöĝîéš, ļîķé šçŕééñ ŕéåðéŕš, çåñ'ţ îñţéŕþŕéţ ÅŔÎÅ åţţŕîбûţéš ŵîţĥ îñvåļîð våļûéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-valid-attr-value/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš ðö ñöţ ĥåvé våļîð våļûéš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš ĥåvé våļîð våļûéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "[Åššîšţîvé ţéçĥñöļöĝîéš, ļîķé šçŕééñ ŕéåðéŕš, çåñ'ţ îñţéŕþŕéţ ÅŔÎÅ åţţŕîбûţéš ŵîţĥ îñvåļîð ñåméš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/aria-valid-attr/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš åŕé ñöţ våļîð öŕ mîššþéļļéð one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "[ᐅ`[aria-*]`ᐊ åţţŕîбûţéš åŕé våļîð åñð ñöţ mîššþéļļéð one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "[Çåþţîöñš måķé åûðîö éļéméñţš ûšåбļé ƒöŕ ðéåƒ öŕ ĥéåŕîñĝ-îmþåîŕéð ûšéŕš, þŕövîðîñĝ çŕîţîçåļ îñƒöŕmåţîöñ šûçĥ åš ŵĥö îš ţåļķîñĝ, ŵĥåţ ţĥéý'ŕé šåýîñĝ, åñð öţĥéŕ ñöñ-šþééçĥ îñƒöŕmåţîöñ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/audio-caption/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "[ᐅ`<audio>`ᐊ éļéméñţš åŕé mîššîñĝ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"captions\"]`ᐊ. one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "[ᐅ`<audio>`ᐊ éļéméñţš çöñţåîñ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"captions\"]`ᐊ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "[Fåîļîñĝ Éļéméñţš one two]"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "[Ŵĥéñ å бûţţöñ ðöéšñ'ţ ĥåvé åñ åççéššîбļé ñåmé, šçŕééñ ŕéåðéŕš åññöûñçé îţ åš \"бûţţöñ\", måķîñĝ îţ ûñûšåбļé ƒöŕ ûšéŕš ŵĥö ŕéļý öñ šçŕééñ ŕéåðéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/button-name/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "[Бûţţöñš ðö ñöţ ĥåvé åñ åççéššîбļé ñåmé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "[Бûţţöñš ĥåvé åñ åççéššîбļé ñåmé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "[Åððîñĝ ŵåýš ţö бýþåšš ŕéþéţîţîvé çöñţéñţ ļéţš ķéýбöåŕð ûšéŕš ñåvîĝåţé ţĥé þåĝé möŕé 郃îçîéñţļý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/bypass/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "[Ţĥé þåĝé ðöéš ñöţ çöñţåîñ å ĥéåðîñĝ, šķîþ ļîñķ, öŕ ļåñðmåŕķ ŕéĝîöñ one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "[Ţĥé þåĝé çöñţåîñš å ĥéåðîñĝ, šķîþ ļîñķ, öŕ ļåñðmåŕķ ŕéĝîöñ one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "[Ļöŵ-çöñţŕåšţ ţéxţ îš ðîçûļţ öŕ îmþöššîбļé ƒöŕ måñý ûšéŕš ţö ŕéåð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/color-contrast/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "[Бåçķĝŕöûñð åñð ƒöŕéĝŕöûñð çöļöŕš ðö ñöţ ĥåvé å šûƒƒîçîéñţ çöñţŕåšţ ŕåţîö. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "[Бåçķĝŕöûñð åñð ƒöŕéĝŕöûñð çöļöŕš ĥåvé å šûƒƒîçîéñţ çöñţŕåšţ ŕåţîö one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "[Ŵĥéñ ðéƒîñîţîöñ ļîšţš åŕé ñöţ þŕöþéŕļý måŕķéð ûþ, šçŕééñ ŕéåðéŕš måý þŕöðûçé çöñƒûšîñĝ öŕ îñåççûŕåţé öûţþûţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/definition-list/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "[ᐅ`<dl>`ᐊ'š ðö ñöţ çöñţåîñ öñļý þŕöþéŕļý-öŕðéŕéð ᐅ`<dt>`ᐊ åñð ᐅ`<dd>`ᐊ ĝŕöûþš, ᐅ`<script>`ᐊ öŕ ᐅ`<template>`ᐊ éļéméñţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "[ᐅ`<dl>`ᐊ'š çöñţåîñ öñļý þŕöþéŕļý-öŕðéŕéð ᐅ`<dt>`ᐊ åñð ᐅ`<dd>`ᐊ ĝŕöûþš, ᐅ`<script>`ᐊ öŕ ᐅ`<template>`ᐊ éļéméñţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "[Ðéƒîñîţîöñ ļîšţ îţémš (ᐅ`<dt>`ᐊ åñð ᐅ`<dd>`ᐊ) mûšţ бé ŵŕåþþéð îñ å þåŕéñţ ᐅ`<dl>`ᐊ éļéméñţ ţö éñšûŕé ţĥåţ šçŕééñ ŕéåðéŕš çåñ þŕöþéŕļý åññöûñçé ţĥém. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/dlitem/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "[Ðéƒîñîţîöñ ļîšţ îţémš åŕé ñöţ ŵŕåþþéð îñ ᐅ`<dl>`ᐊ éļéméñţš one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "[Ðéƒîñîţîöñ ļîšţ îţémš åŕé ŵŕåþþéð îñ ᐅ`<dl>`ᐊ éļéméñţš one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "[Ţĥé ţîţļé ĝîvéš šçŕééñ ŕéåðéŕ ûšéŕš åñ övéŕvîéŵ öƒ ţĥé þåĝé, åñð šéåŕçĥ éñĝîñé ûšéŕš ŕéļý öñ îţ ĥéåvîļý ţö ðéţéŕmîñé îƒ å þåĝé îš ŕéļévåñţ ţö ţĥéîŕ šéåŕçĥ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/document-title/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "[Ðöçûméñţ ðöéšñ'ţ ĥåvé å ᐅ`<title>`ᐊ éļéméñţ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "[Ðöçûméñţ ĥåš å ᐅ`<title>`ᐊ éļéméñţ one two three four five six]"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "[Ţĥé våļûé öƒ åñ îð åţţŕîбûţé mûšţ бé ûñîqûé ţö þŕévéñţ öţĥéŕ îñšţåñçéš ƒŕöm бéîñĝ övéŕļööķéð бý åššîšţîvé ţéçĥñöļöĝîéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/duplicate-id/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "[ᐅ`[id]`ᐊ åţţŕîбûţéš öñ ţĥé þåĝé åŕé ñöţ ûñîqûé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "[ᐅ`[id]`ᐊ åţţŕîбûţéš öñ ţĥé þåĝé åŕé ûñîqûé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕ ûšéŕš ŕéļý öñ ƒŕåmé ţîţļéš ţö ðéšçŕîбé ţĥé çöñţéñţš öƒ ƒŕåméš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/frame-title/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "[ᐅ`<frame>`ᐊ öŕ ᐅ`<iframe>`ᐊ éļéméñţš ðö ñöţ ĥåvé å ţîţļé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "[ᐅ`<frame>`ᐊ öŕ ᐅ`<iframe>`ᐊ éļéméñţš ĥåvé å ţîţļé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "[΃ å þåĝé ðöéšñ'ţ šþéçîƒý å ļåñĝ åţţŕîбûţé, å šçŕééñ ŕéåðéŕ åššûméš ţĥåţ ţĥé þåĝé îš îñ ţĥé ðéƒåûļţ ļåñĝûåĝé ţĥåţ ţĥé ûšéŕ çĥöšé ŵĥéñ šéţţîñĝ ûþ ţĥé šçŕééñ ŕéåðéŕ. ΃ ţĥé þåĝé îšñ'ţ åçţûåļļý îñ ţĥé ðéƒåûļţ ļåñĝûåĝé, ţĥéñ ţĥé šçŕééñ ŕéåðéŕ mîĝĥţ ñöţ åññöûñçé ţĥé þåĝé'š ţéxţ çöŕŕéçţļý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/html-has-lang/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix]"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "[ᐅ`<html>`ᐊ éļéméñţ ðöéš ñöţ ĥåvé å ᐅ`[lang]`ᐊ åţţŕîбûţé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "[ᐅ`<html>`ᐊ éļéméñţ ĥåš å ᐅ`[lang]`ᐊ åţţŕîбûţé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "[Šþéçîƒýîñĝ å våļîð ᐅ[ᐊБÇÞ 47 ļåñĝûåĝéᐅ](https://www.w3.org/International/questions/qa-choosing-language-tags#question)ᐊ ĥéļþš šçŕééñ ŕéåðéŕš åññöûñçé ţéxţ þŕöþéŕļý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/html-lang-valid/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "[ᐅ`<html>`ᐊ éļéméñţ ðöéš ñöţ ĥåvé å våļîð våļûé ƒöŕ îţš ᐅ`[lang]`ᐊ åţţŕîбûţé. one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "[ᐅ`<html>`ᐊ éļéméñţ ĥåš å våļîð våļûé ƒöŕ îţš ᐅ`[lang]`ᐊ åţţŕîбûţé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "[Îñƒöŕmåţîvé éļéméñţš šĥöûļð åîm ƒöŕ šĥöŕţ, ðéšçŕîþţîvé åļţéŕñåţé ţéxţ. Ðéçöŕåţîvé éļéméñţš çåñ бé îĝñöŕéð ŵîţĥ åñ émþţý åļţ åţţŕîбûţé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/image-alt/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "[Îmåĝé éļéméñţš ðö ñöţ ĥåvé ᐅ`[alt]`ᐊ åţţŕîбûţéš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "[Îmåĝé éļéméñţš ĥåvé ᐅ`[alt]`ᐊ åţţŕîбûţéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "[Ŵĥéñ åñ îmåĝé îš бéîñĝ ûšéð åš åñ ᐅ`<input>`ᐊ бûţţöñ, þŕövîðîñĝ åļţéŕñåţîvé ţéxţ çåñ ĥéļþ šçŕééñ ŕéåðéŕ ûšéŕš ûñðéŕšţåñð ţĥé þûŕþöšé öƒ ţĥé бûţţöñ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/input-image-alt/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "[ᐅ`<input type=\"image\">`ᐊ éļéméñţš ðö ñöţ ĥåvé ᐅ`[alt]`ᐊ ţéxţ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "[ᐅ`<input type=\"image\">`ᐊ éļéméñţš ĥåvé ᐅ`[alt]`ᐊ ţéxţ one two three four five six]"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "[Ļåбéļš éñšûŕé ţĥåţ ƒöŕm çöñţŕöļš åŕé åññöûñçéð þŕöþéŕļý бý åššîšţîvé ţéçĥñöļöĝîéš, ļîķé šçŕééñ ŕéåðéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/label/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "[Föŕm éļéméñţš ðö ñöţ ĥåvé åššöçîåţéð ļåбéļš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "[Föŕm éļéméñţš ĥåvé åššöçîåţéð ļåбéļš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "[Å ţåбļé бéîñĝ ûšéð ƒöŕ ļåýöûţ þûŕþöšéš šĥöûļð ñöţ îñçļûðé ðåţå éļéméñţš, šûçĥ åš ţĥé ţĥ öŕ çåþţîöñ éļéméñţš öŕ ţĥé šûmmåŕý åţţŕîбûţé, бéçåûšé ţĥîš çåñ çŕéåţé å çöñƒûšîñĝ éxþéŕîéñçé ƒöŕ šçŕééñ ŕéåðéŕ ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/layout-table/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine]"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "[Þŕéšéñţåţîöñåļ ᐅ`<table>`ᐊ éļéméñţš ðö ñöţ åvöîð ûšîñĝ ᐅ`<th>`ᐊ, ᐅ`<caption>`ᐊ öŕ ţĥé ᐅ`[summary]`ᐊ åţţŕîбûţé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "[Þŕéšéñţåţîöñåļ ᐅ`<table>`ᐊ éļéméñţš åvöîð ûšîñĝ ᐅ`<th>`ᐊ, ᐅ`<caption>`ᐊ öŕ ţĥé ᐅ`[summary]`ᐊ åţţŕîбûţé. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "[Ļîñķ ţéxţ (åñð åļţéŕñåţé ţéxţ ƒöŕ îmåĝéš, ŵĥéñ ûšéð åš ļîñķš) ţĥåţ îš ðîšçéŕñîбļé, ûñîqûé, åñð ƒöçûšåбļé îmþŕövéš ţĥé ñåvîĝåţîöñ éxþéŕîéñçé ƒöŕ šçŕééñ ŕéåðéŕ ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/link-name/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "[Ļîñķš ðö ñöţ ĥåvé å ðîšçéŕñîбļé ñåmé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "[Ļîñķš ĥåvé å ðîšçéŕñîбļé ñåmé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕš ĥåvé å šþéçîƒîç ŵåý öƒ åññöûñçîñĝ ļîšţš. Éñšûŕîñĝ þŕöþéŕ ļîšţ šţŕûçţûŕé åîðš šçŕééñ ŕéåðéŕ öûţþûţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/list/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "[Ļîšţš ðö ñöţ çöñţåîñ öñļý ᐅ`<li>`ᐊ éļéméñţš åñð šçŕîþţ šûþþöŕţîñĝ éļéméñţš (ᐅ`<script>`ᐊ åñð ᐅ`<template>`ᐊ). one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "[Ļîšţš çöñţåîñ öñļý ᐅ`<li>`ᐊ éļéméñţš åñð šçŕîþţ šûþþöŕţîñĝ éļéméñţš (ᐅ`<script>`ᐊ åñð ᐅ`<template>`ᐊ). one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕš ŕéqûîŕé ļîšţ îţémš (ᐅ`<li>`ᐊ) ţö бé çöñţåîñéð ŵîţĥîñ å þåŕéñţ ᐅ`<ul>`ᐊ öŕ ᐅ`<ol>`ᐊ ţö бé åññöûñçéð þŕöþéŕļý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/listitem/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "[Ļîšţ îţémš (ᐅ`<li>`ᐊ) åŕé ñöţ çöñţåîñéð ŵîţĥîñ ᐅ`<ul>`ᐊ öŕ ᐅ`<ol>`ᐊ þåŕéñţ éļéméñţš. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "[Ļîšţ îţémš (ᐅ`<li>`ᐊ) åŕé çöñţåîñéð ŵîţĥîñ ᐅ`<ul>`ᐊ öŕ ᐅ`<ol>`ᐊ þåŕéñţ éļéméñţš one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "[Ûšéŕš ðö ñöţ éxþéçţ å þåĝé ţö ŕéƒŕéšĥ åûţömåţîçåļļý, åñð ðöîñĝ šö ŵîļļ mövé ƒöçûš бåçķ ţö ţĥé ţöþ öƒ ţĥé þåĝé. Ţĥîš måý çŕéåţé å ƒŕûšţŕåţîñĝ öŕ çöñƒûšîñĝ éxþéŕîéñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/meta-refresh/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "[Ţĥé ðöçûméñţ ûšéš ᐅ`<meta http-equiv=\"refresh\">`ᐊ one two three four five]"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "[Ţĥé ðöçûméñţ ðöéš ñöţ ûšé ᐅ`<meta http-equiv=\"refresh\">`ᐊ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "[Ðîšåбļîñĝ žöömîñĝ îš þŕöбļémåţîç ƒöŕ ûšéŕš ŵîţĥ ļöŵ vîšîöñ ŵĥö ŕéļý öñ šçŕééñ måĝñîƒîçåţîöñ ţö þŕöþéŕļý šéé ţĥé çöñţéñţš öƒ å ŵéб þåĝé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/meta-viewport/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "[ᐅ`[user-scalable=\"no\"]`ᐊ îš ûšéð îñ ţĥé ᐅ`<meta name=\"viewport\">`ᐊ éļéméñţ öŕ ţĥé ᐅ`[maximum-scale]`ᐊ åţţŕîбûţé îš ļéšš ţĥåñ 5. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "[ᐅ`[user-scalable=\"no\"]`ᐊ îš ñöţ ûšéð îñ ţĥé ᐅ`<meta name=\"viewport\">`ᐊ éļéméñţ åñð ţĥé ᐅ`[maximum-scale]`ᐊ åţţŕîбûţé îš ñöţ ļéšš ţĥåñ 5. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕš çåññöţ ţŕåñšļåţé ñöñ-ţéxţ çöñţéñţ. Åððîñĝ åļţ ţéxţ ţö ᐅ`<object>`ᐊ éļéméñţš ĥéļþš šçŕééñ ŕéåðéŕš çöñvéý méåñîñĝ ţö ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/object-alt/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "[ᐅ`<object>`ᐊ éļéméñţš ðö ñöţ ĥåvé ᐅ`[alt]`ᐊ ţéxţ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "[ᐅ`<object>`ᐊ éļéméñţš ĥåvé ᐅ`[alt]`ᐊ ţéxţ one two three four five six]"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "[Å våļûé ĝŕéåţéŕ ţĥåñ 0 îmþļîéš åñ éxþļîçîţ ñåvîĝåţîöñ öŕðéŕîñĝ. Åļţĥöûĝĥ ţéçĥñîçåļļý våļîð, ţĥîš öƒţéñ çŕéåţéš ƒŕûšţŕåţîñĝ éxþéŕîéñçéš ƒöŕ ûšéŕš ŵĥö ŕéļý öñ åššîšţîvé ţéçĥñöļöĝîéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/tabindex/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "[Šömé éļéméñţš ĥåvé å ᐅ`[tabindex]`ᐊ våļûé ĝŕéåţéŕ ţĥåñ 0 one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "[Ñö éļéméñţ ĥåš å ᐅ`[tabindex]`ᐊ våļûé ĝŕéåţéŕ ţĥåñ 0 one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕš ĥåvé ƒéåţûŕéš ţö måķé ñåvîĝåţîñĝ ţåбļéš éåšîéŕ. Éñšûŕîñĝ ᐅ`<td>`ᐊ çéļļš ûšîñĝ ţĥé ᐅ`[headers]`ᐊ åţţŕîбûţé öñļý ŕéƒéŕ ţö öţĥéŕ çéļļš îñ ţĥé šåmé ţåбļé måý îmþŕövé ţĥé éxþéŕîéñçé ƒöŕ šçŕééñ ŕéåðéŕ ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/td-headers-attr/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight]"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "[Çéļļš îñ å ᐅ`<table>`ᐊ éļéméñţ ţĥåţ ûšé ţĥé ᐅ`[headers]`ᐊ åţţŕîбûţé ŕéƒéŕ ţö åñ éļéméñţ ᐅ`id`ᐊ ñöţ ƒöûñð ŵîţĥîñ ţĥé šåmé ţåбļé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "[Çéļļš îñ å ᐅ`<table>`ᐊ éļéméñţ ţĥåţ ûšé ţĥé ᐅ`[headers]`ᐊ åţţŕîбûţé ŕéƒéŕ ţö ţåбļé çéļļš ŵîţĥîñ ţĥé šåmé ţåбļé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "[Šçŕééñ ŕéåðéŕš ĥåvé ƒéåţûŕéš ţö måķé ñåvîĝåţîñĝ ţåбļéš éåšîéŕ. Éñšûŕîñĝ ţåбļé ĥéåðéŕš åļŵåýš ŕéƒéŕ ţö šömé šéţ öƒ çéļļš måý îmþŕövé ţĥé éxþéŕîéñçé ƒöŕ šçŕééñ ŕéåðéŕ ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/th-has-data-cells/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "[ᐅ`<th>`ᐊ éļéméñţš åñð éļéméñţš ŵîţĥ ᐅ`[role=\"columnheader\"/\"rowheader\"]`ᐊ ðö ñöţ ĥåvé ðåţå çéļļš ţĥéý ðéšçŕîбé. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "[ᐅ`<th>`ᐊ éļéméñţš åñð éļéméñţš ŵîţĥ ᐅ`[role=\"columnheader\"/\"rowheader\"]`ᐊ ĥåvé ðåţå çéļļš ţĥéý ðéšçŕîбé. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "[Šþéçîƒýîñĝ å våļîð ᐅ[ᐊБÇÞ 47 ļåñĝûåĝéᐅ](https://www.w3.org/International/questions/qa-choosing-language-tags#question)ᐊ öñ éļéméñţš ĥéļþš éñšûŕé ţĥåţ ţéxţ îš þŕöñöûñçéð çöŕŕéçţļý бý å šçŕééñ ŕéåðéŕ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/valid-lang/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "[ᐅ`[lang]`ᐊ åţţŕîбûţéš ðö ñöţ ĥåvé å våļîð våļûé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "[ᐅ`[lang]`ᐊ åţţŕîбûţéš ĥåvé å våļîð våļûé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "[Ŵĥéñ å vîðéö þŕövîðéš å çåþţîöñ îţ îš éåšîéŕ ƒöŕ ðéåƒ åñð ĥéåŕîñĝ îmþåîŕéð ûšéŕš ţö åççéšš îţš îñƒöŕmåţîöñ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/video-caption/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "[ᐅ`<video>`ᐊ éļéméñţš ðö ñöţ çöñţåîñ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"captions\"]`ᐊ. one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "[ᐅ`<video>`ᐊ éļéméñţš çöñţåîñ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"captions\"]`ᐊ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "[Åûðîö ðéšçŕîþţîöñš þŕövîðé ŕéļévåñţ îñƒöŕmåţîöñ ƒöŕ vîðéöš ţĥåţ ðîåļöĝûé çåññöţ, šûçĥ åš ƒåçîåļ éxþŕéššîöñš åñð šçéñéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/video-description/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "[ᐅ`<video>`ᐊ éļéméñţš ðö ñöţ çöñţåîñ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"description\"]`ᐊ. one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "[ᐅ`<video>`ᐊ éļéméñţš çöñţåîñ å ᐅ`<track>`ᐊ éļéméñţ ŵîţĥ ᐅ`[kind=\"description\"]`ᐊ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "[Föŕ îðéåļ åþþéåŕåñçé öñ îÖŠ ŵĥéñ ûšéŕš åðð å þŕöĝŕéššîvé ŵéб åþþ ţö ţĥé ĥömé šçŕééñ, ðéƒîñé åñ ᐅ`apple-touch-icon`ᐊ. Îţ mûšţ þöîñţ ţö å ñöñ-ţŕåñšþåŕéñţ 192þx (öŕ 180þx) šqûåŕé ÞÑĜ. ᐅ[ᐊĻéåŕñ Möŕéᐅ](https://web.dev/apple-touch-icon/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "[Ðöéš ñöţ þŕövîðé å våļîð ᐅ`apple-touch-icon`ᐊ one two three four five six]"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "[ᐅ`apple-touch-icon-precomposed`ᐊ îš öûţ öƒ ðåţé; ᐅ`apple-touch-icon`ᐊ îš þŕéƒéŕŕéð. one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "[Þŕövîðéš å våļîð ᐅ`apple-touch-icon`ᐊ one two three four five]"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "[Çĥŕömé éxţéñšîöñš ñéĝåţîvéļý 僃éçţéð ţĥîš þåĝé'š ļöåð þéŕƒöŕmåñçé. Ţŕý åûðîţîñĝ ţĥé þåĝé îñ îñçöĝñîţö möðé öŕ ƒŕöm å Çĥŕömé þŕöƒîļé ŵîţĥöûţ éxţéñšîöñš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "[Šçŕîþţ Évåļûåţîöñ one two three]"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "[Šçŕîþţ Þåŕšé one two]"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "[Ţöţåļ ÇÞÛ Ţîmé one two]"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "[Çöñšîðéŕ ŕéðûçîñĝ ţĥé ţîmé šþéñţ þåŕšîñĝ, çömþîļîñĝ, åñð éxéçûţîñĝ ĴŠ. Ýöû måý ƒîñð ðéļîvéŕîñĝ šmåļļéŕ ĴŠ þåýļöåðš ĥéļþš ŵîţĥ ţĥîš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/bootup-time)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "[Ŕéðûçé ĴåvåŠçŕîþţ éxéçûţîöñ ţîmé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "[ĴåvåŠçŕîþţ éxéçûţîöñ ţîmé one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "[Ļåŕĝé ĜÎFš åŕé îñ郃îçîéñţ ƒöŕ ðéļîvéŕîñĝ åñîmåţéð çöñţéñţ. Çöñšîðéŕ ûšîñĝ MÞÉĜ4/ŴéбM vîðéöš ƒöŕ åñîmåţîöñš åñð ÞÑĜ/ŴéбÞ ƒöŕ šţåţîç îmåĝéš îñšţéåð öƒ ĜÎF ţö šåvé ñéţŵöŕķ бýţéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/efficient-animated-content)ᐊ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "[Ûšé vîðéö ƒöŕmåţš ƒöŕ åñîmåţéð çöñţéñţ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "[Çöñšîðéŕ ļåžý-ļöåðîñĝ öƒƒšçŕééñ åñð ĥîððéñ îmåĝéš åƒţéŕ åļļ çŕîţîçåļ ŕéšöûŕçéš ĥåvé ƒîñîšĥéð ļöåðîñĝ ţö ļöŵéŕ ţîmé ţö îñţéŕåçţîvé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/offscreen-images)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "[Ðéƒéŕ öƒƒšçŕééñ îmåĝéš one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "[Ŕéšöûŕçéš åŕé бļöçķîñĝ ţĥé ƒîŕšţ þåîñţ öƒ ýöûŕ þåĝé. Çöñšîðéŕ ðéļîvéŕîñĝ çŕîţîçåļ ĴŠ/ÇŠŠ îñļîñé åñð ðéƒéŕŕîñĝ åļļ ñöñ-çŕîţîçåļ ĴŠ/šţýļéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/render-blocking-resources)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "[Éļîmîñåţé ŕéñðéŕ-бļöçķîñĝ ŕéšöûŕçéš one two three four]"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "[Ļåŕĝé ñéţŵöŕķ þåýļöåðš çöšţ ûšéŕš ŕéåļ möñéý åñð åŕé ĥîĝĥļý çöŕŕéļåţéð ŵîţĥ ļöñĝ ļöåð ţîméš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/total-byte-weight)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "[Ţöţåļ šîžé ŵåš ᐅ{totalBytes, number, bytes}ᐊ ĶБ one two three four five]"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "[Åvöîð éñöŕmöûš ñéţŵöŕķ þåýļöåðš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "[Åvöîðš éñöŕmöûš ñéţŵöŕķ þåýļöåðš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "[Mîñîƒýîñĝ ÇŠŠ ƒîļéš çåñ ŕéðûçé ñéţŵöŕķ þåýļöåð šîžéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/unminified-css)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "[Mîñîƒý ÇŠŠ one two]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "[Mîñîƒýîñĝ ĴåvåŠçŕîþţ ƒîļéš çåñ ŕéðûçé þåýļöåð šîžéš åñð šçŕîþţ þåŕšé ţîmé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/unminified-javascript)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "[Mîñîƒý ĴåvåŠçŕîþţ one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "[Ŕémövé ðéåð ŕûļéš ƒŕöm šţýļéšĥééţš åñð ðéƒéŕ ţĥé ļöåðîñĝ öƒ ÇŠŠ ñöţ ûšéð ƒöŕ åбövé-ţĥé-ƒöļð çöñţéñţ ţö ŕéðûçé ûññéçéššåŕý бýţéš çöñšûméð бý ñéţŵöŕķ åçţîvîţý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/unused-css-rules)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "[Ŕémövé ûñûšéð ÇŠŠ one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "[Ŕémövé ûñûšéð ĴåvåŠçŕîþţ ţö ŕéðûçé бýţéš çöñšûméð бý ñéţŵöŕķ åçţîvîţý. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "[Ŕémövé ûñûšéð ĴåvåŠçŕîþţ one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "[Å ļöñĝ çåçĥé ļîƒéţîmé çåñ šþééð ûþ ŕéþéåţ vîšîţš ţö ýöûŕ þåĝé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-long-cache-ttl)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 ŕéšöûŕçé ƒöûñð one two]}other{[# ŕéšöûŕçéš ƒöûñð one two three]}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "[Šéŕvé šţåţîç åššéţš ŵîţĥ åñ 郃îçîéñţ çåçĥé þöļîçý one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "[Ûšéš éƒƒîçîéñţ çåçĥé þöļîçý öñ šţåţîç åššéţš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "[Öþţîmîžéð îmåĝéš ļöåð ƒåšţéŕ åñð çöñšûmé ļéšš çéļļûļåŕ ðåţå. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-optimized-images)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "[Ƀƒîçîéñţļý éñçöðé îmåĝéš one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "[Šéŕvé îmåĝéš ţĥåţ åŕé åþþŕöþŕîåţéļý-šîžéð ţö šåvé çéļļûļåŕ ðåţå åñð îmþŕövé ļöåð ţîmé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-responsive-images)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "[Þŕöþéŕļý šîžé îmåĝéš one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "[Ţéxţ-бåšéð ŕéšöûŕçéš šĥöûļð бé šéŕvéð ŵîţĥ çömþŕéššîöñ (ĝžîþ, ðéƒļåţé öŕ бŕöţļî) ţö mîñîmîžé ţöţåļ ñéţŵöŕķ бýţéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-text-compression)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "[Éñåбļé ţéxţ çömþŕéššîöñ one two three]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "[Îmåĝé ƒöŕmåţš ļîķé ĴÞÉĜ 2000, ĴÞÉĜ XŔ, åñð ŴéбÞ öƒţéñ þŕövîðé бéţţéŕ çömþŕéššîöñ ţĥåñ ÞÑĜ öŕ ĴÞÉĜ, ŵĥîçĥ méåñš ƒåšţéŕ ðöŵñļöåðš åñð ļéšš ðåţå çöñšûmþţîöñ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-webp-images)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "[Šéŕvé îmåĝéš îñ ñéxţ-ĝéñ ƒöŕmåţš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "[΃ ţĥé ŵîðţĥ öƒ ýöûŕ åþþ'š çöñţéñţ ðöéšñ'ţ måţçĥ ţĥé ŵîðţĥ öƒ ţĥé vîéŵþöŕţ, ýöûŕ åþþ mîĝĥţ ñöţ бé öþţîmîžéð ƒöŕ möбîļé šçŕééñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/content-width)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "[Ţĥé vîéŵþöŕţ šîžé öƒ ᐅ{innerWidth}ᐊþx ðöéš ñöţ måţçĥ ţĥé ŵîñðöŵ šîžé öƒ ᐅ{outerWidth}ᐊþx. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "[Çöñţéñţ îš ñöţ šîžéð çöŕŕéçţļý ƒöŕ ţĥé vîéŵþöŕţ one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "[Çöñţéñţ îš šîžéð çöŕŕéçţļý ƒöŕ ţĥé vîéŵþöŕţ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "[Ţĥé Çŕîţîçåļ Ŕéqûéšţ Çĥåîñš бéļöŵ šĥöŵ ýöû ŵĥåţ ŕéšöûŕçéš åŕé ļöåðéð ŵîţĥ å ĥîĝĥ þŕîöŕîţý. Çöñšîðéŕ ŕéðûçîñĝ ţĥé ļéñĝţĥ öƒ çĥåîñš, ŕéðûçîñĝ ţĥé ðöŵñļöåð šîžé öƒ ŕéšöûŕçéš, öŕ ðéƒéŕŕîñĝ ţĥé ðöŵñļöåð öƒ ûññéçéššåŕý ŕéšöûŕçéš ţö îmþŕövé þåĝé ļöåð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/critical-request-chains)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree]"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 çĥåîñ ƒöûñð one two]}other{[# çĥåîñš ƒöûñð one two]}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "[Mîñîmîžé Çŕîţîçåļ Ŕéqûéšţš Ðéþţĥ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "[Ðéþŕéçåţîöñ / Ŵåŕñîñĝ one two three]"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "[Ļîñé one]"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "[Ðéþŕéçåţéð ÅÞΚ ŵîļļ évéñţûåļļý бé ŕémövéð ƒŕöm ţĥé бŕöŵšéŕ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/deprecations)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 ŵåŕñîñĝ ƒöûñð one two]}other{[# ŵåŕñîñĝš ƒöûñð one two]}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "[Ûšéš ðéþŕéçåţéð ÅÞΚ one two three]"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "[Åvöîðš ðéþŕéçåţéð ÅÞΚ one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "[Åþþļîçåţîöñ Çåçĥé îš ðéþŕéçåţéð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/appcache-manifest)ᐊ. one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "[Föûñð \"ᐅ{AppCacheManifest}ᐊ\" one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "[Ûšéš Åþþļîçåţîöñ Çåçĥé one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "[Åvöîðš Åþþļîçåţîöñ Çåçĥé one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "[Šþéçîƒýîñĝ å ðöçţýþé þŕévéñţš ţĥé бŕöŵšéŕ ƒŕöm šŵîţçĥîñĝ ţö qûîŕķš-möðé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/doctype)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "[Ðöçţýþé ñåmé mûšţ бé ţĥé ļöŵéŕçåšé šţŕîñĝ ᐅ`html`ᐊ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "[Ðöçûméñţ mûšţ çöñţåîñ å ðöçţýþé one two three four five six seven]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "[Éxþéçţéð þûбļîçÎð ţö бé åñ émþţý šţŕîñĝ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "[Éxþéçţéð šýšţémÎð ţö бé åñ émþţý šţŕîñĝ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "[Þåĝé ļåçķš ţĥé ĤŢMĻ ðöçţýþé, ţĥûš ţŕîĝĝéŕîñĝ qûîŕķš-möðé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "[Þåĝé ĥåš ţĥé ĤŢMĻ ðöçţýþé one two three four five six]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "[Éļéméñţ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "[Šţåţîšţîç one two]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "[Våļûé one]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "[Бŕöŵšéŕ éñĝîñééŕš ŕéçömméñð þåĝéš çöñţåîñ ƒéŵéŕ ţĥåñ ~1,500 ÐÖM éļéméñţš. Ţĥé šŵééţ šþöţ îš å ţŕéé ðéþţĥ < 32 éļéméñţš åñð ƒéŵéŕ ţĥåñ 60 çĥîļðŕéñ/þåŕéñţ éļéméñţ. Å ļåŕĝé ÐÖM çåñ îñçŕéåšé mémöŕý ûšåĝé, çåûšé ļöñĝéŕ ᐅ[ᐊšţýļé çåļçûļåţîöñšᐅ](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)ᐊ, åñð þŕöðûçé çöšţļý ᐅ[ᐊļåýöûţ ŕéƒļöŵšᐅ](https://developers.google.com/speed/articles/reflow)ᐊ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/dom-size)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 éļéméñţ one two]}other{[# éļéméñţš one two]}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "[Åvöîð åñ éxçéššîvé ÐÖM šîžé one two three four five six]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "[Måxîmûm ÐÖM Ðéþţĥ one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "[Ţöţåļ ÐÖM Éļéméñţš one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "[Måxîmûm Çĥîļð Éļéméñţš one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "[Åvöîðš åñ éxçéššîvé ÐÖM šîžé one two three four five six]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "[Ŕéļ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "[Ţåŕĝéţ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "[Åðð ᐅ`rel=\"noopener\"`ᐊ öŕ ᐅ`rel=\"noreferrer\"`ᐊ ţö åñý éxţéŕñåļ ļîñķš ţö îmþŕövé þéŕƒöŕmåñçé åñð þŕévéñţ šéçûŕîţý vûļñéŕåбîļîţîéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/external-anchors-use-rel-noopener)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "[Ļîñķš ţö çŕöšš-öŕîĝîñ ðéšţîñåţîöñš åŕé ûñšåƒé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "[Ļîñķš ţö çŕöšš-öŕîĝîñ ðéšţîñåţîöñš åŕé šåƒé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "[Ûñåбļé ţö ðéţéŕmîñé ţĥé ðéšţîñåţîöñ ƒöŕ åñçĥöŕ (ᐅ{anchorHTML}ᐊ). ΃ ñöţ ûšéð åš å ĥýþéŕļîñķ, çöñšîðéŕ ŕémövîñĝ ţåŕĝéţ=_бļåñķ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "[Ûšéŕš åŕé mîšţŕûšţƒûļ öƒ öŕ çöñƒûšéð бý šîţéš ţĥåţ ŕéqûéšţ ţĥéîŕ ļöçåţîöñ ŵîţĥöûţ çöñţéxţ. Çöñšîðéŕ ţýîñĝ ţĥé ŕéqûéšţ ţö å ûšéŕ åçţîöñ îñšţéåð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/geolocation-on-start)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "[Ŕéqûéšţš ţĥé ĝéöļöçåţîöñ þéŕmîššîöñ öñ þåĝé ļöåð one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "[Åvöîðš ŕéqûéšţîñĝ ţĥé ĝéöļöçåţîöñ þéŕmîššîöñ öñ þåĝé ļöåð one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "[Véŕšîöñ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "[Åļļ ƒŕöñţ-éñð ĴåvåŠçŕîþţ ļîбŕåŕîéš ðéţéçţéð öñ ţĥé þåĝé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/js-libraries)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "[Ðéţéçţéð ĴåvåŠçŕîþţ ļîбŕåŕîéš one two three four]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "[Föŕ ûšéŕš öñ šļöŵ çöññéçţîöñš, éxţéŕñåļ šçŕîþţš ðýñåmîçåļļý îñĵéçţéð vîå ᐅ`document.write()`ᐊ çåñ ðéļåý þåĝé ļöåð бý ţéñš öƒ šéçöñðš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/no-document-write)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "[Ûšéš ᐅ`document.write()`ᐊ one two]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "[Åvöîðš ᐅ`document.write()`ᐊ one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "[Ĥîĝĥéšţ Šévéŕîţý one two]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "[Ļîбŕåŕý Véŕšîöñ one two]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "[Vûļñéŕåбîļîţý Çöûñţ one two three]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "[Šömé ţĥîŕð-þåŕţý šçŕîþţš måý çöñţåîñ ķñöŵñ šéçûŕîţý vûļñéŕåбîļîţîéš ţĥåţ åŕé éåšîļý îðéñţîƒîéð åñð éxþļöîţéð бý åţţåçķéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/no-vulnerable-libraries)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 vûļñéŕåбîļîţý ðéţéçţéð one two three]}other{[# vûļñéŕåбîļîţîéš ðéţéçţéð one two three]}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "[Îñçļûðéš ƒŕöñţ-éñð ĴåvåŠçŕîþţ ļîбŕåŕîéš ŵîţĥ ķñöŵñ šéçûŕîţý vûļñéŕåбîļîţîéš one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "[Ĥîĝĥ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "[Ļöŵ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "[Méðîûm one]"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "[Åvöîðš ƒŕöñţ-éñð ĴåvåŠçŕîþţ ļîбŕåŕîéš ŵîţĥ ķñöŵñ šéçûŕîţý vûļñéŕåбîļîţîéš one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "[Ûšéŕš åŕé mîšţŕûšţƒûļ öƒ öŕ çöñƒûšéð бý šîţéš ţĥåţ ŕéqûéšţ ţö šéñð ñöţîƒîçåţîöñš ŵîţĥöûţ çöñţéxţ. Çöñšîðéŕ ţýîñĝ ţĥé ŕéqûéšţ ţö ûšéŕ ĝéšţûŕéš îñšţéåð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/notification-on-start)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "[Ŕéqûéšţš ţĥé ñöţîƒîçåţîöñ þéŕmîššîöñ öñ þåĝé ļöåð one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "[Åvöîðš ŕéqûéšţîñĝ ţĥé ñöţîƒîçåţîöñ þéŕmîššîöñ öñ þåĝé ļöåð one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "[Fåîļîñĝ Éļéméñţš one two]"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "[Þŕévéñţîñĝ þåššŵöŕð þåšţîñĝ ûñðéŕmîñéš ĝööð šéçûŕîţý þöļîçý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/password-inputs-can-be-pasted-into)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "[Þŕévéñţš ûšéŕš ţö þåšţé îñţö þåššŵöŕð ƒîéļðš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "[Åļļöŵš ûšéŕš ţö þåšţé îñţö þåššŵöŕð ƒîéļðš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "[Þŕöţöçöļ one]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "[ĤŢŢÞ/2 öƒƒéŕš måñý бéñéƒîţš övéŕ ĤŢŢÞ/1.1, îñçļûðîñĝ бîñåŕý ĥéåðéŕš, mûļţîþļéxîñĝ, åñð šéŕvéŕ þûšĥ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-http2)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 ŕéqûéšţ ñöţ šéŕvéð vîå ĤŢŢÞ/2 one two three four five six seven]}other{[# ŕéqûéšţš ñöţ šéŕvéð vîå ĤŢŢÞ/2 one two three four five six seven]}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ûšé ĤŢŢÞ/2 ƒöŕ åļļ öƒ îţš ŕéšöûŕçéš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "[Ûšéš ĤŢŢÞ/2 ƒöŕ îţš öŵñ ŕéšöûŕçéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "[Çöñšîðéŕ måŕķîñĝ ýöûŕ ţöûçĥ åñð ŵĥééļ évéñţ ļîšţéñéŕš åš ᐅ`passive`ᐊ ţö îmþŕövé ýöûŕ þåĝé'š šçŕöļļ þéŕƒöŕmåñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-passive-event-listeners)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ûšé þåššîvé ļîšţéñéŕš ţö îmþŕövé šçŕöļļîñĝ þéŕƒöŕmåñçé one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "[Ûšéš þåššîvé ļîšţéñéŕš ţö îmþŕövé šçŕöļļîñĝ þéŕƒöŕmåñçé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "[Ðéšçŕîþţîöñ one two]"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "[Éŕŕöŕš ļöĝĝéð ţö ţĥé çöñšöļé îñðîçåţé ûñŕéšöļvéð þŕöбļémš. Ţĥéý çåñ çömé ƒŕöm ñéţŵöŕķ ŕéqûéšţ ƒåîļûŕéš åñð öţĥéŕ бŕöŵšéŕ çöñçéŕñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/errors-in-console)ᐊ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "[Бŕöŵšéŕ éŕŕöŕš ŵéŕé ļöĝĝéð ţö ţĥé çöñšöļé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "[Ñö бŕöŵšéŕ éŕŕöŕš ļöĝĝéð ţö ţĥé çöñšöļé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "[Ļévéŕåĝé ţĥé ƒöñţ-ðîšþļåý ÇŠŠ ƒéåţûŕé ţö éñšûŕé ţéxţ îš ûšéŕ-vîšîбļé ŵĥîļé ŵéбƒöñţš åŕé ļöåðîñĝ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/font-display)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "[Éñšûŕé ţéxţ ŕémåîñš vîšîбļé ðûŕîñĝ ŵéбƒöñţ ļöåð one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "[Åļļ ţéxţ ŕémåîñš vîšîбļé ðûŕîñĝ ŵéбƒöñţ ļöåðš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö åûţömåţîçåļļý çĥéçķ ţĥé ƒöñţ-ðîšþļåý våļûé ƒöŕ ţĥé ƒöļļöŵîñĝ ÛŔĻ: ᐅ{fontURL}ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "[Åšþéçţ Ŕåţîö (Åçţûåļ) one two three]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "[Åšþéçţ Ŕåţîö (Ðîšþļåýéð) one two three]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "[Îmåĝé ðîšþļåý ðîméñšîöñš šĥöûļð måţçĥ ñåţûŕåļ åšþéçţ ŕåţîö. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/image-aspect-ratio)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "[Ðîšþļåýš îmåĝéš ŵîţĥ îñçöŕŕéçţ åšþéçţ ŕåţîö one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "[Ðîšþļåýš îmåĝéš ŵîţĥ çöŕŕéçţ åšþéçţ ŕåţîö one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "[Îñvåļîð îmåĝé šîžîñĝ îñƒöŕmåţîöñ ᐅ{url}ᐊ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "[Бŕöŵšéŕš çåñ þŕöåçţîvéļý þŕömþţ ûšéŕš ţö åðð ýöûŕ åþþ ţö ţĥéîŕ ĥöméšçŕééñ, ŵĥîçĥ çåñ ļéåð ţö ĥîĝĥéŕ éñĝåĝéméñţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/installable-manifest)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "[Ŵéб åþþ måñîƒéšţ ðöéš ñöţ mééţ ţĥé îñšţåļļåбîļîţý ŕéqûîŕéméñţš one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "[Ŵéб åþþ måñîƒéšţ mééţš ţĥé îñšţåļļåбîļîţý ŕéqûîŕéméñţš one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "[Îñšéçûŕé ÛŔĻ one two]"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "[Åļļ šîţéš šĥöûļð бé þŕöţéçţéð ŵîţĥ ĤŢŢÞŠ, évéñ öñéš ţĥåţ ðöñ'ţ ĥåñðļé šéñšîţîvé ðåţå. ĤŢŢÞŠ þŕévéñţš îñţŕûðéŕš ƒŕöm ţåmþéŕîñĝ ŵîţĥ öŕ þåššîvéļý ļîšţéñîñĝ îñ öñ ţĥé çömmûñîçåţîöñš бéţŵééñ ýöûŕ åþþ åñð ýöûŕ ûšéŕš, åñð îš å þŕéŕéqûîšîţé ƒöŕ ĤŢŢÞ/2 åñð måñý ñéŵ ŵéб þļåţƒöŕm ÅÞΚ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/is-on-https)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix]"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 îñšéçûŕé ŕéqûéšţ ƒöûñð one two three four five]}other{[# îñšéçûŕé ŕéqûéšţš ƒöûñð one two three four five six]}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ûšé ĤŢŢÞŠ one two three four]"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "[Ûšéš ĤŢŢÞŠ one two]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "[Å ƒåšţ þåĝé ļöåð övéŕ å çéļļûļåŕ ñéţŵöŕķ éñšûŕéš å ĝööð möбîļé ûšéŕ éxþéŕîéñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/load-fast-enough-for-pwa)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "[Îñţéŕåçţîvé åţ ᐅ{timeInMs, number, seconds}ᐊ š one two three four five]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "[Îñţéŕåçţîvé öñ šîmûļåţéð möбîļé ñéţŵöŕķ åţ ᐅ{timeInMs, number, seconds}ᐊ š one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "[Ýöûŕ þåĝé ļöåðš ţöö šļöŵļý åñð îš ñöţ îñţéŕåçţîvé ŵîţĥîñ 10 šéçöñðš. Ļööķ åţ ţĥé öþþöŕţûñîţîéš åñð ðîåĝñöšţîçš îñ ţĥé \"Þéŕƒöŕmåñçé\" šéçţîöñ ţö ļéåŕñ ĥöŵ ţö îmþŕövé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "[Þåĝé ļöåð îš ñöţ ƒåšţ éñöûĝĥ öñ möбîļé ñéţŵöŕķš one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "[Þåĝé ļöåð îš ƒåšţ éñöûĝĥ öñ möбîļé ñéţŵöŕķš one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "[Çåţéĝöŕý one]"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "[Çöñšîðéŕ ŕéðûçîñĝ ţĥé ţîmé šþéñţ þåŕšîñĝ, çömþîļîñĝ åñð éxéçûţîñĝ ĴŠ. Ýöû måý ƒîñð ðéļîvéŕîñĝ šmåļļéŕ ĴŠ þåýļöåðš ĥéļþš ŵîţĥ ţĥîš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/mainthread-work-breakdown)ᐊ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "[Mîñîmîžé måîñ-ţĥŕéåð ŵöŕķ one two three]"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "[Mîñîmîžéš måîñ-ţĥŕéåð ŵöŕķ one two three]"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "[Ţö ŕéåçĥ ţĥé möšţ ñûmбéŕ öƒ ûšéŕš, šîţéš šĥöûļð ŵöŕķ åçŕöšš évéŕý måĵöŕ бŕöŵšéŕ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/pwa-cross-browser)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "[Šîţé ŵöŕķš çŕöšš-бŕöŵšéŕ one two three]"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "[Éñšûŕé îñðîvîðûåļ þåĝéš åŕé ðééþ ļîñķåбļé vîå ÛŔĻ åñð ţĥåţ ÛŔĻš åŕé ûñîqûé ƒöŕ ţĥé þûŕþöšé öƒ šĥåŕéåбîļîţý öñ šöçîåļ méðîå. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/pwa-each-page-has-url)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "[Éåçĥ þåĝé ĥåš å ÛŔĻ one two three four]"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "[Ţŕåñšîţîöñš šĥöûļð ƒééļ šñåþþý åš ýöû ţåþ åŕöûñð, évéñ öñ å šļöŵ ñéţŵöŕķ. Ţĥîš éxþéŕîéñçé îš ķéý ţö å ûšéŕ'š þéŕçéþţîöñ öƒ þéŕƒöŕmåñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/pwa-page-transitions)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "[Þåĝé ţŕåñšîţîöñš ðöñ'ţ ƒééļ ļîķé ţĥéý бļöçķ öñ ţĥé ñéţŵöŕķ one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "[Éšţîmåţéð Îñþûţ Ļåţéñçý îš åñ éšţîmåţé öƒ ĥöŵ ļöñĝ ýöûŕ åþþ ţåķéš ţö ŕéšþöñð ţö ûšéŕ îñþûţ, îñ mîļļîšéçöñðš, ðûŕîñĝ ţĥé бûšîéšţ 5š ŵîñðöŵ öƒ þåĝé ļöåð. ΃ ýöûŕ ļåţéñçý îš ĥîĝĥéŕ ţĥåñ 50 mš, ûšéŕš måý þéŕçéîvé ýöûŕ åþþ åš ļåĝĝý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/estimated-input-latency)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone]"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "[Éšţîmåţéð Îñþûţ Ļåţéñçý one two three]"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "[Fîŕšţ Çöñţéñţƒûļ Þåîñţ måŕķš ţĥé ţîmé åţ ŵĥîçĥ ţĥé ƒîŕšţ ţéxţ öŕ îmåĝé îš þåîñţéð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/first-contentful-paint)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "[Fîŕšţ Çöñţéñţƒûļ Þåîñţ one two three]"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "[Fîŕšţ ÇÞÛ Îðļé måŕķš ţĥé ƒîŕšţ ţîmé åţ ŵĥîçĥ ţĥé þåĝé'š måîñ ţĥŕéåð îš qûîéţ éñöûĝĥ ţö ĥåñðļé îñþûţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/first-cpu-idle)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "[Fîŕšţ ÇÞÛ Îðļé one two]"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "[Fîŕšţ Méåñîñĝƒûļ Þåîñţ méåšûŕéš ŵĥéñ ţĥé þŕîmåŕý çöñţéñţ öƒ å þåĝé îš vîšîбļé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/first-meaningful-paint)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "[Fîŕšţ Méåñîñĝƒûļ Þåîñţ one two three]"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "[Ţîmé ţö îñţéŕåçţîvé îš ţĥé åmöûñţ öƒ ţîmé îţ ţåķéš ƒöŕ ţĥé þåĝé ţö бéçömé ƒûļļý îñţéŕåçţîvé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/interactive)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "[Ţîmé ţö Îñţéŕåçţîvé one two three]"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "[Ţĥé måxîmûm þöţéñţîåļ Fîŕšţ Îñþûţ Ðéļåý ţĥåţ ýöûŕ ûšéŕš çöûļð éxþéŕîéñçé îš ţĥé ðûŕåţîöñ, îñ mîļļîšéçöñðš, öƒ ţĥé ļöñĝéšţ ţåšķ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/web/updates/2018/05/first-input-delay)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "[Måx Þöţéñţîåļ Fîŕšţ Îñþûţ Ðéļåý one two three four five six seven]"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "[Šþééð Îñðéx šĥöŵš ĥöŵ qûîçķļý ţĥé çöñţéñţš öƒ å þåĝé åŕé vîšîбļý þöþûļåţéð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/speed-index)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "[Šþééð Îñðéx one two]"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "[Šûm öƒ åļļ ţîmé þéŕîöðš бéţŵééñ FÇÞ åñð Ţîmé ţö Îñţéŕåçţîvé, ŵĥéñ ţåšķ ļéñĝţĥ éxçééðéð 50mš, éxþŕéššéð îñ mîļļîšéçöñðš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "[Ţöţåļ Бļöçķîñĝ Ţîmé one two three]"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "[Ñéţŵöŕķ ŕöûñð ţŕîþ ţîméš (ŔŢŢ) ĥåvé å ļåŕĝé îmþåçţ öñ þéŕƒöŕmåñçé. ΃ ţĥé ŔŢŢ ţö åñ öŕîĝîñ îš ĥîĝĥ, îţ'š åñ îñðîçåţîöñ ţĥåţ šéŕvéŕš çļöšéŕ ţö ţĥé ûšéŕ çöûļð îmþŕövé þéŕƒöŕmåñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://hpbn.co/primer-on-latency-and-bandwidth/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "[Ñéţŵöŕķ Ŕöûñð Ţŕîþ Ţîméš one two three four five]"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "[Šéŕvéŕ ļåţéñçîéš çåñ îmþåçţ ŵéб þéŕƒöŕmåñçé. ΃ ţĥé šéŕvéŕ ļåţéñçý öƒ åñ öŕîĝîñ îš ĥîĝĥ, îţ'š åñ îñðîçåţîöñ ţĥé šéŕvéŕ îš övéŕļöåðéð öŕ ĥåš þööŕ бåçķéñð þéŕƒöŕmåñçé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "[Šéŕvéŕ Бåçķéñð Ļåţéñçîéš one two three]"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "[Å šéŕvîçé ŵöŕķéŕ éñåбļéš ýöûŕ ŵéб åþþ ţö бé ŕéļîåбļé îñ ûñþŕéðîçţåбļé ñéţŵöŕķ çöñðîţîöñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/offline-start-url)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "[ᐅ`start_url`ᐊ ðöéš ñöţ ŕéšþöñð ŵîţĥ å 200 ŵĥéñ öƒƒļîñé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "[ᐅ`start_url`ᐊ ŕéšþöñðš ŵîţĥ å 200 ŵĥéñ öƒƒļîñé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "[Ļîĝĥţĥöûšé çöûļðñ'ţ ŕéåð ţĥé ᐅ`start_url`ᐊ ƒŕöm ţĥé måñîƒéšţ. Åš å ŕéšûļţ, ţĥé ᐅ`start_url`ᐊ ŵåš åššûméð ţö бé ţĥé ðöçûméñţ'š ÛŔĻ. Éŕŕöŕ méššåĝé: 'ᐅ{manifestWarning}ᐊ'. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "[Övéŕ Бûðĝéţ one two]"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "[Ķééþ ţĥé qûåñţîţý åñð šîžé öƒ ñéţŵöŕķ ŕéqûéšţš ûñðéŕ ţĥé ţåŕĝéţš šéţ бý ţĥé þŕövîðéð þéŕƒöŕmåñçé бûðĝéţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/web/tools/lighthouse/audits/budgets)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{[1 ŕéqûéšţ one two]}other{[# ŕéqûéšţš one two]}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "[Þéŕƒöŕmåñçé бûðĝéţ one two three]"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "[΃ ýöû'vé åļŕéåðý šéţ ûþ ĤŢŢÞŠ, måķé šûŕé ţĥåţ ýöû ŕéðîŕéçţ åļļ ĤŢŢÞ ţŕ僃îç ţö ĤŢŢÞŠ îñ öŕðéŕ ţö éñåбļé šéçûŕé ŵéб ƒéåţûŕéš ƒöŕ åļļ ýöûŕ ûšéŕš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/redirects-http)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ŕéðîŕéçţ ĤŢŢÞ ţŕ僃îç ţö ĤŢŢÞŠ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "[Ŕéðîŕéçţš ĤŢŢÞ ţŕ僃îç ţö ĤŢŢÞŠ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "[Ŕéðîŕéçţš îñţŕöðûçé åððîţîöñåļ ðéļåýš бéƒöŕé ţĥé þåĝé çåñ бé ļöåðéð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/redirects)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "[Åvöîð mûļţîþļé þåĝé ŕéðîŕéçţš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "[Ţö šéţ бûðĝéţš ƒöŕ ţĥé qûåñţîţý åñð šîžé öƒ þåĝé ŕéšöûŕçéš, åðð å бûðĝéţ.ĵšöñ ƒîļé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/web/tools/lighthouse/audits/budgets)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{[1 ŕéqûéšţ • ᐅ{byteCount, number, bytes}ᐊ ĶБ one two three four]}other{[# ŕéqûéšţš • ᐅ{byteCount, number, bytes}ᐊ ĶБ one two three four]}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "[Ķééþ ŕéqûéšţ çöûñţš ļöŵ åñð ţŕåñšƒéŕ šîžéš šmåļļ one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "[Çåñöñîçåļ ļîñķš šûĝĝéšţ ŵĥîçĥ ÛŔĻ ţö šĥöŵ îñ šéåŕçĥ ŕéšûļţš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/canonical)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "[Mûļţîþļé çöñƒļîçţîñĝ ÛŔĻš (ᐅ{urlList}ᐊ) one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "[Þöîñţš ţö å ðéŕéñţ ðömåîñ (ᐅ{url}ᐊ) one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "[Îñvåļîð ÛŔĻ (ᐅ{url}ᐊ) one two three four]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "[Þöîñţš ţö åñöţĥéŕ ᐅ`hreflang`ᐊ ļöçåţîöñ (ᐅ{url}ᐊ) one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "[Ŕéļåţîvé ÛŔĻ (ᐅ{url}ᐊ) one two three four]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "[Þöîñţš ţö ţĥé ðömåîñ'š ŕööţ ÛŔĻ (ţĥé ĥöméþåĝé), îñšţéåð öƒ åñ éqûîvåļéñţ þåĝé öƒ çöñţéñţ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "[Ðöçûméñţ ðöéš ñöţ ĥåvé å våļîð ᐅ`rel=canonical`ᐊ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "[Ðöçûméñţ ĥåš å våļîð ᐅ`rel=canonical`ᐊ one two three four five]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "[Föñţ šîžéš ļéšš ţĥåñ 12þx åŕé ţöö šmåļļ ţö бé ļéĝîбļé åñð ŕéqûîŕé möбîļé vîšîţöŕš ţö “þîñçĥ ţö žööm” îñ öŕðéŕ ţö ŕéåð. Šţŕîvé ţö ĥåvé >60% oƒ þåĝé ţéxţ ≥12þx. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/font-size)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "[ᐅ{decimalProportion, number, extendedPercent}ᐊ ļéĝîбļé ţéxţ one two three four]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "[Ţéxţ îš îļļéĝîбļé бéçåûšé ţĥéŕé'š ñö vîéŵþöŕţ méţå ţåĝ öþţîmîžéð ƒöŕ möбîļé šçŕééñš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "[ᐅ{decimalProportion, number, extendedPercent}ᐊ öƒ ţéxţ îš ţöö šmåļļ (бåšéð öñ ᐅ{decimalProportionVisited, number, extendedPercent}ᐊ šåmþļé). one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "[Ðöçûméñţ ðöéšñ'ţ ûšé ļéĝîбļé ƒöñţ šîžéš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "[Ðöçûméñţ ûšéš ļéĝîбļé ƒöñţ šîžéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "[ĥŕéƒļåñĝ ļîñķš ţéļļ šéåŕçĥ éñĝîñéš ŵĥåţ véŕšîöñ öƒ å þåĝé ţĥéý šĥöûļð ļîšţ îñ šéåŕçĥ ŕéšûļţš ƒöŕ å ĝîvéñ ļåñĝûåĝé öŕ ŕéĝîöñ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/hreflang)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "[Ðöçûméñţ ðöéšñ'ţ ĥåvé å våļîð ᐅ`hreflang`ᐊ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "[Ðöçûméñţ ĥåš å våļîð ᐅ`hreflang`ᐊ one two three four five]"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "[Þåĝéš ŵîţĥ ûñšûççéššƒûļ ĤŢŢÞ šţåţûš çöðéš måý ñöţ бé îñðéxéð þŕöþéŕļý. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/http-status-code)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "[Þåĝé ĥåš ûñšûççéššƒûļ ĤŢŢÞ šţåţûš çöðé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "[Þåĝé ĥåš šûççéššƒûļ ĤŢŢÞ šţåţûš çöðé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "[Šéåŕçĥ éñĝîñéš åŕé ûñåбļé ţö îñçļûðé ýöûŕ þåĝéš îñ šéåŕçĥ ŕéšûļţš îƒ ţĥéý ðöñ'ţ ĥåvé þéŕmîššîöñ ţö çŕåŵļ ţĥém. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/is-crawable)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "[Þåĝé îš бļöçķéð ƒŕöm îñðéxîñĝ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "[Þåĝé îšñ’ţ бļöçķéð ƒŕöm îñðéxîñĝ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "[Ðéšçŕîþţîvé ļîñķ ţéxţ ĥéļþš šéåŕçĥ éñĝîñéš ûñðéŕšţåñð ýöûŕ çöñţéñţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/link-text)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 ļîñķ ƒöûñð one two]}other{[# ļîñķš ƒöûñð one two]}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "[Ļîñķš ðö ñöţ ĥåvé ðéšçŕîþţîvé ţéxţ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "[Ļîñķš ĥåvé ðéšçŕîþţîvé ţéxţ one two three four five six]"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "[Ŕûñ ţĥé ᐅ[ᐊŠţŕûçţûŕéð Ðåţå Ţéšţîñĝ Ţööļᐅ](https://search.google.com/structured-data/testing-tool/)ᐊ åñð ţĥé ᐅ[ᐊŠţŕûçţûŕéð Ðåţå Ļîñţéŕᐅ](http://linter.structured-data.org/)ᐊ ţö våļîðåţé šţŕûçţûŕéð ðåţå. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/structured-data)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "[Šţŕûçţûŕéð ðåţå îš våļîð one two three four five]"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "[Méţå ðéšçŕîþţîöñš måý бé îñçļûðéð îñ šéåŕçĥ ŕéšûļţš ţö çöñçîšéļý šûmmåŕîžé þåĝé çöñţéñţ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/meta-description)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "[Ðéšçŕîþţîöñ ţéxţ îš émþţý. one two three four five six]"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "[Ðöçûméñţ ðöéš ñöţ ĥåvé å méţå ðéšçŕîþţîöñ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "[Ðöçûméñţ ĥåš å méţå ðéšçŕîþţîöñ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "[Šéåŕçĥ éñĝîñéš çåñ'ţ îñðéx þļûĝîñ çöñţéñţ, åñð måñý ðévîçéš ŕéšţŕîçţ þļûĝîñš öŕ ðöñ'ţ šûþþöŕţ ţĥém. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/plugins)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "[Ðöçûméñţ ûšéš þļûĝîñš one two three]"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "[Ðöçûméñţ åvöîðš þļûĝîñš one two three]"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "[΃ ýöûŕ ŕöбöţš.ţxţ ƒîļé îš måļƒöŕméð, çŕåŵļéŕš måý ñöţ бé åбļé ţö ûñðéŕšţåñð ĥöŵ ýöû ŵåñţ ýöûŕ ŵéбšîţé ţö бé çŕåŵļéð öŕ îñðéxéð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/robots-txt)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "[Ŕéqûéšţ ƒöŕ ŕöбöţš.ţxţ ŕéţûŕñéð ĤŢŢÞ šţåţûš: ᐅ{statusCode}ᐊ one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{[1 éŕŕöŕ ƒöûñð one two]}other{[# éŕŕöŕš ƒöûñð one two]}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö ðöŵñļöåð å ŕöбöţš.ţxţ ƒîļé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "[ŕöбöţš.ţxţ îš ñöţ våļîð one two three four five]"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "[ŕöбöţš.ţxţ îš våļîð one two three]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "[Îñţéŕåçţîvé éļéméñţš ļîķé бûţţöñš åñð ļîñķš šĥöûļð бé ļåŕĝé éñöûĝĥ (48x48þx), åñð ĥåvé éñöûĝĥ šþåçé åŕöûñð ţĥém, ţö бé éåšý éñöûĝĥ ţö ţåþ ŵîţĥöûţ övéŕļåþþîñĝ öñţö öţĥéŕ éļéméñţš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/tap-targets)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "[ᐅ{decimalProportion, number, percent}ᐊ åþþŕöþŕîåţéļý šîžéð ţåþ ţåŕĝéţš one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "[Ţåþ ţåŕĝéţš åŕé ţöö šmåļļ бéçåûšé ţĥéŕé'š ñö vîéŵþöŕţ méţå ţåĝ öþţîmîžéð ƒöŕ möбîļé šçŕééñš one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "[Ţåþ ţåŕĝéţš åŕé ñöţ šîžéð åþþŕöþŕîåţéļý one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "[Övéŕļåþþîñĝ Ţåŕĝéţ one two three]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "[Ţåþ Ţåŕĝéţ one two]"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "[Ţåþ ţåŕĝéţš åŕé šîžéð åþþŕöþŕîåţéļý one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "[Ţĥé šéŕvîçé ŵöŕķéŕ îš ţĥé ţéçĥñöļöĝý ţĥåţ éñåбļéš ýöûŕ åþþ ţö ûšé måñý Þŕöĝŕéššîvé Ŵéб Åþþ ƒéåţûŕéš, šûçĥ åš öƒƒļîñé, åðð ţö ĥöméšçŕééñ, åñð þûšĥ ñöţîƒîçåţîöñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/service-worker)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "[Ţĥîš þåĝé îš çöñţŕöļļéð бý å šéŕvîçé ŵöŕķéŕ, ĥöŵévéŕ ñö ᐅ`start_url`ᐊ ŵåš ƒöûñð бéçåûšé måñîƒéšţ ƒåîļéð ţö þåŕšé åš våļîð ĴŠÖÑ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "[Ţĥîš þåĝé îš çöñţŕöļļéð бý å šéŕvîçé ŵöŕķéŕ, ĥöŵévéŕ ţĥé ᐅ`start_url`ᐊ (ᐅ{startUrl}ᐊ) îš ñöţ îñ ţĥé šéŕvîçé ŵöŕķéŕ'š šçöþé (ᐅ{scopeUrl}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "[Ţĥîš þåĝé îš çöñţŕöļļéð бý å šéŕvîçé ŵöŕķéŕ, ĥöŵévéŕ ñö ᐅ`start_url`ᐊ ŵåš ƒöûñð бéçåûšé ñö måñîƒéšţ ŵåš ƒéţçĥéð. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "[Ţĥîš öŕîĝîñ ĥåš öñé öŕ möŕé šéŕvîçé ŵöŕķéŕš, ĥöŵévéŕ ţĥé þåĝé (ᐅ{pageUrl}ᐊ) îš ñöţ îñ šçöþé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ŕéĝîšţéŕ å šéŕvîçé ŵöŕķéŕ ţĥåţ çöñţŕöļš þåĝé åñð ᐅ`start_url`ᐊ one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "[Ŕéĝîšţéŕš å šéŕvîçé ŵöŕķéŕ ţĥåţ çöñţŕöļš þåĝé åñð ᐅ`start_url`ᐊ one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "[Å ţĥéméð šþļåšĥ šçŕééñ éñšûŕéš å ĥîĝĥ-qûåļîţý éxþéŕîéñçé ŵĥéñ ûšéŕš ļåûñçĥ ýöûŕ åþþ ƒŕöm ţĥéîŕ ĥöméšçŕééñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/splash-screen)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "[Κ ñöţ çöñƒîĝûŕéð ƒöŕ å çûšţöm šþļåšĥ šçŕééñ one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "[Çöñƒîĝûŕéð ƒöŕ å çûšţöm šþļåšĥ šçŕééñ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "[Ţĥé бŕöŵšéŕ åððŕéšš бåŕ çåñ бé ţĥéméð ţö måţçĥ ýöûŕ šîţé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/themed-omnibox)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "[Ðöéš ñöţ šéţ å ţĥémé çöļöŕ ƒöŕ ţĥé åððŕéšš бåŕ. one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "[Šéţš å ţĥémé çöļöŕ ƒöŕ ţĥé åððŕéšš бåŕ. one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "[Måîñ-Ţĥŕéåð Бļöçķîñĝ Ţîmé one two three]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "[Ţĥîŕð-Þåŕţý one two]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "[Ţĥîŕð-þåŕţý çöðé çåñ šîĝñîƒîçåñţļý îmþåçţ ļöåð þéŕƒöŕmåñçé. Ļîmîţ ţĥé ñûmбéŕ öƒ ŕéðûñðåñţ ţĥîŕð-þåŕţý þŕövîðéŕš åñð ţŕý ţö ļöåð ţĥîŕð-þåŕţý çöðé åƒţéŕ ýöûŕ þåĝé ĥåš þŕîmåŕîļý ƒîñîšĥéð ļöåðîñĝ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "[Ţĥîŕð-þåŕţý çöðé бļöçķéð ţĥé måîñ ţĥŕéåð ƒöŕ ᐅ{timeInMs, number, milliseconds}ᐊ mš one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "[Ŕéðûçé ţĥé îmþåçţ öƒ ţĥîŕð-þåŕţý çöðé one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "[Ţĥîŕð-Þåŕţý ûšåĝé one two three]"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "[Ţîmé Ţö Fîŕšţ Бýţé îðéñţîƒîéš ţĥé ţîmé åţ ŵĥîçĥ ýöûŕ šéŕvéŕ šéñðš å ŕéšþöñšé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/time-to-first-byte)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "[Ŕööţ ðöçûméñţ ţööķ ᐅ{timeInMs, number, milliseconds}ᐊ mš one two three four five six]"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "[Ŕéðûçé šéŕvéŕ ŕéšþöñšé ţîméš (ŢŢFБ) one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "[Šéŕvéŕ ŕéšþöñšé ţîméš åŕé ļöŵ (ŢŢFБ) one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "[Ðûŕåţîöñ one]"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "[Šţåŕţ Ţîmé one two]"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "[Ţýþé one]"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "[Çöñšîðéŕ îñšţŕûméñţîñĝ ýöûŕ åþþ ŵîţĥ ţĥé Ûšéŕ Ţîmîñĝ ÅÞÎ ţö méåšûŕé ýöûŕ åþþ'š ŕéåļ-ŵöŕļð þéŕƒöŕmåñçé ðûŕîñĝ ķéý ûšéŕ éxþéŕîéñçéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/user-timings)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{[1 ûšéŕ ţîmîñĝ one two]}other{[# ûšéŕ ţîmîñĝš one two]}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "[Ûšéŕ Ţîmîñĝ måŕķš åñð méåšûŕéš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "[Å þŕéçöññéçţ <link> ŵåš ƒöûñð ƒöŕ \"ᐅ{securityOrigin}ᐊ\" бûţ ŵåš ñöţ ûšéð бý ţĥé бŕöŵšéŕ. Çĥéçķ ţĥåţ ýöû åŕé ûšîñĝ ţĥé ᐅ`crossorigin`ᐊ åţţŕîбûţé þŕöþéŕļý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "[Çöñšîðéŕ åððîñĝ ᐅ`preconnect`ᐊ öŕ ᐅ`dns-prefetch`ᐊ ŕéšöûŕçé ĥîñţš ţö éšţåбļîšĥ éåŕļý çöññéçţîöñš ţö îmþöŕţåñţ ţĥîŕð-þåŕţý öŕîĝîñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-rel-preconnect)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "[Þŕéçöññéçţ ţö ŕéqûîŕéð öŕîĝîñš one two three four five six seven]"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "[Å þŕéļöåð <link> ŵåš ƒöûñð ƒöŕ \"ᐅ{preloadURL}ᐊ\" бûţ ŵåš ñöţ ûšéð бý ţĥé бŕöŵšéŕ. Çĥéçķ ţĥåţ ýöû åŕé ûšîñĝ ţĥé ᐅ`crossorigin`ᐊ åţţŕîбûţé þŕöþéŕļý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "[Çöñšîðéŕ ûšîñĝ ᐅ`<link rel=preload>`ᐊ ţö þŕîöŕîţîžé ƒéţçĥîñĝ ŕéšöûŕçéš ţĥåţ åŕé çûŕŕéñţļý ŕéqûéšţéð ļåţéŕ îñ þåĝé ļöåð. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/uses-rel-preload)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "[Þŕéļöåð ķéý ŕéqûéšţš one two three]"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "[Åðð å ᐅ`<meta name=\"viewport\">`ᐊ ţåĝ ţö öþţîmîžé ýöûŕ åþþ ƒöŕ möбîļé šçŕééñš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/viewport)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "[Ñö ᐅ`<meta name=\"viewport\">`ᐊ ţåĝ ƒöûñð one two three four]"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "[Ðöéš ñöţ ĥåvé å ᐅ`<meta name=\"viewport\">`ᐊ ţåĝ ŵîţĥ ᐅ`width`ᐊ öŕ ᐅ`initial-scale`ᐊ one two three four five six seven eight]"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "[Ĥåš å ᐅ`<meta name=\"viewport\">`ᐊ ţåĝ ŵîţĥ ᐅ`width`ᐊ öŕ ᐅ`initial-scale`ᐊ one two three four five six seven]"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "[Ýöûŕ åþþ šĥöûļð ðîšþļåý šömé çöñţéñţ ŵĥéñ ĴåvåŠçŕîþţ îš ðîšåбļéð, évéñ îƒ îţ'š ĵûšţ å ŵåŕñîñĝ ţö ţĥé ûšéŕ ţĥåţ ĴåvåŠçŕîþţ îš ŕéqûîŕéð ţö ûšé ţĥé åþþ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/without-javascript)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "[Ţĥé þåĝé бöðý šĥöûļð ŕéñðéŕ šömé çöñţéñţ îƒ îţš šçŕîþţš åŕé ñöţ åvåîļåбļé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "[Ðöéš ñöţ þŕövîðé ƒåļļбåçķ çöñţéñţ ŵĥéñ ĴåvåŠçŕîþţ îš ñöţ åvåîļåбļé one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "[Çöñţåîñš šömé çöñţéñţ ŵĥéñ ĴåvåŠçŕîþţ îš ñöţ åvåîļåбļé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "[΃ ýöû'ŕé бûîļðîñĝ å Þŕöĝŕéššîvé Ŵéб Åþþ, çöñšîðéŕ ûšîñĝ å šéŕvîçé ŵöŕķéŕ šö ţĥåţ ýöûŕ åþþ çåñ ŵöŕķ öƒƒļîñé. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://web.dev/works-offline)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "[Çûŕŕéñţ þåĝé ðöéš ñöţ ŕéšþöñð ŵîţĥ å 200 ŵĥéñ öƒƒļîñé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "[Çûŕŕéñţ þåĝé ŕéšþöñðš ŵîţĥ å 200 ŵĥéñ öƒƒļîñé one two three four five six seven eight nine]"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "[Ţĥé þåĝé måý ñöţ бé ļöåðîñĝ öƒƒļîñé бéçåûšé ýöûŕ ţéšţ ÛŔĻ (ᐅ{requested}ᐊ) ŵåš ŕéðîŕéçţéð ţö \"ᐅ{final}ᐊ\". Ţŕý ţéšţîñĝ ţĥé šéçöñð ÛŔĻ ðîŕéçţļý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö îmþŕövé ţĥé ûšåĝé öƒ ÅŔÎÅ îñ ýöûŕ åþþļîçåţîöñ ŵĥîçĥ måý éñĥåñçé ţĥé éxþéŕîéñçé ƒöŕ ûšéŕš öƒ åššîšţîvé ţéçĥñöļöĝý, ļîķé å šçŕééñ ŕéåðéŕ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "[ÅŔÎÅ one]"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö þŕövîðé åļţéŕñåţîvé çöñţéñţ ƒöŕ åûðîö åñð vîðéö. Ţĥîš måý îmþŕövé ţĥé éxþéŕîéñçé ƒöŕ ûšéŕš ŵîţĥ ĥéåŕîñĝ öŕ vîšîöñ îmþåîŕméñţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "[Åûðîö åñð vîðéö one two]"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "[Ţĥéšé îţémš ĥîĝĥļîĝĥţ çömmöñ åççéššîбîļîţý бéšţ þŕåçţîçéš. one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "[Бéšţ þŕåçţîçéš one two]"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "[Ţĥéšé çĥéçķš ĥîĝĥļîĝĥţ öþþöŕţûñîţîéš ţö ᐅ[ᐊîmþŕövé ţĥé åççéššîбîļîţý öƒ ýöûŕ ŵéб åþþᐅ](https://developers.google.com/web/fundamentals/accessibility)ᐊ. Öñļý å šûбšéţ öƒ åççéššîбîļîţý îššûéš çåñ бé åûţömåţîçåļļý ðéţéçţéð šö måñûåļ ţéšţîñĝ îš åļšö éñçöûŕåĝéð. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "[Ţĥéšé îţémš åððŕéšš åŕéåš ŵĥîçĥ åñ åûţömåţéð ţéšţîñĝ ţööļ çåññöţ çövéŕ. Ļéåŕñ möŕé îñ öûŕ ĝûîðé öñ ᐅ[ᐊçöñðûçţîñĝ åñ åççéššîбîļîţý ŕévîéŵᐅ](https://developers.google.com/web/fundamentals/accessibility/how-to-review)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "[Åççéššîбîļîţý one two]"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö îmþŕövé ţĥé ļéĝîбîļîţý öƒ ýöûŕ çöñţéñţ. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "[Çöñţŕåšţ one]"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö îmþŕövé ţĥé îñţéŕþŕéţåţîöñ öƒ ýöûŕ çöñţéñţ бý ûšéŕš îñ ðéŕéñţ ļöçåļéš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "[Îñţéŕñåţîöñåļîžåţîöñ åñð ļöçåļîžåţîöñ one two three four]"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö îmþŕövé ţĥé šémåñţîçš öƒ ţĥé çöñţŕöļš îñ ýöûŕ åþþļîçåţîöñ. Ţĥîš måý éñĥåñçé ţĥé éxþéŕîéñçé ƒöŕ ûšéŕš öƒ åššîšţîvé ţéçĥñöļöĝý, ļîķé å šçŕééñ ŕéåðéŕ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour]"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "[Ñåméš åñð ļåбéļš one two]"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö îmþŕövé ķéýбöåŕð ñåvîĝåţîöñ îñ ýöûŕ åþþļîçåţîöñ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "[Ñåvîĝåţîöñ one two]"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "[Ţĥéšé åŕé öþþöŕţûñîţîéš ţö ţö îmþŕövé ţĥé éxþéŕîéñçé öƒ ŕéåðîñĝ ţåбûļåŕ öŕ ļîšţ ðåţå ûšîñĝ åššîšţîvé ţéçĥñöļöĝý, ļîķé å šçŕééñ ŕéåðéŕ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone]"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "[Ţåбļéš åñð ļîšţš one two]"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "[Бéšţ Þŕåçţîçéš one two]"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "[Þéŕƒöŕmåñçé бûðĝéţš šéţ šţåñðåŕðš ƒöŕ ţĥé þéŕƒöŕmåñçé öƒ ýöûŕ šîţé. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "[Бûðĝéţš one]"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "[Möŕé îñƒöŕmåţîöñ åбöûţ ţĥé þéŕƒöŕmåñçé öƒ ýöûŕ åþþļîçåţîöñ. Ţĥéšé ñûmбéŕš ðöñ'ţ ᐅ[ᐊðîŕéçţļý 僃éçţᐅ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)ᐊ ţĥé Þéŕƒöŕmåñçé šçöŕé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "[Ðîåĝñöšţîçš one two]"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "[Ţĥé möšţ çŕîţîçåļ åšþéçţ öƒ þéŕƒöŕmåñçé îš ĥöŵ qûîçķļý þîxéļš åŕé ŕéñðéŕéð öñšçŕééñ. Ķéý méţŕîçš: Fîŕšţ Çöñţéñţƒûļ Þåîñţ, Fîŕšţ Méåñîñĝƒûļ Þåîñţ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "[Fîŕšţ Þåîñţ Îmþŕövéméñţš one two three]"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "[Ţĥéšé šûĝĝéšţîöñš çåñ ĥéļþ ýöûŕ þåĝé ļöåð ƒåšţéŕ. Ţĥéý ðöñ'ţ ᐅ[ᐊðîŕéçţļý 僃éçţᐅ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)ᐊ ţĥé Þéŕƒöŕmåñçé šçöŕé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "[Öþþöŕţûñîţîéš one two]"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "[Méţŕîçš one]"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "[Éñĥåñçé ţĥé övéŕåļļ ļöåðîñĝ éxþéŕîéñçé, šö ţĥé þåĝé îš ŕéšþöñšîvé åñð ŕéåðý ţö ûšé åš šööñ åš þöššîбļé. Ķéý méţŕîçš: Ţîmé ţö Îñţéŕåçţîvé, Šþééð Îñðéx one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "[Övéŕåļļ Îmþŕövéméñţš one two three]"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "[Þéŕƒöŕmåñçé one two]"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "[Ţĥéšé çĥéçķš våļîðåţé ţĥé åšþéçţš öƒ å Þŕöĝŕéššîvé Ŵéб Åþþ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/web/progressive-web-apps/checklist)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "[Ţĥéšé çĥéçķš åŕé ŕéqûîŕéð бý ţĥé бåšéļîñé ᐅ[ᐊÞŴÅ Çĥéçķļîšţᐅ](https://developers.google.com/web/progressive-web-apps/checklist)ᐊ бûţ åŕé ñöţ åûţömåţîçåļļý çĥéçķéð бý Ļîĝĥţĥöûšé. Ţĥéý ðö ñöţ 僃éçţ ýöûŕ šçöŕé бûţ îţ'š îmþöŕţåñţ ţĥåţ ýöû véŕîƒý ţĥém måñûåļļý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "[Þŕöĝŕéššîvé Ŵéб Åþþ one two three]"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "[Fåšţ åñð ŕéļîåбļé one two three]"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "[Îñšţåļļåбļé one two]"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "[ÞŴÅ Öþţîmîžéð one two]"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "[Ţĥéšé çĥéçķš éñšûŕé ţĥåţ ýöûŕ þåĝé îš öþţîmîžéð ƒöŕ šéåŕçĥ éñĝîñé ŕéšûļţš ŕåñķîñĝ. Ţĥéŕé åŕé åððîţîöñåļ ƒåçţöŕš Ļîĝĥţĥöûšé ðöéš ñöţ çĥéçķ ţĥåţ måý 僃éçţ ýöûŕ šéåŕçĥ ŕåñķîñĝ. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://support.google.com/webmasters/answer/35769)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "[Ŕûñ ţĥéšé åððîţîöñåļ våļîðåţöŕš öñ ýöûŕ šîţé ţö çĥéçķ åððîţîöñåļ ŠÉÖ бéšţ þŕåçţîçéš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "[ŠÉÖ one]"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "[Föŕmåţ ýöûŕ ĤŢMĻ îñ å ŵåý ţĥåţ éñåбļéš çŕåŵļéŕš ţö бéţţéŕ ûñðéŕšţåñð ýöûŕ åþþ’š çöñţéñţ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "[Çöñţéñţ Бéšţ Þŕåçţîçéš one two three]"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "[Ţö åþþéåŕ îñ šéåŕçĥ ŕéšûļţš, çŕåŵļéŕš ñééð åççéšš ţö ýöûŕ åþþ. one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "[Çŕåŵļîñĝ åñð Îñðéxîñĝ one two three]"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "[Måķé šûŕé ýöûŕ þåĝéš åŕé möбîļé ƒŕîéñðļý šö ûšéŕš ðöñ’ţ ĥåvé ţö þîñçĥ öŕ žööm îñ öŕðéŕ ţö ŕéåð ţĥé çöñţéñţ þåĝéš. ᐅ[ᐊĻéåŕñ möŕéᐅ](https://developers.google.com/search/mobile-sites/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty]"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "[Möбîļé Fŕîéñðļý one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "[Çåçĥé ŢŢĻ one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "[Ļöçåţîöñ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "[Ñåmé one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "[Ŕéqûéšţš one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "[Ŕéšöûŕçé Ţýþé one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "[Šîžé one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "[Ţîmé Šþéñţ one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "[Ţŕåñšƒéŕ Šîžé one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "[ÛŔĻ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "[Þöţéñţîåļ Šåvîñĝš one two three]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "[Þöţéñţîåļ Šåvîñĝš one two three]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "[Þöţéñţîåļ šåvîñĝš öƒ ᐅ{wastedBytes, number, bytes}ᐊ ĶБ one two three four five six]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "[Þöţéñţîåļ šåvîñĝš öƒ ᐅ{wastedMs, number, milliseconds}ᐊ mš one two three four five six]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "[Ðöçûméñţ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "[Föñţ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "[Îmåĝé one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "[Méðîå one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "[ᐅ{timeInMs, number, milliseconds}ᐊ mš one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "[Öţĥéŕ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "[Šçŕîþţ one]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "[ᐅ{timeInMs, number, seconds}ᐊ š one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "[Šţýļéšĥééţ one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "[Ţĥîŕð-þåŕţý one two]"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "[Ţöţåļ one]"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "[Šöméţĥîñĝ ŵéñţ ŵŕöñĝ ŵîţĥ ŕéçöŕðîñĝ ţĥé ţŕåçé övéŕ ýöûŕ þåĝé ļöåð. Þļéåšé ŕûñ Ļîĝĥţĥöûšé åĝåîñ. (ᐅ{errorCode}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen]"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "[Ţîméöûţ ŵåîţîñĝ ƒöŕ îñîţîåļ Ðéбûĝĝéŕ Þŕöţöçöļ çöññéçţîöñ. one two three four five six seven eight nine ten eleven twelve]"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "[Çĥŕömé ðîðñ'ţ çöļļéçţ åñý šçŕééñšĥöţš ðûŕîñĝ ţĥé þåĝé ļöåð. Þļéåšé måķé šûŕé ţĥéŕé îš çöñţéñţ vîšîбļé öñ ţĥé þåĝé, åñð ţĥéñ ţŕý ŕé-ŕûññîñĝ Ļîĝĥţĥöûšé. (ᐅ{errorCode}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "[ÐÑŠ šéŕvéŕš çöûļð ñöţ ŕéšöļvé ţĥé þŕövîðéð ðömåîñ. one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "[Ŕéqûîŕéð ᐅ{artifactName}ᐊ ĝåţĥéŕéŕ éñçöûñţéŕéð åñ éŕŕöŕ: ᐅ{errorMessage}ᐊ one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "[Åñ îñţéŕñåļ Çĥŕömé éŕŕöŕ öççûŕŕéð. Þļéåšé ŕéšţåŕţ Çĥŕömé åñð ţŕý ŕé-ŕûññîñĝ Ļîĝĥţĥöûšé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "[Ŕéqûîŕéð ᐅ{artifactName}ᐊ ĝåţĥéŕéŕ ðîð ñöţ ŕûñ. one two three four five six seven]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö ŕéļîåбļý ļöåð ţĥé þåĝé ýöû ŕéqûéšţéð. Måķé šûŕé ýöû åŕé ţéšţîñĝ ţĥé çöŕŕéçţ ÛŔĻ åñð ţĥåţ ţĥé šéŕvéŕ îš þŕöþéŕļý ŕéšþöñðîñĝ ţö åļļ ŕéqûéšţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö ŕéļîåбļý ļöåð ţĥé ÛŔĻ ýöû ŕéqûéšţéð бéçåûšé ţĥé þåĝé šţöþþéð ŕéšþöñðîñĝ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "[Ţĥé ÛŔĻ ýöû ĥåvé þŕövîðéð ðöéš ñöţ ĥåvé å våļîð šéçûŕîţý çéŕţîƒîçåţé. ᐅ{securityMessages}ᐊ one two three four five six seven eight nine ten eleven twelve thirteen fourteen]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "[Çĥŕömé þŕévéñţéð þåĝé ļöåð ŵîţĥ åñ îñţéŕšţîţîåļ. Måķé šûŕé ýöû åŕé ţéšţîñĝ ţĥé çöŕŕéçţ ÛŔĻ åñð ţĥåţ ţĥé šéŕvéŕ îš þŕöþéŕļý ŕéšþöñðîñĝ ţö åļļ ŕéqûéšţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö ŕéļîåбļý ļöåð ţĥé þåĝé ýöû ŕéqûéšţéð. Måķé šûŕé ýöû åŕé ţéšţîñĝ ţĥé çöŕŕéçţ ÛŔĻ åñð ţĥåţ ţĥé šéŕvéŕ îš þŕöþéŕļý ŕéšþöñðîñĝ ţö åļļ ŕéqûéšţš. (Ðéţåîļš: ᐅ{errorDetails}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "[Ļîĝĥţĥöûšé ŵåš ûñåбļé ţö ŕéļîåбļý ļöåð ţĥé þåĝé ýöû ŕéqûéšţéð. Måķé šûŕé ýöû åŕé ţéšţîñĝ ţĥé çöŕŕéçţ ÛŔĻ åñð ţĥåţ ţĥé šéŕvéŕ îš þŕöþéŕļý ŕéšþöñðîñĝ ţö åļļ ŕéqûéšţš. (Šţåţûš çöðé: ᐅ{statusCode}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive]"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "[Ýöûŕ þåĝé ţööķ ţöö ļöñĝ ţö ļöåð. Þļéåšé ƒöļļöŵ ţĥé öþþöŕţûñîţîéš îñ ţĥé ŕéþöŕţ ţö ŕéðûçé ýöûŕ þåĝé ļöåð ţîmé, åñð ţĥéñ ţŕý ŕé-ŕûññîñĝ Ļîĝĥţĥöûšé. (ᐅ{errorCode}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo]"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "[Ŵåîţîñĝ ƒöŕ ÐévŢööļš þŕöţöçöļ ŕéšþöñšé ĥåš éxçééðéð ţĥé åļļöţţéð ţîmé. (Méţĥöð: ᐅ{protocolMethod}ᐊ) one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen]"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "[Féţçĥîñĝ ŕéšöûŕçé çöñţéñţ ĥåš éxçééðéð ţĥé åļļöţţéð ţîmé one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "[Ţĥé ÛŔĻ ýöû ĥåvé þŕövîðéð åþþéåŕš ţö бé îñvåļîð. one two three four five six seven eight nine ten]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "[Šĥöŵ åûðîţš one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "[Îñîţîåļ Ñåvîĝåţîöñ one two three]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "[Måxîmûm çŕîţîçåļ þåţĥ ļåţéñçý: one two three four five six seven]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "[Éŕŕöŕ¡ one]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "[Ŕéþöŕţ éŕŕöŕ: ñö åûðîţ îñƒöŕmåţîöñ one two three four five six seven]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "[Ļåб Ðåţå one]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[ᐅ[ᐊĻîĝĥţĥöûšéᐅ](https://developers.google.com/web/tools/lighthouse/)ᐊ åñåļýšîš öƒ ţĥé çûŕŕéñţ þåĝé öñ åñ émûļåţéð möбîļé ñéţŵöŕķ. Våļûéš åŕé éšţîmåţéð åñð måý våŕý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "[Åððîţîöñåļ îţémš ţö måñûåļļý çĥéçķ one two three four five six seven]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "[Ñöţ åþþļîçåбļé one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "[Öþþöŕţûñîţý one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "[Éšţîmåţéð Šåvîñĝš one two three]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "[Þåššéð åûðîţš one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "[Çöļļåþšé šñîþþéţ one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "[Éxþåñð šñîþþéţ one two]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "[Šĥöŵ 3ŕð-þåŕţý ŕéšöûŕçéš one two three]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "[Ţĥéŕé ŵéŕé îššûéš åƒƒéçţîñĝ ţĥîš ŕûñ öƒ Ļîĝĥţĥöûšé: one two three four five six seven eight nine ten eleven]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "[Våļûéš åŕé éšţîmåţéð åñð måý våŕý. Ţĥé þéŕƒöŕmåñçé šçöŕé îš ᐅ[ᐊбåšéð öñļý öñ ţĥéšé méţŕîçšᐅ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "[Þåššéð åûðîţš бûţ ŵîţĥ ŵåŕñîñĝš one two three four five six seven]"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "[Ŵåŕñîñĝš: one two]"
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "[Çöñšîðéŕ ûþļöåðîñĝ ýöûŕ ĜÎF ţö å šéŕvîçé ŵĥîçĥ ŵîļļ måķé îţ åvåîļåбļé ţö émбéð åš åñ ĤŢMĻ5 vîðéö. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "[Îñšţåļļ å ᐅ[ᐊļåžý-ļöåð ŴöŕðÞŕéšš þļûĝîñᐅ](https://wordpress.org/plugins/search/lazy+load/)ᐊ ţĥåţ þŕövîðéš ţĥé åбîļîţý ţö ðéƒéŕ åñý öƒƒšçŕééñ îmåĝéš, öŕ šŵîţçĥ ţö å ţĥémé ţĥåţ þŕövîðéš ţĥåţ ƒûñçţîöñåļîţý. Åļšö çöñšîðéŕ ûšîñĝ ᐅ[ᐊţĥé ÅMÞ þļûĝîñᐅ](https://wordpress.org/plugins/amp/)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix]"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[Ţĥéŕé åŕé å ñûmбéŕ öƒ ŴöŕðÞŕéšš þļûĝîñš ţĥåţ çåñ ĥéļþ ýöû ᐅ[ᐊîñļîñé çŕîţîçåļ åššéţšᐅ](https://wordpress.org/plugins/search/critical+css/)ᐊ öŕ ᐅ[ᐊðéƒéŕ ļéšš îmþöŕţåñţ ŕéšöûŕçéšᐅ](https://wordpress.org/plugins/search/defer+css+javascript/)ᐊ. Бéŵåŕé ţĥåţ öþţîmîžåţîöñš þŕövîðéð бý ţĥéšé þļûĝîñš måý бŕéåķ ƒéåţûŕéš öƒ ýöûŕ ţĥémé öŕ þļûĝîñš, šö ýöû ŵîļļ ļîķéļý ñééð ţö måķé çöðé çĥåñĝéš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree]"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "[Ţĥéméš, þļûĝîñš, åñð šéŕvéŕ šþéçîƒîçåţîöñš åļļ çöñţŕîбûţé ţö šéŕvéŕ ŕéšþöñšé ţîmé. Çöñšîðéŕ ƒîñðîñĝ å möŕé öþţîmîžéð ţĥémé, çåŕéƒûļļý šéļéçţîñĝ åñ öþţîmîžåţîöñ þļûĝîñ, åñð/öŕ ûþĝŕåðîñĝ ýöûŕ šéŕvéŕ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "[Çöñšîðéŕ šĥöŵîñĝ éxçéŕþţš îñ ýöûŕ þöšţ ļîšţš (é.ĝ. vîå ţĥé möŕé ţåĝ), ŕéðûçîñĝ ţĥé ñûmбéŕ öƒ þöšţš šĥöŵñ öñ å ĝîvéñ þåĝé, бŕéåķîñĝ ýöûŕ ļöñĝ þöšţš îñţö mûļţîþļé þåĝéš, öŕ ûšîñĝ å þļûĝîñ ţö ļåžý-ļöåð çömméñţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "[Å ñûmбéŕ öƒ ᐅ[ᐊŴöŕðÞŕéšš þļûĝîñšᐅ](https://wordpress.org/plugins/search/minify+css/)ᐊ çåñ šþééð ûþ ýöûŕ šîţé бý çöñçåţéñåţîñĝ, mîñîƒýîñĝ, åñð çömþŕéššîñĝ ýöûŕ šţýļéš. Ýöû måý åļšö ŵåñţ ţö ûšé å бûîļð þŕöçéšš ţö ðö ţĥîš mîñîƒîçåţîöñ ûþ-ƒŕöñţ îƒ þöššîбļé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "[Å ñûmбéŕ öƒ ᐅ[ᐊŴöŕðÞŕéšš þļûĝîñšᐅ](https://wordpress.org/plugins/search/minify+javascript/)ᐊ çåñ šþééð ûþ ýöûŕ šîţé бý çöñçåţéñåţîñĝ, mîñîƒýîñĝ, åñð çömþŕéššîñĝ ýöûŕ šçŕîþţš. Ýöû måý åļšö ŵåñţ ţö ûšé å бûîļð þŕöçéšš ţö ðö ţĥîš mîñîƒîçåţîöñ ûþ ƒŕöñţ îƒ þöššîбļé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven]"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "[Çöñšîðéŕ ŕéðûçîñĝ, öŕ šŵîţçĥîñĝ, ţĥé ñûmбéŕ öƒ ᐅ[ᐊŴöŕðÞŕéšš þļûĝîñšᐅ](https://wordpress.org/plugins/)ᐊ ļöåðîñĝ ûñûšéð ÇŠŠ îñ ýöûŕ þåĝé. Ţö îðéñţîƒý þļûĝîñš ţĥåţ åŕé åððîñĝ éxţŕåñéöûš ÇŠŠ, ţŕý ŕûññîñĝ ᐅ[ᐊçöðé çövéŕåĝéᐅ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)ᐊ îñ Çĥŕömé ÐévŢööļš. Ýöû çåñ îðéñţîƒý ţĥé ţĥémé/þļûĝîñ ŕéšþöñšîбļé ƒŕöm ţĥé ÛŔĻ öƒ ţĥé šţýļéšĥééţ. Ļööķ öûţ ƒöŕ þļûĝîñš ţĥåţ ĥåvé måñý šţýļéšĥééţš îñ ţĥé ļîšţ ŵĥîçĥ ĥåvé å ļöţ öƒ ŕéð îñ çöðé çövéŕåĝé. Å þļûĝîñ šĥöûļð öñļý éñqûéûé å šţýļéšĥééţ îƒ îţ îš åçţûåļļý ûšéð öñ ţĥé þåĝé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix thirtyseven thirtyeight thirtynine forty one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "[Çöñšîðéŕ ŕéðûçîñĝ, öŕ šŵîţçĥîñĝ, ţĥé ñûmбéŕ öƒ ᐅ[ᐊŴöŕðÞŕéšš þļûĝîñšᐅ](https://wordpress.org/plugins/)ᐊ ļöåðîñĝ ûñûšéð ĴåvåŠçŕîþţ îñ ýöûŕ þåĝé. Ţö îðéñţîƒý þļûĝîñš ţĥåţ åŕé åððîñĝ éxţŕåñéöûš ĴŠ, ţŕý ŕûññîñĝ ᐅ[ᐊçöðé çövéŕåĝéᐅ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)ᐊ îñ Çĥŕömé ÐévŢööļš. Ýöû çåñ îðéñţîƒý ţĥé ţĥémé/þļûĝîñ ŕéšþöñšîбļé ƒŕöm ţĥé ÛŔĻ öƒ ţĥé šçŕîþţ. Ļööķ öûţ ƒöŕ þļûĝîñš ţĥåţ ĥåvé måñý šçŕîþţš îñ ţĥé ļîšţ ŵĥîçĥ ĥåvé å ļöţ öƒ ŕéð îñ çöðé çövéŕåĝé. Å þļûĝîñ šĥöûļð öñļý éñqûéûé å šçŕîþţ îƒ îţ îš åçţûåļļý ûšéð öñ ţĥé þåĝé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix thirtyseven thirtyeight thirtynine forty one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[Ŕéåð åбöûţ ᐅ[ᐊБŕöŵšéŕ Çåçĥîñĝ îñ ŴöŕðÞŕéššᐅ](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)ᐊ. one two three four five six seven eight nine ten]"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "[Çöñšîðéŕ ûšîñĝ åñ ᐅ[ᐊîmåĝé öþţîmîžåţîöñ ŴöŕðÞŕéšš þļûĝîñᐅ](https://wordpress.org/plugins/search/optimize+images/)ᐊ ţĥåţ çömþŕéššéš ýöûŕ îmåĝéš ŵĥîļé ŕéţåîñîñĝ qûåļîţý. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen]"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "[Ûþļöåð îmåĝéš ðîŕéçţļý ţĥŕöûĝĥ ţĥé ᐅ[ᐊméðîå ļîбŕåŕýᐅ](https://codex.wordpress.org/Media_Library_Screen)ᐊ ţö éñšûŕé ţĥåţ ţĥé ŕéqûîŕéð îmåĝé šîžéš åŕé åvåîļåбļé, åñð ţĥéñ îñšéŕţ ţĥém ƒŕöm ţĥé méðîå ļîбŕåŕý öŕ ûšé ţĥé îmåĝé ŵîðĝéţ ţö éñšûŕé ţĥé öþţîmåļ îmåĝé šîžéš åŕé ûšéð (îñçļûðîñĝ ţĥöšé ƒöŕ ţĥé ŕéšþöñšîvé бŕéåķþöîñţš). Åvöîð ûšîñĝ ᐅ`Full Size`ᐊ îmåĝéš ûñļéšš ţĥé ðîméñšîöñš åŕé åðéqûåţé ƒöŕ ţĥéîŕ ûšåĝé. ᐅ[ᐊĻéåŕñ Möŕéᐅ](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)ᐊ. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twentyone twentytwo twentythree twentyfour twentyfive twentysix twentyseven twentyeight twentynine thirty thirtyone thirtytwo thirtythree thirtyfour thirtyfive thirtysix thirtyseven thirtyeight thirtynine forty one two three four five]"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "[Ýöû çåñ éñåбļé ţéxţ çömþŕéššîöñ îñ ýöûŕ ŵéб šéŕvéŕ çöñƒîĝûŕåţîöñ. one two three four five six seven eight nine ten eleven twelve thirteen]"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "[Çöñšîðéŕ ûšîñĝ å ᐅ[ᐊþļûĝîñᐅ](https://wordpress.org/plugins/search/convert+webp/)ᐊ öŕ šéŕvîçé ţĥåţ ŵîļļ åûţömåţîçåļļý çöñvéŕţ ýöûŕ ûþļöåðéð îmåĝéš ţö ţĥé öþţîmåļ ƒöŕmåţš. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XL.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XL.json
new file mode 100644
index 00000000000..cec5605f18e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/en-XL.json
@@ -0,0 +1,1634 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Âćĉéŝś k̂éŷś l̂ét̂ úŝér̂ś q̂úîćk̂ĺŷ f́ôćûś â ṕâŕt̂ óf̂ t́ĥé p̂áĝé. F̂ór̂ ṕr̂óp̂ér̂ ńâv́îǵât́îón̂, éâćĥ áĉćêśŝ ḱêý m̂úŝt́ b̂é ûńîq́ûé. [L̂éâŕn̂ ḿôŕê](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` v̂ál̂úêś âŕê ńôt́ ûńîq́ûé"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` v̂ál̂úêś âŕê ún̂íq̂úê"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Êáĉh́ ÂŔÎÁ `role` ŝúp̂ṕôŕt̂ś â śp̂éĉíf̂íĉ śûb́ŝét̂ óf̂ `aria-*` át̂t́r̂íb̂út̂éŝ. Ḿîśm̂át̂ćĥín̂ǵ t̂h́êśê ín̂v́âĺîd́ât́êś t̂h́ê `aria-*` át̂t́r̂íb̂út̂éŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś d̂ó n̂ót̂ ḿât́ĉh́ t̂h́êír̂ ŕôĺêś"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś m̂át̂ćĥ t́ĥéîŕ r̂ól̂éŝ"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Ŝóm̂é ÂŔÎÁ r̂ól̂éŝ h́âv́ê ŕêq́ûír̂éd̂ át̂t́r̂íb̂út̂éŝ t́ĥát̂ d́êśĉŕîb́ê t́ĥé ŝt́ât́ê óf̂ t́ĥé êĺêḿêńt̂ t́ô śĉŕêén̂ ŕêád̂ér̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`ŝ d́ô ńôt́ ĥáv̂é âĺl̂ ŕêq́ûír̂éd̂ `[aria-*]` át̂t́r̂íb̂út̂éŝ"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`ŝ h́âv́ê ál̂ĺ r̂éq̂úîŕêd́ `[aria-*]` ât́t̂ŕîb́ût́êś"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Ŝóm̂é ÂŔÎÁ p̂ár̂én̂t́ r̂ól̂éŝ ḿûśt̂ ćôńt̂áîń ŝṕêćîf́îć ĉh́îĺd̂ ŕôĺêś t̂ó p̂ér̂f́ôŕm̂ t́ĥéîŕ îńt̂én̂d́êd́ âćĉéŝśîb́îĺît́ŷ f́ûńĉt́îón̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Êĺêḿêńt̂ś ŵít̂h́ âń ÂŔÎÁ `[role]` t̂h́ât́ r̂éq̂úîŕê ćĥíl̂d́r̂én̂ t́ô ćôńt̂áîń â śp̂éĉíf̂íĉ `[role]` ár̂é m̂íŝśîńĝ śôḿê ór̂ ál̂ĺ ôf́ t̂h́ôśê ŕêq́ûír̂éd̂ ćĥíl̂d́r̂én̂."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Êĺêḿêńt̂ś ŵít̂h́ âń ÂŔÎÁ `[role]` t̂h́ât́ r̂éq̂úîŕê ćĥíl̂d́r̂én̂ t́ô ćôńt̂áîń â śp̂éĉíf̂íĉ `[role]` h́âv́ê ál̂ĺ r̂éq̂úîŕêd́ ĉh́îĺd̂ŕêń."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Ŝóm̂é ÂŔÎÁ ĉh́îĺd̂ ŕôĺêś m̂úŝt́ b̂é ĉón̂t́âín̂éd̂ b́ŷ śp̂éĉíf̂íĉ ṕâŕêńt̂ ŕôĺêś t̂ó p̂ŕôṕêŕl̂ý p̂ér̂f́ôŕm̂ t́ĥéîŕ îńt̂én̂d́êd́ âćĉéŝśîb́îĺît́ŷ f́ûńĉt́îón̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`ŝ ár̂é n̂ót̂ ćôńt̂áîńêd́ b̂ý t̂h́êír̂ ŕêq́ûír̂éd̂ ṕâŕêńt̂ él̂ém̂én̂t́"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`ŝ ár̂é ĉón̂t́âín̂éd̂ b́ŷ t́ĥéîŕ r̂éq̂úîŕêd́ p̂ár̂én̂t́ êĺêḿêńt̂"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ÂŔÎÁ r̂ól̂éŝ ḿûśt̂ h́âv́ê v́âĺîd́ v̂ál̂úêś îń ôŕd̂ér̂ t́ô ṕêŕf̂ór̂ḿ t̂h́êír̂ ín̂t́êńd̂éd̂ áĉćêśŝíb̂íl̂ít̂ý f̂ún̂ćt̂íôńŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` v̂ál̂úêś âŕê ńôt́ v̂ál̂íd̂"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` v̂ál̂úêś âŕê v́âĺîd́"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Âśŝíŝt́îv́ê t́êćĥńôĺôǵîéŝ, ĺîḱê śĉŕêén̂ ŕêád̂ér̂ś, ĉán̂'t́ îńt̂ér̂ṕr̂ét̂ ÁR̂ÍÂ át̂t́r̂íb̂út̂éŝ ẃît́ĥ ín̂v́âĺîd́ v̂ál̂úêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś d̂ó n̂ót̂ h́âv́ê v́âĺîd́ v̂ál̂úêś"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś ĥáv̂é v̂ál̂íd̂ v́âĺûéŝ"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Âśŝíŝt́îv́ê t́êćĥńôĺôǵîéŝ, ĺîḱê śĉŕêén̂ ŕêád̂ér̂ś, ĉán̂'t́ îńt̂ér̂ṕr̂ét̂ ÁR̂ÍÂ át̂t́r̂íb̂út̂éŝ ẃît́ĥ ín̂v́âĺîd́ n̂ám̂éŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś âŕê ńôt́ v̂ál̂íd̂ ór̂ ḿîśŝṕêĺl̂éd̂"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` ât́t̂ŕîb́ût́êś âŕê v́âĺîd́ âńd̂ ńôt́ m̂íŝśp̂él̂ĺêd́"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Ĉáp̂t́îón̂ś m̂ák̂é âúd̂íô él̂ém̂én̂t́ŝ úŝáb̂ĺê f́ôŕ d̂éâf́ ôŕ ĥéâŕîńĝ-ím̂ṕâír̂éd̂ úŝér̂ś, p̂ŕôv́îd́îńĝ ćr̂ít̂íĉál̂ ín̂f́ôŕm̂át̂íôń ŝúĉh́ âś ŵh́ô íŝ t́âĺk̂ín̂ǵ, ŵh́ât́ t̂h́êý'r̂é ŝáŷín̂ǵ, âńd̂ ót̂h́êŕ n̂ón̂-śp̂éêćĥ ín̂f́ôŕm̂át̂íôń. [L̂éâŕn̂ ḿôŕê](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` êĺêḿêńt̂ś âŕê ḿîśŝín̂ǵ â `<track>` él̂ém̂én̂t́ ŵít̂h́ `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` êĺêḿêńt̂ś ĉón̂t́âín̂ á `<track>` êĺêḿêńt̂ ẃît́ĥ `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "F̂áîĺîńĝ Él̂ém̂én̂t́ŝ"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Ŵh́êń â b́ût́t̂ón̂ d́ôéŝń't̂ h́âv́ê án̂ áĉćêśŝíb̂ĺê ńâḿê, śĉŕêén̂ ŕêád̂ér̂ś âńn̂óûńĉé ît́ âś \"b̂út̂t́ôń\", m̂ák̂ín̂ǵ ît́ ûńûśâb́l̂é f̂ór̂ úŝér̂ś ŵh́ô ŕêĺŷ ón̂ śĉŕêén̂ ŕêád̂ér̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "B̂út̂t́ôńŝ d́ô ńôt́ ĥáv̂é âń âćĉéŝśîb́l̂é n̂ám̂é"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "B̂út̂t́ôńŝ h́âv́ê án̂ áĉćêśŝíb̂ĺê ńâḿê"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Âd́d̂ín̂ǵ ŵáŷś t̂ó b̂ýp̂áŝś r̂ép̂ét̂ít̂ív̂é ĉón̂t́êńt̂ ĺêt́ŝ ḱêýb̂óâŕd̂ úŝér̂ś n̂áv̂íĝát̂é t̂h́ê ṕâǵê ḿôŕê éf̂f́îćîén̂t́l̂ý. [L̂éâŕn̂ ḿôŕê](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "T̂h́ê ṕâǵê d́ôéŝ ńôt́ ĉón̂t́âín̂ á ĥéâd́îńĝ, śk̂íp̂ ĺîńk̂, ór̂ ĺâńd̂ḿâŕk̂ ŕêǵîón̂"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "T̂h́ê ṕâǵê ćôńt̂áîńŝ á ĥéâd́îńĝ, śk̂íp̂ ĺîńk̂, ór̂ ĺâńd̂ḿâŕk̂ ŕêǵîón̂"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "L̂óŵ-ćôńt̂ŕâśt̂ t́êx́t̂ íŝ d́îf́f̂íĉúl̂t́ ôŕ îḿp̂óŝśîb́l̂é f̂ór̂ ḿâńŷ úŝér̂ś t̂ó r̂éâd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "B̂áĉḱĝŕôún̂d́ âńd̂ f́ôŕêǵr̂óûńd̂ ćôĺôŕŝ d́ô ńôt́ ĥáv̂é â śûf́f̂íĉíêńt̂ ćôńt̂ŕâśt̂ ŕât́îó."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "B̂áĉḱĝŕôún̂d́ âńd̂ f́ôŕêǵr̂óûńd̂ ćôĺôŕŝ h́âv́ê á ŝúf̂f́îćîén̂t́ ĉón̂t́r̂áŝt́ r̂át̂íô"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Ŵh́êń d̂éf̂ín̂ít̂íôń l̂íŝt́ŝ ár̂é n̂ót̂ ṕr̂óp̂ér̂ĺŷ ḿâŕk̂éd̂ úp̂, śĉŕêén̂ ŕêád̂ér̂ś m̂áŷ ṕr̂ód̂úĉé ĉón̂f́ûśîńĝ ór̂ ín̂áĉćûŕât́ê óût́p̂út̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`'ŝ d́ô ńôt́ ĉón̂t́âín̂ ón̂ĺŷ ṕr̂óp̂ér̂ĺŷ-ór̂d́êŕêd́ `<dt>` âńd̂ `<dd>` ǵr̂óûṕŝ, `<script>` ór̂ `<template>` él̂ém̂én̂t́ŝ."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`'ŝ ćôńt̂áîń ôńl̂ý p̂ŕôṕêŕl̂ý-ôŕd̂ér̂éd̂ `<dt>` án̂d́ `<dd>` ĝŕôúp̂ś, `<script>` ôŕ `<template>` êĺêḿêńt̂ś."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "D̂éf̂ín̂ít̂íôń l̂íŝt́ ît́êḿŝ (`<dt>` án̂d́ `<dd>`) m̂úŝt́ b̂é ŵŕâṕp̂éd̂ ín̂ á p̂ár̂én̂t́ `<dl>` êĺêḿêńt̂ t́ô én̂śûŕê t́ĥát̂ śĉŕêén̂ ŕêád̂ér̂ś ĉán̂ ṕr̂óp̂ér̂ĺŷ án̂ńôún̂ćê t́ĥém̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "D̂éf̂ín̂ít̂íôń l̂íŝt́ ît́êḿŝ ár̂é n̂ót̂ ẃr̂áp̂ṕêd́ îń `<dl>` êĺêḿêńt̂ś"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "D̂éf̂ín̂ít̂íôń l̂íŝt́ ît́êḿŝ ár̂é ŵŕâṕp̂éd̂ ín̂ `<dl>` él̂ém̂én̂t́ŝ"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "T̂h́ê t́ît́l̂é ĝív̂éŝ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś âń ôv́êŕv̂íêẃ ôf́ t̂h́ê ṕâǵê, án̂d́ ŝéâŕĉh́ êńĝín̂é ûśêŕŝ ŕêĺŷ ón̂ ít̂ h́êáv̂íl̂ý t̂ó d̂ét̂ér̂ḿîńê íf̂ á p̂áĝé îś r̂él̂év̂án̂t́ t̂ó t̂h́êír̂ śêár̂ćĥ. [Ĺêár̂ń m̂ór̂é](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ d̂óêśn̂'t́ ĥáv̂é â `<title>` él̂ém̂én̂t́"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "D̂óĉúm̂én̂t́ ĥáŝ á `<title>` êĺêḿêńt̂"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "T̂h́ê v́âĺûé ôf́ âń îd́ ât́t̂ŕîb́ût́ê ḿûśt̂ b́ê ún̂íq̂úê t́ô ṕr̂év̂én̂t́ ôt́ĥér̂ ín̂śt̂án̂ćêś f̂ŕôḿ b̂éîńĝ óv̂ér̂ĺôók̂éd̂ b́ŷ áŝśîśt̂ív̂é t̂éĉh́n̂ól̂óĝíêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]` ât́t̂ŕîb́ût́êś ôń t̂h́ê ṕâǵê ár̂é n̂ót̂ ún̂íq̂úê"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]` ât́t̂ŕîb́ût́êś ôń t̂h́ê ṕâǵê ár̂é ûńîq́ûé"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕ ûśêŕŝ ŕêĺŷ ón̂ f́r̂ám̂é t̂ít̂ĺêś t̂ó d̂éŝćr̂íb̂é t̂h́ê ćôńt̂én̂t́ŝ óf̂ f́r̂ám̂éŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` ôŕ `<iframe>` êĺêḿêńt̂ś d̂ó n̂ót̂ h́âv́ê á t̂ít̂ĺê"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` ôŕ `<iframe>` êĺêḿêńt̂ś ĥáv̂é â t́ît́l̂é"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Îf́ â ṕâǵê d́ôéŝń't̂ śp̂éĉíf̂ý â ĺâńĝ át̂t́r̂íb̂út̂é, â śĉŕêén̂ ŕêád̂ér̂ áŝśûḿêś t̂h́ât́ t̂h́ê ṕâǵê íŝ ín̂ t́ĥé d̂éf̂áûĺt̂ ĺâńĝúâǵê t́ĥát̂ t́ĥé ûśêŕ ĉh́ôśê ẃĥén̂ śêt́t̂ín̂ǵ ûṕ t̂h́ê śĉŕêén̂ ŕêád̂ér̂. Íf̂ t́ĥé p̂áĝé îśn̂'t́ âćt̂úâĺl̂ý îń t̂h́ê d́êf́âúl̂t́ l̂án̂ǵûáĝé, t̂h́êń t̂h́ê śĉŕêén̂ ŕêád̂ér̂ ḿîǵĥt́ n̂ót̂ án̂ńôún̂ćê t́ĥé p̂áĝé'ŝ t́êx́t̂ ćôŕr̂éĉt́l̂ý. [L̂éâŕn̂ ḿôŕê](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` êĺêḿêńt̂ d́ôéŝ ńôt́ ĥáv̂é â `[lang]` át̂t́r̂íb̂út̂é"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` êĺêḿêńt̂ h́âś â `[lang]` át̂t́r̂íb̂út̂é"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ŝṕêćîf́ŷín̂ǵ â v́âĺîd́ [B̂ĆP̂ 47 ĺâńĝúâǵê](https://www.w3.org/International/questions/qa-choosing-language-tags#question) h́êĺp̂ś ŝćr̂éêń r̂éâd́êŕŝ án̂ńôún̂ćê t́êx́t̂ ṕr̂óp̂ér̂ĺŷ. [Ĺêár̂ń m̂ór̂é](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` êĺêḿêńt̂ d́ôéŝ ńôt́ ĥáv̂é â v́âĺîd́ v̂ál̂úê f́ôŕ ît́ŝ `[lang]` át̂t́r̂íb̂út̂é."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` êĺêḿêńt̂ h́âś â v́âĺîd́ v̂ál̂úê f́ôŕ ît́ŝ `[lang]` át̂t́r̂íb̂út̂é"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Îńf̂ór̂ḿât́îv́ê él̂ém̂én̂t́ŝ śĥóûĺd̂ áîḿ f̂ór̂ śĥór̂t́, d̂éŝćr̂íp̂t́îv́ê ál̂t́êŕn̂át̂é t̂éx̂t́. D̂éĉór̂át̂ív̂é êĺêḿêńt̂ś ĉán̂ b́ê íĝńôŕêd́ ŵít̂h́ âń êḿp̂t́ŷ ál̂t́ ât́t̂ŕîb́ût́ê. [Ĺêár̂ń m̂ór̂é](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Îḿâǵê él̂ém̂én̂t́ŝ d́ô ńôt́ ĥáv̂é `[alt]` ât́t̂ŕîb́ût́êś"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Îḿâǵê él̂ém̂én̂t́ŝ h́âv́ê `[alt]` át̂t́r̂íb̂út̂éŝ"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Ŵh́êń âń îḿâǵê íŝ b́êín̂ǵ ûśêd́ âś âń `<input>` b̂út̂t́ôń, p̂ŕôv́îd́îńĝ ál̂t́êŕn̂át̂ív̂é t̂éx̂t́ ĉán̂ h́êĺp̂ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś ûńd̂ér̂śt̂án̂d́ t̂h́ê ṕûŕp̂óŝé ôf́ t̂h́ê b́ût́t̂ón̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` êĺêḿêńt̂ś d̂ó n̂ót̂ h́âv́ê `[alt]` t́êx́t̂"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` êĺêḿêńt̂ś ĥáv̂é `[alt]` t̂éx̂t́"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "L̂áb̂él̂ś êńŝúr̂é t̂h́ât́ f̂ór̂ḿ ĉón̂t́r̂ól̂ś âŕê án̂ńôún̂ćêd́ p̂ŕôṕêŕl̂ý b̂ý âśŝíŝt́îv́ê t́êćĥńôĺôǵîéŝ, ĺîḱê śĉŕêén̂ ŕêád̂ér̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "F̂ór̂ḿ êĺêḿêńt̂ś d̂ó n̂ót̂ h́âv́ê áŝśôćîát̂éd̂ ĺâb́êĺŝ"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "F̂ór̂ḿ êĺêḿêńt̂ś ĥáv̂é âśŝóĉíât́êd́ l̂áb̂él̂ś"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Â t́âb́l̂é b̂éîńĝ úŝéd̂ f́ôŕ l̂áŷóût́ p̂úr̂ṕôśêś ŝh́ôúl̂d́ n̂ót̂ ín̂ćl̂úd̂é d̂át̂á êĺêḿêńt̂ś, ŝúĉh́ âś t̂h́ê t́ĥ ór̂ ćâṕt̂íôń êĺêḿêńt̂ś ôŕ t̂h́ê śûḿm̂ár̂ý ât́t̂ŕîb́ût́ê, b́êćâúŝé t̂h́îś ĉán̂ ćr̂éât́ê á ĉón̂f́ûśîńĝ éx̂ṕêŕîén̂ćê f́ôŕ ŝćr̂éêń r̂éâd́êŕ ûśêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "P̂ŕêśêńt̂át̂íôńâĺ `<table>` êĺêḿêńt̂ś d̂ó n̂ót̂ áv̂óîd́ ûśîńĝ `<th>`, `<caption>` ór̂ t́ĥé `[summary]` ât́t̂ŕîb́ût́ê."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "P̂ŕêśêńt̂át̂íôńâĺ `<table>` êĺêḿêńt̂ś âv́ôíd̂ úŝín̂ǵ `<th>`, `<caption>` ôŕ t̂h́ê `[summary]` át̂t́r̂íb̂út̂é."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "L̂ín̂ḱ t̂éx̂t́ (âńd̂ ál̂t́êŕn̂át̂é t̂éx̂t́ f̂ór̂ ím̂áĝéŝ, ẃĥén̂ úŝéd̂ áŝ ĺîńk̂ś) t̂h́ât́ îś d̂íŝćêŕn̂íb̂ĺê, ún̂íq̂úê, án̂d́ f̂óĉúŝáb̂ĺê ím̂ṕr̂óv̂éŝ t́ĥé n̂áv̂íĝát̂íôń êx́p̂ér̂íêńĉé f̂ór̂ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "L̂ín̂ḱŝ d́ô ńôt́ ĥáv̂é â d́îśĉér̂ńîb́l̂é n̂ám̂é"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "L̂ín̂ḱŝ h́âv́ê á d̂íŝćêŕn̂íb̂ĺê ńâḿê"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ h́âv́ê á ŝṕêćîf́îć ŵáŷ óf̂ án̂ńôún̂ćîńĝ ĺîśt̂ś. Êńŝúr̂ín̂ǵ p̂ŕôṕêŕ l̂íŝt́ ŝt́r̂úĉt́ûŕê áîd́ŝ śĉŕêén̂ ŕêád̂ér̂ óût́p̂út̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "L̂íŝt́ŝ d́ô ńôt́ ĉón̂t́âín̂ ón̂ĺŷ `<li>` él̂ém̂én̂t́ŝ án̂d́ ŝćr̂íp̂t́ ŝúp̂ṕôŕt̂ín̂ǵ êĺêḿêńt̂ś (`<script>` âńd̂ `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "L̂íŝt́ŝ ćôńt̂áîń ôńl̂ý `<li>` êĺêḿêńt̂ś âńd̂ śĉŕîṕt̂ śûṕp̂ór̂t́îńĝ él̂ém̂én̂t́ŝ (`<script>` án̂d́ `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ ŕêq́ûír̂é l̂íŝt́ ît́êḿŝ (`<li>`) t́ô b́ê ćôńt̂áîńêd́ ŵít̂h́îń â ṕâŕêńt̂ `<ul>` ór̂ `<ol>` t́ô b́ê án̂ńôún̂ćêd́ p̂ŕôṕêŕl̂ý. [L̂éâŕn̂ ḿôŕê](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "L̂íŝt́ ît́êḿŝ (`<li>`) ár̂é n̂ót̂ ćôńt̂áîńêd́ ŵít̂h́îń `<ul>` ôŕ `<ol>` p̂ár̂én̂t́ êĺêḿêńt̂ś."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "L̂íŝt́ ît́êḿŝ (`<li>`) ár̂é ĉón̂t́âín̂éd̂ ẃît́ĥín̂ `<ul>` ór̂ `<ol>` ṕâŕêńt̂ él̂ém̂én̂t́ŝ"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Ûśêŕŝ d́ô ńôt́ êx́p̂éĉt́ â ṕâǵê t́ô ŕêf́r̂éŝh́ âút̂óm̂át̂íĉál̂ĺŷ, án̂d́ d̂óîńĝ śô ẃîĺl̂ ḿôv́ê f́ôćûś b̂áĉḱ t̂ó t̂h́ê t́ôṕ ôf́ t̂h́ê ṕâǵê. T́ĥíŝ ḿâý ĉŕêát̂é â f́r̂úŝt́r̂át̂ín̂ǵ ôŕ ĉón̂f́ûśîńĝ éx̂ṕêŕîén̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "T̂h́ê d́ôćûḿêńt̂ úŝéŝ `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "T̂h́ê d́ôćûḿêńt̂ d́ôéŝ ńôt́ ûśê `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "D̂íŝáb̂ĺîńĝ źôóm̂ín̂ǵ îś p̂ŕôb́l̂ém̂át̂íĉ f́ôŕ ûśêŕŝ ẃît́ĥ ĺôẃ v̂íŝíôń ŵh́ô ŕêĺŷ ón̂ śĉŕêén̂ ḿâǵn̂íf̂íĉát̂íôń t̂ó p̂ŕôṕêŕl̂ý ŝéê t́ĥé ĉón̂t́êńt̂ś ôf́ â ẃêb́ p̂áĝé. [L̂éâŕn̂ ḿôŕê](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` îś ûśêd́ îń t̂h́ê `<meta name=\"viewport\">` él̂ém̂én̂t́ ôŕ t̂h́ê `[maximum-scale]` át̂t́r̂íb̂út̂é îś l̂éŝś t̂h́âń 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` îś n̂ót̂ úŝéd̂ ín̂ t́ĥé `<meta name=\"viewport\">` êĺêḿêńt̂ án̂d́ t̂h́ê `[maximum-scale]` át̂t́r̂íb̂út̂é îś n̂ót̂ ĺêśŝ t́ĥán̂ 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ ćâńn̂ót̂ t́r̂án̂śl̂át̂é n̂ón̂-t́êx́t̂ ćôńt̂én̂t́. Âd́d̂ín̂ǵ âĺt̂ t́êx́t̂ t́ô `<object>` él̂ém̂én̂t́ŝ h́êĺp̂ś ŝćr̂éêń r̂éâd́êŕŝ ćôńv̂éŷ ḿêán̂ín̂ǵ t̂ó ûśêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` êĺêḿêńt̂ś d̂ó n̂ót̂ h́âv́ê `[alt]` t́êx́t̂"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` êĺêḿêńt̂ś ĥáv̂é `[alt]` t̂éx̂t́"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Â v́âĺûé ĝŕêát̂ér̂ t́ĥán̂ 0 ím̂ṕl̂íêś âń êx́p̂ĺîćît́ n̂áv̂íĝát̂íôń ôŕd̂ér̂ín̂ǵ. Âĺt̂h́ôúĝh́ t̂éĉh́n̂íĉál̂ĺŷ v́âĺîd́, t̂h́îś ôf́t̂én̂ ćr̂éât́êś f̂ŕûśt̂ŕât́îńĝ éx̂ṕêŕîén̂ćêś f̂ór̂ úŝér̂ś ŵh́ô ŕêĺŷ ón̂ áŝśîśt̂ív̂é t̂éĉh́n̂ól̂óĝíêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Ŝóm̂é êĺêḿêńt̂ś ĥáv̂é â `[tabindex]` v́âĺûé ĝŕêát̂ér̂ t́ĥán̂ 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "N̂ó êĺêḿêńt̂ h́âś â `[tabindex]` v́âĺûé ĝŕêát̂ér̂ t́ĥán̂ 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ h́âv́ê f́êát̂úr̂éŝ t́ô ḿâḱê ńâv́îǵât́îńĝ t́âb́l̂éŝ éâśîér̂. Én̂śûŕîńĝ `<td>` ćêĺl̂ś ûśîńĝ t́ĥé `[headers]` ât́t̂ŕîb́ût́ê ón̂ĺŷ ŕêf́êŕ t̂ó ôt́ĥér̂ ćêĺl̂ś îń t̂h́ê śâḿê t́âb́l̂é m̂áŷ ím̂ṕr̂óv̂é t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ŝćr̂éêń r̂éâd́êŕ ûśêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Ĉél̂ĺŝ ín̂ á `<table>` êĺêḿêńt̂ t́ĥát̂ úŝé t̂h́ê `[headers]` át̂t́r̂íb̂út̂é r̂éf̂ér̂ t́ô án̂ él̂ém̂én̂t́ `id` n̂ót̂ f́ôún̂d́ ŵít̂h́îń t̂h́ê śâḿê t́âb́l̂é."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Ĉél̂ĺŝ ín̂ á `<table>` êĺêḿêńt̂ t́ĥát̂ úŝé t̂h́ê `[headers]` át̂t́r̂íb̂út̂é r̂éf̂ér̂ t́ô t́âb́l̂é ĉél̂ĺŝ ẃît́ĥín̂ t́ĥé ŝám̂é t̂áb̂ĺê."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ h́âv́ê f́êát̂úr̂éŝ t́ô ḿâḱê ńâv́îǵât́îńĝ t́âb́l̂éŝ éâśîér̂. Én̂śûŕîńĝ t́âb́l̂é ĥéâd́êŕŝ ál̂ẃâýŝ ŕêf́êŕ t̂ó ŝóm̂é ŝét̂ óf̂ ćêĺl̂ś m̂áŷ ím̂ṕr̂óv̂é t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ŝćr̂éêń r̂éâd́êŕ ûśêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` êĺêḿêńt̂ś âńd̂ él̂ém̂én̂t́ŝ ẃît́ĥ `[role=\"columnheader\"/\"rowheader\"]` d́ô ńôt́ ĥáv̂é d̂át̂á ĉél̂ĺŝ t́ĥéŷ d́êśĉŕîb́ê."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` êĺêḿêńt̂ś âńd̂ él̂ém̂én̂t́ŝ ẃît́ĥ `[role=\"columnheader\"/\"rowheader\"]` h́âv́ê d́ât́â ćêĺl̂ś t̂h́êý d̂éŝćr̂íb̂é."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ŝṕêćîf́ŷín̂ǵ â v́âĺîd́ [B̂ĆP̂ 47 ĺâńĝúâǵê](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ón̂ él̂ém̂én̂t́ŝ h́êĺp̂ś êńŝúr̂é t̂h́ât́ t̂éx̂t́ îś p̂ŕôńôún̂ćêd́ ĉór̂ŕêćt̂ĺŷ b́ŷ á ŝćr̂éêń r̂éâd́êŕ. [L̂éâŕn̂ ḿôŕê](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` ât́t̂ŕîb́ût́êś d̂ó n̂ót̂ h́âv́ê á v̂ál̂íd̂ v́âĺûé"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` ât́t̂ŕîb́ût́êś ĥáv̂é â v́âĺîd́ v̂ál̂úê"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Ŵh́êń â v́îd́êó p̂ŕôv́îd́êś â ćâṕt̂íôń ît́ îś êáŝíêŕ f̂ór̂ d́êáf̂ án̂d́ ĥéâŕîńĝ ím̂ṕâír̂éd̂ úŝér̂ś t̂ó âćĉéŝś ît́ŝ ín̂f́ôŕm̂át̂íôń. [L̂éâŕn̂ ḿôŕê](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` êĺêḿêńt̂ś d̂ó n̂ót̂ ćôńt̂áîń â `<track>` él̂ém̂én̂t́ ŵít̂h́ `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` êĺêḿêńt̂ś ĉón̂t́âín̂ á `<track>` êĺêḿêńt̂ ẃît́ĥ `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Âúd̂íô d́êśĉŕîṕt̂íôńŝ ṕr̂óv̂íd̂é r̂él̂év̂án̂t́ îńf̂ór̂ḿât́îón̂ f́ôŕ v̂íd̂éôś t̂h́ât́ d̂íâĺôǵûé ĉán̂ńôt́, ŝúĉh́ âś f̂áĉíâĺ êx́p̂ŕêśŝíôńŝ án̂d́ ŝćêńêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` êĺêḿêńt̂ś d̂ó n̂ót̂ ćôńt̂áîń â `<track>` él̂ém̂én̂t́ ŵít̂h́ `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` êĺêḿêńt̂ś ĉón̂t́âín̂ á `<track>` êĺêḿêńt̂ ẃît́ĥ `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "F̂ór̂ íd̂éâĺ âṕp̂éâŕâńĉé ôń îÓŜ ẃĥén̂ úŝér̂ś âd́d̂ á p̂ŕôǵr̂éŝśîv́ê ẃêb́ âṕp̂ t́ô t́ĥé ĥóm̂é ŝćr̂éêń, d̂éf̂ín̂é âń `apple-touch-icon`. Ît́ m̂úŝt́ p̂óîńt̂ t́ô á n̂ón̂-t́r̂án̂śp̂ár̂én̂t́ 192p̂x́ (ôŕ 180p̂x́) ŝq́ûár̂é P̂ŃĜ. [Ĺêár̂ń M̂ór̂é](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ ṕr̂óv̂íd̂é â v́âĺîd́ `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` îś ôút̂ óf̂ d́ât́ê; `apple-touch-icon` íŝ ṕr̂éf̂ér̂ŕêd́."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "P̂ŕôv́îd́êś â v́âĺîd́ `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Ĉh́r̂óm̂é êx́t̂én̂śîón̂ś n̂éĝát̂ív̂él̂ý âf́f̂éĉt́êd́ t̂h́îś p̂áĝé'ŝ ĺôád̂ ṕêŕf̂ór̂ḿâńĉé. T̂ŕŷ áûd́ît́îńĝ t́ĥé p̂áĝé îń îńĉóĝńît́ô ḿôd́ê ór̂ f́r̂óm̂ á Ĉh́r̂óm̂é p̂ŕôf́îĺê ẃît́ĥóût́ êx́t̂én̂śîón̂ś."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Ŝćr̂íp̂t́ Êv́âĺûát̂íôń"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Ŝćr̂íp̂t́ P̂ár̂śê"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "T̂ót̂ál̂ ĆP̂Ú T̂ím̂é"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Ĉón̂śîd́êŕ r̂éd̂úĉín̂ǵ t̂h́ê t́îḿê śp̂én̂t́ p̂ár̂śîńĝ, ćôḿp̂íl̂ín̂ǵ, âńd̂ éx̂éĉút̂ín̂ǵ ĴŚ. Ŷóû ḿâý f̂ín̂d́ d̂él̂ív̂ér̂ín̂ǵ ŝḿâĺl̂ér̂ J́Ŝ ṕâýl̂óâd́ŝ h́êĺp̂ś ŵít̂h́ t̂h́îś. [L̂éâŕn̂ ḿôŕê](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "R̂éd̂úĉé Ĵáv̂áŜćr̂íp̂t́ êx́êćût́îón̂ t́îḿê"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Ĵáv̂áŜćr̂íp̂t́ êx́êćût́îón̂ t́îḿê"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "L̂ár̂ǵê ǴÎF́ŝ ár̂é îńêf́f̂íĉíêńt̂ f́ôŕ d̂él̂ív̂ér̂ín̂ǵ âńîḿât́êd́ ĉón̂t́êńt̂. Ćôńŝíd̂ér̂ úŝín̂ǵ M̂ṔÊǴ4/Ŵéb̂Ḿ v̂íd̂éôś f̂ór̂ án̂ím̂át̂íôńŝ án̂d́ P̂ŃĜ/Ẃêb́P̂ f́ôŕ ŝt́ât́îć îḿâǵêś îńŝt́êád̂ óf̂ ǴÎF́ t̂ó ŝáv̂é n̂ét̂ẃôŕk̂ b́ŷt́êś. [L̂éâŕn̂ ḿôŕê](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Ûśê v́îd́êó f̂ór̂ḿât́ŝ f́ôŕ âńîḿât́êd́ ĉón̂t́êńt̂"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Ĉón̂śîd́êŕ l̂áẑý-l̂óâd́îńĝ óf̂f́ŝćr̂éêń âńd̂ h́îd́d̂én̂ ím̂áĝéŝ áf̂t́êŕ âĺl̂ ćr̂ít̂íĉál̂ ŕêśôúr̂ćêś ĥáv̂é f̂ín̂íŝh́êd́ l̂óâd́îńĝ t́ô ĺôẃêŕ t̂ím̂é t̂ó îńt̂ér̂áĉt́îv́ê. [Ĺêár̂ń m̂ór̂é](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "D̂éf̂ér̂ óf̂f́ŝćr̂éêń îḿâǵêś"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "R̂éŝóûŕĉéŝ ár̂é b̂ĺôćk̂ín̂ǵ t̂h́ê f́îŕŝt́ p̂áîńt̂ óf̂ ýôúr̂ ṕâǵê. Ćôńŝíd̂ér̂ d́êĺîv́êŕîńĝ ćr̂ít̂íĉál̂ J́Ŝ/ĆŜŚ îńl̂ín̂é âńd̂ d́êf́êŕr̂ín̂ǵ âĺl̂ ńôń-ĉŕît́îćâĺ ĴŚ/ŝt́ŷĺêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Êĺîḿîńât́ê ŕêńd̂ér̂-b́l̂óĉḱîńĝ ŕêśôúr̂ćêś"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "L̂ár̂ǵê ńêt́ŵór̂ḱ p̂áŷĺôád̂ś ĉóŝt́ ûśêŕŝ ŕêál̂ ḿôńêý âńd̂ ár̂é ĥíĝh́l̂ý ĉór̂ŕêĺât́êd́ ŵít̂h́ l̂ón̂ǵ l̂óâd́ t̂ím̂éŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "T̂ót̂ál̂ śîźê ẃâś {totalBytes, number, bytes} K̂B́"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Âv́ôíd̂ én̂ór̂ḿôúŝ ńêt́ŵór̂ḱ p̂áŷĺôád̂ś"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Âv́ôíd̂ś êńôŕm̂óûś n̂ét̂ẃôŕk̂ ṕâýl̂óâd́ŝ"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "M̂ín̂íf̂ýîńĝ ĆŜŚ f̂íl̂éŝ ćâń r̂éd̂úĉé n̂ét̂ẃôŕk̂ ṕâýl̂óâd́ ŝíẑéŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "M̂ín̂íf̂ý ĈŚŜ"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "M̂ín̂íf̂ýîńĝ J́âv́âŚĉŕîṕt̂ f́îĺêś ĉán̂ ŕêd́ûćê ṕâýl̂óâd́ ŝíẑéŝ án̂d́ ŝćr̂íp̂t́ p̂ár̂śê t́îḿê. [Ĺêár̂ń m̂ór̂é](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "M̂ín̂íf̂ý Ĵáv̂áŜćr̂íp̂t́"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "R̂ém̂óv̂é d̂éâd́ r̂úl̂éŝ f́r̂óm̂ śt̂ýl̂éŝh́êét̂ś âńd̂ d́êf́êŕ t̂h́ê ĺôád̂ín̂ǵ ôf́ ĈŚŜ ńôt́ ûśêd́ f̂ór̂ áb̂óv̂é-t̂h́ê-f́ôĺd̂ ćôńt̂én̂t́ t̂ó r̂éd̂úĉé ûńn̂éĉéŝśâŕŷ b́ŷt́êś ĉón̂śûḿêd́ b̂ý n̂ét̂ẃôŕk̂ áĉt́îv́ît́ŷ. [Ĺêár̂ń m̂ór̂é](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "R̂ém̂óv̂é ûńûśêd́ ĈŚŜ"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "R̂ém̂óv̂é ûńûśêd́ Ĵáv̂áŜćr̂íp̂t́ t̂ó r̂éd̂úĉé b̂ýt̂éŝ ćôńŝúm̂éd̂ b́ŷ ńêt́ŵór̂ḱ âćt̂ív̂ít̂ý."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "R̂ém̂óv̂é ûńûśêd́ Ĵáv̂áŜćr̂íp̂t́"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Â ĺôńĝ ćâćĥé l̂íf̂ét̂ím̂é ĉán̂ śp̂éêd́ ûṕ r̂ép̂éât́ v̂íŝít̂ś t̂ó ŷóûŕ p̂áĝé. [L̂éâŕn̂ ḿôŕê](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 r̂éŝóûŕĉé f̂óûńd̂}\n other {# ŕêśôúr̂ćêś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Ŝér̂v́ê śt̂át̂íĉ áŝśêt́ŝ ẃît́ĥ án̂ éf̂f́îćîén̂t́ ĉáĉh́ê ṕôĺîćŷ"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Ûśêś êf́f̂íĉíêńt̂ ćâćĥé p̂ól̂íĉý ôń ŝt́ât́îć âśŝét̂ś"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Ôṕt̂ím̂íẑéd̂ ím̂áĝéŝ ĺôád̂ f́âśt̂ér̂ án̂d́ ĉón̂śûḿê ĺêśŝ ćêĺl̂úl̂ár̂ d́ât́â. [Ĺêár̂ń m̂ór̂é](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Êf́f̂íĉíêńt̂ĺŷ én̂ćôd́ê ím̂áĝéŝ"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Ŝér̂v́ê ím̂áĝéŝ t́ĥát̂ ár̂é âṕp̂ŕôṕr̂íât́êĺŷ-śîźêd́ t̂ó ŝáv̂é ĉél̂ĺûĺâŕ d̂át̂á âńd̂ ím̂ṕr̂óv̂é l̂óâd́ t̂ím̂é. [L̂éâŕn̂ ḿôŕê](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "P̂ŕôṕêŕl̂ý ŝíẑé îḿâǵêś"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "T̂éx̂t́-b̂áŝéd̂ ŕêśôúr̂ćêś ŝh́ôúl̂d́ b̂é ŝér̂v́êd́ ŵít̂h́ ĉóm̂ṕr̂éŝśîón̂ (ǵẑíp̂, d́êf́l̂át̂é ôŕ b̂ŕôt́l̂í) t̂ó m̂ín̂ím̂íẑé t̂ót̂ál̂ ńêt́ŵór̂ḱ b̂ýt̂éŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Êńâb́l̂é t̂éx̂t́ ĉóm̂ṕr̂éŝśîón̂"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Îḿâǵê f́ôŕm̂át̂ś l̂ík̂é ĴṔÊǴ 2000, ĴṔÊǴ X̂Ŕ, âńd̂ Ẃêb́P̂ óf̂t́êń p̂ŕôv́îd́ê b́êt́t̂ér̂ ćôḿp̂ŕêśŝíôń t̂h́âń P̂ŃĜ ór̂ J́P̂ÉĜ, ẃĥíĉh́ m̂éâńŝ f́âśt̂ér̂ d́ôẃn̂ĺôád̂ś âńd̂ ĺêśŝ d́ât́â ćôńŝúm̂ṕt̂íôń. [L̂éâŕn̂ ḿôŕê](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Ŝér̂v́ê ím̂áĝéŝ ín̂ ńêx́t̂-ǵêń f̂ór̂ḿât́ŝ"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Îf́ t̂h́ê ẃîd́t̂h́ ôf́ ŷóûŕ âṕp̂'ś ĉón̂t́êńt̂ d́ôéŝń't̂ ḿât́ĉh́ t̂h́ê ẃîd́t̂h́ ôf́ t̂h́ê v́îéŵṕôŕt̂, ýôúr̂ áp̂ṕ m̂íĝh́t̂ ńôt́ b̂é ôṕt̂ím̂íẑéd̂ f́ôŕ m̂ób̂íl̂é ŝćr̂éêńŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "T̂h́ê v́îéŵṕôŕt̂ śîźê óf̂ {innerWidth}ṕx̂ d́ôéŝ ńôt́ m̂át̂ćĥ t́ĥé ŵín̂d́ôẃ ŝíẑé ôf́ {outerWidth}p̂x́."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Ĉón̂t́êńt̂ íŝ ńôt́ ŝíẑéd̂ ćôŕr̂éĉt́l̂ý f̂ór̂ t́ĥé v̂íêẃp̂ór̂t́"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Ĉón̂t́êńt̂ íŝ śîźêd́ ĉór̂ŕêćt̂ĺŷ f́ôŕ t̂h́ê v́îéŵṕôŕt̂"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "T̂h́ê Ćr̂ít̂íĉál̂ Ŕêq́ûéŝt́ Ĉh́âín̂ś b̂él̂óŵ śĥóŵ ýôú ŵh́ât́ r̂éŝóûŕĉéŝ ár̂é l̂óâd́êd́ ŵít̂h́ â h́îǵĥ ṕr̂íôŕît́ŷ. Ćôńŝíd̂ér̂ ŕêd́ûćîńĝ t́ĥé l̂én̂ǵt̂h́ ôf́ ĉh́âín̂ś, r̂éd̂úĉín̂ǵ t̂h́ê d́ôẃn̂ĺôád̂ śîźê óf̂ ŕêśôúr̂ćêś, ôŕ d̂éf̂ér̂ŕîńĝ t́ĥé d̂óŵńl̂óâd́ ôf́ ûńn̂éĉéŝśâŕŷ ŕêśôúr̂ćêś t̂ó îḿp̂ŕôv́ê ṕâǵê ĺôád̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 ĉh́âín̂ f́ôún̂d́}\n other {# ĉh́âín̂ś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Âv́ôíd̂ ćĥáîńîńĝ ćr̂ít̂íĉál̂ ŕêq́ûéŝt́ŝ"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "D̂ép̂ŕêćât́îón̂ / Ẃâŕn̂ín̂ǵ"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "L̂ín̂é"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "D̂ép̂ŕêćât́êd́ ÂṔÎś ŵíl̂ĺ êv́êńt̂úâĺl̂ý b̂é r̂ém̂óv̂éd̂ f́r̂óm̂ t́ĥé b̂ŕôẃŝér̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 ŵár̂ńîńĝ f́ôún̂d́}\n other {# ŵár̂ńîńĝś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Ûśêś d̂ép̂ŕêćât́êd́ ÂṔÎś"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Âv́ôíd̂ś d̂ép̂ŕêćât́êd́ ÂṔÎś"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Âṕp̂ĺîćât́îón̂ Ćâćĥé îś d̂ép̂ŕêćât́êd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "F̂óûńd̂ \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Ûśêś Âṕp̂ĺîćât́îón̂ Ćâćĥé"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Âv́ôíd̂ś Âṕp̂ĺîćât́îón̂ Ćâćĥé"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Ŝṕêćîf́ŷín̂ǵ â d́ôćt̂ýp̂é p̂ŕêv́êńt̂ś t̂h́ê b́r̂óŵśêŕ f̂ŕôḿ ŝẃît́ĉh́îńĝ t́ô q́ûír̂ḱŝ-ḿôd́ê. [Ĺêár̂ń m̂ór̂é](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "D̂óĉt́ŷṕê ńâḿê ḿûśt̂ b́ê t́ĥé l̂óŵér̂ćâśê śt̂ŕîńĝ `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "D̂óĉúm̂én̂t́ m̂úŝt́ ĉón̂t́âín̂ á d̂óĉt́ŷṕê"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Êx́p̂éĉt́êd́ p̂úb̂ĺîćÎd́ t̂ó b̂é âń êḿp̂t́ŷ śt̂ŕîńĝ"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Êx́p̂éĉt́êd́ ŝýŝt́êḿÎd́ t̂ó b̂é âń êḿp̂t́ŷ śt̂ŕîńĝ"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "P̂áĝé l̂áĉḱŝ t́ĥé ĤT́M̂Ĺ d̂óĉt́ŷṕê, t́ĥúŝ t́r̂íĝǵêŕîńĝ q́ûír̂ḱŝ-ḿôd́ê"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "P̂áĝé ĥáŝ t́ĥé ĤT́M̂Ĺ d̂óĉt́ŷṕê"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Êĺêḿêńt̂"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Ŝt́ât́îśt̂íĉ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "V̂ál̂úê"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Â ĺâŕĝé D̂ÓM̂ ẃîĺl̂ ín̂ćr̂éâśê ḿêḿôŕŷ úŝáĝé, ĉáûśê ĺôńĝér̂ [śt̂ýl̂é ĉál̂ćûĺât́îón̂ś](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), âńd̂ ṕr̂ód̂úĉé ĉóŝt́l̂ý [l̂áŷóût́ r̂éf̂ĺôẃŝ](https://developers.google.com/speed/articles/reflow). [Ĺêár̂ń m̂ór̂é](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 êĺêḿêńt̂}\n other {# él̂ém̂én̂t́ŝ}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Âv́ôíd̂ án̂ éx̂ćêśŝív̂é D̂ÓM̂ śîźê"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "M̂áx̂ím̂úm̂ D́ÔḾ D̂ép̂t́ĥ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "T̂ót̂ál̂ D́ÔḾ Êĺêḿêńt̂ś"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "M̂áx̂ím̂úm̂ Ćĥíl̂d́ Êĺêḿêńt̂ś"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Âv́ôíd̂ś âń êx́ĉéŝśîv́ê D́ÔḾ ŝíẑé"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "R̂él̂"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "T̂ár̂ǵêt́"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Âd́d̂ `rel=\"noopener\"` ór̂ `rel=\"noreferrer\"` t́ô án̂ý êx́t̂ér̂ńâĺ l̂ín̂ḱŝ t́ô ím̂ṕr̂óv̂é p̂ér̂f́ôŕm̂án̂ćê án̂d́ p̂ŕêv́êńt̂ śêćûŕît́ŷ v́ûĺn̂ér̂áb̂íl̂ít̂íêś. [L̂éâŕn̂ ḿôŕê](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "L̂ín̂ḱŝ t́ô ćr̂óŝś-ôŕîǵîń d̂éŝt́îńât́îón̂ś âŕê ún̂śâf́ê"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "L̂ín̂ḱŝ t́ô ćr̂óŝś-ôŕîǵîń d̂éŝt́îńât́îón̂ś âŕê śâf́ê"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Ûńâb́l̂é t̂ó d̂ét̂ér̂ḿîńê t́ĥé d̂éŝt́îńât́îón̂ f́ôŕ âńĉh́ôŕ ({anchorHTML}). Îf́ n̂ót̂ úŝéd̂ áŝ á ĥýp̂ér̂ĺîńk̂, ćôńŝíd̂ér̂ ŕêḿôv́îńĝ t́âŕĝét̂=_b́l̂án̂ḱ."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Ûśêŕŝ ár̂é m̂íŝt́r̂úŝt́f̂úl̂ óf̂ ór̂ ćôńf̂úŝéd̂ b́ŷ śît́êś t̂h́ât́ r̂éq̂úêśt̂ t́ĥéîŕ l̂óĉát̂íôń ŵít̂h́ôút̂ ćôńt̂éx̂t́. Ĉón̂śîd́êŕ t̂ýîńĝ t́ĥé r̂éq̂úêśt̂ t́ô á ûśêŕ âćt̂íôń îńŝt́êád̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "R̂éq̂úêśt̂ś t̂h́ê ǵêól̂óĉát̂íôń p̂ér̂ḿîśŝíôń ôń p̂áĝé l̂óâd́"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Âv́ôíd̂ś r̂éq̂úêśt̂ín̂ǵ t̂h́ê ǵêól̂óĉát̂íôń p̂ér̂ḿîśŝíôń ôń p̂áĝé l̂óâd́"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "V̂ér̂śîón̂"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Âĺl̂ f́r̂ón̂t́-êńd̂ J́âv́âŚĉŕîṕt̂ ĺîb́r̂ár̂íêś d̂ét̂éĉt́êd́ ôń t̂h́ê ṕâǵê. [Ĺêár̂ń m̂ór̂é](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "D̂ét̂éĉt́êd́ Ĵáv̂áŜćr̂íp̂t́ l̂íb̂ŕâŕîéŝ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "F̂ór̂ úŝér̂ś ôń ŝĺôẃ ĉón̂ńêćt̂íôńŝ, éx̂t́êŕn̂ál̂ śĉŕîṕt̂ś d̂ýn̂ám̂íĉál̂ĺŷ ín̂j́êćt̂éd̂ v́îá `document.write()` ĉán̂ d́êĺâý p̂áĝé l̂óâd́ b̂ý t̂én̂ś ôf́ ŝéĉón̂d́ŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Ûśêś `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Âv́ôíd̂ś `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Ĥíĝh́êśt̂ Śêv́êŕît́ŷ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "L̂íb̂ŕâŕŷ V́êŕŝíôń"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "V̂úl̂ńêŕâb́îĺît́ŷ Ćôún̂t́"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý ŝćr̂íp̂t́ŝ ḿâý ĉón̂t́âín̂ ḱn̂óŵń ŝéĉúr̂ít̂ý v̂úl̂ńêŕâb́îĺît́îéŝ t́ĥát̂ ár̂é êáŝíl̂ý îd́êńt̂íf̂íêd́ âńd̂ éx̂ṕl̂óît́êd́ b̂ý ât́t̂áĉḱêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 v̂úl̂ńêŕâb́îĺît́ŷ d́êt́êćt̂éd̂}\n other {# v́ûĺn̂ér̂áb̂íl̂ít̂íêś d̂ét̂éĉt́êd́}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Îńĉĺûd́êś f̂ŕôńt̂-én̂d́ Ĵáv̂áŜćr̂íp̂t́ l̂íb̂ŕâŕîéŝ ẃît́ĥ ḱn̂óŵń ŝéĉúr̂ít̂ý v̂úl̂ńêŕâb́îĺît́îéŝ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Ĥíĝh́"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "L̂óŵ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "M̂éd̂íûḿ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Âv́ôíd̂ś f̂ŕôńt̂-én̂d́ Ĵáv̂áŜćr̂íp̂t́ l̂íb̂ŕâŕîéŝ ẃît́ĥ ḱn̂óŵń ŝéĉúr̂ít̂ý v̂úl̂ńêŕâb́îĺît́îéŝ"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Ûśêŕŝ ár̂é m̂íŝt́r̂úŝt́f̂úl̂ óf̂ ór̂ ćôńf̂úŝéd̂ b́ŷ śît́êś t̂h́ât́ r̂éq̂úêśt̂ t́ô śêńd̂ ńôt́îf́îćât́îón̂ś ŵít̂h́ôút̂ ćôńt̂éx̂t́. Ĉón̂śîd́êŕ t̂ýîńĝ t́ĥé r̂éq̂úêśt̂ t́ô úŝér̂ ǵêśt̂úr̂éŝ ín̂śt̂éâd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "R̂éq̂úêśt̂ś t̂h́ê ńôt́îf́îćât́îón̂ ṕêŕm̂íŝśîón̂ ón̂ ṕâǵê ĺôád̂"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Âv́ôíd̂ś r̂éq̂úêśt̂ín̂ǵ t̂h́ê ńôt́îf́îćât́îón̂ ṕêŕm̂íŝśîón̂ ón̂ ṕâǵê ĺôád̂"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "F̂áîĺîńĝ Él̂ém̂én̂t́ŝ"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "P̂ŕêv́êńt̂ín̂ǵ p̂áŝśŵór̂d́ p̂áŝt́îńĝ ún̂d́êŕm̂ín̂éŝ ǵôód̂ śêćûŕît́ŷ ṕôĺîćŷ. [Ĺêár̂ń m̂ór̂é](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "P̂ŕêv́êńt̂ś ûśêŕŝ t́ô ṕâśt̂é îńt̂ó p̂áŝśŵór̂d́ f̂íêĺd̂ś"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Âĺl̂óŵś ûśêŕŝ t́ô ṕâśt̂é îńt̂ó p̂áŝśŵór̂d́ f̂íêĺd̂ś"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "P̂ŕôt́ôćôĺ"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "ĤT́T̂Ṕ/2 ôf́f̂ér̂ś m̂án̂ý b̂én̂éf̂ít̂ś ôv́êŕ ĤT́T̂Ṕ/1.1, îńĉĺûd́îńĝ b́îńâŕŷ h́êád̂ér̂ś, m̂úl̂t́îṕl̂éx̂ín̂ǵ, âńd̂ śêŕv̂ér̂ ṕûśĥ. [Ĺêár̂ń m̂ór̂é](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 r̂éq̂úêśt̂ ńôt́ ŝér̂v́êd́ v̂íâ H́T̂T́P̂/2}\n other {# ŕêq́ûéŝt́ŝ ńôt́ ŝér̂v́êd́ v̂íâ H́T̂T́P̂/2}\n }"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ úŝé ĤT́T̂Ṕ/2 f̂ór̂ ál̂ĺ ôf́ ît́ŝ ŕêśôúr̂ćêś"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Ûśêś ĤT́T̂Ṕ/2 f̂ór̂ ít̂ś ôẃn̂ ŕêśôúr̂ćêś"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Ĉón̂śîd́êŕ m̂ár̂ḱîńĝ ýôúr̂ t́ôúĉh́ âńd̂ ẃĥéêĺ êv́êńt̂ ĺîśt̂én̂ér̂ś âś `passive` t̂ó îḿp̂ŕôv́ê ýôúr̂ ṕâǵê'ś ŝćr̂ól̂ĺ p̂ér̂f́ôŕm̂án̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ úŝé p̂áŝśîv́ê ĺîśt̂én̂ér̂ś t̂ó îḿp̂ŕôv́ê śĉŕôĺl̂ín̂ǵ p̂ér̂f́ôŕm̂án̂ćê"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Ûśêś p̂áŝśîv́ê ĺîśt̂én̂ér̂ś t̂ó îḿp̂ŕôv́ê śĉŕôĺl̂ín̂ǵ p̂ér̂f́ôŕm̂án̂ćê"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "D̂éŝćr̂íp̂t́îón̂"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Êŕr̂ór̂ś l̂óĝǵêd́ t̂ó t̂h́ê ćôńŝól̂é îńd̂íĉát̂é ûńr̂éŝól̂v́êd́ p̂ŕôb́l̂ém̂ś. T̂h́êý ĉán̂ ćôḿê f́r̂óm̂ ńêt́ŵór̂ḱ r̂éq̂úêśt̂ f́âíl̂úr̂éŝ án̂d́ ôt́ĥér̂ b́r̂óŵśêŕ ĉón̂ćêŕn̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "B̂ŕôẃŝér̂ ér̂ŕôŕŝ ẃêŕê ĺôǵĝéd̂ t́ô t́ĥé ĉón̂śôĺê"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "N̂ó b̂ŕôẃŝér̂ ér̂ŕôŕŝ ĺôǵĝéd̂ t́ô t́ĥé ĉón̂śôĺê"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "L̂év̂ér̂áĝé t̂h́ê f́ôńt̂-d́îśp̂ĺâý ĈŚŜ f́êát̂úr̂é t̂ó êńŝúr̂é t̂éx̂t́ îś ûśêŕ-v̂íŝíb̂ĺê ẃĥíl̂é ŵéb̂f́ôńt̂ś âŕê ĺôád̂ín̂ǵ. [L̂éâŕn̂ ḿôŕê](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Êńŝúr̂é t̂éx̂t́ r̂ém̂áîńŝ v́îśîb́l̂é d̂úr̂ín̂ǵ ŵéb̂f́ôńt̂ ĺôád̂"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Âĺl̂ t́êx́t̂ ŕêḿâín̂ś v̂íŝíb̂ĺê d́ûŕîńĝ ẃêb́f̂ón̂t́ l̂óâd́ŝ"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô áût́ôḿât́îćâĺl̂ý ĉh́êćk̂ t́ĥé f̂ón̂t́-d̂íŝṕl̂áŷ v́âĺûé f̂ór̂ t́ĥé f̂ól̂ĺôẃîńĝ ÚR̂Ĺ: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Âśp̂éĉt́ R̂át̂íô (Áĉt́ûál̂)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Âśp̂éĉt́ R̂át̂íô (D́îśp̂ĺâýêd́)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Îḿâǵê d́îśp̂ĺâý d̂ím̂én̂śîón̂ś ŝh́ôúl̂d́ m̂át̂ćĥ ńât́ûŕâĺ âśp̂éĉt́ r̂át̂íô. [Ĺêár̂ń m̂ór̂é](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "D̂íŝṕl̂áŷś îḿâǵêś ŵít̂h́ îńĉór̂ŕêćt̂ áŝṕêćt̂ ŕât́îó"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "D̂íŝṕl̂áŷś îḿâǵêś ŵít̂h́ ĉór̂ŕêćt̂ áŝṕêćt̂ ŕât́îó"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Îńv̂ál̂íd̂ ím̂áĝé ŝíẑín̂ǵ îńf̂ór̂ḿât́îón̂ {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "B̂ŕôẃŝér̂ś ĉán̂ ṕr̂óâćt̂ív̂él̂ý p̂ŕôḿp̂t́ ûśêŕŝ t́ô ád̂d́ ŷóûŕ âṕp̂ t́ô t́ĥéîŕ ĥóm̂éŝćr̂éêń, ŵh́îćĥ ćâń l̂éâd́ t̂ó ĥíĝh́êŕ êńĝáĝém̂én̂t́. [L̂éâŕn̂ ḿôŕê](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Ŵéb̂ áp̂ṕ m̂án̂íf̂éŝt́ d̂óêś n̂ót̂ ḿêét̂ t́ĥé îńŝt́âĺl̂áb̂íl̂ít̂ý r̂éq̂úîŕêḿêńt̂ś"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Ŵéb̂ áp̂ṕ m̂án̂íf̂éŝt́ m̂éêt́ŝ t́ĥé îńŝt́âĺl̂áb̂íl̂ít̂ý r̂éq̂úîŕêḿêńt̂ś"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Îńŝéĉúr̂é ÛŔL̂"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Âĺl̂ śît́êś ŝh́ôúl̂d́ b̂é p̂ŕôt́êćt̂éd̂ ẃît́ĥ H́T̂T́P̂Ś, êv́êń ôńêś t̂h́ât́ d̂ón̂'t́ ĥán̂d́l̂é ŝén̂śît́îv́ê d́ât́â. H́T̂T́P̂Ś p̂ŕêv́êńt̂ś îńt̂ŕûd́êŕŝ f́r̂óm̂ t́âḿp̂ér̂ín̂ǵ ŵít̂h́ ôŕ p̂áŝśîv́êĺŷ ĺîśt̂én̂ín̂ǵ îń ôń t̂h́ê ćôḿm̂ún̂íĉát̂íôńŝ b́êt́ŵéêń ŷóûŕ âṕp̂ án̂d́ ŷóûŕ ûśêŕŝ, án̂d́ îś â ṕr̂ér̂éq̂úîśît́ê f́ôŕ ĤT́T̂Ṕ/2 âńd̂ ḿâńŷ ńêẃ ŵéb̂ ṕl̂át̂f́ôŕm̂ ÁP̂Íŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 îńŝéĉúr̂é r̂éq̂úêśt̂ f́ôún̂d́}\n other {# îńŝéĉúr̂é r̂éq̂úêśt̂ś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ úŝé ĤT́T̂ṔŜ"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Ûśêś ĤT́T̂ṔŜ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Â f́âśt̂ ṕâǵê ĺôád̂ óv̂ér̂ á ĉél̂ĺûĺâŕ n̂ét̂ẃôŕk̂ én̂śûŕêś â ǵôód̂ ḿôb́îĺê úŝér̂ éx̂ṕêŕîén̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Îńt̂ér̂áĉt́îv́ê át̂ {timeInMs, number, seconds} ś"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Îńt̂ér̂áĉt́îv́ê ón̂ śîḿûĺât́êd́ m̂ób̂íl̂é n̂ét̂ẃôŕk̂ át̂ {timeInMs, number, seconds} ś"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Ŷóûŕ p̂áĝé l̂óâd́ŝ t́ôó ŝĺôẃl̂ý âńd̂ íŝ ńôt́ îńt̂ér̂áĉt́îv́ê ẃît́ĥín̂ 10 śêćôńd̂ś. L̂óôḱ ât́ t̂h́ê óp̂ṕôŕt̂ún̂ít̂íêś âńd̂ d́îáĝńôśt̂íĉś îń t̂h́ê \"Ṕêŕf̂ór̂ḿâńĉé\" ŝéĉt́îón̂ t́ô ĺêár̂ń ĥóŵ t́ô ím̂ṕr̂óv̂é."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "P̂áĝé l̂óâd́ îś n̂ót̂ f́âśt̂ én̂óûǵĥ ón̂ ḿôb́îĺê ńêt́ŵór̂ḱŝ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "P̂áĝé l̂óâd́ îś f̂áŝt́ êńôúĝh́ ôń m̂ób̂íl̂é n̂ét̂ẃôŕk̂ś"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Ĉát̂éĝór̂ý"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Ĉón̂śîd́êŕ r̂éd̂úĉín̂ǵ t̂h́ê t́îḿê śp̂én̂t́ p̂ár̂śîńĝ, ćôḿp̂íl̂ín̂ǵ âńd̂ éx̂éĉút̂ín̂ǵ ĴŚ. Ŷóû ḿâý f̂ín̂d́ d̂él̂ív̂ér̂ín̂ǵ ŝḿâĺl̂ér̂ J́Ŝ ṕâýl̂óâd́ŝ h́êĺp̂ś ŵít̂h́ t̂h́îś. [L̂éâŕn̂ ḿôŕê](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "M̂ín̂ím̂íẑé m̂áîń-t̂h́r̂éâd́ ŵór̂ḱ"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "M̂ín̂ím̂íẑéŝ ḿâín̂-t́ĥŕêád̂ ẃôŕk̂"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "T̂ó r̂éâćĥ t́ĥé m̂óŝt́ n̂úm̂b́êŕ ôf́ ûśêŕŝ, śît́êś ŝh́ôúl̂d́ ŵór̂ḱ âćr̂óŝś êv́êŕŷ ḿâj́ôŕ b̂ŕôẃŝér̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Ŝít̂é ŵór̂ḱŝ ćr̂óŝś-b̂ŕôẃŝér̂"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Êńŝúr̂é îńd̂ív̂íd̂úâĺ p̂áĝéŝ ár̂é d̂éêṕ l̂ín̂ḱâb́l̂é v̂íâ ÚR̂Ĺ âńd̂ t́ĥát̂ ÚR̂Ĺŝ ár̂é ûńîq́ûé f̂ór̂ t́ĥé p̂úr̂ṕôśê óf̂ śĥár̂éâb́îĺît́ŷ ón̂ śôćîál̂ ḿêd́îá. [L̂éâŕn̂ ḿôŕê](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Êáĉh́ p̂áĝé ĥáŝ á ÛŔL̂"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "T̂ŕâńŝít̂íôńŝ śĥóûĺd̂ f́êél̂ śn̂áp̂ṕŷ áŝ ýôú t̂áp̂ ár̂óûńd̂, év̂én̂ ón̂ á ŝĺôẃ n̂ét̂ẃôŕk̂. T́ĥíŝ éx̂ṕêŕîén̂ćê íŝ ḱêý t̂ó â úŝér̂'ś p̂ér̂ćêṕt̂íôń ôf́ p̂ér̂f́ôŕm̂án̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "P̂áĝé t̂ŕâńŝít̂íôńŝ d́ôń't̂ f́êél̂ ĺîḱê t́ĥéŷ b́l̂óĉḱ ôń t̂h́ê ńêt́ŵór̂ḱ"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Êśt̂ím̂át̂éd̂ Ín̂ṕût́ L̂át̂én̂ćŷ íŝ án̂ éŝt́îḿât́ê óf̂ h́ôẃ l̂ón̂ǵ ŷóûŕ âṕp̂ t́âḱêś t̂ó r̂éŝṕôńd̂ t́ô úŝér̂ ín̂ṕût́, îń m̂íl̂ĺîśêćôńd̂ś, d̂úr̂ín̂ǵ t̂h́ê b́ûśîéŝt́ 5ŝ ẃîńd̂óŵ óf̂ ṕâǵê ĺôád̂. Íf̂ ýôúr̂ ĺât́êńĉý îś ĥíĝh́êŕ t̂h́âń 50 m̂ś, ûśêŕŝ ḿâý p̂ér̂ćêív̂é ŷóûŕ âṕp̂ áŝ ĺâǵĝý. [L̂éâŕn̂ ḿôŕê](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Êśt̂ím̂át̂éd̂ Ín̂ṕût́ L̂át̂én̂ćŷ"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "F̂ír̂śt̂ Ćôńt̂én̂t́f̂úl̂ Ṕâín̂t́ m̂ár̂ḱŝ t́ĥé t̂ím̂é ât́ ŵh́îćĥ t́ĥé f̂ír̂śt̂ t́êx́t̂ ór̂ ím̂áĝé îś p̂áîńt̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "F̂ír̂śt̂ Ćôńt̂én̂t́f̂úl̂ Ṕâín̂t́"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "F̂ír̂śt̂ ĆP̂Ú Îd́l̂é m̂ár̂ḱŝ t́ĥé f̂ír̂śt̂ t́îḿê át̂ ẃĥíĉh́ t̂h́ê ṕâǵê'ś m̂áîń t̂h́r̂éâd́ îś q̂úîét̂ én̂óûǵĥ t́ô h́âńd̂ĺê ín̂ṕût́. [L̂éâŕn̂ ḿôŕê](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "F̂ír̂śt̂ ĆP̂Ú Îd́l̂é"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "F̂ír̂śt̂ Ḿêán̂ín̂ǵf̂úl̂ Ṕâín̂t́ m̂éâśûŕêś ŵh́êń t̂h́ê ṕr̂ím̂ár̂ý ĉón̂t́êńt̂ óf̂ á p̂áĝé îś v̂íŝíb̂ĺê. [Ĺêár̂ń m̂ór̂é](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "F̂ír̂śt̂ Ḿêán̂ín̂ǵf̂úl̂ Ṕâín̂t́"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "T̂ím̂é t̂ó îńt̂ér̂áĉt́îv́ê íŝ t́ĥé âḿôún̂t́ ôf́ t̂ím̂é ît́ t̂ák̂éŝ f́ôŕ t̂h́ê ṕâǵê t́ô b́êćôḿê f́ûĺl̂ý îńt̂ér̂áĉt́îv́ê. [Ĺêár̂ń m̂ór̂é](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "T̂ím̂é t̂ó Îńt̂ér̂áĉt́îv́ê"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "T̂h́ê ḿâx́îḿûḿ p̂ót̂én̂t́îál̂ F́îŕŝt́ Îńp̂út̂ D́êĺâý t̂h́ât́ ŷóûŕ ûśêŕŝ ćôúl̂d́ êx́p̂ér̂íêńĉé îś t̂h́ê d́ûŕât́îón̂, ín̂ ḿîĺl̂íŝéĉón̂d́ŝ, óf̂ t́ĥé l̂ón̂ǵêśt̂ t́âśk̂. [Ĺêár̂ń m̂ór̂é](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "M̂áx̂ Ṕôt́êńt̂íâĺ F̂ír̂śt̂ Ín̂ṕût́ D̂él̂áŷ"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Ŝṕêéd̂ Ín̂d́êx́ ŝh́ôẃŝ h́ôẃ q̂úîćk̂ĺŷ t́ĥé ĉón̂t́êńt̂ś ôf́ â ṕâǵê ár̂é v̂íŝíb̂ĺŷ ṕôṕûĺât́êd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Ŝṕêéd̂ Ín̂d́êx́"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Ŝúm̂ óf̂ ál̂ĺ t̂ím̂é p̂ér̂íôd́ŝ b́êt́ŵéêń F̂ĆP̂ án̂d́ T̂ím̂é t̂ó Îńt̂ér̂áĉt́îv́ê, ẃĥén̂ t́âśk̂ ĺêńĝt́ĥ éx̂ćêéd̂éd̂ 50ḿŝ, éx̂ṕr̂éŝśêd́ îń m̂íl̂ĺîśêćôńd̂ś."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "T̂ót̂ál̂ B́l̂óĉḱîńĝ T́îḿê"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "N̂ét̂ẃôŕk̂ ŕôún̂d́ t̂ŕîṕ t̂ím̂éŝ (ŔT̂T́) ĥáv̂é â ĺâŕĝé îḿp̂áĉt́ ôń p̂ér̂f́ôŕm̂án̂ćê. Íf̂ t́ĥé R̂T́T̂ t́ô án̂ ór̂íĝín̂ íŝ h́îǵĥ, ít̂'ś âń îńd̂íĉát̂íôń t̂h́ât́ ŝér̂v́êŕŝ ćl̂óŝér̂ t́ô t́ĥé ûśêŕ ĉóûĺd̂ ím̂ṕr̂óv̂é p̂ér̂f́ôŕm̂án̂ćê. [Ĺêár̂ń m̂ór̂é](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "N̂ét̂ẃôŕk̂ Ŕôún̂d́ T̂ŕîṕ T̂ím̂éŝ"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Ŝér̂v́êŕ l̂át̂én̂ćîéŝ ćâń îḿp̂áĉt́ ŵéb̂ ṕêŕf̂ór̂ḿâńĉé. Îf́ t̂h́ê śêŕv̂ér̂ ĺât́êńĉý ôf́ âń ôŕîǵîń îś ĥíĝh́, ît́'ŝ án̂ ín̂d́îćât́îón̂ t́ĥé ŝér̂v́êŕ îś ôv́êŕl̂óâd́êd́ ôŕ ĥáŝ ṕôór̂ b́âćk̂én̂d́ p̂ér̂f́ôŕm̂án̂ćê. [Ĺêár̂ń m̂ór̂é](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Ŝér̂v́êŕ B̂áĉḱêńd̂ Ĺât́êńĉíêś"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Â śêŕv̂íĉé ŵór̂ḱêŕ êńâb́l̂éŝ ýôúr̂ ẃêb́ âṕp̂ t́ô b́ê ŕêĺîáb̂ĺê ín̂ ún̂ṕr̂éd̂íĉt́âb́l̂é n̂ét̂ẃôŕk̂ ćôńd̂ít̂íôńŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` d̂óêś n̂ót̂ ŕêśp̂ón̂d́ ŵít̂h́ â 200 ẃĥén̂ óf̂f́l̂ín̂é"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` r̂éŝṕôńd̂ś ŵít̂h́ â 200 ẃĥén̂ óf̂f́l̂ín̂é"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "L̂íĝh́t̂h́ôúŝé ĉóûĺd̂ń't̂ ŕêád̂ t́ĥé `start_url` f̂ŕôḿ t̂h́ê ḿâńîf́êśt̂. Áŝ á r̂éŝúl̂t́, t̂h́ê `start_url` ẃâś âśŝúm̂éd̂ t́ô b́ê t́ĥé d̂óĉúm̂én̂t́'ŝ ÚR̂Ĺ. Êŕr̂ór̂ ḿêśŝáĝé: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Ôv́êŕ B̂úd̂ǵêt́"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "K̂éêṕ t̂h́ê q́ûán̂t́ît́ŷ án̂d́ ŝíẑé ôf́ n̂ét̂ẃôŕk̂ ŕêq́ûéŝt́ŝ ún̂d́êŕ t̂h́ê t́âŕĝét̂ś ŝét̂ b́ŷ t́ĥé p̂ŕôv́îd́êd́ p̂ér̂f́ôŕm̂án̂ćê b́ûd́ĝét̂. [Ĺêár̂ń m̂ór̂é](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count, plural,\n =1 {1 r̂éq̂úêśt̂}\n other {# ŕêq́ûéŝt́ŝ}\n }"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "P̂ér̂f́ôŕm̂án̂ćê b́ûd́ĝét̂"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Îf́ ŷóû'v́ê ál̂ŕêád̂ý ŝét̂ úp̂ H́T̂T́P̂Ś, m̂ák̂é ŝúr̂é t̂h́ât́ ŷóû ŕêd́îŕêćt̂ ál̂ĺ ĤT́T̂Ṕ t̂ŕâf́f̂íĉ t́ô H́T̂T́P̂Ś îń ôŕd̂ér̂ t́ô én̂áb̂ĺê śêćûŕê ẃêb́ f̂éât́ûŕêś f̂ór̂ ál̂ĺ ŷóûŕ ûśêŕŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ ŕêd́îŕêćt̂ H́T̂T́P̂ t́r̂áf̂f́îć t̂ó ĤT́T̂ṔŜ"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "R̂éd̂ír̂éĉt́ŝ H́T̂T́P̂ t́r̂áf̂f́îć t̂ó ĤT́T̂ṔŜ"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "R̂éd̂ír̂éĉt́ŝ ín̂t́r̂ód̂úĉé âd́d̂ít̂íôńâĺ d̂él̂áŷś b̂éf̂ór̂é t̂h́ê ṕâǵê ćâń b̂é l̂óâd́êd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Âv́ôíd̂ ḿûĺt̂íp̂ĺê ṕâǵê ŕêd́îŕêćt̂ś"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "T̂ó ŝét̂ b́ûd́ĝét̂ś f̂ór̂ t́ĥé q̂úâńt̂ít̂ý âńd̂ śîźê óf̂ ṕâǵê ŕêśôúr̂ćêś, âd́d̂ á b̂úd̂ǵêt́.ĵśôń f̂íl̂é. [L̂éâŕn̂ ḿôŕê](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount, plural, =1 {1 r̂éq̂úêśt̂ • {byteCount, number, bytes} ḰB̂} other {# ŕêq́ûéŝt́ŝ • {byteCount, number, bytes} ḰB̂}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "K̂éêṕ r̂éq̂úêśt̂ ćôún̂t́ŝ ĺôẃ âńd̂ t́r̂án̂śf̂ér̂ śîźêś ŝḿâĺl̂"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Ĉán̂ón̂íĉál̂ ĺîńk̂ś ŝúĝǵêśt̂ ẃĥíĉh́ ÛŔL̂ t́ô śĥóŵ ín̂ śêár̂ćĥ ŕêśûĺt̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "M̂úl̂t́îṕl̂é ĉón̂f́l̂íĉt́îńĝ ÚR̂Ĺŝ ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "P̂óîńt̂ś t̂ó â d́îf́f̂ér̂én̂t́ d̂óm̂áîń ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Îńv̂ál̂íd̂ ÚR̂Ĺ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "P̂óîńt̂ś t̂ó âńôt́ĥér̂ `hreflang` ĺôćât́îón̂ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "R̂él̂át̂ív̂é ÛŔL̂ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "P̂óîńt̂ś t̂ó t̂h́ê d́ôḿâín̂'ś r̂óôt́ ÛŔL̂ (t́ĥé ĥóm̂ép̂áĝé), îńŝt́êád̂ óf̂ án̂ éq̂úîv́âĺêńt̂ ṕâǵê óf̂ ćôńt̂én̂t́"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ d̂óêś n̂ót̂ h́âv́ê á v̂ál̂íd̂ `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "D̂óĉúm̂én̂t́ ĥáŝ á v̂ál̂íd̂ `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "F̂ón̂t́ ŝíẑéŝ ĺêśŝ t́ĥán̂ 12ṕx̂ ár̂é t̂óô śm̂ál̂ĺ t̂ó b̂é l̂éĝíb̂ĺê án̂d́ r̂éq̂úîŕê ḿôb́îĺê v́îśît́ôŕŝ t́ô “ṕîńĉh́ t̂ó ẑóôḿ” îń ôŕd̂ér̂ t́ô ŕêád̂. Śt̂ŕîv́ê t́ô h́âv́ê >60% óf̂ ṕâǵê t́êx́t̂ ≥12ṕx̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} l̂éĝíb̂ĺê t́êx́t̂"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "T̂éx̂t́ îś îĺl̂éĝíb̂ĺê b́êćâúŝé t̂h́êŕê'ś n̂ó v̂íêẃp̂ór̂t́ m̂ét̂á t̂áĝ óp̂t́îḿîźêd́ f̂ór̂ ḿôb́îĺê śĉŕêén̂ś."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} ôf́ t̂éx̂t́ îś t̂óô śm̂ál̂ĺ (b̂áŝéd̂ ón̂ {decimalProportionVisited, number, extendedPercent} śâḿp̂ĺê)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ d̂óêśn̂'t́ ûśê ĺêǵîb́l̂é f̂ón̂t́ ŝíẑéŝ"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "D̂óĉúm̂én̂t́ ûśêś l̂éĝíb̂ĺê f́ôńt̂ śîźêś"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "ĥŕêf́l̂án̂ǵ l̂ín̂ḱŝ t́êĺl̂ śêár̂ćĥ én̂ǵîńêś ŵh́ât́ v̂ér̂śîón̂ óf̂ á p̂áĝé t̂h́êý ŝh́ôúl̂d́ l̂íŝt́ îń ŝéâŕĉh́ r̂éŝúl̂t́ŝ f́ôŕ â ǵîv́êń l̂án̂ǵûáĝé ôŕ r̂éĝíôń. [L̂éâŕn̂ ḿôŕê](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ d̂óêśn̂'t́ ĥáv̂é â v́âĺîd́ `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "D̂óĉúm̂én̂t́ ĥáŝ á v̂ál̂íd̂ `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "P̂áĝéŝ ẃît́ĥ ún̂śûćĉéŝśf̂úl̂ H́T̂T́P̂ śt̂át̂úŝ ćôd́êś m̂áŷ ńôt́ b̂é îńd̂éx̂éd̂ ṕr̂óp̂ér̂ĺŷ. [Ĺêár̂ń m̂ór̂é](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "P̂áĝé ĥáŝ ún̂śûćĉéŝśf̂úl̂ H́T̂T́P̂ śt̂át̂úŝ ćôd́ê"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "P̂áĝé ĥáŝ śûćĉéŝśf̂úl̂ H́T̂T́P̂ śt̂át̂úŝ ćôd́ê"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Ŝéâŕĉh́ êńĝín̂éŝ ár̂é ûńâb́l̂é t̂ó îńĉĺûd́ê ýôúr̂ ṕâǵêś îń ŝéâŕĉh́ r̂éŝúl̂t́ŝ íf̂ t́ĥéŷ d́ôń't̂ h́âv́ê ṕêŕm̂íŝśîón̂ t́ô ćr̂áŵĺ t̂h́êḿ. [L̂éâŕn̂ ḿôŕê](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "P̂áĝé îś b̂ĺôćk̂éd̂ f́r̂óm̂ ín̂d́êx́îńĝ"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "P̂áĝé îśn̂’t́ b̂ĺôćk̂éd̂ f́r̂óm̂ ín̂d́êx́îńĝ"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "D̂éŝćr̂íp̂t́îv́ê ĺîńk̂ t́êx́t̂ h́êĺp̂ś ŝéâŕĉh́ êńĝín̂éŝ ún̂d́êŕŝt́âńd̂ ýôúr̂ ćôńt̂én̂t́. [L̂éâŕn̂ ḿôŕê](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 l̂ín̂ḱ f̂óûńd̂}\n other {# ĺîńk̂ś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "L̂ín̂ḱŝ d́ô ńôt́ ĥáv̂é d̂éŝćr̂íp̂t́îv́ê t́êx́t̂"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "L̂ín̂ḱŝ h́âv́ê d́êśĉŕîṕt̂ív̂é t̂éx̂t́"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "R̂ún̂ t́ĥé [Ŝt́r̂úĉt́ûŕêd́ D̂át̂á T̂éŝt́îńĝ T́ôól̂](https://search.google.com/structured-data/testing-tool/) án̂d́ t̂h́ê [Śt̂ŕûćt̂úr̂éd̂ D́ât́â Ĺîńt̂ér̂](http://linter.structured-data.org/) t́ô v́âĺîd́ât́ê śt̂ŕûćt̂úr̂éd̂ d́ât́â. [Ĺêár̂ń m̂ór̂é](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Ŝt́r̂úĉt́ûŕêd́ d̂át̂á îś v̂ál̂íd̂"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "M̂ét̂á d̂éŝćr̂íp̂t́îón̂ś m̂áŷ b́ê ín̂ćl̂úd̂éd̂ ín̂ śêár̂ćĥ ŕêśûĺt̂ś t̂ó ĉón̂ćîśêĺŷ śûḿm̂ár̂íẑé p̂áĝé ĉón̂t́êńt̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "D̂éŝćr̂íp̂t́îón̂ t́êx́t̂ íŝ ém̂ṕt̂ý."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ d̂óêś n̂ót̂ h́âv́ê á m̂ét̂á d̂éŝćr̂íp̂t́îón̂"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "D̂óĉúm̂én̂t́ ĥáŝ á m̂ét̂á d̂éŝćr̂íp̂t́îón̂"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Ŝéâŕĉh́ êńĝín̂éŝ ćâń't̂ ín̂d́êx́ p̂ĺûǵîń ĉón̂t́êńt̂, án̂d́ m̂án̂ý d̂év̂íĉéŝ ŕêśt̂ŕîćt̂ ṕl̂úĝín̂ś ôŕ d̂ón̂'t́ ŝúp̂ṕôŕt̂ t́ĥém̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "D̂óĉúm̂én̂t́ ûśêś p̂ĺûǵîńŝ"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "D̂óĉúm̂én̂t́ âv́ôíd̂ś p̂ĺûǵîńŝ"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Îf́ ŷóûŕ r̂ób̂ót̂ś.t̂x́t̂ f́îĺê íŝ ḿâĺf̂ór̂ḿêd́, ĉŕâẃl̂ér̂ś m̂áŷ ńôt́ b̂é âb́l̂é t̂ó ûńd̂ér̂śt̂án̂d́ ĥóŵ ýôú ŵán̂t́ ŷóûŕ ŵéb̂śît́ê t́ô b́ê ćr̂áŵĺêd́ ôŕ îńd̂éx̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "R̂éq̂úêśt̂ f́ôŕ r̂ób̂ót̂ś.t̂x́t̂ ŕêt́ûŕn̂éd̂ H́T̂T́P̂ śt̂át̂úŝ: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount, plural,\n =1 {1 êŕr̂ór̂ f́ôún̂d́}\n other {# êŕr̂ór̂ś f̂óûńd̂}\n }"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô d́ôẃn̂ĺôád̂ á r̂ób̂ót̂ś.t̂x́t̂ f́îĺê"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "r̂ób̂ót̂ś.t̂x́t̂ íŝ ńôt́ v̂ál̂íd̂"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "r̂ób̂ót̂ś.t̂x́t̂ íŝ v́âĺîd́"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Îńt̂ér̂áĉt́îv́ê él̂ém̂én̂t́ŝ ĺîḱê b́ût́t̂ón̂ś âńd̂ ĺîńk̂ś ŝh́ôúl̂d́ b̂é l̂ár̂ǵê én̂óûǵĥ (48x́48p̂x́), âńd̂ h́âv́ê én̂óûǵĥ śp̂áĉé âŕôún̂d́ t̂h́êḿ, t̂ó b̂é êáŝý êńôúĝh́ t̂ó t̂áp̂ ẃît́ĥóût́ ôv́êŕl̂áp̂ṕîńĝ ón̂t́ô ót̂h́êŕ êĺêḿêńt̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} âṕp̂ŕôṕr̂íât́êĺŷ śîźêd́ t̂áp̂ t́âŕĝét̂ś"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "T̂áp̂ t́âŕĝét̂ś âŕê t́ôó ŝḿâĺl̂ b́êćâúŝé t̂h́êŕê'ś n̂ó v̂íêẃp̂ór̂t́ m̂ét̂á t̂áĝ óp̂t́îḿîźêd́ f̂ór̂ ḿôb́îĺê śĉŕêén̂ś"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "T̂áp̂ t́âŕĝét̂ś âŕê ńôt́ ŝíẑéd̂ áp̂ṕr̂óp̂ŕîát̂él̂ý"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Ôv́êŕl̂áp̂ṕîńĝ T́âŕĝét̂"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "T̂áp̂ T́âŕĝét̂"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "T̂áp̂ t́âŕĝét̂ś âŕê śîźêd́ âṕp̂ŕôṕr̂íât́êĺŷ"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "T̂h́ê śêŕv̂íĉé ŵór̂ḱêŕ îś t̂h́ê t́êćĥńôĺôǵŷ t́ĥát̂ én̂áb̂ĺêś ŷóûŕ âṕp̂ t́ô úŝé m̂án̂ý P̂ŕôǵr̂éŝśîv́ê Ẃêb́ Âṕp̂ f́êát̂úr̂éŝ, śûćĥ áŝ óf̂f́l̂ín̂é, âd́d̂ t́ô h́ôḿêśĉŕêén̂, án̂d́ p̂úŝh́ n̂ót̂íf̂íĉát̂íôńŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "T̂h́îś p̂áĝé îś ĉón̂t́r̂ól̂ĺêd́ b̂ý â śêŕv̂íĉé ŵór̂ḱêŕ, ĥóŵév̂ér̂ ńô `start_url` ẃâś f̂óûńd̂ b́êćâúŝé m̂án̂íf̂éŝt́ f̂áîĺêd́ t̂ó p̂ár̂śê áŝ v́âĺîd́ ĴŚÔŃ"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "T̂h́îś p̂áĝé îś ĉón̂t́r̂ól̂ĺêd́ b̂ý â śêŕv̂íĉé ŵór̂ḱêŕ, ĥóŵév̂ér̂ t́ĥé `start_url` ({startUrl}) îś n̂ót̂ ín̂ t́ĥé ŝér̂v́îćê ẃôŕk̂ér̂'ś ŝćôṕê ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "T̂h́îś p̂áĝé îś ĉón̂t́r̂ól̂ĺêd́ b̂ý â śêŕv̂íĉé ŵór̂ḱêŕ, ĥóŵév̂ér̂ ńô `start_url` ẃâś f̂óûńd̂ b́êćâúŝé n̂ó m̂án̂íf̂éŝt́ ŵáŝ f́êt́ĉh́êd́."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "T̂h́îś ôŕîǵîń ĥáŝ ón̂é ôŕ m̂ór̂é ŝér̂v́îćê ẃôŕk̂ér̂ś, ĥóŵév̂ér̂ t́ĥé p̂áĝé ({pageUrl}) îś n̂ót̂ ín̂ śĉóp̂é."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ ŕêǵîśt̂ér̂ á ŝér̂v́îćê ẃôŕk̂ér̂ t́ĥát̂ ćôńt̂ŕôĺŝ ṕâǵê án̂d́ `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "R̂éĝíŝt́êŕŝ á ŝér̂v́îćê ẃôŕk̂ér̂ t́ĥát̂ ćôńt̂ŕôĺŝ ṕâǵê án̂d́ `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Â t́ĥém̂éd̂ śp̂ĺâśĥ śĉŕêén̂ én̂śûŕêś â h́îǵĥ-q́ûál̂ít̂ý êx́p̂ér̂íêńĉé ŵh́êń ûśêŕŝ ĺâún̂ćĥ ýôúr̂ áp̂ṕ f̂ŕôḿ t̂h́êír̂ h́ôḿêśĉŕêén̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Îś n̂ót̂ ćôńf̂íĝúr̂éd̂ f́ôŕ â ćûśt̂óm̂ śp̂ĺâśĥ śĉŕêén̂"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Ĉón̂f́îǵûŕêd́ f̂ór̂ á ĉúŝt́ôḿ ŝṕl̂áŝh́ ŝćr̂éêń"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "T̂h́ê b́r̂óŵśêŕ âd́d̂ŕêśŝ b́âŕ ĉán̂ b́ê t́ĥém̂éd̂ t́ô ḿât́ĉh́ ŷóûŕ ŝít̂é. [L̂éâŕn̂ ḿôŕê](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ śêt́ â t́ĥém̂é ĉól̂ór̂ f́ôŕ t̂h́ê ád̂d́r̂éŝś b̂ár̂."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Ŝét̂ś â t́ĥém̂é ĉól̂ór̂ f́ôŕ t̂h́ê ád̂d́r̂éŝś b̂ár̂."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "M̂áîń-T̂h́r̂éâd́ B̂ĺôćk̂ín̂ǵ T̂ím̂é"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "T̂h́îŕd̂-Ṕâŕt̂ý"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "T̂h́îŕd̂-ṕâŕt̂ý ĉód̂é ĉán̂ śîǵn̂íf̂íĉán̂t́l̂ý îḿp̂áĉt́ l̂óâd́ p̂ér̂f́ôŕm̂án̂ćê. Ĺîḿît́ t̂h́ê ńûḿb̂ér̂ óf̂ ŕêd́ûńd̂án̂t́ t̂h́îŕd̂-ṕâŕt̂ý p̂ŕôv́îd́êŕŝ án̂d́ t̂ŕŷ t́ô ĺôád̂ t́ĥír̂d́-p̂ár̂t́ŷ ćôd́ê áf̂t́êŕ ŷóûŕ p̂áĝé ĥáŝ ṕr̂ím̂ár̂íl̂ý f̂ín̂íŝh́êd́ l̂óâd́îńĝ. [Ĺêár̂ń m̂ór̂é](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "T̂h́îŕd̂-ṕâŕt̂ý ĉód̂é b̂ĺôćk̂éd̂ t́ĥé m̂áîń t̂h́r̂éâd́ f̂ór̂ {timeInMs, number, milliseconds} ḿŝ"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "R̂éd̂úĉé t̂h́ê ím̂ṕâćt̂ óf̂ t́ĥír̂d́-p̂ár̂t́ŷ ćôd́ê"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "M̂ín̂ím̂íẑé t̂h́îŕd̂-ṕâŕt̂ý ûśâǵê"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "T̂ím̂é T̂ó F̂ír̂śt̂ B́ŷt́ê íd̂én̂t́îf́îéŝ t́ĥé t̂ím̂é ât́ ŵh́îćĥ ýôúr̂ śêŕv̂ér̂ śêńd̂ś â ŕêśp̂ón̂śê. [Ĺêár̂ń m̂ór̂é](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "R̂óôt́ d̂óĉúm̂én̂t́ t̂óôḱ {timeInMs, number, milliseconds} m̂ś"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "R̂éd̂úĉé ŝér̂v́êŕ r̂éŝṕôńŝé t̂ím̂éŝ (T́T̂F́B̂)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Ŝér̂v́êŕ r̂éŝṕôńŝé t̂ím̂éŝ ár̂é l̂óŵ (T́T̂F́B̂)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "D̂úr̂át̂íôń"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Ŝt́âŕt̂ T́îḿê"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "T̂ýp̂é"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Ĉón̂śîd́êŕ îńŝt́r̂úm̂én̂t́îńĝ ýôúr̂ áp̂ṕ ŵít̂h́ t̂h́ê Úŝér̂ T́îḿîńĝ ÁP̂Í t̂ó m̂éâśûŕê ýôúr̂ áp̂ṕ'ŝ ŕêál̂-ẃôŕl̂d́ p̂ér̂f́ôŕm̂án̂ćê d́ûŕîńĝ ḱêý ûśêŕ êx́p̂ér̂íêńĉéŝ. [Ĺêár̂ń m̂ór̂é](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount, plural,\n =1 {1 ûśêŕ t̂ím̂ín̂ǵ}\n other {# ûśêŕ t̂ím̂ín̂ǵŝ}\n }"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Ûśêŕ T̂ím̂ín̂ǵ m̂ár̂ḱŝ án̂d́ m̂éâśûŕêś"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Â ṕr̂éĉón̂ńêćt̂ <ĺîńk̂> ẃâś f̂óûńd̂ f́ôŕ \"{securityOrigin}\" b̂út̂ ẃâś n̂ót̂ úŝéd̂ b́ŷ t́ĥé b̂ŕôẃŝér̂. Ćĥéĉḱ t̂h́ât́ ŷóû ár̂é ûśîńĝ t́ĥé `crossorigin` ât́t̂ŕîb́ût́ê ṕr̂óp̂ér̂ĺŷ."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Ĉón̂śîd́êŕ âd́d̂ín̂ǵ `preconnect` ôŕ `dns-prefetch` r̂éŝóûŕĉé ĥín̂t́ŝ t́ô éŝt́âb́l̂íŝh́ êár̂ĺŷ ćôńn̂éĉt́îón̂ś t̂ó îḿp̂ór̂t́âńt̂ t́ĥír̂d́-p̂ár̂t́ŷ ór̂íĝín̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "P̂ŕêćôńn̂éĉt́ t̂ó r̂éq̂úîŕêd́ ôŕîǵîńŝ"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Â ṕr̂él̂óâd́ <l̂ín̂ḱ> ŵáŝ f́ôún̂d́ f̂ór̂ \"{preloadURL}\" b́ût́ ŵáŝ ńôt́ ûśêd́ b̂ý t̂h́ê b́r̂óŵśêŕ. Ĉh́êćk̂ t́ĥát̂ ýôú âŕê úŝín̂ǵ t̂h́ê `crossorigin` át̂t́r̂íb̂út̂é p̂ŕôṕêŕl̂ý."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Ĉón̂śîd́êŕ ûśîńĝ `<link rel=preload>` t́ô ṕr̂íôŕît́îźê f́êt́ĉh́îńĝ ŕêśôúr̂ćêś t̂h́ât́ âŕê ćûŕr̂én̂t́l̂ý r̂éq̂úêśt̂éd̂ ĺât́êŕ îń p̂áĝé l̂óâd́. [L̂éâŕn̂ ḿôŕê](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "P̂ŕêĺôád̂ ḱêý r̂éq̂úêśt̂ś"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Âd́d̂ á `<meta name=\"viewport\">` t̂áĝ t́ô óp̂t́îḿîźê ýôúr̂ áp̂ṕ f̂ór̂ ḿôb́îĺê śĉŕêén̂ś. [L̂éâŕn̂ ḿôŕê](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "N̂ó `<meta name=\"viewport\">` t̂áĝ f́ôún̂d́"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ h́âv́ê á `<meta name=\"viewport\">` t̂áĝ ẃît́ĥ `width` ór̂ `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ĥáŝ á `<meta name=\"viewport\">` t̂áĝ ẃît́ĥ `width` ór̂ `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Ŷóûŕ âṕp̂ śĥóûĺd̂ d́îśp̂ĺâý ŝóm̂é ĉón̂t́êńt̂ ẃĥén̂ J́âv́âŚĉŕîṕt̂ íŝ d́îśâb́l̂éd̂, év̂én̂ íf̂ ít̂'ś ĵúŝt́ â ẃâŕn̂ín̂ǵ t̂ó t̂h́ê úŝér̂ t́ĥát̂ J́âv́âŚĉŕîṕt̂ íŝ ŕêq́ûír̂éd̂ t́ô úŝé t̂h́ê áp̂ṕ. [L̂éâŕn̂ ḿôŕê](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "T̂h́ê ṕâǵê b́ôd́ŷ śĥóûĺd̂ ŕêńd̂ér̂ śôḿê ćôńt̂én̂t́ îf́ ît́ŝ śĉŕîṕt̂ś âŕê ńôt́ âv́âíl̂áb̂ĺê."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "D̂óêś n̂ót̂ ṕr̂óv̂íd̂é f̂ál̂ĺb̂áĉḱ ĉón̂t́êńt̂ ẃĥén̂ J́âv́âŚĉŕîṕt̂ íŝ ńôt́ âv́âíl̂áb̂ĺê"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Ĉón̂t́âín̂ś ŝóm̂é ĉón̂t́êńt̂ ẃĥén̂ J́âv́âŚĉŕîṕt̂ íŝ ńôt́ âv́âíl̂áb̂ĺê"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Îf́ ŷóû'ŕê b́ûíl̂d́îńĝ á P̂ŕôǵr̂éŝśîv́ê Ẃêb́ Âṕp̂, ćôńŝíd̂ér̂ úŝín̂ǵ â śêŕv̂íĉé ŵór̂ḱêŕ ŝó t̂h́ât́ ŷóûŕ âṕp̂ ćâń ŵór̂ḱ ôf́f̂ĺîńê. [Ĺêár̂ń m̂ór̂é](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Ĉúr̂ŕêńt̂ ṕâǵê d́ôéŝ ńôt́ r̂éŝṕôńd̂ ẃît́ĥ á 200 ŵh́êń ôf́f̂ĺîńê"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Ĉúr̂ŕêńt̂ ṕâǵê ŕêśp̂ón̂d́ŝ ẃît́ĥ á 200 ŵh́êń ôf́f̂ĺîńê"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "T̂h́ê ṕâǵê ḿâý n̂ót̂ b́ê ĺôád̂ín̂ǵ ôf́f̂ĺîńê b́êćâúŝé ŷóûŕ t̂éŝt́ ÛŔL̂ ({requested}) ẃâś r̂éd̂ír̂éĉt́êd́ t̂ó \"{final}\". T̂ŕŷ t́êśt̂ín̂ǵ t̂h́ê śêćôńd̂ ÚR̂Ĺ d̂ír̂éĉt́l̂ý."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ím̂ṕr̂óv̂é t̂h́ê úŝáĝé ôf́ ÂŔÎÁ îń ŷóûŕ âṕp̂ĺîćât́îón̂ ẃĥíĉh́ m̂áŷ én̂h́âńĉé t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ûśêŕŝ óf̂ áŝśîśt̂ív̂é t̂éĉh́n̂ól̂óĝý, l̂ík̂é â śĉŕêén̂ ŕêád̂ér̂."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ÂŔÎÁ"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ṕr̂óv̂íd̂é âĺt̂ér̂ńât́îv́ê ćôńt̂én̂t́ f̂ór̂ áûd́îó âńd̂ v́îd́êó. T̂h́îś m̂áŷ ím̂ṕr̂óv̂é t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ûśêŕŝ ẃît́ĥ h́êár̂ín̂ǵ ôŕ v̂íŝíôń îḿp̂áîŕm̂én̂t́ŝ."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Âúd̂íô án̂d́ v̂íd̂éô"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "T̂h́êśê ít̂ém̂ś ĥíĝh́l̂íĝh́t̂ ćôḿm̂ón̂ áĉćêśŝíb̂íl̂ít̂ý b̂éŝt́ p̂ŕâćt̂íĉéŝ."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "B̂éŝt́ p̂ŕâćt̂íĉéŝ"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "T̂h́êśê ćĥéĉḱŝ h́îǵĥĺîǵĥt́ ôṕp̂ór̂t́ûńît́îéŝ t́ô [ím̂ṕr̂óv̂é t̂h́ê áĉćêśŝíb̂íl̂ít̂ý ôf́ ŷóûŕ ŵéb̂ áp̂ṕ](https://developers.google.com/web/fundamentals/accessibility). Ôńl̂ý â śûb́ŝét̂ óf̂ áĉćêśŝíb̂íl̂ít̂ý îśŝúêś ĉán̂ b́ê áût́ôḿât́îćâĺl̂ý d̂ét̂éĉt́êd́ ŝó m̂án̂úâĺ t̂éŝt́îńĝ íŝ ál̂śô én̂ćôúr̂áĝéd̂."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "T̂h́êśê ít̂ém̂ś âd́d̂ŕêśŝ ár̂éâś ŵh́îćĥ án̂ áût́ôḿât́êd́ t̂éŝt́îńĝ t́ôól̂ ćâńn̂ót̂ ćôv́êŕ. L̂éâŕn̂ ḿôŕê ín̂ óûŕ ĝúîd́ê ón̂ [ćôńd̂úĉt́îńĝ án̂ áĉćêśŝíb̂íl̂ít̂ý r̂év̂íêẃ](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Âćĉéŝśîb́îĺît́ŷ"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ím̂ṕr̂óv̂é t̂h́ê ĺêǵîb́îĺît́ŷ óf̂ ýôúr̂ ćôńt̂én̂t́."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Ĉón̂t́r̂áŝt́"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ím̂ṕr̂óv̂é t̂h́ê ín̂t́êŕp̂ŕêt́ât́îón̂ óf̂ ýôúr̂ ćôńt̂én̂t́ b̂ý ûśêŕŝ ín̂ d́îf́f̂ér̂én̂t́ l̂óĉál̂éŝ."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Îńt̂ér̂ńât́îón̂ál̂íẑát̂íôń âńd̂ ĺôćâĺîźât́îón̂"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ím̂ṕr̂óv̂é t̂h́ê śêḿâńt̂íĉś ôf́ t̂h́ê ćôńt̂ŕôĺŝ ín̂ ýôúr̂ áp̂ṕl̂íĉát̂íôń. T̂h́îś m̂áŷ én̂h́âńĉé t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ûśêŕŝ óf̂ áŝśîśt̂ív̂é t̂éĉh́n̂ól̂óĝý, l̂ík̂é â śĉŕêén̂ ŕêád̂ér̂."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "N̂ám̂éŝ án̂d́ l̂áb̂él̂ś"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô ím̂ṕr̂óv̂é k̂éŷb́ôár̂d́ n̂áv̂íĝát̂íôń îń ŷóûŕ âṕp̂ĺîćât́îón̂."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "N̂áv̂íĝát̂íôń"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "T̂h́êśê ár̂é ôṕp̂ór̂t́ûńît́îéŝ t́ô t́ô ím̂ṕr̂óv̂é t̂h́ê éx̂ṕêŕîén̂ćê óf̂ ŕêád̂ín̂ǵ t̂áb̂úl̂ár̂ ór̂ ĺîśt̂ d́ât́â úŝín̂ǵ âśŝíŝt́îv́ê t́êćĥńôĺôǵŷ, ĺîḱê á ŝćr̂éêń r̂éâd́êŕ."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "T̂áb̂ĺêś âńd̂ ĺîśt̂ś"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "B̂éŝt́ P̂ŕâćt̂íĉéŝ"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "P̂ér̂f́ôŕm̂án̂ćê b́ûd́ĝét̂ś ŝét̂ śt̂án̂d́âŕd̂ś f̂ór̂ t́ĥé p̂ér̂f́ôŕm̂án̂ćê óf̂ ýôúr̂ śît́ê."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "B̂úd̂ǵêt́ŝ"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "M̂ór̂é îńf̂ór̂ḿât́îón̂ áb̂óût́ t̂h́ê ṕêŕf̂ór̂ḿâńĉé ôf́ ŷóûŕ âṕp̂ĺîćât́îón̂. T́ĥéŝé n̂úm̂b́êŕŝ d́ôń't̂ [d́îŕêćt̂ĺŷ áf̂f́êćt̂](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) t́ĥé P̂ér̂f́ôŕm̂án̂ćê śĉór̂é."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "D̂íâǵn̂óŝt́îćŝ"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "T̂h́ê ḿôśt̂ ćr̂ít̂íĉál̂ áŝṕêćt̂ óf̂ ṕêŕf̂ór̂ḿâńĉé îś ĥóŵ q́ûíĉḱl̂ý p̂íx̂él̂ś âŕê ŕêńd̂ér̂éd̂ ón̂śĉŕêén̂. Ḱêý m̂ét̂ŕîćŝ: F́îŕŝt́ Ĉón̂t́êńt̂f́ûĺ P̂áîńt̂, F́îŕŝt́ M̂éâńîńĝf́ûĺ P̂áîńt̂"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "F̂ír̂śt̂ Ṕâín̂t́ Îḿp̂ŕôv́êḿêńt̂ś"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "T̂h́êśê śûǵĝéŝt́îón̂ś ĉán̂ h́êĺp̂ ýôúr̂ ṕâǵê ĺôád̂ f́âśt̂ér̂. T́ĥéŷ d́ôń't̂ [d́îŕêćt̂ĺŷ áf̂f́êćt̂](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) t́ĥé P̂ér̂f́ôŕm̂án̂ćê śĉór̂é."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Ôṕp̂ór̂t́ûńît́îéŝ"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "M̂ét̂ŕîćŝ"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Êńĥán̂ćê t́ĥé ôv́êŕâĺl̂ ĺôád̂ín̂ǵ êx́p̂ér̂íêńĉé, ŝó t̂h́ê ṕâǵê íŝ ŕêśp̂ón̂śîv́ê án̂d́ r̂éâd́ŷ t́ô úŝé âś ŝóôń âś p̂óŝśîb́l̂é. K̂éŷ ḿêt́r̂íĉś: T̂ím̂é t̂ó Îńt̂ér̂áĉt́îv́ê, Śp̂éêd́ Îńd̂éx̂"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Ôv́êŕâĺl̂ Ím̂ṕr̂óv̂ém̂én̂t́ŝ"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "P̂ér̂f́ôŕm̂án̂ćê"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "T̂h́êśê ćĥéĉḱŝ v́âĺîd́ât́ê t́ĥé âśp̂éĉt́ŝ óf̂ á P̂ŕôǵr̂éŝśîv́ê Ẃêb́ Âṕp̂. [Ĺêár̂ń m̂ór̂é](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "T̂h́êśê ćĥéĉḱŝ ár̂é r̂éq̂úîŕêd́ b̂ý t̂h́ê b́âśêĺîńê [ṔŴÁ Ĉh́êćk̂ĺîśt̂](https://developers.google.com/web/progressive-web-apps/checklist) b́ût́ âŕê ńôt́ âút̂óm̂át̂íĉál̂ĺŷ ćĥéĉḱêd́ b̂ý L̂íĝh́t̂h́ôúŝé. T̂h́êý d̂ó n̂ót̂ áf̂f́êćt̂ ýôúr̂ śĉór̂é b̂út̂ ít̂'ś îḿp̂ór̂t́âńt̂ t́ĥát̂ ýôú v̂ér̂íf̂ý t̂h́êḿ m̂án̂úâĺl̂ý."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "P̂ŕôǵr̂éŝśîv́ê Ẃêb́ Âṕp̂"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "F̂áŝt́ âńd̂ ŕêĺîáb̂ĺê"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Îńŝt́âĺl̂áb̂ĺê"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "P̂ẂÂ Óp̂t́îḿîźêd́"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "T̂h́êśê ćĥéĉḱŝ én̂śûŕê t́ĥát̂ ýôúr̂ ṕâǵê íŝ óp̂t́îḿîźêd́ f̂ór̂ śêár̂ćĥ én̂ǵîńê ŕêśûĺt̂ś r̂án̂ḱîńĝ. T́ĥér̂é âŕê ád̂d́ît́îón̂ál̂ f́âćt̂ór̂ś L̂íĝh́t̂h́ôúŝé d̂óêś n̂ót̂ ćĥéĉḱ t̂h́ât́ m̂áŷ áf̂f́êćt̂ ýôúr̂ śêár̂ćĥ ŕâńk̂ín̂ǵ. [L̂éâŕn̂ ḿôŕê](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "R̂ún̂ t́ĥéŝé âd́d̂ít̂íôńâĺ v̂ál̂íd̂át̂ór̂ś ôń ŷóûŕ ŝít̂é t̂ó ĉh́êćk̂ ád̂d́ît́îón̂ál̂ ŚÊÓ b̂éŝt́ p̂ŕâćt̂íĉéŝ."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "ŜÉÔ"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "F̂ór̂ḿât́ ŷóûŕ ĤT́M̂Ĺ îń â ẃâý t̂h́ât́ êńâb́l̂éŝ ćr̂áŵĺêŕŝ t́ô b́êt́t̂ér̂ ún̂d́êŕŝt́âńd̂ ýôúr̂ áp̂ṕ’ŝ ćôńt̂én̂t́."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Ĉón̂t́êńt̂ B́êśt̂ Ṕr̂áĉt́îćêś"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "T̂ó âṕp̂éâŕ îń ŝéâŕĉh́ r̂éŝúl̂t́ŝ, ćr̂áŵĺêŕŝ ńêéd̂ áĉćêśŝ t́ô ýôúr̂ áp̂ṕ."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Ĉŕâẃl̂ín̂ǵ âńd̂ Ín̂d́êx́îńĝ"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "M̂ák̂é ŝúr̂é ŷóûŕ p̂áĝéŝ ár̂é m̂ób̂íl̂é f̂ŕîén̂d́l̂ý ŝó ûśêŕŝ d́ôń’t̂ h́âv́ê t́ô ṕîńĉh́ ôŕ ẑóôḿ îń ôŕd̂ér̂ t́ô ŕêád̂ t́ĥé ĉón̂t́êńt̂ ṕâǵêś. [L̂éâŕn̂ ḿôŕê](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "M̂ób̂íl̂é F̂ŕîén̂d́l̂ý"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Ĉáĉh́ê T́T̂Ĺ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "L̂óĉát̂íôń"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "N̂ám̂é"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "R̂éq̂úêśt̂ś"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "R̂éŝóûŕĉé T̂ýp̂é"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Ŝíẑé"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "T̂ím̂é Ŝṕêńt̂"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "T̂ŕâńŝf́êŕ Ŝíẑé"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "ÛŔL̂"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "P̂ót̂én̂t́îál̂ Śâv́îńĝś"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "P̂ót̂én̂t́îál̂ Śâv́îńĝś"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "P̂ót̂én̂t́îál̂ śâv́îńĝś ôf́ {wastedBytes, number, bytes} K̂B́"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "P̂ót̂én̂t́îál̂ śâv́îńĝś ôf́ {wastedMs, number, milliseconds} m̂ś"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "D̂óĉúm̂én̂t́"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "F̂ón̂t́"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Îḿâǵê"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "M̂éd̂íâ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} m̂ś"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Ôt́ĥér̂"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Ŝćr̂íp̂t́"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} ŝ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Ŝt́ŷĺêśĥéêt́"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "T̂h́îŕd̂-ṕâŕt̂ý"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "T̂ót̂ál̂"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Ŝóm̂ét̂h́îńĝ ẃêńt̂ ẃr̂ón̂ǵ ŵít̂h́ r̂éĉór̂d́îńĝ t́ĥé t̂ŕâćê óv̂ér̂ ýôúr̂ ṕâǵê ĺôád̂. Ṕl̂éâśê ŕûń L̂íĝh́t̂h́ôúŝé âǵâín̂. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "T̂ím̂éôút̂ ẃâít̂ín̂ǵ f̂ór̂ ín̂ít̂íâĺ D̂éb̂úĝǵêŕ P̂ŕôt́ôćôĺ ĉón̂ńêćt̂íôń."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Ĉh́r̂óm̂é d̂íd̂ń't̂ ćôĺl̂éĉt́ âńŷ śĉŕêén̂śĥót̂ś d̂úr̂ín̂ǵ t̂h́ê ṕâǵê ĺôád̂. Ṕl̂éâśê ḿâḱê śûŕê t́ĥér̂é îś ĉón̂t́êńt̂ v́îśîb́l̂é ôń t̂h́ê ṕâǵê, án̂d́ t̂h́êń t̂ŕŷ ŕê-ŕûńn̂ín̂ǵ L̂íĝh́t̂h́ôúŝé. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "D̂ŃŜ śêŕv̂ér̂ś ĉóûĺd̂ ńôt́ r̂éŝól̂v́ê t́ĥé p̂ŕôv́îd́êd́ d̂óm̂áîń."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "R̂éq̂úîŕêd́ {artifactName} ĝát̂h́êŕêŕ êńĉóûńt̂ér̂éd̂ án̂ ér̂ŕôŕ: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Âń îńt̂ér̂ńâĺ Ĉh́r̂óm̂é êŕr̂ór̂ óĉćûŕr̂éd̂. Ṕl̂éâśê ŕêśt̂ár̂t́ Ĉh́r̂óm̂é âńd̂ t́r̂ý r̂é-r̂ún̂ńîńĝ Ĺîǵĥt́ĥóûśê."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "R̂éq̂úîŕêd́ {artifactName} ĝát̂h́êŕêŕ d̂íd̂ ńôt́ r̂ún̂."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô ŕêĺîáb̂ĺŷ ĺôád̂ t́ĥé p̂áĝé ŷóû ŕêq́ûéŝt́êd́. M̂ák̂é ŝúr̂é ŷóû ár̂é t̂éŝt́îńĝ t́ĥé ĉór̂ŕêćt̂ ÚR̂Ĺ âńd̂ t́ĥát̂ t́ĥé ŝér̂v́êŕ îś p̂ŕôṕêŕl̂ý r̂éŝṕôńd̂ín̂ǵ t̂ó âĺl̂ ŕêq́ûéŝt́ŝ."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô ŕêĺîáb̂ĺŷ ĺôád̂ t́ĥé ÛŔL̂ ýôú r̂éq̂úêśt̂éd̂ b́êćâúŝé t̂h́ê ṕâǵê śt̂óp̂ṕêd́ r̂éŝṕôńd̂ín̂ǵ."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "T̂h́ê ÚR̂Ĺ ŷóû h́âv́ê ṕr̂óv̂íd̂éd̂ d́ôéŝ ńôt́ ĥáv̂é â v́âĺîd́ ŝéĉúr̂ít̂ý ĉér̂t́îf́îćât́ê. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Ĉh́r̂óm̂é p̂ŕêv́êńt̂éd̂ ṕâǵê ĺôád̂ ẃît́ĥ án̂ ín̂t́êŕŝt́ît́îál̂. Ḿâḱê śûŕê ýôú âŕê t́êśt̂ín̂ǵ t̂h́ê ćôŕr̂éĉt́ ÛŔL̂ án̂d́ t̂h́ât́ t̂h́ê śêŕv̂ér̂ íŝ ṕr̂óp̂ér̂ĺŷ ŕêśp̂ón̂d́îńĝ t́ô ál̂ĺ r̂éq̂úêśt̂ś."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô ŕêĺîáb̂ĺŷ ĺôád̂ t́ĥé p̂áĝé ŷóû ŕêq́ûéŝt́êd́. M̂ák̂é ŝúr̂é ŷóû ár̂é t̂éŝt́îńĝ t́ĥé ĉór̂ŕêćt̂ ÚR̂Ĺ âńd̂ t́ĥát̂ t́ĥé ŝér̂v́êŕ îś p̂ŕôṕêŕl̂ý r̂éŝṕôńd̂ín̂ǵ t̂ó âĺl̂ ŕêq́ûéŝt́ŝ. (D́êt́âíl̂ś: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "L̂íĝh́t̂h́ôúŝé ŵáŝ ún̂áb̂ĺê t́ô ŕêĺîáb̂ĺŷ ĺôád̂ t́ĥé p̂áĝé ŷóû ŕêq́ûéŝt́êd́. M̂ák̂é ŝúr̂é ŷóû ár̂é t̂éŝt́îńĝ t́ĥé ĉór̂ŕêćt̂ ÚR̂Ĺ âńd̂ t́ĥát̂ t́ĥé ŝér̂v́êŕ îś p̂ŕôṕêŕl̂ý r̂éŝṕôńd̂ín̂ǵ t̂ó âĺl̂ ŕêq́ûéŝt́ŝ. (Śt̂át̂úŝ ćôd́ê: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Ŷóûŕ p̂áĝé t̂óôḱ t̂óô ĺôńĝ t́ô ĺôád̂. Ṕl̂éâśê f́ôĺl̂óŵ t́ĥé ôṕp̂ór̂t́ûńît́îéŝ ín̂ t́ĥé r̂ép̂ór̂t́ t̂ó r̂éd̂úĉé ŷóûŕ p̂áĝé l̂óâd́ t̂ím̂é, âńd̂ t́ĥén̂ t́r̂ý r̂é-r̂ún̂ńîńĝ Ĺîǵĥt́ĥóûśê. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Ŵáît́îńĝ f́ôŕ D̂év̂T́ôól̂ś p̂ŕôt́ôćôĺ r̂éŝṕôńŝé ĥáŝ éx̂ćêéd̂éd̂ t́ĥé âĺl̂ót̂t́êd́ t̂ím̂é. (M̂ét̂h́ôd́: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "F̂ét̂ćĥín̂ǵ r̂éŝóûŕĉé ĉón̂t́êńt̂ h́âś êx́ĉéêd́êd́ t̂h́ê ál̂ĺôt́t̂éd̂ t́îḿê"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "T̂h́ê ÚR̂Ĺ ŷóû h́âv́ê ṕr̂óv̂íd̂éd̂ áp̂ṕêár̂ś t̂ó b̂é îńv̂ál̂íd̂."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Ŝh́ôẃ âúd̂ít̂ś"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Îńît́îál̂ Ńâv́îǵât́îón̂"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "M̂áx̂ím̂úm̂ ćr̂ít̂íĉál̂ ṕât́ĥ ĺât́êńĉý:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Êŕr̂ór̂!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "R̂ép̂ór̂t́ êŕr̂ór̂: ńô áûd́ît́ îńf̂ór̂ḿât́îón̂"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "L̂áb̂ D́ât́â"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[L̂íĝh́t̂h́ôúŝé](https://developers.google.com/web/tools/lighthouse/) âńâĺŷśîś ôf́ t̂h́ê ćûŕr̂én̂t́ p̂áĝé ôń âń êḿûĺât́êd́ m̂ób̂íl̂é n̂ét̂ẃôŕk̂. V́âĺûéŝ ár̂é êśt̂ím̂át̂éd̂ án̂d́ m̂áŷ v́âŕŷ."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Âd́d̂ít̂íôńâĺ ît́êḿŝ t́ô ḿâńûál̂ĺŷ ćĥéĉḱ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "N̂ót̂ áp̂ṕl̂íĉáb̂ĺê"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Ôṕp̂ór̂t́ûńît́ŷ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Êśt̂ím̂át̂éd̂ Śâv́îńĝś"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "P̂áŝśêd́ âúd̂ít̂ś"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Ĉól̂ĺâṕŝé ŝńîṕp̂ét̂"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Êx́p̂án̂d́ ŝńîṕp̂ét̂"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Ŝh́ôẃ 3r̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "T̂h́êŕê ẃêŕê íŝśûéŝ áf̂f́êćt̂ín̂ǵ t̂h́îś r̂ún̂ óf̂ Ĺîǵĥt́ĥóûśê:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "V̂ál̂úêś âŕê éŝt́îḿât́êd́ âńd̂ ḿâý v̂ár̂ý. T̂h́ê ṕêŕf̂ór̂ḿâńĉé ŝćôŕê íŝ [b́âśêd́ ôńl̂ý ôń t̂h́êśê ḿêt́r̂íĉś](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "P̂áŝśêd́ âúd̂ít̂ś b̂út̂ ẃît́ĥ ẃâŕn̂ín̂ǵŝ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Ŵár̂ńîńĝś: "
+ },
+ "stack-packs/packs/amp.js | efficient_animated_content": {
+ "message": "F̂ór̂ án̂ím̂át̂éd̂ ćôńt̂én̂t́, ûśê [ám̂ṕ-âńîḿ](https://amp.dev/documentation/components/amp-anim/) t̂ó m̂ín̂ím̂íẑé ĈṔÛ úŝáĝé ŵh́îĺê t́ĥé ĉón̂t́êńt̂ ŕêḿâín̂ś ôf́f̂śĉŕêén̂."
+ },
+ "stack-packs/packs/amp.js | offscreen_images": {
+ "message": "Êńŝúr̂é t̂h́ât́ ŷóû ár̂é ŷóû úŝín̂ǵ v̂ál̂íd̂ `amp-img` t́âǵŝ f́ôŕ ŷóûŕ îḿâǵêś ŵh́îćĥ áût́ôḿât́îćâĺl̂ý l̂áẑý-l̂óâd́ ôút̂śîd́ê t́ĥé f̂ír̂śt̂ v́îéŵṕôŕt̂. [Ĺêár̂ń m̂ór̂é](https://amp.dev/documentation/guides-and-tutorials/develop/media_iframes_3p/?format=websites#images)."
+ },
+ "stack-packs/packs/amp.js | render_blocking_resources": {
+ "message": "Ûśê t́ôól̂ś ŝúĉh́ âś [ÂḾP̂ Óp̂t́îḿîźêŕ](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer) t̂ó [ŝér̂v́êŕ-ŝíd̂é r̂én̂d́êŕ ÂḾP̂ ĺâýôút̂ś](https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/server-side-rendering/)."
+ },
+ "stack-packs/packs/amp.js | unminified_css": {
+ "message": "R̂éf̂ér̂ t́ô t́ĥé [ÂḾP̂ d́ôćûḿêńt̂át̂íôń](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/style_pages/) t̂ó êńŝúr̂é âĺl̂ ýôúr̂ śt̂ýl̂éŝ ár̂é ŝúp̂ṕôŕt̂éd̂."
+ },
+ "stack-packs/packs/amp.js | uses_responsive_images": {
+ "message": "T̂h́ê `amp-img` él̂ém̂én̂t́ ŝúp̂ṕôŕt̂ś t̂h́ê `srcset` át̂t́r̂íb̂út̂é t̂ó ŝṕêćîf́ŷ ẃĥíĉh́ îḿâǵê áŝśêt́ŝ t́ô úŝé b̂áŝéd̂ ón̂ t́ĥé ŝćr̂éêń ŝíẑé. [L̂éâŕn̂ ḿôŕê](https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/art_direction/)."
+ },
+ "stack-packs/packs/amp.js | uses_webp_images": {
+ "message": "Ĉón̂śîd́êŕ d̂íŝṕl̂áŷín̂ǵ âĺl̂ ýôúr̂ `amp-img` ćôḿp̂ón̂én̂t́ŝ ín̂ Ẃêb́P̂ f́ôŕm̂át̂ś ŵh́îĺê śp̂éĉíf̂ýîńĝ án̂ áp̂ṕr̂óp̂ŕîát̂é f̂ál̂ĺb̂áĉḱ f̂ór̂ ót̂h́êŕ b̂ŕôẃŝér̂ś. [L̂éâŕn̂ ḿôŕê](https://amp.dev/documentation/components/amp-img/#example:-specifying-a-fallback-image)."
+ },
+ "stack-packs/packs/angular.js | dom_size": {
+ "message": "Ĉón̂śîd́êŕ v̂ír̂t́ûál̂ śĉŕôĺl̂ín̂ǵ ŵít̂h́ t̂h́ê Ćôḿp̂ón̂én̂t́ D̂év̂ Ḱît́ (ĈD́K̂) íf̂ v́êŕŷ ĺâŕĝé l̂íŝt́ŝ ár̂é b̂éîńĝ ŕêńd̂ér̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/virtualize-lists-with-angular-cdk/)."
+ },
+ "stack-packs/packs/angular.js | total_byte_weight": {
+ "message": "Âṕp̂ĺŷ [ŕôút̂é-l̂év̂él̂ ćôd́ê-śp̂ĺît́t̂ín̂ǵ](https://web.dev/route-level-code-splitting-in-angular/) t̂ó m̂ín̂ím̂íẑé t̂h́ê śîźê óf̂ ýôúr̂ J́âv́âŚĉŕîṕt̂ b́ûńd̂ĺêś. Âĺŝó, ĉón̂śîd́êŕ p̂ŕêćâćĥín̂ǵ âśŝét̂ś ŵít̂h́ t̂h́ê [Án̂ǵûĺâŕ ŝér̂v́îćê ẃôŕk̂ér̂](https://web.dev/precaching-with-the-angular-service-worker/)."
+ },
+ "stack-packs/packs/angular.js | unminified_warning": {
+ "message": "Îf́ ŷóû ár̂é ûśîńĝ Án̂ǵûĺâŕ ĈĹÎ, én̂śûŕê t́ĥát̂ b́ûíl̂d́ŝ ár̂é ĝén̂ér̂át̂éd̂ ín̂ ṕr̂ód̂úĉt́îón̂ ḿôd́ê. [Ĺêár̂ń m̂ór̂é](https://angular.io/guide/deployment#enable-runtime-production-mode)."
+ },
+ "stack-packs/packs/angular.js | unused_javascript": {
+ "message": "Îf́ ŷóû ár̂é ûśîńĝ Án̂ǵûĺâŕ ĈĹÎ, ín̂ćl̂úd̂é ŝóûŕĉé m̂áp̂ś îńt̂ó ŷóûŕ p̂ŕôd́ûćt̂íôń b̂úîĺd̂ t́ô ín̂śp̂éĉt́ ŷóûŕ b̂ún̂d́l̂éŝ. [Ĺêár̂ń m̂ór̂é](https://angular.io/guide/deployment#inspect-the-bundles)."
+ },
+ "stack-packs/packs/angular.js | uses_rel_preload": {
+ "message": "P̂ŕêĺôád̂ ŕôút̂éŝ áĥéâd́ ôf́ t̂ím̂é t̂ó ŝṕêéd̂ úp̂ ńâv́îǵât́îón̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/route-preloading-in-angular/)."
+ },
+ "stack-packs/packs/angular.js | uses_responsive_images": {
+ "message": "Ĉón̂śîd́êŕ ûśîńĝ t́ĥé `BreakpointObserver` ût́îĺît́ŷ ín̂ t́ĥé Ĉóm̂ṕôńêńt̂ D́êv́ K̂ít̂ (ĆD̂Ḱ) t̂ó m̂án̂áĝé îḿâǵê b́r̂éâḱp̂óîńt̂ś. [L̂éâŕn̂ ḿôŕê](https://material.angular.io/cdk/layout/overview)."
+ },
+ "stack-packs/packs/magento.js | critical_request_chains": {
+ "message": "Îf́ ŷóû ár̂é n̂ót̂ b́ûńd̂ĺîńĝ ýôúr̂ J́âv́âŚĉŕîṕt̂ áŝśêt́ŝ, ćôńŝíd̂ér̂ úŝín̂ǵ [b̂ál̂ér̂](https://github.com/magento/baler)."
+ },
+ "stack-packs/packs/magento.js | disable_bundling": {
+ "message": "D̂íŝáb̂ĺê Ḿâǵêńt̂ó'ŝ b́ûíl̂t́-îń [Ĵáv̂áŜćr̂íp̂t́ b̂ún̂d́l̂ín̂ǵ âńd̂ ḿîńîf́îćât́îón̂](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html), án̂d́ ĉón̂śîd́êŕ ûśîńĝ [b́âĺêŕ](https://github.com/magento/baler/) îńŝt́êád̂."
+ },
+ "stack-packs/packs/magento.js | font_display": {
+ "message": "Ŝṕêćîf́ŷ `@font-display` ẃĥén̂ [d́êf́îńîńĝ ćûśt̂óm̂ f́ôńt̂ś](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/css-topics/using-fonts.html)."
+ },
+ "stack-packs/packs/magento.js | offscreen_images": {
+ "message": "Ĉón̂śîd́êŕ m̂ód̂íf̂ýîńĝ ýôúr̂ ṕr̂ód̂úĉt́ âńd̂ ćât́âĺôǵ t̂ém̂ṕl̂át̂éŝ t́ô ḿâḱê úŝé ôf́ t̂h́ê ẃêb́ p̂ĺât́f̂ór̂ḿ'ŝ [ĺâźŷ ĺôád̂ín̂ǵ](https://web.dev/native-lazy-loading) f̂éât́ûŕê."
+ },
+ "stack-packs/packs/magento.js | time_to_first_byte": {
+ "message": "Ûśê Ḿâǵêńt̂ó'ŝ [V́âŕn̂íŝh́ îńt̂éĝŕât́îón̂](https://devdocs.magento.com/guides/v2.3/config-guide/varnish/config-varnish.html)."
+ },
+ "stack-packs/packs/magento.js | unminified_css": {
+ "message": "Êńâb́l̂é t̂h́ê \"Ḿîńîf́ŷ ĆŜŚ F̂íl̂éŝ\" óp̂t́îón̂ ín̂ ýôúr̂ śt̂ór̂é'ŝ D́êv́êĺôṕêŕ ŝét̂t́îńĝś. [L̂éâŕn̂ ḿôŕê](https://devdocs.magento.com/guides/v2.3/performance-best-practices/configuration.html?itm_source=devdocs&itm_medium=search_page&itm_campaign=federated_search&itm_term=minify%20css%20files)."
+ },
+ "stack-packs/packs/magento.js | unminified_javascript": {
+ "message": "Ûśê [T́êŕŝér̂](https://www.npmjs.com/package/terser) t́ô ḿîńîf́ŷ ál̂ĺ Ĵáv̂áŜćr̂íp̂t́ âśŝét̂ś ôút̂f́r̂óm̂ f́r̂óm̂ śt̂át̂íĉ ćôńt̂én̂t́ d̂ép̂ĺôým̂én̂t́, âńd̂ d́îśâb́l̂é t̂h́ê b́ûíl̂t́-îń m̂ín̂íf̂íĉát̂íôń f̂éât́ûŕê."
+ },
+ "stack-packs/packs/magento.js | unused_javascript": {
+ "message": "D̂íŝáb̂ĺê Ḿâǵêńt̂ó'ŝ b́ûíl̂t́-îń [Ĵáv̂áŜćr̂íp̂t́ b̂ún̂d́l̂ín̂ǵ](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/themes/js-bundling.html)."
+ },
+ "stack-packs/packs/magento.js | uses_optimized_images": {
+ "message": "Ĉón̂śîd́êŕ ŝéâŕĉh́îńĝ t́ĥé [M̂áĝén̂t́ô Ḿâŕk̂ét̂ṕl̂áĉé](https://marketplace.magento.com/catalogsearch/result/?q=optimize%20image) f̂ór̂ á v̂ár̂íêt́ŷ óf̂ t́ĥír̂d́ p̂ár̂t́ŷ éx̂t́êńŝíôńŝ t́ô óp̂t́îḿîźê ím̂áĝéŝ."
+ },
+ "stack-packs/packs/magento.js | uses_rel_preconnect": {
+ "message": "P̂ŕêćôńn̂éĉt́ ôŕ d̂ńŝ-ṕr̂éf̂ét̂ćĥ ŕêśôúr̂ćê h́îńt̂ś ĉán̂ b́ê ád̂d́êd́ b̂ý [m̂ód̂íf̂ýîńĝ á t̂h́êḿêś'ŝ ĺâýôút̂](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html)."
+ },
+ "stack-packs/packs/magento.js | uses_rel_preload": {
+ "message": "`<link rel=preload>` t̂áĝś ĉán̂ b́ê ád̂d́êd́ b̂ý [m̂ód̂íf̂ýîńĝ á t̂h́êḿêś'ŝ ĺâýôút̂](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/layouts/xml-manage.html)."
+ },
+ "stack-packs/packs/magento.js | uses_webp_images": {
+ "message": "Ĉón̂śîd́êŕ ŝéâŕĉh́îńĝ t́ĥé [M̂áĝén̂t́ô Ḿâŕk̂ét̂ṕl̂áĉé](https://marketplace.magento.com/catalogsearch/result/?q=webp) f̂ór̂ á v̂ár̂íêt́ŷ óf̂ t́ĥír̂d́-p̂ár̂t́ŷ éx̂t́êńŝíôńŝ t́ô ĺêv́êŕâǵê ńêẃêŕ îḿâǵê f́ôŕm̂át̂ś."
+ },
+ "stack-packs/packs/react.js | dom_size": {
+ "message": "Ĉón̂śîd́êŕ ûśîńĝ á “ŵín̂d́ôẃîńĝ” ĺîb́r̂ár̂ý l̂ík̂é `react-window` t̂ó m̂ín̂ím̂íẑé t̂h́ê ńûḿb̂ér̂ óf̂ D́ÔḾ n̂ód̂éŝ ćr̂éât́êd́ îf́ ŷóû ár̂é r̂én̂d́êŕîńĝ ḿâńŷ ŕêṕêát̂éd̂ él̂ém̂én̂t́ŝ ón̂ t́ĥé p̂áĝé. [L̂éâŕn̂ ḿôŕê](https://web.dev/virtualize-long-lists-react-window/). Ál̂śô, ḿîńîḿîźê ún̂éĉéŝśâŕŷ ŕê-ŕêńd̂ér̂ś ûśîńĝ [śĥóûĺd̂Ćôḿp̂ón̂én̂t́Ûṕd̂át̂é](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action), [P̂úr̂éĈóm̂ṕôńêńt̂](https://reactjs.org/docs/react-api.html#reactpurecomponent), ór̂ [Ŕêáĉt́.m̂ém̂ó](https://reactjs.org/docs/react-api.html#reactmemo) âńd̂ [śk̂íp̂ éf̂f́êćt̂ś](https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects) ôńl̂ý ûńt̂íl̂ ćêŕt̂áîń d̂ép̂én̂d́êńĉíêś ĥáv̂é ĉh́âńĝéd̂ íf̂ ýôú âŕê úŝín̂ǵ t̂h́ê Éf̂f́êćt̂ h́ôók̂ t́ô ím̂ṕr̂óv̂é r̂ún̂t́îḿê ṕêŕf̂ór̂ḿâńĉé."
+ },
+ "stack-packs/packs/react.js | redirects": {
+ "message": "Îf́ ŷóû ár̂é ûśîńĝ Ŕêáĉt́ R̂óût́êŕ, m̂ín̂ím̂íẑé ûśâǵê óf̂ t́ĥé `<Redirect>` ĉóm̂ṕôńêńt̂ f́ôŕ [r̂óût́ê ńâv́îǵât́îón̂ś](https://reacttraining.com/react-router/web/api/Redirect)."
+ },
+ "stack-packs/packs/react.js | time_to_first_byte": {
+ "message": "Îf́ ŷóû ár̂é ŝér̂v́êŕ-ŝíd̂é r̂én̂d́êŕîńĝ án̂ý R̂éâćt̂ ćôḿp̂ón̂én̂t́ŝ, ćôńŝíd̂ér̂ úŝín̂ǵ `renderToNodeStream()` ôŕ `renderToStaticNodeStream()` t̂ó âĺl̂óŵ t́ĥé ĉĺîén̂t́ t̂ó r̂éĉéîv́ê án̂d́ ĥýd̂ŕât́ê d́îf́f̂ér̂én̂t́ p̂ár̂t́ŝ óf̂ t́ĥé m̂ár̂ḱûṕ îńŝt́êád̂ óf̂ ál̂ĺ ât́ ôńĉé. [L̂éâŕn̂ ḿôŕê](https://reactjs.org/docs/react-dom-server.html#rendertonodestream)."
+ },
+ "stack-packs/packs/react.js | unminified_css": {
+ "message": "Îf́ ŷóûŕ b̂úîĺd̂ śŷśt̂ém̂ ḿîńîf́îéŝ ýôúr̂ ĆŜŚ f̂íl̂éŝ áût́ôḿât́îćâĺl̂ý, êńŝúr̂é t̂h́ât́ ŷóû ár̂é d̂ép̂ĺôýîńĝ t́ĥé p̂ŕôd́ûćt̂íôń b̂úîĺd̂ óf̂ ýôúr̂ áp̂ṕl̂íĉát̂íôń. Ŷóû ćâń ĉh́êćk̂ t́ĥíŝ ẃît́ĥ t́ĥé R̂éâćt̂ D́êv́êĺôṕêŕ T̂óôĺŝ éx̂t́êńŝíôń. [L̂éâŕn̂ ḿôŕê](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build)."
+ },
+ "stack-packs/packs/react.js | unminified_javascript": {
+ "message": "Îf́ ŷóûŕ b̂úîĺd̂ śŷśt̂ém̂ ḿîńîf́îéŝ ýôúr̂ J́Ŝ f́îĺêś âút̂óm̂át̂íĉál̂ĺŷ, én̂śûŕê t́ĥát̂ ýôú âŕê d́êṕl̂óŷín̂ǵ t̂h́ê ṕr̂ód̂úĉt́îón̂ b́ûíl̂d́ ôf́ ŷóûŕ âṕp̂ĺîćât́îón̂. Ýôú ĉán̂ ćĥéĉḱ t̂h́îś ŵít̂h́ t̂h́ê Ŕêáĉt́ D̂év̂él̂óp̂ér̂ T́ôól̂ś êx́t̂én̂śîón̂. [Ĺêár̂ń m̂ór̂é](https://reactjs.org/docs/optimizing-performance.html#use-the-production-build)."
+ },
+ "stack-packs/packs/react.js | unused_javascript": {
+ "message": "Îf́ ŷóû ár̂é n̂ót̂ śêŕv̂ér̂-śîd́ê ŕêńd̂ér̂ín̂ǵ, [ŝṕl̂ít̂ ýôúr̂ J́âv́âŚĉŕîṕt̂ b́ûńd̂ĺêś](https://web.dev/code-splitting-suspense/) ŵít̂h́ `React.lazy()`. Ôt́ĥér̂ẃîśê, ćôd́ê-śp̂ĺît́ ûśîńĝ á t̂h́îŕd̂-ṕâŕt̂ý l̂íb̂ŕâŕŷ śûćĥ áŝ [ĺôád̂áb̂ĺê-ćôḿp̂ón̂én̂t́ŝ](https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/)."
+ },
+ "stack-packs/packs/react.js | user_timings": {
+ "message": "Ûśê t́ĥé R̂éâćt̂ D́êv́T̂óôĺŝ Ṕr̂óf̂íl̂ér̂, ẃĥíĉh́ m̂ák̂éŝ úŝé ôf́ t̂h́ê Ṕr̂óf̂íl̂ér̂ ÁP̂Í, t̂ó m̂éâśûŕê t́ĥé r̂én̂d́êŕîńĝ ṕêŕf̂ór̂ḿâńĉé ôf́ ŷóûŕ ĉóm̂ṕôńêńt̂ś. [L̂éâŕn̂ ḿôŕê.](https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)"
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Ĉón̂śîd́êŕ ûṕl̂óâd́îńĝ ýôúr̂ ǴÎF́ t̂ó â śêŕv̂íĉé ŵh́îćĥ ẃîĺl̂ ḿâḱê ít̂ áv̂áîĺâb́l̂é t̂ó êḿb̂éd̂ áŝ án̂ H́T̂ḾL̂5 v́îd́êó."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Îńŝt́âĺl̂ á [l̂áẑý-l̂óâd́ Ŵór̂d́P̂ŕêśŝ ṕl̂úĝín̂](https://wordpress.org/plugins/search/lazy+load/) t́ĥát̂ ṕr̂óv̂íd̂éŝ t́ĥé âb́îĺît́ŷ t́ô d́êf́êŕ âńŷ óf̂f́ŝćr̂éêń îḿâǵêś, ôŕ ŝẃît́ĉh́ t̂ó â t́ĥém̂é t̂h́ât́ p̂ŕôv́îd́êś t̂h́ât́ f̂ún̂ćt̂íôńâĺît́ŷ. Ál̂śô ćôńŝíd̂ér̂ úŝín̂ǵ [t̂h́ê ÁM̂Ṕ p̂ĺûǵîń](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "T̂h́êŕê ár̂é â ńûḿb̂ér̂ óf̂ Ẃôŕd̂Ṕr̂éŝś p̂ĺûǵîńŝ t́ĥát̂ ćâń ĥél̂ṕ ŷóû [ín̂ĺîńê ćr̂ít̂íĉál̂ áŝśêt́ŝ](https://wordpress.org/plugins/search/critical+css/) ór̂ [d́êf́êŕ l̂éŝś îḿp̂ór̂t́âńt̂ ŕêśôúr̂ćêś](https://wordpress.org/plugins/search/defer+css+javascript/). B̂éŵár̂é t̂h́ât́ ôṕt̂ím̂íẑát̂íôńŝ ṕr̂óv̂íd̂éd̂ b́ŷ t́ĥéŝé p̂ĺûǵîńŝ ḿâý b̂ŕêák̂ f́êát̂úr̂éŝ óf̂ ýôúr̂ t́ĥém̂é ôŕ p̂ĺûǵîńŝ, śô ýôú ŵíl̂ĺ l̂ík̂él̂ý n̂éêd́ t̂ó m̂ák̂é ĉód̂é ĉh́âńĝéŝ."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "T̂h́êḿêś, p̂ĺûǵîńŝ, án̂d́ ŝér̂v́êŕ ŝṕêćîf́îćât́îón̂ś âĺl̂ ćôńt̂ŕîb́ût́ê t́ô śêŕv̂ér̂ ŕêśp̂ón̂śê t́îḿê. Ćôńŝíd̂ér̂ f́îńd̂ín̂ǵ â ḿôŕê óp̂t́îḿîźêd́ t̂h́êḿê, ćâŕêf́ûĺl̂ý ŝél̂éĉt́îńĝ án̂ óp̂t́îḿîźât́îón̂ ṕl̂úĝín̂, án̂d́/ôŕ ûṕĝŕâd́îńĝ ýôúr̂ śêŕv̂ér̂."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Ĉón̂śîd́êŕ ŝh́ôẃîńĝ éx̂ćêŕp̂t́ŝ ín̂ ýôúr̂ ṕôśt̂ ĺîśt̂ś (ê.ǵ. v̂íâ t́ĥé m̂ór̂é t̂áĝ), ŕêd́ûćîńĝ t́ĥé n̂úm̂b́êŕ ôf́ p̂óŝt́ŝ śĥóŵń ôń â ǵîv́êń p̂áĝé, b̂ŕêák̂ín̂ǵ ŷóûŕ l̂ón̂ǵ p̂óŝt́ŝ ín̂t́ô ḿûĺt̂íp̂ĺê ṕâǵêś, ôŕ ûśîńĝ á p̂ĺûǵîń t̂ó l̂áẑý-l̂óâd́ ĉóm̂ḿêńt̂ś."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Â ńûḿb̂ér̂ óf̂ [Ẃôŕd̂Ṕr̂éŝś p̂ĺûǵîńŝ](https://wordpress.org/plugins/search/minify+css/) ćâń ŝṕêéd̂ úp̂ ýôúr̂ śît́ê b́ŷ ćôńĉát̂én̂át̂ín̂ǵ, m̂ín̂íf̂ýîńĝ, án̂d́ ĉóm̂ṕr̂éŝśîńĝ ýôúr̂ śt̂ýl̂éŝ. Ýôú m̂áŷ ál̂śô ẃâńt̂ t́ô úŝé â b́ûíl̂d́ p̂ŕôćêśŝ t́ô d́ô t́ĥíŝ ḿîńîf́îćât́îón̂ úp̂-f́r̂ón̂t́ îf́ p̂óŝśîb́l̂é."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Â ńûḿb̂ér̂ óf̂ [Ẃôŕd̂Ṕr̂éŝś p̂ĺûǵîńŝ](https://wordpress.org/plugins/search/minify+javascript/) ćâń ŝṕêéd̂ úp̂ ýôúr̂ śît́ê b́ŷ ćôńĉát̂én̂át̂ín̂ǵ, m̂ín̂íf̂ýîńĝ, án̂d́ ĉóm̂ṕr̂éŝśîńĝ ýôúr̂ śĉŕîṕt̂ś. Ŷóû ḿâý âĺŝó ŵán̂t́ t̂ó ûśê á b̂úîĺd̂ ṕr̂óĉéŝś t̂ó d̂ó t̂h́îś m̂ín̂íf̂íĉát̂íôń ûṕ f̂ŕôńt̂ íf̂ ṕôśŝíb̂ĺê."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Ĉón̂śîd́êŕ r̂éd̂úĉín̂ǵ, ôŕ ŝẃît́ĉh́îńĝ, t́ĥé n̂úm̂b́êŕ ôf́ [Ŵór̂d́P̂ŕêśŝ ṕl̂úĝín̂ś](https://wordpress.org/plugins/) l̂óâd́îńĝ ún̂úŝéd̂ ĆŜŚ îń ŷóûŕ p̂áĝé. T̂ó îd́êńt̂íf̂ý p̂ĺûǵîńŝ t́ĥát̂ ár̂é âd́d̂ín̂ǵ êx́t̂ŕâńêóûś ĈŚŜ, t́r̂ý r̂ún̂ńîńĝ [ćôd́ê ćôv́êŕâǵê](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ín̂ Ćĥŕôḿê D́êv́T̂óôĺŝ. Ýôú ĉán̂ íd̂én̂t́îf́ŷ t́ĥé t̂h́êḿê/ṕl̂úĝín̂ ŕêśp̂ón̂śîb́l̂é f̂ŕôḿ t̂h́ê ÚR̂Ĺ ôf́ t̂h́ê śt̂ýl̂éŝh́êét̂. Ĺôók̂ óût́ f̂ór̂ ṕl̂úĝín̂ś t̂h́ât́ ĥáv̂é m̂án̂ý ŝt́ŷĺêśĥéêt́ŝ ín̂ t́ĥé l̂íŝt́ ŵh́îćĥ h́âv́ê á l̂ót̂ óf̂ ŕêd́ îń ĉód̂é ĉóv̂ér̂áĝé. Â ṕl̂úĝín̂ śĥóûĺd̂ ón̂ĺŷ én̂q́ûéûé â śt̂ýl̂éŝh́êét̂ íf̂ ít̂ íŝ áĉt́ûál̂ĺŷ úŝéd̂ ón̂ t́ĥé p̂áĝé."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Ĉón̂śîd́êŕ r̂éd̂úĉín̂ǵ, ôŕ ŝẃît́ĉh́îńĝ, t́ĥé n̂úm̂b́êŕ ôf́ [Ŵór̂d́P̂ŕêśŝ ṕl̂úĝín̂ś](https://wordpress.org/plugins/) l̂óâd́îńĝ ún̂úŝéd̂ J́âv́âŚĉŕîṕt̂ ín̂ ýôúr̂ ṕâǵê. T́ô íd̂én̂t́îf́ŷ ṕl̂úĝín̂ś t̂h́ât́ âŕê ád̂d́îńĝ éx̂t́r̂án̂éôúŝ J́Ŝ, t́r̂ý r̂ún̂ńîńĝ [ćôd́ê ćôv́êŕâǵê](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ín̂ Ćĥŕôḿê D́êv́T̂óôĺŝ. Ýôú ĉán̂ íd̂én̂t́îf́ŷ t́ĥé t̂h́êḿê/ṕl̂úĝín̂ ŕêśp̂ón̂śîb́l̂é f̂ŕôḿ t̂h́ê ÚR̂Ĺ ôf́ t̂h́ê śĉŕîṕt̂. Ĺôók̂ óût́ f̂ór̂ ṕl̂úĝín̂ś t̂h́ât́ ĥáv̂é m̂án̂ý ŝćr̂íp̂t́ŝ ín̂ t́ĥé l̂íŝt́ ŵh́îćĥ h́âv́ê á l̂ót̂ óf̂ ŕêd́ îń ĉód̂é ĉóv̂ér̂áĝé.  ṕl̂úĝín̂ śĥóûĺd̂ ón̂ĺŷ én̂q́ûéûé â śĉŕîṕt̂ íf̂ ít̂ íŝ áĉt́ûál̂ĺŷ úŝéd̂ ón̂ t́ĥé p̂áĝé."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "R̂éâd́ âb́ôút̂ [B́r̂óŵśêŕ Ĉáĉh́îńĝ ín̂ Ẃôŕd̂Ṕr̂éŝś](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Ĉón̂śîd́êŕ ûśîńĝ án̂ [ím̂áĝé ôṕt̂ím̂íẑát̂íôń Ŵór̂d́P̂ŕêśŝ ṕl̂úĝín̂](https://wordpress.org/plugins/search/optimize+images/) t́ĥát̂ ćôḿp̂ŕêśŝéŝ ýôúr̂ ím̂áĝéŝ ẃĥíl̂é r̂ét̂áîńîńĝ q́ûál̂ít̂ý."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Ûṕl̂óâd́ îḿâǵêś d̂ír̂éĉt́l̂ý t̂h́r̂óûǵĥ t́ĥé [m̂éd̂íâ ĺîb́r̂ár̂ý](https://codex.wordpress.org/Media_Library_Screen) t̂ó êńŝúr̂é t̂h́ât́ t̂h́ê ŕêq́ûír̂éd̂ ím̂áĝé ŝíẑéŝ ár̂é âv́âíl̂áb̂ĺê, án̂d́ t̂h́êń îńŝér̂t́ t̂h́êḿ f̂ŕôḿ t̂h́ê ḿêd́îá l̂íb̂ŕâŕŷ ór̂ úŝé t̂h́ê ím̂áĝé ŵíd̂ǵêt́ t̂ó êńŝúr̂é t̂h́ê óp̂t́îḿâĺ îḿâǵê śîźêś âŕê úŝéd̂ (ín̂ćl̂úd̂ín̂ǵ t̂h́ôśê f́ôŕ t̂h́ê ŕêśp̂ón̂śîv́ê b́r̂éâḱp̂óîńt̂ś). Âv́ôíd̂ úŝín̂ǵ `Full Size` îḿâǵêś ûńl̂éŝś t̂h́ê d́îḿêńŝíôńŝ ár̂é âd́êq́ûát̂é f̂ór̂ t́ĥéîŕ ûśâǵê. [Ĺêár̂ń M̂ór̂é](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Ŷóû ćâń êńâb́l̂é t̂éx̂t́ ĉóm̂ṕr̂éŝśîón̂ ín̂ ýôúr̂ ẃêb́ ŝér̂v́êŕ ĉón̂f́îǵûŕât́îón̂."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Ĉón̂śîd́êŕ ûśîńĝ á [p̂ĺûǵîń](https://wordpress.org/plugins/search/convert+webp/) ôŕ ŝér̂v́îćê t́ĥát̂ ẃîĺl̂ áût́ôḿât́îćâĺl̂ý ĉón̂v́êŕt̂ ýôúr̂ úp̂ĺôád̂éd̂ ím̂áĝéŝ t́ô t́ĥé ôṕt̂ím̂ál̂ f́ôŕm̂át̂ś."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es-419.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es-419.json
new file mode 100644
index 00000000000..199c474a971
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es-419.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Las claves de acceso permiten a los usuarios dirigirse rápidamente a una parte concreta de la página. Para facilitar una navegación correcta, las claves de acceso deben ser únicas. [Obtén más información](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Los valores de `[accesskey]` no son únicos"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Los valores de `[accesskey]` son únicos"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Cada `role` de ARIA admite un subconjunto específico de atributos de `aria-*`. Si no coinciden estos valores, los atributos de `aria-*` no serán válidos. [Obtén más información](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no coinciden con sus roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Los atributos `[aria-*]` coinciden con sus roles"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Algunos roles de ARIA incluyen atributos obligatorios que describen el estado del elemento a los lectores de pantalla. [Obtén más información](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Los elementos `[role]` no tienen todos los atributos `[aria-*]` necesarios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Los elementos `[role]` tienen todos los atributos `[aria-*]` necesarios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Algunos roles principales de ARIA deben contener roles secundarios específicos para llevar a cabo las funciones de accesibilidad correspondientes. [Obtén más información](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Los elementos con una función `[role]` ARIA deben incluir elementos secundarios con una `[role]` específica. Faltan algunos o todos los elementos secundarios necesarios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Los elementos con una función `[role]` ARIA deben incluir elementos secundarios con una `[role]` específica. Se detectaron todos los elementos secundarios necesarios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Algunos roles secundarios de ARIA deben incluirse dentro de roles principales específicos para llevar a cabo de manera adecuada las funciones de accesibilidad correspondientes. [Obtén más información](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Los elementos `[role]` no se incluyen en los elementos principales necesarios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Los elementos `[role]` se incluyen en los elementos principales correspondientes"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Los roles de ARIA deben tener valores válidos para realizar las funciones de accesibilidad correspondientes. [Obtén más información](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Los valores de `[role]` no son válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Los valores de `[role]` son válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Las tecnologías de asistencia, como los lectores de pantalla, no pueden interpretar atributos de ARIA con valores no válidos. [Obtén más información](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no tienen valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Los atributos `[aria-*]` tienen valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Las tecnologías de asistencia, como los lectores de pantalla, no pueden interpretar los atributos ARIA cuyos nombres no sean válidos. [Obtén más información](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no son válidos o no están bien escritos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Los atributos `[aria-*]` son válidos y están bien escritos"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Los subtítulos permiten que los usuarios sordos o con dificultades auditivas aprovechen los elementos de audio, dado que proporcionan información fundamental, como la indicación de quién habla, lo que dice y otros datos no verbales. [Obtén más información](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Falta un elemento `<track>` con `[kind=\"captions\"]` en los elementos `<audio>`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Los elementos `<audio>` contienen un elemento `<track>` con `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementos con errores"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Si un botón no tiene un nombre accesible, los lectores de pantalla lo leerán en voz alta como \"botón\", por lo que resulta inservible para los usuarios que necesitan usar lectores de pantalla. [Obtén más información](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Los botones no tienen nombres accesibles"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Los botones tienen nombres accesibles"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Incluir maneras de omitir el contenido repetitivo permite a los usuarios que usan un teclado navegar por la página con mayor eficiencia. [Obtén más información](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "La página no contiene ningún título, vínculo de omisión ni región de punto de referencia"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "La página contiene un título, un vínculo de omisión o una región de punto de referencia"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Los textos con poco contraste resultan difíciles o imposibles de leer para muchos usuarios. [Obtén más información](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Los colores de fondo y de primer plano no tienen una relación de contraste adecuada."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Los colores de fondo y de primer plano tienen una relación de contraste adecuada"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Si las listas de definiciones no están bien marcadas, es posible que los lectores de pantalla las lean de forma confusa o imprecisa. [Obtén más información](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Los elementos `<dl>` no contienen solo elementos `<script>` o `<template>`, o grupos de `<dt>` y `<dd>` ordenados correctamente."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Los elementos `<dl>` contienen solo elementos `<script>` o `<template>`, o grupos de `<dt>` y `<dd>` ordenados correctamente."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Los elementos de la lista de definiciones (`<dt>` y `<dd>`) deben incluirse en un elemento `<dl>` principal para garantizar que los lectores de pantalla los lean correctamente. [Obtén más información](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Los elementos de la lista de definiciones no se incluyen en los elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Los elementos de la lista de definiciones se incluyen en los elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "El título les brinda a los usuarios de lectores de pantalla una descripción general de la página. Por su parte, los usuarios de motores de búsqueda lo usan mucho para determinar si una página es relevante para su búsqueda. [Obtén más información](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "El documento no tiene un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "El documento tiene un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "El valor de los atributos id debe ser único para evitar que las tecnologías de asistencia omitan otras instancias. [Obtén más información](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Los atributos `[id]` de la página no son únicos"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Los atributos `[id]` de la página son únicos"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Los usuarios de lectores de pantalla necesitan que los marcos tengan títulos para que se describa su contenido. [Obtén más información](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Los elementos `<frame>` o `<iframe>` no tienen título"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Los elementos `<frame>` o `<iframe>` tienen un título"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Si no se especifica ningún atributo de idioma para una página, los lectores de pantalla considerarán que la página está en el idioma predeterminado que el usuario eligió al configurar el lector de pantalla. Si el idioma de la página es diferente del predeterminado, es posible que el lector de pantalla no lea bien el texto de la página. [Obtén más información](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "El elemento `<html>` no tiene un atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "El elemento `<html>` tiene un atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Especificar un [idioma BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido permite a los lectores de pantalla leer el texto en voz alta correctamente. [Obtén más información](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "El elemento `<html>` no tiene un valor válido para el atributo `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "El elemento `<html>` tiene un valor válido para su atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "El texto de los elementos informativos debe ser corto y descriptivo. Los elementos decorativos se pueden omitir usando un atributo alt vacío. [Obtén más información](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Los elementos de imagen no tienen ningún atributo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Los elementos de imagen tienen atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Cuando se usa una imagen como botón `<input>`, resulta útil proporcionar un texto alternativo para permitir que los usuarios de lectores de pantalla entiendan cuál es la función del botón. [Obtén más información](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Los elementos `<input type=\"image\">` no tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Los elementos `<input type=\"image\">` tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Las etiquetas garantizan que las tecnologías de asistencia, como los lectores de pantalla, lean los controles de los formularios de forma correcta. [Obtén más información](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Los elementos de formulario no tienen ninguna etiqueta asociada"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Los elementos de formulario tienen etiquetas asociadas"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Las tablas que se usen con fines de diseño no deben incluir elementos de datos (como ordinales, leyendas o atributos de resumen), dado que estos pueden confundir a los usuarios de lectores de pantalla. [Obtén más información](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Los elementos `<table>` de presentación no evitan el uso de `<th>`, `<caption>` ni del atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Los elementos `<table>` de presentación evitan el uso de `<th>`, `<caption>` o del atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Usar textos de vínculo (y textos alternativos para las imágenes, si estas se usan como vínculos) que sean reconocibles y únicos, y que se puedan seleccionar mejora la experiencia de navegación de los usuarios de lectores de pantalla. [Obtén más información](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Los vínculos no tienen nombres reconocibles"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Los vínculos tienen nombres reconocibles"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Los lectores de pantalla leen las listas en voz alta de una forma concreta. Se recomienda utilizar una estructura de lista adecuada para que los lectores de pantalla puedan leer las listas de forma correcta. [Obtén más información](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Las listas no contienen solo elementos `<li>` y elementos que admiten secuencias de comandos (`<script>` y `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Las listas contienen solo elementos `<li>` y elementos que admiten secuencias de comando (`<script>` y `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Los lectores de pantalla requieren que los elementos de lista (`<li>`) se incluyan en un elemento `<ul>` o `<ol>` principal para leerlos correctamente. [Obtén más información](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Los elementos de lista (`<li>`) no se encuentran dentro de elementos principales `<ul>` o `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Los elementos de lista (`<li>`) se incluyen en los elementos principales `<ul>` o `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Los usuarios no esperan que una página se actualice automáticamente. Cuando eso sucede, vuelve a mostrarse la parte superior de la página. Esto puede generar una experiencia frustrante o confusa. [Obtén más información](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "El documento usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "El documento no usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Desactivar el zoom genera problemas para los usuarios con visión reducida, quienes necesitan ampliar la pantalla para ver correctamente el contenido de las páginas web. [Obtén más información](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` se usa en el elemento `<meta name=\"viewport\">` o el atributo `[maximum-scale]` tiene un valor inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "No se usa `[user-scalable=\"no\"]` en el elemento `<meta name=\"viewport\">` y el atributo `[maximum-scale]` no tiene un valor inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Los lectores de pantalla no pueden traducir contenido que no sea texto. El agregado de texto alternativo a los elementos `<object>` ayuda a los lectores de pantalla a transmitir el significado correspondiente a los usuarios. [Obtén más información](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Los elementos `<object>` no tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Los elementos `<object>` tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Si el valor es superior a 0, el orden de navegación es explícito. Aunque técnicamente esta es una posibilidad válida, suele producir experiencias frustrantes en los usuarios que necesitan las tecnologías de asistencia. [Obtén más información](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Algunos elementos tienen un valor de `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "No hay ningún elemento con un valor de `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Los lectores de pantalla incluyen funciones para facilitar la navegación por las tablas. Asegurarse de que las celdas `<td>` que usan el atributo `[headers]` solo hagan referencia a otras celdas de la misma tabla puede mejorar la experiencia de los usuarios de lectores de pantalla. [Obtén más información](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Las celdas de un elemento `<table>` que usan el atributo `[headers]` hacen referencia a un elemento `id` que no se encuentra en la misma tabla."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Las celdas de un elemento `<table>` que usa el atributo `[headers]` hacen referencia a las celdas de esa misma tabla."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Los lectores de pantalla incluyen funciones para facilitar la navegación por las tablas. Asegurarse de que los encabezados de las tablas siempre hagan referencia a un conjunto específico de celdas puede mejorar la experiencia de los usuarios de lectores de pantalla. [Obtén más información](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Los elementos `<th>` y los elementos con `[role=\"columnheader\"/\"rowheader\"]` no contienen las celdas de datos que describen."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Los elementos `<th>` y los elementos con `[role=\"columnheader\"/\"rowheader\"]` contienen celdas de datos que describen."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Especificar un [idioma CP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido en los elementos ayuda a asegurar que los lectores de pantalla pronuncien bien el texto correspondiente. [Obtén más información](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Los atributos `[lang]` no tienen un valor válido"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Los atributos `[lang]` tienen un valor válido"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Si un video tiene subtítulos, los usuarios sordos o con dificultades auditivas pueden acceder a la información más fácilmente. [Obtén más información](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Los elementos `<video>` no contienen un elemento `<track>` con `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Los elementos `<video>` contienen un elemento `<track>` con `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Las descripciones de audio incluidas en los videos proporcionan información relevante que no surge de los diálogos, como la relativa a expresiones faciales y escenografía. [Obtén más información](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Los elementos `<video>` no contienen un elemento `<track>` con `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Los elementos `<video>` contienen un elemento `<track>` con `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Para que el aspecto en iOS sea perfecto cuando los usuarios agreguen una app web progresiva a la pantalla principal, define un atributo `apple-touch-icon`. El atributo debe apuntar a un archivo PNG cuadrado de 192 px (o 180 px) que no sea transparente. [Obtén más información](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "No proporciona un ícono `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "El atributo `apple-touch-icon-precomposed` está desactualizado; usa en su lugar`apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Proporciona un `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Las extensiones de Chrome afectaron de forma negativa al rendimiento de carga de esta página. Prueba a auditarla en modo incógnito o desde un perfil de Chrome sin extensiones."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Evaluación de la secuencia de comandos"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Análisis de la secuencia de comandos"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tiempo de CPU total"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Te recomendamos que reduzcas el tiempo de análisis, compilación y ejecución de secuencias JS. Para ello, puedes entregar cargas útiles de JS más pequeñas. [Obtén más información](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduce el tiempo de ejecución de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Tiempo de ejecución de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Los GIF de gran tamaño no son eficientes para mostrar contenido animado. En su lugar, puedes utilizar formatos de video MPEG4/WebM para animaciones y formatos PNG/WebP para imágenes estáticas a fin de ahorrar bytes de la red. [Más información](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Usa formatos de video para incluir contenido animado"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Te recomendamos que uses la carga diferida para las imágenes ocultas y fuera de pantalla una vez que hayan terminado de cargarse todos los recursos críticos a fin de reducir el tiempo de carga. [Obtén más información](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Posterga la carga de imágenes que no aparecen en pantalla"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Hay recursos que bloquean el primer procesamiento de imagen de la página. Te recomendamos entregar los elementos JS/CSS críticos insertados y postergar todos los JS/estilos que no sean críticos. [Obtén más información](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimina los recursos que bloqueen el renderizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Trabajar con cargas útiles de red de gran tamaño resulta oneroso para el usuario, además de aumentar considerablemente el tiempo de carga de las páginas. [Obtén más información](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "El tamaño total era {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evita cargas útiles de red de gran tamaño"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evita cargas útiles de red de gran tamaño"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Si reduces los archivos CSS, puedes achicar el tamaño de la carga útil de la red. [Obtén más información](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Reduce el uso de CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Si reduces los archivos JavaScript, puedes achicar el tamaño de la carga útil y el tiempo de análisis de secuencias de comandos. [Obtén más información](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Reducir el uso de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Quita las reglas inactivas de las hojas de estilo y retrasa la carga de secuencias CSS que no se utilicen para el contenido de la mitad superior de la página. Así, se reducirán los bytes que consume innecesariamente la actividad de red. [Obtén más información](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Quita los recursos CSS que no se usen"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Quita el contenido JavaScript sin usar para reducir la cantidad de bytes que consume la actividad de red."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Quita el código JavaScript sin usar"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "La duración en caché por un período prolongado puede acelerar la carga de la página cuando el usuario la visita de manera repetida. [Obtén más información](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se encontró 1 recurso}other{Se encontraron # recursos}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Publica elementos estáticos con una política de caché eficaz"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Usa una política de caché eficaz en recursos estáticos"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Las imágenes optimizadas se cargan más rápido y consumen menos datos móviles. [Obtén más información](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifica las imágenes de forma eficaz"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Muestra imágenes con un tamaño adecuado para ahorrar datos móviles y reducir el tiempo de carga. [Obtén más información](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Usa un tamaño adecuado para las imágenes"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Los recursos basados en texto se deberían publicar comprimidos (gzip, deflate o brotli) para minimizar el total de bytes de la red. [Obtén más información](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Habilita la compresión de texto"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Los formatos como JPEG 2000, JPEG XR y WebP suelen comprimir mejor las imágenes que los formatos PNG o JPEG, lo que hace que se descarguen más rápido y consuman menos datos. [Obtén más información](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Publica imágenes con formatos de próxima generación"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Si el ancho del contenido de tu app no coincide con el del viewport, es posible que la app no esté optimizada para pantallas de dispositivos móviles. [Obtén más información](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "El tamaño de viewport de {innerWidth} px no coincide con el tamaño de ventana de {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "El contenido no tiene el tamaño correcto para el viewport"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "El contenido tiene el tamaño correcto para el viewport"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Las cadenas de solicitudes críticas que se muestran a continuación indican qué recursos son de alta prioridad en la carga. Te recomendamos que reduzcas la longitud de las cadenas, disminuyas el tamaño de los recursos para la descarga o postergues la descarga de recursos innecesarios para mejorar la carga de la página. [Obtén más información](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se encontró 1 cadena}other{Se encontraron # cadenas}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimiza la profundidad de las solicitudes críticas"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Baja/advertencia"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Línea"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Con el tiempo, se quitarán las API obsoletas del navegador. [Obtén más información](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se encontró 1 advertencia}other{Se encontraron # advertencias}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Usa API obsoletas"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita las API obsoletas"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "La caché de aplicaciones es obsoleta. [Obtén más información](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Se encontró \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Usa la caché de aplicaciones"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita la caché de aplicaciones"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Especificar un DOCTYPE evita que el navegador cambie al modo no estándar. [Obtén más información](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "El nombre de DOCTYPE debe ser la cadena en minúsculas `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "El documento debe contener un DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Se esperaba que publicId fuera una string vacía"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Se esperaba que systemId fuera una string vacía"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "La página no tiene el DOCKTYPE de HTML; por lo tanto, activa el modo no estándar"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "La página tiene el DOCTYPE de HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Estadística"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Los desarrolladores de navegadores recomiendan que las páginas contengan menos de alrededor de 1500 elementos de DOM. Lo ideal es que la profundidad del árbol sea inferior a 32 elementos, con 60 elementos secundarios por elemento principal como máximo. Los DOM de gran tamaño pueden aumentar el uso de la memoria, hacer que los [cálculos de estilos](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) tarden más y generar costosos [reprocesamientos del diseño](https://developers.google.com/speed/articles/reflow). [Obtén más información](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemento}other{# elementos}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evita un tamaño excesivo de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profundidad máxima de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total de elementos DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Número máximo de elementos secundarios"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evita un tamaño excesivo de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Objetivo"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Agrega `rel=\"noopener\"` o `rel=\"noreferrer\"` a cualquier vínculo externo para mejorar el rendimiento y evitar vulnerabilidades de seguridad. [Obtén más información](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Los vínculos a destinos con orígenes cruzados no son seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Los vínculos a destinos con orígenes cruzados son seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "No se puede determinar el destino de anclaje ({anchorHTML}). Si no se usa como hipervínculo, te recomendamos quitar target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Los sitios que solicitan a los usuarios su ubicación sin contexto los confunden o los hacen desconfiar. Te recomendamos vincular la solicitud a una acción del usuario. [Obtén más información](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Solicita el permiso de ubicación geográfica al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita solicitar el permiso de ubicación geográfica al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versión"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Se detectaron todas las bibliotecas JavaScript de frontend de la página. [Obtén más información](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Se detectaron bibliotecas JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "En el caso de usuarios con una conexión lenta, las secuencias de comandos externas que se incorporan dinámicamente a través de`document.write()` pueden demorar la carga de la página decenas de segundos. [Obtén más información](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Usa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "No usa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Gravedad más alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versión de la biblioteca"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Recuento de vulnerabilidades"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Es posible que algunas secuencias de comandos de terceros contengan vulnerabilidades de seguridad conocidas que los atacantes pueden identificar y aprovechar fácilmente. [Obtén más información](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se detectó una vulnerabilidad}other{Se detectaron # vulnerabilidades}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Incluye bibliotecas JavaScript de frontend con vulnerabilidades de seguridad conocidas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Baja"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Media"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita las bibliotecas JavaScript de frontend con vulnerabilidades de seguridad conocidas"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Los sitios que solicitan a los usuarios permiso para enviar notificaciones sin contexto los confunden o los hacen desconfiar. Te recomendamos vincular la solicitud a los gestos del usuario. [Obtén más información](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Solicita el permiso de notificaciones al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita solicitar el permiso de notificaciones al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementos con errores"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Evitar el pegado de contraseñas debilita las buenas políticas de seguridad. [Obtén más información](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Evita que los usuarios peguen contenido en los campos de contraseña"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permite que los usuarios peguen contenido en los campos de contraseña"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocolo"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ofrece más beneficios que HTTP/1.1, como los encabezados binarios, el multiplexado y los mensajes push del servidor. [Obtén más información](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 solicitud no se entregó mediante HTTP/2}other{# solicitudes no se entregaron mediante HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "No usa HTTP/2 para todos los recursos propios"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Usa HTTP/2 para sus propios recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Puedes marcar tus objetos de escucha de eventos táctiles y de la rueda del mouse como `passive` para mejorar el rendimiento de desplazamiento de tu página. [Obtén más información](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "No usa objetos de escucha pasivos para mejorar el rendimiento del desplazamiento"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Usa objetos de escucha pasivos para mejorar el rendimiento del desplazamiento"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descripción"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Los errores registrados en la consola indican la existencia de problemas no resueltos. Es posible que se deban a problemas con solicitudes de red y otros relativos al navegador. [Obtén más información](https://web.dev/errors-in-console)."
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Se registraron errores del navegador en la consola"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "No se registraron errores del navegador en la consola"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Utiliza la función font-display de CSS a fin de que los usuarios vean el texto mientras se carga la fuente para sitios web. [Obtén más información](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Asegúrate de que el texto permanezca visible mientras se carga la fuente web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Todo el texto permanece visible mientras se carga la fuente para sitios web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse no pudo comprobar automáticamente el valor de font-display para la siguiente URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Relación de aspecto (real)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Relación de aspecto (visualizada)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Las dimensiones de visualización de las imágenes deben coincidir con la relación de aspecto natural. [Obtén más información](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Muestra imágenes con una relación de aspecto incorrecta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Muestra imágenes con una relación de aspecto correcta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "La información sobre el tamaño de la imagen no es válida {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Los navegadores pueden solicitar a los usuarios proactivamente que agreguen tu app a la pantalla principal, lo que es posible que genere un mayor compromiso. [Obtén más información](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "El manifiesto de la aplicación web no cumple los requisitos de aptitud para la instalación"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "El manifiesto de la aplicación web cumple los requisitos de aptitud para la instalación"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL no segura"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Todos los sitios deben estar protegidos con el protocolo HTTPS, incluso aquellos que no controlan datos sensibles. Este protocolo evita que intrusos manipulen o escuchen de forma pasiva las comunicaciones entre tu app y los usuarios. Además, HTTPS es un requisito del protocolo HTTP/2 y muchas API nuevas de Web Platform. [Obtén más información](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se encontró una solicitud no segura}other{Se encontraron # solicitudes no seguras}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "No usa HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Usa HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Si las páginas se cargan rápidamente en las redes móviles, el usuario disfrutará de una buena experiencia. [Obtén más información](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactiva a los {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactiva en una red móvil simulada a los {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Tu página tarda mucho en cargarse y no es interactiva en menos de 10 segundos. Para obtener información sobre cómo mejorarla, accede a la sección Rendimiento, donde podrás consultar las oportunidades disponibles y el diagnóstico correspondiente."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "La página no se carga suficientemente rápido en las redes móviles"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "La carga de la página es lo suficientemente rápida en redes móviles"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoría"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Te recomendamos que reduzcas el tiempo de análisis, compilación y ejecución de JS. Para ello, puedes utilizar cargas útiles de JS más pequeñas. [Obtén más información](https://web.dev/mainthread-work-breakdown)."
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimiza el trabajo del hilo principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimiza el trabajo del hilo principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Para alcanzar la mayor cantidad de usuarios, los sitios tienen que funcionar en todos los navegadores principales. [Obtén más información](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "El sitio funciona en diferentes navegadores"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Garantiza que las páginas individuales puedan vincularse directamente a través de la URL y que las URL sean únicas para que se puedan compartir en redes sociales. [Obtén más información](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Cada página tiene una URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Las transiciones deben ser ágiles cuando presionas en diferentes lugares, incluso con conexiones de red lentas. Esta experiencia es la clave del rendimiento percibido del usuario. [Obtén más información](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "No parece que se bloqueen las transiciones de la página en la red"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "La latencia de entrada estimada es el tiempo aproximado, en milisegundos, que tarda tu app en responder a las acciones de los usuarios durante el periodo de 5 s más activo de carga de la página. Si la latencia es superior a 50 ms, es posible que los usuarios piensen que tu app es lenta. [Obtén más información](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latencia de entrada estimada"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "El primer procesamiento de imagen con contenido indica el momento en el que se visualiza en la pantalla el primer texto o imagen. [Obtén más información](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Primer procesamiento de imagen con contenido"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "El primer tiempo inactivo de la CPU indica la primera vez que el hilo principal de la página está lo suficientemente inactivo para recibir acciones del usuario. [Obtén más información](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primer tiempo inactivo de la CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "La primera pintura significativa mide el momento en que se muestra el contenido principal de la página. [Obtén más información](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Primera pintura significativa"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "El tiempo de carga indica cuánto tarda una página en ser totalmente interactiva. [Obtén más información](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tiempo de carga"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "El máximo retraso de primera entrada que podrían experimentar los usuarios es la duración (en milisegundos) de la tarea más larga. [Obtén más información](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Máximo retraso de primera entrada posible"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "El índice de velocidad indica la rapidez con la que se puede ver el contenido de una página. [Obtén más información](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Índice de velocidad"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Suma todos los períodos entre FCP y el tiempo de carga, cuando la tarea tarda más de 50 ms. El resultado se expresa en milisegundos."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tiempo total de bloqueo"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Los tiempos de ida y vuelta (RTT) de la red afectan mucho el rendimiento. Los valores altos de RTT respecto de un origen son indicio de que usar servidores más cercanos al usuario podría mejorar el rendimiento. [Obtén más información](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tiempos de ida y vuelta de la red"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Las latencias del servidor pueden afectar el rendimiento de la Web. Un nivel alto de latencia del servidor en un origen indica que el servidor está sobrecargado o que su rendimiento de backend es bajo. [Obtén más información](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latencias de backend del servidor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Usar un service worker permite que tu aplicación web sea confiable en condiciones de red impredecibles. [Obtén más información](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` no responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse no pudo leer el atributo `start_url` del manifiesto. Por lo tanto, se tomó como `start_url` la URL del documento. Mensaje de error: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Superior a la estimación"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Asegúrate de que la cantidad y el tamaño de las solicitudes de red sean menores que los valores objetivo establecidos en la estimación de rendimiento. [Obtén más información](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 solicitud}other{# solicitudes}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Estimación de rendimiento"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Si ya configuraste el protocolo HTTPS, asegúrate de redireccionar el tráfico de HTTP a HTTPS a fin de habilitar las características de protección de la Web para todos los usuarios. [Obtén más información](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "No redirecciona el tráfico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirecciona el tráfico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Las redirecciones provocan retrasos adicionales antes de que la página se cargue. [Obtén más información](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evita que haya varias redirecciones de página"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "A fin de configurar estimaciones para la cantidad y el tamaño de los recursos de la página, agrega un archivo budget.json. [Obtén más información](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 solicitud • {byteCount, number, bytes} KB}other{# solicitudes • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Asegúrate de que la cantidad de solicitudes y los tamaños de transferencia sean reducidos"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Los vínculos canónicos indican qué URL mostrar en los resultados de la búsqueda. [Obtén más información](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Varias URL en conflicto ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Redirige al usuario a otro dominio ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL no válida ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Hace referencia a otra ubicación de `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relativa ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Apunta a la URL raíz del dominio (la página principal), en lugar de a una página de contenido equivalente"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "El documento no tiene un vínculo `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "El documento tiene un atributo `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Las fuentes con un tamaño inferior a 12 px son demasiado pequeñas y poco legibles, lo que obliga a los visitantes que acceden con dispositivos móviles a pellizcar la pantalla para ampliarla y poder leer el texto. Intenta que más del 60% del texto de la página tenga un tamaño igual o superior a 12 px. [Obtén más información](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} del texto es legible"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "El texto es ilegible porque no hay metaetiquetas de la vista del puerto optimizadas para pantallas de dispositivos móviles."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "El porcentaje {decimalProportion, number, extendedPercent} del texto es demasiado bajo (según la muestra {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "El documento no usa tamaños de fuente legibles"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "El documento usa tamaños de fuente legibles"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Los vínculos de hreflang indican a los motores de búsqueda qué versión de una página deben incluir en los resultados de la búsqueda para una región o un idioma determinados. [Obtén más información](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "El documento no tiene un atributo `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "El documento tiene un atributo `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Es posible que las páginas con códigos de estado HTTP de error no se indexen correctamente. [Obtén más información](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "El código de estado HTTP de la página no es válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "El código de estado HTTP de la página es válido"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Los motores de búsqueda no pueden incluir tus páginas en los resultados de la búsqueda si no tienen permiso para rastrearlas. [Obtén más información](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Se bloqueó la indexación de la página"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "No se bloqueó la indexación de la página"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "El texto descriptivo de los vínculos ayuda a los motores de búsqueda a entender tu contenido. [Obtén más información](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se encontró 1 vínculo}other{Se encontraron # vínculos}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Los vínculos no tienen texto descriptivo"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Los vínculos tienen texto descriptivo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Ejecuta la [Herramienta de pruebas de datos estructurados](https://search.google.com/structured-data/testing-tool/) y la herramienta [Structured Data Linter](http://linter.structured-data.org/) para validar los datos estructurados. [Obtén más información](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Los datos estructurados son válidos"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Se pueden incluir metadescripciones en los resultados de la búsqueda para resumir el contenido de la página. [Obtén más información](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "El texto de la descripción está vacío."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "El documento no tiene una metadescripción"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "El documento tiene una metadescripción"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Los motores de búsqueda no pueden indexar el contenido de los complementos y muchos dispositivos limitan el uso de complementos o no los admiten. [Obtén más información](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "El documento usa complementos"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Los documentos evitan el uso de complementos"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Si el formato del archivo robots.txt no es correcto, es posible que los rastreadores no puedan interpretar cómo quieres que se rastree o indexe tu sitio web. [Obtén más información](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "La solicitud de robots.txt mostró el siguiente estado de HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Se encontró 1 error}other{Se encontraron # errores}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse no pudo descargar un archivo robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt no es válido"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt es válido"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Los elementos interactivos, como los botones y vínculos, deben ser suficientemente grandes (48 × 48 px) y tener alrededor el espacio necesario para que sea posible tocarlos con facilidad sin presionar otros elementos a la vez. [Obtén más información](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "El {decimalProportion, number, percent} de los elementos táctiles tiene un tamaño adecuado"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Los elementos táctiles son demasiado pequeños porque no hay metaetiquetas de la vista del puerto optimizadas para pantallas de dispositivos móviles"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "El tamaño de los elementos táctiles no es el adecuado"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Elementos superpuestos"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Elemento táctil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "El tamaño de los elementos táctiles es el adecuado"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "El service worker es la tecnología que permite que tu app use varias funciones de las apps web progresivas, como el modo sin conexión, el agregado a la pantalla principal y las notificaciones push. [Obtén más información](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Un service worker controla esta página, pero no se encontró ningún atributo `start_url` porque no se pudo analizar el archivo de manifiesto como un JSON válido"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Un service worker controla esta página, pero el atributo `start_url` ({startUrl}) está fuera del alcance del service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Un service worker controla esta página, pero no se encontró el atributo `start_url` porque no se obtuvo ningún manifiesto."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Este origen tiene al menos un service worker, pero la página ({pageUrl}) no está dentro del alcance."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "No registra un service worker que controle la página y `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registra un service worker que controle la página y `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "El uso de una pantalla de presentación con un tema asegura que los usuarios tengan una experiencia de calidad al ejecutar tu app desde sus pantallas principales. [Obtén más información](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "No se configuró para una pantalla de presentación personalizada"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Se configuró para una pantalla de presentación personalizada"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Se puede aplicar un tema a la barra de direcciones del navegador para que combine con tu sitio web. [Obtén más información](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "No establece un color de tema para la barra de direcciones."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Establece un color de tema para la barra de direcciones."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tiempo de bloqueo del subproceso principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Terceros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "El código de terceros puede reducir en gran medida el rendimiento de carga. Limita la cantidad de proveedores externos redundantes y prueba cargar el código de terceros después de que haya finalizado la carga principal de tu página. [Obtén más información](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "El código de terceros bloqueó el subproceso principal por {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduce el impacto del código de terceros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Uso por parte de terceros"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "El tiempo hasta el primer byte indica el momento en el que el servidor envía una respuesta. [Obtén más información](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "El documento raíz tardó {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduce los tiempos de respuesta del servidor (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "La respuesta del servidor es lenta (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duración"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Hora de inicio"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipo"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Te recomendamos que incorpores la API de Tiempos de usuario en tu app para calcular su rendimiento real durante las principales experiencias de usuario. [Obtén más información](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 tiempo de usuario}other{# tiempos de usuario}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Medidas y marcas de Tiempos de usuario"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Se encontró un elemento <link> previo a la conexión para \"{securityOrigin}\", pero el navegador no lo usó. Comprueba que el atributo `crossorigin` se esté usando correctamente."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Te recomendamos agregar sugerencias de recursos `preconnect` o `dns-prefetch` para establecer conexiones tempranas con orígenes externos importantes. [Obtén más información](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Establece conexión previamente con los orígenes necesarios"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Se encontró un elemento <link> de precarga para \"{preloadURL}\", pero el navegador no lo usó. Comprueba que el atributo `crossorigin` se esté usando correctamente."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Te recomendamos usar `<link rel=preload>` para dar prioridad a la obtención de los recursos que, en este momento, se solicitan en una instancia posterior de la carga de la página. [Obtén más información](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Carga previamente las solicitudes clave"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Agrega una etiqueta `<meta name=\"viewport\">` para optimizar la app para pantallas de dispositivos móviles. [Obtén más información](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "No se encontró ninguna etiqueta `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "No tiene una etiqueta `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Tiene una etiqueta `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Tu app debe mostrar algún contenido cuando JavaScript está inhabilitado, aunque solo sea un aviso para informar al usuario que se necesita JavaScript para usar la app. [Obtén más información](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "El cuerpo de la página debe renderizar parte del contenido aunque sus secuencias de comandos no estén disponibles."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "No se incluye contenido alternativo cuando no está disponible JavaScript"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Se incluye parte del contenido cuando no está disponible JavaScript"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Si estás creando una app web progresiva, puedes usar un service worker para que la app funcione sin conexión. [Obtén más información](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "La página actual no responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "La página actual responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Es posible que la página no se esté cargando sin conexión porque se redireccionó la URL de prueba ({requested}) a \"{final}\". Prueba directamente la segunda URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "A continuación, se indican consejos para optimizar el uso de ARIA en tu app, lo que puede mejorar la experiencia de los usuarios de tecnologías de asistencia, como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Aquí tienes consejos para proporcionar contenido alternativo para audio y video. Así se puede mejorar la experiencia de los usuarios con dificultades auditivas o visuales."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio y video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Estos elementos destacan las prácticas recomendadas de accesibilidad más habituales."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Prácticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Estas comprobaciones incluyen consejos para [mejorar la accesibilidad de tu app web](https://developers.google.com/web/fundamentals/accessibility). Solo algunos problemas de accesibilidad pueden detectarse de forma automática. Por eso, te recomendamos realizar también pruebas manuales."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Estos elementos abarcan áreas que las herramientas de prueba automáticas no contemplan. Obtén más información en nuestra guía sobre [cómo revisar los aspectos de accesibilidad](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accesibilidad"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "A continuación, se indican consejos para facilitar la lectura del contenido."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contraste"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "A continuación, se indican consejos para que los usuarios con diversas configuraciones regionales puedan interpretar mejor el contenido de las páginas."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalización y localización"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "A continuación, se indican consejos para mejorar la semántica de los controles de tu app. Estos consejos pueden mejorar la experiencia de los usuarios de tecnologías de asistencia, como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nombres y etiquetas"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Estas son oportunidades para mejorar la navegación con el teclado en tu app."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navegación"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Aquí tienes consejos para mejorar la lectura de datos en tablas o listas con tecnologías de asistencia como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tablas y listas"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Recomendaciones"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Las estimaciones de rendimiento establecen estándares para el rendimiento de tu sitio."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Estimaciones"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Obtén más información sobre el rendimiento de tu app. Estos números no [afectan directamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) la medición del rendimiento."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnóstico"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "El aspecto más importante del rendimiento es la rapidez con la que se renderizan los píxeles en la pantalla. Métricas clave: primer procesamiento de imagen con contenido, primera pintura significativa"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Mejoras del primer procesamiento de imagen"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Estas sugerencias pueden hacer que tus páginas se carguen más rápido. No [afectan directamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) la medición del rendimiento."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunidades"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Métricas"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Mejora la experiencia de carga general para que la página responda bien y se pueda usar lo antes posible. Métricas clave: Tiempo de carga, Índice de velocidad"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Mejoras generales"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Rendimiento"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Estas comprobaciones se centran en diferentes aspectos de las apps web progresivas. [Obtén más información](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Estas comprobaciones son necesarias según el modelo de referencia [Lista de tareas para AWP](https://developers.google.com/web/progressive-web-apps/checklist), pero Lighthouse no las realiza automáticamente. Es importante que las verifiques a mano (aunque no afectan a la puntuación)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "App web progresiva"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rápida y confiable"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Instalable"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizado para PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Estas comprobaciones aseguran que tu página esté optimizada para posicionarse bien en los resultados de los motores de búsqueda. Hay otros factores que Lighthouse no comprueba y que pueden afectar tu posicionamiento en los buscadores. [Obtén más información](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Ejecuta estos validadores adicionales en tu sitio web para comprobar más prácticas recomendadas de SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Edita el código HTML de tu página web de forma que los rastreadores puedan entender mejor el contenido de tu app."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Prácticas recomendadas para el contenido"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Para aparecer en los resultados de búsqueda, los rastreadores necesitan acceso a tu app."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Rastreo e indexación"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Asegúrate de que tus páginas estén optimizadas para dispositivos móviles a fin de que los usuarios no tengan que pellizcar ni hacer zoom para leer las páginas de contenido. [Obtén más información](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Optimizada para dispositivos móviles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL en caché"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Ubicación"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nombre"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Solicitudes"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipo de recurso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Tamaño"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tiempo de uso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Tamaño de transferencia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Ahorros posibles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Ahorros posibles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Ahorro posible de {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Ahorro posible en {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Documento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Fuente"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imagen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Contenido multimedia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Otro"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Secuencia de comandos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Hoja de estilo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Terceros"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Se produjo un error de registro de seguimiento durante la carga de la página. Vuelve a ejecutar Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Se agotó el tiempo de espera de la conexión inicial del protocolo del depurador."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome no recopiló ninguna captura de pantalla al cargar la página. Comprueba que haya contenido visible en la página y vuelve a ejecutar Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Los servidores DNS no pudieron resolver el dominio proporcionado."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "El recopilador {artifactName} obligatorio encontró un error: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Se produjo un error interno de Chrome. Reinicia Chrome y vuelve a ejecutar Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "No se ejecutó el recopilador necesario para {artifactName}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse no pudo cargar correctamente la página que solicitaste. Comprueba que estás probando la URL correcta y que el servidor responde correctamente a todas las solicitudes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse no pudo cargar correctamente la URL que solicitaste porque la página dejó de responder."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "La URL que proporcionaste no tiene un certificado de seguridad válido. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome evitó la carga de la página y mostró una pantalla intersticial. Verifica que estés probando la URL correcta y que el servidor responda adecuadamente a todas las solicitudes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse no pudo cargar correctamente la página que solicitaste. Verifica que estés probando la URL correcta y que el servidor responda adecuadamente a todas las solicitudes. (Detalles: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse no pudo cargar correctamente la página que solicitaste. Verifica que estés probando la URL correcta y que el servidor responda adecuadamente a todas las solicitudes. (Código de estado: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "La página tardó demasiado en cargarse. Sigue los consejos del informe para reducir el tiempo de carga de la página y vuelve a ejecutar Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Se superó el tiempo asignado para la respuesta de protocolo de DevTools. (Método: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Se superó el tiempo asignado para obtener el contenido de los recursos"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Al parecer, la URL que proporcionaste no es válida."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostrar auditorías"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navegación inicial"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latencia de ruta crítica máxima:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Error del informe: No hay información de la auditoría"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Datos de prueba"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Análisis de [Lighthouse](https://developers.google.com/web/tools/lighthouse/) de la página actual en una red móvil emulada. Los valores son estimados y pueden variar."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Elementos adicionales que se deben comprobar manualmente"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "No aplicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunidad"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Ahorro estimado"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditorías aprobadas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Contraer fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Expandir fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostrar recursos de terceros"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Algunos problemas afectaron la ejecución de Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Los valores son estimados y pueden variar. La medición del rendimiento se [basa solo en estas métricas](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Auditorías aprobadas con advertencias"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Advertencias: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Puedes subir tu GIF a un servicio que permita insertarlo como un video HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instala un [complemento de carga diferida de WordPress](https://wordpress.org/plugins/search/lazy+load/) con la capacidad de postergar las imágenes fuera de pantalla o bien cambia a un tema que incluya esa función. También puedes usar [el complemento AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Existen varios complementos de WordPress que pueden ayudarte a [insertar elementos fundamentales](https://wordpress.org/plugins/search/critical+css/) o a [postergar recursos menos importantes](https://wordpress.org/plugins/search/defer+css+javascript/). Ten en cuenta que las optimizaciones que ofrecen estos complementos pueden interferir con funciones de tu tema o complementos, por lo que seguramente tengas que hacer cambios en el código."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Los temas, los complementos y las especificaciones del servidor afectan al tiempo de respuesta. Puedes buscar un tema más optimizado, seleccionar un complemento de optimización o actualizar tu servidor."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Puedes mostrar fragmentos en tus listas de entradas (por ejemplo, mediante la etiqueta \"<more>\"), reducir la cantidad de entradas que se muestran en cada página, dividir tus entradas más largas en múltiples páginas o usar un complemento para postergar la carga de los comentarios."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Hay varios [complementos de WordPress](https://wordpress.org/plugins/search/minify+css/) que pueden concatenar, reducir y comprimir los estilos para acelerar tu sitio web. Te recomendamos que, si es posible, uses un proceso de compilación para reducir los estilos de forma anticipada."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Hay varios [complementos de WordPress](https://wordpress.org/plugins/search/minify+javascript/) que pueden concatenar, reducir y comprimir las secuencias de comandos para acelerar tu sitio web. Te recomendamos que, si es posible, uses un proceso de compilación para realizar la reducción de forma anticipada."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Puedes reducir o cambiar la cantidad de [complementos de WordPress](https://wordpress.org/plugins/) que cargan hojas de estilo CSS que tu página no usa. Para identificar los complementos que agregan hojas de estilo CSS innecesarias, prueba ejecutar la [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) en DevTools de Chrome. Puedes identificar el tema o complemento concreto en la URL de la hoja de estilo. Presta atención a los complementos que tengan varias hojas de estilo en la lista con muchos elementos en rojo en la cobertura de código. Los complementos solo deberían poner en cola hojas de estilo que se usen en la página."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Puedes reducir o cambiar la cantidad de [complementos de WordPress](https://wordpress.org/plugins/) que cargan secuencias JavaScript que tu página no usa. Para identificar los complementos que agregan secuencias JS innecesarias, prueba ejecutar la [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) en DevTools de Chrome. Puedes identificar el tema o complemento concreto en la URL de la secuencia de comandos. Presta atención a los complementos que tengan varias secuencias de comandos en la lista con muchos elementos en rojo en la cobertura de código. Los complementos solo deberían poner en cola secuencias de comandos que se usen en la página."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Consulta información sobre el [almacenamiento en la memoria caché del navegador en WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Puedes usar un [complemento de optimización de imágenes de WordPress](https://wordpress.org/plugins/search/optimize+images/) que comprima tus imágenes y conserve la calidad."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Carga imágenes directamente a través de la [biblioteca de medios](https://codex.wordpress.org/Media_Library_Screen) para garantizar que estén disponibles los tamaños de imagen requeridos y, luego, insértalas desde la biblioteca de medios, o bien usa el widget de imágenes para asegurarte de que se utilicen los tamaños de imagen óptimos (incluidos los que se emplean para interrupciones receptivas). Evita usar imágenes `Full Size`, a menos que las dimensiones sean adecuadas para su empleo. [Obtén más información](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Puedes habilitar la compresión de texto en la configuración de tu servidor web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Puedes utilizar un [complemento](https://wordpress.org/plugins/search/convert+webp/) o servicio que convierta automáticamente las imágenes que subas a los formatos óptimos."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es.json
new file mode 100644
index 00000000000..95c5f2c690c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/es.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Las claves de acceso permiten a los usuarios dirigirse rápidamente a una parte concreta de la página. Para facilitar una navegación correcta, las claves de acceso deben ser únicas. [Más información](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Los valores de `[accesskey]` no son únicos"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Los valores de `[accesskey]` son únicos"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Cada `role` de ARIA admite un subconjunto determinado de atributos `aria-*`. Si no coinciden, los atributos `aria-*` se invalidarán. [Más información](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no se corresponden con sus funciones"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Los atributos `[aria-*]` coinciden con sus funciones"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Algunas funciones de ARIA incluyen atributos obligatorios que describen el estado del elemento a los lectores de pantalla. [Más información](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Los elementos `[role]` no incluyen todos los atributos `[aria-*]` necesarios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Todos los elementos `[role]` tienen los atributos `[aria-*]` obligatorios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Algunas funciones principales de ARIA deben contener funciones secundarias específicas para llevar a cabo las funciones de accesibilidad correspondientes. [Más información](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "A los elementos con un `[role]` ARIA que requieren que los elementos secundarios contengan un `[role]` específico les faltan algunos o todos los elementos secundarios necesarios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Los elementos con un `[role]` ARIA que requieren que los elementos secundarios contengan un `[role]` específico tienen todos los elementos secundarios necesarios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Algunas funciones secundarias de ARIA se deben incluir dentro de funciones principales concretas para poder llevar a cabo las funciones de accesibilidad correspondientes. [Más información](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Los atributos `[role]` no están incluidos dentro de los elementos principales obligatorios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Los atributos `[role]` están incluidos en los elementos principales correspondientes"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Las funciones de ARIA deben tener valores válidos para realizar las funciones de accesibilidad correspondientes. [Más información](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Los valores de `[role]` no son válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Los valores de `[role]` son válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Las tecnologías de asistencia, como los lectores de pantalla, no pueden interpretar los atributos ARIA cuyos valores no sean válidos. [Más información](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no tienen valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Los atributos `[aria-*]` tienen valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Las tecnologías de asistencia, como los lectores de pantalla, no pueden interpretar los atributos ARIA con nombres no válidos. [Más información](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Los atributos `[aria-*]` no son válidos o no están bien escritos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Los atributos `[aria-*]` son válidos y están bien escritos"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Los subtítulos permiten a los usuarios sordos o con problemas auditivos utilizar elementos de audio, ya que proporcionan detalles esenciales como quién habla, qué se dice e información no verbal adicional. [Más información](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "A los elementos `<audio>` les falta un elemento `<track>` con el atributo `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Los elementos `<audio>` contienen un elemento `<track>` con el atributo `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementos con errores"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Si un botón no tiene un nombre accesible, los lectores de pantalla lo leerán en voz alta como \"botón\", por lo que resultan inservibles para los usuarios que necesitan usar lectores de pantalla para navegar. [Más información](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Los botones no tienen nombres accesibles"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Los botones tienen nombres accesibles"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Incluir maneras de omitir el contenido repetitivo permite a los usuarios con teclado navegar por la página de forma más eficaz. [Más información](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "La página no contiene ningún título, enlace de omisión ni región de punto de referencia"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "La página contiene un título, un enlace de omisión o una región de punto de referencia"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Los textos con poco contraste resultan difíciles o imposibles de leer para muchos usuarios. [Más información](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Los colores de fondo y de primer plano no tienen una relación de contraste adecuada."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Los colores de fondo y de primer plano tienen una relación de contraste adecuada"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Si las listas de definiciones no están bien marcadas, es posible que los lectores de pantalla las interpreten de forma confusa o imprecisa. [Más información](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Los elementos `<dl>` no contienen únicamente grupos de `<dt>` y `<dd>` o elementos `<script>` o `<template>` ordenados correctamente."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Los elementos de `<dl>` solo contienen grupos de `<dt>` y `<dd>` o elementos `<script>` o `<template>` ordenados correctamente."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Los elementos de la lista de definiciones (`<dt>` y`<dd>`) deben estar incluidos en un elemento `<dl>` principal para asegurarte de que los lectores de pantalla puedan leerlos en voz alta correctamente. [Más información](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Los elementos de la lista de definiciones están incluidos dentro de elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Los elementos de la lista de definiciones están incluidos dentro de elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Los títulos proporcionan una idea general sobre la página a los usuarios de lectores de pantalla. Además, los usuarios de buscadores se basan principalmente en los títulos para determinar si una página es relevante para su búsqueda o no. [Más información](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "El documento no contiene un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "El documento tiene un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "El valor de los atributos id debe ser único para evitar que las tecnologías de asistencia omitan otras instancias. [Más información](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Los atributos `[id]` de la página no son únicos"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Los atributos `[id]` de la página son únicos"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Los usuarios de lectores de pantalla confían en que los títulos describan el contenido de los marcos. [Más información](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Los elementos `<frame>` o `<iframe>` no tienen título"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Los elementos `<frame>` o `<iframe>` tienen un título"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Si no se especifica ningún atributo de idioma en una página, el lector de pantalla asumirá que la página está en el idioma predeterminado que el usuario eligió al configurarlo. Si el idioma de la página es diferente del predeterminado, es posible que el lector de pantalla no lea correctamente el texto de la página. [Más información](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "El elemento `<html>` no tiene un atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "El elemento `<html>` tiene un atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Especificar un [idioma BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido permite a los lectores de pantalla leer el texto correctamente en voz alta. [Más información](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "El valor del atributo `[lang]` del elemento `<html>` no es válido."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "El atributo `[lang]` del elemento `<html>` tiene un valor válido"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Los elementos informativos deberían incluir textos alternativos cortos y descriptivos. Los elementos decorativos se pueden omitir usando un atributo \"alt\" vacío. [Más información](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Los elementos de imagen no tienen ningún atributo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Los elementos de imagen tienen atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Cuando se usa una imagen como botón `<input>`, resulta útil proporcionar un texto alternativo para permitir que los usuarios de lectores de pantalla entiendan cuál es la función del botón. [Más información](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Los elementos `<input type=\"image\">` no tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Los elementos `<input type=\"image\">` contienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Las etiquetas facilitan que las tecnologías de asistencia, como los lectores de pantalla, puedan leer los controles de los formularios de forma correcta. [Más información](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Los elementos de formulario no tienen ninguna etiqueta asociada"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Los elementos de formulario tienen etiquetas asociadas"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Las tablas que solo se utilizan para crear un diseño no deben incluir elementos de datos, como los elementos th o caption, o el atributo summary, ya que podrían confundir a los usuarios de lectores de pantalla. [Más información](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Los elementos `<table>` de presentación no evitan el uso de `<th>`, `<caption>` ni del atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Los elementos `<table>` de presentación no utilizan elementos `<th>` o `<caption>` ni el atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Usar textos de enlace (y textos alternativos para las imágenes, si estas se usan como enlaces) que sean reconocibles, únicos y que se puedan seleccionar mejora la experiencia de navegación de los usuarios de lectores de pantalla. [Más información](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Los enlaces no tienen nombres reconocibles"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Los enlaces tienen nombres reconocibles"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Los lectores de pantalla leen las listas en voz alta de una forma concreta. Se recomienda utilizar una estructura de listas adecuada para que los lectores de pantalla puedan leer las listas de forma correcta. [Más información](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Las listas no contienen únicamente elementos `<li>` y elementos que admiten secuencias de comandos (`<script>` y `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Las listas contienen únicamente elementos `<li>` y elementos que admiten secuencias de comandos (`<script>` y `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Los lectores de pantalla requieren que los elementos de lista (`<li>`) estén incluidos dentro de un elemento `<ul>` o `<ol>` principal para poder leerlos correctamente en voz alta. [Más información](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Los elementos de lista (`<li>`) no están incluidos dentro de elementos principales `<ul>` o `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Los elementos de lista (`<li>`) están incluidos dentro de los elementos principales `<ul>` o `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Los usuarios no esperan que las páginas se actualicen automáticamente; si es así, se les volverá a dirigir a la parte superior de la página. Esto puede dar lugar a una experiencia frustrante o confusa. [Más información](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "El documento usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "El documento no usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Inhabilitar el zoom provoca problemas a los usuarios con visión reducida que necesitan ampliar la pantalla para poder ver correctamente el contenido de las páginas web. [Más información](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "El atributo `[user-scalable=\"no\"]` se usa en el elemento `<meta name=\"viewport\">` o el valor del atributo `[maximum-scale]` es inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` no se utiliza en el elemento `<meta name=\"viewport\">` y el valor del atributo `[maximum-scale]` no es inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Los lectores de pantalla no pueden traducir contenido que no sea texto. Al añadir texto alternativo a los elementos `<object>`, los lectores de pantalla podrán transmitir su significado a los usuarios. [Más información](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Los elementos `<object>` no tienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Los elementos `<object>` contienen texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Si el valor es superior a 0, significa que el orden de navegación es explícito. Aunque técnicamente es válido, esto suele producir experiencias frustrantes para los usuarios que necesitan usar tecnologías de asistencia. [Más información](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Algunos elementos tienen un valor de `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "No hay ningún elemento con un valor de `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Los lectores de pantalla incluyen funciones para facilitar la navegación por las tablas. Asegurarse de que las celdas `<td>` que usan el atributo `[headers]` solo hacen referencia a otras celdas de la misma tabla mejora la experiencia de los usuarios de lectores de pantalla. [Más información](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Las celdas de los elementos `<table>` que usen el atributo `[headers]` hacen referencia a un elemento `id` que no se ha encontrado en la misma tabla."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Las celdas de un elemento `<table>` que use el atributo `[headers]` hacen referencia a otras celdas de la misma tabla."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Los lectores de pantalla incluyen funciones para facilitar la navegación por las tablas. Si te aseguras de que los encabezados de las tablas siempre hagan referencia a un conjunto de celdas, puedes mejorar la experiencia de los usuarios de lectores de pantalla. [Más información](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Los elementos `<th>` y los elementos con `[role=\"columnheader\"/\"rowheader\"]` no contienen las celdas de datos que describen."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Los elementos `<th>` y los elementos con atributos `[role=\"columnheader\"/\"rowheader\"]` contienen las celdas de datos que describen."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Especificar un [idioma BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) en los elementos ayuda a asegurar que los lectores de pantalla pronuncien correctamente las palabras del texto. [Más información](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Los atributos `[lang]` no tienen un valor válido"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Los atributos `[lang]` tienen un valor válido"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Si un vídeo tiene subtítulos, los usuarios sordos o con problemas auditivos pueden acceder a la información con más facilidad. [Más información](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Los elementos `<video>` no contienen ningún elemento `<track>` con el atributo `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Los elementos `<video>` contienen un elemento `<track>` con el atributo `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Las audiodescripciones proporcionan información pertinente en vídeos cuyos diálogos no transmiten todo el contenido, como en el caso de las expresiones faciales y las escenas. [Más información](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Los elementos `<video>` no contienen ningún elemento `<track>` con el atributo `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Los elementos `<video>` contienen un elemento `<track>` con el atributo `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Para que el aspecto en iOS sea perfecto cuando los usuarios añadan una aplicación web progresiva a la pantalla de inicio, define un `apple-touch-icon`. Debe apuntar a una imagen PNG cuadrada de 192 px (o 180 px) que sea opaca. [Más información](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "No proporciona un `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` está obsoleto; se recomienda usar `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Proporciona un `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Las extensiones de Chrome han afectado de forma negativa al rendimiento de carga de esta página. Prueba a auditarla en modo incógnito o desde un perfil de Chrome sin extensiones."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Evaluación de la secuencia de comandos"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Análisis de la secuencia de comandos"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tiempo de CPU total"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Te recomendamos que reduzcas el tiempo de análisis, compilación y ejecución de JavaScript. Para ello, puedes utilizar cargas útiles de JavaScript más pequeñas. [Más información](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduce el tiempo de ejecución de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Tiempo de ejecución de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Los GIF de gran tamaño no son eficientes para mostrar contenido animado. Para usar menos bytes de la red, te recomendamos que utilices los formatos de vídeo MPEG4 o WebM para incluir animaciones y los formatos PNG o WebP para añadir imágenes estáticas en lugar del formato GIF. [Más información](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Usa formatos de vídeo para incluir contenido animado"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Te recomendamos que uses la carga diferida con imágenes ocultas y que no aparecen en pantalla una vez que todos los recursos críticos hayan terminado de cargarse para reducir el tiempo que pasa hasta que la página es interactiva. [Más información](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Pospón la carga de imágenes que no aparecen en pantalla"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Hay recursos que bloquean el primer renderizado de la página. Te recomendamos que muestres los elementos de JavaScript y CSS críticos insertados y pospongas todos los que no sean esenciales. [Más información](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimina los recursos que bloqueen el renderizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Si la carga útil de la red es muy grande, los usuarios consumen más datos móviles y las páginas tardan más en cargarse. [Más información](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Tamaño total: {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evita cargas útiles de red de gran tamaño"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evita cargas útiles de red de gran tamaño"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Si minificas los archivos CSS, se puede reducir el tamaño de la carga útil de la red. [Más información](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minifica los archivos CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Si minificas los archivos de JavaScript, se puede reducir el tamaño de la carga útil y el tiempo de análisis de la secuencia de comandos. [Más información](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minifica los recursos JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Elimina las reglas inactivas de las hojas de estilo y retrasa la carga de los archivos CSS que no se utilicen para el contenido de la mitad superior de la página. Así, se reducirán los bytes consumidos innecesariamente por la actividad de red. [Más información](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Elimina archivos CSS sin usar"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Quita el contenido JavaScript que no se use para reducir el número de bytes que consume la actividad de red."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Quita los recursos JavaScript que no se usen"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Una duración en caché más larga puede aumentar el número de visitas repetidas a tu página. [Más información](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se ha encontrado 1 recurso}other{Se han encontrado # recursos}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Publica recursos estáticos con una política de caché eficaz"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Usa una política de caché eficaz en recursos estáticos"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Las imágenes optimizadas se cargan más rápido y consumen menos datos móviles. [Más información](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifica las imágenes de forma eficaz"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Muestra imágenes con un tamaño adecuado para ahorrar datos móviles y mejorar el tiempo de carga. [Más información](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Usa un tamaño adecuado para las imágenes"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Los recursos de texto se deberían publicar comprimidos (gzip, deflate o brotli) para minimizar el total de bytes de la red. [Más información](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Habilita la compresión de texto"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Los formatos JPEG 2000, JPEG XR y WebP comprimen mejor las imágenes que los formatos PNG o JPEG, lo que hace que se descarguen más rápido y consuman menos datos. [Más información](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Publica imágenes con formatos de próxima generación"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Si el ancho del contenido de tu aplicación no coincide con el ancho del viewport, es posible que tu aplicación no esté optimizada para pantallas de dispositivos móviles. [Más información](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "El tamaño del viewport es de {innerWidth} px y no coincide con el de la ventana, que es de {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "El contenido no tiene el tamaño adecuado para el viewport"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "El contenido tiene el tamaño adecuado para el viewport"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Las cadenas de solicitud crítica que se muestran a continuación indican qué recursos son de alta prioridad. Te recomendamos que reduzcas la longitud de las cadenas, disminuyas el tamaño de los recursos o pospongas la descarga de recursos innecesarios para mejorar la carga de la página. [Más información](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se ha encontrado 1 cadena}other{Se han encontrado # cadenas}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimiza la profundidad de las solicitudes críticas"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Desactivación/Advertencia"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Línea"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Las API obsoletas se eliminarán del navegador en el futuro. [Más información](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se ha encontrado 1 advertencia}other{Se han encontrado # advertencias}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Usa API obsoletas"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita las API obsoletas"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "La caché de aplicación está obsoleta. [Más información](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Se ha detectado \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Usa caché de aplicación"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita la caché de aplicación"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Especificar un DOCTYPE evita que el navegador cambie al modo Quirks. [Más información](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "El nombre del DOCTYPE debe ser la cadena `html` en minúsculas"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "El documento debe contener un elemento DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Se esperaba que publicId fuera una cadena vacía"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Se esperaba que systemId fuera una cadena vacía"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "A la página le falta el DOCTYPE de HTML, por lo que se ha activado el modo Quirks"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "La página tiene el DOCTYPE de HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Estadística"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Los desarrolladores de navegadores recomiendan que las páginas contengan menos de 1500 elementos DOM. Lo ideal es conseguir una profundidad de árbol inferior a 32 elementos y a 60 elementos secundarios por cada elemento principal. Los DOM de gran tamaño aumentan el uso de memoria, hacen que los [cálculos de estilo](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) duren más y generan costosos [reinicios del flujo del diseño](https://developers.google.com/speed/articles/reflow). [Más información](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemento}other{# elementos}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evita un tamaño excesivo de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profundidad máxima de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total de elementos DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Número máximo de elementos secundarios"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evita un tamaño excesivo de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Destino"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Añade `rel=\"noopener\"` o `rel=\"noreferrer\"` a cualquier enlace externo para mejorar el rendimiento y evitar vulnerabilidades de seguridad. [Más información](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Los enlaces a destinos de origen cruzado no son seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Los enlaces a destinos de origen cruzado son seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "No se ha podido determinar el destino del enlace ({anchorHTML}). Si no se usa como hiperenlace, se recomienda eliminar el atributo target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Los usuarios dudan o desconfían de los sitios web que solicitan su ubicación sin contexto. Como alternativa, puedes vincular la solicitud a una acción del usuario. [Más información](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Solicita el permiso de geolocalización al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita solicitar el permiso de geolocalización al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versión"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Todas las bibliotecas frontend de JavaScript detectadas en la página. [Más información](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Bibliotecas de JavaScript detectadas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Las secuencias de comandos externas inyectadas dinámicamente mediante `document.write()` pueden retrasar la carga de la página varias decenas de segundos en conexiones lentas. [Más información](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Usa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evita `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Gravedad máxima"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versión de la biblioteca"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Número de vulnerabilidades"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Algunas secuencias de comandos externas pueden contener vulnerabilidades de seguridad conocidas que pueden ser detectadas y aprovechadas por los atacantes. [Más información](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vulnerabilidad detectada}other{# vulnerabilidades detectadas}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Incluye bibliotecas en el frontend de JavaScript con vulnerabilidades de seguridad conocidas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Baja"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Media"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita en el frontend las bibliotecas de JavaScript con vulnerabilidades de seguridad conocidas"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Los usuarios dudan o desconfían de los sitios web que solicitan enviar notificaciones sin contexto. Como alternativa, puedes vincular la solicitud a los gestos de los usuarios. [Más información](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Solicita el permiso de notificación al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita solicitar el permiso de notificación al cargar la página"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementos con errores"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Evitar que se pueda pegar texto en el campo de contraseña debilita una buena política de seguridad. [Más información](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Impide que los usuarios peguen texto en los campos de contraseña"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permite que los usuarios peguen texto en los campos de contraseña"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocolo"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ofrece muchas ventajas con respecto a HTTP/1.1, como encabezados binarios, multiplexación y servidor push. [Más información](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 solicitud no atendida mediante HTTP/2}other{# solicitudes no atendidas mediante HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "No usa HTTP/2 para todos sus recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Usa HTTP/2 para sus propios recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Se recomienda que los procesadores de eventos táctiles y de la rueda sean `passive` para mejorar el desplazamiento de tu página. [Más información](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "No usa listeners pasivos para mejorar el desplazamiento"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Usa listeners pasivos para mejorar el desplazamiento"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descripción"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Los errores registrados en la consola indican problemas sin resolver. Pueden proceder de solicitudes fallidas de la red y otros errores del navegador. [Más información](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Se han registrado errores del navegador en la consola"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "No se ha registrado en la consola ningún error del navegador"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Utiliza la característica de CSS \"font-display\" para que los usuarios vean el texto mientras se carga la fuente web. [Más información](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Asegúrate de que el texto permanece visible mientras se carga la fuente web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Todo el texto permanece visible mientras se carga la fuente web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse no ha podido comprobar automáticamente el valor de font-display de la siguiente URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Relación de aspecto (real)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Relación de aspecto (mostrada)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Las dimensiones de las imágenes mostradas deberían mantener su relación de aspecto natural. [Más información](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Muestra imágenes con una relación de aspecto incorrecta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Muestra imágenes con la relación de aspecto adecuada"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "La información del tamaño de la imagen no es válida ({url})"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Los navegadores pueden preguntar a los usuarios si quieren añadir tu aplicación a la pantalla de inicio, lo que genera más interacción. [Más información](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "El archivo de manifiesto de la aplicación web no cumple los requisitos de instalación"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "El archivo de manifiesto de la aplicación web cumple los requisitos de instalación"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL poco segura"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Todos los sitios web deberían estar protegidos con el protocolo HTTPS, incluso los que no gestionen datos sensibles. HTTPS evita que los intrusos alteren o escuchen pasivamente la comunicación entre tu aplicación y tus usuarios. Además, es un requisito previo para poder usar HTTP/2 y las API de muchas plataformas web nuevas. [Más información](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Se ha encontrado 1 solicitud poco segura}other{Se han encontrado # solicitudes poco seguras}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "No usa HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Usa HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Si las páginas se cargan rápidamente en las redes móviles, se asegurará una buena experiencia de usuario. [Más información](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Página interactiva en {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Página interactiva en una red móvil simulada en {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Tu página tarda mucho en cargar y hay que esperar 10 segundos hasta que se puede interactuar con ella. Para mejorarla, consulta las oportunidades y los diagnósticos en la sección \"Rendimiento\"."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "La página no se carga suficientemente rápido en las redes móviles"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "La carga de la página es lo suficientemente rápida en redes móviles"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoría"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Te recomendamos que reduzcas el tiempo de análisis, compilación y ejecución de JavaScript. Para ello, puedes utilizar cargas útiles de JavaScript más pequeñas. [Más información](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimiza el trabajo del hilo principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimiza el trabajo del hilo principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Para llegar al mayor número de usuarios, los sitios web deben funcionar en los navegadores principales. [Más información](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "El sitio web funciona en diferentes navegadores"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Asegúrate de que la URL de cada página sea un enlace profundo y único para poder compartir las páginas fácilmente en las redes sociales. [Más información](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Cada página tiene una URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Las transiciones deberían ser rápidas al tocar en diferentes partes de la aplicación, incluso si la red es lenta. Esta experiencia es fundamental para la percepción del usuario sobre el funcionamiento de la aplicación. [Más información](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "No parece que se bloqueen las transiciones de la página en la red"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "La latencia de entrada estimada es el tiempo, en milisegundos, que tarda tu aplicación en responder a las acciones de los usuarios durante el periodo de 5 s más activo de carga de la página. Si tu latencia es superior a 50 ms, es posible que los usuarios perciban cierto retardo en tu aplicación. [Más información](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latencia de entrada estimada"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "El primer renderizado con contenido indica el momento en el que se renderiza el primer texto o la primera imagen. [Más información](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Primer renderizado con contenido"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "El primer tiempo inactivo de la CPU indica la primera vez que el hilo principal de la página está lo suficientemente inactivo para recibir acciones del usuario. [Más información](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primer tiempo inactivo de la CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "El primer renderizado significativo mide el momento en que se muestra el contenido principal de la página. [Más información](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Primer renderizado significativo"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "El tiempo hasta que está interactiva es el tiempo que tarda una página en ser totalmente interactiva. [Más información](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tiempo hasta que está interactiva"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "La latencia potencial máxima de la primera interacción que podrían experimentar los usuarios es la duración, en milisegundos, de la tarea más larga. [Más información](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Latencia potencial máxima de la primera interacción"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "El índice de velocidad indica la rapidez con la que se puede ver el contenido de una página. [Más información](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Índice de velocidad"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Suma de los periodos, en milisegundos, entre el primer renderizado con contenido y el tiempo hasta que la página es interactiva cuando se exceden los 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tiempo total de bloqueo"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Los tiempos de ida y vuelta (RTT) de la red afectan mucho al rendimiento. Un RTT alto hasta un origen indica que usar servidores más cercanos al usuario podría mejorar el rendimiento. [Más información](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tiempos de ida y vuelta de la red"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "La latencia del servidor puede afectar al rendimiento del sitio web. Una latencia del servidor alta en un origen indica que el servidor está sobrecargado o que su rendimiento de backend es bajo. [Más información](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latencias de backend del servidor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Un service worker hace que tu aplicación web sea más fiable si la conexión de red es inestable. [Más información](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` no responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse no ha podido leer la propiedad `start_url` en el archivo de manifiesto. Por ello, se considera que el valor de `start_url` es la URL del documento. Mensaje de error: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Por encima del límite"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Mantiene la cantidad y el tamaño de las solicitudes de red por debajo de los límites definidos en los límites de rendimiento. [Más información](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 solicitud}other{# solicitudes}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Límites de rendimiento"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Si ya has configurado HTTPS, asegúrate de redirigir todo el tráfico HTTP a HTTPS para habilitar funciones de seguridad web para todos los usuarios. [Más información](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "No redirige el tráfico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirige el tráfico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Las redirecciones provocan retrasos adicionales antes de que la página se pueda cargar. [Más información](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evita que haya varias redirecciones de página"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Para definir la cantidad y el tamaño de los recursos de la página, añade un archivo budget.json. [Más información](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 solicitud: {byteCount, number, bytes} kB}other{# solicitudes: {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Reduce el número de solicitudes y el tamaño de las transferencias"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Los enlaces canónicos sugieren qué URL se debe mostrar en los resultados de búsqueda. [Más información](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Varias URL en conflicto ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Dirige a un dominio diferente ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "La URL no es válida ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Apunta a una ubicación de `hreflang` distinta ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relativa ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Apunta a la URL raíz del dominio (la página principal), en lugar de a una página de contenido equivalente"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "El documento no tiene un atributo `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "El documento tiene un atributo `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Las fuentes con un tamaño inferior a 12 px son demasiado pequeñas y poco legibles, lo que obliga a los visitantes que acceden con dispositivos móviles a pellizcar la pantalla para ampliarla y poder leer el texto. Intenta que más del 60 % del texto de la página tenga un tamaño igual o superior a 12 px. [Más información](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "El {decimalProportion, number, extendedPercent} del texto es legible"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "El texto es ilegible porque no hay metaetiquetas de viewport optimizadas para pantallas de dispositivos móviles."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "El {decimalProportion, number, extendedPercent} del texto es demasiado pequeño (según una muestra del {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "El documento no usa tamaños de fuente legibles"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "El documento usa tamaños de fuente legibles"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Los enlaces \"hreflang\" indican a los buscadores qué versiones de las páginas deben incluir en los resultados de búsqueda de una región o un idioma determinados. [Más información](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "El atributo `hreflang` del documento no es válido"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "El documento tiene un atributo `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Es posible que las páginas con códigos de estado HTTP no válidos no estén bien indexadas. [Más información](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "El código de estado HTTP de la página no es válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "El código de estado HTTP de la página es válido"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Los buscadores no pueden incluir tus páginas en los resultados de búsqueda si no tienen permiso para rastrearlas. [Más información](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Se ha bloqueado la indexación de la página"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "No se ha bloqueado la indexación de la página"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "El texto descriptivo de los enlaces ayuda a los buscadores a entender tu contenido. [Más información](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 enlace encontrado}other{# enlaces encontrados}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Los enlaces no tienen texto descriptivo"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Los enlaces tienen texto descriptivo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Ejecuta la [Herramienta de prueba de datos estructurados](https://search.google.com/structured-data/testing-tool/) y la herramienta [Structured Data Linter](http://linter.structured-data.org/) para validar los datos estructurados. [Más información](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Los datos estructurados son válidos"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Se pueden incluir metadescripciones en los resultados de búsqueda para resumir brevemente el contenido de la página. [Más información](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "El texto de la descripción está vacío."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "El documento no tiene una metadescripción"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "El documento tiene una metadescripción"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Los buscadores no pueden indexar el contenido de los complementos, y muchos dispositivos limitan el uso de complementos o no los admiten. [Más información](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "El documento usa complementos"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "El documento no usa complementos"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Si el formato del archivo robots.txt no es correcto, es posible que los rastreadores no puedan interpretar cómo quieres que se rastree o indexe tu sitio web. [Más información](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "La solicitud de robots.txt ha devuelto el siguiente código de estado HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 error encontrado}other{# errores encontrados}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse no ha podido descargar un archivo robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt no es válido"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt es válido"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Los elementos interactivos, como los botones y enlaces, deben ser lo suficientemente grandes (48x48 px) y tener suficiente espacio alrededor para poder tocarlos con facilidad sin superponerse con otros elementos. [Más información](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "El {decimalProportion, number, percent} de los elementos táctiles tiene un tamaño adecuado"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Los elementos táctiles son demasiado pequeños porque no hay metaetiquetas de viewport optimizadas para pantallas de dispositivos móviles"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "El tamaño de los elementos táctiles no es el adecuado"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Elementos superpuestos"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Elemento táctil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "El tamaño de los elementos táctiles es el adecuado"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "El service worker es la tecnología que te permite usar las funciones de las aplicaciones web progresivas, como el modo sin conexión, poder añadirlas a la pantalla de inicio y las notificaciones push. [Más información](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Un service worker controla esta página, pero no se ha encontrado ninguna propiedad `start_url` porque el archivo de manifiesto no es un JSON válido"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Un service worker controla esta página, pero la propiedad `start_url` ({startUrl}) está fuera del rango del service worker ({scopeUrl})."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Un service worker controla esta página, pero no se ha encontrado la propiedad `start_url` porque no se ha recuperado ningún archivo de manifiesto."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Este origen tiene al menos un service worker, pero la página ({pageUrl}) no está dentro del rango."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "No tiene un service worker que controle la página y la propiedad`start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Hay un service worker que controla la página y la propiedad `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Una pantalla de inicio personalizada asegura que la experiencia de los usuarios sea de calidad cuando ejecuten tu aplicación desde sus pantallas de inicio. [Más información](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "No se ha configurado para una pantalla de inicio personalizada"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Se ha configurado para una pantalla de inicio personalizada"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "El color de la barra de direcciones del navegador puede adaptarse a tu sitio web. [Más información](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "No establece un color de tema personalizado en la barra de direcciones."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Establece un color personalizado en la barra de direcciones."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tiempo de bloqueo del hilo principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Proveedor externo"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "El código externo puede afectar mucho a la velocidad de carga. Limita el número de proveedores externos redundantes e intenta cargar el código externo cuando se haya completado la carga principal de tu página. [Más información](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "El código de un tercero ha bloqueado el hilo principal durante {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduce el impacto del código de terceros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Uso de código de terceros"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "El tiempo hasta el primer byte indica el momento en el que el servidor envía una respuesta. [Más información](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "El documento raíz ha tardado {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduce los tiempos de respuesta del servidor (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Los tiempos de respuesta del servidor son rápidos (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duración"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Hora de inicio"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipo"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Te recomendamos que uses la API Tiempos de usuario en tu aplicación para calcular su rendimiento real durante las principales experiencias de usuario. [Más información](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 tiempo de usuario}other{# tiempos de usuario}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Medidas y marcas de User Timing"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Se ha encontrado un elemento <link> previo a la conexión para \"{securityOrigin}\", pero el navegador no lo ha usado. Comprueba que el atributo `crossorigin` se esté usando correctamente."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Puedes añadir sugerencias de recursos `preconnect` o `dns-prefetch` para establecer conexiones previas con orígenes importantes de terceros. [Más información](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Establece conexión previamente con los orígenes necesarios"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Se ha encontrado un elemento <link> de precarga para \"{preloadURL}\", pero el navegador no lo ha utilizado. Comprueba que el atributo `crossorigin` se esté usando correctamente."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Te recomendamos usar `<link rel=preload>` para dar prioridad a los recursos que se solicitan más tarde al cargar la página. [Más información](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Carga previamente las solicitudes clave"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Añade una etiqueta `<meta name=\"viewport\">` para que tu aplicación se vea mejor en las pantallas de los dispositivos móviles. [Más información](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "No se ha encontrado ninguna etiqueta `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "No tiene una etiqueta `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Contiene una etiqueta `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Tu aplicación debería mostrar algún contenido cuando JavaScript esté inhabilitado, aunque solo sea un aviso para informar al usuario de que es necesario activar JavaScript para usar la aplicación. [Más información](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "El cuerpo de la página debería renderizar algo de contenido aunque sus secuencias de comandos no estén disponibles."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "No ofrece contenido de reserva cuando JavaScript está inhabilitado"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Muestra algo de contenido cuando JavaScript está inhabilitado"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Si estás creando una aplicación web progresiva, puedes usar un service worker para que tu aplicación funcione sin conexión. [Más información](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "La página web no responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "La página web responde con un código de estado HTTP 200 cuando no hay conexión"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Es posible que la página no se esté cargando sin conexión porque la URL de prueba ({requested}) se haya redirigido a \"{final}\". Prueba directamente la segunda URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "A continuación se indican consejos para optimizar el uso de ARIA en tu aplicación, lo que puede mejorar la experiencia de los usuarios de tecnologías de asistencia, como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Aquí tienes consejos para proporcionar contenido alternativo para audio y vídeo. Así se puede mejorar la experiencia de los usuarios con dificultades auditivas o visuales."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio y vídeo"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Estos elementos destacan las prácticas recomendadas de accesibilidad más habituales."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Prácticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Estas comprobaciones incluyen consejos para [mejorar la accesibilidad de tu aplicación web](https://developers.google.com/web/fundamentals/accessibility). Solo se pueden detectar un subconjunto de problemas de accesibilidad de forma automática. Por eso, te recomendamos realizar pruebas manuales."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Estos elementos se ocupan de áreas que las herramientas de prueba automáticas no pueden analizar. Consulta más información sobre cómo [revisar la accesibilidad](https://developers.google.com/web/fundamentals/accessibility/how-to-review) en nuestra guía."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accesibilidad"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "A continuación se indican consejos para facilitar la lectura del contenido."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contraste"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "A continuación se indican consejos para que los usuarios con diversas configuraciones regionales puedan interpretar mejor el contenido de las páginas."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalización y localización"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "A continuación se indican consejos para mejorar la semántica de los controles de tu aplicación. Estos consejos pueden mejorar la experiencia de los usuarios de tecnologías de asistencia, como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nombres y etiquetas"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Aquí tienes consejos para facilitar el desplazamiento con el teclado en tu aplicación."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navegación"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Aquí tienes consejos para mejorar la lectura de datos en tablas o listas con tecnologías de asistencia como los lectores de pantalla."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tablas y listas"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Prácticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Los límites de rendimiento definen los estándares de rendimiento de tu sitio web."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Límites"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Consulta más información sobre el rendimiento de tu aplicación. Estos datos no [afectan directamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) a la puntuación del rendimiento."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnósticos"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "El aspecto más importante del rendimiento es la rapidez con la que se renderizan los píxeles en la pantalla. Métricas clave: Primer renderizado con contenido y Primer renderizado significativo"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Mejoras del primer renderizado"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Estas sugerencias pueden ayudar a que tu página cargue más rápido. No [afectan directamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) a la puntuación del rendimiento"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunidades"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Métricas"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Mejora la experiencia de carga general para que la página responda bien y se pueda usar lo antes posible. Métricas clave: Tiempo hasta que está interactiva, Índice de velocidad"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Mejoras generales"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Rendimiento"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Estas comprobaciones se centran en diferentes aspectos de las aplicaciones web progresivas. [Más información](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Estas comprobaciones son necesarias según el documento de referencia [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) (lista de comprobación para aplicaciones web progresivas), pero Lighthouse no las verifica automáticamente. Es importante que las verifiques a mano (aunque no afectan a la puntuación)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Aplicación web progresiva"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rapidez y fiabilidad"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Instalabilidad"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizado para PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Estas comprobaciones aseguran que tu página esté optimizada para posicionarse en los resultados de los buscadores. Hay otros factores que Lighthouse no comprueba y que pueden afectar a tu posicionamiento en los buscadores. [Más información](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Ejecuta estos validadores adicionales en tu sitio web para comprobar más prácticas recomendadas de SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Edita el código HTML de tu página web de forma que los rastreadores puedan entender mejor el contenido de tu aplicación."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Prácticas recomendadas de contenido"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Para aparecer en los resultados de búsqueda, los rastreadores necesitan acceder a tu aplicación."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Rastrear e indexar"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Asegúrate de que tus páginas están optimizadas para móviles de forma que los usuarios no tengan que pellizcar la pantalla o ampliarla para poder leer su contenido. [Más información](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Optimización para móviles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Tiempo de vida en caché"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Ubicación"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nombre"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Solicitudes"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipo de recurso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Tamaño"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Duración"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Tamaño de la transferencia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Ahorro potencial"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Ahorro potencial"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Ahorro potencial de {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Ahorro potencial de {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Documento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Fuente"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imagen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Contenido multimedia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Otros"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Secuencia de comandos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Hoja de estilo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Recursos externos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Se ha producido un error al registrar el rastro durante la carga de la página. Ejecuta Lighthouse de nuevo. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Se ha agotado el tiempo de espera de la conexión inicial del protocolo del depurador."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome no ha recopilado ninguna captura de pantalla al cargar la página. Comprueba que haya contenido visible en la página e intenta ejecutar Lighthouse de nuevo. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Los servidores DNS no han podido resolver el dominio proporcionado."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "No se ha podido recuperar el recurso {artifactName} necesario: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Se ha producido un error interno de Chrome. Reinicia Chrome y prueba a ejecutar Lighthouse de nuevo."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "No se ha podido recuperar el recurso {artifactName} necesario."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse no ha podido cargar correctamente la página que has solicitado. Comprueba que estás probando la URL correcta y que el servidor responde correctamente a todas las solicitudes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse no ha podido cargar correctamente la URL que has solicitado porque la página ha dejado de responder."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "La URL que has proporcionado no tiene un certificado de seguridad válido. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome ha evitado la carga de la página con un intersticial. Comprueba que estás probando la URL correcta y que el servidor responde correctamente a todas las solicitudes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse no ha podido cargar correctamente la página que has solicitado. Comprueba que estás probando la URL correcta y que el servidor responde correctamente a todas las solicitudes. (Detalles: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse no ha podido cargar correctamente la página que has solicitado. Comprueba que estás probando la URL correcta y que el servidor responde correctamente a todas las solicitudes. (Código de estado: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "La página ha tardado demasiado tiempo en cargarse. Sigue los consejos del informe para reducir el tiempo de carga de la página y prueba a ejecutar Lighthouse de nuevo. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Se ha superado el tiempo asignado para la respuesta de protocolo de DevTools. (Método: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Se ha superado el tiempo asignado para obtener el contenido de los recursos"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "La URL que has proporcionado no es válida."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostrar auditorías"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navegación inicial"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latencia de ruta crítica máxima:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Error del informe: no hay información de la auditoría"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Datos de prueba"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) ha analizado la página actual en una red móvil emulada. Los valores son estimaciones y pueden variar."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Elementos adicionales que se deben comprobar manualmente"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "No aplicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunidad"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Ahorro estimado"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditorías aprobadas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Ocultar fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Mostrar fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostrar recursos externos"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Algunos problemas han afectado a la ejecución de Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Los valores son estimaciones y pueden variar. La puntuación del rendimiento [se basa solo en estas métricas](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Auditorías aprobadas con advertencias"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Advertencias: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Puedes subir tu GIF a un servicio que permita insertarlo como un vídeo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instala un [complemento de carga en diferido de WordPress](https://wordpress.org/plugins/search/lazy+load/) con la capacidad de posponer imágenes que no aparecen en la pantalla, o cambia a un tema con esa función. También puedes usar el [complemento AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Existen varios complementos de WordPress que pueden ayudarte a [insertar recursos fundamentales](https://wordpress.org/plugins/search/critical+css/) o [posponer recursos menos importantes](https://wordpress.org/plugins/search/defer+css+javascript/). Ten en cuenta que las optimizaciones que ofrecen estos complementos pueden bloquear funciones de tu tema o tus complementos, así que seguramente tengas que hacer cambios en el código."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Los temas, los complementos y las especificaciones del servidor afectan al tiempo de respuesta. Puedes buscar un tema más optimizado, seleccionar un complemento de optimización o actualizar tu servidor."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Puedes mostrar fragmentos en tus listas de entradas (por ejemplo, mediante la etiqueta \"more\"), reducir la cantidad de entradas que se muestran en cada página, dividir tus entradas más largas en múltiples páginas o usar un complemento para posponer la carga de los comentarios."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Hay varios [complementos de WordPress](https://wordpress.org/plugins/search/minify+css/) que pueden concatenar, minificar y comprimir tus estilos para acelerar tu sitio web. Te recomendamos que, si es posible, uses un proceso de creación para realizar la minificación de forma anticipada."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Hay varios [complementos de WordPress](https://wordpress.org/plugins/search/minify+javascript/) que pueden concatenar, minificar y comprimir tus secuencias de comandos para acelerar tu sitio web. Te recomendamos que, si es posible, uses un proceso de creación para realizar la minificación de forma anticipada."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Puedes reducir o cambiar la cantidad de [complementos de WordPress](https://wordpress.org/plugins/) que cargan archivos CSS sin usar en tu página. Para identificar los complementos que añaden archivos CSS externos, ejecuta la [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) en DevTools de Chrome. Puedes identificar el tema o complemento concreto en la URL de la hoja de estilo. Presta atención a los complementos con varias hojas de estilo en la lista y con muchos elementos en rojo en la cobertura de código. Un complemento solo debería poner en cola una hoja de estilo (si esta se usa en la página)."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Puedes reducir o cambiar la cantidad de [complementos de WordPress](https://wordpress.org/plugins/) que cargan código de JavaScript sin usar en tu página. Para identificar los complementos que añaden código de JavaScript externo, ejecuta la [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) en DevTools de Chrome. Puedes identificar el tema o complemento concreto en la URL de la secuencia de comandos. Presta atención a los complementos con varias secuencias de comandos en la lista y con muchos elementos en rojo en la cobertura de código. Un complemento solo debería poner en cola una secuencia de comandos (si esta se usa en la página)."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Consulta más información sobre el [almacenamiento en la memoria caché del navegador en WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Puedes utilizar un [complemento de optimización de imágenes de WordPress](https://wordpress.org/plugins/search/optimize+images/) que comprima tus imágenes conservando la calidad."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Sube imágenes directamente a la [biblioteca multimedia](https://codex.wordpress.org/Media_Library_Screen) para asegurarte de que estén disponibles los tamaños de imagen necesarios y, después, insértalas desde esa biblioteca multimedia o utiliza el widget de imagen para usar los tamaños de imagen óptimos (incluidos los tamaños de los puntos de interrupción adaptables). Evita usar imágenes `Full Size`, a no ser que las dimensiones sean las adecuadas para su uso. [Más información](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Puedes habilitar la compresión de texto en la configuración de tu servidor web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Puedes utilizar un [complemento](https://wordpress.org/plugins/search/convert+webp/) o servicio que convierta automáticamente las imágenes que subas en los formatos óptimos."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fi.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fi.json
new file mode 100644
index 00000000000..581cda19943
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fi.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Pääsyavaimien avulla käyttäjät voivat nopeasti kohdistaa tiettyyn sivun osaan. Jotta sivulla siirtyminen onnistuu, jokaisen pääsyavaimen on oltava yksilöllinen. [Lue lisää](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]`-arvot eivät ole yksilöllisiä"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`-arvot ovat yksilöllisiä."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Jokainen ARIA-`role` tukee tiettyä `aria-*`-määritteiden osaa. Vastaavuusjärjestyksen sekoittaminen mitätöi `aria-*`-määritteet. [Lue lisää](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]`-määritteet eivät vastaa rooleja"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]`-määritteet vastaavat roolejaan"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Joillakin ARIA-rooleilla on pakollisia määritteitä, jotka kuvaavat elementin tilaa näytönlukuohjelmille. [Lue lisää](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`-elementeissä ei ole kaikkia vaadittuja `[aria-*]`-määritteitä"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`-elementeissä on kaikki vaaditut `[aria-*]`-määritteet"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Voidakseen suorittaa esteettömyyteen liittyvät toiminnot joidenkin alatason ARIA-roolien on kuuluttava tiettyihin ylätason rooleihin. [Lue lisää](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "ARIAn `[role]` sisältämät elementit edellyttävät alatasoilta tiettyä elementtiä (`[role]`), mutta se puuttuu osalta tai kaikilta alatasoilta."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "ARIAn `[role]` sisältämät elementit edellyttävät alatasoilta tiettyä elementtiä (`[role]`), joka on kaikilla alatasoilla."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Voidakseen suorittaa esteettömyyteen liittyvät toiminnot joidenkin alatason ARIA-roolien on kuuluttava tiettyihin ylätason rooleihin. [Lue lisää](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`-elementit eivät sisälly niiden pakolliseen ylätason elementtiin"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`-elementit sisältyvät niiden pakolliseen ylätason elementtiin"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Voidakseen suorittaa esteettömyyteen liittyvät toiminnot ARIA-rooleilla on oltava kelvolliset arvot. [Lue lisää](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]`-arvot eivät ole kelvollisia"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]`-arvot ovat kelvollisia"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Avustustekniikat (kuten näytönlukuohjelmat) eivät voi tulkita ARIA-määritteitä, joissa on virheelliset arvot. [Lue lisää](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]`-määritteiden arvot eivät ole kelvollisia"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]`-määritteiden arvot ovat kelvollisia"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Avustustekniikat (kuten näytönlukuohjelmat) eivät voi tulkita ARIA-määritteitä, joilla on virheelliset nimet. [Lue lisää](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]`-määritteet eivät ole kelvollisia tai sisältävät kirjoitusvirheitä"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]`-määritteet ovat kelvollisia eivätkä sisällä kirjoitusvirheitä"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Tekstitykset tekevät äänielementeistä merkittäviä kuuroille tai heikkokuuloisille kertomalla, kuka puhuu ja mitä, sekä antamalla muita kuin puheeseen liittyviä tietoja. [Lue lisää](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>`-elementeistä puuttuu `<track>`-elementti, jossa on `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>`-elementit sisältävät `<track>`-elementin, jossa on `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Hylätyt elementit"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Kun painikkeen nimi ei ole esteetön, näytönlukuohjelmat ilmoittavat sen painikkeeksi, jolloin se on hyödytön näytönlukuohjelmia tarvitseville käyttäjille. [Lue lisää](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Painikkeiden nimet eivät ole esteettömiä"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Painikkeiden nimet ovat esteettömiä"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Tapojen lisääminen toistuvan sisällön ohittamiseen auttaa näppäimistön käyttäjiä siirtymään sivulla tehokkaammin. [Lue lisää](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Sivu ei sisällä otsikkoa, ohituslinkkiä tai maamerkin aluetta"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Sivu sisältää otsikon, ohituslinkin tai maamerkin alueen"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Alhaisen kontrastin teksti on monelle vaikea tai mahdoton lukea. [Lue lisää](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Taustan ja etualan värien kontrastisuhde ei ole riittävä."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Taustan ja etualan värien kontrastisuhde on riittävä"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Kun määritelmäluetteloita ei ole merkitty kunnolla, näytönlukuohjelmien tuottama sisältö voi olla sekavaa tai epätarkkaa. [Lue lisää](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`-elementit eivät sisällä vain oikein järjestettyjä `<dt>`- ja `<dd>`-ryhmiä ja `<script>`- tai `<template>`-elementtejä"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`-elementit sisältävät vain oikein järjestettyjä `<dt>`- ja `<dd>`-ryhmiä ja `<script>`- tai `<template>`-elementtejä"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Määritelmien luettelokohdat (`<dt>` ja `<dd>`) on yhdistettävä ylätason `<dl>`-elementtiin, jotta näytönlukuohjelmat voivat varmasti lukea ne oikein. [Lue lisää](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Määritelmien luettelokohtia ei ole yhdistetty `<dl>`-elementeillä"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Määritelmien luettelokohdat on yhdistetty `<dl>`-elementeillä"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Nimi antaa näytönlukuohjelmaa käyttäville yleiskuvan sivusta, ja hakukoneen käyttäjille nimi on tärkeä oleellisten sivujen löytämiseen hakutuloksista. [Lue lisää](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumentissa ei ole `<title>`-elementtiä"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumentissa on `<title>`-elementti"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Tunnusmääritteen arvon on oltava yksilöllinen, jotta avustustekniikat eivät jätä muita esiintymiä huomioimatta. [Lue lisää](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Sivulla olevat `[id]`-määritteet eivät ole yksilöllisiä"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Sivulla olevat `[id]`-määritteet ovat yksilöllisiä"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Näytönlukuohjelman käyttäjät saavat tietää kehysten sisällöt vain kehysten nimien avulla. [Lue lisää](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>`- tai `<iframe>`-elementeillä ei ole nimeä"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>`- tai `<iframe>`-elementeillä on nimi"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Jos sivulla ei ole kielimääritettä, näytönlukuohjelma arvioi kieleksi oletuskielen, jonka käyttäjä valitsi ottaessaan näytönlukuohjelman käyttöön. Jos oletuskieli ei ole käytössä sivulla, näytönlukuohjelma voi ilmoittaa sivun tekstin väärin. [Lue lisää](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-elementissä ei ole `[lang]`-määritettä"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-elementissä on `[lang]`-määrite"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Kelvollisen [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ‑määritteen ilmoittaminen elementeille auttaa näytönlukuohjelmaa kertomaan tekstin oikein. [Lue lisää](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-elementin `[lang]`-määritteen arvo ei ole kelvollinen"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>`-elementin `[lang]`-määritteen arvo on kelvollinen"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informatiivisilla elementeillä pitäisi olla lyhyt ja kuvaileva vaihtoehtoinen teksti. Koristeelliset elementit voidaan ohittaa tyhjällä Alt-määritteellä. [Lue lisää](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Kuvaelementeillä ei ole `[alt]`-määritteitä"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Kuvaelementeillä on `[alt]`-määritteet"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Kun `<input>`-painikkeena käytetään kuvaa, vaihtoehtoisen tekstin lisääminen voi auttaa näytönlukuohjelman käyttäjiä ymmärtämään painikkeen tarkoituksen. [Lue lisää](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">`-elementeissä ei ole `[alt]`-tekstiä"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">`-elementeissä on `[alt]`-teksti"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Tunnisteilla varmistetaan, että avustustekniikat (kuten näytönlukuohjelmat) ilmoittavat lomakkeiden ohjaimista oikein. [Lue lisää](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Lomakkeiden elementeillä ei ole niihin liittyviä tunnisteita"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Lomake-elementeillä on niihin liittyvät tunnisteet"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Asettelua varten luodussa taulukossa ei pitäisi olla dataelementtejä, kuten taulukoiden otsikko ‑elementtejä, tekstityselementtejä tai yhteenvetomääritteitä, koska ne voivat tehdä näytönlukuohjelman käytöstä sekavaa. [Lue lisää](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Esittelyyn tarkoitetut `<table>`-elementit eivät vältä `<th>`-,`<caption>`- tai `[summary]`-määritteen käyttöä"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Esittelyyn tarkoitetut `<table>`-elementit välttävät `<th>`-,`<caption>`- tai `[summary]`-määritteiden käyttöä"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Linkkiteksti (ja vaihtoehtoinen teksti kuvia varten, kun niitä käytetään linkkeinä), joka on erottuva, yksilöllinen ja tarkennettavissa, parantaa näytönlukuohjelmaa käyttävien navigointikokemusta. [Lue lisää](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Linkkien nimet eivät ole helposti erottuvia"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Linkkien nimet ovat helposti erottuvia"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Näytönlukuohjelmat ilmoittavat luettelot tietyillä tavoilla. Kelvollinen luettelorakenne tukee näytönlukuohjelman tuottamaa sisältöä. [Lue lisää](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Luettelot eivät sisällä ainoastaan `<li>`-elementtejä ja skriptiä tukevia elementtejä (`<script>` ja `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Luettelot sisältävät ainoastaan `<li>`-elementtejä ja skriptiä tukevia elementtejä (`<script>` ja `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Näytönlukuohjelmat edellyttävät, että luettelokohdat (`<li>`) sisältyvät ylätason elementteihin `<ul>` tai `<ol>`, jotta ne voidaan ilmoittaa oikein. [Lue lisää](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Luettelokohteet (`<li>`) eivät sisälly ylätason `<ul>`- tai `<ol>`-elementtiin"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Luettelokohdat (`<li>`) sisältyvät ylätason elementteihin `<ul>` tai `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Käyttäjät eivät odota sivun päivittyvän automaattisesti, ja päivittäminen siirtää kohdistuksen takaisin sivun yläreunaan. Tämä voi tehdä käytöstä turhauttavaa tai sekavaa. [Lue lisää](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumentissa on käytössä `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumentti ei käytä `<meta http-equiv=\"refresh\">`-tagia"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Zoomauksen poistaminen käytöstä aiheuttaa ongelmia heikkonäköisille käyttäjille, jotka tarvitsevat näytön suurennusta nähdäkseen verkkosivun sisällön kunnolla. [Lue lisää](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` on käytössä `<meta name=\"viewport\">`-elementissä tai `[maximum-scale]`-määrite on pienempi kuin 5"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` ei ole käytössä `<meta name=\"viewport\">`-elementissä, ja `[maximum-scale]`-määrite on vähintään 5"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Näytönlukuohjelmat eivät voi kääntää sisältöä, joka ei ole tekstiä. Vaihtoehtoisen tekstin lisääminen `<object>`-elementteihin auttaa näytönlukuohjelmia esittämään sisällön merkityksen käyttäjille. [Lue lisää](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>`-elementeissä ei ole `[alt]`-tekstiä"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>`-elementeissä on `[alt]`-teksti"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Navigointijärjestys on eksplisiittinen, jos arvo on suurempi kuin 0. Vaikka ratkaisu on teknisesti käypä, se tekee usein kokemuksesta turhauttavan avustustekniikkaa tarvitseville käyttäjille. [Lue lisää](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Joidenkin elementtien `[tabindex]`-arvo on suurempi kuin 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Yhdenkään elementin `[tabindex]`-arvo ei ole suurempi kuin 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Näytönlukuohjelmissa on ominaisuuksia, jotka tekevät taulukoissa siirtymisestä helpompaa. Voit parantaa näytönlukuohjelman käyttäjien kokemusta varmistamalla, että `[headers]`-määritettä käyttävät `<td>`-solut viittaavat vain toisiin soluihin samassa taulukossa. [Lue lisää](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`[headers]`-määritettä käyttävät `<table>`-elementin solut viittaavat elementtiin (`id`), joka ei ole samassa taulukossa."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`[headers]`-määritettä käyttävät `<table>`-elementin solut viittaavat soluihin samassa taulukossa"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Näytönlukuohjelmissa on ominaisuuksia, jotka tekevät taulukoissa siirtymisestä helpompaa. Voit parantaa näytönlukuohjelmaa käyttävien kokemusta varmistamalla, että taulukoiden otsikot viittaavat aina johonkin solujoukkoon. [Lue lisää](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>`-elementit ja elementit, joissa on `[role=\"columnheader\"/\"rowheader\"]`, eivät sisällä niissä kuvattuja datasoluja"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>`-elementit ja elementit, joissa on `[role=\"columnheader\"/\"rowheader\"]`, sisältävät niissä kuvatut datasolut"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Kelvollisen [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ‑määritteen ilmoittaminen elementeille auttaa varmistamaan, että näytönlukuohjelma ääntää tekstin oikein. [Lue lisää](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]`-määritteiden arvot eivät ole kelvollisia"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]`-määritteillä on kelvollinen arvo"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Kun videossa on tekstitykset, kuurot ja heikkokuuloiset saavat videon tiedot paremmin. [Lue lisää](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>`-elementit eivät sisällä `<track>`-elementtiä, jossa on `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>`-elementit sisältävät `<track>`-elementin, jossa on `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Äänikuvaukset antavat videoista oleellista tietoa (esimerkiksi ilmeistä ja tapahtumapaikoista), jota ei saa keskustelusta. [Lue lisää](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>`-elementit eivät sisällä `<track>`-elementtiä, jossa on `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>`-elementit sisältävät `<track>`-elementin, jossa on `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Määritä `apple-touch-icon`, jotta iOS-näkyvyys on paras mahdollinen, kun käyttäjä lisää progressiivisen web-sovelluksen aloitusnäytölle. Sen on viitattava läpinäkymättömään neliön muotoiseen (192 px tai 180 px) PNG-tiedostoon. [Lue lisää](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Ei sisällä kelvollista `apple-touch-icon`-arvoa"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` on vanhentunut; `apple-touch-icon`-määritettä suositellaan."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Sisältää kelvollisen `apple-touch-icon`-määritteen"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chromen laajennukset heikensivät tämän sivun latausnopeutta. Yritä tarkastaa sivu incognito-tilassa tai Chrome-profiililla, johon ei ole lisätty laajennuksia."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Skriptin arviointi"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Skriptin jäsennys"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Prosessoriaika yhteensä"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Suosittelemme lyhentämään JS:n jäsentämiseen, kääntämiseen ja suorittamiseen kuluvaa aikaa. Pienempien JS-resurssien jakaminen voi helpottaa tätä. [Lue lisää](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Vähennä JavaScriptin suorittamiseen kuluvaa aikaa"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScriptin suorittamiseen kuluva aika"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Suuret GIFit eivät ole tehokas tapa jaella animoitua sisältöä. Voit pienentää ladattavien tavujen määrää jakelemalla animaatioita MPEG4- tai WebM-muodossa ja staattisia kuvia PNG- tai WebP-muodossa. [Lue lisää](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Jakele animaatiosisältöä videomuodossa"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Suosittelemme lykkäämään poissa näkyvistä olevien ja piilotettujen kuvien lataamista, kunnes kaikki kriittiset resurssit on ladattu. [Lue lisää](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Lykkää kuvien lataamista, jos ne eivät ole näkyvissä"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resurssit estävät sivun ensimmäisen renderöinnin. Suosittelemme jakelemaan kriittiset JS- ja CSS-osat sivuun upotettuina ja lykkäämään kaikkien ei-kriittisten JS- tai tyyliosien lataamista. [Lue lisää](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Poista renderöinnin estävät resurssit"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Suuret verkkoresurssit aiheuttavat kuluja käyttäjille ja liittyvät vahvasti pitkiin latausaikoihin. [Lue lisää](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Yhteenlaskettu koko oli {totalBytes, number, bytes} kt"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Vältä valtavia verkkoresursseja"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Välttää valtavia verkkoresursseja"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS-tiedostojen pienentäminen voi auttaa pienentämään verkkoresurssien kokoa. [Lue lisää](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Pienennä CSS-tiedostoja"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript-tiedostojen pienentäminen voi auttaa pienentämään resurssien kokoa ja lyhentämään skriptin jäsentämiseen kuluvaa aikaa. [Lue lisää](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Pienennä JavaScript-tiedostoja"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Poista käyttämättömät säännöt tyylisivuilta ja lykkää sellaisen CSS:n lataamista, jota ei käytetä sivun yläosan sisältöön, niin vähennät verkkotoiminnan turhaa tavujen kulutusta. [Lue lisää](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Poista käyttämätön CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Poista käyttämättömät JavaScript-osat, jotta voit vähentää verkkotoiminnan kuluttamia tavuja."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Poista käyttämätön JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Pitkä välimuistin käyttöikä voi nopeuttaa sivun lataamista, kun käyttäjä avaa sen uudelleen. [Lue lisää](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 resurssi löydetty}other{# resurssia löydetty}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Käytä tehokasta välimuistikäytäntöä staattisten resurssien jakelemiseen"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Käyttää tehokasta välimuistikäytäntöä staattisten resurssien käsittelyyn"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimoidut kuvat latautuvat nopeammin ja kuluttavat vähemmän mobiilidataa. [Lue lisää](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Koodaa kuvat tehokkaasti"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Näytä sopivan kokoisia kuvia, jotta voit vähentää mobiilidatan kulutusta ja lyhentää latausaikoja. [Lue lisää](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Määritä kuvien koko oikein"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstipohjaiset resurssit on hyvä pakata ennen jakelua (gzip, deflate tai brotli), jotta ladattavien tavujen määrä voidaan minimoida. [Lue lisää](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Ota tekstin pakkaus käyttöön"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Tietyt kuvamuodot, kuten JPEG 2000, JPEG XR ja WebP, pakkaavat sisältöä usein paremmin kuin PNG tai JPEG, minkä vuoksi ne auttavat nopeuttamaan latauksia ja vähentämään datan kulutusta. [Lue lisää](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Jakele kuvat seuraavan sukupolven muodoissa"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Jos sovelluksesi leveys ei vastaa näkymän leveyttä, sovelluksesi ei välttämättä ole mobiilinäytöille optimoitu. [Lue lisää](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Näkymän koko, {innerWidth} px, ei vastaa ikkunan kokoa, {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Sisällön koko ei vastaa näkymää"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Sisällön koko on näkymän mukainen"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Alla olevat kriittiset pyyntöketjut kertovat, minkä resurssien lataaminen priorisoidaan. Suosittelemme parantamaan sivun latausaikaa lyhentämällä ketjuja, pienentämällä resurssien latauskokoa ja lykkäämällä tarpeettomien resurssien lataamista. [Lue lisää](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ketju löydetty}other{# ketjua löydetty}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimoi kriittisten pyyntöjen syvyys"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Käytöstä poistaminen / varoitus"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Rivi"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Käytöstä poistetut käyttöliittymät poistetaan aikanaan selaimesta. [Lue lisää](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 varoitus löydetty}other{# varoitusta löydetty}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Käyttää käytöstä poistettuja sovellusliittymiä"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Välttää käytöstä poistettuja sovellusliittymiä"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Sovellusvälimuisti on poistettu käytöstä. [Lue lisää](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Löydetty {AppCacheManifest}"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Käyttää sovellusvälimuistia"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Välttää sovellusvälimuistia"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Dokumenttityypin määrittäminen estää selainta siirtymästä quirks-tilaan. [Lue lisää](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Dokumenttityypin nimen on oltava pienillä kirjaimilla kirjoitettu merkkijono `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumentin täytyy sisältää dokumenttityyppi"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Oletettu publicId-arvo on tyhjä merkkijono"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Oletettu systemId-arvo on tyhjä merkkijono"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Sivulta puuttuu HTML-tiedostotyyppi, mikä käynnistää quirks-tilan"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Sivulla on HTML-dokumenttityyppi"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elementti"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Tilastotieto"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Arvo"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Selainten kehittäjät suosittelevat käyttämään sivulla enintään noin 1 500:aa DOM-elementtiä. Sopiva puun syvyys on alle 32 elementtiä ja alle 60 ala- ja ylätason elementtiä. Suuri DOM voi lisätä muistin käyttöä, pidentää [tyylilaskelmia](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) ja aiheuttaa työläitä [asettelun uudelleenjuoksutuksia](https://developers.google.com/speed/articles/reflow). [Lue lisää](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elementti}other{# elementtiä}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Vältä liian suurta DOM:ää"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "DOM:n enimmäissyvyys"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM-elementit yhteensä"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Alatason elementtien maksimimäärä"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Välttää liian suurta DOM:ää"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Kohde"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Lisää ulkoisiin linkkeihin `rel=\"noopener\"` tai `rel=\"noreferrer\"` parantaaksesi tehokkuutta ja estääksesi tietoturvahaavoittuvuuksia. [Lue lisää](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Eri lähteisiin johtavat linkit eivät ole turvallisia"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Eri lähteisiin johtavat linkit ovat turvallisia"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Ankkurin ({anchorHTML}) kohteen määritys epäonnistui. Sinun kannattaa ehkä poistaa target=_blank, jos sitä ei käytetä linkkinä."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Sivustot, jotka pyytävät sijainnin käyttöoikeutta ilman asiayhteyttä, saavat käyttäjät epäluuloisiksi tai hämmentävät heitä. Kokeile sen sijaan yhdistää pyyntö käyttäjätoimintoon. [Lue lisää](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Pyytää maantieteellistä sijaintia sivun latauksessa"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Välttää maantieteellisen sijainnin pyytämistä sivun latauksessa"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versio"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Kaikki käyttöliittymän JavaScript-kirjastot havaittiin sivulla. [Lue lisää](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Havaitut JavaScript-kirjastot"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Hitaiden yhteyksien käyttäjien kohdalla `document.write()`-komennolla dynaamisesti lisätyt ulkoiset skriptit voivat hidastaa sivun latausta kymmenillä sekunneilla. [Lue lisää](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()` on käytössä"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Vältetty: `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Vakavin mahdollinen"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Kirjaston versio"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Haavoittuvuuksien määrä"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Jotkin kolmannen osapuolen skriptit voivat sisältää tunnettuja tietoturvahaavoittuvuuksia, joita hyökkääjien on helppo tunnistaa ja hyödyntää. [Lue lisää](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 haavoittuvuus havaittu}other{# haavoittuvuutta havaittu}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Sisältää käyttöliittymän JavaScript-kirjastot, joissa on tunnettuja tietoturvahaavoittuvuuksia"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Vakava"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Vähäinen"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Kohtalainen"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Välttää käyttöliittymän JavaScript-kirjastoja, joissa on tunnettuja tietoturvahaavoittuvuuksia"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Sivustot, jotka pyytävät lupaa ilmoitusten lähettämiseen ilman asiayhteyttä, saavat käyttäjät epäluuloisiksi tai hämmentävät heitä. Kokeile sen sijaan yhdistää pyyntö käyttäjäeleisiin. [Lue lisää](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Pyytää ilmoitusten käyttöoikeutta sivun latauksessa"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Välttää ilmoitusten käyttöoikeuden pyytämistä sivun latauksessa"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Hylätyt elementit"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Salasanan liittämisen estäminen on hyvän tietoturvakäytännön vastaista. [Lue lisää](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Estää käyttäjiä liittämästä sisältöä salasanakenttiin"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Sallii käyttäjien liittää sisältöä salasanakenttiin"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokolla"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 tarjoaa monia etuja HTTP/1.1:een verrattuna, mukaan lukien binaariotsikot, kanavoinnin ja palvelinkehotteet. [Lue lisää](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 pyyntöä ei tehty HTTP/2:n kautta}other{# pyyntöä ei tehty HTTP/2:n kautta}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Ei käytä HTTP/2:ta kaikille resursseille"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Käyttää HTTP/2:ta omille resursseilleen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Sinun kannattaa ehkä merkitä kosketus- ja vieritystapahtumien seurainten arvoksi `passive` sivun vieritystoiminnan parantamiseksi. [Lue lisää](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Ei käytä passiivisia seuraimia vieritystoiminnan parantamiseen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Käyttää passiivisia seuraimia vieritystoiminnan parantamiseen"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Kuvaus"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Konsoliin kirjatut virheet viittaavat ratkaisemattomiin ongelmiin. Ne voivat johtua epäonnistuneista verkkopyynnöistä ja muista selainongelmista. [Lue lisää](https://web.dev/errors-in-console)."
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Selainvirheet kirjattiin konsoliin"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Konsoliin ei kirjattu selainvirheitä"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Käytä CSS:n kirjasimennäyttöominaisuutta, jotta voit varmistaa, että käyttäjä näkee tekstin myös verkkofonttien lataamisen aikana. [Lue lisää](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Varmista, että teksti pysyy näkyvissä verkkofontin lataamisen aikana"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Kaikki teksti pysyy näkyvissä verkkofontin lataamisen aikana"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse ei pystynyt tarkistamaan seuraavan URL-osoitteen kirjasimennäyttöarvoa automaattisesti: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Kuvasuhde (todellinen)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Kuvasuhde (näkyvä)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Kuvan mittasuhteiden tulisi täsmätä luonnolliseen kuvasuhteeseen. [Lue lisää](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Näytä kuvat, joiden kuvasuhde on virheellinen"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Näytä kuvat, joiden kuvasuhde on oikea"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Virheelliset kuvan kokotiedot: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Selain voi aktiivisesti suositella käyttäjille sovelluksesi lisäämistä aloitusnäytölle, mikä voi edistää aktivoitumista. [Lue lisää](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Verkkosovelluksen luettelo ei vastaa asennettavuusvaatimuksia"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Verkkosovelluksen luettelo vastaa asennettavuusvaatimuksia"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Suojaamaton URL-osoite"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Kaikki sivustot tulee suojata HTTPS:llä, myös ne, jotka eivät käsittele arkaluontoista dataa. HTTPS estää tunkeutujia peukaloimasta sovelluksesi ja sen käyttäjien välistä toimintaa tai seuraamasta sitä passiivisesti. HTTPS:ää edellytetään HTTP/2:ssa ja monien uusien verkkoalustojen käyttöliittymissä. [Lue lisää](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 suojaamaton pyyntö löytyi}other{# suojaamatonta pyyntöä löytyi}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Ei käytä HTTPS:ää"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Käyttää HTTPS:ää"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Nopea sivun lataus mobiiliverkon kautta varmistaa hyvän mobiilikäyttökokemuksen. [Lue lisää](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktiivinen: {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktiivinen simuloidussa mobiiliverkossa: {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Sivu latautuu liian hitaasti eikä ole interaktiivinen 10 sekunnin sisällä. Katso mahdollisuuksia ja diagnostiikkatietoja Tehokkuus-osiosta sivujen kehittämiseksi."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Sivu ei lataudu tarpeeksi nopeasti mobiiliverkoissa"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Sivu latautuu tarpeeksi nopeasti mobiiliverkoissa"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Luokka"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Suosittelemme lyhentämään JS:n jäsentämiseen, kääntämiseen ja suorittamiseen kuluvaa aikaa. Pienempien JS-resurssien jakeleminen voi auttaa. [Lue lisää](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimoi pääsäikeen työkuorma"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimoi pääsäikeen työkuorman"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Tavoittaakseen maksimimäärän käyttäjiä sivustojen tulee toimia kaikilla tärkeillä selaimilla. [Lue lisää](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Sivusto toimii eri selaimilla"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Varmista, että yksittäisiin sivuihin voi täsmälinkittää URL-osoitteella ja että URL-osoitteet ovat ainutlaatuisia, jotta jaettavuus somessa paranee. [Lue lisää](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Joka sivulla on URL-osoite"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Napautuksilla navigoitaessa siirtymien tulee olla saumattomia, vaikka verkko olisi hidas. Näin syntyy vaikutelma toimivuudesta. [Lue lisää](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Verkko ei estä sivujen välisiä siirtymiä"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Arvioitu syöttöviive on millisekunteina annettu arvio siitä, kuinka kauan sovelluksellasi kestää vastata käyttäjän syötteeseen sivun lataamisen kiireisimmän, viiden sekunnin mittaisen jakson aikana. Jos viive on yli 50 ms, sovelluksesi voi toimia käyttäjien mielestä hitaasti. [Lue lisää](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Arvioitu syöttöviive"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Ensimmäinen sisällön renderöinti kertoo, milloin ensimmäinen tekstikohde tai kuva renderöidään. [Lue lisää](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Ensimmäinen sisällön renderöinti"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "CPU:n ensimmäinen toimettomuusjakso kertoo, milloin sivun pääsäikeen tilanne sallii syötteiden käsittelyn. [Lue lisää](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU:n ensimmäinen toimettomuusjakso"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Ensimmäinen merkityksellinen renderöinti kertoo, milloin sivun ensisijainen sisältö tulee näkyviin. [Lue lisää](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Ensimmäinen merkityksellinen renderöinti"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Interaktiivisuutta edeltävä aika tarkoittaa aikaa, joka sivulla kestää siihen, että se on täysin interaktiivinen. [Lue lisää](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Interaktiivisuutta edeltävä aika"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Käyttäjiesi suurin mahdollinen ensimmäisen toiminnon viive on pisimmän tehtävän kesto millisekunneissa. [Lue lisää](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Suurin mahdollinen ensimmäisen toiminnon viive"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Nopeusindeksi kertoo, kuinka nopeasti sivun sisältö tulee näkyviin. [Lue lisää](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Nopeusindeksi"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Kaikkien FCP:n ja interaktiivisuutta edeltävän ajan väliset ajanjaksot yhteenlaskettuna, kun tehtävän pituus on yli 50 ms (ilmoitettu millisekunteina)"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Estoaika yhteensä"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Verkon meno-paluuajoilla (RTT) on suuri vaikutus suorituskykyyn. Jos RTT lähtöpaikkaan on korkea, se on merkki siitä, että käyttäjää lähellä olevien palvelimien suorituskyvyssä on parantamisen varaa. [Lue lisää](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Verkon meno-paluuajat"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Palvelimen viiveet voivat vaikuttaa verkon suorituskykyyn. Jos lähtöpaikan palvelimen viive on korkea, se on merkki siitä, että palvelin on ylikuormittunut tai sen taustasuorituskyky on huono. [Lue lisää](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Palvelimen taustaviiveet"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service worker auttaa tekemään verkkosovelluksesta luotettavan, jos verkko-olosuhteet ovat vaikeita ennustaa. [Lue lisää](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ei vastaa 200-viestillä offline-tilassa"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` vastaa 200-viestillä offline-tilassa"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "`start_url` ei ollut Lighthousen luettavissa luettelossa. Siksi oletimme, että `start_url` on dokumentin URL-osoite. Virheilmoitus: {manifestWarning}"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Ylittää budjetin"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Pidä verkkopyyntöjen määrä ja koko tehokkuusbudjetissa määritettyjen tavoitteiden rajoissa. [Lue lisää](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 pyyntö}other{# pyyntöä}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Tehokkuusbudjetti"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Jos määritit jo HTTPS:n, varmista että ohjaat kaiken HTTP-liikenteen HTTPS:ään, jotta kaikki käyttäjät saavat turvalliset verkko-ominaisuudet. [Lue lisää](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Ei uudelleenohjaa HTTP-liikennettä HTTPS:ään"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Uudelleenohjaa HTTP-liikennettä HTTPS:ään"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Uudelleenohjaukset viivästyttävät sivun lataamista. [Lue lisää](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Vältä useita uudelleenohjauksia"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Jos haluat asettaa sivuresurssien määrälle ja koolle budjetin, lisää budget.json-tiedosto. [Lue lisää](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 pyyntö • {byteCount, number, bytes} Kt}other{# pyyntöä • {byteCount, number, bytes} Kt}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Pidä pyyntöjen määrät alhaisina ja siirtojen koot pieninä"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Ensisijaiset linkit ehdottavat, mitä URL-osoitteita näyttää hakutuloksissa. [Lue lisää](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Useita ristiriitaisia URL-osoitteita ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Viittaa toiseen verkkotunnukseen ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Virheellinen URL-osoite ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Viittaa toiseen `hreflang`-sijaintiin ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Suhteellinen URL-osoite ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Osoittaa verkkotunnuksen juuri-URL-osoitteeseen (kotisivulle) sitä vastaavan sisältösivun sijaan"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumentissa ei ole kelvollista `rel=canonical`-määritettä"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumentissa on kelvollinen `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Alle 12 pikselin kirjasinkoot ovat liian pieniä luettavaksi ja edellyttävät mobiilivierailijoiden zoomaavan nipistämällä voidakseen lukea. Pyri siihen, että >60 % sivun tekstistä on ≥12 px. [Lue lisää](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} lukukelpoista tekstiä"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Teksti on lukukelvotonta, koska näkymän sisällönkuvauskenttää ei ole optimoitu mobiilinäytöille."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} tekstistä on liian pientä (perustuen {decimalProportionVisited, number, extendedPercent}:n näytteeseen)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumentissa ei käytetä lukukelpoisia kirjasinkokoja"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumentti käyttää lukukelpoisia kirjasinkokoja"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang-linkit kertovat hakukoneille, mikä sivuversio niiden pitäisi lisätä tietyn kielen tai alueen hakutuloksiin. [Lue lisää](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumentissa ei ole kelvollista `hreflang`-elementtiä"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumentissa on kelvollinen `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Epäonnistuneita HTTP-tilakoodeja sisältäviä sivuja ei välttämättä indeksoida oikein. [Lue lisää](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Sivun HTTP-tilakoodi on epäonnistunut"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Sivun HTTP-tilakoodi on onnistunut"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Hakukoneet eivät voi sisällyttää sivujasi hakutuloksiin, jos niillä ei ole lupaa indeksoida niitä. [Lue lisää](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Sivun indeksointi on estetty"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Sivun indeksointia ei ole estetty"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Kuvailevat linkkitekstit auttavat hakukoneita ymmärtämään sisältöäsi. [Lue lisää](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 linkki löydetty}other{# linkkiä löydetty}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linkeissä ei ole kuvaavaa tekstiä"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linkeissä on kuvailevaa tekstiä"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Suorita [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) ja [Structured Data Linter](http://linter.structured-data.org/) vahvistaaksesi strukturoidun datan. [Lue lisää](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturoitu data on kelvollinen"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Hakutuloksiin voidaan lisätä sisällönkuvauskenttiä, joissa kuvaillaan sivun sisältöä lyhyesti. [Lue lisää](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Kuvausteksti on tyhjä."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumentissa ei ole sisällönkuvauskenttää"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumentissa on sisällönkuvauskenttä"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Hakukoneet eivät voi indeksoida laajennusten sisältöä, ja monet laitteet rajoittavat laajennusten käyttöä tai eivät tue niitä. [Lue lisää](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumentti käyttää laajennuksia"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumentti välttää laajennuksia"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Jos robots.txt-tiedostosi on muotoiltu väärin, indeksointirobotit eivät välttämättä ymmärrä, miten haluat sivustosi indeksoitavan. [Lue lisää](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Robots.txt-pyyntö palautti HTTP-tilan: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 virhe löydetty}other{# virhettä löydetty}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse ei voinut ladata robots.txt-tiedostoa"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt ei ole kelvollinen"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt on kelvollinen"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktiivisten elementtien, kuten painikkeiden ja linkkien, on oltava tarpeeksi suuria (48 x 48 px) ja niiden ympärillä on oltava tarpeeksi tilaa, jotta niiden napauttaminen onnistuu helposti niin, etteivät ne ole muiden elementtien päällä. [Lue lisää](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} oikean kokoisia napautuskohteita"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Napautuskohteet ovat liian pieniä, koska näkymän sisällönkuvauskenttää ei ole optimoitu mobiilinäytöille"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Napautuskohteet eivät ole sopivan kokoisia"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Päällekkäinen kohde"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Napautuskohde"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Napautuskohteet ovat sopivan kokoisia"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service worker ‑teknologia tuo sovelluksen käyttöön monia progressiivisen web-sovelluksen ominaisuuksia, kuten offline-käytön, aloitusnäytölle lisäämisen ja ilmoitukset. [Lue lisää](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Service worker hallitsee sivua, mutta osoitetta (`start_url`) ei löytynyt, koska luetteloa ei voitu jäsentää kelvollisena JSONina."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Service worker hallitsee sivua, mutta `start_url` ({startUrl}) ei ole workerin toiminta-alueella ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Service worker hallitsee sivua, mutta osoitetta (`start_url`) ei löytynyt, koska luetteloa ei noudettu."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Lähteessä on ainakin yksi service worker, mutta sivu ({pageUrl}) ei kuulu sen toiminta-alueeseen."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Ei rekisteröi service workeria, jonka hallinnassa sivu ja `start_url` ovat"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Rekisteröi service workerin, jonka hallinnassa sivu ja `start_url` ovat"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Teeman sisältävä aloitussivu varmistaa laadukkaan kokemuksen, kun käyttäjä avaa sovelluksen aloitusnäytöltään. [Lue lisää](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Yksilöityä aloitusnäyttöä ei ole määritetty"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Yksilöity aloitusnäyttö määritetty"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Voit muokata selaimen osoitepalkkia sivustosi teeman mukaiseksi. [Lue lisää](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Ei aseta osoitepalkin teemaväriä"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Asettaa osoitepalkin teemavärin"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Pääsäikeen estoaika"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Kolmas osapuoli"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kolmannen osapuolen koodi voi vaikuttaa lataustehokkuuteen merkittävästi. Rajoita tarpeettomien kolmannen osapuolen palveluntarjoajien määrää ja yritä ladata kolmannen osapuolen koodi sen jälkeen, kun sivun ensisijainen lataus on valmis. [Lue lisää](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kolmannen osapuolen koodi esti pääsäikeen {timeInMs, number, milliseconds} ms:n ajan"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Vähennä kolmannen osapuolen koodin vaikutusta"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Kolmannen osapuolen käyttö"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Ensimmäistä tavua edeltävä aika kertoo, kuinka kauan kestää, ennen kuin palvelimesi lähettää vastauksen. [Lue lisää](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Päädokumentti käytti {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Lyhennä palvelimen vastausaikoja (ensimmäistä tavua edeltävä aika)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Palvelimen vastausajat ovat lyhyitä (ensimmäistä tavua edeltävä aika)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Kesto"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Aloitusaika"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tyyppi"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Suosittelemme käyttämään sovelluksen kehittämisessä User Timing ‑sovellusliittymää mittaamaan todellista toimivuutta tärkeiden käyttökokemusten aikana. [Lue lisää](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 käyttäjän ajankäyttömerkintä}other{# käyttäjän ajankäyttömerkintää}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing ‑merkinnät ja ‑mitat"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Yhteyttä edeltävä linkki (<link>) löytyi osoitteelle {securityOrigin}, mutta selain ei käyttänyt sitä. Varmista, että käytät eri lähteiden `crossorigin`-määritettä oikein."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Suosittelemme lisäämään sivulle `preconnect`- tai `dns-prefetch` ‑resurssivihjeitä, joiden avulla yhteydet tärkeisiin kolmannen osapuolen lähteisiin voidaan muodostaa ajoissa. [Lue lisää](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Muodosta yhteydet pakollisiin kohteisiin etukäteen"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Esilatauslinkki <link> löytyi osoitteelle {preloadURL}, mutta selain ei käyttänyt sitä. Varmista, että käytät eri lähteiden `crossorigin`-määritettä oikein."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Suosittelemme käyttämään `<link rel=preload>`-tagia, jotta voit priorisoida resursseja, joiden noutamista pyydetään sivun lataamisen myöhemmässä vaiheessa. [Lue lisää](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Lataa tärkeät pyynnöt etukäteen"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Lisää `<meta name=\"viewport\">`-tagi optimoidaksesi sovelluksen mobiilinäytöille. [Lue lisää](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "`<meta name=\"viewport\">`-tagia ei löytynyt"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "`<meta name=\"viewport\">` ‑tagi, jossa `width` tai `initial-scale`, puuttuu"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "`<meta name=\"viewport\">` ‑tagi, jossa `width` tai `initial-scale`, löytyy"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Sovelluksen tulee näyttää jotakin sisältöä, vaikka JavaScript ei ole toiminnassa. Näytä käyttäjälle vähintään varoitus, että JavaScript on pakollinen sovelluksen käyttöä varten. [Lue lisää](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Sivun runko-osan pitäisi renderöidä sisältöä, vaikka sen skriptit eivät ole saatavilla."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Ei palauta varasisältöä, kun JavaScript ei ole käytettävissä"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Palauttaa sisältöä, vaikka JavaScript ei ole käytettävissä"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Jos kehität progressiivista web-sovellusta, harkitse service workerin käyttöä tukemaan sovelluksen toimintaa offline-tilassa. [Lue lisää](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Nykyinen sivu ei vastaa 200-viestillä offline-tilassa"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Nykyinen sivu vastaa 200-viestillä offline-tilassa"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Sivun offline-lataus ei ehkä onnistu, koska testi-URL ({requested}) ohjattiin uudelleen osoitteeseen {final}. Kokeile suoraan toista URL-osoitetta."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Näillä voit parantaa ARIA:n käyttöä sovelluksessasi, mikä voi tehdä avustusteknologiaa (kuten näytönlukuohjelmaa) käyttävien kokemuksesta paremman."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Näillä voit antaa vaihtoehtoista sisältöä äänelle ja videolle. Tämä voi parantaa kuulo- tai näkörajoitteisten käyttäjien kokemusta."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Ääni ja video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Näissä kohdissa kerrotaan yleisistä esteettömyyden parhaista käytännöistä."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Parhaat käytännöt"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Nämä tarkistukset tuovat esiin kohtia, joissa voit [parantaa verkkosovelluksesi esteettömyyttä](https://developers.google.com/web/fundamentals/accessibility). Vain pieni joukko esteettömyysongelmia voidaan havaita automaattisesti, joten myös manuaalista testaamista suositellaan."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Nämä kohteet koskevat alueita, joita automaattinen testaustyökalu ei voi testata. Lue lisää [esteettömyystarkistuksen tekemisen](https://developers.google.com/web/fundamentals/accessibility/how-to-review) oppaastamme."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Esteettömyys"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Näillä voit parantaa sisältösi luettavuutta."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrasti"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Näillä voit parantaa tulkintoja, joita eri alueiden käyttäjät tekevät sisällöstäsi."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Kansainvälistyminen ja lokalisointi"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Näillä voit parantaa sovelluksen ohjainten semantiikkaa. Tämä voi parantaa avustusteknologiaa (kuten näytönlukuohjelmaa) käyttävien kokemusta."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nimet ja tunnisteet"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Nämä ovat tilaisuuksia parantaa näppäimistöllä siirtymistä sovelluksessasi."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Siirtyminen"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Näillä voi parantaa taulukko- tai luettelodatan lukukokemusta avustusteknologiaa (kuten näytönlukuohjelmaa) käyttäville."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Taulukot ja luettelot"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Parhaat käytännöt"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Tehokkuusbudjetit määrittävät sivuston tehokkuuden standardit."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budjetit"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Lisätietoja sovelluksen toiminnasta. Luvut eivät [suoraan vaikuta](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) tehokkuusprosenttiin."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostiikka"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Tehokkuuden tärkein osa-alue on se, kuinka nopeasti pikselit renderöidään näytölle. Tärkeimmät mittarit ovat ensimmäinen sisällön renderöinti ja ensimmäinen merkityksellinen renderöinti."
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Ensimmäistä renderöintiä koskevat parannusehdotukset"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Nämä ehdotukset voivat auttaa sivua latautumaan nopeammin. Ne eivät [suoraan vaikuta](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) tehokkuusprosenttiin."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Suositukset"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Tiedot"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Paranna latauskokemusta kokonaisuutena, jotta sivu on responsiivisempi ja käytettävissä mahdollisimman pian. Tärkeimmät mittarit ovat interaktiivisuutta edeltävä aika ja nopeusindeksi."
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Yleiset parannusehdotukset"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Tehokkuus"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Näillä testeillä vahvistetaan progressiivisen web-sovelluksen ominaisuudet. [Lue lisää](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Normaali [PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) sisältää nämä kohdat, mutta Lighthouse ei tarkista niitä automaattisesti. Ne eivät vaikuta tulokseesi, mutta on tärkeää, että tarkistat kohdat manuaalisesti."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressiivinen web-sovellus"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Nopea ja luotettava"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Asennettavissa"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA optimoitu"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Näillä tarkistuksilla varmistetaan, että sivusi optimoidaan hakukoneiden tulossijoituksia varten. Hakusijoitukseesi voivat vaikuttaa myös muut tekijät, joita Lighthouse ei tarkista. [Lue lisää](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Käytä näitä lisätarkistustyökaluja sivustollasi tarkistaaksesi kaikki hakukoneoptimoinnin parhaat käytännöt."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Hakukoneoptimointi"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Muotoile HTML niin, että indeksointirobottien on helpompi ymmärtää sovelluksen sisältöä."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Parhaat sisältökäytännöt"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Indeksointiroboteilla on oltava pääsy sovellukseen, jotta se voi näkyä hakutuloksissa."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Indeksointi ja hakemistoon lisääminen"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Varmista, että sivut ovat mobiiliystävällisiä, jotta käyttäjien ei tarvitse nipistää tai lähentää sisältösivuja lukeakseen niitä. [Lue lisää](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobiiliystävällinen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Välimuistin käyttöikä"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Sijainti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nimi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Pyynnöt"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Resurssin tyyppi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Koko"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Käytetty aika"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Siirron koko"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL-osoite"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potentiaalinen säästö"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potentiaalinen säästö"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potentiaalinen säästö: {wastedBytes, number, bytes} kt"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potentiaalinen säästö: {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokumentti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Kirjasin"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Kuva"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Muu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skripti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Tyylisivu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Kolmas osapuoli"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Yhteensä"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Sivun lataamisen jäljen tallennuksessa tapahtui virhe. Suorita Lighthouse uudelleen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Aikakatkaisu: odotetaan yhteyttä virheenkorjausprotokollaan"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome ei kerännyt kuvakaappauksia sivun latautumisen aikana. Varmista, että sisältö näkyy sivulla, ja suorita sitten Lighthouse uudelleen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-palvelimet eivät voineet ratkaista verkkotunnusta."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Vaadittu {artifactName}-keräystoiminto kohtasi virheen: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Tapahtui sisäinen Chrome-virhe. Käynnistä Chrome uudelleen ja yritä suorittaa Lighthouse sen jälkeen."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Vaadittua {artifactName}-keräystoimintoa ei suoritettu."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse ei pystynyt lataamaan pyytämääsi sivua luotettavasti. Varmista, että testaat oikeaa URL-osoitetta ja että palvelin vastaa kunnolla kaikkiin pyyntöihin."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse ei pystynyt lataamaan pyytämääsi URL-osoitetta luotettavasti, koska sivu lakkasi vastaamasta."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Ilmoittamasi URL-osoitteen suojausvarmenne ei ole kelvollinen. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome esti sivun lataamisen välimainoksella. Varmista, että testaat oikeaa URL-osoitetta ja että palvelin vastaa kunnolla kaikkiin pyyntöihin."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse ei pystynyt lataamaan pyytämääsi sivua luotettavasti. Varmista, että testaat oikeaa URL-osoitetta ja että palvelin vastaa kunnolla kaikkiin pyyntöihin. (Tiedot: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse ei pystynyt lataamaan pyytämääsi sivua luotettavasti. Varmista, että testaat oikeaa URL-osoitetta ja että palvelin vastaa kunnolla kaikkiin pyyntöihin. (Tilakoodi: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Sivun lataaminen kesti liian kauan. Lyhennä sivun latausaikaa raportin ehdotusten mukaisesti ja yritä suorittaa Lighthouse sen jälkeen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools-protokollan vastauksen odotus on ylittänyt sille lasketun ajan. (Tapa: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Resurssisisällön hakeminen on ylittänyt sille varatun ajan"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Kirjoittamasi URL-osoite näyttää olevan virheellinen."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Näytä tarkastukset"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Ensimmäinen navigointi"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Kriittisen polun enimmäisviive:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Virhe!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Raporttivirhe: ei tarkastustietoja"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratoriodata"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysoi nykyisen sivun mobiiliverkon emulaation avulla. Arvot ovat arvioita ja voivat vaihdella."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Lisää manuaalisesti tarkistettavia kohteita"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Ei sovellu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Suositus"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Arvioitu säästö"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Hyväksytyt tarkastukset"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Tiivistä koodinpätkä"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Laajenna koodinpätkä"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Näytä kolmannen osapuolen resurssit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Lighthousen suorituksessa havaittiin ongelmia:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Arvot ovat arvioita ja voivat vaihdella. Tehokkuusprosentti [perustuu vain näihin mittareihin](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Läpäisi tarkastukset, mutta sai varoituksia"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Varoitukset: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "GIF kannattaa ehkä ladata palveluun, jonka avulla se voidaan upottaa HTML5-videona."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Asenna [WordPressin lazy load ‑laajennus](https://wordpress.org/plugins/search/lazy+load/), joka lykkää näytöllä näkymättömien kuvien lataamista, tai vaihda teemaan, joka tarjoaa tämän ominaisuuden. Harkitse myös [AMP-laajennuksen](https://wordpress.org/plugins/amp/) käyttöä."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Monet WordPress-laajennukset voivat [tuoda tärkeää materiaalia sivun sisälle](https://wordpress.org/plugins/search/critical+css/) tai [lykätä vähemmän tärkeiden resurssien lataamista](https://wordpress.org/plugins/search/defer+css+javascript/). Huomaa, että näiden laajennusten tuomat optimoinnit voivat rikkoa teeman tai laajennusten toimintoja, joten sinun on todennäköisesti muutettava koodia."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Teemat, laajennukset ja palvelinasetukset vaikuttavat kaikki palvelimen vastausaikaan. Sinun kannattaa ehkä etsiä optimoidumpi teema, valita optimointilaajennus tai päivittää palvelimesi."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Sinun kannattaa ehkä näyttää postausluettelossa katkelmia (esim. more-tagin avulla), näyttää yhdellä sivulla vähemmän postauksia, jakaa pitkät postaukset usealle sivulle tai käyttää kommenttien lazy load ‑laajennusta."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Monet [WordPress-laajennukset](https://wordpress.org/plugins/search/minify+css/) voivat nopeuttaa sivustosi toimintaa yhdistämällä, kutistamalla ja pakkaamalla tyylejä. Tämä kutistaminen voidaan mahdollisesti tehdä jo aiemmin kehitysvaiheen prosessilla."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Monet [WordPress-laajennukset](https://wordpress.org/plugins/search/minify+javascript/) voivat nopeuttaa sivustosi toimintaa yhdistämällä, kutistamalla ja pakkaamalla skriptejä. Tämä kutistaminen voidaan mahdollisesti tehdä jo aiemmin kehitysvaiheen prosessilla."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Sinun kannattaa ehkä poistaa tai vaihtaa toisiin [WordPress-laajennuksia](https://wordpress.org/plugins/), jotka lataavat sivulla käyttämätöntä CSS:ää. Etsi tarpeetonta CSS:ää lisääviä laajennuksia [tutkimalla koodin testikattavuutta](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) Chromen DevToolsissa. Löydät syynä olevan teeman tai laajennuksen tyylitiedoston URL-osoitteen avulla. Etsi laajennuksia, joilla on monia tyylitiedostoja luettelossa ja paljon punaista koodin testikattavuudessa. Laajennuksen pitäisi lisätä tyylitiedosto jonoon vain, jos sitä todella käytetään sivulla."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Sinun kannattaa ehkä poistaa tai vaihtaa toisiin [WordPress-laajennuksia](https://wordpress.org/plugins/), jotka lataavat sivulla käyttämätöntä JavaScriptiä. Etsi tarpeetonta JS:ää lisääviä laajennuksia [tutkimalla koodin testikattavuutta](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) Chromen DevToolsissa. Löydät syynä olevan teeman tai laajennuksen skriptin URL-osoitteen avulla. Etsi laajennuksia, joilla on monia skriptejä luettelossa ja paljon punaista koodin testikattavuudessa. Laajennuksen pitäisi lisätä skripti jonoon vain, jos sitä todella käytetään sivulla."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Lue lisää [selaimen välimuistin käytöstä WordPressissä](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Harkitse [WordPressin kuvaoptimointilaajennusta](https://wordpress.org/plugins/search/optimize+images/), joka pakkaa kuvat mutta säilyttää niiden laadun."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Lataa kuvat suoraan [mediakirjastosta](https://codex.wordpress.org/Media_Library_Screen), jolloin oikeat kuvakoot ovat varmasti saatavilla, ja lisää ne kuvakirjastosta tai varmista oikeiden kuvakokojen käyttö kuva-widgetillä (myös responsiivisuuden raja-arvojen kohdalla). Älä käytä kuvia, joiden koko on `Full Size`, paitsi jos sivun koko on riittävä. [Lue lisää](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Voit ottaa tekstin pakkaamisen käyttöön palvelimen määrityksistä."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Sinun kannattaa ehkä käyttää [laajennusta](https://wordpress.org/plugins/search/convert+webp/) tai palvelua, joka muuntaa ladatut kuvat automaattisesti oikeisiin muotoihin."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fil.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fil.json
new file mode 100644
index 00000000000..bccb5455e07
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fil.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Hinahayaan ng mga access key ang mga user na mabilis na makatuon sa isang bahagi ng page. Para sa maayos na navigation, natatangi dapat ang bawat access key. [Matuto pa](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Hindi natatangi ang mga value na `[accesskey]`"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Natatangi ang mga value ng `[accesskey]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Sinusuportahan ng bawat `role` ng ARIA ang isang partikular na subset ng mga attribute na `aria-*`. Kapag hindi pinagtugma ang mga ito, magiging invalid ang mga attribute na `aria-*`. [Matuto pa](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Hindi tumutugma ang mga attribute na `[aria-*]` sa mga tungkulin ng mga ito"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Tumutugma ang mga attribute na `[aria-*]` sa mga tungkulin ng mga ito"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Ang ilang tungkulin ng ARIA ay may mga kinakailangang attribute na naglalarawan sa status ng element sa mga screen reader. [Matuto pa](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "May mga kulang na kinakailangang attribute na `[aria-*]` ang mga `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Mayroon ng lahat ng kinakailangang attribute na `[aria-*]` ang mga `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Dapat maglaman ang ilang parent role ng ARIA ng mga partikular na child role para maisagawa nito ang mga nilalayong function sa pagiging accessible. [Matuto pa](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Ang mga element na may ARIA na `[role]` na nag-aatas sa mga child na maglaman ng partikular na `[role]` ay kulang ng ilan sa o lahat ng mga kinakailangang child na iyon."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Ang mga element na may ARIA na `[role]` na nag-aatas sa mga child na maglaman ng partikular na `[role]` ay mayroon ng lahat ng kinakailangang child."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Ang ilang child role ng ARIA ay laman dapat ng mga partikular na parent role para maayos na maisagawa ang mga nilalayong function sa pagiging accessible. [Matuto pa](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Hindi nakapaloob ang mga `[role]` sa kinakailangang parent element ng mga ito"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Nakapaloob ang mga `[role]` sa kinakailangang pangunahing element ng mga ito"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Dapat ay may mga valid na value ang mga tungkulin ng ARIA para maisagawa ang mga nilalayong function sa pagiging accessible. [Matuto pa](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Hindi valid ang mga value ng `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Valid ang mga value ng `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Hindi mauunawaan ng mga nakakatulong na teknolohiya, gaya ng mga screen reader, ang mga attribute ng ARIA na may mga invalid na value. [Matuto pa](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Walang valid na value ang mga attribute na`[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "May valid na value ang mga attribute na `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Hindi mauunawaan ng mga nakakatulong na teknolohiya, gaya ng mga screen reader, ang mga attribute ng ARIA na may mga invalid na pangalan. [Matuto pa](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Hindi valid o hindi mali ang spelling ng mga attribute na `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Valid at hindi mali ang spelling ng mga attribute na `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Ginagawang kapaki-pakinabang ng mga caption ang mga element ng audio para sa mga user na bingi o may problema sa pandinig, nagbibigay ng mahalagang impormasyon gaya ng kung sino ang nagsasalita, ano ang kanilang sinasabi, at iba pang hindi binibigkas na impormasyon. [Matuto pa](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "May kulang na element na `<track>` na may `[kind=\"captions\"]` ang mga element na `<audio>`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Naglalaman ng element na `<track>` na may `[kind=\"captions\"]` ang mga element na `<audio>`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Mga Hindi Nakapasang Element"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Kapag walang naa-access na pangalan ang isang button, iaanunsyo ito ng mga screen reader bilang \"button,\" kaya naman hindi ito magagamit ng mga user na umaasa sa mga screen reader. [Matuto pa](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Walang naa-access na pangalan ang mga button"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "May naa-access na pangalan ang mga button"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Kapag nagdagdag ng mga paraan para i-bypass ang paulit-ulit na content, mas madaling makakapag-navigate sa page ang mga user ng keyboard. [Matuto pa](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Walang heading, link ng paglaktaw, o rehiyon ng landmark ang page"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Ang page ay naglalaman ng heading, link ng paglaktaw, o rehiyon ng landmark"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Mahirap o imposibleng mabasa ng maraming user ang text na mababa ang contrast. [Matuto pa](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Kulang ang ratio ng contrast ng mga kulay ng background at foreground."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "May sapat na ratio ng contrast ang mga kulay ng background at foreground"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Kapag hindi naka-mark up nang maayos ang mga listahan ng kahulugan, puwedeng gumawa ng nakakalito o hindi tumpak na output ang mga screen reader. [Matuto pa](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Hindi naglalaman ang `<dl>` ng mga nakaayos lang na pangkat na `<dt>` at `<dd>`, mga element na `<script>` o `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Naglalaman ang `<dl>` ng mga nakaayos lang na `<dt>` at mga `<dd>` na pangkat, `<script>` o mga `<template>` na element."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Nakapaloob dapat ang mga item sa listahan ng kahulugan (`<dt>` at `<dd>`) sa isang parent element na `<dl>` para matiyak na maayos na maiaanunsyo ng mga screen reader ang mga ito. [Matuto pa](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Hindi nakapaloob sa mga element na `<dl>` ang mga item sa listahan ng kahulugan"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Nakapaloob sa mga element na `<dl>` ang mga item sa listahan ng kahulugan"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Binibigyan ng pamagat ang mga user ng screen reader ng pangkalahatang-ideya ng page, at lubos na umaasa rito ang mga user ng search engine para matukoy kung may kaugnayan ang isang page sa kanilang paghahanap. [Matuto pa](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Walang element na `<title>` ang dokumento"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "May `<title>` na element ang dokumento"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Natatangi dapat ang value ng id attribute para hindi makaligtaan ng mga nakakatulong na teknolohiya ang iba pang instance. [Matuto pa](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Hindi natatangi ang mga attribute na `[id]`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Natatangi ang mga attribute na `[id]` sa page"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Umaasa ang mga user ng screen reader sa mga pamagat ng frame para ilarawan ang mga content ng mga frame. [Matuto pa](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Walang pamagat ang mga element na`<frame>` o `<iframe>`"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "May pamagat ang mga elemento na`<frame>` o `<iframe>`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Kung hindi tutukoy ng lang attribute ang isang page, ipagpapalagay ng screen reader na ang page ay nasa default na wikang pinili ng user noong sine-set up ang screen reader. Kung wala talaga sa default na wika ang page, puwedeng hindi maianunsyo nang tama ng screen reader ang text ng page. [Matuto pa](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Walang attribute na `[lang]` ang element na `<html>`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Ang `<html>` na element ay may attribute na `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ang pagtukoy ng valid na [wika ng BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ay nakakatulong na maianunsyo nang maayos ang text. [Matuto pa](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Walang valid na value ang element na `<html>` para sa attribute nitong `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "May valid na value ang element na `<html>` para sa `[lang]` na attribute nito"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Layunin dapat ng mga nagbibigay-impormasyong element na magkaroon ng maikli at naglalarawang alternatibong text. Puwedeng balewalain ang mga palamuting element sa pamamagitan ng walang lamang kahaliling attribute. [Matuto pa](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Walang attribute na `[alt]` ang mga element ng larawan"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "May mga attribute na `[alt]` ang mga element na larawan"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Kapag gumagamit ng larawan bilang button na `<input>`, makakatulong sa mga user ng screen reader ang pagbibigay ng alternatibong text na maunawaan kung para saan ang button. [Matuto pa](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Walang text na `[alt]` ang mga element na `<input type=\"image\">`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "May text na `[alt]` ang mga element na `<input type=\"image\">`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Tinitiyak ng mga label na maayos na inaanunsyo ang mga kontrol ng form ng mga nakakatulong na teknolohiya, tulad ng mga screen reader. [Matuto pa](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Walang nauugnay na label ang mga element ng form"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "May mga nauugnay na label ang mga element ng form"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Dapat ay walang kasamang element ng data ang isang talahanayang ginagamit para sa mga layunin ng layout, gaya ng th o mga element ng caption o attribute ng buod, dahil puwede itong gumawa ng nakakalitong karanasan para sa mga user ng screen reader. [Matuto pa](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Hindi iniiwasan ng mga pang-presentation na element na `<table>` ang paggamit ng attribute na `<th>`, `<caption>` o `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Iniiwasan ng mga pang-presentation na element na `<table>` ang paggamit ng attribute na `<th>`, `<caption>` o `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Pinapahusay ng text ng link (at alternatibong text para sa mga larawan, kapag ginamit bilang mga link) na nakikita, natatangi, at nafo-focus ang karanasan sa navigation para sa mga user ng screen reader. [Matuto pa](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Walang nakikitang pangalan ang mga link"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "May nakikitang pangalan ang mga link"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "May partikular na paraan ng pag-aanunsyo ng mga listahan ang mga screen reader. Makakatulong sa output ng screen reader ang pagtiyak na maayos ang istruktura ng listahan. [Matuto pa](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Hindi lang naglalaman ang listahan ng mga element na `<li>` at element na sumusuporta sa script (`<script>` at `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Naglalaman lang ang mga listahan ng mga element na `<li>` at element na sumusuporta sa script (`<script>` at `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Kailangang nakapaloob sa parent `<ul>` o `<ol>` ang mga item sa listahan `<li>` para maayos itong maianunsyo ng mga screen reader. [Matuto pa](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Hindi nakapaloob ang mga item sa listahan (`<li>`) sa mga parent element na `<ul>` o `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Nakapaloob ang mga item sa listahan (`<li>`) sa mga pangunahing element na `<ul>` o `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Hindi inaasahan ng mga user na awtomatikong magre-refresh ang isang page, at babalik sa itaas ng page ang focus kapag ginawa ito. Puwede itong gumawa ng nakakainis o nakakalitong karanasan. [Matuto pa](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Gumagamit ng `<meta http-equiv=\"refresh\">` ang dokumento"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Hindi gumagamit ng `<meta http-equiv=\"refresh\">` ang dokumento"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Problema ang pag-disable ng pag-zoom para sa mga user na malabo ang paningin na umaasa sa pag-magnify ng screen para maayos na makita ang mga content ng isang web page. [Matuto pa](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Ginagamit ang `[user-scalable=\"no\"]` sa element na `<meta name=\"viewport\">` o `[maximum-scale]` na attribute na mas mababa sa 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Hindi ginagamit ang `[user-scalable=\"no\"]` sa element na `<meta name=\"viewport\">` at hindi mas mababa sa 5 ang attribute na `[maximum-scale]`."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Hindi makakapag-translate ng hindi text na content ang mga screen reader. Kapag nagdagdag ng alt text sa mga element na `<object>`, matutulungan ang mga screen reader sa pagpaparating ng kahulugan sa mga user. [Matuto pa](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Walang text na `[alt]` ang mga element na `<object>`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "May text na `[alt]` ang mga element na `<object>`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Nagpapahiwatig ng tahasang pagsasaayos ng navigation ang value na mas mataas sa 0. Bagama't kung tutuusin ay valid ito, madalas itong nagdudulot ng mga nakakainis na karanasan para sa mga user na umaasa sa mga nakakatulong na teknolohiya. [Matuto pa](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Ang ilang element ay may value ng `[tabindex]` na mas mataas sa 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Walang element na may value na `[tabindex]` na mas mataas sa 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "May mga feature ang mga screen reader na mas nagpapadali ng pag-navigate sa mga talahanayan. Kapag tiniyak na ang mga cell na `<td>` na gumagamit sa attribute na `[headers]` ay tumutukoy lang sa iba pang cell sa talahanayang ding iyon, puwedeng mapaganda ang karanasan para sa mga user ng screen reader. [Matuto pa](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Tumutukoy sa isang element na `id` na hindi makikita sa parehong talahanayan ang mga cell sa element na `<table>` na gumagamit ng attribute na `[headers]`."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Tumutukoy sa iba pang cell sa kaparehong talahanayan ang mga cell sa isang element na `<table>` na gumagamit ng attribute na `[headers]`."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "May mga feature ang mga screen reader na mas nagpapadali ng pag-navigate sa mga talahanayan. Kapag tiniyak na ang mga header ng talahanayan ay tumutukoy sa ilang hanay ng mga cell, puwedeng mapahusay ang karanasan para sa mga user ng screen reader. [Matuto pa](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Ang mga element na `<th>` at element na may `[role=\"columnheader\"/\"rowheader\"]` ay walang cell ng data na inilalarawan ng mga ito."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "May mga inilalarawang cell ng data ang mga element na `<th>` at element na may `[role=\"columnheader\"/\"rowheader\"]`."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ang pagtukoy ng valid na [wika ng BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) sa mga element ay nakakatulong sa pagtiyak na tama ang pagbigkas ng screen reader sa text. [Matuto pa](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Walang valid na value ang mga attribute na `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "May valid na value ang mga attribute na `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Kapag nagbigay ng caption ang isang video, mas madaling maa-access ng mga user na bingi at may problema sa pandinig ang impormasyon nito. [Matuto pa](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Hindi naglalaman ng element na `<track>` na may `[kind=\"captions\"]` ang mga element na `<video>`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Naglalaman ng element na `<track>` na may `[kind=\"captions\"]` ang mga element na `<video>`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Nagbibigay ang mga audio na paglalarawan ng may kaugnayang impormasyon para sa mga video na hindi magagawa ng dialogue, gaya ng mga expression ng mukha at eksena. [Matuto pa](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Hindi naglalaman ng element na `<track>` na may `[kind=\"description\"]` ang mga element na `<video>`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Naglalaman ng element na `<track>` na may `[kind=\"description\"]` ang mga element na `<video>`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Para sa magandang hitsura sa iOS kapag nagdagdag ang mga user ng progressive web app sa home screen, tumukoy ng `apple-touch-icon`. Dapat itong nakadirekta sa isang hindi transparent na kuwadradong 192px (o 180px) PNG. [Matuto Pa](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Hindi nagbibigay ng valid na `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Hindi napapanahon ang `apple-touch-icon-precomposed`; mas gusto ang `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Nagbibigay ng valid na `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Nagkaroon ng negatibong epekto ang mga extension ng Chrome sa performance ng pag-load ng page na ito. Subukang i-audit ang page sa incognito mode o mula sa isang profile sa Chrome nang walang extension."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Pagsusuri ng Script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Pag-parse ng Script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Kabuuang Oras ng CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Pag-isipang bawasan ang oras na ginugugol sa pag-parse, pag-compile, at pagpapagana ng JS. Puwedeng mapansin mong nakakatulong dito ang paghahatid ng mas maliliit na payload ng JS. [Matuto pa](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Pabilisin ang pagpapagana ng JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Bilis ng pagpapagana ng JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Hindi mahusay ang malalaking GIF sa paghahatid ng animated na content. Pag-isipang gumamit ng mga MPEG4/WebM na video para sa mga animation at PNG/WebP para sa mga static na larawan sa halip na GIF para makatipid ng mga byte ng network. [Matuto pa](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Gumamit ng mga format ng video para sa animated na content"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Pag-isipang i-lazy load ang mga larawang wala sa screen at nakatago kapag tapos nang mag-load ang lahat ng mahalagang resource para mapabilis ang oras bago maging interactive. [Matuto pa](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Ipagpaliban ang mga larawang wala sa screen"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Bina-block ng mga resource ang first paint ng iyong page. Pag-isipang ihatid ang mahalagang JS/CSS inline at ipagpaliban ang lahat ng hindi mahalagang JS/istilo. [Matuto pa](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Alisin ang mga resource na nagba-block ng pag-render"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Napapagastos ang mga user sa malalaking payload ng network, at malaki ang kaugnayan ng mga ito sa matagal na pag-load. [Matuto pa](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Ang kabuuang laki ay {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Iwasan ang malalaking payload ng network"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Umiiwas sa malalaking payload ng network"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Puwedeng bawasan ng pagpapaliit ng mga file ng CSS ang laki ng payload ng network. [Matuto pa](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Paliitin ang CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Puwedeng bawasan ng pagpapaliit ng mga file ng JavaScript ang laki ng payload at oras ng pag-parse ng script. [Matuto pa](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Paliitin ang JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Alisin ang mga hindi na gumaganang panuntunan sa mga stylesheet at ipagpaliban ang pag-load ng CSS na hindi ginagamit para sa content sa itaas ng fold para mabawasan ang mga hindi kinakailangang byte na nakokonsumo ng aktibidad sa network. [Matuto pa](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Alisin ang hindi ginagamit na CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Alisin ang hindi nagamit na JavaScript para mabawasan ang mga byte na nakokonsumo ng aktibidad sa network."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Alisin ang hindi nagamit na JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Puwedeng mapabilis ng mahabang lifetime ng cache ang mga umuulit na pagbisita sa iyong page. [Matuto pa](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Nakakita ng 1 resource}one{Nakakita ng # resource}other{Nakakita ng # na resource}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Maghatid ng mga static na asset nang may mahusay na patakaran sa cache"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Gumagamit ng mahusay na patakaran sa cache sa mga static na asset"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Mas mabilis mag-load ang mga na-optimize na larawan at mas kaunti ang nakokonsumong cellular data ng mga ito. [Matuto pa](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Mahusay na mag-encode ng mga larawan"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Maghatid ng mga larawang naaangkop ang laki para makatipid sa cellular data at mapabilis ang pag-load. [Matuto pa](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Iangkop ang laki ng mga larawan"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Dapat maghatid ang mga text-based na resource nang may compression (gzip, deflate, o brotli) para mabawasan ang kabuuang mga byte ng network. [Matuto pa](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "I-enable ang compression ng text"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Kadalasan, mas mahusay ang pag-compress ng mga format ng larawan gaya ng JPEG 2000, JPEG XR, at WebP kaysa sa pag-compress ng PNG o JPEG, kaya mas mabilis ang pag-download at mas kaunti ang nakokonsumong data. [Matuto pa](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Maghatid ng mga larawan sa mga makabagong format"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Kung hindi tumutugma ang lapad ng content ng iyong app sa lapad ng viewport, puwedeng hindi ma-optimize ang app mo para sa mga screen ng mobile. [Matuto pa](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Hindi tumutugma ang laki ng viewport na {innerWidth}px sa laki ng window na {outerWidth}px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Hindi tama ang laki ng content para sa viewport"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Tama ang laki ng content para sa viewport"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Ipinapakita sa iyo ng Mga Chain ng Mahahalagang Kahilingan kung anong mga resource ang nilo-load nang may mataas na priyoridad. Pag-isipang paikliin ang mga chain, paliitin ang mga dina-download na resource, o ipagpaliban ang pag-download ng mga hindi kinakailangang resource para mapabilis ang pag-load ng page. [Matuto pa](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Nakakita ng 1 chain}one{Nakakita ng # chain}other{Nakakita ng # na chain}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "I-minimize ang Lalim ng Mahahalagang Kahilingan"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Paghinto sa Paggamit / Babala"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linya"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Aalisin sa browser ang mga hindi na ginagamit na API sa paglaon. [Matuto pa](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{May nakitang 1 babala}one{May nakitang # babala}other{May nakitang # na babala}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Gumagamit ng mga hindi na ginagamit na API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Iniiwasan ang mga hindi na ginagamit na API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Hindi na ginagamit ang Cache ng Application. [Matuto pa](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Nakita ang \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Gumagamit ng Cache ng Application"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Iniiwasan ang Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Ang pagtukoy ng doctype ay pumipigil sa browser na lumipat sa quirks-mode. [Matuto pa](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Ang pangalan ng doctype ay dapat ang nasa maliliit na titik na string na `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dapat maglaman ng doctype ang dokumento"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Walang lamang string ang inaasahang publicId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Walang lamang string ang inaasahang systemId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Walang HTML na doctype ang page, at dahil dito, na-trigger nito ang quirks-mode"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "May HTML na doctype ang page"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Istatistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Value"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Inirerekomenda ng mga engineer ng browser ang mga page na naglalaman ng mas kaunti sa ~1,500 element ng DOM. Ang pinakamainam ay isang lalim ng tree na < 32 element at mas kaunti sa 60 child/parent na element. Kapag malaki ang DOM, puwedeng tumaas ang paggamit ng memory, magdulot ng mas mahahabang [pagkalkula ng istilo](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), at makagawa ng mamahaling [mga reflow ng layout](https://developers.google.com/speed/articles/reflow). [Matuto pa](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}one{# element}other{# na element}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Umiwas sa masyadong malaking DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximum na Lalim ng DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Kabuuang Element ng DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximum na Mga Child na Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Umiiwas sa masyadong malaking DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Idagdag ang `rel=\"noopener\"` o `rel=\"noreferrer\"` sa anumang external na link para pahusayin ang performance at pigilan ang mga kahinaan sa seguridad. [Matuto pa](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Hindi ligtas ang mga link sa mga cross-origin na destinasyon"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Ligtas ang mga link sa mga cross-origin na destinasyon"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Hindi matukoy ang destinasyon para sa anchor na ({anchorHTML}). Kung hindi ginagamit bilang hyperlink, pag-isipang alisin ang target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Walang tiwala o nalilito ang mga user sa mga site na humihiling ng kanilang lokasyon nang walang konteksto. Sa halip ay pag-isipang iugnay ang kahilingan sa pagkilos ng user. [Matuto pa](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Humihiling ng pahintulot sa geolocation sa pag-load ng page"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Iniiwasan ang paghiling ng pahintulot sa geolocation sa pag-load ng page"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Bersyon"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Lahat ng front-end na library ng JavaScript na natukoy sa page. [Matuto pa](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Natukoy na mga library ng JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Para sa mga user na may mabagal na koneksyon, puwedeng maantala ang pag-load ng page dahil sa mga external na script na dynamic na inilagay sa pamamagitan ng `document.write()`. [Matuto pa](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Gumagamit ng `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Umiiwas sa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Pinakamataas na Kalalaan"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bersyon ng Library"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Bilang ng Kahinaan"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Puwedeng maglaman ng mga kilalang kahinaan sa seguridad ang ilang script ng third party na madaling natutukoy at nasasamantala ng mga nang-aatake. [Matuto pa](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kahinaan ang natukoy}one{# kahinaan ang natukoy}other{# na kahinaan ang natukoy}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "May mga kasamang front-end na library ng JavaScript na may mga kilalang kahinaan sa seguridad"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Mataas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Mababa"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Katamtaman"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Umiiwas sa mga front-end na library ng JavaScript na may mga kilalang kahinaan sa seguridad"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Walang tiwala o nalilito ang mga user sa mga site na humihiling na magpadala ng mga notification nang walang konteksto. Sa halip ay pag-isipang iugnay ang kahilingan sa mga galaw ng user. [Matuto pa](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Humihiling ng pahintulot sa notification sa pag-load ng page"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Iniiwasan ang paghiling ng pahintulot sa notification sa pag-load ng page"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Mga Hindi Nakapasang Element"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Pinapahina ng paghadlang sa pag-paste ng password ang magandang patakarang panseguridad. [Matuto pa](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Pinipigilan ang mga user na mag-paste sa mga field ng password"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Pinapayagan ang mga user na mag-paste sa mga field ng password"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Nag-aalok ang HTTP/2 ng mas maraming benepisyo kaysa sa HTTP/1.1, kasama ang mga binary header, multiplexing, at server push. [Matuto pa](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kahilingan ang hindi naihatid sa pamamagitan ng HTTP/2}one{# kahilingan ang hindi naihatid sa pamamagitan ng HTTP/2}other{# na kahilingan ang hindi naihatid sa pamamagitan ng HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Hindi gumagamit ng HTTP/2 para sa lahat ng resource nito"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Hindi gumagamit ng HTTP/2 para sa mga sarili nitong resource"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Pag-isipang markahan ang iyong pan-detect ng event sa pagpindot at wheel bilang `passive` para mapahusay ang performance sa pag-scroll ng iyong page. [Matuto pa](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Hindi gumagamit ng mga passive na listener para pahusayin ang performance sa pag-scroll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Gumagamit ng mga passive na listener para pahusayin ang performance sa pag-scroll"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Paglalarawan"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Nagsasaad ng mga hindi naresolbang problema ang mga error na naka-log sa console. Puwedeng manggaling ang mga ito sa mga hindi nagawang kahilingan sa network at iba pang alalahanin sa browser. [Matuto pa](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Na-log sa console ang mga error sa browser"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Walang naka-log na mga error sa browser sa console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Gamitin ang feature na font-display ng CSS para matiyak na nakikita ng user ang text habang nilo-load ang mga webfont. [Matuto pa](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Tiyaking patuloy na nakikita ang text sa pag-load ng webfont"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Patuloy na nakikita ang lahat ng text sa pag-load ng webfont"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Hindi awtomatikong nasuri ng Lighthouse ang value na font-display para sa sumusunod na URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Aspect Ratio (Aktwal)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Aspect Ratio (Ipinakita)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Dapat na tumugma ang mga dimensyon ng display ng larawan sa natural na aspect ratio. [Matuto pa](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Ipinapakita ang mga larawang may maling aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Ipinapakita ang mga larawang may tamang aspect ratio"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Invalid ang laki ng larawan ng impormasyon {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Puwedeng proactive na i-prompt ng mga browser ang mga user na idagdag ang iyong app sa kanilang homescreen, na puwedeng magresulta sa mas maraming pakikipag-ugnayan. [Matuto pa](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Hindi natutugunan ng manifest ng web app ang mga kinakailangan sa pag-install"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Natutugunan ng manifest ng web app ang mga kinakailangan sa pag-install"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Hindi secure na URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Dapat protektahan gamit ang HTTPS ang lahat ng site, kahit ang mga hindi nangangasiwa ng sensitibong data. Pinipigilan ng HTTPS ang mga nanghihimasok na makialam o tahimik na makinig sa mga pakikipag-ugnayan sa pagitan ng iyong app at mga user, at isa itong prerequisite para sa HTTP/2 at maraming bagong API ng web platform. [Matuto pa](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 hindi secure na kahilingan ang nakita}one{# hindi secure na kahilingan ang nakita}other{# na hindi secure na kahilingan ang nakita}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Hindi gumagamit ng HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Gumagamit ng HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Kapag mabilis ang pag-load ng page sa cellular network, nagkakaroon ng magandang karanasan ng user sa mobile. [Matuto pa](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactive sa {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactive sa naka-simulate na mobile network sa loob ng {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Masyadong mabagal mag-load ang iyong page at hindi ito interactive sa loob ng 10 segundo. Tingnan ang mga pagkakataon at diagnostic sa seksyong \"Performance\" para malaman kung paano magpahusay."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Hindi sapat ang bilis ng pag-load ng page sa mga mobile network"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Sapat ang bilis ng pag-load ng page sa mga mobile network"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorya"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Pag-isipang bawasan ang oras na ginugugol sa pag-parse, pag-compile, at pagpapagana ng JS. Posibleng mapansin mong nakakatulong dito ang paghahatid ng mas maliliit na payload ng JS. [Matuto pa](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Bawasan ang gawain sa pangunahing thread"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Binabawasan ang gawain sa pangunahing thread"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Para maabot ang pinakamaraming user, dapat gumana ang mga site sa bawat pangunahing browser. [Matuto pa](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Gumagana ang site sa iba't ibang browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Tiyaking puwedeng i-deep link ang mga indibidwal na page sa pamamagitan ng URL at natatangi ang mga URL para sa pagbabahagi sa social media. [Matuto pa](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "May URL ang bawat page"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Mabilis dapat ang mga transition habang nagta-tap ka, kahit sa mabagal na network. Ang karanasang ito ay susi sa pagtingin ng user sa performance. [Matuto pa](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Mukhang hindi nagba-block sa network ang mga transition ng page"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Ang Tinantyang Latency ng Input ay isang pagtatantya ng bilis ng pagtugon ng iyong app sa input ng user, na nasa millisecond, sa pinakaabalang 5 segundong palugit ng pag-load ng page. Kung mas mataas kaysa sa 50 ms ang iyong latency, puwedeng ituring ng mga user na mabagal ang app mo. [Matuto pa](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Tinatayang Latency ng Input"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Minamarkahan ng First Contentful Paint ang tagal bago ma-paint ang unang text o larawan. [Matuto pa](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Minamarkahan ng First CPU Idle ang unang beses kung kailan hindi abala ang pangunahing thread ng page at puwede itong mangasiwa ng input. [Matuto pa](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "First CPU Idle"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Sinusukat ng First Meaningful Paint ang bilis ng pagpapakita ng pangunahing content ng isang page. [Matuto pa](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Ang oras bago maging interactive ay ang haba ng oras na inaabot bago maging ganap na interactive ang page. [Matuto pa](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Time to Interactive"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Ang maximum na potensyal na First Input Delay na puwedeng maranasan ng iyong mga user ay ang tagal, na nasa millisecond, ng pinakamahabang gawain. [Matuto pa](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max na Potensyal na First Input Delay"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Ipinapakita ng Speed Index ang bilis ng nakikitang pag-populate ng mga content ng isang page. [Matuto pa](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Speed Index"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Kabuuan ng lahat ng yugto ng panahon sa pagitan ng FCP at Oras bago maging Interactive, kapag lumampas ang haba ng gawain sa 50ms, ipinahayag sa milliseconds."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Kabuuang Oras ng Pag-block"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Malaki ang epekto ng mga round trip time (RTT) ng network sa performance. Kung mataas ang RTT sa isang pinagmulan, isa itong palatandaan na mapapahusay ng mga server na malapit sa user ang performance. [Matuto pa](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Mga Round Trip Time ng Network"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Puwedeng makaapekto sa performance sa web ang mga latency ng server. Kung mataas ang latency ng server ng isang pinagmulan, ito ay palatandaang na-overload ang server o hindi mahusay ang performance nito sa backend. [Matuto pa](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Mga Latency sa Backend ng Server"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Ine-enable ng isang service worker ang iyong web app para maging maaasahan sa mga pabagu-bagong kundisyon ng network. [Matuto pa](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "Hindi tumutugon ang `start_url` gamit ang 200 kapag offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "Tumutugon ang `start_url` gamit ang 200 kapag offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Hindi mabasa ng Lighthouse ang `start_url` na galing sa manifest. Dahil dito, ipinagpapalagay na `start_url` ang URL ng dokumento. Mensahe ng error: '{manifestWarning}.'"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Lampas sa Badyet"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Panatilihin ang dami at laki ng mga kahilingan sa network sa ilalim ng mga target na itinakda ng ibinigay na badyet sa performance. [Matuto pa](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 kahilingan}one{# kahilingan}other{# na kahilingan}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Badyet sa performance"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Kung na-set up mo na ang HTTPS, tiyaking ire-redirect mo sa HTTPS ang lahat ng trapiko sa HTTP para ma-enable ang mga ligtas na feature sa web para sa lahat ng iyong user. [Matuto pa](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Hindi nire-redirect sa HTTPS ang trapiko sa HTTP"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Nire-redirect sa HTTPS ang trapiko sa HTTP"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Nagpapasimula ang mga pag-redirect ng mga karagdagang pagkaantala bago ma-load ang page. [Matuto pa](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Iwasan ang mga pag-redirect sa maraming page"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Para magtakda ng mga badyet para sa dami at laki ng mga resource ng page, magdagdag ng budget.json na file. [Matuto pa](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 kahilingan • {byteCount, number, bytes} KB}one{# kahilingan • {byteCount, number, bytes} KB}other{# na kahilingan • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Panatilihing mababa ang mga bilang ng kahilingan at maliit ang mga paglipat"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Iminumungkahi ng mga canonical na link kung aling URL ang ipapakita sa mga resulta ng paghahanap. [Matuto pa](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Maraming URL ang hindi magkakatugma ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Tumuturo sa ibang domain ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Invalid na URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Tumuturo sa ibang lokasyon ng `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relatibong URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Tumuturo sa root URL ng domain (ang homepage), sa halip na sa katumbas na page ng content"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Walang valid na `rel=canonical` ang dokumento"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "May valid na `rel=canonical` ang dokumento"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Ang mga laki ng font na mas mababa sa 12px ay masyadong maliit para mabasa at kinakailangan ng mga bisita sa mobile na “mag-pinch para mag-zoom in” para mabasa ito. Subukang gawing ≥12px ang >60% ng text sa page. [Matuto pa](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} nababasang text"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Hindi nababasa ang text dahil walang viewport meta tag na naka-optimize para sa mga screen ng mobile."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Masyadong maliit ang {decimalProportion, number, extendedPercent} ng text (batay sa sample na {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Hindi gumagamit ng mga nababasang laki ng font ang dokumento"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Gumagamit ng mga nababasang laki ng font ang dokumento"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Sinasabi ng mga link na hreflang sa mga search engine kung anong bersyon ng isang page ang dapat ilista ng mga ito sa mga resulta ng paghahanap para sa isang partikular na wika o rehiyon. [Matuto pa](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Walang valid na `hreflang` ang dokumento"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "May valid na `hreflang` ang dokumento"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Puwedeng hindi ma-index nang maayos ang mga page na may mga hindi matagumpay na status code ng HTTP. [Matuto pa](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Hindi matagumpay ang status code ng HTML ng page"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Matagumpay ang status code ng HTTP ng page"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Hindi maisasama ng mga search engine ang iyong mga page sa mga resulta ng paghahanap kung walang pahintulot ang mga ito na i-crawl ang mga iyon. [Matuto pa](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Naka-block ang page mula sa pag-index"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Hindi naka-block ang page mula sa pag-index"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Nakakatulong ang naglalarawang text ng link sa mga search engine na maunawaan ang iyong content. [Matuto pa](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{May nakitang 1 link}one{May nakitang # link}other{May nakitang # na link}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Walang naglalarawang text ang mga link"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "May naglalarawang text ang mga link"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Patakbuhin ang [Tool sa Pag-test ng Structured Data](https://search.google.com/structured-data/testing-tool/) at ang [Structured Data Linter](http://linter.structured-data.org/) para i-validate ang structured data. [Matuto pa](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Valid ang structured data"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Puwedeng magsama ng mga paglalarawan ng meta sa mga resulta ng paghahanap para makapagbigay ng maikling buod ng content ng page. [Matuto pa](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Walang laman ang text ng paglalarawan."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Walang paglalarawan ng meta ang dokumento"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "May paglalarawan ng meta ang dokumento"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Hindi nai-index ng mga search engine ang content ng plugin, at maraming device ang naglilimita sa mga plugin o hindi sumusuporta sa mga ito. [Matuto pa](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Gumagamit ng mga plugin ang dokumento"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Iniiwasan ng dokumento ang mga plugin"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Kung sira ang iyong robots.txt, puwedeng hindi maunawaan ng mga crawler kung paano mo gustong ma-crawl o ma-index ang iyong website. [Matuto pa](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Ang kahilingan para sa robots.txt ay nagbalik ng status ng HTTP na: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{May nakitang 1 error}one{May nakitang # error}other{May nakitang # na error}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Hindi nakapag-download ng robots.txt file ang Lighthouse"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Hindi valid ang robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Valid ang robots.txt"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Sapat dapat ang laki (48x48px) at mayroon dapat sapat na espasyo sa paligid ang mga interactive na element gaya ng mga button at link, para madaling ma-tap ang mga ito nang hindi nag-o-overlap sa iba pang element. [Matuto pa](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} ng mga target sa pag-tap ang may angkop na laki"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Masyadong maliit ang mga target ng pag-tap dahil walang viewport meta tag na naka-optimize para sa mga screen ng mobile"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Hindi angkop ang laki ng mga target ng pag-tap"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Nag-o-overlap na Target"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Target ng Pag-tap"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Angkop ang laki ng mga target ng pag-tap"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Ang service worker ay ang teknolohiyang nagbibigay-daan sa iyong app na gumamit ng maraming feature ng Progressive Web App, gaya ng offline, pagdaragdag sa homescreen, at mga push notification. [Matuto pa](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Kinokontrol ng service worker ang page na ito, gayunpaman, walang nakitang `start_url` dahil hindi na-parse ang manifest bilang valid na JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Kinokontrol ng service worker ang page na ito, gayunpaman, wala ang `start_url` ({startUrl}) sa saklaw ng service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Kinokontrol ng service worker ang page na ito, gayunpaman, walang nakitang `start_url` dahil walang nakuhang manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "May isa o higit pang service worker ang pinagmulang ito, gayunpaman, wala sa saklaw ang page ({pageUrl})."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Hindi nagrerehistro ng service worker na kumokontrol sa page at `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Nagrerehistro ng service worker na kumokontrol sa page at `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Tinitiyak ng splash screen na may tema na magkakaroon ng karanasang may mataas na kalidad kapag inilunsad ng mga user ang iyong app sa kanilang mga homescreen. [Matuto pa](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Hindi naka-configure para sa custom na splash screen"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Naka-configure para sa custom na splash screen"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Puwedeng lagyan ng tema ang address bar ng browser para tumugma sa iyong site. [Matuto pa](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Hindi nagtatakda ng kulay ng tema para sa address bar."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Nagtatakda ng kulay ng tema para sa address bar."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Oras ng Pag-block ng Pangunahing Thread"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Third-Party"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Puwedeng lubos na makaapekto ang code ng third party sa performance ng pag-load. Limitahan ang bilang ng paulit-ulit na mga third-party na provider at subukang i-load ang code ng third party pagkatapos ng pangunahing pag-load ng iyong page. [Matuto pa](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Na-block ng code ng third party ang pangunahing thread sa loob ng {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Bawasan ang epekto ng code ng third party"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Paggamit ng Third Party"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Tinutukoy ng Time To First Byte ang tagal bago makapagpadala ng tugon ang iyong server. [Matuto pa](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Inabot nang {timeInMs, number, milliseconds} ms ang root na dokumento"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Pabilisin ang pagtugon ng server (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Masyadong matagal ang pagtugon ng server (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Tagal"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Oras ng Pagsisimula"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Uri"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Pag-isipang gumamit ng User Timing API sa iyong app para sukatin ang makatotohanang performance ng app mo sa mahahalagang karanasan ng user. [Matuto pa](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 timing ng user}one{# timing ng user}other{# na timing ng user}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Mga marka at sukat ng User Timing"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "May nakitang preconnect na <link> para sa \"{securityOrigin}\" pero hindi ito ginamit ng browser. Tingnan kung ginagamit mo nang maayos ang attribute na `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Pag-isipang magdagdag ng mga hint ng resource na `preconnect` o `dns-prefetch` para magtakda ng mga paunang koneksyon sa mahahalagang third-party na pinagmulan. [Matuto pa](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Mag-preconnect sa mga kinakailangang origin"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "May nakitang preload na <link> para sa \"{preloadURL}\" pero hindi ito ginamit ng browser. Tingnan kung ginagamit mo nang maayos ang attribute na `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Pag-isipang gumamit ng `<link rel=preload>` para mabigyang-priyoridad ang pagkuha ng mga resource na kasalukuyang hinihiling sa huling bahagi ng pag-load ng page. [Matuto pa](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "I-preload ang mahahalagang kahilingan"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Magdagdag ng tag na `<meta name=\"viewport\">` para i-optimize ang iyong app para sa mga screen ng mobile. [Matuto pa](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Walang nahanap na tag na `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Walang tag na `<meta name=\"viewport\">` na may `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "May tag na `<meta name=\"viewport\">` na may `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Dapat magpakita ng ilang content ang iyong app kapag naka-disable ang JavaScript, kahit isang babala lang sa user na kinakailangan ang Javascript para magamit ang app. [Matuto pa](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Dapat mag-render ng ilang content ang nilalaman ng page kung hindi available ang mga script nito."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Hindi nagbibigay ng fallback na content kapag hindi available ang JavaScript"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Naglalaman ng ilang content kapag hindi available ang JavaScript"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Kung bumubuo ka ng Progressive Web App, pag-isipang gumamit ng service worker para gumana ang iyong app offline. [Matuto pa](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Hindi tumutugon ang kasalukuyang page gamit ang 200 kapag offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Tumutugon ang kasalukuyang page gamit ang 200 kapag offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Puwedeng hindi naglo-load ang page offline dahil na-redirect ang iyong pansubok na URL ({requested}) sa \"{final}\". Subukang suriin ang pangalawang URL nang direkta."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Mga pagkakataon ito na pahusayin ang paggamit ng ARIA sa iyong application na maaaring mapahusay ang karanasan para sa mga user ng nakakatulong na teknolohiya, tulad ng screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Ito ay mga pagkakataong magbigay ng alternatibong content para sa audio at video. Puwede nitong mapaganda ang karanasan para sa mga user na may mga problema sa paningin o pandinig."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio at video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Hina-highlight ng mga item na ito ang mga karaniwang pinakamahusay na kagawian sa pagiging accessible."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Pinakamahuhusay na kagawian"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Hina-highlight ng mga pagsusuring ito ang mga pagkakataong [gawing mas accessible ng iyong web app](https://developers.google.com/web/fundamentals/accessibility). Isang subset lang ng mga isyu sa pagiging accessible ang awtomatikong matutukoy kaya hinihikayat din ang manual na pagsusuri."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Tinutugunan ng mga item na ito ang mga bahaging hindi masasakop ng naka-automate na tool sa pagsusuri. Matuto pa sa aming gabay sa [pagsasagawa ng pagsusuri sa pagiging accessible](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Pagiging accessible"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Mga pagkakataon ito na pahusayin ang pagiging nababasa ng iyong content."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Mga pagkakataon ito na pahusayin ang pagsasalin ng mga user sa iyong content sa iba't ibang lokal."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Pag-internationalize at pag-localize"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Mga pagkakataon ito ng pahusayin ang mga semantic ng mga kontrol sa iyong application. Maaari nitong pahusayin ang karanasan para sa mga user ng nakakatulong na teknolohiya, tulad ng screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Mga pangalan at label"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ito ay mga pagkakataong pahusayin ang pag-navigate gamit ang keyboard sa iyong application."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Ito ay mga pagkakataon para pagandahin ang karanasan ng pagbabasa ng data na nasa talahanayan o listahan gamit ang nakakatulong na teknolohiya, gaya ng screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Mga talahanayan at listahan"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Pinakamahuhusay na Kagawian"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Nagtatakda ng mga pamantayan para sa performance ng iyong site ang mga badyet ng performance."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Mga Badyet"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Higit pang impormasyon tungkol sa performance ng iyong application. Ang mga numerong ito ay hindi [direktang makakaapekto ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) sa score sa Performance."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Mga Diagnostic"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Ang pinakamahalagang aspeto ng performance ay ang bilis ng pag-render ng mga pixel sa screen. Mahahalagang sukatan: First Contentful Paint, First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Mga Pagpapahusay sa First Paint"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Puwedeng makatulong ang mga suhestyon na ito na mapabilis ang pag-load ng iyong page. Hindi [direktang nakakaapekto](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) ang mga ito sa score sa Performance."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Mga Pagkakataon"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Mga Sukatan"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Pagandahin ang pangkalahatang karanasan sa pag-load para bumilis ang pagtugon ng page at magamit ito kaagad. Mahahalagang sukatan: Time to Interactive, Speed Index"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Mga Pangkalahatang Pagpapahusay"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performance"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Vina-validate ng mga pagsusuring ito ang mga aspeto ng isang Progressive Web App. [Matuto pa](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Kinakailangan ang mga pagsusuring ito ng baseline na [Checklist ng PWA ](https://developers.google.com/web/progressive-web-apps/checklist) pero hindi ito awtomatikong sinusuri ng Lighthouse. Hindi nakakaapekto ang mga ito sa iyong score pero mahalagang ma-verify mo ang mga ito nang manual."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Mabilis at maaasahan"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Nai-install"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Na-optimize ang PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Tinitiyak ng mga pagsusuring ito na naka-optimize ang iyong page para sa ranking ng mga resulta ng search engine. May mga karagdagang salik na hindi sinusuri ng Lighthouse na puwedeng makaapekto sa iyong ranking sa paghahanap. [Matuto pa](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Paganahin ang mga karagdagang validator na ito sa iyong site para tingnan ang karagdagang pinakamahuhusay na kagawian sa SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "I-format ang iyong HTML sa paraang nag-e-enable sa mga crawler na mas maunawaan ang content ng app mo."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Pinakamahuhusay na Kagawian sa Content"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Para lumabas sa mga resulta ng paghahanap, kailangan ng mga crawler ng access sa iyong app."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Pag-crawl at Pag-index"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Tiyaking pang-mobile ang iyong mga page para hindi na kailangang mag-pinch o mag-zoom in ng mga user para mabasa ang mga page ng content. [Matuto pa](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Pang-mobile"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL ng Cache"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokasyon"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Pangalan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Mga Kahilingan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Uri ng Resource"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Laki"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Oras na Ginugol"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Laki ng Paglipat"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Puwedeng Matipid"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Puwedeng Matipid"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Puwedeng makatipid ng {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Puwedeng makatipid ng {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokumento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Larawan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Iba pa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Third-party"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Kabuuan"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Nagkaroon ng problema sa pag-record ng trace sa pag-load ng iyong page. Paganahin ulit ang Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Nag-timeout habang naghihintay para sa paunang koneksyon sa Protocol ng Debugger."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Hindi nangolekta ang Chrome ng anumang screenshot habang nilo-load ang page. Pakitiyak na may nakikitang content sa page, at pagkatapos ay subukang paganahin ulit ang Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Hindi malutas ng mga DNS server ang ibinigay na domain."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Ang kinakailangang gatherer na {artifactName} ay nagkaroon ng error: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Nagkaroon ng internal na error sa Chrome. Paki-restart ang Chrome at subukang muling paganahin ang Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Hindi tumakbo ang kinakailangang gatherer na {artifactName}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Hindi na-load nang maayos ng Lighthouse ang page na hiniling mo. Tiyaking tamang URL ang sinusubukan mo at tumutugon nang maayos ang server sa lahat ng kahilingan."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Hindi na-load nang maayos ng Lighthouse ang URL na hiniling mo dahil huminto sa pagtugon ang page."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Walang valid na panseguridad na certificate ang URL na ibinigay mo. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Pinigilan ng Chrome ang pag-load ng page gamit ang interstitial. Tiyaking tamang URL ang sinusubukan mo at tumutugon nang maayos ang server sa lahat ng kahilingan."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Hindi na-load nang maayos ng Lighthouse ang page na hiniling mo. Tiyaking tamang URL ang sinusubukan mo at tumutugon nang maayos ang server sa lahat ng kahilingan. (Mga Detalye: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Hindi na-load nang maayos ng Lighthouse ang page na hiniling mo. Tiyaking tamang URL ang sinusubukan mo at tumutugon nang maayos ang server sa lahat ng kahilingan. (Status code: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Masyadong matagal na na-load ang iyong page. Pakisunod ang mga pagkakataon sa ulat para mabawasan ang tagal ng pag-load ng iyong page, at pagkatapos ay paganahin ulit ang Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Lumampas na sa nakalaang oras ang paghihintay ng tugon ng DevTools protocol. (Pamamaraan: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Lumampas na sa nakalaang panahon ang pag-fetch ng content ng resource"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Mukhang invalid ang URL na ibinigay mo."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Ipakita ang mga pag-audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Unang Navigation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximum na latency ng critical path:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Nagka-error!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Error sa ulat: walang impormasyon sa pag-audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Data ng Lab"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Ang pagsusuri ng [Lighthouse](https://developers.google.com/web/tools/lighthouse/) ng kasalukuyang page sa isang na-emulate na mobile network. Tinantya at puwedeng mag-iba ang mga value."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Mga karagdagang item na manual na susuriin"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Hindi naaangkop"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Pagkakataon"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Tinatayang Matitipid"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Mga pumasang pag-audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "I-collapse ang snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "I-expand ang snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Ipakita ang mga resource ng 3rd party"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "May mga isyung nakakaapekto sa pagpapatakbong ito ng Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Tinantya at puwedeng mag-iba ang mga value. [Batay lang sa mga sukatang ito ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) ang score sa performance."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Pumasa sa mga pag-audit ngunit may mga babala"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Mga Babala: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Pag-isipang i-upload ang iyong GIF sa isang serbisyo kung saan gagawin itong available para i-embed bilang HTML5 video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Mag-install ng [lazy-load na plugin sa WordPress](https://wordpress.org/plugins/search/lazy+load/) na nagbibigay ng kakayahang ipagpaliban ang anumang offscreen na larawan, o lumipat sa isang temang nagbibigay ng functionality. Pag-isipan ding gamiting [ang AMP na plugin](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "May ilang plugin sa WordPress na makakatulong sa iyong [i-inline ang mahahalagang asset](https://wordpress.org/plugins/search/critical+css/) o [ipagpaliban ang hindi masyadong mahahalagang resource](https://wordpress.org/plugins/search/defer+css+javascript/). Tandaang puwedeng makasira sa mga feature ng iyong tema o mga plugin ang mga pag-optimize na mula sa mga plugin na ito, kaya malamang na kakailanganin mong gumawa ng mga pagbabago sa code."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Nakakaapekto ang mga tema, plugin, at detalye ng server sa oras ng pagtugon ng server. Pag-isipang maghanap ng mas naka-optimize na tema, maingat na pumili ng plugin sa pag-optimize, at/o i-upgrade ang iyong server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Pag-isipang magpakita ng mga sipi sa iyong mga listahan ng post (hal. sa pamamagitan ng tag na higit pa), bawasan ang bilang ng post na ipinapakita sa isang page, hatiin ang mahahaba mong post sa maraming page, o gumamit ng plugin sa mga lazy-load na komento."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Puwedeng pabilisin ng ilang [plugin sa WordPress](https://wordpress.org/plugins/search/minify+css/) ang iyong site sa pamamagitan ng pagsasama-sama, pagpapaliit, at pagko-compress ng mga istilo mo. Puwede ka ring gumamit ng proseso ng pagbuo para gawin ang pagpapaliit na ito nang mas maaga kung posible."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Puwedeng pabilisin ng ilang [plugin sa WordPress](https://wordpress.org/plugins/search/minify+javascript/) ang iyong site sa pamamagitan ng pagsasama-sama, pagpapaliit, at pagko-compress ng mga script mo. Puwede ka ring gumamit ng proseso ng pagbuo para gawin ang pagpapaliit na ito nang mas maaga kung posible."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Pag-isipang bawasan, o baguhin, ang bilang ng [mga plugin sa WordPress](https://wordpress.org/plugins/) na naglo-load ng mga hindi ginagamit na CSS sa iyong page. Para tukuyin ang mga plugin na nagdaragdag ng mga hindi nauugnay na CSS, subukang patakbuhin ang [sakop ng code](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) sa Chrome DevTools. Puwede mong tukuyin ang tema/plugin na sanhi nito mula sa URL ng stylesheet. Abangan ang mga plugin na maraming stylesheet sa listahang maraming pula sa sakop ng code. Dapat lang i-enqueue ng plugin ang isang stylesheet kung talagang ginagamit ito sa page."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Pag-isipang bawasan, o baguhin, ang bilang ng [mga plugin sa WordPress](https://wordpress.org/plugins/) na naglo-load ng mga hindi ginagamit na JavaScript sa iyong page. Para tukuyin ang mga plugin na nagdaragdag ng mga hindi nauugnay na JS, subukang patakbuhin ang [sakop ng code](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) sa Chrome DevTools. Puwede mong tukuyin ang tema/plugin na sanhi nito mula sa URL ng script. Abangan ang mga plugin na maraming script sa listahang may maraming pula sa sakop ng code. Dapat lang i-enqueue ng plugin ang isang script kung talagang ginagamit ito sa page."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Magbasa tungkol sa [Pag-cache ng Browser sa WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Pag-isipang gumamit ng [plugin sa WordPress para sa pag-optimize ng larawan](https://wordpress.org/plugins/search/optimize+images/) na nagko-compress ng iyong mga larawan habang pinapanatili ang kalidad."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Direktang i-upload ang mga larawan sa pamamagitan ng [library ng media](https://codex.wordpress.org/Media_Library_Screen) para tiyaking available ang mga kinakailangang laki ng larawan, at pagkatapos ay ilagay ang mga ito mula sa library ng media o gamitin ang widget ng larawan para tiyaking ginagamit ang mga pinakaangkop na laki ng larawan (kabilang ang para sa mga tumutugong breakpoint). Iwasang gamitin ang mga larawang nasa `Full Size` maliban kung sapat ang mga dimensyon para sa paggamit ng mga ito. [Matuto Pa](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Puwede mong i-enable ang pag-compress ng text sa configuration ng iyong server sa web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Pag-isipang gumamit ng [plugin](https://wordpress.org/plugins/search/convert+webp/) o serbisyong awtomatikong magko-convert ng iyong mga na-upload na larawan sa mga optimal na format."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fr.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fr.json
new file mode 100644
index 00000000000..29c3393561d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/fr.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Les clés d'accès permettent aux utilisateurs de positionner rapidement le curseur dans une partie spécifique de la page. Pour les aider à naviguer correctement, pensez à définir des clés d'accès uniques. [En savoir plus](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Les valeurs `[accesskey]` ne sont pas uniques"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Les valeurs `[accesskey]` sont uniques"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Chaque `role` ARIA est rattaché à un sous-ensemble spécifique d'attributs `aria-*`. S'ils ne sont pas correctement associés, les attributs `aria-*` ne seront pas valides. [En savoir plus](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Les attributs `[aria-*]` ne correspondent pas à leurs rôles"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Les attributs `[aria-*]` correspondent à leurs rôles"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Certains rôles ARIA ont des attributs obligatoires qui décrivent l'état de l'élément aux lecteurs d'écran. [En savoir plus](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Les éléments `[role]` ne possèdent pas tous les attributs `[aria-*]` requis"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Tous les éléments `[role]` contiennent les attributs `[aria-*]` requis"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Certains rôles ARIA parents doivent contenir des rôles enfants spécifiques afin de remplir correctement leurs fonctions d'accessibilité. [En savoir plus](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Les éléments ayant un `[role]` ARIA, qui exigent que les enfants incluent un `[role]` spécifique, ne possèdent pas certains ou l'ensemble des enfants requis."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Les éléments ayant un `[role]` ARIA, qui exigent que les enfants incluent un `[role]` spécifique, possèdent tous les enfants requis."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Certains rôles ARIA enfants doivent être inclus dans un rôle parent spécifique afin de remplir correctement leurs fonctions d'accessibilité. [En savoir plus](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Les éléments `[role]` ne sont pas inclus dans l'élément parent requis"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Les éléments `[role]` sont inclus dans l'élément parent approprié"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Les rôles ARIA doivent comporter des valeurs valides afin de remplir correctement leurs fonctions d'accessibilité. [En savoir plus](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Les valeurs `[role]` ne sont pas valides"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Les valeurs `[role]` sont valides"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Les technologies d'assistance telles que les lecteurs d'écran ne peuvent pas interpréter les attributs ARIA si leurs valeurs ne sont pas valides. [En savoir plus](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "La valeur des attributs `[aria-*]` n'est pas valide"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Les attributs `[aria-*]` ont des valeurs valides"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Les technologies d'assistance telles que les lecteurs d'écran ne peuvent pas interpréter les attributs ARIA si leurs noms ne sont pas valides. [En savoir plus](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Les attributs `[aria-*]` ne sont pas valides ou sont mal orthographiés"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Les attributs `[aria-*]` sont valides et correctement orthographiés"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Les sous-titres rendent les contenus audio accessibles aux personnes sourdes et malentendantes, en leur fournissant des informations essentielles (qui est en train de parler, ce que cette personne dit et d'autres informations non contenues dans le dialogue, par exemple). [En savoir plus](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Il manque un élément `<track>` possédant l'attribut `[kind=\"captions\"]` dans les éléments `<audio>`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Les éléments `<audio>` contiennent un élément `<track>` possédant l'attribut `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Éléments non conformes"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Lorsqu'un bouton n'a pas de nom accessible, les lecteurs d'écran annoncent simplement qu'il s'agit d'un \"bouton\", ce qui le rend inutilisable pour les personnes qui se servent de tels outils. [En savoir plus](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Les boutons n'ont pas de nom accessible"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Les boutons ont un nom accessible"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "En ajoutant des méthodes pour contourner les contenus répétitifs, vous permettez aux internautes qui utilisent un clavier de naviguer plus efficacement sur la page. [En savoir plus](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "La page ne contient pas de titre, de lien \"Ignorer\" ni de point de repère"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "La page contient un titre, un lien \"Ignorer\" ou un point de repère"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Un texte faiblement contrasté est difficile, voire impossible à lire pour de nombreux utilisateurs. [En savoir plus](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Les couleurs d'arrière-plan et de premier plan ne sont pas suffisamment contrastées"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Les couleurs d'arrière-plan et de premier plan sont suffisamment contrastées"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Si les listes de définition ne sont pas correctement balisées, les lecteurs d'écran risquent de donner des résultats confus ou imprécis. [En savoir plus](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Les éléments `<dl>` ne contiennent pas uniquement des groupes `<dt>` et `<dd>` ainsi que des éléments `<script>` ou `<template>` dans le bon ordre."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Les éléments `<dl>` ne contiennent que des groupes `<dt>` et `<dd>` ainsi que des éléments `<script>` ou `<template>` dans le bon ordre."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Les éléments de liste de définition (`<dt>` et `<dd>`) doivent être encapsulés dans un élément `<dl>` parent afin que les lecteurs d'écran puissent les énoncer correctement. [En savoir plus](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Les éléments de liste de définition ne sont pas encapsulés dans des éléments `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Les éléments de liste de définition sont encapsulés dans des éléments `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Le titre donne aux utilisateurs de lecteurs d'écran un aperçu de la page. En outre, les moteurs de recherche s'appuient principalement sur ce dernier pour déterminer la pertinence du contenu proposé. [En savoir plus](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Le document ne contient pas d'élément `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Le document contient un élément `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "La valeur de chaque attribut \"id\" doit être unique afin que les différentes instances soient toutes prises en compte par les technologies d'assistance. [En savoir plus](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Les attributs `[id]` de la page ne sont pas uniques"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Les attributs `[id]` de la page sont uniques"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Les lecteurs d'écran s'appuient sur le titre des frames pour décrire le contenu de ces derniers aux utilisateurs. [En savoir plus](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Les éléments `<frame>` ou `<iframe>` n'ont pas de titre"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Les éléments `<frame>` ou `<iframe>` ont un titre"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Lorsqu'une page ne spécifie pas d'attribut \"lang\", les lecteurs d'écran considèrent qu'elle est rédigée dans la langue par défaut sélectionnée au moment de leur configuration par l'utilisateur. Si la page n'est pas rédigée dans cette langue par défaut, les lecteurs d'écran risquent de ne pas énoncer correctement son contenu. [En savoir plus](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "L'élément `<html>` n'a pas d'attribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "L'élément `<html>` contient un attribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Le fait de spécifier une [langue BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valide permet d'aider les lecteurs d'écran à énoncer correctement le texte. [En savoir plus](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "La valeur de l'attribut `[lang]` de l'élément `<html>` n'est pas valide."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "La valeur de l'attribut `[lang]` de l'élément `<html>` est valide"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Les éléments informatifs doivent contenir un texte de substitution court et descriptif. L'attribut alt peut rester vide pour les éléments décoratifs. [En savoir plus](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Des éléments d'image n'ont pas d'attribut `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Les éléments d'image possèdent des attributs `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Lorsqu'une image est utilisée comme bouton `<input>`, vous pouvez aider les utilisateurs de lecteurs d'écran à comprendre son utilité en ajoutant un texte de substitution. [En savoir plus](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Les éléments `<input type=\"image\">` n'ont pas de texte `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Les éléments `<input type=\"image\">` contiennent du texte `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Les libellés permettent de s'assurer que les éléments de contrôle des formulaires sont énoncés correctement par les technologies d'assistance, comme les lecteurs d'écran. [En savoir plus](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Les éléments de formulaire ne sont pas associés à des libellés"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Les éléments de formulaire sont associés à des libellés"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Un tableau utilisé pour la mise en page ne doit pas inclure d'éléments de données tels que les éléments \"th\" ou \"caption\", ou encore l'attribut \"summary\", car cela peut perturber l'expérience des utilisateurs de lecteurs d'écran. [En savoir plus](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Les éléments `<table>` de présentation n'évitent pas d'utiliser `<th>`, `<caption>` ni l'attribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Les éléments `<table>` de présentation ne font pas appel aux éléments `<th>` et `<caption>`, ni à l'attribut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Rédigez du texte visible et unique pour les liens (et pour le texte de substitution des images, si vous vous en servez dans des liens), afin que les utilisateurs de lecteurs d'écran puissent facilement positionner le curseur dessus et bénéficient d'une meilleure expérience de navigation. [En savoir plus](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Les liens n'ont pas de nom visible"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Les liens ont un nom visible"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Les lecteurs d'écran ont une façon spécifique d'énoncer les listes. Pour leur permettre de donner de bons résultats, pensez à bien structurer ces dernières. [En savoir plus](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Les listes ne contiennent pas uniquement des éléments `<li>` et des éléments de type script (`<script>` et `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Les listes contiennent uniquement des éléments `<li>` et des éléments de type script (`<script>` et `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Les lecteurs d'écran requièrent que les éléments de liste (`<li>`) soient contenus dans un élément parent `<ul>` ou `<ol>` pour les énoncer correctement. [En savoir plus](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Les éléments de liste (`<li>`) ne sont pas inclus dans des éléments parents `<ul>` ni `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Les éléments de liste (`<li>`) sont inclus dans des éléments parents `<ul>` ou `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Les utilisateurs ne s'attendent pas à ce qu'une page s'actualise automatiquement. De plus, lorsque cela se produit, le curseur est aussitôt repositionné en haut de la page. Cela peut générer de la frustration et perturber l'expérience utilisateur. [En savoir plus](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Le document utilise une balise Meta `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Le document n'utilise pas de balise Meta `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "La désactivation de la fonction de zoom peut être problématique pour les utilisateurs qui ne voient pas bien et qui ont besoin d'agrandir le contenu d'une page Web pour en saisir le sens. [En savoir plus](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "L'attribut `[user-scalable=\"no\"]` est utilisé dans l'élément `<meta name=\"viewport\">`, ou l'attribut `[maximum-scale]` est inférieur à 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` n'est pas utilisé dans l'élément `<meta name=\"viewport\">`, et l'attribut `[maximum-scale]` n'est pas inférieur à 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Les lecteurs d'écran ne peuvent pas traduire les contenus non textuels. En ajoutant un texte de substitution aux éléments `<object>`, vous aiderez les lecteurs d'écran à transmettre votre message aux utilisateurs. [En savoir plus](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Les éléments `<object>` n'ont pas de texte `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Les éléments `<object>` contiennent du texte `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Une valeur supérieure à 0 implique un ordre de navigation explicite. Bien que cela soit valide d'un point de vue technique, cela crée souvent une expérience frustrante pour les utilisateurs qui s'appuient sur des technologies d'assistance. [En savoir plus](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Certains éléments ont une valeur `[tabindex]` supérieure à 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Aucun élément n'a de valeur `[tabindex]` supérieure à 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Les lecteurs d'écran proposent des fonctionnalités qui permettent de naviguer plus simplement dans les tableaux. En vous assurant que les cellules `<td>` qui comportent l'attribut `[headers]` fassent référence à d'autres cellules dans le même tableau uniquement, vous pourrez améliorer l'expérience des utilisateurs de lecteurs d'écran. [En savoir plus](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Les cellules d'un élément `<table>` qui utilisent l'attribut `[headers]` font référence à un élément `id` ne figurant pas dans le même tableau."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Les cellules d'un élément `<table>` qui utilisent l'attribut `[headers]` font référence à des cellules figurant dans le même tableau."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Les lecteurs d'écran proposent des fonctionnalités qui permettent de naviguer plus simplement dans les tableaux. En vous assurant que les en-têtes de tableaux fassent toujours référence à un ensemble de cellules spécifique, vous pourrez améliorer l'expérience des utilisateurs de lecteurs d'écran. [En savoir plus](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Les éléments `<th>` et ceux portant l'attribut `[role=\"columnheader\"/\"rowheader\"]` ne décrivent aucune cellule de données."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Les éléments `<th>` et ceux portant l'attribut `[role=\"columnheader\"/\"rowheader\"]` décrivent des cellules de données."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Le fait de spécifier une [langue BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valide pour les éléments permet de s'assurer que le texte sera prononcé correctement par les lecteurs d'écran. [En savoir plus](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "La valeur des attributs `[lang]` n'est pas valide"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Les attributs `[lang]` ont une valeur valide"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Le fait d'ajouter des sous-titres à une vidéo rend cette dernière plus accessible aux personnes sourdes et malentendantes. [En savoir plus](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Les éléments `<video>` ne contiennent pas d'élément `<track>` possédant l'attribut `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Les éléments `<video>` contiennent un élément `<track>` possédant l'attribut `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Les descriptions audio fournissent des informations pertinentes qui ne sont pas comprises dans le dialogue des vidéos, comme les expressions faciales et les scènes. [En savoir plus](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Les éléments `<video>` ne contiennent pas d'élément `<track>` possédant l'attribut `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Les éléments `<video>` contiennent un élément `<track>` possédant l'attribut `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Définissez un attribut `apple-touch-icon` afin d'optimiser l'affichage de votre progressive web app sur l'écran d'accueil des appareils iOS. Il doit mener vers une image PNG carrée opaque de 180 ou 192 pixels. [Découvrez-en davantage](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "La valeur de l'attribut `apple-touch-icon` n'est pas valide"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` est obsolète. Utilisez plutôt `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "La valeur de l'attribut `apple-touch-icon` est valide"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Les extensions Chrome ont eu un impact négatif sur les performances de chargement de la page. Essayez de contrôler la page en mode navigation privée ou depuis un profil Chrome sans extensions."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Évaluation des scripts"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analyse des scripts"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Temps CPU total"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Envisagez de réduire le temps consacré à l'analyse, la compilation et l'exécution de JavaScript. La livraison de charges utiles JavaScript plus petites peut vous aider. [En savoir plus](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Réduisez le temps d'exécution de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Délai d'exécution de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Les grandes images GIF sont inefficaces pour diffuser du contenu animé. Envisagez d'utiliser des vidéos MPEG4/WebM pour les animations et PNG/WebP pour les images statiques au lieu d'images GIF afin d'économiser des octets réseau. [En savoir plus](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Utilisez des formats vidéo pour le contenu animé"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Envisagez de charger des images masquées ou hors écran après le chargement de toutes les ressources essentielles afin de réduire le délai avant interactivité. [En savoir plus](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Différez le chargement des images hors écran"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Des ressources bloquent la première visualisation (first paint) de votre page. Envisagez de diffuser des feuilles JS/CSS essentielles en ligne et de différer la diffusion de toutes les feuilles JS/de style non essentielles. [En savoir plus](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Éliminez les ressources qui bloquent le rendu"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Les charges utiles des grands réseaux coûtent de l'argent réel aux utilisateurs et sont fortement corrélées aux délais de chargement interminables. [En savoir plus](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Taille totale : {totalBytes, number, bytes} Ko"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Évitez d'énormes charges utiles de réseau"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Éviter d'énormes charges utiles de réseau"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "La réduction des fichiers CSS peut réduire la taille des charges utiles de réseau. [En savoir plus](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Réduisez la taille des ressources CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "La minimisation des fichiers JavaScript peut réduire la taille des charges utiles et la durée d'analyse des scripts. [En savoir plus](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Réduisez la taille des ressources JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Supprimez les règles inutilisées des feuilles de style et différez le chargement des ressources CSS inutilisées pour le contenu au-dessus de la ligne de flottaison afin de réduire la quantité d'octets inutiles consommés par l'activité réseau. [En savoir plus](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Supprimer les ressources CSS inutilisées"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Supprimez les ressources JavaScript inutilisées pour réduire la quantité d'octets consommés par l'activité réseau."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Supprimez les ressources JavaScript inutilisées"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Une longue durée de vie du cache peut accélérer les visites répétées sur votre page. [En savoir plus](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ressource trouvée}one{# ressource trouvée}other{# ressources trouvées}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Diffusez des éléments statiques grâce à des règles de cache efficaces"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Utiliser des règles de cache efficaces sur les éléments statiques"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Les images optimisées se chargent plus rapidement et consomment moins de données mobiles. [En savoir plus](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Encodez les images de manière efficace"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Diffusez des images de taille appropriée afin d'économiser des données mobiles et de réduire le temps de chargement. [En savoir plus](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Dimensionnez correctement les images"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Les ressources textuelles doivent être diffusées compressées (Gzip, Deflate ou Brotli) pour réduire le nombre total d'octets du réseau. [En savoir plus](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Activez la compression de texte"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Les formats d'image comme JPEG 2000, JPEG XR et WebP proposent souvent une meilleure compression que les formats PNG ou JPEG. Par conséquent, les téléchargements sont plus rapides et la consommation de données est réduite. [En savoir plus](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Diffusez des images aux formats nouvelle génération"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Si la largeur du contenu de votre application ne correspond pas à la largeur de la fenêtre d'affichage, il se peut que votre application ne soit pas optimisée pour les écrans mobiles. [Découvrez-en davantage](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "La dimension de la fenêtre d'affichage ({innerWidth} pixels) ne correspond pas à la taille de la fenêtre ({outerWidth} pixels)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Le contenu n'est pas correctement dimensionné pour la fenêtre d'affichage"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Le contenu est correctement dimensionné pour la fenêtre d'affichage"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Les chaînes de demandes critiques ci-dessous vous montrent quelles ressources sont chargées avec une priorité élevée. Envisagez de réduire la longueur des chaînes et la taille de téléchargement des ressources ou de reporter le téléchargement de ressources inutiles afin d'améliorer le chargement des pages. [En savoir plus](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 chaîne trouvée}one{# chaîne trouvée}other{# chaînes trouvées}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Réduisez la profondeur des demandes critiques"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "API obsolète/Avertissement"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Ligne"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Les API obsolètes seront finalement supprimées du navigateur. [En savoir plus](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 avertissement détecté}one{# avertissement détecté}other{# avertissements détectés}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "API obsolètes utilisées"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "La page n'utilise pas d'API obsolètes"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "L'API Application Cache est obsolète. [En savoir plus](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" trouvé"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "API Application Cache utilisée"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "API Application Cache non utilisée"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "La spécification d'un attribut doctype empêche le navigateur de passer en mode quirks. [Découvrez-en davantage](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Le nom de l'attribut doctype doit être en minuscules `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Le document doit contenir un attribut doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "La chaîne publicId est censée être vide"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "La chaîne systemId est censée être vide"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "La page n'a pas d'attribut doctype HTML, ce qui déclenche le mode quirks"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "La page n'a pas d'attribut doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Élément"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistique"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valeur"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Les ingénieurs en navigation recommandent que les pages contiennent moins de 1 500 éléments DOM environ. La zone d'écoute idéale est une profondeur d'arborescence inférieure à 32 éléments et contenant moins de 60 éléments enfant/parent. Un grand DOM peut accroître l'utilisation de la mémoire, et entraîner de plus longs [calculs de style](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) et de coûteux [ajustements de la mise en page](https://developers.google.com/speed/articles/reflow). [En savoir plus](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 élément}one{# élément}other{# éléments}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Évitez une taille excessive de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profondeur maximum de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Nombre total d'éléments DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Nombre maximal d'éléments enfants"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Éviter une taille excessive de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cible"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Ajoutez les attributs `rel=\"noopener\"` ou `rel=\"noreferrer\"` à tous les liens externes pour améliorer les performances et prévenir les failles de sécurité. [En savoir plus](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Les liens vers les destinations multi-domaines sont dangereux"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Les liens vers les destinations multi-domaines sont sûrs"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Impossible de déterminer la destination de l'ancrage ({anchorHTML}). S'il n'est pas utilisé comme lien hypertexte, envisagez de supprimer target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Les utilisateurs se méfient des sites qui demandent leur position sans contexte. Envisagez plutôt d'associer la demande à des actions de l'utilisateur. [En savoir plus](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Demandes d'autorisation de géolocalisation lors du chargement de page"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Aucune autorisation de géolocalisation n'est demandée au chargement de la page"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Toutes les bibliothèques JavaScript frontales détectées sur la page. [Découvrez-en davantage](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Bibliothèques JavaScript détectées"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Pour les utilisateurs rencontrant des problèmes de connexion lente, les scripts externes injectés dynamiquement via `document.write()` peuvent retarder le chargement des pages de plusieurs dizaines de secondes. [En savoir plus](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "La page utilise l'attribut `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Évite `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Extrême"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Version de la bibliothèque"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Nombre de failles"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Certains scripts tiers peuvent présenter des failles de sécurité connues, faciles à identifier et à exploiter par des pirates informatiques. [En savoir plus](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 faille détectée}one{# faille détectée}other{# failles détectées}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "La page utilise des bibliothèques JavaScript frontales présentant des failles de sécurité connues"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Élevée"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Faible"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Moyenne"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Les bibliothèques JavaScript frontales ne présentent aucune faille de sécurité connue"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Les utilisateurs se méfient des sites qui demandent à envoyer des notifications sans contexte. Envisagez plutôt d'associer la demande à des gestes de l'utilisateur. [En savoir plus](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Demandes d'autorisation d'envoi de notifications lors du chargement de page"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Aucune autorisation d'envoi de notifications n'est demandée au chargement de la page"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Éléments non conformes"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Empêcher la copie de contenu dans les champs de mot de passe nuit aux règles de sécurité. [En savoir plus](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "La copie de contenu n'est pas autorisée dans les champs de mot de passe"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Autoriser les utilisateurs à copier un contenu dans les champs de mot de passe"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocole"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Le protocole HTTP/2 offre de nombreux avantages par rapport à HTTP/1.1, comme les en-têtes binaires, le multiplexage et la fonctionnalité Push des serveurs. [En savoir plus](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 requête non traitée via le protocole HTTP/2}one{# requête non traitée via le protocole HTTP/2}other{# requêtes non traitées via le protocole HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "La page n'utilise pas le protocole HTTP/2 pour toutes ses ressources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "La page utilise le protocole HTTP/2 pour ses propres ressources"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Envisagez de marquer vos écouteurs d'événements tactiles et à la molette comme `passive` pour améliorer les performances de défilement de votre page. [En savoir plus](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "La page n'utilise pas d'écouteurs d'événements passifs pour améliorer les performances de défilement"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "La page utilise des écouteurs d'événements passifs pour améliorer les performances de défilement"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Description"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Les erreurs enregistrées dans la console indiquent des problèmes non résolus. Ces derniers peuvent être dus à des requêtes réseau qui ont échoué et à d'autres problèmes du navigateur. [En savoir plus](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Les erreurs de navigateur ont été enregistrées dans la console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Aucune erreur de navigateur enregistrée dans la console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Utilisez la fonction d'affichage de la police CSS afin que le texte soit visible par l'utilisateur pendant le chargement des polices Web. [En savoir plus](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Assurez-vous que le texte reste visible pendant le chargement des polices Web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "La totalité du texte reste visible pendant le chargement des polices Web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse n'a pas pu vérifier automatiquement la valeur d'affichage de la police pour l'URL suivante : {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Format (image réelle)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Format (image affichée)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Les dimensions d'affichage des images doivent correspondre au format naturel. [En savoir plus](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Images affichées dans un format incorrect"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Images affichées au bon format"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informations sur la taille d'image non valides {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Les utilisateurs peuvent être invités à ajouter votre application à leur écran d'accueil par le biais de leur navigateur. Cette fonctionnalité peut contribuer à une hausse de l'engagement. [Découvrez-en davantage](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Le fichier manifeste de l'application Web ne respecte pas les conditions d'installation requises"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Le fichier manifeste de l'application Web respecte les conditions d'installation requises"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL non sécurisée"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Tous les sites doivent être protégés par le protocole HTTPS, même ceux qui ne traitent pas de données sensibles. Le protocole HTTPS empêche les intrus de détourner ou d’écouter passivement les communications entre votre application et les utilisateurs. Il constitue également une condition préalable à l'utilisation de HTTP/2 et de nombreuses nouvelles API de plates-formes Web. [En savoir plus](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 requête non sécurisée trouvée}one{# requête non sécurisée trouvée}other{# requêtes non sécurisées trouvées}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "La page n'utilise pas le protocole HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Requêtes HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Le chargement rapide des pages sur un réseau mobile garantit une expérience utilisateur de qualité. [En savoir plus](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Page interactive en {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Page devenue interactive sur un réseau mobile au bout de {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Votre page se charge trop lentement. L'utilisateur ne peut pas interagir avec en moins de 10 secondes. Pour découvrir comment l'améliorer, consultez les conseils et les diagnostics de la section \"Performances\"."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Le chargement de la page n'est pas suffisamment rapide sur les réseaux mobiles"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Le chargement de la page est suffisamment rapide sur les réseaux mobiles"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Catégorie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Envisagez de réduire le temps consacré à l'analyse, la compilation et l'exécution de JavaScript. La livraison de charges utiles JavaScript plus petites peut vous aider. [En savoir plus](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Réduisez le travail du thread principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Réduire le travail du thread principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Afin de toucher le plus grand nombre d'utilisateurs possible, les sites doivent fonctionner sur tous les principaux navigateurs. [Découvrez-en davantage](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Le site fonctionne sur différents navigateurs"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Veillez à ce que les URL de vos pages puissent être utilisées dans des liens profonds. En outre, chaque URL doit être unique afin de pouvoir être correctement partagée sur les médias sociaux. [Découvrez-en davantage](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Chaque page a sa propre URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "La navigation sur les pages doit être rapide et fluide, même pour les utilisateurs avec une connexion lente. C'est un critère de performance fondamental pour les utilisateurs. [Découvrez-en davantage.](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "La navigation entre les différentes pages du site doit être rapide et fluide"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "La valeur \"Estimated Input Latency\" est une estimation du temps en millisecondes que prend votre application pour réagir à l'intervention de l'utilisateur, pendant la fenêtre de pointe de 5 s de chargement de la page. Si le temps de latence est supérieur à 50 ms, les utilisateurs peuvent percevoir votre application comme étant lente. [En savoir plus](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Estimation du temps de latence avant intervention"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "La statistique \"First Contentful Paint\" indique le moment où le premier texte ou la première image sont affichés. [En savoir plus](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "La statistique \"First CPU Idle\" marque la première fois que le thread principal de la page est suffisamment silencieux pour gérer l'entrée. [Découvrez-en davantage.](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Premier processeur inactif"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "La statistique \"First Meaningful Paint\" mesure quand le contenu principal d'une page est visible. [En savoir plus](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "La valeur \"Time to Interactive\" correspond au temps nécessaire pour que la page devienne entièrement interactive. [En savoir plus](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Délai avant interactivité"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Le retard maximal (Maximum Potential First Input Delay) auquel vos utilisateurs peuvent éventuellement être confrontés correspond à la durée, en millisecondes, de la tâche la plus longue. [En savoir plus](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max Potential First Input Delay"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "La valeur \"Speed Index\" indique la rapidité avec laquelle le contenu d'une page est disponible. [En savoir plus](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indice de vitesse"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Somme en millisecondes de toutes les périodes entre le FCP et le délai avant interactivité, lorsque la durée de la tâche a dépassé 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total Blocking Time"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Les délais aller-retour (DAR) du réseau ont un impact important sur les performances. Si le DAR par rapport à un point d'origine est élevé, cela signifie que les performances des serveurs proches de l'utilisateur peuvent sans doute être améliorées. [En savoir plus](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Délai aller-retour réseau"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "La latence du serveur peut avoir une incidence sur les performances Web. Si la latence serveur d'une origine est élevée, cela signifie que le serveur est en surcharge ou que ses performances backend sont médiocres. [En savoir plus](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latences du backend serveur"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Les service workers garantissent le bon fonctionnement de votre application Web, indépendamment des aléas du réseau. [Découvrez-en davantage](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ne retourne pas de code 200 en mode hors connexion"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` retourne un code 200 en mode hors connexion"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse ne parvient pas à lire l'attribut `start_url` du fichier manifeste et considère donc `start_url` comme étant l'URL du document. Message d'erreur : \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Au-dessus du budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Maintenez le volume et la taille des requêtes réseau sous les objectifs définis par le budget de performances fourni. [En savoir plus](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 requête}one{# requête}other{# requêtes}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Budget de performances"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Si vous avez déjà configuré le protocole HTTPS, veillez à rediriger tout le trafic HTTP vers HTTPS afin de proposer des fonctionnalités Web sûres à tous vos utilisateurs. [Découvrez-en davantage](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Ne redirige pas le trafic HTTP vers HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Trafic HTTP redirigé vers HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Les redirections entraînent des retards supplémentaires avant que la page ne puisse être chargée. [En savoir plus](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Évitez les redirections de page multiples"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Pour définir des budgets liés à la quantité et à la taille des ressources de pages, ajoutez un fichier budget.json. [En savoir plus](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 requête • {byteCount, number, bytes} Ko}one{# requête • {byteCount, number, bytes} Ko}other{# requêtes • {byteCount, number, bytes} Ko}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Réduisez au maximum le nombre de requêtes et la taille des transferts"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Les liens canoniques suggèrent l'URL à afficher dans les résultats de recherche. [En savoir plus](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Plusieurs URL en conflit ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "L'URL mène à un autre domaine ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL incorrecte ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "URL qui mène à un autre emplacement `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relative ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Pointe vers l'URL racine du domaine (la page d'accueil), et non vers une page de contenu équivalente"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "L'attribut `rel=canonical` du document n'est pas valide"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "L'attribut `rel=canonical` du document est valide"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Les tailles de police inférieures à 12 pixels sont trop petites pour être lisibles et nécessitent que les visiteurs sur la version mobile pincent l'écran pour zoomer et lire le texte. Veuillez utiliser une police de texte de plus de 12 pixels sur plus de 60 % du texte de la page. [En savoir plus](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} du texte lisibles"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Le texte est illisible, car aucune balise Meta de fenêtre d'affichage n'est optimisée pour les écrans mobiles."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} du texte sont trop petits (d'après un échantillon de {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Les tailles de police utilisées dans le document ne sont pas lisibles"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Le document utilise des tailles de police lisibles"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Les liens hreflang indiquent aux moteurs de recherche la version de la page qu'ils doivent répertorier dans les résultats de recherche pour une page ou une région donnée. [En savoir plus](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Le document ne contient pas d'attribut `hreflang` valide"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "L'attribut `hreflang` du document est valide"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Les pages renvoyant des codes d'état HTTP d'échec peuvent ne pas être indexées correctement. [En savoir plus](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "La page renvoie un code d'état HTTP d'échec"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "La page renvoie un code d'état HTTP de réussite"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Les moteurs de recherche ne peuvent pas inclure vos pages dans les résultats de recherche s'ils ne sont pas autorisés à les explorer. [En savoir plus](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "L'indexation de la page est bloquée"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "L'indexation de cette page n'est pas bloquée"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Le texte descriptif d'un lien aide les moteurs de recherche à comprendre votre contenu. [En savoir plus](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 lien trouvé}one{# lien trouvé}other{# liens trouvés}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Les liens ne contiennent pas de texte descriptif"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Les liens contiennent un texte descriptif"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Exécutez l'[outil de test des données structurées](https://search.google.com/structured-data/testing-tool/) et le [validateur Lint de données structurées](http://linter.structured-data.org/) pour valider les données structurées. [En savoir plus](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Les données structurées sont valides"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Les résultats de recherche peuvent inclure des attributs \"meta description\" pour résumer de façon concise le contenu de la page. [En savoir plus](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Le texte de la description est vide."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Le document ne contient pas d'attribut \"meta description\""
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Le document contient un attribut \"meta description\""
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Les moteurs de recherche ne peuvent pas indexer le contenu des plug-ins, et de nombreux appareils limitent l'utilisation de ces derniers, voire ne les acceptent pas. [En savoir plus](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Le document utilise des plug-ins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Le document évite les plug-ins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Si votre fichier robots.txt n'est pas créé correctement, il se peut que les robots d'exploration ne puissent pas comprendre comment votre site Web doit être exploré ou indexé. [Découvrez-en davantage](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "La requête pour le fichier robots.txt a renvoyé l'état HTTP {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 erreur détectée}one{# erreur détectée}other{# erreurs détectées}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse n'est pas parvenu à télécharger le fichier robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Le fichier robots.txt n'est pas valide"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Le fichier robots.txt est valide"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Les éléments interactifs comme les boutons et les liens doivent être suffisamment larges (48 x 48 pixels) et avoir suffisamment d'espace autour d'eux pour que l'utilisateur puisse appuyer facilement dessus sans appuyer en même temps sur d'autres éléments. [En savoir plus](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} des éléments tactiles sont correctement dimensionnés"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Les éléments tactiles sont trop petits, car aucune balise Meta de fenêtre d'affichage n'est optimisée pour les écrans mobiles"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Les éléments tactiles ne sont pas dimensionnés correctement"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Cible en chevauchement"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Élément tactile"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Les éléments tactiles sont dimensionnés correctement"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Un service worker est une technologie qui permet à votre application d'exploiter de nombreuses fonctionnalités propres aux progressive web apps, comme le fonctionnement hors connexion, l'ajout à un écran d'accueil et les notifications push. [Découvrez-en davantage](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Un service worker contrôle cette page. Toutefois, aucun attribut `start_url` n'a été trouvé en raison d'un échec lors de l'analyse du fichier manifeste (JSON non valide)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Un service worker contrôle cette page. Toutefois, l'attribut `start_url` ({startUrl}) est situé en dehors du champ d'application du service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Un service worker contrôle cette page. Toutefois, aucun attribut `start_url` n'a été trouvé, car le fichier manifeste n'a pas pu être récupéré."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Plusieurs service workers existent pour cette origine. Toutefois, la page ({pageUrl}) est située en dehors du champ d'application."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Aucun service worker de contrôle de la page et de `start_url` n'est enregistré"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Un service worker de contrôle de la page et de `start_url` est enregistré"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Avec un écran d'accueil à thème, vous garantissez une expérience de qualité aux utilisateurs qui lancent votre application depuis leur écran d'accueil. [Découvrez-en davantage](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Écran d'accueil personnalisé non disponible"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Écran d'accueil personnalisé disponible"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Vous pouvez définir un thème assorti à votre site pour la barre d'adresse du navigateur. [Découvrez-en davantage](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Aucune couleur de thème n'est configurée pour la barre d'adresse."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Une couleur de thème est configurée pour la barre d'adresse."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Durée de blocage du thread principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tiers"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Le code tiers peut affecter considérablement les performances de chargement des pages. Limitez le nombre de fournisseurs tiers redondants, et essayez de charger du code tiers une fois le chargement de votre page terminé. [En savoir plus](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Le thread principal a été bloqué par du code tiers pendant {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Réduire l'impact du code tiers"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Code tiers"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "La valeur \"Time To First Byte\" identifie l'heure à laquelle votre serveur envoie une réponse. [En savoir plus](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Le document racine a pris {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Réduisez les délais de réponse du serveur (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Les délais de réponse du serveur sont faibles (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Durée"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Heure de début"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Envisagez de doter votre application de l'API User Timing pour mesurer ses performances réelles lors d'expériences utilisateur clés. [En savoir plus](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{[=1]1 temps utilisateur}one{# temps utilisateur}other{# temps utilisateur}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Marques et mesures du temps utilisateur"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Un élément <link> de pré-connexion a été trouvé pour \"{securityOrigin}\", mais il n'a pas été utilisé par le navigateur. Vérifiez que vous utilisez correctement l'attribut \"`crossorigin`\"."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Envisagez d'ajouter les indices de ressources `preconnect` ou `dns-prefetch` pour établir les premières connexions avec des origines tierces importantes. [Découvrez-en davantage](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Connectez-vous à l'avance aux origines souhaitées"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Une balise <link> de préchargement a été détectée pour \"{preloadURL}\", mais n'a pas été utilisée par le navigateur. Vérifiez que vous utilisez correctement l'attribut \"`crossorigin`\"."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Envisagez d'utiliser `<link rel=preload>` pour hiérarchiser la récupération des ressources actuellement requises pour le chargement ultérieur de la page. [En savoir plus](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Préchargez les demandes clés"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Ajoutez une balise `<meta name=\"viewport\">` afin d'optimiser votre application pour les écrans mobiles. [Découvrez-en davantage](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Aucune balise `<meta name=\"viewport\">` trouvée"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Aucune balise `<meta name=\"viewport\">` ayant l'attribut `width` ou `initial-scale` n'est configurée"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Une balise `<meta name=\"viewport\">` ayant l'attribut `width` ou `initial-scale` est configurée"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Nous vous recommandons d'afficher du contenu même lorsque JavaScript est indisponible. Il peut s'agir d'un simple avertissement informant l'utilisateur que JavaScript est requis pour utiliser votre application. [Découvrez-en davantage](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Il est recommandé d'afficher du contenu dans le corps de la page lorsque les scripts sont indisponibles."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Aucun contenu de remplacement ne s'affiche lorsque JavaScript est indisponible"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Du contenu s'affiche lorsque JavaScript est indisponible"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Si vous développez une progressive web app, envisagez d'utiliser un service worker afin que votre application soit accessible hors connexion. [Découvrez-en davantage](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "La page actuelle ne retourne pas de code 200 en mode hors connexion"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "La page actuelle retourne un code 200 en mode hors connexion"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Il est possible que cette page ne se charge pas hors connexion, car votre URL de test ({requested}) redirige vers \"{final}\". Testez directement la seconde URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer l'utilisation des éléments ARIA dans votre application et ainsi optimiser l'expérience des utilisateurs de technologies d'assistance, comme les lecteurs d'écran."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Servez-vous de ces indications pour fournir un contenu alternatif pour l'audio et la vidéo. Vous pourrez ainsi améliorer l'expérience des utilisateurs malvoyants ou malentendants."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio et vidéo"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ces indications présentent les bonnes pratiques courantes en matière d'accessibilité."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Bonnes pratiques"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ces vérifications permettent de connaître les possibilités d'[amélioration de l'accessibilité de vos applications Web](https://developers.google.com/web/fundamentals/accessibility). Seule une partie des problèmes d'accessibilité peut être détectée automatiquement. Il est donc conseillé d'effectuer un test manuel."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ces éléments concernent des zones qu'un outil de test automatique ne peut pas couvrir. Consultez notre guide sur la [réalisation d'un examen d'accessibilité](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accessibilité"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer la lisibilité de votre contenu."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contraste"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer l'interprétation de votre contenu en fonction des différents paramètres régionaux choisis par les utilisateurs."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisation et localisation"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer la sémantique des éléments de contrôle de votre application. Vous optimiserez ainsi l'expérience des utilisateurs de technologies d'assistance, comme les lecteurs d'écran."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Noms et étiquettes"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer la navigation au clavier de votre application."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigation"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Servez-vous de ces indications pour améliorer l'expérience de lecture des listes ou tableaux de données en utilisant une technologie d'assistance, comme un lecteur d'écran."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tableaux et listes"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Bonnes pratiques"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Les budgets de performances établissent des normes sur les performances de votre site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Au niveau des budgets"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Plus d'informations sur les performances de votre application. Ces chiffres n'ont pas d'[incidence directe](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) sur le score lié aux performances."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostic"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "L'aspect le plus essentiel des performances est la rapidité avec laquelle les pixels sont affichés à l'écran. Statistiques clés : First Contentful Paint, First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Amélioration de First Paint"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ces suggestions peuvent contribuer à charger votre page plus rapidement. En revanche, elles n'ont pas d'[incidence directe](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) sur le score lié aux performances."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Opportunités"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Statistiques"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Améliorez l'expérience globale de chargement, afin que la page soit réactive et disponible dès que possible. Statistiques clés : délai avant interactivité, indice de vitesse"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Améliorations générales"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performances"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Ces contrôles permettent de vérifier que les conditions requises pour les progressive web apps sont remplies. [Découvrez-en davantage](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ces contrôles font partie des [vérifications de base de la checklist PWA](https://developers.google.com/web/progressive-web-apps/checklist), mais ne sont pas exécutés automatiquement par Lighthouse. Même s'ils n'ont pas d'influence sur votre score, il est important de les effectuer manuellement."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive web app"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rapide et fiable"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Possibilités d'installation"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimisation PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Ces vérifications vous permettent de vous assurer que votre page est optimisée pour le classement dans les résultats sur les moteurs de recherche. Lighthouse ne vérifie pas certains facteurs supplémentaires susceptibles d'avoir un impact sur votre classement dans les moteurs de recherche. [En savoir plus](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Exécutez ces outils de validation supplémentaires sur votre site pour vérifier les bonnes pratiques de SEO complémentaires."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Rédigez votre code HTML de sorte à autoriser les robots d'exploration à analyser le contenu de votre application."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Bonnes pratiques relatives au contenu"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Pour que votre contenu apparaisse dans les résultats de recherche, les robots d'exploration doivent accéder à votre application."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Exploration et indexation"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Assurez-vous que vos pages sont adaptées aux mobiles, afin que les utilisateurs n'aient pas besoin de pincer l'écran ni de zoomer pour lire votre contenu. [En savoir plus](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Adapté aux mobiles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache de la valeur TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Emplacement"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nom"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Requêtes"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Type de ressource"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Taille"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Temps passé"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Taille de transfert"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Économies potentielles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Économies potentielles"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Économies potentielles de {wastedBytes, number, bytes} Ko"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Économies potentielles de {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Police de caractères"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Image"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Contenu multimédia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Autre"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Feuille de style"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tiers"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Un problème est survenu lors de l'enregistrement de la trace du chargement de votre page. Veuillez relancer Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Expiration du délai pendant la tentative de connexion initiale du protocole du débogueur."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome n'a collecté aucune capture d'écran pendant le chargement de la page. Veuillez vous assurer que du contenu est visible sur la page, puis essayez de relancer Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Les serveurs DNS n'ont pas pu résoudre le domaine fourni."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Une erreur s'est produite lors de la collecte de la ressource {artifactName} requise : {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Une erreur Chrome interne s'est produite. Veuillez redémarrer Chrome et essayer de relancer Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "La ressource {artifactName} nécessaire n'a pas été collectée."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse n'a pas pu charger correctement la page que vous avez demandée. Assurez-vous de tester la bonne URL et vérifiez que le serveur répond correctement à toutes les requêtes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse n'a pas pu charger correctement l'URL que vous avez demandée, car la page a cessé de répondre."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "L'URL que vous avez fournie n'est pas associée à un certificat de sécurité valide. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Le chargement de la page dans Chrome a été bloqué et remplacé par un écran interstitiel. Assurez-vous de tester la bonne URL et vérifiez que le serveur répond correctement à toutes les requêtes."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse n'a pas pu charger correctement la page que vous avez demandée. Assurez-vous de tester la bonne URL et vérifiez que le serveur répond correctement à toutes les requêtes. (Détails : {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse n'a pas pu charger correctement la page que vous avez demandée. Assurez-vous de tester la bonne URL et vérifiez que le serveur répond correctement à toutes les requêtes. (Code d'état : {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Le chargement de la page a pris trop de temps. Veuillez suivre les indications du rapport pour réduire le temps de chargement de la page, puis essayez de relancer Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Le délai d'attente de la réponse du protocole DevTools est arrivé à expiration. (Méthode : {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Le délai alloué à la récupération des ressources a été atteint"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "L'URL que vous avez fournie ne semble pas valide."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Afficher les audits"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navigation initiale"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latence de chemin d'accès critique maximale :"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Erreur"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Erreur de rapport : pas d'information d'audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Données de test"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analyse [Lighthouse](https://developers.google.com/web/tools/lighthouse/) de la page actuelle sur un réseau mobile émulé. Les valeurs sont estimées et peuvent varier."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Autres éléments à vérifier manuellement"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Non applicable"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Opportunité"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estimation des économies"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Audits réussis"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Réduire l'extrait"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Développer l'extrait"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Afficher les ressources tierces"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Cette exécution de Lighthouse a rencontré des problèmes :"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Les valeurs sont estimées et peuvent varier. Le score lié aux performances [ne repose que sur ces statistiques](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Réussite des audits, mais avec des avertissements"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Avertissements : "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Vous pouvez envisager d'importer votre GIF dans un service qui permettra de l'intégrer dans une vidéo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installez un [plug-in WordPress de chargement différé](https://wordpress.org/plugins/search/lazy+load/) pour différer le chargement des images qui ne sont pas à l'écran, ou remplacez le thème par un autre qui offre cette fonctionnalité. Vous pouvez également envisager d'utiliser [le plug-in AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Divers plug-ins WordPress peuvent vous aider à [aligner des éléments critiques](https://wordpress.org/plugins/search/critical+css/) ou à [différer le chargement des ressources moins importantes](https://wordpress.org/plugins/search/defer+css+javascript/). Gardez en tête qu'à cause des optimisations fournies par ces plug-ins, certaines fonctionnalités de votre thème ou de vos plug-ins peuvent cesser de fonctionner. Vous devrez donc probablement modifier le code."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Les thèmes, les plug-ins et les spécifications du serveur sont autant d'éléments qui influent sur le temps de réponse du serveur. Vous pouvez envisager d'utiliser un thème plus optimisé ou un plug-in d'optimisation plus performant, ou bien de mettre à niveau votre serveur."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Vous pouvez envisager d'afficher des extraits dans vos listes d'articles (par exemple en utilisant la balise \"more\"), de réduire le nombre d'articles affichés dans une page donnée, de répartir vos articles longs sur plusieurs pages ou d'utiliser un plug-in qui charge de façon différée les commentaires."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Un certain nombre de [plug-ins WordPress](https://wordpress.org/plugins/search/minify+css/) peuvent accélérer l'affichage de votre site en concaténant, en minimisant et en compressant vos styles. Si possible, utilisez un processus de build pour réaliser cette minimisation en amont."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Un certain nombre de [plug-ins WordPress](https://wordpress.org/plugins/search/minify+javascript/) peuvent accélérer l'affichage de votre site en concaténant, en minimisant et en compressant vos scripts. Si possible, utilisez un processus de build pour réaliser cette minimisation en amont."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Vous pouvez envisager de réduire le nombre de [plug-ins WordPress](https://wordpress.org/plugins/) qui chargent des feuilles de style CSS inutilisées dans votre page, ou désactiver certains de ces plug-ins. Pour déterminer les plug-ins qui ajoutent des feuilles de style CSS superflues, exécutez une [couverture de code](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) dans Chrome DevTools. Vous pouvez identifier le thème ou le plug-in responsable à partir de l'URL de la feuille de style. Recherchez les plug-ins pour lesquels un grand nombre de feuilles de style présentent beaucoup d'éléments en rouge dans la couverture de code. Un plug-in ne doit mettre une feuille de style en file d'attente que si elle est effectivement utilisée dans la page."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Vous pouvez envisager de réduire le nombre de [plug-ins WordPress](https://wordpress.org/plugins/) qui chargent des scripts JavaScript inutilisés dans votre page, ou désactiver certains de ces plug-ins. Pour déterminer les plug-ins qui ajoutent des scripts JavaScript superflus, exécutez une [couverture de code](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) dans Chrome DevTools. Vous pouvez identifier le thème ou le plug-in responsable à partir de l'URL du script. Recherchez les plug-ins pour lesquels un grand nombre de scripts présentent beaucoup d'éléments en rouge dans la couverture de code. Un plug-in ne doit mettre un script en file d'attente que s'il est effectivement utilisé dans la page."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "En savoir plus sur la [mise en cache dans le navigateur dans WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Vous pouvez envisager d'utiliser un [plug-in WordPress d'optimisation d'image](https://wordpress.org/plugins/search/optimize+images/) pour compresser vos images sans dégrader leur qualité."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Importez des images directement via la [bibliothèque multimédia](https://codex.wordpress.org/Media_Library_Screen) pour vous assurer que les tailles d'images requises sont disponibles. Ensuite, insérez-les depuis la bibliothèque multimédia ou utilisez le widget d'image pour vous assurer que les tailles d'images optimales sont utilisées (y compris celles pour les points d'arrêt réactifs). Évitez d'utiliser les images `Full Size`, sauf si les dimensions sont adéquates pour l'utilisation prévue. [En savoir plus](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Vous pouvez activer la compression du texte dans la configuration de votre serveur Web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Vous pouvez envisager d'utiliser un [plug-in](https://wordpress.org/plugins/search/convert+webp/) ou un service qui convertit automatiquement les images que vous importez dans un format optimal."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/he.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/he.json
new file mode 100644
index 00000000000..87ba0f7c736
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/he.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "מקשי גישה מאפשרים למשתמשים להתמקד במהירות בחלק מסוים בדף. כדי לאפשר ניווט תקין, כל מקש גישה צריך להיות ייחודי. [מידע נוסף](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "יש ערכי `[accesskey]` שאינם ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` הערכים ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "כל ARIA `role` תומכת בקבוצת משנה ספציפית של `aria-*` מאפיינים. חוסר התאמה בין המאפיינים הופך אותם `aria-*` ללא חוקיים. [מידע נוסף](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "יש מאפייני `[aria-*]` שלא תואמים לתפקידים שלהם"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "מאפייני ה-`[aria-*]`‎ תואמים לתפקידים שלהם"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "חלק מתפקידי ה-ARIA כוללים מאפיינים נדרשים שמתארים לקוראי המסך את מצב הרכיב. [מידע נוסף](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "יש רכיבים מסוג `[role]` שאין להם את כל מאפייני ה-`[aria-*]` הנדרשים"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "לכל הרכיבים מסוג `[role]` יש את כל מאפייני ה-`[aria-*]` הדרושים"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "תפקידי הורה מסוימים של ARIA צריכים לכלול תפקידי צאצא ספציפיים כדי לבצע את פונקציות הנגישות שלהם. [מידע נוסף](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "ברכיבים עם `[role]` של ARIA שדורשים מצאצאים לכלול `[role]` ספציפי, חסרים חלק מהצאצאים הנדרשים האלה, או שכולם חסרים בהם."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "ברכיבים עם `[role]` של ARIA שדורשים מצאצאים לכלול `[role]` ספציפי, קיימים כל הצאצאים הנדרשים."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "חלק מתפקידי הצאצא מסוג ARIA חייבים להיכלל בין תפקידי הורה ספציפיים כדי למלא באופן תקין את פונקציות הנגישות שלהם. [מידע נוסף](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "מאפייני `[role]` לא נמצאים בתוך רכיב ההורה הנדרש שלהם"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "רכיבים מסוג `[role]` נמצאים בתוך רכיב ההורה הנדרש שלהם"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "תפקידי ARIA חייבים לכלול ערכים חוקיים כדי לבצע את פונקציות הנגישות שלהם. [מידע נוסף](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "יש ערכי `[role]` לא חוקיים"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "ערכי ה-`[role]` חוקיים"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "טכנולוגיות לנגישות, כמו קוראי מסך, לא יכולות לפענח מאפייני ARIA שהערכים שלהם לא חוקיים. [מידע נוסף](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "למאפייני ‎`[aria-*]`‎ אין ערכים חוקיים"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "למאפייני ה-`[aria-*]` יש ערכים חוקיים"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "טכנולוגיות לנגישות, כמו קוראי מסך, לא יכולות לפענח מאפייני ARIA עם שמות לא חוקיים. [מידע נוסף](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "יש מאפייני `[aria-*]` שאינם חוקיים או שכוללים שגיאות איות"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "מאפייני ה-`[aria-*]` חוקיים ולא כוללים שגיאות איות"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "כתוביות מאפשרות לאנשים חרשים ולקויי שמיעה להשתמש ברכיבי אודיו, ומספקות מידע קריטי, כמו זהות הדובר, המילים שנאמרות ומידע אחר שאינו מועבר בדיבור. [מידע נוסף](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "יש רכיבי `<audio>` שחסר בהם רכיב `<track>` עם `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "רכיבי `<audio>` מכילים רכיב `<track>` עם `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "רכיבים שנכשלו בבדיקה"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "כשאין ללחצן שם נגיש, קוראי מסך אומרים את המילה \"לחצן\", ובמצב כזה אנשים שמסתמכים על קוראי מסך יתקשו להשתמש בלחצן. [מידע נוסף](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "ללחצנים אין שמות ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "ללחצנים יש שם נגיש"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "הוספה של דרכים לעקיפת תוכן שחוזר על עצמו מאפשרת לאנשים שמשתמשים במקלדת לנווט בדף בצורה יעילה יותר. [מידע נוסף](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "הדף לא כולל כותרת, קישור לדילוג או קטע שמסומן כ-landmark"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "הדף כולל כותרת, קישור לדילוג או קטע שמסומן כ-landmark"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "משתמשים רבים מתקשים לקרוא טקסט עם ניגודיות נמוכה, או לא מסוגלים לקרוא אותו. [מידע נוסף](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "יחס הניגודיות של צבעי הרקע והחזית אינו מספיק."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "יש יחס ניגודיות מספיק בין צבעי הרקע והחזית"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "כשרשימות של הגדרות לא מסומנות כראוי, קוראי מסך עשויים לספק פלט מבלבל או לא מדויק. [מידע נוסף](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "יש רכיבי `<dl>` שלא מכילים רק רכיבי `<script>` או `<template>`, או קבוצות `<dt>` ו-`<dd>` עם סדר תקין."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "רכיבי `<dl>` מכילים רק רכיבי `<script>` או `<template>`, או קבוצות `<dt>` ו-`<dd>` עם סדר תקין."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "פריטים ברשימות של הגדרות (`<dt>` ו-`<dd>`) צריכים להיות תחומים בתוך רכיב הורה מסוג `<dl>` כדי שקוראי מסך יוכלו להקריא אותם בצורה נכונה. [מידע נוסף](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "יש פריטים ברשימות של הגדרות שלא תחומים בין רכיבי `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "פריטים ברשימות של הגדרות מוצבים בין רכיבי `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "הכותרת מספקת סקירה כללית של הדף למשתמשים הנעזרים בקוראי מסך. בנוסף, משתמשים של מנועי חיפוש מסתמכים במידה רבה על הכותרת כדי להבין אם הדף רלוונטי לחיפוש שלהם. [מידע נוסף](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "למסמך אין רכיב `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "המסמך מכיל רכיב `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "הערך של מאפיין id חייב להיות ייחודי כדי למנוע מטכנולוגיות לנגישות להתעלם ממופעים אחרים. [מידע נוסף](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "יש בדף מאפייני `[id]` שאינם ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "מאפייני ה-`[id]` בדף הם ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "משתמשים הנעזרים בקוראי מסך מסתמכים על כותרות של מסגרות כדי להבין מה תוכן המסגרות. [מידע נוסף](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "לרכיבי `<frame>` או `<iframe>` אין מאפיין title"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "לרכיבי `<frame>` או `<iframe>` יש מאפיין title"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "אם בדף לא מצוין מאפיין lang, קורא המסך יפעל כאילו שהדף כתוב בשפת ברירת המחדל שהמשתמש בחר במהלך הגדרת קורא המסך. אם שפת הדף שונה משפת ברירת המחדל, ייתכן שקורא המסך לא יקרא בצורה נכונה את הטקסט שבדף. [מידע נוסף](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "לרכיב `<html>` אין רכיב `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "לרכיב `<html>` יש מאפיין `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "ציון של [שפת BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) חוקית עוזר לקוראי מסך להקריא טקסט בצורה נכונה. [מידע נוסף](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "לרכיב `<html>` אין ערך חוקי עבור המאפיין `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "לרכיב `<html>` יש ערך חוקי עבור המאפיין `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "רכיבים אינפורמטיביים צריכים לכלול טקסט חלופי קצר ותיאורי. אפשר להתעלם מרכיבי עיצוב עם מאפיין alt ריק. [מידע נוסף](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "יש רכיבי תמונה ללא מאפייני `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "לרכיבי תמונה יש מאפייני `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "כשתמונה משמשת כלחצן `<input>`, הוספה של טקסט חלופי יכולה לעזור למשתמשים הנעזרים בקוראי מסך להבין מה הלחצן עושה. [מידע נוסף](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "יש רכיבי `<input type=\"image\">` שאין להם טקסט `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "לרכיבים מסוג `<input type=\"image\">` יש טקסט `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "תוויות עוזרות לוודא ששמות של פקדי טפסים מוקראים באופן תקין על ידי טכנולוגיות לנגישות, כמו קוראי מסך. [מידע נוסף](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "לא שויכו תוויות אל רכיבי טופס"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "לרכיבי טופס יש תוויות המשויכות אליהם"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "טבלה המשמשת לקביעת פריסה אינה יכולה לכלול רכיבי נתונים, כמו הרכיב th, הרכיב ‏caption או המאפיין summary, כי הם עשויים ליצור חוויה מבלבלת עבור משתמשים הנעזרים בקורא מסך. [מידע נוסף](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "ברכיבי `<table>` להצגה, אין הימנעות משימוש ב-`<th>`, ב-`<caption>` או במאפיין `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "רכיבי `<table>` להצגה לא מכילים `<th>`, `<caption>` או את המאפיין `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "כשהטקסט של הקישור מובן וייחודי ואפשר להתמקד בו, משתמשים שנעזרים בקורא מסך נהנים מחוויית ניווט משופרת. מצב זה נכון גם לגבי טקסט חלופי של תמונות כשנעשה בהן שימוש כקישורים. [מידע נוסף](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "לקישורים אין שמות ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "לקישורים יש שמות ייחודיים"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "קוראי מסך מקריאים רשימות בצורה מסוימת. שמירה על מבנה רשימות תקין מאפשרת הקראה תקינה על ידי קורא המסך. [מידע נוסף](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "הרשימות לא מכילות רק רכיבי `<li>` ורכיבים שתומכים בסקריפט (`<script>` ו- `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "הרשימות מכילות רק רכיבי `<li>` ורכיבים שתומכים בסקריפט (`<script>` ו-`<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "כדי שקוראי מסך יוכלו לקרוא כראוי פריטים ברשימות, (`<li>`) הם צריכים להופיע בין רכיבי הורה מסוג `<ul>` או `<ol>`. [מידע נוסף](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "יש פריטים ברשימות (`<li>`) שלא נמצאים בין רכיבי הורה של `<ul>` או `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "פריטים ברשימות (`<li>`) מופיעים בין רכיבי הורה `<ul>` או `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "משתמשים לא מצפים לרענון אוטומטי של הדף, ושימוש ברענון כזה יחזיר את ההתמקדות אל ראש הדף. מצב כזה יכול ליצור חוויה מתסכלת או מבלבלת. [מידע נוסף](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "המסמך מכיל `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "המסמך לא כולל שימוש ב-`<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "השבתת האפשרות להגדיל את תצוגת התוכן יוצרת בעיה עבור משתמשים עם ליקויי ראייה שנוהגים להגדיל את המסך כדי לראות היטב את תוכן דף האינטרנט. [מידע נוסף](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "נעשה שימוש ב-`[user-scalable=\"no\"]` ברכיב `<meta name=\"viewport\">`, או שערך המאפיין `[maximum-scale]` קטן מ-5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "לא נעשה שימוש ב-`[user-scalable=\"no\"]` ברכיב `<meta name=\"viewport\">` וערך המאפיין `[maximum-scale]` לא קטן מ-5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "קוראי מסך לא יכולים לתרגם תוכן שאינו טקסט. הוספה של טקסט חלופי לרכיבי `<object>` עוזרת להבהיר את המשמעות כשמשתמשים בקוראי מסך. [מידע נוסף](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "יש רכיבי `<object>` שאין להם טקסט `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "לרכיבים מסוג `<object>` יש טקסט `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "ערך גדול מ-0 מרמז על סדר ניווט מפורש. זו אפשרות תקינה מבחינה טכנית, אבל במקרים רבים היא גורמת לחוויה מתסכלת עבור משתמשים שמסתמכים על טכנולוגיות לנגישות. [מידע נוסף](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "לחלק מהרכיבים יש ערך `[tabindex]` גדול מ-0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "לאף רכיב אין ערך `[tabindex]` גדול מ-0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "קוראי מסך כוללים תכונות שמקלות את הניווט בטבלאות. כשתאי `<td>` שמשתמשים במאפיין `[headers]` מתייחסים רק לתאים אחרים באותה טבלה, משתמשים הנעזרים בקוראי מסך יכולים ליהנות מחוויה טובה יותר. [מידע נוסף](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "תאים ברכיב `<table>` שמשתמשים במאפיין `[headers]`, מתייחסים לרכיב `id` שלא נמצא באותה טבלה."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "תאים ברכיב `<table>` שמשתמשים במאפיין `[headers]`, מתייחסים לתאים אחרים באותה הטבלה."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "קוראי מסך כוללים תכונות שמקלות את הניווט בטבלאות. כשכותרות של טבלאות מתייחסות תמיד לקבוצה כלשהי של תאים, משתמשים הנעזרים בקורא מסך יכולים ליהנות מחוויה טובה יותר. [מידע נוסף](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "יש רכיבי `<th>` ורכיבים עם `[role=\"columnheader\"/\"rowheader\"]` שאין להם את תאי הנתונים שהם מתארים."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "לרכיבי `<th>` ולרכיבים עם `[role=\"columnheader\"/\"rowheader\"]` יש תאי נתונים שהם מתארים."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "ציון של [שפת BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) חוקית ברכיבים עוזר להבטיח הגייה נכונה של הטקסט על ידי קורא המסך. [מידע נוסף](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "יש מאפייני `[lang]` שאין להם ערך חוקי"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "למאפייני `[lang]` יש ערך חוקי"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "כשסרטון כולל כתוביות, המידע שהוא כולל נגיש יותר למשתמשים חרשים ולקויי שמיעה. [מידע נוסף](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "יש רכיבי `<video>` שלא מכילים רכיב `<track>` עם `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "רכיבי `<video>` מכילים רכיב `<track>` עם `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "בסרטונים, תיאורים קוליים מספקים מידע רלוונטי שאי אפשר להבין מהדיאלוג. למשל, הבעות פנים ונופים. [מידע נוסף](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "יש רכיבי `<video>` שלא מכילים רכיב `<track>` עם `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "רכיבי `<video>` מכילים רכיב `<track>` עם `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "כדי שהדף יוצג למשתמשים באופן אידיאלי ב-iOS לאחר הוספת Progressive Web App למסך הבית, מומלץ להגדיר `apple-touch-icon`. המאפיין חייב להפנות לתמונת PNG לא שקופה בפורמט ריבוע בגודל 192 פיקסלים (או 180 פיקסלים). [מידע נוסף](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "הדף לא מכיל `apple-touch-icon` חוקי"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` לא עדכני; עדיף להשתמש ב-`apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "האתר מכיל `apple-touch-icon` חוקי"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "תוספים ל-Chrome השפיעו לרעה על ביצועי הטעינה של הדף הזה. כדאי לבדוק את הדף במצב גלישה בסתר או באמצעות פרופיל Chrome שאינו כולל תוספים."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "הערכת סקריפט"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "ניתוח סקריפט"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "זמן כולל של CPU (יחידת עיבוד מרכזית)"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "כדאי לשקול את האפשרות לקצר את הזמן הדרוש לניתוח, הידור וביצוע של JS. לשם כך כדאי להשתמש במטענים ייעודיים (payloads) קטנים יותר של JS. [מידע נוסף](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "יש לקצר את זמן הביצוע של JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "זמן ביצוע של JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "קובצי GIF גדולים לא מעבירים אנימציות בצורה יעילה. כדי לצמצם את מספר הבייטים שמועברים ברשת, במקום קובצי GIF כדאי לשקול את האפשרות להשתמש בסרטוני MPEG4/WebM בשביל אנימציות ובקובצי PNG/WebP בשביל תמונות סטטיות. [מידע נוסף](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "יש להשתמש בפורמטים של וידאו כדי להציג תוכן אנימציה"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "כדי לקצר את הזמן עד לפעילות מלאה, כדאי לשקול לבצע טעינה הדרגתית של תמונות מוסתרות ותמונות שלא מופיעות מיד במסך, כך שייטענו רק אחרי סיום הטעינה של כל המשאבים הקריטיים. [מידע נוסף](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "יש לעכב טעינה של תמונות שאינן מופיעות במסך"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "משאבים חוסמים את הצגת התמונה הראשונית של הדף במסך כדאי לשקול את האפשרות לספק תוכן JS/CSS קריטי באופן מוטבע ולדחות את הטעינה של כל תוכן ה-JS/הסגנונות שאינם קריטיים. [מידע נוסף](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "יש להימנע ממשאבים שחוסמים עיבוד"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "מטענים ייעודיים (payload) בנפח גדול המועברים ברשת עולים למשתמשים כסף ולעתים קרובות מאריכים את זמני הטעינה. [מידע נוסף](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "הגודל הכולל היה ‎{totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "יש להימנע מהעברה של מטענים ייעודיים ענקיים (payload) ברשת"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "נמנע מהעברה של מטענים ייעודיים ענקיים (payload) ברשת"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "הקטנה של קובצי CSS יכולה לצמצם את הגודל של מטענים ייעודיים (payloads) שמועברים ברשת. [מידע נוסף](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "יש להקטין קובצי CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "הקטנה של קובצי JavaScript יכולה לצמצם את המטען הייעודי (payload) ולקצר את משך הזמן הנדרש לניתוח סקריפט. [מידע נוסף](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "יש לקצר את קוד JavaScript למינימום ההכרחי"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "יש להסיר מגיליונות הסגנונות כללים שאינם בשימוש ולדחות את הטעינה של רכיבי CSS שאינם חלק מהתוכן בחלק העליון והקבוע. הפעולה הזו תצמצם צריכה בלתי נחוצה של בייטים כתוצאה מפעילות הרשת. [מידע נוסף](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "יש להסיר CSS שאינו בשימוש"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "יש להסיר JavaScript שאינו בשימוש כדי לצמצם צריכת בייטים על-ידי פעילות ברשת."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "יש להסיר JavaScript שאינו בשימוש"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "משך חיים ארוך של מטמון יכול לזרז את הביקורים החוזרים בדף. [מידע נוסף](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{נמצא משאב אחד}two{נמצאו # משאבים}many{נמצאו # משאבים}other{נמצאו # משאבים}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "יש להציג נכסים סטטיים בעזרת מדיניות מטמון יעילה"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "יש להשתמש במדיניות מטמון יעילה בנכסים סטטיים"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "תמונות שעברו אופטימיזציה נטענות מהר יותר וצורכות פחות נתונים בחבילת הגלישה. [מידע נוסף](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "יש לקודד תמונות בצורה יעילה"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "הצגת תמונות שהגודל שלהן הוגדר בצורה נכונה עוזרת לחסוך בניצול חבילת הגלישה ולקצר את זמן הטעינה. [מידע נוסף](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "יש להגדיר את גודל התמונות בצורה נכונה"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "הצגת משאבים המבוססים על טקסט צריכה להתבצע עם דחיסה (gzip‏, deflate או brotli) כדי לצמצם את כמות הבייטים שמועברים ברשת. [מידע נוסף](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "יש להפעיל דחיסת טקסט"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "לעתים קרובות, פורמטים של תמונות כמו JPEG 2000‏, JPEG XR ו-WebP מספקים דחיסה טובה יותר מאשר PNG או JPEG. הדחיסה המשופרת מקצרת את זמן ההורדות ומצמצמת את צריכת הנתונים. [מידע נוסף](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "יש להציג תמונות בפורמטים עדכניים"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "אם הרוחב של תוכן האפליקציה לא תואם לרוחב של אזור התצוגה, ייתכן שלא בוצעה אופטימיזציה לאפליקציה שלך עבור מסכים של ניידים. [מידע נוסף](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "גודל אזור התצוגה של {innerWidth} פיקסלים לא תואם לגודל החלון של {outerWidth} פיקסלים."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "הגודל של התוכן הוגדר בצורה לא תקינה עבור אזור התצוגה"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "הגודל של התוכן הוגדר בצורה תקינה עבור אזור התצוגה"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "בקטע 'שרשראות בקשה קריטיות' שבהמשך מוצגים המשאבים שנטענים עם עדיפות גבוהה. כדי לשפר את מהירות טעינת הדף, מומלץ לקצר את השרשראות, להקטין את גודל ההורדה של משאבים או לעכב את ההורדה של משאבים לא נחוצים. [מידע נוסף](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{נמצאה שרשרת אחת}two{נמצאו # שרשראות}many{נמצאו # שרשראות}other{נמצאו # שרשראות}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "יש לצמצם את העומק של בקשות קריטיות"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "הוצאה משימוש/אזהרה"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "שורה"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "רכיבי API שהוצאו משימוש יוסרו בסופו של דבר מהדפדפן. [מידע נוסף](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{נמצאה אזהרה אחת}two{נמצאו # אזהרות}many{נמצאו # אזהרות}other{נמצאו # אזהרות}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "הדף מכיל רכיבי API שהוצאו משימוש"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "אין רכיבי API שהוצאו משימוש"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache הוצא משימוש. [מידע נוסף](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "בשימוש: \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "נעשה שימוש ב-Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "לא נעשה שימוש ב-Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "ציון של doctype מונע מהדפדפן לעבור למצב תאימות (quirks mode). [מידע נוסף](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "שם של Doctype חייב להיות המחרוזת `html` עם אותיות קטנות"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "המסמך חייב להכיל doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId אמור להיות מחרוזת ריקה"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId אמור להיות מחרוזת ריקה"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "ה-doctype של הדף אינו מוגדר ל-HTML, ולכן הופעל מצב תאימות (quirks mode)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "ה-doctype של הדף מוגדר ל-HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "רכיב"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "נתון סטטיסטי"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "ערך"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "מהנדסי דפדפנים ממליצים לכלול פחות מכ-1,500 רכיבי DOM בדפים. התצורה המועדפת היא עץ בעומק של פחות מ-32 רכיבים, ופחות מ-60 רכיבי צאצא לכל רכיב הורה. DOM גדול עשוי להגדיל את צריכת משאבי הזיכרון, להאריך את הזמן הדרוש ל[חישובי סגנונות](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) ולהוביל ל[זרימה חוזרת של פריסות](https://developers.google.com/speed/articles/reflow) שגוזלת משאבים יקרים. [מידע נוסף](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{רכיב אחד}two{# רכיבים}many{# רכיבים}other{# רכיבים}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "יש להימנע מ-DOM גדול מדי"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "עומק DOM מרבי"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "סך רכיבי DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "מקסימום רכיבי צאצא"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "נמנע מ-DOM גדול מדי"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "יעד"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "כדי לשפר את הביצועים ולמנוע פגיעויות המסכנות את האבטחה, יש להוסיף `rel=\"noopener\"` או `rel=\"noreferrer\"` לקישורים חיצוניים. [מידע נוסף](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "הדף מכיל קישורים לא בטוחים ליעדים ממקורות שונים"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "כל הקישורים ליעדים ממקורות שונים בטוחים לשימוש"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "לא ניתן לקבוע את יעד העוגן ({anchorHTML}). אם target=_blank לא משמש כהיפר-קישור, כדאי לשקול להסיר אותו."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "אתרים שמבקשים לקבל גישה למיקום של המשתמשים, בלי לציין הקשר, מעוררים אצל המשתמשים תחושת בלבול או חשדנות. במקום זאת, כדאי לשקול לקשר את הבקשות לפעולה של המשתמשים. [מידע נוסף](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "הדף מבקש הרשאות למיקום גאוגרפי במהלך טעינת הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "הדף לא מבקש הרשאות למיקום גאוגרפי במהלך טעינת הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "גרסה"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "זו ביקורת שמטרתה לזהות את כל ספריות ה-JavaScript החזיתיות בדף. [מידע נוסף](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "ספריות JavaScript שזוהו"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "אם החיבור איטי, סקריפטים חיצוניים המושתלים באופן דינמי דרך `document.write()` יכולים לעכב את טעינת הדף בעשרות שניות. [מידע נוסף](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "הדף כולל שימוש ב-`document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "לא נעשה שימוש ב-`document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "רמת החומרה הגבוהה ביותר"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "גרסת הספרייה"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "מספר הפגיעויות"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "סקריפטים של צד שלישי עשויים להכיל פגיעויות ידועות באבטחה, שתוקפים יכולים לזהות ולנצל בקלות. [מידע נוסף](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{זוהתה פגיעוּת אחת}two{זוהו # פגיעויות}many{זוהו # פגיעויות}other{זוהו # פגיעויות}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "הדף מכיל ספריות JavaScript חזיתיות בעלות פגיעויות ידועות באבטחה"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "גבוהה"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "נמוכה"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "בינונית"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "הדף לא מכיל ספריות JavaScript חזיתיות בעלות פגיעויות ידועות באבטחה"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "אתרים שמבקשים לשלוח התראות ללא הקשר מעוררים תחושת בלבול או חשדנות בקרב המשתמשים. במקום זאת, כדאי לשקול לקשר את הבקשות למחוות של המשתמשים. [מידע נוסף](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "הדף מבקש הרשאה להודעות במהלך טעינת הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "הדף לא מבקש הרשאה להתראות במהלך טעינת הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "רכיבים שנכשלו בבדיקה"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "מניעה של הדבקת סיסמאות פוגעת ביכולת לקיים מדיניות אבטחה טובה. [מידע נוסף](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "בדף הזה משתמשים לא יכולים להדביק תוכן מועתק לתוך שדות של סיסמאות"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "בדף הזה משתמשים יכולים להדביק תוכן מועתק לתוך שדות של סיסמאות"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "פרוטוקול"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "ל-HTTP/2 יש הרבה יתרונות על-פני HTTP/1.1, ביניהם כותרות בינאריות, ריבוב והקצאות שרת מוקדמות (Server Push). [מידע נוסף](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{בקשה אחת לא מולאה דרך HTTP/2}two{# בקשות לא מולאו דרך HTTP/2}many{# בקשות לא מולאו דרך HTTP/2}other{# בקשות לא מולאו דרך HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "לא נעשה שימוש ב-HTTP/2 עבור כל משאבי הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "נעשה שימוש ב-HTTP/2 עבור משאבי הדף"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "כדי לשפר את ביצועי הגלילה של הדף, מומלץ לשקול להוסיף סימון `passive` למעבדים של אירועי נגיעה וגלילה עם גלגל העכבר. [מידע נוסף](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "לא נעשה שימוש ברכיבי listener פסיביים לשיפור ביצועי הגלילה"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "נעשה שימוש ברכיבי listener פסיביים לשיפור ביצועי הגלילה"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "תיאור"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "שגיאות שנרשמו במסוף מצביעות על בעיות לא פתורות. הן עשויות להופיע בעקבות כשל בבקשות ברשת או בעיות אחרות בדפדפן. [מידע נוסף](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "נרשמו שגיאות דפדפן במסוף"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "לא נרשמו במסוף שגיאות דפדפן"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "שימוש בתכונת תצוגת הגופן של CSS מבטיח שהטקסט מוצג למשתמש בזמן טעינה של גופני webfont. [מידע נוסף](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "יש לוודא שטקסט ממשיך להופיע במהלך טעינת webfont"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "כל הטקסט ממשיך להופיע במהלך טעינות של webfont"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "מערכת Lighthouse לא הצליחה לבדוק באופן אוטומטי את ערך תצוגת הגופן של כתובת ה-URL הבאה: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "יחס גובה-רוחב (בפועל)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "יחס גובה-רוחב (בתצוגה)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "מידות התצוגה של התמונה צריכות להתאים ליחס הגובה-רוחב הטבעי. [מידע נוסף](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "יש תמונות עם יחס גובה-רוחב שגוי"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "התמונות מוצגות ביחס גובה-רוחב נכון"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "נתוני הגודל של תמונה לא חוקיים: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "הדפדפנים יכולים לבקש ממשתמשים באופן יזום להוסיף את האפליקציה שלך אל מסך הבית שלהם, פעולה שמגדילה את הסיכוי להשגת מעורבות גבוהה יותר. [מידע נוסף](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "המניפסט של אפליקציית האינטרנט לא עומד בדרישות יכולת ההתקנה"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "המניפסט של אפליקציית האינטרנט עומד בדרישות יכולת ההתקנה"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "כתובת URL של בקשה לא מאובטחת"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "יש להגן באמצעות פרוטוקול HTTPS על כל האתרים, אפילו אם הם לא מכילים נתונים רגישים. פרוטוקול HTTPS מונע מפורצים לעשות שימוש לרעה בתקשורת המתקיימת בין האפליקציה למשתמשים או לצותת לה. השימוש בפרוטוקול הזה הוא דרישה מוקדמת של HTTP/2 ושל רכיבי ה-API של רבות מפלטפורמות האינטרנט החדשות. [מידע נוסף](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{נמצאה בקשה לא מאובטחת אחת}two{נמצאו # בקשות לא מאובטחות}many{נמצאו # בקשות לא מאובטחות}other{נמצאו # בקשות לא מאובטחות}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "לא נעשה שימוש ב-HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "שימוש ב-HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "כשהדף נטען במהירות ברשת סלולרית, חוויית המשתמש איכותית. [מידע נוסף](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "פעילות מלאה תוך {timeInMs, number, seconds} שנ'"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "הזמן עד לפעילות מלאה בהדמיית רשת סלולרית הוא {timeInMs, number, seconds} שניות"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "הדף שלך נטען לאט מדי ולא מגיע לפעילות מלאה תוך 10 שניות. כדי ללמוד כיצד לבצע שיפורים, מומלץ לעיין בהזדמנויות ובניתוחים שמופיעים בקטע \"ביצועים\"."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "טעינת הדף לא מהירה מספיק ברשתות סלולריות"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "טעינת הדף ברשתות סלולריות מהירה מספיק"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "קטגוריה"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "כדאי לשקול את האפשרות לקצר את הזמן הדרוש לניתוח, הידור וביצוע של JS. לשם כך, כדאי להשתמש במטענים ייעודיים (payloads) קטנים יותר של JS. [מידע נוסף](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "צריך לצמצם את העבודה על התהליכון הראשי"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "מצמצם את העבודה על התהליכון הראשי"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "כדי להגדיל את היקף החשיפה לכמה שיותר משתמשים, האתרים צריכים לעבוד בכל הדפדפנים המובילים. [מידע נוסף](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "האתר עובד בדפדפנים שונים"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "יש לוודא שניתן לבצע קישור עמוק לדפים נפרדים דרך כתובת URL ושכתובות ה-URL ייחודיות, כדי שניתן יהיה לשתף אותן ברשתות חברתיות. [מידע נוסף](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "לכל דף יש כתובת URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "כשמקישים באפליקציה, התחושה של המעברים צריכה להיות מהירה, גם ברשת איטית. החוויה הזו היא אחד הגורמים החשובים לתפיסת הביצועים בעיני משתמשים. [מידע נוסף](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "מעברי הדפים לא מרגישים חסומים ברשת"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "זמן אחזור מוערך של קלט הוא אומדן של משך הזמן הנדרש לאפליקציה כדי להגיב לקלט של משתמש. הערך מצוין באלפיות שנייה ומתייחס ל-5 השניות העמוסות ביותר בטעינת הדף. אם זמן האחזור ארוך מ-50 אלפיות שנייה, ייתכן שהמשתמשים יבחינו בעיכוב בפעילות האפליקציה. [מידע נוסף](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "אומדן זמן האחזור של קלט"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "המדד 'הצגת תוכן ראשוני (FCP)' מציין את הזמן שבו הטקסט או התמונה הראשונים מוצגים. [מידע נוסף](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "הצגת התוכן הראשוני"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "הערך 'מצב ראשון של חוסר פעילות ב-CPU' מציין את הפעם הראשונה שבה התהליכון הראשי של הדף פנוי מספיק בשביל להגיב לקלט. [מידע נוסף](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "מצב ראשון של חוסר פעילות ב-CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "הערך 'הצגת התוכן העיקרי (FMP)' מציין מתי מוצג התוכן העיקרי של הדף. [מידע נוסף](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "הצגת התוכן העיקרי"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "הזמן עד לפעילות מלאה הוא משך הזמן שחולף עד שהדף מאפשר פעילות מלאה. [מידע נוסף](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "זמן עד לאינטראקטיביות"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "ההשהיה הפוטנציאלית המרבית שהמשתמשים יכולים לחוות לאחר קלט ראשוני היא משך הזמן (באלפיות שנייה) של המשימה הארוכה ביותר. [מידע נוסף](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "השהיה פוטנציאלית מרבית לאחר קלט ראשוני"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "מדד המהירות (Speed Index) מראה באיזו מהירות מוצג התוכן בדף [מידע נוסף](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "מדד מהירות (Speed Index)"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "משך הזמן המצטבר של כל פרקי הזמן מרגע הצגת התוכן הראשוני (FCP) ועד לפעילות מלאה, במקרים שבהם משך המשימה חורג מ-50 אלפיות שנייה. הערך מבוטא באלפיות שנייה."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "זמן החסימה הכולל"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "לזמני הלוך ושוב (RTT) ברשת יש השפעה גדולה על הביצועים. אם נדרש RTT ארוך בתקשורת עם מקור, זה סימן לכך שאפשר לשפר את הביצועים בעזרת שרתים שממוקמים קרוב יותר אל המשתמש. [מידע נוסף](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "זמני הלוך ושוב ברשת"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "זמני האחזור של שרתים יכולים להשפיע על ביצועי האינטרנט. אם נדרש זמן אחזור ארוך בתקשורת עם המקור, זה סימן לכך שהשרת עמוס או שביצועי הקצה העורפי שלו נמוכים. [מידע נוסף](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "זמני אחזור בקצה עורפי של שרת"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "קובץ שירות (service worker) מאפשר לאפליקציית האינטרנט שלך להיות אמינה יותר בתנאי רשת לא צפויים. [מידע נוסף](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` לא מגיב בסטטוס 200 כשהוא במצב לא מקוון"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` מגיב בסטטוס 200 כשהוא במצב לא מקוון"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "מערכת Lighthouse לא הצליחה לקרוא את `start_url` מהמניפסט. כתוצאה מכך, התבצעה הנחה ש-`start_url` היא כתובת ה-URL של המסמך. הודעת שגיאה: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "גובה החריגה מהתקציב"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "הכמות והגודל של בקשות ברשת צריכים להיות מתחת ליעדים שהוגדרו בתקציב הביצועים הרלוונטי. [מידע נוסף](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{בקשה אחת}two{# בקשות}many{# בקשות}other{# בקשות}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "תקציב ביצועים"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "אם כבר הגדרת HTTPS, יש לוודא שכל תנועת ה-HTTP מופנית אוטומטית ל-HTTPS כדי להפעיל תכונות רשת מאובטחות לכל המשתמשים שלך. [מידע נוסף](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "לא מפנה תנועת HTTP באופן אוטומטי אל HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "מפנה תנועת HTTP באופן אוטומטי אל HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "הפניות אוטומטיות מעכבות את טעינת הדף. [מידע נוסף](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "יש להימנע מהפניות אוטומטיות מרובות"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "כדי להגדיר תקציבים עבור הכמות והגודל של משאבי הדף, יש להוסיף קובץ budget.json. [מידע נוסף](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{בקשה אחת • ‎{byteCount, number, bytes} KB‏}two{# בקשות • ‎KB {byteCount, number, bytes}}many{# בקשות • ‎KB {byteCount, number, bytes}}other{# בקשות • ‎KB {byteCount, number, bytes}}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "יש לצמצם ככל האפשר את מספר הבקשות ואת גודל ההעברות"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "קישורים קנוניים מציעים את כתובת ה-URL שיש להציג בתוצאות החיפוש. [מידע נוסף](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "התנגשויות בין כתובות URL מרובות ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "הכתובת מפנה לדומיין אחר ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "כתובת אתר לא חוקית ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "הכתובת מפנה למיקום `hreflang` אחר ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "כתובת URL יחסית ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "מצביע אל כתובת ה-URL הבסיסית של הדומיין (דף הבית), במקום אל דף תוכן מתאים"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "למסמך אין `rel=canonical` חוקי"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "למסמך יש `rel=canonical` חוקי"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "גופן בגודל של פחות מ-12 פיקסלים הוא קטן מדי לקריאה: מבקרים עם מכשיר נייד ייאלצו לעשות תנועת צביטה של התקרבות לתצוגה על מנת לקרוא את הטקסט. ההמלצה היא שיותר מ-60% מהטקסט יהיה בגודל של 12 פיקסלים לפחות. [מידע נוסף](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "טקסט קריא: {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "הטקסט לא קריא כי לא בוצעה אופטימיזציית מטא תג של אזור התצוגה בשביל מסכים של ניידים."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "הגודל של {decimalProportion, number, extendedPercent} מהטקסט קטן מדי (מבוסס על דגימה של {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "מידות הגופן במסך מקשות על הקריאה"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "במסמך נעשה שימוש בגופן בגודל קריא"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "קישורי hreflang עוזרים למנועי חיפוש להבין איזו גרסה של הדף הם צריכים להציג בתוצאות החיפוש בשביל שפה מסוימת או אזור מסוים. [מידע נוסף](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "למסמך אין `hreflang` חוקי"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "למסמך יש `hreflang` חוקי"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "כשלדפים יש קוד מצב HTTP לא תקין, עשויות להיות שגיאות בהוספה שלהם לאינדקס. [מידע נוסף](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "לדף יש קוד מצב HTTP המצביע על בעיה"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "קוד מצב ה-HTTP של הדף הוא 'הצלחה'"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "מנועי חיפוש לא יכולים לכלול את הדפים בתוצאות החיפוש אם אין להם הרשאה לסרוק אותם. [מידע נוסף](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "הוספת הדף לאינדקס חסומה"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "הוספת הדף לאינדקס אינה חסומה"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "טקסט שמתאר את הקישורים עוזר למנועי חיפוש להבין במה עוסק התוכן. [מידע נוסף](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{נמצא קישור אחד}two{נמצאו # קישורים}many{נמצאו # קישורים}other{נמצאו # קישורים}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "אין לקישורים טקסט תיאורי"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "לקישורים יש טקסט תיאורי"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "כדי לאמת את תקינות הנתונים המובְנים צריך להפעיל את [הכלי לבדיקת הנתונים המובְנים](https://search.google.com/structured-data/testing-tool/) ואת [הלינטר (Linter) לנתונים מובנְים](http://linter.structured-data.org/). [מידע נוסף](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "הנתונים המובְנים חוקיים"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "תיאורי מטא יכולים להופיע בתוצאות החיפוש כדי לספק סיכום תמציתי של תוכן הדף. [מידע נוסף](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "טקסט התיאור ריק."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "אין למסמך מטא תיאור"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "יש למסמך מטא תיאור"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "מנועי חיפוש לא יכולים להוסיף לאינדקס תוכן של פלאגין, ומכשירים רבים מגבילים יישומי פלאגין או לא תומכים בהם. [מידע נוסף](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "במסמך נעשה שימוש ביישומי פלאגין"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "אין במסמך שימוש ביישומי פלאגין"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "אם קובץ robots.txt אינו תקין, ייתכן שסורקים לא יוכלו להבין איך ברצונך שהאתר ייסרק או ייתווסף לאינדקס. [מידע נוסף](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "הבקשה לקובץ robots.txt החזירה מצב HTTP‏: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{נמצאה שגיאה אחת}two{נמצאו # שגיאות}many{נמצאו # שגיאות}other{נמצאו # שגיאות}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "מערכת Lighthouse לא הצליחה להוריד קובץ robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt אינו חוקי"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "הקובץ robots.txt חוקי"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "כדי שיהיה קל להקיש על רכיבים אינטראקטיביים, כמו לחצנים וקישורים, בלי לגעת ברכיבים אחרים, הם צריכים להיות גדולים מספיק (48x48 פיקסלים) ועם ריווח גדול מספיק סביבם. [מידע נוסף](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} מבין יעדי ההקשה הם בגודל תקין"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "רכיבי ההקשה קטנים מדי כי לא בוצעה אופטימיזציית מטא תגים של אזור התצוגה למסכים של ניידים"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "הגודל של רכיבי ההקשה הוגדר בצורה לא תקינה"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "יעד חופף"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "רכיב הקשה"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "הרכיבים להקשה הוגדרו בגודל המתאים"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "קובץ השירות (service worker) הוא הטכנולוגיה שמאפשרת לאפליקציה שלך להשתמש במספר תכונות Progressive Web App, כמו 'מצב לא מקוון', 'הוספה לדף הבית' ו'התראות'. [מידע נוסף](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "דף זה נשלט על ידי קובץ שירות (service worker), אך לא נמצא `start_url` כי לא ניתן היה לנתח את המניפסט בתור JSON תקף"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "דף זה נשלט על ידי קובץ שירות (service worker), אך ה-`start_url` ({startUrl}) לא נמצא בטווח ({scopeUrl}) של קובץ השירות"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "דף זה נשלט על ידי קובץ שירות (service worker), אך לא נמצא `start_url` כי לא אוחזר מניפסט."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "למקור זה יש לפחות קובץ שירות (service worker) אחד, אך הדף ({pageUrl}) לא נמצא בטווח."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "לא רושם קובץ שירות (service worker) ששולט בדף וב-`start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "רושם קובץ שירות (service worker) ששולט בדף וב-`start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "מסך פתיחה מעוצב מבטיח חוויה באיכות גבוהה כשמשתמשים מפעילים את האפליקציה שלך ממסכי הבית שלהם. [מידע נוסף](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "לא מוגדר עבור מסך פתיחה בהתאמה אישית"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "מוגדר עבור מסך פתיחה בהתאמה אישית"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "ניתן לעצב את סרגל הכתובות של הדפדפן כך שיתאים לאתר שלך. [מידע נוסף](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "לא מגדיר צבע עיצוב עבור סרגל הכתובות."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "מגדיר צבע עיצוב עבור סרגל הכתובות."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "משך החסימה של התהליכון הראשי"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "צד שלישי"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "קוד של צד שלישי עשוי להשפיע בצורה משמעותית על ביצועי הטעינה. מומלץ להגביל את הכמות של ספקי צד שלישי שאינם הכרחיים ולהשתדל לטעון קודים של צד שלישי רק אחרי שמסתיימת הטעינה של הדף. [מידע נוסף](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "קוד של צד שלישי חסם את התהליכון הראשי למשך {timeInMs, number, milliseconds} אלפיות השנייה"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "עליך להפחית את השפעת הקוד של צד שלישי"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "שימוש של צד שלישי"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "'זמן עד בייט ראשון' (Time To First Byte) הוא פרק הזמן שחולף עד שהשרת שולח תגובה. [מידע נוסף](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "טעינת מסמך השורש ארכה {timeInMs, number, milliseconds} אלפיות שנייה"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "יש לקצר את זמני התגובה של השרת (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "זמני התגובה של השרת ארוכים (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "משך זמן"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "שעת התחלה"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "סוג"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "כדי למדוד את ביצועי האפליקציה בפועל במהלך חוויות משתמש חשובות, כדאי לשקול את האפשרות להוסיף לאפליקציה את User Timing API. [מידע נוסף](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{תזמון משתמש אחד}two{# תזמוני משתמש}many{# תזמוני משתמש}other{# תזמוני משתמש}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "סימונים ומדידות של User Timing"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "נמצא רכיב <link> לקישור מראש בשביל \"{securityOrigin}\", אבל הדפדפן לא השתמש בו. יש לוודא שנעשה שימוש תקין במאפיין `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "כדאי לשקול להוסיף את ההינטים של המשאבים `preconnect` או `dns-prefetch` כדי ליצור מראש קישורים אל מקורות חשובים של צד שלישי. [מידע נוסף](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "יש להתחבר מראש למקורות נדרשים"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "נמצא ערך <link> של טעינה מראש בשביל \"{preloadURL}\", אבל הדפדפן לא השתמש בו. יש לוודא שנעשה שימוש תקין במאפיין `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "כדאי לשקול את האפשרות להשתמש ב-`<link rel=preload>` כדי לקבוע את סדר העדיפויות של אחזור משאבים שנדרשים בשלב מאוחר יותר של טעינת הדף. [מידע נוסף](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "יש לטעון מראש בקשות עיקריות"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "כדי לבצע אופטימיזציה של האפליקציה למסכים של ניידים, עליך להוסיף את התג `<meta name=\"viewport\">`. [מידע נוסף](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "לא נמצא תג `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "אין תג `<meta name=\"viewport\">` עם `width` או `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "יש תג `<meta name=\"viewport\">` עם `width` או `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "האפליקציה שלך צריכה להציג תוכן כלשהו כשה-JavaScript מושבת, גם אם זו רק אזהרה למשתמש שנדרש JavaScript כדי להשתמש באפליקציה. [מידע נוסף](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "אם הסקריפטים של גוף הדף לא זמינים, הוא צריך לעבד תוכן כלשהו."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "לא מספק תוכן חלופי כש-JavaScript לא זמין"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "מכיל תוכן כלשהו כש-JavaScript לא זמין"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "אם בונים Progressive Web App, מומלץ לשקול להשתמש בקובץ שירות (service worker) כדי שהאפליקציה תוכל לעבוד במצב לא מקוון. [מידע נוסף](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "דף זה לא מגיב בסטטוס 200 כשהוא במצב לא מקוון"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "דף זה מגיב בסטטוס 200 כשהוא במצב לא מקוון"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "ייתכן שהדף לא נטען באופן לא מקוון בגלל שכתובת ה-URL לבדיקה ({requested}) הופנתה אל \"{final}\". מומלץ לבדוק את כתובת ה-URL השנייה באופן ישיר."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "אלו הזדמנויות לשיפור השימוש ב-ARIA באפליקציה, והן יכולות לשפר את החוויה של משתמשים שנעזרים בטכנולוגיות לנגישות, כמו קוראי מסך."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "אלה הזדמנויות לספק תוכן חלופי לווידאו ואודיו. הפעולות האלה יכולות לשפר את החוויה של משתמשים עם לקויות שמיעה או ראייה."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "וידאו ואודיו"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "הפריטים האלה מדגישים שיטות מומלצות נפוצות בשביל נגישות."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "שיטות מומלצות"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "הבדיקות האלה מדגישות הזדמנויות [לשפר את הנגישות של אפליקציית האינטרנט](https://developers.google.com/web/fundamentals/accessibility). אפשר לזהות באופן אוטומטי רק חלק מבעיות הנגישות, ולכן מומלץ לבצע גם בדיקות ידניות."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "הפריטים האלה בודקים תחומים שלא ניתן לבדוק באמצעות כלי בדיקה אוטומטיים. מידע נוסף זמין במדריך שלנו שבו מוסבר [איך לערוך בדיקת נגישות](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "נגישות"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "אלו הזדמנויות לשיפורים שיאפשרו לקרוא את התוכן בצורה קלה יותר."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "ניגודיות"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "אלו הזדמנויות לשיפור של פענוח התוכן על-ידי משתמשים בלוקאלים שונים."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "התאמה לשוק המקומי והבינלאומי"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "אלו הזדמנויות לשיפור הסמנטיקה של פקדים באפליקציה. הן יכולות לשפר את החוויה של משתמשים שנעזרים בטכנולוגיות לנגישות, כמו קורא מסך."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "שמות ותוויות"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "אלו הזדמנויות לשיפור הניווט באפליקציה באמצעות מקלדת."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "ניווט"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "אלו הזדמנויות לשיפור החוויה של קריאת נתונים בטבלאות או רשימות באמצעות טכנולוגיה לנגישות, כמו קורא מסך."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "טבלאות ורשימות"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "שיטות מומלצות"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "באמצעות תקציבי ביצועים ניתן להגדיר יעדי ביצועים עבור האתר."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "תקציבים"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "מידע נוסף לגבי ביצועי האפליקציה. למספרים האלה אין [השפעה ישירה](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) על ציון הביצועים."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "ניתוחים"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "היבט הביצועים הקריטי ביותר הוא מהירות העיבוד של פיקסלים במסך. ערכי מפתח: הצגת התוכן הראשוני, הצגת התוכן העיקרי"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "שיפורים בעיבוד ראשון"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "ההצעות האלה יכולות לעזור לך להאיץ את טעינת הדף. אין להן [השפעה ישירה](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) על ציון הביצועים."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "הזדמנויות"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "ערכים"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "צריך לשפר את חוויית הטעינה הכללית, כך שהדף יגיב ויהיה מוכן לשימוש במהירות האפשרית. ערכי מפתח: זמן עד לאינטראקטיביות (Time to Interactive), מדד מהירות (Speed Index)"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "סך השיפורים"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "ביצועים"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "בדיקות אלה נותנות תוקף להיבטים של Progressive Web App. [מידע נוסף](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "בדיקות אלה נדרשות עבור שורת הבסיס [רשימת משימות של PWA](https://developers.google.com/web/progressive-web-apps/checklist), אך הן לא נבדקות באופן אוטומטי על ידי Lighthouse. הן לא משפיעות על הניקוד שלך, אך חשוב לאמת אותן באופן ידני."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "מהיר ואמין"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "ניתן להתקנה"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "מותאם ל-PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "הבדיקות האלה עוזרות לוודא שהתוכן בדף עבר אופטימיזציה לשיפור הדירוג בתוצאות של מנועי חיפוש. יש גורמים נוספים שעשויים להשפיע על הדירוג בחיפוש, אבל מערכת Lighthouse לא בודקת אותם. [מידע נוסף](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "אפשר להפעיל באתר את המאמתים הנוספים האלה כדי לבדוק עוד שיטות מומלצות של אופטימיזציה למנועי חיפוש."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "אופטימיזציה למנועי חיפוש"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "יש לכתוב את קוד ה-HTML באופן שיאפשר לסורקים להבין את תוכן האפליקציה בצורה טובה יותר."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "שיטות מומלצות לגבי תוכן"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "כדי שהאפליקציה תופיע בתוצאות החיפוש, סורקים צריכים לקבל גישה אליה."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "סריקה והוספה לאינדקס"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "הדפים צריכים להתאים לניידים, כדי שמשתמשים לא יצטרכו לעשות תנועת צביטה או לשנות את המרחק מהתצוגה כדי לקרוא את דפי התוכן. [מידע נוסף](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "התאמה לניידים"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "אורך חיים (TTL) של מטמון"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "מיקום"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "שם"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "בקשות"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "סוג המשאב"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "גודל"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "משך הזמן שנדרש"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "גודל ההעברה"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "כתובת אתר"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "פוטנציאל חיסכון"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "פוטנציאל חיסכון"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "צמצום של ‎{wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "פוטנציאל לקיצור זמן הטעינה ב-{wastedMs, number, milliseconds} אלפיות שנייה"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "מסמך"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "גופן"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "תמונה"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "מדיה"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} אלפיות שנייה"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "אחר"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "סקריפט"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} שנ'"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "גליון סגנונות"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "צד שלישי"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "סה\"כ"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "משהו השתבש בתיעוד המעקב אחרי טעינת הדף. יש להריץ שוב את Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "חלף הזמן הקצוב לתפוגה בהמתנה לחיבור הראשוני של פרוטוקול Debugger."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "לא נאספו צילומי מסך ב-Chrome במהלך טעינת הדף. כדאי לוודא תחילה שיש תוכן גלוי בדף, ורק אז להריץ מחדש את Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "שרתי DNS לא הצליחו לפענח את הדומיין שצוין."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "בפעולת האיסוף של המשאב הנדרש {artifactName} הייתה שגיאה: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "קרתה שגיאה פנימית של Chrome. יש להפעיל מחדש את Chrome ולנסות להריץ שוב את Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "פעולת האיסוף של המשאב הנדרש {artifactName} לא בוצעה."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "מערכת Lighthouse לא הצליחה לטעון באופן מהימן את הדף שביקשת. יש לוודא שהבדיקה מתבצעת בכתובת ה-URL הנכונה ושהשרת מגיב באופן תקין לכל הבקשות."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "מערכת Lighthouse לא הצליחה לטעון באופן מהימן את כתובת ה-URL שביקשת, כי הדף הפסיק להגיב."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "לכתובת ה-URL שסיפקת אין אישור אבטחה חוקי. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "דפדפן Chrome מנע טעינה של דף והציג מסך מעברון במקומו. יש לוודא שהבדיקה מתבצעת בכתובת ה-URL הנכונה ושהשרת מגיב באופן תקין לכל הבקשות."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "מערכת Lighthouse לא הצליחה לטעון באופן מהימן את הדף שביקשת. יש לוודא שהבדיקה מתבצעת בכתובת ה-URL הנכונה ושהשרת מגיב באופן תקין לכל הבקשות. (פרטים: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "מערכת Lighthouse לא הצליחה לטעון באופן מהימן את הדף שביקשת. יש לוודא שהבדיקה מתבצעת בכתובת ה-URL הנכונה ושהשרת מגיב באופן תקין לכל הבקשות. (קוד סטטוס: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "טעינת הדף ארכה זמן רב מדי. מומלץ ליישם את ההמלצות שבדוח כדי לקצר את זמן הטעינה של הדף, ואז לנסות להריץ שוב את Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "משך ההמתנה לפרוטוקול DevTools חרג מהזמן המוקצב. (שיטה: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "אחזור תוכן של משאבים חרג מהזמן המוקצב"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "נראה שכתובת ה-URL שסיפקת אינה חוקית."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "הצגת בדיקות"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "ניווט התחלתי"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "זמן אחזור מקסימלי של נתיב קריטי:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "שגיאה!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "שגיאה בדוח: אין מידע על הבדיקה"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "נתוני בדיקה"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "ניתוח [Lighthouse](https://developers.google.com/web/tools/lighthouse/) של הדף הנוכחי באמולציה של רשת סלולרית. הערכים מהווים אומדן והם עשויים להשתנות."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "פריטים נוספים שיש לבדוק באופן ידני"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "לא רלוונטי"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "הזדמנות"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "אומדן חיסכון"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "בדיקות עם ציון 'עובר'"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "כיווץ קטע הטקסט"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "הרחבת קטע הטקסט"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "הצגה של משאבי צד שלישי"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "היו בעיות שהשפיעו על ההרצה הזו של Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "הערכים מהווים אומדן והם עשויים להשתנות. ציון הביצועים [מבוסס רק על המדדים האלה](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "בדיקות שהסתיימו בציון 'עובר', אבל עם אזהרות"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "אזהרות: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "אפשר להעלות את ה-GIF לשירות שיאפשר להטמיע אותו כסרטון HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "ניתן להתקין [פלאגין של WordPress לטעינה מדורגת](https://wordpress.org/plugins/search/lazy+load/) שמאפשר לדחות את הטעינה של רכיבים שאינם מופיעים מיד במסך. ניתן גם להשתמש בעיצוב שמספק את האפשרות הזו. אפשרות נוספת היא להשתמש ב[פלאגין של AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "יש כמה יישומי פלאגין של WordPress שיכולים לעזור לך [להטביע נכסים קריטיים](https://wordpress.org/plugins/search/critical+css/) או [לדחות טעינה של משאבים פחות חשובים](https://wordpress.org/plugins/search/defer+css+javascript/). חשוב: ייתכן שהאופטימיזציות המבוצעות על ידי יישומי הפלאגין האלה יגרמו לתקלות בתכונות של העיצוב או יישומי הפלאגין האחרים, ולכן כנראה שיהיה צורך לבצע שינויים בקוד."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "עיצובים, יישומי פלאגין ומפרטי שרתים משפיעים על זמן התגובה של השרת. אפשר להשתמש בעיצוב שעבר אופטימיזציה, לבחור בקפידה פלאגין לאופטימיזציה ו/או לשדרג את השרת."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "אפשר להציג קטעים ברשימות הפוסטים (למשל, עם תג 'עוד'), לצמצם את מספר הפוסטים המוצגים בדף נתון, לחלק פוסטים ארוכים למספר דפים או להשתמש בפלאגין כדי לטעון תגובות בצורה מדורגת."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "יש כמה [יישומי פלאגין של WordPress](https://wordpress.org/plugins/search/minify+css/) שיכולים להאיץ את האתר על ידי שרשור, הקטנה ודחיסה של סגנונות. ניתן גם להשתמש בתהליך build כדי לבצע את ההקטנה מראש, אם אפשר."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "יש כמה [יישומי פלאגין של WordPress](https://wordpress.org/plugins/search/minify+javascript/) שיכולים להאיץ את האתר על ידי שרשור, הקטנה ודחיסה של סקריפטים. ניתן גם להשתמש בתהליך build כדי לבצע את ההקטנה מראש, אם אפשר."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "כדאי לשקול לצמצם את מספר [יישומי הפלאגין של WordPress](https://wordpress.org/plugins/) שטוענים תוכן CSS בלתי נחוץ בדף, או להשבית אותם. כדי לזהות יישומי פלאגין שמוסיפים תוכן CSS מיותר, אפשר להפעיל [כיסוי קוד](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ב-Chrome DevTools. לפי כתובת ה-URL של גיליון הסגנונות, ניתן לזהות את העיצוב/הפלאגין שאחראים להוספת התוכן. יישומי הפלאגין הבעייתיים הם אלה שברשימת גיליונות הסגנונות שלהם יש כמות גדולה של כיסוי קוד באדום. פלאגין צריך להכניס גיליון סגנונות לתור רק אם נעשה בו שימוש בדף."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "כדאי לשקול לצמצם את מספר [יישומי הפלאגין של WordPress](https://wordpress.org/plugins/) שטוענים תוכן JavaScript בלתי נחוץ בדף, או להשבית אותם. כדי לזהות יישומי פלאגין שמוסיפים תוכן JS מיותר, אפשר להפעיל [כיסוי קוד](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) ב-Chrome DevTools. לפי כתובת ה-URL של הסקריפט, ניתן לזהות את העיצוב/הפלאגין שאחראים להוספת התוכן. יישומי הפלאגין הבעייתיים הם אלה שברשימת הסקריפטים שלהם יש כמות גדולה של כיסוי קוד באדום. פלאגין צריך להכניס סקריפט לתור רק אם נעשה בו שימוש בדף."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "למידע על [שמירה במטמון הדפדפן ב-WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "כדאי לשקול להשתמש ב[פלאגין של WordPress לאופטימיזציית תמונות](https://wordpress.org/plugins/search/optimize+images/) שדוחס את התמונות בלי לפגוע באיכות שלהן."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "העלאה של תמונות באופן ישיר דרך [ספריית המדיה](https://codex.wordpress.org/Media_Library_Screen) תאפשר לך לוודא שהתמונות זמינות במידות הדרושות. אחר כך אפשר להוסיף אותן מספריית המדיה או להשתמש בווידג'ט התמונות כדי לוודא שנעשה שימוש בתמונות במידות האופטימליות (כולל תמונות בשביל נקודות מעבר רספונסיביות). יש להימנע משימוש בתמונות ב`Full Size`, אלא אם המימדים מתאימים לשימוש שנעשה בהן. [מידע נוסף](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "אפשר להפעיל דחיסת טקסט בהגדרות שרת האינטרנט."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "כדאי לשקול להשתמש ב[פלאגין](https://wordpress.org/plugins/search/convert+webp/) או בשירות שימירו את התמונות שהועלו לפורמטים האופטימליים באופן אוטומטי."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hi.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hi.json
new file mode 100644
index 00000000000..cd063f5412c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hi.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "ऐक्सेस कुंजी से उपयोगकर्ता तेज़ी से पेज के किसी भाग पर फ़ोकस कर सकते हैं. सही नेविगेशन के लिए, हर ऐक्सेस कुंजी सबसे अलग होनी चाहिए. [ज़्यादा जानें](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` मान सबसे अलग नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` के मान सबसे अलग हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "हर एआरआईए `role`, `aria-*` विशेषताओं के खास सबसेट पर काम करती है. इनमें मिलान न होने पर `aria-*` विशेषताएं गलत हो जाती हैं. [ज़्यादा जानें](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` विशेषताएं और उनकी भूमिकाएं आपस में मेल नहीं खातीं"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` विशेषताएं और उनकी भूमिकाएं एक-दूसरे से मेल खाती हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "कुछ ARIA भूमिकाओं में ऐसी विशेषताओं की ज़रूरत होती है जो स्क्रीन रीडर को एलिमेंट की स्थिति बताती हैं. [ज़्यादा जानें](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`s में सभी ज़रूरी `[aria-*]` विशेषताएं नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` के पास सभी ज़रूरी `[aria-*]` विशेषताएं हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "कुछ ARIA पैरंट भूमिकाओं में खास चाइल्ड भूमिकाएं होनी चाहिए ताकि वे तय किए गए सुलभता फ़ंक्शन कर सकें. [ज़्यादा जानें](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` are missing some or all of those required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "कुछ ARIA चाइल्ड रोल अपने तय सुलभता फ़ंक्शन को ठीक से कर पाएं. इसके लिए, उन्हें खास पैरंट रोल में शामिल होना चाहिए. [ज़्यादा जानें](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` अपने ज़रूरी पैरंट एलिमेंट में शामिल नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`अपने लिए ज़रूरी पैरंट एलिमेंट में शामिल हैं."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA भूमिकाओं में सही मान होने चाहिए, ताकि वे तय किए गए सुलभता फ़ंक्शन कर सकें. [ज़्यादा जानें](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` मान सही नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` मान सही हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "स्क्रीन रीडर जैसी सहायक तकनीक, गलत मानों वाली ARIA विशेषताओं को समझ नहीं सकतीं. [ज़्यादा जानें](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` विशेषताओं में सही मान नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` विशेषताओं के मान सही हैं"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "स्क्रीन रीडर जैसी सहायक तकनीक, गलत नामों वाली ARIA विशेषताओं को समझ नहीं सकतीं. [ज़्यादा जानें](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` विशेषताएं गलत हैं या उनकी वर्तनी गलत है"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` विशेषताएं सही हैं और उनकी वर्तनी गलत नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "ऑडियो एलिमेंट इस्तेमाल करने वाले जो लोग सुन नहीं पाते या जिन्हें कम सुनाई देता है, वे कैप्शन का इस्तेमाल करके एलिमेंट की जानकारी पढ़ सकते हैं. साथ ही, कैप्शन यह भी बताते हैं कि कौन बा़त कर रहा है, वे क्या बोल रहे हैं, और ऐसी ही दूसरी, बोली न जाने वाली जानकारी भी कैप्शन की मदद से लोगों को पता चलती है. [ज़्यादा जानें](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` एलिमेंट में `[kind=\"captions\"]` के साथ `<track>` एलिमेंट नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` एलिमेंट में `[kind=\"captions\"]` वाला एक `<track>` एलिमेंट है"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "फ़ेल होने वाले एलिमेंट"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "अगर बटन का कोई ऐसा नाम नहीं है जिसे ऐक्सेस किया जा सकता है, तो स्क्रीन रीडर उसे \"बटन\" के रूप में बताते हैं. इस वजह से यह उन इस्तेमाल करने वालों के लिए किसी काम का नहीं रहता जो स्क्रीन रीडर से ही टेक्स्ट पढ़ या समझ सकते हैं. [ज़्यादा जानें](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "बटन के नाम ऐक्सेस करने लायक नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "बटनों का एक सुलभता नाम है"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "दोहराव वाली सामग्री को नज़रअंदाज करके आगे बढ़ने के तरीके जोड़ने से, कीबोर्ड इस्तेमाल करने वाले लोग पेज पर ज़्यादा अच्छे से नेविगेट कर सकते हैं. [ज़्यादा जानें](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "पेज में 'हेडिंग', 'स्किप लिंक' या 'लैंडमार्क' क्षेत्र नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "पेज में 'हेडिंग', 'स्किप लिंक' या 'लैंडमार्क' क्षेत्र हैं"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "इस्तेमाल करने वाले कई लोगों के लिए कम कंट्रास्ट वाला टेक्स्ट पढ़ना मुश्किल या नामुमकिन होता है. [ज़्यादा जानें](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "बैकग्राउंड और फ़ोरग्राउंड रंगों में काफ़ी कंट्रास्ट अनुपात नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "बैकग्राउंड और फ़ोरग्राउंड के रंगों का कंट्रास्ट अनुपात काफ़ी है"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "जब परिभाषा सूचियां ठीक से मार्क अप नहीं की जातीं, तो स्क्रीन रीडर उलझन भरे या गलत आउटपुट दे सकते हैं. [ज़्यादा जानें](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` में ठीक क्रम से लगाए गए `<dt>` और `<dd>` ग्रुप, `<script>` या `<template>` एलिमेंट नहीं हैं."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` में सिर्फ़ ठीक क्रम से लगे हुए`<dt>` और `<dd>` ग्रुप, `<script>` या `<template>` एलिमेंट हैं."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "परिभाषा सूची आइटम (`<dt>` और `<dd>`) को पैरंट `<dl>` एलिमेंट में रैप किया जाना चाहिए, ताकि यह पक्का किया जा सके कि स्क्रीन रीडर उन्हें ठीक तरीके से बोल सकते हैं. [ज़्यादा जानें](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "परिभाषा सूची के आइटम `<dl>` एलिमेंट में रैप नहीं किए जाते"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "परिभाषा सूची के आइटम `<dl>` एलिमेंट में रैप किए जाते हैं"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "शीर्षक से स्क्रीन रीडर उपयोगकर्ताओं को पेज की खास जानकारी मिलती है. सर्च इंजन के उपयोगकर्ता शीर्षक के भरोसे यह तय करते हैं कि कोई पेज उनकी खोज के हिसाब से सही है या नहीं. [ज़्यादा जानें](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "दस्तावेज़ में कोई `<title>` एलिमेंट नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "दस्तावेज़ में `<title>` एलिमेंट है"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "सहायक तकनीकों को दूसरे इंस्टेंस अनदेखा करने से रोकने के लिए, आईडी विशेषता का मान सबसे अलग होना चाहिए. [ज़्यादा जानें](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "पेज पर `[id]` विशेषताएं सबसे अलग नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "पेज पर `[id]` विशेषताएं सबसे अलग हैं"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "स्क्रीन रीडर उपयोगकर्ता, फ़्रेम की सामग्री के बारे में जानने के लिए फ़्रेम के शीर्षकों का इस्तेमाल करते हैं. [ज़्यादा जानें](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` या `<iframe>` एलिमेंट का कोई शीर्षक नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` या `<iframe>` एलिमेंट का एक शीर्षक है"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "अगर कोई पेज, भाषा विशेषता तय नहीं करता है, तो स्क्रीन रीडर को लगता है कि पेज उस डिफ़ॉल्ट भाषा में है जो उपयोगकर्ता ने स्क्रीन रीडर सेट अप करते समय चुनी थी. अगर वह पेज डिफ़ॉल्ट भाषा में नहीं है, तो शायद स्क्रीन रीडर, पेज का टेक्स्ट ठीक से न बोल पाए. [ज़्यादा जानें](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` एलिमेंट में `[lang]` विशेषता नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` एलिमेंट में `[lang]` विशेषता है"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "सही [BCP 47 भाषा ](https://www.w3.org/International/questions/qa-choosing-language-tags#question) तय करने से स्क्रीन रीडर को टेक्स्ट ठीक से बोलने में मदद मिलती है. [ज़्यादा जानें](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` एलिमेंट के पास अपनी `[lang]`विशेषता के लिए कोई सही मान नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` एलिमेंट के पास अपनी `[lang]` विशेषता के लिए एक सही मान है"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "जानकारी वाले एलिमेंट का मकसद यह होना चाहिए कि उनमें छोटा और पूरी जानकारी देने वाला वैकल्पिक टेक्स्ट शामिल हो. डेकोरेटिव एलिमेंट, एक खाली ऑल्ट एट्रिब्यूट के साथ अनदेखे किया जा सकते हैं. [ज़्यादा जानें](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "इमेज एलिमेंट में `[alt]` विशेषताएं नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "इमेज एलिमेंट में `[alt]` विशेषताएं शामिल हैं"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "जब किसी इमेज को `<input>` बटन के रूप में इस्तेमाल किया जा रहा हो, तब वैकल्पिक टेक्स्ट देने से, स्क्रीन रीडर इस्तेमाल करने वाले लोगों को उस बटन के मकसद को समझने में मदद मिलती है. [ज़्यादा जानें](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` एलिमेंट में `[alt]` टेक्स्ट नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` एलिमेंट में`[alt]` टेक्स्ट है"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "लेबल यह पक्का करते हैं कि स्क्रीन रीडर जैसी सहायक तकनीकें, फ़ॉर्म नियंत्रणों को सही तरीके से बोलें. [ज़्यादा जानें](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "फ़ॉर्म एलिमेंट में जुड़े हुए लेबल नहीं हैं"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "फ़ॉर्म एलिमेंट में सहभागी लेबल हैं"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "लेआउट के लिए इस्तेमाल की जाने वाली टेबल में th या कैप्शन वाले एलिमेंट जैसे, डेटा एलिमेंट या सारांश विशेषता शामिल नहीं होनी चाहिए, क्योंकि इससे स्क्रीन रीडर उपयोगकर्ताओं को उलझन हो सकती हैं. [ज़्यादा जानें](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "प्रज़ेंटेशन के लिए इस्तेमाल होने वाले `<table>`एलिमेंट में `<th>`, `<caption>` या `[summary]` विशेषता का इस्तेमाल होता है."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "प्रज़ेंटेशन के लिए इस्तेमाल होने वाले `<table>`एलिमेंट में `<th>`, `<caption>` या `[summary]` विशेषता का इस्तेमाल नहीं होता."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "जो लिंक टेक्स्ट (और इमेज के लिए इस्तेमाल किया वैकल्पिक टेक्स्ट) समझने लायक, सबसे अलग, और फ़ोकस करने लायक है, उससे स्क्रीन रीडर उपयोगकर्ताओं का नेविगेशन अनुभव बेहतर बनता है. [ज़्यादा जानें](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "लिंक का समझने लायक नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "लिंक का समझने लायक नाम है"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "स्क्रीन रीडर, सूचियों को एक खास तरीके से बोलते हैं. सूची की सही बनावट पक्की करने से स्क्रीन रीडर को आउटपुट देने में मदद मिलती है. [ज़्यादा जानें](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "सूचियों में सिर्फ़ `<li>` एलिमेंट और स्क्रिप्ट के साथ काम करने वाले एलिमेंट (`<script>`और `<template>`) ही शामिल नहीं हैं."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "सूची में सिर्फ़ `<li>` एलिमेंट और स्क्रिप्ट के साथ काम करने वाले एलिमेंट शामिल हैं (`<script>` और `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "स्क्रीन रीडर के लिए ज़रूरी है कि उनमें `<ul>` या `<ol>` पैरंट में सूची आइटम (`<li>`) शामिल हों, ताकि उन्हें ठीक तरह से बोला जा सके. [ज़्यादा जानें](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "सूची आइटम (`<li>`) `<ul>` या `<ol>` पैरंट एलिमेंट में शामिल नहीं हैं."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "सूची वाले आइटम (`<li>`) `<ul>` या `<ol>` पैरंट एलिमेंट में हैं"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "उपयोगकर्ताओं को ऐसी उम्मीद नहीं होती कि कोई पेज अपने आप रीफ़्रेश हो जाएगा. इसके बाद, फ़ोकस वापस पेज के सबसे ऊपर चला जाएगा. इससे उन्हें परेशानी या उलझन हो सकती है. [ज़्यादा जानें](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "यह दस्तावेज़ `<meta http-equiv=\"refresh\">` का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "दस्तावेज़ `<meta http-equiv=\"refresh\">` का इस्तेमाल नहीं करते"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "ज़ूम करने की सुविधा को बंद करने से उन उपयोगकर्ताओं को परेशानी होती है जिन्हें कम दिखाई देता है. ऐसे उपयोगकर्ता वेब पेज की सामग्री को ठीक तरह से देखने के लिए स्क्रीन को बड़ा करते हैं. [ज़्यादा जानें](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` का इस्तेमाल `<meta name=\"viewport\">` एलिमेंट में किया जाता है या `[maximum-scale]`विशेषता पांच से कम है."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` का इस्तेमाल `<meta name=\"viewport\">` एलिमेंट में नहीं किया जाता और `[maximum-scale]`विशेषता पाँच से कम नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "स्क्रीन रीडर ऐसी सामग्री का अनुवाद नहीं कर सकते जिसमें टेक्स्ट नहीं है. `<object>` एलिमेंट में वैकल्पिक टेक्स्ट जोड़ने से, स्क्रीन रीडर आसानी से उपयोगकर्ताओं को बात का मतलब समझा सकते हैं. [ज़्यादा जानें](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` एलिमेंट में `[alt]` टेक्स्ट नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` एलिमेंट में`[alt]` टेक्स्ट है"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "0 से ज़्यादा मान साफ़ तौर पर नेविगेशन क्रम को लागू करता है. हालांकि, यह तकनीकी रूप से सही है, लेकिन यह अक्सर उन इस्तेमाल करने वालों को निराश करता है जो सहायक तकनीकों पर भरोसा करते हैं. [ज़्यादा जानें](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "कुछ एलिमेंट का `[tabindex]` मान 0 से ज़्यादा होता है"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "किसी भी एलिमेंट का `[tabindex]` मान 0 से ज़्यादा नहीं हो सकता"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "स्क्रीन रीडर में ऐसी सुविधाएं होती हैं जिनसे टेबल में जाना आसान हो जाता है. `[headers]` विशेषता का इस्तेमाल करके `<td>` सेल की मौजूदगी पक्की करने के लिए उसी टेबल में मौजूद दूसरे सेल का हवाला दिया जाता है. इससे स्क्रीन रीडर उपयोगकर्ताओं के अनुभव को बेहतर बनाया जा सकता है. [ज़्यादा जानें](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to an element `id` not found within the same table."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "स्क्रीन रीडर में ऐसी सुविधाएं होती हैं जिनसे टेबल में जाना आसान हो जाता है. यह पक्का करें कि टेबल हेडर हमेशा कुछ सेल के सेट के बारे में बताते हों. इससे स्क्रीन रीडर के उपयोगकर्ताओं को बेहतर अनुभव मिल सकता है. [ज़्यादा जानें](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` एलिमेंट और `[role=\"columnheader\"/\"rowheader\"]` वाले एलिमेंट में वे डेटा सेल मौजूद नहीं हैं जो उनके ब्यौरे में शामिल हैं."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` एलिमेंट और `[role=\"columnheader\"/\"rowheader\"]` वाले एलिमेंट में वे डेटा सेल शामिल हैं जिनकी वे जानकारी देते हैं."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "एलिमेंट पर एक सही [BCP 47 भाषा ](https://www.w3.org/International/questions/qa-choosing-language-tags#question) तय करने से आप पक्का कर सकते हैं कि स्क्रीन रीडर, टेक्स्ट को सही से बोले. [ज़्यादा जानें](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` विशेषताओं का कोई सही मान नहीं है"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` विशेषताओं का मान सही है"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "वीडियो में कैप्शन उपलब्ध कराने पर वे उपयोगकर्ता आसानी से जानकारी समझ सकते हैं जो सुन नहीं पाते और जिन्हें कम सुनाई देता है. [ज़्यादा जानें](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` एलिमेंट में `[kind=\"captions\"]` वाला कोई `<track>` एलिमेंट नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` एलिमेंट में `[kind=\"captions\"]` वाला एक `<track>` एलिमेंट है"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "ऑडियो के ब्यौरे में वीडियो से जुड़ी काम की ऐसी जानकारी दी जाती है जो बातचीत से नहीं दी जा सकती. जैसे, चेहरे के हावभाव और सीन. [ज़्यादा जानें](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` एलिमेंट में `[kind=\"description\"]` वाला कोई `<track>` एलिमेंट नहीं है."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` एलिमेंट में `[kind=\"description\"]` वाला एक `<track>` एलिमेंट है"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "उपयोगकर्ता जब होम स्क्रीन पर प्रगतिशील वेब ऐप्लिकेशन जोड़ें, तो iOS पर वह अच्छे से नज़र आए, इसके लिए `apple-touch-icon` तय करें. यह ज़रूरी है कि यह आइकॉन किसी ऐसे 192px (या 180px) के वर्गाकार PNG की तरफ़ इशारा करे जिसके आर-पार न देखा जा सके. [ज़्यादा जानें](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "एक सही `apple-touch-icon` नहीं उपलब्ध कराता"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` पुराना हो गया है; `apple-touch-icon` को प्राथमिकता दी जाती है."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "एक सही `apple-touch-icon` देता है"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome एक्सटेंशन ने इस पेज के लोड परफ़ॉर्मेंस पर नकारात्मक रूप से असर डाला है. 'गुप्त मोड' में या बिना किसी एक्सटेंशन के Chrome प्रोफ़ाइल से पेज ऑडिट करके देखें."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "स्क्रिप्ट मूल्यांकन"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "स्क्रिप्ट पार्स"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "कुल सीपीयू समय"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JS को पार्स करने, कंपाइल करने, और एक्ज़ीक्यूट करने में लगने वाला समय कम करें. आप देखेंगे कि इसकी मदद से छोटे-छोटे JS पेलोड डिलीवर करने में मदद मिलती है. [ज़्यादा जानें](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript क्रियान्वयन समय कम करें"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript क्रियान्वयन समय"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "बड़ी GIFs ऐनिमेशन वाली सामग्री डिलीवर नहीं कर सकते. नेटवर्क बाइट बचाने के लिए GIF का इस्तेमाल करने के बजाय, ऐनिमेशन के लिए MPEG4/WebM वीडियो और स्टैटिक इमेज के लिए PNG/WebP का इस्तेमाल करें. [ज़्यादा जानें](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "ऐनिमेट की गई सामग्री के लिए वीडियो फ़ॉर्मेट का इस्तेमाल करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "इंटरैक्टिव में लगने वाला समय कम करने के लिए, सभी अहम संसाधन लोड हो जाने के बाद ऑफ़स्क्रीन और छिपी हुई इमेज को धीरे-धीरे लोड करें. [ज़्यादा जानें](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "ऑफ़स्क्रीन इमेज टालें"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "संसाधन आपके पेज का फ़र्स्ट पेंट ब्लॉक कर रहे हैं. ज़रूरी JS/सीएसएस इनलाइन डिलीवर करने और सभी गैर-ज़रूरी JS/शैलियों को टाल दें. [ज़्यादा जानें](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "रेंडर ब्लॉक करने वाले संसाधनों को खत्म करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "बड़े नेटवर्क वाले पेलोड के लिए उपयोगकर्ताओं को रकम खर्च करनी होती है. साथ ही, उन पर लोड होने में ज़्यादा समय भी लगता है. [ज़्यादा जानें](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "कुल आकार {totalBytes, number, bytes} केबी था"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "बहुत ज़्यादा नेटवर्क पेलोड से बचें"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "भारी नेटवर्क पेलोड से बचाता है"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS फ़ाइलों को छोटा करने से नेटवर्क पेलोड आकार कम किए जा सकते हैं. [ज़्यादा जानें](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSS कम करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript फ़ाइलों को छोटा करने से पेलोड का आकार और स्क्रिप्ट पार्स करने में लगने वाला समय कम हो सकता है. [ज़्यादा जानें](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScript का आकार कम करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "स्टाइलशीट से इस्तेमाल न किए गए नियमों को हटाएं और पेज के ऊपरी हिस्से की सामग्री के लिए इस्तेमाल न होने वाले CSS को लोड होने से टालें. ऐसा करके, नेटवर्क गतिविधि में खर्च होने वाले गैर-ज़रूरी बाइट कम किए जा सकते हैं. [ज़्यादा जानें](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "इस्तेमाल नहीं किए गए CSS को हटाएं"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "नेटवर्क गतिविधि में खर्च होने वाले बाइट में कमी करने के लिए इस्तेमाल नहीं किया गया JavaScript हटाएं."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "इस्तेमाल नहीं किया गया JavaScript हटाएं"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "अगर कैश मेमोरी ज़्यादा समय तक रहेगी, तो लोगों के आपकी साइट पर लौटने की प्रक्रिया में तेज़ी आएगी. [ज़्यादा जानें](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 संसाधन मिला}one{# संसाधन मिले}other{# संसाधन मिले}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "कुशल कैश नीति के साथ स्थिर एसेट ऑफ़र करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "स्थिर एसेट पर कुशल कैश नीति का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "ऑप्टिमाइज़ की गई इमेज तेज़ी से लोड होती हैं. साथ ही, इसमें कम सेल्युलर डेटा खर्च होता है. [ज़्यादा जानें](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "इमेज को कुशलता से एन्कोड करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "ऐसी इमेज ऑफ़र करें जिनका आकार सही हो, ताकि सेल्युलर डेटा बचाया जा सके और लोड होने में लगने वाले समय को कम किया जा सके. [ज़्यादा जानें](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "सही तरीके के आकार वाली इमेज"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "कुल नेटवर्क बाइट को कम से कम करने के लिए, टेक्स्ट आधारित संसाधन, कंप्रेशन (gzip, deflate या brotli) के साथ ऑफ़र किए जाने चाहिए. [ज़्यादा जानें](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "लेख कंप्रेशन चालू करें"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000, JPEG XR, और WebP जैसे इमेज फ़ॉर्मैट, ज़्यादातर PNG या JPEG से बेहतर कंप्रेस करते हैं जिससे उपयोगकर्ता कम डेटा खर्च करके तेज़ डाउनलोड कर सकते हैं. [ज़्यादा जानें](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "इमेज अगली जेनरेशन के फ़ॉर्मेट में ऑफ़र करें"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "अगर आपके ऐप्लिकेशन की सामग्री की चौड़ाई व्यूपोर्ट की चौड़ाई से मेल नहीं खाती है, तो आपका ऐप्लिकेशन मोबाइल स्क्रीन पर ऑप्टिमाइज़ नहीं किया जा सकेगा. [ज़्यादा जानें](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{innerWidth}px के व्यूपोर्ट का आकार {outerWidth}px की विंडो के आकार से मेल नहीं खाता है."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "सामग्री का आकार व्यूपोर्ट (किसी वेब पेज के स्क्रीन पर दिखने वाले हिस्से) के मुताबिक नहीं है"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "सामग्री का आकार व्यूपोर्ट (किसी वेब पेज के स्क्रीन पर दिखने वाले हिस्से) के मुताबिक है"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "नीचे दी गई अहम अनुरोध शृंखलाएं बताती हैं कि किन संसाधनों को ज़्यादा प्राथमिकता से लोड किया गया है. शृंखलाओं की अवधि कम करें. इससे संसाधनों का डाउनलोड आकार कम हो जाएगा या पेज लोड को बेहतर बनाने के लिए गैर-ज़रूरी संसाधनों का डाउनलोड टल जाएगा. [ज़्यादा जानें](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 शृंखला मिली}one{# शृंखलाएं मिलीं}other{# शृंखलाएं मिलीं}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "अहम अनुरोधों की गहराई कम से कम करें"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "रुक गया है / चेतावनी"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "लाइन"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "काम न करने वाले एपीआई आपके ब्राउज़र से हटा दिए जाएंगे. [ज़्यादा जानें](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 चेतावनी मिली}one{# चेतावनियां मिलीं}other{# चेतावनियां मिलीं}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "रुके हुए एपीआई का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "रुके हुई एपीआई का इस्तेमाल नहीं किया जाता"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "ऐप्लिकेशन की कैश मेमोरी अब काम नहीं करती. [ज़्यादा जानें](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" मिल गया"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "ऐप्लिकेशन की कैश मेमोरी का इस्तेमाल किया जाता है"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "ऐप्लिकेशन की कैश मेमोरी का इस्तेमाल नहीं किया जाता"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "doctype तय करने से, ब्राउज़र क्वर्क-मोड (पुराने वर्शन पर काम करने की सुविधा) पर स्विच नहीं करता है. [ज़्यादा जानें](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype का नाम अंग्रेज़ी के छोटे अक्षरों वाली स्ट्रिंग `html` में होना चाहिए"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "दस्तावेज़ में doctype होना ज़रूरी है"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "उम्मीद थी कि publicId खाली स्ट्रिंग होगी"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "उम्मीद थी कि systemId खाली स्ट्रिंग होगी"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "पेज में HTML doctype नहीं है जिसकी वजह से क्वर्क-मोड (पुराने वर्शन पर काम करने की सुविधा) ट्रिगर हो रही है"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "पेज में एचटीएमएल doctype है"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "तत्व"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "आंकड़े"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "मान"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "ब्राउज़र इंजीनियर यह सुझाव देते हैं कि पेज में ~1,500 से कम DOM एलिमेंट शामिल हों. सबसे सही आंकड़ा है 32 से कम एलिमेंट वाली ट्री डेप्थ और 60 से कम चिल्ड्रन/पैरंट एलिमेंट. ज़्यादा बड़े DOM से मेमोरी का इस्तेमाल बढ़ सकता है जिससे ज़्यादा लंबे [स्टाइल कैल्युलेशन](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) हो सकते हैं और इनसे महंगे [लेआउट रीफ़्लो](https://developers.google.com/speed/articles/reflow) बन सकते हैं. [ज़्यादा जानें](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ऐलिमेंट}one{# ऐलिमेंट}other{# ऐलिमेंट}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "बहुत ज़्यादा बड़े DOM आकार से बचें"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "सबसे ज़्यादा DOM गहराई"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "कुल डीओएम ऐलिमेंट"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "ज़्यादातर बच्चों की चीजें"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "बहुत ज़्यादा बड़े DOM आकार से बचता है"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "लक्ष्य"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "किसी बाहरी लिंक में `rel=\"noopener\"` या `rel=\"noreferrer\"` जोड़कर परफ़ॉर्मेंस बेहतर करें और सुरक्षा जोखिमों से बचें. [ज़्यादा जानें](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "जिन जगहों पर दो डोमेन से होकर जाना होता है वे सुरक्षित नहीं हैं"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "जिन जगहों पर दो डोमेन से होकर जाना होता है वे सुरक्षित हैं"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "एंकर ({anchorHTML}) के भेजे जाने की जगह नहीं पता की जा सकी. अगर target=_blank का इस्तेमाल हाइपरलिंक की तरह नहीं हो रहा, तो इसे हटा दें."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "उपयोगकर्ता ऐसी साइटों पर भरोसा नहीं करते या उनकी वजह से उलझन में रहते हैं जो बिना किसी संदर्भ के उनकी जगह की जानकारी पता करने का अनुरोध करती हैं. इसके बजाय, उपयोगकर्ता के जेस्चर के हिसाब से अनुरोध करें. [ज़्यादा जानें](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "पेज लोड पर भौगोलिक स्थान जानने का अनुरोध किया जाता है"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "पेज लोड पर भौगोलिक स्थान जानने की मंज़ूरी का अनुरोध नहीं किया जाता"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "वर्शन"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "इस पेज पर पहचानी गई सभी फ़्रंट-एंड JavaScript लाइब्रेरी. [ज़्यादा जानें](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "पहचानी गई JavaScript लाइब्रेरी"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "धीमे कनेक्शन वाले उपयोगकर्ताओं के लिए, `document.write()` की दी गई बाहरी स्क्रिप्ट की वजह से पेज लोड होने में दस से ज़्यादा सेकंड की देरी हो सकती है. [ज़्यादा जानें](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()` का इस्तेमाल होता है"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()` का इस्तेमाल नहीं किया जाता"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "सबसे ज़्यादा गंभीर"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "लाइब्रेरी वर्शन"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "जोखिम की संभावना की संख्या"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "तीसरे पक्ष की कुछ स्क्रिप्ट में सुरक्षा के ऐसे जोखिम हो सकते हैं जिनके बारे में लोगों को पता है. साथ ही, जिन्हें हमलावर आसानी से पहचानकर उनका फ़ायदा उठा सकते हैं. [ज़्यादा जानें](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 जोखिम की संभावना का पता चला}one{# जोखिमों की संभावना का पता चला}other{# जोखिमों की संभावना का पता चला}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "ऐसी फ़्रंट-एंड JavaScript लाइब्रेरी का इस्तेमाल करता है जिनमें शामिल सुरक्षा जोखिमों के बारे में सबको पता होता है."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "ज़्यादा"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "कम"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "मीडियम"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "ऐसी फ़्रंट-एंड JavaScript लाइब्रेरी का इस्तेमाल नहीं करता जिनमें शामिल सुरक्षा जोखिमों के बारे में सबको पता होता है."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "उपयोगकर्ता ऐसी साइटों पर भरोसा नहीं करते या उनकी वजह से उलझन में रहते हैं जो उन्हें बिना किसी संदर्भ के सूचनाएं भेजने का अनुरोध करती हैं. इसके बजाय, उपयोगकर्ता के जेस्चर के हिसाब से अनुरोध करें. [ज़्यादा जानें](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "पेज लोड पर सूचनाओं की अनुमति पाने का अनुरोध किया जाता है"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "पेज लोड पर सूचना भेजने की मंज़ूरी का अनुरोध नहीं किया जाता"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "फ़ेल होने वाले एलिमेंट"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "पासवर्ड वाले फ़ील्ड में कुछ कॉपी करके चिपकाने की सुविधा न लागू करने का मतलब है एक अच्छी सुरक्षा नीति को कमज़ोर समझना. [ज़्यादा जानें](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "इस्तेमाल करने वालों को पासवर्ड फ़ील्ड में पहले से कॉपी की गई जानकारी चिपकाने से रोकता है"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "इस्तेमाल करने वालों को पासवर्ड फ़ील्ड में पहले से कॉपी की गई जानकारी चिपकाने देता है"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "प्रोटोकॉल"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 , HTTP/1.1 से ज़्यादा फ़ायदे ऑफ़र करता है जिनमें बाइनरी हैडर, मल्टीप्लेक्सिंग, और सर्वर पुश शामिल हैं. [ज़्यादा जानें](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 अनुरोध HTTP/2 से सर्व नहीं किया गया}one{# अनुरोध HTTP/2 से सर्व नहीं किए गए}other{# अनुरोध HTTP/2 से सर्व नहीं किए गए}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "अपने सभी संसाधनों के लिए HTTP/2 का इस्तेमाल नहीं करता"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "अपने संसाधन के लिए HTTP/2 का इस्तेमाल किया जाता है"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "अपने 'टच एंड व्हील' घटना श्रोता पर `passive` का निशान लगाएं, ताकि आपके पेज की स्क्रोल परफ़ॉर्मेंस को बेहतर किया जा सके. [ज़्यादा जानें](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "स्क्रोल परफ़ॉर्मेंस बेहतर करने के लिए पैसिव श्रोताओं का इस्तेमाल नहीं करता"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "पैसिव श्रोताओं की मदद से स्क्रोल परफ़ॉर्मेंस बेहतर की जाती है"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "ब्यौरा"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "कंसोल में लॉग की गई गड़बड़ियां उन मुश्किलों की तरफ़ इशारा करती हैं जिनका समाधान किया जाना अभी बाकी है. ये गड़बड़ियां, नेटवर्क अनुरोधों के काम न करने और ब्राउज़र से जुड़ी दूसरी वजहों से हो सकती हैं. [ज़्यादा जानें](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "ब्राउज़र की गड़बड़ियां कंसोल में लॉग की गईं"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "ब्राउज़र की किसी गड़बड़ी को कंसोल में लॉग नहीं किया गया"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "यह पक्का करने के लिए कि वेबफ़ॉन्ट लोड होने के दौरान उपयोगकर्ता को टेक्स्ट दिखाई देता रहे, फ़ॉन्ट-डिसप्ले सीएसएस फ़ीचर का फ़ायदा लें. [ज़्यादा जानें](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "पक्का करें कि वेबफ़ॉन्ट लोड होने के दौरान लेख दिखाई देता रहे"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "वेबफ़ॉन्ट लोड होने के दौरान सभी लेख दिखाई देते रहते हैं"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse इस यूआरएल के लिए, फ़ॉन्ट-डिसप्ले की अपने आप जांच नहीं कर सका: {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "चौड़ाई-ऊंचाई का अनुपात (असल)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "चौड़ाई-ऊंचाई का अनुपात (डिसप्ले किया गया)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "इमेज डिसप्ले डाइमेंशन, चौड़ाई-ऊंचाई के अनुपात जितने होने चाहिए. [ज़्यादा जानें](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "चौड़ाई-ऊंचाई के गलत अनुपात वाली इमेज दिखाता है"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "चौड़ाई-ऊंचाई के सही अनुपात वाली इमेज दिखाता है"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "इमेज के आकार की जानकारी गलत है {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "ब्राउज़र अपनी ओर से उपयोगकर्ताओं को आपके ऐप्लिकेशन को उनकी होमस्क्रीन पर जोड़ने का सुझाव दे सकते हैं. इससे उपयोगकर्ताओं के साथ बेहतर तरीके से जुड़ने में मदद मिलती है. [ज़्यादा जानें](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "वेब ऐप्लिकेशन का मेनिफ़ेस्ट, इंस्टॉल करने की ज़रूरतों को पूरा नहीं करता है"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "वेब ऐप्लिकेशन का मेनिफ़ेस्ट, इंस्टॉल करने की ज़रूरतों को पूरा करता है"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "असुरक्षित यूआरएल"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "सभी साइटों को HTTPS से सुरक्षित किया जाना चाहिए, चाहे उनमें संवेदनशील डेटा हो या नहीं. HTTPS की वजह से अनचाहे लोग (घुसपैठिये), आपके ऐप्लिकेशन और उसके उपयोगकर्ताओं के बीच होने वाली बातों को न तो सुन पाएंगे और न ही उसके साथ किसी तरह की छेड़खानी कर पाएंगे. HTTP/2 और कई नए वेब प्लेटफ़ॉर्म एपीआई पर इस सुविधा के बिना साइटें नहीं बनाई जा सकतीं. [ज़्यादा जानें](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 असुरक्षित अनुरोध मिला}one{# असुरक्षित अनुरोध मिले}other{# असुरक्षित अनुरोध मिले}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "HTTPS का इस्तेमाल नहीं किया जाता"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPS का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "सेल्युलर नेटवर्क पर तेज़ी से पेज लोड होने की सुविधा से मोबाइल इस्तेमाल करने वालों को अच्छा अनुभव मिलता है. [ज़्यादा जानें](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "इंटरैक्शन {timeInMs, number, seconds} से. में शुरू हुआ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "{timeInMs, number, seconds} से. में सिम्युलेट किए गए मोबाइल नेटवर्क पर इंटरैक्शन शुरू हुआ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "आपका पेज बहुत धीरे लोड होता है और 10 सेकंड में इंटरैक्टिव नहीं होता है. सुधार करने के तरीके जानने के लिए \"परफ़ॉर्मेंस\" सेक्शन में अवसरों पर नज़र डालें और गड़बड़ी की जानकारी लें."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "मोबाइल नेटवर्क पर पेज लोड होने की गति ज़रूरत के मुताबिक तेज़ नहीं है"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "मोबाइल नेटवर्क पर पेज लोड होने की गति ज़रूरत के मुताबिक तेज़ है"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "श्रेणी"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "मुख्य थ्रेड के काम को कम करना"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "मुख्य थ्रेड के काम को कम करता है"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "ज़्यादा से ज़्यादा उपयोगकर्ताओं तक पहुंचने के लिए, साइटों का सभी प्रमुख ब्राउज़र पर काम करना ज़रूरी है. [ज़्यादा जानें](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "यह वेबसाइट अलग-अलग ब्राउज़र पर काम करती है"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "पक्का करें कि हर पेज को यूआरएल के ज़रिए डीप लिंक किया जा सकता हो. साथ ही, वे ऐसे खास यूआरएल हों जिन्हें सोशल मीडिया पर शेयर किया जा सकता है. [ज़्यादा जानें](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "हर पेज का एक यूआरएल होता है"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Transitions should feel snappy as you tap around, even on a slow network. This experience is key to a user's perception of performance. [Learn more](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "पेज ट्रांज़िशन को देखकर ऐसा नहीं लगना चाहिए जैसे कि वे नेटवर्क लोड होने का इंतज़ार कर रहे हैं"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "इनपुट के इंतज़ार के समय का अंदाज़ा, इस बात से लगाया जाता है कि पेज लोड होने की सबसे व्यस्त पांच सेकंड की विंडो के दौरान आपके ऐप्लिकेशन को इस्तेमाल करने वाले के इनपुट का जवाब देने में कितना समय लगेगा. इस समय का हिसाब मिलीसेकंड में लगाया जाता है. अगर इंतज़ार का समय 50 मिलीसेकंड से ज़्यादा हो, तो इस्तेमाल करने वाले आपके ऐप्लिकेशन को धीमा मान सकते हैं. [ज़्यादा जानें](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "अनुमानित इनपुट प्रतीक्षा समय"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "फ़र्स्ट कॉन्टेंटफ़ुल पेंट से उस समय का पता चलता है जब पहले टेक्स्ट या इमेज को पेंट किया गया था. [ज़्यादा जानें](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "उपयोगी सामग्री वाला पहला पेंट"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "पहला सीपीयू (CPU) इस्तेमाल में नहीं"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "फ़र्स्ट मीनिंगफ़ुल पेंट, पेज की मुख्य सामग्री दिखाई देने का समय बताता है. [ज़्यादा जानें](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "पहला सार्थक पेंट"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "इंटरैक्टिव में लगने वाला समय, वह समय है जितनी देर में पेज पूरी तरह से इंटरैक्टिव हो जाता है. [ज़्यादा जानें](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "इंटरएक्टिव में लगने वाला समय"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "आपके उपयोगकर्ताओं को अनुभव होने वाले संभावित फ़र्स्ट इनपुट डिले में सबसे लंबे टास्क की अवधि शामिल होती है. यह वह डिले है जिसकी वजह से आपके उपयोगकर्ताओं को सबसे ज़्यादा देरी का सामना करना पड़ सकता है. यह अवधि मिलीसेकंड इकाई में बताई जाती है. [ज़्यादा जानें](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "सबसे ज़्यादा संभावित फ़र्स्ट इनपुट डिले"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "स्पीड इंडेक्स से पता चलता है कि किसी पेज की सामग्री, विज़ुअल रूप से कितनी तेज़ी से डाली गई है. [ज़्यादा जानें](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "गति इंडेक्स"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "टास्क में लगने वाले समय की अवधि 50 मि. से. से ज़्यादा होने पर एफ़सीपी और इंटरैक्टिव में लगने वाले समय के बीच के कुल समय. यह समय मिलिसेकंड इकाई में बताया जाता है."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "ब्लॉक होने का कुल समय"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "नेटवर्क के 'दोतरफ़ा यात्रा के समय' (आरटीटी) का परफ़ॉर्मेंस पर बहुत गहरा असर होता है. शुरुआत की जगह पर आरटीटी ज़्यादा होने से यह पता चलता है कि अगर सर्वर इस्तेमाल करने वालों के करीब होंगे, तो परफ़ॉर्मेंस बेहतर हो सकती है. [ज़्यादा जानें](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "नेटवर्क का दोतरफ़ा यात्रा का समय"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "सर्वर के इंतज़ार के समय का असर वेब परफ़ॉर्मेंस पर हो सकता है. शुरुआती जगह के सर्वर के 'इंतज़ार का समय' ज़्यादा होने से यह पता चलता है कि सर्वर ओवरलोड हो गया है या उसकी बैकएंड परफ़ॉर्मेंस खराब है. [ज़्यादा जानें](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "सर्वर बैकएंड के इंतज़ार का समय"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "सर्विस वर्कर की वजह से आपका वेब ऐप्लिकेशन ऑनलाइन, ऑफ़लाइन, और रुक-रुककर चलने वाले नेटवर्क जैसी स्थितियों में भी अच्छे ढंग से काम करता है. [ज़्यादा जानें](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ऑफ़लाइन होने पर, \"200\" कोड का जवाब नहीं देता है"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` ऑफ़लाइन होने पर, \"200\" कोड का जवाब देता है"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse, मेनिफ़ेस्ट फ़ाइल से `start_url` को नहीं ढूंढ सका. इसी वजह से, `start_url` को दस्तावेज़ का यूआरएल मान लिया गया. गड़बड़ी का मैसेज: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "बजट से ज़्यादा"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "नेटवर्क अनुरोधों की संख्या और उनकी क्वालिटी, आपको दिए गए परफ़ॉर्मेंस बजट की ओर से सेट किए गए लक्ष्यों के हिसाब से होनी चाहिए. [ज़्यादा जानें](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{अनुरोध}one{# अनुरोध}other{# अनुरोध}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "परफ़ॉर्मेंस बजट"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "अगर आप एचटीटीपीएस पहले ही सेट अप कर चुके हैं, तो पक्का करें कि अपने सभी उपयोगकर्ताओं के लिए सुरक्षित वेब फ़ीचर चालू करने के मकसद से आप सभी एचटीटीपी ट्रैफ़िक को एचटीटीपीएस पर रीडायरेक्ट करें. [ज़्यादा जानें](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "वेब पेज, एचटीटीपी ट्रैफ़िक को एचटीटीपीएस पर रीडायरेक्ट नहीं करता है"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "वेब पेज, एचटीटीपी ट्रैफ़िक को एचटीटीपीएस पर रीडायरेक्ट करता है"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "रीडायरेक्ट की वजह से पेज के लोड होने से लगने वाला समय और बढ़ जाता है. [ज़्यादा जानें](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "एक से ज़्यादा पेज रीडायरेक्ट करने से बचें"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "पेज संसाधनों की संख्या और आकार के बजट सेट करने के लिए, एक budget.json फ़ाइल जोड़ें. [ज़्यादा जानें](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 अनुरोध • {byteCount, number, bytes} केबी}one{# अनुरोध • {byteCount, number, bytes} केबी}other{# अनुरोध • {byteCount, number, bytes} केबी}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "अनुरोधों की संख्या कम और ट्रांसफ़र का आकार छोटा रखें"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "कैननिकल लिंक, खोज नतीजों में दिखाए जाने वाले यूआरएल के बारे में बताते हैं. [ज़्यादा जानें](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "कई कॉन्फ़्लिक्टिंग यूआरएल हैं ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "किसी दूसरे डोमेन की तरफ़ इशारा करता है ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "गलत यूआरएल ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "किसी दूसरी `hreflang` जगह वाली विशेषता ({url}) की तरफ़ इशारा करता है"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "मिलता-जुलता यूआरएल ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "मिलती-जुलती सामग्री वाले पेज पर ले जाने के बजाय डोमेन के रूट यूआरएल (होम पेज) पर ले जाता है"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "दस्तावेज़ में सही `rel=canonical` नहीं है"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "दस्तावेज़ में सही `rel=canonical` शामिल है"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "पढ़ने के नज़रिए से, 12px से कम आकार वाले फ़ॉन्ट काफ़ी छोटे होते हैं. ऐसा होने पर, मोबाइल से वेबसाइट पर आने वालों को पढ़ने के लिए “पिंच करके ज़ूम करना” होगा. कोशिश करें कि पेज का 60% से ज़्यादा टेक्स्ट 12px या उससे बड़े आकार का हो. [ज़्यादा जानें](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} टेक्स्ट पढ़ने लायक है"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "मोबाइल स्क्रीन के लिए कोई व्यूपोर्ट मेटा टैग ऑप्टिमाइज़ नहीं किए जाने की वजह से टेक्स्ट पढ़ने लायक नहीं है."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "टेक्स्ट का {decimalProportion, number, extendedPercent} बहुत छोटा है ({decimalProportionVisited, number, extendedPercent} नमूने पर आधारित)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "दस्तावेज़ पढ़ने लायक फ़ॉन्ट आकारों का इस्तेमाल नहीं करता है"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "दस्तावेज़ पढ़ने लायक फ़ॉन्ट आकारों का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang लिंक से सर्च इंजन को यह पता चलता है कि किसी खास भाषा या क्षेत्र के लिए पेज के किस वर्शन को खोज नतीजों में रखना चाहिए. [ज़्यादा जानें](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "दस्तावेज़ में सही `hreflang` नहीं है"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "दस्तावेज़ में सही `hreflang` शामिल है"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "ऐसे पेज ठीक से इंडेक्स नहीं किए जा सकते जिनमें काम न करने वाले एचटीटीपी स्टेटस कोड हों. [ज़्यादा जानें](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "पेज में काम नहीं करने वाला एचटीटीपी स्थिति कोड है"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "पेज में काम करने वाला एचटीटीपी स्थिति कोड है"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "अगर सर्च इंजन के पास आपके पेज क्रॉल करने की मंज़ूरी नहीं होती, तो वे खोज नतीजों में आपके पेज शामिल नहीं कर पाएंगे. [ज़्यादा जानें](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "पेज को इंडेक्स करने से ब्लॉक किया गया है"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "पेज को इंडेक्स करने से ब्लॉक नहीं किया गया है"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "लिंक की पूरी जानकारी देने वाले टेक्स्ट की मदद से सर्च इंजन आपकी सामग्री के बारे में समझ पाते हैं. [ज़्यादा जानें](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 लिंक मिला}one{# लिंक मिले}other{# लिंक मिले}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "लिंक में पूरी जानकारी देने वाला टेक्स्ट नहीं है"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "लिंक में पूरी जानकारी देने वाला टेक्स्ट है"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "स्ट्रक्चर्ड डेटा की पुष्टि करने के लिए [स्ट्रक्चर्ड डेटा टेस्टिंग टूल](https://search.google.com/structured-data/testing-tool/) और [ स्ट्रक्चर्ड डेटा लिंटर](http://linter.structured-data.org/) चलाएं. [ज़्यादा जानें](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "स्ट्रक्चर्ड डेटा सही है"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "खोज नतीजों में मुख्य जानकारी शामिल हो सकती है, ताकि पेज सामग्री के बारे में थोड़े शब्दों में खास जानकारी दी जा सके. [ज़्यादा जानें](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "ब्यौरे का टेक्स्ट खाली है."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "दस्तावेज़ में संक्षिप्त विवरण नहीं है"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "दस्तावेज़ में संक्षिप्त विवरण है"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "सर्च इंजन प्लग इन की सामग्री इंडेक्स नहीं कर सकते. साथ ही, कई डिवाइस प्लग इन पर पाबंदी लगाते हैं या वे उन पर काम नहीं करते. [ज़्यादा जानें](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "दस्तावेज़ प्लग इन का इस्तेमाल करता है"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "दस्तावेज़ प्लग इन से बचता है"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "अगर आपकी robots.txt फ़ाइल सही नहीं है, तो क्रॉलर यह नहीं समझ पाएंगे कि आप अपनी वेबसाइट को किस तरह क्रॉल या इंडेक्स करना चाहते हैं. [ज़्यादा जानें](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt के अनुरोध ने यह एचटीटीपी स्थिति लौटाई है: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 गड़बड़ी मिली}one{# गड़बड़ियां मिलीं}other{# गड़बड़ियां मिलीं}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse, robots.txt फ़ाइल डाउनलोड नहीं कर सका"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt सही नहीं है"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt सही है"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "बटन और लिंक जैसे इंटरैक्टिव एलिमेंट, आकार में बड़े (48x48px) होने चाहिए और इनके आस-पास बड़ी जगह होनी चाहिए. ऐसा करने से, दूसरे एलिमेंट को ओवरलैप किए बिना आसानी से उन पर टैप किया जा सकेगा. [ज़्यादा जानें](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} टैप की जाने वाली जगहें सही आकार में हैं"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "मोबाइल स्क्रीन के लिए कोई व्यूपोर्ट मेटा टैग ऑप्टिमाइज़ नहीं किए जाने की वजह से टैप की जाने वाली जगहें काफ़ी छोटी हैं"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "टैप की जाने वाली जगहें सही आकार में नहीं हैं"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "ओवरलैप करने वाली जगह"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "टैप की जाने वाली जगह"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "टैप की जाने वाली जगहें सही आकार में हैं"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "सर्विस वर्कर एक ऐसी तकनीक है जो आपके ऐप्लिकेशन के लिए कई प्रगतिशील वेब ऐप्लिकेशन फ़ीचर जैसे कि ऑफ़लाइन, होमस्क्रीन पर जोड़ें, और पुश नोटिफ़िकेशन को चालू करती है. [ज़्यादा जानें](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "इस पेज का नियंत्रण सर्विस वर्कर के पास है. हालांकि, कोई `start_url` नहीं मिला, क्योंकि मेनिफ़ेस्ट को मान्य JSON के रूप में पार्स नहीं किया जा सका"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "इस पेज का नियंत्रण सर्विस वर्कर के पास है. हालांकि, `start_url` ({startUrl}) सर्विस वर्कर के दायरे में नहीं है ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "इस पेज का नियंत्रण सर्विस वर्कर के पास है. हालांकि, कोई `start_url` नहीं मिला, क्योंकि किसी पेज पर कोई मेनिफ़ेस्ट ही नहीं था."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "यहां पर एक या ज़्यादा सर्विस वर्कर हैं. हालांकि, पेज ({pageUrl}) दायरे में नहीं है."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "किसी ऐसे सर्विस वर्कर को रजिस्टर नहीं करता जो पेज और `start_url` को नियंत्रित करता है"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "किसी ऐसे सर्विस वर्कर को रजिस्टर करता है जो पेज और `start_url` को नियंत्रित करता है"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "उपयोगकर्ता जब अपनी होमस्क्रीन से आपका ऐप्लिकेशन लॉन्च करते हैं, तो थीम वाली स्प्लैश स्क्रीन की वजह से इस्तेमाल करने वालों को अच्छा अनुभव मिलता है. [ज़्यादा जानें](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "पसंद के मुताबिक स्प्लैश स्क्रीन के लिए कॉन्फ़िगर नहीं किया गया"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "पसंद के मुताबिक स्प्लैश स्क्रीन के लिए कॉन्फ़िगर किया गया"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "ब्राउज़र के 'पता बार' की थीम ऐसी हो सकती है जो आपकी वेबसाइट से मेल खाए. [ज़्यादा जानें](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "'पता बार' के लिए थीम का रंग सेट नहीं करता है."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "'पता बार' के लिए थीम का रंग सेट करता है."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "मुख्य थ्रेड ब्लॉक होने का समय"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "तीसरा पक्ष"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "तीसरे पक्ष के कोड आपके पेज की लोड परफ़ॉर्मेंस पर गहरा असर कर सकते हैं. ऐसी तीसरे-पक्ष की सेवा देने वाली कंपनियों का इस्तेमाल ज़्यादा न करें जिनके कोड अब आपके काम के नहीं हैं. साथ ही, तीसरे पक्ष का कोड तब लोड करें जब आपके पेज पर मुख्य लोडिंग का काम पूरा हो गया हो. [ज़्यादा जानें](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "तीसरे पक्ष के कोड ने {timeInMs, number, milliseconds} एमएस के लिए मुख्य थ्रेड को ब्लॉक कर दिया है"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "तीसरे पक्ष के कोड का असर कम करें"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "इसका इस्तेमाल तीसरा पक्ष करता है"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "पहली बाइट का समय, उस समय की पहचान करता है जब आपका सर्वर कोई जवाब भेजता है. [ज़्यादा जानें](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "रुट दस्तावेज़ बनने में {timeInMs, number, milliseconds} मि.से. का समय लगा"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "सर्वर प्रतिक्रिया समय घटाएं (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "सर्वर के जवाब देने के समय धीमे हैं (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "कुल समय"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "शुरुआत का समय"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "प्रकार"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "मुख्य उपयोगकर्ता अनुभवों के दौरान, असली दुनिया के माप तैयार करने के लिए अपने ऐप्लिकेशन को 'उपयोगकर्ता समय एपीआई' की मदद से तैयार करें. [ज़्यादा जानें](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 उपयोगकर्ता समय}one{# उपयोगकर्ता समय}other{# उपयोगकर्ता समय}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "उपयोगकर्ता समय अंक और मापन"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "\"{securityOrigin}\" के लिए पहले से कनेक्ट किया गया <link> मिला, लेकिन ब्राउज़र ने इसका इस्तेमाल नहीं किया था. यह पक्का कर लें कि आप `crossorigin` विशेषता का इस्तेमाल ठीक से कर रहे हैं."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "तीसरे पक्ष से जल्दी कनेक्शन बनाने के लिए `preconnect` या `dns-prefetch` संसाधन संकेत जोड़ें. [ज़्यादा जानें](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "ज़रूरी मूल से प्री-कनेक्ट करें"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "\"{preloadURL}\" के लिए पहले से लोड किया गया <link> मिला, लेकिन ब्राउज़र ने इसका इस्तेमाल नहीं किया था. यह पक्का कर लें कि आप `crossorigin` विशेषता का इस्तेमाल ठीक से कर रहे हैं."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "`<link rel=preload>` का इस्तेमाल करके उन संसाधनों को पाने को प्राथमिकता दें जिन्हें फ़िलहाल पेज लोड में 'बाद में चाहिए होंगे' का दर्जा दिया गया है. [ज़्यादा जानें](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "प्रमुख अनुरोधों को पहले से लोड करें"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "अपने ऐप्लिकेशन को किसी भी मोबाइल स्क्रीन पर ऑप्टिमाइज़ करने के लिए `<meta name=\"viewport\">` टैग जोड़ें. [ज़्यादा जानें](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "कोई `<meta name=\"viewport\">` टैग नहीं मिला"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "वेब पेज पर कोई `width` या `initial-scale` वाला `<meta name=\"viewport\">` टैग नहीं है"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "वेब पेज पर `width` या `initial-scale` वाला `<meta name=\"viewport\">` टैग है"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "JavaScript बंद होने पर भी आपके ऐप्लिकेशन की कुछ सामग्री दिखाई देनी चाहिए. भले ही वह उपयोगकर्ता को दी जाने वाली एक चेतावनी हो कि ऐप्लिकेशन को इस्तेमाल करने के लिए JavaScript ज़रूरी है. [ज़्यादा जानें](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "अगर इसकी स्क्रिप्ट उपलब्ध नहीं हैं, तो पेज के मुख्य हिस्से को कुछ सामग्री रेंडर करनी चाहिए या उसकी इमेज बनानी चाहिए."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "यह वेब पेज, JavaScript उपलब्ध न होने पर फ़ॉलबैक सामग्री मुहैया नहीं कराता है"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "यह वेब पेज, JavaScript उपलब्ध नहीं होने पर कुछ सामग्री दिखाता है"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "अगर आप एक प्रगतिशील वेब ऐप्लिकेशन बना रहे हैं, तो सर्विस वर्कर का इस्तेमाल करें, ताकि आपका ऐप्लिकेशन ऑफ़लाइन भी काम कर सके. [ज़्यादा जानें](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "ऑफ़लाइन होने पर, मौजूदा पेज \"200\" कोड का जवाब नहीं देता है"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "ऑफ़लाइन होने पर, मौजूदा पेज \"200\" कोड का जवाब देता है"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "ऐसा हो सकता है कि ऑफ़लाइन होने पर पेज इसलिए लोड नहीं हो रहा है, क्योंकि आपका टेस्ट यूआरएल ({requested}) को \"{final}\" की ओर रीडायरेक्ट किया गया था. टेस्टिंग के लिए सीधे दूसरा यूआरएल आज़माएं."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "ये आपके ऐप्लिकेशन में ARIA के इस्तेमाल को बेहतर बनाने के अवसर हैं, जिससे उपयोगकर्ताओं का स्क्रीन रीडर जैसी सहायक तकनीक का अनुभव बेहतर हो सकता है."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "ये अवसर ऑडियो और वीडियो के लिए वैकल्पिक सामग्री मुहैया कराते हैं. इससे ऐसे इस्तेमाल करने वालों को बेहतर सुविधा मिल सकती है जो ठीक से सुन या देख नहीं पाते हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "ऑडियो और वीडियो"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "ये आइटम सुलभता के सबसे अच्छे सामान्य तरीके हाइलाइट करते हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "सबसे अच्छे तरीके"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "ये सभी जांच आपको [आपके वेब ऐप्लिकेशन की सुलभता बेहतर करने](https://developers.google.com/web/fundamentals/accessibility) के अवसर देती हैं. सुलभता गड़बड़ियों के सिर्फ़ एक उपसेट के बारे में अपने आप पता लगाया जा सकता है, इसलिए हम मैन्युअल टेस्टिंग का सुझाव देते हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "ये आइटम ऐसे मामलों में भी काम करते हैं जहां अपने आप काम करने वाला टेस्टिंग टूल नाकाम रहता है. हमारी गाइड में जाकर [सुलभता समीक्षा करने](https://developers.google.com/web/fundamentals/accessibility/how-to-review) के बारे में ज़्यादा जानें."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "सुलभता"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "आपकी सामग्री को पढ़ने में आसान बनाने के अवसर मौजूद हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "कंट्रास्ट"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "इन अवसरों की मदद से कई भाषाओं में उपयोगकर्ताओं के ज़रिए आपकी सामग्री के प्रस्तुतिकरण को बेहतर बनाया जा सकता है."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "अंतरराष्ट्रीय और स्थानीय भाषा के अनुसार"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "इन अवसरों से आपके ऐप्लिकेशन में नियंत्रणों के सीमेंटिक (शब्दार्थ विज्ञान) को बेहतर बनाया जा सकता है. इससे उपयोगकर्ता का स्क्रीन रीडर जैसी सहायक तकनीक का अनुभव बेहतर हो सकता है."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "नाम और लेबल"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "ये अवसर आपके ऐप्लिकेशन में कीबोर्ड नेविगेशन को बेहतर बनाते हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "नेविगेशन"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "ये अवसर स्क्रीन रीडर जैसी सहायक तकनीक का इस्तेमाल करके टेबल या सूची का डेटा पढ़ने की सुविधा बेहतर बनाते हैं."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "टेबल और सूचियां"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "सबसे अच्छे तरीके"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "परफ़ॉर्मेंस बजट बनाकर आप अपनी साइट की परफ़ॉर्मेंस के मानक तय करते हैं."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "बजट"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "आपके ऐप्लिकेशन के परफ़ॉर्मेंस के बारे में ज़्यादा जानकारी. इन आंकड़ों का परफ़ॉर्मेंस स्कोर पर [सीधा असर](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) नहीं पड़ता."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "निदान"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "परफ़ॉर्मेंस का सबसे अहम पहलू यह है कि स्क्रीन पर पिक्सेल कितनी तेज़ी से रेंडर होते हैं. प्रमुख मेट्रिक: उपयोगी सामग्री वाला पहला पेंट, पहला उपयोगी पेंट"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "पहले पेंट के सुधार"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "इन सुझावों से आप अपने पेज को तेज़ी से लोड करा सकते हैं. इनसे आपके परफ़ॉर्मेंस स्कोर पर [सीधा असर](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) नहीं होगा."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "अवसर"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "मेट्रिक"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "पूरे लोडिंग अनुभव को बेहतर बनाएं ताकि पेज जवाब दे और जल्दी से जल्दी इस्तेमाल के लिए तैयार हो जाए. प्रमुख मेट्रिक: इंटरेक्टिव में लगने वाला समय, गति इंडेक्स"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "समस्त सुधार"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "परफ़ॉर्मेंस"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "ये जांच प्रगतिशील वेब ऐप्लिकेशन के पहलुओं की पुष्टि करती हैं. [ज़्यादा जानें](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "इस तरह की जांच, बेसलाइन [PWA चेकलिस्ट](https://developers.google.com/web/progressive-web-apps/checklist) के लिए ज़रूरी हैं, लेकिन Lighthouse इनकी जांच अपने आप नहीं करता है. वे आपके स्कोर पर असर नहीं डालते हैं, लेकिन इनकी मैन्युअल तरीके से पुष्टि करना ज़रूरी है."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "प्रगतिशील वेब ऐप्लिकेशन"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "तेज़ और भरोसेमंद"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "इंस्टॉल किया जा सकता है"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA ऑप्टिमाइज़ किया गया"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "ये जांच पक्का करती हैं कि आपका पेज, सर्च इंजन के नतीजे रैंक करने के लिए ऑप्टिमाइज़ किया हुआ है. दूसरी वजहों से Lighthouse जांच नहीं करता है. इसका असर आपकी खोज की रैंकिंग पर हो सकता है. [ज़्यादा जानें](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "SEO के दूसरे सबसे अच्छे तरीके देखने के लिए अपनी साइट पर पुष्टि करने वाले ये और भी टूल चलाएं."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "अपने एचटीएमएल को इस तरह फ़ॉर्मैट करें जिससे क्रॉलर आपके ऐप्लिकेशन की सामग्री को बेहतर ढंग से समझ सकें."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "सामग्री से जुड़े सबसे अच्छे तरीके"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "खोज नतीजों में दिखाई देने के लिए, क्रॉलर को आपके ऐप्लिकेशन का ऐक्सेस चाहिए."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "क्रॉल करना और इंडेक्स करना"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "यह पक्का करें कि आपके पेज मोबाइल फ़्रेंडली हों. इससे सामग्री वाले पेज पढ़ने के लिए उपयोगकर्ताओं को पिंच या ज़ूम नहीं करना पड़ेगा. [ज़्यादा जानें](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "मोबाइल फ़्रेंडली"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "कैश TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "जगह की जानकारी"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "नाम"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "अनुरोध"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "संसाधन का प्रकार"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "आकार"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "बिताया गया समय"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "ट्रांसफ़र आकार"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "यूआरएल"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "संभावित बचत"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "संभावित बचत"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "{wastedBytes, number, bytes} केबी की संभावित बचत"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "{wastedMs, number, milliseconds} मि. से. की संभावित बचत"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "दस्तावेज़"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "फ़ॉन्ट"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "इमेज"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "मीडिया"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} मि.से."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "कोई दूसरा विकल्प"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "स्क्रिप्ट"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} से."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "स्टाइलशीट"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "तीसरा पक्ष"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "कुल"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "आपके पेज लोड में ट्रेस की रिकॉर्डिंग करते समय कोई गड़बड़ी हुई. कृपया Lighthouse को फिर से चलाएं. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "शुरुआती डीबगर प्रोटोकॉल कनेक्शन का इंतज़ार करते हुए समय खत्म हो गया."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome ने पेज लोड के दौरान कोई भी स्क्रीन शॉट इकट्ठा नहीं किया. कृपया पक्का करें कि पेज पर सामग्री दिखाई दे रही है. इसके बाद, Lighthouse को फिर से चलाकर देखें. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS सर्वर दिए गए डोमेन को हल नहीं कर सका."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "ज़रूरी {artifactName} इकट्ठा करने वाला संसाधन चलाने में गड़बड़ी हुई: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "एक अंदरूनी Chrome गड़बड़ी हुई. कृपया Chrome को रीस्टार्ट करें और Lighthouse को फिर से चलाकर देखें."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "ज़रूरी {artifactName} इकट्ठा करने वाला संसाधन नहीं चलाया जा सका."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse आपका अनुरोध किया गया पेज ठीक से लोड नहीं कर सका. पक्का करें कि आप सही यूआरएल को टेस्ट कर रहे हैं और सर्वर सभी अनुरोधों के लिए ठीक से काम कर रहा है."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse उस यूआरएल को भरोसेमंद रूप से लोड नहीं कर सका जिसका आपने अनुरोध किया था क्योंकि पेज ने काम करना बंद कर दिया था."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "आपके दिए यूआरएल में सही सुरक्षा सर्टिफ़िकेट नहीं है. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome ने वे पेज लोड नहीं किए जिन पर अचानक दिखने वाले विज्ञापन होते हैं. पक्का करें कि आप सही यूआरएल को टेस्ट कर रहे हैं और सर्वर सभी अनुरोधों के लिए ठीक से काम कर रहा है."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse आपका अनुरोध किया गया पेज ठीक से लोड नहीं कर सका. पक्का करें कि आप सही यूआरएल को टेस्ट कर रहे हैं और सर्वर सभी अनुरोधों के लिए ठीक से काम कर रहा है. (जानकारी: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse आपका अनुरोध किया गया पेज ठीक से लोड नहीं कर सका. पक्का करें कि आप सही यूआरएल को टेस्ट कर रहे हैं और सर्वर सभी अनुरोधों के लिए ठीक से काम कर रहा है. (स्थिति कोड: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "आपके पेज को लोड होने में बहुत ज़्यादा समय लगा. अपने पेज के लोड होने का समय कम करने के लिए, कृपया रिपोर्ट में दिए गए अवसरों का फ़ायदा लें. इसके बाद, Lighthouse को फिर से चलाकर देखें. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools प्रोटोकॉल जवाब के लिए इंतज़ार का समय, तय समय से ज़्यादा हो गया है. (तरीका:{protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "संसाधन की सामग्री लाने में दिए गए समय से ज़्यादा समय लगा"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "आपका दिया हुआ यूआरएल गलत लगता है."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "ऑडिट दिखाएं"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "शुरुआती नेविगेशन"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "पाथ का ज़्यादा से ज़्यादा अहम प्रतीक्षा समय:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "गड़बड़ी!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "गड़बड़ी की रिपोर्ट करें: कोई ऑडिट जानकारी नहीं"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "किसी नई या दुबारा जाँची जाने वाली ऐप्लिकेशन के लिए तैयार किया गया डेटा"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "एम्युलेट किए गए मोबाइल नेटवर्क पर मौजूद पेज का [Lighthouse](https://developers.google.com/web/tools/lighthouse/) विश्लेषण. मान अनुमान के हिसाब से लिखे गए हैं और इनमें अंतर हो सकता है."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "मैन्युअल रूप से देखे जाने वाले और ज़्यादा आइटम"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "लागू नहीं"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "अवसर"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "अनुमानित बचत"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "पास हुए ऑडिट"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "स्निपेट को छोटा करें"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "स्निपेट को बड़ा करें"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "तीसरे पक्ष के संसाधन दिखाएं"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "कुछ समस्याएं आने के कारण Lighthouse के इस रन पर असर पड़ा है:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "मान अनुमान के हिसाब से लिखे गए हैं और इनमें अंतर हो सकता है. परफ़ॉर्मेंस स्कोर सिर्फ़ [इन मेट्रिक पर आधारित ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) होता है."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "चेतावनियों के साथ पास हुए ऑडिट"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "चेतावनियां: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "किसी ऐसी सेवा में अपनी GIF अपलोड करने पर विचार करें जो उसे HTML5 वीडियो में एम्बेड करने के लिए उपलब्ध कराएगी."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "ऐसा [धीमे लोड होने वाले WordPress प्लग इन](https://wordpress.org/plugins/search/lazy+load/) इंस्टॉल करें जिसमें किसी भी ऑफ़स्क्रीन इमेज को अलग करने की सुविधा हो. अगर नहीं, तो किसी ऐसी थीम पर जाएं जो यह सुविधा मुहैया कराती हो. साथ ही, [एएमपी प्लग इन](https://wordpress.org/plugins/amp/) का इस्तेमाल करें."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "ऐसे कई WordPress प्लग इन हैं जो [क्रिटिकल एसेट इनलाइन करने ](https://wordpress.org/plugins/search/critical+css/) या [कम ज़रूरी संसाधनों को डेफ़र करने](https://wordpress.org/plugins/search/defer+css+javascript/) में आपकी मदद कर सकते हैं. ध्यान रखें कि ऐसी प्लग इन से मिलने वाले ऑप्टिमाइज़ेशन आपकी थीम या प्लग इन की सुविधाएं बिगाड़ सकते हैं. इसलिए, आपको कोड में बदलावों को करने की ज़रुरत हो सकती है."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "थीम, प्लगइन, और सर्वर की खास बातें सर्वर से जवाब मिलने के समय में योगदान करती हैं. ज़्यादा ऑप्टिमाइज़ की हुई थीम ढूंढने, एक ऑप्टिमाइज़ेशन प्लगइन को सावधानी से चुनने, और/या अपना सर्वर अपग्रेड करने पर विचार करें."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "अपनी पोस्ट सूचियों में खास हिस्से दिखाने पर विचार करें (जैसे 'ज़्यादा' टैग से), किसी पेज पर दिखाई गई पोस्ट की संख्या घटाने, अपनी लंबी पोस्ट को कई पेज में बाँटने या फिर टिप्पणियों को धीरे-धीरे लोड करने वाले प्लगइन का इस्तेमाल करने पर विचार करें."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "कई [WordPress प्लग इन](https://wordpress.org/plugins/search/minify+css/) आपकी साइट की गति को बढ़ा सकते हैं. ऐसा करने के लिए वे आपके स्टाइल को जोड़ते हैं, उन्हें छोटा करते हैं, और कंप्रेस करते हैं. ऐसा हो सकता है कि आप काट-छांट करने के लिए, एक बिल्ड प्रोसेस का इस्तेमाल भी करना चाहें, अगर ऐसा करना मुमकिन हो."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "कई [WordPress प्लग इन](https://wordpress.org/plugins/search/minify+javascript/) आपकी साइट की गति को बढ़ा सकते हैं. ऐसा करने के लिए वह आपकी स्क्रिप्ट को जोड़ते हैं, उन्हें छोटा करते हैं, और कंप्रेस करते हैं. ऐसा हो सकता है कि आप काट-छांट करने की इस प्रक्रिया के लिए, एक बिल्ड प्रोसेस का इस्तेमाल भी करना चाहें, अगर ऐसा करना मुमकिन हो."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "उन [WordPress प्लग इन](https://wordpress.org/plugins/) की संख्या कम करके या स्विच करके देखें जो आपके पेज में ऐसी सीएसएस लोड कर रहे हैं जिसका कभी इस्तेमाल नहीं हुआ. Chrome DevTools में [कोड कवरेज](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) चलाकर उन प्लग इन की पहचान करें जो आपके पेज में गैर-ज़रूरी सीएसएस जोड़ रहे हैं. आप स्क्रिप्ट के यूआरएल से पहचान सकते हैं कि ऐसा किस थीम/प्लग इन ने किया. ऐसे प्लग इन खोजें जिनके पास उस सूची की कई स्टाइल शीट हैं जिसमें कोड कवरेज में बहुत से लाल निशान हैं. प्लग इन को स्क्रिप्ट तभी क्यू में लगानी चाहिए, अगर पेज पर उसका वाकई इस्तेमाल किया गया हो."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "उन [WordPress प्लग इन](https://wordpress.org/plugins/) की संख्या कम करके या स्विच करके देखें जो आपके पेज में ऐसी JavaScript लोड कर रहे हैं जिसका कभी इस्तेमाल नहीं हुआ. Chrome DevTools में [कोड कवरेज](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) चलाकर उन प्लग इन की पहचान करें जो आपके पेज में गैर-ज़रूरी JS जोड़ रहे हैं. आप स्क्रिप्ट के यूआरएल से पहचान सकते हैं कि ऐसा किस थीम/प्लग इन ने किया. ऐसे प्लग इन खोजें जिनके पास उस सूची में कई स्क्रिप्ट हैं जिसमें कोड कवरेज में बहुत से लाल निशान हैं. प्लग इन को स्क्रिप्ट तभी क्यू में लगानी चाहिए, अगर पेज पर उसका वाकई इस्तेमाल किया गया हो."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPress में ब्राउज़र कैशिंग](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching) के बारे में पढ़ें."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "ऐसे [इमेज ऑप्टिमाइज़ेशन WordPress प्लग इन](https://wordpress.org/plugins/search/optimize+images/) का इस्तेमाल करें जो आपकी क्वालिटी बरकरार रखते हुए आपकी इमेज कंप्रेस करता है."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "[मीडिया लाइब्रेरी](https://codex.wordpress.org/Media_Library_Screen) की मदद से इमेज सीधे अपलोड करें, ताकि आप यह पक्का कर सकें कि आपके पास इमेज के वे आकार मौजूद हैं जिनकी आपको ज़रूरत पड़ेगी. इसके बाद, उन्हें डालने के लिए मीडिया लाइब्रेरी या इमेज विजेट का इस्तेमाल करें, ताकि आप यह पक्का कर सकें कि सबसे बेहतर इमेज आकारों का इस्तेमाल किया गया है (इसमें जवाब देने वाले ब्रेकपॉइंट की इमेज भी शामिल हैं). `Full Size` इमेज का इस्तेमाल तब तक न करें जब तक डाइमेंशन उनके इस्तेमाल के हिसाब से ठीक न हों. [ज़्यादा जानें](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "आप अपने वेब सर्वर कॉन्फ़िगरेशन में टेक्स्ट कंप्रेस करने की सुविधा चालू कर सकते हैं."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "ऐसे [प्लग इन](https://wordpress.org/plugins/search/convert+webp/) या सेवा का इस्तेमाल करें जो आपकी अपलोड की गई इमेज को अपने आप ही सबसे सही फ़ॉर्मैट में बदल देगी."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hr.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hr.json
new file mode 100644
index 00000000000..78e5b08e15b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hr.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Pristupne tipke omogućuju korisnicima da se brzo usredotoče na određeni dio stranice. Za pravilno kretanje svaka pristupna tipka mora biti jedinstvena. [Saznajte više](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Vrijednosti `[accesskey]` nisu jedinstvene"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` vrijednosti su jedinstvene"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Svaki ARIA `role` podržava određeni podskup `aria-*` atributa. Njihovo nepodudaranje poništava `aria-*` atribute. [Saznajte više](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` ne podudaraju se sa svojim ulogama"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributi `[aria-*]` podudaraju se sa svojim ulogama"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Neke uloge ARIA-e zahtijevaju atribute koji opisuju stanje elementa čitačima zaslona. [Saznajte više](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Elementi `[role]` nemaju sve potrebne atribute `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` imaju sve obavezne atribute`[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Neke nadređene uloge ARIA moraju sadržavati posebne podređene uloge za izvršavanje svojih namijenjenih funkcija pristupačnosti. [Saznajte više](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementi s ARIA-om `[role]` koji zahtijevaju da podređeni elementi sadrže određenu ulogu `[role]` ne sadrže neke ili sve te obavezne podređene elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementi s ARIA-om `[role]` koji zahtijevaju da podređeni elementi sadrže određenu ulogu `[role]` imaju sve obavezne podređene elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Određene nadređene uloge moraju sadržavati neke podređene uloge ARIA kako bi mogle pravilno izvršavati namijenjene funkcije pristupačnosti. [Saznajte više](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Potrebni nadređeni element ne sadrži `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Potrebni nadređeni element sadrži `[role]`."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Uloge ARIA moraju sadržavati valjane vrijednosti da bi se mogle izvršavati njihove namijenjene funkcije pristupačnosti. [Saznajte više](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Vrijednosti `[role]` nisu valjane"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Vrijednosti `[role]` su valjane"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Pomoćne tehnologije, poput čitača zaslona, ne mogu tumačiti atribute ARIA s nevažećim vrijednostima. [Saznajte više](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atributi `[aria-*]` ne sadrže valjane vrijednosti"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atributi `[aria-*]` sadrže valjane vrijednosti"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Pomoćne tehnologije, poput čitača zaslona, ne mogu tumačiti atribute ARIA s nevažećim nazivima. [Saznajte više](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` nisu valjani ili su pogrešno napisani"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributi `[aria-*]` su valjani i nisu pogrešno napisani"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Titlovi omogućuju gluhim i nagluhim korisnicima uporabu audioelemenata jer pružaju ključne informacije, primjerice tko govori, što govori i druge informacije osim govora. [Saznajte više](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementima `<audio>` nedostaje element `<track>` s `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementi `<audio>` sadržavaju element `<track>` s `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementi koji nisu prošli provjeru"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Kada gumb nema pristupačan naziv, čitači zaslona najavljuju ga kao \"gumb\" te je on neupotrebljiv za korisnike koji se oslanjaju na čitače zaslona. [Saznajte više](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Gumbi nemaju pristupačan naziv"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Gumbi imaju pristupačan naziv"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Dodavanje načina za zaobilaženje repetitivnog sadržaja omogućuje korisnicima tipkovnice učinkovitije kretanje po stranici. [Saznajte više](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Stranica ne sadrži naslov, vezu za preskakanje ili regiju kao orijentir"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Stranica sadrži naslov, vezu za preskakanje ili regiju kao orijentir"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Mnogim je korisnicima teško ili nemoguće čitati tekst niskog kontrasta. [Saznajte više](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Boje u pozadini i prednjem planu nemaju zadovoljavajući omjer kontrasta."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Boje u pozadini i prednjem planu imaju zadovoljavajući omjer kontrasta"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Kada popisi definicija nisu valjano označeni, čitači zaslona mogu proizvesti zbunjujuć ili netočan izlaz. [Saznajte više](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Elementi `<dl>` ne sadrže samo pravilno naručene grupe `<dt>` i `<dd>`, elemente `<script>` ili `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` sadrži samo pravilno naručene grupe `<dt>` i `<dd>` `<script>` ili elemente `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Stavke na popisu definicija (`<dt>` i `<dd>`) moraju biti sadržane u nadređenom elementu `<dl>` da bi ih čitači zaslona mogli pravilno najaviti. [Saznajte više](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Stavke na popisu definicija nisu upakirane u elemente `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Stavke na popisu definicija upakirane su u elemente `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Naslov korisnicima čitača zaslona pruža pregled stranice, a korisnici tražilice značajno se na njega oslanjaju kako bi odredili je li neka stranica relevantna za njihovo pretraživanje. [Saznajte više](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument ne sadrži element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument sadrži element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Vrijednost atributa ID mora biti jedinstvena kako bi se spriječilo da pomoćne tehnologije propuste druge instance. [Saznajte više](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atributi `[id]` na stranici nisu jedinstveni."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atributi `[id]` na stranici su jedinstveni"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Korisnici čitača zaslona oslanjaju se na naslove okvira za opisivanje sadržaja okvira. [Saznajte više](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementi `<frame>` ili `<iframe>` nemaju naslov"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementi `<frame>` ili `<iframe>` imaju naslov"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ako za stranicu nije naveden atribut jezika, čitač zaslona pretpostavlja da je stranica na zadanom jeziku koji je korisnik odabrao prilikom postavljanja čitača zaslona. Ako stranica nije stvarno na zadanom jeziku, čitač zaslona možda neće ispravno najaviti tekst sa stranice. [Saznajte više](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Element `<html>` nema atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Element `<html>` ima atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Navođenje valjanog [BCP 47 jezika](https://www.w3.org/International/questions/qa-choosing-language-tags#question) pomaže čitačima zaslona u pravilnom najavljivanju teksta. [Saznajte više](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Element `<html>` ne sadrži valjanu vrijednost za atribut `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Element `<html>` ima valjanu vrijednost za svoj atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informativni elementi trebali bi sadržavati kratak, opisni zamjenski tekst. Ukrasni elementi mogu se zanemariti praznim atributom alt. [Saznajte više](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elementi slike nemaju atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elementi slike imaju `[alt]` atribute"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Kada se slika upotrebljava kao gumb `<input>`, navođenje zamjenskog teksta može pomoći korisnicima čitača zaslona da shvate svrhu gumba. [Saznajte više](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementi `<input type=\"image\">` nemaju tekst`[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementi `<input type=\"image\">` sadrže `[alt]` tekst"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Oznake osiguravaju da pomoćne tehnologije, poput čitača zaslona, pravilno najavljuju kontrole oblika. [Saznajte više](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Elementi oblika ne sadrže povezane oznake"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Elementi oblika imaju povezane oznake"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tablica koja se upotrebljava u svrhe izgleda ne smije sadržavati elemente podataka kao što su elementi th ili opis ili atribut sažetka jer to može zbuniti korisnike čitača zaslona. [Saznajte više](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Prezentacijski elementi za `<table>` ne izbjegavaju upotrebu atributa `<th>`, `<caption>` ili `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Prezentacijski elementi za `<table>` izbjegavaju upotrebu `<th>`, `<caption>` ili atributa `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Tekst veze (i zamjenski tekst za slike kada se upotrebljava kao veze) koji je prepoznatljiv, jedinstven i može se fokusirati omogućuje lakše kretanje korisnicima čitača zaslona. [Saznajte više](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Veze nemaju naziv koji je moguće raspoznati"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Veze imaju naziv koji je moguće raspoznati"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Čitači zaslona imaju poseban način najavljivanja popisa. Osiguravanje pravilne strukture popisa pomaže izlazu čitača zaslona. [Saznajte više](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Popisi ne sadrže samo elemente `<li>` i elemente koji podupiru skriptu (`<script>` i`<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Popisi sadrže samo elemente `<li>` i elemente koji podupiru skriptu (`<script>` i`<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Za čitače zaslona stavke na popisu (`<li>`) moraju biti sadržane unutar nadređenog `<ul>` ili `<ol>` kako bi ih se moglo pravilno najaviti. [Saznajte više](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Stavke popisa (`<li>`) nisu sadržane unutar nadređenih elemenata `<ul>` ili `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Stavke popisa (`<li>`) sadržane su unutar nadređenih elemenata `<ul>` ili `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Korisnici ne očekuju automatsko osvježavanje stranice, pa se fokus vraća na vrh stranice. To može biti frustrirajuće i zbuniti korisnike. [Saznajte više](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokument upotrebljava `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokument ne upotrebljava `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Onemogućavanje zumiranja problematično je za slabovidne korisnike koji se oslanjaju na povećavanje zaslona kako bi pravilno vidjeli sadržaj web-stranice. [Saznajte više](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` se upotrebljava u elementu `<meta name=\"viewport\">` ili je atribut `[maximum-scale]` manji od pet."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` se ne upotrebljava u elementu `<meta name=\"viewport\">` i atribut `[maximum-scale]` nije manji od pet."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Čitači zaslona ne mogu prevesti sadržaj osim teksta. Dodavanje zamjenskog teksta elementima `<object>` pomaže čitačima zaslona u prenošenju značenja korisnicima. [Saznajte više](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementi `<object>` nemaju tekst`[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementi `<object>` sadrže `[alt]` tekst"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Vrijednost viša od 0 podrazumijeva eksplicitno naređivanje kretanja. Iako je tehnički valjano, to često frustrira korisnike koji se oslanjaju na pomoćne tehnologije. [Saznajte više](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Neki elementi imaju vrijednost `[tabindex]` višu od 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nijedan element nema vrijednost `[tabindex]` veću od 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Čitači zaslona sadrže značajke za olakšavanje kretanja po tablicama. Potrebno je pripaziti da se ćelije `<td>` koje upotrebljavaju atribut `[headers]` odnose samo na druge ćelije u istoj tablici kako bi se korisnicima čitača zaslona omogućio bolji doživljaj. [Saznajte više](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Ćelije u elementu `<table>` koje upotrebljavaju atribut `[headers]` odnose se na element `id` koji nije pronađen unutar iste tablice."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Ćelije u elementu `<table>` koje upotrebljavaju atribut `[headers]` odnose se na ćelije tablice unutar iste tablice."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Čitači zaslona sadrže značajke za olakšavanje kretanja po tablicama. Osiguravanje da se zaglavlja tablice uvijek odnose na neki skup ćelija može poboljšati doživljaj za korisnike čitača zaslona. [Saznajte više](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementi `<th>` i elementi s`[role=\"columnheader\"/\"rowheader\"]` nemaju podatkovne ćelije koje oni opisuju."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementi `<th>` i elementi s `[role=\"columnheader\"/\"rowheader\"]` imaju podatkovne ćelije koje opisuju."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Navođenje valjanog [BCP 47 jezika](https://www.w3.org/International/questions/qa-choosing-language-tags#question) u elementima pomaže osigurati da čitač zaslona ispravno izgovara tekst. [Saznajte više](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atributi `[lang]` ne sadrže valjanu vrijednost"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributi `[lang]` imaju valjanu vrijednost"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Kada videozapis sadrži titlove, gluhim i nagluhim osobama jednostavnije je pristupiti njegovim informacijama. [Saznajte više](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementi `<video>` ne sadrže element `<track>` s `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementi `<video>` sadržavaju element `<track>` s `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audioopisi pružaju relevantne informacije za videozapise koje dijaloški okviri ne mogu pružiti, primjerice izraze lica i scene. [Saznajte više](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementi `<video>` ne sadrže element `<track>` s `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementi `<video>` sadržavaju element `<track>` s `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Za idealan izgled na iOS-u kad korisnici na početni zaslon dodaju progresivnu web-aplikaciju definirajte `apple-touch-icon`. Mora ukazivati na neprozirni kvadratni PNG od 192 px (ili 180 px). [Saznajte više](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Ne pruža valjani `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` je zastario; prednost ima `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Ima valjanu ikonu `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chromeova proširenja negativno su utjecala na izvedbu učitavanja ove stranice. Pokušajte pregledati stranicu anonimno ili putem Chromeovog profila bez proširenja."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Procjena skripte"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Raščlamba skripte"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Ukupno vrijeme CPU-a"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Savjetujemo vam da skratite vrijeme potrebno za raščlambu, kompiliranje i izvršavanje JS-a. Isporuka manjih JS-ova mogla bi vam pomoći da to postignete. [Saznajte više](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Skratite vrijeme izvršavanja JavaScripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Vrijeme izvršavanja JavaScripta"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Veliki GIF-ovi nisu učinkoviti za prikaz animiranog sadržaja. Savjetujemo vam da umjesto GIF-a upotrebljavate MPEG4/WebM videozapise za animacije i PNG/WebP za statične slike da biste smanjili količinu mrežnih bajtova. [Saznajte više](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Upotrebljavajte formate videozapisa za animirani sadržaj"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Za slike izvan zaslona i skrivene slike savjetujemo odgođeno učitavanje nakon što se učitaju svi kritični resursi da biste skratili vrijeme do interaktivnosti. [Saznajte više](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Odgodite slike izvan zaslona"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resursi blokiraju prvo renderiranje vaše stranice. Savjetujemo vam da kljulan JS/CSS isporučite u tekstu te da da odgodite sve JS-ove/stilove koji nisu ključni. [Saznajte više](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Uklonite resurse koji blokiraju generiranje"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Veliki mrežni resursi korisnicima uzrokuju stvarne novčane troškove i usko koreliraju s dugim vremenom učitavanja. [Saznajte više](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Ukupna veličina bila je {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Izbjegavajte ogromne mrežne resurse"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Izbjegava ogromne mrežne resurse"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Umanjenjem CSS datoteka mogu se smanjiti veličine mrežnih resursa. [Saznajte više](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Umanjite CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Umanjenjem JavaScript datoteka mogu se smanjiti veličine resursa i skratiti vrijeme raščlambe skripte. [Saznajte više](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Umanjite JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Uklonite nepotrebna pravila iz stilskih tablica i odgodite učitavanje CSS-a koji se ne koristi za sadržaj na vidljivom dijelu stranice kako biste smanjili nepotrebnu potrošnju bajtova u mrežnoj aktivnosti. [Saznajte više](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Uklonite CSS koji se ne koristi"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Uklonite JavaScript koji se ne koristi da biste smanjili potrošnju bajtova u mrežnoj aktivnosti."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Uklonite nekorišteni JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Dugotrajno predmemoriranje može ubrzati ponovljene posjete vašoj stranici. [Saznajte više](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je jedan resurs}one{Pronađen je # resurs}few{Pronađena su # resursa}other{Pronađeno je # resursa}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Poslužite statične elemente s pravilima učinkovitog predmemoriranja"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Upotrebljava pravila učinkovitog predmemoriranja za statične elemente"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimizirane slike učitavaju se brže i troše manje mobilnih podataka. [Saznajte više](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Kodirajte slike učinkovito"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Poslužite slike prikladnih veličina da biste uštedjeli mobilne podatke i poboljšali vrijeme učitavanja. [Saznajte više](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Postavite slike u odgovarajućoj veličini"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstualni resursi trebaju se posluživati s kompresijom (gzip, deflate ili brotli) radi minimiziranja ukupne količine mrežnih bajtova. [Saznajte više](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Omogućite sažimanje teksta"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formati slike kao što su JPEG 2000, JPEG XR i WebP često pružaju bolje sažimanje nego PNG ili JPEG, što znači brža preuzimanja i manju potrošnju podataka. [Saznajte više](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Poslužite slike u modernim formatima"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ako se širina sadržaja vaše aplikacije ne podudara s vidljivim dijelom, vaša aplikacija možda neće biti optimizirana za mobilne zaslone. [Saznajte više](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Veličina vidljivog dijela od {innerWidth} px ne podudara se s veličinom prozora od {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Sadržaj nije ispravne veličine za vidljivi dio."
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Sadržaj je ispravne veličine za vidljivi dio"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Lanci kritičkih zahtjeva u nastavku prikazuju koji se resursi učitavaju s visokim prioritetom. Savjetujemo vam da skratite duljinu lanaca, smanjite veličinu resursa za preuzimanje ili odgodite preuzimanje resursa koji nisu nužni kako biste poboljšali učitavanje stranice. [Saznajte više](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je jedan lanac}one{Pronađen je # lanac}few{Pronađena su # lanca}other{Pronađeno je # lanaca}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimizirajte dubinu kritičnih zahtjeva"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Ukidanje / upozorenje"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Redak"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Ukinuti API-ji na kraju će se ukloniti iz preglednika. [Saznajte više](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađeno je jedno upozorenje}one{Broj pronađenih upozorenja: #}few{Broj pronađenih upozorenja: #}other{Broj pronađenih upozorenja: #}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Upotrebljava ukinute API-je"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Izbjegava ukinute API-je"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Ukinuta je predmemorija aplikacije. [Saznajte više](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "„{AppCacheManifest}” je pronađen"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Upotrebljava predmemoriju aplikacije"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Izbjegava predmemoriju aplikacije"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Specificiranje vrste dokumenta (doctype) sprječava preglednik da prijeđe u način rada sa starijim značajkama. [Saznajte više](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Naziv vrste dokumenta (doctype) mora biti niz napisan malim slovima `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "URL mora sadržavati vrstu dokumenta."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Očekivani javni ID bit će prazan niz"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Očekivani ID sustava bit će prazan niz"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Stranici nedostaje vrsta dokumenta HTML, stoga pokreće način rada sa starijim značajkama"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Stranica ima HTML vrstu dokumenta"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Vrijednost"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Inženjeri za preglednike preporučuju da stranice sadrže manje od ~1500 DOM elemenata. Pravo mjesto jest drvo dubine < 32 elemenata te koje ima manje od 60 podređenih/nadređenih elemenata. Veliki DOM može povećati upotrebu memorije, uzrokovati duže [izračune stila](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) te dovesti do skupih [preoblikovanja izgleda](https://developers.google.com/speed/articles/reflow). [Saznajte više](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{Jedan element}one{# element}few{# elementa}other{# elemenata}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Izbjegavajte pretjeranu veličinu DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimalna dubina DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Ukupan broj elemenata DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimalni broj podređenih elemenata"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Izbjegava pretjeranu veličinu DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cilj"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Dodajte `rel=\"noopener\"` ili `rel=\"noreferrer\"` bilo kojoj eksternoj vezi da biste unaprijedili uspješnost i spriječili sigurnosne propuste. [Saznajte više](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Veze na odredišta različitih polazišta nisu sigurne"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Veze na odredišta različitih polazišta sigurne su"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nije moguće odrediti odredište sidrenja za ({anchorHTML}). Ako se ne upotrebljava kao hiperveza, razmislite o tome da uklonite target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Korisnici ne vjeruju web-lokacijama koje žele znati njihovu lokaciju bez konteksta ili ih takve web-lokacije zbunjuju. Razmislite o tome da umjesto toga zahtjev povežete s radnjama korisnika. [Saznajte više](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Zahtijeva dopuštenje za geolociranje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Izbjegava traženje dopuštenja za geolociranje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Verzija"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Sve pristupne JavaScript biblioteke otkrivene na stranici. [Saznajte više](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Pronađene JavaScript biblioteke"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Ako korisnici imaju spore veze, vanjske skripte koje se dinamički ubacuju pomoću `document.write()` mogu odgoditi učitavanje stranice za desetke sekundi. [Saznajte više](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Upotrebljava `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Izbjegava `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Najviši stupanj ozbiljnosti"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Verzija biblioteke"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Broj propusta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Neke skripte treće strane mogu sadržavati poznate sigurnosne propuste te ih napadači mogu lako identificirati i iskoristiti. [Saznajte više](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Otkriven je jedan sigurnosni propust}one{Broj otkrivenih sigurnosnih propusta: #}few{Broj otkrivenih sigurnosnih propusta: #}other{Broj otkrivenih sigurnosnih propusta: #}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Uključuje pristupne JavaScript biblioteke s poznatim sigurnosnim propustima"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Visok"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Nisko"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Srednje"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Izbjegava pristupne JavaScript biblioteke s poznatim sigurnosnim propustima"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Korisnici ne vjeruju web-lokacijama koje traže slanje obavijesti bez konteksta ili ih takve web-lokacije zbunjuju. Razmislite o tome da umjesto toga zahtjev povežete s pokretima korisnika. [Saznajte više](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Zahtijeva dopuštenje za obavještavanje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Izbjegava traženje dopuštenja za obavještavanje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementi koji nisu prošli provjeru"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Sprječavanje lijepljenja zaporke narušava kvalitetu dobrih sigurnosnih pravila. [Saznajte više](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Onemogućuje korisnicima lijepljenje u polja za zaporku"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Omogućuje korisnicima lijepljenje u polja za zaporku"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ima brojne prednosti u odnosu na HTTP/1.1, uključujući binarna zaglavlja, multipleksiranja i oglašavanja poslužitelja. [Saznajte više](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{Jedan zahtjev koji nije poslužen protokolom HTTP/2}one{Broj zahtjeva koji nisu posluženi protokolom HTTP/2: #}few{Broj zahtjeva koji nisu posluženi protokolom HTTP/2: #}other{Broj zahtjeva koji nisu posluženi protokolom HTTP/2: #}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Ne upotrebljava HTTP/2 za sve svoje resurse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Upotrebljava HTTP/2 za svoje resurse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Razmislite o tome da svoje pasivne slušatelje događaja označite kao `passive` da biste poboljšali rezultate pretraživanja. [Saznajte više](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Ne upotrebljava pasivne osluškivače za unaprjeđenje rezultata pretraživanja"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Upotrebljava pasivne osluškivače za unaprjeđenje rezultata pretraživanja"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Opis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Pogreške zabilježene u konzoli ukazuju na neriješene probleme. Rezultat su neuspjelih mrežnih zahtjeva i ostalih pitanja povezanih s preglednikom. [Saznajte više](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Pogreške preglednika zabilježene su u konzoli"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Na konzoli nema zabilježenih pogrešaka preglednika"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Iskoristite CSS značajku za prikaz fontova kako bi tekst bio vidljiv korisnicima dok se web-fontovi učitavaju. [Saznajte više](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Neka tekst ostaje vidljiv tijekom učitavanja web-fontova"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Sav tekst ostaje vidljiv tijekom učitavanja web-fontova"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse nije mogao automatski provjeriti vrijednost prikazanog fonta za sljedeći URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Omjer slike (stvarni)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Omjer slike (prikazane)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Dimenzije prikaza slike trebale bi odgovarati prirodnom omjeru slike. [Saznajte više](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Prikazuje slike netočnog omjera"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Prikazuje slike točnog omjera"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Nevažeće informacije o veličini slike {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Preglednici mogu proaktivno zatražiti od korisnika da dodaju vašu aplikaciju na početni zaslon, što može dovesti do veće angažiranosti. [Saznajte više](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifest web-aplikacije ne udovoljava zahtjevima za instalaciju"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifest web-aplikacije udovoljava zahtjevima za instalaciju"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nesiguran URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Sve web-lokacije trebale bi biti zaštićene HTTPS-om, čak i one koje ne obrađuju osjetljive podatke. HTTPS sprječava uljeze u neovlaštenom pristupu komunikacijama između vaše aplikacije i vaših korisnika te im onemogućuje pasivno slušanje tih komunikacija. Preduvjet je za HTTP/2 i API-je brojnih novih web-platformi. [Saznajte više](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je jedan zahtjev koji nije siguran}one{Broj pronađenih zahtjeva koji nisu sigurni: #}few{Broj pronađenih zahtjeva koji nisu sigurni: #}other{Broj pronađenih zahtjeva koji nisu sigurni: #}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Ne upotrebljava HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Upotrebljava HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Brzo učitavanje stranice putem mobilne mreže omogućuje dobar doživljaj korisnicima na mobilnim uređajima. [Saznajte više](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktivno u {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktivno na simuliranoj mobilnoj mreži za {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Vaša stranica presporo se učitava i nije interaktivna unutar deset sekundi. U odjeljku \"Izvedba\" pogledajte prilike i dijagnostiku da biste saznali kako je poboljšati."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Učitavanje stranice nije dovoljno brzo na mobilnim mrežama"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Učitavanje stranice dovoljno je brzo na mobilnim mrežama"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorija"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Savjetujemo vam da skratite vrijeme potrebno za raščlambu, kompiliranje i izvršavanje JS-a. Isporuka manjih JS-ova mogla bi vam pomoći da to postignete. [Saznajte više](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimizirajte rad glavne niti"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimizira rad glavne niti"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Da bi dosegle najveći broj korisnika, web-lokacije bi trebale funkcionirati u svakom značajnijem pregledniku. [Saznajte više](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Web-lokacija funkcionira na različitim preglednicima"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Pobrinite se da su sve individualne stranice dubinski povezane putem URL-a i da su URL-ovi jedinstveni radi dijeljenja na društvenim medijima. [Saznajte više](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Svaka stranica ima URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Pri dodirivanju stavki prijelazi bi trebali biti brzi, čak i na sporoj mreži. To je ključno za korisnikovu percepciju izvedbe. [Saznajte više](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Ne čini se da se prijelazi stranica blokiraju na mreži"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Procijenjena latencija unosa procjena je vremena koje je potrebno da vaša aplikacija reagira na korisnički unos, u milisekundama, tijekom najintenzivnijih pet sekundi učitavanja stranice. Ako je latencija viša od 50 ms, korisnici mogu doživjeti vašu aplikaciju kao usporenu. [Saznajte više](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Procijenjena latencija unosa"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Prvo renderiranje sadržaja označava vrijeme renderiranja prvog teksta ili slike. [Saznajte više](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Prvo bojenje sadržaja"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Prvi procesor u mirovanju označava prvi trenutak u kojem je glavna nit stranice dovoljno neopterećena da bi obradila unos. [Saznajte više](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Prvi procesor u mirovanju"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Prvo korisno renderiranje mjeri kada je vidljiv primarni sadržaj stranice. [Saznajte više](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Prvo smisleno bojenje"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Vrijeme do interaktivnosti količina je vremena koje je potrebno da stranica postane potpuno interaktivna. [Saznajte više](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Vrijeme do interaktivnosti"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Maksimalno potencijalno prvo kašnjenje unosa koje bi korisnik mogao doživjeti trajanje je, u milisekundama, najduljeg zadatka. [Saznajte više](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks. potencijalno kašnjenje odgovora na prvi unos"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indeks brzine prikazuje koliko se brzo sadržaj stranice vidljivo popunjava. [Saznajte više](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indeks brzine"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Zbroj svih razdoblja između PRS-a i vremena do interaktivnosti kada trajanje zadatka prelazi 50 ms, iskazano u milisekundama."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Ukupno vrijeme blokiranja"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Vrijeme od slanja upita do primanja odgovora (RTT) za mrežu ima velik utjecaj na izvedbu. Ako je RTT do polazišta visok, to je znak da bi poslužitelji bliže korisniku mogli poboljšati izvedbu. [Saznajte više](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Vrijeme od slanja upita do primanja odgovora za mrežu"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Latencije poslužitelja mogu utjecati na izvedbu na webu. Ako je latencija poslužitelja polazišta visoka, to je znak da je poslužitelj preopterećen ili da ima lošu pozadinsku izvedbu. [Saznajte više](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Pozadinske latencije poslužitelja"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Uslužni alat omogućava web-aplikaciji da bude pouzdana u nepredvidivim mrežnim uvjetima. [Saznajte više](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "Za `start_url` ne prikazuje se kôd 200 kad je offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "Za `start_url` prikazuje se kôd 200 kad je offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse nije mogao pročitati `start_url` iz manifesta. Zbog toga se pretpostavilo da je `start_url` URL dokumenta. Poruka pogreške: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Više od proračuna"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Zahtjeve za količinom i veličinom mreže održavajte ispod ciljeva utvrđenih danim proračunom za izvršavanje. [Saznajte više](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{Jedan zahtjev}one{Broj zahtjeva: #}few{Broj zahtjeva: #}other{Broj zahtjeva: #}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Proračun za izvedbu"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ako ste već postavili HTTPS, provjerite preusmjeravate li sav HTTP promet na HTTPS kako biste omogućili sigurne web-značajke za sve korisnike. [Saznajte više](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Ne preusmjerava HTTP promet na HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Preusmjerava HTTP promet na HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Preusmjeravanja uvode dodatna kašnjenja prije nego što se stranica može učitati. [Saznajte više](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Izbjegavajte višestruka preusmjeravanja stranica"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Da biste postavili proračune za količinu i veličinu resursa stranice, dodajte datoteku budget.json. [Saznajte više](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{Jedan zahtjev • {byteCount, number, bytes} KB}one{# zahtjev • {byteCount, number, bytes} KB}few{# zahtjeva • {byteCount, number, bytes} KB}other{# zahtjeva • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Neka zahtjevi budu malobrojni, a veličine prijenosa male"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanonske veze ukazuju na to koji URL prikazati u rezultatima pretraživanja. [Saznajte više](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Više URL-ova u sukobu ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Usmjerava na drugu domenu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Nevažeći URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Usmjerava na drugu `hreflang` lokaciju ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativni URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Upućuje na korijenski URL domene (početnu stranicu), a ne na ekvivalentnu stranicu sadržaja"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument ne sadrži valjanu vezu `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument ima valjani `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Fontovi manji od 12 px premali su da bi bili čitljivi, pa posjetitelji na mobilnim uređajima moraju zumirati prstima. Neka više od 60% teksta na stranici ima veličinu od najmanje 12px. [Saznajte više](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} čitljivog teksta"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Tekst nije čitljiv jer nijedna metaoznaka vidljivog dijela nije optimizirana za zaslone mobilnih uređaja."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} teksta nije dovoljno veliko (na temelju uzorka od {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokument ne sadrži čitljive veličine fontova"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokument upotrebljava čitljive veličine fontova"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Veze s atributom hreflang govore tražilicama koju verziju stranice trebaju navesti u rezultatima pretraživanja za određeni jezik ili regiju. [Saznajte više](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument ne sadrži važeći `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument ima valjani `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Stranice s neuspješnim HTTP kodom statusa možda se neće pravilno indeksirati. [Saznajte više](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Stranica ima neuspješan HTTP kôd statusa"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Stranica ima uspješan HTTP kôd statusa"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Tražilice ne mogu uključiti vaše stranice u rezultate pretraživanja ako nemaju dopuštenje da ih pretraže i indeksiraju. [Saznajte više](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Indeksiranje je stranice blokirano"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indeksiranje stranice nije blokirano"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Opisni tekst veze pomaže tražilicama da razumiju vaš sadržaj. [Saznajte više](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađena je jedna veza}one{Pronađena je # veza}few{Pronađene su # veze}other{Pronađeno je # veza}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Veze nemaju opisni tekst"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Veze sadrže deskriptivan tekst"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Pokrenite [Alat za testiranje strukturiranih podataka](https://search.google.com/structured-data/testing-tool/) i [Datoteku za provjeru koda (linter) strukturiranih podataka](http://linter.structured-data.org/) da biste potvrdili strukturirane podatke. [Saznajte više](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturirani su podaci važeći"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metaopisi mogu se uključiti u rezultate pretraživanja kako bi se jezgrovito sažeo sadržaj stranice. [Saznajte više](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Tekst opisa nema sadržaj."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument ne sadrži metaopis"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument sadrži metaopis"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Tražilice ne mogu indeksirati sadržaj dodataka, pa mnogi uređaji ograničavaju dodatke ili ih ne podržavaju. [Saznajte više](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument upotrebljava dodatke"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument izbjegava dodatke"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ako je vaša robots.txt datoteka oštećena, alati za indeksiranje možda neće moći razumjeti kako želite da se vaša web-lokacija pretraži ili indeksira. [Saznajte više](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Zahtjevi za robots.txt vraćaju HTTP status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Pronađena je jedna pogreška}one{Pronađena je # pogreška}few{Pronađene su # pogreške}other{Pronađeno je # pogrešaka}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse nije uspio preuzeti robots.txt datoteku"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt nije valjan"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt je valjan"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktivni elementi kao što su gumbi i veze trebali bi biti dovoljno veliki (48 x 48 px) i oko njih bi trebalo biti dovoljno prostora da ih se može lako dodirnuti bez preklapanja s drugim elementima. [Saznajte više](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} ciljeva dodira odgovarajuće veličine"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Ciljevi dodira nisu dovoljno veliki jer nijedna metaoznaka vidljivog dijela nije optimizirana za zaslone mobilnih uređaja"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Ciljevi dodira nisu odgovarajuće veličine"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Preklapanje cilja"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Cilj dodira"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Ciljevi dodira odgovarajuće su veličine"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Uslužni alat jest tehnologija koja aplikaciji omogućava korištenje brojnih značajki progresivne web-aplikacije, kao što je offline rad, dodavanje na početni zaslon i push obavijesti. [Saznajte više](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Ovom stranicom upravlja uslužni alat, no nije pronađen `start_url` jer manifest nije raščlanjen kao važeći JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Ovom stranicom upravlja uslužni alat, no `start_url` ({startUrl}) nije u rasponu uslužnog alata ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Ovom stranicom upravlja uslužni alat, no nije pronađen `start_url` jer nije dohvaćen manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ova izvor ima jedan ili više uslužnih alata, no stranica ({pageUrl}) nije u rasponu."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Ne registrira uslužni alat koji kontrolira stranicu i `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registrira uslužni alat koji upravlja stranicom i `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Tematski pozdravni zaslon pruža bolji doživljaj korisnicima koji pokreću vašu aplikaciju na početnom zaslonu. [Saznajte više](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nije konfigurirano za prilagođeni pozdravni zaslon"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfiguriran za prilagođeni pozdravni zaslon"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Adresna traka preglednika može se tematski podudarati s vašom web-lokacijom. [Saznajte više](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Ne postavlja boju teme za adresnu traku."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Postavlja boju teme za adresnu traku."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Vrijeme blokiranja glavne niti"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Treća strana"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kôd treće strane može znatno utjecati na uspješnost učitavanja. Ograničite broj suvišnih pružatelja treće strane i pokušajte učitati kôd treće strane nakon primarnog zavšetka učitavanja vaše stranice. [Saznajte više](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kôd treće strane blokirao je glavnu nit na {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Smanjite utjecaj koda trećih strana"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Upotreba treće strane"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Vrijeme do prvog bajta navodi vrijeme u koje poslužitelj šalje odgovor. [Saznajte više](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Za korijenski dokument bilo je potrebno {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Skratite vremena odgovora poslužitelja (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Poslužitelj odgovara sporo (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trajanje"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Vrijeme početka"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Vrsta"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Savjetujemo vam da na aplikaciju primijenite API za praćenje korisničkog vremena radi mjerenja izvedbe aplikacije u stvarnom vremenu tijekom važnih korisničkih doživljaja. [Saznajte više](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{Jedno praćenje korisničkog vremena}one{# praćenje korisničkog vremena}few{# praćenja korisničkog vremena}other{# praćenja korisničkog vremena}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Oznake i izmjere Praćenja korisničkog vremena"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Pronađen je <link> za pretpovezivanje za „{securityOrigin}”, ali ga preglednik nije upotrijebio. Provjerite upotrebljavate li atribut `crossorigin` pravilno."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Savjetujemo vam da dodate `preconnect` ili `dns-prefetch` prilagodbe resursa radi uspostavljanja ranih veza s važnim izvorima trećih strana. [Saznajte više](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Rano se povežite s potrebnim izvorima"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Za „{preloadURL}” pronađen je <link> za predučitavanje, no preglednik ga nije upotrijebio. Provjerite upotrebljavate li atribut `crossorigin` pravilno."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Savjetujemo vam da koristite `<link rel=preload>` da biste dali prednost dohvaćanju resursa koji se trenutačno traže kasnije u učitavanju stranice. [Saznajte više](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Unaprijed učitajte ključne zahtjeve"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Dodajte oznaku `<meta name=\"viewport\">` da biste optimizirali svoju aplikaciju za mobilne zaslone. [Saznajte više](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nijedna oznaka `<meta name=\"viewport\">` nije pronađena"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nema oznaku `<meta name=\"viewport\">` s `width` ili `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ima oznaku `<meta name=\"viewport\">` s `width` ili `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Vaša aplikacija trebala bi prikazati bilo kakav sadržaj kada je onemogućen JavaScript, čak i ako je to samo upozorenje da je JavaScript obavezan za korištenje aplikacije. [Saznajte više](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Tijelo stranice trebalo bi generirati bilo kakav sadržaj ako skripte nisu dostupne."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Ne pruža zamjenski sadržaj kada JavaScript nije dostupan"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Prikazuje se bilo kakav sadržaj kada JavaScript nije dostupan"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ako razvijate progresivnu web-aplikaciju, razmislite o korištenju uslužnog alata tako da aplikacija može funkcionirati offline. [Saznajte više](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Za trenutačnu stranicu ne prikazuje se kôd 200 kad je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Za trenutačnu stranicu prikazuje se kôd 200 kad je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Stranica se možda ne učitava offline jer je vaš testni URL ({requested}) preusmjeren na \"{final}\". Pokušajte izravno testirati drugi URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "To su prilike za poboljšanje uporabe sustava ARIA u vašoj aplikaciji, što može unaprijediti doživljaj za korisnike pomoćne tehnologije, primjerice čitača zaslona."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Ovo su prilike za poboljšanje zamjenskog sadržaja za zvuk i videoprikaz. To može poboljšati doživljaj za korisnike s oštećenjem sluha ili vida."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Zvuk i videoprikaz"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ove stavke ističu uobičajene najbolje primjere iz prakse za pristupačnost."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Najbolji primjeri iz prakse"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ove provjere ističu prilike za [poboljšanje pristupačnosti vaše web-aplikacije](https://developers.google.com/web/fundamentals/accessibility). Budući da se automatskom provjerom može otkriti samo dio poteškoća s pristupačnošću, savjetujemo i ručno testiranje."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Područja adresa za te stavke koja alat za automatizirano testiranje ne može pokriti. Saznajte više u našem vodiču o [provođenju pregleda pristupačnosti](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Pristupačnost"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "To su mogućnosti za poboljšanje čitljivosti vašeg sadržaja."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "To su prilike da unaprijedite tumačenje svojeg sadržaja za korisnike na različitim jezicima."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizacija i lokalizacija"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "To su prilike za poboljšanje semantike kontrola u vašoj aplikaciji. Na taj način možete poboljšati doživljaj za korisnike pomoćne tehnologije, primjerice čitača zaslona."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nazivi i oznake"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ovo su prilike za poboljšanje kretanja tipkovnicom u vašoj aplikaciji."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Kretanje"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Ovo su prilike za poboljšanje doživljaja čitanja podataka u tablicama ili na popisima koristeći se pomoćnim tehnologijama, primjerice čitačem zaslona."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tablice i popisi"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Najbolji primjeri iz prakse"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Proračuni za izvedbu postavljaju standarde izvedbe vaše stranice."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Proračuni"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Više informacija o izvedbi vaše aplikacije. Ovi brojevi ne [utječu izravno](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na rezultat izvedbe."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Dijagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Najkritičniji je aspekt izvedbe brzina kojom se pikseli generiraju na zaslonu. Ključni mjerni podaci: Prvo bojenje sadržaja, Prvo smisleno bojenje"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Poboljšanja prvog bojenja"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ovi prijedlozi mogu vam pomoći da brže učitate stranicu. Oni ne [utječu izravno](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na rezultat izvedbe."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Prilike"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Mjerni podaci"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Poboljšajte općeniti doživljaj učitavanja tako da stranica bude responzivna i spremna za upotrebu što je prije moguće. Ključni mjerni podaci: Vrijeme do interaktivnosti, Indeks brzine"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Općenita poboljšanja"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Izvedba"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Te provjere potvrđuju aspekte progresivne web-aplikacije. [Saznajte više](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Te su provjere potrebne za osnovni [PWA kontrolni popis](https://developers.google.com/web/progressive-web-apps/checklist), no Lighthouse ih ne izvodi automatski. One ne utječu na vaš rezultat, no važno je da ih ručno izvršite."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresivna web-aplikacija"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Brzo i pouzdano"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Može se instalirati"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA je optimiziran"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Ove provjere služe za optimizaciju vaše stranice za rangiranje rezultata tražilice. Lighthouse ne provjerava neke dodatne čimbenike koji mogu utjecati na vaše rangiranje u pretraživanju. [Saznajte više](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Pokrenite ove dodatne validatore na svojoj web-lokaciji da biste pregledali dodatne najbolje primjere iz prakse za SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatirajte HTML na način koji omogućuje alatima za indeksiranje da bolje razumiju sadržaj vaše aplikacije."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Najbolji primjeri sadržaja"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Da bi se vaša aplikacija pojavila u rezultatima pretraživanja, omogućite alatima za indeksiranje da joj pristupe."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Pretraživanje i indeksiranje"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Prilagodite svoje stranice mobilnim uređajima kako ih korisnici ne bi trebali sami povećavati da bi čitali sadržaj. [Saznajte više](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Prilagođeno mobilnim uređajima"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL predmemoriranja"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokacija"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Naziv"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Zahtjevi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Vrsta resursa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Veličina"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Utrošeno vrijeme"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Veličina prijenosa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potencijalna ušteda"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potencijalna ušteda"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potencijalna ušteda {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potencijalna ušteda {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Slika"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Mediji"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Drugo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skripta"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "List stila"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Treća strana"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Ukupno"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Nešto nije u redu sa snimanjem traga preko učitavanja stranice. Ponovno pokrenite Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Isteklo je vrijeme čekanja za inicijalnu vezu za protokol za otklanjanje pogrešaka."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome nije prikupio nikakve snimke zaslona tijekom učitavanja stranice. Provjerite je li sadržaj vidljiv na stranici, a zatim pokušajte ponovno pokrenuti Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS poslužitelji nisu mogli razriješiti navedenu domenu."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Potrebni prikupljač {artifactName} naišao je na pogrešku: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Došlo je do interne pogreške u Chromeu. Ponovo pokrenite Chrome i pokušajte ponovo pokrenuti Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Nije se pokrenuo potrebni prikupljač {artifactName}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse nije mogao pouzdano učitati stranicu koju ste zatražili. Provjerite testirate li ispravan URL i odgovara li poslužitelj pravilno na sve zahtjeve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse nije mogao pouzdano učitati URL koji ste zatražili jer je stranica prestala reagirati."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL koji ste naveli nema valjani sigurnosni certifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome je spriječio međuprostorno učitavanje stranice. Provjerite testirate li ispravan URL i odgovara li poslužitelj pravilno na sve zahtjeve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse nije mogao pouzdano učitati stranicu koju ste zatražili. Provjerite testirate li ispravan URL i odgovara li poslužitelj pravilno na sve zahtjeve. (Pojedinosti: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse nije mogao pouzdano učitati stranicu koju ste zatražili. Provjerite testirate li ispravan URL i odgovara li poslužitelj pravilno na sve zahtjeve. (Statusni kôd: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Učitavanje stranice trajalo je predugo. Slijedite mogućnosti u izvješću da biste smanjili vrijeme učitavanja stranice, a zatim pokušajte ponovno pokrenuti Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Čekanje odgovora protokola DevTools premašilo je dodijeljeno vrijeme. (Način: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Dohvaćanje sadržaja resursa premašilo je dodijeljeno vrijeme"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Čini se da URL koji ste naveli nije važeći."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Prikažite preglede"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Početna navigacija"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimalna latencija kritičkog puta:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Pogreška!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Pogreška izvješća: nema podataka o pregledu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratorijski podaci"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analiza trenutačne stranice na emuliranoj mobilnoj mreži. Vrijednosti se procjenjuju i mogu se razlikovati."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Dodatne stavke za ručnu provjeru"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nije primjenjivo"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Prilika"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Procijenjena ušteda"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Uspješni pregledi"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Sažmi isječak"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Proširi isječak"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Pokaži resurse treće strane"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Na ovo izvođenje Lighthousea utjecale su neke poteškoće:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Vrijednosti se procjenjuju i mogu se razlikovati. Rezultat izvedbe jest [, a temelji se samo na ovim mjernim podacima ](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Uspješni pregledi no s upozorenjima"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Upozorenja: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Savjetujemo vam da prenesete GIF na uslugu na kojoj će se kodirati za ugrađivanje kao HTML5 videozapis."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instalirajte [WordPressov dodatak za lijeno učitavanje](https://wordpress.org/plugins/search/lazy+load/) koji pruža mogućnost odgode slika koje nisu na zaslonu ili prijeđite na temu koja pruža tu funkciju. Savjetujemo vam i upotrebu [dodatka za AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Brojni WordPressovi dodaci omogućuju vam da [ugradite kritične elemente](https://wordpress.org/plugins/search/critical+css/) ili [odgodite nevažnije resurse](https://wordpress.org/plugins/search/defer+css+javascript/). Upozoravamo da optimizacije koje pružaju ti dodaci mogu oštetiti značajke vaše teme ili dodataka, pa ćete vjerojatno trebati unijeti promjene u kôd."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Specifikacije za teme, dodatke i poslužitelj produljuju vrijeme odgovora poslužitelja. Savjetujemo vam da pronađete optimiziraniju temu, pažljivo odaberete dodatak za optimizaciju i/ili nadogradite poslužitelj."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Savjetujemo vam da prikažete odlomke na popisu postova (na primjer pomoću više oznaka), smanjite broj postova koji se prikazuju na određenoj stranici, razlomite dugačke postove na više stranica ili koristite dodatak za lijeno učitavanje komentara."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Brojni [WordPressovi dodaci](https://wordpress.org/plugins/search/minify+css/) mogu ubrzati vašu web-lokaciju ulančavanjem, umanjivanjem i komprimiranjem stilova. Umanjivanje je dobro izvršiti i unaprijed, tijekom postupka razvoja."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Brojni [WordPressovi dodaci](https://wordpress.org/plugins/search/minify+javascript/) mogu ubrzati vašu web-lokaciju ulančavanjem, umanjivanjem i komprimiranjem skripti. Umanjivanje je dobro izvršiti i unaprijed, tijekom postupka razvoja."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Savjetujemo vam da smanjite broj [WordPressovih dodataka](https://wordpress.org/plugins/) koji učitavaju CSS koji se ne koristi na vašoj stranici ili da ih isključite. Da biste pronašli dodatke koji dodaju suvišan CSS, pokrenite [pokrivenost koda](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) u alatu Chrome DevTools. Odgovornu temu ili dodatak možete pronaći u URL-u stilske tablice. Obratite pažnju na dodatke koji na popisu imaju mnogo stilskih tablica s mnogo crvenog u pokrivenosti koda. Dodatak bi trebao postaviti stilsku tablicu u red samo ako se ona doista upotrebljava na stranici."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Savjetujemo vam da smanjite broj [WordPressovih dodataka](https://wordpress.org/plugins/) koji učitavaju JavaScript koji se ne koristi na vašoj stranici ili da ih isključite. Da biste pronašli dodatke koji dodaju suvišan JS, pokrenite [pokrivenost koda](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) u alatu Chrome DevTools. Odgovornu temu ili dodatak možete pronaći u URL-u skripte. Obratite pažnju na dodatke koji na popisu imaju mnogo skripti s mnogo crvenog u pokrivenosti koda. Dodatak bi trebao postaviti skriptu u red samo ako se ona doista upotrebljava na stranici."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Pročitajte više o [predmemoriranju koje preglednici obavljaju u WordPressu](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Savjetujemo vam upotrebu [WordPressovog dodatka za optimizaciju slika](https://wordpress.org/plugins/search/optimize+images/) koji komprimira slike bez gubitka kvalitete."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Prenesite slike izravno pomoću [medijske biblioteke](https://codex.wordpress.org/Media_Library_Screen) kako bi bile dostupne potrebne veličine slika, a zatim ih umetnite iz medijske biblioteke ili upotrijebite widget za slike da bi se koristile optimalne veličine slika (uključujući one za responzivne prijelomne točke). Izbjegavajte upotrebu slika `Full Size` osim ako dimenzije odgovaraju njihovoj upotrebi. [Saznajte više](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Možete omogućiti kompresiju teksta u konfiguraciji web-poslužitelja."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Savjetujemo vam upotrebu [dodatka](https://wordpress.org/plugins/search/convert+webp/) ili usluge koji će automatski konvertirati prenesene slike u optimalne formate."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hu.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hu.json
new file mode 100644
index 00000000000..954acd0492d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/hu.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "A hozzáférési kulcsok segítségével a felhasználók gyorsan fókuszálhatnak az oldal adott részére. A megfelelő navigáció érdekében az összes hozzáférési kulcsnak egyedinek kell lennie. [További információ](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "A(z) `[accesskey]` értékek nem egyediek"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "A következő értékek egyediek: `[accesskey]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Minden egyes ARIA `role` szerepkör `aria-*` attribútumok konkrét részhalmazát támogatja. A hibás párosításuk érvényteleníti a(z) `aria-*` attribútumokat. [További információ](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Bizonyos `[aria-*]` attribútumok nem felelnek meg szerepkörüknek"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "A(z) `[aria-*]` attribútumok megfelelnek szerepüknek"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Bizonyos ARIA-szerepkörök kötelező attribútumokkal rendelkeznek, amelyek az elem állapotát írják le a képernyőolvasók számára. [További információ](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "A(z) `[role]` elemek nem rendelkeznek minden szükséges `[aria-*]` attribútummal"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "A(z) `[role]` attribútumok minden szükséges `[aria-*]` attribútummal rendelkeznek"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Bizonyos fölérendelt ARIA-szerepköröknek meghatározott alárendelt szerepköröket kell tartalmazniuk, hogy megfelelően teljesíthessék a kívánt kisegítő funkciójukat. [További információ](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Olyan ARIA `[role]` attribútummal rendelkező elemekből, melyek gyermekelemeiben kell lennie adott `[role]` attribútumnak, hiányzik ezeknek a kötelező gyermekelemeknek mindegyike vagy némelyike."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Olyan ARIA `[role]` attribútummal rendelkező elemekben, melyek gyermekelemeiben kell lennie adott `[role]` attribútumnak, megvan a kötelező gyermekelemek mindegyike."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Bizonyos alárendelt ARIA-szerepköröket meghatározott fölérendelt szerepköröknek kell tartalmazniuk, hogy megfelelően teljesíthessék a kívánt kisegítő funkciójukat. [További információ](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "A(z) `[role]` elemek nem a megfelelő szülőelemben vannak"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "A(z) `[role]` elemek a megfelelő szülőelemben vannak"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Az ARIA-szerepköröknek érvényes értékekkel kell rendelkezniük, hogy megfelelően teljesíthessék a kívánt kisegítő funkciójukat. [További információ](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "A(z) `[role]` értékek nem érvényesek"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "A(z) `[role]` értékek érvényesek"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "A kisegítő technológiák (például a képernyőolvasók) nem tudják értelmezni az érvénytelen értékkel rendelkező ARIA-attribútumokat. [További információ](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "A(z) `[aria-*]` attribútumoknak nincs érvényes értékük"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "A(z) `[aria-*]` attribútumok érvényes értékkel rendelkeznek"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "A kisegítő technológiák (például a képernyőolvasók) nem tudják értelmezni az érvénytelen névvel rendelkező ARIA-attribútumokat. [További információ](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "A(z) `[aria-*]` attribútumok nem érvényesek vagy elgépelést tartalmaznak"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "A(z) `[aria-*]` attribútumok érvényesek és nincsenek elgépelve"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "A feliratok a legfontosabb információk közlésével teszik használhatóvá az audioelemeket a siket és hallássérült felhasználók számára (például ki beszél, mit mond, valamint egyéb, nem beszédhez kötődő információk). [További információ](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "A(z) `<audio>` elemek nem rendelkeznek `[kind=\"captions\"]` tartalmú `<track>` elemmel."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "A(z) `<audio>` elemekhez `[kind=\"captions\"]` tartalmú `<track>` elem tartozik"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Hibás elemek"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Ha valamelyik gomb nem rendelkezik hozzáférhető névvel, a képernyőolvasók „gomb” néven olvassák fel, ami nem igazán hasznos a képernyőolvasóra hagyatkozó felhasználók számára. [További információ](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Bizonyos gombok nem rendelkeznek hozzáférhető névvel"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "A gombok rendelkeznek kisegítő névvel"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Az ismétlődő tartalmakat megkerülő módszerek megvalósításával a billentyűzetet használó személyek hatékonyabban navigálhatnak az oldalon. [További információ](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Az oldal nem tartalmaz címsort, átugró linket vagy igazodásipont-régiót"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Az oldal címsort, átugró linket vagy igazodásipont-régiót tartalmaz"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Az alacsony kontrasztú szöveg sokak számára nehezen vagy egyáltalán nem olvasható. [További információ](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Nem megfelelő a háttér- és előtérszínek közötti kontrasztarány."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Megfelelő a háttér- és előtérszínek közötti kontrasztarány"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Ha nem megfelelő a definíciós listák jelölése, a képernyőolvasók zavaros vagy pontatlan szöveget generálhatnak. [További információ](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "A(z) `<dl>` elemek nem csak megfelelően rendezett `<dt>` és `<dd>` csoportokat, illetve `<script>` vagy `<template>` elemeket tartalmaznak."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "A(z) `<dl>` elemek csak megfelelő sorrendű `<dt>` és `<dd>` csoportokat, illetve `<script>` vagy `<template>` elemeket tartalmaznak."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "A definíciós listák elemeit (`<dt>` és `<dd>`) `<dl>` szülőelembe kell foglalni, hogy a képernyőolvasók megfelelően felolvashassák őket. [További információ](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "A definíciós listák elemei nincsenek `<dl>` elemekben"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "A definíciós listák elemei `<dl>` elemekben vannak"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "A cím áttekintést ad az oldalról a képernyőolvasót használó személyeknek, a keresőmotorok pedig nagymértékben hagyatkoznak rá annak meghatározásához, hogy az oldal releváns-e az adott kereséshez. [További információ](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "A dokumentum nem rendelkezik `<title>` elemmel"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "A dokumentum tartalmaz `<title>` elemet"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Az „id” attribútum értékének egyedinek kell lennie, hogy a kisegítő technológiák ne hagyják figyelmen kívül a többi előfordulást. [További információ](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Az oldal `[id]` attribútumai nem egyediek"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Az oldalon található `[id]` attribútumok egyediek"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "A képernyőolvasók a keretcímek alapján írják le a keretek tartalmát. [További információ](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "A(z) `<frame>` és a(z) `<iframe>` elemeknek nincs címük"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Van címe a(z) `<frame>` és `<iframe>` elemeknek"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ha az oldal nem határoz meg „lang” attribútumot, a képernyőolvasók azt feltételezik majd, hogy az oldal nyelve megegyezik azzal az alapértelmezett nyelvvel, amelyet a felhasználó a képernyőolvasó beállításakor választott. Ha az oldal tényleges nyelve eltér az alapértelmezett nyelvtől, akkor előfordulhat, hogy a képernyőolvasók helytelen kiejtéssel olvassák majd fel az oldal szövegét. [További információ](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "A(z) `<html>` elem nem rendelkezik `[lang]` attribútummal"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "A(z) `<html>` elemhez tartozik `[lang]` attribútum"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ha érvényes [BCP 47 által definiált nyelvet](https://www.w3.org/International/questions/qa-choosing-language-tags#question) használ, a képernyőolvasók könnyebben felolvassák a szövegeket. [További információ](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "A(z) `<html>` elem `[lang]` attribútumának nincs érvényes értéke."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "A(z) `<html>` elem `[lang]` attribútumának értéke érvényes"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Rövid, beszédes alternatív szöveget használjon a tájékoztató elemekhez. A díszítőelemek figyelmen kívül hagyhatók üres „alt” attribútummal. [További információ](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "A képelemekhez nem tartozik `[alt]` attribútum"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "A képelemekhez tartozik `[alt]` attribútum"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Ha a(z) `<input>` típusú gombként használt képekhez alternatív szöveget is megad, segíthet a képernyőolvasót használó látogatóknak a gomb rendeltetésének megértésében. [További információ](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "A(z) `<input type=\"image\">` elemekhez nem tartozik `[alt]` szöveg"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "A(z) `<input type=\"image\">` elemek rendelkeznek `[alt]` szöveggel"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "A címkék biztosítják, hogy a kisegítő technológiák (pl. a képernyőolvasók) megfelelően jelezzék az űrlapvezérlőket. [További információ](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Bizonyos formátumelemek nem rendelkeznek társított címkékkel"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "A formátumelemekhez megfelelő címkék vannak társítva"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Az elrendezési célokat szolgáló táblázat ne tartalmazzon adatelemeket (pl. „th” vagy „caption” elemet, illetve „summary” attribútumot), mert zavarók lehetnek a képernyőolvasót használó személyek számára. [További információ](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "A prezentációs `<table>` elemek nem kerülik a(z) `<th>`, a(z) `<caption>` vagy a(z) `[summary]` attribútum használatát."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "A prezentációs `<table>` elemek kerülik a(z) `<th>`, a(z) `<caption>` vagy a(z) `[summary]` attribútum használatát."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "A felismerhető, egyedi és fókuszálható linkszövegek (és linkként használt képek alternatív szövegei) jobb navigációs élményt biztosítanak a képernyőolvasóra hagyatkozó felhasználók számára. [További információ](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "A linkekhez nem tartozik felismerhető név"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "A linkekhez felismerhető név tartozik"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "A képernyőolvasók sajátos módon olvassák fel a listákat. A megfelelő listastruktúra biztosítása segíti a képernyőolvasók működését. [További információ](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "A listák nem csak `<li>` elemeket és szkripttámogató elemeket (`<script>` és `<template>`) tartalmaznak."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "A listák csak `<li>` elemeket és szkripttámogató elemeket (`<script>`, `<template>`) tartalmaznak."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "A listaelemeket (`<li>`) fölérendelt `<ul>` vagy `<ol>` elemekben kell elhelyezni, hogy a képernyőolvasók megfelelően olvassák fel őket. [További információ](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "A listaelemek (`<li>`) nem `<ul>` vagy `<ol>` szülőelemekben vannak."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "A listaelemek (`<li>`) `<ul>` vagy `<ol>` szülőelemekben vannak"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "A felhasználók nem számítanak az oldal automatikus frissítésére, ráadásul a frissítés visszahelyezi a fókuszt az oldal tetejére. Ez frusztráló lehet, valamint összezavarhatja a felhasználót. [További információ](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "A dokumentum `<meta http-equiv=\"refresh\">` címkét használ"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "A dokumentum nem használja a(z) `<meta http-equiv=\"refresh\">` címkét"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "A nagyítás letiltása problémát jelent a gyengén látó felhasználók számára, akik a képernyőnagyításra hagyatkoznak ahhoz, hogy megfelelően láthassák a weboldal tartalmát. [További információ](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "A(z) `[user-scalable=\"no\"]` szerepel a(z) `<meta name=\"viewport\">` elemben, vagy a(z) `[maximum-scale]` attribútum 5-nél kisebb."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Nem használja a(z) `[user-scalable=\"no\"]` attribútumot a(z) `<meta name=\"viewport\">` elemben, a(z) `[maximum-scale]` attribútum pedig nem kevesebb 5-nél."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "A képernyőolvasók nem tudják lefordítani a nem szövegalapú tartalmakat. Ha alternatív szöveget helyez el a(z) `<object>` elemekben, a képernyőolvasók kommunikálhatják az elemek jelentését a felhasználóknak. [További információ](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "A(z) `<object>` elemekhez nem tartozik `[alt]` szöveg"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "A(z) `<object>` elemek rendelkeznek `[alt]` szöveggel"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "A 0-nál nagyobb érték explicit navigációs sorrendet jelent. Ez ugyan technikailag érvényes, azonban gyakran problémát jelent a kisegítő technológiákra hagyatkozó felhasználók számára. [További információ](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Bizonyos elemek `[tabindex]` attribútuma 0-nál nagyobb értékkel rendelkezik."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Egyetlen elem `[tabindex]` attribútumának sem 0-nál nagyobb az értéke"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "A képernyőolvasók olyan funkciókkal is rendelkeznek, amelyek megkönnyítik a táblázatokban való navigációt. Ha a(z) `[headers]` attribútumot használó `<td>` cellák csak a saját táblázatuk más celláira hivatkoznak, jobb felhasználói élményt nyújthat a képernyő felolvasása során. [További információ](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Az egyik `<table>` elemben lévő, `[headers]` attribútumot használó cellák olyan `id` elemre hivatkoznak, amely nem található meg ugyanabban a táblázatban."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Az egyik `<table>` elemben lévő, `[headers]` attribútumot használó cellák a saját táblázatuk celláira hivatkoznak."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "A képernyőolvasók olyan funkciókkal is rendelkeznek, amelyek megkönnyítik a táblázatokban való navigációt. Ha biztosítja, hogy a táblák fejlécei mindig hivatkozzanak cellákra, megkönnyítheti az oldal használatát a képernyőolvasóra hagyatkozó felhasználók számára. [További információ](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "A(z) `<th>` elemekhez és a(z) `[role=\"columnheader\"/\"rowheader\"]` tartalmú elemekhez nem tartoznak általuk leírt adatcellák."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "A(z) `<th>` elemek és a(z) `[role=\"columnheader\"/\"rowheader\"]` tartalmú elemek rendelkeznek a leírt adatcellákkal."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ha az elemeken érvényes [BCP 47 által definiált nyelvet](https://www.w3.org/International/questions/qa-choosing-language-tags#question) határoz meg, akkor segíthet a képernyőolvasóknak a szöveg helyes kiejtésében. [További információ](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "A(z) `[lang]` attribútumokhoz nem tartozik érvényes érték"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "A(z) `[lang]` attribútumok érvényes értékkel rendelkeznek"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Ha a videóhoz felirat tartozik, a siket és hallássérült felhasználók egyszerűbben hozzájuthatnak a videóban található információkhoz. [További információ](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "A(z) `<video>` elemekhez nem tartozik `[kind=\"captions\"]` tartalmú `<track>` elem."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "A(z) `<video>` elemekhez `[kind=\"captions\"]` tartalmú `<track>` elem tartozik"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Az audiokommentárok olyan fontos információkat nyújtanak a videókhoz, amelyek a párbeszédekből nem derülnek ki (ilyen például az arckifejezések és a jelenetek leírása). [További információ](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "A(z) `<video>` elemekhez nem tartozik `[kind=\"description\"]` tartalmú `<track>` elem."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "A(z) `<video>` elemekhez `[kind=\"description\"]` tartalmú `<track>` elem tartozik"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Ha azt szeretné, hogy a megjelenés ideális legyen iOS rendszeren, amikor a felhasználók progresszív webes alkalmazást adnak hozzá a kezdőképernyőhöz, határozzon meg egy `apple-touch-icon` elemet. Az ikonnak 192 képpont (vagy 180 képpont) méretű, nem átlátszó, négyzetes PNG-re kell mutatnia. [További információ](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Nincs érvényes `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "A(z) `apple-touch-icon-precomposed` elavult; a(z) `apple-touch-icon` használandó helyette."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Érvényes `apple-touch-icon` elemet tartalmaz"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Egyes Chrome-bővítmények kedvezőtlenül befolyásolták az oldal betöltési teljesítményét. Próbálkozzon az oldal inkognitómódban vagy bővítmények nélküli Chrome-profilból történő ellenőrzésével."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Szkriptértékelés"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Szkriptelemzés"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Teljes processzoridő"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Érdemes csökkenteni a JavaScript értelmezésére, összeállítására és végrehajtására fordított időt. Ebben segíthet, ha kisebb méretű JavaScript-forrásokat továbbít. [További információ](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Csökkentse a JavaScript végrehajtási idejét"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript végrehajtási ideje"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "A túl nagy GIF-fájlokkal nem lehet hatékonyan animált tartalmakat nyújtani. Az adatforgalom csökkentésének érdekében a GIF-ek helyett érdemes az animációkhoz MPEG4-/WebM-videókat használnia, a statikus képekhez pedig PNG-/WebP-képeket. [További információ](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Használjon videoformátumot az animált tartalmakhoz"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Vegye fontolóra a képernyőn kívüli és rejtett képek késleltetett, kritikus források utáni betöltését, hogy az oldal hamarabb interaktívvá váljon. [További információ](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Késleltesse a képernyőn kívüli képek betöltését"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Források blokkolják az oldal első vizuális válaszát. Javasoljuk, hogy a legfontosabb JavaScript-/CSS-elemeket beágyazva továbbítsa, a nem fontos JS-t/CSS-t pedig késleltesse [További információ](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Távolítsa el a megjelenítést gátló erőforrásokat"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "A nagy hálózati terhelés tényleges anyagi költséget jelenthet a felhasználóknak, és jellemzően jelentősen megnöveli a betöltési időt. [További információ](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "A teljes méret {totalBytes, number, bytes} kB volt"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Kerülje a nagyon nagy hálózati hasznosadat-forgalmat"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "A nagyon nagy hálózati terhelés elkerülése"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "A CSS-fájlok minimalizálása csökkentheti a hálózaton továbbított adatok méretét. [További információ](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minimalizálja a CSS-fájlokat"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "A JavaScript-fájlok minimalizálásával csökkenthető a továbbított adatok mérete és a szkriptek értelmezésére fordított idő. [További információ](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minimalizálja a JavaScript-kódot"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "A stíluslapok érvénytelen szabályainak eltávolításával és a hajtás feletti tartalomhoz nem használt CSS-kód betöltésének késleltetésével csökkentheti a hálózati tevékenység által felhasznált bájtmennyiséget. [További információ](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Távolítsa el a nem használt CSS-kódot"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "A nem használt JavaScript-kód eltávolítása a hálózati tevékenység adatforgalmának csökkentéséhez."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Távolítsa el a nem használt JavaScript-kódot"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Ha a gyorsítótárak élettartama hosszú, gyorsabbá válnak a weboldal későbbi ismételt megnyitásai. [További információ](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 erőforrás található}other{# erőforrás található}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Jelenítse meg a statikus eszközöket hatékony gyorsítótár-házirend használatával"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Használjon hatékony gyorsítótár-házirendet a statikus eszközöknél"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Az optimalizált képek gyorsabban betöltődnek és kevesebb adatforgalmat generálnak. [További információ](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Kódolja hatékonyan a képeket"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Használjon olyan képeket, amelyek megfelelő méretükkel elősegítik a mobiladat-forgalom csökkentését és a betöltési idő javulását. [További információ](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Méretezze megfelelően a képeket"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "A szövegalapú forrásokat tömörítéssel (gzip, Deflate vagy Brotli) célszerű továbbítani a hálózati adatforgalom minimalizálása érdekében. [További információ](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Engedélyezze a szövegtömörítést"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Az olyan képformátumok, mint a JPEG 2000, a JPEG XR és a WebP gyakran jobb tömörítést nyújtanak, mint a PNG és a JPEG, azaz kevesebb adatforgalom mellett gyorsabb letöltést biztosítanak. [További információ](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Jelenítse meg a képeket következő generációs formátumokban"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ha az alkalmazás tartalmának szélessége nem egyezik a megjelenítési terület szélességével, akkor lehet, hogy alkalmazása nincs optimalizálva a mobilok képernyőjére. [További információ](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "A megjelenítési terület mérete ({innerWidth} képpont) nem egyezik az ablak méretével ({outerWidth} képpont)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "A tartalom nincs megfelelően méretezve a megjelenítési területhez"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "A tartalom megfelelően van méretezve a megjelenítési területhez"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Az alábbi kritikus kérésláncok megjelenítik, hogy milyen források töltődnek be magas prioritással. Az oldalbetöltés javítása érdekében fontolja meg a láncok hosszának csökkentését, a letöltött források méretének csökkentését, vagy a felesleges források letöltésének késleltetését. [További információ](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 lánc található}other{# lánc található}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimalizálja a kritikus lekérdezések mélységét"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Elavulás / Figyelmeztetés"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Sor"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Az elavult API-k előbb-utóbb kikerülnek a böngészőből. [További információ](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 figyelmeztetés}other{# figyelmeztetés}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Elavult API-kat használ"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Kerüli az elavult API-kat"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Az alkalmazás-gyorsítótár elavult. [További információ](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "A(z) „{AppCacheManifest}” van használatban"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Alkalmazás-gyorsítótárat használ"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Kerüli az alkalmazás-gyorsítótárat"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "A doctype meghatározásával elkerülhető, hogy a böngésző visszafelé kompatibilis módra váltson. [További információ](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "A doctype nevének a kisbetűs `html` szövegnek kell lennie"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "A dokumentumnak doctype szakaszt kell tartalmaznia"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "A publicId nem üres karakterlánc"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "A systemId mező nem üres karakterlánc"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Az oldalon nincs HTML doctype, ezért visszafelé kompatibilis módot indít"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Az oldalon szerepel a HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elem"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Jellemző"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Érték"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "A böngészők fejlesztői azt javasolják, hogy az oldalak legfeljebb kb. 1500 DOM-elemet tartalmazzanak. Ideális esetben 32-nél kisebb mélységű fa és 60-nál kevesebb gyermek/szülő elem van. A nagy méretű DOM megnöveli a memóriahasználatot, hosszabb ideig tartó [stílusszámítást](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) igényel, valamint költséges [elrendezés-áttördeléssel](https://developers.google.com/speed/articles/reflow) jár. [További információ](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elem}other{# elem}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Kerülje a túl nagy DOM-méretet"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximális DOM-mélység"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM-elemek száma"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Alárendelt elemek maximális száma"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Kerüli a túlzó DOM-méretet"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cél"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Adjon `rel=\"noopener\"` vagy `rel=\"noreferrer\"` címkét a külső linkekhez, hogy javíthassa a teljesítményt és elkerülhesse a sebezhetőségeket. [További információ](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Az eredetközi célokra mutató linkek nem biztonságosak"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Az eredetközi célokra mutató linkek biztonságosak"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "A horgony célpontja nem meghatározható ({anchorHTML}). Ha nem hiperlinkről van szó, érdemes eltávolítania a target=_blank részt."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "A tartózkodási helyre vonatkozó engedély váratlan kérése bizalmatlanságra adhat okot, valamint összezavarhatja a felhasználókat. Érdemes inkább felhasználói műveletekhez kötni a kérést. [További információ](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Oldalbetöltéskor a földrajzi helyre vonatkozó engedélyt kéri"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Kerüli a földrajzi helyre vonatkozó engedély kérését oldalbetöltéskor"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Verzió"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Az oldalon észlelt minden front-end JavaScript-függvénytár. [További információ](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Észlelt JavaScript-függvénytárak"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "A külső szkriptek `document.write()` segítségével történő dinamikus beillesztése több tíz másodperccel lassíthatja az oldalbetöltést a lassú kapcsolaton csatlakozó felhasználók esetében. [További információ](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "A(z) `document.write()` metódust használja"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Kerüli a(z) `document.write()` használatát"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Legmagasabb súlyosság"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Függvénytár verziója"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Sebezhetőségek száma"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "A harmadik felektől származó szkriptek ismert sebezhetőségeket tartalmazhatnak, melyeket a támadók könnyedén felismerhetnek és kihasználhatnak. [További információ](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 észlelt sebezhetőség}other{# észlelt sebezhetőség}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Ismert sebezhetőségeket tartalmazó front-end JavaScript-függvénytárakat használ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Magas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Alacsony"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Közepes"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Kerüli az ismert sebezhetőségeket tartalmazó front-end JavaScript-függvénytárakat"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Az értesítésekre vonatkozó engedély váratlan kérése bizalmatlanságra adhat okot, valamint összezavarhatja a felhasználókat. Érdemes inkább felhasználói műveletekhez kötni a kérést. [További információ](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Oldalbetöltéskor az értesítésekre vonatkozó engedélyt kéri"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Kerüli az értesítésekre vonatkozó engedély kérését oldalbetöltéskor"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Hibás elemek"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "A jelszóbeillesztés megakadályozása rossz biztonsági gyakorlat. [További információ](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Megakadályozza, hogy a felhasználók szöveget illesszenek be a jelszómezőkbe"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Lehetővé teszi, hogy a felhasználók beillesszenek a jelszómezőkbe"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokoll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "A HTTP/2 számos előnyt nyújt a HTTP/1.1-hez képest, például bináris fejléceket, multiplexelést és előzetes adatküldést (server push). [További információ](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 nem HTTP/2-t használó kérés}other{# nem HTTP/2-t használó kérés}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nem minden forráshoz használ HTTP/2-t"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "HTTP/2-t használ a saját forrásokhoz"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Fontolja meg az érintési és görgetési eseményfigyelők megjelölését mint `passive`, hogy javuljon az oldal görgetést érintő teljesítménye. [További információ](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nem használ passzív figyelőket a görgetés teljesítményének javításához"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Passzív figyelőket alkalmaz a görgetés teljesítményének javításához"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Leírás"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "A konzolon megjelenő hibák megoldatlan problémákat jeleznek. Okaik lehetnek sikertelen hálózati kérések, valamint más böngészős tényezők is. [További információ](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "A böngészőhibák a konzolon láthatók"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nem került böngészőhiba a konzolra"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Használja a CSS font-display leíróját, hogy a szövegek a webes betűtípusok betöltése közben is biztosan láthatók legyenek a felhasználók számára. [További információ](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Biztosítsa, hogy a szöveg látható marad a webes betűtípusok betöltése során"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Az összes szöveg látható marad a webes betűtípusok betöltésekor"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "A Lighthouse nem tudta automatikusan ellenőrizni a következő URL font-display értékét: {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Képarány (tényleges)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Képarány (megjelenített)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "A képmegjelenítési méretek ideális esetben természetes képarányt alkalmaznak. [További információ](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Hibás képaránnyal jeleníti meg a képeket"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Helyes képaránnyal jeleníti meg a képeket"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Érvénytelen képméretezési információ {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "A böngészők proaktív módon kérhetik a felhasználókat, hogy adják hozzá az Ön alkalmazását a kezdőképernyőjükhöz, ami erősebb elköteleződéshez vezethet. [További információ](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Az internetes alkalmazás manifestje nem felel meg a telepíthetőségi követelményeknek"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Az internetes alkalmazás manifestje megfelel a telepíthetőségi követelményeknek"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nem biztonságos URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Minden webhelyet HTTPS-sel kell védeni, még akkor is, ha nem kezelnek bizalmas adatokat A HTTPS megakadályozza, hogy behatolók módosítsák vagy megfigyeljék az alkalmazás és a felhasználók közötti kommunikációt. Ezt a protokollt megköveteli a HTTP/2, valamint számos új webes API is. [További információ](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 nem biztonságos kérés}other{# nem biztonságos kérés}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nem használ HTTPS-t"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPS-t használ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "A mobilhálózatokon is gyors oldalbetöltés jobb mobilos felhasználói élményt jelent. [További információ](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "{timeInMs, number, seconds} mp az interaktívvá válásig"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktívvá válás szimulált mobilhálózaton: {timeInMs, number, seconds} mp"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Az oldal túl lassan töltődik be, és nem válik interaktívvá tíz másodpercen belül. A probléma elhárításához tekintse meg a „Teljesítmény” szakaszban lévő lehetőségeket és diagnosztikákat."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Az oldalbetöltés nem elég gyors mobilhálózatokon"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Az oldalbetöltés kellően gyors mobilhálózatokon"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategória"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Érdemes csökkenteni a JavaScript értelmezésére, összeállítására és végrehajtására fordított időt. Ebben segíthet, ha kisebb méretű JavaScript-forrásokat továbbít. [További információ](https://web.dev/mainthread-work-breakdown)."
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimalizálja a fő szál terhelését"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimalizálja a fő szál terhelését"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "A lehető legtöbb felhasználó elérése érdekében a webhelyeknek minden elterjedtebb böngészőben működniük kell. [További információ](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "A webhely többféle böngészőben is működik"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Lássa el az egyes oldalakat mélylinkként használható URL-ekkel, és ügyeljen arra, hogy ezek az URL-ek egyediek legyenek a közösségi médiában való megosztás céljából. [További információ](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Minden oldal rendelkezik URL-címmel"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "A koppintgatás során az átmeneteknek még lassú hálózaton is gyorsnak kell lenniük. Ez az egyik legfontosabb tényező a felhasználók által észlelt teljesítmény tekintetében. [További információ](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Az oldalak közti váltásnak nem szabadna akadályozni a hálózati forgalmat"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "A becsült bemeneti késés annak a becsült értéke, hogy az alkalmazás mennyi idő alatt reagál – ezredmásodpercben (ms) megadva – a felhasználói interakciókra az oldalbetöltés legforgalmasabb 5 másodperces időkeretében. Ha a várakozási idő meghaladja az 50 ms-ot, a felhasználók lassúnak érezhetik az alkalmazást. [További információ](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Becsült bemeneti késés"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Az első vizuális tartalomválasz azt az időpontot jelöli, amikor a rendszer megkezdi az első szöveg vagy kép megjelenítését. [További információ](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Első, tartalommal rendelkező leképezés"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Az első processzor-üresjárat mutató az első olyan alkalmat jelöli, amikor az oldal főszálának aktivitása elég alacsonnyá vált ahhoz, hogy kezelni tudja a felhasználói interakciókat. [További információ](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Első processzor-üresjárat"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Az első releváns vizuális válasz azt méri, hogy mikor válik láthatóvá az oldal elsődleges tartalma. [További információ](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Első releváns leképezés"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Az interaktivitásig eltelt idő az az idő, amely ahhoz szükséges, hogy az oldal teljesen interaktívvá váljon. [További információ](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Interaktivitásig eltelt idő"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Az első interakciótól számított maximális potenciális válaszkésés a leghosszabb feladat időtartama ezredmásodpercben. [További információ](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Első interakciótól számított max. potenciális késés"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "A Sebességindex mutató azt jelzi, hogy az adott oldal tartalmai milyen gyorsan válnak láthatóvá. [További információ](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Sebességindex"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Az első vizuális tartalomválasz és az interaktivitásig eltelt idő közötti minden (50 ms-nál hosszabb feladatot jelentő) periódus időtartamának összege milliszekundumban kifejezve."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Blokkolás összideje"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "A hálózati oda-vissza út ideje (round trip time, RTT) nagy hatással van a teljesítményre. Ha túl magas az RTT értéke valamelyik eredet esetében, az azt jelenti, hogy a felhasználóhoz közelebbi szerverek javíthatják a teljesítményt. [További információ](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Oda-visszautak ideje a hálózaton"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "A szerverek várakozási ideje hatással lehet a webes teljesítményre. Túlterhelést vagy nem megfelelő back-end teljesítmény jelez, ha az eredetszerver várakozási ideje túl magas. [További információ](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Várakozási idő a háttérszervereknél"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "A szolgáltató munkatársnak köszönhetően internetes alkalmazása előre nem látható hálózati körülmények mellett is megbízhatóan fog működni. [További információ](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "A(z) `start_url` nem 200-as állapotkódot küld vissza, amikor offline állapotban van"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "A(z) `start_url` 200-as állapotkódot küld vissza, amikor offline állapotban van"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "A Lighthouse nem tudta olvasni a manifest `start_url` elemét. Ennek következtében azt feltételezi, hogy a(z) `start_url` a dokumentum URL-címe. Hibaüzenet: „{manifestWarning}”."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Büdzsén kívül"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "A hálózati kérések száma és mérete maradjon a megadott teljesítménybüdzsé célpontjai alatt. [További információ](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 kérés}other{# kérés}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Teljesítménybüdzsé"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ha már beállította a HTTPS protokollt, gondoskodjon a teljes HTTP-forgalom HTTPS-re történő átirányításáról, hogy a biztonságos webes funkciók az összes felhasználó számára rendelkezésre álljanak. [További információ](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nem irányítja át a HTTP-forgalmat HTTPS-re"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Átirányítja a HTTP-forgalmat HTTPS-re"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Az átirányítások további késlekedéssel hosszabbítják meg az oldalbetöltéshez szükséges időt. [További információ](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Kerülje a többszörös oldalátirányítást"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Az oldal forrásainak mennyiségére és méretére vonatkozó büdzséket budget.json fájl hozzáadásával határozhatja meg. [További információ](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 kérelem • {byteCount, number, bytes} KB}other{# kérelem • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "A kérések száma legyen kevés, az átvitelek pedig kis méretűek"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "A gyűjtőlinkek a keresési eredményként megjelenítendő URL-re tesznek javaslatot. [További információ](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Több ütköző URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Más domainre mutat ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Érvénytelen URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Másik `hreflang` helyre mutat ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relatív URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "A domain gyökér-URL-jére (a kezdőlapra) mutat egyenértékű tartalommal rendelkező oldal helyett"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "A dokumentumhoz nem tartozik érvényes `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "A dokumentum érvényes `rel=canonical` attribútumot tartalmaz"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "A 12 képpontnál kisebb betűméretek nehezen láthatók, ezért a mobilhasználóknak a szöveget elolvasásához fel kell nagyítaniuk a képernyő tartalmát. Törekedjen arra, hogy az oldal szövegének legalább 60%-a minimum 12 képpontos betűmérettel jelenjen meg. [További információ](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent}-nyi olvasható szöveg"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "A szöveg olvashatatlan, ugyanis a látható terület metacímkéje nincs optimalizálva a mobilképernyőkre"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "A szöveg {decimalProportion, number, extendedPercent}-a túl kicsi (az összes szöveg {decimalProportionVisited, number, extendedPercent}-a alapján)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "A dokumentum olvashatatlan betűméreteket használ"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "A dokumentum olvasható betűméreteket tartalmaz"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "A hreflang linkek azt mondják meg a keresőmotoroknak, hogy nyelvtől vagy régiótól függően az oldal melyik változatát kell megjeleníteniük a keresési találatokban. [További információ](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "A dokumentum nem rendelkezik érvényes `hreflang` attribútummal"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "A dokumentum érvényes `hreflang` attribútumot tartalmaz"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "A sikertelenséget jelző HTTP-állapotkóddal rendelkező oldalak indexelése eredménytelen lehet. [További információ](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Az oldal sikertelenséget jelző HTTP-állapotkóddal rendelkezik"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Az oldal sikerességet jelző HTTP-állapotkóddal rendelkezik"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "A keresőmotorok azokat az oldalakat nem tudják keresési eredményként megjeleníteni, amelyek feltérképezésére nincs engedélyük. [További információ](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Az oldal indexelését letiltották"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Az oldalnál nincs letiltva az indexelés"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "A leíró jellegű linkszövegek segítenek a keresőmotoroknak a tartalmak értelmezésében. [További információ](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link található}other{# link található}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "A linkek nem rendelkeznek leíró jellegű szöveggel"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "A linkek leíró jellegű szöveggel rendelkeznek"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Ellenőrizze a strukturált adatok érvényességét a [Strukturált adatok tesztelőeszköz](https://search.google.com/structured-data/testing-tool/) és a [Structured Data Linter](http://linter.structured-data.org/) segítségével. [További információ](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "A strukturált adatok érvényesek"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Az oldaltartalom tömör összefoglalásának érdekében metaleírások szerepelhetnek a keresési eredményekben. [További információ](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "A Leírás mező üres."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "A dokumentum nem rendelkezik metaleírással"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "A dokumentum rendelkezik metaleírással"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Sok eszköz korlátozza vagy nem támogatja a beépülő modulokat, a keresőmotorok pedig nem tudják indexelni a modulok által megjelenített tartalmakat. [További információ](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "A dokumentum beépülő modulokat használ"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "A dokumentum nem használ beépülő modulokat"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ha a robots.txt fájl formázása rossz, előfordulhat, hogy a feltérképező robotok nem tudják értelmezni, hogy Ön hogyan szeretné feltérképeztetni vagy indexeltetni a webhelyét. [További információ](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "A robots.txt fájlra irányuló kérés a következő HTTP-állapotkóddal tért vissza: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 hiba található}other{# hiba található}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "A Lighthouse nem tudta letölteni a robots.txt fájlt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "A robots.txt fájl nem érvényes"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "A robots.txt fájl érvényes"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Az interaktív elemeknek (például a gomboknak és a linkeknek) elég nagynak kell lenniük (48 × 48 képpont), és elég helynek kell lennie közöttük, hogy könnyen rájuk lehessen koppintani a szomszédos elemek megérintése nélkül. [További információ](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent}-nyi megfelelően méretezett koppintható elem"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "A koppintási célok túl kicsik, ugyanis a látható terület metacímkéje nincs optimalizálva a mobilképernyőkre"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "A koppintási célok mérete nem megfelelő"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Átfedésben lévő cél"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Koppintási cél"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "A koppintási célok mérete megfelelő"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "A szolgáltató munkatárs elnevezésű technológia lehető teszi az alkalmazás számára a progresszív webes alkalmazások funkcióinak használatát. Ilyen funkció például az offline működés, a kezdőképernyőhöz való hozzáadás és a leküldött (push) értesítések. [További információ](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Az oldalt szolgáltató munkatárs vezérli, azonban a(z) `start_url` nem található, ugyanis nem sikerült a manifest érvényes JSON-ként való elemzése"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Az oldalt szolgáltató munkatárs vezérli, azonban a(z) `start_url` ({startUrl}) nincs a szolgáltató munkatárs hatókörében ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Az oldalt szolgáltató munkatárs vezérli, azonban a(z) `start_url` nem található, mert nem sikerült lekérni a manifestfájlt."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ez a forrás rendelkezik legalább egy szolgáltató munkatárssal, azonban az oldal ({pageUrl}) nincs a hatókörükben."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Nem regisztrál szolgáltató munkatársat, amely vezérli az oldalt és a(z) `start_url` URL-t"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Olyan szolgáltató munkatársat regisztrál, amely vezérli az oldalt és a(z) `start_url` URL-t"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "A saját témájú betöltési képernyő jó felhasználói élményt eredményez, amikor a kezdőképernyőről indítják el az alkalmazást. [További információ](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nincs beállítva egyéni betöltési képernyő"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Be van állítva egyéni betöltési képernyő"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "A böngésző címsávjához megadható a webhelyhez illő téma. [További információ](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nem állítja be a téma színét a címsávon."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "A téma színét állítja be a címsávon."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Fő szál akadályozásának időtartama"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Harmadik fél"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "A harmadik felektől származó kódok jelentős hatással lehetnek a betöltés teljesítményére. Minél kevesebb harmadik féltől származó kódot használjon, és lehetőleg azután töltse be őket, hogy az oldal nagyrészt már betöltődött. [További információ](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Harmadik féltől származó kód {timeInMs, number, milliseconds} ms-ig akadályozta a fő szál végrehajtását"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Csökkentse a harmadik felek kódjai által kiváltott hatást"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Harmadik féltől származó kód használata"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Az első bájtig eltelt idő azt mutatja, hogy a szerver mikor küldött választ. [További információ](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "{timeInMs, number, milliseconds} ms a gyökérdokumentumhoz"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Csökkentse a szerver válaszidejét (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Alacsony a szerver válaszideje (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Időtartam"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Kezdés ideje"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Típus"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Érdemes lehet felhasználnia alkalmazásában a User Timing API-t, amellyel valós használat során mért teljesítményadatokat kaphat a legfontosabb felhasználói műveletekről. [További információ](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 felhasználói időmérés}other{# felhasználói időmérés}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Felhasználói időzítőjelek és intézkedések"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Előcsatlakozási <link> található a(z) {securityOrigin} címre vonatkozóan, de a böngésző nem használta. Ellenőrizze, hogy megfelelően használja-e a(z) `crossorigin` attribútumot."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Vegye fontolóra `preconnect` vagy `dns-prefetch` erőforrástipp hozzáadását, hogy korai kapcsolatokat hozhasson létre harmadik felekhez tartozó fontos forrásokkal. [További információ](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Csatlakozzon előre a szükséges forrásokhoz"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Előtöltési <link> található a(z) {preloadURL} címre vonatkozóan, de a böngésző nem használta. Ellenőrizze, hogy megfelelően használja-e a(z) `crossorigin` attribútumot."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Fontolja meg a(z) `<link rel=preload>` használatát, hogy prioritással tölthesse be azokat a forrásokat, melyeket az aktuális oldalbetöltés egyébként későbbre sorolt. [További információ](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Töltse be előre a kulcsfontosságú kéréseket"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Adjon hozzá `<meta name=\"viewport\">` címkét, amellyel mobilképernyőkre optimalizálhatja az alkalmazást. [További információ](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nem található `<meta name=\"viewport\">` címke"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nincs `width` vagy `initial-scale` beállítással rendelkező `<meta name=\"viewport\">` címkéje"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Van `width` vagy `initial-scale` beállítással rendelkező `<meta name=\"viewport\">` címkéje"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Az alkalmazásnak akkor is meg kellene jelenítenie valamilyen tartalmat, ha a JavaScript le van tiltva. Ez akár egy figyelmeztetés is lehet, mely szerint JavaScript szükséges az alkalmazás használatához. [További információ](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Az oldal törzsében meg kellene jelennie valamilyen tartalomnak, ha a szkriptek nem használhatók."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Nem biztosít tartalék tartalmat, ha a JavaScript nem használható"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Vannak benne tartalmak akkor is, amikor a JavaScript nem használható"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ha progresszív webes alkalmazást készít, fontolja meg szolgáltató munkatárs használatát, így alkalmazása offline állapotban is működni fog. [További információ](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "A jelenlegi oldal nem 200-as állapotkódot küld vissza, amikor offline állapotban van"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "A jelenlegi oldal 200-as állapotkódot küld vissza, amikor offline állapotban van"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Előfordulhat, hogy az oldal offline állapotban nem töltődik be, mert a teszt-URL-t ({requested}) a rendszer a következő címre irányította át: „{final}”. Próbálkozzon a második URL közvetlen ellenőrzésével."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Ezek a lehetőségek segíthetnek az ARIA alkalmazásban való használatának javításában, ami jobb felhasználói élményt biztosíthat a kisegítő technológiákat (például képernyőolvasót) használó személyeknek."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Több lehetőség van, melyek révén alternatív tartalmakat biztosíthat videókhoz és hanganyagokhoz. Ezzel javíthatja a hallás- és látássérült felhasználók élményét."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Hang- és videohívások"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Itt a kisegítő lehetőségekkel kapcsolatos bevált módszereket találja."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Bevált módszerek"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ezek az ellenőrzések olyan lehetőségeket emelnek ki, melyekkel javíthatók a [webalkalmazás kisegítő lehetőségei](https://developers.google.com/web/fundamentals/accessibility). A kisegítő lehetőségekkel kapcsolatos problémáknak csak egy része észlelhető automatikusan, ezért a manuális ellenőrzés is ajánlott."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Az alábbiak automatikus tesztelőeszközzel nem ellenőrizhető területekre vonatkoznak. További információt a [kisegítő lehetőségek felülvizsgálatáról](https://developers.google.com/web/fundamentals/accessibility/how-to-review) szóló útmutatónkban talál."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Kisegítő lehetőségek"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Ezek a lehetőségek a tartalom olvashatóságát segítik."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontraszt"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Ezek a lehetőségek a tartalom különböző országokban élő felhasználók általi értelmezését segítik."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Nemzetközi megoldások és honosítás"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Ezek a lehetőségek az alkalmazás szemantikai jellemzőinek fejlesztését segítik. Javíthatják a kisegítő technológiákat (például képernyőolvasót) használó személyek felhasználói élményét."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nevek és címkék"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Több lehetőség is van a billentyűzettel való navigáció fejlesztésére az alkalmazásban."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigáció"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Ezek a lehetőségek a táblázatos és listaformátumú adatok olvasási élményét javítják olyan kisegítő technológiák használata esetén, mint a képernyőolvasó."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Táblázatok és listák"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Bevált módszerek"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "A teljesítménybüdzsék elvárásokat határoznak meg a webhely teljesítményére vonatkozóan."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Büdzsék"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "További információ alkalmazása teljesítményéről. Ezek a számok [nem befolyásolják közvetlenül](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) a teljesítménypontszámot."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnosztika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "A teljesítmény legfontosabb szempontja az, hogy milyen gyorsan jelennek meg a képpontok a képernyőn. Legfontosabb mutatók: Első, tartalommal rendelkező leképezés, Első releváns leképezés"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Az első leképezést érintő fejlesztések"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ezek a javaslatok segíthetnek az oldalbetöltés felgyorsításában. Mindazonáltal a teljesítménypontszámra [nincs közvetlen hatásuk](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Lehetőségek"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Mutatók"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Növelje az átfogó betöltési élményt annak érdekében, hogy az oldal reszponzív legyen, és a lehető legrövidebb időn belül használhatóvá váljon. Főbb mutatók: interaktivitásig eltelt idő, sebességindex"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Átfogó javítások"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Teljesítmény"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Ezek az ellenőrzések különböző szempontokból érvényesítik a progresszív webes alkalmazásokat. [További információ](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ezek az ellenőrzések kötelezők a [progresszív webes alkalmazások alapvető ellenőrzőlistáján](https://developers.google.com/web/progressive-web-apps/checklist), de a Lighthouse nem végzi el őket automatikusan. Az ellenőrzések a kapott pontszámot nem befolyásolják, de fontos a manuális végrehajtásuk."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresszív webes alkalmazás"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Gyors és megbízható"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Telepíthető"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA-optimalizálás"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Ezekkel az ellenőrzésekkel győződhet meg arról, hogy oldala megfelelően optimalizált-e a keresőmotorok találati rangsorolásához. Vannak olyan egyéb, a Lighthouse által nem ellenőrzött tényezők is, amelyek befolyásolhatják a keresésekben elért helyezést. [További információ](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Ha ezeket a további érvényesítőket is futtatja webhelyén, egyéb bevált SEO-módszereket is ellenőrizhet."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Keresőoptimalizálás"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formázza úgy a HTML-kódot, hogy a feltérképező robotok jobban megérthessék az alkalmazás tartalmait."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Tartalommal kapcsolatos bevált módszerek"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "A feltérképező robotoknak hozzáférésre van szükségük az alkalmazáshoz annak érdekében, hogy a webhely megjelenhessen a keresési találatok között."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Feltérképezés és indexelés"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Ha mobilbarát oldalakat készít, a tartalmak felnagyítás nélkül is olvashatók lesznek. [További információ](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobilbarát"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Gyorsítótár-TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Hely"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Név"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Kérések"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Forrás típusa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Méret"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Eltöltött idő"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Átviteli méret"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potenciális megtakarítás"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potenciális megtakarítás"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potenciálisan {wastedBytes, number, bytes} KB megtakarítás"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potenciálisan {wastedMs, number, milliseconds} ms megtakarítás"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokumentum"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Betűtípus"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Kép"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Média"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Egyéb"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Szkript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} mp"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stíluslap"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Harmadik féltől származó"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Összes"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Hiba történt az oldalbetöltés nyomának rögzítése során. Futtassa újra a Lighthouse szolgáltatást. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Időtúllépés a hibaelhárító protokoll kezdeti kapcsolatára való várakozás során."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "A Chrome nem gyűjtött képernyőképeket az oldal betöltése során. Ellenőrizze, hogy van-e látható tartalom az oldalon, majd próbálja újra futtatni a Lighthouse szolgáltatást. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "A DNS-szerverek nem tudták értelmezni a megadott domaint."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "A szükséges {artifactName} begyűjtő hibába ütközött: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Belső Chrome-hiba történt. Indítsa újra a Chrome-ot, és próbálja újra futtatni a Lighthouse szolgáltatást."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "A kötelező {artifactName} nem futott le."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "A Lighthouse nem tudta megfelelően betölteni a kért oldalt. Győződjön meg arról, hogy a helyes URL-t teszteli, és a szerver megfelelően válaszol az összes kérelemre."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "A Lighthouse nem tudta megfelelően betölteni a kért URL-t, mert az oldal nem válaszol."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "A megadott URL-hez nem tartozik érvényes biztonsági tanúsítvány. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "A Chrome közbeiktatott képernyő megjelenítésével megakadályozta az oldal betöltését. Ellenőrizze, hogy a helyes URL-t teszteli-e, és hogy a szerver minden kérésre megfelelően reagál-e."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "A Lighthouse nem tudta megbízhatóan betölteni a kért oldalt. Ellenőrizze, hogy a helyes URL-t teszteli-e, és hogy a szerver minden kérésre megfelelően reagál-e. (Részletek: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "A Lighthouse nem tudta megbízhatóan betölteni a kért oldalt. Ellenőrizze, hogy a helyes URL-t teszteli-e, és hogy a szerver minden kérésre megfelelően reagál-e. (Állapotkód: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Túl sokáig tartott az oldal betöltése. Csökkentse az oldalbetöltési időt a jelentésben leírt lehetőségeket követve, majd futtassa újra a Lighthouse-t. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "A DevTools protokoll válaszára való várakozás túllépte a megengedett időt. (Módszer: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "A tartalom lekérése túllépte a megengedett időt"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Úgy tűnik, a megadott URL érvénytelen."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Ellenőrzések megjelenítése"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Kezdeti navigáció"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Kritikus elérési út maximális várakozási ideje:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Hiba!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Jelentési hiba: nincs ellenőrzési információ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboradatok"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Az aktuális oldal [Lighthouse](https://developers.google.com/web/tools/lighthouse/)-elemzése emulált mobilhálózaton. Az értékek becsültek és változhatnak."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "További manuálisan elemzendő elemek"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nem alkalmazható"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Lehetőség"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Becsült megtakarítás"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Sikeresen teljesített ellenőrzések"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Kódrészlet összecsukása"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Kódrészlet kibontása"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Harmadik féltől származó források megjelenítése"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "A Lighthouse-futtatást befolyásoló problémák fordultak elő:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Az értékek becsültek és változhatnak. A teljesítménypontszám [csak ezeken a mutatókon alapszik](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Átment az ellenőrzéseken – figyelmeztetésekkel"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Figyelmeztetések: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Fontolja meg a GIF-fájlok olyan szolgáltatóhoz való feltöltését, amely lehetővé teszi a fájlok HTML5-videóként történő beágyazását."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Telepítsen [lusta betöltést biztosító WordPress-bővítményt](https://wordpress.org/plugins/search/lazy+load/), amely lehetőséget ad a képernyőn kívül eső képek késleltetett betöltésére – vagy váltson olyan témára, amely rendelkezik ezzel a funkcióval. Fontolja meg az [AMP-bővítmény](https://wordpress.org/plugins/amp/) használatát is."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Számos WordPress-bővítmény segíthet a [kritikus elemek beágyazásában](https://wordpress.org/plugins/search/critical+css/) és a [kevésbé fontos források](https://wordpress.org/plugins/search/defer+css+javascript/) késleltetésében. Fontos, hogy az ilyen jellegű bővítmények által nyújtott optimalizációk működésképtelenné tehetik a témák vagy más bővítmények funkcióit, ezért valószínűleg módosítania kell majd a meglévő kódot."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "A témák, a bővítmények és a szerver specifikációi mind befolyásolják a szerver válaszidejét. Érdemes lehet jobban optimalizált témát keresnie, megfelelő optimalizáló bővítményt választania és/vagy nagyobb teljesítményű szerverre váltania."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Fontolja meg kivonatok megjelenítését a bejegyzéslistákban (pl. a more címkével), az oldalanként megjelenített bejegyzések számának csökkentését, a hosszabb bejegyzések több oldalra tördelését, valamint a hozzászólások lusta betöltését bővítmény segítségével."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Számos [WordPress-bővítmény](https://wordpress.org/plugins/search/minify+css/) gyorsíthat webhelyén a stíluslapok egyesítésével, minimalizálásával és tömörítésével. Ha lehetséges, a minimalizálást érdemes buildfolyamat használatával előre elvégezni."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Számos [WordPress-bővítmény](https://wordpress.org/plugins/search/minify+javascript/) gyorsíthat webhelyén a szkriptek egyesítésével, minimalizálásával és tömörítésével. Ha lehetséges, a minimalizálást érdemes buildfolyamat használatával előre elvégezni."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Fontolja meg a nem használt CSS-t betöltő [WordPress-bővítmények](https://wordpress.org/plugins/) lecserélését, vagy számuk csökkentését. A felesleges CSS-t elhelyező bővítmények azonosításában a Chrome DevTools [kódlefedettség](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) eszköze is segíthet. A felelős téma vagy bővítmény a stíluslap URL-je alapján azonosítható. Keressen olyan bővítményeket, amelyeknek több stíluslapjában is sok piros szín szerepel a kódlefedettségi listán. Ideális esetben a bővítmények csak az oldalon ténylegesen használt stíluslapokat állítják sorba."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Fontolja meg a nem használt JavaScriptet betöltő [WordPress-bővítmények](https://wordpress.org/plugins/) lecserélését vagy számuk csökkentését. A felesleges JavaScriptet elhelyező bővítmények azonosításában a Chrome DevTools [kódlefedettség](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) eszköze is segíthet. A felelős téma vagy bővítmény a szkript URL-je alapján azonosítható. Keressen olyan bővítményeket, amelyeknek több szkriptjében is sok piros szín szerepel a kódlefedettségi listán. Ideális esetben a bővítmények csak az oldalon ténylegesen használt szkripteket állítják sorba."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "További információ a [WordPress böngészős gyorsítótárazásáról](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Fontolja meg olyan [képoptimalizáló WordPress-bővítmény](https://wordpress.org/plugins/search/optimize+images/) használatát, mellyel minőségromlás nélkül tömöríthetők a képek."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "A képeket közvetlenül a [Media Library](https://codex.wordpress.org/Media_Library_Screen) felületén töltse fel, hogy biztosan minden szükséges képméret rendelkezésre álljon, ezután pedig innen szúrja be őket, vagy használja az Image Widgetet, hogy biztosan az optimális képméreteket alkalmazza (a reszponzív töréspontok esetében is) `Full Size` képeket csak akkor használjon, ha méretük megfelel a felhasználás módjának. [További információ](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "A szövegtömörítést a webszerver konfigurációjában engedélyezheti."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Érdemes olyan [bővítményt](https://wordpress.org/plugins/search/convert+webp/) vagy szolgáltatást használnia, amely automatikusan az optimális formátumba konvertálja a feltöltött képeket."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/id.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/id.json
new file mode 100644
index 00000000000..00007c3230e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/id.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Kunci akses memungkinkan pengguna memfokuskan bagian halaman dengan cepat. Untuk navigasi yang tepat, setiap kunci akses harus unik. [Pelajari lebih lanjut](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Nilai `[accesskey]` tidak unik."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Nilai `[accesskey]` bersifat unik"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Setiap ARIA `role` mendukung subset tertentu dari atribut `aria-*`. Membatalkan pencocokan ini akan membuat atribut `aria-*` menjadi tidak valid. [Pelajari lebih lanjut](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atribut `[aria-*]` tidak cocok dengan perannya"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atribut `[aria-*]` cocok dengan perannya"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Beberapa peran ARIA memiliki atribut wajib yang menjelaskan status elemen ke pembaca layar. [Pelajari lebih lanjut](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` tidak memiliki semua atribut `[aria-*]` yang diperlukan"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` memiliki semua atribut `[aria-*]` yang diperlukan"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Beberapa peran induk ARIA harus memuat peran turunan tertentu agar dapat menjalankan fungsi aksesibilitas yang diinginkan. [Pelajari lebih lanjut](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elemen dengan`[role]` ARIA yang mewajibkan turunannya berisi `[role]` tertentu kehilangan beberapa atau semua turunan yang diperlukan."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elemen dengan `[role]` ARIA yang mewajibkan turunannya berisi `[role]` tertentu memiliki semua turunan yang diperlukan."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Beberapa peran turunan ARIA harus dimuat oleh peran induk tertentu agar dapat menjalankan fungsi aksesibilitas yang diinginkan dengan tepat. [Pelajari lebih lanjut](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` tidak dimuat oleh elemen induk wajibnya"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` dimuat oleh elemen induk wajibnya"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Peran ARIA harus memiliki nilai yang valid agar dapat menjalankan fungsi aksesibilitas yang diinginkan. [Pelajari lebih lanjut](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Nilai `[role]` tidak valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Nilai `[role]` valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Teknologi asistif, seperti pembaca layar, tidak dapat menafsirkan atribut ARIA dengan nilai yang tidak valid. [Pelajari lebih lanjut](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atribut `[aria-*]` tidak memiliki nilai yang valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atribut `[aria-*]` memiliki nilai yang valid"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Teknologi asistif, seperti pembaca layar, tidak dapat menafsirkan atribut ARIA dengan nama yang tidak valid. [Pelajari lebih lanjut](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atribut `[aria-*]` tidak valid atau salah eja"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atribut `[aria-*]` valid dan tidak salah eja"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Teks membuat elemen audio mudah digunakan oleh pengguna yang menyandang gangguan pendengaran atau tunarungu, sehingga memberikan informasi penting seperti siapa yang berbicara, apa yang diucapkan, dan informasi non-lisan lainnya. [Pelajari lebih lanjut](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elemen `<audio>` tidak memiliki elemen `<track>` dengan `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elemen `<audio>` memuat elemen `<track>` dengan `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elemen yang Gagal"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Jika tombol tidak memiliki nama yang dapat diakses, pembaca layar akan mengucapkannya sebagai \"tombol\", sehingga tidak dapat digunakan oleh pengguna yang mengandalkan pembaca layar. [Pelajari lebih lanjut](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Tombol tidak memiliki nama yang dapat diakses"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Tombol memiliki nama yang dapat diakses"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Dengan menambahkan cara untuk mengabaikan konten berulang, pengguna keyboard dapat membuka halaman dengan lebih efisien. [Pelajari lebih lanjut](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Halaman ini tidak memuat judul, link lewati, atau wilayah landmark"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Halaman ini memuat judul, link lewati, atau wilayah landmark"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Teks yang memiliki kontras rendah sulit atau tidak mungkin dibaca oleh kebanyakan pengguna. [Pelajari lebih lanjut](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Warna latar belakang dan latar depan tidak memiliki rasio kontras yang cukup."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Warna latar belakang dan latar depan memiliki rasio kontras yang cukup"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Jika daftar definisi tidak di-markup dengan tepat, pembaca layar dapat menghasilkan output yang membingungkan atau tidak akurat. [Pelajari lebih lanjut](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` tidak memuat grup `<dt>` dan `<dd>`, `<script>`, atau elemen `<template>` yang diurutkan dengan tepat."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` hanya memuat grup `<dt>` dan `<dd>`, `<script>`, atau elemen `<template>` yang diurutkan dengan tepat."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Item daftar definisi (`<dt>` dan `<dd>`) harus tergabung dalam elemen `<dl>` induk untuk memastikan bahwa pembaca layar dapat mengucapkannya dengan tepat. [Pelajari lebih lanjut](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Item daftar definisi tidak tergabung dalam elemen `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Item daftar definisi tergabung dalam elemen `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Judul ini memberi pengguna pembaca layar ringkasan halaman, dan pengguna mesin telusur sangat mengandalkannya untuk menentukan apakah halaman relevan dengan penelusurannya atau tidak. [Pelajari lebih lanjut](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumen tidak memiliki elemen `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumen memiliki elemen `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Nilai atribut ID harus unik untuk mencegah instance lain terabaikan oleh teknologi asistif. [Pelajari lebih lanjut](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atribut `[id]` di halaman ini tidak unik"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atribut `[id]` di halaman ini unik"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Pengguna pembaca layar mengandalkan judul bingkai untuk menjelaskan isi bingkai. [Pelajari lebih lanjut](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elemen `<frame>` atau `<iframe>` tidak memiliki judul"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elemen `<frame>` atau `<iframe>` memiliki judul"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Jika halaman tidak menentukan atribut bahasa, pembaca layar akan mengasumsikan bahwa halaman menggunakan bahasa default yang dipilih pengguna saat menyiapkan pembaca layar. Jika halaman tidak dalam bahasa default, pembaca layar mungkin tidak dapat mengucapkan teks di halaman tersebut dengan benar. [Pelajari lebih lanjut](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Elemen `<html>` tidak memiliki atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Elemen `<html>` memiliki atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Menentukan [bahasa BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) yang valid akan membantu pembaca layar mengucapkan teks dengan tepat. [Pelajari lebih lanjut](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Elemen `<html>` tidak memiliki nilai yang valid untuk atribut `[lang]`-nya."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Elemen `<html>` memiliki nilai yang valid untuk atribut `[lang]`-nya"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Elemen informatif harus memberikan teks alternatif yang singkat dan deskriptif. Elemen dekoratif dapat diabaikan dengan atribut alt kosong. [Pelajari lebih lanjut](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elemen gambar tidak memiliki atribut `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elemen halaman memiliki atribut `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Saat suatu gambar digunakan sebagai tombol `<input>`, menyediakan teks alternatif dapat membantu pengguna pembaca layar memahami fungsi tombol tersebut. [Pelajari lebih lanjut](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elemen `<input type=\"image\">` tidak memiliki teks `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elemen `<input type=\"image\">` memiliki teks `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Label memastikan bahwa kontrol bentuk diucapkan dengan tepat oleh teknologi asistif, seperti pembaca layar. [Pelajari lebih lanjut](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Elemen formulir tidak memiliki label yang terkait"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Elemen formulir memiliki label yang terkait"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabel yang digunakan untuk tujuan tata letak sebaiknya tidak mencakup elemen data, seperti elemen th atau teks atau atribut ringkasan karena hal ini dapat menyebabkan pengalaman yang membingungkan bagi pengguna pembaca layar. [Pelajari lebih lanjut](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Elemen `<table>` presentasional tidak menghindari penggunaan atribut `<th>`, `<caption>`, atau `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Elemen `<table>` yang bersifat presentasional menghindari penggunaan atribut `<th>`, `<caption>`, atau `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Teks link (dan teks alternatif untuk gambar, saat digunakan sebagai link) yang mudah dilihat, unik, dan dapat difokuskan menyempurnakan pengalaman navigasi bagi pengguna pembaca layar. [Pelajari lebih lanjut](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Link tidak memiliki nama yang dapat dikenali"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Link memiliki nama yang dapat dikenali"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Pembaca layar memiliki cara tertentu untuk membacakan daftar. Memastikan struktur daftar dengan tepat akan membantu output pembaca layar. [Pelajari lebih lanjut](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Daftar tidak hanya berisi elemen `<li>` dan skrip yang mendukung elemen (`<script>` dan `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Daftar hanya memuat elemen `<li>` dan skrip yang mendukung elemen (`<script>` dan `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Pembaca layar mengharuskan item daftar (`<li>`) untuk dimuat dalam `<ul>` atau `<ol>` induk agar dapat diucapkan dengan tepat. [Pelajari lebih lanjut](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Daftar item (`<li>`) tidak dimuat dalam elemen induk `<ul>` atau `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Item daftar (`<li>`) dimuat dalam elemen induk `<ul>` atau `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Pengguna tidak mengharapkan halaman dimuat ulang secara otomatis, karena tindakan tersebut akan memindahkan fokus kembali ke bagian atas halaman. Hal ini dapat menimbulkan pengalaman yang menjengkelkan atau membingungkan. [Pelajari lebih lanjut](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumen menggunakan `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumen tidak menggunakan `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Menonaktifkan zoom akan menimbulkan masalah bagi pengguna dengan gangguan penglihatan yang mengandalkan pembesaran layar untuk melihat konten halaman dengan tepat. [Pelajari lebih lanjut](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` digunakan dalam elemen `<meta name=\"viewport\">` atau atribut `[maximum-scale]` kurang dari 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` tidak digunakan dalam elemen `<meta name=\"viewport\">` dan atribut `[maximum-scale]` tidak kurang dari 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Pembaca layar tidak dapat menerjemahkan konten yang bukan teks. Menambahkan teks alternatif ke elemen `<object>` membantu pembaca layar menyampaikan makna kepada pengguna. [Pelajari lebih lanjut](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elemen `<object>` tidak memiliki teks `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elemen `<object>` memiliki teks `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Nilai yang lebih besar dari 0 menunjukkan pengurutan navigasi eksplisit. Walaupun secara teknis valid, hal ini sering menciptakan pengalaman yang membingungkan bagi pengguna yang mengandalkan teknologi asistif. [Pelajari lebih lanjut](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Beberapa elemen memiliki nilai `[tabindex]` yang lebih besar dari 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Tidak ada elemen yang memiliki nilai `[tabindex]` lebih besar dari 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Pembaca layar memiliki fitur yang memudahkan navigasi tabel. Memastikan sel `<td>` yang menggunakan atribut `[headers]` hanya merujuk ke sel lain dalam tabel yang sama dapat menyempurnakan pengalaman bagi pengguna pembaca layar. [Pelajari lebih lanjut](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Sel di elemen `<table>` yang menggunakan atribut `[headers]` yang merujuk pada elemen `id` tidak ditemukan dalam tabel yang sama."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Sel dalam elemen `<table>` yang menggunakan atribut `[headers]` yang merujuk pada sel tabel dalam tabel yang sama."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Pembaca layar memiliki fitur yang memudahkan navigasi tabel. Memastikan header tabel selalu merujuk ke sekumpulan sel dapat menyempurnakan pengalaman bagi pengguna pembaca layar. [Pelajari lebih lanjut](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elemen `<th>` dan elemen dengan `[role=\"columnheader\"/\"rowheader\"]` tidak memiliki sel data yang dideskripsikannya."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elemen `<th>` dan elemen dengan `[role=\"columnheader\"/\"rowheader\"]` memiliki sel data yang dideskripsikan."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Menentukan [bahasa BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) yang valid pada elemen membantu memastikan bahwa teks diucapkan dengan benar oleh pembaca layar. [Pelajari lebih lanjut](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atribut `[lang]` tidak memiliki nilai yang valid"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atribut `[lang]` memiliki nilai yang valid"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Video yang menyediakan teks akan memudahkan pengguna yang menyandang gangguan pendengaran dan tunarungu untuk mengakses informasinya. [Pelajari lebih lanjut](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elemen `<video>` tidak memuat elemen `<track>` dengan `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elemen `<video>` memuat elemen `<track>` dengan `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Deskripsi audio memberikan informasi yang relevan untuk video yang tidak dapat diberikan melalui dialog, seperti ekspresi wajah dan adegan. [Pelajari lebih lanjut](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elemen `<video>` tidak memuat elemen `<track>` dengan `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elemen `<video>` memuat elemen `<track>` dengan `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Untuk tampilan ideal pada iOS saat pengguna menambahkan progressive web app ke layar utama, tentukan `apple-touch-icon`. Ikon harus mengarah ke PNG persegi 192 piksel (atau 180 piksel) yang tidak transparan. [Pelajari Lebih Lanjut](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Tidak menyediakan `apple-touch-icon` yang valid"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` sudah usang; `apple-touch-icon` dipilih."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Memberikan `apple-touch-icon` yang valid"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Ekstensi Chrome berpengaruh negatif terhadap performa pemuatan halaman ini. Coba audit halaman dalam mode samaran atau dari profil Chrome tanpa ekstensi."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Evaluasi Skrip"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Penguraian Skrip"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Waktu CPU Total"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Sebaiknya kurangi waktu yang dihabiskan untuk mengurai, mengompilasi, dan mengeksekusi JS. Coba kirim payload JS yang lebih kecil untuk membantu mengurangi waktu. [Pelajari lebih lanjut](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Mengurangi waktu eksekusi JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Waktu eksekusi JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "GIF berukuran besar tidak efisien untuk menayangkan konten animasi. Sebaiknya gunakan video MPEG4/WebM sebagai animasi dan PNG/WebP sebagai gambar statis untuk menggantikan GIF guna menghemat byte jaringan. [Pelajari lebih lanjut](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Gunakan format video untuk konten animasi"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Sebaiknya lakukan pemuatan lambat di balik layar dan gambar tersembunyi setelah semua resource kritis selesai dimuat guna mengurangi waktu untuk interaktif. [Pelajari lebih lanjut](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Tunda gambar di balik layar"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resource memblokir first paint halaman. Sebaiknya kirim inline JS/CSS kritis dan tunda semua JS/gaya yang tidak kritis. [Pelajari lebih lanjut](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Hilangkan resource yang memblokir render"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Payload jaringan yang besar menimbulkan biaya yang tinggi bagi pengguna dan berkorelasi erat dengan waktu pemuatan yang lama. [Pelajari lebih lanjut](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Total ukuran adalah {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Menghindari payload jaringan yang sangat besar"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Menghindari payload jaringan yang sangat besar"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Meminifikasi file CSS dapat mengurangi ukuran payload jaringan. [Pelajari lebih lanjut](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Kecilkan CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Meminifikasi file JavaScript dapat mengurangi ukuran payload dan waktu penguraian skrip. [Pelajari lebih lanjut](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Kecilkan ukuran JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Hapus aturan yang tidak berlaku dari stylesheet dan tunda pemuatan CSS yang tidak digunakan untuk konten paruh atas, guna mengurangi byte yang tidak perlu yang digunakan oleh aktivitas jaringan. [Pelajari lebih lanjut](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Hapus CSS yang tidak digunakan"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Menghapus JavaScript yang tidak digunakan untuk mengurangi byte yang digunakan oleh aktivitas jaringan."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Hapus JavaScript yang tidak digunakan"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Durasi cache yang panjang dapat mempercepat kunjungan berulang ke halaman Anda. [Pelajari lebih lanjut](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 resource ditemukan}other{# resource ditemukan}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Tayangkan aset statis dengan kebijakan cache yang efisien"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Menggunakan kebijakan cache yang efisien pada aset statis"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Gambar yang dioptimalkan dimuat lebih cepat dan menghabiskan lebih sedikit data seluler. [Pelajari lebih lanjut](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Enkode gambar secara efisien"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Menayangkan gambar yang berukuran sesuai untuk menghemat kuota dan meningkatkan waktu pemuatan. [Pelajari lebih lanjut](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Ubah ukuran gambar dengan tepat"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Resource berbasis teks harus ditayangkan dengan kompresi (gzip, deflate, atau brotli) untuk meminimalkan total byte jaringan. [Pelajari lebih lanjut](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Aktifkan kompresi teks"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Format gambar seperti JPEG 2000, JPEG XR, dan WebP biasanya memberikan kompresi yang lebih baik daripada PNG atau JPEG, sehingga download lebih cepat dan konsumsi data lebih kecil. [Pelajari lebih lanjut](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Tayangkan gambar dalam format generasi berikutnya"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Jika lebar konten aplikasi Anda tidak cocok dengan lebar area pandang, aplikasi mungkin tidak dioptimalkan untuk layar perangkat seluler. [Pelajari lebih lanjut](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Ukuran area pandang {innerWidth} piksel tidak cocok dengan ukuran jendela {outerWidth} piksel."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Ukuran konten untuk area pandang tidak tepat"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Ukuran konten untuk area pandang sudah tepat"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Rantai Permintaan Penting di bawah menampilkan resource apa saja yang dimuat dengan prioritas tinggi. Sebaiknya kurangi panjang rantai, kurangi ukuran download resource, atau tunda download resource yang tidak penting untuk mempercepat pemuatan halaman. [Pelajari lebih lanjut](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 rantai ditemukan}other{# rantai ditemukan}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimalkan Kedalaman Permintaan Penting"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Penghentian/Peringatan"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Baris"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "API yang tidak digunakan lagi pada akhirnya akan dihapus dari browser. [Pelajari lebih lanjut](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 peringatan ditemukan}other{# peringatan ditemukan}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Menggunakan API yang tidak digunakan lagi"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Menghindari API yang tidak digunakan lagi"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Cache Aplikasi tidak digunakan lagi. [Pelajari lebih lanjut](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Menemukan \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Menggunakan Cache Aplikasi"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Menghindari Cache Aplikasi"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Menentukan doctype akan mencegah browser beralih ke quirks mode. [Pelajari lebih lanjut](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Nama doctype harus berupa string huruf kecil `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumen harus berisi doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "PublicId diperkirakan menjadi string kosong"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "SystemId diperkirakan menjadi string kosong"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Halaman tidak memiliki doctype HTML sehingga memicu quirks mode"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Halaman memiliki doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemen"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistik"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Nilai"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Engineer browser merekomendasikan halaman yang berisi kurang dari ~ 1.500 elemen DOM. Ukuran yang pas adalah suatu kedalaman hierarki yang terdiri dari <32 elemen dan kurang dari 60 elemen turunan/induk. DOM yang besar dapat meningkatkan penggunaan memori, menyebabkan [penghitungan gaya](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) yang lebih lama, dan menghasilkan [penyesuaian tata letak](https://developers.google.com/speed/articles/reflow) yang mahal. [Pelajari lebih lanjut](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemen}other{# elemen}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Menghindari ukuran DOM yang berlebihan"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Kedalaman DOM Maksimum"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Elemen DOM Total"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Elemen Turunan Maksimum"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Menghindari ukuran DOM yang berlebihan"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Tambahkan `rel=\"noopener\"` atau `rel=\"noreferrer\"` ke link eksternal mana pun untuk menyempurnakan performa dan mencegah kerentanan keamanan. [Pelajari lebih lanjut](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Link ke tujuan lintas asal tidak aman"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Link ke tujuan lintas asal aman"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Tidak dapat menentukan tujuan untuk anchor ({anchorHTML}). Jika tidak digunakan sebagai hyperlink, sebaiknya hapus target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Pengguna tidak percaya atau bingung dengan situs yang meminta lokasi mereka tanpa konteks. Sebaiknya kaitkan permintaan dengan tindakan pengguna. [Pelajari lebih lanjut](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Meminta izin geolokasi pada pemuatan halaman"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Menghindari meminta izin geolokasi pada pemuatan halaman"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versi"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Semua library JavaScript front-end terdeteksi di halaman. [Pelajari lebih lanjut](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Library JavaScript yang terdeteksi"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Untuk pengguna dengan koneksi lambat, skrip eksternal secara dinamis dimasukkan melalui `document.write()` dapat menunda pemuatan halaman selama puluhan detik. [Pelajari lebih lanjut](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Menggunakan `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Menghindari `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Keparahan Tertinggi"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versi Library"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Jumlah Kerentanan"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Beberapa skrip pihak ketiga dapat berisi kerentanan keamanan umum yang mudah diidentifikasi dan dimanfaatkan oleh penyerang. [Pelajari lebih lanjut](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kerentanan terdeteksi}other{# kerentanan terdeteksi}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Menyertakan library JavaScript front-end yang memiliki kerentanan keamanan umum"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Tinggi"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Rendah"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Sedang"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Menghindari library JavaScript front-end yang memiliki kerentanan keamanan umum"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Pengguna tidak percaya atau bingung dengan situs yang meminta untuk mengirim pemberitahuan tanpa konteks. Sebaiknya kaitkan permintaan dengan gestur pengguna. [Pelajari lebih lanjut](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Meminta izin notifikasi pada pemuatan halaman"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Menghindari meminta izin notifikasi pada pemuatan halaman"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elemen yang Gagal"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Mencegah menempelkan sandi akan merusak kebijakan keamanan yang baik. [Pelajari lebih lanjut](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Mencegah pengguna menempelkan sesuatu ke kolom sandi."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Mengizinkan pengguna menempelkan sesuatu ke kolom sandi"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 menawarkan banyak manfaat dibandingkan HTTP/1.1, termasuk header biner, multiplexing, dan push server. [Pelajari lebih lanjut](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 permintaan tidak dilayani melalui HTTP/2}other{# permintaan tidak dilayani melalui HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Tidak menggunakan HTTP/2 untuk semua resourcenya"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Menggunakan HTTP/2 untuk resource miliknya sendiri"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Sebaiknya tandai sentuhan Anda dan pemroses peristiwa gulir sebagai `passive` untuk menyempurnakan performa scroll halaman Anda. [Pelajari lebih lanjut](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Tidak menggunakan pemroses pasif untuk menyempurnakan performa scroll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Menggunakan pemroses pasif untuk menyempurnakan performa scroll"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Deskripsi"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Error yang dicatat di konsol menunjukkan masalah yang belum terselesaikan. Error dapat berasal dari permintaan jaringan yang gagal dan masalah browser lainnya. [Pelajari lebih lanjut](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Error browser dicatat di konsol"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Tidak ada error browser yang dicatat ke konsol"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Memanfaatkan fitur CSS tampilan font untuk memastikan teks terlihat oleh pengguna saat font web sedang dimuat. [Pelajari lebih lanjut](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Pastikan teks tetap terlihat selama pemuatan font web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Semua teks tetap terlihat selama pemuatan font web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse tidak dapat secara otomatis memeriksa nilai tampilan font untuk URL berikut: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Rasio Tinggi Lebar (Aktual)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Rasio Tinggi Lebar (Ditampilkan)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Dimensi tampilan gambar harus cocok dengan rasio tinggi lebar natural. [Pelajari lebih lanjut](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Menampilkan gambar dengan rasio tinggi lebar yang salah"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Menampilkan gambar dengan rasio tinggi lebar yang benar"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informasi ukuran gambar {url} tidak valid"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browser dapat secara proaktif meminta pengguna untuk menambahkan aplikasi Anda ke layar utama mereka sehingga interaksi menjadi lebih tinggi. [Pelajari lebih lanjut](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifes aplikasi web tidak memenuhi persyaratan kemampuan penginstalan"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifes aplikasi web memenuhi persyaratan kemampuan penginstalan"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL yang tidak aman"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Semua situs harus dilindungi dengan HTTPS, termasuk situs-situs yang tidak menangani data sensitif. HTTPS mencegah penyusup merusak atau mendengarkan komunikasi secara pasif antara aplikasi dan pengguna, serta merupakan prasyarat untuk HTTP/2 dan banyak API platform web baru. [Pelajari lebih lanjut](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 permintaan tidak aman ditemukan}other{# permintaan tidak aman ditemukan}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Tidak menggunakan HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Menggunakan HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Pemuatan halaman yang cepat melalui jaringan seluler menjamin pengalaman pengguna seluler yang baik. [Pelajari lebih lanjut](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktif di {timeInMs, number, seconds} dtk"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktif di jaringan seluler tersimulasi pada {timeInMs, number, seconds} dtk"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Pemuatan halaman terlalu lambat dan tidak interaktif selama 10 detik. Lihat peluang dan diagnostik dalam bagian \"Performa\" untuk mempelajari cara meningkatkan kecepatan pemuatan."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Pemuatan halaman tidak cukup cepat pada jaringan seluler"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Pemuatan halaman cukup cepat pada jaringan seluler"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategori"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Sebaiknya kurangi waktu yang dihabiskan untuk mengurai, mengompilasi, dan mengeksekusi JS. Coba kirim payload JS yang lebih kecil untuk membantu mengurangi waktu. [Pelajari lebih lanjut](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimalkan pekerjaan thread utama"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Meminimalkan pekerjaan thread utama"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Untuk menjangkau jumlah pengguna terbanyak, situs harus berjalan di seluruh browser utama. [Pelajari lebih lanjut](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Situs dapat berjalan lintas-browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Pastikan halaman individu dapat dijadikan deep link melalui URL, dan URL tersebut unik agar dapat dibagikan di media sosial. [Pelajari lebih lanjut](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Setiap halaman memiliki URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Transisi harus terasa cepat ketika Anda mengetuk-ngetuk, bahkan saat jaringan lambat. Pengalaman ini merupakan kunci persepsi pengguna terhadap performa. [Pelajari lebih lanjut](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Transisi halaman sepertinya tidak diblokir di jaringan"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Perkiraan Latensi Masukan adalah perkiraan durasi yang diperlukan aplikasi untuk merespons masukan pengguna, dalam milidetik, selama durasi 5 detik tersibuk saat pemuatan halaman. Jika latensi di atas 50 md, pengguna dapat menganggap aplikasi Anda lambat. [Pelajari lebih lanjut](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Perkiraan Latensi Masukan"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First Contentful Paint menandai waktu saat teks atau gambar pertama di-paint. [Pelajari lebih lanjut](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "CPU Pertama Tidak Ada Aktivitas menandai waktu pertama kalinya thread utama halaman menjadi agak tenang untuk menangani masukan. [Pelajari lebih lanjut](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU Pertama Tidak Ada Aktivitas"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "First Meaningful Paint mengukur waktu saat konten utama halaman terlihat. [Pelajari lebih lanjut](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Waktu untuk interaktif adalah lamanya waktu yang diperlukan halaman untuk menjadi interaktif sepenuhnya. [Pelajari lebih lanjut](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Waktu untuk Interaktif"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Potensi maksimal Penundaan Input Pertama yang dapat dialami pengguna Anda adalah durasi tugas terpanjang, yang dinyatakan dalam milidetik. [Pelajari lebih lanjut](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Potensi Maksimal Penundaan Input Pertama"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indeks Kecepatan menunjukkan seberapa cepat konten halaman terlihat terisi lengkap. [Pelajari lebih lanjut](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indeks Kecepatan"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Jumlah semua jangka waktu antara FCP dan Waktu untuk Interaktif, ketika durasi tugas melebihi 50 md, dinyatakan dalam milidetik."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total Waktu Pemblokiran"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Waktu round trip (RTT) jaringan berdampak besar pada performa. RTT ke asal yang tinggi merupakan indikasi bahwa server yang berjarak lebih dekat ke pengguna dapat meningkatkan performa. [Pelajari lebih lanjut](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Waktu Round Trip Jaringan"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Latensi server dapat memengaruhi performa web. Latensi server untuk suatu asal yang tinggi merupakan indikasi bahwa server kelebihan muatan atau memiliki performa backend yang buruk. [Pelajari lebih lanjut](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latensi Backend Server"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Pekerja layanan memungkinkan aplikasi web dapat diandalkan dalam kondisi jaringan yang tidak terduga. [Pelajari lebih lanjut](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` tidak merespons dengan kode 200 saat offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` merespons dengan kode 200 saat offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse tidak dapat membaca `start_url` dari manifes tersebut. Oleh karena itu, `start_url` dianggap sebagai URL dokumen. Pesan error: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Melebihi Anggaran"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Pertahankan jumlah dan ukuran permintaan jaringan di bawah target yang ditetapkan oleh anggaran performa yang disediakan. [Pelajari lebih lanjut](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 permintaan}other{# permintaan}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Anggaran performa"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Jika Anda sudah menyiapkan HTTPS, pastikan mengalihkan semua traffic HTTP ke HTTPS agar dapat menyediakan fitur web yang aman bagi semua pengguna. [Pelajari lebih lanjut](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Tidak mengalihkan traffic HTTP ke HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Mengalihkan traffic HTTP ke HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Pengalihan mencakup penundaan tambahan sebelum halaman dapat dimuat. [Pelajari lebih lanjut](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Hindari pengalihan lebih dari satu halaman"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Untuk mengatur anggaran jumlah dan ukuran resource halaman, tambahkan file budget.json. [Pelajari lebih lanjut](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 permintaan • {byteCount, number, bytes} KB}other{# permintaan • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Pertahankan jumlah permintaan tetap rendah dan ukuran transfer tetap kecil"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Link kanonis menyarankan URL yang akan ditampilkan dalam hasil penelusuran. [Pelajari lebih lanjut](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Ada beberapa URL yang bertentangan ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Mengarahkan ke domain yang berbeda ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL tidak valid ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Mengarahkan ke lokasi `hreflang` lain ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relatif ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Mengarah ke URL root domain (halaman beranda), bukan ke halaman yang setara untuk konten itu"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumen tidak memiliki `rel=canonical` yang valid"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumen memiliki `rel=canonical` yang valid"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Ukuran font di bawah 12 piksel terlalu kecil untuk dapat dibaca dan memaksa pengunjung seluler “mencubit untuk memperbesar\" agar dapat membacanya. Usahakan untuk menampilkan >60% teks halaman dalam ukuran ≥12 piksel. [Pelajari lebih lanjut](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "Teks yang dapat dibaca {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Teks tidak terbaca karena tidak ada tag meta viewport yang dioptimalkan untuk layar seluler."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} teks terlalu kecil (berdasarkan sampel {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumen tidak menggunakan ukuran font yang terbaca"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumen menggunakan ukuran font yang terbaca"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Link hreflang memberi tahu mesin telusur versi halaman yang harus dicantumkan dalam hasil penelusuran untuk wilayah atau bahasa tertentu. [Pelajari lebih lanjut](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumen tidak memiliki `hreflang` yang valid"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumen memiliki `hreflang` yang valid"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Halaman dengan kode status HTTP yang tidak berhasil mungkin tidak akan diindeks dengan tepat. [Pelajari lebih lanjut](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Halaman memiliki kode status HTTP yang tidak berhasil"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Halaman memiliki kode status HTTP yang berhasil"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Mesin telusur tidak dapat menyertakan halaman Anda dalam hasil penelusuran jika tidak memiliki izin untuk meng-crawl halaman tersebut. [Pelajari lebih lanjut](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Halaman diblokir dari pengindeksan"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Halaman tidak diblokir dari pengindeksan"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Teks link deskriptif membantu mesin telusur memahami konten Anda. [Pelajari lebih lanjut](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link ditemukan}other{# link ditemukan}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Link tidak memiliki teks deskriptif"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Link memiliki teks deskriptif"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Jalankan [Fitur Pengujian Data Terstruktur](https://search.google.com/structured-data/testing-tool/) dan [Linter Data Terstruktur](http://linter.structured-data.org/) untuk memvalidasi data terstruktur. [Pelajari lebih lanjut](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Data terstruktur valid"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Deskripsi meta mungkin disertakan dalam hasil penelusuran untuk merangkum isi halaman dengan singkat. [Pelajari lebih lanjut](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Teks deskripsi kosong."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumen tidak memiliki deskripsi meta"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumen memiliki deskripsi meta"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Mesin telusur tidak dapat mengindeks konten plugin, dan banyak perangkat yang membatasi plugin atau tidak mendukungnya. [Pelajari lebih lanjut](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumen menggunakan plugin"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumen menghindari plugin"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Jika file robots.txt Anda salah format, crawler mungkin tidak dapat memahami cara crawling atau pengindeksan situs yang Anda inginkan. [Pelajari lebih lanjut](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Permintaan untuk robots.txt menampilkan status HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 error ditemukan}other{# error ditemukan}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse tidak dapat mendownload file robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt tidak valid"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt valid"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Elemen interaktif seperti tombol dan link harus berukuran cukup besar (48x48 piksel), dan memiliki cukup ruang di sekelilingnya, agar cukup mudah diketuk tanpa tumpang-tindih dengan elemen lain. [Pelajari lebih lanjut](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} target ketuk memiliki ukuran yang tepat"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Target ketuk terlalu kecil karena tidak ada tag meta viewport yang dioptimalkan untuk layar seluler"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Target ketuk tidak memiliki ukuran yang tepat"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Target Tumpang-Tindih"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Target Ketuk"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Target ketuk memiliki ukuran yang tepat"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Pekerja layanan adalah teknologi yang memungkinkan aplikasi Anda menggunakan banyak fitur Progressive Web App, seperti fitur offline, tambahkan ke layar utama, dan notifikasi push. [Pelajari lebih lanjut](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Halaman ini dikontrol oleh pekerja layanan, tetapi `start_url` tidak ditemukan karena manifes gagal diurai sebagai JSON yang valid"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Halaman ini dikontrol oleh pekerja layanan, tetapi `start_url` ({startUrl}) tidak termasuk dalam cakupan pekerja layanan ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Halaman ini dikontrol oleh pekerja layanan, tetapi `start_url` tidak ditemukan karena tidak ada manifes yang diambil."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Asal memiliki satu pekerja layanan atau lebih, tetapi halaman ({pageUrl}) tidak termasuk dalam cakupan."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Tidak mendaftarkan pekerja layanan yang mengontrol halaman dan `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Mendaftarkan pekerja layanan yang mengontrol halaman dan `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Layar pembuka yang diberi tema akan memberikan pengalaman berkualitas tinggi saat pengguna meluncurkan aplikasi dari layar utama. [Pelajari lebih lanjut](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Tidak dikonfigurasi untuk layar pembuka khusus"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Dikonfigurasi untuk layar pembuka khusus"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Kolom URL browser dapat diberi tema agar cocok dengan situs Anda. [Pelajari lebih lanjut](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Tidak menyetel warna tema untuk kolom URL."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Menyetel warna tema untuk kolom URL."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Waktu Pemblokiran Thread Utama"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Pihak Ketiga"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kode pihak ketiga dapat memberikan dampak signifikan terhadap performa muatan. Batasi jumlah penyedia pihak ketiga yang berlebihan dan coba muat kode pihak ketiga terutama setelah halaman selesai memuat. [Pelajari lebih lanjut](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kode pihak ketiga memblokir thread utama untuk {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Kurangi dampak kode pihak ketiga"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Penggunaan oleh Pihak Ketiga"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Time To First Byte mengidentifikasi waktu saat server mengirim respons. [Pelajari lebih lanjut](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Dokumen root memerlukan waktu {timeInMs, number, milliseconds} md"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Mengurangi waktu respons server (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Waktu respons server sedikit (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Durasi"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Waktu Mulai"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Jenis"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Sebaiknya lengkapi aplikasi Anda dengan User Timing API untuk mengukur performa aplikasi Anda yang sebenarnya selama pengalaman pengguna utama. [Pelajari lebih lanjut](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 waktu pengguna}other{# waktu pengguna}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Tanda dan ukuran Waktu Pengguna"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Sebuah <link> prakoneksi ditemukan untuk {securityOrigin}, tetapi tidak digunakan oleh browser. Pastikan Anda menggunakan atribut `crossorigin` dengan tepat."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Sebaiknya tambahkan petunjuk resource `preconnect` atau `dns-prefetch` guna membuat sambungan lebih awal ke asal pihak ketiga yang penting. [Pelajari lebih lanjut](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Sambungkan terlebih dahulu ke nama domain yang diperlukan"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Sebuah <link> pramuat ditemukan untuk {preloadURL}, tetapi tidak digunakan oleh browser. Pastikan Anda menggunakan atribut `crossorigin` dengan tepat."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Sebaiknya gunakan `<link rel=preload>` untuk memprioritaskan pengambilan resource yang saat ini diminta selama pemuatan halaman. [Pelajari lebih lanjut](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Muat permintaan utama terlebih dahulu"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Tambahkan tag `<meta name=\"viewport\">` guna mengoptimalkan aplikasi Anda untuk layar perangkat seluler. [Pelajari lebih lanjut](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Tag `<meta name=\"viewport\">` tidak ditemukan"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Tidak memiliki tag `<meta name=\"viewport\">` dengan `width` atau `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Memiliki tag `<meta name=\"viewport\">` dengan `width` atau `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Aplikasi Anda harus menampilkan beberapa konten saat JavaScript nonaktif, meskipun hanya berupa peringatan kepada pengguna bahwa JavaScript diperlukan untuk menggunakan aplikasi. [Pelajari lebih lanjut](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Isi halaman harus merender beberapa konten jika skripnya tidak tersedia."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Tidak menyediakan konten pengganti saat JavaScript tidak tersedia"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Berisi beberapa konten saat JavaScript tidak tersedia"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Jika Anda membuat build Progressive Web App, pertimbangkan untuk menggunakan pekerja layanan agar aplikasi dapat berfungsi secara offline. [Pelajari lebih lanjut](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Halaman saat ini tidak merespons dengan kode 200 saat offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Halaman saat ini merespons dengan kode 200 saat offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Halaman tersebut mungkin tidak dimuat secara offline karena URL uji Anda ({requested}) tidak dialihkan ke \"{final}\". Coba uji URL kedua secara langsung."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Ini adalah peluang untuk meningkatkan penggunaan ARIA pada aplikasi Anda, yang dapat meningkatkan pengalaman bagi pengguna teknologi asistif, seperti pembaca layar."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Ini adalah peluang untuk memberikan konten alternatif untuk audio dan video. Hal ini dapat meningkatkan pengalaman bagi pengguna yang menyandang gangguan penglihatan atau pendengaran."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio dan video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Item berikut memperjelas praktik terbaik yang umum untuk aksesibilitas."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Praktik terbaik"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Pemeriksaan ini menandai peluang untuk [menyempurnakan aksesibilitas aplikasi web Anda](https://developers.google.com/web/fundamentals/accessibility). Hanya sejumlah kecil masalah aksesibilitas yang dapat terdeteksi secara otomatis, sehingga pengujian manual juga dianjurkan."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Item berikut ini menangani area yang tidak dapat dicakup oleh fitur pengujian otomatis. Pelajari lebih lanjut dalam panduan kami tentang [menjalankan tinjauan aksesibilitas](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Aksesibilitas"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Ini adalah peluang untuk meningkatkan keterbacaan konten Anda."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontras"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Ini adalah peluang untuk menyempurnakan interpretasi konten Anda oleh pengguna dalam lokal yang berbeda."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internasionalisasi dan pelokalan"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Ini adalah peluang untuk meningkatkan semantik kontrol dalam aplikasi Anda. Hal ini dapat menyempurnakan pengalaman bagi pengguna teknologi asistif, seperti pembaca layar."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nama dan label"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ini adalah peluang untuk menyempurnakan navigasi keyboard pada aplikasi Anda."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigasi"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Ini adalah peluang untuk meningkatkan pengalaman membaca data dalam format tabel atau daftar menggunakan teknologi asistif, seperti pembaca layar."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabel dan daftar"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Praktik Terbaik"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Anggaran performa menetapkan standar performa situs Anda."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Anggaran"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Informasi selengkapnya tentang performa aplikasi Anda. Angka ini tidak [secara langsung memengaruhi](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) skor Performa."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostik"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Aspek terpenting dari performa adalah seberapa cepat piksel dirender di layar. Metrik utama: First Contentful Paint, First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Penyempurnaan First Paint"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Saran ini dapat membantu pemuatan halaman menjadi lebih cepat. Saran tersebut tidak [secara langsung memengaruhi](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) skor Performa."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Peluang"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrik"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Menyempurnakan pengalaman pemuatan halaman keseluruhan, sehingga halaman responsif dan siap untuk digunakan secepatnya. Metrik utama: Waktu untuk Interaktif, Indeks Kecepatan"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Penyempurnaan Keseluruhan"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performa"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Pemeriksaan ini memvalidasi aspek-aspek Progressive Web App. [Pelajari lebih lanjut](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Pemeriksaan ini diperlukan oleh [Checklist PWA](https://developers.google.com/web/progressive-web-apps/checklist) untuk dasar pengukuran tetapi tidak otomatis diperiksa oleh Lighthouse. Pemeriksaan tersebut tidak memengaruhi skor, tetapi penting karena hal ini berarti Anda memverifikasi situs-situs secara manual."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Cepat dan dapat diandalkan"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Dapat Diinstal"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA yang Dioptimalkan"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Pemeriksaan ini memastikan bahwa halaman Anda dioptimalkan untuk pemeringkatan hasil mesin telusur. Ada faktor lain yang tidak diperiksa Lighthouse yang dapat memengaruhi pemeringkatan penelusuran Anda. [Pelajari lebih lanjut](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Jalankan validator tambahan ini di situs Anda untuk memeriksa praktik terbaik SEO lainnya."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Format HTML Anda dengan cara yang memungkinkan crawler untuk lebih memahami konten aplikasi Anda."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Praktik Terbaik Konten"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Agar muncul di hasil penelusuran, crawler perlu mengakses aplikasi Anda."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawling dan Pengindeksan"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Pastikan halaman Anda mobile-friendly agar pengguna tidak perlu mencubit atau memperbesar untuk membaca halaman konten. [Pelajari lebih lanjut](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobile Friendly"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL Cache"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokasi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nama"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Permintaan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Jenis Resource"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Ukuran"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Waktu yang Dihabiskan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Ukuran Transfer"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potensi Penghematan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potensi Penghematan"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potensi penghematan sebesar {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potensi penghematan {wastedMs, number, milliseconds} md"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokumen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Gambar"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} md"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Lainnya"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skrip"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} dtk"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Pihak ketiga"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Terjadi kesalahan saat merekam jejak selama pemuatan halaman Anda. Harap jalankan Lighthouse kembali. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Waktu tunggu untuk sambungan Protokol Debugger awal berakhir."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome tidak mengumpulkan screenshot apa pun selama pemuatan halaman. Pastikan terdapat konten yang terlihat pada halaman, kemudian coba jalankan kembali Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Server DNS tidak dapat menetapkan domain yang disediakan."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Terjadi error pada pengumpul {artifactName} wajib: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Terjadi error Chrome internal. Harap mulai ulang Chrome dan coba jalankan kembali Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Pengumpul {artifactName} yang diperlukan tidak berjalan."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse tidak dapat memuat halaman yang Anda minta dengan lancar. Pastikan Anda menguji URL yang benar dan server merespons semua permintaan dengan baik."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse tidak dapat memuat URL yang Anda minta dengan lancar karena halaman berhenti merespons."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL yang Anda berikan tidak memiliki sertifikat keamanan yang valid. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome mencegah pemuatan halaman dengan interstisial. Pastikan Anda menguji URL yang benar dan server merespons semua permintaan dengan baik."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse tidak dapat memuat halaman yang Anda minta dengan lancar. Pastikan Anda menguji URL yang benar dan server merespons semua permintaan dengan baik. (Detail: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse tidak dapat memuat halaman yang Anda minta dengan lancar. Pastikan Anda menguji URL yang benar dan server merespons semua permintaan dengan baik. (Kode status: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Waktu pemuatan halaman Anda terlalu lama. Harap ikuti peluang dalam laporan untuk mengurangi waktu muat halaman Anda, kemudian coba jalankan kembali Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Waktu tunggu respons protokol DevTools telah melampaui waktu yang dialokasikan. (Metode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Pengambilan konten resource telah melampaui waktu yang dialokasikan"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "URL yang Anda berikan tampaknya tidak valid."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Tampilkan audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navigasi Awal"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latensi lokasi kritis maksimal:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Error!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Error laporan: tidak ada informasi audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Data Lab"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analisis [Lighthouse](https://developers.google.com/web/tools/lighthouse/) untuk halaman saat ini di jaringan seluler teremulasi. Nilai adalah hasil perkiraan dan dapat berbeda-beda."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Item tambahan untuk diperiksa secara manual"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Tidak berlaku"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Peluang"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Perkiraan Penghematan"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Lulus audit"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Ciutkan cuplikan"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Luaskan cuplikan"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Tampilkan resource pihak ketiga"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Ada masalah yang memengaruhi jalannya Lighthouse ini:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Nilai adalah hasil perkiraan dan dapat berbeda-beda. Skor performa [hanya berdasarkan metrik-metrik ini](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Lulus audit tetapi dengan peringatan"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Peringatan: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Sebaiknya upload GIF ke server yang akan menyediakannya untuk disematkan sebagai video HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instal [plugin pemuatan lambat di WordPress ](https://wordpress.org/plugins/search/lazy+load/) yang menyediakan kemampuan untuk menunda pemuatan gambar di bagian halaman yang belum ditampilkan, atau beralihlah ke tema yang menyediakan fungsi tersebut. Sebaiknya juga gunakan [plugin AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Terdapat sejumlah plugin di WordPress yang dapat membantu Anda [menyejajarkan aset penting](https://wordpress.org/plugins/search/critical+css/) atau [menunda resource yang tidak penting](https://wordpress.org/plugins/search/defer+css+javascript/). Harap berhati-hati karena pengoptimalan yang disediakan oleh plugin ini dapat merusak fitur tema atau plugin, sehingga Anda cenderung perlu mengubah kode."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Semua spesifikasi tema, plugin, dan server berkontribusi pada waktu respons server. Sebaiknya cari tema yang lebih optimal, pilih plugin pengoptimalan dengan hati-hati, dan/atau upgrade server Anda."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Sebaiknya tampilkan kutipan dalam daftar postingan (misalnya melalui tag lainnya), kurangi jumlah postingan yang ditampilkan pada halaman yang ada, bagi postingan panjang menjadi beberapa halaman, atau gunakan plugin untuk menunda pemuatan (lazy-load) komentar."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Sejumlah [plugin WordPress](https://wordpress.org/plugins/search/minify+css/) dapat mempercepat situs Anda dengan menggabungkan, meminifikasi, dan mengompresi gaya Anda. Anda juga dapat menggunakan proses pembuatan build untuk melakukan minifikasi di tahap awal jika memungkinkan."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Sejumlah [plugin WordPress](https://wordpress.org/plugins/search/minify+javascript/) dapat mempercepat situs Anda dengan menggabungkan, meminifikasi, dan mengompresi skrip. Anda juga dapat menggunakan proses pembuatan build untuk melakukan minifikasi di awal jika mungkin."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Sebaiknya kurangi atau ubah jumlah [plugin WordPress](https://wordpress.org/plugins/) yang memuat CSS yang tidak digunakan di halaman Anda. Untuk mengidentifikasi plugin yang menambahkan CSS tidak relevan, coba jalankan [cakupan kode](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) di Chrome DevTools. Anda dapat mengidentifikasi tema/plugin yang bertanggung jawab dari URL stylesheet. Cari plugin yang memiliki banyak stylesheet dalam daftar yang memiliki banyak warna merah dalam cakupan kode. Plugin sebaiknya hanya menambahkan stylesheet ke antrean jika memang benar digunakan di halaman."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Sebaiknya kurangi atau ubah jumlah [plugin WordPress](https://wordpress.org/plugins/) yang memuat JavaScript yang tidak digunakan di halaman Anda. Untuk mengidentifikasi plugin yang menambahkan JS tidak relevan, coba jalankan [cakupan kode](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) di Chrome DevTools. Anda dapat mengidentifikasi tema/plugin yang bertanggung jawab dari URL skrip. Cari plugin dengan banyak skrip dalam daftar yang memiliki banyak warna merah dalam cakupan kode. Plugin sebaiknya hanya menambahkan skrip ke dalam antrean jika memang benar digunakan di halaman."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Baca [Cache Browser di WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Sebaiknya gunakan [plugin WordPress untuk pengoptimalan gambar](https://wordpress.org/plugins/search/optimize+images/) yang mengompresi gambar Anda dengan tetap mempertahankan kualitas."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Upload gambar langsung melalui [koleksi media](https://codex.wordpress.org/Media_Library_Screen) untuk memastikan ukuran gambar yang diperlukan tersedia, lalu masukkan koleksi media atau gunakan widget gambar untuk memastikan ukuran gambar optimal digunakan (termasuk untuk titik henti sementara responsif). Hindari menggunakan gambar `Full Size`, kecuali dimensinya memungkinkan untuk digunakan. [Pelajari Lebih Lanjut](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Anda dapat mengaktifkan kompresi teks di konfigurasi server web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Sebaiknya gunakan [plugin](https://wordpress.org/plugins/search/convert+webp/) atau layanan yang otomatis mengonversi gambar yang diupload ke format optimal."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/it.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/it.json
new file mode 100644
index 00000000000..7feb23145b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/it.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Le chiavi di accesso consentono agli utenti di impostare rapidamente lo stato attivo su una parte della pagina. Per assicurare una navigazione corretta, ogni chiave di accesso deve essere univoca. [Ulteriori informazioni](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "I valori `[accesskey]` non sono univoci"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "I valori `[accesskey]` sono univoci"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Ogni elemento `role` di ARIA supporta un determinato sottoinsieme di attributi `aria-*`. Se non dovessero corrispondere, gli attributi `aria-*` non saranno considerati validi. [Ulteriori informazioni](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Gli attributi `[aria-*]` non corrispondono ai rispettivi ruoli"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Gli attributi `[aria-*]` corrispondono ai rispettivi ruoli"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Alcuni ruoli di ARIA hanno attributi obbligatori che descrivono lo stato dell'elemento agli screen reader. [Ulteriori informazioni](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Gli elementi `[role]` non hanno tutti gli attributi `[aria-*]` obbligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Gli elementi `[role]` hanno tutti gli attributi `[aria-*]` obbligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Alcuni ruoli principali di ARIA devono contenere specifici ruoli secondari per poter eseguire le funzionalità per l'accessibilità previste. [Ulteriori informazioni](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Negli elementi con un ruolo ARIA `[role]` che richiedono che gli elementi secondari contengano un ruolo `[role]` specifico mancano alcuni o tutti questi elementi secondari obbligatori."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Gli elementi con un ruolo ARIA `[role]` che richiedono che gli elementi secondari contengano un ruolo `[role]` specifico hanno tutti gli elementi secondari obbligatori."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Alcuni ruoli secondari di ARIA devono essere contenuti in specifici ruoli principali per poter eseguire in modo corretto le funzionalità per l'accessibilità previste. [Ulteriori informazioni](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Gli elementi `[role]` non sono contenuti nei rispettivi elementi principali obbligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Gli elementi `[role]` sono contenuti nei rispettivi elementi principali obbligatori"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "I ruoli di ARIA devono contenere valori validi per poter eseguire le funzionalità per l'accessibilità previste. [Ulteriori informazioni](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "I valori `[role]` non sono validi"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "I valori `[role]` sono validi"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Le tecnologie di ausilio per la disabilità, come gli screen reader, non sono in grado di interpretare gli attributi di ARIA con valori non validi. [Ulteriori informazioni](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Gli attributi `[aria-*]` non hanno valori validi"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Gli attributi `[aria-*]` hanno valori validi"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Le tecnologie di ausilio per la disabilità, come gli screen reader, non sono in grado di interpretare gli attributi di ARIA con nomi non validi. [Ulteriori informazioni](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Gli attributi `[aria-*]` non sono validi o contengono errori ortografici"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Gli attributi `[aria-*]` sono validi e non contengono errori ortografici"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "I sottotitoli forniscono informazioni essenziali relative agli elementi audio, come chi sta parlando, il contenuto del dialogo e altre informazioni di contorno utilizzabili da non udenti e utenti con problemi di udito. [Ulteriori informazioni](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Negli elementi `<audio>` manca un elemento `<track>` con `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Gli elementi `<audio>` contengono un elemento `<track>` con `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementi respinti"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Quando un pulsante non ha un nome accessibile, gli screen reader lo descrivono semplicemente come \"pulsante\", rendendolo inutilizzabile per gli utenti che si affidano agli screen reader. [Ulteriori informazioni](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "I pulsanti non hanno nomi accessibili"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "I pulsanti hanno un nome accessibile"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Se aggiungi metodi per ignorare contenuti ripetitivi, la navigazione della pagina diventa più efficiente per chi usa la tastiera. [Ulteriori informazioni](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "La pagina non contiene alcun titolo, skip link o area di riferimento"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "La pagina contiene un titolo, uno skip link o un'area di riferimento"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Il testo a basso contrasto è difficile, se non impossibile, da leggere per molti utenti. [Ulteriori informazioni](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Il rapporto di contrasto tra i colori di sfondo e primo piano non è sufficiente."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Il rapporto di contrasto tra i colori di sfondo e primo piano è sufficiente"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Se il markup degli elenchi di definizioni non è stato eseguito in modo corretto, gli screen reader possono generare risultati ambigui o imprecisi. [Ulteriori informazioni](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Gli elementi `<dl>` non contengono solo gruppi `<dt>` e `<dd>` ed elementi `<script>` o `<template>` nell'ordine corretto."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Gli elementi `<dl>` contengono solo gruppi `<dt>` e `<dd>` ed elementi `<script>` o `<template>` nell'ordine corretto."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Gli elementi dell'elenco di definizioni (`<dt>` e `<dd>`) devono essere aggregati in un elemento `<dl>` principale affinché gli screen reader possano descriverli correttamente. [Ulteriori informazioni](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Gli elementi dell'elenco di definizioni non sono aggregati negli elementi `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Gli elementi dell'elenco di definizioni sono aggregati negli elementi `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Il titolo fornisce agli utenti di screen reader una panoramica della pagina, mentre per gli utenti di motori di ricerca è utile per stabilire se una pagina è attinente alla loro ricerca. [Ulteriori informazioni](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Il documento non ha un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Il documento ha un elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Il valore di un attributo id deve essere univoco per evitare che altre istanze vengano ignorate dalle tecnologie di ausilio per la disabilità. [Ulteriori informazioni](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Gli attributi `[id]` nella pagina non sono univoci"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Gli attributi `[id]` nella pagina sono univoci"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Gli screen reader si affidano ai titoli dei frame per descrivere i contenuti dei frame agli utenti. [Ulteriori informazioni](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Gli elementi `<frame>` o `<iframe>` non hanno un titolo"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Gli elementi `<frame>` o `<iframe>` hanno un titolo"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Se per una pagina non viene specificato alcun attributo lang, lo screen reader presuppone che la lingua della pagina sia quella predefinita scelta dall'utente durante la configurazione dello screen reader. Se la lingua della pagina non è effettivamente quella predefinita, lo screen reader potrebbe non pronunciare correttamente il testo della pagina. [Ulteriori informazioni](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "L'elemento `<html>` non ha un attributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "L'elemento `<html>` ha un attributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "La specifica di una [lingua BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valida consente agli screen reader di pronunciare correttamente il testo. [Ulteriori informazioni](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "L'attributo `[lang]` dell'elemento `<html>` non ha un valore valido."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "L'attributo `[lang]` dell'elemento `<html>` ha un valore valido"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Gli elementi informativi dovrebbero mostrare testo alternativo breve e descrittivo. Gli elementi decorativi possono essere ignorati con un attributo alt vuoto. [Ulteriori informazioni](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Gli elementi immagine non hanno attributi `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Gli elementi immagine hanno attributi `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Quando viene utilizzata un'immagine come pulsante `<input>`, fornire del testo alternativo può aiutare gli utenti di screen reader a comprendere lo scopo del pulsante. [Ulteriori informazioni](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Gli elementi `<input type=\"image\">` non hanno testo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Gli elementi `<input type=\"image\">` hanno testo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Le etichette consentono di assicurarsi che i comandi dei moduli vengano descritti in modo corretto dalle tecnologie di ausilio per la disabilità, come gli screen reader. [Ulteriori informazioni](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Gli elementi del modulo non hanno le corrispondenti etichette"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Gli elementi del modulo sono associati a etichette"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Una tabella utilizzata per il layout non deve includere elementi di dati, come elementi th, elementi didascalia o l'attributo riepilogo, per evitare di confondere gli utenti di screen reader. [Ulteriori informazioni](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Gli elementi `<table>` della presentazione non evitano di utilizzare `<th>`, `<caption>` o l'attributo`[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Gli elementi `<table>` della presentazione evitano di utilizzare `<th>`, `<caption>` o l'attributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Un testo dei link (incluso il testo alternativo delle immagini, se usate come link) distinguibile, univoco e per cui sia impostabile lo stato attivo migliora l'esperienza di navigazione per gli utenti di screen reader. [Ulteriori informazioni](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Il nome dei link non è distinguibile"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "I link hanno un nome distinguibile"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Gli screen reader descrivono gli elenchi in un determinato modo. Una struttura dell'elenco corretta agevola il compito dello screen reader. [Ulteriori informazioni](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Gli elenchi non contengono solo elementi `<li>` ed elementi che supportano script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Gli elenchi contengono solo elementi `<li>` ed elementi che supportano gli script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Gli screen reader richiedono che gli elementi dell'elenco (`<li>`) siano contenuti in un elemento `<ul>` o `<ol>` principale per poterli descrivere in modo corretto. [Ulteriori informazioni](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Gli elementi dell'elenco (`<li>`) non sono contenuti in elementi principali `<ul>` o `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Gli elementi dell'elenco (`<li>`) sono contenuti in elementi principali `<ul>` o `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "L'aggiornamento automatico della pagina è un evento imprevisto per l'utente e, una volta verificatosi, imposta di nuovo lo stato attivo sulla parte superiore della pagina. Ciò può costituire motivo di frustrazione o confusione per l'utente. [Ulteriori informazioni](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Il documento usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Il documento non usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Disattivare lo zoom è problematico per gli utenti ipovedenti che si affidano all'ingrandimento dello schermo per vedere in modo chiaro i contenuti di una pagina web. [Ulteriori informazioni](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` viene usato nell'elemento `<meta name=\"viewport\">` o l'attributo `[maximum-scale]` è inferiore a 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` non viene usato nell'elemento `<meta name=\"viewport\">` e l'attributo `[maximum-scale]` non è inferiore a 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Gli screen reader non possono tradurre contenuti non testuali. Aggiungere testo alternativo agli elementi `<object>` aiuta gli screen reader a comunicare il significato agli utenti. [Ulteriori informazioni](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Gli elementi `<object>` non hanno testo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Gli elementi `<object>` hanno testo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Un valore maggiore di 0 implica un ordine di navigazione esplicito. Sebbene sia tecnicamente valido, spesso genera un'esperienza frustrante per gli utenti che usano tecnologie di ausilio per la disabilità. [Ulteriori informazioni](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Alcuni elementi hanno un valore `[tabindex]` maggiore di 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nessun elemento ha un valore `[tabindex]` maggiore di 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Gli screen reader sono dotati di funzionalità che semplificano lo spostamento nelle tabelle. Se ti assicuri che le celle `<td>` che usano l'attributo `[headers]` facciano riferimento esclusivamente ad altre celle nella stessa tabella puoi migliorare l'esperienza degli utenti di screen reader. [Ulteriori informazioni](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Le celle in un elemento `<table>` che utilizzano l'attributo `[headers]` fanno riferimento a un elemento `id` non trovato all'interno della stessa tabella."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Le celle in un elemento `<table>` che utilizzano l'attributo `[headers]` fanno riferimento a celle della stessa tabella."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Gli screen reader sono dotati di funzionalità che semplificano lo spostamento nelle tabelle. Se ti assicuri che le intestazioni delle tabelle facciano sempre riferimento a un insieme di celle puoi migliorare l'esperienza degli utenti di screen reader. [Ulteriori informazioni](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Gli elementi `<th>` e gli elementi con `[role=\"columnheader\"/\"rowheader\"]` non hanno le celle di dati da essi descritte."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Gli elementi `<th>` e gli elementi con ruolo `[role=\"columnheader\"/\"rowheader\"]` hanno le celle di dati da essi descritte."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "La specifica di una [lingua BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valida per gli elementi consente di assicurarsi che il testo sia pronunciato correttamente dallo screen reader. [Ulteriori informazioni](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Gli attributi `[lang]` non hanno un valore valido"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Gli attributi `[lang]` hanno un valore valido"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Se un video ha i sottotitoli, per i non udenti o gli utenti con problemi di udito è più facile accedere alle relative informazioni. [Ulteriori informazioni](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Gli elementi `<video>` non contengono un elemento `<track>` con `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Gli elementi `<video>` contengono un elemento `<track>` con `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Le descrizioni audio forniscono informazioni importanti che il dialogo non può trasmettere, come espressioni facciali e scene. [Ulteriori informazioni](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Gli elementi `<video>` non contengono un elemento `<track>` con `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Gli elementi `<video>` contengono un elemento `<track>` con `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Per una visualizzazione ottimale su iOS quando gli utenti aggiungono un'applicazione web progressiva alla schermata Home, definisci un elemento `apple-touch-icon`, che deve rimandare a un'immagine PNG quadrata di 192 px (o 180 px) non trasparente. [Ulteriori informazioni](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Non fornisce un valore `apple-touch-icon` valido"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Il valore `apple-touch-icon-precomposed` è obsoleto, pertanto è preferibile usare `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Fornisce un valore `apple-touch-icon` valido"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Le estensioni di Chrome incidono negativamente sulle prestazioni di caricamento di questa pagina. Prova a controllare la pagina in modalità di navigazione in incognito o da un profilo Chrome senza estensioni."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Valutazione degli script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analisi script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tempo di CPU totale"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Potresti ridurre i tempi di analisi, compilazione ed esecuzione di JavaScript. A tale scopo potrebbe essere utile pubblicare payload JavaScript di dimensioni inferiori. [Ulteriori informazioni](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Riduci il tempo di esecuzione di JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Tempo di esecuzione JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "I file GIF di grandi dimensioni non sono efficaci per la pubblicazione di contenuti animati. Anziché il formato GIF potresti usare video MPEG4/WebM per le animazioni e PNG/WebP per le immagini statiche. In questo modo userai meno byte di rete. [Ulteriori informazioni](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Usa formati video per i contenuti animati"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Potresti usare il caricamento lento per le immagini fuori schermo e nascoste al termine del caricamento di tutte le risorse fondamentali per ridurre il tempo necessario per la completa interattività. [Ulteriori informazioni](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Rimanda immagini fuori schermo"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Alcune risorse bloccano la prima visualizzazione della pagina. Potresti pubblicare le risorse JS/CSS fondamentali incorporate e rimandare tutte le risorse JS/styles non fondamentali. [Ulteriori informazioni](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimina le risorse di blocco della visualizzazione"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "I payload di rete di grandi dimensioni comportano costi reali per gli utenti e sono strettamente correlati a lunghi tempi di caricamento. [Ulteriori informazioni](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Dimensioni totali: {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evita payload di rete enormi"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Vengono evitati payload di rete enormi"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minimizza i file CSS per ridurre le dimensioni dei payload di rete. [Ulteriori informazioni](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minimizza CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minimizza i file JavaScript per ridurre le dimensioni dei payload e i tempi di analisi degli script. [Ulteriori informazioni](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minimizza JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Rimuovi le regole non valide dai fogli di stile e rimanda il caricamento dei CSS non utilizzati per i contenuti above the fold per ridurre i byte inutili consumati dall'attività di rete. [Ulteriori informazioni](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Rimuovi il CSS inutilizzato"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Rimuovi il codice JavaScript inutilizzato per ridurre i byte consumati dall'attività di rete."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Rimuovi il codice JavaScript inutilizzato"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "La memorizzazione nella cache per un lungo periodo di tempo può velocizzare le visite abituali alla tua pagina. [Ulteriori informazioni](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 risorsa trovata}other{# risorse trovate}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Pubblica le risorse statiche con criteri della cache efficaci"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Vengono usati criteri della cache efficaci per le risorse statiche"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Le immagini ottimizzate vengono caricate più velocemente e consumano meno traffico della rete dati. [Ulteriori informazioni](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifica in modo efficace le immagini"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Pubblica immagini di dimensioni adeguate per consumare meno traffico della rete dati e ridurre i tempi di caricamento. [Ulteriori informazioni](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Usa immagini di dimensioni adeguate"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Le risorse basate sul testo dovrebbero essere pubblicate con compressione (gzip, deflate o brotli) per ridurre al minimo il numero totale di byte di rete. [Ulteriori informazioni](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Attiva la compressione del testo"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "I formati delle immagini come JPEG 2000, JPEG XR e WebP spesso consentono una compressione migliore rispetto a quella dei formati PNG o JPEG, che comporta download più veloci e un minor consumo di dati. [Ulteriori informazioni](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Pubblica immagini in formati più recenti"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Se la larghezza dei contenuti dell'app non corrisponde alla larghezza dell'area visibile, l'app potrebbe non essere ottimizzata per gli schermi dei dispositivi mobili. [Ulteriori informazioni](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Le dimensioni di {innerWidth} px dell'area visibile non corrispondono alle dimensioni di {outerWidth} px della finestra."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Le dimensioni dei contenuti non sono corrette per l'area visibile"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Le dimensioni dei contenuti sono corrette per l'area visibile"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Nella sezione Catene di richieste fondamentali indicata di seguito vengono mostrate le risorse caricate con priorità elevata. Potresti ridurre la lunghezza delle catene e le dimensioni del download delle risorse oppure rimandare il download delle risorse non necessarie per velocizzare il caricamento della pagina. [Ulteriori informazioni](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 catena trovata}other{# catene trovate}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Riduci al minimo la profondità delle richieste fondamentali"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Ritiro/avviso"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Riga"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Le API obsolete verranno rimosse dal browser prima o poi. [Ulteriori informazioni](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 avviso trovato}other{# avvisi trovati}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Usa API obsolete"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita le API obsolete"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "L'API Cache applicazione è obsoleta. [Ulteriori informazioni](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" trovato"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Usa l'API Cache applicazione"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita l'API Cache applicazione"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "La specifica di un doctype impedisce al browser di passare alla modalità non standard. [Ulteriori informazioni](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Il nome del doctype deve essere la stringa minuscola `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Il documento deve contenere un doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Il campo publicId dovrebbe essere vuoto"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Il campo systemId dovrebbe essere vuoto"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Nella pagina manca il doctype HTML e viene quindi attivata la modalità non standard"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "La pagina ha il doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistica"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valore"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Gli ingegneri che si occupano dei browser consigliano di usare meno di ~1500 elementi DOM per le pagine. L'ideale sarebbe una struttura ad albero con profondità di < 32 elementi e meno di 60 elementi secondari/principali. Un DOM di grandi dimensioni può aumentare l'utilizzo di memoria, causare [calcoli di stile](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) più lunghi e generare costosi [adattamenti dinamici del layout](https://developers.google.com/speed/articles/reflow). [Ulteriori informazioni](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemento}other{# elementi}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evita di usare un DOM di dimensioni eccessive"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profondità massima DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Elementi DOM totali"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Elementi secondari massimi"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Viene evitato un DOM di dimensioni eccessive"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Aggiungi `rel=\"noopener\"` o `rel=\"noreferrer\"` a eventuali link esterni per migliorare le prestazioni ed evitare vulnerabilità di sicurezza. [Ulteriori informazioni](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "I link che rimandano a destinazioni multiorigine non sono sicuri"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "I link che rimandano a destinazioni multiorigine sono sicuri"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Impossibile stabilire la destinazione dell'ancoraggio ({anchorHTML}). Se non viene usato come link ipertestuale, potresti rimuovere target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Gli utenti sono sospettosi nei confronti dei siti che chiedono la loro posizione senza contesto o sono confusi da tali siti. Potresti associare la richiesta a un'azione dell'utente. [Ulteriori informazioni](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Chiede l'autorizzazione alla geolocalizzazione durante il caricamento della pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita di chiedere l'autorizzazione alla geolocalizzazione durante il caricamento della pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versione"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Tutte le librerie JavaScript front-end rilevate nella pagina. [Ulteriori informazioni](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Librerie JavaScript rilevate"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Per gli utenti con connessioni lente, gli script esterni inseriti in modo dinamico tramite `document.write()` potrebbero ritardare il caricamento della pagina di decine di secondi. [Ulteriori informazioni](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Usa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evita `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Massima gravità"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versione libreria"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Numero di vulnerabilità"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Alcuni script di terze parti potrebbero contenere vulnerabilità di sicurezza note facilmente identificate e sfruttate dai malintenzionati. [Ulteriori informazioni](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vulnerabilità rilevata}other{# vulnerabilità rilevate}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Include librerie JavaScript front-end con vulnerabilità di sicurezza note"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Bassa"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Media"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita librerie JavaScript front-end con vulnerabilità di sicurezza note"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Gli utenti sono sospettosi nei confronti dei siti che chiedono di inviare notifiche senza contesto o sono confusi da tali siti. Potresti associare la richiesta ai gesti dell'utente. [Ulteriori informazioni](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Chiede l'autorizzazione di accesso alle notifiche durante il caricamento della pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita di chiedere l'autorizzazione di accesso alle notifiche durante il caricamento della pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementi che non consentono di incollare"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Impedire di incollare le password pregiudica l'efficacia delle norme di sicurezza. [Ulteriori informazioni](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Impedisce agli utenti di incollare contenuti nei campi delle password"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Consente agli utenti di incollare contenuti nei campi delle password"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocollo"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 offre tanti vantaggi rispetto a HTTP/1.1, tra cui intestazioni binarie, multiplexing e push del server. [Ulteriori informazioni](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 richiesta non pubblicata tramite HTTP/2}other{# richieste non pubblicate tramite HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Non usa HTTP/2 per tutte le sue risorse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Usa HTTP/2 per le proprie risorse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Potresti contrassegnare i listener di eventi di tocco e rotellina come `passive` per migliorare le prestazioni di scorrimento della pagina. [Ulteriori informazioni](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Non usa listener passivi per migliorare le prestazioni dello scorrimento"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Usa listener passivi per migliorare le prestazioni dello scorrimento"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descrizione"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Gli errori registrati nella console indicano la presenza di problemi irrisolti che potrebbero riguardare richieste di rete non andate a buon fine e altri problemi del browser. [Ulteriori informazioni](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Gli errori del browser sono stati registrati nella console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nessun errore del browser registrato nella console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Usa la funzionalità CSS font-display per assicurarti che il testo sia visibile agli utenti durante il caricamento dei caratteri web. [Ulteriori informazioni](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Assicurati che il testo rimanga visibile durante il caricamento dei caratteri web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Tutto il testo rimane visibile durante il caricamento dei caratteri web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Impossibile controllare automaticamente in Lighthouse il valore font-display del seguente URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Proporzioni (effettive)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Proporzioni (visualizzate)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Le dimensioni di visualizzazione delle immagini dovrebbero corrispondere alle proporzioni naturali. [Ulteriori informazioni](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Visualizza immagini con proporzioni errate"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Visualizza immagini con proporzioni corrette"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informazioni sulle dimensioni dell'immagine {url} non valide"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "I browser possono chiedere proattivamente agli utenti di aggiungere la tua app alla schermata Home, che potrebbe comportare un maggiore coinvolgimento. [Ulteriori informazioni](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Il file manifest dell'applicazione web non soddisfa i requisiti di installabilità"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Il file manifest dell'applicazione web soddisfa i requisiti di installabilità"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL non sicuro"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Tutti i siti dovrebbero essere protetti con HTTPS, anche quelli che non trattano dati sensibili. HTTPS impedisce agli intrusi di manomettere o ascoltare passivamente le comunicazioni tra la tua app e i tuoi utenti ed è un prerequisito per HTTP/2 e tante nuove API delle piattaforme web. [Ulteriori informazioni](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 richiesta non sicura trovata}other{# richieste non sicure trovate}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Non usa HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Usa HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Il caricamento veloce delle pagine su una rete cellulare assicura una buona esperienza utente sui dispositivi mobili. [Ulteriori informazioni](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interattiva a {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interattiva su una rete mobile simulata a {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "La pagina viene caricata troppo lentamente e non diventa interattiva entro 10 secondi. Controlla le opportunità e i dati diagnostici della sezione \"Prestazioni\" per avere informazioni su come migliorare."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Il caricamento della pagina non è abbastanza veloce sulle reti mobili"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Il caricamento della pagina è abbastanza veloce sulle reti mobili"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoria"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Potresti ridurre i tempi di analisi, compilazione ed esecuzione di JavaScript. A tale scopo potrebbe essere utile pubblicare payload JavaScript di dimensioni inferiori. [Ulteriori informazioni](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Riduci al minimo il lavoro del thread principale"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Il lavoro del thread principale è ridotto al minimo"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Per raggiungere il maggior numero di utenti, i siti dovrebbero funzionare su ogni browser più usato. [Ulteriori informazioni](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Il sito funziona su più browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Assicurati che le singole pagine siano collegabili tramite link diretti sotto forma di URL e che gli URL siano univoci per la condivisione sui social media. [Ulteriori informazioni](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Ogni pagina ha un URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Le transizioni dovrebbero sembrare rapide mentre esegui i tocchi, anche con una rete lenta. Questa esperienza è un fattore che incide sulle prestazioni percepite dall'utente. [Ulteriori informazioni](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Non sembra che le transizioni di pagina si blocchino sulla rete"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "La metrica Latenza input stimata fornisce una stima del tempo impiegato dall'app, espresso in millisecondi, per rispondere all'input dell'utente durante il periodo di 5 s più impegnativo del caricamento della pagina. Se la latenza è superiore a 50 ms, gli utenti potrebbero considerare lenta la tua app. [Ulteriori informazioni](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latenza input stimata"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "La metrica First Contentful Paint (prima visualizzazione con contenuti) indica il momento in cui vengono visualizzati il primo testo o la prima immagine. [Ulteriori informazioni](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Visualizzazione dei primi contenuti"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "La metrica Prima inattività CPU indica la prima volta in cui il thread principale della pagina è abbastanza tranquillo da poter gestire l'input. [Ulteriori informazioni](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Prima inattività CPU"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "La metrica First Meaningful Paint (visualizzazione primo elemento utile) indica quando diventano visibili i contenuti principali di una pagina. [Ulteriori informazioni](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Visualizzazione primi contenuti utili"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "La metrica Tempo all'interattività indica il tempo necessario affinché la pagina diventi completamente interattiva. [Ulteriori informazioni](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tempo per interattività"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Il potenziale ritardo prima interazione massimo che i tuoi utenti potrebbero riscontrare è la durata, in millisecondi, del task più lungo. [Ulteriori informazioni](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Ritardo prima interazione potenziale max"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "La metrica Indice velocità mostra la velocità con cui diventano visibili i contenuti di una pagina. [Ulteriori informazioni](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indice velocità"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Somma di tutti i periodi di tempo, espressi in millisecondi, tra FCP e Tempo all'interattività, quando la durata del task ha superato 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tempo di blocco totale"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "I tempi di round trip della rete (RTT) influiscono notevolmente sulle prestazioni. Quando l'RTT verso un'origine è elevato, significa che i server più vicini all'utente potrebbero migliorare le prestazioni. [Ulteriori informazioni](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tempi di round trip della rete"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Le latenze dei server possono influire sulle prestazioni del Web. Quando la latenza del server di un'origine è elevata, significa che il server è sovraccarico oppure ha prestazioni di backend scadenti. [Ulteriori informazioni](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latenze server backend"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Un service worker rende la tua applicazione web affidabile in condizioni di rete imprevedibili. [Ulteriori informazioni](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` non risponde con un codice 200 quando è offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` risponde con un codice 200 quando è offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Impossibile leggere `start_url` dal file manifest in Lighthouse. Di conseguenza si presume che `start_url` sia l'URL del documento. Messaggio di errore: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Oltre il budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Mantieni la quantità e le dimensioni delle richieste di rete al di sotto dei target impostati tramite il budget per le prestazioni fornito. [Ulteriori informazioni](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 richiesta}other{# richieste}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Budget per le prestazioni"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Se hai già configurato HTTPS, assicurati di reindirizzare tutto il traffico HTTP a HTTPS per attivare funzionalità web sicure per tutti i tuoi utenti. [Ulteriori informazioni](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Non reindirizza il traffico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Reindirizza il traffico HTTP a HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "I reindirizzamenti comportano ulteriori ritardi prima del caricamento della pagina. [Ulteriori informazioni](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evita i reindirizzamenti tra più pagine"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Per impostare budget relativi alla quantità e alle dimensioni delle risorse della pagina, aggiungi un file budget.json. [Ulteriori informazioni](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 richiesta • {byteCount, number, bytes} kB}other{# richieste • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Mantieni un numero ridotto di richieste e dimensioni di trasferimento limitate"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "I link canonici suggeriscono quale URL mostrare nei risultati di ricerca. [Ulteriori informazioni](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Diversi URL in conflitto ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Rimanda a un altro dominio ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL non valido ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Rimanda a un'altra posizione `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relativo ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Indirizza all'URL principale del dominio (la home page), anziché a una pagina di contenuto equivalente"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Il documento non ha un valore `rel=canonical` valido"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Il documento ha un elemento `rel=canonical` valido"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Le dimensioni dei caratteri minori di 12 px sono troppo piccole per essere leggibili e richiederebbero ai visitatori di dispositivi mobili di \"pizzicare per eseguire lo zoom\" e poter leggere la pagina. Cerca di avere più del 60% del testo della pagina con una dimensione uguale o superiore a 12 px. [Ulteriori informazioni](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} del testo leggibile"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Il testo è illeggibile perché non esiste un meta tag viewport ottimizzato per gli schermi dei dispositivi mobili."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Il {decimalProportion, number, extendedPercent} del testo è troppo piccolo (in base a un campione del {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Il documento non usa dimensioni dei caratteri leggibili"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Il documento utilizza dimensioni dei caratteri leggibili"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "I link hreflang indicano ai motori di ricerca quale versione di una pagina devono elencare nei risultati di ricerca per una determinata lingua o area geografica. [Ulteriori informazioni](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Il documento non ha un elemento `hreflang` valido"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Il documento ha un elemento `hreflang` valido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Le pagine con codici di stato HTTP non validi potrebbero non essere indicizzate correttamente. [Ulteriori informazioni](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "La pagina ha un codice di stato HTTP non valido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "La pagina ha un codice di stato HTTP valido"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "I motori di ricerca non sono in grado di includere le pagine nei risultati di ricerca se non dispongono dell'autorizzazione per eseguirne la scansione. [Ulteriori informazioni](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "L'indicizzazione della pagina è bloccata"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "L'indicizzazione della pagina non è bloccata"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Il testo descrittivo dei link aiuta i motori di ricerca a comprendere i tuoi contenuti. [Ulteriori informazioni](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link trovato}other{# link trovati}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "I link non contengono testo descrittivo"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "I link hanno un testo descrittivo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Esegui lo [Strumento di test per i dati strutturati](https://search.google.com/structured-data/testing-tool/) e [Structured Data Linter](http://linter.structured-data.org/) per convalidare i dati strutturati. [Ulteriori informazioni](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Dati strutturati validi"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Le meta descrizioni possono essere incluse nei risultati di ricerca per riassumere brevemente i contenuti della pagina. [Ulteriori informazioni](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Il testo della descrizione è vuoto."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Il documento non ha una meta descrizione"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Il documento ha una meta descrizione"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "I motori di ricerca non possono indicizzare i contenuti dei plug-in e molti dispositivi limitano i plug-in o non li supportano. [Ulteriori informazioni](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Il documento utilizza plug-in"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Il documento non fa uso di plug-in"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Se il file robots.txt non è valido, i crawler potrebbero non essere in grado di capire come vuoi che il tuo sito web venga sottoposto a scansione o indicizzato. [Ulteriori informazioni](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "La richiesta per robots.txt ha restituito uno stato HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 errore trovato}other{# errori trovati}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse non può completare il download del file robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt non è valido"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt è valido"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Gli elementi interattivi come pulsanti e link dovrebbero essere abbastanza grandi (48 x 48 px) e avere abbastanza spazio intorno a loro, per essere facili da toccare senza sovrapporsi ad altri elementi. [Ulteriori informazioni](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Il {decimalProportion, number, percent} dei target dei tocchi ha dimensioni appropriate"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "I target dei tocchi sono troppo piccoli perché non esiste un meta tag viewport ottimizzato per gli schermi dei dispositivi mobili"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "I target dei tocchi non sono dimensionati in modo appropriato"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Target sovrapposto"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Target dei tocchi"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "I target dei tocchi sono dimensionati in modo appropriato"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Il service worker è la tecnologia che consente alla tua app di usare tante funzionalità delle applicazioni web progressive, ad esempio il funzionamento offline, l'aggiunta alla schermata Home e le notifiche push. [Ulteriori informazioni](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Questa pagina è controllata tramite un service worker, ma non è stato trovato alcun elemento `start_url` perché non è stato possibile analizzare il file manifest come JSON valido"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Questa pagina è controllata tramite un service worker, ma `start_url` ({startUrl}) non rientra nell'ambito del service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Questa pagina è controllata tramite un service worker, ma non è stato trovato alcun elemento `start_url` perché non è stato recuperato alcun file manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Questa origine contiene uno o più service worker, ma la pagina ({pageUrl}) non rientra nell'ambito."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Non registra un service worker che controlla la pagina e `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registra un service worker che controlla la pagina e `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Una schermata iniziale a tema assicura un'esperienza di alta qualità quando gli utenti avviano la tua app dalla schermata Home. [Ulteriori informazioni](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Non è configurato con una schermata iniziale personalizzata"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configurato con una schermata iniziale personalizzata"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "È possibile impostare per la barra degli indirizzi del browser un tema corrispondente a quello del tuo sito. [Ulteriori informazioni](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Non imposta un colore tema per la barra degli indirizzi."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Imposta un colore tema per la barra degli indirizzi."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Durata blocco thread principale"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Terza parte"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Il codice di terze parti può incidere notevolmente sulle prestazioni del caricamento. Limita il numero di provider di terze parti superflui e prova a caricare il codice di terze parti al termine del caricamento della pagina. [Ulteriori informazioni](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Il codice di terze parti ha bloccato il thread principale per {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Riduci l'impatto del codice di terze parti"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Uso di terze parti"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "La metrica Tempo per primo byte identifica il momento in cui il server invia una risposta. [Ulteriori informazioni](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Il documento radice ha richiesto {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Riduci i tempi di risposta del server (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "I tempi di risposta del server sono brevi (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Durata"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Inizio"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipo"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Potresti dotare la tua app dell'API User Timing per misurare le prestazioni reali dell'app durante le esperienze utente chiave. [Ulteriori informazioni](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 tempo utente}other{# tempi utente}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Indicatori e misure User Timing"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "È stato trovato un elemento <link> di preconnessione per \"{securityOrigin}\", ma non è stato utilizzato dal browser. Verifica che l'attributo `crossorigin` sia utilizzato in modo corretto."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Potresti aggiungere hint delle risorse `preconnect` o `dns-prefetch` per collegarti anticipatamente a importanti origini di terze parti. [Ulteriori informazioni](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Precollegati alle origini necessarie"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "È stato trovato un elemento <link> di precaricamento per \"{preloadURL}\", ma non è stato utilizzato dal browser. Verifica che l'attributo `crossorigin` sia utilizzato in modo corretto."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Potresti usare `<link rel=preload>` per dare la priorità al recupero delle risorse attualmente richieste in un secondo momento nel caricamento della pagina. [Ulteriori informazioni](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Precarica le richieste fondamentali"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Aggiungi un tag `<meta name=\"viewport\">` per ottimizzare la tua app per gli schermi dei dispositivi mobili. [Ulteriori informazioni](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nessun tag `<meta name=\"viewport\">` trovato"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Non ha un tag `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ha un tag `<meta name=\"viewport\">` con `width` o `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Nella tua app dovresti visualizzare alcuni contenuti quando JavaScript è disattivato, anche soltanto un avviso che comunica all'utente che è necessario JavaScript per usare l'app. [Ulteriori informazioni](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Nel corpo della pagina dovrebbero essere visualizzati alcuni contenuti se gli script della pagina non sono disponibili."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Non fornisce contenuti di riserva quando JavaScript non è disponibile"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Ha alcuni contenuti quando JavaScript non è disponibile"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Se devi creare un'applicazione web progressiva, potresti usare un service worker per far funzionare la tua app offline. [Ulteriori informazioni](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "La pagina attuale non risponde con un codice 200 quando è offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "La pagina attuale risponde con un codice 200 quando è offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "La pagina potrebbe non essere caricata offline perché l'URL di prova ({requested}) è stato reindirizzato a \"{final}\". Prova a testare direttamente il secondo URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Si tratta di opportunità per facilitare l'uso di ARIA nella tua applicazione e migliorare l'esperienza per gli utenti di tecnologie per la disabilità, come uno screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Si tratta di opportunità per fornire contenuti alternativi per audio e video. Ciò può migliorare l'esperienza per gli utenti con problemi di udito o di vista."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio e video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Questi elementi evidenziano le best practice di accessibilità comuni."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Best practice"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Questi controlli mettono in evidenza le opportunità per [migliorare l'accessibilità della tua applicazione web](https://developers.google.com/web/fundamentals/accessibility). È possibile rilevare automaticamente soltanto un sottoinsieme di problemi di accessibilità, pertanto sono consigliati anche i test manuali."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Questi elementi riguardano aree che uno strumento di test automatizzato non può coprire. Leggi ulteriori informazioni nella nostra guida su come [effettuare un esame di accessibilità](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accessibilità"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Si tratta di opportunità per migliorare la leggibilità dei contenuti."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrasto"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Si tratta di opportunità per migliorare l'interpretazione data ai tuoi contenuti da utenti di lingua diversa."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internazionalizzazione e localizzazione"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Si tratta di opportunità per migliorare la semantica dei comandi della tua applicazione. Ciò può migliorare l'esperienza per gli utenti di tecnologie per la disabilità, come uno screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nomi ed etichette"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Si tratta di opportunità per migliorare la navigazione da tastiera nella tua applicazione."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigazione"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Si tratta di opportunità per migliorare l'esperienza di lettura dei dati nelle tabelle o negli elenchi per gli utenti di tecnologie per la disabilità, come uno screen reader."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabelle ed elenchi"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Best practice"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "I budget per le prestazioni consentono di stabilire gli standard per le prestazioni del tuo sito."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budget"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Ulteriori informazioni sulle prestazioni della tua applicazione. Questi valori non [incidono direttamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) sul punteggio Prestazioni."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostica"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "L'aspetto più importante delle prestazioni è la velocità di visualizzazione dei pixel sullo schermo. Metriche chiave: Visualizzazione dei primi contenuti, Visualizzazione primi contenuti utili"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Miglioramenti della prima visualizzazione"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Questi suggerimenti possono aiutarti a velocizzare il caricamento della pagina. Non [incidono direttamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) sul punteggio Prestazioni."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Opportunità"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metriche"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Migliora l'esperienza di caricamento generale per fare in modo che la pagina diventi reattiva e pronta all'uso nel più breve tempo possibile. Metriche chiave: Tempo per interattività, Indice velocità"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Miglioramenti generali"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Prestazioni"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Questi controlli consentono di convalidare gli aspetti di un'applicazione web progressiva. [Ulteriori informazioni](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Questi controlli sono richiesti in base all'[Elenco di controllo PWA](https://developers.google.com/web/progressive-web-apps/checklist) di riferimento, ma non vengono eseguiti automaticamente da Lighthouse. Non incidono sul tuo punteggio, ma è importante verificarli manualmente."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Applicazione web progressiva"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Veloce e affidabile"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Installabile"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Ottimizzato per PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Questi controlli assicurano che la pagina sia ottimizzata per il ranking dei risultati del motore di ricerca. Ci sono altri fattori che Lighthouse non controlla che potrebbero incidere sul ranking nella ricerca. [Ulteriori informazioni](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Esegui questi altri strumenti di convalida sul tuo sito per controllare ulteriori best practice per SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatta il tuo codice HTML in modo che i crawler possano comprendere meglio i contenuti della tua app."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Best practice per i contenuti"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Per poter mostrare la tua app nei risultati di ricerca, i crawler devono potervi accedere."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Scansione e indicizzazione"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Assicurati che le tue pagine siano ottimizzate per i dispositivi mobili in modo che gli utenti non debbano pizzicare o aumentare lo zoom per riuscire a leggere i contenuti delle pagine. [Ulteriori informazioni](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Ottimizzata per i dispositivi mobili"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL cache"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Posizione"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nome"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Richieste"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipo di risorsa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Dimensioni"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tempo trascorso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Dimensioni trasferimento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potenziali riduzioni"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potenziali riduzioni"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potenziali riduzioni di {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potenziali riduzioni di {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Documento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Carattere"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Immagine"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Contenuti multimediali"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Altro"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Foglio di stile"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Terze parti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Totale"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Si è verificato un problema con la registrazione della traccia durante il caricamento della pagina. Esegui di nuovo Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Timeout durante l'attesa della connessione iniziale al protocollo del debugger."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome non ha raccolto nessuno screenshot durante il caricamento pagina. Assicurati che nella pagina siano presenti contenuti visibili, quindi riprova a eseguire Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "I server DNS non sono stati in grado di risolvere il dominio fornito."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Il gatherer {artifactName} richiesto ha riscontrato un errore: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Errore interno di Chrome. Riavvia Chrome e prova a eseguire di nuovo Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Il gatherer {artifactName} richiesto non è stato eseguito."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse non può completare il caricamento della pagina richiesta. Assicurati che l'URL verificato sia quello corretto e che il server stia rispondendo opportunamente a tutte le richieste."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse non può completare il caricamento dell'URL richiesto perché la pagina non risponde più."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "L'URL fornito non ha un certificato di sicurezza valido. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome ha impedito il caricamento della pagina con un interstitial. Assicurati che l'URL verificato sia quello corretto e che il server stia rispondendo opportunamente a tutte le richieste."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Impossibile caricare la pagina richiesta in modo affidabile in Lighthouse. Assicurati che l'URL verificato sia quello corretto e che il server stia rispondendo opportunamente a tutte le richieste. Informazioni dettagliate: {errorDetails}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Impossibile caricare la pagina richiesta in modo affidabile in Lighthouse. Assicurati che l'URL verificato sia quello corretto e che il server stia rispondendo opportunamente a tutte le richieste. (Codice di stato: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Il caricamento della tua pagina ha richiesto troppo tempo. Segui le opportunità fornite nel rapporto per ridurre il tempo di caricamento della pagina e prova a eseguire di nuovo Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Il tempo di attesa allocato per ricevere una risposta dal protocollo DevTools è scaduto. (Metodo: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Il tempo allocato per il recupero dei contenuti della risorsa è scaduto"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "L'URL fornito non è valido."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostra controlli"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navigazione iniziale"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latenza massima del percorso critico:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Errore"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Errore segnalato: nessuna informazione sul controllo"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dati di prova controllati"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analisi [Lighthouse](https://developers.google.com/web/tools/lighthouse/) della pagina corrente su una rete mobile emulata. I valori sono delle stime e potrebbero variare."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Ulteriori elementi da controllare manualmente"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Non applicabile"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Opportunità"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Risparmi stimati"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Controlli superati"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Comprimi snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Espandi snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostra risorse di terze parti"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Si sono verificati dei problemi che incidono su questa esecuzione di Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "I valori sono delle stime e potrebbero variare. Il punteggio relativo alle prestazioni è [basato soltanto su queste metriche](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Controlli superati ma con avvisi"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Avvisi: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Prendi in considerazione la possibilità di caricare la tua GIF su un servizio che la renda disponibile per l'incorporamento come video HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installa un [plug-in di WordPress per il caricamento lento](https://wordpress.org/plugins/search/lazy+load/) che consenta di rimandare qualsiasi immagine fuori schermo oppure passa a un tema che offra questa funzionalità. Potresti anche usare [il plug-in AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Esistono diversi plug-in di WordPress che possono esserti utili per [incorporare le risorse di importanza critica](https://wordpress.org/plugins/search/critical+css/) o [rimandare le risorse meno importanti](https://wordpress.org/plugins/search/defer+css+javascript/). Fai attenzione perché le ottimizzazioni offerte da questi plug-in potrebbero interrompere le funzionalità del tuo tema o dei tuoi plug-in, pertanto potresti dover modificare il codice."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Le specifiche del server, i plug-in e i temi contribuiscono al tempo di risposta del server. Prendi in considerazione l'idea di utilizzare un tema più ottimizzato, selezionando con cura un plug-in per l'ottimizzazione e/o eseguendo l'upgrade del server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Prendi in considerazione la possibilità di mostrare degli estratti nell'elenco dei tuoi post (ad esempio utilizzando il tag more), riducendo il numero di post che vengono mostrati su una determinata pagina, spezzando i post più lunghi su più pagine o utilizzando un plug-in per il caricamento differito dei commenti."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Esistono diversi [plug-in di WordPress](https://wordpress.org/plugins/search/minify+css/) in grado di velocizzare il tuo sito concatenando, minimizzando e comprimendo i tuoi stili. Puoi anche utilizzare una procedura di progettazione per eseguire la minimizzazione in anticipo, se possibile."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Esistono diversi [plug-in di WordPress](https://wordpress.org/plugins/search/minify+javascript/) in grado di velocizzare il tuo sito concatenando, minimizzando e comprimendo i tuoi script. Puoi anche utilizzare una procedura di progettazione per eseguire la minimizzazione in anticipo, se possibile."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Potresti ridurre, o cambiare, il numero di [plug-in di WordPress](https://wordpress.org/plugins/) che caricano file CSS inutilizzati nella tua pagina. Per individuare i plug-in che aggiungono CSS estraneo, prova a eseguire il [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. Puoi individuare il tema o il plug-in responsabile nell'URL del foglio di stile. Cerca i plug-in che nell'elenco hanno diversi fogli di stile con molto rosso nel code coverage. Un plug-in dovrebbe aggiungere in coda un foglio di stile solo se viene effettivamente utilizzato nella pagina."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Potresti ridurre, o cambiare, il numero di [plug-in di WordPress](https://wordpress.org/plugins/) che caricano file JavaScript inutilizzati nella tua pagina. Per individuare i plug-in che aggiungono JavaScript estraneo, prova a eseguire il [code coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) in Chrome DevTools. Puoi individuare il tema o il plug-in responsabile nell'URL dello script. Cerca i plug-in che nell'elenco hanno diversi script con molto rosso nel code coverage. Un plug-in dovrebbe aggiungere in coda uno script solo se viene effettivamente utilizzato nella pagina."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Leggi informazioni sulla [memorizzazione nella cache del browser in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Potresti usare un [plug-in di WordPress per l'ottimizzazione delle immagini](https://wordpress.org/plugins/search/optimize+images/) in grado di comprimere le tue immagini preservandone la qualità."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Carica le immagini direttamente tramite la [libreria multimediale](https://codex.wordpress.org/Media_Library_Screen) per assicurarti che siano disponibili le dimensioni delle immagini richieste, quindi inseriscile dalla libreria multimediale o utilizza il widget per immagini per assicurarti che vengano utilizzate le dimensioni ottimali (incluse quelle per i punti di interruzione adattabili). Evita di utilizzare immagini `Full Size`, a meno che le dimensioni siano adatte all'utilizzo previsto. [Ulteriori informazioni](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Puoi attivare la compressione del testo nella configurazione del server web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Potresti usare un [plug-in](https://wordpress.org/plugins/search/convert+webp/) o un servizio che converta automaticamente le immagini caricate nei formati ottimali."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ja.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ja.json
new file mode 100644
index 00000000000..64bec7ff192
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ja.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "アクセスキーは、ユーザーがページの特定の部分にすばやくフォーカスを移動するときに使います。正しく操作できるよう、各アクセスキーは一意にする必要があります。[詳細](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` の値が一意ではありません"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` の値は一意です"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "各 ARIA `role` は、`aria-*` 属性の特定のサブセットに対応しています。これらが一致しない場合、`aria-*` 属性は無効になります。[詳細](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` 属性は役割と一致していません"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` 属性は役割と一致しています"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "一部の ARIA 役割には、スクリーン リーダーに要素の状態を伝える必須の属性があります。[詳細](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` に必須の `[aria-*]` 属性が一部指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` に必須の `[aria-*]` 属性がすべて指定されています"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "目的のユーザー補助機能を実行するには、一部の ARIA 親役割に特定の子役割を含める必要があります。[詳細](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` are missing some or all of those required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "目的のユーザー補助機能を正しく実行するには、一部の ARIA 子役割を特定の親役割に含める必要があります。[詳細](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` が必須の親要素に含まれていません"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` は必須の親要素に含まれています"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "目的のユーザー補助機能を実行するには、ARIA 役割に有効な値を指定してください。[詳細](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` の値は無効です"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` の値は有効です"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "支援技術(スクリーン リーダーなど)で、無効な値が指定された ARIA 属性を解釈できません。[詳細](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` 属性に有効な値が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` 属性に有効な値が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "支援技術(スクリーン リーダーなど)で、無効な名前が指定された ARIA 属性を解釈できません。[詳細](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` 属性は無効か、スペルミスがあります"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` 属性は有効で、スペルミスもありません"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "字幕を使用すると、聴覚障がいのあるユーザーが音声要素を利用できるようになります。話している人物やその内容、その他の会話以外の情報など、重要な情報を字幕で伝えることができます。[詳細](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` 要素に `[kind=\"captions\"]` が指定された `<track>` 要素がありません。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` 要素に `[kind=\"captions\"]` が指定された `<track>` 要素が含まれています"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "問題のある要素"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "ボタンにユーザー補助機能名が指定されていない場合、スクリーン リーダーでは「ボタン」と読み上げられるため、スクリーン リーダーを使用しているユーザーはボタンの用途がわからず、使用することができなくなります。[詳細](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "ボタンにユーザー補助機能名が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "ボタンにユーザー補助機能名が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "重複するコンテンツをスキップする手段を追加すると、キーボードを使ったページの移動を効率化できます。[詳細](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "ページに見出し、スキップリンク、またはランドマーク領域が設定されていません"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "ページに見出し、スキップリンク、またはランドマーク領域が設定されています"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "低コントラストのテキストを使用すると、多くのユーザーは読むことが困難または不可能になります。[詳細](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "背景色と前景色には十分なコントラスト比がありません"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "背景色と前景色には十分なコントラスト比があります"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "定義リストが適切にマークアップされていないと、スクリーン リーダーで、誤解を招く内容や不正確な内容が読み上げられる可能性があります。[詳細](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` には、正しく順序付けられた `<dt>` および `<dd>` グループ、`<script>` または `<template>` 要素以外も含まれています。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` には、正しく順序付けられた `<dt>` および `<dd>` グループ、`<script>` または `<template>` 要素のみが含まれています。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "スクリーン リーダーで正しく読み上げられるようにするには、定義リストの項目(`<dt>` と `<dd>`)を親の `<dl>` 要素でラップする必要があります。[詳細](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "定義リストの項目が `<dl>` 要素でラップされていません"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "定義リストの項目は `<dl>` 要素でラップされています"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "タイトルを指定すると、スクリーン リーダーのユーザーがページの概要を把握できるようになります。検索エンジンの使用時には、検索語句に関連するページかどうかを判断するための重要な要素となります。[詳細](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "ドキュメントに `<title>` 要素が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "ドキュメントに `<title>` 要素が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "他のインスタンスが支援技術によって見落とされることのないように、id 属性の値は一意にする必要があります。[詳細](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "ページの `[id]` 属性が一意ではありません"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "ページの `[id]` 属性は一意です"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "スクリーン リーダーでは、フレームのコンテンツを説明するためにフレームのタイトルが使用されます。[詳細](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` または `<iframe>` の要素にタイトルが指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` または `<iframe>` の要素にタイトルが指定されています"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "ページで lang 属性が指定されていない場合、スクリーン リーダーは、スクリーン リーダーの設定時にユーザーが選択したデフォルト言語がページで使用されているものと見なします。そのページでデフォルト言語が実際には使用されていない場合、スクリーン リーダーはページのテキストを正しく読み上げられない可能性があります。[詳細](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` 要素に `[lang]` 属性が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` 要素に `[lang]` 属性が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "有効な [BCP 47 言語](https://www.w3.org/International/questions/qa-choosing-language-tags#question)を指定すると、スクリーン リーダーでテキストが正しく読み上げられるようになります。[詳細](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` 要素の `[lang]` 属性に有効な値が指定されていません。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` 要素の `[lang]` 属性に有効な値が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "説明的要素は、簡潔でわかりやすい代替テキストにする必要があります。装飾的要素は、alt 属性が空の場合は無視される可能性があります。[詳細](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "画像要素に `[alt]` 属性が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "画像要素に `[alt]` 属性が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "画像を `<input>` ボタンとして使用している場合は、代替テキストを指定すると、スクリーン リーダーのユーザーがボタンの用途を理解しやすくなります。[詳細](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` 要素に `[alt]` テキストが指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` 要素に `[alt]` テキストが指定されています"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "ラベルを使用すると、フォームの各コントロールが支援技術(スクリーン リーダーなど)によって正しく読み上げられるようになります。[詳細](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "フォームの要素にラベルが関連付けられていません"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "フォームの要素にラベルが関連付けられています"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "レイアウト目的で表を使用している場合は、th 要素、caption 要素、summary 属性などのデータ要素を含めないでください。スクリーン リーダーを操作しにくくなる可能性があります。[詳細](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "レイアウト用の `<table>` 要素で、`<th>`、`<caption>`、または `[summary]` 属性が使用されています。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "レイアウト用の `<table>` 要素で、`<th>`、`<caption>`、または `[summary]` 属性は使用されていません。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "識別可能、フォーカス可能な一意のリンクテキスト(および画像をリンクとして使用している場合はその代替テキスト)を使用すると、スクリーン リーダーでのナビゲーションの操作性が向上します。[詳細](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "リンクに識別可能な名前が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "リンクに識別可能な名前が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "スクリーン リーダーでは、特殊な方法でリストが読み上げられます。適切に読み上げられるようにするには、正しいリスト構造を指定する必要があります。[詳細](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "リストには、`<li>` 要素と、スクリプト対応要素(`<script>` と `<template>`)以外も含まれています。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "リストには、`<li>` 要素と、スクリプト対応要素(`<script>` と `<template>`)のみが含まれています。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "スクリーン リーダーで正しく読み上げられるようにするには、リスト項目(`<li>`)を親の `<ul>` または `<ol>` に含める必要があります。[詳細](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "リスト項目(`<li>`)が `<ul>` または `<ol>` の親要素に含まれていません。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "リスト項目(`<li>`)は `<ul>` または `<ol>` の親要素に含まれています"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "ユーザーはページが自動的に更新されると思っていないため、自動更新によってフォーカスがページ上部に戻ると、ユーザーの利便性が低下する可能性があります。[詳細](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "ドキュメントで `<meta http-equiv=\"refresh\">` が使用されています"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "ドキュメントで `<meta http-equiv=\"refresh\">` が使用されていません"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "ズーム機能を無効にすると、画面の拡大操作を利用する視力の弱いユーザーがウェブページのコンテンツを確認できなくなります。[詳細](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` が `<meta name=\"viewport\">` 要素で使用されているか、`[maximum-scale]` 属性が 5 未満に指定されています。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` は `<meta name=\"viewport\">` 要素で使用されておらず、`[maximum-scale]` 属性も 5 未満ではありません。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "スクリーン リーダーは、テキスト以外のコンテンツを解釈できません。`<object>` 要素に代替テキストを追加すると、スクリーン リーダーを使用するユーザーが意味を把握するのに役立ちます。[詳細](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` 要素に `[alt]` テキストが指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` 要素に `[alt]` テキストが指定されています"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "値が 0 より大きい場合は、明示的なナビゲーション順序を示します。技術的には有効ですが、多くの場合、支援技術を使用しているユーザーにとって利便性が低下します。[詳細](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "一部の要素で `[tabindex]` に 0 より大きい値が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "`[tabindex]` に 0 より大きい値を指定している要素はありません"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "スクリーン リーダーには、表内の移動を補助する機能があります。`[headers]` 属性を使用している `<td>` セルが同じ表の他のセルのみを参照するように設定すると、スクリーン リーダーの利便性が向上する可能性があります。[詳細](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to an element `id` not found within the same table."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "スクリーン リーダーには、表内の移動を補助する機能があります。表のヘッダーが常に一部のセルを参照するように設定すると、スクリーン リーダーの利便性が向上する可能性があります。[詳細](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` 要素および `[role=\"columnheader\"/\"rowheader\"]` が指定された要素に、記述されたデータセルがありません。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` 要素および `[role=\"columnheader\"/\"rowheader\"]` が指定された要素に、記述されたデータセルがあります。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "要素に有効な [BCP 47 言語](https://www.w3.org/International/questions/qa-choosing-language-tags#question)を指定すると、スクリーン リーダーでテキストが正しく読み上げられるようになります。[詳細](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` 属性に有効な値が指定されていません"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` 属性に有効な値が指定されています"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "動画に字幕を設定すると、聴覚障がいのあるユーザーが情報にアクセスしやすくなります。[詳細](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` 要素に、`[kind=\"captions\"]` が指定された `<track>` 要素が含まれていません。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` 要素に `[kind=\"captions\"]` が指定された `<track>` 要素が含まれています"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "音声による説明を使用すると、顔の表情や場面といった、会話で伝えることのできない動画の関連情報を提供できます。[詳細](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` 要素に、`[kind=\"description\"]` が指定された `<track>` 要素が含まれていません。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` 要素に `[kind=\"description\"]` が指定された `<track>` 要素が含まれています"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "ユーザーがプログレッシブ ウェブアプリを iOS のホーム画面に追加したとき、アプリが希望どおりのデザインで表示されるようにするには、`apple-touch-icon` を定義します。参照先は不透明な 192 ピクセル(または 180 ピクセル)の正方形の PNG 画像とする必要があります。[詳細](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "有効な `apple-touch-icon` が提供されていません"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` は古いバージョンです。`apple-touch-icon` を使用することをおすすめします。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "有効な `apple-touch-icon` が提供されています"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome 拡張機能がこのページの読み込みに悪影響を及ぼしています。シークレット モードで、または拡張機能なしの Chrome プロファイルからページを監査してみてください。"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "スクリプトの評価"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "スクリプトの解析"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "合計 CPU 時間"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JavaScript の解析、コンパイル、実行にかかる時間の短縮をご検討ください。配信する JavaScript ペイロードのサイズを抑えると効果が見込めます。[詳細](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript の実行にかかる時間の低減"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript の実行にかかる時間"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "サイズの大きい GIF は、アニメーション コンテンツの配信方法として効率的ではありません。ネットワークの通信量を抑えるため、GIF を使用する代わりに、アニメーションには MPEG4/WebM 動画、静止画像には PNG/WebP を使用することをご検討ください。[詳細](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "アニメーション コンテンツでの動画フォーマットの使用"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "オフスクリーンの非表示の画像は、重要なリソースをすべて読み込んだ後に遅れて読み込むようにして、操作可能になるまでの時間を短縮することをご検討ください。[詳細](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "オフスクリーン画像の遅延読み込み"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "ページの First Paint をリソースがブロックしています。重要な JavaScript や CSS はインラインで配信し、それ以外の JavaScript やスタイルはすべて遅らせることをご検討ください。[詳細](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "レンダリングを妨げるリソースの除外"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "ネットワーク ペイロードのサイズが大きいと、ユーザーの金銭的負担が大きくなり、多くの場合、読み込み時間が長くなります。[詳細](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "合計サイズは {totalBytes, number, bytes} KB でした"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "過大なネットワーク ペイロードの回避"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "過大なネットワーク ペイロードの回避"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS ファイルを最小化すると、ネットワーク ペイロードのサイズを抑えることができます。[詳細](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSS の最小化"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript ファイルを最小化すると、ペイロード サイズとスクリプトの解析時間を抑えることができます。[詳細](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScript の最小化"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "スタイルシートから古いルールを削除し、スクロールせずに見える範囲のコンテンツに使用されていない CSS の読み込みを遅延させると、データ通信量を減らすことができます。[詳細](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "使用していない CSS を削除してください"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "使用していない JavaScript を削除して、データ通信量を減らしてください。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "使用していない JavaScript の削除"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "キャッシュの有効期間を長くすると、再訪問したユーザーへのページの読み込み速度を向上できます。[詳細](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件のリソースが見つかりました}other{# 件のリソースが見つかりました}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "静的なアセットと効率的なキャッシュ ポリシーの配信"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "静的なアセットでの効率的なキャッシュ ポリシーの使用"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "画像を最適化すると、読み込み時間を短縮しモバイルデータ量を抑えることができます。[詳細](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "効率的な画像フォーマット"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "適切なサイズの画像を配信して、モバイルデータ量を節約し読み込み時間を短縮してください。[詳細](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "適切なサイズの画像"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "テキストベースのリソースは圧縮(gzip、deflate、または brotli)して配信し、ネットワークの全体的な通信量を最小限に抑えてください。[詳細](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "テキスト圧縮の有効化"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000、JPEG XR、WebP などの画像フォーマットは、PNG や JPEG より圧縮性能が高く、ダウンロード時間やデータ使用量を抑えることができます。[詳細](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "次世代フォーマットでの画像の配信"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "アプリのコンテンツの幅がビューポートの幅と一致しない場合、アプリがモバイル画面に合わせて最適化されない可能性があります。[詳細](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "ビューポートのサイズ({innerWidth} ピクセル)がウィンドウのサイズ({outerWidth} ピクセル)と一致していません。"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "コンテンツのサイズとビューポートのサイズが一致していません"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "コンテンツのサイズとビューポートのサイズが一致しています"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "下のクリティカル リクエスト チェーンでは、高い優先度で読み込まれたリソースを確認できます。チェーンの長さを縮小する、リソースのダウンロード サイズを抑える、不要なリソースのダウンロードを遅らせるなどの手段を行って、ページの読み込み速度を改善することをご検討ください。[詳細](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件のチェーンが見つかりました}other{# 件のチェーンが見つかりました}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "クリティカルなリクエストの深さの最小化"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "非推奨 / 警告"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "行"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "サポートの終了した API は最終的にブラウザから削除されます。[詳細](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件の警告が見つかりました}other{# 件の警告が見つかりました}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "サポートを終了した API が使用されています"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "サポートを終了した API は使用されていません"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "アプリケーション キャッシュはサポートを終了しました。[詳細](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "「{AppCacheManifest}」が見つかりました"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "アプリケーション キャッシュを使用しています"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "アプリケーション キャッシュは使用していません"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "doctype を指定すると、ブラウザは後方互換モードに切り替えることができなくなります。[詳細](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "doctype 名には `html` を小文字の文字列で指定する必要があります"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "ドキュメントには doctype を指定する必要があります"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId は空の文字列であることが想定されています"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId は空の文字列であることが想定されています"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "ページに HTML doctype が指定されていないため、後方互換モードに切り替わります"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "ページに HTML doctype が指定されています"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "要素"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "統計情報"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "値"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "ブラウザ エンジニアは、ページに含まれる DOM の要素数が 1,500 個を超えないようにすることを推奨しています。ツリーの深さは 32 要素まで、子や親の要素数は 60 個までにするのが最適です。DOM サイズが大きいと、メモリの使用量が増え、[スタイルの計算](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)に時間がかかり、[レイアウトのリフロー](https://developers.google.com/speed/articles/reflow)というコストが発生する可能性があります。[詳細](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件の要素}other{# 件の要素}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "過大な DOM サイズの回避"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "DOM の最大深さ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "合計 DOM 要素数"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "子要素の上限数"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "過大な DOM サイズの回避"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "リンク先"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "パフォーマンスを向上し、セキュリティの脆弱性が生じないようにするには、`rel=\"noopener\"` または `rel=\"noreferrer\"` を外部リンクに追加します。[詳細](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "クロスオリジンへのリンクは安全ではありません"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "クロスオリジンへのリンクは安全です"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "アンカー({anchorHTML})のリンク先を特定できません。ハイパーリンクとして使用していない場合は、target=_blank を削除することをご検討ください。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "サイトから脈絡なしに位置情報の許可を求められると、ユーザーは不信感を抱き、困惑します。リクエストはユーザーの操作と関連付けて行うようにしてください。[詳細](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "ページの読み込み時に位置情報の許可がリクエストされます"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "ページの読み込み時に位置情報の許可はリクエストされません"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "バージョン"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "ページで検出されたすべてのフロントエンドの JavaScript ライブラリです。[詳細](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript ライブラリが検出されました"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "接続速度が遅い環境のユーザーの場合、`document.write()` で動的に挿入される外部スクリプトによってページの読み込みが数十秒遅れる可能性があります。[詳細](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()` が使用されています"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()` は使用されていません"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "最も高い重大度"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "ライブラリのバージョン"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "脆弱性の件数"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "一部の第三者スクリプトには、悪意のあるユーザーによって簡単に特定され利用されるような、既知のセキュリティの脆弱性が含まれていることがあります。[詳細](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件の脆弱性が検出されました}other{# 件の脆弱性が検出されました}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "既知のセキュリティの脆弱性を含んだフロントエンドの JavaScript ライブラリが含まれています"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "高"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "低"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "中"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "既知のセキュリティの脆弱性を含んだフロントエンドの JavaScript ライブラリは除外されています"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "サイトから脈絡なしに通知の送信許可を求められると、ユーザーは不信感を抱き、困惑します。リクエストはユーザーの操作と関連付けて行うようにしてください。[詳細](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "ページの読み込み時に通知の許可がリクエストされます"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "ページの読み込み時に通知の許可はリクエストされません"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "問題のある要素"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "パスワードの貼り付けを禁止すると、良好なセキュリティ ポリシーが損なわれます。[詳細](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "ユーザーはパスワード欄に貼り付けできません"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "ユーザーはパスワード欄に貼り付けできます"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "プロトコル"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 には、バイナリ ヘッダー、多重化、サーバー プッシュなど、HTTP/1.1 と比べて多くのメリットがあります。[詳細](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{HTTP/2 経由で配信されなかったリクエストが 1 件あります}other{HTTP/2 経由で配信されなかったリクエストが # 件あります}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "ページリソースの一部で HTTP/2 が使用されていません"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "ページ独自のリソースで HTTP/2 が使用されています"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "ページのスクロール パフォーマンスを高めるには、touch および wheel イベント リスナーを `passive` として指定することをご検討ください。[詳細](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "スクロール パフォーマンスを高める受動的なリスナーが使用されていません"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "スクロール パフォーマンスを高める受動的なリスナーが使用されています"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "説明"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "コンソールに記録されたエラーは未解決の問題を表します。これらはネットワーク リクエストの失敗や他のブラウザの問題が原因で表示される可能性があります。[詳細](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "ブラウザのエラーがコンソールに記録されました"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "コンソールに記録されたブラウザのエラーはありません"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "フォント表示の CSS 機能を使用して、Web フォントの読み込み中にユーザーがテキストを読めるようにしてください。[詳細](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "ウェブフォント読み込み中のテキストの表示"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "ウェブフォント読み込み中の全テキストの表示"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "次の URL の font-display の値を Lighthouse で確認できませんでした: {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "アスペクト比(実際)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "アスペクト比(表示)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "画像は本来のアスペクト比で表示する必要があります。[詳細](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "不適切なアスペクト比の画像が表示されています"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "正しいアスペクト比の画像が表示されています"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "画像サイズに関する情報({url})が正しくありません"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "ブラウザではホーム画面へのアプリの追加を促すメッセージを事前にユーザーに表示できます。これによりエンゲージメントが向上します。[詳細](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "ウェブアプリのマニフェストはインストール可能となる要件を満たしていません"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "ウェブアプリのマニフェストはインストール可能となる要件を満たしています"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "安全でない URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "すべてのサイトは、機密性の高い情報を扱っていない場合でも、HTTPS で保護する必要があります。HTTPS は、侵入者があなたのアプリとユーザー間の通信を改ざんしたり、傍受したりするのを防ぎます。HTTPS は、HTTP/2 や多くの新しいウェブ プラットフォーム API を使用するための前提条件となります。[詳細](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{安全でないリクエストが 1 件見つかりました}other{安全でないリクエストが # 件見つかりました}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "HTTPS が使用されていません"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPS を使用しています"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "モバイル ネットワークでのページ読み込みを速くすることで、優れたモバイル ユーザー エクスペリエンスが実現されます。[詳細](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "操作可能になるまでの時間: {timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "モバイル ネットワークのシミュレーションで操作可能になるまでの時間: {timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "ページの読み込みが遅すぎます。応答に 10 秒以上かかっています。改善方法については、[パフォーマンス] に表示される最適化案と診断結果をご確認ください。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "ページ読み込みはモバイル ネットワークで十分な速度で実行されません"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "ページ読み込みはモバイル ネットワークで十分な速度で実行されます"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "カテゴリ"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. [Learn more](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "メインスレッド処理の最小化"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "メインスレッド処理の最小化"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "ユーザー数を最大限に増やすには、サイトがすべての主要ブラウザで機能するようにします。[詳細](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "サイトがクロスブラウザに対応している"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "ソーシャル メディアで共有できるように、個々のページが URL によるディープリンクに対応していることと、それらの URL が固有であることを確認してください。[詳細](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "ページごとに 1 つの URL を使用している"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Transitions should feel snappy as you tap around, even on a slow network. This experience is key to a user's perception of performance. [Learn more](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "ページの切り替え時、ネットワークが遅いという印象を与えない"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "入力の推定待ち時間とは、ページ読み込みの最もビジーな 5 秒間における、ユーザーの入力に対するアプリの推定応答時間(ミリ秒単位)です。待ち時間が 50 ミリ秒より長い場合、ユーザーはアプリの反応が悪いと感じる可能性があります。[詳細](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "入力の推定待ち時間"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First Contentful Paint は、テキストまたは画像が初めてペイントされるまでにかかった時間です。[詳細](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "First Contentful Paint"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "First CPU Idle marks the first time at which the page's main thread is quiet enough to handle input. [Learn more](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU の初回アイドル"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "First Meaningful Paint は、ページの主要なコンテンツが可視化されるまでにかかった時間です。[詳細](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "First Meaningful Paint"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "操作可能になるまでの時間とは、ページが完全に操作可能になるのに要する時間です。[詳細](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "インタラクティブになるまでの時間"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "ユーザーに発生する可能性がある初回入力遅延の最大推定時間とは、最も長いタスクの時間(ミリ秒単位)です。[詳細](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "初回入力遅延の最大推定時間"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "速度インデックスは、ページのコンテンツが取り込まれて表示される速さを表します。[詳細](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "速度インデックス"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "タスクの時間が 50 ミリ秒を上回った場合の、コンテンツの初回ペイントから操作可能になるまでのすべての時間の合計を、ミリ秒単位で表します。"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "合計ブロック時間"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "ネットワークのラウンドトリップ時間(RTT)はパフォーマンスに大きく影響します。発信元への RTT が高い場合は、サーバーの場所をユーザーの近くにするとパフォーマンスを改善できることを示しています。[詳細](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "ネットワークのラウンドトリップ時間"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "サーバーの待ち時間はウェブ パフォーマンスに影響することがあります。発信元のサーバーのレイテンシが高い場合は、サーバーが過負荷であるか、サーバーのバックエンド パフォーマンスが低いことを示しています。[詳細](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "サーバーのバックエンド待ち時間"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker によって、ネットワークが予期しない状態になったときでもウェブアプリの安定した動作が可能になります。[詳細](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` は、オフライン時にステータス 200 の応答を返しません"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` は、オフライン時にステータス 200 の応答を返します"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse でマニフェストから `start_url` を読み取れませんでした。その結果、`start_url` はドキュメントの URL と認識されています。エラー メッセージ: 「{manifestWarning}」。"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "予算超過"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "ネットワーク リクエストの数とサイズが、指定したパフォーマンス予算の設定目標内に収まるよう維持します。[詳細](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 件のリクエスト}other{# 件のリクエスト}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "パフォーマンス予算"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "HTTPS を設定済みの場合は、すべてのユーザーに安全なウェブ機能を提供できるように、すべての HTTP トラフィックが HTTPS にリダイレクトされることを確認してください。[詳細](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP トラフィックは HTTPS にリダイレクトされません"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP トラフィックは HTTPS にリダイレクトされます"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "リダイレクトを行うと、ページの読み込みにさらに時間がかかる可能性があります。[詳細](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "複数のページ リダイレクトの回避"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "ページリソースの数とサイズの予算を設定するには、budget.json ファイルを追加します。[詳細](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 件のリクエスト • {byteCount, number, bytes} KB}other{# 件のリクエスト • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "リクエスト数を少なく、転送サイズを小さく維持してください"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "正規リンクで、検索結果に表示する URL を指定します。[詳細](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "複数の URL が競合しています({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "別のドメイン({url})を指しています"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL({url})が無効です"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "別の `hreflang` 位置({url})を指しています"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "相対 URL({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "コンテンツの同等のページではなく、ドメインのルート URL(ホームページ)を参照しています。"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "ドキュメントに有効な `rel=canonical` が指定されていません"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "ドキュメントに有効な `rel=canonical` が指定されています"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12 px より小さいフォントサイズは小さすぎて判読できず、モバイル ユーザーには「ピンチしてズーム」の操作が必要になります。60% を超えるページ テキストでフォント サイズが 12 px 以上になるようにしてください。[詳細](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "判読可能なテキスト: {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "テキストが判読できません。モバイル スクリーン向けに最適化されたビューポート メタタグがありません。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} のテキストが小さすぎます({decimalProportionVisited, number, extendedPercent} のサンプルを基準とします)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "ドキュメントで判読可能なフォントサイズが使用されていません"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "ドキュメントで判読可能なフォントサイズが使用されています"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang リンクを利用して、所定の言語や地域の検索結果に掲載する必要があるページのバージョンを検索エンジンに伝えます。[詳細](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "ドキュメントに有効な `hreflang` が指定されていません"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "ドキュメントに有効な `hreflang` が指定されています"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "HTTP ステータス コードが正しくないページはインデックスに適切に登録されていない可能性があります。[詳細](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "ページに設定されている HTTP ステータス コードが正しくありません"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "ページに適切な HTTP ステータス コードが指定されています"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "ページのクロールを許可しない場合、検索エンジンはそのページを検索結果に追加できません。[詳細](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "ページのインデックス登録を行えません"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "ページのインデックス登録はブロックされていません"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "リンクテキストをわかりやすくすると、検索エンジンがコンテンツを認識しやすくなります。[詳細](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件のリンクが見つかりました}other{# 件のリンクが見つかりました}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "リンクにわかりやすいテキストが設定されていません"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "リンクにわかりやすいテキストが設定されています"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "[構造化データ テストツール](https://search.google.com/structured-data/testing-tool/)と[構造化データ用 Linter](http://linter.structured-data.org/) を実行して構造化データを検証してください。[詳細](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "構造化データが無効です"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "メタ ディスクリプションを検索結果に追加すると、ページ コンテンツの内容を簡潔にまとめることができます。[詳細](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "説明のテキストが空です。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "ドキュメントにメタ ディスクリプションが指定されていません"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "ドキュメントにメタ ディスクリプションが指定されています"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "検索エンジンはプラグイン コンテンツをインデックスに登録できません。多くのデバイスで、プラグインが制限され、プラグインがサポートされていないこともあります。[詳細](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "ドキュメントでプラグインを使用しています"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "ドキュメントではプラグインを使用できません"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "robots.txt ファイルの形式が間違っていると、ウェブサイトのクロールやインデックス登録について指定した設定をクローラが認識できない可能性があります。[詳細](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt のリクエストで返された HTTP ステータス: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 件のエラーが見つかりました}other{# 件のエラーが見つかりました}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse は robots.txt ファイルをダウンロードできませんでした"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt が無効です"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt は有効です"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "ボタンやリンクなどの操作可能な要素は十分な大きさ(48x48 px)に設定し、他の要素と重ならずに簡単にタップできるよう、要素の周囲にスペースを取る必要があります。[詳細](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} でタップ ターゲットが適切なサイズに設定されています"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "タップ ターゲットが小さすぎます。モバイル スクリーン向けに最適化されたビューポート メタタグがありません。"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "タップ ターゲットのサイズが適切に設定されていません"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "重複するターゲット"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "タップ ターゲット"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "タップ ターゲットのサイズは適切に設定されています"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker は、多くのプログレッシブ ウェブアプリ機能(オフライン、ホーム画面への追加、プッシュ通知など)をアプリで使用できるようにするための技術です。[詳細](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "このページは Service Worker によって制御されていますが、マニフェストが有効な JSON としてパースされなかったため、`start_url` は見つかりませんでした"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "このページは Service Worker によって制御されていますが、`start_url`({startUrl})が Service Worker のスコープ({scopeUrl})内にありません"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "このページは Service Worker によって制御されていますが、マニフェストが取得されなかったため、`start_url` は見つかりませんでした。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "この発信元には Service Worker が存在しますが、ページ({pageUrl})がスコープ内にありません。"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "ページと `start_url` を制御する Service Worker が登録されていません"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "ページと `start_url` を制御する Service Worker が登録されています"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "テーマのあるスプラッシュ画面を設定すると、ホーム画面からのアプリの起動時に、質の良いアプリであることをユーザーにアピールできます。[詳細](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "カスタムのスプラッシュ画面が設定されていません"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "カスタムのスプラッシュ画面が設定されています"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "ブラウザのアドレスバーにサイトに合わせたテーマを設定できます。[詳細](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "アドレスバーにテーマの色が設定されていません。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "アドレスバーにテーマの色が設定されています。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "メインスレッドのブロック時間"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "第三者"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "第三者コードによって、読み込み速度が著しく低下する可能性があります。重複する第三者プロバイダの数を制限したうえで、ページのメインの部分を読み込み終えた後に第三者コードを読み込んでみてください。[詳細](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "第三者コードによってメインスレッドが {timeInMs, number, milliseconds} ミリ秒間ブロックされました"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "第三者コードの影響を抑えてください"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "第三者コードの利用"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "最初の 1 バイトまでの時間は、サーバーが応答を返すまでにかかった時間を表しています。[詳細](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "ルート ドキュメントの読み込みに {timeInMs, number, milliseconds} ミリ秒かかりました"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "サーバー応答時間の短縮(TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "サーバーの応答時間が遅い(TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "継続時間"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "開始時間"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "タイプ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "User Timing API を使用してアプリをインストルメント化し、主要なユーザー エクスペリエンスでのアプリの実際のパフォーマンスを測定できるようにしてください。[詳細](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 件のカスタム速度}other{# 件のカスタム速度}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "カスタム速度の記録と計測"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "「{securityOrigin}」で事前接続の <link> が見つかりましたが、ブラウザで使用されませんでした。`crossorigin` 属性を適切に使用していることをご確認ください。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "重要な第三者ドメインへの接続を早期に確立できるように、`preconnect` または `dns-prefetch` のリソースヒントを追加することを検討してください。[詳細](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "必須のドメインへの事前接続"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "「{preloadURL}」のプリロード <link> が見つかりましたが、ブラウザで使用されませんでした。`crossorigin` 属性を適切に使用していることをご確認ください。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "`<link rel=preload>` を使用して、現在ページ読み込みの後のほうでリクエストしているリソースを優先的に取得することをご検討ください。[詳細](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "キー リクエストのプリロード"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "モバイル画面用にアプリを最適化するには、`<meta name=\"viewport\">` タグを追加してください。[詳細](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "`<meta name=\"viewport\">` タグが見つかりません"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "`width` または `initial-scale` を指定した `<meta name=\"viewport\">` タグがありません"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "`width` または `initial-scale` を指定した `<meta name=\"viewport\">` タグがあります"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "JavaScript が無効になっている場合でも、アプリではなんらかのコンテンツを表示する必要があります。「アプリの使用には JavaScript が必要」という旨の警告を表示するだけでもかまいません。[詳細](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "スクリプトを利用できない場合でも、ページの本文にはなんらかのコンテンツを表示する必要があります。"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "JavaScript を利用できない場合の代替コンテンツが提供されていません"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "JavaScript を利用できない場合のコンテンツが含まれています"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "プログレッシブ ウェブアプリを作成している場合は、アプリがオフラインでも動作するように、Service Worker の使用を検討してください。[詳細](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "現在のページは、オフライン時にステータス 200 の応答を返しません"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "現在のページは、オフライン時にステータス 200 の応答を返します"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "テスト URL({requested})が「{final}」にリダイレクトされているため、このページはオフラインで読み込まれない可能性があります。2 番目の URL を直接テストしてみてください。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "ここには、アプリでの ARIA の使用方法に関する改善点が表示されます。修正すると、支援技術(スクリーン リーダーなど)の利便性が向上する可能性があります。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "ここで、音声と動画の代替コンテンツを提供できます。代替コンテンツを提供すると、聴覚や視覚に障がいがあるユーザーの利便性が向上する可能性があります。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "音声と動画"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "ここで、一般的なユーザー補助機能のおすすめの方法を確認できます。"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "おすすめの方法"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "これらのチェックにより、[ウェブアプリのユーザー補助機能の改善点](https://developers.google.com/web/fundamentals/accessibility)が明確になります。自動的に検出できるユーザー補助の問題は一部に過ぎないため、手動テストも実施することをおすすめします。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "ここに、自動テストツールではカバーできない範囲に対処する項目が表示されます。詳しくは、[ユーザー補助機能の審査を実施する](https://developers.google.com/web/fundamentals/accessibility/how-to-review)方法についてのガイドをご覧ください。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "ユーザー補助"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "ここには、コンテンツの読みやすさに関する改善点が表示されます。"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "コントラスト"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "ここには、地域ユーザー別のコンテンツの解釈に関する改善点が表示されます。"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "多言語対応とローカライズ"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "ここには、アプリ内のコントロールのセマンティクスに関する改善点が表示されます。修正すると、支援技術(スクリーン リーダーなど)の利便性が向上する可能性があります。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "名前とラベル"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "ここには、アプリのキーボード操作性に関する改善点が表示されます。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "操作性"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "ここには、支援技術(スクリーン リーダーなど)を使用した表やリストのデータの読み取りの利便性に関する改善点が表示されます。"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "表とリスト"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "おすすめの方法"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "パフォーマンス予算は、サイトのパフォーマンスに関する基準を設定します。"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "予算(リソースの上限)"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "アプリケーションのパフォーマンスに関する詳細。これらの数値は、パフォーマンス スコアには[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)しません。"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "診断"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "パフォーマンスの最も重要な点は、ピクセルをどのくらい速く画面にレンダリングできるかです。主要な指標: First Contentful Paint、First Meaningful Paint"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "First Paint の改善点"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "これらの提案を実施すると、ページの読み込み時間を短縮できる可能性があります。なお、パフォーマンス スコアには[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)しません。"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "改善できる項目"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "指標"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "読み込みの全体的なパフォーマンスを改善して、ページの反応性や操作性を高めましょう。主要な指標: インタラクティブになるまでの時間、速度インデックス"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "全体的な改善点"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "パフォーマンス"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "これらのチェックではプログレッシブ ウェブアプリのさまざまな側面が検証されます。[詳細](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "これらのチェック項目は基本の [PWA チェックリスト](https://developers.google.com/web/progressive-web-apps/checklist)で必須とされていますが、Lighthouse では自動的にチェックされません。スコアには影響しませんが、手動で確認することが重要です。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "プログレッシブ ウェブアプリ"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "スピードと高い信頼性"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "インストール対応"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA の最適化"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "これらのチェックを実行することで、ページが検索エンジンの検索結果ランキングに対し最適化されていることを確認できます。Lighthouse ではチェックされない、検索結果ランキングに影響する可能性がある他の要因もあります。[詳細](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "サイトでこれらの他の検証ツールを実行し、SEO のその他のおすすめの方法をご確認ください。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "クローラがアプリのコンテンツを正確に読み取れるように HTML を適切な形式で記述します。"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "コンテンツ制作のおすすめの方法"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "検索結果に表示するには、クローラがアプリにアクセスできるようにする必要があります。"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "クロールとインデックス登録"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "ページをスマホ対応にして、ピンチ操作や拡大操作なしでコンテンツを読めるようにします。[詳細](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "スマホ対応"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "キャッシュの TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "場所"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "名前"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "リクエスト"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "リソースの種類"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "サイズ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "かかった時間"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "転送サイズ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "減らせるデータ量"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "短縮できる時間"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "{wastedBytes, number, bytes} KB 減らせます"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "{wastedMs, number, milliseconds} ミリ秒短縮できます"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "ドキュメント"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "フォント"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "画像"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "メディア"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ミリ秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "その他"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "スクリプト"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "スタイルシート"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "第三者"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "合計"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "ページを読み込む際のトレースの記録中にエラーが発生しました。もう一度 Lighthouse を実行してください。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Debugger プロトコル接続の開始中にタイムアウトが発生しました。"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome でページの読み込み中にスクリーンショットが収集されませんでした。ページにコンテンツが表示されていることを確認してから、Lighthouse を再実行してください。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS サーバーは指定したドメインを解決できませんでした。"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "必須の {artifactName} の収集でエラー({errorMessage})が発生しました"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Chrome 内部エラーが発生しました。Chrome を再起動して Lighthouse を再実行してください。"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "必須の {artifactName} の収集は行われませんでした。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "リクエストしたページを Lighthouse で正確に読み込めませんでした。正しい URL でテストを行い、すべてのリクエストに対してサーバーからの応答が適切であることを確認してください。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "ページからの応答が停止されたため、リクエストした URL を Lighthouse で正確に読み込めませんでした。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "指定した URL には有効なセキュリティ証明書がありません。{securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome によりページ読み込みが停止され、中間ページが表示されました。テスト対象の URL が正しいこと、サーバーがすべてのリクエストに適切に応答していることを確認してください。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "リクエストしたページを Lighthouse で正確に読み込めませんでした。テスト対象の URL が正しいこと、サーバーがすべてのリクエストに適切に応答していることを確認してください。(詳細: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "リクエストしたページを Lighthouse で正確に読み込めませんでした。テスト対象の URL が正しいこと、サーバーがすべてのリクエストに適切に応答していることを確認してください。(ステータス コード: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "ページの読み込み時間が長すぎます。ページの読み込み時間を短縮するには、レポートに示される提案を実施してください。その後で、Lighthouse を再実行してください。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools プロトコルからの応答の待ち時間が、割り当てられた時間を超えました。(メソッド: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "リソース コンテンツの取得時間が、割り当てられた時間を超えました"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "指定した URL は無効の可能性があります。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "監査を表示"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "最初の移動先"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "クリティカル パスの最大待ち時間:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "エラー"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "レポートエラー: 監査情報はありません"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "ラボデータ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "エミュレート済みモバイル ネットワークでの現在のページに関する [Lighthouse](https://developers.google.com/web/tools/lighthouse/) 分析です。推定値のため変動する可能性があります。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "個別の検証が必要な他の項目"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "該当なし"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "改善できる項目"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "短縮できる時間(推定)"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "合格した監査"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "スニペットを折りたたむ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "スニペットを展開"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "第三者リソースを表示"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Lighthouse の実行に影響する問題が発生しました。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "推定値のため変動する可能性があります。パフォーマンス スコアは、[こちらの指標のみを基準に算出](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)されます。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "監査には合格しましたが警告があります"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "警告: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "GIF を HTML5 動画として埋め込み可能なサービスにアップロードすることをご検討ください。"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "[WordPress の遅延読み込みプラグイン](https://wordpress.org/plugins/search/lazy+load/)をインストールすると、画面外の画像の読み込みを遅らせたり、遅延読み込み機能のあるテーマに切り替えたりできます。[AMP プラグイン](https://wordpress.org/plugins/amp/)の使用もご検討ください。"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[重要なアセットをインラインで読み込む](https://wordpress.org/plugins/search/critical+css/)または[重要度が低いリソースの読み込みを遅らせる](https://wordpress.org/plugins/search/defer+css+javascript/)ために役立つ、さまざまな WordPress プラグインがあります。ただし、これらのプラグインの最適化処理によって、テーマやプラグインの機能が阻害されることがあります。その場合は、コードを変更する必要があります。"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "テーマ、プラグイン、サーバー仕様はすべてサーバーの応答時間に影響します。より最適化されたテーマを探す、最適化プラグインを慎重に選ぶ、サーバーをアップグレードすることをおすすめします。"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "「詳しく読む」タグなどを使用して投稿リストに抜粋を表示する、ページに表示する投稿の数を減らす、長い投稿を複数のページに分けて表示する、またはコメントを遅延読み込みするプラグインを使用することをご検討ください。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "スタイルを結合、軽量化、圧縮してサイトの動作を速くする、さまざまな [WordPress プラグイン](https://wordpress.org/plugins/search/minify+css/)があります。可能な場合は、ビルド処理で事前に軽量化しておくこともおすすめします。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "スクリプトを結合、軽量化、圧縮してサイトの動作を速くする、さまざまな [WordPress プラグイン](https://wordpress.org/plugins/search/minify+javascript/)があります。可能な場合は、ビルド処理で事前に軽量化しておくこともおすすめします。"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "ページで使用されていない CSS を読み込む [WordPress プラグイン](https://wordpress.org/plugins/)の数を減らすか、他のプラグインに切り替えることをご検討ください。不要な CSS を読み込んでいるプラグインを特定するには、Chrome DevTools で[コードの Coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) を確認します。スタイルシートの URL から、それを使用しているテーマやプラグインを特定できます。多くのスタイルシートを使用しているプラグイン(コードの Coverage で赤色の部分が多いもの)をリストで探します。プラグインによってキューに追加されるスタイルシートは、実際にページで使用されるもののみにする必要があります。"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "ページで使用されていない JavaScript を読み込む [WordPress プラグイン](https://wordpress.org/plugins/)の数を減らすか、他のプラグインに切り替えることをご検討ください。不要な JavaScript を読み込んでいるプラグインを特定するには、Chrome DevTools で[コードの Coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) を確認します。スクリプトの URL から、該当のテーマやプラグインを特定できます。多くのスクリプトを使用しているプラグイン(コードの Coverage で赤色の部分が多いもの)をリストで探します。プラグインによってキューに追加されるスクリプトは、実際にページで使用されるもののみにする必要があります。"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPress のブラウザ キャッシング](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)についてご確認ください。"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "画質を落とさずに画像を圧縮できる [WordPress の画像最適化プラグイン](https://wordpress.org/plugins/search/optimize+images/)の使用をご検討ください。"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "[メディア ライブラリ](https://codex.wordpress.org/Media_Library_Screen)から直接画像をアップロードして必要な画像サイズを利用できるようにしたうえで、メディア ライブラリから挿入するか、画像ウィジェットを使用して、最適な画像サイズ(レスポンシブ ブレークポイントのサイズを含む)が使用されるようにします。「`Full Size`」の画像は、十分なスペースがある場合を除いて使用しないようにします。[詳細](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "ウェブサーバーの設定でテキスト圧縮を有効にできます。"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "アップロードした画像を最適なフォーマットに自動変換する[プラグイン](https://wordpress.org/plugins/search/convert+webp/)またはサービスの使用をご検討ください。"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ko.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ko.json
new file mode 100644
index 00000000000..5b271f207d7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ko.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "액세스 키를 사용하면 사용자가 페이지의 특정 부분에 신속하게 포커스를 맞출 수 있습니다. 정상적으로 탐색하려면 모든 액세스 키가 고유해야 합니다. [자세히 알아보기](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` 값이 고유하지 않음"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` 값이 고유합니다"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "각 ARIA `role`은(는) `aria-*` 속성으로 구성된 특정 하위 세트를 지원합니다. 이 두 가지가 일치하지 않으면 `aria-*` 속성이 유효하지 않게 됩니다. [자세히 알아보기](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` 속성이 역할과 일치하지 않음"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` 속성이 역할과 일치함"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "일부 ARIA 역할에는 스크린 리더에 관한 요소의 상태를 설명하는 속성이 필요합니다. [자세히 알아보기](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`에 필요한 `[aria-*]` 속성이 일부 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`에 필요한 모든 `[aria-*]` 속성이 있음"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "일부 ARIA 상위 역할에서 의도한 접근성 기능을 실행하려면 특정 하위 역할을 포함하고 있어야 합니다. [자세히 알아보기](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "하위 요소에 특정 `[role]`을(를) 포함해야 하는 ARIA `[role]` 지원 요소에 일부 또는 전체 하위 요소가 누락되었습니다."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "하위 요소에 특정 `[role]`을(를) 포함해야 하는 ARIA `[role]` 지원 요소에 필요한 모든 하위 요소가 있습니다."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "일부 ARIA 하위 역할에서 의도한 접근성 기능을 올바르게 실행하려면 특정 상위 역할에 포함되어 있어야 합니다. [자세히 알아보기](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`이(가) 필수 상위 요소에 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`이(가) 필수 상위 요소에 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA 역할에서 의도한 접근성 기능을 실행하려면 유효한 값을 포함하고 있어야 합니다. [자세히 알아보기](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` 값이 유효하지 않음"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` 값이 유효함"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "스크린 리더와 같은 보조 기술은 잘못된 값이 있는 ARIA 속성을 해석하지 못합니다. [자세히 알아보기](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` 속성에 유효한 값이 없음"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` 속성에 유효한 값이 있음"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "스크린 리더와 같은 보조 기술은 잘못된 이름이 있는 ARIA 속성을 해석하지 못합니다. [자세히 알아보기](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` 속성이 유효하지 않거나 맞춤법 오류가 있음"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` 속성이 유효하며 맞춤법 오류가 없음"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "자막이 있으면 청각장애인이나 청각에 문제가 있는 사용자도 오디오 요소를 사용할 수 있게 되며 말하고 있는 사람, 말하는 내용, 기타 비음성적 정보와 같은 중요 정보가 제공됩니다. [자세히 알아보기](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` 요소에서 `[kind=\"captions\"]` 지원 `<track>` 요소가 누락됨"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` 요소에 `[kind=\"captions\"]` 지원 `<track>` 요소가 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "통과하지 못한 요소"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "버튼에 접근 가능한 이름이 없는 경우 스크린 리더에서 '버튼'으로만 읽기 때문에 스크린 리더에 의존하는 사용자에게는 해당 버튼이 유용하지 않게 됩니다. [자세히 알아보기](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "버튼에 접근 가능한 이름이 없습니다"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "버튼에 접근 가능한 이름이 있습니다"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "반복적인 콘텐츠를 건너뛸 방법을 추가하면 키보드 사용자가 페이지를 더 효율적으로 탐색할 수 있습니다. [자세히 알아보기](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "페이지에 제목, 링크 건너뛰기, 랜드마크 영역이 포함되어 있지 않습니다"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "페이지에 제목, 링크 건너뛰기, 랜드마크 영역이 포함되어 있습니다"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "많은 사용자가 저대비 텍스트를 읽는 데 어려움을 겪거나 전혀 읽지 못합니다. [자세히 알아보기](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "백그라운드 및 포그라운드 색상의 대비율이 충분하지 않습니다"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "백그라운드 및 포그라운드 색상의 대비율이 충분합니다"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "정의 목록이 올바르게 표시되지 않으면 스크린 리더에서 혼란스럽거나 정확하지 않은 내용을 말할 수 있습니다. [자세히 알아보기](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`에 순서가 올바른 `<dt>` 및 `<dd>` 그룹, `<script>` 또는 `<template>` 요소만 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`에 순서가 올바른 `<dt>` 및 `<dd>` 그룹, `<script>` 또는 `<template>` 요소만 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "스크린 리더에서 정의 목록 항목(`<dt>` 및 `<dd>`)을 올바르게 읽으려면 정의 목록 항목이 상위 `<dl>` 요소에 래핑되어 있어야 합니다. [자세히 알아보기](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "정의 목록 항목이 `<dl>` 요소에서 래핑되어 있지 않음"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "정의 목록 항목이 `<dl>` 요소에서 래핑되어 있음"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "제목을 사용하면 스크린 리더 사용자에게는 페이지의 개요를 제공할 수 있습니다. 검색엔진 사용자는 제목으로 페이지가 자신의 검색어와 관련되어 있는지 여부를 판단합니다. [자세히 알아보기](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "문서에 `<title>` 요소가 없음"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "문서에 `<title>` 요소가 있음"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "보조 기술에서 다른 인스턴스를 놓치지 않도록 하려면 ID 속성값이 고유해야 합니다. [자세히 알아보기](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "페이지에 있는 `[id]` 속성이 고유하지 않음"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "페이지에 있는 `[id]` 속성이 고유함"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "스크린 리더 사용자는 프레임 콘텐츠를 설명해 주는 프레임 제목을 사용합니다. [자세히 알아보기](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` 또는 `<iframe>` 요소에 제목이 없음"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` 또는 `<iframe>` 요소에 제목이 있음"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "페이지에서 lang 속성을 지정하지 않는 경우 스크린 리더는 사용자가 스크린 리더를 설정할 때 선택한 기본 언어로 페이지가 작성되어 있다고 가정합니다. 페이지가 기본 언어로 작성되어 있지 않으면 스크린 리더에서 페이지에 있는 텍스트를 제대로 읽어줄 수 없습니다. [자세히 알아보기](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` 요소에 `[lang]` 속성이 없음"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` 요소에 `[lang]` 속성이 있음"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "유효한 [BCP 47 언어](https://www.w3.org/International/questions/qa-choosing-language-tags#question)를 지정하면 스크린 리더에서 텍스트를 올바르게 읽는 데 도움이 됩니다. [자세히 알아보기](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` 요소의 `[lang]` 속성에 유효한 값이 없음"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` 요소에 `[lang]` 속성의 유효한 값이 있음"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "정보 요소는 짧아야 하며 설명을 제공하는 대체 텍스트를 목표로 해야 합니다. 장식 요소는 Alt 속성이 비어 있는 경우 무시될 수 있습니다. [자세히 알아보기](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "이미지 요소에 `[alt]` 속성 없음"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "이미지 요소에 `[alt]` 속성이 있음"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "이미지가 `<input>` 버튼으로 사용되는 경우 대체 텍스트를 제공하면 스크린 리더 사용자가 버튼의 목적을 쉽게 이해하는 데 도움이 됩니다. [자세히 알아보기](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` 요소에 `[alt]` 텍스트가 없음"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` 요소에 `[alt]` 텍스트가 있음"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "라벨을 사용하면 스크린 리더와 같은 보조 기술에서 양식 컨트롤을 올바르게 읽을 수 있습니다. [자세히 알아보기](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "양식 요소에 관련 라벨이 포함되어 있지 않습니다"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "양식 요소에 관련 라벨이 포함되어 있습니다"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "스크린 리더 사용자에게 혼란스러운 환경이 생길 수 있으므로 레이아웃 용도로 사용되는 표에는 th 또는 caption 요소와 같은 데이터 요소나 summary 속성이 포함되지 않아야 합니다. [자세히 알아보기](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "프레젠테이션 `<table>` 요소에서 `<th>`, `<caption>` 또는 `[summary]` 속성의 사용이 지양되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "프레젠테이션 `<table>` 요소에서 `<th>`, `<caption>` 또는 `[summary]` 속성을 가급적 사용하지 않음"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "인식하기 쉽고, 고유하고, 초점을 맞추기 쉬운 링크 텍스트(및 이미지가 링크로 사용되는 경우 이미지의 대체 텍스트)를 사용하면 스크린 리더 사용자의 탐색 환경을 개선할 수 있습니다. [자세히 알아보기](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "링크에 인식 가능한 이름이 포함되어 있지 않습니다"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "링크에 인식 가능한 이름이 포함되어 있습니다"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "스크린 리더에는 목록을 읽는 특정 방식이 있습니다. 목록 구조를 적절히 작성하면 스크린 리더 출력에 도움이 됩니다. [자세히 알아보기](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "목록에 `<li>` 요소와 스크립트 지원 요소(`<script>` 및 `<template>`)만 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "목록에 `<li>` 요소와 요소 지원 스크립트(`<script>` 및 `<template>`)만 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "스크린 리더에서 목록 항목(`<li>`)을 올바르게 읽으려면 목록 항목이 상위 `<ul>` 또는 `<ol>`에 포함되어 있어야 합니다. [자세히 알아보기](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "목록 항목(`<li>`)이 `<ul>` 또는 `<ol>` 상위 요소 내에 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "목록 항목(`<li>`)이 `<ul>` 또는 `<ol>` 상위 요소 내에 포함되어 있음"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "사용자는 페이지가 자동으로 새로고침된다고 예상하지 못하기 때문에 페이지가 자동으로 새로고침되면 초점이 다시 페이지 상단에 맞춰집니다. 이로 인해 불쾌하거나 혼란스러운 상황이 발생할 수 있습니다. [자세히 알아보기](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "문서에서 `<meta http-equiv=\"refresh\">` 사용됨"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "문서에서 `<meta http-equiv=\"refresh\">`이(가) 사용되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "확대/축소를 사용 중지하면 저시력으로 인해 웹페이지의 콘텐츠를 제대로 확인하기 위해 화면 확대를 사용하는 사용자에게 문제가 될 수 있습니다. [자세히 알아보기](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]`이(가) `<meta name=\"viewport\">` 요소에서 사용되거나 `[maximum-scale]` 속성이 5보다 작음"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]`은(는) `<meta name=\"viewport\">` 요소에 사용되지 않으며 `[maximum-scale]` 속성이 5보다 작지 않음"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "스크린 리더는 텍스트가 아닌 콘텐츠를 번역할 수 없습니다. `<object>` 요소에 Alt 텍스트를 추가하면 스크린 리더에서 사용자에게 텍스트의 의미를 전달하는 데 도움이 됩니다. [자세히 알아보기](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` 요소에 `[alt]` 텍스트가 없음"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` 요소에 `[alt]` 텍스트가 있음"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "0보다 큰 값은 명시적인 탐색 순서를 나타냅니다. 기술적으로는 유효하나 보조 기술에 의존하는 사용자에게 불편한 환경이 생기는 경우가 많습니다. [자세히 알아보기](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "일부 요소의 `[tabindex]` 값이 0보다 큼"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "`[tabindex]` 값이 0보다 큰 요소가 없음"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "스크린 리더에는 표를 좀 더 쉽게 탐색하는 기능이 있습니다. `[headers]` 속성을 사용하는 `<td>` 셀이 동일한 테이블에 있는 다른 셀만 참조하게 하면 스크린 리더 사용자 환경을 개선할 수 있습니다. [자세히 알아보기](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`[headers]` 속성을 사용하는 `<table>` 요소의 셀은 동일한 테이블 내에 없는 요소 `id`만 참조합니다."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`[headers]` 속성을 사용하는 `<table>` 요소의 셀이 동일한 테이블 내의 테이블 셀을 참조합니다."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "스크린 리더에는 표를 좀 더 쉽게 탐색하는 기능이 있습니다. 표 헤더에서 항상 셀 세트 일부를 참조하게 하면 스크린 리더 사용자 환경이 개선될 수 있습니다. [자세히 알아보기](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` 요소와 `[role=\"columnheader\"/\"rowheader\"]` 지원 요소가 설명하는 데이터 셀이 해당 요소에 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` 요소와 `[role=\"columnheader\"/\"rowheader\"]` 지원 요소가 설명하는 데이터 셀이 해당 요소에 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "요소에 유효한 [BCP 47 언어](https://www.w3.org/International/questions/qa-choosing-language-tags#question)를 지정하면 스크린 리더에서 텍스트를 올바르게 읽는 데 도움이 됩니다. [자세히 알아보기](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` 속성에 유효한 값이 없음"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` 속성에 유효한 값이 있음"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "동영상에 자막이 제공되면 청각장애인이나 난청이 있는 사용자가 동영상의 정보에 더 쉽게 접근할 수 있습니다. [자세히 알아보기](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` 요소에 `[kind=\"captions\"]` 지원 `<track>` 요소가 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` 요소에 `[kind=\"captions\"]` 지원 `<track>` 요소가 포함됨"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "오디오 설명은 표정 및 장면과 같이 대화에서 제공할 수 없는 동영상에 관한 정보를 제공합니다. [자세히 알아보기](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` 요소에 `[kind=\"description\"]` 지원 `<track>` 요소가 포함되지 않음"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` 요소에 `[kind=\"description\"]` 지원 `<track>` 요소가 포함됨"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "프로그레시브 웹 앱을 홈 화면에 추가했을 때 iOS에서 제대로 표시되려면 `apple-touch-icon`을(를) 정의해야 합니다. 투명하지 않은 192px 또는 180px 정사각형 PNG로 설정되어야 합니다. [자세히 알아보기](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "유효한 `apple-touch-icon`이(가) 제공되지 않음"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed`이(가) 최신 버전이 아니므로 `apple-touch-icon`이(가) 적합합니다."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "유효한 `apple-touch-icon` 제공"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome 확장 프로그램이 이 페이지의 로드 성능에 부정적인 영향을 미쳤습니다. 시크릿 모드나 확장 프로그램이 없는 Chrome 프로필에서 페이지를 검사해 보세요."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "스크립트 평가"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "스크립트 파싱"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "총 CPU 시간"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JS 파싱, 컴파일, 실행에 소요되는 시간을 줄여 보세요. 용량이 적은 JS 페이로드를 제공하면 도움이 될 수 있습니다. [자세히 알아보기](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "자바스크립트 실행 시간 단축"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "자바스크립트 실행 시간"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "대용량의 GIF는 애니메이션 콘텐츠를 전달하는 데 비효율적입니다. 애니메이션에는 MPEG4/WebM 동영상을, 정적인 이미지에는 GIF 대신 PNG/WebP를 사용하여 네트워크 바이트를 절약하세요. [자세히 알아보기](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "애니메이션 콘텐츠에 동영상 형식 사용하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "중요한 리소스의 로드가 모두 완료된 후에는 오프스크린 및 숨겨진 이미지를 지연 로드함으로써 상호작용 시간을 줄이는 것이 좋습니다. [자세히 알아보기](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "오프스크린 이미지 지연하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "리소스가 페이지의 첫 페인트를 차단하고 있습니다. 중요한 JS/CSS를 인라인으로 전달하고 중요하지 않은 모든 JS/Style을 지연하는 것이 좋습니다. [자세히 알아보기](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "렌더링 차단 리소스 제거하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "네트워크 페이로드가 커지면 사용자에게 실제 비용 부담이 되며 로드 시간이 길어질 수 있습니다. [자세히 알아보기](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "총 크기: {totalBytes, number, bytes}KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "네트워크 페이로드가 커지지 않도록 관리하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "대규모 네트워크 페이로드 방지하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS 파일을 축소하면 네트워크 페이로드 크기를 줄일 수 있습니다. [자세히 알아보기](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSS 축소하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "자바스크립트 파일을 축소하면 페이로드 크기와 스크립트 파싱 시간을 줄일 수 있습니다. [자세히 알아보기](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "자바스크립트 줄이기"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "스타일시트에서 사용하지 않는 규칙을 삭제하고 스크롤 없이 볼 수 있는 부분에 사용되지 않는 CSS의 로드를 지연시켜 네트워크 활동에 소비되는 불필요한 바이트를 줄이세요. [자세히 알아보기](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "사용하지 않는 CSS 제거"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "사용하지 않는 자바스크립트를 삭제하고 네트워크 활동에 소비되는 바이트를 줄이세요."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "사용하지 않는 자바스크립트 삭제하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "캐시 수명이 길면 페이지를 반복해서 방문하는 속도가 빨라질 수 있습니다. [자세히 알아보기](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{리소스 1개 발견됨}other{리소스 #개 발견됨}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "효율적인 캐시 정책을 사용하여 정적인 애셋 제공하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "정적인 애셋에 효율적인 캐시 정책 사용하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "최적화된 이미지는 빠르게 로드되며 모바일 데이터를 적게 소비합니다. [자세히 알아보기](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "효율적으로 이미지 인코딩하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "적절한 크기의 이미지를 게재하여 모바일 데이터를 절약하고 로드 시간을 단축하세요. [자세히 알아보기](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "이미지 크기 적절하게 설정하기"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "총 네트워크 바이트를 최소화하려면 텍스트 기반 리소스를 압축(gzip, deflate, brotli)하여 제공해야 합니다. [자세히 알아보기](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "텍스트 압축 사용"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000, JPEG XR, WebP와 같은 이미지 형식을 사용하면 PNG 또는 JPEG보다 압축률이 높으므로 다운로드 속도가 빠르고 데이터 소비량도 줄어듭니다. [자세히 알아보기](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "차세대 형식을 사용해 이미지 제공하기"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "앱 콘텐츠의 너비가 표시 영역의 너비와 일치하지 않을 경우 앱이 휴대기기 화면에 최적화되지 않을 수 있습니다. [자세히 알아보기](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{innerWidth}px의 표시 영역 크기는 {outerWidth}px인 창 크기와 일치하지 않습니다."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "콘텐츠의 크기가 표시 영역에 알맞지 않음"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "콘텐츠의 크기가 표시 영역에 알맞음"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "다음의 크리티컬 요청 체인은 로드 시 우선순위가 높은 리소스를 보여줍니다. 체인의 길이를 줄이고, 리소스의 다운로드 크기를 줄이거나 불필요한 리소스의 다운로드를 지연하여 페이지 로드 속도를 높이는 것이 좋습니다. [자세히 알아보기](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1개 체인 발견됨}other{#개 체인 발견됨}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "중요 요청 깊이 최소화하기"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "지원 중단/경고"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "행"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "이후에 지원 중단된 API는 브라우저에서 삭제됩니다. [자세히 알아보기](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{경고 1개가 발견됨}other{경고 #개가 발견됨}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "지원 중단된 API 사용"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "지원 중단 API 사용하지 않기"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "애플리케이션 캐시는 지원이 중단되었습니다. [자세히 알아보기](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "검색된 ‘{AppCacheManifest}’"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "애플리케이션 캐시 사용"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "애플리케이션 캐시 사용하지 않기"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Doctype을 지정하면 브라우저가 쿼크 모드로 전환할 수 없습니다. [자세히 알아보기](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype 이름은 소문자 문자열 `html`이어야 합니다."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "문서에는 Doctype이 포함되어 있어야 합니다."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId가 빈 문자열일 것으로 예상됨"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId가 빈 문자열일 것으로 예상됨"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "페이지에 HTML Doctype이 없으므로 쿼크 모드가 트리거됨"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "페이지에 HTML Doctype 있음"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "요소"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "통계"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "값"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "브라우저 엔지니어들은 페이지에 1,500개 미만의 DOM 요소를 포함하는 것을 권장합니다. 최적값은 트리 깊이가 요소 32개 미만이고 하위/상위 요소 60개 미만일 때입니다. DOM이 크면 메모리 사용량이 늘어나고 [스타일 계산](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) 시간이 길어질 수 있으며 큰 비용이 드는 [레이아웃 리플로우](https://developers.google.com/speed/articles/reflow)가 발생할 수 있습니다. [자세히 알아보기](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{요소 1개}other{요소 #개}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "과도한 DOM 크기 지양하기"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "최대 DOM 깊이"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "총 DOM 요소 개수"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "최대 하위 요소"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "과도한 DOM 크기 지양하기"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "타겟"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "성능을 개선하고 보안 취약점을 예방하려면 `rel=\"noopener\"` 또는 `rel=\"noreferrer\"`을(를) 외부 링크에 추가합니다. [자세히 알아보기](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "교차 도메인 대상 링크가 안전하지 않음"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "교차 도메인 대상 링크가 안전함"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "앵커({anchorHTML})의 대상을 확인하지 못했습니다. 하이퍼링크로 사용되지 않는 경우 target=_blank를 삭제하는 것이 좋습니다."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "사용자가 컨텍스트 없이 위치 정보를 요청한 사이트를 신뢰할 수 없거나 이로 인해 혼란스러운 상태입니다. 대신 사용자 작업 요청 입력을 고려해 보세요. [자세히 알아보기](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "페이지 로드 시 위치정보 권한 요청"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "페이지 로드 시 위치정보 권한 요청 방지하기"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "버전"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "페이지에서 감지된 모든 프런트 엔드 JavaScript 라이브러리입니다. [자세히 알아보기](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "감지된 JavaScript 라이브러리"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "연결이 느린 사용자의 경우 `document.write()`에서 동적으로 삽입된 외부 스크립트로 인해 페이지 로드가 몇십 초까지 지연될 수 있습니다. [자세히 알아보기](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()`을(를) 사용함"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()` 지양하기"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "높은 심각도순"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "라이브러리 버전"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "취약점 수"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "일부 타사 스크립트에는 공격자가 쉽게 식별하고 공격할 수 있는 알려진 보안 취약점이 포함되어 있을 수 있습니다. [자세히 알아보기](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{취약점 1개가 감지됨}other{취약점 #개가 감지됨}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "알려진 보안 취약점이 있는 프런트 엔드 JavaScript 라이브러리가 포함됨"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "높음"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "낮음"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "보통"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "알려진 보안 취약점이 있는 프런트 엔드 JavaScript 라이브러리를 사용하지 않음"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "사용자가 컨텍스트 없이 알림 전송을 요청한 사이트를 신뢰할 수 없거나 이로 인해 혼란스러운 상태입니다. 대신 사용자 동작에 대한 요청 입력을 고려해 보세요. [자세히 알아보기](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "페이지 로드 시 알림 권한 요청"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "페이지 로드 시 알림 권한 요청 방지하기"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "통과하지 못한 요소"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "비밀번호 붙여넣기 방지로 인해 타당한 보안 정책이 저해됩니다. [자세히 알아보기](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "사용자가 비밀번호 입력란에 내용을 붙여넣지 못하도록 차단"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "사용자가 비밀번호 입력란에 붙여넣을 수 있도록 허용"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "프로토콜"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2는 HTTP/1.1에 비해 바이너리 헤더, 멀티플렉싱, 서버 푸시 등의 다양한 이점을 제공합니다. [자세히 알아보기](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{HTTP/2를 통해 게재되지 않는 요청 1건}other{HTTP/2를 통해 게재되지 않는 요청 #건}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "모든 리소스에 HTTP/2를 사용하지 않음"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "자체 리소스에 HTTP/2 사용"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "터치 및 휠 이벤트 리스너를 `passive`(으)로 표시하면 페이지 스크롤 성능을 개선할 수 있습니다. [자세히 알아보기](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "스크롤 성능 개선에 패시브 리스너를 사용하지 않음"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "스크롤 성능 개선에 패시브 리스너 사용"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "설명"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "콘솔에 로그된 오류는 해결되지 않은 문제를 의미합니다. 네트워크 요청 실패를 비롯한 기타 브라우저 문제로 인해 발생할 수 있습니다. [자세히 알아보기](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "브라우저 오류가 콘솔에 로그됨"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "콘솔에 로그된 브라우저 오류 없음"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "웹폰트가 로드되는 동안 사용자에게 텍스트가 표시되도록 글꼴 표시 CSS 기능을 사용합니다. [자세히 알아보기](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "웹폰트가 로드되는 동안 텍스트가 계속 표시되는지 확인하기"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "웹폰트가 로드되는 동안 모든 텍스트가 계속 표시됩니다"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse에서 다음 URL의 글꼴 표시 값을 자동으로 확인하지 못했습니다. {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "가로세로 비율(실제)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "가로세로 비율(표시됨)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "이미지 표시 측정기준은 원래 가로세로 비율과 일치해야 합니다. [자세히 알아보기](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "이미지를 올바르지 않은 가로세로 비율로 표시"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "이미지를 올바른 가로세로 비율로 표시"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "잘못된 이미지 크기 정보 {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "브라우저는 사용자에게 홈 화면에 앱을 추가하라는 메시지를 사전에 표시할 수 있으며 이렇게 하면 참여도가 높아질 수 있습니다. [자세히 알아보기](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "웹 앱 매니페스트가 설치 가능 요건을 충족하지 않음"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "웹 앱 매니페스트가 설치 가능 요건을 충족함"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "안전하지 않은 URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "민감한 데이터를 다루지 않는 사이트를 포함한 모든 사이트는 HTTPS로 보호해야 합니다. HTTPS는 침입자가 앱과 사용자 사이의 통신을 조작하거나 통신에 대해 패시브 리스너를 사용하지 못하도록 방지하며 HTTP/2와 여러 신규 웹 플랫폼 API의 필수 요건이기도 합니다. [자세히 알아보기](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{안전하지 않은 요청 1건 검색됨}other{안전하지 않은 요청 #건 검색됨}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "HTTPS 사용하지 않음"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPS 사용"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "셀룰러 네트워크에서 페이지 로드가 빠르면 우수한 모바일 사용자 환경을 제공할 수 있습니다. [자세히 알아보기](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "페이지와 상호작용할 수 있게 될 때까지 걸린 시간: {timeInMs, number, seconds}초"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "시뮬레이션된 모바일 네트워크에서 페이지와 상호작용할 수 있게 될 때까지 걸린 시간: {timeInMs, number, seconds}초"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "페이지가 너무 느리게 로드되므로 10초 이내에 사용할 수 없습니다. '성능' 섹션에서 추천 내용과 진단을 확인해 개선 방안을 알아보세요."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "모바일 네트워크에서 페이지 로딩이 충분히 빠르지 않음"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "모바일 네트워크에서 페이지 로드가 충분히 빠름"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "카테고리"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "JS 파싱, 컴파일, 실행에 소요되는 시간을 줄여 보세요. 용량이 적은 JS 페이로드를 제공하면 도움이 될 수 있습니다. [자세히 알아보기](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "기본 스레드 작업 최소화하기"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "기본 스레드 작업 최소화하기"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "최대한 많은 사용자가 이용할 수 있으려면 사이트가 모든 주요 브라우저에서 작동해야 합니다. [자세히 알아보기](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "사이트가 다양한 브라우저에서 작동함"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "페이지를 소셜 미디어에 공유하려면 개별 페이지가 URL을 통해 딥 링크로 연결될 수 있어야 하며 페이지별로 URL이 달라야 합니다. [자세히 알아보기](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "페이지마다 URL이 있음"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "탭을 했을 때 느린 네트워크에서도 전환이 빠르게 느껴져야 합니다. 이 환경은 사용자가 체감하는 성능의 핵심입니다. [자세히 알아보기](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "페이지 전환 시 네트워크에서 막히는 느낌이 들지 않음"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "예상 입력 대기시간은 페이지 로드가 가장 많은 5초 동안 앱이 사용자 입력에 응답하는 데 걸리는 시간(밀리초)의 추정치입니다. 지연 시간이 50밀리초보다 길면 사용자가 앱이 느리다고 인식할 수 있습니다. [자세히 알아보기](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "예상 입력 대기시간"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "콘텐츠가 포함된 첫 페인트는 첫 번째 텍스트 또는 이미지가 표시되는 시간을 나타냅니다. [자세히 알아보기](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "최초 만족 페인트"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "최초 CPU 유휴 상태는 페이지의 기본 스레드가 입력을 처리할 수 있을 만큼 조용한 상태가 된 첫 번째 시간을 표시합니다. [자세히 알아보기](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "최초 CPU 유휴 상태"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "유의미한 첫 페인트는 페이지의 기본 콘텐츠가 표시되는 경우를 측정합니다. [자세히 알아보기](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "최초 유의미 페인트"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "사용할 수 있을 때까지 걸리는 시간은 완전히 페이지와 상호작용할 수 있게 될 때까지 걸리는 시간입니다. [자세히 알아보기](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "상호작용 시간"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "사용자가 경험할 수 있는 최대 첫 입력 지연 예상 시간은 가장 긴 작업의 길이(밀리초)입니다. [자세히 알아보기](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "최대 첫 입력 지연 예상 시간"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "속도 색인은 페이지 콘텐츠가 얼마나 빨리 표시되는지 보여줍니다. [자세히 알아보기](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "속도 색인"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "FCP와 상호작용 시간 사이의 모든 시간의 합으로 작업 지속 시간이 50ms를 넘으면 밀리초 단위로 표현됩니다."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "총 차단 시간"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "네트워크 왕복 시간(RTT)이 성능에 큰 영향을 줍니다. 출발지로의 RTT가 크면 서버가 사용자에게 가까울 때 성능이 향상될 수 있음을 나타냅니다. [자세히 알아보기](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "네트워크 왕복 시간"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "서버 지연 시간은 웹 성능에 영향을 줄 수 있습니다. 출발지의 서버 지연 시간이 길면 서버에 과부하가 걸렸거나 백엔드 성능이 낮음을 나타냅니다. [자세히 알아보기](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "서버 백엔드 지연 시간"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "서비스 워커를 사용하면 예측 불가능한 네트워크 상태에서도 웹 앱이 안정적으로 작동할 수 있습니다. [자세히 알아보기](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url`이(가) 오프라인 시 200으로 응답하지 않음"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url`이(가) 오프라인 시 200으로 응답함"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse가 매니페스트에서 `start_url`을(를) 읽지 못했습니다. 그 결과 `start_url`은(는) 문서 URL인 것으로 간주되었습니다. 오류 메시지는 '{manifestWarning}'입니다."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "예산 초과"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "네트워크 요청의 양과 크기는 제공된 성능 예산에 따라 설정된 목표치 아래로 유지하세요. [자세히 알아보기](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{요청 1건}other{요청 #건}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "성능 예산"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "HTTPS를 이미 설정한 경우 모든 사용자가 안전한 웹 기능을 사용하기 위해서는 모든 HTTP 트래픽이 HTTPS로 리디렉션되어야 합니다. [자세히 알아보기](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP 트래픽을 HTTPS로 리디렉션하지 않음"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP 트래픽을 HTTPS로 리디렉션함"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "리디렉션을 사용하면 페이지가 로드되기 전 추가적인 지연이 발생합니다. [자세히 알아보기](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "여러 차례의 페이지 리디렉션 피하기"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "페이지 리소스의 수량과 크기와 관련해 예산을 설정하려면 budget.json 파일을 추가하세요. [자세히 알아보기](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{요청 1건 • {byteCount, number, bytes}KB}other{요청 #건 • {byteCount, number, bytes}KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "요청 수는 낮게, 전송 크기는 작게 유지하기"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "표준 링크는 검색결과에 어떤 URL을 표시할지 알려줍니다. [자세히 알아보기](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "여러 개의 URL({urlList})이 충돌됨"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "다른 도메인({url})을 가리킵니다."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "잘못된 URL({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "다른 `hreflang` 위치({url})를 가리킵니다."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "상대 URL({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "콘텐츠 페이지가 아닌 도메인의 루트 URL(홈페이지)을 가리킴"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "문서에 유효한 `rel=canonical` 없음"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "문서에 유효한 `rel=canonical` 있음"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12px보다 글꼴 크기가 작으면 읽기 어렵기 때문에 모바일 방문자가 '손가락으로 확대'해야만 읽을 수 있습니다. 페이지 텍스트의 60% 이상을 12px 이상으로 유지하도록 노력하세요. [자세히 알아보기](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} 읽기 쉬운 텍스트"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "모바일 화면에 최적화된 표시 영역 메타 태그가 없어서 텍스트를 알아볼 수 없음"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "텍스트의 {decimalProportion, number, extendedPercent} 값이 너무 작습니다({decimalProportionVisited, number, extendedPercent} 샘플 기준)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "문서에서 읽기 쉬운 글꼴 크기를 사용하지 않음"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "문서가 읽기 쉬운 글꼴 크기를 사용함"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang 링크는 검색엔진에 특정 언어나 지역에서 페이지의 어떤 버전을 검색결과로 표시해야 할지 알려줍니다. [자세히 알아보기](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "문서에 유효한 `hreflang` 없음"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "문서에 유효한 `hreflang` 있음"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "실패한 HTTP 상태 코드가 있는 페이지는 제대로 색인이 생성되지 않을 수 있습니다. [자세히 알아보기](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "페이지에 실패한 HTTP 상태 코드가 있음"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "페이지에 성공적인 HTTP 상태 코드가 있음"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "검색엔진이 페이지를 크롤링할 권한이 없으면 검색결과에 포함할 수 없습니다. [자세히 알아보기](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "페이지의 색인 생성이 차단됨"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "페이지의 색인 생성이 차단되지 않음"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "구체적인 링크 텍스트는 검색엔진에서 콘텐츠를 이해하는 데 도움이 됩니다. [자세히 알아보기](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{링크 1개 찾음}other{링크 #개 찾음}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "링크에 설명 텍스트가 없음"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "링크에 설명 텍스트가 있음"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "[구조화된 데이터용 테스트 도구](https://search.google.com/structured-data/testing-tool/)와 [구조화된 데이터 Linter](http://linter.structured-data.org/)를 실행하여 구조화된 데이터를 검증합니다. [자세히 알아보기](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "구조화된 데이터가 유효함"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "검색결과에 페이지 콘텐츠를 간략하게 요약하기 위한 메타 설명이 포함될 수 있습니다. [자세히 알아보기](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "설명 텍스트가 비어 있습니다."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "문서에 메타 설명이 없음"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "문서에 메타 설명이 있음"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "검색엔진은 플러그인 콘텐츠의 색인을 생성할 수 없고 플러그인을 제한하거나 지원하지 않는 기기도 많습니다. [자세히 알아보기](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "문서가 플러그인을 사용함"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "문서에서 플러그인을 사용할 수 없음"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "robots.txt 파일 형식이 잘못된 경우 크롤러가 웹사이트를 어떻게 크롤링하고 색인을 생성해야 할지 파악하지 못할 수 있습니다. [자세히 알아보기](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt 요청에 반환된 HTTP 상태: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{오류 1개 발견}other{오류 #개 발견}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse에서 robots.txt 파일을 다운로드할 수 없음"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt가 유효하지 않음"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt가 유효함"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "버튼이나 링크 같은 상호작용 요소는 충분히 커야 하며(48 x 48px), 주변에 충분한 공간이 있고 다른 요소와 겹치지 않아 쉽게 탭할 수 있어야 합니다. [자세히 알아보기](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} 탭 타겟 크기가 적절함"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "모바일 화면에 최적화된 표시 영역 메타 태그가 없어서 탭 타겟이 너무 작음"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "탭 타겟 크기가 적절하지 않음"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "타겟이 중복됨"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "탭 타겟"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "탭 타겟의 크기가 적절함"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "서비스 워커는 앱에서 오프라인, 홈 화면에 추가, 푸시 알림 등 다양한 프로그레시브 웹 앱 기능을 사용할 수 있도록 설정하는 기술입니다. [자세히 알아보기](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "이 페이지는 서비스 워커로 인해 제어되지만 매니페스트가 유효한 JSON으로 파싱하는 데 실패했으므로 `start_url`을(를) 찾지 못했습니다."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "이 페이지는 서비스 워커로 인해 제어되지만 `start_url`({startUrl})이(가) 서비스 워커의 범위({scopeUrl})에 있지 않습니다."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "이 페이지는 서비스 워커로 인해 제어되지만 가져온 매니페스트가 없으므로 `start_url`을(를) 찾지 못했습니다."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "이 원본에 하나 이상의 서비스 워커가 있지만 페이지({pageUrl})가 범위 내에 있지 않습니다."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "페이지와 `start_url`을(를) 제어하는 서비스 워커를 등록하지 않음"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "페이지와 `start_url`을(를) 제어하는 서비스 워커를 등록함"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "테마 스플래시 화면을 사용하면 사용자가 홈 화면에서 앱을 실행했을 때 고품질의 환경을 경험할 수 있습니다. [자세히 알아보기](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "맞춤 스플래시 화면에 맞게 구성되지 않음"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "맞춤 스플래시 화면에 맞게 구성됨"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "브라우저 주소 표시줄에는 사이트와 맞는 테마를 설정할 수 있습니다. [자세히 알아보기](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "주소 표시줄의 테마 색상을 설정하지 않음"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "주소 표시줄의 테마 색상을 설정함"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "기본 스레드 차단 시간"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "타사"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "타사 코드는 로드 성능에 크게 영향을 미칠 수 있습니다. 페이지에서 먼저 로딩을 끝낸 후 중복되는 타사 공급업체의 수를 제한하고 타사 코드를 로드해 보세요. [자세히 알아보기](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "타사 코드가 {timeInMs, number, milliseconds} ms 동안 기본 스레드를 차단했습니다."
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "타사 코드의 영향을 줄임"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "타사 사용"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Time To First Byte는 서버가 응답을 보내는 시간을 식별합니다. [자세히 알아보기](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "루트 문서에 {timeInMs, number, milliseconds} ms 소요됨"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "서버 응답 시간(TTFB) 단축"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "서버 응답 시간 낮음(TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "시간"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "시작 시간"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "유형"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "앱에서 User Timing API를 사용하여 중요 사용자 경험이 이루어지는 동안의 실제 성능을 측정하세요. [자세히 알아보기](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{사용자 시간 1회}other{사용자 시간 #회}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "사용자 타이밍 표시 및 측정 값"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "‘{securityOrigin}’에 사전 연결 <link>가 있으나 브라우저에서 사용되지 않습니다. `crossorigin` 속성을 올바르게 사용하고 있는지 확인하세요."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "`preconnect` 또는 `dns-prefetch` 리소스 힌트를 추가하여 중요한 타사 원본에 대한 조기 연결을 수립하는 것이 좋습니다. [자세히 알아보기](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "필수 원본 미리 연결하기"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "'{preloadURL}'에 사전 로드 <link>가 있으나 브라우저에서 사용되지 않습니다. `crossorigin` 속성을 올바르게 사용하고 있는지 확인하세요."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "`<link rel=preload>`을(를) 사용하여 현재 요청되는 리소스를 페이지 로드에 나중에 가져올 때 우선순위를 정하는 것이 좋습니다. [자세히 알아보기](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "중요한 요청을 미리 로드하기"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "휴대기기 화면에 앱을 최적화하려면 `<meta name=\"viewport\">` 태그를 추가합니다. [자세히 알아보기](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "`<meta name=\"viewport\">` 태그 없음"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "`width` 또는 `initial-scale`이(가) 포함된 `<meta name=\"viewport\">` 태그가 없음"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "`width` 또는 `initial-scale`이(가) 포함된 `<meta name=\"viewport\">` 태그가 있음"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "JavaScript가 사용 중지되었더라도 사용자에게 앱을 사용하려면 JavaScript가 필요하다는 경고 등의 일부 콘텐츠는 앱에 표시되어야 합니다. [자세히 알아보기](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "페이지 본문에서 스크립트를 사용할 수 없는 경우 본문에서 콘텐츠를 일부 렌더링해야 합니다."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "JavaScript를 사용할 수 없는 경우 대체 콘텐츠를 제공하지 않음"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "JavaScript를 사용할 수 없는 경우에도 일부 콘텐츠를 포함함"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "프로그레시브 웹 앱을 빌드할 경우 앱이 오프라인에서도 작동할 수 있도록 서비스 워커를 사용하는 것이 좋습니다. [자세히 알아보기](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "현재 페이지가 오프라인 시 200으로 응답하지 않음"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "현재 페이지가 오프라인 시 200으로 응답함"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "테스트 URL({requested})이 '{final}'(으)로 리디렉션되므로 이 페이지가 오프라인 상태에서는 로드되지 않을 수 있습니다. 두 번째 URL로 직접 테스트해 보세요."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "애플리케이션의 ARIA 사용을 개선하도록 추천된 사항입니다. 이를 통해 스크린 리더와 같은 지원 기술을 사용하는 사용자의 환경을 개선할 수 있습니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "오디오 및 비디오의 대체 콘텐츠를 제공하도록 추천된 사항입니다. 이를 통해 청각 장애나 시각 장애가 있는 사용자의 환경을 개선할 수 있습니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "오디오 및 동영상"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "일반적인 접근성 권장사항을 강조표시합니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "권장사항"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "이 검사에서는 [웹 앱의 접근성을 개선](https://developers.google.com/web/fundamentals/accessibility)하도록 추천된 사항을 강조합니다. 접근성 문제의 일부만 자동으로 감지되므로 직접 테스트하는 것도 좋습니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "자동화된 테스트 도구가 처리할 수 없는 영역을 다루는 항목입니다. [접근성 검토 실시](https://developers.google.com/web/fundamentals/accessibility/how-to-review)에 관한 가이드에서 자세히 알아보세요."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "접근성"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "콘텐츠의 가독성을 개선할 추천 내용입니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "대비"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "다른 언어를 사용하는 사용자가 콘텐츠를 더 쉽게 이해할 수 있게 개선하도록 추천된 사항입니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "다국어화 및 현지화"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "애플리케이션 컨트롤의 의미 해석을 개선하도록 추천된 사항입니다. 이를 통해 스크린 리더와 같은 지원 기술을 사용하는 사용자의 환경을 개선할 수 있습니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "이름 및 라벨"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "애플리케이션에서 키보드 탐색을 개선하도록 추천된 사항입니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "탐색"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "다음은 스크린 리더와 같은 보조 기술을 사용하여 표나 목록 데이터를 읽는 환경을 개선하도록 추천된 사항입니다."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "표와 목록"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "권장사항"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "성능 예산은 사이트 성능의 표준을 설정합니다."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "예산"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "애플리케이션 성능과 관련된 추가 정보입니다. 이러한 숫자는 성능 점수에 [직접적인 영향](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)을 미치지 않습니다."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "진단"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "성능에서 가장 중요한 측면은 픽셀이 화면에 렌더링되는 속도입니다. 주요 측정항목: 최초 만족 페인트, 최초 유의미 페인트"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "최초 페인트 개선"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "이러한 권장사항은 페이지를 더 빠르게 로드하는 데 도움이 될 수 있습니다. 성능 점수에는 [직접적인 영향](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)을 미치지 않습니다."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "추천"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "측정항목"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "페이지가 빠르게 반응하고 가능한 한 빨리 사용할 수 있는 준비가 되도록 전반적인 로드 환경을 강화하세요. 주요 측정항목: 상호작용 시간, 속도 색인"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "전반적인 개선사항"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "성능"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "이 검사는 프로그레시브 웹 앱의 요소를 검사합니다. [자세히 알아보기](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "이 검사는 기준 [PWA 체크리스트](https://developers.google.com/web/progressive-web-apps/checklist)의 필수 항목이지만 Lighthouse에서 자동으로 확인되지는 않습니다. 점수에 영향을 미치지는 않지만 직접 확인하는 것이 중요합니다."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "프로그레시브 웹 앱"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "속도와 안정성"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "설치 가능"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA 최적화됨"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "이와 같은 검사를 통해 페이지가 검색엔진 결과 순위에 최적화되도록 할 수 있습니다. Lighthouse에서 점검하지 않는 추가적인 요소가 검색 순위에 영향을 줄 수도 있습니다. [자세히 알아보기](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "사이트에서 이러한 추가 검증 도구를 실행하여 추가적인 검색엔진 최적화 권장사항을 확인합니다."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "검색엔진 최적화"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "크롤러가 앱 콘텐츠를 효과적으로 파악할 수 있도록 HTML 형식을 지정하세요."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "콘텐츠 권장사항"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "검색결과에 표시하려면 크롤러가 앱에 액세스할 수 있어야 합니다."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "크롤링 및 색인 생성"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "사용자가 콘텐츠를 읽기 위해 페이지를 확대하거나 축소할 필요가 없도록 모바일 친화적인 페이지를 지원하세요. [자세히 알아보기](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "모바일 친화적"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "캐시 TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "위치"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "이름"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "요청"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "리소스 유형"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "크기"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "소요 시간"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "전송 크기"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "가능한 절감 효과"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "가능한 절감 효과"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "절감 가능치: {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "절감 가능치: {wastedMs, number, milliseconds} 밀리초"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "문서"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "글꼴"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "이미지"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "미디어"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} 밀리초"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "기타"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "스크립트"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} 초"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "스타일시트"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "타사"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "합계"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "페이지 로드 중 처리한 추적을 기록하던 중 문제가 발생했습니다. Lighthouse를 다시 실행하세요. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "초기 디버거 프로토콜 연결 대기 시간이 초과되었습니다."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome이 페이지 로드 중 스크린샷을 수집하지 않았습니다. 페이지에 표시된 콘텐츠가 있는지 확인한 다음 Lighthouse를 다시 실행해 보세요. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS 서버에서 제공된 도메인을 해결하지 못했습니다."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "필수 {artifactName} 수집기에 다음 오류가 발생했습니다. {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Chrome 내부 오류가 발생했습니다. Chrome을 다시 시작한 다음 Lighthouse를 다시 실행해 주세요."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "필수 {artifactName} 수집기가 실행되지 않았습니다."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse에서 사용자가 요청한 페이지를 안정적으로 로드하지 못했습니다. 올바른 URL을 테스트하고 있으며 서버에서 모든 요청에 적절하게 응답하고 있는지 확인하세요."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "페이지 응답이 중지되었기 때문에 Lighthouse에서 사용자가 요청한 URL을 안정적으로 로드하지 못했습니다."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "제공한 URL에 유효한 보안 인증서가 포함되어 있지 않습니다. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome에서 전면 광고가 있는 페이지를 로드하지 못하도록 했습니다. 올바른 URL로 테스트하고 있으며 서버가 모든 요청에 적절하게 응답하고 있는지 확인하세요."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse에서 사용자가 요청한 페이지를 안정적으로 로드하지 못했습니다. 올바른 URL로 테스트하고 있으며 서버가 모든 요청에 적절하게 응답하고 있는지 확인하세요. (세부정보: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse에서 사용자가 요청한 페이지를 안정적으로 로드하지 못했습니다. 올바른 URL로 테스트하고 있으며 서버가 모든 요청에 적절하게 응답하고 있는지 확인하세요. (상태 코드: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "페이지 로드에 시간이 너무 오래 걸립니다. 보고서의 추천에 따라 페이지 로드 시간을 줄인 다음 Lighthouse를 다시 실행해 보세요. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools 프로토콜 응답 대기가 할당된 시간을 초과했습니다. (메서드: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "리소스 콘텐츠 가져오기 시간이 할당된 시간을 초과했습니다"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "사용자가 제공한 URL이 잘못되었습니다."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "감사 보기"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "초기 탐색"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "최상 경로 최대 지연 시간:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "오류!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "보고 오류: 감사 정보 없음"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "실험실 데이터"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "에뮬레이션된 모바일 네트워크에서 분석한 현재 페이지의 [Lighthouse](https://developers.google.com/web/tools/lighthouse/) 결과입니다. 값은 추정치이며 달라질 수 있습니다."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "직접 확인해야 하는 추가 항목"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "해당 사항 없음"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "추천"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "예상 절감치"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "통과한 감사"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "스니펫 접기"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "스니펫 펼치기"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "타사 리소스 표시"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Lighthouse 실행에 영향을 미치는 문제가 발생했습니다."
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "값은 추정치이며 달라질 수 있습니다. 성능 점수는 [이 측정항목만을 기준](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)으로 합니다."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "감사를 통과했으나 경고를 받음"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "경고: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "GIF를 HTML5 동영상으로 삽입할 수 있게 해주는 서비스에 GIF를 업로드하는 것이 좋습니다."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "[지연 로드 WordPress 플러그인](https://wordpress.org/plugins/search/lazy+load/)을 설치하면 화면에 모든 오프스크린 이미지를 지연하거나 이 기능을 제공하는 테마로 전환할 수 있습니다. [AMP 플러그인](https://wordpress.org/plugins/amp/) 사용도 고려해 보세요."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[중요한 애셋을 인라인](https://wordpress.org/plugins/search/critical+css/)하거나 [덜 중요한 리소스를 지연](https://wordpress.org/plugins/search/defer+css+javascript/)할 수 있게 도와주는 다양한 WordPress 플러그인이 있습니다. 이러한 플러그인에서 제공하는 최적화로 인해 내가 사용하는 테마 또는 플러그인의 기능이 깨질 수 있으므로 코드를 변경해야 할 가능성이 큽니다."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "테마, 플러그인, 서버 사양은 모두 서버 응답 시간을 길어지게 만듭니다. 보다 최적화된 테마를 찾고, 최적화 플러그인을 신중하게 선택하고, 서버 업그레이드를 고려해 보세요."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "게시물 목록에 발췌문을 표시하거나(예: 더 많은 태그 사용), 특정 페이지에 표시되는 게시물의 개수를 줄이거나, 길이가 긴 게시물을 여러 페이지로 나누거나, 플러그인을 사용하여 댓글을 지연 로드하는 것이 좋습니다."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "다양한 [WordPress 플러그인](https://wordpress.org/plugins/search/minify+css/)을 사용해 스타일을 연결, 축소, 압축함으로써 사이트 속도를 높일 수 있습니다. 또한 가능한 경우 빌드 프로세스를 사용하여 축소 작업을 미리 실행할 수도 있습니다."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "다양한 [WordPress 플러그인](https://wordpress.org/plugins/search/minify+javascript/)을 사용해 스크립트를 연결, 축소, 압축함으로써 사이트 속도를 높일 수 있습니다. 또한 가능한 경우 빌드 프로세스를 사용하여 축소 작업을 미리 실행할 수도 있습니다."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "페이지에서 사용되지 않는 CSS를 로드하는 [WordPress 플러그인](https://wordpress.org/plugins/) 개수를 줄이거나 전환하는 것이 좋습니다. 과도한 CSS를 부가하는 플러그인이 무엇인지 확인하려면 Chrome DevTools의 [코드 범위](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)를 실행해 보세요. 스타일시트의 URL에서 관련된 테마 또는 플러그인을 확인할 수 있습니다. 목록에서 코드 범위에 빨간색이 길게 표시된 스타일시트가 있는 플러그인을 찾아보세요. 실제로 페이지에서 사용되는 플러그인은 대기열에 하나의 스타일시트만 포함해야 합니다."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "페이지에서 사용되지 않는 JavaScript를 로드하는 [WordPress 플러그인](https://wordpress.org/plugins/) 개수를 줄이거나 전환하는 것이 좋습니다. 과도한 JS를 부가하는 플러그인이 무엇인지 확인하려면 Chrome DevTools의 [코드 범위](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)를 실행해 보세요. 스크립트의 URL에서 관련 테마 또는 플러그인을 확인할 수 있습니다. 목록에서 코드 범위에 빨간색이 길게 표시된 스크립트가 있는 플러그인을 찾아보세요. 실제로 페이지에서 사용되는 플러그인은 대기열에 하나의 스크립트만 포함해야 합니다."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPress 브라우저 캐싱](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)에 관해 자세히 알아보세요."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "품질은 그대로 유지하면서 이미지를 압축해주는 [이미지 최적화 WordPress 플러그인](https://wordpress.org/plugins/search/optimize+images/)을 사용해 보세요."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "필수 이미지 크기를 사용할 수 있도록 [미디어 라이브러리](https://codex.wordpress.org/Media_Library_Screen)에서 직접 이미지를 업로드하세요. 그런 다음 미디어 라이브러리에서 이미지를 삽입하거나 이미지 위젯을 사용하여 최적의 이미지 크기를 사용하는지 확인하세요(반응형 중단점용 이미지 포함). 이미지 크기가 용도에 적합하지 않다면 `Full Size` 이미지는 사용하지 않는 것이 좋습니다. [자세히 알아보기](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "웹 서버 구성에서 텍스트 압축을 사용 설정할 수 있습니다."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "업로드한 이미지를 최적화된 양식으로 자동 변환해주는 [플러그인](https://wordpress.org/plugins/search/convert+webp/) 또는 서비스를 사용하는 것이 좋습니다."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lt.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lt.json
new file mode 100644
index 00000000000..1a4ec08e7ec
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lt.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Naudodami prieigos raktus naudotojai gali greitai suaktyvinti puslapio dalį. Kad naršymas veiktų tinkamai, kiekvienas prieigos raktas turi būti unikalus. [Sužinokite daugiau](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Elemento „`[accesskey]`“ vertės nėra unikalios"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "„`[accesskey]`“ vertės yra unikalios"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Kiekviename ARIA elemente „`role`“ palaikoma tik dalis konkrečių atributų „`aria-*`“. Jei jie nebus suderinti, atributai „`aria-*`“ taps netinkami. [Sužinokite daugiau](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributai „`[aria-*]`“ neatitinka savo vaidmenų"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributai „`[aria-*]`“ atitinka savo vaidmenis"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Kai kuriems ARIA vaidmenims reikia atributų, aprašančių elementų būseną ekrano skaitytuvams. [Sužinokite daugiau](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Elementuose „`[role]`“ nėra visų privalomų atributų „`[aria-*]`“"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Elementuose „`[role]`“ yra visi būtini atributai „`[aria-*]`“"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Kai kuriuose ARIA pirminiuose vaidmenyse turi būti konkrečių antrinių vaidmenų, kad būtų galima atlikti numatytas pritaikomumo funkcijas. [Sužinokite daugiau](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementuose su ARIA vaidmeniu „`[role]`“, kurių antriniuose elementuose turi būti nurodytas konkretus „`[role]`“, trūksta kai kurių arba visų būtinų antrinių elementų."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementuose su ARIA vaidmeniu „`[role]`“, kurių antriniuose elementuose turi būti nurodytas konkretus „`[role]`“, yra visi būtini antriniai elementai."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Kai kurie ARIA antriniai vaidmenys turi būti konkrečiuose pirminiuose vaidmenyse, kad būtų tinkamai vykdomos numatytosios pritaikomumo funkcijos. [Sužinokite daugiau](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Elementų „`[role]`“ nėra būtiname pirminiame elemente"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Elementai „`[role]`“ yra būtiname pirminiame elemente"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA vaidmenų vertės turi būti tinkamos, kad būtų galima atlikti numatytas pritaikomumo funkcijas. [Sužinokite daugiau](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Elemento „`[role]`“ vertės yra netinkamos"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Elemento „`[role]`“ vertės yra tinkamos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Pagalbinės technologijos, pvz., ekrano skaitytuvai, negali interpretuoti ARIA atributų su netinkamomis vertėmis. [Sužinokite daugiau](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atributuose „`[aria-*]`“ nėra tinkamų verčių"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atributų „`[aria-*]`“ vertės yra tinkamos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Pagalbinės technologijos, pvz., ekrano skaitytuvai, negali tinkamai interpretuoti ARIA atributų su netinkamais pavadinimais. [Sužinokite daugiau](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributai „`[aria-*]`“ netinkami arba yra rašybos klaidų"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributai „`[aria-*]`“ yra tinkami, rašybos klaidų nėra"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Nurodžius antraštes garso įrašų elementus gali naudoti kurtieji arba sutrikusios klausos naudotojai. Jiems teikiama svarbi informacija, pvz., kas kalba, kas sakoma ir kita nekalbinė informacija. [Sužinokite daugiau](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementuose „`<audio>`“ trūksta elemento „`<track>`“ su atributu „`[kind=\"captions\"]`“."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementuose „`<audio>`“ yra elementas „`<track>`“ su atributu „`[kind=\"captions\"]`“"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Netinkami elementai"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Kai nenurodytas neįgaliesiems pritaikytas mygtuko pavadinimas, ekrano skaitytuvai apie jį praneša kaip „button“ (mygtukas), todėl jo negali naudoti ekrano skaitytuvo naudotojai. [Sužinokite daugiau](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Nenurodyti neįgaliesiems pritaikyti mygtukų pavadinimai"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Mygtukų pavadinimai pritaikyti neįgaliesiems"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Pridėjus būdų apeiti pasikartojantį turinį, klaviatūros naudotojai galės efektyviau naršyti puslapį. [Sužinokite daugiau](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Puslapyje nėra antraštės, praleidimo nuorodos arba orientyro regiono"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Puslapyje yra antraštė, praleidžiama nuoroda arba orientyro regionas"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Mažo kontrasto tekstą daugumai naudotojų yra sudėtinga arba neįmanoma perskaityti. [Sužinokite daugiau](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Nepakankamas fono ir priekinio fono spalvų kontrasto santykis."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Fono ir priekinio plano spalvų kontrasto santykis pakankamas"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Kai aprašo sąrašai netinkamai pažymėti, ekrano skaitytuvai gali pateikti klaidinančią arba netikslią išvestį. [Sužinokite daugiau](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Elementuose „`<dl>`“ nurodytos ne tik tinkamai surikiuotos grupės „`<dt>`“ ir „`<dd>`“ bei elementai „`<script>`“ arba „`<template>`“."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Elementuose „`<dl>`“ nurodytos tik tinkamai surikiuotos grupės „`<dt>`“ ir „`<dd>`“ ir elementai „`<script>`“ arba „`<template>`“."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Aprašo sąrašo elementai („`<dt>`“ ir „`<dd>`“) turi būti sujungti pirminiame elemente „`<dl>`“, kad ekrano skaitytuvai galėtų apie juos tinkamai pranešti. [Sužinokite daugiau](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Aprašo sąrašo elementai nesujungti elementuose „`<dl>`“"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Aprašo sąrašo elementai sujungti elementuose „`<dl>`“"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Pagal pavadinimą ekrano skaitytuvo naudotojai sužino, apie ką yra puslapio turinys, o paieškos variklio naudotojai gali nuspręsti, ar puslapis atitinka jų paiešką. [Sužinokite daugiau](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumente nėra elemento „`<title>`“"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumente yra elementas „`<title>`“"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Atributo „id“ vertė turi būti unikali, kad pagalbinės technologijos nepraleistų kitų objektų. [Sužinokite daugiau](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Puslapio atributai „`[id]`“ nėra unikalūs"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Puslapio atributai „`[id]`“ yra unikalūs"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Pagal rėmelių pavadinimus ekrano skaitytuvų naudotojai sužino, koks yra rėmelių turinys. [Sužinokite daugiau](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementas „`<frame>`“ arba „`<iframe>`“ neturi pavadinimo"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementai „`<frame>`“ arba „`<iframe>`“ turi pavadinimą"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Jei puslapyje nenurodytas atributas „lang“, ekrano skaitytuvas manys, kad puslapio kalba atitinka naudotojo pasirinktą numatytąją kalbą, kai buvo nustatomas ekrano skaitytuvas. Jei puslapio kalba neatitinka numatytosios kalbos, gali būti, kad ekrano skaitytuvas netinkamai skaitys puslapio tekstą. [Sužinokite daugiau](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Elemente „`<html>`“ nėra atributo „`[lang]`“"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Elemente „`<html>`“ yra atributas „`[lang]`“"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Nurodžius tinkamą [BCP 47 kalbą](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ekrano skaitytuvai gali tinkamai pranešti tekstą. [Sužinokite daugiau](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Elemente „`<html>`“ nenurodyta tinkama atributo „`[lang]`“ vertė."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Elemento „`<html>`“ atributo „`[lang]`“ vertė yra tinkama"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informaciniuose elementuose turėtų būti pateiktas trumpas, aprašomasis alternatyvus tekstas. Dekoratyvinių elementų galima nepaisyti nurodžius tuščią alternatyvų atributą. [Sužinokite daugiau](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Vaizdo elementuose nėra atributų „`[alt]`“"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Vaizdo elementuose yra atributų „`[alt]`“"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Kai vaizdas naudojamas kaip mygtukas „`<input>`“, pateikus alternatyvų tekstą ekrano skaitytuvo naudotojams bus lengviau suprasti mygtuko tikslą. [Sužinokite daugiau](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementuose „`<input type=\"image\">`“ nėra „`[alt]`“ teksto"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementuose „`<input type=\"image\">`“ yra „`[alt]`“ teksto"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etiketės užtikrina, kad pagalbinės technologijos, pvz., ekrano skaitytuvai, tinkamai praneštų apie formų valdiklius. [Sužinokite daugiau](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Nėra susietų formos elementų etikečių"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Formos elementuose yra atitinkamų etikečių"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Lentelėje, kuri naudojama išdėstymo tikslais, neturėtų būti duomenų elementų, pvz., elementų „th“ ar „caption“ arba atributo „summary“, nes taip ekrano skaitytuvų naudotojams gali būti teikiama trikdanti patirtis. [Sužinokite daugiau](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Pristatomuose elementuose „`<table>`“ nevengiama naudoti atributų „`<th>`“, „`<caption>`“ arba „`[summary]`“."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Pristatomuose elementuose „`<table>`“ vengiama naudoti atributus „`<th>`“, „`<caption>`“ ar „`[summary]`“."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Aiškus ir unikalus nuorodos tekstas (ir alternatyvusis vaizdų tekstas, kai jie naudojami kaip nuorodos), į kurį lengva sutelkti dėmesį, pagerina naršymo patirtį ekrano skaitytuvų naudotojams. [Sužinokite daugiau](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Nėra aiškių nuorodų pavadinimų"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Nuorodų pavadinimai aiškūs"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Ekrano skaitytuvai apie sąrašus praneša tam tikru būdu. Tinkama sąrašo struktūra padeda ekrano skaitytuvams pateikti tinkamą išvestį. [Sužinokite daugiau](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Sąrašuose pateikiami ne tik elementai „`<li>`“ ir scenarijaus palaikymo elementai („`<script>`“ ir „`<template>`“)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Sąrašuose pateikiami tik elementai „`<li>`“ ir scenarijaus palaikymo elementai („`<script>`“ ir „`<template>`“)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Naudojant ekrano skaitytuvus reikia, kad sąrašo elementai („`<li>`“) būtų pirminiame elemente „`<ul>`“ arba „`<ol>`“, kad apie juos būtų galima tinkamai pranešti. [Sužinokite daugiau](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Sąrašo elementų („`<li>`“) nėra pirminiuose elementuose „`<ul>`“ arba „`<ol>`“."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Sąrašo elementai („`<li>`“) yra pirminiuose elementuose „`<ul>`“ arba „`<ol>`“"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Naudotojai nesitiki, kad puslapis bus atnaujintas automatiškai. Tai atlikus dėmesys vėl sutelkiamas į puslapio viršų. Dėl to galima erzinanti arba klaidinanti patirtis. [Sužinokite daugiau](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumente naudojama metažyma „`<meta http-equiv=\"refresh\">`“"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumente nenaudojama metažyma „`<meta http-equiv=\"refresh\">`“"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Išjungus mastelio keitimą gali kilti problemų sutrikusio regėjimo naudotojams, kurie padidina ekraną, kad tinkamai matytų tinklalapio turinį. [Sužinokite daugiau](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Atributas „`[user-scalable=\"no\"]`“ naudojamas elemente „`<meta name=\"viewport\">`“ arba atributas „`[maximum-scale]`“ yra mažesnis nei 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Atributas „`[user-scalable=\"no\"]`“ nenaudojamas elemente „`<meta name=\"viewport\">`“, o atributas „`[maximum-scale]`“ yra ne mažesnis nei 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Ekrano skaitytuvai negali išversti turinio, kuris nėra tekstas. Prie elementų „`<object>`“ pridėjus alternatyviojo teksto, ekrano skaitytuvai naudotojams geriau perteikia reiškmę. [Sužinokite daugiau](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementuose „`<object>`“ nėra „`[alt]`“ teksto"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementuose „`<object>`“ yra „`[alt]`“ teksto"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Didesnė nei 0 vertė aiškiai nurodo naršymo tvarką. Iš tiesų tai yra tinkamas sprendimas, tačiau tai dažnai gali erzinti pagalbinių technologijų naudotojus. [Sužinokite daugiau](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Kai kurių elementų „`[tabindex]`“ vertė yra didesnė nei 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nėra elemento su didesne nei 0 „`[tabindex]`“ verte"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Ekrano skaitytuvuose naudojamos funkcijos, padedančios lengviau naršyti lenteles. Užtikrinus, kad langeliai „`<td>`“, kuriuose naudojamas atributas „`[headers]`“, nurodo tik langelius toje pačioje lentelėje, gali būti pagerinta ekrano skaitytuvų naudotojų patirtis. [Sužinokite daugiau](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Langeliai elemente „`<table>`“, kuriuose naudojamas atributas „`[headers]`“, nurodo elementą „`id`“, nerastą toje pačioje lentelėje."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Langeliai elemente „`<table>`“, kuriuose naudojamas atributas „`[headers]`“, nurodo lentelės langelius, esančius toje pačioje lentelėje."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Ekrano skaitytuvuose naudojamos funkcijos, padedančios lengviau naršyti lenteles. Užtikrinus, kad lentelės antraštės visada nurodo tam tikrą langelių rinkinį, gali būti pagerinta ekrano skaitytuvų naudotojų patirtis. [Sužinokite daugiau](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementuose „`<th>`“ ir elementuose su atributu „`[role=\"columnheader\"/\"rowheader\"]`“ nėra duomenų langelių, kuriuos jie aprašo."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementuose „`<th>`“ ir elementuose su atributu „`[role=\"columnheader\"/\"rowheader\"]`“ yra duomenų langelių, kuriuos jie aprašo."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Nurodžius tinkamą elementų [BCP 47 kalbą](https://www.w3.org/International/questions/qa-choosing-language-tags#question), užtikrinama, kad ekrano skaitytuvas tinkamai ištars tekstą. [Sužinokite daugiau](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atributuose „`[lang]`“ nėra tinkamos vertės"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributų „`[lang]`“ vertė tinkama"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Kai pateikiama vaizdo įrašo antraštė, kurtiems ir sutrikusios klausos naudotojams lengviau suprasti pateikiamą informaciją. [Sužinokite daugiau](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementuose „`<video>`“ nėra elemento „`<track>`“ su atributu „`[kind=\"captions\"]`“."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementuose „`<video>`“ yra elementas „`<track>`“ su atributu „`[kind=\"captions\"]`“"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Garso įrašų aprašai teikia reikiamą informaciją apie vaizdo įrašus, kurios negalima pateikti dialoge, pvz., susijusios su veido išraiškomis ir scenomis. [Sužinokite daugiau](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementuose „`<video>`“ nėra elemento „`<track>`“ su atributu „`[kind=\"description\"]`“."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementuose „`<video>`“ yra elementas „`<track>`“ su atributu „`[kind=\"description\"]`“"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Kad būtų tinkamai rodoma sistemoje „iOS“, kai naudotojai prideda laipsniškąją žiniatinklio programą prie pagrindinio ekrano, nurodykite `apple-touch-icon`. Ji turi nukreipti į neskaidrų 192 tšk. (arba 180 tšk.) kvadratinį PNG failą. [Sužinokite daugiau](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Nepateikiama tinkama piktograma „`apple-touch-icon`“"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "„`apple-touch-icon-precomposed`“ paseno, verčiau naudokite „`apple-touch-icon`“."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Pateikiama tinkama piktograma „`apple-touch-icon`“"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "„Chrome“ plėtiniai neigiamai paveikė šio puslapio įkėlimo našumą. Pabandykite patikrinti puslapį inkognito režimu arba naudodami „Chrome“ profilį be plėtinių."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Scenarijaus įvertinimas"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Scenarijaus analizė"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Bendras centrinio procesoriaus laikas"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Apsvarstykite galimybę sutrumpinti JS analizei, kompiliavimui ir vykdymui skiriamą laiką. Mažesnės JS naudingosios apkrovos gali padėti tai padaryti. [Sužinokite daugiau](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Sutrumpinkite „JavaScript“ vykdymo laiką"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "„JavaScript“ vykdymo laikas"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Dideli GIF failai nėra efektyvus animuoto turinio pateikimo būdas. Kad sutaupytumėte tinklo baitų, vietoje GIF failų galite naudoti MPEG4 ar „WebM“ vaizdo įrašų animacijai ir PNG ar „WebP“ statiniams vaizdams pateikti. [Sužinokite daugiau](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Naudokite vaizdo įrašo formatus animuotam turiniui pateikti"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Apsvarstykite galimybę įkelti ne ekraninius ir paslėptus vaizdus tik tada, kai bus įkelti visi svarbiausi ištekliai, kad sutrumpėtų laikas iki sąveikos. [Sužinokite daugiau](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Atidėkite ne ekraninius vaizdus"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Šaltiniai blokuoja puslapio pirmą žymėjimą. Apsvarstykite galimybę pateikti svarbiausius JS ar CSS kaip eilutinius elementus ir atidėti visus nesvarbius JS ar stilius. [Sužinokite daugiau](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Pašalinkite pateikimą blokuojančius išteklius"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Naudotojai turi mokėti už dideles tinklo naudingąsias apkrovas, be to, jos glaudžiai susijusios su ilgu įkėlimo laiku. [Sužinokite daugiau](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Bendras dydis: {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Išvenkite didelių tinklo naudingųjų apkrovų"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Išvengiama didelių tinklo naudingųjų apkrovų"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Sumažinus CSS failų dydį, gali sumažėti tinklo naudingosios apkrovos. [Sužinokite daugiau](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Sumažinkite CSS failus"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Sumažinus „JavaScript“ failus, galima sumažinti naudingąsias apkrovas ir sutrumpinti scenarijaus analizavimo laiką. [Sužinokite daugiau](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Sumažinkite „JavaScript“"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Pašalinkite neveikiančias taisykles iš stiliaus failų ir atidėkite CSS kalbos, nenaudojamos turiniui virš matomos ribos, įkėlimą, kad tinklo veikla sunaudotų mažiau baitų. [Sužinokite daugiau](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Pašalinkite nevartojamą CSS kalbą"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Pašalinkite nenaudojamą „JavaScript“, kad tinklo veikla sunaudotų mažiau baitų."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Pašalinkite nenaudojamą „JavaScript“"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Jei talpykla galios ilgiau, greičiau sulauksite pakartotinių apsilankymų puslapyje. [Sužinokite daugiau](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Rastas 1 išteklius}one{Rastas # išteklius}few{Rasti # ištekliai}many{Rasta # ištekliaus}other{Rasta # išteklių}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Statiniams ištekliams taikykite efektyvią talpyklos politiką"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Naudojama efektyvi statinių išteklių talpyklos politika"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimizuoti vaizdai įkeliami greičiau ir sunaudoja mažiau mobiliojo ryšio duomenų. [Sužinokite daugiau](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Efektyviai koduokite vaizdus"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Teikite tinkamo dydžio vaizdus, kad būtų taupomi mobiliojo ryšio duomenys ir puslapis būtų įkeliamas greičiau. [Sužinokite daugiau](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Pasirinkite tinkamo dydžio vaizdus"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstinius išteklius reikėtų suglaudinti (naudojant „Gzip“, „Deflate“ arba „Brotli“), kad bendrai būtų sunaudojama kuo mažiau tinklo baitų. [Sužinokite daugiau](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Įgalinkite teksto glaudinimą"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Tokių formatų kaip JPEG 2000, JPEG XR ir „WebP“ vaizdai dažniausiai glaudinami geriau nei PNG ar JPEG vaizdai, todėl yra atsisiunčiami greičiau ir sunaudoja mažiau duomenų. [Sužinokite daugiau](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Pateikite naujos kartos formatų vaizdus"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Jei programos turinio plotis nesutampa su peržiūros srities pločiu, jūsų programa gali būti neoptimizuota mobiliųjų įrenginių ekranams. [Sužinokite daugiau](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{innerWidth} tšk. peržiūros sritis neatitinka {outerWidth} tšk. lango dydžio."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Turinys nėra tinkamo dydžio peržiūros sričiai"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Turinys yra tinkamo dydžio peržiūros sričiai"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Toliau pateiktose svarbiausių užklausų grandinėse nurodoma, kurie ištekliai įkelti nurodant aukštą prioritetą. Kad puslapio įkėlimas būtų sklandesnis, apsvarstykite galimybę sutrumpinti grandines, sumažinti atsisiunčiamų išteklių dydį arba atidėti nebūtinų išteklių atsisiuntimą. [Sužinokite daugiau](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Rasta 1 grandinė}one{Rasta # grandinė}few{Rastos # grandinės}many{Rasta # grandinės}other{Rasta # grandinių}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Sumažinkite svarbiausių užklausų gylį"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Naudojimo nutraukimas / įspėjimas"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linija"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Nebenaudojamos API galiausiai bus pašalintos iš naršyklės. [Sužinokite daugiau](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Rastas 1 įspėjimas}one{Rastas # įspėjimas}few{Rasti # įspėjimai}many{Rasta # įspėjimo}other{Rasta # įspėjimų}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Naudojamos pasenusios API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Vengiama nebenaudojamų API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Programos talpykla nebenaudojama. [Sužinokite daugiau](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Rastas elementas „{AppCacheManifest}“"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Naudojama programos talpykla"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Vengiama naudoti programos talpyklą"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Nurodžius DOCTYPE, naršyklė neperjungia į seno standarto tinklalapių palaikymo režimą. [Sužinokite daugiau](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE pavadinimas turi būti mažosiomis raidėmis nurodyta eilutė „`html`“"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumente turi būti nurodytas DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Laukas „publicId“ turėtų būti tuščias"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Laukas „systemId“ turėtų būti tuščias"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Puslapyje trūksta HTML DOCTYPE, todėl aktyvinamas seno standarto tinklalapių palaikymo režimas"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Puslapyje yra HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elementas"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Vertė"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Naršyklių inžinieriai rekomenduoja puslapiuose naudoti ne daugiau kaip apytiksliai 1,5 tūkst. DOM elementų. Optimaliausias medžio gylis – mažiau nei 32 elementai ir mažiau nei 60 antrinių bei pirminių elementų. Dėl didelio DOM elementų skaičiaus gali būti sunaudojama daugiau atminties, ilgiau [skaičiuojami stiliai](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) ir gali reikėti brangių [išdėstymo perskaičiavimų](https://developers.google.com/speed/articles/reflow). [Sužinokite daugiau](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elementas}one{# elementas}few{# elementai}many{# elemento}other{# elementų}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Venkite per didelių DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimalus DOM gylis"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Bendras DOM elementų skaičius"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimalus antrinių elementų skaičius"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Išvengiama per didelių DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Atributas „rel“"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Taikymas"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Pridėkite fragmentus „`rel=\"noopener\"`“ arba „`rel=\"noreferrer\"`“ prie bet kurių išorinių nuorodų, kad pagerintumėte našumą ir išvengtumėte saugos pažeidimų. [Sužinokite daugiau](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Nuorodos į mišrios kilmės paskirties vietas yra nesaugios"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Nuorodos į mišrios kilmės paskirties vietas yra saugios"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nepavyko nustatyti prieraišo ({anchorHTML}) paskirties vietos. Jei jo nenaudojate kaip hipersaito, apsvarstykite galimybę pašalinti atributą „target=_blank“."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Naudotojai gali būti įtarūs arba sumišę, jei svetainėse bus prašoma suteikti leidimą pasiekti vietovės duomenis be jokio konteksto. Apsvarstykite galimybę susieti užklausą su naudotojų veiksmu. [Sužinokite daugiau](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Įkeliant puslapį pateikiama užklausa dėl pranešimų leidimo"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Įkeliant puslapį vengiama pateikti užklausą dėl leidimo nustatyti geografinę vietovę"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versija"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Puslapyje aptiktos visos „JavaScript“ sąsajos bibliotekos. [Sužinokite daugiau](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Aptikta „JavaScript“ bibliotekų"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Esant lėtam ryšiui, išoriniai scenarijai, dinamiškai įterpiami naudojant „`document.write()`“, gali atidėti puslapio įkėlimą dešimtimis sekundžių. [Sužinokite daugiau](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Naudojamas „`document.write()`“"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Vengiama naudoti „`document.write()`“"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Rimčiausias pažeidimas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bibliotekos versija"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Pažeidimų skaičius"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Kai kuriuose trečiųjų šalių scenarijuose gali būti žinomų saugos pažeidimų, kuriuos užpuolėjai gali lengvai nustatyti ir jais pasinaudoti. [Sužinokite daugiau](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Aptiktas 1 pažeidimas}one{Aptiktas # pažeidimas}few{Aptikti # pažeidimai}many{Aptikta # pažeidimo}other{Aptikta # pažeidimų}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Puslapyje yra „JavaScript“ sąsajos bibliotekų, kuriose yra žinomų saugos pažeidimų"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Didelis"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Mažas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Vidutinis"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Vengiama „JavaScript“ sąsajos bibliotekų, kuriose yra žinomų saugos pažeidimų"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Naudotojai gali būti įtarūs arba sumišę, jei svetainėse bus prašoma suteikti pranešimų leidimą be jokio konteksto. Apsvarstykite galimybę susieti užklausą su naudotojų gestais. [Sužinokite daugiau](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Įkeliant puslapį pateikiama užklausa dėl pranešimų leidimo"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Įkeliant puslapį vengiama pateikti užklausą dėl pranešimų leidimo"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Netinkami elementai"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Neleidžiant įklijuoti slaptažodžių, pažeidžiama tinkamos saugos politika. [Sužinokite daugiau](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Naudotojams neleidžiama įklijuoti teksto į slaptažodžių laukus"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Naudotojams leidžiama įklijuoti tekstą į slaptažodžių laukus"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokolas"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Naudodami HTTP/2 gaunate daugiau privalumų, nei naudodami HTTP/1.1, pvz., dvigubas antraštes, tankinimą ir serverio įkėlimo funkciją. [Sužinokite daugiau](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 užklausa nepateikta naudojant HTTP/2}one{# užklausa nepateikta naudojant HTTP/2}few{# užklausos nepateiktos naudojant HTTP/2}many{# užklausos nepateikta naudojant HTTP/2}other{# užklausų nepateikta naudojant HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nenaudojamas HTTP/2 visuose šaltiniuose"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Naudojamas HTTP/2 puslapio šaltiniuose"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Apsvarstykite galimybę pažymėti lietimo ir pelės ratuko sukimo įvykių apdorojimą kaip „`passive`“, kad pagerintumėte puslapio slinkimo našumą. [Sužinokite daugiau](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nenaudojamos pasyvios apdorojimo priemonės siekiant pagerinti slinkimo našumą"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Naudojamos pasyvios apdorojimo priemonės siekiant pagerinti slinkimo našumą"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Aprašas"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Pulte užregistruotos klaidos nurodo, kad esama neišspręstų problemų. Jos galėjo kilti nepavykus pateikti tinklo užklausų arba dėl kitų naršyklės problemų. [Sužinokite daugiau](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Naršyklės klaidos registruojamos pulte"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Pulte neužregistruota naršyklės klaidų"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Pasinaudokite šriftų pateikimo CSS funkcija, kad tekstas būtų matomas naudotojui, kol įkeliami žiniatinklio šriftai. [Sužinokite daugiau](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Užtikrinkite, kad įkeliant žiniatinklio šriftą būtų matomas tekstas"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Įkeliant žiniatinklio šriftą matomas visas tekstas"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "„Lighthouse“ nepavyko automatiškai patikrinti toliau nurodyto URL šriftų pateikimo vertės: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Formato koeficientas (faktinis)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Formato koeficientas (rodomas)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Rodomo vaizdo matmenys turi atitikti natūralų formato koeficientą. [Sužinokite daugiau](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Rodomi vaizdai su netinkamu formato koeficientu"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Rodomi vaizdai su tinkamu formato koeficientu"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Netinkama vaizdo dydžio informacija: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Naršyklės gali aktyviai raginti naudotojus pridėti jūsų programą prie pagrindinio ekrano, tai paskatintų geresnį įtraukimą. [Sužinokite daugiau](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Žiniatinklio programos aprašas neatitinka diegiamumo reikalavimų."
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Žiniatinklio programos aprašas atitinka diegiamumo reikalavimus"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nesaugus URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Visos svetainės turėtų būti apsaugotos naudojant HTTPS, net ir tos, kuriose nėra neskelbtinų duomenų. Naudojant HTTPS įsibrovėliams neleidžiama gadinti ar pasyviai klausytis jūsų programos ir jos naudotojų komunikacijos, be to, jį privaloma naudoti HTTP/2 ir daugelyje naujų žiniatinklio platformų API. [Sužinokite daugiau](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Rasta 1 nesaugi užklausa}one{Rasta # nesaugi užklausa}few{Rastos # nesaugios užklausos}many{Rasta # nesaugos užklausos}other{Rasta # nesaugių užklausų}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nenaudojamas HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Naudojamas HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Spartus puslapių įkėlimas mobiliojo ryšio tinkle užtikrina gerą mobiliųjų įrenginių naudotojų patirtį. [Sužinokite daugiau](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Laikas iki sąveikos – {timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Laikas iki sąveikos imituojamame mobiliojo ryšio tinkle – {timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Puslapis įkeliamas per lėtai ir nėra interaktyvus 10 sekundžių. Peržiūrėkite galimybes ir diagnostiką skiltyje „Našumas“, kad sužinotumėte, kaip pagerinti situaciją."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Puslapis įkeliamas nepakankamai sparčiai mobiliojo ryšio tinkluose"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Puslapis įkeliamas pakankamai sparčiai mobiliojo ryšio tinkluose"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorija"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Apsvarstykite galimybę sutrumpinti JS analizei, kompiliavimui ir vykdymui skiriamą laiką. Mažesnės JS naudingosios apkrovos gali padėti tai padaryti. [Sužinokite daugiau](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Pagrindinės grupės veikimo sutrumpinimas"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Sutrumpinamas pagrindinės grupės veikimas"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Norint pasiekti daugiausia naudotojų, svetainės turi veikti visose svarbiausiose naršyklėse. [Sužinokite daugiau](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Svetainė veikia skirtingose naršyklėse"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Užtikrinkite, kad atskiri puslapiai būtų susiejami giliąja nuoroda naudojant URL ir kad URL yra unikalūs pagal bendrinimo visuomeninėje medijoje tikslą. [Sužinokite daugiau](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Kiekvienas puslapis turi URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Palietus ekraną perėjimai turi būti sklandūs, net esant lėtam interneto ryšiui. Tai labai svarbu, kad naudotojas tinkamai suvoktų našumą. [Sužinokite daugiau](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Neatrodo, kad puslapio perėjimai būtų blokuojami tinklo"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Įvertinta įvesties delsa yra įvertintas laikas milisekundėmis, per kurį programa atsako į naudotojo įvestį per labiausiai užimtas puslapio įkėlimo 5 sekundes. Jei delsa ilgesnė nei 50 ms, naudotojams gali atrodyti, kad programa veikia lėtai. [Sužinokite daugiau](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Įvertinta įvesties delsa"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Pirmas turiningas žymėjimas nurodo laiką, kada pažymimas pirmasis tekstas ar vaizdas. [Sužinokite daugiau](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Pirmasis „Contentful“ parodymas"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Pirmas centrinio procesoriaus neaktyvumo laikas nurodo pirmą kartą, kai pagrindinė puslapio grupė yra pakankamai neaktyvi, kad galėtų apdoroti įvestį. [Sužinokite daugiau](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Pirmas cent. procesoriaus laisvas laikas"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Pirmasis reikšmingas parodymas nurodo, kada parodomas pagrindinis puslapio turinys. [Sužinokite daugiau](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Pirmasis reikšmingas parodymas"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Laikas iki sąveikos yra vertė, nurodanti, kiek laiko reikia, kol puslapis tampa visiškai interaktyvus. [Sužinokite daugiau](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Laikas iki sąveikos"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Didžiausia potenciali naudotojų patiriama pirmosios įvesties delsa yra ilgiausios užduoties trukmė milisekundėmis. [Sužinokite daugiau](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maksimali potenciali pirmosios įvesties delsa"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Greičio rodiklis parodo, kaip greitai pavaizduojamas puslapio turinys. [Sužinokite daugiau](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Greičio rodiklis"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Visų laikotarpių tarp PTŽ ir laiko iki sąveikos suma milisekundėmis, kai užduoties atlikimo laikas viršija 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Bendras blokavimo laikas"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Abipusis tinklo laikas (RTT) turi didelės įtakos našumui. Didelė RTT į šaltinį vertė nurodo, kad arčiau naudotojo esantys serveriai galėtų padidinti našumą. [Sužinokite daugiau](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Abipusis tinklo laikas"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Serverio delsa gali turėti įtakos žiniatinklio našumui. Didelė šaltinio serverio delsa nurodo, kad serveris per daug apkrautas arba mažas vidinės pusės našumas. [Sužinokite daugiau](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Serverio vidinės pusės delsa"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Pagalbinis „JavaScript“ failas įgalina žiniatinklio programą veikti patikimai nenuspėjamomis tinklo sąlygomis. [Sužinokite daugiau](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "Kai neprisijungta prie interneto, `start_url` neatsako rodydamas klaidos kodą 200."
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "Kai neprisijungta prie interneto, `start_url` atsako rodydamas klaidos kodą 200."
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "„Lighthouse“ nepavyko nuskaityti `start_url` iš aprašo. Dėl to `start_url` buvo laikomas dokumento URL. Klaidos pranešimas: „{manifestWarning}“."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Viršijo biudžetą"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Tinklo užklausų kiekis ir dydis neturi viršyti tikslinių verčių, nustatytų našumo biudžete. [Sužinokite daugiau](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 užklausa}one{# užklausa}few{# užklausos}many{# užklausos}other{# užklausų}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Našumo biudžetas"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Jei jau nustatėte HTTPS, būtinai peradresuokite visą HTTP srautą į HTTPS, kad visi naudotojai galėtų naudotis saugiomis žiniatinklio funkcijomis. [Sužinokite daugiau](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nenukreipia HTTP srauto į HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Nukreipia HTTP srautą į HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Peradresuojant puslapio įkėlimo delsos laikas dar labiau pailgėja. [Sužinokite daugiau](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Venkite kelių puslapio peradresavimų"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Kad nustatytumėte puslapio išteklių kiekio ir dydžio biudžetus, pridėkite biudžeto .json failą. [Sužinokite daugiau](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 užklausa • {byteCount, number, bytes} KB}one{# užklausa • {byteCount, number, bytes} KB}few{# užklausos • {byteCount, number, bytes} KB}many{# užklausos • {byteCount, number, bytes} KB}other{# užklausų • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Pasistenkite neteikti daug užklausų ir neperkelti daug duomenų"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Standartizuotos nuorodos siūlo, kurį URL rodyti paieškos rezultatuose. [Sužinokite daugiau](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Keli nesuderinami URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Nukreipia į kitą domeną ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Negaliojantis URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Nukreipia į kitą „`hreflang`“ vietą ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Susijęs URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Nukreipiama į domeno šakninį URL (pagrindinį puslapį) vietoje atitinkamo turinio puslapio"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumente nėra tinkamo atributo „`rel=canonical`“"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumente yra tinkamas atributas „`rel=canonical`“"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Mažesnis nei 12 piks. šriftas yra per mažas, kad būtų įskaitomas, todėl mobiliuosius įrenginius naudojantys lankytojai turi keisti mastelį suėmę pirštais, kad galėtų perskaityti. Pasistenkite, kad daugiau nei 60 proc. puslapio teksto šrifto dydis būtų 12 piks. arba didesnis. [Sužinokite daugiau](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} aiškaus teksto"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Tekstas neįskaitomas, nes nėra mobiliųjų įrenginių ekranams optimizuotos peržiūros srities metažymos"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} teksto yra per mažo dydžio (atsižvelgiant į pavyzdį – {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumente naudojami neįskaitomo dydžio šriftai"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumente naudojami aiškaus dydžio šriftai"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "„hreflang“ nuorodos nurodo paieškos varikliams, kokią puslapio versiją jie turėtų pateikti paieškos rezultatuose pagal nurodytą kalbą ar regioną. [Sužinokite daugiau](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumente nėra tinkamo atributo „`hreflang`“"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumente yra tinkamas atributas „`hreflang`“"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Puslapiai, kurių HTTP būsenos kodų nepavyko pateikti, gali būti indeksuojami netinkamai. [Sužinokite daugiau](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Nepavyko pateikti puslapio HTTP būsenos kodo"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Sėkmingai pateiktas puslapio HTTP būsenos kodas"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Paieškos varikliai negali įtraukti puslapių į paieškos rezultatus, jei neturi leidimo jų tikrinti. [Sužinokite daugiau](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Puslapio indeksavimas blokuojamas"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Puslapio indeksavimas nėra užblokuotas"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Pagal aprašomąjį nuorodų tekstą paieškos varikliai gali lengviau suprasti jūsų turinį. [Sužinokite daugiau](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Rasta 1 nuoroda}one{Rasta # nuoroda}few{Rastos # nuorodos}many{Rasta # nuorodos}other{Rasta # nuorodų}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Nuorodose nėra aprašomojo teksto"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Nuorodose yra aprašomojo teksto"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Paleiskite [struktūrinių duomenų bandymo įrankį](https://search.google.com/structured-data/testing-tool/) ir [„Structured Data Linter“](http://linter.structured-data.org/), kad būtų patvirtinti struktūriniai duomenys. [Sužinokite daugiau](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Struktūriniai duomenys tinkami"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Norint glaustai apibendrinti puslapio turinį, į paieškos rezultatus galima įtraukti metaaprašų. [Sužinokite daugiau](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Nepateiktas aprašomasis tekstas."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumente nėra metaaprašo"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumente yra metaaprašas"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Paieškos varikliai negali indeksuoti papildinių turinio ir daug įrenginių riboja papildinius arba jų nepalaiko. [Sužinokite daugiau](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumente naudojami papildiniai"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumente vengiama papildinių"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Jei failas „robots.txt“ netinkamai suformatuotas, tikrintuvai gali nesuprasti, kaip norite tikrinti ar indeksuoti svetainę. [Sužinokite daugiau](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Pateikus „robots.txt“ užklausą gauta HTTP būsena: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Rasta 1 klaida}one{Rasta # klaida}few{Rastos # klaidos}many{Rasta # klaidos}other{Rasta # klaidų}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "„Lighthouse“ nepavyko atsisiųsti failo robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Failas robots.txt netinkamas"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt tinkamas"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktyvūs elementai, pvz., mygtukai ir nuorodos, turi būti pakankamai dideli (48 x 48 piks.) ir aplink juos turi būti pakankamai vietos, kad būtų galima lengvai paliesti ir kad jie nepersidengtų su kitais elementais. [Sužinokite daugiau](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} tinkamo dydžio liečiamų objektų"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Liečiami objektai per maži, nes nėra mobiliųjų įrenginių ekranams optimizuotos peržiūros srities metažymos"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Liečiami objektai netinkamo dydžio"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Persidengiantis objektas"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Liečiamas objektas"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Liečiami objektai tinkamo dydžio"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Pagalbinis „JavaScript“ failas – tai technologija, įgalinanti jūsų programą naudoti daug laipsniškosios žiniatinklio programos funkcijų, pvz., naudoti neprisijungus, pridėti prie pagrindinio ekrano ar naudoti iš karto gaunamus pranešimus. [Sužinokite daugiau](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Šis puslapis valdomas naudojant pagalbinį „JavaScript“ failą, tačiau `start_url` nerasta, nes aprašo nepavyko analizuoti kaip galiojančio JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Šs puslapis valdomas naudojant pagalbinį „JavaScript“ failą, tačiau `start_url` ({startUrl}) nepatenka į pagalbinio „JavaScript“ failo aprėptį ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Šis puslapis valdomas naudojant pagalbinį „JavaScript“ failą, tačiau neaptikta `start_url`, nes neįkeltas joks aprašas."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Šiame pradiniame puslapyje yra vienas ar daugiau pagalbinių „JavaScript“ failų, tačiau puslapis ({pageUrl}) neįtrauktas."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Neregistruojamas pagalbinis „JavaScript“ failas, naudojamas puslapiams ir `start_url` valdyti"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registruojamas pagalbinis „JavaScript“ failas, naudojamas puslapiams ir `start_url` valdyti"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Teminis prisistatymo langas užtikrina kokybišką patirtį naudotojui paleidžiant jūsų programą iš pagrindinio ekrano. [Sužinokite daugiau](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nesukonfigūruota tinkintam prisistatymo langui"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Sukonfigūruota tinkintam prisistatymo langui"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Naršyklės adreso juostos temos negalima pakeisti taip, kad atitiktų svetainės temą. [Sužinokite daugiau](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nenustatoma adreso juostos temos spalva."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Nustatoma adreso juostos temos spalva."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Pagrindinės grupės blokavimo laikas"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Trečioji šalis"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Trečiosios šalies kodas gali smarkiai paveikti įkėlimo našumą. Apribokite trečiosios šalies teikėjų skaičių ir pabandykite įkelti trečiosios šalies kodą, kai puslapis bus įkeltas. [Sužinokite daugiau](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Trečiosios šalies kodas {timeInMs, number, milliseconds} ms užblokavo pagrindinę grupę"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Sumažina trečiosios šalies kodo poveikį"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Trečiosios šalies naudojimas"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Laikas iki pirmojo baito nurodo laiką, per kurį serveris atsako. [Sužinokite daugiau](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Šakninio dokumento įkėlimas užtruko {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Serverio atsako laiko sutrumpinimas (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Serverio atsako laikas yra trumpas (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trukmė"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Pradžios laikas"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipas"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Apsvarstykite galimybę apdoroti programą naudojant naudotojo laiko API ir įvertinti programos realų našumą, kai naudotojas naudoja pagrindines funkcijas. [Sužinokite daugiau](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 naudotojo laikas}one{# naudotojo laikas}few{# naudotojo laikai}many{# naudotojo laiko}other{# naudotojo laikų}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Naudotojo laiko žymės ir matavimas"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Rasta atributo „{securityOrigin}“ išankstinio sujungimo nuoroda „<link>“, bet naršyklė jos nenaudojo. Patikrinkite, ar atributas „`crossorigin`“ naudojamas tinkamai."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Apsvarstykite galimybę pridėti `preconnect` arba `dns-prefetch` ištekliaus nurodymus, kad ryšys su svarbiais trečiųjų šalių šaltiniais būtų užmezgamas iš anksto. [Sužinokite daugiau](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Iš anksto prisijunkite prie reikiamų šaltinių"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Rasta atributo „{preloadURL}“ išankstinio įkėlimo nuoroda „<link>“, bet naršyklė jos nenaudojo. Patikrinkite, ar atributas „`crossorigin`“ naudojamas tinkamai."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Apsvarstykite galimybę naudoti „`<link rel=preload>`“ ir suteikti pirmenybę gaunamiems ištekliams, kurių užklausos šiuo metu teikiamos vėliau įkeliant puslapį. [Sužinokite daugiau](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Iš anksto įkelkite svarbiausias užklausas"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Pridedama žyma `<meta name=\"viewport\">`, siekiant optimizuoti programą mobiliųjų ekranams. [Sužinokite daugiau](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Žyma `<meta name=\"viewport\">` nerasta"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nėra žymos `<meta name=\"viewport\">` su `width` arba `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Yra žyma `<meta name=\"viewport\">` su `width` arba `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Kai „JavaScript“ išjungta, jūsų programoje turėtų būti rodoma turinio, net jei tai tik įspėjimas naudotojui, kad „JavaScript“ būtina norint naudoti programą. [Sužinokite daugiau](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Puslapio pagrindinėje dalyje turi būti pateikta turinio, jei scenarijus nepasiekiamas."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Atsarginis turinys neteikiamas, kai „JavaScript“ nepasiekiama"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Yra turinio, kai „JavaScript“ nepasiekiama"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Jei kuriate laipsniškąją žiniatinklio programą, apsvarstykite galimybę naudoti pagalbinį „JavaScript“ failą, kad programa veiktų neprisijungus. [Sužinokite daugiau](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Kai neprisijungta prie interneto, dabartinis puslapis neatsako rodydamas klaidos kodą 200."
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Kai neprisijungta prie interneto, dabartinis puslapis atsako rodydamas klaidos kodą 200."
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Puslapis gali būti neįkeliamas neprisijungus, nes bandomasis URL ({requested}) peradresavo į {final}. Išbandykite antrąjį URL tiesiogiai."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Tai yra galimybės, skirtos pagerinti ARIA naudojimą programoje. Jos gali pagerinti pagalbinių technologijų, pvz., ekrano skaitytuvų, naudotojų patirtį."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Tai yra galimybės, skirtos alternatyviam garso ir vaizdo įrašų turiniui teikti. Tai gali pagerinti klausos ar regėjimo sutrikimų turinčių naudotojų patirtį."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Garsas ir vaizdas"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Šie elementai paryškina dažniausiai naudojamus pritaikomumo geriausios praktikos metodus."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Geriausia praktika"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Atlikę šias patikras sužinosite, kaip galite [geriau pritaikyti žiniatinklio programą](https://developers.google.com/web/fundamentals/accessibility). Automatiškai galima aptikti tik dalį pritaikomumo problemų, todėl rekomenduojama atlikti ir neautomatinį tikrinimą."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Šie elementai apima sritis, kurių automatinio bandymo įrankis negali aprėpti. Mūsų vadove sužinokite daugiau apie tai, kaip [atlikti pritaikomumo peržiūrą](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Pritaikomumas"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Tai yra galimybės, kaip pagerinti turinio skaitomumą."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrastas"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Tai yra galimybės, skirtos pagerinti, kaip skirtingų lokalių naudotojai interpretuoja jūsų turinį."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizavimas ir lokalizavimas"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Tai yra galimybės, skirtos pagerinti programos valdiklių semantiką. Tai gali pagerinti pagalbinių technologijų, pvz., ekrano skaitytuvų, naudotojų patirtį."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Pavadinimai ir etiketės"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Tai yra galimybės, skirtos pagerinti naršymą klaviatūra programoje."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Naršymas"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Tai yra galimybės, skirtos pagerinti lentelėse ar sąrašuose pateiktų duomenų skaitymą naudojant pagalbines technologijas, pvz., ekrano skaitytuvą."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Lentelės ir sąrašai"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Geriausios praktikos pavyzdžiai"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Nuo kategorijoje „Našumas“ nustatyto biudžeto priklauso svetainės našumas."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Biudžetai"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Daugiau informacijos apie programos našumą. Šie skaičiai [tiesiogiai nepaveikia](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) našumo įvertinimo."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Svarbiausias našumo rodiklis – kaip greitai taškai pateikiami ekrane. Svarbiausia metrika: pirmasis „Contentful“ parodymas, pirmasis reikšmingas parodymas"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Pirmojo parodymo patobulinimai"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Pasinaudojus šiais pasiūlymais puslapis gali būti įkeliamas greičiau. Tai [tiesiogiai nepaveiks](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) našumo įvertinimo."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Galimybės"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrika"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Pagerinkite bendrą įkėlimo našumą, kad puslapis reaguotų ir būtų parengtas naudoti kuo greičiau. Svarbiausia metrika: laikas iki sąveikos, greičio rodiklis"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Bendri patobulinimai"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Našumas"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Per šias patikras vertinami laipsniškosios žiniatinklio programos aspektai. [Sužinokite daugiau](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Šios patikros būtinos pagal pradinį [LŽP kontrolinį sąrašą](https://developers.google.com/web/progressive-web-apps/checklist), tačiau „Lighthouse“ jų neatlieka automatiškai. Jos neturi įtakos jūsų rezultatui, tačiau svarbu, kad patvirtintumėte patys."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Laipsniškoji žiniatinklio programa"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Sparčios ir patikimos"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Galima įdiegti"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizuota PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Šios patikros užtikrina, kad jūsų puslapis optimizuotas paieškos variklio rezultatams reitinguoti. Yra papildomų veiksnių, galinčių paveikti paieškos reitingavimą, kurių „Lighthouse“ netikrina. [Sužinokite daugiau](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Paleiskite šias papildomas patvirtinimo priemones svetainėje, kad patikrintumėte papildomus PVO geriausios praktikos metodus."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "PVO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatuokite HTML taip, kad tikrintuvai galėtų geriau suprasti programos turinį."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Geriausios turinio praktikos pavyzdžiai"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Kad programa būtų rodoma paieškos rezultatuose, tikrintuvams reikalinga prieiga prie jos."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Tikrinimas ir indeksavimas"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Įsitikinkite, kad puslapiai yra pritaikyti mobiliesiems, kad naudotojams nereikėtų suėmus artinti ar keisti mastelio norint perskaityti puslapių turinį. [Sužinokite daugiau](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Pritaikyta mobiliesiems"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Talpyklos TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Vietovė"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Pavadinimas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Užklausos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Ištekliaus tipas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Dydis"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Sugaištas laikas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Failų perkėlimo dydis"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Galima sutaupyti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Galima sutaupyti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Galima sutaupyti {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Galima sutaupyti {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokumentas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Šriftas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Vaizdas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Medija"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Kita"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Scenarijus"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} sek."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stiliaus failas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Trečioji šalis"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Iš viso"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Įkeliant puslapį kilo su pėdsako įrašymu susijusi problema. Dar kartą paleiskite „Lighthouse“. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Laukiant, kol bus inicijuotas derintuvės protokolo ryšys, baigėsi skirtasis laikas."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Įkeliant puslapį „Chrome“ nesukūrė ekrano kopijų. Užtikrinkite, kad puslapyje yra matomo turinio, tada pabandykite iš naujo paleisti „Lighthouse“. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS serveriams nepavyko nustatyti pateikto domeno."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Įvyko su reikiamo ištekliaus „{artifactName}“ rinkimo priemone susijusi klaida: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Įvyko vidinės „Chrome“ klaida. Iš naujo paleiskite „Chrome“ ir pabandykite iš naujo paleisti „Lighthouse“."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Reikiamo ištekliaus „{artifactName}“ rinkimo priemonė nebuvo paleista."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "„Lighthouse“ nepavyko patikimai įkelti puslapio, kurio užklausą pateikėte. Įsitikinkite, kad testuojate tinkamą URL ir kad serveris tinkamai atsako į visas užklausas."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "„Lighthouse“ nepavyko patikimai įkelti URL, kurio užklausą pateikėte, nes puslapis nebeatsako."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Pateiktame URL nėra tinkamo saugos sertifikato: {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "„Chrome“ neleido įkelti puslapio ir buvo parodytas tarpinis ekranas. Įsitikinkite, kad tikrinate tinkamą URL ir kad serveris tinkamai atsako į visas užklausas."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "„Lighthouse“ nepavyko patikimai įkelti puslapio, kurio užklausą pateikėte. Įsitikinkite, kad tikrinate tinkamą URL ir kad serveris tinkamai atsako į visas užklausas. (Išsami informacija: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "„Lighthouse“ nepavyko patikimai įkelti puslapio, kurio užklausą pateikėte. Įsitikinkite, kad tikrinate tinkamą URL ir kad serveris tinkamai atsako į visas užklausas. (Būsenos kodas: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Puslapis buvo įkeliamas per ilgai. Pasinaudokite ataskaitoje pateiktomis galimybėmis ir sumažinkite puslapio įkėlimo laiką, tada pabandykite iš naujo paleisti „Lighthouse“. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Laukiama, kol „DevTools“ protokolo atsakymas viršys skirtąjį laiką. (Metodas: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Šaltinio turinio gavimas viršijo skirtąjį laiką"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Panašu, kad pateiktas URL netinkamas."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Rodyti patikras"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Pradinis naršymas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Didžiausia svarbiausio kelio delsa:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Klaida!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Ataskaitos klaida: nėra patikros informacijos"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratorijos duomenys"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[„Lighthouse“](https://developers.google.com/web/tools/lighthouse/) dabartinio puslapio analizė emuliuotame mobiliojo ryšio tinkle. Vertės yra apytikslės ir gali skirtis."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Papildomi elementai, kuriuos reikia patikrinti neautomatiškai"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Netaikoma"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Galimybė"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Numatomos santaupos"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Sėkmingos patikros"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Sutraukti fragmentą"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Išplėsti fragmentą"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Rodyti trečiųjų šalių išteklius"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Paleidžiant „Lighthouse“ kilo problemų."
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Vertės yra apytikslės ir gali skirtis. Našumo įvertinimas nustatomas [tik pagal šias metrikas](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Sėkmingos patikros, bet pateikta įspėjimų"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Įspėjimai: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Apsvarstykite galimybę įkelti savo GIF į paslaugą, kuri leis jį įterpti kaip HTML5 vaizdo įrašą."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Įdiekite [atidėtojo įkėlimo „WordPress“ papildinį](https://wordpress.org/plugins/search/lazy+load/), leidžiantį atidėti bet kokius ne ekraninius vaizdus, arba perjunkite į šią funkciją teikiančią temą. Be to, apsvarstykite galimybę naudoti [AMP papildinį](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Yra įvairių „WordPress“ papildinių, kuriuos naudodami galite [įterpti svarbių išteklių](https://wordpress.org/plugins/search/critical+css/) arba [atidėti mažiau svarbius šaltinius](https://wordpress.org/plugins/search/defer+css+javascript/). Atminkite, kad dėl šių papildinių teikiamo optimizavimo gali būti pažeistos jūsų temos ar papildinių funkcijos, todėl tikriausiai turėsite atlikti kodo pakeitimų."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Temos, papildiniai ir serverio specifikacijos – visa tai turi įtakos serverio atsako laikui. Galbūt vertėtų surasti geriau optimizuotą temą, atidžiai pasirinkti optimizavimo papildinį ir (arba) naujovinti serverį."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Apsvarstykite galimybę rodyti ištraukas įrašų sąrašuose (pvz., naudodami daugiau elementų žymą), sumažinti nurodytame puslapyje rodomų įrašų skaičių, suskaidyti ilgus įrašus į kelis puslapius arba naudoti komentarų atidėtojo įkėlimo papildinį."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Įvairūs [„WordPress“ papildiniai](https://wordpress.org/plugins/search/minify+css/) gali padėti svetainei sparčiau veikti sujungdami, sumažindami ar suglaudindami stilius. Be to, galbūt norėsite pasinaudoti kūrimo procesu, kad sumažintumėte iš anksto (jei tai įmanoma)."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Įvairūs [„WordPress“ papildiniai](https://wordpress.org/plugins/search/minify+javascript/) gali padėti svetainei sparčiau veikti sujungdami, sumažindami ar suglaudindami scenarijus. Be to, galbūt norėsite pasinaudoti kūrimo procesu, kad sumažintumėte iš anksto (jei tai įmanoma)."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Apsvarstykite galimybę sumažinti [„WordPress“ papildinių](https://wordpress.org/plugins/), įkeliančių nenaudojamą CSS kalbą jūsų puslapyje, skaičių arba juos pakeisti. Kad nustatytumėte papildinius, pridedančius nesusijusios CSS kalbos, pabandykite vykdyti [kodo aprėpties procesą](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) naudodami „Chrome DevTools“. Susijusią temą / papildinį galite nustatyti pagal stiliaus failo URL. Ieškokite papildinių, kurių sąraše pateikta daug stiliaus failų, kurių kodo aprėptyje yra daug raudonos spalvos. Papildinys įtraukti stiliaus failą į eilę turėtų tik tokiu atveju, jei jis tikrai naudojamas puslapyje."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Apsvarstykite galimybę sumažinti [„WordPress“ papildinių](https://wordpress.org/plugins/), įkeliančių nenaudojamą „JavaScript“ jūsų puslapyje, skaičių arba juos pakeisti. Kad nustatytumėte papildinius, pridedančius nesusijusios JS, pabandykite vykdyti [kodo aprėpties procesą](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) naudodami „Chrome DevTools“. Susijusią temą / papildinį galite nustatyti pagal scenarijaus URL. Ieškokite papildinių, kurių sąraše pateikta daug scenarijų, kurių kodo aprėptyje yra daug raudonos spalvos. Papildinys įtraukti scenarijų į eilę turėtų tik tokiu atveju, jei jis tikrai naudojamas puslapyje."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Skaitykite apie [naršyklės saugojimo talpykloje funkciją sistemoje „WordPress“](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Apsvarstykite galimybę naudoti [vaizdų optimizavimo „WordPress“ papildinį](https://wordpress.org/plugins/search/optimize+images/), leidžiantį suglaudinti vaizdus išlaikant kokybę."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Įkelkite vaizdus tiesiai per [medijos biblioteką](https://codex.wordpress.org/Media_Library_Screen), kad būtų pasiekiami reikiami vaizdų dydžiai, tada įterpkite juos iš medijos bibliotekos arba naudokite vaizdų valdiklį, kad užtikrintumėte, jog naudojami optimalaus dydžio vaizdai (įskaitant tuos, kurie naudojami interaktyviems atskaitos taškams). Stenkitės nenaudoti vaizdų „`Full Size`“, nebent galima naudoti tokių matmenų vaizdus. [Sužinokite daugiau](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Galite įgalinti teksto glaudinimą žiniatinklio serverio konfigūracijoje."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Apsvarstykite galimybę naudoti [papildinį](https://wordpress.org/plugins/search/convert+webp/) arba paslaugą, kuri automatiškai konvertuotų įkeltus vaizdus į optimalius formatus."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lv.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lv.json
new file mode 100644
index 00000000000..5056775378a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/lv.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Piekļuves atslēgas ļauj lietotājiem ātri pievērsties lapas daļai. Lai navigācija būtu pareiza, katrai piekļuves atslēgai ir jābūt unikālai. [Uzziniet vairāk](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Atribūtu `[accesskey]` vērtības nav unikālas"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Atribūta “`[accesskey]`” vērtības ir unikālas"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Katrs ARIA elements “`role`” atbalsta konkrētu atribūtu “`aria-*`” apakškopu. Ja tie netiek norādīti pareizi, atribūti “`aria-*`” nav derīgi. [Uzziniet vairāk](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atribūti `[aria-*]` neatbilst savām lomām"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atribūti `[aria-*]` atbilst savām lomām"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Dažām ARIA lomām ir obligāti atribūti, kas ekrāna lasītājiem norāda elementa statusu. [Uzziniet vairāk](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Elementiem `[role]` nav visu pieprasīto atribūtu `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Visiem elementiem `[role]` ir nepieciešamie atribūti `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Dažām ARIA vecāklomām ir jāietver konkrētas pakārtotās lomas, lai varētu nodrošināt pieejamības funkcijas. [Uzziniet vairāk](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementos ar ARIA lomu `[role]`, kuru pakārtotajiem elementiem ir jāsatur konkrēts vienums `[role]`, trūkst dažu vai visu šo obligāto pakārtoto elementu."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementos ar ARIA lomu `[role]`, kuru pakārtotajiem elementiem ir jāsatur konkrēts vienums `[role]`, ir visi obligātie pakārtotie elementi."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Dažām ARIA pakārtotajām lomām ir jābūt ietvertām konkrētās vecāklomās, lai varētu nodrošināt pieejamības funkcijas. [Uzziniet vairāk](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Atribūts `[role]` neietver pieprasīto vecākelementu"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Atribūtā `[role]` ir ietverts pieprasītais vecākelements"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA lomām ir nepieciešamas derīgas vērtības, lai varētu nodrošināt pieejamības funkcijas. [Uzziniet vairāk](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Atribūta `[role]` vērtības nav derīgas"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Atribūta `[role]` vērtības ir derīgas"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Palīgtehnoloģijas, piemēram, ekrāna lasītāji, nevar interpretēt ARIA atribūtus ar nederīgām vērtībām. [Uzziniet vairāk](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atribūtiem `[aria-*]` nav derīgu vērtību"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atribūtiem `[aria-*]` ir derīgas vērtības"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Palīgtehnoloģijas, piemēram, ekrāna lasītāji, nevar interpretēt ARIA atribūtus ar nederīgiem nosaukumiem. [Uzziniet vairāk](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atribūti `[aria-*]` nav derīgi vai ir kļūdaini uzrakstīti"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atribūti `[aria-*]` ir derīgi un pareizi uzrakstīti"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Izmantojot subtitrus, nedzirdīgi lietotāji vai lietotāji ar dzirdes traucējumiem var piekļūt audio elementiem, kuri nodrošina būtisku informāciju, piemēram, runātājus, sarunu saturu, kā arī citu informāciju, kas nav sarunas. [Uzziniet vairāk](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementos `<audio>` trūkst elementu `<track>` ar parametru `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementi `<audio>` ietver elementu `<track>` ar parametru `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Nederīgi elementi"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Ja pogai nav atbilstoša nosaukuma, ko var nolasīt ekrāna lasītāji, tad ekrāna lasītāji to atskaņo kā “Poga”. Tādējādi lietotāji, kuri izmanto ekrāna lasītājus, nesapratīs tās nozīmi. [Uzziniet vairāk](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Pogām nav piekļūstamības principiem atbilstošu nosaukumu"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Pogām ir piekļūstamības principiem atbilstoši nosaukumi"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Ja nodrošināsiet iespēju apiet atkārtotu saturu, tastatūras lietotāji varēs labāk pārvietoties lapā. [Uzziniet vairāk](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Lapā nav virsraksta, izlaišanas saites vai orientieru daļas"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Lapā ir virsraksts, izlaišanas saite vai orientieru daļa"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Daudziem lasītājiem ir grūti vai pat neiespējami izlasīt tekstu ar zemu kontrastu. [Uzziniet vairāk](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Fona un priekšplāna krāsu kontrasta koeficients nav pietiekams."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Fona un priekšplāna krāsām ir pietiekams kontrasta koeficients"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Ja definīciju saraksti nav marķēti pareizi, ekrāna lasītāju atskaņotais saturs var būt mulsinošs vai neprecīzs. [Uzziniet vairāk](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Atribūtā `<dl>` nav ietvertas tikai pareizā secībā sakārtotas elementu `<dt>` un `<dd>` grupas, elements `<script>` vai elements `<template>`"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Atribūtā `<dl>` ir ietvertas tikai pareizā secībā sakārtotas elementu `<dt>` un `<dd>` grupas, elements `<script>` vai elements `<template>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Definīciju saraksta vienumiem (`<dt>` un `<dd>`) ir jābūt ietvertiem vecākelementā `<dl>`, lai ekrāna lasītāji tos varētu pareizi atskaņot. [Uzziniet vairāk](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Definīciju saraksta vienumi netiek apvienoti elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Definīciju saraksta vienumi tiek apvienoti elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Nosaukums sniedz lapas kopsavilkumu ekrāna lasītāja lietotājiem, un meklētājprogrammas lietotāji ļoti paļaujas uz to, lai noteiktu, vai lapa ir atbilstoša viņu meklēšanai. [Uzziniet vairāk](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumentā nav elementa `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumentā ir ietverts elements `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "ID atribūta vērtībai ir jābūt unikālai, lai palīgtehnoloģijas neizlaistu citas instances. [Uzziniet vairāk](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atribūti `[id]` lapā nav unikāli"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atribūti `[id]` lapā ir unikāli"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Ekrāna lasītāji izmanto ietvaru nosaukumus, lai raksturotu ietvaru saturu. [Uzziniet vairāk](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementiem `<frame>` vai `<iframe>` nav nosaukuma"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementiem `<frame>` vai `<iframe>` ir nosaukums"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ja lapā nav norādīts atribūts “lang”, ekrāna lasītājā tiek pieņemts, ka lapas saturs ir noklusējuma valodā, kuru lietotājs izvēlējās, iestatot ekrāna lasītāju. Ja lapas saturs nav noklusējuma valodā, iespējams, ekrāna lasītājs tekstu neatskaņos pareizi. [Uzziniet vairāk](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Tagam `<html>` nav derīga atribūta `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Tagam `<html>` ir atribūts `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ja norādīsiet derīgu [BCP 47 valodu](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ), ekrāna lasītāji pareizi atskaņos tekstu. [Uzziniet vairāk](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Tagam `<html>` nav derīgas vērtības tā atribūtam `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Elementam `<html>` ir derīga tā atribūta `[lang]` vērtība"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informatīvajiem elementiem ir nepieciešams īss, aprakstošs alternatīvais teksts. Dekoratīvajiem elementiem alternatīvo atribūtu var atstāt tukšu. [Uzziniet vairāk](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Attēlu elementiem nav atribūtu `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Attēlu elementiem ir atribūti `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Ja attēls tiek izmantots kā poga `<input>`, alternatīvais teksts var sniegt informāciju par pogas nozīmi lietotājiem, kuri izmanto ekrāna lasītāju. [Uzziniet vairāk](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementiem `<input type=\"image\">` nav teksta `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementi `<input type=\"image\">` ietver tekstu `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Ja norādīsiet iezīmes, palīgtehnoloģijas, piemēram, ekrāna lasītāji, varēs pareizi atskaņot veidlapu vadīklas. [Uzziniet vairāk](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Veidlapu elementiem nav saistīto iezīmju"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Veidlapu elementiem ir saistītas iezīmes"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabulā, kas tiek izmantota izkārtojumam, nav ieteicams iekļaut datu elementus, piemēram, elementus “th” vai “caption”, kā arī atribūtu “summary”, jo tā var mulsināt lietotājus, kuri izmanto ekrāna lasītājus. [Uzziniet vairāk](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Attēlojumam paredzētajos elementos `<table>` tiek izmantots atribūts `<th>`, `<caption>` vai `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Attēlojumam paredzētajos elementos `<table>` netiek izmantots atribūts `<th>`, `<caption>` vai `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Atšķirams, unikāls un aktivizējams saites teksts (un alternatīvais teksts attēliem, kas tiek izmantoti kā saites) nodrošina labākas navigācijas iespējas lietotājiem, kuri izmanto ekrāna lasītājus. [Uzziniet vairāk](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Saitēm nav atšķirama nosaukuma"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Saitēm ir atšķirams nosaukums"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Ekrāna lasītāji nolasa sarakstus īpašā veidā. Ja saraksta struktūra ir pareiza, tiek atvieglota satura atskaņošana ekrāna lasītājā. [Uzziniet vairāk](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Saraksti neietver tikai tos elementus `<li>` un skriptus, kas atbalsta elementus (`<script>` un `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Saraksti ietver tikai elementus `<li>` un skriptus, kas atbalsta elementus (`<script>` un `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Lai ekrāna lasītāji varētu pareizi atskaņot saraksta vienumus (`<li>`), tiem ir jābūt ietvertiem vecākelementos `<ul>` vai `<ol>`. [Uzziniet vairāk](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Saraksta vienumi (`<li>`) nav ietverti vecākelementos `<ul>` vai `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Saraksta vienumi (`<li>`) ir ietverti vecākelementos `<ul>` vai `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Lietotāji negaida, ka lapa tiks automātiski atsvaidzināta, un tādējādi atkal tiks pāriets uz lapas augšdaļu. Tas var būt kaitinoši vai mulsinoši. [Uzziniet vairāk](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumentā tiek izmantots metatags `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumentā netiek izmantots metatags “`<meta http-equiv=\"refresh\">`”"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Ja tālummaiņa ir atspējota, lietotājiem ar redzes traucējumiem, kuri izmanto ekrāna palielinājumu, ir grūtības piekļūt tīmekļa lapas saturam. [Uzziniet vairāk](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Parametrs `[user-scalable=\"no\"]` tiek lietots elementā `<meta name=\"viewport\">`, vai atribūts `[maximum-scale]` ir mazāks par 5"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Atribūts `[user-scalable=\"no\"]` netiek izmantots elementā `<meta name=\"viewport\">`, un atribūts `[maximum-scale]` nav mazāks par 5"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Ekrāna lasītāji nevar tulkot saturu, kas nav teksts. Ja elementiem `<object>` pievienosiet alternatīvo tekstu, ekrāna lasītāji varēs lietotājiem paziņot teksta nozīmi. [Uzziniet vairāk](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementiem `<object>` nav teksta `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementi `<object>` ietver tekstu `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Ja vērtība ir lielāka par “0”, navigācijas secība ir noteikta. Lai gan tehniski šis risinājums ir derīgs, bieži vien tas mulsina lietotājus, kuri izmanto palīgtehnoloģijas. [Uzziniet vairāk](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Dažiem elementiem atribūta “`[tabindex]`” vērtība ir lielāka par 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nevienam elementam nav atribūta `[tabindex]` vērtības, kas augstāka par 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Ekrāna lasītāju funkcijas atvieglo pārvietošanos tabulās. Ja elementa `<td>` šūnās, kas izmanto atribūtu `[headers]`, ir atsauces tikai uz citām šūnām tajā pašā tabulā, tiek nodrošināta labāka pieredze lietotājiem, kuri izmanto ekrāna lasītājus. [Uzziniet vairāk](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Elementa `<table>` šūnās, kuras izmanto atribūtu `[headers]`, ir atsauces uz elementu `id`, kas netika atrasts tajā pašā tabulā."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Elementa `<table>` šūnās, kuras izmanto atribūtu `[headers]`, ir atsauces uz citām šūnām tajā pašā tabulā."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Ekrāna lasītāju funkcijas atvieglo pārvietošanos tabulās. Ja tabulu virsrakstos vienmēr ir atsauces uz citām šūnām, tas var nodrošināt labāku pieredzi lietotājiem, kuri izmanto ekrāna lasītājus. [Uzziniet vairāk](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementi `<th>` un elementi ar atribūtu `[role=\"columnheader\"/\"rowheader\"]` neietver to aprakstītās datu šūnas"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementi `<th>` un elementi ar atribūtu `[role=\"columnheader\"/\"rowheader\"]` ietver to aprakstītās datu šūnas"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ja elementos norādīsiet derīgu [BCP 47 valodu](https://www.w3.org/International/questions/qa-choosing-language-tags#question), ekrāna lasītājs pareizi atskaņos tekstu. [Uzziniet vairāk](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atribūtiem `[lang]` nav derīgas vērtības"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atribūtiem `[lang]` ir derīga vērtība"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Ja videoklipam ir subtitri, nedzirdīgi lietotāji un lietotāji ar dzirdes traucējumiem varēs vieglāk piekļūt informācijai. [Uzziniet vairāk](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementi `<video>` neietver elementu `<track>` ar parametru `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementi `<video>` ietver elementu `<track>` ar parametru `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audio aprakstos ir noderīga, videoklipos neiekļauta informācija, piemēram, sejas izteiksmes un ainas. [Uzziniet vairāk](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementi `<video>` neietver elementu `<track>` ar parametru `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementi `<video>` ietver elementu `<track>` ar parametru `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Lai iegūtu ideālu izskatu iOS ierīcē, lietotājiem pievienojot progresīvo tīmekļa lietotni sākuma ekrānam, definējiet atribūtu `apple-touch-icon`. Tam ir jānorāda uz necaurspīdīgu 192 pikseļu (vai 180 pikseļu) kvadrātveida PNG. [Uzziniet vairāk](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Netiek nodrošināts derīgs atribūts “`apple-touch-icon`”"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Atribūts “`apple-touch-icon-precomposed`” ir novecojis; ieteicams izmantot atribūtu “`apple-touch-icon`”."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Nodrošina derīgu atribūtu “`apple-touch-icon`”"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome paplašinājumi negatīvi ietekmē šīs lapas ielādes veiktspēju. Mēģiniet lapas pārbaudi veikt inkognito režīmā vai no Chrome profila bez paplašinājumiem."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Skripta novērtēšana"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Skriptu parsēšana"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Kopējais centrālā procesora laiks"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Ieteicams samazināt laiku, kas tiek izmantots JS parsēšanai, kompilēšanai un izpildei. Iespējams, konstatēsiet, ka ir noderīgi izmantot mazākas JS lietderīgās slodzes. [Uzziniet vairāk](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript izpildes laika samazināšana"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript izpildes laiks"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Lieli GIF attēli nav efektīvi animēta satura rādīšanai. Animācijām ieteicams izmantot MPEG4/WebM video, bet statiskiem attēliem — PNG/WebP, nevis GIF, lai samazinātu tīkla lietojumu (baitos). [Uzziniet vairāk](https://web.dev/efficient-animated-content)."
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Izmantojiet video failu formātus animētam saturam"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Lai samazinātu laiku līdz interaktivitātei, ārpus ekrāna attēlus un paslēptos attēlus ar lēnu ielādi ieteicams atlikt līdz visu svarīgo resursu ielādes pabeigšanai. [Uzziniet vairāk](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Ārpus ekrāna esošo attēlu atlikšana"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resursi bloķē jūsu lapas pirmo satura atveidojumu. Ieteicams rādīt svarīgos JS/CSS iekļautā veidā un atteikties no visiem nesvarīgajiem JS/stiliem. [Uzziniet vairāk](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Samaziniet resursus, kas bloķē renderēšanu"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Lielas tīkla lietderīgās slodzes izmaksā lietotājiem īstu naudu un ir cieši saistītas ar ilgu ielādes laiku. [Uzziniet vairāk](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Kopējais lielums bija {totalBytes, number, bytes} KB."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Pārāk lielas tīkla lietderīgās slodzes nepieļaušana"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Nepieļauj pārāk lielu tīkla lietderīgo slodzi"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Samazinot CSS failus, var samazināties tīkla lietderīgā slodze. [Uzziniet vairāk](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Samaziniet CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Samazinot JavaScript failus, var samazināties lietderīgās slodzes apjomi un skriptu parsēšanas laiks. [Uzziniet vairāk](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScript·samazināšana"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Noņemiet stila lapās kārtulas, kas nedarbojas, un atlieciet pirmajā ekrāna saturā neizmantotā CSS ielādi, lai samazinātu tīkla aktivitātes nevajadzīgi izmantoto baitu apjomu. [Uzziniet vairāk](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Noņemt neizmantoto CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Noņemiet neizmantoto JavaScript, lai samazinātu tīkla aktivitātes izmantoto baitu apjomu."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Noņemiet neizmantoto JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Iestatot ilgu kešatmiņas mūžu, lapas atkārtoti apmeklējumi varētu paātrināties. [Uzziniet vairāk](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Atrasts 1 resurss}zero{Atrasti # resursi}one{Atrasts # resurss}other{Atrasti # resursi}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Statisko elementu noteikšana, izmantojot efektīvu kešatmiņas politiku"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Efektīvas kešatmiņas politikas izmantošana statiskiem elementiem"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimizēti attēli tiek ielādēti ātrāk un izmanto mazāku mobilo datu apjomu. [Uzziniet vairāk](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Efektīva attēlu kodēšana"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Rādiet atbilstoša izmēra attēlus, lai tiktu izmantots mazāks mobilo datu apjoms un tiktu uzlabots ielādes laiks. [Uzziniet vairāk](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Atbilstoša lieluma attēli"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Lai samazinātu kopējo tīkla lietojumu (baitos), ieteicams izmantot saspiešanu (Gzip, Deflate vai Brotli). [Uzziniet vairāk](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Iespējojiet teksta saspiešanu"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Tādi attēlu formāti kā JPEG 2000, JPEG XR un WebP bieži ir veiksmīgāk saspiežami nekā PNG vai JPEG. Tas nozīmē ātrāku lejupielādi un mazāku datu patēriņu. [Uzziniet vairāk](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Rādiet attēlus nākamās paaudzes formātos"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ja lietotnes satura platums neatbilst skatvietas platumam, lietotne var nebūt optimizēta mobilo ierīču ekrāniem. [Uzziniet vairāk](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Skatvietas izmērs ({innerWidth} px) neatbilst loga izmēram ({outerWidth} px)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Satura izmērs nav pareizs, salīdzinot ar skatvietu"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Satura izmērs ir pareizs, salīdzinot ar skatvietu"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Metrika “Kritisko pieprasījumu ķēdes” tālāk parāda, kuri resursi ir ielādēti ar augstāko prioritāti. Lai uzlabotu lapas ielādi, ieteicams samazināt ķēžu garumu, samazināt resursu lejupielādes apjomu vai atlikt nevajadzīgo resursu lejupielādi. [Uzziniet vairāk](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Atrasta 1 ķēde}zero{Atrastas # ķēdes}one{Atrasta # ķēde}other{Atrastas # ķēdes}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Kritisko pieprasījumu dziļuma samazināšana"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Pārtraukšana/brīdinājums"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Rindiņa"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Novecojušas saskarnes API laika gaitā tiks noņemtas no pārlūkprogrammas. [Uzziniet vairāk](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Atrasts 1 brīdinājums}zero{Atrasti # brīdinājumi}one{Atrasts # brīdinājums}other{Atrasti # brīdinājumi}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Tiek izmantotas novecojušas saskarnes API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Nav atļautas novecojušas saskarnes API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Lietojumprogrammas kešatmiņa ir novecojusi. [Uzziniet vairāk](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Atrasts parametrs “{AppCacheManifest}”"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Tiek izmantota lietojumprogrammas kešatmiņa"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Netiek izmantota lietojumprogrammas kešatmiņa"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Ja norādāt DOCTYPE, pārlūkprogramma nevar pārslēgties uz saderības režīmu. [Uzziniet vairāk](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE nosaukumam jābūt mazo burtu virknei “`html`”."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumentam ir jāietver DOCTYPE."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Paredzamais publiskais ID būs tukša virkne."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Paredzamais sistēmas ID būs tukša virkne."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Lapai trūkst HTML DOCTYPE, tāpēc tiek aktivizēts saderības režīms"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Lapā ir HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elements"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistikas dati"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Vērtība"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Pārlūkprogrammas inženieri iesaka, lai lapā nebūtu vairāk par 1500 DOM elementiem. Ieteicams, lai koka dziļums nepārsniegtu 32 elementus un 60 bērnelementus/vecākelementus. Liels DOM elements var palielināt atmiņas lietojumu, radīt ilgākus [stila aprēķinus](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) un izraisīt [izkārtojuma plūduma sakārtošanu](https://developers.google.com/speed/articles/reflow). [Uzziniet vairāk](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elements}zero{# elementu}one{# elements}other{# elementi}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Pārāk lielu DOM izmēru nepieļaušana"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimālais DOM dziļums"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM elementu kopskaits"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimālais pakārtoto elementu skaits"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Nepieļauj pārāk lielus DOM izmērus"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Mērķis"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Pievienojiet parametru `rel=\"noopener\"` vai `rel=\"noreferrer\"` jebkurām ārējām saitēm, lai uzlabotu veiktspēju un novērstu drošības ievainojamību. [Uzziniet vairāk](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Saites uz savstarpējās izcelsmes galamērķiem nav drošas"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Saites uz savstarpējās izcelsmes galamērķiem ir drošas"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nevar noteikt enkura ({anchorHTML}) galamērķi. Ja to neizmantojat kā hipersaiti, apsveriet galamērķa noņemšanu (target=_blank)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Lietotājus mulsina un rada neuzticību vietnes, kas pieprasa viņu atrašanās vietu bez konteksta. Tā vietā ieteicams saistīt pieprasījumu ar lietotāja darbību. [Uzziniet vairāk](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Tiek pieprasīta ģeogrāfiskās atrašanās vietas noteikšanas atļauja lapas ielādei"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Netiek pieprasīta ģeogrāfiskās atrašanās vietas noteikšanas atļauja lapas ielādei"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versija"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Šajā lapā tika noteiktas visas JavaScript priekšgalsistēmas bibliotēkas. [Uzziniet vairāk](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Noteiktās JavaScript bibliotēkas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Lietotājiem, kuriem ir lēns savienojums, ārējie skripti, kas ir dinamiski ievadīti, izmantojot elementu “`document.write()`”, var ievērojami aizkavēt lapas ielādi. [Uzziniet vairāk](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Tiek izmantots elements “`document.write()`”"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Netiek izmantots elements “`document.write()`”"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Vislielākā nozīme"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bibliotēkas versija"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Ievainojamības gadījumu skaits"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Dažos trešo pušu skriptos var būt zināma drošības ievainojamība, kuras uzbrucēji viegli identificē un izmanto. [Uzziniet vairāk](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Konstatēta 1 ievainojamība}zero{Konstatētas # ievainojamības}one{Konstatēta # ievainojamība}other{Konstatētas # ievainojamības}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Ietver JavaScript priekšgalsistēmas bibliotēkas ar zināmu drošības ievainojamību"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Augsts"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Zems"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Vidējs"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Nepieļauj JavaScript priekšgalsistēmas bibliotēkas ar zināmām drošības ievainojamībām"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Lietotājus mulsina un viņiem rada neuzticību vietnes, kas pieprasa sūtīt paziņojumus bez konteksta. Tā vietā ieteicams saistīt pieprasījumu ar lietotāja žestiem. [Uzziniet vairāk](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Tiek pieprasīta paziņojumu atļauja lapas ielādei"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Netiek pieprasīta paziņojumu atļauja lapas ielādei"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Nederīgi elementi"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Paroles ielīmēšanas novēršana neatbilst labai drošības politikai. [Uzziniet vairāk](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Neļauj lietotājiem ielīmēt paroles laukos"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Ļauj lietotājiem ielīmēt paroles laukos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokols"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 piedāvā daudzas priekšrocības salīdzinājumā ar HTTP/1.1, tostarp binārās galvenes, multipleksēšanu un servera tiešu darbību (server push). [Uzziniet vairāk](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 pieprasījums nav parādīts, izmantojot HTTP/2}zero{# pieprasījumi nav parādīti, izmantojot HTTP/2}one{# pieprasījums nav parādīts, izmantojot HTTP/2}other{# pieprasījumi nav parādīti, izmantojot HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Netiek izmantots protokols HTTP/2 visiem tā resursiem"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Tiek izmantots protokols HTTP/2 tā resursiem"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Llai uzlabotu savas lapas ritināšanas veiktspēju, ieteicams atzīmēt pieskārienu un peles ritentiņa notikumu uztvērējus kā “`passive`”. [Uzziniet vairāk](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Netiek izmantoti pasīvie klausītāji, lai uzlabotu ritināšanas veiktspēju"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Tiek izmantoti pasīvie klausītāji, lai uzlabotu ritināšanas veiktspēju"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Apraksts"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Konsolē reģistrētās kļūdas norāda uz neatrisinātām problēmām. Tās var rasties no tīkla pieprasījuma kļūmēm un citām pārlūkprogrammas problēmām. [Uzzināt vairāk](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Pārlūkprogrammas kļūdas tika reģistrētas konsolē"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Neviena pārlūkprogrammas kļūda nav reģistrēta konsolē"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Izmantojiet fonta rādīšanas CSS funkciju, lai lietotāji tīmekļa fontu ielādes laikā varētu redzēt tekstu. [Uzziniet vairāk](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Visa teksta redzamības nodrošināšana tīmekļa fonta ielādes laikā"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Tīmekļa fonta ielādes laikā viss teksts paliek redzams"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse nevarēja automātiski pārbaudīt šī URL fonta attēlojuma vērtību: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Malu attiecība (faktiskā)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Malu attiecība (attēlotā)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Attēla parādīšanas izmēriem jāatbilst dabiskajai malu attiecībai. [Uzziniet vairāk](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Tiek rādīti attēli ar nepareizu malu attiecību"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Tiek rādīti attēli ar pareizu malu attiecību"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Nederīga attēla lieluma informācija: {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Pārlūkprogrammās var aktīvi rādīt lietotājiem uzvednes ar ierosinājumu pievienot jūsu lietotni sākuma ekrānam. Tādējādi var izdoties palielināt iesaisti. [Uzziniet vairāk](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Tīmekļa lietotnes manifests neatbilst instalējamības prasībām"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Tīmekļa lietotnes manifests atbilst instalējamības prasībām"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nedrošs URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Visas vietnes ir jāaizsargā ar protokolu HTTPS, pat ja tajās netiek apstrādāti sensitīvi dati. HTTPS neļauj iebrucējiem manipulēt vai pasīvi uztvert sakarus starp jūsu lietotni un lietotājiem, un tas ir HTTP/2 un daudzu jaunu tīmekļa platformu saskarņu API priekšnoteikums. [Uzziniet vairāk](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Noteikts 1 nedrošs pieprasījums}zero{Noteikti # nedroši pieprasījumi}one{Noteikts # nedrošs pieprasījums}other{Noteikti # nedroši pieprasījumi}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Netiek izmantots protokols HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Tiek izmantots protokols HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Ātra lapas ielāde, izmantojot mobilo datu tīklu, nodrošina labu pieredzi mobilo ierīču lietotājiem. [Uzziniet vairāk](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktīvais laiks: {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktīvs simulētā mobilajā tīklā {timeInMs, number, seconds} sekunžu laikā"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Lapas ielāde ir pārāk lēna — laiks līdz interaktivitātei pārsniedz 10 sekundes. Lai uzzinātu, kā uzlabot situāciju, skatiet sadaļā “Veiktspēja” norādītās iespējas un diagnostiku."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Lapas ielāde nav pietiekami ātra mobilajos tīklos"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Lapas ielāde ir pietiekami ātra mobilajos tīklos"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorija"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Ieteicams samazināt laiku, kas tiek izmantots JS parsēšanai, kompilēšanai un izpildei. Iespējams, konstatēsiet, ka ir noderīgi izmantot mazākas JS lietderīgās slodzes. [Uzziniet vairāk](https://web.dev/mainthread-work-breakdown)."
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Samaziniet galvenā pavediena darbu"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Galvenā pavediena darba samazināšana"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Lai sasniegtu pēc iespējas vairāk lietotāju, ieteicams izstrādāt vietnes, kas darbojas visās lielākajās pārlūkprogrammās. [Uzziniet vairāk](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Vietne darbojas dažādās pārlūkprogrammās"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Nodrošiniet, lai lietotāji varētu veidot un atvērt dziļās saites uz atsevišķām lapām, izmantojot URL. Turklāt URL jābūt unikāliem, lai varētu kopīgot lapas sociālajos saziņas līdzekļos. [Uzziniet vairāk](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Katrai lapai ir URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Ieteicams, lai, pieskaroties lietotnes elementiem, pārejas būtu ātras pat tad, ja tīkla darbība ir lēna. Šis ir galvenais faktors, kas nosaka to, kā lietotājs uztver veiktspēju. [Uzziniet vairāk](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Tīklā nerodas sajūta, ka lēna ielāde bloķētu pārejas starp lapām"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Paredzētais ievades latentums aptuveni norāda, pēc cik ilga laika (milisekundēs) uz lietotāja ievadi reaģēs jūsu lietotne aizņemtākajā lapas ielādes 5 s periodā. Ja latentums pārsniedz 50 ms, iespējams, lietotājiem liksies, ka jūsu lietotne strādā ar traucējumiem. [Uzziniet vairāk](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Paredzētais ievades latentums"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Metrika \"Pirmais satura marķējums\" atzīmē laiku, kad tiek marķēts pirmais teksts vai attēls. [Uzziniet vairāk](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Pirmais saturīgais satura atveidojums"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Metrika “Pirmā CPU dīkstāve” norāda laiku, kad lapas galvenais pavediens ir kļuvis pietiekami mazs, lai varētu apstrādāt ievadi. [Uzziniet vairāk](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Pirmā CPU dīkstāve"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Metrika “Pirmais nozīmīgais satura atveidojums” norāda, kad kļūst redzams lapas galvenais saturs. [Uzziniet vairāk](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Pirmais nozīmīgais satura atveidojums"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Laiks līdz interaktivitātei ir laika apjoms, kas nepieciešams, lai lapa kļūtu pilnībā interaktīva. [Uzziniet vairāk](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Laiks līdz interaktivitātei"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Iespējamā maksimālā pirmās ievades aizkave, ar ko jūsu lietotāji var saskarties, ir ilgākā uzdevuma ilgums milisekundēs. [Uzziniet vairāk](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks. potenciālā pirmā ievades aizkave"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Ātruma rādītājs norāda, cik ātri tiek parādīts lapas saturs. [Uzziniet vairāk](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Ātruma rādītājs"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Visu laika periodu summa (no PSM līdz “Laiks līdz interaktivitātei”), kad uzdevuma ilgums pārsniedz 50 ms (izteikts milisekundēs)."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Kopējais bloķēšanas laiks"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Tīkla aprites laiks (RTT) spēcīgi ietekmē veiktspēju. Ja aprites laiks uz sākumpunktu ir augsts, tas norāda, ka serveru veiktspēja, kas atrodas tuvāk lietotājam, var tikt uzlabota. [Uzziniet vairāk](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tīkla aprites laiks"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Tīmekļa veiktspēju var ietekmēt servera latentums. Ja sākumpunkta servera latentums ir augsts, tas norāda, ka serveris ir pārslogots vai arī tam ir vāja aizmugursistēmas veiktspēja. [Uzziniet vairāk](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Servera aizmugursistēmas latentums"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Izmantojot pakalpojumu skriptu, varat nodrošināt uzticamu tīmekļa lietotnes darbību neparedzamos tīkla apstākļos. [Uzziniet vairāk](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` bezsaistē nereaģē ar statusa kodu 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` bezsaistē reaģē ar statusa kodu 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Rīkā Lighthouse neizdevās no manifesta nolasīt `start_url`. Tāpēc tika pieņemts, ka `start_url` ir dokumenta URL. Kļūdas ziņojums: “{manifestWarning}”."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Pārsniegts budžets"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Saglabājiet tīkla pieprasījumu daudzumu un lielumu zem mērķiem, kas noteikti sniegtajā izpildes budžetā. [Uzziniet vairāk](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 pieprasījums}zero{# pieprasījumi}one{# pieprasījums}other{# pieprasījumi}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Izpildes budžets"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ja HTTPS protokols jau ir iestatīts, noteikti novirziet visu HTTP datplūsmu uz HTTPS, lai visiem lietotājiem iespējotu droša tīmekļa funkcijas. [Uzziniet vairāk](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP datplūsma netiek novirzīta uz HTTPS lapām"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP datplūsma tiek novirzīta uz HTTPS lapām"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Novirzīšana rada papildu aizkaves pirms lapas ielādes. [Uzziniet vairāk](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Nepieļaujiet vairākas lapas novirzīšanas"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Lai iestatītu lapas resursu daudzuma un lieluma budžetus, pievienojiet failu budget.json. [Uzziniet vairāk](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 pieprasījums • {byteCount, number, bytes} KB}zero{# pieprasījumu • {byteCount, number, bytes} KB}one{# pieprasījums • {byteCount, number, bytes} KB}other{# pieprasījumi • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Uzturiet nelielu pieprasījumu skaitu un mazu pārsūtīšanas failu lielumu"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanoniskās saites iesaka, kurus URL rādīt meklēšanas rezultātos. [Uzziniet vairāk](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Vairāki konfliktējoši URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Norāda uz citu domēnu ({url})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Nederīgs URL ({url})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Norāda uz citu atribūta “`hreflang`” atrašanās vietu ({url})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Atbilstošs URL ({url})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Ekvivalenta satura lapas vietā norāda uz domēna saknes piekļuves URL (sākumlapu)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumentā nav derīga atribūta “`rel=canonical`”"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumentam ir derīgs atribūts “`rel=canonical`”"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Fonta izmērs, kas ir mazāks par 12 pikseļiem, ir pārāk mazs, lai būtu salasāms, un mobilo ierīču lietotāji ir spiesti tuvināt tekstu, lai varētu to salasīt. Centieties, lai vairāk nekā 60% lapas teksta būtu vismaz 12 pikseļu vai lielāka izmēra. [Uzziniet vairāk](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} salasāms teksts"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Teksts nav salasāms, jo mobilo ierīču ekrāniem nav optimizēts skatvietas metatags."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} ir pārāk mazs teksta izmērs (pamatojoties uz {decimalProportionVisited, number, extendedPercent} paraugu)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumentā netiek izmantoti salasāmi fonta izmēri"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumentā izmantoti salasāmi fonta izmēri"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Atribūta “hreflang” saites norāda meklētājprogrammām, kuru lapas versiju iekļaut meklēšanas rezultātu sarakstā konkrētai valodai vai reģionam. [Uzziniet vairāk](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumentā nav derīga atribūta “`hreflang`”"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumentam ir derīgs atribūts “`hreflang`”"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Lapas ar nesekmīgu HTTP statusa kodu var tikt indeksētas nepareizi. [Uzziniet vairāk](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Lapai ir nesekmīgs HTTP statusa kods"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Lapai ir sekmīgs HTTP statusa kods"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Meklētājprogrammas nevar iekļaut jūsu lapas meklēšanas rezultātos, ja tām nav atļaujas pārmeklēt lapas. [Uzziniet vairāk](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Lapā ir bloķēta indeksēšana"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Lapa ir pieejama indeksēšanai"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Saites aprakstošais teksts palīdz meklētājprogrammām saprast jūsu saturu. [Uzziniet vairāk](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Atrasta 1 saite}zero{Atrastas # saites}one{Atrasta # saite}other{Atrastas # saites}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Saitēm nav aprakstoša teksta"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Saitēm ir aprakstošs teksts"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Lai validētu strukturētos datus, palaidiet [strukturētu datu testēšanas rīku](https://search.google.com/structured-data/testing-tool/) un rīku [Structured Data Linter](http://linter.structured-data.org/). [Uzziniet vairāk](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturētie dati ir derīgi"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Meklēšanas rezultātos var tikt iekļauti metaapraksti, lai sniegtu īsu kopsavilkumu par lapas saturu. [Uzziniet vairāk](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Apraksta teksts ir tukšs."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumentā nav metaapraksta"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumentā ir metaapraksts"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Meklētājprogrammas nevar indeksēt spraudņu saturu, un daudzās ierīcēs spraudņi ir ierobežoti vai netiek atbalstīti. [Uzziniet vairāk](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumentā tiek izmantoti spraudņi"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumentā netiek pieļauti spraudņi"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ja jūsu robots.txt fails ir nepareizi veidots, rāpuļprogrammas, iespējams, nevarēs saprast, kā vajadzētu pārmeklēt vai indeksēt tīmekļa vietni atbilstoši jūsu vēlmēm. [Uzziniet vairāk](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Atbildē uz robots.txt pieprasījumu tika atgriezts HTTP statuss {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Tika atrasta 1 kļūda}zero{Tika atrastas # kļūdas}one{Tika atrasta # kļūda}other{Tika atrastas # kļūdas}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse nevarēja ielādēt robots.txt failu"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt nav derīgs"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt ir derīgs"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktīvajiem elementiem, piemēram, pogām un saitēm, ir jābūt pietiekami lieliem (48 x 48 pikseļi), un tiem apkārt ir jābūt pietiekami daudz brīvas vietas, lai tiem varētu viegli pieskarties, neaizskarot citus elementus. [Uzziniet vairāk](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} pieskārienu mērķu izmērs ir atbilstošs."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Pieskārienu mērķu izmērs ir pārāk mazs, jo mobilo ierīču ekrāniem nav optimizēts skatvietas metatags"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Pieskārienu mērķi nav atbilstoša izmēra"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Mērķis, kas pārklājas"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Pieskārienu mērķis"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Pieskārienu mērķi ir pietiekami liela izmēra"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Pakalpojuma skripts ir tehnoloģija, kas palīdz nodrošināt daudzas progresīvo tīmekļa lietotņu funkcijas, piemēram, lietotnes izmantošanu bezsaistē, pievienošanu sākuma ekrānam un informatīvos paziņojumus. [Uzziniet vairāk](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Lapu kontrolē pakalpojumu skripts, taču netika atrasts `start_url`, jo neizdevās analizēt manifestu kā derīgu JSON failu"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Lapu kontrolē pakalpojumu skripts, taču vietrādis URL `start_url` ({startUrl}) nav ietverts pakalpojumu skripta tvērumā ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Lapu kontrolē pakalpojumu skripts, taču netika atrasts `start_url`, jo manifests netika ienests."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Šim sākumpunktam ir viens vai vairāki pakalpojumu skripti, taču attiecīgā lapa ({pageUrl}) nav tvērumā."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Nav reģistrēts pakalpojumu skripts, kas kontrolētu lapu un `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Ir reģistrēts pakalpojumu skripts, kas kontrolē lapu un `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Uzplaiksnījuma ekrāns ar piemērotu motīvu nodrošina labu pieredzi, lietotājiem palaižot lietotni no sākuma ekrāna. [Uzziniet vairāk](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nav konfigurēta ar pielāgotu uzplaiksnījuma ekrānu"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigurēta ar pielāgotu uzplaiksnījuma ekrānu"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Pārlūkprogrammas adreses joslu var noformēt atbilstoši jūsu vietnes motīvam. [Uzziniet vairāk](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Lapa neiestata adreses joslas motīva krāsu."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Lapa iestata adreses joslas motīva krāsu."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Galvenā pavediena bloķēšanas laiks"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Trešā puse"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Trešās puses kods var ievērojami ietekmēt ielādes veiktspēju. Ierobežojiet lieko trešo pušu pakalpojumu sniedzēju skaitu un mēģiniet ielādēt trešās puses kodu pēc tam, kad jūsu lapa būs ielādēta. [Uzziniet vairāk](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Trešās puses kods bloķēja galveno pavedienu uz {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Samaziniet trešo pušu koda ietekmi"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Trešo pušu lietojums"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Metrika “Laiks līdz pirmajam baitam” norāda laiku, kad jūsu serveris nosūta atbildi. [Uzziniet vairāk](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Saknes dokumentam nepieciešamais laiks: {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Servera atbildes laika samazināšana (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Servera atbildes laiks ir mazs (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Ilgums"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Sākuma laiks"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Veids"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Ieteicams pievienot lietotnei “Lietotāja laika API”, lai noteiktu lietotnes aktuālo veiktspēju lietotāju pamata darbības laikā. [Uzziniet vairāk](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 lietotāja laiks}zero{# lietotāju laiks}one{# lietotāja laiks}other{# lietotāju laiks}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Lietotāju laika atzīmes un mērījumi"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Elementam “{securityOrigin}” tika atrasta iepriekšējas pieslēgšanās parametrs <link>, taču pārlūkprogramma to neizmantoja. Pārbaudiet, vai pareizi izmantojat atribūtu “`crossorigin`”."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Ieteicams pievienot “`preconnect`” vai “`dns-prefetch`” resursa norādes, lai savlaicīgi izveidotu savienojumus ar svarīgiem trešo pušu sākumpunktiem. [Uzziniet vairāk](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Veiciet iepriekšēju pieslēgšanu obligātajiem sākumpunktiem"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Saitei “{preloadURL}” tika atrasts iepriekšējas ielādes parametrs <link>, taču pārlūkprogramma to neizmantoja. Pārbaudiet, vai pareizi izmantojat atribūtu “`crossorigin`”."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Ieteicams izmantot atribūtu `<link rel=preload>`, lai noteiktu prioritāti tādu resursu iegūšanai, kas pašlaik lapas ielādē tiek pieprasīti vēlāk. [Uzziniet vairāk](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Veiciet svarīgāko pieprasījumu iepriekšēju ielādi"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Pievienojiet tagu `<meta name=\"viewport\">`, lai optimizētu lietotni mobilo ierīču ekrāniem. [Uzziniet vairāk](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Netika atrasts tags `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nav taga `<meta name=\"viewport\">` ar `width` vai `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ir tags `<meta name=\"viewport\">` ar `width` vai `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Ja JavaScript ir atspējots, lietotnē jāparāda zināms saturs — kaut vai tikai brīdinājums, ka lietotnes izmantošanai nepieciešams JavaScript. [Uzziniet vairāk](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Ja lapas skripti nav pieejami, lapas pamattekstā jātiek vismaz daļēji attēlotam saturam."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Ja JavaScript nav pieejams, netiek sniegts atkāpšanās saturs"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Ja JavaScript nav pieejams, lapas saturs zināmā mērā tiek parādīts"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ja izstrādājat progresīvo tīmekļa lietotni, apsveriet iespēju izmantot pakalpojumu skriptu, lai lietotne varētu darboties bezsaistē. [Uzziniet vairāk](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Pašreizējā lapa bezsaistē nereaģē ar statusa kodu 200"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Pašreizējā lapa bezsaistē reaģē ar statusa kodu 200"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Iespējams, lapa bezsaistē netiek ielādēta, jo tika veikta novirzīšana no jūsu testa URL ({requested}) uz \"{final}\". Mēģiniet tieši testēt otro URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Šie ieteikumi ļauj uzlabot ARIA lietojumu jūsu lietojumprogrammā. Tādējādi varat uzlabot pieredzi lietotājiem, kuri izmanto palīgtehnoloģijas, piemēram, ekrāna lasītājus."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Šie ieteikumi ļauj nodrošināt papildu audio vai video saturu. Tādējādi var uzlabot pieredzi lietotājiem ar dzirdes vai redzes traucējumiem."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio un video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Šie vienumi parāda izplatītas pieejamības paraugprakses."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Paraugprakse"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Šīs atzīmes parāda iespējas [uzlabot jūsu tīmekļa lietotnes pieejamību](https://developers.google.com/web/fundamentals/accessibility). Automātiski var noteikt tikai pieejamības problēmu apakškopu, tāpēc ir ieteicama arī manuālā testēšana."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Šie vienumi norāda uz vietām, kurām automātiskais testēšanas rīks nevar piekļūt. Uzziniet vairāk mūsu ceļvedī par [pieejamības pārskata veikšanu](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Pieejamība"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Šie ieteikumi ļauj uzlabot satura lasāmību."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrasts"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Šie ieteikumi lietotājiem, kuri izmanto dažādas lokalizācijas, ļauj labāk izprast jūsu saturu."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizācija un lokalizēšana"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Šie ieteikumi ļauj uzlabot lietojumprogrammas vadīklu semantiku. Tādējādi var nodrošināt labāku pieredzi lietotājiem, kuri izmanto palīgtehnoloģijas, piemēram, ekrāna lasītājus."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nosaukumi un iezīmes"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Šie ieteikumi ļauj uzlabot jūsu lietotnes tastatūras navigāciju."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigācija"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Šie ieteikumi ļauj uzlabot tabulas vai sarakstu datu lasīšanu, izmantojot palīgtehnoloģijas, piemēram, ekrāna lasītājus."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabulas un saraksti"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Paraugprakse"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Izpildes budžets nosaka jūsu vietnes veiktspējas standartus."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budžeti"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Plašāka informācija par jūsu lietojumprogrammas veiktspēju. Šie skaitļi [tieši neietekmē](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) veiktspējas rezultātu"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Vissvarīgākais veiktspējas aspekts ir pikseļu renderēšanas ātrums ekrānā. Galvenās metrikas: “Pirmais saturīgais satura atveidojums”, “Pirmais nozīmīgais satura atveidojums”"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Pirmā satura atveidojuma uzlabojumi"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Šie ieteikumi var palīdzēt ātrāk ielādēt jūsu lapu. Tie [tieša veidā neietekmē](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) veiktspējas rezultātu."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Iespējas"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrikas"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Uzlabojiet vispārējo ielādes darbību, lai lapa reaģētu un būtu gatava izmantošanai pēc iespējas ātrāk. Galvenās metrikas: “Laiks līdz interaktivitātei”, “Ātruma rādītājs”"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Vispārēji uzlabojumi"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Veiktspēja"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Veicot šīs pārbaudes, varat validēt progresīvo tīmekļa lietotņu aspektus. [Uzziniet vairāk](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Šīs pārbaudes ir vajadzīgas saskaņā ar standarta [PWA kontrolsarakstu](https://developers.google.com/web/progressive-web-apps/checklist), taču Lighthouse neveic tās automātiski. Tās neietekmē jūsu rezultātu, taču ir svarīgi pārbaudīt šos lietotnes aspektus manuāli."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresīvā tīmekļa lietotne"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Ātrums un uzticamība"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Instalēšana"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PTL optimizācija"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Šīs atzīmes nodrošina, ka jūsu lapa ir optimizēta meklētājprogrammu rezultātu ranžēšanai. Pastāv papildu faktori, kurus Lighthouse neatzīmē, bet tie var ietekmēt jūsu meklēšanas rezultātu ranžēšanu. [Uzziniet vairāk](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Palaidiet savā vietnē šos papildu apstiprināšanas rīkus, lai aplūkotu papildu MPO paraugpraksi."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "MPO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatējiet savu HTML tā, lai rāpuļprogrammas varētu labāk saprast jūsu lietotnes saturu."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Satura paraugprakse"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Rāpuļprogrammām ir nepieciešama piekļuve jūsu lietotnei, lai nodrošinātu parādīšanu meklēšanas rezultātos."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Pārmeklēšana un indeksēšana"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Jūsu lapām ir jābūt piemērotām mobilajām ierīcēm, lai lietotājiem nebūtu jāizmanto savilkšana vai tuvināšana lapu satura lasīšanai. [Uzziniet vairāk](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Piemērota mobilajām ierīcēm"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Kešatmiņas TTL vērtība"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Atrašanās vieta"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Vārds"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Pieprasījumi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Resursu veids"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Izmērs"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Iztērētais laiks"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Pārsūtīto failu lielums"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potenciālie ietaupījumi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potenciālie ietaupījumi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potenciālais ietaupījums: {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potenciālais ietaupījums: {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokuments"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Fonts"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Attēls"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Multivide"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Cits"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skripts"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stilu lapa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Trešā puse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Kopā"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Nevarēja reģistrēt lapas ielādes trasējumu. Lūdzu, vēlreiz palaidiet Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Gaidot sākotnējā atkļūdotāja protokola savienojumu, radās noildze."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Lapas ielādes laikā pārlūkprogramma Chrome nav apkopojusi nevienu ekrānuzņēmumu. Lūdzu, nodrošiniet, ka saturs ir redzams lapā, un pēc tam mēģiniet atkārtoti palaist Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS serveri nevarēja atrast norādīto domēnu."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Nepieciešamajam parametra “{artifactName}” vācējam radās kļūda: {errorMessage}."
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Radās iekšēja Chrome kļūda. Lūdzu, restartējiet Chrome un mēģiniet atkārtoti palaist Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Nepieciešamais parametra “{artifactName}” vācējs nedarbojās."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse nevarēja droši ielādēt jūsu pieprasīto lapu. Pārliecinieties, ka testējat pareizo URL un serveris pareizi reaģē uz visiem pieprasījumiem."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse nevarēja droši ielādēt jūsu pieprasīto URL, jo lapa pārstāja reaģēt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Jūsu norādītajam URL nav derīga drošības sertifikāta. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Pārlūkprogramma Chrome neļāva ielādēt lapu ar iespiestu reklāmu. Nodrošiniet, ka pārbaudāt pareizo URL un ka serveris pareizi reaģē uz visiem pieprasījumiem."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse nevarēja uzticami ielādēt jūsu pieprasīto lapu. Nodrošiniet, ka pārbaudāt pareizo URL un ka serveris pareizi reaģē uz visiem pieprasījumiem. (Detalizēta informācija: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse nevarēja uzticami ielādēt jūsu pieprasīto lapu. Nodrošiniet, ka pārbaudāt pareizo URL un ka serveris pareizi reaģē uz visiem pieprasījumiem. (Statusa kods: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Lapas ielādei bija nepieciešams pārāk ilgs laiks. Lūdzu, izmantojiet pārskatā sniegtās iespējas, lai samazinātu lapas ielādes laiku, un pēc tam mēģiniet atkārtoti palaist Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Gaidot DevTools protokola atbildi, ir pārsniegts atvēlētais laiks. (Veids: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Resursu satura izgūšanai ir nepieciešams ilgāks laiks, nekā pieļaujams"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Šķiet, ka jūsu norādītais URL nav derīgs."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Rādīt pārbaudes"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Sākotnējā navigācija"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimālais kritiskais ceļa latentums:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Kļūda!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Pārskata kļūda: nav pārbaudes informācijas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratorijas dati"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) pašreizējās lapas analīze emulētajā mobilajā tīklā. Vērtības ir aptuvenas un var atšķirties."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Papildu vienumi manuālai pārbaudei"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nav piemērojams"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Iespēja"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Aptuvenais ietaupījums"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Izpildītās pārbaudes"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Sakļaut fragmentu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Izvērst fragmentu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Parādīt trešās puses resursus"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Radās problēmas, kas ietekmēja šo Lighthouse palaišanu:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Vērtības ir aptuvenas un var atšķirties. Veiktspējas rezultāts tiek [tiek pamatots tikai uz šīm metrikām](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Veiktās pārbaudes ar brīdinājumiem"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Brīdinājumi: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Apsveriet iespēju augšupielādēt GIF attēlu pakalpojumā, kuru varēs izmantot, lai iegultu GIF attēlu kā HTML5 videoklipu."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instalējiet [atliktās ielādes WordPress spraudni](https://wordpress.org/plugins/search/lazy+load/), kas sniedz iespēju atlikt jebkādus ārpus ekrāna esošus attēlus vai mainīt motīvu uz tādu, kurā šī funkcija tiek nodrošināta. Ieteicams izmantot arī [AMP spraudni](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Ir vairāki WordPress spraudņi, kas var palīdzēt [iekļaut būtiskus līdzekļus](https://wordpress.org/plugins/search/critical+css/) vai [atlikt mazāk svarīgus resursus](https://wordpress.org/plugins/search/defer+css+javascript/). Ņemiet vērā, ka šo spraudņu nodrošinātā optimizācija var traucēt funkciju darbībai jūsu motīvā vai spraudņos, tādēļ, visticamāk, jums būs jāveic koda izmaiņas."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Motīvi, spraudņi un servera specifikācijas ietekmē servera atbildes laiku. Apsveriet iespēju atrast optimizētāku motīvu, rūpīgi izvēlēties optimizācijas spraudni un/vai jaunināt serveri."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Apsveriet iespēju rādīt fragmentus ziņu sarakstos (piemēram, izmantojot tagu “more”), samazināt attiecīgajā lapā rādāmo ziņu skaitu, sadalīt garas ziņas vairākās lapās vai izmantot spraudni, lai atliktu komentāru ielādi."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Vairāki [WordPress spraudņi](https://wordpress.org/plugins/search/minify+css/) var paātrināt jūsu vietnes darbību, savienojot, samazinot un saspiežot stilus. Ja iespējams, varat arī veikt šo samazināšanu iepriekš izveides procesā."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Vairāki [WordPress spraudņi](https://wordpress.org/plugins/search/minify+javascript/) var paātrināt jūsu vietnes darbību, savienojot, samazinot un saspiežot skriptus. Ja iespējams, varat veikt šo samazināšanu jau iepriekš izveides procesā."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Ieteicams samazināt vai mainīt tādu [WordPress spraudņu](https://wordpress.org/plugins/) skaitu, kuri ielādē nelietotu CSS kodu jūsu lapā. Lai identificētu spraudņus, kuri pievieno lieku CSS kodu, mēģiniet izpildīt [koda pārklājumu](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage), izmantojot Chrome DevTools. Saistīto motīvu/spraudni varat identificēt stila lapas vietrādī URL. Meklējiet spraudņus, kuriem sarakstā ir daudz stila lapu ar daudz sarkanām atzīmēm koda pārklājumā. Spraudnim ir jāievieto rindā stilu lapa tikai tad, ja tā faktiski tiek izmantota lapā."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Ieteicams samazināt vai mainīt tādu [WordPress spraudņu](https://wordpress.org/plugins/) skaitu, kuri ielādē nelietotu JavaScript kodu jūsu lapā. Lai identificētu spraudņus, kuri pievieno lieku JS kodu, mēģiniet izpildīt [koda pārklājumu](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage), izmantojot Chrome DevTools. Saistīto motīvu/spraudni varat identificēt skripta vietrādī URL. Meklējiet spraudņus, kuriem sarakstā ir daudz skriptu ar daudz sarkanām atzīmēm koda pārklājumā. Spraudnim ir jāievieto rindā skripts tikai tad, ja tas faktiski tiek izmantots lapā."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Uzziniet par [pārlūkprogrammas datu saglabāšanu kešatmiņā programmatūrā WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Ieteicams izmantot [attēlu optimizācijas WordPress spraudni](https://wordpress.org/plugins/search/optimize+images/), kas saspiež attēlus, vienlaikus saglabājot kvalitāti."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Tieši augšupielādējiet attēlus, izmantojot [multivides bibliotēku](https://codex.wordpress.org/Media_Library_Screen), lai nodrošinātu nepieciešamo attēlu lielumu pieejamību. Pēc tam ievietojiet attēlus no multivides bibliotēkas vai izmantojiet attēlu logrīku, lai tiktu izmantoti optimāli attēlu lielumi (tostarp reaģējošām robežvērtībām paredzētie). Neizmantojiet `Full Size` attēlus, ja to izmēri neatbilst to lietojumam. [Uzziniet vairāk](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Varat iespējot teksta saspiešanu tīmekļa servera konfigurācijā."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Ieteicams izmantot [spraudni](https://wordpress.org/plugins/search/convert+webp/) vai pakalpojumu, kurā jūsu augšupielādētie attēli tiks automātiski pārveidoti optimālos formātos."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/nl.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/nl.json
new file mode 100644
index 00000000000..6e193b4e779
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/nl.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Met toegangstoetsen kunnen gebruikers snel de focus op een gedeelte van de pagina plaatsen. Voor correcte navigatie moet elke toegangstoets uniek zijn. [Meer informatie](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]`-waarden zijn niet uniek"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`-waarden zijn uniek"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Elke ARIA-`role` ondersteunt een specifieke subset van `aria-*`-kenmerken. Als deze verkeerd worden gekoppeld, worden de `aria-*`-kenmerken ongeldig. [Meer informatie](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]`-kenmerken komen niet overeen met hun rollen"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]`-kenmerken komen overeen met hun rollen"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Sommige ARIA-rollen hebben vereiste kenmerken die de status van het element beschrijven voor schermlezers. [Meer informatie](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`-elementen bevatten niet alle vereiste `[aria-*]`-kenmerken"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`-elementen bevatten alle vereiste `[aria-*]`-kenmerken"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Sommige bovenliggende ARIA-rollen moeten specifieke onderliggende rollen bevatten om de beoogde toegankelijkheidsfuncties uit te voeren. [Meer informatie](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "In elementen met een ARIA `[role]` die vereisen dat onderliggende elementen een specifieke `[role]` bevatten, ontbreken enkele (of alle) van die vereiste onderliggende elementen."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementen met een ARIA `[role]` die vereisen dat onderliggende elementen een specifieke `[role]` bevatten, bevatten alle vereiste onderliggende elementen."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Sommige onderliggende ARIA-rollen moeten zijn opgenomen in specifieke bovenliggende rollen om de beoogde toegankelijkheidsfuncties op de juiste manier uit te voeren. [Meer informatie](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`-elementen zijn niet opgenomen in het vereiste bovenliggende element"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`-elementen zijn opgenomen in het vereiste bovenliggende element"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA-rollen moeten geldige waarden hebben om hun beoogde toegankelijkheidsfuncties uit te voeren. [Meer informatie](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]`-waarden zijn niet geldig"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]`-waarden zijn geldig"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "ARIA-kenmerken met ongeldige waarden kunnen niet worden geïnterpreteerd door hulptechnologieën, zoals schermlezers. [Meer informatie](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]`-kenmerken hebben geen geldige waarden"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]`-kenmerken bevatten geldige waarden"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "ARIA-kenmerken met ongeldige namen kunnen niet worden geïnterpreteerd door hulptechnologieën, zoals schermlezers. [Meer informatie](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]`-kenmerken zijn niet geldig of zijn verkeerd gespeld"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]`-kenmerken zijn geldig en niet verkeerd gespeld"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Ondertiteling maakt audio-elementen bruikbaar voor doven en slechthorenden en geeft essentiële informatie zoals wie praat, wat de persoon zegt en andere niet-gesproken informatie. [Meer informatie](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Voor `<audio>`-elementen ontbreekt een `<track>`-element met `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>`-elementen bevatten een `<track>`-element met `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Mislukte elementen"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Wanneer een knop geen toegankelijke naam heeft, kondigen schermlezers deze aan als 'knop', waardoor de knop onbruikbaar wordt voor gebruikers die afhankelijk zijn van schermlezers. [Meer informatie](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Knoppen hebben geen toegankelijke naam"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Knoppen hebben een toegankelijke naam"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Als je manieren toevoegt om herhaalde content te omzeilen, kunnen toetsenbordgebruikers efficiënter navigeren op de pagina. [Meer informatie](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "De pagina bevat geen kop, link voor overslaan of herkenningspuntregio"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "De pagina bevat een kop, link voor overslaan of herkenningspuntregio"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Voor veel gebruikers is tekst met weinig contrast moeilijk of onmogelijk te lezen. [Meer informatie](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "De contrastverhouding van achtergrond- en voorgrondkleuren is niet voldoende"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "De contrastverhouding van achtergrond- en voorgrondkleuren is voldoende"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Wanneer definitielijsten niet juist zijn opgemaakt, kunnen schermlezers verwarrende of onjuiste uitvoer produceren. [Meer informatie](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`-elementen bevatten niet alleen juist geordende `<dt>`- en `<dd>`-groepen, `<script>` of `<template>`-elementen."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`-elementen bevatten alleen juist geordende`<dt>`- en `<dd>`-groepen,`<script>` of `<template>`-elementen."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Definitielijstitems (`<dt>` en `<dd>`) moeten zijn verpakt in een bovenliggend `<dl>`-element om ervoor te zorgen dat schermlezers ze juist kunnen aankondigen. [Meer informatie](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Definitielijstitems zijn niet verpakt in `<dl>`-elementen"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Definitielijstitems zijn verpakt in `<dl>`-elementen"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "De titel geeft gebruikers van een schermlezer een overzicht van de pagina. Gebruikers van een zoekmachine vertrouwen in hoge mate hierop om te bepalen of een pagina relevant is voor hun zoekopdracht. [Meer informatie](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Document bevat geen `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Document bevat een `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "De waarde van een id-kenmerk moet uniek zijn om te voorkomen dat andere instanties over het hoofd worden gezien door hulptechnologieën. [Meer informatie](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "De `[id]`-kenmerken op de pagina zijn niet uniek"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "De `[id]`-kenmerken op de pagina zijn uniek"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Gebruikers van een schermlezer zijn afhankelijk van frametitels die de content van de frames beschrijven. [Meer informatie](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>`- of `<iframe>`-elementen hebben geen titel"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>`- of `<iframe>`-elementen hebben een titel"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Als de pagina geen lang-kenmerk specificeert, neemt een schermlezer aan dat de pagina is geschreven in de standaardtaal die de gebruiker heeft gekozen toen de schermlezer werd ingesteld. Als de pagina niet in de standaardtaal is geschreven, kan de schermlezer de tekst van de pagina mogelijk niet juist aankondigen. [Meer informatie](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-element bevat geen `[lang]`-kenmerk"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-element bevat een `[lang]`-kenmerk"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Als je een geldige [BCP 47-taal](https://www.w3.org/International/questions/qa-choosing-language-tags#question) opgeeft, kunnen schermlezers de tekst juist aankondigen. [Meer informatie](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-element bevat geen geldige waarde voor het `[lang]`-kenmerk."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>`-element bevat een geldige waarde voor het`[lang]`-kenmerk"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Voor informatieve elementen moet een korte, beschrijvende alternatieve tekst worden gebruikt. Decoratieve elementen kunnen worden genegeerd met een leeg alt-kenmerk. [Meer informatie](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Afbeeldingselementen hebben geen `[alt]`-kenmerken"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Afbeeldingselementen bevatten `[alt]`-kenmerken"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Wanneer een afbeelding wordt gebruikt als `<input>`-knop en je hiervoor alternatieve tekst opgeeft, kunnen gebruikers van een schermlezer beter begrijpen wat het doel van de knop is. [Meer informatie](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">`-elementen bevatten geen `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">`-elementen bevatten `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Labels zorgen ervoor dat formulieropties juist worden aangekondigd door hulptechnologieën, zoals schermlezers. [Meer informatie](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Formulierelementen hebben geen bijbehorende labels"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Formulierelementen hebben bijbehorende labels"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Een tabel die wordt gebruikt voor lay-outdoeleinden, mag geen gegevenselementen (zoals th- of caption-elementen of het summary-kenmerk) bevatten omdat dit verwarrend kan zijn voor gebruikers van een schermlezer. [Meer informatie](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "`<table>`-presentatie-elementen vermijden niet het gebruik van `<th>`, `<caption>` of het `[summary]`-kenmerk."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "In `<table>`-presentatie-elementen wordt het gebruik van `<th>`, `<caption>` of het `[summary]`-kenmerk vermeden."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Met linktekst (en alternatieve tekst voor afbeeldingen, indien gebruikt als links) die herkenbaar, uniek en focusbaar is, verbeter je de navigatiefunctionaliteit voor gebruikers van een schermlezer. [Meer informatie](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Links hebben geen herkenbare naam"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Links hebben een herkenbare naam"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Schermlezers hebben een specifieke manier om lijsten aan te kondigen. Met een juiste lijststructuur verbetert de uitvoer van schermlezers. [Meer informatie](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Lijsten bevatten niet alleen `<li>`-elementen en elementen voor scriptondersteuning (`<script>` en `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Lijsten bevatten alleen `<li>`-elementen en elementen voor scriptondersteuning (`<script>` en `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Voor schermlezers moeten lijstitems (`<li>`) binnen een bovenliggende `<ul>` of `<ol>` worden geplaatst om juist te worden aangekondigd. [Meer informatie](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Lijstitems (`<li>`) zijn niet opgenomen in `<ul>` of bovenliggende `<ol>`-elementen."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Lijstitems (`<li>`) zijn tussen bovenliggende `<ul>`- of `<ol>`-elementen geplaatst"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Gebruikers verwachten niet dat een pagina automatisch wordt vernieuwd. Als dit wel gebeurt, wordt de focus teruggezet op de bovenkant van de pagina. Dit kan vervelend of verwarrend zijn voor gebruikers. [Meer informatie](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Het document gebruikt `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Het document gebruikt `<meta http-equiv=\"refresh\">` niet"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Uitschakeling van de zoomfunctie is problematisch voor slechtzienden die afhankelijk zijn van schermvergroting om de content van een webpagina te zien. [Meer informatie](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` wordt gebruikt in het `<meta name=\"viewport\">`-element of het `[maximum-scale]`-kenmerk is minder dan 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` wordt niet gebruikt in het `<meta name=\"viewport\">`-element en het `[maximum-scale]`-kenmerk is niet minder dan 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Schermlezers kunnen geen andere content dan tekst vertalen. Als je alt-tekst aan `<object>`-elementen toevoegt, kunnen schermlezers de betekenis overbrengen aan gebruikers. [Meer informatie](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>`-elementen bevatten geen `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>`-elementen bevatten `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Een waarde groter dan 0 impliceert een expliciete navigatievolgorde. Hoewel dit technisch geldig is, is dit vaak vervelend voor gebruikers die afhankelijk zijn van hulptechnologieën. [Meer informatie](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Sommige elementen hebben een `[tabindex]`-waarde die groter is dan 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Geen element dat een `[tabindex]`-waarde heeft die groter is dan 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Schermlezers hebben functies waarmee gemakkelijker kan worden genavigeerd in tabellen. Als je zorgt dat `<td>`-cellen die het `[headers]`-kenmerk gebruiken, alleen verwijzen naar andere cellen in dezelfde tabel, kun je de functionaliteit verbeteren voor gebruikers van een schermlezer. [Meer informatie](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Cellen in een `<table>`-element die het `[headers]`-kenmerk gebruiken, verwijzen naar een element `id` dat niet in dezelfde tabel wordt gevonden."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Cellen in een `<table>`-element dat het `[headers]`-kenmerk gebruikt, verwijzen naar tabelcellen in dezelfde tabel."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Schermlezers hebben functies waarmee gemakkelijker kan worden genavigeerd in tabellen. Als je zorgt dat tabelheaders altijd verwijzen naar een bepaalde reeks cellen, kun je de functionaliteit verbeteren voor gebruikers van een schermlezer. [Meer informatie](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>`-elementen en elementen met `[role=\"columnheader\"/\"rowheader\"]` bevatten niet de gegevenscellen die ze beschrijven."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>`-elementen en elementen met `[role=\"columnheader\"/\"rowheader\"]` bevatten de gegevenscellen die ze beschrijven."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Als je een geldige [BCP 47-taal](https://www.w3.org/International/questions/qa-choosing-language-tags#question) voor elementen opgeeft, kan de tekst juist wordt uitgesproken door een schermlezer. [Meer informatie](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]`-kenmerken hebben geen geldige waarde"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]`-kenmerken bevatten een geldige waarde"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Video's met ondertiteling bieden doven en slechthorenden betere toegang tot de bijbehorende informatie. [Meer informatie](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>`-elementen bevatten geen `<track>`-element met `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>`-elementen bevatten een `<track>`-element met `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audiobeschrijvingen bieden relevante informatie over video's die dialoog niet kan bieden, zoals gezichtsuitdrukkingen en scènes. [Meer informatie](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>`-elementen bevatten geen `<track>`-element met `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>`-elementen bevatten een `<track>`-element met `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Definieer een `apple-touch-icon` voor een ideale weergave op iOS wanneer gebruikers een progressive web-app aan het startscherm toevoegen. Deze moet verwijzen naar een niet-transparante vierkante PNG van 192px (of 180px). [Meer informatie](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Geeft geen geldig `apple-touch-icon` op"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` is verouderd; `apple-touch-icon` krijgt de voorkeur."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Verstrekt een geldige `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome-extensies hadden een negatieve invloed op de laadprestaties van deze pagina. Controleer de pagina in de incognitomodus of via een Chrome-profiel zonder extensies."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Scriptevaluatie"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Script parseren"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Totale CPU-tijd"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Overweeg de tijd te verminderen die aan parseren, compileren en uitvoeren van JS wordt besteed. Het leveren van kleinere JS-payloads kan hierbij helpen. [Meer informatie](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Verkort de JavaScript-uitvoeringstijd"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript-uitvoeringstijd"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Grote gif's zijn niet efficiënt om content met animaties te leveren. Overweeg het gebruik van MPEG4-/WebM-video's voor animaties en PNG/WebP voor statische afbeeldingen in plaats van gif's om netwerkbytes te besparen. [Meer informatie](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Gebruik video-indelingen voor content met animaties"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Overweeg om afbeeldingen die niet in beeld zijn en verborgen afbeeldingen via 'lazy loading' te laden nadat alle kritieke bronnen zijn geladen om zo de tijd tot interactief te verlagen. [Meer informatie](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Laad afbeeldingen die niet in beeld zijn nog niet"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Bronnen blokkeren de eerste weergave (FP) voor je pagina. Overweeg kritieke JS/css inline te leveren en alle niet-kritieke JS/stijlen uit te stellen. [Meer informatie](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Verwijder bronnen die de weergave blokkeren"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Grote netwerkpayloads kosten gebruikers effectief geld en hebben vaak lange laadtijden. [Meer informatie](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Totale grootte was {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Vermijd enorme netwerkpayloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Vermijdt enorme netwerkpayloads"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Als je css-bestanden verkleint, kun je de omvang van netwerkpayloads verkleinen. [Meer informatie](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Verklein de css"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Als je JavaScript-bestanden verkleint, kunnen de omvang van de payload en de parseringstijd van het script worden verkleind. [Meer informatie](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Verklein JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Verwijder overbodig geworden regels uit stylesheets en stel het laden van ongebruikte css uit voor content boven de vouw zodat er minder onnodige bytes worden verbruikt door netwerkactiviteit. [Meer informatie](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Ongebruikte css verwijderen"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Verwijder ongebruikt JavaScript om het aantal bytes te verminderen dat wordt verbruikt door netwerkactiviteit."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Verwijder ongebruikt JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Een lange levensduur voor het cachegeheugen kan herhaalde bezoeken aan je pagina versnellen. [Meer informatie](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 bron gevonden}other{# bronnen gevonden}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Lever statische items met een efficiënt cachebeleid"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Gebruikt een efficiënt cachebeleid voor statische items"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Geoptimaliseerde afbeeldingen worden sneller geladen en verbruiken minder mobiele data. [Meer informatie](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codeer afbeeldingen op een efficiënte manier"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Lever afbeeldingen met het juiste formaat om mobiele data te besparen en de laadtijd te verbeteren. [Meer informatie](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Geef afbeeldingen het juiste formaat"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstgebaseerde bronnen moeten worden geleverd met compressie (gzip, deflate of brotli) om het totale aantal netwerkbytes te minimaliseren. [Meer informatie](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Schakel tekstcompressie in"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Afbeeldingsindelingen zoals JPEG 2000, JPEG XR en WebP bieden vaak betere compressie dan PNG of JPEG. Dit resulteert in snellere downloads en minder dataverbruik. [Meer informatie](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Lever afbeeldingen in moderne indelingen"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Als de breedte van de content van je app niet overeenkomt met de breedte van het kijkvenster, is je app mogelijk niet geoptimaliseerd voor mobiele schermen. [Meer informatie](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Het kijkvensterformaat van {innerWidth}px komt niet overeen met het vensterformaat van {outerWidth}px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "De content heeft niet het juiste formaat voor het kijkvenster"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "De content heeft het juiste formaat voor het kijkvenster"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "De onderstaande kritieke verzoekketens laten zien welke bronnen met een hoge prioriteit worden geladen. Overweeg de lengte van ketens te verkleinen, de downloadgrootte van bronnen te beperken of het downloaden van onnodige bronnen uit te stellen om de laadtijd van de pagina te verbeteren. [Meer informatie](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 keten gevonden}other{# ketens gevonden}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimaliseer de diepte van kritieke verzoeken"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Beëindiging / Waarschuwing"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Lijn"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Beëindigde API's worden uiteindelijk verwijderd uit de browser. [Meer informatie](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 waarschuwing gevonden}other{# waarschuwingen gevonden}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Gebruikt beëindigde API's"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Vermijdt beëindigde API's"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Applicatiecache is beëindigd. [Meer informatie](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "'{AppCacheManifest}' gevonden"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Gebruikt applicatiecache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Vermijdt applicatiecache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Door een doctype op te geven, voorkom je dat de browser overschakelt naar de quirks-modus. [Meer informatie](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "De naam van het doctype moet de tekenreeks `html` in kleine letters zijn"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Document moet een doctype bevatten"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Verwachtte een lege tekenreeks voor publicId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Verwachtte een lege tekenreeks voor systemId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Pagina heeft geen html-doctype en activeert dus de quirks-modus"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Pagina bevat html-doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistiek"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Waarde"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Ontwikkelaars van browsers raden aan dat pagina's minder dan ~1.500 DOM-elementen bevatten. De ideale hoeveelheid bestaat uit vertakkingen met < 32 elementen en minder dan 60 onder-/bovenliggende elementen. Een grote DOM kan het geheugengebruik vergroten, en [stijlberekeningen](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) en kostbare [dynamische aanpassingen in de vormgeving](https://developers.google.com/speed/articles/reflow) veroorzaken. [Meer informatie](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}other{# elementen}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Vermijd een overmatig grote DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximum DOM-diepte"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Totaal aantal DOM-elementen"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximum aantal onderliggende elementen"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Vermijdt een overmatige grote DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Doel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Voeg `rel=\"noopener\"` of `rel=\"noreferrer\"` toe aan eventuele externe links om de prestaties te verbeteren en kwetsbaarheden in de beveiliging te voorkomen. [Meer informatie](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links naar cross-origin-bestemmingen zijn onveilig"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links naar cross-origin-bestemmingen zijn veilig"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Kan geen bestemming bepalen voor ankeradvertentie ({anchorHTML}). Als deze niet wordt gebruikt als hyperlink, overweeg dan om target=_blank te verwijderen."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Gebruikers wantrouwen of raken in de war van sites die vragen om hun locatie zonder context. Overweeg het verzoek in plaats daarvan te koppelen aan gebruikershandelingen. [Meer informatie](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Verzoekt om de geolocatierechten bij laden van pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Vermijdt verzoeken om de geolocatierechten bij laden van pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versie"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Alle front end JavaScript-bibliotheken op de pagina gedetecteerd. [Meer informatie](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Gedetecteerde JavaScript-bibliotheken"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Externe scripts die dynamisch worden geïnjecteerd via `document.write()` kunnen bij gebruikers met een langzame verbinding het laden van de pagina met tientallen seconden vertragen. [Meer informatie](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Gebruikt `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Vermijdt `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Meest ernstig"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bibliotheekversie"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Aantal kwetsbaarheden"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Sommige scripts van derden kunnen bekende beveiligingskwetsbaarheden bevatten die makkelijk te identificeren en door aanvallers te gebruiken zijn. [Meer informatie](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kwetsbaarheid gedetecteerd}other{# kwetsbaarheden gedetecteerd}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Omvat front end JavaScript-bibliotheken met bekende beveiligingskwetsbaarheden"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Hoog"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Laag"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Normaal"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Vermijdt front end JavaScript-bibliotheken met bekende beveiligingskwetsbaarheden"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Gebruikers wantrouwen of raken in de war van sites die vragen om het versturen van meldingen zonder context. Overweeg het verzoek in plaats daarvan te koppelen aan gebruikersgebaren. [Meer informatie](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Verzoekt om de meldingsrechten bij laden van pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Vermijdt verzoeken om de meldingsrechten bij laden van pagina"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Mislukte elementen"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Verhindering van het plakken van wachtwoorden ondermijnt een goed beveiligingsbeleid. [Meer informatie](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Voorkomt dat gebruikers kunnen plakken in wachtwoordvelden"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Laat gebruikers plakken in wachtwoordvelden"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 beschikt over veel voordelen ten opzichte van HTTP/1.1, waaronder binaire headers, multiplexing en serverpush. [Meer informatie](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 verzoek niet weergegeven via HTTP/2}other{# verzoeken niet weergegeven via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Gebruikt HTTP/2 niet voor alle bronnen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Gebruikt HTTP/2 voor de eigen bronnen"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Overweeg je touch- en event-listeners te markeren als `passive` om de scrollprestaties van je pagina te verbeteren. [Meer informatie](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Gebruikt geen passieve listeners om scrollprestaties te verbeteren"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Gebruikt passieve listeners voor de verbetering van de scrollprestaties"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Beschrijving"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Fouten die op de console worden geregistreerd, geven aan dat er onopgeloste problemen zijn. Ze kunnen afkomstig zijn van niet-uitgevoerde netwerkverzoeken en andere problemen met de browser. [Meer informatie](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Er zijn browserfouten gelogd op de console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Er zijn geen browserfouten gelogd op de console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Maak gebruik van de css-functie 'font-display' om ervoor te zorgen dat tekst zichtbaar is voor gebruikers terwijl weblettertypen worden geladen. [Meer informatie](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Zorg ervoor dat tekst zichtbaar blijft tijdens het laden van weblettertypen"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Alle tekst blijft zichtbaar tijdens het laden van weblettertypen"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse kan de waarde voor de lettertypeweergave niet automatisch controleren voor de volgende URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Beeldverhouding (werkelijk)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Beeldverhouding (weergegeven)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "De weergaveafmetingen van afbeeldingen moeten overeenkomen met de natuurlijke beeldverhouding. [Meer informatie](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Geeft afbeeldingen weer met een onjuiste beeldverhouding"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Geeft afbeeldingen weer met een juiste beeldverhouding"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Ongeldige informatie over afbeeldingsformaat {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browsers kunnen gebruikers proactief vragen je app aan hun startscherm toe te voegen. Dit kan leiden tot grotere betrokkenheid. [Meer informatie](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Het manifest van de web-app voldoet niet aan de vereisten voor installeerbaarheid"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Het manifest van de web-app voldoet aan de vereisten voor installeerbaarheid"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Niet-beveiligde URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Alle sites moeten worden beschermd met HTTPS, zelfs sites die geen gevoelige gegevens verwerken. HTTPS voorkomt dat indringers de communicatie tussen je app en je gebruikers manipuleren of hier passief naar luisteren en is een vereiste voor HTTP/2 en veel nieuwe webplatform-API's. [Meer informatie](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 niet-beveiligd verzoek gevonden}other{# niet-beveiligde verzoeken gevonden}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Gebruikt geen HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Gebruikt HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Snel laden van een pagina via een mobiel netwerk zorgt voor een goede mobiele gebruikerservaring. [Meer informatie](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactief na {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactief op gesimuleerd mobiel netwerk binnen {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Je pagina wordt te langzaam geladen en is niet binnen tien seconden interactief. Bekijk de mogelijkheden en diagnostische gegevens in het gedeelte Prestaties voor meer informatie over verbeteringen."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "De pagina wordt niet snel genoeg geladen via mobiele netwerken"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "De pagina wordt snel genoeg geladen via mobiele netwerken"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categorie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Overweeg de tijd te verminderen die aan parseren, compileren en uitvoeren van JS wordt besteed. Het leveren van kleinere JS-payloads kan hierbij helpen. [Meer informatie](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Primaire threadbewerkingen minimaliseren"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Primaire threadbewerkingen minimaliseren"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Sites moeten werken in alle grote browsers om zoveel mogelijk gebruikers te bereiken. [Meer informatie](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "De site werkt in verschillende browsers"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Zorg ervoor dat deep links voor afzonderlijke pagina's via een URL kunnen worden opgenomen en dat URL's uniek zijn zodat ze op social media kunnen worden gedeeld. [Meer informatie](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Elke pagina heeft een URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Overgangen moeten snel aanvoelen terwijl je op een pagina tikt, zelfs bij gebruik van een langzaam netwerk. Dit is essentieel voor hoe de gebruiker de prestaties waarneemt. [Meer informatie](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Paginaovergangen voelen niet alsof ze vastlopen op het netwerk"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Geschatte wachttijd voor invoer is een schatting van de tijd die je app nodig heeft om te reageren op gebruikersinvoer (in milliseconden) gemeten voor de drukste periode van 5 seconden tijdens het laden van de pagina. Als de wachttijd langer dan 50 ms is, kunnen gebruikers je app als traag beschouwen. [Meer informatie](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Geschatte invoerwachttijd"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "'Eerste tekenbewerking met content' (FCP) geeft het tijdstip aan waarop de eerste tekst of afbeelding wordt weergegeven. [Meer informatie](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Eerste weergave met content (FCP)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "'Eerste keer dat CPU inactief was' geeft de eerste keer aan dat de primaire thread van de pagina rustig genoeg was om invoer te verwerken. [Meer informatie](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Eerste keer dat CPU inactief was"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "'Eerste nuttige weergave' (FMP) meet wanneer de primaire content van een pagina zichtbaar is. [Meer informatie](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Eerste nuttige weergave (FMP)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Tijd tot interactief is de hoeveelheid tijd die nodig is voordat een pagina volledig interactief is. [Meer informatie](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tijd tot interactief"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "De maximale potentiële vertraging voor de eerste invoer die gebruikers kunnen ervaren, is de duur (in milliseconden) van de langste taak. [Meer informatie](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max. potentiële eerste invoervertraging"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Snelheidsindex laat zien hoe snel de content van een pagina zichtbaar is. [Meer informatie](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Snelheidsindex"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Som van alle perioden tussen 'Eerste tekenbewerking met content' (FCP) en 'Tijd tot interactief', wanneer de taaklengte langer duurt dan 50 ms, aangegeven in milliseconden."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Totale geblokkeerde tijd"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Retourtijden (RTT) van netwerken hebben een grote invloed op de prestaties. Een hoge RTT naar een beginpunt geeft aan dat de prestaties van servers dichter bij de gebruiker kunnen worden verbeterd. [Meer informatie](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Retourtijden van netwerk"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Serverwachttijden kunnen invloed hebben op webprestaties. Als de serverwachttijd van een beginpunt hoog is, is dit een indicatie dat de server overbelast is of slechte backend-prestaties levert. [Meer informatie](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Wachttijden van server-backend"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Met een service worker kan je web-app betrouwbaar functioneren bij onvoorspelbare netwerkomstandigheden. [Meer informatie](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` retourneert geen 200-statuscode wanneer de pagina offline is"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` retourneert een 200-statuscode wanneer de pagina offline is"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse kan de `start_url` in het manifest niet lezen. Daarom is aangenomen dat de `start_url` de URL van het document is. Foutmelding: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Over het budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Houd de hoeveelheid en grootte van netwerkverzoeken onder de door het verstrekte prestatiebudget ingestelde doelen. [Meer informatie](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 verzoek}other{# verzoeken}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Prestatiebudget"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Als je HTTPS al hebt ingesteld, zorg je ervoor dat je al het HTTP-verkeer omleidt naar HTTPS om beveiligde webfuncties voor alle gebruikers te activeren. [Meer informatie](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Hiermee wordt HTTP-verkeer niet omgeleid naar HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Hiermee wordt HTTP-verkeer omgeleid naar HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Omleidingen zorgen voor extra vertraging voordat de pagina kan worden geladen. [Meer informatie](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Vermijd meerdere pagina-omleidingen"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Voeg een budget.json-bestand toe om budgetten in te stellen voor de hoeveelheid en grootte van paginabronnen. [Meer informatie](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 verzoek • {byteCount, number, bytes} KB}other{# verzoeken • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Houd het aantal verzoeken laag en de overdrachtsgrootte klein"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Canonieke links geven een suggestie voor welke URL moet worden weergegeven in de zoekresultaten. [Meer informatie](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Meerdere conflicterende URL's ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Wijst naar een ander domein ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Ongeldige URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Wijst naar een andere `hreflang`-locatie ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relatieve URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Verwijst naar de root-URL van het domein (de homepage), in plaats van een equivalente pagina van de content"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Document bevat geen geldig `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Document bevat een geldige `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Lettergrootten kleiner dan 12 pixels zijn te klein om leesbaar te zijn en leiden ertoe dat mobiele bezoekers hun 'vingers moeten 'samenknijpen' om te zoomen voordat ze de tekst kunnen lezen. Probeer om meer dan 60% van de paginatekst gelijk aan of groter dan 12 pixels te maken. [Meer informatie](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} leesbare tekst"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Tekst is onleesbaar omdat er geen kijkvenstermetatag is geoptimaliseerd voor mobiele schermen."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} van de tekst is te klein (op basis van een voorbeeld van {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Document gebruikt geen leesbare lettergrootten"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Document gebruikt leesbare lettergrootten"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang-links laten zoekmachines weten welke versie van een pagina ze moeten vermelden in zoekresultaten voor een bepaalde taal of regio. [Meer informatie](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Document bevat geen geldige `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Document bevat een geldige `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Pagina's met ongeldige HTTP-statuscodes worden mogelijk niet juist geïndexeerd. [Meer informatie](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Pagina bevat ongeldige HTTP-statuscode"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Pagina bevat geldige HTTP-statuscode"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Zoekmachines kunnen je pagina's niet opnemen in zoekresultaten als de zoekmachines geen rechten hebben om ze te crawlen. [Meer informatie](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Pagina is geblokkeerd tegen indexeren"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Pagina is niet geblokkeerd tegen indexeren"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Aan de hand van beschrijvende linktekst kunnen zoekmachines je content begrijpen. [Meer informatie](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link gevonden}other{# links gevonden}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Links bevatten geen beschrijvende tekst"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Links bevatten beschrijvende tekst"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Voer de [Tool voor het testen van gestructureerde gegevens](https://search.google.com/structured-data/testing-tool/) en de [Linter voor gestructureerde gegevens](http://linter.structured-data.org/) uit om gestructureerde gegevens te valideren. [Meer informatie](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "De gestructureerde gegevens zijn geldig"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Er kunnen metabeschrijvingen worden opgenomen in zoekresultaten voor een korte samenvatting van paginacontent. [Meer informatie](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Beschrijvingstekst is leeg."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Document bevat geen metabeschrijving"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Document bevat een metabeschrijving"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Zoekmachines kunnen content van plug-ins niet indexeren en veel apparaten beperken plug-ins of ondersteunen deze niet. [Meer informatie](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Document gebruikt plug-ins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Document vermijdt plug-ins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Als je robots.txt-bestand niet juist is opgemaakt, begrijpen crawlers mogelijk niet hoe je wilt dat je website wordt gecrawld of geïndexeerd. [Meer informatie](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Verzoek voor robots.txt heeft volgende HTTP-status geretourneerd: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 fout gevonden}other{# fouten gevonden}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse kan geen robots.txt-bestand downloaden"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt is niet geldig"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt is geldig"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interactieve elementen, zoals knoppen en links, moeten groot genoeg zijn (48 x 48 pixels) en moeten voldoende ruimte eromheen hebben, zodat er makkelijk op getikt kan worden zonder dat andere elementen worden aangeraakt. [Meer informatie](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} van de tikdoelen heeft een geschikt formaat"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Tikdoelen zijn te klein, omdat er geen kijkvenstermetatag is geoptimaliseerd voor mobiele schermen"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Tikdoelen hebben niet het juiste formaat"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Overlappend doel"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Tikdoel"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Tikdoelen hebben het juiste formaat"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "De service worker is de technologie waarmee je app veel functies van progressive web-apps kan gebruiken, zoals offline functionaliteit, toevoegen aan het startscherm en pushmeldingen. [Meer informatie](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Deze pagina wordt beheerd door een service worker, maar er is geen `start_url` gevonden omdat het manifest niet kan worden geparseerd als geldig json-bestand"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Deze pagina wordt beheerd door een service worker, maar de `start_url` ({startUrl}) valt niet binnen het bereik van de service worker ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Deze pagina wordt beheerd door een service worker, maar er is geen `start_url` gevonden omdat er geen manifest is opgehaald."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Deze herkomst heeft een of meer service workers, maar de pagina ({pageUrl}) valt niet binnen het bereik."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Registreert geen service worker die de pagina en `start_url` beheert"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registreert een service worker die de pagina en `start_url` beheert"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Een startscherm met een thema zorgt voor een gebruikerservaring van hoge kwaliteit wanneer gebruikers je app starten vanaf hun startscherm. [Meer informatie](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Is niet geconfigureerd voor een aangepast startscherm"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Is geconfigureerd voor een aangepast startscherm"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Het thema van de adresbalk van de browser kan worden aangepast aan je site. [Meer informatie](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Hiermee wordt geen themakleur voor de adresbalk ingesteld."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Hiermee wordt een themakleur voor de adresbalk ingesteld."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tijd dat primaire thread is geblokkeerd"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Derden"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Code van derden kan van grote invloed zijn op de laadprestaties. Beperk het aantal overbodige externe providers en probeer code van derden te laden nadat je pagina primair is geladen. [Meer informatie](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Code van derden heeft de primaire thread gedurende {timeInMs, number, milliseconds} ms geblokkeerd"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "De impact van code van derden beperken"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Gebruik door derden"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "'Tijd tot eerste byte' identificeert het tijdstip waarop je server een reactie stuurt. [Meer informatie](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Hoofddocument duurde {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Beperk serverreactietijden (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Serverreactietijden zijn laag (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duur"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Begintijd"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Overweeg je app te voorzien van de API voor gebruikerstiming om de daadwerkelijke prestaties van je app tijdens belangrijke gebruikerservaringen te meten. [Meer informatie](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 gebruikerstiming}other{# gebruikerstimings}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Markeringen en metingen voor gebruikerstiming"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Er is een <link> voor vooraf verbinden gevonden voor {securityOrigin} maar deze is niet gebruikt door de browser. Controleer of je het `crossorigin`-kenmerk juist gebruikt."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Overweeg hints voor `preconnect` of `dns-prefetch` van bronnen toe te voegen om vroege verbindingen met belangrijke externe herkomsten tot stand te brengen. [Meer informatie](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Maak vooraf verbinding met vereiste herkomsten"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Er is een <link> voor vooraf laden gevonden voor {preloadURL} maar deze is niet gebruikt door de browser. Controleer of je het `crossorigin`-kenmerk juist gebruikt."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Overweeg `<link rel=preload>` te gebruiken om prioriteit te geven aan het ophalen van bronnen die momenteel later tijdens het laden van de pagina worden opgehaald. [Meer informatie](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Laad belangrijke verzoeken vooraf"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Voeg een `<meta name=\"viewport\">`-tag toe om je app te optimaliseren voor mobiele schermen. [Meer informatie](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Geen `<meta name=\"viewport\">`-tag gevonden"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Bevat geen `<meta name=\"viewport\">`-tag met `width` of `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Bevat een `<meta name=\"viewport\">`-tag met `width` of `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Je app moet wat content weergeven wanneer JavaScript is uitgeschakeld, zelfs als het alleen maar een waarschuwing aan de gebruiker is dat JavaScript is vereist om de app te gebruiken. [Meer informatie](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Het hoofdgedeelte van de pagina moet wat content weergeven als de bijbehorende scripts niet beschikbaar zijn."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Biedt geen reservecontent wanneer JavaScript niet beschikbaar is"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Bevat wat content wanneer JavaScript niet beschikbaar is"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Als je een progressive web-app bouwt, kun je overwegen een service worker te gebruiken zodat je app offline kan worden gebruikt. [Meer informatie](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "De huidige pagina retourneert geen 200-statuscode wanneer de pagina offline is"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "De huidige pagina retourneert een 200-statuscode wanneer de pagina offline is"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "De pagina wordt mogelijk niet geladen omdat je test-URL ({requested}) is omgeleid naar '{final}'. Test de tweede URL rechtstreeks."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Dit zijn suggesties om het gebruik van ARIA in je app te verbeteren, wat kan leiden tot betere functionaliteit voor gebruikers van hulptechnologie, zoals een schermlezer."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Dit zijn mogelijkheden om alternatieve content voor audio en video te bieden. Dit verbetert mogelijk de functionaliteit voor gebruikers met een visuele of gehoorbeperking."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio en video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Deze items geven praktische tips voor algemene toegankelijkheid aan."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Praktische tips"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Deze controles geven mogelijkheden aan om [de toegang tot je web-app te verbeteren](https://developers.google.com/web/fundamentals/accessibility). Alleen een subset van toegankelijkheidsproblemen kan automatisch worden gedetecteerd. Daarom wordt handmatig testen ook aangeraden."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Deze items gaan over gebieden die niet kunnen worden getest met een automatische testtool. Bekijk meer informatie in onze gids over [het uitvoeren van een toegankelijkheidscontrole](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Toegankelijkheid"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Dit zijn suggesties om de leesbaarheid van je content te verbeteren."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Dit zijn suggesties om de interpretatie van je content door gebruikers in verschillende landen te verbeteren."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisering en lokalisatie"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Dit zijn suggesties om de semantiek van de opties in je app te verbeteren. Zo kun je de functionaliteit verbeteren voor gebruikers van hulptechnologie, zoals een schermlezer."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Namen en labels"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Dit zijn de mogelijkheden om toetsenbordnavigatie in je app te verbeteren."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigatie"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Dit zijn mogelijkheden om de functionaliteit voor het lezen van gegevens in tabellen of lijsten te verbeteren met hulptechnologie, zoals een schermlezer."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabellen en lijsten"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Praktische tips"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Prestatiebudgetten stellen normen in voor de prestaties van je site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgetten"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Meer informatie over de prestaties van je app. Deze cijfers hebben geen [directe invloed](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) op de prestatiescore."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostische gegevens"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Het meest essentiële aspect van de prestaties is hoe snel pixels worden weergegeven op het scherm. Belangrijkste statistieken: eerste weergave met content (FCP), eerste nuttige weergave (FMP)"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Verbeteringen voor eerste weergave"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Deze suggesties kunnen helpen je pagina sneller te laden. Ze hebben geen [directe invloed](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) op de prestatiescore."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Aanbevelingen"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Statistieken"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Verbeter de algemene laadfunctionaliteit, zodat de pagina zo snel mogelijk reageert en gebruiksklaar is. Belangrijkste statistieken: Tijd tot interactief, Snelheidsindex"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Algemene verbeteringen"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Prestaties"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Deze controles valideren de aspecten van een progressive web-app. [Meer informatie](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Deze controles worden vereist door de baseline [PWA-checklist](https://developers.google.com/web/progressive-web-apps/checklist) maar worden niet automatisch gecontroleerd door Lighthouse. Ze zijn niet van invloed op je score, maar het is wel belangrijk dat je ze handmatig verifieert."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive web-app"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Snel en betrouwbaar"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Installeerbaar"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Geoptimaliseerd voor PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Deze controles zorgen ervoor dat je pagina is geoptimaliseerd voor positionering in zoekmachineresultaten. Er zijn aanvullende factoren waarop Lighthouse niet controleert, die van invloed kunnen zijn op je positie in de zoekresultaten. [Meer informatie](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Voer deze extra validators op je site uit om aanvullende praktische tips voor SEO te controleren."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Maak je html zo op dat crawlers de content van je app beter begrijpen."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Praktische tips voor content"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Crawlers hebben toegang nodig tot je app om je website in zoekresultaten weer te geven."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Crawlen en indexeren"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Zorg dat je pagina's geschikt zijn voor mobiele apparaten zodat gebruikers niet hun vingers hoeven samen te knijpen of moeten zoomen om de contentpagina's te lezen. [Meer informatie](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Geschikt voor mobiele apparaten"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache-TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Locatie"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Naam"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Verzoeken"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Brontype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Formaat"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Bestede tijd"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Overdrachtgrootte"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potentiële besparingen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potentiële besparingen"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potentiële besparing van {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potentiële besparing van {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Lettertype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Afbeelding"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Anders"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stylesheet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Derden"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Totaal"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Er is een fout opgetreden bij het opnemen van het netwerkspoor voor het laden van je pagina. Voer Lighthouse opnieuw uit. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Time-out tijdens wachten op eerste verbinding met Debugger-protocol."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome heeft geen screenshots verzameld tijdens het laden van de pagina. Zorg dat er content zichtbaar is op de pagina en voer Lighthouse daarna opnieuw uit. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-servers kunnen het opgegeven domein niet omzetten."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Er is een fout opgetreden in de vereiste {artifactName}-verzamelaar: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Er is een interne Chrome-fout opgetreden. Start Chrome opnieuw op en probeer Lighthouse nogmaals uit te voeren."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Vereiste {artifactName}-verzamelaar is niet uitgevoerd."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse kan de door jou aangevraagde pagina niet goed laden. Zorg ervoor dat je de juiste URL test en dat de server correct reageert op alle verzoeken."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse kan de door jou aangevraagde URL niet goed laden omdat de pagina niet meer reageert."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "De URL die je hebt opgegeven, bevat geen geldig beveiligingscertificaat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome heeft laden van pagina met interstitial voorkomen. Zorg dat je de juiste URL test en de server correct reageert op alle verzoeken."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse kan de aangevraagde pagina niet goed laden. Zorg dat je de juiste URL test en de server correct reageert op alle verzoeken. (Details: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse kan de aangevraagde pagina niet goed laden. Zorg dat je de juiste URL test en de server correct reageert op alle verzoeken. (Statuscode: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Het laden van je pagina duurde te lang. Volg de suggesties in het rapport om de laadtijd van je pagina te beperken. Voer Lighthouse daarna opnieuw uit. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Tijdens het wachten op een reactie van het DevTools-protocol is de toegewezen tijd overschreden. (Methode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Voor het ophalen van broncontent is de toegewezen tijd overschreden"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Het lijkt erop dat je een ongeldige URL hebt opgegeven."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Controles weergeven"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Beginnavigatie"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximum wachttijd voor kritiek pad:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Fout"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Rapportfout: geen controlegegevens"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Labgegevens"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analyse met [Lighthouse](https://developers.google.com/web/tools/lighthouse/) van de huidige pagina via een geëmuleerd mobiel netwerk. Waarden worden geschat en kunnen variëren."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Aanvullende items om handmatig te controleren"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "N.v.t."
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Aanbeveling"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Geschatte besparing"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Geslaagde controles"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Fragment samenvouwen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Fragment uitvouwen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Bronnen van derden weergeven"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Er zijn problemen opgetreden bij deze uitvoering van Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Waarden worden geschat en kunnen variëren. De prestatiescore is [alleen gebaseerd op deze statistieken](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Geslaagd voor controles maar met waarschuwingen"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Waarschuwingen: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Overweeg je gif te uploaden naar een service waarmee het mogelijk is de gif in te sluiten als html5-video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installeer een [WordPress-plug-in voor lazy loading](https://wordpress.org/plugins/search/lazy+load/) waarmee afbeeldingen die niet in beeld zijn, kunnen worden uitgesteld, of schakel over naar een thema met deze functionaliteit. Je kunt ook overwegen [de AMP-plug-in](https://wordpress.org/plugins/amp/) te gebruiken."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Er zijn een aantal WordPress-plug-ins om [kritieke items inline te plaatsen](https://wordpress.org/plugins/search/critical+css/) of [minder belangrijke bronnen uit te stellen](https://wordpress.org/plugins/search/defer+css+javascript/). Bedenk wel dat de optimalisatie die deze plug-ins bieden, bepaalde functies van je thema of plug-ins kunnen verstoren. Het is daarom goed mogelijk dat je de code moet wijzigen."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Thema's, plug-ins en serverspecificaties zijn allemaal van invloed op de reactietijd van de server. Overweeg een thema te gebruiken dat beter is geoptimaliseerd, kies met zorg een optimalisatieplug-in en/of upgrade je server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Overweeg fragmenten te tonen in je postlijsten (bijvoorbeeld via de tag 'more'), zodat er per pagina minder posts worden weergegeven. Ook kun je lange posts verdelen over meerdere pagina's of een plug-in voor lazy loading van reacties gebruiken."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Er zijn een aantal [WordPress-plug-ins](https://wordpress.org/plugins/search/minify+css/) die stijlen inkorten, verkleinen en comprimeren en je site sneller maken. Mogelijk kun je een ontwerpproces gebruiken dat deze verkleining van tevoren toepast."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Er zijn een aantal [WordPress-plug-ins](https://wordpress.org/plugins/search/minify+javascript/) die je site sneller kunnen maken door je scripts in te korten, te verkleinen of te comprimeren. Indien mogelijk is het bovendien handig zulke verkleining al mee te nemen in het ontwerpproces."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Overweeg gebruik te maken van minder of andere [WordPress-plug-ins](https://wordpress.org/plugins/) die ongebruikte css laden op je pagina. Voer [codedekking](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) uit in Chrome DevTools als je plug-ins wilt identificeren die extra css toevoegen. Via de URL van de stylesheet kun je identificeren welk thema/welke plug-in verantwoordelijk is. Ga in de lijst op zoek naar plug-ins met veel stylesheets en veel rood in de codedekking. Een plug-in zou een stylesheet alleen in de wachtrij moeten plaatsen als deze daadwerkelijk wordt gebruikt op de pagina."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Overweeg gebruik te maken van minder of andere [WordPress-plug-ins](https://wordpress.org/plugins/) die ongebruikt JavaScript laden op je pagina. Voer [codedekking](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) uit in Chrome DevTools als je plug-ins wilt identificeren die extra JS toevoegen. Via de URL van het script kun je identificeren welk thema/welke plug-in verantwoordelijk is. Ga in de lijst op zoek naar plug-ins met veel scripts en veel rood in de codedekking. Een plug-in zou een script alleen in de wachtrij moeten plaatsen als het daadwerkelijk wordt gebruikt op de pagina."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Lees meer over [browsercaching in WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Overweeg een [beeldoptimalisatieplug-in voor WordPress](https://wordpress.org/plugins/search/optimize+images/) te gebruiken om je afbeeldingen te comprimeren terwijl de beeldkwaliteit behouden blijft."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Upload afbeeldingen rechtstreeks via de [mediabibliotheek](https://codex.wordpress.org/Media_Library_Screen) om er zeker van te zijn dat de vereiste afbeeldingsformaten beschikbaar zijn. Voeg de afbeeldingen vervolgens in vanuit de mediabibliotheek. Ook kun je de afbeeldingswidget gebruiken om ervoor te zorgen dat de optimale afbeeldingsformaten worden gebruikt (inclusief voor responsieve breakpoints). Vermijd `Full Size`-afbeeldingen, tenzij de afmetingen geschikt zijn voor waar ze worden geplaatst. [Meer informatie](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Je kunt tekstcompressie inschakelen bij je webserverinstellingen."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Overweeg een [plug-in](https://wordpress.org/plugins/search/convert+webp/) of service te gebruiken die je geüploade afbeeldingen automatisch converteert naar de optimale formaten."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/no.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/no.json
new file mode 100644
index 00000000000..5f78d103d5e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/no.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Med tilgangsnøkler kan brukere raskt fokusere på deler av siden. Hver tilgangsnøkkel må være unik for at navigeringen skal fungere riktig. [Finn ut mer](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]`-verdier er ikke unike"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`-verdiene er unike"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Hver ARIA-`role` støtter en spesifikk undergruppe av `aria-*`-attributter. Manglende samsvar mellom disse gjør `aria-*`-attributtene ugyldige. [Finn ut mer](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]`-attributter samsvarer ikke med rollene sine"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]`-attributtene samsvarer med rollene sine"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Noen ARIA-roller har obligatoriske attributter som beskriver elementenes tilstand for skjermlesere. [Finn ut mer](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`-elementer har ikke alle de obligatoriske `[aria-*]`-attributtene"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`-elementene har alle de obligatoriske `[aria-*]`-attributtene"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Noen overordnede ARIA-roller må inneholde spesifikke underordnede roller for å utføre de tiltenkte tilgjengelighetsfunksjonene. [Finn ut mer](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementer som har en ARIA-`[role]` og krever underordnede elementer som inneholder en spesifikk `[role]`, mangler noen av eller alle disse underordnede elementene."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementer som har en ARIA-`[role]` og krever underordnede elementer som inneholder en spesifikk `[role]`, har alle de nødvendige underordnede elementene."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Noen underordnede ARIA-roller må ligge innenfor de spesifikke overordnede rollene for å utføre de tiltenkte tilgjengelighetsfunksjonene på riktig måte. [Finn ut mer](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`-elementer ligger ikke i de obligatoriske overordnede elementene"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`-elementer ligger i de obligatoriske overordnede elementene"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA-roller må ha gyldige verdier for å utføre de tiltenkte tilgjengelighetsfunksjonene. [Finn ut mer](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]`-verdiene er ikke gyldige"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]`-verdiene er gyldige"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Assisterende teknologi, for eksempel skjermlesere, kan ikke tolke ARIA-attributter med ugyldige verdier. [Finn ut mer](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]`-attributter har ikke gyldige verdier"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]`-attributtene har gyldige verdier"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Assisterende teknologi, som skjermlesere, kan ikke tolke ARIA-attributter med ugyldige navn. [Finn ut mer](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]`-attributter er ugyldige eller feilstavet"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]`-attributtene er gyldige og ikke feilstavet"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Når du inkluderer teksting, kan døve og hørselshemmede brukere også dra nytte av lydelementer, siden de får se kritisk informasjon, for eksempel om hvem som snakker, hva de sier, og annen informasjon som ikke er talerelatert. [Finn ut mer](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>`-elementer mangler et `<track>`-element med `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>`-elementer inneholder et `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementer som ikke besto kontrollen"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Når knapper ikke har tilgjengelige navn, beskriver skjermlesere dem som «knapp». Dermed er de ubrukelige for brukere som er avhengige av skjermlesere. [Finn ut mer](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Knapper har ikke tilgjengelige navn"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Knappene har tilgjengelige navn"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Hvis du legger til måter å hoppe over repeterende innhold på, kan tastaturbrukere navigere mer effektivt på siden. [Finn ut mer](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Siden mangler overskrift, landemerkeregion eller link for å hoppe over innhold"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Siden inneholder en overskrift, en landemerkeregion eller en link for å hoppe over innhold"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Tekst med lav kontrast er vanskelig eller umulig å lese for mange brukere. [Finn ut mer](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Kontrastforholdet mellom bakgrunns- og forgrunnsfarger er ikke tilstrekkelig."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Kontrastforholdet mellom bakgrunns- og forgrunnsfargene er tilstrekkelig"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Når definisjonslister ikke er riktig kodet, kan resultatene fra skjermlesere bli forvirrende eller unøyaktige. [Finn ut mer](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`-elementer inneholder ikke bare velordnede `<dt>`- og `<dd>`-grupper og `<script>`- eller `<template>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`-elementene inneholder bare velordnede `<dt>`- og `<dd>`-grupper og `<script>`- eller `<template>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Elementer i definisjonslister (`<dt>` og `<dd>`) må være omsluttet av et overordnet `<dl>`-element for å sørge for at skjermlesere kan lese dem opp riktig. [Finn ut mer](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Elementer i definisjonslister er ikke omsluttet av `<dl>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Elementene i definisjonslister er omsluttet av `<dl>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Tittelen gir brukere av skjermlesere oversikt over siden, og søkemotorbrukere er svært avhengige av den for å avgjøre om siden er relevant for søket deres. [Finn ut mer](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumentet har ikke noe `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumentet har et `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "ID-attributter må ha unike verdier for å unngå at andre forekomster blir oversett av assisterende teknologi. [Finn ut mer](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "`[id]`-attributter på siden er ikke unike"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "`[id]`-attributtene på siden er unike"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Brukere av skjermlesere er avhengige av titler for «frame»/«iframe»-elementer for å forstå innholdet i dem. [Finn ut mer](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>`- eller `<iframe>`-elementer mangler tittel"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>`- og `<iframe>`-elementer har titler"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Hvis en side ikke angir noe «lang»-attributt, antar skjermlesere at siden er på standardspråket brukeren valgte ved konfigurering av skjermleseren. Hvis siden ikke faktisk er på standardspråket, kan det hende skjermleseren leser teksten på siden feil. [Finn ut mer](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-elementet har ikke noe gyldig `[lang]`-attributt"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-elementet har et `[lang]`-attributt"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ved å angi et gyldig [BCP 47-språk](https://www.w3.org/International/questions/qa-choosing-language-tags#question) hjelper du skjermlesere med å lese opp teksten riktig. [Finn ut mer](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-elementet har ikke noen gyldig verdi for `[lang]`-attributtet."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>`-elementet har en gyldig verdi for `[lang]`-attributtet"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informative elementer bør ta sikte på korte og beskrivende alternative tekster. Dekorative elementer kan ignoreres med tomme alt-attributter. [Finn ut mer](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Bildeelementer har ikke `[alt]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Bildeelementene har `[alt]`-attributter"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Når et bilde brukes som `<input>`-knapp, bør du oppgi en alternativ tekst som hjelper brukere av skjermlesere med å forstå hva knappen er til. [Finn ut mer](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">`-elementer har ikke `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">`-elementer har `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etiketter sørger for at skjemakontroller leses opp på riktig måte av assisterende teknologi, som skjermlesere. [Finn ut mer](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Skjemaelementer har ikke tilknyttede etiketter"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Skjemaelementene har tilknyttede etiketter"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabeller som brukes til layoutformål, skal ikke inneholde dataelementer, som th-elementer, caption-elementer eller summary-attributtet, da disse kan skape en forvirrende opplevelse for brukere av skjermlesere. [Finn ut mer](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Presentasjonsmessige `<table>`-elementer unngår ikke å bruke `<th>`, `<caption>` eller `[summary]`-attributtet."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Presentasjonsmessige `<table>`-elementer unngår å bruke `<th>`, `<caption>` og `[summary]`-attributtet."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Når du bruker linktekst (og alternativ tekst for bilder som brukes som linker) som er tydelig, unik og mulig å sette fokus på, blir navigeringsopplevelsen bedre for brukere av skjermlesere. [Finn ut mer](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Linker har ikke tydelige navn"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Linkene har tydelige navn"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Skjermlesere har en spesifikk måte å lese opp lister på. Du kan øke kvaliteten på resultatene fra skjermlesere ved å bruke en god listestruktur. [Finn ut mer](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Lister inneholder ikke kun `<li>`-elementer og elementer som støtter skript (`<script>` og `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listene inneholder bare `<li>`-elementer og elementer som støtter skript (`<script>` og `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Skjermlesere krever at listeelementer (`<li>`) ligger i et overordnet `<ul>`- eller `<ol>`-element – ellers kan de ikke leses opp på riktig måte. [Finn ut mer](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Listeelementer (`<li>`) ligger ikke i overordnede `<ul>`- eller `<ol>`-elementer."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Listeelementene (`<li>`) ligger i overordnede `<ul>`- eller `<ol>`-elementer"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Brukere forventer ikke at sider oppdateres automatisk, så hvis dette skjer, flyttes fokuset tilbake til toppen av siden. Dette kan føre til frustrasjon eller forvirring. [Finn ut mer](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokumentet bruker `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokumentet bruker ikke `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Deaktivering av zoom er problematisk for brukere med nedsatt synsevne som har behov for å forstørre skjermen for å se innholdet på nettsider. [Finn ut mer](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` brukes i `<meta name=\"viewport\">`-elementet, eller `[maximum-scale]`-attributtet er mindre enn 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` brukes ikke i `<meta name=\"viewport\">`-elementet, og `[maximum-scale]`-attributtet er ikke mindre enn 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Skjermlesere kan ikke oversette innhold som ikke er tekst. Ved å legge til alternativ tekst i `<object>`-elementer hjelper du skjermlesere med å formidle mening til brukerne. [Finn ut mer](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>`-elementer har ikke `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>`-elementer har `[alt]`-tekst"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Større verdier enn 0 antyder en eksplisitt navigeringsrekkefølge. Selv om dette teknisk sett er gyldig, kan det ofte være frustrerende for brukere som er avhengige av assisterende teknologi. [Finn ut mer](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Noen elementer har en `[tabindex]`-verdi som er større enn 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Ingen elementer har en `[tabindex]`-verdi som er større enn 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Skjermlesere har funksjonalitet som gjør det enklere å navigere i tabeller. Ved å sørge for at `<td>`-celler som bruker `[headers]`-attributtet, kun refererer til andre celler i den samme tabellen, kan du gjøre opplevelsen bedre for brukere av skjermlesere. [Finn ut mer](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Celler som er en del av et `<table>`-element og bruker `[headers]`-attributtet, refererer til et element (`id`) som ikke finnes i den samme tabellen."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Celler som er en del av et `<table>`-element og bruker `[headers]`-attributtet, refererer til tabellceller i den samme tabellen."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Skjermlesere har funksjonalitet som gjør det enklere å navigere i tabeller. Ved å sørge for at tabelloverskrifter alltid refererer til spesifikke cellesett, kan du gjøre opplevelsen bedre for brukere av skjermlesere. [Finn ut mer](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>`-elementer og elementer med `[role=\"columnheader\"/\"rowheader\"]` har ikke datacellene de beskriver."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>`-elementene og elementene med `[role=\"columnheader\"/\"rowheader\"]` har datacellene de beskriver."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ved å angi et gyldig [BCP 47-språk](https://www.w3.org/International/questions/qa-choosing-language-tags#question) i elementer bidrar du til at skjermlesere leser opp teksten riktig. [Finn ut mer](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]`-attributter mangler gyldige verdier"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]`-attributtene har gyldige verdier"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Når videoer har teksting, blir det lettere for døve og hørselshemmede brukere å få med seg informasjonen i dem. [Finn ut mer](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>`-elementer mangler et `<track>`-element med `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>`-elementer inneholder et `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Lydbeskrivelser gir relevant videoinformasjon som dialog ikke kan formidle, for eksempel ansiktsuttrykk og scener. [Finn ut mer](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>`-elementer mangler et `<track>`-element med `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>`-elementer inneholder et `<track>`-element med `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "For å oppnå det ideelle utseendet på iOS når brukere legger til progressive nettprogrammer på startskjermen, definer et `apple-touch-icon`. Det må peke til et ugjennomsiktig, kvadratisk PNG-bilde med sidelengde på 192 (eller 180) piksler. [Finn ut mer](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Har ikke noe gyldig `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` er utdatert – `apple-touch-icon` foretrekkes."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Har et gyldig `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome-utvidelser gjør innlastingen av denne siden tregere. Prøv å revidere siden i inkognitomodus eller fra en Chrome-profil uten utvidelser."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Skriptevaluering"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Skriptparsing"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Total CPU-tid"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Vurder å redusere tiden som brukes til parsing, kompilering og kjøring av JavaScript. Levering av mindre JS-ressurser kan bidra til dette. [Finn ut mer](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduser JavaScript-kjøretiden"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript-kjøretid"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Store GIF-er er mindre effektive for visning av animert innhold. I stedet for GIF bør du vurdere å bruke MPEG4/WebM-videoer for animasjon og PNG/WebP for statiske bilder, da dette belaster nettverket mindre. [Finn ut mer](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Bruk videoformat for animert innhold"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Vurder «lat» innlasting av bilder som er utenfor skjermen eller skjult, etter at alle kritiske ressurser er ferdig innlastet, for å redusere tiden det tar før siden blir interaktiv. [Finn ut mer](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Utsett bilder utenfor skjermen"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ressurser blokkerer første opptegning (FP) av siden. Vurder å levere kritisk JS/CSS innebygd og utsette all JS/CSS som ikke er kritisk. [Finn ut mer](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Eliminer ressurser som blokkerer gjengivelse"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Store nettverksressurser koster brukerne ekte penger og er hovedgrunnen til lange innlastingstider. [Finn ut mer](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Den totale størrelsen var {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Unngå enorme nettverksressurser"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Unngår enorme nettverksbelastninger"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Forminskede CSS-filer kan redusere nettverksbelastningen. [Finn ut mer](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Forminsk CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Forminskede JavaScript-filer kan redusere mengden data som må overføres, og parsetiden for skript. [Finn ut mer](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Forminsk JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Fjern overflødige regler fra stilark og utsett å laste inn CSS som ikke brukes på innholdet i den synlige delen av nettsiden. Da reduserer du antall byte som går med til unødvendig nettverksaktivitet. [Finn ut mer](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Fjern ubrukt CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Fjern ubrukt JavaScript for å redusere antall byte som brukes av nettverksaktiviteten."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Fjern ubrukt JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "En lang bufferlevetid kan gjøre at gjentatte besøk på siden din går raskere. [Finn ut mer](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ressurs funnet}other{# ressurser funnet}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Vis statiske ressurser med effektive buffer-retningslinjer"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Bruker effektive buffer-retningslinjer på statiske ressurser"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimaliserte bilder lastes inn raskere og bruker mindre mobildata. [Finn ut mer](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Effektiviser omgjøring av bilder til kode"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Vis bilder som har passende størrelse, for å spare mobildata og redusere innlastingstiden. [Finn ut mer](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Velg riktige bildestørrelser"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Tekstbaserte ressurser bør leveres komprimert (gzip, deflate eller brotli) for å minimere antall byte som sendes over nettverket. [Finn ut mer](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Aktiver tekstkomprimering"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Bildeformater som JPEG 2000, JPEG XR og WebP gir ofte bedre komprimering enn PNG eller JPEG, noe som betyr raskere nedlasting og mindre databruk. [Finn ut mer](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Bruk nyere bildeformater"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Hvis bredden på appinnholdet ikke samsvarer med bredden på det synlige området, er appen kanskje ikke optimalisert for mobilskjermer. [Finn ut mer](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Det synlige områdets størrelse på {innerWidth} px samsvarer ikke med vindusstørrelsen på {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Innholdet har ikke riktig størrelse i forhold til det synlige området"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Innholdet har riktig størrelse i forhold til det synlige området"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "De kritiske forespørselskjedene nedenfor viser hvilke ressurser som lastes inn med høy prioritet. Vurder å redusere lengden på kjedene, redusere nedlastingsstørrelsen på ressursene eller utsette nedlasting av unødvendige ressurser for å bedre sideinnlastingen. [Finn ut mer](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kjede funnet}other{# kjeder funnet}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimer dybden på kritiske forespørsler"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Avvikling/varsel"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linje"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Avviklede API-er kommer etter hvert til å bli fjernet fra nettleseren. [Finn ut mer](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 varsel er funnet}other{# varsler er funnet}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Bruker avviklede API-er"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Unngår å bruke avviklede API-er"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Programbufferen er avviklet. [Finn ut mer](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Fant «{AppCacheManifest}»"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Bruker programbufferen"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Unngår å bruke programbufferen"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Ved å angi en doctype forhindrer du nettleseren fra å bytte til modus for bred kompatibilitet. [Finn ut mer](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype-navnet må være strengen `html` med små bokstaver"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokumentet må ha en doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Forventet at publicId skulle være en tom streng"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Forventet at systemId skulle være en tom streng"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Siden har ikke HTML som doctype og utløser derfor modus for bred kompatibilitet."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Siden har HTML som doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistikk"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Verdi"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Nettleseringeniører anbefaler å ha mindre enn 1500 DOM-elementer på nettsider. Ideelt bør treet være mindre enn 32 elementer dypt, og det bør være færre enn 60 underordnede/overordnede elementer. Store DOM-er kan øke minnebruken, forårsake lengre [stilberegninger](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) og utløse kostbare [dynamiske tilpasninger av layouten](https://developers.google.com/speed/articles/reflow). [Finn ut mer](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}other{# elementer}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Unngå for stor DOM-struktur"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimal DOM-dybde"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Totalt antall DOM-elementer"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimalt antall underordnede elementer"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Unngå for stor DOM-struktur"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Mål"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Legg til `rel=\"noopener\"` eller `rel=\"noreferrer\"` i eksterne linker for å øke ytelsen og forhindre sikkerhetssårbarheter. [Finn ut mer](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Linker til opphavsuavhengige destinasjoner er utrygge"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Linker til opphavsuavhengige destinasjoner er trygge"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Kunne ikke avgjøre destinasjonen for ankeret ({anchorHTML}). Hvis ankeret ikke brukes som hyperlink, vurder å fjerne target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Brukere er mistroiske overfor eller blir forvirret av nettsteder som spør om posisjonen deres uten kontekst. Vurder å knytte forespørselen opp mot en brukerhandling i stedet. [Finn ut mer](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Spør om geolokaliseringstillatelsen ved sideinnlasting"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Unngår å spørre om geolokaliseringstillatelsen ved sideinnlasting"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versjon"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Alle JavaScript-grensesnittsbiblioteker som ble funnet på siden. [Finn ut mer](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript-biblioteker som ble oppdaget"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "For brukere som har trege tilkoblinger, kan eksterne skript som injiseres dynamisk via `document.write()`, forsinke sideinnlastingen med flere titalls sekunder. [Finn ut mer](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Bruker `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Unngår `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Høyeste alvorlighetsgrad"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Bibliotekversjon"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Antall sårbarheter"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Noen tredjepartsskript kan inneholde kjente sikkerhetssårbarheter som enkelt kan identifiseres og utnyttes av angripere. [Finn ut mer](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 sårbarhet er oppdaget}other{# sårbarheter er oppdaget}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Inkluderer JavaScript-grensesnittsbiblioteker med kjente sikkerhetssårbarheter"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Høy"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Lav"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Middels"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Unngår JavaScript-grensesnittsbiblioteker med kjente sikkerhetssårbarheter"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Brukere er mistroiske overfor eller blir forvirret av nettsteder som spør om å få sende varsler uten kontekst. Vurder å knytte forespørselen opp mot brukerbevegelser i stedet. [Finn ut mer](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Spør om varseltillatelsen ved sideinnlasting"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Unngår å spørre om varseltillatelsen ved sideinnlasting"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementer som ikke besto kontrollen"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Å hindre brukere i å lime inn passord underminerer gode retningslinjer for sikkerhet. [Finn ut mer](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Forhindrer brukere fra å lime inn i passordfelt"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Brukerne kan lime inn i passordfelt"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokoll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 har mange fordeler sammenlignet med HTTP/1.1, blant annet binære headers, multipleksing og aktiv meldingslevering fra tjener. [Finn ut mer](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 forespørsel ble ikke vist via HTTP/2}other{# forespørsler ble ikke vist via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Bruker ikke HTTP/2 for alle ressursene"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Bruker HTTP/2 til sine egne ressurser"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Vurder å markere aktivitetslytterne for berøring og musehjul som `passive` for å oppnå bedre ytelse ved rulling på siden. [Finn ut mer](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Bruker ikke passive lyttere for å oppnå bedre ytelse ved rulling på siden"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Bruker passive lyttere for å oppnå bedre ytelse ved rulling på siden"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Beskrivelse"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Feil som loggføres i konsollen, tyder på uløste problemer. De kan stamme fra mislykkede nettverksforespørsler og andre nettleserproblemer. [Finn ut mer](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Nettleserfeil ble loggført i konsollen"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Ingen nettleserfeil ble loggført i konsollen"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Bruk CSS-funksjonen font-display til å forsikre deg om at brukerne ser teksten mens skrifttypene for nettet lastes inn. [Finn ut mer](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Sørg for at teksten forblir synlig under innlasting av skrifttyper for nettet"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "All tekst forblir synlig under innlasting av skrifttype for nettet"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse kunne ikke automatisk kontrollere verdien av font-display for denne nettadressen: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Høyde/bredde-forhold (faktisk)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Høyde/bredde-forhold (vist)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Visningsstørrelsen for bilder bør samsvare med det naturlige høyde/bredde-forholdet. [Finn ut mer](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Viser bilder med feil høyde/bredde-forhold"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Viser bilder med riktig høyde/bredde-forhold"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Ugyldig informasjon om bildestørrelse – {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Nettlesere kan aktivt spørre brukere om de vil legge til appen på startskjermen sin. Det kan føre til økt interaksjon. [Finn ut mer](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifestet til nettprogrammet oppfyller ikke kravene til installerbarhet"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifestet til nettprogrammet oppfyller kravene til installerbarhet"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Utrygg nettadresse"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Alle nettsteder bør være beskyttet med HTTPS, selv de som ikke håndterer sensitive opplysninger. HTTPS forhindrer inntrengere fra å tukle med eller lytte passivt til kommunikasjonen mellom appen din og brukerne dine og er en forutsetning for å kunne bruke HTTP/2 og mange nye nettplattform-API-er. [Finn ut mer](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 utrygg forespørsel er funnet}other{# utrygge forespørsler er funnet}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Bruker ikke HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Bruker HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Når sider lastes inn raskt over mobilnettverk, gir det en god brukeropplevelse på mobilenheter. [Finn ut mer](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktiv etter {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Siden ble interaktiv på det simulerte mobilnettverket etter {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Siden lastes inn for sakte og blir ikke interaktiv i løpet av 10 sekunder. Se på mulighetene og diagnostikken i delen «Ytelse» for å finne ut hva som kan forbedres."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Siden lastes ikke inn raskt nok over mobilnettverk"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Siden lastes inn raskt nok over mobilnettverk"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategori"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Vurder å redusere tiden som brukes til parsing, kompilering og kjøring av JS. Levering av mindre JS-ressurser kan bidra til dette. [Finn ut mer](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimer arbeidet på hovedtråden"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimerer arbeidet på hovedtråden"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "For å nå så mange brukere som mulig bør nettsteder fungere i alle de vanligste nettleserne. [Finn ut mer](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Nettstedet fungerer i ulike nettlesere"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Sørg for at individuelle sider kan dyplinkes via nettadresser, og at nettadressene er unike, slik at de kan deles på sosiale medier. [Finn ut mer](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Hver side har en nettadresse"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Overganger skal føles smidige når du trykker deg rundt, selv på et tregt nettverk. Denne opplevelsen er avgjørende for brukerens opplevelse av ytelsen. [Finn ut mer](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Sideoverganger føles ikke som om de blokkerer på nettverket"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Beregnet inndataforsinkelse er et estimat av hvor lang tid (i millisekunder) det tar for appen å svare på brukerinndata i det travleste 5-sekunders tidsrommet mens siden lastes inn. Hvis tidsforsinkelsen er høyere enn 50 ms, kan brukere oppleve appen som treg. [Finn ut mer](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Anslått tidsforsinkelse for inndata"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Den første innholdsrike opptegningen (FCP) markerer den første gangen tekst eller bilder tegnes opp. [Finn ut mer](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Første innholdsrike opptegning"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Første prosessor ledig markerer den første gangen at sidens hovedtråd er rolig nok til å klare å håndtere inndata. [Finn ut mer](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Første prosessor ledig"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Første vesentlige opptegning måler når hovedinnholdet på en side er synlig. [Finn ut mer](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Første vesentlige opptegning"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Tid til interaktiv vil si hvor lang tid det tar før siden blir helt interaktiv. [Finn ut mer](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tid til interaktiv"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Den maksimale potensielle forsinkelsen for første inndata som brukerne dine kan oppleve, er varigheten (i millisekunder) av den lengste oppgaven. [Finn ut mer](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks forsinkelse for første inndata"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Hastighetsindeksen viser hvor raskt innholdet på siden blir synlig. [Finn ut mer](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Hastighetsindeks"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Summen av alle tidsperiodene mellom første innholdsrike opptegning (FCP) og tid til interaktiv, når oppgavelengden har overskredet 50 ms, uttrykt i millisekunder."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total blokkeringstid"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Rundturstidene (RTT) for nettverket har stor innvirkning på ytelsen. Hvis RTT-en til et bestemt opprinnelsessted er høy, tyder det på at tjenere som befinner seg nærmere brukeren, muligens kan gi bedre ytelse. [Finn ut mer](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Rundturstider for nettverket"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Tidsforsinkelser fra tjeneren kan påvirke nettytelsen. Hvis tjeneren for et bestemt opprinnelsessted har høy tidsforsinkelse, tyder det på at tjeneren er overbelastet eller har dårlig ytelse i tjenerdelen. [Finn ut mer](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Forsinkelser i tjenerdelen"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Med en tjenestearbeider kan nettprogrammet ditt vært pålitelig under uforutsigbare nettverksforhold. [Finn ut mer](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` svarer ikke med 200 når siden er uten nett"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` svarer med 200 når siden er uten nett"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse kunne ikke lese `start_url` i manifestet. Derfor ble det antatt at `start_url` var dokumentets nettadresse. Feilmelding: «{manifestWarning}»."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Over budsjett"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Sørg for at antall nettverksforespørsler og størrelsen på disse er lavere enn målene som er angitt i det aktuelle ytelsesbudsjettet. [Finn ut mer](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 forespørsel}other{# forespørsler}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Ytelsesbudsjett"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Hvis du allerede har satt opp HTTPS, må du sørge for at du viderekobler all HTTP-trafikk til HTTPS, slik at du gir alle brukerne dine tilgang til sikker nettfunksjonalitet. [Finn ut mer](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Viderekobler ikke HTTP-trafikk til HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Viderekobler HTTP-trafikk til HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Viderekoblinger fører til flere forsinkelser før siden kan lastes inn. [Finn ut mer](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Unngå flere viderekoblinger av siden"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "For å angi budsjetter for antall sideressurser og størrelsen på disse, legg til en budget.json-fil. [Finn ut mer](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 forespørsel • {byteCount, number, bytes} kB}other{# forespørsler • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Minimer antall forespørsler og størrelsen på overføringer"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanoniske linker foreslår hvilken nettadresse som skal vises i søkeresultater. [Finn ut mer](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Flere motstridende nettadresser ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Peker til et annet domene ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Ugyldig nettadresse ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Peker til en annen `hreflang`-plassering ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativ nettadresse ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Peker til domenets rotadresse (startsiden) i stedet for en tilsvarende side med innhold"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumentet har ikke noe gyldig `rel=canonical`-element"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumentet har en gyldig `rel=canonical`-link"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Skriftstørrelser på mindre enn 12 px er for små til å være leselige og gjør at besøkende på mobil må «klype for å zoome» for å klare å lese teksten. Prøv å sørge for at mer enn 60 % av teksten på siden er 12 px eller større. [Finn ut mer](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} lesbar tekst"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Teksten er uleselig fordi det ikke er noen viewport-metatag som er optimalisert for mobilskjermer."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} av teksten er for liten (basert på et utvalg på {decimalProportionVisited, number, extendedPercent} av siden)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumentet bruker ikke leselige skriftstørrelser"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumentet bruker leselige skriftstørrelser"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang-linker forteller søkemotorer hvilken sideversjon som skal føres opp i søkeresultatene for bestemte språk eller regioner. [Finn ut mer](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumentet har ikke noe gyldig `hreflang`-attributt"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumentet har et gyldig `hreflang`-attributt"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Sider med HTTP-statuskoder som indikerer mislykkede forespørsler, indekseres kanskje ikke skikkelig. [Finn ut mer](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Sidens HTTP-statuskode indikerer mislykket forespørsel"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Sidens HTTP-statuskode er gyldig"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Søkemotorer kan ikke ta med sidene dine i søkeresultatene hvis de ikke har tillatelse til å gjennomsøke dem. [Finn ut mer](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Siden er blokkert for indeksering"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Siden er ikke blokkert for indeksering"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Beskrivende linktekst hjelper søkemotorer med å forstå innholdet. [Finn ut mer](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Fant 1 link}other{Fant # linker}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linker har ikke beskrivende tekst"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linkene har beskrivende tekst"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Kjør [Testverktøy for strukturerte data](https://search.google.com/structured-data/testing-tool/) og [Structured Data Linter](http://linter.structured-data.org/) for å validere strukturerte data. [Finn ut mer](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturerte data er gyldige"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metabeskrivelser kan tas med i søkeresultater for å oppsummere sideinnholdet kort og konsist. [Finn ut mer](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Beskrivelsesteksten er tom."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumentet har ingen metabeskrivelse"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumentet har en metabeskrivelse"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Søkemotorer kan ikke indeksere innholdet i programtillegg, og mange enheter begrenser programtillegg eller støtter dem ikke. [Finn ut mer](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumentet bruker programtillegg"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumentet bruker ikke programtillegg"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Hvis robots.txt-filen har feil format, kan det hende at søkeroboter ikke forstår hvordan du vil at nettstedet ditt skal gjennomsøkes eller indekseres. [Finn ut mer](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Forespørselen om robots.txt returnerte HTTP-statusen: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Fant 1 feil}other{Fant # feil}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse kunne ikke laste ned noen robots.txt-fil"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt er ikke gyldig"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt er gyldig"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktive elementer, som knapper og linker, må være store nok (48 x 48 px) og ha nok plass rundt seg til at det er lett å trykke på dem uten at de overlapper andre elementer. [Finn ut mer](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} av de trykkbare elementene er store nok"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "De trykkbare elementene er for små fordi det ikke er noen viewport-metatag som er optimalisert for mobilskjermer"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Trykkbare elementer er ikke store nok"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Overlappende trykkbart element"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Trykkbart element"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Trykkbare elementer er store nok"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Tjenestearbeideren er teknologien som gjør at appen din kan bruke mange funksjoner for progressive nettprogrammer, f.eks. muligheten til å bruke appen uten nett, legge den til på startskjermen og sende pushvarslinger. [Finn ut mer](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Denne siden styres av en tjenestearbeider, men ingen `start_url` ble funnet fordi manifestet ikke kunne parses som gyldig JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Denne siden styres av en tjenestearbeider, men `start_url` ({startUrl}) ligger utenfor tjenestearbeiderens omfang ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Denne siden styres av en tjenestearbeider, men ingen `start_url` ble funnet fordi manifestet ikke ble hentet."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Denne plasseringen har én eller flere tjenestearbeidere, men siden ({pageUrl}) ligger utenfor omfanget."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Registrerer ikke en tjenestearbeider som styrer siden og `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registrerer en tjenestearbeider som styrer siden og `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Tematiske splash-skjermer gjør at brukerne får en kvalitetsopplevelse når de starter appen fra startskjermen. [Finn ut mer](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Er ikke konfigurert med tilpasset splash-skjerm"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigurert med tilpasset splash-skjerm"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Adressefeltet i nettleseren kan gis et tema for å stå i stil med nettstedet ditt. [Finn ut mer](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Angir ikke en temafarge for adressefeltet."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Angir en temafarge for adressefeltet."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Blokkeringstid i hovedtråden"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tredjepart"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Tredjepartskode kan ha betydelig innvirkning på hvor lang tid det tar å laste inn siden. Begrens antallet overflødige tredjepartsleverandører, og prøv å laste inn tredjepartskode etter at siden for det meste er ferdig innlastet. [Finn ut mer](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Tredjepartskode blokkerte hovedtråden i {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduser innvirkningen av tredjepartskode"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Tredjepartsbruk"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Tid til første byte identifiserer tidspunktet da tjeneren sendte et svar. [Finn ut mer](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Root-dokumentet brukte {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduser responstiden for tjener (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Svartiden til tjeneren er lav (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Varighet"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Starttid"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Type"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Vurder å utstyre appen din med brukertiming-API-et for å måle appens reelle ytelse under viktige brukeropplevelser. [Finn ut mer](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{ 1 brukertiming}other{# brukertiminger}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing – merker og intervaller"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Det ble funnet en <link> for forhåndstilkobling for {securityOrigin}, men denne ble ikke brukt av nettleseren. Kontrollér at du bruker `crossorigin`-attributtet riktig."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Vurder å legge til `preconnect`- eller `dns-prefetch`-ressurshint for å opprette tidlige tilkoblinger til viktige tredjepartsplasseringer. [Finn ut mer](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Opprett forhåndstilkobling til nødvendige domenenavn"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Det ble funnet en <link> for forhåndsinnlasting for {preloadURL}, men denne ble ikke brukt av nettleseren. Kontrollér at du bruker `crossorigin`-attributtet riktig."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Vurder å bruke `<link rel=preload>` for å prioritere henting av ressurser som for øyeblikket blir forespurt senere i sideinnlastingen. [Finn ut mer](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Forhåndsinnlast (preload) nøkkelforespørsler"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Legg til en `<meta name=\"viewport\">`-tag for å optimalisere appen for mobilskjermer. [Finn ut mer](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Fant ingen `<meta name=\"viewport\">`-tag"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Har ingen `<meta name=\"viewport\">`-tag med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Har en `<meta name=\"viewport\">`-tag med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Appen bør vise noe innhold når JavaScript er deaktivert, selv om det bare er en advarsel til brukeren om at JavaScript kreves for å bruke appen. [Finn ut mer](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Sidekroppen bør vise noe innhold hvis skriptene ikke er tilgjengelige."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Tilbyr ikke reserveinnhold når JavaScript ikke er tilgjengelig"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Inneholder noe innhold når JavaScript ikke er tilgjengelig"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Hvis du utvikler et progressivt nettprogram, kan du vurdere å bruke en tjenestearbeider, så appen fungerer uten nett. [Finn ut mer](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Den gjeldende siden svarer ikke med 200 når den er uten nett"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Den gjeldende siden svarer med 200 når den er uten nett"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Siden lastes kanskje ikke inn uten nett, fordi testnettadressen ({requested}) ble viderekoblet til «{final}». Prøv å teste den andre nettadressen direkte."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Dette er muligheter til å forbedre bruken av ARIA i programmet ditt, noe som kan gjøre opplevelsen bedre for brukere av assisterende teknologi, som skjermlesere."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Dette er muligheter til å tilby alternativt innhold for lyd og video. Dette kan gjøre opplevelsen bedre for brukere med nedsatt syn eller hørsel."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Lyd og video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Disse punktene fremhever de vanligste anbefalte fremgangsmåtene for å sikre god tilgjengelighet."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Anbefalte fremgangsmåter"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Disse kontrollene fremhever muligheter til [å gjøre nettprogrammet ditt mer tilgjengelig](https://developers.google.com/web/fundamentals/accessibility). Kun et utvalg av tilgjengelighetsproblemer kan oppdages automatisk, så du bør teste manuelt i tillegg."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Disse punktene tar for seg områder som ikke kan dekkes av automatiske testverktøy. Finn ut mer i veiledningen vår om [å utføre tilgjengelighetsgjennomganger](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Tilgjengelighet"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Dette er muligheter til å gjøre innholdet mer leselig."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Dette er muligheter til å gjøre innholdet lettere å tolke for brukere med forskjellige lokaliteter."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internasjonalisering og lokalisering"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Dette er muligheter til å gjøre kontrollene i programmet mer semantiske. Dette kan gjøre opplevelsen bedre for brukere av assisterende teknologi, som skjermlesere."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Navn og etiketter"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Dette er muligheter til å gjøre tastaturnavigeringen i programmet ditt bedre."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigering"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Dette er muligheter til å gi en bedre opplevelse når assisterende teknologi, som skjermlesere, brukes til å lese data i tabeller eller lister."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabeller og lister"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Gode fremgangsmåter"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Ytelsesbudsjetter angir standarder for ytelsen på nettstedet."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budsjetter"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Mer informasjon om ytelsen til appen din. Disse tallene har ingen [direkte innvirkning](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) på ytelsespoengsummen."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostikk"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Det mest kritiske aspektet for ytelse er hvor raskt piksler blir gjengitt på skjermen. Nøkkelberegninger: Første innholdsrike opptegning, Første vesentlige opptegning"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Forbedringer av første opptegning"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Disse forslagene kan bidra til at siden lastes inn raskere. De har ingen [direkte innvirkning](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) på ytelsespoengsummen."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Muligheter"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Beregninger"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Gjør den totale innlastingsopplevelsen bedre, slik at siden reagerer og er klar til bruk så snart som mulig. Nøkkelberegninger: Tid til interaktiv, Hastighetsindeks"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Forbedringsmuligheter"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Resultater"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Disse kontrollene validerer ulike aspekter av progressive nettprogrammer. [Finn ut mer](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Disse kontrollene kreves av den grunnleggende [sjekklisten for progressive nettprogrammer](https://developers.google.com/web/progressive-web-apps/checklist), men kontrolleres ikke automatisk av Lighthouse. De påvirker ikke poengsummen din, men det er viktig at du verifiserer dem manuelt."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressivt nettprogram"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rask og pålitelig"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Kan installeres"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA-optimalisert"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Disse kontrollene sørger for at siden din er optimalisert for god rangering i resultatene fra søkemotorer. Det finnes flere faktorer som Lighthouse ikke kontrollerer, men som kan påvirke søkerangeringen. [Finn ut mer](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Kjør disse tilleggsvalideringene på nettstedet ditt for å sjekke flere anbefalte fremgangsmåter for SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatér HTML-koden din på en måte som gjør det enklere for søkeroboter å forstå innholdet i appen."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Anbefalte fremgangsmåter for innhold"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Søkeroboter trenger tilgang til appen din for at den skal vises i søkeresultater."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Gjennomsøking og indeksering"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Sørg for at sidene dine er mobilvennlige, så brukere ikke trenger å klype eller zoome inn for å lese innholdssidene. [Finn ut mer](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobilvennlig"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Buffer-TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Posisjon"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Navn"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Forespørsler"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Ressurstype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Størrelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Brukt tid"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Overføringsstørrelse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "Nettadresse"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potensielle besparelser"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potensielle besparelser"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potensielle besparelser på {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potensielle besparelser på {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Skrifttype"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Bilde"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Medier"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Annet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stilark"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tredjepart"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Totalt"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Noe gikk galt med sporingsregistreringen for sideinnlastingen. Kjør Lighthouse på nytt. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Tidsavbrudd under venting på første tilkobling fra feilsøkingsprogramprotokollen."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome samlet ingen skjermdumper under innlasting av siden. Sørg for at det finnes synlig innhold på siden, og prøv deretter å kjøre Lighthouse på nytt. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-tjenerne kunne ikke oversette domenet du oppga."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Den obligatoriske {artifactName}-samleren støtte på en feil: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Det oppsto en intern Chrome-feil. Start Chrome på nytt, og prøv å kjøre Lighthouse igjen."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Den obligatoriske {artifactName}-samleren ble ikke kjørt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse kunne ikke laste inn den forespurte siden på en pålitelig måte. Sjekk at du tester riktig nettadresse, og at tjeneren svarer ordentlig på alle forespørsler."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse kunne ikke laste inn den forespurte nettadressen på en pålitelig måte, fordi siden sluttet å svare."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Nettadressen du oppga, har ikke noe gyldig sikkerhetssertifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome forhindret siden fra å lastes inn og viste en interstitial-skjerm i stedet. Sjekk at du tester riktig nettadresse, og at tjeneren svarer ordentlig på alle forespørsler."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse kunne ikke laste inn den forespurte siden på en pålitelig måte. Sjekk at du tester riktig nettadresse, og at tjeneren svarer ordentlig på alle forespørsler. (Detaljer: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse kunne ikke laste inn den forespurte siden på en pålitelig måte. Sjekk at du tester riktig nettadresse, og at tjeneren svarer ordentlig på alle forespørsler. (Statuskode: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Det tok for lang tid å laste inn siden. Følg tipsene i rapporten for å redusere sideinnlastingstiden, og prøv deretter å kjøre Lighthouse på nytt. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Venting på DevTools-protokollsvar har overskredet den kvoterte tiden. (Metode: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Henting av ressursinnhold har overskredet den kvoterte tiden"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Nettadressen du oppga, ser ut til å være ugyldig."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Vis revisjoner"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navigasjonsstart"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimum kritisk baneforsinkelse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Feil!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Rapportfeil: ingen revisjonsinformasjon"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Prøvefunksjonsdata"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/)-analyse av den nåværende siden på et emulert mobilnettverk. Verdiene er anslått og kan variere."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Tilleggselementer for manuell kontroll"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Ikke relevant"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Mulighet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Estimerte besparelser"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Beståtte revisjoner"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Skjul fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Vis fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Vis tredjepartsressurser"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Det oppsto problemer som påvirker denne kjøringen av Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Verdiene er anslått og kan variere. Ytelsespoengsummen er [kun basert på disse verdiene](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Revisjoner som er bestått, men med advarsler"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Advarsler: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Vurder å laste opp GIF-filen til en tjeneste som gjør det mulig å bygge den inn som en HTML5-video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installer et [WordPress-programtillegg for utsatt innlasting](https://wordpress.org/plugins/search/lazy+load/) som gjør det mulig å utsette innlasting av bilder som ikke er på skjermen, eller bytt til et tema som gir denne funksjonaliteten. Vurder også å bruke [AMP-programtillegget](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Det finnes en rekke WordPress-programtillegg som kan hjelpe deg med å [bygge inn kritiske elementer direkte på siden](https://wordpress.org/plugins/search/critical+css/) eller [utsette innlasting av mindre viktige ressurser](https://wordpress.org/plugins/search/defer+css+javascript/). Vær obs på at optimalisering som gjøres av disse programtilleggene, kan ødelegge funksjonalitet i temaet ditt eller programtilleggene dine, så du må sannsynligvis gjøre kodeendringer."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Både temaer, programtillegg og tjenerspesifikasjoner virker inn på tjenerens responstid. Vurder å finne et mer optimalisert tema, velge et programtillegg for optimalisering nøye og/eller oppgradere tjeneren."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Vurder å vise utdrag på innleggslistene (f.eks. via Mer-taggen), redusere antall innlegg som vises på en gitt side, fordele lange innlegg på flere sider eller bruke et programtillegg for utsatt innlasting av kommentarer."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "En rekke [WordPress-programtillegg](https://wordpress.org/plugins/search/minify+css/) kan gjøre nettstedet ditt raskere ved å slå sammen, forminske og komprimere stilarkene dine. Det kan også være lurt å bruke en byggeprosess til å gjøre denne forminskningen på forhånd hvis mulig."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "En rekke [WordPress-programtillegg](https://wordpress.org/plugins/search/minify+javascript/) kan gjøre nettstedet ditt raskere ved å slå sammen, forminske og komprimere skriptene dine. Det kan også være lurt å bruke en byggeprosess til å gjøre denne forminskningen på forhånd hvis mulig."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Vurder å redusere eller endre antall [WordPress-programtillegg](https://wordpress.org/plugins/) som laster inn ubrukt CSS på siden. For å identifisere programtillegg som legger til overflødig CSS, prøv å kjøre [kodedekning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chrome DevTools. Du kan finne det ansvarlige temaet eller programtillegget i nettadressen til stilarket. Se opp for programtillegg som har mange stilark på listen, og som viser mye rødt i kodedekningen. Programtillegg bør bare legge stilark i kø hvis de faktisk brukes på siden."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Vurder å redusere eller endre antall [WordPress-programtillegg](https://wordpress.org/plugins/) som laster inn ubrukt JavaScript på siden. For å identifisere programtillegg som legger til overflødig JavaScript, prøv å kjøre [kodedekning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chrome DevTools. Du kan finne det ansvarlige temaet eller programtillegget i nettadressen til skriptet. Se opp for programtillegg som har mange skript på listen, og som viser mye rødt i kodedekningen. Programtillegg bør bare legge skript i kø hvis de faktisk brukes på siden."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Les om [nettleserbufring i WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Vurder å bruke et [WordPress-programtillegg for bildeoptimalisering](https://wordpress.org/plugins/search/optimize+images/) som komprimerer bildene uten at det går ut over kvaliteten."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Last opp bilder direkte gjennom [mediebiblioteket](https://codex.wordpress.org/Media_Library_Screen) for å sikre at de nødvendige bildestørrelsene er tilgjengelige, og sett dem deretter inn fra mediebiblioteket eller bruk bildemodulen for å sikre at de optimale bildestørrelsene brukes (inkludert dem som brukes for responsive stoppunkter). Unngå å bruke `Full Size`-bilder med mindre størrelsen er tilstrekkelig for bruksområdet. [Finn ut mer](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Du kan slå på tekstkomprimering i oppsettet av nettjeneren."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Vurder å bruke et [programtillegg](https://wordpress.org/plugins/search/convert+webp/) eller en tjeneste som automatisk konverterer opplastede bilder til de optimale formatene."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pl.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pl.json
new file mode 100644
index 00000000000..3be8eea5c1d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pl.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Klawisze dostępu umożliwiają szybkie ustawienie fokusu na określonej części strony. Aby nawigacja działała dobrze, każdy klawisz dostępu musi być unikalny. [Więcej informacji](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Wartości `[accesskey]` nie są unikalne"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Wartości `[accesskey]` są unikalne"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Każda `role` ARIA obsługuje podzbiór atrybutów `aria-*`. Brak ich dopasowania skutkuje niepoprawnością atrybutów `aria-*`. [Więcej informacji](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atrybuty `[aria-*]` nie pasują do swoich ról"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atrybuty `[aria-*]` odpowiadają swoim rolom"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Niektóre role ARIA mają atrybuty wymagane, które opisują stan elementu na potrzeby czytników ekranu. [Więcej informacji](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Elementy z atrybutem `[role]` nie mają wszystkich wymaganych atrybutów `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Elementy `[role]` mają wszystkie wymagane atrybuty `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Niektóre role nadrzędne ARIA muszą zawierać określone role podrzędne, by poprawnie realizować funkcje ułatwień dostępu. [Więcej informacji](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementy z atrybutem ARIA `[role]`, których elementy podrzędne muszą zawierać określony atrybut `[role]`, nie mają niektórych lub wszystkich tych wymaganych elementów podrzędnych."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementy z atrybutem ARIA `[role]`, których elementy podrzędne muszą zawierać określony atrybut `[role]`, mają wszystkie wymagane elementy podrzędne."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Niektóre role podrzędne ARIA muszą znajdować się wewnątrz określonych ról nadrzędnych, by poprawnie realizować funkcje ułatwień dostępu. [Więcej informacji](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Elementy `[role]` nie znajdują się wewnątrz wymaganych elementów nadrzędnych"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Elementy `[role]` znajdują się wewnątrz wymaganych elementów nadrzędnych"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Role ARIA muszą mieć prawidłowe wartości, by poprawnie realizować funkcje ułatwień dostępu. [Więcej informacji](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Wartości `[role]` są nieprawidłowe"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Wartości `[role]` są prawidłowe"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Technologie wspomagające, takie jak czytniki ekranu, nie potrafią interpretować atrybutów ARIA o nieprawidłowej wartości. [Więcej informacji](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atrybuty `[aria-*]` nie mają prawidłowych wartości"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atrybuty `[aria-*]` mają prawidłowe wartości"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Technologie wspomagające, takie jak czytniki ekranu, nie potrafią interpretować atrybutów ARIA o nieprawidłowych nazwach. [Więcej informacji](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atrybuty `[aria-*]` są nieprawidłowe lub są w nich literówki"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atrybuty `[aria-*]` są prawidłowe i nie ma w nich literówek"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Dzięki napisom z elementów audio mogą korzystać osoby niesłyszące i słabosłyszące. Napisy zawierają ważne informacje na przykład o tym, kto i co mówi, a także informacje niedotyczące mowy. [Więcej informacji](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementy `<audio>` nie mają elementu `<track>` z atrybutem `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementy `<audio>` zawierają element `<track>` z atrybutem `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Nieprawidłowe elementy"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Gdy przycisk nie ma nazwy na potrzeby ułatwień dostępu, czytniki ekranu określają go jako „przycisk”, przez co jest on bezużyteczny dla ich użytkowników. [Więcej informacji](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Przyciski nie mają nazw dostępnych dla czytników ekranu"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Przyciski mają nazwy dostępne dla czytników ekranu"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Dodanie sposobu na ominięcie powtarzających się treści ułatwia nawigację na stronie za pomocą klawiatury. [Więcej informacji](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Strona nie zawiera nagłówka, linku pomijającego ani regionu orientacyjnego"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Strona zawiera nagłówek, link pomijający lub region orientacyjny"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Wielu użytkowników ma problemy z czytaniem tekstu o niskim kontraście. [Więcej informacji](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Kolory tła i pierwszego planu mają niewystarczający współczynnik kontrastu."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Kolory tła i pierwszego planu mają wystarczający współczynnik kontrastu"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Gdy listy definicji nie mają właściwej struktury, czytniki ekranu mogą odczytywać je niedokładnie lub błędnie. [Więcej informacji](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Elementy `<dl>` nie zawierają tylko właściwie uporządkowanych grup elementów `<dt>` i `<dd>` oraz elementów `<script>` lub `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Elementy `<dl>` zawierają tylko właściwie uporządkowane grupy elementów `<dt>` i `<dd>` oraz elementy `<script>` lub `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Elementy listy definicji (`<dt>` i `<dd>`) muszą znajdować się wewnątrz nadrzędnego elementu `<dl>`, by mogły je poprawnie odczytać czytniki ekranu. [Więcej informacji](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Elementy listy definicji nie znajdują się wewnątrz elementów `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Elementy listy definicji znajdują się wewnątrz elementów `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Tytuł informuje użytkowników czytnika ekranu o ogólnej zawartości strony, a użytkownicy wyszukiwarki mogą dowiedzieć się z niego, czy strona zawiera szukane informacje. [Więcej informacji](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "W dokumencie nie ma elementu `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument zawiera element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Wartość atrybutu id musi być unikalna, by inne wystąpienia nie zostały pominięte przez technologie wspomagające. [Więcej informacji](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atrybuty `[id]` na stronie nie są unikalne"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atrybuty `[id]` na stronie są unikalne"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Tytuły ramek służą użytkownikom czytników ekranu jako opisy zawartości ramek. [Więcej informacji](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Element `<frame>` lub `<iframe>` nie ma tytułu"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementy `<frame>` i `<iframe>` mają tytuł"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Jeśli strona nie ma atrybutu lang, czytnik ekranu przyjmuje, że strona jest w języku domyślnym, który użytkownik wybrał podczas konfigurowania czytnika. Jeśli strona nie jest w języku domyślnym, czytnik ekranu może niepoprawnie wymawiać tekst strony. [Więcej informacji](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Element `<html>` nie ma atrybutu `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Element `<html>` ma atrybut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Określenie prawidłowego [języka w formacie BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) pomaga czytnikom ekranu prawidłowo wymawiać tekst. [Więcej informacji](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Element `<html>` nie ma prawidłowej wartości atrybutu `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Element `<html>` ma prawidłową wartość atrybutu `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Elementy informacyjne powinny mieć krótki, opisowy tekst zastępczy. Elementy dekoracyjne można zignorować, podając pusty atrybut alt. [Więcej informacji](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elementy graficzne nie mają atrybutów `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elementy graficzne mają atrybuty `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Gdy jako przycisk `<input>` używany jest obraz, warto dodać tekst zastępczy, by ułatwić użytkownikom czytnika ekranu zrozumienie, do czego służy ten przycisk. [Więcej informacji](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementy `<input type=\"image\">` nie mają tekstu `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementy `<input type=\"image\">` mają tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etykiety zapewniają prawidłowe odczytywanie kontrolek formularzy przez technologie wspomagające takie jak czytniki ekranu. [Więcej informacji](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Z elementami formularzy nie są powiązane etykiety"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Z elementami formularzy są powiązane etykiety"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabela używana do tworzenia układu graficznego nie powinna zawierać elementów danych, takich jak elementy th czy caption albo atrybut summary, ponieważ mogą one utrudniać korzystanie z czytnika ekranu. [Więcej informacji](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "W prezentacyjnych elementach `<table>` są używane elementy `<th>` lub `<caption>` albo atrybut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "W prezentacyjnych elementach `<table>` nie są używane elementy `<th>` i `<caption>` ani atrybut `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Tekst linków (i tekst zastępczy obrazów używanych jako linki), który jest charakterystyczny, unikalny i możliwy do wybrania, ułatwia nawigację użytkownikom czytników ekranu. [Więcej informacji](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Linki nie mają wyróżniających je nazw"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Linki mają wyróżniające je nazwy"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Czytniki ekranu odczytują listy w specjalny sposób. Właściwa struktura list pomaga czytnikom poprawnie odczytać tekst. [Więcej informacji](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listy nie zawierają tylko elementów `<li>` i elementów skryptowych (`<script>` i `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listy zawierają tylko elementy `<li>` i elementy skryptowe (`<script>` i `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Elementy list (`<li>`) muszą być zawarte w elementach nadrzędnych `<ul>` lub `<ol>`, by czytniki ekranu mogły je poprawnie odczytać. [Więcej informacji](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Elementy list (`<li>`) nie znajdują się wewnątrz elementów nadrzędnych `<ul>` lub `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Elementy list (`<li>`) znajdują się wewnątrz elementów nadrzędnych `<ul>` lub `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Użytkownicy nie spodziewają się automatycznego odświeżania strony – powoduje ono powrót zaznaczenia na jej początek. Może to dezorientować i irytować użytkowników. [Więcej informacji](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokument używa tagu `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokument nie używa tagu `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Wyłączenie powiększania to problem dla użytkowników niedowidzących, którzy muszą korzystać z powiększenia ekranu, by dobrze widzieć zawartość stron internetowych. [Więcej informacji](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "W elemencie `<meta name=\"viewport\">` jest używany atrybut `[user-scalable=\"no\"]` lub atrybut `[maximum-scale]` ma wartość mniejszą niż 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "W elemencie `<meta name=\"viewport\">` nie jest używany atrybut `[user-scalable=\"no\"]`, a atrybut `[maximum-scale]` ma wartość nie mniejszą niż 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Czytniki ekranu nie potrafią tłumaczyć treści innych niż tekst. Dodanie do elementów `<object>` tekstu zastępczego pomaga czytnikom ekranu w przekazywaniu użytkownikom właściwego znaczenia. [Więcej informacji](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementy `<object>` nie mają tekstu `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementy `<object>` mają tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Wartość większa niż 0 implikuje określoną wprost kolejność nawigacji. Chociaż takie rozwiązanie jest technicznie poprawne, często powoduje frustrację użytkowników technologii wspomagających. [Więcej informacji](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Niektóre elementy mają atrybut `[tabindex]` o wartości większej niż 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Żaden element nie ma wartości atrybutu `[tabindex]` większej niż 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Czytniki ekranu mają funkcje, które ułatwiają nawigację w tabelach. Gdy komórki `<td>` używające atrybutu `[headers]` odwołują się tylko do innych komórek w tej samej tabeli, użytkownicy czytników ekranu mogą wygodniej korzystać z tabel. [Więcej informacji](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Komórki w elemencie `<table>`, które używają atrybutu `[headers]`, odwołują się do elementu `id`, którego nie znaleziono w tej samej tabeli."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Komórki w elemencie `<table>`, które używają atrybutu `[headers]`, odwołują się do komórek w tej samej tabeli."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Czytniki ekranu mają funkcje, które ułatwiają nawigację w tabelach. Gdy nagłówki tabel zawsze odwołują się do jakiegoś zbioru komórek, użytkownicy czytników ekranu mogą wygodniej korzystać z tabel. [Więcej informacji](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Nie istnieją komórki danych opisywane przez elementy `<th>` i elementy z atrybutem `[role=\"columnheader\"/\"rowheader\"]`."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Istnieją komórki danych opisywane przez elementy `<th>` i elementy z atrybutem `[role=\"columnheader\"/\"rowheader\"]`."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Określenie w elementach prawidłowego [tagu języka w formacie BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) pomaga zapewnić prawidłową wymowę tekstu przez czytnik ekranu. [Więcej informacji](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atrybuty `[lang]` nie mają prawidłowej wartości"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atrybuty `[lang]` mają prawidłową wartość"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Filmy z napisami są bardziej dostępne dla osób niesłyszących i niedosłyszących. [Więcej informacji](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementy `<video>` nie zawierają elementu `<track>` z atrybutem `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementy `<video>` zawierają element `<track>` z atrybutem `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audiodeskrypcja dostarcza ważnych informacji, których nie ma w dialogach – na przykład o wyrazie twarzy i scenerii. [Więcej informacji](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementy `<video>` nie zawierają elementu `<track>` z atrybutem `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementy `<video>` zawierają element `<track>` z atrybutem `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Zdefiniuj element `apple-touch-icon`, by Twoja progresywna aplikacja internetowa wyglądała idealnie na iOS, gdy użytkownicy dodadzą ją do ekranu głównego. Element musi wskazywać kwadratowy obraz PNG o rozmiarze 192 (lub 180) pikseli bez przezroczystości. [Więcej informacji](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Nie dostarcza prawidłowego atrybutu `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Atrybut `apple-touch-icon-precomposed` jest przestarzały. Preferowany jest `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Dostarcza prawidłowy atrybut `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Rozszerzenia Chrome pogorszyły szybkość ładowania tej strony. Przeprowadź audyt strony w trybie incognito lub w profilu Chrome bez rozszerzeń."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Ocena skryptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analiza skryptów"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Łączny czas pracy procesora"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Pomyśl o skróceniu czasu poświęcanego na analizowanie, kompilowanie i wykonywanie kodu JS. Może w tym pomóc dostarczanie mniejszych ładunków JS. [Więcej informacji](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Skróć czas wykonywania JavaScriptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Czas wykonania JavaScriptu"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Duże pliki GIF są nieefektywnym sposobem dostarczania animacji. Proponujemy użyć zamiast nich filmów MPEG4/WebM (animacje) lub plików PNG/WebP (obrazy statyczne), by zmniejszyć ilość przesyłanych danych. [Więcej informacji](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Użyj formatów wideo dla animacji"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Aby skrócić czas do pełnej interaktywności, warto skorzystać z leniwego ładowania. Dzięki temu najpierw będą ładowane wszystkie zasoby kluczowe, a dopiero potem obrazy ukryte i znajdujące się poza ekranem. [Więcej informacji](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Odłóż ładowanie obrazów poza ekranem"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Zasoby blokują pierwsze wyrenderowanie strony. Sugerujemy umieszczenie krytycznego kodu JS/CSS w kodzie strony i opóźnienie ładowania wszystkich niekrytycznych plików JS i stylów. [Więcej informacji](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Wyeliminuj zasoby blokujące renderowanie"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Duże ładunki sieciowe powodują wyższe koszty dla użytkowników i są mocno powiązane z długim czasem ładowania. [Więcej informacji](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Łączny rozmiar to {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Unikaj bardzo dużych ładunków sieciowych"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Unikaj bardzo dużych ładunków sieciowych"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minifikacja plików CSS może zmniejszyć ładunki sieciowe. [Więcej informacji](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minifikuj CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minifikacja plików JavaScript może zmniejszyć ładunki i skrócić czas analizowania skryptów. [Więcej informacji](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minifikuj JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Usuń nieużywane reguły z arkuszy stylów i opóźnij ładowanie kodu CSS, który nie jest używany w części strony widocznej na ekranie bez przewijania, by zmniejszyć ilość danych niepotrzebnie przesyłanych w sieci. [Więcej informacji](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Usuń nieużywany kod CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Usuń nieużywany kod JavaScript, by zmniejszyć ilość danych przesyłanych w sieci."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Usuń nieużywany JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Długi czas przechowywania w pamięci podręcznej może przyśpieszyć ponowne otwarcie strony. [Więcej informacji](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Znaleziono 1 zasób}few{Znaleziono # zasoby}many{Znaleziono # zasobów}other{Znaleziono # zasobu}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Wyświetlaj zasoby statyczne, stosując efektywne zasady pamięci podręcznej"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Stosuje efektywne zasady pamięci podręcznej dla zasobów statycznych"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Zoptymalizowane obrazy ładują się szybciej i wykorzystują mniej komórkowej transmisji danych. [Więcej informacji](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Użyj efektywnego kodowania obrazów"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Wyświetlaj obrazy o odpowiednim rozmiarze, by oszczędzać komórkową transmisję danych i przyśpieszyć ładowanie. [Więcej informacji](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Zmień rozmiar obrazów"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Zasoby tekstowe powinny być kompresowane (gzip, deflate lub brotli), by zminimalizować ilość danych przesyłanych w sieci. [Więcej informacji](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Włącz kompresję tekstu"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Takie formaty obrazów jak JPEG 2000, JPEG XR i WebP często zapewniają lepszą kompresję niż PNG czy JPEG, co przekłada się na szybsze pobieranie i mniejsze wykorzystanie danych. [Więcej informacji](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Wyświetlaj obrazy w formatach nowej generacji"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Jeśli szerokość zawartości aplikacji nie odpowiada szerokości widocznego obszaru, aplikacja może nie być zoptymalizowana pod kątem ekranów urządzeń mobilnych. [Więcej informacji](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Rozmiar widocznego obszaru ({innerWidth} piks.) nie odpowiada rozmiarowi okna ({outerWidth} piks.)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Zawartość nie jest odpowiednio dopasowana do widocznego obszaru"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Zawartość jest odpowiednio dopasowana do widocznego obszaru"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Poniższe łańcuchy żądań krytycznych pokazują zasoby ładowane z wysokim priorytetem. Aby przyśpieszyć ładowanie strony, możesz skrócić łańcuchy, zmniejszyć rozmiar pobieranych zasobów lub opóźnić pobieranie zasobów, które nie są niezbędne. [Więcej informacji](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Znaleziono 1 łańcuch}few{Znaleziono # łańcuchy}many{Znaleziono # łańcuchów}other{Znaleziono # łańcucha}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Zminimalizuj głębię żądań krytycznych"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Wycofanie/ostrzeżenie"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Wiersz"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Wycofane interfejsy API zostaną w przyszłości usunięte z przeglądarki. [Więcej informacji](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Znaleziono 1 ostrzeżenie}few{Znaleziono # ostrzeżenia}many{Znaleziono # ostrzeżeń}other{Znaleziono # ostrzeżenia}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Używa wycofanych interfejsów API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Nie używa wycofanych interfejsów API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Pamięć podręczna aplikacji została wycofana. [Więcej informacji](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Znaleziono „{AppCacheManifest}”"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Używa pamięci podręcznej aplikacji"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Nie używa pamięci podręcznej aplikacji"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Podanie definicji doctype zapobiega przełączaniu przeglądarki w tryb osobliwości. [Więcej informacji](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Nazwa określona w doctype musi być ciągiem małych liter `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument musi zawierać deklarację doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Oczekiwano pustego ciągu w polu publicId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Oczekiwano pustego ciągu w polu systemId"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Strona nie zawiera elementu HTML doctype, przez co aktywuje tryb osobliwości"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Strona ma deklarację doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statystyki"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Wartość"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Twórcy przeglądarek zalecają, by strony zawierały mniej niż około 1500 elementów DOM. Optymalne jest drzewo o głębokości mniejszej niż 32 elementy i zawierające mniej niż 60 elementów podrzędnych/nadrzędnych. Duży DOM może zwiększyć wykorzystanie pamięci, wydłużyć [obliczanie stylów](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) i powodować kosztowne [przeformatowania układu](https://developers.google.com/speed/articles/reflow). [Więcej informacji](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}few{# elementy}many{# elementów}other{# elementu}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Unikaj zbyt dużego DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksymalna głębokość DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Łączna liczba elementów DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksymalna liczba elementów podrzędnych"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Unika zbyt dużego DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Dodaj atrybut `rel=\"noopener\"` lub `rel=\"noreferrer\"` do wszystkich linków zewnętrznych, by przyśpieszyć działanie i zapobiec lukom w zabezpieczeniach. [Więcej informacji](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Linki do innych domen są niebezpieczne"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Linki do innych domen są bezpieczne"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nie można ustalić miejsca docelowego dla kotwicy ({anchorHTML}). Jeśli nie jest używana jako hiperlink, sugerujemy usunięcie atrybutu target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Witryny, które bez kontekstu pytają o zgodę na dostęp do lokalizacji, nie budzą zaufania użytkowników lub ich dezorientują. Sugerujemy powiązanie wyświetlenia tej prośby z działaniem użytkownika. [Więcej informacji](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Pyta o zgodę na geolokalizację podczas wczytywania strony"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Nie pyta o zgodę na geolokalizację podczas wczytywania strony"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Wersja"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Wszystkie biblioteki JavaScript interfejsu użytkownika wykryte na stronie. [Więcej informacji](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Wykryte biblioteki JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "W przypadku wolnego połączenia sieciowego skrypty zewnętrzne dodawane dynamicznie przy użyciu instrukcji `document.write()` mogą opóźnić wczytanie strony o dziesiątki sekund. [Więcej informacji](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Używa instrukcji `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Nie używa instrukcji `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Najwyższy poziom zagrożenia"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Wersja biblioteki"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Liczba luk w zabezpieczeniach"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Niektóre skrypty spoza witryny mogą mieć znane luki w zabezpieczeniach, które mogą łatwo odkryć i wykorzystać hakerzy. [Więcej informacji](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Wykryto 1 lukę w zabezpieczeniach}few{Wykryto # luki w zabezpieczeniach}many{Wykryto # luk w zabezpieczeniach}other{Wykryto # luki w zabezpieczeniach}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Używa bibliotek JavaScript interfejsu użytkownika, które mają znane luki w zabezpieczeniach"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Wysoki"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Niski"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Średni"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Nie używa bibliotek JavaScript interfejsu użytkownika, które mają znane luki w zabezpieczeniach"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Witryny, które bez kontekstu pytają o zgodę na wyświetlanie powiadomień, nie budzą zaufania użytkowników lub ich dezorientują. Sugerujemy powiązanie wyświetlenia tej prośby z gestami użytkownika. [Więcej informacji](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Pyta o zgodę na wyświetlanie powiadomień podczas wczytywania strony"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Nie pyta o zgodę na wyświetlanie powiadomień podczas wczytywania strony"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Nieprawidłowe elementy"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Uniemożliwianie wklejania haseł jest sprzeczne z dobrymi zasadami bezpieczeństwa. [Więcej informacji](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Uniemożliwia wklejanie tekstu w polach haseł"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Pozwala wklejać tekst w polach haseł"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokół"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ma wiele funkcji niedostępnych w HTTP/1.1, m.in. nagłówki binarne, multipleksowanie i komunikaty push z serwera. [Więcej informacji](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 żądanie nieprzesłane przez HTTP/2}few{# żądania nieprzesłane przez HTTP/2}many{# żądań nieprzesłanych przez HTTP/2}other{# żądania nieprzesłanego przez HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nie używa HTTP/2 dla wszystkich swoich zasobów"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Używa HTTP/2 dla własnych zasobów"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Proponujemy oznaczenie detektorów zdarzeń dotyku i kółka myszy jako `passive`, by poprawić działanie przewijania strony. [Więcej informacji](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nie używa pasywnych detektorów do poprawy działania przewijania"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Używa detektorów pasywnych do poprawy działania przewijania"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Opis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Błędy zarejestrowane w konsoli wskazują na nierozwiązane problemy. Mogą być spowodowane nieudanymi żądaniami sieciowymi i innymi problemami w przeglądarce. [Więcej informacji](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Błędy przeglądarki zostały zarejestrowane w konsoli"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "W konsoli nie zostały zarejestrowane żadne błędy przeglądarki"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Użyj funkcji CSS „font-display”, by zapewnić widoczność tekstu dla użytkownika podczas ładowania czcionek internetowych. [Więcej informacji](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Zapewnij widoczność tekstu podczas ładowania czcionek internetowych"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Cały tekst pozostaje widoczny podczas ładowania czcionek internetowych"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Narzędziu Lighthouse nie udało się automatycznie sprawdzić wartości font-display dla tego adresu URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Współczynnik proporcji (rzeczywisty)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Współczynnik proporcji (wyświetlany)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Wymiary wyświetlanego obrazu muszą odpowiadać naturalnemu współczynnikowi proporcji. [Więcej informacji](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Wyświetla obrazy o niepoprawnym współczynniku proporcji"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Wyświetla obrazy o poprawnym współczynniku proporcji"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Nieprawidłowa informacja o rozmiarze obrazu {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Przeglądarki mogą aktywnie prosić użytkowników o dodanie Twojej aplikacji do ekranu głównego, co może przekładać się na większe zaangażowanie. [Więcej informacji](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Plik manifestu aplikacji internetowej nie spełnia wymagań instalowalności"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Plik manifestu aplikacji internetowej spełnia wymagania instalowalności"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Niezabezpieczony URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Wszystkie witryny powinny być zabezpieczone przy użyciu HTTPS – również te, które nie obsługują danych wrażliwych. HTTPS uniemożliwia intruzom modyfikowanie i podsłuchiwanie komunikacji między aplikacją a użytkownikami. HTTP/2 i liczne nowe interfejsy API platformy WWW wymagają używania HTTPS. [Więcej informacji](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Wykryto 1 niezabezpieczone żądanie}few{Wykryto # niezabezpieczone żądania}many{Wykryto # niezabezpieczonych żądań}other{Wykryto # niezabezpieczonego żądania}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nie używa HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Używa HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Szybkie wczytywanie stron przez sieć komórkową zapewnia dobre wrażenia użytkowników telefonów. [Więcej informacji](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktywna po {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktywna w symulowanej sieci komórkowej po {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Strona wczytuje się zbyt wolno i nie jest interaktywna w ciągu 10 sekund. Zapoznaj się z możliwościami usprawnień i diagnostyką w sekcji „Wydajność”, by dowiedzieć się, co możesz poprawić."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Wczytywanie strony przez sieć komórkową nie jest dostatecznie szybkie"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Wczytywanie strony przez sieć komórkową jest dostatecznie szybkie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategoria"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Pomyśl o skróceniu czasu poświęcanego na analizowanie, kompilowanie i wykonywanie kodu JS. Może w tym pomóc dostarczanie mniejszych ładunków JS. [Więcej informacji](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Zminimalizuj aktywność głównego wątku"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimalizuje aktywność głównego wątku"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Witryny powinny działać w każdej popularnej przeglądarce, by mogło do nich dotrzeć jak najwięcej użytkowników. [Więcej informacji](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Witryna działa w różnych przeglądarkach"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Upewnij się, że do poszczególnych stron można dotrzeć za pomocą precyzyjnych linków w postaci adresów URL i że adresy URL są unikalne na potrzeby udostępniania w mediach społecznościowych. [Więcej informacji](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Każda strona ma swój URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Przejścia po kliknięciu powinny być płynne, nawet jeśli sieć jest wolna. Ma to kluczowe znaczenie dla postrzegania szybkości działania przeglądarki. [Więcej informacji](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Przejścia między stronami nie sprawiają wrażenia, jakby zacinały się z powodu opóźnień w sieci"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Szacowane opóźnienie reakcji jest szacunkowym czasem (w milisekundach), po którym aplikacja reaguje na działanie użytkownika w trakcie najbardziej intensywnego, pięciosekundowego okresu ładowania strony. Jeśli opóźnienie jest większe niż 50 ms, użytkownicy mogą uznać aplikację za powolną. [Więcej informacji](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Szacowane opóźnienie reakcji"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Pierwsze wyrenderowanie treści oznacza czas wyrenderowania pierwszego tekstu lub obrazu. [Więcej informacji](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Pierwsze wyrenderowanie treści"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "CPU bezczynny po raz pierwszy oznacza czas, gdy wątek główny na stronie jest po raz pierwszy na tyle mało obciążony, że może obsługiwać działania użytkownika. [Więcej informacji](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU bezczynny po raz pierwszy"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Pierwsze wyrenderowanie elementu znaczącego oznacza czas pojawienia się na ekranie głównej zawartości strony. [Więcej informacji](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Pierwsze wyrenderowanie elementu znaczącego"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Czas do pełnej interaktywności to czas, po którym strona staje się w pełni interaktywna. [Więcej informacji](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Czas do pełnej interaktywności"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Maksymalne opóźnienie przy pierwszym działaniu, którego mogą doświadczyć użytkownicy, to czas wykonywania (w milisekundach) najdłuższego zadania. [Więcej informacji](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks. potencjalne opóźnienie przy 1. działaniu"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indeks szybkości wskazuje, jak szybko strona zapełnia się widocznymi treściami. [Więcej informacji](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indeks szybkości"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Wyrażona w milisekundach suma wszystkich okresów między pierwszym wyrenderowaniem treści a czasem do pełnej interaktywności, gdy długość zadania przekroczyła 50 ms."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Łączny czas zablokowania"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Czas błądzenia w sieci (RTT) ma duży wpływ na szybkość działania. Jeśli RTT do źródła jest duży, serwery znajdujące się bliżej użytkownika mogą przyśpieszyć działanie. [Więcej informacji](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Czasy błądzenia w sieci (Network Round Trip Times)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Opóźnienie serwera może wpływać na szybkość stron internetowych. Jeśli opóźnienie serwera źródłowego jest duże, serwer może być przeciążony lub mieć mało wydajny backend. [Więcej informacji](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Opóźnienia backendu serwera"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Skrypt service worker pozwala aplikacji działać stabilnie w nieprzewidywalnych warunkach sieciowych. [Więcej informacji](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` nie wyświetla błędu 200, kiedy jest offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` wyświetla błąd 200, kiedy jest offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Narzędziu Lighthouse nie udało się odczytać elementu `start_url` z pliku manifestu. Dlatego uznano, że `start_url` to URL dokumentu. Komunikat o błędzie: „{manifestWarning}”."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Przekroczenie budżetu"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Liczba ani rozmiar żądań sieciowych nie mogą przekraczać wartości określonych przez podany budżet wydajności. [Więcej informacji](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 żądanie}few{# żądania}many{# żądań}other{# żądania}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Budżet wydajności"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Jeśli HTTPS jest już skonfigurowany, upewnij się, że cały ruch HTTP jest przekierowywany do HTTPS, by wszyscy użytkownicy mogli korzystać z bezpiecznych funkcji. [Więcej informacji](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nie przekierowuje ruchu HTTP do HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Przekierowuje ruch HTTP do HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Przekierowania wprowadzają dodatkowe opóźnienia przed rozpoczęciem ładowania strony. [Więcej informacji](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Unikaj wielokrotnych przekierowań"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Aby określić budżety dla liczby i rozmiaru zasobów strony, dodaj plik budget.json. [Więcej informacji](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 żądanie • {byteCount, number, bytes} KB}few{# żądania • {byteCount, number, bytes} KB}many{# żądań • {byteCount, number, bytes} KB}other{# żądania • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Liczba żądań i ilość przesyłanych danych powinny być małe"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Linki kanoniczne sugerują URL, który ma być pokazywany w wynikach wyszukiwania. [Więcej informacji](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Niezgodne ze sobą adresy URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Wskazuje inną domenę ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Nieprawidłowy URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Wskazuje inną lokalizację atrybutu `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Względny URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Wskazuje główny URL domeny (stronę główną) zamiast odpowiedniej strony z treścią"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument nie zawiera prawidłowego atrybutu `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument ma prawidłowy atrybut `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Na urządzeniach mobilnych czcionka o rozmiarze mniejszym niż 12 pikseli jest nieczytelna, dlatego użytkownicy muszą powiększać ekran, by odczytać tekst. Ponad 60% tekstu na stronie powinno mieć rozmiar co najmniej 12 pikseli. [Więcej informacji](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} czytelnego tekstu"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Tekst jest nieczytelny z powodu braku metatagu viewport zoptymalizowanego na potrzeby ekranów telefonów."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} tekstu jest zbyt małe (na podstawie próbki {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "W dokumencie nie są używane czytelne rozmiary czcionek"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "W dokumencie używane są czytelne rozmiary czcionek"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Linki hreflang informują wyszukiwarki, którą wersję strony pokazywać w wynikach wyszukiwania dla danego języka lub regionu. [Więcej informacji](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument nie ma prawidłowego atrybutu `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument ma prawidłowy atrybut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Strony z kodem stanu HTTP oznaczającym niepowodzenie mogą nie być indeksowane poprawnie. [Więcej informacji](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Strona ma kod stanu HTTP oznaczający niepowodzenie"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Strona ma kod stanu HTTP oznaczający powodzenie"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Wyszukiwarki nie mogą umieszczać Twoich stron w wynikach wyszukiwania, jeśli nie mają uprawnień, by je indeksować. [Więcej informacji](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Zablokowano indeksowanie strony"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indeksowanie strony nie jest zablokowane"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Opisowy tekst linków ułatwia wyszukiwarkom zrozumienie zawartości stron. [Więcej informacji](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Znaleziono 1 link}few{Znaleziono # linki}many{Znaleziono # linków}other{Znaleziono # linku}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linki nie mają opisowego tekstu"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linki mają tekst opisowy"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Uruchom [Narzędzie do testowania uporządkowanych danych](https://search.google.com/structured-data/testing-tool/) i narzędzie [Structured Data Linter](http://linter.structured-data.org/), by sprawdzić uporządkowane dane. [Więcej informacji](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Uporządkowane dane są prawidłowe"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metaopis można umieścić w wynikach wyszukiwania, by krótko podsumować zawartość strony. [Więcej informacji](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Tekst opisu jest pusty."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument nie ma metaopisu"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument ma metaopis"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Wyszukiwarki nie potrafią indeksować treści z wtyczek, a wiele urządzeń nie obsługuje wtyczek lub ogranicza ich działanie. [Więcej informacji](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument używa wtyczek"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument nie wymaga wtyczek"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Jeśli plik robots.txt ma nieprawidłowy format, roboty indeksujące mogą nie wiedzieć, jak mają indeksować witrynę. [Więcej informacji](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Żądanie pliku robots.txt zwróciło stan HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Znaleziono 1 błąd}few{Znaleziono # błędy}many{Znaleziono # błędów}other{Znaleziono # błędu}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse nie udało się pobrać pliku robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Plik robots.txt jest nieprawidłowy"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Plik robots.txt jest prawidłowy"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Elementy interaktywne, takie jak przyciski i linki, powinny być dostatecznie duże (48 x 48 pikseli) i mieć wokół siebie odpowiednią ilość miejsca, by można było je łatwo dotknąć, nie zahaczając o inne elementy. [Więcej informacji](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} elementów dotykowych ma odpowiednią wielkość"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Elementy dotykowe są zbyt małe z powodu braku metatagu viewport zoptymalizowanego na potrzeby ekranów telefonów"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Elementy dotykowe nie mają odpowiedniej wielkości"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Pokrywające się elementy dotykowe"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Element dotykowy"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Elementy dotykowe mają odpowiednią wielkość"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Skrypt service worker pozwala aplikacji na korzystanie z wielu funkcji progresywnych aplikacji internetowych – takich jak działanie offline, dodawanie do ekranu głównego czy powiadomienia push. [Więcej informacji](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Stroną steruje skrypt service worker, ale nie znaleziono elementu `start_url`, ponieważ nie udało się przetworzyć pliku manifestu jako prawidłowego pliku JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Tą stroną steruje skrypt service worker, ale element `start_url` ({startUrl}) nie znajduje się w jego zakresie ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Tą stroną steruje skrypt service worker, ale nie znaleziono elementu `start_url`, ponieważ nie został pobrany żaden plik manifestu."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ta witryna zawiera co najmniej jeden skrypt service worker, ale strona ({pageUrl}) nie jest w zakresie."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Nie rejestruje skryptu service worker, który steruje stroną i elementem `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Rejestruje skrypt service worker, który steruje stroną i elementem `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Ekran powitalny z niestandardowym motywem zapewnia użytkownikom lepsze wrażenia podczas otwierania aplikacji z ekranu głównego. [Więcej informacji](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nie skonfigurowano niestandardowego ekranu powitalnego"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Skonfigurowano niestandardowy ekran powitalny"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Motyw paska adresu w przeglądarce możesz dopasować do swojej witryny. [Więcej informacji](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nie ustawia motywu kolorystycznego paska adresu."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Ustawia motyw kolorystyczny paska adresu."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Czas blokowania głównego wątku"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Dostawca zewnętrzny"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kod spoza witryny może znacznie spowalniać wczytywanie stron. Ogranicz liczbę zewnętrznych dostawców kodu i spróbuj wczytywać kod spoza witryny dopiero po zakończeniu wczytywania podstawowej strony. [Więcej informacji](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kod spoza witryny zablokował główny wątek na {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Ogranicz wpływ kodu spoza witryny"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Używanie kodu spoza witryny"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Czas do pierwszego bajta oznacza czas wysłania odpowiedzi przez serwer. [Więcej informacji](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Czas odpowiedzi głównego dokumentu: {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Skróć czasy reakcji serwera (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Czasy odpowiedzi serwera są krótkie (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Czas trwania"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Czas rozpoczęcia"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Typ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Do aplikacji możesz dodać obsługę interfejsu User Timing API, by mierzyć rzeczywistą szybkość aplikacji z punktu widzenia użytkownika. [Więcej informacji](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 czas działań użytkownika}few{# czasy działań użytkownika}many{# czasów działań użytkownika}other{# czasu działań użytkownika}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Znaczniki i odcinki Czasu działań użytkownika"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Znaleziono element <link> typu preconnect dla „{securityOrigin}”, który nie jest używany przez przeglądarkę. Sprawdź, czy poprawnie używasz atrybutu `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Rozważ dodanie wskazówek `preconnect` lub `dns-prefetch`, by wcześniej nawiązać połączenia z ważnymi źródłami w innych domenach. [Więcej informacji](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Wcześniej nawiąż połączenia z wymaganymi źródłami"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Znaleziono element <link> wstępnego wczytywania dla „{preloadURL}”, który nie jest używany przez przeglądarkę. Sprawdź, czy poprawnie używasz atrybutu `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Pomyśl o użyciu elementu `<link rel=preload>`, by szybciej pobierały się zasoby, które są obecnie żądane na dalszym etapie ładowania strony. [Więcej informacji](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Załaduj wstępnie kluczowe żądania"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Dodaj tag `<meta name=\"viewport\">`, by zoptymalizować aplikację pod kątem ekranów urządzeń mobilnych. [Więcej informacji](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nie znaleziono tagu `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nie zawiera tagu `<meta name=\"viewport\">` z elementem `width` lub `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Zawiera tag `<meta name=\"viewport\">` z elementem `width` lub `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Aplikacja powinna wyświetlać jakieś treści, jeśli JavaScript jest wyłączony. Wystarczy nawet ostrzeżenie, że JavaScript jest wymagany do korzystania z aplikacji. [Więcej informacji](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Główna część strony powinna renderować jakieś treści, kiedy jej skrypty są niedostępne"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Nie zawiera treści zastępczych na wypadek niedostępności JavaScriptu"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Zawiera jakieś treści na wypadek niedostępności JavaScriptu"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Jeśli tworzysz progresywną aplikację internetową, rozważ użycie skryptu service worker, który pozwoli na działanie aplikacji w trybie offline. [Więcej informacji](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Strona nie wyświetla błędu 200, kiedy jest offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Bieżąca strona wyświetla błąd 200, kiedy jest offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Strona może nie wczytywać się offline, ponieważ testowy URL ({requested}) został przekierowany pod adres „{final}”. Przetestuj drugi URL bezpośrednio."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "To są możliwości lepszego wykorzystania atrybutów ARIA w Twojej aplikacji, by była ona wygodniejsza dla użytkowników technologii wspomagających, takich jak czytniki ekranu."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "To są możliwości dostarczenia alternatywnej treści dla audio i wideo. Dzięki temu treści mogą stać się bardziej przystępne dla osób niedowidzących i niedosłyszących."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Dźwięk i obraz"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Te pozycje wskazują typowe sprawdzone metody ułatwień dostępu."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Sprawdzone metody"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Te testy wskazują możliwości [poprawy ułatwień dostępu Twojej aplikacji internetowej](https://developers.google.com/web/fundamentals/accessibility). Ponieważ wykryć automatycznie można tylko część problemów z ułatwieniami dostępu, wskazane jest przeprowadzenie też testów ręcznych."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Te pozycje dotyczą obszarów, których narzędzie do testów automatycznych nie może zbadać. Więcej informacji w naszym przewodniku po [prowadzeniu przeglądu ułatwień dostępu](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Ułatwienia dostępu"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "To są możliwości poprawy czytelności treści."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "To są możliwości ulepszenia interpretacji treści przez użytkowników mających różne ustawienia języka."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacjonalizacja i lokalizacja"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "To są możliwości ulepszenia semantyki kontrolek aplikacji. Dzięki temu treści mogą stać się bardziej przystępne dla użytkowników technologii wspomagających, takich jak czytniki ekranu."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nazwy i etykiety"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "To są możliwości ulepszenia nawigacji za pomocą klawiatury w Twojej aplikacji."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Nawigacja"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "To są możliwości lepszego odczytywania danych z tabel i list za pomocą technologii wspomagających, takich jak czytnik ekranu."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabele i listy"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Sprawdzone metody"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Budżety wydajności są podstawą do określania standardów wydajności witryny."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budżety"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Więcej o wydajności aplikacji. Te liczby nie mają [bezpośredniego wpływu](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na wyniki w kategorii Wydajność."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostyka"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Najważniejszym aspektem wydajności jest to, jak szybko piksele zostaną wyświetlone na ekranie. Kluczowe wskaźniki: Pierwsze wyrenderowanie treści, Pierwsze wyrenderowanie elementu znaczącego"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Ulepszenia pierwszego renderowania"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Te sugestie mogą pomóc przyśpieszyć wczytywanie strony. Nie mają one [bezpośredniego wpływu](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na wynik w kategorii Wydajność."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Możliwości"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Dane"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Usprawnij całe ładowanie, by strona jak najszybciej była gotowa do używania i reagowała na działania użytkownika. Główne wskaźniki: Czas do pełnej interaktywności, Indeks szybkości"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Ogólne usprawnienia"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Wydajność"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Te testy służą do sprawdzenia różnych aspektów progresywnej aplikacji internetowej. [Więcej informacji](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Te testy są wymagane w ramach podstawowej [listy kontrolnej PWA](https://developers.google.com/web/progressive-web-apps/checklist), ale narzędzie Lighthouse nie przeprowadza ich automatycznie. Nie mają wpływu na wynik, ale należy pamiętać o wykonaniu ich ręcznie."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresywna aplikacja internetowa"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Szybka i niezawodna"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Możliwa do zainstalowania"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optymalizacja dla PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Te testy sprawdzają, czy strona jest zoptymalizowana pod kątem rankingu wyników wyszukiwarki. Na ranking mogą wpływać inne czynniki, których Lighthouse nie sprawdza. [Więcej informacji](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Uruchom te dodatkowe walidatory w swojej witrynie, by skontrolować więcej sprawdzonych metod SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Dostosuj kod HTML w taki sposób, by roboty lepiej rozumiały zawartość aplikacji."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Sprawdzone metody publikowania treści"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Jeśli Twoja aplikacja ma pojawiać się w wynikach wyszukiwania, muszą mieć do niej dostęp roboty."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Skanowanie i indeksowanie"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Dostosuj strony do komórek, by użytkownicy nie musieli pomniejszać ani powiększać ekranu, gdy będą chcieli coś przeczytać. [Więcej informacji](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Na komórki"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Czas przechowywania danych w pamięci podręcznej"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokalizacja"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nazwa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Żądania"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Typ zasobu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Rozmiar"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Spędzony czas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Rozmiar przesłanych danych"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potencjalne oszczędności"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potencjalne oszczędności"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potencjalne przyspieszenie o {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potencjalne przyspieszenie o {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Czcionka"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Obraz"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Multimedia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Inne"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skrypt"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Arkusz stylów"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Zewnętrzne"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Razem"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Podczas rejestrowania śladu wczytywania strony wystąpił błąd. Uruchom Lighthouse ponownie. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Upłynął czas oczekiwania na wstępne połączenie z Protokołem debugującym."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Podczas wczytywania strony w Chrome nie zostały utworzone zrzuty ekranu. Zapewnij widoczność treści na stronie, a potem uruchom Lighthouse jeszcze raz. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Serwery DNS nie potrafiły ustalić adresu podanej domeny."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Wystąpił błąd wymaganego elementu zbierającego {artifactName}: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Wystąpił wewnętrzny błąd Chrome. Uruchom ponownie Chrome, a następnie Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Wymagany element zbierający {artifactName} nie został uruchomiony."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Narzędziu Lighthouse nie udało się całkowicie wczytać żądanej strony. Upewnij się, że testujesz właściwy URL, a serwer poprawnie odpowiada na wszystkie żądania."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Narzędziu Lighthouse nie udało się całkowicie wczytać żądanego URL-a, ponieważ strona przestała odpowiadać."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Podany URL nie ma prawidłowego certyfikatu bezpieczeństwa. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Przeglądarka Chrome zablokowała wczytywanie strony i wyświetliła komunikat pełnoekranowy. Upewnij się, że testujesz właściwy URL, a serwer poprawnie odpowiada na wszystkie żądania."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Narzędziu Lighthouse nie udało się całkowicie wczytać żądanej strony. Upewnij się, że testujesz właściwy URL, a serwer poprawnie odpowiada na wszystkie żądania. Szczegóły: {errorDetails}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Narzędziu Lighthouse nie udało się całkowicie wczytać żądanej strony. Upewnij się, że testujesz właściwy URL, a serwer poprawnie odpowiada na wszystkie żądania. Kod stanu: {statusCode}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Wczytywanie strony trwało zbyt długo. Skorzystaj z możliwości przyspieszenia wczytywania strony podanych w raporcie, a następnie ponownie uruchom Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Przekroczono przydzielony czas oczekiwania na odpowiedź protokołu DevTools. Metoda: {protocolMethod}"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Przekroczono czas przydzielony na pobranie zasobów"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Podany URL jest nieprawidłowy."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Pokaż audyty"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Początkowa nawigacja"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksymalne opóźnienie ścieżki krytycznej:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Błąd"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Błąd raportu: brak informacji o audycie"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dane laboratoryjne"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Bieżąca strona została przeanalizowana przez narzędzie [Lighthouse](https://developers.google.com/web/tools/lighthouse/) wraz z emulacją sieci komórkowej. Wartości są szacunkowe i mogą się zmieniać."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Dodatkowe elementy do ręcznego sprawdzenia"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nie dotyczy"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Możliwość"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Szacowane oszczędności"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Zaliczone audyty"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Zwiń fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Rozwiń fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Pokaż zasoby zewnętrzne"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Podczas tego uruchomienia Lighthouse wystąpiły problemy:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Wartości są szacunkowe i mogą się zmieniać. Wynik wydajności jest [oparty tylko na tych danych](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Audyty zaliczone z ostrzeżeniami"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Ostrzeżenia "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Możesz przesłać plik GIF do usługi, która umożliwi umieszczanie go jako pliku wideo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Zainstaluj [wtyczkę WordPressa do leniwego ładowania](https://wordpress.org/plugins/search/lazy+load/), która umożliwia odłożenie ładowania obrazów niewyświetlanych na ekranie, albo wybierz motyw, który ma tę funkcję. Warto też skorzystać z [wtyczki AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Jest wiele wtyczek WordPressa, które mogą pomóc Ci [umieścić w tekście najważniejsze zasoby](https://wordpress.org/plugins/search/critical+css/) lub [opóźnić wczytywanie mniej ważnych zasobów](https://wordpress.org/plugins/search/defer+css+javascript/). Pamiętaj, że optymalizacje dostarczane przez te wtyczki mogą uszkodzić funkcje Twojego motywu lub innych wtyczek i konieczne może być wprowadzenie zmian w kodzie."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Motywy, wtyczki i specyfikacje serwera są nie bez znaczenia dla jego czasu reakcji. Być może warto znaleźć lepiej zoptymalizowany motyw, starannie wybierając wtyczkę optymalizującą, i przejść na nowszą wersję serwera."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Korzystne może być wyświetlanie fragmentów na liście postów (np. przy użyciu tagu more), zmniejszenie liczby postów wyświetlanych na danej stronie, podział długich postów na kilka stron lub użycie wtyczki umożliwiającej opóźnione wczytywanie komentarzy."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Kilka [wtyczek WordPressa](https://wordpress.org/plugins/search/minify+css/) może przyśpieszyć działanie strony dzięki konkatenacji, minifikacji i kompresji stylów. Jeśli masz taką możliwość, przeprowadż minifikację, zanim opublikujesz skrypty."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Kilka [wtyczek WordPressa](https://wordpress.org/plugins/search/minify+javascript/) może przyśpieszyć działanie strony dzięki konkatenacji, minifikacji i kompresji skryptów. Jeśli masz taką możliwość, przeprowadź minifikację, zanim opublikujesz skrypty."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Dobrym rozwiązaniem może być ograniczenie liczby [wtyczek WordPressa](https://wordpress.org/plugins/) wczytujących na stronie nieużywany kod CSS albo zmiana tych wtyczek na inne. Aby zidentyfikować wtyczki, które dodają nieistotny kod CSS, uruchom [zasięg kodu](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) w Chrome DevTools. Możesz zidentyfikować taki motyw/wtyczkę w adresie URL arkusza stylów. Szukaj wtyczek, które mają na liście wiele arkuszy stylów z dużą ilością czerwonego koloru w zasięgu kodu. Wtyczka powinna umieszczać arkusz stylów w kolejce tylko wtedy, gdy rzeczywiście jest on używany na stronie."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Dobrym rozwiązaniem może być ograniczenie liczby [wtyczek WordPressa](https://wordpress.org/plugins/) wczytujących na stronie nieużywany kod JavaScript albo zmiana tych wtyczek na inne. Aby zidentyfikować wtyczki, które dodają nieistotny kod JS, uruchom [zasięg kodu](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) w Chrome DevTools. Możesz zidentyfikować taki motyw/wtyczkę w adresie URL skryptu. Szukaj wtyczek, które mają na liście wiele skryptów z dużą ilością czerwonego koloru w zasięgu kodu. Wtyczka powinna umieszczać skrypt w kolejce, tylko jeśli rzeczywiście jest on używany na stronie."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Dowiedz się więcej o [pamięci podręcznej przeglądarki w WordPressie](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Pomocna może być [wtyczka WordPressa do optymalizacji obrazów](https://wordpress.org/plugins/search/optimize+images/), która kompresuje obrazy, zachowując ich jakość."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Przesyłaj obrazy bezpośrednio przez [bibliotekę multimediów](https://codex.wordpress.org/Media_Library_Screen), by mieć pewność, że wymagane rozmiary obrazów są dostępne, a następnie wstawiaj je z biblioteki multimediów lub używaj widżetu obrazów, by zapewnić użycie optymalnych rozmiarów obrazów (także w dynamicznych punktach przerwania). Unikaj używania obrazów `Full Size`, chyba że wymiary są adekwatne do danego zastosowania. [Więcej informacji](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Możesz włączyć kompresję tekstu w konfiguracji swojego serwera WWW."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Możesz skorzystać z [wtyczki](https://wordpress.org/plugins/search/convert+webp/) lub usługi, która będzie automatycznie konwertować przesłane obrazy do optymalnych formatów."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt-PT.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt-PT.json
new file mode 100644
index 00000000000..6ee289a5595
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt-PT.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "As chaves de acesso permitem que os utilizadores se concentrem rapidamente numa parte da página. Para uma navegação adequada, cada chave de acesso tem de ser exclusiva. [Saiba mais](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Os valores `[accesskey]` não são exclusivos"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Os valores `[accesskey]` são exclusivos"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Cada ARIA `role` suporta um subconjunto específico de atributos `aria-*`. A não correspondência destes invalida os atributos `aria-*`. [Saiba mais](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não correspondem às respetivas funções"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Os atributos `[aria-*]` correspondem às respetivas funções"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Algumas funções ARIA têm atributos obrigatórios que descrevem o estado do elemento para os leitores de ecrã. [Saiba mais](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Os `[role]`s não têm todos os atributos `[aria-*]` obrigatórios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Os `[role]`s têm todos os atributos `[aria-*]` obrigatórios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Algumas funções superiores ARIA têm de conter funções secundárias específicas para desempenhar as respetivas funções de acessibilidade previstas. [Saiba mais](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Os elementos com um `[role]` ARIA que requerem que os elementos secundários contenham um `[role]` específico têm alguns ou todos esses elementos secundários requeridos em falta."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Os elementos com um `[role]` ARIA que requerem que os elementos secundários contenham um `[role]` específico têm todos os elementos secundários requeridos."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Algumas funções secundárias ARIA têm de ser contidas por funções superiores específicas para desempenharem adequadamente as respetivas funções de acessibilidade pretendidas. [Saiba mais](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Os `[role]`s não são contidos pelo respetivo elemento superior obrigatório"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Os `[role]`s são contidos pelo respetivo elemento superior obrigatório"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "As funções ARIA têm de possuir valores válidos para desempenhar as funções de acessibilidade previstas. [Saiba mais](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Os valores `[role]` não são válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Os valores `[role]` são válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "As tecnologias de assistência, que incluem os leitores de ecrã, não conseguem interpretar atributos ARIA com valores inválidos. [Saiba mais](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não têm valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Os atributos `[aria-*]` têm valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "As tecnologias de assistência, que incluem os leitores de ecrã, não conseguem interpretar atributos ARIA com nomes inválidos. [Saiba mais](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não são válidos ou têm erros ortográficos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Os atributos `[aria-*]` são válidos e não têm erros ortográficos"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "As legendas tornam os elementos áudio utilizáveis para os utilizadores surdos ou com problemas de audição, ao facultar informações essenciais, como quem está a falar, o que está a dizer e outras informações não verbais. [Saiba mais](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Os elementos `<audio>` têm um elemento `<track>` em falta com `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Os elementos `<audio>` contêm um elemento `<track>` com `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementos reprovados"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Quando um botão não tem um nome acessível, os leitores de ecrã anunciam-no como \"botão\", tornando-o inutilizável para os utilizadores que dependem de leitores de ecrã. [Saiba mais](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Os botões não têm um nome acessível"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Os botões têm um nome acessível"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Adicionar formas de ignorar conteúdo repetitivo permite que os utilizadores com teclado naveguem na página de forma mais eficiente. [Saiba mais](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "A página não contém um título, um link para ignorar ou uma região de ponto de referência"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "A página contém um título, um link para ignorar ou uma região de ponto de referência"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "O texto de baixo contraste é difícil ou impossível de ler para muitos utilizadores. [Saiba mais](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "As cores de primeiro e de segundo plano não têm uma relação de contraste suficiente"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "As cores de segundo plano e de primeiro plano têm uma relação de contraste suficiente"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Quando as listas de definição não estão devidamente marcadas, os leitores de ecrã podem produzir um resultado confuso ou impreciso. [Saiba mais](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Os `<dl>`s não contêm grupos de `<dt>` e `<dd>` apenas devidamente ordenados, nem elementos `<script>` ou `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Os `<dl>` contêm grupos de `<dt>` e `<dd>` bem como elementos `<script>` ou `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Os itens de lista de definição (`<dt>` e `<dd>`) têm de estar unidos num elemento `<dl>` superior de modo a garantir que os leitores de ecrã os possam anunciar adequadamente. [Saiba mais](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Os itens de lista de definição não estão unidos em elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Os itens de lista de definição estão unidos em elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "O título proporciona aos utilizadores de leitores de ecrã uma vista geral da página, sendo que os utilizadores de motores de pesquisa dependem dele para determinar se uma página é relevante para a respetiva pesquisa. [Saiba mais](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "O documento não tem um elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "O documento tem um elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "O valor de um atributo id tem de ser exclusivo para evitar que outras instâncias sejam ignoradas pelas tecnologias de assistência. [Saiba mais](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Os atributos `[id]` na página não são exclusivos"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Os atributos `[id]` na página são exclusivos"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Os utilizadores com leitores de ecrã dependem dos títulos de frames para descrever o conteúdo dos frames. [Saiba mais](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Os elementos `<frame>` ou `<iframe>` não têm um título"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Os elementos `<frame>` ou `<iframe>` têm um título"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Se uma página não especificar um atributo lang, um leitor de ecrã parte do princípio de que a página está no idioma predefinido que o utilizador escolheu quando configurou o leitor de ecrã. Se a página não estiver realmente no idioma predefinido, o leitor de ecrã pode não anunciar corretamente o texto da página. [Saiba mais](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "O elemento `<html>` não tem um atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "O elemento `<html>` tem um atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Especificar um idioma [BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido ajuda os leitores de ecrã a anunciar texto adequadamente. [Saiba mais](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "O elemento `<html>` tem um valor válido para o respetivo atributo `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "O elemento `<html>` tem um valor válido para o respetivo atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Os elementos informativos devem procurar incluir texto curto, descritivo e alternativo. Os elementos decorativos podem ser ignorados com um atributo alternativo vazio. [Saiba mais](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Os elementos de imagem não têm atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Os elementos de imagem têm atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Quando uma imagem está a ser utilizada como um botão `<input>`, facultar texto alternativo pode ajudar os utilizadores com leitores de ecrã a compreender a finalidade do botão. [Saiba mais](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Os elementos `<input type=\"image\">` não têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Os elementos `<input type=\"image\">` têm texto de `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "As etiquetas garantem que os controlos de formulários são anunciados adequadamente pelas tecnologias de assistência, que incluem os leitores de ecrã. [Saiba mais](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Os elementos de formulário não têm etiquetas associadas"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Os elementos de formulário têm etiquetas associadas"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Uma tabela utilizada para esquemas não deve incluir elementos de dados, como os elementos th ou de legenda ou o atributo resumo, porque esta situação pode criar uma experiência confusa para os utilizadores com leitores de ecrã. [Saiba mais](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Os elementos `<table>` de apresentação não evitam a utilização de `<th>`, `<caption>` nem do atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Os elementos `<table>` de apresentação evitam a utilização de `<th>`, `<caption>` ou do atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "O texto de link (e texto alternativo para imagens, quando utilizado como link) que seja percetível, exclusivo e ajustável melhora a experiência de navegação dos utilizadores de leitores de ecrã. [Saiba mais](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Os links não têm um nome percetível"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Os links têm um nome percetível"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Os leitores de ecrã têm uma forma específica de anunciar listas. Garantir uma estrutura de listas adequada é benéfico para o resultado do leitor de ecrã. [Saiba mais](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "As listas não contêm apenas elementos `<li>` e elementos de suporte de script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "As listas contêm apenas elementos `<li>` e elementos de suporte de script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Os leitores de ecrã necessitam que os itens de lista (`<li>`) sejam contidos num `<ul>` ou `<ol>` superior para serem adequadamente anunciados. [Saiba mais](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Os itens de lista (`<li>`) não estão incluídos nos elementos superiores `<ul>` ou `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Os itens de lista (`<li>`) estão incluídos nos elementos superiores `<ul>` ou `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Os utilizadores não esperam que uma página se atualize automaticamente e, se tal acontecer, vai desviar o foco para a parte superior da página. Esta situação pode criar uma experiência frustrante ou confusa. [Saiba mais](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "O documento utiliza `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "O documento não utiliza `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Desativar o zoom é problemático para os utilizadores com visão reduzida que dependem da ampliação do ecrã para ver adequadamente o conteúdo de uma página Web. [Saiba mais](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "O `[user-scalable=\"no\"]` é utilizado no elemento `<meta name=\"viewport\">` ou o atributo `[maximum-scale]` é inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "O `[user-scalable=\"no\"]` não é utilizado no elemento `<meta name=\"viewport\">` e o atributo `[maximum-scale]` não é inferior a 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Os leitores de ecrã não conseguem traduzir conteúdo que não seja de texto. Adicionar texto alternativo a elementos `<object>` ajuda os leitores de ecrã a transmitir significado aos utilizadores. [Saiba mais](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Os elementos `<object>` não têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Os elementos `<object>` têm texto de `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Um valor superior a 0 implica uma ordenação de navegação explícita. Embora seja tecnicamente válida, esta situação costuma criar experiências frustrantes para os utilizadores que dependem de tecnologias de assistência. [Saiba mais](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Alguns elementos têm um valor `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nenhum elemento tem um valor `[tabindex]` superior a 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Os leitores de ecrã têm funcionalidades para facilitar a navegação em tabelas. Garantir que as células `<td>` que utilizam o atributo `[headers]` apenas referenciam outras células na mesma tabela pode melhorar a experiência para os utilizadores com leitores de ecrã. [Saiba mais](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "As células num elemento `<table>` que utilizam o atributo `[headers]` referem-se a um elemento `id` que não se encontra dentro da mesma tabela."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "As células num elemento `<table>` que utilizam o atributo `[headers]` referem-se a células de tabela dentro da mesma tabela."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Os leitores de ecrã têm funcionalidades para facilitar a navegação em tabelas. Garantir que os cabeçalhos de tabelas referenciam sempre algum conjunto de células pode melhorar a experiência dos utilizadores com leitores de ecrã. [Saiba mais](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Os elementos `<th>` e os elementos com `[role=\"columnheader\"/\"rowheader\"]` não têm as células de dados que descrevem."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Os elementos `<th>` e os elementos com `[role=\"columnheader\"/\"rowheader\"]` têm as células de dados que descrevem."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Especificar um idioma [BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido para elementos ajuda a garantir que o texto é pronunciado corretamente por um leitor de ecrã. [Saiba mais](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Os atributos `[lang]` não têm um valor válido"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Os atributos `[lang]` têm um valor válido"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Quando um vídeo oferece uma legenda, é mais fácil para os utilizadores surdos e com problemas de audição aceder às informações. [Saiba mais](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Os elementos `<video>` não contêm um elemento `<track>` com `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Os elementos `<video>` contêm um elemento `<track>` com `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "As descrições de áudio proporcionam informações relevantes que os diálogos não conseguem proporcionar nos vídeos, como expressões faciais e cenas. [Saiba mais](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Os elementos `<video>` não contêm um elemento `<track>` com `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Os elementos `<video>` contêm um elemento `<track>` com `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Para um aspeto ideal no iOS quando os utilizadores adicionam uma progressive web app ao ecrã principal, defina um `apple-touch-icon`. Deve apontar para um PNG quadrado não transparente de 192 px (ou 180 px). [Saiba mais](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Não fornece um `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "O `apple-touch-icon-precomposed` está desatualizado; recomendamos o `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Fornece um `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "As extensões do Chrome afetam negativamente o desempenho de carregamento desta página. Experimente efetuar uma auditoria à página no modo de navegação anónima ou com um perfil do Chrome sem extensões."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Avaliação do script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Análise do script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tempo total da CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Considere reduzir o tempo despendido a analisar, compilar e executar JS. Poderá descobrir que é útil fornecer payloads de JS mais pequenos. [Saiba mais](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduza o tempo de execução de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Tempo de execução de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Os GIFs grandes são ineficientes para publicação de conteúdo animado. Para poupar bytes de rede, considere utilizar vídeos MPEG4/WebM para animações e ficheiros PNG/WebP para imagens estáticas em vez de GIFs. [Saiba mais](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Utilize formatos de vídeo para conteúdo animado"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Considere utilizar imagens de carregamento lento não visíveis e ocultas após a conclusão do carregamento de todos os recursos críticos, para reduzir o tempo até à interação. [Saiba mais](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Adie as imagens não visíveis"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Os recursos estão a bloquear o primeiro preenchimento da página. Considere publicar JS/CSS críticos inline e adiar todos os JS/estilos não críticos. [Saiba mais](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimine recursos que bloqueiam o processamento"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Os grandes payloads de rede têm custos reais para os utilizadores e estão fortemente correlacionados com tempos de carregamento demorados. [Saiba mais](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "O tamanho total era {totalBytes, number, bytes} KB."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evite enormes payloads de rede"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evita enormes payloads de rede"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Reduzir os ficheiros CSS pode reduzir os tamanhos dos payloads de rede. [Saiba mais](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Reduza o CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Reduzir os ficheiros JavaScript pode reduzir os tamanhos dos payloads e o tempo de análise de scripts. [Saiba mais](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Reduza o JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Remova as regras vazias das folhas de estilo e adie o carregamento de CSS não utilizado para conteúdo na parte superior para reduzir a quantidade de bytes desnecessários consumidos pela atividade da rede. [Saiba mais](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Remova o CSS não utilizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Remova o JavaScript não utilizado para reduzir os bytes consumidos pela atividade da rede."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Remova o JavaScript não utilizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Uma longa duração total da cache pode acelerar as visitas repetidas à sua página. [Saiba mais](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 recurso encontrado}other{# recursos encontrados}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Publique recursos estáticos com uma política de cache eficiente"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Utiliza uma política de cache eficiente em recursos estáticos"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "As imagens otimizadas são carregadas mais rapidamente e consomem menos dados móveis. [Saiba mais](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifique as imagens de forma eficiente"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Publique imagens com um tamanho adequado para poupar dados móveis e melhorar o tempo de carregamento. [Saiba mais](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Dimensione adequadamente as imagens"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Os recursos baseados em texto devem ser publicados com compressão (gzip, Deflate ou Brotli) para reduzir o total de bytes de rede. [Saiba mais](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Ative a compressão de texto"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Muitas vezes, os formatos de imagem como JPEG 2000, JPEG XR e WebP proporcionam uma melhor compressão do que os formatos PNG ou JPEG, o que se traduz em transferências mais rápidas e num menor consumo de dados. [Saiba mais](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Publique imagens em formatos de última geração"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Se a largura do conteúdo da sua aplicação não corresponder à largura da área visível, a sua aplicação poderá não estar otimizada para ecrãs de dispositivos móveis. [Saiba mais](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "O tamanho da área visível de {innerWidth} px não corresponde ao tamanho da janela de {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "O conteúdo não é dimensionado corretamente para a área visível"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "O conteúdo é dimensionado corretamente para a área visível"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "As Cadeias de pedidos críticos abaixo apresentam os recursos que são carregados com uma prioridade elevada. Considere reduzir o tamanho das cadeias, reduzir o tamanho de transferência dos recursos ou adiar a transferência de recursos desnecessários para melhorar o carregamento de página. [Saiba mais](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 cadeia encontrada}other{# cadeias encontradas}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Reduza a profundidade de pedidos críticos"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Descontinuação/aviso"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linha"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "As APIs descontinuadas serão eventualmente removidas do navegador. [Saiba mais](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 aviso encontrado}other{# avisos encontrados}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Utiliza APIs descontinuadas"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita APIs descontinuadas"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "A cache da aplicação foi descontinuada. [Saiba mais](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" encontrado"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Utiliza a cache da aplicação"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita a cache da aplicação"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Especificar um doctype impede que o navegador mude para o modo quirks. [Saiba mais](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "O nome do doctype deve ser a string `html` minúscula"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "O documento deve conter um doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Era esperado que o PublicId fosse uma string vazia"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Era esperado que o SystemId fosse uma string vazia."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "A página não possui o doctype HTML, o que faz com que o modo quirks seja acionado"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "A página possui o doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Estatística"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Os engenheiros de navegadores recomendam que as páginas contenham menos de ~1500 elementos DOM. O ideal é uma árvore com uma profundidade < 32 elementos e menos de 60 elementos superiores/secundários. Um DOM grande pode aumentar a utilização da memória, gerar [cálculos de estilo](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) mais demorados e produzir [ajustes de esquema](https://developers.google.com/speed/articles/reflow) dispendiosos. [Saiba mais](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemento}other{# elementos}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evite um tamanho excessivo do DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profundidade máxima do DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total de elementos DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Máximo de elementos secundários"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evita um tamanho excessivo do DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Alvo"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Adicione `rel=\"noopener\"` ou `rel=\"noreferrer\"` a quaisquer links externos para melhorar o desempenho e prevenir vulnerabilidades de segurança. [Saiba mais](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Os links para destinos de origem cruzada não são seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Os links para destinos de origem cruzada são seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Não é possível determinar o destino da âncora ({anchorHTML}). Se não for utilizado como uma hiperligação, considere remover o target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Os utilizadores desconfiam ou ficam confusos perante os sites que solicitam a sua localização sem contexto. Em vez disso, considere associar o pedido a uma ação do utilizador. [Saiba mais](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Solicita a autorização de geolocalização no carregamento da página"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita a solicitação da autorização de geolocalização no carregamento da página"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versão"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Todas as bibliotecas de interface JavaScript detetadas na página. [Saiba mais](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Bibliotecas JavaScript detetadas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "No caso de utilizadores com ligações lentas, os scripts externos inseridos dinamicamente através de `document.write()` podem atrasar o carregamento da página em dezenas de segundos. [Saiba mais](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Utiliza `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evita `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Gravidade mais alta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versão da biblioteca"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Contagem de vulnerabilidades"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Alguns scripts de terceiros podem conter vulnerabilidades de segurança conhecidas que são facilmente identificadas e exploradas pelos atacantes. [Saiba mais](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vulnerabilidade detetada}other{# vulnerabilidades detetadas}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Inclui bibliotecas de interface JavaScript com vulnerabilidades de segurança conhecidas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alto"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Baixo"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Médio"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita bibliotecas de interface JavaScript com vulnerabilidades de segurança conhecidas"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Os utilizadores desconfiam ou ficam confusos perante os sites que solicitam o envio de notificações sem contexto. Em vez disso, considere associar o pedido aos gestos do utilizador. [Saiba mais](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Solicita a autorização de notificações no carregamento da página"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita a solicitação da autorização de notificações no carregamento da página"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementos reprovados"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Impedir a colagem de palavras-passe compromete o cumprimento de uma política de segurança adequada. [Saiba mais](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Impede que os utilizadores colem conteúdo nos campos de palavra-passe"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permite que os utilizadores colem nos campos de palavra-passe"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocolo"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "O HTTP/2 oferece muitas vantagens em relação ao HTTP/1.1, incluindo cabeçalhos binários, multiplexação e push de servidor. [Saiba mais](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 pedido não publicado através de HTTP/2}other{# pedidos não publicados através de HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Não utiliza o HTTP/2 para todos os respetivos recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Utiliza HTTP/2 para os seus próprios recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Considere marcar os seus event listeners de toque e roda como `passive` para melhorar o desempenho de deslocamento da sua página. [Saiba mais](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Não utiliza ouvintes passivos para melhorar o desempenho do deslocamento"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Utiliza ouvintes passivos para melhorar o desempenho do deslocamento"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descrição"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Os erros registados na consola indicam problemas não resolvidos. Estes podem ser provenientes de falhas de pedidos de rede e outras questões do navegador. [Saiba mais](https://web.dev/errors-in-console)."
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Os erros do navegador foram registados na consola"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nenhum erro do navegador registado na consola"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Tire partido da funcionalidade CSS de apresentação de tipos de letra para garantir que o texto é visível para o utilizador enquanto os tipos de letra para Websites são carregados. [Saiba mais](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Garanta que o texto permanece visível durante o carregamento de tipos de letra para Websites"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Todo o texto permanece visível durante os carregamentos de tipos de letra para Websites"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "O Lighthouse não conseguiu verificar automaticamente o valor de apresentação de tipos de letra para o seguinte URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Proporção (atual)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Formato (apresentado)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "As dimensões de apresentação das imagens devem corresponder à proporção natural. [Saiba mais](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Apresenta imagens com uma proporção incorreta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Apresenta imagens com uma proporção correta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informações inválidas de dimensionamento de imagens {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Os navegadores podem solicitar proativamente aos utilizadores que adicionem a sua aplicação ao respetivo ecrã principal, o que pode levar a uma maior interação. [Saiba mais](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "O manifesto da aplicação para a Web não cumpre os requisitos de capacidade de instalação"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "O manifesto da aplicação para a Web cumpre os requisitos de capacidade de instalação"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL inseguro"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Todos os sites devem ser protegidos com HTTPS, mesmo aqueles que não lidam com dados confidenciais. O HTTPS evita que os intrusos adulterem ou escutem passivamente as comunicações entre a sua aplicação e os seus utilizadores, e é um pré-requisito para o HTTP/2 e muitas novas APIs de plataformas Web. [Saiba mais](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 pedido inseguro encontrado}other{# pedidos inseguros encontrados}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Não utiliza HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Utiliza HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Um rápido carregamento da página numa rede móvel assegura uma boa experiência do utilizador móvel. [Saiba mais](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interativa em {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interativa numa rede móvel simulada em {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "A sua página é carregada muito lentamente e não fica interativa após 10 segundos. Veja as oportunidades e os diagnósticos na secção \"Desempenho\" para saber como melhorar."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "O carregamento da página não é suficientemente rápido em redes móveis"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "O carregamento da página é suficientemente rápido em redes móveis"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoria"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Considere reduzir o tempo despendido a analisar, compilar e executar JS. Poderá descobrir que é útil fornecer payloads de JS mais pequenos. [Saiba mais](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Reduzir as operações do thread principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Reduz as operações do thread principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Para alcançar o maior número possível de utilizadores, os sites devem funcionar em todos os navegadores principais. [Saiba mais](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "O site funciona em vários navegadores"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Certifique-se de que as páginas individuais têm links diretos através de URLs e que os URLs são exclusivos para a finalidade de serem partilhados em redes sociais. [Saiba mais](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Cada página tem um URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "As transições devem parecer rápidas à medida em que toca em qualquer local, mesmo numa rede lenta. Esta experiência é essencial para a perceção do desempenho de um utilizador. [Saiba mais](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "As transições da página não parecem ficar bloqueadas na rede"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "A Latência de entrada estimada é uma estimativa do tempo que a sua aplicação demora a responder a ações do utilizador, em milissegundos, durante a janela dos 5 segundos mais ativos do carregamento da página. Se a latência for superior a 50 ms, os utilizadores podem considerar que a sua aplicação é lenta. [Saiba mais](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latência estimada das ações"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "O Primeiro preenchimento com conteúdo assinala o momento de preenchimento com o primeiro texto ou a primeira imagem. [Saiba mais](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Primeiro preenchimento com conteúdo"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "A métrica Primeira CPU inativa indica quando é que o thread principal da página está suficientemente inativo pela primeira vez para processar ações. [Saiba mais](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primeira CPU inativa"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "A métrica Primeiro preenchimento significativo mede quando é que o conteúdo principal de uma página fica visível. [Saiba mais](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Primeiro preenchimento significativo"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "O Tempo até à interação é a quantidade de tempo que a página demora a ficar totalmente interativa. [Saiba mais](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tempo até à interação"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "O máximo potencial do primeiro atraso de entrada que pode afetar os utilizadores é a duração, em milissegundos, da tarefa mais longa. [Saiba mais](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Máximo potencial de primeiro atraso de entrada"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "A métrica Índice de velocidade apresenta a rapidez de preenchimento visível dos conteúdos de uma página. [Saiba mais](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Índice de velocidade"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "A soma de todos os períodos de tempo entre o FCP e o Tempo até à interação, quando a duração da tarefa é superior a 50 ms, expressa em milissegundos."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tempo de bloqueio total"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Os tempos de ida e volta da rede (RTT) têm um grande impacto no desempenho. Se o RTT para uma origem for elevado, é uma indicação de que os servidores mais próximos do utilizador podem melhorar o desempenho. [Saiba mais](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tempos de ida e volta da rede"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "As latências do servidor podem afetar o desempenho Web. Se a latência do servidor de uma origem for elevada, é uma indicação de que o servidor está sobrecarregado ou tem um fraco desempenho de back-end. [Saiba mais](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latências de back-end do servidor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Um service worker permite que a sua aplicação para a Web seja fiável em condições de rede imprevisíveis. [Saiba mais](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` não responde com um 200 quando está offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responde com um 200 quando está offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "O Lighthouse não conseguiu ler o `start_url` do manifesto. Como resultado, o `start_url` foi assumido como o URL do documento. Mensagem de erro: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Superior ao orçamento"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Mantenha a quantidade e o tamanho dos pedidos de rede abaixo dos alvos estabelecidos pelo orçamento de desempenho fornecido. [Saiba mais](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 pedido}other{# pedidos}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Orçamento de desempenho"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Se já tiver configurado o HTTPS, certifique-se de que redireciona todo o tráfego HTTP para HTTPS de modo a ativar as funcionalidades Web seguras para todos os seus utilizadores. [Saiba mais](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Não redireciona o tráfego HTTP para HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redireciona o tráfego HTTP para HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "A auditoria Redirecionamentos introduz atrasos adicionais antes do carregamento da página. [Saiba mais](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evite vários redirecionamentos de página"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Adicione um ficheiro budget.json para definir orçamentos para a quantidade e tamanho dos recursos da página. [Saiba mais](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 pedido • {byteCount, number, bytes} KB}other{# pedidos • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Mantenha a contagem dos pedidos baixa e os tamanhos de transferência pequenos"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Os links canónicos sugerem o URL a apresentar nos resultados da pesquisa. [Saiba mais](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Vários URLs em conflito ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Aponta para um domínio diferente ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL inválido ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Aponta para outra localização `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relativo ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Aponta para o URL raiz do domínio (a página inicial), em vez de uma página de conteúdo equivalente."
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "O documento não tem um `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "O documento tem um `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Os tamanhos de tipo de letra inferiores a 12 px são demasiado pequenos para serem legíveis e requerem que os visitantes de dispositivos móveis \"juntem os dedos para aumentar o zoom” para conseguirem ler. Tente ter > 60% de texto da página ≥ 12 px. [Saiba mais](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} de texto legível"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "O texto é ilegível porque não existe nenhuma metatag de área visível otimizada para ecrãs de dispositivos móveis."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} do texto é demasiado pequeno (com base na amostra de {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "O documento não utiliza tamanhos de tipo de letra legíveis"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "O documento utiliza tamanhos de tipo de letra legíveis"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Os links hreflang indicam aos motores de pesquisa a versão de uma página que devem apresentar nos resultados da pesquisa para um determinado idioma ou região. [Saiba mais](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "O documento não tem um `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "O documento tem um `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "As páginas com códigos de estado HTTP não executados com êxito podem não ser indexadas corretamente. [Saiba mais](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "A página tem código de estado HTTP não executado com êxito"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "A página tem código de estado HTTP executado com êxito"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Os motores de pesquisa não podem incluir as suas páginas nos resultados da pesquisa se não tiverem autorização para as rastrear. [Saiba mais](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "A página está impedida de ser indexada"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "A página não está impedida de ser indexada"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "O texto descritivo dos links ajuda os motores de pesquisa a compreender o conteúdo. [Saiba mais](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link encontrado}other{# links encontrados}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Os links não têm texto descritivo"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Os links têm texto descritivo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Execute a [Ferramenta de teste de dados estruturados](https://search.google.com/structured-data/testing-tool/) e o [Linter de dados estruturados](http://linter.structured-data.org/) para validar dados estruturados. [Saiba mais](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Os dados estruturados são válidos"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "As meta descrições podem ser incluídas nos resultados da pesquisa para resumir concisamente o conteúdo da página. [Saiba mais](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "O texto da descrição está vazio."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "O documento não tem uma meta descrição"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "O documento tem uma meta descrição"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Não é possível aos motores de pesquisa indexar o conteúdo de plug-ins e muitos dispositivos restringem plug-ins ou não os suportam. [Saiba mais](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "O documento utiliza plug-ins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "O documento evita plug-ins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Se o ficheiro robots.txt estiver mal formado, os motores de rastreio podem não conseguir compreender como pretende que o seu Website seja rastreado ou indexado. [Saiba mais](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "O pedido de robots.txt devolveu o seguinte estado de HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 erro encontrado}other{# erros encontrados}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "O Lighthouse não conseguiu transferir um ficheiro robots.txt."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "O ficheiro robots.txt não é válido"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "O ficheiro robots.txt é válido"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Os elementos interativos, como botões e links, devem ser suficientemente grandes (48 x 48 px) e ter espaço suficiente à volta para serem fáceis de tocar sem que se sobreponham a outros elementos. [Saiba mais](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Os alvos táteis foram dimensionados corretamente com um tamanho de {decimalProportion, number, percent}"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Os alvos táteis são demasiado pequenos porque não existe nenhuma metatag de área visível otimizada para ecrãs de dispositivos móveis."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Os alvos táteis não estão dimensionados corretamente"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Alvo sobreposto"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Alvo tátil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Os alvos táteis estão dimensionados corretamente"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "O service worker é a tecnologia que permite que a sua aplicação utilize muitas funcionalidades de progressive web app, tais como offline, adicionar ao ecrã principal e envios de notificações. [Saiba mais](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Esta página é controlada por um service worker, no entanto, não foi encontrado nenhum `start_url` porque o manifesto falhou ao analisar como um JSON válido."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Esta página é controlada por um service worker, no entanto, o `start_url` ({startUrl}) não está no âmbito do service worker ({scopeUrl})."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Esta página é controlada por um service worker, no entanto, não foi encontrado nenhum `start_url` porque não foi obtido nenhum manifesto."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Esta origem tem um ou mais service workers, no entanto, a página ({pageUrl}) não está no âmbito."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Não regista um service worker que controla a página e `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Regista um service worker que controla a página e `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Um ecrã inicial temático garante uma experiência de alta qualidade quando os utilizadores iniciam a aplicação a partir dos respetivos ecrãs principais. [Saiba mais](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Não está configurado para um ecrã inicial personalizado"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configurado para um ecrã inicial personalizado"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "A barra de endereço do navegador pode ter um tema que corresponda ao seu site. [Saiba mais](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Não define uma cor do tema para a barra de endereço."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Define uma cor do tema para a barra de endereço"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tempo de bloqueio do thread principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Terceiros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "O código de terceiros pode afetar significativamente o desempenho de carregamento. Limite o número de fornecedores terceiros redundantes e tente carregar o código de terceiros após a conclusão do carregamento da sua página. [Saiba mais](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "O código de terceiros bloqueou o thread principal durante {timeInMs, number, milliseconds} ms."
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduza o impacto do código de terceiros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Utilização de terceiros"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "A auditoria Tempo até ao primeiro byte indica o tempo de envio de uma resposta pelo seu servidor. [Saiba mais](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "O documento de raiz demorou {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduza os tempos de resposta do servidor (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Os tempos de resposta do servidor são curtos (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duração"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Hora de início"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipo"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Pondere a possibilidade de complementar a sua aplicação com a API Tempos do utilizador para analisar o desempenho real da aplicação durante as principais experiências do utilizador. [Saiba mais](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 tempo do utilizador}other{# tempos do utilizador}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Marcas e medições de Tempos do utilizador"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Foi encontrado um <link> de pré-ligação para \"{securityOrigin}\", mas este não foi utilizado pelo navegador. Confirme se está a utilizar o atributo `crossorigin` adequadamente."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Considere adicionar instruções para recursos de `preconnect` ou `dns-prefetch` para estabelecer ligações antecipadamente a origens de terceiros importantes. [Saiba mais](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Efetue a pré-ligação às origens necessárias"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Foi encontrado um <link> de pré-carregamento para \"{preloadURL}\", mas este não foi utilizado pelo navegador. Confirme se está a utilizar o atributo `crossorigin` adequadamente."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Considere utilizar `<link rel=preload>` para dar prioridade à obtenção de recursos que são atualmente solicitados mais tarde no carregamento de página. [Saiba mais](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Pré-carregue pedidos-chave"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Adicione uma etiqueta `<meta name=\"viewport\">` para otimizar a sua aplicação para ecrãs de dispositivos móveis. [Saiba mais](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nenhuma etiqueta `<meta name=\"viewport\">` encontrada."
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Não tem uma etiqueta `<meta name=\"viewport\">` com `width` ou `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Tem uma etiqueta `<meta name=\"viewport\">` com `width` ou `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "A sua aplicação deve apresentar algum conteúdo quando o JavaScript está desativado, mesmo que seja apenas um aviso ao utilizador de que o JavaScript é necessário para utilizar a aplicação. [Saiba mais](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "O corpo da página deve renderizar algum conteúdo se os respetivos scripts não estiverem disponíveis."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Não fornece conteúdo obsoleto quando o JavaScript não está disponível"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Contém algum conteúdo quando o JavaScript não está disponível"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Se estiver a criar uma progressive web app, considere utilizar um service worker para que a sua aplicação possa funcionar offline. [Saiba mais](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "A página atual não responde com um 200 quando está offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "A página atual responde com um 200 quando está offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "A página pode não estar a ser carregada offline porque o seu URL de teste ({requested}) foi redirecionado para \"{final}\". Experimente testar o segundo URL diretamente."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Estas são oportunidades para otimizar a utilização do ARIA na sua aplicação, que pode melhorar a experiência dos utilizadores de tecnologias de assistência, como os de leitores de ecrã."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Estas são oportunidades para fornecer conteúdo alternativo para áudio e vídeo. Pode melhorar a experiência dos utilizadores com deficiências auditivas ou visuais."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Áudio e vídeo"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Estes itens realçam as práticas recomendadas de acessibilidade comuns."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Práticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Estas verificações realçam as oportunidades de [melhorar a acessibilidade da sua aplicação Web](https://developers.google.com/web/fundamentals/accessibility). Apenas um subconjunto de problemas de acessibilidade pode ser detetado automaticamente, pelo que é recomendado efetuar também testes manuais."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Estes itens destinam-se a áreas não abrangidas por uma ferramenta de teste automatizada. Saiba mais no nosso guia sobre como [efetuar uma revisão de acessibilidade](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Acessibilidade"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Estas são oportunidades para melhorar a legibilidade do seu conteúdo."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contraste"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Estas são oportunidades para melhorar a interpretação do seu conteúdo por parte dos utilizadores em locais diferentes."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalização e localização"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Estas são oportunidades para melhorar a semântica dos controlos na sua aplicação. Desta forma, poderá melhorar a experiência dos utilizadores de tecnologia de assistência, como os de leitores de ecrã."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nomes e etiquetas"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Estas são oportunidades para melhorar a navegação do teclado na sua aplicação."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navegação"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Estas são oportunidades para melhorar a experiência de leitura de dados em tabelas ou listas com tecnologia de assistência, como os leitores de ecrã."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabelas e listas"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Práticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Os orçamentos de desempenho definem padrões para o desempenho do seu site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Orçamentos"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Mais informações sobre o desempenho da sua aplicação. Estes números não [afetam diretamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) a pontuação de desempenho."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnósticos"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "O aspeto mais importante do desempenho é a rapidez de renderização dos píxeis no ecrã. Métricas principais: Primeiro preenchimento com conteúdo, Primeiro preenchimento significativo."
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Melhorias no primeiro preenchimento"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Estas sugestões podem ajudar a sua página a ser carregada mais rapidamente. As mesmas não [afetam diretamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) a pontuação de desempenho."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunidades"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Métricas"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Melhore a experiência de carregamento geral para que a página responda e fique pronta a utilizar logo que possível. Métricas principais: Tempo até à interação, Índice de velocidade."
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Melhorias gerais"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Desempenho"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Estas verificações validam os aspetos de uma progressive web app. [Saiba mais](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "A [Lista de verificação de PWA](https://developers.google.com/web/progressive-web-apps/checklist) de referência requer estas verificações, mas as mesmas não são verificadas automaticamente pelo Lighthouse. Não afetam a sua pontuação, mas é importante que as valide manualmente."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive web app"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rápido e fiável"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Instalável"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA otimizada"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Estas verificações asseguram que a página está otimizada para a classificação de resultados dos motores de pesquisa. Existem fatores adicionais, que o Lighthouse não verifica, que podem afetar a classificação de pesquisa. [Saiba mais](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Execute estes verificadores adicionais no seu site para consultar mais práticas recomendadas de SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formate o HTML de uma forma que permita aos motores de rastreio compreender melhor o conteúdo da aplicação."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Práticas recomendadas para conteúdo"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Para ser apresentada nos resultados da pesquisa, os motores de rastreio necessitam de acesso à sua aplicação."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Rastreio e indexação"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Certifique-se de que as suas páginas são compatíveis com dispositivos móveis, de modo a que os utilizadores não tenham de juntar os dedos ou aumentar o zoom para lerem as páginas de conteúdo. [Saiba mais](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Compatível com dispositivos móveis"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL da cache"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Localização"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nome"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Pedidos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipo de recurso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Tamanho"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tempo gasto"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Tamanho da transferência"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Poupança potencial"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Poupança potencial"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Poupança potencial de {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Poupança potencial de {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Documento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Tipo de letra"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imagem"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Multimédia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Outro"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Folha de estilos"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Terceiros"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Ocorreu um erro ao registar o rastreio durante o carregamento da sua página. Volte a executar o Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Atingido o tempo limite de espera pela ligação inicial do protocolo do depurador."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "O Chrome não recolheu quaisquer capturas de ecrã durante o carregamento da página. Certifique-se de que existe conteúdo visível na página e, em seguida, experimente executar novamente o Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Os servidores DNS não conseguiram resolver o domínio fornecido."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "O coletor {artifactName} obrigatório encontrou o seguinte erro: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Ocorreu um erro interno do Chrome. Reinicie o Chrome e experimente executar novamente o Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "O coletor {artifactName} obrigatório não foi executado."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "O Lighthouse não conseguiu carregar com fiabilidade a página que solicitou. Certifique-se de que está a testar o URL correto e que o servidor está a responder adequadamente a todos os pedidos."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "O Lighthouse não conseguiu carregar com fiabilidade o URL que solicitou porque a página deixou de responder."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "O URL que forneceu não tem um certificado de segurança válido. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "O Chrome impediu o carregamento da página com um anúncio intercalar. Certifique-se de que está a testar o URL correto e que o servidor está a responder adequadamente a todos os pedidos."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "O Lighthouse não conseguiu carregar com fiabilidade a página que solicitou. Certifique-se de que está a testar o URL correto e que o servidor está a responder adequadamente a todos os pedidos. (Detalhes: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "O Lighthouse não conseguiu carregar com fiabilidade a página que solicitou. Certifique-se de que está a testar o URL correto e que o servidor está a responder adequadamente a todos os pedidos. (Código de estado: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "A sua página demorou demasiado tempo a ser carregada. Siga as oportunidades no relatório para reduzir o tempo de carregamento da página e, em seguida, experimente executar novamente o Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "A espera pela resposta do protocolo DevTools excedeu o tempo atribuído. (Método: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "A obtenção de conteúdo de recursos excedeu o tempo atribuído."
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "O URL que forneceu parece ser inválido."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostrar auditorias"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navegação inicial"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latência crítica máxima do caminho:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Erro!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Erro de relatório: sem informações de auditoria"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dados laboratoriais"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "A análise do [Lighthouse](https://developers.google.com/web/tools/lighthouse/) da página atual numa rede móvel emulada. Os valores são o resultado de uma estimativa e podem variar."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Itens adicionais a verificar manualmente"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Não aplicável"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunidade"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Poupança estimada"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditorias aprovadas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Reduzir fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Expandir fragmento"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostrar recursos de terceiros"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Ocorreram problemas que afetaram esta execução do Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Os valores são o resultado de uma estimativa e podem variar. A pontuação de desempenho é [baseada apenas nestas métricas](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "As auditorias foram concluídas com êxito, mas com avisos"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Avisos: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Considere carregar o GIF para um serviço que o disponibilizará para incorporação como vídeo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instale um [plug-in do WordPress de carregamento lento](https://wordpress.org/plugins/search/lazy+load/) com capacidade para adiar imagens não visíveis ou para mudar para um tema com essa funcionalidade. Considere ainda a utilização do [plug-in de AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Há vários plug-ins do WordPress que o podem ajudar a [colocar recursos críticos inline](https://wordpress.org/plugins/search/critical+css/) ou [adiar recursos menos importantes](https://wordpress.org/plugins/search/defer+css+javascript/). Tenha em atenção que as otimizações oferecidas por estes plug-ins podem quebrar funcionalidades do seu tema ou plug-ins, pelo que poderá ser necessário efetuar alterações ao código."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "As especificações dos temas, plug-ins e servidor, no seu conjunto, contribuem para o tempo de resposta do servidor. Considere procurar um tema mais otimizado, selecionar cuidadosamente um plug-in de otimização e/ou atualizar o servidor."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Considere mostrar excertos nas suas listas de publicações (por exemplo, através da etiqueta de mais), reduzir o número de publicações apresentadas numa determinada página, dividir as publicações longas em várias páginas ou utilizar um plug-in para tornar o carregamento de comentários lento."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Um número de [plug-ins do WordPress](https://wordpress.org/plugins/search/minify+css/) pode acelerar o seu site ao concatenar, reduzir e comprimir os seus estilos. Poderá ainda utilizar um processo de criação para proceder previamente à redução se possível."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Um número de [plug-ins do WordPress](https://wordpress.org/plugins/search/minify+javascript/) pode acelerar o seu site ao concatenar, reduzir e comprimir os seus scripts. Poderá ainda utilizar um processo de criação para proceder previamente à redução se possível."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Considere reduzir ou mudar o número de [plug-ins do WordPress](https://wordpress.org/plugins/) que carregam CSS não utilizadas na sua página. Para identificar plug-ins que estejam a adicionar CSS não reconhecido, experimente realizar a [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) nas DevTools do Chrome. Pode identificar o tema/plug-in responsável a partir do URL da folha de estilos. Esteja atento a plug-ins que tenham muitas folhas de estilo na lista com muito vermelho na cobertura do código. Um plug-in só deve ter uma folha de estilos na lista de espera se esta for realmente utilizada na página."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Considere reduzir ou mudar o número de [plug-ins do WordPress](https://wordpress.org/plugins/) que carregam JavaScript não utilizado na sua página. Para identificar plug-ins que estejam a adicionar JS não reconhecido, experimente realizar a [cobertura de código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) nas DevTools do Chrome. Pode identificar o tema/plug-in responsável a partir do URL do script. Esteja atento a plug-ins que tenham muitos scripts na lista com muito vermelho na cobertura do código. Um plug-in só deve ter um script na lista de espera se este for realmente utilizado na página."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Leia sobre [Colocação do navegador em cache no WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Considere utilizar um [plug-in do WordPress de otimização da imagem](https://wordpress.org/plugins/search/optimize+images/) que comprima as imagens, ao mesmo tempo que mantém a qualidade."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Carregue imagens diretamente a partir da [biblioteca de multimédia](https://codex.wordpress.org/Media_Library_Screen) para garantir que estão disponíveis os tamanhos de imagem necessários e, em seguida, introduza-as a partir da biblioteca de multimédia ou utilize o widget de imagens para garantir que são utilizados os tamanhos ideais das imagens (incluindo as referentes a breakpoints adaptáveis). Evite utilizar imagens de `Full Size`, a menos que as dimensões sejam adequadas à utilização. [Saiba mais](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Pode ativar a compressão de texto na configuração do servidor Web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Considere utilizar um [plug-in](https://wordpress.org/plugins/search/convert+webp/) ou serviço que converta automaticamente as imagens carregadas nos formatos ideais."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt.json
new file mode 100644
index 00000000000..e396fb9fd2c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/pt.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "As chaves de acesso permitem ao usuário focar rapidamente determinada parte da página. Para haver uma navegação adequada, cada chave de acesso precisa ser única. [Saiba mais](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Os valores de `[accesskey]` não são únicos"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Valores de `[accesskey]` são exclusivos"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Cada `role` ARIA é compatível com um subconjunto específico de atributos `aria-*`. A falta de correspondência entre eles invalida os atributos `aria-*`. [Saiba mais](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não correspondem às próprias funções"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Os atributos `[aria-*]` correspondem às próprias funções"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Algumas funções ARIA têm atributos obrigatórios que descrevem o estado do elemento para leitores de tela. [Saiba mais](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`s não têm todos os atributos `[aria-*]` obrigatórios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]`s têm todos os atributos `[aria-*]` obrigatórios"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Algumas funções ARIA mães precisam ter funções filhas específicas para cumprir as tarefas de acessibilidade pretendidas. [Saiba mais](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementos com uma `[role]` ARIA que exigem que os filhos contenham uma `[role]` específica não têm alguns ou nenhum dos filhos obrigatórios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementos com uma `[role]` ARIA que exigem que os filhos contenham uma `[role]` específica têm todos os filhos obrigatórios."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Algumas funções ARIA filhas precisam fazer parte das funções mães específicas para cumprir as tarefas de acessibilidade pretendidas. [Saiba mais](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`s não fazem parte do elemento pai obrigatório"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`s fazem parte do elemento pai obrigatório"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "As funções ARIA precisam ter valores válidos para que realizem as tarefas de acessibilidade pretendidas. [Saiba mais](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Os valores de `[role]` não são válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Os valores de `[role]` são válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Tecnologias assistivas, como leitores de tela, não conseguem interpretar atributos ARIA com valores inválidos. [Saiba mais](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não têm valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Os atributos `[aria-*]` têm valores válidos"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "As tecnologias assistivas, como leitores de tela, não conseguem interpretar atributos ARIA com nomes inválidos. [Saiba mais](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Os atributos `[aria-*]` não são válidos nem contêm erros de ortografia"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Os atributos `[aria-*]` são válidos e não contêm erros de ortografia"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "As legendas tornam os elementos de áudio úteis para pessoas surdas ou deficientes auditivas, disponibilizando informações essenciais, como quem está falando, o que a pessoa está dizendo e outras informações não relacionadas à fala. [Saiba mais](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Os elementos `<audio>` estão sem um elemento `<track>` com `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Os elementos `<audio>` contêm um elemento `<track>` com `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementos com falha"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Quando um botão não tem um nome acessível, os leitores de tela o enunciam como \"botão\", o que o inutiliza para usuários que dependem desses leitores. [Saiba mais](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Os botões não têm um nome acessível"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Os botões têm um nome acessível"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "A adição de maneiras de ignorar conteúdo repetido permite ao usuário do teclado navegar pela página com mais eficiência. [Saiba mais](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "A página não contém um cabeçalho, link de salto ou região de ponto de referência"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "A página contém um título, um link de salto ou uma região de ponto de referência"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Para muitos usuários, é difícil ou impossível ler textos com baixo contraste. [Saiba mais](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "As cores de primeiro e segundo plano não têm uma taxa de contraste suficiente."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "As cores de primeiro e segundo plano têm uma taxa de contraste suficiente"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Quando listas de definição não são marcadas corretamente, os leitores de tela podem produzir resultados confusos ou imprecisos. [Saiba mais](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>`s não contêm apenas grupos `<dt>` e `<dd>` devidamente organizados e elementos `<script>` ou `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`s contêm apenas os grupos `<dt>` e `<dd>` devidamente organizados ou os elementos `<script>` ou `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Os itens da lista de definição (`<dt>` e `<dd>`) precisam ficar unidos em um elemento `<dl>` pai para garantir que os leitores de tela consigam enunciá-los corretamente. [Saiba mais](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Os itens da lista de definição não estão unidos em elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Os itens da lista de definição estão unidos em elementos `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "O título oferece ao usuário do leitor de tela uma visão geral da página, além de ser extremamente útil para que os usuários de mecanismos de pesquisa determinem se uma página é relevante à pesquisa deles. [Saiba mais](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "O documento não tem um elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "O documento tem um elemento `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "O valor de um atributo \"id\" precisa ser único para evitar que outras instâncias sejam ignoradas por tecnologias assistivas. [Saiba mais](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Os atributos `[id]` da página não são únicos"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Os atributos `[id]` da página são únicos"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Os usuários de leitores de tela utilizam títulos para descrever o conteúdo de frames. [Saiba mais](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Os elementos `<frame>` ou `<iframe>` não têm um título"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Os elementos `<frame>` ou `<iframe>` têm um título"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Se uma página não especificar um atributo lang, o leitor de tela presumirá que a página está no idioma padrão que o usuário escolheu ao configurar esse leitor. Se a página não estiver no idioma padrão, o leitor de tela poderá ler o texto dela incorretamente. [Saiba mais](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "O elemento `<html>` não tem um atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "O elemento `<html>` tem um atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "A especificação de um [idioma BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido ajuda os leitores de tela a enunciar o texto corretamente. [Saiba mais](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "O elemento `<html>` não tem um valor válido para o atributo `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "O elemento `<html>` tem um valor válido para o atributo `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "O texto dos elementos informativos precisa ser alternativo, breve e descritivo. Os elementos decorativos podem ser ignorados com um atributo alternativo vazio. [Saiba mais](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Os elementos de imagem não têm atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Os elementos de imagem têm atributos `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Quando uma imagem for usada como um botão `<input>`, a oferta de texto alternativo poderá ajudar o usuário do leitor de tela a entender a finalidade do botão. [Saiba mais](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Os elementos `<input type=\"image\">` não têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Os elementos `<input type=\"image\">` têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "As etiquetas garantem que os controles de formulário sejam enunciados corretamente por tecnologias assistivas, como leitores de tela. [Saiba mais](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Os elementos de formulário não têm etiquetas associadas"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Os elementos de formulário têm etiquetas associadas"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Não inclua elementos de dados, como os elementos \"th\" ou \"caption\", nem o atributo \"summary\" em uma tabela utilizada para fins de layout, já que isso pode gerar uma experiência confusa para os usuários de leitores de telas. [Saiba mais](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Os elementos `<table>` de apresentação não evitam o uso de `<th>`, `<caption>` ou do atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Os elementos `<table>` de apresentação evitam o uso de `<th>`, `<caption>` ou do atributo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Textos de link (e textos alternativos de imagens, quando utilizados como link) compreensíveis, únicos e focalizáveis melhoram a experiência de navegação para usuários de leitores de tela. [Saiba mais](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Os links não têm um nome compreensível"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Os links têm um nome compreensível"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Os leitores de tela têm uma maneira específica de enunciar listas. Uma estrutura de lista adequada melhora os resultados do leitor de tela. [Saiba mais](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "As listas não contêm apenas elementos `<li>` e elementos compatíveis com script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "As listas contêm somente elementos `<li>` e elementos compatíveis com script (`<script>` e `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Os leitores de tela exigem que os itens de lista (`<li>`) estejam contidos em um `<ul>` ou `<ol>` pai para serem enunciados corretamente. [Saiba mais](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Os itens de lista (`<li>`) não estão contidos nos elementos pai `<ul>` ou `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Os itens de lista (`<li>`) estão contidos nos elementos pai `<ul>` ou `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "O usuário não espera a atualização automática da página, o que move o foco novamente para a parte superior dela. Isso pode causar uma experiência confusa ou frustrante. [Saiba mais](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "O documento usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "O documento não usa `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "A desativação do zoom gera problemas para usuários com baixa visão que utilizam a ampliação de tela para enxergar corretamente o conteúdo de uma página da Web. [Saiba mais](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` é usado no elemento `<meta name=\"viewport\">` ou o atributo `[maximum-scale]` é menor que 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` não é usado no elemento `<meta name=\"viewport\">`, e o atributo `[maximum-scale]` não é menor que 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Os leitores de tela não traduzem conteúdo não textual. A adição de texto alternativo aos elementos `<object>` ajuda os leitores de tela a transmitir o significado para os usuários. [Saiba mais](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Os elementos `<object>` não têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Os elementos `<object>` têm texto `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Um valor maior que 0 indica uma ordem explícita de navegação. Embora tecnicamente válido, isso costuma gerar experiências frustrantes para os usuários que utilizam tecnologias assistivas. [Saiba mais](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Alguns elementos têm um valor de `[tabindex]` maior que 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Nenhum elemento tem um valor de `[tabindex]` maior que 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Os leitores de tela têm recursos para facilitar a navegação em tabelas. Para melhorar a experiência dos usuários de leitores de tela, as células `<td>` que usam o atributo `[headers]` precisam referenciar apenas outras células na mesma tabela. [Saiba mais](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Células em um elemento `<table>` que usam o atributo `[headers]` referem-se a um elemento `id` não encontrado na mesma tabela."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Células em um elemento `<table>` que usam o atributo `[headers]` referem-se às células na mesma tabela."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Os leitores de tela têm recursos para facilitar a navegação em tabelas. Garantir que os cabeçalhos das tabelas se refiram sempre a alguns conjuntos de células pode melhorar a experiência dos usuários de leitores de tela. [Saiba mais](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Os elementos `<th>` e os elementos com `[role=\"columnheader\"/\"rowheader\"]` não têm as células de dados descritas."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Os elementos `<th>` e os elementos com `[role=\"columnheader\"/\"rowheader\"]` têm as células de dados descritas."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "A especificação de um [idioma BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) válido nos elementos ajuda a garantir que o texto seja pronunciado corretamente pelo leitor de tela. [Saiba mais](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Os atributos `[lang]` não têm um valor válido"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Os atributos `[lang]` têm um valor válido"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Quando um vídeo é acompanhado de legendas, as pessoas surdas e deficientes auditivas têm mais facilidade para acessar as informações dele. [Saiba mais](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Os elementos `<video>` não contêm um elemento `<track>` com `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Os elementos `<video>` contêm um elemento `<track>` com `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "As descrições de áudio trazem informações importantes que não podem ser transmitidas por meio do diálogo nos vídeos, por exemplo, expressões faciais e cenários. [Saiba mais](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Os elementos `<video>` não contêm um elemento `<track>` com `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Os elementos `<video>` contêm um elemento `<track>` com `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Para ter uma exibição ideal no iOS quando o usuário adiciona um Progressive Web App à tela inicial, defina um `apple-touch-icon`. Ele precisa apontar para um PNG quadrado não transparente de 192 px (ou 180 px). [Saiba mais](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Não oferece um `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` está desatualizado. Use `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Disponibiliza um `apple-touch-icon` válido"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "As extensões do Chrome afetaram negativamente o desempenho de carregamento desta página. Tente fazer a auditoria da página no modo de navegação anônima ou em um perfil do Chrome sem extensões."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Avaliação de script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Análise de script"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tempo total de CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Diminua o tempo gasto na análise, compilação e execução de JS. Você perceberá que exibir payloads de JS menores ajuda a fazer isso. [Saiba mais](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Reduza o tempo de execução de JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Tempo de execução de JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "GIFs grandes não são eficientes para exibir conteúdo animado. Use vídeos MPEG4/WebM para animações e PNG/WebP para imagens estáticas em vez de GIF para economizar bytes de rede. [Saiba mais](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Use formatos de vídeo para conteúdo animado"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "A fim de reduzir o tempo para interação da página, faça o carregamento lento de imagens fora da tela e ocultas quando todos os recursos críticos já estiverem carregados. [Saiba mais](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Adie imagens fora da tela"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Os recursos estão bloqueando a primeira exibição da sua página. Exiba JS/CSS crítico inline e adie todos os JS/estilos não críticos. [Saiba mais](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimine recursos que impedem a renderização"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Grandes payloads de rede geram custos para o usuário e estão diretamente relacionados a tempos de carregamento maiores. [Saiba mais](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "O tamanho total foi de {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evite payloads de rede muito grandes"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evita payloads de rede muito grandes"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "A redução de arquivos CSS pode diminuir o tamanho do payload de rede. [Saiba mais](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Reduza o CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "A redução de arquivos JavaScript pode diminuir o tamanho de payloads e o tempo de análise de scripts. [Saiba mais](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Reduza o JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Remova as regras inativas das folhas de estilo e adie o carregamento de CSS não usado para conteúdo acima da dobra, a fim de reduzir o consumo desnecessário de bytes da atividade da rede. [Saiba mais](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Remova CSS não utilizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Remova o JavaScript não utilizado para reduzir o consumo de bytes da atividade de rede."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Remova o JavaScript não utilizado"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Um cache com ciclo de vida longo pode acelerar visitas repetidas à sua página. [Saiba mais](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 recurso encontrado}one{# recurso encontrado}other{# recursos encontrados}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Disponibilize recursos estáticos com uma política de cache eficiente"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Usa uma política de cache eficiente em recursos estáticos"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Imagens otimizadas são carregadas mais rapidamente e consomem menos dados da rede celular. [Saiba mais](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifique as imagens com eficiência"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Veicule imagens que tenham o tamanho adequado para economizar dados da rede celular e melhorar o tempo de carregamento. [Saiba mais](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Defina um tamanho adequado para as imagens"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Os recursos baseados em texto precisam ser veiculados com compactação (gzip, deflate ou brotli) para minimizar o total de bytes da rede. [Saiba mais](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Ative a compactação de texto"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formatos de imagem como JPEG 2000, JPEG XR e WebP geralmente oferecem uma melhor compactação do que PNG ou JPEG, o que significa downloads mais rápidos e menor consumo de dados. [Saiba mais](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Disponibilize imagens em formatos de última geração"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Se a largura do conteúdo do seu app não corresponder à largura da janela de visualização, não será possível otimizar o app para telas de dispositivos móveis. [Saiba mais](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "O tamanho da janela de visualização de {innerWidth} px não corresponde ao tamanho da janela {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "O conteúdo não está no tamanho correto para a janela de visualização"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "O conteúdo está no tamanho correto para a janela de visualização"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "As cadeias de solicitação críticas abaixo mostram quais recursos são carregados com prioridade alta. Diminua o tamanho das cadeias, reduza o tamanho do download de recursos ou adie o download de recursos desnecessários para melhorar o carregamento de página. [Saiba mais](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 rede encontrada}one{# rede encontrada}other{# redes encontradas}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Reduza a profundidade de solicitações críticas"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Suspensão de uso/aviso"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Linha"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "As APIs obsoletas acabarão sendo removidas do navegador. [Saiba mais](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 aviso encontrado}one{# aviso encontrado}other{# avisos encontrados}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Utiliza APIs obsoletas"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evita APIs obsoletas"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "O cache de aplicativo está obsoleto. [Saiba mais](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" encontrado"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Usa cache de aplicativo"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evita o cache de aplicativo"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "A especificação de um doctype evita que o navegador alterne para o modo quirks. [Saiba mais](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "O nome do doctype precisa ser o `html` da string em letra minúscula"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "O documento precisa conter um doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "O ID público deveria ser uma string vazia"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "O ID do sistema deveria ser uma string vazia"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "A página não tem o doctype HTML e, assim, aciona o modo quirks"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "A página tem o doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Elemento"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Estatística"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Os engenheiros do navegador recomendam páginas com menos de ~1.500 elementos DOM. A posição ideal é uma profundidade de árvore com menos de 32 elementos e menos de 60 elementos filhos/pais. Um DOM grande pode aumentar o uso da memória, causar [cálculos de estilo](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) mais longos e produzir [reflows de layout](https://developers.google.com/speed/articles/reflow) dispendiosos. [Saiba mais](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 elemento}one{# elemento}other{# elementos}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evite DOM de tamanho excessivo"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Profundidade máxima de DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Total de elementos DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Máximo de elementos filhos"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evita DOM de tamanho excessivo"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Destino"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Adicione `rel=\"noopener\"` ou `rel=\"noreferrer\"` a qualquer link externo para melhorar o desempenho e evitar vulnerabilidades de segurança. [Saiba mais](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Links para destinos de origem cruzada não são seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Links para destinos de origem cruzada são seguros"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Não é possível determinar o destino do item fixo ({anchorHTML}). Se não for usado como um hiperlink, remova target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Os usuários não confiam ou ficam confusos com sites que solicitam a localização sem contexto. Vincule a solicitação a uma ação do usuário. [Saiba mais](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Solicita a permissão de geolocalização no carregamento de página"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evita o pedido da permissão de geolocalização no carregamento de página"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versão"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Todas as bibliotecas JavaScript de front-end detectadas na página. [Saiba mais](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Bibliotecas JavaScript detectadas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Para usuários em conexões lentas, os scripts externos injetados dinamicamente via `document.write()` podem atrasar o carregamento de página em dezenas de segundos. [Saiba mais](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Usa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evita `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Maior gravidade"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versão da biblioteca"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Contagem de vulnerabilidades"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Alguns scripts de terceiros podem conter vulnerabilidades de segurança conhecidas, facilmente identificadas e exploradas por invasores. [Saiba mais](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vulnerabilidade detectada}one{# vulnerabilidade detectada}other{# vulnerabilidades detectadas}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Inclui bibliotecas JavaScript de front-end com vulnerabilidades de segurança conhecidas"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Alto"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Baixo"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Médio"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evita bibliotecas JavaScript de front-end com vulnerabilidades de segurança conhecidas"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Os usuários não confiam ou ficam confusos com sites que solicitam o envio de notificações sem contexto. Vincule a solicitação a gestos do usuário. [Saiba mais](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Solicita a permissão de notificação no carregamento de página"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evita o pedido da permissão de notificação no carregamento de página"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementos com falha"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Impedir a colagem da senha prejudica a política de boa segurança. [Saiba mais](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Evita que o usuário cole nos campos de senha"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permite que o usuário cole nos campos de senha"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocolo"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 oferece muitos benefícios com relação ao HTTP/1.1, incluindo cabeçalhos binários, multiplexação e push do servidor. [Saiba mais](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 solicitação não veiculada via HTTP/2}one{# solicitação não veiculada via HTTP/2}other{# solicitações não veiculadas via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Não utiliza HTTP/2 para todos os recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Usa HTTP/2 para os próprios recursos"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Marque os listeners de eventos de toque e rolagem como `passive` para melhorar o desempenho de rolagem da página. [Saiba mais](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Não utiliza listeners passivos para melhorar o desempenho de rolagem"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Utiliza listeners passivos para melhorar o desempenho de rolagem"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descrição"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Os erros registrados no console indicam problemas não resolvidos. Eles podem ocorrer devido a falhas de solicitação de rede e outras questões relacionadas ao navegador. [Saiba mais](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Erros do navegador foram registrados no console"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nenhum erro do navegador registrado no console"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Use o recurso CSS de exibição de fonte para garantir que o texto possa ser visto pelo usuário enquanto as webfonts são carregadas. [Saiba mais](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Garanta que o texto continue visível durante o carregamento da webfont"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Todo o texto continua visível durante o carregamento da webfont"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "O Lighthouse não conseguiu verificar automaticamente o valor de exibição da fonte para o seguinte URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Proporção (real)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Proporção (exibida)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "As dimensões de exibição da imagem devem corresponder à proporção. [Saiba mais](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Exibe imagens com a proporção incorreta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Exibe imagens com a proporção correta"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informações inválidas para tamanho de imagem {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Os navegadores podem solicitar automaticamente aos usuários que adicionem o app à tela inicial deles, o que pode aumentar a interação. [Saiba mais](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "O manifesto do app da Web não atende os requisitos de instabilidade."
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "O manifesto do app de Web atende aos requisitos de instabilidade."
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL não seguro"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Todos os sites devem ser protegidos com HTTPS, mesmo aqueles que não lidam com dados confidenciais. O HTTPS evita que invasores falsifiquem ou escutem passivamente a comunicação entre o app e o usuário, além de ser um pré-requisito para HTTP/2 e muitas novas APIs para plataforma da Web. [Saiba mais](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 solicitação não segura encontrada}one{# solicitação não segura encontrada}other{# solicitações não seguras encontradas}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Não utiliza HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Utiliza HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Um carregamento de página rápido em uma rede celular garante uma boa experiência do usuário em dispositivos móveis. [Saiba mais](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interativa em {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interativa na rede móvel simulada em {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Esta página está carregando muito lentamente e está há 10 segundos sem interagir. Consulte a seção \"Desempenho\" e veja oportunidades e diagnósticos para saber como melhorar o desempenho."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "A velocidade de carregamento da página não é suficiente em redes móveis"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "A velocidade de carregamento da página é suficiente em redes móveis"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categoria"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Considere diminuir o tempo gasto na análise, compilação e execução de JS. Você perceberá que exibir payloads de JS menores ajuda a fazer isso. [Saiba mais](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimize o trabalho da thread principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimiza o trabalho da thread principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Os sites precisam funcionar em todos os principais navegadores para que sejam acessíveis ao maior número de usuários. [Saiba mais](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "O site funciona em diferentes navegadores"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "É necessário que as páginas individuais permitam links diretos via URL e que os URLs sejam exclusivos para o propósito de compartilhamento em mídias sociais. [Saiba mais](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Cada página tem um URL."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "As transições precisam ser dinâmicas durante a navegação por toque, mesmo em uma conexão de rede lenta. Essa experiência é essencial para a percepção de desempenho. [Saiba mais](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "As transições de página não devem parecer bloqueadas pelo carregamento da rede."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "\"Latência de entrada estimada\" é uma estimativa de quanto tempo o app leva para responder à entrada do usuário, em milésimos de segundo, durante a janela de carregamento de página mais movimentada de cinco segundos. Se a latência for maior que 50 ms, o usuário poderá notar lentidão no app. [Saiba mais](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latência de entrada estimada"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "\"Primeira exibição de conteúdo\" marca o momento em que o primeiro texto ou imagem é disponibilizado. [Saiba mais](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Primeiro aparecimento com conteúdo"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "\"Primeira CPU ociosa\" marca a primeira vez que a linha de execução principal da página fica silenciosa o suficiente para lidar com a entrada. [Saiba mais](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primeira CPU ociosa"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "\"Primeira exibição significativa\" marca o momento em que o conteúdo principal de uma página se torna visível. [Saiba mais](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Primeira exibição importante"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "\"Tempo para interação da página\" é o período necessário para que ela fique totalmente interativa. [Saiba mais](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tempo até ficar interativa"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "A possível latência máxima na primeira entrada que seus usuários notariam seria a duração, em milésimos de segundo, da tarefa mais longa. [Saiba mais](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Possível latência máxima na primeira entrada"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "\"Índice de velocidade\" mostra a rapidez com que o conteúdo de uma página é preenchido visivelmente. [Saiba mais](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Índice de velocidade"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Soma de todos os períodos entre \"FCP\" e \"Tempo para interação da página\", quando a duração da tarefa ultrapassa 50 ms, expressa em milésimos de segundo."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tempo total de bloqueio"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "O tempo de retorno (RTT, na sigla em inglês) da rede tem um grande impacto no desempenho. Se o RTT para uma origem é alto, significa que os servidores mais próximos do usuário poderiam melhorar o desempenho. [Saiba mais](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Tempos de retorno da rede"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "As latências de servidor podem afetar o desempenho na Web. Se a latência do servidor de uma origem for alta, isso indica que ele está sobrecarregado ou que o back-end apresenta um desempenho ruim. [Saiba mais](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latências do back-end do servidor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Um service worker permite que seu app da Web funcione de maneira confiável em condições imprevisíveis de rede. [Saiba mais](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` não responde com um código 200 quando off-line."
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` responde com um código 200 quando off-line."
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "A propriedade `start_url` não pode ser lida pelo Lighthouse no manifesto. Como resultado, a URL do documento foi considerada como `start_url`. Mensagem de erro: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Acima do orçamento"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Mantenha a quantidade e o tamanho de solicitações de rede de acordo com os destinos definidos pelo orçamento de desempenho informado. [Saiba mais](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 solicitação}one{# solicitação}other{# solicitações}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Orçamento de desempenho"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Se você já definiu o HTTPS, redirecione todo o tráfego HTTP para HTTPS para garantir recursos da Web para todos os seus usuários. [Saiba mais](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "O tráfego HTTP não é redirecionado para HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "O tráfego HTTP é redirecionado para HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Os redirecionamentos causam mais atrasos antes do carregamento da página. [Saiba mais](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evite redirecionamentos múltiplos de página"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Para definir orçamentos para a quantidade e o tamanho dos recursos da página, adicione um arquivo budget.json. [Saiba mais](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 solicitação de • {byteCount, number, bytes} KB}one{# solicitação de • {byteCount, number, bytes} KB}other{# solicitações de • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Mantenha as contagens de solicitações baixas e os tamanhos de transferência pequenos"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Os links canônicos sugerem o URL a ser exibido nos resultados da pesquisa. [Saiba mais](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Vários URLs com conflito ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Aponta para um domínio diferente ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL inválido ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Aponta para outro local de `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL relativo ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Aponta para o URL raiz do domínio (a página inicial), em vez de uma página de conteúdo equivalente"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "O documento não tem um `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "O documento tem um `rel=canonical` válido"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Fontes menores que 12 px não são legíveis e exigem que os visitantes que utilizam dispositivos móveis façam um gesto de pinça para aumentar o zoom e conseguir ler. Faça o possível para ter mais de 60% do texto da página com pelo menos 12 px. [Saiba mais](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} do texto legível"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "O texto é ilegível porque não há nenhuma metatag de janela de visualização otimizada para telas de dispositivos móveis."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} do texto é muito pequeno (com base na amostra de {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "O documento não usa tamanhos de fonte legíveis"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "O documento usa tamanhos de fonte legíveis"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Os links hreflang informam aos mecanismos de pesquisa qual versão de uma página deve ser listada nos resultados de pesquisa para um determinado idioma ou região. [Saiba mais](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "O documento não tem um `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "O documento tem um `hreflang` válido"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "As páginas com falha no código de status HTTP talvez não sejam indexadas corretamente. [Saiba mais](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "A página tem uma falha no código de status HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "A página tem um código de status HTTP bem-sucedido"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Os mecanismos de pesquisa não poderão incluir suas páginas nos resultados se não tiverem permissão para rastreá-las. [Saiba mais](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "A página está bloqueada para indexação"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "A página não está bloqueada para indexação"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "O texto com link descritivo ajuda os mecanismos de pesquisa a entender o conteúdo. [Saiba mais](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 link encontrado}one{# link encontrado}other{# links encontrados}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Os links não têm texto descritivo"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Os links têm texto descritivo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Execute a [Ferramenta de teste de dados estruturados](https://search.google.com/structured-data/testing-tool/) e a [Structured Data Linter](http://linter.structured-data.org/) para validar os dados estruturados. [Saiba mais](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Os dados estruturados são válidos"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metadescrições podem ser incluídas nos resultados da pesquisa para resumir concisamente o conteúdo da página. [Saiba mais](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "O campo de texto da descrição está vazio."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "O documento não tem uma metadescrição"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "O documento tem uma metadescrição"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Mecanismos de pesquisa não podem indexar conteúdo de plug-in, e muitos dispositivos restringem plug-ins ou não são compatíveis com eles. [Saiba mais](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "O documento usa plug-ins"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "O documento evita plug-ins"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Se o arquivo robots.txt for inválido, talvez não seja possível aos rastreadores entender como você quer que seu site seja rastreado ou indexado. [Saiba mais](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "A solicitação para robots.txt retornou o status HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 erro encontrado}one{# erro encontrado}other{# erros encontrados}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "O Lighthouse não fez o download de um arquivo robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt não é válido"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt é válido"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Os elementos interativos, como botões e links, precisam ser grandes o bastante (48x48 px) e ter espaço suficiente ao redor para poderem ser tocados sem sobreposição com outros elementos. [Saiba mais](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} de áreas de toque dimensionadas corretamente"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "As áreas de toque são muito pequenas porque não há nenhuma metatag de janela de visualização otimizada para telas de dispositivos móveis"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "As áreas de toque não estão dimensionadas corretamente"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Área com sobreposição"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Área de toque"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "As áreas de toque estão dimensionadas corretamente"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "O service worker é a tecnologia que permite que seu app use muitos recursos do Progressive Web App, como disponibilidade off-line, adicionar à tela inicial, e notificações de push. [Saiba mais](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Esta página é controlada por um service worker, no entanto, nenhum `start_url` foi encontrado porque o manifesto não foi analisado como um JSON válido."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Esta página é controlada por um service worker, no entanto, a `start_url` ({startUrl}) não está no escopo dele ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Esta página é controlada por um service worker, no entanto, nenhuma `start_url` foi encontrada porque nenhum manifesto foi recuperado."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Esta origem tem um ou mais service workers, no entanto, a página ({pageUrl}) não está em escopo."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Não há registro de um service worker que controle a página e `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Há registro de um service worker que controla a página e `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Uma tela de apresentação personalizada garante uma experiência de alta qualidade quando os usuários abrem o aplicativo na tela inicial. [Saiba mais](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Não foi configurado para uma tela de apresentação personalizada"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configurado para uma tela de apresentação personalizada"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "É possível atribuir um tema relacionado ao seu site à barra de endereço do navegador. [Saiba mais](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Não foi definida uma cor de tema para a barra de endereços."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Foi definida uma cor de tema para a barra de endereços."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tempo de bloqueio da linha de execução principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Terceiros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Código de terceiros pode afetar significativamente o desempenho de carregamento. Limite o número de provedores terceiros redundantes e carregue o código de terceiros depois que a página tiver sido carregada. [Saiba mais](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "A linha de execução principal foi bloqueada por {timeInMs, number, milliseconds} ms pelo código de terceiros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Reduza o impacto de códigos de terceiros"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Uso de terceiros"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "\"Tempo até o primeiro byte\" identifica o momento em que o servidor envia uma resposta. [Saiba mais](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "O documento raiz levou {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Reduza os tempos de resposta do servidor (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Os tempos de resposta do servidor são baixos (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Duração"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Horário de início"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tipo"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Instrumente seu app com a API User Timing para avaliar o desempenho real do app durante as principais experiências do usuário. [Saiba mais](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 velocidade do usuário}one{# velocidade do usuário}other{# velocidades do usuário}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Marcações e medições de User Timing"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Um <link> de pré-conexão foi encontrado para \"{securityOrigin}\", mas não foi utilizado pelo navegador. Verifique se você está usando o atributo `crossorigin` corretamente."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Adicione dicas de recursos de `preconnect` ou `dns-prefetch` para estabelecer conexões antecipadas a origens importantes de terceiros. [Saiba mais](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Pré-conecte às origens necessárias"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Um <link> de pré-carregamento foi encontrado para \"{preloadURL}\", mas não foi usado pelo navegador. Verifique se você está usando o atributo `crossorigin` corretamente."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Use `<link rel=preload>` para priorizar a busca de recursos que, no momento, são solicitados posteriormente no carregamento de página. [Saiba mais](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Pré-carregue as principais solicitações"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Adicione uma tag `<meta name=\"viewport\">` para otimizar seu app para telas de dispositivos móveis. [Saiba mais](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nenhuma tag `<meta name=\"viewport\">` foi encontrada."
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Não há uma tag `<meta name=\"viewport\">` com `width` ou `initial-scale` definida"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Há uma tag `<meta name=\"viewport\">` com `width` ou `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Seu app precisa mostrar algum conteúdo quando o JavaScript está desativado, mesmo que seja somente um aviso de que o JavaScript é necessário para o uso do app. [Saiba mais](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "O corpo da página precisa renderizar algum conteúdo se os scripts não estão disponíveis."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Nenhum conteúdo substituto é exibido quando o JavaScript não está disponível."
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Algum conteúdo é exibido quando o JavaScript não está disponível."
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Se você estiver criando um Progressive Web App, é recomendável usar um service worker para que seu app possa funcionar off-line. [Saiba mais](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "A página atual não responde com um código 200 quando off-line"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "A página atual responde com um código 200 quando off-line"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "A página pode não carregar off-line porque sua URL de teste ({requested}) foi redirecionada para \"{final}\". Tente a segunda URL diretamente."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar o uso de ARIA no seu aplicativo, o que pode aprimorar a experiência dos usuários de tecnologias assistivas, como leitores de tela."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Veja aqui oportunidades de oferecer conteúdo alternativo para áudio e vídeo. Isso pode melhorar a experiência de usuários com deficiências auditivas e visuais."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Áudio e vídeo"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Esses itens destacam as práticas recomendadas comuns para acessibilidade."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Práticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Essas verificações destacam oportunidades para [melhorar a acessibilidade do seu app da Web](https://developers.google.com/web/fundamentals/accessibility). Somente um subconjunto de problemas de acessibilidade pode ser detectado automaticamente, portanto, testes manuais também devem ser realizados."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Esses itens se referem a áreas que uma ferramenta de teste automatizada não pode cobrir. Saiba mais no nosso guia sobre [como realizar uma avaliação de acessibilidade](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Acessibilidade"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar a legibilidade do seu conteúdo."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contraste"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar a interpretação que usuários de diferentes localidades fazem do seu conteúdo."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalização e localização"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar a semântica dos controles do seu aplicativo. Isso pode melhorar a experiência de usuários de tecnologias assistivas, como leitores de tela."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nomes e etiquetas"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar a navegação por teclado no seu aplicativo."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navegação"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Veja aqui oportunidades de melhorar a experiência de leitura de dados em tabelas ou listas usando tecnologia assistiva, como um leitor de tela."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabelas e listas"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Práticas recomendadas"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Os orçamentos de desempenho definem padrões para o desempenho do seu site."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Orçamentos"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Mais informações sobre o desempenho do seu aplicativo. Esses números não [afetam diretamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) o índice de desempenho."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnóstico"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "O aspecto de desempenho mais importante é a rapidez com que os pixels são renderizados na tela. Principais métricas: Primeiro aparecimento com conteúdo, Primeira exibição importante"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Melhorias do primeiro aparecimento"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Essas sugestões podem ajudar a acelerar o carregamento de página. Elas não [afetam diretamente](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) o índice de desempenho."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunidades"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Métricas"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Aprimore a experiência geral de carregamento, para que a página seja responsiva e esteja pronta para ser usada assim que possível. Principais métricas: Tempo até fica interativa, Índice de velocidade"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Melhorias gerais"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Desempenho"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Estas verificações validam os aspectos de um Progressive Web App. [Saiba mais](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Essas verificações são solicitadas pela [Lista de verificação de PWA](https://developers.google.com/web/progressive-web-apps/checklist) de referência, mas não são automaticamente realizadas pelo Lighthouse. Elas não afetam sua pontuação, mas é importante verificá-las manualmente."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rápido e confiável"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Pode ser instalado"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Otimizado para PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Essas verificações garantem que sua página seja otimizada para a classificação dos resultados dos mecanismos de pesquisa. Existem outros fatores que o Lighthouse não verifica e que podem afetar a classificação da pesquisa. [Saiba mais](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Execute estes validadores adicionais no seu site para verificar mais práticas recomendadas de SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formate seu HTML de maneira que permita que os rastreadores entendam melhor o conteúdo do seu app."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Práticas recomendadas para conteúdo"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Para que seu app seja exibido nos resultados da pesquisa, é necessário que os rastreadores tenham acesso a ele."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Rastreamento e indexação"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Suas páginas precisam ser compatíveis com dispositivos móveis, para que o usuário não tenha que usar gestos de pinça ou zoom para ler o conteúdo. [Saiba mais](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Otimizada para dispositivos móveis"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Cache TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Localização"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nome"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Solicitações"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tipo de recurso"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Tamanho"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tempo gasto"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Tamanho da transferência"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Possível economia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Possível economia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Possível economia de {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Possível economia de {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Documento"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Fonte"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imagem"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Mídia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Outro"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Folha de estilo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Terceiros"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Ocorreu um erro com a gravação dos rastros no carregamento de página. Execute o Lighthouse novamente. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Tempo limite atingido ao aguardar a conexão inicial do protocolo do depurador."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "O Chrome não coletou nenhuma captura de tela durante o carregamento de página. Verifique se há conteúdo visível na página e execute o Lighthouse novamente. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Os servidores DNS não resolveram o domínio fornecido."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "O coletor {artifactName} obrigatório encontrou um erro: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Ocorreu um erro interno do Chrome. Reinicie o Chrome e tente executar o Lighthouse novamente."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "O coletor {artifactName} obrigatório não foi executado."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "O Lighthouse não carregou de maneira confiável a página solicitada. Verifique se você está testando o URL correto e se o servidor está respondendo de forma adequada a todas as solicitações."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "O Lighthouse não carregou de maneira confiável o URL solicitado, porque a página parou de responder."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "O URL informado não tem um certificado de segurança válido. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "O Chrome impediu o carregamento da página com um intersticial. Verifique se você está testando o URL correto e se o servidor está respondendo de forma adequada a todas as solicitações."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "O Lighthouse não carregou de maneira confiável a página solicitada. Verifique se você está testando o URL correto e se o servidor está respondendo de forma adequada a todas as solicitações. (Detalhes: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "O Lighthouse não carregou de maneira confiável a página solicitada. Verifique se você está testando o URL correto e se o servidor está respondendo de forma adequada a todas as solicitações. (Código de status: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "A página demorou muito para ser carregada. Siga as oportunidades no relatório para diminuir o tempo de carregamento da página, depois execute o Lighthouse novamente. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "A espera pela resposta do protocolo DevTools excedeu o tempo limite. (Método: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "A busca de conteúdo de recursos excedeu o tempo limite"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "O URL informado parece ser inválido."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Mostrar auditorias"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navegação inicial"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latência máxima do caminho crítico:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Erro!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Informar erro: nenhuma informação de auditoria"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dados de laboratório"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Análise do [Lighthouse](https://developers.google.com/web/tools/lighthouse/) da página atual em uma rede móvel emulada. Os valores são estimados e podem variar."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Outros itens para verificação manual"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Não aplicável"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunidade"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Economia estimada"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditorias aprovadas"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Recolher snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Expandir snippet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Mostrar recursos de terceiros"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Alguns problemas afetaram esta execução do Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Os valores são estimados e podem variar. O índice de desempenho [se baseia somente nessas métricas](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Passou nas auditorias, mas como avisos"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Avisos: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Faça upload do seu GIF para um serviço que o disponibilizará para incorporação como um vídeo HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instale um [plug-in de carregamento lento do WordPress](https://wordpress.org/plugins/search/lazy+load/), que permite adiar imagens fora da tela, ou alterne para um tema que ofereça essa funcionalidade. Também recomendamos o uso do [plug-in de AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Existem vários plug-ins do WordPress que podem ajudar você a [aplicar inline a recursos essenciais](https://wordpress.org/plugins/search/critical+css/) ou [adiar recursos menos importantes](https://wordpress.org/plugins/search/defer+css+javascript/). As otimizações oferecidas por esses plug-ins podem corromper os recursos do tema ou dos seus plug-ins, então é provável que você precise fazer alterações no código."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Todas as especificações de servidor, temas e plug-ins contribuem para o tempo de resposta do servidor. Recomendamos que você use um tema mais otimizado, selecionando cuidadosamente um plug-in de otimização e/ou fazendo upgrade do seu servidor."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Recomendamos que você mostre trechos nas suas listas de postagem (por exemplo, por meio da tag \"mais\"), reduza o número de postagens exibidas em uma determinada página, divida suas postagens longas em várias páginas ou use um plug-in para aplicar lazy-load nos comentários."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Vários [plug-ins do WordPress](https://wordpress.org/plugins/search/minify+css/) podem acelerar seu site concatenando, reduzindo e compactando seus estilos. Você também pode usar um processo de compilação para fazer essa redução antecipadamente, se possível."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Vários [plug-ins do WordPress](https://wordpress.org/plugins/search/minify+javascript/) podem acelerar seu site concatenando, reduzindo e compactando seus scripts. Você também pode usar um processo de compilação para fazer essa redução antecipadamente, se possível."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Reduza ou troque o número de [plug-ins do WordPress](https://wordpress.org/plugins/) que carregam CSS não utilizado na sua página. Para identificar plug-ins que estão adicionando CSS externo, execute a [cobertura do código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) no Chrome DevTools. Você pode identificar o tema/plug-in responsável a partir do URL da folha de estilo. Procure plug-ins que tenham muitas folhas de estilo na lista, apresentando um nível alto de vermelho na cobertura do código. Um plug-in só deverá colocar uma folha de estilo na fila se ela for realmente utilizada na página."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Reduza ou troque o número de [plug-ins do WordPress](https://wordpress.org/plugins/) que carregam JavaScript não utilizado na sua página. Para identificar plug-ins que estão adicionando JS externo, execute a [cobertura do código](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) no Chrome DevTools. Você pode identificar o tema/plug-in responsável a partir do URL do script. Procure plug-ins que tenham muitos scripts na lista, apresentando um nível alto de vermelho na cobertura do código. Um plug-in só deverá colocar um script na fila se ele for realmente usado na página."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Leia sobre o [Processo de cache do navegador no WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Use um [plug-in do WordPress para otimização de imagens](https://wordpress.org/plugins/search/optimize+images/), que as compacta sem afetar a qualidade."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Faça upload de imagens diretamente por meio da [biblioteca de mídia](https://codex.wordpress.org/Media_Library_Screen) para garantir que os tamanhos de imagem necessários estejam disponíveis. Depois, insira-os na biblioteca de mídia ou use o widget de imagem para garantir que os tamanhos ideais sejam usados (incluindo aqueles para os pontos de interrupção responsivos). Evite usar imagens `Full Size`, a não ser que as dimensões sejam adequadas para uso. [Saiba mais](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Você pode ativar a compactação de texto na configuração do servidor da Web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Use um [plug-in](https://wordpress.org/plugins/search/convert+webp/) ou serviço que converta automaticamente as imagens enviadas nos formatos ideais."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ro.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ro.json
new file mode 100644
index 00000000000..6a9f08a926d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ro.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Tastele de acces permit utilizatorilor să focalizeze rapid o parte a paginii. Pentru o navigare corectă, fiecare tastă de acces trebuie să fie unică. [Află mai multe](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Valorile `[accesskey]` nu sunt unice"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Valorile `[accesskey]`sunt unice"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Fiecare `role` ARIA acceptă un anumit subset de atribute `aria-*`. Nepotrivirea acestora anulează atributele `aria-*`. [Află mai multe](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributele `[aria-*]` nu se potrivesc cu rolurile"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributele `[aria-*]` se potrivesc cu rolurile"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Unele roluri ARIA au atribute obligatorii care descriu starea elementului cititoarelor de ecrane. [Află mai multe](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` nu au toate atributele `[aria-*]` necesare"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` au toate atributele `[aria-*]` obligatorii"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Unele roluri ARIA principale trebuie să conțină roluri secundare specifice pentru a-și îndeplini funcțiile de accesibilitate pentru care au fost concepute. [Află mai multe](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Din elementele unui rol ARIA `[role]` care impun ca elementele secundare să conțină un anumit element `[role]` lipsește unul sau toate elementele secundare necesare respective."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementele unui rol ARIA `[role]` care impun ca elementele secundare să conțină un anumit element `[role]` includ toate elementele secundare necesare."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Unele roluri ARIA secundare trebuie să fie conținute de roluri principale specifice pentru a-și îndeplini corect funcțiile de accesibilitate pentru care au fost concepute. [Află mai multe](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` nu sunt conținute de elementul părinte impus"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` sunt conținute de elementul părinte impus"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Rolurile ARIA trebuie să aibă valori valide pentru a-și îndeplini funcțiile de accesibilitate pentru care au fost concepute. [Află mai multe](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Valorile `[role]` nu sunt valide"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Valorile `[role]` sunt valide"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Tehnologiile care asigură asistență, precum cititoarele de ecran, nu pot interpreta atributele ARIA cu valori nevalide. [Află mai multe](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atributele `[aria-*]` nu au valori valide"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atributele `[aria-*]` au valori valide"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Tehnologiile care oferă asistență, precum cititoarele de ecran, nu pot interpreta atributele ARIA cu nume nevalide. [Află mai multe](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributele `[aria-*]` sunt nevalide sau scrise greșit"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributele `[aria-*]` sunt valide și nu sunt scrise greșit"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Subtitrările fac ca elementele audio să poată fi folosite de utilizatorii surzi sau cu dizabilități de auz, furnizând informații esențiale, precum cine vorbește, ce spune și alte informații care nu sunt legate de vorbire. [Află mai multe](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementele `<audio>` au un element `<track>` cu `[kind=\"captions\"]` lipsă."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementele `<audio>` conțin un element `<track>` cu `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elemente cu probleme"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Când un buton nu are un nume accesibil, cititoarele de ecran îl anunță ca „buton”, făcându-l inutil pentru utilizatorii care se bazează pe cititoarele de ecran. [Află mai multe](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Butoanele nu au un nume accesibil"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Butoanele au un nume accesibil"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Dacă adaugi modalități de a ocoli conținutul repetitiv, utilizatorii tastaturii vor naviga pe pagină mai eficient. [Află mai multe](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Această pagină nu conține un titlu, un link de închidere sau o regiune de reper"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Pagina conține un titlu, un link de închidere sau o regiune de reper"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Textul cu un contrast redus este dificil sau imposibil de citit pentru mulți utilizatori. [Află mai multe](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Culorile din fundal și din prim-plan nu au un raport de contrast suficient."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Culorile din fundal și din prim-plan au un raport de contrast suficient"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Când listele de definiții nu sunt marcate corect, cititoarele de ecran pot produce un rezultat derutant sau inexact. [Află mai multe](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` nu conțin doar grupurile `<dt>` și `<dd>` ordonate corect, `<script>` sau elementele `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` conțin doar grupurile `<dt>` și `<dd>` ordonate corect, `<script>` sau elemente `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Elementele din lista de definiții (`<dt>` și `<dd>`) trebuie grupate într-un element principal `<dl>` pentru a se asigura că cititoarele de ecran le pot anunța corect. [Află mai multe](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Elementele din lista de definiții nu sunt incluse în elementele `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Elementele din lista de definiții sunt incluse în elementele `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Titlul le oferă utilizatorilor de cititoare de ecran o prezentare generală a paginii, iar utilizatorii de motoare de căutare îl folosesc intensiv pentru a stabili dacă o pagină este relevantă pentru căutarea lor. [Află mai multe](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Documentul nu are un element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Documentul are un element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Valoarea unui atribut ID trebuie să fie unică pentru a preveni omiterea altor instanțe de tehnologiile care asigură asistență. [Află mai multe](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atributele `[id]` de pe pagină nu sunt unice"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atributele `[id]` de pe pagină sunt unice"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Utilizatorii cititoarelor de ecran se bazează pe titlurile cadrelor pentru a descrie conținutul cadrelor. [Află mai multe](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementele `<frame>` sau `<iframe>` nu au un titlu"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementele `<frame>` sau `<iframe>` au un titlu"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Dacă o pagină nu specifică un atribut de limbă, cititorul de ecran presupune că pagina este în limba prestabilită pe care utilizatorul a ales-o când a configurat cititorul de ecran. Dacă pagina nu este în limba prestabilită, atunci cititorul de ecran este posibil să nu citească corect textul paginii. [Află mai multe](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Elementul `<html>` nu are un atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Elementul `<html>` are un atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Indicarea unei etichete de [limbă BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valide ajută cititoarele de ecran să anunțe corect textul. [Află mai multe](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Elementul `<html>` nu are o valoare validă pentru atributul `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Elementul `<html>` are o valoare validă pentru atributul `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Elementele informative ar trebui să conțină texte alternative descriptive scurte. Elementele decorative pot fi ignorate cu un atribut Alt gol. [Află mai multe](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elementele imaginii nu au atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elementele imagine au atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Când o imagine este folosită ca buton `<input>`, furnizarea unui text alternativ poate ajuta utilizatorii cititorului de ecran să înțeleagă scopul butonului. [Află mai multe](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementele `<input type=\"image\">` nu au text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementele `<input type=\"image\">` au text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etichetele asigură că opțiunile formularelor sunt anunțate corect de tehnologiile care asigură asistență, precum cititoarele de ecran. [Află mai multe](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Elementele formularului nu au etichete asociate"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Elementele formularului au etichete asociate"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Un tabel care este folosit pentru aspect nu ar trebui să includă elemente de date, precum elementele th sau de subtitrare sau atributul rezumat, deoarece poate crea confuzie pentru utilizatorii cititoarelor de ecran. [Află mai multe](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Elementele `<table>` de prezentare nu evită folosirea `<th>`, `<caption>` sau a atributului `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Elementele `<table>` de prezentare evită să folosească `<th>`, `<caption>` sau atributul `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Textul linkurilor (și textul alternativ pentru imagini, când sunt folosite ca linkuri) care se poate distinge, unic și pe care se poate focaliza, îmbunătățește navigarea pentru utilizatorii de cititoare de ecran. [Află mai multe](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Linkurile nu au un nume care se poate distinge"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Linkurile au un nume care se poate distinge"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Cititoarele de ecran au un anumit mod de anunțare a listelor. Asigurarea unei structuri corecte a listei îmbunătățește rezultatele cititorului de ecran. [Află mai multe](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listele nu conțin doar elemente `<li>` și elemente pe care se bazează scriptul (`<script>` și `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listele conțin doar elemente `<li>` și elemente pe care se bazează scriptul (`<script>` și `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Cititoarele de ecran necesită ca elementele din listă (`<li>`) să fie conținute într-un element principal `<ul>` sau `<ol>` pentru a fi anunțate corect. [Află mai multe](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Elementele din listă (`<li>`) nu sunt incluse în elementele principale `<ul>` sau `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Elementele din listă (`<li>`) sunt conținute în elementele principale `<ul>` sau `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Utilizatorii nu se așteaptă ca o pagină să se actualizeze automat, iar dacă ei actualizează, focalizarea se va muta din nou în partea de sus a paginii. Acest lucru poate crea frustrare sau confuzie. [Află mai multe](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Documentul folosește `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Documentul nu folosește `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Dezactivarea măririi sau micșorării este o problemă pentru utilizatorii cu vedere slabă, care se bazează pe mărirea ecranului pentru a vedea bine conținutul unei pagini web. [Află mai multe](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` este folosit în elementul `<meta name=\"viewport\">` sau atributul `[maximum-scale]` este mai mic decât 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` nu se folosește în elementul `<meta name=\"viewport\">` și atributul `[maximum-scale]` nu este mai mic decât 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Cititoarele de ecran nu pot traduce conținut în alt format decât text. Adăugarea de text alternativ la elementele `<object>` ajută cititoarele de ecran să le transmită utilizatorilor înțelesul. [Află mai multe](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementele `<object>` nu au text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementele `<object>` au text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "O valoare mai mare decât 0 implică o ordine explicită de navigare. Deși valid din punct de vedere tehnic, acest lucru creează adesea frustrări utilizatorilor care se bazează pe tehnologii care oferă asistență. [Află mai multe](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Unele elemente au o valoare `[tabindex]` mai mare decât 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Niciun element nu are o valoare `[tabindex]` mai mare decât 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Cititoarele de ecran au funcții care facilitează navigarea în tabele. Dacă se asigură că celulele `<td>` care folosesc atributul `[headers]` se referă doar la alte celule din același tabel, se poate îmbunătăți experiența pentru utilizatorii de cititoare de ecran. [Află mai multe](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Celulele dintr-un element `<table>` care folosesc atributul `[headers]` se referă la un element `id` care nu se găsește în același tabel."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Celulele dintr-un element `<table>` care folosesc atributul `[headers]` se referă la celule ale aceluiași tabel."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Cititoarele de ecran au funcții care facilitează navigarea în tabele. Dacă se asigură că antetele tabelelor se referă întotdeauna la unele seturi de celule, se poate îmbunătăți experiența pentru utilizatorii de cititoare de ecran. [Află mai multe](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementele `<th>` și elementele cu `[role=\"columnheader\"/\"rowheader\"]` nu au celule de date pe care să le descrie."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementele `<th>` și elementele cu `[role=\"columnheader\"/\"rowheader\"]` au celule de date pe care le descriu."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Indicarea unei etichete de [limbă BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) valide la elemente ajută la pronunțarea corectă a textului de un cititor de ecran. [Află mai multe](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atributele `[lang]` nu au o valoare validă"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributele `[lang]` au o valoare validă"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Când un videoclip are subtitrare, este mai simplu pentru utilizatorii surzi și cu dizabilități de auz să îi acceseze informațiile. [Află mai multe](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementele `<video>` nu conțin un element `<track>` cu `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementele `<video>` conțin un element `<track>` cu `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Descrierile audio oferă informații relevante pentru videoclipuri pe care dialogul nu le poate oferi, precum scene și expresii faciale. [Află mai multe](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementele `<video>` nu conțin un element `<track>` cu `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementele `<video>` conțin un element `<track>` cu `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Pentru un aspect ideal în iOS atunci când utilizatorii adaugă o aplicație web progresivă în ecranul de pornire, definește o `apple-touch-icon`. Aceasta trebuie să indice spre un PNG pătrat netransparent, de 192 px (sau 180 px). [Află mai multe](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Nu oferă o `apple-touch-icon` validă"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` este învechit; se preferă `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Oferă o `apple-touch-icon` validă"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Extensiile Chrome au afectat performanța de încărcare a acestei pagini. Încearcă să auditezi pagina în modul incognito sau dintr-un profil Chrome fără extensii."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Evaluarea scripturilor"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analizarea scripturilor"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Timp CPU total"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Poți reduce timpul petrecut cu analizarea, compilarea și executarea JS. Livrarea unor sarcini JS mai mici poate ajuta în acest sens. [Află mai multe](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Redu timpul de execuție JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Timpul de executare JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "GIF-urile mari nu sunt eficiente pentru difuzarea conținutului animat. Folosește videoclipuri MPEG4/WebM pentru animații și PNG/WebP pentru imagini statice în locul GIF-urilor ca să economisești date în rețea. [Află mai multe](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Folosește formate video pentru conținut animat"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Poți încărca lent imaginile ascunse sau pe cele din afara ecranului după ce toate resursele esențiale s-au încărcat, pentru a micșora timpul până la interactivitate. [Află mai multe](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Amână imaginile din afara ecranului"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resursele blochează prima redare a paginii. Poți să livrezi conținutul JS/CSS esențial inline și să amâni toate elementele JS/stilurile neesențiale. [Află mai multe](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Elimină resursele care blochează redarea"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Sarcinile mari de rețea îi costă pe utilizatori și sunt corelate cu timpi de încărcare îndelungați. [Află mai multe](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Dimensiunea totală a fost de {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Evită sarcinile uriașe de rețea"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Evită sarcinile uriașe de rețea"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Comprimarea fișierelor CSS poate reduce dimensiunea sarcinilor de rețea. [Află mai multe](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Comprimă codul CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Comprimarea fișierelor JavaScript poate reduce dimensiunea sarcinilor și timpul de analizare a scripturilor. [Află mai multe](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Comprimă codul JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Elimină regulile nefolosite din foile de stil și amână încărcarea conținutului CSS nefolosit pentru conținutul din partea superioară a paginii ca să reduci numărul de byți consumați de activitatea în rețea. [Află mai multe](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Elimină conținutul CSS nefolosit"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Elimină codul JavaScript nefolosit pentru a reduce byții consumați de activitatea rețelei."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Elimină codul JavaScript nefolosit"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "O durată lungă a memoriei cache poate grăbi accesările repetate ale paginii. [Află mai multe](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{o resursă găsită}few{# resurse găsite}other{# de resurse găsite}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Difuzează elementele statice cu o politică eficientă de stocare în memoria cache"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Folosește o politică eficientă de stocare în memoria cache pentru elementele statice"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Imaginile optimizate se încarcă mai repede și consumă mai puține date mobile. [Află mai multe](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Codifică eficient imaginile"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Difuzează imagini de dimensiuni corespunzătoare ca să economisești date mobile și să obții o încărcare mai rapidă. [Află mai multe](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Dimensionează corect imaginile"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Resursele bazate pe text trebuie comprimate (gzip, deflate sau brotli) pentru a minimiza numărul total de byți în rețea. [Află mai multe](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Activează comprimarea textului"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formatele de imagine ca JPEG 2000, JPEG XR și WebP oferă adesea o comprimare mai bună decât PNG sau JPEG, ceea ce înseamnă descărcări mai rapide și mai puțin consum de date. [Află mai multe](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Difuzează imagini în formate moderne"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Dacă lățimea conținutului aplicației nu se potrivește cu lățimea ariei vizibile, este posibil ca aplicația să nu fie optimizată pentru ecrane mobile. [Află mai multe](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Aria vizibilă de {innerWidth} px nu corespunde cu dimensiunea ferestrei, de {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Conținutul nu este dimensionat corect pentru aria vizibilă"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Conținutul este dimensionat corect pentru aria vizibilă"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Lanțurile de solicitări esențiale de mai jos îți arată ce resurse sunt încărcate cu prioritate ridicată. Poți să reduci lungimea lanțurilor, să reduci dimensiunea de descărcare a resurselor sau să amâni descărcarea de resurse inutile pentru a îmbunătăți încărcarea paginilor. [Află mai multe](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{un lanț găsit}few{# lanțuri găsite}other{# de lanțuri găsite}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Redu profunzimea solicitărilor esențiale"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Renunțare la dezvoltare/Avertisment"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Rând"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "API-urile învechite vor fi eliminate, în final, din browser. [Află mai multe](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{A fost identificat un avertisment}few{Au fost identificate # avertismente}other{Au fost identificate # de avertismente}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Folosește API-uri învechite"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Evită API-urile învechite"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Memoria cache a aplicației este învechită. [Află mai multe](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Am găsit „{AppCacheManifest}”"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Folosește memoria cache de aplicație"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Evită memoria cache a aplicației"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Specificarea unui doctype împiedică browserul să treacă la modul caracteristici speciale. [Află mai multe](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Numele doctype trebuie să fie șirul cu litere mici `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Documentul trebuie să conțină un doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Se aștepta ca publicId să fie un șir gol"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Se aștepta ca systemId să fie un șir gol"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Pagina nu are doctype HTML, așadar declanșează modul caracteristici speciale"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Pagina are doctype HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistică"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Valoare"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Specialiștii în browsere recomandă ca paginile să conțină mai puțin de ~1.500 de elemente DOM. Ideal este ca arborele să aibă o profunzime mai mică de 32 de elemente și mai puțin de 60 de elemente principale/subordonate. Un DOM mare poate crește folosirea memoriei, poate produce [calcule de stil](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) mai lungi și [rearanjări ale aspectului](https://developers.google.com/speed/articles/reflow) costisitoare. [Află mai multe](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}few{# elemente}other{# de elemente}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Evită o dimensiune DOM excesivă"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Adâncimea DOM maximă"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Numărul total de elemente DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Numărul maxim de elemente subordonate"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Evită o dimensiune DOM excesivă"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Obiectiv"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Adaugă `rel=\"noopener\"` sau `rel=\"noreferrer\"` la orice linkuri externe pentru a îmbunătăți rezultatele și a preveni vulnerabilitățile de securitate. [Află mai multe](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Linkurile spre destinații cu mai multe origini sunt nesigure"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Linkurile spre destinații cu mai multe origini sunt sigure"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nu se poate determina destinația pentru ancora ({anchorHTML}). Dacă nu se folosește ca hyperlink, elimină target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Utilizatorii nu au încredere sau sunt derutați de site-urile care le solicită locația fără context. Asociază solicitarea cu o acțiune a utilizatorilor. [Află mai multe](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Solicită permisiunea de localizare geografică la încărcarea paginii"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Evită solicitarea permisiunii de localizare geografică la încărcarea paginii"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Versiune"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Toate bibliotecile JavaScript front-end detectate în pagină. [Află mai multe](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Biblioteci JavaScript detectate"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Pentru utilizatorii cu conexiuni lente, scripturile externe injectate dinamic prin `document.write()` pot întârzia încărcarea paginilor cu zeci de secunde. [Află mai multe](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Utilizări `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Evită `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Cea mai mare severitate"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Versiunea bibliotecii"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Numărul de vulnerabilități"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Unele scripturi terță parte pot conține vulnerabilități de securitate cunoscute, ușor de identificat și de exploatat de atacatori. [Află mai multe](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{O vulnerabilitate detectată}few{# vulnerabilități detectate}other{# de vulnerabilități detectate}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Include bibliotecile JavaScript front-end cu vulnerabilități de securitate cunoscute"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Înaltă"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Redusă"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Medie"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Evită bibliotecile JavaScript front-end cu vulnerabilități de securitate cunoscute"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Utilizatorii nu au încredere sau sunt derutați de site-urile care solicită să trimită notificări fără context. Asociază solicitarea cu gesturile utilizatorilor. [Află mai multe](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Solicită permisiunea de notificare la încărcarea paginii"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Evită solicitarea permisiunii de notificare la încărcarea paginii"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elemente cu probleme"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Împiedicarea inserării parolelor subminează buna politică de securitate. [Află mai multe](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Împiedică utilizatorii să insereze în câmpurile pentru parole"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Permite-le utilizatorilor să insereze în câmpurile pentru parole"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protocol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 oferă multe beneficii față de HTTP/1.1, inclusiv antete binare, anunțuri multiplex și tehnologie push pentru server. [Află mai multe](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{O solicitare nu a fost difuzată prin HTTP/2}few{# solicitări nu au fost difuzate prin HTTP/2}other{# de solicitări nu au fost difuzate prin HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nu folosește HTTP/2 pentru toate resursele"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Folosește HTTP/2 pentru propriile sale resurse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Poți marca funcțiile de procesare a evenimentelor prin atingere sau derulare `passive` pentru a îmbunătăți capacitatea de derulare a paginii. [Află mai multe](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nu folosește ascultători pasivi pentru a îmbunătăți performanța la derulare"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Folosește ascultători pasivi pentru a îmbunătăți performanța la derulare"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Descriere"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Erorile înregistrate pe consolă indică probleme nerezolvate Acestea pot fi provocate de erorile de solicitare din rețea și de alte probleme ale browserului. [Află mai multe](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "S-au înregistrat erori de browser pe consolă"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nu s-a înregistrat nicio eroare de browser pe consolă"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Poți folosi funcția CSS de afișare a fonturilor pentru a verifica dacă textul este vizibil pentru utilizatori în timp ce se încarcă fonturile web. [Află mai multe](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Asigură-te că textul rămâne vizibil în timpul încărcării fonturilor web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Tot textul rămâne vizibil în timpul încărcării fonturilor web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse nu a putut verifica automat valoarea de afișare a fonturilor pentru următoarea adresă URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Raport de dimensiuni (real)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Raport de dimensiuni (afișat)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Dimensiunile de afișare a imaginilor trebuie să se potrivească raportului natural de dimensiuni. [Află mai multe](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Afișează imaginile cu rapoarte de dimensiuni incorecte"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Afișează imaginile cu rapoarte de dimensiuni corecte"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Informații nevalide privind dimensiunea imaginilor {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Browserele le pot solicita utilizatorilor să adauge aplicația pe ecranele de pornire, lucru care poate duce la o implicare mai mare. [Află mai multe](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifestul aplicației web nu îndeplinește cerințele de instalare"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifestul aplicației web îndeplinește cerințele de instalare"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Adresă URL nesigură"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Toate site-urile trebuie protejate cu HTTPS, chiar și cele care nu gestionează date sensibile. HTTPS împiedică persoanele străine să modifice sau să asculte pasiv comunicațiile dintre aplicația ta și utilizatori, fiind o cerință obligatorie pentru HTTP/2 și multe API-uri noi pentru platformele web. [Află mai multe](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{S-a găsit o solicitare nesigură}few{S-au găsit # solicitări nesigure}other{S-au găsit # de solicitări nesigure}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nu folosește HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Folosește HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "O încărcare rapidă a paginii într-o rețea celulară asigură o experiență bună a utilizatorului pe mobil. [Află mai multe](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interactiv la {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interactivă pe rețeaua mobilă simulată la {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Pagina se încarcă prea lent și nu este interactivă în 10 secunde. Analizează oportunitățile și diagnosticele din secțiunea „Performanță” ca să afli cum s-o îmbunătățești."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Încărcarea paginii nu este suficient de rapidă în rețele mobile"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Încărcarea paginii este suficient de rapidă în rețele mobile"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Categorie"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Poți reduce timpul petrecut cu analizarea, compilarea și executarea JS. Livrarea unor sarcini JS mai mici poate ajuta în acest sens. [Află mai multe](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimizează procesarea firului principal"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimizează procesarea firului principal"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Ca să se adreseze cât mai multor utilizatori, site-urile trebuie să funcționeze în toate browserele importante. [Află mai multe](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Site-ul funcționează pe orice browser"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Asigură-te că se pot crea linkuri directe către pagini individuale prin adresa URL și că adresele URL sunt unice, pentru a putea fi trimise în rețelele sociale. [Află mai multe](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Fiecare pagină are o adresă URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Tranzițiile trebuie să aibă loc repede atunci când atingi ecranul, chiar și în rețele lente. Această experiență este esențială pentru performanța percepută de utilizator. [Află mai multe](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Tranzițiile de pagini nu par să blocheze rețeaua"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Latența estimată a comenzilor reprezintă o estimare a duratei necesare pentru ca aplicația să răspundă la comanda utilizatorului, în milisecunde, în cea mai aglomerată fereastră de cinci secunde de încărcare a paginii. Dacă latența este mai mare de 50 ms, utilizatorii îți pot percepe aplicația ca fiind lentă. [Află mai multe](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Latența estimată a comenzilor"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Prima redare de conținut arată momentul când se redă primul text sau prima imagine. [Află mai multe](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Prima redare de conținut"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Primul „CPU inactiv” semnalează primul moment în care firul principal al paginii este suficient de liber pentru a accepta comenzi. [Află mai multe](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Primul „CPU inactiv”"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Prima redare semnificativă arată momentul când este vizibil conținutul principal al unei pagini. [Află mai multe](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Prima redare semnificativă"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Timpul până la interactivitate este timpul necesar pentru ca pagina să devină complet interactivă. [Află mai multe](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Timpul până la interactivitate"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Timpul maxim potențial de la prima interacțiune cu care utilizatorii se pot confrunta este durata, în milisecunde, a celei mai lungi activități. [Află mai multe](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Timpul maxim potențial de la prima interacțiune"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indexul de viteză arată cât de repede se completează vizibil conținutul unei pagini. [Află mai multe](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Index de viteză"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Suma tuturor perioadelor de timp dintre FCP și Timpul până la interactivitate, când lungimea activității a depășit 50 ms, exprimate în milisecunde."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Durata totală de blocare"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Durata pingului în rețea (RTT) are impact important asupra performanței. Dacă RTT către o origine este mare, înseamnă că serverele mai apropiate de utilizator pot îmbunătăți performanța. [Află mai multe](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Durata pingului în rețea"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Latențele serverului pot influența rezultatele pe web. Dacă latența serverului unei origini este mare, înseamnă că serverul este supraîncărcat sau are performanțe slabe în backend. [Află mai multe](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latențe ale backendului serverului"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Un service worker permite ca aplicația să fie fiabilă în condiții de rețea imprevizibile. [Află mai multe](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` nu răspunde cu codul de stare 200 când este offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` răspunde cu codul de stare 200 când este offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse nu a putut citi `start_url` din manifest. Prin urmare, s-a presupus că `start_url` este adresa URL a documentului. Mesaj de eroare: „{manifestWarning}”."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Peste buget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Păstrează cantitatea și dimensiunea solicitărilor din rețea sub obiectivele stabilite de bugetul de performanță solicitat. [Află mai multe](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{O solicitare}few{# solicitări}other{# de solicitări}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Buget de performanță"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Dacă ai configurat deja HTTPS, redirecționează tot traficul HTTP spre HTTPS, ca să activezi funcțiile web sigure pentru toți utilizatorii. [Află mai multe](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nu redirecționează traficul HTTP spre HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Redirecționează traficul HTTP spre HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Redirecționările introduc întârzieri suplimentare înainte ca pagina să se poată încărca. [Află mai multe](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Evită mai multe redirecționări ale paginii"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Ca să setezi bugetele pentru cantitatea și dimensiunea resurselor de pagină, adaugă un fișier budget.json. [Află mai multe](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{O solicitare • {byteCount, number, bytes} KB}few{# solicitări • {byteCount, number, bytes} KB}other{# de solicitări • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Păstrează numărul de solicitări scăzut și dimensiunea transferurilor redusă"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Linkurile canonice sugerează care adresă URL să se afișeze în rezultatele căutării. [Află mai multe](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Mai multe adrese URL incompatibile ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Indică spre alt domeniu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Adresă URL nevalidă ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Indică spre altă locație `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Adresa URL relativă ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Direcționează către adresa URL a rădăcinii domeniului (pagina principală), nu către o pagină de conținut echivalentă"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Documentul nu are un `rel=canonical` valid"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Documentul are un `rel=canonical` valid"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Dimensiunile fontului mai mici de 12 pixeli sunt prea mici pentru a putea fi citite, iar utilizatorii de dispozitive mobile trebuie să „ciupească pentru zoom” pentru a citi. Încearcă să ai peste 60 % din textul paginii cu font ≥12 px. [Află mai multe](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "Text lizibil {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Textul nu este lizibil deoarece nu există nicio metaetichetă viewport optimizată pentru ecranele dispozitivelor mobile."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} din text este prea mic (pornind de la un eșantion de {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Documentul nu folosește dimensiuni de fonturi lizibile"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Documentul folosește dimensiuni de font lizibile"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Linkurile hreflang spun motoarelor de căutare ce versiune a unei pagini să înregistreze în rezultatele căutării pentru o limbă sau regiune dată. [Află mai multe](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Document nu are un `hreflang` valid"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Documentul are un `hreflang` valid"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Este posibil ca paginile cu Coduri de stare HTTP nefuncționale să nu fie indexate corect. [Află mai multe](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Pagina are Cod de stare HTTP nefuncțional"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Pagina are Cod de stare HTTP funcțional"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Motoarele de căutare nu pot include paginile în rezultatele căutării dacă nu au permisiunea de a le accesa cu crawlere. [Află mai multe](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Indexarea este blocată pentru pagină"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indexarea nu este blocată pentru pagină"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Textul descriptiv al linkului ajută motoarele de căutare să înțeleagă conținutul. [Află mai multe](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{S-a găsit un link}few{S-au găsit # linkuri}other{S-au găsit # de linkuri}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linkurile nu au text descriptiv"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linkurile au text descriptiv"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Rulează [Instrumentul de testare pentru date structurate](https://search.google.com/structured-data/testing-tool/) și [Structured Data Linter](http://linter.structured-data.org/) pentru a valida datele structurate. [Află mai multe](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Datele structurate sunt valide"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metadescrierile pot fi incluse în rezultatele căutării pentru a rezuma conținutul paginii. [Află mai multe](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Textul de descriere nu este completat."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Documentul nu are o metadescriere"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Documentul are o metadescriere"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Motoarele de căutare nu pot indexa conținutul pluginurilor și multe dispozitive restricționează pluginurile sau nu le acceptă. [Află mai multe](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Documentul folosește pluginuri"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Documentul evită pluginurile"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Dacă fișierul robots.txt este deteriorat, este posibil ca aplicațiile crawler să nu poată înțelege cum vrei să fie site-ul tău accesat cu crawlere sau indexat. [Află mai multe](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Cererea pentru robots.txt a returnat starea HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{A fost identificată o eroare}few{Au fost identificate # erori}other{Au fost identificate # de erori}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse nu a putut să descarce un fișier robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Fișierul robots.txt nu este valid"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Fișierul robots.txt este valid"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Elementele interactive, precum butoanele și linkurile, trebuie să fie suficient de mari (48x48 px) și să aibă suficient spațiu în jurul lor, pentru a fi ușor de atins, fără a se suprapune peste alte elemente. [Află mai multe](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} direcționări ale atingerilor au mărimea corectă"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Direcționările atingerilor sunt prea mici, deoarece nu există o metaetichetă Viewport optimizată pentru ecranele dispozitivelor mobile"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Direcționările atingerilor nu sunt dimensionate corect"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Direcționarea se suprapune"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Direcționarea atingerii"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Direcționările atingerilor sunt dimensionate corect"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service worker este tehnologia care îi permite aplicației să folosească mai multe funcții de aplicații web progresive, cum ar fi cele offline, adăugarea în ecranul de pornire și notificările push. [Află mai multe](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Pagina este controlată de un service worker, dar nu s-a găsit niciun `start_url`, deoarece manifestul nu s-a putut analiza ca un JSON valid"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Pagina este controlată de un service worker, dar `start_url` ({startUrl}) nu este în aria de acoperire a acestuia ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Pagina este controlată de un service worker, dar nu s-a găsit un `start_url`, deoarece nu s-a preluat niciun manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Această origine are unul sau mai multe elemente service worker, însă pagina ({pageUrl}) nu este în aria de acoperire."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Nu înregistrează un service worker care să controleze pagina și `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Înregistrează un service worker care să controleze pagina și `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Un ecran de întâmpinare tematic asigură o experiență de calitate atunci când utilizatorii lansează aplicația din ecranele de pornire. [Află mai multe](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nu este configurat pentru un ecran de întâmpinare personalizat"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Configurat pentru un ecran de întâmpinare personalizat"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Bara de adrese din browser poate avea o temă ce corespunde cu site-ul tău. [Află mai multe](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nu setează o culoare tematică pentru bara de adrese."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Setează o culoare tematică pentru bara de adrese."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Timpul de blocare a firului principal"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Terță parte"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Codul terță parte poate influența semnificativ performanța de încărcare. Limitează numărul de furnizori terță parte redundanți și încearcă să încarce cod terță parte după ce pagina a terminat încărcarea de bază. [Află mai multe](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Codul terță parte a blocat firul principal pentru {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Redu impactul codului de la terți"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Utilizarea terță parte"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Timpul până la primul byte identifică timpul în care serverul trimite un răspuns. [Află mai multe](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Documentul rădăcină a avut nevoie de {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Redu timpii de răspuns ai serverului (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Serverul răspunde repede (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Durată"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Ora de începere"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tip"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Îți poți îmbunătăți aplicația cu API-ul User Timing ca să măsori performanța reală a acesteia în timpul experiențelor de utilizare principale. [Află mai multe](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{o durată a utilizării}few{# durate ale utilizărilor}other{# de durate ale utilizărilor}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Mărci și dimensiuni pentru Duratele utilizărilor"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Un <link> preconectat a fost găsit pentru „{securityOrigin}”, dar nu a fost folosit de browser. Verifică dacă folosești corect atributul `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Adaugă indicii de resurse `preconnect` sau `dns-prefetch` pentru a crea conexiunile inițiale la originile terță parte importante. [Află mai multe](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Preconectează la originile necesare"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Un <link> preîncărcat a fost găsit pentru „{preloadURL}”, dar nu a fost folosit de browser. Verifică dacă folosești corect atributul `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Poți folosi `<link rel=preload>` ca să acorzi prioritate preluării resurselor care sunt momentan solicitate mai târziu la încărcarea paginii. [Află mai multe](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Preîncarcă solicitările importante"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Adaugă o etichetă `<meta name=\"viewport\">` ca să-ți optimizezi aplicația pentru ecranele mobile. [Află mai multe](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nu s-a găsit nicio etichetă `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nu are o etichetă `<meta name=\"viewport\">` cu `width` sau `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Are o etichetă `<meta name=\"viewport\">` cu `width` sau `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Aplicația ta trebuie să afișeze o parte de conținut când JavaScript este dezactivat, chiar dacă este doar o atenționare pentru utilizator că JavaScript este obligatoriu pentru a folosi aplicația. [Află mai multe](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Corpul paginii trebuie să redea o parte de conținut dacă scripturile sale nu sunt disponibile."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Nu oferă conținut alternativ când JavaScript nu este disponibil"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Include o parte de conținut când JavaScript nu este disponibil"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Dacă creezi o aplicație web progresivă, poți folosi un service worker pentru ca aplicația să poată funcționa offline. [Află mai multe](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Pagina curentă nu răspunde cu codul de stare 200 când este offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Pagina curentă răspunde cu codul de stare 200 când este offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Este posibil ca pagina să nu se încarce offline, deoarece adresa URL de testare ({requested}) a fost redirecționată spre „{final}”. Încearcă să testezi direct a doua adresă URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Acestea sunt oportunități de a îmbunătăți utilizarea ARIA în aplicație, lucru care poate îmbunătăți experiența pentru utilizatorii tehnologiei care asigură asistență, precum un cititor de ecran."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Acestea sunt oportunități de a oferi conținut secundar audio și video. Astfel se poate îmbunătăți experiența utilizatorilor cu deficiențe de auz sau de vedere."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Audio și video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Aceste elemente evidențiază cele mai bune practici privind accesibilitatea."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Cele mai bune practici"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Aceste verificări evidențiază oportunitățile pentru a [îmbunătăți accesibilitatea aplicației web](https://developers.google.com/web/fundamentals/accessibility). Doar un subset de probleme de accesibilitate pot fi detectate automat, astfel încât se recomandă și testarea manuală."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Aceste elemente se adresează zonelor pe care un instrument de testare automată nu le poate acoperi. Află mai multe din ghidul nostru despre [realizarea unei evaluări a accesibilității](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Accesibilitate"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Acestea sunt oportunități de a-ți îmbunătăți lizibilitatea conținutului."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Contrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Acestea sunt oportunități de a îmbunătăți interpretarea conținutului tău de utilizatori, în diferite coduri locale."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internaționalizare și localizare"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Acestea sunt oportunități de a îmbunătăți semantica opțiunilor de control din aplicația ta. Astfel se poate îmbunătăți experiența utilizatorilor de tehnologii care asigură asistență, precum un cititor de ecran."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nume și etichete"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Acestea sunt oportunități de a îmbunătăți navigarea pe tastatură în aplicația ta."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigare"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Acestea sunt oportunități de a îmbunătăți experiența citirii datelor din tabele sau din liste folosind tehnologia care asigură asistență, cum ar fi un cititor de ecran."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabele și liste"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Cele mai bune practici"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Bugetele de performanță stabilesc standarde pentru performanța site-ului."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Bugete"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Mai multe informații despre performanța aplicației tale. Numerele nu [influențează direct](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) Scorul de performanță."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnosticare"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Cel mai important aspect al performanței este cât de repede se redau pixelii pe ecran. Valori cheie: prima redare de conținut, prima redare semnificativă"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Îmbunătățirile pentru prima redare"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Aceste sugestii îți pot face pagina să se încarce mai repede. Ele nu [influențează direct](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) scorul de performanță."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Oportunități"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Valori"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Îmbunătățește experiența globală de încărcare, astfel ca pagina să se afișeze și să fie gata de utilizare cât mai curând posibil. Valori cheie: timpul până la interactivitate, indexul de viteză"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Îmbunătățiri generale"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performanță"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Aceste verificări validează aspectele unei aplicații web progresive. [Află mai multe](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Aceste verificări sunt impuse de [Lista de verificare PWA](https://developers.google.com/web/progressive-web-apps/checklist) de referință, dar nu sunt verificate automat de Lighthouse. Ele nu-ți afectează scorul, dar e important să fie făcute manual."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Aplicație web progresivă"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rapid și sigur"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Poate fi instalat"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizat pentru PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Aceste verificări asigură că pagina este optimizată pentru poziționarea în rezultatele motorului de căutare. Există alți factori pe care Lighthouse nu îi verifică și care pot afecta poziția în rezultatele căutării. [Află mai multe](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Rulează acești validatori suplimentari pe site pentru a căuta alte recomandări SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatează codul HTML în așa fel încât crawlerele să înțeleagă mai bine conținutul aplicației."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Cele mai bune practici privind conținutul"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Pentru a apărea în rezultatele căutării, crawlerele trebuie să îți acceseze aplicația."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Accesarea cu crawlere și indexarea"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Asigură-te că paginile sunt create pentru dispozitivele mobile, pentru ca utilizatorii să nu trebuiască să ciupească sau să mărească pentru a citi paginile conținutului. [Află mai multe](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Pentru dispozitivele mobile"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL cache"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Locație"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Nume"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Solicitări"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tip de resursă"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Dimensiune"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Timp petrecut"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Dimensiunea transferului"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "Adresa URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Economii potențiale"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Economii potențiale"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Poți economisi {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Poți economisi {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Document"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Imagine"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Altele"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Script"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Foaie de stil"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Terță parte"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Total"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "A apărut o eroare la înregistrarea urmei de la încărcarea paginii. Rulează din nou Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Timpul a expirat așteptând conexiunea inițială la protocolul Debugger."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome nu a colectat capturi de ecran în timpul încărcării paginii. Asigură-te că există conținut vizibil în pagină și încearcă să rulezi din nou Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Serverele DNS nu au putut rezolva domeniul furnizat."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Colectorul de {artifactName} obligatorii a întâmpinat o eroare: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "A apărut o eroare Chrome internă. Repornește Chrome și încearcă să rulezi din nou Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Colectorul {artifactName} obligatoriu nu a rulat."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse nu a putut încărca în mod sigur pagina solicitată. Asigură-te că testezi adresa URL corectă și că serverul răspunde corect la toate solicitările."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse nu a putut încărca în mod sigur adresa URL solicitată, deoarece pagina nu mai răspunde."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Adresa URL furnizată nu are un certificat de securitate valid. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome a împiedicat încărcarea paginii cu un interstițial. Asigură-te că testezi adresa URL corectă și că serverul răspunde corect la toate solicitările."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse nu a putut încărca în mod sigur pagina solicitată. Asigură-te că testezi adresa URL corectă și că serverul răspunde corect la toate solicitările. (Detalii: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse nu a putut încărca în mod sigur pagina solicitată. Asigură-te că testezi adresa URL corectă și că serverul răspunde corect la toate solicitările. (Cod de stare: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Încărcarea paginii a durat prea mult. Urmează recomandările din raport pentru a reduce durata de încărcare a paginii, apoi încearcă din nou să rulezi Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Așteptarea răspunsului la protocolul DevTools a depășit timpul alocat. (Metoda: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Preluarea conținutului resursei a depășit timpul alocat"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Adresa URL furnizată pare să fie nevalidă."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Afișează audituri"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Navigare inițială"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Latența maximă a căii critice:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Eroare!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Eroare de raport: nu există informații de auditare"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Datele testului"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analiza în [Lighthouse](https://developers.google.com/web/tools/lighthouse/) a paginii actuale cu o rețea mobilă simulată. Valorile sunt estimate și pot varia."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Elemente suplimentare de verificat manual"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nu se aplică"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Oportunitate"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Economii estimate"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Auditări trecute"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Restrânge fragmentul"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Extinde fragmentul"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Afișează resursele terță parte"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Au apărut probleme care au afectat această rulare Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Valorile sunt estimate și pot varia. Scorul de performanță [se bazează doar pe aceste valori](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Auditări trecute, dar cu avertismente"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Avertismente: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Îți recomandăm să încarci GIF-ul într-un serviciu care îl va pune dispoziție pentru încorporare ca videoclip HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instalează un [plugin WordPress de încărcare lentă](https://wordpress.org/plugins/search/lazy+load/) care oferă capacitatea de a amâna imaginile din afara ecranului sau schimbă-ți tema cu una care oferă acea funcție. Îți recomandăm [pluginul AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Există o serie de pluginuri Wordpress care te pot ajuta să [activezi inline elementele critice](https://wordpress.org/plugins/search/critical+css/) sau să [amâni resurse mai puțin importante](https://wordpress.org/plugins/search/defer+css+javascript/). Atenție, optimizările oferite de aceste pluginuri pot să întrerupă funcțiile temei sau pluginurilor tale, astfel încât este posibil să trebuiască să modifici codul."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Temele, pluginurile și specificațiile serverului contribuie toate la timpul de răspuns al serverului. Îți recomandăm să găsești o temă mai optimizată, selectând cu atenție un plugin de optimizare și/sau făcând upgrade la server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Îți recomandăm să afișezi extrase în listele postărilor tale (de exemplu, prin intermediul filei Mai multe), reducând numărul de postări afișate pe o anumită pagină, împărțind postările lungi pe mai multe pagini sau folosind un plugin pentru a încărca lent comentariile."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Mai multe [pluginuri WordPress](https://wordpress.org/plugins/search/minify+css/) îți pot accelera site-ul prin concatenarea, minimizarea și comprimarea stilurilor. Ai putea să folosești și un proces de design pentru a face minimizarea în avans, dacă este posibil."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Mai multe [pluginuri WordPress](https://wordpress.org/plugins/search/minify+javascript/) îți pot accelera site-ul prin concatenarea, minimizarea și comprimarea scripturilor. Ai putea să folosești și un proces de design pentru a face minimizarea în avans, dacă este posibil."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Îți recomandăm să reduci sau să schimbi numărul de [pluginuri WordPress](https://wordpress.org/plugins/) care încarcă CSS nefolosit în pagină. Ca să identifici pluginurile care adaugă conținut CSS neesențial, încearcă să rulezi [acoperirea codului](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) în Chrome DevTools. Poți identifica tema/pluginul responsabil din adresa URL a foii de stil. Caută pluginuri care au multe foi de stil în listă cu mult roșu în bara acoperirii codului. Un plugin ar trebui să pună în coadă o foaie de stil numai dacă este într-adevăr folosită în pagină."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Îți recomandăm să reduci sau să schimbi numărul de [pluginuri WordPress](https://wordpress.org/plugins/) care încarcă JavaScript nefolosit în pagină. Ca să identifici pluginurile care adaugă conținut JS neesențial, încearcă să rulezi [acoperirea codului](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) în Chrome DevTools. Poți identifica tema/pluginul responsabil din adresa URL a scriptului. Caută pluginuri care au multe scripturi în listă cu mult roșu în bara acoperirii codului. Un plugin ar trebui să pună în coadă un script numai dacă este într-adevăr folosit în pagină."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Citește despre [stocarea în memoria cache a browserului în WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Îți recomandăm să folosești un [plugin WordPress de optimizare a imaginii](https://wordpress.org/plugins/search/optimize+images/) care comprimă imaginile, păstrând calitatea."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Încarcă imaginile direct prin [biblioteca de media](https://codex.wordpress.org/Media_Library_Screen) pentru a te asigura că sunt disponibile dimensiunile de imagine necesare, apoi inserează-le din biblioteca de media sau folosește widgetul de imagine pentru a te asigura că se folosesc dimensiunile de imagine optime (inclusiv cele pentru punctele de întrerupere adaptabile). Evită să folosești imagini `Full Size`, cu excepția cazului în care dimensiunile sunt adecvate pentru utilizare. [Află mai multe](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Poți activa comprimarea textului în configurarea serverului web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Îți recomandăm să folosești un [plugin](https://wordpress.org/plugins/search/convert+webp/) sau un serviciu care convertește automat imaginile încărcate în formatele optime."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ru.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ru.json
new file mode 100644
index 00000000000..f7081cf5d38
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ru.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Ключи доступа позволяют быстро перейти к нужной части страницы. Каждый из них должен быть уникальным. [Подробнее…](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Значения атрибута `[accesskey]` не уникальны"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]`: значения уникальны"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Каждая `role` ARIA поддерживает определенный набор атрибутов `aria-*`. Неверно присвоенные атрибуты `aria-*` будут недействительны. [Подробнее…](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Атрибуты `[aria-*]` не соответствуют своим ролям"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Атрибуты `[aria-*]` соответствуют своим ролям"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "К некоторым ролям ARIA требуется добавить атрибуты, описывающие состояние элемента для программ чтения с экрана. [Подробнее…](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Для элементов с атрибутом `[role]` заданы не все необходимые атрибуты `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "У элементов `[role]` есть все необходимые атрибуты `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Некоторые родительские элементы с ролями ARIA должны содержать определенные дочерние роли, иначе связанные с ними функции специальных возможностей будут работать неправильно. [Подробнее…](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "В элементах с ролью ARIA `[role]` отсутствуют некоторые или все обязательные дочерние элементы, которые должны содержать определенный элемент `[role]`."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "В элементах с ролью ARIA `[role]` присутствуют все обязательные дочерние элементы, которые должны содержать определенный элемент `[role]`."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Некоторые дочерние элементы с ролями ARIA должны содержаться внутри определенных родительских элементов, иначе связанные с ними функции специальных возможностей будут работать неправильно. [Подробнее…](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Элементы с атрибутом `[role]` не содержатся в своих родительских элементах"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Элементы с атрибутом `[role]` содержатся в своих родительских элементах"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Значения ролей ARIA должны быть действительными, иначе связанные с ними функции будут работать неправильно. [Подробнее…](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Присутствуют недействительные значения атрибутов `[role]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Недействительные значения атрибутов `[role]` отсутствуют"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Программы чтения с экрана не могут распознавать атрибуты ARIA с недействительными значениями. [Подробнее…](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "У атрибутов `[aria-*]` недействительные значения"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Недействительные значения атрибутов `[aria-*]` отсутствуют"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Программы чтения с экрана не могут интерпретировать атрибуты ARIA с недействительными названиями. [Подробнее…](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Атрибуты `[aria-*]` недействительны или указаны с ошибками"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Атрибуты `[aria-*]` действительны и написаны без ошибок"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Чтобы ваш аудиоконтент был доступен людям с нарушениями слуха, добавьте субтитры. В них можно включить описания сцен, у которых нет звукового сопровождения. [Подробнее…](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Элементы `<audio>` не содержат элемент `<track>` с атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Элементы `<audio>` содержат элемент `<track>` с атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Элементы, не прошедшие проверку"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Если у кнопки нет названия, доступного программам чтения с экрана, пользователи услышат слово \"кнопка\", но не поймут, для чего она нужна. [Подробнее…](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Названия кнопок недоступны программам чтения с экрана"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Названия кнопок доступны программам чтения с экрана"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Чтобы пользователям было проще перемещаться по странице с помощью клавиатуры, добавьте возможность пропускать повторяющийся контент. [Подробнее…](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "На странице отсутствует заголовок, ссылка для пропуска или указание региона"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Страница содержит заголовок, ссылку для пропуска контента или указание региона"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Многие пользователи не могут разобрать или не видят текст с низкой контрастностью. [Подробнее…](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Цвета фона и переднего плана недостаточно контрастны"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Цвета фона и переднего плана достаточно контрастны"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Если в структуре списков определений есть ошибки, программы чтения с экрана могут неправильно их озвучивать. [Подробнее…](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Элементы `<dt>`, `<dd>`, `<script>` и `<template>` расположены внутри элементов `<dl>` в неправильном порядке"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Элементы `<dt>`, `<dd>`, `<script>` и `<template>` расположены внутри элементов `<dl>` в нужном порядке"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Чтобы программы чтения с экрана правильно озвучивали элементы списков определений `<dt>` и `<dd>`, они должны располагаться внутри родительского элемента `<dl>`. [Подробнее…](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Элементы списков определений не расположены внутри элементов `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Элементы списков определений расположены внутри элементов `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Элемент title нужен для того, чтобы программы чтения с экрана могли озвучивать название страницы. Также он появляется в результатах поиска и позволяет определять, соответствует ли сайт запросу. [Подробнее…](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "В документе нет элемента `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Документ содержит элемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Значение атрибута id должно быть уникальным, так как программы для людей с ограниченными возможностями могут игнорировать повторяющиеся идентификаторы. [Подробнее…](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Атрибуты `[id]` не уникальны на этой странице"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Атрибуты `[id]` уникальны на этой странице"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Чтобы программы чтения с экрана могли описывать содержимое фреймов, для каждого из них должен быть указан атрибут title. [Подробнее…](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Для элементов `<frame>` или `<iframe>` не указан атрибут title"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "У элементов `<frame>` и `<iframe>` есть атрибут title"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Если для страницы не указан атрибут lang, программа чтения с экрана предполагает, что текст приведен на языке по умолчанию, выбранном пользователем при установке программы. Если текст написан на другом языке, он может озвучиваться некорректно. [Подробнее…](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Для элемента `<html>` не задан атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Элемент `<html>` содержит атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Чтобы программы чтения с экрана правильно озвучивали текст, укажите действительный [языковой тег BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question). [Подробнее…](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "В элементе `<html>` нет действительного значения для атрибута `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Для элемента `<html>` указано действительное значение атрибута `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "В информационных элементах должен содержаться короткий и ясный альтернативный текст. Если элемент декоративный, то атрибут alt для него можно оставить пустым. [Подробнее…](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Для элементов изображений не заданы атрибуты `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "У элементов изображений есть атрибут `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Если в элементе `<input>` в качестве кнопки используется изображение, добавьте альтернативный текст, описывающий назначение этой кнопки для программ чтения с экрана. [Подробнее…](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Атрибут `[alt]` задан не для всех элементов `<input type=\"image\">`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Элементы `<input type=\"image\">` содержат атрибут `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Ярлыки нужны для того, чтобы программы чтения с экрана могли правильно озвучивать элементы управления формой. [Подробнее…](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Элементам формы не присвоены соответствующие ярлыки"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Элементам формы присвоены соответствующие ярлыки"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "В таблице, используемой в качестве основы дизайна веб-страницы, не должны содержаться элементы данных, например th, caption или атрибут summary, так как они могут создать трудности для тех, кто использует программы чтения с экрана. [Подробнее…](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "В элементах `<table>` с атрибутом role=\"presentation\" используются элементы `<th>` и `<caption>` или атрибут `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "В элементах `<table>` с атрибутом role=\"presentation\" не используются элементы `<th>` и `<caption>` или атрибут `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Текст ссылок (как и альтернативный текст для изображений, используемых в качестве ссылок) должен быть уникальным, фокусируемым и доступным для программ чтения с экрана. [Подробнее…](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Текст ссылок неразличим для программ чтения с экрана"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Текст ссылок различим для программ чтения с экрана"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Используйте правильную структуру кода при верстке списков, иначе программы чтения с экрана будут неправильно их озвучивать. [Подробнее…](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "В списках содержатся другие элементы, помимо элементов `<li>` и элементов поддержки скрипта (`<script>` и `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "В списках содержатся только элементы `<li>` и элементы поддержки скрипта (`<script>` и `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Чтобы программы чтения с экрана правильно озвучивали списки, элементы `<li>` должны располагаться внутри родительских элементов `<ul>` или `<ol>`. [Подробнее…](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Элементы списка `<li>` не содержатся в родительских элементах `<ul>` или `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Элементы списка `<li>` расположены внутри родительских элементов `<ul>` или `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Когда страница обновляется автоматически, фокус, используемый программами для чтения с экрана, перемещается в верхнюю часть. Это может раздражать пользователей и мешать их работе. [Подробнее…](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "В документе используется метатег `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "В документе не используется метатег `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Не отключайте масштабирование: эта функция помогает слабовидящим пользователям читать информацию на веб-страницах. [Подробнее…](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Атрибут `[user-scalable=\"no\"]` используется в элементе `<meta name=\"viewport\">` или значение атрибута `[maximum-scale]` меньше 5"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Атрибут `[user-scalable=\"no\"]` не используется в элементе `<meta name=\"viewport\">`, и значение атрибута `[maximum-scale]` больше или равно 5"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Чтобы программы чтения с экрана могли озвучивать содержимое элементов `<object>`, добавьте к ним атрибут alt. [Подробнее…](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Атрибут `[alt]` задан не для всех элементов `<object>`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Элементы `<object>` содержат атрибут `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Значение больше 0 подразумевает определенный порядок навигации. Это может создавать трудности для пользователей с ограниченными возможностями. [Подробнее…](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Для некоторых элементов значение `[tabindex]` больше 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Нет элементов со значением атрибута `[tabindex]` выше 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Чтобы пользователям было проще перемещаться по таблицам с помощью программ чтения с экрана, убедитесь, что ячейки в элементах `<td>` с атрибутом `[headers]` ссылаются только на другие ячейки в той же таблице. [Подробнее…](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Ячейки внутри элемента `<table>`, в которых используется атрибут `[headers]`, ссылаются на элемент `id`, не найденный внутри той же таблицы."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Ячейки внутри элемента `<table>`, в которых используется атрибут `[headers]`, ссылаются на ячейки той же таблицы."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Чтобы пользователям было проще перемещаться по таблицам с помощью программ чтения с экрана, убедитесь, что все заголовки в таблицах ссылаются на определенный набор ячеек. [Подробнее…](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "В элементах `<th>` и элементах с атрибутом `[role=\"columnheader\"/\"rowheader\"]` нет описываемых ими ячеек с данными"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "В элементах `<th>` и элементах с атрибутом `[role=\"columnheader\"/\"rowheader\"]` есть описываемые ими ячейки с данными"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Чтобы программы чтения с экрана правильно озвучивали текст, укажите для элементов корректный [языковой тег BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question). [Подробнее…](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Присутствуют недействительные значения атрибутов `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Недействительные значения атрибутов `[lang]` отсутствуют"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Чтобы информация, озвучиваемая в видео, была доступна людям с нарушениями слуха, добавьте субтитры. [Подробнее…](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Элементы `<video>` не содержат элемент `<track>` с атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Элементы `<video>` содержат элемент `<track>` с атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Благодаря звуковым описаниям к видео слабовидящие пользователи могут узнавать, что происходит на экране в сценах без аудиосопровождения. [Подробнее…](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Элементы `<video>` не содержат элемент `<track>` с атрибутом `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Элементы `<video>` содержат элемент `<track>` с атрибутом `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Чтобы современное веб-приложение лучше смотрелось на главном экране iOS, задайте значение для атрибута `apple-touch-icon`. Он должен указывать на непрозрачное квадратное PNG-изображение со стороной 192 или 180 пикселей. [Подробнее…](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Не содержит действительный атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Атрибут `apple-touch-icon-precomposed` устарел. Используйте атрибут `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Содержит действительный атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Расширения Chrome замедляют загрузку этой страницы. Попробуйте использовать режим инкогнито или профиль Chrome без расширений."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Время оценки скриптов"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Время анализа скриптов"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Общее процессорное время"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Рекомендуем сократить время на анализ, компиляцию и выполнение скриптов JS. Для этого вы можете уменьшить размер фрагментов кода JS. [Подробнее…](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Сократите время выполнения кода JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Время выполнения кода JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Анимированный контент неэффективно загружать в виде больших GIF-файлов. Чтобы сэкономить сетевой трафик, используйте формат видео MPEG4/WebM для анимированного контента и формат изображений PNG/WebP – для статического. [Подробнее…](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Используйте видеоформаты для анимированного контента"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Чтобы уменьшить время загрузки для взаимодействия, рекомендуем настроить отложенную загрузку скрытых изображений. Тогда основные ресурсы сайта будут загружаться в первую очередь. [Подробнее…](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Отложите загрузку скрытых изображений"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Некоторые ресурсы блокируют первую отрисовку страницы. Рекомендуем встроить критическую часть данных JS/CSS в код HTML и отложить загрузку остальных ресурсов. [Подробнее…](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Устраните ресурсы, блокирующие отображение"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Чрезмерная нагрузка на сеть стоит пользователям реальных денег и может стать причиной долгого ожидания при работе в Интернете. [Подробнее…](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Общий размер достиг {totalBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Предотвратите чрезмерную нагрузку на сеть"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Предотвращение чрезмерной нагрузки на сеть"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Уменьшив файлы CSS, вы можете сократить объем полезной сетевой нагрузки. [Подробнее…](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Уменьшите размер кода CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Уменьшив файлы JavaScript, вы можете сократить объем полезной нагрузки и время анализа скриптов. [Подробнее…](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Уменьшите размер кода JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Чтобы сократить расход трафика, удалите ненужные правила из таблиц стилей и отложите загрузку кода CSS, который не используется в верхней части страницы. [Подробнее…](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Удалите неиспользуемый код CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Чтобы сократить расход трафика, удалите неиспользуемый код JavaScript."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Удалите неиспользуемый код JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Благодаря долгому времени хранения кеша страница может быстрее загружаться при повторных посещениях. [Подробнее…](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Найден 1 ресурс}one{Найден # ресурс}few{Найдено # ресурса}many{Найдено # ресурсов}other{Найдено # ресурса}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Задайте правила эффективного использования кеша для статических объектов"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Настройка правил эффективного использования кеша для статических объектов"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Оптимизированные изображения загружаются быстрее и меньше расходуют мобильный трафик. [Подробнее…](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Настройте эффективную кодировку изображений"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Чтобы сэкономить мобильный трафик и ускорить загрузку страницы, следите за тем, чтобы размеры ваших изображений соответствовали требованиям. [Подробнее…](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Настройте подходящий размер изображений"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Чтобы уменьшить расход сетевого трафика, рекомендуем сжимать текстовые ресурсы (gzip, deflate или brotli). [Подробнее…](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Включите сжатие текста"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Форматы JPEG 2000, JPEG XR и WebP обеспечивают более эффективное сжатие по сравнению с PNG или JPEG, поэтому такие изображения загружаются быстрее и потребляют меньше трафика. [Подробнее…](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Используйте современные форматы изображений"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Приложение не оптимизировано для работы на экранах мобильных устройств, если ширина контента приложения не совпадает с шириной области просмотра. [Подробнее…](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Область просмотра ({innerWidth} пикселей) не совпадает с размером окна ({outerWidth} пикселей)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Размер контента не соответствует области просмотра"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Размер контента соответствует области просмотра"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Приведенные ниже цепочки критических запросов показывают, какие ресурсы загружаются с высоким приоритетом. Чтобы ускорить загрузку страниц, рекомендуем сократить длину цепочек, уменьшить размер скачиваемых ресурсов или отложить скачивание ненужных ресурсов. [Подробнее…](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Найдена 1 цепочка}one{Найдена # цепочка}few{Найдено # цепочки}many{Найдено # цепочек}other{Найдено # цепочки}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Сократите глубину вложенности критических запросов"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Прекращение поддержки / предупреждение"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Строка"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Рано или поздно устаревшие API будут удалены из браузера. [Подробнее…](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Обнаружено 1 предупреждение}one{Обнаружено # предупреждение}few{Обнаружено # предупреждения}many{Обнаружено # предупреждений}other{Обнаружено # предупреждения}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "На странице используются устаревшие API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Устаревшие API не используются"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache больше не поддерживается. [Подробнее…](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Обнаружен манифест {AppCacheManifest}"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Используется Application Cache"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Application Cache не используется"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Если для страницы указан параметр DOCTYPE, браузер не будет переключаться в режим совместимости. [Подробнее…](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "В качестве названия элемента DOCTYPE нужно указать `html` строчными буквами."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Необходимо добавить элемент DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Поле publicId содержит данные"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Поле systemId содержит данные"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Активирован режим совместимости, так как на странице отсутствует элемент DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Тип страницы (DOCTYPE): HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Элемент"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Статистический показатель"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Значение"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Разработчики браузеров рекомендуют размещать на странице не более 1500 элементов DOM. Оптимальные показатели: глубина дерева – менее 32 элементов, количество дочерних и родительских элементов – менее 60. Сложная структура DOM может привести к использованию большего объема памяти, замедлить [вычисление стилей](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) и увеличить затраты на [компоновку шаблонов](https://developers.google.com/speed/articles/reflow). [Подробнее…](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 элемент}one{# элемент}few{# элемента}many{# элементов}other{# элемента}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Сократите размер структуры DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Максимальная глубина вложенности DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Общее количество элементов DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Максимальное число дочерних элементов"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Сокращение размера структуры DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Атрибут target"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Добавьте атрибут `rel=\"noopener\"` или `rel=\"noreferrer\"` ко всем внешним ссылкам, чтобы повысить производительность и избежать уязвимостей в защите. [Подробнее…](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Ссылки на сторонние ресурсы небезопасны"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Ссылки на сторонние ресурсы безопасны"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Не удалось определить целевой якорь ({anchorHTML}). Если элемент не используется в качестве гиперссылки, попробуйте удалить атрибут target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Пользователи с подозрением относятся к сайтам, которые беспричинно запрашивают доступ к их местоположению. Мы рекомендуем связать этот запрос с определенными действиями пользователя. [Подробнее…](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Разрешение на определение местоположения запрашивается при загрузке страницы"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Разрешение на определение местоположения не запрашивается при загрузке страницы"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Версия"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Все клиентские библиотеки JavaScript, обнаруженные на странице. [Подробнее…](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Обнаруженные библиотеки JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Использование метода `document.write()` для динамической подгрузки внешних скриптов может значительно замедлять загрузку страницы для пользователей с низкой скоростью подключения. [Подробнее…](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Используется метод `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Метод `document.write()` не используется"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Максимальная степень опасности"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Версия библиотеки"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Количество уязвимостей"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Некоторые сторонние скрипты содержат известные уязвимости, которые легко могут быть обнаружены и использованы злоумышленниками. [Подробнее…](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Обнаружена 1 уязвимость}one{Обнаружена # уязвимость}few{Обнаружено # уязвимости}many{Обнаружено # уязвимостей}other{Обнаружено # уязвимости}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Содержит клиентские библиотеки JavaScript с известными уязвимостями"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Высокая"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Низкая"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Средняя"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Не содержит клиентские библиотеки JavaScript с известными уязвимостями"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Пользователи с подозрением относятся к сайтам, которые беспричинно запрашивают разрешение на отправку уведомлений. Мы рекомендуем связать этот запрос с определенными жестами пользователя. [Подробнее…](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Разрешение на отправку уведомлений запрашивается при загрузке страницы"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Разрешение на отправку уведомлений не запрашивается при загрузке страницы"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Элементы, запрещающие вставку из буфера обмена"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Запрет на вставку пароля из буфера обмена отрицательно сказывается на безопасности пользователей. [Подробнее…](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Вставка пароля из буфера обмена запрещена"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Вставка пароля из буфера обмена разрешена"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Протокол"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Протокол HTTP/2 отличается от HTTP/1.1 массой преимуществ, включая бинарность, мультиплексирование запросов, а также возможность отправки данных по инициативе сервера. [Подробнее…](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 запрос не передан через HTTP/2}one{# запрос не передан через HTTP/2}few{# запроса не передано через HTTP/2}many{# запросов не передано через HTTP/2}other{# запроса не передано через HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Не использует протокол HTTP/2 для всех ресурсов"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Протокол HTTP/2 используется для собственных ресурсов"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Чтобы повысить производительность при прокрутке страницы, используйте флаг `passive` для прослушивателей событий прикосновения и колеса мыши. [Подробнее…](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Пассивные прослушиватели событий не используются для улучшения производительности при прокрутке"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Пассивные прослушиватели событий используются для улучшения производительности при прокрутке"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Описание"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Ошибки, записанные в журнале консоли, указывают на нерешенные проблемы. Это могут быть невыполненные сетевые запросы и другие сбои в работе браузера. [Подробнее…](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Ошибки браузера занесены в журнал консоли"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "В журнале консоли нет ошибок браузера"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Используйте свойство CSS font-display, чтобы пользователи могли видеть текст во время загрузки веб-шрифтов. [Подробнее…](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Настройте показ всего текста во время загрузки веб-шрифтов"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Показ всего текста во время загрузки веб-шрифтов"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Сервису Lighthouse не удалось автоматически проверить значение font-display для следующего URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Соотношение сторон (фактическое)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Соотношение сторон (отображаемое)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Размеры отображаемого изображения должны соответствовать нормальному соотношению сторон. [Подробнее…](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Присутствуют изображения с некорректным соотношением сторон"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Отсутствуют изображения с некорректным соотношением сторон"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Недействительные данные о размере изображения {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Для увеличения частоты использования браузеры могут предлагать пользователям добавлять приложение на главный экран. [Подробнее…](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Манифест веб-приложения не соответствует условиям, необходимым для установки"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Манифест веб-приложения соответствует условиям, необходимым для установки"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Небезопасный URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Все сайты (даже если они не обрабатывают конфиденциальные данные) должны быть защищены протоколом HTTPS. Он обеспечивает защиту от взлома и не позволяет посторонним узнавать, как пользователи взаимодействуют с приложением. Кроме того, использование этого протокола обязательно при работе с версией HTTP/2 и многими новыми API для веб-платформ. [Подробнее…](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Обнаружен 1 небезопасный запрос}one{Обнаружен # небезопасный запрос}few{Обнаружено # небезопасных запроса}many{Обнаружено # небезопасных запросов}other{Обнаружено # небезопасного запроса}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Протокол HTTPS не используется"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Используется протокол HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Если страницы будут быстро загружаться по мобильной сети, сайтом станет удобно пользоваться на телефоне или планшете. [Подробнее…](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Станица интерактивна через {timeInMs, number, seconds} сек."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Страница интерактивна в эмулированной мобильной сети через {timeInMs, number, seconds} сек."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Ваша страница загружается слишком долго и неактивна в течение первых 10 секунд. Для улучшения ее работы изучите возможности оптимизации и диагностические данные в разделе \"Производительность\"."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Страницы загружаются через мобильную сеть недостаточно быстро"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Страницы загружаются через мобильную сеть достаточно быстро"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Категория"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Рекомендуем сократить время на анализ, компиляцию и выполнение скриптов JS. Для этого вы можете уменьшить размер фрагментов кода JS. [Подробнее…](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Минимизируйте работу в основном потоке"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Минимизация работы в основном потоке"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Для максимального охвата аудитории сайт должен поддерживать все основные браузеры. [Подробнее…](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Сайт работает в разных браузерах"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Убедитесь, что у каждой страницы есть уникальный URL, чтобы их было удобно распространять в социальных сетях. [Подробнее…](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "У каждой страницы есть URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Переходы должны создавать впечатление мгновенного отклика даже при медленной работе сети. Это имеет решающее значение для удобства работы с приложением. [Подробнее…](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Во время перехода между страницами нет ощущения, что они ожидают ответа от сети"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Примерное время задержки при вводе показывает время в миллисекундах, через которое приложение реагирует на действия пользователя в течение самых активных 5 секунд загрузки страницы. Если это время превышает 50 мс, пользователям может показаться, что ваше приложение работает слишком медленно. [Подробнее…](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Приблизительное время задержки при вводе"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Первая отрисовка контента – показатель, который определяет интервал времени между началом загрузки страницы и появлением первого изображения или блока текста. [Подробнее…](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Время загрузки первого контента"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Время окончания работы ЦП – время, когда на странице становится возможна обработка пользовательского ввода. [Подробнее…](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Время окончания работы ЦП"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Первая значимая отрисовка – показатель, определяющий интервал времени между началом загрузки страницы и появлением основного контента. [Подробнее…](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Время загрузки достаточной части контента"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Время загрузки для взаимодействия – это время, в течение которого страница становится полностью готова к взаимодействию с пользователем. [Подробнее…](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Время загрузки для взаимодействия"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Максимальная потенциальная задержка после первого ввода показывает время выполнения самой длительной задачи в миллисекундах. [Подробнее…](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Макс. потенц. задержка после первого ввода"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Индекс скорости загрузки показывает, как быстро на странице появляется контент. [Подробнее…](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Индекс скорости загрузки"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Общее время в миллисекундах между первой отрисовкой контента и временем загрузки для взаимодействия, когда скорость выполнения задач превышала 50 мс"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Общее время блокировки"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Время прохождения сигнала сети (RTT) напрямую влияет на производительность сайта. Высокое время прохождения сигнала означает, что серверы расположены слишком далеко от пользователя и сайт будет работать медленнее. [Подробнее…](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Время прохождения сигнала сети"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Задержки со стороны сервера могут влиять на скорость загрузки страниц. Высокое время реакции сервера говорит о его перегруженности или недостаточной производительности. [Подробнее…](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Задержка со стороны сервера"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker обеспечивает надежную работу веб-приложения при нестабильных условиях работы сети. [Подробнее…](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` не отправляет код 200 в офлайн-режиме"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` отправляет код 200 в офлайн-режиме"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse не удалось прочитать `start_url` в файле манифеста. По этой причине в качестве URL документа была выбрана ссылка `start_url`. Сообщение об ошибке: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Сверх бюджета"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Следите за тем, чтобы количество и размер сетевых запросов соответствовали целям, установленным в бюджете производительности. [Подробнее…](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 запрос}one{# запрос}few{# запроса}many{# запросов}other{# запроса}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Бюджет производительности"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Если у вас уже настроен протокол HTTPS, убедитесь, что весь трафик перенаправляется с HTTP на HTTPS, чтобы обеспечить безопасность для всех своих пользователей. [Подробнее…](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Не перенаправляет трафик с HTTP на HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Перенаправляет трафик с HTTP на HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Переадресации могут стать причиной дополнительных задержек при загрузке страницы. [Подробнее…](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Избегайте большого количества переадресаций"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Чтобы установить бюджет для количества и размера ресурсов на странице, добавьте файл budget.json. [Подробнее…](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 запрос • {byteCount, number, bytes} КБ}one{# запрос • {byteCount, number, bytes} КБ}few{# запроса • {byteCount, number, bytes} КБ}many{# запросов • {byteCount, number, bytes} КБ}other{# запроса • {byteCount, number, bytes} КБ}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Постарайтесь уменьшить количество запросов и размеры передаваемых данных"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Ссылки с атрибутом rel=\"canonical\" будут показаны в результатах поиска. [Подробнее…](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Несколько конфликтующих URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Указывает на другой домен ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Недопустимый URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Указывает на другое расположение атрибута `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Относительный URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Каноническая ссылка ведет на корневой URL домена, а не на соответствующую страницу с контентом."
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "В документе нет действительного атрибута `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Для документа указан действительный атрибут `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Если вы хотите, чтобы текст легко читался, размер шрифта должен составлять не менее 12 пикс. В противном случае пользователям мобильных устройств придется масштабировать страницу для чтения. В идеале на странице должно быть более 60 % текста высотой не менее 12 пикс. [Подробнее…](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} текста можно легко прочитать"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Слишком мелкий текст. Настройте область просмотра для экранов мобильных устройств с помощью метатега viewport."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} текста набрано слишком мелким шрифтом (на основе образца размером {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "В документе используются шрифты слишком маленького размера"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "В документе используются шрифты оптимального размера"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Добавьте на страницу элементы link с атрибутом hreflang. Тогда в результатах поиска будут представлены те версии ваших страниц, которые лучше всего подходят для языка и региона пользователя. [Подробнее…](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "В документе нет действительного атрибута `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Для документа указан действительный атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Индексация страниц с недействительным кодом статуса HTTP может быть нарушена. [Подробнее…](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Код статуса HTTP недействителен"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Код статуса HTTP действителен"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Поисковые системы не смогут включать ваши страницы в результаты поиска, если вы не предоставите разрешение на сканирование. [Подробнее…](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Страница недоступна для индексации"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Страница доступна для индексации"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Добавьте к ссылкам текстовые описания, чтобы поисковые системы лучше распознавали ваш контент. [Подробнее…](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Найдена 1 ссылка}one{Найдена # ссылка}few{Найдено # ссылки}many{Найдено # ссылок}other{Найдено # ссылки}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "У ссылок нет описаний"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "У ссылок есть описания"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Для тестирования структурированных данных воспользуйтесь [инструментом проверки](https://search.google.com/structured-data/testing-tool/) и [инструментом Structured Data Linter](http://linter.structured-data.org/). [Подробнее…](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Структурированные данные действительны"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Метаописания содержат общие сведения о контенте страницы и могут быть показаны в результатах поиска. [Подробнее…](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Отсутствует описание."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "В документе нет метаописания"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "В документе есть метаописание"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Поисковые системы не могут индексировать содержимое плагинов. К тому же на многих устройствах использование плагинов ограничено или не поддерживается. [Подробнее…](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "В документе используются плагины"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "В документе нет плагинов"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Если файл robots.txt поврежден, поисковые роботы могут не распознать ваши инструкции по сканированию или индексации сайта. [Подробнее…](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Код статуса HTTP, полученный в ответ на запрос файла robots.txt: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Обнаружена 1 ошибка}one{Обнаружена # ошибка}few{Обнаружено # ошибки}many{Обнаружено # ошибок}other{Обнаружено # ошибки}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Не удалось скачать файл robots.txt."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Файл robots.txt недействителен"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Файл robots.txt действителен"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Интерактивные элементы, такие как кнопки и ссылки, должны быть достаточно крупными (48 x 48 пикс.) и располагаться на достаточном расстоянии друг от друга. Тогда пользователям будет удобно нажимать на них. [Подробнее…](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Размеры {decimalProportion, number, percent} интерактивных элементов соответствуют требованиям."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Слишком маленькие интерактивные элементы. Настройте область просмотра для экранов мобильных устройств с помощью метатега viewport."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Размер интерактивных элементов не оптимален"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Частичное совпадение элементов"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Интерактивный элемент"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Размер интерактивных элементов оптимален"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker — это технология, добавляющая в приложение преимущества современных веб-приложений, такие как поддержка офлайн-режима, добавления на главный экран и push-уведомлений. [Подробнее…](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Страницей управляет Service Worker, но не найден `start_url`, так как не удалось интерпретировать манифест как JSON."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Страницей управляет Service Worker, но `start_url` ({startUrl}) находится вне его области действия ({scopeUrl})."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Страницей управляет Service Worker, но не удалось найти `start_url`, так как не был получен манифест."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "В этом источнике несколько Service Worker, но страница {pageUrl} не входит в их область действия."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Не регистрируется Service Worker, управляющий страницей и `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Регистрируется Service Worker, управляющий страницей и `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Приложение оставляет у пользователей более приятное впечатление, когда оно встречает их качественной заставкой. [Подробнее…](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Собственная заставка не настроена"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Настроена собственная заставка"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Цвет адресной строки браузера можно изменить под цвет сайта. [Подробнее…](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Не изменяет цвет адресной строки в соответствии с темой"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Изменяет цвет адресной строки в соответствии с темой"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Время блокировки основного потока"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Сторонний поставщик"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Сторонний код может сильно замедлить загрузку страниц сайта. Рекомендуем использовать только самые необходимые сторонние ресурсы и сделать так, чтобы они загружались в последнюю очередь. [Подробнее…](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Сторонний код заблокировал основной поток на {timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Уменьшите влияние стороннего кода"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Сторонний код"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Время до первого байта – показатель, который определяет интервал времени между отправкой запроса и ответом вашего сервера. [Подробнее…](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Загрузка корневого документа заняла {timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Сократите время ответа сервера (время до получения первого байта)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Короткое время ответа сервера (время до получения первого байта)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Длительность"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Время начала"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Тип"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Используйте User Timing API, чтобы измерить реальную производительность своего приложения во время ключевых моментов взаимодействия с пользователями. [Подробнее…](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 временная метка}one{# временная метка}few{# временные метки}many{# временных меток}other{# временной метки}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Метки и промежутки пользовательского времени"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Для страницы {securityOrigin} найден элемент <link> с атрибутом rel=\"preconnect\", но он не использовался браузером. Проверьте значение атрибута `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Чтобы быстро устанавливать соединение с необходимыми сторонними источниками, добавьте ресурсную подсказку `preconnect` или `dns-prefetch`. [Подробнее…](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Используйте предварительное подключение к необходимым доменам"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Для страницы {preloadURL} найден элемент <link> с атрибутом rel=\"preload\", но он не использовался браузером. Проверьте значение атрибута `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Чтобы основные ресурсы загружались в первую очередь, используйте для них элемент `<link rel=preload>`. [Подробнее…](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Настройте предварительную загрузку ключевых запросов"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Добавьте метатег `<meta name=\"viewport\">`, чтобы оптимизировать приложение для экранов мобильных устройств. [Подробнее…](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Метатег `<meta name=\"viewport\">` не найден."
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Отсутствует метатег `<meta name=\"viewport\">` со свойством `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Присутствует метатег `<meta name=\"viewport\">` со свойством `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "В приложении должен отображаться контент, даже если JavaScript отключен. Достаточно уведомления, что для работы приложения необходим JavaScript. [Подробнее…](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Даже при недоступности скриптов в теле страницы должен отображаться контент."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Не предоставляет резервный контент при недоступности JavaScript"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Содержит некоторый контент при недоступности JavaScript"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "При создании современного веб-приложения используйте Service Worker, чтобы оно продолжало работу в офлайн-режиме. [Подробнее…](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Текущая страница не отправляет код 200 в офлайн-режиме"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Текущая страница отправляет код 200 в офлайн-режиме"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Эта страница может не загружаться в офлайн-режиме, потому что тестовый URL ({requested}) перенаправляет на {final}. Попробуйте напрямую испытать второй URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Проверьте, правильно ли заданы атрибуты ARIA. Они облегчают работу с вашим приложением пользователям с ограниченными возможностями."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Проверьте, доступны ли на вашем сайте описания для аудио- и видеоконтента. Это сделает сайт удобнее для пользователей с нарушениями зрения и слуха."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Аудио и видео"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Проверьте, соответствует ли ваш сайт рекомендациям по оптимизации для поисковых систем."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Рекомендации"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Узнайте, какие трудности могут возникнуть у людей с ограниченными возможностями при использовании вашего веб-приложения, и [сделайте его доступнее](https://developers.google.com/web/fundamentals/accessibility). Тестирование вручную поможет выявить проблемы доступности, которые не были обнаружены автоматически."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ручная проверка позволяет охватить области, которые невозможно протестировать автоматически. Подробнее [о проверке специальных возможностей](https://developers.google.com/web/fundamentals/accessibility/how-to-review)…"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Специальные возможности"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Проверьте, хорошо ли виден ваш текст."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Контрастность"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Проверьте, правильно ли заданы атрибуты языков для программ чтения с экрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Интернационализация и локализация"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Проверьте, насколько элементы управления в вашем приложении различимы для программ чтения с экрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Названия и ярлыки"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Проверьте, удобно ли пользователям перемещаться по вашему приложению с помощью клавиатуры."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Навигация"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Проверьте, насколько эффективно программы чтения с экрана распознают данные в таблицах и списках на вашем сайте."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Таблицы и списки"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Рекомендации"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "В бюджете производительности устанавливаются нормы для производительности вашего сайта."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Бюджет"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Подробная информация о производительности вашего приложения. Эти цифры не влияют на показатель производительности [напрямую](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Диагностика"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Один из самых важных параметров производительности – насколько быстро пиксели отображаются на экране. Ключевые показатели: \"Время загрузки первого контента\" и \"Время загрузки достаточной части контента\"."
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Уменьшение времени загрузки контента"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Эти рекомендации могут помочь вам ускорить загрузку страницы. Они не влияют на показатель производительности [напрямую](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Оптимизация"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Показатели"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Улучшите параметры загрузки, чтобы страница была готова для работы как можно скорее. Ключевые показатели: \"Время загрузки для взаимодействия\" и \"Индекс скорости загрузки\"."
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Общие улучшения"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Производительность"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Здесь проверяется соответствие нормам современных веб-приложений. [Подробнее…](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Lighthouse не проверяет эти пункты автоматически, но они необходимы для соответствия базовому [контрольному списку современных веб-приложений](https://developers.google.com/web/progressive-web-apps/checklist). Они не влияют на показатель приложения, однако их следует проверить вручную."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Современное веб-приложение"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Скорость работы и надежность"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Возможность установки"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Соответствие рекомендациям для PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Эти проверки позволяют оптимизировать сайт для успешной индексации поисковыми системами. Lighthouse проверяет не все факторы, которые могут повлиять на позицию сайта в результатах поиска. [Подробнее…](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Проверьте, соответствует ли ваш сайт рекомендациям по поисковой оптимизации (SEO), с помощью этих дополнительных сервисов."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Поисковая оптимизация"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Оптимизируйте HTML-код, чтобы поисковые роботы могли лучше проанализировать контент приложения."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Рекомендации в отношении контента"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Чтобы ваше приложение появлялось в результатах поиска, предоставьте доступ к нему поисковым роботам."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Сканирование и индексирование"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Убедитесь, что ваши страницы оптимизированы для мобильных устройств, чтобы пользователям не приходилось менять масштаб страниц или подстраивать их под размер экрана. [Подробнее…](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Оптимизация для мобильных устройств"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Время жизни кеша"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Расположение"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Название"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Запросы"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Тип ресурса"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Размер"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Потраченное время"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Объем переданных данных"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Потенциальная экономия"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Потенциальная экономия"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Потенциальная экономия – {wastedBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Потенциальная экономия – {wastedMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Документ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Шрифт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Изображение"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Медиа"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Другой"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Скрипт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} сек."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Таблица стилей"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Сторонний"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Всего"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "При записи трассировки для вашей страницы произошла ошибка. Перезапустите Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Превышено время ожидания для первичного соединения с протоколом отладчика."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "При загрузке страницы в Chrome не были сделаны скриншоты. Проверьте, есть ли на странице видимый контент, и перезапустите Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-серверам не удалось определить IP-адрес по указанному домену."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "При сборе данных ресурса {artifactName} произошла ошибка ({errorMessage})."
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Произошла внутренняя ошибка. Перезапустите Chrome и Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Не удалось собрать данные ресурса {artifactName}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Не удалось загрузить страницу. Убедитесь, что URL введен правильно и сервер отвечает на все запросы."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Не удалось загрузить URL, так как страница не отвечает."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Сертификат безопасности для указанного URL недействителен ({securityMessages})."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Браузер Chrome остановил загрузку страницы с межстраничным объявлением. Убедитесь, что URL введен правильно и сервер отвечает на все запросы."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Не удалось загрузить страницу. Убедитесь, что URL введен правильно и сервер отвечает на все запросы. Подробнее: {errorDetails}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Не удалось загрузить страницу. Убедитесь, что URL введен правильно и сервер отвечает на все запросы. Код статуса: {statusCode}."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Страница загружалась слишком долго. Уменьшите время загрузки, выполнив рекомендации из отчета, а затем перезапустите Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Истекло время ожидания ответа от протокола DevTools. Метод: {protocolMethod}."
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Контент загружался слишком долго. Время ожидания истекло."
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Недействительный URL."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Показать аудиты"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Начальная навигация"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Максимальная задержка критического пути:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Ошибка"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Ошибка отчета: информация аудита отсутствует"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Лабораторные данные"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Результаты анализа [Lighthouse](https://developers.google.com/web/tools/lighthouse/), проведенного для текущей страницы в эмулированной мобильной сети. Значения приблизительные и могут изменяться."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Дополнительные объекты для проверки вручную"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Неприменимо"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Возможности"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Приблизительная экономия"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Успешные аудиты"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Свернуть фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Развернуть фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Показывать сторонние ресурсы"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Во время работы Lighthouse возникли следующие проблемы:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Значения приблизительные и могут изменяться. Уровень производительности рассчитывается [только на основании этих показателей](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Пройденные проверки с предупреждениями"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Предупреждения: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Используйте сервисы, которые позволяют встраивать GIF-файлы на страницы сайта в формате видео HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Чтобы отложить загрузку скрытых страниц, установите [плагин WordPress](https://wordpress.org/plugins/search/lazy+load/) или подберите тему, которая поддерживает такую возможность. Мы также рекомендуем [плагин AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Используйте плагины WordPress, которые позволяют [встроить критическую часть данных](https://wordpress.org/plugins/search/critical+css/) или [отложить загрузку менее важных ресурсов](https://wordpress.org/plugins/search/defer+css+javascript/). Обратите внимание, что такие плагины могут привести к сбоям в работе других используемых вами тем или плагинов. Не исключено, что вам потребуется внести изменения в код."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Темы, плагины и спецификации сервера – все это влияет на время ответа сервера. Советуем найти более подходящую тему, тщательно подобрать плагин для оптимизации и/или обновить сервер."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Мы рекомендуем включить показ только начального фрагмента записей (например, с помощью тега More). Вы также можете сократить количество записей на одной странице, разбить длинные записи на несколько страниц или использовать отложенную загрузку комментариев."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Ускорьте загрузку сайта с помощью [плагинов WordPress](https://wordpress.org/plugins/search/minify+css/), которые позволяют объединять, уменьшать и сжимать стили. Рекомендуем использовать такие плагины на этапе сборки."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Ускорьте загрузку сайта с помощью [плагинов WordPress](https://wordpress.org/plugins/search/minify+javascript/), которые позволяют объединять, уменьшать и сжимать скрипты. Рекомендуем использовать такие плагины на этапе сборки."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Рекомендуем заменить или удалить [плагины WordPress](https://wordpress.org/plugins/), которые загружают неиспользуемый код CSS на вашей странице. Чтобы найти такие плагины, запустите [анализ покрытия кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в инструментах разработчика Chrome. Определить нужный плагин или тему можно по URL таблицы стилей. Обращайте внимание на плагины с большим количеством таблиц стилей, в которых при анализе покрытия кода преобладает красный цвет. Таблица стилей должна попадать в очередь, только если она используется на странице."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Рекомендуем заменить или удалить [плагины WordPress](https://wordpress.org/plugins/), которые загружают неиспользуемый код JavaScript на вашей странице. Чтобы найти такие плагины, запустите [анализ покрытия кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в инструментах разработчика Chrome. Определить нужный плагин или тему можно по URL скрипта. Обращайте внимание на плагины с большим количеством скриптов, в которых при анализе покрытия кода преобладает красный цвет. Скрипт должен попадать в очередь, только если он используется на странице."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Подробнее [о кешировании в браузере на платформе WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)…"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Чтобы сжимать изображения без потери качества, используйте [специальный плагин WordPress](https://wordpress.org/plugins/search/optimize+images/)."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Чтобы привести размеры ваших изображений в соответствие с требованиями, загрузите их в [библиотеку файлов](https://codex.wordpress.org/Media_Library_Screen). Затем вставьте их на сайт прямо из библиотеки или используйте виджет изображений. Таким образом вы сможете обеспечить оптимальный размер изображений (в том числе для контрольных точек адаптивного дизайна). Старайтесь не использовать для изображения значение `Full Size` без особой необходимости. [Подробнее…](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Включить сжатие текста можно в настройках веб-сервера."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Чтобы загружаемые изображения автоматически конвертировались в оптимальный формат, используйте специальный [плагин](https://wordpress.org/plugins/search/convert+webp/) или сервис."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sk.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sk.json
new file mode 100644
index 00000000000..a6aed71719c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sk.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Prístupové klávesy umožňujú používateľom rýchlejšie vybrať časť stránky. Každý prístupový kláves musí byť jedinečný, aby navigácia správne fungovala. [Ďalšie informácie](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Hodnoty `[accesskey]` nie sú jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Počet jedinečných hodnôt: `[accesskey]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Každá značka ARIA `role` podporuje konkrétnu podmnožinu atribútov `aria-*`. Ak ich pomiešate, znehodnotia sa atribúty `aria-*`. [Ďalšie informácie](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atribúty `[aria-*]` nezodpovedajú svojim rolám"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atribúty `[aria-*]` zodpovedajú svojim rolám"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Niektoré roly ARIA majú povinné atribúty, ktoré čítačkám obrazovky opisujú stav prvku. [Ďalšie informácie](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Roly `[role]` nemajú všetky požadované atribúty `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Roly `[role]` majú všetky požadované atribúty `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Ak majú poskytovať správne funkcie dostupnosti, musia niektoré nadradené roly ARIA obsahovať určité podradené roly. [Ďalšie informácie](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Prvkom so štítkom ARIA `[role]`, ktoré vyžadujú, aby podradené prvky obsahovali konkrétnu rolu `[role]`, chýbajú niektoré alebo všetky požadované podradené prvky."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Prvky so štítkom ARIA `[role]`, ktoré vyžadujú, aby podradené prvky obsahovali konkrétnu rolu `[role]`, majú všetky požadované podradené prvky."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Ak majú niektoré podradené roly ARIA poskytovať správne funkcie dostupnosti, musia byť obsiahnuté v konkrétnych nadradených rolách. [Ďalšie informácie](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Roly `[role]` sa nenachádzajú v požadovanom nadradenom prvku"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Roly `[role]` sa nachádzajú v požadovanom nadradenom prvku"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Ak majú roly ARIA vykonávať zamýšľané funkcie dostupnosti, musia mať platné hodnoty. [Ďalšie informácie](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Hodnoty `[role]` nie sú platné"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Hodnoty `[role]` sú platné"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Asistenčné technológie, ako sú čítačky obrazovky, nedokážu interpretovať atribúty ARIA s neplatnými hodnotami. [Ďalšie informácie](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atribúty `[aria-*]` nemajú platné hodnoty"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atribúty `[aria-*]` majú platné hodnoty"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Asistenčné technológie, ako sú čítačky obrazovky, nedokážu interpretovať atribúty ARIA s neplatnými názvami. [Ďalšie informácie](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atribúty `[aria-*]` nie sú platné ani neobsahujú preklepy"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atribúty `[aria-*]` sú platné a neobsahujú preklepy"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Titulky sprístupňujú nepočujúcim a sluchovo postihnutým používateľom zvukové prvky pomocou dôležitých informácií, napríklad údajov o tom, kto hovorí, čo hovorí a ďalších informácií nesúvisiacich s rečou. [Ďalšie informácie](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Prvkom `<audio>` chýba prvok `<track>` s titulkami `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Prvky `<audio>` obsahujú prvok `<track>` s titulkami `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Prvky s chybami"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Keď tlačidlo nemá dostupný názov, čítačky obrazovky ho oznamujú ako „tlačidlo“, takže je pre používateľov v podstate nanič. [Ďalšie informácie](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Tlačidlá nemajú dostupný názov"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Tlačidlá majú dostupný názov"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Keď pridáte možnosti, ako obísť opakujúci sa obsah, umožníte tým efektívnejšiu navigáciu na stránke pomocou klávesnice. [Ďalšie informácie](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Stránka neobsahuje hlavičku, odkaz na preskočenie či orientačný bod regióna."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Stránka obsahuje hlavičku, odkaz na preskočenie alebo orientačný bod regiónu"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Mnohí používatelia majú problémy s čítaním textu s nízkym kontrastom, prípadne to vôbec nedokážu. [Ďalšie informácie](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Farby pozadia a popredia nemajú dostatočný kontrastný pomer."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Farby pozadia a popredia majú dostatočný kontrastný pomer"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Keď zoznamy definícií nie sú správne označené, čítačky obrazovky môžu generovať mätúci alebo nepresný výstup. [Ďalšie informácie](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` neobsahuje iba správne usporiadané skupiny `<dt>` a `<dd>`, prvky `<script>` alebo `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` obsahuje iba správne usporiadané skupiny `<dt>` a `<dd>`, prvky `<script>` alebo `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Položky zoznamu definícií (`<dt>` a `<dd>`) musia byť zabalené v nadradenom prvku `<dl>`, aby ich čítačky obrazovky dokázali správne oznamovať. [Ďalšie informácie](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Položky zoznamu definícií nie sú zabalené v prvkoch `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Položky zoznamu definícií sú zabalené v prvkoch `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Názov poskytuje používateľom čítačiek obrazovky prehľadné informácie o stránke a používatelia vyhľadávačov sa podľa neho rozhodujú, či je stránka pre ich vyhľadávanie relevantná. [Ďalšie informácie](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument nemá prvok `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument má prvok `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Hodnota atribútu ID musí byť jedinečná, aby asistenčné technológie neprehliadli ďalšie výskyty. [Ďalšie informácie](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atribúty `[id]` na stránke nie sú jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atribúty `[id]` na stránke sú jedinečné"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Používatelia čítačiek obrazovky zistia obsah rámcov pomocou ich názvov. [Ďalšie informácie](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Prvky `<frame>` alebo `<iframe>` nemajú názov"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Prvok `<frame>` alebo `<iframe>` má názov"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ak stránka neuvádza atribút lang, čítačka obrazovky predpokladá, že je v predvolenom jazyku vybranom používateľom pri nastavovaní čítačky obrazovky. Ak stránka v skutočnosti nie je v predvolenom jazyku, čítačka obrazovky nemusí jej text prečítať správne. [Ďalšie informácie](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Prvok `<html>` nemá atribút `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Prvok `<html>` má atribút `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Ak je uvedený platný [jazyk BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), čítačkám obrazovky to pomôže správne oznamovať text. [Ďalšie informácie](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Prvok `<html>` nemá platnú hodnotu pre atribút `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Prvok `<html>` má platnú hodnotu pre svoj atribút `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informatívne prvky by mali mať krátky popisný alternatívny text. Dekoratívne prvky je možné ignorovať pomocou prázdneho atribútu alt. [Ďalšie informácie](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Prvky obrázkov nemajú atribúty `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Prvky obrázka majú atribúty `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Keď je ako tlačidlo `<input>` použitý obrázok, uvedenie alternatívneho textu môže pomôcť používateľom čítačky obrazovky pochopiť účel tlačidla. [Ďalšie informácie](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Prvky `<input type=\"image\">` nemajú text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Prvky `<input type=\"image\">` majú text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Štítky zaisťujú, aby asistenčné technológie (napríklad čítačky obrazovky) správne oznamovali ovládacie prvky formulárov. [Ďalšie informácie](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Prvky formulárov nemajú priradené štítky"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "K prvkom formulára sú priradené štítky"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabuľka používaná na vytvorenie rozloženia by nemala obsahovať údajové prvky, ako sú prvky th a caption, prípadne atribút summary, pretože by ste tým mohli zmiasť používateľov čítačiek obrazovky. [Ďalšie informácie](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Prezentačné prvky `<table>` nepoužívajú atribút `<th>`, `<caption>` alebo `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Prezentačné prvky `<table>` nepoužívajú atribút `<th>`, `<caption>` ani `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Rozpoznateľný, jedinečný a zamerateľný text odkazu (a alternatívny text pre obrázky, ktoré sa používajú ako odkazy) zlepšuje navigáciu pomocou čítačky obrazovky. [Ďalšie informácie](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Odkazy nemajú rozpoznateľné názvy"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Odkazy majú rozpoznateľné názvy"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Čítačky obrazovky oznamujú zoznamy špeciálnym spôsobom. Použitím správnej štruktúry zoznamu pomôžete čítačkám obrazovky s výstupom. [Ďalšie informácie](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Zoznamy neobsahujú iba prvky `<li>` a prvky podporujúce skript (`<script>` a `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Zoznamy obsahujú iba prvky `<li>` a prvky podporujúce skript (`<script>` a `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Položky zoznamu (`<li>`) sa musia nachádzať v nadradenom prvku `<ul>` alebo `<ol>`, aby ich dokázali čítačky obrazovky správne oznámiť. [Ďalšie informácie](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Položky zoznamu (`<li>`) sa nenachádzajú v nadradených prvkoch `<ul>` ani `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Položky zoznamu (`<li>`) sa nachádzajú v nadradených prvkoch `<ul>` alebo `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Používatelia neočakávajú, že sa stránka bude automaticky obnovovať. Pri automatickom obnovení sa zameranie vráti späť na začiatok stránky. Na používateľov to môže pôsobiť nepríjemne alebo mätúco. [Ďalšie informácie](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokument používa metaznačku `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokument nepoužíva `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Deaktivácia približovania spôsobuje problémy slabozrakým používateľom, ktorí pri čítaní obsahu webovej stránky využívajú priblíženie obrazovky. [Ďalšie informácie](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` sa nepoužíva v prvku `<meta name=\"viewport\">` alebo hodnota atribútu `[maximum-scale]` je nižšia ako 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` sa nepoužíva v prvku `<meta name=\"viewport\">` a atribút `[maximum-scale]` nie je menší ako 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Čítačky obrazovky nedokážu preložiť netextový obsah. Pridaním alternatívneho textu k prvkom `<object>` pomôžete čítačkám obrazovky sprostredkovať používateľom význam. [Ďalšie informácie](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Prvky `<object>` nemajú text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Prvky `<object>` majú text `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Hodnota väčšia ako 0 označuje explicitné usporiadanie navigácie. Hoci je to technicky platné riešenie, často vedie k nepríjemným skúsenostiam používateľov, ktorí potrebujú asistenčné technológie. [Ďalšie informácie](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Niektoré prvky majú hodnotu `[tabindex]` vyššiu ako 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Žiadny prvok nemá hodnotu `[tabindex]` vyššiu ako 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Čítačky obrazovky majú funkcie, ktoré zjednodušujú prehliadanie tabuliek. Keď zaistíte, aby bunky `<td>` s atribútom `[headers]` odkazovali iba na bunky v rovnakej tabuľke, môžete tým používateľom čítačiek obrazovky zjednodušiť prehliadanie. [Ďalšie informácie](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Bunky v prvku `<table>`, ktoré používajú atribút `[headers]`, odkazujú na prvok `id`, ktorý nie je v rovnakej tabuľke."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Bunky v prvku `<table>`, ktoré používajú atribút `[headers]`, odkazujú na bunky v tej istej tabuľke."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Čítačky obrazovky majú funkcie, ktoré zjednodušujú prehliadanie tabuliek. Dojem používateľov čítačiek obrazovky môžete vylepšiť tým, že hlavičky tabuliek budú odkazovať na určitú skupinu buniek. [Ďalšie informácie](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Prvky `<th>` a prvky s rolou `[role=\"columnheader\"/\"rowheader\"]` nemajú bunky s údajmi, ktoré opisujú."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Prvky `<th>` a prvky s rolou `[role=\"columnheader\"/\"rowheader\"]` majú bunky s údajmi, ktoré opisujú."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Ak je v prvkoch uvedený platný [jazyk BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), pomôže to zaistiť, aby čítačky obrazovky čítali text správne. [Ďalšie informácie](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atribúty `[lang]` nemajú platnú hodnotu"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atribúty `[lang]` majú platnú hodnotu"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Keď má video k dispozícii titulky, nepočujúci a sluchovo postihnutí používatelia jednoduchšie získajú informácie vo videu. [Ďalšie informácie](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Prvky `<video>` neobsahujú prvok `<track>` s titulkami `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Prvky `<video>` obsahujú prvok `<track>` s titulkami `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Zvukové popisy pridávajú k videám relevantné informácie, napríklad o výrazoch tváre a scénach, ktoré dialógy neposkytujú. [Ďalšie informácie](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Prvky `<video>` neobsahujú prvok `<track>` s titulkami `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Prvky `<video>` obsahujú prvok `<track>` s titulkami `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Ak chcete zaistiť ideálny vzhľad progresívnej webovej aplikácie v systéme iOS, keď si ju používateľ pridá na plochu, definujte vlastnosť `apple-touch-icon`. Musí odkazovať na nepriehľadný obrázok PNG s veľkosťou 192 × 192 px (alebo 180 × 180 px). [Ďalšie informácie](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Neposkytuje platnú ikonu `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Prvok `apple-touch-icon-precomposed` je zastaraný, preferuje sa `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Poskytuje platnú ikonu `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Rozšírenia pre Chrome negatívne ovplyvnili výkonnosť načítania tejto stránky. Skúste stránku skontrolovať v režime inkognito alebo profile Chrome bez rozšírení."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Hodnotenie skriptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Analýza skriptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Celkový čas využitia procesora"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Zvážte skrátenie času stráveného analýzou, zostavovaním a spustením JavaScriptu. Možno vám s tým pomôže zobrazovanie menších prenášaných dát JavaScriptu. [Ďalšie informácie](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Skráťte čas spustenia JavaScriptu"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Čas spustenia JavaScriptu"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Veľké gify nie sú vhodné na zobrazovanie animovaného obsahu. Namiesto nich odporúčame použiť videá MPEG4/WebM pre animácie a PNG/WebP pre statické obrázky, aby ste ušetrili spotrebu bajtov v sieti. [Ďalšie informácie](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Pre animovaný obsah použite formáty videa"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Zvážte oneskorené načítanie obrázkov, ktoré sú mimo obrazovky alebo skryté, a to až po dokončení načítania všetkých podstatných zdrojov, čím skrátite čas do interaktívneho vykreslenia. [Ďalšie informácie](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Oddiaľte načítanie obrázkov mimo obrazovky"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Zdroje blokujú prvé vykreslenie stránky. Zvážte zobrazovanie podstatných JavaScriptov alebo šablón CSS v texte a oddialenie všetkých nepodstatných JavaScriptov alebo štýlov. [Ďalšie informácie](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Odstráňte zdroje blokujúce vykreslenie"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Veľké sieťové prenosy dát stoja používateľov mnoho peňazí a často sú spájané s dlhými časmi načítania. [Ďalšie informácie](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Celková veľkosť bola {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Zabráňte nadmerným sieťovým prenosom dát"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Zabráni nadmerným sieťovým prenosom dát"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Minifikáciou súborov šablón CSS môžete znížiť veľkosti sieťových prenosov dát. [Ďalšie informácie](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minifikujte súbory CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Minifikáciou súborov JavaScriptu môžete znížiť veľkosti prenášaných dát a čas analýzy skriptu. [Ďalšie informácie](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minifikujte JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Odstráňte nepoužívané pravidlá zo šablón štýlov a odložte načítavanie šablón CSS, ktoré sa nepoužívajú pre obsah nad záhybom stránky, čím znížite zbytočnú spotrebu bajtov sieťovou aktivitou. [Ďalšie informácie](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Odstráňte nepoužívané šablóny CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Odstráňte nepoužívaný JavaScript a znížte tak spotrebu bajtov sieťovou aktivitou."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Odstráňte nepoužívaný JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Dlhá životnosť vyrovnávacej pamäte môže zrýchliť opakované návštevy stránky. [Ďalšie informácie](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Našiel sa 1 zdroj}few{Našli sa # zdroje}many{# resources found}other{Našlo sa # zdrojov}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Zobrazujte statické podklady s účinnými pravidlami ukladania do vyrovnávacej pamäte"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Používa účinné pravidlá ukladania do vyrovnávacej pamäte pre statické podklady"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimalizované obrázky sa načítavajú rýchlejšie a spotrebúvajú menej mobilných dát. [Ďalšie informácie](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Účinne zakódujte obrázky"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Zobrazujte obrázky s primeranou veľkosťou, čím ušetríte mobilné dáta a skrátite čas načítania. [Ďalšie informácie](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Nastavte primeranú veľkosť obrázkov"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Textové zdroje by sa mali zobrazovať komprimované (gzip, deflate alebo brotli), aby sa minimalizovala celková spotreba bajtov v sieti. [Ďalšie informácie](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Povoľte kompresiu textu"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formáty obrázka, napríklad JPEG 2000, JPEG XR a WebP, zvyčajne poskytujú lepšiu kompresiu než PNG alebo JPEG, čo znamená rýchlejšie sťahovanie a nižšiu spotrebu dát. [Ďalšie informácie](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Zobrazujte obrázky vo formátoch ďalšej generácie"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ak šírka obsahu vašej aplikácie nezodpovedá šírke oblasti zobrazenia, aplikácia nemusí byť optimalizovaná pre obrazovky mobilných zariadení. [Ďalšie informácie](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Veľkosť oblasti zobrazenia {innerWidth} px nezodpovedá veľkosti okna {outerWidth} px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Obsah nemá správnu veľkosť pre oblasť zobrazenia"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Obsah má správnu veľkosť pre oblasť zobrazenia"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Reťazce podstatných žiadostí uvedené nižšie znázorňujú, ktoré zdroje sú načítané s vysokou prioritou. Zvážte skrátenie dĺžky reťazcov, aby ste znížili veľkosť sťahovaných zdrojov, alebo odložte sťahovanie nepotrebných zdrojov, čím zlepšíte načítanie stránky. [Ďalšie informácie](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Našiel sa 1 reťazec}few{Našli sa # reťazce}many{# chains found}other{Našlo sa # reťazcov}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minimalizujte hĺbku podstatných žiadostí"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Ukončenie podpory / upozornenie"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Riadok"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Rozhrania API s ukončenou podporou budú nakoniec z prehliadača odstránené. [Ďalšie informácie](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Zistilo sa 1 upozornenie}few{Zistili sa # upozornenia}many{# warnings found}other{Zistilo sa # upozornení}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Používa rozhrania API s ukončenou podporou"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Nepoužíva rozhrania API s ukončenou podporou"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Podpora vyrovnávacej pamäte aplikácie je ukončená. [Ďalšie informácie](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Našiel sa prvok {AppCacheManifest}"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Používa vyrovnávaciu pamäť aplikácie"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Nepoužíva vyrovnávaciu pamäť aplikácie"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Špecifikáciou typu dokumentu zabránite prechodu prehliadača do režimu kompatibility. [Ďalšie informácie](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Názov prvku doctype musí byť reťazec `html` s malými písmenami"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument musí obsahovať prvok doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Očakávalo sa, že publicId bude prázdny reťazec"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Očakávalo sa, že systemId bude prázdny reťazec"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Stránke chýba prvok HTML doctype, preto spúšťa režim kompatibility"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Stránka obsahuje prvok HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Prvok"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Štatistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Hodnota"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Programátori prehliadača odporúčajú, aby stránky obsahovali menej ako ~1 500 prvkov DOM. Optimálna hodnota je hĺbka stromovej štruktúry menšia ako 32 prvkov a menej ako 60 podradených či nadradených prvkov. Veľký prvok DOM môže zvýšiť spotrebu pamäte, predĺžiť [výpočty štýlov](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) a spôsobiť nákladné [preformátovania rozložení](https://developers.google.com/speed/articles/reflow). [Ďalšie informácie](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 prvok}few{# prvky}many{# elements}other{# prvkov}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Nepoužívajte nadmerne veľký prvok DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maximálna hĺbka prvku DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Celkový počet prvkov DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maximálny počet podradených prvkov"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Zabráni použitiu nadmerne veľkého prvku DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cieľ"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Ak chcete zlepšiť výkonnosť a zabrániť chybám zabezpečenia, pridajte k ľubovoľným externým odkazom prvok `rel=\"noopener\"` alebo `rel=\"noreferrer\"`. [Ďalšie informácie](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Odkazy na destinácie typu cross origin nie sú bezpečné"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Odkazy na destinácie typu cross origin sú bezpečné"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nepodarilo sa zistiť cieľ ukotvenia ({anchorHTML}). Ak sa nepoužíva ako hypertextový odkaz, zvážte odstránenie prvku target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Používatelia nedôverujú webom, ktoré požadujú ich polohu bez kontextu, alebo ich považujú za mätúce. Zvážte namiesto toho spojenie žiadosti s akciou používateľa. [Ďalšie informácie](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Požaduje povolenie na geolokáciu pri načítaní stránky"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Nepožaduje povolenie na geolokáciu pri načítaní stránky"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Verzia"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Na stránke boli zistené všetky JavaScriptové knižnice klientskeho rozhrania. [Ďalšie informácie](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Zistené knižnice JavaScriptu"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "V prípade používateľov s pomalým pripojením môžu externé skripty, ktoré sú dynamicky vložené prostredníctvom funkcie `document.write()`, oneskoriť načítavanie stránky o desiatky sekúnd. [Ďalšie informácie](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Používa `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Nepoužíva `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Najzávažnejšie"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Verzia knižnice"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Počet chýb zabezpečenia"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Niektoré skripty tretích strán môžu obsahovať chyby zabezpečenia, ktoré dokážu útočníci ľahko rozpoznať a zneužiť. [Ďalšie informácie](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Bola zistená 1 chyba zabezpečenia}few{Boli zistené # chyby zabezpečenia}many{# vulnerabilities detected}other{Bolo zistených # chýb zabezpečenia}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Zahrnuje JavaScriptové knižnice v klientskom rozhraní so známymi chybami zabezpečenia"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Vysoká"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Nízka"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Stredné"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Nepoužíva v klientskom rozhraní knižnice JavaScriptov so známymi chybami zabezpečenia"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Používatelia nedôverujú webom, ktoré požadujú odosielanie upozornení bez kontextu, alebo ich považujú za mätúce. Zvážte namiesto toho spojenie žiadosti s gestami používateľa. [Ďalšie informácie](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Požaduje povolenie na upozornenie pri načítaní stránky"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Nepožaduje povolenie na upozornenie pri načítaní stránky"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Prvky s chybami"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Ak zakážete prilepovanie hesiel, zhoršíte kvalitu zabezpečenia. [Ďalšie informácie](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Zabráňte používateľom prilepovať do polí pre heslá"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Umožnite používateľom prilepovať do polí pre heslá"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ponúka oproti HTTP/1.1 mnoho výhod vrátane binárnych hlavičiek, multiplexovania a technológie push na strane servera. [Ďalšie informácie](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 žiadosť nebola odoslaná cez HTTP/2}few{# žiadosti neboli odoslané cez HTTP/2}many{# requests not served via HTTP/2}other{# žiadostí nebolo odoslaných cez HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Nepoužíva HTTP/2 pre všetky svoje zdroje"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Používa HTTP/2 pre svoje vlastné zdroje"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Odporúčame zmeniť prijímače udalostí aktivovaných dotykom alebo kolieskom myši na `passive`, čím zlepšíte výkonnosť posúvania stránky. [Ďalšie informácie](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Nepoužíva pasívne prijímače na zlepšenie posúvania"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Používa pasívne prijímače na zlepšenie posúvania"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Popis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Chyby zapísané do denníka konzoly označujú nevyriešené problémy. Môžu pochádzať zo zlyhaní žiadostí siete a ďalších problémov prehliadača. [Ďalšie informácie](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Chyby prehliadača boli zaznamenané do konzoly"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Do konzoly neboli zaznamenané žiadne chyby prehliadača"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Využite funkciu CSS zobrazenia písma, ktorá pomôže zaistiť, aby používatelia videli text počas načítavania webfontov. [Ďalšie informácie](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Zaistite, aby text zostal počas načítania webfontov viditeľný"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Všetok text zostane počas načítania webfontov viditeľný"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Nástroj Lighthouse nedokázal automaticky skontrolovať hodnotu zobrazenia písma na nasledujúcej webovej adrese: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Pomer strán (skutočný)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Pomer strán (zobrazený)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Rozmery zobrazenia obrázka by mali zodpovedať prirodzenému pomeru strán. [Ďalšie informácie](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Zobrazuje obrázky s nesprávnym pomerom strán"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Zobrazuje obrázky so správnym pomerom strán"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Neplatné informácie o veľkosti obrázka {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Prehliadače môžu proaktívne vyzývať používateľov, aby si pridali vašu aplikáciu na plochu, čo môže viesť k ich lepšiemu zapojeniu. [Ďalšie informácie](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifest webovej aplikácie nespĺňa požiadavky na inštaláciu"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifest webovej aplikácie spĺňa požiadavky na inštaláciu"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nezabezpečená webová adresa"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Všetky weby by mali byť zabezpečené protokolom HTTPS, dokonca aj tie, ktoré nespracúvajú citlivé údaje. HTTPS bráni útočníkom narušovať komunikáciu medzi vašou aplikáciou a používateľmi alebo ju pasívne odpočúvať, a je podmienkou pre HTTP/2 a mnoho nových rozhraní API webových platforiem. [Ďalšie informácie](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Bola zistená 1 nezabezpečená žiadosť}few{Boli zistené # nezabezpečené žiadosti}many{# insecure requests found}other{Bolo zistených # nezabezpečených žiadostí}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Nepoužíva HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Používa HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Rýchle načítanie stránky cez mobilnú sieť zaisťuje dobrý dojem používateľov mobilných zariadení. [Ďalšie informácie](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktívna po {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktívna v simulovanej mobilnej sieti v čase {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Vaša stránka sa načítava príliš pomaly a nie je interaktívna do desiatich sekúnd. Prezrite si príležitosti a diagnostiku v sekcii Výkonnosť a zistite, ako ju zlepšiť."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Načítanie stránky nie je dostatočne rýchle v mobilných sieťach"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Načítanie stránky je dostatočne rýchle v mobilných sieťach"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategória"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Zvážte skrátenie času stráveného analýzou, zostavovaním a spustením JavaScriptu. Možno vám s tým pomôže zobrazovanie menších prenášaných dát JavaScriptu. [Ďalšie informácie](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimalizujte prácu hlavného vlákna"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimalizuje prácu hlavného vlákna"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Ak chcete osloviť maximálny počet používateľov, weby by mali fungovať vo všetkých hlavných prehliadačoch. [Ďalšie informácie](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Web funguje v rôznych prehliadačoch"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Zaistite, aby jednotlivé stránky podporovali priame odkazovanie prostredníctvom webovej adresy a aby dané webové adresy boli jedinečné na účely zdieľania v sociálnych médiách. [Ďalšie informácie](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Každá stránka má webovú adresu"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Prechody by pri klepaní mali pôsobiť plynulo, dokonca aj v pomalej sieti. Ide o kľúčový faktor ovplyvňujúci vnímanú výkonnosť. [Ďalšie informácie](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Prechody stránok zrejme nie sú blokované sieťou"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Odhadovaná latencia vstupu je odhadovaný čas odozvy na vstup používateľa v milisekundách počas najrušnejších 5 sekúnd načítania stránky. Ak latencia prevyšuje 50 ms, používateľom sa môžu zdať odozvy aplikácie oneskorené. [Ďalšie informácie](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Odhadovaná latencia vstupu"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Prvé vykreslenie obsahu označuje čas, za ktorý je vykreslený prvý text alebo obrázok. [Ďalšie informácie](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Prvé obsahové vyfarbenie"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Prvá nečinnosť procesora označuje, kedy je hlavné vlákno stránky prvýkrát dostatočne nečinné na spracovanie vstupu. [Ďalšie informácie](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Prvá nečinnosť procesora"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Prvé zmysluplné vykreslenie meria, kedy je hlavný obsah stránky viditeľný. [Ďalšie informácie](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Prvé účelné vyfarbenie"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Čas do interaktivity je údaj o tom, koľko času prejde, kým bude stránka plne interaktívna. [Ďalšie informácie](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Čas do interaktívneho vykreslenia"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Maximálne potenciálne oneskorenie prvého vstupu, ktoré sa u vašich používateľov môže vyskytnúť, je trvanie najdlhšej úlohy (v milisekundách). [Ďalšie informácie](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Max. potenc. oneskorenie prvého vstupu"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Index rýchlosti znázorňuje, za aký čas sa viditeľne doplní obsah stránky. [Ďalšie informácie](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Index rýchlosti"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Súčet všetkých časových období medzi prvým vykreslením obsahu a časom do interaktivity, kedy dĺžka úlohy presiahla 50 ms (vyjadrený v milisekundách)."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Celkový čas blokovania"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Časy vrátenia žiadostí v rámci siete majú veľký vplyv na výkonnosť. Ak je čas vrátenia žiadostí v rámci siete k pôvodnému zdroju vysoký, znamená to, že servery umiestnené bližšie k používateľovi by mohli zlepšiť výkonnosť. [Ďalšie informácie](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Časy vrátania žiadostí v rámci siete"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Výkonnosť webu môžu ovplyvniť latencie servera. Ak je latencia zdrojového servera vysoká, znamená to, že je preťažený alebo má slabú výkonnosť. [Ďalšie informácie](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Latencie na strane servera"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Obsluha umožňuje vašej webovej aplikácii spoľahlivo fungovať za nepredvídateľných podmienok siete. [Ďalšie informácie](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` nereaguje kódom 200, keď je offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` reaguje kódom 200, keď je offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Nástroju Lighthouse sa nepodarilo prečítať vlastnosť `start_url` z manifestu. Na základe toho sa za webovú adresu dokumentu považuje `start_url`. Chybové hlásenie: {manifestWarning}."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Cez rozpočet"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Udržujte množstvo a veľkosť žiadostí siete pod cieľovými hodnotami stanovenými poskytnutým rozpočtom výkonnosti. [Ďalšie informácie](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 žiadosť}few{# žiadosti}many{# requests}other{# žiadostí}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Rozpočet výkonnosti"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ak ste už nastavili HTTPS, zaistite presmerovanie všetkej návštevnosti cez HTTP na HTTPS a poskytnite tak funkcie zabezpečeného webu všetkým používateľom. [Ďalšie informácie](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Nepresmerúva návštevnosť cez HTTP na HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Presmerúva návštevnosť cez HTTP na HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Presmerovania spôsobujú ďalšie oneskorenia pri načítavaní stránky. [Ďalšie informácie](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Vyhnite sa viacnásobným presmerovaniam stránky"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Ak chcete nastaviť rozpočty pre množstvo a veľkosť zdrojov stránky, pridajte súbor budget.json. [Ďalšie informácie](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 žiadosť • {byteCount, number, bytes} kB}few{# žiadosti • {byteCount, number, bytes} kB}many{# requests • {byteCount, number, bytes} KB}other{# žiadostí • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Udržiavajte nízke počty žiadostí a malé veľkosti prenosov"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanonické odkazy navrhujú, ktorá webová adresa by sa mala zobraziť vo výsledkoch vyhľadávania. [Ďalšie informácie](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Viacero kolidujúcich webových adries ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Odkazuje na inú doménu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Neplatná webová adresa ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Odkazuje na iné umiestnenie `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relatívna webová adresa ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Odkazuje na koreňovú webovú adresu domény (domovskú stránku), a nie na ekvivalentnú stránku s obsahom"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument nemá platný odkaz `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument má platný odkaz `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Veľkosti písma menšie ako 12 px sú príliš malé na to, aby boli čitateľné, a nútia používateľov mobilných zariadení, aby si ich priblížili stiahnutím prstov. Zaistite, aby viac ako 60 % textu na stránke malo veľkosť ≥ 12 px. [Ďalšie informácie](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} čitateľného textu"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text nie je čitateľný, pretože neexistuje žiadna metaznačka oblasti zobrazenia optimalizovaná pre mobilné obrazovky."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Určitá časť textu ({decimalProportion, number, extendedPercent}) je príliš malá (na základe vzorky {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokument nepoužíva čitateľné veľkosti písma"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokument používa čitateľné veľkosti písma"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Odkazy hreflang informujú vyhľadávače, akú verziu stránky by mali uviesť vo výsledkoch vyhľadávania pre daný jazyk alebo oblasť. [Ďalšie informácie](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument nemá platný atribút `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument má platný odkaz `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Stránky s neúspešnými stavovými kódmi HTTP sa nemusia správne indexovať. [Ďalšie informácie](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Stránka má neúspešný stavový kód HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Stránka má úspešný stavový kód HTTP"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Ak nemajú vyhľadávače povolenie prehľadávať vaše stránky, nemôžu ich zahrnúť do výsledkov vyhľadávania. [Ďalšie informácie](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Stránka má blokované indexovanie"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Stránka nemá blokované indexovanie"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Popisný text odkazu pomáha vyhľadávačom pochopiť váš obsah. [Ďalšie informácie](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Našiel sa 1 odkaz}few{Našli sa # odkazy}many{# links found}other{Našlo sa # odkazov}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Odkazy nemajú popisný text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Odkazy majú popisný text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Spustite [tester štruktúrovaných dát](https://search.google.com/structured-data/testing-tool/) a nástroj [Structured Data Linter](http://linter.structured-data.org/) na overenie štruktúrovaných dát. [Ďalšie informácie](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Štruktúrované dáta sú platné"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Vo výsledkoch vyhľadávania môžu byť zahrnuté metapopisy, ktoré stručne zhrnú obsah stránky. [Ďalšie informácie](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Text popisu chýba."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument nemá metapopis"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument má metapopis"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Vyhľadávače nemôžu indexovať obsah doplnkov a mnoho zariadení obmedzuje doplnky alebo ich nepodporuje. [Ďalšie informácie](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument používa doplnky"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument nepoužíva doplnky"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ak máte chybný súbor robots.txt, prehľadávače nemusia pochopiť, akým spôsobom majú váš web prehľadávať alebo indexovať. [Ďalšie informácie](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Žiadosť o súbor robots.txt vrátila stav HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Našla sa 1 chyba}few{Našli sa # chyby}many{# errors found}other{Našlo sa # chýb}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Nástroj Lighthouse nedokázal stiahnuť súbor robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Súbor robots.txt nie je platný"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Súbor robots.txt je platný"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktívne prvky, ako sú tlačidlá a odkazy, by mali byť dostatočne veľké (48 × 48 px) a mať okolo seba dostatočné voľné miesto, aby sa na ne dalo ľahko klepnúť a neprekrývali ďalšie prvky. [Ďalšie informácie](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} cieľových oblastí s vhodnou veľkosťou"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Cieľové oblasti klepnutia sú príliš malé, pretože neexistuje žiadna metaznačka oblasti zobrazenia optimalizovaná pre mobilné obrazovky"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Cieľové oblasti klepnutia nemajú vhodnú veľkosť"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Prekrývajúce sa cieľové oblasti"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Cieľová oblasť klepnutia"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Cieľové oblasti klepnutia majú vhodnú veľkosť"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Obsluha je technológia, ktorá umožňuje vašej aplikácii používať mnoho funkcií progresívnej webovej aplikácie, napríklad offline režim, pridanie na plochu a upozornenia aplikácie. [Ďalšie informácie](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Túto stránku ovláda obsluha, ale nenašla sa vlastnosť `start_url`, pretože sa nepodarilo analyzovať manifest ako platný súbor JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Túto stránku ovláda obsluha, ale hodnota `start_url` ({startUrl}) sa nenachádza v rozsahu obsluhy ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Túto stránku ovláda obsluha, ale nenašla sa vlastnosť `start_url`, pretože sa nepodarilo načítať manifest."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Zdroj obsahuje jednu alebo viac obslúh, avšak stránka ({pageUrl}) nie je v rozsahu."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Nemá zaregistrovanú obsluhu, ktorá ovláda stránku a vlastnosť `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Má zaregistrovanú obsluhu, ktorá ovláda stránku a vlastnosť `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Úvodná obrazovka s motívom zaistí skvelý dojem používateľa, keď si spustí vašu aplikáciu z plochy. [Ďalšie informácie](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nie je nakonfigurovaný pre vlastnú úvodnú obrazovku"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Nakonfigurované pre vlastnú úvodnú obrazovku"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Panel s adresou prehliadača je možné upraviť motívom, aby zodpovedal vášmu webu. [Ďalšie informácie](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Nenastavuje farbu motívu pre panel s adresou."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Nastavuje farbu motívu pre panel s adresou."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Čas blokovania hlavného vlákna"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tretia strana"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kód tretích strán môže výrazne ovplyvniť výkonnosť načítavania. Obmedzte počet nadbytočných poskytovateľov tretích strán a skúste načítavať kód tretích strán po dokončení načítavania stránky. [Ďalšie informácie](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Hlavné vlákno bolo {timeInMs, number, milliseconds} ms zablokované kódom tretej strany"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Zníženie vplyvu kódu tretích strán"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Používanie tretími stranami"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Čas do prvého bajtu určuje čas, za ktorý váš server odošle odpoveď. [Ďalšie informácie](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Hlavný dokument trval {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Znížte časy odpovede servera (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Časy odozvy servera sú krátke (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trvanie"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Čas začatia"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Typ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Odporúčame do aplikácie implementovať rozhranie User Timing API, ktoré umožňuje odmerať jej skutočnú výkonnosť počas udalostí kľúčových pre dojem používateľov. [Ďalšie informácie](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 trvanie aktivít používateľov}few{# trvania aktivít používateľov}many{# user timings}other{# trvaní aktivít používateľov}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Značky a merania trvania aktivít používateľov"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Pre atribút {securityOrigin} sa našiel odkaz predpripojenia <link>, prehliadač ho však nepoužil. Skontrolujte, či atribút `crossorigin` používate správne."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Zvážte pridanie indikátorov zdrojov `preconnect` a `dns-prefetch`, ktoré vám pomôžu zriadiť predbežné pripojenia k dôležitým zdrojom tretích strán. [Ďalšie informácie](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Nastavte predbežné pripojenie k požadovaným zdrojom"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Pre atribút {preloadURL} sa našiel odkaz <link> prednačítania, prehliadač ho však nepoužil. Skontrolujte, či atribút `crossorigin` používate správne."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Zvážte použitie funkcie `<link rel=preload>`, čím uprednostníte načítanie zdrojov momentálne požadovaných v neskoršej fáze načítania stránky. [Ďalšie informácie](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Predbežne načítavajte kľúčové žiadosti"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Ak chcete optimalizovať svoju aplikáciu pre obrazovky mobilných zariadení, pridajte značku `<meta name=\"viewport\">`. [Ďalšie informácie](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nenašla sa žiadna značka `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nemá značku `<meta name=\"viewport\">` s vlastnosťou `width` alebo `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Obsahuje značku `<meta name=\"viewport\">` s vlastnosťou `width` alebo `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Vaša aplikácia by mala zobrazovať nejaký obsah, keď je zakázaný JavaScript, aj keby malo ísť iba o upozornenie používateľa, že na používanie aplikácie sa vyžaduje JavaScript. [Ďalšie informácie](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Telo stránky by malo vykresliť nejaký obsah, ak jej skripty nie sú k dispozícii."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Neposkytuje záložný obsah, keď nie je k dispozícii JavaScript"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Obsahuje určitý obsah, keď nie je k dispozícii JavaScript"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ak vytvárate progresívnu webovú aplikáciu, zvážte použitie obsluhy, aby aplikácia mohla fungovať offline. [Ďalšie informácie](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Aktuálna stránka nereaguje kódom 200, keď je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Aktuálna stránka reaguje kódom 200, keď je offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Táto stránka sa nemusí načítavať offline, pretože testovacia webová adresa ({requested}) bola presmerovaná na {final}. Skúste priamo otestovať druhú webovú adresu."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Toto sú možnosti zlepšenia technológie ARIA vo vašej aplikácii, čo môže pomôcť používateľom asistenčných technológií (napr. čítačiek obrazovky)."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Toto sú možnosti na poskytnutie alternatívneho obsahu pre zvuk a video. Môže to zlepšiť dojem používateľov so slabým sluchom alebo zrakom."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Zvuk a video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Tieto položky zvýrazňujú bežné osvedčené postupy týkajúce sa dostupnosti."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Osvedčené postupy"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Tieto kontroly zvýrazňujú možnosti [zlepšenia dostupnosti vašej webovej aplikácie](https://developers.google.com/web/fundamentals/accessibility). Automaticky je možné zistiť iba podmnožinu problémov s dostupnosťou, preto sa odporúča ručné testovanie."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Tieto položky sa zaoberajú oblasťami, ktoré automatické testovanie nemôže obsiahnuť. Ďalšie informácie získate v [sprievodcovi vykonávaním kontroly dostupnosti](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Dostupnosť"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Toto sú možnosti vylepšenia čitateľnosti obsahu."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Toto sú možnosti zlepšenia interpretácie vášho obsahu používateľmi rôznych jazykov."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizácia a lokalizácia"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Toto sú možnosti vylepšenia sémantiky ovládacích prvkov vašej aplikácie. Môže to pomôcť používateľom asistenčných technológií, ako sú čítačky obrazovky."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Názvy a štítky"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Toto sú možnosti zlepšenia prechádzania vašej aplikácie pomocou klávesnice."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigácia"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Toto sú možnosti na zlepšenie dojmu z čítania údajov v tabuľke alebo zozname pomocou asistenčných technológií, ako je čítačka obrazovky."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabuľky a zoznamy"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Osvedčené postupy"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Rozpočty výkonnosti sú štandardy výkonnosti vášho webu."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Rozpočty"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Ďalšie informácie o výkonnosti vašej aplikácie. Tieto hodnoty [priamo ovplyvňujú](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) skóre výkonnosti."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Najpodstatnejší aspekt výkonnosti je čas, za ktorý sa pixely vykreslia na obrazovke. Kľúčové metriky: Prvé obsahové vyfarbenie, Prvé účelné vyfarbenie."
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Vylepšenia prvého vyfarbenia"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Tieto návrhy môžu pomôcť s rýchlejším načítavaním vašej stránky. [Neovplyvňujú priamo](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) skóre výkonnosti."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Príležitosti"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metriky"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Vylepšite celkové načítavanie, aby bola stránka čo najskôr responzívna a pripravená na použitie. Kľúčové metriky: Čas do interaktívneho vykreslenia, Index rýchlosti"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Celkové vylepšenia"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Výkonnosť"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Tieto kontroly overujú aspekty progresívnej webovej aplikácie. [Ďalšie informácie](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Tieto kontroly vyžaduje základný [kontrolný zoznam PWA](https://developers.google.com/web/progressive-web-apps/checklist), ale Lighthouse ich automaticky nevykonáva. Nemajú vplyv na vaše skóre, ale je dôležité, aby ste ich overili ručne."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresívna webová aplikácia"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Rýchle a spoľahlivé"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Inštalovateľné"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimalizované pre PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Tieto kontroly zaisťujú, že vaša stránka je optimalizovaná pre hodnotenie výsledkov vyhľadávačov. Existujú ďalšie faktory, ktoré Lighthouse nekontroluje a ktoré by mohli ovplyvniť vaše hodnotenie v rámci vyhľadávania. [Ďalšie informácie](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Ak chcete skontrolovať ďalšie osvedčené postupy SEO, spusťte na svojom webe tieto ďalšie nástroje na overenie."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Naformátujte kód HTML svojej aplikácie spôsobom, ktorý umožní prehľadávačom lepšie pochopiť jej obsah."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Osvedčené postupy pre obsah"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Prehľadávače potrebujú prístup k vašej aplikácii, aby sa mohla zobraziť vo výsledkoch vyhľadávania."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Prehľadávanie a indexovanie"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Upravte svoje stránky pre mobilné zariadenia, aby používatelia pri čítaní ich obsahu nemuseli sťahovať prsty ani približovať. [Ďalšie informácie](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Vhodné pre mobilné zariadenia"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL vyrovnávacej pamäte"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Umiestnenie"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Názov"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Žiadosti"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Typ zdroja"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Veľkosť"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Strávený čas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Veľkosť prenosu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "Webová adresa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potenciálna úspora"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potenciálna úspora"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potenciálna úspora: {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potenciálna úspora: {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Písmo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Obrázok"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Médiá"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Iné"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Šablóna štýlu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tretia strana"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Celkovo"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Pri zaznamenávaní stopy načítania stránky sa vyskytol problém. Znova spustite Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Časový limit čaká na počiatočné pripojenie protokolu ladiaceho nástroja."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome počas načítavania stránky nevytvoril žiadne snímky obrazovky. Skontrolujte, či je na stránke viditeľný obsah, a potom skúste znova spustiť Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Servery DNS nedokázali rozpoznať poskytnutú doménu."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "V súvislosti s požadovaným zberačom {artifactName} sa vyskytla chyba: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Vyskytla sa interná chyba Chromu. Reštartujte Chrome a skúste nástroj Lighthouse spustiť znova."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Požadovaný zberač {artifactName} nebol spustený."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Nástroj Lighthouse nedokázal spoľahlivo načítať požadovanú stránku. Skontrolujte, či testujete správnu webovú adresu a či server správne odpovedá na všetky žiadosti."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Nástroj Lighthouse nedokázal spoľahlivo načítať webovú adresu, pretože stránka prestala reagovať."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Poskytnutá webová adresa nemá platný bezpečnostný certifikát. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome zabránil načítaniu stránky s intersticiálnou reklamou. Skontrolujte, či testujete správnu webovú adresu a server správne reaguje na všetky žiadosti."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Nástroj Lighthouse nedokázal spoľahlivo načítať požadovanú stránku. Skontrolujte, či testujete správnu webovú adresu a server správne reaguje na všetky žiadosti. (Podrobnosti: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Nástroj Lighthouse nedokázal spoľahlivo načítať požadovanú stránku. Skontrolujte, či testujete správnu webovú adresu a server správne reaguje na všetky žiadosti. (Kód stavu: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Načítanie stránky trvalo príliš dlho. Riaďte sa príležitosťami v prehľade a skráťte tak načítavanie stránky. Potom skúste Lighthouse znova spustiť. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Čakanie na odpoveď protokolu DevTools presiahlo pridelený čas. (Metóda: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Pri načítaní obsahu zdroja bol prekročený pridelený čas"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Poskytnutá webová adresa je zrejme neplatná."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Zobraziť kontroly"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Počiatočná navigácia"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maximálna latencia cesty dôležitých žiadostí:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Chyba!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Nahlásenie chyby: žiadne informácie o kontrole"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Údaje laboratória"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analýza aktuálnej stránky v emulovanej mobilnej sieti nástrojom [Lighthouse](https://developers.google.com/web/tools/lighthouse/). Hodnoty sú odhady, ktoré sa môžu líšiť."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Ďalšie položky na manuálnu kontrolu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nehodí sa"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Príležitosti"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Odhadovaná úspora"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Absolvované kontroly"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Zbaliť útržok"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Rozbaliť útržok"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Zobrazovať zdroje tretích strán"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Vyskytli sa problémy ovplyvňujúce funkčnosť nástroja Lighthouse:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Hodnoty sú odhady, ktoré sa môžu líšiť. Skóre výkonnosti je [založené iba na týchto metrikách](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Úspešne absolvované kontroly, ale s upozorneniami"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Upozornenia: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Zvážte nahranie gifu do služby, ktorá umožní jeho vloženie v podobe videa HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Nainštalujte si [doplnok WordPress na predbežné načítanie](https://wordpress.org/plugins/search/lazy+load/) poskytujúci možnosť odložiť všetky obrázky mimo obrazovky alebo prepnúť na motív, ktorý túto funkciu poskytuje. Tiež zvážte použitie [doplnku AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Existuje niekoľko doplnkov WordPress, ktoré vám pomôžu [vložiť do textu kľúčové podklady](https://wordpress.org/plugins/search/critical+css/) alebo [odložiť menej dôležité zdroje](https://wordpress.org/plugins/search/defer+css+javascript/). Dajte pozor, pretože optimalizácie poskytované týmito doplnkami môžu porušiť funkcie motívu či doplnkov, takže budete musieť zrejme zmeniť kód."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Čas odpovede servera ovplyvňujú motívy, doplnky a špecifikácie servera. Odporúčame nájsť optimalizovanejší motív, opatrne vybrať doplnok na optimalizáciu a/alebo aktualizovať server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Zvážte zobrazovanie úryvkov v zoznamoch príspevkov (napr. prostredníctvom značky Viac), znížte počet príspevkov zobrazovaných na danej stránke alebo rozdeľte dlhé príspevky na niekoľko stránok. Prípadne použite doplnok na predbežné načítavanie komentárov."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Niekoľko [doplnkov WordPress](https://wordpress.org/plugins/search/minify+css/) môže váš web zrýchliť konkatenáciou, minifikáciou a komprimáciou štýlov. Ak je to možné, tiež odporúčame túto minifikáciu vykonať vopred pomocou procesu zostavy."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Niekoľko [doplnkov WordPress](https://wordpress.org/plugins/search/minify+javascript/) môže váš web zrýchliť konkatenáciou, minifikáciou a komprimáciou skriptov. Ak je to možné, odporúčame túto minifikáciu vykonať vopred pomocou procesu zostavy."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Zvážte zníženie alebo prepnutie počtu [doplnkov WordPress](https://wordpress.org/plugins/) načítavajúcich nepoužívané šablóny CSS na stránke. Na identifikáciu doplnkov pridávajúcich externé šablóny CSS skúste spustiť funkciu [zahrnutia v kóde](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) v nástroji Chrome DevTools. Príslušný motív alebo doplnok môžete identifikovať pomocou webovej adresy danej šablóny štýlov. Nájdite doplnky, ktoré majú v zozname mnoho šablón štýlov s veľkým počtom červených hodnôt vo funkcii zahrnutia v kóde. Doplnok by mal šablónu štýlov zaradiť do poradia iba vtedy, keď sa používa na stránke."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Zvážte zníženie alebo prepnutie počtu [doplnkov WordPress](https://wordpress.org/plugins/) načítavajúcich nepoužívaný JavaScript na stránke. Doplnky pridávajúce externý JavaScript skúste identifikovať pomocou funkcie [zahrnutia v kóde](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) v nástroji Chrome DevTools. Príslušný motív alebo doplnok môžete identifikovať pomocou webovej adresy daného skriptu. Nájdite doplnky, ktoré majú v zozname mnoho skriptov s veľkým počtom červených hodnôt vo funkcii zahrnutia v kóde. Doplnok by nemal skript zaradiť do poradia, keď sa používa na stránke."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Prečítajte si o [ukladaní obsahu do vyrovnávacej pamäte prehliadača na webe WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Zvážte použitie [doplnku WordPress na optimalizáciu obrázkov](https://wordpress.org/plugins/search/optimize+images/), ktorý skomprimuje obrázky, ale zachová ich kvalitu."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Nahrajte obrázky priamo prostredníctvom [knižnice médií](https://codex.wordpress.org/Media_Library_Screen), čím zaistíte dostupnosť ich požadovaných veľkostí. Potom ich vložte z knižnice médií alebo zaistite použitie optimálnych veľkostí obrázkov pomocou ich miniaplikácií (vrátane tých, ktoré sú určené pre responzívne zlomové body). Obrázky s veľkosťou `Full Size` použite iba vtedy, keď sú dané rozmery vhodné na použitie. [Ďalšie informácie](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "V konfigurácii webového servera môžete povoliť kompresiu textu."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Zvážte použitie [doplnku](https://wordpress.org/plugins/search/convert+webp/) alebo služby, ktorá automaticky konvertuje nahrané obrázky do optimálnych formátov."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sl.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sl.json
new file mode 100644
index 00000000000..af11be3d80d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sl.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Tipke za dostop uporabnikom omogočajo hiter izbor dela strani. Za ustrezno pomikanje mora biti vsaka tipka za dostop drugačna. [Več o tem](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Vrednosti `[accesskey]` niso enolične"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Vrednosti `[accesskey]` so enolične"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Vsak element ARIA `role` podpira določen podniz atributov `aria-*`. Če se ne ujemajo, so atributi `aria-*` razveljavljeni. [Več o tem](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` se ne ujemajo z vlogami"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributi `[aria-*]` se ujemajo s svojimi vlogami"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Nekatere vloge ARIA imajo zahtevane atribute, ki opišejo stanje elementa bralnikom zaslona. [Več o tem](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Vloge `[role]` nimajo vseh zahtevanih atributov `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Vloge `[role]` imajo vse zahtevane atribute `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Nekatere nadrejene vloge ARIA morajo zaradi ustreznega izvajanja funkcij za ljudi s posebnimi potrebami vsebovati določene podrejene vloge. [Več o tem](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementi z vlogo ARIA `[role]`, ki zahtevajo, da podrejeni elementi vsebujejo določeno vlogo `[role]`, ne vsebujejo nekaterih ali vseh teh zahtevanih podrejenih elementov."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementi z vlogo ARIA `[role]`, ki zahtevajo, da podrejeni elementi vsebujejo določeno vlogo `[role]`, vsebujejo vse zahtevane podrejene elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Nekatere podrejene vloge ARIA morajo biti zaradi ustreznega izvajanja funkcij za ljudi s posebnimi potrebami vsebovane v določenih nadrejenih vlogah. [Več o tem](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Vloge `[role]` niso vsebovane v zahtevanem nadrejenem elementu"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Vloge `[role]` so vsebovane v zahtevanem nadrejenem elementu"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Vloge ARIA morajo imeti veljavne vrednosti, če želite, da bodo izvajale želene funkcije za ljudi s posebnimi potrebami. [Več o tem](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Vrednosti `[role]` niso veljavne"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Vrednosti `[role]` so veljavne"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Pomožne tehnologije, kot so bralniki zaslona, ne morejo tolmačiti atributov ARIA z neveljavnimi vrednostmi. [Več o tem](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Atributi `[aria-*]` nimajo veljavnih vrednosti"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Atributi `[aria-*]` imajo veljavne vrednosti"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Pomožne tehnologije, kot so bralniki zaslona, ne morejo tolmačiti atributov ARIA z neveljavnimi imeni. [Več o tem](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` so neveljavni ali napačno črkovani"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributi `[aria-*]` so veljavni in niso napačno črkovani"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Podnapisi poskrbijo, da so zvočni elementi uporabni za gluhe ali slušno prizadete tako, da zagotavljajo ključne informacije, na primer, kdo govori, kaj govori in druge neverbalne informacije. [Več o tem](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementi `<audio>` nimajo elementa `<track>` s podnapisi `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementi `<audio>` vsebujejo element `<track>` s podnapisi `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Neuspešni elementi"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Če gumb nima dostopnega imena, ga bralniki zaslona predstavijo kot »gumb«, s čimer je neuporaben za uporabnike, ki se zanašajo na bralnike zaslona. [Več o tem](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Gumbi nimajo dostopnega imena"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Gumbi imajo dostopna imena"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Če dodate načine, s katerimi je mogoče zaobiti ponavljajočo se vsebino, uporabnikom s tipkovnico omogočite učinkovitejše pomikanje po strani. [Več o tem](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Stran ne vsebuje naslova, povezave za preskok ali območja z mejnikom"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Stran vsebuje naslov, povezavo za preskok ali območje z mejnikom"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Besedilo z nizkim kontrastom številni uporabniki težko preberejo ali ga sploh ne morejo prebrati. [Več o tem](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Barve ozadja in ospredja nimajo zadostnega kontrastnega razmerja."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Barve ozadja in ospredja imajo zadostno kontrastno razmerje"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Če seznami opredelitev niso ustrezno označeni, lahko bralniki zaslona izgovorijo nejasno ali netočno vsebino. [Več o tem](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Elementi `<dl>` ne vsebujejo samo ustrezno razvrščenih skupin `<dt>` in `<dd>`, skripta `<script>` ali elementov `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Elementi `<dl>` vsebujejo samo ustrezno razvrščene skupine `<dt>` in `<dd>`, skript `<script>` ali elemente `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Elementi seznamov opredelitev (`<dt>` in `<dd>`) morajo biti zaradi zagotavljanja, da jih lahko bralniki zaslona ustrezno predstavijo, oviti z nadrejenim elementom `<dl>`. [Več o tem](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Elementi seznamov opredelitev niso oviti z elementi `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Elementi seznamov opredelitev so oviti z elementi `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Naslov uporabnikom bralnikov zaslona zagotavlja pregled strani, uporabniki iskalnikov pa se nanašajo nanj pri določanju, ali je stran pomembna za njihovo iskanje. [Več o tem](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument nima elementa `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument ima element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Vrednost atributa ID-ja mora biti enolična, če želite preprečiti, da bi pomožne tehnologije spregledale druge primerke. [Več o tem](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atributi `[id]` na strani niso enolični"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atributi `[id]` na strani so enolični"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Uporabniki bralnikov zaslona se zanašajo, da jim vsebino okvirjev opišejo naslovi okvirjev. [Več o tem](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementi `<frame>` ali `<iframe>` nimajo naslova"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementi `<frame>` ali `<iframe>` imajo naslov"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Če stran ne določi atributa »lang«, bralnik zaslona predvideva, da je stran v privzetem jeziku, ki ga je uporabnik izbral pri nastavljanju bralnika zaslona. Če stran ni v privzetem jeziku, bralnik zaslona morda ne bo pravilno predstavil besedila na strani. [Več o tem](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Element `<html>` nima atributa `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Element `<html>` ima atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Če določite veljaven [jezik BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), pomagate bralnikom zaslona ustrezno predstaviti besedilo [Več o tem](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Element `<html>` nima veljavne vrednosti za atribut `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Element `<html>` ima veljavno vrednost za svoj atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informativni elementi naj imajo kratko, opisno nadomestno besedilo. Okrasne elemente je mogoče prezreti s praznim nadomestnim atributom. [Več o tem](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elementi slik nimajo atributov `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elementi slik imajo atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Če se kot gumb `<input>` uporablja slika, lahko z navajanjem nadomestnega besedila uporabnikom bralnikov zaslona pomagate razumeti namen gumba. [Več o tem](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementi `<input type=\"image\">` nimajo besedila `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementi `<input type=\"image\">` imajo besedilo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Oznake zagotavljajo, da pomožne tehnologije, na primer bralniki zaslona, ustrezno predstavijo kontrolnike za obrazce. [Več o tem](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Elementi obrazcev nimajo povezanih oznak"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Elementi obrazcev imajo povezane oznake"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabela, ki se uporablja za namene postavitve, ne sme vsebovati podatkovnih elementov, na primer elementov »th« oziroma podnapisov ali atributa povzetka, ker lahko to privede do zavajajoče izkušnje za uporabnike bralnikov zaslona. [Več o tem](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Elementi predstavitvene razpredelnice `<table>` se ne izogibajo uporabi atributa `<th>`, `<caption>` ali `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Elementi predstavitvene razpredelnice `<table>` se izogibajo uporabi atributa `<th>`, `<caption>` ali `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Besedilo za povezavo (in nadomestno besedilo za slike, kadar so uporabljene kot povezave), ki je prepoznavno in edinstveno ter ga je mogoče izbrati, uporabnikom bralnikov zaslona zagotavlja boljšo izkušnjo pomikanja. [Več o tem](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Povezave nimajo prepoznavnega imena"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Povezave imajo prepoznavno ime"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Bralniki zaslona predstavljajo sezname na poseben način. Če želite doprinesti h kakovostnejši izgovorjavi bralnikov zaslona, poskrbite za ustrezno strukturo seznamov. [Več o tem](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Seznami ne vsebujejo samo elementov `<li>` in elementov, ki podpirajo skripte (`<script>` in `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Seznami vsebujejo samo elemente `<li>` in elemente, ki podpirajo skripte (`<script>` in `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Bralniki zaslona zahtevajo, da so elementi seznamov (`<li>`) vsebovani v nadrejenih elementih `<ul>` ali `<ol>`, da jih lahko ustrezno predstavijo. [Več o tem](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Elementi seznamov (`<li>`) niso vsebovani v nadrejenih elementih `<ul>` ali `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Elementi seznamov (`<li>`) so vsebovani v nadrejenih elementih `<ul>` ali `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Uporabniki ne pričakujejo samodejne osvežitve strani. Če se to zgodi, se izbira pomakne nazaj na vrh strani. To lahko privede do zoprne ali zavajajoče izkušnje. [Več o tem](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokument uporablja `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokument ne uporablja `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Onemogočanje povečave/pomanjšave je težavno za slabovidne uporabnike, ki se zanašajo na povečavo zaslona, da lahko ustrezno vidijo vsebino spletne strani. [Več o tem](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Lastnosti prilagajanja velikosti `[user-scalable=\"no\"]` se uporabljajo v elementu `<meta name=\"viewport\">` ali pa je atribut `[maximum-scale]` manjši od 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Lastnosti prilagajanja velikosti `[user-scalable=\"no\"]` se ne uporabljajo v elementu `<meta name=\"viewport\">` in atribut `[maximum-scale]` ni manjši od 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Bralniki zaslona ne morejo prevesti vsebine, ki ni besedilna. Če elementom `<object>` dodate nadomestno besedilo, bralnikom zaslona pomagate prenesti pomen uporabnikom. [Več o tem](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementi `<object>` nimajo besedila `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementi `<object>` imajo besedilo `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Vrednost, večja od 0, kaže na izrecno razporeditev pomikanja. Čeprav je načeloma veljavna, pogosto vodi v zoprne izkušnje za uporabnike, ki se zanašajo na pomožne tehnologije. [Več o tem](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Nekateri elementi imajo vrednost za `[tabindex]` večjo od 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Noben element nima večje vrednosti za `[tabindex]` od 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Bralniki zaslona imajo funkcije za preprostejše pomikanje po razpredelnicah. Če zagotovite, da se celice `<td>`, ki uporabljajo atribut `[headers]`, nanašajo samo na druge celice v isti razpredelnici, lahko izboljšate izkušnjo za uporabnike bralnikov zaslona. [Več o tem](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Celice v elementu `<table>`, ki uporabljajo atribut `[headers]`, se nanašajo na element `id`, ki ga ni mogoče najti v isti razpredelnici."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Celice v elementu `<table>`, ki uporabljajo atribut `[headers]`, se nanašajo na celice razpredelnice v isti razpredelnici."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Bralniki zaslona imajo funkcije za preprostejše pomikanje po razpredelnicah. Če zagotovite, da se glave razpredelnic vedno nanašajo na določen nabor celic, lahko izboljšate izkušnjo za uporabnike bralnikov zaslona. [Več o tem](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementi `<th>` in elementi z glavami `[role=\"columnheader\"/\"rowheader\"]` nimajo podatkovnih celic, ki jih opisujejo."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementi `<th>` in elementi z glavami `[role=\"columnheader\"/\"rowheader\"]` imajo podatkovne celice, ki jih opisujejo."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Če za elemente določite veljaven [jezik BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), pomagate zagotoviti, da bralnik zaslona pravilno izgovori besedilo. [Več o tem](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Atributi `[lang]` nimajo veljavne vrednosti"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributi `[lang]` imajo veljavno vrednost"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Če ima videoposnetek dodan podnapis, lahko gluhi in slušno prizadeti uporabniki preprosteje dostopajo do informacij, ki jih podaja. [Več o tem](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementi `<video>` ne vsebujejo elementa `<track>` z opisom `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementi `<video>` vsebujejo element `<track>` s podnapisi `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Zvočni opisi zagotavljajo pomembne informacije glede videoposnetkov, ki jih sam dialog ne more, na primer opisujejo obrazne izraze in prizore. [Več o tem](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementi `<video>` ne vsebujejo elementa `<track>` z opisom `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementi `<video>` vsebujejo element `<track>` s podnapisi `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Za idealen prikaz v iOSu, ko uporabniki dodajo moderno spletno aplikacijo na začetni zaslon, določite to: `apple-touch-icon`. Kazati mora na neprosojno kvadratno datoteko PNG velikosti 192 (ali 180) slikovnih pik. [Več o tem](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Ne vsebuje veljavne vrednosti `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` je zastarel; prednostni je `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Vsebuje veljavno vrednost `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Razširitve za Chrome so negativno vplivale na nalaganje te strani. Poskusite pregledati to stran v načinu brez beleženja zgodovine ali v profilu za Chrome brez razširitev."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Ocenjevanje skripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Razčlenitev skripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Skupni čas CPE"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Razmislite o skrajšanju časa, ki ga porabite za razčlenjevanje, prevajanje in izvajanje JavaScripta. Ugotovili boste, da vam lahko pri tem morda pomaga dostavljanje manjših paketov koristne vsebine JavaScript. [Več o tem](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Skrajšajte čas izvajanja JavaScripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Čas izvajanja JavaScripta"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Veliki GIF-i so neučinkoviti za dostavljanje animirane vsebine. Razmislite o uporabi videoposnetkov MPEG4/WebM za animacije in slik PNG/WebP za statične slike namesto GIF-ov, s čimer prihranite omrežne bajte. [Več o tem](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Uporabite oblike zapisa videoposnetkov za animirano vsebino"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Razmislite o odloženem nalaganju slik zunaj zaslona in skritih slik po dokončanem nalaganju kritičnih sredstev zaradi skrajšanja časa do interaktivnosti strani. [Več o tem](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Odložite nalaganje slik, ki so zunaj zaslona"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Sredstva blokirajo prvo barvanje strani. Razmislite o sprotnem dostavljanju kritičnega JavaScripta/CSS-ja in odlaganju JavaScripta/slogov, ki ni oziroma niso kritični. [Več o tem](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Izločite sredstva, ki blokirajo upodabljanje"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Veliki omrežni paketi koristne vsebine uporabnikom povzročajo dejanske stroške in so tesno povezani z dolgimi časi nalaganja. [Več o tem](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Skupna velikost je bila {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Izogibajte se velikanskim omrežnim paketom koristne vsebine"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Izogiba se velikanskim omrežnim paketom koristne vsebine"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Z zmanjšanjem datotek CSS-ja lahko zmanjšate velikosti paketov koristne vsebine. [Več o tem](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Zmanjšajte CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Z zmanjšanjem datotek JavaScript lahko zmanjšate velikosti paketov koristne vsebine in skrajšate čas razčlenjevanja skriptov. [Več o tem](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Pomanjšajte JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Iz slogovnih datotek odstranite nedejavna pravila in odložite nalaganje CSS-ja, ki se ne uporablja za vsebino na vrhu strani, ter tako zmanjšajte nepotrebno porabo bajtov v omrežni dejavnosti. [Več o tem](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Odstranitev neuporabljenega CSS-ja"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Odstranite neuporabljeni JavaScript, če želite zmanjšati število bajtov, uporabljenih v omrežni dejavnosti."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Odstranite neuporabljeni JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Dolgotrajno predpomnjenje lahko pospeši vnovične obiske strani. [Več o tem](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Najdeno je bilo 1 sredstvo}one{Najdeno je bilo # sredstvo}two{Najdeni sta bili # sredstvi}few{Najdena so bila # sredstva}other{Najdenih je bilo # sredstev}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Dostavljajte statična sredstva z učinkovitim pravilnikom o predpomnjenju"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Uporaba pravilnika o učinkovitem predpomnjenju za statična sredstva"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimizirane slike se nalagajo hitreje in terjajo manj prenesenih podatkov v mobilnih omrežjih. [Več o tem](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Učinkovito kodirajte slike"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Prikazujte slike primerne velikosti, s čimer poskrbite za prihranek prenesenih podatkov v mobilnih omrežjih in izboljšate čas nalaganja. [Več o tem](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Uporabite slike ustrezne velikosti"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Pri dostavi besedilnih sredstev uporabite stiskanje (gzip, deflate ali brotli) zaradi zmanjšanja skupnega števila omrežnih bajtov. [Več o tem](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Omogočite stiskanje besedila"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Oblike zapisa slik, kot so JPEG 2000, JPEG XR in WebP, pogosto omogočajo učinkovitejše stiskanje kot oblika zapisa PNG ali JPEG, kar pomeni hitrejše prenose in manjšo porabo podatkov. [Več o tem](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Dostavljajte slike v sodobnih oblikah zapisa"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Če se širina vsebine aplikacije ne ujema s širino vidnega polja, aplikacija morda ni optimizirana za zaslone mobilnih naprav. [Več o tem](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Velikost vidnega območja, ki znaša {innerWidth} slikovnih pik, se ne ujema z velikostjo okna, ki znaša {outerWidth} slikovnih pik."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Vsebina ni ustrezne velikosti za vidno območje"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Vsebina je ustrezne velikosti za vidno območje"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Verige kritičnih zahtev spodaj vam prikazujejo, katera sredstva so naložena z visoko prednostjo. Razmislite o skrajšanju verig, zmanjšanju velikosti sredstev ali odlaganju prenosa nepotrebnih sredstev zaradi izboljšanja nalaganja strani. [Več o tem](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Najdena je bila 1 veriga}one{Najdena je bila # veriga}two{Najdeni sta bili # verigi}few{Najdene so bile # verige}other{Najdenih je bilo # verig}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Zmanjšajte globino kritičnih zahtev"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Zastaranje/opozorilo"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Vrstica"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Zastareli API-ji bodo sčasoma odstranjeni iz brskalnika. [Več o tem](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Najdeno je bilo 1 opozorilo}one{Najdeno je bilo # opozorilo}two{Najdeni sta bili # opozorili}few{Najdena so bila # opozorila}other{Najdenih je bilo # opozoril}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Uporablja zastarele API-je"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Izogiba se zastarelim API-jem"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Predpomnilnik aplikacij je zastarel. [Več o tem](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Najdeno – »{AppCacheManifest}«"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Uporablja predpomnilnik aplikacij"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Izogiba se predpomnilniku aplikacij"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Če določite doctype, brskalnik ne more preklopiti v način »quirks«. [Več o tem](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Ime doctype mora biti niz z majhnimi črkami `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument mora vsebovati doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Pričakovano je bilo, da je publicid prazen niz"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Pričakovano je bilo, da je systemid prazen niz"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Stran nima HTML-doctype, zato se sproži način »quirks«"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Stran ima HTML-doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistični podatek"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Vrednost"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Inženirji za brskalnike priporočajo, da strani vsebujejo manj kot približno 1500 elementov DOM. Idealna vrednost je globina drevesa z manj kot 32 elementi in manj kot 60 podrejenimi/nadrejenimi elementi. Velik DOM lahko povzroči povečano uporabo pomnilnika, daljše [slogovne izračune](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) in drage [prilagoditve postavitve](https://developers.google.com/speed/articles/reflow). [Več o tem](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}one{# element}two{# elementa}few{# elementi}other{# elementov}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Izogibajte se prekomerni velikosti DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Največja globina DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Skupno število elementov DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Največje število podrejenih elementov"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Izogiba se prekomerni velikosti DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cilj"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Zunanjim povezavam dodajte `rel=\"noopener\"` ali `rel=\"noreferrer\"` zaradi izboljšanja delovanja in preprečevanja varnostnih ranljivosti. [Več o tem](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Povezave do ciljev iz več izvorov niso varne"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Povezave do ciljev iz več izvorov so varne"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Ni mogoče določiti cilja za sidro ({anchorHTML}). Če se ne uporablja kot hiperpovezava, lahko odstranite target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Uporabniki so nezaupljivi do spletnih mest oziroma jih begajo spletna mesta, ki zahtevajo njihovo lokacijo brez konteksta. Razmislite o tem, da bi zahtevo povezali z uporabniškim dejanjem. [Več o tem](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Zahteva dovoljenje za geolokacijo pri nalaganju strani"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Ne zahteva dovoljenja za geolokacijo pri nalaganju strani"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Različica"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Vse knjižnice JavaScript vmesnikov, zaznane na strani. [Več o tem](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Zaznane knjižnice JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Pri uporabnikih s počasnimi povezavami lahko zunanji skripti, dinamično vstavljeni prek `document.write()`, zakasnijo nalaganje strani za več deset sekund. [Več o tem](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Uporablja `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Se izogiba `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Največja resnost"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Različica knjižnice"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Štetje ranljivosti"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Nekateri skripti drugih ponudnikov morda vsebujejo znane varnostne ranljivosti, ki jih napadalci lahko preprosto prepoznajo in izkoristijo. [Več o tem](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Zaznana je bila 1 ranljivost}one{Zaznana je bila # ranljivost}two{Zaznani sta bili # ranljivosti}few{Zaznane so bile # ranljivosti}other{Zaznanih je bilo # ranljivosti}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Vključuje knjižniceJavaScript vmesnikov z znanimi varnostnimi ranljivostmi"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Visoka"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Nizka"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Srednja"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Izogiba se knjižnicam JavaScript vmesnikov z znanimi varnostnimi ranljivostmi"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Uporabniki so nezaupljivi do spletnih mest oziroma jih begajo spletna mesta, ki zahtevajo pošiljanje obvestil brez konteksta. Razmislite o tem, da bi zahtevo povezali z uporabniškimi potezami. [Več o tem](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Zahteva dovoljenje za obvestila pri nalaganju strani"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Ne zahteva dovoljenja za obvestila pri nalaganju strani"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Neuspešni elementi"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Preprečevanje lepljenja gesel omeji dober pravilnik o varnosti. [Več o tem](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Uporabnikom preprečuje lepljenje v polja za gesla"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Uporabnikom omogoča lepljenje v polja za gesla"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ima več prednosti pred HTTP/1.1, vključno z binarnimi glavami, multipleksiranjem in potisnimi sredstvi iz strežnika. [Več o tem](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 zahteva ni bila poslana prek HTTP/2}one{# zahteva ni bila poslana prek HTTP/2}two{# zahtevi nista bili poslani prek HTTP/2}few{# zahteve niso bile poslane prek HTTP/2}other{# zahtev ni bilo poslanih prek HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Ne uporablja HTTP/2 za vsa svoja sredstva"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Uporablja HTTP/2 za svoja sredstva"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Posluševalnike dogodkov dotika in kolesca lahko označite kot `passive` zaradi izboljšanja delovanja pomikanja na strani. [Več o tem](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Ne uporablja pasivnih poslušalcev za izboljšanje delovanja pomikanja"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Uporablja pasivne poslušalce za izboljšanje delovanja pomikanja"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Opis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Napake, zabeležene v konzoli, označujejo nerazrešene težave. Te so lahko posledica neuspešnih omrežnih zahtev in drugih težav z brskalnikom. [Več o tem](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Napake brskalnika so bile zabeležene v konzoli"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "V konzoli ni bila zabeležena nobena napaka brskalnika"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Izkoristite funkcijo CSS-ja za prikaz pisave, s čimer poskrbite, da je med nalaganjem spletne pisave besedilo vidno uporabnikom. [Več o tem](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Poskrbite, da bo med nalaganjem spletne pisave besedilo ostalo vidno"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Vse besedilo ostaja vidno med nalaganjem spletne pisave"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Orodje Lighthouse ni utegnilo samodejno preveriti vrednosti font-display za naslednji URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Razmerje stranic (dejansko)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Razmerje stranic (prikazano)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Mere prikaza slike se morajo ujemati z naravnim razmerjem stranic. [Več o tem](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Prikazuje slike z nepravilnim razmerjem stranic"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Prikazuje slike s pravilnim razmerjem stranic"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Neveljavni podatki o velikosti slike {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Brskalniki lahko proaktivno pozovejo uporabnike, da dodajo vašo aplikacijo na začetni zaslon, kar lahko privede do več dejavnosti. [Več o tem](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifest spletne aplikacije ne izpolnjuje zahtev za izvedljivost namestitve"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifest spletne aplikacije izpolnjuje zahteve za izvedljivost namestitve"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL zahtev, ki niso varne"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Vsa spletna mesta morajo biti zaščitena s HTTPS, tudi tista, ki nimajo opravka z občutljivimi podatki. HTTPS vsiljivcem preprečuje manipuliranje s komunikacijami ali pasivno poslušanje komunikacij med aplikacijo in uporabniki ter je pogoj za HTTP/2 in veliko novih API-jev za spletna okolja. [Več o tem](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Najdena je bila 1 zahteva, ki ni varna}one{Najdena je bila # zahteva, ki ni varna}two{Najdeni sta bili # zahtevi, ki nista varni}few{Najdene so bile # zahteve, ki niso varne}other{Najdenih je bilo # zahtev, ki niso varne}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Ne uporablja HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Uporablja HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Hitro nalaganje strani prek mobilnega omrežja zagotavlja dobro uporabniško izkušnjo pri uporabi mobilnih naprav. [Več o tem](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktivno ob {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktivno v simuliranem mobilnem omrežju ob {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Stran se nalaga prepočasi in ni interaktivna v 10 sekundah. Oglejte si priložnosti in diagnostiko v razdelku »Delovanje«, če želite izvedeti, kako do izboljšanja."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Nalaganje strani ni dovolj hitro v mobilnih omrežjih"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Nalaganje strani je dovolj hitro v mobilnih omrežjih"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorija"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Razmislite o skrajšanju časa, ki ga porabite za razčlenjevanje, prevajanje in izvajanje JavaScripta. Ugotovili boste, da vam lahko pri tem morda pomaga dostavljanje manjših paketov koristne vsebine JavaScript. [Več o tem](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minimizirajte delo glavne niti"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minimizira delo glavne niti"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Če želite doseči največ uporabnikov, morajo spletna mesta delovati v vsakem pomembnejšem brskalniku. [Več o tem](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Spletno mesto deluje v različnih brskalnikih"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Zagotovite povezave v globino do posameznih strani prek URL-jev in poskrbite, da so zaradi objavljanja v družbenih omrežjih ti URL-ji enolični. [Več o tem](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Vsaka stran ima URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Prehodi morajo ob dotikanju delovati hitro in tekoče tudi v počasnem omrežju. To je ključno za uporabnikov vtis zmogljivega delovanja. [Več o tem](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Prehodi med stranmi ne dajejo občutka, kot da so blokirani v omrežju"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Predvidena vhodna zakasnitev je ocena, koliko milisekund potrebuje vaša aplikacija za odziv na uporabnikovo dejavnost med najaktivnejšimi 5 sekundami pri nalaganju strani. Če je zakasnitev večja od 50 ms, se lahko uporabnikom zdi, da se aplikacija zatika. [Več o tem](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Ocenjena zakasnitev vnosa"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Prvi vsebinski izris označuje čas, ko je izrisano prvo besedilo oziroma je izrisana prva slika. [Več o tem](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Prvo vsebinsko barvanje"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Prva nedejavnost CPE-ja označuje čas, po katerem je glavna nit strani dovolj neobremenjena, da lahko obravnava vnos. [Več o tem](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Prva nedejavnost CPE-ja"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Prvo smiselno barvanje meri, kdaj je vidna glavna vsebina strani. [Več o tem](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Prvo smiselno barvanje"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Čas do interaktivnosti je čas, potreben, da stran postane povsem interaktivna. [Več o tem](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Čas do interaktivnosti"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Največja potencialna zakasnitev od prvega vnosa, na katero lahko uporabniki naletijo, je trajanje (v ms) najdaljšega opravila. [Več o tem](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Najv. potencial. zakasn. od prvega vnosa"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indeks hitrosti prikazuje, kako hitro je vsebina strani vidno izpolnjena. [Več o tem](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indeks hitrosti"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Skupek vseh časovnih obdobij med FCP-jem in časom do interaktivnosti, ko je dolžina opravila presegla 50 ms, izražena v milisekundah."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Skupni čas blokiranja"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Omrežni časi povratnega potovanja (RTT) imajo velik vpliv na učinkovitost delovanja. Če je RTT do izvora velik, to kaže na to, da bi lahko strežniki bližje uporabniku izboljšali učinkovitost delovanja. [Več o tem](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Časi omrežnega povratnega potovanja"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Na spletno učinkovitost delovanja lahko vplivajo zakasnitve strežnikov. Če je zakasnitev strežnika za izvor velika, to kaže na to, da je strežnik preobremenjen ali ima slabo zaledno učinkovitost delovanja. [Več o tem](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Zakasnitve strežnikovega zaledja"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Proces storitve spletni aplikaciji omogoča zanesljivost v nepredvidljivih omrežnih okoliščinah. [Več o tem](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` se ne odzove s kodo stanja HTTP 200, ko nima povezave"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` se odzove s kodo stanja HTTP 200, ko nima povezave"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse ni mogel prebrati URL-ja `start_url` v manifestu. Za URL dokumenta se je posledično imelo ta URL: `start_url`. Sporočilo o napaki: »{manifestWarning}«."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Prek proračuna"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Količino in velikosti omrežnih zahtev imejte pod cilji, ki so nastavljeni z navedenim proračunom za uspešnost. [Več o tem](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 zahteva}one{# zahteva}two{# zahtevi}few{# zahteve}other{# zahtev}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Proračun za uspešnost"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Če ste že nastavili protokol HTTPS, poskrbite za preusmeritev vsega prometa prek protokola HTTP na protokol HTTPS, da zagotovite varne spletne funkcije vsem uporabnikom. [Več o tem](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Ne preusmeri prometa prek protokola HTTP na protokol HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Preusmeri promet prek protokola HTTP na protokol HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Preusmeritve vnašajo dodatne zakasnitve nalaganja strani. [Več o tem](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Izogibajte se preusmeritvam na več strani"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Če želite nastaviti proračune za količino in velikost sredstev strani, dodajte datoteko budget.json. [Več o tem](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 zahteva • {byteCount, number, bytes} KB}one{# zahteva • {byteCount, number, bytes} KB}two{# zahtevi • {byteCount, number, bytes} KB}few{# zahteve • {byteCount, number, bytes} KB}other{# zahtev • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Število zahtev naj bo majhno in prenosi naj ne bodo preveliki"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanonične povezave predlagajo, kateri URL naj bo prikazan v rezultatih iskanja. [Več o tem](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Več URL-jev v sporu ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Kaže na drugo domeno ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Neveljaven URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Kaže na drugo lokacijo `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativni URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Kaže na korenski URL domene (domačo stran), namesto na enakovredno stran z vsebino"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument nima veljavne povezave `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument ima veljaven atribut `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Velikosti pisave, manjše od 12 slikovnih pik, so premajhne, da bi bile berljive, zato morajo obiskovalci z mobilnimi napravami s potezo razširjanja prstov na zaslonu povečati strani, da bi jih lahko prebrali. Poskušajte zagotoviti, da bo več kot 60 % besedila na strani velikosti, ki ni manjša od 12 slikovnih pik. [Več o tem](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} berljivega besedila"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Besedilo je neberljivo, ker ni metaoznake »viewport«, optimizirane za zaslone mobilnih naprav."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} besedila je premajhnega (na podlagi {decimalProportionVisited, number, extendedPercent} vzorca)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokument ne uporablja berljivih velikosti pisav"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokument uporablja berljive velikosti pisav"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Povezave hreflang iskalnikom povedo, katero različico strani naj prikažejo v rezultatih iskanja za določen jezik ali regijo. [Več o tem](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument nima veljavnega atributa `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument ima veljaven atribut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Strani z neuspešnimi kodami stanja HTTP morda ne bodo pravilno indeksirane. [Več o tem](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Stran ima neuspešno kodo stanja HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Stran ima uspešno kodo stanja HTTP"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Če iskalniki nimajo dovoljenja za iskanje po vsebini vaših strani, jih ne morejo vključiti v rezultate iskanja. [Več o tem](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Indeksiranje strani je blokirano"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indeksiranje strani ni blokirano"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Opisno besedilo povezave iskalnikom pomaga razumeti vašo vsebino. [Več o tem](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Najdena je 1 povezava}one{Najdena je # povezava}two{Najdeni sta # povezavi}few{Najdene so # povezave}other{Najdenih je # povezav}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Povezave nimajo opisnega besedila"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Povezave imajo opisno besedilo"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Za preverjanje strukturiranih podatkov zaženite [orodje za preizkušanje strukturiranih podatkov](https://search.google.com/structured-data/testing-tool/) in [orodje Linter za strukturirane podatke](http://linter.structured-data.org/). [Več o tem](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturirani podatki so veljavni"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Za podroben povzetek vsebine strani so lahko v rezultatih iskanja vključeni metaopisi. [Več o tem](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Opisno besedilo je prazno."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument nima metaopisa"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument ima metaopis"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Iskalniki ne morejo indeksirati vsebine vtičnikov in številne naprave vtičnike omejujejo ali jih ne podpirajo. [Več o tem](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument uporablja vtičnike"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument ne vsebuje vtičnikov"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Če datoteka robots.txt ni pravilno oblikovana, iskalniki po spletni vsebini morda ne bodo razumeli, kako želite, da se išče po spletni vsebini vašega spletnega mesta in se jo indeksira. [Več o tem](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Zahteva za datoteko robots.txt je vrnila to stanje HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Najdena je bila 1 napaka}one{Najdena je bila # napaka}two{Najdeni sta bili # napaki}few{Najdene so bile # napake}other{Najdenih je bilo # napak}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse ni mogel prenesti datoteke robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Datoteka robots.txt ni veljavna"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Datoteka robots.txt je veljavna"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktivni elementi, kot so gumbi in povezave, morajo biti dovolj veliki (48 x 48 slikovnih pik) in okoli njih mora biti dovolj prostora, da se jih je mogoče dotakniti, ne da bi se pri tem dotaknili drugih elementov. [Več o tem](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} ciljev dotika primerne velikosti"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Cilji za dotik so premajhni, ker ni metaoznake »viewport«, optimizirane za zaslone mobilnih naprav."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Cilji za dotik niso primerne velikosti"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Prekrivajoči se cilj"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Cilj za dotik"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Cilji za dotikanje so ustrezne velikosti"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Proces storitve je tehnologija, ki aplikaciji omogoča uporabo številnih funkcij moderne spletne aplikacije, na primer delovanje brez povezave, dodajanje na začetni zaslon in potisna obvestila. [Več o tem](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "To stran nadzira proces storitve, vendar ni bilo mogoče najti ničesar od tega: `start_url`, ker ni bilo mogoče razčleniti manifesta kot veljavne datoteke JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "To stran nadzira proces storitve, vendar `start_url` ({startUrl}) ni v obsegu procesa storitve ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "To stran nadzira proces storitve, vendar ni bilo mogoče najti ničesar od tega: `start_url`, ker niso bili preneseni manifesti."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ta izvor ima enega ali več procesov storitve, vendar stran ({pageUrl}) ni v obsegu."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Ne registrira procesa storitve, ki nadzira stran in to: `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registrira proces storitve, ki nadzira stran in to: `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "S tematskim pozdravnim zaslonom zagotovite visokokakovostno izkušnjo, ko uporabniki zaženejo aplikacijo z začetnih zaslonov. [Več o tem](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Ni konfigurirano za pozdravni zaslon po meri"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigurirano za pozdravni zaslon po meri"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Naslovno vrstico brskalnika je mogoče prilagoditi s temo, ki se ujema s spletnim mestom. [Več o tem](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Ne nastavi barve teme za naslovno vrstico."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Nastavi barvo teme za naslovno vrstico."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Čas blokiranja glavne niti"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Drugi ponudniki"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Koda drugega ponudnika lahko znatno vpliva na učinkovitost nalaganja. Omejite število odvečnih drugih ponudnikov in poskusite naložiti kodo drugega ponudnika, ko je stran prvenstveno končala nalaganje. [Več o tem](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Koda drugega ponudnika je blokirala glavno nit {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Zmanjšanje vpliva kode drugega ponudnika"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Uporaba drugih ponudnikov"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "»Čas do prvega bajta« navaja čas, v katerem vaš strežnik pošlje odziv. [Več o tem](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Korenski dokument je terjal {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Skrajšajte odzivne čase strežnika (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Odzivni časi strežnika so nizki (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trajanje"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Začetni čas"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Vrsta"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Razmislite o uporabi API-ja za merjenje dejanskih izvedb uporabniških dogodkov (User Timing API), če želite izmeriti dejansko delovanje aplikacije med ključnimi uporabniškimi izkušnjami. [Več o tem](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 trajanje izvedbe uporabniških dogodkov}one{# trajanje izvedbe uporabniških dogodkov}two{# trajanji izvedbe uporabniških dogodkov}few{# trajanja izvedbe uporabniških dogodkov}other{# trajanj izvedbe uporabniških dogodkov}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Oznake in merjenja trajanj izvedbe uporabniških dogodkov"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Povezava <link> za vnaprejšnje povezovanje je bila najdena za »{securityOrigin}«, vendar je brskalnik ni uporabil. Preverite, ali pravilno uporabljate atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Razmislite o dodajanju namigov za sredstva (`preconnect` ali `dns-prefetch`) zaradi vzpostavljanja zgodnjih povezav s pomembnimi izvori drugih ponudnikov. [Več o tem](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Vnaprej se povežite z zahtevanimi izvori"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Najden je bil element <link> za »{preloadURL}«, vendar ga brskalnik ni uporabil. Preverite, ali pravilno uporabljate atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Razmislite o uporabi oznake `<link rel=preload>` za dodeljevanje višje stopnje prednosti pri pridobivanju sredstev, ki so trenutno zahtevana pri nadaljnjem nalaganju strani. [Več o tem](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Vnaprej nalagajte ključne zahteve"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Dodajte oznako `<meta name=\"viewport\">`, da optimizirate aplikacijo za zaslone mobilnih naprav. [Več o tem](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Ni oznak `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nima oznake `<meta name=\"viewport\">` s tem: `width` ali `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ima oznako `<meta name=\"viewport\">` s tem: `width` ali `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Aplikacija bi morala prikazati nekaj vsebine, če je JavaScript onemogočen, četudi zgolj opozorilo uporabniku, da uporaba aplikacije terja JavaScript. [Več o tem](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Telo strani bi moralo upodobiti nekaj vsebine, če njeni skripti niso na voljo."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Ne zagotavlja nadomestne vsebine, ko JavaScript ni na voljo"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Vsebuje nekaj vsebine, ko JavaScript ni na voljo"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Če ustvarjate moderno spletno aplikacijo, razmislite o uporabi procesa storitve, da lahko aplikacija deluje brez povezave. [Več o tem](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Trenutna stran se ne odzove s kodo stanja HTTP 200, ko nima povezave"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Trenutna stran se odzove s kodo stanja HTTP 200, ko nima povezave"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Stran se morda ne naloži brez povezave, ker je bil preizkusni URL ({requested}) preusmerjen na »{final}«. Poskusite neposredno preizkusiti drugi URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Tu imate na voljo priložnosti, da izboljšate uporabo atributov ARIA v aplikaciji, s čimer lahko izboljšate izkušnjo za uporabnike pomožnih tehnologij, kot je bralnik zaslona."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "To so priložnosti za izboljšanje nadomestne vsebine za zvok in videoposnetke. S tem lahko izboljšate izkušnjo za uporabnike z motnjami sluha ali vida."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Zvok in video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ti elementi izpostavijo pogoste najboljše postopke za zagotavljanje dostopnosti."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Najboljši postopki"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ta preverjanja izpostavijo priložnosti za [izboljšanje dostopnosti vaše spletne aplikacije](https://developers.google.com/web/fundamentals/accessibility). Samodejno je mogoče ugotoviti samo podnabor morebitnih težav z dostopnostjo, zato spodbujamo ročno preverjanje."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ti elementi se nanašajo na področja, ki jih ne more obdelati samodejno orodje za preizkušanje. Več o tem lahko preberete v našem vodniku o [izvedbi pregleda dostopnosti](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Dostopnost"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Tu imate na voljo priložnosti, da izboljšate berljivost vsebine."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Tu imate na voljo priložnosti, da izboljšate, kako si uporabniki v različnih jezikih tolmačijo vašo vsebino."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizacija in lokalizacija"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Tu imate na voljo priložnosti, da izboljšate pomen kontrolnikov v aplikaciji. S tem lahko izboljšate izkušnjo uporabnikov pomožne tehnologije, kot je bralnik zaslona."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Imena in oznake"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "To so priložnosti, da izboljšate premikanje po aplikaciji s tipkovnico."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Pomikanje"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "To so priložnosti, da z uporabo pomožnih tehnologij, kot je bralnik zaslona, izboljšate izkušnjo pri branju tabelarnih podatkov ali podatkov na seznamih."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabele in seznami"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Najboljši postopki"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Proračuni za uspešnost postavljajo standarde za uspešnost spletnega mesta."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Proračuni"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Več informacij o delovanju aplikacije. Te številke [neposredno ne vplivajo](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na rezultat uspešnosti."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Bistveni vidik delovanja je, kako hitro se upodabljajo slikovne pike na zaslonu. Ključni meritvi: Prvo vsebinsko barvanje, Prvo smiselno barvanje"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Izboljšave prvega barvanja"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ti predlogi lahko pomagajo pri hitrejšem nalaganju strani. [Neposredno ne vplivajo](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na rezultat uspešnosti."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Priložnosti"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Meritve"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Izboljšajte splošno izkušnjo nalaganja, da bo stran odzivna in čim prej pripravljena na uporabo. Ključni meritvi: Čas do interaktivnosti, Indeks hitrosti"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Splošne izboljšave"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Delovanje"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Ta preverjanja potrjujejo vidike moderne spletne aplikacije. [Več o tem](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ta preverjanja zahteva osnovni [kontrolni seznam za MSA](https://developers.google.com/web/progressive-web-apps/checklist), vendar jih Lighthouse ne opravi samodejno. Preverjanja vplivajo na vaš rezultat, vendar je pomembno, da jih opravite ročno."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Moderna spletna aplikacija"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Hitro in zanesljivo"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Namestljivo"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizirano za PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "S temi preverjanji se zagotovi, da je stran optimizirana za uvrstitev v rezultatih iskanja. Na uvrstitev v rezultatih iskanja lahko vplivajo dodatni dejavniki, ki jih Lighthouse ne preverja. [Več o tem](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Na spletnem mestu izvedite ta dodatna preverjanja, da preverite dodatne najboljše postopke za SEO."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Oblikujte HTML na način, ki iskalnikom po vsebini omogoča boljše razumevanje vsebine vaše aplikacije."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Najboljši postopki glede vsebine"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Če želite, da bo prikazana v rezultatih iskanja, morajo imeti iskalniki po vsebini dostop do vaše aplikacije."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Iskanje po vsebini in indeksiranje"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Poskrbite, da so strani prilagojene za mobilne naprave, da uporabnikom ne bo treba vleči s prsti skupaj ali povečevati slike, če bodo želeli brati strani z vsebino. [Več o tem](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Prilagojeno za mobilne naprave"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL predpomnjenja"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokacija"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Ime"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Zahteve"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Vrsta sredstva"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Velikost"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Porabljeni čas"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Velikost prenosa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Morebitni prihranki"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Morebitni prihranki"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "{wastedBytes, number, bytes} KB morebitnega prihranka"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "{wastedMs, number, milliseconds} ms morebitnega prihranka"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Pisava"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Slika"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Predstavnost"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Drugo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Slogovna datoteka"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Drugi ponudniki"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Skupno"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Pri snemanju sledi ob nalaganju strani je prišlo do napake. Znova zaženite Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Potek časovne omejitve pri čakanju na začetno povezavo protokola za odpravljanje napak"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome med nalaganjem strani ni zbral posnetkov zaslona. Poskrbite, da je vsebina vidna na strani, nato poskusite znova zagnati Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Strežnikom DNS ni uspelo razrešiti navedene domene."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "V zahtevanem zbiralniku {artifactName} je prišlo do napake: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Prišlo je do notranje napake Chroma. Znova zaženite Chrome in poskusite znova zagnati Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Zahtevani zbiralnik {artifactName} se ni izvedel."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Orodje Lighthouse ni utegnilo zanesljivo naložiti zahtevane strani. Poskrbite, da preizkušate pravilen URL in da se strežnik ustrezno odziva na vse zahteve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Orodje Lighthouse ni utegnilo zanesljivo naložiti zahtevanega URL-ja, ker se je stran nehala odzivati."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Navedeni URL nima veljavnega varnostnega potrdila. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome je preprečil nalaganje strani z vrinjenim zaslonom. Poskrbite, da preizkušate pravilen URL in da se strežnik ustrezno odziva na vse zahteve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Orodje Lighthouse ni utegnilo zanesljivo naložiti zahtevane strani. Poskrbite, da preizkušate pravilen URL in da se strežnik ustrezno odziva na vse zahteve. (Podrobnosti: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Orodje Lighthouse ni utegnilo zanesljivo naložiti zahtevane strani. Poskrbite, da preizkušate pravilen URL in da se strežnik ustrezno odziva na vse zahteve. (Koda stanja: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Nalaganje strani je trajalo predolgo. Upoštevajte priložnosti v poročilu, da zmanjšate čas nalaganja strani, nato poskusite znova zagnati Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Čakanje na odziv protokola za DevTools je preseglo dodeljeni čas. (Metoda: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Trajanje pridobivanja vsebine sredstva je preseglo dodeljeni čas"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Videti je, da ste navedli neveljaven URL."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Pokaži preglede"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Začetno krmarjenje"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Največja zakasnitev kritične poti:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Napaka"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Napaka sporočila: ni podatkov o pregledu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Laboratorijski podatki"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analiza orodja [Lighthouse](https://developers.google.com/web/tools/lighthouse/) trenutne strani v emuliranem mobilnem omrežju. Vrednosti so ocenjene in lahko odstopajo."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Dodatni elementi za ročno preverjanje"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Se ne uporablja"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Priložnost"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Ocenjeni prihranek"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Uspešni pregledi"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Strni delček"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Razširi delček"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Prikaži sredstva drugih ponudnikov"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Na to izvedbo storitve Lighthouse so vplivale težave:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Vrednosti so ocenjene in lahko odstopajo. Rezultat uspešnosti [temelji samo na teh meritvah](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Pregledi so bili uspešno opravljeni, vendar z opozorili"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Opozorila: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Razmislite o tem, da bi GIF naložili v storitev, prek katere bo na voljo za vdelavo kot videposnetek v obliki HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Namestite [vtičnik za postopno nalaganje za WordPress](https://wordpress.org/plugins/search/lazy+load/) ki omogoča odlog nalaganja slik, ki niso na zaslonu, ali preidite na temo, ki ponuja to funkcijo. Razmislite tudi o uporabi [vtičnika AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Na voljo je več vtičnikov za WordPress, ki vam lahko pomagajo [uvrstiti nujna sredstva](https://wordpress.org/plugins/search/critical+css/) ali [odložiti manj pomembna sredstva](https://wordpress.org/plugins/search/defer+css+javascript/). Upoštevajte, da lahko optimizacije, ki jih ponujajo ti vtičniki, pokvarijo delovanje funkcij vaših tem ali vtičnikov, zato boste verjetno morali spremeniti kodo."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Teme, vtičniki in strežniške specifikacije prispevajo k odzivnemu času strežnika. Razmislite o tem, da bi poiskali bolj optimizirano temo, skrbno izbrali optimizacijski vtičnik in/ali nadgradili strežnik."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Razmislite o tem, da bi na seznamih objav prikazali izvlečke (npr. z oznako »more«), zmanjšali število objav, prikazanih na posamezni strani, daljše objave razdelili na več strani ali uporabili vtičnik za odloženo nalaganje komentarjev."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Na voljo je več [vtičnikov za WordPress](https://wordpress.org/plugins/search/minify+css/) ki lahko s sestavljanjem, pomanjševanjem in stiskanjem slogov pospešijo vaše spletno mesto. Po možnosti uporabite tudi postopek gradnje, ki to pomanjševanje izvede vnaprej."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Na voljo je več [vtičnikov za WordPress](https://wordpress.org/plugins/search/minify+javascript/), ki lahko s sestavljanjem, pomanjševanjem in stiskanjem slogov pospešijo vaše spletno mesto. Po možnosti uporabite tudi postopek gradnje, ki to pomanjševanje izvede vnaprej."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Razmislite o tem, da bi zmanjšali ali spremenili število [vtičnikov za WordPress](https://wordpress.org/plugins/), ki na vaši strani nalagajo neuporabljen CSS. Če želite ugotoviti, kateri vtičniki dodajo zunanji CSS, poskušajte z orodji Chrome DevTools izvesti [pokritost kode](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage). Ustrezen vtičnik/temo lahko ugotovite na podlagi URL-ja datoteke s slogi. Bodite pozorni na vtičnike, ki imajo na seznamu mnogo datotek s slogi, ki imajo v pokritosti kode veliko rdeče obarvanega območja. Datoteka s slogi naj bo v čakalni vrsti vtičnika samo, če je dejansko uporabljena na strani."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Razmislite o tem, da bi zmanjšali ali spremenili število [vtičnikov za WordPress](https://wordpress.org/plugins/), ki na vaši strani nalagajo neuporabljen JavaScript. Če želite ugotoviti, kateri vtičniki dodajo zunanji JS, poskušajte z orodji Chrome DevTools izvesti [pokritost kode](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage). Ustrezen vtičnik/temo lahko ugotovite na podlagi URL-ja skripta. Bodite pozorni na vtičnike, ki imajo na seznamu mnogo skriptov, ki imajo v pokritosti kode veliko rdeče obarvanega območja. Skript naj bo v čakalni vrsti vtičnika samo, če je dejansko uporabljen na strani."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Preberite o [predpomnjenju brskalnika v WordPressu](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Razmislite o tem, da bi uporabili [vtičnik za optimizacijo slik za WordPress](https://wordpress.org/plugins/search/optimize+images/), ki slike stisne, a ohrani kakovost."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Slike naložite neposredno prek [predstavnostne knjižnice](https://codex.wordpress.org/Media_Library_Screen) in tako zagotovite, da so na voljo potrebne velikosti slik. Nato jih vstavite iz predstavnostne knjižnice ali uporabite slikovni pripomoček, da zagotovite uporabo optimalnih velikosti slik (vključno s tistimi za odzivne prekinitvene točke). Izogibajte se slikam `Full Size`, razen če so mere primerne za njihovo uporabo. [Več o tem](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Stiskanje besedila lahko omogočite v konfiguraciji spletnega strežnika."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Razmislite o tem, da bi uporabili [vtičnik](https://wordpress.org/plugins/search/convert+webp/) ali storitev, ki naložene slike samodejno pretvori v optimalne oblike."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr-Latn.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr-Latn.json
new file mode 100644
index 00000000000..162d3f3cd70
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr-Latn.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Tasteri za pristup omogućavaju korisnicima da brzo fokusiraju deo stranice. Da bi navigacija radila ispravno, svaki taster za pristup mora da bude jedinstven. [Saznajte više](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Vrednosti za `[accesskey]` nisu jedinstvene"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Vrednosti za `[accesskey]` su jedinstvene"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Svaki ARIA element „`role`“ podržava određeni podskup atributa „`aria-*`“. Ako se ovi elementi ne podudaraju, atributi „`aria-*`“ će biti nevažeći. [Saznajte više](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` se ne podudaraju sa svojim ulogama"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Atributi `[aria-*]` se podudaraju sa svojim ulogama"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Pojedine ARIA uloge imaju obavezne atribute koji status elementa opisuju čitačima ekrana. [Saznajte više](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Uloge `[role]` nemaju sve obavezne atribute `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Uloge `[role]` imaju sve obavezne atribute `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Pojedine nadređene ARIA uloge moraju da obuhvataju određene podređene uloge da bi pravilno obavljale namenjene funkcije pristupačnosti. [Saznajte više](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Elementima sa ARIA ulogom `[role]` koji zahtevaju da podređeni elementi sadrže konkretni element `[role]` nedostaju neki ili svi ti potrebni podređeni elementi."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Elementi sa ARIA ulogom `[role]` koji zahtevaju da podređeni elementi sadrže konkretni element `[role]` imaju sve potrebne podređene elemente."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Pojedine podređene ARIA uloge moraju da budu obuhvaćene određenim nadređenim ulogama da bi pravilno obavljale namenjene funkcije pristupačnosti. [Saznajte više](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Uloge `[role]` nisu obuhvaćene svojim obaveznim nadređenim elementom"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Uloge `[role]` su obuhvaćene svojim obaveznim nadređenim elementom"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Vrednosti ARIA uloga moraju da budu važeće da bi pravilno obavljale namenjene funkcije pristupačnosti. [Saznajte više](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Vrednosti za `[role]` nisu važeće"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Vrednosti za `[role]` su važeće"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Tehnologije za pomoć osobama sa invaliditetom, poput čitača ekrana, ne mogu da interpretiraju ARIA atribute sa nevažećim vrednostima. [Saznajte više](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Vrednosti atributa `[aria-*]` nisu važeće"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Vrednosti atributa `[aria-*]` su važeće"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Tehnologije za pomoć osobama sa invaliditetom, poput čitača ekrana, ne mogu da interpretiraju ARIA atribute sa nevažećim nazivima. [Saznajte više](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Atributi `[aria-*]` nisu važeći ili su pogrešno napisani"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Atributi `[aria-*]` su važeći i nisu pogrešno napisani"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Titlovi omogućavaju da gluvi korisnici ili korisnici sa oštećenjem sluha koriste audio elemente, čime se pružaju važne informacije, na primer, informacije o tome koja osoba govori, šta govori, kao i druge informacije koje nisu vezane za govor. [Saznajte više](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Elementima `<audio>` nedostaje element `<track>` sa atributom `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Elementi `<audio>` sadrže element `<track>` sa atributom `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Elementi koji nisu prošli proveru"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Kada dugme nema naziv prilagođen funkciji pristupačnosti, čitači ekrana ga najavljuju kao „dugme“, pa korisnici koji se oslanjaju na čitače ekrana ne mogu da ga koriste. [Saznajte više](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Dugmad nema nazive prilagođene funkcijama pristupačnosti"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Dugmad ima nazive prilagođene funkcijama pristupačnosti"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Kada se dodaju načini za zaobilaženje sadržaja koji se ponavlja, korisnici tastature mogu efikasnije da se kreću po stranici. [Saznajte više](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Stranica ne obuhvata naslov, link za preskakanje niti region orijentira"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Stranica obuhvata naslov, link za preskakanje ili region orijentira"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Mnogi korisnici veoma teško čitaju tekst sa malim kontrastom ili uopšte ne mogu da ga čitaju. [Saznajte više](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Boje u pozadini i u prvom planu nemaju zadovoljavajući odnos kontrasta."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Boje u pozadini i u prvom planu imaju zadovoljavajući odnos kontrasta"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Kada liste definicija nisu pravilno označene, čitači ekrana mogu da pružaju zbunjujući ili netačan izlaz. [Saznajte više](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` ne sadrži samo pravilno naručene grupe `<dt>` i `<dd>`, elemente `<script>` ili `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` sadrži samo pravilno naručene grupe`<dt>` i `<dd>`, elemente `<script>` ili `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Stavke liste definicija (`<dt>` i `<dd>`) moraju da budu upakovane u nadređeni element`<dl>` da bi čitači ekrana mogli da ih pravilno čitaju. [Saznajte više](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Stavke liste definicija su upakovane u elemente `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Stavke liste definicija su upakovane u elemente`<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Naslov korisnicima čitača ekrana pruža pregled stranice, a korisnici pretraživača se na njega oslanjaju da bi utvrdili da li je stranica relevantna za njihovu pretragu. [Saznajte više](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokument nema element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokument ima element `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Vrednost atributa ID mora da bude jedinstvena da bi se sprečilo da tehnologije za pomoć osobama sa invaliditetom propuste druge instance. [Saznajte više](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Atributi `[id]` na stranici nisu jedinstveni"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Atributi `[id]` na stranici su jedinstveni"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Korisnici čitača ekrana očekuju od naslova okvira da im opišu sadržaj okvira. [Saznajte više](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Elementi `<frame>` ili `<iframe>` nemaju naslov"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Elementi `<frame>` ili `<iframe>` imaju naslov"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ako za stranicu nije naveden atribut za jezik, čitač ekrana pretpostavlja da je stranica na podrazumevanom jeziku koji je korisnik odabrao tokom podešavanja čitača ekrana. Ako stranica zapravo nije na podrazumevanom jeziku, čitač ekrana možda neće pravilno čitati tekst sa stranice. [Saznajte više](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Element `<html>` nema atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Element `<html>` ima atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Navođenjem važećeg koda [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) omogućava se da čitač ekrana pravilno čita tekst. [Saznajte više](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Element `<html>` nema važeću vrednost za svoj atribut `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Element `<html>` ima važeću vrednost za svoj atribut `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Informativni elementi treba da sadrže kratki, opisni alternativni tekst. Dekorativni elementi mogu da se zanemare praznim atributom alt. [Saznajte više](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Elementi slike nemaju atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Elementi slika imaju atribute `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Kada se slika koristi kao dugme `<input>`, navođenje alternativnog teksta može da pomogne korisnicima da razumeju svrhu dugmeta. [Saznajte više](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Elementi `<input type=\"image\">` ne sadrže tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Elementi `<input type=\"image\">` sadrže tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Oznake omogućavaju da tehnologije za pomoć osobama sa invaliditetom, poput čitača ekrana, pravilno najavljuju kontrole obrazaca. [Saznajte više](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Elementi obrazaca nemaju povezane oznake"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Elementi obrazaca imaju povezane oznake"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Tabela koja se koristi u svrhe rasporeda ne treba da obuhvata elemente podataka, kao što su elementi th ili titl ili atribut rezimea jer to može da zbuni korisnike čitača ekrana. [Saznajte više](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Prezentacioni elementi `<table>` ne izbegavaju upotrebu atributa `<th>`, `<caption>` ili `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Prezentacioni elementi `<table>` izbegavaju upotrebu atributa `<th>`, `<caption>` ili `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Tekst linka (i alternativni tekst za slike kada se koristi za linkove) koji je prepoznatljiv, jedinstven i može da se fokusira olakšava kretanje za korisnike čitača ekrana. [Saznajte više](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Naziv linkova ne može da se prepozna"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Naziv linkova može da se prepozna"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Čitači ekrana čitaju liste na poseban način. Pravilna struktura liste olakšava razumevanje čitača ekrana. [Saznajte više](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Liste ne sadrže isključivo elemente `<li>` i elemente koji podržavaju skripte (`<script>` i`<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Liste sadrže isključivo elemente `<li>` i elemente koji podržavaju skripte (`<script>` i `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Čitači ekrana zahtevaju da stavke liste (`<li>`) budu obuhvaćene nadređenim elementima `<ul>` ili `<ol>` da bi mogle da se pravilno čitaju. [Saznajte više](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Stavke liste (`<li>`) nisu obuhvaćene nadređenim elementima`<ul>` ili `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Stavke liste (`<li>`) su obuhvaćene nadređenim elementima `<ul>` ili `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Korisnici ne očekuju da se stranica automatski osvežava i time se fokus premešta na početak stranice. To može da frustira ili zbunjuje korisnike. [Saznajte više](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Dokument koristi metaoznaku `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Dokument ne koristi metaoznaku `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Onemogućavanje zumiranja predstavlja problem za slabovide korisnike koji se oslanjaju na uvećavanje prikaza ekrana da bi mogli da vide sadržaj veb-stranice. [Saznajte više](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` se koristi u elementu `<meta name=\"viewport\">` ili je vrednost atributa `[maximum-scale]` manja od 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` se ne koristi u elementu `<meta name=\"viewport\">`, a vrednost atributa `[maximum-scale]` nije manja od 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Čitači ekrana ne mogu da prevode sadržaj koji nije tekst. Dodavanje alt teksta elementima `<object>` omogućava da čitači ekrana lakše prenesu značenje korisnicima. [Saznajte više](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Elementi `<object>` ne sadrže tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Elementi `<object>` sadrže tekst `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Vrednost veća od 0 označava eksplicitno naručivanje navigacije. Iako je tehnički ispravno, to često frustrira korisnike koji se oslanjaju na tehnologije za pomoć osobama sa invaliditetom. [Saznajte više](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Neki elementi imaju vrednost za `[tabindex]` koja je veća od 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Vrednost nijednog elementa `[tabindex]` nije veća od 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Čitači ekrana imaju funkcije koje olakšavaju kretanje kroz tabele. Ako se pobrinete da se ćelije `<td>` koje koriste atribut `[headers]` odnose samo na druge ćelije u istoj tabeli, možete da poboljšate doživljaj za korisnike čitača ekrana. [Saznajte više](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Ćelije u elementu `<table>` koje koriste atribut `[headers]` odnose se na element `id` koji se ne nalazi u istoj tabeli."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Ćelije u elementu `<table>` koje koriste atribut `[headers]` odnose se na ćelije tabele u istoj tabeli."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Čitači ekrana imaju funkcije koje olakšavaju kretanje kroz tabele. Ako se pobrinete da se naslovi tabela uvek odnose na neku grupu ćelija, možete da poboljšate doživljaj za korisnike čitača ekrana. [Saznajte više](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Elementi `<th>` i elementi sa atributom`[role=\"columnheader\"/\"rowheader\"]` nemaju ćelije sa podacima koje opisuju."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Elementi `<th>` i elementi sa atributom `[role=\"columnheader\"/\"rowheader\"]` imaju ćelije sa podacima koje opisuju."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Navođenjem važećeg koda [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) u elementima omogućava se da čitač ekrana pravilno čita tekst. [Saznajte više](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Vrednost atributa `[lang]` nije važeća"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Atributi `[lang]` imaju važeću vrednost"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Kada je dostupan titl za video, gluvi korisnici i oni sa oštećenjem sluha lakše mogu da pristupaju informacijama koje video obuhvata. [Saznajte više](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Elementi `<video>` ne obuhvataju element `<track>` sa atributom `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Elementi `<video>` sadrže element `<track>` sa atributom `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Audio opisi pružaju relevantne informacije za video snimke koje dijalog ne može, poput izraza lica i scena. [Saznajte više](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Elementi `<video>` ne obuhvataju element `<track>` sa atributom `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Elementi `<video>` sadrže element `<track>` sa atributom `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Da bi izgled na iOS-u bio idealan kada korisnici dodaju progresivnu veb-aplikaciju na početni ekran, definišite ikonu `apple-touch-icon`. Ona mora da usmerava na netransparentni kvadratni PNG od 192 piksela (ili 180 piksela). [Saznajte više](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Ne pruža važeći atribut `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Atribut `apple-touch-icon-precomposed` je zastareo; preporučuje se `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Pruža važeći atribut `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Dodaci za Chrome su negativno uticali na brzinu učitavanja ove stranice. Probajte da proverite stranicu u režimu bez arhiviranja ili sa Chrome profila bez dodataka."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Procena skripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Raščlanjivanje skripta"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Ukupno CPU vreme"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Preporučujemo vam da smanjite vreme potrebno za raščlanjivanje, kompajliranje i izvršavanje JS datoteka. Prikazivanje manjih JS resursa će vam možda pomoći u tome. [Saznajte više](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Smanjite vreme izvršavanja JavaScript datoteka"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Vreme izvršavanja JavaScript-a"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Veliki GIF-ovi nisu korisni za prikazivanje animiranog sadržaja. Preporučujemo vam da umesto GIF-ova koristite MPEG4/WebM video snimke za animacije i PNG/WebP za statične slike da biste uštedeli mrežne podatke. [Saznajte više](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Koristite video formate za animirani sadržaj"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Preporučujemo vam da odložite učitavanje slika van ekrana i skrivenih slika dok se svi veoma važni resursi ne učitaju kako biste smanjili vreme do početka interakcije. [Saznajte više](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Odložite slike van ekrana"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resursi blokiraju prvo prikazivanje stranice. Preporučujemo vam da prikazujete sve važne JS/CSS datoteke u tekstu i da odložite sve JS datoteke/stilove koji nisu toliko važni. [Saznajte više](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Eliminišite resurse koji blokiraju prikazivanje"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Velike mrežne resurse korisnici moraju da plate stvarnim novcem i oni su veoma povezani sa dugim vremenima učitavanja. [Saznajte više](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Ukupna veličina je bila {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Izbegavajte ogromne mrežne resurse"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Izbegava ogromne mrežne resurse"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Umanjivanjem CSS datoteka možete da smanjite veličine mrežnih resursa. [Saznajte više](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Umanjite CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Umanjivanje JavaScript datoteka može da smanji veličine resursa i vreme raščlanjivanja skripta. [Saznajte više](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Umanjite JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Uklonite neaktivna pravila iz opisa stilova i odložite učitavanje CSS-a koji se ne koristi za sadržaj iznad preloma da biste smanjili nepotrebnu potrošnju podataka tokom mrežnih aktivnosti. [Saznajte više](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Uklonite nekorišćeni CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Uklonite nekorišćeni JavaScript da biste smanjili potrošnju podataka tokom mrežnih aktivnosti."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Uklonite nekorišćeni JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Dugo trajanje keša može da ubrza ponovne posete stranici. [Saznajte više](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je 1 resurs}one{Pronađen je # resurs}few{Pronađena su # resursa}other{Pronađeno je # resursa}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Prikazujte statične elemente sa efikasnim smernicama keša"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Koristi efikasne smernice keša na statičnim elementima"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimizovane slike se učitavaju brže i troše manje mobilnih podataka. [Saznajte više](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Efikasno kodirajte slike"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Prikazujte slike odgovarajuće veličine da biste uštedeli mobilne podatke i poboljšali vreme učitavanja. [Saznajte više](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Odredite odgovarajuću veličinu slika"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Resurse zasnovane na tekstu treba da prikazujete u komprimovanom formatu (gzip, deflate ili brotli) da biste smanjili ukupnu količinu potrošenih mrežnih podataka. [Saznajte više](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Omogućite kompresiju teksta"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Formati slika kao što su JPEG 2000, JPEG XR i WebP često pružaju bolju kompresiju nego PNG ili JPEG, što podrazumeva brža preuzimanja i manju potrošnju podataka. [Saznajte više](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Prikazujte slike u formatima sledeće generacije"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ako se širina sadržaja aplikacije ne podudara sa širinom oblasti prikaza, aplikacija možda nije optimizovana za ekrane na mobilnim uređajima. [Saznajte više](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Veličina oblasti prikaza od {innerWidth} piksela se ne podudara sa veličinom prozora od {outerWidth} piksela."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Sadržaj nije odgovarajuće veličine za oblast prikaza"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Sadržaj je odgovarajuće veličine za oblast prikaza"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Lanci veoma važnih zahteva u nastavku vam prikazuju koji resursi se učitavaju sa visokim prioritetom. Preporučujemo vam da smanjite dužinu lanaca, da smanjite veličinu preuzimanja za resurse ili da odložite preuzimanje resursa koji nisu neophodni radi bržeg učitavanja stranice. [Saznajte više](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je 1 lanac}one{Pronađen je # lanac}few{Pronađena su # lanca}other{Pronađeno je # lanaca}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Smanjite broj veoma važnih zahteva"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Zastarelo/upozorenje"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Red"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Zastareli API-ji će na kraju biti uklonjeni iz pregledača. [Saznajte više](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Otkriveno je 1 upozorenje}one{Otkriveno je # upozorenje}few{Otkrivena su # upozorenja}other{Otkriveno je # upozorenja}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Koristi zastarele API-je"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Izbegava zastarele API-je"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Keš aplikacije je zastareo. [Saznajte više](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Pronađeno je „{AppCacheManifest}“"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Koristi keš aplikacije"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Izbegava keš aplikacije"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Navođenjem doctype-a sprečava se prelazak na arhajski režim pregledača. [Saznajte više](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Naziv za doctype mora da bude string napisan malim slovima `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument mora da sadrži doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Očekivani publicId će biti prazan string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Očekivani systemId će biti prazan string"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Stranici nedostaje HTML doctype, pa se aktivira arhajski režim"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Stranica ima HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Statistika"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Vrednost"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Inženjeri za pregledače preporučuju da stranice sadrže manje od približno 1500 DOM elemenata. Najbolje bi bilo da dubina stabla bude ispod 32 elementa i da ima manje od 60 podređenih/nadređenih elemenata. Veliki DOM može da poveća potrošnju memorije, da izazove duža [izračunavanja stilova](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) i da dovede do skupih [preoblikovanja izgleda](https://developers.google.com/speed/articles/reflow). [Saznajte više](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}one{# element}few{# elementa}other{# elemenata}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Izbegavajte preveliku veličinu DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimalna dubina DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Ukupan broj DOM elemenata"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimalan broj podređenih elemenata"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Izbegava preveliku veličinu DOM-a"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Cilj"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Dodajte `rel=\"noopener\"` ili`rel=\"noreferrer\"` svim spoljnim linkovima da biste poboljšali učinak i sprečili bezbednosne propuste. [Saznajte više](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Linkovi do odredišta iz drugih izvora nisu bezbedni"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Linkovi do odredišta iz drugih izvora su bezbedni"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Nije moguće odrediti odredište za tekst linka ({anchorHTML}). Ako se ne koristi kao hiperlink, preporučujemo vam da uklonite target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Korisnici nemaju poverenja u sajtove koji traže njihovu lokaciju bez konteksta ili ih takvi sajtovi zbunjuju. Preporučujemo vam da umesto toga povežete zahtev sa radnjom koju obavlja korisnik. [Saznajte više](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Traži dozvolu za geolociranje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Izbegavajte traženje dozvole za geolociranje pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Verzija"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Sve korisničke JavaScript biblioteke otkrivene na ovoj stranici. [Saznajte više](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Otkrivene su JavaScript biblioteke"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Ako korisnici imaju spore veze, spoljne skripte koje se dinamički ubacuju pomoću atributa `document.write()` mogu da odlože učitavanje stranice za desetine sekundi. [Saznajte više](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Koristi `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Izbegava atribut `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Najviši nivo ozbiljnosti"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Verzija biblioteke"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Broj propusta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Neke nezavisne skripte mogu da obuhvataju poznate bezbednosne propuste koje napadači mogu lako da prepoznaju i iskoriste. [Saznajte više](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Otkriven je 1 propust}one{Otkriven je # propust}few{Otkrivena su # propusta}other{Otkriveno je # propusta}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Obuhvata korisničke JavaScript datoteke sa poznatim bezbednosnim propustima"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Visoka"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Niska"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Srednja"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Izbegava korisničke JavaScript datoteke sa poznatim bezbednosnim propustima"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Korisnici nemaju poverenja u sajtove koji traže dozvolu za slanje obaveštenja bez konteksta ili ih takvi sajtovi zbunjuju. Preporučujemo vam da umesto toga povežete zahtev sa pokretima korisnika. [Saznajte više](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Traži dozvolu za obaveštenja pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Izbegavajte traženje dozvole za obaveštenja pri učitavanju stranice"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Elementi koji nisu prošli proveru"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Sprečavanje lepljenja lozinke narušava dobre smernice za bezbednost. [Saznajte više](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Sprečava korisnike da nalepe vrednost u polja za lozinke"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Dozvoljava korisnicima da nalepe vrednost u polja za lozinke"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ima brojne prednosti u odnosu na HTTP/1.1, uključujući binarna zaglavlja, multipleksiranje i serverski puš. [Saznajte više](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 zahtev nije isporučen preko protokola HTTP/2}one{# zahtev nije isporučen preko protokola HTTP/2}few{# zahteva nisu isporučena preko protokola HTTP/2}other{# zahteva nije isporučeno preko protokola HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Ne koristi HTTP/2 za sve svoje resurse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Koristi HTTP/2 za svoje resurse"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Preporučujemo vam da pasivne obrađivače događaja označite kao `passive` da biste poboljšali rezultate pomeranja. [Saznajte više](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Ne koristite pasivne obrađivače da biste poboljšali učinak pomeranja"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Koristite pasivne obrađivače da biste poboljšali učinak pomeranja"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Opis"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Greške evidentirane u konzoli ukazuju na nerešene probleme. One su rezultat neuspelih mrežnih zahteva i drugih problema u vezi sa pregledačem. [Saznajte više](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Greške pregledača su evidentirane u konzoli"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Nijedna greška pregledača nije evidentirana u konzoli"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Iskoristite CSS funkciju za prikaz fontova da biste bili sigurni da korisnik može da vidi tekst dok se veb-fontovi učitavaju. [Saznajte više](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Pobrinite se da tekst ostane vidljiv tokom učitavanja veb-fontova"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Sav tekst ostaje vidljiv tokom učitavanja veb-fontova"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse nije uspeo da automatski proveri vrednost za prikaz fontova za sledeći URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Razmera (stvarna)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Razmera (prikazana)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Dimenzije prikaza slike treba da se podudaraju sa prirodnom razmerom. [Saznajte više](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Prikazuje slike sa pogrešnom razmerom"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Prikazuje slike sa tačnom razmerom"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Nevažeće informacije o veličini slike {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Pregledači mogu proaktivno da traže od korisnika da dodaju aplikaciju na početni ekran, što može da dovede do većeg angažovanja. [Saznajte više](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Manifest veb-aplikacije ne zadovoljava uslove za instaliranje"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Manifest veb-aplikacije zadovoljava uslove za instaliranje"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Nebezbedan URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Svi sajtovi treba da budu zaštićeni HTTPS-om, čak i oni koji ne obrađuju osetljive podatke. HTTPS sprečava uljeze da neovlašćeno pristupaju komunikaciji između aplikacije i korisnika ili da je pasivno slušaju. On je preduslov za HTTP/2 i API-je brojnih novih veb-platformi. [Saznajte više](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je 1 nebezbedan zahtev}one{Pronađen je # nebezbedan zahtev}few{Pronađena su # nebezbedna zahteva}other{Pronađeno je # nebezbednih zahteva}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Ne koristi HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Koristi HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Brzo učitavanje stranice preko mobilne mreže obezbeđuje dobar doživljaj korisnicima mobilnih uređaja. [Saznajte više](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktivno za {timeInMs, number, seconds} sek"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktivna na simuliranoj mobilnoj mreži za {timeInMs, number, seconds} sek"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Stranica se presporo učitava i ne postaje interaktivna u roku od 10 sekundi. Pogledajte prilike i dijagnostiku u odeljku „Učinak“ da biste saznali kako da poboljšate učinak stranice."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Učitavanje stranice nije dovoljno brzo na mobilnim mrežama"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Učitavanje stranice je dovoljno brzo na mobilnim mrežama"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategorija"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Preporučujemo vam da smanjite vreme potrebno za raščlanjivanje, kompajliranje i izvršavanje JS datoteka. Prikazivanje manjih JS resursa će vam možda pomoći u tome. [Saznajte više](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Smanjite rad glavne niti"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Smanjuje rad glavne niti"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Da bi imali što više korisnika, sajtovi treba da rade u svim značajnijim pregledačima. [Saznajte više](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Sajt radi u različitim veb-pregledačima"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Uverite se da do pojedinačnih stranica vode precizni linkovi preko URL-ova i da su URL-ovi jedinstveni u svrhu deljenja na društvenim medijima. [Saznajte više](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Svaka stranica ima URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Korisnici treba da imaju utisak da su prelazi brzi dok dodiruju stavke, čak i na sporoj mreži. Ovaj doživljaj je ključan za utisak koji će korisnik imati o učinku. [Saznajte više](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Prelasci sa stranice na stranicu ne deluju kao da se blokiraju zbog mreže"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Procenjeno kašnjenje unosa je procena vremena koje je aplikaciji potrebno da odgovori na unos korisnika, u milisekundama, tokom najprometnijeg roka od 5 sekundi za učitavanje stranice. Ako je kašnjenje veće od 50 ms, korisnici će možda smatrati da aplikacija radi sporo. [Saznajte više](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Procenjeno kašnjenje unosa"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Prvo prikazivanje sadržaja označava vreme kada se prikazuju prvi tekst ili slika. [Saznajte više](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Prvo prikazivanje sadržaja"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Vreme prvog neaktivnog procesora označava prvi trenutak u kom je glavna nit stranice dovoljno neaktivna da bi obradila unos. [Saznajte više](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Vreme prvog neaktivnog procesora"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Prvo značajno prikazivanje označava vreme kada primarni sadržaj stranice postaje vidljiv. [Saznajte više](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Prvo značajno prikazivanje"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Vreme do interakcije je količina vremena koja je potrebna da bi stranica postala potpuno interaktivna. [Saznajte više](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Vreme početka interakcije"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Maksimalno potencijalno kašnjenje prvog unosa koje može da se desi korisnicima je trajanje najdužeg zadatka u milisekundama. [Saznajte više](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maks. potencijalno kašnjenje prvog prikaza"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Indeks brzine prikazuje koliko brzo sadržaj stranice postaje vidljiv za korisnike. [Saznajte više](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Indeks brzine"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Zbir svih perioda između FCP-a i vremena do početka interakcije, kada zadatak traje duže od 50 ms, izraženo u milisekundama."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Ukupno vreme blokiranja"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Trajanja povratnog puta (RTT) mreže znatno utiču na učinak. Ako je trajanje povratnog puta do početne lokacije veliko, to znači da bi serveri koji su bliži korisniku mogli da poboljšaju učinak. [Saznajte više](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Trajanja povratnog puta mreže"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Kašnjenja servera mogu da utiču na učinak veba. Ako je kašnjenje servera za početnu lokaciju veliko, to znači da je server preopterećen ili da ima slab pozadinski učinak. [Saznajte više](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Pozadinska kašnjenja servera"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Serviser omogućava da veb-aplikacija bude pouzdana u nepredvidivim uslovima mreže. [Saznajte više](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ne odgovara kodom 200 kada je oflajn"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` odgovara kodom 200 kada je oflajn"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse nije uspeo da pročita `start_url` iz manifesta. Kao posledica toga, pretpostavili smo da je `start_url` URL dokumenta. Poruka o grešci: „{manifestWarning}“."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Premašuje cilj"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Zahteve za količinu i veličinu mreže održavajte ispod granica određenih ciljevima za učinak. [Saznajte više](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 zahtev}one{# zahtev}few{# zahteva}other{# zahteva}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Cilj za učinak"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ako ste već podesili HTTPS, uverite se da preusmeravate sav HTTP saobraćaj na HTTPS da biste omogućili bezbedne veb-funkcije za sve korisnike. [Saznajte više](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Ne preusmerava HTTP saobraćaj na HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Preusmerava HTTP saobraćaj na HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Preusmeravanja dovode do dodatnih kašnjenja pre učitavanja stranice. [Saznajte više](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Izbegavajte višestruka preusmeravanja stranice"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Da biste podesili ciljeve za količinu i veličinu resursa stranice, dodajte datoteku budget.json file. [Saznajte više](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 zahtev • {byteCount, number, bytes} KB}one{# zahtev • {byteCount, number, bytes} KB}few{# zahteva • {byteCount, number, bytes} KB}other{# zahteva • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Omogući da broj zahteva i veličine prenosa budu mali"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanonički linkovi predlažu koji URL treba da se prikaže u rezultatima pretrage. [Saznajte više](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Više neusaglašenih URL-ova ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Usmerava ka drugom domenu ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Nevažeći URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Usmerava na drugu `hreflang` lokaciju ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativni URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Usmerava na osnovni URL domena (početnu stranicu), umesto ekvivalentne stranice sadržaja"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokument nema važeću vrednost `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokument ima važeći atribut `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Veličine fontova ispod 12 piksela su premale da bi bile čitljive i zbog njih korisnici na mobilnim uređajima moraju da „zumiraju prstima“ kako bi mogli da čitaju sadržaj. Potrudite se da >60% teksta stranice bude ≥12 piksela. [Saznajte više](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} čitljivog teksta"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Tekst nije čitljiv jer ne postoji metaoznaka oblasti prikaza koja je optimizovana za ekrane na mobilnim uređajima."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} teksta je premalo (na osnovu uzorka od {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokument ne koristi čitljive veličine fontova"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokument koristi čitljive veličine fontova"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Linkovi hreflang obaveštavaju pretraživače koju verziju stranice treba da navedu u rezultatima pretrage za dati jezik ili region. [Saznajte više](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokument nema važeći atribut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokument ima važeći atribut `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Stranice sa neuspešnim HTTP kodovima statusa možda neće biti pravilno indeksirane. [Saznajte više](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Stranica ima neuspešan HTTP kôd statusa"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Stranica ima uspešan HTTP kôd statusa"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Pretraživači ne mogu da uvrste stranice u rezultate pretrage ako nemaju dozvolu da ih popisuju. [Saznajte više](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Indeksiranje stranice je blokirano"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Indeksiranje stranice nije blokirano"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Opisni tekst u linkovima pomaže pretraživačima da razumeju sadržaj. [Saznajte više](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Pronađen je 1 link}one{Pronađen je # link}few{Pronađena su # linka}other{Pronađeno je # linkova}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Linkovi nemaju opisni tekst"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Linkovi imaju opisni tekst"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Pokrenite [alatku za testiranje strukturiranih podataka](https://search.google.com/structured-data/testing-tool/) i [alatku za analiziranje strukturiranih podataka](http://linter.structured-data.org/) da biste procenili strukturirane podatke. [Saznajte više](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturirani podaci su važeći"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metaopisi mogu da budu uvršteni u rezultate pretrage da bi pružili sažeti rezime sadržaja stranice. [Saznajte više](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Polje za tekst opisa je prazno."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokument nema metaopis"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokument ima metaopis"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Pretraživači ne mogu da indeksiraju sadržaj dodatnih komponenata, a mnogi uređaji ograničavaju dodatne komponente ili ih ne podržavaju. [Saznajte više](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokument koristi dodatne komponente"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokument izbegava dodatne komponente"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ako datoteka robots.txt nije pravilno napravljena, popisivači možda neće moći da razumeju kako želite da se veb-sajt popiše ili indeksira. [Saznajte više](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Zahtev za datoteku robots.txt vratio je HTTP status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Pronađena je 1 greška}one{Pronađena je # greška}few{Pronađene su # greške}other{Pronađeno je # grešaka}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse nije uspeo da preuzme datoteku robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Datoteka robots.txt nije važeća"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Datoteka robots.txt je važeća"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktivni elementi poput dugmadi i linkova treba da budu dovoljno veliki (48×48 piksela) i da imaju dovoljno prostora oko sebe da bi bilo lako da se dodirnu bez preklapanja sa drugim elementima. [Saznajte više](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} ciljeva dodirivanja ima odgovarajuću veličinu"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Ciljevi dodirivanja su premali jer ne postoji metaoznaka oblasti prikaza koja je optimizovana za ekrane na mobilnim uređajima"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Ciljevi dodirivanja nemaju odgovarajuću veličinu"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Cilj koji se preklapa"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Cilj dodirivanja"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Ciljevi dodirivanja imaju odgovarajuću veličinu"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Serviser je tehnologija koja omogućava aplikaciji da koristi mnoge funkcije progresivnih veb-aplikacija, poput oflajn rada, dodavanja na početni ekran i iskačućih obaveštenja. [Saznajte više](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Ovu stranicu kontroliše serviser, ali nije pronađen nijedan `start_url` jer nije uspelo raščlanjivanje manifesta kao važeće JSON datoteke"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Ovu stranicu kontroliše serviser, ali `start_url` ({startUrl}) ne spada u opseg servisera ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Ovu stranicu kontroliše serviser, ali nije pronađen nijedan `start_url` jer nijedan manifest nije preuzet."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ovaj izvor ima jedan ili više servisera, ali stranica ({pageUrl}) nije u opsegu."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Ne registruje serviser koji kontroliše stranicu i `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registruje serviser koji kontroliše stranicu i `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Tematski uvodni ekran obezbeđuje kvalitetan doživljaj kada korisnici pokreću aplikaciju sa početnih ekrana. [Saznajte više](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Nije konfigurisano za prilagođeni uvodni ekran"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigurisano za prilagođeni uvodni ekran"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Traka za adresu pregledača može da ima temu koja odgovara sajtu. [Saznajte više](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Ne podešava boju teme za traku za adresu."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Podešava boju teme za traku za adresu."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Period blokiranja glavne niti"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Nezavisni dobavljač"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kôd nezavisnog dobavljača može značajno da utiče na učinak učitavanja. Ograničite broj suvišnih nezavisnih dobavljača usluge i probajte da učitate kôd nezavisnog dobavljača kada stranica primarno završi sa učitavanjem. [Saznajte više](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Kôd nezavisnog dobavljača je blokirao glavnu nit {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Smanjite uticaj koda nezavisnog dobavljača"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Nezavisna upotreba"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Vreme prvog odgovora određuje vreme u koje server šalje odgovor. [Saznajte više](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Osnovnom dokumentu je trebalo {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Smanjite vremena odgovora servera (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Vremena odgovora servera su kratka (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Trajanje"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Vreme početka"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tip"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Preporučujemo vam da opremite aplikaciju API-jem za vreme korisnika da biste izmerili učinak aplikacije u realnom svetu tokom ključnih korisničkih doživljaja. [Saznajte više](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 vreme korisnika}one{# vreme korisnika}few{# vremena korisnika}other{# vremena korisnika}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Oznake i mere Vremena korisnika"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Povezivanje unapred <link> je pronađeno za „{securityOrigin}“, ali ga pregledač nije upotrebio. Proverite da li pravilno koristite atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Razmislite o tome da dodate savete za resurse `preconnect` ili `dns-prefetch` kako biste uspostavili rane veze sa važnim izvorima trećih strana. [Saznajte više](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Povežite se unapred sa potrebnim izvorima"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Predučitavanje <link> je pronađeno za „{preloadURL}“, ali ga pregledač nije upotrebio. Proverite da li pravilno koristite atribut `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Preporučujemo vam da koristite `<link rel=preload>` kako biste kasnije tokom učitavanja stranice dali prioritet preuzimanju resursa koji se trenutno traže. [Saznajte više](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Unapred učitajte najvažnije zahteve"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Dodajte oznaku `<meta name=\"viewport\">` da biste optimizovali aplikaciju za ekrane na mobilnim uređajima. [Saznajte više](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Nije pronađena oznaka `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Nema oznaku `<meta name=\"viewport\">` sa oznakama `width` ili `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Ima oznaku `<meta name=\"viewport\">` sa oznakom `width` ili `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Aplikacija treba da prikazuje neki sadržaj kada je JavaScript onemogućen, čak i ako je to samo upozorenje korisniku da je JavaScript obavezan za korišćenje aplikacije. [Saznajte više](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Telo stranice treba da prikazuje neki sadržaj ako joj skripte nisu dostupne."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Ne pruža rezervni sadržaj kada JavaScript nije dostupan"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Ima neki sadržaj kada JavaScript nije dostupan"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ako pravite progresivnu veb-aplikaciju, razmislite o tome da koristite serviser kako bi aplikacija mogla da radi oflajn. [Saznajte više](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Aktuelna stranica ne odgovara kodom 200 kada je oflajn"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Aktuelna stranica odgovara kodom 200 kada je oflajn"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Stranica se možda ne učitava oflajn zato što je probni URL ({requested}) preusmeren na „{final}“. Probajte direktno da testirate drugi URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "To su prilike da poboljšate korišćenje ARIA uloga u aplikaciji, čime može da poboljša doživljaj korisnika tehnologije za pomoć osobama sa invaliditetom, kao što je čitač ekrana."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "To su prilike da pružite alternativni sadržaj za audio i video datoteke. To može da poboljša doživljaj za korisnike sa oštećenim sluhom ili vidom."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Zvuk i video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ove stavke ističu uobičajene najbolje prakse u vezi sa pristupačnošću."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Najbolje prakse"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ove provere ističu prilike za [poboljšanje pristupačnosti veb-aplikacije](https://developers.google.com/web/fundamentals/accessibility). Automatski može da se otkrije samo jedan podskup problema sa pristupačnošću, pa preporučujemo da obavljate i ručno testiranje."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ove stavke obrađuju oblasti koje alatka za automatizovano testiranje ne može da obuhvati. Saznajte više u vodiču o [sprovođenju pregleda pristupačnosti](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Pristupačnost"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "To su prilike da poboljšate čitljivost sadržaja."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "To su prilike da poboljšate tumačenje svog sadržaja za korisnike na različitim jezicima."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internacionalizacija i lokalizacija"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "To su prilike da poboljšate semantiku kontrola u aplikaciji. To može da poboljša doživljaj korisnika tehnologije za pomoć osobama sa invaliditetom, kao što je čitač ekrana."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Nazivi i oznake"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ovo su prilike da poboljšate kretanje po tastaturi u aplikaciji."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigacija"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "To su prilike za poboljšanje doživljaja pri čitanju podataka iz tabela i lista pomoću tehnologije za pomoć osobama sa invaliditetom, poput čitača ekrana."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabele i liste"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Najbolje prakse"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Ciljevima za učinak određuju se standardi za učinak sajta."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Ciljevi"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Više informacija o učinku aplikacije. Ovi brojevi ne [utiču direktno](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na ocenu učinka."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Dijagnostika"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Najvažniji aspekt učinka je brzina kojom se pikseli prikazuju na ekranu. Ključni pokazatelji: Prvo prikazivanje sadržaja, Prvo značajno prikazivanje"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Poboljšanja prvog prikazivanja"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ovi predlozi mogu da vam pomognu da se stranica učitava brže. Ne [utiču direktno](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) na ocenu učinka."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Mogućnosti"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Pokazatelji"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Poboljšajte opšti doživljaj učitavanja da bi stranica počela da se odaziva i da bi bila spremna za korišćenje u najkraćem mogućem roku. Ključni pokazatelji: Vreme početka interakcije, Indeks brzine"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Opšta poboljšanja"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Učinak"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Ovim proverama se ocenjuju aspekti progresivne veb-aplikacije. [Saznajte više](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ove provere zahteva osnovna [Kontrolna lista za progresivne veb-aplikacije](https://developers.google.com/web/progressive-web-apps/checklist), ali ih Lighthouse ne sprovodi automatski. One ne utiču na vaš rezultat, ali je važno da ih ručno potvrdite."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresivna veb-aplikacija"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Brzo i pouzdano"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Može da se instalira"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimizovano za PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Zahvaljujući ovim proverama stranica će sigurno biti optimizovana za rangiranje rezultata pretraživača. Ima još nekih faktora koje Lighthouse ne proverava, a koji mogu da utiču na rangiranje u pretrazi. [Saznajte više](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Pokrećite ove dodatne validatore na sajtu da biste proverili dodatne najbolje prakse optimizacije za pretraživače."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Optimizacija za pretraživače"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatirajte HTML sadržaj na način koji omogućava popisivačima da bolje razumeju sadržaj aplikacije."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Najbolje prakse za sadržaj"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Da bi se aplikacija pojavila u rezultatima pretrage, popisivači treba da imaju pristup do nje."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Popisivanje i indeksiranje"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Uverite se da su stranice prilagođene mobilnim uređajima da korisnici ne bi morali da umanjuju ili uvećavaju prikaz kako bi čitali stranice sa sadržajem. [Saznajte više](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Prilagođeno mobilnim uređajima"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Vreme preživljavanja keša"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Lokacija"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Naziv"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Zahtevi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Tip resursa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Veličina"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Provedeno vreme"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Veličina prenosa"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potencijalna ušteda"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potencijalna ušteda"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Potencijalna ušteda od {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Potencijalna ušteda od {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Font"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Slika"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Mediji"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Drugo"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skripta"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} sek"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Opis stila"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Nezavisni resursi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Ukupno"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Došlo je do greške pri evidentiranju traga tokom učitavanja stranice. Ponovo pokrenite Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Vremensko ograničenje čekanja na inicijalnu vezu za protokol programa za otklanjanje grešaka."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome nije prikupio nijedan snimak ekrana tokom učitavanja stranice. Uverite se da je sadržaj vidljiv na stranici, pa probajte da ponovo pokrenete Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS serveri nisu mogli da razreše navedeni domen."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Prikupljač za obavezni resurs {artifactName} je naišao na grešku: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Došlo je do interne greške u Chrome-u. Ponovo pokrenite Chrome i probajte da ponovo pokrenete Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Prikupljač za obavezni resurs {artifactName} se nije pokrenuo."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse nije uspeo da pouzdano učita stranicu koju ste zahtevali. Uverite se da testirate odgovarajući URL i da server pravilno odgovara na sve zahteve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse nije uspeo da pouzdano učita URL koji ste zahtevali jer je stranica prestala da reaguje."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL koji ste naveli nema važeći bezbednosni sertifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome je sprečio učitavanje stranice sa tranzitivnim oglasom. Uverite se da testirate odgovarajući URL i da server pravilno odgovara na sve zahteve."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse nije uspeo da pouzdano učita stranicu koju ste zahtevali. Uverite se da testirate odgovarajući URL i da server pravilno odgovara na sve zahteve. (Detalji: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse nije uspeo da pouzdano učita stranicu koju ste zahtevali. Uverite se da testirate odgovarajući URL i da server pravilno odgovara na sve zahteve. (Kôd statusa: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Učitavanje stranice je trajalo predugo. Pratite prilike u izveštaju da biste skratili vreme učitavanja stranice, pa ponovo pokrenite Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Odgovor protokola DevTools se čeka duže od dodeljenog perioda. (Metod: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Preuzimanje sadržaja resursa traje duže od dodeljenog perioda."
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Izgleda da je URL koji ste naveli nevažeći."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Prikaži provere"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Početna navigacija"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimalno kašnjenje kritične putanje:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Greška!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Prijavljivanje greške: nema informacija o proveri"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Podaci o eksperimentalnim funkcijama"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analiza aktuelne stranice emulirane pomoću mobilne mreže. Vrednosti predstavljaju procene i mogu da variraju."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Dodatne stavke za ručnu proveru"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Nije primenjivo"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Mogućnost"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Procenjena ušteda"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Provere sa zadovoljavajućom ocenom"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Skupi fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Proširi fragment"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Prikaži nezavisne resurse"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Bilo je izvesnih problema koji su uticali na ovo pokretanje Lighthouse-a:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Vrednosti predstavljaju procene i mogu da variraju. Ocena učinka se [zasniva samo na ovim pokazateljima](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Provere sa zadovoljavajućom ocenom koje sadrže upozorenja"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Upozorenja: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Predlažemo da otpremite GIF u uslugu koja će ga kodirati za ugradnju u HTML5 video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Instalirajte [WordPress dodatnu komponentu za lako učitavanje](https://wordpress.org/plugins/search/lazy+load/) koja omogućava da odložite sve slike van ekrana ili da pređete na temu koja pruža tu funkciju. Preporučujemo i da koristite [dodatnu komponentu za AMP stranice](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Neke WordPress dodatne komponente mogu da vam pomognu da [umetnete kritične elemente](https://wordpress.org/plugins/search/critical+css/) ili [odložite manje važne resurse](https://wordpress.org/plugins/search/defer+css+javascript/). Imajte na umu da optimizacije koje pružaju ove dodatne komponente mogu da oštete funkcije ili teme dodatnih komponenti, pa ćete verovatno morati da unosite promene u kôd."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Teme, dodatne komponente i specifikacije servera doprinose vremenu odgovora servera. Preporučujemo da pronađete optimizovaniju temu, pažljivo izaberete dodatnu komponentu za optimizaciju i/ili nadogradite server."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Preporučujemo da prikažete odlomke u listama postova (na primer, preko još oznaka), smanjite broj postova koji se prikazuju na određenoj stranici, razdvojite dugačke postove na više strancia ili koristite dodatnu komponentu za lako učitavanje komentara."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Neke [WordPress dodatne komponente](https://wordpress.org/plugins/search/minify+css/) mogu da ubrzaju sajt tako što povezuju, umanjuju i komprimuju stilove. Ovo umanjivanje možete da obavite i unapred pomoću procesa dizajniranja ako je moguće."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Neke [WordPress dodatne komponente](https://wordpress.org/plugins/search/minify+javascript/) mogu da ubrzaju sajt tako što povezuju, umanjuju i komprimuju skripte. Ovo umanjivanje možete da obavite i unapred pomoću procesa dizajniranja ako je moguće."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Preporučujemo da umanjite ili promenite broj [WordPress dodatnih komponenti](https://wordpress.org/plugins/) koje na stranici učitavaju CSS koji se ne koristi. Da biste identifikovali dodatne komponente koje dodaju suvišan CSS, probajte da pokrenete [pokrivenost koda](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) u alatki Chrome DevTools. Možete da identifikujete odgovornu temu/dodatnu komponentu u URL-u stilske stranice. Potražite dodatne komponente koje na listi imaju mnogo stilskih stranica sa dosta crvenila u pokrivenosti koda. Dodatna komponenta treba da stavi stilsku stranicu na listu samo ako se stvarno koristi na stranici."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Preporučujemo da umanjite ili promenite broj [WordPress dodatnih komponenti](https://wordpress.org/plugins/) koje na stranici učitavaju JavaScript koji se ne koristi. Da biste identifikovali dodatne komponente koje dodaju suvišan JS, probajte da pokrenete [pokrivenost koda](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) u alatki Chrome DevTools. Možete da identifikujete odgovornu temu/dodatnu komponentu u URL-u skripte. Potražite dodatne komponente koje na listi imaju mnogo skripti sa dosta crvenila u pokrivenosti koda. Dodatna komponenta treba da stavi skriptu na listu samo ako se stvarno koristi na stranici."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Pročitajte više o [keširanju pregledača u WordPress-u](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Preporučujemo da koristite [WordPress dodatnu komponentu za optimizaciju slika](https://wordpress.org/plugins/search/optimize+images/) koja komprimuje slike bez gubitka kvaliteta."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Otpremajte slike direktno pomoću [biblioteke medija](https://codex.wordpress.org/Media_Library_Screen) da biste se uverili da su dostupne obavezne veličine slika, pa ih umetnite u biblioteku medija ili koristite vidžet stranice da biste se uverili da se koriste optimalne veličine slika (uključujući one za prelomne tačke koje se odazivaju). Izbegavajte korišćenje slika `Full Size` ako dimenzije nisu adekvatne za njihovo korišćenje. [Saznajte više](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Možete da omogućite komprimovanje teksta u konfiguraciji veb-servera."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Preporučujemo da koristite [dodatnu komponentu](https://wordpress.org/plugins/search/convert+webp/) ili uslugu koja automatski konvertuje otpremljene slike u optimalne formate."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr.json
new file mode 100644
index 00000000000..bf92ffa6320
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sr.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Тастери за приступ омогућавају корисницима да брзо фокусирају део странице. Да би навигација радила исправно, сваки тастер за приступ мора да буде јединствен. [Сазнајте више](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Вредности за `[accesskey]` нису јединствене"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Вредности за `[accesskey]` су јединствене"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Сваки ARIA елемент „`role`“ подржава одређени подскуп атрибута „`aria-*`“. Ако се ови елементи не подударају, атрибути „`aria-*`“ ће бити неважећи. [Сазнајте више](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Атрибути `[aria-*]` се не подударају са својим улогама"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Атрибути `[aria-*]` се подударају са својим улогама"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Поједине ARIA улоге имају обавезне атрибуте који статус елемента описују читачима екрана. [Сазнајте више](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Улоге `[role]` немају све обавезне атрибуте `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Улоге `[role]` имају све обавезне атрибуте `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Поједине надређене ARIA улоге морају да обухватају одређене подређене улоге да би правилно обављале намењене функције приступачности. [Сазнајте више](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Елементима са ARIA улогом `[role]` који захтевају да подређени елементи садрже конкретни елемент `[role]` недостају неки или сви ти потребни подређени елементи."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Елементи са ARIA улогом `[role]` који захтевају да подређени елементи садрже конкретни елемент `[role]` имају све потребне подређене елементе."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Поједине подређене ARIA улоге морају да буду обухваћене одређеним надређеним улогама да би правилно обављале намењене функције приступачности. [Сазнајте више](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Улоге `[role]` нису обухваћене својим обавезним надређеним елементом"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Улоге `[role]` су обухваћене својим обавезним надређеним елементом"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Вредности ARIA улога морају да буду важеће да би правилно обављале намењене функције приступачности. [Сазнајте више](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Вредности за `[role]` нису важеће"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Вредности за `[role]` су важеће"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Технологије за помоћ особама са инвалидитетом, попут читача екрана, не могу да интерпретирају ARIA атрибуте са неважећим вредностима. [Сазнајте више](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Вредности атрибута `[aria-*]` нису важеће"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Вредности атрибута `[aria-*]` су важеће"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Технологије за помоћ особама са инвалидитетом, попут читача екрана, не могу да интерпретирају ARIA атрибуте са неважећим називима. [Сазнајте више](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Атрибути `[aria-*]` нису важећи или су погрешно написани"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Атрибути `[aria-*]` су важећи и нису погрешно написани"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Титлови омогућавају да глуви корисници или корисници са оштећењем слуха користе аудио елементе, чиме се пружају важне информације, на пример, информације о томе која особа говори, шта говори, као и друге информације које нису везане за говор. [Сазнајте више](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Елементима `<audio>` недостаје елемент `<track>` са атрибутом `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Елементи `<audio>` садрже елемент `<track>` са атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Елементи који нису прошли проверу"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Када дугме нема назив прилагођен функцији приступачности, читачи екрана га најављују као „дугме“, па корисници који се ослањају на читаче екрана не могу да га користе. [Сазнајте више](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Дугмад нема називе прилагођене функцијама приступачности"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Дугмад има називе прилагођене функцијама приступачности"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Када се додају начини за заобилажење садржаја који се понавља, корисници тастатуре могу ефикасније да се крећу по страници. [Сазнајте више](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Страница не обухвата наслов, линк за прескакање нити регион оријентира"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Страница обухвата наслов, линк за прескакање или регион оријентира"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Многи корисници веома тешко читају текст са малим контрастом или уопште не могу да га читају. [Сазнајте више](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Боје у позадини и у првом плану немају задовољавајући однос контраста."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Боје у позадини и у првом плану имају задовољавајући однос контраста"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Када листе дефиниција нису правилно означене, читачи екрана могу да пружају збуњујући или нетачан излаз. [Сазнајте више](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` не садржи само правилно наручене групе `<dt>` и `<dd>`, елементе `<script>` или `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` садржи само правилно наручене групе`<dt>` и `<dd>`, елементе `<script>` или `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Ставке листе дефиниција (`<dt>` и `<dd>`) морају да буду упаковане у надређени елемент`<dl>` да би читачи екрана могли да их правилно читају. [Сазнајте више](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Ставке листе дефиниција су упаковане у елементе `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Ставке листе дефиниција су упаковане у елементе`<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Наслов корисницима читача екрана пружа преглед странице, а корисници претраживача се на њега ослањају да би утврдили да ли је страница релевантна за њихову претрагу. [Сазнајте више](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Документ нема елемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Документ има елемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Вредност атрибута ИД мора да буде јединствена да би се спречило да технологије за помоћ особама са инвалидитетом пропусте друге инстанце. [Сазнајте више](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Атрибути `[id]` на страници нису јединствени"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Атрибути `[id]` на страници су јединствени"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Корисници читача екрана очекују од наслова оквира да им опишу садржај оквира. [Сазнајте више](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Елементи `<frame>` или `<iframe>` немају наслов"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Елементи `<frame>` или `<iframe>` имају наслов"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Ако за страницу није наведен атрибут за језик, читач екрана претпоставља да је страница на подразумеваном језику који је корисник одабрао током подешавања читача екрана. Ако страница заправо није на подразумеваном језику, читач екрана можда неће правилно читати текст са странице. [Сазнајте више](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Елемент `<html>` нема атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Елемент `<html>` има атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Навођењем важећег кода [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) омогућава се да читач екрана правилно чита текст. [Сазнајте више](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Елемент `<html>` нема важећу вредност за свој атрибут `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Елемент `<html>` има важећу вредност за свој атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Информативни елементи треба да садрже кратки, описни алтернативни текст. Декоративни елементи могу да се занемаре празним атрибутом alt. [Сазнајте више](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Елементи слике немају атрибуте `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Елементи слика имају атрибуте `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Када се слика користи као дугме `<input>`, навођење алтернативног текста може да помогне корисницима да разумеју сврху дугмета. [Сазнајте више](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Елементи `<input type=\"image\">` не садрже текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Елементи `<input type=\"image\">` садрже текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Ознаке омогућавају да технологије за помоћ особама са инвалидитетом, попут читача екрана, правилно најављују контроле образаца. [Сазнајте више](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Елементи образаца немају повезане ознаке"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Елементи образаца имају повезане ознаке"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Табела која се користи у сврхе распореда не треба да обухвата елементе података, као што су елементи th или титл или атрибут резимеа јер то може да збуни кориснике читача екрана. [Сазнајте више](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Презентациони елементи `<table>` не избегавају употребу атрибута `<th>`, `<caption>` или `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Презентациони елементи `<table>` избегавају употребу атрибута `<th>`, `<caption>` или `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Текст линка (и алтернативни текст за слике када се користи за линкове) који је препознатљив, јединствен и може да се фокусира олакшава кретање за кориснике читача екрана. [Сазнајте више](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Назив линкова не може да се препозна"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Назив линкова може да се препозна"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Читачи екрана читају листе на посебан начин. Правилна структура листе олакшава разумевање читача екрана. [Сазнајте више](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Листе не садрже искључиво елементе `<li>` и елементе који подржавају скрипте (`<script>` и`<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Листе садрже искључиво елементе `<li>` и елементе који подржавају скрипте (`<script>` и `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Читачи екрана захтевају да ставке листе (`<li>`) буду обухваћене надређеним елементима `<ul>` или `<ol>` да би могле да се правилно читају. [Сазнајте више](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Ставке листе (`<li>`) нису обухваћене надређеним елементима`<ul>` или `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Ставке листе (`<li>`) су обухваћене надређеним елементима `<ul>` или `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Корисници не очекују да се страница аутоматски освежава и тиме се фокус премешта на почетак странице. То може да фрустира или збуњује кориснике. [Сазнајте више](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Документ користи метаознаку `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Документ не користи метаознаку `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Онемогућавање зумирања представља проблем за слабовиде кориснике који се ослањају на увећавање приказа екрана да би могли да виде садржај веб-странице. [Сазнајте више](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` се користи у елементу `<meta name=\"viewport\">` или је вредност атрибута `[maximum-scale]` мања од 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` се не користи у елементу `<meta name=\"viewport\">`, а вредност атрибута `[maximum-scale]` није мања од 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Читачи екрана не могу да преводе садржај који није текст. Додавање alt текста елементима `<object>` омогућава да читачи екрана лакше пренесу значење корисницима. [Сазнајте више](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Елементи `<object>` не садрже текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Елементи `<object>` садрже текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Вредност већа од 0 означава експлицитно наручивање навигације. Иако је технички исправно, то често фрустрира кориснике који се ослањају на технологије за помоћ особама са инвалидитетом. [Сазнајте више](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Неки елементи имају вредност за `[tabindex]` која је већа од 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Вредност ниједног елемента `[tabindex]` није већа од 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Читачи екрана имају функције које олакшавају кретање кроз табеле. Ако се побринете да се ћелије `<td>` које користе атрибут `[headers]` односе само на друге ћелије у истој табели, можете да побољшате доживљај за кориснике читача екрана. [Сазнајте више](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Ћелије у елементу `<table>` које користе атрибут `[headers]` односе се на елемент `id` који се не налази у истој табели."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Ћелије у елементу `<table>` које користе атрибут `[headers]` односе се на ћелије табеле у истој табели."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Читачи екрана имају функције које олакшавају кретање кроз табеле. Ако се побринете да се наслови табела увек односе на неку групу ћелија, можете да побољшате доживљај за кориснике читача екрана. [Сазнајте више](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Елементи `<th>` и елементи са атрибутом`[role=\"columnheader\"/\"rowheader\"]` немају ћелије са подацима које описују."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Елементи `<th>` и елементи са атрибутом `[role=\"columnheader\"/\"rowheader\"]` имају ћелије са подацима које описују."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Навођењем важећег кода [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) у елементима омогућава се да читач екрана правилно чита текст. [Сазнајте више](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Вредност атрибута `[lang]` није важећа"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Атрибути `[lang]` имају важећу вредност"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Када је доступан титл за видео, глуви корисници и они са оштећењем слуха лакше могу да приступају информацијама које видео обухвата. [Сазнајте више](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Елементи `<video>` не обухватају елемент `<track>` са атрибутом `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Елементи `<video>` садрже елемент `<track>` са атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Аудио описи пружају релевантне информације за видео снимке које дијалог не може, попут израза лица и сцена. [Сазнајте више](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Елементи `<video>` не обухватају елемент `<track>` са атрибутом `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Елементи `<video>` садрже елемент `<track>` са атрибутом `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Да би изглед на iOS-у био идеалан када корисници додају прогресивну веб-апликацију на почетни екран, дефинишите икону `apple-touch-icon`. Она мора да усмерава на нетранспарентни квадратни PNG од 192 пиксела (или 180 пиксела). [Сазнајте више](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Не пружа важећи атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Атрибут `apple-touch-icon-precomposed` је застарео; препоручује се `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Пружа важећи атрибут `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Додаци за Chrome су негативно утицали на брзину учитавања ове странице. Пробајте да проверите страницу у режиму без архивирања или са Chrome профила без додатака."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Процена скрипта"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Рашчлањивање скрипта"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Укупно CPU време"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Препоручујемо вам да смањите време потребно за рашчлањивање, компајлирање и извршавање JS датотека. Приказивање мањих JS ресурса ће вам можда помоћи у томе. [Сазнајте више](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Смањите време извршавања JavaScript датотека"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Време извршавања JavaScript-а"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Велики GIF-ови нису корисни за приказивање анимираног садржаја. Препоручујемо вам да уместо GIF-ова користите MPEG4/WebM видео снимке за анимације и PNG/WebP за статичне слике да бисте уштедели мрежне податке. [Сазнајте више](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Користите видео формате за анимирани садржај"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Препоручујемо вам да одложите учитавање слика ван екрана и скривених слика док се сви веома важни ресурси не учитају како бисте смањили време до почетка интеракције. [Сазнајте више](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Одложите слике ван екрана"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ресурси блокирају прво приказивање странице. Препоручујемо вам да приказујете све важне JS/CSS датотеке у тексту и да одложите све JS датотеке/стилове који нису толико важни. [Сазнајте више](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Елиминишите ресурсе који блокирају приказивање"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Велике мрежне ресурсе корисници морају да плате стварним новцем и они су веома повезани са дугим временима учитавања. [Сазнајте више](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Укупна величина је била {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Избегавајте огромне мрежне ресурсе"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Избегава огромне мрежне ресурсе"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Умањивањем CSS датотека можете да смањите величине мрежних ресурса. [Сазнајте више](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Умањите CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Умањивање JavaScript датотека може да смањи величине ресурса и време рашчлањивања скрипта. [Сазнајте више](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Умањите JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Уклоните неактивна правила из описа стилова и одложите учитавање CSS-а који се не користи за садржај изнад прелома да бисте смањили непотребну потрошњу података током мрежних активности. [Сазнајте више](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Уклоните некоришћени CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Уклоните некоришћени JavaScript да бисте смањили потрошњу података током мрежних активности."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Уклоните некоришћени JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Дуго трајање кеша може да убрза поновне посете страници. [Сазнајте више](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Пронађен је 1 ресурс}one{Пронађен је # ресурс}few{Пронађена су # ресурса}other{Пронађено је # ресурса}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Приказујте статичне елементе са ефикасним смерницама кеша"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Користи ефикасне смернице кеша на статичним елементима"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Оптимизоване слике се учитавају брже и троше мање мобилних података. [Сазнајте више](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Ефикасно кодирајте слике"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Приказујте слике одговарајуће величине да бисте уштедели мобилне податке и побољшали време учитавања. [Сазнајте више](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Одредите одговарајућу величину слика"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Ресурсе засноване на тексту треба да приказујете у компримованом формату (gzip, deflate или brotli) да бисте смањили укупну количину потрошених мрежних података. [Сазнајте више](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Омогућите компресију текста"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Формати слика као што су JPEG 2000, JPEG XR и WebP често пружају бољу компресију него PNG или JPEG, што подразумева бржа преузимања и мању потрошњу података. [Сазнајте више](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Приказујте слике у форматима следеће генерације"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Ако се ширина садржаја апликације не подудара са ширином области приказа, апликација можда није оптимизована за екране на мобилним уређајима. [Сазнајте више](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Величина области приказа од {innerWidth} пиксела се не подудара са величином прозора од {outerWidth} пиксела."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Садржај није одговарајуће величине за област приказа"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Садржај је одговарајуће величине за област приказа"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Ланци веома важних захтева у наставку вам приказују који ресурси се учитавају са високим приоритетом. Препоручујемо вам да смањите дужину ланаца, да смањите величину преузимања за ресурсе или да одложите преузимање ресурса који нису неопходни ради бржег учитавања странице. [Сазнајте више](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Пронађен је 1 ланац}one{Пронађен је # ланац}few{Пронађена су # ланца}other{Пронађено је # ланаца}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Смањите број веома важних захтева"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Застарело/упозорење"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Ред"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Застарели API-ји ће на крају бити уклоњени из прегледача. [Сазнајте више](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Откривено је 1 упозорење}one{Откривено је # упозорење}few{Откривена су # упозорења}other{Откривено је # упозорења}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Користи застареле API-је"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Избегава застареле API-је"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Кеш апликације је застарео. [Сазнајте више](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Пронађено је „{AppCacheManifest}“"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Користи кеш апликације"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Избегава кеш апликације"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Навођењем doctype-а спречава се прелазак на архајски режим прегледача. [Сазнајте више](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Назив за doctype мора да буде стринг написан малим словима `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Документ мора да садржи doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Очекивани publicId ће бити празан стринг"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Очекивани systemId ће бити празан стринг"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Страници недостаје HTML doctype, па се активира архајски режим"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Страница има HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Елемент"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Статистика"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Вредност"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Инжењери за прегледаче препоручују да странице садрже мање од приближно 1500 DOM елемената. Најбоље би било да дубина стабла буде испод 32 елемента и да има мање од 60 подређених/надређених елемената. Велики DOM може да повећа потрошњу меморије, да изазове дужа [израчунавања стилова](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) и да доведе до скупих [преобликовања изгледа](https://developers.google.com/speed/articles/reflow). [Сазнајте више](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 елемент}one{# елемент}few{# елемента}other{# елемената}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Избегавајте превелику величину DOM-а"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Максимална дубина DOM-а"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Укупан број DOM елемената"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Максималан број подређених елемената"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Избегава превелику величину DOM-а"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Циљ"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Додајте `rel=\"noopener\"` или`rel=\"noreferrer\"` свим спољним линковима да бисте побољшали учинак и спречили безбедносне пропусте. [Сазнајте више](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Линкови до одредишта из других извора нису безбедни"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Линкови до одредишта из других извора су безбедни"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Није могуће одредити одредиште за текст линка ({anchorHTML}). Ако се не користи као хиперлинк, препоручујемо вам да уклоните target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Корисници немају поверења у сајтове који траже њихову локацију без контекста или их такви сајтови збуњују. Препоручујемо вам да уместо тога повежете захтев са радњом коју обавља корисник. [Сазнајте више](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Тражи дозволу за геолоцирање при учитавању странице"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Избегавајте тражење дозволе за геолоцирање при учитавању странице"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Верзија"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Све корисничке JavaScript библиотеке откривене на овој страници. [Сазнајте више](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Откривене су JavaScript библиотеке"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Ако корисници имају споре везе, спољне скрипте које се динамички убацују помоћу атрибута `document.write()` могу да одложе учитавање странице за десетине секунди. [Сазнајте више](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Користи `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Избегава атрибут `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Највиши ниво озбиљности"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Верзија библиотеке"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Број пропуста"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Неке независне скрипте могу да обухватају познате безбедносне пропусте које нападачи могу лако да препознају и искористе. [Сазнајте више](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Откривен је 1 пропуст}one{Откривен је # пропуст}few{Откривена су # пропуста}other{Откривено је # пропуста}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Обухвата корисничке JavaScript датотеке са познатим безбедносним пропустима"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Висока"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Ниска"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Средња"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Избегава корисничке JavaScript датотеке са познатим безбедносним пропустима"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Корисници немају поверења у сајтове који траже дозволу за слање обавештења без контекста или их такви сајтови збуњују. Препоручујемо вам да уместо тога повежете захтев са покретима корисника. [Сазнајте више](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Тражи дозволу за обавештења при учитавању странице"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Избегавајте тражење дозволе за обавештења при учитавању странице"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Елементи који нису прошли проверу"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Спречавање лепљења лозинке нарушава добре смернице за безбедност. [Сазнајте више](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Спречава кориснике да налепе вредност у поља за лозинке"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Дозвољава корисницима да налепе вредност у поља за лозинке"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Протокол"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 има бројне предности у односу на HTTP/1.1, укључујући бинарна заглавља, мултиплексирање и серверски пуш. [Сазнајте више](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 захтев није испоручен преко протокола HTTP/2}one{# захтев није испоручен преко протокола HTTP/2}few{# захтева нису испоручена преко протокола HTTP/2}other{# захтева није испоручено преко протокола HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Не користи HTTP/2 за све своје ресурсе"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Користи HTTP/2 за своје ресурсе"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Препоручујемо вам да пасивне обрађиваче догађаја означите као `passive` да бисте побољшали резултате померања. [Сазнајте више](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Не користите пасивне обрађиваче да бисте побољшали учинак померања"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Користите пасивне обрађиваче да бисте побољшали учинак померања"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Опис"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Грешке евидентиране у конзоли указују на нерешене проблеме. Оне су резултат неуспелих мрежних захтева и других проблема у вези са прегледачем. [Сазнајте више](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Грешке прегледача су евидентиране у конзоли"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Ниједна грешка прегледача није евидентирана у конзоли"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Искористите CSS функцију за приказ фонтова да бисте били сигурни да корисник може да види текст док се веб-фонтови учитавају. [Сазнајте више](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Побрините се да текст остане видљив током учитавања веб-фонтова"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Сав текст остаје видљив током учитавања веб-фонтова"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse није успео да аутоматски провери вредност за приказ фонтова за следећи URL: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Размера (стварна)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Размера (приказана)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Димензије приказа слике треба да се подударају са природном размером. [Сазнајте више](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Приказује слике са погрешном размером"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Приказује слике са тачном размером"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Неважеће информације о величини слике {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Прегледачи могу проактивно да траже од корисника да додају апликацију на почетни екран, што може да доведе до већег ангажовања. [Сазнајте више](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Манифест веб-апликације не задовољава услове за инсталирање"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Манифест веб-апликације задовољава услове за инсталирање"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Небезбедан URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Сви сајтови треба да буду заштићени HTTPS-ом, чак и они који не обрађују осетљиве податке. HTTPS спречава уљезе да неовлашћено приступају комуникацији између апликације и корисника или да је пасивно слушају. Он је предуслов за HTTP/2 i API-је бројних нових веб-платформи. [Сазнајте више](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Пронађен је 1 небезбедан захтев}one{Пронађен је # небезбедан захтев}few{Пронађена су # небезбедна захтева}other{Пронађено је # небезбедних захтева}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Не користи HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Користи HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Брзо учитавање странице преко мобилне мреже обезбеђује добар доживљај корисницима мобилних уређаја. [Сазнајте више](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Интерактивно за {timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Интерактивна на симулираној мобилној мрежи за {timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Страница се преспоро учитава и не постаје интерактивна у року од 10 секунди. Погледајте прилике и дијагностику у одељку „Учинак“ да бисте сазнали како да побољшате учинак странице."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Учитавање странице није довољно брзо на мобилним мрежама"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Учитавање странице је довољно брзо на мобилним мрежама"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Категорија"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Препоручујемо вам да смањите време потребно за рашчлањивање, компајлирање и извршавање JS датотека. Приказивање мањих JS ресурса ће вам можда помоћи у томе. [Сазнајте више](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Смањите рад главне нити"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Смањује рад главне нити"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Да би имали што више корисника, сајтови треба да раде у свим значајнијим прегледачима. [Сазнајте више](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Сајт ради у различитим веб-прегледачима"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Уверите се да до појединачних страница воде прецизни линкови преко URL-ова и да су URL-ови јединствени у сврху дељења на друштвеним медијима. [Сазнајте више](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Свака страница има URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Корисници треба да имају утисак да су прелази брзи док додирују ставке, чак и на спорој мрежи. Овај доживљај је кључан за утисак који ће корисник имати о учинку. [Сазнајте више](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Преласци са странице на страницу не делују као да се блокирају због мреже"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Процењено кашњење уноса је процена времена које је апликацији потребно да одговори на унос корисника, у милисекундама, током најпрометнијег рока од 5 секунди за учитавање странице. Ако је кашњење веће од 50 ms, корисници ће можда сматрати да апликација ради споро. [Сазнајте више](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Процењено кашњење уноса"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Прво приказивање садржаја означава време када се приказују први текст или слика. [Сазнајте више](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Прво приказивање садржаја"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Време првог неактивног процесора означава први тренутак у ком је главна нит странице довољно неактивна да би обрадила унос. [Сазнајте више](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Време првог неактивног процесора"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Прво значајно приказивање означава време када примарни садржај странице постаје видљив. [Сазнајте више](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Прво значајно приказивање"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Време до интеракције је количина времена која је потребна да би страница постала потпуно интерактивна. [Сазнајте више](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Време почетка интеракције"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Максимално потенцијално кашњење првог уноса које може да се деси корисницима је трајање најдужег задатка у милисекундама. [Сазнајте више](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Макс. потенцијално кашњење првог приказа"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Индекс брзине приказује колико брзо садржај странице постаје видљив за кориснике. [Сазнајте више](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Индекс брзине"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Збир свих периода између FCP-а и времена до почетка интеракције, када задатак траје дуже од 50 ms, изражено у милисекундама."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Укупно време блокирања"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Трајања повратног пута (RTT) мреже знатно утичу на учинак. Ако је трајање повратног пута до почетне локације велико, то значи да би сервери који су ближи кориснику могли да побољшају учинак. [Сазнајте више](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Трајања повратног пута мреже"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Кашњења сервера могу да утичу на учинак веба. Ако је кашњење сервера за почетну локацију велико, то значи да је сервер преоптерећен или да има слаб позадински учинак. [Сазнајте више](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Позадинска кашњења сервера"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Сервисер омогућава да веб-апликација буде поуздана у непредвидивим условима мреже. [Сазнајте више](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` не одговара кодом 200 када је офлајн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` одговара кодом 200 када је офлајн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse није успео да прочита `start_url` из манифеста. Као последица тога, претпоставили смо да је `start_url` URL документа. Порука о грешци: „{manifestWarning}“."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Премашује циљ"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Захтеве за количину и величину мреже одржавајте испод граница одређених циљевима за учинак. [Сазнајте више](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 захтев}one{# захтев}few{# захтева}other{# захтева}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Циљ за учинак"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Ако сте већ подесили HTTPS, уверите се да преусмеравате сав HTTP саобраћај на HTTPS да бисте омогућили безбедне веб-функције за све кориснике. [Сазнајте више](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Не преусмерава HTTP саобраћај на HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Преусмерава HTTP саобраћај на HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Преусмеравања доводе до додатних кашњења пре учитавања странице. [Сазнајте више](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Избегавајте вишеструка преусмеравања странице"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Да бисте подесили циљеве за количину и величину ресурса странице, додајте датотеку budget.json file. [Сазнајте више](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 захтев • {byteCount, number, bytes} KB}one{# захтев • {byteCount, number, bytes} KB}few{# захтева • {byteCount, number, bytes} KB}other{# захтева • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Омогући да број захтева и величине преноса буду мали"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Канонички линкови предлажу који URL треба да се прикаже у резултатима претраге. [Сазнајте више](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Више неусаглашених URL-ова ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Усмерава ка другом домену ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Неважећи URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Усмерава на другу `hreflang` локацију ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Релативни URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Усмерава на основни URL домена (почетну страницу), уместо еквивалентне странице садржаја"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Документ нема важећу вредност `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Документ има важећи атрибут `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Величине фонтова испод 12 пиксела су премале да би биле читљиве и због њих корисници на мобилним уређајима морају да „зумирају прстима“ како би могли да читају садржај. Потрудите се да >60% текста странице буде ≥12 пиксела. [Сазнајте више](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} читљивог текста"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Текст није читљив јер не постоји метаознака области приказа која је оптимизована за екране на мобилним уређајима."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} текста је премало (на основу узорка од {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Документ не користи читљиве величине фонтова"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Документ користи читљиве величине фонтова"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Линкови hreflang обавештавају претраживаче коју верзију странице треба да наведу у резултатима претраге за дати језик или регион. [Сазнајте више](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Документ нема важећи атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Документ има важећи атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Странице са неуспешним HTTP кодовима статуса можда неће бити правилно индексиране. [Сазнајте више](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Страница има неуспешан HTTP кôд статуса"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Страница има успешан HTTP кôд статуса"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Претраживачи не могу да уврсте странице у резултате претраге ако немају дозволу да их пописују. [Сазнајте више](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Индексирање странице је блокирано"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Индексирање странице није блокирано"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Описни текст у линковима помаже претраживачима да разумеју садржај. [Сазнајте више](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Пронађен је 1 линк}one{Пронађен је # линк}few{Пронађена су # линка}other{Пронађено је # линкова}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Линкови немају описни текст"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Линкови имају описни текст"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Покрените [алатку за тестирање структурираних података](https://search.google.com/structured-data/testing-tool/) и [алатку за анализирање структурираних података](http://linter.structured-data.org/) да бисте проценили структуриране податке. [Сазнајте више](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Структурирани подаци су важећи"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Метаописи могу да буду уврштени у резултате претраге да би пружили сажети резиме садржаја странице. [Сазнајте више](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Поље за текст описа је празно."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Документ нема метаопис"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Документ има метаопис"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Претраживачи не могу да индексирају садржај додатних компонената, а многи уређаји ограничавају додатне компоненте или их не подржавају. [Сазнајте више](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Документ користи додатне компоненте"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Документ избегава додатне компоненте"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Ако датотека robots.txt није правилно направљена, пописивачи можда неће моћи да разумеју како желите да се веб-сајт попише или индексира. [Сазнајте више](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Захтев за датотеку robots.txt вратио је HTTP статус: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Пронађена је 1 грешка}one{Пронађена је # грешка}few{Пронађене су # грешке}other{Пронађено је # грешака}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse није успео да преузме датотеку robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Датотека robots.txt није важећа"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Датотека robots.txt је важећа"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Интерактивни елементи попут дугмади и линкова треба да буду довољно велики (48×48 пиксела) и да имају довољно простора око себе да би било лако да се додирну без преклапања са другим елементима. [Сазнајте више](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} циљева додиривања има одговарајућу величину"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Циљеви додиривања су премали јер не постоји метаознака области приказа која је оптимизована за екране на мобилним уређајима"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Циљеви додиривања немају одговарајућу величину"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Циљ који се преклапа"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Циљ додиривања"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Циљеви додиривања имају одговарајућу величину"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Сервисер је технологија која омогућава апликацији да користи многе функције прогресивних веб-апликација, попут офлајн рада, додавања на почетни екран и искачућих обавештења. [Сазнајте више](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Ову страницу контролише сервисер, али није пронађен ниједан `start_url` јер није успело рашчлањивање манифеста као важеће JSON датотеке"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Ову страницу контролише сервисер, али `start_url` ({startUrl}) не спада у опсег сервисера ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Ову страницу контролише сервисер, али није пронађен ниједан `start_url` јер ниједан манифест није преузет."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Овај извор има један или више сервисера, али страница ({pageUrl}) није у опсегу."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Не региструје сервисер који контролише страницу и `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Региструје сервисер који контролише страницу и `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Тематски уводни екран обезбеђује квалитетан доживљај када корисници покрећу апликацију са почетних екрана. [Сазнајте више](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Није конфигурисано за прилагођени уводни екран"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Конфигурисано за прилагођени уводни екран"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Трака за адресу прегледача може да има тему која одговара сајту. [Сазнајте више](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Не подешава боју теме за траку за адресу."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Подешава боју теме за траку за адресу."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Период блокирања главне нити"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Независни добављач"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Кôд независног добављача може значајно да утиче на учинак учитавања. Ограничите број сувишних независних добављача услуге и пробајте да учитате кôд независног добављача када страница примарно заврши са учитавањем. [Сазнајте више](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Кôд независног добављача је блокирао главну нит {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Смањите утицај кода независног добављача"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Независна употреба"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Време првог одговора одређује време у које сервер шаље одговор. [Сазнајте више](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Основном документу је требало {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Смањите времена одговора сервера (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Времена одговора сервера су кратка (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Трајање"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Време почетка"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Тип"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Препоручујемо вам да опремите апликацију API-јем за време корисника да бисте измерили учинак апликације у реалном свету током кључних корисничких доживљаја. [Сазнајте више](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 време корисника}one{# време корисника}few{# времена корисника}other{# времена корисника}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Ознаке и мере Времена корисника"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Повезивање унапред <link> је пронађено за „{securityOrigin}“, али га прегледач није употребио. Проверите да ли правилно користите атрибут `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Размислите о томе да додате савете за ресурсе `preconnect` или `dns-prefetch` како бисте успоставили ране везе са важним изворима трећих страна. [Сазнајте више](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Повежите се унапред са потребним изворима"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Предучитавање <link> је пронађено за „{preloadURL}“, али га прегледач није употребио. Проверите да ли правилно користите атрибут `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Препоручујемо вам да користите `<link rel=preload>` како бисте касније током учитавања странице дали приоритет преузимању ресурса који се тренутно траже. [Сазнајте више](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Унапред учитајте најважније захтеве"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Додајте ознаку `<meta name=\"viewport\">` да бисте оптимизовали апликацију за екране на мобилним уређајима. [Сазнајте више](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Није пронађена ознака `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Нема ознаку `<meta name=\"viewport\">` са ознакама `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Има ознаку `<meta name=\"viewport\">` са ознаком `width` или `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Апликација треба да приказује неки садржај када је JavaScript онемогућен, чак и ако је то само упозорење кориснику да је JavaScript обавезан за коришћење апликације. [Сазнајте више](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Тело странице треба да приказује неки садржај ако јој скрипте нису доступне."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Не пружа резервни садржај када JavaScript није доступан"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Има неки садржај када JavaScript није доступан"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Ако правите прогресивну веб-апликацију, размислите о томе да користите сервисер како би апликација могла да ради офлајн. [Сазнајте више](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Актуелна страница не одговара кодом 200 када је офлајн"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Актуелна страница одговара кодом 200 када је офлајн"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Страница се можда не учитава офлајн зато што је пробни URL ({requested}) преусмерен на „{final}“. Пробајте директно да тестирате други URL."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "То су прилике да побољшате коришћење ARIA улога у апликацији, чиме може да побољша доживљај корисника технологије за помоћ особама са инвалидитетом, као што је читач екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "То су прилике да пружите алтернативни садржај за аудио и видео датотеке. То може да побољша доживљај за кориснике са оштећеним слухом или видом."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Звук и видео"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ове ставке истичу уобичајене најбоље праксе у вези са приступачношћу."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Најбоље праксе"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ове провере истичу прилике за [побољшање приступачности веб-апликације](https://developers.google.com/web/fundamentals/accessibility). Аутоматски може да се открије само један подскуп проблема са приступачношћу, па препоручујемо да обављате и ручно тестирање."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ове ставке обрађују области које алатка за аутоматизовано тестирање не може да обухвати. Сазнајте више у водичу о [спровођењу прегледа приступачности](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Приступачност"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "То су прилике да побољшате читљивост садржаја."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Контраст"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "То су прилике да побољшате тумачење свог садржаја за кориснике на различитим језицима."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Интернационализација и локализација"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "То су прилике да побољшате семантику контрола у апликацији. То може да побољша доживљај корисника технологије за помоћ особама са инвалидитетом, као што је читач екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Називи и ознаке"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ово су прилике да побољшате кретање по тастатури у апликацији."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Навигација"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "То су прилике за побољшање доживљаја при читању података из табела и листа помоћу технологије за помоћ особама са инвалидитетом, попут читача екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Табеле и листе"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Најбоље праксе"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Циљевима за учинак одређују се стандарди за учинак сајта."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Циљеви"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Више информација о учинку апликације. Ови бројеви не [утичу директно](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) на оцену учинка."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Дијагностика"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Најважнији аспект учинка је брзина којом се пиксели приказују на екрану. Кључни показатељи: Прво приказивање садржаја, Прво значајно приказивање"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Побољшања првог приказивања"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ови предлози могу да вам помогну да се страница учитава брже. Не [утичу директно](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) на оцену учинка."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Могућности"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Показатељи"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Побољшајте општи доживљај учитавања да би страница почела да се одазива и да би била спремна за коришћење у најкраћем могућем року. Кључни показатељи: Време почетка интеракције, Индекс брзине"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Општа побољшања"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Учинак"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Овим проверама се оцењују аспекти прогресивне веб-апликације. [Сазнајте више](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ове провере захтева основна [Контролна листа за прогресивне веб-апликације](https://developers.google.com/web/progressive-web-apps/checklist), али их Lighthouse не спроводи аутоматски. Оне не утичу на ваш резултат, али је важно да их ручно потврдите."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Прогресивна веб-апликација"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Брзо и поуздано"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Може да се инсталира"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Оптимизовано за PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Захваљујући овим проверама страница ће сигурно бити оптимизована за рангирање резултата претраживача. Има још неких фактора које Lighthouse не проверава, а који могу да утичу на рангирање у претрази. [Сазнајте више](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Покрећите ове додатне валидаторе на сајту да бисте проверили додатне најбоље праксе оптимизације за претраживаче."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Оптимизација за претраживаче"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Форматирајте HTML садржај на начин који омогућава пописивачима да боље разумеју садржај апликације."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Најбоље праксе за садржај"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Да би се апликација појавила у резултатима претраге, пописивачи треба да имају приступ до ње."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Пописивање и индексирање"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Уверите се да су странице прилагођене мобилним уређајима да корисници не би морали да умањују или увећавају приказ како би читали странице са садржајем. [Сазнајте више](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Прилагођено мобилним уређајима"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Време преживљавања кеша"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Локација"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Назив"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Захтеви"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Тип ресурса"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Величина"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Проведено време"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Величина преноса"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Потенцијална уштеда"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Потенцијална уштеда"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Потенцијална уштеда од {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Потенцијална уштеда од {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Документ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Фонт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Слика"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Медији"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Друго"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Скрипта"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} сек"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Опис стила"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Независни ресурси"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Укупно"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Дошло је до грешке при евидентирању трага током учитавања странице. Поново покрените Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Временско ограничење чекања на иницијалну везу за протокол програма за отклањање грешака."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome није прикупио ниједан снимак екрана током учитавања странице. Уверите се да је садржај видљив на страници, па пробајте да поново покренете Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS сервери нису могли да разреше наведени домен."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Прикупљач за обавезни ресурс {artifactName} је наишао на грешку: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Дошло је до интерне грешке у Chrome-у. Поново покрените Chrome и пробајте да поново покренете Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Прикупљач за обавезни ресурс {artifactName} се није покренуо."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse није успео да поуздано учита страницу коју сте захтевали. Уверите се да тестирате одговарајући URL и да сервер правилно одговара на све захтеве."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse није успео да поуздано учита URL који сте захтевали јер је страница престала да реагује."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL који сте навели нема важећи безбедносни сертификат. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome је спречио учитавање странице са транзитивним огласом. Уверите се да тестирате одговарајући URL и да сервер правилно одговара на све захтеве."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse није успео да поуздано учита страницу коју сте захтевали. Уверите се да тестирате одговарајући URL и да сервер правилно одговара на све захтеве. (Детаљи: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse није успео да поуздано учита страницу коју сте захтевали. Уверите се да тестирате одговарајући URL и да сервер правилно одговара на све захтеве. (Кôд статуса: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Учитавање странице је трајало предуго. Пратите прилике у извештају да бисте скратили време учитавања странице, па поново покрените Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Одговор протокола DevTools се чека дуже од додељеног периода. (Метод: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Преузимање садржаја ресурса траје дуже од додељеног периода."
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Изгледа да је URL који сте навели неважећи."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Прикажи провере"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Почетна навигација"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Максимално кашњење критичне путање:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Грешка!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Пријављивање грешке: нема информација о провери"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Подаци о експерименталним функцијама"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) анализа актуелне странице емулиране помоћу мобилне мреже. Вредности представљају процене и могу да варирају."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Додатне ставке за ручну проверу"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Није примењиво"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Могућност"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Процењена уштеда"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Провере са задовољавајућом оценом"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Скупи фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Прошири фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Прикажи независне ресурсе"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Било је извесних проблема који су утицали на ово покретање Lighthouse-а:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Вредности представљају процене и могу да варирају. Оцена учинка се [заснива само на овим показатељима](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Провере са задовољавајућом оценом које садрже упозорења"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Упозорења: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Предлажемо да отпремите GIF у услугу која ће га кодирати за уградњу у HTML5 видео."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Инсталирајте [WordPress додатну компоненту за лако учитавање](https://wordpress.org/plugins/search/lazy+load/) која омогућава да одложите све слике ван екрана или да пређете на тему која пружа ту функцију. Препоручујемо и да користите [додатну компоненту за AMP странице](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Неке WordPress додатне компоненте могу да вам помогну да [уметнете критичне елементе](https://wordpress.org/plugins/search/critical+css/) или [одложите мање важне ресурсе](https://wordpress.org/plugins/search/defer+css+javascript/). Имајте на уму да оптимизације које пружају ове додатне компоненте могу да оштете функције или теме додатних компоненти, па ћете вероватно морати да уносите промене у кôд."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Теме, додатне компоненте и спецификације сервера доприносе времену одговора сервера. Препоручујемо да пронађете оптимизованију тему, пажљиво изаберете додатну компоненту за оптимизацију и/или надоградите сервер."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Препоручујемо да прикажете одломке у листама постова (на пример, преко још ознака), смањите број постова који се приказују на одређеној страници, раздвојите дугачке постове на више странциа или користите додатну компоненту за лако учитавање коментара."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Неке [WordPress додатне компоненте](https://wordpress.org/plugins/search/minify+css/) могу да убрзају сајт тако што повезују, умањују и компримују стилове. Ово умањивање можете да обавите и унапред помоћу процеса дизајнирања ако је могуће."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Неке [WordPress додатне компоненте](https://wordpress.org/plugins/search/minify+javascript/) могу да убрзају сајт тако што повезују, умањују и компримују скрипте. Ово умањивање можете да обавите и унапред помоћу процеса дизајнирања ако је могуће."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Препоручујемо да умањите или промените број [WordPress додатних компоненти](https://wordpress.org/plugins/) које на страници учитавају CSS који се не користи. Да бисте идентификовали додатне компоненте које додају сувишан CSS, пробајте да покренете [покривеност кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) у алатки Chrome DevTools. Можете да идентификујете одговорну тему/додатну компоненту у URL-у стилске странице. Потражите додатне компоненте које на листи имају много стилских страница са доста црвенила у покривености кода. Додатна компонента треба да стави стилску страницу на листу само ако се стварно користи на страници."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Препоручујемо да умањите или промените број [WordPress додатних компоненти](https://wordpress.org/plugins/) које на страници учитавају JavaScript који се не користи. Да бисте идентификовали додатне компоненте које додају сувишан JS, пробајте да покренете [покривеност кода](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) у алатки Chrome DevTools. Можете да идентификујете одговорну тему/додатну компоненту у URL-у скрипте. Потражите додатне компоненте које на листи имају много скрипти са доста црвенила у покривености кода. Додатна компонента треба да стави скрипту на листу само ако се стварно користи на страници."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Прочитајте више о [кеширању прегледача у WordPress-у](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Препоручујемо да користите [WordPress додатну компоненту за оптимизацију слика](https://wordpress.org/plugins/search/optimize+images/) која компримује слике без губитка квалитета."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Отпремајте слике директно помоћу [библиотеке медија](https://codex.wordpress.org/Media_Library_Screen) да бисте се уверили да су доступне обавезне величине слика, па их уметните у библиотеку медија или користите виџет странице да бисте се уверили да се користе оптималне величине слика (укључујући оне за преломне тачке које се одазивају). Избегавајте коришћење слика `Full Size` ако димензије нису адекватне за њихово коришћење. [Сазнајте више](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Можете да омогућите компримовање текста у конфигурацији веб-сервера."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Препоручујемо да користите [додатну компоненту](https://wordpress.org/plugins/search/convert+webp/) или услугу која аутоматски конвертује отпремљене слике у оптималне формате."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sv.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sv.json
new file mode 100644
index 00000000000..c9d8d6a3f7b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/sv.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Med åtkomsttangenter kan användaren snabbt flytta fokus till en viss del av sidan. Ingen åtkomsttangent får användas flera gånger om navigeringen ska fungera ordentligt. [Läs mer](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Alla värden på `[accesskey]` är inte unika"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` värden är unika"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Varje ARIA-`role` har stöd för ett visst antal attribut av typen `aria-*`. Om dessa inte överensstämmer blir attributen av typen `aria-*` ogiltiga. [Läs mer](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Alla attribut av typen `[aria-*]` stämmer inte med elementets roll"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Attributen av typen `[aria-*]` stämmer med elementets roll"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Vissa ARIA-roller har obligatoriska attribut som beskriver elementets tillstånd för skärmläsare. [Läs mer](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Vissa element med attributet `[role]` har inte alla obligatoriska attribut av typen `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Alla element med `[role]`-attribut har alla obligatoriska attribut av typen `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Vissa överordnade element med ARIA-attributet role måste ha vissa underordnade element med role för att hjälpmedlen ska fungera som avsett. [Läs mer](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Några eller alla obligatoriska underordnade element med `[role]` saknas för element med ARIA-rollen `[role]`."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Alla obligatoriska underordnade element med `[role]` används för element med ARIA-rollen `[role]`."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Vissa underordnade element med ARIA-attributet role måste ha ett bestämt överordnat element med role för att hjälpmedlen ska fungera som avsett. [Läs mer](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Det finns element med `[role]`-attribut utan ett obligatoriskt överordnat element"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Rätt överordnat element används för alla element med `[role]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Alla ARIA-rollattribut måste ha giltiga värden om de ska fungera som avsett med hjälpmedlen. [Läs mer](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Vissa `[role]`-värden är inte giltiga"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Alla `[role]`-värden är giltiga"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Skärmläsare och andra hjälpmedel kan inte tolka ARIA-attribut med ogiltiga värden. [Läs mer](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Alla attribut av typen `[aria-*]` har inte ett giltigt värde"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Alla attribut av typen `[aria-*]` har giltiga värden"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Skärmläsare och andra hjälpmedel kan inte tolka ARIA-attribut med ogiltiga namn. [Läs mer](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Vissa attribut av typen `[aria-*]` är ogiltiga eller felstavade"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Alla attribut av typen `[aria-*]` är giltiga och rättstavade"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Textningen ger döva och hörselskadade viktig information om vem som talar, vad de säger och andra ljud som inte är tal. [Läs mer](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Alla `<audio>`-element har inte ett underordnat `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Alla `<audio>`-element innehåller ett `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Element med fel"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Utan ett igenkännligt namn läses knappen upp som ”knapp” av skärmläsarna. Det gör knappen oanvändbar för den som behöver använda en skärmläsare. [Läs mer](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Vissa knappar har inte namn som hjälpmedlen kan använda"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Alla knappar har namn som hjälpmedlen kan använda"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Om du lägger till ett sätt att hoppa över innehåll som upprepas går det att navigera effektivare på sidan för den som använder tangentbordet. [Läs mer](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Sidan saknar rubrik, överhoppningslänk eller landmärkesområde"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Sidan har en rubrik, en överhoppningslänk eller ett landmärkesområde"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Text med låg kontrast blir svårläst eller oläslig för många användare. [Läs mer](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Kontrasten mellan bakgrundsfärg och förgrundsfärg är inte tillräckligt stor."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Kontrasten mellan bakgrundsfärg och förgrundsfärg är tillräckligt stor"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Om en definitionslista inte har märkts upp korrekt kan den läsas upp på ett missvisande eller felaktigt sätt av skärmläsare. [Läs mer](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Det finns `<dl>`-element som inte enbart består av `<dt>`- och `<dd>`-grupper i rätt ordning, `<script>`- och `<template>`-element."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Alla `<dl>`-element består enbart av `<dt>`- och `<dd>`-grupper i rätt ordning, `<script>`- eller `<template>`-element."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Alla poster i definitionslistor (`<dt>` och `<dd>`) måste ha överordnade `<dl>`-element så att de kan presenteras korrekt av skärmläsare. [Läs mer](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Vissa poster i definitionslistor har inte bäddats in i `<dl>`-element"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Alla poster i definitionslistor har bäddats in i `<dl>`-element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Titeln ger den som använder skärmläsare en uppfattning om vad sidan handlar om. Dessutom fyller sidtiteln en viktig funktion i sökmotorer när användarna väljer ut sidor som verkar vara relevanta för sökningen. [Läs mer](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokumentet har inget `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Dokumentet har ett `<title>`-element"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Alla id-attribut måste ha unika värden. Hjälpmedelstekniken skulle annars hoppa över dubblettförekomsterna av ett värde. [Läs mer](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Alla `[id]`-attribut på sidan är inte unika"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Alla `[id]`-attribut på sidan är unika"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Med en skärmläsare behövs namn på ramarna som beskriver vad ramen innehåller. [Läs mer](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Vissa `<frame>`- eller `<iframe>`-element saknar titel"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Alla `<frame>`- eller `<iframe>`-element har en titel"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Om inget lang-attribut har angetts för en sida används skärmläsarens standardspråk, det vill säga det språk som användaren valde när skärmläsaren konfigurerades. Om sidan inte är på det språket kanske texten inte läses upp korrekt. [Läs mer](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>`-elementet har inget `[lang]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>`-elementet har ett `[lang]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Om du anger ett giltigt [språk enligt BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) kan texten uttalas korrekt av skärmläsare. [Läs mer](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>`-elementets `[lang]`-attribut har inte ett giltigt värde."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>`-elementets `[lang]`-attribut har ett giltigt värde"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Element med informativ funktion bör ha en kort, beskrivande alternativtext. Element som bara har estetisk funktion kan ignoreras genom att alt-attributet lämnas tomt. [Läs mer](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Alla bildelement har inte `[alt]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Alla bildelement har `[alt]`-attribut"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Om du anger en alternativ text när en bild används som `<input>`-knapp blir det lättare för användare med skärmläsare att förstå hur knappen används. [Läs mer](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Vissa `<input type=\"image\">`-element saknar `[alt]`-text"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Alla `<input type=\"image\">`-element har `[alt]`-text"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etiketterna gör att de olika delarna av ett formulär kan presenteras korrekt för användare med skärmläsare eller andra hjälpmedel. [Läs mer](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Vissa formulärelement har inte etiketter"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Alla formulärelement har etiketter"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "I en tabell som används i layoutsyfte ska det inte finnas dataelement som th eller caption eller attributet summary, eftersom det kan bli missvisande för den som använder skärmläsare. [Läs mer](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Det finns `<table>`-element som används i layoutsyfte men som ändå har `<th>`- eller `<caption>`-element eller `[summary]`-attribut, vilket bör undvikas."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Inga `<th>`- eller `<caption>`-element eller `[summary]`-attribut förekommer i `<table>`-element som används i layoutsyfte."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Det blir enklare att navigera för den som använder en skärmläsare om alla länktexter (och alternativtexter för alla bilder som används som länkar) är igenkännliga, unika och möjliga att flytta fokus till. [Läs mer](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Vissa länkar har inte ett igenkännligt namn"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Alla länkar har igenkännliga namn"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Listor presenteras på ett särskilt sätt av skärmläsare. Med rätt liststruktur kan skärmläsarna ge rätt information. [Läs mer](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listor innehåller inte enbart `<li>`-element och stödelement för skript (`<script>` och `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Alla listor innehåller enbart `<li>`-element eller stödelement för skript (`<script>` och `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Alla listposter (`<li>`) måste ha ett överordnat `<ul>`- eller `<ol>`-element för att kunna presenteras korrekt av skärmläsare. [Läs mer](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Vissa listposter (`<li>`) saknar ett överordnat `<ul>`- eller `<ol>`-element."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Alla listposter (`<li>`) har ett överordnat `<ul>`- eller `<ol>`-element"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Användarna förväntar sig inte att en sida ska uppdateras automatiskt, och när det händer flyttas fokus tillbaka till sidans början. Det kan vara både frustrerande och förvirrande. [Läs mer](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "`<meta http-equiv=\"refresh\">` används i dokumentet"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "`<meta http-equiv=\"refresh\">` används inte i dokumentet"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Att inaktivera förstoring leder till problem för användare med nedsatt syn, som behöver skärmförstoring för att kunna se webbsidan ordentligt. [Läs mer](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` används i elementet `<meta name=\"viewport\">`, eller också är värdet på attributet `[maximum-scale]` mindre än 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` används inte i elementet `<meta name=\"viewport\">` och attributet `[maximum-scale]` är inte mindre än 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "En skärmläsare kan inte tolka innehåll som inte är text. Om du lägger till alt-text i `<object>`-elementen kan skärmläsarna förmedla ett meningsfullt innehåll till användaren. [Läs mer](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Vissa `<object>`-element saknar `[alt]`-text"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Alla `<object>`-element har `[alt]`-text"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Med värden större än noll anges en explicit ordningsföljd för navigeringen. Även om detta inte är fel rent tekniskt leder det ofta till en frustrerande upplevelse för den som är beroende av tekniska hjälpmedel. [Läs mer](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Det finns element med ett `[tabindex]`-värde som är större än 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Det finns inga element med ett `[tabindex]`-värde som är större än 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Skärmläsare har funktioner som gör det enklare att navigera i tabeller. Sidan fungerar bättre för den som använder skärmläsare om attributet `[headers]` i `<td>`-celler bara refererar till andra celler i samma tabell. [Läs mer](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Det finns celler i ett `<table>`-element där attributet `[headers]` hänvisar till ett `id`-element som inte finns i samma tabell."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Det finns celler i ett `<table>`-element där attributet `[headers]` hänvisar till celler i samma tabell."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Skärmläsare har funktioner som gör det enklare att navigera i tabeller. Det fungerar bättre för den som använder skärmläsare om det inte finns några tabellrubriker som hänger i luften utan att referera till några dataceller. [Läs mer](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Vissa `<th>`-element och element med `[role=\"columnheader\"/\"rowheader\"]` står inte som rubrik för några dataceller."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Alla `<th>`-element och element med `[role=\"columnheader\"/\"rowheader\"]` står som rubriker för andra dataceller."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Om du anger ett giltigt [språk enligt BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) för elementen uttalas texten korrekt av en skärmläsare. [Läs mer](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Vissa `[lang]`-attribut har inte ett giltigt värde"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Alla `[lang]`-attribut har ett giltigt värde"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Det blir lättare för döva och hörselskadade att ta del av en video som är textad. [Läs mer](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Alla `<video>`-element har inte ett underordnat `<track>`-element med `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Alla `<video>`-element innehåller ett `<track>`-element med `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Upplästa beskrivningar ger viktig information om videon som inte framgår av dialogen, t.ex. ansiktsuttryck och naturvyer. [Läs mer](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Alla `<video>`-element har inte ett underordnat `<track>`-element med `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Alla `<video>`-element innehåller ett `<track>`-element med `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Definiera en `apple-touch-icon` för att få bästa möjliga utseende i iOS när användare lägger till en progressiv webbapp på startskärmen. Den måste peka på en icke-transparent, kvadratisk PNG med sidan 192 pixlar (eller 180 pixlar). [Läs mer](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Anger inte ett giltigt `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Attributet `apple-touch-icon-precomposed` är inaktuellt. `apple-touch-icon` är att föredra."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Anger en giltig `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Inläsningen av den här sidan påverkas negativt av tillägg i Chrome. Testa att granska sidan i inkognitoläge eller med en Chrome-profil utan tillägg."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Utvärdering av skript"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Skriptanalys"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Processortid totalt"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Minska tiden det tar att tolka, kompilera och köra JS-kod. Det brukar hjälpa att minska storleken på JS-resurserna som skickas. [Läs mer](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Minska körningstiden för JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Körningstid för JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Stora GIF-filer är inte ett effektivt sätt att visa animerat innehåll. I stället för GIF kan du använda videor i MPEG4-/WebM-format för animationer och PNG-/WebP-format för statiska bilder. Då minskar antalet byte som skickas via nätverket. [Läs mer](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Använd videoformat för animationer"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Låt bilder utanför skärmen och dolda bilder läsas in med lat inläsning efter att alla viktiga resurser är inlästa så att tiden till interaktivt tillstånd minskar. [Läs mer](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Skjut upp inläsningen av bilder som inte visas på skärmen"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Resurser blockerar sidans första rendering. Infoga nödvändig JS-/CSS-kod direkt på sidan och skjut upp inläsningen av JS-kod/formatmallar som är mindre viktiga. [Läs mer](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Ta bort resurser som blockerar renderingen"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Hög nätverksbelastning kostar användarna pengar och har ett starkt samband med lång inläsningstid. [Läs mer](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Storleken totalt var {totalBytes, number, bytes} kB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Undvik enorm nätverksbelastning"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Undviker enorm nätverksbelastning"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Att minifiera CSS-filer kan minska nätverksbelastningen. [Läs mer](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Minifiera CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Att minifiera JavaScript-filer kan minska nätverksbelastningen och tiden det tar att tolka skript. [Läs mer](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Minifiera JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Ta bort regler som inte används från formatmallar och skjut upp inläsning av CSS som inte används för innehåll ovanför mitten för att minska onödig nätverksaktivitet. [Läs mer](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Ta bort oanvänd CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Ta bort JavaScript som inte används så att färre byte skickas via nätverket."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Ta bort JavaScript som inte används"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Om filerna cachelagras under längre tid kan upprepade besök på sidan gå snabbare. [Läs mer](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 resurs hittades}other{# resurser hittades}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Skicka statiska tillgångar med en effektiv cachelagringspolicy"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Använder en effektiv cachelagringspolicy för statiska tillgångar"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimerade bilder läses in snabbare och förbrukar mindre mobildata. [Läs mer](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Koda bilder effektivt"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Minska mobildataförbrukningen och förbättra inläsningstiden genom att skicka bilder i rätt storlek. [Läs mer](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Använd bilder med rätt storlek"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Textresurser bör skickas komprimerade (gzip, deflate eller brotli) så att färre byte skickas via nätverket. [Läs mer](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Aktivera textkomprimering"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Bildformat som JPEG 2000, JPEG XR och WebP ger ofta bättre komprimering än PNG eller JPEG. Det gör att nedladdningen går snabbare och ger minskad dataförbrukning. [Läs mer](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Skicka bilder i modernare bildformat"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Om bredden på appens innehåll inte stämmer överens med bredden på visningsområdet kanske inte appen är optimerad för mobilskärmar. [Läs mer](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Visningsområdets storlek på {innerWidth} pixlar stämmer inte överens med fönsterstorleken på {outerWidth} pixlar."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Innehållet har inte rätt storlek för visningsområdet"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Innehållet har rätt storlek för visningsområdet"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Orderkedjorna nedan visar vilka resurser som läses in med hög prioritet. Se om du kan förbättra sidinläsningstiden genom att göra kedjorna kortare, minska storleken på resurser som laddas ned eller skjuta upp nedladdningen av onödiga resurser. [Läs mer](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kedja hittades}other{# kedjor hittades}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Minska antalet steg i viktiga orderkedjor"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Utfasning/varning"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Rad"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Utfasade API:er tas bort från webbläsaren efter hand. [Läs mer](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 varning hittades}other{# varningar hittades}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Utfasade API:er används"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Utfasade API:er undviks"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Programmets cacheminne är utfasat. [Läs mer](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "{AppCacheManifest} hittades"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Använder programmets cacheminne"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Undviker programcache"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "En doctype förhindrar att webbläsaren byter till quirks-läge. [Läs mer](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Doctype-namnet måste vara strängen `html` i gemener"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Dokument måste innehålla en doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId förväntades vara en tom sträng"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId förväntades vara en tom sträng"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Sidan har inte HTML som doctype, vilket aktiverar quirks-läge"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Sidan har HTML som doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Värde"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Antal"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Webbutvecklare rekommenderar att sidor innehåller mindre än 1500 DOM-element. Det bästa är ett träddjup med mindre än 32 element och högst 60 underordnade/överordnade element. En stor DOM kan öka minnesförbrukningen, förlänga [formatberäkningarna](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) och producera kostsamma [flödesuppdateringar för layouten](https://developers.google.com/speed/articles/reflow). [Läs mer](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 element}other{# element}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Undvik ett onödigt stort DOM-träd"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Största DOM-djup"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Totalt antal DOM-element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Högsta antal underordnade element"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Undviker ett onödigt stort DOM-träd"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Mål"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Lägg till `rel=\"noopener\"` eller `rel=\"noreferrer\"` i alla externa länkar för att förbättra prestanda och säkerhet. [Läs mer](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Länkar till mål med korsursprung är osäkra"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Länkar till mål med korsursprung är säkra"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Det går inte att fastställa målet för ankaret ({anchorHTML}). Det kan vara bra att ta bort target=_blank om det inte används som hyperlänk."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Användare blir misstänksamma eller förvirrade av webbplatser som ber om åtkomst till deras plats utan sammanhang. Det kan vara bättre att koppla förfrågan till något användaren gör. [Läs mer](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Begär åtkomst till geografisk plats vid sidinläsning"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Undviker att begära åtkomst till geografisk plats vid sidinläsning"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Version"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Alla JavaScript-bibliotek på klientsidan har identifierats på den här sidan. [Läs mer](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript-bibliotek har identifierats"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "För användare med långsam anslutning kan externa skript som infogas dynamiskt via `document.write()` fördröja sidinläsningen med tiotals sekunder. [Läs mer](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()` används"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()` undviks"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Högsta allvarlighetsgrad"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Biblioteksversion"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Antal säkerhetsbrister"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Vissa skript från tredje part kan innehålla kända säkerhetsproblem som är lätta att identifiera och utnyttja för angripare. [Läs mer](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 säkerhetsbrist har identifierats}other{# säkerhetsbrister har identifierats}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Innehåller JavaScript-bibliotek på klientsidan med kända säkerhetsbrister"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Hög"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Låg"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Medelstor"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Undviker JavaScript-bibliotek med kända säkerhetsproblem på klientsidan"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Användare blir misstänksamma eller förvirrade av webbplatser som ber om åtkomst att skicka aviseringar utan sammanhang. Det kan vara bättre att koppla förfrågan till rörelser. [Läs mer](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Begär aviseringsbehörighet vid sidinläsning"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Undviker att begära aviseringsbehörighet vid sidinläsning"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Element med fel"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Att förhindra att lösenord klistras in underminerar en bra säkerhetspolicy. [Läs mer](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Användarna tillåts inte att klistra in i lösenordsfält"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Användarna tillåts klistra in i lösenordsfält"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokoll"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ger många fördelar jämfört med HTTP/1.1, inklusive binära rubriker, multiplexning och server push. [Läs mer](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 begäran visades inte via HTTP/2}other{# begäranden visades inte via HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Använder inte HTTP/2 för alla resurser"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Använder HTTP/2 för egna resurser"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Det kan vara bra att märka dina händelselyssnare för tryck och hjul som `passive` för att förbättra sidans rullningsfunktion. [Läs mer](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Passiva lyssnare används inte för att förbättra rullningsprestanda"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Passiva lyssnare används för att förbättra rullningsprestanda"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Beskrivning"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Fel som loggats i konsolen indikerar olösta problem. De kan bero på fel i nätverksförfrågningar och andra webbläsarproblem. [Läs mer](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Webbläsarfel loggades i konsolen"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Inga webbläsarfel loggades i konsolen"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Använd funktionen font-display i CSS så att texten är synlig för användaren medan webbteckensnitten läses in. [Läs mer](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Se till att all text förblir synlig medan webbteckensnitten läses in"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "All text förblir synlig medan webbteckensnitten läses in"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse kunde inte kontrollera värdet för teckensnittsvisning automatiskt för följande webbadress: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Bildproportioner (faktiska)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Bildproportioner (visade)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Bildens visningsformat ska matcha de naturliga proportionerna. [Läs mer](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Visar bilder med felaktiga bildproportioner"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Bilder visas med korrekta bildproportioner"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Ogiltig information om bildstorlek {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Webbläsare kan i förväg uppmana användare att lägga till appen på startskärmen, vilket leder till att de använder den mer. [Läs mer](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Webbappens manifest uppfyller inte kraven för installation"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Webbappens manifest uppfyller kraven för installation"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Osäker webbadress"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Alla webbplatser ska skyddas med HTTPS, även de som inte hanterar känslig data. HTTPS förhindrar att inkräktare påverkar eller passivt avlyssnar kommunikationen mellan din app och dina användare, och är ett krav för HTTP/2 och många nya API:er för webbplattformar. [Läs mer](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 osäker begäran hittades}other{# osäkra begäranden hittades}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Använder inte HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Använder HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Snabb sidinläsning i mobila nätverk ger en bra upplevelse för mobila användare. [Läs mer](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Interaktiv vid {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Interaktiv i simulerade mobilnätverk på {timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Sidan läses in för långsamt och är inte interaktiv inom tio sekunder. Ta en titt på möjligheter och diagnostik i avsnittet Prestanda för att se hur du kan förbättra sidan."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Sidor läses inte in tillräckligt snabbt i mobila nätverk"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Sidan läses in tillräckligt snabbt i mobila nätverk"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategori"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Minska tiden det tar att tolka, kompilera och köra JS-kod. Det brukar hjälpa att minska storleken på JS-resurserna som skickas. [Läs mer](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Minska arbetsbelastningen på modertråden"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Minskar arbetsbelastningen på modertråden"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Webbplatser ska fungera i alla stora webbläsare för att nå så många användare som möjligt. [Läs mer](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Webbläsaren fungerar i olika webbläsare"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Kontrollera att enskilda sidor går att djuplänka via en webbadress och att webbadresserna är unika för syftet att dela sidorna på sociala medier. [Läs mer](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Varje sida har en webbadress"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Övergångar ska gå snabbt när du trycker i appen, även på långsamma nätverk. Det är avgörande för vad användarna uppfattar som prestanda. [Läs mer](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Det ska inte kännas som om övergångar mellan sidor blockeras på nätverket"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Uppskattad inmatningslatens är en uppskattning av hur lång tid (i millisekunder) det tar innan appen svarar på användarens inmatning under den mest aktiva femsekundersperioden av sidinläsningen. Om latensen är högre än 50 ms kan användarna uppfatta appen som seg. [Läs mer](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Beräknad inmatningslatens"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Första innehållsrenderingen anger när den första texten eller bilden ritades upp. [Läs mer](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Första uppritningen av innehåll"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Första CPU-avbrottet anger när sidans modertråd först blev inaktiv nog att hantera indata. [Läs mer](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Första CPU-inaktivitet"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Första användbara renderingen anger när sidans primära innehåll blev synligt. [Läs mer](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Första meningsfulla skärmuppritningen"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Tiden till interaktivitet är den tid det tar innan sidan är fullständigt interaktiv. [Läs mer](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Tid till interaktivt tillstånd"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Den högsta potentiella fördröjningen vid första indata som användarna kan få är längden på den längsta uppgiften i millisekunder. [Läs mer](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Högsta potentiella fördröjning till första inmatningen"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Hastighetsindexet visar hur snabbt en sida fylls med synligt innehåll. [Läs mer](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Hastighetsindex"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Summan av alla tidsperioder mellan FCP och Tid till interaktivt tillstånd när uppgiftstiden överskred 50 ms, uttryckt i millisekunder."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Total blockeringstid"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Nätverkets RTT-tider (Round Trip Times) har stor inverkan på prestanda. Om RTT-tiden till ett ursprung är för hög tyder det på att servrar närmare användaren skulle kunna förbättra prestanda. [Läs mer](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Nätverkets RTT-tider"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Serverlatens kan påverka webbprestanda. Om serverlatensen är hög för ett ursprung tyder det på att servern är överbelastad eller har dålig kapacitet. [Läs mer](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Serverlatens"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Med en tjänstefunktion kan appen användas under oförutsägbara nätverksförhållanden. [Läs mer](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "HTTP-statuskoden 200 visas inte när `start_url` är offline"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "HTTP-statuskoden 200 visas när `start_url` är offline."
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse kunde inte läsa `start_url` i manifestet. Därför antogs det att `start_url` var dokumentets webbadress. Felmeddelande: {manifestWarning}."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Över budget"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Håll antal och storlek för nätverksbegäranden under de mål som anges i den angivna prestandabudgeten. [Läs mer](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 begäran}other{# begäranden}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Prestandabudget"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Om du redan har konfigurerat HTTPS ska du omdirigera all HTTP-trafik till HTTPS för att se till att webbfunktionerna är säkra för alla användare. [Läs mer](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Omdirigerar inte HTTP-trafik till HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Omdirigerar HTTP-trafik till HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Omdirigeringar medför en ytterligare fördröjning innan sidan kan läsas in. [Läs mer](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Undvik upprepade omdirigeringar"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Lägg till en budget.json-fil för att ange budget för kvantitet och storlek på sidresurser. [Läs mer](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 begäran • {byteCount, number, bytes} kB}other{# förfrågningar • {byteCount, number, bytes} kB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Begränsa antalet begäranden och storleken på överföringar"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Kanoniska länkar föreslår vilka webbadresser som ska visas i sökresultat. [Läs mer](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Flera webbadresser som står i konflikt ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Pekar på en annan domän ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Ogiltig webbadress ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Pekar på en annan `hreflang`-plats ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Relativ webbadress ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Pekar på domänens rotadress (startsidan) i stället för motsvarande sida med innehåll"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Dokumentet har ingen giltig länk med `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Dokumentet har ett giltigt `rel=canonical`-värde"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Teckenstorlekar under 12 pixlar är för små för att kunna läsas och kräver att mobila användare zoomar genom att nypa för att kunna läsa. Försök ha minst 60 % av texten i 12 pixlar eller mer. [Läs mer](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} läslig text"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Text är oläslig eftersom det inte finns någon metatagg för visningsområde som är optimerad för mobila skärmar."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} av texten är för liten (baserat på ett urval av {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokumentet har inga läsliga teckenstorlekar"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokumentet har läsliga teckenstorlekar"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang-länkar informerar sökmotorer om vilken version av en sida de ska visa i sökresultatet för ett visst språk eller område. [Läs mer](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Dokumentet har inte ett giltigt `hreflang`-värde"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Dokumentet har ett giltigt `hreflang`-värde"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Sidor med HTTP-statuskoder som indikerar att begäran misslyckades kanske inte indexeras korrekt. [Läs mer](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Sidan har en HTTP-statuskod som visar att begäran inte lyckades"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Sidan har en giltig HTTP-statuskod"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Sökmotorer kan inte inkludera dina sidor i sökresultat om de inte har behörighet att genomsöka dem. [Läs mer](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Sidan är blockerad för indexering"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Sidan är inte blockerad från indexering"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Beskrivande länktext hjälper sökmotorer att förstå innehållet. [Läs mer](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 länk hittades}other{# länkar hittades}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Länkar har inte beskrivande text"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Länkar har beskrivande text"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Kör [testverktyget för strukturerad data](https://search.google.com/structured-data/testing-tool/) och [Structured Data Linter](http://linter.structured-data.org/) för att validera strukturerad data. [Läs mer](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Strukturerad data är giltig"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Metabeskrivningar kan inkluderas i sökresultat för att sammanfatta sidinnehållet. [Läs mer](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Beskrivningstexten är tom."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Dokumentet har ingen metabeskrivning"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Dokumentet har en metabeskrivning"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Sökmotorer kan inte indexera plugin-innehåll och många enheter begränsar plugin-program eller stöder dem inte. [Läs mer](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Dokumentet använder plugin-program"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Dokumentet undviker plugin-program"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Om robots.txt-filen har felaktigt format kan sökrobotarna inte förstå hur du vill att din webbplats ska genomsökas eller indexeras. [Läs mer](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Begäran om robots.txt returnerade HTTP-status: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Ett fel hittades}other{# fel hittades}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse kunde inte ladda ned en robots.txt-fil"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt är inte giltig"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt är giltig"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Interaktiva element som knappar och länkar ska vara tillräckligt stora (48 × 48 pixlar) och ha tillräckligt mycket utrymme runt omkring för att vara lätta att trycka på utan att överlappa andra element. [Läs mer](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} av tryckmålen har lämplig storlek"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Tryckmålen är för små eftersom det inte finns någon metatagg för visningsområde som är optimerad för mobilskärmar"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Tryckmålen har inte lämplig storlek"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Överlappande tryckmål"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Tryckmål"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Tryckmål har lämplig storlek"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Tjänstefunktioner är en teknik som gör det möjligt att använda flera funktioner för progressiva webbappar i appen, till exempel offlineanvändning, pushmeddelanden och att lägga till den på startskärmen. [Läs mer](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Sidan styrs av en tjänstefunktion, men `start_url` hittades inte eftersom det inte gick att analysera manifestet som giltigt JSON-format."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Den här sidan styrs av en tjänstefunktion, men `start_url` ({startUrl}) är inte inom tjänstefunktionens omfattning ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Sidan styrs av en tjänstefunktion, men `start_url` hittades inte eftersom inget manifest hämtades."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Ursprunget har en eller flera tjänstefunktioner, men sidan ({pageUrl}) är inte inom omfattningen."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Registrerar inte en tjänstefunktion som styr sidan och `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Registrerar en tjänstefunktion som styr sidan och `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Med hjälp av en välkomstskärm med ett tema som visas när användarna startar appen på startskärmen kan du se till att de får en bra upplevelse. [Läs mer](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Har inte konfigurerats för en anpassad välkomstskärm"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Konfigurerad för en anpassad välkomstskärm"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Det går att ändra temat för webbläsarens adressfält så att det matchar din webbplats. [Läs mer](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Anger inte ett färgtema för adressfältet."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Anger ett färgtema för adressfältet."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Tidsåtgång för blockering av huvudtråd"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Tredje part"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Kod från tredje part kan påverka inläsningsprestandan betydligt. Begränsa antalet överflödiga tredjepartsleverantörer och testa att låta tredjepartskod läsas in efter att sidans huvudinnehåll har lästs in helt. [Läs mer](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Tredjepartskod blockerade huvudtråden i {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Minska påverkan från tredjepartskod"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Tredjepartsanvändning"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Mätvärdet Tid till första byte anger när servern svarade. [Läs mer](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Rotdokumentet tog {timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Minska svarstiderna från servern (tid till första byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Servern svarar snabbt (tid till första byte)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Varaktighet"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Starttid"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Typ"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Om du bygger in User Timing API i appen kan du mäta appens prestanda i realtid i samband med viktiga användarupplevelser. [Läs mer](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 användartimer}other{# användartimer}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing API – tidsstämplar och mått"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Ett <link>-element för föranslutning till {securityOrigin} hittades men ignorerades av webbläsaren. Kontrollera att attributet `crossorigin` används korrekt."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Lägg till signaler för `preconnect` eller `dns-prefetch` så att viktiga anslutningar till tredje part upprättas tidigt. [Läs mer](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Föranslut till obligatoriska källor"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "En <link> för förinläsning hittades för {preloadURL} men den användes inte av webbläsaren. Kontrollera att attributet `crossorigin` används korrekt."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Det kan vara bra att använda `<link rel=preload>` för att prioritera hämtning av resurser som kommer att begäras senare i sidinläsningen. [Läs mer](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Läs in viktiga resurser i förväg"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Lägg till en `<meta name=\"viewport\">`-tagg för att optimera appen för mobilskärmar. [Läs mer](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Ingen `<meta name=\"viewport\">`-tagg hittades"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Har inte en `<meta name=\"viewport\">`-tagg med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Har en `<meta name=\"viewport\">`-tagg med `width` eller `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Appen ska visa innehåll när JavaScript är inaktiverat, även om det bara är en varning till användaren om att JavaScript krävs för att använda appen. [Läs mer](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Någon form av innehåll ska renderas för sidans brödtext om dess skript inte är tillgängliga."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Visar inte reservinnehåll när JavaScript inte är tillgängligt"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Visar innehåll när JavaScript inte är tillgängligt"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Om du skapar en progressiv webbapp rekommenderar vi att du använder en tjänstefunktion så att appen kan användas offline. [Läs mer](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "HTTP-statuskoden 200 visas inte för den aktuella sidan när den är offline"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "HTTP-statuskoden 200 visas för den aktuella sidan när den är offline"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Sidan kanske inte läses in offline eftersom testwebbadressen ({requested}) omdirigerades till {final}. Testa den andra webbadressen direkt i stället."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Det här är förslag på hur ARIA kan förbättras i appen så att den fungerar bättre för den som använder skärmläsare eller andra hjälpmedel."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Det här är möjligheter att tillhandahålla alternativt innehåll för ljud och video. Detta kan förbättra upplevelsen för användare med nedsatt syn eller hörsel."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Ljud och bild"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Dessa punkter visar bra metoder för vanliga hjälpmedel."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Bästa metoder"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Dessa kontroller visar möjligheter att [förbättra tillgängligheten för din webbapp](https://developers.google.com/web/fundamentals/accessibility). Alla tillgänglighetsproblem kan inte identifieras automatiskt. Du bör därför även testa manuellt."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Dessa punkter beskriver områden som inte kan testas automatiskt. Läs mer i vår guide om att [granska tillgängligheten](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Tillgänglighet"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Det här är förslag på hur du kan göra innehållet lättare att läsa."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Det här är förslag på hur du kan göra det lättare för användare med olika språkinställningar att tolka innehållet."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Internationalisering och lokalisering"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Det här är förslag på hur du kan göra det tydligare vad olika objekt i appens gränssnitt är. Det kan förenkla för den som använder skärmläsare eller andra hjälpmedel."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Namn och etiketter"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Det här är möjligheter att förbättra tangentbordsnavigeringen i appen."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Navigering"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Det här är möjligheter att förbättra upplevelsen av att läsa tabeller eller listor med skärmläsare eller andra hjälpmedel."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tabeller och listor"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Bästa metoder"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Prestandabudget anger standard för webbplatsens prestanda."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Budgetar"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Mer information om appens prestanda. Värdena påverkar inte prestandapoängen [direkt](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Diagnostik"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Den viktigaste delen av sidans prestanda är hur snabbt pixlarna renderas på skärmen. Viktiga mätvärden: Första uppritningen av innehåll, Första meningsfulla skärmuppritningen"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Förbättringar av första skärmuppritningen"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Dessa förslag kan hjälpa sidan att läsas in snabbare. De påverkar inte prestandavärdet [direkt](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Möjligheter"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Mätvärden"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Förbättra inläsningstiden överlag så att sidan upplevs som responsiv och blir klar att använda så snabbt som möjligt. Viktiga mätvärden: Tid till interaktivt tillstånd, Hastighetsindex"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Övergripande förbättringar"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Prestanda"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Med dessa kontroller verifieras att webbplatsen är en progressiv webbapp. [Läs mer](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Dessa kontroller krävs enligt [checklistan för progressiva webbappar](https://developers.google.com/web/progressive-web-apps/checklist) som används som baslinje, men de kontrolleras inte automatiskt av Lighthouse. De påverkar inte resultatet, men det är viktigt att du verifierar dem manuellt."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressiv webbapp"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Snabb och pålitlig"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Kan installeras"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimerad för progressiv webbapp"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Dessa kontroller ser till att din sida är optimerad för rankning i sökmotorresultat. Det finns fler faktorer som Lighthouse inte kontrollerar som kan påverka rankningen i sökresultat. [Läs mer](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Kontrollera att fler av de bästa metoderna för sökmotoroptimering följs på din webbplats genom att köra dessa extra valideringar."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Formatera HTML-koden på ett sätt som gör det enklare för sökrobotar att tolka appens innehåll."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Bästa metoder för innehåll"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Du måste ge sökrobotar tillgång till appen om den ska kunna visas i sökresultaten."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Genomsökning och indexering"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Gör sidorna mobilanpassade så att användarna kan läsa dem utan att behöva nypa eller zooma in. [Läs mer](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobilanpassad"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Lagringstid i cacheminnet"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Plats"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Namn"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Begäranden"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Resurstyp"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Storlek"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Tid som använts"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Överföringsstorlek"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "Webbadress"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Möjlig besparing"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Möjlig besparing"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Möjlig databesparing: {wastedBytes, number, bytes} kB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Möjlig tidsbesparing: {wastedMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Dokument"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Teckensnitt"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Bild"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Media"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Annat"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Skript"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} s"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Formatmall"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Tredje part"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Totalt"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Ett fel uppstod när spårningen skulle registreras för sidinläsningen. Kör Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Tidsgränsen överskreds under väntan på den första anslutningen till felsökningsprotokollet."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Inga skärmdumpar togs i Chrome medan sidan lästes in. Kontrollera att det finns synligt innehåll på sidan och kör Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Uppslagningen av den angivna domänen misslyckades på DNS-servern."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "En obligatorisk {artifactName}-insamlare påträffade ett fel: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Ett internt fel har uppstått i Chrome. Starta om Chrome och testa att köra Lighthouse igen."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "En {artifactName}-samlare som krävs kördes inte."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Det gick inte att läsa in den begärda sidan i Lighthouse. Kontrollera att du testar rätt webbadress och att servern svarar korrekt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Det gick inte att läsa in den begärda webbadressen med Lighthouse eftersom sidan slutade svara."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Den webbadress du angav har inget giltigt säkerhetscertifikat. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome förhindrade sidhämtning med en mellansidesannons. Kontrollera att du testar rätt webbadress och att servern svarar korrekt."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Det gick inte att läsa in den begärda sidan i Lighthouse. Kontrollera att du testar rätt webbadress och att servern svarar korrekt. (Mer information: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Det gick inte att läsa in den begärda sidan i Lighthouse. Kontrollera att du testar rätt webbadress och att servern svarar korrekt. (Statuskod: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Det tog för lång tid att läsa in sidan. Minska sidans inläsningstid genom att följa förslagen i rapporten och kör sedan Lighthouse igen. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Den angivna väntetiden för svar med DevTools-protokollet har överskridits. (Metod: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Den angivna tiden för att hämta resurser har överskridits"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Den angivna webbadressen verkar vara ogiltig."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Visa granskningar"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Första navigering"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Högsta latens för kritisk kedja:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Fel."
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Rapportfel: ingen granskningsinformation"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Labbdata"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Analys med [Lighthouse](https://developers.google.com/web/tools/lighthouse/) av den aktuella sidan i ett emulerat mobilnätverk. Värdena är uppskattningar och kan variera."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Fler saker att kolla manuellt"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Ej tillämpligt"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Möjlighet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Uppskattad tidsbesparing"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Godkända granskningar"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Komprimera utdrag"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Utöka utdrag"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Visa resurser från tredje part"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Problem uppstod med den här körningen av Lighthouse."
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Värdena är uppskattningar och kan variera. Prestandapoängen [baseras enbart på dessa mätvärden](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Godkänd i granskningarna men med varningar"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Varningar: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Ladda upp GIF-filen till en tjänst som kan göra den tillgänglig för inbäddning som HTML5-video."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Installera en [WordPress-plugin för lat inläsning](https://wordpress.org/plugins/search/lazy+load/) som ger möjlighet att skjuta upp inläsningen av bilder som inte visas på skärmen, eller byt till ett tema som har den funktionen. Du kan även använda [AMP-pluginmodulen](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Det finns ett antal pluginmoduler för WordPress som kan hjälpa dig att [lägga till kritiska tillgångar direkt på sidan](https://wordpress.org/plugins/search/critical+css/) eller [skjuta upp inläsningen av mindre viktiga resurser](https://wordpress.org/plugins/search/defer+css+javascript/). Tänk på att optimeringarna som dessa pluginmoduler gör kan leda till att funktioner i teman eller andra pluginmoduler slutar fungera, så du kan behöva ändra i koden."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Serverns svarstider påverkas av teman, pluginmoduler och serverns prestanda. Du kan använda ett mer optimerat tema, välja en optimeringsplugin och/eller uppgradera servern."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Du kan visa utdrag i inläggslistan (t.ex. via en more-tagg), minska antalet inlägg på sidan, dela upp långa inlägg på flera sidor eller använda en plugin som läser in kommentarer med lat inläsning."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Det finns ett antal [pluginmoduler för WordPress](https://wordpress.org/plugins/search/minify+css/) som kan göra webbplatsen snabbare genom att sammanfoga, minifiera och komprimera skript. Du kan också göra minifieringen direkt i konstruktionsfasen om möjligt."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Ett antal [pluginmoduler för WordPress](https://wordpress.org/plugins/search/minify+javascript/) kan göra webbplatsen snabbare genom att sammanfoga, minifiera och komprimera skript. Du kan också göra minifieringen direkt i konstruktionsfasen om möjligt."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Du kan minska antalet [WordPress-pluginmoduler](https://wordpress.org/plugins/) som läser in CSS som inte används på sidan, eller byta ut dem. Testa fliken för [kodtäckning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chromes utvecklarverktyg om du vill se vilka pluginmoduler som lägger till överflödig CSS. Du ser på CSS-formatmallens webbadress vilket tema eller vilken plugin som koden kommer från. Titta efter pluginmoduler med många CSS-formatmallar på listan där en stor del av stapeln är röd. En plugin ska bara ställa en formatmall i kö för inläsning om den faktiskt används på sidan."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Du kan minska antalet [WordPress-pluginmoduler](https://wordpress.org/plugins/) som läser in JavaScript som inte används på sidan, eller byta ut dem. Testa fliken för [kodtäckning](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) i Chromes utvecklarverktyg om du vill se vilka pluginmoduler som lägger till överflödig JS. Du ser på skriptets webbadress vilket tema eller vilken plugin som koden kommer från. Titta efter pluginmoduler med många skript på listan där en stor del av stapeln är röd. En plugin ska bara ställa ett skript i kö för inläsning om det faktiskt används på sidan."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Läs mer om [cachelagring i webbläsaren och WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Du kan använda en [WordPress-plugin för bildoptimering](https://wordpress.org/plugins/search/optimize+images/) som komprimerar dina bilder utan att göra avkall på kvaliteten."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Säkerställ att de bildstorlekar som krävs finns tillgängliga genom att ladda upp bilderna direkt via [mediebiblioteket](https://codex.wordpress.org/Media_Library_Screen) och infoga dem sedan från mediebiblioteket eller med bildwidgeten, så att de optimala bildstorlekarna används (även för brytpunkterna för responsiv design). Undvik att använda `Full Size`-bilder såvida de inte har mått som passar där bilderna ska användas. [Läs mer](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Du kan aktivera textkomprimering i webbserverns konfiguration."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Det kan vara bra att använda en [plugin](https://wordpress.org/plugins/search/convert+webp/) eller tjänst som automatiskt konverterar uppladdade bilder till optimalt format."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ta.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ta.json
new file mode 100644
index 00000000000..ba73afc2d5a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/ta.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "பக்கத்தின் ஏதேனும் ஒரு பகுதிக்கு விரைவாகச் செல்ல அணுகல் விசைகளைப் பயனர்கள் பயன்படுத்தலாம். சரியாகச் செல்வதற்கு, ஒவ்வொரு அணுகல் விசையும் தனித்துவமானதாக இருக்க வேண்டும். [மேலும் அறிக](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` மதிப்புகள் பிரத்தியேகமானவையாக இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` மதிப்புகள் தனித்துவமாக உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "ஒவ்வொரு ARIA `role` நியமனமும் `aria-*` பண்புக்கூறுகளின் குறிப்பிட்ட துணைத்தொகுப்பை ஆதரிக்கும். பொருந்தாதபட்சத்தில் `aria-*` பண்புக்கூறுகள் செல்லுபடியாகாதவையாகும். [மேலும் அறிக](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் அவற்றின் பங்களிப்புகளுடன் பொருந்தவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் அவற்றின் பங்களிப்புகளுடன் பொருந்துகின்றன"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "சில ARIA பங்களிப்புகளில் ஸ்க்ரீன் ரீடர்களுக்கு உறுப்பின் நிலையை விவரிக்கத் தேவையான பண்புக்கூறுகள் உள்ளன. [மேலும் அறிக](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]`கள் தேவையான அனைத்து `[aria-*]` பண்புக்கூறுகளையும் கொண்டிருக்கவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "தேவையான அனைத்து `[aria-*]` பண்புக்கூறுகளும் `[role]`களில் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "சில ARIA முதல்நிலைப் பங்களிப்புகள், அவற்றுக்கான அணுகல்தன்மை செயல்பாடுகளை செய்ய, குறிப்பிட்ட உபநிலைப் பங்களிப்புகளைக் கொண்டிருக்க வேண்டும். [மேலும் அறிக](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "குறிப்பிட்ட `[role]` ஐக் கொண்டிருப்பதற்கு உபநிலைகள் தேவைப்படுகின்ற ARIA `[role]` ஐ உடைய உறுப்புகளில் தேவையான சில உபநிலைகளோ அனைத்துமோ காணப்படவில்லை."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "குறிப்பிட்ட `[role]` ஐக் கொண்டிருப்பதற்கு உபநிலைகள் தேவைப்படுகின்ற ARIA `[role]` ஐ உடைய உறுப்புகளில் தேவையான உபநிலைகள் உள்ளன."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "சில ARIA உபநிலைப் பங்களிப்புகள் அவற்றுக்கான அணுகல்தன்மை செயல்பாடுகளை சரியாக செய்ய, குறிப்பிட்ட முதல்நிலைப் பங்களிப்புகளில் இருக்க வேண்டும். [மேலும் அறிக](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]`கள் அவற்றுக்குத் தேவையான முதல்நிலை உறுப்புக்குள் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]`கள் அவற்றுக்குத் தேவையான முதல்நிலை உறுப்புகளுக்குள் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA பங்களிப்புகள் தங்களுக்கான அணுகல்தன்மை செயல்பாடுகளை செய்ய அவற்றில் செல்லுபடியாகும் மதிப்புகள் இருக்க வேண்டும். [மேலும் அறிக](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` செல்லுபடியாகாத மதிப்புகளைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` செல்லுபடியாகும் மதிப்புகளைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "செல்லுபடியாகாத மதிப்புகள் உள்ள ARIA பண்புக்கூறுகளை ஸ்க்ரீன் ரீடர்கள் போன்ற உதவிகரமான தொழில்நுட்பங்களால் புரிந்துகொள்ள இயலாது. [மேலும் அறிக](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் செல்லுபடியாகும் மதிப்புகளைக் கொண்டிருக்கவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் செல்லுபடியாகும் மதிப்புகளைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "செல்லுபடியாகாத பெயர்கள் உள்ள ARIA பண்புக்கூறுகளை ஸ்க்ரீன் ரீடர்கள் போன்ற உதவிகரமான தொழில்நுட்பங்களால் புரிந்துகொள்ள இயலாது. [மேலும் அறிக](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் செல்லுபடியாகாத மதிப்புகளைக் கொண்டுள்ளன அல்லது தவறாக உள்ளிடப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` பண்புக்கூறுகள் செல்லுபடியாகும் மதிப்புகளைக் கொண்டுள்ளன, மேலும் அவை சரியாக உள்ளிடப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "காது கேளாதோர், செவித்திறன் குறைவானவர்கள் வசதிக்காக யார் என்ன பேசுகிறார்கள் என்பதையும் பேச்சல்லாத பிற தகவல்கள் போன்ற முக்கியமான தகவல்களையும் வழங்குவதன் மூலம் ஆடியோ உறுப்புகளைப் பயனுள்ளதாக்க தலைப்புகள் உதவுகின்றன. [மேலும் அறிக](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` உறுப்புகளில் `[kind=\"captions\"]` உடன் இருக்கும்`<track>` உறுப்பு ஒன்று விடுபட்டுள்ளது."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` உறுப்புகளில் `[kind=\"captions\"]`ஐக் கொண்டுள்ள`<track>` உறுப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "தோல்வியுற்ற உறுப்புகள்"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "ஒரு பட்டனுக்குத் தெளிவான பெயர் இல்லையெனில் ஸ்க்ரீன் ரீடர்கள் அதை \"பட்டன்\" என அறிவிக்கும், இது ஸ்க்ரீன் ரீடர்களைப் பயன்படுத்தும் பயனர்களுக்கு உதவியாக இருக்காது. [மேலும் அறிக](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "பட்டன்களுக்குத் தெளிவான பெயர் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "பட்டன்களுக்கு ஸ்க்ரீன் ரீடர்களால் படிக்கக்கூடிய பெயர்கள் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "திரும்பத்திரும்ப வரும் உள்ளடக்கத்தை மீறி செல்லும் வழிகளை சேர்த்தால், பக்கத்தைக் கீபோர்டுப் பயனர்கள் மேலும் திறனுள்ள வகையில் கையாள முடியும். [மேலும் அறிக](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "பக்கத்தில் தலைப்பு, தவிர்ப்பு இணைப்பு அல்லது இட அடையாள மண்டலம் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "பக்கத்தில் தலைப்பு, தவிர்ப்பு இணைப்பு அல்லது இட அடையாள மண்டலம் உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "பல பயனர்களால் குறைவான ஒளி மாறுபாடுள்ள உரையைப் படிக்க இயலாது அல்லது கடினமாக இருக்கும். [மேலும் அறிக](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "பின்னணி, முன்னணி நிறங்களுக்குப் போதுமான ஒளி மாறுபாடு விகிதம் இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "பின்னணி, முன்னணி நிறங்கள் போதுமான ஒளி மாறுபாட்டு விகிதத்தைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "வரையறைப் பட்டியல்கள் சரியாகக் குறிக்கப்படவில்லை எனில் ஸ்க்ரீன் ரீடர்கள் குழப்பமான அல்லது துல்லியமற்ற வெளியீட்டைத் தரக்கூடும். [மேலும் அறிக](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "சரியாக வரிசைப்படுத்தப்பட்ட `<dt>`, `<dd>` குழுக்கள், `<script>` அல்லது `<template>` உறுப்புகள் மட்டுமல்லாது வேறு வகைகளையும் `<dl>` கொண்டுள்ளது."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>`கள் முறையாக வரிசைப்படுத்தப்பட்ட `<dt>`, `<dd>` குழுக்களையும் `<script>` அல்லது `<template>` உறுப்புகளையும் மட்டுமே கொண்டிருக்கும்."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "விளக்கப்பட்டியலில் உள்ளவற்றை (`<dt>`,`<dd>`) ஸ்க்ரீன் ரீடர்கள் சரியாகப் படிக்க அவை ஒரு முதல்நிலை `<dl>` உறுப்பில் சேர்க்கப்பட்டிருக்க வேண்டும். [மேலும் அறிக](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "விளக்கப்பட்டியலில் உள்ளவை`<dl>` உறுப்புகளில் சேர்க்கப்படவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "விளக்கப் பட்டியலில் உள்ளவை`<dl>` உறுப்புகளில் சேர்க்கப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "தலைப்பானது அந்தப் பக்கத்தைப் பற்றிய மேலோட்ட விவரங்களை ஸ்க்ரீன் ரீடர் பயனர்களுக்கு வழங்குகிறது, தேடல் இன்ஜின் பயனர்கள் தங்களுடைய தேடலுடன் பக்கம் பொருந்துகின்றதா என்பதைத் தீர்மானிக்க அதைப் பெரிதும் நம்பியுள்ளனர். [மேலும் அறிக](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "ஆவணத்தில் `<title>` உறுப்பு இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "ஆவணத்தில் `<title>` உறுப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "உதவிகரமான தொழில்நுட்பங்களால் நேர்வுகள் புறக்கணிக்கப்படுவதைத் தடுக்க, ஐடி பண்புக்கூறின் மதிப்பு பிரத்தியேகமானவையாக இருக்க வேண்டும். [மேலும் அறிக](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "பக்கத்திலுள்ள `[id]` பண்புக்கூறுகள் பிரத்தியேகமானவையாக இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "பக்கத்தில் உள்ள `[id]` பண்புக்கூறுகள் பிரத்தியேகமானவை"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "ஃபிரேம்களில் உள்ளவற்றை விவரிக்க அவற்றின் தலைப்பை ஸ்க்ரீன் ரீடர் பயனர்கள் சார்ந்துள்ளனர். [மேலும் அறிக](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` அல்லது `<iframe>` உறுப்புகளுக்குத் தலைப்பு இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` அல்லது `<iframe>` உறுப்புகளுக்குத் தலைப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "ஒரு பக்கமானது மொழியின் பண்புக்கூறைக் குறிப்பிடவில்லை எனில் ஸ்க்ரீன் ரீடரை அமைக்கும்போது பயனர் தேர்வுசெய்த மொழியையே பக்கத்தின் இயல்பு மொழியாக ஸ்க்ரீன் ரீடர் கருதும். இயல்பு மொழியில் பக்கம் இல்லை எனில் பக்கத்தின் உரையை ஸ்க்ரீன் ரீடர் சரியாக வாசிக்க முடியாமல் போகக்கூடும். [மேலும் அறிக](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` உறுப்பில்`[lang]` பண்புக்கூறு இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` உறுப்பானது`[lang]` பண்புக்கூறைக் கொண்டுள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "செல்லுபடியாகும் [BCP 47 மொழியைக்](https://www.w3.org/International/questions/qa-choosing-language-tags#question) குறிப்பிட்டால், உரையை ஸ்க்ரீன் ரீடர்கள் சரியாகப் படிக்க அது உதவியாக இருக்கும். [மேலும் அறிக](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` உறுப்பில் அதன்`[lang]` பண்புக்கூறுக்கான செல்லுபடியாகும் மதிப்பு இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` உறுப்பில் அதன்`[lang]` பண்புக்கூறுக்கான செல்லுபடியாகும் மதிப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "தகவல் உறுப்புகள் சுருக்கமான, விளக்கமான மாற்று உரையைக் கொண்டிருக்க வேண்டும். அலங்கார உறுப்புகளில் காலியான மாற்றுப் பண்புக்கூறு இருக்கலாம். [மேலும் அறிக](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "பட உறுப்புகளில் `[alt]` பண்புக்கூறுகள் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "பட உறுப்புகள் `[alt]` பண்புக்கூறுகளைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "`<input>` பட்டனாக ஒரு படத்தைப் பயன்படுத்தும்போது அந்த பட்டனுக்கான மாற்று உரையை வழங்குவது அதன் செயல்பாட்டை ஸ்க்ரீன் ரீடர் பயனர்கள் புரிந்துகொள்ள உதவியாக இருக்கும். [மேலும் அறிக](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` உறுப்புகளில் `[alt]` உரை இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` உறுப்புகள் `[alt]` உரையைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "ஸ்க்ரீன் ரீடர்கள் போன்ற உதவிகரமான தொழில்நுட்பங்களால் சரியாக அறிவிக்கப்படும் வகையில் படிவக் கட்டுப்பாடுகள் இருப்பதை லேபிள்கள் உறுதிசெய்கின்றன. [மேலும் அறிக](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "படிவ உறுப்புகளுக்கு, தொடர்புடைய லேபிள்கள் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "படிவ உறுப்புகளுக்கு, தொடர்புடைய லேபிள்கள் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "தளவமைப்புக்காகப் பயன்படுத்தப்படும் அட்டவணையில் th, தலைப்பு உறுப்புகள், சுருக்கவிவரப் பண்புக்கூறு போன்ற தரவு உறுப்புகளை சேர்க்கக் கூடாது, ஏனெனில் இது ஸ்க்ரீன் ரீடர் பயனர்களுக்குக் குழப்பத்தை ஏற்படுத்தும். [மேலும் அறிக](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "`<th>`, `<caption>` அல்லது `[summary]` பண்புக்கூறைப் பயன்படுத்துவதை விளக்க `<table>` உறுப்புகள் தவிர்க்கவில்லை."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "`<th>`, `<caption>` அல்லது `[summary]` பண்புக்கூறைப் பயன்படுத்துவதை விளக்க `<table>` உறுப்புகள் தவிர்க்கும்."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "தெளிவான, தனித்துவமான, மையப்படுத்தக்கூடிய இணைப்பு உரை (மற்றும் இணைப்புகளாகப் பயன்படுத்தப்படும் படங்களுக்கான மாற்று உரை) ஸ்க்ரீன் ரீடர் பயனர்களுக்கான வழிகாட்டும் அனுபவத்தை மேம்படுத்தும். [மேலும் அறிக](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "இணைப்புகளுக்குத் தெளிவான பெயர் இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "இணைப்புகளுக்குத் தெளிவான பெயர்கள் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "பட்டியல்களை அறிவிப்பதற்கு ஸ்க்ரீன் ரீடர்களுக்கென ஒரு குறிப்பிட்ட வழிமுறை உள்ளது. சரியான பட்டியல் வடிவமைப்பை உறுதிசெய்தால் அது ஸ்க்ரீன் ரீடர் வெளியீட்டுக்கு உதவிசெய்யும். [மேலும் அறிக](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "பட்டியல்களில் `<li>` உறுப்புகள், ஸ்கிரிப்ட்டை ஆதரிக்கும் உறுப்புகள்(`<script>`,`<template>`) மட்டுமல்லாமல் வேறு உறுப்புகளும் உள்ளன."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "`<li>` உறுப்புகள், ஸ்கிரிப்ட்டை ஆதரிக்கும் உறுப்புகள் (`<script>`, `<template>`) ஆகியவை மட்டும் பட்டியல்களில் உள்ளன."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "பட்டியலில் உள்ளவற்றை (`<li>`) ஸ்க்ரீன் ரீடர்கள் சரியாகப் படிப்பதற்கு அவை ஒரு முதல்நிலை `<ul>` அல்லது `<ol>`க்குள் இருக்க வேண்டும். [மேலும் அறிக](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "பட்டியலிலுள்ளவை (`<li>`) `<ul>` என்பதிலோ `<ol>` முதல்நிலை உறுப்புகளிலோ இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "பட்டியலிலுள்ளவை (`<li>`), `<ul>` அல்லது `<ol>` முதல்நிலை உறுப்புகளுக்குள் உள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "பக்கம் தானாகப் புதுப்பிக்கும் எனப் பயனர்கள் எதிர்பார்க்க மாட்டார்கள். அவ்வாறு ஏற்பட்டால் பக்கம் மீண்டும் முதலில் இருந்தே காட்டப்படும். இது அவர்களுக்குக் குழப்பத்தை விளைவிக்கக்கூடும். [மேலும் அறிக](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "ஆவணம் `<meta http-equiv=\"refresh\">`ஐப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "`<meta http-equiv=\"refresh\">`ஐ ஆவணம் பயன்படுத்தவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "அளவை மாற்றும் வசதியை முடக்கினால் இணையப் பக்கத்தில் உள்ளவற்றைத் தெளிவாகப் பார்க்க 'திரையைப் பெரிதாக்கும் செயல்பாட்டைப்' பயன்படுத்தும் பார்வைக் குறைபாடுள்ள பயனர்களுக்கு சிக்கல் ஏற்படும். [மேலும் அறிக](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`<meta name=\"viewport\">` உறுப்பில் `[user-scalable=\"no\"]` பயன்படுத்தப்பட்டுள்ளது அல்லது `[maximum-scale]` பண்புக்கூறின் மதிப்பு 5க்குக் கீழ் உள்ளது."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`<meta name=\"viewport\">` உறுப்பில் `[user-scalable=\"no\"]` பயன்படுத்தப்படவில்லை, `[maximum-scale]` பண்புக்கூறு 5க்குக் குறைவாக இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "உரை அல்லாதவற்றை ஸ்க்ரீன் ரீடர்களால் மொழிபெயர்க்க முடியாது. `<object>` உறுப்புகளுக்கு மாற்று உரையை சேர்த்தால் அவற்றுக்கான அர்த்தத்தை ஸ்க்ரீன் ரீடர்கள் பயனர்களுக்குத் தெரிவிக்கும். [மேலும் அறிக](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` உறுப்புகளில் `[alt]` உரை இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` உறுப்புகள் `[alt]` உரையைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "0க்கு அதிகமான மதிப்பானது வெளிப்படையான ஒரு வழிசெலுத்தல் வரிசை முறையைக் குறிப்பிடுகிறது. முறைப்படி செல்லுபடியாகும் என்றாலும் தொழில்நுட்பங்களை சார்ந்திருக்கும் மாற்றுத்திறன் பயனர்களுக்கு இது பெரும்பாலும் குழப்பமான அனுபவத்தையே உருவாக்கும். [மேலும் அறிக](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "சில உறுப்புகளின் `[tabindex]` மதிப்பு 0க்கு அதிகமாக உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "எந்த உறுப்புக்கும் `[tabindex]` மதிப்பு 0க்கு அதிகமாக இல்லை"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "அட்டவணைகளில் எளிதாகச் செல்வதற்கு ஸ்க்ரீன் ரீடர்களில் அம்சங்கள் உள்ளன. `[headers]` பண்புக்கூறைப் பயன்படுத்தும் `<td>` கலங்கள் அதே அட்டவணையில் உள்ள பிற கலங்களை மட்டும் குறிப்பிடுவதை உறுதிசெய்தால் அது ஸ்க்ரீன் ரீடர் பயனர்களின் அனுபவத்தை மேம்படுத்தக்கூடும். [மேலும் அறிக](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`[headers]` பண்புக்கூற்றைப் பயன்படுத்தும் `<table>` உறுப்பிலுள்ள கலங்கள் அதே அட்டவணையில் கண்டறியப்படாத `id` உறுப்பைக் குறிப்பிடுகின்றன."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`[headers]` பண்புக்கூற்றைப் பயன்படுத்தும் `<table>` உறுப்பிலுள்ள கலங்கள் அதே அட்டவணையிலுள்ள கலங்களைக் குறிப்பிடுகின்றன."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "அட்டவணைகளில் எளிதாகச் செல்வதற்கு ஸ்க்ரீன் ரீடர்களில் அம்சங்கள் உள்ளன. அட்டவணைத் தலைப்புகள் எப்போதும் சில கலங்களின் தொகுப்பைக் குறிப்பிடுமாறு அமைப்பது ஸ்க்ரீன் ரீடர் பயனர்களின் அனுபவத்தை மேம்படுத்தக்கூடும். [மேலும் அறிக](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` உறுப்புகளும் `[role=\"columnheader\"/\"rowheader\"]`ஐக் கொண்டுள்ள உறுப்புகளும் விவரிக்கும் தரவுக் கலங்கள் அவற்றுக்கு இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` உறுப்புகளும் `[role=\"columnheader\"/\"rowheader\"]`ஐக் கொண்டுள்ள உறுப்புகளும் விவரிக்கும் தரவுக் கலங்கள் அவற்றுக்கு உள்ளன."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "உறுப்புகளில் செல்லுபடியாகும் [BCP 47 மொழியைக்](https://www.w3.org/International/questions/qa-choosing-language-tags#question) குறிப்பிட்டால், உரையை ஸ்க்ரீன் ரீடர் சரியாக உச்சரிக்கிறதா என்பதை உறுதிப்படுத்திக் கொள்ள அது உதவும். [மேலும் அறிக](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` பண்புக்கூறுகள் செல்லுபடியாகும் மதிப்பைக் கொண்டிருக்கவில்லை"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` பண்புக்கூறுகள் செல்லுபடியாகும் மதிப்பைக் கொண்டுள்ளன"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "வீடியோவில் தலைப்பு குறிப்பிடப்பட்டிருந்தால் காது கேளாதோர், செவித்திறன் குறைபாடுள்ளவர்கள் அதுகுறித்த தகவல்களை அறிந்துகொள்ள எளிதாக இருக்கும். [மேலும் அறிக](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` உறுப்புகளில் `[kind=\"captions\"]` உள்ள `<track>` உறுப்பு இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` உறுப்புகளில் `[kind=\"captions\"]`ஐக் கொண்டுள்ள`<track>` உறுப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "வீடியோக்களில் வசனங்களால் வெளிப்படுத்த முடியாத முக பாவனைகள், காட்சிகள் போன்றவற்றுக்கான தொடர்புடைய தகவல்களை ஆடியோ விளக்கங்கள் வழங்கும். [மேலும் அறிக](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` உறுப்புகளில் `[kind=\"description\"]` உள்ள `<track>` உறுப்பு இல்லை."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` உறுப்புகளில் `[kind=\"description\"]`ஐக் கொண்டுள்ள`<track>` உறுப்பு உள்ளது"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "முகப்புத் திரையில் நவீன இணைய ஆப்ஸை பயனர்கள் சேர்க்கும் போது iOSஸில் சிறப்பாகத் தோன்ற `apple-touch-icon` ஒன்றை வரையறுக்கவும். அது ஒளிபுகுத்தன்மையற்ற 192 பிகசல் (அல்லது 180 பிக்சல்) அளவுள்ள கட்ட வடிவத்திலான PNGயைக் காட்ட வேண்டும். [மேலும் அறிக](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "செல்லுபடியாகும் `apple-touch-icon`ஐ வழங்கவில்லை"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` காலாவதியாகிவிட்டது; `apple-touch-icon` பரிந்துரைக்கப்படுகிறது."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "செல்லுபடியாகும் `apple-touch-icon`ஐ வழங்குகிறது"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome நீட்டிப்புகள் இந்தப் பக்கத்தின் ஏற்றுதல் செயல்திறனை எதிர்மறையாகப் பாதிக்கின்றன. மறைநிலையிலோ, நீட்டிப்புகள் இல்லாத ஒரு Chrome கணக்கிலிருந்தோ பக்கத்தைத் தணிக்கை செய்ய முயலவும்."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "ஸ்கிரிப்ட் மதிப்பாய்வு"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "ஸ்கிரிப்ட் பாகுபடுத்துதல்"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "மொத்த CPU நேரம்"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JSஸைப் பாகுபடுத்துதல், தொகுத்தல் மற்றும் இயக்குவதில் செலவழிக்கும் நேரத்தைக் குறைக்கவும். இதற்கு சிறிய அளவிலான JS ஆதாரங்களை வழங்குவது உதவக்கூடும். [மேலும் அறிக](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript செயல்பாட்டு நேரத்தைக் குறைக்கவும்"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript செயல்பாட்டு நேரம்"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "அனிமேஷன் செய்தவற்றைக் காட்டுவதற்கு பெரிய அளவிலான GIFகள் பொருத்தமானவை அல்ல. நெட்வொர்க் பைட்களை சேமிக்க GIFக்குப் பதிலாக அனிமேஷன்களுக்கு MPEG4/WebM வீடியோக்களையும் நிலையான படங்களுக்கு PNG/WebP வடிவமைப்புகளையும் பயன்படுத்தவும். [மேலும் அறிக](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "அனிமேஷன் செய்யப்பட்ட உள்ளடக்கங்களுக்கு வீடியோ வடிவமைப்புகளைப் பயன்படுத்தவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "எதிர்வினையாற்றும் நேரத்தைக் குறைக்க முக்கியமான அனைத்து ஆதாரங்களும் ஏற்றப்பட்ட பின்னர், திரைக்கு வெளியிலுள்ள மற்றும் மறைக்கப்பட்ட படங்களை மெதுவாக ஏற்றுமாறு அமைக்கவும். [மேலும் அறிக](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "திரைக்கு வெளியிலுள்ள படங்களைத் தவிர்க்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "ஆதாரங்கள் உங்கள் பக்கத்தின் முதல் தோற்றத்தைத் தடுக்கின்றன. முக்கிய JS/CSSஸை இன்லைனில் வழங்கவும். முக்கியமல்லாத அனைத்து JS/ஸ்டைல்களையும் தவிர்க்கவும். [மேலும் அறிக](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "ரென்டரிங்கைத் தடுக்கும் ஆதாரங்களை நீக்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "அதிகளவிலான நெட்வொர்க் ஆதாரங்கள், பயனர்களுக்குப் பண இழப்பை ஏற்படுத்துவதோடு பக்கங்கள் ஏற்றப்பட நீண்ட நேரமாவதற்கும் காரணமாகின்றன. [மேலும் அறிக](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "மொத்த அளவு: {totalBytes, number, bytes} கி.பை."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "அபரிமிதமான நெட்வொர்க் ஆதாரங்களைத் தவிர்க்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "அபரிமிதமான நெட்வொர்க் ஆதாரங்களைத் தவிர்க்கிறது"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS கோப்புகளை சிறிதாக்கினால் நெட்வொர்க் ஆதாரங்களின் அளவுகள் குறையலாம். [மேலும் அறிக](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSSஸைச் சிறிதாக்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript கோப்புகளை சிறிதாக்கி ஆதாரங்களின் அளவுகளையும் ஸ்கிரிப்ட் பாகுபடுத்தப்படும் நேரத்தையும் குறைக்கலாம். [மேலும் அறிக](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScriptடைச் சிறிதாக்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "நெட்வொர்க் செயல்பாட்டின்போது பயன்படுத்தப்படும் தேவையற்ற பைட்களைக் குறைக்க, ஸ்டைல்ஷீட்களிலிருந்து காலாவதியான விதிகளை அகற்றி, பக்கத்தின் மேல் பகுதியில் உள்ள உள்ளடக்கத்தை ஏற்றுவதற்குப் பயன்படுத்தப்படுத்தப்படாத CSSஸை ஏற்றுவதைத் தவிர்க்கவும். [மேலும் அறிக](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "பயன்படுத்தப்படாத CSSசை அகற்றவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "நெட்வொர்க் செயல்பாடு பயன்படுத்தும் பைட்களைக் குறைப்பதற்கு, பயன்படுத்தப்படாத JavaScriptடை அகற்றவும்."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "பயன்படுத்தப்படாத JavaScriptடை அகற்றவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "தற்காலிக நினைவகத்தின் ஆயுட்காலம் நீண்டதாக இருந்தால் அது மீண்டும் மீண்டும் திறக்கப்படும் உங்கள் இணையப் பக்கங்களை விரைவாக ஏற்றக்கூடும். [மேலும் அறிக](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ஆதாரம் கண்டறியப்பட்டது}other{# ஆதாரங்கள் கண்டறியப்பட்டன}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "திறனுள்ள தற்காலிக நினைவகக் கொள்கையுடன் நிலையான உள்ளடக்கத்தை வழங்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "நிலையான உள்ளடக்கத்தில் திறனுள்ள தற்காலிக நினைவகக் கொள்கையைப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "மேம்படுத்தப்பட்ட படங்கள் குறைவான மொபைல் டேட்டாவைப் பயன்படுத்தி விரைவாக ஏற்றும். [மேலும் அறிக](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "படங்களைத் திறம்பட என்கோடிங் செய்யவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "மொபைல் டேட்டாவை சேமிக்கவும் பக்கத்தை விரைவாக ஏற்றவும் படங்களை சரியான அளவில் வழங்கவும். [மேலும் அறிக](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "படங்களைச் சரியான அளவுக்கு மாற்றவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "மொத்த நெட்வொர்க் பைட்களைக் குறைப்பதற்கு, உரை அடிப்படையிலான ஆதாரங்கள் சுருக்கப்பட்டு (gzip, deflate அல்லது brotli) வழங்கப்பட வேண்டும். [மேலும் அறிக](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "உரைச் சுருக்கத்தை இயக்கவும்"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000, JPEG XR, WebP போன்ற பட வடிவமைப்புகளானது PNG அல்லது JPEGயைக் காட்டிலும் சிறந்த அளவு சுருக்கத்தை வழங்குகின்றன, இதன் மூலம் பதிவிறக்கங்கள் வேகமாக நடைபெறுவதுடன் டேட்டா உபயோகமும் குறையும். [மேலும் அறிக](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "படங்களை நவீன வடிவமைப்புகளில் வழங்கவும்"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "ஆப்ஸின் உள்ளடக்க அகலம் காட்சிப் பகுதியின் அகலத்துடன் பொருந்தவில்லை எனில் மொபைல் திரைகளுக்கு ஏற்ற வகையில் உங்கள் ஆப்ஸ் மேம்படுத்தப்படாமல் போகலாம். [மேலும் அறிக](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{innerWidth} என்ற காட்சிப் பகுதி அளவு பிக்சலுடன் {outerWidth} என்ற சாளரத்தின் அளவு பிக்சல் பொருந்தவில்லை."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "காட்சிப் பகுதிக்கு ஏற்ற வகையில் உள்ளடக்கம் சரியாகப் பொருந்தவில்லை"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "காட்சிப் பகுதிக்கு ஏற்ற வகையில் உள்ளடக்கம் சரியாகப் பொருந்துகிறது"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "கீழே இருக்கும் 'முக்கியக் கோரிக்கை வரிசைகள்' எந்தெந்த ஆதாரங்கள் அதிக முன்னுரிமையுடன் ஏற்றப்பட்டன என்பதைக் காட்டுகின்றன. பக்கம் ஏற்றப்படுவதன் வேகத்தை அதிகரிக்க, வரிசைகளின் நீளத்தைக் குறைத்தல், ஆதாரங்களின் பதிவிறக்க அளவைக் குறைத்தல் அல்லது தேவையற்ற ஆதாரங்களைப் பதிவிறக்குவதைத் தவிர்த்தல் போன்றவற்றை முயற்சி செய்யவும். [மேலும் அறிக](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 வரிசை கண்டறியப்பட்டது}other{# வரிசைகள் கண்டறியப்பட்டன}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "'முக்கியக் கோரிக்கைகளின் அடுக்கைக்' குறைக்கவும்"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "தடுத்தல் / எச்சரித்தல்"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "வரி"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "தடுக்கப்பட்ட APIகள் இறுதியில் உலாவியிலிருந்து அகற்றப்படும். [மேலும் அறிக](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 எச்சரிக்கை கண்டறியப்பட்டது}other{# எச்சரிக்கைகள் கண்டறியப்பட்டுள்ளன}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "தடுக்கப்பட்ட APIகளைப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "தடுக்கப்பட்டுள்ள APIகளைத் தவிர்க்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "ஆப்ஸின் தற்காலிக சேமிப்பு தடுக்கப்பட்டுள்ளது. [மேலும் அறிக](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" கண்டறியப்பட்டது"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "ஆப்ஸின் தற்காலிக சேமிப்பைப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "ஆப்ஸின் தற்காலிக சேமிப்பைத் தவிர்க்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "ஆவண வகையைக் குறிப்பிடுவது குவர்க்ஸ் பயன்முறைக்கு உலாவியை மாற்றுவதைத் தடுக்கும். [மேலும் அறிக](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "ஆவண வகையின் பெயர் சிற்றெழுத்துகளில் இருக்க வேண்டும் `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "ஆவணமானது ஏதேனுமொரு ஆவண வகையைக் கொண்டிருக்க வேண்டும்"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "பப்ளிக்ஐடி காலியாக இருந்திருக்க வேண்டும்"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "சிஸ்டம்ஐடி காலியாக இருந்திருக்க வேண்டும்"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "பக்கத்தில் HTML ஆவண வகை இல்லாததால் குவர்க்ஸ் பயன்முறையை இயக்குகிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "இந்தப் பக்கமானது HTML ஆவண வகையில் உள்ளது"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "உறுப்பு"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "புள்ளிவிவரம்"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "மதிப்பு"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "உலாவிப் பொறியாளர்கள் ~1,500 DOM உறுப்புகளுக்குக் குறைவாக இருக்கும் பக்கங்களையே பரிந்துரைக்கின்றனர். ட்ரீ டெப்த் 32 உறுப்புகளுக்குக் கீழ் இருப்பதும் உபநிலை/முதல்நிலை உறுப்புகள் 60க்குக் கீழ் இருப்பதும் மிக சரியான அளவுகளாகும். ஒரு பெரிய DOMமால் நினைவக உபயோகத்தை அதிகரிக்கவும், [ஸ்டைல் கணக்கீடுகளை](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) நீட்டிக்கவும், அதிக செலவு பிடிக்கும் [தளவமைப்பு மறுசீராக்கங்களை](https://developers.google.com/speed/articles/reflow) ஏற்படுத்தவும் முடியும். [மேலும் அறிக](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 உறுப்பு}other{# உறுப்புகள்}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "அபரிமிதமான DOM அளவைத் தவிர்க்கவும்"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "அதிகபட்ச DOM கிளை அடுக்கு"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "மொத்த DOM உறுப்புகள்"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "அதிகபட்சத் துணை உறுப்புகள்"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "அபரிமிதமான DOM அளவைத் தவிர்க்கிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "இலக்கு"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "ஏதேனும் புற இணைப்புகளின் செயல்திறனை அதிகரிக்கவும் அவற்றிலுள்ள பாதுகாப்புக் குறைபாடுகளைத் தடுக்கவும் `rel=\"noopener\"` அல்லது `rel=\"noreferrer\"`ஐ சேர்க்கவும். [மேலும் அறிக](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "வேறு மூலங்களுக்கு செல்லும் இணைப்புகள் பாதுகாப்பற்றவை"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "வேறு மூலங்களுக்கு செல்லும் இணைப்புகள் பாதுகாப்பானவை"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "ஆங்கருக்கான இடத்தை நிர்ணயிக்க முடியவில்லை ({anchorHTML}). லிங்க்காகப் பயன்படாதபட்சத்தில் target=_blank என்பதை அகற்றவும்."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "சரியான காரணங்கள் இன்றி இருப்பிடத்தை அறிய கோரிக்கையிடும் தளங்களால் பயனர்கள் குழப்பமடையலாம் அல்லது சந்தேகப்படலாம். அதற்கு பதிலாக பயனர் செயல்பாட்டை முயலவும். [மேலும் அறிக](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "பக்கம் ஏற்றப்படும்போது உங்கள் புவி இருப்பிடத்தைத் தெரிந்துகொள்வதற்கான அனுமதியைக் கோரும்"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "பக்கம் ஏற்றப்படும்போது உங்கள் புவி இருப்பிடத்தைத் தெரிந்துகொள்வதற்கான அனுமதியைக் கோராது"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "பதிப்பு"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "பக்கத்திலுள்ள அனைத்து ஃபிரெண்ட் எண்ட் JavaScript லைப்ரரிகளையும் கண்டறிந்துள்ளது. [மேலும் அறிக](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript லைப்ரரிகள் கண்டறியப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "வேகம் குறைந்த இணைய சேவை உள்ள பயனர்களுக்கு, வெளி ஸ்கிரிப்ட்களை `document.write()` வழியாக உட்செலுத்தும்போது பக்கத்தை ஏற்றுவதை அது பல வினாடிகள் தாமதிக்கும். [மேலும் அறிக](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()`ஐப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()`ஐத் தவிர்க்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "அதிகபட்ச அபாயம்"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "லைப்ரரி பதிப்பு"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "பாதுகாப்புக் குறைபாடுகளின் எண்ணிக்கை"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "சில மூன்றாம் தரப்பு ஸ்கிரிப்ட்களில் ஹேக்கர்கள் எளிதாக அடையாளம் கண்டுகொண்டு பயன்படுத்திக் கொள்ளக்கூடிய தெரிந்த பாதுகாப்புக் குறைபாடுகள் இருக்கக்கூடும். [மேலும் அறிக](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 பாதுகாப்புக் குறைபாடு கண்டறியப்பட்டுள்ளது}other{# பாதுகாப்புக் குறைபாடுகள் கண்டறியப்பட்டுள்ளன}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "தெரிந்த பாதுகாப்புக் குறைபாடுகளுள்ள ஃபிரண்ட் எண்டு JavaScript லைப்ரரிகள் இதில் அடங்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "அதிகம்"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "குறைவானது"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "நடுத்தரமானது"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "தெரிந்த பாதுகாப்புக் குறைபாடுகளுடைய ஃபிரண்ட் எண்ட் JavaScript லைப்ரரிகளைத் தவிர்க்கிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "சரியான காரணங்கள் இன்றி அறிவிப்புகளை அனுப்பக் கோரிக்கையிடும் தளங்களால் பயனர்கள் குழப்பமடையலாம் அல்லது சந்தேகப்படலாம். அதற்கு பதிலாக பயனர் சைகைகளை முயலவும். [மேலும் அறிக](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "பக்கம் ஏற்றப்படும்போது அதுகுறித்த அறிவிப்பைத் தெரிந்துகொள்வதற்கான அனுமதியைக் கோரும்"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "பக்கம் ஏற்றப்படும்போது அதுகுறித்த அறிவிப்பைத் தெரிந்துகொள்வதற்கான அனுமதியைக் கோராது"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "தோல்வியுறும் உறுப்புகள்"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "கடவுச்சொல்லை ஒட்டுவதைத் தடுப்பதால் நல்ல பாதுகாப்புக் கொள்கை பாதிக்கப்படுகிறது. [மேலும் அறிக](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "கடவுச்சொல் புலங்களில் பயனர்கள் ஒட்டுவதைத் தடுக்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "கடவுச்சொல் புலங்களில் பயனர்கள் ஒட்டுவதை அனுமதிக்கும்"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "நெறிமுறை"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/1.1ஐ விட அதிகப் பலன்களை HTTP/2 வழங்குகிறது. அவற்றில் பைனரி ஹெட்டர்கள், மல்டிஃபிளெக்ஸிங் மற்றும் சர்வர் ஃபுஷ் போன்றவை அடங்கும். [மேலும் அறிக](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{HTTP/2 வழியாக 1 கோரிக்கை பதிலளிக்கப்படவில்லை}other{HTTP/2 வழியாக # கோரிக்கைகள் பதிலளிக்கப்படவில்லை}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "அதன் அனைத்து ஆதாரங்களுக்கும் HTTP/2வைப் பயன்படுத்தவில்லை"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "அதன் சொந்த ஆதாரங்களுக்கு HTTP/2வைப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "உங்கள் பக்கத்தின் நகர்த்துதல் செயல்திறனை மேம்படுத்த டச் மற்றும் வீல் ஈவண்ட் லிசனர்களை `passive` என அமைக்கவும். [மேலும் அறிக](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "நகர்த்துதல் செயல்திறனை மேம்படுத்துவதற்காக பேசிவ் லிசனர்களைப் பயன்படுத்தவில்லை"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "நகர்த்துதல் செயல்திறனை மேம்படுத்துவதற்காக பேசிவ் லிசனர்களைப் பயன்படுத்துகின்றன"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "விளக்கம்"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "கன்சோலில் பதிவுசெய்யப்பட்ட பிழைகள் தீர்க்கப்படாத சிக்கல்களைக் குறிக்கின்றன. அவை நெட்வொர்க் கோரிக்கை பிழைகளினாலும் வேறு உலாவி சிக்கல்களினாலும் ஏற்பட்டிருக்கும். [மேலும் அறிக](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "கன்சோலில் உலாவி தொடர்பான பிழைகள் பதிவு செய்யப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "கன்சோலில் உலாவியின் பிழைகள் எதுவும் பதிவு செய்யப்படவில்லை"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "இணைய எழுத்துருக்கள் ஏற்றப்படும்போது உரை எழுத்துகள் பயனருக்குத் தெரிவதை உறுதிசெய்ய எழுத்துருக் காட்சியின் CSS அம்சத்தை சேர்க்கவும். [மேலும் அறிக](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "இணைய எழுத்துரு ஏற்றப்படும்போது உரை எழுத்துகள் தெரிவதை உறுதிசெய்யவும்"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "இணைய எழுத்துருக்கள் ஏற்றப்படும்போது உரை எழுத்துகள் அனைத்தும் தெரிகின்றன"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "பின்வரும் URLளுக்கான எழுத்துருக் காட்சியின் மதிப்பை Lighthouseஸால் தானாக சரிபார்க்க முடியவில்லை: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "தோற்ற விகிதம் (அசல்)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "தோற்ற விகிதம் (காட்சிப்படுத்தப்பட்டது)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "படத்தின் காட்சிப் பரிமாணங்கள் இயல்பான தோற்ற விகிதத்துடன் பொருந்த வேண்டும். [மேலும் அறிக](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "தவறான தோற்ற விகிதமுள்ள படங்களைக் காட்டுகிறது"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "சரியான தோற்ற விகிதத்துடன் படங்களைக் காட்டுகிறது"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "பட அளவு குறித்த தகவல் செல்லாதது {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "முக்கியத்துவத்தின் காரணமாக ஆப்ஸை முகப்புத் திரையில் சேர்க்குமாறு முன்னெச்சரிக்கையாக உலாவிகள் பயனர்களுக்கு அறிவிக்கும். [மேலும் அறிக](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "இணைய ஆப்ஸ் மெனிஃபெஸ்ட் நிறுவுதலுக்கான தேவைகளைப் பூர்த்தி செய்யவில்லை"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "இணைய ஆப்ஸ் மெனிஃபெஸ்ட்டானது நிறுவுதலுக்கான தேவைகளைப் பூர்த்தி செய்கிறது"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "பாதுகாப்பில்லாத URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "அனைத்துத் தளங்களும் HTTPS மூலம் பாதுகாக்கப்பட வேண்டும், பாதுகாக்கப்பட வேண்டிய தனிப்பட்ட தரவைக் கொண்டிருக்காத தளங்களுக்கும் இது பொருந்தும். உங்கள் ஆப்ஸிற்கும் பயனர்களுக்கும் இடையில் நடக்கும் தகவல் பரிமாற்றத்தில் குறுக்கிடுபவர்களையும் மறைந்திருந்து கவனிப்பவர்களையும் HTTPS தடுக்கிறது. அது HTTP/2 மற்றும் பல புதிய பிளாட்ஃபார்ம் APIகளில் முக்கியமாக இருக்க வேண்டியதாகும். [மேலும் அறிக](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{பாதுகாப்பு இல்லாத 1 கோரிக்கை கண்டறியப்பட்டுள்ளது}other{பாதுகாப்பு இல்லாத # கோரிக்கைகள் கண்டறியப்பட்டுள்ளன}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "HTTPSஸைப் பயன்படுத்தவில்லை"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPSஸைப் பயன்படுத்துகிறது"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "மொபைல் நெட்வொர்க்கில் பக்கம் வேகமாக ஏற்றப்பட்டால் அது மொபைல் பயனர்களுக்கு சிறந்த அனுபவத்தை வழங்கும். [மேலும் அறிக](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "பக்கம் பதிலளிக்க எடுத்துக்கொண்ட நேரம்: {timeInMs, number, seconds} வி."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "மாதிரி மொபைல் நெட்வொர்க்கில் {timeInMs, number, seconds} வினாடிகளில் பதிலளிக்கிறது"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "உங்கள் பக்கம் மிகவும் மெதுவாக ஏற்றப்படுவதால் 10 நொடிகளுக்குள் விரைவாகப் பதிலளிக்கவில்லை. எவ்வாறு மேம்படுத்துவது என்பதைத் தெரிந்து கொள்ள \"செயல்திறன்\" பிரிவில் உள்ள 'வாய்ப்புகள் மற்றும் பிழை கண்டறிதல்' என்பதைப் பார்க்கவும்."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "மொபைல் நெட்வொர்க்குகளில் பக்கம் போதுமான வேகத்தில் ஏற்றப்படவில்லை"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "மொபைல் நெட்வொர்க்குகளில் பக்கம் போதுமான வேகத்தில் ஏற்றப்படுகிறது"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "வகை"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "JSஸைப் பாகுபடுத்துதல், தொகுத்தல் மற்றும் இயக்குவதில் செலவழிக்கும் நேரத்தைக் குறைக்கவும். இதைச் செய்வதற்கு சிறிய அளவிலான JS ஆதாரங்களை வழங்கலாம். [மேலும் அறிக](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "முக்கியத் தொடரிழையின் பணியைக் குறைக்கவும்"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "முக்கியத் தொடரிழையின் பணியைக் குறைக்கிறது"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "அதிக அளவிலான பயனர்களைப் பெற பிரபலமான ஒவ்வொரு உலாவியிலும் தளங்கள் செயல்பட வேண்டும். [மேலும் அறிக](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "வெவ்வேறு உலாவியிலும் தளம் செயல்படும்"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "URL மூலம் தனிப்பட்ட பக்கங்களை லிங்க் செய்யலாம் என்பதையும் சமூக வலைதளங்களில் பகிர்வதற்கு அந்த URLகள் தனித்துவமானவை என்பதையும் உறுதிப்படுத்தவும். [மேலும் அறிக](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "ஒவ்வொரு பக்கத்திற்கும் URL உள்ளது"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "வேகம் குறைந்த நெட்வொர்க்கிலும் பக்கத்தை நீங்கள் தட்டும்போது மாற்றங்கள் விரைவாக இருக்க வேண்டும். இது சிறந்த செயல்திறன் என பயனர் கருதும் முக்கிய அம்சமாகும். [மேலும் அறிக](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "பக்கத்தின் மாற்றங்கள் நெட்வொர்க்கில் தடுக்கப்பட்டவை போன்று தோன்றக்கூடாது"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "'தோராய உள்ளீட்டுத் தாமதம்' என்பது பக்கம் ஏற்றப்படும் பிஸியான 5 வினாடி காலஅளவின்போது பயனரின் உள்ளீட்டுக்கு பதிலளிக்க உங்கள் ஆப்ஸ் எவ்வளவு நேரம் எடுத்துக் கொள்கிறது என்பதற்கான தோராய மதிப்பாகும். பதிலளிக்க 50 மி.வி.க்கு மேல் தாமதமானால் உங்கள் ஆப்ஸ் மெதுவானது என்று பயனர்கள் கருதக்கூடும். [மேலும் அறிக](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "தோராயமான உள்ளீட்டுத் தாமதம்"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "'உள்ளடக்கமுள்ள முதல் தோற்றம்' என்பது முதல் உரையோ படமோ தோன்றும் நேரத்தைக் குறிக்கிறது. [மேலும் அறிக](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "உள்ளடக்கமுள்ள முதல் தோற்றம்"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "'CPU செயல்படாநிலையின் தொடக்க நேரம்' என்பது உள்ளீட்டை பக்கத்தின் முக்கியத் தொடரிழை கையாள்வதற்குத் தயாராக செயல்படாநிலையில் இருக்கும் நேரத்தின் தொடக்கத்தைக் குறிக்கிறது. [மேலும் அறிக](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU செயல்படாநிலையின் தொடக்க நேரம்"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "'பயனுள்ள முதல் தோற்றம்' என்பது பக்கத்தின் முதன்மை உள்ளடக்கம் எப்போது தெரிகிறது என்பதை அளவிடுகிறது. [மேலும் அறிக](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "அர்த்தமுள்ள முதல் தோற்றம்"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "எதிர்வினை நேரம் என்பது பக்கம் முழுமையாக எதிர்வினையாற்றும் வகையில் ஏற்றப்படுவதற்கான கால அளவாகும். [மேலும் அறிக](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "எதிர்வினை நேரம்"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "உங்கள் பயனர்கள் எதிர்கொள்ளக்கூடிய அதிக சாத்தியமான ’முதல் உள்ளீட்டுத் தாமதம்’ என்பது மிக நீண்ட பணியின் காலஅளவாகும் (மில்லி வினாடிகளில் குறிப்பிடப்படும்). [மேலும் அறிக](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "முதல் உள்ளீட்டிற்கு பதிலளிக்கக்கூடிய அதிகபட்ச நேரம்"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "பக்கத்திலுள்ள உள்ளடக்கங்கள் எவ்வளவு விரைவாகத் தெரிகின்றன என்பதை 'வேக அட்டவணை' காண்பிக்கிறது. [மேலும் அறிக](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "வேக அட்டவணை"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "பணியின் நீளம் 50மி.வி.களைத் தாண்டும்போது FCP மற்றும் எதிர்வினை நேரத்திற்கு இடையில் இருக்கும் மொத்தக் கால அளவுகளின் கூடுதல் (மில்லி வினாடிகளில்)."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "தடுக்கப்படும் மொத்த நேரம்"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "நெட்வொர்க் ரவுண்ட் டிரிப் டைம்ஸ் (Round Trip Times - RTT) செயல்திறனில் பெரும் தாக்கத்தை ஏற்படுத்தும். அசல் சேவையகத்துக்கான RTT அதிகமாக இருந்தால் பயனரின் அருகில் இருக்கும் சேவையகங்கள் இணையதளத்தின் செயல்திறனை மேம்படுத்தலாம் என்பதைக் குறிக்கும். [மேலும் அறிக](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "நெட்வொர்க் ரவுண்ட் டிரிப் நேரங்கள்"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "சேவையகத் தாமதங்கள் இணைய செயல்திறனைப் பாதிக்கக்கூடும். மூல சேவையகத்தில் தாமதம் அதிகமாக இருந்தால் சேவையகத்தின் வேலைப் பளு அதிகமாக உள்ளது அல்லது மோசமான பின்னணி செயல்திறன் உள்ளது என்று பொருள். [மேலும் அறிக](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "சேவையக பேக்எண்ட் தாமதங்கள்"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "கணிக்க முடியாத நெட்வொர்க் சூழல்களிலும் சேவைச் செயலாக்கி உங்கள் இணைய ஆப்ஸை நம்பகமானதாக மாற்றும். [மேலும் அறிக](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "ஆஃப்லைனில் உள்ள போது 200 என்ற HTTP நிலைக் குறியீட்டுடன் `start_url` விரைவாகப் பதிலளிக்கவில்லை"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "ஆஃப்லைனில் உள்ள போது 200 என்ற HTTP நிலைக் குறியீட்டுடன் `start_url` விரைவாகப் பதிலளிக்கும்"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "மெனிஃபெஸ்ட்டில் இருந்து `start_url`ஐ Lighthouseஸால் படிக்க முடியவில்லை. இதனால் `start_url` இந்த ஆவணத்தின் URL ஆகக் கருதப்பட்டது. பிழைச் செய்தி: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "பட்ஜெட்டைத் தாண்டிவிட்டது"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "நெட்வொர்க் கோரிக்கைகளின் அளவையும் எண்ணிக்கையையும் செயல்திறன் பட்ஜெட் அமைத்துள்ள இலக்கீடுகளுக்குள் வைத்திருக்கவும். [மேலும் அறிக](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 கோரிக்கை}other{# கோரிக்கைகள்}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "செயல்திறன் பட்ஜெட்"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "HTTPSஐ ஏற்கனவே நீங்கள் அமைத்திருந்தால் உங்களின் அனைத்துப் பயனர்களுக்கும் பாதுகாப்பான இணைய அம்சங்களைச் செயல்படுத்தும் வகையில் எல்லா HTTP ட்ராஃபிக்கையும் HTTPSக்குத் திசைதிருப்பவும். [மேலும் அறிக](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP ட்ராஃபிக் HTTPSக்குத் திசைதிருப்பப்படவில்லை"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTPSக்கு HTTP ட்ராஃபிக்கைத் திசைதிருப்பும்"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "'திசைதிருப்புதல்கள்' பக்கம் ஏற்றப்படுவதற்கு முன்பு கூடுதல் தாமதங்களை ஏற்படுத்தலாம். [மேலும் அறிக](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "பல பக்கங்களுக்குத் திசைதிருப்புவதைத் தவிர்க்கவும்"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "பக்க ஆதாரங்களின் அளவையும் எண்ணிக்கைக்கான பட்ஜெட்களையும் அமைக்க budget.json கோப்பை சேர்க்கவும். [மேலும் அறிக](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 கோரிக்கை • {byteCount, number, bytes} KB}other{# கோரிக்கைகள் • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "கோரிக்கை எண்ணிக்கைகளைக் குறைவாகவும் பரிமாற்ற அளவுகளை சிறியதாகவும் வைத்திருங்கள்"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "தேடல் முடிவுகளில் எந்த URLலைக் காண்பிக்க வேண்டும் என்பதை ’முன்னுரிமை இணைப்புகள்’ பரிந்துரைக்கும். [மேலும் அறிக](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "பல முரண்படும் URLகள் ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "வேறொரு டொமைனைச் சுட்டுகிறது ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "தவறான URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "வேறொரு `hreflang` இருப்பிடத்தைச் சுட்டுகிறது ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "தொடர்புடைய URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "உள்ளடக்கத்திற்குப் பொருத்தமான பக்கத்திற்குப் பதிலாக டொமைனின் மூல URLலை (முகப்புப்பக்கம்) குறிப்பிடுகிறது"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "ஆவணத்தில் செல்லுபடியாகும் `rel=canonical` இல்லை"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "ஆவணத்தில் செல்லுபடியாகும்`rel=canonical` உள்ளது"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12pxக்குக் குறைவான எழுத்துரு அளவுகள் படிப்பதற்கு மிக சிறியவை, இதனால் மொபைல் பயனாளர்கள் உரையைப் படிக்க, ”அளவை மாற்ற பின்ச் செய்தல்” அம்சத்தைப் பயன்படுத்த வேண்டியிருக்கும். எனவே பக்கத்தின் 60% அதிகமான உரைக்கு 12px அல்லது அதற்கு அதிகமான எழுத்துரு அளவை அமைக்க முயலவும். [மேலும் அறிக](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} தெளிவான உரை"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "மொபைல் திரைகளுக்கேற்ப காட்சிப் பகுதி மேலதிகத் தகவல் மேம்படுத்தப்படாததால் உரையைச் சரியாகப் படிக்க முடியவில்லை."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} உரை மிகவும் சிறியது ({decimalProportionVisited, number, extendedPercent} மாதிரியின் அடிப்படையில்)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "ஆவணத்தில் தெளிவான எழுத்துரு அளவுகள் பயன்படுத்தப்படவில்லை"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "ஆவணத்தில் தெளிவான எழுத்துரு அளவுகள் பயன்படுத்தப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang இணைப்புகளானவை குறிப்பிட்ட ஒரு மொழியிலான அல்லது பகுதிக்கான தேடல் முடிவுகளில், ஒரு பக்கத்தின் எந்தப் பதிப்பைப் பட்டியலிட வேண்டும் என்பதைத் தேடல் இன்ஜின்களுக்கு சொல்கின்றன. [மேலும் அறிக](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "ஆவணத்தில் செல்லுபடியாகும் `hreflang` இல்லை"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "ஆவணத்தில் செல்லுபடியாகும்`hreflang` உள்ளது"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "வெற்றியடையாத HTTP நிலைக் குறியீடுகள் உள்ள பக்கங்கள் சரியாக அட்டவணைப்படுத்தப்படாமல் போகலாம். [மேலும் அறிக](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "பக்கத்தில் வெற்றியடையாத HTTP நிலைக் குறியீடு உள்ளது"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "பக்கத்தில் வெற்றிகரமான HTTP நிலைக் குறியீடு உள்ளது"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "தேடல் இன்ஜின்களுக்கு உங்கள் பக்கங்களை உருட்டுவதற்கான அனுமதி இல்லையென்றால் அவற்றால் உங்கள் பக்கங்களைத் தேடல் முடிவுகளில் சேர்க்க முடியாது. [மேலும் அறிக](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "பக்கம் அட்டவணைப்படுத்தப்படுவதிலிருந்து தடுக்கப்பட்டுள்ளது"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "பக்கம் அட்டவணைப்படுத்தப்படுவதிலிருந்து தடுக்கப்படவில்லை"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "தேடல் இன்ஜின்கள் உங்கள் உள்ளடக்கத்தைப் புரிந்துகொள்ள இணைப்புக்கான விளக்க உரை உதவும். [மேலும் அறிக](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 இணைப்பு உள்ளது}other{# இணைப்புகள் உள்ளன}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "இணைப்புகளுக்கு விளக்க உரை இல்லை"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "இணைப்புகளுக்கு விளக்க உரை உள்ளது"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "கட்டமைந்த தரவை சரிபார்க்க [கட்டமைந்த தரவு சோதனைக் கருவியையும்](https://search.google.com/structured-data/testing-tool/) [கட்டமைந்த தரவு லிண்டரையும்](http://linter.structured-data.org/) இயக்கவும். [மேலும் அறிக](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "கட்டமைந்த தரவு செல்லுபடியாகிறது"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "பக்கத்தின் உள்ளடக்கத்தைத் தெளிவாக சுருக்கி விளக்குவதற்கு, மீவிளக்கங்களைத் தேடல் முடிவுகளில் சேர்க்கலாம். [மேலும் அறிக](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "விளக்க உரை காலியாக உள்ளது."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "ஆவணத்தில் மீவிளக்கம் இல்லை"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "ஆவணத்தில் மீவிளக்கம் உள்ளது"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "தேடல் இன்ஜின்களால் செருகுநிரல் உள்ளடக்கத்தை அட்டவணைப்படுத்த முடியாது, செருகுநிரல்களைப் பல சாதனங்கள் கட்டுப்படுத்தும் அல்லது ஆதரிக்காது. [மேலும் அறிக](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "ஆவணத்தில் செருகுநிரல்கள் உள்ளன"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "ஆவணத்தில் செருகுநிரல்கள் தவிர்க்கப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "உங்கள் robots.txt கோப்பு தவறான வடிவமைப்பில் இருந்தால் உங்கள் இணையதளத்தை எப்படி உலாவ அல்லது அட்டவணைப்படுத்த விரும்புகிறீர்கள் என்பதை crawlers மென்பொருட்களால் புரிந்துகொள்ள முடியாமல் போகக்கூடும். [மேலும் அறிக](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txtக்கான கோரிக்கை இந்த HTTP நிலையைப் பதிலாக அனுப்பியுள்ளது: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 பிழை உள்ளது}other{# பிழைகள் உள்ளன}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouseஸால் robots.txt கோப்பைப் பதிவிறக்க முடியவில்லை"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt செல்லுபடியாகவில்லை"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt செல்லுபடியாகிறது"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "பட்டன்கள், இணைப்புகள் போன்ற எதிர்வினையாற்றும் உறுப்புகள் போதுமான அளவு பெரிதாகவும் (48x48px) அவற்றைச் சுற்றி போதுமான இடத்துடனும் இருக்க வேண்டும், இதனால் அவற்றைப் பிற உறுப்புகளின் குறுக்கீடு இல்லாமல் எளிதாகத் தட்டலாம். [மேலும் அறிக](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} தட்டுவதற்கான இலக்குகள் பொருத்தமான அளவில் இருக்கின்றன"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "மொபைல் திரைகளுக்கேற்ப காட்சிப் பகுதி மேலதிகத் தகவல் மேம்படுத்தப்படாததால் தட்டுவதற்கான இலக்குகள் மிகச் சிறிதாக உள்ளன"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "தட்டுவதற்கான இலக்குகள் சரியாக அளவிடப்படவில்லை"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "குறுக்கிடும் இலக்கு"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "தட்டுவதற்கான இலக்கு"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "தட்டுவதற்கான இலக்குகள் சரியாக அளவிடப்பட்டுள்ளன"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "சேவைச் செயலாக்கி என்பது ஆஃப்லைனில் பணிபுரிவது, முகப்புத்திரையில் சேர்ப்பது, புஷ் அறிவிப்புகள் போன்ற நவீன இணைய ஆப்ஸின் பல்வேறு அம்சங்களை உங்கள் ஆப்ஸ் பயன்படுத்த அனுமதிக்கும் தொழில்நுட்பமாகும். [மேலும் அறிக](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "சேவைச் செயலாக்கி மூலம் இந்தப் பக்கம் கட்டுப்படுத்தப்படுகிறது, இருப்பினும் சரியான JSON ஆக மெனிஃபெஸ்ட்டைப் பாகுபடுத்த முடியாத காரணத்தால் `start_url` கண்டறியப்படவில்லை"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "இந்தப் பக்கம் சேவைச் செயலாக்கி மூலம் கட்டுப்படுத்தப்படுகிறது, இருப்பினும் `start_url` ({startUrl}) சேவைச் செயாலாக்கியின் நோக்கத்தில் ({scopeUrl}) இல்லை"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "இந்தப் பக்கம் சேவைச் செயலாக்கி மூலம் கட்டுப்படுத்தப்படுகிறது, இருப்பினும் மெனிஃபெஸ்ட் எதுவும் பெறப்படவில்லை என்பதால் `start_url` கண்டறியப்படவில்லை."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "இந்த இணையதளத்தில் ஒன்றோ அதற்கு மேற்பட்ட சேவைச் செயலாக்கிகளோ உள்ளன, இருப்பினும் இந்தப் பக்கம் ({pageUrl}) நோக்கத்தில் இல்லை."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "பக்கம், `start_url` போன்றவற்றைக் கட்டுப்படுத்துவதற்கான சேவைச் செயலாக்கி பதிவு செய்யப்படவில்லை"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "பக்கம், `start_url` போன்றவற்றைக் கட்டுப்படுத்தும் சேவைச் செயலாக்கியைப் பதிவுசெய்யும்."
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "தங்களின் முகப்புத் திரைகளில் இருந்து உங்களின் ஆப்ஸைப் பயனர்கள் தொடங்கும் போது உயர்தர அனுபவத்தை அவர்கள் பெறுவதை தீம் வண்ணம் அமைக்கப்பட்ட ஸ்பிளாஷ் திரை உறுதிப்படுத்தும். [மேலும் அறிக](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "பிரத்யேக ஸ்பிளாஷ் திரைக்கு உள்ளமைக்கப்படவில்லை"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "பிரத்யேக ஸ்பிளாஷ் திரைக்கு உள்ளமைக்கப்பட்டது"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "உங்களின் தளத்திற்குப் பொருந்தும் வகையில் உலாவி முகவரிப் பட்டியை வண்ணமிட முடியும். [மேலும் அறிக](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "முகவரிப் பட்டிக்கான தீம் வண்ணத்தை அமைக்க முடியவில்லை."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "முகவரிப் பட்டிக்கான தீம் வண்ணத்தை அமைக்கும்."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "முக்கியத் தொடரிழையில் தடுப்பதற்குச் செலவிட்ட நேரம்"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "மூன்றாம் தரப்பு"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "மூன்றாம் தரப்புக் குறியீடானது ஏற்றுதல் செயல்திறனைக் குறிப்பிடத்தக்க வகையில் பாதிக்கக்கூடும். தேவையற்ற மூன்றாம் தரப்பு சேவை வழங்குநர்களின் எண்ணிக்கையைக் குறைத்துக் கொள்ளவும். மேலும் உங்கள் பக்கத்தின் முதன்மை விவரங்களை ஏற்றியபிறகு மூன்றாம் தரப்புக் குறியீட்டை ஏற்ற முயலவும். [மேலும் அறிக](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "{timeInMs, number, milliseconds} msக்கான முக்கியத் தொடரிழையை மூன்றாம் தரப்புக் குறியீடு தடுத்துள்ளது"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "மூன்றாம் தரப்புக் குறியீட்டின் பாதிப்பைக் குறைக்கவும்"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "மூன்றாம் தரப்பு உபயோகம்"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "'முதல் பைட்டின் நேரம்' என்பது உங்கள் சேவையகம் ஒரு பதிலை அனுப்பும் நேரத்தை சுட்டிக்காட்டுகிறது. [மேலும் அறிக](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "மூல ஆவணம் எடுத்துக் கொண்ட நேரம்: {timeInMs, number, milliseconds} மி.வி."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "சேவையக எதிர்வினை நேரங்களைக் குறைக்கவும் (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "சேவையகம் எதிர்வினையாற்றும் நேரங்கள் குறைவாக உள்ளன (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "கால அளவு"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "தொடக்க நேரம்"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "வகை"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "முக்கியமான பயனர் அனுபவங்களின்போது உங்கள் ஆப்ஸின் நிகழ்நேர செயல்திறனை அளவிட உங்கள் ஆப்ஸில் User Timing APIயைப் பயன்படுத்தவும். [மேலும் அறிக](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 பயனர் நேரம்}other{# பயனர் நேரங்கள்}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "பயனர் நேரக் குறிப்புகளும் அளவீடுகளும்"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "{securityOrigin}க்கான <link> முன்னிணைப்பு கண்டறியப்பட்டது, ஆனால் அது உலாவியால் பயன்படுத்தப்படவில்லை. `crossorigin` பண்புக்கூறை முறையாகப் பயன்படுத்துகிறீர்களா என்று சரிபார்க்கவும்."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "முக்கிய மூன்றாம் தரப்பு டொமைன்களுடன் விரைவான இணைப்புகளை ஏற்படுத்த `preconnect` அல்லது `dns-prefetch` ஆதாரக் குறிப்புகளைச் சேர்க்கலாம். [மேலும் அறிக](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "தேவைப்படும் டொமைன் பெயர்களுக்கு முன்கூட்டியே இணைப்பு வழங்கவும்"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "\"{preloadURL}\"க்கான <link> முன்னிணைப்பு கண்டறியப்பட்டது, ஆனால் உலாவியால் அது பயன்படுத்தப்படவில்லை. `crossorigin` பண்புக்கூறை முறையாகப் பயன்படுத்துகிறீர்களா என்று சரிபார்க்கவும்."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "பக்கம் ஏற்றப்படும்போது தற்சமயம் பின்னர் கோரிக்கையளிக்கப்படும் ஆதாரங்களை முன்னுரிமை அளிக்க `<link rel=preload>`ஐப் பயன்படுத்தவும். [மேலும் அறிக](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "முக்கியக் கோரிக்கைகளை முன்கூட்டியே ஏற்றவும்"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "மொபைல் திரைகளுக்கு ஏற்றவாறு உங்களின் ஆப்ஸை மேம்படுத்தும் வகையில் `<meta name=\"viewport\">` குறிச்சொல்லைச் சேர்க்கவும். [மேலும் அறிக](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "`<meta name=\"viewport\">` குறிச்சொல் எதுவும் இல்லை"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "`width` அல்லது `initial-scale` உடன் கூடிய `<meta name=\"viewport\">` குறிச்சொல் அமைக்கப்படவில்லை"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "`width` அல்லது `initial-scale` உடன் `<meta name=\"viewport\">` குறிச்சொல் அமைக்கப்பட்டுள்ளது"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "JavaScript முடக்கத்தில் உள்ள போது சில உள்ளடக்கத்தை உங்கள் ஆப்ஸ் காட்ட வேண்டும். அது ஆப்ஸைப் பயன்படுத்த JavaScript தேவை என்ற எச்சரிக்கைச் செய்தியாக இருந்தாலும் பரவாயில்லை. [மேலும் அறிக](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "ஸ்கிரிப்ட்கள் இல்லாத போது பக்கம் சில உள்ளடக்கத்தை ரெண்டர் செய்ய வேண்டும்."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "JavaScript முடக்கத்தில் உள்ள போது ஃபால்பேக் உள்ளடக்கத்தை வழங்காது"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "JavaScript முடக்கத்தில் உள்ள போது சில உள்ளடக்கம் காட்டப்படும்"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "நவீன இணைய ஆப்ஸை உருவாக்குகிறீர்கள் எனில் ஆஃப்லைனில் உங்கள் ஆப்ஸ் செயல்படும் வகையில் சேவைச் செயலாக்கியைப் பயன்படுத்தும்படி பரிந்துரைக்கிறோம். [மேலும் அறிக](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "ஆஃப்லைனில் உள்ள போது 200 என்ற HTTP நிலைக் குறியீட்டுடன் தற்போதைய பக்கம் விரைவாகப் பதிலளிக்கவில்லை"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "ஆஃப்லைனில் உள்ள போது 200 என்ற HTTP நிலைக் குறியீட்டுடன் தற்போதைய பக்கம் விரைவாகப் பதிலளிக்கும்"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "\"{final}\"க்கு உங்களின் சோதனை URL ({requested}) திசைதிருப்பப்பட்டதால் இந்தப் பக்கத்தை ஆஃப்லைனில் ஏற்ற முடியாமல் போகக்கூடும். இரண்டாவது URLஐ நேரடியாகச் சோதித்துப் பார்க்கவும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "இந்த வாய்ப்புகள் உங்கள் ஆப்ஸில் உள்ள ARIAயின் ஆப்ஸை மேம்படுத்தும், இது ஸ்க்ரீன் ரீடர் போன்ற உதவிகரமான தொழில்நுட்பத்தைப் பயன்படுத்தும் பயனர்களின் அனுபவத்தை மேம்படுத்தக்கூடும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "இவை ஆடியோவுக்கும் வீடியோவுக்கும் மாற்று உள்ளடக்கத்தை வழங்குவதற்கான வாய்ப்புகளாகும். இது செவித்திறன் அல்லது பார்வைக் குறைபாடுள்ள பயனர்களுக்கான அனுபவத்தை மேம்படுத்தக்கூடும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "ஆடியோ & வீடியோ"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "இவை பொதுவான அணுகல்தன்மைக்கான சிறந்த நடைமுறைகளைத் தனிப்படுத்துகின்றன."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "சிறந்த நடைமுறைகள்"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "இந்த சரிபார்ப்புகள் [உங்கள் இணைய ஆப்ஸின் அணுகல்தன்மையை மேம்படுத்துவதற்கான](https://developers.google.com/web/fundamentals/accessibility) வாய்ப்புகளைத் தனிப்படுத்திக் காட்டுகின்றன. அணுகல்தன்மை சிக்கல்களில் சிலவற்றை மட்டுமே தானாகக் கண்டறிய முடியும் என்பதால் நேரடி பரிசோதனையையும் செய்ய ஊக்குவிக்கிறோம்."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "தானியங்கி சோதனைக் கருவியால் சோதிக்க முடியாத பகுதிகளை இவை சோதிக்கும். எங்கள் வழிகாட்டியில் [அணுகல்தன்மை மதிப்பாய்வை நடத்துவதைப்](https://developers.google.com/web/fundamentals/accessibility/how-to-review) பற்றி மேலும் தெரிந்துகொள்ளலாம்."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "அணுகல்தன்மை"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "இவை உங்கள் உள்ளடக்கத்தின் நம்பகத்தன்மையை மேம்படுத்துவதற்கான வாய்ப்புகளாகும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "ஒளி மாறுபாடு"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "இந்த வாய்ப்புகள், பல்வேறு மொழிப் பயனர்கள் உங்கள் உள்ளடக்கத்தைப் புரிந்துகொள்வதற்கான வாய்ப்பினை மேம்படுத்தும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "சர்வதேசமயமாக்குதல் & உள்ளூர்மயமாக்குதல்"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "இந்த வாய்ப்புகள் உங்கள் ஆப்ஸின் கட்டுப்பாடுகளின் பொருள்விளக்கத்தை மேம்படுத்தும். இது ஸ்க்ரீன் ரீடர் போன்ற உதவிகரமான தொழில்நுட்பத்தைப் பயன்படுத்தும் பயனர்களின் அனுபவத்தை மேம்படுத்தக்கூடும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "பெயர்கள் & லேபிள்கள்"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "இவை உங்கள் ஆப்ஸில் கீபோர்டு நேவிகேஷனை மேம்படுத்துவதற்கான வாய்ப்புகளாகும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "நேவிகேஷன்"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "இவை ஸ்க்ரீன் ரீடர் போன்ற உதவிகரமான தொழில்நுட்பத்தைப் பயன்படுத்தி அட்டவணை அல்லது பட்டியல் தரவைப் படிக்கும் அனுபவத்தை மேம்படுத்துவதற்கான வாய்ப்புகளாகும்."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "டேபிள்கள் & பட்டியல்கள்"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "சிறந்த நடைமுறைகள்"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "செயல்திறன் பட்ஜெட்கள் உங்கள் தளத்தின் செயல்திறனுக்கான தர நிலைகளை அமைக்கும்."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "பட்ஜெட்கள்"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "உங்கள் ஆப்ஸின் செயல்திறன் பற்றிய மேலும் சில தகவல்கள். இந்த மதிப்புகளானது செயல்திறனின் ஸ்கோரை [நேரடியாகப் பாதிக்காது](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "பகுப்பாய்வு"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "திரையில் பிக்சல்கள் எவ்வளவு விரைவாக ரென்டரிங் செய்யப்படுகின்றன என்பது செயல்திறனின் மிக முக்கிய அம்சமாகும். முக்கிய அளவீடுகள்: 'உள்ளடக்கமுள்ள முதல் தோற்றம்', 'அர்த்தமுள்ள முதல் தோற்றம்'"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "முதல் தோற்ற மேம்பாடுகள்"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "இந்தப் பரிந்துரைகள் உங்கள் பக்கத்தை வேகமாக ஏற்ற உதவும். அவை செயல்திறன் ஸ்கோரை [நேரடியாகப் பாதிக்காது](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "பரிந்துரைகள்"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "அளவீடுகள்"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "ஒட்டுமொத்தமாகப் பக்கம் ஏற்றப்படும் அனுபவத்தை மேம்படுத்தவும், இதனால் பக்கம் விரைவாக எதிர்வினையாற்றும், அத்துடன் முடிந்தளவு விரைவாகப் பயன்படுத்தத் தயாராக இருக்கும். முக்கிய அளவீடுகள்: 'எதிர்வினை நேரம்', 'வேக அட்டவணை'"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "ஒட்டுமொத்த மேம்பாடுகள்"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "இணையச் செயல்திறன்"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "இந்தச் சரிபார்ப்புகள் நவீன இணைய ஆப்ஸின் அம்சங்களை மதிப்பிடும். [மேலும் அறிக](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "பேஸ்லைன் [PWA சரிபார்ப்புப் பட்டியலுக்கு ](https://developers.google.com/web/progressive-web-apps/checklist) இந்தச் சரிபார்ப்புகள் தேவை, இருப்பினும் இவற்றை Lighthouse தானாகச் சரிபார்ப்பதில்லை. அவை உங்களின் ஸ்கோரில் பாதிப்பை ஏற்படுத்தாது, இருப்பினும் நீங்களாகவே அவற்றைச் சரிபார்ப்பது முக்கியமாகும்."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "நவீன இணைய ஆப்ஸ்"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "விரைவானது, நம்பகமானது"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "நிறுவக்கூடியவை"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA மேம்படுத்தப்பட்டுள்ளது"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "தேடல் இன்ஜின் முடிவுகளில் ரேங்கிங்கிற்காக உங்கள் பக்கம் உகந்ததாக்கப்பட்டுள்ளதை இந்தச் சரிபார்ப்புகள் உறுதிசெய்யும். உங்கள் தேடல் ரேங்கிங்கைப் பாதிக்கக்கூடிய, Lighthouse சரிபார்க்காத கூடுதல் காரணிகள் உள்ளன. [மேலும் அறிக](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "மேலும் சில சிறந்த SEO நடைமுறைகளைச் சோதனை செய்ய, உங்கள் தளத்தில் இந்தக் கூடுதல் வேலிடேட்டர்களை இயக்கவும்."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "ஆப்ஸின் உள்ளடக்கத்தை கிராலர்கள் நன்கு புரிந்துகொள்ள வசதியாக HTMLலைப் பொருத்தமாக வடிவமைக்கவும்."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "உள்ளடக்கம் தொடர்பான சிறந்த நடைமுறைகள்"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "தேடல் முடிவுகளில் தோன்ற உங்கள் ஆப்ஸிற்கான அணுகல் கிராலர்களுக்குத் தேவை."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "கிராலிங் & அட்டவணைப்படுத்துதல்"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "பக்கங்களின் உள்ளடக்கத்தை பயனர்கள் பின்ச் செய்தோ பெரிதாக்கியோ படிக்க வேண்டிய அவசியம் ஏற்படாதவாறு உங்கள் பக்கங்கள் மொபைலுக்கு ஏற்றவையாக இருக்க வேண்டும். [மேலும் அறிக](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "மொபைலுக்கேற்றது"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "தற்காலிக நினைவக TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "இடம்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "பெயர்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "கோரிக்கைகள்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "ஆதார வகை"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "அளவு"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "செலவிட்ட நேரம்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "பரிமாற்ற அளவு"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "சேமிக்கப்படக்கூடியது"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "சேமிக்கப்படக்கூடியது"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "சேமிக்கக்கூடிய அளவு: {wastedBytes, number, bytes} கி.பை."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "சேமிக்கக்கூடிய நேரம்: {wastedMs, number, milliseconds} மி.வி."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "ஆவணம்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "எழுத்துரு"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "படம்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "மீடியா"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} மி.வி."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "மற்றவை"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "ஸ்கிரிப்ட்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} வி."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "ஸ்டைல்ஷீட்"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "மூன்றாம் தரப்பு"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "மொத்தம்"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "உங்கள் பக்கம் ஏற்றப்படுகையில் டிரேஸைப் பதிவுசெய்யும்போது ஏதோ தவறாகிவிட்டது. Lighthouseஸை மீண்டும் இயக்கவும். ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "முதல் பிழைதிருத்தும் நெறிமுறை இணைப்பிற்கான நேரமுடிவு காத்திருப்பு."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "பக்கம் ஏற்றப்பட்டபோது ஸ்க்ரீன்ஷாட்கள் எதையும் Chrome சேகரிக்கவில்லை. பக்கத்தில் ஏதேனும் உள்ளடக்கம் காண்பிக்கப்படுவதை உறுதிப்படுத்திக் கொண்டு Lighthouseஸை மீண்டும் இயக்கவும். ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "வழங்கப்பட்டுள்ள டொமைனை DNS சேவையகங்களால் அடையாளம் காண முடியவில்லை."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "தேவைப்படும் {artifactName} சேகரிப்பானில் பிழையொன்று ஏற்பட்டது: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Chrome அகப் பிழை நேர்ந்தது. Chromeமை மீண்டும் தொடங்கி, Lighthouseஸை மீண்டும் இயக்கவும்."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "தேவைப்படும் {artifactName} சேகரிப்பான் இயங்கவில்லை."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "நீங்கள் கோரிய பக்கத்தை Lighthouseஸால் முழுமையாக ஏற்ற முடியவில்லை. நீங்கள் சரியான URLலைச் சோதிப்பதையும் அனைத்துக் கோரிக்கைகளுக்கும் சேவையகம் சரியாகப் பதிலளிப்பதையும் உறுதிசெய்யவும்."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "பக்கம் பதிலளிப்பதை நிறுத்தியதால் நீங்கள் கோரிய URLலை Lighthouseஸால் முழுமையாக ஏற்ற முடியவில்லை."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "நீங்கள் வழங்கியுள்ள URLலில் செல்லுபடியாகும் பாதுகாப்பு சான்றிதழ்கள் இல்லை. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "பக்கத்தை ஏற்றுவதை இடைச்செருகல் திரையொன்றின் மூலம் Chrome தடுத்துவிட்டது. நீங்கள் சரியான URLலைப் பரிசோதிப்பதையும் அனைத்துக் கோரிக்கைகளுக்கும் சேவையகம் முறையாக பதிலளிப்பதையும் உறுதிசெய்து கொள்ளவும்."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "நீங்கள் கோரிய பக்கத்தை Lighthouseஸால் முழுமையாக ஏற்ற முடியவில்லை. நீங்கள் சரியான URLலைப் பரிசோதிப்பதையும் அனைத்துக் கோரிக்கைகளுக்கும் சேவையகம் முறையாக பதிலளிப்பதையும் உறுதிசெய்து கொள்ளவும். (விவரங்கள்: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "நீங்கள் கோரிய பக்கத்தை Lighthouseஸால் முழுமையாக ஏற்ற முடியவில்லை. நீங்கள் சரியான URLலைப் பரிசோதிப்பதையும் அனைத்துக் கோரிக்கைகளுக்கும் சேவையகம் முறையாக பதிலளிப்பதையும் உறுதிசெய்து கொள்ளவும். (நிலைக் குறியீடு: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "உங்கள் பக்கம் ஏற்றப்பட நீண்ட நேரம் எடுத்துக்கொண்டது. பக்கம் ஏற்றப்படும் நேரத்தைக் குறைக்க அறிக்கையிலுள்ள வாய்ப்புகளைப் பின்பற்றி Lighthouseஸை மீண்டும் இயக்கவும். ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools நெறிமுறைக்காகக் காத்திருக்கும் ஒதுக்கப்பட்ட நேரத்தை மீறிவிட்டது. (முறை:{protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "ஒதுக்கப்பட்ட நேரத்தை ஆதார உள்ளடக்கத்தைப் பெறுவதற்கான நேரம் மீறிவிட்டது"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "நீங்கள் அளித்துள்ள URL செல்லாததெனத் தோன்றுகிறது."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "தணிக்கைகளைக் காட்டு"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "துவக்க நெட்வொர்க் கோரிக்கை"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "முக்கியக் கோரிக்கைத் தடத்தின் அதிகபட்சத் தாமதம்:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "பிழை!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "அறிக்கைப் பிழை: தணிக்கைத் தகவல் இல்லை"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "ஆய்வகத் தரவு"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "மாதிரியாக உருவாக்கப்பட்ட மொபைல் நெட்வொர்க்கில் தற்போதைய பக்கத்திற்கான [Lighthouse](https://developers.google.com/web/tools/lighthouse/) பகுப்பாய்வு. மதிப்புகள் தோராயமானவை, மாறுபடக்கூடியவை."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "கைமுறையாகச் சரிபார்க்க வேண்டிய கூடுதல் விஷயங்கள்"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "பொருந்தாதது"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "பரிந்துரை"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "தோராயமான சேமிப்பு"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "தேர்ச்சி பெற்ற தணிக்கைகள்"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "துணுக்கைச் சுருக்கு"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "துணுக்கை விரி"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "மூன்றாம் தரப்பு ஆதாரங்களைக் காட்டு"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Lighthouseஸின் இந்த இயக்கத்தைச் சில சிக்கல்கள் பாதிக்கின்றன:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "மதிப்புகள் தோராயமானவை, மாறுபடக்கூடியவை. [இந்த அளவீடுகளின் அடிப்படையில் மட்டுமே](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) செயல்திறன் ஸ்கோர் கணக்கிடப்படும்."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "தணிக்கைகளில் தேர்ச்சிபெற்றவை, ஆனால் எச்சரிக்கைகள் உள்ளவை"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "எச்சரிக்கைகள்: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "உங்கள் GIFஃபை HTML5 வீடியோவாக உட்பொதிந்து கிடைக்கச் செய்யும் சேவையில் பதிவேற்ற முயலுங்கள்."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "[lazy-load WordPress செருகுநிரலை](https://wordpress.org/plugins/search/lazy+load/) நிறுவி திரைக்கு வெளியிலுள்ள படங்களைத் தேவையான போது ஏற்றும் திறனைப் பெறலாம் அல்லது அந்தத் திறன் கொண்ட தீமிற்கு மாறலாம். [AMP செருகுநிரலையும்](https://wordpress.org/plugins/amp/) பயன்படுத்திப் பார்க்கவும்."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[முக்கியமான சொத்துகளை முன்னிலைப்படுத்தவோ](https://wordpress.org/plugins/search/critical+css/) [முக்கியத்துவம் குறைவான ஆதாரங்களைத் தவிர்க்கவோ](https://wordpress.org/plugins/search/defer+css+javascript/) உங்களுக்கு உதவக்கூடிய பல WordPress செருகுநிரல்கள் உள்ளன. இந்த செருகுநிரல்கள் வழங்கும் மேம்படுத்துதல்கள் உங்கள் தீமிலோ செருகுநிரலிலோ உள்ள அம்சத்தைப் பாதிக்கலாம். அதனால் நீங்கள் குறியீட்டில் சில மாற்றங்களை செய்ய வேண்டியிருக்கும்."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "தீம்கள், செருகுநிரல்கள், சேவையக விவரக்குறிப்புகள் அனைத்தும் சேவையகத்தின் வேகத்தை நிர்ணயிக்கும். மேலும் மேம்படுத்தப்பட்ட தீமைக் கண்டறிந்து, மேம்படுத்தும் செருகுநிரலைக் கவனமாகத் தேர்ந்தெடுத்து மற்றும்/அல்லது சேவையகத்தை மேம்படுத்தவும்."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "இடுகைப் பட்டியல்களில் முக்கியமான பகுதியை மட்டும் காட்டலாம் (உதாரணமாக மேலும் என்ற குறிச்சொல்லுடன்), பக்கத்தில் இடுகைகளின் எண்ணிக்கையைக் குறைக்கலாம், ஒரு பெரிய இடுகையைப் பல சின்ன பக்கங்களாகப் பிரிக்கலாம் அல்லது தேவையுள்ள போது மட்டும் கருத்துகளைச் செருகுநிரல்கள் மூலம் ஏற்றலாம்."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "பல [WordPress செருகுநிரல்கள்](https://wordpress.org/plugins/search/minify+css/) உங்கள் இணையதளத்தில் உள்ள ஸ்டைல்களை சிறிதாக்கியும், சுருக்கியும், ஒன்றிணைத்தும் அதை வேகப்படுத்த முடியும். முடிந்தால், ஸ்கிரிப்ட்களை முன்னதாகவே சிறிதாக்க பதிப்பு முறைமையைப் பயன்படுத்திப் பார்க்கலாம்."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "பல [WordPress செருகுநிரல்கள்](https://wordpress.org/plugins/search/minify+javascript/) உங்கள் இணையதளத்திலுள்ள ஸ்கிரிப்ட்களை சிறிதாக்கியும், சுருக்கியும், ஒன்றிணைத்தும் அதை வேகப்படுத்த முடியும். முடிந்தால், ஸ்கிரிப்ட்களை முன்னதாகவே சிறிதாக்க பதிப்பு முறைமையைப் பயன்படுத்திப் பார்க்கலாம்."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "உங்கள் பக்கத்தில் [WordPress செருகுநிரல்கள்](https://wordpress.org/plugins/) ஏற்றும் பயன்படுத்தப்படாத CSSஸின் எண்ணிக்கையைக் குறைக்கவும் அல்லது மாற்றிப் பார்க்கவும். Chrome DevToolsஸில் [குறியீட்டுக் கவரேஜ் ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) என்பதை இயக்கி தேவையற்ற CSSஸை சேர்க்கும் செருகுநிரல்களைக் கண்டறியவும். ஸ்டைல்ஷீட்டின் URLலில் இதற்குக் காரணமான தீம்/செருகுநிரலைக் கண்டறியலாம். அதிகளவு சிவப்பில் உள்ள குறியீட்டுக் கவரேஜைக் கொண்ட பட்டியலில் பல ஸ்டைல்ஷீட்களைக் கொண்ட செருகுநிரல்களைக் கண்டறியவும். இணையப் பக்கத்தில் பயன்படுத்தும் பட்சத்தில் ஒரு செருகுநிரல் ஒரு ஸ்டைல்ஷீட்டை மட்டுமே வரிசையில் சேர்க்க வேண்டும்."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "உங்கள் பக்கத்தில் [WordPress செருகுநிரல்கள்](https://wordpress.org/plugins/) ஏற்றும் பயன்படுத்தப்படாத JavaScriptகளின் எண்ணிக்கையைக் குறைக்கவும் அல்லது மாற்றிப் பார்க்கவும். Chrome DevToolsஸில் [குறியீட்டுக் கவரேஜ் ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) என்பதை இயக்கி தேவையற்ற JSகளைச் சேர்க்கும் செருகுநிரல்களைக் கண்டறியவும். ஸ்கிரிப்ட்டின் URLலில் இதற்குக் காரணமான தீம்/செருகுநிரலைக் கண்டறியலாம். அதிகளவு சிவப்பில் உள்ள குறியீட்டுக் கவரேஜைக் கொண்ட பட்டியலில் பல ஸ்கிரிப்ட்களைக் கொண்ட செருகுநிரல்களைக் கண்டறியவும். இணையப் பக்கத்தில் பயன்படுத்தும் பட்சத்தில் ஒரு செருகுநிரல் ஒரு ஸ்கிரிப்ட்டை மட்டுமே வரிசையில் சேர்க்க வேண்டும்."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPressஸில் உலாவியின் தற்காலிக சேமிப்பு](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching) பற்றித் தெரிந்துகொள்ளவும்."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "[படங்களை மேம்படுத்தும் WordPress செருகுநிரலைப்](https://wordpress.org/plugins/search/optimize+images/) பயன்படுத்தி உங்கள் படங்களின் தரத்திற்குப் பாதிப்பு ஏற்படாமல் சுருக்கலாம்."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "[மீடியா லைப்ரரி](https://codex.wordpress.org/Media_Library_Screen) மூலம் படத்தை நேரடியாகப் பதிவேற்றி சரியான அளவில் கிடைக்கிறதா என்று உறுதிப்படுத்திக் கொள்ளலாம். பிறகு மேம்படுத்தப்பட்ட அளவுகளில் (சிறப்பாகப் பதிலளிக்கும் புள்ளிகளுக்கும் ஏற்ற அளவுகளில்) படங்கள் பயன்படுத்தப்படுவதை உறுதி செய்ய மீடியா லைப்ரரியிலிருந்தோ பட விட்ஜெட்டைப் பயன்படுத்தியோ படங்களைச் செருகலாம். பயன்படுத்த ஏதுவான அளவுகள் உள்ளபோது மட்டுமே `Full Size` படங்களைப் பயன்படுத்தவும். [மேலும் அறிக](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "இணையச் சேவையக உள்ளமைவில் உரை சுருக்குதலை இயக்கலாம்."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "நீங்கள் பதிவேற்றிய படங்களை மேம்படுத்தப்பட்ட வடிவமைப்புகளுக்குத் தானாக மாற்றும் ஒரு [செருகுநிரலையோ](https://wordpress.org/plugins/search/convert+webp/) சேவையையோ பயன்படுத்தவும்."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/te.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/te.json
new file mode 100644
index 00000000000..9dfa697f0e5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/te.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "యాక్సెస్ కీలతో వినియోగదారులు పేజీలోని నిర్దిష్ట భాగంపై వేగంగా దృష్టి సారించగలరు. సక్రమమైన నావిగేషన్ కోసం, ప్రతి యాక్సెస్ కీ తప్పనిసరిగా విభిన్నంగా ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "'`[accesskey]`' విలువలు విశిష్ఠమైనవి కావు"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` విలువలు ప్రత్యేకమైనవి"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "ప్రతి ARIA `role`, `aria-*` లక్షణాల నిర్ధిష్ట సబ్‌సెట్‌కు మద్దతు ఇస్తుంది. వీటికి సరిపోలకపోతే `aria-*` లక్షణాలను చెల్లనివిగా చేస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "``[aria-*]`` లక్షణాలు వాటి పాత్రలతో సరిపోలలేదు"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "'`[aria-*]`' లక్షణాలు వాటి పాత్రలతో సరిపోలాలి"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "కొన్ని ARIA పాత్రలు మూలకం స్థితిని స్క్రీన్ రీడర్‌లకు వివరించే ఆవశ్యక లక్షణాలను కలిగి ఉన్నాయి. [మరింత తెలుసుకోండి](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "'`[role]`'లలో అవసరమైన అన్ని '`[aria-*]`' లక్షణాలు లేవు"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "'`[role]`'లకు అన్ని అవసరమైన అన్ని '`[aria-*]`' లక్షణాలు ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "కొన్ని ARIA మూలాధార పాత్రలు తప్పనిసరిగా నిర్దిష్ట ఉపాంశ పాత్రల కలయికతో వాటి ఉద్దేశిత యాక్సెసిబిలిటీ ఫంక్షన్‌లు సరిగ్గా అమలయ్యే విధంగా ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "ఉప మూలకాలు నిర్దిష్టమైన '`[role]`'ను కలిగి ఉండాల్సిన ARIA '`[role]`' మూలకాలలో కొన్నింటిని లేదా వేటినీ ఉప మూలకాలు కలిగి ఉండకపోవడంతో సమస్య ఏర్పడింది."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "ఉప మూలకాలు నిర్దిష్టమైన '`[role]`'ను కలిగి ఉండటం అవసరమైన ARIA `[role]` గల మూలకాలు అవసరమైన అన్ని ఉప మూలకాలను కలిగి ఉన్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "కొన్ని ARIA ఉపాంశ పాత్రలు తప్పనిసరిగా నిర్దిష్ట మూలధార పాత్రల కలయికతో వాటి ఉద్దేశిత యాక్సెసిబిలిటీ ఫంక్షన్‌లు సరిగ్గా అమలయ్యే విధంగా ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "``[role]``లు వాటి అవసరమైన మూలాధార మూలకంతో లేవు"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "``[role]``లు వాటికి అవసరమైన మూలాధార మూలకాలలో ఉన్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA పాత్రలు వాటి ఉద్దేశిత యాక్సెసిబిలిటీ ఫంక్షన్‌లను అమలు చేయడానికి తప్పనిసరిగా వాటిలో చెల్లుబాటయ్యే విలువలు ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` విలువలు చెల్లుబాటు అయ్యేవి కావు"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` విలువలు చెల్లుబాటు అయ్యేవి"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "స్క్రీన్ రీడర్‌ల లాంటి సహాయక సాంకేతిక పరిజ్ఞానాలు చెల్లుబాటు కాని విలువలు గల ARIA లక్షణాలను అర్థం చేసుకోలేవు. [మరింత తెలుసుకోండి](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "'`[aria-*]`' లక్షణాలలో చెల్లుబాటయ్యే విలువలు లేవు"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "'`[aria-*]`' లక్షణాలు చెల్లుబాటయ్యే విలువలను కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "స్క్రీన్ రీడర్‌ల లాంటి సహాయక సాంకేతిక పరిజ్ఞానాలు చెల్లుబాటు కాని పేర్లు గల ARIA లక్షణాలను అర్థం చేసుకోలేవు. [మరింత తెలుసుకోండి](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "``[aria-*]`` లక్షణాలు చెల్లుబాటు అయ్యేవి కావు లేదా అక్షరదోషాలు ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "``[aria-*]`` లక్షణాలు చెల్లుబాటు అయ్యేవి, అక్షరదోషాలేవీ లేవు"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "శీర్షికల సహాయంతో ఆడియో మూలకాలలో ఏమి ఉన్నది చెవిటి లేదా వినికిడి సమస్య ఉన్న వినియోగదారులు అర్థం చేసుకోగలరు, దీని ద్వారా ఎవరు మాట్లాడుతున్నారు, ఏమి చెబుతున్నారు లాంటి కీలకమైన సమాచారం, ఇతర సంభాషణేతర సమాచారం అందించబడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "'`<audio>`' మూలకాలలో '`[kind=\"captions\"]`'తో '`<track>`' మూలకం లేదు."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "'`<audio>`' మూలకాలు '`[kind=\"captions\"]`'తో '`<track>`' మూలకం కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "విఫలం అవుతున్న మూలకాలు"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "ఒక బటన్‌కు యాక్సెస్ చేయదగిన పేరు లేనప్పుడు, స్క్రీన్ రీడర్‌లు దానిని \"బటన్\"గా ప్రకటిస్తాయి, తద్వారా స్క్రీన్ రీడర్‌లపై ఆధారపడే వినియోగదారులకు నిరుపయోగమైనవిగా చేస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "బటన్‌లకు యాక్సెస్‌కి తగిన పేరు లేదు"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "బటన్‌లు యాక్సెస్ చేయదగిన పేరును కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "పునరావృత కంటెంట్‌ను దాటవేయడానికి మార్గాలను జోడించడం వలన కీబోర్డ్ వినియోగదారులు పేజీలో మరింత సమర్థవంతంగా నావిగేట్ చేయగలరు. [మరింత తెలుసుకోండి](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "పేజీలో ముఖ్యశీర్షిక, దాటివేత లింక్ లేదా ల్యాండ్‌మార్క్ ప్రాంతం లేవు"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "పేజీలో ముఖ్య శీర్షిక, దాటివేత లింక్ లేదా ల్యాండ్‌మార్క్ ప్రాంతం ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "తక్కువ వర్ణభేద వచనం- చాలా మంది వినియోగదారులు చదవడానికి కష్టసాధ్యమైనది లేదా అసలు సాధ్యం కానిది. [మరింత తెలుసుకోండి](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "నేపథ్యం, ముందువైపు రంగులు తగినంత వర్ణభేద నిష్పత్తితో లేవు"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "నేపథ్యం మరియు ముందువైపు రంగులు తగినంత వర్ణభేద నిష్పత్తితో ఉంటున్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "నిర్వచన జాబితాలను సరిగ్గా గుర్తు పట్టే విధంగా సెట్ చేయనప్పుడు, స్క్రీన్ రీడర్‌లు అయోమయానికి గురి చేసే లేదా అనిర్దిష్టమైన అవుట్‌పుట్‌ను అందించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "'`<dl>`'లకు సంబంధించి కేవలం సక్రమంగా ఆర్డర్ చేసిన ఏకైక '`<dt>`', '`<dd>`' సమూహాలు, '`<script>`' లేదా '`<template>`' మూలకాలతో ఉండకూడదు."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "'`<dl>`'లలో కేవలం సక్రమంగా ఆర్డర్ చేసిన '`<dt>`', '`<dd>`' సమూహాలు, '`<script>`' లేదా '`<template>`' మూలకాలు ఉన్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "స్క్రీన్ రీడర్‌లు నిర్వచన జాబితా అంశాలను ('`<dt>`', '`<dd>`') సక్రమంగా ప్రకటించడం కోసం వాటిని తప్పనిసరిగా మూలాధార '`<dl>`' మూలకంలో సర్దుబాటు చేయాలి. [మరింత తెలుసుకోండి](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "నిర్వచన జాబితా అంశాలు '`<dl>`' మూలకాలలో సర్దుబాటు చేయబడలేదు"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "నిర్వచన జాబితా అంశాలు '`<dl>`' మూలకాలలో సర్దుబాటు చేయబడ్డాయి"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "శీర్షిక అన్నది స్క్రీన్ రీడర్ వినియోగదారులకు పేజీ గురించి అవగాహన కలుగజేస్తుంది, అలాగే శోధన ఇంజిన్ వినియోగదారులు ఒక పేజీ వారి శోధనకు సంబంధితమైనదో కాదో గుర్తించడానికి చాలా ఎక్కువగా దీనిపై ఆధారపడుతుంటారు. [మరింత తెలుసుకోండి](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "పత్రంలో '`<title>`' మూలకం లేదు"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "పత్రంలో '`<title>`' మూలకం ఉంది"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "సహాయకర సాంకేతిక పరిజ్ఞానాల ద్వారా ఇతర సందర్భాలు విస్మరించబడకుండా నిరోధించడానికి id లక్షణం విలువ ప్రత్యేకంగా ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "పేజీలోని ``[id]`` లక్షణాలు విశిష్ఠమైనవి కావు"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "పేజీలోని ``[id]`` లక్షణాలు విశిష్ఠంగా ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "స్క్రీన్ రీడర్ వినియోగదారులు ఫ్రేమ్‌ల కంటెంట్‌లను వివరించడానికి ఫ్రేమ్ శీర్షికలపై ఆధారపడతారు. [మరింత తెలుసుకోండి](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "'`<frame>`' లేదా '`<iframe>`' మూలకాలకు పేరు అందించలేదు"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "'`<frame>`' లేదా '`<iframe>`' మూలకాలలో శీర్షికలు ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "ఒక పేజీలో భాషా లక్షణాన్ని పేర్కొనకుంటే, స్క్రీన్ రీడర్‌ను సెట్ చేస్తున్నప్పుడు వినియోగదారు ఎంచుకున్న డిఫాల్ట్ భాషలో పేజీ ఉందని స్క్రీన్ రీడర్ భావిస్తుంది. ఒకవేళ ఆ పేజీ డిఫాల్ట్ భాషలో లేకపోతే, ఆ పేజీలోని వచనాన్ని స్క్రీన్ రీడర్ సరిగ్గా చదివి వినిపించలేకపోవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "'`<html>`' మూలకంలో '`[lang]`' మూలకం లేదు"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "'`<html>`' మూలకంలో `[lang]` లక్షణం ఉంది"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "చెల్లుబాటయ్యే [BCP 47 భాష](https://www.w3.org/International/questions/qa-choosing-language-tags#question)ను పేర్కొనడం అనేది, వచనాన్ని సక్రమంగా ప్రకటించడంలో స్క్రీన్ రీడర్‌లకు సహాయపడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "'`<html>`' మూలకంలో దాని '`[lang]`' లక్షణం కోసం చెల్లుబాటయ్యే విలువ లేదు."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "'`<html>`' మూలకంలో దాని '`[lang]`' లక్షణానికి చెల్లుబాటయ్యే విలువ ఉంది"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "సమాచార మూలకాలు సంక్షిప్తమైన, వివరణాత్మక ప్రత్యామ్నాయ వచనాన్ని లక్ష్యంగా చేసుకోవాలి. అలంకార మూలకాలను ఖాళీ alt లక్షణంతో విస్మరించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "చిత్రం మూలకాలలో '`[alt]`' లక్షణాలు ఏవీ లేవు"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "చిత్ర మూలకాలు '`[alt]`' లక్షణాలను కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "ఒక చిత్రం '`<input>`' బటన్‌గా ఉపయోగిస్తున్నప్పుడు, ప్రత్యామ్నాయ వచనం అందించడమనేది బటన్ ప్రయోజనాన్ని అర్థం చేసుకోవడంలో స్క్రీన్ రీడర్ వినియోగదారులకు సహాయం చేస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "'`<input type=\"image\">`' మూలకాలలో '`[alt]`' వచనం లేదు"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "'`<input type=\"image\">`' మూలకాలు '`[alt]`' వచనాన్ని కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "స్క్రీన్ రీడర్‌ల లాంటి సహాయక సాంకేతిక పరిజ్ఞానాల ద్వారా ఫారమ్ నియంత్రణలు సక్రమంగా ప్రకటించబడుతున్నాయని లేబుల్‌లు నిర్ధారిస్తున్నాయి. [మరింత తెలుసుకోండి](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "ఫారమ్ మూలకాలలో అనుబంధిత లేబుల్‌లు లేవు"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "ఫారమ్ మూలకాలు అనుబంధిత లేబుల్‌లను కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "లేఅవుట్ ప్రయోజనాల కోసం ఉపయోగించే పట్టికలో th లాంటి డేటా మూలకాలు లేదా శీర్షిక మూలకాలు లేదా సారంశ లక్షణం ఉండకూడదు, ఎందుకంటే ఇది స్క్రీన్ రీడర్ వినియోగదారులకు గందరగోళమైన అనుభవాన్ని అందించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "ప్రదర్శన సంబంధిత '`<table>`' మూలకాలలో '`<th>`', '`<caption>`' లేదా '`[summary]`' లక్షణాన్ని వినియోగించడం నివారించబడలేదు."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "ప్రదర్శన సంబంధిత '`<table>`' మూలకాలు '`<th>`', '`<caption>`' లేదా `[summary]` లక్షణాన్ని వినియోగించడం నివారిస్తున్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "కనుగొనదగిన, విశిష్ఠమైన, దృష్టి కేంద్రీకరించగలిగిన లింక్ వచనం (అలాగే చిత్రాలను లింక్‌లుగా ఉపయోగించినప్పుడు వాటి ప్రత్యామ్నాయ వచనం) సహాయంతో స్క్రీన్ రీడర్ వినియోగదారులకు నావిగేషన్ అనుభవం మరింత మెరుగవుతుంది. [మరింత తెలుసుకోండి](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "లింక్‌లలో కనుగొనదగిన పేరు లేదు"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "లింక్‌లలో కనుగొనదగిన పేరు ఉంది"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "స్క్రీన్ రీడర్‌లు, జాబితాలను ఒక నిర్దిష్ట రకమైన రీతిలో ప్రకటిస్తాయి. జాబితా నిర్మాణక్రమం సక్రమ రీతిలో ఉందని నిర్ధారించుకుంటే, అది స్క్రీన్ రీడర్ అవుట్‌పుట్‌కు ఉపకరిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "జాబితాలు కేవలం '`<li>`' మూలకాలు, స్క్రిప్ట్ మద్దతు మూలకాలు ('`<script>`', '`<template>`')తో ఉండకూడదు."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "జాబితాలలో కేవలం '`<li>`' మూలకాలు, స్క్రిప్ట్ మద్దతు మూలకాలు (`<script>`, `<template>`) మాత్రమే ఉన్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "జాబితా అంశాలను ('`<li>`') స్క్రీన్ రీడర్‌లు సక్రమంగా ప్రకటించాలంటే, వాటిని మూలాధార అంశం '`<ul>`' లేదా '`<ol>`'లో ఉంచాలి. [మరింత తెలుసుకోండి](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "జాబితా అంశాలు ('`<li>`') అన్నవి '`<ul>`' లేదా '`<ol>`' మూలాధార మూలకాలలో లేవు."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "జాబితా అంశాలు ('`<li>`') అనేవి '`<ul>`' లేదా '`<ol>`' అనే మూలాధార మూలకాలలో భాగంగా ఉంటాయి"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "వినియోగదారులు పేజీ ఆటోమేటిక్‌గా రిఫ్రెష్ కావాలని కోరుకోరు, అలా చేయడం వలన దృష్టి కేంద్రీకరణ తిరిగి పేజీ పైభాగంలోకి వెళ్తుంది. ఇది విసుగు తెప్పించే లేదా అయోమయానికి గురి చేసే అనుభవం అందించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "పత్రం '`<meta http-equiv=\"refresh\">`'ను వినియోగిస్తోంది"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "పత్రంలో '`<meta http-equiv=\"refresh\">`'ను వినియోగించలేదు"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "జూమ్ చేయగల సామర్థ్యం నిలిపివేస్తే, స్క్రీన్ మ్యాగ్నిఫికేషన్‌పై ఆధారపడే తక్కువ కంటిచూపు ఉన్న వినియోగదారులు వెబ్ పేజీ కంటెంట్‌లను సరిగ్గా చూడలేరు. [మరింత తెలుసుకోండి](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "'`[user-scalable=\"no\"]`' అన్నది '`<meta name=\"viewport\">`' మూలకంలో ఉపయోగించబడింది, అలాగే '`[maximum-scale]`' లక్షణం 5 కంటే తక్కువ ఉంది."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "'`[user-scalable=\"no\"]`' అన్నది '`<meta name=\"viewport\">`' మూలకంలో ఉపయోగించలేదు, అలాగే '`[maximum-scale]`' లక్షణం 5 కంటే తక్కువగా లేదు."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "స్క్రీన్ రీడర్‌లు వచనేతర కంటెంట్‌ను అనువదించలేవు. '`<object>`' మూలకాలకు ప్రత్యామ్నాయ వచనాన్ని జోడించడం వలన స్క్రీన్ రీడర్‌లు వాటి అర్థాన్ని వినియోగదారులకు సరిగ్గా అందించగలుగుతాయి. [మరింత తెలుసుకోండి](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "'`<object>`' మూలకాలలో '`[alt]`' వచనం లేదు"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "'`<object>`' మూలకాలు '`[alt]`' వచనాన్ని కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "0 కంటే పెద్ద విలువ విశిష్ఠమైన నావిగేషన్ క్రమాన్ని సూచిస్తుంది. సాంకేతికంగా చెల్లుబాటు అయినప్పటికీ, సహాయక సాంకేతిక పరిజ్ఞానంపై ఆధారపడిన వినియోగదారులకు ఇది తరచూ విసుగు తెప్పించే అనుభవాలను సృష్టిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "కొన్ని మూలకాలు 0 కంటే పెద్దవైన ``[tabindex]`` విలువను కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "ఏ మూలకానికీ సున్నా కంటే పెద్ద ``[tabindex]`` విలువ లేదు"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "పట్టికలను నావిగేట్ చేయడం సులభతరం చేసే ఫీచర్‌లు స్క్రీన్ రీడర్‌లలో ఉంటాయి. '`[headers]`' లక్షణాన్ని ఉపయోగిస్తున్న '`<td>`' సెల్‌లు కేవలం అదే పట్టికలోని ఇతర సెల్‌లను సూచించడం స్క్రీన్ రీడర్ వినియోగదారుల అనుభవాన్ని మెరుగుపరచవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "'`<table>`' మూలకంలో '`[headers]`' లక్షణాన్ని ఉపయోగించే సెల్‌లు అదే పట్టికలో కనుగొనబడని '`id`' మూలకాన్ని సూచిస్తున్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "'`<table>`' మూలకంలో '`[headers]`' లక్షణాన్ని ఉపయోగించే సెల్‌లు అదే పట్టికలోని పట్టిక సెల్‌లను సూచిస్తున్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "పట్టికలను నావిగేట్ చేయడం సులభతరం చేసే ఫీచర్‌లు స్క్రీన్ రీడర్‌లలో ఉంటాయి. పట్టిక ముఖ్య శీర్షికలు ఎల్లప్పుడూ కొన్ని సెల్‌ల సెట్‌ను సూచించేలా నిర్ధారించుకోవడం ద్వారా స్క్రీన్ రీడర్ వినియోగదారుల అనుభవాన్ని మెరుగుపరచవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "'`<th>`' మూలకాలలో, అలాగే '`[role=\"columnheader\"/\"rowheader\"]`' కలిగి ఉండే మూలకాలలో అవి వివరిస్తున్న డేటా సెల్‌లు లేవు."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "'`<th>`' మూలకాలు, '`[role=\"columnheader\"/\"rowheader\"]`' కలిగి ఉన్న మూలకాలలో అవి వివరిస్తున్న డేటా సెల్‌లు ఉన్నాయి."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "మూలకాలలో చెల్లుబాటయ్యే [BCP 47 భాష](https://www.w3.org/International/questions/qa-choosing-language-tags#question) పేర్కొనడం అన్నది, వచనాన్ని స్క్రీన్ రీడర్ సరిగ్గా ఉచ్చరించేలా నిర్ధారిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "``[lang]`` లక్షణాలలో చెల్లుబాటు అయ్యే విలువ లేదు"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "'`[lang]`' లక్షణాలు చెల్లుబాటయ్యే విలువను కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "వీడియోకు శీర్షికను అందిస్తే, చెవిటి వారు లేదా వినికిడి సమస్య ఉన్న వినియోగదారులు వీడియోలోని సమాచారాన్ని సులభంగా యాక్సెస్ చేయగలుగుతారు. [మరింత తెలుసుకోండి](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "'`<video>`' మూలకాలలో '`[kind=\"captions\"]`'తో '`<track>`' మూలకం లేదు."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "'`<video>`' మూలకాలు '`[kind=\"captions\"]`'తో '`<track>`' మూలకం కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "డైలాగ్‌లతో కాకుండా, ముఖంలోని హావభావాలు, దృశ్యాలతో నిండిన వీడియోలకు ఆడియో వివరణలు సంబంధిత సమాచారాన్ని అందిస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "'`<video>`' మూలకాలలో '`[kind=\"description\"]`'తో '`<track>`' మూలకం లేదు."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "'`<video>`' మూలకాలు '`[kind=\"description\"]`'తో '`<track>`' మూలకం కలిగి ఉన్నాయి"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "వినియోగదారులు హోమ్ స్క్రీన్‌కు ప్రోగ్రెసివ్ వెబ్ యాప్‌ను జోడించినప్పుడు, iOSలో ఉత్తమ ప్రదర్శన కోసం, '`apple-touch-icon`'ను నిర్వచించండి. అది తప్పనిసరిగా పారదర్శకం కాని 192px (లేదా 180px) చతురస్రాకార PNGని సూచించాలి. [మరింత తెలుసుకోండి](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "చెల్లుబాటయ్యే '`apple-touch-icon`' లేదు"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "'`apple-touch-icon-precomposed`' గడువు ముగిసింది, `apple-touch-icon`ను ప్రాధాన్యంగా తీసుకోవాలి."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "చెల్లుబాటు అయ్యే '`apple-touch-icon`'ను అందిస్తుంది"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome ఎక్స్‌టెన్షన్‌లు ఈ పేజీ లోడ్ పనితీరును ప్రతికూలంగా ప్రభావితం చేసాయి. ఎక్స్టెన్షన్‌లు లేకుండా పేజీని అజ్ఞాత మోడ్‌లో లేదా ఎక్స్‌టెన్షన్‌లు లేని Chrome ప్రొఫైల్‌లో ఆడిట్ చేయడాన్ని ప్రయత్నించండి."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "స్క్రిప్ట్ మూల్యనిర్ధారణ"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "స్క్రిప్ట్ అన్వయింపు"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "మొత్తం CPU సమయం"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JSను అన్వయించడం, సంకలనం చేయడం, అమలు చేయడం కోసం వెచ్చించే సమయాన్ని తగ్గించడాన్ని పరిశీలించండి. చిన్న JS పేలోడ్‌లను అందించడం ఈ విషయంలో మీకు సహాయపడవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript అమలు సమయాన్ని తగ్గించండి"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript అమలు సమయం"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "యానిమేట్ చేయబడిన కంటెంట్‌ను అందించడంలో పెద్ద GIFలు సమర్థవంతంగా పని చేయవు. నెట్‌వర్క్ బైట్‌లను పొదుపు చేయడానికి, యానిమేషన్‌ల కోసం MPEG4/WebM వీడియోలను, GIFకి బదులుగా నిశ్చల చిత్రాల కోసం PNG/WebPను ఉపయోగించడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "యానిమేటెడ్ కంటెంట్ కోసం వీడియో ఫార్మాట్‌లను ఉపయోగించండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "పేజీలో పూర్తి పరస్పర చర్యకు పట్టే సమయం తగ్గించడానికి అన్ని క్లిష్టమైన వనరులు లోడ్ అవ్వడం పూర్తయిన తర్వాతే ఆఫ్‌స్క్రీన్, దాగి ఉన్న చిత్రాలను నెమ్మదిగా లోడ్ చేయడాన్ని పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "ఆఫ్‌స్క్రీన్ చిత్రాలను వాయిదా వేయండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "వనరులు మీ పేజీలోని మొదటి పెయింట్‌ను బ్లాక్ చేస్తున్నాయి. ముఖ్యమైన JS/CSSలను ఇన్‌లైన్‌లో అందించడం, ముఖ్యం-కానటువంటి అన్ని JS/శైలులను తీసివేయడాన్ని పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "రెండర్-బ్లాకింగ్ వనరులను నివారించండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "పెద్ద నెట్‌వర్క్ పేలోడ్‌లకు వినియోగదారులు నిజమైన డబ్బును చెల్లించాలి. అవి అధికంగా సుదీర్ఘ లోడ్ సమయాలతో ముడిపడి ఉంటాయి. [మరింత తెలుసుకోండి](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "మొత్త పరిమాణం {totalBytes, number, bytes} KBగా ఉండేది"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "అతి పెద్ద నెట్‌వర్క్ పేలోడ్‌లను నివారించండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "అతి పెద్ద నెట్‌వర్క్ పేలోడ్‌లను నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS ఫైల్‌లను చిన్నవిగా చేయడం వలన నెట్‌వర్క్ పేలోడ్ పరిమాణాలు తగ్గిపోగలవు. [మరింత తెలుసుకోండి](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSSని చిన్నదిగా చేయండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript ఫైల్‌లను చిన్నవిగా చేయడం పేలోడ్ పరిమాణాలను, స్క్రిప్ట్‌ను అన్వయించడానికి పట్టే సమయాన్ని తగ్గించగలదు. [మరింత తెలుసుకోండి](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScriptను చిన్నదిగా చేయండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "నెట్‌వర్క్ కార్యకలాపంలో ఉపయోగించబడే అనవసరమైన బైట్‌లను తగ్గించడం కోసం, స్టైల్‌షీట్‌ల నుండి గడువు ముగిసిన నియమాలను తీసివేయండి. అలాగే, మడత పైన ఉన్న కంటెంట్ కోసం ఉపయోగించని CSSను లోడ్ చేయకుండా ఆపివేయండి. [మరింత తెలుసుకోండి](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "ఉపయోగించని CSS తీసివేయబడింది"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "నెట్‌వర్క్ కార్యకలాపం వినియోగించే బైట్‌లను తగ్గించడానికి ఉపయోగించని JavaScriptను తీసివేయండి."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "ఉపయోగించని JavaScriptను తీసివేయండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "దీర్ఘమైన కాష్ జీవితకాలం మీ పేజీకి పునరావృత సందర్శనలను వేగవంతం చేయవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 వనరు కనుగొనబడింది}other{ # వనరులు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "నిశ్చల ఆస్తులను సమర్ధవంతమైన కాష్ విధానంతో అందించండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "నిశ్చలమైన ఆస్తులపై సమర్ధవంతమైన కాష్ విధానాన్ని ఉపయోగిస్తుంది"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "ఆప్టిమైజ్ చేసిన చిత్రాలు త్వరగా లోడ్ అవుతాయి, తక్కువ సెల్యులార్ డేటాను ఉపయోగిస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "చిత్రాలను సమర్థవంతంగా ఎన్‌కోడ్ చేయండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "సెల్యులార్ డేటాను పొదుపు చేయడానికి, లోడ్ సమయాన్ని మెరుగుపరచడానికి తగిన-పరిమాణానికి మార్చబడిన చిత్రాలను అందించండి. [మరింత తెలుసుకోండి](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "చిత్రాల పరిమాణాన్ని సరిగ్గా మార్చండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "మొత్తం నెట్‌వర్క్ బైట్‌లను తగ్గించడానికి వచనం-ఆధారిత వనరులు ఖచ్చితంగా కుదింపు (gzip, deflate లేదా brotli)తో అందించబడాలి. [మరింత తెలుసుకోండి](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "వచనం కుదింపును ప్రారంభించండి"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000, JPEG XR, WebP లాంటి చిత్రం ఫార్మాట్‌లు తరచుగా PNG లేదా JPEG కంటే మెరుగైన కుదింపును అందిస్తాయి. దీని వలన, డౌన్‌లోడ్‌లు మరింత వేగంగా ఉంటాయి, తక్కువ డేటా వినియోగం అవుతుంది. [మరింత తెలుసుకోండి](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "చిత్రాలను తర్వాతి-తరం ఫార్మాట్‌లలో అందించండి"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "ఒకవేళ వీక్షణ పోర్ట్ వెడల్పుతో మీ యాప్ కంటెంట్ వెడల్పు సరిపోలకుంటే, మొబైల్ స్క్రీన్‌లకు అనుగుణంగా మీ యాప్‌ను ఆప్టిమైజ్ చేయడం సాధ్యపడకపోవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{outerWidth}px విండో సైజ్‌తో {innerWidth}px వీక్షణ పోర్ట్ సైజ్ సరిపోలలేదు."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "వీక్షణ పోర్ట్‌కు తగినట్లుగా కంటెంట్ సైజ్ సర్దుబాటు చేయబడలేదు"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "వీక్షణ పోర్ట్‌కు తగినట్లుగా కంటెంట్ సైజ్ సర్దుబాటు చేయబడింది"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "కింద పేర్కొన్న ముఖ్యమైన అభ్యర్ధన గొలుసులు ఏ వనరులు అధిక ప్రాధాన్యతతో లోడ్ అయ్యాయో చూపిస్తాయి. పేజీ లోడ్‌ను మెరుగుపరచడానికి గొలుసుల పొడవును తగ్గించడం, వనరుల డౌన్‌లోడ్ పరిమాణాన్ని తగ్గించడం, లేదా అనవసర వనరులను డౌన్‌లోడ్ చేయడాన్ని వాయిదా వేయడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 గొలుసు కనుగొనబడింది}other{# గొలుసులు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "క్లిష్టమైన అభ్యర్ధనల గాఢత్వమును తగ్గించండి"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "విస్మరణ / హెచ్చరిక"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "పంక్తి"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "విస్మరించబడిన APIలు క్రమంగా బ్రౌజర్ నుండి తీసివేయబడతాయి. [మరింత తెలుసుకోండి](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 హెచ్చరిక కనుగొనబడింది}other{# హెచ్చరికలు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "విస్మరించబడిన APIలను వినియోగిస్తోంది"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "విస్మరించబడిన APIలను నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "అప్లికేషన్ కాష్ విస్మరించబడింది. [మరింత తెలుసుకోండి](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" కనుగొనబడింది"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "అప్లికేషన్ కాష్‌ను వినియోగిస్తున్నారు"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "అప్లికేషన్ కాష్‌ను నివారిస్తోంది"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "'doctype'ను పేర్కొనడం వలన క్విర్క్స్-మోడ్‌కు మారనివ్వకుండా బ్రౌజర్ నిరోధించబడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "'Doctype' పేరు తప్పనిసరిగా లోయర్-కేస్ స్ట్రింగ్ రూపంలో ఉండాలి `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "పత్రంలో తప్పనిసరిగా doctype ఉండాలి"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "'publicId' ఒక ఖాళీ స్ట్రింగ్‌గా వదిలిపెట్టాలి"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "'systemId' ఒక ఖాళీ స్ట్రింగ్‌గా వదిలిపెట్టాలి"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "పేజీలో HTML doctype లేదు, కనుక క్విర్క్స్-మోడ్‌ను ట్రిగ్గర్ చేస్తోంది"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "పేజీలో 'HTML doctype' ఉంది"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "మూలకం"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "గణాంక రకం"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "విలువ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "బ్రౌజర్ ఇంజినీర్‌లు ~1,500 కంటే తక్కువ DOM మూలకాలను కలిగి ఉండే పేజీలను సిఫార్సు చేస్తారు. అత్యుత్తమ ప్రమాణంలో ట్రీ డెప్త్ < 32 మూలకాలు, 60 కంటే తక్కువ ఉపాంశ/మూలాధార మూలకాలు ఉండాలి. పెద్ద DOM వలన మెమరీ వినియోగం పెరగవచ్చు. దీర్ఘమైన [స్టైల్ గణనలు](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) జరగవచ్చు, ఖరీదైన [లేఅవుట్ రీఫ్లోలు](https://developers.google.com/speed/articles/reflow) అందించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 మూలకం}other{# మూలకాలు}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "అధిక DOM పరిమాణాన్ని నివారించండి"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "DOM గరిష్ట గాఢత్వము"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "మొత్తం DOM మూలకాలు"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "పిల్ల మూలకాల గరిష్ట సంఖ్య"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "అధిక DOM పరిమాణాన్ని నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "లక్ష్యం"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "పనితీరును మెరుగుపరచడానికి, అలాగే భద్రతా ప్రమాదాలను నిరోధించడానికి ఏవైనా బయటి లింక్‌లకు '`rel=\"noopener\"`' లేదా '`rel=\"noreferrer\"`'లను జోడించండి. [మరింత తెలుసుకోండి](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "క్రాస్-ఆరిజిన్ గమ్యస్థానాలకు తీసుకెళ్లే లింక్‌లు అసురక్షితమైనవి"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "క్రాస్-ఆరిజిన్ గమ్యస్థానాలకు తీసుకెళ్లే లింక్‌లు సురక్షితమైనవి"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "యాంకర్ ({anchorHTML}) కోసం గమ్యస్థానాన్ని కనుగొనడం సాధ్యపడలేదు. ఒకవేళ హైపర్‌లింక్ లాగా ఉపయోగించకుంటే, 'target=_blank'ను తీసివేయడం గురించి పరిశీలించండి."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "సందర్భం ఏమీ లేకుండా స్థానాన్ని అభ్యర్థించే సైట్‌లను వినియోగదారులు నమ్మరు లేదా గందరగోళానికి గురి అవుతారు. దానికి బదులుగా, వినియోగదారు చర్యతో అభ్యర్థనను ప్రయత్నించడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "పేజీ లోడ్ సమయంలో భౌగోళిక స్థానం అనుమతిని అభ్యర్థిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "పేజీ లోడ్ సమయంలో భౌగోళిక స్థానం అనుమతిని అభ్యర్థించడం నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "వెర్షన్"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "పేజీలోని అన్ని ఫ్రంట్-ఎండ్ JavaScript లైబ్రరీలు గుర్తించబడ్డాయి. [మరింత తెలుసుకోండి](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript లైబ్రరీలు గుర్తించబడ్డాయి"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "కనెక్షన్‌లు నెమ్మదిగా పని చేస్తున్న వినియోగదారుల కోసం, '`document.write()`' ద్వారా డైనమిక్‌గా ఇంజెక్ట్ చేయబడే బయటి స్క్రిప్ట్‌ల వలన పేజీ పదుల సెకన్ల పాటు ఆలస్యంగా లోడ్ కాగలదు. [మరింత తెలుసుకోండి](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "'`document.write()`'ను వినియోగిస్తోంది"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "'`document.write()`'ను నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "అత్యంత తీవ్రత"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "లైబ్రరీ వెర్షన్"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "భద్రతా ప్రమాదాల సంఖ్య"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "కొన్ని మూడవ పక్షం స్క్రిప్ట్‌లలో, దాడులకు పాల్పడేవారు సులభంగా గుర్తించగలిగే, సమాచారం దొంగిలించగలిగే తెలిసిన భద్రతా ప్రమాదాలు ఉండవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 ప్రమాద కారకం గుర్తించబడింది}other{# ప్రమాద కారకాలు గుర్తించబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "తెలిసిన భద్రతా ప్రమాదాలను కలిగి ఉండే ఫ్రంట్-ఎండ్ JavaScript లైబ్రరీలను జోడిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "అధికం"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "తక్కువ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "మధ్యస్థం"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "తెలిసిన భద్రతా ప్రమాదాలను కలిగి ఉండే ఫ్రంట్-ఎండ్ JavaScript లైబ్రరీలను నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "సందర్భం ఏమీ లేకుండా నోటిఫికేషన్‌లను పంపడానికి అనుమతి కోరే సైట్‌లను వినియోగదారులు నమ్మరు లేదా గందరగోళానికి గురి అవుతారు. బదులుగా వినియోగదారు సంజ్ఞలకు అభ్యర్థనను ప్రయత్నించడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "పేజీ లోడ్ సమయంలో నోటిఫికేషన్ అనుమతిని అభ్యర్థిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "పేజీ లోడ్ సమయంలో నోటిఫికేషన్ అనుమతిని అభ్యర్థించడం నివారిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "విఫలం అవుతున్న మూలకాలు"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "పాస్‌వర్డ్‌లో అతికించే చర్యను నిరోధించడం వలన మంచి భద్రతా విధానానికి ఆటంకం ఏర్పడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "పాస్‌వర్డ్ ఫీల్డ్‌లలో అతికించడం చేయలేకుండా వినియోగదారులను నిరోధిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "పాస్‌వర్డ్ ఫీల్డ్‌లలో అతికించడానికి వినియోగదారులను అనుమతిస్తుంది"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "ప్రోటోకాల్"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 ద్వారా HTTP/1.1 కంటే ఎక్కువ ప్రయోజనాలు, అలాగే బైనరీ హెడర్‌లు, మల్టీప్లెక్సింగ్, సర్వర్ పుష్ కూడా అందించబడతాయి. [మరింత తెలుసుకోండి](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 అభ్యర్థన 'HTTP/2' ద్వారా అందించబడలేదు}other{# అభ్యర్థనలు 'HTTP/2' ద్వారా అందించబడలేదు}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "'HTTP/2' దాని వనరులు అన్నింటిలో వినియోగించబడలేదు"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "\"HTTP/2\" దాని స్వంత వనరులు అన్నింటిలో వినియోగించబడుతోంది"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "మీ పేజీ స్క్రోలింగ్ పనితీరును మెరుగుపరచడానికి మీ స్పర్శ, చక్రం కదలికలను గుర్తుపట్టే లిజనర్‌లను '`passive`'కు సెట్ చేయడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "స్క్రోలింగ్ పనితీరును మెరుగుపరచడానికి పాసివ్ లిజనర్‌లను వినియోగించడం లేదు"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "స్క్రోలింగ్ పనితీరును మెరుగుపరచడానికి పాసివ్ లిజనర్‌లను వినియోగిస్తుంది"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "వివరణ"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "కన్సోల్‌లో లాగ్ చేయబడిన ఎర్రర్‌లు పరిష్కారం కాని సమస్యలను సూచిస్తాయి. నెట్‌వర్క్ అభ్యర్థన వైఫల్యాలు, ఇతర బ్రౌజర్ ఇబ్బందుల వలన అవి ఏర్పడి ఉంటాయి. [మరింత తెలుసుకోండి](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "బ్రౌజర్ ఎర్రర్‌లు కన్సోల్‌లో లాగ్ చేయబడ్డాయి"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "కన్సోల్‌లో లాగ్ చేయబడిన బ్రౌజర్ ఎర్రర్‌లు ఏవీ లేవు"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "వెబ్ ఫాంట్‌లు లోడ్ అవుతున్నప్పుడు వచనం వినియోగదారుకు కనిపించేలా ఉందని నిర్ధారించుకోవడానికి ఫాంట్-ప్రదర్శన CSS ఫీచర్‌ను శక్తివంతం చేయండి. [మరింత తెలుసుకోండి](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "వెబ్ ఫాంట్ లోడ్ సమయంలో వచనం కనిపించేటట్లు నిర్ధారించుకోండి"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "వెబ్ ఫాంట్ లోడ్‌ల సమయంలో వచనం మొత్తం కనిపిస్తూ ఉంటుంది"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "కింది URL కోసం ఫాంట్ ప్రదర్శన విలువను Lighthouse ఆటోమేటిక్‌గా తనిఖీ చేయలేకపోయింది: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "ఆకార నిష్పత్తి (ఉండాల్సినది)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "ఆకార నిష్పత్తి (ప్రదర్శించబడింది)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "చిత్ర ప్రదర్శన కొలతలు సహజ ఆకార నిష్పత్తికి సరిపోలే విధంగా ఉండాలి. [మరింత తెలుసుకోండి](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "తప్పు ఆకార నిష్పత్తిని కలిగి ఉన్న చిత్రాలను ప్రదర్శిస్తుంది"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "సరైన ఆకార నిష్పత్తితో చిత్రాలను ప్రదర్శిస్తుంది"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "చెల్లుబాటు కాని చిత్ర పరిమాణ సమాచారం {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "మీ యాప్‌ను హోమ్ స్క్రీన్‌కు జోడించుకోవాల్సిందిగా బ్రౌజర్‌లు క్రియాశీలంగా వినియోగదారులను ప్రాంప్ట్ చేయగలవు, దీని వలన అధిక మంది జనాభాకు చేరువయ్యే అవకాశం పెరగవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "ఇన్‌స్టాల్ సామర్థ్య అవసరాలకు అనుగుణంగా వెబ్ యాప్ మానిఫెస్ట్ లేదు"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "ఇన్‌స్టాల్ సామర్థ్య అవసరాలకు అనుగుణంగా వెబ్ యాప్ మానిఫెస్ట్ ఉంది"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "అసురక్షితమైన URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "అన్ని సైట్‌లకు 'HTTPS' రక్షణను జోడించాలి. సున్నితమైన వ్యక్తిగత సమాచారం ఏదీ లేని వాటికి కూడా ఈ రక్షణను జోడించాలి. HTTPS రక్షణను జోడించడం వలన దాడులకు పాల్పడేవారు ఎవరూ కూడా మీ యాప్, మీ వినియోగదారుల మధ్య జరిగే కమ్యూనికేషన్‌లను ట్యాంపర్ చేయడం లేదా దొంగచాటుగా వినడం లాంటివి చేయకుండా అడ్డుకోబడతారు. అలాగే HTTP/2, ఇంకా అనేక కొత్త వెబ్ ప్లాట్‌ఫామ్ APIల కోసం దీనిని తప్పనిసరిగా వినియోగించాలి. [మరింత తెలుసుకోండి](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 అసురక్షితమైన అభ్యర్థన కనుగొనబడింది}other{# అసురక్షితమైన అభ్యర్థనలు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "'HTTPS'ను ఉపయోగించడం లేదు"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPSను ఉపయోగిస్తుంది"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "పేజీ కనుక సెల్యులార్ నెట్‌వర్క్‌లో వేగంగా లోడ్ అయితే తప్పకుండా మంచి మొబైల్ వినియోగదారు అనుభవాన్ని అందిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "ప్రభావశీలత సమయం {timeInMs, number, seconds} సెకన్లు"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "సిములేటెడ్ మొబైల్ నెట్‌వర్క్‌లో ప్రభావశీలత సమయం {timeInMs, number, seconds} సెకన్లు"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "మీ పేజీ చాలా నెమ్మదిగా లోడ్ అవుతోంది. కనుక 10 సెకన్ల వ్యవధిలో ఇంటరాక్ట్ కాలేరు. ఎలా మెరుగుపరచాలో తెలుసుకోవడానికి \"పనితీరు\" విభాగంలోని అవకాశాలు, సమస్య విశ్లేషణలను చూడండి."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "మొబైల్ నెట్‌వర్క్‌లలో పేజీ తగినంత వేగంగా లోడ్ కావడం లేదు"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "మొబైల్ నెట్‌వర్క్‌లలో పేజీ తగినంత వేగంగా లోడ్ అవుతోంది"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "వర్గం"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "JSను అన్వయించడం, సంకలనం చేయడం, అమలు చేయడం కోసం వెచ్చించే సమయాన్ని తగ్గించడానికి ప్రయత్నించండి. చిన్న JS పేలోడ్‌లను అందించడం ఈ విషయంలో మీకు సహాయపడవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "ప్రధాన థ్రెడ్ పనిని తగ్గించండి"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "ప్రధాన థ్రెడ్ పనిని తగ్గిస్తుంది"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "అత్యధిక మంది వినియోగదారులకు చేరువ కావడానికి, సైట్‌లు ప్రతి ప్రధాన బ్రౌజర్‌లో పని చేయాలి. [మరింత తెలుసుకోండి](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "వివిధ రకాల బ్రౌజర్‌లలో సైట్ పని చేస్తుంది"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "విడివిడిగా ఉన్న పేజీలు URL ద్వారా లోతైన లింక్‌తో అనుబంధించబడేలా, ఆ URLలు సోషల్ మీడియాలో షేర్ చేసుకోవడానికి ప్రత్యేక రీతిలో ఉండేలా జాగ్రత్త వహించండి. [మరింత తెలుసుకోండి](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "ప్రతి పేజీకి URL ఉంది"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "నెట్‌వర్క్ కనెక్షన్ నెమ్మదిగా ఉన్నప్పటికీ, మీరు స్క్రీన్‌పై ఎక్కడైనా నొక్కినప్పుడు పరివర్తనలు వీక్షణకు భంగం కలిగించకుండా మృదువుగా ఉండాలి. నిర్వహణాపరమైన పనితీరు దృష్ట్యా ఇలాంటి అనుభూతి అందించడం అత్యంత కీలకం. [మరింత తెలుసుకోండి](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "పేజీ పరివర్తనలు నెట్‌వర్క్‌లో లోడ్ అవుతున్నప్పుడు బ్లాక్ అవుతున్నట్లుగా కనిపించకూడదు"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "పేజీ లోడ్‌కు అత్యంత రద్దీ అయిన 5 సెకన్ల విండో సమయంలో, వినియోగదారు ఇన్‌పుట్‌కు ప్రతిస్పందించడానికి, మిల్లీ సెకన్లలో, మీ యాప్ తీసుకునే సమయం యొక్క అంచనాను 'అంచనా వేసిన ఇన్‌పుట్ ప్రతిస్పందన సమయం' అని అంటారు. మీ ప్రతిస్పందన సమయం 50 మిల్లీ సెక‌న్ల‌ కన్నా ఎక్కువ అయితే, మీ యాప్ వేగవంతంగా పని చేయట్లేదని వినియోగదారులు భావించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "అంచనా వేయబడిన ఇన్‌పుట్ ప్రతిస్పందన సమయం"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "మొదటి కంటెంట్ సహిత పెయింట్ ఏదైనా వచనం లేదా చిత్రం మొదటిసారి పెయింట్ చేయబడిన సమయాన్ని గుర్తిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "మొదటి కంటెంట్ సహిత పెయింట్"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "'మొదటి CPU ఖాళీ సమయం' కొలమానం, మొదటి సారి పేజీ యొక్క ప్రధాన థ్రెడ్ ఇన్‌పుట్‌ను నిర్వహించడానికి తీసుకున్న సమయాన్ని గుర్తిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU మొదటి ఖాళీ సమయం"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "ఒక పేజీ ప్రాథమిక కంటెంట్ ఎప్పుడు కనిపించింది అనేదానికి, మొదటి అర్ధవంతమైన పెయింట్ ఒక కొలమానం. [మరింత తెలుసుకోండి](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "మొదటి అర్థవంతమైన పెయింట్"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "పరస్పర చర్య చేయడానికి పేజీ పూర్తిగా సిద్ధం అయ్యేందుకు పట్టే సమయాన్ని 'పేజీలో పూర్తి పరస్పర చర్యకు పట్టే సమయం' అంటారు. [మరింత తెలుసుకోండి](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "పేజీలో పూర్తి పరస్పర చర్యకు పట్టే సమయం"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "మీ వినియోగదారులు ఎదుర్కోగల గరిష్ఠ మొదటి ఇన్‌పుట్ ఆలస్యం అన్నది సుదీర్ఘ టాస్క్‌లో మిల్లీసెకన్ల వ్యవధిలో ఉంటుంది. [మరింత తెలుసుకోండి](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "మొదటి ఇన్‌పుట్ ఆలస్య గరిష్ఠ వ్యవధి"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "వేగం సూచిక అనేది, ఒక పేజీలోని కంటెంట్‌లు ఎంత వేగంగా ప్రత్యక్షంగా చూపించబడతాయో తెలియజేస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "వేగం సూచిక"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "టాస్క్ వ్యవధి 50 మిల్లీసెకన్లు మించిపోయినప్పుడు FCP మరియు పేజీలో పూర్తి పరస్పర చర్యకు పట్టే సమయం మధ్య వేచి ఉండాల్సిన మొత్తం కాలవ్యవధి మిల్లీసెకన్లలో పేర్కొనబడుతుంది."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "మొత్తం బ్లాక్ చేయబడే సమయం"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "నెట్‌వర్క్ రౌండ్ ట్రిప్ సమయాలు (RTT) పనితీరుపై తీవ్రమైన ప్రభావం చూపుతాయి. మూలానికి RTT ఎక్కువగా ఉంటే, వినియోగదారుకు దగ్గరగా ఉన్న సర్వర్‌ల పనితీరు మెరుగ్గా ఉండవచ్చని సంకేతం. [మరింత తెలుసుకోండి](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "నెట్‌వర్క్ రౌండ్ ట్రిప్ సమయాలు"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "సర్వర్ ప్రతిస్పందన సమయాలు వెబ్ పనితీరుపై ప్రభావం చూపగలవు. మూలంలో సర్వర్ ప్రతిస్పందన సమయం ఎక్కువగా ఉంటే, సర్వర్ ఓవర్‌లోడ్ అయినట్లు లేదా బ్యాక్ఎండ్ పనితీరు సరిగ్గా లేనట్లు అర్థం. [మరింత తెలుసుకోండి](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "సర్వర్ బ్యాక్ఎండ్ ప్రతిస్పందన సమయాలు"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "సర్వీస్ వర్కర్ సహాయంతో, మీ వెబ్ యాప్ ఇబ్బందికరమైన నెట్‌వర్క్ పరిస్థితులలో కూడా విశ్వసనీయత కోల్పోకుండా పని చేయగలుగుతుంది. [మరింత తెలుసుకోండి](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "ఆఫ్‌లైన్‌‌లో ఉన్నప్పుడు `start_url` అన్నది '200' కోడ్‌తో స్పందించలేదు"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "ఆఫ్‌లైన్‌‌లో ఉన్నప్పుడు `start_url` అన్నది '200' కోడ్‌తో స్పందించింది"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "మానిఫెస్ట్ నుండి '`start_url`'ను Lighthouse చదవలేకపోయింది. దీని ఫలితంగా, '`start_url`' అన్నది పత్రం యొక్క URLగా పరిగణించబడింది. ఎర్రర్ సందేశం: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "బడ్జెట్ దాటిపోయింది"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "నెట్‌వర్క్ అభ్యర్థనల సంఖ్య, పరిమాణాన్ని అందించబడిన పనితీరు బడ్జెట్ ప్రకారం నిర్దేశించిన లక్ష్యాల కంటే తక్కువకు ఉంచండి. [మరింత తెలుసుకోండి](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 అభ్యర్థన}other{# అభ్యర్థనలు}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "పనితీరు బడ్జెట్"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "మీరు ఇప్పటికే 'HTTPS' సెటప్ చేసుకుని ఉంటే, మొత్తం 'HTTP' ట్రాఫిక్‌ను 'HTTPS'కు మళ్లించేలా జాగ్రత్త తీసుకోవడం ద్వారా మీ వినియోగదారులందరికీ సురక్షితమైన వెబ్ ఫీచర్‌లను అందించండి. [మరింత తెలుసుకోండి](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "'HTTP' ట్రాఫిక్‌ను 'HTTPS'కు మళ్లించదు"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "'HTTP' ట్రాఫిక్‌ను 'HTTPS'కు మళ్లిస్తుంది"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "మళ్లింపులు పేజీ లోడ్ అవ్వడానికి ముందు అదనపు ఆలస్యాలను కలుగజేస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "అనేక పేజీ మళ్లింపులను నివారించండి"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "పేజీ వనరుల సంఖ్య, పరిమాణం కోసం బడ్జెట్‌లను సెట్ చేయడానికి, 'budget.json' ఫైల్‌ను జోడించండి. [మరింత తెలుసుకోండి](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 అభ్యర్థన • {byteCount, number, bytes} KB}other{# అభ్యర్థనలు • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "అభ్యర్థనల సంఖ్యను తగ్గించుకోండి, బదిలీ పరిమాణాలు తక్కువగా ఉండేలా చూసుకోండి"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "శోధన ఫలితాలలో ఏ URLను చూపాలో నియమానుగుణమైన లింక్‌లు సూచిస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "వైరుధ్యమైన అనేక URLలు ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "వేరొక డొమైన్ ({url})కు సూచిస్తోంది"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "చెల్లని URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "మరొక '`hreflang`' స్థానం ({url})కు నిర్దేశిస్తోంది"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "సంబంధిత URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "అలాంటి కంటెంట్‌ను కలిగిన పేజీకి బదులుగా డొమైన్ యొక్క మూలాధార URL (హోమ్‌పేజీ)ని సూచిస్తుంది"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "పత్రంలో చెల్లుబాటు అయ్యే '`rel=canonical`' లేదు"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "పత్రంలో చెల్లుబాటు అయ్యే '`rel=canonical`' ఉంది"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12px కంటే తక్కువగా ఉన్న ఫాంట్ పరిమాణాలు చాలా చిన్నవిగా ఉంటాయి, కనుక అవి సముచితంగా పరిగణించబడవు. వీటిని చదవడం కోసం మొబైల్ సందర్శకులు “జూమ్ చేయడానికి స్క్రీన్‌పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగాలి”. మీరు కలిగి ఉండాల్సింది >పేజీ వచనంలో 60% ≥12px. [మరింత తెలుసుకోండి](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} సముచిత వచనం"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "మొబైల్ స్క్రీన్‌ల కోసం ఆప్టిమైజ్ చేసిన వీక్షణ పోర్ట్ మెటా ట్యాగ్ అందుబాటులో లేదు కనుక వచనం సముచితంగా లేదు."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "'{decimalProportion, number, extendedPercent}' వచనం చాలా చిన్నదిగా ఉంది ('{decimalProportionVisited, number, extendedPercent}' నమూనా ఆధారంగా)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "పత్రంలో సముచితమైన ఫాంట్ పరిమాణాలను ఉపయోగించలేదు"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "పత్రంలో ఫాంట్ పరిమాణాలు సముచితంగా ఉన్నాయి"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "'hreflang' లింక్‌లు అన్నవి నిర్దిష్ట భాష లేదా ప్రాంతం కోసం పేజీ యొక్క ఏ వెర్షన్‌ను శోధన ఫలితాలలో చూపాలన్నది శోధన ఇంజిన్‌లకు తెలియజేస్తాయి. [మరింత తెలుసుకోండి](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "పత్రంలో చెల్లుబాటు అయ్యే ``hreflang`` లేదు"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "పత్రంలో చెల్లుబాటు అయ్యే '`hreflang`' ఉంది"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "విజయవంతం కాని HTTP స్థితి కోడ్‌లను కలిగిన పేజీలు సరిగ్గా సూచిక చేయబడకపోవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "పేజీలో విజయవంతం కాని HTTP స్థితి కోడ్ ఉంది"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "పేజీలో విజయవంతమైన HTTP స్థితి కోడ్ ఉంది"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "మీ పేజీలను క్రాల్ చేయడానికి శోధన ఇంజిన్‌లను అనుమతించకుంటే, అవి శోధన ఫలితాలలో మీ పేజీలను చూపడం సాధ్యం కాదు. [మరింత తెలుసుకోండి](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "సూచిక చేయకుండా పేజీ బ్లాక్ చేయబడింది"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "సూచికలో పేజీ బ్లాక్ చేయబడలేదు"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "మీ కంటెంట్‌ను అర్థం చేసుకోవడంలో శోధన ఇంజిన్‌లకు వివరణాత్మక లింక్ వచనం సహాయపడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 లింక్ కనుగొనబడింది}other{# లింక్‌లు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "లింక్‌లలో వివరణాత్మక వచనం లేదు"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "లింక్‌లలో వివరణాత్మక వచనం ఉంది"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "నిర్మాణాత్మకమైన డేటాను ప్రామాణీకరించడం కోసం [నిర్మాణాత్మక డేటా పరీక్ష సాధనం](https://search.google.com/structured-data/testing-tool/), [నిర్మాణాత్మక డేటా లింటర్‌](http://linter.structured-data.org/)లను అమలు చేయండి. [మరింత తెలుసుకోండి](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "నిర్మాణాత్మక డేటా చెల్లుబాటు అవుతుంది"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "పేజీ కంటెంట్ సారాంశాన్ని క్లుప్తంగా అందించడం కోసం శోధన ఫలితాలలో మెటా వివరణలను జోడించవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "వివరణ వచనం ఖాళీగా ఉంది."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "పత్రంలో మెటా వివరణ లేదు"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "పత్రంలో మెటా వివరణ ఉంది"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "ప్లగ్ఇన్ కంటెంట్‌ను శోధన ఇంజిన్‌లు సూచిక చేయలేవు. అలాగే, చాలా పరికరాలలో ప్లగ్ఇన్‌లు నియంత్రించబడతాయి లేదా వాటికి మద్దతు ఉండదు. [మరింత తెలుసుకోండి](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "పత్రంలో ప్లగ్ఇన్‌లు ఉపయోగించబడుతున్నాయి"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "పత్రంలో ప్లగ్ఇన్‌లు నివారించబడ్డాయి"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "మీ robots.txt ఫైల్ పాడైతే, మీరు మీ వెబ్‌సైట్‌ను ఎలా క్రాల్ చేయాలనుకుంటున్నారు లేదా సూచిక చేయాలనుకుంటున్నారు అన్నది crawlerలకు అర్థం కాకపోవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt కోసం పంపిన అభ్యర్థనకు ప్రతిస్పందనగా అందించబడిన HTTP స్థితి: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 ఎర్రర్ కనుగొనబడింది}other{# ఎర్రర్‌లు కనుగొనబడ్డాయి}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "robots.txt ఫైల్‌ను డౌన్‌లోడ్ చేయడం లైట్‌హౌస్‌కు సాధ్యం కాలేదు"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt చెల్లుబాటు కాదు"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt చెల్లుబాటు అవుతుంది"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "బటన్‌లు మరియ లింక్‌లు వంటి సహకారాన్ని అందించే ఎలిమెంట్‌ల పరిమాణం తగినంత ఉండాలి (48x48px), వాటి చుట్టూ తగినంత ఖాళీ స్థలం ఉండాలి. అలా అయితే అవి ఇతర ఎలిమెంట్‌లతో ఓవర్‌ల్యాప్ కాకుండా ఉంటాయి. [మరింత తెలుసుకోండి](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} సముచిత పరిమాణంలో ట్యాప్ టార్గెట్‌లను కలిగి ఉంది"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "మొబైల్ స్క్రీన్‌లలో ఆప్టిమైజ్ చేసిన వీక్షణ పోర్ట్ మెటా ట్యాగ్ అందుబాటులో లేదు కనుక ట్యాప్ టార్గెట్‌లు చాలా చిన్నవిగా ఉన్నాయి"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "ట్యాప్ టార్గెట్‌ల పరిమాణం సముచితంగా ఉంది"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "లక్ష్యం ఓవర్‌ల్యాప్ అవుతోంది"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "ట్యాప్ టార్గెట్"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "ట్యాప్‌టార్గెట్‌ల పరిమాణం సముచితంగా ఉంది"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "'సర్వీస్ వర్కర్' సాంకేతిక పరిజ్ఞానం సహాయంతో మీ యాప్ - 'ఆఫ్‌లైన్ వినియోగం', 'హోమ్ స్క్రీన్‌కు జోడింపు', 'పుష్ నోటిఫికేషన్‌లు' లాంటి అనేక ప్రోగ్రెసివ్ వెబ్ యాప్ ఫీచర్‌లను ఉపయోగించగలుగుతుంది. [మరింత తెలుసుకోండి](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "ఈ పేజీ ఒక సర్వీస్ వర్కర్ ద్వారా నియంత్రించబడినప్పటికీ, చెల్లుబాటయ్యే JSON ఫార్మాట్‌లో అన్వయించడంలో మానిఫెస్ట్ విఫలమైనందున '`start_url`' ఏదీ కనుగొనబడలేదు"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "ఈ పేజీ ఒక సర్వీస్ వర్కర్ ద్వారా నియంత్రించబడినప్పటికీ, '`start_url`' ({startUrl}) అన్నది సర్వీస్ వర్కర్ పరిధి ({scopeUrl})లో లేదు"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "ఈ పేజీ ఒక సర్వీస్ వర్కర్ ద్వారా నియంత్రించబడినప్పటికీ, మానిఫెస్ట్ ఏదీ పొందనందున '`start_url`' ఏదీ కనుగొనబడలేదు."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "ఈ మూలాధారంలో ఒకటి లేదా అంతకంటే ఎక్కువ సర్వీస్ వర్కర్‌లు ఉన్నప్పటికీ, పేజీ ({pageUrl}) పరిధిలో లేదు."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "పేజీని, '`start_url`'ను నియంత్రించే సర్వీస్ వర్కర్ ఏదీ నమోదు చేయబడలేదు"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "పేజీని, '`start_url`'ను నియంత్రించే సర్వీస్ వర్కర్ నమోదు చేయబడింది"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "ఒక థీమ్‌తో కూడిన స్ప్లాష్ స్క్రీన్ వలన వినియోగదారులు వారి హోమ్ స్క్రీన్‌ల నుండి మీ యాప్‌ను ప్రారంభించినప్పుడు అధిక నాణ్యత గల అనుభవం అందించబడుతుంది. [మరింత తెలుసుకోండి](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "అనుకూలమైన స్ప్లాష్ స్క్రీన్ కోసం కాన్ఫిగర్ చేయలేదు"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "అనుకూలమైన స్ప్లాష్ స్క్రీన్ కోసం కాన్ఫిగర్ చేయబడింది"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "బ్రౌజర్ చిరునామా బార్‌ను మీ సైట్‌తో సరిపోలే థీమ్‌లోకి మార్చుకోవచ్చు. [మరింత తెలుసుకోండి](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "చిరునామా బార్ కోసం థీమ్ రంగును సెట్ చేయలేదు."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "చిరునామా బార్ కోసం థీమ్ రంగు సెట్ చేయబడింది."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "ప్రధాన థ్రెడ్ బ్లాక్ చేయబడే సమయం"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "మూడవ పక్షం"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "మూడవ పక్షం కోడ్ గణనీయ స్థాయిలో లోడ్ పనితీరుపై ప్రభావం చూపవచ్చు. అవసరం లేని మూడవ పక్ష ప్రదాతల సంఖ్యను పరిమితం చేసి, మీ పేజీ ప్రాథమికంగా లోడ్ కావడం పూర్తయిన తర్వాత మూడవ పక్ష కోడ్‌ను లోడ్ చేయడానికి ప్రయత్నించండి. [మరింత తెలుసుకోండి](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "మూడవ పక్షం కోడ్ ఒక ప్రధానమైన థ్రెడ్‌ను {timeInMs, number, milliseconds} మిల్లీసెకన్ల పాటు బ్లాక్ చేసింది"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "మూడవ పక్షం కోడ్ ప్రభావాన్ని తగ్గించండి"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "మూడవ పక్షం వినియోగం"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "మొదటి బైట్ సమయం మీ సర్వర్ ప్రతిస్పందనను పంపించిన సమయాన్ని గుర్తిస్తుంది. [మరింత తెలుసుకోండి](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "రూట్ పత్రం {timeInMs, number, milliseconds} మి.సె తీసుకుంది"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "సర్వర్ ప్రతిస్పందన సమయాలను తగ్గించండి (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "సర్వర్ ప్రతిస్పందన సమయాలు తక్కువగా ఉన్నాయి (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "వ్యవధి"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "ప్రారంభ సమయం"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "రకం"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "కీలక వినియోగదారు అనుభవాల సమయంలో మీ యాప్ వాస్తవ ప్రపంచ పనితీరును అంచనా వేయడానికి, మీ యాప్ కోసం వినియోగదారు సమయానుకూల APIని కొలమానంగా చేసుకుని పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 వినియోగదారు సమయం}other{# వినియోగదారు సమయాలు}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "వినియోగదారు సమయం మార్కులు మరియు కొలమానాలు"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "\"{securityOrigin}\" కోసం ముందస్తు కనెక్షన్ <link> కనుగొనబడింది, కానీ బ్రౌజర్ ద్వారా ఉపయోగించబడలేదు. మీరు ``crossorigin`` లక్షణాన్ని సక్రమంగా ఉపయోగిస్తున్నారో లేదో తనిఖీ చేయండి."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "ముఖ్యమైన మూడవ పక్ష మూలాలకు ముందస్తు కనెక్షన్‌లను ఏర్పాటు చేయడానికి '`preconnect`' లేదా '`dns-prefetch`' వనరు సూచనలను జోడించడాన్ని పరిగణనలోకి తీసుకోండి. [మరింత తెలుసుకోండి](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "అవసరమైన మూలాలకు ముందుగా కనెక్ట్ చేయండి"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "'{preloadURL}' కోసం ముందే లోడ్ చేసిన ఒక <link> కనుగొనబడింది. కానీ దానిని బ్రౌజర్ ఉపయోగించలేదు. మీరు ``crossorigin`` లక్షణాన్ని సక్రమంగా ఉపయోగిస్తున్నారో లేదో తనిఖీ చేయండి."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "ప్రస్తుతం పేజీ లోడ్‌లో తర్వాత అభ్యర్ధించబడిన వనరులను పొందడాన్ని ప్రాధాన్యపరచడానికి '`<link rel=preload>`'ను ఉపయోగించడం పరిశీలించండి. [మరింత తెలుసుకోండి](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "కీలక అభ్యర్ధనలను ముందుగా లోడ్ చేయండి"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "మీ యాప్‌ను మొబైల్ స్క్రీన్‌ల కోసం ఆప్టిమైజ్ చేయడానికి '`<meta name=\"viewport\">`' ట్యాగ్‌ను జోడించండి. [మరింత తెలుసుకోండి](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "'`<meta name=\"viewport\">`' ట్యాగ్ ఏదీ కనుగొనబడలేదు"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "'`width`' లేదా '`initial-scale`'తో '`<meta name=\"viewport\">`' 'ట్యాగ్ ఏదీ లేదు"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "'`width`' లేదా '`initial-scale`'తో '`<meta name=\"viewport\">`' ట్యాగ్‌ను కలిగి ఉంది"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "'JavaScript' నిలిపివేయబడినప్పుడు, దాని గురించి తెలియజేసే ఏదైనా సమాచారం, అంటే యాప్‌ను ఉపయోగించాలంటే 'JavaScript' కలిగి ఉండాలని వినియోగదారుకు తెలియజేసే హెచ్చరిక లాంటి ఏదొక కంటెంట్ మీ యాప్‌లో ప్రదర్శించబడాలి. [మరింత తెలుసుకోండి](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "పేజీ విషయాంశంలో స్క్రిప్ట్‌లు ఏవైనా అందుబాటులో లేనప్పుడు, కొంత కంటెంట్‌ను రెండర్ చేయాలి."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "JavaScript అందుబాటులో లేనప్పుడు ప్రత్యామ్నాయ కంటెంట్‌ను అందించలేదు"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "JavaScript అందుబాటులో లేనప్పుడు, దాని గురించి తెలియజేసే కొంత కంటెంట్‌ను కలిగి ఉంది"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "మీరు ప్రోగ్రెసివ్ వెబ్ యాప్‌ను రూపొందిస్తున్నట్లయితే, సర్వీస్ వర్కర్‌ను ఉపయోగించడం పరిగణనలోకి తీసుకోండి. దీని వలన ఆఫ్‌లైన్‌లో కూడా మీ యాప్ పని చేయగలదు. [మరింత తెలుసుకోండి](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "ఆఫ్‌లైన్‌‌లో ఉన్నప్పుడు, ప్రస్తుత పేజీ '200' కోడ్‌తో స్పందించలేదు"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "ఆఫ్‌లైన్‌‌లో ఉన్నప్పుడు ప్రస్తుత పేజీ '200' కోడ్‌తో స్పందించింది"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "మీ పరీక్ష URL ({requested}) అన్నది \"{final}\"కు మళ్లించబడినందున పేజీ ఆఫ్‌లైన్‌లో లోడ్ కాలేకపోతుండవచ్చు. నేరుగా రెండవ URLను పరీక్షించడానికి ప్రయత్నించండి."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "మీ అప్లికేషన్‌లో ARIA వినియోగాన్ని మెరుగుపరచాడానికి ఇవి అవకాశాలుగా ఉపయోగపడతాయి, ఇది స్క్రీన్ రీడర్ లాంటి సహాయక సాంకేతిక పరిజ్ఞానం ఉపయోగించే వినియోగదారులకు మెరుగైన అనుభవాన్ని అందించవచ్చు."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "ఇవి, ఆడియో మరియు వీడియో కోసం ప్రత్యామ్నాయ వచనాన్ని అందించ‌గ‌ల అవకాశాలు. వినికిడి లేదా కంటిచూపులో సమస్యలు ఉన్న వినియోగదారులకు ఇది మెరుగైన అనుభవాన్ని అందించగలదు."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "ఆడియో మరియు వీడియో"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "సాధారణ యాక్సెసిబిలిటీ ఉత్తమ అభ్యాసాలను ఈ అంశాలు హైలైట్ చేస్తాయి."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "ఉత్తమ అభ్యాసాలు"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "[మీ వెబ్ యాప్ యొక్క యాక్సెసిబిలిటీని మెరుగుపరచగల](https://developers.google.com/web/fundamentals/accessibility) అవకాశాలను ఈ తనిఖీలు హైలైట్ చేస్తాయి. యాక్సెసిబిలిటీ సమస్యలలోని ఒక సబ్‌సెట్‌ను మాత్రమే ఆటోమేటిక్‌గా గుర్తించడం సాధ్యపడుతుంది, కనుక మాన్యువల్ పరీక్ష కూడా చేయాల్సిందిగా సిఫార్సు చేస్తున్నాము."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "ఆటోమేటెడ్ పరీక్ష సాధనం కవర్ చేయని ప్రాంతాలను ఈ అంశాలు పేర్కొంటాయి. [యాక్సెసిబిలిటీ సమీక్షను నిర్వహించడం](https://developers.google.com/web/fundamentals/accessibility/how-to-review) గురించి మా గైడ్‌లో మరింత తెలుసుకోండి."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "యాక్సెసిబిలిటీ"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "మీ కంటెంట్ స్పష్టతను మెరుగుపరచడానికి ఇవి అవకాశాలుగా ఉపయోగపడతాయి."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "కాంట్రాస్ట్"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "వివిధ లొకేల్‌లలో వినియోగదారుల ద్వారా మీ కంటెంట్ భావ వ్యక్తీకరణను మెరుగుపరచడానికి ఇవి అవకాశాలుగా ఉపయోగపడతాయి."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "అంతర్జాతీయీకరణ మరియు స్థానికీకరణ"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "మీ అప్లికేషన్‌లోని నియంత్రణల అర్థ విచారాలను మెరుగుపరచడానికి ఇవి అవకాశాలుగా ఉపయోగపడతాయి. స్క్రీన్ రీడర్ లాంటి సహాయక సాంకేతిక పరిజ్ఞాన వినియోగదారులకు ఇది మరింత మెరుగైన అనుభవాన్ని అందించవచ్చు."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "పేరు మరియు లేబుల్‌లు"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "ఇవి, మీ అప్లికేషన్‌లో కీబోర్డ్ నావిగేషన్‌ను మెరుగ‌ప‌ర‌చ‌గ‌ల అవ‌కాశాలు."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "నావిగేషన్"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "ఇవి, స్క్రీన్ రీడర్ వంటి సహాయకరమైన సాంకేతికతను ఉపయోగించి పట్టికను లేదా జాబితా డేటాను చదువుతున్నప్పుడు మెరుగైన అనుభవాన్ని అందించగల అవకాశాలు."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "పట్టికలు మరియు జాబితాలు"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "ఉత్తమ అభ్యాసాలు"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "పనితీరు బడ్జెట్‌లు అనేవి మీ సైట్ యొక్క పనితీరు ప్రమాణాలను నిర్దేశిస్తాయి."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "బడ్జెట్‌లు"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "మీ అప్లికేషన్ పనితీరు గురించి మరింత సమాచారం. ఈ సంఖ్యలు పనితీరు స్కోర్‌ను [నేరుగా ప్రభావితం చేయవు](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "సమస్య విశ్లేషణ"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "పిక్సెల్‌లు ఎంత వేగంగా స్క్రీన్ పై ప్రదర్శింపబడతాయి అనేది పనితీరులో అతి క్లష్టమైన అంశం. కీలక గణంకాలు: మొదటి కంటెంట్ సహిత పెయింట్, మొదటి అర్ధవంతమైన పెయింట్"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "మొదటి పెయింట్ మెరుగుదలలు"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "మీ పేజీని వేగంగా లోడ్ చేయడంలో ఈ సూచనలు సహాయపడగలవు. అవి పనితీరు స్కోర్‌పై [నేరుగా ప్రభావం](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) చూపవు."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "అవకాశాలు"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "గణాంకాలు"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "పేజీ ఎంత త్వరగా వీలైతే అంత త్వరగా ప్రతిస్పందించి, ఉపయోగించడానికి సిద్దంగా ఉండడానికి, మొత్తం లోడింగ్ అనుభవాన్ని మెరుగుపరచండి. కీలక గణాంకాలు: పేజీలో పూర్తి పరస్పర చర్యకు పట్టే సమయం, వేగం సూచిక"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "మొత్తం మొరుగుదలలు"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "పనితీరు"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "ఈ తనిఖీల ద్వారా ప్రోగ్రెసివ్ వెబ్ యాప్ అంశాలు ధృవీకరించబడతాయి. [మరింత తెలుసుకోండి](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "మౌళికమైన [PWA తనిఖీ జాబితా](https://developers.google.com/web/progressive-web-apps/checklist) ప్రకారం ఈ తనిఖీలను తప్పనిసరిగా నిర్వహించాలి, కానీ ఇవి Lighthouse ద్వారా ఆటోమేటిక్‌గా తనిఖీ చేయబడవు. ఇవి మీ స్కోర్‌పై ప్రభావం చూపవు, కానీ మీరు వీటిని మాన్యువల్‌గా అయినా ధృవీకరించడం ముఖ్యం."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "ప్రోగ్రెసివ్ వెబ్ యాప్"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "వేగమైనది, విశ్వసనీయమైనది"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "ఇన్‌స్టాల్ చేయదగినవి"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA ఆప్టిమైజ్ చేసినవి"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "శోధన ఇంజిన్ ఫలితాల ర్యాంకింగ్ కోసం మీ పేజీ ఆప్టిమైజ్ చేయబడినట్లు ఈ తనిఖీలు నిర్ధారిస్తాయి. మీ శోధన ర్యాంకింగ్‌పై ప్రభావం చూపగల ఈ అదనపు అంశాలను Lighthouse తనిఖీ చేయదు. [మరింత తెలుసుకోండి](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "అదనపు SEO ఉత్తమ అభ్యాసాలను తనిఖీ చేయడం కోసం మీ సైట్‌లో అదనపు వాలిడేటర్‌లను అమలు చేయండి."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "మీ యాప్ యొక్క కంటెంట్‌ను బాగా అర్థం చేసుకోవడానికి, crawlerలు ప్రారంభయ్యే విధంగా మీ HTMLను ఫార్మాట్ చేయండి."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "కంటెంట్ ఉత్తమ అభ్యాసాలు"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "శోధన ఫలితాలలో కనిపించేందుకు, crawlerలకు మీ యాప్ యాక్సెస్ అవసరం."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "క్రాలింగ్ మరియు అనుక్రమణ"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "వినియోగదారులు కంటెంట్ పేజీలను చదవడం కోసం స్క్రీన్‌పై రెండు వేళ్లను ఉంచి దగ్గరకు లేదా దూరానికి లాగుతూ లేదా దగ్గరగా జూమ్ చేసి ఇబ్బందిపడేలా కాకుండా మీ పేజీలు మొబైల్ అనుకూలంగా ఉన్నాయని నిర్థారించుకోండి. [మరింత తెలుసుకోండి](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "మొబైల్-అనుకూలం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "కాష్ TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "స్థానం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "పేరు"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "అభ్యర్థనలు"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "వనరు రకం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "పరిమాణం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "వెచ్చించిన సమయం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "బదిలీ పరిమాణం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "ఆదా చేయగల పరిమాణం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "ఆదా చేయగల వ్యవధి"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "ఆదా చేయగల పరిమాణం {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "ఆదా చేయగల వ్యవధి {wastedMs, number, milliseconds} మి.సెలు"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "పత్రం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "ఫాంట్"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "చిత్రం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "మీడియా"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} మి.సె"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "ఇతరం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "స్క్రిప్ట్"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} సె"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "స్టైల్‌షీట్"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "మూడవ పక్షం"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "మొత్తం"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "మీ పేజీ లోడ్ చేసే సమయంలో స్థితిగతిని రికార్డ్ చేస్తున్నప్పుడు ఏదో తప్పు జరిగింది. దయచేసి Lighthouseని మళ్లీ అమలు చేయండి. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "ప్రారంభ డీబగ్గర్ ప్రోటోకాల్ కనెక్షన్ నిరీక్షణ సమయం గడువు ముగిసింది."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "పేజీ లోడ్ సమయంలో Chrome ఎలాంటి స్క్రీన్‌షాట్‌లను సేకరించలేదు. దయచేసి పేజీలో కనిపించే కంటెంట్ ఉందని నిర్ధారించుకుని, ఆపై Lighthouseని తిరిగి అమలు చేయడం ప్రయత్నించండి. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS సర్వర్‌లు అందించిన డొమైన్‌ని పరిష్కరించలేవు."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "అవసరమైన '{artifactName}' గ్యాదరర్ ఒక ఎర్రర్‌ను ఎదుర్కొంది: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "అంతర్గత Chrome ఎర్రర్ ఏర్పడింది. దయచేసి Chromeని పునఃప్రారంభించి, Lighthouseని తిరిగి అమలు చేయడం ప్రయత్నించండి."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "అవసరమైన '{artifactName}' గ్యాదరర్ అమలు కాలేదు."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "మీరు అభ్యర్థించిన పేజీని Lighthouse విశ్వసనీయ రీతిలో పేజీని లోడ్ చేయలేకపోయింది. మీరు సరైన URLని పరీక్షిస్తున్నారని, సర్వర్ అన్ని అభ్యర్థనలకు సరిగ్గా ప్రతిస్పందిస్తుందని నిర్ధారించుకోండి."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "పేజీ ప్రతిస్పందించడం ఆపివేసినందున, మీరు అభ్యర్థించిన URLని విశ్వసనీయ రీతిలో Lighthouse లోడ్ చేయలేకపోయింది."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "మీరు అందించిన URLకు చెల్లుబాటయ్యే భద్రత సర్టిఫికెట్ లేదు. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "మధ్యలో వచ్చే సందేశ బ్యానర్‌తో పేజీ లోడ్ కావడాన్ని Chrome నిరోధించింది. మీరు సరైన URLను పరీక్షిస్తున్నారని, సర్వర్ అన్ని అభ్యర్థనలకు సరిగ్గా ప్రతిస్పందిస్తోందని నిర్ధారించుకోండి."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "మీరు అభ్యర్థించిన పేజీని Lighthouse విశ్వసనీయ రీతిలో లోడ్ చేయలేకపోయింది. మీరు సరైన URLను పరీక్షిస్తున్నారని, సర్వర్ అన్ని అభ్యర్థనలకు సరిగ్గా ప్రతిస్పందిస్తోందని నిర్ధారించుకోండి. (వివరాలు: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "మీరు అభ్యర్థించిన పేజీని Lighthouse విశ్వసనీయ రీతిలో లోడ్ చేయలేకపోయింది. మీరు సరైన URLను పరీక్షిస్తున్నారని, సర్వర్ అన్ని అభ్యర్థనలకు సరిగ్గా ప్రతిస్పందిస్తోందని నిర్ధారించుకోండి. (స్థితి కోడ్: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "మీ పేజీ లోడ్ కావడానికి చాలా ఎక్కువ సమయం పట్టింది. మీ పేజీ లోడ్ సమయం తగ్గించడానికి దయచేసి నివేదికలో ఉన్న అవకాశాలను అనుసరించి, ఆపై Lighthouseను తిరిగి అమలు చేయడానికి ప్రయత్నించండి. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools ప్రోటోకాల్ ప్రతిస్పందన కోసం వేచి ఉండటం వలన కేటాయించిన సమయాన్ని దాటిపోయింది. (పద్ధతి: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "వనరు కంటెంట్‌ను పొందడంలో కేటాయించిన సమయం దాటిపోయింది"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "మీరు అందించిన URL చెల్లనిదిగా కనిపిస్తోంది."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "ఆడిట్‌లను చూపించండి"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "ప్రారంభ నావిగేషన్"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "గరిష్ట క్లిష్టమైన మార్గ ప్రతిస్పందన సమయం:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "ఎర్రర్ ఏర్పడింది!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "నివేదిక ఎర్రర్: ఆడిట్ సమాచారం లేదు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "ల్యాబ్ డేటా"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "అనుకరణ మొబైల్ నెట్‌వర్క్‌లో ప్రస్తుత పేజీకి సంబంధించిన [Lighthouse](https://developers.google.com/web/tools/lighthouse/) విశ్లేషణ. విలువలు కేవలం అంచనా మాత్రమే, ఇవి మారే అవకాశం ఉంది."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "మాన్యువల్‌గా తనిఖీ చేయవలసిన అదనపు అంశాలు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "వర్తించదు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "అవకాశం"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "అంచనా వేసిన పొదుపులు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "ఉత్తీర్ణత సాధించిన ఆడిట్‌లు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "స్నిప్పెట్‌ను కుదించు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "స్నిప్పెట్‌ను విస్తరించు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "3వ పక్షం వనరులను చూపు"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Lighthouse యొక్క ఈ అమలును ప్రభావితం చేసిన సమస్యలు ఉన్నాయి:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "విలువలు కేవలం అంచనా మాత్రమే, ఇవి మారే అవకాశం ఉంది. పనితీరు స్కోర్ [కేవలం ఈ కొలమానాల ఆధారంగా అందించబడుతుంది](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "ఆడిట్‌లు పాస్ అయ్యాయి కానీ హెచ్చరికలు ఉన్నాయి"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "హెచ్చరికలు: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "మీ GIFను HTML5 వీడియోగా పొందుపరచగల సౌలభ్యం అందించే సేవకు అప్‌లోడ్ చేయడానికి ప్రయత్నించండి."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "ఏవైనా ఆఫ్‌స్క్రీన్ చిత్రాలు ఉంటే, వాటిని మినహాయించగల సామర్థ్యం కలిగి ఉండే లేదా ఆ కార్యశీలతను అందించే థీమ్‌కు మార్చగలిగే [లేజీ-లోడ్ WordPress ప్లగ్ఇన్‌](https://wordpress.org/plugins/search/lazy+load/)ను ఇన్‌స్టాల్ చేసుకోండి. అలాగే, [AMP ప్లగ్ఇన్‌](https://wordpress.org/plugins/amp/)ను ఉపయోగించడం కూడా పరిశీలించండి."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[కీలకమైన ఆస్తులను ఇన్‌లైన్‌లో ఉంచడానికి](https://wordpress.org/plugins/search/critical+css/) లేదా [తక్కువ ప్రాముఖ్యత ఉన్న వనరులను మినహాయించడానికి](https://wordpress.org/plugins/search/defer+css+javascript/) మీకు సహాయపడగల అనేక WordPress ప్లగ్ఇన్‌లు ఉన్నాయి. ఈ ప్లగ్ఇన్‌ల ద్వారా అందించబడే ఆప్టిమైజేషన్‌లు మీ థీమ్ లేదా ప్లగ్ఇన్‌ల ఫీచర్‌లను విడగొట్టవచ్చని గుర్తుంచుకోండి, దీని వలన మీరు కోడ్‌కు మార్పులు చేయాల్సి రావచ్చు."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "థీమ్‌లు, ప్లగ్ఇన్‌లు, సర్వర్ లక్షణాలన్నీ కూడా సర్వర్ ప్రతిస్పందన సమయాన్ని ప్రభావితం చేస్తాయి. మరింత ఆప్టిమైజ్ చేయబడిన థీమ్‌ను కనుగొనడానికి, చాలా జాగ్రత్తగా ఆప్టిమైజేషన్ ప్లగ్ఇన్‌ను ఎంచుకోవడానికి మరియు/లేదా మీ సర్వర్‌ను అప్‌గ్రేడ్ చేయడానికి ప్రయత్నించండి."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "ఇవ్వబడిన పేజీలో చూపబడే పోస్ట్‌ల సంఖ్యను తగ్గించడం, మీ పొడవైన పోస్ట్‌లను బహుళ పేజీలుగా విడగొట్టడం లేదా మందకొడి లోడింగ్ వ్యాఖ్యల కోసం ప్లగ్ఇన్‌ను ఉపయోగించడం ద్వారా (అంటే, మరిన్ని ట్యాగ్ ద్వారా) మీ పోస్ట్ జాబితాలలో సారాంశాలను చూపడానికి ప్రయత్నించండి."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "అనేక '[WordPress ప్లగ్ఇన్‌లు](https://wordpress.org/plugins/search/minify+css/)' మీ శైలులను క్రమపరచడం, చిన్నవిగా చేయడం, కుదించడం ద్వారా మీ సైట్‌ను మరింత వేగవంతం చేయవచ్చు. వీలైతే, ఈ కనిష్ఠీకరణను ముందుగానే నిర్వహించేలా కూడా మీరు ఒక బిల్డ్ ప్రాసెస్‌ను ఉపయోగించవచ్చు."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "అనేక [WordPress ప్లగ్ఇన్‌లు](https://wordpress.org/plugins/search/minify+javascript/) మీ స్క్రిప్ట్‌లను క్రమపరచడం, చిన్నవిగా చేయడం, కుదించడం ద్వారా మీ సైట్‌ను మరింత వేగవంతం చేయవచ్చు. వీలైతే, ఈ కనిష్ఠీకరణను ముందుగానే నిర్వహించేలా కూడా మీరు ఒక బిల్డ్ ప్రాసెస్‌ను ఉపయోగించడం పరిగణించవచ్చు."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "మీ పేజీలో ఉపయోగించని CSSను లోడ్ చేస్తున్న '[WordPress ప్లగ్ఇన్‌‌ల](https://wordpress.org/plugins/)' సంఖ్యను తగ్గించడం లేదా మార్చడాన్ని పరిశీలించండి. అదనపు CSSను జోడించే ప్లగ్ఇన్‌లను గుర్తించడానికి, Chrome DevToolsలో '[కోడ్ కవరేజీ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)' అమలు చేయడానికి ప్రయత్నించండి. అందుకు కారణమైన థీమ్/ప్లగ్ఇన్‌ను స్టైల్‌షీట్‌లోని URL నుండి మీరు గుర్తించవచ్చు. కోడ్ కవరేజ్‌లో ఎక్కువ ఎరుపు రంగు కలిగి ఉన్న జాబితాలో అనేక స్టైల్‌షీట్‌లను కలిగి ఉన్న ప్లగ్ఇన్‌లను వెతకండి. నిజంగా ప్లగ్ఇన్‌ను ఆ పేజీలో ఉపయోగించినప్పుడు మాత్రమే స్టైల్‌షీట్‌కు జత చేయాలి."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "మీ పేజీలో ఉపయోగించని JavaScriptను లోడ్ చేస్తున్న '[WordPress ప్లగ్ఇన్‌‌ల](https://wordpress.org/plugins/)' సంఖ్యను తగ్గించడం లేదా మార్చడాన్ని పరిశీలించండి. అదనపు JSను జోడించే ప్లగ్ఇన్‌లను గుర్తించడానికి, Chrome DevToolsలో '[కోడ్ కవరేజీ](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)' అమలు చేయడానికి ప్రయత్నించండి. అందుకు కారణమైన థీమ్/ప్లగ్ఇన్‌ను స్క్రిప్ట్ యొక్క URL నుండి మీరు గుర్తించవచ్చు. కోడ్ కవరేజ్‌లో ఎక్కువ ఎరుపు రంగు కలిగి ఉన్న జాబితాలో అనేక స్క్రిప్ట్‌లను కలిగి ఉన్న ప్లగ్ఇన్‌లను వెతకండి. నిజంగా ప్లగ్ఇన్‌ను ఆ పేజీలో ఉపయోగించినప్పుడు మాత్రమే స్క్రిప్ట్‌కు జత చేయాలి."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPressలో బ్రౌజర్ కాష్ విధానం](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching) గురించి చదవండి."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "నాణ్యత తగ్గకుండా మీ చిత్రాలను కుదించే [చిత్రం ఆప్టిమైజేషన్ WordPress ప్లగ్ఇన్‌](https://wordpress.org/plugins/search/optimize+images/)ను ఉపయోగించడం పరిశీలించండి."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "అవసరమైన చిత్ర పరిమాణాలు అందుబాటులో ఉన్నాయో లేదో నిర్ధారించుకోవడానికి చిత్రాలను నేరుగా [మీడియా లైబ్రరీ](https://codex.wordpress.org/Media_Library_Screen) ద్వారా అప్‌లోడ్ చేయండి. ఆపై వాటిని మీడియా లైబ్రరీ నుండి చొప్పించండి లేదా అనుకూలమైన చిత్ర పరిమాణాలు ఉపయోగించబడ్డాయో లేదో నిర్ధారించుకోవడానికి (ప్రతిస్పందనాత్మక బ్రేక్ పాయింట్‌లు కలిగి ఉండే వాటికి కూడా) చిత్ర విడ్జెట్‌ను ఉపయోగించండి. కొలతలు వాటి వినియోగానికి తగినట్లుగా ఉంటే తప్పితే, '`Full Size`' చిత్రాలను వినియోగించడం నివారించండి. [మరింత తెలుసుకోండి](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "మీరు మీ వెబ్ సర్వర్ కన్ఫిగరేషన్‌లో వచన కుదింపును ప్రారంభించవచ్చు."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "మీరు అప్‌లోడ్ చేసిన చిత్రాలను అనుకూలమైన ఫార్మాట్‌లలోకి ఆటోమేటిక్‌గా మార్చే [ప్లగ్ఇన్](https://wordpress.org/plugins/search/convert+webp/) లేదా సేవను ఉపయోగించడం పరిశీలించండి."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/th.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/th.json
new file mode 100644
index 00000000000..d75623e400e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/th.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "คีย์การเข้าถึงให้ผู้ใช้โฟกัสที่ส่วนหนึ่งของหน้าได้อย่างรวดเร็ว คีย์การเข้าถึงแต่ละรายการต้องไม่ซ้ำกันเพื่อให้ไปยังส่วนต่างๆ ได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/accesskeys/)"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "ค่า `[accesskey]` ซ้ำกัน"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "ค่า `[accesskey]` ไม่ซ้ำกัน"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "`role` ของ ARIA แต่ละรายการรองรับชุดย่อยของแอตทริบิวต์ `aria-*` ที่เจาะจง หากรายการเหล่านี้ไม่ตรงกันจะทำให้แอตทริบิวต์ `aria-*` ไม่ถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-allowed-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "แอตทริบิวต์ `[aria-*]` ไม่ตรงกับบทบาทของตน"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "แอตทริบิวต์ `[aria-*]` ตรงกับบทบาทของตน"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "บทบาท ARIA บางบทบาทกำหนดให้มีแอตทริบิวต์ที่อธิบายสถานะขององค์ประกอบให้โปรแกรมอ่านหน้าจอทราบ [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-required-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` ไม่มีแอตทริบิวต์ `[aria-*]` ทั้งหมดที่จำเป็น"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` มีแอตทริบิวต์ `[aria-*]` ที่จำเป็นทั้งหมด"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "บทบาท ARIA ระดับบนสุดบางบทบาทต้องมีบทบาทย่อยที่เจาะจงเพื่อใช้ฟังก์ชันการช่วยเหลือพิเศษตามวัตถุประสงค์ [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-required-children/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "องค์ประกอบที่มี ARIA `[role]` ที่กำหนดให้องค์ประกอบย่อยต้องมี `[role]` ที่เฉพาะเจาะจงขาดองค์ประกอบย่อยที่จำเป็นดังกล่าวบางส่วนหรือทั้งหมด"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "องค์ประกอบที่มี ARIA `[role]` ที่กำหนดให้องค์ประกอบย่อยต้องมี `[role]` ที่เฉพาะเจาะจงนั้นมีองค์ประกอบย่อยที่จำเป็นทั้งหมด"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "บทบาท ARIA ย่อยบางบทบาทต้องอยู่ในบทบาทระดับบนสุดที่เจาะจงเพื่อให้ใช้ฟังก์ชันการช่วยเหลือพิเศษตามวัตถุประสงค์ได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-required-parent/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` ไม่ได้อยู่ในองค์ประกอบระดับบนสุดที่กำหนด"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` อยู่ในองค์ประกอบระดับบนสุดที่กำหนด"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "บทบาท ARIA ต้องมีค่าที่ถูกต้องเพื่อใช้ฟังก์ชันการช่วยเหลือพิเศษตามวัตถุประสงค์ [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-roles/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "ค่า `[role]` ไม่ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "ค่า `[role]` ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "เทคโนโลยีอำนวยความสะดวก เช่น โปรแกรมอ่านหน้าจอ จะตีความแอตทริบิวต์ ARIA ที่มีค่าไม่ถูกต้องไม่ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-valid-attr-value/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "แอตทริบิวต์ `[aria-*]` ไม่มีค่าที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "แอตทริบิวต์ `[aria-*]` มีค่าที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "เทคโนโลยีอำนวยความสะดวก เช่น โปรแกรมอ่านหน้าจอ จะตีความแอตทริบิวต์ ARIA ที่มีชื่อไม่ถูกต้องไม่ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/aria-valid-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "แอตทริบิวต์ `[aria-*]` ไม่ถูกต้องหรือสะกดผิด"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "แอตทริบิวต์ `[aria-*]` ถูกต้องและสะกดถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "คำบรรยายวิดีโอช่วยให้คนหูหนวกหรือผู้ใช้ที่มีความบกพร่องทางการได้ยินเข้าใจองค์ประกอบเสียง โดยให้ข้อมูลสำคัญ เช่น ผู้ที่กำลังพูด สิ่งที่กำลังพูด และข้อมูลอื่นๆ ที่ไม่ใช่เสียงพูด [ดูข้อมูลเพิ่มเติม](https://web.dev/audio-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "องค์ประกอบ `<audio>` ไม่มีองค์ประกอบ `<track>` ที่มี`[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "องค์ประกอบ `<audio>` มีองค์ประกอบ `<track>` ที่มี `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "องค์ประกอบที่ไม่ผ่านการตรวจสอบ"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "เมื่อปุ่มไม่มีชื่อสำหรับการช่วยเหลือพิเศษ โปรแกรมอ่านหน้าจอจะอ่านปุ่มนั้นว่า \"ปุ่ม\" ซึ่งทำให้ผู้ที่ต้องใช้โปรแกรมอ่านหน้าจอใช้ปุ่มดังกล่าวไม่ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/button-name/)"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "ปุ่มต่างๆ ไม่มีชื่อสำหรับการช่วยเหลือพิเศษ"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "ปุ่มต่างๆ มีชื่อสำหรับการช่วยเหลือพิเศษ"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "การเพิ่มวิธีข้ามผ่านเนื้อหาที่ซ้ำกันช่วยให้ผู้ใช้แป้นพิมพ์ไปยังส่วนต่างๆ ของหน้าได้อย่างมีประสิทธิภาพมากขึ้น [ดูข้อมูลเพิ่มเติม](https://web.dev/bypass/)"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "หน้าเว็บไม่มีส่วนหัว ลิงก์การข้าม หรือภูมิภาคของจุดสังเกต"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "หน้าเว็บมีส่วนหัว ลิงก์การข้าม หรือภูมิภาคของจุดสังเกต"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "ข้อความคอนทราสต์ต่ำมักทำให้ผู้ใช้จำนวนมากอ่านได้ยากหรืออ่านไม่ได้เลย [ดูข้อมูลเพิ่มเติม](https://web.dev/color-contrast/)"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "สีพื้นหลังและสีพื้นหน้ามีอัตราส่วนคอนทราสต์ไม่เพียงพอ"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "สีพื้นหลังและสีพื้นหน้ามีอัตราส่วนคอนทราสต์ที่เพียงพอ"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "เมื่อมีการทำเครื่องหมายรายการคำจำกัดความอย่างไม่ถูกต้อง โปรแกรมอ่านหน้าจออาจสร้างเอาต์พุตที่ทำให้สับสนหรือไม่แม่นยำ [ดูข้อมูลเพิ่มเติม](https://web.dev/definition-list/)"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` ไม่ได้มีเพียงกลุ่ม `<dt>` และ `<dd>` หรือองค์ประกอบ `<script>` หรือ `<template>` ที่เรียงลำดับอย่างถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` มีเพียงกลุ่ม `<dt>` และ `<dd>` องค์ประกอบ `<script>` หรือ `<template>` ที่เรียงลำดับอย่างถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "รายการย่อยของคำจำกัดความ (`<dt>` และ `<dd>`) ต้องรวมอยู่ในองค์ประกอบ `<dl>` ระดับบนสุดเพื่อดูแลให้โปรแกรมอ่านหน้าจออ่านได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/dlitem/)"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "รายการย่อยของคำจำกัดความไม่ได้รวมอยู่ในองค์ประกอบ `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "รายการย่อยของคำจำกัดความรวมอยู่ในองค์ประกอบ `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "ชื่อช่วยให้ผู้ใช้โปรแกรมอ่านหน้าจอทราบถึงภาพรวมของหน้า และผู้ใช้เครื่องมือค้นหาจะดูความเกี่ยวข้องของหน้ากับการค้นหาของตนจากชื่อเป็นหลัก [ดูข้อมูลเพิ่มเติม](https://web.dev/document-title/)"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "เอกสารไม่มีองค์ประกอบ `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "เอกสารมีองค์ประกอบ `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "ค่าของแอตทริบิวต์รหัสต้องไม่ซ้ำกันเพื่อป้องกันไม่ให้เทคโนโลยีอำนวยความสะดวกมองข้ามอินสแตนซ์อื่นๆ [ดูข้อมูลเพิ่มเติม](https://web.dev/duplicate-id/)"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "แอตทริบิวต์ `[id]` ในหน้าเว็บซ้ำกัน"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "แอตทริบิวต์ `[id]` ในหน้าเว็บไม่ซ้ำกัน"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "ผู้ใช้โปรแกรมอ่านหน้าจอต้องใช้ชื่อเฟรมเพื่ออธิบายเนื้อหาของเฟรม [ดูข้อมูลเพิ่มเติม](https://web.dev/frame-title/)"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "องค์ประกอบ `<frame>` หรือ `<iframe>` ไม่มีชื่อ"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "องค์ประกอบ `<frame>` หรือ `<iframe>` มีชื่อ"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "หากหน้าเว็บไม่ได้ระบุแอตทริบิวต์ lang โปรแกรมอ่านหน้าจอจะถือว่าหน้าดังกล่าวใช้ภาษาเริ่มต้นที่ผู้ใช้เลือกเมื่อตั้งค่าโปรแกรมอ่านหน้าจอ หากที่จริงแล้วหน้าดังกล่าวไม่ได้ใช้ภาษาเริ่มต้น โปรแกรมอ่านหน้าจออาจอ่านข้อความในหน้าได้ไม่ถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/html-has-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "องค์ประกอบ `<html>` ไม่มีแอตทริบิวต์ `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "องค์ประกอบ `<html>` มีแอตทริบิวต์ `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "การระบุ[ภาษา BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ที่ถูกต้องช่วยให้โปรแกรมอ่านหน้าจออ่านข้อความได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/html-lang-valid/)"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "องค์ประกอบ `<html>` ไม่มีค่าที่ถูกต้องสำหรับแอตทริบิวต์ `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "องค์ประกอบ `<html>` มีค่าที่ถูกต้องสำหรับแอตทริบิวต์ `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "องค์ประกอบเพื่อการให้ข้อมูลควรมีข้อความสำรองที่สั้นกระชับและสื่อความหมาย การใช้แอตทริบิวต์ Alt ที่ว่างเปล่าจะเป็นการเพิกเฉยต่อองค์ประกอบเพื่อการตกแต่ง [ดูข้อมูลเพิ่มเติม](https://web.dev/image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "องค์ประกอบรูปภาพไม่มีแอตทริบิวต์ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "องค์ประกอบรูปภาพมีแอตทริบิวต์ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "เมื่อมีการใช้รูปภาพเป็นปุ่ม `<input>` การระบุข้อความสำรองจะช่วยให้ผู้ใช้โปรแกรมอ่านหน้าจอเข้าใจวัตถุประสงค์ของปุ่มได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/input-image-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "องค์ประกอบ `<input type=\"image\">` ไม่มีข้อความ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "องค์ประกอบ `<input type=\"image\">` มีข้อความ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "ป้ายกำกับช่วยดูแลให้เทคโนโลยีอำนวยความสะดวกอย่างเช่น โปรแกรมอ่านหน้าจอ อ่านส่วนควบคุมฟอร์มได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/label/)"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "องค์ประกอบฟอร์มไม่มีป้ายกำกับที่เชื่อมโยง"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "องค์ประกอบฟอร์มมีป้ายกำกับที่เชื่อมโยงอยู่"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "ตารางที่ใช้สำหรับการออกแบบต้องไม่มีองค์ประกอบข้อมูล เช่น องค์ประกอบ th หรือคำอธิบายภาพ หรือแอตทริบิวต์สรุป เพราะอาจสร้างความสับสนระหว่างการใช้งานของผู้ใช้โปรแกรมอ่านหน้าจอ [ดูข้อมูลเพิ่มเติม](https://web.dev/layout-table/)"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "องค์ประกอบ `<table>` สำหรับการนำเสนอไม่หลีกเลี่ยงการใช้ `<th>`, `<caption>` หรือแอตทริบิวต์ `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "องค์ประกอบ `<table>` สำหรับการนำเสนอหลีกเลี่ยงการใช้ `<th>`, `<caption>` หรือแอตทริบิวต์ `[summary]`"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "ข้อความลิงก์ (และข้อความสำรองสำหรับรูปภาพเมื่อใช้เป็นลิงก์) ที่แยกแยะได้ ไม่ซ้ำกัน และโฟกัสได้ ช่วยปรับปรุงประสบการณ์การไปยังส่วนต่างๆ สำหรับผู้ใช้โปรแกรมอ่านหน้าจอ [ดูข้อมูลเพิ่มเติม](https://web.dev/link-name/)"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "ลิงก์ไม่มีชื่อที่แยกแยะได้"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "ลิงก์มีชื่อที่แยกแยะได้"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "โปรแกรมอ่านหน้าจอมีวิธีเฉพาะในการอ่านรายการ การดูแลให้รายการมีโครงสร้างที่ถูกต้องช่วยโปรแกรมอ่านหน้าจอในการอ่านเนื้อหา [ดูข้อมูลเพิ่มเติม](https://web.dev/list/)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "รายการไม่ได้มีแต่องค์ประกอบ `<li>` และองค์ประกอบที่รองรับสคริปต์ (`<script>` และ`<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "รายการมีเพียงองค์ประกอบ `<li>` และองค์ประกอบที่รองรับสคริปต์ (`<script>` และ `<template>`)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "โปรแกรมอ่านหน้าจอกำหนดให้รายการย่อย (`<li>`) อยู่ใน `<ul>` หรือ `<ol>` ระดับบนสุดเพื่อให้อ่านได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/listitem/)"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "รายการย่อย (`<li>`) ไม่ได้อยู่ภายในองค์ประกอบระดับบนสุด `<ul>` หรือ `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "รายการย่อย (`<li>`) อยู่ในองค์ประกอบระดับบนสุด `<ul>` หรือ `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "ผู้ใช้ไม่ได้คาดหวังให้หน้าเว็บรีเฟรชโดยอัตโนมัติ และการรีเฟรชหน้าเว็บจะย้ายโฟกัสกลับไปที่ด้านบนของหน้า ซึ่งอาจทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สับสนหรือน่าหงุดหงิด [ดูข้อมูลเพิ่มเติม](https://web.dev/meta-refresh/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "เอกสารใช้ `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "เอกสารนี้ไม่ได้ใช้ `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "การปิดใช้การซูมจะเป็นปัญหาสำหรับผู้ใช้ที่มีสายตาเลือนรางซึ่งต้องใช้การขยายหน้าจอเพื่อให้ดูเนื้อหาของหน้าเว็บได้อย่างชัดเจน [ดูข้อมูลเพิ่มเติม](https://web.dev/meta-viewport/)"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "มีการใช้ `[user-scalable=\"no\"]` ในองค์ประกอบ `<meta name=\"viewport\">`หรือแอตทริบิวต์ `[maximum-scale]` น้อยกว่า 5"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "ไม่มีการใช้ `[user-scalable=\"no\"]` ในองค์ประกอบ `<meta name=\"viewport\">` และแอตทริบิวต์ `[maximum-scale]` ไม่น้อยกว่า 5"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "โปรแกรมอ่านหน้าจอแปลเนื้อหาที่ไม่ใช่ข้อความไม่ได้ การเพิ่มข้อความแสดงแทนลงในองค์ประกอบ `<object>` ช่วยโปรแกรมอ่านหน้าจอถ่ายทอดความหมายให้แก่ผู้ใช้ [ดูข้อมูลเพิ่มเติม](https://web.dev/object-alt/)"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "องค์ประกอบ `<object>` ไม่มีข้อความ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "องค์ประกอบ `<object>` มีข้อความ `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "ค่าที่มากกว่า 0 หมายความว่ามีการจัดเรียงการนำทางที่ชัดเจน แม้ว่าการทำงานนี้จะไม่มีปัญหาในทางเทคนิค แต่มักก่อให้เกิดประสบการณ์การใช้งานที่น่าหงุดหงิดสำหรับผู้ใช้เทคโนโลยีอำนวยความสะดวก [ดูข้อมูลเพิ่มเติม](https://web.dev/tabindex/)"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "องค์ประกอบบางอย่างมีค่า `[tabindex]` มากกว่า 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "ไม่มีองค์ประกอบที่มีค่า `[tabindex]` มากกว่า 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "โปรแกรมอ่านหน้าจอมีฟีเจอร์ที่ช่วยให้ไปยังส่วนต่างๆ ของตารางได้ง่ายขึ้น การดูแลให้เซลล์ `<td>` ที่ใช้แอตทริบิวต์ `[headers]` อ้างอิงถึงเซลล์อื่นๆ ในตารางเดียวกันเท่านั้นอาจช่วยปรับปรุงประสบการณ์สำหรับผู้ใช้โปรแกรมอ่านหน้าจอ [ดูข้อมูลเพิ่มเติม](https://web.dev/td-headers-attr/)"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "เซลล์ในองค์ประกอบ `<table>` ที่ใช้แอตทริบิวต์ `[headers]` อ้างอิงถึง `id` ขององค์ประกอบที่ไม่พบในตารางเดียวกันนี้"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "เซลล์ในองค์ประกอบ `<table>` ที่ใช้แอตทริบิวต์ `[headers]` อ้างอิงถึงเซลล์ของตารางภายในตารางเดียวกัน"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "โปรแกรมอ่านหน้าจอมีฟีเจอร์ที่ช่วยให้ไปยังส่วนต่างๆ ของตารางได้ง่ายขึ้น การดูแลให้ส่วนหัวของตารางอ้างอิงถึงชุดเซลล์บางชุดอยู่เสมออาจช่วยปรับปรุงประสบการณ์สำหรับผู้ใช้โปรแกรมอ่านหน้าจอ [ดูข้อมูลเพิ่มเติม](https://web.dev/th-has-data-cells/)"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "องค์ประกอบ `<th>` และองค์ประกอบที่มี `[role=\"columnheader\"/\"rowheader\"]` ไม่มีเซลล์ข้อมูลที่องค์ประกอบอธิบาย"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "องค์ประกอบ `<th>` และองค์ประกอบที่มี `[role=\"columnheader\"/\"rowheader\"]` มีเซลล์ข้อมูลที่องค์ประกอบอธิบาย"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "การระบุ[ภาษา BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question) ที่ถูกต้องในองค์ประกอบต่างๆ ช่วยดูแลให้โปรแกรมอ่านหน้าจอออกเสียงข้อความได้อย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/valid-lang/)"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "แอตทริบิวต์ `[lang]` ไม่มีค่าที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "แอตทริบิวต์ `[lang]` มีค่าที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "เมื่อวิดีโอมีคำอธิบายภาพ คนหูหนวกและผู้ใช้ที่มีความบกพร่องทางการได้ยินจะเข้าถึงข้อมูลของวิดีโอได้ง่ายขึ้น [ดูข้อมูลเพิ่มเติม](https://web.dev/video-caption/)"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "องค์ประกอบ `<video>` ไม่มีองค์ประกอบ `<track>` ที่มี `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "องค์ประกอบ `<video>` มีองค์ประกอบ `<track>` ที่มี `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "คำอธิบายเสียงให้ข้อมูลเกี่ยวข้องสำหรับวิดีโอที่สื่อสารผ่านบทพูดไม่ได้ เช่น สีหน้าและฉากต่างๆ [ดูข้อมูลเพิ่มเติม](https://web.dev/video-description/)"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "องค์ประกอบ `<video>` ไม่มีองค์ประกอบ `<track>` ที่มี `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "องค์ประกอบ `<video>` มีองค์ประกอบ `<track>` ที่มี `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "ให้ระบุ `apple-touch-icon` เพื่อให้ปรากฏใน iOS ได้อย่างดีที่สุดเมื่อผู้ใช้เพิ่ม Progressive Web App ลงในหน้าจอหลัก โดยต้องชี้ไปที่สี่เหลี่ยมจตุรัสแบบไม่โปร่งใสขนาด 192 พิกเซล (หรือ 180 พิกเซล) รูปแบบ PNG [ดูข้อมูลเพิ่มเติม](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "ไม่ได้ให้ `apple-touch-icon` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` ไม่อัปเดต แนะนำให้ใช้ `apple-touch-icon` จะดีกว่า"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "มี `apple-touch-icon` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "ส่วนขยาย Chrome ส่งผลเสียต่อประสิทธิภาพในการโหลดของหน้านี้ ลองตรวจสอบหน้าในโหมดไม่ระบุตัวตนหรือจากโปรไฟล์ Chrome ที่ไม่มีส่วนขยาย"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "การประเมินสคริปต์"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "การแยกวิเคราะห์สคริปต์"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "เวลา CPU รวม"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "พิจารณาลดเวลาที่ใช้ในการแยกวิเคราะห์ แปลโปรแกรม และดำเนินการกับ JS การส่งเปย์โหลด JS ปริมาณน้อยอาจช่วยในเรื่องนี้ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/bootup-time)"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "ลดเวลาในการดำเนินการกับ JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "เวลาในการดำเนินการกับ JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "GIF ขนาดใหญ่ไม่มีประสิทธิภาพในการแสดงเนื้อหาภาพเคลื่อนไหว พิจารณาใช้วิดีโอ MPEG4/WebM สำหรับภาพเคลื่อนไหวและใช้ PNG/WebP สำหรับภาพนิ่งแทน GIF เพื่อประหยัดไบต์ของเครือข่าย [ดูข้อมูลเพิ่มเติม](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "ใช้รูปแบบวิดีโอสำหรับเนื้อหาภาพเคลื่อนไหว"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "พิจารณาโหลดรูปภาพนอกหน้าจอและรูปภาพที่ซ่อนไว้แบบ Lazy Loading หลังจากที่ทรัพยากรที่สำคัญทั้งหมดโหลดเสร็จแล้วเพื่อลดเวลาในการโต้ตอบ [ดูข้อมูลเพิ่มเติม](https://web.dev/offscreen-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "เลื่อนเวลาโหลดรูปภาพนอกจอภาพ"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "ทรัพยากรบล็อก First Paint ของหน้าเว็บอยู่ พิจารณาแสดง JS/CSS ที่สำคัญในหน้าและเลื่อนเวลาแสดง JS/สไตล์ที่ไม่สำคัญทั้งหมดออกไป [ดูข้อมูลเพิ่มเติม](https://web.dev/render-blocking-resources)"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "กำจัดทรัพยากรที่บล็อกการแสดงผล"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "เปย์โหลดปริมาณมากของเครือข่ายทำให้ผู้ใช้เสียค่าใช้จ่ายสูงและสัมพันธ์กับเวลาการโหลดนานเป็นอย่างมาก [ดูข้อมูลเพิ่มเติม](https://web.dev/total-byte-weight)"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "ขนาดรวมเดิมคือ {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "หลีกเลี่ยงเปย์โหลดเครือข่ายปริมาณมาก"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "หลีกเลี่ยงเปย์โหลดเครือข่ายปริมาณมาก"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "การลดขนาดไฟล์ CSS ช่วยลดขนาดเปย์โหลดของเครือข่ายได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/unminified-css)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "ลดขนาด CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "การลดขนาดไฟล์ JavaScript ช่วยลดขนาดเปย์โหลดและเวลาในการแยกวิเคราะห์สคริปต์ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/unminified-javascript)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "ลดขนาด JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "นำกฎที่ไม่มีผลแล้วออกจากสไตล์ชีตและเลื่อนเวลาการโหลด CSS ที่ไม่ได้ใช้สำหรับเนื้อหาครึ่งหน้าบนเพื่อลดจำนวนไบต์ที่ไม่จำเป็นที่กิจกรรมเครือข่ายใช้ [ดูข้อมูลเพิ่มเติม](https://web.dev/unused-css-rules)"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "นำ CSS ที่ไม่ได้ใช้ออก"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "นำ JavaScript ที่ไม่ได้ใช้ออกเพื่อลดจำนวนไบต์ที่กิจกรรมเครือข่ายใช้"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "นำ JavaScript ที่ไม่ได้ใช้ออก"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "อายุการใช้งานแคชที่ยาวนานช่วยเพิ่มการเข้าชมหน้าเว็บซ้ำได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-long-cache-ttl)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{พบทรัพยากร 1 รายการ}other{พบทรัพยากร # รายการ}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "แสดงเนื้อหาคงที่ที่มีนโยบายแคชที่มีประสิทธิภาพ"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "ใช้นโยบายแคชที่มีประสิทธิภาพกับเนื้อหาคงที่"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "รูปภาพที่ได้รับการเพิ่มประสิทธิภาพจะโหลดได้เร็วขึ้นและใช้อินเทอร์เน็ตมือถือน้อยลง [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-optimized-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "เข้ารหัสรูปภาพอย่างมีประสิทธิภาพ"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "แสดงรูปภาพที่มีขนาดที่เหมาะสมเพื่อประหยัดอินเทอร์เน็ตมือถือและปรับปรุงเวลาในการโหลด [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-responsive-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "ปรับขนาดรูปภาพให้เหมาะสม"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "ทรัพยากรแบบข้อความควรแสดงผลโดยมีการบีบอัด (Gzip, Deflate หรือ Brotli) เพื่อลดจำนวนไบต์เครือข่ายทั้งหมด [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-text-compression)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "เปิดใช้การบีบอัดข้อความ"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "รูปแบบรูปภาพอย่างเช่น JPEG 2000, JPEG XR และ WebP มักบีบอัดได้ดีกว่า PNG หรือ JPEG ซึ่งหมายความว่าจะดาวน์โหลดได้เร็วขึ้นและใช้อินเทอร์เน็ตน้อยลง [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-webp-images)"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "แสดงรูปภาพในรูปแบบสมัยใหม่"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "หากความกว้างของเนื้อหาในแอปไม่ตรงกับความกว้างของวิวพอร์ต แอปอาจไม่ได้รับการเพิ่มประสิทธิภาพสำหรับหน้าจออุปกรณ์เคลื่อนที่ [ดูข้อมูลเพิ่มเติม](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "ขนาดวิวพอร์ต {innerWidth} พิกเซลไม่ตรงกับขนาดหน้าต่าง {outerWidth} พิกเซล"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "ไม่ได้ปรับขนาดเนื้อหาอย่างถูกต้องสำหรับวิวพอร์ต"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "มีการปรับขนาดเนื้อหาอย่างถูกต้องสำหรับวิวพอร์ต"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "ห่วงโซ่คำขอที่สำคัญด้านล่างแสดงให้เห็นทรัพยากรที่โหลดโดยมีลำดับความสำคัญสูง พิจารณาลดความยาวของห่วงโซ่ ลดขนาดการดาวน์โหลดของทรัพยากร หรือเลื่อนเวลาการดาวน์โหลดทรัพยากรที่ไม่จำเป็นเพื่อปรับปรุงการโหลดหน้าเว็บ [ดูข้อมูลเพิ่มเติม](https://web.dev/critical-request-chains)"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{พบห่วงโซ่ 1 รายการ}other{พบห่วงโซ่ # รายการ}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "ลดความลึกของคำขอที่สำคัญ"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "การเลิกใช้งาน / คำเตือน"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "บรรทัด"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "API ที่เลิกใช้งานแล้วจะถูกนำออกจากเบราว์เซอร์ในท้ายที่สุด [ดูข้อมูลเพิ่มเติม](https://web.dev/deprecations)"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{พบคำเตือน 1 รายการ}other{พบคำเตือน # รายการ}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "ใช้ API ที่เลิกใช้งานแล้ว"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "หลีกเลี่ยงการใช้ API ที่เลิกใช้งานแล้ว"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "แคชของแอปพลิเคชันเลิกใช้งานแล้ว [ดูข้อมูลเพิ่มเติม](https://web.dev/appcache-manifest)"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "พบ \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "ใช้แคชของแอปพลิเคชัน"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "หลีกเลี่ยงการใช้แคชของแอปพลิเคชัน"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "การระบุ DOCTYPE ช่วยป้องกันไม่ให้เบราว์เซอร์เปลี่ยนไปใช้โหมดที่ไม่มาตรฐาน [ดูข้อมูลเพิ่มเติม](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "ชื่อ DOCTYPE ต้องเป็นสตริงตัวพิมพ์เล็ก `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "เอกสารต้องมี DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "สตริง publicId ควรจะว่าง"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "สตริง systemId ควรจะว่าง"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "หน้าไม่มี DOCTYPE HTML ดังนั้นจึงทริกเกอร์โหมดที่ไม่มาตรฐาน"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "หน้ามี DOCTYPE HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "องค์ประกอบ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "สถิติ"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "ค่า"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "วิศวกรเบราว์เซอร์แนะนำให้ใช้หน้าเว็บที่มีองค์ประกอบ DOM น้อยกว่า 1,500 รายการโดยประมาณ ความลึกที่เหมาะที่สุดคือแบบต้นไม้ซึ่งมีองค์ประกอบน้อยกว่า 32 รายการและมีองค์ประกอบย่อย/หลักน้อยกว่า 60 รายการ รายการ DOM ขนาดใหญ่อาจใช้หน่วยความจำเพิ่มขึ้น ทำให้[การคำนวณสไตล์](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)ยาวนานขึ้น และสร้าง[การจัดเรียงการออกแบบใหม่](https://developers.google.com/speed/articles/reflow)ซึ่งมีค่าใช้จ่ายสูง [ดูข้อมูลเพิ่มเติม](https://web.dev/dom-size)"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 องค์ประกอบ}other{# องค์ประกอบ}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "หลีกเลี่ยง DOM ที่มีขนาดใหญ่เกินไป"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "ความลึก DOM สูงสุด"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "องค์ประกอบ DOM ทั้งหมด"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "จำนวนองค์ประกอบย่อยสูงสุด"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "หลีกเลี่ยง DOM ที่มีขนาดใหญ่เกินไป"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "เป้าหมาย"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "เพิ่ม `rel=\"noopener\"` หรือ `rel=\"noreferrer\"` ไปยังลิงก์ภายนอกใดๆ เพื่อปรับปรุงประสิทธิภาพและป้องกันช่องโหว่ด้านความปลอดภัย [ดูข้อมูลเพิ่มเติม](https://web.dev/external-anchors-use-rel-noopener)"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "ลิงก์ไปปลายทางแบบ Cross-Origin ไม่ปลอดภัย"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "ลิงก์ไปปลายทางแบบ Cross-Origin ปลอดภัย"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "ระบุปลายทางสำหรับโฆษณาด้านล่างสุด ({anchorHTML}) ไม่ได้ หากไม่ได้ใช้เป็นไฮเปอร์ลิงก์ ลองเอา target=_blank ออก"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "ผู้ใช้ไม่เชื่อถือหรือเกิดความสับสนในเว็บไซต์ที่ขอข้อมูลตำแหน่งโดยไม่มีบริบทให้ พิจารณาผูกคำขอกับการกระทำของผู้ใช้แทน [ดูข้อมูลเพิ่มเติม](https://web.dev/geolocation-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "ขอสิทธิ์เข้าถึงตำแหน่งทางภูมิศาสตร์ในการโหลดหน้าเว็บ"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "หลีกเลี่ยงการขอสิทธิ์เข้าถึงตำแหน่งทางภูมิศาสตร์ในการโหลดหน้าเว็บ"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "เวอร์ชัน"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "ตรวจพบไลบรารี JavaScript ส่วนหน้าทั้งหมดในหน้าเว็บ [ดูข้อมูลเพิ่มเติม](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "ตรวจพบไลบรารี JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "สำหรับผู้ใช้ที่การเชื่อมต่อช้า สคริปต์ภายนอกที่แทรกเข้ามาแบบไดนามิกผ่านทาง `document.write()` จะช่วยหน่วงการโหลดหน้าเว็บได้หลายสิบวินาที [ดูข้อมูลเพิ่มเติม](https://web.dev/no-document-write)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "ใช้ `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "หลีกเลี่ยงการใช้ `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "ความรุนแรงสูงสุด"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "เวอร์ชันของไลบรารี"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "จำนวนช่องโหว่"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "สคริปต์ของบุคคลที่สามบางรายการอาจมีช่องโหว่ด้านความปลอดภัยที่เป็นที่รู้จักซึ่งผู้โจมตีจะหาพบได้ง่ายและใช้ประโยชน์จากช่องโหว่นั้น [ดูข้อมูลเพิ่มเติม](https://web.dev/no-vulnerable-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{ตรวจพบช่องโหว่ 1 รายการ}other{ตรวจพบช่องโหว่ # รายการ}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "มีไลบรารี JavaScript ส่วนหน้าที่มีช่องโหว่ด้านความปลอดภัย"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "สูง"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "ต่ำ"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "ปานกลาง"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "หลีกเลี่ยงการใช้ไลบรารี JavaScript ส่วนหน้าที่มีช่องโหว่ด้านความปลอดภัย"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "ผู้ใช้ไม่เชื่อถือหรือเกิดความสับสนในเว็บไซต์ที่ขอส่งการแจ้งเตือนโดยไม่มีบริบทให้ พิจารณาผูกคำขอกับท่าทางสัมผัสของผู้ใช้แทน [ดูข้อมูลเพิ่มเติม](https://web.dev/notification-on-start)"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "ขอสิทธิ์การแจ้งเตือนในการโหลดหน้าเว็บ"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "หลีกเลี่ยงการขอสิทธิ์การแจ้งเตือนในการโหลดหน้าเว็บ"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "องค์ประกอบที่ไม่ผ่านการตรวจสอบ"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "การป้องกันการวางรหัสผ่านทำให้นโยบายความปลอดภัยที่ดีอ่อนแอลง [ดูข้อมูลเพิ่มเติม](https://web.dev/password-inputs-can-be-pasted-into)"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "ป้องกันผู้ใช้ไม่ให้วางรหัสผ่านในช่อง"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "อนุญาตผู้ใช้ให้วางรหัสผ่านในช่องได้"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "โปรโตคอล"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 มีข้อดีที่มากกว่า HTTP/1.1 คือ ส่วนหัวแบบไบนารี การทำมัลติเพล็กซิง และการ Push ไปที่เซิร์ฟเวอร์ [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-http2)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{คำขอ 1 รายการไม่ได้แสดงผ่าน HTTP/2}other{คำขอ # รายการไม่ได้แสดงผ่าน HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "ไม่ได้ใช้ HTTP/2 สำหรับทรัพยากรทั้งหมด"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "ใช้ HTTP/2 กับทรัพยากรของตนเอง"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "ลองระบุ Listener เหตุการณ์แบบแตะและลูกกลิ้งเป็น `passive` เพื่อปรับปรุงประสิทธิภาพการเลื่อนของหน้าเว็บ [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-passive-event-listeners)"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "ไม่ได้ใช้ Listener แบบแพสซีฟเพื่อปรับปรุงประสิทธิภาพการเลื่อน"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "ใช้ Listener แบบแพสซีฟเพื่อปรับปรุงประสิทธิภาพการเลื่อน"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "รายละเอียด"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "ข้อผิดพลาดที่บันทึกลงในคอนโซลแสดงให้เห็นถึงปัญหาที่ไม่ได้รับการแก้ไข ข้อผิดพลาดอาจมาจากคำขอเครือข่ายที่ไม่สำเร็จ และปัญหาอื่นๆ เกี่ยวกับเบราว์เซอร์ [ดูข้อมูลเพิ่มเติม](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "บันทึกข้อผิดพลาดเบราว์เซอร์ลงในคอนโซลแล้ว"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "ไม่มีข้อผิดพลาดเบราว์เซอร์บันทึกลงในคอนโซล"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "ใช้ประโยชน์จากฟีเจอร์ CSS สำหรับแสดงแบบอักษรเพื่อให้ผู้ใช้มองเห็นข้อความได้ในขณะที่กำลังโหลดเว็บฟอนต์ [ดูข้อมูลเพิ่มเติม](https://web.dev/font-display)"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "ตรวจสอบว่าข้อความจะยังมองเห็นได้ในระหว่างการโหลดเว็บฟอนต์"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "ข้อความทั้งหมดจะยังมองเห็นได้ในระหว่างการโหลดเว็บฟอนต์"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse ตรวจสอบค่าการแสดงแบบอักษรสำหรับ URL ต่อไปนี้โดยอัตโนมัติไม่ได้: {fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "สัดส่วนภาพ (ขนาดจริง)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "สัดส่วนภาพ (ที่แสดง)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "ขนาดแสดงรูปภาพควรจะมีสัดส่วนที่เป็นธรรมชาติ [ดูข้อมูลเพิ่มเติม](https://web.dev/image-aspect-ratio)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "แสดงรูปภาพที่มีสัดส่วนไม่ถูกต้อง"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "แสดงรูปภาพที่มีสัดส่วนถูกต้อง"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "ข้อมูลขนาดรูปภาพไมู่กต้อง {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "เบราว์เซอร์แจ้งผู้ใช้อย่างชัดแจ้งให้เพิ่มแอปของคุณในหน้าจอหลัก ซึ่งจะทำให้ผู้ใช้มีส่วนร่วมเพิ่มขึ้นได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "ไฟล์ Manifest ของเว็บแอปไม่ตรงตามข้อกำหนดด้านความสามารถในการติดตั้ง"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "ไฟล์ Manifest ของเว็บแอปตรงตามข้อกำหนดด้านความสามารถในการติดตั้ง"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL ไม่ปลอดภัย"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "ทุกเว็บไซต์ควรป้องกันด้วยการใช้ HTTPS แม้ว่าจะเป็นเว็บไซต์ที่ไม่มีข้อมูลที่ละเอียดอ่อนก็ตาม HTTPS ป้องกันผู้บุกรุกไม่ให้แทรกแซงหรือแอบฟังการสื่อสารระหว่างแอปกับผู้ใช้ของคุณ และเป็นข้อกำหนดที่ต้องทำก่อนสำหรับ HTTP/2 รวมถึง API ของแพลตฟอร์มเว็บใหม่ๆ อีกมาก [ดูข้อมูลเพิ่มเติม](https://web.dev/is-on-https)"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{พบคำขอที่ไม่ปลอดภัย 1 รายการ}other{พบคำขอที่ไม่ปลอดภัย # รายการ}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "ไม่ได้ใช้ HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "ใช้ HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "การโหลดหน้าเว็บที่รวดเร็วผ่านเครือข่ายมือถือช่วยให้มั่นใจว่าผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีในอุปกรณ์เคลื่อนที่ [ดูข้อมูลเพิ่มเติม](https://web.dev/load-fast-enough-for-pwa)"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "โต้ตอบที่ {timeInMs, number, seconds} วินาที"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "มีการโต้ตอบในเครือข่ายมือถือจำลองที่ {timeInMs, number, seconds} วินาที"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "หน้าเว็บโหลดช้าเกินไปและไม่มีการโต้ตอบภายใน 10 วินาที ไปที่โอกาสและการวินิจฉัยในส่วน \"ประสิทธิภาพ\" เพื่อดูวิธีปรับปรุง"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "การโหลดหน้าเว็บไม่เร็วพอเมื่อใช้เครือข่ายมือถือ"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "การโหลดหน้าเว็บเร็วพอเมื่อใช้เครือข่ายมือถือ"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "หมวดหมู่"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "พิจารณาลดเวลาที่ใช้ในการแยกวิเคราะห์ แปลโปรแกรม และดำเนินการกับ JS การส่งเพย์โหลด JS ปริมาณน้อยลงอาจช่วยในเรื่องนี้ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "ลดการทำงานของเธรดหลัก"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "ลดการทำงานของเธรดหลัก"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "เว็บไซต์ควรทำงานในเบราว์เซอร์หลักๆ ทั้งหมดได้เพื่อให้เข้าถึงผู้ใช้จำนวนมากที่สุด [ดูข้อมูลเพิ่มเติม](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "เว็บไซต์ทำงานในเบราว์เซอร์ต่างๆ ได้"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "ตรวจดูว่าแต่ละหน้าทำ Deep Link ผ่าน URL ได้และ URL ต่างๆ ไม่ซ้ำกันเพื่อให้แชร์ได้ในโซเชียลมีเดีย [ดูข้อมูลเพิ่มเติม](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "แต่ละหน้ามี URL ที่ไม่ซ้ำกัน"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "การเปลี่ยนควรจะดำเนินไปอย่างรวดเร็วขณะที่คุณแตะไปรอบๆ แม้ในเครือข่ายที่ช้า ซึ่งเป็นสิ่งสำคัญที่ทำให้ผู้ใช้รับรู้ได้ถึงประสิทธิภาพ [ดูข้อมูลเพิ่มเติม](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "เปลี่ยนหน้าได้รวดเร็วแม้ว่าเครือข่ายจะช้า"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "เวลาตอบสนองต่ออินพุตโดยประมาณเป็นระยะเวลาโดยประมาณที่แอปใช้เพื่อตอบสนองอินพุตของผู้ใช้ระหว่างการโหลดหน้าเว็บในกรอบเวลา 5 วินาทีที่ทำงานหนักที่สุด มีหน่วยเป็นมิลลิวินาที หากเวลาในการตอบสนองนานกว่า 50 มิลลิวินาที ผู้ใช้อาจรู้สึกว่าแอปช้า [ดูข้อมูลเพิ่มเติม](https://web.dev/estimated-input-latency)"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "เวลาในการตอบสนองต่ออินพุตโดยประมาณ"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "First Contentful Paint ระบุเวลาที่มีการแสดงผลข้อความหรือรูปภาพครั้งแรก [ดูข้อมูลเพิ่มเติม](https://web.dev/first-contentful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "การแสดงผลที่มีเนื้อหาเต็มครั้งแรก"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "First CPU Idle ระบุครั้งแรกที่เทรดหลักของหน้าเว็บว่างพอที่จะจัดการกับอินพุต [ดูข้อมูลเพิ่มเติม](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU ไม่ได้ใช้งานครั้งแรก"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "การแสดงผลที่มีความหมายครั้งแรกวัดเมื่อเนื้อหาหลักของหน้าเว็บปรากฏ [ดูข้อมูลเพิ่มเติม](https://web.dev/first-meaningful-paint)"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "การแสดงผลที่มีความหมายครั้งแรก"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "เวลาในการตอบสนองคือระยะเวลาที่หน้าเว็บใช้ในการตอบสนองอย่างสมบูรณ์ [ดูข้อมูลเพิ่มเติม](https://web.dev/interactive)"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "เวลาในการโต้ตอบ"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "First Input Delay สูงสุดที่อาจเกิดขึ้นซึ่งผู้ใช้อาจเจอคือระยะเวลาของงานที่ยาวที่สุดเป็นมิลลิวินาที [ดูข้อมูลเพิ่มเติม](https://developers.google.com/web/updates/2018/05/first-input-delay)"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "First Input Delay สูงสุดที่อาจเกิดขึ้น"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "ดัชนีความเร็วแสดงให้เห็นความเร็วที่เนื้อหาของหน้าปรากฏจนดูสมบูรณ์ [ดูข้อมูลเพิ่มเติม](https://web.dev/speed-index)"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "ดัชนีความเร็ว"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "ผลรวมช่วงเวลาทั้งหมดระหว่าง FCP และเวลาในการตอบสนอง เมื่อความยาวของงานเกิน 50ms หน่วยเป็นมิลลิวินาที"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "เวลาที่บล็อกทั้งหมด"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "ระยะเวลารับส่งข้อมูล (RTT) ของเครือข่ายมีผลกระทบอย่างมากต่อประสิทธิภาพ หากต้นทางมี RTT สูง แสดงว่าเซิร์ฟเวอร์ที่อยู่ใกล้กับผู้ใช้มากกว่าอาจช่วยปรับปรุงประสิทธิภาพได้ [ดูข้อมูลเพิ่มเติม](https://hpbn.co/primer-on-latency-and-bandwidth/)"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "ระยะเวลารับส่งข้อมูลของเครือข่าย"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "เวลาในการตอบสนองต่อเซิร์ฟเวอร์อาจส่งผลกระทบต่อประสิทธิภาพของเว็บ หากต้นทางใช้เวลาในการตอบสนองต่อเซิร์ฟเวอร์นาน แสดงว่ามีการใช้งานเซิร์ฟเวอร์มากเกินไปหรือประสิทธิภาพแบ็กเอนด์ของเซิร์ฟเวอร์ไม่ดี [ดูข้อมูลเพิ่มเติม](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "เวลาในการตอบสนองจากแบ็กเอนด์ของเซิร์ฟเวอร์"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker ช่วยให้เว็บแอปของคุณเชื่อถือได้ในสภาวะของเครือข่ายที่คาดการณ์ไม่ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` ไม่ตอบสนองด้วยรหัส 200 เมื่อออฟไลน์"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` ตอบสนองด้วยรหัส 200 เมื่อออฟไลน์"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse อ่าน `start_url` จากไฟล์ Manifest ไม่ได้ ด้วยเหตุนี้ ระบบจึงสันนิษฐานว่า `start_url` เป็น URL ของเอกสาร ข้อความแสดงข้อผิดพลาด: \"{manifestWarning}\""
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "เกินงบประมาณ"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "ควบคุมให้จำนวนและขนาดของคำขอเครือข่ายอยู่ภายในเป้าหมายที่กำหนดตามงบประมาณประสิทธิภาพที่ให้มา [ดูข้อมูลเพิ่มเติม](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 คำขอ}other{# คำขอ}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "งบประมาณประสิทธิภาพ"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "หากคุณตั้งค่า HTTPS ไว้แล้ว ให้ตรวจสอบว่าได้เปลี่ยนเส้นทางการเข้าชมผ่าน HTTP ทั้งหมดไปยัง HTTPS เพื่อให้ผู้ใช้ทุกคนใช้ฟีเจอร์เว็บที่ปลอดภัยได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "ไม่ได้เปลี่ยนเส้นทางการเข้าชมผ่าน HTTP ไปยัง HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "เปลี่ยนเส้นทางการเข้าชมผ่าน HTTP ไปยัง HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "การเปลี่ยนเส้นทางทำให้เกิดความล่าช้ามากขึ้นก่อนที่หน้าเว็บจะโหลดได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/redirects)"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "หลีกเลี่ยงการเปลี่ยนเส้นทางหลายหน้า"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "หากต้องการตั้งงบประมาณสำหรับจำนวนและขนาดของทรัพยากรหน้า ให้เพิ่มไฟล์ budget.json [ดูข้อมูลเพิ่มเติม](https://developers.google.com/web/tools/lighthouse/audits/budgets)"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{คำขอ 1 รายการ • {byteCount, number, bytes} KB}other{คำขอ # รายการ • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "ควบคุมให้จำนวนคำขอมีไม่มากและการโอนมีขนาดเล็ก"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "ลิงก์ Canonical จะบอกถึง URL ที่จะแสดงในผลการค้นหา [ดูข้อมูลเพิ่มเติม](https://web.dev/canonical)"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "URL หลายรายการขัดแย้งกัน ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "ชี้ไปที่โดเมนอื่น ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL ไม่ถูกต้อง ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "ชี้ไปที่ `hreflang` ตำแหน่งอื่น ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL แบบสัมพัทธ์ ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "ชี้ไปที่ URL ระดับรากของโดเมน (หน้าแรก) แทนที่จะเป็นหน้าที่เทียบเท่ากันของเนื้อหา"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "เอกสารไม่มี `rel=canonical` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "เอกสารมี `rel=canonical` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "ขนาดตัวอักษรที่เล็กกว่า 12 พิกเซลจะเล็กเกินไปจนอ่านไม่ออกและทำให้ผู้เข้าชมในอุปกรณ์เคลื่อนที่ต้อง “บีบเพื่อซูมเข้า” เพื่ออ่าน พยายามให้ข้อความในหน้าเว็บมากกว่า 60% มีขนาดอย่างน้อย 12 พิกเซล [ดูข้อมูลเพิ่มเติม](https://web.dev/font-size)"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "ข้อความที่อ่านได้ชัดเจน {decimalProportion, number, extendedPercent}"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "ข้อความอ่านได้ไม่ชัดเจนเพราะไม่มีเมตาแท็กวิวพอร์ตที่เพิ่มประสิทธิภาพให้เหมาะกับหน้าจออุปกรณ์เคลื่อนที่"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} ของข้อความมีขนาดเล็กเกินไป (อิงจากตัวอย่าง {decimalProportionVisited, number, extendedPercent})"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "เอกสารไม่ได้ใช้ขนาดตัวอักษรที่อ่านได้ชัดเจน"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "เอกสารใช้ขนาดตัวอักษรที่อ่านได้ชัดเจน"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "ลิงก์ hreflang จะบอกให้เครื่องมือค้นหาทราบถึงเวอร์ชันของหน้าเว็บที่ควรแสดงในผลการค้นหาสำหรับแต่ละภาษาหรือภูมิภาค [ดูข้อมูลเพิ่มเติม](https://web.dev/hreflang)"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "เอกสารไม่มี `hreflang` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "เอกสารมี `hreflang` ที่ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "หน้าเว็บที่มีรหัสสถานะ HTTP ไม่สำเร็จอาจไม่ได้รับการจัดทำดัชนีอย่างถูกต้อง [ดูข้อมูลเพิ่มเติม](https://web.dev/http-status-code)"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "หน้าเว็บมีรหัสสถานะ HTTP ไม่สำเร็จ"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "หน้าเว็บมีรหัสสถานะ HTTP สำเร็จ"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "เครื่องมือค้นหาจะรวมหน้าเว็บของคุณไว้ในผลการค้นหาไม่ได้หากไม่มีสิทธิ์รวบรวมข้อมูลหน้าดังกล่าว [ดูข้อมูลเพิ่มเติม](https://web.dev/is-crawable)"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "หน้าเว็บถูกบล็อกไม่ให้มีการจัดทำดัชนี"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "หน้าไม่ได้ถูกบล็อกจากการจัดทำดัชนี"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "ข้อความอธิบายลิงก์ช่วยให้เครื่องมือค้นหาเข้าใจเนื้อหาของคุณ [ดูข้อมูลเพิ่มเติม](https://web.dev/link-text)"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{พบ 1 ลิงก์}other{พบ # ลิงก์}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "ลิงก์ไม่มีข้อความอธิบาย"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "ลิงก์มีข้อความอธิบาย"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "เรียกใช้[เครื่องมือทดสอบข้อมูลที่มีโครงสร้าง](https://search.google.com/structured-data/testing-tool/)และ [Linter ข้อมูลที่มีโครงสร้าง](http://linter.structured-data.org/)เพื่อตรวจสอบความถูกต้องของข้อมูลที่มีโครงสร้าง [ดูข้อมูลเพิ่มเติม](https://web.dev/structured-data)"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "ข้อมูลที่มีโครงสร้างถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "อาจมีการรวมคำอธิบายเมตาในผลการค้นหาเพื่อสรุปเนื้อหาของหน้าเว็บให้สั้นกระชับ [ดูข้อมูลเพิ่มเติม](https://web.dev/meta-description)"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "ข้อความอธิบายว่างเปล่า"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "เอกสารไม่มีคำอธิบายเมตา"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "เอกสารมีคำอธิบายเมตา"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "เครื่องมือค้นหาจัดทำดัชนีเนื้อหาปลั๊กอินไม่ได้ และอุปกรณ์จำนวนมากจำกัดการใช้หรือไม่รองรับปลั๊กอิน [ดูข้อมูลเพิ่มเติม](https://web.dev/plugins)"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "เอกสารใช้ปลั๊กอิน"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "เอกสารหลีกเลี่ยงการใช้ปลั๊กอิน"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "หากไฟล์ robots.txt มีรูปแบบไม่ถูกต้อง โปรแกรมรวบรวมข้อมูลอาจไม่เข้าใจวิธีที่คุณต้องการให้รวบรวมข้อมูลหรือจัดทำดัชนีเว็บไซต์ [ดูข้อมูลเพิ่มเติม](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "คำขอ robots.txt แสดงสถานะ HTTP ต่อไปนี้ {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{พบข้อผิดพลาด 1 รายการ}other{พบข้อผิดพลาด # รายการ}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse ดาวน์โหลดไฟล์ robots.txt ไม่ได้"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt ไม่ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt ถูกต้อง"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "องค์ประกอบสำหรับการโต้ตอบ เช่น ปุ่มและลิงก์ ต้องมีขนาดใหญ่พอ (48x48 พิกเซล) และมีพื้นที่ว่างโดยรอบมากพอเพื่อให้แตะได้ง่ายๆ โดยไม่ซ้อนทับกับองค์ประกอบอื่นๆ [ดูข้อมูลเพิ่มเติม](https://web.dev/tap-targets)"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "เป้าหมายการแตะที่มีขนาดเหมาะสม {decimalProportion, number, percent}"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "เป้าหมายการแตะมีขนาดเล็กเกินไปเพราะไม่มีเมตาแท็กวิวพอร์ตที่เพิ่มประสิทธิภาพให้เหมาะกับหน้าจออุปกรณ์เคลื่อนที่"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "เป้าหมายการแตะมีขนาดที่ไม่เหมาะสม"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "เป้าหมายซ้อนทับกัน"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "เป้าหมายการแตะ"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "เป้าหมายการแตะมีขนาดที่เหมาะสม"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker เป็นเทคโนโลยีที่ช่วยให้แอปของคุณใช้ฟีเจอร์ของ Progressive Web App ได้หลายฟีเจอร์ เช่น ออฟไลน์ เพิ่มไปยังหน้าจอหลัก และข้อความ Push [ดูข้อมูลเพิ่มเติม](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "หน้านี้ควบคุมโดย Service Worker แต่ไม่พบ `start_url` เนื่องจากไฟล์ Manifest แยกวิเคราะห์เป็น JSON ที่ถูกต้องไม่ได้"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "หน้านี้ควบคุมโดย Service Worker แต่ `start_url` ({startUrl}) ไม่ได้อยู่ในขอบเขตของ Service Worker นั้น ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "หน้านี้ควบคุมโดย Service Worker แต่ไม่พบ `start_url` เพราะไม่มีการดึงไฟล์ Manifest"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "ต้นทางนี้มี Service Worker อย่างน้อย 1 ไฟล์ แต่หน้าเว็บ ({pageUrl}) ไม่อยู่ในขอบเขต"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "ไม่ได้ลงทะเบียน Service Worker ที่ควบคุมหน้าเว็บและ `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "ลงทะเบียน Service Worker ที่ควบคุมหน้าเว็บและ `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "หน้าจอแนะนำที่มีธีมช่วยให้ผู้ใช้ได้รับประสบการณ์ที่มีคุณภาพสูงเมื่อเปิดแอปของคุณจากหน้าจอหลัก [ดูข้อมูลเพิ่มเติม](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "ไม่ได้กำหนดค่าให้ใช้หน้าจอแนะนำที่กำหนดเอง"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "มีการกำหนดค่าให้ใช้หน้าจอแนะนำที่กำหนดเอง"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "คุณกำหนดธีมของแถบที่อยู่เบราว์เซอร์ให้เข้ากับเว็บไซต์ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "ไม่ได้กำหนดสีธีมสำหรับแถบที่อยู่"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "กำหนดสีธีมของแถบที่อยู่"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "เวลาในการบล็อกเทรดหลัก"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "บุคคลที่สาม"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "โค้ดของบุคคลที่สามอาจส่งผลกระทบที่สำคัญต่อประสิทธิภาพการโหลด จำกัดจำนวนผู้ให้บริการบุคคลที่สามที่มากเกินไปและพยายามโหลดโค้ดของบุคคลที่สามหลังจากที่หน้าเว็บโหลดเบื้องต้นเสร็จเรียบร้อยแล้ว [ดูข้อมูลเพิ่มเติม](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "โค้ดของบุคคลที่สามบล็อกเทรดหลักเป็นเวลา {timeInMs, number, milliseconds} วินาที"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "ลดผลกระทบจากโค้ดของบุคคลที่สาม"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "การใช้บุคคลที่สาม"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Time To First Byte ระบุเวลาที่เซิร์ฟเวอร์ส่งการตอบกลับ [ดูข้อมูลเพิ่มเติม](https://web.dev/time-to-first-byte)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "เอกสารรากใช้เวลา {timeInMs, number, milliseconds} มิลลิวินาที"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "ลดเวลาในการตอบกลับของเซิร์ฟเวอร์ (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "เวลาตอบสนองของเซิร์ฟเวอร์ต่ำ (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "ระยะเวลา"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "เวลาเริ่มต้น"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "ประเภท"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "พิจารณาติดตั้ง User Timing API ในแอปเพื่อวัดประสิทธิภาพในระหว่างประสบการณ์สำคัญของผู้ใช้ในชีวิตจริงได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/user-timings)"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{ระยะเวลาของผู้ใช้ 1 รายการ}other{ระยะเวลาของผู้ใช้ # รายการ}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "ระยะเวลาที่เจาะจงของผู้ใช้และระยะเวลาทั่วไป"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "พบ <link> ที่เชื่อมต่อล่วงหน้าสำหรับ \"{securityOrigin}\" แต่เบราว์เซอร์ไม่ได้นำไปใช้งาน โปรดตรวจสอบว่าคุณใช้แอตทริบิวต์ `crossorigin` อย่างถูกต้องแล้ว"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "พิจารณาเพิ่ม `preconnect` หรือ `dns-prefetch` ซึ่งบอกถึงทรัพยากรเพื่อสร้างการเชื่อมต่อกับต้นทางที่สำคัญของบุคคลที่สามตั้งแต่เนิ่นๆ [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "เชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้า"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "พบ <link> ที่โหลดล่วงหน้าสำหรับ \"{preloadURL}\" แต่เบราว์เซอร์ไม่ได้นำไปใช้งาน โปรดตรวจสอบว่าคุณใช้แอตทริบิวต์ `crossorigin` อย่างถูกต้องแล้ว"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "พิจารณาใช้ `<link rel=preload>` เพื่อจัดลำดับความสำคัญในการเรียกทรัพยากรที่มีการขอให้โหลดหน้าเว็บภายหลัง [ดูข้อมูลเพิ่มเติม](https://web.dev/uses-rel-preload)"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "โหลดคำขอสำคัญล่วงหน้า"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "เพิ่มแท็ก `<meta name=\"viewport\">` เพื่อเพิ่มประสิทธิภาพแอปสำหรับหน้าจออุปกรณ์เคลื่อนที่ [ดูข้อมูลเพิ่มเติม](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "ไม่พบแท็ก `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "ไม่มีแท็ก `<meta name=\"viewport\">` ที่มี `width` หรือ `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "มีแท็ก `<meta name=\"viewport\">` ที่มี `width` หรือ `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "แอปควรแสดงเนื้อหาบางอย่างเมื่อมีการปิดใช้ JavaScript แม้จะเป็นเพียงการเตือนผู้ใช้ว่าการใช้แอปจำเป็นต้องใช้ JavaScript [ดูข้อมูลเพิ่มเติม](https://web.dev/without-javascript)"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "ส่วนเนื้อหาในหน้าควรแสดงเนื้อหาบางอย่างถ้าสคริปต์ในหน้าไม่พร้อมใช้งาน"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "ไม่แสดงเนื้อหาทางเลือกเมื่อ JavaScript ไม่พร้อมใช้งาน"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "มีเนื้อหาบางอย่างแสดงขึ้นเมื่อ JavaScript ไม่พร้อมใช้งาน"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "หากคุณกำลังสร้าง Progressive Web App ให้พิจารณาใช้ Service Worker เพื่อให้แอปทำงานแบบออฟไลน์ได้ [ดูข้อมูลเพิ่มเติม](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "หน้าปัจจุบันไม่ตอบสนองด้วยรหัส 200 เมื่อออฟไลน์"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "หน้าปัจจุบันตอบสนองด้วยรหัส 200 เมื่อออฟไลน์"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "หน้านี้อาจไม่โหลดขึ้นขณะออฟไลน์เนื่องจาก URL ทดสอบของคุณ ({requested}) มีการเปลี่ยนเส้นทางไปยัง \"{final}\" ลองทดสอบ URL ที่ 2 โดยตรง"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงการใช้งาน ARIA ในแอปพลิเคชันของคุณ ซึ่งอาจช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานเทคโนโลยีอำนวยความสะดวก เช่น โปรแกรมอ่านหน้าจอ ที่ดียิ่งขึ้น"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "นี่เป็นโอกาสระบุเนื้อหาสำรองสำหรับเสียงและวิดีโอ การดำเนินการนี้อาจช่วยปรับปรุงประสบการณ์ของผู้ใช้ที่มีความบกพร่องทางการได้ยินหรือการมองเห็น"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "เสียงและวิดีโอ"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "รายการเหล่านี้ไฮไลต์แนวทางปฏิบัติที่ดีที่สุดที่พบบ่อยของการช่วยเหลือพิเศษ"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "แนวทางปฏิบัติที่ดีที่สุด"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "การตรวจสอบเหล่านี้ไฮไลต์โอกาสในการ[ปรับปรุงการช่วยเหลือพิเศษของเว็บแอป](https://developers.google.com/web/fundamentals/accessibility) โดยจะตรวจพบอัตโนมัติได้เฉพาะปัญหากลุ่มย่อยด้านการช่วยเหลือพิเศษ เราจึงขอแนะนำให้ตรวจสอบด้วยตนเองด้วย"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "รายการเหล่านี้จัดการพื้นที่ที่เครื่องมือทดสอบอัตโนมัติไม่ครอบคลุม ดูข้อมูลเพิ่มเติมในคำแนะนำเกี่ยวกับ[การดำเนินการตรวจสอบการช่วยเหลือพิเศษ](https://developers.google.com/web/fundamentals/accessibility/how-to-review)"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "การช่วยเหลือพิเศษ"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงความอ่านง่ายของเนื้อหา"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "คอนทราสต์"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงการตีความเนื้อหาของคุณโดยผู้ใช้ภาษาต่างๆ"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "การปรับให้เป็นสากลและการแปล"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงความหมายของส่วนควบคุมในแอปพลิเคชันของคุณ การดำเนินการนี้อาจช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานเทคโนโลยีอำนวยความสะดวก เช่น โปรแกรมอ่านหน้าจอ ที่ดียิ่งขึ้น"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "ชื่อและป้ายกำกับ"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงการไปยังส่วนต่างๆ ในแอปพลิเคชันของคุณด้วยแป้นพิมพ์"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "การนำทาง"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "นี่เป็นโอกาสปรับปรุงประสบการณ์การอ่านตารางหรือข้อมูลรายการโดยใช้เทคโนโลยีอำนวยความสะดวก เช่น โปรแกรมอ่านหน้าจอ"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "ตารางและรายการ"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "แนวทางปฏิบัติที่ดีที่สุด"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "งบประมาณประสิทธิภาพจะใช้เป็นมาตรฐานสำหรับประสิทธิภาพของเว็บไซต์คุณ"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "งบประมาณ"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "ข้อมูลเพิ่มเติมเกี่ยวกับประสิทธิภาพของแอปพลิเคชัน ตัวเลขเหล่านี้ไม่[ส่งผลกระทบโดยตรง](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)ต่อคะแนนประสิทธิภาพ"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "การวินิจฉัย"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "ประสิทธิภาพที่สำคัญที่สุดคือความเร็วที่พิกเซลแสดงผลในหน้าจอ เมตริกที่สำคัญ ได้แก่ การแสดงผลที่มีเนื้อหาเต็มครั้งแรก การแสดงผลที่มีความหมายครั้งแรก"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "การปรับปรุงการแสดงผลครั้งแรก"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "คำแนะนำเหล่านี้จะช่วยให้หน้าโหลดได้เร็วขึ้น โดยจะไม่[ส่งผลกระทบโดยตรง](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)ต่อคะแนนประสิทธิภาพ"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "โอกาส"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "เมตริก"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "ปรับปรุงประสบการณ์ในการโหลดโดยรวมเพื่อให้หน้าเว็บตอบสนองและพร้อมใช้งานโดยเร็วที่สุด เมตริกที่สำคัญ ได้แก่ เวลาในการโต้ตอบ ดัชนีความเร็ว"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "การปรับปรุงโดยรวม"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "ประสิทธิภาพ"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "การตรวจสอบเหล่านี้ตรวจสอบความถูกต้องของลักษณะต่างๆ ของ Progressive Web App [ดูข้อมูลเพิ่มเติม](https://developers.google.com/web/progressive-web-apps/checklist)"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "การตรวจสอบเหล่านี้เป็นสิ่งที่ต้องทำใน[รายการตรวจสอบ PWA](https://developers.google.com/web/progressive-web-apps/checklist) ซึ่งเป็นเกณฑ์พื้นฐาน แต่ Lighthouse ไม่ได้ทำการตรวจสอบดังกล่าวโดยอัตโนมัติ การตรวจสอบจะไม่ส่งผลต่อคะแนนของคุณ แต่คุณควรตรวจสอบด้วยตนเอง"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progressive Web App"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "ทำงานเร็วและวางใจได้"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "ติดตั้งได้"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "เพิ่มประสิทธิภาพ PWA แล้ว"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "การตรวจสอบเหล่านี้ช่วยให้มั่นใจว่าหน้าเว็บของคุณได้รับการเพิ่มประสิทธิภาพสำหรับการจัดอันดับผลลัพธ์ของเครื่องมือค้นหา มีปัจจัยอื่นๆ ที่ Lighthouse ไม่ได้ตรวจสอบซึ่งอาจส่งผลกระทบต่อการจัดอันดับของคุณในการค้นหา [ดูข้อมูลเพิ่มเติม](https://support.google.com/webmasters/answer/35769)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "เรียกใช้ตัวตรวจสอบความถูกต้องเพิ่มเติมเหล่านี้ในเว็บไซต์ของคุณเพื่อดูแนวทางปฏิบัติที่ดีที่สุดเพิ่มเติมเกี่ยวกับ SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "จัด HTML ให้อยู่ในรูปแบบที่ช่วยให้โปรแกรมรวบรวมข้อมูลเข้าใจเนื้อหาแอปได้ง่ายขึ้น"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "แนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับเนื้อหา"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "โปรแกรมรวบรวมข้อมูลจะต้องเข้าถึงแอปของคุณได้เพื่อให้แอปปรากฏในผลการค้นหา"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "การรวบรวมข้อมูลและจัดทำดัชนี"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "ตรวจสอบว่าหน้าเว็บเหมาะกับอุปกรณ์เคลื่อนที่ ผู้ใช้จะได้ไม่ต้องบีบนิ้วหรือซูมเข้าเพื่ออ่านหน้าเนื้อหา [ดูข้อมูลเพิ่มเติม](https://developers.google.com/search/mobile-sites/)"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "เหมาะกับอุปกรณ์เคลื่อนที่"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "แคช TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "ตำแหน่ง"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "ชื่อ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "คำขอ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "ประเภททรัพยากร"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "ขนาด"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "เวลาที่ใช้"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "ขนาดการโอน"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "เวลาที่อาจประหยัดได้"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "เวลาที่อาจประหยัดได้"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "อาจประหยัดได้ {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "อาจประหยัดได้ {wastedMs, number, milliseconds} มิลลิวินาที"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "เอกสาร"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "แบบอักษร"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "รูปภาพ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "สื่อ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} มิลลิวินาที"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "อื่นๆ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "สคริปต์"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} วินาที"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "สไตล์ชีต"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "บุคคลที่สาม"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "รวม"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "เกิดข้อผิดพลาดในการบันทึกการติดตามระหว่างการโหลดหน้าเว็บ โปรดเรียกใช้ Lighthouse อีกครั้ง ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "หมดเวลาระหว่างที่รอการเชื่อมต่อโปรโตคอลโปรแกรมแก้ไขข้อบกพร่องเริ่มต้น"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome ไม่ได้รวบรวมภาพหน้าจอใดๆ ระหว่างการโหลดหน้า โปรดตรวจสอบว่ามีเนื้อหาที่มองเห็นได้ในหน้าเว็บ จากนั้นลองเรียกใช้ Lighthouse อีกครั้ง ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "เซิร์ฟเวอร์ DNS แก้ปัญหาโดเมนที่ระบุไม่ได้"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "ตัวรวบรวม {artifactName} ที่จำเป็นพบข้อผิดพลาด: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "เกิดข้อผิดพลาดภายในของ Chrome โปรดรีสตาร์ท Chrome และลองเรียกใช้ Lighthouse อีกครั้ง"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "ตัวรวบรวม {artifactName} ที่จำเป็นไม่ทำงาน"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse โหลดหน้าเว็บที่คุณขออย่างน่าเชื่อถือไม่ได้ ตรวจสอบว่าคุณกำลังทดสอบ URL ที่ถูกต้องและเซิร์ฟเวอร์ตอบสนองคำขอทั้งหมดอย่างถูกต้อง"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse โหลด URL ที่คุณขออย่างน่าเชื่อถือไม่ได้เพราะหน้าเว็บไม่ตอบสนอง"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL ที่ระบุไม่มีใบรับรองความปลอดภัยที่ถูกต้อง {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome ป้องกันการโหลดหน้าเว็บด้วยโฆษณาคั่นระหว่างหน้า ตรวจสอบว่าคุณกำลังทดสอบ URL ที่ถูกต้องและเซิร์ฟเวอร์ตอบสนองคำขอทั้งหมดอย่างถูกต้อง"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse โหลดหน้าเว็บที่คุณขออย่างน่าเชื่อถือไม่ได้ ตรวจสอบว่าคุณกำลังทดสอบ URL ที่ถูกต้องและเซิร์ฟเวอร์ตอบสนองคำขอทั้งหมดอย่างถูกต้อง (รายละเอียด: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse โหลดหน้าเว็บที่คุณขออย่างน่าเชื่อถือไม่ได้ ตรวจสอบว่าคุณกำลังทดสอบ URL ที่ถูกต้องและเซิร์ฟเวอร์ตอบสนองคำขอทั้งหมดอย่างถูกต้อง (รหัสสถานะ: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "หน้าเว็บของคุณใช้เวลาโหลดนานเกินไป โปรดทำตามโอกาสในรายงานเพื่อลดเวลาในการโหลดหน้าเว็บแล้วลองเรียกใช้ Lighthouse อีกครั้ง ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "การรอการตอบสนองของโปรโตคอล DevTools เกินเวลาที่จัดสรรไว้ (เมธอด: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "การดึงข้อมูลเนื้อหาทรัพยากรเกินเวลาที่จัดสรรไว้"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "ดูเหมือนว่า URL ที่ระบุจะไม่ถูกต้อง"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "แสดงการตรวจสอบ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "การนำทางเริ่มต้น"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "เวลาในการตอบสนองของเส้นทางสำคัญที่ยาวที่สุด"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "ข้อผิดพลาด!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "ข้อผิดพลาดในรายงาน: ไม่มีข้อมูลการตรวจสอบ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "ข้อมูลในห้องทดลอง"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "การวิเคราะห์หน้าปัจจุบันในเครือข่ายมือถือจำลองโดย [Lighthouse](https://developers.google.com/web/tools/lighthouse/) ค่ามาจากการประมาณและอาจแตกต่างกันไป"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "รายการเพิ่มเติมที่ควรตรวจสอบด้วยตนเอง"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "ไม่เกี่ยวข้อง"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "โอกาส"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "เวลาที่ประหยัดได้โดยประมาณ"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "การตรวจสอบที่ผ่านแล้ว"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "ยุบตัวอย่างข้อมูล"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "ขยายตัวอย่างข้อมูล"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "แสดงทรัพยากรของบุคคลที่สาม"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "เกิดปัญหาที่มีผลต่อการทำงานนี้ของ Lighthouse"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "ค่ามาจากการประมาณและอาจแตกต่างกันไป คะแนนประสิทธิภาพ[อิงจากเมตริกเหล่านี้เท่านั้น](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "ผ่านการตรวจสอบแต่มีคำเตือน"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "คำเตือน "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "ลองอัปโหลด GIF ไปยังบริการซึ่งจะทำให้ใช้ GIF เพื่อฝังเป็นวิดีโอ HTML5 ได้"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "ติดตั้ง[ปลั๊กอินการโหลดแบบ Lazy Loading ของ WordPress](https://wordpress.org/plugins/search/lazy+load/) ที่จะช่วยเลื่อนเวลาโหลดรูปภาพนอกหน้าจอ หรือเปลี่ยนไปใช้ธีมที่มีฟังก์ชันดังกล่าว และอาจลองพิจารณาใช้[ปลั๊กอิน AMP](https://wordpress.org/plugins/amp/)"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "มีปลั๊กอิน WordPress หลายรายการที่ช่วยคุณ[แทรกเนื้อหาที่สำคัญ](https://wordpress.org/plugins/search/critical+css/) หรือ[เลื่อนเวลาโหลดทรัพยากรที่สำคัญน้อยกว่า](https://wordpress.org/plugins/search/defer+css+javascript/) โปรดระวังว่าการเพิ่มประสิทธิภาพโดยปลั๊กอินเหล่านี้อาจทำให้ฟีเจอร์ของธีมหรือปลั๊กอินของคุณเสียหาย ซึ่งน่าจะทำให้คุณต้องแก้ไขโค้ด"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "การกำหนดธีม ปลั๊กอิน และเซิร์ฟเวอร์ล้วนส่งผลต่อเวลาการตอบสนองของเซิร์ฟเวอร์ ลองหาธีมที่เพิ่มประสิทธิภาพมากขึ้น พยายามเลือกปลั๊กอินการเพิ่มประสิทธิภาพด้วยความระมัดระวัง และ/หรืออัปเกรดเซิร์ฟเวอร์"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "ลองแสดงข้อความที่ตัดตอนมาในรายการโพสต์ (เช่น ผ่านแท็ก \"เพิ่มเติม\") ลดจำนวนโพสต์ที่แสดงในหน้าหนึ่งๆ แบ่งโพสต์ยาวๆ เป็นหลายหน้า หรือใช้ปลั๊กอินเพื่อโหลดความคิดเห็นแบบ Lazy Loading"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "มี[ปลั๊กอิน WordPress](https://wordpress.org/plugins/search/minify+css/) หลายอย่างที่ช่วยให้เว็บไซต์เร็วขึ้นได้ด้วยการลิงก์ ลดขนาด และบีบอัดสไตล์ นอกจากนี้คุณอาจใช้กระบวนการของเวอร์ชันเพื่อลดขนาดล่วงหน้าหากเป็นไปได้"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "มี[ปลั๊กอิน WordPress](https://wordpress.org/plugins/search/minify+javascript/) หลายอย่างที่ช่วยให้เว็บไซต์เร็วขึ้นได้ด้วยการลิงก์ ลดขนาด และบีบอัดสคริปต์ นอกจากนี้คุณอาจใช้กระบวนการของเวอร์ชันเพื่อลดขนาดล่วงหน้าหากเป็นไปได้"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "ลองลดหรือเปลี่ยนจำนวน[ปลั๊กอิน WordPress](https://wordpress.org/plugins/) ที่โหลด CSS ที่ไม่ได้ใช้ในหน้าเว็บของคุณ หากต้องการระบุปลั๊กอินที่เพิ่ม CSS โดยไม่จำเป็น ให้ลองเรียกใช้[การครอบคลุมโค้ด](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)ใน DevTools ของ Chrome คุณระบุธีม/ปลั๊กอินที่รับผิดชอบได้จาก URL ของสไตล์ชีต หาปลั๊กอินที่มีสไตล์ชีตจำนวนมากอยู่ในรายการซึ่งมีสีแดงอยู่จำนวนมากในการครอบคลุมโค้ด ปลั๊กอินควรเป็นเพียงตัวกำหนดลำดับของสไตล์ชีตเท่านั้นหากใช้ปลั๊กอินในหน้าจริงๆ"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "ลองลดหรือเปลี่ยนจำนวน[ปลั๊กอิน WordPress](https://wordpress.org/plugins/) ที่โหลด JavaScript ที่ไม่ได้ใช้ในหน้าเว็บของคุณ หากต้องการระบุปลั๊กอินที่เพิ่ม JS โดยไม่จำเป็น ให้ลองเรียกใช้ [การครอบคลุมโค้ด](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)ใน DevTools ของ Chrome คุณระบุธีม/ปลั๊กอินที่รับผิดชอบได้จาก URL ของสคริปต์ หาปลั๊กอินที่มีสคริปต์จำนวนมากอยู่ในรายการซึ่งมีสีแดงอยู่จำนวนมากในการครอบคลุมโค้ด ปลั๊กอินควรเป็นเพียงตัวกำหนดลำดับของสคริปต์เท่านั้นหากใช้ปลั๊กอินในหน้าจริงๆ"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "อ่านเกี่ยวกับ[การแคชของเบราว์เซอร์ใน WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "พิจารณาใช้[ปลั๊กอิน WordPress การเพิ่มประสิทธิภาพรูปภาพ](https://wordpress.org/plugins/search/optimize+images/)ที่บีบอัดรูปภาพแต่ยังคงคุณภาพไว้ได้"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "อัปโหลดรูปภาพโดยตรงผ่าน[ไลบรารีสื่อ](https://codex.wordpress.org/Media_Library_Screen)เพื่อให้แน่ใจว่ามีขนาดรูปภาพที่จำเป็นพร้อมใช้งาน จากนั้นแทรกรูปภาพจากไลบรารีสื่อหรือใช้วิดเจ็ตรูปภาพเพื่อให้มีการใช้ขนาดรูปภาพที่มีประสิทธิภาพสูงสุด (รวมถึงขนาดสำหรับเบรกพอยท์ที่ปรับเปลี่ยนตามอุปกรณ์) หลีกเลี่ยงการใช้รูปภาพ`Full Size` นอกเสียจากว่าขนาดจะเพียงพอต่อการใช้งาน [ดูข้อมูลเพิ่มเติม](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "คุณเปิดใช้การบีบอัดข้อความในการกำหนดค่าเว็บเซิร์ฟเวอร์ได้"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "พิจารณาใช้[ปลั๊กอิน](https://wordpress.org/plugins/search/convert+webp/)หรือบริการที่จะแปลงรูปภาพที่อัปโหลดเป็นรูปแบบที่เหมาะสมที่สุดโดยอัตโนมัติ"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/tr.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/tr.json
new file mode 100644
index 00000000000..00ef37be719
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/tr.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Erişim anahtarları, kullanıcıların sayfanın bir bölümüne hızlıca odaklanmalarını sağlar. Gezinmenin düzgün bir şekilde gerçekleştirilebilmesi için her bir erişim anahtarının benzersiz olması gerekir [Daha fazla bilgi](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` değerleri benzersiz değil"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` değerleri benzersiz"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Her ARIA `role`, belirli bir `aria-*` özellik alt kümesini destekler. Bunların eşleşmemesi `aria-*` özelliklerini geçersiz kılar. [Daha fazla bilgi](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` özellikleri, rolleriyle eşleşmiyor"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` özellikleri rolleriyle eşleşiyor"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Bazı ARIA rolleri, öğenin durumunu ekran okuyuculara açıklayan gerekli özelliklere sahiptir. [Daha fazla bilgi](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` rolleri gereken tüm `[aria-*]` özelliklerine sahip değil"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` öğelerinin rolleri, gereken tüm`[aria-*]` özelliklerine sahip"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Bazı ARIA üst rollerinin amaçlanan erişilebilirlik işlevlerini gerçekleştirebilmek için belirli alt rolleri içermesi gerekir. [Daha fazla bilgi](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "ARIA `[role]` sahibi olup alt öğelerin belirli bir `[role]` içermesini gerektiren öğelerde bu gerekli alt öğelerin bazıları veya hiçbiri bulunmuyor."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "ARIA `[role]` sahibi olup alt öğelerin belirli bir `[role]` içermesini gerektiren öğelerde gerekli alt öğelerin hepsi bulunuyor."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Bazı ARIA alt rollerinin amaçlanan erişilebilirlik işlevlerini gerektiği gibi gerçekleştirebilmesi için belirli üst rollerin içinde bulunması gerekir. [Daha fazla bilgi](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` rolleri gerekli üst öğelerinin içinde bulunmuyor"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` öğeleri gerekli üst öğelerinin içinde bulunuyor"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA rollerinin amaçlanan erişilebilirlik işlevlerini gerçekleştirebilmesi için geçerli değerlere sahip olması gerekir. [Daha fazla bilgi](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` değerleri geçerli değil"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` değerleri geçerli"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Ekran okuyucular gibi yardımcı teknolojiler geçersiz değerlere sahip ARIA özelliklerini yorumlayamaz. [Daha fazla bilgi](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` özellikleri geçerli değerlere sahip değil"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` özelliklerinin geçerli değerleri var"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Ekran okuyucular gibi yardımcı teknolojiler geçersiz adlara sahip ARIA özelliklerini yorumlayamaz. [Daha fazla bilgi](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` özellikleri geçerli değil veya yanlış yazılmış"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` özellikleri geçerli ve yanlış yazılmamış"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Altyazılar kimin konuştuğu, neler dediği gibi önemli bilgiler ve konuşma dışında başka bilgiler sağlayarak ses öğelerinin işitme engelli veya işitme zorluğuna sahip kullanıcılar tarafından kullanılabilmesini sağlar. [Daha fazla bilgi](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` öğelerinde `[kind=\"captions\"]` içeren bir `<track>` öğesi bulunmuyor."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` öğelerinde `[kind=\"captions\"]`içeren bir `<track>` öğesi bulunuyor"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Başarısız Öğeler"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Bir düğmenin erişilebilir özellikli bir adı yoksa ekran okuyucular bu düğmeyi yalnızca \"düğme\" olarak okuyacağı için bu, ekran okuyuculardan yararlanan kullanıcılar için yararlı olmaz. [Daha fazla bilgi](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Düğmelerin erişilebilir adları yok"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Düğmeler erişilebilir bir ada sahip"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Tekrar eden içeriği atlamanın yollarını eklemek, klavye kullanıcılarının sayfada daha verimli bir şekilde gezinmesini sağlar. [Daha fazla bilgi](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Bu sayfa bir başlık, atlama bağlantısı veya önemli nokta bölgesi içermiyor"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Sayfa bir başlık, atlama bağlantısı veya önemli nokta bölgesi içeriyor"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Birçok kullanıcı, düşük kontrastlı metni okumakta zorlanır veya okuyamaz. [Daha fazla bilgi](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Arka plan ve ön plan renkleri yeterli kontrast oranına sahip değil."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Arka plan ve ön plan renkleri yeterli kontrast oranına sahip"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Tanım listeleri gerektiği gibi işaretlenmediğinde ekran okuyucular kafa karışıklığına yol açan veya yanlış çıkışlar sunabilir. [Daha fazla bilgi](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` öğeleri yalnızca gerektiği gibi sıralanmış `<dt>` ve `<dd>` gruplarını,`<script>` veya `<template>` öğelerini içermiyor."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` öğeleri yalnızca gerektiği gibi sıralanmış `<dt>` ve `<dd>` gruplarını, `<script>` veya `<template>` öğelerini içeriyor."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Tanım listesi öğelerinin (`<dt>` ve `<dd>`) ekran okuyucular tarafından düzgün bir şekilde duyurulabilmesi için üst `<dl>` öğesinin içine yerleştirilmesi gerekir. [Daha fazla bilgi](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Tanım listesi öğeleri `<dl>` öğeleri arasına yerleştirilmemiş"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Tanım listesi öğeleri `<dl>` öğeleri arasına yerleştirilmiş"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Başlık, ekran okuyucu kullanıcılarına sayfayla ilgili genel bir fikir verir ve arama motoru kullanıcılarının bir sayfanın aramalarıyla ilgili olup olmadığını belirlemeleri açısından son derece önemlidir. [Daha fazla bilgi](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Dokümanın `<title>` öğesi yok"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Doküman geçerli bir `<title>` öğesi içeriyor"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Kimlik özelliğinin değeri benzersiz olmalıdır. Bunun nedeni, yardımcı teknolojilerin farkına varmadan diğer örnekleri atlamasını önlemektir. [Daha fazla bilgi](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Sayfadaki `[id]` özellikleri benzersiz değil"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Sayfadaki `[id]` özellikleri benzersiz"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Ekran okuyucu kullanıcıları, çerçevelerin içeriklerinin açıklanması için çerçeve başlıklarından yararlanır. [Daha fazla bilgi](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` veya `<iframe>` öğelerinin başlığı yok"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` veya `<iframe>` öğesi bir başlığa sahip"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Sayfa bir lang özelliği belirtmezse ekran okuyucu, sayfanın kullanıcı ekran okuyucuyu kurarken seçtiği varsayılan dilde olduğunu varsayar. Sayfa aslında varsayılan dilde değilse ekran okuyucu, sayfanın metnini doğru bir şekilde duyurmayabilir. [Daha fazla bilgi](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` öğesinin `[lang]` özelliği yok"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` öğesi `[lang]` özelliği içeriyor"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Geçerli bir [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) belirtilmesi, ekran okuyucuların metni düzgün bir şekilde duyurmasına yardımcı olur. [Daha fazla bilgi](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` öğesi, `[lang]` özelliği için geçerli bir değeri sahip değil."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` öğesi, `[lang]` özelliği için geçerli bir değere sahip"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Bilgilendirme amaçlı öğelerin hedefi, kısa ve açıklayıcı alternatif metinler olmalıdır. Dekoratif öğeler boş bir alt özelliğiyle yok sayılabilir. [Daha fazla bilgi](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Resim öğelerinin `[alt]` özellikleri yok"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Resim öğelerinin `[alt]` özellikleri var"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Bir resim `<input>` düğmesi olarak kullanılırken alternatif metin sağlamak, ekran okuyucu kullanıcılarının düğmenin amacını anlamalarına yardımcı olabilir. [Daha fazla bilgi](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` öğelerinin `[alt]` metni yok"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` öğelerinin `[alt]` metni var"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Etiketler, form kontrollerinin ekran okuyucular gibi yardımcı teknolojiler tarafından düzgün bir şekilde duyurulmasını sağlar. [Daha fazla bilgi](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Form öğelerinin ilişkili etiketleri yok"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Form öğelerinin ilişkili etiketleri var"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Düzen amaçlı kullanılan bir tablonun, veri öğeleri (ör. th veya başlık öğeleri ya da özet özelliği) içermemesi gerekir. Zira bu durum, ekran okuyucu kullanıcılarının kafa karıştırıcı bir deneyim yaşamalarına neden olabilir. [Daha fazla bilgi](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Sunu amaçlı `<table>` öğeleri `<th>`, `<caption>` veya `[summary]` özelliğini kullanmaktan kaçınmıyor."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Sunum amaçlı `<table>` öğeleri `<th>`, `<caption>` veya `[summary]` özelliğini kullanmaktan kaçınıyor."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Ayırt edilebilir, benzersiz ve odaklanılabilir bağlantı metni (ve bağlantı olarak kullanıldığında resimler için alternatif metin), ekran okuyucu kullanıcılarına daha iyi bir gezinme deneyimi sunar. [Daha fazla bilgi](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Bağlantıların ayırt edilebilir adları yok"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Bağlantıların ayırt edilebilir adları var"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Ekran okuyucular listeleri duyurmak için belirli bir yöntem kullanır. Liste yapısının gerektiği gibi olmasını sağlamak, ekran okuyucu çıkışının düzgün olmasına yardımcı olur. [Daha fazla bilgi](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Listeler yalnızca `<li>` öğelerini ve komut dosyası destekleyen öğeleri (`<script>` ve `<template>`) içermiyor."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Listeler yalnızca `<li>` öğelerini ve komut dosyası destekleyen öğeleri (`<script>` ve `<template>`) içeriyor."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Ekran okuyucuların liste öğelerini (`<li>`) düzgün bir şekilde okuyabilmesi için liste öğelerinin, üst `<ul>` veya `<ol>` öğesinde yer alması gerekir. [Daha fazla bilgi](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Liste öğeleri (`<li>`), `<ul>` veya `<ol>` üst öğelerinde yer almıyor."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Liste öğeleri (`<li>`), `<ul>` veya `<ol>` üst öğelerinde yer alıyor"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Kullanıcılar bir sayfanın otomatik olarak yenileneceğini düşünmez ve bu işlem yeniden sayfanın üst tarafına odaklanılmasına neden olur. Bu durum, can sıkıcı veya kafa karışıklığına yol açan bir deneyime yol açabilir. [Daha fazla bilgi](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Doküman `<meta http-equiv=\"refresh\">` kullanıyor"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Doküman `<meta http-equiv=\"refresh\">` öğesini kullanmıyor"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Yakınlaştırmanın devre dışı bırakılması, az gören ve bir web sayfasının içeriğini düzgün bir şekilde görebilmek için ekran büyütme özelliğinden yararlanan kullanıcılar için sorun teşkil eder. [Daha fazla bilgi](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]`, `<meta name=\"viewport\">` öğesinde kullanılmış veya `[maximum-scale]` özelliği 5'ten küçük."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]`, `<meta name=\"viewport\">` öğesinde kullanılmamış ve `[maximum-scale]` özelliği 5'ten küçük değil."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Ekran okuyucular metin dışı içeriği çeviremez. `<object>` öğelerine alternatif metin eklemek, ekran okuyucuların ilgili öğenin ne anlama geldiğini kullanıcılara söylemesine yardımcı olur. [Daha fazla bilgi](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` öğelerinin `[alt]` metni yok"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` öğelerinin `[alt]` metni var"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "0'dan büyük bir değer, açık bir gezinme sıralamasını belirtir. Bu durum teknik olarak geçerli olsa da yardımcı teknolojilerden yararlanan kullanıcıların genellikle sinir bozucu deneyimler yaşamalarına neden olur. [Daha fazla bilgi](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Bazı öğeler 0'dan büyük bir `[tabindex]` değeri içeriyor"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Hiçbir öğe 0'dan büyük `[tabindex]` değeri içermiyor"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Ekran okuyucuların tablolarda daha kolay gezinmeyi sağlayan özellikleri vardır. `[headers]` özelliğini kullanan`<td>` hücrelerinin yalnızca aynı tablodaki diğer hücrelere atıfta bulunmasını sağlamak, ekran okuyucu kullanıcılarına daha iyi bir deneyim sunabilir. [Daha fazla bilgi](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`<table>` öğesinde olup `[headers]` özelliğini kullanan hücrelerin atıfta bulunduğu öğe `id` aynı tabloda yer almıyor."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`<table>` öğesinde olup `[headers]` özelliğini kullanan hücreler, aynı tablodaki tablo hücrelerine atıfta bulunuyor."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Ekran okuyucuların tablolarda daha kolay gezinmeyi sağlayan özellikleri vardır. Tablo başlıklarının her zaman bazı hücre kümelerine atıfta bulunmasını sağlamak, ekran okuyucu kullanıcılarına daha iyi bir deneyim sunabilir. [Daha fazla bilgi](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` öğelerinin ve `[role=\"columnheader\"/\"rowheader\"]` içeren öğelerin açıkladıkları veri hücreleri yok."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` öğelerinin ve`[role=\"columnheader\"/\"rowheader\"]` içeren öğelerin açıkladıkları veri hücreleri var."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Öğelerde geçerli bir [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) belirtilmesi, ekran okuyucunun metni doğru telaffuz etmesini sağlar. [Daha fazla bilgi](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` özellikleri geçerli bir değere sahip değil"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` özellikleri geçerli bir değere sahip"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Bir videoda altyazının yer alması işitme engelli ve işitme zorluğuna sahip kullanıcıların videonun bilgilerine daha kolay erişmelerini sağlar. [Daha fazla bilgi](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` öğelerinde `[kind=\"captions\"]` içeren bir `<track>` öğesi bulunmuyor."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` öğelerinde `[kind=\"captions\"]`içeren bir `<track>` öğesi bulunuyor"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Sesli açıklamalar, videolarla ilgili olarak diyaloğun sağlayamayacağı bilgiler (ör. yüz ifadeleri ve sahneler) sağlar. [Daha fazla bilgi](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` öğelerinde `[kind=\"description\"]` içeren bir `<track>` öğesi bulunmuyor."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` öğelerinde `[kind=\"description\"]`içeren bir `<track>` öğesi bulunuyor"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Kullanıcılar ana ekranlarına progresif web uygulaması eklerinde iOS'ta ideal görünüm için bir `apple-touch-icon` öğesi tanımlayın. Tanım, saydam olmayan bir 192 piksel (veya 180 piksel) kare PNG'ye götürmelidir. [Daha Fazla Bilgi](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Geçerli bir `apple-touch-icon` öğesi içermiyor"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` güncel değil; `apple-touch-icon` tercih edilir."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Geçerli bir `apple-touch-icon` sunuyor"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome uzantıları bu sayfanın yükleme performansını olumsuz etkilemiştir. Sayfayı gizli modda veya uzantı içermeyen bir Chrome profilinden denetlemeyi deneyin."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Komut Dosyası Değerlendirmesi"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Komut Dosyası Ayrıştırma"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Toplam CPU Süresi"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "JS'yi ayrıştırma, derleme ve yürütme için harcanan zamanı kısaltmayı düşünün. Daha küçük JS yüklerinin sağlanması bu konuda yardımcı olabilir. [Daha fazla bilgi](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "JavaScript yürütme süresini azaltın"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript yürütme süresi"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Büyük GIF'ler, animasyonlu içeriğin sunulmasında verimli olmaz. Ağ veri miktarından tasarruf etmek üzere animasyonlar için MPEG4/WebM videoları ve statik resimler için GIF yerine PNG/WebP kullanma seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Animasyonlu içerik için video biçimleri kullanın"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Etkileşim için hazır olma süresini kısaltmak için ekran dışı ve gizli resimleri, tüm kritik kaynakların yüklenmesi bittikten sonra gecikmeli olarak yükleme seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Ekran dışındaki resimleri ertele"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Kaynaklar, sayfanızda ilk boyamayı engelliyor. Kritik JS/CSS'yi satır içinde yayınlama ve kritik olmayan tüm JS/stilleri erteleme seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Oluşturmayı engelleyen kaynakları ortadan kaldırın"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Büyük ağ yükleri kullanıcılar için parasal maliyet anlamına gelir ve yükleme sürelerinin uzamasında yüksek bir etkiye sahiptir. [Daha fazla bilgi](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Toplam boyut {totalBytes, number, bytes} KB'tı"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Çok büyük ağ yüklerinden kaçının"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Çok büyük ağ yüklerini önler"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "CSS dosyalarının küçültülmesi ağ yükü boyutlarını azaltabilir. [Daha fazla bilgi](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "CSS'yi küçültün"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "JavaScript dosyalarının küçültülmesi yük boyutlarını azaltabilir ve komut dosyası ayrıştırma süresini kısaltabilir. [Daha fazla bilgi](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "JavaScript'i küçült"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Ağ etkinliğinin gereksiz yere kullandığı bayt sayısını azaltmak için, kullanılmayan kuralları stil sayfalarından kaldırın ve ekranın üst kısmında içerik için kullanılmayan CSS'nin yüklenmesini erteleyin. [Daha fazla bilgi](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Kullanılmayan CSS'yi kaldırın"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Ağ etkinliğinin kullandığı bayt sayısını azaltmak için kullanılmayan JavaScript'i kaldırın."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Kullanılmayan JavaScript'i kaldırın"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Uzun önbellek ömrü, sayfanızın tekrar ziyaret edilmesi sürecini hızlandırabilir. [Daha fazla bilgi](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kaynak bulundu}other{# kaynak bulundu}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Statik öğeleri verimli bir önbellek politikasıyla yayınlayın"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Statik öğelerde verimli önbellek politikası kullanır"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Optimize edilmiş resimler daha hızlı yüklenir ve daha az hücresel veri kullanır. [Daha fazla bilgi](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Resimleri verimli bir şekilde kodlayın"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Hücresel veriden tasarruf etmek ve yükleme süresini kısaltmak için uygun boyutlu resimler sunun. [Daha fazla bilgi](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Doğru boyuta sahip resimler"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Metne dayalı kaynaklar, toplam ağ baytı sayısını en aza indirmek için sıkıştırılarak (gizp, deflate veya brotli) yayınlanmalıdır. [Daha fazla bilgi](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Metin sıkıştırmayı etkinleştirin"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000, JPEG XR ve WebP gibi resim biçimleri genellikle PNG veya JPEG'den daha iyi sıkıştırma sağlar. Böylece indirme işlemleri daha hızlı tamamlanır ve veri tüketimi daha az olur. [Daha fazla bilgi](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Resimleri yeni nesil biçimlerde yayınlayın"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Uygulamanızın içeriğinin genişliği, görüntü alanının genişliğiyle eşleşmiyorsa uygulamanız mobil ekranlar için optimize edilmemiş olabilir. [Daha fazla bilgi](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "{innerWidth} piksel görüntü alanı boyutu, {outerWidth} piksel pencere boyutuyla eşleşmiyor."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "İçerik, görüntü alanı için doğru boyutlandırılmadı"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "İçerik görüntü alanı için doğru boyutlandırıldı"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Aşağıdaki Kritik İstek Zincirleri, hangi kaynakların yüksek öncelikle yüklendiğini göstermektedir. Sayfa yüklemesini iyileştirmek için zincir uzunluğunu azaltma, kaynakların indirme boyutunu küçültme veya gereksiz kaynakların indirilmesini erteleme seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 zincir bulundu}other{# zincir bulundu}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Kritik İsteklerin Derinliğini En Aza İndirin"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Kullanımdan Kaldırma / Uyarı"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Satır"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Kullanımdan kaldırılan API'ler sonunda tarayıcıdan kaldırılacaktır. [Daha fazla bilgi](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 uyarı bulundu}other{# uyarı bulundu}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Kullanımdan kaldırılan API'leri kullanıyor"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Kullanımdan kaldırılan API'leri içermiyor"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache API'si kullanımdan kaldırılmıştır. [Daha fazla bilgi](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "\"{AppCacheManifest}\" bulundu"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Uygulama Önbelleği Kullanma"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Uygulama Önbelleği Kullanılmıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Bir DOCTYPE belirlemek, tarayıcının Quirks moduna geçmesini önler. [Daha fazla bilgi](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE adı, küçük harf `html` dizesi olmalıdır"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Doküman bir DOCTYPE içermelidir"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Beklenen publicId boş bir dize olmalı"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Beklenen systemId boş bir dize olmalı"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Sayfada HTML DOCTYPE eksik, bu nedenle Quirks modunu tetikliyor"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Sayfa HTML DOCTYPE içeriyor"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Öğe"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "İstatistik"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Değer"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Tarayıcı mühendisleri, sayfaların yaklaşık olarak 1.500'den az DOM öğesi içermesini önerir. En iyisi, 32 öğeden ve 60 alt/üst öğeden az olan bir ağaç derinliğidir. Büyük bir DOM, bellek kullanımını artırarak daha uzun [stil hesaplamalarına](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations), yol açabilir ve yüksek maliyetli [düzen yeniden düzenlemeleri](https://developers.google.com/speed/articles/reflow). [Daha fazla bilgi](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 öğe}other{# öğe}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Aşırı büyük bir DOM boyutundan kaçının"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Maksimum DOM Derinliği"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Tüm DOM Öğeleri"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Maksimum Alt Öğe"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Aşırı büyük bir DOM boyutunu önler"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Hedef"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Performansı artırmak ve güvenlik açıklarını önlemek için harici bağlantılara `rel=\"noopener\"` veya `rel=\"noreferrer\"` ekleyin. [Daha fazla bilgi](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Çapraz kökenli hedeflere bağlantılar güvenli değildir"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Çapraz kökenli hedeflere bağlantılar güvenli"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Bağlantı için hedef belirlenemedi ({anchorHTML}). Köprü olarak kullanılmadıysa target=_blank öğesini kaldırmayı değerlendirin."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Kullanıcılar herhangi bir bağlam olmadan konum bilgilerini isteyen sitelere şüpheyle bakarlar veya bu istek karşısında şaşırırlar. Onun yerine isteği bir kullanıcı işlemine bağlamayı değerlendirin. [Daha fazla bilgi](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Sayfa yüklemede coğrafi konum izni istiyor"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Sayfa yüklemede coğrafi konum izni istemiyor"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Sürüm"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Sayfadaki tüm JavaScript kitaplıkları kullanıcı arabirimleri algılandı. [Daha fazla bilgi](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "JavaScript kitaplıkları algılandı"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "`document.write()` aracılığıyla dinamik olarak enjekte edilen harici komut dosyaları, yavaş bağlantıdaki kullanıcılar için sayfa yüklemeyi onlarca saniye geciktirebilir. [Daha fazla bilgi](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "`document.write()` öğesini kullanıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "`document.write()` öğesinden kaçınıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "En Yüksek Önem Derecesi"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Kitaplık Sürümü"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Güvenlik Açığı Sayısı"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Bazı üçüncü taraf komut dosyaları, saldırganlar tarafından kolayca belirlenen ve istismar edilen bilinen güvenlik açıkları içerebilir. [Daha fazla bilgi](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 güvenlik açığı algılandı}other{# güvenlik açığı algılandı}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Bilinen güvenlik açıklarına sahip JavaScript kitaplıkları kullanıcı arabirimi içeriyor"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Yüksek"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Düşük"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Orta"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Bilinen güvenlik açıklarına sahip JavaScript kitaplıkları kullanıcı arabirimini önlüyor"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Kullanıcılar herhangi bir bağlam olmadan bildirim göndermek isteyen sitelere şüpheyle bakarlar veya bu istek karşısında şaşırırlar. Onun yerine isteği kullanıcı hareketlerine bağlamayı değerlendirin. [Daha fazla bilgi](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Sayfa yüklemede bildirim izni istiyor"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Sayfa yüklemede bildirim izni istemiyor"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Başarısız Öğeler"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Şifre yapıştırmanın engellenmesi, iyi güvenlik politikasına zarar verir. [Daha fazla bilgi](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Kullanıcıların şifre alanlarına yapıştırmalarını önler"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Kullanıcıların şifre alanlarına yapıştırmalarına izin verir"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Protokol"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2, HTTP/1.1'e kıyasla ikili başlıklar, çoğullama ve sunucu push mesajları dahil olmak üzere birçok avantaj sunar. [Daha fazla bilgi](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 istek HTTP/2 üzerinden sunulmuyor}other{# istek HTTP/2 üzerinden sunulmuyor}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Tüm kaynakları için HTTP/2 kullanmıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Kendi kaynakları için HTTP/2 kullanıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Sayfanızın kaydırma performansını artırmak için dokunma ve ve tekerlek etkinliği işleyicilerini `passive` olarak işaretlemeyi değerlendirin. [Daha fazla bilgi](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Kaydırma performansını artırmak için pasif işleyicileri kullanmıyor"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Kaydırma performansını artırmak için pasif işleyicileri kullanıyor"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Açıklama"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Konsola kaydedilen hatalar çözülmemiş problemleri belirtir Bunlar, ağ istek hatalarından ve diğer tarayıcı sorunlarından gelebilir. [Daha fazla bilgi](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Tarayıcı hataları konsola kaydedildi"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Konsola tarayıcı hatası kaydedilmedi"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Web yazı tipleri yüklenirken kullanıcının metni görebilmesini sağlamak için yazı tipi görüntüleme CSS özelliğinden yararlanın. [Daha fazla bilgi](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Web yazı tipi yüklemesi sırasında metnin görünür halde kalmasını sağlayın"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Web yazı tipi yüklenirken tüm metin görünür halde kalır"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse, şu URL için yazı tipi görüntüleme değerini otomatik olarak kontrol edemedi: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "En Boy Oranı (Gerçek)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "En Boy Oranı (Görüntülenen)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Resim görüntüleme boyutları doğal en boy oranıyla eşleşmeli. [Daha fazla bilgi](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Yanlış en boy oranına sahip resimler görüntülüyor"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Resimleri doğru en boy oranıyla görüntülüyor"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Geçersiz resim boyutlandırma bilgileri {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Tarayıcılar proaktif olarak kullanıcılardan uygulamanızı ana ekranlarına eklemelerini isteyebilirler ve bu da daha yüksek etkileşim sağlayabilir. [Daha fazla bilgi](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Web uygulaması manifest dosyası yüklenebilir olma gerekliliklerini karşılamıyor"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Web uygulaması manifest dosyası yüklenebilir olma gereklerini karşılar"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Güvenli olmayan URL"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Tüm siteler (hassas veriler işlemeyenler dahi) HTTPS ile korunmalıdır . HTTPS, izinsiz kişilerin uygulamanızla kullanıcılarınız arasındaki iletişime müdahale etmelerine veya pasif olarak dinlemelerini önler ayrıca HTTP/2 ve birçok yeni web platformu için ön koşuldur. [Daha fazla bilgi](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Güvenli olmayan 1 istek bulundu}other{Güvenli olmayan # istek bulundu}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "HTTPS kullanmıyor"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "HTTPS kullanıyor"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Sayfaların hücresel ağ üzerinden hızlı bir şekilde yüklenmesi, mobil cihaz kullanıcılarının iyi bir deneyim yaşamalarını sağlar. [Daha fazla bilgi](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Etkileşimli hale gelme süresi: {timeInMs, number, seconds} sn."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Sayfanın simüle mobil ağda etkileşime hazır hale gelmesi {timeInMs, number, seconds} sn. sürdü"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Sayfanız çok yavaş yükleniyor ve etkileşimli hale gelmesi 10 saniyeyi geçiyor. Nasıl iyileştireceğinizi öğrenmek için \"Performans\" bölümünde fırsatlara ve teşhise bakın."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Sayfalar mobil ağlarda yeterince hızlı yüklenmiyor"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Sayfalar mobil ağlarda yeterince hızlı yükleniyor"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Kategori"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "JS'yi ayrıştırma, derleme ve yürütme için harcanan zamanı kısaltmayı düşünün. Daha küçük JS yüklerinin sağlanması bu konuda yardımcı olabilir. [Daha fazla bilgi](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Ana iş parçacığı çalışmasını en aza indir"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Ana iş parçacığının çalışmasını en aza indirir"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Mümkün olduğunca fazla sayıda kullanıcıya ulaşmak için sitelerin belli başlı her tarayıcıda çalışması gerekir. [Daha fazla bilgi](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Site farklı tarayıcılarda çalışıyor"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Her bir sayfaya URL aracılığıyla derin bağlantı verilebildiğinden ve URL'lerin sosyal medyada paylaşılabilmesi için benzersiz olduğundan emin olun. [Daha fazla bilgi](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Her sayfa bir URL'ye sahip"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Yavaş ağlarda bile sağa sola dokundukça geçişlerin hızlı gerçekleştiği hissedilmelidir. Bu deneyim, kullanıcının performans algısının temelinde yatar. [Daha fazla bilgi](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Sayfa geçişleri ağda takılıyorlarmış gibi hissedilmiyor"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Tahmini Giriş Gecikmesi, sayfa yüklemesinin en yoğun olduğu 5 saniyelik zaman aralığında uygulamanızın kullanıcı girişine kaç milisaniye içinde yanıt vereceğine dair bir tahmindir. Gecikmeniz 50 ms.nin üzerinde olursa kullanıcılar uygulamanızın durakladığını düşünebilir. [Daha fazla bilgi](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Tahmini Giriş Gecikmesi"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "İlk Zengin İçerikli Boyama, ilk metnin veya resmin boyandığı zamanı işaret eder. [Daha fazla bilgi](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "İlk Zengin İçerikli Boya"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "İlk CPU Boşta metriği, sayfanın ana iş parçacığının girişi işlemek için yeterli olduğu ilk anı işaret eder. [Daha fazla bilgi](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "İlk CPU Boşta"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "İlk Anlamlı Boyama, bir sayfanın ana içeriğinin ne zaman görünür hale geldiğini ölçer. [Daha fazla bilgi](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "İlk Anlamlı Boya"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Etkileşime hazır olma süresi, sayfanın tamamen etkileşime hazır hale gelmesi için geçmesi gereken süreyi ifade eder. [Daha fazla bilgi](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Etkileşim Süresi"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Kullanıcılarınızın karşılaşabileceği olası maksimum İlk Giriş Gecikmesi, en uzun görevin milisaniye cinsinden süresidir. [Daha fazla bilgi](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Maksimum Olası İlk Giriş Gecikmesi"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Hız Endeksi, bir sayfa içeriğinin görsel olarak ne kadar hızlı doldurulabildiğini gösterir. [Daha fazla bilgi](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Hız İndeksi"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Görev süresi 50 ms.yi aştığında, FCP ile Etkileşime Hazır Olma Süresi arasındaki tüm dönemlerin milisaniye cinsinden toplamı."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Toplam Engellenme Süresi"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Ağ gidiş dönüş sürelerinin (RTT) performans üzerinde büyük bir etkisi vardır. Kaynağa RTT'nin fazla olması, kullanıcıya daha yakın olan sunucuların performansı iyileştirebileceğinin göstergesidir. [Daha fazla bilgi](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Ağ Gidiş Dönüş Süreleri"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Sunucudan kaynaklanan gecikmeler web performansını etkileyebilir. Bir kaynakta sunucu gecikmesinin fazla olması, sunucunun aşırı yüklendiğinin veya arka uç performansının kötü olduğunun göstergesidir. [Daha fazla bilgi](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Sunucunun Arka Uç Gecikmeleri"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Hizmet çalışanı web uygulamanızın öngörülemeyen ağ koşullarında güvenilir olmasını sağlar. [Daha fazla bilgi](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` çevrimdışıyken 200 koduyla yanıt vermiyor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` çevrimdışıyken 200 koduyla yanıt veriyor"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse, manifest dosyasından `start_url` öğesini okuyamadı. Bu yüzden `start_url` dokümanın URL'si olarak kabul edildi. Hata mesajı: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Bütçe Aşımı"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Ağ isteklerinin miktarını ve büyüklüğünü, performans bütçesi tarafından belirlenen hedeflerin altında tutun. [Daha fazla bilgi](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 istek}other{# istek}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Performans bütçesi"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Zaten HTTPS kurduysanız kullanıcılarınıza güvenli web özellikleri sağlayabilmek için tüm HTTP trafiğini HTTPS'ye yönlendirdiğinizden emin olun. [Daha fazla bilgi](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "HTTP trafiğini HTTPS'ye yönlendirmiyor"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "HTTP trafiğini HTTPS'ye yönlendiriyor"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Yönlendirmeler, sayfanın yüklenmesinden önce ek gecikmelere neden olur. [Daha fazla bilgi](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Birden çok sayfa yönlendirmesini önleyin"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Sayfa kaynaklarının miktarı ve büyüklüğü için bütçeler belirlemek üzere bir budget.json dosyası ekleyin. [Daha fazla bilgi](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 istek • {byteCount, number, bytes} KB}other{# istek • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "İstek sayısını az ve aktarma boyutlarını küçük tutun"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Standart bağlantılar, arama sonuçlarında hangi URL'nin gösterileceğini belirtir. [Daha fazla bilgi](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Birden fazla çakışan URL ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Farklı bir alan adına yönlendiriyor ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Geçersiz URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Başka bir `hreflang` konumuna ({url}) yönlendiriyor"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Göreli URL ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "İçeriğe eşdeğer bir sayfanın yerine alan adının kök URL'sine (ana sayfa) yönlendiriyor"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Doküman geçerli bir `rel=canonical` değeri içermiyor"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Doküman geçerli bir `rel=canonical` öğesi içeriyor"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12 pikselden küçük yazı tipi boyutları okunamayacak kadar küçüktür ve mobil cihaz kullanıcılarının içeriği okuyabilmek için parmaklarıyla sıkıştırma hareketi yaparak yakınlaştırmalarını gerektirir. Sayfanın %60'ından fazlasının en az 12 piksel boyutunda olmasını sağlamaya çalışın. [Daha fazla bilgi](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} kadar okunabilir metin"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Mobil ekranlar için optimize edilmiş görüntü alanı meta etiketi olmadığından metin okunaklı değil."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Metnin {decimalProportion, number, extendedPercent} kadarı çok küçük ({decimalProportionVisited, number, extendedPercent} örneği baz alınarak)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Dokümanda okunabilir yazı tipi boyutları kullanılmıyor"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Dokümanda okunabilir yazı tipi boyutları kullanılıyor"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang bağlantıları, arama motorlarına, belirli bir dildeki veya bölgedeki arama sonuçlarında bir sayfanın hangi sürümünün listeleneceğini bildirir. [Daha fazla bilgi](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Doküman geçerli bir `hreflang` öğesi içermiyor"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Doküman geçerli bir `hreflang` öğesi içeriyor"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Başarısız HTTP durum kodlarına sahip olan sayfalar düzgün bir şekilde dizine eklenmeyebilir. [Daha fazla bilgi](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Sayfa başarısız bir HTTP durum koduna sahip"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Sayfa başarılı bir HTTP durum koduna sahip"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Sayfalarınız, tarama iznine sahip olmayan arama motorları tarafından arama sonuçlarına eklenemez. [Daha fazla bilgi](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Sayfanın dizine eklenmesi engellenmiş"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Sayfanın dizine eklenmesi engellenmemiş"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Açıklayıcı bağlantı metni, arama motorlarının içeriğinizi anlamasına yardımcı olur. [Daha fazla bilgi](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 bağlantı bulundu}other{# bağlantı bulundu}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Bağlantılar açıklayıcı metin içermiyor"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Bağlantılar açıklayıcı metin içeriyor"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Yapılandırılmış verileri doğrulamak için [Yapılandırılmış Veri Test Aracı](https://search.google.com/structured-data/testing-tool/)'nı ve [Structured Data Linter](http://linter.structured-data.org/)'ı çalıştırın. [Daha fazla bilgi](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Yapılandırılmış veriler geçerli"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Sayfa içeriğini kısa ve öz bir şekilde özetlemek amacıyla arama sonuçlarına meta tanımlar eklenebilir. [Daha fazla bilgi](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Açıklama metni boş."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Doküman meta tanım içermiyor"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Doküman meta tanım içeriyor"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Arama motorları eklenti içeriğini dizine ekleyemez. Ayrıca birçok cihaz eklentileri kısıtlar veya desteklemez. [Daha fazla bilgi](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Doküman, eklenti kullanıyor"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Doküman eklenti içermiyor"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "robots.txt dosyanız yanlış biçimlendirilmişse, tarayıcılar web sitenizin nasıl taranmasını veya dizine eklenmesini istediğinizi anlayamayabilir. [Daha fazla bilgi](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Robots.txt isteği şu HTTP durumunu döndürdü: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{1 hata bulundu}other{# hata bulundu}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse bir robots.txt dosyasını indiremedi"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt dosyası geçerli değil"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt dosyası geçerli"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Düğmeler ve bağlantılar gibi etkileşimli öğelerin, başka öğelerle üst üste binmeden rahatlıkla dokunulabilecek kadar büyük olması (48x48 piksel) ve etrafında yeterli boşluk bulunması gerekir. [Daha fazla bilgi](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "Dokunma hedeflerinin {decimalProportion, number, percent} kadarı uygun boyutta"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Mobil ekranlar için optimize edilmiş görüntü alanı meta etiketi olmadığından dokunma hedefleri çok küçük"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Dokunma hedefleri uygun boyutta değil"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Çakışan Hedef"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Dokunma Hedefi"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Dokunma hedefleri uygun boyutta"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Servis çalışanı, uygulamanızın çevrimdışı çalışma, ana ekrana ekleme ve push bildirimleri gibi pek çok Progresif Web Uygulaması özelliğini kullanmasını sağlayan teknolojidir. [Daha fazla bilgi](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Sayfa bir hizmet çalışanı tarafından kontrol ediliyor ancak manifest dosyası geçerli JSON olarak ayrışmadığından `start_url` bulunamadı"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Sayfa bir hizmet çalışanı tarafından kontrol ediliyor ancak `start_url` ({startUrl}) öğesi hizmet çalışanının kapsamında ({scopeUrl}) değil"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Bu sayfa bir hizmet çalışanı tarafından yönetiliyor ancak manifest dosyası getirilmediğinden `start_url` öğesi bulunamadı."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Bu kaynak bir veya daha fazla hizmet çalışanına sahip ancak sayfa ({pageUrl}) kapsam içinde değil."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Sayfayı kontrol eden bir hizmet çalışanı ve `start_url` öğesi kaydedilmiyor"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Sayfayı kontrol eden bir hizmet çalışanı ve `start_url` öğesi kaydediliyor"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Temalı başlangıç ekranı, kullanıcılar uygulamanızı ana ekranlarında başlattığında yüksek kaliteli bir deneyim sağlar. [Daha fazla bilgi](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Özel başlangıç ekranı için yapılandırılmadı"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Özel başlangıç ekranı için yapılandırıldı"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Sitenizle eşleşmesi için tarayıcı adres çubuğu temalı yapılabilir. [Daha fazla bilgi](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Adres çubuğu için tema rengi ayarlamıyor."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Adres çubuğu için tema rengi ayarlar."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Ana İleti Dizisi Engelleme Süresi"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Üçüncü Taraf"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Üçüncü taraf kodu, yükleme performansını önemli ölçüde etkileyebilir. Yedekli üçüncü taraf sağlayıcıların sayısını sınırlayın ve öncelikle sayfanızın yüklenmesi tamamlandıktan sonra üçüncü taraf kodunu yükleyin. [Daha fazla bilgi](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Üçüncü taraf kodu, ana ileti dizisini {timeInMs, number, milliseconds} ms. süreyle engelledi"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Üçüncü taraf kodun etkisini azaltın"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Üçüncü Taraf Kullanımı"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "İlk Bayt Zamanı, sunucunuzun yanıt gönderme zamanını tanımlar. [Daha fazla bilgi](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Root doküman {timeInMs, number, milliseconds} ms. sürdü"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Sunucu yanıt sürelerini kısaltın (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Sunucu yanıt süreleri düşük (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Süre"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Başlangıç Zamanı"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Tür"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Önemli kullanıcı deneyimleri esnasında uygulamanızın gerçek dünya performansını ölçmek için uygulamanıza User Timing API'si ekleme seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 kullanıcı zamanlaması}other{# kullanıcı zamanlaması}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Kullanıcı Zamanlaması işaretleri ve ölçüleri"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "\"{securityOrigin}\" için bir önceden bağlanma <link> öğesi bulundu ancak tarayıcı tarafından kullanılmadı. `crossorigin` özelliğini gerektiği gibi kullandığınızdan emin olun."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Önemli üçüncü taraf kaynaklarına erken bağlantılar oluşturmak için `preconnect` veya `dns-prefetch` kaynak ipuçları ekleme seçeneğini değerlendirin. [Daha fazla bilgi](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Gerekli kaynaklara önceden bağlan"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "\"{preloadURL}\" için bir önceden yükleme <link> bulundu ancak tarayıcı tarafından kullanılmadı. `crossorigin` özelliğini gerektiği gibi kullandığınızdan emin olun."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Mevcut durumda sayfa yüklemesinden sonra istenen kaynakları daha önce getirmek için `<link rel=preload>` kullanmayı düşünün. [Daha fazla bilgi](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Önemli istekleri önceden yükleyin"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Uygulamanızı mobil ekranlar için optimize etmek üzere `<meta name=\"viewport\">` etiketi ekleyin. [Daha fazla bilgi](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "`<meta name=\"viewport\">` etiketi bulunamadı"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "`width` veya `initial-scale` değerleri olan bir `<meta name=\"viewport\">` etiketi yok"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "`width` veya `initial-scale` değerleri olan bir `<meta name=\"viewport\">` etiketi var"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Uygulamanız, JavaScript devre dışı bırakıldığında bazı içerikler görüntülemelidir. Bu içerik, kullanıcıya uygulamayı kullanmak için JavaScript gerektiğini belirten bir uyarı bile olabilir. [Daha fazla bilgi](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Komut dosyaları kullanılamıyorsa sayfa gövdesi bazı içerikler oluşturmalıdır."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "JavaScript kullanılamadığında ikame içerik sağlamıyor"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "JavaScript kullanılamadığında bazı içerikler bulundurur"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Progresif Web Uygulaması oluşturuyorsanız uygulamanızın çevrimdışı da çalışabilmesi için hizmet çalışanı kullanmayı düşünün. [Daha fazla bilgi](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Geçerli sayfa çevrimdışıyken 200 koduyla yanıt vermiyor"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Geçerli sayfa çevrimdışıyken 200 koduyla yanıt veriyor"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Sayfa, test URL'niz ({requested}) \"{final}\" adresine yönlendirildiğinden çevrimdışı yüklenmiyor olabilir. Doğrudan ikinci URL'yi test etmeyi deneyin."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Bu fırsatlar, uygulamanızda ARIA kullanımının iyileştirilmesine olanak tanır. Bu da ekran okuyucu gibi yardımcı teknolojilerin kullanıcılarına daha iyi bir deneyim sunulmasını sağlayabilir."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Bu fırsatlar, alternatif ses ve video içerikleri sağlanmasına olanak tanır. Bu durum, işitme veya görme bozukluğu olan kullanıcıların daha iyi bir deneyim yaşamalarını sağlayabilir."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Ses ve video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Bu öğeler, erişilebilirlikle ilgili yaygın en iyi uygulamaları öne çıkarır."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "En iyi uygulamalar"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Bu kontroller, [web uygulamanızın erişilebilirliğini iyileştirme](https://developers.google.com/web/fundamentals/accessibility) fırsatlarını ön plana çıkarır. Erişilebilirlik sorunlarının yalnızca bir alt kümesi otomatik olarak algılanabildiğinden manuel test yapılması da önerilir."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Bu öğeler, otomatik test aracının kapsamında yer almayan alanları ele alır. [Erişilebilirlik incelemesi gerçekleştirme](https://developers.google.com/web/fundamentals/accessibility/how-to-review) hakkında daha fazla bilgiyi rehberimizde bulabilirsiniz."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Erişilebilirlik"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Bu fırsatlar, içeriğinizin daha rahat okunmasına olanak tanır."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Kontrast"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Bu fırsatlar, içeriğinizin farklı ülkelerdeki kullanıcılar tarafından daha iyi yorumlanmasına olanak tanır."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Uluslararası hale getirme ve yerelleştirme"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Bu fırsatlar, uygulamanızdaki kontrollerin anlamının iyileştirilmesine olanak tanır. Bu durum, ekran okuyucu gibi yardımcı teknolojilerin kullanıcılarına daha iyi bir deneyim sunulmasını sağlayabilir."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Adlar ve etiketler"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Bu fırsatlar, uygulamanızda klavyeyle gezinmeyi kolaylaştırır."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Gezinme"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Bu fırsatlar, tablo veya liste halindeki verilerin ekran okuyucu gibi yardımcı teknolojiler kullanılarak daha rahat okunmasına olanak tanır."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Tablolar ve listeler"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "En İyi Uygulamalar"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Performans bütçeleri, sitenizin performansı için standartları belirler."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Bütçeler"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Uygulamanızın performansı hakkında daha fazla bilgi. Bu sayılar Performan skoruna [doğrudan etki](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) etmezler."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Teşhis"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Performansın en kritik unsuru, piksellerin ekranda oluşturulma hızıdır. Önemli metrikler: İlk Zengin İçerikli Boya, İlk Anlamlı Boya"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "İlk Boya İyileştirmeleri"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Bu öneriler, sayfanızın daha hızlı yüklenmesine yardımcı olabilir. Performan skoruna [doğrudan etki](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) etmezler."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Fırsatlar"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Metrikler"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Toplam yükleme deneyimini geliştirerek sayfanın mümkün olan en kısa sürede duyarlı ve kullanıma hazır olmasını sağlayın. Önemli metrikler: Etkileşim Süresi, Hız İndeksi"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Toplam İyileştirmeler"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Performans"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Bu denetimler, bir Progresif Web Uygulamasının çeşitli yönlerini doğrular. [Daha fazla bilgi](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Temel [Progresif Web Uygulaması Yapılacaklar Listesi](https://developers.google.com/web/progressive-web-apps/checklist) tarafından zorunlu tutulan bu denetimler, Lighthouse tarafından otomatik olarak kontrol edilmez. Bunlar skorunuzu etkilemez ancak manuel olarak doğrulamanız önemlidir."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Progresif Web Uygulaması"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Hızlı ve güvenilir"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Yüklenebilir"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Optimize Edilmiş PWA (Progresif Web Uygulaması)"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Bu kontroller, sayfanızın arama motoru sonuç sıralaması için optimize edilmesini sağlar. Lighthouse tarafından kontrol edilmeyen, ancak aramadaki sıralamanızı etkileyebilecek başka faktörler de vardır. [Daha fazla bilgi](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "SEO ile ilgili diğer en iyi uygulamaları kontrol etmek için sitenizde bu ek doğrulayıcıları çalıştırın."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Tarayıcıların uygulamanızın içeriğini daha iyi anlamasını sağlayacak şekilde HTML kodunuzu biçimlendirin."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "İçerik En İyi Uygulamaları"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Uygulamanızın arama sonuçlarında görünmesi için, tarayıcıların uygulamanıza erişmesi gerekir."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Tarama ve Dizine Ekleme"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Kullanıcıların küçültme veya yakınlaştırma hareketi yapmadan sayfadaki içerikleri okuyabilmelerini sağlamak için sayfalarınızın mobil uyumlu olduğundan emin olun. [Daha fazla bilgi](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Mobil Uyumlu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL'yi Önbelleğe Alma"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Konum"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Ad"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "İstek Sayısı"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Kaynak Türü"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Boyut"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Harcanan Süre"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Aktarım Boyutu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Potansiyel Tasarruflar"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Potansiyel Tasarruflar"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "{wastedBytes, number, bytes} KB potansiyel tasarruf"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "{wastedMs, number, milliseconds} ms. potansiyel tasarruf"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Doküman"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Yazı tipi"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Resim"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Medya"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} ms."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Diğer"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Komut dosyası"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} sn."
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Stil Sayfası"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Üçüncü taraf"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Toplam"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Sayfa yüklemenizin izlemesi kaydedilirken bir sorun oluştu. Lütfen Lighthouse'u tekrar çalıştırın. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "İlk Hata Ayıklayıcı Protokolü bağlantısı beklenirken zaman aşımı oluştu."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome, sayfa yükleme sırasında ekran görüntüsü toplayamadı. Lütfen sayfada görülebilir içerik olduğundan emin olun ve sonra Lighthouse'u tekrar çalıştırmayı deneyin. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS sunucuları sağlanan alan adını çözümleyemedi."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Zorunlu {artifactName} toplayıcı bir hatayla karşılaştı: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Dahili bir Chrome hatası oluştu. Lütfen Chrome'u yeniden başlatıp Lighthouse'u tekrar çalıştırmayı deneyin."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Zorunlu {artifactName} toplayıcı çalışmadı."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse istediğiniz sayfayı güvenli bir şekilde yükleyemedi. Doğru URL'yi test ettiğinizden ve sunucunun tüm isteklere gerektiği gibi yanıt verdiğinden emin olun."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Sayfa yanıt vermeyi durdurduğu için Lighthouse istediğiniz URL'yi güvenli bir şekilde yükleyemedi."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Sağladığınız URL, geçerli güvenlik sertifikasına sahip değil. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome bir geçiş reklamıyla sayfa yüklemesini önledi. Doğru URL'yi test ettiğinizden ve sunucunun tüm isteklere gerektiği gibi yanıt verdiğinden emin olun."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse istediğiniz sayfayı güvenli bir şekilde yükleyemedi. Doğru URL'yi test ettiğinizden ve sunucunun tüm isteklere gerektiği gibi yanıt verdiğinden emin olun. (Ayrıntılar: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse istediğiniz sayfayı güvenli bir şekilde yükleyemedi. Doğru URL'yi test ettiğinizden ve sunucunun tüm isteklere gerektiği gibi yanıt verdiğinden emin olun. (Durum kodu: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Sayfanın yüklenmesi çok uzun sürdü. Sayfanızın yüklenme süresini azaltmak için lütfen rapordaki fırsatları uygulayın ve sonra Lighthouse'u tekrar çalıştırmayı deneyin. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "DevTools protokol yanıtının beklenmesi için ayrılan süre aşıldı. (Yöntem: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Kaynak içeriğinin getirilmesi için ayrılan süre aşıldı"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Sağladığınız URL'nin geçersiz olduğu anlaşılıyor."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Denetimleri göster"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "İlk Gezinme"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Maksimum kritik yol gecikmesi:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Hata!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Bildirme hatası: denetim bilgisi yok"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Test Verileri"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Mevcut sayfanın mobil ağ kullanılarak gerçekleştirilen [Lighthouse](https://developers.google.com/web/tools/lighthouse/) analizi. Değerler tahminidir ve değişiklik gösterebilir."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Manuel olarak kontrol edilecek ek öğeler"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Geçerli değil"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Fırsat"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Tahmini Tasarruf Miktarı"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Başarılı denetimler"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Snippet'i daralt"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Snippet'i genişlet"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "3. taraf kaynaklarını göster"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Şu Lighthouse çalışmasını etkileyen sorunlar vardı:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Değerler tahminidir ve değişiklik gösterebilir. Performans skoru [sadece bu metriklere dayanır](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Kontrollerden geçti, ancak uyarılar var"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Uyarılar: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "GIF dosyanızı, HTML5 videosu olarak katıştırmak için kullanılabilmesini sağlayacak bir hizmete yüklemeyi düşünün."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Ekran dışı görüntüleri erteleme veya bu işlevselliği sağlayan bir temaya geçiş yapma olanağı veren bir [WordPress geç yükleme (lazy-load) eklentisi](https://wordpress.org/plugins/search/lazy+load/) yükleyin. Ayrıca [AMP eklentisini](https://wordpress.org/plugins/amp/) kullanmayı da değerlendirin."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "[Kritik öğeleri satır içi yapmanıza](https://wordpress.org/plugins/search/critical+css/) veya [daha az önemli kaynakları ertelemenize](https://wordpress.org/plugins/search/defer+css+javascript/) yardımcı olabilecek çeşitli WordPress eklentileri vardır. Bu eklentilerin sağlayacağı optimizasyonların tema veya eklentilerinizin özelliklerini bozabileceğine dikkat edin. Bunu engellemek için muhtemelen kodda değişiklik yapmanız gerekecektir."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Temalar, eklentiler ve sunucu özellikleri öğelerinin tümü sunucunun yanıt süresini etkiler. Bir optimizayon eklentisini dikkatle seçerek ve/veya sunucunuzu yeni sürüme geçirerek, daha ileri düzeyde optimize edilmiş bir tema bulmayı düşünün."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Yayın listelerinizde alıntılar göstermeyi (ör. daha fazla etiket kullanarak), belirli bir sayfada gösterilen yayınların sayısını azaltmayı, uzun yayınlarınızı birden fazla sayfaya bölmeyi veya yorumların geç yüklenmesi için bir eklenti kullanmayı düşünün."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Çeşitli [WordPress eklentileri](https://wordpress.org/plugins/search/minify+css/) stillerinizi sıralayarak, küçülterek ve sıkıştırarak sitenizi hızlandırabilir. Ayrıca mümkünse bu küçültme yapmak için bir derleme işlemi kullanmak isteyebilirsiniz."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Çeşitli [WordPress eklentileri](https://wordpress.org/plugins/search/minify+javascript/) komut dosyalarınızı sıralayarak, küçülterek ve sıkıştırarak sitenizi hızlandırabilir. Ayrıca mümkünse bu sadeleştirmeyi yapmak için bir derleme işlemi kullanmak isteyebilirsiniz."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Sayfanızda kullanılmayan CSS'ler yükleyen [WordPress eklentilerinin](https://wordpress.org/plugins/) sayısını azaltmayı veya değiştirmeyi düşünün. Gereksiz CSS ekleyen eklentileri belirlemek için Chrome Geliştirme Araçlarında [kod kapsamını](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) çalıştırmayı deneyin. Sorumlu temayı/eklentiyi stil sayfasının URL'sinden belirleyebilirsiniz. Listede çok sayıda stil sayfasına sahip olan ve kod kapsamında çok sayıda kırmızı işaret taşıyan eklentileri arayın. Bir eklenti sadece sayfada gerçekten kullanılan bir stil sayfasını kuyruğa almalıdır."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Sayfanızda kullanılmayan JavaScript'ler yükleyen [WordPress eklentilerinin](https://wordpress.org/plugins/) sayısını azaltmayı veya değiştirmeyi değerlendirin. Gereksiz JS ekleyen eklentileri belirlemek için Chrome Geliştirme Araçlarında [kod kapsamını](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) çalıştırmayı düşünün. Sorumlu temayı/eklentiyi komut dosyasının URL'sinden belirleyebilirsiniz. Listede çok sayıda komut dosyasına sahip olan ve kod kapsamında çok sayıda kırmızı işaret taşıyan eklentileri arayın. Bir eklenti sadece sayfada gerçekten kullanılan bir komut dosyasını kuyruğa almalıdır."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "[WordPress'te Tarayıcı Önbelleği](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching) ile ilgili bilgi edinin."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Kaliteden ödün vermeden resimlerinizi sıkıştıran bir [resim optimizasyonu WordPress eklentisi](https://wordpress.org/plugins/search/optimize+images/) kullanmayı değerlendirin."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Gerekli resim boyutlarının kullanılabilmesi için resimleri doğrudan [medya kitaplığından](https://codex.wordpress.org/Media_Library_Screen) yükleyin, ardından ideal resim boyutlarının kullanıldığından (esnek ayrılma noktası için olanlar dahil) emin olmak için resimleri medya kitaplığından ekleyin veya resim widget'ını kullanın. Boyutları kullanım için yeterli değilse `Full Size` resimler kullanmaktan kaçının. [Daha fazla bilgi](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Web sunucunuzun yapılandırmasında metin sıkıştırmayı etkinleştirebilirsiniz."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Yüklediğiniz resimleri ideal biçimlere otomatik olarak dönüştürecek bir [eklenti](https://wordpress.org/plugins/search/convert+webp/) veya hizmet kullanmayı değerlendirin."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/uk.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/uk.json
new file mode 100644
index 00000000000..28499fa73ef
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/uk.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Ключі доступу дають змогу швидко виділяти частину сторінки. Для належної навігації кожний ключ доступу має бути унікальним. [Докладніше](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Значення `[accesskey]` неунікальні"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Значення `[accesskey]` унікальні"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Кожна `role` ARIA підтримує конкретний набір атрибутів `aria-*`. Якщо вони не збігаються, атрибути `aria-*` стають недійсними. [Докладніше](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Атрибути `[aria-*]` не відповідають своїм ролям"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Атрибути `[aria-*]` відповідають своїм ролям"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Деякі ролі ARIA мають обов'язкові атрибути, що описують стан елемента для програм зчитування з екрана. [Докладніше](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "Ролі `[role]` не мають усіх обов'язкових атрибутів `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "Ролі `[role]` мають усі потрібні атрибути `[aria-*]`"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Щоб виконувати потрібні функції спеціальних можливостей, деякі батьківські ролі ARIA повинні містити відповідні дочірні ролі. [Докладніше](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "В елементах з ARIA `[role]`, які вимагають дочірні елементи з певним атрибутом `[role]`, немає кількох або всіх дочірніх елементів."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Елементи з ARIA `[role]`, які вимагають дочірні елементи з певним атрибутом `[role]`, мають усі необхідні дочірні елементи."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Щоб належно виконувати потрібні функції спеціальних можливостей, відповідні батьківські ролі повинні містити деякі дочірні ролі ARIA. [Докладніше](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "Ролі `[role]` не містяться в обов'язковому батьківському елементі"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "Ролі `[role]` містяться у відповідному батьківському елементі"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Щоб належно виконувати функції спеціальних можливостей, ролі ARIA повинні мати дійсні значення. [Докладніше](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Значення `[role]` недійсні"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Значення `[role]` дійсні"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Допоміжні технології, як-от програми зчитування з екрана, не можуть тлумачити атрибути ARIA з недійсними значеннями. [Докладніше](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Атрибути `[aria-*]` не мають дійсних значень"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Атрибути `[aria-*]` мають дійсні значення"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Допоміжні технології, як-от програми зчитування з екрана, не можуть тлумачити атрибути ARIA з недійсними назвами. [Докладніше](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Атрибути `[aria-*]` недійсні або написані неправильно"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Атрибути `[aria-*]` дійсні та написані правильно"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Субтитри роблять звукові елементи ефективнішими для користувачів із вадами слуху, зокрема надають важливу інформацію про те, хто й що говорить, а також інші непов'язані з мовленням деталі. [Докладніше](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Елементи `<audio>` не містять елемент `<track>` з атрибутом `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Елементи `<audio>` містять елемент `<track>` з атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Елементи, що не пройшли перевірку"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Коли кнопка не має зрозумілої назви, програми зчитування з екрана озвучують її словом \"кнопка\", через що вона стає непридатною для користувачів. [Докладніше](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Кнопки не мають доступних для зчитування назв"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Кнопки мають доступну для зчитування назву"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Якщо додати способи обходу вмісту, що повторюється, користувачам буде простіше переходити між елементами на сторінці за допомогою клавіатури. [Докладніше](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Сторінка не містить заголовка, посилання для пропуску вмісту чи мітки області"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Сторінка містить заголовок, посилання для пропуску вмісту чи мітку області"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Для багатьох користувачів складно або неможливо читати текст із низькою контрастністю. [Докладніше](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Між кольорами фону та переднього плану недостатній коефіцієнт контрастності."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Між кольорами фону та переднього плану достатній коефіцієнт контрастності"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Коли списки визначень мають неправильну розмітку, програми зчитування з екрана можуть генерувати незрозумілі або неточні дані. [Докладніше](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "Списки визначення `<dl>` містять не лише належно впорядковані групи `<dt>` і `<dd>` чи елементи `<script>` або `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "Списки визначення `<dl>` містять лише належно впорядковані групи `<dt>` та `<dd>` чи елементи `<script>` або `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Щоб програми зчитування з екрана правильно озвучували елементи списку визначень (`<dt>` і `<dd>`), елементи має бути згруповано в батьківському елементі `<dl>`. [Докладніше](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Елементи списку визначень не згруповано в елементах `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Елементи списку визначень згруповано в елементах `<dl>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Завдяки назві користувачі програми зчитування з екрана дізнаються загальну інформацію про сторінку, а користувачі пошукових систем визначають, чи сторінка відповідає їхньому запиту. [Докладніше](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Документ не має елемента `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Документ містить елемент `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Значення атрибута ідентифікатора має бути унікальним, щоб допоміжні технології не пропускали інші копії. [Докладніше](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Атрибути `[id]` на сторінці неунікальні"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Атрибути `[id]` на сторінці унікальні"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Користувачі програм зчитування з екрана використовують назви фреймів, щоб дізнатися їх вміст. [Докладніше](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Елементи `<frame>` або `<iframe>` не мають назви"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Елементи `<frame>` або `<iframe>` мають назву"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Якщо для сторінки не вказано атрибут мови, програма зчитування з екрана припускає, що мовою сторінки є мова за умовчанням, яку користувач вибрав під час налаштування програми зчитування. Якщо насправді мова сторінки інша, програма зчитування з екрана може неправильно озвучувати текст на сторінці. [Докладніше](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Елемент `<html>` не має атрибута `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Елемент `<html>` містить атрибут `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Якщо указати дійсний тег мови за [стандартом BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), це допоможе програмі зчитування з екрана правильно озвучувати текст. [Докладніше](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Елемент `<html>` не містить дійсного значення для атрибута `[lang]`."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Елемент `<html>` має дійсне значення атрибута `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Інформативні елементи повинні містити короткий, описовий альтернативний текст. Декоративні елементи можуть ігноруватись і мати порожній атрибут alt. [Докладніше](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Елементи зображення не мають атрибутів `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Елементи зображення мають атрибути `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Коли зображення використовується як кнопка `<input>`, додавши альтернативний текст, ви допоможете користувачам програм зчитування з екрана зрозуміти призначення кнопки. [Докладніше](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Елементи `<input type=\"image\">` не містять текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Елементи `<input type=\"image\">` містять текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Завдяки міткам допоміжні технології, як-от програми зчитування з екрана, правильно озвучують елементи керування формою. [Докладніше](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Елементи форми не мають пов’язаних міток"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Елементи форми мають пов’язані мітки"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Таблиця, яка використовується як макет, не повинна містити елементів даних, як-от елементів th або caption чи атрибут summary, оскільки це може спантеличити користувачів програм зчитування з екрана. [Докладніше](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Презентаційні елементи `<table>` використовують атрибути `<th>`, `<caption>` або `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Презентаційні елементи `<table>` не використовують атрибути `<th>`, `<caption>` або `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Унікальний і доступний для виділення текст посилання (а також альтернативний текст для зображень, коли вони використовуються як посилання), який можна розпізнати, покращує навігацію для користувачів програм зчитування з екрана. [Докладніше](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Посилання не мають назв, які можна розпізнати"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Посилання мають назви, які можна розпізнати"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Програми зчитування з екрана озвучують списки в особливий спосіб. Правильна структура списків допомагає таким програмам правильно розпізнавати інформацію. [Докладніше](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Списки не містять лише елементи `<li>` і елементи для підтримки виконання сценарію (`<script>` та `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Списки містять лише елементи `<li>` й елементи для підтримки виконання сценарію (`<script>` і `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Щоб програми зчитування з екрана правильно озвучували елементи списку (`<li>`), ці елементи повинні міститися в батьківських елементах `<ul>` або `<ol>`. [Докладніше](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Елементів списку (`<li>`) немає в батьківських елементах `<ul>` або `<ol>`."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Елементи списку (`<li>`) містяться в батьківських елементах `<ul>` або `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Користувачі не очікують, що сторінка оновлюватиметься автоматично. Таке оновлення перемістить фокус назад угору сторінки. Це може роздратувати або спантеличити користувачів. [Докладніше](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Документ використовує `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Документ не використовує тег `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Якщо вимкнути масштабування, користувачі з поганим зором не зможуть збільшити екран, щоб краще бачити вміст веб-сторінки. [Докладніше](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "Параметр `[user-scalable=\"no\"]` використовується в елементі `<meta name=\"viewport\">` або атрибут `[maximum-scale]` менший за 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "Параметр `[user-scalable=\"no\"]` не використовується в елементі `<meta name=\"viewport\">`, а атрибут `[maximum-scale]` має значення не менше 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Програми зчитування з екрана розпізнають лише текст. Якщо додати текст заміщення до елементів `<object>`, це допоможе таким програмам передати їх значення користувачам. [Докладніше](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Елементи `<object>` не містять текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Елементи `<object>` містять текст `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Значення, що перевищує 0, передбачає явне встановлення порядку навігації. Хоча технічно воно дійсне, це часто ускладнює взаємодію для користувачів, які застосовують допоміжні технології. [Докладніше](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Деякі елементи мають значення `[tabindex]`, що перевищує 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Жоден елемент не має значення `[tabindex]`, що перевищує 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Програми зчитування з екрана мають функції, які полегшують навігацію в таблицях. Якщо клітинки `<td>`, які використовують атрибут `[headers]`, посилаються лише на інші клітинки в тій самій таблиці, це може покращити взаємодію для користувачів програми зчитування з екрана. [Докладніше](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Клітинки в елементі `<table>`, які використовують атрибут `[headers]`, посилаються на елемент `id`, відсутній в тій самій таблиці."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Клітинки в елементі `<table>`, які використовують атрибут `[headers]`, посилаються на клітинки тієї ж таблиці."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Програми зчитування з екрана мають функції, які полегшують навігацію в таблицях. Якщо заголовки таблиці завжди посилаються на певні набори клітинок, це може покращити взаємодію для користувачів програм зчитування з екрана. [Докладніше](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Елементи `<th>` і елементи з роллю `[role=\"columnheader\"/\"rowheader\"]` не містять клітинок із даними, які описують."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Елементи `<th>` і елементи з роллю `[role=\"columnheader\"/\"rowheader\"]` містять клітинки з даними, які описують."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Якщо для елементів указати дійсний тег мови за [стандартом BCP 47](https://www.w3.org/International/questions/qa-choosing-language-tags#question), це допоможе програмі зчитування з екрана правильно озвучувати текст. [Докладніше](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Атрибути `[lang]` не мають дійсного значення"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Атрибути `[lang]` мають дійсне значення"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Коли відео має субтитри, користувачам із вадами слуху простіше зрозуміти його. [Докладніше](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Елементи `<video>` не містять елемент `<track>` з атрибутом `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Елементи `<video>` містять елемент `<track>` з атрибутом `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Звукові описи надають важливу інформацію про відео (як-от міміка й оточення), яку не можуть забезпечити діалоги. [Докладніше](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Елементи `<video>` не містять елемент `<track>` з атрибутом `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Елементи `<video>` містять елемент `<track>` з атрибутом `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Налаштуйте параметр `apple-touch-icon` для ідеального вигляду на пристроях iOS, коли користувачі додають прогресивний веб-додаток на головний екран. Цей параметр має вказувати на непрозоре квадратне зображення PNG розміром 192 пікс. (або 180 пікс.). [Докладніше](https://web.dev/apple-touch-icon/)."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Не містить дійсного значка `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "Атрибут `apple-touch-icon-precomposed` застарів. Радимо використовувати `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Містить дійсний значок `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Розширення Chrome негативно впливають на завантаження цієї сторінки. Спробуйте перевірити сторінку в режимі анонімного перегляду або в профілі Chrome без розширень."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Оцінка сценарію"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Синтаксичний аналіз сценарію"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Загальний процесорний час"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Зменште час виконання синтаксичного аналізу, компілювання й запуску сценаріїв JavaScript. Для цього корисно завантажувати менші обсяги даних JavaScript. [Докладніше](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Зменште час виконання JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Час виконання JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Великі файли GIF неефективні для передавання анімованого вмісту. Щоб заощадити мережевий трафік даних, радимо замість формату GIF використовувати MPEG4 або WebM для анімацій і PNG чи WebP для статичних зображень. [Докладніше](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Використовуйте формати відео для анімованого вмісту"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Щоб зменшити час до повного завантаження, використовуйте закадрові й приховані зображення, коли завантажаться всі важливі ресурси. [Докладніше](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Відкладіть закадрові зображення"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Ресурси блокують першу візуалізацію сторінки. Надсилайте спершу важливі фрагменти JavaScript або таблиці CSS і відкладайте всі некритичні елементи. [Докладніше](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Вилучіть ресурси, які блокують відображення"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Великі обсяги мережевих даних використовують багато коштовного трафіку відвідувачів і довго завантажуються. [Докладніше](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Загальний розмір – {totalBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Уникайте великих обсягів даних у мережі"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Уникається великий обсяг даних мережі"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Стиснення файлів CSS може зменшити обсяг даних у мережі. [Докладніше](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Зменште СSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Стиснення файлів JavaScript може зменшити обсяг даних і час синтаксичного аналізу сценарію. [Докладніше](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Зменште файл JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Щоб зменшити трафік даних у мережі, видаліть непотрібні правила з таблиць стилів і відкладіть завантаження таблиць CSS, що не використовуються для вмісту у верхній частині сторінки. [Докладніше](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Видаліть вміст CSS, який не використовується"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Видаліть файли JavaScript, які ви не використовуєте, щоб зменшити кількість байтів під час активності в мережі."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Вилучіть файли JavaScript, які ви не використовуєте"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Якщо зберігати кеш за тривалий період часу, сторінки можуть завантажуватися швидше під час повторних відвідувань. [Докладніше](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Знайдено 1 ресурс}one{Знайдено # ресурс}few{Знайдено # ресурси}many{Знайдено # ресурсів}other{Знайдено # ресурсу}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Показуйте статичні об’єкти за допомогою ефективних правил кешування"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Використовуються ефективні правила кешування статичних об’єктів"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Оптимізовані зображення завантажуються швидше й використовують менше мобільного трафіку. [Докладніше](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Ефективно кодуйте зображення"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Показуйте зображення правильного розміру, щоб заощадити мобільний трафік і покращити час завантаження. [Докладніше](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Правильно виберіть розмір зображень"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Текстові ресурси потрібно відображати зі стисненням (Gzip, Deflate чи Brotli), щоб мінімізувати загальний трафік мережі. [Докладніше](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Увімкніть стиснення тексту"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Формати зображень JPEG 2000, JPEG XR і WebP часто стискаються краще, ніж PNG чи JPEG. Тому вони швидше завантажуються й використовують менше даних. [Докладніше](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Показуйте зображення в нових форматах"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Якщо ширина контенту додатка не збігається з шириною області перегляду, можливо, додаток не вдасться оптимізувати для екранів мобільних пристроїв. [Докладніше](https://web.dev/content-width)."
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Розмір області перегляду ({innerWidth} пікс.) не збігається з розміром вікна ({outerWidth} пікс.)."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Розмір контенту не відповідає області перегляду"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Розмір контенту відповідає області перегляду"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Ланцюжки важливих запитів нижче показують, які ресурси мають високий пріоритет. Щоб пришвидшити завантаження сторінки, зменште довжину ланцюжків і розмір завантажень або відкладіть завантаження непотрібних ресурсів. [Докладніше](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Знайдено 1 ланцюжок}one{Знайдено # ланцюжок}few{Знайдено # ланцюжки}many{Знайдено # ланцюжків}other{Знайдено # ланцюжка}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Мінімізуйте глибину важливих запитів"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Припинення підтримки/застереження"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Рядок"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "API, які більше не підтримуються, будуть видалені з веб-переглядача. [Докладніше](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Знайдено 1 застереження}one{Знайдено # застереження}few{Знайдено # застереження}many{Знайдено # застережень}other{Знайдено # застереження}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Використовує непідтримувані API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Уникає інтерфейсів API, які більше не підтримуються"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Application Cache API більше не підтримується. [Докладніше](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Знайдено кеш \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Використовує кеш додатка"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Уникає кешу додатка"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Якщо вказати елемент doctype, веб-переглядач не перейде в режим сумісності. [Докладніше](https://web.dev/doctype)."
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Назва елемента doctype має починатися з малої літери й мати значення `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Документ має містити тег doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "Очікується, що поле publicId буде порожнім"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "Очікується, що поле systemId буде порожнім"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Для сторінки не вказано елемента HTML doctype, що активує режим сумісності"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Сторінка має елемент HTML doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Елемент"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Статистика"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Значення"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Розробники веб-переглядачів радять розміщувати на сторінці до ~1500 елементів DOM. Зона найкращого сприйняття – глибина дерева, що має менше 32 елементів і менше ніж 60 дочірніх чи батьківських елементів. Через великий файл DOM використовується більше пам'яті, [стилі обчислюються](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) довше, а [перекомпонування макетів](https://developers.google.com/speed/articles/reflow) коштує дорого. [Докладніше](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 елемент}one{# елемент}few{# елементи}many{# елементів}other{# елемента}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Уникайте надмірного розміру DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Максимальна глибина DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Усього елементів DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Максимальна кількість дочірніх елементів"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Уникається надмірний розмір DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Ціль"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Додайте `rel=\"noopener\"` або `rel=\"noreferrer\"` до зовнішніх посилань, щоб покращити ефективність і підвищити їх захищеність. [Докладніше](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Міждоменні посилання на веб-сторінці ненадійні"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Міждоменні посилання на веб-сторінці надійні"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Не вдалося визначити сервіс для прив'язки ({anchorHTML}). Якщо гіперпосилання не використовується, видаліть цю частину: \"target=_blank\"."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Сайти, які надсилають запит на доступ до місцезнаходження без пояснення, викликають у користувачів недовіру або спантеличеність. Радимо пов'язувати запит із діями користувача. [Докладніше](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Надсилає запит на доступ до геолокації під час завантаження сторінки"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Уникає надсилання запитів на доступ до геолокації під час завантаження сторінки"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Версія"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Усі бібліотеки JavaScript зовнішнього інтерфейсу виявлено на сторінці. [Докладніше](https://web.dev/js-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Виявлені бібліотеки JavaScript"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Зовнішні сценарії, динамічно вставлені методом `document.write()`, можуть затримувати завантаження сторінки на десятки секунд для користувачів із повільним з'єднанням. [Докладніше](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Використовує `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Уникає `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Найвищий рівень серйозності"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Версія бібліотеки"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Кількість прогалин системи безпеки"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Деякі сторонні сценарії можуть містити відомі прогалини системи безпеки, які зловмисники можуть легко виявити та використати. [Докладніше](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Виявлено 1 прогалину системи безпеки}one{Виявлено # прогалину системи безпеки}few{Виявлено # прогалини системи безпеки}many{Виявлено # прогалин системи безпеки}other{Виявлено # прогалини системи безпеки}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Включає бібліотеки JavaScript зовнішнього інтерфейсу з відомими прогалинами системи безпеки"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Високий"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Низький"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Середній"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Уникає бібліотек JavaScript зовнішнього інтерфейсу з відомими прогалинами в системі безпеки"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Сайти, які надсилають запит на показ сповіщень без пояснення, викликають у користувачів недовіру або спантеличеність. Радимо пов'язувати запит із жестами користувача. [Докладніше](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Надсилає запит на показ сповіщень під час завантаження сторінки"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Уникає надсилання запитів на показ сповіщень під час завантаження сторінки"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Відхилені елементи"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Якщо заборонити вставляти пароль, це порушить правила щодо високого рівня безпеки. [Докладніше](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Не дозволяє користувачам вставляти вміст у поля паролів"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Дає змогу користувачам вставляти вміст у поля паролів"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Протокол"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "Протокол HTTP/2 має низку переваг над HTTP/1.1, як-от двійкові заголовки, мультиплексування та технологія Server Push. [Докладніше](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 запит не розміщено через протокол HTTP/2}one{# запит не розміщено через протокол HTTP/2}few{# запити не розміщено через протокол HTTP/2}many{# запитів не розміщено через протокол HTTP/2}other{# запиту не розміщено через протокол HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Не використовує протокол HTTP/2 для всіх ресурсів"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Використовує протокол HTTP/2 для власних ресурсів"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Щоб сторінка краще прокручувалася, позначте блоки прослуховування подій сенсорного екрана та коліщатка як `passive`. [Докладніше](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Не використовує пасивні прослуховувачі, щоб покращити функцію прокручування"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Використовує пасивні прослуховувачі, щоб покращити прокручування сторінки"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Опис"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Помилки, записані в журнал консолі, указують на невирішені проблеми. Вони можуть бути викликані збоями запитів мережі або іншими проблемами веб-переглядача. [Докладніше](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Помилки веб-переглядача записано в журнал консолі"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Помилки веб-переглядача не записано в журнал консолі"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Використовуйте функцію відображення шрифтів CSS, щоб текст було видно під час завантаження веб-шрифтів. [Докладніше](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Переконайтеся, що текст залишається видимим під час завантаження веб-шрифту"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Увесь текст залишається видимим під час завантаження веб-шрифтів"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Інструменту Lighthouse не вдалось автоматично перевірити значення відображення шрифтів для цієї URL-адреси: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Формат (фактичний)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Формат (відображуваний)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Розміри показаного зображення мають відповідати реальному формату. [Докладніше](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Показує зображення неправильного формату"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Показує зображення правильного формату"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Недійсна інформація про розмір зображення {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Веб-переглядачі можуть активно заохочувати користувачів установити ваш додаток на головний екран, що сприятиме кращій взаємодії. [Докладніше](https://web.dev/installable-manifest)."
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Маніфест веб-додатка не відповідає умовам для встановлення"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Маніфест веб-додатка відповідає умовам щодо встановлення"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "Ненадійна URL-адреса"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Усі сайти мають бути захищені протоколом HTTPS, навіть якщо вони не обробляють конфіденційні дані. HTTPS не дозволяє зловмисникам втручатись в обмін даними між додатком і користувачами або пасивно прослуховувати супутні події. Це обов'язкова умова для протоколу HTTP/2 та багатьох нових API веб-платформ. [Докладніше](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Знайдено 1 ненадійний запит}one{Знайдено # ненадійний запит}few{Знайдено # ненадійні запити}many{Знайдено # ненадійних запитів}other{Знайдено # ненадійного запиту}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Не використовує протокол HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Використовує протокол HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Якщо сторінка швидко завантажується в мобільній мережі, це покращує враження користувачів мобільних пристроїв. [Докладніше](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Стає інтерактивною через {timeInMs, number, seconds} с"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Стає інтерактивною в емульованій мобільній мережі через {timeInMs, number, seconds} с"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Сторінка завантажується надто повільно й неактивна впродовж 10 секунд. Щоб дізнатися, як виправити цю ситуацію, перегляньте можливості та дані діагностики в розділі \"Ефективність\"."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Швидкість завантаження сторінки через мобільну мережу недостатньо висока"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Швидкість завантаження сторінки через мобільну мережу достатньо висока"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Категорія"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Зменште час виконання синтаксичного аналізу, компілювання й запуску сценаріїв JavaScript. Для цього корисно завантажувати менші обсяги даних JavaScript. [Докладніше](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Мінімізуйте роботу основного потоку"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Мінімізується робота основного потоку"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Щоб охопити якомога більше користувачів, сайти мають працювати в усіх відомих веб-переглядачах. [Докладніше](https://web.dev/pwa-cross-browser)."
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Сайт працює у різних веб-переглядачах"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Переконайтеся, що окремі сторінки можна відкрити за допомогою прямого посилання, а URL-адреси унікальні, щоб ними можна було ділитися в соціальних мережах. [Докладніше](https://web.dev/pwa-each-page-has-url)."
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Кожна сторінка має URL-адресу"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Додаток має швидко реагувати на дії користувача, навіть якщо мережа повільна. Це суттєво впливає на оцінку роботи вашого додатка користувачем. [Докладніше](https://web.dev/pwa-page-transitions)."
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Схоже, перехід між сторінками не блокує мережу"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Приблизна затримка введення показує, скільки часу в мілісекундах додаток відповідає на ввід користувача під час п'ятисекундного періоду завантаження сторінки. Якщо затримка перевищує 50 мс, користувачі можуть вважати ваш додаток повільним. [Докладніше](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Приблизна затримка введення"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Перша візуалізація вмісту показує, коли з'являється текст чи зображення. [Докладніше](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Перше відображення всього вмісту"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Перший простій ЦП вказує, коли основний ланцюжок сторінки вперше може обробити введення. [Докладніше](https://web.dev/first-cpu-idle)."
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "Перший простій ЦП"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Час початку візуалізації вказує, коли видно основний вміст сторінки. [Докладніше](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Перше значне відображення"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Час до повного завантаження – це період часу, через який сторінка стане повністю інтерактивною. [Докладніше](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Час до повної взаємодії"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Максимальна потенційна затримка відповіді на першу дію – це тривалість найдовшого завдання в мілісекундах. [Докладніше](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Максимальна потенційна затримка відповіді на першу дію"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Індекс швидкості показує, через скільки часу відображається вміст сторінки. [Докладніше](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Індекс швидкості"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Загальна тривалість усіх періодів часу в мілісекундах між першою візуалізацією вмісту та часом до повного завантаження, коли час виконання завдання перевищує 50 мс."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Загальний час блокування"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Час затримки передачі сигналу мережі (RTT) суттєво впливає на ефективність. Якщо показник RTT високий, це означає, що сервери, розташовані ближче до користувача, можуть покращити ефективність. [Докладніше](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Час затримки передачі сигналу мережі"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Затримка сервера може впливати на ефективність веб-сайту. Якщо показник затримки сервера високий, це означає, що сервер перевантажено або в нього низька ефективність. [Докладніше](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Затримка сервера"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Синтаксис Service Worker забезпечує надійність вашого веб-додатка в разі непередбачуваних умов у мережі. [Докладніше](https://web.dev/offline-start-url)."
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` не надсилає код 200 у режимі офлайн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` надсилає код 200 у режимі офлайн"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse не може прочитати `start_url` з маніфесту. Через це `start_url` вважається URL-адресою документа. Повідомлення про помилку: \"{manifestWarning}\"."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Перевищення бюджету"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Стежте, щоб кількість і розмір мережевих запитів не перевищували цільових значень, указаних у бюджеті ефективності. [Докладніше](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 запит}one{# запит}few{# запити}many{# запитів}other{# запиту}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Бюджет ефективності"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Якщо ви вже налаштували HTTPS, переконайтеся, що весь трафік HTTP переспрямовується на HTTPS, щоб увімкнути безпечні веб-функції для всіх користувачів. [Докладніше](https://web.dev/redirects-http)."
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Трафік HTTP не перепрямовується на HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Трафік HTTP переспрямовується на HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Переспрямування викликають додаткові затримки під час завантаження сторінки. [Докладніше](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Уникайте переспрямувань кількох сторінок"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Щоб установити бюджет відповідно до кількості та розміру ресурсів на сторінці, додайте файл budget.json. [Докладніше](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 запит • {byteCount, number, bytes} КБ}one{# запит • {byteCount, number, bytes} КБ}few{# запити • {byteCount, number, bytes} КБ}many{# запитів • {byteCount, number, bytes} КБ}other{# запиту • {byteCount, number, bytes} КБ}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Не надсилайте багато запитів і передавайте вміст малого розміру"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Канонічні посилання вказують, які URL-адреси показувати в результатах пошуку. [Докладніше](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Кілька URL-адрес конфліктують ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Указує на інший домен ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "Недійсна URL-адреса ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Указує на інше місце `hreflang` ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "Відносна URL-адреса ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Указує на основну URL-адресу домену (домашню сторінку), а не на еквівалентну сторінку вмісту"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Документ не має дійсного посилання `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Документ має дійсний атрибут `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Розміри шрифту до 12px замалі й нечитабельні. Щоб користувачі мобільних пристроїв змогли прочитати текст, їм потрібно буде збільшувати масштаб пальцями. Бажано, щоб понад 60% тексту на сторінці було написано щонайменше шрифтом 12px. [Докладніше](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} читабельного тексту"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Текст нечитабельний, оскільки метатег області перегляду не оптимізовано для мобільних пристроїв."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} тексту має замалий шрифт (на основі {decimalProportionVisited, number, extendedPercent} вибірки)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "У документі використано нечитабельні розміри шрифтів"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "У документі використано читабельні розміри шрифтів"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Посилання hreflang указують пошуковим системам версію сторінки, яку потрібно додати в результати пошуку для певної мови чи регіону. [Докладніше](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Документ не має дійсного атрибута `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Документ має дійсний атрибут `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Сторінки з недійсними кодами статусу HTTP можуть неправильно індексуватися. [Докладніше](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Сторінка має недійсний код статусу HTTP"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Сторінка має дійсний код статусу HTTP"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Пошукові системи не зможуть включити ваші сторінки в результати пошуку, якщо в них немає дозволу сканувати їх. [Докладніше](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Сторінку не можна індексувати"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Сторінку можна індексувати"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Описовий текст посилання допомагає пошуковим системам розуміти ваш вміст. [Докладніше](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Знайдено 1 посилання}one{Знайдено # посилання}few{Знайдено # посилання}many{Знайдено # посилань}other{Знайдено # посилання}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Посилання не містять опису"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Посилання містять опис"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Щоб перевірити структуровані дані, скористайтесь [інструментом тестування](https://search.google.com/structured-data/testing-tool/) й [інструментом статичного аналізу структурованих даних](http://linter.structured-data.org/). [Докладніше](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Структуровані дані дійсні"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Результати пошуку можуть містити метаописи для короткого підсумку вмісту сторінки. [Докладніше](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Немає опису."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Документ не містить метаопису"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Документ містить метаопис"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Пошукові системи не можуть індексувати вміст плагінів. Багато пристроїв обмежують або не підтримують плагіни. [Докладніше](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Документ використовує плагіни"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Документ уникає плагінів"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Якщо файл robots.txt недійсний, веб-сканери можуть не зрозуміти, як потрібно індексувати або сканувати ваш веб-сайт. [Докладніше](https://web.dev/robots-txt)."
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "У відповідь на запит robots.txt отримано такий статус HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Знайдено 1 помилку}one{Знайдено # помилку}few{Знайдено # помилки}many{Знайдено # помилок}other{Знайдено # помилки}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Інструменту Lighthouse не вдалося завантажити файл robots.txt"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "Файл robots.txt недійсний"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "Файл robots.txt дійсний"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Інтерактивні елементи, як-от кнопки та посилання, мають бути достатньо великі (48x48 пікселів), а навколо них має бути достатньо місця, щоб їх можна було легко натиснути, не зачепивши інші елементи. [Докладніше](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} елементів для натискання мають правильний розмір"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Елементи для натискання замалі, оскільки метатег області перегляду не оптимізовано для мобільних пристроїв"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Елементи для натискання мають неправильний розмір"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Елементи для натискання накладаються"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Елемент для натискання"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Елементи для натискання мають правильний розмір"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Синтаксис Service Worker – це технологія, яка дає змогу додатку використовувати багато функцій прогресивного веб-додатка, як-от режим офлайн, додавання на головний екран і push-сповіщення. [Докладніше](https://web.dev/service-worker)."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Цією сторінкою керує синтаксис Service Worker, однак `start_url` не знайдено, оскільки не вдалося виконати синтаксичний аналіз маніфесту як дійсного файлу JSON"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Цією сторінкою керує синтаксис Service Worker, однак параметр `start_url` ({startUrl}) перебуває за межами дії служби ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Цією сторінкою керує синтаксис Service Worker, однак `start_url` не знайдено, оскільки маніфест не завантажено."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Це джерело містить один або кілька синтаксисів Service Worker, але сторінка ({pageUrl}) перебуває за межами дії служби."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Немає синтаксису Service Worker, який керує сторінкою та `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Наявний синтаксис Service Worker, який керує сторінкою та `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Тематична заставка покращує взаємодію з користувачами під час запуску додатка з головного екрана. [Докладніше](https://web.dev/splash-screen)."
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Власну заставку не налаштовано"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Налаштовано власну заставку"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Для адресного рядка веб-переглядача можна створити тему, яка відповідатиме вашому сайту [Докладніше](https://web.dev/themed-omnibox)."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Не змінює колір адресного рядка відповідно до теми."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Змінює колір адресного рядка відповідно до теми."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Час блокування основного ланцюжка"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Сторонні розробники"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Сторонній код може значно погіршити швидкість завантаження. Не використовуйте зайвий раз елементи коду сторонніх розробників та налаштуйте сторінку так, щоб сторонній код завантажувався після її основної частини. [Докладніше](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Сторонній код заблокував основний ланцюжок на {timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Зменште вплив стороннього коду"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Використання стороннього коду"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Час до першого байта визначає швидкість реакції сервера. [Докладніше](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Кореневий документ відповів через {timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Зменште час відповіді сервера (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Сервер довго відповідає (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Тривалість"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Час початку"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Тип"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Використовуйте в додатку User Timing API, щоб отримувати показники ефективності додатка під час взаємодії з користувачами. [Докладніше](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 позначка часу користувача}one{# позначка часу користувача}few{# позначки часу користувача}many{# позначок часу користувача}other{# позначки часу користувача}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Показники й мітки часу користувача"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Для {securityOrigin} знайдено посилання для попереднього з'єднання <link>, але веб-переглядач його не використав. Переконайтеся, що ви правильно використовуєте атрибут `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Додайте в ресурси корективи `preconnect` чи `dns-prefetch`, щоб заздалегідь встановлювати з'єднання з важливими сторонніми джерелами. [Докладніше](https://web.dev/uses-rel-preconnect)."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Попередньо під’єднуйтеся до потрібних джерел"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Для {preloadURL} знайдено посилання для попереднього завантаження <link>, але веб-переглядач його не використав. Переконайтеся, що ви правильно використовуєте атрибут `crossorigin`."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Використовуйте `<link rel=preload>`, щоб указати пріоритетність завантаження ресурсів, які наразі отримуються пізніше під час завантаження сторінки. [Докладніше](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Попередньо завантажуйте основні запити"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Додайте тег `<meta name=\"viewport\">`, щоб оптимізувати додаток для екранів мобільних пристроїв. [Докладніше](https://web.dev/viewport)."
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Тег `<meta name=\"viewport\">` не знайдено"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Немає тегу `<meta name=\"viewport\">` з атрибутами `width` або `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Має тег `<meta name=\"viewport\">` з атрибутами `width` або `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Ваш додаток має відображати певний контент, коли JavaScript вимкнено, навіть якщо це просто сповіщення для користувачів про те, що для використання додатка потрібно ввімкнути JavaScript. [Докладніше](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Сторінка має відображати контент, навіть якщо її сценарії недоступні."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Резервний контент не відображається, коли JavaScript вимкнено"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Певний контент відображається, коли JavaScript вимкнено"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Якщо ви створюєте прогресивний веб-додаток, можете скористатися синтаксисом Service Worker, щоб додаток працював офлайн. [Докладніше](https://web.dev/works-offline)."
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Поточна сторінка не надсилає код 200 у режимі офлайн"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Поточна сторінка надсилає код 200 у режимі офлайн"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Ця сторінка може не завантажуватись офлайн, оскільки тестову URL-адресу ({requested}) було переспрямовано на {final}. Спробуйте перевірити другу URL-адресу напряму."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Ці рекомендації допоможуть покращити використання ролей ARIA у вашому додатку, що може позитивно вплинути на взаємодію для користувачів допоміжних технологій, як-от програм зчитування з екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Ці рекомендації допоможуть надати альтернативний вміст для аудіо та відео. Це може покращити взаємодію для користувачів із вадами слуху або зору."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Аудіо та відео"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Ці елементи надають поширені практичні поради щодо спеціальних можливостей."
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Практичні поради"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Ці перевірки визначають можливості для [покращення доступності веб-додатка](https://developers.google.com/web/fundamentals/accessibility). Радимо також проводити перевірки вручну, оскільки не всі проблеми з доступністю визначаються автоматично."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Ці елементи опрацьовують області, які не може охопити автоматизований інструмент перевірки. Докладніше читайте в нашому посібнику з [перевірки доступності](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Спеціальні можливості"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Ці рекомендації допоможуть покращити читабельність вмісту."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Контраст"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Ці рекомендації допоможуть покращити те, як користувачі тлумачать ваш вміст різними мовами."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Інтернаціоналізація та локалізація"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Ці рекомендації допоможуть удосконалити семантику елементів керування в додатку. Це може покращити взаємодію для користувачів допоміжних технологій, як-от програм зчитування з екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Назви та мітки"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Ці рекомендації допоможуть покращити навігацію клавіатурою в додатку."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Навігація"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Ці рекомендації допоможуть покращити перегляд даних у таблиці чи списку за допомогою допоміжної технології, наприклад програми зчитування з екрана."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Таблиці та списки"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Практичні поради"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Бюджети визначають стандарти ефективності вашого сайту."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Бюджети"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Докладніше про ефективність додатка. Ці числа не [впливають безпосередньо](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) на значення ефективності."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Діагностика"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Найважливішим аспектом ефективності є швидкість відображення пікселів на екрані. Основні показники: перше відображення вмісту, перше значне відображення"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Покращення першого відображення"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Ці пропозиції допоможуть завантажувати сторінку швидше. Вони не [впливають безпосередньо](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) на значення ефективності."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Можливості"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Показники"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Покращте загальну ефективність завантаження, щоб сторінка швидко реагувала й завантажувалася. Основні показники: час до повної взаємодії, індекс швидкості"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Загальні покращення"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Ефективність"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Ці категорії підтверджують аспекти прогресивного веб-додатка. [Докладніше](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Ці категорії обов'язкові відповідно до основного [контрольного списку для прогресивних веб-додатків](https://developers.google.com/web/progressive-web-apps/checklist), але Lighthouse не перевіряє їх автоматично. Вони не впливають на ваш показник, проте їх потрібно підтвердити вручну."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Прогресивний веб-додаток"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Швидкість і надійність"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Можна встановити"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "Оптимізовано для прогресивного веб-додатка"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Ці перевірки визначають, чи сторінка оптимізована для позиціонування результатів пошукової системи. Lighthouse не перевіряє певні додаткові чинники, які можуть впливати на позицію веб-сайту в результатах пошуку. [Докладніше](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Щоб отримати додаткові практичні поради щодо оптимізації пошукових систем, скористайтеся додатковими засобами перевірки на своєму сайті."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "Оптим. пошук. систем"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Відформатуйте HTML так, щоб веб-сканери краще розуміли вміст вашого додатка."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Практичні поради щодо вмісту"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Щоб ваш вміст з’являвся в результатах пошуку, веб-сканерам потрібно надати доступ до додатка."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Сканування й індексування"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Переконайтеся, що ваші сторінки адаптовані для мобільних пристроїв і користувачам не потрібно зменшувати чи збільшувати масштаб, щоб читати їх вміст. [Докладніше](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Для мобільних пристроїв"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "TTL кешу"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Місцезнаходження"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Назва"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Запити"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Тип ресурсу"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Розмір"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Витрачений час"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Розмір передавання"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL-адреса"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Потенційне заощадження"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Потенційне заощадження"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Потенційне заощадження – {wastedBytes, number, bytes} КБ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Потенційне заощадження – {wastedMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Документ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Шрифт"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Зображення"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Медіа"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} мс"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Інше"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Сценарій"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} с"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Таблиця стилів"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Сторонні"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Усього"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Не вдалося записати результати трасування для завантаження вашої сторінки. Запустіть інструмент Lighthouse ще раз. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Час очікування початкового з’єднання з протоколом Debugger минув."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Веб-переглядач Chrome не отримав знімки екрана під час завантаження сторінки. Переконайтеся, що на сторінці є видимий вміст, а потім спробуйте перезапустити інструмент Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS-серверам не вдалось обробити вказаний домен."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "У збирачі обов'язкових ресурсів {artifactName} сталася помилка: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Сталася внутрішня помилка Chrome. Перезапустіть Chrome і спробуйте знову запустити інструмент Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Збирач обов'язкових ресурсів {artifactName} не запущено."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Інструменту Lighthouse не вдалося безпечно завантажити сторінку, яку ви вказали. Переконайтеся, що ви тестуєте правильну URL-адресу, а сервер належним чином відповідає на всі запити."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Інструменту Lighthouse не вдалося безпечно завантажити URL-адресу, яку ви вказали, оскільки сторінка перестала відповідати."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "Указана вами URL-адреса не має дійсного сертифіката безпеки. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Веб-переглядач Chrome заблокував завантаження сторінки та відобразив проміжний екран. Переконайтеся, що ви тестуєте правильну URL-адресу, а сервер належним чином відповідає на всі запити."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Інструменту Lighthouse не вдалося безпечно завантажити сторінку, яку ви вказали. Переконайтеся, що ви тестуєте правильну URL-адресу, а сервер належним чином відповідає на всі запити. (Деталі: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Інструменту Lighthouse не вдалося безпечно завантажити сторінку, яку ви вказали. Переконайтеся, що ви тестуєте правильну URL-адресу, а сервер належним чином відповідає на всі запити. (Код статусу: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Сторінка завантажувалася задовго. Дотримуйтеся рекомендацій у звіті, щоб зменшити час завантаження сторінки, а потім спробуйте перезапустити інструмент Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Час очікування відповіді протоколу DevTools перевищив установлений період. (Метод: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Час отримання вмісту ресурсу перевищив установлений час"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "Схоже, указана вами URL-адреса недійсна."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Показати перевірки"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Початкова навігація"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Максимальна критична затримка шляху:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Помилка."
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Повідомлення про помилку: немає інформації про перевірку"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Дані тестів"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Аналіз [Lighthouse](https://developers.google.com/web/tools/lighthouse/) поточної сторінки в емульованій мобільній мережі. Значення приблизні й можуть відрізнятися."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Додаткові елементи, які потрібно перевірити вручну"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Не застосовуються"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Можливість"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Приблизне заощадження"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Виконані перевірки"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Згорнути фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Розгорнути фрагмент"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Показати сторонні ресурси"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Під час запуску Lighthouse виникли перелічені нижче проблеми."
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Значення приблизні й можуть відрізнятися. Значення ефективності визначається [на основі цих показників](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Перевірки зі статусом \"Пройдено\", що містять застереження"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Застереження. "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Спробуйте завантажити файл GIF у сервіс, де його можна вставити як відео HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Установіть [плагін lazy-load від WordPress](https://wordpress.org/plugins/search/lazy+load/), який дає змогу відкласти завантаження закадрових зображень, або виберіть тему, що дозволяє це зробити. Також можете скористатися [плагіном AMP](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Існує багато плагінів WordPress, які можуть допомогти [вбудувати важливі об'єкти](https://wordpress.org/plugins/search/critical+css/) або [відкласти менш важливі ресурси](https://wordpress.org/plugins/search/defer+css+javascript/). Зауважте, що така оптимізація може порушити функції теми або плагінів, тож доведеться змінити код."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Теми, плагіни й характеристики сервера впливають на час відповіді. Спробуйте знайти більш оптимізовану тему, підібрати плагін для оптимізації та/або оновити сервер."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Спробуйте показувати витяги в списках дописів (через тег \"більше\"), зменшити кількість показаних публікацій на сторінці, розділити довгі дописи на кілька сторінок або скористатися плагіном, щоб відкласти завантаження коментарів."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Багато [плагінів WordPress](https://wordpress.org/plugins/search/minify+css/) можуть пришвидшити ваш сайт: вони об'єднують, зменшують і стискають стилі. Також можна скористатися процесом складання, щоб завчасно зменшити розмір, якщо це можливо."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Багато [плагінів WordPress](https://wordpress.org/plugins/search/minify+javascript/) можуть пришвидшити ваш сайт: вони об'єднують, зменшують і стискають сценарії. Також можна скористатися процесом складання, щоб завчасно зменшити розмір, якщо це можливо."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Спробуйте зменшити кількість [плагінів WordPress](https://wordpress.org/plugins/), що завантажують на сторінці непотрібні таблиці стилів CSS. Щоб визначити плагіни, які додають зайві таблиці CSS, перевірте [покриття коду](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в Chrome DevTools. Ви можете визначити тему чи плагін через URL-адресу таблиці стилів. У покритті коду знайдіть плагіни з багатьма таблицями стилів за великим обсягом червоного тексту. Плагін має ставити таблицю стилів у чергу, лише коли вона дійсно використовується на сторінці."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Спробуйте зменшити кількість [плагінів WordPress](https://wordpress.org/plugins/), що завантажують на сторінці непотрібні фрагменти JavaScript. Щоб визначити плагіни, які додають зайвий код JavaScript, перевірте [покриття коду](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) в Chrome DevTools. Ви можете визначити тему чи плагін через URL-адресу сценарію. У покритті коду знайдіть плагіни з багатьма сценаріями за великим обсягом червоного тексту. Плагін має ставити сценарій у чергу, лише коли він дійсно використовується на сторінці."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Дізнайтеся про [кешування веб-переглядача у WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Спробуйте [плагін WordPress для оптимізації зображень](https://wordpress.org/plugins/search/optimize+images/), який стискає зображення, але зберігає їх якість."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Завантажуйте зображення через [бібліотеку медіафайлів](https://codex.wordpress.org/Media_Library_Screen), щоб переконатися, що вони доступні в потрібному розмірі. Потім вставляйте їх в оптимальному розмірі з бібліотеки або через віджет для зображень (зокрема для адаптивних точок переходу). Використовуйте зображення, що мають `Full Size`, лише якщо вони повністю поміщаються. [Докладніше](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Ви можете ввімкнути стиснення тексту в конфігурації веб-сервера."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Скористайтеся [плагіном](https://wordpress.org/plugins/search/convert+webp/) або сервісом, який автоматично конвертує завантажені зображення в оптимальні формати."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/vi.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/vi.json
new file mode 100644
index 00000000000..d6f1f911246
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/vi.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "Các phím truy cập cho phép người dùng chuyển nhanh đến một phần của trang. Để di chuyển đúng cách, mỗi phím truy cập phải là duy nhất. [Tìm hiểu thêm](https://web.dev/accesskeys/)."
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "Các giá trị của `[accesskey]` không phải là duy nhất"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "Các giá trị của `[accesskey]` là duy nhất"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "Mỗi `role` của Ứng dụng Internet phong phú dễ dùng (ARIA) hỗ trợ một tập hợp con cụ thể các thuộc tính `aria-*`. Nếu không trùng khớp, các thuộc tính `aria-*` sẽ bị vô hiệu. [Tìm hiểu thêm](https://web.dev/aria-allowed-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "Các thuộc tính `[aria-*]` không khớp với vai trò tương ứng"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "Các thuộc tính `[aria-*]` khớp với vai trò tương ứng"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "Một số vai trò ARIA có các thuộc tính bắt buộc mô tả trạng thái của phần tử cho trình đọc màn hình. [Tìm hiểu thêm](https://web.dev/aria-required-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` không có tất cả các thuộc tính `[aria-*]` bắt buộc"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` có tất cả các thuộc tính `[aria-*]` bắt buộc"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "Một số vai trò mẹ của Ứng dụng Internet phong phú dễ dùng (ARIA) phải chứa vai trò con cụ thể để thực hiện các chức năng hỗ trợ tiếp cận chủ định tương ứng. [Tìm hiểu thêm](https://web.dev/aria-required-children/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "Các phần tử có `[role]` ARIA yêu cầu phần tử con phải chứa một `[role]` cụ thể hiện đang thiếu một số hoặc tất cả các phần tử con bắt buộc đó."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "Các phần tử có `[role]` ARIA yêu cầu phần tử con phải chứa một `[role]` cụ thể có tất cả các phần tử con bắt buộc."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "Các vai trò mẹ cụ thể phải chứa một số vai trò con của Ứng dụng Internet phong phú dễ dùng (ARIA) để thực hiện đúng cách các chức năng hỗ trợ tiếp cận chủ định tương ứng. [Tìm hiểu thêm](https://web.dev/aria-required-parent/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` không có trong phần tử mẹ bắt buộc tương ứng"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` có trong phần tử mẹ bắt buộc tương ứng"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "Các vai trò của Ứng dụng Internet phong phú dễ dùng (ARIA) phải có giá trị hợp lệ để thực hiện những chức năng hỗ trợ tiếp cận chủ định tương ứng. [Tìm hiểu thêm](https://web.dev/aria-roles/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "Các giá trị của `[role]` là không hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "Các giá trị của `[role]` là hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "Các công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình, không thể diễn giải thuộc tính của Ứng dụng Internet phong phú dễ dùng (ARIA) có giá trị không hợp lệ. [Tìm hiểu thêm](https://web.dev/aria-valid-attr-value/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "Giá trị của các thuộc tính `[aria-*]` là không hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "Các thuộc tính `[aria-*]` có giá trị hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "Các công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình, không thể diễn giải các thuộc tính của Ứng dụng Internet phong phú dễ dùng (ARIA) có tên không hợp lệ. [Tìm hiểu thêm](https://web.dev/aria-valid-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "Các thuộc tính `[aria-*]` là không hợp lệ hoặc bị sai chính tả"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "Các thuộc tính `[aria-*]` là hợp lệ và không bị sai chính tả"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "Phụ đề giúp người điếc hoặc người dùng khiếm thính có thể sử dụng các phần tử âm thanh, cung cấp cho họ những thông tin quan trọng như ai đang nói chuyện, những người đó đang nói gì và các thông tin khác không phải lời nói. [Tìm hiểu thêm](https://web.dev/audio-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "Các phần tử `<audio>` bị thiếu phần tử `<track>` có `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "Các phần tử `<audio>` chứa phần tử `<track>` có `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "Các phần tử không đạt"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "Khi một nút không có tên có thể tiếp cận, trình đọc màn hình sẽ thông báo đó là \"nút\", khiến người dùng trình đọc màn hình không sử dụng được nút này. [Tìm hiểu thêm](https://web.dev/button-name/)."
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "Các nút không có tên có thể tiếp cận được"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "Các nút có tên tiếp cận được"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "Bằng việc thêm các cách bỏ qua nội dung lặp lại, người dùng bàn phím có thể khám phá trang một cách hiệu quả hơn. [Tìm hiểu thêm](https://web.dev/bypass/)."
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "Trang này không chứa tiêu đề, đường dẫn liên kết bỏ qua hoặc vùng mốc"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "Trang này chứa tiêu đề, phần tử liên kết bỏ qua hoặc vùng mốc"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "Nhiều người dùng gặp khó khăn khi đọc hoặc không thể đọc được văn bản có độ tương phản thấp. [Tìm hiểu thêm](https://web.dev/color-contrast/)."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "Màu nền trước và nền sau không có đủ tỷ lệ tương phản."
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "Màu nền trước và nền sau có đủ tỷ lệ tương phản"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "Khi danh sách định nghĩa không được đánh dấu đúng cách, thì trình đọc màn hình có thể tạo ra thông báo gây nhầm lẫn hoặc không chính xác. [Tìm hiểu thêm](https://web.dev/definition-list/)."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` không chỉ chứa các nhóm `<dt>` và `<dd>` được sắp xếp đúng cách, các phần tử `<script>` hoặc `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` chỉ chứa các nhóm `<dt>` và `<dd>` được sắp xếp đúng cách, các phần tử `<script>` hoặc `<template>`."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "Các mục trong danh sách định nghĩa (`<dt>` và `<dd>`) phải được đưa vào một phần tử `<dl>` mẹ để đảm bảo rằng trình đọc màn hình có thể thông báo đúng cách các mục này. [Tìm hiểu thêm](https://web.dev/dlitem/)."
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "Các phần tử `<dl>` không bao gồm những mục trong danh sách định nghĩa"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "Các phần tử `<dl>` chứa mục trong danh sách định nghĩa"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "Tiêu đề giúp người dùng trình đọc màn hình nắm được thông tin tổng quan về trang, và giúp người dùng công cụ tìm kiếm chủ yếu dựa vào tiêu đề này xác định xem một trang có liên quan đến nội dung tìm kiếm của họ hay không. [Tìm hiểu thêm](https://web.dev/document-title/)."
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "Tài liệu không có phần tử `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "Tài liệu có phần tử `<title>`"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "Giá trị của thuộc tính id phải là duy nhất, có như vậy công nghệ hỗ trợ mới không bỏ qua các điểm dữ liệu khác. [Tìm hiểu thêm](https://web.dev/duplicate-id/)."
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "Các thuộc tính `[id]` trên trang không phải là duy nhất"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "Các thuộc tính `[id]` trên trang là duy nhất"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "Người dùng trình đọc màn hình dựa vào tiêu đề khung để mô tả nội dung của khung. [Tìm hiểu thêm](https://web.dev/frame-title/)."
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "Phần tử `<frame>` hoặc `<iframe>` không có tiêu đề"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "Các phần tử `<frame>` hoặc `<iframe>` có tiêu đề"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "Nếu một trang chưa chỉ định thuộc tính ngôn ngữ, thì trình đọc màn hình sẽ xem như trang đó đang hiển thị bằng ngôn ngữ mặc định mà người dùng chọn khi thiết lập trình đọc màn hình. Nếu trên thực tế, trang đó không hiển thị bằng ngôn ngữ mặc định, tức là trình đọc màn hình có thể thông báo sai về văn bản của trang đó. [Tìm hiểu thêm](https://web.dev/html-has-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "Phần tử `<html>` chưa có thuộc tính `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "Phần tử `<html>` có thuộc tính `[lang]`"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "Việc chỉ định [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) hợp lệ sẽ giúp trình đọc màn hình thông báo văn bản đúng cách. [Tìm hiểu thêm](https://web.dev/html-lang-valid/)."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "Thuộc tính `[lang]` của phần tử `<html>` không có giá trị hợp lệ."
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "Thuộc tính `[lang]` của phần tử `<html>` có giá trị hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "Các phần tử thông tin nên là đoạn văn bản thay thế ngắn, có tính mô tả. Có thể bỏ qua phần tử trang trí bằng một thuộc tính alt trống. [Tìm hiểu thêm](https://web.dev/image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "Phần tử hình ảnh không có thuộc tính `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "Các phần tử hình ảnh có thuộc tính `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "Khi dùng một hình ảnh làm nút `<input>`, thì việc cung cấp văn bản thay thế có thể giúp người dùng trình đọc màn hình hiểu rõ mục đích của nút đó. [Tìm hiểu thêm](https://web.dev/input-image-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "Các phần tử `<input type=\"image\">` không có văn bản `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "Các phần tử `<input type=\"image\">` có văn bản `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "Các nhãn đảm bảo rằng những công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình, thông báo các biện pháp kiểm soát biểu mẫu đúng cách. [Tìm hiểu thêm](https://web.dev/label/)."
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "Các phần tử biểu mẫu không có nhãn liên kết"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "Các phần tử biểu mẫu có nhãn liên quan"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "Bảng đang dùng cho mục đích bố cục không nên bao gồm phần tử dữ liệu, chẳng hạn như th, phần tử chú thích hoặc thuộc tính tóm tắt, vì điều này có thể tạo ra trải nghiệm gây bối rối cho người dùng trình đọc màn hình. [Tìm hiểu thêm](https://web.dev/layout-table/)."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "Các phần tử `<table>` dạng trình bày không tránh sử dụng `<th>`, `<caption>` hoặc thuộc tính `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "Các phần tử `<table>` dạng trình bày tránh sử dụng `<th>`, `<caption>` hoặc thuộc tính `[summary]`."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "Văn bản liên kết (và văn bản thay thế cho hình ảnh, khi dùng làm đường dẫn liên kết) có thể thấy rõ, duy nhất và có thể lấy tiêu điểm sẽ cải thiện trải nghiệm khám phá cho người dùng trình đọc màn hình. [Tìm hiểu thêm](https://web.dev/link-name/)."
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "Các phần tử liên kết không có tên có thể nhận rõ"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "Các phần tử liên kết có tên có thể nhận rõ"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "Các trình đọc màn hình có cách riêng để thông báo về danh sách. Khi danh sách có cấu trúc phù hợp, trình đọc màn hình sẽ thông báo về danh sách chính xác hơn. [Tìm hiểu thêm](https://web.dev/list/)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "Danh sách không chỉ chứa các phần tử `<li>` và phần tử hỗ trợ tập lệnh (`<script>` và `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "Danh sách chỉ chứa các phần tử `<li>` và phần tử hỗ trợ tập lệnh (`<script>` và `<template>`)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "Trình đọc màn hình yêu cầu các mục danh sách (`<li>`) phải có trong một `<ul>` hoặc `<ol>` mẹ để được thông báo đúng cách. [Tìm hiểu thêm](https://web.dev/listitem/)."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "Các mục trong danh sách (`<li>`) không có trong phần tử `<ul>` hoặc `<ol>` mẹ."
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "Các mục trong danh sách (`<li>`) có trong phần tử mẹ `<ul>` hoặc `<ol>`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "Người dùng không muốn trang tự động làm mới. Khi trang tự động làm mới, tiêu điểm sẽ quay về đầu trang. Người dùng có thể cảm thấy khó chịu hoặc bị nhầm lẫn nếu gặp trường hợp này. [Tìm hiểu thêm](https://web.dev/meta-refresh/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "Tài liệu này sử dụng `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "Tài liệu này không dùng `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "Việc tắt tính năng thu phóng sẽ gây trở ngại cho những người dùng có thị lực kém bị lệ thuộc vào chức năng phóng to màn hình để thấy rõ nội dung trang web. [Tìm hiểu thêm](https://web.dev/meta-viewport/)."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`[user-scalable=\"no\"]` được dùng trong phần tử `<meta name=\"viewport\">` hoặc thuộc tính `[maximum-scale]` nhỏ hơn 5."
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` không được sử dụng trong phần tử `<meta name=\"viewport\">` và thuộc tính `[maximum-scale]` không nhỏ hơn 5."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "Trình đọc màn hình không thể dịch nội dung không ở dạng văn bản. Khi bạn thêm văn bản thay thế vào các phần tử `<object>`, trình đọc màn hình sẽ truyền đạt được ý nghĩa cho người dùng. [Tìm hiểu thêm](https://web.dev/object-alt/)."
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "Các phần tử `<object>` không có văn bản `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "Các phần tử `<object>` có văn bản `[alt]`"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "Giá trị lớn hơn 0 ngụ ý thứ tự di chuyển rõ ràng. Mặc dù hợp lệ về mặt kỹ thuật nhưng điều này thường tạo ra trải nghiệm khó chịu cho những người dùng bị lệ thuộc vào công nghệ hỗ trợ. [Tìm hiểu thêm](https://web.dev/tabindex/)."
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "Một số phần tử có giá trị `[tabindex]` lớn hơn 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "Không phần tử nào có giá trị `[tabindex]` lớn hơn 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "Trình đọc màn hình có các tính năng giúp người dùng dễ sử dụng bảng hơn. Việc đảm bảo các ô `<td>` sử dụng thuộc tính `[headers]` chỉ tham chiếu các ô khác trong cùng bảng có thể cải thiện trải nghiệm của người dùng trình đọc màn hình. [Tìm hiểu thêm](https://web.dev/td-headers-attr/)."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "Các ô trong phần tử `<table>` sử dụng thuộc tính `[headers]` tham chiếu đến một phần tử `id` không tìm thấy trong cùng một bảng."
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "Các ô trong phần tử `<table>` sử dụng thuộc tính `[headers]` tham chiếu đến các ô trong cùng một bảng."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "Trình đọc màn hình có các tính năng giúp người dùng dễ sử dụng bảng hơn. Việc đảm bảo tiêu đề bảng luôn tham chiếu đến một nhóm ô nào đó có thể cải thiện trải nghiệm của người dùng trình đọc màn hình. [Tìm hiểu thêm](https://web.dev/th-has-data-cells/)."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "Các phần tử `<th>` và phần tử có `[role=\"columnheader\"/\"rowheader\"]` không chứa các ô dữ liệu mà các phần tử đó mô tả."
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "Các phần tử `<th>` và phần tử có `[role=\"columnheader\"/\"rowheader\"]` chứa các ô dữ liệu mà các phần tử này mô tả."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "Việc chỉ định một [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) hợp lệ cho các phần tử sẽ giúp trình đọc màn hình phát âm văn bản chính xác. [Tìm hiểu thêm](https://web.dev/valid-lang/)."
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "Các thuộc tính `[lang]` không có giá trị hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "Các thuộc tính `[lang]` có giá trị hợp lệ"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "Video có phụ đề có thể giúp người dùng bị khiếm thính và nặng tai dễ dàng tiếp cận nội dung video hơn. [Tìm hiểu thêm](https://web.dev/video-caption/)."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "Các phần tử `<video>` không chứa phần tử `<track>` có `[kind=\"captions\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "Các phần tử `<video>` chứa phần tử `<track>` có `[kind=\"captions\"]`"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "Phần mô tả âm thanh cung cấp thông tin liên quan cho video mà phần hội thoại không thể làm được, chẳng hạn như cảnh và biểu cảm khuôn mặt. [Tìm hiểu thêm](https://web.dev/video-description/)."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "Các phần tử `<video>` không chứa phần tử `<track>` có `[kind=\"description\"]`."
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "Các phần tử `<video>` chứa phần tử `<track>` có `[kind=\"description\"]`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "Hãy xác định `apple-touch-icon` để khi người dùng thêm một ứng dụng web tiến bộ vào màn hình chính trên iOS, biểu tượng ứng dụng sẽ hiển thị chính xác. Thuộc tính này phải trỏ đến ảnh PNG vuông có kích thước 192px (hoặc 180px) ở dạng không trong suốt. [Tìm hiểu thêm](https://web.dev/apple-touch-icon/)"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "Chưa cung cấp `apple-touch-icon` hợp lệ"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` đã lỗi thời, nên dùng `apple-touch-icon`."
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "Hãy cung cấp `apple-touch-icon` hợp lệ"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Các tiện ích của Chrome ảnh hưởng tiêu cực đến hiệu suất tải của trang này. Hãy thử kiểm tra trang ở chế độ ẩn danh hoặc từ một hồ sơ trên Chrome không có tiện ích."
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "Đánh giá tập lệnh"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "Phân tích cú pháp tập lệnh"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "Tổng thời gian của CPU"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "Hãy cân nhắc giảm thời gian dùng để phân tích cú pháp, biên soạn và thực thi JS. Bạn có thể giải quyết vấn đề này bằng cách phân phối các tải trọng JS nhỏ hơn. [Tìm hiểu thêm](https://web.dev/bootup-time)."
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "Giảm thời gian thực thi JavaScript"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "Thời gian thực thi JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "Ảnh GIF lớn không có hiệu quả trong việc phân phối nội dung động. Hãy cân nhắc sử dụng video MPEG4/WebM cho ảnh động và PNG/WebP cho ảnh tĩnh thay vì ảnh GIF để tiết kiệm dữ liệu mạng. [Tìm hiểu thêm](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "Sử dụng các định dạng video cho nội dung động"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "Hãy cân nhắc tải từng phần các hình ảnh ẩn và nằm ngoài màn hình sau khi tải xong tất cả tài nguyên quan trọng nhằm giảm thời gian tương tác. [Tìm hiểu thêm](https://web.dev/offscreen-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "Trì hoãn tải các hình ảnh ngoài màn hình"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "Các tài nguyên đang chặn lần hiển thị đầu tiên của trang. Hãy cân nhắc phân phối nội dòng JS/Biểu định kiểu xếp chồng (CSS) quan trọng và trì hoãn mọi JS/kiểu không quan trọng. [Tìm hiểu thêm](https://web.dev/render-blocking-resources)."
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "Loại bỏ các tài nguyên chặn hiển thị"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "Tải trọng mạng lớn gây tốn kém cho người dùng và thường khiến thời gian tải lâu. [Tìm hiểu thêm](https://web.dev/total-byte-weight)."
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "Tổng kích thước là {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "Tránh các tài nguyên lớn trên mạng"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "Tránh tài nguyên lớn trên mạng"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "Việc giảm kích thước tệp Biểu định kiểu xếp chồng (CSS) có thể giảm kích thước tải trọng mạng. [Tìm hiểu thêm](https://web.dev/unminified-css)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "Rút gọn CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "Việc giảm kích thước tệp JavaScript có thể giảm kích thước tải trọng và thời gian phân tích cú pháp tập lệnh. [Tìm hiểu thêm](https://web.dev/unminified-javascript)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "Rút gọn JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "Hãy xóa các quy tắc vô hiệu khỏi biểu định kiểu và trì hoãn tải Biểu định kiểu xếp chồng (CSS) không dùng cho nội dung trong màn hình đầu tiên để giảm số byte không cần thiết mà hoạt động mạng sử dụng. [Tìm hiểu thêm](https://web.dev/unused-css-rules)."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "Xóa biểu định kiểu xếp chồng (CSS) không dùng"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "Xóa JavaScript không dùng để giảm số byte tiêu tốn vào hoạt động mạng."
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "Xóa JavaScript không dùng"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "Bộ nhớ đệm có thời gian hữu dụng dài có thể giúp tăng tốc số lượt truy cập lặp lại vào trang của bạn. [Tìm hiểu thêm](https://web.dev/uses-long-cache-ttl)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{Đã tìm thấy 1 tài nguyên}other{Đã tìm thấy # tài nguyên}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "Phân phối các nội dung tĩnh bằng chính sách bộ nhớ đệm hiệu quả"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "Sử dụng chính sách bộ nhớ đệm hiệu quả cho các nội dung tĩnh"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "Hình ảnh được tối ưu hóa sẽ tải nhanh hơn và tiêu tốn ít dữ liệu di động hơn. [Tìm hiểu thêm](https://web.dev/uses-optimized-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "Mã hóa hình ảnh hiệu quả"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "Phân phát hình ảnh có kích thước phù hợp để tiết kiệm dữ liệu di động và cải thiện thời gian tải. [Tìm hiểu thêm](https://web.dev/uses-responsive-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "Thay đổi kích thước hình ảnh cho phù hợp"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "Phải phân phát các tài nguyên dựa trên văn bản ở định dạng nén (gzip, deflate hoặc brotli) để giảm thiểu tổng số byte mạng. [Tìm hiểu thêm](https://web.dev/uses-text-compression)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "Bật tính năng nén văn bản"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "Các định dạng hình ảnh như JPEG 2000, JPEG XR và WebP thường nén tốt hơn PNG hoặc JPEG, tức là tải xuống nhanh hơn và tiêu tốn ít dữ liệu hơn. [Tìm hiểu thêm](https://web.dev/uses-webp-images)."
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "Phân phối hình ảnh ở định dạng mới và hiệu quả hơn"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "Nếu chiều rộng của nội dung trong ứng dụng không khớp với chiều rộng của khung nhìn, thì ứng dụng có thể không được tối ưu hóa cho màn hình thiết bị di động. [Tìm hiểu thêm](https://web.dev/content-width)"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "Kích thước khung nhìn {innerWidth}px không khớp với kích thước cửa sổ {outerWidth}px."
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "Kích thước của nội dung không phù hợp với khung nhìn"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "Kích thước của nội dung phù hợp với khung nhìn"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "Các Chuỗi yêu cầu quan trọng dưới đây cho bạn biết những tài nguyên có mức độ ưu tiên cao sẽ được tải. Hãy cân nhắc giảm độ dài chuỗi, giảm kích thước tài nguyên tải xuống hoặc trì hoãn tải xuống các tài nguyên không cần thiết để cải thiện tốc độ tải trang. [Tìm hiểu thêm](https://web.dev/critical-request-chains)."
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{Đã tìm thấy 1 chuỗi}other{Đã tìm thấy # chuỗi}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "Giảm thiểu độ sâu của các yêu cầu quan trọng"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "Không dùng nữa/Cảnh báo"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Dòng"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "Cuối cùng, các API không dùng nữa sẽ bị xóa khỏi trình duyệt. [Tìm hiểu thêm](https://web.dev/deprecations)."
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{Tìm thấy 1 cảnh báo}other{Tìm thấy # cảnh báo}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "Sử dụng các API không dùng nữa"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "Tránh các API không dùng nữa"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "Bộ nhớ đệm của ứng dụng không còn dùng nữa. [Tìm hiểu thêm](https://web.dev/appcache-manifest)."
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "Tìm thấy \"{AppCacheManifest}\""
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "Dùng bộ nhớ đệm của ứng dụng"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "Tránh sử dụng bộ nhớ đệm của ứng dụng"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "Khi bạn chỉ định loại tài liệu, trình duyệt sẽ không chuyển sang chế độ tương thích ngược. [Tìm hiểu thêm](https://web.dev/doctype)"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "Tên loại tài liệu phải là chuỗi `html` viết thường"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "Tài liệu phải chứa một loại tài liệu"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId lẽ ra phải là một chuỗi trống"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId lẽ ra phải là một chuỗi trống"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "Trang thiếu loại tài liệu HTML nên đã kích hoạt chế độ tương thích ngược"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "Trang có loại tài liệu HTML"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "Phần tử"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "Thống kê"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "Giá trị"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "Các kỹ sư trình duyệt khuyến cáo rằng các trang không nên chứa quá 1.500 phần tử DOM. Tốt nhất là có độ sâu của cây nhỏ hơn 32 phần tử và có ít hơn 60 phần tử con/phần tử mẹ. Một DOM lớn có thể làm tăng mức sử dụng bộ nhớ, khiến [các phép tính về kiểu](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations) dài hơn, đồng thời tạo ra [các quy trình trình bày lại bố cục](https://developers.google.com/speed/articles/reflow) tốn kém. [Tìm hiểu thêm](https://web.dev/dom-size)."
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 phần tử}other{# phần tử}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "Tránh kích thước DOM quá lớn"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "Độ sâu DOM tối đa"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "Tổng số các phần tử DOM"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "Phần tử con tối đa"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "Tránh kích thước DOM quá lớn"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "Mục tiêu"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "Thêm `rel=\"noopener\"` hoặc `rel=\"noreferrer\"` vào mọi đường dẫn liên kết ngoài để cải thiện hiệu suất và ngăn chặn các lỗ hổng bảo mật. [Tìm hiểu thêm](https://web.dev/external-anchors-use-rel-noopener)."
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "Các đường dẫn liên kết đến các trang đích trên nhiều nguồn gốc là không an toàn"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "Các đường dẫn liên kết đến các trang đích trên nhiều nguồn gốc là an toàn"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "Không thể xác định trang đích cho phần tử neo ({anchorHTML}). Nếu không dùng làm siêu liên kết, hãy cân nhắc xóa target=_blank."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "Các trang web yêu cầu vị trí của người dùng mà không cung cấp ngữ cảnh sẽ khiến người dùng không tin tưởng hoặc bối rối. Hãy cân nhắc liên kết yêu cầu với hành động của người dùng. [Tìm hiểu thêm](https://web.dev/geolocation-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "Yêu cầu quyền truy cập vị trí địa lý khi tải trang"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "Tránh yêu cầu quyền truy cập vị trí địa lý khi tải trang"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "Phiên bản"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "Phát hiện tất cả thư viện JavaScript ở phía giao diện người dùng trên trang này. [Tìm hiểu thêm](https://web.dev/js-libraries)"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "Thư viện JavaScript phát hiện được"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "Đối với những người dùng có kết nối chậm, các tập lệnh bên ngoài tự động được đưa vào qua `document.write()` có thể làm trang tải chậm hàng chục giây. [Tìm hiểu thêm](https://web.dev/no-document-write)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "Sử dụng `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "Tránh `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "Mức độ nghiêm trọng cao nhất"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "Phiên bản thư viện"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "Số lượng lỗ hổng"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "Một số tập lệnh của bên thứ ba có thể chứa các lỗ hổng bảo mật đã biết mà kẻ tấn công dễ dàng xác định và khai thác. [Tìm hiểu thêm](https://web.dev/no-vulnerable-libraries)."
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{Phát hiện thấy 1 lỗ hổng}other{Phát hiện thấy # lỗ hổng}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "Bao gồm các thư viện giao diện người dùng JavaScript có những lỗ hổng bảo mật đã biết"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "Cao"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "Thấp"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "Trung bình"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "Tránh các thư viện giao diện người dùng JavaScript có lỗ hổng bảo mật đã biết"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "Các trang web gửi thông báo không có ngữ cảnh sẽ khiến người dùng không tin tưởng hoặc bối rối. Hãy cân nhắc liên kết yêu cầu với cử chỉ của người dùng. [Tìm hiểu thêm](https://web.dev/notification-on-start)."
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "Yêu cầu quyền truy cập thông báo khi tải trang"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "Tránh yêu cầu quyền truy cập thông báo khi tải trang"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "Các phần tử không đạt"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "Việc ngăn dán mật khẩu sẽ làm giảm tác dụng của chính sách bảo mật hiệu quả. [Tìm hiểu thêm](https://web.dev/password-inputs-can-be-pasted-into)."
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "Ngăn người dùng dán vào các trường mật khẩu"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "Cho phép người dùng dán vào các trường mật khẩu"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "Giao thức"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 mang lại nhiều lợi ích hơn HTTP/1.1, trong đó có tiêu đề nhị phân, đa hợp và máy chủ tự quyết. [Tìm hiểu thêm](https://web.dev/uses-http2)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{Chưa phân phát 1 yêu cầu qua HTTP/2}other{Chưa phân phát # yêu cầu qua HTTP/2}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "Không sử dụng HTTP/2 cho tất cả các tài nguyên của trang web"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "Sử dụng HTTP/2 cho các tài nguyên của chính trang web"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "Hãy cân nhắc đánh dấu trình xử lý sự kiện chạm và di chuyển con lăn là `passive` để cải thiện hiệu suất cuộn trên trang. [Tìm hiểu thêm](https://web.dev/uses-passive-event-listeners)."
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "Không sử dụng trình nghe bị động để cải thiện hiệu suất cuộn"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "Sử dụng trình nghe bị động để cải thiện hiệu suất cuộn"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "Nội dung mô tả"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "Các lỗi được ghi vào bảng điều khiển là những sự cố chưa giải quyết. Những sự cố này có thể do lỗi yêu cầu mạng và các vấn đề khác của trình duyệt gây ra. [Tìm hiểu thêm](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "Đã ghi lỗi của trình duyệt vào bảng điều khiển"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "Chưa ghi lỗi nào của trình duyệt vào bảng điều khiển"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "Sử dụng tính năng Biểu định kiểu xếp chồng (CSS) hiển thị phông chữ để đảm bảo văn bản hiển thị với người dùng khi phông chữ web đang tải. [Tìm hiểu thêm](https://web.dev/font-display)."
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "Đảm bảo văn bản vẫn hiển thị trong khi tải phông chữ web"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "Tất cả văn bản vẫn hiển thị trong khi tải phông chữ web"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse không thể tự động kiểm tra giá trị hiển thị phông chữ cho URL sau: {fontURL}."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "Tỷ lệ khung hình (Thực tế)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "Tỷ lệ khung hình (Hiển thị)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "Kích thước hiển thị của hình ảnh phải khớp với tỷ lệ khung hình tự nhiên. [Tìm hiểu thêm](https://web.dev/image-aspect-ratio)."
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "Hiển thị hình ảnh có tỷ lệ khung hình không chính xác"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "Hiển thị hình ảnh có tỷ lệ khung hình chính xác"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "Thông tin kích thước hình ảnh không hợp lệ {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "Các trình duyệt có thể chủ động nhắc người dùng thêm ứng dụng của bạn vào màn hình chính để tăng mức độ tương tác. [Tìm hiểu thêm](https://web.dev/installable-manifest)"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Tệp kê khai ứng dụng web không đáp ứng các yêu cầu về khả năng cài đặt"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Tệp kê khai ứng dụng web đáp ứng các yêu cầu về khả năng cài đặt"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "URL không an toàn"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "Bạn phải bảo vệ tất cả các trang web bằng HTTPS, kể cả những trang web không xử lý dữ liệu nhạy cảm. HTTPS ngăn kẻ xâm nhập can thiệp hoặc vô tình biết được nội dung trao đổi giữa ứng dụng và người dùng của bạn, đồng thời là điều kiện tiên quyết nếu bạn muốn dùng HTTP/2 và nhiều API nền tảng web mới. [Tìm hiểu thêm](https://web.dev/is-on-https)."
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{Tìm thấy 1 yêu cầu không an toàn}other{Tìm thấy # yêu cầu không an toàn}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "Không sử dụng HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "Sử dụng HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "Tốc độ tải trang nhanh trên mạng di động giúp mang đến trải nghiệm tích cực cho người dùng thiết bị di động. [Tìm hiểu thêm](https://web.dev/load-fast-enough-for-pwa)."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "Tương tác ở giây thứ {timeInMs, number, seconds}"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "Tương tác trên mạng di động mô phỏng ở giây thứ {timeInMs, number, seconds}"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "Trang của bạn tải quá chậm và không tương tác trong vòng 10 giây. Hãy xem các lựa chọn tối ưu hóa và thông tin chẩn đoán trong phần \"Hiệu suất\" để tìm hiểu cách cải thiện."
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "Tốc độ tải trang không đủ nhanh trên mạng di động"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "Tốc độ tải trang đủ nhanh trên mạng di động"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "Danh mục"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "Hãy cân nhắc giảm thời gian dùng để phân tích cú pháp, biên soạn và thực thi JS. Bạn có thể giải quyết vấn đề này bằng cách phân phối các tải trọng JS nhỏ hơn. [Tìm hiểu thêm](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "Giảm thiểu công việc theo chuỗi chính"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "Giảm thiểu công việc theo chuỗi chính"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "Để tiếp cận nhiều người dùng nhất, các trang web phải hoạt động trên mọi trình duyệt chính. [Tìm hiểu thêm](https://web.dev/pwa-cross-browser)"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "Trang web hoạt động trên nhiều trình duyệt"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "Đảm bảo từng trang có thể liên kết sâu qua URL và URL là duy nhất để có thể chia sẻ trên mạng xã hội. [Tìm hiểu thêm](https://web.dev/pwa-each-page-has-url)"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "Mỗi trang có một URL"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "Quá trình chuyển tiếp phải diễn ra ngay khi bạn nhấn vào, kể cả khi mạng chậm. Trải nghiệm này là một yếu tố quan trọng quyết định cảm nhận của người dùng về hiệu suất. [Tìm hiểu thêm](https://web.dev/pwa-page-transitions)"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "Người dùng không cảm thấy mạng chậm khi chuyển trang"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "Thời gian chờ nhập thông tin theo ước tính là thời gian ước tính mà ứng dụng cần để phản hồi thông tin do người dùng nhập (tính bằng mili giây) trong khoảng thời gian 5 giây tải nhiều trang nhất. Nếu người dùng phải chờ quá 50 mili giây, thì ứng dụng của bạn bị coi là chạy chậm. [Tìm hiểu thêm](https://web.dev/estimated-input-latency)."
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "Thời gian chờ nhập thông tin theo ước tính"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "Chỉ số Hiển thị nội dung đầu tiên đánh dấu thời điểm hiển thị văn bản hoặc hình ảnh đầu tiên. [Tìm hiểu thêm](https://web.dev/first-contentful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "Hình ảnh có nội dung đầu tiên"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "Chỉ số CPU nhàn rỗi đầu tiên đánh dấu thời điểm đầu tiên chuỗi chính của trang không phải xử lý quá nhiều thông tin nhập vào. [Tìm hiểu thêm](https://web.dev/first-cpu-idle)"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "CPU nhàn rỗi đầu tiên"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "Chỉ số Hiển thị nội dung đầu tiên đo lường thời điểm hiển thị nội dung chính của trang. [Tìm hiểu thêm](https://web.dev/first-meaningful-paint)."
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "Hình ảnh có ý nghĩa đầu tiên"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "Thời điểm tương tác là khoảng thời gian mà trang cần để trở nên hoàn toàn tương tác. [Tìm hiểu thêm](https://web.dev/interactive)."
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "Thời điểm tương tác"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "Thời gian phản hồi lần tương tác đầu tiên tối đa mà người dùng có thể gặp phải là thời gian thực hiện nhiệm vụ lâu nhất (tính bằng mili giây). [Tìm hiểu thêm](https://developers.google.com/web/updates/2018/05/first-input-delay)."
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "Thời gian phản hồi lần tương tác đầu tiên tối đa có thể"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "Chỉ số tốc độ cho biết nội dung của một trang hiển thị nhanh chóng đến mức nào. [Tìm hiểu thêm](https://web.dev/speed-index)."
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "Chỉ số tốc độ"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "Tổng tất cả các khoảng thời gian giữa thời điểm Hiển thị nội dung đầu tiên (FCP) và Thời điểm tương tác khi thời gian nhiệm vụ vượt quá 50 mili giây được biểu thị bằng đơn vị mili giây."
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "Tổng thời gian chặn"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "Thời gian trọn vòng (RTT) của mạng có ảnh hưởng lớn đến hiệu suất. Nếu mất nhiều thời gian trọn vòng (RTT) để đến một nguồn gốc, tức là máy chủ càng gần người dùng thì hiệu quả càng cao. [Tìm hiểu thêm](https://hpbn.co/primer-on-latency-and-bandwidth/)."
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "Thời gian trọn vòng của mạng"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "Thời gian chờ của máy chủ có thể ảnh hưởng đến hiệu suất của trang web. Nếu máy chủ của một nguồn gốc có thời gian chờ cao, tức là máy chủ bị quá tải hoặc có hiệu suất phụ trợ thấp. [Tìm hiểu thêm](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)."
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "Thời gian dưới nền của máy chủ"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Trình chạy dịch vụ giúp ứng dụng web của bạn hoạt động ổn định trong điều kiện mạng chập chờn. [Tìm hiểu thêm](https://web.dev/offline-start-url)"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` không trả về mã trạng thái 200 khi không có mạng"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` trả về mã trạng thái 200 khi không có mạng"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse không đọc được `start_url` trong tệp kê khai. Do đó, `start_url` được giả định là URL của tài liệu. Thông báo lỗi: '{manifestWarning}'."
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "Vượt ngân sách"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "Đảm bảo số lượng và quy mô của yêu cầu mạng thấp hơn mục tiêu đặt ra của ngân sách hiệu suất đã cung cấp. [Tìm hiểu thêm](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 yêu cầu}other{# yêu cầu}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "Ngân sách hiệu suất"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "Nếu bạn thiết lập HTTPS từ trước, hãy nhớ chuyển hướng toàn bộ lưu lượng truy cập HTTP tới HTTPS để bật các tính năng web an toàn cho tất cả người dùng. [Tìm hiểu thêm](https://web.dev/redirects-http)"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "Không chuyển hướng lưu lượng truy cập HTTP tới HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "Chuyển hướng lưu lượng truy cập HTTP tới HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "Các lần chuyển hướng sẽ làm giảm tốc độ tải trang. [Tìm hiểu thêm](https://web.dev/redirects)."
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "Tránh chuyển hướng trang nhiều lần"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "Để thiết lập ngân sách cho số lượng và quy mô của tài nguyên trang, hãy thêm tệp budget.json. [Tìm hiểu thêm](https://developers.google.com/web/tools/lighthouse/audits/budgets)."
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 yêu cầu • {byteCount, number, bytes} KB}other{# yêu cầu • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "Giảm số lượng yêu cầu và chuyển những tài nguyên có kích thước nhỏ"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "Phần tử liên kết chính tắc đề xuất URL nào nên hiển thị trong kết quả tìm kiếm. [Tìm hiểu thêm](https://web.dev/canonical)."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "Nhiều URL xung đột ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "Trỏ đến một miền khác ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "URL không hợp lệ ({url})."
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "Trỏ đến một vị trí `hreflang` khác ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "URL tương đối ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "Trỏ đến URL gốc của miền (trang chủ) thay vì trang nội dung tương đương"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "Tài liệu không có `rel=canonical` hợp lệ"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "Tài liệu có `rel=canonical` hợp lệ"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "Cỡ chữ dưới 12 pixel là quá nhỏ và khó đọc, buộc khách truy cập trên thiết bị di động phải “chụm để thu phóng” mới đọc được. Tốt nhất là hơn 60% văn bản trên trang có cỡ chữ lớn hơn hoặc bằng 12 pixel. [Tìm hiểu thêm](https://web.dev/font-size)."
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} văn bản dễ đọc"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "Văn bản không đọc được vì không có thẻ meta viewport nào được tối ưu hóa cho màn hình thiết bị di động."
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "Văn bản có tỷ lệ {decimalProportion, number, extendedPercent} là quá nhỏ (căn cứ vào mẫu {decimalProportionVisited, number, extendedPercent})."
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "Tài liệu không sử dụng cỡ chữ dễ đọc"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "Tài liệu sử dụng cỡ chữ dễ đọc"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "Các phần tử liên kết hreflang cho công cụ tìm kiếm biết nên liệt kê phiên bản trang nào trong kết quả tìm kiếm cho một ngôn ngữ hoặc khu vực cụ thể. [Tìm hiểu thêm](https://web.dev/hreflang)."
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "Tài liệu không có `hreflang` hợp lệ"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "Tài liệu có `hreflang` hợp lệ"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "Các trang có mã trạng thái HTTP không thành công có thể được lập chỉ mục không chính xác. [Tìm hiểu thêm](https://web.dev/http-status-code)."
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "Trang có mã trạng thái HTTP không thành công"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "Trang có mã trạng thái HTTP thành công"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "Các công cụ tìm kiếm không thể đưa trang của bạn vào kết quả tìm kiếm nếu bạn không cấp cho các công cụ này quyền thu thập thông tin của trang. [Tìm hiểu thêm](https://web.dev/is-crawable)."
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "Trang bị chặn lập chỉ mục"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "Trang không bị chặn lập chỉ mục"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "Văn bản mô tả trên đường dẫn liên kết giúp công cụ tìm kiếm hiểu được nội dung của bạn. [Tìm hiểu thêm](https://web.dev/link-text)."
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{Đã tìm thấy 1 liên kết}other{Đã tìm thấy # liên kết}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "Các phần tử liên kết không có văn bản mô tả"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "Các phần tử liên kết có văn bản mô tả"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "Chạy [Công cụ kiểm tra dữ liệu có cấu trúc](https://search.google.com/structured-data/testing-tool/) và [Công cụ khử lỗi dữ liệu có cấu trúc](http://linter.structured-data.org/) để xác thực loại dữ liệu này. [Tìm hiểu thêm](https://web.dev/structured-data)."
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "Dữ liệu có cấu trúc là hợp lệ"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "Bạn có thể thêm phần mô tả meta vào kết quả tìm kiếm để tóm tắt ngắn gọn nội dung trang. [Tìm hiểu thêm](https://web.dev/meta-description)."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "Văn bản mô tả hiện đang trống."
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "Tài liệu không có phần mô tả meta"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "Tài liệu có phần mô tả meta"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "Các công cụ tìm kiếm không thể lập chỉ mục nội dung plugin và nhiều thiết bị hạn chế hoặc không hỗ trợ plugin. [Tìm hiểu thêm](https://web.dev/plugins)."
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "Tài liệu sử dụng plugin"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "Tài liệu tránh sử dụng plugin"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "Nếu định dạng của tệp robots.txt không đúng, thì trình thu thập thông tin có thể không hiểu được cách bạn muốn thu thập thông tin hoặc lập chỉ mục trang web của mình. [Tìm hiểu thêm](https://web.dev/robots-txt)"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "Yêu cầu robots.txt trả về trạng thái HTTP: {statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{Đã tìm thấy 1 lỗi}other{Đã tìm thấy # lỗi}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse không tải được tệp robots.txt xuống"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt không hợp lệ"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt hợp lệ"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "Các phần tử tương tác, chẳng hạn như nút và phần tử liên kết, nên có kích thước đủ lớn (48x48 pixel) và khoảng cách xung quanh các phần tử này đủ để nhấn mà không chồng chéo lên các phần tử khác. [Tìm hiểu thêm](https://web.dev/tap-targets)."
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} mục tiêu nhấn có kích thước phù hợp"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "Mục tiêu nhấn có kích thước quá nhỏ do không có thẻ meta viewport nào được tối ưu hóa cho màn hình thiết bị di động"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "Các mục tiêu nhấn có kích thước không phù hợp"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "Mục tiêu chồng chéo"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "Mục tiêu nhấn"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "Mục tiêu nhấn có kích thước phù hợp"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Trình chạy dịch vụ là công nghệ cho phép ứng dụng của bạn dùng nhiều tính năng của Ứng dụng web tiến bộ, chẳng hạn như hoạt động khi không có mạng, thêm vào màn hình chính, và thông báo đẩy. [Tìm hiểu thêm](https://web.dev/service-worker)"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "Trang này do một trình chạy dịch vụ kiểm soát. Tuy nhiên, không tìm thấy `start_url` vì tệp kê khai không thể phân tích cú pháp thành tệp JSON hợp lệ"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "Trang này do một trình chạy dịch vụ kiểm soát. Tuy nhiên, `start_url` ({startUrl}) không thuộc phạm vi của trình chạy dịch vụ này ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "Trang này do một trình chạy dịch vụ kiểm soát. Tuy nhiên, không tìm thấy `start_url` vì không tìm nạp được tệp kê khai."
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "Nguồn gốc này có một hoặc nhiều trình chạy dịch vụ. Tuy nhiên, trang ({pageUrl}) không thuộc phạm vi của các trình chạy dịch vụ này."
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "Không đăng ký một trình chạy dịch vụ kiểm soát trang và `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "Đăng ký một trình chạy dịch vụ kiểm soát trang và `start_url`"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "Màn hình chờ có giao diện giúp đảm bảo người dùng có trải nghiệm chất lượng cao khi chạy ứng dụng từ màn hình chính. [Tìm hiểu thêm](https://web.dev/splash-screen)"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "Chưa được định cấu hình cho màn hình chờ tùy chỉnh"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "Đã định cấu hình cho màn hình chờ tùy chỉnh"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "Bạn có thể đặt giao diện cho thanh địa chỉ trên trình duyệt để phù hợp với trang web của mình. [Tìm hiểu thêm](https://web.dev/themed-omnibox)"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "Không đặt màu giao diện cho thanh địa chỉ."
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "Đặt màu giao diện cho thanh địa chỉ."
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "Thời gian chặn chuỗi chính"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "Bên thứ ba"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "Mã của bên thứ ba có thể tác động đáng kể đến hiệu suất tải. Hãy hạn chế số nhà cung cấp bên thứ ba dư thừa và cố gắng tải mã của bên thứ ba sau khi trang của bạn hoàn thành phần lớn quá trình tải. [Tìm hiểu thêm](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)."
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "Mã của bên thứ ba đã chặn chuỗi chính trong {timeInMs, number, milliseconds} mili giây"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "Giảm mức ảnh hưởng của mã bên thứ ba"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "Việc sử dụng mã của bên thứ ba"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "Chỉ số Thời gian cho byte đầu tiên xác định thời gian máy chủ của bạn gửi phản hồi. [Tìm hiểu thêm](https://web.dev/time-to-first-byte)."
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "Tài liệu gốc mất {timeInMs, number, milliseconds} mili giây"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "Giảm thời gian phản hồi của máy chủ (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "Thời gian phản hồi của máy chủ chậm (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "Thời lượng"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "Thời gian bắt đầu"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "Loại"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "Hãy cân nhắc trang bị API Thời gian người dùng cho ứng dụng để đo lường hiệu suất thực tế của ứng dụng trong trải nghiệm người dùng chính. [Tìm hiểu thêm](https://web.dev/user-timings)."
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 dấu thời gian người dùng}other{# dấu thời gian người dùng}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "Các thời điểm cụ thể và khoảng thời gian được ghi lại bằng API Thời gian người dùng"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "Tìm thấy <link> kết nối trước cho \"{securityOrigin}\" nhưng trình duyệt không sử dụng phần tử liên kết này. Hãy kiểm tra để đảm bảo rằng bạn đang sử dụng thuộc tính `crossorigin` đúng cách."
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "Hãy cân nhắc thêm các gợi ý về tài nguyên `preconnect` hoặc `dns-prefetch` để thiết lập kết nối sớm tới những nguồn gốc quan trọng của bên thứ ba. [Tìm hiểu thêm](https://web.dev/uses-rel-preconnect)"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "Kết nối trước với các tên miền bắt buộc"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "Tìm thấy <link> tải trước cho \"{preloadURL}\" nhưng trình duyệt không sử dụng phần tử liên kết này. Hãy kiểm tra để đảm bảo rằng bạn đang sử dụng thuộc tính `crossorigin` đúng cách."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "Hãy cân nhắc sử dụng `<link rel=preload>` để ưu tiên tìm nạp các tài nguyên đang được yêu cầu vào một thời điểm khác trong quá trình tải trang. [Tìm hiểu thêm](https://web.dev/uses-rel-preload)."
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "Tải trước các yêu cầu chính"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "Thêm thẻ `<meta name=\"viewport\">` để tối ưu hóa ứng dụng của bạn cho màn hình thiết bị di động. [Tìm hiểu thêm](https://web.dev/viewport)"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "Không tìm thấy thẻ `<meta name=\"viewport\">`"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "Không có thẻ `<meta name=\"viewport\">` có `width` hoặc `initial-scale`"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "Có thẻ `<meta name=\"viewport\">` có `width` hoặc `initial-scale`"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "Ứng dụng của bạn phải hiển thị một số nội dung khi JavaScript bị tắt, ngay cả khi đó chỉ là một cảnh báo cho người dùng biết phải có JavaScript mới dùng được ứng dụng. [Tìm hiểu thêm](https://web.dev/without-javascript)."
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "Phần nội dung trang phải hiển thị một số nội dung nếu không có sẵn tập lệnh."
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "Không cung cấp nội dung dự phòng khi JavaScript không có sẵn"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "Chứa một số nội dung khi JavaScript không có sẵn"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "Nếu bạn đang tạo một Ứng dụng web tiến bộ, hãy cân nhắc dùng trình chạy dịch vụ để ứng dụng có thể hoạt động khi không có mạng. [Tìm hiểu thêm](https://web.dev/works-offline)"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "Trang hiện tại không trả về mã trạng thái 200 khi không có mạng"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "Trang hiện tại trả về mã trạng thái 200 khi không có mạng"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "Trang này có thể không tải được khi không có mạng vì URL kiểm tra ({requested}) đã được chuyển hướng tới \"{final}\". Hãy thử kiểm tra trực tiếp URL thứ hai."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "Đây là những cơ hội giúp cải thiện việc sử dụng ARIA trong ứng dụng của bạn, nhờ đó có thể nâng cao trải nghiệm cho người dùng công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình."
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "Đây là các cơ hội để cung cấp nội dung thay thế cho âm thanh và video. Điều này có thể cải thiện trải nghiệm của người dùng khiếm thính hoặc khiếm thị."
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "Âm thanh và video"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "Những mục này nêu bật các phương pháp hay nhất thường dùng cho hỗ trợ tiếp cận"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "Các phương pháp hay nhất"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "Các hoạt động kiểm tra này giúp xác định cơ hội [cải thiện khả năng hỗ trợ tiếp cận của ứng dụng web](https://developers.google.com/web/fundamentals/accessibility). Các hoạt động này chỉ có thể tự động phát hiện một phần vấn đề liên quan đến khả năng hỗ trợ tiếp cận, do đó, bạn nên kiểm tra cả theo cách thủ công."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "Các mục này nằm trong vùng không thể sử dụng công cụ kiểm tra tự động. Tìm hiểu thêm trong hướng dẫn của chúng tôi về cách [đánh giá khả năng hỗ trợ tiếp cận](https://developers.google.com/web/fundamentals/accessibility/how-to-review)."
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "Hỗ trợ tiếp cận"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "Đây là các cơ hội giúp cải thiện độ dễ đọc cho nội dung của bạn."
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "Độ tương phản"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "Đây là những cơ hội giúp cải thiện khả năng diễn giải của người dùng đối với nội dung của bạn ở các ngôn ngữ khác nhau."
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "Quốc tế hóa và bản địa hóa"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "Đây là những cơ hội giúp cải thiện chức năng diễn giải ngữ nghĩa của các biện pháp kiểm soát trong ứng dụng của bạn. Điều này có thể nâng cao trải nghiệm cho những người dùng công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình."
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "Tên và nhãn"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "Đây là các cơ hội để cải thiện khả năng điều hướng bằng bàn phím trong ứng dụng của bạn."
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "Điều hướng"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "Đây là các cơ hội để cải thiện trải nghiệm đọc dữ liệu trong bảng hoặc danh sách bằng công nghệ hỗ trợ, chẳng hạn như trình đọc màn hình."
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "Bảng và danh sách"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "Phương pháp hay nhất"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "Phần Ngân sách hiệu suất đặt ra tiêu chuẩn về hiệu suất của trang web."
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "Ngân sách"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "Thông tin bổ sung về hiệu suất của ứng dụng. Những số liệu này không [trực tiếp ảnh hưởng](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) đến Điểm hiệu suất."
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "Chẩn đoán"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "Khía cạnh quan trọng nhất của hiệu suất là tốc độ hiển thị pixel nhanh chóng trên màn hình. Các chỉ số chính: Hình ảnh có nội dung đầu tiên, Hình ảnh có ý nghĩa đầu tiên"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "Các thao tác để cải thiện thời gian hiển thị hình ảnh đầu tiên"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "Những đề xuất này có thể giúp trang của bạn tải nhanh hơn, chứ không [trực tiếp ảnh hưởng](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted) đến Điểm hiệu suất."
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "Cơ hội"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "Các chỉ số"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "Cải thiện trải nghiệm tải tổng thể để trang phản hồi và sẵn sàng cho bạn sử dụng sớm nhất có thể. Các số liệu chính: Thời điểm tương tác, Chỉ số tốc độ"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "Các thao tác để cải thiện hiệu suất tổng thể"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "Hiệu suất"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "Những hoạt động kiểm tra này sẽ xác thực các khía cạnh của một Ứng dụng web tiến bộ. [Tìm hiểu thêm](https://developers.google.com/web/progressive-web-apps/checklist)."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "Đây là những hoạt động kiểm tra được chỉ định trong [Danh sách kiểm tra ứng dụng web tiến bộ (PWA)](https://developers.google.com/web/progressive-web-apps/checklist) cơ bản, nhưng Lighthouse không tự động kiểm tra các mục này. Các hoạt động kiểm tra này không ảnh hưởng đến điểm số của bạn, nhưng bạn nên xác minh theo cách thủ công."
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "Ứng dụng web tiến bộ"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "Nhanh và đáng tin cậy"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "Có thể cài đặt"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA đã tối ưu hóa"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "Các hoạt động kiểm tra này đảm bảo rằng trang của bạn được tối ưu hóa cho thứ hạng trong kết quả của công cụ tìm kiếm. Những yếu tố bổ sung mà Lighthouse không kiểm tra có thể ảnh hưởng đến thứ hạng của bạn trong kết quả tìm kiếm. [Tìm hiểu thêm](https://support.google.com/webmasters/answer/35769)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "Chạy những trình xác thực bổ sung này trên trang web của bạn để xem thêm các phương pháp hay nhất dành cho quy trình Tối ưu hóa cho công cụ tìm kiếm (SEO)."
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "Định dạng HTML sao cho các trình thu thập thông tin có thể hiểu rõ hơn nội dung trong ứng dụng của bạn."
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "Các phương pháp hay nhất về nội dung"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "Để xuất hiện trong kết quả tìm kiếm, các trình thu thập thông tin cần quyền truy cập vào ứng dụng của bạn."
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "Thu thập thông tin và lập chỉ mục"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "Đảm bảo các trang của bạn thân thiện với thiết bị di động để người dùng có thể đọc các trang nội dung mà không cần phải chụm hoặc thu phóng. [Tìm hiểu thêm](https://developers.google.com/search/mobile-sites/)."
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "Thân thiện với thiết bị di động"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "Thời gian tồn tại (TTL) của bộ nhớ đệm"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "Vị trí"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "Tên"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "Số yêu cầu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "Loại tài nguyên"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "Kích thước"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "Thời gian sử dụng"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "Kích thước cần chuyển"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "URL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "Lượng dữ liệu có thể tiết kiệm được"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "Thời gian có thể tiết kiệm được"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "Lượng dữ liệu có thể tiết kiệm được là {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "Thời gian có thể tiết kiệm được là {wastedMs, number, milliseconds} mili giây"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "Tài liệu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "Phông chữ"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "Hình ảnh"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "Nội dung nghe nhìn"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} mili giây"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "Khác"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "Tập lệnh"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} giây"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "Biểu định kiểu"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "Bên thứ ba"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "Tổng"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "Đã xảy ra lỗi khi ghi dấu vết quá trình tải trang của bạn. Vui lòng chạy lại Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "Đã hết thời gian chờ kết nối với Giao thức của trình gỡ lỗi ban đầu ban đầu."
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome không thu thập được bất kỳ ảnh chụp màn hình nào trong quá trình tải trang. Hãy đảm bảo trang có nội dung hiển thị, sau đó thử chạy lại Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "Máy chủ DNS không thể phân giải miền đã cung cấp."
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "Trình thu thập {artifactName} bắt buộc đã gặp lỗi: {errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Đã xảy ra lỗi Chrome nội bộ. Vui lòng khởi động lại Chrome và thử chạy lại Lighthouse."
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "Trình thu thập {artifactName} bắt buộc không chạy."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse không thể tải trang bạn đã yêu cầu một cách đáng tin cậy. Hãy đảm bảo bạn đang kiểm tra URL chính xác và máy chủ đang phản hồi tất cả các yêu cầu đúng cách."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse không thể tải URL bạn yêu cầu một cách đáng tin cậy vì trang này đã ngừng phản hồi."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "URL bạn cung cấp không có chứng chỉ bảo mật hợp lệ. {securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome đã ngăn tải trang có quảng cáo xen kẽ. Hãy đảm bảo bạn đang kiểm tra URL chính xác và máy chủ đang phản hồi tất cả các yêu cầu đúng cách."
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse không thể tải trang bạn đã yêu cầu một cách đáng tin cậy. Hãy đảm bảo bạn đang kiểm tra URL chính xác và máy chủ đang phản hồi tất cả các yêu cầu đúng cách. (Chi tiết: {errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse không thể tải trang bạn đã yêu cầu một cách đáng tin cậy. Hãy đảm bảo bạn đang kiểm tra URL chính xác và máy chủ đang phản hồi tất cả các yêu cầu đúng cách. (Mã trạng thái: {statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "Thời gian tải trang quá lâu. Hãy thực hiện các khuyến nghị trong báo cáo để giảm thời gian tải trang rồi thử chạy lại Lighthouse. ({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "Quá trình chờ phản hồi của giao thức DevTools đã vượt quá thời gian phân bổ. (Phương thức: {protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "Quá trình tìm nạp nội dung tài nguyên đã vượt quá thời gian phân bổ"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "URL bạn cung cấp có vẻ không hợp lệ."
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "Hiển thị kết quả kiểm tra"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "Điều hướng ban đầu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "Độ trễ tối đa của đường dẫn quan trọng:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "Lỗi!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "Lỗi báo cáo: không có thông tin kiểm tra"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "Dữ liệu của phòng thí nghiệm"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "Kết quả phân tích [Lighthouse](https://developers.google.com/web/tools/lighthouse/) cho trang hiện tại dựa trên một mạng di động mô phỏng. Các giá trị chỉ là ước tính và có thể thay đổi."
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "Các mục bổ sung cần kiểm tra theo cách thủ công"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "Không áp dụng"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "Cơ hội"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "Thời lượng tiết kiệm được theo ước tính"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "Số lần kiểm tra đạt yêu cầu"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "Thu gọn đoạn mã"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "Mở rộng đoạn mã"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "Hiển thị tài nguyên của bên thứ ba"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "Đã xảy ra sự cố ảnh hưởng đến lần chạy Lighthouse này:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "Các giá trị chỉ là ước tính và có thể thay đổi. Điểm hiệu suất [chỉ căn cứ vào các chỉ số này](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)."
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "Đã vượt qua bài kiểm tra nhưng có cảnh báo"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "Cảnh báo: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "Hãy cân nhắc tải tệp GIF lên một dịch vụ mà nhờ đó, tệp GIF có thể được nhúng ở dạng video HTML5."
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "Cài đặt một [plugin tải từng phần của WordPress](https://wordpress.org/plugins/search/lazy+load/) để trì hoãn mọi hình ảnh ngoài màn hình, hoặc chuyển sang một giao diện cung cấp chức năng đó. Ngoài ra, hãy cân nhắc sử dụng [plugin AMP (Accelerated Mobile Pages)](https://wordpress.org/plugins/amp/)."
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "Có một số plugin của WordPress có thể giúp bạn [đưa phần tử quan trọng vào nội tuyến](https://wordpress.org/plugins/search/critical+css/) hoặc [trì hoãn tài nguyên ít quan trọng hơn](https://wordpress.org/plugins/search/defer+css+javascript/). Xin lưu ý rằng những phương thức tối ưu hóa mà các plugin này cung cấp có thể làm gián đoạn tính năng của giao diện hoặc plugin, do đó, có thể bạn cần thay đổi mã."
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "Giao diện, plugin và thông số máy chủ đều tác động đến thời gian phản hồi của máy chủ. Hãy cân nhắc tìm một giao diện được tối ưu hóa, lựa chọn cẩn thận một plugin tối ưu hóa và/hoặc nâng cấp máy chủ."
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "Hãy cân nhắc hiển thị phần trích dẫn trong danh sách bài đăng (ví dụ như qua thẻ thêm), giảm số lượng bài đăng hiển thị trên một trang cụ thể, chia các bài đăng dài thành nhiều trang hoặc sử dụng một plugin để tải nhận xét theo từng phần."
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "Một số [plugin của WordPress](https://wordpress.org/plugins/search/minify+css/) có thể làm tăng tốc độ của trang web bằng cách ghép, giảm kích thước và nén kiểu. Bạn cũng có thể dùng quy trình tạo để tiến hành thu nhỏ trước, nếu có thể."
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "Một số [plugin của WordPress](https://wordpress.org/plugins/search/minify+javascript/) có thể làm tăng tốc độ của trang web bằng cách ghép, giảm kích thước và nén tập lệnh. Ngoài ra, bạn nên dùng quy trình tạo để tiến hành thu nhỏ trước, nếu có thể."
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "Hãy cân nhắc giảm hoặc chuyển đổi số lượng [plugin của WordPress](https://wordpress.org/plugins/) tải Biểu định kiểu xếp chồng (CSS) không dùng đến trong trang của bạn. Để xác định các plugin đang thêm Biểu định kiểu xếp chồng (CSS) không liên quan, hãy thử chạy [phạm vi của mã](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) trong Chrome DevTools. Bạn có thể xác định giao diện/plugin gây ra tình trạng này từ URL của biểu định kiểu. Hãy chú ý đến những plugin có nhiều biểu định kiểu trong danh sách. Những plugin này có nhiều màu đỏ trong phạm vi của mã. Một plugin chỉ nên thêm một biểu định kiểu vào hàng đợi nếu biểu định kiểu đó thực sự được sử dụng trên trang."
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "Hãy cân nhắc giảm hoặc chuyển đổi số lượng [plugin của WordPress](https://wordpress.org/plugins/) tải JavaScript không dùng đến trong trang của bạn. Để xác định các plugin đang thêm JS không liên quan, hãy thử chạy [phạm vi của mã](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) trong Chrome DevTools. Bạn có thể xác định giao diện/plugin gây ra tình trạng này từ URL của tập lệnh. Hãy chú ý đến những plugin có nhiều tập lệnh trong danh sách. Những plugin này có nhiều màu đỏ trong phạm vi của mã. Một plugin chỉ nên thêm một tập lệnh vào hàng đợi nếu tập lệnh đó thực sự được dùng trên trang."
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "Hãy đọc về [Bộ nhớ đệm của trình duyệt trong WordPress](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)."
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "Hãy cân nhắc sử dụng một [plugin tối ưu hóa hình ảnh của WordPress](https://wordpress.org/plugins/search/optimize+images/) có khả năng nén hình ảnh mà vẫn đảm bảo chất lượng."
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "Trực tiếp tải hình ảnh lên thông qua [thư viện nội dung đa phương tiện](https://codex.wordpress.org/Media_Library_Screen) để đảm bảo có các kích thước hình ảnh theo yêu cầu, sau đó chèn hình ảnh từ thư viện nội dung đa phương tiện hoặc sử dụng tiện ích hình ảnh để đảm bảo sử dụng kích thước hình ảnh tối ưu (bao gồm cả các kích thước dành cho điểm ngắt thích ứng). Tránh sử dụng hình ảnh có `Full Size` trừ khi những hình ảnh đó có kích thước phù hợp. [Tìm hiểu thêm](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)."
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "Bạn có thể bật tính năng nén văn bản trong cấu hình máy chủ web."
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "Hãy cân nhắc sử dụng một [plugin](https://wordpress.org/plugins/search/convert+webp/) hoặc dịch vụ tự động chuyển các hình ảnh đã tải lên sang định dạng tối ưu."
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-HK.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-HK.json
new file mode 100644
index 00000000000..98e16bf06c7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-HK.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "快速鍵可讓使用者快速聚焦網頁的特定部分。如要讓使用者正確瀏覽,每個快速鍵一律不可重複。[瞭解詳情](https://web.dev/accesskeys/)。"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` 的值重複"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` 值獨一無二"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "每個 ARIA「`role`」都支援一部分特定的「`aria-*`」屬性。配對錯誤會導致「`aria-*`」屬性無效。[瞭解詳情](https://web.dev/aria-allowed-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` 屬性與其角色不符"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` 屬性與其角色相符"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "部分 ARIA 角色的必要屬性會向螢幕閱讀器使用者說明元素的狀態。[瞭解詳情](https://web.dev/aria-required-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` 未具備所有必要的 `[aria-*]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` 具備所有必要的 `[aria-*]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "部分 ARIA 父角色必須包含特定的子角色,才能正確執行無障礙功能。[瞭解詳情](https://web.dev/aria-required-children/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "包含 ARIA `[role]` 且要求子元素包含特定 `[role]` 的元素缺少部分或全部的必要子元素。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "包含 ARIA `[role]` 且要求子元素包含特定 `[role]` 的元素具有全部必要的子元素。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "部分 ARIA 子角色必須包括在特定的父角色中,才能正確執行無障礙功能。[瞭解詳情](https://web.dev/aria-required-parent/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` 未包含在必要的父元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` 已包含在必要的父元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA 角色必須具備有效的值,才能執行無障礙功能。[瞭解詳情](https://web.dev/aria-roles/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` 值無效"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` 值有效"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "輔助技術 (如螢幕閱讀器) 無法解讀具有無效值的 ARIA 屬性。[瞭解詳情](https://web.dev/aria-valid-attr-value/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` 屬性並無有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "輔助技術 (例如螢幕閱讀器) 無法解讀名稱無效的 ARIA 屬性。[瞭解詳情](https://web.dev/aria-valid-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` 屬性無效或拼字錯誤"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` 屬性有效且無拼字錯誤"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "字幕可提供說話者身分、說話內容等關鍵資訊以及其他非口語資訊,方便失聰或聽障使用者使用音訊元素。[瞭解詳情](https://web.dev/audio-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` 元素缺少帶有 `[kind=\"captions\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` 元素包含帶有 `[kind=\"captions\"]` 的`<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "審核失敗的元素"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "如果按鈕沒有可存取的名稱,螢幕閱讀器只會讀出「按鈕」,導致依賴螢幕閱讀器的使用者並法使用該按鈕。[瞭解詳情](https://web.dev/button-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "按鈕沒有可存取的名稱"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "按鈕有可存取的名稱"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "為重複的內容新增略過選項,可提高鍵盤使用者的網頁瀏覽效率。[瞭解詳情](https://web.dev/bypass/)。"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "網頁中沒有標題、略過連結或地標區域"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "網頁包含標題、略過連結或地標區域"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "大部分使用者難以閱讀或無法閱讀低對比度的文字。[瞭解詳情](https://web.dev/color-contrast/)。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "背景和前景顏色沒有足夠的對比度。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "背景和前景顏色有足夠的對比度"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "如果定義清單的標記不正確,螢幕閱讀器可能會輸出令人混淆或不正確的內容。[瞭解詳情](https://web.dev/definition-list/)。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` 並非只包含排序正確的 `<dt>` 和 `<dd>` 群組、`<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` 只包含排序正確的 `<dt>` 和 `<dd>` 群組、`<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "定義清單項目 (`<dt>` 和 `<dd>`) 必須納入在父 `<dl>` 元素中,才能確保螢幕閱讀器正確朗讀這些項目。[瞭解詳情](https://web.dev/dlitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "定義清單項目未納入在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "定義清單項目已納入在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "標題可讓螢幕閱讀器使用者概略瞭解網頁內容;搜尋引擎使用者經常需要使用此資料,判斷網頁內容是否與他們的搜尋查詢有關。[瞭解詳情](https://web.dev/document-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "文件並無有效的 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "文件具備 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "ID 屬性的值不可重複,以免輔助技術忽略其他例項。[瞭解詳情](https://web.dev/duplicate-id/)。"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "網頁中的 `[id]` 屬性重複"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "網頁中的 `[id]` 屬性沒有重複"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "螢幕閱讀器使用者依賴頁框標題來瞭解頁框內容。[瞭解詳情](https://web.dev/frame-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` 或 `<iframe>` 元素沒有標題"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` 或 `<iframe>` 元素包含名稱"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "如果網頁未指定 [lang] 屬性,螢幕閱讀器會假設網頁採用使用者設定螢幕閱讀器時選擇的預設語言。如果網頁實際並非採用預設語言,螢幕閱讀器可能無法正確朗讀文字。[瞭解詳情](https://web.dev/html-has-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` 元素並無 `[lang]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` 元素具備 `[lang]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "指定有效的 [BCP 47 語言](https://www.w3.org/International/questions/qa-choosing-language-tags#question)可協助螢幕閱讀器正確朗讀文字。[瞭解詳情](https://web.dev/html-lang-valid/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` 元素的 `[lang]` 屬性並無有效的值。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` 元素的 `[lang]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "資訊型元素應提供簡短貼切的替代文字。只要將 alt 屬性留空,系統便會忽略該裝飾元素。[瞭解詳情](https://web.dev/image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "圖片元素並無 `[alt]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "圖片元素具有 `[alt]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "如果 `<input>` 按鈕是以圖片呈現,提供替代文字可協助螢幕閱讀器使用者瞭解該按鈕的用途。[瞭解詳情](https://web.dev/input-image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` 元素未設定 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` 元素具有 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "標籤可以確保輔助技術 (例如螢幕閱讀器) 正確朗讀表格控制項。[瞭解詳情](https://web.dev/label/)。"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "表格元素沒有相關聯的標籤"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "表格元素具有相關聯的標籤"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "用於版面配置的表格不應包含資料元素 (例如 th、字幕元素或摘要屬性),因為這些元素可能會對螢幕閱讀器使用者造成混淆。[瞭解詳情](https://web.dev/layout-table/)。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "展示性元素 `<table>` 使用了 `<th>`、`<caption>` 元素或 `[summary]` 屬性。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "展示性元素 `<table>` 並未使用`<th>`、`<caption>` `[summary]` 屬性。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "使用可辨別、不重複且可聚焦的連結文字 (以及連結圖片的替代文字),有助改善螢幕閱讀器使用者的瀏覽體驗。[瞭解詳情](https://web.dev/link-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "連結並無可辨別的名稱"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "連結具有可辨別的名稱"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "螢幕閱讀器會以特定方式朗讀清單。確認清單採用正確的結構有助螢幕閱讀器順利輸出內容。[瞭解詳情](https://web.dev/list/)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "清單中並非只包含 `<li>` 元素和指令碼支援元素 (`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "清單只包含 `<li>` 元素和支援指令碼的元素 (`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "清單項目 `<li>` 必須包含在父元素 `<ul>` 或 `<ol>` 中,螢幕閱讀器才能正確朗讀這些項目。[瞭解詳情](https://web.dev/listitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "清單項目 (`<li>`) 未包含在 `<ul>` 或 `<ol>` 父元素中。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "清單項目 (`<li>`) 已包含在 `<ul>` 或 `<ol>` 父元素中。"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "使用者不會預期系統自動重新整理網頁,且執行此操作會將焦點移回網頁頂端。這可能會對使用者造成困擾或混淆。[瞭解詳情](https://web.dev/meta-refresh/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "文件使用 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "文件未使用 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "停用縮放功能會對低視力人士造成困擾,他們需要透過螢幕放大功能才能清楚看見網頁內容。[瞭解詳情](https://web.dev/meta-viewport/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`<meta name=\"viewport\">` 元素中使用了 `[user-scalable=\"no\"]`,或 `[maximum-scale]` 屬性少於 5。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`<meta name=\"viewport\">` 元素中未有使用 `[user-scalable=\"no\"]` 元素,而且 `[maximum-scale]` 屬性少於 5。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "螢幕閱讀器無法翻譯非文字內容。為 `<object>` 元素新增替代文字,可協助螢幕閱讀器向使用者傳達其意義。[瞭解詳情](https://web.dev/object-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` 元素未設定 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` 元素具有 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "如果值大於 0,表示採用的是明確的瀏覽排序。雖然此做法在技術上可行,但通常會對依賴輔助技術的使用者造成困擾。[瞭解詳情](https://web.dev/tabindex/)。"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "部分元素的 `[tabindex]` 值大於 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "所有元素的 `[tabindex]` 值皆未超過 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "螢幕閱讀器的功能可讓使用者更輕鬆瀏覽表格。如能確保採用 `[headers]` 屬性的 `<td>` 儲存格只參照同一表格中的其他儲存格,或許能改善螢幕閱讀器的使用體驗。[瞭解詳情](https://web.dev/td-headers-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`<table>` 元素中採用 `[headers]` 屬性的儲存格參照了 `id`,無法在同一表格中找到此元素。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`<table>` 元素中採用 `[headers]` 屬性的儲存格,參照了同一表格中的其他儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "螢幕閱讀器的功能可讓使用者更輕鬆瀏覽表格。如能確保表格標題一律參照特定一組儲存格,或許能有助改善螢幕閱讀器使用者的體驗。[瞭解詳情](https://web.dev/th-has-data-cells/)。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` 元素及帶有 `[role=\"columnheader\"/\"rowheader\"]` 的元素沒有所描述的資料儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` 元素和帶有 `[role=\"columnheader\"/\"rowheader\"]` 的元素有其描述的資料儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "指定元素有效的[[BCP 47 語言](https://www.w3.org/International/questions/qa-choosing-language-tags#question)] 可協助螢幕閱讀器正確朗讀文字。[瞭解詳情](https://web.dev/valid-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` 屬性並無有效的值"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "如果在影片中提供字幕,將有助於失聰或聽障使用者取得影片資料。[瞭解詳情](https://web.dev/video-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` 元素不含任何帶有 `[kind=\"captions\"]``<track>` 的元素"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` 元素包含帶有 `[kind=\"captions\"]` 的`<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "音訊說明可為影片提供對話功能無法提供的相關資料,例如面部表情和場景。[瞭解詳情](https://web.dev/video-description/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` 元素不含任何帶有 `[kind=\"description\"]``<track>` 的元素"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` 元素包含帶有 `[kind=\"description\"]` 的`<track>` 元素"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "請定義 `apple-touch-icon`。這樣,當 iOS 使用者將漸進式網絡應用程式新增到主畫面時,系統才會顯示正確圖示。apple-touch-icon 必須指向大小為 192 像素 (或 180 像素) 的不透明正方形 PNG。[瞭解詳情](https://web.dev/apple-touch-icon/)。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "未提供有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` 版本過舊,建議使用 `apple-touch-icon`。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "提供有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome 擴充程式會對此頁面的載入效能產生負面影響。建議透過無痕模式或使用未安裝擴充程式的 Chrome 設定檔來審核頁面。"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "指令碼評估"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "指令碼剖析"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "CPU 總執行時間"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "建議減少剖析、編譯和執行 JS 所用的時間。傳送較小的 JS 負載可能有所幫助。[瞭解詳情](https://web.dev/bootup-time)。"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "縮短 JavaScript 執行時間"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript 執行時間"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "大型 GIF 放送動畫內容效率往往不佳。建議改用 MPEG4/WebM 格式的動畫影片和 PNG/WebP 格式的靜態圖片,以節省網絡位元組。[瞭解詳情](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "使用影片格式的動畫內容"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "建議延遲載入螢幕外的項目並隱藏圖片,直到重要資源全部載入後再開始操作,以縮短可互動時間。[瞭解詳情](https://web.dev/offscreen-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "延遲載入螢幕外圖片"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "過多資源往往會阻止系統首次繪製頁面。建議內嵌重要的 JS/CSS,延遲所有不重要的 JS/樣式。[瞭解詳情](https://web.dev/render-blocking-resources)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "排除阻止呈現的資源"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "網絡負載過大會造成使用者的費用負擔,且往往與過長載入時間息息相關。[瞭解詳情](https://web.dev/total-byte-weight)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "總大小為 {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "避免網絡負載過大"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "避免網絡負載過大"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "壓縮 CSS 檔案可減少網絡負載大小。[瞭解詳情](https://web.dev/unminified-css)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "壓縮 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "壓縮 JavaScript 檔案可減少負載大小和指令碼剖析時間。[瞭解詳情](https://web.dev/unminified-javascript)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "壓縮 Javascript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "從樣式表中移除無用的規則,並延遲載在毋需捲動的當眼位置內容中未使用的 CSS,減少網絡活動耗用不必要的位元組。[瞭解詳情](https://web.dev/unused-css-rules)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "移除未使用的 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "移除未使用的 JavaScript,以減少網絡活動耗用的位元組。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "移除未使用的 JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "延長快取期限可加快重覆瀏覽頁面的速度。[瞭解詳情](https://web.dev/uses-long-cache-ttl)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{已找到 1 項資源}other{已找到 # 項資源}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "採用有效的快取政策提供靜態資產"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "使用有效的快取政策處理靜態資產"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "優化圖片以加快載入速度,減少流動數據用量。[瞭解詳情](https://web.dev/uses-optimized-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "有效地進行圖片編碼"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "提供適當大小的圖片有助節省流動數據用量,並縮短載入時間。[瞭解詳情](https://web.dev/uses-responsive-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "適當調整圖片大小"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "文字資源應經過 (gzip、deflate 或 brotli) 壓縮,以將網絡位元總數減至最少。[瞭解詳情](https://web.dev/uses-text-compression)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "啟用文字壓縮"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000、JPEG XR 和 WebP 等圖片格式通常比 PNG 或 JPEG 有更好的壓縮效果,能夠更快完成下載及減少數據用量。[瞭解詳情](https://web.dev/uses-webp-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "提供 next-gen 格式的圖片"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "如果應用程式內容寬度與檢視區的寬度不相符,應用程式可能無法在流動裝置螢幕上呈現優化效果。[瞭解詳情](https://web.dev/content-width)。"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "檢視區大小 ({innerWidth} 像素) 與視窗大小 ({outerWidth} 像素) 不相符。"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "尚未為檢視區正確調整內容大小"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "已將檢視區正確調整內容大小"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "下方的「關鍵要求鏈結」顯示以高優先次序發佈的資源。為了提高頁面載入速度,建議您縮短鏈結長度,縮減下載資源的大小,或延遲下載不必要資源。[瞭解詳情](https://web.dev/critical-request-chains)。"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{已找到 1 個鏈結}other{已找到 # 個鏈結}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "將重要要求深度降至最低"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "淘汰/警告"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "行數"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "系統最終會從瀏覽器中移除已淘汰的 API。[瞭解詳情](https://web.dev/deprecations)。"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{發現 1 個警告}other{發現 # 個警告}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "使用已淘汰的 API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "避免使用已淘汰的 API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "應用程式快取已被淘汰。[瞭解詳情](https://web.dev/appcache-manifest)。"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "已找到「{AppCacheManifest}」"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "使用應用程式快取"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "避免使用應用程式快取"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "指定 DOCTYPE 能防止瀏覽器切換至怪異模式。[瞭解詳情](https://web.dev/doctype)。"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE 名稱必須是小寫字串 `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "文件必須包含 doctype"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId 必須為空白字串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId 必須為空白字串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "網頁缺少 HTML DOCTYPE,因此觸發了怪異模式"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "網頁含有 HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "元素"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "統計資料"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "值"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "瀏覽器工程師建議網頁包含的 DOM 元素數量應少於 1,500 個左右。理想的樹狀結構深度包含少於 32 個元素,且子/父元素少於 60 個。大型 DOM 會增加記憶體用量、延長[樣式運算](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)的時間,並產生高昂的[版面配置重排](https://developers.google.com/speed/articles/reflow)。[瞭解詳情](https://web.dev/dom-size)。"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 個元素}other{# 個元素}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "避免 DOM 過大"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "DOM 深度上限"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM 元素總數"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "子元素數量上限"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "避免 DOM 過大"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "目標"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "將 `rel=\"noopener\"` 或 `rel=\"noreferrer\"` 新增至所有外部連結,可提升效能並防範安全漏洞。[瞭解詳情](https://web.dev/external-anchors-use-rel-noopener)。"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "跨原始來源目的地的連結不安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "跨來源目的地的連結安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "無法判斷錨點的目的地 ({anchorHTML})。如果 target=_blank 不是用作連結,請考慮移除。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "如果未提供其他資訊就要求存取使用者的位置資訊,會讓使用者感到困惑而不信任網站。建議您在使用者執行特定動作時,再提出這項要求。[瞭解詳情](https://web.dev/geolocation-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "在載入網頁時要求存取使用者的地理位置"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "避免在載入網頁時要求存取使用者的地理位置"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "版本"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "在此網頁上偵測到的所有前端 JavaScript 程式庫。[瞭解詳情](https://web.dev/js-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "偵測到的 JavaScript 媒體庫"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "對於連線速度較慢的使用者,透過 `document.write()` 動態插入的外部指令碼可能會導致網頁延遲載入數十秒。[瞭解詳情](https://web.dev/no-document-write)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "使用 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "避免使用 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "嚴重程度"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "程式庫版本"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "安全漏洞數量"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "部分第三方指令碼可能包含已知的安全漏洞,攻擊者將能輕易識別及利用這些漏洞。[瞭解詳情](https://web.dev/no-vulnerable-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{偵測到 1 個安全漏洞}other{偵測到 # 個安全漏洞}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "包括前端 JavaScript 程式庫具有已知安全漏洞"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "高"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "低"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "中"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "避免使用包含已知安全漏洞的前端 JavaScript 程式庫"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "如果未提供其他資訊就要求使用者允許網站顯示通知,會讓使用者感到困惑而不信任網站。建議您在使用者操作特定手勢時,再提出這項要求。[瞭解詳情](https://web.dev/notification-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "在載入網頁時要求使用者允許網站顯示通知"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "避免在載入網頁時要求使用者允許網站顯示通知"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "審核失敗的元素"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "禁止貼上密碼會對安全政策造成不良影響。[瞭解詳情](https://web.dev/password-inputs-can-be-pasted-into)。"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "禁止使用者貼到密碼欄位"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "允許使用者貼到密碼欄位"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "通訊協定"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 具備很多 HTTP/1.1 沒有的優點,包括二進制標題、多工處理和伺服器推送。[瞭解詳情](https://web.dev/uses-http2)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{有 1 個要求未透過 HTTP/2 傳送}other{有 # 個要求未透過 HTTP/2 傳送}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "網頁要求的部分資源未使用 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "為本身的資源使用 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "建議將輕觸動作和滑鼠滾輪活動監聽器標示為 `passive`,以提升網頁的捲動效能。[瞭解詳情](https://web.dev/uses-passive-event-listeners)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "未使用被動事件監聽器來提升捲動效能"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "使用被動活動監聽器來提升捲動效能"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "說明"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "如果管理中心有錯誤記錄,表示系統仍有問題尚待解決,例如網絡要求錯誤和其他瀏覽器問題。[瞭解詳情](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "瀏覽器錯誤已記錄在控制台"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "系統未在管理中心記錄瀏覽器發生的錯誤"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "運用顯示字型的 CSS 功能,確保使用者可在網頁字型載入時看到文字。[瞭解詳情](https://web.dev/font-display)。"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "確保文字在網頁字型載入時仍然顯示"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "在網頁字型載入時,所有文字仍然顯示"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse 無法自動檢查以下網址顯示字型的值:{fontURL}。"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "實際的圖片長寬比"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "網頁上顯示的圖片長寬比"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "圖片顯示尺寸應符合正常顯示長寬比。[瞭解詳情](https://web.dev/image-aspect-ratio)。"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "顯示的圖片長寬比不正確"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "顯示的圖片長寬比正確"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "圖片大小資料無效 {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "瀏覽器可主動提示使用者,建議他們將您的應用程式新增至主畫面,藉此提高參與度[瞭解詳情](https://web.dev/installable-manifest)。"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "網絡應用程式資訊清單不符合可安裝性要求"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "網絡應用程式資訊清單符合可安裝性要求"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "不安全的網址"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "所有網站都應該使用 HTTPS 確保安全,即使網站不處理敏感資料亦然。HTTPS 能防範入侵者竄改或被動監聽應用程式與使用者之間的通訊,且 HTTP/2 和很多新的網絡平台 API 都要求使用 HTTPS。[瞭解詳情](https://web.dev/is-on-https)。"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{發現 1 個不安全的要求}other{發現 # 個不安全的要求}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "未使用 HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "使用 HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "如果網頁在流動網絡中能快速載入,可為流動裝置使用者提供良好的使用體驗。[瞭解詳情](https://web.dev/load-fast-enough-for-pwa)。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "在 {timeInMs, number, seconds} 秒開始互動"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "在 {timeInMs, number, seconds} 秒時於模擬流動網絡上開始互動"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "您的網頁載入速度太慢,無法在 10 秒內與使用者互動。請參閱「效能」部分的優化建議和診斷,瞭解如何改善載入速度。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "網頁在流動網絡中的載入速度不夠快"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "網頁在流動網絡中的載入速度夠快"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "類別"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "建議減少剖析、編譯和執行 JS 所用的時間。傳送較小的 JS 負載可能有所幫助。[瞭解詳情](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "將主要執行緒的工作減至最少"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "將主要執行緒的工作減至最少"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "為盡量觸及最多使用者,網站應能在每個主要瀏覽器上暢順運作。[瞭解詳情](https://web.dev/pwa-cross-browser)。"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "網站可以在不同瀏覽器上運作"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "確保每個網頁都可透過網址進行深層連結,且具有專屬網址,方便您在社交媒體上分享。[瞭解詳情](https://web.dev/pwa-each-page-has-url)。"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "每個網頁都有一個網址"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "即使網絡速度緩慢,只要使用者瀏覽不同網頁也能營造流暢切換的感覺。這就是為使用者帶來高效感觀的關鍵。[瞭解詳情](https://web.dev/pwa-page-transitions)。"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "使用者在切換頁面時不會覺得網絡速度緩慢"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "預計輸入延遲時間是在頁面載入視窗最忙碌的 5 秒期間,您的應用程式對使用者輸入動作的預計回應時間 (以毫秒為單位)。如果延遲超過 50 毫秒,使用者可能會認為應用程式的速度緩慢。[瞭解詳情](https://web.dev/estimated-input-latency)。"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "預計輸入延遲時間"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "「首次內容繪製時間」標示繪製首個文字/首張圖片的時間。[瞭解詳情](https://web.dev/first-contentful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "首次內容繪製時間"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "「首次 CPU 閒置時間」標示頁面的主要執行緒首次有空處理輸入的時間。[瞭解詳情](https://web.dev/first-cpu-idle)。"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "首次 CPU 閒置時間"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "「首次有效繪製時間」評估頁面主要內容顯示的時間。[瞭解詳情](https://web.dev/first-meaningful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "首次有效繪製時間"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "互動準備時間是網頁進入完整互動狀態前所花的時間。[瞭解詳情](https://web.dev/interactive)。"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "可互動所需時間"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "使用者可以體驗到最長的「首次輸入延遲時間」就是最長的工作持續時間 (以毫秒為單位)。[瞭解詳情](https://developers.google.com/web/updates/2018/05/first-input-delay)。"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "首次輸入延遲時間最長預計值"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "「速度指數」會顯示頁面內容的展現速度。[瞭解詳情](https://web.dev/speed-index)。"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "速度指數"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "當工作長度超過 50 毫秒時,所有 FCP 和「可互動所需時間」之間的時長總和 (以毫秒為單位)。"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "總封鎖時間"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "網絡來回通訊時間 (RTT) 對效能有很大影響。如果系統傳送到某個來源的來回通訊時間很高,表示靠近使用者端的伺服器可改善效能。[瞭解詳情](https://hpbn.co/primer-on-latency-and-bandwidth/)。"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "網絡來回通訊時間"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "伺服器延遲時間可能會影響網頁效能。如果來源端的伺服器延遲時間高,代表伺服器已超載或後端效能欠佳。[瞭解詳情](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)。"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "伺服器後端延遲時間"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker 可確保您的網絡應用程式運作可靠,即使網絡連線不穩定亦然。[瞭解詳情](https://web.dev/offline-start-url)。"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` 在離線時不會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` 在離線時會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse 無法從資訊清單中讀取 `start_url`,因此將 `start_url` 假設為文件的網址。錯誤訊息:「{manifestWarning}」。"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "超出預算"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "讓網絡要求的數量和大小低於使用者根據效能預算所設定的目標。[瞭解詳情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 個要求}other{# 個要求}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "效能預算"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "如果您已設定 HTTPS,請確認是否已將所有 HTTP 流量重新導向至 HTTPS,以便為所有使用者提供安全的網絡功能。[瞭解詳情](https://web.dev/redirects-http)。"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "尚未將 HTTP 流量重新導向至 HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "將 HTTP 流量重新導向至 HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "重新導向會導致頁面延遲載入。[瞭解詳情](https://web.dev/redirects)。"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "避免多次頁面重新導向"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "如要設定網頁資源的數量和大小的預算,請新增 budget.json 檔案。[瞭解詳情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 個要求 • {byteCount, number, bytes} KB}other{# 個要求 • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "降低要求數量並減少傳輸大小"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "標準連結會建議要在搜尋結果中顯示哪個網址。[瞭解詳情](https://web.dev/canonical)。"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "多個互相衝突的網址 ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "指向其他網域 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "網址無效 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "指向其他 `hreflang` 位置 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "相對網址 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "指向目標為網域的根網址 (首頁),而非相應的內容網頁"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "文件並無有效的 `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "文件具備有效的 `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "如果字型小於 12 像素,文字會太小而難以辨識,流動裝置訪客需要「兩指縮放」才能閱讀內容。網頁中應有超過 60% 採用 12 像素或以上大小的文字。[瞭解詳情](https://web.dev/font-size)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} 的文字清晰可讀"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "由於網頁沒有為流動裝置螢幕設定合適的檢視區中繼標記,因文字難以辨識。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} 的文字過小 (以 {decimalProportionVisited, number, extendedPercent} 範例為準)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "文件使用的字型大小難以辨識"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "文件使用的字型大小清晰可讀"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang 連結會通知搜尋引擎,應在特定語言或區域的搜尋結果中該顯示哪個版本的網頁。[瞭解詳情](https://web.dev/hreflang)。"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "文件並無有效的 `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "文件具備有效的 `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "如果網頁傳回失敗的 HTTP 狀態碼,可能無法正確加入索引。[瞭解詳情](https://web.dev/http-status-code)。"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "網頁傳回失敗的 HTTP 狀態碼"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "網頁傳回成功的 HTTP 狀態碼"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "如果搜尋引擎沒有檢索網頁的權限,將無法在搜尋結果中顯示您的網頁。[瞭解詳情](https://web.dev/is-crawable)。"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "網頁的索引功能被封鎖"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "網頁的索引功能未被封鎖"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "連結說明文字可協助搜尋引擎瞭解您的內容。[瞭解詳情](https://web.dev/link-text)。"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到 1 個連結}other{找到 # 個連結}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "連結並無說明文字"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "連結具有說明文字"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "執行[結構化資料測試工具](https://search.google.com/structured-data/testing-tool/)和[結構化資料 Linter](http://linter.structured-data.org/) 來驗證結構化資料。[瞭解詳情](https://web.dev/structured-data)。"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "結構化資料有效"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "您可在搜尋結果中加入中繼說明,簡要描述網頁內容。[瞭解詳情](https://web.dev/meta-description)。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "沒有說明文字。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "文件並無中繼說明"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "文件具有中繼說明"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "搜尋引擎無法為外掛程式內容加入索引,而且很多裝置對外掛程式都設有限制甚至不提供支援。[瞭解詳情](https://web.dev/plugins)。"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "文件使用外掛程式"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "文件避免使用外掛程式"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "如果您的 robots.txt 檔案格式錯誤,檢索器可能無法瞭解您偏好的網站檢索或加入索引方式。[瞭解詳情](https://web.dev/robots-txt)。"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt 要求傳回以下 HTTP 狀態:{statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{找到 1 個錯誤}other{找到 # 個錯誤}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse 無法下載 robots.txt 檔"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt 無效"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt 有效"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "按鈕和連結等互動元素的大小應至少有 48x48 像素,且周圍應保留足夠空間以便使用者輕按,同時避免與其他元素重疊的情況。[瞭解詳情](https://web.dev/tap-targets)。"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} 的輕按目標大小適中"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "由於網頁沒有為流動裝置螢幕設定合適的檢視區中繼標記,因此輕按目標太小"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "輕按目標未設定成適當大小"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "重疊的目標"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "輕按目標"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "輕按目標已設定成適當大小"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker 技術可讓您的應用程式使用多項漸進式網絡應用程式的功能,例如離線存取、新增到主畫面和推送通知。[瞭解詳情](https://web.dev/service-worker)。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "此網頁由 Service Worker 控制,但系統無法將資訊清單剖析為有效的 JSON,因此找不到任何 `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "此網頁由 Service Worker 控制,但 `start_url` ({startUrl}) 不在 Service Worker 的範圍內 ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "此網頁由 Service Worker 控制,但系統未能擷取任何資訊清單,因此找不到任何 `start_url`。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "此來源包含一個或多個 Service Worker,但該頁面 ({pageUrl}) 不在 Service Worker 的範圍內。"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "未註冊可控制網頁和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "已註冊可控制網頁和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "透過設定啟動畫面的主題,可確保使用者從主畫面啟動您的應用程式時享有優質體驗。[瞭解詳情](https://web.dev/splash-screen)。"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "未設定自訂啟動畫面"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "設有自訂啟動畫面"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "您可以將瀏覽器網址列的主題設定為與網站相符。[瞭解詳情](https://web.dev/themed-omnibox)。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "未設定網址列的主題顏色。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "設定網址列的主題顏色。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "主要執行緒封鎖時間"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "第三方"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "第三方程式碼可能會嚴重影響載入效能。請盡量減少不必要的第三方供應商,並在網頁的主要內容載入完成後,再載入第三方程式碼。[瞭解詳情](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "第三方程式碼將主要執行緒封鎖了 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "減低第三方程式碼的影響"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "第三方程式碼使用情況"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "「首個字節時間」會指出您的伺服器傳送回應的時間。[瞭解詳情](https://web.dev/time-to-first-byte)。"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "根文件回應時間為 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "縮短伺服器回應時間 (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "伺服器回應時間短 (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "時間長度"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "開始時間"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "類別"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "建議使用「用戶使用時間」檢測您的應用程式,評估其在關鍵使用者體驗期間的實際成效。[瞭解詳情](https://web.dev/user-timings)。"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 個用戶使用時間標記}other{# 個用戶使用時間標記}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "用戶使用時間標記和測量結果"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "「{securityOrigin}」有預先連線的 <link>,但瀏覽器沒有使用。請檢查您使用 `crossorigin` 屬性的方式是否正確。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "建議您新增 `preconnect` 或 `dns-prefetch` 資源提示,及早連線至重要的第三方來源。[瞭解詳情](https://web.dev/uses-rel-preconnect)。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "預先連接至必要來源"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "{preloadURL} 有預先載入的 <link>,但瀏覽器沒有使用。請檢查您使用 `crossorigin` 屬性的方式是否正確。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "建議使用 `<link rel=preload>` 來指定優先需要的網絡要求,並預先擷取資源。[瞭解詳情](https://web.dev/uses-rel-preload)。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "預先載入關鍵要求"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "新增 `<meta name=\"viewport\">` 標籤以對流動裝置螢幕優化您的應用程式。[瞭解詳情](https://web.dev/viewport)。"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "找不到任何 `<meta name=\"viewport\">` 標籤"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "缺少包括 `width` 或 `initial-scale` 的 `<meta name=\"viewport\">` 標籤"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "具備包括 `<meta name=\"viewport\">` 或 `width` 的 `initial-scale` 標籤"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "當 JavaScript 停用時,您的應用程式應該要顯示一些內容,即使只是向使用者顯示「必須啟用 JavaScript 才能使用此應用程式」這類警告訊息亦可。[瞭解詳情](https://web.dev/without-javascript)。"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "即使網頁的指令碼無法使用,網頁內文仍應顯示一些內容。"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "當 JavaScript 無法使用時不提供備用內容"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "當 JavaScript 無法使用時包含一些內容"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "如果您正在建立漸進式網絡應用程式,請考慮使用 Service Worker,以便您的應用程式離線運作。[瞭解詳情](https://web.dev/works-offline)。"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "目前的網頁在離線時不會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "目前的網頁在離線時會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "由於您的測試網址 ({requested}) 已重新導向至「{final}」,因此此頁面可能無法在離線時載入。請試著直接測試第二個網址。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "這些提示可協助改善 ARIA 在應用程式中的使用情況,進而提升輔助技術 (例如螢幕閱讀器) 使用者的體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "這些審核結果建議您為音訊和影片提供替代內容。這或許能改善聽障或視障人士的使用體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "音訊和影片"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "這些審核項目會提供常見的無障礙功能最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "這些檢查會提供[網頁應用程式無障礙功能的改善建議](https://developers.google.com/web/fundamentals/accessibility)。系統只能自動偵測一部分的無障礙功能問題,因此建議您另行手動測試。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "這些審核項目會檢查自動化測試工具未涵蓋的區域。詳情請參閱[無障礙功能審查的執行指南](https://developers.google.com/web/fundamentals/accessibility/how-to-review)。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "無障礙功能"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "這些提示有助提高內容的易讀性。"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "對比"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "您可以根據這些提示作出改善,讓其他地區的使用者更容易理解您的內容。"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "國際化和本地化"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "這些提示可協助提高應用程式中的控制項語義品質。這或許能改善輔助技術 (例如螢幕閱讀器) 的使用體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "名稱和標籤"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "這些審核結果可協助提高應用程式中的鍵盤瀏覽體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "導覽"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "這些審核結果建議您運用輔助技術 (例如螢幕閱讀器),改善表格或清單資料的閱讀體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "表格和清單"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "您可根據效能預算設定網站效能的標準。"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "預算"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "進一步瞭解應用程式效能。這些數字不會[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)「效能」分數。"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "診斷"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "評估效能的最重要指標在於像素在畫面上的呈現速度。關鍵數據:「首次內容繪製時間」、「首次有效繪製時間」"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "首次繪製改進"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "這些建議可加快網頁載入速度,但不會[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)「效能」分數。"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "優化建議"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "數據"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "改善整體載入體驗,令網頁反應更靈敏快捷,盡快可供用戶使用。關鍵數據:可互動時間、速度指數"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "整體改進"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "效能"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "這些檢查項目可驗證漸進式網絡應用程式的不同層面。[瞭解詳情](https://developers.google.com/web/progressive-web-apps/checklist)。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "這些是基本 [PWA 檢查清單](https://developers.google.com/web/progressive-web-apps/checklist)規定的檢查項目,但 Lighthouse 不會自動檢查這些項目。它們不會影響您的分數,但請務必手動驗證這些項目。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "漸進式網絡應用程式"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "運作快速,效能可靠"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "可安裝"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "已優化 PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "這些檢查可確保網頁採用已優化的搜尋引擎結果排名設定。部分其他因素不在 Lighthouse 檢查範圍內,仍可能會影響您的搜尋排名。[瞭解詳情](https://support.google.com/webmasters/answer/35769)。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "在您的網站上執行這些額外的驗證工具,以檢查其他 SEO 最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "搜尋引擎優化 (SEO)"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "請設定您的 HTML 格式,讓檢索器更能瞭解應用程式內容。"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "關於內容的最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "檢索器需要存取您的應用程式,網站才會在搜尋結果中顯示。"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "檢索和加入索引"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "請確保您的頁面適合透過流動裝置瀏覽,讓使用者無需兩指縮放或放大螢幕即可閱讀網頁內容。[瞭解詳情](https://developers.google.com/search/mobile-sites/)。"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "適合透過流動裝置瀏覽"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "快取 TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "位置"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "名稱"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "要求"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "資源類型"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "所用的時間"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "傳輸大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "網址"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "可節省的數據用量"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "可節省的數據用量"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "可節省 {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "可減少 {wastedMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "文件"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "字型"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "圖片"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "媒體"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "其他"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "指令碼"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "樣式表"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "第三方"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "總計"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "追蹤記錄網頁載入情況時發生錯誤。請重新執行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "等待「Debugger 通訊協定」初始連線時逾時。"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome 在網頁載入期間未能收集任何螢幕擷取畫面。請確認網頁上有可見內容,然後嘗試重新執行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS 伺服器無法解析您提供的網域。"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "必要的 {artifactName} 收集程式發生錯誤:{errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Chrome 發生內部錯誤。請重新啟動 Chrome,並嘗試重新執行 Lighthouse。"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "未執行必要的 {artifactName} 收集程式。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse 無法穩定載入您要求的網頁。請確認您測試的網址是否正確,以及伺服器是否正確回應所有要求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "您要求的網頁已停止回應,因此 Lighthouse 無法穩定載入該網址。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "您提供的網址並無有效的安全憑證。{securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome 使用插頁式畫面阻止系統載入網頁。請確認您測試的網址是否正確,以及伺服器是否正確回應所有要求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse 無法穩定載入您要求的網頁。請確認您測試的網址是否正確,以及伺服器是否正確回應所有要求。(詳情:{errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse 無法穩定載入您要求的網頁。請確認您測試的網址是否正確,以及伺服器是否正確回應所有要求。(狀態代碼:{statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "網頁的載入時間過長。請按照報告中的建議縮短網頁的載入時間,並嘗試重新啟動 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "等待 DevTools 通訊協定回應的時間超出系統分配上限。(方法:{protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "擷取資源內容的時間超出系統分配上限。"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "您提供的網址無效。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "顯示審核結果"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "初始導覽"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "關鍵路徑延遲時間上限:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "發生錯誤!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "報告錯誤:無審核資料"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "實驗室數據"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) 在模擬流動網絡上對目前網頁進行的分析。此為預計值,可能與實際值有所不同。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "其他手動檢查項目"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "不適用"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "優化建議"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "預計節省的時間"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "已通過的審核"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "收合片段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "展開片段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "顯示第三方資源"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "導致這次 Lighthouse 無法順利執行的問題:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "此為預計值,可能與實際值有所不同。系統[只會根據這些數據](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)計算效能分數。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "經過審核,但附有警告訊息"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "警告: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "建議將 GIF 上載至可將 GIF 用作 HTML5 影片嵌入的伺服器。"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "安裝可延遲載入所有畫面外圖片的[延遲載入 WordPress 外掛程式](https://wordpress.org/plugins/search/lazy+load/),或改用提供此功能的主題。您亦可考慮使用 [AMP 外掛程式](https://wordpress.org/plugins/amp/)。"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "部分 WordPress 外掛程式可助您[內嵌重要資產](https://wordpress.org/plugins/search/critical+css/)或[延後載入較不重要的資源](https://wordpress.org/plugins/search/defer+css+javascript/)。請注意,這些外掛程式的優化設定可能影響主題或外掛程式的功能,因此您可能需要變更程式碼。"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "主題、外掛程式和伺服器規格均會影響伺服器回應時間。建議尋找更優化的主題、謹慎選擇優化外掛程式和/或升級伺服器。"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "建議在文章清單中顯示摘錄 (例如加入更多標籤)、減少特定頁面顯示的文章數量、將較長的文章分為多個頁面,或使用可延遲載入留言的外掛程式。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "部分 [WordPress 外掛程式](https://wordpress.org/plugins/search/minify+css/) 可以透過串連、縮小及壓縮樣式來提升網站速度。可以的話,您亦可建立流程來直接進行此壓縮操作。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "部分 [WordPress 外掛程式](https://wordpress.org/plugins/search/minify+javascript/) 可透過串連、縮小及壓縮指令碼來提升網站速度。可以的話,您亦可建立流程來直接進行此壓縮操作。"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "部分 [WordPress 外掛程式](https://wordpress.org/plugins/)會在網頁中載入未使用的 CSS,建議你減少這類外掛程式的數量,或改用其他外掛程式。如要找出會新增多餘 CSS 的外掛程式,請嘗試在 Chrome DevTools 中執[程式碼覆蓋率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)。您可透過樣式表網址找出有問題的主題/外掛程式。請留意清單中包含很多樣式表,且程式碼覆蓋率中有大量紅色標示的外掛程式。外掛程式應只將網頁上實際使用的樣式表加入清單。"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "部分 [WordPress 外掛程式](https://wordpress.org/plugins/)會在網頁中載入未使用的 JavaScript,建議你減少這類外掛程式的數量,或改用其他外掛程式。如要找出會新增多餘 JS 的外掛程式,請嘗試在 Chrome DevTools 中執[程式碼覆蓋率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)。您可透過指令碼網址找出有問題的主題/外掛程式。請留意清單中包含很多指令碼,且程式碼覆蓋率中有大量紅色標示的外掛程式。外掛程式應只將網頁上實際使用的指令碼加入清單。"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "瞭解 [WordPress 的瀏覽器快取功能](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "建議使用[圖片優化 WordPress 外掛程式](https://wordpress.org/plugins/search/optimize+images/),在壓縮圖片時保持畫質。"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "您可直接透過[媒體庫](https://codex.wordpress.org/Media_Library_Screen)上載圖片,確保可使用所需的圖片大小,然後從媒體庫插入圖片,或使用圖片小工具來確保您使用優化的圖片大小 (包括回應式中斷點適用的圖片大小)。除非可用空間足夠,否則請避免使用「`Full Size`」圖片。[瞭解詳情](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "您可在網絡伺服器設定中啟用文字壓縮功能。"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "建議使用會自動將已上載圖片轉換成最佳格式的[外掛程式](https://wordpress.org/plugins/search/convert+webp/)或服務。"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-TW.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-TW.json
new file mode 100644
index 00000000000..695c0d8f5fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh-TW.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "快速鍵可讓使用者快速聚焦網頁的特定部分。要讓使用者正確瀏覽,每個快速鍵一律不得重複。[瞭解詳情](https://web.dev/accesskeys/)。"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` 的值重複"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "`[accesskey]` 的值沒有重複"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "每個 ARIA `role`都支援一部分特定的 `aria-*` 屬性。若配對錯誤,`aria-*` 屬性將失去效力。[瞭解詳情](https://web.dev/aria-allowed-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` 屬性與其角色不符"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` 屬性與其角色相符"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "部分 ARIA 角色的必要屬性會向螢幕閱讀器的使用者說明元素狀態。[瞭解詳情](https://web.dev/aria-required-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` 未具備所有必要的 `[aria-*]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` 具備所有必要的 `[aria-*]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "部分 ARIA 父項角色必須包含特定的子項角色,才能正確執行無障礙功能。[瞭解詳情](https://web.dev/aria-required-children/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "有些元素具備 ARIA `[role]` 且要求子項包含特定 `[role]`,這些元素缺少部分或全部的必要子項。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "具備 ARIA `[role]` 且要求子項包含特定 `[role]` 的元素具有全部的必要子項。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "部分 ARIA 子項角色必須包含在特定的父項角色中,才能正確執行其無障礙功能。[瞭解詳情](https://web.dev/aria-required-parent/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` 未包含在必要的父項元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` 包含在必要的父項元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA 角色必須具備有效的值,才能執行其無障礙功能。[瞭解詳情](https://web.dev/aria-roles/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` 不具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` 具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "輔助技術 (例如螢幕閱讀器) 無法解讀數值無效的 ARIA 屬性。[瞭解詳情](https://web.dev/aria-valid-attr-value/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` 屬性缺少有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "輔助技術 (例如螢幕閱讀器) 無法解讀包含無效名稱的 ARIA 屬性。[瞭解詳情](https://web.dev/aria-valid-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` 屬性無效或有錯字"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` 屬性有效且拼字正確"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "字幕可提供說話者身分、說話內容等關鍵資訊以及其他非口語資訊,方便失聰或聽障使用者使用音訊元素。[瞭解詳情](https://web.dev/audio-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` 元素缺少帶有 `[kind=\"captions\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` 元素包含帶有 `[kind=\"captions\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "未通過稽核的元素"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "如果沒有可解讀的按鈕名稱,螢幕閱讀器只會讀出「按鈕」,這樣仰賴螢幕閱讀器的使用者就無法知道這個按鈕的用途。[瞭解詳情](https://web.dev/button-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "按鈕沒有可存取的名稱"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "按鈕具有可解讀的名稱"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "針對重複的內容增設略過選項,可提高鍵盤使用者的網頁瀏覽效率。[瞭解詳情](https://web.dev/bypass/)。"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "這個網頁中沒有標題、略過連結或標記區域"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "這個網頁包含標題、略過連結或標記區域"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "低對比度的文字對許多讀者來說難以閱讀或無法閱讀。[瞭解詳情](https://web.dev/color-contrast/)。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "背景和前景顏色沒有足夠的對比度。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "背景和前景顏色具有足夠的對比度"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "如果定義清單的標記不正確,螢幕閱讀器可能會輸出令人混淆或不正確的內容。[瞭解詳情](https://web.dev/definition-list/)。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` 所含項目不只有排序正確的 `<dt>` 和 `<dd>` 群組、`<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` 所含項目只有排序正確的 `<dt>` 和 `<dd>` 群組、`<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "定義清單項目 (`<dt>` 和 `<dd>`) 必須納入在父項 `<dl>` 元素中,才能確保螢幕閱讀器正確朗讀這些項目。[瞭解詳情](https://web.dev/dlitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "定義清單項目未納入在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "定義清單項目已納入在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "標題可讓螢幕閱讀器使用者概略瞭解網頁內容;搜尋引擎使用者經常需要使用這項資訊,以判斷網頁內容是否與他們的搜尋項目有關。[瞭解詳情](https://web.dev/document-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "文件缺少 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "文件具有 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "ID 屬性的值不得重複,以免輔助技術忽略其他重複的值。[瞭解詳情](https://web.dev/duplicate-id/)。"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "網頁中的 `[id]` 屬性重複"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "網頁中的 `[id]` 屬性沒有重複"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "螢幕閱讀器需使用頁框標題才能說明頁框內容。[瞭解詳情](https://web.dev/frame-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` 或 `<iframe>` 元素缺少名稱"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` 或 `<iframe>` 元素包含名稱"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "如果網頁未指定 [lang] 屬性,螢幕閱讀器會假設網頁採用的是使用者在設定螢幕閱讀器時所選擇的預設語言。如果網頁實際採用的語言並非預設語言,那麼螢幕閱讀器可能無法正確朗讀網頁文字。[瞭解詳情](https://web.dev/html-has-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` 元素缺少 `[lang]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` 元素具備 `[lang]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "指定有效的 [BCP 47 語言](https://www.w3.org/International/questions/qa-choosing-language-tags#question),可協助螢幕閱讀器正確朗讀文字。[瞭解詳情](https://web.dev/html-lang-valid/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` 元素的 `[lang]` 屬性缺少有效的值。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` 元素的 `[lang]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "說明元素應提供簡短貼切的替代文字。如果是裝飾元素,只要將 alt 屬性留空,系統即會忽略該元素。[瞭解詳情](https://web.dev/image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "圖片元素缺少 `[alt]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "圖片元素具有 `[alt]` 屬性"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "如果 `<input>` 按鈕是以圖片呈現,提供替代文字可協助螢幕閱讀器使用者瞭解該按鈕的用途。[瞭解詳情](https://web.dev/input-image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` 元素未設定 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` 元素具有 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "標籤可確保輔助技術 (例如螢幕閱讀器) 正確朗讀表單控制項。[瞭解詳情](https://web.dev/label/)。"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "表單元素沒有相關聯的標籤"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "表單元素具有相關聯的標籤"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "用於版面配置的表格不應包含資料元素 (例如 th、字幕元素或摘要屬性),否則可能會對螢幕閱讀器使用者造成混淆。[瞭解詳情](https://web.dev/layout-table/)。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "表示性元素 `<table>` 未避免使用 `<th>`、`<caption>` 元素或 `[summary]` 屬性。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "表示性元素 `<table>` 並未使用 `<th>`、`<caption>` 或 `[summary]` 屬性。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "使用可辨別、未重複且可聚焦的連結文字 (以及連結圖片的替代文字),有助於改善螢幕閱讀器使用者的瀏覽體驗。[瞭解詳情](https://web.dev/link-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "連結缺少可辨別的名稱"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "連結具有可辨別的名稱"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "螢幕閱讀器會以特定方式朗讀清單。請務必採用正確的清單結構,這樣螢幕閱讀器才能順利讀出畫面內容。[瞭解詳情](https://web.dev/list/)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "清單中並非只包含 `<li>` 元素和指令碼支援元素 (`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "清單只包含 `<li>` 元素和指令碼支援元素 (`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "清單項目 (`<li>`) 必須包含在父項元素 `<ul>` 或 `<ol>` 中,螢幕閱讀器才能正確朗讀這些項目。[瞭解詳情](https://web.dev/listitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "清單項目 (`<li>`) 未包含在 `<ul>` 或 `<ol>` 父項元素中。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "清單項目 (`<li>`) 已包含在 `<ul>` 或 `<ol>` 父項元素中"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "使用者不會預期系統自動重新整理網頁,而且這麼做會將焦點移回網頁頂端。這可能會對使用者造成困擾或混淆。[瞭解詳情](https://web.dev/meta-refresh/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "這個文件使用 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "這個文件未使用 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "停用縮放功能會對低視能使用者造成困擾,他們需要使用螢幕放大功能才能清楚看見網頁內容。[瞭解詳情](https://web.dev/meta-viewport/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`<meta name=\"viewport\">` 元素中使用了 `[user-scalable=\"no\"]`,或是 `[maximum-scale]` 屬性小於 5。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`<meta name=\"viewport\">` 元素中未使用 `[user-scalable=\"no\"]`,而且 `[maximum-scale]` 屬性大於或等於 5。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "螢幕閱讀器無法解讀非文字內容。為 `<object>` 元素新增替代文字,可協助螢幕閱讀器向使用者傳達該元素的意義。[瞭解詳情](https://web.dev/object-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` 元素未設定 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` 元素具有 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "如果值大於 0,表示採用的是明確的瀏覽排序。雖然這在技術上可行,但經常會對仰賴輔助技術的使用者造成困擾。[瞭解詳情](https://web.dev/tabindex/)。"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "部分元素的 `[tabindex]` 值大於 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "所有元素的 `[tabindex]` 值皆未超過 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "螢幕閱讀器的功能可讓使用者輕鬆瀏覽表格。請確保使用 `[headers]` 屬性的 `<td>` 儲存格只參照同一表格中的其他儲存格,這樣可改善螢幕閱讀器的使用體驗。[瞭解詳情](https://web.dev/td-headers-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "在 `<table>` 元素中使用 `[headers]` 屬性的儲存格參照了元素 `id`,系統無法在相同表格中找到這個元素。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "在 `<table>` 元素中使用 `[headers]` 屬性的儲存格參照了同一表格中的表格儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "螢幕閱讀器的功能可讓使用者輕鬆瀏覽表格。如果能確保表格標題一律參照特定一組儲存格,或許能讓螢幕閱讀器的使用體驗更上一層樓。[瞭解詳情](https://web.dev/th-has-data-cells/)。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` 元素和具有 `[role=\"columnheader\"/\"rowheader\"]` 的元素不包含所描述的資料儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` 元素和帶有 `[role=\"columnheader\"/\"rowheader\"]` 的元素具有其所描述的資料儲存格。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "為元素指定有效的 [BCP 47 語言](https://www.w3.org/International/questions/qa-choosing-language-tags#question),可協助確保螢幕閱讀器正確朗讀文字。[瞭解詳情](https://web.dev/valid-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` 屬性缺少有效的值"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` 屬性具備有效的值"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "如果在影片中提供字幕,將有助於失聰或聽障使用者瞭解影片資訊。[瞭解詳情](https://web.dev/video-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` 元素不含任何帶有 `[kind=\"captions\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` 元素包含帶有 `[kind=\"captions\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "音訊說明可為影片提供對話功能無法提供的相關資訊,例如面部表情和場景。[瞭解詳情](https://web.dev/video-description/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` 元素不含任何帶有 `[kind=\"description\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` 元素包含帶有 `[kind=\"description\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "請定義「`apple-touch-icon`」,這樣一來,當 iOS 使用者將漸進式網頁應用程式新增到主螢幕時,系統才會顯示正確圖示。apple-touch-icon 必須指向大小為 192 像素 (或 180 像素) 的不透明正方形 PNG。[瞭解詳情](https://web.dev/apple-touch-icon/)。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "未提供有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` 版本過舊,建議使用 `apple-touch-icon`。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "具備有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome 擴充功能對這個頁面的載入效能有負面影響。建議透過無痕模式或不含擴充功能的 Chrome 設定檔來稽核頁面。"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "指令碼評估"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "指令碼剖析"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "CPU 總執行時間"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "建議你縮短剖析、編譯及執行 JavaScript 所耗費的時間。提供較小的 JavaScript 酬載可能會有幫助。[瞭解詳情](https://web.dev/bootup-time)。"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "減少 JavaScript 執行時間"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript 執行時間"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "使用大型 GIF 檔案呈現動畫內容會降低網路傳輸效率。建議你改用 MPEG4/WebM 影片格式呈現動畫內容,或是使用 PNG/WebP 格式顯示靜態圖片,以減少網路傳輸的資料量。[瞭解詳情](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "使用影片格式的動畫內容"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "建議在所有重要資源載入完成之前,延遲載入畫面外圖片和隱藏項目,以縮短互動準備時間。[瞭解詳情](https://web.dev/offscreen-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "延後載入畫面外圖片"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "網頁的資源過多,因此妨礙了首次顯示畫面的時間。建議你先載入重要的內嵌 JavaScript/CSS,並延後載入不重要的 JavaScript/樣式。[瞭解詳情](https://web.dev/render-blocking-resources)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "排除禁止轉譯的資源"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "大量的網路酬載會增加使用者的費用負擔,而且往往會延長網頁載入時間。[瞭解詳情](https://web.dev/total-byte-weight)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "總大小為 {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "避免耗用大量網路資源"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "避免耗用大量網路資源"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "壓縮 CSS 檔案能減少網路酬載大小。[瞭解詳情](https://web.dev/unminified-css)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "壓縮 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "壓縮 JavaScript 檔案能減少酬載大小,並縮短剖析指令碼的時間。[瞭解詳情](https://web.dev/unminified-javascript)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "壓縮 JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "移除樣式表中的無用規則,並延遲載入在不需捲動位置內容中未使用的 CSS,儘量避免網路活動消耗不必要的流量。[瞭解詳情](https://web.dev/unused-css-rules)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "移除未使用的 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "移除未使用的 JavaScript,減少網路活動消耗的流量。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "移除未使用的 JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "延長快取生命週期可以加快使用者再次造訪網頁的速度。[瞭解詳情](https://web.dev/uses-long-cache-ttl)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到 1 項資源}other{找到 # 項資源}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "運用有效的快取政策提供靜態資產"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "使用有效的快取政策處理靜態資產"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "經過最佳化的圖片載入速度較快,且能節省使用者的行動數據用量。[瞭解詳情](https://web.dev/uses-optimized-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "圖片編碼有效率"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "使用大小合適的圖片有助於節省行動數據用量並縮短載入時間。[瞭解詳情](https://web.dev/uses-responsive-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "使用合適的圖片大小"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "提供的文字資源應經過 (gzip、deflate 或 brotli) 壓縮,將網路傳輸的資料量降至最低。[瞭解詳情](https://web.dev/uses-text-compression)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "啟用文字壓縮"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000、JPEG XR 和 WebP 等圖片格式的壓縮效果通常優於 PNG 或 JPEG,因此能提高下載速度並節省使用者的數據用量。[瞭解詳情](https://web.dev/uses-webp-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "提供 next-gen 格式的圖片"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "如果你的應用程式內容寬度與可視區域的寬度不相符,應用程式可能無法在行動裝置螢幕上呈現最佳效果。[瞭解詳情](https://web.dev/content-width)。"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "可視區域大小 ({innerWidth} 像素) 與視窗大小 ({outerWidth} 像素) 不相符。"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "未針對可視區域正確調整內容大小"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "已針對可視區域正確調整內容大小"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "下方的「關鍵要求鏈結」顯示優先載入的資源。建議你縮短鏈結長度、降低下載資源的大小,或是將非必要資源延後載入,以提高網頁載入速度。[瞭解詳情](https://web.dev/critical-request-chains)。"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到 1 個鏈結}other{找到 # 個鏈結}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "將關鍵要求層級降至最低"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "淘汰/警告"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "行數"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "系統最終會從瀏覽器中移除已淘汰的 API。[瞭解詳情](https://web.dev/deprecations)。"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{發現 1 則警告}other{發現 # 則警告}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "使用已淘汰的 API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "避免使用已淘汰的 API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "應用程式快取已遭到淘汰。[瞭解詳情](https://web.dev/appcache-manifest)。"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "已找到「{AppCacheManifest}」"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "使用應用程式快取"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "避免使用應用程式快取"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "指定 DOCTYPE 能防止瀏覽器切換至相容模式。[瞭解詳情](https://web.dev/doctype)。"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE 名稱必須是小寫字串 `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "文件必須包含 DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId 須為空白字串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId 須為空白字串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "網頁缺少 HTML DOCTYPE,因此觸發了相容模式"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "網頁含有 HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "元素"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "統計資料"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "值"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "瀏覽器工程師建議網頁包含的 DOM 元素數量應少於 1,500 個左右。最理想的情況是樹狀結構深度包含的元素少於 32 個,且子項/父項元素少於 60 個。大型 DOM 會增加記憶體用量、延長[樣式運算](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)的時間,並產生費工的[版面配置重排](https://developers.google.com/speed/articles/reflow)。[瞭解詳情](https://web.dev/dom-size)。"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 個元素}other{# 個元素}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "避免 DOM 過大"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "DOM 層級上限"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM 元素總計"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "子元素數量上限"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "避免 DOM 過大"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "目標"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "將 `rel=\"noopener\"` 或 `rel=\"noreferrer\"` 新增至所有外部連結,可提升效能並防範安全漏洞。[瞭解詳情](https://web.dev/external-anchors-use-rel-noopener)。"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "跨原始來源目的地的連結不安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "跨來源目的地的連結很安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "無法判定錨點的目的地 ({anchorHTML})。如果 target=_blank 不是做為超連結使用,請考慮移除它。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "如果未提供其他資訊就要求存取使用者的位置資訊,會讓使用者感到困惑而不信任網站。建議你在使用者執行特定動作時,再提出這項要求。[瞭解詳情](https://web.dev/geolocation-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "在載入網頁時要求存取使用者的位置資訊"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "避免在載入網頁時要求存取使用者的位置資訊"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "版本"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "在此網頁上偵測到的所有前端 JavaScript 程式庫。[瞭解詳情](https://web.dev/js-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "偵測到 JavaScript 程式庫"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "對於連線速度較慢的使用者,透過 `document.write()` 動態置入的外部指令碼可能會導致網頁延遲數十秒載入。[瞭解詳情](https://web.dev/no-document-write)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "使用 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "避免使用 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "最高嚴重性"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "程式庫版本"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "安全漏洞數量"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "部分第三方指令碼可能包含已知的安全漏洞,攻擊者將能輕易識別及利用這些漏洞。[瞭解詳情](https://web.dev/no-vulnerable-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{偵測到 1 項安全漏洞}other{偵測到 # 項安全漏洞}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "包含的前端 JavaScript 程式庫具有已知安全漏洞"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "高"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "低"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "中"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "避免使用包含已知安全漏洞的前端 JavaScript 程式庫"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "如果未提供其他資訊就要求使用者允許網站顯示通知,會讓使用者感到困惑而不信任網站。建議你在使用者操作特定手勢時,再提出這項要求。[瞭解詳情](https://web.dev/notification-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "在載入網頁時要求使用者允許網站顯示通知"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "避免在載入網頁時要求使用者允許網站顯示通知"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "未通過稽核的元素"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "禁止貼上密碼會對安全性政策造成不良影響[瞭解詳情](https://web.dev/password-inputs-can-be-pasted-into)。"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "禁止使用者貼到密碼欄位"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "允許使用者貼到密碼欄位"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "通訊協定"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 具備許多 HTTP/1.1 沒有的優點,包括二進位標題、多工處理和伺服器推送。[瞭解詳情](https://web.dev/uses-http2)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{有 1 項要求未透過 HTTP/2 傳送}other{有 # 項要求未透過 HTTP/2 傳送}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "網頁要求的部分資源未使用 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "針對本身的資源使用 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "建議將輕觸動作和滑鼠滾輪事件監聽器標示為 `passive`,以提升網頁的捲動效能。[瞭解詳情](https://web.dev/uses-passive-event-listeners)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "未使用被動事件監聽器來提升捲動效能"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "使用被動事件監聽器來提升捲動效能"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "說明"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "如果主控台有錯誤記錄,表示系統有問題尚待解決,例如網路要求錯誤和其他瀏覽器問題。[瞭解詳情](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "主控台已記錄瀏覽器發生的錯誤"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "系統未在主控台中記錄瀏覽器發生的錯誤"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "運用顯示字型的 CSS 功能,確保使用者可以在網站字型載入期間看到文字。[瞭解詳情](https://web.dev/font-display)。"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "確認載入網站字型時文字不會消失"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "載入網站字型時沒有任何文字消失"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse 無法自動檢查以下網址顯示字型的值:{fontURL}"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "實際顯示比例"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "網頁上顯示的圖片比例"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "圖片顯示尺寸應符合正常顯示比例。[瞭解詳情](https://web.dev/image-aspect-ratio)。"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "圖片的顯示比例不正確"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "圖片的顯示比例正確"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "圖片大小資訊無效 ({url})"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "瀏覽器可以主動提示使用者,建議他們將你的應用程式新增到主螢幕,藉此提高參與度。[瞭解詳情](https://web.dev/installable-manifest)。"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "網頁應用程式資訊清單不符合安裝規定"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "網頁應用程式資訊清單符合安裝規定"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "不安全的網址"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "所有網站都應該使用 HTTPS 確保安全,即使網站未處理機密資料也一樣。HTTPS 能防範入侵者竄改或被動監聽應用程式與使用者之間的通訊,且 HTTP/2 和許多新的網路平台 API 都要求使用 HTTPS。[瞭解詳情](https://web.dev/is-on-https)。"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{發現 1 個不安全的要求}other{發現 # 個不安全的要求}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "未使用 HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "使用 HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "如果網頁能透過行動網路快速載入,就可確保行動裝置使用者獲得良好的使用體驗。[瞭解詳情](https://web.dev/load-fast-enough-for-pwa)。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "在 {timeInMs, number, seconds} 秒開始互動"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "在 {timeInMs, number, seconds} 秒於模擬行動網路上開始互動"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "你的網頁載入速度太慢,無法在 10 秒內與使用者互動。請參閱「效能」部分的最佳化建議與診斷報告,瞭解如何改善載入速度。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "網頁在行動網路中的載入速度不夠快"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "網頁在行動網路中的載入速度夠快"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "類別"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "建議你縮短剖析、編譯及執行 JavaScript 所耗費的時間。提供較小的 JavaScript 酬載可能會有幫助。[瞭解詳情](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "將主要執行緒的工作降到最低"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "將主要執行緒的工作降到最低"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "為觸及大多數使用者,網站應在每個主要瀏覽器上運作。[瞭解詳情](https://web.dev/pwa-cross-browser)。"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "網站可以在不同瀏覽器上運作"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "可確保每個網頁都能透過網址進行深層連結,而且具有專屬網址,方便你在社交媒體上分享。[瞭解詳情](https://web.dev/pwa-each-page-has-url)。"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "每個網頁都有一個網址"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "即使網路速度緩慢,當使用者輕觸不同網頁也應該要能流暢切換,這是展現效能的重要關鍵。[瞭解詳情](https://web.dev/pwa-page-transitions)。"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "使用者在切換頁面時不會覺得網路速度緩慢"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "預估輸入延遲時間是指在頁面載入作業最忙碌的 5 秒中,應用程式對於使用者輸入動作的預估回應時間 (以毫秒為單位)。如果延遲時間超過 50 毫秒,使用者可能會覺得應用程式的速度很慢。[瞭解詳情](https://web.dev/estimated-input-latency)。"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "預估輸入延遲"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "首次顯示內容所需時間是指瀏覽器首次顯示文字或圖片的時間。[瞭解詳情](https://web.dev/first-contentful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "首次內容繪製"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "首次 CPU 閒置時間是指網頁的主要執行緒已不再忙碌,且有能力處理輸入內容的最早時間。[瞭解詳情](https://web.dev/first-cpu-idle)。"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "首次 CPU 閒置"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "畫面首次有效顯示所需時間是指網頁顯示主要內容的時間。[瞭解詳情](https://web.dev/first-meaningful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "首次有效繪製"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "互動準備時間是網頁進入完整互動狀態前花費的時間。[瞭解詳情](https://web.dev/interactive)。"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "可互動時間"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "使用者可能要等待的最長「首次輸入延遲時間」就是耗時最久的工作所需要的處理時間 (以毫秒為單位)。[瞭解詳情](https://developers.google.com/web/updates/2018/05/first-input-delay)。"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "首次輸入延遲時間最長預估值"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "速度指數會顯示網頁可見內容的填入速度。[瞭解詳情](https://web.dev/speed-index)。"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "速度指數"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "當工作長度超過 50 毫秒時,從 FCP 到互動準備時間的時間範圍總計 (以毫秒為單位)。"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "封鎖時間總計"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "網路封包往返時間 (RTT) 對效能有很大的影響。如果將封包傳送到某個來源的 RTT 很高,表示靠近使用者端的伺服器在效能方面有改善空間。[瞭解詳情](https://hpbn.co/primer-on-latency-and-bandwidth/)。"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "網路封包往返時間"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "伺服器延遲時間可能會影響網站效能。如果原始伺服器的延遲時間很高,表示伺服器有超載情形或後端效能不佳。[瞭解詳情](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)。"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "伺服器後端延遲時間"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker 可讓你的網路應用程式即使在連線不穩定時依然維持正常運作。[瞭解詳情](https://web.dev/offline-start-url)。"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` 在離線時不會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` 在離線時會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse 無法從資訊清單中讀取 `start_url`,因此將 `start_url` 假設為文件的網址。錯誤訊息:「{manifestWarning}」。"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "超過預算"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "讓網路要求的數量和大小低於使用者根據效能預算所設定的目標。[瞭解詳情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 個要求}other{# 個要求}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "效能預算"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "如果你已設定 HTTPS,請確認是否已將所有 HTTP 流量都重新導向至 HTTPS,以便為所有使用者提供安全的網路功能。[瞭解詳情](https://web.dev/redirects-http)。"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "未將 HTTP 流量重新導向至 HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "將 HTTP 流量重新導向至 HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "重新導向會導致頁面延遲載入。[瞭解詳情](https://web.dev/redirects)。"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "避免進行多次頁面重新導向"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "如要針對網頁資源的數量和大小設定預算,請新增 budget.json 檔案。[瞭解詳情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 個要求 • {byteCount, number, bytes} KB}other{# 個要求 • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "降低要求數量並減少傳輸大小"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "標準連結可指出要在搜尋結果中顯示哪個網址。[瞭解詳情](https://web.dev/canonical)。"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "多個衝突的網址 ({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "指向其他網域 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "網址無效 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "指向其他 `hreflang` 位置 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "相對網址 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "指向目標為網域的根網址 (首頁),而不是相應的內容網頁"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "文件缺少有效的 `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "文件具備有效的 `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "如果字型小於 12 像素,文字會太小而難以辨識;行動裝置訪客必須「以雙指撥動縮放」才能閱讀內容。網頁中應有超過 60% 的文字採用 12 像素以上的大小。[瞭解詳情](https://web.dev/font-size)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} 的文字清晰易讀"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "文字難以辨識,這是因為網頁沒有針對行動裝置螢幕設定合適的可視區域中繼標記。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} 的文字過小 (根據 {decimalProportionVisited, number, extendedPercent} 的取樣結果)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "文件使用的字型大小難以辨識"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "文件使用的字型大小清晰易讀"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang 連結會告訴搜尋引擎在特定語言或區域的搜尋結果中應顯示哪種版本的網頁。[瞭解詳情](https://web.dev/hreflang)。"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "文件缺少有效的 `hreflang`"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "文件具備有效的 `hreflang`"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "如果網頁傳回失敗的 HTTP 狀態碼,可能無法正確編入索引。[瞭解詳情](https://web.dev/http-status-code)。"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "網頁傳回失敗的 HTTP 狀態碼"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "網頁傳回成功的 HTTP 狀態碼"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "如果搜尋引擎沒有檢索網頁的權限,將無法在搜尋結果中顯示你的網頁。[瞭解詳情](https://web.dev/is-crawable)。"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "網頁的索引功能遭到封鎖"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "網頁的索引功能未遭到封鎖"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "連結說明文字可協助搜尋引擎瞭解你的內容。[瞭解詳情](https://web.dev/link-text)。"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到 1 個連結}other{找到 # 個連結}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "連結缺少說明文字"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "連結具有說明文字"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "執行[結構化資料測試工具](https://search.google.com/structured-data/testing-tool/)和 [Structured Data Linter](http://linter.structured-data.org/) 來驗證結構化資料。[瞭解詳情](https://web.dev/structured-data)。"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "結構化資料有效"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "你可以在搜尋結果中加入中繼說明,簡要描述網頁內容。[瞭解詳情](https://web.dev/meta-description)。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "沒有說明文字。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "文件缺少中繼說明"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "文件具有中繼說明"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "搜尋引擎無法為外掛程式內容建立索引,而且許多裝置對外掛程式設有限制或不提供支援。[瞭解詳情](https://web.dev/plugins)。"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "文件使用外掛程式"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "文件盡量不使用外掛程式"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "如果你的 robots.txt 檔案格式錯誤,檢索器可能無法瞭解你偏好的網站檢索方式或索引建立方式。[瞭解詳情](https://web.dev/robots-txt)。"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "robots.txt 要求傳回以下 HTTP 狀態:{statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{發現 1 項錯誤}other{發現 # 項錯誤}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse 無法下載 robots.txt 檔"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt 無效"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt 有效"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "按鈕和連結等互動元素的大小應至少有 48x48 像素,且周圍應保留足夠空間,讓使用者能輕鬆點選,同時避免與其他元素重疊的情況。[瞭解詳情](https://web.dev/tap-targets)。"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} 的輕觸目標大小適中"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "輕觸目標太小,這是因為網頁沒有針對行動裝置螢幕設定合適的可視區域中繼標記"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "輕觸目標未設定成適當大小"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "重疊的目標"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "輕觸目標"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "輕觸目標已設定成適當大小"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker 技術可讓你的應用程式使用許多漸進式網頁應用程式的功能,例如離線存取、新增到主螢幕,以及推播通知。[瞭解詳情](https://web.dev/service-worker)。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "此網頁由 Service Worker 所控管,但系統無法將資訊清單剖析為有效的 JSON,因此找不到任何 `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "這個網頁由 Service Worker 所控管,但是 `start_url` ({startUrl}) 不在 Service Worker 的範圍內 ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "這個網頁由 Service Worker 所控管,但系統未擷取任何資訊清單,因此找不到任何 `start_url`。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "此來源包含一個或多個 Service Worker,但該頁面 ({pageUrl}) 不在 Service Worker 的範圍內。"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "未註冊可控管網頁和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "已註冊可控管網頁和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "透過設定啟動畫面的主題,可確保使用者從主螢幕啟動你的應用程式時享有優質體驗。[瞭解詳情](https://web.dev/splash-screen)。"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "未設定自訂啟動畫面"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "設有自訂啟動畫面"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "你可以將瀏覽器網址列的主題設定為與網站相符。[瞭解詳情](https://web.dev/themed-omnibox)。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "尚未設定網址列的主題顏色。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "設定網址列的主題顏色。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "主要執行緒封鎖時間"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "第三方"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "第三方程式碼可能會嚴重影響載入效能。請儘量減少不必要的第三方供應商,並在網頁的主要內容載入完畢後,再載入第三方程式碼。[瞭解詳情](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "第三方程式碼將主要執行緒封鎖了 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "降低第三方程式碼的影響"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "第三方程式碼使用情形"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "第一個位元組時間會指出你的伺服器傳送回應的時間。[瞭解詳情](https://web.dev/time-to-first-byte)。"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "根文件回應時間為 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "減少伺服器回應時間 (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "伺服器回應時間低 (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "時間長度"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "開始時間"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "類型"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "建議你使用 User Timing API 評估應用程式在關鍵使用者體驗期間的實際效能。[瞭解詳情](https://web.dev/user-timings)。"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 個 User Timing 標記}other{# 個 User Timing 標記}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing 標記和測量結果"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "「{securityOrigin}」有預先連線的 <link>,但未獲瀏覽器使用。請檢查你使用 `crossorigin` 屬性的方式是否正確。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "建議你新增 `preconnect` 或 `dns-prefetch` 資源提示,及早連線至重要的第三方來源。[瞭解詳情](https://web.dev/uses-rel-preconnect)。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "預先連上必要來源"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "「{preloadURL}」有預先載入的 <link>,但未獲瀏覽器使用。請檢查你使用 `crossorigin` 屬性的方式是否正確。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "建議使用 `<link rel=preload>` 優先擷取目前在網頁載入時較晚要求的資源。[瞭解詳情](https://web.dev/uses-rel-preload)。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "預先載入重要要求"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "如要配合行動裝置螢幕將你的應用程式進行最佳化調整,請新增 `<meta name=\"viewport\">` 標記。[瞭解詳情](https://web.dev/viewport)。"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "找不到任何 `<meta name=\"viewport\">` 標記"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "缺少包含 `width` 或 `initial-scale` 的 `<meta name=\"viewport\">` 標記"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "具備包含 `width` 或 `initial-scale` 的 `<meta name=\"viewport\">` 標記"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "當 JavaScript 停用時,你的應用程式應該要顯示一些內容,即使只是向使用者顯示「必須啟用 JavaScript 才能使用此應用程式」這類警告訊息也可以。[瞭解詳情](https://web.dev/without-javascript)。"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "即使網頁的指令碼無法使用,網頁內文仍應顯示一些內容。"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "當 JavaScript 無法使用時不提供備用內容"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "當 JavaScript 無法使用時包含一些內容"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "如果你正在建構漸進式網頁應用程式,請考慮使用 Service Worker,讓你的應用程式可以離線運作。[瞭解詳情](https://web.dev/works-offline)。"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "目前的網頁在離線時不會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "目前的網頁在離線時會傳回狀態碼 200 的回應"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "由於你的測試網址 ({requested}) 重新導向到「{final}」,因此這個頁面可能無法在離線時載入。請試著直接測試第二個網址。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "這些稽核建議可協助改善 ARIA 在應用程式中的使用情形,進而讓輔助技術 (例如螢幕閱讀器) 的使用體驗更上一層樓。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "你可以根據這些資訊判斷是否要提供用來替代音訊和影片的內容。這或許能改善聽障或視障人士的使用體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "音訊和影片"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "這些稽核項目會提供常見的無障礙功能最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "這些檢查會清楚說明[網頁應用程式無障礙功能的改善建議](https://developers.google.com/web/fundamentals/accessibility),但系統只能自動偵測一部分的無障礙功能問題,因此建議你另外進行手動測試。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "這些稽核項目會檢查自動化測試工具未涵蓋的區域。詳情請參閱[無障礙功能審查的執行指南](https://developers.google.com/web/fundamentals/accessibility/how-to-review)。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "無障礙功能"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "這些稽核建議有助於提高內容的易讀性。"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "對比"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "你可以根據這些稽核建議做出改善,讓其他地區的使用者更容易理解你的內容。"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "國際化和本地化"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "這些稽核建議可協助提高應用程式中的控制項語義品質。這或許能改善輔助技術 (例如螢幕閱讀器) 的使用體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "名稱和標籤"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "你可以根據這些資訊來改善應用程式的鍵盤瀏覽操作方式。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "瀏覽"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "這些稽核結果建議你運用輔助技術 (例如螢幕閱讀器),改善表格或清單資料的閱讀體驗。"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "表格和清單"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "你可以根據效能預算設定網站效能的標準。"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "預算"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "進一步瞭解應用程式的效能。這些數字不會[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)「效能」分數。"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "診斷"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "像素呈現在畫面上的速度是最重要的效能層面。重要指標:首次內容繪製、首次有效繪製"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "改進首次繪製程序"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "這些建議有助於提升網頁載入速度,但不會[直接影響](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)「效能」分數。"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "最佳化建議"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "指標"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "改進整體載入體驗,採用回應式頁面設計,儘快為使用者提供服務。重要指標:可互動時間、速度指數"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "整體改進"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "效能"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "這些檢查項目可驗證漸進式網頁應用程式的不同層面。[瞭解詳情](https://developers.google.com/web/progressive-web-apps/checklist)。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "這些是基本 [PWA 檢查清單](https://developers.google.com/web/progressive-web-apps/checklist)規定的項目,但 Lighthouse 不會自動進行檢查。它們不會影響你的分數,但請務必手動驗證這些項目。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "漸進式網頁應用程式"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "快速穩定"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "可安裝"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "PWA 最佳化"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "這些檢查可確保你的網頁採用的是最佳的搜尋引擎結果排名設定。有一些其他因素不在 Lighthouse 檢查範圍內,仍可能會影響你的搜尋排名。[瞭解詳情](https://support.google.com/webmasters/answer/35769)。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "在您的網站上執行這些額外的驗證工具,以檢查其他 SEO 最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "搜尋引擎最佳化 (SEO)"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "請設定適當的 HTML 格式,讓檢索器更容易辨識你的應用程式內容。"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "內容最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "檢索器需要存取你的應用程式,才能將網站顯示在搜尋結果中。"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "檢索及建立索引"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "請確認你的網頁適合透過行動裝置瀏覽,使用者不須撥動雙指或縮放螢幕即可閱讀網頁內容。[瞭解詳情](https://developers.google.com/search/mobile-sites/)。"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "適合透過行動裝置瀏覽"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "快取 TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "位置"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "名稱"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "要求"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "資源類型"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "花費的時間"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "傳輸大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "網址"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "可節省的數據用量"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "可節省的時間"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "可減少 {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "可減少 {wastedMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "文件"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "字型"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "圖片"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "媒體"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "其他"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "指令碼"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "樣式表"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "第三方"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "總計"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "追蹤記錄網頁載入情形時發生錯誤。請重新執行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "等候偵錯工具通訊協定初始連線時發生逾時。"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome 在網頁載入期間未能擷取螢幕畫面。請確認網頁上有可見內容,然後嘗試重新執行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS 伺服器無法解析你提供的網域。"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "必要的 {artifactName} 收集程式發生錯誤:{errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "Chrome 發生內部錯誤。請重新啟動 Chrome,並嘗試重新執行 Lighthouse。"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "未執行必要的 {artifactName} 收集程式。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse 無法穩定載入你要求的網頁。請確認你測試的網址是否正確,以及伺服器是否正確回應所有要求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "你要求的網頁已停止回應,因此 Lighthouse 無法穩定載入該網址。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "你所提供的網址缺少有效的安全性憑證。{securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome 使用插頁式畫面阻止系統載入網頁。請確認你的測試網址是否正確,以及伺服器是否正確回應所有要求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse 無法穩定載入你要求的網頁。請確認你的測試網址是否正確,以及伺服器是否正確回應所有要求。(詳細資訊:{errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse 無法穩定載入你要求的網頁。請確認你的測試網址是否正確,以及伺服器是否正確回應所有要求。(狀態碼:{statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "網頁載入時間過長。請按照報告中的建議做法縮短網頁載入時間,然後嘗試重新執行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "等待 DevTools 通訊協定回應的時間超出系統分配上限。(方法:{protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "擷取資源內容的時間超出系統分配上限。"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "你所提供的網址無效。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "顯示稽核結果"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "起始導覽"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "關鍵路徑延遲時間上限:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "發生錯誤!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "回報錯誤:無稽核資訊"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "研究資料"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) 在模擬行動網路上對目前網頁進行的分析。此為預估值,可能與實際情況有所不同。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "其他手動檢查項目"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "不適用"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "最佳化建議"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "預估減少量"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "通過稽核項目"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "收合程式碼片段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "展開程式碼片段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "顯示第三方資源"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "有問題導致 Lighthouse 無法順利執行這項作業:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "此為預估值,可能與實際情況有所出入。系統[只會根據這些指標](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)計算效能分數。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "通過稽核,但附有警告訊息"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "警告: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "建議你將 GIF 上傳到可將 GIF 做為 HTML5 影片嵌入的服務。"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "安裝可延遲載入所有畫面外圖片的[延遲載入 WordPress 外掛程式](https://wordpress.org/plugins/search/lazy+load/),或改用提供這項功能的主題。你也可以考慮使用 [AMP 外掛程式](https://wordpress.org/plugins/amp/)。"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "有些 WordPress 外掛程式能協助你[內嵌重要的素材資源](https://wordpress.org/plugins/search/critical+css/)或[延後載入較不重要的資源](https://wordpress.org/plugins/search/defer+css+javascript/)。請注意,這些外掛程式的最佳化設定可能會對現有主題或外掛程式的功能有不良影響,因此你可能需要變更程式碼。"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "主題、外掛程式和伺服器規格都會影響伺服器回應時間。建議你尋找經過最佳化調整的主題、謹慎選擇最佳化外掛程式,並 (或) 升級伺服器。"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "建議你在文章清單中顯示摘錄 (例如加入更多標記)、減少特定頁面顯示的文章數量、將較長的文章分為多個頁面,或使用可延遲載入留言的外掛程式。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "有些 [WordPress 外掛程式](https://wordpress.org/plugins/search/minify+css/) 可以透過串連、縮小及壓縮樣式來提升網站速度。你也可以透過建構流程直接執行這項壓縮作業 (如果可行的話)。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "有些 [WordPress 外掛程式](https://wordpress.org/plugins/search/minify+javascript/) 可以透過串連、縮小及壓縮指令碼來提升網站速度。你也可以透過建構流程直接執行這項壓縮作業 (如果可行的話)。"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "有些 [WordPress 外掛程式](https://wordpress.org/plugins/)會在網頁中載入未使用的 CSS,建議你減少這類外掛程式的數量,或改用其他外掛程式。如要找出會新增多餘 CSS 的外掛程式,請嘗試在 Chrome DevTools 中執行[程式碼涵蓋率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)功能。你可以透過樣式表網址找出有問題的主題/外掛程式。請留意在清單中包含許多樣式表,且程式碼涵蓋率中有許多紅色標示的外掛程式。外掛程式只應將網頁上實際使用的樣式表加入清單。"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "有些 [WordPress 外掛程式](https://wordpress.org/plugins/)會在網頁中載入未使用的 JavaScript,建議你減少這類外掛程式的數量,或改用其他外掛程式。如要找出會新增多餘 JavaScript 的外掛程式,請嘗試在 Chrome DevTools 中執行[程式碼涵蓋率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)功能。你可以透過指令碼網址找出有問題的主題/外掛程式。請留意在清單中包含許多指令碼,且程式碼涵蓋率中有許多紅色標示的外掛程式。外掛程式只應將網頁實際使用的指令碼加入佇列。"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "瞭解 [WordPress 的瀏覽器快取功能](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "建議你使用壓縮圖片時不會影響到畫質的[圖片最佳化 WordPress 外掛程式](https://wordpress.org/plugins/search/optimize+images/)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "你可以直接透過[媒體庫](https://codex.wordpress.org/Media_Library_Screen)上傳圖片,確保你可以使用所需的圖片大小,然後透過從媒體庫插入圖片,或使用圖片小工具來確保你使用的是最佳圖片大小 (包括回應式中斷點適用的圖片大小)。除非圖片尺寸符合使用目的,否則請避免使用`Full Size`圖片。[瞭解詳情](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "你可以在網路伺服器設定中啟用文字壓縮功能。"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "建議你使用會自動將已上傳圖片轉換成最佳格式的[外掛程式](https://wordpress.org/plugins/search/convert+webp/)或服務。"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh.json b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh.json
new file mode 100644
index 00000000000..2070a9e5bcc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits_worker/lighthouse/locales/zh.json
@@ -0,0 +1,1541 @@
+{
+ "lighthouse-core/audits/accessibility/accesskeys.js | description": {
+ "message": "快捷键可让用户快速转到页面的某个部分。为确保正确进行导航,每个快捷键都必须是独一无二的。[了解详情](https://web.dev/accesskeys/)。"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | failureTitle": {
+ "message": "`[accesskey]` 的值重复"
+ },
+ "lighthouse-core/audits/accessibility/accesskeys.js | title": {
+ "message": "“`[accesskey]`”值是独一无二的"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | description": {
+ "message": "每个 ARIA“`role`”都支持一部分特定的“`aria-*`”属性。如果这些项不匹配,会导致“`aria-*`”属性无效。[了解详情](https://web.dev/aria-allowed-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | failureTitle": {
+ "message": "`[aria-*]` 属性与其角色不匹配"
+ },
+ "lighthouse-core/audits/accessibility/aria-allowed-attr.js | title": {
+ "message": "`[aria-*]` 属性与其角色匹配"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | description": {
+ "message": "一些 ARIA 角色有必需属性,这些属性向屏幕阅读器描述了相应元素的状态。[了解详情](https://web.dev/aria-required-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | failureTitle": {
+ "message": "`[role]` 缺少部分必需的 `[aria-*]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-attr.js | title": {
+ "message": "`[role]` 具备所有必需的 `[aria-*]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | description": {
+ "message": "一些 ARIA 父角色必须包含特定子角色,才能执行它们的预期无障碍功能。[了解详情](https://web.dev/aria-required-children/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | failureTitle": {
+ "message": "具有 ARIA `[role]`且要求子元素必须包含特定`[role]`的元素缺少部分或全部必需子元素。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-children.js | title": {
+ "message": "具有 ARIA `[role]`且要求子元素必须包含特定`[role]`的元素包含全部必需子元素。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | description": {
+ "message": "一些 ARIA 子角色必须包含在特定的父角色中,才能正确执行它们的预期无障碍功能。[了解详情](https://web.dev/aria-required-parent/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | failureTitle": {
+ "message": "`[role]` 未包含在其必需的父元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-required-parent.js | title": {
+ "message": "`[role]` 包含在其必需的父元素中"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | description": {
+ "message": "ARIA 角色必须具备有效值,才能执行它们的预期无障碍功能。[了解详情](https://web.dev/aria-roles/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | failureTitle": {
+ "message": "`[role]` 值无效"
+ },
+ "lighthouse-core/audits/accessibility/aria-roles.js | title": {
+ "message": "`[role]` 值有效"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | description": {
+ "message": "辅助技术(如屏幕阅读器)无法解读值无效的 ARIA 属性。[了解详情](https://web.dev/aria-valid-attr-value/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | failureTitle": {
+ "message": "`[aria-*]` 属性缺少有效值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr-value.js | title": {
+ "message": "`[aria-*]` 属性具备有效值"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | description": {
+ "message": "辅助技术(如屏幕阅读器)无法解读名称无效的 ARIA 属性。[了解详情](https://web.dev/aria-valid-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | failureTitle": {
+ "message": "`[aria-*]` 属性无效或拼写有误"
+ },
+ "lighthouse-core/audits/accessibility/aria-valid-attr.js | title": {
+ "message": "`[aria-*]` 属性有效且拼写正确"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | description": {
+ "message": "字幕让失聪用户或听障用户能够使用音频元素,并可提供关键信息(例如谁在说话、他们在说什么以及其他非语音信息)。[了解详情](https://web.dev/audio-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | failureTitle": {
+ "message": "`<audio>` 元素缺少含 `[kind=\"captions\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/audio-caption.js | title": {
+ "message": "`<audio>` 元素包含带 `[kind=\"captions\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/axe-audit.js | failingElementsHeader": {
+ "message": "未通过审核的元素"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | description": {
+ "message": "当某个按钮没有可供访问的名称时,屏幕阅读器会将它读为“按钮”,这会导致依赖屏幕阅读器的用户无法使用它。[了解详情](https://web.dev/button-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | failureTitle": {
+ "message": "按钮缺少可供访问的名称"
+ },
+ "lighthouse-core/audits/accessibility/button-name.js | title": {
+ "message": "按钮有可供访问的名称"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | description": {
+ "message": "添加用于绕过重复内容的方式有助于键盘用户更高效地浏览页面。[了解详情](https://web.dev/bypass/)。"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | failureTitle": {
+ "message": "该页面不含任何标题、跳过链接或地标区域"
+ },
+ "lighthouse-core/audits/accessibility/bypass.js | title": {
+ "message": "该页面包含一个标题、跳过链接或地标区域"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | description": {
+ "message": "对于许多用户而言,对比度低的文字都是难以阅读或无法阅读的。[了解详情](https://web.dev/color-contrast/)。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | failureTitle": {
+ "message": "背景色和前景色没有足够高的对比度。"
+ },
+ "lighthouse-core/audits/accessibility/color-contrast.js | title": {
+ "message": "背景色和前景色具有足够高的对比度"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | description": {
+ "message": "如果未正确标记定义列表,屏幕阅读器可能会读出令人困惑或不准确的内容。[了解详情](https://web.dev/definition-list/)。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | failureTitle": {
+ "message": "`<dl>` 并非只包含经过适当排序的 `<dt>` 和 `<dd>` 组及 `<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/definition-list.js | title": {
+ "message": "`<dl>` 只包含经过适当排序的 `<dt>` 和 `<dd>` 组及 `<script>` 或 `<template>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | description": {
+ "message": "定义列表项 (`<dt>` 和 `<dd>`) 必须封装在父 `<dl>` 元素中,以确保屏幕阅读器可以正确地读出它们。[了解详情](https://web.dev/dlitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | failureTitle": {
+ "message": "定义列表项已封装在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/dlitem.js | title": {
+ "message": "定义列表项已封装在 `<dl>` 元素中"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | description": {
+ "message": "屏幕阅读器用户可借助标题来大致了解某个页面的内容,搜索引擎用户则非常依赖标题来确定某个页面是否与其搜索相关。[了解详情](https://web.dev/document-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | failureTitle": {
+ "message": "文档不含 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/document-title.js | title": {
+ "message": "文档包含 `<title>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | description": {
+ "message": "id 属性的值必须独一无二,以防其他实例被辅助技术忽略。[了解详情](https://web.dev/duplicate-id/)。"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | failureTitle": {
+ "message": "页面上的 `[id]` 属性不是独一无二的"
+ },
+ "lighthouse-core/audits/accessibility/duplicate-id.js | title": {
+ "message": "页面上的 `[id]` 属性是独一无二的"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | description": {
+ "message": "屏幕阅读器用户依靠框架标题来描述框架的内容。[了解详情](https://web.dev/frame-title/)。"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | failureTitle": {
+ "message": "`<frame>` 或 `<iframe>` 元素缺少标题"
+ },
+ "lighthouse-core/audits/accessibility/frame-title.js | title": {
+ "message": "`<frame>` 或 `<iframe>` 元素有标题"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | description": {
+ "message": "如果页面未指定 lang 属性,屏幕阅读器便会假定该页面采用的是用户在设置屏幕阅读器时选择的默认语言。如果该页面实际上并未采用默认语言,则屏幕阅读器可能无法正确读出该页面中的文字。[了解详情](https://web.dev/html-has-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | failureTitle": {
+ "message": "`<html>` 元素缺少 `[lang]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/html-has-lang.js | title": {
+ "message": "`<html>` 元素包含 `[lang]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | description": {
+ "message": "指定有效的 [BCP 47 语言](https://www.w3.org/International/questions/qa-choosing-language-tags#question)有助于屏幕阅读器正确读出文字。[了解详情](https://web.dev/html-lang-valid/)。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | failureTitle": {
+ "message": "`<html>` 元素的 `[lang]` 属性缺少有效值。"
+ },
+ "lighthouse-core/audits/accessibility/html-lang-valid.js | title": {
+ "message": "`<html>` 元素的 `[lang]` 属性具备有效值"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | description": {
+ "message": "说明性元素应力求使用简短的描述性替代文字。未指定 alt 属性的装饰性元素可被忽略。[了解详情](https://web.dev/image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | failureTitle": {
+ "message": "图片元素缺少 `[alt]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/image-alt.js | title": {
+ "message": "图片元素具备 `[alt]` 属性"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | description": {
+ "message": "将图片用作 `<input>` 按钮时,提供替代文字有助于屏幕阅读器用户了解该按钮的用途。[了解详情](https://web.dev/input-image-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | failureTitle": {
+ "message": "`<input type=\"image\">` 元素缺少 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/input-image-alt.js | title": {
+ "message": "`<input type=\"image\">` 元素包含 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/label.js | description": {
+ "message": "标签可确保辅助技术(如屏幕阅读器)正确读出表单控件。[了解详情](https://web.dev/label/)。"
+ },
+ "lighthouse-core/audits/accessibility/label.js | failureTitle": {
+ "message": "表单元素不具备关联的标签"
+ },
+ "lighthouse-core/audits/accessibility/label.js | title": {
+ "message": "表单元素具有关联的标签"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | description": {
+ "message": "用于实现布局用途的表格不应包含数据元素(例如 th 或 caption 元素或 summary 属性),因为这会令屏幕阅读器用户感到困惑。[了解详情](https://web.dev/layout-table/)。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | failureTitle": {
+ "message": "展示性 `<table>` 元素未避免使用 `<th>`、`<caption>` 或 `[summary]` 属性。"
+ },
+ "lighthouse-core/audits/accessibility/layout-table.js | title": {
+ "message": "展示性 `<table>` 元素未使用 `<th>`、`<caption>` 或 `[summary]` 属性。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | description": {
+ "message": "请确保链接文字(以及用作链接的图片替代文字)可识别、独一无二且可成为焦点,这样做会提升屏幕阅读器用户的导航体验。[了解详情](https://web.dev/link-name/)。"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | failureTitle": {
+ "message": "链接缺少可识别的名称"
+ },
+ "lighthouse-core/audits/accessibility/link-name.js | title": {
+ "message": "链接具备可识别的名称"
+ },
+ "lighthouse-core/audits/accessibility/list.js | description": {
+ "message": "屏幕阅读器会采用特定的方法来读出列表内容。确保列表结构正确有助于屏幕阅读器顺利读出相应内容。[了解详情](https://web.dev/list/)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | failureTitle": {
+ "message": "列表并非只包含 `<li>` 元素和脚本支持元素(`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/list.js | title": {
+ "message": "列表只包含 `<li>` 元素和脚本支持元素(`<script>` 和 `<template>`)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | description": {
+ "message": "屏幕阅读器要求列表项 (`<li>`) 必须包含在父 `<ul>` 或 `<ol>` 中,这样才能正确读出它们。[了解详情](https://web.dev/listitem/)。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | failureTitle": {
+ "message": "列表项 (`<li>`) 未包含在 `<ul>` 或 `<ol>` 父元素中。"
+ },
+ "lighthouse-core/audits/accessibility/listitem.js | title": {
+ "message": "列表项 (`<li>`) 包含在 `<ul>` 或 `<ol>` 父元素中"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | description": {
+ "message": "用户并不希望网页自动刷新,因为自动刷新会不断地将焦点移回到页面顶部。这可能会让用户感到沮丧或困惑。[了解详情](https://web.dev/meta-refresh/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | failureTitle": {
+ "message": "文档使用了 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-refresh.js | title": {
+ "message": "文档未使用 `<meta http-equiv=\"refresh\">`"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | description": {
+ "message": "对于必须依靠放大屏幕才能清晰看到网页内容的弱视用户而言,停用缩放功能会给他们带来问题。[了解详情](https://web.dev/meta-viewport/)。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | failureTitle": {
+ "message": "`<meta name=\"viewport\">` 元素中使用了 `[user-scalable=\"no\"]`,或者 `[maximum-scale]` 属性小于 5。"
+ },
+ "lighthouse-core/audits/accessibility/meta-viewport.js | title": {
+ "message": "`[user-scalable=\"no\"]` 未用在 `<meta name=\"viewport\">` 元素中,并且 `[maximum-scale]` 属性不小于 5。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | description": {
+ "message": "屏幕阅读器无法转换非文字内容。向 `<object>` 元素添加替代文字可帮助屏幕阅读器将含义传达给用户。[了解详情](https://web.dev/object-alt/)。"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | failureTitle": {
+ "message": "`<object>` 元素缺少 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/object-alt.js | title": {
+ "message": "`<object>` 元素包含 `[alt]` 文字"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | description": {
+ "message": "值大于 0 意味着明确的导航顺序。尽管这在技术上可行,但往往会让依赖辅助技术的用户感到沮丧。[了解详情](https://web.dev/tabindex/)。"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | failureTitle": {
+ "message": "一些元素的 `[tabindex]` 值大于 0"
+ },
+ "lighthouse-core/audits/accessibility/tabindex.js | title": {
+ "message": "所有元素的 `[tabindex]` 值都不大于 0"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | description": {
+ "message": "屏幕阅读器提供了更便于用户浏览表格内容的功能。请确保那些使用 `[headers]` 属性的 `<td>` 单元格仅引用同一个表格中的其他单元格,这样做可提升屏幕阅读器用户的体验。[了解详情](https://web.dev/td-headers-attr/)。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | failureTitle": {
+ "message": "`<table>` 元素中使用 `[headers]` 属性的单元格引用了在同一表格中找不到的元素 `id`。"
+ },
+ "lighthouse-core/audits/accessibility/td-headers-attr.js | title": {
+ "message": "`<table>` 元素中使用 `[headers]` 属性的单元格引用的是同一表格中的单元格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | description": {
+ "message": "屏幕阅读器提供了更便于用户浏览表格内容的功能。确保表格标头始终引用特定一组单元格可以提升屏幕阅读器用户的体验。[了解详情](https://web.dev/th-has-data-cells/)。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | failureTitle": {
+ "message": "`<th>` 元素和 `[role=\"columnheader\"/\"rowheader\"]` 的元素缺少它们所描述的数据单元格。"
+ },
+ "lighthouse-core/audits/accessibility/th-has-data-cells.js | title": {
+ "message": "`<th>` 元素和 `[role=\"columnheader\"/\"rowheader\"]` 的元素具备它们所描述的数据单元格。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | description": {
+ "message": "为元素指定有效的 [BCP 47 语言](https://www.w3.org/International/questions/qa-choosing-language-tags#question)有助于确保屏幕阅读器正确读出文字。[了解详情](https://web.dev/valid-lang/)。"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | failureTitle": {
+ "message": "`[lang]` 属性缺少有效值"
+ },
+ "lighthouse-core/audits/accessibility/valid-lang.js | title": {
+ "message": "`[lang]` 属性的值有效"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | description": {
+ "message": "如果视频提供了字幕,失聪用户和听障用户便能更轻松地获取此视频中的信息。[了解详情](https://web.dev/video-caption/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | failureTitle": {
+ "message": "`<video>` 元素缺少含 `[kind=\"captions\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/video-caption.js | title": {
+ "message": "`<video>` 元素包含带 `[kind=\"captions\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | description": {
+ "message": "音频说明可提供对话框无法提供的视频相关信息(例如面部表情和场景)。[了解详情](https://web.dev/video-description/)。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | failureTitle": {
+ "message": "`<video>` 元素缺少含 `[kind=\"description\"]` 的 `<track>` 元素。"
+ },
+ "lighthouse-core/audits/accessibility/video-description.js | title": {
+ "message": "`<video>` 元素包含带 `[kind=\"description\"]` 的 `<track>` 元素"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | description": {
+ "message": "请定义一个 `apple-touch-icon`,以在 iOS 用户向主屏幕添加渐进式 Web 应用时获得理想的外观。它必须指向一张不透明的 192px(或 180px)方形 PNG 图片。[了解详情](https://web.dev/apple-touch-icon/)。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | failureTitle": {
+ "message": "未提供有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | precomposedWarning": {
+ "message": "`apple-touch-icon-precomposed` 不是最新版本,建议使用 `apple-touch-icon`。"
+ },
+ "lighthouse-core/audits/apple-touch-icon.js | title": {
+ "message": "提供了有效的 `apple-touch-icon`"
+ },
+ "lighthouse-core/audits/bootup-time.js | chromeExtensionsWarning": {
+ "message": "Chrome 扩展程序对此网页的加载性能产生了负面影响。请尝试在无痕模式下或使用未安装这些扩展程序的 Chrome 个人资料审核此网页。"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptEval": {
+ "message": "脚本评估"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnScriptParse": {
+ "message": "脚本解析"
+ },
+ "lighthouse-core/audits/bootup-time.js | columnTotal": {
+ "message": "总 CPU 时间"
+ },
+ "lighthouse-core/audits/bootup-time.js | description": {
+ "message": "建议您减少为解析、编译和执行 JS 而花费的时间。您可能会发现,提供较小的 JS 负载有助于实现此目标。[了解详情](https://web.dev/bootup-time)。"
+ },
+ "lighthouse-core/audits/bootup-time.js | failureTitle": {
+ "message": "缩短 JavaScript 执行用时"
+ },
+ "lighthouse-core/audits/bootup-time.js | title": {
+ "message": "JavaScript 执行用时"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | description": {
+ "message": "使用大型 GIF 提供动画内容会导致效率低下。建议您改用 MPEG4/WebM 视频(来提供动画)和 PNG/WebP(来提供静态图片)以减少网络活动消耗的字节数。[了解详情](https://web.dev/efficient-animated-content)"
+ },
+ "lighthouse-core/audits/byte-efficiency/efficient-animated-content.js | title": {
+ "message": "使用视频格式提供动画内容"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | description": {
+ "message": "建议您在所有关键资源加载完毕后推迟加载屏幕外图片和处于隐藏状态的图片,从而缩短可交互前的耗时。[了解详情](https://web.dev/offscreen-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/offscreen-images.js | title": {
+ "message": "推迟加载屏幕外图片"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | description": {
+ "message": "资源阻止了系统对您网页的首次渲染。建议以内嵌方式提供关键的 JS/CSS,并推迟提供所有非关键的 JS/样式。[了解详情](https://web.dev/render-blocking-resources)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/render-blocking-resources.js | title": {
+ "message": "移除阻塞渲染的资源"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | description": {
+ "message": "网络负载过大不仅会让用户付出真金白银,还极有可能会延长加载用时。[了解详情](https://web.dev/total-byte-weight)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | displayValue": {
+ "message": "总大小为 {totalBytes, number, bytes} KB"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | failureTitle": {
+ "message": "避免网络负载过大"
+ },
+ "lighthouse-core/audits/byte-efficiency/total-byte-weight.js | title": {
+ "message": "避免网络负载过大"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | description": {
+ "message": "缩减 CSS 文件大小可缩减网络负载规模。[了解详情](https://web.dev/unminified-css)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-css.js | title": {
+ "message": "缩减 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | description": {
+ "message": "如果缩减 JavaScript 文件大小,则既能缩减负载规模,又能缩短脚本解析用时。[了解详情](https://web.dev/unminified-javascript)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unminified-javascript.js | title": {
+ "message": "缩减 JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | description": {
+ "message": "从样式表中移除无效规则并延迟加载首屏内容未使用的 CSS 可减少网络活动的无谓消耗。[了解详情](https://web.dev/unused-css-rules)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-css-rules.js | title": {
+ "message": "移除未使用的 CSS"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | description": {
+ "message": "移除未使用的 JavaScript 可减少网络活动消耗的字节数。"
+ },
+ "lighthouse-core/audits/byte-efficiency/unused-javascript.js | title": {
+ "message": "移除未使用的 JavaScript"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | description": {
+ "message": "延长缓存期限可加快重访您网页的速度。[了解详情](https://web.dev/uses-long-cache-ttl)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到了 1 项资源}other{找到了 # 项资源}}"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | failureTitle": {
+ "message": "采用高效的缓存策略提供静态资源"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js | title": {
+ "message": "针对静态资源使用高效的缓存策略"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | description": {
+ "message": "如果图片经过了优化,则加载速度会更快,且消耗的移动数据网络流量会更少。[了解详情](https://web.dev/uses-optimized-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-optimized-images.js | title": {
+ "message": "对图片进行高效编码"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | description": {
+ "message": "提供大小合适的图片可节省移动数据网络流量并缩短加载用时。[了解详情](https://web.dev/uses-responsive-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-responsive-images.js | title": {
+ "message": "适当调整图片大小"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | description": {
+ "message": "对于文本资源,应先压缩(gzip、deflate 或 brotli),然后再提供,以最大限度地减少网络活动消耗的字节总数。[了解详情](https://web.dev/uses-text-compression)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-text-compression.js | title": {
+ "message": "启用文本压缩"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | description": {
+ "message": "JPEG 2000、JPEG XR 和 WebP 等图片格式的压缩效果通常比 PNG 或 JPEG 好,因此下载速度更快,消耗的数据流量更少。[了解详情](https://web.dev/uses-webp-images)。"
+ },
+ "lighthouse-core/audits/byte-efficiency/uses-webp-images.js | title": {
+ "message": "采用新一代格式提供图片"
+ },
+ "lighthouse-core/audits/content-width.js | description": {
+ "message": "如果应用内容的宽度与视口的宽度不一致,该应用可能不会针对移动设备屏幕进行优化。[了解详情](https://web.dev/content-width)。"
+ },
+ "lighthouse-core/audits/content-width.js | explanation": {
+ "message": "视口大小({innerWidth} 像素)与窗口大小({outerWidth} 像素)不一致。"
+ },
+ "lighthouse-core/audits/content-width.js | failureTitle": {
+ "message": "未根据视口正确设置内容尺寸"
+ },
+ "lighthouse-core/audits/content-width.js | title": {
+ "message": "已根据视口正确设置内容尺寸"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | description": {
+ "message": "下面的关键请求链显示了以高优先级加载的资源。请考虑缩短链长、缩减资源的下载文件大小,或者推迟下载不必要的资源,从而提高网页加载速度。[了解详情](https://web.dev/critical-request-chains)。"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到了 1 条请求链}other{找到了 # 条请求链}}"
+ },
+ "lighthouse-core/audits/critical-request-chains.js | title": {
+ "message": "最大限度地缩短关键请求深度"
+ },
+ "lighthouse-core/audits/deprecations.js | columnDeprecate": {
+ "message": "弃用/警告"
+ },
+ "lighthouse-core/audits/deprecations.js | columnLine": {
+ "message": "Line"
+ },
+ "lighthouse-core/audits/deprecations.js | description": {
+ "message": "已弃用的的 API 最终将从浏览器中移除。[了解详情](https://web.dev/deprecations)。"
+ },
+ "lighthouse-core/audits/deprecations.js | displayValue": {
+ "message": "{itemCount,plural, =1{发现了 1 条警告}other{发现了 # 条警告}}"
+ },
+ "lighthouse-core/audits/deprecations.js | failureTitle": {
+ "message": "使用了已弃用的 API"
+ },
+ "lighthouse-core/audits/deprecations.js | title": {
+ "message": "请勿使用已弃用的 API"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | description": {
+ "message": "应用缓存已被弃用。[了解详情](https://web.dev/appcache-manifest)。"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | displayValue": {
+ "message": "发现了“{AppCacheManifest}”"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | failureTitle": {
+ "message": "使用了应用缓存"
+ },
+ "lighthouse-core/audits/dobetterweb/appcache-manifest.js | title": {
+ "message": "请勿使用应用缓存"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | description": {
+ "message": "指定 DOCTYPE 会阻止浏览器切换到怪异模式。[了解详情](https://web.dev/doctype)。"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationBadDoctype": {
+ "message": "DOCTYPE 名称必须为小写字符串 `html`"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationNoDoctype": {
+ "message": "文档必需包含 DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationPublicId": {
+ "message": "publicId 应为空字符串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | explanationSystemId": {
+ "message": "systemId 应为空字符串"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | failureTitle": {
+ "message": "页面缺少 HTML DOCTYPE,从而触发了怪异模式"
+ },
+ "lighthouse-core/audits/dobetterweb/doctype.js | title": {
+ "message": "页面包含 HTML DOCTYPE"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnElement": {
+ "message": "元素"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnStatistic": {
+ "message": "统计信息"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | columnValue": {
+ "message": "值"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | description": {
+ "message": "浏览器工程师建议,页面包含的 DOM 元素最好少于 1,500 个左右。理想状况是,树深度少于 32 个元素,且少于 60 个子/父元素。大型 DOM 可能会增加内存使用量、导致[样式计算](https://developers.google.com/web/fundamentals/performance/rendering/reduce-the-scope-and-complexity-of-style-calculations)用时延长,并产生高昂的[布局重排](https://developers.google.com/speed/articles/reflow)费用。[了解详情](https://web.dev/dom-size)。"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 个元素}other{# 个元素}}"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | failureTitle": {
+ "message": "避免 DOM 规模过大"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMDepth": {
+ "message": "最大 DOM 深度"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMElements": {
+ "message": "DOM 元素总数"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | statisticDOMWidth": {
+ "message": "子元素数量最大值"
+ },
+ "lighthouse-core/audits/dobetterweb/dom-size.js | title": {
+ "message": "避免 DOM 规模过大"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnRel": {
+ "message": "Rel"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | columnTarget": {
+ "message": "目标"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | description": {
+ "message": "向任何外部链接添加 `rel=\"noopener\"` 或 `rel=\"noreferrer\"`,可提高性能并减少安全漏洞。[了解详情](https://web.dev/external-anchors-use-rel-noopener)。"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | failureTitle": {
+ "message": "指向跨域目的地的链接不安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | title": {
+ "message": "指向跨域目的地的链接安全"
+ },
+ "lighthouse-core/audits/dobetterweb/external-anchors-use-rel-noopener.js | warning": {
+ "message": "无法确定锚点 ({anchorHTML}) 的目的地。如果不用作超链接,建议移除 target=_blank。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | description": {
+ "message": "如果网站在缺少上下文的情况下请求位置,会导致用户不信任网站或感到困惑。建议将请求与用户操作进行绑定。[了解详情](https://web.dev/geolocation-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | failureTitle": {
+ "message": "在网页加载时请求地理定位权限"
+ },
+ "lighthouse-core/audits/dobetterweb/geolocation-on-start.js | title": {
+ "message": "避免在网页加载时请求地理定位权限"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | columnVersion": {
+ "message": "版本"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | description": {
+ "message": "页面上检测到的所有前端 JavaScript 库。[了解详情](https://web.dev/js-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/js-libraries.js | title": {
+ "message": "已检测到的 JavaScript 库"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | description": {
+ "message": "对于连接速度较慢的用户,通过 `document.write()` 动态注入的外部脚本可将网页加载延迟数十秒。[了解详情](https://web.dev/no-document-write)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | failureTitle": {
+ "message": "使用了 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-document-write.js | title": {
+ "message": "请勿使用 `document.write()`"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnSeverity": {
+ "message": "最高严重程度"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVersion": {
+ "message": "库版本"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | columnVuln": {
+ "message": "漏洞数量"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | description": {
+ "message": "某些第三方脚本可能包含已知的安全漏洞,攻击者很容易识别和利用这些漏洞。[了解详情](https://web.dev/no-vulnerable-libraries)。"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | displayValue": {
+ "message": "{itemCount,plural, =1{检测到 1 个漏洞}other{检测到 # 个漏洞}}"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | failureTitle": {
+ "message": "包含有已知安全漏洞的前端 JavaScript 库"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityHigh": {
+ "message": "高"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityLow": {
+ "message": "低"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | rowSeverityMedium": {
+ "message": "中"
+ },
+ "lighthouse-core/audits/dobetterweb/no-vulnerable-libraries.js | title": {
+ "message": "避免使用含已知安全漏洞的前端 JavaScript 库"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | description": {
+ "message": "如果网站在缺少上下文的情况下请求发送通知,会导致用户不信任网站或感到困惑。建议将请求与用户手势进行绑定。[了解详情](https://web.dev/notification-on-start)。"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | failureTitle": {
+ "message": "在网页加载时请求通知权限"
+ },
+ "lighthouse-core/audits/dobetterweb/notification-on-start.js | title": {
+ "message": "避免在网页加载时请求通知权限"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | columnFailingElem": {
+ "message": "失败的元素"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | description": {
+ "message": "阻止密码粘贴,会破坏良好的安全政策。[了解详情](https://web.dev/password-inputs-can-be-pasted-into)。"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | failureTitle": {
+ "message": "不允许用户粘贴内容到密码字段"
+ },
+ "lighthouse-core/audits/dobetterweb/password-inputs-can-be-pasted-into.js | title": {
+ "message": "允许用户粘贴内容到密码字段"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | columnProtocol": {
+ "message": "协议"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | description": {
+ "message": "HTTP/2 提供了许多优于 HTTP/1.1的优点,包括二进制标头、多路复用和服务器推送等。[了解详情](https://web.dev/uses-http2)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 条请求未通过 HTTP/2 传送}other{# 条请求未通过 HTTP/2 传送}}"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | failureTitle": {
+ "message": "没有对所有网页资源使用 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-http2.js | title": {
+ "message": "对其自身资源使用了 HTTP/2"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | description": {
+ "message": "建议您将触摸和滚轮事件监听器标记为 `passive`,以提高页面的滚动性能。[了解详情](https://web.dev/uses-passive-event-listeners)。"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | failureTitle": {
+ "message": "未使用被动式监听器来提高滚动性能"
+ },
+ "lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js | title": {
+ "message": "使用被动式监听器来提高滚动性能"
+ },
+ "lighthouse-core/audits/errors-in-console.js | columnDesc": {
+ "message": "说明"
+ },
+ "lighthouse-core/audits/errors-in-console.js | description": {
+ "message": "控制台中记录的错误表明有未解决的问题。导致这些错误的可能原因是网络请求失败和其他浏览器问题。[了解详情](https://web.dev/errors-in-console)"
+ },
+ "lighthouse-core/audits/errors-in-console.js | failureTitle": {
+ "message": "控制台日志中已记录浏览器错误"
+ },
+ "lighthouse-core/audits/errors-in-console.js | title": {
+ "message": "控制台日志中未记录浏览器错误"
+ },
+ "lighthouse-core/audits/font-display.js | description": {
+ "message": "利用 font-display 这项 CSS 功能,确保文本在网页字体加载期间始终对用户可见。[了解详情](https://web.dev/font-display)。"
+ },
+ "lighthouse-core/audits/font-display.js | failureTitle": {
+ "message": "确保文本在网页字体加载期间保持可见状态"
+ },
+ "lighthouse-core/audits/font-display.js | title": {
+ "message": "在网页字体加载期间,所有文本都保持可见状态"
+ },
+ "lighthouse-core/audits/font-display.js | undeclaredFontURLWarning": {
+ "message": "Lighthouse 无法自动检查以下网址的字体显示值:{fontURL}。"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnActual": {
+ "message": "宽高比(实际)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | columnDisplayed": {
+ "message": "宽高比(显示)"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | description": {
+ "message": "图像显示尺寸应与自然宽高比相匹配。[了解详情](https://web.dev/image-aspect-ratio)。"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | failureTitle": {
+ "message": "显示的图像宽高比不正确"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | title": {
+ "message": "显示的图像宽高比正确"
+ },
+ "lighthouse-core/audits/image-aspect-ratio.js | warningCompute": {
+ "message": "无效的图片大小信息 {url}"
+ },
+ "lighthouse-core/audits/installable-manifest.js | description": {
+ "message": "浏览器可主动提示用户向其主屏幕中添加您的应用,这有助于提高互动度。[了解详情](https://web.dev/installable-manifest)。"
+ },
+ "lighthouse-core/audits/installable-manifest.js | failureTitle": {
+ "message": "Web 应用清单不符合可安装性要求"
+ },
+ "lighthouse-core/audits/installable-manifest.js | title": {
+ "message": "Web 应用清单符合可安装性要求"
+ },
+ "lighthouse-core/audits/is-on-https.js | columnInsecureURL": {
+ "message": "不安全的网址"
+ },
+ "lighthouse-core/audits/is-on-https.js | description": {
+ "message": "应该使用 HTTPS 保护所有网站(包括不会处理敏感数据的网站)。HTTPS 可防止入侵程序篡改或被动地监听您的应用与用户之间的通信,它是HTTP/2 和许多新的网络平台 API 的先决条件。[了解详情](https://web.dev/is-on-https)。"
+ },
+ "lighthouse-core/audits/is-on-https.js | displayValue": {
+ "message": "{itemCount,plural, =1{发现 1 条不安全的请求}other{发现 # 条不安全的请求}}"
+ },
+ "lighthouse-core/audits/is-on-https.js | failureTitle": {
+ "message": "未使用 HTTPS"
+ },
+ "lighthouse-core/audits/is-on-https.js | title": {
+ "message": "使用 HTTPS"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": {
+ "message": "如果网页在移动网络中的加载速度较快,则可确保良好的移动用户体验。[了解详情](https://web.dev/load-fast-enough-for-pwa)。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueText": {
+ "message": "页面交互需要 {timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | displayValueTextWithOverride": {
+ "message": "在模拟移动网络上需要 {timeInMs, number, seconds} 秒才能支持交互"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | explanationLoadSlow": {
+ "message": "您的网页加载速度过慢,在 10 秒钟内一直未进行互动。要了解如何改进,请查看“性能”部分中的优化建议和诊断结果。"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | failureTitle": {
+ "message": "页面在移动网络上的加载速度不够快"
+ },
+ "lighthouse-core/audits/load-fast-enough-for-pwa.js | title": {
+ "message": "页面在移动网络上的加载速度足够快"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | columnCategory": {
+ "message": "类别"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | description": {
+ "message": "建议您减少为解析、编译和执行 JS 而花费的时间。您可能会发现,提供较小的 JS 负载有助于实现此目标。[了解详情](https://web.dev/mainthread-work-breakdown)"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | failureTitle": {
+ "message": "最大限度地减少主线程工作"
+ },
+ "lighthouse-core/audits/mainthread-work-breakdown.js | title": {
+ "message": "最大限度地减少主线程工作"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | description": {
+ "message": "网站应该能在所有主流浏览器中正常显示,以便覆盖数量最多的用户。[了解详情](https://web.dev/pwa-cross-browser)。"
+ },
+ "lighthouse-core/audits/manual/pwa-cross-browser.js | title": {
+ "message": "网站能在各种浏览器中正常显示"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | description": {
+ "message": "确保各个网页可通过网址建立深层链接,并且这些网址是独一无二的,可以在社交媒体上共享。[了解详情](https://web.dev/pwa-each-page-has-url)。"
+ },
+ "lighthouse-core/audits/manual/pwa-each-page-has-url.js | title": {
+ "message": "每个网页都有一个网址"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | description": {
+ "message": "无论点按哪个链接,都应能快速跳转到相应页面,即使网速缓慢也应如此。若想让用户感知到出色的网页加载速度,这种体验至关重要。[了解详情](https://web.dev/pwa-page-transitions)。"
+ },
+ "lighthouse-core/audits/manual/pwa-page-transitions.js | title": {
+ "message": "在不同网页之间跳转时,用户感觉不到网页加载缓慢"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | description": {
+ "message": "预计输入延迟是估算值,表示您的应用在网页加载最繁忙的 5 秒期间大概需要花费多长时间(以毫秒为单位)才能对用户输入做出响应。如果您的延迟时间超过了 50 毫秒,用户可能会感觉您的应用运行迟缓。[了解详情](https://web.dev/estimated-input-latency)。"
+ },
+ "lighthouse-core/audits/metrics/estimated-input-latency.js | title": {
+ "message": "输入延迟(估算值)"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | description": {
+ "message": "首次内容渲染时间标记了渲染出首个文本或首张图片的时间。[了解详情](https://web.dev/first-contentful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-contentful-paint.js | title": {
+ "message": "首次内容绘制时间"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | description": {
+ "message": "首次 CPU 闲置时间标记了网页的主线程首次有空处理输入操作的时间。[了解详情](https://web.dev/first-cpu-idle)。"
+ },
+ "lighthouse-core/audits/metrics/first-cpu-idle.js | title": {
+ "message": "首次 CPU 闲置时间"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | description": {
+ "message": "首次有效渲染时间测量了网页主要内容开始对用户显示的时间。[了解详情](https://web.dev/first-meaningful-paint)。"
+ },
+ "lighthouse-core/audits/metrics/first-meaningful-paint.js | title": {
+ "message": "首次有效绘制时间"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | description": {
+ "message": "可交互时间是指网页需要多长时间才能提供完整交互功能。[了解详情](https://web.dev/interactive)。"
+ },
+ "lighthouse-core/audits/metrics/interactive.js | title": {
+ "message": "可交互前的耗时"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | description": {
+ "message": "您的用户可能会遇到的最长首次输入延迟是用时最长的任务的耗时(以毫秒为单位)。[了解详情](https://developers.google.com/web/updates/2018/05/first-input-delay)。"
+ },
+ "lighthouse-core/audits/metrics/max-potential-fid.js | title": {
+ "message": "首次输入延迟最长预估值"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | description": {
+ "message": "速度指数表明了网页内容的可见填充速度。[了解详情](https://web.dev/speed-index)。"
+ },
+ "lighthouse-core/audits/metrics/speed-index.js | title": {
+ "message": "速度指数"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | description": {
+ "message": "当任务长度超过 50 毫秒时,首次内容渲染 (FCP) 和可交互时间之间的所有时间段的总和,以毫秒表示。"
+ },
+ "lighthouse-core/audits/metrics/total-blocking-time.js | title": {
+ "message": "总阻塞时间"
+ },
+ "lighthouse-core/audits/network-rtt.js | description": {
+ "message": "网络往返时间 (RTT) 对性能有很大的影响。如果与来源之间的 RTT 较长,则表明缩短服务器与用户之间的距离可能会提高性能。[了解详情](https://hpbn.co/primer-on-latency-and-bandwidth/)。"
+ },
+ "lighthouse-core/audits/network-rtt.js | title": {
+ "message": "网络往返时间"
+ },
+ "lighthouse-core/audits/network-server-latency.js | description": {
+ "message": "服务器延迟时间可能会对网站性能产生不良影响。如果源服务器的延迟时间较长,则表明服务器过载或后端性能较差。[了解详情](https://hpbn.co/primer-on-web-performance/#analyzing-the-resource-waterfall)。"
+ },
+ "lighthouse-core/audits/network-server-latency.js | title": {
+ "message": "服务器后端延迟"
+ },
+ "lighthouse-core/audits/offline-start-url.js | description": {
+ "message": "Service Worker 可让您的 Web 应用在无法预测的网络状况下正常运行。[了解详情](https://web.dev/offline-start-url)。"
+ },
+ "lighthouse-core/audits/offline-start-url.js | failureTitle": {
+ "message": "`start_url` 在离线时没有响应,并返回 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | title": {
+ "message": "`start_url` 在离线时也能成功做出响应,并返回 200"
+ },
+ "lighthouse-core/audits/offline-start-url.js | warningCantStart": {
+ "message": "Lighthouse 无法从清单读取 `start_url`。因此,系统已将 `start_url` 视为该文档的网址。错误消息:“{manifestWarning}”。"
+ },
+ "lighthouse-core/audits/performance-budget.js | columnOverBudget": {
+ "message": "超出预算"
+ },
+ "lighthouse-core/audits/performance-budget.js | description": {
+ "message": "请将网络请求的数量和数据大小保持在提供的性能预算所设定的目标之内。[了解详情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/performance-budget.js | requestCountOverBudget": {
+ "message": "{count,plural, =1{1 条请求}other{# 条请求}}"
+ },
+ "lighthouse-core/audits/performance-budget.js | title": {
+ "message": "性能预算"
+ },
+ "lighthouse-core/audits/redirects-http.js | description": {
+ "message": "如果您已设置 HTTPS,请确保将所有 HTTP 流量重定向到 HTTPS,以便让所有用户都能使用安全的网络功能。[了解详情](https://web.dev/redirects-http)。"
+ },
+ "lighthouse-core/audits/redirects-http.js | failureTitle": {
+ "message": "未将 HTTP 流量重定向到 HTTPS"
+ },
+ "lighthouse-core/audits/redirects-http.js | title": {
+ "message": "将 HTTP 流量重定向到 HTTPS"
+ },
+ "lighthouse-core/audits/redirects.js | description": {
+ "message": "重定向会在网页可加载前引入更多延迟。[了解详情](https://web.dev/redirects)。"
+ },
+ "lighthouse-core/audits/redirects.js | title": {
+ "message": "避免多次网页重定向"
+ },
+ "lighthouse-core/audits/resource-summary.js | description": {
+ "message": "若要设置页面资源数量和大小的预算,请添加 budget.json 文件。[了解详情](https://developers.google.com/web/tools/lighthouse/audits/budgets)。"
+ },
+ "lighthouse-core/audits/resource-summary.js | displayValue": {
+ "message": "{requestCount,plural, =1{1 项请求 • {byteCount, number, bytes} KB}other{# 项请求 • {byteCount, number, bytes} KB}}"
+ },
+ "lighthouse-core/audits/resource-summary.js | title": {
+ "message": "请保持较低的请求数量和较小的传输大小"
+ },
+ "lighthouse-core/audits/seo/canonical.js | description": {
+ "message": "规范链接用于建议应在搜索结果中显示哪个网址。[了解详情](https://web.dev/canonical)。"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationConflict": {
+ "message": "存在多个相互冲突的网址({urlList})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationDifferentDomain": {
+ "message": "指向不同的域名 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationInvalid": {
+ "message": "网址无效 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationPointsElsewhere": {
+ "message": "指向了其他 `hreflang` 位置 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRelative": {
+ "message": "相对网址 ({url})"
+ },
+ "lighthouse-core/audits/seo/canonical.js | explanationRoot": {
+ "message": "指向了网域的根网址(首页),而非等效内容页面"
+ },
+ "lighthouse-core/audits/seo/canonical.js | failureTitle": {
+ "message": "文档缺少有效的 `rel=canonical`"
+ },
+ "lighthouse-core/audits/seo/canonical.js | title": {
+ "message": "文档的 `rel=canonical` 有效"
+ },
+ "lighthouse-core/audits/seo/font-size.js | description": {
+ "message": "12px 以下的字体过小,会导致用户无法辨认;此外,这样的字体需要移动设备访问者“张合双指进行缩放”才能阅读。请尽量让 60% 以上的页面文字不小于 12px。[了解详情](https://web.dev/font-size)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | displayValue": {
+ "message": "{decimalProportion, number, extendedPercent} 清晰可辨的文字"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationViewport": {
+ "message": "无法辨认文字,因为缺少已针对移动设备屏幕进行优化的 viewport meta 标记。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | explanationWithDisclaimer": {
+ "message": "{decimalProportion, number, extendedPercent} 的文字过小(基于规模为 {decimalProportionVisited, number, extendedPercent} 的样本)。"
+ },
+ "lighthouse-core/audits/seo/font-size.js | failureTitle": {
+ "message": "文档未使用清晰可辨的字体大小"
+ },
+ "lighthouse-core/audits/seo/font-size.js | title": {
+ "message": "文档所用的字体大小清晰可辨"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | description": {
+ "message": "hreflang 链接用于告知搜索引擎应在特定语言或地区的搜索结果中显示哪种版本的网页。[了解详情](https://web.dev/hreflang)。"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | failureTitle": {
+ "message": "文档的 `hreflang` 无效"
+ },
+ "lighthouse-core/audits/seo/hreflang.js | title": {
+ "message": "文档的 `hreflang` 有效"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | description": {
+ "message": "返回无效 HTTP 状态代码的页面可能无法被正确编入索引。[了解详情](https://web.dev/http-status-code)。"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | failureTitle": {
+ "message": "页面返回了无效的 HTTP 状态代码"
+ },
+ "lighthouse-core/audits/seo/http-status-code.js | title": {
+ "message": "页面返回了有效的 HTTP 状态代码"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | description": {
+ "message": "如果搜索引擎无权抓取您的网页,则无法将它们添加到搜索结果中。[了解详情](https://web.dev/is-crawable)。"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | failureTitle": {
+ "message": "页面已被屏蔽,无法编入索引"
+ },
+ "lighthouse-core/audits/seo/is-crawlable.js | title": {
+ "message": "页面未被屏蔽,可编入索引"
+ },
+ "lighthouse-core/audits/seo/link-text.js | description": {
+ "message": "描述性链接文字有助于搜索引擎理解您的内容。[了解详情](https://web.dev/link-text)。"
+ },
+ "lighthouse-core/audits/seo/link-text.js | displayValue": {
+ "message": "{itemCount,plural, =1{找到了 1 个链接}other{找到了 # 个链接}}"
+ },
+ "lighthouse-core/audits/seo/link-text.js | failureTitle": {
+ "message": "链接缺少描述性文字"
+ },
+ "lighthouse-core/audits/seo/link-text.js | title": {
+ "message": "链接有描述性文字"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | description": {
+ "message": "运行[结构化数据测试工具](https://search.google.com/structured-data/testing-tool/) 和 [Structured Data Linter](http://linter.structured-data.org/) 可验证结构化数据。[了解详情](https://web.dev/structured-data)。"
+ },
+ "lighthouse-core/audits/seo/manual/structured-data.js | title": {
+ "message": "结构化数据有效"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | description": {
+ "message": "元描述可能会被包含在搜索结果中,以简要概括网页内容。[了解详情](https://web.dev/meta-description)。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | explanation": {
+ "message": "描述性文字为空。"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | failureTitle": {
+ "message": "文档缺少 meta 描述"
+ },
+ "lighthouse-core/audits/seo/meta-description.js | title": {
+ "message": "文档有 meta 描述"
+ },
+ "lighthouse-core/audits/seo/plugins.js | description": {
+ "message": "搜索引擎无法将插件内容编入索引,而且许多设备都限制或不支持使用插件。[了解详情](https://web.dev/plugins)。"
+ },
+ "lighthouse-core/audits/seo/plugins.js | failureTitle": {
+ "message": "文档使用了插件"
+ },
+ "lighthouse-core/audits/seo/plugins.js | title": {
+ "message": "文档中没有插件"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | description": {
+ "message": "如果 robots.txt 文件的格式不正确,抓取工具可能无法理解您希望以何种方式抓取网站内容或将其编入索引。[了解详情](https://web.dev/robots-txt)。"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueHttpBadCode": {
+ "message": "对 robots.txt 的请求返回了 HTTP 状态代码:{statusCode}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | displayValueValidationError": {
+ "message": "{itemCount,plural, =1{发现了 1 处错误}other{发现了 # 处错误}}"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | explanation": {
+ "message": "Lighthouse 无法下载 robots.txt 文件"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | failureTitle": {
+ "message": "robots.txt 无效"
+ },
+ "lighthouse-core/audits/seo/robots-txt.js | title": {
+ "message": "robots.txt 有效"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | description": {
+ "message": "交互式元素(例如按钮和链接)应足够大 (48x48px),且其周围应有足够的空间,以便用户轻松点按且避免遮挡其他元素。[了解详情](https://web.dev/tap-targets)。"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | displayValue": {
+ "message": "{decimalProportion, number, percent} 的点按目标大小合适"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | explanationViewportMetaNotOptimized": {
+ "message": "点按目标过小,因为缺少已针对移动设备屏幕进行优化的 viewport meta 标记"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | failureTitle": {
+ "message": "点按目标的大小不合适"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | overlappingTargetHeader": {
+ "message": "点按目标重叠"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | tapTargetHeader": {
+ "message": "点按目标"
+ },
+ "lighthouse-core/audits/seo/tap-targets.js | title": {
+ "message": "点按目标的大小合适"
+ },
+ "lighthouse-core/audits/service-worker.js | description": {
+ "message": "Service Worker 是一项技术,可让您的应用使用很多渐进式 Web 应用功能,例如离线、添加到主屏幕和推送通知。[了解详情](https://web.dev/service-worker)。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadManifest": {
+ "message": "此网页由 Service Worker 控制,但由于清单未能解析为有效的 JSON,因此未找到 `start_url`"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationBadStartUrl": {
+ "message": "此网页由 Service Worker 控制,但 `start_url` ({startUrl}) 不在 Service Worker 的控制范围内 ({scopeUrl})"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationNoManifest": {
+ "message": "此网页由 Service Worker 控制,但由于未提取任何清单,因此未找到 `start_url`。"
+ },
+ "lighthouse-core/audits/service-worker.js | explanationOutOfScope": {
+ "message": "此来源有一个或多个 Service Worker,但网页 ({pageUrl}) 不在控制范围内。"
+ },
+ "lighthouse-core/audits/service-worker.js | failureTitle": {
+ "message": "无法注册用于控制网页和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/service-worker.js | title": {
+ "message": "注册用于控制网页和 `start_url` 的 Service Worker"
+ },
+ "lighthouse-core/audits/splash-screen.js | description": {
+ "message": "选定主题的启动画面可确保用户在从主屏幕中启动您应用时获得优质体验。[了解详情](https://web.dev/splash-screen)。"
+ },
+ "lighthouse-core/audits/splash-screen.js | failureTitle": {
+ "message": "未针对自定义启动画面进行配置"
+ },
+ "lighthouse-core/audits/splash-screen.js | title": {
+ "message": "已针对自定义启动画面进行配置"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | description": {
+ "message": "可以为浏览器地址栏设置与您的网站相契合的主题背景。[了解详情](https://web.dev/themed-omnibox)。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | failureTitle": {
+ "message": "没有为地址栏设置主题背景颜色。"
+ },
+ "lighthouse-core/audits/themed-omnibox.js | title": {
+ "message": "为地址栏设置主题背景颜色。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": {
+ "message": "主线程拦截时间"
+ },
+ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": {
+ "message": "第三方"
+ },
+ "lighthouse-core/audits/third-party-summary.js | description": {
+ "message": "第三方代码可能会显著影响加载性能。请限制冗余第三方提供商的数量,并尝试在页面完成主要加载后再加载第三方代码。[了解详情](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/)。"
+ },
+ "lighthouse-core/audits/third-party-summary.js | displayValue": {
+ "message": "第三方代码将主线程阻止了 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/third-party-summary.js | failureTitle": {
+ "message": "降低第三方代码的影响"
+ },
+ "lighthouse-core/audits/third-party-summary.js | title": {
+ "message": "第三方使用"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | description": {
+ "message": "首字节显示前的耗时表明了服务器发出响应的时间。[了解详情](https://web.dev/time-to-first-byte)。"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | displayValue": {
+ "message": "根文档花费了 {timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | failureTitle": {
+ "message": "缩短服务器响应用时 (TTFB)"
+ },
+ "lighthouse-core/audits/time-to-first-byte.js | title": {
+ "message": "服务器响应用时较短 (TTFB)"
+ },
+ "lighthouse-core/audits/user-timings.js | columnDuration": {
+ "message": "时长"
+ },
+ "lighthouse-core/audits/user-timings.js | columnStartTime": {
+ "message": "开始时间"
+ },
+ "lighthouse-core/audits/user-timings.js | columnType": {
+ "message": "类型"
+ },
+ "lighthouse-core/audits/user-timings.js | description": {
+ "message": "建议使用 User Timing API 检测您的应用,从而衡量应用在关键用户体验中的实际性能。[了解详情](https://web.dev/user-timings)。"
+ },
+ "lighthouse-core/audits/user-timings.js | displayValue": {
+ "message": "{itemCount,plural, =1{1 项 User Timing 结果}other{# 项 User Timing 结果}}"
+ },
+ "lighthouse-core/audits/user-timings.js | title": {
+ "message": "User Timing 标记和测量结果"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | crossoriginWarning": {
+ "message": "发现了“{securityOrigin}”的预连接 <link>,但浏览器未使用该连接。请检查并确保您正确地使用了 `crossorigin` 属性。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | description": {
+ "message": "建议添加 `preconnect` 或 `dns-prefetch` 资源提示,以尽早与重要的第三方来源建立连接。[了解详情](https://web.dev/uses-rel-preconnect)。"
+ },
+ "lighthouse-core/audits/uses-rel-preconnect.js | title": {
+ "message": "预先连接到必要的来源"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | crossoriginWarning": {
+ "message": "发现了“{preloadURL}”的预加载 <link>,但浏览器未使用该链接。请检查并确保您正确地使用了 `crossorigin` 属性。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | description": {
+ "message": "建议使用 `<link rel=preload>` 来优先提取当前在网页加载后期请求的资源。[了解详情](https://web.dev/uses-rel-preload)。"
+ },
+ "lighthouse-core/audits/uses-rel-preload.js | title": {
+ "message": "预加载关键请求"
+ },
+ "lighthouse-core/audits/viewport.js | description": {
+ "message": "添加 `<meta name=\"viewport\">` 标记以针对移动设备屏幕优化您的应用。[了解详情](https://web.dev/viewport)。"
+ },
+ "lighthouse-core/audits/viewport.js | explanationNoTag": {
+ "message": "未找到任何 `<meta name=\"viewport\">` 标记"
+ },
+ "lighthouse-core/audits/viewport.js | failureTitle": {
+ "message": "没有包含 `width` 或 `initial-scale` 的 `<meta name=\"viewport\">` 标记"
+ },
+ "lighthouse-core/audits/viewport.js | title": {
+ "message": "具有包含 `width` 或 `initial-scale` 的 `<meta name=\"viewport\">` 标记"
+ },
+ "lighthouse-core/audits/without-javascript.js | description": {
+ "message": "您的应用应该在 JavaScript 被禁用时显示一些内容,哪怕只是向用户显示一则警告(告知其必须启用 JavaScript 才能使用该应用)。[了解详情](https://web.dev/without-javascript)。"
+ },
+ "lighthouse-core/audits/without-javascript.js | explanation": {
+ "message": "网页正文应该能在其脚本不可用时呈现一些内容。"
+ },
+ "lighthouse-core/audits/without-javascript.js | failureTitle": {
+ "message": "不提供在 JavaScript 未启用时显示的后备内容"
+ },
+ "lighthouse-core/audits/without-javascript.js | title": {
+ "message": "包含一些 JavaScript 未启用时显示的内容"
+ },
+ "lighthouse-core/audits/works-offline.js | description": {
+ "message": "如果您想构建渐进式 Web 应用,不妨考虑使用 Service Worker,以确保您的应用可离线工作。[了解详情](https://web.dev/works-offline)。"
+ },
+ "lighthouse-core/audits/works-offline.js | failureTitle": {
+ "message": "当前网页在离线时没有响应,并返回 200"
+ },
+ "lighthouse-core/audits/works-offline.js | title": {
+ "message": "当前网页即使在离线时也能成功做出响应,并返回 200"
+ },
+ "lighthouse-core/audits/works-offline.js | warningNoLoad": {
+ "message": "由于您的测试网址 ({requested}) 已重定向到“{final}”,因此该网页可能无法离线加载。请尝试直接测试另一个网址。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupDescription": {
+ "message": "这些提示旨在帮助改进 ARIA 在您的应用内的使用情况,从而改善辅助技术(例如屏幕阅读器)用户的体验。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAriaGroupTitle": {
+ "message": "ARIA"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupDescription": {
+ "message": "这提示旨在为音频和视频提供替代内容。这或许能改善听障用户或视障用户的体验。"
+ },
+ "lighthouse-core/config/default-config.js | a11yAudioVideoGroupTitle": {
+ "message": "音频和视频"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupDescription": {
+ "message": "这些条目突出显示了常见的无障碍功能最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | a11yBestPracticesGroupTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryDescription": {
+ "message": "这些检查会突出显示可[改进您网络应用的无障碍功能](https://developers.google.com/web/fundamentals/accessibility)的提示。系统只能自动检测到一小部分无障碍功能问题,因此您最好也手动测试一下。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryManualDescription": {
+ "message": "这些条目旨在检查自动化测试工具未涵盖的方面。如需了解详情,请参阅有关如何[执行无障碍功能审查](https://developers.google.com/web/fundamentals/accessibility/how-to-review)的指南。"
+ },
+ "lighthouse-core/config/default-config.js | a11yCategoryTitle": {
+ "message": "无障碍"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupDescription": {
+ "message": "这些提示旨在帮助改进您的内容的易读性。"
+ },
+ "lighthouse-core/config/default-config.js | a11yColorContrastGroupTitle": {
+ "message": "对比度"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupDescription": {
+ "message": "这些提示旨在让不同语言区域中的用户能够更好地解读您的内容。"
+ },
+ "lighthouse-core/config/default-config.js | a11yLanguageGroupTitle": {
+ "message": "国际化和本地化"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupDescription": {
+ "message": "这些提示旨在帮助改进您的应用内控件的语义。这可以改善辅助技术(例如屏幕阅读器)用户的体验。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNamesLabelsGroupTitle": {
+ "message": "名称和标签"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupDescription": {
+ "message": "这些提示旨在改进您应用中的键盘导航。"
+ },
+ "lighthouse-core/config/default-config.js | a11yNavigationGroupTitle": {
+ "message": "导航"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupDescription": {
+ "message": "这些提示旨在改善使用辅助技术(例如屏幕阅读器)查看表格数据或列表数据的体验。"
+ },
+ "lighthouse-core/config/default-config.js | a11yTablesListsVideoGroupTitle": {
+ "message": "表格和列表"
+ },
+ "lighthouse-core/config/default-config.js | bestPracticesCategoryTitle": {
+ "message": "最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupDescription": {
+ "message": "性能预算为您的网站的性能设置了标准。"
+ },
+ "lighthouse-core/config/default-config.js | budgetsGroupTitle": {
+ "message": "预算"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupDescription": {
+ "message": "详细了解您的应用的性能。这些数字不会[直接影响](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)性能得分。"
+ },
+ "lighthouse-core/config/default-config.js | diagnosticsGroupTitle": {
+ "message": "诊断结果"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupDescription": {
+ "message": "像素在屏幕上的呈现速度是性能的最重要方面。关键指标:首次内容绘制时间、首次有效绘制时间"
+ },
+ "lighthouse-core/config/default-config.js | firstPaintImprovementsGroupTitle": {
+ "message": "改进首次绘制"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupDescription": {
+ "message": "这些建议可以帮助您提高网页加载速度。它们不会[直接影响](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)性能得分。"
+ },
+ "lighthouse-core/config/default-config.js | loadOpportunitiesGroupTitle": {
+ "message": "优化建议"
+ },
+ "lighthouse-core/config/default-config.js | metricGroupTitle": {
+ "message": "指标"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupDescription": {
+ "message": "改善整体的加载体验,使该网页响应迅速且可尽快投入使用。关键指标:可交互前的耗时、速度指数"
+ },
+ "lighthouse-core/config/default-config.js | overallImprovementsGroupTitle": {
+ "message": "整体改进"
+ },
+ "lighthouse-core/config/default-config.js | performanceCategoryTitle": {
+ "message": "性能"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryDescription": {
+ "message": "此类检查会验证渐进式 Web 应用的各个方面。[了解详情](https://developers.google.com/web/progressive-web-apps/checklist)。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryManualDescription": {
+ "message": "基准 [PWA 核对清单](https://developers.google.com/web/progressive-web-apps/checklist)要求必须进行此类检查,但 Lighthouse 不会自动进行此类检查。它们不会影响您的得分,但您必须手动对其进行验证。"
+ },
+ "lighthouse-core/config/default-config.js | pwaCategoryTitle": {
+ "message": "渐进式 Web 应用"
+ },
+ "lighthouse-core/config/default-config.js | pwaFastReliableGroupTitle": {
+ "message": "快速且可靠"
+ },
+ "lighthouse-core/config/default-config.js | pwaInstallableGroupTitle": {
+ "message": "可安装"
+ },
+ "lighthouse-core/config/default-config.js | pwaOptimizedGroupTitle": {
+ "message": "优化 PWA"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryDescription": {
+ "message": "这些检查可确保您的页面已经过优化,有利于其在搜索引擎结果中的排名。不在 Lighthouse 检查范围内的其他因素可能会影响您的搜索排名。[了解详情](https://support.google.com/webmasters/answer/35769)。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryManualDescription": {
+ "message": "请在您的网站上运行这些额外的验证程序,以检查其他 SEO 最佳做法。"
+ },
+ "lighthouse-core/config/default-config.js | seoCategoryTitle": {
+ "message": "SEO"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupDescription": {
+ "message": "请确保您的 HTML 格式正确,以便抓取工具更好地了解您的应用的内容。"
+ },
+ "lighthouse-core/config/default-config.js | seoContentGroupTitle": {
+ "message": "内容最佳做法"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupDescription": {
+ "message": "若想让您的应用显示在搜索结果中,您需要先授权抓取工具访问该应用。"
+ },
+ "lighthouse-core/config/default-config.js | seoCrawlingGroupTitle": {
+ "message": "抓取和编入索引"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupDescription": {
+ "message": "请确保您的网页适合移动设备,以便用户无需进行缩放即可轻松阅读内容页面。[了解详情](https://developers.google.com/search/mobile-sites/)。"
+ },
+ "lighthouse-core/config/default-config.js | seoMobileGroupTitle": {
+ "message": "适合移动设备"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": {
+ "message": "缓存 TTL"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnLocation": {
+ "message": "位置"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnName": {
+ "message": "名称"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnRequests": {
+ "message": "请求"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnResourceType": {
+ "message": "资源类型"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnSize": {
+ "message": "大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTimeSpent": {
+ "message": "花费的时间"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnTransferSize": {
+ "message": "传输文件大小"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnURL": {
+ "message": "网址"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedBytes": {
+ "message": "可能达到的节省程度"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | columnWastedMs": {
+ "message": "可能达到的节省程度"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueByteSavings": {
+ "message": "有望节省 {wastedBytes, number, bytes} KB"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | displayValueMsSavings": {
+ "message": "有望节省 {wastedMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | documentResourceType": {
+ "message": "文档"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | fontResourceType": {
+ "message": "字体"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | imageResourceType": {
+ "message": "图片"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | mediaResourceType": {
+ "message": "媒体"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | ms": {
+ "message": "{timeInMs, number, milliseconds} 毫秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": {
+ "message": "其他"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": {
+ "message": "脚本"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | seconds": {
+ "message": "{timeInMs, number, seconds} 秒"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | stylesheetResourceType": {
+ "message": "样式表"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | thirdPartyResourceType": {
+ "message": "第三方"
+ },
+ "lighthouse-core/lib/i18n/i18n.js | totalResourceType": {
+ "message": "总计"
+ },
+ "lighthouse-core/lib/lh-error.js | badTraceRecording": {
+ "message": "在您加载的网页上录制跟踪记录时发生了错误。请重新运行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | criTimeout": {
+ "message": "等待调试程序协议初次连接时超时。"
+ },
+ "lighthouse-core/lib/lh-error.js | didntCollectScreenshots": {
+ "message": "Chrome 在网页加载期间未收集任何屏幕截图。请确保网页上有可见的内容,然后尝试重新运行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | dnsFailure": {
+ "message": "DNS 服务器无法解析所提供的网域。"
+ },
+ "lighthouse-core/lib/lh-error.js | erroredRequiredArtifact": {
+ "message": "必需的 {artifactName} 收集器出现错误:{errorMessage}"
+ },
+ "lighthouse-core/lib/lh-error.js | internalChromeError": {
+ "message": "发生了内部 Chrome 错误。请重新启动 Chrome,然后尝试重新运行 Lighthouse。"
+ },
+ "lighthouse-core/lib/lh-error.js | missingRequiredArtifact": {
+ "message": "必需的 {artifactName} 收集器未运行。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailed": {
+ "message": "Lighthouse 无法可靠地加载您请求的页面。请确保您测试的网址正确无误并且服务器可正确响应所有请求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedHung": {
+ "message": "Lighthouse 无法可靠地加载您请求的网址,因为页面已停止响应。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInsecure": {
+ "message": "您提供的网址缺少有效的安全证书。{securityMessages}"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedInterstitial": {
+ "message": "Chrome 阻止了带有插页式广告的网页加载。请确保您测试的网址正确无误并且服务器可正确响应所有请求。"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithDetails": {
+ "message": "Lighthouse 无法可靠地加载您请求的页面。请确保您测试的网址正确无误并且服务器可正确响应所有请求。(详细信息:{errorDetails})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadFailedWithStatusCode": {
+ "message": "Lighthouse 无法可靠地加载您请求的页面。请确保您测试的网址正确无误并且服务器可正确响应所有请求。(状态代码:{statusCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | pageLoadTookTooLong": {
+ "message": "您的网页加载时间过长。请按照报告中给出的提示缩短网页加载时间,然后尝试重新运行 Lighthouse。({errorCode})"
+ },
+ "lighthouse-core/lib/lh-error.js | protocolTimeout": {
+ "message": "等待 DevTools 协议响应的用时超出了分配的时间。(方法:{protocolMethod})"
+ },
+ "lighthouse-core/lib/lh-error.js | requestContentTimeout": {
+ "message": "提取资源内容的用时超出了分配的时间"
+ },
+ "lighthouse-core/lib/lh-error.js | urlInvalid": {
+ "message": "您提供的网址似乎无效。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | auditGroupExpandTooltip": {
+ "message": "显示审核结果"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcInitialNavigation": {
+ "message": "初始导航"
+ },
+ "lighthouse-core/report/html/renderer/util.js | crcLongestDurationLabel": {
+ "message": "关键路径延迟时间上限:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorLabel": {
+ "message": "出错了!"
+ },
+ "lighthouse-core/report/html/renderer/util.js | errorMissingAuditInfo": {
+ "message": "报告错误:没有任何审核信息"
+ },
+ "lighthouse-core/report/html/renderer/util.js | labDataTitle": {
+ "message": "实验室数据"
+ },
+ "lighthouse-core/report/html/renderer/util.js | lsPerformanceCategoryDescription": {
+ "message": "[Lighthouse](https://developers.google.com/web/tools/lighthouse/) 使用模拟的移动网络对当前页面进行的分析。这些值都是估算值,且可能会因时而异。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | manualAuditsGroupTitle": {
+ "message": "待手动检查的其他项"
+ },
+ "lighthouse-core/report/html/renderer/util.js | notApplicableAuditsGroupTitle": {
+ "message": "不适用"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunityResourceColumnLabel": {
+ "message": "优化建议"
+ },
+ "lighthouse-core/report/html/renderer/util.js | opportunitySavingsColumnLabel": {
+ "message": "有望节省的总时间(估算值)"
+ },
+ "lighthouse-core/report/html/renderer/util.js | passedAuditsGroupTitle": {
+ "message": "已通过的审核"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetCollapseButtonLabel": {
+ "message": "收起代码段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | snippetExpandButtonLabel": {
+ "message": "展开代码段"
+ },
+ "lighthouse-core/report/html/renderer/util.js | thirdPartyResourcesLabel": {
+ "message": "显示第三方资源"
+ },
+ "lighthouse-core/report/html/renderer/util.js | toplevelWarningsMessage": {
+ "message": "此次 Lighthouse 运行并不顺利,原因如下:"
+ },
+ "lighthouse-core/report/html/renderer/util.js | varianceDisclaimer": {
+ "message": "这些值都是估算值,且可能会因时而异。性能得分[仅基于这些指标](https://github.com/GoogleChrome/lighthouse/blob/d2ec9ffbb21de9ad1a0f86ed24575eda32c796f0/docs/scoring.md#how-are-the-scores-weighted)。"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningAuditsGroupTitle": {
+ "message": "已顺利通过审核,但有警告消息"
+ },
+ "lighthouse-core/report/html/renderer/util.js | warningHeader": {
+ "message": "警告: "
+ },
+ "stack-packs/packs/wordpress.js | efficient_animated_content": {
+ "message": "建议您将 GIF 上传到可让其作为 HTML5 视频嵌入的服务。"
+ },
+ "stack-packs/packs/wordpress.js | offscreen_images": {
+ "message": "安装[延迟加载 WordPress 插件](https://wordpress.org/plugins/search/lazy+load/)以便能够推迟加载所有的屏幕外图片,或者改用可提供该功能的主题背景。另外,建议您使用 [AMP 插件](https://wordpress.org/plugins/amp/)。"
+ },
+ "stack-packs/packs/wordpress.js | render_blocking_resources": {
+ "message": "有很多 WordPress 插件可帮助您[内嵌重要资源](https://wordpress.org/plugins/search/critical+css/)或[推迟加载不太重要的资源](https://wordpress.org/plugins/search/defer+css+javascript/)。请注意,这些插件提供的优化可能会导致您的主题背景或插件的功能中断,因此您可能需要更改代码。"
+ },
+ "stack-packs/packs/wordpress.js | time_to_first_byte": {
+ "message": "主题背景、插件和服务器规范都会影响服务器响应用时。建议您查找更优化的主题背景、仔细选择所需的优化插件并/或升级您的服务器。"
+ },
+ "stack-packs/packs/wordpress.js | total_byte_weight": {
+ "message": "建议您在博文列表中显示摘录(例如,通过“更多”标签)、减少给定页面上显示的博文的数量、将您的长博文拆分成多个页面或者使用插件延迟加载评论。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_css": {
+ "message": "很多 [WordPress 插件](https://wordpress.org/plugins/search/minify+css/)都可通过连接、削减和压缩您的样式来加快您网站的加载速度。另外,您最好使用编译流程预先执行此缩减操作(如果可能的话)。"
+ },
+ "stack-packs/packs/wordpress.js | unminified_javascript": {
+ "message": "很多 [WordPress 插件](https://wordpress.org/plugins/search/minify+javascript/)都可通过连接、削减和压缩您的脚本来加快您网站的加载速度。另外,您最好使用编译流程预先执行此缩减操作(如果可能的话)。"
+ },
+ "stack-packs/packs/wordpress.js | unused_css_rules": {
+ "message": "建议您减少或改变会在您网页中加载未使用的 CSS 的 [WordPress 插件](https://wordpress.org/plugins/)的数量。若想找出会添加无关 CSS 的插件,请尝试在 Chrome DevTools 中运行[代码覆盖率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)测试。您可根据样式表网址找出导致问题的主题背景/插件。请留意在列表中包含多个以大量红色显示代码覆盖率的样式表的插件。插件应该只将网页中确实用到的样式表加入队列。"
+ },
+ "stack-packs/packs/wordpress.js | unused_javascript": {
+ "message": "建议您减少或改变会在您网页中加载未使用的 JavaScript 的 [WordPress 插件](https://wordpress.org/plugins/)的数量。若想找出会添加无关 JS 的插件,请尝试在 Chrome DevTools 中运行[代码覆盖率](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)测试。您可根据脚本网址找出导致问题的主题背景/插件。请留意在列表中包含多个以大量红色显示代码覆盖率的脚本的插件。插件应只将网页中确实用到的脚本加入队列。"
+ },
+ "stack-packs/packs/wordpress.js | uses_long_cache_ttl": {
+ "message": "了解 [WordPress 中的浏览器缓存](https://codex.wordpress.org/WordPress_Optimization#Browser_Caching)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_optimized_images": {
+ "message": "建议您使用[图片优化 WordPress 插件](https://wordpress.org/plugins/search/optimize+images/),以在不影响图片质量的前提下压缩图片大小。"
+ },
+ "stack-packs/packs/wordpress.js | uses_responsive_images": {
+ "message": "直接通过[媒体库](https://codex.wordpress.org/Media_Library_Screen)上传图片,以确保能够按要求的尺寸提供图片,然后从媒体库插入图片,或使用图片微件来确保采用最佳的图片尺寸(包括适用于自适应断点的尺寸)。避免使用 `Full Size` 图片,除非有足够的可用空间。[了解详情](https://codex.wordpress.org/Inserting_Images_into_Posts_and_Pages#Image_Size)。"
+ },
+ "stack-packs/packs/wordpress.js | uses_text_compression": {
+ "message": "您可以在网络服务器配置中启用文本压缩。"
+ },
+ "stack-packs/packs/wordpress.js | uses_webp_images": {
+ "message": "建议您使用可自动将您上传的图片转换为最佳格式的[插件](https://wordpress.org/plugins/search/convert+webp/)或服务。"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/axe_core_test_runner/AxeCoreTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/axe_core_test_runner/AxeCoreTestRunner.js
index 9f13497aafb..d82e840e74f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/axe_core_test_runner/AxeCoreTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/axe_core_test_runner/AxeCoreTestRunner.js
@@ -17,6 +17,15 @@ const DISABLED_RULES = {
// Slow rules
// https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#section-4-performance
// (more performance investigation) https://github.com/dequelabs/axe-core/pull/1503
+ 'aria-hidden-focus': {
+ enabled: false,
+ },
+ 'aria-input-field-name': {
+ enabled: false,
+ },
+ 'aria-toggle-field-name': {
+ enabled: false,
+ },
'color-contrast': {
enabled: false,
},
@@ -29,18 +38,57 @@ const DISABLED_RULES = {
enabled: false,
},
// Low value rules
+ 'aria-allowed-role': {
+ enabled: false,
+ },
+ 'aria-dpub-role-fallback': {
+ enabled: false,
+ },
'audio-caption': {
enabled: false,
},
'blink': {
enabled: false,
},
+ 'form-field-multiple-labels': {
+ enabled: false,
+ },
+ 'frame-tested': {
+ enabled: false,
+ },
'html-has-lang': {
enabled: false,
},
'html-lang-valid': {
enabled: false,
},
+ 'html-xml-lang-mismatch': {
+ enabled: false,
+ },
+ 'landmark-banner-is-top-level': {
+ enabled: false,
+ },
+ 'landmark-complementary-is-top-level': {
+ enabled: false,
+ },
+ 'landmark-contentinfo-is-top-level': {
+ enabled: false,
+ },
+ 'landmark-main-is-top-level': {
+ enabled: false,
+ },
+ 'landmark-no-duplicate-banner': {
+ enabled: false,
+ },
+ 'landmark-no-duplicate-contentinfo': {
+ enabled: false,
+ },
+ 'landmark-one-main': {
+ enabled: false,
+ },
+ 'landmark-unique': {
+ enabled: false,
+ },
'marquee': {
enabled: false,
},
@@ -56,6 +104,12 @@ const DISABLED_RULES = {
'object-alt': {
enabled: false,
},
+ 'page-has-heading-one': {
+ enabled: false,
+ },
+ 'scrollable-region-focusable': {
+ enabled: false,
+ },
'video-caption': {
enabled: false,
},
@@ -76,7 +130,8 @@ const DEFAULT_CONFIG = {
// This should be removed after axe-core is updated.
// See: https://github.com/dequelabs/axe-core/issues/1457
{id: 'aria-valid-attr', options: ['aria-placeholder']}
- ]
+ ],
+ runOnly: {type: 'tags', values: {include: ['wcag2a', 'best-practice'], exclude: ['experimental']}}
};
AxeCoreTestRunner.processAxeResult = function(violations) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/BlackboxManager.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/BlackboxManager.js
index 0e6aab390f3..0952be4b9fb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/BlackboxManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/BlackboxManager.js
@@ -5,7 +5,7 @@
* @unrestricted
* @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>}
*/
-Bindings.BlackboxManager = class {
+export default class BlackboxManager {
/**
* @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
*/
@@ -63,8 +63,9 @@ Bindings.BlackboxManager = class {
}
_clearCacheIfNeeded() {
- if (this._isBlackboxedURLCache.size > 1024)
+ if (this._isBlackboxedURLCache.size > 1024) {
this._isBlackboxedURLCache.clear();
+ }
}
/**
@@ -75,8 +76,9 @@ Bindings.BlackboxManager = class {
const regexPatterns = Common.moduleSetting('skipStackFramesPattern').getAsArray();
const patterns = /** @type {!Array<string>} */ ([]);
for (const item of regexPatterns) {
- if (!item.disabled && item.pattern)
+ if (!item.disabled && item.pattern) {
patterns.push(item.pattern);
+ }
}
return debuggerModel.setBlackboxPatterns(patterns);
}
@@ -88,8 +90,9 @@ Bindings.BlackboxManager = class {
isBlackboxedUISourceCode(uiSourceCode) {
const projectType = uiSourceCode.project().type();
const isContentScript = projectType === Workspace.projectTypes.ContentScripts;
- if (isContentScript && Common.moduleSetting('skipContentScripts').get())
+ if (isContentScript && Common.moduleSetting('skipContentScripts').get()) {
return true;
+ }
const url = this._uiSourceCodeURL(uiSourceCode);
return url ? this.isBlackboxedURL(url) : false;
}
@@ -100,10 +103,12 @@ Bindings.BlackboxManager = class {
* @return {boolean}
*/
isBlackboxedURL(url, isContentScript) {
- if (this._isBlackboxedURLCache.has(url))
+ if (this._isBlackboxedURLCache.has(url)) {
return !!this._isBlackboxedURLCache.get(url);
- if (isContentScript && Common.moduleSetting('skipContentScripts').get())
+ }
+ if (isContentScript && Common.moduleSetting('skipContentScripts').get()) {
return true;
+ }
const regex = Common.moduleSetting('skipStackFramesPattern').asRegExp();
const isBlackboxed = (regex && regex.test(url)) || false;
this._isBlackboxedURLCache.set(url, isBlackboxed);
@@ -134,16 +139,18 @@ Bindings.BlackboxManager = class {
*/
async _updateScriptRanges(script, sourceMap) {
let hasBlackboxedMappings = false;
- if (!Bindings.blackboxManager.isBlackboxedURL(script.sourceURL, script.isContentScript()))
+ if (!Bindings.blackboxManager.isBlackboxedURL(script.sourceURL, script.isContentScript())) {
hasBlackboxedMappings = sourceMap ? sourceMap.sourceURLs().some(url => this.isBlackboxedURL(url)) : false;
+ }
if (!hasBlackboxedMappings) {
- if (script[Bindings.BlackboxManager._blackboxedRanges] && await script.setBlackboxedRanges([]))
- delete script[Bindings.BlackboxManager._blackboxedRanges];
+ if (script[_blackboxedRanges] && await script.setBlackboxedRanges([])) {
+ delete script[_blackboxedRanges];
+ }
this._debuggerWorkspaceBinding.updateLocations(script);
return;
}
- const mappings = sourceMap.mappings();
+ const mappings = /** @type {!SDK.TextSourceMap} */ (sourceMap).mappings();
const newRanges = [];
let currentBlackboxed = false;
if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) {
@@ -157,9 +164,10 @@ Bindings.BlackboxManager = class {
}
}
- const oldRanges = script[Bindings.BlackboxManager._blackboxedRanges] || [];
- if (!isEqual(oldRanges, newRanges) && await script.setBlackboxedRanges(newRanges))
- script[Bindings.BlackboxManager._blackboxedRanges] = newRanges;
+ const oldRanges = script[_blackboxedRanges] || [];
+ if (!isEqual(oldRanges, newRanges) && await script.setBlackboxedRanges(newRanges)) {
+ script[_blackboxedRanges] = newRanges;
+ }
this._debuggerWorkspaceBinding.updateLocations(script);
/**
@@ -168,11 +176,13 @@ Bindings.BlackboxManager = class {
* @return {boolean}
*/
function isEqual(rangesA, rangesB) {
- if (rangesA.length !== rangesB.length)
+ if (rangesA.length !== rangesB.length) {
return false;
+ }
for (let i = 0; i < rangesA.length; ++i) {
- if (rangesA[i].lineNumber !== rangesB[i].lineNumber || rangesA[i].columnNumber !== rangesB[i].columnNumber)
+ if (rangesA[i].lineNumber !== rangesB[i].lineNumber || rangesA[i].columnNumber !== rangesB[i].columnNumber) {
return false;
+ }
}
return true;
}
@@ -200,8 +210,9 @@ Bindings.BlackboxManager = class {
*/
blackboxUISourceCode(uiSourceCode) {
const url = this._uiSourceCodeURL(uiSourceCode);
- if (url)
+ if (url) {
this._blackboxURL(url);
+ }
}
/**
@@ -209,8 +220,9 @@ Bindings.BlackboxManager = class {
*/
unblackboxUISourceCode(uiSourceCode) {
const url = this._uiSourceCodeURL(uiSourceCode);
- if (url)
+ if (url) {
this._unblackboxURL(url);
+ }
}
blackboxContentScripts() {
@@ -227,8 +239,9 @@ Bindings.BlackboxManager = class {
_blackboxURL(url) {
const regexPatterns = Common.moduleSetting('skipStackFramesPattern').getAsArray();
const regexValue = this._urlToRegExpString(url);
- if (!regexValue)
+ if (!regexValue) {
return;
+ }
let found = false;
for (let i = 0; i < regexPatterns.length; ++i) {
const item = regexPatterns[i];
@@ -238,8 +251,9 @@ Bindings.BlackboxManager = class {
break;
}
}
- if (!found)
+ if (!found) {
regexPatterns.push({pattern: regexValue});
+ }
Common.moduleSetting('skipStackFramesPattern').setAsArray(regexPatterns);
}
@@ -249,19 +263,22 @@ Bindings.BlackboxManager = class {
_unblackboxURL(url) {
let regexPatterns = Common.moduleSetting('skipStackFramesPattern').getAsArray();
const regexValue = Bindings.blackboxManager._urlToRegExpString(url);
- if (!regexValue)
+ if (!regexValue) {
return;
+ }
regexPatterns = regexPatterns.filter(function(item) {
return item.pattern !== regexValue;
});
for (let i = 0; i < regexPatterns.length; ++i) {
const item = regexPatterns[i];
- if (item.disabled)
+ if (item.disabled) {
continue;
+ }
try {
const regex = new RegExp(item.pattern);
- if (regex.test(url))
+ if (regex.test(url)) {
item.disabled = true;
+ }
} catch (e) {
}
}
@@ -276,13 +293,15 @@ Bindings.BlackboxManager = class {
for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)) {
promises.push(this._setBlackboxPatterns(debuggerModel));
const sourceMapManager = debuggerModel.sourceMapManager();
- for (const script of debuggerModel.scripts())
+ for (const script of debuggerModel.scripts()) {
promises.push(this._updateScriptRanges(script, sourceMapManager.sourceMapForClient(script)));
+ }
}
await Promise.all(promises);
const listeners = Array.from(this._listeners);
- for (const listener of listeners)
+ for (const listener of listeners) {
listener();
+ }
this._patternChangeFinishedForTests();
}
@@ -296,32 +315,49 @@ Bindings.BlackboxManager = class {
*/
_urlToRegExpString(url) {
const parsedURL = new Common.ParsedURL(url);
- if (parsedURL.isAboutBlank() || parsedURL.isDataURL())
+ if (parsedURL.isAboutBlank() || parsedURL.isDataURL()) {
return '';
- if (!parsedURL.isValid)
+ }
+ if (!parsedURL.isValid) {
return '^' + url.escapeForRegExp() + '$';
+ }
let name = parsedURL.lastPathComponent;
- if (name)
+ if (name) {
name = '/' + name;
- else if (parsedURL.folderPathComponents)
+ } else if (parsedURL.folderPathComponents) {
name = parsedURL.folderPathComponents + '/';
- if (!name)
+ }
+ if (!name) {
name = parsedURL.host;
- if (!name)
+ }
+ if (!name) {
return '';
+ }
const scheme = parsedURL.scheme;
let prefix = '';
if (scheme && scheme !== 'http' && scheme !== 'https') {
prefix = '^' + scheme + '://';
- if (scheme === 'chrome-extension')
+ if (scheme === 'chrome-extension') {
prefix += parsedURL.host + '\\b';
+ }
prefix += '.*';
}
return prefix + name.escapeForRegExp() + (url.endsWith(name) ? '$' : '\\b');
}
-};
+}
+
+export const _blackboxedRanges = Symbol('blackboxedRanged');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.BlackboxManager = BlackboxManager;
-Bindings.BlackboxManager._blackboxedRanges = Symbol('blackboxedRanged');
+Bindings.BlackboxManager._blackboxedRanges = _blackboxedRanges;
-/** @type {!Bindings.BlackboxManager} */
-Bindings.blackboxManager;
+/** @type {!BlackboxManager} */
+Bindings.blackboxManager; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/BreakpointManager.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/BreakpointManager.js
index 22527be29ac..6287949b87d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/BreakpointManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/BreakpointManager.js
@@ -30,7 +30,7 @@
/**
* @unrestricted
*/
-Bindings.BreakpointManager = class extends Common.Object {
+export default class BreakpointManager extends Common.Object {
/**
* @param {!Workspace.Workspace} workspace
* @param {!SDK.TargetManager} targetManager
@@ -38,14 +38,14 @@ Bindings.BreakpointManager = class extends Common.Object {
*/
constructor(workspace, targetManager, debuggerWorkspaceBinding) {
super();
- this._storage = new Bindings.BreakpointManager.Storage();
+ this._storage = new Storage();
this._workspace = workspace;
this._targetManager = targetManager;
this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
/** @type {!Map<!Workspace.UISourceCode, !Map<string, !Bindings.BreakpointManager.BreakpointLocation>>} */
this._breakpointsForUISourceCode = new Map();
- /** @type {!Map<string, !Bindings.BreakpointManager.Breakpoint>} */
+ /** @type {!Map<string, !Breakpoint>} */
this._breakpointByStorageId = new Map();
this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
@@ -58,8 +58,9 @@ Bindings.BreakpointManager = class extends Common.Object {
* @return {string}
*/
static _breakpointStorageId(url, lineNumber, columnNumber) {
- if (!url)
+ if (!url) {
return '';
+ }
return url + ':' + lineNumber + ':' + columnNumber;
}
@@ -69,8 +70,9 @@ Bindings.BreakpointManager = class extends Common.Object {
*/
copyBreakpoints(fromURL, toSourceCode) {
const breakpointItems = this._storage.breakpointItems(fromURL);
- for (const item of breakpointItems)
+ for (const item of breakpointItems) {
this.setBreakpoint(toSourceCode, item.lineNumber, item.columnNumber, item.condition, item.enabled);
+ }
}
/**
@@ -78,13 +80,15 @@ Bindings.BreakpointManager = class extends Common.Object {
*/
_restoreBreakpoints(uiSourceCode) {
const url = uiSourceCode.url();
- if (!url)
+ if (!url) {
return;
+ }
this._storage.mute();
const breakpointItems = this._storage.breakpointItems(url);
- for (const item of breakpointItems)
+ for (const item of breakpointItems) {
this._innerSetBreakpoint(uiSourceCode, item.lineNumber, item.columnNumber, item.condition, item.enabled);
+ }
this._storage.unmute();
}
@@ -102,7 +106,7 @@ Bindings.BreakpointManager = class extends Common.Object {
* @param {number} columnNumber
* @param {string} condition
* @param {boolean} enabled
- * @return {!Bindings.BreakpointManager.Breakpoint}
+ * @return {!Breakpoint}
*/
setBreakpoint(uiSourceCode, lineNumber, columnNumber, condition, enabled) {
let uiLocation = new Workspace.UILocation(uiSourceCode, lineNumber, columnNumber);
@@ -121,10 +125,10 @@ Bindings.BreakpointManager = class extends Common.Object {
* @param {number} columnNumber
* @param {string} condition
* @param {boolean} enabled
- * @return {!Bindings.BreakpointManager.Breakpoint}
+ * @return {!Breakpoint}
*/
_innerSetBreakpoint(uiSourceCode, lineNumber, columnNumber, condition, enabled) {
- const itemId = Bindings.BreakpointManager._breakpointStorageId(uiSourceCode.url(), lineNumber, columnNumber);
+ const itemId = BreakpointManager._breakpointStorageId(uiSourceCode.url(), lineNumber, columnNumber);
let breakpoint = this._breakpointByStorageId.get(itemId);
if (breakpoint) {
breakpoint._updateState(condition, enabled);
@@ -132,8 +136,7 @@ Bindings.BreakpointManager = class extends Common.Object {
breakpoint._updateBreakpoint();
return breakpoint;
}
- breakpoint = new Bindings.BreakpointManager.Breakpoint(
- this, uiSourceCode, uiSourceCode.url(), lineNumber, columnNumber, condition, enabled);
+ breakpoint = new Breakpoint(this, uiSourceCode, uiSourceCode.url(), lineNumber, columnNumber, condition, enabled);
this._breakpointByStorageId.set(itemId, breakpoint);
return breakpoint;
}
@@ -158,8 +161,9 @@ Bindings.BreakpointManager = class extends Common.Object {
const endLocations = Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(
uiSourceCode, textRange.endLine, textRange.endColumn);
const endLocationByModel = new Map();
- for (const location of endLocations)
+ for (const location of endLocations) {
endLocationByModel.set(location.debuggerModel, location);
+ }
let startLocation = null;
let endLocation = null;
for (const location of startLocations) {
@@ -170,15 +174,16 @@ Bindings.BreakpointManager = class extends Common.Object {
break;
}
}
- if (!startLocation || !endLocation)
+ if (!startLocation || !endLocation) {
return Promise.resolve([]);
+ }
return startLocation.debuggerModel
.getPossibleBreakpoints(startLocation, endLocation, /* restrictToFunction */ false)
.then(toUILocations.bind(this));
/**
- * @this {!Bindings.BreakpointManager}
+ * @this {!BreakpointManager}
* @param {!Array<!SDK.DebuggerModel.BreakLocation>} locations
* @return {!Array<!Workspace.UILocation>}
*/
@@ -186,13 +191,15 @@ Bindings.BreakpointManager = class extends Common.Object {
let sortedLocations = locations.map(location => this._debuggerWorkspaceBinding.rawLocationToUILocation(location));
sortedLocations = sortedLocations.filter(location => location && location.uiSourceCode === uiSourceCode);
sortedLocations.sort(Workspace.UILocation.comparator);
- if (!sortedLocations.length)
+ if (!sortedLocations.length) {
return [];
+ }
const result = [sortedLocations[0]];
let lastLocation = sortedLocations[0];
for (let i = 1; i < sortedLocations.length; ++i) {
- if (sortedLocations[i].id() === lastLocation.id())
+ if (sortedLocations[i].id() === lastLocation.id()) {
continue;
+ }
result.push(sortedLocations[i]);
lastLocation = sortedLocations[i];
}
@@ -214,23 +221,25 @@ Bindings.BreakpointManager = class extends Common.Object {
*/
allBreakpointLocations() {
let result = [];
- for (const breakpoints of this._breakpointsForUISourceCode.values())
+ for (const breakpoints of this._breakpointsForUISourceCode.values()) {
result = result.concat(Array.from(breakpoints.values()));
+ }
return result;
}
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
* @param {boolean} removeFromStorage
*/
_removeBreakpoint(breakpoint, removeFromStorage) {
- if (removeFromStorage)
+ if (removeFromStorage) {
this._storage._removeBreakpoint(breakpoint);
+ }
this._breakpointByStorageId.delete(breakpoint._breakpointStorageId());
}
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
* @param {!Workspace.UILocation} uiLocation
*/
_uiLocationAdded(breakpoint, uiLocation) {
@@ -241,48 +250,43 @@ Bindings.BreakpointManager = class extends Common.Object {
}
const breakpointLocation = {breakpoint: breakpoint, uiLocation: uiLocation};
breakpoints.set(uiLocation.id(), breakpointLocation);
- this.dispatchEventToListeners(Bindings.BreakpointManager.Events.BreakpointAdded, breakpointLocation);
+ this.dispatchEventToListeners(Events.BreakpointAdded, breakpointLocation);
}
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
* @param {!Workspace.UILocation} uiLocation
*/
_uiLocationRemoved(breakpoint, uiLocation) {
const breakpoints = this._breakpointsForUISourceCode.get(uiLocation.uiSourceCode);
- if (!breakpoints)
+ if (!breakpoints) {
return;
+ }
const breakpointLocation = breakpoints.get(uiLocation.id()) || null;
- if (!breakpointLocation)
+ if (!breakpointLocation) {
return;
+ }
breakpoints.delete(uiLocation.id());
- if (breakpoints.size === 0)
+ if (breakpoints.size === 0) {
this._breakpointsForUISourceCode.delete(uiLocation.uiSourceCode);
- this.dispatchEventToListeners(
- Bindings.BreakpointManager.Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
+ }
+ this.dispatchEventToListeners(Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
}
-};
+}
/** @enum {symbol} */
-Bindings.BreakpointManager.Events = {
+export const Events = {
BreakpointAdded: Symbol('breakpoint-added'),
BreakpointRemoved: Symbol('breakpoint-removed')
};
-/** @typedef {{
- * breakpoint: !Bindings.BreakpointManager.Breakpoint,
- * uiLocation: !Workspace.UILocation
- * }}
- */
-Bindings.BreakpointManager.BreakpointLocation;
-
/**
* @unrestricted
* @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>}
*/
-Bindings.BreakpointManager.Breakpoint = class {
+export class Breakpoint {
/**
- * @param {!Bindings.BreakpointManager} breakpointManager
+ * @param {!BreakpointManager} breakpointManager
* @param {!Workspace.UISourceCode} primaryUISourceCode
* @param {string} url
* @param {number} lineNumber
@@ -306,7 +310,7 @@ Bindings.BreakpointManager.Breakpoint = class {
/** @type {boolean} */ this._isRemoved;
this._currentState = null;
- /** @type {!Map.<!SDK.DebuggerModel, !Bindings.BreakpointManager.ModelBreakpoint>}*/
+ /** @type {!Map.<!SDK.DebuggerModel, !ModelBreakpoint>}*/
this._modelBreakpoints = new Map();
this._updateState(condition, enabled);
this.setPrimaryUISourceCode(primaryUISourceCode);
@@ -314,10 +318,12 @@ Bindings.BreakpointManager.Breakpoint = class {
}
refreshInDebugger() {
- if (this._isRemoved)
+ if (this._isRemoved) {
return;
- for (const breakpoint of this._modelBreakpoints.values())
+ }
+ for (const breakpoint of this._modelBreakpoints.values()) {
breakpoint._refreshBreakpoint();
+ }
}
/**
@@ -326,8 +332,7 @@ Bindings.BreakpointManager.Breakpoint = class {
*/
modelAdded(debuggerModel) {
const debuggerWorkspaceBinding = this._breakpointManager._debuggerWorkspaceBinding;
- this._modelBreakpoints.set(
- debuggerModel, new Bindings.BreakpointManager.ModelBreakpoint(debuggerModel, this, debuggerWorkspaceBinding));
+ this._modelBreakpoints.set(debuggerModel, new ModelBreakpoint(debuggerModel, this, debuggerWorkspaceBinding));
}
/**
@@ -344,14 +349,17 @@ Bindings.BreakpointManager.Breakpoint = class {
* @param {?Workspace.UISourceCode} primaryUISourceCode
*/
setPrimaryUISourceCode(primaryUISourceCode) {
- if (this._uiLocations.size === 0 && this._defaultUILocation)
+ if (this._uiLocations.size === 0 && this._defaultUILocation) {
this._breakpointManager._uiLocationRemoved(this, this._defaultUILocation);
- if (primaryUISourceCode)
+ }
+ if (primaryUISourceCode) {
this._defaultUILocation = primaryUISourceCode.uiLocation(this._lineNumber, this._columnNumber);
- else
+ } else {
this._defaultUILocation = null;
- if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved)
+ }
+ if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved) {
this._breakpointManager._uiLocationAdded(this, this._defaultUILocation);
+ }
}
/**
@@ -379,10 +387,12 @@ Bindings.BreakpointManager.Breakpoint = class {
* @param {!Workspace.UILocation} uiLocation
*/
_uiLocationAdded(uiLocation) {
- if (this._isRemoved)
+ if (this._isRemoved) {
return;
- if (this._uiLocations.size === 0 && this._defaultUILocation)
+ }
+ if (this._uiLocations.size === 0 && this._defaultUILocation) {
this._breakpointManager._uiLocationRemoved(this, this._defaultUILocation);
+ }
this._uiLocations.add(uiLocation);
this._breakpointManager._uiLocationAdded(this, uiLocation);
}
@@ -393,8 +403,9 @@ Bindings.BreakpointManager.Breakpoint = class {
_uiLocationRemoved(uiLocation) {
this._uiLocations.delete(uiLocation);
this._breakpointManager._uiLocationRemoved(this, uiLocation);
- if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved)
+ if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved) {
this._breakpointManager._uiLocationAdded(this, this._defaultUILocation);
+ }
}
/**
@@ -430,8 +441,9 @@ Bindings.BreakpointManager.Breakpoint = class {
* @param {boolean} enabled
*/
_updateState(condition, enabled) {
- if (this._enabled === enabled && this._condition === condition)
+ if (this._enabled === enabled && this._condition === condition) {
return;
+ }
this._enabled = enabled;
this._condition = condition;
this._breakpointManager._storage._updateBreakpoint(this);
@@ -439,13 +451,16 @@ Bindings.BreakpointManager.Breakpoint = class {
}
_updateBreakpoint() {
- if (this._uiLocations.size === 0 && this._defaultUILocation)
+ if (this._uiLocations.size === 0 && this._defaultUILocation) {
this._breakpointManager._uiLocationRemoved(this, this._defaultUILocation);
- if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved)
+ }
+ if (this._uiLocations.size === 0 && this._defaultUILocation && !this._isRemoved) {
this._breakpointManager._uiLocationAdded(this, this._defaultUILocation);
+ }
const modelBreakpoints = this._modelBreakpoints.valuesArray();
- for (let i = 0; i < modelBreakpoints.length; ++i)
+ for (let i = 0; i < modelBreakpoints.length; ++i) {
modelBreakpoints[i]._scheduleUpdateInDebugger();
+ }
}
/**
@@ -469,24 +484,25 @@ Bindings.BreakpointManager.Breakpoint = class {
* @return {string}
*/
_breakpointStorageId() {
- return Bindings.BreakpointManager._breakpointStorageId(this._url, this._lineNumber, this._columnNumber);
+ return BreakpointManager._breakpointStorageId(this._url, this._lineNumber, this._columnNumber);
}
_resetLocations() {
this.setPrimaryUISourceCode(null);
const modelBreakpoints = this._modelBreakpoints.valuesArray();
- for (let i = 0; i < modelBreakpoints.length; ++i)
+ for (let i = 0; i < modelBreakpoints.length; ++i) {
modelBreakpoints[i]._resetLocations();
+ }
}
-};
+}
/**
* @unrestricted
*/
-Bindings.BreakpointManager.ModelBreakpoint = class {
+export class ModelBreakpoint {
/**
* @param {!SDK.DebuggerModel} debuggerModel
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
* @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
*/
constructor(debuggerModel, breakpoint, debuggerWorkspaceBinding) {
@@ -506,13 +522,15 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
this._isUpdating = false;
this._cancelCallback = false;
this._currentState = null;
- if (this._debuggerModel.debuggerEnabled())
+ if (this._debuggerModel.debuggerEnabled()) {
this._scheduleUpdateInDebugger();
+ }
}
_resetLocations() {
- for (const uiLocation of this._uiLocations.values())
+ for (const uiLocation of this._uiLocations.values()) {
this._breakpoint._uiLocationRemoved(uiLocation);
+ }
this._uiLocations.clear();
this._liveLocations.disposeAll();
@@ -542,8 +560,9 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
_scriptDiverged() {
const uiLocation = this._breakpoint._defaultUILocation;
const uiSourceCode = uiLocation ? uiLocation.uiSourceCode : null;
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return false;
+ }
const scriptFile = this._debuggerWorkspaceBinding.scriptFile(uiSourceCode, this._debuggerModel);
return !!scriptFile && scriptFile.hasDivergedFromVM();
}
@@ -577,21 +596,19 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
} else if (debuggerLocation) {
const script = debuggerLocation.script();
if (script.sourceURL) {
- newState = new Bindings.BreakpointManager.Breakpoint.State(
+ newState = new Breakpoint.State(
script.sourceURL, null, null, debuggerLocation.lineNumber, debuggerLocation.columnNumber, condition);
} else {
- newState = new Bindings.BreakpointManager.Breakpoint.State(
+ newState = new Breakpoint.State(
null, script.scriptId, script.hash, debuggerLocation.lineNumber, debuggerLocation.columnNumber, condition);
}
} else if (this._breakpoint._currentState && this._breakpoint._currentState.url) {
const position = this._breakpoint._currentState;
- newState = new Bindings.BreakpointManager.Breakpoint.State(
- position.url, null, null, position.lineNumber, position.columnNumber, condition);
+ newState = new Breakpoint.State(position.url, null, null, position.lineNumber, position.columnNumber, condition);
} else if (uiSourceCode) {
- newState = new Bindings.BreakpointManager.Breakpoint.State(
- uiSourceCode.url(), null, null, lineNumber, columnNumber, condition);
+ newState = new Breakpoint.State(uiSourceCode.url(), null, null, lineNumber, columnNumber, condition);
}
- if (this._debuggerId && Bindings.BreakpointManager.Breakpoint.State.equals(newState, this._currentState)) {
+ if (this._debuggerId && Breakpoint.State.equals(newState, this._currentState)) {
callback();
return;
}
@@ -618,15 +635,17 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
result = await this._debuggerModel.setBreakpointInAnonymousScript(
newState.scriptId, newState.scriptHash, newState.lineNumber, newState.columnNumber, newState.condition);
}
- if (result && result.breakpointId)
+ if (result && result.breakpointId) {
this._didSetBreakpointInDebugger(callback, result.breakpointId, result.locations);
- else
+ } else {
this._didSetBreakpointInDebugger(callback, null, []);
+ }
}
async _refreshBreakpoint() {
- if (!this._debuggerId)
+ if (!this._debuggerId) {
return;
+ }
this._resetLocations();
await this._debuggerModel.removeBreakpoint(this._debuggerId);
this._didRemoveFromDebugger();
@@ -655,8 +674,9 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
this._debuggerId = breakpointId;
this._debuggerModel.addBreakpointListener(this._debuggerId, this._breakpointResolved, this);
for (let i = 0; i < locations.length; ++i) {
- if (!this._addResolvedLocation(locations[i]))
+ if (!this._addResolvedLocation(locations[i])) {
break;
+ }
}
callback();
}
@@ -684,14 +704,16 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
*/
_locationUpdated(liveLocation) {
const oldUILocation = this._uiLocations.get(liveLocation);
- if (oldUILocation)
+ if (oldUILocation) {
this._breakpoint._uiLocationRemoved(oldUILocation);
+ }
let uiLocation = liveLocation.uiLocation();
if (uiLocation) {
const breakpointLocation = this._breakpoint._breakpointManager.findBreakpoint(uiLocation);
- if (breakpointLocation && breakpointLocation.uiLocation !== breakpointLocation.breakpoint._defaultUILocation)
+ if (breakpointLocation && breakpointLocation.uiLocation !== breakpointLocation.breakpoint._defaultUILocation) {
uiLocation = null;
+ }
}
if (uiLocation) {
@@ -708,8 +730,9 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
*/
_addResolvedLocation(location) {
const uiLocation = this._debuggerWorkspaceBinding.rawLocationToUILocation(location);
- if (!uiLocation)
+ if (!uiLocation) {
return false;
+ }
const breakpointLocation = this._breakpoint._breakpointManager.findBreakpoint(uiLocation);
if (breakpointLocation && breakpointLocation.breakpoint !== this._breakpoint) {
// location clash
@@ -721,13 +744,15 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
}
_cleanUpAfterDebuggerIsGone() {
- if (this._isUpdating)
+ if (this._isUpdating) {
this._cancelCallback = true;
+ }
this._resetLocations();
this._currentState = null;
- if (this._debuggerId)
+ if (this._debuggerId) {
this._didRemoveFromDebugger();
+ }
}
_removeEventListeners() {
@@ -736,9 +761,9 @@ Bindings.BreakpointManager.ModelBreakpoint = class {
this._debuggerModel.removeEventListener(
SDK.DebuggerModel.Events.DebuggerWasEnabled, this._scheduleUpdateInDebugger, this);
}
-};
+}
-Bindings.BreakpointManager.Breakpoint.State = class {
+Breakpoint.State = class {
/**
* @param {?string} url
* @param {?string} scriptId
@@ -757,13 +782,14 @@ Bindings.BreakpointManager.Breakpoint.State = class {
}
/**
- * @param {?Bindings.BreakpointManager.Breakpoint.State|undefined} stateA
- * @param {?Bindings.BreakpointManager.Breakpoint.State|undefined} stateB
+ * @param {?Breakpoint.State|undefined} stateA
+ * @param {?Breakpoint.State|undefined} stateB
* @return {boolean}
*/
static equals(stateA, stateB) {
- if (!stateA || !stateB)
+ if (!stateA || !stateB) {
return false;
+ }
return stateA.url === stateB.url && stateA.scriptId === stateB.scriptId &&
stateA.scriptHash === stateB.scriptHash && stateA.lineNumber === stateB.lineNumber &&
stateA.columnNumber === stateB.columnNumber && stateA.condition === stateB.condition;
@@ -771,16 +797,15 @@ Bindings.BreakpointManager.Breakpoint.State = class {
};
-Bindings.BreakpointManager.Storage = class {
+export class Storage {
constructor() {
this._setting = Common.settings.createLocalSetting('breakpoints', []);
- /** @type {!Map<string, !Bindings.BreakpointManager.Storage.Item>} */
+ /** @type {!Map<string, !Storage.Item>} */
this._breakpoints = new Map();
- const items = /** @type {!Array<!Bindings.BreakpointManager.Storage.Item>} */ (this._setting.get());
+ const items = /** @type {!Array<!Storage.Item>} */ (this._setting.get());
for (const item of items) {
item.columnNumber = item.columnNumber || 0;
- this._breakpoints.set(
- Bindings.BreakpointManager._breakpointStorageId(item.url, item.lineNumber, item.columnNumber), item);
+ this._breakpoints.set(BreakpointManager._breakpointStorageId(item.url, item.lineNumber, item.columnNumber), item);
}
/** @type {boolean|undefined} */ this._muted;
}
@@ -795,28 +820,30 @@ Bindings.BreakpointManager.Storage = class {
/**
* @param {string} url
- * @return {!Array<!Bindings.BreakpointManager.Storage.Item>}
+ * @return {!Array<!Storage.Item>}
*/
breakpointItems(url) {
return Array.from(this._breakpoints.values()).filter(item => item.url === url);
}
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
*/
_updateBreakpoint(breakpoint) {
- if (this._muted || !breakpoint._breakpointStorageId())
+ if (this._muted || !breakpoint._breakpointStorageId()) {
return;
- this._breakpoints.set(breakpoint._breakpointStorageId(), new Bindings.BreakpointManager.Storage.Item(breakpoint));
+ }
+ this._breakpoints.set(breakpoint._breakpointStorageId(), new Storage.Item(breakpoint));
this._save();
}
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
*/
_removeBreakpoint(breakpoint) {
- if (this._muted)
+ if (this._muted) {
return;
+ }
this._breakpoints.delete(breakpoint._breakpointStorageId());
this._save();
}
@@ -824,14 +851,14 @@ Bindings.BreakpointManager.Storage = class {
_save() {
this._setting.set(Array.from(this._breakpoints.values()));
}
-};
+}
/**
* @unrestricted
*/
-Bindings.BreakpointManager.Storage.Item = class {
+Storage.Item = class {
/**
- * @param {!Bindings.BreakpointManager.Breakpoint} breakpoint
+ * @param {!Breakpoint} breakpoint
*/
constructor(breakpoint) {
this.url = breakpoint._url;
@@ -842,5 +869,33 @@ Bindings.BreakpointManager.Storage.Item = class {
}
};
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.BreakpointManager = BreakpointManager;
+
+/** @enum {symbol} */
+Bindings.BreakpointManager.Events = Events;
+
+/** @constructor */
+Bindings.BreakpointManager.Breakpoint = Breakpoint;
+
+/** @constructor */
+Bindings.BreakpointManager.ModelBreakpoint = ModelBreakpoint;
+
+/** @constructor */
+Bindings.BreakpointManager.Storage = Storage;
+
+/** @typedef {{
+ * breakpoint: !Breakpoint,
+ * uiLocation: !Workspace.UILocation
+ * }}
+ */
+Bindings.BreakpointManager.BreakpointLocation;
+
/** @type {!Bindings.BreakpointManager} */
-Bindings.breakpointManager;
+Bindings.breakpointManager; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/CSSWorkspaceBinding.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/CSSWorkspaceBinding.js
index e91167457bd..8d5ab20232e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/CSSWorkspaceBinding.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/CSSWorkspaceBinding.js
@@ -5,7 +5,7 @@
/**
* @implements {SDK.SDKModelObserver<!SDK.CSSModel>}
*/
-Bindings.CSSWorkspaceBinding = class {
+export default class CSSWorkspaceBinding {
/**
* @param {!SDK.TargetManager} targetManager
* @param {!Workspace.Workspace} workspace
@@ -13,9 +13,9 @@ Bindings.CSSWorkspaceBinding = class {
constructor(targetManager, workspace) {
this._workspace = workspace;
- /** @type {!Map.<!SDK.CSSModel, !Bindings.CSSWorkspaceBinding.ModelInfo>} */
+ /** @type {!Map.<!SDK.CSSModel, !ModelInfo>} */
this._modelToInfo = new Map();
- /** @type {!Array<!Bindings.CSSWorkspaceBinding.SourceMapping>} */
+ /** @type {!Array<!SourceMapping>} */
this._sourceMappings = [];
targetManager.observeModels(SDK.CSSModel, this);
}
@@ -25,7 +25,7 @@ Bindings.CSSWorkspaceBinding = class {
* @param {!SDK.CSSModel} cssModel
*/
modelAdded(cssModel) {
- this._modelToInfo.set(cssModel, new Bindings.CSSWorkspaceBinding.ModelInfo(cssModel, this._workspace));
+ this._modelToInfo.set(cssModel, new ModelInfo(cssModel, this._workspace));
}
/**
@@ -48,7 +48,7 @@ Bindings.CSSWorkspaceBinding = class {
* @param {!SDK.CSSLocation} rawLocation
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
- * @return {!Bindings.CSSWorkspaceBinding.LiveLocation}
+ * @return {!LiveLocation}
*/
createLiveLocation(rawLocation, updateDelegate, locationPool) {
return this._modelToInfo.get(rawLocation.cssModel())._createLiveLocation(rawLocation, updateDelegate, locationPool);
@@ -61,15 +61,18 @@ Bindings.CSSWorkspaceBinding = class {
*/
propertyUILocation(cssProperty, forName) {
const style = cssProperty.ownerStyle;
- if (!style || style.type !== SDK.CSSStyleDeclaration.Type.Regular || !style.styleSheetId)
+ if (!style || style.type !== SDK.CSSStyleDeclaration.Type.Regular || !style.styleSheetId) {
return null;
+ }
const header = style.cssModel().styleSheetHeaderForId(style.styleSheetId);
- if (!header)
+ if (!header) {
return null;
+ }
const range = forName ? cssProperty.nameRange() : cssProperty.valueRange();
- if (!range)
+ if (!range) {
return null;
+ }
const lineNumber = range.startLine;
const columnNumber = range.startColumn;
@@ -85,8 +88,9 @@ Bindings.CSSWorkspaceBinding = class {
rawLocationToUILocation(rawLocation) {
for (let i = this._sourceMappings.length - 1; i >= 0; --i) {
const uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
- if (uiLocation)
+ if (uiLocation) {
return uiLocation;
+ }
}
return this._modelToInfo.get(rawLocation.cssModel())._rawLocationToUILocation(rawLocation);
}
@@ -98,43 +102,45 @@ Bindings.CSSWorkspaceBinding = class {
uiLocationToRawLocations(uiLocation) {
for (let i = this._sourceMappings.length - 1; i >= 0; --i) {
const rawLocations = this._sourceMappings[i].uiLocationToRawLocations(uiLocation);
- if (rawLocations.length)
+ if (rawLocations.length) {
return rawLocations;
+ }
}
const rawLocations = [];
- for (const modelInfo of this._modelToInfo.values())
+ for (const modelInfo of this._modelToInfo.values()) {
rawLocations.pushAll(modelInfo._uiLocationToRawLocations(uiLocation));
+ }
return rawLocations;
}
/**
- * @param {!Bindings.CSSWorkspaceBinding.SourceMapping} sourceMapping
+ * @param {!SourceMapping} sourceMapping
*/
addSourceMapping(sourceMapping) {
this._sourceMappings.push(sourceMapping);
}
-};
+}
/**
* @interface
*/
-Bindings.CSSWorkspaceBinding.SourceMapping = function() {};
-
-Bindings.CSSWorkspaceBinding.SourceMapping.prototype = {
+export class SourceMapping {
/**
* @param {!SDK.CSSLocation} rawLocation
* @return {?Workspace.UILocation}
*/
- rawLocationToUILocation(rawLocation) {},
+ rawLocationToUILocation(rawLocation) {
+ }
/**
* @param {!Workspace.UILocation} uiLocation
* @return {!Array<!SDK.CSSLocation>}
*/
- uiLocationToRawLocations(uiLocation) {},
-};
+ uiLocationToRawLocations(uiLocation) {
+ }
+}
-Bindings.CSSWorkspaceBinding.ModelInfo = class {
+export class ModelInfo {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Workspace.Workspace} workspace
@@ -149,20 +155,20 @@ Bindings.CSSWorkspaceBinding.ModelInfo = class {
const sourceMapManager = cssModel.sourceMapManager();
this._sassSourceMapping = new Bindings.SASSSourceMapping(cssModel.target(), sourceMapManager, workspace);
- /** @type {!Multimap<!SDK.CSSStyleSheetHeader, !Bindings.CSSWorkspaceBinding.LiveLocation>} */
- this._locations = new Multimap();
- /** @type {!Multimap<string, !Bindings.CSSWorkspaceBinding.LiveLocation>} */
- this._unboundLocations = new Multimap();
+ /** @type {!Platform.Multimap<!SDK.CSSStyleSheetHeader, !LiveLocation>} */
+ this._locations = new Platform.Multimap();
+ /** @type {!Platform.Multimap<string, !LiveLocation>} */
+ this._unboundLocations = new Platform.Multimap();
}
/**
* @param {!SDK.CSSLocation} rawLocation
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
- * @return {!Bindings.CSSWorkspaceBinding.LiveLocation}
+ * @return {!LiveLocation}
*/
_createLiveLocation(rawLocation, updateDelegate, locationPool) {
- const location = new Bindings.CSSWorkspaceBinding.LiveLocation(rawLocation, this, updateDelegate, locationPool);
+ const location = new LiveLocation(rawLocation, this, updateDelegate, locationPool);
const header = rawLocation.header();
if (header) {
location._header = header;
@@ -175,21 +181,23 @@ Bindings.CSSWorkspaceBinding.ModelInfo = class {
}
/**
- * @param {!Bindings.CSSWorkspaceBinding.LiveLocation} location
+ * @param {!LiveLocation} location
*/
_disposeLocation(location) {
- if (location._header)
+ if (location._header) {
this._locations.delete(location._header, location);
- else
+ } else {
this._unboundLocations.delete(location._url, location);
+ }
}
/**
* @param {!SDK.CSSStyleSheetHeader} header
*/
_updateLocations(header) {
- for (const location of this._locations.get(header))
+ for (const location of this._locations.get(header)) {
location.update();
+ }
}
/**
@@ -197,8 +205,9 @@ Bindings.CSSWorkspaceBinding.ModelInfo = class {
*/
_styleSheetAdded(event) {
const header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
- if (!header.sourceURL)
+ if (!header.sourceURL) {
return;
+ }
for (const location of this._unboundLocations.get(header.sourceURL)) {
location._header = header;
@@ -238,10 +247,15 @@ Bindings.CSSWorkspaceBinding.ModelInfo = class {
* @return {!Array<!SDK.CSSLocation>}
*/
_uiLocationToRawLocations(uiLocation) {
- const rawLocations = this._sassSourceMapping.uiLocationToRawLocations(uiLocation);
- if (rawLocations.length)
+ let rawLocations = this._sassSourceMapping.uiLocationToRawLocations(uiLocation);
+ if (rawLocations.length) {
+ return rawLocations;
+ }
+ rawLocations = this._stylesSourceMapping.uiLocationToRawLocations(uiLocation);
+ if (rawLocations.length) {
return rawLocations;
- return this._stylesSourceMapping.uiLocationToRawLocations(uiLocation);
+ }
+ return Bindings.resourceMapping.uiLocationToCSSLocations(uiLocation);
}
_dispose() {
@@ -249,15 +263,15 @@ Bindings.CSSWorkspaceBinding.ModelInfo = class {
this._stylesSourceMapping.dispose();
this._sassSourceMapping.dispose();
}
-};
+}
/**
* @unrestricted
*/
-Bindings.CSSWorkspaceBinding.LiveLocation = class extends Bindings.LiveLocationWithPool {
+export class LiveLocation extends Bindings.LiveLocationWithPool {
/**
* @param {!SDK.CSSLocation} rawLocation
- * @param {!Bindings.CSSWorkspaceBinding.ModelInfo} info
+ * @param {!ModelInfo} info
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
*/
@@ -275,8 +289,9 @@ Bindings.CSSWorkspaceBinding.LiveLocation = class extends Bindings.LiveLocationW
* @return {?Workspace.UILocation}
*/
uiLocation() {
- if (!this._header)
+ if (!this._header) {
return null;
+ }
const rawLocation = new SDK.CSSLocation(this._header, this._lineNumber, this._columnNumber);
return Bindings.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
}
@@ -296,9 +311,30 @@ Bindings.CSSWorkspaceBinding.LiveLocation = class extends Bindings.LiveLocationW
isBlackboxed() {
return false;
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.CSSWorkspaceBinding = CSSWorkspaceBinding;
+
+/** @interface */
+Bindings.CSSWorkspaceBinding.SourceMapping = SourceMapping;
+
+/** @interface */
+Bindings.SourceMapping = SourceMapping;
+
+/** @constructor */
+Bindings.CSSWorkspaceBinding.ModelInfo = ModelInfo;
+
+/** @constructor */
+Bindings.CSSWorkspaceBinding.LiveLocation = LiveLocation;
/**
- * @type {!Bindings.CSSWorkspaceBinding}
+ * @type {!CSSWorkspaceBinding}
*/
Bindings.cssWorkspaceBinding;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/CompilerScriptMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/CompilerScriptMapping.js
index 44c4d83c6df..dc2f398de3f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/CompilerScriptMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/CompilerScriptMapping.js
@@ -31,7 +31,7 @@
* @implements {Bindings.DebuggerSourceMapping}
* @unrestricted
*/
-Bindings.CompilerScriptMapping = class {
+export default class CompilerScriptMapping {
/**
* @param {!SDK.DebuggerModel} debuggerModel
* @param {!Workspace.Workspace} workspace
@@ -52,9 +52,9 @@ Bindings.CompilerScriptMapping = class {
Bindings.NetworkProject.setTargetForProject(this._regularProject, target);
Bindings.NetworkProject.setTargetForProject(this._contentScriptsProject, target);
- /** @type {!Map<string, !Bindings.CompilerScriptMapping.Binding>} */
+ /** @type {!Map<string, !Binding>} */
this._regularBindings = new Map();
- /** @type {!Map<string, !Bindings.CompilerScriptMapping.Binding>} */
+ /** @type {!Map<string, !Binding>} */
this._contentScriptsBindings = new Map();
/** @type {!Map<!SDK.Script, !Workspace.UISourceCode>} */
@@ -102,9 +102,10 @@ Bindings.CompilerScriptMapping = class {
* @return {?string}
*/
static uiSourceCodeOrigin(uiSourceCode) {
- const sourceMap = uiSourceCode[Bindings.CompilerScriptMapping._sourceMapSymbol];
- if (!sourceMap)
+ const sourceMap = uiSourceCode[_sourceMapSymbol];
+ if (!sourceMap) {
return null;
+ }
return sourceMap.compiledURL();
}
@@ -115,9 +116,11 @@ Bindings.CompilerScriptMapping = class {
mapsToSourceCode(rawLocation) {
const script = rawLocation.script();
const sourceMap = script ? this._sourceMapManager.sourceMapForClient(script) : null;
- if (!sourceMap)
+ if (!sourceMap) {
return true;
- return !!sourceMap.findEntry(rawLocation.lineNumber, rawLocation.columnNumber);
+ }
+ const entry = sourceMap.findEntry(rawLocation.lineNumber, rawLocation.columnNumber);
+ return !!entry && entry.lineNumber === rawLocation.lineNumber && entry.columnNumber === rawLocation.columnNumber;
}
/**
@@ -136,28 +139,34 @@ Bindings.CompilerScriptMapping = class {
*/
rawLocationToUILocation(rawLocation) {
const script = rawLocation.script();
- if (!script)
+ if (!script) {
return null;
+ }
const lineNumber = rawLocation.lineNumber - script.lineOffset;
let columnNumber = rawLocation.columnNumber;
- if (!lineNumber)
+ if (!lineNumber) {
columnNumber -= script.columnOffset;
+ }
const stubUISourceCode = this._stubUISourceCodes.get(script);
- if (stubUISourceCode)
+ if (stubUISourceCode) {
return new Workspace.UILocation(stubUISourceCode, lineNumber, columnNumber);
+ }
const sourceMap = this._sourceMapManager.sourceMapForClient(script);
- if (!sourceMap)
+ if (!sourceMap) {
return null;
+ }
const entry = sourceMap.findEntry(lineNumber, columnNumber);
- if (!entry || !entry.sourceURL)
+ if (!entry || !entry.sourceURL) {
return null;
+ }
const uiSourceCode = script.isContentScript() ? this._contentScriptsProject.uiSourceCodeForURL(entry.sourceURL) :
this._regularProject.uiSourceCodeForURL(entry.sourceURL);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return null;
+ }
return uiSourceCode.uiLocation(
/** @type {number} */ (entry.sourceLineNumber), /** @type {number} */ (entry.sourceColumnNumber));
}
@@ -170,15 +179,18 @@ Bindings.CompilerScriptMapping = class {
* @return {!Array<!SDK.DebuggerModel.Location>}
*/
uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
- const sourceMap = uiSourceCode[Bindings.CompilerScriptMapping._sourceMapSymbol];
- if (!sourceMap)
+ const sourceMap = uiSourceCode[_sourceMapSymbol];
+ if (!sourceMap) {
return [];
+ }
const scripts = this._sourceMapManager.clientsForSourceMap(sourceMap);
- if (!scripts.length)
+ if (!scripts.length) {
return [];
+ }
const entry = sourceMap.sourceLineMapping(uiSourceCode.url(), lineNumber, columnNumber);
- if (!entry)
+ if (!entry) {
return [];
+ }
return scripts.map(
script => this._debuggerModel.createRawLocation(
script, entry.lineNumber + script.lineOffset,
@@ -225,15 +237,16 @@ Bindings.CompilerScriptMapping = class {
*/
_sourceMapDetached(event) {
const script = /** @type {!SDK.Script} */ (event.data.client);
- const frameId = script[Bindings.CompilerScriptMapping._frameIdSymbol];
+ const frameId = script[_frameIdSymbol];
const sourceMap = /** @type {!SDK.SourceMap} */ (event.data.sourceMap);
const bindings = script.isContentScript() ? this._contentScriptsBindings : this._regularBindings;
for (const sourceURL of sourceMap.sourceURLs()) {
const binding = bindings.get(sourceURL);
if (binding) {
binding.removeSourceMap(sourceMap, frameId);
- if (!binding._uiSourceCode)
+ if (!binding._uiSourceCode) {
bindings.delete(sourceURL);
+ }
}
}
this._debuggerWorkspaceBinding.updateLocations(script);
@@ -259,13 +272,13 @@ Bindings.CompilerScriptMapping = class {
*/
_populateSourceMapSources(script, sourceMap) {
const frameId = Bindings.frameIdForScript(script);
- script[Bindings.CompilerScriptMapping._frameIdSymbol] = frameId;
+ script[_frameIdSymbol] = frameId;
const project = script.isContentScript() ? this._contentScriptsProject : this._regularProject;
const bindings = script.isContentScript() ? this._contentScriptsBindings : this._regularBindings;
for (const sourceURL of sourceMap.sourceURLs()) {
let binding = bindings.get(sourceURL);
if (!binding) {
- binding = new Bindings.CompilerScriptMapping.Binding(project, sourceURL);
+ binding = new Binding(project, sourceURL);
bindings.set(sourceURL, binding);
}
binding.addSourceMap(sourceMap, frameId);
@@ -274,15 +287,15 @@ Bindings.CompilerScriptMapping = class {
}
/**
- * @override
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {number} lineNumber
* @return {boolean}
*/
static uiLineHasMapping(uiSourceCode, lineNumber) {
- const sourceMap = uiSourceCode[Bindings.CompilerScriptMapping._sourceMapSymbol];
- if (!sourceMap)
+ const sourceMap = uiSourceCode[_sourceMapSymbol];
+ if (!sourceMap) {
return true;
+ }
return !!sourceMap.sourceLineMapping(uiSourceCode.url(), lineNumber, 0);
}
@@ -292,13 +305,12 @@ Bindings.CompilerScriptMapping = class {
this._contentScriptsProject.dispose();
this._stubProject.dispose();
}
-};
-
-Bindings.CompilerScriptMapping._frameIdSymbol = Symbol('Bindings.CompilerScriptMapping._frameIdSymbol');
-Bindings.CompilerScriptMapping._sourceMapSymbol = Symbol('Bindings.CompilerScriptMapping._sourceMapSymbol');
+}
+export const _frameIdSymbol = Symbol('_frameIdSymbol');
+export const _sourceMapSymbol = Symbol('_sourceMapSymbol');
-Bindings.CompilerScriptMapping.Binding = class {
+export class Binding {
/**
* @param {!Bindings.ContentProviderBasedProject} project
* @param {string} url
@@ -318,12 +330,13 @@ Bindings.CompilerScriptMapping.Binding = class {
*/
_recreateUISourceCodeIfNeeded(frameId) {
const sourceMap = this._referringSourceMaps.peekLast();
- if (this._activeSourceMap === sourceMap)
+ if (this._activeSourceMap === sourceMap) {
return;
+ }
this._activeSourceMap = sourceMap;
const newUISourceCode = this._project.createUISourceCode(this._url, Common.resourceTypes.SourceMapScript);
- newUISourceCode[Bindings.CompilerScriptMapping._sourceMapSymbol] = sourceMap;
+ newUISourceCode[_sourceMapSymbol] = sourceMap;
const contentProvider = sourceMap.sourceContentProvider(this._url, Common.resourceTypes.SourceMapScript);
const mimeType = Common.ResourceType.mimeFromURL(this._url) || 'text/javascript';
const embeddedContent = sourceMap.embeddedContentByURL(this._url);
@@ -345,8 +358,9 @@ Bindings.CompilerScriptMapping.Binding = class {
* @param {string} frameId
*/
addSourceMap(sourceMap, frameId) {
- if (this._uiSourceCode)
+ if (this._uiSourceCode) {
Bindings.NetworkProject.addFrameAttribution(this._uiSourceCode, frameId);
+ }
this._referringSourceMaps.push(sourceMap);
this._recreateUISourceCodeIfNeeded(frameId);
}
@@ -359,8 +373,9 @@ Bindings.CompilerScriptMapping.Binding = class {
Bindings.NetworkProject.removeFrameAttribution(
/** @type {!Workspace.UISourceCode} */ (this._uiSourceCode), frameId);
const lastIndex = this._referringSourceMaps.lastIndexOf(sourceMap);
- if (lastIndex !== -1)
+ if (lastIndex !== -1) {
this._referringSourceMaps.splice(lastIndex, 1);
+ }
if (!this._referringSourceMaps.length) {
this._project.removeFile(this._uiSourceCode.url());
this._uiSourceCode = null;
@@ -368,4 +383,19 @@ Bindings.CompilerScriptMapping.Binding = class {
this._recreateUISourceCodeIfNeeded(frameId);
}
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.CompilerScriptMapping = CompilerScriptMapping;
+
+Bindings.CompilerScriptMapping._frameIdSymbol = _frameIdSymbol;
+Bindings.CompilerScriptMapping._sourceMapSymbol = _sourceMapSymbol;
+
+/** @constructor */
+Bindings.CompilerScriptMapping.Binding = Binding;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ContentProviderBasedProject.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ContentProviderBasedProject.js
index bf59485de59..1df00cf8e2e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ContentProviderBasedProject.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ContentProviderBasedProject.js
@@ -32,7 +32,7 @@
* @implements {Workspace.Project}
* @unrestricted
*/
-Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
+export default class ContentProviderBasedProject extends Workspace.ProjectStore {
/**
* @param {!Workspace.Workspace} workspace
* @param {string} id
@@ -51,13 +51,18 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
/**
* @override
* @param {!Workspace.UISourceCode} uiSourceCode
- * @param {function(?string,boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(uiSourceCode, callback) {
+ async requestFileContent(uiSourceCode) {
const contentProvider = this._contentProviders[uiSourceCode.url()];
- (async () => {
- callback(await contentProvider.requestContent(), await contentProvider.contentEncoded());
- })();
+ try {
+ const [content, isEncoded] =
+ await Promise.all([contentProvider.requestContent(), contentProvider.contentEncoded()]);
+ return {content: content.content, isEncoded, error: content.error};
+ } catch (err) {
+ // TODO(rob.paveza): CRBug 1013683 - Consider propagating exceptions full-stack
+ return {isEncoded: false, error: err ? String(err) : ls`Unknown error loading file`};
+ }
}
/**
@@ -74,7 +79,7 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
* @return {!Promise<?Workspace.UISourceCodeMetadata>}
*/
requestMetadata(uiSourceCode) {
- return Promise.resolve(uiSourceCode[Bindings.ContentProviderBasedProject._metadata]);
+ return Promise.resolve(uiSourceCode[_metadata]);
}
/**
@@ -115,7 +120,7 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
* @return {string}
*/
mimeType(uiSourceCode) {
- return /** @type {string} */ (uiSourceCode[Bindings.ContentProviderBasedProject._mimeType]);
+ return /** @type {string} */ (uiSourceCode[_mimeType]);
}
/**
@@ -139,7 +144,7 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
/**
* @param {boolean} success
* @param {string=} newName
- * @this {Bindings.ContentProviderBasedProject}
+ * @this {ContentProviderBasedProject}
*/
function innerCallback(success, newName) {
if (success && newName) {
@@ -240,7 +245,7 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
/**
* @param {string} path
- * @this {Bindings.ContentProviderBasedProject}
+ * @this {ContentProviderBasedProject}
*/
async function searchInContent(path) {
const provider = this._contentProviders[path];
@@ -252,8 +257,9 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
break;
}
}
- if (allMatchesFound)
+ if (allMatchesFound) {
result.push(path);
+ }
progress.worked(1);
}
}
@@ -273,9 +279,9 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
* @param {string} mimeType
*/
addUISourceCodeWithProvider(uiSourceCode, contentProvider, metadata, mimeType) {
- uiSourceCode[Bindings.ContentProviderBasedProject._mimeType] = mimeType;
+ uiSourceCode[_mimeType] = mimeType;
this._contentProviders[uiSourceCode.url()] = contentProvider;
- uiSourceCode[Bindings.ContentProviderBasedProject._metadata] = metadata;
+ uiSourceCode[_metadata] = metadata;
this.addUISourceCode(uiSourceCode);
}
@@ -309,7 +315,19 @@ Bindings.ContentProviderBasedProject = class extends Workspace.ProjectStore {
this._contentProviders = {};
this.removeProject();
}
-};
+}
+
+export const _metadata = Symbol('ContentProviderBasedProject.Metadata');
+export const _mimeType = Symbol('ContentProviderBasedProject.MimeType');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.ContentProviderBasedProject = ContentProviderBasedProject;
-Bindings.ContentProviderBasedProject._metadata = Symbol('ContentProviderBasedProject.Metadata');
-Bindings.ContentProviderBasedProject._mimeType = Symbol('Bindings.ContentProviderBasedProject._mimeType');
+Bindings.ContentProviderBasedProject._metadata = _metadata;
+Bindings.ContentProviderBasedProject._mimeType = _mimeType;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/DebuggerWorkspaceBinding.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
index b3bba8a2325..02149ad72dc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/DebuggerWorkspaceBinding.js
@@ -6,7 +6,7 @@
* @unrestricted
* @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>}
*/
-Bindings.DebuggerWorkspaceBinding = class {
+export default class DebuggerWorkspaceBinding {
/**
* @param {!SDK.TargetManager} targetManager
* @param {!Workspace.Workspace} workspace
@@ -14,10 +14,10 @@ Bindings.DebuggerWorkspaceBinding = class {
constructor(targetManager, workspace) {
this._workspace = workspace;
- /** @type {!Array<!Bindings.DebuggerSourceMapping>} */
+ /** @type {!Array<!DebuggerSourceMapping>} */
this._sourceMappings = [];
- /** @type {!Map.<!SDK.DebuggerModel, !Bindings.DebuggerWorkspaceBinding.ModelData>} */
+ /** @type {!Map.<!SDK.DebuggerModel, !ModelData>} */
this._debuggerModelToData = new Map();
targetManager.addModelListener(
SDK.DebuggerModel, SDK.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, this);
@@ -27,7 +27,7 @@ Bindings.DebuggerWorkspaceBinding = class {
}
/**
- * @param {!Bindings.DebuggerSourceMapping} sourceMapping
+ * @param {!DebuggerSourceMapping} sourceMapping
*/
addSourceMapping(sourceMapping) {
this._sourceMappings.push(sourceMapping);
@@ -38,7 +38,7 @@ Bindings.DebuggerWorkspaceBinding = class {
* @param {!SDK.DebuggerModel} debuggerModel
*/
modelAdded(debuggerModel) {
- this._debuggerModelToData.set(debuggerModel, new Bindings.DebuggerWorkspaceBinding.ModelData(debuggerModel, this));
+ this._debuggerModelToData.set(debuggerModel, new ModelData(debuggerModel, this));
}
/**
@@ -56,15 +56,16 @@ Bindings.DebuggerWorkspaceBinding = class {
*/
updateLocations(script) {
const modelData = this._debuggerModelToData.get(script.debuggerModel);
- if (modelData)
+ if (modelData) {
modelData._updateLocations(script);
+ }
}
/**
* @param {!SDK.DebuggerModel.Location} rawLocation
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
- * @return {!Bindings.DebuggerWorkspaceBinding.Location}
+ * @return {!Location}
*/
createLiveLocation(rawLocation, updateDelegate, locationPool) {
const modelData = this._debuggerModelToData.get(rawLocation.script().debuggerModel);
@@ -79,8 +80,7 @@ Bindings.DebuggerWorkspaceBinding = class {
*/
createStackTraceTopFrameLiveLocation(rawLocations, updateDelegate, locationPool) {
console.assert(rawLocations.length);
- const location = new Bindings.DebuggerWorkspaceBinding.StackTraceTopFrameLocation(
- rawLocations, this, updateDelegate, locationPool);
+ const location = new StackTraceTopFrameLocation(rawLocations, this, updateDelegate, locationPool);
location.update();
return location;
}
@@ -89,12 +89,13 @@ Bindings.DebuggerWorkspaceBinding = class {
* @param {!SDK.DebuggerModel.Location} location
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
- * @return {?Bindings.DebuggerWorkspaceBinding.Location}
+ * @return {?Location}
*/
createCallFrameLiveLocation(location, updateDelegate, locationPool) {
const script = location.script();
- if (!script)
+ if (!script) {
return null;
+ }
const debuggerModel = location.debuggerModel;
const liveLocation = this.createLiveLocation(location, updateDelegate, locationPool);
this._registerCallFrameLiveLocation(debuggerModel, liveLocation);
@@ -108,8 +109,9 @@ Bindings.DebuggerWorkspaceBinding = class {
rawLocationToUILocation(rawLocation) {
for (let i = 0; i < this._sourceMappings.length; ++i) {
const uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation);
- if (uiLocation)
+ if (uiLocation) {
return uiLocation;
+ }
}
const modelData = this._debuggerModelToData.get(rawLocation.debuggerModel);
return modelData._rawLocationToUILocation(rawLocation);
@@ -122,8 +124,9 @@ Bindings.DebuggerWorkspaceBinding = class {
*/
uiSourceCodeForSourceMapSourceURL(debuggerModel, url, isContentScript) {
const modelData = this._debuggerModelToData.get(debuggerModel);
- if (!modelData)
+ if (!modelData) {
return null;
+ }
return modelData._compilerMapping.uiSourceCodeForURL(url, isContentScript);
}
@@ -135,12 +138,15 @@ Bindings.DebuggerWorkspaceBinding = class {
*/
uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
let locations = [];
- for (let i = 0; i < this._sourceMappings.length && !locations.length; ++i)
+ for (let i = 0; i < this._sourceMappings.length && !locations.length; ++i) {
locations = this._sourceMappings[i].uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber);
- if (locations.length)
+ }
+ if (locations.length) {
return locations;
- for (const modelData of this._debuggerModelToData.values())
+ }
+ for (const modelData of this._debuggerModelToData.values()) {
locations.push(...modelData._uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber));
+ }
return locations;
}
@@ -153,8 +159,9 @@ Bindings.DebuggerWorkspaceBinding = class {
this.uiLocationToRawLocations(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber);
for (const location of rawLocations) {
const uiLocationCandidate = this.rawLocationToUILocation(location);
- if (uiLocationCandidate)
+ if (uiLocationCandidate) {
return uiLocationCandidate;
+ }
}
return uiLocation;
}
@@ -175,8 +182,9 @@ Bindings.DebuggerWorkspaceBinding = class {
*/
sourceMapForScript(script) {
const modelData = this._debuggerModelToData.get(script.debuggerModel);
- if (!modelData)
+ if (!modelData) {
return null;
+ }
return modelData._compilerMapping.sourceMapForScript(script);
}
@@ -208,7 +216,7 @@ Bindings.DebuggerWorkspaceBinding = class {
/**
* @param {!SDK.DebuggerModel} debuggerModel
- * @param {!Bindings.DebuggerWorkspaceBinding.Location} location
+ * @param {!Location} location
*/
_registerCallFrameLiveLocation(debuggerModel, location) {
const locations = this._debuggerModelToData.get(debuggerModel).callFrameLocations;
@@ -216,12 +224,13 @@ Bindings.DebuggerWorkspaceBinding = class {
}
/**
- * @param {!Bindings.DebuggerWorkspaceBinding.Location} location
+ * @param {!Location} location
*/
_removeLiveLocation(location) {
const modelData = this._debuggerModelToData.get(location._script.debuggerModel);
- if (modelData)
+ if (modelData) {
modelData._disposeLocation(location);
+ }
}
/**
@@ -231,21 +240,21 @@ Bindings.DebuggerWorkspaceBinding = class {
const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
this._reset(debuggerModel);
}
-};
+}
/**
* @unrestricted
*/
-Bindings.DebuggerWorkspaceBinding.ModelData = class {
+export class ModelData {
/**
* @param {!SDK.DebuggerModel} debuggerModel
- * @param {!Bindings.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
+ * @param {!DebuggerWorkspaceBinding} debuggerWorkspaceBinding
*/
constructor(debuggerModel, debuggerWorkspaceBinding) {
this._debuggerModel = debuggerModel;
this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
- /** @type {!Set.<!Bindings.DebuggerWorkspaceBinding.Location>} */
+ /** @type {!Set.<!Location>} */
this.callFrameLocations = new Set();
const workspace = debuggerWorkspaceBinding._workspace;
@@ -254,8 +263,8 @@ Bindings.DebuggerWorkspaceBinding.ModelData = class {
this._resourceMapping = new Bindings.ResourceScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
this._compilerMapping = new Bindings.CompilerScriptMapping(debuggerModel, workspace, debuggerWorkspaceBinding);
- /** @type {!Multimap<!SDK.Script, !Bindings.DebuggerWorkspaceBinding.Location>} */
- this._locations = new Multimap();
+ /** @type {!Platform.Multimap<!SDK.Script, !Location>} */
+ this._locations = new Platform.Multimap();
debuggerModel.setBeforePausedCallback(this._beforePaused.bind(this));
}
@@ -264,20 +273,19 @@ Bindings.DebuggerWorkspaceBinding.ModelData = class {
* @param {!SDK.DebuggerModel.Location} rawLocation
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
- * @return {!Bindings.DebuggerWorkspaceBinding.Location}
+ * @return {!Location}
*/
_createLiveLocation(rawLocation, updateDelegate, locationPool) {
const script = /** @type {!SDK.Script} */ (rawLocation.script());
console.assert(script);
- const location = new Bindings.DebuggerWorkspaceBinding.Location(
- script, rawLocation, this._debuggerWorkspaceBinding, updateDelegate, locationPool);
+ const location = new Location(script, rawLocation, this._debuggerWorkspaceBinding, updateDelegate, locationPool);
this._locations.set(script, location);
location.update();
return location;
}
/**
- * @param {!Bindings.DebuggerWorkspaceBinding.Location} location
+ * @param {!Location} location
*/
_disposeLocation(location) {
this._locations.delete(location._script, location);
@@ -287,8 +295,9 @@ Bindings.DebuggerWorkspaceBinding.ModelData = class {
* @param {!SDK.Script} script
*/
_updateLocations(script) {
- for (const location of this._locations.get(script))
+ for (const location of this._locations.get(script)) {
location.update();
+ }
}
/**
@@ -338,16 +347,16 @@ Bindings.DebuggerWorkspaceBinding.ModelData = class {
this._resourceMapping.dispose();
this._defaultMapping.dispose();
}
-};
+}
/**
* @unrestricted
*/
-Bindings.DebuggerWorkspaceBinding.Location = class extends Bindings.LiveLocationWithPool {
+export class Location extends Bindings.LiveLocationWithPool {
/**
* @param {!SDK.Script} script
* @param {!SDK.DebuggerModel.Location} rawLocation
- * @param {!Bindings.DebuggerWorkspaceBinding} binding
+ * @param {!DebuggerWorkspaceBinding} binding
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
*/
@@ -383,12 +392,12 @@ Bindings.DebuggerWorkspaceBinding.Location = class extends Bindings.LiveLocation
const uiLocation = this.uiLocation();
return uiLocation ? Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode) : false;
}
-};
+}
-Bindings.DebuggerWorkspaceBinding.StackTraceTopFrameLocation = class extends Bindings.LiveLocationWithPool {
+export class StackTraceTopFrameLocation extends Bindings.LiveLocationWithPool {
/**
* @param {!Array<!SDK.DebuggerModel.Location>} rawLocations
- * @param {!Bindings.DebuggerWorkspaceBinding} binding
+ * @param {!DebuggerWorkspaceBinding} binding
* @param {function(!Bindings.LiveLocation)} updateDelegate
* @param {!Bindings.LiveLocationPool} locationPool
*/
@@ -422,39 +431,41 @@ Bindings.DebuggerWorkspaceBinding.StackTraceTopFrameLocation = class extends Bin
*/
dispose() {
super.dispose();
- for (const location of this._locations)
+ for (const location of this._locations) {
location.dispose();
+ }
this._locations = null;
this._current = null;
}
_scheduleUpdate() {
- if (this._updateScheduled)
+ if (this._updateScheduled) {
return;
+ }
this._updateScheduled = true;
setImmediate(this._updateLocation.bind(this));
}
_updateLocation() {
this._updateScheduled = false;
- if (!this._locations)
+ if (!this._locations) {
return;
+ }
this._current = this._locations.find(location => !location.isBlackboxed()) || this._locations[0];
this.update();
}
-};
+}
/**
* @interface
*/
-Bindings.DebuggerSourceMapping = function() {};
-
-Bindings.DebuggerSourceMapping.prototype = {
+export class DebuggerSourceMapping {
/**
* @param {!SDK.DebuggerModel.Location} rawLocation
* @return {?Workspace.UILocation}
*/
- rawLocationToUILocation(rawLocation) {},
+ rawLocationToUILocation(rawLocation) {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
@@ -462,10 +473,32 @@ Bindings.DebuggerSourceMapping.prototype = {
* @param {number} columnNumber
* @return {!Array<!SDK.DebuggerModel.Location>}
*/
- uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {},
-};
+ uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
+ }
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.DebuggerWorkspaceBinding = DebuggerWorkspaceBinding;
+
+/** @constructor */
+Bindings.DebuggerWorkspaceBinding.ModelData = ModelData;
+
+/** @constructor */
+Bindings.DebuggerWorkspaceBinding.Location = Location;
+
+/** @constructor */
+Bindings.DebuggerWorkspaceBinding.StackTraceTopFrameLocation = StackTraceTopFrameLocation;
+
+/** @interface */
+Bindings.DebuggerSourceMapping = DebuggerSourceMapping;
/**
- * @type {!Bindings.DebuggerWorkspaceBinding}
+ * @type {!DebuggerWorkspaceBinding}
*/
Bindings.debuggerWorkspaceBinding;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/DefaultScriptMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/DefaultScriptMapping.js
index 26fea9642b4..b0191c26808 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/DefaultScriptMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/DefaultScriptMapping.js
@@ -31,7 +31,7 @@
* @implements {Bindings.DebuggerSourceMapping}
* @unrestricted
*/
-Bindings.DefaultScriptMapping = class {
+export default class DefaultScriptMapping {
/**
* @param {!SDK.DebuggerModel} debuggerModel
* @param {!Workspace.Workspace} workspace
@@ -57,7 +57,7 @@ Bindings.DefaultScriptMapping = class {
* @return {?SDK.Script}
*/
static scriptForUISourceCode(uiSourceCode) {
- const scripts = uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol];
+ const scripts = uiSourceCode[_scriptsSymbol];
return scripts ? scripts.values().next().value : null;
}
@@ -68,13 +68,15 @@ Bindings.DefaultScriptMapping = class {
*/
rawLocationToUILocation(rawLocation) {
const script = rawLocation.script();
- if (!script)
+ if (!script) {
return null;
- const uiSourceCode = script[Bindings.DefaultScriptMapping._uiSourceCodeSymbol];
+ }
+ const uiSourceCode = script[_uiSourceCodeSymbol];
const lineNumber = rawLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0);
let columnNumber = rawLocation.columnNumber || 0;
- if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber)
+ if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber) {
columnNumber -= script.columnOffset;
+ }
return uiSourceCode.uiLocation(lineNumber, columnNumber);
}
@@ -87,8 +89,9 @@ Bindings.DefaultScriptMapping = class {
*/
uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
const script = uiSourceCode[this._scriptSymbol];
- if (!script)
+ if (!script) {
return [];
+ }
if (script.isInlineScriptWithSourceURL()) {
return [this._debuggerModel.createRawLocation(
script, lineNumber + script.lineOffset, lineNumber ? columnNumber : columnNumber + script.columnOffset)];
@@ -106,11 +109,12 @@ Bindings.DefaultScriptMapping = class {
const uiSourceCode = this._project.createUISourceCode(url, Common.resourceTypes.Script);
uiSourceCode[this._scriptSymbol] = script;
- if (!uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol])
- uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol] = new Set([script]);
- else
- uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol].add(script);
- script[Bindings.DefaultScriptMapping._uiSourceCodeSymbol] = uiSourceCode;
+ if (!uiSourceCode[_scriptsSymbol]) {
+ uiSourceCode[_scriptsSymbol] = new Set([script]);
+ } else {
+ uiSourceCode[_scriptsSymbol].add(script);
+ }
+ script[_uiSourceCodeSymbol] = uiSourceCode;
this._project.addUISourceCodeWithProvider(uiSourceCode, script, null, 'text/javascript');
this._debuggerWorkspaceBinding.updateLocations(script);
}
@@ -120,14 +124,16 @@ Bindings.DefaultScriptMapping = class {
*/
_discardedScriptSource(event) {
const script = /** @type {!SDK.Script} */ (event.data);
- const uiSourceCode = script[Bindings.DefaultScriptMapping._uiSourceCodeSymbol];
- if (!uiSourceCode)
+ const uiSourceCode = script[_uiSourceCodeSymbol];
+ if (!uiSourceCode) {
return;
- delete script[Bindings.DefaultScriptMapping._uiSourceCodeSymbol];
+ }
+ delete script[_uiSourceCodeSymbol];
delete uiSourceCode[this._scriptSymbol];
- uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol].delete(script);
- if (!uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol].size)
- delete uiSourceCode[Bindings.DefaultScriptMapping._scriptsSymbol];
+ uiSourceCode[_scriptsSymbol].delete(script);
+ if (!uiSourceCode[_scriptsSymbol].size) {
+ delete uiSourceCode[_scriptsSymbol];
+ }
this._project.removeUISourceCode(uiSourceCode.url());
}
@@ -140,7 +146,19 @@ Bindings.DefaultScriptMapping = class {
this._debuggerReset();
this._project.dispose();
}
-};
+}
+
+export const _scriptsSymbol = Symbol('symbol');
+export const _uiSourceCodeSymbol = Symbol('uiSourceCodeSymbol');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.DefaultScriptMapping = DefaultScriptMapping;
-Bindings.DefaultScriptMapping._scriptsSymbol = Symbol('symbol');
-Bindings.DefaultScriptMapping._uiSourceCodeSymbol = Symbol('uiSourceCodeSymbol');
+Bindings.DefaultScriptMapping._scriptsSymbol = _scriptsSymbol;
+Bindings.DefaultScriptMapping._uiSourceCodeSymbol = _uiSourceCodeSymbol;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/FileUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/FileUtils.js
index 2128ecaf268..ab99bf556d8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/FileUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/FileUtils.js
@@ -31,41 +31,43 @@
/**
* @interface
*/
-Bindings.ChunkedReader = function() {};
-
-Bindings.ChunkedReader.prototype = {
+export class ChunkedReader {
/**
* @return {number}
*/
- fileSize() {},
+ fileSize() {
+ }
/**
* @return {number}
*/
- loadedSize() {},
+ loadedSize() {
+ }
/**
* @return {string}
*/
- fileName() {},
+ fileName() {
+ }
- cancel() {},
+ cancel() {
+ }
/**
* @return {?FileError}
*/
error() {}
-};
+}
/**
- * @implements {Bindings.ChunkedReader}
+ * @implements {ChunkedReader}
* @unrestricted
*/
-Bindings.ChunkedFileReader = class {
+export class ChunkedFileReader {
/**
* @param {!Blob} blob
* @param {number} chunkSize
- * @param {function(!Bindings.ChunkedReader)=} chunkTransferredCallback
+ * @param {function(!ChunkedReader)=} chunkTransferredCallback
*/
constructor(blob, chunkSize, chunkTransferredCallback) {
this._file = blob;
@@ -84,8 +86,9 @@ Bindings.ChunkedFileReader = class {
* @return {!Promise<boolean>}
*/
read(output) {
- if (this._chunkTransferredCallback)
+ if (this._chunkTransferredCallback) {
this._chunkTransferredCallback(this);
+ }
this._output = output;
this._reader = new FileReader();
this._reader.onload = this._onChunkLoaded.bind(this);
@@ -137,21 +140,25 @@ Bindings.ChunkedFileReader = class {
* @param {!Event} event
*/
_onChunkLoaded(event) {
- if (this._isCanceled)
+ if (this._isCanceled) {
return;
+ }
- if (event.target.readyState !== FileReader.DONE)
+ if (event.target.readyState !== FileReader.DONE) {
return;
+ }
const buffer = this._reader.result;
this._loadedSize += buffer.byteLength;
const endOfFile = this._loadedSize === this._fileSize;
const decodedString = this._decoder.decode(buffer, {stream: !endOfFile});
this._output.write(decodedString);
- if (this._isCanceled)
+ if (this._isCanceled) {
return;
- if (this._chunkTransferredCallback)
+ }
+ if (this._chunkTransferredCallback) {
this._chunkTransferredCallback(this);
+ }
if (endOfFile) {
this._file = null;
@@ -178,13 +185,13 @@ Bindings.ChunkedFileReader = class {
this._error = event.target.error;
this._transferFinished(false);
}
-};
+}
/**
* @implements {Common.OutputStream}
* @unrestricted
*/
-Bindings.FileOutputStream = class {
+export class FileOutputStream {
/**
* @param {string} fileName
* @return {!Promise<boolean>}
@@ -195,8 +202,9 @@ Bindings.FileOutputStream = class {
this._writeCallbacks = [];
this._fileName = fileName;
const saveResponse = await Workspace.fileManager.save(this._fileName, '', true);
- if (saveResponse)
+ if (saveResponse) {
Workspace.fileManager.addEventListener(Workspace.FileManager.Events.AppendedToURL, this._onAppendDone, this);
+ }
return !!saveResponse;
}
@@ -215,10 +223,11 @@ Bindings.FileOutputStream = class {
/**
* @override
*/
- close() {
+ async close() {
this._closed = true;
- if (this._writeCallbacks.length)
+ if (this._writeCallbacks.length) {
return;
+ }
Workspace.fileManager.removeEventListener(Workspace.FileManager.Events.AppendedToURL, this._onAppendDone, this);
Workspace.fileManager.close(this._fileName);
}
@@ -227,14 +236,32 @@ Bindings.FileOutputStream = class {
* @param {!Common.Event} event
*/
_onAppendDone(event) {
- if (event.data !== this._fileName)
+ if (event.data !== this._fileName) {
return;
+ }
this._writeCallbacks.shift()();
- if (this._writeCallbacks.length)
+ if (this._writeCallbacks.length) {
return;
- if (!this._closed)
+ }
+ if (!this._closed) {
return;
+ }
Workspace.fileManager.removeEventListener(Workspace.FileManager.Events.AppendedToURL, this._onAppendDone, this);
Workspace.fileManager.close(this._fileName);
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @interface */
+Bindings.ChunkedReader = ChunkedReader;
+
+/** @constructor */
+Bindings.ChunkedFileReader = ChunkedFileReader;
+
+/** @constructor */
+Bindings.FileOutputStream = FileOutputStream; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/LiveLocation.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/LiveLocation.js
index d4b13f7373a..e6fe900f8b9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/LiveLocation.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/LiveLocation.js
@@ -1,33 +1,35 @@
// 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.
-/** @interface */
-Bindings.LiveLocation = function() {};
-Bindings.LiveLocation.prototype = {
- update() {},
+/** @interface */
+export default class LiveLocation {
+ update() {
+ }
/**
* @return {?Workspace.UILocation}
*/
- uiLocation() {},
+ uiLocation() {
+ }
- dispose() {},
+ dispose() {
+ }
/**
* @return {boolean}
*/
isBlackboxed() {}
-};
+}
/**
- * @implements {Bindings.LiveLocation}
+ * @implements {LiveLocation}
* @unrestricted
*/
-Bindings.LiveLocationWithPool = class {
+export class LiveLocationWithPool {
/**
- * @param {function(!Bindings.LiveLocation)} updateDelegate
- * @param {!Bindings.LiveLocationPool} locationPool
+ * @param {function(!LiveLocation)} updateDelegate
+ * @param {!LiveLocationPool} locationPool
*/
constructor(updateDelegate, locationPool) {
this._updateDelegate = updateDelegate;
@@ -65,32 +67,48 @@ Bindings.LiveLocationWithPool = class {
isBlackboxed() {
throw 'Not implemented';
}
-};
+}
/**
* @unrestricted
*/
-Bindings.LiveLocationPool = class {
+export class LiveLocationPool {
constructor() {
this._locations = new Set();
}
/**
- * @param {!Bindings.LiveLocation} location
+ * @param {!LiveLocation} location
*/
_add(location) {
this._locations.add(location);
}
/**
- * @param {!Bindings.LiveLocation} location
+ * @param {!LiveLocation} location
*/
_delete(location) {
this._locations.delete(location);
}
disposeAll() {
- for (const location of this._locations)
+ for (const location of this._locations) {
location.dispose();
+ }
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @interface */
+Bindings.LiveLocation = LiveLocation;
+
+/** @constructor */
+Bindings.LiveLocationWithPool = LiveLocationWithPool;
+
+/** @constructor */
+Bindings.LiveLocationPool = LiveLocationPool;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
index cddee9d847a..5c8c997dfe6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
@@ -27,10 +27,9 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-Bindings.NetworkProjectManager = class extends Common.Object {
-};
+export class NetworkProjectManager extends Common.Object {}
-Bindings.NetworkProjectManager.Events = {
+export const Events = {
FrameAttributionAdded: Symbol('FrameAttributionAdded'),
FrameAttributionRemoved: Symbol('FrameAttributionRemoved')
};
@@ -38,13 +37,13 @@ Bindings.NetworkProjectManager.Events = {
/**
* @unrestricted
*/
-Bindings.NetworkProject = class {
+export default class NetworkProject {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {string} frameId
*/
static _resolveFrame(uiSourceCode, frameId) {
- const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
+ const target = NetworkProject.targetForUISourceCode(uiSourceCode);
const resourceTreeModel = target && target.model(SDK.ResourceTreeModel);
return resourceTreeModel ? resourceTreeModel.frameForId(frameId) : null;
}
@@ -54,13 +53,14 @@ Bindings.NetworkProject = class {
* @param {string} frameId
*/
static setInitialFrameAttribution(uiSourceCode, frameId) {
- const frame = Bindings.NetworkProject._resolveFrame(uiSourceCode, frameId);
- if (!frame)
+ const frame = NetworkProject._resolveFrame(uiSourceCode, frameId);
+ if (!frame) {
return;
+ }
/** @type {!Map<string, !{frame: !SDK.ResourceTreeFrame, count: number}>} */
const attribution = new Map();
attribution.set(frameId, {frame: frame, count: 1});
- uiSourceCode[Bindings.NetworkProject._frameAttributionSymbol] = attribution;
+ uiSourceCode[_frameAttributionSymbol] = attribution;
}
/**
@@ -68,12 +68,13 @@ Bindings.NetworkProject = class {
* @param {!Workspace.UISourceCode} toUISourceCode
*/
static cloneInitialFrameAttribution(fromUISourceCode, toUISourceCode) {
- const fromAttribution = fromUISourceCode[Bindings.NetworkProject._frameAttributionSymbol];
- if (!fromAttribution)
+ const fromAttribution = fromUISourceCode[_frameAttributionSymbol];
+ if (!fromAttribution) {
return;
+ }
/** @type {!Map<string, !{frame: !SDK.ResourceTreeFrame, count: number}>} */
const toAttribution = new Map();
- toUISourceCode[Bindings.NetworkProject._frameAttributionSymbol] = toAttribution;
+ toUISourceCode[_frameAttributionSymbol] = toAttribution;
for (const frameId of fromAttribution.keys()) {
const value = fromAttribution.get(frameId);
toAttribution.set(frameId, {frame: value.frame, count: value.count});
@@ -85,19 +86,20 @@ Bindings.NetworkProject = class {
* @param {string} frameId
*/
static addFrameAttribution(uiSourceCode, frameId) {
- const frame = Bindings.NetworkProject._resolveFrame(uiSourceCode, frameId);
- if (!frame)
+ const frame = NetworkProject._resolveFrame(uiSourceCode, frameId);
+ if (!frame) {
return;
- const frameAttribution = uiSourceCode[Bindings.NetworkProject._frameAttributionSymbol];
+ }
+ const frameAttribution = uiSourceCode[_frameAttributionSymbol];
const attributionInfo = frameAttribution.get(frameId) || {frame: frame, count: 0};
attributionInfo.count += 1;
frameAttribution.set(frameId, attributionInfo);
- if (attributionInfo.count !== 1)
+ if (attributionInfo.count !== 1) {
return;
+ }
const data = {uiSourceCode: uiSourceCode, frame: frame};
- Bindings.networkProjectManager.dispatchEventToListeners(
- Bindings.NetworkProjectManager.Events.FrameAttributionAdded, data);
+ Bindings.networkProjectManager.dispatchEventToListeners(Events.FrameAttributionAdded, data);
}
/**
@@ -105,18 +107,19 @@ Bindings.NetworkProject = class {
* @param {string} frameId
*/
static removeFrameAttribution(uiSourceCode, frameId) {
- const frameAttribution = uiSourceCode[Bindings.NetworkProject._frameAttributionSymbol];
- if (!frameAttribution)
+ const frameAttribution = uiSourceCode[_frameAttributionSymbol];
+ if (!frameAttribution) {
return;
+ }
const attributionInfo = frameAttribution.get(frameId);
console.assert(attributionInfo, 'Failed to remove frame attribution for url: ' + uiSourceCode.url());
attributionInfo.count -= 1;
- if (attributionInfo.count > 0)
+ if (attributionInfo.count > 0) {
return;
+ }
frameAttribution.delete(frameId);
const data = {uiSourceCode: uiSourceCode, frame: attributionInfo.frame};
- Bindings.networkProjectManager.dispatchEventToListeners(
- Bindings.NetworkProjectManager.Events.FrameAttributionRemoved, data);
+ Bindings.networkProjectManager.dispatchEventToListeners(Events.FrameAttributionRemoved, data);
}
/**
@@ -124,7 +127,7 @@ Bindings.NetworkProject = class {
* @return {?SDK.Target} target
*/
static targetForUISourceCode(uiSourceCode) {
- return uiSourceCode.project()[Bindings.NetworkProject._targetSymbol] || null;
+ return uiSourceCode.project()[_targetSymbol] || null;
}
/**
@@ -132,7 +135,7 @@ Bindings.NetworkProject = class {
* @param {!SDK.Target} target
*/
static setTargetForProject(project, target) {
- project[Bindings.NetworkProject._targetSymbol] = target;
+ project[_targetSymbol] = target;
}
/**
@@ -140,15 +143,33 @@ Bindings.NetworkProject = class {
* @return {!Array<!SDK.ResourceTreeFrame>}
*/
static framesForUISourceCode(uiSourceCode) {
- const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
+ const target = NetworkProject.targetForUISourceCode(uiSourceCode);
const resourceTreeModel = target && target.model(SDK.ResourceTreeModel);
- const attribution = uiSourceCode[Bindings.NetworkProject._frameAttributionSymbol];
- if (!resourceTreeModel || !attribution)
+ const attribution = uiSourceCode[_frameAttributionSymbol];
+ if (!resourceTreeModel || !attribution) {
return [];
+ }
const frames = Array.from(attribution.keys()).map(frameId => resourceTreeModel.frameForId(frameId));
return frames.filter(frame => !!frame);
}
-};
+}
+
+export const _targetSymbol = Symbol('target');
+export const _frameAttributionSymbol = Symbol('_frameAttributionSymbol');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.NetworkProjectManager = NetworkProjectManager;
+
+Bindings.NetworkProjectManager.Events = Events;
+
+/** @constructor */
+Bindings.NetworkProject = NetworkProject;
-Bindings.NetworkProject._targetSymbol = Symbol('target');
-Bindings.NetworkProject._frameAttributionSymbol = Symbol('Bindings.NetworkProject._frameAttributionSymbol');
+Bindings.NetworkProject._targetSymbol = _targetSymbol;
+Bindings.NetworkProject._frameAttributionSymbol = _frameAttributionSymbol;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/PresentationConsoleMessageHelper.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
index 41c62e7f3a6..66e9d4c524f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -31,7 +31,7 @@
/**
* @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>}
*/
-Bindings.PresentationConsoleMessageManager = class {
+export class PresentationConsoleMessageManager {
constructor() {
SDK.targetManager.observeModels(SDK.DebuggerModel, this);
@@ -47,8 +47,7 @@ Bindings.PresentationConsoleMessageManager = class {
* @param {!SDK.DebuggerModel} debuggerModel
*/
modelAdded(debuggerModel) {
- debuggerModel[Bindings.PresentationConsoleMessageManager._symbol] =
- new Bindings.PresentationConsoleMessageHelper(debuggerModel);
+ debuggerModel[PresentationConsoleMessageManager._symbol] = new PresentationConsoleMessageHelper(debuggerModel);
}
/**
@@ -56,7 +55,7 @@ Bindings.PresentationConsoleMessageManager = class {
* @param {!SDK.DebuggerModel} debuggerModel
*/
modelRemoved(debuggerModel) {
- debuggerModel[Bindings.PresentationConsoleMessageManager._symbol]._consoleCleared();
+ debuggerModel[PresentationConsoleMessageManager._symbol]._consoleCleared();
}
/**
@@ -64,21 +63,23 @@ Bindings.PresentationConsoleMessageManager = class {
*/
_consoleMessageAdded(message) {
if (!message.isErrorOrWarning() || !message.runtimeModel() ||
- message.source === SDK.ConsoleMessage.MessageSource.Violation)
+ message.source === SDK.ConsoleMessage.MessageSource.Violation) {
return;
+ }
const debuggerModel = message.runtimeModel().debuggerModel();
- debuggerModel[Bindings.PresentationConsoleMessageManager._symbol]._consoleMessageAdded(message);
+ debuggerModel[PresentationConsoleMessageManager._symbol]._consoleMessageAdded(message);
}
_consoleCleared() {
- for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel))
- debuggerModel[Bindings.PresentationConsoleMessageManager._symbol]._consoleCleared();
+ for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)) {
+ debuggerModel[PresentationConsoleMessageManager._symbol]._consoleCleared();
+ }
}
-};
+}
-Bindings.PresentationConsoleMessageManager._symbol = Symbol('PresentationConsoleMessageHelper');
+PresentationConsoleMessageManager._symbol = Symbol('PresentationConsoleMessageHelper');
-Bindings.PresentationConsoleMessageHelper = class {
+export default class PresentationConsoleMessageHelper {
/**
* @param {!SDK.DebuggerModel} debuggerModel
*/
@@ -88,7 +89,7 @@ Bindings.PresentationConsoleMessageHelper = class {
/** @type {!Object.<string, !Array.<!SDK.ConsoleMessage>>} */
this._pendingConsoleMessages = {};
- /** @type {!Array.<!Bindings.PresentationConsoleMessage>} */
+ /** @type {!Array.<!PresentationConsoleMessage>} */
this._presentationConsoleMessages = [];
// TODO(dgozman): setImmediate because we race with DebuggerWorkspaceBinding on ParsedScriptSource event delivery.
@@ -104,10 +105,11 @@ Bindings.PresentationConsoleMessageHelper = class {
*/
_consoleMessageAdded(message) {
const rawLocation = this._rawLocation(message);
- if (rawLocation)
+ if (rawLocation) {
this._addConsoleMessageToScript(message, rawLocation);
- else
+ } else {
this._addPendingConsoleMessage(message);
+ }
}
/**
@@ -115,15 +117,17 @@ Bindings.PresentationConsoleMessageHelper = class {
* @return {?SDK.DebuggerModel.Location}
*/
_rawLocation(message) {
- if (message.scriptId)
+ if (message.scriptId) {
return this._debuggerModel.createRawLocationByScriptId(message.scriptId, message.line, message.column);
+ }
const callFrame = message.stackTrace && message.stackTrace.callFrames ? message.stackTrace.callFrames[0] : null;
if (callFrame) {
return this._debuggerModel.createRawLocationByScriptId(
callFrame.scriptId, callFrame.lineNumber, callFrame.columnNumber);
}
- if (message.url)
+ if (message.url) {
return this._debuggerModel.createRawLocationByURL(message.url, message.line, message.column);
+ }
return null;
}
@@ -132,18 +136,19 @@ Bindings.PresentationConsoleMessageHelper = class {
* @param {!SDK.DebuggerModel.Location} rawLocation
*/
_addConsoleMessageToScript(message, rawLocation) {
- this._presentationConsoleMessages.push(
- new Bindings.PresentationConsoleMessage(message, rawLocation, this._locationPool));
+ this._presentationConsoleMessages.push(new PresentationConsoleMessage(message, rawLocation, this._locationPool));
}
/**
* @param {!SDK.ConsoleMessage} message
*/
_addPendingConsoleMessage(message) {
- if (!message.url)
+ if (!message.url) {
return;
- if (!this._pendingConsoleMessages[message.url])
+ }
+ if (!this._pendingConsoleMessages[message.url]) {
this._pendingConsoleMessages[message.url] = [];
+ }
this._pendingConsoleMessages[message.url].push(message);
}
@@ -154,25 +159,29 @@ Bindings.PresentationConsoleMessageHelper = class {
const script = /** @type {!SDK.Script} */ (event.data);
const messages = this._pendingConsoleMessages[script.sourceURL];
- if (!messages)
+ if (!messages) {
return;
+ }
const pendingMessages = [];
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
const rawLocation = this._rawLocation(message);
- if (!rawLocation)
+ if (!rawLocation) {
continue;
- if (script.scriptId === rawLocation.scriptId)
+ }
+ if (script.scriptId === rawLocation.scriptId) {
this._addConsoleMessageToScript(message, rawLocation);
- else
+ } else {
pendingMessages.push(message);
+ }
}
- if (pendingMessages.length)
+ if (pendingMessages.length) {
this._pendingConsoleMessages[script.sourceURL] = pendingMessages;
- else
+ } else {
delete this._pendingConsoleMessages[script.sourceURL];
+ }
}
_consoleCleared() {
@@ -181,17 +190,18 @@ Bindings.PresentationConsoleMessageHelper = class {
}
_debuggerReset() {
- for (const message of this._presentationConsoleMessages)
+ for (const message of this._presentationConsoleMessages) {
message.dispose();
+ }
this._presentationConsoleMessages = [];
this._locationPool.disposeAll();
}
-};
+}
/**
* @unrestricted
*/
-Bindings.PresentationConsoleMessage = class {
+export class PresentationConsoleMessage {
/**
* @param {!SDK.ConsoleMessage} message
* @param {!SDK.DebuggerModel.Location} rawLocation
@@ -209,17 +219,35 @@ Bindings.PresentationConsoleMessage = class {
* @param {!Bindings.LiveLocation} liveLocation
*/
_updateLocation(liveLocation) {
- if (this._uiMessage)
+ if (this._uiMessage) {
this._uiMessage.remove();
+ }
const uiLocation = liveLocation.uiLocation();
- if (!uiLocation)
+ if (!uiLocation) {
return;
+ }
this._uiMessage =
uiLocation.uiSourceCode.addLineMessage(this._level, this._text, uiLocation.lineNumber, uiLocation.columnNumber);
}
dispose() {
- if (this._uiMessage)
+ if (this._uiMessage) {
this._uiMessage.remove();
+ }
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.PresentationConsoleMessageHelper = PresentationConsoleMessageHelper;
+
+/** @constructor */
+Bindings.PresentationConsoleMessageManager = PresentationConsoleMessageManager;
+
+/** @constructor */
+Bindings.PresentationConsoleMessage = PresentationConsoleMessage;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceMapping.js
index c26e2741cc7..84b666a34b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceMapping.js
@@ -5,14 +5,14 @@
/**
* @implements {SDK.SDKModelObserver<!SDK.ResourceTreeModel>}
*/
-Bindings.ResourceMapping = class {
+export default class ResourceMapping {
/**
* @param {!SDK.TargetManager} targetManager
* @param {!Workspace.Workspace} workspace
*/
constructor(targetManager, workspace) {
this._workspace = workspace;
- /** @type {!Map<!SDK.ResourceTreeModel, !Bindings.ResourceMapping.ModelInfo>} */
+ /** @type {!Map<!SDK.ResourceTreeModel, !ModelInfo>} */
this._modelToInfo = new Map();
targetManager.observeModels(SDK.ResourceTreeModel, this);
}
@@ -22,7 +22,7 @@ Bindings.ResourceMapping = class {
* @param {!SDK.ResourceTreeModel} resourceTreeModel
*/
modelAdded(resourceTreeModel) {
- const info = new Bindings.ResourceMapping.ModelInfo(this._workspace, resourceTreeModel);
+ const info = new ModelInfo(this._workspace, resourceTreeModel);
this._modelToInfo.set(resourceTreeModel, info);
}
@@ -38,7 +38,7 @@ Bindings.ResourceMapping = class {
/**
* @param {!SDK.Target} target
- * @return {?Bindings.ResourceMapping.ModelInfo}
+ * @return {?ModelInfo}
*/
_infoForTarget(target) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
@@ -51,20 +51,24 @@ Bindings.ResourceMapping = class {
*/
cssLocationToUILocation(cssLocation) {
const header = cssLocation.header();
- if (!header)
+ if (!header) {
return null;
+ }
const info = this._infoForTarget(cssLocation.cssModel().target());
- if (!info)
+ if (!info) {
return null;
+ }
const uiSourceCode = info._project.uiSourceCodeForURL(cssLocation.url);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return null;
- const offset = header[Bindings.ResourceMapping._offsetSymbol] ||
- TextUtils.TextRange.createFromLocation(header.startLine, header.startColumn);
+ }
+ const offset =
+ header[_offsetSymbol] || TextUtils.TextRange.createFromLocation(header.startLine, header.startColumn);
const lineNumber = cssLocation.lineNumber + offset.startLine - header.startLine;
let columnNumber = cssLocation.columnNumber;
- if (cssLocation.lineNumber === header.startLine)
+ if (cssLocation.lineNumber === header.startLine) {
columnNumber += offset.startColumn - header.startColumn;
+ }
return uiSourceCode.uiLocation(lineNumber, columnNumber);
}
@@ -74,20 +78,24 @@ Bindings.ResourceMapping = class {
*/
jsLocationToUILocation(jsLocation) {
const script = jsLocation.script();
- if (!script)
+ if (!script) {
return null;
+ }
const info = this._infoForTarget(jsLocation.debuggerModel.target());
- if (!info)
+ if (!info) {
return null;
+ }
const uiSourceCode = info._project.uiSourceCodeForURL(script.sourceURL);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return null;
- const offset = script[Bindings.ResourceMapping._offsetSymbol] ||
- TextUtils.TextRange.createFromLocation(script.lineOffset, script.columnOffset);
+ }
+ const offset =
+ script[_offsetSymbol] || TextUtils.TextRange.createFromLocation(script.lineOffset, script.columnOffset);
const lineNumber = jsLocation.lineNumber + offset.startLine - script.lineOffset;
let columnNumber = jsLocation.columnNumber;
- if (jsLocation.lineNumber === script.lineOffset)
+ if (jsLocation.lineNumber === script.lineOffset) {
columnNumber += offset.startColumn - script.columnOffset;
+ }
return uiSourceCode.uiLocation(lineNumber, columnNumber);
}
@@ -98,16 +106,42 @@ Bindings.ResourceMapping = class {
* @return {!Array<!SDK.DebuggerModel.Location>}
*/
uiLocationToJSLocations(uiSourceCode, lineNumber, columnNumber) {
- if (!uiSourceCode[Bindings.ResourceMapping._symbol])
+ if (!uiSourceCode[_symbol]) {
return [];
+ }
const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
- if (!target)
+ if (!target) {
return [];
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return [];
+ }
const location = debuggerModel.createRawLocationByURL(uiSourceCode.url(), lineNumber, columnNumber);
- return location ? [location] : [];
+ if (location && location.script().containsLocation(lineNumber, columnNumber)) {
+ return [location];
+ }
+ return [];
+ }
+
+ /**
+ * @param {!Workspace.UILocation} uiLocation
+ * @return {!Array<!SDK.CSSLocation>}
+ */
+ uiLocationToCSSLocations(uiLocation) {
+ if (!uiLocation.uiSourceCode[_symbol]) {
+ return [];
+ }
+ const target = Bindings.NetworkProject.targetForUISourceCode(uiLocation.uiSourceCode);
+ if (!target) {
+ return [];
+ }
+ const cssModel = target.model(SDK.CSSModel);
+ if (!cssModel) {
+ return [];
+ }
+ return cssModel.createRawLocationsByURL(
+ uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber);
}
/**
@@ -116,12 +150,13 @@ Bindings.ResourceMapping = class {
_resetForTest(target) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
const info = resourceTreeModel ? this._modelToInfo.get(resourceTreeModel) : null;
- if (info)
+ if (info) {
info._resetForTest();
+ }
}
-};
+}
-Bindings.ResourceMapping.ModelInfo = class {
+export class ModelInfo {
/**
* @param {!Workspace.Workspace} workspace
* @param {!SDK.ResourceTreeModel} resourceTreeModel
@@ -132,7 +167,7 @@ Bindings.ResourceMapping.ModelInfo = class {
workspace, 'resources:' + target.id(), Workspace.projectTypes.Network, '', false /* isServiceProject */);
Bindings.NetworkProject.setTargetForProject(this._project, target);
- /** @type {!Map<string, !Bindings.ResourceMapping.Binding>} */
+ /** @type {!Map<string, !Binding>} */
this._bindings = new Map();
const cssModel = target.model(SDK.CSSModel);
@@ -150,11 +185,13 @@ Bindings.ResourceMapping.ModelInfo = class {
*/
_styleSheetChanged(event) {
const header = this._cssModel.styleSheetHeaderForId(event.data.styleSheetId);
- if (!header || !header.isInline)
+ if (!header || !header.isInline) {
return;
+ }
const binding = this._bindings.get(header.resourceURL());
- if (!binding)
+ if (!binding) {
return;
+ }
binding._styleSheetChanged(header, event.data.edit);
}
@@ -165,17 +202,21 @@ Bindings.ResourceMapping.ModelInfo = class {
const resourceType = resource.resourceType();
// Only load selected resource types from resources.
if (resourceType !== Common.resourceTypes.Image && resourceType !== Common.resourceTypes.Font &&
- resourceType !== Common.resourceTypes.Document && resourceType !== Common.resourceTypes.Manifest)
+ resourceType !== Common.resourceTypes.Document && resourceType !== Common.resourceTypes.Manifest) {
return false;
+ }
// Ignore non-images and non-fonts.
- if (resourceType === Common.resourceTypes.Image && resource.mimeType && !resource.mimeType.startsWith('image'))
+ if (resourceType === Common.resourceTypes.Image && resource.mimeType && !resource.mimeType.startsWith('image')) {
return false;
- if (resourceType === Common.resourceTypes.Font && resource.mimeType && !resource.mimeType.includes('font'))
+ }
+ if (resourceType === Common.resourceTypes.Font && resource.mimeType && !resource.mimeType.includes('font')) {
return false;
+ }
if ((resourceType === Common.resourceTypes.Image || resourceType === Common.resourceTypes.Font) &&
- resource.contentURL().startsWith('data:'))
+ resource.contentURL().startsWith('data:')) {
return false;
+ }
return true;
}
@@ -184,12 +225,13 @@ Bindings.ResourceMapping.ModelInfo = class {
*/
_resourceAdded(event) {
const resource = /** @type {!SDK.Resource} */ (event.data);
- if (!this._acceptsResource(resource))
+ if (!this._acceptsResource(resource)) {
return;
+ }
let binding = this._bindings.get(resource.url);
if (!binding) {
- binding = new Bindings.ResourceMapping.Binding(this._project, resource);
+ binding = new Binding(this._project, resource);
this._bindings.set(resource.url, binding);
} else {
binding.addResource(resource);
@@ -201,8 +243,9 @@ Bindings.ResourceMapping.ModelInfo = class {
*/
_removeFrameResources(frame) {
for (const resource of frame.resources()) {
- if (!this._acceptsResource(resource))
+ if (!this._acceptsResource(resource)) {
continue;
+ }
const binding = this._bindings.get(resource.url);
if (binding._resources.size === 1) {
binding.dispose();
@@ -230,24 +273,26 @@ Bindings.ResourceMapping.ModelInfo = class {
}
_resetForTest() {
- for (const binding of this._bindings.valuesArray())
+ for (const binding of this._bindings.valuesArray()) {
binding.dispose();
+ }
this._bindings.clear();
}
dispose() {
Common.EventTarget.removeEventListeners(this._eventListeners);
- for (const binding of this._bindings.valuesArray())
+ for (const binding of this._bindings.valuesArray()) {
binding.dispose();
+ }
this._bindings.clear();
this._project.removeProject();
}
-};
+}
/**
* @implements {Common.ContentProvider}
*/
-Bindings.ResourceMapping.Binding = class {
+export class Binding {
/**
* @param {!Bindings.ContentProviderBasedProject} project
* @param {!SDK.Resource} resource
@@ -256,7 +301,7 @@ Bindings.ResourceMapping.Binding = class {
this._resources = new Set([resource]);
this._project = project;
this._uiSourceCode = this._project.createUISourceCode(resource.url, resource.contentType());
- this._uiSourceCode[Bindings.ResourceMapping._symbol] = true;
+ this._uiSourceCode[_symbol] = true;
Bindings.NetworkProject.setInitialFrameAttribution(this._uiSourceCode, resource.frameId);
this._project.addUISourceCodeWithProvider(
this._uiSourceCode, this, Bindings.resourceMetadata(resource), resource.mimeType);
@@ -274,8 +319,9 @@ Bindings.ResourceMapping.Binding = class {
if (cssModel) {
for (const headerId of cssModel.styleSheetIdsForURL(this._uiSourceCode.url())) {
const header = cssModel.styleSheetHeaderForId(headerId);
- if (header)
+ if (header) {
stylesheets.push(header);
+ }
}
}
return stylesheets;
@@ -287,8 +333,9 @@ Bindings.ResourceMapping.Binding = class {
_inlineScripts() {
const target = Bindings.NetworkProject.targetForUISourceCode(this._uiSourceCode);
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return [];
+ }
return debuggerModel.scriptsForSourceURL(this._uiSourceCode.url());
}
@@ -298,12 +345,14 @@ Bindings.ResourceMapping.Binding = class {
*/
async _styleSheetChanged(stylesheet, edit) {
this._edits.push({stylesheet, edit});
- if (this._edits.length > 1)
- return; // There is already a _styleSheetChanged loop running
+ if (this._edits.length > 1) {
+ return;
+ } // There is already a _styleSheetChanged loop running
- const content = await this._uiSourceCode.requestContent();
- if (content !== null)
+ const {content} = await this._uiSourceCode.requestContent();
+ if (content !== null) {
this._innerStyleSheetChanged(content);
+ }
this._edits = [];
}
@@ -317,26 +366,28 @@ Bindings.ResourceMapping.Binding = class {
for (const data of this._edits) {
const edit = data.edit;
const stylesheet = data.stylesheet;
- const startLocation = stylesheet[Bindings.ResourceMapping._offsetSymbol] ||
+ const startLocation = stylesheet[_offsetSymbol] ||
TextUtils.TextRange.createFromLocation(stylesheet.startLine, stylesheet.startColumn);
const oldRange = edit.oldRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
const newRange = edit.newRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
text = new TextUtils.Text(text.replaceRange(oldRange, edit.newText));
for (const script of scripts) {
- const scriptOffset = script[Bindings.ResourceMapping._offsetSymbol] ||
- TextUtils.TextRange.createFromLocation(script.lineOffset, script.columnOffset);
- if (!scriptOffset.follows(oldRange))
+ const scriptOffset =
+ script[_offsetSymbol] || TextUtils.TextRange.createFromLocation(script.lineOffset, script.columnOffset);
+ if (!scriptOffset.follows(oldRange)) {
continue;
- script[Bindings.ResourceMapping._offsetSymbol] = scriptOffset.rebaseAfterTextEdit(oldRange, newRange);
+ }
+ script[_offsetSymbol] = scriptOffset.rebaseAfterTextEdit(oldRange, newRange);
Bindings.debuggerWorkspaceBinding.updateLocations(script);
}
for (const style of styles) {
- const styleOffset = style[Bindings.ResourceMapping._offsetSymbol] ||
- TextUtils.TextRange.createFromLocation(style.startLine, style.startColumn);
- if (!styleOffset.follows(oldRange))
+ const styleOffset =
+ style[_offsetSymbol] || TextUtils.TextRange.createFromLocation(style.startLine, style.startColumn);
+ if (!styleOffset.follows(oldRange)) {
continue;
- style[Bindings.ResourceMapping._offsetSymbol] = styleOffset.rebaseAfterTextEdit(oldRange, newRange);
+ }
+ style[_offsetSymbol] = styleOffset.rebaseAfterTextEdit(oldRange, newRange);
Bindings.cssWorkspaceBinding.updateLocations(style);
}
}
@@ -389,7 +440,7 @@ Bindings.ResourceMapping.Binding = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
return this._resources.firstValue().requestContent();
@@ -405,7 +456,25 @@ Bindings.ResourceMapping.Binding = class {
searchInContent(query, caseSensitive, isRegex) {
return this._resources.firstValue().searchInContent(query, caseSensitive, isRegex);
}
-};
+}
+
+export const _symbol = Symbol('Bindings.ResourceMapping._symbol');
+export const _offsetSymbol = Symbol('Bindings.ResourceMapping._offsetSymbol');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.ResourceMapping = ResourceMapping;
+
+/** @constructor */
+Bindings.ResourceMapping.ModelInfo = ModelInfo;
+
+/** @constructor */
+Bindings.ResourceMapping.Binding = Binding;
-Bindings.ResourceMapping._symbol = Symbol('Bindings.ResourceMapping._symbol');
-Bindings.ResourceMapping._offsetSymbol = Symbol('Bindings.ResourceMapping._offsetSymbol'); \ No newline at end of file
+Bindings.ResourceMapping._symbol = _symbol;
+Bindings.ResourceMapping._offsetSymbol = _offsetSymbol;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceScriptMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceScriptMapping.js
index 92bcbcfd4f6..f2f8068ba3a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceScriptMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceScriptMapping.js
@@ -31,7 +31,7 @@
* @implements {Bindings.DebuggerSourceMapping}
* @unrestricted
*/
-Bindings.ResourceScriptMapping = class {
+export default class ResourceScriptMapping {
/**
* @param {!SDK.DebuggerModel} debuggerModel
* @param {!Workspace.Workspace} workspace
@@ -41,7 +41,7 @@ Bindings.ResourceScriptMapping = class {
this._debuggerModel = debuggerModel;
this._workspace = workspace;
this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
- /** @type {!Map.<!Workspace.UISourceCode, !Bindings.ResourceScriptFile>} */
+ /** @type {!Map.<!Workspace.UISourceCode, !ResourceScriptFile>} */
this._uiSourceCodeToScriptFile = new Map();
/** @type {!Map<string, !Bindings.ContentProviderBasedProject>} */
@@ -64,7 +64,7 @@ Bindings.ResourceScriptMapping = class {
* @return {!Bindings.ContentProviderBasedProject}
*/
_project(script) {
- const frameId = script[Bindings.ResourceScriptMapping._frameIdSymbol];
+ const frameId = script[_frameIdSymbol];
const prefix = script.isContentScript() ? 'js:extensions:' : 'js::';
const projectId = prefix + this._debuggerModel.target().id() + ':' + frameId;
let project = this._projects.get(projectId);
@@ -86,23 +86,29 @@ Bindings.ResourceScriptMapping = class {
*/
rawLocationToUILocation(rawLocation) {
const script = rawLocation.script();
- if (!script)
+ if (!script) {
return null;
+ }
const project = this._project(script);
const uiSourceCode = project.uiSourceCodeForURL(script.sourceURL);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return null;
+ }
const scriptFile = this._uiSourceCodeToScriptFile.get(uiSourceCode);
- if (!scriptFile)
+ if (!scriptFile) {
return null;
- if ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM())
+ }
+ if ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM()) {
return null;
- if (!scriptFile._hasScripts([script]))
+ }
+ if (!scriptFile._hasScripts([script])) {
return null;
+ }
const lineNumber = rawLocation.lineNumber - (script.isInlineScriptWithSourceURL() ? script.lineOffset : 0);
let columnNumber = rawLocation.columnNumber || 0;
- if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber)
+ if (script.isInlineScriptWithSourceURL() && !lineNumber && columnNumber) {
columnNumber -= script.columnOffset;
+ }
return uiSourceCode.uiLocation(lineNumber, columnNumber);
}
@@ -115,8 +121,9 @@ Bindings.ResourceScriptMapping = class {
*/
uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
const scriptFile = this._uiSourceCodeToScriptFile.get(uiSourceCode);
- if (!scriptFile)
+ if (!scriptFile) {
return [];
+ }
const script = scriptFile._script;
if (script.isInlineScriptWithSourceURL()) {
return [this._debuggerModel.createRawLocation(
@@ -130,13 +137,15 @@ Bindings.ResourceScriptMapping = class {
* @return {boolean}
*/
_acceptsScript(script) {
- if (!script.sourceURL || script.isLiveEdit() || (script.isInlineScript() && !script.hasSourceURL))
+ if (!script.sourceURL || script.isLiveEdit() || (script.isInlineScript() && !script.hasSourceURL)) {
return false;
+ }
// Filter out embedder injected content scripts.
if (script.isContentScript() && !script.hasSourceURL) {
const parsedURL = new Common.ParsedURL(script.sourceURL);
- if (!parsedURL.isValid)
+ if (!parsedURL.isValid) {
return false;
+ }
}
return true;
}
@@ -146,12 +155,13 @@ Bindings.ResourceScriptMapping = class {
*/
_parsedScriptSource(event) {
const script = /** @type {!SDK.Script} */ (event.data);
- if (!this._acceptsScript(script))
+ if (!this._acceptsScript(script)) {
return;
+ }
this._acceptedScripts.add(script);
const originalContentProvider = script.originalContentProvider();
const frameId = Bindings.frameIdForScript(script);
- script[Bindings.ResourceScriptMapping._frameIdSymbol] = frameId;
+ script[_frameIdSymbol] = frameId;
const url = script.sourceURL;
const project = this._project(script);
@@ -169,7 +179,7 @@ Bindings.ResourceScriptMapping = class {
const metadata = Bindings.metadataForURL(this._debuggerModel.target(), frameId, url);
// Bind UISourceCode to scripts.
- const scriptFile = new Bindings.ResourceScriptFile(this, uiSourceCode, [script]);
+ const scriptFile = new ResourceScriptFile(this, uiSourceCode, [script]);
this._uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile);
project.addUISourceCodeWithProvider(uiSourceCode, originalContentProvider, metadata, 'text/javascript');
@@ -178,7 +188,7 @@ Bindings.ResourceScriptMapping = class {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
- * @return {?Bindings.ResourceScriptFile}
+ * @return {?ResourceScriptFile}
*/
scriptFile(uiSourceCode) {
return this._uiSourceCodeToScriptFile.get(uiSourceCode) || null;
@@ -188,8 +198,9 @@ Bindings.ResourceScriptMapping = class {
* @param {!SDK.Script} script
*/
_removeScript(script) {
- if (!this._acceptedScripts.has(script))
+ if (!this._acceptedScripts.has(script)) {
return;
+ }
this._acceptedScripts.delete(script);
const project = this._project(script);
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (project.uiSourceCodeForURL(script.sourceURL));
@@ -206,8 +217,9 @@ Bindings.ResourceScriptMapping = class {
_executionContextDestroyed(event) {
const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
const scripts = this._debuggerModel.scriptsForExecutionContext(executionContext);
- for (const script of scripts)
+ for (const script of scripts) {
this._removeScript(script);
+ }
}
/**
@@ -215,33 +227,37 @@ Bindings.ResourceScriptMapping = class {
*/
_globalObjectCleared(event) {
const scripts = Array.from(this._acceptedScripts);
- for (const script of scripts)
+ for (const script of scripts) {
this._removeScript(script);
+ }
}
resetForTest() {
const scripts = Array.from(this._acceptedScripts);
- for (const script of scripts)
+ for (const script of scripts) {
this._removeScript(script);
+ }
}
dispose() {
Common.EventTarget.removeEventListeners(this._eventListeners);
const scripts = Array.from(this._acceptedScripts);
- for (const script of scripts)
+ for (const script of scripts) {
this._removeScript(script);
- for (const project of this._projects.values())
+ }
+ for (const project of this._projects.values()) {
project.removeProject();
+ }
this._projects.clear();
}
-};
+}
/**
* @unrestricted
*/
-Bindings.ResourceScriptFile = class extends Common.Object {
+export class ResourceScriptFile extends Common.Object {
/**
- * @param {!Bindings.ResourceScriptMapping} resourceScriptMapping
+ * @param {!ResourceScriptMapping} resourceScriptMapping
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {!Array.<!SDK.Script>} scripts
*/
@@ -252,8 +268,9 @@ Bindings.ResourceScriptFile = class extends Common.Object {
this._resourceScriptMapping = resourceScriptMapping;
this._uiSourceCode = uiSourceCode;
- if (this._uiSourceCode.contentType().isScript())
+ if (this._uiSourceCode.contentType().isScript()) {
this._script = scripts[scripts.length - 1];
+ }
this._uiSourceCode.addEventListener(
Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
@@ -273,19 +290,24 @@ Bindings.ResourceScriptFile = class extends Common.Object {
* @return {boolean}
*/
_isDiverged() {
- if (this._uiSourceCode.isDirty())
+ if (this._uiSourceCode.isDirty()) {
return true;
- if (!this._script)
+ }
+ if (!this._script) {
return false;
- if (typeof this._scriptSource === 'undefined')
+ }
+ if (typeof this._scriptSource === 'undefined') {
return false;
+ }
const workingCopy = this._uiSourceCode.workingCopy();
- if (!workingCopy)
+ if (!workingCopy) {
return false;
+ }
// Match ignoring sourceURL.
- if (!workingCopy.startsWith(this._scriptSource.trimRight()))
+ if (!workingCopy.startsWith(this._scriptSource.trimRight())) {
return true;
+ }
const suffix = this._uiSourceCode.workingCopy().substr(this._scriptSource.length);
return !!suffix.length && !suffix.match(SDK.Script.sourceURLRegex);
}
@@ -301,10 +323,12 @@ Bindings.ResourceScriptFile = class extends Common.Object {
* @param {!Common.Event} event
*/
_workingCopyCommitted(event) {
- if (this._uiSourceCode.project().canSetFileContent())
+ if (this._uiSourceCode.project().canSetFileContent()) {
return;
- if (!this._script)
+ }
+ if (!this._script) {
return;
+ }
const debuggerModel = this._resourceScriptMapping._debuggerModel;
const breakpoints = Bindings.breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode)
.map(breakpointLocation => breakpointLocation.breakpoint);
@@ -314,11 +338,12 @@ Bindings.ResourceScriptFile = class extends Common.Object {
/**
* @param {?string} error
* @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
- * @this {Bindings.ResourceScriptFile}
+ * @this {ResourceScriptFile}
*/
async function scriptSourceWasSet(error, exceptionDetails) {
- if (!error && !exceptionDetails)
+ if (!error && !exceptionDetails) {
this._scriptSource = source;
+ }
this._update();
if (!error && !exceptionDetails) {
@@ -339,10 +364,11 @@ Bindings.ResourceScriptFile = class extends Common.Object {
}
_update() {
- if (this._isDiverged() && !this._hasDivergedFromVM)
+ if (this._isDiverged() && !this._hasDivergedFromVM) {
this._divergeFromVM();
- else if (!this._isDiverged() && this._hasDivergedFromVM)
+ } else if (!this._isDiverged() && this._hasDivergedFromVM) {
this._mergeToVM();
+ }
}
_divergeFromVM() {
@@ -350,7 +376,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
this._resourceScriptMapping._debuggerWorkspaceBinding.updateLocations(this._script);
delete this._isDivergingFromVM;
this._hasDivergedFromVM = true;
- this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._uiSourceCode);
+ this.dispatchEventToListeners(ResourceScriptFile.Events.DidDivergeFromVM, this._uiSourceCode);
}
_mergeToVM() {
@@ -358,7 +384,7 @@ Bindings.ResourceScriptFile = class extends Common.Object {
this._isMergingToVM = true;
this._resourceScriptMapping._debuggerWorkspaceBinding.updateLocations(this._script);
delete this._isMergingToVM;
- this.dispatchEventToListeners(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._uiSourceCode);
+ this.dispatchEventToListeners(ResourceScriptFile.Events.DidMergeToVM, this._uiSourceCode);
}
/**
@@ -387,17 +413,11 @@ Bindings.ResourceScriptFile = class extends Common.Object {
this._mappingCheckedForTest();
return;
}
- this._script.requestContent().then(callback.bind(this));
-
- /**
- * @param {?string} source
- * @this {Bindings.ResourceScriptFile}
- */
- function callback(source) {
- this._scriptSource = source;
+ this._script.requestContent().then(deferredContent => {
+ this._scriptSource = deferredContent.content;
this._update();
this._mappingCheckedForTest();
- }
+ });
}
_mappingCheckedForTest() {
@@ -414,8 +434,9 @@ Bindings.ResourceScriptFile = class extends Common.Object {
* @param {string} sourceMapURL
*/
addSourceMapURL(sourceMapURL) {
- if (!this._script)
+ if (!this._script) {
return;
+ }
this._script.debuggerModel.setSourceMapURL(this._script, sourceMapURL);
}
@@ -425,12 +446,26 @@ Bindings.ResourceScriptFile = class extends Common.Object {
hasSourceMapURL() {
return this._script && !!this._script.sourceMapURL;
}
-};
+}
-Bindings.ResourceScriptMapping._frameIdSymbol = Symbol('frameid');
+export const _frameIdSymbol = Symbol('frameid');
/** @enum {symbol} */
-Bindings.ResourceScriptFile.Events = {
+ResourceScriptFile.Events = {
DidMergeToVM: Symbol('DidMergeToVM'),
DidDivergeFromVM: Symbol('DidDivergeFromVM'),
};
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.ResourceScriptMapping = ResourceScriptMapping;
+
+Bindings.ResourceScriptMapping._frameIdSymbol = _frameIdSymbol;
+
+/** @constructor */
+Bindings.ResourceScriptFile = ResourceScriptFile; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceUtils.js
index 917741ba647..bb4c3e46c4c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/ResourceUtils.js
@@ -31,59 +31,67 @@
* @param {string} url
* @return {?SDK.Resource}
*/
-Bindings.resourceForURL = function(url) {
+export function resourceForURL(url) {
for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
const resource = resourceTreeModel.resourceForURL(url);
- if (resource)
+ if (resource) {
return resource;
+ }
}
return null;
-};
+}
/**
* @param {function(!SDK.Resource)} callback
*/
-Bindings.forAllResources = function(callback) {
- for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel))
+export function forAllResources(callback) {
+ for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
resourceTreeModel.forAllResources(callback);
-};
+ }
+}
/**
* @param {string} url
* @return {string}
*/
-Bindings.displayNameForURL = function(url) {
- if (!url)
+export function displayNameForURL(url) {
+ if (!url) {
return '';
+ }
const resource = Bindings.resourceForURL(url);
- if (resource)
+ if (resource) {
return resource.displayName;
+ }
const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
- if (uiSourceCode)
+ if (uiSourceCode) {
return uiSourceCode.displayName();
+ }
const mainTarget = SDK.targetManager.mainTarget();
const inspectedURL = mainTarget && mainTarget.inspectedURL();
- if (!inspectedURL)
+ if (!inspectedURL) {
return url.trimURL('');
+ }
const parsedURL = inspectedURL.asParsedURL();
const lastPathComponent = parsedURL ? parsedURL.lastPathComponent : parsedURL;
const index = inspectedURL.indexOf(lastPathComponent);
if (index !== -1 && index + lastPathComponent.length === inspectedURL.length) {
const baseURL = inspectedURL.substring(0, index);
- if (url.startsWith(baseURL))
+ if (url.startsWith(baseURL)) {
return url.substring(index);
+ }
}
- if (!parsedURL)
+ if (!parsedURL) {
return url;
+ }
const displayName = url.trimURL(parsedURL.host);
return displayName === '/' ? parsedURL.host + '/' : displayName;
-};
+}
/**
* @param {!SDK.Target} target
@@ -91,37 +99,55 @@ Bindings.displayNameForURL = function(url) {
* @param {string} url
* @return {?Workspace.UISourceCodeMetadata}
*/
-Bindings.metadataForURL = function(target, frameId, url) {
+export function metadataForURL(target, frameId, url) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
- if (!resourceTreeModel)
+ if (!resourceTreeModel) {
return null;
+ }
const frame = resourceTreeModel.frameForId(frameId);
- if (!frame)
+ if (!frame) {
return null;
+ }
return Bindings.resourceMetadata(frame.resourceForURL(url));
-};
+}
/**
* @param {?SDK.Resource} resource
* @return {?Workspace.UISourceCodeMetadata}
*/
-Bindings.resourceMetadata = function(resource) {
- if (!resource || (typeof resource.contentSize() !== 'number' && !resource.lastModified()))
+export function resourceMetadata(resource) {
+ if (!resource || (typeof resource.contentSize() !== 'number' && !resource.lastModified())) {
return null;
+ }
return new Workspace.UISourceCodeMetadata(resource.lastModified(), resource.contentSize());
-};
+}
/**
* @param {!SDK.Script} script
* @return {string}
*/
-Bindings.frameIdForScript = function(script) {
+export function frameIdForScript(script) {
const executionContext = script.executionContext();
- if (executionContext)
+ if (executionContext) {
return executionContext.frameId || '';
+ }
// This is to overcome compilation cache which doesn't get reset.
const resourceTreeModel = script.debuggerModel.target().model(SDK.ResourceTreeModel);
- if (!resourceTreeModel || !resourceTreeModel.mainFrame)
+ if (!resourceTreeModel || !resourceTreeModel.mainFrame) {
return '';
+ }
return resourceTreeModel.mainFrame.id;
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+Bindings.resourceForURL = resourceForURL;
+Bindings.forAllResources = forAllResources;
+Bindings.displayNameForURL = displayNameForURL;
+Bindings.metadataForURL = metadataForURL;
+Bindings.resourceMetadata = resourceMetadata;
+Bindings.frameIdForScript = frameIdForScript;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/SASSSourceMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/SASSSourceMapping.js
index c1062369db5..7e4f350d98a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/SASSSourceMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/SASSSourceMapping.js
@@ -31,7 +31,7 @@
/**
* @implements {Bindings.CSSWorkspaceBinding.SourceMapping}
*/
-Bindings.SASSSourceMapping = class {
+export default class SASSSourceMapping {
/**
* @param {!SDK.Target} target
* @param {!SDK.SourceMapManager} sourceMapManager
@@ -79,7 +79,7 @@ Bindings.SASSSourceMapping = class {
typeof embeddedContent === 'string' ? new Workspace.UISourceCodeMetadata(null, embeddedContent.length) : null;
uiSourceCode = this._project.createUISourceCode(sassURL, contentProvider.contentType());
Bindings.NetworkProject.setInitialFrameAttribution(uiSourceCode, header.frameId);
- uiSourceCode[Bindings.SASSSourceMapping._sourceMapSymbol] = sourceMap;
+ uiSourceCode[_sourceMapSymbol] = sourceMap;
this._project.addUISourceCodeWithProvider(uiSourceCode, contentProvider, metadata, mimeType);
}
Bindings.cssWorkspaceBinding.updateLocations(header);
@@ -120,8 +120,9 @@ Bindings.SASSSourceMapping = class {
const sassText = /** @type {string} */ (newSources.get(sourceURL));
uiSourceCode.setWorkingCopy(sassText);
}
- for (const header of headers)
+ for (const header of headers) {
Bindings.cssWorkspaceBinding.updateLocations(header);
+ }
}
/**
@@ -131,17 +132,21 @@ Bindings.SASSSourceMapping = class {
*/
rawLocationToUILocation(rawLocation) {
const header = rawLocation.header();
- if (!header)
+ if (!header) {
return null;
+ }
const sourceMap = this._sourceMapManager.sourceMapForClient(header);
- if (!sourceMap)
+ if (!sourceMap) {
return null;
+ }
const entry = sourceMap.findEntry(rawLocation.lineNumber, rawLocation.columnNumber);
- if (!entry || !entry.sourceURL)
+ if (!entry || !entry.sourceURL) {
return null;
+ }
const uiSourceCode = this._project.uiSourceCodeForURL(entry.sourceURL);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return null;
+ }
return uiSourceCode.uiLocation(entry.sourceLineNumber || 0, entry.sourceColumnNumber);
}
@@ -151,14 +156,16 @@ Bindings.SASSSourceMapping = class {
* @return {!Array<!SDK.CSSLocation>}
*/
uiLocationToRawLocations(uiLocation) {
- const sourceMap = uiLocation.uiSourceCode[Bindings.SASSSourceMapping._sourceMapSymbol];
- if (!sourceMap)
+ const sourceMap = uiLocation.uiSourceCode[_sourceMapSymbol];
+ if (!sourceMap) {
return [];
+ }
const entries =
sourceMap.findReverseEntries(uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber);
const locations = [];
- for (const header of this._sourceMapManager.clientsForSourceMap(sourceMap))
+ for (const header of this._sourceMapManager.clientsForSourceMap(sourceMap)) {
locations.pushAll(entries.map(entry => new SDK.CSSLocation(header, entry.lineNumber, entry.columnNumber)));
+ }
return locations;
}
@@ -166,6 +173,17 @@ Bindings.SASSSourceMapping = class {
this._project.dispose();
Common.EventTarget.removeEventListeners(this._eventListeners);
}
-};
+}
+
+export const _sourceMapSymbol = Symbol('sourceMap');
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.SASSSourceMapping = SASSSourceMapping;
-Bindings.SASSSourceMapping._sourceMapSymbol = Symbol('sourceMap');
+Bindings.SASSSourceMapping._sourceMapSymbol = _sourceMapSymbol;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/StylesSourceMapping.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/StylesSourceMapping.js
index 1b8877aa9f7..fbd06788b9c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/StylesSourceMapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/StylesSourceMapping.js
@@ -32,7 +32,7 @@
* @implements {Bindings.CSSWorkspaceBinding.SourceMapping}
* @unrestricted
*/
-Bindings.StylesSourceMapping = class {
+export default class StylesSourceMapping {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Workspace.Workspace} workspace
@@ -44,7 +44,7 @@ Bindings.StylesSourceMapping = class {
workspace, 'css:' + target.id(), Workspace.projectTypes.Network, '', false /* isServiceProject */);
Bindings.NetworkProject.setTargetForProject(this._project, target);
- /** @type {!Map.<string, !Bindings.StyleFile>} */
+ /** @type {!Map.<string, !StyleFile>} */
this._styleFiles = new Map();
this._eventListeners = [
this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this),
@@ -60,11 +60,13 @@ Bindings.StylesSourceMapping = class {
*/
rawLocationToUILocation(rawLocation) {
const header = rawLocation.header();
- if (!header || !this._acceptsHeader(header))
+ if (!header || !this._acceptsHeader(header)) {
return null;
+ }
const styleFile = this._styleFiles.get(header.resourceURL());
- if (!styleFile)
+ if (!styleFile) {
return null;
+ }
let lineNumber = rawLocation.lineNumber;
let columnNumber = rawLocation.columnNumber;
if (header.isInline && header.hasSourceURL) {
@@ -80,9 +82,10 @@ Bindings.StylesSourceMapping = class {
* @return {!Array<!SDK.CSSLocation>}
*/
uiLocationToRawLocations(uiLocation) {
- const styleFile = uiLocation.uiSourceCode[Bindings.StyleFile._symbol];
- if (!styleFile)
+ const styleFile = uiLocation.uiSourceCode[StyleFile._symbol];
+ if (!styleFile) {
return [];
+ }
const rawLocations = [];
for (const header of styleFile._headers) {
let lineNumber = uiLocation.lineNumber;
@@ -100,10 +103,12 @@ Bindings.StylesSourceMapping = class {
* @param {!SDK.CSSStyleSheetHeader} header
*/
_acceptsHeader(header) {
- if (header.isInline && !header.hasSourceURL && header.origin !== 'inspector')
+ if (header.isInline && !header.hasSourceURL && header.origin !== 'inspector') {
return false;
- if (!header.resourceURL())
+ }
+ if (!header.resourceURL()) {
return false;
+ }
return true;
}
@@ -112,13 +117,14 @@ Bindings.StylesSourceMapping = class {
*/
_styleSheetAdded(event) {
const header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
- if (!this._acceptsHeader(header))
+ if (!this._acceptsHeader(header)) {
return;
+ }
const url = header.resourceURL();
let styleFile = this._styleFiles.get(url);
if (!styleFile) {
- styleFile = new Bindings.StyleFile(this._cssModel, this._project, header);
+ styleFile = new StyleFile(this._cssModel, this._project, header);
this._styleFiles.set(url, styleFile);
} else {
styleFile.addHeader(header);
@@ -130,8 +136,9 @@ Bindings.StylesSourceMapping = class {
*/
_styleSheetRemoved(event) {
const header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
- if (!this._acceptsHeader(header))
+ if (!this._acceptsHeader(header)) {
return;
+ }
const url = header.resourceURL();
const styleFile = this._styleFiles.get(url);
if (styleFile._headers.size === 1) {
@@ -147,26 +154,28 @@ Bindings.StylesSourceMapping = class {
*/
_styleSheetChanged(event) {
const header = this._cssModel.styleSheetHeaderForId(event.data.styleSheetId);
- if (!header || !this._acceptsHeader(header))
+ if (!header || !this._acceptsHeader(header)) {
return;
+ }
const styleFile = this._styleFiles.get(header.resourceURL());
styleFile._styleSheetChanged(header);
}
dispose() {
- for (const styleFile of this._styleFiles.values())
+ for (const styleFile of this._styleFiles.values()) {
styleFile.dispose();
+ }
this._styleFiles.clear();
Common.EventTarget.removeEventListeners(this._eventListeners);
this._project.removeProject();
}
-};
+}
/**
* @implements {Common.ContentProvider}
* @unrestricted
*/
-Bindings.StyleFile = class {
+export class StyleFile {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Bindings.ContentProviderBasedProject} project
@@ -184,7 +193,7 @@ Bindings.StyleFile = class {
const metadata = Bindings.metadataForURL(target, header.frameId, url);
this._uiSourceCode = this._project.createUISourceCode(url, header.contentType());
- this._uiSourceCode[Bindings.StyleFile._symbol] = this;
+ this._uiSourceCode[StyleFile._symbol] = this;
Bindings.NetworkProject.setInitialFrameAttribution(this._uiSourceCode, header.frameId);
this._project.addUISourceCodeWithProvider(this._uiSourceCode, this, metadata, 'text/css');
@@ -194,7 +203,7 @@ Bindings.StyleFile = class {
this._uiSourceCode.addEventListener(
Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this)
];
- this._throttler = new Common.Throttler(Bindings.StyleFile.updateTimeout);
+ this._throttler = new Common.Throttler(StyleFile.updateTimeout);
this._terminated = false;
}
@@ -219,8 +228,9 @@ Bindings.StyleFile = class {
*/
_styleSheetChanged(header) {
console.assert(this._headers.has(header));
- if (this._isUpdatingHeaders || !this._headers.has(header))
+ if (this._isUpdatingHeaders || !this._headers.has(header)) {
return;
+ }
const mirrorContentBound = this._mirrorContent.bind(this, header, true /* majorChange */);
this._throttler.schedule(mirrorContentBound, false /* asSoonAsPossible */);
}
@@ -229,8 +239,9 @@ Bindings.StyleFile = class {
* @param {!Common.Event} event
*/
_workingCopyCommitted(event) {
- if (this._isAddingRevision)
+ if (this._isAddingRevision) {
return;
+ }
const mirrorContentBound = this._mirrorContent.bind(this, this._uiSourceCode, true /* majorChange */);
this._throttler.schedule(mirrorContentBound, true /* asSoonAsPossible */);
}
@@ -239,8 +250,9 @@ Bindings.StyleFile = class {
* @param {!Common.Event} event
*/
_workingCopyChanged(event) {
- if (this._isAddingRevision)
+ if (this._isAddingRevision) {
return;
+ }
const mirrorContentBound = this._mirrorContent.bind(this, this._uiSourceCode, false /* majorChange */);
this._throttler.schedule(mirrorContentBound, false /* asSoonAsPossible */);
}
@@ -260,8 +272,8 @@ Bindings.StyleFile = class {
if (fromProvider === this._uiSourceCode) {
newContent = this._uiSourceCode.workingCopy();
} else {
- // ------ ASYNC ------
- newContent = await fromProvider.requestContent();
+ const deferredContent = await fromProvider.requestContent();
+ newContent = deferredContent.content;
}
if (newContent === null || this._terminated) {
@@ -278,8 +290,9 @@ Bindings.StyleFile = class {
this._isUpdatingHeaders = true;
const promises = [];
for (const header of this._headers) {
- if (header === fromProvider)
+ if (header === fromProvider) {
continue;
+ }
promises.push(this._cssModel.setStyleSheetText(header.id, newContent, majorChange));
}
// ------ ASYNC ------
@@ -292,8 +305,9 @@ Bindings.StyleFile = class {
}
dispose() {
- if (this._terminated)
+ if (this._terminated) {
return;
+ }
this._terminated = true;
this._project.removeFile(this._uiSourceCode.url());
Common.EventTarget.removeEventListeners(this._eventListeners);
@@ -325,7 +339,7 @@ Bindings.StyleFile = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
return this._headers.firstValue().originalContentProvider().requestContent();
@@ -341,8 +355,20 @@ Bindings.StyleFile = class {
searchInContent(query, caseSensitive, isRegex) {
return this._headers.firstValue().originalContentProvider().searchInContent(query, caseSensitive, isRegex);
}
-};
+}
+
+StyleFile._symbol = Symbol('Bindings.StyleFile._symbol');
+
+StyleFile.updateTimeout = 200;
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
-Bindings.StyleFile._symbol = Symbol('Bindings.StyleFile._symbol');
+/** @constructor */
+Bindings.StylesSourceMapping = StylesSourceMapping;
-Bindings.StyleFile.updateTimeout = 200;
+/** @constructor */
+Bindings.StyleFile = StyleFile;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/TempFile.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/TempFile.js
index 9d74521e912..cc1fdee81d3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/TempFile.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/TempFile.js
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-Bindings.TempFile = class {
+export default class TempFile {
constructor() {
/** @type {?Blob} */
this._lastBlob = null;
@@ -38,8 +38,9 @@ Bindings.TempFile = class {
* @param {!Array<string|!Blob>} pieces
*/
write(pieces) {
- if (this._lastBlob)
+ if (this._lastBlob) {
pieces.unshift(this._lastBlob);
+ }
this._lastBlob = new Blob(pieces, {type: 'text/plain'});
}
@@ -82,7 +83,7 @@ Bindings.TempFile = class {
Common.console.error('Failed to read from temp file: ' + error.message);
}
- return reader.result;
+ return /** @type {?string} */ (reader.result);
}
/**
@@ -102,14 +103,14 @@ Bindings.TempFile = class {
remove() {
this._lastBlob = null;
}
-};
+}
/**
* @implements {SDK.BackingStorage}
*/
-Bindings.TempFileBackingStorage = class {
+export class TempFileBackingStorage {
constructor() {
- /** @type {?Bindings.TempFile} */
+ /** @type {?TempFile} */
this._file = null;
/** @type {!Array<string>} */
this._strings;
@@ -126,8 +127,9 @@ Bindings.TempFileBackingStorage = class {
this._strings.push(string);
this._stringsLength += string.length;
const flushStringLength = 10 * 1024 * 1024;
- if (this._stringsLength > flushStringLength)
+ if (this._stringsLength > flushStringLength) {
this._flush();
+ }
}
/**
@@ -144,10 +146,12 @@ Bindings.TempFileBackingStorage = class {
}
_flush() {
- if (!this._strings.length)
+ if (!this._strings.length) {
return;
- if (!this._file)
- this._file = new Bindings.TempFile();
+ }
+ if (!this._file) {
+ this._file = new TempFile();
+ }
this._stringsLength = 0;
this._file.write(this._strings.splice(0));
}
@@ -163,8 +167,9 @@ Bindings.TempFileBackingStorage = class {
* @override
*/
reset() {
- if (this._file)
+ if (this._file) {
this._file.remove();
+ }
this._file = null;
/** @type {!Array<string>} */
this._strings = [];
@@ -178,12 +183,24 @@ Bindings.TempFileBackingStorage = class {
writeToStream(outputStream) {
return this._file ? this._file.copyToOutputStream(outputStream) : Promise.resolve(null);
}
-};
+}
+
+/* Legacy exported object */
+self.Bindings = self.Bindings || {};
+
+/* Legacy exported object */
+Bindings = Bindings || {};
+
+/** @constructor */
+Bindings.TempFile = TempFile;
+
+/** @constructor */
+Bindings.TempFileBackingStorage = TempFileBackingStorage;
/**
* @typedef {{
- * startOffset: number,
- * endOffset: number
- * }}
- */
+ * startOffset: number,
+ * endOffset: number
+ * }}
+ */
Bindings.TempFileBackingStorage.Chunk;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings.js
new file mode 100644
index 00000000000..ad6fd2fcada
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings.js
@@ -0,0 +1,44 @@
+// 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 './LiveLocation.js';
+import './ResourceMapping.js';
+
+import * as BlackboxManager from './BlackboxManager.js';
+import * as BreakpointManager from './BreakpointManager.js';
+import * as CompilerScriptMapping from './CompilerScriptMapping.js';
+import * as ContentProviderBasedProject from './ContentProviderBasedProject.js';
+import * as CSSWorkspaceBinding from './CSSWorkspaceBinding.js';
+import * as DebuggerWorkspaceBinding from './DebuggerWorkspaceBinding.js';
+import * as DefaultScriptMapping from './DefaultScriptMapping.js';
+import * as FileUtils from './FileUtils.js';
+import * as LiveLocation from './LiveLocation.js';
+import * as NetworkProject from './NetworkProject.js';
+import * as PresentationConsoleMessageHelper from './PresentationConsoleMessageHelper.js';
+import * as ResourceMapping from './ResourceMapping.js';
+import * as ResourceScriptMapping from './ResourceScriptMapping.js';
+import * as ResourceUtils from './ResourceUtils.js';
+import * as SASSSourceMapping from './SASSSourceMapping.js';
+import * as StylesSourceMapping from './StylesSourceMapping.js';
+import * as TempFile from './TempFile.js';
+
+export {
+ BlackboxManager,
+ BreakpointManager,
+ CompilerScriptMapping,
+ ContentProviderBasedProject,
+ CSSWorkspaceBinding,
+ DebuggerWorkspaceBinding,
+ DefaultScriptMapping,
+ FileUtils,
+ LiveLocation,
+ NetworkProject,
+ PresentationConsoleMessageHelper,
+ ResourceMapping,
+ ResourceScriptMapping,
+ ResourceUtils,
+ SASSSourceMapping,
+ StylesSourceMapping,
+ TempFile,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp
index 948dfcfe383..2a9b5d4f5da 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/bindings_strings.grdp
@@ -3,6 +3,9 @@
<message name="IDS_DEVTOOLS_412dac8227bbaf752fecaad8826f20e6" desc="Text in Resource Script Mapping">
LiveEdit failed: <ph name="ERROR">$1s<ex>warning</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_5e2c3eac46d298d72b51f1500601d7be" desc="Error message that is displayed in the Sources panel when can't be loaded.">
+ Unknown error loading file
+ </message>
<message name="IDS_DEVTOOLS_d3ff22990e37ccce8a501ffba38626b7" desc="Text in Resource Script Mapping">
LiveEdit compile failed: <ph name="EXCEPTIONDETAILS_TEXT">$1s<ex>connection lost</ex></ph>
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/module.json b/chromium/third_party/blink/renderer/devtools/front_end/bindings/module.json
index 918802ab2c5..eb6f9ef7a2f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/module.json
@@ -5,7 +5,9 @@
"services",
"workspace"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "bindings.js",
"LiveLocation.js",
"ResourceMapping.js",
"CompilerScriptMapping.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js
index 4a4ed69e94d..ddc35188117 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/AutomappingTestRunner.js
@@ -24,20 +24,23 @@ BindingsTestRunner.overrideNetworkModificationTime = function(urlToTime) {
TestRunner.override(Bindings.ContentProviderBasedProject.prototype, 'requestMetadata', overrideTime, true);
}
- for (const url in urlToTime)
+ for (const url in urlToTime) {
timeOverrides.set(url, urlToTime[url]);
+ }
function overrideTime(uiSourceCode) {
- if (!timeOverrides.has(uiSourceCode.url()))
+ if (!timeOverrides.has(uiSourceCode.url())) {
return originalRequestMetadata.call(this, uiSourceCode);
+ }
const override = timeOverrides.get(uiSourceCode.url());
return originalRequestMetadata.call(this, uiSourceCode).then(onOriginalMetadata.bind(null, override));
}
function onOriginalMetadata(timeOverride, metadata) {
- if (!timeOverride && !metadata)
+ if (!timeOverride && !metadata) {
return null;
+ }
return new Workspace.UISourceCodeMetadata(timeOverride, (metadata ? metadata.contentSize : null));
}
@@ -48,8 +51,9 @@ BindingsTestRunner.AutomappingTest = function(workspace) {
this._networkProject = new Bindings.ContentProviderBasedProject(
this._workspace, 'AUTOMAPPING', Workspace.projectTypes.Network, 'simple website');
- if (workspace !== Workspace.workspace)
+ if (workspace !== Workspace.workspace) {
new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, this._workspace);
+ }
this._failedBindingsCount = 0;
this._automapping =
@@ -60,8 +64,9 @@ BindingsTestRunner.AutomappingTest = function(workspace) {
BindingsTestRunner.AutomappingTest.prototype = {
removeResources: function(urls) {
- for (const url of urls)
+ for (const url of urls) {
this._networkProject.removeFile(url);
+ }
},
addNetworkResources: function(assets) {
@@ -105,8 +110,9 @@ BindingsTestRunner.AutomappingTest.prototype = {
},
_checkStabilized: function() {
- if (!this._stabilizedCallback || this._automapping._sweepThrottler._process)
+ if (!this._stabilizedCallback || this._automapping._sweepThrottler._process) {
return;
+ }
const networkUISourceCodes = this._workspace.uiSourceCodesForProjectType(Workspace.projectTypes.Network);
const stabilized = this._failedBindingsCount + this._automapping._statuses.size === networkUISourceCodes.length;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/BindingsTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/BindingsTestRunner.js
index 472853f52f8..1bb4941e63b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/BindingsTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/BindingsTestRunner.js
@@ -8,8 +8,9 @@
*/
BindingsTestRunner.cleanupURL = function(url) {
- if (!url.startsWith('debugger://'))
+ if (!url.startsWith('debugger://')) {
return url;
+ }
return url.replace(/VM\d+/g, 'VM[XXX]');
};
@@ -31,8 +32,9 @@ BindingsTestRunner.dumpWorkspace = function(previousSnapshot) {
let index = 0;
for (const entry of diff) {
- if (entry[0] === Diff.Diff.Operation.Delete)
+ if (entry[0] === Diff.Diff.Operation.Delete) {
continue;
+ }
if (entry[0] === Diff.Diff.Operation.Equal) {
index += entry[1].length;
@@ -40,8 +42,9 @@ BindingsTestRunner.dumpWorkspace = function(previousSnapshot) {
}
// eslint-disable-next-line no-unused-vars
- for (const line of entry[1])
+ for (const line of entry[1]) {
isAdded[index++] = true;
+ }
}
const addedEntries = diff.filter(entry => entry[0] === Diff.Diff.Operation.Insert).map(entry => entry[1]);
@@ -50,8 +53,9 @@ BindingsTestRunner.dumpWorkspace = function(previousSnapshot) {
TestRunner.addResult(`Removed: ${removedLines.length} uiSourceCodes`);
- for (const url of removedLines)
+ for (const url of removedLines) {
TestRunner.addResult('[-] ' + url);
+ }
TestRunner.addResult(`Workspace: ${urls.length} uiSourceCodes.`);
@@ -67,8 +71,9 @@ BindingsTestRunner.dumpWorkspace = function(previousSnapshot) {
BindingsTestRunner.attachFrame = function(frameId, url, evalSourceURL) {
let evalSource = `(${attachFrame.toString()})('${frameId}', '${url}')`;
- if (evalSourceURL)
+ if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
+ }
return TestRunner.evaluateInPageAsync(evalSource);
@@ -84,8 +89,9 @@ BindingsTestRunner.attachFrame = function(frameId, url, evalSourceURL) {
BindingsTestRunner.detachFrame = function(frameId, evalSourceURL) {
let evalSource = `(${detachFrame.toString()})('${frameId}')`;
- if (evalSourceURL)
+ if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
+ }
return TestRunner.evaluateInPageAnonymously(evalSource);
@@ -98,8 +104,9 @@ BindingsTestRunner.detachFrame = function(frameId, evalSourceURL) {
BindingsTestRunner.navigateFrame = function(frameId, navigateURL, evalSourceURL) {
let evalSource = `(${navigateFrame.toString()})('${frameId}', '${navigateURL}')`;
- if (evalSourceURL)
+ if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
+ }
return TestRunner.evaluateInPageAsync(evalSource);
@@ -113,8 +120,9 @@ BindingsTestRunner.navigateFrame = function(frameId, navigateURL, evalSourceURL)
BindingsTestRunner.attachShadowDOM = function(id, templateSelector, evalSourceURL) {
let evalSource = `(${createShadowDOM.toString()})('${id}', '${templateSelector}')`;
- if (evalSourceURL)
+ if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
+ }
return TestRunner.evaluateInPageAnonymously(evalSource);
@@ -134,8 +142,9 @@ BindingsTestRunner.attachShadowDOM = function(id, templateSelector, evalSourceUR
BindingsTestRunner.detachShadowDOM = function(id, evalSourceURL) {
let evalSource = `(${removeShadowDOM.toString()})('${id}')`;
- if (evalSourceURL)
+ if (evalSourceURL) {
evalSource += '//# sourceURL=' + evalSourceURL;
+ }
return TestRunner.evaluateInPageAnonymously(evalSource);
@@ -153,8 +162,9 @@ BindingsTestRunner.waitForStyleSheetRemoved = function(urlSuffix) {
function onStyleSheetRemoved(event) {
const styleSheetHeader = event.data;
- if (!styleSheetHeader.resourceURL().endsWith(urlSuffix))
+ if (!styleSheetHeader.resourceURL().endsWith(urlSuffix)) {
return;
+ }
TestRunner.cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, onStyleSheetRemoved);
fulfill();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
index a6e75d1302e..b450cdf968b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
@@ -7,7 +7,7 @@
* @suppress {accessControls}
*/
-InspectorFrontendHost.isolatedFileSystem = function(name) {
+Host.InspectorFrontendHost.isolatedFileSystem = function(name) {
return BindingsTestRunner.TestFileSystem._instances[name];
};
@@ -29,8 +29,9 @@ BindingsTestRunner.TestFileSystem.prototype = {
result.push(indent + node.name);
const newIndent = indent + ' ';
- for (const child of node._children)
+ for (const child of node._children) {
dfs(child, newIndent);
+ }
}
},
@@ -42,8 +43,8 @@ BindingsTestRunner.TestFileSystem.prototype = {
const fileSystemPath = this.fileSystemPath;
BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath] = this;
- InspectorFrontendHost.events.dispatchEventToListeners(
- InspectorFrontendHostAPI.Events.FileSystemAdded,
+ Host.InspectorFrontendHost.events.dispatchEventToListeners(
+ Host.InspectorFrontendHostAPI.Events.FileSystemAdded,
{fileSystem: {fileSystemPath: this.fileSystemPath, fileSystemName: this.fileSystemPath, type}});
Persistence.isolatedFileSystemManager.addEventListener(
@@ -52,8 +53,9 @@ BindingsTestRunner.TestFileSystem.prototype = {
function created(event) {
const fileSystem = event.data;
- if (fileSystem.path() !== fileSystemPath)
+ if (fileSystem.path() !== fileSystemPath) {
return;
+ }
Persistence.isolatedFileSystemManager.removeEventListener(
Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, created);
@@ -63,8 +65,8 @@ BindingsTestRunner.TestFileSystem.prototype = {
reportRemoved: function() {
delete BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath];
- InspectorFrontendHost.events.dispatchEventToListeners(
- InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath);
+ Host.InspectorFrontendHost.events.dispatchEventToListeners(
+ Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath);
},
addFile: function(path, content, lastModified) {
@@ -76,16 +78,18 @@ BindingsTestRunner.TestFileSystem.prototype = {
for (const folder of folders) {
let dir = node._childrenMap[folder];
- if (!dir)
+ if (!dir) {
dir = node.mkdir(folder);
+ }
node = dir;
}
const file = node.addFile(fileName, content);
- if (lastModified)
+ if (lastModified) {
file._timestamp = lastModified;
+ }
return file;
}
@@ -123,8 +127,8 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
delete this._childrenMap[child.name];
child.parent = null;
- InspectorFrontendHost.events.dispatchEventToListeners(
- InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
+ Host.InspectorFrontendHost.events.dispatchEventToListeners(
+ Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
{changed: [], added: [], removed: [fullPath]});
success();
@@ -148,8 +152,8 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
const fullPath = this._fileSystem.fileSystemPath + child.fullPath;
- InspectorFrontendHost.events.dispatchEventToListeners(
- InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
+ Host.InspectorFrontendHost.events.dispatchEventToListeners(
+ Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
{changed: [], added: [fullPath], removed: []});
return child;
@@ -161,8 +165,8 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
this._timestamp += 1000;
const fullPath = this._fileSystem.fileSystemPath + this.fullPath;
- InspectorFrontendHost.events.dispatchEventToListeners(
- InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
+ Host.InspectorFrontendHost.events.dispatchEventToListeners(
+ Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved,
{changed: [fullPath], added: [], removed: []});
},
@@ -191,8 +195,9 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
const name = tokens.pop();
let parentEntry = this;
- for (const token of tokens)
+ for (const token of tokens) {
parentEntry = parentEntry._childrenMap[token];
+ }
let entry = parentEntry._childrenMap[name];
@@ -201,15 +206,17 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
return;
}
- if (!entry)
+ if (!entry) {
entry = parentEntry.addFile(name, '');
+ }
callback(entry);
},
getEntry: function(path, options, callback, errorCallback) {
- if (path.startsWith('/'))
+ if (path.startsWith('/')) {
path = path.substring(1);
+ }
if (options && options.create) {
this._createEntry(path, options, callback, errorCallback);
@@ -225,8 +232,9 @@ BindingsTestRunner.TestFileSystem.Entry.prototype = {
for (const token of path.split('/')) {
entry = entry._childrenMap[token];
- if (!entry)
+ if (!entry) {
break;
+ }
}
(entry ? callback(entry) : errorCallback(new DOMException('Path not found: ' + path, 'NotFoundError')));
@@ -273,15 +281,17 @@ BindingsTestRunner.TestFileSystem.Writer.prototype = {
this._entry._timestamp += this._modificationTimesDelta;
this._entry.content = blob;
- if (this.onwriteend)
+ if (this.onwriteend) {
this.onwriteend();
+ }
},
truncate: function(num) {
this._entry._timestamp += this._modificationTimesDelta;
this._entry.content = this._entry.content.slice(0, num);
- if (this.onwriteend)
+ if (this.onwriteend) {
this.onwriteend();
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js
index b142dd674ff..505e014bff7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings_test_runner/PersistenceTestRunner.js
@@ -29,11 +29,13 @@ BindingsTestRunner.waitForBinding = function(fileName) {
for (const uiSourceCode of uiSourceCodes) {
const binding = Persistence.persistence.binding(uiSourceCode);
- if (!binding)
+ if (!binding) {
continue;
+ }
- if (uiSourceCode.name() === fileName)
+ if (uiSourceCode.name() === fileName) {
return Promise.resolve(binding);
+ }
}
return TestRunner.waitForEvent(
@@ -75,8 +77,9 @@ class TestMapping {
_findBinding(urlSuffix) {
for (const binding of this._bindings) {
- if (binding.network.url().endsWith(urlSuffix))
+ if (binding.network.url().endsWith(urlSuffix)) {
return binding;
+ }
}
return null;
@@ -96,8 +99,9 @@ class TestMapping {
}
dispose() {
- for (const binding of this._bindings)
+ for (const binding of this._bindings) {
this._persistence.removeBindingForTest(binding);
+ }
this._bindings.clear();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/DOMBreakpointsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/DOMBreakpointsSidebarPane.js
index 67a94a8a064..7689b54ef15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/DOMBreakpointsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/DOMBreakpointsSidebarPane.js
@@ -51,8 +51,9 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
for (const domDebuggerModel of SDK.targetManager.models(SDK.DOMDebuggerModel)) {
domDebuggerModel.retrieveDOMBreakpoints();
- for (const breakpoint of domDebuggerModel.domBreakpoints())
+ for (const breakpoint of domDebuggerModel.domBreakpoints()) {
this._addBreakpoint(breakpoint);
+ }
}
this._highlightedElement = null;
@@ -72,8 +73,9 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
_breakpointToggled(event) {
const breakpoint = /** @type {!SDK.DOMDebuggerModel.DOMBreakpoint} */ (event.data);
const item = this._items.get(breakpoint);
- if (item)
+ if (item) {
item.checkbox.checked = breakpoint.enabled;
+ }
}
/**
@@ -109,13 +111,16 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
const labelElement = createElementWithClass('div', 'dom-breakpoint');
element.appendChild(labelElement);
+ const description = createElement('div');
+ const breakpointTypeLabel = BrowserDebugger.DOMBreakpointsSidebarPane.BreakpointTypeLabels.get(breakpoint.type);
+ description.textContent = breakpointTypeLabel;
const linkifiedNode = createElementWithClass('monospace');
linkifiedNode.style.display = 'block';
labelElement.appendChild(linkifiedNode);
- Common.Linkifier.linkify(breakpoint.node).then(linkified => linkifiedNode.appendChild(linkified));
-
- const description = createElement('div');
- description.textContent = BrowserDebugger.DOMBreakpointsSidebarPane.BreakpointTypeLabels.get(breakpoint.type);
+ Common.Linkifier.linkify(breakpoint.node).then(linkified => {
+ linkifiedNode.appendChild(linkified);
+ UI.ARIAUtils.setAccessibleName(checkboxElement, ls`${breakpointTypeLabel}: ${linkified.deepTextContent()}`);
+ });
labelElement.appendChild(description);
const item = {breakpoint: breakpoint, element: element, checkbox: checkboxElement};
@@ -124,8 +129,9 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
let currentElement = this._listElement.firstChild;
while (currentElement) {
- if (currentElement._item && currentElement._item.breakpoint.type < breakpoint.type)
+ if (currentElement._item && currentElement._item.breakpoint.type < breakpoint.type) {
break;
+ }
currentElement = currentElement.nextSibling;
}
this._listElement.insertBefore(element, currentElement);
@@ -153,8 +159,9 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
*/
_checkboxClicked(breakpoint) {
const item = this._items.get(breakpoint);
- if (!item)
+ if (!item) {
return;
+ }
breakpoint.domDebuggerModel.toggleDOMBreakpoint(breakpoint, item.checkbox.checked);
}
@@ -176,19 +183,23 @@ BrowserDebugger.DOMBreakpointsSidebarPane = class extends UI.VBox {
return;
}
const domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel);
- if (!domDebuggerModel)
+ if (!domDebuggerModel) {
return;
+ }
const data = domDebuggerModel.resolveDOMBreakpointData(/** @type {!Object} */ (details.auxData));
- if (!data)
+ if (!data) {
return;
+ }
let element = null;
for (const item of this._items.values()) {
- if (item.breakpoint.node === data.node && item.breakpoint.type === data.type)
+ if (item.breakpoint.node === data.node && item.breakpoint.type === data.type) {
element = item.element;
+ }
}
- if (!element)
+ if (!element) {
return;
+ }
UI.viewManager.showView('sources.domBreakpoints');
element.classList.add('breakpoint-hit');
this._highlightedElement = element;
@@ -216,20 +227,23 @@ BrowserDebugger.DOMBreakpointsSidebarPane.ContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, object) {
const node = /** @type {!SDK.DOMNode} */ (object);
- if (node.pseudoType())
+ if (node.pseudoType()) {
return;
+ }
const domDebuggerModel = node.domModel().target().model(SDK.DOMDebuggerModel);
- if (!domDebuggerModel)
+ if (!domDebuggerModel) {
return;
+ }
/**
* @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type
*/
function toggleBreakpoint(type) {
- if (domDebuggerModel.hasDOMBreakpoint(node, type))
+ if (domDebuggerModel.hasDOMBreakpoint(node, type)) {
domDebuggerModel.removeDOMBreakpoint(node, type);
- else
+ } else {
domDebuggerModel.setDOMBreakpoint(node, type);
+ }
}
const breakpointsMenu = contextMenu.debugSection().appendSubMenuItem(Common.UIString('Break on'));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js
index a72ac4ecf68..037bc868a9e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/EventListenerBreakpointsSidebarPane.js
@@ -8,8 +8,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
constructor() {
super(true);
this._categoriesTreeOutline = new UI.TreeOutlineInShadow();
- this._categoriesTreeOutline.element.tabIndex = 0;
this._categoriesTreeOutline.registerRequiredCSS('browser_debugger/eventListenerBreakpoints.css');
+ this._categoriesTreeOutline.setShowSelectionOnKeyboardFocus(/* show */ true);
this.contentElement.appendChild(this._categoriesTreeOutline.element);
/** @type {!Map<string, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */
@@ -17,14 +17,20 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
const categories = SDK.domDebuggerManager.eventListenerBreakpoints().map(breakpoint => breakpoint.category());
categories.sort();
for (const category of categories) {
- if (!this._categories.has(category))
+ if (!this._categories.has(category)) {
this._createCategory(category);
+ }
+ }
+ if (categories.length > 0) {
+ const firstCategory = this._categories.get(categories[0]);
+ firstCategory.element.select();
}
/** @type {!Map<!SDK.DOMDebuggerModel.EventListenerBreakpoint, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */
this._breakpoints = new Map();
- for (const breakpoint of SDK.domDebuggerManager.eventListenerBreakpoints())
+ for (const breakpoint of SDK.domDebuggerManager.eventListenerBreakpoints()) {
this._createBreakpoint(breakpoint);
+ }
SDK.targetManager.addModelListener(SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._update, this);
SDK.targetManager.addModelListener(SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerResumed, this._update, this);
@@ -32,14 +38,28 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
}
/**
+ * @override
+ */
+ focus() {
+ this._categoriesTreeOutline.forceSelect();
+ }
+
+ /**
* @param {string} name
*/
_createCategory(name) {
const labelNode = UI.CheckboxLabel.create(name);
labelNode.checkboxElement.addEventListener('click', this._categoryCheckboxClicked.bind(this, name), true);
+ labelNode.checkboxElement.tabIndex = -1;
const treeElement = new UI.TreeElement(labelNode);
- treeElement.selectable = false;
+ treeElement.listItemElement.addEventListener('keydown', event => {
+ if (event.key === ' ') {
+ this._categories.get(name).checkbox.click();
+ event.consume(true);
+ }
+ });
+ UI.ARIAUtils.setChecked(treeElement.listItemElement, false);
this._categoriesTreeOutline.appendChild(treeElement);
this._categories.set(name, {element: treeElement, checkbox: labelNode.checkboxElement});
@@ -52,10 +72,17 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
const labelNode = UI.CheckboxLabel.create(breakpoint.title());
labelNode.classList.add('source-code');
labelNode.checkboxElement.addEventListener('click', this._breakpointCheckboxClicked.bind(this, breakpoint), true);
+ labelNode.checkboxElement.tabIndex = -1;
const treeElement = new UI.TreeElement(labelNode);
+ treeElement.listItemElement.addEventListener('keydown', event => {
+ if (event.key === ' ') {
+ this._breakpoints.get(breakpoint).checkbox.click();
+ event.consume(true);
+ }
+ });
+ UI.ARIAUtils.setChecked(treeElement.listItemElement, false);
treeElement.listItemElement.createChild('div', 'breakpoint-hit-marker');
- treeElement.selectable = false;
this._categories.get(breakpoint.category()).element.appendChild(treeElement);
this._breakpoints.set(breakpoint, {element: treeElement, checkbox: labelNode.checkboxElement});
@@ -68,6 +95,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
if (!details || details.reason !== SDK.DebuggerModel.BreakReason.EventListener || !details.auxData) {
if (this._highlightedElement) {
+ UI.ARIAUtils.setDescription(this._highlightedElement, '');
this._highlightedElement.classList.remove('breakpoint-hit');
delete this._highlightedElement;
}
@@ -75,12 +103,14 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
}
const breakpoint = SDK.domDebuggerManager.resolveEventListenerBreakpoint(/** @type {!Object} */ (details.auxData));
- if (!breakpoint)
+ if (!breakpoint) {
return;
+ }
UI.viewManager.showView('sources.eventListenerBreakpoints');
this._categories.get(breakpoint.category()).element.expand();
this._highlightedElement = this._breakpoints.get(breakpoint).element.listItemElement;
+ UI.ARIAUtils.setDescription(this._highlightedElement, ls`breakpoint hit`);
this._highlightedElement.classList.add('breakpoint-hit');
}
@@ -90,6 +120,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
_categoryCheckboxClicked(category) {
const item = this._categories.get(category);
const enabled = item.checkbox.checked;
+ UI.ARIAUtils.setChecked(item.element.listItemElement, enabled);
+
for (const breakpoint of this._breakpoints.keys()) {
if (breakpoint.category() === category) {
breakpoint.setEnabled(enabled);
@@ -104,21 +136,28 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
_breakpointCheckboxClicked(breakpoint) {
const item = this._breakpoints.get(breakpoint);
breakpoint.setEnabled(item.checkbox.checked);
+ UI.ARIAUtils.setChecked(item.element.listItemElement, item.checkbox.checked);
let hasEnabled = false;
let hasDisabled = false;
for (const other of this._breakpoints.keys()) {
if (other.category() === breakpoint.category()) {
- if (other.enabled())
+ if (other.enabled()) {
hasEnabled = true;
- else
+ } else {
hasDisabled = true;
+ }
}
}
- const checkbox = this._categories.get(breakpoint.category()).checkbox;
- checkbox.checked = hasEnabled;
- checkbox.indeterminate = hasEnabled && hasDisabled;
+ const category = this._categories.get(breakpoint.category());
+ category.checkbox.checked = hasEnabled;
+ category.checkbox.indeterminate = hasEnabled && hasDisabled;
+ if (category.checkbox.indeterminate) {
+ UI.ARIAUtils.setCheckboxAsIndeterminate(category.element.listItemElement);
+ } else {
+ UI.ARIAUtils.setChecked(category.element.listItemElement, hasEnabled);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/ObjectEventListenersSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/ObjectEventListenersSidebarPane.js
index 37bdd75c24e..be9118ffb4f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/ObjectEventListenersSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/ObjectEventListenersSidebarPane.js
@@ -8,12 +8,13 @@
BrowserDebugger.ObjectEventListenersSidebarPane = class extends UI.VBox {
constructor() {
super();
- this._refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
+ this._refreshButton = new UI.ToolbarButton(ls`Refresh global listeners`, 'largeicon-refresh');
this._refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshClick, this);
this._refreshButton.setEnabled(false);
this._eventListenersView = new EventListeners.EventListenersView(this.update.bind(this));
this._eventListenersView.show(this.element);
+ this.setDefaultFocusedChild(this._eventListenersView);
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/XHRBreakpointsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/XHRBreakpointsSidebarPane.js
index 2fd60a923f2..dd542164984 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/XHRBreakpointsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/XHRBreakpointsSidebarPane.js
@@ -92,8 +92,9 @@ BrowserDebugger.XHRBreakpointsSidebarPane = class extends UI.VBox {
let currentElement = /** @type {?Element} */ (this._listElement.firstChild);
while (currentElement) {
- if (currentElement._url && currentElement._url < element._url)
+ if (currentElement._url && currentElement._url < element._url) {
break;
+ }
currentElement = /** @type {?Element} */ (currentElement.nextSibling);
}
this._addListElement(element, currentElement);
@@ -105,8 +106,9 @@ BrowserDebugger.XHRBreakpointsSidebarPane = class extends UI.VBox {
*/
_removeBreakpoint(url) {
const element = this._breakpointElements.get(url);
- if (!element)
+ if (!element) {
return;
+ }
this._removeListElement(element);
this._breakpointElements.delete(url);
@@ -214,8 +216,9 @@ BrowserDebugger.XHRBreakpointsSidebarPane = class extends UI.VBox {
}
const url = details.auxData['breakpointURL'];
const element = this._breakpointElements.get(url);
- if (!element)
+ if (!element) {
return;
+ }
UI.viewManager.showView('sources.xhrBreakpoints');
element.classList.add('breakpoint-hit');
this._highlightedElement = element;
@@ -223,7 +226,8 @@ BrowserDebugger.XHRBreakpointsSidebarPane = class extends UI.VBox {
_restoreBreakpoints() {
const breakpoints = SDK.domDebuggerManager.xhrBreakpoints();
- for (const url of breakpoints.keys())
+ for (const url of breakpoints.keys()) {
this._setBreakpoint(url, breakpoints.get(url));
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
index 5fa06107079..7cd1d3edd82 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_debugger/browser_debugger_strings.grdp
@@ -1,28 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_0ca08f8f4a8a19f7f1ae87c119494327" desc="Title of the 'Overrides' tool in the Overrides Navigator View, which is part of the Sources tool">
- Overrides
- </message>
<message name="IDS_DEVTOOLS_1106d01848580ffc52dd36e2d60316d9" desc="Title of the 'XHR/fetch Breakpoints' tool in the bottom sidebar of the Sources tool">
XHR/fetch Breakpoints
</message>
- <message name="IDS_DEVTOOLS_193cfc9be3b995831c6af2fea6650e60" desc="Title of the 'Page' tool in the Network Navigator View, which is part of the Sources tool">
- Page
- </message>
<message name="IDS_DEVTOOLS_2daf59f0ff992924e42c14c1e674bd6a" desc="Text in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Attribute modified
</message>
<message name="IDS_DEVTOOLS_30d67fd6c32c9a9ff5ecb4472b44ed54" desc="Input element container text content in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Break when URL contains:
</message>
- <message name="IDS_DEVTOOLS_340641a167ad6da1bcb4016357f4695d" desc="Title of the 'Content scripts' tool in the Content Scripts Navigator View, which is part of the Sources tool">
- Content scripts
- </message>
<message name="IDS_DEVTOOLS_39c145d69ad05e44e74017346c116251" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Remove all DOM breakpoints
</message>
- <message name="IDS_DEVTOOLS_47bda3033cb8fe0e76c45c293db011b5" desc="Empty element text content in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
- No breakpoints
+ <message name="IDS_DEVTOOLS_3ea566249a507705d9a7ff4d3bd31440" desc="Screen reader description of a hit breakpoint in the Sources panel">
+ breakpoint hit
</message>
<message name="IDS_DEVTOOLS_59eaf6955f44a94237b6d26911c1d983" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Break on
@@ -30,17 +21,11 @@
<message name="IDS_DEVTOOLS_626585724f35f9d9fce0bd36525cb7de" desc="Title of the Marker Decorator of Elements">
DOM Breakpoint
</message>
- <message name="IDS_DEVTOOLS_63a6a88c066880c5ac42394a22803ca6" desc="Tooltip text that appears when hovering over the largeicon refresh button in the Object Event Listeners Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
- Refresh
- </message>
<message name="IDS_DEVTOOLS_66b74432bdc2797086f419010cc5ff86" desc="Title of the 'DOM Breakpoints' tool in the bottom sidebar of the Sources tool">
DOM Breakpoints
</message>
- <message name="IDS_DEVTOOLS_6ba3a9ac3e0d57683c56299484b7ee3b" desc="Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
- Remove all breakpoints
- </message>
- <message name="IDS_DEVTOOLS_b4e79b551a1ceae24b7de243ab1fd27c" desc="Tooltip text that appears when hovering over the largeicon add button in the XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
- Add breakpoint
+ <message name="IDS_DEVTOOLS_9f76c421048cb58ab03988d2ce1c813e" desc="Label for a button in the sources panel that refreshes the list of global event listeners.">
+ Refresh global listeners
</message>
<message name="IDS_DEVTOOLS_b839f802a330e4d4145cb182e6767f45" desc="Text in XHRBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Any XHR or fetch
@@ -51,9 +36,6 @@
<message name="IDS_DEVTOOLS_c4bd9c57c6b315e3f7374cf77143ca58" desc="Text in DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Subtree modified
</message>
- <message name="IDS_DEVTOOLS_d5bfaaca8e28f8b9b9211038f86a4494" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
- Remove breakpoint
- </message>
<message name="IDS_DEVTOOLS_e30c4292775f68b2bc9eb3957a69f899" desc="Title of the 'Global Listeners' tool in the bottom sidebar of the Sources tool">
Global Listeners
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js
index faf4032e660..4c996614560 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js
@@ -5,7 +5,7 @@
/**
* @implements {SDK.SDKModelObserver<!SDK.LogModel>}
*/
-BrowserSDK.LogManager = class {
+export default class LogManager {
constructor() {
SDK.targetManager.observeModels(SDK.LogModel, this);
}
@@ -17,7 +17,7 @@ BrowserSDK.LogManager = class {
modelAdded(logModel) {
const eventListeners = [];
eventListeners.push(logModel.addEventListener(SDK.LogModel.Events.EntryAdded, this._logEntryAdded, this));
- logModel[BrowserSDK.LogManager._eventSymbol] = eventListeners;
+ logModel[_eventSymbol] = eventListeners;
}
/**
@@ -25,7 +25,7 @@ BrowserSDK.LogManager = class {
* @param {!SDK.LogModel} logModel
*/
modelRemoved(logModel) {
- Common.EventTarget.removeEventListeners(logModel[BrowserSDK.LogManager._eventSymbol]);
+ Common.EventTarget.removeEventListeners(logModel[_eventSymbol]);
}
/**
@@ -40,8 +40,9 @@ BrowserSDK.LogManager = class {
data.entry.lineNumber, undefined, [data.entry.text, ...(data.entry.args || [])], data.entry.stackTrace,
data.entry.timestamp, undefined, undefined, data.entry.workerId);
- if (data.entry.networkRequestId)
+ if (data.entry.networkRequestId) {
SDK.networkLog.associateConsoleMessageWithRequest(consoleMessage, data.entry.networkRequestId);
+ }
if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Worker) {
const workerId = consoleMessage.workerId || '';
@@ -49,18 +50,32 @@ BrowserSDK.LogManager = class {
// user can see messages from the worker which has been already destroyed.
// When opening DevTools, give us some time to connect to the worker and
// not report the message twice if the worker is still alive.
- if (SDK.targetManager.targetById(workerId))
+ if (SDK.targetManager.targetById(workerId)) {
return;
+ }
setTimeout(() => {
- if (!SDK.targetManager.targetById(workerId))
+ if (!SDK.targetManager.targetById(workerId)) {
SDK.consoleModel.addMessage(consoleMessage);
+ }
}, 1000);
} else {
SDK.consoleModel.addMessage(consoleMessage);
}
}
-};
+}
+
+export const _eventSymbol = Symbol('_events');
+
+/* Legacy exported object */
+self.BrowserSDK = self.BrowserSDK || {};
+
+/* Legacy exported object */
+BrowserSDK = BrowserSDK || {};
+
+/** @constructor */
+BrowserSDK.LogManager = LogManager;
-BrowserSDK.LogManager._eventSymbol = Symbol('_events');
+BrowserSDK.LogManager._eventSymbol = _eventSymbol;
-new BrowserSDK.LogManager();
+// TODO(crbug.com/1006759): Move out of this module
+new LogManager(); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk.js
new file mode 100644
index 00000000000..9d9f5835eea
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk.js
@@ -0,0 +1,9 @@
+// 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 * as LogManager from './LogManager.js';
+
+export {
+ LogManager,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
index 09b8959bdad..cc3665ab2e2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/browser_sdk_strings.grdp
@@ -6,10 +6,13 @@
<message name="IDS_DEVTOOLS_6aed54027cf3a260de904a43cf439cc9" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Preserve log on page reload / navigation
</message>
- <message name="IDS_DEVTOOLS_edd24cce7afedea5a1b2f90675880687" desc="Title of a setting under the Network category in Settings">
- Preserve log
+ <message name="IDS_DEVTOOLS_01bc6f8efa4202821e95f4fdf6298b30" desc="A tag of Network preserve log settings that can be searched in the command menu">
+ clear
</message>
- <message name="IDS_DEVTOOLS_eec89088ee408b80387155272b113256" desc="A title of the 'Network' setting category">
- Network
+ <message name="IDS_DEVTOOLS_86266ee937d97f812a8e57d22b62ee29" desc="A tag of Network preserve log settings that can be searched in the command menu">
+ reset
+ </message>
+ <message name="IDS_DEVTOOLS_ec4875cf2d241556a0965f7237864693" desc="A tag of Network preserve log settings that can be searched in the command menu">
+ preserve
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json
index 7cca023c87a..6a4b3ab5376 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_sdk/module.json
@@ -20,7 +20,9 @@
]
}
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "browser_sdk.js",
"LogManager.js"
],
"dependencies": [
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesHighlighter.js b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesHighlighter.js
index 01f9c245a3e..ff0530881b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesHighlighter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesHighlighter.js
@@ -44,8 +44,9 @@ Changes.ChangesHighlighter = function(config, parserConfig) {
let lineNumber = from;
while (lineNumber < to && lineNumber < lines.length) {
const stream = new CodeMirror.StringStream(lines[lineNumber]);
- if (stream.eol() && syntaxHighlightMode.blankLine)
+ if (stream.eol() && syntaxHighlightMode.blankLine) {
syntaxHighlightMode.blankLine(syntaxState);
+ }
while (!stream.eol()) {
syntaxHighlightMode.token(stream, syntaxState);
stream.start = stream.pos;
@@ -86,8 +87,9 @@ Changes.ChangesHighlighter = function(config, parserConfig) {
}
fastForward(state, diffRow.baselineLineNumber - 1, diffRow.currentLineNumber - 1);
let classes = '';
- if (stream.pos === 0)
+ if (stream.pos === 0) {
classes += ' line-background-' + diffRow.type + ' line-' + diffRow.type;
+ }
const syntaxHighlighterNeedsRefresh = state.diffPosition >= state.syntaxPosition;
if (state.diffPosition <= state.syntaxPosition) {
@@ -114,10 +116,11 @@ Changes.ChangesHighlighter = function(config, parserConfig) {
if (stream.eol()) {
state.rowNumber++;
- if (diffRow.type === Changes.ChangesView.RowType.Deletion)
+ if (diffRow.type === Changes.ChangesView.RowType.Deletion) {
state.baselineLineNumber++;
- else
+ } else {
state.currentLineNumber++;
+ }
state.diffPosition = 0;
state.syntaxPosition = 0;
state.diffTokenIndex = 0;
@@ -135,8 +138,9 @@ Changes.ChangesHighlighter = function(config, parserConfig) {
state.syntaxPosition = 0;
state.diffPosition = 0;
state.diffTokenIndex = 0;
- if (!diffRow)
+ if (!diffRow) {
return '';
+ }
let style = '';
if (syntaxHighlightMode.blankLine) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js
index e1788dfd0ac..20c1423a5fa 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesSidebar.js
@@ -29,8 +29,9 @@ Changes.ChangesSidebar = class extends UI.Widget {
*/
selectUISourceCode(uiSourceCode, omitFocus) {
const treeElement = this._treeElements.get(uiSourceCode);
- if (!treeElement)
+ if (!treeElement) {
return;
+ }
treeElement.select(omitFocus);
}
@@ -49,10 +50,11 @@ Changes.ChangesSidebar = class extends UI.Widget {
* @param {!Common.Event} event
*/
_uiSourceCodeMofiedStatusChanged(event) {
- if (event.data.isModified)
+ if (event.data.isModified) {
this._addUISourceCode(event.data.uiSourceCode);
- else
+ } else {
this._removeUISourceCode(event.data.uiSourceCode);
+ }
}
/**
@@ -81,8 +83,9 @@ Changes.ChangesSidebar = class extends UI.Widget {
const treeElement = new Changes.ChangesSidebar.UISourceCodeTreeElement(uiSourceCode);
this._treeElements.set(uiSourceCode, treeElement);
this._treeoutline.appendChild(treeElement);
- if (!this._treeoutline.selectedTreeElement)
+ if (!this._treeoutline.selectedTreeElement) {
treeElement.select(true);
+ }
}
};
@@ -103,8 +106,9 @@ Changes.ChangesSidebar.UISourceCodeTreeElement = class extends UI.TreeElement {
this.listItemElement.classList.add('navigator-' + uiSourceCode.contentType().name() + '-tree-item');
let iconType = 'largeicon-navigator-file';
- if (Snippets.isSnippetsUISourceCode(this.uiSourceCode))
+ if (Snippets.isSnippetsUISourceCode(this.uiSourceCode)) {
iconType = 'largeicon-navigator-snippet';
+ }
const defaultIcon = UI.Icon.create(iconType, 'icon');
this.setLeadingIcons([defaultIcon]);
@@ -119,13 +123,15 @@ Changes.ChangesSidebar.UISourceCodeTreeElement = class extends UI.TreeElement {
_updateTitle() {
let titleText = this.uiSourceCode.displayName();
- if (this.uiSourceCode.isDirty())
+ if (this.uiSourceCode.isDirty()) {
titleText = '*' + titleText;
+ }
this.title = titleText;
let tooltip = this.uiSourceCode.url();
- if (this.uiSourceCode.contentType().isFromSourceMap())
+ if (this.uiSourceCode.contentType().isFromSourceMap()) {
tooltip = Common.UIString('%s (from source map)', this.uiSourceCode.displayName());
+ }
this.tooltip = tooltip;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js
index ddddec1fd33..aa48a2d5db5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/changes/ChangesView.js
@@ -57,8 +57,9 @@ Changes.ChangesView = class extends UI.VBox {
_revert() {
const uiSourceCode = this._selectedUISourceCode;
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
this._workspaceDiff.revertToOriginal(uiSourceCode);
}
@@ -67,8 +68,9 @@ Changes.ChangesView = class extends UI.VBox {
*/
_click(event) {
const selection = this._editor.selection();
- if (!selection.isEmpty())
+ if (!selection.isEmpty()) {
return;
+ }
const row = this._diffRows[selection.startLine];
Common.Revealer.reveal(
this._selectedUISourceCode.uiLocation(row.currentLineNumber - 1, selection.startColumn), false);
@@ -79,13 +81,16 @@ Changes.ChangesView = class extends UI.VBox {
* @param {?Workspace.UISourceCode} uiSourceCode
*/
_revealUISourceCode(uiSourceCode) {
- if (this._selectedUISourceCode === uiSourceCode)
+ if (this._selectedUISourceCode === uiSourceCode) {
return;
+ }
- if (this._selectedUISourceCode)
+ if (this._selectedUISourceCode) {
this._workspaceDiff.unsubscribeFromDiffChange(this._selectedUISourceCode, this._refreshDiff, this);
- if (uiSourceCode && this.isShowing())
+ }
+ if (uiSourceCode && this.isShowing()) {
this._workspaceDiff.subscribeToDiffChange(uiSourceCode, this._refreshDiff, this);
+ }
this._selectedUISourceCode = uiSourceCode;
this._refreshDiff();
@@ -99,8 +104,9 @@ Changes.ChangesView = class extends UI.VBox {
}
_refreshDiff() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
if (!this._selectedUISourceCode) {
this._renderDiffRows(null);
@@ -112,8 +118,9 @@ Changes.ChangesView = class extends UI.VBox {
return;
}
this._workspaceDiff.requestDiff(uiSourceCode).then(diff => {
- if (this._selectedUISourceCode !== uiSourceCode)
+ if (this._selectedUISourceCode !== uiSourceCode) {
return;
+ }
this._renderDiffRows(diff);
});
}
@@ -157,8 +164,9 @@ Changes.ChangesView = class extends UI.VBox {
currentLines.pushAll(token[1]);
break;
case Diff.Diff.Operation.Insert:
- for (const line of token[1])
+ for (const line of token[1]) {
this._diffRows.push(createRow(line, Changes.ChangesView.RowType.Addition));
+ }
insertions += token[1].length;
currentLines.pushAll(token[1]);
break;
@@ -171,8 +179,9 @@ Changes.ChangesView = class extends UI.VBox {
insertions += diff[i][1].length;
currentLines.pushAll(diff[i][1]);
} else {
- for (const line of token[1])
+ for (const line of token[1]) {
this._diffRows.push(createRow(line, Changes.ChangesView.RowType.Deletion));
+ }
}
break;
}
@@ -181,16 +190,18 @@ Changes.ChangesView = class extends UI.VBox {
this._maxLineDigits = Math.ceil(Math.log10(Math.max(currentLineNumber, baselineLineNumber)));
let insertionText = '';
- if (insertions === 1)
+ if (insertions === 1) {
insertionText = ls`${insertions} insertion (+),`;
- else
+ } else {
insertionText = ls`${insertions} insertions (+),`;
+ }
let deletionText = '';
- if (deletions === 1)
+ if (deletions === 1) {
deletionText = ls`${deletions} deletion (-)`;
- else
+ } else {
deletionText = ls`${deletions} deletions (-)`;
+ }
this._diffStats.setText(`${insertionText} ${deletionText}`);
this._toolbar.setEnabled(true);
@@ -218,8 +229,9 @@ Changes.ChangesView = class extends UI.VBox {
function createEqualRows(lines, atStart, atEnd) {
const equalRows = [];
if (!atStart) {
- for (let i = 0; i < paddingLines && i < lines.length; i++)
+ for (let i = 0; i < paddingLines && i < lines.length; i++) {
equalRows.push(createRow(lines[i], Changes.ChangesView.RowType.Equal));
+ }
if (lines.length > paddingLines * 2 + 1 && !atEnd) {
equalRows.push(createRow(
Common.UIString('( \u2026 Skipping %d matching lines \u2026 )', lines.length - paddingLines * 2),
@@ -229,15 +241,17 @@ Changes.ChangesView = class extends UI.VBox {
if (!atEnd) {
const start = Math.max(lines.length - paddingLines - 1, atStart ? 0 : paddingLines);
let skip = lines.length - paddingLines - 1;
- if (!atStart)
+ if (!atStart) {
skip -= paddingLines;
+ }
if (skip > 0) {
baselineLineNumber += skip;
currentLineNumber += skip;
}
- for (let i = start; i < lines.length; i++)
+ for (let i = start; i < lines.length; i++) {
equalRows.push(createRow(lines[i], Changes.ChangesView.RowType.Equal));
+ }
}
return equalRows;
}
@@ -258,16 +272,21 @@ Changes.ChangesView = class extends UI.VBox {
const className = type === Diff.Diff.Operation.Equal ? '' : 'inner-diff';
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
- if (i > 0 && type !== Diff.Diff.Operation.Insert)
+ if (i > 0 && type !== Diff.Diff.Operation.Insert) {
deletionRows.push(createRow('', Changes.ChangesView.RowType.Deletion));
- if (i > 0 && type !== Diff.Diff.Operation.Delete)
+ }
+ if (i > 0 && type !== Diff.Diff.Operation.Delete) {
insertionRows.push(createRow('', Changes.ChangesView.RowType.Addition));
- if (!lines[i])
+ }
+ if (!lines[i]) {
continue;
- if (type !== Diff.Diff.Operation.Insert)
+ }
+ if (type !== Diff.Diff.Operation.Insert) {
deletionRows[deletionRows.length - 1].tokens.push({text: lines[i], className});
- if (type !== Diff.Diff.Operation.Delete)
+ }
+ if (type !== Diff.Diff.Operation.Delete) {
insertionRows[insertionRows.length - 1].tokens.push({text: lines[i], className});
+ }
}
}
return deletionRows.concat(insertionRows);
@@ -279,10 +298,12 @@ Changes.ChangesView = class extends UI.VBox {
* @return {!Changes.ChangesView.Row}
*/
function createRow(text, type) {
- if (type === Changes.ChangesView.RowType.Addition)
+ if (type === Changes.ChangesView.RowType.Addition) {
currentLineNumber++;
- if (type === Changes.ChangesView.RowType.Deletion)
+ }
+ if (type === Changes.ChangesView.RowType.Deletion) {
baselineLineNumber++;
+ }
if (type === Changes.ChangesView.RowType.Equal) {
baselineLineNumber++;
currentLineNumber++;
@@ -341,8 +362,9 @@ Changes.ChangesView.DiffUILocationRevealer = class {
* @return {!Promise}
*/
async reveal(diffUILocation, omitFocus) {
- if (!(diffUILocation instanceof WorkspaceDiff.DiffUILocation))
+ if (!(diffUILocation instanceof WorkspaceDiff.DiffUILocation)) {
throw new Error('Internal error: not a diff ui location');
+ }
/** @type {!Changes.ChangesView} */
const changesView = self.runtime.sharedInstance(Changes.ChangesView);
await UI.viewManager.showView('changes.changes');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
index 8bba0fe8cbf..de23afbedb2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/changes/changes_strings.grdp
@@ -30,7 +30,4 @@
<message name="IDS_DEVTOOLS_f550ec70278cc72604795d91ff8dcd30" desc="Text in Changes View of the Changes tab">
Binary data
</message>
- <message name="IDS_DEVTOOLS_fa6711f918fe2018131a4ad0380b9e56" desc="Tooltip in Changes Sidebar of the Changes tab">
- <ph name="THIS_UISOURCECODE_DISPLAYNAME__">$1s<ex>compile.html</ex></ph> (from source map)
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/cm_modes/DefaultCodeMirrorMimeMode.js b/chromium/third_party/blink/renderer/devtools/front_end/cm_modes/DefaultCodeMirrorMimeMode.js
index 31497d4a638..c76bf67ee8a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/cm_modes/DefaultCodeMirrorMimeMode.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/cm_modes/DefaultCodeMirrorMimeMode.js
@@ -6,19 +6,16 @@
* @constructor
* @implements {TextEditor.CodeMirrorMimeMode}
*/
-CmModes.DefaultCodeMirrorMimeMode = function()
-{
-}
+CmModes.DefaultCodeMirrorMimeMode = function() {};
CmModes.DefaultCodeMirrorMimeMode.prototype = {
- /**
- * @param {!Runtime.Extension} extension
+ /**
+ * @param {!Root.Runtime.Extension} extension
* @override
*/
- install: function(extension)
- {
- var modeFileName = extension.descriptor()["fileName"];
- var modeContent = extension.module().resource(modeFileName);
- self.eval(modeContent + "\n//# sourceURL=" + modeFileName);
- }
+ install: function(extension) {
+ var modeFileName = extension.descriptor()['fileName'];
+ var modeContent = extension.module().resource(modeFileName);
+ self.eval(modeContent + '\n//# sourceURL=' + modeFileName);
+ }
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js
index ff20719b98d..261bc0da232 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-ColorPicker.ContrastDetails = class {
+ColorPicker.ContrastDetails = class extends Common.Object {
/**
* @param {!ColorPicker.ContrastInfo} contrastInfo
* @param {!Element} contentElement
@@ -10,6 +10,7 @@ ColorPicker.ContrastDetails = class {
* @param {function()} expandedChangedCallback
*/
constructor(contrastInfo, contentElement, toggleMainColorPickerCallback, expandedChangedCallback) {
+ super();
/** @type {!ColorPicker.ContrastInfo} */
this._contrastInfo = contrastInfo;
@@ -80,7 +81,7 @@ ColorPicker.ContrastDetails = class {
this._bgColorPickerButton =
new UI.ToolbarToggle(Common.UIString('Toggle background color picker'), 'largeicon-eyedropper');
this._bgColorPickerButton.addEventListener(
- UI.ToolbarButton.Events.Click, this._toggleBackgroundColorPicker.bind(this, undefined));
+ UI.ToolbarButton.Events.Click, this._toggleBackgroundColorPicker.bind(this, undefined, true));
pickerToolbar.appendToolbarItem(this._bgColorPickerButton);
this._bgColorPickedBound = this._bgColorPicked.bind(this);
@@ -123,10 +124,11 @@ ColorPicker.ContrastDetails = class {
const labelAA = this._contrastPassFailAA.createChild('span', 'contrast-link-label');
labelAA.textContent = Common.UIString('AA');
this._contrastPassFailAA.createChild('span').textContent = Common.UIString(': %s', aa.toFixed(1));
- if (this._passesAA)
+ if (this._passesAA) {
this._contrastPassFailAA.appendChild(UI.Icon.create('smallicon-checkmark-square'));
- else
+ } else {
this._contrastPassFailAA.appendChild(UI.Icon.create('smallicon-no'));
+ }
const aaa = this._contrastInfo.contrastRatioThreshold('aaa');
const passesAAA = this._contrastInfo.contrastRatio() >= aaa;
@@ -134,10 +136,11 @@ ColorPicker.ContrastDetails = class {
const labelAAA = this._contrastPassFailAAA.createChild('span', 'contrast-link-label');
labelAAA.textContent = Common.UIString('AAA');
this._contrastPassFailAAA.createChild('span').textContent = Common.UIString(': %s', aaa.toFixed(1));
- if (passesAAA)
+ if (passesAAA) {
this._contrastPassFailAAA.appendChild(UI.Icon.create('smallicon-checkmark-square'));
- else
+ } else {
this._contrastPassFailAAA.appendChild(UI.Icon.create('smallicon-no'));
+ }
[labelAA, labelAAA].forEach(e => e.addEventListener('click', event => ColorPicker.ContrastDetails._showHelp()));
@@ -147,7 +150,7 @@ ColorPicker.ContrastDetails = class {
}
static _showHelp() {
- InspectorFrontendHost.openInNewTab(
+ Host.InspectorFrontendHost.openInNewTab(
'https://developers.google.com/web/fundamentals/accessibility/accessible-styles#color_and_contrast');
}
@@ -198,8 +201,9 @@ ColorPicker.ContrastDetails = class {
this._toggleMainColorPicker(false);
this._expandButton.setGlyph('smallicon-expand-less');
this._expandButton.setTitle(Common.UIString('Show less'));
- if (this._contrastUnknown)
+ if (this._contrastUnknown) {
this._toggleBackgroundColorPicker(true);
+ }
} else {
this._toggleBackgroundColorPicker(false);
this._expandButton.setGlyph('smallicon-expand-more');
@@ -222,19 +226,41 @@ ColorPicker.ContrastDetails = class {
}
/**
+ * @returns {boolean}
+ */
+ backgroundColorPickerEnabled() {
+ return this._bgColorPickerButton.toggled();
+ }
+
+ /**
+ * @param {boolean} enabled
+ */
+
+ toggleBackgroundColorPicker(enabled) {
+ this._toggleBackgroundColorPicker(enabled, false);
+ }
+
+ /**
* @param {boolean=} enabled
+ * @param {boolean=} shouldTriggerEvent
*/
- _toggleBackgroundColorPicker(enabled) {
- if (enabled === undefined)
+ _toggleBackgroundColorPicker(enabled, shouldTriggerEvent = true) {
+ if (enabled === undefined) {
enabled = !this._bgColorPickerButton.toggled();
+ }
this._bgColorPickerButton.setToggled(enabled);
- InspectorFrontendHost.setEyeDropperActive(enabled);
+
+ if (shouldTriggerEvent) {
+ this.dispatchEventToListeners(ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled, enabled);
+ }
+
+ Host.InspectorFrontendHost.setEyeDropperActive(enabled);
if (enabled) {
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound);
} else {
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound);
}
}
@@ -247,10 +273,14 @@ ColorPicker.ContrastDetails = class {
const color = Common.Color.fromRGBA(rgba);
this._contrastInfo.setBgColor(color);
this._toggleBackgroundColorPicker(false);
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
}
};
+ColorPicker.ContrastDetails.Events = {
+ BackgroundColorPickerWillBeToggled: Symbol('BackgroundColorPickerWillBeToggled')
+};
+
ColorPicker.ContrastDetails.Swatch = class {
/**
* @param {!Element} parentElement
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastInfo.js b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastInfo.js
index 245576841a3..864766d541f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastInfo.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastInfo.js
@@ -18,12 +18,14 @@ ColorPicker.ContrastInfo = class extends Common.Object {
/** @type {?Common.Color} */
this._bgColor = null;
- if (!contrastInfo)
+ if (!contrastInfo) {
return;
+ }
if (!contrastInfo.computedFontSize || !contrastInfo.computedFontWeight || !contrastInfo.backgroundColors ||
- contrastInfo.backgroundColors.length !== 1)
+ contrastInfo.backgroundColors.length !== 1) {
return;
+ }
this._isNull = false;
const isLargeFont =
@@ -33,8 +35,9 @@ ColorPicker.ContrastInfo = class extends Common.Object {
ColorPicker.ContrastInfo._ContrastThresholds[(isLargeFont ? 'largeFont' : 'normalFont')];
const bgColorText = contrastInfo.backgroundColors[0];
const bgColor = Common.Color.parse(bgColorText);
- if (bgColor)
+ if (bgColor) {
this._setBgColorInternal(bgColor);
+ }
}
/**
@@ -81,8 +84,9 @@ ColorPicker.ContrastInfo = class extends Common.Object {
_setBgColorInternal(bgColor) {
this._bgColor = bgColor;
- if (!this._fgColor)
+ if (!this._fgColor) {
return;
+ }
const fgRGBA = this._fgColor.rgba();
@@ -106,8 +110,9 @@ ColorPicker.ContrastInfo = class extends Common.Object {
}
_updateContrastRatio() {
- if (!this._bgColor || !this._fgColor)
+ if (!this._bgColor || !this._fgColor) {
return;
+ }
this._contrastRatio = Common.Color.calculateContrastRatio(this._fgColor.rgba(), this._bgColor.rgba());
}
@@ -116,8 +121,9 @@ ColorPicker.ContrastInfo = class extends Common.Object {
* @return {?number}
*/
contrastRatioThreshold(level) {
- if (!this._contrastRatioThresholds)
+ if (!this._contrastRatioThresholds) {
return null;
+ }
return this._contrastRatioThresholds[level];
}
@@ -133,10 +139,11 @@ ColorPicker.ContrastInfo = class extends Common.Object {
const isBold = (boldWeights.indexOf(fontWeight) !== -1);
const fontSizePt = fontSizePx * 72 / 96;
- if (isBold)
+ if (isBold) {
return fontSizePt >= 14;
- else
+ } else {
return fontSizePt >= 18;
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastOverlay.js b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastOverlay.js
index 2ea28636dc5..fe70cf78887 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastOverlay.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/ContrastOverlay.js
@@ -31,8 +31,9 @@ ColorPicker.ContrastOverlay = class {
}
_update() {
- if (!this._visible || this._contrastInfo.isNull() || !this._contrastInfo.contrastRatio())
+ if (!this._visible || this._contrastInfo.isNull() || !this._contrastInfo.contrastRatio()) {
return;
+ }
this._contrastRatioLinesThrottler.schedule(this._drawContrastRatioLinesBound);
}
@@ -59,10 +60,11 @@ ColorPicker.ContrastOverlay = class {
async _drawContrastRatioLines() {
for (const level in this._contrastRatioLines) {
const path = this._contrastRatioLineBuilder.drawContrastRatioLine(this._width, this._height, level);
- if (path)
+ if (path) {
this._contrastRatioLines[level].setAttribute('d', path);
- else
+ } else {
this._contrastRatioLines[level].removeAttribute('d');
+ }
}
}
};
@@ -84,8 +86,9 @@ ColorPicker.ContrastRatioLineBuilder = class {
*/
drawContrastRatioLine(width, height, level) {
const requiredContrast = this._contrastInfo.contrastRatioThreshold(level);
- if (!width || !height || !requiredContrast)
+ if (!width || !height || !requiredContrast) {
return null;
+ }
const dS = 0.02;
const epsilon = 0.0002;
@@ -96,8 +99,9 @@ ColorPicker.ContrastRatioLineBuilder = class {
const color = this._contrastInfo.color();
const bgColor = this._contrastInfo.bgColor();
- if (!color || !bgColor)
+ if (!color || !bgColor) {
return null;
+ }
const fgRGBA = color.rgba();
const fgHSVA = color.hsva();
@@ -142,8 +146,9 @@ ColorPicker.ContrastRatioLineBuilder = class {
let previousSign = Math.sign(dLuminance);
for (let guard = 100; guard; guard--) {
- if (Math.abs(dLuminance) < epsilon)
+ if (Math.abs(dLuminance) < epsilon) {
return x;
+ }
const sign = Math.sign(dLuminance);
if (sign !== previousSign) {
@@ -180,8 +185,9 @@ ColorPicker.ContrastRatioLineBuilder = class {
candidateHSVA[V] = lastV + currentSlope * dS;
const v = approach(V);
- if (v === null)
+ if (v === null) {
break;
+ }
// Approximate the current gradient of the curve.
currentSlope = s === 0 ? 0 : (v - lastV) / dS;
@@ -198,11 +204,13 @@ ColorPicker.ContrastRatioLineBuilder = class {
s -= dS;
candidateHSVA[V] = 1;
s = approach(S);
- if (s !== null)
+ if (s !== null) {
pathBuilder = pathBuilder.concat(['L', (s * width).toFixed(2), '-0.1']);
+ }
}
- if (pathBuilder.length === 0)
+ if (pathBuilder.length === 0) {
return null;
+ }
return pathBuilder.join(' ');
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
index ba1c124481f..0f260e867eb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
@@ -76,7 +76,11 @@ ColorPicker.Spectrum = class extends UI.VBox {
const displaySwitcher = toolsContainer.createChild('div', 'spectrum-display-switcher spectrum-switcher');
appendSwitcherIcon(displaySwitcher);
- displaySwitcher.addEventListener('click', this._formatViewSwitch.bind(this));
+ displaySwitcher.tabIndex = 0;
+ self.onInvokeElement(displaySwitcher, event => {
+ this._formatViewSwitch();
+ event.consume(true);
+ });
// RGBA/HSLA display.
this._displayContainer = toolsContainer.createChild('div', 'spectrum-text source-code');
@@ -122,13 +126,15 @@ ColorPicker.Spectrum = class extends UI.VBox {
this._contrastDetails = new ColorPicker.ContrastDetails(
this._contrastInfo, this.contentElement, this._toggleColorPicker.bind(this),
this._contrastPanelExpanded.bind(this));
+
+ this._contrastDetailsBackgroundColorPickedToggledBound =
+ this._contrastDetailsBackgroundColorPickedToggled.bind(this);
}
this.element.classList.add('flex-none');
/** @type {!Map.<string, !ColorPicker.Spectrum.Palette>} */
this._palettes = new Map();
this._palettePanel = this.contentElement.createChild('div', 'palette-panel');
- this._palettePanel.tabIndex = -1;
this._palettePanel.addEventListener('keydown', this._onPalettePanelKeydown.bind(this));
this._palettePanelShowing = false;
this._paletteSectionContainer = this.contentElement.createChild('div', 'spectrum-palette-container');
@@ -144,7 +150,7 @@ ColorPicker.Spectrum = class extends UI.VBox {
UI.ARIAUtils.markAsButton(paletteSwitcher);
UI.ARIAUtils.setAccessibleName(paletteSwitcher, ls`Preview palettes`);
paletteSwitcher.tabIndex = 0;
- onInvokeElement(paletteSwitcher, event => {
+ self.onInvokeElement(paletteSwitcher, event => {
this._togglePalettePanel(true);
event.consume(true);
});
@@ -165,10 +171,11 @@ ColorPicker.Spectrum = class extends UI.VBox {
this._loadPalettes();
new ColorPicker.Spectrum.PaletteGenerator(palette => {
- if (palette.colors.length)
+ if (palette.colors.length) {
this.addPalette(palette);
- else if (this._selectedColorPalette.get() === palette.title)
+ } else if (this._selectedColorPalette.get() === palette.title) {
this._paletteSelected(ColorPicker.Spectrum.MaterialPalette);
+ }
});
/**
@@ -218,6 +225,12 @@ ColorPicker.Spectrum = class extends UI.VBox {
}
}
+ _contrastDetailsBackgroundColorPickedToggled({data: enabled}) {
+ if (enabled) {
+ this._toggleColorPicker(false);
+ }
+ }
+
_contrastPanelExpanded() {
this._contrastOverlay.setVisible(this._contrastDetails.expanded());
this._resizeForSelectedPalette(true);
@@ -231,18 +244,21 @@ ColorPicker.Spectrum = class extends UI.VBox {
const closeButton = new UI.ToolbarButton('Return to color picker', 'largeicon-delete');
closeButton.addEventListener(UI.ToolbarButton.Events.Click, this._togglePalettePanel.bind(this, false));
toolbar.appendToolbarItem(closeButton);
- for (const palette of this._palettes.values())
+ for (const palette of this._palettes.values()) {
this._palettePanel.appendChild(this._createPreviewPaletteElement(palette));
+ }
}
/**
* @param {boolean} show
*/
_togglePalettePanel(show) {
- if (this._palettePanelShowing === show)
+ if (this._palettePanelShowing === show) {
return;
- if (show)
+ }
+ if (show) {
this._updatePalettePanel();
+ }
this._palettePanelShowing = show;
this.contentElement.classList.toggle('palette-panel-showing', show);
this._focus();
@@ -263,12 +279,14 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @suppress {checkTypes}
*/
_focus() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
- if (this._palettePanelShowing)
+ }
+ if (this._palettePanelShowing) {
this._palettePanel.focus({preventScroll: true});
- else
+ } else {
this.contentElement.focus();
+ }
}
/**
@@ -280,8 +298,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
_createPaletteColor(colorText, colorName, animationDelay) {
const element = createElementWithClass('div', 'spectrum-palette-color');
element.style.background = String.sprintf('linear-gradient(%s, %s), url(Images/checker.png)', colorText, colorText);
- if (animationDelay)
+ if (animationDelay) {
element.animate([{opacity: 0}, {opacity: 1}], {duration: 100, delay: animationDelay, fill: 'backwards'});
+ }
element.title = colorName || colorText;
return element;
}
@@ -300,6 +319,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
colorElement.addEventListener(
'mousedown',
this._paletteColorSelected.bind(this, palette.colors[i], palette.colorNames[i], palette.matchUserFormat));
+ colorElement.addEventListener(
+ 'keydown',
+ this._onPaletteColorKeydown.bind(this, palette.colors[i], palette.colorNames[i], palette.matchUserFormat));
if (palette.mutable) {
colorElement.__mutable = true;
colorElement.__color = palette.colors[i];
@@ -315,6 +337,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
}
this._paletteContainer.appendChild(colorElement);
}
+ if (this._paletteContainer.childNodes.length > 0) {
+ this._paletteContainer.childNodes[0].tabIndex = 0;
+ }
this._paletteContainerMutable = palette.mutable;
if (palette.mutable) {
@@ -346,8 +371,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
delete this._shadesCloseHandler;
}
- if (this._shadesCloseHandler)
+ if (this._shadesCloseHandler) {
this._shadesCloseHandler();
+ }
this._shadesContainer.classList.remove('hidden');
this._shadesContainer.removeChildren();
@@ -355,8 +381,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
[{transform: 'scaleY(0)', opacity: '0'}, {transform: 'scaleY(1)', opacity: '1'}],
{duration: 200, easing: 'cubic-bezier(0.4, 0, 0.2, 1)'});
let shadesTop = this._paletteContainer.offsetTop + colorElement.offsetTop + colorElement.parentElement.offsetTop;
- if (this._contrastDetails)
+ if (this._contrastDetails) {
shadesTop += this._contrastDetails.element().offsetHeight;
+ }
this._shadesContainer.style.top = shadesTop + 'px';
this._shadesContainer.style.left = colorElement.offsetLeft + 'px';
colorElement.classList.add('spectrum-shades-shown');
@@ -402,8 +429,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
_paletteDragStart(e) {
const element = e.deepElementFromPoint();
- if (!element || !element.__mutable)
+ if (!element || !element.__mutable) {
return false;
+ }
const index = this._slotIndexForEvent(e);
this._dragElement = element;
@@ -418,8 +446,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @param {!Event} e
*/
_paletteDrag(e) {
- if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._paletteContainer.totalOffsetTop())
+ if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._paletteContainer.totalOffsetTop()) {
return;
+ }
const newIndex = this._slotIndexForEvent(e);
const offsetX =
e.pageX - (newIndex % ColorPicker.Spectrum._itemsPerPaletteRow) * ColorPicker.Spectrum._colorChipSize;
@@ -436,15 +465,18 @@ ColorPicker.Spectrum = class extends UI.VBox {
const index = children.indexOf(this._dragElement);
/** @type {!Map.<!Element, {left: number, top: number}>} */
const swatchOffsets = new Map();
- for (const swatch of children)
+ for (const swatch of children) {
swatchOffsets.set(swatch, swatch.totalOffset());
+ }
- if (index !== newIndex)
+ if (index !== newIndex) {
this._paletteContainer.insertBefore(this._dragElement, children[newIndex > index ? newIndex + 1 : newIndex]);
+ }
for (const swatch of children) {
- if (swatch === this._dragElement)
+ if (swatch === this._dragElement) {
continue;
+ }
const before = swatchOffsets.get(swatch);
const after = swatch.totalOffset();
if (before.left !== after.left || before.top !== after.top) {
@@ -465,14 +497,16 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @param {!Event} e
*/
_paletteDragEnd(e) {
- if (this._isDraggingToBin(e))
+ if (this._isDraggingToBin(e)) {
this._dragElement.remove();
+ }
this._dragElement.style.removeProperty('transform');
const children = this._paletteContainer.children;
const colors = [];
for (let i = 0; i < children.length; ++i) {
- if (children[i].__color)
+ if (children[i].__color) {
colors.push(children[i].__color);
+ }
}
const palette = this._customPaletteSetting.get();
palette.colors = colors;
@@ -496,8 +530,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
this._selectedColorPalette =
Common.settings.createSetting('selectedColorPalette', ColorPicker.Spectrum.GeneratedPaletteTitle);
const palette = this._palettes.get(this._selectedColorPalette.get());
- if (palette)
+ if (palette) {
this._showPalette(palette, true);
+ }
}
/**
@@ -505,8 +540,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
addPalette(palette) {
this._palettes.set(palette.title, palette);
- if (this._selectedColorPalette.get() === palette.title)
+ if (this._selectedColorPalette.get() === palette.title) {
this._showPalette(palette, true);
+ }
}
/**
@@ -521,11 +557,13 @@ ColorPicker.Spectrum = class extends UI.VBox {
const titleElement = previewElement.createChild('div', 'palette-preview-title');
titleElement.textContent = palette.title;
let i;
- for (i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++)
+ for (i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++) {
previewElement.appendChild(this._createPaletteColor(palette.colors[i], palette.colorNames[i]));
- for (; i < colorsPerPreviewRow; i++)
+ }
+ for (; i < colorsPerPreviewRow; i++) {
previewElement.createChild('div', 'spectrum-palette-color empty-color');
- onInvokeElement(previewElement, event => {
+ }
+ self.onInvokeElement(previewElement, event => {
this._paletteSelected(palette);
event.consume(true);
});
@@ -545,23 +583,27 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
_resizeForSelectedPalette(force) {
const palette = this._palettes.get(this._selectedColorPalette.get());
- if (!palette)
+ if (!palette) {
return;
+ }
let numColors = palette.colors.length;
- if (palette === this._customPaletteSetting.get())
+ if (palette === this._customPaletteSetting.get()) {
numColors++;
+ }
const rowsNeeded = Math.max(1, Math.ceil(numColors / ColorPicker.Spectrum._itemsPerPaletteRow));
- if (this._numPaletteRowsShown === rowsNeeded && !force)
+ if (this._numPaletteRowsShown === rowsNeeded && !force) {
return;
+ }
this._numPaletteRowsShown = rowsNeeded;
const paletteColorHeight = 12;
const paletteMargin = 12;
let paletteTop = 236;
if (this._contrastDetails) {
- if (this._contrastDetails.expanded())
+ if (this._contrastDetails.expanded()) {
paletteTop += 78;
- else
+ } else {
paletteTop += 36;
+ }
}
this.element.style.height = (paletteTop + paletteMargin + (paletteColorHeight + paletteMargin) * rowsNeeded) + 'px';
this.dispatchEventToListeners(ColorPicker.Spectrum.Events.SizeChanged);
@@ -574,14 +616,35 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
_paletteColorSelected(colorText, colorName, matchUserFormat) {
const color = Common.Color.parse(colorText);
- if (!color)
+ if (!color) {
return;
+ }
this._innerSetColor(
color.hsva(), colorText, colorName, matchUserFormat ? this._colorFormat : color.format(),
ColorPicker.Spectrum._ChangeSource.Other);
}
/**
+ * @param {string} colorText
+ * @param {(string|undefined)} colorName
+ * @param {boolean} matchUserFormat
+ * @param {!Event} event
+ */
+ _onPaletteColorKeydown(colorText, colorName, matchUserFormat, event) {
+ if (isEnterOrSpaceKey(event)) {
+ this._paletteColorSelected(colorText, colorName, matchUserFormat);
+ // If this is a long keypress on color palette of type Material then, it needs to handled by _showLightnessShades on same element. So, just stopPropagation instead of consuming it.
+ event.stopPropagation();
+ } else if (event.key === 'ArrowLeft' && event.target.previousElementSibling) {
+ event.target.previousElementSibling.focus();
+ event.consume(true);
+ } else if (event.key === 'ArrowRight' && event.target.nextElementSibling) {
+ event.target.nextElementSibling.focus();
+ event.consume(true);
+ }
+ }
+
+ /**
* @param {!Common.Event} event
*/
_addColorToCustomPalette(event) {
@@ -596,8 +659,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @param {!Event} event
*/
_showPaletteColorContextMenu(colorIndex, event) {
- if (!this._paletteContainerMutable)
+ if (!this._paletteContainerMutable) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
if (colorIndex !== -1) {
contextMenu.defaultSection().appendItem(
@@ -616,10 +680,11 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
_deletePaletteColors(colorIndex, toRight) {
const palette = this._customPaletteSetting.get();
- if (toRight)
+ if (toRight) {
palette.colors.splice(colorIndex + 1, palette.colors.length - colorIndex - 1);
- else
+ } else {
palette.colors.splice(colorIndex, 1);
+ }
this._customPaletteSetting.set(palette);
this._showPalette(this._customPaletteSetting.get(), false);
}
@@ -642,35 +707,41 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @param {string} changeSource
*/
_innerSetColor(hsva, colorString, colorName, colorFormat, changeSource) {
- if (hsva !== undefined)
+ if (hsva !== undefined) {
this._hsv = hsva;
+ }
this._colorName = colorName;
- if (colorString !== undefined)
+ if (colorString !== undefined) {
this._colorString = colorString;
+ }
if (colorFormat !== undefined) {
const cf = Common.Color.Format;
console.assert(colorFormat !== cf.Original, 'Spectrum\'s color format cannot be Original');
- if (colorFormat === cf.RGBA)
+ if (colorFormat === cf.RGBA) {
colorFormat = cf.RGB;
- else if (colorFormat === cf.HSLA)
+ } else if (colorFormat === cf.HSLA) {
colorFormat = cf.HSL;
- else if (colorFormat === cf.HEXA)
+ } else if (colorFormat === cf.HEXA) {
colorFormat = cf.HEX;
- else if (colorFormat === cf.ShortHEXA)
+ } else if (colorFormat === cf.ShortHEXA) {
colorFormat = cf.ShortHEX;
+ }
this._colorFormat = colorFormat;
}
- if (hsva && this._contrastInfo)
+ if (hsva && this._contrastInfo) {
this._contrastInfo.setColor(Common.Color.fromHSVA(hsva));
+ }
this._updateHelperLocations();
this._updateUI();
- if (changeSource !== ColorPicker.Spectrum._ChangeSource.Input)
+ if (changeSource !== ColorPicker.Spectrum._ChangeSource.Input) {
this._updateInput();
- if (changeSource !== ColorPicker.Spectrum._ChangeSource.Model)
+ }
+ if (changeSource !== ColorPicker.Spectrum._ChangeSource.Model) {
this.dispatchEventToListeners(ColorPicker.Spectrum.Events.ColorChanged, this.colorString());
+ }
}
/**
@@ -691,24 +762,27 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @return {string}
*/
colorString() {
- if (this._colorString)
+ if (this._colorString) {
return this._colorString;
+ }
const cf = Common.Color.Format;
const color = this._color();
let colorString = color.asString(this._colorFormat);
- if (colorString)
+ if (colorString) {
return colorString;
+ }
- if (this._colorFormat === cf.Nickname)
+ if (this._colorFormat === cf.Nickname) {
colorString = color.asString(color.hasAlpha() ? cf.HEXA : cf.HEX);
- else if (this._colorFormat === cf.ShortHEX)
+ } else if (this._colorFormat === cf.ShortHEX) {
colorString = color.asString(color.detectHEXFormat());
- else if (this._colorFormat === cf.HEX)
+ } else if (this._colorFormat === cf.HEX) {
colorString = color.asString(cf.HEXA);
- else if (this._colorFormat === cf.HSL)
+ } else if (this._colorFormat === cf.HSL) {
colorString = color.asString(cf.HSLA);
- else
+ } else {
colorString = color.asString(cf.RGBA);
+ }
console.assert(colorString);
return colorString || '';
@@ -759,8 +833,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
const colorValues = isRgb ? this._color().canonicalRGBA() : this._color().canonicalHSLA();
for (let i = 0; i < 3; ++i) {
this._textValues[i].value = colorValues[i];
- if (!isRgb && (i === 1 || i === 2))
+ if (!isRgb && (i === 1 || i === 2)) {
this._textValues[i].value += '%';
+ }
}
this._textValues[3].value = Math.round(colorValues[3] * 100) / 100;
}
@@ -769,8 +844,9 @@ ColorPicker.Spectrum = class extends UI.VBox {
_updateUI() {
const h = Common.Color.fromHSVA([this._hsv[0], 1, 1, 1]);
this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(Common.Color.Format.RGB));
- if (this._contrastOverlay)
+ if (this._contrastOverlay) {
this._contrastOverlay.setDimensions(this.dragWidth, this.dragHeight);
+ }
this._swatch.setColor(this._color(), this.colorString());
this._colorDragElement.style.backgroundColor =
@@ -783,10 +859,11 @@ ColorPicker.Spectrum = class extends UI.VBox {
_formatViewSwitch() {
const cf = Common.Color.Format;
let format = cf.RGB;
- if (this._colorFormat === cf.RGB)
+ if (this._colorFormat === cf.RGB) {
format = cf.HSL;
- else if (this._colorFormat === cf.HSL)
+ } else if (this._colorFormat === cf.HSL) {
format = (this._originalFormat === cf.ShortHEX || this._originalFormat === cf.ShortHEXA) ? cf.ShortHEX : cf.HEX;
+ }
this._innerSetColor(undefined, '', undefined /* colorName */, format, ColorPicker.Spectrum._ChangeSource.Other);
}
@@ -822,12 +899,14 @@ ColorPicker.Spectrum = class extends UI.VBox {
}
const color = Common.Color.parse(colorString);
- if (!color)
+ if (!color) {
return;
+ }
let colorFormat = undefined;
- if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX)
+ if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) {
colorFormat = color.detectHEXFormat();
+ }
this._innerSetColor(
color.hsva(), colorString, undefined /* colorName */, colorFormat, ColorPicker.Spectrum._ChangeSource.Input);
}
@@ -844,6 +923,12 @@ ColorPicker.Spectrum = class extends UI.VBox {
this._innerSetColor(
undefined, undefined, undefined /* colorName */, undefined, ColorPicker.Spectrum._ChangeSource.Model);
this._toggleColorPicker(true);
+
+ if (this._contrastDetails) {
+ this._contrastDetails.addEventListener(
+ ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled,
+ this._contrastDetailsBackgroundColorPickedToggledBound);
+ }
}
/**
@@ -851,6 +936,11 @@ ColorPicker.Spectrum = class extends UI.VBox {
*/
willHide() {
this._toggleColorPicker(false);
+ if (this._contrastDetails) {
+ this._contrastDetails.removeEventListener(
+ ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled,
+ this._contrastDetailsBackgroundColorPickedToggledBound);
+ }
}
/**
@@ -858,16 +948,24 @@ ColorPicker.Spectrum = class extends UI.VBox {
* @param {!Common.Event=} event
*/
_toggleColorPicker(enabled, event) {
- if (enabled === undefined)
+ if (enabled === undefined) {
enabled = !this._colorPickerButton.toggled();
+ }
this._colorPickerButton.setToggled(enabled);
- InspectorFrontendHost.setEyeDropperActive(enabled);
+
+ // This is to make sure that only one picker is open at a time
+ // Also have a look at this._contrastDetailsBackgroundColorPickedToggled
+ if (this._contrastDetails && enabled && this._contrastDetails.backgroundColorPickerEnabled()) {
+ this._contrastDetails.toggleBackgroundColorPicker(false);
+ }
+
+ Host.InspectorFrontendHost.setEyeDropperActive(enabled);
if (enabled) {
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
} else {
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound);
}
}
@@ -880,7 +978,7 @@ ColorPicker.Spectrum = class extends UI.VBox {
const color = Common.Color.fromRGBA(rgba);
this._innerSetColor(
color.hsva(), '', undefined /* colorName */, undefined, ColorPicker.Spectrum._ChangeSource.Other);
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
}
};
@@ -913,8 +1011,9 @@ ColorPicker.Spectrum.PaletteGenerator = class {
this._frequencyMap = new Map();
const stylesheetPromises = [];
for (const cssModel of SDK.targetManager.models(SDK.CSSModel)) {
- for (const stylesheet of cssModel.allStyleSheets())
+ for (const stylesheet of cssModel.allStyleSheets()) {
stylesheetPromises.push(this._processStylesheet(stylesheet));
+ }
}
Promise.all(stylesheetPromises).catchException(null).then(this._finish.bind(this));
}
@@ -939,16 +1038,20 @@ ColorPicker.Spectrum.PaletteGenerator = class {
const hsvb = paletteColors.get(b).hsva();
// First trim the shades of gray
- if (hsvb[1] < 0.12 && hsva[1] < 0.12)
+ if (hsvb[1] < 0.12 && hsva[1] < 0.12) {
return hsvb[2] * hsvb[3] - hsva[2] * hsva[3];
- if (hsvb[1] < 0.12)
+ }
+ if (hsvb[1] < 0.12) {
return -1;
- if (hsva[1] < 0.12)
+ }
+ if (hsva[1] < 0.12) {
return 1;
+ }
// Equal hue -> sort by sat
- if (hsvb[0] === hsva[0])
+ if (hsvb[0] === hsva[0]) {
return hsvb[1] * hsvb[3] - hsva[1] * hsva[3];
+ }
return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1;
}
@@ -961,8 +1064,9 @@ ColorPicker.Spectrum.PaletteGenerator = class {
while (paletteColors.size < colorsPerRow && colors.length) {
const colorText = colors.shift();
const color = Common.Color.parse(colorText);
- if (!color || color.nickname() === 'white' || color.nickname() === 'black')
+ if (!color || color.nickname() === 'white' || color.nickname() === 'black') {
continue;
+ }
paletteColors.set(colorText, color);
}
@@ -979,7 +1083,7 @@ ColorPicker.Spectrum.PaletteGenerator = class {
* @return {!Promise}
*/
async _processStylesheet(stylesheet) {
- let text = await stylesheet.requestContent() || '';
+ let text = (await stylesheet.requestContent()).content || '';
text = text.toLowerCase();
const regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || [];
for (const c of regexResult) {
@@ -1050,11 +1154,16 @@ ColorPicker.Spectrum.Swatch = class {
this._swatchInnerElement = swatchElement.createChild('span', 'swatch-inner');
this._swatchOverlayElement = swatchElement.createChild('span', 'swatch-overlay');
- this._swatchOverlayElement.addEventListener('click', this._onCopyIconClick.bind(this));
+ UI.ARIAUtils.markAsButton(this._swatchOverlayElement);
+ UI.ARIAUtils.setPressed(this._swatchOverlayElement, false);
+ this._swatchOverlayElement.tabIndex = 0;
+ self.onInvokeElement(this._swatchOverlayElement, this._onCopyText.bind(this));
this._swatchOverlayElement.addEventListener('mouseout', this._onCopyIconMouseout.bind(this));
+ this._swatchOverlayElement.addEventListener('blur', this._onCopyIconMouseout.bind(this));
this._swatchCopyIcon = UI.Icon.create('largeicon-copy', 'copy-color-icon');
- this._swatchCopyIcon.title = Common.UIString('Copy color to clipboard');
+ this._swatchCopyIcon.title = ls`Copy color to clipboard`;
this._swatchOverlayElement.appendChild(this._swatchCopyIcon);
+ UI.ARIAUtils.setAccessibleName(this._swatchOverlayElement, this._swatchCopyIcon.title);
}
/**
@@ -1067,18 +1176,25 @@ ColorPicker.Spectrum.Swatch = class {
// Show border if the swatch is white.
this._swatchInnerElement.classList.toggle('swatch-inner-white', color.hsla()[2] > 0.9);
this._colorString = colorString || null;
- if (colorString)
+ if (colorString) {
this._swatchOverlayElement.hidden = false;
- else
+ } else {
this._swatchOverlayElement.hidden = true;
+ }
}
- _onCopyIconClick() {
+ /**
+ * @param {!Event} event
+ */
+ _onCopyText(event) {
this._swatchCopyIcon.setIconType('largeicon-checkmark');
- InspectorFrontendHost.copyText(this._colorString);
+ Host.InspectorFrontendHost.copyText(this._colorString);
+ UI.ARIAUtils.setPressed(this._swatchOverlayElement, true);
+ event.consume();
}
_onCopyIconMouseout() {
this._swatchCopyIcon.setIconType('largeicon-copy');
+ UI.ARIAUtils.setPressed(this._swatchOverlayElement, false);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
index 346e0b25263..0537b085c25 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/color_picker_strings.grdp
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_146ffe2fd9fa5bec3b63b52543793ec7" desc="Tooltip text that appears when hovering over the smallicon expand more button in the Contrast Details of the Color Picker">
- Show more
- </message>
<message name="IDS_DEVTOOLS_158eabad9d23e8a99bbcfd6f411c575f" desc="A context menu item in the Spectrum of the Color Picker">
Remove color
</message>
@@ -39,12 +36,6 @@
<message name="IDS_DEVTOOLS_bbe0cb0a04956e97e8fc70f519d10e0d" desc="Color element title in Spectrum of the Color Picker">
<ph name="PALETTE_COLORS_I_">$1s<ex>#9c1724</ex></ph>. Long-click to show alternate shades.
</message>
- <message name="IDS_DEVTOOLS_c74ea6dbff701bfa23819583c52ebd97" desc="Title of expand button in contrast details of the color picker">
- Show less
- </message>
- <message name="IDS_DEVTOOLS_ce82e07fa1f0521f5cee30e368fe2e73" desc="Text in Contrast Details of the Color Picker">
- : <ph name="AA_TOFIXED___">$1s<ex>3.0</ex></ph>
- </message>
<message name="IDS_DEVTOOLS_d1e2107b34fa404fabd54bcce4fd858f" desc="Tooltip text that appears when hovering over the largeicon add button in the Spectrum of the Color Picker">
Add to palette
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
index 90f0c160c97..147ccea76bf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
@@ -259,7 +259,8 @@
padding: 4px;
}
-.swatch-overlay:hover {
+.swatch-overlay:hover,
+.swatch-overlay[data-keyboard-focus="true"]:focus {
background-color: rgba(0, 0, 0, .3);
opacity: 1;
}
@@ -372,11 +373,13 @@
z-index: 14;
}
-.spectrum-palette-color:hover:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow {
+.spectrum-palette-color:hover:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow,
+.spectrum-palette-color:focus:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow {
opacity: 0.2;
}
-.spectrum-palette-color:hover:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow:first-child {
+.spectrum-palette-color:hover:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow:first-child,
+.spectrum-palette-color:focus:not(.spectrum-shades-shown) > .spectrum-palette-color-shadow:first-child {
opacity: 0.6;
top: -3px;
left: 1px;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/App.js b/chromium/third_party/blink/renderer/devtools/front_end/common/App.js
new file mode 100644
index 00000000000..f09920f4954
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/App.js
@@ -0,0 +1,23 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class App {
+ /**
+ * @param {!Document} document
+ */
+ presentUI(document) {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.App = App;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/AppProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/common/AppProvider.js
new file mode 100644
index 00000000000..77c20ca1745
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/AppProvider.js
@@ -0,0 +1,23 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class AppProvider {
+ /**
+ * @return {!Common.App}
+ */
+ createApp() {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.AppProvider = AppProvider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js b/chromium/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
index 627df761a21..f535f980ad1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/CharacterIdMap.js
@@ -5,7 +5,7 @@
* @template T
* @unrestricted
*/
-Common.CharacterIdMap = class {
+export default class CharacterIdMap {
constructor() {
/** @type {!Map<T, string>} */
this._elementToCharacter = new Map();
@@ -21,8 +21,9 @@ Common.CharacterIdMap = class {
toChar(object) {
let character = this._elementToCharacter.get(object);
if (!character) {
- if (this._charCode >= 0xFFFF)
+ if (this._charCode >= 0xFFFF) {
throw new Error('CharacterIdMap ran out of capacity!');
+ }
character = String.fromCharCode(this._charCode++);
this._elementToCharacter.set(object, character);
this._characterToElement.set(character, object);
@@ -36,8 +37,18 @@ Common.CharacterIdMap = class {
*/
fromChar(character) {
const object = this._characterToElement.get(character);
- if (object === undefined)
+ if (object === undefined) {
return null;
+ }
return object;
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.CharacterIdMap = CharacterIdMap;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Color.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Color.js
index 1fa43f22e1c..a4fc6392dad 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Color.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Color.js
@@ -30,10 +30,10 @@
/**
* @unrestricted
*/
-Common.Color = class {
+export default class Color {
/**
* @param {!Array.<number>} rgba
- * @param {!Common.Color.Format} format
+ * @param {!Format} format
* @param {string=} originalText
*/
constructor(rgba, format, originalText) {
@@ -41,8 +41,9 @@ Common.Color = class {
this._originalText = originalText || null;
this._originalTextIsValid = !!this._originalText;
this._format = format;
- if (typeof this._rgba[3] === 'undefined')
+ if (typeof this._rgba[3] === 'undefined') {
this._rgba[3] = 1;
+ }
for (let i = 0; i < 4; ++i) {
if (this._rgba[i] < 0) {
@@ -58,7 +59,7 @@ Common.Color = class {
/**
* @param {string} text
- * @return {?Common.Color}
+ * @return {?Color}
*/
static parse(text) {
// Simple - #hex, nickname
@@ -70,32 +71,33 @@ Common.Color = class {
let hex = match[1].toLowerCase();
let format;
if (hex.length === 3) {
- format = Common.Color.Format.ShortHEX;
+ format = Format.ShortHEX;
hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
} else if (hex.length === 4) {
- format = Common.Color.Format.ShortHEXA;
+ format = Format.ShortHEXA;
hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2) +
hex.charAt(3) + hex.charAt(3);
} else if (hex.length === 6) {
- format = Common.Color.Format.HEX;
+ format = Format.HEX;
} else {
- format = Common.Color.Format.HEXA;
+ format = Format.HEXA;
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
let a = 1;
- if (hex.length === 8)
+ if (hex.length === 8) {
a = parseInt(hex.substring(6, 8), 16) / 255;
- return new Common.Color([r / 255, g / 255, b / 255, a], format, text);
+ }
+ return new Color([r / 255, g / 255, b / 255, a], format, text);
}
if (match[2]) { // nickname
const nickname = match[2].toLowerCase();
- if (nickname in Common.Color.Nicknames) {
- const rgba = Common.Color.Nicknames[nickname];
- const color = Common.Color.fromRGBA(rgba);
- color._format = Common.Color.Format.Nickname;
+ if (nickname in Nicknames) {
+ const rgba = Nicknames[nickname];
+ const color = Color.fromRGBA(rgba);
+ color._format = Format.Nickname;
color._originalText = text;
return color;
}
@@ -115,8 +117,9 @@ Common.Color = class {
values = components.split(/\s+/);
if (values[3] === '/') {
values.splice(3, 1);
- if (values.length !== 4)
+ if (values.length !== 4) {
return null;
+ }
} else if ((values.length > 2 && values[2].indexOf('/') !== -1) || (values.length > 3 && values[3].indexOf('/') !== -1)) {
const alpha = values.slice(2, 4).join('');
values = values.slice(0, 2).concat(alpha.split(/\//)).concat(values.slice(4));
@@ -124,30 +127,33 @@ Common.Color = class {
return null;
}
}
- if (values.length !== 3 && values.length !== 4 || values.indexOf('') > -1)
+ if (values.length !== 3 && values.length !== 4 || values.indexOf('') > -1) {
return null;
+ }
const hasAlpha = (values[3] !== undefined);
if (match[1]) { // rgb/rgba
const rgba = [
- Common.Color._parseRgbNumeric(values[0]), Common.Color._parseRgbNumeric(values[1]),
- Common.Color._parseRgbNumeric(values[2]), hasAlpha ? Common.Color._parseAlphaNumeric(values[3]) : 1
+ Color._parseRgbNumeric(values[0]), Color._parseRgbNumeric(values[1]), Color._parseRgbNumeric(values[2]),
+ hasAlpha ? Color._parseAlphaNumeric(values[3]) : 1
];
- if (rgba.indexOf(null) > -1)
+ if (rgba.indexOf(null) > -1) {
return null;
- return new Common.Color(rgba, hasAlpha ? Common.Color.Format.RGBA : Common.Color.Format.RGB, text);
+ }
+ return new Color(rgba, hasAlpha ? Format.RGBA : Format.RGB, text);
}
if (match[2]) { // hsl/hsla
const hsla = [
- Common.Color._parseHueNumeric(values[0]), Common.Color._parseSatLightNumeric(values[1]),
- Common.Color._parseSatLightNumeric(values[2]), hasAlpha ? Common.Color._parseAlphaNumeric(values[3]) : 1
+ Color._parseHueNumeric(values[0]), Color._parseSatLightNumeric(values[1]),
+ Color._parseSatLightNumeric(values[2]), hasAlpha ? Color._parseAlphaNumeric(values[3]) : 1
];
- if (hsla.indexOf(null) > -1)
+ if (hsla.indexOf(null) > -1) {
return null;
+ }
const rgba = [];
- Common.Color.hsl2rgb(hsla, rgba);
- return new Common.Color(rgba, hasAlpha ? Common.Color.Format.HSLA : Common.Color.Format.HSL, text);
+ Color.hsl2rgb(hsla, rgba);
+ return new Color(rgba, hasAlpha ? Format.HSLA : Format.HSL, text);
}
}
@@ -156,20 +162,20 @@ Common.Color = class {
/**
* @param {!Array.<number>} rgba
- * @return {!Common.Color}
+ * @return {!Color}
*/
static fromRGBA(rgba) {
- return new Common.Color([rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]], Common.Color.Format.RGBA);
+ return new Color([rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]], Format.RGBA);
}
/**
* @param {!Array.<number>} hsva
- * @return {!Common.Color}
+ * @return {!Color}
*/
static fromHSVA(hsva) {
const rgba = [];
- Common.Color.hsva2rgba(hsva, rgba);
- return new Common.Color(rgba, Common.Color.Format.HSLA);
+ Color.hsva2rgba(hsva, rgba);
+ return new Color(rgba, Format.HSLA);
}
/**
@@ -177,13 +183,15 @@ Common.Color = class {
* return {number}
*/
static _parsePercentOrNumber(value) {
- if (isNaN(value.replace('%', '')))
+ if (isNaN(value.replace('%', ''))) {
return null;
+ }
const parsed = parseFloat(value);
if (value.indexOf('%') !== -1) {
- if (value.indexOf('%') !== value.length - 1)
+ if (value.indexOf('%') !== value.length - 1) {
return null;
+ }
return parsed / 100;
}
return parsed;
@@ -194,12 +202,14 @@ Common.Color = class {
* return {number}
*/
static _parseRgbNumeric(value) {
- const parsed = Common.Color._parsePercentOrNumber(value);
- if (parsed === null)
+ const parsed = Color._parsePercentOrNumber(value);
+ if (parsed === null) {
return null;
+ }
- if (value.indexOf('%') !== -1)
+ if (value.indexOf('%') !== -1) {
return parsed;
+ }
return parsed / 255;
}
@@ -209,16 +219,18 @@ Common.Color = class {
*/
static _parseHueNumeric(value) {
const angle = value.replace(/(deg|g?rad|turn)$/, '');
- if (isNaN(angle) || value.match(/\s+(deg|g?rad|turn)/))
+ if (isNaN(angle) || value.match(/\s+(deg|g?rad|turn)/)) {
return null;
+ }
const number = parseFloat(angle);
- if (value.indexOf('turn') !== -1)
+ if (value.indexOf('turn') !== -1) {
return number % 1;
- else if (value.indexOf('grad') !== -1)
+ } else if (value.indexOf('grad') !== -1) {
return (number / 400) % 1;
- else if (value.indexOf('rad') !== -1)
+ } else if (value.indexOf('rad') !== -1) {
return (number / (2 * Math.PI)) % 1;
+ }
return (number / 360) % 1;
}
@@ -227,8 +239,9 @@ Common.Color = class {
* return {number}
*/
static _parseSatLightNumeric(value) {
- if (value.indexOf('%') !== value.length - 1 || isNaN(value.replace('%', '')))
+ if (value.indexOf('%') !== value.length - 1 || isNaN(value.replace('%', ''))) {
return null;
+ }
const parsed = parseFloat(value);
return Math.min(1, parsed / 100);
}
@@ -238,7 +251,7 @@ Common.Color = class {
* return {number}
*/
static _parseAlphaNumeric(value) {
- return Common.Color._parsePercentOrNumber(value);
+ return Color._parsePercentOrNumber(value);
}
/**
@@ -251,10 +264,11 @@ Common.Color = class {
const v = hsva[2];
const t = (2 - s) * v;
- if (v === 0 || s === 0)
+ if (v === 0 || s === 0) {
s = 0;
- else
+ } else {
s *= v / (t < 1 ? t : 2 - t);
+ }
out_hsla[0] = h;
out_hsla[1] = s;
@@ -272,29 +286,33 @@ Common.Color = class {
const l = hsl[2];
function hue2rgb(p, q, h) {
- if (h < 0)
+ if (h < 0) {
h += 1;
- else if (h > 1)
+ } else if (h > 1) {
h -= 1;
+ }
- if ((h * 6) < 1)
+ if ((h * 6) < 1) {
return p + (q - p) * h * 6;
- else if ((h * 2) < 1)
+ } else if ((h * 2) < 1) {
return q;
- else if ((h * 3) < 2)
+ } else if ((h * 3) < 2) {
return p + (q - p) * ((2 / 3) - h) * 6;
- else
+ } else {
return p;
+ }
}
- if (s < 0)
+ if (s < 0) {
s = 0;
+ }
let q;
- if (l <= 0.5)
+ if (l <= 0.5) {
q = l * (1 + s);
- else
+ } else {
q = l + s - (l * s);
+ }
const p = 2 * l - q;
@@ -313,11 +331,12 @@ Common.Color = class {
* @param {!Array<number>} out_rgba
*/
static hsva2rgba(hsva, out_rgba) {
- Common.Color._hsva2hsla(hsva, Common.Color.hsva2rgba._tmpHSLA);
- Common.Color.hsl2rgb(Common.Color.hsva2rgba._tmpHSLA, out_rgba);
+ Color._hsva2hsla(hsva, Color.hsva2rgba._tmpHSLA);
+ Color.hsl2rgb(Color.hsva2rgba._tmpHSLA, out_rgba);
- for (let i = 0; i < Common.Color.hsva2rgba._tmpHSLA.length; i++)
- Common.Color.hsva2rgba._tmpHSLA[i] = 0;
+ for (let i = 0; i < Color.hsva2rgba._tmpHSLA.length; i++) {
+ Color.hsva2rgba._tmpHSLA[i] = 0;
+ }
}
/**
@@ -362,14 +381,15 @@ Common.Color = class {
* @return {number}
*/
static calculateContrastRatio(fgRGBA, bgRGBA) {
- Common.Color.blendColors(fgRGBA, bgRGBA, Common.Color.calculateContrastRatio._blendedFg);
+ Color.blendColors(fgRGBA, bgRGBA, Color.calculateContrastRatio._blendedFg);
- const fgLuminance = Common.Color.luminance(Common.Color.calculateContrastRatio._blendedFg);
- const bgLuminance = Common.Color.luminance(bgRGBA);
+ const fgLuminance = Color.luminance(Color.calculateContrastRatio._blendedFg);
+ const bgLuminance = Color.luminance(bgRGBA);
const contrastRatio = (Math.max(fgLuminance, bgLuminance) + 0.05) / (Math.min(fgLuminance, bgLuminance) + 0.05);
- for (let i = 0; i < Common.Color.calculateContrastRatio._blendedFg.length; i++)
- Common.Color.calculateContrastRatio._blendedFg[i] = 0;
+ for (let i = 0; i < Color.calculateContrastRatio._blendedFg.length; i++) {
+ Color.calculateContrastRatio._blendedFg[i] = 0;
+ }
return contrastRatio;
}
@@ -387,10 +407,11 @@ Common.Color = class {
*/
static desiredLuminance(luminance, contrast, lighter) {
function computeLuminance() {
- if (lighter)
+ if (lighter) {
return (luminance + 0.05) * contrast - 0.05;
- else
+ } else {
return (luminance + 0.05) / contrast - 0.05;
+ }
}
let desiredLuminance = computeLuminance();
if (desiredLuminance < 0 || desiredLuminance > 1) {
@@ -401,29 +422,30 @@ Common.Color = class {
}
/**
- * @param {!Common.Color} color
- * @return {!Common.Color.Format}
+ * @param {!Color} color
+ * @return {!Format}
*/
static detectColorFormat(color) {
- const cf = Common.Color.Format;
+ const cf = Format;
let format;
const formatSetting = Common.moduleSetting('colorFormat').get();
- if (formatSetting === cf.Original)
+ if (formatSetting === cf.Original) {
format = cf.Original;
- else if (formatSetting === cf.RGB)
+ } else if (formatSetting === cf.RGB) {
format = (color.hasAlpha() ? cf.RGBA : cf.RGB);
- else if (formatSetting === cf.HSL)
+ } else if (formatSetting === cf.HSL) {
format = (color.hasAlpha() ? cf.HSLA : cf.HSL);
- else if (formatSetting === cf.HEX)
+ } else if (formatSetting === cf.HEX) {
format = color.detectHEXFormat();
- else
+ } else {
format = cf.RGBA;
+ }
return format;
}
/**
- * @return {!Common.Color.Format}
+ * @return {!Format}
*/
format() {
return this._format;
@@ -433,8 +455,9 @@ Common.Color = class {
* @return {!Array.<number>} HSLA with components within [0..1]
*/
hsla() {
- if (this._hsla)
+ if (this._hsla) {
return this._hsla;
+ }
const r = this._rgba[0];
const g = this._rgba[1];
const b = this._rgba[2];
@@ -444,26 +467,28 @@ Common.Color = class {
const add = max + min;
let h;
- if (min === max)
+ if (min === max) {
h = 0;
- else if (r === max)
+ } else if (r === max) {
h = ((1 / 6 * (g - b) / diff) + 1) % 1;
- else if (g === max)
+ } else if (g === max) {
h = (1 / 6 * (b - r) / diff) + 1 / 3;
- else
+ } else {
h = (1 / 6 * (r - g) / diff) + 2 / 3;
+ }
const l = 0.5 * add;
let s;
- if (l === 0)
+ if (l === 0) {
s = 0;
- else if (l === 1)
+ } else if (l === 1) {
s = 0;
- else if (l <= 0.5)
+ } else if (l <= 0.5) {
s = diff / add;
- else
+ } else {
s = diff / (2 - add);
+ }
this._hsla = [h, s, l, this._rgba[3]];
return this._hsla;
@@ -498,7 +523,7 @@ Common.Color = class {
}
/**
- * @return {!Common.Color.Format}
+ * @return {!Format}
*/
detectHEXFormat() {
let canBeShort = true;
@@ -511,9 +536,10 @@ Common.Color = class {
}
const hasAlpha = this.hasAlpha();
- const cf = Common.Color.Format;
- if (canBeShort)
+ const cf = Format;
+ if (canBeShort) {
return hasAlpha ? cf.ShortHEXA : cf.ShortHEX;
+ }
return hasAlpha ? cf.HEXA : cf.HEX;
}
@@ -521,11 +547,13 @@ Common.Color = class {
* @return {?string}
*/
asString(format) {
- if (format === this._format && this._originalTextIsValid)
+ if (format === this._format && this._originalTextIsValid) {
return this._originalText;
+ }
- if (!format)
+ if (!format) {
format = this._format;
+ }
/**
* @param {number} value
@@ -553,60 +581,66 @@ Common.Color = class {
}
switch (format) {
- case Common.Color.Format.Original:
+ case Format.Original:
return this._originalText;
- case Common.Color.Format.RGB:
- if (this.hasAlpha())
+ case Format.RGB:
+ if (this.hasAlpha()) {
return null;
+ }
return String.sprintf(
'rgb(%d, %d, %d)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]));
- case Common.Color.Format.RGBA:
+ case Format.RGBA:
return String.sprintf(
'rgba(%d, %d, %d, %f)', toRgbValue(this._rgba[0]), toRgbValue(this._rgba[1]), toRgbValue(this._rgba[2]),
this._rgba[3]);
- case Common.Color.Format.HSL:
- if (this.hasAlpha())
+ case Format.HSL:
+ if (this.hasAlpha()) {
return null;
+ }
const hsl = this.hsla();
return String.sprintf(
'hsl(%d, %d%, %d%)', Math.round(hsl[0] * 360), Math.round(hsl[1] * 100), Math.round(hsl[2] * 100));
- case Common.Color.Format.HSLA:
+ case Format.HSLA:
const hsla = this.hsla();
return String.sprintf(
'hsla(%d, %d%, %d%, %f)', Math.round(hsla[0] * 360), Math.round(hsla[1] * 100), Math.round(hsla[2] * 100),
hsla[3]);
- case Common.Color.Format.HEXA:
+ case Format.HEXA:
return String
.sprintf(
'#%s%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]),
toHexValue(this._rgba[3]))
.toLowerCase();
- case Common.Color.Format.HEX:
- if (this.hasAlpha())
+ case Format.HEX:
+ if (this.hasAlpha()) {
return null;
+ }
return String
.sprintf('#%s%s%s', toHexValue(this._rgba[0]), toHexValue(this._rgba[1]), toHexValue(this._rgba[2]))
.toLowerCase();
- case Common.Color.Format.ShortHEXA:
+ case Format.ShortHEXA:
const hexFormat = this.detectHEXFormat();
- if (hexFormat !== Common.Color.Format.ShortHEXA && hexFormat !== Common.Color.Format.ShortHEX)
+ if (hexFormat !== Format.ShortHEXA && hexFormat !== Format.ShortHEX) {
return null;
+ }
return String
.sprintf(
'#%s%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
toShortHexValue(this._rgba[2]), toShortHexValue(this._rgba[3]))
.toLowerCase();
- case Common.Color.Format.ShortHEX:
- if (this.hasAlpha())
+ case Format.ShortHEX:
+ if (this.hasAlpha()) {
return null;
- if (this.detectHEXFormat() !== Common.Color.Format.ShortHEX)
+ }
+ if (this.detectHEXFormat() !== Format.ShortHEX) {
return null;
+ }
return String
.sprintf(
'#%s%s%s', toShortHexValue(this._rgba[0]), toShortHexValue(this._rgba[1]),
toShortHexValue(this._rgba[2]))
.toLowerCase();
- case Common.Color.Format.Nickname:
+ case Format.Nickname:
return this.nickname();
}
@@ -625,8 +659,9 @@ Common.Color = class {
*/
canonicalRGBA() {
const rgba = new Array(4);
- for (let i = 0; i < 3; ++i)
+ for (let i = 0; i < 3; ++i) {
rgba[i] = Math.round(this._rgba[i] * 255);
+ }
rgba[3] = this._rgba[3];
return rgba;
}
@@ -635,17 +670,18 @@ Common.Color = class {
* @return {?string} nickname
*/
nickname() {
- if (!Common.Color._rgbaToNickname) {
- Common.Color._rgbaToNickname = {};
- for (const nickname in Common.Color.Nicknames) {
- let rgba = Common.Color.Nicknames[nickname];
- if (rgba.length !== 4)
+ if (!Color._rgbaToNickname) {
+ Color._rgbaToNickname = {};
+ for (const nickname in Nicknames) {
+ let rgba = Nicknames[nickname];
+ if (rgba.length !== 4) {
rgba = rgba.concat(1);
- Common.Color._rgbaToNickname[rgba] = nickname;
+ }
+ Color._rgbaToNickname[rgba] = nickname;
}
}
- return Common.Color._rgbaToNickname[this.canonicalRGBA()] || null;
+ return Color._rgbaToNickname[this.canonicalRGBA()] || null;
}
/**
@@ -654,13 +690,14 @@ Common.Color = class {
toProtocolRGBA() {
const rgba = this.canonicalRGBA();
const result = {r: rgba[0], g: rgba[1], b: rgba[2]};
- if (rgba[3] !== 1)
+ if (rgba[3] !== 1) {
result.a = rgba[3];
+ }
return result;
}
/**
- * @return {!Common.Color}
+ * @return {!Color}
*/
invert() {
const rgba = [];
@@ -668,37 +705,37 @@ Common.Color = class {
rgba[1] = 1 - this._rgba[1];
rgba[2] = 1 - this._rgba[2];
rgba[3] = this._rgba[3];
- return new Common.Color(rgba, Common.Color.Format.RGBA);
+ return new Color(rgba, Format.RGBA);
}
/**
* @param {number} alpha
- * @return {!Common.Color}
+ * @return {!Color}
*/
setAlpha(alpha) {
const rgba = this._rgba.slice();
rgba[3] = alpha;
- return new Common.Color(rgba, Common.Color.Format.RGBA);
+ return new Color(rgba, Format.RGBA);
}
/**
- * @param {!Common.Color} fgColor
- * @return {!Common.Color}
+ * @param {!Color} fgColor
+ * @return {!Color}
*/
blendWith(fgColor) {
const rgba = [];
- Common.Color.blendColors(fgColor._rgba, this._rgba, rgba);
- return new Common.Color(rgba, Common.Color.Format.RGBA);
+ Color.blendColors(fgColor._rgba, this._rgba, rgba);
+ return new Color(rgba, Format.RGBA);
}
-};
+}
/** @type {!RegExp} */
-Common.Color.Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
+export const Regex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
/**
* @enum {string}
*/
-Common.Color.Format = {
+export const Format = {
Original: 'original',
Nickname: 'nickname',
HEX: 'hex',
@@ -711,15 +748,7 @@ Common.Color.Format = {
HSLA: 'hsla'
};
-
-/** @type {!Array<number>} */
-Common.Color.hsva2rgba._tmpHSLA = [0, 0, 0, 0];
-
-
-Common.Color.calculateContrastRatio._blendedFg = [0, 0, 0, 0];
-
-
-Common.Color.Nicknames = {
+export const Nicknames = {
'aliceblue': [240, 248, 255],
'antiquewhite': [250, 235, 215],
'aqua': [0, 255, 255],
@@ -871,23 +900,23 @@ Common.Color.Nicknames = {
'transparent': [0, 0, 0, 0],
};
-Common.Color.PageHighlight = {
- Content: Common.Color.fromRGBA([111, 168, 220, .66]),
- ContentLight: Common.Color.fromRGBA([111, 168, 220, .5]),
- ContentOutline: Common.Color.fromRGBA([9, 83, 148]),
- Padding: Common.Color.fromRGBA([147, 196, 125, .55]),
- PaddingLight: Common.Color.fromRGBA([147, 196, 125, .4]),
- Border: Common.Color.fromRGBA([255, 229, 153, .66]),
- BorderLight: Common.Color.fromRGBA([255, 229, 153, .5]),
- Margin: Common.Color.fromRGBA([246, 178, 107, .66]),
- MarginLight: Common.Color.fromRGBA([246, 178, 107, .5]),
- EventTarget: Common.Color.fromRGBA([255, 196, 196, .66]),
- Shape: Common.Color.fromRGBA([96, 82, 177, 0.8]),
- ShapeMargin: Common.Color.fromRGBA([96, 82, 127, .6]),
- CssGrid: Common.Color.fromRGBA([0x4b, 0, 0x82, 1])
+export const PageHighlight = {
+ Content: Color.fromRGBA([111, 168, 220, .66]),
+ ContentLight: Color.fromRGBA([111, 168, 220, .5]),
+ ContentOutline: Color.fromRGBA([9, 83, 148]),
+ Padding: Color.fromRGBA([147, 196, 125, .55]),
+ PaddingLight: Color.fromRGBA([147, 196, 125, .4]),
+ Border: Color.fromRGBA([255, 229, 153, .66]),
+ BorderLight: Color.fromRGBA([255, 229, 153, .5]),
+ Margin: Color.fromRGBA([246, 178, 107, .66]),
+ MarginLight: Color.fromRGBA([246, 178, 107, .5]),
+ EventTarget: Color.fromRGBA([255, 196, 196, .66]),
+ Shape: Color.fromRGBA([96, 82, 177, 0.8]),
+ ShapeMargin: Color.fromRGBA([96, 82, 127, .6]),
+ CssGrid: Color.fromRGBA([0x4b, 0, 0x82, 1])
};
-Common.Color.Generator = class {
+export class Generator {
/**
* @param {!{min: number, max: number}|number=} hueSpace
* @param {!{min: number, max: number, count: (number|undefined)}|number=} satSpace
@@ -943,10 +972,39 @@ Common.Color.Generator = class {
* @return {number}
*/
_indexToValueInSpace(index, space) {
- if (typeof space === 'number')
+ if (typeof space === 'number') {
return space;
+ }
const count = space.count || space.max - space.min;
index %= count;
return space.min + Math.floor(index / (count - 1) * (space.max - space.min));
}
-};
+}
+
+/** @type {!Array<number>} */
+Color.hsva2rgba._tmpHSLA = [0, 0, 0, 0];
+
+Color.calculateContrastRatio._blendedFg = [0, 0, 0, 0];
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Color = Color;
+
+Common.Color.Regex = Regex;
+
+/**
+ * @enum {string}
+ */
+Common.Color.Format = Format;
+Common.Color.Nicknames = Nicknames;
+Common.Color.PageHighlight = PageHighlight;
+
+/**
+ * @constructor
+ */
+Common.Color.Generator = Generator;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Console.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Console.js
index 71350cb17c9..06510fdad75 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Console.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Console.js
@@ -1,24 +1,26 @@
// 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 ObjectWrapper from './Object.js';
+
/**
* @unrestricted
*/
-Common.Console = class extends Common.Object {
+export default class Console extends ObjectWrapper {
constructor() {
super();
- /** @type {!Array.<!Common.Console.Message>} */
+ /** @type {!Array.<!Message>} */
this._messages = [];
}
/**
* @param {string} text
- * @param {!Common.Console.MessageLevel} level
+ * @param {!MessageLevel} level
* @param {boolean=} show
*/
addMessage(text, level, show) {
- const message =
- new Common.Console.Message(text, level || Common.Console.MessageLevel.Info, Date.now(), show || false);
+ const message = new Message(text, level || MessageLevel.Info, Date.now(), show || false);
this._messages.push(message);
this.dispatchEventToListeners(Common.Console.Events.MessageAdded, message);
}
@@ -27,25 +29,25 @@ Common.Console = class extends Common.Object {
* @param {string} text
*/
log(text) {
- this.addMessage(text, Common.Console.MessageLevel.Info);
+ this.addMessage(text, MessageLevel.Info);
}
/**
* @param {string} text
*/
warn(text) {
- this.addMessage(text, Common.Console.MessageLevel.Warning);
+ this.addMessage(text, MessageLevel.Warning);
}
/**
* @param {string} text
*/
error(text) {
- this.addMessage(text, Common.Console.MessageLevel.Error, true);
+ this.addMessage(text, MessageLevel.Error, true);
}
/**
- * @return {!Array.<!Common.Console.Message>}
+ * @return {!Array.<!Message>}
*/
messages() {
return this._messages;
@@ -61,17 +63,17 @@ Common.Console = class extends Common.Object {
showPromise() {
return Common.Revealer.reveal(this);
}
-};
+}
/** @enum {symbol} */
-Common.Console.Events = {
+export const Events = {
MessageAdded: Symbol('messageAdded')
};
/**
* @enum {string}
*/
-Common.Console.MessageLevel = {
+export const MessageLevel = {
Info: 'info',
Warning: 'warning',
Error: 'error'
@@ -80,10 +82,10 @@ Common.Console.MessageLevel = {
/**
* @unrestricted
*/
-Common.Console.Message = class {
+export class Message {
/**
* @param {string} text
- * @param {!Common.Console.MessageLevel} level
+ * @param {!MessageLevel} level
* @param {number} timestamp
* @param {boolean} show
*/
@@ -93,6 +95,28 @@ Common.Console.Message = class {
this.timestamp = (typeof timestamp === 'number') ? timestamp : Date.now();
this.show = show;
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.console = new Console();
+
+/**
+ * @constructor
+ */
+Common.Console = Console;
-Common.console = new Common.Console();
+/** @enum {symbol} */
+Common.Console.Events = Events;
+
+/**
+ * @enum {string}
+ */
+Common.Console.MessageLevel = MessageLevel;
+
+/**
+ * @constructor
+ */
+Common.Console.Message = Message;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
index b5fdf2384a0..12574e8f4ba 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/ContentProvider.js
@@ -27,31 +27,45 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
/**
- * @interface
+ * @typedef {{
+ * content: string,
+ * isEncoded: boolean,
+ * }|{
+ * error: string,
+ * isEncoded: boolean,
+ * }}
*/
-Common.ContentProvider = function() {};
+Common.DeferredContent;
-Common.ContentProvider.prototype = {
+/**
+ * @interface
+ */
+export default class ContentProvider {
/**
* @return {string}
*/
- contentURL() {},
+ contentURL() {
+ }
/**
* @return {!Common.ResourceType}
*/
- contentType() {},
+ contentType() {
+ }
/**
* @return {!Promise<boolean>}
*/
- contentEncoded() {},
+ contentEncoded() {
+ }
/**
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
- requestContent() {},
+ requestContent() {
+ }
/**
* @param {string} query
@@ -60,12 +74,12 @@ Common.ContentProvider.prototype = {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
searchInContent(query, caseSensitive, isRegex) {}
-};
+}
/**
* @unrestricted
*/
-Common.ContentProvider.SearchMatch = class {
+export class SearchMatch {
/**
* @param {number} lineNumber
* @param {string} lineContent
@@ -74,7 +88,7 @@ Common.ContentProvider.SearchMatch = class {
this.lineNumber = lineNumber;
this.lineContent = lineContent;
}
-};
+}
/**
* @param {string} content
@@ -83,7 +97,7 @@ Common.ContentProvider.SearchMatch = class {
* @param {boolean} isRegex
* @return {!Array.<!Common.ContentProvider.SearchMatch>}
*/
-Common.ContentProvider.performSearchInContent = function(content, query, caseSensitive, isRegex) {
+export const performSearchInContent = function(content, query, caseSensitive, isRegex) {
const regex = createSearchRegex(query, caseSensitive, isRegex);
const text = new TextUtils.Text(content);
@@ -91,8 +105,9 @@ Common.ContentProvider.performSearchInContent = function(content, query, caseSen
for (let i = 0; i < text.lineCount(); ++i) {
const lineContent = text.lineAt(i);
regex.lastIndex = 0;
- if (regex.exec(lineContent))
+ if (regex.exec(lineContent)) {
result.push(new Common.ContentProvider.SearchMatch(i, lineContent));
+ }
}
return result;
};
@@ -104,11 +119,28 @@ Common.ContentProvider.performSearchInContent = function(content, query, caseSen
* @param {?string=} charset
* @return {?string}
*/
-Common.ContentProvider.contentAsDataURL = function(content, mimeType, contentEncoded, charset) {
+export const contentAsDataURL = function(content, mimeType, contentEncoded, charset) {
const maxDataUrlSize = 1024 * 1024;
- if (content === null || content.length > maxDataUrlSize)
+ if (content === null || content.length > maxDataUrlSize) {
return null;
+ }
return 'data:' + mimeType + (charset ? ';charset=' + charset : '') + (contentEncoded ? ';base64' : '') + ',' +
content;
};
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.ContentProvider = ContentProvider;
+
+/**
+ * @constructor
+ */
+Common.ContentProvider.SearchMatch = SearchMatch;
+Common.ContentProvider.performSearchInContent = performSearchInContent;
+Common.ContentProvider.contentAsDataURL = contentAsDataURL;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/EventTarget.js b/chromium/third_party/blink/renderer/devtools/front_end/common/EventTarget.js
new file mode 100644
index 00000000000..6ad716abf95
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/EventTarget.js
@@ -0,0 +1,78 @@
+// 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.
+
+/**
+ * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList
+ */
+export function removeEventListeners(eventList) {
+ for (const eventInfo of eventList) {
+ eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.listener, eventInfo.thisObject);
+ }
+ // Do not hold references on unused event descriptors.
+ eventList.splice(0);
+}
+
+/**
+ * @interface
+ */
+export default class EventTarget {
+ /**
+ * @param {symbol} eventType
+ * @param {function(!Common.Event)} listener
+ * @param {!Object=} thisObject
+ * @return {!Common.EventTarget.EventDescriptor}
+ */
+ addEventListener(eventType, listener, thisObject) {
+ }
+
+ /**
+ * @param {symbol} eventType
+ * @return {!Promise<*>}
+ */
+ once(eventType) {
+ }
+
+ /**
+ * @param {string|symbol} eventType
+ * @param {function(!Common.Event)} listener
+ * @param {!Object=} thisObject
+ */
+ removeEventListener(eventType, listener, thisObject) {
+ }
+
+ /**
+ * @param {symbol} eventType
+ * @return {boolean}
+ */
+ hasEventListeners(eventType) {
+ }
+
+ /**
+ * @param {symbol} eventType
+ * @param {*=} eventData
+ */
+ dispatchEventToListeners(eventType, eventData) {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @typedef {!{data: *}}
+ */
+Common.Event;
+
+/**
+ * @interface
+ */
+Common.EventTarget = EventTarget;
+
+EventTarget.removeEventListeners = removeEventListeners;
+
+/**
+ * @typedef {!{eventTarget: !Common.EventTarget, eventType: (string|symbol), thisObject: (!Object|undefined), listener: function(!Common.Event)}}
+ */
+Common.EventTarget.EventDescriptor;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js b/chromium/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js
new file mode 100644
index 00000000000..9e3eda8326d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/JavaScriptMetaData.js
@@ -0,0 +1,40 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class JavaScriptMetadata {
+ /**
+ * @param {string} name
+ * @return {?Array<!Array<string>>}
+ */
+ signaturesForNativeFunction(name) {
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} receiverClassName
+ * @return {?Array<!Array<string>>}
+ */
+ signaturesForInstanceMethod(name, receiverClassName) {
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} receiverConstructorName
+ * @return {?Array<!Array<string>>}
+ */
+ signaturesForStaticMethod(name, receiverConstructorName) {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.JavaScriptMetadata = JavaScriptMetadata;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Linkifier.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Linkifier.js
new file mode 100644
index 00000000000..d134a3b5755
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Linkifier.js
@@ -0,0 +1,43 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class Linkifier {
+ /**
+ * @param {!Object} object
+ * @param {!Common.Linkifier.Options=} options
+ * @return {!Node}
+ */
+ linkify(object, options) {
+ }
+}
+
+/**
+ * @param {?Object} object
+ * @param {!Common.Linkifier.Options=} options
+ * @return {!Promise<!Node>}
+ */
+export function linkify(object, options) {
+ if (!object) {
+ return Promise.reject(new Error('Can\'t linkify ' + object));
+ }
+ return self.runtime.extension(Common.Linkifier, object)
+ .instance()
+ .then(linkifier => linkifier.linkify(object, options));
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Linkifier = Linkifier;
+Common.Linkifier.linkify = linkify;
+
+/** @typedef {{tooltip: (string|undefined), preventKeyboardFocus: (boolean|undefined)}} */
+Common.Linkifier.Options;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js b/chromium/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js
deleted file mode 100644
index ce14692c0e4..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/ModuleExtensionInterfaces.js
+++ /dev/null
@@ -1,152 +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.
-
-/**
- * @interface
- */
-Common.Revealer = function() {};
-
-/**
- * @param {?Object} revealable
- * @param {boolean=} omitFocus
- * @return {!Promise.<undefined>}
- */
-Common.Revealer.reveal = function(revealable, omitFocus) {
- if (!revealable)
- return Promise.reject(new Error('Can\'t reveal ' + revealable));
- return self.runtime.allInstances(Common.Revealer, revealable).then(reveal);
-
- /**
- * @param {!Array.<!Common.Revealer>} revealers
- * @return {!Promise.<undefined>}
- */
- function reveal(revealers) {
- const promises = [];
- for (let i = 0; i < revealers.length; ++i)
- promises.push(revealers[i].reveal(/** @type {!Object} */ (revealable), omitFocus));
- return Promise.race(promises);
- }
-};
-
-/**
- * @param {?Object} revealable
- * @return {?string}
- */
-Common.Revealer.revealDestination = function(revealable) {
- const extension = self.runtime.extension(Common.Revealer, revealable);
- if (!extension)
- return null;
- return extension.descriptor()['destination'];
-};
-
-Common.Revealer.prototype = {
- /**
- * @param {!Object} object
- * @param {boolean=} omitFocus
- * @return {!Promise}
- */
- reveal(object, omitFocus) {}
-};
-
-/**
- * @interface
- */
-Common.App = function() {};
-
-Common.App.prototype = {
- /**
- * @param {!Document} document
- */
- presentUI(document) {}
-};
-
-/**
- * @interface
- */
-Common.AppProvider = function() {};
-
-Common.AppProvider.prototype = {
- /**
- * @return {!Common.App}
- */
- createApp() {}
-};
-
-/**
- * @interface
- */
-Common.QueryParamHandler = function() {};
-
-Common.QueryParamHandler.prototype = {
- /**
- * @param {string} value
- */
- handleQueryParam(value) {}
-};
-
-/**
- * @interface
- */
-Common.Runnable = function() {};
-
-Common.Runnable.prototype = {
- run() {}
-};
-
-/**
- * @interface
- */
-Common.Linkifier = function() {};
-
-Common.Linkifier.prototype = {
- /**
- * @param {!Object} object
- * @param {!Common.Linkifier.Options=} options
- * @return {!Node}
- */
- linkify(object, options) {}
-};
-
-/**
- * @param {?Object} object
- * @param {!Common.Linkifier.Options=} options
- * @return {!Promise<!Node>}
- */
-Common.Linkifier.linkify = function(object, options) {
- if (!object)
- return Promise.reject(new Error('Can\'t linkify ' + object));
- return self.runtime.extension(Common.Linkifier, object)
- .instance()
- .then(linkifier => linkifier.linkify(object, options));
-};
-
-/** @typedef {{tooltip: (string|undefined), preventKeyboardFocus: (boolean|undefined)}} */
-Common.Linkifier.Options;
-
-/**
- * @interface
- */
-Common.JavaScriptMetadata = function() {};
-Common.JavaScriptMetadata.prototype = {
-
- /**
- * @param {string} name
- * @return {?Array<!Array<string>>}
- */
- signaturesForNativeFunction(name) {},
-
- /**
- * @param {string} name
- * @param {string} receiverClassName
- * @return {?Array<!Array<string>>}
- */
- signaturesForInstanceMethod(name, receiverClassName) {},
-
- /**
- * @param {string} name
- * @param {string} receiverConstructorName
- * @return {?Array<!Array<string>>}
- */
- signaturesForStaticMethod(name, receiverConstructorName) {}
-};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Object.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Object.js
index 2156cf68fe2..44c4c6b0407 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Object.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Object.js
@@ -27,28 +27,31 @@
* @implements {Common.EventTarget}
* @unrestricted
*/
-Common.Object = class {
+export default class ObjectWrapper {
constructor() {
- /** @type {(!Map<symbol, !Array<!Common.Object._listenerCallbackTuple>>|undefined)} */
+ /** @type {(!Map<string|symbol, !Array<!Common.Object._listenerCallbackTuple>>|undefined)} */
this._listeners;
}
/**
* @override
- * @param {symbol} eventType
+ * @param {string|symbol} eventType
* @param {function(!Common.Event)} listener
* @param {!Object=} thisObject
* @return {!Common.EventTarget.EventDescriptor}
*/
addEventListener(eventType, listener, thisObject) {
- if (!listener)
+ if (!listener) {
console.assert(false);
+ }
- if (!this._listeners)
+ if (!this._listeners) {
this._listeners = new Map();
+ }
- if (!this._listeners.has(eventType))
+ if (!this._listeners.has(eventType)) {
this._listeners.set(eventType, []);
+ }
this._listeners.get(eventType).push({thisObject: thisObject, listener: listener});
return {eventTarget: this, eventType: eventType, thisObject: thisObject, listener: listener};
}
@@ -69,15 +72,16 @@ Common.Object = class {
/**
* @override
- * @param {symbol} eventType
+ * @param {string|symbol} eventType
* @param {function(!Common.Event)} listener
* @param {!Object=} thisObject
*/
removeEventListener(eventType, listener, thisObject) {
console.assert(listener);
- if (!this._listeners || !this._listeners.has(eventType))
+ if (!this._listeners || !this._listeners.has(eventType)) {
return;
+ }
const listeners = this._listeners.get(eventType);
for (let i = 0; i < listeners.length; ++i) {
if (listeners[i].listener === listener && listeners[i].thisObject === thisObject) {
@@ -86,13 +90,14 @@ Common.Object = class {
}
}
- if (!listeners.length)
+ if (!listeners.length) {
this._listeners.delete(eventType);
+ }
}
/**
* @override
- * @param {symbol} eventType
+ * @param {string|symbol} eventType
* @return {boolean}
*/
hasEventListeners(eventType) {
@@ -101,83 +106,34 @@ Common.Object = class {
/**
* @override
- * @param {symbol} eventType
+ * @param {string|symbol} eventType
* @param {*=} eventData
*/
dispatchEventToListeners(eventType, eventData) {
- if (!this._listeners || !this._listeners.has(eventType))
+ if (!this._listeners || !this._listeners.has(eventType)) {
return;
+ }
const event = /** @type {!Common.Event} */ ({data: eventData});
const listeners = this._listeners.get(eventType).slice(0);
for (let i = 0; i < listeners.length; ++i) {
- if (!listeners[i].disposed)
+ if (!listeners[i].disposed) {
listeners[i].listener.call(listeners[i].thisObject, event);
+ }
}
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
/**
- * @typedef {!{data: *}}
+ * @constructor
*/
-Common.Event;
+Common.Object = ObjectWrapper;
/**
* @typedef {!{thisObject: (!Object|undefined), listener: function(!Common.Event), disposed: (boolean|undefined)}}
*/
Common.Object._listenerCallbackTuple;
-
-/**
- * @interface
- */
-Common.EventTarget = function() {};
-
-/**
- * @typedef {!{eventTarget: !Common.EventTarget, eventType: symbol, thisObject: (!Object|undefined), listener: function(!Common.Event)}}
- */
-Common.EventTarget.EventDescriptor;
-
-/**
- * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList
- */
-Common.EventTarget.removeEventListeners = function(eventList) {
- for (const eventInfo of eventList)
- eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.listener, eventInfo.thisObject);
- // Do not hold references on unused event descriptors.
- eventList.splice(0);
-};
-
-Common.EventTarget.prototype = {
- /**
- * @param {symbol} eventType
- * @param {function(!Common.Event)} listener
- * @param {!Object=} thisObject
- * @return {!Common.EventTarget.EventDescriptor}
- */
- addEventListener(eventType, listener, thisObject) {},
-
- /**
- * @param {symbol} eventType
- * @return {!Promise<*>}
- */
- once(eventType) {},
-
- /**
- * @param {symbol} eventType
- * @param {function(!Common.Event)} listener
- * @param {!Object=} thisObject
- */
- removeEventListener(eventType, listener, thisObject) {},
-
- /**
- * @param {symbol} eventType
- * @return {boolean}
- */
- hasEventListeners(eventType) {},
-
- /**
- * @param {symbol} eventType
- * @param {*=} eventData
- */
- dispatchEventToListeners(eventType, eventData) {},
-};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js b/chromium/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
index eea78c50da2..16718fae245 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/ParsedURL.js
@@ -29,7 +29,7 @@
/**
* @unrestricted
*/
-Common.ParsedURL = class {
+export default class ParsedURL {
/**
* @param {string} url
*/
@@ -95,10 +95,11 @@ Common.ParsedURL = class {
static platformPathToURL(fileSystemPath) {
fileSystemPath = fileSystemPath.replace(/\\/g, '/');
if (!fileSystemPath.startsWith('file://')) {
- if (fileSystemPath.startsWith('/'))
+ if (fileSystemPath.startsWith('/')) {
fileSystemPath = 'file://' + fileSystemPath;
- else
+ } else {
fileSystemPath = 'file:///' + fileSystemPath;
+ }
}
return fileSystemPath;
}
@@ -110,8 +111,9 @@ Common.ParsedURL = class {
*/
static urlToPlatformPath(fileURL, isWindows) {
console.assert(fileURL.startsWith('file://'), 'This must be a file URL.');
- if (isWindows)
+ if (isWindows) {
return fileURL.substr('file:///'.length).replace(/\//g, '\\');
+ }
return fileURL.substr('file://'.length);
}
@@ -121,8 +123,9 @@ Common.ParsedURL = class {
*/
static urlWithoutHash(url) {
const hashIndex = url.indexOf('#');
- if (hashIndex !== -1)
+ if (hashIndex !== -1) {
return url.substr(0, hashIndex);
+ }
return url;
}
@@ -130,8 +133,9 @@ Common.ParsedURL = class {
* @return {!RegExp}
*/
static _urlRegex() {
- if (Common.ParsedURL._urlRegexInstance)
+ if (Common.ParsedURL._urlRegexInstance) {
return Common.ParsedURL._urlRegexInstance;
+ }
// RegExp groups:
// 1 - scheme, hostname, ?port
// 2 - scheme (using the RFC3986 grammar)
@@ -180,17 +184,20 @@ Common.ParsedURL = class {
static extractExtension(url) {
url = Common.ParsedURL.urlWithoutHash(url);
const indexOfQuestionMark = url.indexOf('?');
- if (indexOfQuestionMark !== -1)
+ if (indexOfQuestionMark !== -1) {
url = url.substr(0, indexOfQuestionMark);
+ }
const lastIndexOfSlash = url.lastIndexOf('/');
- if (lastIndexOfSlash !== -1)
+ if (lastIndexOfSlash !== -1) {
url = url.substr(lastIndexOfSlash + 1);
+ }
const lastIndexOfDot = url.lastIndexOf('.');
if (lastIndexOfDot !== -1) {
url = url.substr(lastIndexOfDot + 1);
const lastIndexOfPercent = url.indexOf('%');
- if (lastIndexOfPercent !== -1)
+ if (lastIndexOfPercent !== -1) {
return url.substr(0, lastIndexOfPercent);
+ }
return url;
}
return '';
@@ -216,20 +223,24 @@ Common.ParsedURL = class {
// Return special URLs as-is.
const trimmedHref = href.trim();
if (trimmedHref.startsWith('data:') || trimmedHref.startsWith('blob:') || trimmedHref.startsWith('javascript:') ||
- trimmedHref.startsWith('mailto:'))
+ trimmedHref.startsWith('mailto:')) {
return href;
+ }
// Return absolute URLs as-is.
const parsedHref = trimmedHref.asParsedURL();
- if (parsedHref && parsedHref.scheme)
+ if (parsedHref && parsedHref.scheme) {
return trimmedHref;
+ }
const parsedURL = baseURL.asParsedURL();
- if (!parsedURL)
+ if (!parsedURL) {
return null;
+ }
- if (parsedURL.isDataURL())
+ if (parsedURL.isDataURL()) {
return href;
+ }
if (href.length > 1 && href.charAt(0) === '/' && href.charAt(1) === '/') {
// href starts with "//" which is a full URL with the protocol dropped (use the baseURL protocol).
@@ -241,20 +252,24 @@ Common.ParsedURL = class {
const queryText = parsedURL.queryParams ? '?' + parsedURL.queryParams : '';
// Empty href resolves to a URL without fragment.
- if (!href.length)
+ if (!href.length) {
return securityOrigin + pathText + queryText;
+ }
- if (href.charAt(0) === '#')
+ if (href.charAt(0) === '#') {
return securityOrigin + pathText + queryText + href;
+ }
- if (href.charAt(0) === '?')
+ if (href.charAt(0) === '?') {
return securityOrigin + pathText + href;
+ }
let hrefPath = href.match(/^[^#?]*/)[0];
const hrefSuffix = href.substring(hrefPath.length);
- if (hrefPath.charAt(0) !== '/')
+ if (hrefPath.charAt(0) !== '/') {
hrefPath = parsedURL.folderPathComponents + '/' + hrefPath;
- return securityOrigin + Runtime.normalizePath(hrefPath) + hrefSuffix;
+ }
+ return securityOrigin + Root.Runtime.normalizePath(hrefPath) + hrefSuffix;
}
/**
@@ -303,21 +318,27 @@ Common.ParsedURL = class {
}
get displayName() {
- if (this._displayName)
+ if (this._displayName) {
return this._displayName;
+ }
- if (this.isDataURL())
+ if (this.isDataURL()) {
return this.dataURLDisplayName();
- if (this.isBlobURL())
+ }
+ if (this.isBlobURL()) {
return this.url;
- if (this.isAboutBlank())
+ }
+ if (this.isAboutBlank()) {
return this.url;
+ }
this._displayName = this.lastPathComponent;
- if (!this._displayName)
+ if (!this._displayName) {
this._displayName = (this.host || '') + '/';
- if (this._displayName === '/')
+ }
+ if (this._displayName === '/') {
this._displayName = this.url;
+ }
return this._displayName;
}
@@ -325,11 +346,13 @@ Common.ParsedURL = class {
* @return {string}
*/
dataURLDisplayName() {
- if (this._dataURLDisplayName)
+ if (this._dataURLDisplayName) {
return this._dataURLDisplayName;
- if (!this.isDataURL())
+ }
+ if (!this.isDataURL()) {
return '';
- this._dataURLDisplayName = this.url.trimEnd(20);
+ }
+ this._dataURLDisplayName = this.url.trimEndWithMaxLength(20);
return this._dataURLDisplayName;
}
@@ -365,8 +388,9 @@ Common.ParsedURL = class {
* @return {string}
*/
domain() {
- if (this.isDataURL())
+ if (this.isDataURL()) {
return 'data:';
+ }
return this.host + (this.port ? ':' + this.port : '');
}
@@ -374,8 +398,9 @@ Common.ParsedURL = class {
* @return {string}
*/
securityOrigin() {
- if (this.isDataURL())
+ if (this.isDataURL()) {
return 'data:';
+ }
const scheme = this.isBlobURL() ? this._blobInnerScheme : this.scheme;
return scheme + '://' + this.domain();
}
@@ -384,19 +409,29 @@ Common.ParsedURL = class {
* @return {string}
*/
urlWithoutScheme() {
- if (this.scheme && this.url.startsWith(this.scheme + '://'))
+ if (this.scheme && this.url.startsWith(this.scheme + '://')) {
return this.url.substring(this.scheme.length + 3);
+ }
return this.url;
}
-};
-
+}
/**
* @return {?Common.ParsedURL}
*/
String.prototype.asParsedURL = function() {
const parsedURL = new Common.ParsedURL(this.toString());
- if (parsedURL.isValid)
+ if (parsedURL.isValid) {
return parsedURL;
+ }
return null;
};
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.ParsedURL = ParsedURL;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Progress.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Progress.js
index 669ecf08dd1..e60d3ae8d5b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Progress.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Progress.js
@@ -27,47 +27,51 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
/**
* @interface
*/
-Common.Progress = function() {};
-
-Common.Progress.prototype = {
+export default class Progress {
/**
* @param {number} totalWork
*/
- setTotalWork(totalWork) {},
+ setTotalWork(totalWork) {
+ }
/**
* @param {string} title
*/
- setTitle(title) {},
+ setTitle(title) {
+ }
/**
* @param {number} worked
* @param {string=} title
*/
- setWorked(worked, title) {},
+ setWorked(worked, title) {
+ }
/**
* @param {number=} worked
*/
- worked(worked) {},
+ worked(worked) {
+ }
- done() {},
+ done() {
+ }
/**
* @return {boolean}
*/
isCanceled() {
return false;
- },
-};
+ }
+}
/**
* @unrestricted
*/
-Common.CompositeProgress = class {
+export class CompositeProgress {
/**
* @param {!Common.Progress} parent
*/
@@ -80,8 +84,9 @@ Common.CompositeProgress = class {
}
_childDone() {
- if (++this._childrenDone !== this._children.length)
+ if (++this._childrenDone !== this._children.length) {
return;
+ }
this._parent.done();
}
@@ -101,19 +106,20 @@ Common.CompositeProgress = class {
for (let i = 0; i < this._children.length; ++i) {
const child = this._children[i];
- if (child._totalWork)
+ if (child._totalWork) {
done += child._weight * child._worked / child._totalWork;
+ }
totalWeights += child._weight;
}
this._parent.setWorked(done / totalWeights);
}
-};
+}
/**
* @implements {Common.Progress}
* @unrestricted
*/
-Common.SubProgress = class {
+export class SubProgress {
/**
* @param {!Common.CompositeProgress} composite
* @param {number=} weight
@@ -164,8 +170,9 @@ Common.SubProgress = class {
*/
setWorked(worked, title) {
this._worked = worked;
- if (typeof title !== 'undefined')
+ if (typeof title !== 'undefined') {
this.setTitle(title);
+ }
this._composite._update();
}
@@ -176,13 +183,13 @@ Common.SubProgress = class {
worked(worked) {
this.setWorked(this._worked + (worked || 1));
}
-};
+}
/**
* @implements {Common.Progress}
* @unrestricted
*/
-Common.ProgressProxy = class {
+export class ProgressProxy {
/**
* @param {?Common.Progress} delegate
* @param {function()=} doneCallback
@@ -205,18 +212,21 @@ Common.ProgressProxy = class {
* @param {string} title
*/
setTitle(title) {
- if (this._delegate)
+ if (this._delegate) {
this._delegate.setTitle(title);
+ }
}
/**
* @override
*/
done() {
- if (this._delegate)
+ if (this._delegate) {
this._delegate.done();
- if (this._doneCallback)
+ }
+ if (this._doneCallback) {
this._doneCallback();
+ }
}
/**
@@ -224,8 +234,9 @@ Common.ProgressProxy = class {
* @param {number} totalWork
*/
setTotalWork(totalWork) {
- if (this._delegate)
+ if (this._delegate) {
this._delegate.setTotalWork(totalWork);
+ }
}
/**
@@ -234,8 +245,9 @@ Common.ProgressProxy = class {
* @param {string=} title
*/
setWorked(worked, title) {
- if (this._delegate)
+ if (this._delegate) {
this._delegate.setWorked(worked, title);
+ }
}
/**
@@ -243,7 +255,32 @@ Common.ProgressProxy = class {
* @param {number=} worked
*/
worked(worked) {
- if (this._delegate)
+ if (this._delegate) {
this._delegate.worked(worked);
+ }
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Progress = Progress;
+
+/**
+ * @constructor
+ */
+Common.CompositeProgress = CompositeProgress;
+
+/**
+ * @constructor
+ */
+Common.SubProgress = SubProgress;
+
+/**
+ * @constructor
+ */
+Common.ProgressProxy = ProgressProxy;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js b/chromium/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js
new file mode 100644
index 00000000000..60a1036ec60
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/QueryParamHandler.js
@@ -0,0 +1,23 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class QueryParamHandler {
+ /**
+ * @param {string} value
+ */
+ handleQueryParam(value) {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.QueryParamHandler = QueryParamHandler;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js b/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
index 5a69005ee46..8a29f3d32df 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
@@ -30,11 +30,11 @@
/**
* @unrestricted
*/
-Common.ResourceType = class {
+export default class ResourceType {
/**
* @param {string} name
* @param {string} title
- * @param {!Common.ResourceCategory} category
+ * @param {!ResourceCategory} category
* @param {boolean} isTextType
*/
constructor(name, title, category, isTextType) {
@@ -46,47 +46,56 @@ Common.ResourceType = class {
/**
* @param {string} mimeType
- * @return {!Common.ResourceType}
+ * @return {!ResourceType}
*/
static fromMimeType(mimeType) {
- if (mimeType.startsWith('text/html'))
- return Common.resourceTypes.Document;
- if (mimeType.startsWith('text/css'))
- return Common.resourceTypes.Stylesheet;
- if (mimeType.startsWith('image/'))
- return Common.resourceTypes.Image;
- if (mimeType.startsWith('text/'))
- return Common.resourceTypes.Script;
-
- if (mimeType.includes('font'))
- return Common.resourceTypes.Font;
- if (mimeType.includes('script'))
- return Common.resourceTypes.Script;
- if (mimeType.includes('octet'))
- return Common.resourceTypes.Other;
- if (mimeType.includes('application'))
- return Common.resourceTypes.Script;
-
- return Common.resourceTypes.Other;
+ if (mimeType.startsWith('text/html')) {
+ return resourceTypes.Document;
+ }
+ if (mimeType.startsWith('text/css')) {
+ return resourceTypes.Stylesheet;
+ }
+ if (mimeType.startsWith('image/')) {
+ return resourceTypes.Image;
+ }
+ if (mimeType.startsWith('text/')) {
+ return resourceTypes.Script;
+ }
+
+ if (mimeType.includes('font')) {
+ return resourceTypes.Font;
+ }
+ if (mimeType.includes('script')) {
+ return resourceTypes.Script;
+ }
+ if (mimeType.includes('octet')) {
+ return resourceTypes.Other;
+ }
+ if (mimeType.includes('application')) {
+ return resourceTypes.Script;
+ }
+
+ return resourceTypes.Other;
}
/**
* @param {string} url
- * @return {?Common.ResourceType}
+ * @return {?ResourceType}
*/
static fromURL(url) {
- return Common.ResourceType._resourceTypeByExtension.get(Common.ParsedURL.extractExtension(url)) || null;
+ return ResourceType._resourceTypeByExtension.get(Common.ParsedURL.extractExtension(url)) || null;
}
/**
* @param {string} name
- * @return {?Common.ResourceType}
+ * @return {?ResourceType}
*/
static fromName(name) {
- for (const resourceTypeId in Common.resourceTypes) {
- const resourceType = Common.resourceTypes[resourceTypeId];
- if (resourceType.name() === name)
+ for (const resourceTypeId in resourceTypes) {
+ const resourceType = resourceTypes[resourceTypeId];
+ if (resourceType.name() === name) {
return resourceType;
+ }
}
return null;
}
@@ -97,11 +106,12 @@ Common.ResourceType = class {
*/
static mimeFromURL(url) {
const name = Common.ParsedURL.extractName(url);
- if (Common.ResourceType._mimeTypeByName.has(name))
- return Common.ResourceType._mimeTypeByName.get(name);
+ if (ResourceType._mimeTypeByName.has(name)) {
+ return ResourceType._mimeTypeByName.get(name);
+ }
const ext = Common.ParsedURL.extractExtension(url).toLowerCase();
- return Common.ResourceType._mimeTypeByExtension.get(ext);
+ return ResourceType._mimeTypeByExtension.get(ext);
}
/**
@@ -109,7 +119,7 @@ Common.ResourceType = class {
* @return {string|undefined}
*/
static mimeFromExtension(ext) {
- return Common.ResourceType._mimeTypeByExtension.get(ext);
+ return ResourceType._mimeTypeByExtension.get(ext);
}
/**
@@ -127,7 +137,7 @@ Common.ResourceType = class {
}
/**
- * @return {!Common.ResourceCategory}
+ * @return {!ResourceCategory}
*/
category() {
return this._category;
@@ -194,20 +204,23 @@ Common.ResourceType = class {
* @return {string}
*/
canonicalMimeType() {
- if (this.isDocument())
+ if (this.isDocument()) {
return 'text/html';
- if (this.isScript())
+ }
+ if (this.isScript()) {
return 'text/javascript';
- if (this.isStyleSheet())
+ }
+ if (this.isStyleSheet()) {
return 'text/css';
+ }
return '';
}
-};
+}
/**
* @unrestricted
*/
-Common.ResourceCategory = class {
+export class ResourceCategory {
/**
* @param {string} title
* @param {string} shortTitle
@@ -216,67 +229,68 @@ Common.ResourceCategory = class {
this.title = title;
this.shortTitle = shortTitle;
}
-};
+}
-Common.resourceCategories = {
- XHR: new Common.ResourceCategory('XHR and Fetch', 'XHR'),
- Script: new Common.ResourceCategory('Scripts', 'JS'),
- Stylesheet: new Common.ResourceCategory('Stylesheets', 'CSS'),
- Image: new Common.ResourceCategory('Images', 'Img'),
- Media: new Common.ResourceCategory('Media', 'Media'),
- Font: new Common.ResourceCategory('Fonts', 'Font'),
- Document: new Common.ResourceCategory('Documents', 'Doc'),
- WebSocket: new Common.ResourceCategory('WebSockets', 'WS'),
- Manifest: new Common.ResourceCategory('Manifest', 'Manifest'),
- Other: new Common.ResourceCategory('Other', 'Other')
+/**
+ * @enum {!ResourceCategory}
+ */
+export const resourceCategories = {
+ XHR: new ResourceCategory(ls`XHR and Fetch`, ls`XHR`),
+ Script: new ResourceCategory(ls`Scripts`, ls`JS`),
+ Stylesheet: new ResourceCategory(ls`Stylesheets`, ls`CSS`),
+ Image: new ResourceCategory(ls`Images`, ls`Img`),
+ Media: new ResourceCategory(ls`Media`, ls`Media`),
+ Font: new ResourceCategory(ls`Fonts`, ls`Font`),
+ Document: new ResourceCategory(ls`Documents`, ls`Doc`),
+ WebSocket: new ResourceCategory(ls`WebSockets`, ls`WS`),
+ Manifest: new ResourceCategory(ls`Manifest`, ls`Manifest`),
+ Other: new ResourceCategory(ls`Other`, ls`Other`)
};
/**
* Keep these in sync with WebCore::InspectorPageAgent::resourceTypeJson
- * @enum {!Common.ResourceType}
+ * @enum {!ResourceType}
*/
-Common.resourceTypes = {
- XHR: new Common.ResourceType('xhr', 'XHR', Common.resourceCategories.XHR, true),
- Fetch: new Common.ResourceType('fetch', 'Fetch', Common.resourceCategories.XHR, true),
- EventSource: new Common.ResourceType('eventsource', 'EventSource', Common.resourceCategories.XHR, true),
- Script: new Common.ResourceType('script', 'Script', Common.resourceCategories.Script, true),
- Stylesheet: new Common.ResourceType('stylesheet', 'Stylesheet', Common.resourceCategories.Stylesheet, true),
- Image: new Common.ResourceType('image', 'Image', Common.resourceCategories.Image, false),
- Media: new Common.ResourceType('media', 'Media', Common.resourceCategories.Media, false),
- Font: new Common.ResourceType('font', 'Font', Common.resourceCategories.Font, false),
- Document: new Common.ResourceType('document', 'Document', Common.resourceCategories.Document, true),
- TextTrack: new Common.ResourceType('texttrack', 'TextTrack', Common.resourceCategories.Other, true),
- WebSocket: new Common.ResourceType('websocket', 'WebSocket', Common.resourceCategories.WebSocket, false),
- Other: new Common.ResourceType('other', 'Other', Common.resourceCategories.Other, false),
- SourceMapScript: new Common.ResourceType('sm-script', 'Script', Common.resourceCategories.Script, true),
- SourceMapStyleSheet:
- new Common.ResourceType('sm-stylesheet', 'Stylesheet', Common.resourceCategories.Stylesheet, true),
- Manifest: new Common.ResourceType('manifest', 'Manifest', Common.resourceCategories.Manifest, true),
- SignedExchange: new Common.ResourceType('signed-exchange', 'SignedExchange', Common.resourceCategories.Other, false),
+export const resourceTypes = {
+ XHR: new ResourceType('xhr', ls`XHR`, resourceCategories.XHR, true),
+ Fetch: new ResourceType('fetch', ls`Fetch`, resourceCategories.XHR, true),
+ EventSource: new ResourceType('eventsource', ls`EventSource`, resourceCategories.XHR, true),
+ Script: new ResourceType('script', ls`Script`, resourceCategories.Script, true),
+ Stylesheet: new ResourceType('stylesheet', ls`Stylesheet`, resourceCategories.Stylesheet, true),
+ Image: new ResourceType('image', ls`Image`, resourceCategories.Image, false),
+ Media: new ResourceType('media', ls`Media`, resourceCategories.Media, false),
+ Font: new ResourceType('font', ls`Font`, resourceCategories.Font, false),
+ Document: new ResourceType('document', ls`Document`, resourceCategories.Document, true),
+ TextTrack: new ResourceType('texttrack', ls`TextTrack`, resourceCategories.Other, true),
+ WebSocket: new ResourceType('websocket', ls`WebSocket`, resourceCategories.WebSocket, false),
+ Other: new ResourceType('other', ls`Other`, resourceCategories.Other, false),
+ SourceMapScript: new ResourceType('sm-script', ls`Script`, resourceCategories.Script, true),
+ SourceMapStyleSheet: new ResourceType('sm-stylesheet', ls`Stylesheet`, resourceCategories.Stylesheet, true),
+ Manifest: new ResourceType('manifest', ls`Manifest`, resourceCategories.Manifest, true),
+ SignedExchange: new ResourceType('signed-exchange', ls`SignedExchange`, resourceCategories.Other, false)
};
-Common.ResourceType._mimeTypeByName = new Map([
+export const _mimeTypeByName = new Map([
// CoffeeScript
['Cakefile', 'text/x-coffeescript']
]);
-Common.ResourceType._resourceTypeByExtension = new Map([
- ['js', Common.resourceTypes.Script], ['mjs', Common.resourceTypes.Script],
+export const _resourceTypeByExtension = new Map([
+ ['js', resourceTypes.Script], ['mjs', resourceTypes.Script],
- ['css', Common.resourceTypes.Stylesheet], ['xsl', Common.resourceTypes.Stylesheet],
+ ['css', resourceTypes.Stylesheet], ['xsl', resourceTypes.Stylesheet],
- ['jpeg', Common.resourceTypes.Image], ['jpg', Common.resourceTypes.Image], ['svg', Common.resourceTypes.Image],
- ['gif', Common.resourceTypes.Image], ['png', Common.resourceTypes.Image], ['ico', Common.resourceTypes.Image],
- ['tiff', Common.resourceTypes.Image], ['tif', Common.resourceTypes.Image], ['bmp', Common.resourceTypes.Image],
+ ['jpeg', resourceTypes.Image], ['jpg', resourceTypes.Image], ['svg', resourceTypes.Image],
+ ['gif', resourceTypes.Image], ['png', resourceTypes.Image], ['ico', resourceTypes.Image],
+ ['tiff', resourceTypes.Image], ['tif', resourceTypes.Image], ['bmp', resourceTypes.Image],
- ['webp', Common.resourceTypes.Media],
+ ['webp', resourceTypes.Media],
- ['ttf', Common.resourceTypes.Font], ['otf', Common.resourceTypes.Font], ['ttc', Common.resourceTypes.Font],
- ['woff', Common.resourceTypes.Font]
+ ['ttf', resourceTypes.Font], ['otf', resourceTypes.Font], ['ttc', resourceTypes.Font], ['woff', resourceTypes.Font]
]);
-Common.ResourceType._mimeTypeByExtension = new Map([
+export const _mimeTypeByExtension = new Map([
// Web extensions
['js', 'text/javascript'], ['mjs', 'text/javascript'], ['css', 'text/css'], ['html', 'text/html'],
['htm', 'text/html'], ['xml', 'application/xml'], ['xsl', 'application/xml'],
@@ -346,3 +360,31 @@ Common.ResourceType._mimeTypeByExtension = new Map([
// Font
['ttf', 'font/opentype'], ['otf', 'font/opentype'], ['ttc', 'font/opentype'], ['woff', 'application/font-woff']
]);
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @enum {!ResourceType}
+ */
+Common.resourceTypes = resourceTypes;
+
+/**
+ * @enum {!ResourceCategory}
+ */
+Common.resourceCategories = resourceCategories;
+
+/**
+ * @constructor
+ */
+Common.ResourceCategory = ResourceCategory;
+
+/**
+ * @constructor
+ */
+Common.ResourceType = ResourceType;
+
+Common.ResourceType._mimeTypeByName = _mimeTypeByName;
+Common.ResourceType._resourceTypeByExtension = _resourceTypeByExtension;
+Common.ResourceType._mimeTypeByExtension = _mimeTypeByExtension;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Revealer.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Revealer.js
new file mode 100644
index 00000000000..af1b783e1fa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Revealer.js
@@ -0,0 +1,63 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class Revealer {
+ /**
+ * @param {!Object} object
+ * @param {boolean=} omitFocus
+ * @return {!Promise}
+ */
+ reveal(object, omitFocus) {
+ }
+}
+
+/**
+ * @param {?Object} revealable
+ * @param {boolean=} omitFocus
+ * @return {!Promise.<undefined>}
+ */
+export const reveal = function(revealable, omitFocus) {
+ if (!revealable) {
+ return Promise.reject(new Error('Can\'t reveal ' + revealable));
+ }
+ return self.runtime.allInstances(Common.Revealer, revealable).then(reveal);
+
+ /**
+ * @param {!Array.<!Common.Revealer>} revealers
+ * @return {!Promise.<undefined>}
+ */
+ function reveal(revealers) {
+ const promises = [];
+ for (let i = 0; i < revealers.length; ++i) {
+ promises.push(revealers[i].reveal(/** @type {!Object} */ (revealable), omitFocus));
+ }
+ return Promise.race(promises);
+ }
+};
+
+/**
+ * @param {?Object} revealable
+ * @return {?string}
+ */
+export const revealDestination = function(revealable) {
+ const extension = self.runtime.extension(Common.Revealer, revealable);
+ if (!extension) {
+ return null;
+ }
+ return extension.descriptor()['destination'];
+};
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Revealer = Revealer;
+Common.Revealer.reveal = reveal;
+Common.Revealer.revealDestination = revealDestination;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Runnable.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Runnable.js
new file mode 100644
index 00000000000..5edda691c21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Runnable.js
@@ -0,0 +1,23 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class Runnable {
+ /**
+ * @return {!Promise}
+ */
+ run() {
+ }
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.Runnable = Runnable;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js b/chromium/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
index ddb66daf1c2..97447fe0a94 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/SegmentedRange.js
@@ -4,15 +4,16 @@
/**
* @unrestricted
*/
-Common.Segment = class {
+export class Segment {
/**
* @param {number} begin
* @param {number} end
* @param {*} data
*/
constructor(begin, end, data) {
- if (begin > end)
- console.assert(false, 'Invalid segment');
+ if (begin > end) {
+ throw new Error('Invalid segment');
+ }
this.begin = begin;
this.end = end;
this.data = data;
@@ -25,12 +26,12 @@ Common.Segment = class {
intersects(that) {
return this.begin < that.end && that.begin < this.end;
}
-};
+}
/**
* @unrestricted
*/
-Common.SegmentedRange = class {
+export default class SegmentedRange {
/**
* @param {(function(!Common.Segment, !Common.Segment): ?Common.Segment)=} mergeCallback
*/
@@ -66,8 +67,9 @@ Common.SegmentedRange = class {
}
}
// 3. Consume all segments that are entirely covered by the new one.
- while (endIndex < this._segments.length && this._segments[endIndex].end <= newSegment.end)
+ while (endIndex < this._segments.length && this._segments[endIndex].end <= newSegment.end) {
++endIndex;
+ }
// 4. Merge or adjust the succeeding segment if it overlaps.
if (endIndex < this._segments.length) {
merged = this._tryMerge(newSegment, this._segments[endIndex]);
@@ -102,10 +104,25 @@ Common.SegmentedRange = class {
*/
_tryMerge(first, second) {
const merged = this._mergeCallback && this._mergeCallback(first, second);
- if (!merged)
+ if (!merged) {
return null;
+ }
merged.begin = first.begin;
merged.end = Math.max(first.end, second.end);
return merged;
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Segment = Segment;
+
+/**
+ * @constructor
+ */
+Common.SegmentedRange = SegmentedRange;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
index 2c1e984496d..2c1002308fb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Common.Settings = class {
+export default class Settings {
/**
* @param {!Common.SettingsStorage} globalStorage
* @param {!Common.SettingsStorage} localStorage
@@ -50,7 +50,7 @@ Common.Settings = class {
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
_registerModuleSetting(extension) {
const descriptor = extension.descriptor();
@@ -73,10 +73,12 @@ Common.Settings = class {
}
const setting = isRegex ? this.createRegExpSetting(settingName, defaultValue, undefined, storageType) :
this.createSetting(settingName, defaultValue, storageType);
- if (extension.title())
+ if (extension.title()) {
setting.setTitle(extension.title());
- if (descriptor['userActionCondition'])
- setting.setRequiresUserAction(!!Runtime.queryParam(descriptor['userActionCondition']));
+ }
+ if (descriptor['userActionCondition']) {
+ setting.setRequiresUserAction(!!Root.Runtime.queryParam(descriptor['userActionCondition']));
+ }
setting._extension = extension;
this._moduleSettings.set(settingName, setting);
}
@@ -87,8 +89,9 @@ Common.Settings = class {
*/
moduleSetting(settingName) {
const setting = this._moduleSettings.get(settingName);
- if (!setting)
+ if (!setting) {
throw new Error('No setting registered: ' + settingName);
+ }
return setting;
}
@@ -98,8 +101,9 @@ Common.Settings = class {
*/
settingForTest(settingName) {
const setting = this._registry.get(settingName);
- if (!setting)
+ if (!setting) {
throw new Error('No setting registered: ' + settingName);
+ }
return setting;
}
@@ -111,8 +115,9 @@ Common.Settings = class {
*/
createSetting(key, defaultValue, storageType) {
const storage = this._storageFromType(storageType);
- if (!this._registry.get(key))
+ if (!this._registry.get(key)) {
this._registry.set(key, new Common.Setting(this, key, defaultValue, this._eventSupport, storage));
+ }
return /** @type {!Common.Setting} */ (this._registry.get(key));
}
@@ -164,12 +169,12 @@ Common.Settings = class {
}
return this._globalStorage;
}
-};
+}
/**
* @unrestricted
*/
-Common.SettingsStorage = class {
+export class SettingsStorage {
/**
* @param {!Object} object
* @param {function(string, string)=} setCallback
@@ -231,8 +236,9 @@ Common.SettingsStorage = class {
Common.console.log('Ten largest settings: ');
const sizes = {__proto__: null};
- for (const key in this._object)
+ for (const key in this._object) {
sizes[key] = this._object[key].length;
+ }
const keys = Object.keys(sizes);
function comparator(key1, key2) {
@@ -241,16 +247,17 @@ Common.SettingsStorage = class {
keys.sort(comparator);
- for (let i = 0; i < 10 && i < keys.length; ++i)
+ for (let i = 0; i < 10 && i < keys.length; ++i) {
Common.console.log('Setting: \'' + keys[i] + '\', size: ' + sizes[keys[i]]);
+ }
}
-};
+}
/**
* @template V
* @unrestricted
*/
-Common.Setting = class {
+export class Setting {
/**
* @param {!Common.Settings} settings
* @param {string} name
@@ -315,11 +322,13 @@ Common.Setting = class {
* @return {V}
*/
get() {
- if (this._requiresUserAction && !this._hadUserAction)
+ if (this._requiresUserAction && !this._hadUserAction) {
return this._defaultValue;
+ }
- if (typeof this._value !== 'undefined')
+ if (typeof this._value !== 'undefined') {
return this._value;
+ }
this._value = this._defaultValue;
if (this._storage.has(this._name)) {
@@ -358,7 +367,7 @@ Common.Setting = class {
}
/**
- * @return {?Runtime.Extension}
+ * @return {?Root.Runtime.Extension}
*/
extension() {
return this._extension;
@@ -376,12 +385,12 @@ Common.Setting = class {
Common.console.error(errorMessage);
this._storage._dumpSizes();
}
-};
+}
/**
* @unrestricted
*/
-Common.RegExpSetting = class extends Common.Setting {
+export class RegExpSetting extends Setting {
/**
* @param {!Common.Settings} settings
* @param {string} name
@@ -404,8 +413,9 @@ Common.RegExpSetting = class extends Common.Setting {
const items = this.getAsArray();
for (let i = 0; i < items.length; ++i) {
const item = items[i];
- if (item.pattern && !item.disabled)
+ if (item.pattern && !item.disabled) {
result.push(item.pattern);
+ }
}
return result.join('|');
}
@@ -437,23 +447,25 @@ Common.RegExpSetting = class extends Common.Setting {
* @return {?RegExp}
*/
asRegExp() {
- if (typeof this._regex !== 'undefined')
+ if (typeof this._regex !== 'undefined') {
return this._regex;
+ }
this._regex = null;
try {
const pattern = this.get();
- if (pattern)
+ if (pattern) {
this._regex = new RegExp(pattern, this._regexFlags || '');
+ }
} catch (e) {
}
return this._regex;
}
-};
+}
/**
* @unrestricted
*/
-Common.VersionController = class {
+export class VersionController {
updateVersion() {
const localStorageVersion =
window.localStorage ? window.localStorage[Common.VersionController._currentVersionName] : 0;
@@ -466,8 +478,9 @@ Common.VersionController = class {
return;
}
const methodsToRun = this._methodsToRunToUpdateVersion(oldVersion, currentVersion);
- for (let i = 0; i < methodsToRun.length; ++i)
+ for (let i = 0; i < methodsToRun.length; ++i) {
this[methodsToRun[i]].call(this);
+ }
versionSetting.set(currentVersion);
}
@@ -477,8 +490,9 @@ Common.VersionController = class {
*/
_methodsToRunToUpdateVersion(oldVersion, currentVersion) {
const result = [];
- for (let i = oldVersion; i < currentVersion; ++i)
+ for (let i = oldVersion; i < currentVersion; ++i) {
result.push('_updateVersionFrom' + i + 'To' + (i + 1));
+ }
return result;
}
@@ -543,8 +557,9 @@ Common.VersionController = class {
newValue.horizontal.size = oldSettingH.get();
oldSettingH.remove();
}
- if (newValue)
+ if (newValue) {
Common.settings.createSetting(newName, {}).set(newValue);
+ }
}
}
@@ -590,13 +605,16 @@ Common.VersionController = class {
for (const name in settingNames) {
const setting = Common.settings.createSetting(name, empty);
const value = setting.get();
- if (value === empty)
+ if (value === empty) {
continue;
+ }
// Zero out saved percentage sizes, and they will be restored to defaults.
- if (value.vertical && value.vertical.size && value.vertical.size < 1)
+ if (value.vertical && value.vertical.size && value.vertical.size < 1) {
value.vertical.size = 0;
- if (value.horizontal && value.horizontal.size && value.horizontal.size < 1)
+ }
+ if (value.horizontal && value.horizontal.size && value.horizontal.size < 1) {
value.horizontal.size = 0;
+ }
setting.set(value);
}
}
@@ -610,13 +628,16 @@ Common.VersionController = class {
for (let i = 0; i < settingNames.length; ++i) {
const setting = Common.settings.createSetting(settingNames[i], '');
let value = setting.get();
- if (!value)
+ if (!value) {
return;
- if (typeof value === 'string')
+ }
+ if (typeof value === 'string') {
value = [value];
+ }
for (let j = 0; j < value.length; ++j) {
- if (typeof value[j] === 'string')
+ if (typeof value[j] === 'string') {
value[j] = {pattern: value[j]};
+ }
}
setting.set(value);
}
@@ -624,11 +645,13 @@ Common.VersionController = class {
_updateVersionFrom9To10() {
// This one is localStorage specific, which is fine.
- if (!window.localStorage)
+ if (!window.localStorage) {
return;
+ }
for (const key in window.localStorage) {
- if (key.startsWith('revision-history'))
+ if (key.startsWith('revision-history')) {
window.localStorage.removeItem(key);
+ }
}
}
@@ -637,8 +660,9 @@ Common.VersionController = class {
const newSettingName = 'customEmulatedDeviceList';
const oldSetting = Common.settings.createSetting(oldSettingName, undefined);
const list = oldSetting.get();
- if (!Array.isArray(list))
+ if (!Array.isArray(list)) {
return;
+ }
const newList = [];
for (let i = 0; i < list.length; ++i) {
const value = list[i];
@@ -647,10 +671,12 @@ Common.VersionController = class {
device['type'] = 'unknown';
device['user-agent'] = value['userAgent'];
device['capabilities'] = [];
- if (value['touch'])
+ if (value['touch']) {
device['capabilities'].push('touch');
- if (value['mobile'])
+ }
+ if (value['mobile']) {
device['capabilities'].push('mobile');
+ }
device['screen'] = {};
device['screen']['vertical'] = {width: value['width'], height: value['height']};
device['screen']['horizontal'] = {width: value['height'], height: value['width']};
@@ -660,8 +686,9 @@ Common.VersionController = class {
device['show'] = 'Default';
newList.push(device);
}
- if (newList.length)
+ if (newList.length) {
Common.settings.createSetting(newSettingName, []).set(newList);
+ }
oldSetting.remove();
}
@@ -685,8 +712,9 @@ Common.VersionController = class {
const newValue = {};
for (const fileSystemPath in oldValue) {
newValue[fileSystemPath] = [];
- for (const entry of oldValue[fileSystemPath])
+ for (const entry of oldValue[fileSystemPath]) {
newValue[fileSystemPath].push(entry.path);
+ }
}
setting.set(newValue);
}
@@ -694,8 +722,9 @@ Common.VersionController = class {
_updateVersionFrom15To16() {
const setting = Common.settings.createSetting('InspectorView.panelOrder', {});
const tabOrders = setting.get();
- for (const key of Object.keys(tabOrders))
+ for (const key of Object.keys(tabOrders)) {
tabOrders[key] = (tabOrders[key] + 1) * 10;
+ }
setting.set(tabOrders);
}
@@ -725,10 +754,11 @@ Common.VersionController = class {
for (const oldKey in oldValue) {
let newKey = oldKey.replace(/\\/g, '/');
if (!newKey.startsWith('file://')) {
- if (newKey.startsWith('/'))
+ if (newKey.startsWith('/')) {
newKey = 'file://' + newKey;
- else
+ } else {
newKey = 'file:///' + newKey;
+ }
}
newValue[newKey] = oldValue[oldKey];
}
@@ -744,8 +774,9 @@ Common.VersionController = class {
const configs = {};
for (const columnId in visibleColumns) {
- if (!visibleColumns.hasOwnProperty(columnId))
+ if (!visibleColumns.hasOwnProperty(columnId)) {
continue;
+ }
configs[columnId.toLowerCase()] = {visible: visibleColumns[columnId]};
}
const newSetting = Common.settings.createSetting('networkLogColumns', {});
@@ -833,8 +864,9 @@ Common.VersionController = class {
function renameInStringSetting(settingName, from, to) {
const setting = Common.settings.createSetting(settingName, '');
const value = setting.get();
- if (value === from)
+ if (value === from) {
setting.set(to);
+ }
}
renameKeyInObjectSetting('panel-tabOrder', 'audits2', 'audits');
@@ -844,8 +876,9 @@ Common.VersionController = class {
_updateVersionFrom27To28() {
const setting = Common.settings.createSetting('uiTheme', 'systemPreferred');
- if (setting.get() === 'default')
+ if (setting.get() === 'default') {
setting.set('systemPreferred');
+ }
}
_migrateSettingsFromLocalStorage() {
@@ -855,12 +888,14 @@ Common.VersionController = class {
'fileSystemMapping', 'lastSelectedSourcesSidebarPaneTab', 'previouslyViewedFiles', 'savedURLs',
'watchExpressions', 'workspaceExcludedFolders', 'xhrBreakpoints'
]);
- if (!window.localStorage)
+ if (!window.localStorage) {
return;
+ }
for (const key in window.localStorage) {
- if (localSettings.has(key))
+ if (localSettings.has(key)) {
continue;
+ }
const value = window.localStorage[key];
window.localStorage.removeItem(key);
Common.settings._globalStorage[key] = value;
@@ -874,23 +909,16 @@ Common.VersionController = class {
_clearBreakpointsWhenTooMany(breakpointsSetting, maxBreakpointsCount) {
// If there are too many breakpoints in a storage, it is likely due to a recent bug that caused
// periodical breakpoints duplication leading to inspector slowness.
- if (breakpointsSetting.get().length > maxBreakpointsCount)
+ if (breakpointsSetting.get().length > maxBreakpointsCount) {
breakpointsSetting.set([]);
+ }
}
-};
-
-Common.VersionController._currentVersionName = 'inspectorVersion';
-Common.VersionController.currentVersion = 28;
-
-/**
- * @type {!Common.Settings}
- */
-Common.settings;
+}
/**
* @enum {symbol}
*/
-Common.SettingStorageType = {
+export const SettingStorageType = {
Global: Symbol('Global'),
Local: Symbol('Local'),
Session: Symbol('Session')
@@ -900,14 +928,58 @@ Common.SettingStorageType = {
* @param {string} settingName
* @return {!Common.Setting}
*/
-Common.moduleSetting = function(settingName) {
+export function moduleSetting(settingName) {
return Common.settings.moduleSetting(settingName);
-};
+}
/**
* @param {string} settingName
* @return {!Common.Setting}
*/
-Common.settingForTest = function(settingName) {
+export function settingForTest(settingName) {
return Common.settings.settingForTest(settingName);
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Settings = Settings;
+
+/**
+ * @constructor
+ */
+Common.SettingsStorage = SettingsStorage;
+
+/**
+ * @constructor
+ */
+Common.Setting = Setting;
+
+/**
+ * @constructor
+ */
+Common.RegExpSetting = RegExpSetting;
+Common.settingForTest = settingForTest;
+
+/**
+ * @constructor
+ */
+Common.VersionController = VersionController;
+Common.moduleSetting = moduleSetting;
+
+/**
+ * @enum {symbol}
+ */
+Common.SettingStorageType = SettingStorageType;
+
+Common.VersionController._currentVersionName = 'inspectorVersion';
+Common.VersionController.currentVersion = 28;
+
+/**
+ * @type {!Common.Settings}
+ */
+Common.settings;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
index f871b5b34ba..a73ec1dcc53 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/StaticContentProvider.js
@@ -5,11 +5,11 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-Common.StaticContentProvider = class {
+export default class StaticContentProvider {
/**
* @param {string} contentURL
* @param {!Common.ResourceType} contentType
- * @param {function():!Promise<?string>} lazyContent
+ * @param {function():!Promise<!Common.DeferredContent>} lazyContent
*/
constructor(contentURL, contentType, lazyContent) {
this._contentURL = contentURL;
@@ -24,7 +24,7 @@ Common.StaticContentProvider = class {
* @return {!Common.StaticContentProvider}
*/
static fromString(contentURL, contentType, content) {
- const lazyContent = () => Promise.resolve(content);
+ const lazyContent = () => Promise.resolve({content, isEncoded: false});
return new Common.StaticContentProvider(contentURL, contentType, lazyContent);
}
@@ -54,7 +54,7 @@ Common.StaticContentProvider = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
return this._lazyContent();
@@ -68,7 +68,16 @@ Common.StaticContentProvider = class {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- const content = await this._lazyContent();
+ const {content} = (await this._lazyContent());
return content ? Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex) : [];
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.StaticContentProvider = StaticContentProvider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/OutputStream.js b/chromium/third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js
index a4fa83b251a..abd6b497935 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/OutputStream.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/StringOutputStream.js
@@ -5,22 +5,25 @@
/**
* @interface
*/
-Common.OutputStream = function() {};
-
-Common.OutputStream.prototype = {
+export class OutputStream {
/**
* @param {string} data
* @return {!Promise}
*/
- write(data) {},
+ async write(data) {
+ }
- close() {}
-};
+ /**
+ * @return {!Promise}
+ */
+ async close() {
+ }
+}
/**
* @implements {Common.OutputStream}
*/
-Common.StringOutputStream = class {
+export default class StringOutputStream {
constructor() {
this._data = '';
}
@@ -37,7 +40,7 @@ Common.StringOutputStream = class {
/**
* @override
*/
- close() {
+ async close() {
}
/**
@@ -46,4 +49,14 @@ Common.StringOutputStream = class {
data() {
return this._data;
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @interface
+ */
+Common.OutputStream = OutputStream;
+Common.StringOutputStream = StringOutputStream;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js b/chromium/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
index 9c555b2763b..adf355a0db3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/TextDictionary.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Common.TextDictionary = class {
+export default class TextDictionary {
constructor() {
/** @type {!Map<string, number>} */
this._words = new Map();
@@ -53,8 +53,9 @@ Common.TextDictionary = class {
*/
removeWord(word) {
let count = this._words.get(word) || 0;
- if (!count)
+ if (!count) {
return;
+ }
if (count === 1) {
this._words.delete(word);
this._index.remove(word);
@@ -92,4 +93,10 @@ Common.TextDictionary = class {
this._words.clear();
this._index.clear();
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.TextDictionary = TextDictionary;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Throttler.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Throttler.js
index a88e78f5474..95a60b63013 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Throttler.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Throttler.js
@@ -1,10 +1,11 @@
// 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.
+
/**
* @unrestricted
*/
-Common.Throttler = class {
+export default class Throttler {
/**
* @param {number} timeout
*/
@@ -24,8 +25,9 @@ Common.Throttler = class {
_processCompleted() {
this._lastCompleteTime = this._getTime();
this._isRunningProcess = false;
- if (this._process)
+ if (this._process) {
this._innerSchedule(false);
+ }
this._processCompletedForTests();
}
@@ -75,12 +77,15 @@ Common.Throttler = class {
* @param {boolean} forceTimerUpdate
*/
_innerSchedule(forceTimerUpdate) {
- if (this._isRunningProcess)
+ if (this._isRunningProcess) {
return;
- if (this._processTimeout && !forceTimerUpdate)
+ }
+ if (this._processTimeout && !forceTimerUpdate) {
return;
- if (this._processTimeout)
+ }
+ if (this._processTimeout) {
this._clearTimeout(this._processTimeout);
+ }
const timeout = this._asSoonAsPossible ? 0 : this._timeout;
this._processTimeout = this._setTimeout(this._onTimeout.bind(this), timeout);
@@ -108,7 +113,13 @@ Common.Throttler = class {
_getTime() {
return window.performance.now();
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.Throttler = Throttler;
/** @typedef {function(!Error=)} */
Common.Throttler.FinishCallback;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Trie.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Trie.js
index 98291c5042f..9e9143a8529 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Trie.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Trie.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-Common.Trie = class {
+export default class Trie {
constructor() {
this.clear();
}
@@ -41,8 +41,9 @@ Common.Trie = class {
* @return {boolean}
*/
remove(word) {
- if (!this.has(word))
+ if (!this.has(word)) {
return false;
+ }
let node = this._root;
--this._wordsInSubtree[this._root];
for (let i = 0; i < word.length; ++i) {
@@ -66,8 +67,9 @@ Common.Trie = class {
let node = this._root;
for (let i = 0; i < word.length; ++i) {
node = this._edges[node][word[i]];
- if (!node)
+ if (!node) {
return false;
+ }
}
return this._isWord[node];
}
@@ -81,8 +83,9 @@ Common.Trie = class {
let node = this._root;
for (let i = 0; i < prefix.length; ++i) {
node = this._edges[node][prefix[i]];
- if (!node)
+ if (!node) {
return [];
+ }
}
const results = [];
this._dfs(node, prefix, results);
@@ -95,11 +98,13 @@ Common.Trie = class {
* @param {!Array<string>} results
*/
_dfs(node, prefix, results) {
- if (this._isWord[node])
+ if (this._isWord[node]) {
results.push(prefix);
+ }
const edges = this._edges[node];
- for (const edge in edges)
+ for (const edge in edges) {
this._dfs(edges[edge], prefix + edge, results);
+ }
}
/**
@@ -112,10 +117,12 @@ Common.Trie = class {
let wordIndex = 0;
for (let i = 0; i < word.length; ++i) {
node = this._edges[node][word[i]];
- if (!node)
+ if (!node) {
break;
- if (!fullWordOnly || this._isWord[node])
+ }
+ if (!fullWordOnly || this._isWord[node]) {
wordIndex = i + 1;
+ }
}
return word.substring(0, wordIndex);
}
@@ -132,4 +139,10 @@ Common.Trie = class {
/** @type {!Array<number>} */
this._freeNodes = [];
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+Common.Trie = Trie;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/UIString.js b/chromium/third_party/blink/renderer/devtools/front_end/common/UIString.js
index 8845ed7b66a..c84e84eb351 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/UIString.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/UIString.js
@@ -29,35 +29,56 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-self['Common'] = self['Common'] || {};
-
/**
* @param {string} string
* @param {...*} vararg
* @return {string}
*/
-Common.UIString = function(string, vararg) {
+export default function UIString(string, vararg) {
return String.vsprintf(Common.localize(string), Array.prototype.slice.call(arguments, 1));
-};
+}
/**
* @param {string} string
+ * @param {?ArrayLike} values
* @return {string}
*/
-Common.localize = function(string) {
+export function serializeUIString(string, values = []) {
+ const messageParts = [string];
+ const serializedMessage = {messageParts, values};
+ return JSON.stringify(serializedMessage);
+}
+
+/**
+ * @param {string} serializedMessage
+ * @return {*}
+ */
+export function deserializeUIString(serializedMessage) {
+ if (!serializedMessage) {
+ return {};
+ }
+
+ return JSON.parse(serializedMessage);
+}
+
+/**
+ * @param {string} string
+ * @return {string}
+ */
+export function localize(string) {
return string;
-};
+}
/**
* @unrestricted
*/
-Common.UIStringFormat = class {
+export class UIStringFormat {
/**
* @param {string} format
*/
constructor(format) {
/** @type {string} */
- this._localizedFormat = Common.localize(format);
+ this._localizedFormat = localize(format);
/** @type {!Array.<!Object>} */
this._tokenizedFormat = String.tokenizeFormatString(this._localizedFormat, String.standardFormatters);
}
@@ -82,10 +103,7 @@ Common.UIStringFormat = class {
this._tokenizedFormat)
.formattedResult;
}
-};
-
-/** @type {!WeakMap<!Array<string>, string>} */
-Common._substitutionStrings = new WeakMap();
+}
/**
* @param {!Array<string>|string} strings
@@ -93,8 +111,9 @@ Common._substitutionStrings = new WeakMap();
* @return {string}
*/
self.ls = function(strings, vararg) {
- if (typeof strings === 'string')
+ if (typeof strings === 'string') {
return strings;
+ }
let substitutionString = Common._substitutionStrings.get(strings);
if (!substitutionString) {
substitutionString = strings.join('%s');
@@ -102,3 +121,20 @@ self.ls = function(strings, vararg) {
}
return Common.UIString(substitutionString, ...Array.prototype.slice.call(arguments, 1));
};
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.UIStringFormat = UIStringFormat;
+
+Common.UIString = UIString;
+Common.serializeUIString = serializeUIString;
+Common.deserializeUIString = deserializeUIString;
+Common.localize = localize;
+
+/** @type {!WeakMap<!Array<string>, string>} */
+Common._substitutionStrings = new WeakMap();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Worker.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Worker.js
index 5bdacedd480..bdf73e88e93 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Worker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Worker.js
@@ -31,13 +31,13 @@
/**
* @unrestricted
*/
-Common.Worker = class {
+export default class WorkerWrapper {
/**
* @param {string} appName
*/
constructor(appName) {
let url = appName + '.js';
- url += Runtime.queryParamsString();
+ url += Root.Runtime.queryParamsString();
/** @type {!Promise<!Worker>} */
this._workerPromise = new Promise(fulfill => {
@@ -64,8 +64,9 @@ Common.Worker = class {
*/
postMessage(message) {
this._workerPromise.then(worker => {
- if (!this._disposed)
+ if (!this._disposed) {
worker.postMessage(message);
+ }
});
}
@@ -91,4 +92,13 @@ Common.Worker = class {
set onerror(listener) {
this._workerPromise.then(worker => worker.onerror = listener);
}
-};
+}
+
+/* Legacy exported object */
+self.Common = self.Common || {};
+Common = Common || {};
+
+/**
+ * @constructor
+ */
+Common.Worker = WorkerWrapper;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/common.js b/chromium/third_party/blink/renderer/devtools/front_end/common/common.js
new file mode 100644
index 00000000000..8073066d256
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/common.js
@@ -0,0 +1,63 @@
+// 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 './EventTarget.js';
+import './Object.js';
+import './UIString.js';
+
+// Do not reorder these imports as it breaks dependencies.
+
+import * as App from './App.js';
+import * as AppProvider from './AppProvider.js';
+import * as CharacterIdMap from './CharacterIdMap.js';
+import * as Color from './Color.js';
+import * as Console from './Console.js';
+import * as ContentProvider from './ContentProvider.js';
+import * as EventTarget from './EventTarget.js';
+import * as JavaScriptMetaData from './JavaScriptMetaData.js';
+import * as Linkifier from './Linkifier.js';
+import * as Object from './Object.js';
+import * as ParsedURL from './ParsedURL.js';
+import * as Progress from './Progress.js';
+import * as QueryParamHandler from './QueryParamHandler.js';
+import * as ResourceType from './ResourceType.js';
+import * as Revealer from './Revealer.js';
+import * as Runnable from './Runnable.js';
+import * as SegmentedRange from './SegmentedRange.js';
+import * as Settings from './Settings.js';
+import * as StaticContentProvider from './StaticContentProvider.js';
+import * as StringOutputStream from './StringOutputStream.js';
+import * as TextDictionary from './TextDictionary.js';
+import * as Throttler from './Throttler.js';
+import * as Trie from './Trie.js';
+import * as UIString from './UIString.js';
+import * as Worker from './Worker.js';
+
+export {
+ App,
+ AppProvider,
+ CharacterIdMap,
+ Color,
+ Console,
+ ContentProvider,
+ EventTarget,
+ JavaScriptMetaData,
+ Linkifier,
+ Object,
+ ParsedURL,
+ Progress,
+ QueryParamHandler,
+ ResourceType,
+ Revealer,
+ Runnable,
+ SegmentedRange,
+ Settings,
+ StaticContentProvider,
+ StringOutputStream,
+ TextDictionary,
+ Throttler,
+ Trie,
+ UIString,
+ Worker,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/common_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/common/common_strings.grdp
new file mode 100644
index 00000000000..52aac3b8f19
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/common_strings.grdp
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_DEVTOOLS_0945359809dad1fbf3dea1c95a0da951" desc="Name of a network resource type">
+ Document
+ </message>
+ <message name="IDS_DEVTOOLS_21133d71a056222fa2096906538e4e04" desc="Text that appears on a button for the image resource type filter.">
+ Img
+ </message>
+ <message name="IDS_DEVTOOLS_375c9558f2166cab6515a7ab774c1735" desc="Name of a network resource type">
+ TextTrack
+ </message>
+ <message name="IDS_DEVTOOLS_441d3aea2e55865603a26ca972779831" desc="Text that appears in a tooltip the xhr and fetch resource types filter.">
+ XHR and Fetch
+ </message>
+ <message name="IDS_DEVTOOLS_45edc1b96407d9d213dd1135962a32a0" desc="Name of a network resource type">
+ WebSocket
+ </message>
+ <message name="IDS_DEVTOOLS_4ea7755f84f02d23876d90be2f9765cf" desc="Name of a network resource type">
+ Fetch
+ </message>
+ <message name="IDS_DEVTOOLS_54df3baef130c81e6ae8432a2567320a" desc="Text that appears on a button for the websocket resource type filter.">
+ WS
+ </message>
+ <message name="IDS_DEVTOOLS_59c4ad3f3cb3d812d68fab7a354d4a63" desc="Text that appears in a tooltip for the resource types filter.">
+ Fonts
+ </message>
+ <message name="IDS_DEVTOOLS_7a48ae1b7387f8a8159c488fbd850021" desc="Text that appears on a button for the document resource type filter.">
+ Doc
+ </message>
+ <message name="IDS_DEVTOOLS_85e8231d44b865e90f6a39b356ded9bd" desc="Text that appears in a tooltip for the css types filter.">
+ Stylesheets
+ </message>
+ <message name="IDS_DEVTOOLS_8cf6dd5e7b4fe7b6df3319b9803278f3" desc="Name of a network resource type">
+ EventSource
+ </message>
+ <message name="IDS_DEVTOOLS_a83f1ca5ad00b39773d9e6a26b0e70b2" desc="Text that appears in a tooltip for the javascript types filter.">
+ Scripts
+ </message>
+ <message name="IDS_DEVTOOLS_bef61d7d03206d267fdbab45fdca247d" desc="Name of a network resource type">
+ SignedExchange
+ </message>
+ <message name="IDS_DEVTOOLS_bf4e3c3f0fc3aee351d560e6e026f805" desc="Text that appears in a tooltip for the websocket types filter.">
+ WebSockets
+ </message>
+ <message name="IDS_DEVTOOLS_c350bb18c3cdfbd4e5444faa63be6586" desc="Name of a network resource type">
+ Stylesheet
+ </message>
+ <message name="IDS_DEVTOOLS_fff0d600f8a0b5e19e88bfb821dd1157" desc="Text that appears in a tooltip for the image types filter.">
+ Images
+ </message>
+</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/module.json b/chromium/third_party/blink/renderer/devtools/front_end/common/module.json
index 99b5427a8ab..72644c8a891 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/module.json
@@ -3,24 +3,34 @@
"text_utils",
"platform"
],
- "scripts": [
+ "modules": [
+ "common.js",
+ "EventTarget.js",
+ "Object.js",
"Worker.js",
"TextDictionary.js",
- "Object.js",
"Color.js",
"Console.js",
"ContentProvider.js",
"ParsedURL.js",
"Progress.js",
+ "UIString.js",
"ResourceType.js",
"Settings.js",
"StaticContentProvider.js",
- "OutputStream.js",
"SegmentedRange.js",
"Throttler.js",
"Trie.js",
- "UIString.js",
- "ModuleExtensionInterfaces.js",
+ "Revealer.js",
+ "App.js",
+ "AppProvider.js",
+ "JavaScriptMetaData.js",
+ "Linkifier.js",
+ "QueryParamHandler.js",
+ "Revealer.js",
+ "Runnable.js",
+ "StringOutputStream.js",
"CharacterIdMap.js"
- ]
+ ],
+ "scripts": []
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/DockController.js b/chromium/third_party/blink/renderer/devtools/front_end/components/DockController.js
index 801f25dc1a0..fbf54129554 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/DockController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/DockController.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Components.DockController = class extends Common.Object {
+export default class DockController extends Common.Object {
/**
* @param {boolean} canDock
*/
@@ -41,30 +41,30 @@ Components.DockController = class extends Common.Object {
this._closeButton = new UI.ToolbarButton(Common.UIString('Close'), 'largeicon-delete');
this._closeButton.addEventListener(
- UI.ToolbarButton.Events.Click, InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost));
+ UI.ToolbarButton.Events.Click, Host.InspectorFrontendHost.closeWindow.bind(Host.InspectorFrontendHost));
if (!canDock) {
- this._dockSide = Components.DockController.State.Undocked;
+ this._dockSide = State.Undocked;
this._closeButton.setVisible(false);
return;
}
- this._states = [
- Components.DockController.State.DockedToRight, Components.DockController.State.DockedToBottom,
- Components.DockController.State.DockedToLeft, Components.DockController.State.Undocked
- ];
+ this._states = [State.DockedToRight, State.DockedToBottom, State.DockedToLeft, State.Undocked];
this._currentDockStateSetting = Common.settings.moduleSetting('currentDockState');
this._currentDockStateSetting.addChangeListener(this._dockSideChanged, this);
this._lastDockStateSetting = Common.settings.createSetting('lastDockState', 'bottom');
- if (this._states.indexOf(this._currentDockStateSetting.get()) === -1)
+ if (this._states.indexOf(this._currentDockStateSetting.get()) === -1) {
this._currentDockStateSetting.set('right');
- if (this._states.indexOf(this._lastDockStateSetting.get()) === -1)
+ }
+ if (this._states.indexOf(this._lastDockStateSetting.get()) === -1) {
this._currentDockStateSetting.set('bottom');
+ }
}
initialize() {
- if (!this._canDock)
+ if (!this._canDock) {
return;
+ }
this._titles = [
Common.UIString('Dock to right'), Common.UIString('Dock to bottom'), Common.UIString('Dock to left'),
@@ -95,8 +95,7 @@ Components.DockController = class extends Common.Object {
* @return {boolean}
*/
isVertical() {
- return this._dockSide === Components.DockController.State.DockedToRight ||
- this._dockSide === Components.DockController.State.DockedToLeft;
+ return this._dockSide === State.DockedToRight || this._dockSide === State.DockedToLeft;
}
/**
@@ -104,32 +103,35 @@ Components.DockController = class extends Common.Object {
* @suppressGlobalPropertiesCheck
*/
setDockSide(dockSide) {
- if (this._states.indexOf(dockSide) === -1)
+ if (this._states.indexOf(dockSide) === -1) {
dockSide = this._states[0];
+ }
- if (this._dockSide === dockSide)
+ if (this._dockSide === dockSide) {
return;
+ }
- if (this._dockSide)
+ if (this._dockSide) {
this._lastDockStateSetting.set(this._dockSide);
+ }
this._savedFocus = document.deepActiveElement();
const eventData = {from: this._dockSide, to: dockSide};
- this.dispatchEventToListeners(Components.DockController.Events.BeforeDockSideChanged, eventData);
+ this.dispatchEventToListeners(Events.BeforeDockSideChanged, eventData);
console.timeStamp('DockController.setIsDocked');
this._dockSide = dockSide;
this._currentDockStateSetting.set(dockSide);
- InspectorFrontendHost.setIsDocked(
- dockSide !== Components.DockController.State.Undocked, this._setIsDockedResponse.bind(this, eventData));
- this._closeButton.setVisible(this._dockSide !== Components.DockController.State.Undocked);
- this.dispatchEventToListeners(Components.DockController.Events.DockSideChanged, eventData);
+ Host.InspectorFrontendHost.setIsDocked(
+ dockSide !== State.Undocked, this._setIsDockedResponse.bind(this, eventData));
+ this._closeButton.setVisible(this._dockSide !== State.Undocked);
+ this.dispatchEventToListeners(Events.DockSideChanged, eventData);
}
/**
* @param {{from: string, to: string}} eventData
*/
_setIsDockedResponse(eventData) {
- this.dispatchEventToListeners(Components.DockController.Events.AfterDockSideChanged, eventData);
+ this.dispatchEventToListeners(Events.AfterDockSideChanged, eventData);
if (this._savedFocus) {
this._savedFocus.focus();
this._savedFocus = null;
@@ -143,9 +145,9 @@ Components.DockController = class extends Common.Object {
}
this.setDockSide(this._lastDockStateSetting.get());
}
-};
+}
-Components.DockController.State = {
+export const State = {
DockedToBottom: 'bottom',
DockedToRight: 'right',
DockedToLeft: 'left',
@@ -157,7 +159,7 @@ Components.DockController.State = {
// after frontend is docked/undocked in the browser.
/** @enum {symbol} */
-Components.DockController.Events = {
+export const Events = {
BeforeDockSideChanged: Symbol('BeforeDockSideChanged'),
DockSideChanged: Symbol('DockSideChanged'),
AfterDockSideChanged: Symbol('AfterDockSideChanged')
@@ -167,7 +169,7 @@ Components.DockController.Events = {
* @implements {UI.ActionDelegate}
* @unrestricted
*/
-Components.DockController.ToggleDockActionDelegate = class {
+export class ToggleDockActionDelegate {
/**
* @override
* @param {!UI.Context} context
@@ -178,13 +180,13 @@ Components.DockController.ToggleDockActionDelegate = class {
Components.dockController._toggleDockSide();
return true;
}
-};
+}
/**
* @implements {UI.ToolbarItem.Provider}
* @unrestricted
*/
-Components.DockController.CloseButtonProvider = class {
+export class CloseButtonProvider {
/**
* @override
* @return {?UI.ToolbarItem}
@@ -192,9 +194,29 @@ Components.DockController.CloseButtonProvider = class {
item() {
return Components.dockController._closeButton;
}
-};
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+/** @constructor */
+Components.DockController = DockController;
+
+Components.DockController.State = State;
+
+/** @enum {symbol} */
+Components.DockController.Events = Events;
+
+/** @constructor */
+Components.DockController.ToggleDockActionDelegate = ToggleDockActionDelegate;
+
+/** @constructor */
+Components.DockController.CloseButtonProvider = CloseButtonProvider;
/**
* @type {!Components.DockController}
*/
-Components.dockController;
+Components.dockController; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js b/chromium/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js
index 29af920d484..4d4cb787cbb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/ImagePreview.js
@@ -2,32 +2,38 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Components.ImagePreview = class {
+export default class ImagePreview {
/**
* @param {!SDK.Target} target
* @param {string} originalImageURL
* @param {boolean} showDimensions
- * @param {!Object=} precomputedFeatures
+ * @param {!{precomputedFeatures: (!Object|undefined), imageAltText: (string|undefined)}=} options
* @return {!Promise<?Element>}
*/
- static build(target, originalImageURL, showDimensions, precomputedFeatures) {
+ static build(target, originalImageURL, showDimensions, options = {}) {
+ const {precomputedFeatures, imageAltText} = options;
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
- if (!resourceTreeModel)
+ if (!resourceTreeModel) {
return Promise.resolve(/** @type {?Element} */ (null));
+ }
let resource = resourceTreeModel.resourceForURL(originalImageURL);
let imageURL = originalImageURL;
if (!isImageResource(resource) && precomputedFeatures && precomputedFeatures.currentSrc) {
imageURL = precomputedFeatures.currentSrc;
resource = resourceTreeModel.resourceForURL(imageURL);
}
- if (!isImageResource(resource))
+ if (!isImageResource(resource)) {
return Promise.resolve(/** @type {?Element} */ (null));
+ }
let fulfill;
const promise = new Promise(x => fulfill = x);
const imageElement = createElement('img');
imageElement.addEventListener('load', buildContent, false);
imageElement.addEventListener('error', () => fulfill(null), false);
+ if (imageAltText) {
+ imageElement.alt = imageAltText;
+ }
resource.populateImageSource(imageElement);
return promise;
@@ -58,8 +64,9 @@ Components.ImagePreview = class {
}
container.createChild('tr').createChild('td', 'image-container').appendChild(imageElement);
- if (description)
+ if (description) {
container.createChild('tr').createChild('td').createChild('span', 'description').textContent = description;
+ }
if (imageURL !== originalImageURL) {
container.createChild('tr').createChild('td').createChild('span', 'description').textContent =
String.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
@@ -73,13 +80,15 @@ Components.ImagePreview = class {
* @return {!Promise<!Object|undefined>}
*/
static async loadDimensionsForNode(node) {
- if (!node.nodeName() || node.nodeName().toLowerCase() !== 'img')
+ if (!node.nodeName() || node.nodeName().toLowerCase() !== 'img') {
return;
+ }
const object = await node.resolveToObject('');
- if (!object)
+ if (!object) {
return;
+ }
const featuresObject = object.callFunctionJSON(features, undefined);
object.release();
@@ -94,4 +103,23 @@ Components.ImagePreview = class {
return {renderedWidth: this.width, renderedHeight: this.height, currentSrc: this.currentSrc};
}
}
-};
+
+ /**
+ * @param {string} url
+ * @return {string}
+ */
+ static defaultAltTextForImageURL(url) {
+ const parsedImageURL = new Common.ParsedURL(url);
+ const imageSourceText = parsedImageURL.isValid ? parsedImageURL.displayName : ls`unknown source`;
+ return ls`Image from ${imageSourceText}`;
+ }
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+/** @constructor */
+Components.ImagePreview = ImagePreview;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/JSPresentationUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/components/JSPresentationUtils.js
index 3e74bea526b..4a147ae5a98 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/JSPresentationUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/JSPresentationUtils.js
@@ -28,7 +28,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.
*/
-Components.JSPresentationUtils = {};
/**
* @param {?SDK.Target} target
@@ -37,9 +36,8 @@ Components.JSPresentationUtils = {};
* @param {function()=} contentUpdated
* @return {{element: !Element, links: !Array<!Element>}}
*/
-Components.JSPresentationUtils.buildStackTracePreviewContents = function(
- target, linkifier, stackTrace, contentUpdated) {
- const element = createElement('span');
+export function buildStackTracePreviewContents(target, linkifier, stackTrace, contentUpdated) {
+ const element = createElementWithClass('span', 'monospace');
element.style.display = 'inline-block';
const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'components/jsUtils.css');
const contentElement = shadowRoot.createChild('table', 'stack-preview-container');
@@ -64,8 +62,9 @@ Components.JSPresentationUtils.buildStackTracePreviewContents = function(
if (link) {
link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
const uiLocation = Components.Linkifier.uiLocation(link);
- if (uiLocation && Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode))
+ if (uiLocation && Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode)) {
shouldHide = true;
+ }
row.createChild('td').textContent = ' @ ';
row.createChild('td').appendChild(link);
links.push(link);
@@ -101,8 +100,9 @@ Components.JSPresentationUtils.buildStackTracePreviewContents = function(
contextMenu.show();
}
- if (!stackTrace)
+ if (!stackTrace) {
return {element, links};
+ }
appendStackTrace(stackTrace);
@@ -118,8 +118,9 @@ Components.JSPresentationUtils.buildStackTracePreviewContents = function(
UI.asyncStackTraceLabel(asyncStackTrace.description);
row.createChild('td');
row.createChild('td');
- if (appendStackTrace(asyncStackTrace))
+ if (appendStackTrace(asyncStackTrace)) {
row.classList.add('blackboxed');
+ }
asyncStackTrace = asyncStackTrace.parent;
}
@@ -129,16 +130,28 @@ Components.JSPresentationUtils.buildStackTracePreviewContents = function(
const cell = row.createChild('td');
cell.colSpan = 4;
const showAllLink = cell.createChild('span', 'link');
- if (totalHiddenCallFramesCount === 1)
+ if (totalHiddenCallFramesCount === 1) {
showAllLink.textContent = ls`Show 1 more frame`;
- else
+ } else {
showAllLink.textContent = ls`Show ${totalHiddenCallFramesCount} more frames`;
+ }
showAllLink.addEventListener('click', () => {
contentElement.classList.add('show-blackboxed');
- if (contentUpdated)
+ if (contentUpdated) {
contentUpdated();
+ }
}, false);
}
return {element, links};
-};
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+Components.JSPresentationUtils = {};
+
+Components.JSPresentationUtils.buildStackTracePreviewContents = buildStackTracePreviewContents;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/Linkifier.js b/chromium/third_party/blink/renderer/devtools/front_end/components/Linkifier.js
index d6a04090421..bc6a339a31d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/Linkifier.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/Linkifier.js
@@ -32,7 +32,7 @@
* @implements {SDK.TargetManager.Observer}
* @unrestricted
*/
-Components.Linkifier = class {
+export default class Linkifier {
/**
* @param {number=} maxLengthForDisplayedURLs
* @param {boolean=} useLinkDecorator
@@ -44,35 +44,38 @@ Components.Linkifier = class {
/** @type {!Map<!SDK.Target, !Bindings.LiveLocationPool>} */
this._locationPoolByTarget = new Map();
this._useLinkDecorator = !!useLinkDecorator;
- Components.Linkifier._instances.add(this);
+ _instances.add(this);
SDK.targetManager.observeTargets(this);
}
/**
- * @param {!Components.LinkDecorator} decorator
+ * @param {!LinkDecorator} decorator
*/
static setLinkDecorator(decorator) {
- console.assert(!Components.Linkifier._decorator, 'Cannot re-register link decorator.');
- Components.Linkifier._decorator = decorator;
- decorator.addEventListener(Components.LinkDecorator.Events.LinkIconChanged, onLinkIconChanged);
- for (const linkifier of Components.Linkifier._instances)
+ console.assert(!_decorator, 'Cannot re-register link decorator.');
+ _decorator = decorator;
+ decorator.addEventListener(LinkDecorator.Events.LinkIconChanged, onLinkIconChanged);
+ for (const linkifier of _instances) {
linkifier._updateAllAnchorDecorations();
+ }
/**
* @param {!Common.Event} event
*/
function onLinkIconChanged(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
- const links = uiSourceCode[Components.Linkifier._sourceCodeAnchors] || [];
- for (const link of links)
- Components.Linkifier._updateLinkDecorations(link);
+ const links = uiSourceCode[_sourceCodeAnchors] || [];
+ for (const link of links) {
+ Linkifier._updateLinkDecorations(link);
+ }
}
}
_updateAllAnchorDecorations() {
for (const anchors of this._anchorsByTarget.values()) {
- for (const anchor of anchors)
- Components.Linkifier._updateLinkDecorations(anchor);
+ for (const anchor of anchors) {
+ Linkifier._updateLinkDecorations(anchor);
+ }
}
}
@@ -81,14 +84,15 @@ Components.Linkifier = class {
* @param {!Workspace.UILocation} uiLocation
*/
static _bindUILocation(anchor, uiLocation) {
- Components.Linkifier._linkInfo(anchor).uiLocation = uiLocation;
- if (!uiLocation)
+ Linkifier._linkInfo(anchor).uiLocation = uiLocation;
+ if (!uiLocation) {
return;
+ }
const uiSourceCode = uiLocation.uiSourceCode;
- let sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors];
+ let sourceCodeAnchors = uiSourceCode[_sourceCodeAnchors];
if (!sourceCodeAnchors) {
sourceCodeAnchors = new Set();
- uiSourceCode[Components.Linkifier._sourceCodeAnchors] = sourceCodeAnchors;
+ uiSourceCode[_sourceCodeAnchors] = sourceCodeAnchors;
}
sourceCodeAnchors.add(anchor);
}
@@ -97,15 +101,17 @@ Components.Linkifier = class {
* @param {!Element} anchor
*/
static _unbindUILocation(anchor) {
- const info = Components.Linkifier._linkInfo(anchor);
- if (!info.uiLocation)
+ const info = Linkifier._linkInfo(anchor);
+ if (!info.uiLocation) {
return;
+ }
const uiSourceCode = info.uiLocation.uiSourceCode;
info.uiLocation = null;
- const sourceCodeAnchors = uiSourceCode[Components.Linkifier._sourceCodeAnchors];
- if (sourceCodeAnchors)
+ const sourceCodeAnchors = uiSourceCode[_sourceCodeAnchors];
+ if (sourceCodeAnchors) {
sourceCodeAnchors.delete(anchor);
+ }
}
/**
@@ -126,15 +132,15 @@ Components.Linkifier = class {
locationPool.disposeAll();
const anchors = this._anchorsByTarget.remove(target);
for (const anchor of anchors) {
- const info = Components.Linkifier._linkInfo(anchor);
+ const info = Linkifier._linkInfo(anchor);
info.liveLocation = null;
- Components.Linkifier._unbindUILocation(anchor);
+ Linkifier._unbindUILocation(anchor);
if (info.fallback) {
anchor.href = info.fallback.href;
anchor.title = info.fallback.title;
anchor.className = info.fallback.className;
anchor.textContent = info.fallback.textContent;
- anchor[Components.Linkifier._infoSymbol] = info.fallback[Components.Linkifier._infoSymbol];
+ anchor[_infoSymbol] = info.fallback[_infoSymbol];
}
}
}
@@ -151,24 +157,27 @@ Components.Linkifier = class {
maybeLinkifyScriptLocation(target, scriptId, sourceURL, lineNumber, columnNumber, classes) {
let fallbackAnchor = null;
if (sourceURL) {
- fallbackAnchor = Components.Linkifier.linkifyURL(
+ fallbackAnchor = Linkifier.linkifyURL(
sourceURL,
{className: classes, lineNumber: lineNumber, columnNumber: columnNumber, maxLength: this._maxLength});
}
- if (!target || target.isDisposed())
+ if (!target || target.isDisposed()) {
return fallbackAnchor;
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return fallbackAnchor;
+ }
const rawLocation =
(scriptId ? debuggerModel.createRawLocationByScriptId(scriptId, lineNumber, columnNumber || 0) : null) ||
debuggerModel.createRawLocationByURL(sourceURL, lineNumber, columnNumber || 0);
- if (!rawLocation)
+ if (!rawLocation) {
return fallbackAnchor;
+ }
- const anchor = Components.Linkifier._createLink('', classes || '');
- const info = Components.Linkifier._linkInfo(anchor);
+ const anchor = Linkifier._createLink('', classes || '');
+ const info = Linkifier._linkInfo(anchor);
info.enableDecorator = this._useLinkDecorator;
info.fallback = fallbackAnchor;
info.liveLocation = Bindings.debuggerWorkspaceBinding.createLiveLocation(
@@ -192,7 +201,7 @@ Components.Linkifier = class {
linkifyScriptLocation(target, scriptId, sourceURL, lineNumber, columnNumber, classes) {
const scriptLink = this.maybeLinkifyScriptLocation(target, scriptId, sourceURL, lineNumber, columnNumber, classes);
return scriptLink ||
- Components.Linkifier.linkifyURL(
+ Linkifier.linkifyURL(
sourceURL,
{className: classes, lineNumber: lineNumber, columnNumber: columnNumber, maxLength: this._maxLength});
}
@@ -230,22 +239,24 @@ Components.Linkifier = class {
console.assert(stackTrace.callFrames && stackTrace.callFrames.length);
const topFrame = stackTrace.callFrames[0];
- const fallbackAnchor = Components.Linkifier.linkifyURL(topFrame.url, {
+ const fallbackAnchor = Linkifier.linkifyURL(topFrame.url, {
className: classes,
lineNumber: topFrame.lineNumber,
columnNumber: topFrame.columnNumber,
maxLength: this._maxLength
});
- if (target.isDisposed())
+ if (target.isDisposed()) {
return fallbackAnchor;
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
const rawLocations = debuggerModel.createRawLocationsByStackTrace(stackTrace);
- if (rawLocations.length === 0)
+ if (rawLocations.length === 0) {
return fallbackAnchor;
+ }
- const anchor = Components.Linkifier._createLink('', classes || '');
- const info = Components.Linkifier._linkInfo(anchor);
+ const anchor = Linkifier._createLink('', classes || '');
+ const info = Linkifier._linkInfo(anchor);
info.enableDecorator = this._useLinkDecorator;
info.fallback = fallbackAnchor;
info.liveLocation = Bindings.debuggerWorkspaceBinding.createStackTraceTopFrameLiveLocation(
@@ -263,8 +274,8 @@ Components.Linkifier = class {
* @return {!Element}
*/
linkifyCSSLocation(rawLocation, classes) {
- const anchor = Components.Linkifier._createLink('', classes || '');
- const info = Components.Linkifier._linkInfo(anchor);
+ const anchor = Linkifier._createLink('', classes || '');
+ const info = Linkifier._linkInfo(anchor);
info.enableDecorator = this._useLinkDecorator;
info.liveLocation = Bindings.cssWorkspaceBinding.createLiveLocation(
rawLocation, this._updateAnchor.bind(this, anchor),
@@ -283,10 +294,11 @@ Components.Linkifier = class {
}
dispose() {
- for (const target of this._anchorsByTarget.keysArray())
+ for (const target of this._anchorsByTarget.keysArray()) {
this.targetRemoved(target);
+ }
SDK.targetManager.unobserveTargets(this);
- Components.Linkifier._instances.delete(this);
+ _instances.delete(this);
}
/**
@@ -294,35 +306,40 @@ Components.Linkifier = class {
* @param {!Bindings.LiveLocation} liveLocation
*/
_updateAnchor(anchor, liveLocation) {
- Components.Linkifier._unbindUILocation(anchor);
+ Linkifier._unbindUILocation(anchor);
const uiLocation = liveLocation.uiLocation();
- if (!uiLocation)
+ if (!uiLocation) {
return;
+ }
- Components.Linkifier._bindUILocation(anchor, uiLocation);
+ Linkifier._bindUILocation(anchor, uiLocation);
const text = uiLocation.linkText(true /* skipTrim */);
- Components.Linkifier._setTrimmedText(anchor, text, this._maxLength);
+ Linkifier._setTrimmedText(anchor, text, this._maxLength);
let titleText = uiLocation.uiSourceCode.url();
- if (typeof uiLocation.lineNumber === 'number')
+ if (typeof uiLocation.lineNumber === 'number') {
titleText += ':' + (uiLocation.lineNumber + 1);
+ }
anchor.title = titleText;
anchor.classList.toggle('webkit-html-blackbox-link', liveLocation.isBlackboxed());
- Components.Linkifier._updateLinkDecorations(anchor);
+ Linkifier._updateLinkDecorations(anchor);
}
/**
* @param {!Element} anchor
*/
static _updateLinkDecorations(anchor) {
- const info = Components.Linkifier._linkInfo(anchor);
- if (!info || !info.enableDecorator)
+ const info = Linkifier._linkInfo(anchor);
+ if (!info || !info.enableDecorator) {
return;
- if (!Components.Linkifier._decorator || !info.uiLocation)
+ }
+ if (!_decorator || !info.uiLocation) {
return;
- if (info.icon && info.icon.parentElement)
+ }
+ if (info.icon && info.icon.parentElement) {
anchor.removeChild(info.icon);
- const icon = Components.Linkifier._decorator.linkIcon(info.uiLocation.uiSourceCode);
+ }
+ const icon = _decorator.linkIcon(info.uiLocation.uiSourceCode);
if (icon) {
icon.style.setProperty('margin-right', '2px');
anchor.insertBefore(icon, anchor.firstChild);
@@ -350,15 +367,18 @@ Components.Linkifier = class {
}
let linkText = text || Bindings.displayNameForURL(url);
- if (typeof lineNumber === 'number' && !text)
+ if (typeof lineNumber === 'number' && !text) {
linkText += ':' + (lineNumber + 1);
+ }
const title = linkText !== url ? url : '';
- const link = Components.Linkifier._createLink(linkText, className, maxLength, title, url, preventClick);
- const info = Components.Linkifier._linkInfo(link);
- if (typeof lineNumber === 'number')
+ const link = Linkifier._createLink(linkText, className, maxLength, title, url, preventClick);
+ const info = Linkifier._linkInfo(link);
+ if (typeof lineNumber === 'number') {
info.lineNumber = lineNumber;
- if (typeof columnNumber === 'number')
+ }
+ if (typeof columnNumber === 'number') {
info.columnNumber = columnNumber;
+ }
return link;
}
@@ -369,8 +389,8 @@ Components.Linkifier = class {
* @return {!Element}
*/
static linkifyRevealable(revealable, text, fallbackHref) {
- const link = Components.Linkifier._createLink(text, '', UI.MaxLengthForDisplayedURLs, undefined, fallbackHref);
- Components.Linkifier._linkInfo(link).revealable = revealable;
+ const link = Linkifier._createLink(text, '', UI.MaxLengthForDisplayedURLs, undefined, fallbackHref);
+ Linkifier._linkInfo(link).revealable = revealable;
return link;
}
@@ -386,12 +406,14 @@ Components.Linkifier = class {
static _createLink(text, className, maxLength, title, href, preventClick) {
const link = createElementWithClass('span', className);
link.classList.add('devtools-link');
- if (title)
+ if (title) {
link.title = title;
- if (href)
+ }
+ if (href) {
link.href = href;
- Components.Linkifier._setTrimmedText(link, text, maxLength);
- link[Components.Linkifier._infoSymbol] = {
+ }
+ Linkifier._setTrimmedText(link, text, maxLength);
+ link[_infoSymbol] = {
icon: null,
enableDecorator: false,
uiLocation: null,
@@ -404,12 +426,14 @@ Components.Linkifier = class {
};
if (!preventClick) {
link.addEventListener('click', event => {
- if (Components.Linkifier._handleClick(event))
+ if (Linkifier._handleClick(event)) {
event.consume(true);
+ }
}, false);
link.addEventListener('keydown', event => {
- if (isEnterKey(event) && Components.Linkifier._handleClick(event))
+ if (isEnterKey(event) && Linkifier._handleClick(event)) {
event.consume(true);
+ }
}, false);
} else {
link.classList.add('devtools-link-prevent-click');
@@ -439,7 +463,7 @@ Components.Linkifier = class {
*/
function appendHiddenText(string) {
const ellipsisNode = link.createChild('span', 'devtools-link-ellipsis').createTextChild('\u2026');
- ellipsisNode[Components.Linkifier._untruncatedNodeTextSymbol] = string;
+ ellipsisNode[_untruncatedNodeTextSymbol] = string;
}
/**
@@ -471,8 +495,9 @@ Components.Linkifier = class {
rightIndex++;
leftIndex++;
}
- if (leftIndex > 0 && string.codePointAt(leftIndex - 1) >= 0x10000)
+ if (leftIndex > 0 && string.codePointAt(leftIndex - 1) >= 0x10000) {
leftIndex--;
+ }
return [string.substring(0, leftIndex), string.substring(leftIndex, rightIndex), string.substring(rightIndex)];
}
}
@@ -482,7 +507,7 @@ Components.Linkifier = class {
* @return {string}
*/
static untruncatedNodeText(node) {
- return node[Components.Linkifier._untruncatedNodeTextSymbol] || node.textContent;
+ return node[_untruncatedNodeTextSymbol] || node.textContent;
}
/**
@@ -490,7 +515,7 @@ Components.Linkifier = class {
* @return {?Components._LinkInfo}
*/
static _linkInfo(link) {
- return /** @type {?Components._LinkInfo} */ (link ? link[Components.Linkifier._infoSymbol] || null : null);
+ return /** @type {?Components._LinkInfo} */ (link ? link[_infoSymbol] || null : null);
}
/**
@@ -499,8 +524,17 @@ Components.Linkifier = class {
*/
static _handleClick(event) {
const link = /** @type {!Element} */ (event.currentTarget);
- if (UI.isBeingEdited(/** @type {!Node} */ (event.target)) || link.hasSelection())
+ if (UI.isBeingEdited(/** @type {!Node} */ (event.target)) || link.hasSelection()) {
return false;
+ }
+ return Components.Linkifier.invokeFirstAction(link);
+ }
+
+ /**
+ * @param {!Element} link
+ * @return {boolean}
+ */
+ static invokeFirstAction(link) {
const actions = Components.Linkifier._linkActions(link);
if (actions.length) {
actions[0].handler.call(null);
@@ -513,28 +547,27 @@ Components.Linkifier = class {
* @return {!Common.Setting}
*/
static _linkHandlerSetting() {
- if (!Components.Linkifier._linkHandlerSettingInstance) {
- Components.Linkifier._linkHandlerSettingInstance =
- Common.settings.createSetting('openLinkHandler', Common.UIString('auto'));
+ if (!Linkifier._linkHandlerSettingInstance) {
+ Linkifier._linkHandlerSettingInstance = Common.settings.createSetting('openLinkHandler', ls`auto`);
}
- return Components.Linkifier._linkHandlerSettingInstance;
+ return Linkifier._linkHandlerSettingInstance;
}
/**
* @param {string} title
- * @param {!Components.Linkifier.LinkHandler} handler
+ * @param {!Linkifier.LinkHandler} handler
*/
static registerLinkHandler(title, handler) {
- Components.Linkifier._linkHandlers.set(title, handler);
- self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._update();
+ _linkHandlers.set(title, handler);
+ self.runtime.sharedInstance(LinkHandlerSettingUI)._update();
}
/**
* @param {string} title
*/
static unregisterLinkHandler(title) {
- Components.Linkifier._linkHandlers.delete(title);
- self.runtime.sharedInstance(Components.Linkifier.LinkHandlerSettingUI)._update();
+ _linkHandlers.delete(title);
+ self.runtime.sharedInstance(LinkHandlerSettingUI)._update();
}
/**
@@ -542,7 +575,7 @@ Components.Linkifier = class {
* @return {?Workspace.UILocation}
*/
static uiLocation(link) {
- const info = Components.Linkifier._linkInfo(link);
+ const info = Linkifier._linkInfo(link);
return info ? info.uiLocation : null;
}
@@ -551,10 +584,11 @@ Components.Linkifier = class {
* @return {!Array<{title: string, handler: function()}>}
*/
static _linkActions(link) {
- const info = Components.Linkifier._linkInfo(link);
+ const info = Linkifier._linkInfo(link);
const result = [];
- if (!info)
+ if (!info) {
return result;
+ }
let url = '';
let uiLocation = null;
@@ -581,98 +615,69 @@ Components.Linkifier = class {
}
if (contentProvider) {
const lineNumber = uiLocation ? uiLocation.lineNumber : info.lineNumber || 0;
- for (const title of Components.Linkifier._linkHandlers.keys()) {
- const handler = Components.Linkifier._linkHandlers.get(title);
+ for (const title of _linkHandlers.keys()) {
+ const handler = _linkHandlers.get(title);
const action = {
section: 'reveal',
title: Common.UIString('Open using %s', title),
handler: handler.bind(null, contentProvider, lineNumber)
};
- if (title === Components.Linkifier._linkHandlerSetting().get())
+ if (title === Linkifier._linkHandlerSetting().get()) {
result.unshift(action);
- else
+ } else {
result.push(action);
+ }
}
}
if (resource || info.url) {
result.push({
section: 'reveal',
title: UI.openLinkExternallyLabel(),
- handler: () => InspectorFrontendHost.openInNewTab(url)
+ handler: () => Host.InspectorFrontendHost.openInNewTab(url)
+ });
+ result.push({
+ section: 'clipboard',
+ title: UI.copyLinkAddressLabel(),
+ handler: () => Host.InspectorFrontendHost.copyText(url)
});
- result.push(
- {section: 'clipboard', title: UI.copyLinkAddressLabel(), handler: () => InspectorFrontendHost.copyText(url)});
}
return result;
}
-};
+}
/** @type {!Set<!Components.Linkifier>} */
-Components.Linkifier._instances = new Set();
-/** @type {?Components.LinkDecorator} */
-Components.Linkifier._decorator = null;
+export const _instances = new Set();
-Components.Linkifier._sourceCodeAnchors = Symbol('Linkifier.anchors');
-Components.Linkifier._infoSymbol = Symbol('Linkifier.info');
-Components.Linkifier._untruncatedNodeTextSymbol = Symbol('Linkifier.untruncatedNodeText');
+/** @type {?LinkDecorator} */
+export let _decorator = null;
-/**
- * @typedef {{
- * icon: ?UI.Icon,
- * enableDecorator: boolean,
- * uiLocation: ?Workspace.UILocation,
- * liveLocation: ?Bindings.LiveLocation,
- * url: ?string,
- * lineNumber: ?number,
- * columnNumber: ?number,
- * revealable: ?Object,
- * fallback: ?Element
- * }}
- */
-Components._LinkInfo;
-
-/**
- * @typedef {{
- * text: (string|undefined),
- * className: (string|undefined),
- * lineNumber: (number|undefined),
- * columnNumber: (number|undefined),
- * preventClick: (boolean|undefined),
- * maxLength: (number|undefined)
- * }}
- */
-Components.LinkifyURLOptions;
+export const _sourceCodeAnchors = Symbol('Linkifier.anchors');
+export const _infoSymbol = Symbol('Linkifier.info');
+export const _untruncatedNodeTextSymbol = Symbol('Linkifier.untruncatedNodeText');
/**
* The maximum length before strings are considered too long for finding URLs.
* @const
* @type {number}
*/
-Components.Linkifier.MaxLengthToIgnoreLinkifier = 10000;
-
-/**
- * @typedef {function(!Common.ContentProvider, number)}
- */
-Components.Linkifier.LinkHandler;
+export const MaxLengthToIgnoreLinkifier = 10000;
-/** @type {!Map<string, !Components.Linkifier.LinkHandler>} */
-Components.Linkifier._linkHandlers = new Map();
+/** @type {!Map<string, !Linkifier.LinkHandler>} */
+export const _linkHandlers = new Map();
/**
* @extends {Common.EventTarget}
* @interface
*/
-Components.LinkDecorator = function() {};
-
-Components.LinkDecorator.prototype = {
+export class LinkDecorator {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {?UI.Icon}
*/
linkIcon(uiSourceCode) {}
-};
+}
-Components.LinkDecorator.Events = {
+LinkDecorator.Events = {
LinkIconChanged: Symbol('LinkIconChanged')
};
@@ -680,7 +685,7 @@ Components.LinkDecorator.Events = {
* @implements {UI.ContextMenu.Provider}
* @unrestricted
*/
-Components.Linkifier.LinkContextMenuProvider = class {
+export class LinkContextMenuProvider {
/**
* @override
* @param {!Event} event
@@ -689,20 +694,22 @@ Components.Linkifier.LinkContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, target) {
let targetNode = /** @type {!Node} */ (target);
- while (targetNode && !targetNode[Components.Linkifier._infoSymbol])
+ while (targetNode && !targetNode[_infoSymbol]) {
targetNode = targetNode.parentNodeOrShadowHost();
+ }
const link = /** @type {?Element} */ (targetNode);
- const actions = Components.Linkifier._linkActions(link);
- for (const action of actions)
+ const actions = Linkifier._linkActions(link);
+ for (const action of actions) {
contextMenu.section(action.section).appendItem(action.title, action.handler);
+ }
}
-};
+}
/**
* @implements {UI.SettingUI}
* @unrestricted
*/
-Components.Linkifier.LinkHandlerSettingUI = class {
+export class LinkHandlerSettingUI {
constructor() {
this._element = createElementWithClass('select', 'chrome-select');
this._element.addEventListener('change', this._onChange.bind(this), false);
@@ -711,12 +718,12 @@ Components.Linkifier.LinkHandlerSettingUI = class {
_update() {
this._element.removeChildren();
- const names = Components.Linkifier._linkHandlers.keysArray();
+ const names = _linkHandlers.keysArray();
names.unshift(Common.UIString('auto'));
for (const name of names) {
const option = createElement('option');
option.textContent = name;
- option.selected = name === Components.Linkifier._linkHandlerSetting().get();
+ option.selected = name === Linkifier._linkHandlerSetting().get();
this._element.appendChild(option);
}
this._element.disabled = names.length <= 1;
@@ -727,7 +734,7 @@ Components.Linkifier.LinkHandlerSettingUI = class {
*/
_onChange(event) {
const value = event.target.value;
- Components.Linkifier._linkHandlerSetting().set(value);
+ Linkifier._linkHandlerSetting().set(value);
}
/**
@@ -737,13 +744,13 @@ Components.Linkifier.LinkHandlerSettingUI = class {
settingElement() {
return UI.SettingsUI.createCustomSetting(Common.UIString('Link handling:'), this._element);
}
-};
+}
/**
* @implements {UI.ContextMenu.Provider}
* @unrestricted
*/
-Components.Linkifier.ContentProviderContextMenuProvider = class {
+export class ContentProviderContextMenuProvider {
/**
* @override
* @param {!Event} event
@@ -752,20 +759,83 @@ Components.Linkifier.ContentProviderContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, target) {
const contentProvider = /** @type {!Common.ContentProvider} */ (target);
- if (!contentProvider.contentURL())
+ if (!contentProvider.contentURL()) {
return;
+ }
contextMenu.revealSection().appendItem(
- UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(contentProvider.contentURL()));
- for (const title of Components.Linkifier._linkHandlers.keys()) {
- const handler = Components.Linkifier._linkHandlers.get(title);
+ UI.openLinkExternallyLabel(), () => Host.InspectorFrontendHost.openInNewTab(contentProvider.contentURL()));
+ for (const title of _linkHandlers.keys()) {
+ const handler = _linkHandlers.get(title);
contextMenu.revealSection().appendItem(
Common.UIString('Open using %s', title), handler.bind(null, contentProvider, 0));
}
- if (contentProvider instanceof SDK.NetworkRequest)
+ if (contentProvider instanceof SDK.NetworkRequest) {
return;
+ }
contextMenu.clipboardSection().appendItem(
- UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(contentProvider.contentURL()));
+ UI.copyLinkAddressLabel(), () => Host.InspectorFrontendHost.copyText(contentProvider.contentURL()));
}
-};
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+/** @constructor */
+Components.Linkifier = Linkifier;
+
+Components.Linkifier._instances = _instances;
+Components.Linkifier._decorator = _decorator;
+Components.Linkifier._sourceCodeAnchors = _sourceCodeAnchors;
+Components.Linkifier._infoSymbol = _infoSymbol;
+Components.Linkifier._untruncatedNodeTextSymbol = _untruncatedNodeTextSymbol;
+Components.Linkifier.MaxLengthToIgnoreLinkifier = MaxLengthToIgnoreLinkifier;
+Components.Linkifier._linkHandlers = _linkHandlers;
+
+/** @constructor */
+Components.Linkifier.LinkContextMenuProvider = LinkContextMenuProvider;
+
+/** @constructor */
+Components.Linkifier.LinkHandlerSettingUI = LinkHandlerSettingUI;
+
+/** @constructor */
+Components.Linkifier.ContentProviderContextMenuProvider = ContentProviderContextMenuProvider;
+
+/** @interface */
+Components.LinkDecorator = LinkDecorator;
+
+/**
+ * @typedef {{
+ * icon: ?UI.Icon,
+ * enableDecorator: boolean,
+ * uiLocation: ?Workspace.UILocation,
+ * liveLocation: ?Bindings.LiveLocation,
+ * url: ?string,
+ * lineNumber: ?number,
+ * columnNumber: ?number,
+ * revealable: ?Object,
+ * fallback: ?Element
+ * }}
+ */
+Components._LinkInfo;
+
+/**
+ * @typedef {{
+ * text: (string|undefined),
+ * className: (string|undefined),
+ * lineNumber: (number|undefined),
+ * columnNumber: (number|undefined),
+ * preventClick: (boolean|undefined),
+ * maxLength: (number|undefined)
+ * }}
+ */
+Components.LinkifyURLOptions;
+
+/**
+ * @typedef {function(!Common.ContentProvider, number)}
+ */
+Components.Linkifier.LinkHandler; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/Reload.js b/chromium/third_party/blink/renderer/devtools/front_end/components/Reload.js
index 105f5c970a8..e3e1f84552d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/Reload.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/Reload.js
@@ -1,9 +1,19 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Components.reload = function() {
+
+export function reload() {
if (Components.dockController.canDock() &&
- Components.dockController.dockSide() === Components.DockController.State.Undocked)
- InspectorFrontendHost.setIsDocked(true, function() {});
+ Components.dockController.dockSide() === Components.DockController.State.Undocked) {
+ Host.InspectorFrontendHost.setIsDocked(true, function() {});
+ }
window.location.reload();
-};
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+Components.reload = reload;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/TargetDetachedDialog.js b/chromium/third_party/blink/renderer/devtools/front_end/components/TargetDetachedDialog.js
index 234e7dfadc2..cca1fcafcfa 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/TargetDetachedDialog.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/TargetDetachedDialog.js
@@ -5,18 +5,19 @@
/**
* @implements {Protocol.InspectorDispatcher}
*/
-Components.TargetDetachedDialog = class extends SDK.SDKModel {
+export default class TargetDetachedDialog extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
- if (target.parentTarget())
+ if (target.parentTarget()) {
return;
+ }
target.registerInspectorDispatcher(this);
target.inspectorAgent().enable();
this._hideCrashedDialog = null;
- Components.TargetDetachedDialog._disconnectedScreenWithReasonWasShown = false;
+ TargetDetachedDialog._disconnectedScreenWithReasonWasShown = false;
}
/**
@@ -24,7 +25,7 @@ Components.TargetDetachedDialog = class extends SDK.SDKModel {
* @param {string} reason
*/
detached(reason) {
- Components.TargetDetachedDialog._disconnectedScreenWithReasonWasShown = true;
+ TargetDetachedDialog._disconnectedScreenWithReasonWasShown = true;
UI.RemoteDebuggingTerminatedScreen.show(reason);
}
@@ -55,6 +56,15 @@ Components.TargetDetachedDialog = class extends SDK.SDKModel {
this._hideCrashedDialog = null;
}
}
-};
+}
+
+/* Legacy exported object */
+self.Components = self.Components || {};
+
+/* Legacy exported object */
+Components = Components || {};
+
+/** @constructor */
+Components.TargetDetachedDialog = TargetDetachedDialog;
-SDK.SDKModel.register(Components.TargetDetachedDialog, SDK.Target.Capability.Inspector, true);
+SDK.SDKModel.register(TargetDetachedDialog, SDK.Target.Capability.Inspector, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/components.js b/chromium/third_party/blink/renderer/devtools/front_end/components/components.js
new file mode 100644
index 00000000000..15198040125
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/components.js
@@ -0,0 +1,19 @@
+// 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 * as DockController from './DockController.js';
+import * as ImagePreview from './ImagePreview.js';
+import * as JSPresentationUtils from './JSPresentationUtils.js';
+import * as Linkifier from './Linkifier.js';
+import * as Reload from './Reload.js';
+import * as TargetDetachedDialog from './TargetDetachedDialog.js';
+
+export {
+ DockController,
+ ImagePreview,
+ JSPresentationUtils,
+ Linkifier,
+ Reload,
+ TargetDetachedDialog,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
index 01189afd627..bf9098fd9e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/components_strings.grdp
@@ -3,14 +3,11 @@
<message name="IDS_DEVTOOLS_013cf261f9ccf5d4f027bc001d0d1d0c" desc="Text in Linkifier">
(unknown)
</message>
- <message name="IDS_DEVTOOLS_0b484cfcf50c8fabff48c0aad426f544" desc="Text in Dock Controller">
- Dock to left
- </message>
<message name="IDS_DEVTOOLS_131c97f8ba5bc0277386d660a18f13b6" desc="Text in Linkifier">
Reveal in <ph name="DESTINATION">$1s<ex>Sources panel</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_393c3f5ea8ad35c02691d507bdbb31b0" desc="Text in Linkifier">
- Reveal
+ <message name="IDS_DEVTOOLS_3b9e0551f1ed4b83f205b7f1d26dde5c" desc="Alt text description of an image's source">
+ unknown source
</message>
<message name="IDS_DEVTOOLS_7f52f5f786eb8d9bf9e56ce89fb3db3a" desc="Show all link text content in JSPresentation Utils">
Show 1 more frame
@@ -18,27 +15,12 @@
<message name="IDS_DEVTOOLS_908ae571a925e675f5c55619aa16a99b" desc="Description in Image Preview">
<ph name="RENDEREDWIDTH">$1s<ex>500</ex></ph> × <ph name="RENDEREDHEIGHT">$2s<ex>300</ex></ph> pixels (intrinsic: <ph name="INTRINSICWIDTH">$3s<ex>200</ex></ph> × <ph name="INTRINSICHEIGHT">$4s<ex>100</ex></ph> pixels)
</message>
- <message name="IDS_DEVTOOLS_93898e12951c906e5286ccb36d980ce5" desc="A context menu item in the JSPresentation Utils">
- Blackbox script
- </message>
- <message name="IDS_DEVTOOLS_9df22f196a33acd0b372fe502de51211" desc="Text in Linkifier">
- auto
- </message>
<message name="IDS_DEVTOOLS_a498f0751d1221223efb0defc71cc804" desc="Description in Image Preview">
<ph name="RENDEREDWIDTH">$1s<ex>500</ex></ph> × <ph name="RENDEREDHEIGHT">$2s<ex>500</ex></ph> pixels
</message>
- <message name="IDS_DEVTOOLS_b9dee6bade160c89fb7f0e539d453513" desc="Text in Dock Controller">
- Dock to bottom
- </message>
- <message name="IDS_DEVTOOLS_c3fe109bf99ade2d76a55e5737015e3e" desc="A context menu item in the JSPresentation Utils">
- Stop blackboxing
- </message>
<message name="IDS_DEVTOOLS_c850ae12703fa2b00eeaf8445ecf00ef" desc="Show all link text content in JSPresentation Utils">
Show <ph name="TOTALHIDDENCALLFRAMESCOUNT">$1s<ex>2</ex></ph> more frames
</message>
- <message name="IDS_DEVTOOLS_d3d2e617335f08df83599665eef8a418" desc="Tooltip text that appears when hovering over the largeicon delete button in the Dock Controller">
- Close
- </message>
<message name="IDS_DEVTOOLS_e3de40c656e1189770049db9846b69df" desc="Text on the remote debugging window to indicate the connection is lost">
WebSocket disconnected
</message>
@@ -48,10 +30,4 @@
<message name="IDS_DEVTOOLS_e6cd0f8a4fe4fb9e08505b784e48caa2" desc="Text in Linkifier">
Link handling:
</message>
- <message name="IDS_DEVTOOLS_f53944c3a55bdb5ad65c6226e358a626" desc="Text in Dock Controller">
- Undock into separate window
- </message>
- <message name="IDS_DEVTOOLS_fe7fb037b290768d6a6be30b237e183d" desc="Text in Dock Controller">
- Dock to right
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/components/module.json b/chromium/third_party/blink/renderer/devtools/front_end/components/module.json
index b7b5ca9282e..77489e05707 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/components/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/components/module.json
@@ -4,7 +4,9 @@
"platform",
"ui"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "components.js",
"JSPresentationUtils.js",
"DockController.js",
"ImagePreview.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
index 8252942bb92..556009427a5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
@@ -57,13 +57,16 @@ Console.ConsoleContextSelector = class {
SDK.OverlayModel.hideDOMNodeHighlight();
if (to && to.frameId) {
const overlayModel = to.target().model(SDK.OverlayModel);
- if (overlayModel)
+ if (overlayModel) {
overlayModel.highlightFrame(to.frameId);
+ }
}
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('highlighted');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('highlighted');
+ }
}
/**
@@ -77,8 +80,9 @@ Console.ConsoleContextSelector = class {
if (executionContext.frameId) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
const frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
- if (frame)
+ if (frame) {
label = label || frame.displayName();
+ }
}
label = label || executionContext.origin;
@@ -92,8 +96,9 @@ Console.ConsoleContextSelector = class {
_depthFor(executionContext) {
let target = executionContext.target();
let depth = 0;
- if (!executionContext.isDefault)
+ if (!executionContext.isDefault) {
depth++;
+ }
if (executionContext.frameId) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
let frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
@@ -120,12 +125,14 @@ Console.ConsoleContextSelector = class {
* @return {?Element}
*/
_badgeFor(executionContext) {
- if (!executionContext.frameId || !executionContext.isDefault)
+ if (!executionContext.frameId || !executionContext.isDefault) {
return null;
+ }
const resourceTreeModel = executionContext.target().model(SDK.ResourceTreeModel);
const frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
- if (!frame)
+ if (!frame) {
return null;
+ }
const badgePool = new ProductRegistry.BadgePool();
this._badgePoolForExecutionContext.set(executionContext, badgePool);
return badgePool.badgeForFrame(frame);
@@ -136,8 +143,9 @@ Console.ConsoleContextSelector = class {
*/
_disposeExecutionContextBadge(executionContext) {
const badgePool = this._badgePoolForExecutionContext.get(executionContext);
- if (!badgePool)
+ if (!badgePool) {
return;
+ }
badgePool.reset();
this._badgePoolForExecutionContext.delete(executionContext);
}
@@ -148,8 +156,9 @@ Console.ConsoleContextSelector = class {
_executionContextCreated(executionContext) {
this._items.insertWithComparator(executionContext, executionContext.runtimeModel.executionContextComparator());
- if (executionContext === UI.context.flavor(SDK.ExecutionContext))
+ if (executionContext === UI.context.flavor(SDK.ExecutionContext)) {
this._dropDown.selectItem(executionContext);
+ }
}
/**
@@ -165,8 +174,9 @@ Console.ConsoleContextSelector = class {
*/
_onExecutionContextChanged(event) {
const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
- if (this._items.indexOf(executionContext) === -1)
+ if (this._items.indexOf(executionContext) === -1) {
return;
+ }
this._executionContextDestroyed(executionContext);
this._executionContextCreated(executionContext);
}
@@ -176,8 +186,9 @@ Console.ConsoleContextSelector = class {
*/
_executionContextDestroyed(executionContext) {
const index = this._items.indexOf(executionContext);
- if (index === -1)
+ if (index === -1) {
return;
+ }
this._disposeExecutionContextBadge(executionContext);
this._items.remove(index);
}
@@ -203,13 +214,15 @@ Console.ConsoleContextSelector = class {
* @return {boolean}
*/
_isTopContext(executionContext) {
- if (!executionContext || !executionContext.isDefault)
+ if (!executionContext || !executionContext.isDefault) {
return false;
+ }
const resourceTreeModel = executionContext.target().model(SDK.ResourceTreeModel);
const frame =
executionContext.frameId && resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
- if (!frame)
+ if (!frame) {
return false;
+ }
return frame.isTopFrame();
}
@@ -234,8 +247,9 @@ Console.ConsoleContextSelector = class {
*/
modelRemoved(runtimeModel) {
for (let i = this._items.length - 1; i >= 0; i--) {
- if (this._items.at(i).runtimeModel === runtimeModel)
+ if (this._items.at(i).runtimeModel === runtimeModel) {
this._executionContextDestroyed(this._items.at(i));
+ }
}
}
@@ -248,7 +262,7 @@ Console.ConsoleContextSelector = class {
const element = createElementWithClass('div');
const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'console/consoleContextSelector.css');
const title = shadowRoot.createChild('div', 'title');
- title.createTextChild(this.titleFor(item).trimEnd(100));
+ title.createTextChild(this.titleFor(item).trimEndWithMaxLength(100));
const subTitle = shadowRoot.createChild('div', 'subtitle');
const badgeElement = this._badgeFor(item);
if (badgeElement) {
@@ -271,18 +285,21 @@ Console.ConsoleContextSelector = class {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
}
- if (executionContext.origin.startsWith('chrome-extension://'))
+ if (executionContext.origin.startsWith('chrome-extension://')) {
return Common.UIString('Extension');
+ }
if (!frame || !frame.parentFrame || frame.parentFrame.securityOrigin !== executionContext.origin) {
const url = executionContext.origin.asParsedURL();
- if (url)
+ if (url) {
return url.domain();
+ }
}
if (frame) {
const callFrame = frame.findCreationCallFrame(callFrame => !!callFrame.url);
- if (callFrame)
+ if (callFrame) {
return new Common.ParsedURL(callFrame.url).domain();
+ }
return Common.UIString('IFrame');
}
return '';
@@ -313,8 +330,9 @@ Console.ConsoleContextSelector = class {
_callFrameSelectedInUI() {
const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
const callFrameContext = callFrame && callFrame.script.executionContext();
- if (callFrameContext)
+ if (callFrameContext) {
UI.context.setFlavor(SDK.ExecutionContext, callFrameContext);
+ }
}
/**
@@ -336,8 +354,9 @@ Console.ConsoleContextSelector = class {
_frameNavigated(event) {
const frame = /** @type {!SDK.ResourceTreeFrame} */ (event.data);
const runtimeModel = frame.resourceTreeModel().target().model(SDK.RuntimeModel);
- if (!runtimeModel)
+ if (!runtimeModel) {
return;
+ }
for (const executionContext of runtimeModel.executionContexts()) {
if (frame.id === executionContext.frameId) {
this._disposeExecutionContextBadge(executionContext);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleFilter.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleFilter.js
index 5a867497c08..bb8b8a98ed2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleFilter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleFilter.js
@@ -21,8 +21,9 @@ Console.ConsoleFilter = class {
*/
static allLevelsFilterValue() {
const result = {};
- for (const name of Object.values(SDK.ConsoleMessage.MessageLevel))
+ for (const name of Object.values(SDK.ConsoleMessage.MessageLevel)) {
result[name] = true;
+ }
return result;
}
@@ -62,39 +63,47 @@ Console.ConsoleFilter = class {
const message = viewMessage.consoleMessage();
if (this.executionContext &&
(this.executionContext.runtimeModel !== message.runtimeModel() ||
- this.executionContext.id !== message.executionContextId))
+ this.executionContext.id !== message.executionContextId)) {
return false;
+ }
if (message.type === SDK.ConsoleMessage.MessageType.Command ||
- message.type === SDK.ConsoleMessage.MessageType.Result || message.isGroupMessage())
+ message.type === SDK.ConsoleMessage.MessageType.Result || message.isGroupMessage()) {
return true;
+ }
- if (message.level && !this.levelsMask[/** @type {string} */ (message.level)])
+ if (message.level && !this.levelsMask[/** @type {string} */ (message.level)]) {
return false;
+ }
for (const filter of this.parsedFilters) {
if (!filter.key) {
- if (filter.regex && viewMessage.matchesFilterRegex(filter.regex) === filter.negative)
+ if (filter.regex && viewMessage.matchesFilterRegex(filter.regex) === filter.negative) {
return false;
- if (filter.text && viewMessage.matchesFilterText(filter.text) === filter.negative)
+ }
+ if (filter.text && viewMessage.matchesFilterText(filter.text) === filter.negative) {
return false;
+ }
} else {
switch (filter.key) {
case Console.ConsoleFilter.FilterType.Context:
- if (!passesFilter(filter, message.context, false /* exactMatch */))
+ if (!passesFilter(filter, message.context, false /* exactMatch */)) {
return false;
+ }
break;
case Console.ConsoleFilter.FilterType.Source:
const sourceNameForMessage = message.source ?
SDK.ConsoleMessage.MessageSourceDisplayName.get(
/** @type {!SDK.ConsoleMessage.MessageSource} */ (message.source)) :
message.source;
- if (!passesFilter(filter, sourceNameForMessage, true /* exactMatch */))
+ if (!passesFilter(filter, sourceNameForMessage, true /* exactMatch */)) {
return false;
+ }
break;
case Console.ConsoleFilter.FilterType.Url:
- if (!passesFilter(filter, message.url, false /* exactMatch */))
+ if (!passesFilter(filter, message.url, false /* exactMatch */)) {
return false;
+ }
break;
}
}
@@ -108,16 +117,20 @@ Console.ConsoleFilter = class {
* @return {boolean}
*/
function passesFilter(filter, value, exactMatch) {
- if (!filter.text)
+ if (!filter.text) {
return !!value === filter.negative;
- if (!value)
+ }
+ if (!value) {
return !filter.text === !filter.negative;
+ }
const filterText = /** @type {string} */ (filter.text).toLowerCase();
const lowerCaseValue = value.toLowerCase();
- if (exactMatch && (lowerCaseValue === filterText) === filter.negative)
+ if (exactMatch && (lowerCaseValue === filterText) === filter.negative) {
return false;
- if (!exactMatch && lowerCaseValue.includes(filterText) === filter.negative)
+ }
+ if (!exactMatch && lowerCaseValue.includes(filterText) === filter.negative) {
return false;
+ }
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePanel.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePanel.js
index 9a16cf09666..c55d02961ff 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePanel.js
@@ -53,8 +53,9 @@ Console.ConsolePanel = class extends UI.Panel {
wasShown() {
super.wasShown();
const wrapper = Console.ConsolePanel.WrapperView._instance;
- if (wrapper && wrapper.isShowing())
+ if (wrapper && wrapper.isShowing()) {
UI.inspectorView.setDrawerMinimized(true);
+ }
this._view.show(this.element);
Console.ConsolePanel._updateContextFlavor();
}
@@ -67,8 +68,9 @@ Console.ConsolePanel = class extends UI.Panel {
// The minimized drawer has 0 height, and showing Console inside may set
// Console's scrollTop to 0. Unminimize before calling show to avoid this.
UI.inspectorView.setDrawerMinimized(false);
- if (Console.ConsolePanel.WrapperView._instance)
+ if (Console.ConsolePanel.WrapperView._instance) {
Console.ConsolePanel.WrapperView._instance._showViewInWrapper();
+ }
Console.ConsolePanel._updateContextFlavor();
}
@@ -98,10 +100,11 @@ Console.ConsolePanel.WrapperView = class extends UI.VBox {
* @override
*/
wasShown() {
- if (!Console.ConsolePanel.instance().isShowing())
+ if (!Console.ConsolePanel.instance().isShowing()) {
this._showViewInWrapper();
- else
+ } else {
UI.inspectorView.setDrawerMinimized(true);
+ }
Console.ConsolePanel._updateContextFlavor();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
index 7367b0273f4..3024e3cd7c8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
@@ -13,16 +13,18 @@ Console.ConsolePinPane = class extends UI.ThrottledWidget {
/** @type {!Set<!Console.ConsolePin>} */
this._pins = new Set();
this._pinsSetting = Common.settings.createLocalSetting('consolePins', []);
- for (const expression of this._pinsSetting.get())
+ for (const expression of this._pinsSetting.get()) {
this.addPin(expression);
+ }
}
/**
* @override
*/
willHide() {
- for (const pin of this._pins)
+ for (const pin of this._pins) {
pin.setHovered(false);
+ }
}
_savePins() {
@@ -50,8 +52,9 @@ Console.ConsolePinPane = class extends UI.ThrottledWidget {
}
_removeAllPins() {
- for (const pin of this._pins)
+ for (const pin of this._pins) {
this._removePin(pin);
+ }
}
/**
@@ -72,8 +75,9 @@ Console.ConsolePinPane = class extends UI.ThrottledWidget {
this.contentElement.appendChild(pin.element());
this._pins.add(pin);
this._savePins();
- if (userGesture)
+ if (userGesture) {
pin.focus();
+ }
this.update();
}
@@ -81,10 +85,12 @@ Console.ConsolePinPane = class extends UI.ThrottledWidget {
* @override
*/
doUpdate() {
- if (!this._pins.size || !this.isShowing())
+ if (!this._pins.size || !this.isShowing()) {
return Promise.resolve();
- if (this.isShowing())
+ }
+ if (this.isShowing()) {
this.update();
+ }
const updatePromises = Array.from(this._pins, pin => pin.updatePreview());
return Promise.all(updatePromises).then(this._updatedForTest.bind(this));
}
@@ -101,7 +107,7 @@ Console.ConsolePin = class extends Common.Object {
constructor(expression, pinPane) {
super();
const deletePinIcon = UI.Icon.create('smallicon-cross', 'console-delete-pin');
- onInvokeElement(deletePinIcon, () => pinPane._removePin(this));
+ self.onInvokeElement(deletePinIcon, () => pinPane._removePin(this));
deletePinIcon.tabIndex = 0;
UI.ARIAUtils.setAccessibleName(deletePinIcon, ls`Remove expression`);
UI.ARIAUtils.markAsButton(deletePinIcon);
@@ -157,14 +163,16 @@ Console.ConsolePin = class extends Common.Object {
event.consume();
return;
}
- if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code)
+ if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code) {
this._editor.setText(this._committedExpression);
+ }
}, true);
this._editor.widget().element.addEventListener('focusout', event => {
const text = this._editor.text();
const trimmedText = text.trim();
- if (text.length !== trimmedText.length)
+ if (text.length !== trimmedText.length) {
this._editor.setText(trimmedText);
+ }
this._committedExpression = trimmedText;
pinPane._savePins();
this._editor.setSelection(TextUtils.TextRange.createFromLocation(Infinity, Infinity));
@@ -176,11 +184,13 @@ Console.ConsolePin = class extends Common.Object {
* @param {boolean} hovered
*/
setHovered(hovered) {
- if (this._hovered === hovered)
+ if (this._hovered === hovered) {
return;
+ }
this._hovered = hovered;
- if (!hovered && this._lastNode)
+ if (!hovered && this._lastNode) {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
}
/**
@@ -218,8 +228,9 @@ Console.ConsolePin = class extends Common.Object {
* @return {!Promise}
*/
async updatePreview() {
- if (!this._editor)
+ if (!this._editor) {
return;
+ }
const text = this._editor.textWithCurrentSuggestion().trim();
const isEditing = this._pinElement.hasFocus();
const throwOnSideEffect = isEditing && text !== this._committedExpression;
@@ -227,8 +238,9 @@ Console.ConsolePin = class extends Common.Object {
const executionContext = UI.context.flavor(SDK.ExecutionContext);
const {preview, result} = await ObjectUI.JavaScriptREPL.evaluateAndBuildPreview(
text, throwOnSideEffect, timeout, !isEditing /* allowErrors */, 'console');
- if (this._lastResult && this._lastExecutionContext)
+ if (this._lastResult && this._lastExecutionContext) {
this._lastExecutionContext.runtimeModel.releaseEvaluationResult(this._lastResult);
+ }
this._lastResult = result || null;
this._lastExecutionContext = executionContext || null;
@@ -248,18 +260,20 @@ Console.ConsolePin = class extends Common.Object {
}
let node = null;
- if (result && result.object && result.object.type === 'object' && result.object.subtype === 'node')
+ if (result && result.object && result.object.type === 'object' && result.object.subtype === 'node') {
node = result.object;
+ }
if (this._hovered) {
- if (node)
+ if (node) {
SDK.OverlayModel.highlightObjectAsDOMNode(node);
- else if (this._lastNode)
+ } else if (this._lastNode) {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
}
this._lastNode = node || null;
const isError = result && result.exceptionDetails && !SDK.RuntimeModel.isSideEffectFailure(result);
- this._pinElement.classList.toggle('error-level', isError);
+ this._pinElement.classList.toggle('error-level', !!isError);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
index 80299e5f8b1..3be491f5c3a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -67,8 +67,9 @@ Console.ConsolePrompt = class extends UI.Widget {
this.setText(this._initialText);
delete this._initialText;
- if (this.hasFocus())
+ if (this.hasFocus()) {
this.focus();
+ }
this.element.removeAttribute('tabindex');
this._editor.widget().element.tabIndex = -1;
@@ -82,8 +83,9 @@ Console.ConsolePrompt = class extends UI.Widget {
_eagerSettingChanged() {
const enabled = this._eagerEvalSetting.get();
this._eagerPreviewElement.classList.toggle('hidden', !enabled);
- if (enabled)
+ if (enabled) {
this._requestPreview();
+ }
}
/**
@@ -113,8 +115,9 @@ Console.ConsolePrompt = class extends UI.Widget {
const {preview, result} =
await ObjectUI.JavaScriptREPL.evaluateAndBuildPreview(text, true /* throwOnSideEffect */, 500);
this._innerPreviewElement.removeChildren();
- if (preview.deepTextContent() !== this._editor.textWithCurrentSuggestion().trim())
+ if (preview.deepTextContent() !== this._editor.textWithCurrentSuggestion().trim()) {
this._innerPreviewElement.appendChild(preview);
+ }
if (result && result.object && result.object.subtype === 'node') {
this._highlightingNode = true;
SDK.OverlayModel.highlightObjectAsDOMNode(result.object);
@@ -122,8 +125,9 @@ Console.ConsolePrompt = class extends UI.Widget {
this._highlightingNode = false;
SDK.OverlayModel.hideDOMNodeHighlight();
}
- if (result)
+ if (result) {
executionContext.runtimeModel.releaseEvaluationResult(result);
+ }
}
/**
@@ -144,8 +148,9 @@ Console.ConsolePrompt = class extends UI.Widget {
}
clearAutocomplete() {
- if (this._editor)
+ if (this._editor) {
this._editor.clearAutocomplete();
+ }
}
/**
@@ -156,18 +161,20 @@ Console.ConsolePrompt = class extends UI.Widget {
}
moveCaretToEndOfPrompt() {
- if (this._editor)
+ if (this._editor) {
this._editor.setSelection(TextUtils.TextRange.createFromLocation(Infinity, Infinity));
+ }
}
/**
* @param {string} text
*/
setText(text) {
- if (this._editor)
+ if (this._editor) {
this._editor.setText(text);
- else
+ } else {
this._initialText = text;
+ }
this.dispatchEventToListeners(Console.ConsolePrompt.Events.TextChanged);
}
@@ -199,16 +206,18 @@ Console.ConsolePrompt = class extends UI.Widget {
switch (keyboardEvent.keyCode) {
case UI.KeyboardShortcut.Keys.Up.code:
const startY = this._editor.visualCoordinates(0, 0).y;
- if (keyboardEvent.shiftKey || !selection.isEmpty() || cursorY !== startY)
+ if (keyboardEvent.shiftKey || !selection.isEmpty() || cursorY !== startY) {
break;
+ }
newText = this._history.previous(this.text());
isPrevious = true;
break;
case UI.KeyboardShortcut.Keys.Down.code:
const fullRange = this._editor.fullRange();
const endY = this._editor.visualCoordinates(fullRange.endLine, fullRange.endColumn).y;
- if (keyboardEvent.shiftKey || !selection.isEmpty() || cursorY !== endY)
+ if (keyboardEvent.shiftKey || !selection.isEmpty() || cursorY !== endY) {
break;
+ }
newText = this._history.next();
break;
case UI.KeyboardShortcut.Keys.P.code: // Ctrl+P = Previous
@@ -220,35 +229,40 @@ Console.ConsolePrompt = class extends UI.Widget {
break;
case UI.KeyboardShortcut.Keys.N.code: // Ctrl+N = Next
if (Host.isMac() && keyboardEvent.ctrlKey && !keyboardEvent.metaKey && !keyboardEvent.altKey &&
- !keyboardEvent.shiftKey)
+ !keyboardEvent.shiftKey) {
newText = this._history.next();
+ }
break;
case UI.KeyboardShortcut.Keys.Enter.code:
this._enterKeyPressed(keyboardEvent);
break;
case UI.KeyboardShortcut.Keys.Tab.code:
- if (!this.text())
+ if (!this.text()) {
keyboardEvent.consume();
+ }
break;
}
- if (newText === undefined)
+ if (newText === undefined) {
return;
+ }
keyboardEvent.consume(true);
this.setText(newText);
- if (isPrevious)
+ if (isPrevious) {
this._editor.setSelection(TextUtils.TextRange.createFromLocation(0, Infinity));
- else
+ } else {
this.moveCaretToEndOfPrompt();
+ }
}
/**
* @return {!Promise<boolean>}
*/
async _enterWillEvaluate() {
- if (!this._isCaretAtEndOfPrompt())
+ if (!this._isCaretAtEndOfPrompt()) {
return true;
+ }
return await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(this.text());
}
@@ -263,8 +277,9 @@ Console.ConsolePrompt = class extends UI.Widget {
* @param {!KeyboardEvent} event
*/
async _enterKeyPressed(event) {
- if (event.altKey || event.ctrlKey || event.shiftKey)
+ if (event.altKey || event.ctrlKey || event.shiftKey) {
return;
+ }
event.consume(true);
@@ -273,13 +288,15 @@ Console.ConsolePrompt = class extends UI.Widget {
this.clearAutocomplete();
const str = this.text();
- if (!str.length)
+ if (!str.length) {
return;
+ }
- if (await this._enterWillEvaluate())
+ if (await this._enterWillEvaluate()) {
await this._appendCommand(str, true);
- else
+ } else {
this._editor.newlineAndIndent();
+ }
this._enterProcessedForTest();
}
@@ -297,8 +314,9 @@ Console.ConsolePrompt = class extends UI.Widget {
SDK.consoleModel.evaluateCommandInConsole(
executionContext, message, wrappedResult.text, useCommandLineAPI,
/* awaitPromise */ wrappedResult.preprocessed);
- if (Console.ConsolePanel.instance().isShowing())
+ if (Console.ConsolePanel.instance().isShowing()) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.CommandEvaluatedInConsolePanel);
+ }
}
}
@@ -312,17 +330,20 @@ Console.ConsolePrompt = class extends UI.Widget {
*/
_historyCompletions(prefix, force) {
const text = this.text();
- if (!this._addCompletionsFromHistory || !this._isCaretAtEndOfPrompt() || (!text && !force))
+ if (!this._addCompletionsFromHistory || !this._isCaretAtEndOfPrompt() || (!text && !force)) {
return [];
+ }
const result = [];
const set = new Set();
const data = this._history.historyData();
for (let i = data.length - 1; i >= 0 && result.length < 50; --i) {
const item = data[i];
- if (!item.startsWith(text))
+ if (!item.startsWith(text)) {
continue;
- if (set.has(item))
+ }
+ if (set.has(item)) {
continue;
+ }
set.add(item);
result.push(
{text: item.substring(text.length - prefix.length), iconType: 'smallicon-text-prompt', isSecondary: true});
@@ -334,10 +355,11 @@ Console.ConsolePrompt = class extends UI.Widget {
* @override
*/
focus() {
- if (this._editor)
+ if (this._editor) {
this._editor.widget().focus();
- else
+ } else {
this.element.focus();
+ }
}
/**
@@ -400,8 +422,9 @@ Console.ConsoleHistoryManager = class {
}
this._historyOffset = 1;
- if (text === this._currentHistoryItem())
+ if (text === this._currentHistoryItem()) {
return;
+ }
this._data.push(text);
}
@@ -410,8 +433,9 @@ Console.ConsoleHistoryManager = class {
* @param {string} currentText
*/
_pushCurrentText(currentText) {
- if (this._uncommittedIsTop)
- this._data.pop(); // Throw away obsolete uncommitted text.
+ if (this._uncommittedIsTop) {
+ this._data.pop();
+ } // Throw away obsolete uncommitted text.
this._uncommittedIsTop = true;
this._data.push(currentText);
}
@@ -421,10 +445,12 @@ Console.ConsoleHistoryManager = class {
* @return {string|undefined}
*/
previous(currentText) {
- if (this._historyOffset > this._data.length)
+ if (this._historyOffset > this._data.length) {
return undefined;
- if (this._historyOffset === 1)
+ }
+ if (this._historyOffset === 1) {
this._pushCurrentText(currentText);
+ }
++this._historyOffset;
return this._currentHistoryItem();
}
@@ -433,8 +459,9 @@ Console.ConsoleHistoryManager = class {
* @return {string|undefined}
*/
next() {
- if (this._historyOffset === 1)
+ if (this._historyOffset === 1) {
return undefined;
+ }
--this._historyOffset;
return this._currentHistoryItem();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleSidebar.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleSidebar.js
index 8154fb9fb2e..dfd1b389c5f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleSidebar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleSidebar.js
@@ -27,23 +27,23 @@ Console.ConsoleSidebar = class extends UI.VBox {
negative: false
}];
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.All, [], Console.ConsoleFilter.allLevelsFilterValue(),
+ Console.ConsoleSidebar._groupName.All, [], Console.ConsoleFilter.allLevelsFilterValue(),
UI.Icon.create('mediumicon-list'), badgePool, selectedFilterSetting);
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.ConsoleAPI, consoleAPIParsedFilters,
+ Console.ConsoleSidebar._groupName.ConsoleAPI, consoleAPIParsedFilters,
Console.ConsoleFilter.allLevelsFilterValue(), UI.Icon.create('mediumicon-account-circle'), badgePool,
selectedFilterSetting);
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.Error, [], Console.ConsoleFilter.singleLevelMask(Levels.Error),
+ Console.ConsoleSidebar._groupName.Error, [], Console.ConsoleFilter.singleLevelMask(Levels.Error),
UI.Icon.create('mediumicon-error-circle'), badgePool, selectedFilterSetting);
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.Warning, [], Console.ConsoleFilter.singleLevelMask(Levels.Warning),
+ Console.ConsoleSidebar._groupName.Warning, [], Console.ConsoleFilter.singleLevelMask(Levels.Warning),
UI.Icon.create('mediumicon-warning-triangle'), badgePool, selectedFilterSetting);
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.Info, [], Console.ConsoleFilter.singleLevelMask(Levels.Info),
+ Console.ConsoleSidebar._groupName.Info, [], Console.ConsoleFilter.singleLevelMask(Levels.Info),
UI.Icon.create('mediumicon-info-circle'), badgePool, selectedFilterSetting);
this._appendGroup(
- Console.ConsoleSidebar._groupSingularName.Verbose, [], Console.ConsoleFilter.singleLevelMask(Levels.Verbose),
+ Console.ConsoleSidebar._groupName.Verbose, [], Console.ConsoleFilter.singleLevelMask(Levels.Verbose),
UI.Icon.create('mediumicon-bug'), badgePool, selectedFilterSetting);
const selectedTreeElementName = selectedFilterSetting.get();
const defaultTreeElement =
@@ -67,16 +67,18 @@ Console.ConsoleSidebar = class extends UI.VBox {
}
clear() {
- for (const treeElement of this._treeElements)
+ for (const treeElement of this._treeElements) {
treeElement.clear();
+ }
}
/**
* @param {!Console.ConsoleViewMessage} viewMessage
*/
onMessageAdded(viewMessage) {
- for (const treeElement of this._treeElements)
+ for (const treeElement of this._treeElements) {
treeElement.onMessageAdded(viewMessage);
+ }
}
/**
@@ -84,8 +86,9 @@ Console.ConsoleSidebar = class extends UI.VBox {
* @return {boolean}
*/
shouldBeVisible(viewMessage) {
- if (!this._selectedTreeElement)
+ if (!this._selectedTreeElement) {
return true;
+ }
return this._selectedTreeElement._filter.shouldBeVisible(viewMessage);
}
@@ -113,8 +116,9 @@ Console.ConsoleSidebar.URLGroupTreeElement = class extends UI.TreeElement {
this._filter = filter;
this._countElement = this.listItemElement.createChild('span', 'count');
const leadingIcons = [UI.Icon.create('largeicon-navigator-file')];
- if (badge)
+ if (badge) {
leadingIcons.push(badge);
+ }
this.setLeadingIcons(leadingIcons);
this._messageCount = 0;
}
@@ -169,10 +173,15 @@ Console.ConsoleSidebar.FilterTreeElement = class extends UI.TreeElement {
}
_updateCounter() {
- const prefix = this._messageCount ? this._messageCount : Common.UIString('No');
- const pluralizedName = this._messageCount === 1 ? this._filter.name :
- Console.ConsoleSidebar._groupPluralNameMap.get(this._filter.name);
- this.title = `${prefix} ${pluralizedName}`;
+ if (!this._messageCount) {
+ this.title = Console.ConsoleSidebar._groupNoMessageTitleMap.get(this._filter.name);
+ } else if (this._messageCount === 1) {
+ this.title = Console.ConsoleSidebar._groupSingularTitleMap.get(this._filter.name);
+ } else {
+ this.title =
+ String.sprintf(Console.ConsoleSidebar._groupPluralTitleMap.get(this._filter.name), this._messageCount);
+ }
+
this.setExpandable(!!this.childCount());
}
@@ -183,8 +192,9 @@ Console.ConsoleSidebar.FilterTreeElement = class extends UI.TreeElement {
const message = viewMessage.consoleMessage();
const shouldIncrementCounter = message.type !== SDK.ConsoleMessage.MessageType.Command &&
message.type !== SDK.ConsoleMessage.MessageType.Result && !message.isGroupMessage();
- if (!this._filter.shouldBeVisible(viewMessage) || !shouldIncrementCounter)
+ if (!this._filter.shouldBeVisible(viewMessage) || !shouldIncrementCounter) {
return;
+ }
const child = this._childElement(message.url);
child.incrementAndUpdateCounter();
this._messageCount++;
@@ -198,20 +208,23 @@ Console.ConsoleSidebar.FilterTreeElement = class extends UI.TreeElement {
_childElement(url) {
const urlValue = url || null;
let child = this._urlTreeElements.get(urlValue);
- if (child)
+ if (child) {
return child;
+ }
const filter = this._filter.clone();
const parsedURL = urlValue ? urlValue.asParsedURL() : null;
- if (urlValue)
+ if (urlValue) {
filter.name = parsedURL ? parsedURL.displayName : urlValue;
- else
+ } else {
filter.name = Common.UIString('<other>');
+ }
filter.parsedFilters.push({key: Console.ConsoleFilter.FilterType.Url, text: urlValue, negative: false});
const badge = parsedURL ? this._badgePool.badgeForURL(parsedURL) : null;
child = new Console.ConsoleSidebar.URLGroupTreeElement(filter, badge);
- if (urlValue)
+ if (urlValue) {
child.tooltip = urlValue;
+ }
this._urlTreeElements.set(urlValue, child);
this.appendChild(child);
return child;
@@ -219,21 +232,35 @@ Console.ConsoleSidebar.FilterTreeElement = class extends UI.TreeElement {
};
/** @enum {string} */
-Console.ConsoleSidebar._groupSingularName = {
- ConsoleAPI: Common.UIString('user message'),
- All: Common.UIString('message'),
- Error: Common.UIString('error'),
- Warning: Common.UIString('warning'),
- Info: Common.UIString('info'),
- Verbose: Common.UIString('verbose')
+Console.ConsoleSidebar._groupName = {
+ ConsoleAPI: 'user message',
+ All: 'message',
+ Error: 'error',
+ Warning: 'warning',
+ Info: 'info',
+ Verbose: 'verbose'
};
/** @const {!Map<string, string>} */
-Console.ConsoleSidebar._groupPluralNameMap = new Map([
- [Console.ConsoleSidebar._groupSingularName.ConsoleAPI, Common.UIString('user messages')],
- [Console.ConsoleSidebar._groupSingularName.All, Common.UIString('messages')],
- [Console.ConsoleSidebar._groupSingularName.Error, Common.UIString('errors')],
- [Console.ConsoleSidebar._groupSingularName.Warning, Common.UIString('warnings')],
- [Console.ConsoleSidebar._groupSingularName.Info, Common.UIString('info')],
- [Console.ConsoleSidebar._groupSingularName.Verbose, Common.UIString('verbose')]
+Console.ConsoleSidebar._groupSingularTitleMap = new Map([
+ [Console.ConsoleSidebar._groupName.ConsoleAPI, ls`1 user message`],
+ [Console.ConsoleSidebar._groupName.All, ls`1 message`], [Console.ConsoleSidebar._groupName.Error, ls`1 error`],
+ [Console.ConsoleSidebar._groupName.Warning, ls`1 warning`], [Console.ConsoleSidebar._groupName.Info, ls`1 info`],
+ [Console.ConsoleSidebar._groupName.Verbose, ls`1 verbose`]
+]);
+
+/** @const {!Map<string, string>} */
+Console.ConsoleSidebar._groupPluralTitleMap = new Map([
+ [Console.ConsoleSidebar._groupName.ConsoleAPI, ls`%d user messages`],
+ [Console.ConsoleSidebar._groupName.All, ls`%d messages`], [Console.ConsoleSidebar._groupName.Error, ls`%d errors`],
+ [Console.ConsoleSidebar._groupName.Warning, ls`%d warnings`], [Console.ConsoleSidebar._groupName.Info, ls`%d info`],
+ [Console.ConsoleSidebar._groupName.Verbose, ls`%d verbose`]
+]);
+
+/** @const {!Map<string, string>} */
+Console.ConsoleSidebar._groupNoMessageTitleMap = new Map([
+ [Console.ConsoleSidebar._groupName.ConsoleAPI, ls`No user messages`],
+ [Console.ConsoleSidebar._groupName.All, ls`No messages`], [Console.ConsoleSidebar._groupName.Error, ls`No errors`],
+ [Console.ConsoleSidebar._groupName.Warning, ls`No warnings`], [Console.ConsoleSidebar._groupName.Info, ls`No info`],
+ [Console.ConsoleSidebar._groupName.Verbose, ls`No verbose`]
]);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
index f07fec79a20..af780fcf77d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
@@ -57,8 +57,9 @@ Console.ConsoleView = class extends UI.VBox {
this._splitWidget.hideSidebar();
this._splitWidget.enableShowModeSaving();
this._isSidebarOpen = this._splitWidget.showMode() === UI.SplitWidget.ShowMode.Both;
- if (this._isSidebarOpen)
+ if (this._isSidebarOpen) {
this._filter._levelMenuButton.setEnabled(false);
+ }
this._splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, event => {
this._isSidebarOpen = event.data === UI.SplitWidget.ShowMode.Both;
this._filter._levelMenuButton.setEnabled(!this._isSidebarOpen);
@@ -151,8 +152,9 @@ Console.ConsoleView = class extends UI.VBox {
const userGestureCheckbox =
new UI.ToolbarSettingCheckbox(Common.settings.moduleSetting('consoleUserActivationEval'));
settingsToolbarRight.appendToolbarItem(userGestureCheckbox);
- if (!this._showSettingsPaneSetting.get())
+ if (!this._showSettingsPaneSetting.get()) {
settingsPane.element.classList.add('hidden');
+ }
this._showSettingsPaneSetting.addChangeListener(
() => settingsPane.element.classList.toggle('hidden', !this._showSettingsPaneSetting.get()));
@@ -212,8 +214,9 @@ Console.ConsoleView = class extends UI.VBox {
this._messagesElement.addEventListener('keydown', this._messagesKeyDown.bind(this), false);
this._prompt.element.addEventListener('focusin', () => {
- if (this._isScrolledToBottom())
+ if (this._isScrolledToBottom()) {
this._viewport.setStickToBottom(true);
+ }
});
this._consoleHistoryAutocompleteSetting.addChangeListener(this._consoleHistoryAutocompleteChanged, this);
@@ -250,8 +253,9 @@ Console.ConsoleView = class extends UI.VBox {
* @return {!Console.ConsoleView}
*/
static instance() {
- if (!Console.ConsoleView._instance)
+ if (!Console.ConsoleView._instance) {
Console.ConsoleView._instance = new Console.ConsoleView();
+ }
return Console.ConsoleView._instance;
}
@@ -264,8 +268,9 @@ Console.ConsoleView = class extends UI.VBox {
this._filter._messageLevelFiltersSetting.get();
this._cancelBuildHiddenCache();
if (this._immediatelyFilterMessagesForTest) {
- for (const viewMessage of this._consoleMessages)
+ for (const viewMessage of this._consoleMessages) {
this._computeShouldMessageBeVisible(viewMessage);
+ }
this._updateMessageList();
return;
}
@@ -390,10 +395,11 @@ Console.ConsoleView = class extends UI.VBox {
* @override
*/
focus() {
- if (this._viewport.hasVirtualSelection())
+ if (this._viewport.hasVirtualSelection()) {
this._viewport.contentElement().focus();
- else
+ } else {
this._focusPrompt();
+ }
}
_focusPrompt() {
@@ -410,10 +416,11 @@ Console.ConsoleView = class extends UI.VBox {
* @override
*/
restoreScrollPositions() {
- if (this._viewport.stickToBottom())
+ if (this._viewport.stickToBottom()) {
this._immediatelyScrollToBottom();
- else
+ } else {
super.restoreScrollPositions();
+ }
}
/**
@@ -422,10 +429,12 @@ Console.ConsoleView = class extends UI.VBox {
onResize() {
this._scheduleViewportRefresh();
this._hidePromptSuggestBox();
- if (this._viewport.stickToBottom())
+ if (this._viewport.stickToBottom()) {
this._immediatelyScrollToBottom();
- for (let i = 0; i < this._visibleViewMessages.length; ++i)
+ }
+ for (let i = 0; i < this._visibleViewMessages.length; ++i) {
this._visibleViewMessages[i].onResize();
+ }
}
_hidePromptSuggestBox() {
@@ -474,8 +483,9 @@ Console.ConsoleView = class extends UI.VBox {
}
_updateFilterStatus() {
- if (this._hiddenByFilterCount === this._lastShownHiddenByFilterCount)
+ if (this._hiddenByFilterCount === this._lastShownHiddenByFilterCount) {
return;
+ }
this._filterStatusText.setText(ls`${this._hiddenByFilterCount} hidden`);
this._filterStatusText.setVisible(!!this._hiddenByFilterCount);
this._lastShownHiddenByFilterCount = this._hiddenByFilterCount;
@@ -506,10 +516,11 @@ Console.ConsoleView = class extends UI.VBox {
let insertAt;
if (!this._consoleMessages.length ||
- timeComparator(viewMessage, this._consoleMessages[this._consoleMessages.length - 1]) > 0)
+ timeComparator(viewMessage, this._consoleMessages[this._consoleMessages.length - 1]) > 0) {
insertAt = this._consoleMessages.length;
- else
+ } else {
insertAt = this._consoleMessages.upperBound(viewMessage, timeComparator);
+ }
const insertedInMiddle = insertAt < this._consoleMessages.length;
this._consoleMessages.splice(insertAt, 0, viewMessage);
@@ -583,10 +594,11 @@ Console.ConsoleView = class extends UI.VBox {
*/
_computeShouldMessageBeVisible(viewMessage) {
if (this._filter.shouldBeVisible(viewMessage) &&
- (!this._isSidebarOpen || this._sidebar.shouldBeVisible(viewMessage)))
+ (!this._isSidebarOpen || this._sidebar.shouldBeVisible(viewMessage))) {
this._shouldBeHiddenCache.delete(viewMessage);
- else
+ } else {
this._shouldBeHiddenCache.add(viewMessage);
+ }
}
/**
@@ -599,27 +611,31 @@ Console.ConsoleView = class extends UI.VBox {
return;
}
- if (!preventCollapse && this._tryToCollapseMessages(viewMessage, this._visibleViewMessages.peekLast()))
+ if (!preventCollapse && this._tryToCollapseMessages(viewMessage, this._visibleViewMessages.peekLast())) {
return;
+ }
const lastMessage = this._visibleViewMessages.peekLast();
if (viewMessage.consoleMessage().type === SDK.ConsoleMessage.MessageType.EndGroup) {
- if (lastMessage && !this._currentGroup.messagesHidden())
+ if (lastMessage && !this._currentGroup.messagesHidden()) {
lastMessage.incrementCloseGroupDecorationCount();
+ }
this._currentGroup = this._currentGroup.parentGroup() || this._currentGroup;
return;
}
if (!this._currentGroup.messagesHidden()) {
const originatingMessage = viewMessage.consoleMessage().originatingMessage();
- if (lastMessage && originatingMessage && lastMessage.consoleMessage() === originatingMessage)
+ if (lastMessage && originatingMessage && lastMessage.consoleMessage() === originatingMessage) {
viewMessage.toMessageElement().classList.add('console-adjacent-user-command-result');
+ }
this._visibleViewMessages.push(viewMessage);
this._searchMessage(this._visibleViewMessages.length - 1);
}
- if (viewMessage.consoleMessage().isGroupStartMessage())
+ if (viewMessage.consoleMessage().isGroupStartMessage()) {
this._currentGroup = new Console.ConsoleGroup(this._currentGroup, viewMessage);
+ }
this._messageAppendedForTests();
}
@@ -658,15 +674,17 @@ Console.ConsoleView = class extends UI.VBox {
*/
async _onMessageResized(event) {
const treeElement = /** @type {!UI.TreeElement} */ (event.data);
- if (this._pendingBatchResize || !treeElement.treeOutline)
+ if (this._pendingBatchResize || !treeElement.treeOutline) {
return;
+ }
this._pendingBatchResize = true;
await Promise.resolve();
const treeOutlineElement = treeElement.treeOutline.element;
this._viewport.setStickToBottom(this._isScrolledToBottom());
// Scroll, in case mutations moved the element below the visible area.
- if (treeOutlineElement.offsetHeight <= this._messagesElement.offsetHeight)
+ if (treeOutlineElement.offsetHeight <= this._messagesElement.offsetHeight) {
treeOutlineElement.scrollIntoViewIfNeeded();
+ }
this._pendingBatchResize = false;
}
@@ -685,8 +703,9 @@ Console.ConsoleView = class extends UI.VBox {
this._linkifier.reset();
this._badgePool.reset();
this._filter.clear();
- if (hadFocus)
+ if (hadFocus) {
this._prompt.focus();
+ }
}
_handleContextMenuEvent(event) {
@@ -715,8 +734,9 @@ Console.ConsoleView = class extends UI.VBox {
if (consoleMessage) {
const request = SDK.NetworkLog.requestForConsoleMessage(consoleMessage);
- if (request && SDK.NetworkManager.canReplayRequest(request))
+ if (request && SDK.NetworkManager.canReplayRequest(request)) {
contextMenu.debugSection().appendItem(ls`Replay XHR`, SDK.NetworkManager.replayRequest.bind(null, request));
+ }
}
contextMenu.show();
@@ -735,8 +755,9 @@ Console.ConsoleView = class extends UI.VBox {
/** @const */
const chunkSize = 350;
- if (!await stream.open(filename))
+ if (!await stream.open(filename)) {
return;
+ }
this._progressToolbarItem.element.appendChild(progressIndicator.element);
let messageIndex = 0;
@@ -768,8 +789,9 @@ Console.ConsoleView = class extends UI.VBox {
viewMessage.consoleMessage().type !== SDK.ConsoleMessage.MessageType.Result &&
viewMessage.consoleMessage().isEqual(lastMessage.consoleMessage())) {
lastMessage.incrementRepeatCount();
- if (viewMessage.isLastInSimilarGroup())
+ if (viewMessage.isLastInSimilarGroup()) {
lastMessage.setInSimilarGroup(true, true);
+ }
return true;
}
@@ -785,8 +807,9 @@ Console.ConsoleView = class extends UI.VBox {
let i;
for (i = startIndex; i < viewMessages.length; ++i) {
this._computeShouldMessageBeVisible(viewMessages[i]);
- if (i % 10 === 0 && Date.now() - startTime > 12)
+ if (i % 10 === 0 && Date.now() - startTime > 12) {
break;
+ }
}
if (i === viewMessages.length) {
@@ -836,8 +859,9 @@ Console.ConsoleView = class extends UI.VBox {
for (let i = 0; i < this._consoleMessages.length; ++i) {
const viewMessage = this._consoleMessages[i];
const message = viewMessage.consoleMessage();
- if (alreadyAdded.has(message))
+ if (alreadyAdded.has(message)) {
continue;
+ }
if (!message.isGroupable()) {
this._appendMessageToEnd(viewMessage);
@@ -854,8 +878,9 @@ Console.ConsoleView = class extends UI.VBox {
continue;
}
- if (processedGroupKeys.has(key))
+ if (processedGroupKeys.has(key)) {
continue;
+ }
if (!viewMessagesInGroup.find(x => this._shouldMessageBeVisible(x))) {
// Optimize for speed.
@@ -909,8 +934,9 @@ Console.ConsoleView = class extends UI.VBox {
*/
_messagesKeyDown(event) {
const hasActionModifier = event.ctrlKey || event.altKey || event.metaKey;
- if (hasActionModifier || event.key.length !== 1 || UI.isEditing() || this._messagesElement.hasSelection())
+ if (hasActionModifier || event.key.length !== 1 || UI.isEditing() || this._messagesElement.hasSelection()) {
return;
+ }
this._prompt.moveCaretToEndOfPrompt();
this._focusPrompt();
}
@@ -919,8 +945,9 @@ Console.ConsoleView = class extends UI.VBox {
* @param {!Event} event
*/
_messagesPasted(event) {
- if (UI.isEditing())
+ if (UI.isEditing()) {
return;
+ }
this._prompt.focus();
}
@@ -958,8 +985,9 @@ Console.ConsoleView = class extends UI.VBox {
* @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
*/
_printResult(result, originatingConsoleMessage, exceptionDetails) {
- if (!result)
+ if (!result) {
return;
+ }
const level = !!exceptionDetails ? SDK.ConsoleMessage.MessageLevel.Error : SDK.ConsoleMessage.MessageLevel.Info;
let message;
@@ -1026,8 +1054,9 @@ Console.ConsoleView = class extends UI.VBox {
this._regexMatchRanges = [];
this._currentMatchRangeIndex = -1;
- if (shouldJump)
+ if (shouldJump) {
this._searchShouldJumpBackwards = !!jumpBackwards;
+ }
this._searchProgressIndicator = new UI.ProgressIndicator();
this._searchProgressIndicator.setTitle(Common.UIString('Searching…'));
@@ -1064,8 +1093,9 @@ Console.ConsoleView = class extends UI.VBox {
}
const startTime = Date.now();
- for (; index < this._visibleViewMessages.length && Date.now() - startTime < 100; ++index)
+ for (; index < this._visibleViewMessages.length && Date.now() - startTime < 100; ++index) {
this._searchMessage(index);
+ }
this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.length);
if (typeof this._searchShouldJumpBackwards !== 'undefined' && this._regexMatchRanges.length) {
@@ -1089,8 +1119,9 @@ Console.ConsoleView = class extends UI.VBox {
_searchMessage(index) {
const message = this._visibleViewMessages[index];
message.setSearchRegex(this._searchRegex);
- for (let i = 0; i < message.searchCount(); ++i)
+ for (let i = 0; i < message.searchCount(); ++i) {
this._regexMatchRanges.push({messageIndex: index, matchIndex: i});
+ }
}
/**
@@ -1127,8 +1158,9 @@ Console.ConsoleView = class extends UI.VBox {
* @param {number} index
*/
_jumpToMatch(index) {
- if (!this._regexMatchRanges.length)
+ if (!this._regexMatchRanges.length) {
return;
+ }
let matchRange;
if (this._currentMatchRangeIndex >= 0) {
@@ -1161,8 +1193,9 @@ Console.ConsoleView = class extends UI.VBox {
}
_updateStickToBottomOnPointerUp() {
- if (!this._muteViewportUpdates)
+ if (!this._muteViewportUpdates) {
return;
+ }
// Delay querying isScrolledToBottom to give time for smooth scroll
// events to arrive. The value for the longest timeout duration is
@@ -1174,8 +1207,9 @@ Console.ConsoleView = class extends UI.VBox {
*/
function updateViewportState() {
this._muteViewportUpdates = false;
- if (this.isShowing())
+ if (this.isShowing()) {
this._viewport.setStickToBottom(this._isScrolledToBottom());
+ }
if (this._maybeDirtyWhileMuted) {
this._scheduleViewportRefresh();
delete this._maybeDirtyWhileMuted;
@@ -1198,8 +1232,9 @@ Console.ConsoleView = class extends UI.VBox {
const oldStickToBottom = this._viewport.stickToBottom();
const willStickToBottom = this._isScrolledToBottom();
this._viewport.setStickToBottom(willStickToBottom);
- if (willStickToBottom && !oldStickToBottom)
+ if (willStickToBottom && !oldStickToBottom) {
this._scheduleViewportRefresh();
+ }
this._promptTextChangedForTest();
}
@@ -1238,11 +1273,12 @@ Console.ConsoleViewFilter = class {
const filterKeys = Object.values(Console.ConsoleFilter.FilterType);
this._suggestionBuilder = new UI.FilterSuggestionBuilder(filterKeys);
this._textFilterUI = new UI.ToolbarInput(
- Common.UIString('Filter'), 0.2, 1, Common.UIString('e.g. /event\\d/ -cdn url:a.com'),
+ Common.UIString('Filter'), '', 0.2, 1, Common.UIString('e.g. /event\\d/ -cdn url:a.com'),
this._suggestionBuilder.completions.bind(this._suggestionBuilder));
this._textFilterSetting = Common.settings.createSetting('console.textFilter', '');
- if (this._textFilterSetting.get())
+ if (this._textFilterSetting.get()) {
this._textFilterUI.setValue(this._textFilterSetting.get());
+ }
this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, () => {
this._textFilterSetting.set(this._textFilterUI.value());
this._onFilterChanged();
@@ -1271,14 +1307,18 @@ Console.ConsoleViewFilter = class {
*/
onMessageAdded(message) {
if (message.type === SDK.ConsoleMessage.MessageType.Command ||
- message.type === SDK.ConsoleMessage.MessageType.Result || message.isGroupMessage())
+ message.type === SDK.ConsoleMessage.MessageType.Result || message.isGroupMessage()) {
return;
- if (message.context)
+ }
+ if (message.context) {
this._suggestionBuilder.addItem(Console.ConsoleFilter.FilterType.Context, message.context);
- if (message.source)
+ }
+ if (message.source) {
this._suggestionBuilder.addItem(Console.ConsoleFilter.FilterType.Source, message.source);
- if (message.url)
+ }
+ if (message.url) {
this._suggestionBuilder.addItem(Console.ConsoleFilter.FilterType.Url, message.url);
+ }
}
/**
@@ -1320,15 +1360,17 @@ Console.ConsoleViewFilter = class {
for (const name of Object.values(SDK.ConsoleMessage.MessageLevel)) {
isAll = isAll && levels[name] === allValue[name];
isDefault = isDefault && levels[name] === defaultValue[name];
- if (levels[name])
+ if (levels[name]) {
text = text ? Common.UIString('Custom levels') : Common.UIString('%s only', this._levelLabels[name]);
+ }
}
- if (isAll)
+ if (isAll) {
text = Common.UIString('All levels');
- else if (isDefault)
+ } else if (isDefault) {
text = Common.UIString('Default levels');
- else
+ } else {
text = text || Common.UIString('Hide all');
+ }
this._levelMenuButton.element.classList.toggle('warning', !isAll && !isDefault);
this._levelMenuButton.setText(text);
this._levelMenuButton.setTitle(ls`Log level: ${text}`);
@@ -1366,8 +1408,9 @@ Console.ConsoleViewFilter = class {
* @param {string} url
*/
addMessageURLFilter(url) {
- if (!url)
+ if (!url) {
return;
+ }
const suffix = this._textFilterUI.value() ? ` ${this._textFilterUI.value()}` : '';
this._textFilterUI.setValue(`-url:${url}${suffix}`);
this._textFilterSetting.set(this._textFilterUI.value());
@@ -1511,7 +1554,7 @@ Console.ConsoleView.ActionDelegate = class {
handleAction(context, actionId) {
switch (actionId) {
case 'console.show':
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
Common.console.show();
Console.ConsoleView.instance()._focusPrompt();
return true;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
index bc60825ea72..3ed93b53044 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
@@ -59,6 +59,8 @@ Console.ConsoleViewMessage = class {
this._traceExpanded = false;
/** @type {?function(boolean)} */
this._expandTrace = null;
+ /** @type {?Element} */
+ this._anchorElement = null;
}
/**
@@ -73,16 +75,19 @@ Console.ConsoleViewMessage = class {
* @override
*/
wasShown() {
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.updateWidths();
+ }
this._isVisible = true;
}
onResize() {
- if (!this._isVisible)
+ if (!this._isVisible) {
return;
- if (this._dataGrid)
+ }
+ if (this._dataGrid) {
this._dataGrid.onResize();
+ }
}
/**
@@ -97,15 +102,17 @@ Console.ConsoleViewMessage = class {
* @return {number}
*/
fastHeight() {
- if (this._cachedHeight)
+ if (this._cachedHeight) {
return this._cachedHeight;
+ }
// This value reflects the 18px min-height of .console-message, plus the
// 1px border of .console-message-wrapper. Keep in sync with consoleView.css.
const defaultConsoleRowHeight = 19;
if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
const table = this._message.parameters[0];
- if (table && table.preview)
+ if (table && table.preview) {
return defaultConsoleRowHeight * table.preview.properties.length;
+ }
}
return defaultConsoleRowHeight;
}
@@ -123,17 +130,21 @@ Console.ConsoleViewMessage = class {
_buildTableMessage() {
const formattedMessage = createElementWithClass('span', 'source-code');
this._anchorElement = this._buildMessageAnchor();
- if (this._anchorElement)
+ if (this._anchorElement) {
formattedMessage.appendChild(this._anchorElement);
+ }
const badgeElement = this._buildMessageBadge();
- if (badgeElement)
+ if (badgeElement) {
formattedMessage.appendChild(badgeElement);
+ }
let table = this._message.parameters && this._message.parameters.length ? this._message.parameters[0] : null;
- if (table)
+ if (table) {
table = this._parameterToRemoteObject(table);
- if (!table || !table.preview)
+ }
+ if (!table || !table.preview) {
return this._buildMessage();
+ }
const rawValueColumnSymbol = Symbol('rawValueColumn');
const columnNames = [];
@@ -142,12 +153,13 @@ Console.ConsoleViewMessage = class {
for (let i = 0; i < preview.properties.length; ++i) {
const rowProperty = preview.properties[i];
let rowSubProperties;
- if (rowProperty.valuePreview)
+ if (rowProperty.valuePreview) {
rowSubProperties = rowProperty.valuePreview.properties;
- else if (rowProperty.value)
+ } else if (rowProperty.value) {
rowSubProperties = [{name: rawValueColumnSymbol, type: rowProperty.type, value: rowProperty.value}];
- else
+ } else {
continue;
+ }
const rowValue = {};
const maxColumnsToRender = 20;
@@ -155,8 +167,9 @@ Console.ConsoleViewMessage = class {
const cellProperty = rowSubProperties[j];
let columnRendered = columnNames.indexOf(cellProperty.name) !== -1;
if (!columnRendered) {
- if (columnNames.length === maxColumnsToRender)
+ if (columnNames.length === maxColumnsToRender) {
continue;
+ }
columnRendered = true;
columnNames.push(cellProperty.name);
}
@@ -175,8 +188,9 @@ Console.ConsoleViewMessage = class {
const rowName = rows[i][0];
const rowValue = rows[i][1];
flatValues.push(rowName);
- for (let j = 0; j < columnNames.length; ++j)
+ for (let j = 0; j < columnNames.length; ++j) {
flatValues.push(rowValue[columnNames[j]]);
+ }
}
columnNames.unshift(Common.UIString('(index)'));
const columnDisplayNames = columnNames.map(name => name === rawValueColumnSymbol ? Common.UIString('Value') : name);
@@ -209,10 +223,11 @@ Console.ConsoleViewMessage = class {
break;
case SDK.ConsoleMessage.MessageType.Clear:
messageElement = createElementWithClass('span', 'console-info');
- if (Common.moduleSetting('preserveConsoleLog').get())
+ if (Common.moduleSetting('preserveConsoleLog').get()) {
messageElement.textContent = Common.UIString('console.clear() was prevented due to \'Preserve log\'');
- else
+ } else {
messageElement.textContent = Common.UIString('Console was cleared');
+ }
messageElement.title =
ls`Clear all messages with ${UI.shortcutRegistry.shortcutTitleForAction('console.clear')}`;
break;
@@ -231,8 +246,9 @@ Console.ConsoleViewMessage = class {
// Fall through.
default: {
if (this._message.parameters && this._message.parameters.length === 1 &&
- this._message.parameters[0].type === 'string')
+ this._message.parameters[0].type === 'string') {
messageElement = this._tryFormatAsError(/** @type {string} */ (this._message.parameters[0].value));
+ }
const args = this._message.parameters || [messageText];
messageElement = messageElement || this._format(args);
}
@@ -243,15 +259,17 @@ Console.ConsoleViewMessage = class {
} else {
const messageInParameters =
this._message.parameters && messageText === /** @type {string} */ (this._message.parameters[0]);
- if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation)
+ if (this._message.source === SDK.ConsoleMessage.MessageSource.Violation) {
messageText = Common.UIString('[Violation] %s', messageText);
- else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention)
+ } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Intervention) {
messageText = Common.UIString('[Intervention] %s', messageText);
- else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation)
+ } else if (this._message.source === SDK.ConsoleMessage.MessageSource.Deprecation) {
messageText = Common.UIString('[Deprecation] %s', messageText);
+ }
const args = this._message.parameters || [messageText];
- if (messageInParameters)
+ if (messageInParameters) {
args[0] = messageText;
+ }
messageElement = this._format(args);
}
}
@@ -259,11 +277,13 @@ Console.ConsoleViewMessage = class {
const formattedMessage = createElementWithClass('span', 'source-code');
this._anchorElement = this._buildMessageAnchor();
- if (this._anchorElement)
+ if (this._anchorElement) {
formattedMessage.appendChild(this._anchorElement);
+ }
const badgeElement = this._buildMessageBadge();
- if (badgeElement)
+ if (badgeElement) {
formattedMessage.appendChild(badgeElement);
+ }
formattedMessage.appendChild(messageElement);
return formattedMessage;
}
@@ -273,8 +293,9 @@ Console.ConsoleViewMessage = class {
*/
_formatAsNetworkRequest() {
const request = SDK.NetworkLog.requestForConsoleMessage(this._message);
- if (!request)
+ if (!request) {
return null;
+ }
const messageElement = createElement('span');
if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
messageElement.createTextChild(request.requestMethod + ' ');
@@ -283,12 +304,15 @@ Console.ConsoleViewMessage = class {
linkElement.tabIndex = -1;
this._selectableChildren.push({element: linkElement, forceSelect: () => linkElement.focus()});
messageElement.appendChild(linkElement);
- if (request.failed)
+ if (request.failed) {
messageElement.createTextChildren(' ', request.localizedFailDescription);
- if (request.statusCode !== 0)
+ }
+ if (request.statusCode !== 0) {
messageElement.createTextChildren(' ', String(request.statusCode));
- if (request.statusText)
+ }
+ if (request.statusText) {
messageElement.createTextChildren(' (', request.statusText, ')');
+ }
} else {
const messageText = this._message.messageText;
const fragment = this._linkifyWithCustomLinkifier(messageText, (text, url, lineNumber, columnNumber) => {
@@ -324,6 +348,11 @@ Console.ConsoleViewMessage = class {
// Append a space to prevent the anchor text from being glued to the console message when the user selects and copies the console messages.
if (anchorElement) {
+ anchorElement.tabIndex = -1;
+ this._selectableChildren.push({
+ element: anchorElement,
+ forceSelect: () => anchorElement.focus(),
+ });
const anchorWrapperElement = createElementWithClass('span', 'console-message-anchor');
anchorWrapperElement.appendChild(anchorElement);
anchorWrapperElement.createTextChild(' ');
@@ -337,8 +366,9 @@ Console.ConsoleViewMessage = class {
*/
_buildMessageBadge() {
const badgeElement = this._badgeElement();
- if (!badgeElement)
+ if (!badgeElement) {
return null;
+ }
badgeElement.classList.add('console-message-badge');
return badgeElement;
}
@@ -347,32 +377,39 @@ Console.ConsoleViewMessage = class {
* @return {?Element}
*/
_badgeElement() {
- if (this._message._url)
+ if (this._message._url) {
return this._badgePool.badgeForURL(new Common.ParsedURL(this._message._url));
+ }
if (this._message.stackTrace) {
let stackTrace = this._message.stackTrace;
while (stackTrace) {
for (const callFrame of this._message.stackTrace.callFrames) {
- if (callFrame.url)
+ if (callFrame.url) {
return this._badgePool.badgeForURL(new Common.ParsedURL(callFrame.url));
+ }
}
stackTrace = stackTrace.parent;
}
}
- if (!this._message.executionContextId)
+ if (!this._message.executionContextId) {
return null;
+ }
const runtimeModel = this._message.runtimeModel();
- if (!runtimeModel)
+ if (!runtimeModel) {
return null;
+ }
const executionContext = runtimeModel.executionContext(this._message.executionContextId);
- if (!executionContext || !executionContext.frameId)
+ if (!executionContext || !executionContext.frameId) {
return null;
+ }
const resourceTreeModel = executionContext.target().model(SDK.ResourceTreeModel);
- if (!resourceTreeModel)
+ if (!resourceTreeModel) {
return null;
+ }
const frame = resourceTreeModel.frameForId(executionContext.frameId);
- if (!frame || !frame.parentFrame)
+ if (!frame || !frame.parentFrame) {
return null;
+ }
return this._badgePool.badgeForFrame(frame);
}
@@ -411,15 +448,17 @@ Console.ConsoleViewMessage = class {
* @param {?Event} event
*/
function toggleStackTrace(event) {
- if (UI.isEditing() || contentElement.hasSelection())
+ if (UI.isEditing() || contentElement.hasSelection()) {
return;
+ }
this._expandTrace(stackTraceElement.classList.contains('hidden'));
event.consume();
}
clickableElement.addEventListener('click', toggleStackTrace.bind(this), false);
- if (this._message.type === SDK.ConsoleMessage.MessageType.Trace)
+ if (this._message.type === SDK.ConsoleMessage.MessageType.Trace) {
this._expandTrace(true);
+ }
toggleElement._expandStackTraceForTest = this._expandTrace.bind(this, true);
return toggleElement;
@@ -432,8 +471,9 @@ Console.ConsoleViewMessage = class {
* @return {?Element}
*/
_linkifyLocation(url, lineNumber, columnNumber) {
- if (!this._message.runtimeModel())
+ if (!this._message.runtimeModel()) {
return null;
+ }
return this._linkifier.linkifyScriptLocation(
this._message.runtimeModel().target(), null, url, lineNumber, columnNumber);
}
@@ -443,8 +483,9 @@ Console.ConsoleViewMessage = class {
* @return {?Element}
*/
_linkifyStackTraceTopFrame(stackTrace) {
- if (!this._message.runtimeModel())
+ if (!this._message.runtimeModel()) {
return null;
+ }
return this._linkifier.linkifyStackTraceTopFrame(this._message.runtimeModel().target(), stackTrace);
}
@@ -456,8 +497,9 @@ Console.ConsoleViewMessage = class {
* @return {?Element}
*/
_linkifyScriptId(scriptId, url, lineNumber, columnNumber) {
- if (!this._message.runtimeModel())
+ if (!this._message.runtimeModel()) {
return null;
+ }
return this._linkifier.linkifyScriptLocation(
this._message.runtimeModel().target(), scriptId, url, lineNumber, columnNumber);
}
@@ -467,13 +509,16 @@ Console.ConsoleViewMessage = class {
* @return {!SDK.RemoteObject}
*/
_parameterToRemoteObject(parameter) {
- if (parameter instanceof SDK.RemoteObject)
+ if (parameter instanceof SDK.RemoteObject) {
return parameter;
+ }
const runtimeModel = this._message.runtimeModel();
- if (!runtimeModel)
+ if (!runtimeModel) {
return SDK.RemoteObject.fromLocalObject(parameter);
- if (typeof parameter === 'object')
+ }
+ if (typeof parameter === 'object') {
return runtimeModel.createRemoteObject(parameter);
+ }
return runtimeModel.createRemoteObjectFromPrimitiveValue(parameter);
}
@@ -484,17 +529,20 @@ Console.ConsoleViewMessage = class {
_format(rawParameters) {
// This node is used like a Builder. Values are continually appended onto it.
const formattedResult = createElement('span');
- if (this._messagePrefix)
+ if (this._messagePrefix) {
formattedResult.createChild('span').textContent = this._messagePrefix;
- if (!rawParameters.length)
+ }
+ if (!rawParameters.length) {
return formattedResult;
+ }
// Formatting code below assumes that parameters are all wrappers whereas frontend console
// API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here.
// FIXME: Only pass runtime wrappers here.
let parameters = [];
- for (let i = 0; i < rawParameters.length; ++i)
+ for (let i = 0; i < rawParameters.length; ++i) {
parameters[i] = this._parameterToRemoteObject(rawParameters[i]);
+ }
// There can be string log and string eval result. We distinguish between them based on message type.
const shouldFormatMessage =
@@ -507,19 +555,22 @@ Console.ConsoleViewMessage = class {
const result = this._formatWithSubstitutionString(
/** @type {string} **/ (parameters[0].description), parameters.slice(1), formattedResult);
parameters = result.unusedSubstitutions;
- if (parameters.length)
+ if (parameters.length) {
formattedResult.createTextChild(' ');
+ }
}
// Single parameter, or unused substitutions from above.
for (let i = 0; i < parameters.length; ++i) {
// Inline strings when formatting.
- if (shouldFormatMessage && parameters[i].type === 'string')
+ if (shouldFormatMessage && parameters[i].type === 'string') {
formattedResult.appendChild(this._linkifyStringAsFragment(parameters[i].description));
- else
+ } else {
formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
- if (i < parameters.length - 1)
+ }
+ if (i < parameters.length - 1) {
formattedResult.createTextChild(' ');
+ }
}
return formattedResult;
}
@@ -531,8 +582,9 @@ Console.ConsoleViewMessage = class {
* @return {!Element}
*/
_formatParameter(output, forceObjectFormat, includePreview) {
- if (output.customPreview())
+ if (output.customPreview()) {
return (new ObjectUI.CustomPreviewComponent(output)).element;
+ }
const type = forceObjectFormat ? 'object' : (output.subtype || output.type);
let element;
@@ -591,12 +643,14 @@ Console.ConsoleViewMessage = class {
_formatParameterAsValue(obj) {
const result = createElement('span');
const description = obj.description || '';
- if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength)
+ if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
- else
+ } else {
result.createTextChild(description);
- if (obj.objectId)
+ }
+ if (obj.objectId) {
result.addEventListener('contextmenu', this._contextMenuEventFired.bind(this, obj), false);
+ }
return result;
}
@@ -618,14 +672,16 @@ Console.ConsoleViewMessage = class {
titleElement.createTextChild(obj.description || '');
}
- if (!obj.hasChildren || obj.customPreview())
+ if (!obj.hasChildren || obj.customPreview()) {
return titleElement;
+ }
const note = titleElement.createChild('span', 'object-state-note info-note');
- if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult)
+ if (this._message.type === SDK.ConsoleMessage.MessageType.QueryObjectResult) {
note.title = ls`This value will not be collected until console is cleared.`;
- else
+ } else {
note.title = ls`Value below was evaluated just now.`;
+ }
const section = new ObjectUI.ObjectPropertiesSection(obj, titleElement, this._linkifier);
section.element.classList.add('console-view-object-properties-section');
@@ -686,8 +742,9 @@ Console.ConsoleViewMessage = class {
*/
_renderPropertyPreviewOrAccessor(object, propertyPath) {
const property = propertyPath.peekLast();
- if (property.type === 'accessor')
+ if (property.type === 'accessor') {
return this._formatAsAccessorProperty(object, propertyPath.map(property => property.name), false);
+ }
return this._previewFormatter.renderPropertyPreview(
property.type, /** @type {string} */ (property.subtype), property.value);
}
@@ -700,8 +757,9 @@ Console.ConsoleViewMessage = class {
const result = createElement('span');
const domModel = remoteObject.runtimeModel().target().model(SDK.DOMModel);
- if (!domModel)
+ if (!domModel) {
return result;
+ }
domModel.pushObjectAsNodeToFrontend(remoteObject).then(async node => {
if (!node) {
result.appendChild(this._formatParameterAsObject(remoteObject, false));
@@ -779,8 +837,9 @@ Console.ConsoleViewMessage = class {
function onInvokeGetterClick(result) {
const wasThrown = result.wasThrown;
const object = result.object;
- if (!object)
+ if (!object) {
return;
+ }
rootElement.removeChildren();
if (wasThrown) {
const element = rootElement.createChild('span');
@@ -795,10 +854,11 @@ Console.ConsoleViewMessage = class {
const subtype = object.subtype;
let description = '';
if (type !== 'function' && object.description) {
- if (type === 'string' || subtype === 'regexp')
+ if (type === 'string' || subtype === 'regexp') {
description = object.description.trimMiddle(maxLength);
- else
- description = object.description.trimEnd(maxLength);
+ } else {
+ description = object.description.trimEndWithMaxLength(maxLength);
+ }
}
rootElement.appendChild(this._previewFormatter.renderPropertyPreview(type, subtype, description));
}
@@ -831,16 +891,19 @@ Console.ConsoleViewMessage = class {
}
function floatFormatter(obj) {
- if (typeof obj.value !== 'number')
+ if (typeof obj.value !== 'number') {
return 'NaN';
+ }
return obj.value;
}
function integerFormatter(obj) {
- if (obj.type === 'bigint')
+ if (obj.type === 'bigint') {
return obj.description;
- if (typeof obj.value !== 'number')
+ }
+ if (typeof obj.value !== 'number') {
return 'NaN';
+ }
return Math.floor(obj.value);
}
@@ -855,8 +918,9 @@ Console.ConsoleViewMessage = class {
buffer.setAttribute('style', obj.description);
for (let i = 0; i < buffer.style.length; i++) {
const property = buffer.style[i];
- if (isWhitelistedProperty(property))
+ if (isWhitelistedProperty(property)) {
currentStyle[property] = buffer.style[property];
+ }
}
}
@@ -867,8 +931,9 @@ Console.ConsoleViewMessage = class {
'-webkit-border', '-webkit-font', '-webkit-margin', '-webkit-padding', '-webkit-text'
];
for (let i = 0; i < prefixes.length; i++) {
- if (property.startsWith(prefixes[i]))
+ if (property.startsWith(prefixes[i])) {
return true;
+ }
}
return false;
}
@@ -900,8 +965,9 @@ Console.ConsoleViewMessage = class {
a.appendChild(b);
return a;
}
- if (typeof b === 'undefined')
+ if (typeof b === 'undefined') {
return a;
+ }
if (!currentStyle) {
a.appendChild(this._linkifyStringAsFragment(String(b)));
return a;
@@ -917,12 +983,14 @@ Console.ConsoleViewMessage = class {
wrapper.appendChild(lineFragment);
applyCurrentStyle(wrapper);
for (const child of wrapper.children) {
- if (child.classList.contains('devtools-link'))
+ if (child.classList.contains('devtools-link')) {
this._applyForcedVisibleStyle(child);
+ }
}
a.appendChild(wrapper);
- if (i < lines.length - 1)
+ if (i < lines.length - 1) {
a.appendChild(createElement('br'));
+ }
}
return a;
}
@@ -931,8 +999,9 @@ Console.ConsoleViewMessage = class {
* @param {!Element} element
*/
function applyCurrentStyle(element) {
- for (const key in currentStyle)
+ for (const key in currentStyle) {
element.style[key] = currentStyle[key];
+ }
}
// String.format does treat formattedResult like a Builder, result is an object.
@@ -950,10 +1019,11 @@ Console.ConsoleViewMessage = class {
element.style.setProperty('color', themedColor, 'important');
let backgroundColor = 'hsl(0, 0%, 100%)';
- if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error)
+ if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
backgroundColor = 'hsl(0, 100%, 97%)';
- else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning())
+ } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning || this._shouldRenderAsWarning()) {
backgroundColor = 'hsl(50, 100%, 95%)';
+ }
const themedBackgroundColor =
UI.themeSupport.patchColorText(backgroundColor, UI.ThemeSupport.ColorUsage.Background);
element.style.setProperty('background-color', themedBackgroundColor, 'important');
@@ -980,12 +1050,14 @@ Console.ConsoleViewMessage = class {
}
updateTimestamp() {
- if (!this._contentElement)
+ if (!this._contentElement) {
return;
+ }
if (Common.moduleSetting('consoleTimestampsEnabled').get()) {
- if (!this._timestampElement)
+ if (!this._timestampElement) {
this._timestampElement = createElementWithClass('span', 'console-timestamp');
+ }
this._timestampElement.textContent = UI.formatTimestamp(this._message.timestamp, false) + ' ';
this._timestampElement.title = UI.formatTimestamp(this._message.timestamp, true);
this._contentElement.insertBefore(this._timestampElement, this._contentElement.firstChild);
@@ -1027,8 +1099,9 @@ Console.ConsoleViewMessage = class {
}
resetCloseGroupDecorationCount() {
- if (!this._closeGroupDecorationCount)
+ if (!this._closeGroupDecorationCount) {
return;
+ }
this._closeGroupDecorationCount = 0;
this._updateCloseGroupDecorations();
}
@@ -1039,8 +1112,9 @@ Console.ConsoleViewMessage = class {
}
_updateCloseGroupDecorations() {
- if (!this._nestingLevelMarkers)
+ if (!this._nestingLevelMarkers) {
return;
+ }
for (let i = 0, n = this._nestingLevelMarkers.length; i < n; ++i) {
const marker = this._nestingLevelMarkers[i];
marker.classList.toggle('group-closed', n - i <= this._closeGroupDecorationCount);
@@ -1051,8 +1125,9 @@ Console.ConsoleViewMessage = class {
* @return {number}
*/
_focusedChildIndex() {
- if (!this._selectableChildren.length)
+ if (!this._selectableChildren.length) {
return -1;
+ }
return this._selectableChildren.findIndex(child => child.element.hasFocus());
}
@@ -1060,10 +1135,12 @@ Console.ConsoleViewMessage = class {
* @param {!Event} event
*/
_onKeyDown(event) {
- if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection())
+ if (UI.isEditing() || !this._element.hasFocus() || this._element.hasSelection()) {
return;
- if (this.maybeHandleOnKeyDown(event))
+ }
+ if (this.maybeHandleOnKeyDown(event)) {
event.consume(true);
+ }
}
/**
@@ -1080,16 +1157,18 @@ Console.ConsoleViewMessage = class {
return true;
}
}
- if (!this._selectableChildren.length)
+ if (!this._selectableChildren.length) {
return false;
+ }
if (event.key === 'ArrowLeft') {
this._element.focus();
return true;
}
if (event.key === 'ArrowRight') {
- if (isWrapperFocused && this._selectNearestVisibleChild(0))
+ if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
return true;
+ }
}
if (event.key === 'ArrowUp') {
const firstVisibleChild = this._nearestVisibleChild(0);
@@ -1101,10 +1180,12 @@ Console.ConsoleViewMessage = class {
}
}
if (event.key === 'ArrowDown') {
- if (isWrapperFocused && this._selectNearestVisibleChild(0))
+ if (isWrapperFocused && this._selectNearestVisibleChild(0)) {
return true;
- if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1))
+ }
+ if (!isWrapperFocused && this._selectNearestVisibleChild(focusedChildIndex + 1)) {
return true;
+ }
}
return false;
}
@@ -1130,34 +1211,39 @@ Console.ConsoleViewMessage = class {
*/
_nearestVisibleChild(fromIndex, backwards) {
const childCount = this._selectableChildren.length;
- if (fromIndex < 0 || fromIndex >= childCount)
+ if (fromIndex < 0 || fromIndex >= childCount) {
return null;
+ }
const direction = backwards ? -1 : 1;
let index = fromIndex;
while (!this._selectableChildren[index].element.offsetParent) {
index += direction;
- if (index < 0 || index >= childCount)
+ if (index < 0 || index >= childCount) {
return null;
+ }
}
return this._selectableChildren[index];
}
focusLastChildOrSelf() {
- if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */))
+ if (this._element && !this._selectNearestVisibleChild(this._selectableChildren.length - 1, true /* backwards */)) {
this._element.focus();
+ }
}
/**
* @return {!Element}
*/
contentElement() {
- if (this._contentElement)
+ if (this._contentElement) {
return this._contentElement;
+ }
const contentElement = createElementWithClass('div', 'console-message');
- if (this._messageLevelIcon)
+ if (this._messageLevelIcon) {
contentElement.appendChild(this._messageLevelIcon);
+ }
this._contentElement = contentElement;
let formattedMessage;
@@ -1167,12 +1253,13 @@ Console.ConsoleViewMessage = class {
this._message.level === SDK.ConsoleMessage.MessageLevel.Error ||
this._message.level === SDK.ConsoleMessage.MessageLevel.Warning ||
this._message.type === SDK.ConsoleMessage.MessageType.Trace);
- if (this._message.runtimeModel() && shouldIncludeTrace)
+ if (this._message.runtimeModel() && shouldIncludeTrace) {
formattedMessage = this._buildMessageWithStackTrace();
- else if (this._message.type === SDK.ConsoleMessage.MessageType.Table)
+ } else if (this._message.type === SDK.ConsoleMessage.MessageType.Table) {
formattedMessage = this._buildTableMessage();
- else
+ } else {
formattedMessage = this._buildMessage();
+ }
contentElement.appendChild(formattedMessage);
this.updateTimestamp();
@@ -1183,8 +1270,9 @@ Console.ConsoleViewMessage = class {
* @return {!Element}
*/
toMessageElement() {
- if (this._element)
+ if (this._element) {
return this._element;
+ }
this._element = createElement('div');
this._element.tabIndex = -1;
@@ -1194,23 +1282,27 @@ Console.ConsoleViewMessage = class {
}
updateMessageElement() {
- if (!this._element)
+ if (!this._element) {
return;
+ }
this._element.className = 'console-message-wrapper';
this._element.removeChildren();
- if (this._message.isGroupStartMessage())
+ if (this._message.isGroupStartMessage()) {
this._element.classList.add('console-group-title');
- if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI)
+ }
+ if (this._message.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI) {
this._element.classList.add('console-from-api');
+ }
if (this._inSimilarGroup) {
this._similarGroupMarker = this._element.createChild('div', 'nesting-level-marker');
this._similarGroupMarker.classList.toggle('group-closed', this._lastInSimilarGroup);
}
this._nestingLevelMarkers = [];
- for (let i = 0; i < this._nestingLevel; ++i)
+ for (let i = 0; i < this._nestingLevel; ++i) {
this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
+ }
this._updateCloseGroupDecorations();
this._element.message = this;
@@ -1220,8 +1312,9 @@ Console.ConsoleViewMessage = class {
break;
case SDK.ConsoleMessage.MessageLevel.Info:
this._element.classList.add('console-info-level');
- if (this._message.type === SDK.ConsoleMessage.MessageType.System)
+ if (this._message.type === SDK.ConsoleMessage.MessageType.System) {
this._element.classList.add('console-system-type');
+ }
break;
case SDK.ConsoleMessage.MessageLevel.Warning:
this._element.classList.add('console-warning-level');
@@ -1231,12 +1324,14 @@ Console.ConsoleViewMessage = class {
break;
}
this._updateMessageLevelIcon();
- if (this._shouldRenderAsWarning())
+ if (this._shouldRenderAsWarning()) {
this._element.classList.add('console-warning-level');
+ }
this._element.appendChild(this.contentElement());
- if (this._repeatCount > 1)
+ if (this._repeatCount > 1) {
this._showRepeatCountElement();
+ }
}
/**
@@ -1261,12 +1356,14 @@ Console.ConsoleViewMessage = class {
iconType = 'smallicon-error';
accessibleName = ls`Error`;
}
- if (!iconType && !this._messageLevelIcon)
+ if (!iconType && !this._messageLevelIcon) {
return;
+ }
if (iconType && !this._messageLevelIcon) {
this._messageLevelIcon = UI.Icon.create('', 'message-level-icon');
- if (this._contentElement)
+ if (this._contentElement) {
this._contentElement.insertBefore(this._messageLevelIcon, this._contentElement.firstChild);
+ }
}
this._messageLevelIcon.setIconType(iconType);
UI.ARIAUtils.setAccessibleName(this._messageLevelIcon, accessibleName);
@@ -1281,12 +1378,14 @@ Console.ConsoleViewMessage = class {
resetIncrementRepeatCount() {
this._repeatCount = 1;
- if (!this._repeatCountElement)
+ if (!this._repeatCountElement) {
return;
+ }
this._repeatCountElement.remove();
- if (this._contentElement)
+ if (this._contentElement) {
this._contentElement.classList.remove('repeated-message');
+ }
delete this._repeatCountElement;
}
@@ -1304,8 +1403,9 @@ Console.ConsoleViewMessage = class {
}
_showRepeatCountElement() {
- if (!this._element)
+ if (!this._element) {
return;
+ }
if (!this._repeatCountElement) {
this._repeatCountElement = createElementWithClass('span', 'console-message-repeat-count', 'dt-small-bubble');
@@ -1322,18 +1422,20 @@ Console.ConsoleViewMessage = class {
default:
this._repeatCountElement.type = 'info';
}
- if (this._shouldRenderAsWarning())
+ if (this._shouldRenderAsWarning()) {
this._repeatCountElement.type = 'warning';
+ }
this._element.insertBefore(this._repeatCountElement, this._contentElement);
this._contentElement.classList.add('repeated-message');
}
this._repeatCountElement.textContent = this._repeatCount;
let accessibleName = ls`Repeat ${this._repeatCount}`;
- if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning)
+ if (this._message.level === SDK.ConsoleMessage.MessageLevel.Warning) {
accessibleName = ls`Warning ${accessibleName}`;
- else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error)
+ } else if (this._message.level === SDK.ConsoleMessage.MessageLevel.Error) {
accessibleName = ls`Error ${accessibleName}`;
+ }
UI.ARIAUtils.setAccessibleName(this._repeatCountElement, accessibleName);
}
@@ -1348,8 +1450,9 @@ Console.ConsoleViewMessage = class {
const lines = [];
const nodes = this.contentElement().childTextNodes();
const messageContent = nodes.map(Components.Linkifier.untruncatedNodeText).join('');
- for (let i = 0; i < this.repeatCount(); ++i)
+ for (let i = 0; i < this.repeatCount(); ++i) {
lines.push(messageContent);
+ }
return lines.join('\n');
}
@@ -1357,20 +1460,23 @@ Console.ConsoleViewMessage = class {
* @param {?RegExp} regex
*/
setSearchRegex(regex) {
- if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length)
+ if (this._searchHiglightNodeChanges && this._searchHiglightNodeChanges.length) {
UI.revertDomChanges(this._searchHiglightNodeChanges);
+ }
this._searchRegex = regex;
this._searchHighlightNodes = [];
this._searchHiglightNodeChanges = [];
- if (!this._searchRegex)
+ if (!this._searchRegex) {
return;
+ }
const text = this.contentElement().deepTextContent();
let match;
this._searchRegex.lastIndex = 0;
const sourceRanges = [];
- while ((match = this._searchRegex.exec(text)) && match[0])
+ while ((match = this._searchRegex.exec(text)) && match[0]) {
sourceRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
+ }
if (sourceRanges.length) {
this._searchHighlightNodes =
@@ -1413,8 +1519,9 @@ Console.ConsoleViewMessage = class {
const errorPrefixes =
['EvalError', 'ReferenceError', 'SyntaxError', 'TypeError', 'RangeError', 'Error', 'URIError'];
- if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith))
+ if (!this._message.runtimeModel() || !errorPrefixes.some(startsWith)) {
return null;
+ }
const debuggerModel = this._message.runtimeModel().debuggerModel();
const baseURL = this._message.runtimeModel().target().inspectedURL();
@@ -1424,11 +1531,13 @@ Console.ConsoleViewMessage = class {
for (let i = 0; i < lines.length; ++i) {
position += i > 0 ? lines[i - 1].length + 1 : 0;
const isCallFrameLine = /^\s*at\s/.test(lines[i]);
- if (!isCallFrameLine && links.length)
+ if (!isCallFrameLine && links.length) {
return null;
+ }
- if (!isCallFrameLine)
+ if (!isCallFrameLine) {
continue;
+ }
let openBracketIndex = -1;
let closeBracketIndex = -1;
@@ -1436,11 +1545,13 @@ Console.ConsoleViewMessage = class {
const inBrackets = /\([^\)\(]+\)/g;
let lastMatch = null;
let currentMatch;
- while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i])))
+ while ((currentMatch = inBracketsWithLineAndColumn.exec(lines[i]))) {
lastMatch = currentMatch;
+ }
if (!lastMatch) {
- while ((currentMatch = inBrackets.exec(lines[i])))
+ while ((currentMatch = inBrackets.exec(lines[i]))) {
lastMatch = currentMatch;
+ }
}
if (lastMatch) {
openBracketIndex = lastMatch.index;
@@ -1451,16 +1562,20 @@ Console.ConsoleViewMessage = class {
const right = hasOpenBracket ? closeBracketIndex : lines[i].length;
const linkCandidate = lines[i].substring(left, right);
const splitResult = Common.ParsedURL.splitLineAndColumn(linkCandidate);
- if (!splitResult)
+ if (!splitResult) {
return null;
+ }
- if (splitResult.url === '<anonymous>')
+ if (splitResult.url === '<anonymous>') {
continue;
+ }
let url = parseOrScriptMatch(splitResult.url);
- if (!url && Common.ParsedURL.isRelativeURL(splitResult.url))
+ if (!url && Common.ParsedURL.isRelativeURL(splitResult.url)) {
url = parseOrScriptMatch(Common.ParsedURL.completeURL(baseURL, splitResult.url));
- if (!url)
+ }
+ if (!url) {
return null;
+ }
links.push({
url: url,
@@ -1471,8 +1586,9 @@ Console.ConsoleViewMessage = class {
});
}
- if (!links.length)
+ if (!links.length) {
return null;
+ }
const formattedResult = createElement('span');
let start = 0;
@@ -1486,8 +1602,9 @@ Console.ConsoleViewMessage = class {
start = links[i].positionRight;
}
- if (start !== string.length)
+ if (start !== string.length) {
formattedResult.appendChild(this._linkifyStringAsFragment(string.substring(start)));
+ }
return formattedResult;
@@ -1496,13 +1613,16 @@ Console.ConsoleViewMessage = class {
* @return {?string}
*/
function parseOrScriptMatch(url) {
- if (!url)
+ if (!url) {
return null;
+ }
const parsedURL = url.asParsedURL();
- if (parsedURL)
+ if (parsedURL) {
return parsedURL.url;
- if (debuggerModel.scriptsForSourceURL(url).length)
+ }
+ if (debuggerModel.scriptsForSourceURL(url).length) {
return url;
+ }
return null;
}
}
@@ -1513,22 +1633,25 @@ Console.ConsoleViewMessage = class {
* @return {!DocumentFragment}
*/
_linkifyWithCustomLinkifier(string, linkifier) {
- if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength)
+ if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
+ }
const container = createDocumentFragment();
const tokens = Console.ConsoleViewMessage._tokenizeMessageText(string);
for (const token of tokens) {
- if (!token.text)
+ if (!token.text) {
continue;
+ }
switch (token.type) {
case 'url': {
const realURL = (token.text.startsWith('www.') ? 'http://' + token.text : token.text);
const splitResult = Common.ParsedURL.splitLineAndColumn(realURL);
let linkNode;
- if (splitResult)
+ if (splitResult) {
linkNode = linkifier(token.text, splitResult.url, splitResult.lineNumber, splitResult.columnNumber);
- else
+ } else {
linkNode = linkifier(token.text, token.value);
+ }
container.appendChild(linkNode);
break;
}
@@ -1579,8 +1702,9 @@ Console.ConsoleViewMessage = class {
Console.ConsoleViewMessage._tokenizerRegexes = Array.from(handlers.keys());
Console.ConsoleViewMessage._tokenizerTypes = Array.from(handlers.values());
}
- if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength)
+ if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength) {
return [{text: string, type: undefined}];
+ }
const results = TextUtils.TextUtils.splitStringByRegexes(string, Console.ConsoleViewMessage._tokenizerRegexes);
return results.map(
result => ({text: result.value, type: Console.ConsoleViewMessage._tokenizerTypes[result.regexIndex]}));
@@ -1590,8 +1714,9 @@ Console.ConsoleViewMessage = class {
* @return {string}
*/
groupKey() {
- if (!this._groupKey)
+ if (!this._groupKey) {
this._groupKey = this._message.groupCategoryKey() + ':' + this.groupTitle();
+ }
return this._groupKey;
}
@@ -1602,16 +1727,17 @@ Console.ConsoleViewMessage = class {
const tokens = Console.ConsoleViewMessage._tokenizeMessageText(this._message.messageText);
const result = tokens.reduce((acc, token) => {
let text = token.text;
- if (token.type === 'url')
+ if (token.type === 'url') {
text = Common.UIString('<URL>');
- else if (token.type === 'time')
+ } else if (token.type === 'time') {
text = Common.UIString('took <N>ms');
- else if (token.type === 'event')
+ } else if (token.type === 'event') {
text = Common.UIString('<some> event');
- else if (token.type === 'milestone')
+ } else if (token.type === 'milestone') {
text = Common.UIString(' M<XX>');
- else if (token.type === 'autofill')
+ } else if (token.type === 'autofill') {
text = Common.UIString('<attribute>');
+ }
return acc + text;
}, '');
return result.replace(/[%]o/g, '');
@@ -1644,8 +1770,9 @@ Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
*/
_setCollapsed(collapsed) {
this._collapsed = collapsed;
- if (this._expandGroupIcon)
+ if (this._expandGroupIcon) {
this._expandGroupIcon.setIconType(this._collapsed ? 'smallicon-triangle-right' : 'smallicon-triangle-down');
+ }
this._onToggle.call(null);
}
@@ -1682,10 +1809,11 @@ Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
this._expandGroupIcon = UI.Icon.create(iconType, 'expand-group-icon');
// Intercept focus to avoid highlight on click.
this._contentElement.tabIndex = -1;
- if (this._repeatCountElement)
+ if (this._repeatCountElement) {
this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
- else
+ } else {
this._element.insertBefore(this._expandGroupIcon, this._contentElement);
+ }
this._element.addEventListener('click', () => this._setCollapsed(!this._collapsed));
}
return this._element;
@@ -1696,8 +1824,9 @@ Console.ConsoleGroupViewMessage = class extends Console.ConsoleViewMessage {
*/
_showRepeatCountElement() {
super._showRepeatCountElement();
- if (this._repeatCountElement && this._expandGroupIcon)
+ if (this._repeatCountElement && this._expandGroupIcon) {
this._repeatCountElement.insertBefore(this._expandGroupIcon, this._repeatCountElement.firstChild);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewport.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewport.js
index ae47b5c36a3..72c9945ce0b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewport.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewport.js
@@ -92,10 +92,11 @@ Console.ConsoleViewport = class {
*/
setStickToBottom(value) {
this._stickToBottom = value;
- if (this._stickToBottom)
+ if (this._stickToBottom) {
this._observer.observe(this._contentElement, this._observerConfig);
- else
+ } else {
this._observer.disconnect();
+ }
}
/**
@@ -115,11 +116,13 @@ Console.ConsoleViewport = class {
* @param {!Event} event
*/
_onCopy(event) {
- if (this._muteCopyHandler)
+ if (this._muteCopyHandler) {
return;
+ }
const text = this._selectedText();
- if (!text)
+ if (!text) {
return;
+ }
event.preventDefault();
event.clipboardData.setData('text/plain', text);
}
@@ -129,8 +132,9 @@ Console.ConsoleViewport = class {
*/
_onFocusIn(event) {
const renderedIndex = this._renderedItems.findIndex(item => item.element().isSelfOrAncestor(event.target));
- if (renderedIndex !== -1)
+ if (renderedIndex !== -1) {
this._virtualSelectedIndex = this._firstActiveIndex + renderedIndex;
+ }
let focusLastChild = false;
// Make default selection when moving from external (e.g. prompt) to the container.
if (this._virtualSelectedIndex === -1 && this._isOutsideViewport(/** @type {?Element} */ (event.relatedTarget)) &&
@@ -150,8 +154,9 @@ Console.ConsoleViewport = class {
*/
_onFocusOut(event) {
// Remove selection when focus moves to external location (e.g. prompt).
- if (this._isOutsideViewport(/** @type {?Element} */ (event.relatedTarget)))
+ if (this._isOutsideViewport(/** @type {?Element} */ (event.relatedTarget))) {
this._virtualSelectedIndex = -1;
+ }
this._updateFocusedItem();
}
@@ -168,8 +173,9 @@ Console.ConsoleViewport = class {
*/
_onDragStart(event) {
const text = this._selectedText();
- if (!text)
+ if (!text) {
return false;
+ }
event.dataTransfer.clearData();
event.dataTransfer.setData('text/plain', text);
event.dataTransfer.effectAllowed = 'copy';
@@ -180,8 +186,9 @@ Console.ConsoleViewport = class {
* @param {!Event} event
*/
_onKeyDown(event) {
- if (UI.isEditing() || !this._itemCount || event.shiftKey)
+ if (UI.isEditing() || !this._itemCount || event.shiftKey) {
return;
+ }
let isArrowUp = false;
switch (event.key) {
case 'ArrowUp':
@@ -193,10 +200,11 @@ Console.ConsoleViewport = class {
}
break;
case 'ArrowDown':
- if (this._virtualSelectedIndex < this._itemCount - 1)
+ if (this._virtualSelectedIndex < this._itemCount - 1) {
this._virtualSelectedIndex++;
- else
+ } else {
return;
+ }
break;
case 'Home':
this._virtualSelectedIndex = 0;
@@ -219,8 +227,9 @@ Console.ConsoleViewport = class {
const selectedElement = this.renderedElementAt(this._virtualSelectedIndex);
const changed = this._lastSelectedElement !== selectedElement;
const containerHasFocus = this._contentElement === this.element.ownerDocument.deepActiveElement();
- if (this._lastSelectedElement && changed)
+ if (this._lastSelectedElement && changed) {
this._lastSelectedElement.classList.remove('console-selected');
+ }
if (selectedElement && (focusLastChild || changed || containerHasFocus) && this.element.hasFocus()) {
selectedElement.classList.add('console-selected');
// Do not focus the message if something within holds focus (e.g. object).
@@ -231,10 +240,11 @@ Console.ConsoleViewport = class {
focusWithoutScroll(selectedElement);
}
}
- if (this._itemCount && !this._contentElement.hasFocus())
+ if (this._itemCount && !this._contentElement.hasFocus()) {
this._contentElement.tabIndex = 0;
- else
+ } else {
this._contentElement.tabIndex = -1;
+ }
this._lastSelectedElement = selectedElement;
/**
@@ -257,8 +267,9 @@ Console.ConsoleViewport = class {
invalidate() {
delete this._cachedProviderElements;
this._itemCount = this._provider.itemCount();
- if (this._virtualSelectedIndex > this._itemCount - 1)
+ if (this._virtualSelectedIndex > this._itemCount - 1) {
this._virtualSelectedIndex = this._itemCount - 1;
+ }
this._rebuildCumulativeHeights();
this.refresh();
}
@@ -268,8 +279,9 @@ Console.ConsoleViewport = class {
* @return {?Console.ConsoleViewportElement}
*/
_providerElement(index) {
- if (!this._cachedProviderElements)
+ if (!this._cachedProviderElements) {
this._cachedProviderElements = new Array(this._itemCount);
+ }
let element = this._cachedProviderElements[index];
if (!element) {
element = this._provider.itemElement(index);
@@ -284,10 +296,11 @@ Console.ConsoleViewport = class {
let height = 0;
this._cumulativeHeights = new Int32Array(this._itemCount);
for (let i = 0; i < this._itemCount; ++i) {
- if (firstActiveIndex <= i && i - firstActiveIndex < this._renderedItems.length && i <= lastActiveIndex)
+ if (firstActiveIndex <= i && i - firstActiveIndex < this._renderedItems.length && i <= lastActiveIndex) {
height += this._renderedItems[i - firstActiveIndex].element().offsetHeight;
- else
+ } else {
height += this._provider.fastHeight(i);
+ }
this._cumulativeHeights[i] = height;
}
}
@@ -327,8 +340,9 @@ Console.ConsoleViewport = class {
* @suppressGlobalPropertiesCheck
*/
_isSelectionBackwards(selection) {
- if (!selection || !selection.rangeCount)
+ if (!selection || !selection.rangeCount) {
return false;
+ }
const range = document.createRange();
range.setStart(selection.anchorNode, selection.anchorOffset);
range.setEnd(selection.focusNode, selection.focusOffset);
@@ -424,10 +438,11 @@ Console.ConsoleViewport = class {
anchorElement = this._anchorSelection.node;
anchorOffset = this._anchorSelection.offset;
} else {
- if (this._anchorSelection.item < this._firstActiveIndex)
+ if (this._anchorSelection.item < this._firstActiveIndex) {
anchorElement = this._topGapElement;
- else if (this._anchorSelection.item > this._lastActiveIndex)
+ } else if (this._anchorSelection.item > this._lastActiveIndex) {
anchorElement = this._bottomGapElement;
+ }
anchorOffset = this._selectionIsBackward ? 1 : 0;
}
@@ -437,10 +452,11 @@ Console.ConsoleViewport = class {
headElement = this._headSelection.node;
headOffset = this._headSelection.offset;
} else {
- if (this._headSelection.item < this._firstActiveIndex)
+ if (this._headSelection.item < this._firstActiveIndex) {
headElement = this._topGapElement;
- else if (this._headSelection.item > this._lastActiveIndex)
+ } else if (this._headSelection.item > this._lastActiveIndex) {
headElement = this._bottomGapElement;
+ }
headOffset = this._selectionIsBackward ? 0 : 1;
}
@@ -450,17 +466,20 @@ Console.ConsoleViewport = class {
refresh() {
this._observer.disconnect();
this._innerRefresh();
- if (this._stickToBottom)
+ if (this._stickToBottom) {
this._observer.observe(this._contentElement, this._observerConfig);
+ }
}
_innerRefresh() {
- if (!this._visibleHeight())
- return; // Do nothing for invisible controls.
+ if (!this._visibleHeight()) {
+ return;
+ } // Do nothing for invisible controls.
if (!this._itemCount) {
- for (let i = 0; i < this._renderedItems.length; ++i)
+ for (let i = 0; i < this._renderedItems.length; ++i) {
this._renderedItems[i].willHide();
+ }
this._renderedItems = [];
this._contentElement.removeChildren();
this._topGapElement.style.height = '0px';
@@ -512,10 +531,12 @@ Console.ConsoleViewport = class {
this._partialViewportUpdate(prepare.bind(this));
this._contentElement.style.removeProperty('height');
// Should be the last call in the method as it might force layout.
- if (shouldRestoreSelection)
+ if (shouldRestoreSelection) {
this._restoreSelection(selection);
- if (this._stickToBottom)
+ }
+ if (this._stickToBottom) {
this.element.scrollTop = 10000000;
+ }
}
/**
@@ -523,11 +544,13 @@ Console.ConsoleViewport = class {
*/
_partialViewportUpdate(prepare) {
const itemsToRender = new Set();
- for (let i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i)
+ for (let i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i) {
itemsToRender.add(this._providerElement(i));
+ }
const willBeHidden = this._renderedItems.filter(item => !itemsToRender.has(item));
- for (let i = 0; i < willBeHidden.length; ++i)
+ for (let i = 0; i < willBeHidden.length; ++i) {
willBeHidden[i].willHide();
+ }
prepare();
let hadFocus = false;
for (let i = 0; i < willBeHidden.length; ++i) {
@@ -541,19 +564,22 @@ Console.ConsoleViewport = class {
const element = viewportElement.element();
if (element !== anchor) {
const shouldCallWasShown = !element.parentElement;
- if (shouldCallWasShown)
+ if (shouldCallWasShown) {
wasShown.push(viewportElement);
+ }
this._contentElement.insertBefore(element, anchor);
} else {
anchor = anchor.nextSibling;
}
}
- for (let i = 0; i < wasShown.length; ++i)
+ for (let i = 0; i < wasShown.length; ++i) {
wasShown[i].wasShown();
+ }
this._renderedItems = Array.from(itemsToRender);
- if (hadFocus)
+ if (hadFocus) {
this._contentElement.focus();
+ }
this._updateFocusedItem();
}
@@ -562,8 +588,9 @@ Console.ConsoleViewport = class {
*/
_selectedText() {
this._updateSelectionModel(this.element.getComponentSelection());
- if (!this._headSelection || !this._anchorSelection)
+ if (!this._headSelection || !this._anchorSelection) {
return null;
+ }
let startSelection = null;
let endSelection = null;
@@ -618,14 +645,16 @@ Console.ConsoleViewport = class {
let node = itemElement;
while ((node = node.traverseNextNode(itemElement)) && node !== selectionNode) {
if (node.nodeType !== Node.TEXT_NODE || node.parentElement.nodeName === 'STYLE' ||
- node.parentElement.nodeName === 'SCRIPT')
+ node.parentElement.nodeName === 'SCRIPT') {
continue;
+ }
chars += Components.Linkifier.untruncatedNodeText(node).length;
}
// If the selected node text was truncated, treat any non-zero offset as the full length.
const untruncatedContainerLength = Components.Linkifier.untruncatedNodeText(selectionNode).length;
- if (offset > 0 && untruncatedContainerLength !== selectionNode.textContent.length)
+ if (offset > 0 && untruncatedContainerLength !== selectionNode.textContent.length) {
offset = untruncatedContainerLength;
+ }
return chars + offset;
}
@@ -640,8 +669,9 @@ Console.ConsoleViewport = class {
* @return {number}
*/
firstVisibleIndex() {
- if (!this._cumulativeHeights.length)
+ if (!this._cumulativeHeights.length) {
return -1;
+ }
this._rebuildCumulativeHeightsIfNeeded();
return this._cumulativeHeights.lowerBound(this.element.scrollTop + 1);
}
@@ -650,8 +680,9 @@ Console.ConsoleViewport = class {
* @return {number}
*/
lastVisibleIndex() {
- if (!this._cumulativeHeights.length)
+ if (!this._cumulativeHeights.length) {
return -1;
+ }
this._rebuildCumulativeHeightsIfNeeded();
const scrollBottom = this.element.scrollTop + this.element.clientHeight;
const right = this._itemCount - 1;
@@ -662,8 +693,9 @@ Console.ConsoleViewport = class {
* @return {?Element}
*/
renderedElementAt(index) {
- if (index === -1 || index < this._firstActiveIndex || index > this._lastActiveIndex)
+ if (index === -1 || index < this._firstActiveIndex || index > this._lastActiveIndex) {
return null;
+ }
return this._renderedItems[index - this._firstActiveIndex].element();
}
@@ -674,17 +706,21 @@ Console.ConsoleViewport = class {
scrollItemIntoView(index, makeLast) {
const firstVisibleIndex = this.firstVisibleIndex();
const lastVisibleIndex = this.lastVisibleIndex();
- if (index > firstVisibleIndex && index < lastVisibleIndex)
+ if (index > firstVisibleIndex && index < lastVisibleIndex) {
return;
+ }
// If the prompt is visible, then the last item must be fully on screen.
- if (index === lastVisibleIndex && this._cumulativeHeights[index] <= this.element.scrollTop + this._visibleHeight())
+ if (index === lastVisibleIndex &&
+ this._cumulativeHeights[index] <= this.element.scrollTop + this._visibleHeight()) {
return;
- if (makeLast)
+ }
+ if (makeLast) {
this.forceScrollItemToBeLast(index);
- else if (index <= firstVisibleIndex)
+ } else if (index <= firstVisibleIndex) {
this.forceScrollItemToBeFirst(index);
- else if (index >= lastVisibleIndex)
+ } else if (index >= lastVisibleIndex) {
this.forceScrollItemToBeLast(index);
+ }
}
/**
@@ -695,8 +731,9 @@ Console.ConsoleViewport = class {
this.setStickToBottom(false);
this._rebuildCumulativeHeightsIfNeeded();
this.element.scrollTop = index > 0 ? this._cumulativeHeights[index - 1] : 0;
- if (this.element.isScrolledToBottom())
+ if (this.element.isScrolledToBottom()) {
this.setStickToBottom(true);
+ }
this.refresh();
// After refresh, the item is in DOM, but may not be visible (items above were larger than expected).
this.renderedElementAt(index).scrollIntoView(true /* alignTop */);
@@ -710,8 +747,9 @@ Console.ConsoleViewport = class {
this.setStickToBottom(false);
this._rebuildCumulativeHeightsIfNeeded();
this.element.scrollTop = this._cumulativeHeights[index] - this._visibleHeight();
- if (this.element.isScrolledToBottom())
+ if (this.element.isScrolledToBottom()) {
this.setStickToBottom(true);
+ }
this.refresh();
// After refresh, the item is in DOM, but may not be visible (items above were larger than expected).
this.renderedElementAt(index).scrollIntoView(false /* alignTop */);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css b/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css
index 32367f44bb7..33b99f8dcdb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css
@@ -5,6 +5,7 @@
*/
.console-pins {
+ max-height: 200px;
overflow-y: auto;
background: var(--toolbar-bg-color);
--error-background-color: hsl(0, 100%, 97%);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css b/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
index 4fa8cf38fdf..a44d4895ec5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
@@ -490,5 +490,5 @@
.console-view-pinpane {
flex: none;
- max-height: 200px;
+ max-height: 50%;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
index b4cbf8e8552..a10db7e4e1a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/console_strings.grdp
@@ -15,11 +15,8 @@
<message name="IDS_DEVTOOLS_04c247c2ba261c7511e4f479728bd7ea" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Do not treat evaluation as user activation
</message>
- <message name="IDS_DEVTOOLS_0511551e6cf7d61acd9b62f9304efa93" desc="Tooltip text that appears on the setting when hovering over it in Console View of the Console panel">
- Do not clear log on page reload / navigation
- </message>
- <message name="IDS_DEVTOOLS_07213a0161f52846ab198be103b5ab43" desc="Text in Console Sidebar of the Console panel">
- errors
+ <message name="IDS_DEVTOOLS_0598dbc1dda8ffdd9f5015fccf675ae1" desc="Text in Console Sidebar of the Console panel to show that there are no user messages">
+ No user messages
</message>
<message name="IDS_DEVTOOLS_0a2f561bf52ee6d8cd2dda123c8f74fe" desc="Text in Console View of the Console panel">
Default levels
@@ -33,17 +30,17 @@
<message name="IDS_DEVTOOLS_0bbce02e304562c295a1d57d66c296d3" desc="Text in Console View Message of the Console panel">
&lt;URL&gt;
</message>
- <message name="IDS_DEVTOOLS_0eaadb4fcb48a0a0ed7bc9868be9fbaa" desc="Accessible name in Console View Message of the Console panel">
- Warning
- </message>
<message name="IDS_DEVTOOLS_0fa06588bd5c83bd6f3b1734eefc6b16" desc="Text in Console View of the Console panel">
Hide messages from <ph name="NEW_COMMON_PARSEDURL_CONSOLEMESSAGE_URL__DISPLAYNAME">$1s<ex>index.js</ex></ph>
</message>
<message name="IDS_DEVTOOLS_1a37d25ba6689d174f51ba8e2425fde6" desc="Filter name in Console Sidebar of the Console panel">
&lt;other&gt;
</message>
- <message name="IDS_DEVTOOLS_1ebc7540a5327b857144f04cf1435b4e" desc="A context menu item in the Console View of the Console panel">
- Replay XHR
+ <message name="IDS_DEVTOOLS_20b290881fd9c9f310c38f92e963193f" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 verbose messages">
+ <ph name="PH1">$1d<ex>2</ex></ph> verbose
+ </message>
+ <message name="IDS_DEVTOOLS_2169b4627df97333ed94d1e30a9b8148" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 errors">
+ <ph name="PH1">$1d<ex>2</ex></ph> errors
</message>
<message name="IDS_DEVTOOLS_26649c8f3cadc9c0170f2443e6fc0252" desc="Text in Console View Message of the Console panel">
&lt;attribute&gt;
@@ -60,9 +57,6 @@
<message name="IDS_DEVTOOLS_2b918231caba2d08f2223246ac06222c" desc="A context menu item in the Console View of the Console panel">
Copy visible styled selection
</message>
- <message name="IDS_DEVTOOLS_2c7aea4237e25b4f8ee3b0bf77d6fed0" desc="Text in Console Sidebar of the Console panel">
- verbose
- </message>
<message name="IDS_DEVTOOLS_2d82fe5a069854a35204b4e64e8e08ae" desc="Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in console view of the console panel">
Console settings
</message>
@@ -70,14 +64,11 @@
[Violation] <ph name="MESSAGETEXT">$1s<ex>console.log(1)</ex></ph>
</message>
<message name="IDS_DEVTOOLS_375855385115b292f160b5131495003d" desc="Message element text content in Console View Message of the Console panel">
- console.clear() was prevented due to &apos;Preserve log&apos;
+ <ph name="LOCKED_1">console.clear()</ph> was prevented due to &apos;Preserve log&apos;
</message>
<message name="IDS_DEVTOOLS_383b1deb90603a79d86f3ae82e55a9e2" desc="Text in Console View of the Console panel">
<ph name="THIS__HIDDENBYFILTERCOUNT">$1s<ex>3</ex></ph> hidden
</message>
- <message name="IDS_DEVTOOLS_3879149292f9af4469cec013785d6dfd" desc="Text in Console Sidebar of the Console panel">
- warnings
- </message>
<message name="IDS_DEVTOOLS_388024c56c38c3d1c635b09a2b28b8ac" desc="Note title in Console View Message of the Console panel">
Value below was evaluated just now.
</message>
@@ -102,17 +93,20 @@
<message name="IDS_DEVTOOLS_4cad9e20fde3f8991c5dd1d6a0fe13e7" desc="A context menu item in the Console Pin Pane of the Console panel">
Remove expression
</message>
- <message name="IDS_DEVTOOLS_4d1b0b75a9737b7dcdc3a15a84fe856b" desc="Title of search progress indicator in console view of the console panel">
- Searching…
- </message>
<message name="IDS_DEVTOOLS_53f0fca28a013c116a1df533d9bdf764" desc="Message text in Console View Message of the Console panel">
[Deprecation] <ph name="MESSAGETEXT">$1s<ex>console.log(1)</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_5ef0c737746fae2ca90e66c39333f8f6" desc="Sdk console message message level error of level Labels in Console View of the Console panel">
- Errors
+ <message name="IDS_DEVTOOLS_5045f70382e14de07fd8328426d7083b" desc="Text in Console Sidebar of the Console panel to show that there is 1 error">
+ 1 error
+ </message>
+ <message name="IDS_DEVTOOLS_58a747ef5d07d22101bdcd058e772ff9" desc="Text in Console Sidebar of the Console panel to show that there are no messages">
+ No messages
</message>
- <message name="IDS_DEVTOOLS_5f8442a46861496e9d2a3d11be13692b" desc="Title of progress indicator in console view of the console panel">
- Writing file…
+ <message name="IDS_DEVTOOLS_59d96b10d94add90060c79efdd8db191" desc="Text in Console Sidebar of the Console panel to show that there are no warnings">
+ No warnings
+ </message>
+ <message name="IDS_DEVTOOLS_5cc9e9d6312328b3f61b7aa86b0b5b5e" desc="Text in Console Sidebar of the Console panel to show that there is 1 user message">
+ 1 user message
</message>
<message name="IDS_DEVTOOLS_6047a6c9fb775557639afb3fbc90b4e7" desc="Text in Console View of the Console panel">
Log levels
@@ -132,23 +126,14 @@
<message name="IDS_DEVTOOLS_6eed4ce2d5859b11dc44a5e3bd91af20" desc="Title of a setting under the Console category in Settings">
Eager evaluation
</message>
- <message name="IDS_DEVTOOLS_78e731027d8fd50ed642340b7c9a63b3" desc="Text in Console Sidebar of the Console panel">
- message
- </message>
<message name="IDS_DEVTOOLS_7a1920d61156abc05a60135aefe8bc67" desc="A context menu item in the Console View of the Console panel">
Default
</message>
- <message name="IDS_DEVTOOLS_7b83d3f08fa392b79e3f553b585971cd" desc="Text in Console Sidebar of the Console panel">
- warning
- </message>
<message name="IDS_DEVTOOLS_7be1a30a7758269755609f1f7434d828" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Group similar messages in console
</message>
- <message name="IDS_DEVTOOLS_84d0c431d1472a0609d69b39dcb3a287" desc="Text in Console View Message of the Console panel">
- (index)
- </message>
- <message name="IDS_DEVTOOLS_902b0d55fddef6f8d651fe1035b7d4bd" desc="Accessible name in Console View Message of the Console panel">
- Error
+ <message name="IDS_DEVTOOLS_7c1e3c25af10fa5d8046dff929148280" desc="Text in Console Sidebar of the Console panel to show that there is 1 info">
+ 1 info
</message>
<message name="IDS_DEVTOOLS_93977f1310f482395375a9950b512462" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Eagerly evaluate console prompt text
@@ -156,11 +141,8 @@
<message name="IDS_DEVTOOLS_95c74dafb449d894014c2eb1d80ded01" desc="A context menu item in the Console Pin Pane of the Console panel">
Edit expression
</message>
- <message name="IDS_DEVTOOLS_9aae9fe27dbf2db0ad90762b5b59d3a7" desc="Title of an action in the console tool to clear">
- Clear console
- </message>
- <message name="IDS_DEVTOOLS_9d8c209e49e328528c39c273798e98c9" desc="A context menu item in the Console View of the Console panel">
- Save as...
+ <message name="IDS_DEVTOOLS_97b0da743d68f96933d990003383ccf1" desc="Text in Console Sidebar of the Console panel to show that there is 1 warning">
+ 1 warning
</message>
<message name="IDS_DEVTOOLS_a092483ed730ed040e5df5776dca49e5" desc="Title of a setting under the Console category in Settings">
Log XMLHttpRequests
@@ -174,29 +156,35 @@
<message name="IDS_DEVTOOLS_a3eb3c95c4cb8e06fd3682c1f0d70bc0" desc="Tooltip text that appears on the setting when hovering over it in Console View of the Console panel">
Only show messages from the current context (top, iframe, worker, extension)
</message>
+ <message name="IDS_DEVTOOLS_a5e4febd4637e35098ee6e8f493ca390" desc="Text in Console Sidebar of the Console panel to show that there is 1 message">
+ 1 message
+ </message>
+ <message name="IDS_DEVTOOLS_a6f9c9bba5831ed632218f165adcfeed" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 messages">
+ <ph name="PH1">$1d<ex>2</ex></ph> messages
+ </message>
<message name="IDS_DEVTOOLS_abba8787b900565790eae8ceceed3c2b" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Do not autocomplete from history
</message>
<message name="IDS_DEVTOOLS_ac17bdcb3f6c8d86ccb64aff1ab8db7c" desc="Message element text content in Console View Message of the Console panel">
Console was cleared
</message>
- <message name="IDS_DEVTOOLS_ac2671ba859591dd83845c680aaa144e" desc="Text in Console Sidebar of the Console panel">
- user messages
- </message>
<message name="IDS_DEVTOOLS_ace3e0307b2ce23a81b18747fc5f555f" desc="Note title in Console View Message of the Console panel">
Function was resolved from bound function.
</message>
+ <message name="IDS_DEVTOOLS_ad410611ff249a09acdba47cc8505186" desc="Text in Console Sidebar of the Console panel to show that there is no verbose messages">
+ No verbose
+ </message>
<message name="IDS_DEVTOOLS_b184e7a44bed11a41d9c104529010e23" desc="Text in Console View of the Console panel">
<ph name="THIS__LEVELLABELS_NAME_">$1s<ex>Warnings</ex></ph> only
</message>
<message name="IDS_DEVTOOLS_b2f8489bbd55a4e9b9edbbbfe49edf70" desc="Text of a DOM element in Console Pin Pane of the Console panel">
not available
</message>
- <message name="IDS_DEVTOOLS_bafd7322c6e97d25b6299b5d6fe8920b" desc="Text in Console Sidebar of the Console panel">
- No
+ <message name="IDS_DEVTOOLS_b4372757bcd49be89af758f485f8666f" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 warnings">
+ <ph name="PH1">$1d<ex>2</ex></ph> warnings
</message>
- <message name="IDS_DEVTOOLS_bccaa4aa80831b76c11240a16447975f" desc="Title of the 'Console' tool in the bottom drawer">
- Console
+ <message name="IDS_DEVTOOLS_bb9a56bce1ad1ae114ffd9807146f3f4" desc="Text in Console Sidebar of the Console panel to show that there is no info">
+ No info
</message>
<message name="IDS_DEVTOOLS_c0274fa278f2e0dfef862234e0eb9b8b" desc="Element text content in Console View Message of the Console panel">
&lt;exception&gt;
@@ -204,6 +192,9 @@
<message name="IDS_DEVTOOLS_c43a34d2abee57824fac5bb704994d88" desc="Text in Console Prompt of the Console panel">
Console prompt
</message>
+ <message name="IDS_DEVTOOLS_c795329f17cb738005b904b650167704" desc="Text in Console Sidebar of the Console panel to show that there is 1 verbose message">
+ 1 verbose
+ </message>
<message name="IDS_DEVTOOLS_c9818b2c0890a205d294a2b31354f8b4" desc="Text in Console View of the Console panel">
All levels
</message>
@@ -216,12 +207,6 @@
<message name="IDS_DEVTOOLS_caf037034c3205725511c1216f772402" desc="Text in Console View Message of the Console panel">
&lt;some&gt; event
</message>
- <message name="IDS_DEVTOOLS_caf9b6b99962bf5c2264824231d7a40c" desc="Text in Console Sidebar of the Console panel">
- info
- </message>
- <message name="IDS_DEVTOOLS_cb5e100e5a9a3e7f6d1fd97512215282" desc="Text in Console Sidebar of the Console panel">
- error
- </message>
<message name="IDS_DEVTOOLS_cf3eed6aa30c47cec1321a835dc7b1ac" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Treat evaluation as user activation
</message>
@@ -243,18 +228,15 @@
<message name="IDS_DEVTOOLS_d7746aa6b562c73487a4015eef3244e9" desc="Text in Console Context Selector of the Console panel">
IFrame
</message>
- <message name="IDS_DEVTOOLS_d7778d0c64b6ba21494c97f77a66885a" desc="Text in Console View of the Console panel">
- Filter
- </message>
<message name="IDS_DEVTOOLS_d779282283c011149d163edbcd5e5f11" desc="Side effect label title in Console Pin Pane of the Console panel">
Evaluate, allowing side effects
</message>
+ <message name="IDS_DEVTOOLS_dd4a2c85f951ba07ba460abc6b726615" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 user messages">
+ <ph name="PH1">$1d<ex>2</ex></ph> user messages
+ </message>
<message name="IDS_DEVTOOLS_de6fc8cb2d1b20158aeda5cd1cb2e03c" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Show messages from all contexts
</message>
- <message name="IDS_DEVTOOLS_de70938849b75d3db63bba421c93e018" desc="Text in Console Sidebar of the Console panel">
- messages
- </message>
<message name="IDS_DEVTOOLS_dfcc689f6e70e39a408b78912822cec9" desc="Accessible name in Console View Message of the Console panel">
Error <ph name="ACCESSIBLENAME">$1s<ex>Repeat 4</ex></ph>
</message>
@@ -267,11 +249,17 @@
<message name="IDS_DEVTOOLS_e1dd1b8e32626f508bd3a5612a60ab97" desc="Title of an action in the console tool to create pin">
Create live expression
</message>
+ <message name="IDS_DEVTOOLS_e6009dd637bf0d330cc5316cd67d9533" desc="Text in Console Sidebar of the Console panel to show that there are more than 1 info">
+ <ph name="PH1">$1d<ex>2</ex></ph> info
+ </message>
<message name="IDS_DEVTOOLS_e6320ee2b5f66ac1520e6156e5ac8fb3" desc="Text in Console Context Selector of the Console panel">
JavaScript context: <ph name="THIS_TITLEFOR_ITEM_">$1s<ex>top</ex></ph>
</message>
<message name="IDS_DEVTOOLS_eacaf2bd1c1414e5086cf04573e154ef" desc="Text in Console View of the Console panel">
- e.g. /event\d/ -cdn url:a.com
+ e.g. <ph name="LOCKED_1">/event\d/ -cdn url:a.com</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_eb7431d253e289bd63b3d73927cd40c1" desc="Text in Console Sidebar of the Console panel to show that there are no errors">
+ No errors
</message>
<message name="IDS_DEVTOOLS_ebfab4df1bb91688c62d4523eba870a5" desc="Title of a setting under the Console category in Settings">
Evaluate triggers user activation
@@ -279,9 +267,6 @@
<message name="IDS_DEVTOOLS_f0b0e075af71ecd9b3435697417c1f05" desc="Title of level menu button in console view of the console panel">
Log level: <ph name="TEXT">$1s<ex>All levels</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_f8ec55cf268ca6106fb23a98523b7549" desc="Text in Console Sidebar of the Console panel">
- user message
- </message>
<message name="IDS_DEVTOOLS_fb554075057f4d116097df434bcef393" desc="Note title in Console View Message of the Console panel">
This value will not be collected until console is cleared.
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console_counters/WarningErrorCounter.js b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/WarningErrorCounter.js
index be51d80a1d3..f5157422e22 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console_counters/WarningErrorCounter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/WarningErrorCounter.js
@@ -6,9 +6,9 @@
* @implements {UI.ToolbarItem.Provider}
* @unrestricted
*/
-ConsoleCounters.WarningErrorCounter = class {
+export default class WarningErrorCounter {
constructor() {
- ConsoleCounters.WarningErrorCounter._instanceForTest = this;
+ WarningErrorCounter._instanceForTest = this;
const countersWrapper = createElement('div');
this._toolbarItem = new UI.ToolbarItem(countersWrapper);
@@ -24,14 +24,16 @@ ConsoleCounters.WarningErrorCounter = class {
});
const violationShadowRoot =
UI.createShadowRootWithCoreStyles(this._violationCounter, 'console_counters/errorWarningCounter.css');
- if (Runtime.experiments.isEnabled('spotlight'))
+ if (Root.Runtime.experiments.isEnabled('spotlight')) {
countersWrapper.appendChild(this._violationCounter);
+ }
this._errors = this._createItem(shadowRoot, 'smallicon-error');
this._warnings = this._createItem(shadowRoot, 'smallicon-warning');
- if (Runtime.experiments.isEnabled('spotlight'))
+ if (Root.Runtime.experiments.isEnabled('spotlight')) {
this._violations = this._createItem(violationShadowRoot, 'smallicon-info');
+ }
this._titles = [];
this._errorCount = -1;
this._warningCount = -1;
@@ -85,8 +87,9 @@ ConsoleCounters.WarningErrorCounter = class {
const errors = SDK.consoleModel.errors();
const warnings = SDK.consoleModel.warnings();
const violations = SDK.consoleModel.violations();
- if (errors === this._errorCount && warnings === this._warningCount && violations === this._violationCount)
+ if (errors === this._errorCount && warnings === this._warningCount && violations === this._violationCount) {
return Promise.resolve();
+ }
this._errorCount = errors;
this._warningCount = warnings;
this._violationCount = violations;
@@ -97,29 +100,34 @@ ConsoleCounters.WarningErrorCounter = class {
this._toolbarItem.setVisible(!!(errors || warnings || violations));
let errorCountTitle = '';
- if (errors === 1)
+ if (errors === 1) {
errorCountTitle = ls`${errors} error`;
- else
+ } else {
errorCountTitle = ls`${errors} errors`;
+ }
this._updateItem(this._errors, errors, false);
- if (errors)
+ if (errors) {
this._titles.push(errorCountTitle);
+ }
let warningCountTitle = '';
- if (warnings === 1)
+ if (warnings === 1) {
warningCountTitle = ls`${warnings} warning`;
- else
+ } else {
warningCountTitle = ls`${warnings} warnings`;
+ }
this._updateItem(this._warnings, warnings, !errors);
- if (warnings)
+ if (warnings) {
this._titles.push(warningCountTitle);
+ }
- if (Runtime.experiments.isEnabled('spotlight')) {
+ if (Root.Runtime.experiments.isEnabled('spotlight')) {
let violationCountTitle = '';
- if (violations === 1)
+ if (violations === 1) {
violationCountTitle = ls`${violations} violation`;
- else
+ } else {
violationCountTitle = ls`${violations} violations`;
+ }
this._updateItem(this._violations, violations, true);
this._violationCounter.title = violationCountTitle;
}
@@ -138,4 +146,13 @@ ConsoleCounters.WarningErrorCounter = class {
item() {
return this._toolbarItem;
}
-};
+}
+
+/* Legacy exported object */
+self.ConsoleCounters = self.ConsoleCounters || {};
+
+/* Legacy exported object */
+ConsoleCounters = ConsoleCounters || {};
+
+/** @constructor */
+ConsoleCounters.WarningErrorCounter = WarningErrorCounter;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console_counters/console_counters.js b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/console_counters.js
new file mode 100644
index 00000000000..4bfc9441265
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/console_counters.js
@@ -0,0 +1,9 @@
+// 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 * as WarningErrorCounter from './WarningErrorCounter.js';
+
+export {
+ WarningErrorCounter,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console_counters/module.json b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/module.json
index 420d1af7712..71b24948918 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console_counters/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console_counters/module.json
@@ -12,7 +12,9 @@
"ui",
"sdk"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "console_counters.js",
"WarningErrorCounter.js"
],
"resources": [
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
index 451be307465..5d7bdfe5a61 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
@@ -33,8 +33,9 @@ ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman
const originalViewportStyle = consoleView._viewport.element.style;
const originalSize = {width: originalViewportStyle.width, height: originalViewportStyle.height};
ConsoleTestRunner.disableConsoleViewport();
- if (consoleView._needsFullUpdate)
+ if (consoleView._needsFullUpdate) {
consoleView._updateMessageList();
+ }
const viewMessages = consoleView._visibleViewMessages;
for (let i = 0; i < viewMessages.length; ++i) {
const uiMessage = viewMessages[i];
@@ -49,8 +50,9 @@ ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman
let depth = 0;
let depthTest = node;
while (depthTest !== element) {
- if (depthTest.nodeType === Node.ELEMENT_NODE && depthTest.className)
+ if (depthTest.nodeType === Node.ELEMENT_NODE && depthTest.className) {
depth++;
+ }
depthTest = depthTest.parentNodeOrShadowHost();
}
classNames.push(
@@ -63,16 +65,18 @@ ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman
}
if (ConsoleTestRunner.dumpConsoleTableMessage(uiMessage, false, result)) {
- if (dumpClassNames)
+ if (dumpClassNames) {
result.push(classNames.join('\n'));
+ }
} else {
let messageText = formatter(element, message);
messageText = messageText.replace(/VM\d+/g, 'VM');
result.push(messageText + (dumpClassNames ? ' ' + classNames.join('\n') : ''));
}
- if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage())
+ if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage()) {
result.push('Originating from: ' + uiMessage.consoleMessage().originatingMessage().messageText);
+ }
}
consoleView._viewport.element.style.width = originalSize.width;
consoleView._viewport.element.style.height = originalSize.height;
@@ -106,16 +110,19 @@ ConsoleTestRunner.prepareConsoleMessageText = function(messageElement) {
* @return {boolean}
*/
ConsoleTestRunner.dumpConsoleTableMessage = function(viewMessage, forceInvalidate, results) {
- if (forceInvalidate)
+ if (forceInvalidate) {
Console.ConsoleView.instance()._viewport.invalidate();
+ }
const table = viewMessage.element();
const headers = table.querySelectorAll('th > div:first-child');
- if (!headers.length)
+ if (!headers.length) {
return false;
+ }
let headerLine = '';
- for (let i = 0; i < headers.length; i++)
+ for (let i = 0; i < headers.length; i++) {
headerLine += headers[i].textContent + ' | ';
+ }
addResult('HEADER ' + headerLine);
@@ -125,21 +132,24 @@ ConsoleTestRunner.dumpConsoleTableMessage = function(viewMessage, forceInvalidat
const row = rows[i];
let rowLine = '';
const items = row.querySelectorAll('td > span');
- for (let j = 0; j < items.length; j++)
+ for (let j = 0; j < items.length; j++) {
rowLine += items[j].textContent + ' | ';
+ }
- if (rowLine.trim())
+ if (rowLine.trim()) {
addResult('ROW ' + rowLine);
+ }
}
/**
* @param {string} x
*/
function addResult(x) {
- if (results)
+ if (results) {
results.push(x);
- else
+ } else {
TestRunner.addResult(x);
+ }
}
return true;
@@ -177,8 +187,9 @@ ConsoleTestRunner.selectMainExecutionContext = function() {
* @param {boolean=} dontForceMainContext
*/
ConsoleTestRunner.evaluateInConsole = function(code, callback, dontForceMainContext) {
- if (!dontForceMainContext)
+ if (!dontForceMainContext) {
ConsoleTestRunner.selectMainExecutionContext();
+ }
callback = TestRunner.safeWrap(callback);
const consoleView = Console.ConsoleView.instance();
@@ -229,6 +240,15 @@ ConsoleTestRunner.evaluateInConsoleAndDump = function(code, callback, dontForceM
};
/**
+ * @param {string} code
+ * @param {boolean=} dontForceMainContext
+ * @return {!Promise}
+ */
+ConsoleTestRunner.evaluateInConsoleAndDumpPromise = function(code, dontForceMainContext) {
+ return new Promise(fulfill => ConsoleTestRunner.evaluateInConsoleAndDump(code, fulfill, dontForceMainContext));
+};
+
+/**
* @return {number}
*/
ConsoleTestRunner.consoleMessagesCount = function() {
@@ -291,8 +311,9 @@ ConsoleTestRunner.dumpConsoleMessagesWithStyles = function() {
const messageText = ConsoleTestRunner.prepareConsoleMessageText(element);
TestRunner.addResult(messageText);
const spans = element.querySelectorAll('.console-message-text *');
- for (let j = 0; j < spans.length; ++j)
+ for (let j = 0; j < spans.length; ++j) {
TestRunner.addResult('Styled text #' + j + ': ' + (spans[j].style.cssText || 'NO STYLES DEFINED'));
+ }
}
};
@@ -308,8 +329,9 @@ ConsoleTestRunner.dumpConsoleMessagesWithClasses = function(sortMessages) {
const messageText = ConsoleTestRunner.prepareConsoleMessageText(element);
result.push(messageText + ' ' + element.getAttribute('class') + ' > ' + contentElement.getAttribute('class'));
}
- if (sortMessages)
+ if (sortMessages) {
result.sort();
+ }
TestRunner.addResults(result);
};
@@ -323,10 +345,12 @@ ConsoleTestRunner.dumpConsoleClassesBrief = function() {
ConsoleTestRunner.dumpConsoleCounters = async function() {
const counter = ConsoleCounters.WarningErrorCounter._instanceForTest;
- if (counter._updatingForTest)
+ if (counter._updatingForTest) {
await TestRunner.addSnifferPromise(counter, '_updatedForTest');
- for (let index = 0; index < counter._titles.length; ++index)
+ }
+ for (let index = 0; index < counter._titles.length; ++index) {
TestRunner.addResult(counter._titles[index]);
+ }
ConsoleTestRunner.dumpConsoleClassesBrief();
};
@@ -340,8 +364,9 @@ ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, section
const messageViews = Console.ConsoleView.instance()._visibleViewMessages;
// Initiate round-trips to fetch necessary data for further rendering.
- for (let i = 0; i < messageViews.length; ++i)
+ for (let i = 0; i < messageViews.length; ++i) {
messageViews[i].element();
+ }
TestRunner.deprecatedRunAfterPendingDispatches(expandTreeElements);
@@ -349,24 +374,30 @@ ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, section
for (let i = 0; i < messageViews.length; ++i) {
const element = messageViews[i].element();
for (let node = element; node; node = node.traverseNextNode(element)) {
- if (node.treeElementForTest)
+ if (node.treeElementForTest) {
node.treeElementForTest.expand();
- if (node._expandStackTraceForTest)
+ }
+ if (node._expandStackTraceForTest) {
node._expandStackTraceForTest();
- if (!node._section)
+ }
+ if (!node._section) {
continue;
- if (sectionFilter && !sectionFilter(node._section))
+ }
+ if (sectionFilter && !sectionFilter(node._section)) {
continue;
+ }
node._section.expand();
- if (!deepFilter)
+ if (!deepFilter) {
continue;
+ }
const treeElements = node._section.rootElement().children();
for (let j = 0; j < treeElements.length; ++j) {
for (let treeElement = treeElements[j]; treeElement;
treeElement = treeElement.traverseNextTreeElement(true, null, true)) {
- if (deepFilter(treeElement))
+ if (deepFilter(treeElement)) {
treeElement.expand();
+ }
}
}
}
@@ -406,8 +437,9 @@ ConsoleTestRunner.expandGettersInConsoleMessages = function(callback) {
function propertyExpandableUpdated() {
--propertiesCount;
if (propertiesCount === 0) {
- for (let i = 0; i < properties.length; ++i)
+ for (let i = 0; i < properties.length; ++i) {
properties[i].click();
+ }
TestRunner.deprecatedRunAfterPendingDispatches(callback);
} else {
TestRunner.addSniffer(
@@ -422,8 +454,9 @@ ConsoleTestRunner.expandGettersInConsoleMessages = function(callback) {
ConsoleTestRunner.expandConsoleMessagesErrorParameters = function(callback) {
const messageViews = Console.ConsoleView.instance()._visibleViewMessages;
// Initiate round-trips to fetch necessary data for further rendering.
- for (let i = 0; i < messageViews.length; ++i)
+ for (let i = 0; i < messageViews.length; ++i) {
messageViews[i].element();
+ }
TestRunner.deprecatedRunAfterPendingDispatches(callback);
};
@@ -432,8 +465,9 @@ ConsoleTestRunner.expandConsoleMessagesErrorParameters = function(callback) {
*/
ConsoleTestRunner.waitForRemoteObjectsConsoleMessages = function(callback) {
const messages = Console.ConsoleView.instance()._visibleViewMessages;
- for (let i = 0; i < messages.length; ++i)
+ for (let i = 0; i < messages.length; ++i) {
messages[i].toMessageElement();
+ }
TestRunner.deprecatedRunAfterPendingDispatches(callback);
};
@@ -451,10 +485,11 @@ ConsoleTestRunner.waitUntilConsoleEditorLoaded = function() {
let fulfill;
const promise = new Promise(x => (fulfill = x));
const prompt = Console.ConsoleView.instance()._prompt;
- if (prompt._editor)
+ if (prompt._editor) {
fulfill(prompt._editor);
- else
+ } else {
TestRunner.addSniffer(Console.ConsolePrompt.prototype, '_editorSetForTest', _ => fulfill(prompt._editor));
+ }
return promise;
};
@@ -478,10 +513,11 @@ ConsoleTestRunner.waitUntilMessageReceivedPromise = function() {
*/
ConsoleTestRunner.waitUntilNthMessageReceived = function(count, callback) {
function override() {
- if (--count === 0)
+ if (--count === 0) {
TestRunner.safeWrap(callback)();
- else
+ } else {
TestRunner.addSniffer(SDK.consoleModel, 'addMessage', override, false);
+ }
}
TestRunner.addSniffer(SDK.consoleModel, 'addMessage', override, false);
};
@@ -563,8 +599,9 @@ ConsoleTestRunner.selectConsoleMessages = function(fromMessage, fromTextOffset,
let charCount = 0;
while ((node = node.traverseNextTextNode(container))) {
const length = node.textContent.length;
- if (charCount + length >= offset)
+ if (charCount + length >= offset) {
return {container: node, offset: offset - charCount};
+ }
charCount += length;
}
@@ -626,8 +663,9 @@ ConsoleTestRunner.visibleIndices = function() {
for (let i = 0; i < consoleView._visibleViewMessages.length; i++) {
// Created message elements may have a bounding rect, but not be connected to DOM.
const item = consoleView._visibleViewMessages[i];
- if (!item._element || !item._element.isConnected)
+ if (!item._element || !item._element.isConnected) {
continue;
+ }
const itemRect = item._element.getBoundingClientRect();
const isVisible = (itemRect.bottom > viewportRect.top + 1) && (itemRect.top <= viewportRect.bottom - 1);
if (isVisible) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/CookiesTable.js b/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/CookiesTable.js
index 0052dedda78..2e181eaac71 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/CookiesTable.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/CookiesTable.js
@@ -33,12 +33,13 @@
*/
CookieTable.CookiesTable = class extends UI.VBox {
/**
+ * @param {boolean=} renderInline
* @param {function(!SDK.Cookie, ?SDK.Cookie): !Promise<boolean>=} saveCallback
* @param {function()=} refreshCallback
* @param {function()=} selectedCallback
* @param {function(!SDK.Cookie, function())=} deleteCallback
*/
- constructor(saveCallback, refreshCallback, selectedCallback, deleteCallback) {
+ constructor(renderInline, saveCallback, refreshCallback, selectedCallback, deleteCallback) {
super();
this._saveCallback = saveCallback;
@@ -49,7 +50,7 @@ CookieTable.CookiesTable = class extends UI.VBox {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
{
- id: 'name',
+ id: SDK.Cookie.Attributes.Name,
title: ls`Name`,
sortable: true,
disclosure: editable,
@@ -58,14 +59,39 @@ CookieTable.CookiesTable = class extends UI.VBox {
weight: 24,
editable: editable
},
- {id: 'value', title: ls`Value`, sortable: true, longText: true, weight: 34, editable: editable},
- {id: 'domain', title: ls`Domain`, sortable: true, weight: 7, editable: editable},
- {id: 'path', title: ls`Path`, sortable: true, weight: 7, editable: editable},
- {id: 'expires', title: ls`Expires / Max-Age`, sortable: true, weight: 7, editable: editable},
- {id: 'size', title: ls`Size`, sortable: true, align: DataGrid.DataGrid.Align.Right, weight: 7},
- {id: 'httpOnly', title: ls`HttpOnly`, sortable: true, align: DataGrid.DataGrid.Align.Center, weight: 7},
- {id: 'secure', title: ls`Secure`, sortable: true, align: DataGrid.DataGrid.Align.Center, weight: 7},
- {id: 'sameSite', title: ls`SameSite`, sortable: true, align: DataGrid.DataGrid.Align.Center, weight: 7}
+ {
+ id: SDK.Cookie.Attributes.Value,
+ title: ls`Value`,
+ sortable: true,
+ longText: true,
+ weight: 34,
+ editable: editable
+ },
+ {id: SDK.Cookie.Attributes.Domain, title: ls`Domain`, sortable: true, weight: 7, editable: editable},
+ {id: SDK.Cookie.Attributes.Path, title: ls`Path`, sortable: true, weight: 7, editable: editable},
+ {id: SDK.Cookie.Attributes.Expires, title: ls`Expires / Max-Age`, sortable: true, weight: 7, editable: editable},
+ {
+ id: SDK.Cookie.Attributes.Size,
+ title: ls`Size`,
+ sortable: true,
+ align: DataGrid.DataGrid.Align.Right,
+ weight: 7
+ },
+ {
+ id: SDK.Cookie.Attributes.HttpOnly,
+ title: ls`HttpOnly`,
+ sortable: true,
+ align: DataGrid.DataGrid.Align.Center,
+ weight: 7
+ },
+ {
+ id: SDK.Cookie.Attributes.Secure,
+ title: ls`Secure`,
+ sortable: true,
+ align: DataGrid.DataGrid.Align.Center,
+ weight: 7
+ },
+ {id: SDK.Cookie.Attributes.SameSite, title: ls`SameSite`, sortable: true, weight: 7}
]);
if (editable) {
@@ -75,12 +101,15 @@ CookieTable.CookiesTable = class extends UI.VBox {
this._dataGrid = new DataGrid.DataGrid(columns);
}
this._dataGrid.setStriped(true);
-
this._dataGrid.setName('cookiesTable');
this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._rebuildTable, this);
+ if (renderInline) {
+ this._dataGrid.renderInline();
+ }
- if (selectedCallback)
+ if (selectedCallback) {
this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, selectedCallback, this);
+ }
/** @type {?string} */
this._lastEditedColumnId = null;
@@ -90,20 +119,26 @@ CookieTable.CookiesTable = class extends UI.VBox {
/** @type {string} */
this._cookieDomain = '';
+
+ /** @type {?Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>} */
+ this._cookieToBlockedReasons = null;
}
/**
* @param {!Array.<!SDK.Cookie>} cookies
+ * @param {!Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>=} cookieToBlockedReasons
*/
- setCookies(cookies) {
- this.setCookieFolders([{cookies: cookies}]);
+ setCookies(cookies, cookieToBlockedReasons) {
+ this.setCookieFolders([{cookies: cookies}], cookieToBlockedReasons);
}
/**
* @param {!Array.<!{folderName: ?string, cookies: ?Array.<!SDK.Cookie>}>} cookieFolders
+ * @param {!Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>=} cookieToBlockedReasons
*/
- setCookieFolders(cookieFolders) {
+ setCookieFolders(cookieFolders, cookieToBlockedReasons) {
this._data = cookieFolders;
+ this._cookieToBlockedReasons = cookieToBlockedReasons || null;
this._rebuildTable();
}
@@ -149,18 +184,21 @@ CookieTable.CookiesTable = class extends UI.VBox {
* @return {?SDK.Cookie}
*/
_findSelectedCookie(selectionCookies, cookies) {
- if (!cookies)
+ if (!cookies) {
return null;
+ }
const current = selectionCookies.current;
const foundCurrent = cookies.find(cookie => this._isSameCookie(cookie, current));
- if (foundCurrent)
+ if (foundCurrent) {
return foundCurrent;
+ }
const neighbor = selectionCookies.neighbor;
const foundNeighbor = cookies.find(cookie => this._isSameCookie(cookie, neighbor));
- if (foundNeighbor)
+ if (foundNeighbor) {
return foundNeighbor;
+ }
return null;
}
@@ -184,17 +222,17 @@ CookieTable.CookiesTable = class extends UI.VBox {
const item = this._data[i];
const selectedCookie = this._findSelectedCookie(selectionCookies, item.cookies);
if (item.folderName) {
- const groupData = {
- name: item.folderName,
- value: '',
- domain: '',
- path: '',
- expires: '',
- size: this._totalSize(item.cookies),
- httpOnly: '',
- secure: '',
- sameSite: ''
- };
+ const groupData = {};
+ groupData[SDK.Cookie.Attributes.Name] = item.folderName;
+ groupData[SDK.Cookie.Attributes.Value] = '';
+ groupData[SDK.Cookie.Attributes.Size] = this._totalSize(item.cookies);
+ groupData[SDK.Cookie.Attributes.Domain] = '';
+ groupData[SDK.Cookie.Attributes.Path] = '';
+ groupData[SDK.Cookie.Attributes.Expires] = '';
+ groupData[SDK.Cookie.Attributes.HttpOnly] = '';
+ groupData[SDK.Cookie.Attributes.Secure] = '';
+ groupData[SDK.Cookie.Attributes.SameSite] = '';
+
const groupNode = new DataGrid.DataGridNode(groupData);
groupNode.selectable = true;
this._dataGrid.rootNode().appendChild(groupNode);
@@ -205,10 +243,12 @@ CookieTable.CookiesTable = class extends UI.VBox {
this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCookie, lastEditedColumnId);
}
}
- if (selectionCookies.current && lastEditedColumnId && !this._dataGrid.selectedNode)
+ if (selectionCookies.current && lastEditedColumnId && !this._dataGrid.selectedNode) {
this._addInactiveNode(this._dataGrid.rootNode(), selectionCookies.current, lastEditedColumnId);
- if (this._saveCallback)
+ }
+ if (this._saveCallback) {
this._dataGrid.addCreationNode(false);
+ }
}
/**
@@ -219,8 +259,9 @@ CookieTable.CookiesTable = class extends UI.VBox {
*/
_populateNode(parentNode, cookies, selectedCookie, lastEditedColumnId) {
parentNode.removeChildren();
- if (!cookies)
+ if (!cookies) {
return;
+ }
this._sortCookies(cookies);
for (let i = 0; i < cookies.length; ++i) {
@@ -229,8 +270,9 @@ CookieTable.CookiesTable = class extends UI.VBox {
parentNode.appendChild(cookieNode);
if (this._isSameCookie(cookie, selectedCookie)) {
cookieNode.select();
- if (lastEditedColumnId !== null)
+ if (lastEditedColumnId !== null) {
this._dataGrid.startEditingNextEditableColumnOfDataGridNode(cookieNode, lastEditedColumnId);
+ }
}
}
}
@@ -245,14 +287,16 @@ CookieTable.CookiesTable = class extends UI.VBox {
parentNode.appendChild(cookieNode);
cookieNode.select();
cookieNode.setInactive(true);
- if (editedColumnId !== null)
+ if (editedColumnId !== null) {
this._dataGrid.startEditingNextEditableColumnOfDataGridNode(cookieNode, editedColumnId);
+ }
}
_totalSize(cookies) {
let totalSize = 0;
- for (let i = 0; cookies && i < cookies.length; ++i)
+ for (let i = 0; cookies && i < cookies.length; ++i) {
totalSize += cookies[i].size();
+ }
return totalSize;
}
@@ -275,6 +319,7 @@ CookieTable.CookiesTable = class extends UI.VBox {
* @param {string} property
* @param {!SDK.Cookie} cookie1
* @param {!SDK.Cookie} cookie2
+ * @return {number}
*/
function compareTo(property, cookie1, cookie2) {
return sortDirection * getValue(cookie1, property).compareTo(getValue(cookie2, property));
@@ -283,6 +328,7 @@ CookieTable.CookiesTable = class extends UI.VBox {
/**
* @param {!SDK.Cookie} cookie1
* @param {!SDK.Cookie} cookie2
+ * @return {number}
*/
function numberCompare(cookie1, cookie2) {
return sortDirection * (cookie1.size() - cookie2.size());
@@ -291,29 +337,35 @@ CookieTable.CookiesTable = class extends UI.VBox {
/**
* @param {!SDK.Cookie} cookie1
* @param {!SDK.Cookie} cookie2
+ * @return {number}
*/
function expiresCompare(cookie1, cookie2) {
- if (cookie1.session() !== cookie2.session())
+ if (cookie1.session() !== cookie2.session()) {
return sortDirection * (cookie1.session() ? 1 : -1);
+ }
- if (cookie1.session())
+ if (cookie1.session()) {
return 0;
+ }
- if (cookie1.maxAge() && cookie2.maxAge())
+ if (cookie1.maxAge() && cookie2.maxAge()) {
return sortDirection * (cookie1.maxAge() - cookie2.maxAge());
- if (cookie1.expires() && cookie2.expires())
+ }
+ if (cookie1.expires() && cookie2.expires()) {
return sortDirection * (cookie1.expires() - cookie2.expires());
+ }
return sortDirection * (cookie1.expires() ? 1 : -1);
}
let comparator;
const columnId = this._dataGrid.sortColumnId() || 'name';
- if (columnId === 'expires')
+ if (columnId === 'expires') {
comparator = expiresCompare;
- else if (columnId === 'size')
+ } else if (columnId === 'size') {
comparator = numberCompare;
- else
+ } else {
comparator = compareTo.bind(null, columnId);
+ }
cookies.sort(comparator);
}
@@ -323,34 +375,38 @@ CookieTable.CookiesTable = class extends UI.VBox {
*/
_createGridNode(cookie) {
const data = {};
- data.name = cookie.name();
- data.value = cookie.value();
+ data[SDK.Cookie.Attributes.Name] = cookie.name();
+ data[SDK.Cookie.Attributes.Value] = cookie.value();
+
if (cookie.type() === SDK.Cookie.Type.Request) {
- data.domain = Common.UIString('N/A');
- data.path = Common.UIString('N/A');
- data.expires = Common.UIString('N/A');
+ data[SDK.Cookie.Attributes.Domain] = cookie.domain() ? cookie.domain() : ls`N/A`;
+ data[SDK.Cookie.Attributes.Path] = cookie.path() ? cookie.path() : ls`N/A`;
} else {
- data.domain = cookie.domain() || '';
- data.path = cookie.path() || '';
- if (cookie.maxAge()) {
- data.expires = Number.secondsToString(parseInt(cookie.maxAge(), 10));
- } else if (cookie.expires()) {
- if (cookie.expires() < 0)
- data.expires = CookieTable.CookiesTable._expiresSessionValue;
- else
- data.expires = new Date(cookie.expires()).toISOString();
+ data[SDK.Cookie.Attributes.Domain] = cookie.domain() || '';
+ data[SDK.Cookie.Attributes.Path] = cookie.path() || '';
+ }
+
+ if (cookie.maxAge()) {
+ data[SDK.Cookie.Attributes.Expires] = Number.secondsToString(parseInt(cookie.maxAge(), 10));
+ } else if (cookie.expires()) {
+ if (cookie.expires() < 0) {
+ data[SDK.Cookie.Attributes.Expires] = CookieTable.CookiesTable._expiresSessionValue;
} else {
- data.expires = CookieTable.CookiesTable._expiresSessionValue;
+ data[SDK.Cookie.Attributes.Expires] = new Date(cookie.expires()).toISOString();
}
+ } else {
+ data[SDK.Cookie.Attributes.Expires] =
+ cookie.type() === SDK.Cookie.Type.Request ? ls`N/A` : CookieTable.CookiesTable._expiresSessionValue;
}
- data.size = cookie.size();
+
+ data[SDK.Cookie.Attributes.Size] = cookie.size();
const checkmark = '\u2713';
- data.httpOnly = (cookie.httpOnly() ? checkmark : '');
- data.secure = (cookie.secure() ? checkmark : '');
- data.sameSite = cookie.sameSite() || '';
+ data[SDK.Cookie.Attributes.HttpOnly] = (cookie.httpOnly() ? checkmark : '');
+ data[SDK.Cookie.Attributes.Secure] = (cookie.secure() ? checkmark : '');
+ data[SDK.Cookie.Attributes.SameSite] = cookie.sameSite() || '';
- const node = new DataGrid.DataGridNode(data);
- node.cookie = cookie;
+ const node = new CookieTable.DataGridNode(
+ data, cookie, this._cookieToBlockedReasons ? this._cookieToBlockedReasons.get(cookie) : null);
node.selectable = true;
return node;
}
@@ -359,8 +415,9 @@ CookieTable.CookiesTable = class extends UI.VBox {
* @param {!DataGrid.DataGridNode} node
*/
_onDeleteCookie(node) {
- if (node.cookie && this._deleteCallback)
+ if (node.cookie && this._deleteCallback) {
this._deleteCallback(node.cookie, () => this._refresh());
+ }
}
/**
@@ -372,26 +429,32 @@ CookieTable.CookiesTable = class extends UI.VBox {
_onUpdateCookie(editingNode, columnIdentifier, oldText, newText) {
this._lastEditedColumnId = columnIdentifier;
this._setDefaults(editingNode);
- if (this._isValidCookieData(editingNode.data))
+ if (this._isValidCookieData(editingNode.data)) {
this._saveNode(editingNode);
- else
+ } else {
editingNode.setDirty(true);
+ }
}
/**
* @param {!DataGrid.DataGridNode} node
*/
_setDefaults(node) {
- if (node.data.name === null)
- node.data.name = '';
- if (node.data.value === null)
- node.data.value = '';
- if (node.data.domain === null)
- node.data.domain = this._cookieDomain;
- if (node.data.path === null)
- node.data.path = '/';
- if (node.data.expires === null)
- node.data.expires = CookieTable.CookiesTable._expiresSessionValue;
+ if (node.data[SDK.Cookie.Attributes.Name] === null) {
+ node.data[SDK.Cookie.Attributes.Name] = '';
+ }
+ if (node.data[SDK.Cookie.Attributes.Value] === null) {
+ node.data[SDK.Cookie.Attributes.Value] = '';
+ }
+ if (node.data[SDK.Cookie.Attributes.Domain] === null) {
+ node.data[SDK.Cookie.Attributes.Domain] = this._cookieDomain;
+ }
+ if (node.data[SDK.Cookie.Attributes.Path] === null) {
+ node.data[SDK.Cookie.Attributes.Path] = '/';
+ }
+ if (node.data[SDK.Cookie.Attributes.Expires] === null) {
+ node.data[SDK.Cookie.Attributes.Expires] = CookieTable.CookiesTable._expiresSessionValue;
+ }
}
/**
@@ -402,30 +465,35 @@ CookieTable.CookiesTable = class extends UI.VBox {
const newCookie = this._createCookieFromData(node.data);
node.cookie = newCookie;
this._saveCallback(newCookie, oldCookie).then(success => {
- if (success)
+ if (success) {
this._refresh();
- else
+ } else {
node.setDirty(true);
+ }
});
}
/**
- * @param {!Object.<string, *>} data
+ * @param {!Object.<string, string>} data
* @returns {!SDK.Cookie}
*/
_createCookieFromData(data) {
- const cookie = new SDK.Cookie(data.name, data.value, null);
- cookie.addAttribute('domain', data.domain);
- cookie.addAttribute('path', data.path);
- if (data.expires && data.expires !== CookieTable.CookiesTable._expiresSessionValue)
- cookie.addAttribute('expires', (new Date(data.expires)).toUTCString());
- if (data.httpOnly)
- cookie.addAttribute('httpOnly');
- if (data.secure)
- cookie.addAttribute('secure');
- if (data.sameSite)
- cookie.addAttribute('sameSite', data.sameSite);
- cookie.setSize(data.name.length + data.value.length);
+ const cookie = new SDK.Cookie(data[SDK.Cookie.Attributes.Name], data[SDK.Cookie.Attributes.Value], null);
+ cookie.addAttribute(SDK.Cookie.Attributes.Domain, data[SDK.Cookie.Attributes.Domain]);
+ cookie.addAttribute(SDK.Cookie.Attributes.Path, data[SDK.Cookie.Attributes.Path]);
+ if (data.expires && data.expires !== CookieTable.CookiesTable._expiresSessionValue) {
+ cookie.addAttribute(SDK.Cookie.Attributes.Expires, (new Date(data[SDK.Cookie.Attributes.Expires])).toUTCString());
+ }
+ if (data[SDK.Cookie.Attributes.HttpOnly]) {
+ cookie.addAttribute(SDK.Cookie.Attributes.HttpOnly);
+ }
+ if (data[SDK.Cookie.Attributes.Secure]) {
+ cookie.addAttribute(SDK.Cookie.Attributes.Secure);
+ }
+ if (data[SDK.Cookie.Attributes.SameSite]) {
+ cookie.addAttribute(SDK.Cookie.Attributes.SameSite, data[SDK.Cookie.Attributes.SameSite]);
+ }
+ cookie.setSize(data[SDK.Cookie.Attributes.Name].length + data[SDK.Cookie.Attributes.Value].length);
return cookie;
}
@@ -443,8 +511,9 @@ CookieTable.CookiesTable = class extends UI.VBox {
* @returns {boolean}
*/
_isValidDomain(domain) {
- if (!domain)
+ if (!domain) {
return true;
+ }
const parsedURL = ('http://' + domain).asParsedURL();
return !!parsedURL && parsedURL.domain() === domain;
}
@@ -467,10 +536,71 @@ CookieTable.CookiesTable = class extends UI.VBox {
}
_refresh() {
- if (this._refreshCallback)
+ if (this._refreshCallback) {
this._refreshCallback();
+ }
+ }
+};
+
+CookieTable.DataGridNode = class extends DataGrid.DataGridNode {
+ /**
+ * @param {!Object<string, *>} data
+ * @param {!SDK.Cookie} cookie
+ * @param {?Array<!CookieTable.BlockedReason>} blockedReasons
+ */
+ constructor(data, cookie, blockedReasons) {
+ super(data);
+ this.cookie = cookie;
+ this._blockedReasons = blockedReasons;
+ }
+
+ /**
+ * @override
+ * @param {!Element} element
+ */
+ createCells(element) {
+ super.createCells(element);
+ if (this._blockedReasons && this._blockedReasons.length) {
+ element.classList.add('flagged-cookie-attribute-row');
+ }
+ }
+
+ /**
+ * @override
+ * @param {string} columnId
+ * @return {!Element}
+ */
+ createCell(columnId) {
+ const cell = super.createCell(columnId);
+ cell.title = cell.textContent;
+
+ let blockedReasonString = '';
+ if (this._blockedReasons) {
+ for (const blockedReason of this._blockedReasons) {
+ const attributeMatches = blockedReason.attribute === /** @type {!SDK.Cookie.Attributes} */ (columnId);
+ const useNameColumn = !blockedReason.attribute && columnId === SDK.Cookie.Attributes.Name;
+ if (attributeMatches || useNameColumn) {
+ if (blockedReasonString) {
+ blockedReasonString += '\n';
+ }
+ blockedReasonString += blockedReason.uiString;
+ }
+ }
+ }
+
+ if (blockedReasonString) {
+ const infoElement = UI.Icon.create('smallicon-info', 'cookie-warning-icon');
+ infoElement.title = blockedReasonString;
+ cell.insertBefore(infoElement, cell.firstChild);
+ cell.classList.add('flagged-cookie-attribute-cell');
+ }
+
+ return cell;
}
};
/** @const */
CookieTable.CookiesTable._expiresSessionValue = Common.UIString('Session');
+
+/** @typedef {!{uiString: string, attribute: ?SDK.Cookie.Attributes}} */
+CookieTable.BlockedReason;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
index d4e0c86724c..9f3f28ce6bb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/cookie_table/cookie_table_strings.grdp
@@ -3,28 +3,13 @@
<message name="IDS_DEVTOOLS_2e7501c512976a9d9a9dca45bce9f128" desc="Text in Cookies Table of the Cookies table in the Application panel">
Expires / Max-Age
</message>
- <message name="IDS_DEVTOOLS_382b0f5185773fa0f67a8ed8056c7759" desc="Data expires in Cookies Table of the Cookies table in the Application panel">
- N/A
- </message>
<message name="IDS_DEVTOOLS_6c8f0cef6081f0f97ec0f01a5a3ce2a7" desc="Text in Cookies Table of the Cookies table in the Application panel">
HttpOnly
</message>
- <message name="IDS_DEVTOOLS_6f6cb72d544962fa333e2e34ce64f719" desc="Text in Cookies Table of the Cookies table in the Application panel">
- Size
- </message>
<message name="IDS_DEVTOOLS_71c7ae294b7abd866b3fb295b3b9e4a4" desc="Cookie table cookies table expires session value in Cookies Table of the Cookies table in the Application panel">
Session
</message>
- <message name="IDS_DEVTOOLS_7a2ccf251ecb20b2b84ce0e3c3f72a29" desc="Text in Cookies Table of the Cookies table in the Application panel">
- Secure
- </message>
<message name="IDS_DEVTOOLS_9f8e4d5e9b6d7a439dc6b5ebc5eedca4" desc="Text in Cookies Table of the Cookies table in the Application panel">
SameSite
</message>
- <message name="IDS_DEVTOOLS_ac70412e939d72a9234cdebb1af5867b" desc="Text in Cookies Table of the Cookies table in the Application panel">
- Path
- </message>
- <message name="IDS_DEVTOOLS_eae639a70006feff484a39363c977e24" desc="Text in Cookies Table of the Cookies table in the Application panel">
- Domain
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageDecorationManager.js b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageDecorationManager.js
index 8aa45139ba7..b3a34f81d28 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageDecorationManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageDecorationManager.js
@@ -20,20 +20,19 @@ Coverage.CoverageDecorationManager = class {
this._coverageModel = coverageModel;
/** @type {!Map<!Common.ContentProvider, ?TextUtils.Text>} */
this._textByProvider = new Map();
- /** @type {!Multimap<!Common.ContentProvider, !Workspace.UISourceCode>} */
- this._uiSourceCodeByContentProvider = new Multimap();
- // TODO(crbug.com/720162): get rid of this, use bindings.
- /** @type {!WeakMap<!Workspace.UISourceCode, !Array<!SDK.CSSStyleSheetHeader>>} */
- this._documentUISouceCodeToStylesheets = new WeakMap();
+ /** @type {!Platform.Multimap<!Common.ContentProvider, !Workspace.UISourceCode>} */
+ this._uiSourceCodeByContentProvider = new Platform.Multimap();
- for (const uiSourceCode of Workspace.workspace.uiSourceCodes())
+ for (const uiSourceCode of Workspace.workspace.uiSourceCodes()) {
uiSourceCode.addLineDecoration(0, Coverage.CoverageDecorationManager._decoratorType, this);
+ }
Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._onUISourceCodeAdded, this);
}
reset() {
- for (const uiSourceCode of Workspace.workspace.uiSourceCodes())
+ for (const uiSourceCode of Workspace.workspace.uiSourceCodes()) {
uiSourceCode.removeDecorationsForType(Coverage.CoverageDecorationManager._decoratorType);
+ }
}
dispose() {
@@ -60,7 +59,11 @@ Coverage.CoverageDecorationManager = class {
*/
async usageByLine(uiSourceCode) {
const result = [];
- const sourceText = new TextUtils.Text(uiSourceCode.content() || '');
+ const {content} = await uiSourceCode.requestContent();
+ if (!content) {
+ return [];
+ }
+ const sourceText = new TextUtils.Text(/** @type {string} */ (content));
await this._updateTexts(uiSourceCode, sourceText);
const lineEndings = sourceText.lineEndings();
for (let line = 0; line < sourceText.lineCount(); ++line) {
@@ -75,25 +78,32 @@ Coverage.CoverageDecorationManager = class {
for (let startIndex = 0, endIndex = 0; startIndex < startLocations.length; ++startIndex) {
const start = startLocations[startIndex];
while (endIndex < endLocations.length &&
- Coverage.CoverageDecorationManager._compareLocations(start, endLocations[endIndex]) >= 0)
+ Coverage.CoverageDecorationManager._compareLocations(start, endLocations[endIndex]) >= 0) {
++endIndex;
- if (endIndex >= endLocations.length || endLocations[endIndex].id !== start.id)
+ }
+ if (endIndex >= endLocations.length || endLocations[endIndex].id !== start.id) {
continue;
+ }
const end = endLocations[endIndex++];
const text = this._textByProvider.get(end.contentProvider);
- if (!text)
+ if (!text) {
continue;
+ }
const textValue = text.value();
let startOffset = Math.min(text.offsetFromPosition(start.line, start.column), textValue.length - 1);
let endOffset = Math.min(text.offsetFromPosition(end.line, end.column), textValue.length - 1);
- while (startOffset <= endOffset && /\s/.test(textValue[startOffset]))
+ while (startOffset <= endOffset && /\s/.test(textValue[startOffset])) {
++startOffset;
- while (startOffset <= endOffset && /\s/.test(textValue[endOffset]))
+ }
+ while (startOffset <= endOffset && /\s/.test(textValue[endOffset])) {
--endOffset;
- if (startOffset <= endOffset)
+ }
+ if (startOffset <= endOffset) {
used = this._coverageModel.usageForRange(end.contentProvider, startOffset, endOffset);
- if (used)
+ }
+ if (used) {
break;
+ }
}
result.push(used);
}
@@ -109,8 +119,9 @@ Coverage.CoverageDecorationManager = class {
const promises = [];
for (let line = 0; line < text.lineCount(); ++line) {
for (const entry of this._rawLocationsForSourceLocation(uiSourceCode, line, 0)) {
- if (this._textByProvider.has(entry.contentProvider))
+ if (this._textByProvider.has(entry.contentProvider)) {
continue;
+ }
this._textByProvider.set(entry.contentProvider, null);
this._uiSourceCodeByContentProvider.set(entry.contentProvider, uiSourceCode);
promises.push(this._updateTextForProvider(entry.contentProvider));
@@ -124,8 +135,8 @@ Coverage.CoverageDecorationManager = class {
* @return {!Promise}
*/
async _updateTextForProvider(contentProvider) {
- const content = await contentProvider.requestContent();
- this._textByProvider.set(contentProvider, new TextUtils.Text(content));
+ const {content} = await contentProvider.requestContent();
+ this._textByProvider.set(contentProvider, new TextUtils.Text(content || ''));
}
/**
@@ -140,41 +151,35 @@ Coverage.CoverageDecorationManager = class {
if (contentType.hasScripts()) {
let locations = Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(uiSourceCode, line, column);
locations = locations.filter(location => !!location.script());
- for (let location of locations) {
+ for (const location of locations) {
const script = location.script();
if (script.isInlineScript() && contentType.isDocument()) {
- if (comparePositions(script.lineOffset, script.columnOffset, location.lineNumber, location.columnNumber) >
- 0 ||
- comparePositions(script.endLine, script.endColumn, location.lineNumber, location.columnNumber) <= 0) {
- location = null;
- } else {
- location.lineNumber -= script.lineOffset;
- if (!location.lineNumber)
- location.columnNumber -= script.columnOffset;
+ location.lineNumber -= script.lineOffset;
+ if (!location.lineNumber) {
+ location.columnNumber -= script.columnOffset;
}
}
- if (location) {
- result.push({
- id: `js:${location.scriptId}`,
- contentProvider: location.script(),
- line: location.lineNumber,
- column: location.columnNumber
- });
- }
+ result.push({
+ id: `js:${location.scriptId}`,
+ contentProvider: location.script(),
+ line: location.lineNumber,
+ column: location.columnNumber
+ });
}
}
if (contentType.isStyleSheet() || contentType.isDocument()) {
- const rawStyleLocations = contentType.isDocument() ?
- this._documentUILocationToCSSRawLocations(uiSourceCode, line, column) :
+ const rawStyleLocations =
Bindings.cssWorkspaceBinding.uiLocationToRawLocations(new Workspace.UILocation(uiSourceCode, line, column));
for (const location of rawStyleLocations) {
const header = location.header();
- if (!header)
+ if (!header) {
continue;
+ }
if (header.isInline && contentType.isDocument()) {
location.lineNumber -= header.startLine;
- if (!location.lineNumber)
+ if (!location.lineNumber) {
location.columnNumber -= header.startColumn;
+ }
}
result.push({
id: `css:${location.styleSheetId}`,
@@ -184,64 +189,7 @@ Coverage.CoverageDecorationManager = class {
});
}
}
- result.sort(Coverage.CoverageDecorationManager._compareLocations);
-
- /**
- * @param {number} aLine
- * @param {number} aColumn
- * @param {number} bLine
- * @param {number} bColumn
- * @return {number}
- */
- function comparePositions(aLine, aColumn, bLine, bColumn) {
- return aLine - bLine || aColumn - bColumn;
- }
- return result;
- }
-
- /**
- * TODO(crbug.com/720162): get rid of this, use bindings.
- *
- * @param {!Workspace.UISourceCode} uiSourceCode
- * @param {number} line
- * @param {number} column
- * @return {!Array<!SDK.CSSLocation>}
- */
- _documentUILocationToCSSRawLocations(uiSourceCode, line, column) {
- let stylesheets = this._documentUISouceCodeToStylesheets.get(uiSourceCode);
- if (!stylesheets) {
- stylesheets = [];
- const cssModel = this._coverageModel.target().model(SDK.CSSModel);
- if (!cssModel)
- return [];
- for (const headerId of cssModel.styleSheetIdsForURL(uiSourceCode.url())) {
- const header = cssModel.styleSheetHeaderForId(headerId);
- if (header)
- stylesheets.push(header);
- }
- stylesheets.sort(stylesheetComparator);
- this._documentUISouceCodeToStylesheets.set(uiSourceCode, stylesheets);
- }
- const endIndex =
- stylesheets.upperBound(undefined, (unused, header) => line - header.startLine || column - header.startColumn);
- if (!endIndex)
- return [];
- const locations = [];
- const last = stylesheets[endIndex - 1];
- for (let index = endIndex - 1; index >= 0 && stylesheets[index].startLine === last.startLine &&
- stylesheets[index].startColumn === last.startColumn;
- --index)
- locations.push(new SDK.CSSLocation(stylesheets[index], line, column));
-
- return locations;
- /**
- * @param {!SDK.CSSStyleSheetHeader} a
- * @param {!SDK.CSSStyleSheetHeader} b
- * @return {number}
- */
- function stylesheetComparator(a, b) {
- return a.startLine - b.startLine || a.startColumn - b.startColumn || a.id.localeCompare(b.id);
- }
+ return result.sort(Coverage.CoverageDecorationManager._compareLocations);
}
/**
@@ -267,6 +215,11 @@ Coverage.CoverageDecorationManager._decoratorType = 'coverage';
* @implements {SourceFrame.LineDecorator}
*/
Coverage.CoverageView.LineDecorator = class {
+ constructor() {
+ /** @type {!WeakMap<!TextEditor.CodeMirrorTextEditor, function(!Common.Event)>} */
+ this._listeners = new WeakMap();
+ }
+
/**
* @override
* @param {!Workspace.UISourceCode} uiSourceCode
@@ -275,32 +228,83 @@ Coverage.CoverageView.LineDecorator = class {
decorate(uiSourceCode, textEditor) {
const decorations = uiSourceCode.decorationsForType(Coverage.CoverageDecorationManager._decoratorType);
if (!decorations || !decorations.size) {
- textEditor.uninstallGutter(Coverage.CoverageView.LineDecorator._gutterType);
+ this._uninstallGutter(textEditor);
return;
}
const decorationManager =
/** @type {!Coverage.CoverageDecorationManager} */ (decorations.values().next().value.data());
decorationManager.usageByLine(uiSourceCode).then(lineUsage => {
- textEditor.operation(() => this._innerDecorate(textEditor, lineUsage));
+ textEditor.operation(() => this._innerDecorate(uiSourceCode, textEditor, lineUsage));
});
}
/**
+ * @param {!Workspace.UISourceCode} uiSourceCode
* @param {!TextEditor.CodeMirrorTextEditor} textEditor
* @param {!Array<boolean>} lineUsage
*/
- _innerDecorate(textEditor, lineUsage) {
+ _innerDecorate(uiSourceCode, textEditor, lineUsage) {
const gutterType = Coverage.CoverageView.LineDecorator._gutterType;
- textEditor.uninstallGutter(gutterType);
- textEditor.installGutter(gutterType, false);
+ this._uninstallGutter(textEditor);
+ if (lineUsage.length) {
+ this._installGutter(textEditor, uiSourceCode.url());
+ }
for (let line = 0; line < lineUsage.length; ++line) {
// Do not decorate the line if we don't have data.
- if (typeof lineUsage[line] !== 'boolean')
+ if (typeof lineUsage[line] !== 'boolean') {
continue;
+ }
const className = lineUsage[line] ? 'text-editor-coverage-used-marker' : 'text-editor-coverage-unused-marker';
- textEditor.setGutterDecoration(line, gutterType, createElementWithClass('div', className));
+ const gutterElement = createElementWithClass('div', className);
+ textEditor.setGutterDecoration(line, gutterType, gutterElement);
+ }
+ }
+
+ /**
+ * @param {string} url - the url of the file this click handler will select in the coverage drawer
+ * @return {function(!Common.Event)}
+ */
+ makeGutterClickHandler(url) {
+ function handleGutterClick(event) {
+ const eventData = /** @type {!SourceFrame.SourcesTextEditor.GutterClickEventData} */ (event.data);
+ if (eventData.gutterType !== Coverage.CoverageView.LineDecorator._gutterType) {
+ return;
+ }
+ const coverageViewId = 'coverage';
+ UI.viewManager.showView(coverageViewId).then(() => UI.viewManager.view(coverageViewId).widget()).then(widget => {
+ const matchFormattedSuffix = url.match(/(.*):formatted$/);
+ const urlWithoutFormattedSuffix = (matchFormattedSuffix && matchFormattedSuffix[1]) || url;
+ widget.selectCoverageItemByUrl(urlWithoutFormattedSuffix);
+ });
+ }
+ return handleGutterClick;
+ }
+
+ /**
+ * @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to install the gutter on
+ * @param {string} url - the url of the file in the text editor
+ */
+ _installGutter(textEditor, url) {
+ let listener = this._listeners.get(textEditor);
+ if (!listener) {
+ listener = this.makeGutterClickHandler(url);
+ this._listeners.set(textEditor, listener);
+ }
+ textEditor.installGutter(Coverage.CoverageView.LineDecorator._gutterType, false);
+ textEditor.addEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
+ }
+
+ /**
+ * @param {!TextEditor.CodeMirrorTextEditor} textEditor - the text editor to uninstall the gutter from
+ */
+ _uninstallGutter(textEditor) {
+ textEditor.uninstallGutter(Coverage.CoverageView.LineDecorator._gutterType);
+ const listener = this._listeners.get(textEditor);
+ if (listener) {
+ textEditor.removeEventListener(SourceFrame.SourcesTextEditor.Events.GutterClick, listener, this);
+ this._listeners.delete(textEditor);
}
}
};
-Coverage.CoverageView.LineDecorator._gutterType = 'CodeMirror-gutter-coverage'; \ No newline at end of file
+Coverage.CoverageView.LineDecorator._gutterType = 'CodeMirror-gutter-coverage';
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageListView.js b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageListView.js
index c3ed61c4601..88ed965fafb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageListView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageListView.js
@@ -56,8 +56,9 @@ Coverage.CoverageListView = class extends UI.VBox {
for (const entry of coverageInfo) {
let node = this._nodeForCoverageInfo.get(entry);
if (node) {
- if (this._filterCallback(node._coverageInfo))
+ if (this._filterCallback(node._coverageInfo)) {
hadUpdates = node._refreshIfNeeded(maxSize) || hadUpdates;
+ }
continue;
}
node = new Coverage.CoverageListView.GridNode(entry, maxSize);
@@ -67,8 +68,9 @@ Coverage.CoverageListView = class extends UI.VBox {
hadUpdates = true;
}
}
- if (hadUpdates)
+ if (hadUpdates) {
this._sortingChanged();
+ }
}
reset() {
@@ -85,18 +87,31 @@ Coverage.CoverageListView = class extends UI.VBox {
for (const node of this._nodeForCoverageInfo.values()) {
const shouldBeVisible = this._filterCallback(node._coverageInfo);
const isVisible = !!node.parent;
- if (shouldBeVisible)
+ if (shouldBeVisible) {
node._setHighlight(this._highlightRegExp);
- if (shouldBeVisible === isVisible)
+ }
+ if (shouldBeVisible === isVisible) {
continue;
+ }
hadTreeUpdates = true;
- if (!shouldBeVisible)
+ if (!shouldBeVisible) {
node.remove();
- else
+ } else {
this._dataGrid.rootNode().appendChild(node);
+ }
}
- if (hadTreeUpdates)
+ if (hadTreeUpdates) {
this._sortingChanged();
+ }
+ }
+
+ selectByUrl(url) {
+ for (const [info, node] of this._nodeForCoverageInfo.entries()) {
+ if (info.url() === url) {
+ node.revealAndSelect();
+ break;
+ }
+ }
}
_onOpenedNode() {
@@ -107,35 +122,39 @@ Coverage.CoverageListView = class extends UI.VBox {
* @param {!Event} event
*/
_onKeyDown(event) {
- if (!isEnterKey(event))
+ if (!isEnterKey(event)) {
return;
+ }
event.consume(true);
this._revealSourceForSelectedNode();
}
async _revealSourceForSelectedNode() {
const node = this._dataGrid.selectedNode;
- if (!node)
+ if (!node) {
return;
+ }
const coverageInfo = /** @type {!Coverage.CoverageListView.GridNode} */ (node)._coverageInfo;
let sourceCode = Workspace.workspace.uiSourceCodeForURL(coverageInfo.url());
- if (!sourceCode)
+ if (!sourceCode) {
return;
- const content = await sourceCode.requestContent();
+ }
+ const content = (await sourceCode.requestContent()).content || '';
if (TextUtils.isMinified(content)) {
const formatData = await Sources.sourceFormatter.format(sourceCode);
- // ------------ ASYNC ------------
sourceCode = formatData.formattedSourceCode;
}
- if (this._dataGrid.selectedNode !== node)
+ if (this._dataGrid.selectedNode !== node) {
return;
+ }
Common.Revealer.reveal(sourceCode);
}
_sortingChanged() {
const columnId = this._dataGrid.sortColumnId();
- if (!columnId)
+ if (!columnId) {
return;
+ }
let sortFunction;
switch (columnId) {
case 'url':
@@ -202,12 +221,14 @@ Coverage.CoverageListView = class extends UI.VBox {
*/
static _typeToString(type) {
const types = [];
- if (type & Coverage.CoverageType.CSS)
+ if (type & Coverage.CoverageType.CSS) {
types.push(Common.UIString('CSS'));
- if (type & Coverage.CoverageType.JavaScriptCoarse)
+ }
+ if (type & Coverage.CoverageType.JavaScriptCoarse) {
types.push(Common.UIString('JS (coarse)'));
- else if (type & Coverage.CoverageType.JavaScript)
+ } else if (type & Coverage.CoverageType.JavaScript) {
types.push(Common.UIString('JS'));
+ }
return types.join('+');
}
};
@@ -233,8 +254,9 @@ Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode
* @param {?RegExp} highlightRegExp
*/
_setHighlight(highlightRegExp) {
- if (this._highlightRegExp === highlightRegExp)
+ if (this._highlightRegExp === highlightRegExp) {
return;
+ }
this._highlightRegExp = highlightRegExp;
this.refresh();
}
@@ -244,8 +266,9 @@ Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode
* @return {boolean}
*/
_refreshIfNeeded(maxSize) {
- if (this._lastUsedSize === this._coverageInfo.usedSize() && maxSize === this._maxSize)
+ if (this._lastUsedSize === this._coverageInfo.usedSize() && maxSize === this._maxSize) {
return false;
+ }
this._lastUsedSize = this._coverageInfo.usedSize();
this._maxSize = maxSize;
this.refresh();
@@ -268,13 +291,15 @@ Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode
const splitURL = /^(.*)(\/[^/]*)$/.exec(this._url);
prefix.textContent = splitURL ? splitURL[1] : this._url;
suffix.textContent = splitURL ? splitURL[2] : '';
- if (this._highlightRegExp)
+ if (this._highlightRegExp) {
this._highlight(outer, this._url);
+ }
break;
case 'type':
cell.textContent = Coverage.CoverageListView._typeToString(this._coverageInfo.type());
- if (this._coverageInfo.type() & Coverage.CoverageType.JavaScriptCoarse)
+ if (this._coverageInfo.type() & Coverage.CoverageType.JavaScriptCoarse) {
cell.title = Common.UIString('JS coverage is function-level only. Reload the page for block-level coverage.');
+ }
break;
case 'size':
cell.textContent = Number.withThousandsSeparator(this._coverageInfo.size() || 0);
@@ -302,8 +327,9 @@ Coverage.CoverageListView.GridNode = class extends DataGrid.SortableDataGridNode
*/
_highlight(element, textContent) {
const matches = this._highlightRegExp.exec(textContent);
- if (!matches || !matches.length)
+ if (!matches || !matches.length) {
return;
+ }
const range = new TextUtils.SourceRange(matches.index, matches[0].length);
UI.highlightRangesWithStyleClass(element, [range], 'filter-highlight');
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
index 73136c19c2f..14cf7896360 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
@@ -17,6 +17,13 @@ Coverage.CoverageType = {
JavaScriptCoarse: (1 << 2),
};
+/** @enum {symbol} */
+Coverage.SuspensionState = {
+ Active: Symbol('Active'),
+ Suspending: Symbol('Suspending'),
+ Suspended: Symbol('Suspended')
+};
+
Coverage.CoverageModel = class extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
@@ -33,12 +40,30 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
this._coverageByContentProvider = new Map();
/** @type {?Promise<!Array<!Protocol.Profiler.ScriptCoverage>>} */
this._bestEffortCoveragePromise = null;
+
+ /** @type {!Coverage.SuspensionState} */
+ this._suspensionState = Coverage.SuspensionState.Active;
+ /** @type {?number} */
+ this._pollTimer = null;
+ /** @type {?Promise} */
+ this._currentPollPromise = null;
+ /** @type {?boolean} */
+ this._shouldResumePollingOnResume = false;
+ /** @type {!Array<!{rawCoverageData:!Array<!Protocol.Profiler.ScriptCoverage>,stamp:number}>} */
+ this._jsBacklog = [];
+ /** @type {!Array<!{rawCoverageData:!Array<!Protocol.CSS.RuleUsage>,stamp:number}>} */
+ this._cssBacklog = [];
+ /** @type {?boolean} */
+ this._performanceTraceRecording = false;
}
/**
* @return {!Promise<boolean>}
*/
async start() {
+ if (this._suspensionState !== Coverage.SuspensionState.Active) {
+ throw Error('Cannot start CoverageModel while it is not active.');
+ }
const promises = [];
if (this._cssModel) {
// Note there's no JS coverage since JS won't ever return
@@ -55,15 +80,18 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
}
/**
- * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ * @return {!Promise}
*/
- stop() {
- const pollPromise = this.poll();
- if (this._cpuProfilerModel)
- this._cpuProfilerModel.stopPreciseCoverage();
- if (this._cssModel)
- this._cssModel.stopCoverage();
- return pollPromise;
+ async stop() {
+ await this.stopPolling();
+ const promises = [];
+ if (this._cpuProfilerModel) {
+ promises.push(this._cpuProfilerModel.stopPreciseCoverage());
+ }
+ if (this._cssModel) {
+ promises.push(this._cssModel.stopCoverage());
+ }
+ await Promise.all(promises);
}
reset() {
@@ -72,11 +100,112 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
}
/**
- * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ * @return {!Promise}
*/
- async poll() {
- const updates = await Promise.all([this._takeCSSCoverage(), this._takeJSCoverage()]);
- return updates[0].concat(updates[1]);
+ async startPolling() {
+ if (this._currentPollPromise || this._suspensionState !== Coverage.SuspensionState.Active) {
+ return;
+ }
+ await this._pollLoop();
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ async _pollLoop() {
+ this._clearTimer();
+ this._currentPollPromise = this._pollAndCallback();
+ await this._currentPollPromise;
+ if (this._suspensionState === Coverage.SuspensionState.Active || this._performanceTraceRecording) {
+ this._pollTimer = setTimeout(() => this._pollLoop(), Coverage.CoverageModel._coveragePollingPeriodMs);
+ }
+ }
+
+ async stopPolling() {
+ this._clearTimer();
+ await this._currentPollPromise;
+ this._currentPollPromise = null;
+ // Do one last poll to get the final data.
+ await this._pollAndCallback();
+ }
+
+ /**
+ * @return {!Promise<undefined>}
+ */
+ async _pollAndCallback() {
+ if (this._suspensionState === Coverage.SuspensionState.Suspended && !this._performanceTraceRecording) {
+ return;
+ }
+ const updates = await this._takeAllCoverage();
+ // This conditional should never trigger, as all intended ways to stop
+ // polling are awaiting the `_currentPollPromise` before suspending.
+ console.assert(
+ this._suspensionState !== Coverage.SuspensionState.Suspended || this._performanceTraceRecording,
+ 'CoverageModel was suspended while polling.');
+ if (updates.length) {
+ this.dispatchEventToListeners(Coverage.CoverageModel.Events.CoverageUpdated, updates);
+ }
+ }
+
+ _clearTimer() {
+ if (this._pollTimer) {
+ clearTimeout(this._pollTimer);
+ this._pollTimer = null;
+ }
+ }
+
+ /**
+ * Stops polling as preparation for suspension. This function is idempotent
+ * due because it changes the state to suspending.
+ * @override
+ * @param {string=} reason - optionally provide a reason, so the model can respond accordingly
+ * @return {!Promise<undefined>}
+ */
+ async preSuspendModel(reason) {
+ if (this._suspensionState !== Coverage.SuspensionState.Active) {
+ return;
+ }
+ this._suspensionState = Coverage.SuspensionState.Suspending;
+ if (reason === 'performance-timeline') {
+ this._performanceTraceRecording = true;
+ // Keep polling to the backlog if a performance trace is recorded.
+ return;
+ }
+ if (this._currentPollPromise) {
+ await this.stopPolling();
+ this._shouldResumePollingOnResume = true;
+ }
+ }
+
+ /**
+ * @override
+ * @param {string=} reason - optionally provide a reason, so the model can respond accordingly
+ * @return {!Promise<undefined>}
+ */
+ async suspendModel(reason) {
+ this._suspensionState = Coverage.SuspensionState.Suspended;
+ }
+
+ /**
+ * @override
+ * @return {!Promise<undefined>}
+ */
+ async resumeModel() {
+ }
+
+ /**
+ * Restarts polling after suspension. Note that the function is idempotent
+ * because starting polling is idempotent.
+ * @override
+ * @return {!Promise<undefined>}
+ */
+ async postResumeModel() {
+ this._suspensionState = Coverage.SuspensionState.Active;
+ this._performanceTraceRecording = false;
+ if (this._shouldResumePollingOnResume) {
+ this._shouldResumePollingOnResume = false;
+ await this.startPolling();
+ }
}
/**
@@ -99,46 +228,77 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
_clearCSS() {
for (const entry of this._coverageByContentProvider.values()) {
- if (entry.type() !== Coverage.CoverageType.CSS)
+ if (entry.type() !== Coverage.CoverageType.CSS) {
continue;
+ }
const contentProvider = /** @type {!SDK.CSSStyleSheetHeader} */ (entry.contentProvider());
this._coverageByContentProvider.delete(contentProvider);
const key = `${contentProvider.startLine}:${contentProvider.startColumn}`;
const urlEntry = this._coverageByURL.get(entry.url());
- if (!urlEntry || !urlEntry._coverageInfoByLocation.delete(key))
+ if (!urlEntry || !urlEntry._coverageInfoByLocation.delete(key)) {
continue;
+ }
urlEntry._size -= entry._size;
urlEntry._usedSize -= entry._usedSize;
- if (!urlEntry._coverageInfoByLocation.size)
+ if (!urlEntry._coverageInfoByLocation.size) {
this._coverageByURL.delete(entry.url());
+ }
}
}
/**
* @return {!Promise<!Array<!Coverage.CoverageInfo>>}
*/
+ async _takeAllCoverage() {
+ const [updatesCSS, updatesJS] = await Promise.all([this._takeCSSCoverage(), this._takeJSCoverage()]);
+ return [...updatesCSS, ...updatesJS];
+ }
+
+ /**
+ * @return {!Promise<!Array<!Coverage.CoverageInfo>>}
+ */
async _takeJSCoverage() {
- if (!this._cpuProfilerModel)
+ if (!this._cpuProfilerModel) {
return [];
- let rawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
+ }
+ const now = Date.now();
+ let freshRawCoverageData = await this._cpuProfilerModel.takePreciseCoverage();
if (this._bestEffortCoveragePromise) {
const bestEffortCoverage = await this._bestEffortCoveragePromise;
this._bestEffortCoveragePromise = null;
- rawCoverageData = bestEffortCoverage.concat(rawCoverageData);
+ freshRawCoverageData = bestEffortCoverage.concat(freshRawCoverageData);
+ }
+ if (this._suspensionState !== Coverage.SuspensionState.Active) {
+ if (freshRawCoverageData.length > 0) {
+ this._jsBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
+ }
+
+ return [];
+ }
+ const results = [];
+ for (const {rawCoverageData, stamp} of this._jsBacklog) {
+ results.push(this._processJSCoverage(rawCoverageData, stamp));
+ }
+
+ this._jsBacklog = [];
+ if (freshRawCoverageData.length > 0) {
+ results.push(this._processJSCoverage(freshRawCoverageData, now));
}
- return this._processJSCoverage(rawCoverageData);
+ return results.flat();
}
/**
* @param {!Array<!Protocol.Profiler.ScriptCoverage>} scriptsCoverage
* @return {!Array<!Coverage.CoverageInfo>}
*/
- _processJSCoverage(scriptsCoverage) {
+ _processJSCoverage(scriptsCoverage, stamp) {
const updatedEntries = [];
for (const entry of scriptsCoverage) {
const script = this._debuggerModel.scriptForId(entry.scriptId);
- if (!script)
+ if (!script) {
continue;
+ }
+
const ranges = [];
let type = Coverage.CoverageType.JavaScript;
for (const func of entry.functions) {
@@ -146,15 +306,19 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
// if back-end explicitly provides blockLevel field, otherwise presume blockLevel
// coverage is not available. Also, ignore non-block level functions that weren't
// ever called.
- if (func.isBlockCoverage === false && !(func.ranges.length === 1 && !func.ranges[0].count))
+ if (func.isBlockCoverage === false && !(func.ranges.length === 1 && !func.ranges[0].count)) {
type |= Coverage.CoverageType.JavaScriptCoarse;
- for (const range of func.ranges)
+ }
+ for (const range of func.ranges) {
ranges.push(range);
+ }
}
- const subentry =
- this._addCoverage(script, script.contentLength, script.lineOffset, script.columnOffset, ranges, type);
- if (subentry)
+ const subentry = this._addCoverage(
+ script, script.contentLength, script.lineOffset, script.columnOffset, ranges,
+ /** @type {!Coverage.CoverageType} */ (type), stamp);
+ if (subentry) {
updatedEntries.push(subentry);
+ }
}
return updatedEntries;
}
@@ -163,24 +327,43 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
* @return {!Promise<!Array<!Coverage.CoverageInfo>>}
*/
async _takeCSSCoverage() {
- if (!this._cssModel)
+ if (!this._cssModel) {
return [];
- const rawCoverageData = await this._cssModel.takeCoverageDelta();
- return this._processCSSCoverage(rawCoverageData);
+ }
+ const now = Date.now();
+ const freshRawCoverageData = await this._cssModel.takeCoverageDelta();
+ if (this._suspensionState !== Coverage.SuspensionState.Active) {
+ if (freshRawCoverageData.length > 0) {
+ this._cssBacklog.push({rawCoverageData: freshRawCoverageData, stamp: now});
+ }
+
+ return [];
+ }
+ const results = [];
+ for (const {rawCoverageData, stamp} of this._cssBacklog) {
+ results.push(this._processCSSCoverage(rawCoverageData, stamp));
+ }
+
+ this._cssBacklog = [];
+ if (freshRawCoverageData.length > 0) {
+ results.push(this._processCSSCoverage(freshRawCoverageData, now));
+ }
+ return results.flat();
}
/**
* @param {!Array<!Protocol.CSS.RuleUsage>} ruleUsageList
* @return {!Array<!Coverage.CoverageInfo>}
*/
- _processCSSCoverage(ruleUsageList) {
+ _processCSSCoverage(ruleUsageList, stamp) {
const updatedEntries = [];
/** @type {!Map<!SDK.CSSStyleSheetHeader, !Array<!Coverage.RangeUseCount>>} */
const rulesByStyleSheet = new Map();
for (const rule of ruleUsageList) {
const styleSheetHeader = this._cssModel.styleSheetHeaderForId(rule.styleSheetId);
- if (!styleSheetHeader)
+ if (!styleSheetHeader) {
continue;
+ }
let ranges = rulesByStyleSheet.get(styleSheetHeader);
if (!ranges) {
ranges = [];
@@ -193,9 +376,10 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
const ranges = /** @type {!Array<!Coverage.RangeUseCount>} */ (entry[1]);
const subentry = this._addCoverage(
styleSheetHeader, styleSheetHeader.contentLength, styleSheetHeader.startLine, styleSheetHeader.startColumn,
- ranges, Coverage.CoverageType.CSS);
- if (subentry)
+ ranges, Coverage.CoverageType.CSS, stamp);
+ if (subentry) {
updatedEntries.push(subentry);
+ }
}
return updatedEntries;
}
@@ -204,7 +388,7 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
* @param {!Array<!Coverage.RangeUseCount>} ranges
* @return {!Array<!Coverage.CoverageSegment>}
*/
- static _convertToDisjointSegments(ranges) {
+ static _convertToDisjointSegments(ranges, stamp) {
ranges.sort((a, b) => a.startOffset - b.startOffset);
const result = [];
@@ -232,14 +416,15 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
function append(end, count) {
const last = result.peekLast();
if (last) {
- if (last.end === end)
+ if (last.end === end) {
return;
+ }
if (last.count === count) {
last.end = end;
return;
}
}
- result.push({end: end, count: count});
+ result.push({end: end, count: count, stamp: stamp});
}
return result;
@@ -254,25 +439,30 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
* @param {!Coverage.CoverageType} type
* @return {?Coverage.CoverageInfo}
*/
- _addCoverage(contentProvider, contentLength, startLine, startColumn, ranges, type) {
+ _addCoverage(contentProvider, contentLength, startLine, startColumn, ranges, type, stamp) {
const url = contentProvider.contentURL();
- if (!url)
+ if (!url) {
return null;
+ }
let urlCoverage = this._coverageByURL.get(url);
+ let isNewUrlCoverage = false;
if (!urlCoverage) {
+ isNewUrlCoverage = true;
urlCoverage = new Coverage.URLCoverageInfo(url);
this._coverageByURL.set(url, urlCoverage);
}
const coverageInfo = urlCoverage._ensureEntry(contentProvider, contentLength, startLine, startColumn, type);
this._coverageByContentProvider.set(contentProvider, coverageInfo);
- const segments = Coverage.CoverageModel._convertToDisjointSegments(ranges);
- if (segments.length && segments.peekLast().end < contentLength)
- segments.push({end: contentLength});
+ const segments = Coverage.CoverageModel._convertToDisjointSegments(ranges, stamp);
+ if (segments.length && segments.peekLast().end < contentLength) {
+ segments.push({end: contentLength, stamp: stamp});
+ }
const oldUsedSize = coverageInfo._usedSize;
coverageInfo.mergeCoverage(segments);
- if (coverageInfo._usedSize === oldUsedSize)
+ if (!isNewUrlCoverage && coverageInfo._usedSize === oldUsedSize) {
return null;
+ }
urlCoverage._usedSize += coverageInfo._usedSize - oldUsedSize;
return coverageInfo;
}
@@ -282,10 +472,18 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
*/
async exportReport(fos) {
const result = [];
- for (const urlInfo of this._coverageByURL.values()) {
+ function locationCompare(a, b) {
+ const [aLine, aPos] = a.split(':');
+ const [bLine, bPos] = b.split(':');
+ return aLine - bLine || aPos - bPos;
+ }
+ const coverageByUrlKeys = Array.from(this._coverageByURL.keys()).sort();
+ for (const urlInfoKey of coverageByUrlKeys) {
+ const urlInfo = this._coverageByURL.get(urlInfoKey);
const url = urlInfo.url();
- if (url.startsWith('extensions::') || url.startsWith('chrome-extension://'))
+ if (url.startsWith('extensions::') || url.startsWith('chrome-extension://')) {
continue;
+ }
// For .html resources, multiple scripts share URL, but have different offsets.
let useFullText = false;
@@ -299,20 +497,25 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
let fullText = null;
if (useFullText) {
const resource = SDK.ResourceTreeModel.resourceForURL(url);
- fullText = resource ? new TextUtils.Text(await resource.requestContent()) : null;
+ const content = (await resource.requestContent()).content;
+ fullText = resource ? new TextUtils.Text(content || '') : null;
}
+ const coverageByLocationKeys = Array.from(urlInfo._coverageInfoByLocation.keys()).sort(locationCompare);
+
// We have full text for this resource, resolve the offsets using the text line endings.
if (fullText) {
const entry = {url, ranges: [], text: fullText.value()};
- for (const info of urlInfo._coverageInfoByLocation.values()) {
+ for (const infoKey of coverageByLocationKeys) {
+ const info = urlInfo._coverageInfoByLocation.get(infoKey);
const offset = fullText ? fullText.offsetFromPosition(info._lineOffset, info._columnOffset) : 0;
let start = 0;
for (const segment of info._segments) {
- if (segment.count)
+ if (segment.count) {
entry.ranges.push({start: start + offset, end: segment.end + offset});
- else
+ } else {
start = segment.end;
+ }
}
}
result.push(entry);
@@ -320,14 +523,16 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
}
// Fall back to the per-script operation.
- for (const info of urlInfo._coverageInfoByLocation.values()) {
- const entry = {url, ranges: [], text: await info.contentProvider().requestContent()};
+ for (const infoKey of coverageByLocationKeys) {
+ const info = urlInfo._coverageInfoByLocation.get(infoKey);
+ const entry = {url, ranges: [], text: (await info.contentProvider().requestContent()).content};
let start = 0;
for (const segment of info._segments) {
- if (segment.count)
+ if (segment.count) {
entry.ranges.push({start: start, end: segment.end});
- else
+ } else {
start = segment.end;
+ }
}
result.push(entry);
}
@@ -337,6 +542,16 @@ Coverage.CoverageModel = class extends SDK.SDKModel {
}
};
+/** @enum {symbol} */
+Coverage.CoverageModel.Events = {
+ CoverageUpdated: Symbol('CoverageUpdated')
+};
+
+/** @type {number} */
+Coverage.CoverageModel._coveragePollingPeriodMs = 200;
+
+SDK.SDKModel.register(Coverage.CoverageModel, SDK.Target.Capability.None, false);
+
Coverage.URLCoverageInfo = class {
/**
* @param {string} url
@@ -394,6 +609,10 @@ Coverage.URLCoverageInfo = class {
return this._isContentScript;
}
+ entries() {
+ return this._coverageInfoByLocation.values();
+ }
+
/**
* @param {!Common.ContentProvider} contentProvider
* @param {number} contentLength
@@ -406,8 +625,9 @@ Coverage.URLCoverageInfo = class {
const key = `${lineOffset}:${columnOffset}`;
let entry = this._coverageInfoByLocation.get(key);
- if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size)
+ if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
this._isContentScript = /** @type {!SDK.Script} */ (contentProvider).isContentScript();
+ }
this._type |= type;
if (entry) {
@@ -415,8 +635,9 @@ Coverage.URLCoverageInfo = class {
return entry;
}
- if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size)
+ if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size) {
this._isContentScript = /** @type {!SDK.Script} */ (contentProvider).isContentScript();
+ }
entry = new Coverage.CoverageInfo(contentProvider, contentLength, lineOffset, columnOffset, type);
this._coverageInfoByLocation.set(key, entry);
@@ -438,6 +659,7 @@ Coverage.CoverageInfo = class {
this._contentProvider = contentProvider;
this._size = size;
this._usedSize = 0;
+ this._statsByTimestamp = new Map();
this._lineOffset = lineOffset;
this._columnOffset = columnOffset;
this._coverageType = type;
@@ -475,6 +697,14 @@ Coverage.CoverageInfo = class {
this._updateStats();
}
+ usedByTimestamp() {
+ return this._statsByTimestamp;
+ }
+
+ size() {
+ return this._size;
+ }
+
/**
* @param {number} start
* @param {number} end
@@ -483,8 +713,9 @@ Coverage.CoverageInfo = class {
usageForRange(start, end) {
let index = this._segments.upperBound(start, (position, segment) => position - segment.end);
for (; index < this._segments.length && this._segments[index].end < end; ++index) {
- if (this._segments[index].count)
+ if (this._segments[index].count) {
return true;
+ }
}
return index < this._segments.length && !!this._segments[index].count;
}
@@ -505,30 +736,44 @@ Coverage.CoverageInfo = class {
typeof a.count === 'number' || typeof b.count === 'number' ? (a.count || 0) + (b.count || 0) : undefined;
const end = Math.min(a.end, b.end);
const last = result.peekLast();
- if (!last || last.count !== count)
- result.push({end: end, count: count});
- else
+ const stamp = Math.min(a.stamp, b.stamp);
+ if (!last || last.count !== count || last.stamp !== stamp) {
+ result.push({end: end, count: count, stamp: stamp});
+ } else {
last.end = end;
- if (a.end <= b.end)
+ }
+ if (a.end <= b.end) {
indexA++;
- if (a.end >= b.end)
+ }
+ if (a.end >= b.end) {
indexB++;
+ }
}
- for (; indexA < segmentsA.length; indexA++)
+ for (; indexA < segmentsA.length; indexA++) {
result.push(segmentsA[indexA]);
- for (; indexB < segmentsB.length; indexB++)
+ }
+ for (; indexB < segmentsB.length; indexB++) {
result.push(segmentsB[indexB]);
+ }
return result;
}
_updateStats() {
+ this._statsByTimestamp = new Map();
this._usedSize = 0;
let last = 0;
for (const segment of this._segments) {
- if (segment.count)
- this._usedSize += segment.end - last;
+ if (!this._statsByTimestamp.has(segment.stamp)) {
+ this._statsByTimestamp.set(segment.stamp, 0);
+ }
+
+ if (segment.count) {
+ const used = segment.end - last;
+ this._usedSize += used;
+ this._statsByTimestamp.set(segment.stamp, this._statsByTimestamp.get(segment.stamp) + used);
+ }
last = segment.end;
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
index 6df185d9191..ab3909af1d9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
@@ -8,8 +8,6 @@ Coverage.CoverageView = class extends UI.VBox {
/** @type {?Coverage.CoverageModel} */
this._model = null;
- /** @type {?number} */
- this._pollTimer = null;
/** @type {?Coverage.CoverageDecorationManager} */
this._decorationManager = null;
/** @type {?SDK.ResourceTreeModel} */
@@ -44,12 +42,39 @@ Coverage.CoverageView = class extends UI.VBox {
/** @type {?RegExp} */
this._textFilterRegExp = null;
toolbar.appendSeparator();
- this._filterInput = new UI.ToolbarInput(Common.UIString('URL filter'), 0.4, 1);
+ this._filterInput = new UI.ToolbarInput(Common.UIString('URL filter'), '', 0.4, 1);
this._filterInput.setEnabled(false);
this._filterInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onFilterChanged, this);
toolbar.appendToolbarItem(this._filterInput);
toolbar.appendSeparator();
+
+ this._typeFilterValue = null;
+ this._filterByTypeComboBox =
+ new UI.ToolbarComboBox(this._onFilterByTypeChanged.bind(this), ls`Filter coverage by type`);
+ const options = [
+ {
+ label: ls`All`,
+ value: '',
+ },
+ {
+ label: ls`CSS`,
+ value: Coverage.CoverageType.CSS,
+ },
+ {
+ label: ls`JavaScript`,
+ value: Coverage.CoverageType.JavaScript | Coverage.CoverageType.JavaScriptCoarse,
+ },
+ ];
+ for (const option of options) {
+ this._filterByTypeComboBox.addOption(this._filterByTypeComboBox.createOption(option.label, option.value));
+ }
+
+ this._filterByTypeComboBox.setSelectedIndex(0);
+ this._filterByTypeComboBox.setEnabled(false);
+ toolbar.appendToolbarItem(this._filterByTypeComboBox);
+
+ toolbar.appendSeparator();
this._showContentScriptsSetting = Common.settings.createSetting('showContentScripts', false);
this._showContentScriptsSetting.addChangeListener(this._onFilterChanged, this);
const contentScriptsCheckbox = new UI.ToolbarSettingCheckbox(
@@ -88,7 +113,9 @@ Coverage.CoverageView = class extends UI.VBox {
}
_clear() {
- this._model = null;
+ if (this._model) {
+ this._model.reset();
+ }
this._reset();
}
@@ -102,15 +129,25 @@ Coverage.CoverageView = class extends UI.VBox {
this._landingPage.show(this._coverageResultsElement);
this._statusMessageElement.textContent = '';
this._filterInput.setEnabled(false);
+ this._filterByTypeComboBox.setEnabled(false);
}
_toggleRecording() {
const enable = !this._toggleRecordAction.toggled();
- if (enable)
+ if (enable) {
this._startRecording(false);
- else
- this._stopRecording();
+ } else {
+ this.stopRecording();
+ }
+ }
+
+ async ensureRecordingStarted() {
+ const enable = !this._toggleRecordAction.toggled();
+
+ if (enable) {
+ await this._startRecording(false);
+ }
}
/**
@@ -119,15 +156,19 @@ Coverage.CoverageView = class extends UI.VBox {
async _startRecording(reload) {
this._reset();
const mainTarget = SDK.targetManager.mainTarget();
- if (!mainTarget)
+ if (!mainTarget) {
return;
+ }
- if (!this._model || reload)
- this._model = new Coverage.CoverageModel(/** @type {!SDK.Target} */ (mainTarget));
+ if (!this._model || reload) {
+ this._model = mainTarget.model(Coverage.CoverageModel);
+ }
Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageStarted);
const success = await this._model.start();
- if (!success)
+ if (!success) {
return;
+ }
+ this._model.addEventListener(Coverage.CoverageModel.Events.CoverageUpdated, this._onCoverageDataReceived, this);
this._resourceTreeModel = /** @type {?SDK.ResourceTreeModel} */ (mainTarget.model(SDK.ResourceTreeModel));
if (this._resourceTreeModel) {
this._resourceTreeModel.addEventListener(
@@ -137,44 +178,39 @@ Coverage.CoverageView = class extends UI.VBox {
new Coverage.CoverageDecorationManager(/** @type {!Coverage.CoverageModel} */ (this._model));
this._toggleRecordAction.setToggled(true);
this._clearButton.setEnabled(false);
- if (this._startWithReloadButton)
+ if (this._startWithReloadButton) {
this._startWithReloadButton.setEnabled(false);
+ }
this._filterInput.setEnabled(true);
- if (this._landingPage.isShowing())
+ this._filterByTypeComboBox.setEnabled(true);
+ if (this._landingPage.isShowing()) {
this._landingPage.detach();
+ }
this._listView.show(this._coverageResultsElement);
- if (reload && this._resourceTreeModel)
+ if (reload && this._resourceTreeModel) {
this._resourceTreeModel.reloadPage();
- else
- this._poll();
+ } else {
+ this._model.startPolling();
+ }
}
- async _poll() {
- if (this._pollTimer) {
- clearTimeout(this._pollTimer);
- // Clear until this._model.poll() finishes.
- this._pollTimer = null;
- }
- const updates = await this._model.poll();
- this._updateViews(updates);
- this._pollTimer = setTimeout(() => this._poll(), 700);
+ _onCoverageDataReceived(event) {
+ this._updateViews(event.data);
}
- async _stopRecording() {
- if (this._pollTimer) {
- clearTimeout(this._pollTimer);
- this._pollTimer = null;
- }
+ async stopRecording() {
if (this._resourceTreeModel) {
this._resourceTreeModel.removeEventListener(
SDK.ResourceTreeModel.Events.MainFrameNavigated, this._onMainFrameNavigated, this);
this._resourceTreeModel = null;
}
- const updatedEntries = await this._model.stop();
- this._updateViews(updatedEntries);
+ // Stopping the model triggers one last poll to get the final data.
+ await this._model.stop();
+ this._model.removeEventListener(Coverage.CoverageModel.Events.CoverageUpdated, this._onCoverageDataReceived, this);
this._toggleRecordAction.setToggled(false);
- if (this._startWithReloadButton)
+ if (this._startWithReloadButton) {
this._startWithReloadButton.setEnabled(true);
+ }
this._clearButton.setEnabled(true);
}
@@ -182,13 +218,13 @@ Coverage.CoverageView = class extends UI.VBox {
this._model.reset();
this._decorationManager.reset();
this._listView.reset();
- this._poll();
+ this._model.startPolling();
}
/**
* @param {!Array<!Coverage.CoverageInfo>} updatedEntries
*/
- async _updateViews(updatedEntries) {
+ _updateViews(updatedEntries) {
this._updateStats();
this._listView.update(this._model.entries());
this._decorationManager.update(updatedEntries);
@@ -198,8 +234,9 @@ Coverage.CoverageView = class extends UI.VBox {
let total = 0;
let unused = 0;
for (const info of this._model.entries()) {
- if (!this._isVisible(true, info))
+ if (!this._isVisible(true, info)) {
continue;
+ }
total += info.size();
unused += info.unusedSize();
}
@@ -212,14 +249,28 @@ Coverage.CoverageView = class extends UI.VBox {
}
_onFilterChanged() {
- if (!this._listView)
+ if (!this._listView) {
return;
+ }
const text = this._filterInput.value();
this._textFilterRegExp = text ? createPlainTextSearchRegex(text, 'i') : null;
this._listView.updateFilterAndHighlight(this._textFilterRegExp);
this._updateStats();
}
+ _onFilterByTypeChanged() {
+ if (!this._listView) {
+ return;
+ }
+
+ Host.userMetrics.actionTaken(Host.UserMetrics.Action.CoverageReportFiltered);
+
+ const type = this._filterByTypeComboBox.selectedOption().value;
+ this._typeFilterValue = parseInt(type, 10) || null;
+ this._listView.updateFilterAndHighlight(this._textFilterRegExp);
+ this._updateStats();
+ }
+
/**
* @param {boolean} ignoreTextFilter
* @param {!Coverage.URLCoverageInfo} coverageInfo
@@ -227,10 +278,16 @@ Coverage.CoverageView = class extends UI.VBox {
*/
_isVisible(ignoreTextFilter, coverageInfo) {
const url = coverageInfo.url();
- if (url.startsWith(Coverage.CoverageView._extensionBindingsURLPrefix))
+ if (url.startsWith(Coverage.CoverageView._extensionBindingsURLPrefix)) {
return false;
- if (coverageInfo.isContentScript() && !this._showContentScriptsSetting.get())
+ }
+ if (coverageInfo.isContentScript() && !this._showContentScriptsSetting.get()) {
+ return false;
+ }
+ if (this._typeFilterValue && !(coverageInfo.type() & this._typeFilterValue)) {
return false;
+ }
+
return ignoreTextFilter || !this._textFilterRegExp || this._textFilterRegExp.test(url);
}
@@ -238,10 +295,15 @@ Coverage.CoverageView = class extends UI.VBox {
const fos = new Bindings.FileOutputStream();
const fileName = `Coverage-${new Date().toISO8601Compact()}.json`;
const accepted = await fos.open(fileName);
- if (!accepted)
+ if (!accepted) {
return;
+ }
this._model.exportReport(fos);
}
+
+ selectCoverageItemByUrl(url) {
+ this._listView.selectByUrl(url);
+ }
};
Coverage.CoverageView._extensionBindingsURLPrefix = 'extensions::';
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverageListView.css b/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverageListView.css
index 3b915e2b6f6..438c240a1dd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverageListView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverageListView.css
@@ -43,11 +43,11 @@
}
.data-grid td .bar-unused-size {
- background-color: #E57373;
+ background-color: #EE442F;
}
.data-grid td .bar-used-size {
- background-color: #81C784;
+ background-color: #63ACBE;
}
.data-grid td .percent-value {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
index 1dd15152070..eeac010f881 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage/coverage_strings.grdp
@@ -13,14 +13,8 @@ Click the reload button <ph name="RELOAD_BUTTON_ICON">$2s<ex>reload button icon<
<message name="IDS_DEVTOOLS_2adbfb69a37aa4a29ca846736d2111db" desc="Text in Coverage List View of the Coverage tab">
JS (coarse)
</message>
- <message name="IDS_DEVTOOLS_2c56c360580420d293172f42d85dfbed" desc="Text in Coverage List View of the Coverage tab">
- CSS
- </message>
- <message name="IDS_DEVTOOLS_5bc06f5800d415cc95e1349edbaca425" desc="Text in Coverage List View of the Coverage tab">
- JS
- </message>
- <message name="IDS_DEVTOOLS_6525b37c568c526bde7c02fac8195c73" desc="Unused percents span text content in Coverage List View of the Coverage tab">
- <ph name="UNUSEDSIZE___THIS__COVERAGEINFO_SIZE________">$1.1f<ex>20.1</ex></ph> %%
+ <message name="IDS_DEVTOOLS_44ea86aada1381cf21cf9899b3dd32fe" desc="Label for the type filter in the Converage Panel">
+ Filter coverage by type
</message>
<message name="IDS_DEVTOOLS_73af525212a812236f1a3618e9cfa717" desc="Tooltip text that appears when hovering over the largeicon download button in the Coverage View of the Coverage tab">
Export...
@@ -41,12 +35,6 @@ Click the reload button <ph name="RELOAD_BUTTON_ICON">$2s<ex>reload button icon<
<ph name="NUMBER_BYTESTOSTRING_USED_">$1s<ex>1.5 MB</ex></ph> of <ph name="NUMBER_BYTESTOSTRING_TOTAL_">$2s<ex>2.1 MB</ex></ph> (<ph name="PERCENTUSED">$3s<ex>71%</ex></ph>%) used so far.
<ph name="NUMBER_BYTESTOSTRING_UNUSED_">$4s<ex>29%</ex></ph> unused.
</message>
- <message name="IDS_DEVTOOLS_9841bdc50c4226cb6ec5db76494249e6" desc="Title of the 'Coverage' tool in the bottom drawer">
- Coverage
- </message>
- <message name="IDS_DEVTOOLS_a1fa27779242b4902f7ae3bdd5c6d508" desc="Text in Coverage List View of the Coverage tab">
- Type
- </message>
<message name="IDS_DEVTOOLS_bca27ccb808f436cd1ce828dd47604b7" desc="Title of an action in the coverage tool to start with reload">
Start instrumenting coverage and reload page
</message>
@@ -56,7 +44,4 @@ Click the reload button <ph name="RELOAD_BUTTON_ICON">$2s<ex>reload button icon<
<message name="IDS_DEVTOOLS_d98bd5257b9f29c266777264411735a3" desc="Tooltip text that appears on the setting when hovering over it in Coverage View of the Coverage tab">
Include extension content scripts
</message>
- <message name="IDS_DEVTOOLS_e6b391a8d2c4d45902a23a8b6585703d" desc="Text in Coverage List View of the Coverage tab">
- URL
- </message>
</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
index a7914e31216..21567508263 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
@@ -18,15 +18,34 @@ CoverageTestRunner.startCoverage = async function() {
*/
CoverageTestRunner.stopCoverage = function() {
const coverageView = self.runtime.sharedInstance(Coverage.CoverageView);
- return coverageView._stopRecording();
+ return coverageView.stopRecording();
};
/**
* @return {!Promise}
*/
+CoverageTestRunner.suspendCoverageModel = async function() {
+ const coverageView = self.runtime.sharedInstance(Coverage.CoverageView);
+ await coverageView._model.preSuspendModel();
+ await coverageView._model.suspendModel();
+};
+
+/**
+ * @return {!Promise}
+ */
+CoverageTestRunner.resumeCoverageModel = async function() {
+ const coverageView = self.runtime.sharedInstance(Coverage.CoverageView);
+ await coverageView._model.resumeModel();
+ await coverageView._model.postResumeModel();
+};
+
+
+/**
+ * @return {!Promise}
+ */
CoverageTestRunner.pollCoverage = function() {
const coverageView = self.runtime.sharedInstance(Coverage.CoverageView);
- return coverageView._poll();
+ return coverageView._model._takeAllCoverage();
};
/**
@@ -63,8 +82,9 @@ CoverageTestRunner.findCoverageNodeForURL = function(url) {
const rootNode = coverageListView._dataGrid.rootNode();
for (const child of rootNode.children) {
- if (child._coverageInfo.url().endsWith(url))
+ if (child._coverageInfo.url().endsWith(url)) {
return child;
+ }
}
return null;
@@ -79,8 +99,9 @@ CoverageTestRunner.dumpDecorationsInSourceFrame = function(sourceFrame) {
let markerType = ' ';
const lineInfo = codeMirror.lineInfo(line);
- if (!lineInfo)
+ if (!lineInfo) {
continue;
+ }
const gutterElement = lineInfo.gutterMarkers && lineInfo.gutterMarkers['CodeMirror-gutter-coverage'];
@@ -102,8 +123,9 @@ CoverageTestRunner.dumpCoverageListView = function() {
const data = child._coverageInfo;
const url = TestRunner.formatters.formatAsURL(data.url());
- if (url.startsWith('test://'))
+ if (url.startsWith('test://')) {
continue;
+ }
const type = Coverage.CoverageListView._typeToString(data.type());
TestRunner.addResult(`${url} ${type} used: ${data.usedSize()} unused: ${data.unusedSize()} total: ${data.size()}`);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/cpu_profiler_test_runner/ProfilerTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/cpu_profiler_test_runner/ProfilerTestRunner.js
index 49abf7dd2dd..cfc48a30a59 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/cpu_profiler_test_runner/ProfilerTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/cpu_profiler_test_runner/ProfilerTestRunner.js
@@ -45,8 +45,9 @@ CPUProfilerTestRunner.showProfileWhenAdded = function(title) {
};
CPUProfilerTestRunner._profileHeaderAdded = function(profile) {
- if (CPUProfilerTestRunner._showProfileWhenAdded === profile.title)
+ if (CPUProfilerTestRunner._showProfileWhenAdded === profile.title) {
UI.panels.js_profiler.showProfile(profile);
+ }
};
CPUProfilerTestRunner.waitUntilProfileViewIsShown = function(title, callback) {
@@ -54,10 +55,11 @@ CPUProfilerTestRunner.waitUntilProfileViewIsShown = function(title, callback) {
const profilesPanel = UI.panels.js_profiler;
if (profilesPanel.visibleView && profilesPanel.visibleView.profile &&
- profilesPanel.visibleView._profileHeader.title === title)
+ profilesPanel.visibleView._profileHeader.title === title) {
callback(profilesPanel.visibleView);
- else
+ } else {
CPUProfilerTestRunner._waitUntilProfileViewIsShownCallback = {title: title, callback: callback};
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewCompletedView.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewCompletedView.js
new file mode 100644
index 00000000000..4665b54e187
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewCompletedView.js
@@ -0,0 +1,260 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.CSSOverviewCompletedView = class extends UI.PanelWithSidebar {
+ constructor(controller, target) {
+ super('css_overview_completed_view');
+ this.registerRequiredCSS('css_overview/cssOverviewCompletedView.css');
+
+ this._controller = controller;
+ this._formatter = new Intl.NumberFormat('en-US');
+ this._mainContainer = new UI.VBox();
+
+ this._sideBar = new CssOverview.CSSOverviewSidebarPanel();
+ this.splitWidget().setSidebarWidget(this._sideBar);
+ this.splitWidget().setMainWidget(this._mainContainer);
+
+ this._cssModel = target.model(SDK.CSSModel);
+ this._linkifier = new Components.Linkifier(/* maxLinkLength */ 20, /* useLinkDecorator */ true);
+
+ this._columns = [
+ {id: 'text', title: ls`Text`, visible: true, sortable: true, weight: 60},
+ {id: 'sourceURL', title: ls`Source`, visible: true, sortable: true, weight: 40}
+ ];
+
+ this._mediaQueryGrid = new DataGrid.SortableDataGrid(this._columns);
+ this._mediaQueryGrid.element.classList.add('media-query-grid');
+ this._mediaQueryGrid.setStriped(true);
+ this._mediaQueryGrid.addEventListener(
+ DataGrid.DataGrid.Events.SortingChanged, this._sortMediaQueryDataGrid.bind(this));
+
+ this._sideBar.addItem(ls`Overview summary`, 'summary');
+ this._sideBar.addItem(ls`Colors`, 'colors');
+ this._sideBar.addItem(ls`Media queries`, 'media-queries');
+ this._sideBar.select('summary');
+
+ this._sideBar.addEventListener(CssOverview.SidebarEvents.ItemSelected, this._sideBarItemSelected, this);
+ this._sideBar.addEventListener(CssOverview.SidebarEvents.Reset, this._sideBarReset, this);
+ this._controller.addEventListener(CssOverview.Events.Reset, this._reset, this);
+ this._render({});
+ }
+
+ _sortMediaQueryDataGrid() {
+ const sortColumnId = this._mediaQueryGrid.sortColumnId();
+ if (!sortColumnId) {
+ return;
+ }
+
+ const comparator = DataGrid.SortableDataGrid.StringComparator.bind(null, sortColumnId);
+ this._mediaQueryGrid.sortNodes(comparator, !this._mediaQueryGrid.isSortOrderAscending());
+ }
+
+ _sideBarItemSelected(event) {
+ const section = this._fragment.$(event.data);
+ if (!section) {
+ return;
+ }
+
+ section.scrollIntoView();
+ }
+
+ _sideBarReset() {
+ this._controller.dispatchEventToListeners(CssOverview.Events.Reset);
+ }
+
+ _reset() {
+ this._mainContainer.element.removeChildren();
+ this._mediaQueryGrid.rootNode().removeChildren();
+ }
+
+ _render(data) {
+ if (!(data && ('textColors' in data) && ('backgroundColors' in data))) {
+ return;
+ }
+
+ const {elementStyleStats, elementCount, backgroundColors, textColors, globalStyleStats, mediaQueries} = data;
+
+ // Convert rgb values from the computed styles to either undefined or HEX(A) strings.
+ const nonTransparentBackgroundColors = this._getNonTransparentColorStrings(backgroundColors);
+ const nonTransparentTextColors = this._getNonTransparentColorStrings(textColors);
+
+ this._fragment = UI.Fragment.build`
+ <div class="vbox overview-completed-view">
+ <div $="summary" class="results-section summary">
+ <h1>${ls`Overview summary`}</h1>
+
+ <ul>
+ <li>
+ <div class="label">${ls`Elements processed`}</div>
+ <div class="value">${this._formatter.format(elementCount)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`External stylesheets`}</div>
+ <div class="value">${this._formatter.format(globalStyleStats.externalSheets)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Inline style elements`}</div>
+ <div class="value">${this._formatter.format(globalStyleStats.inlineStyles)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Style rules`}</div>
+ <div class="value">${this._formatter.format(globalStyleStats.styleRules)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Media queries`}</div>
+ <div class="value">${this._formatter.format(mediaQueries.length)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Type selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.type.size)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`ID selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.id.size)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Class selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.class.size)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Universal selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.universal.size)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Attribute selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.attribute.size)}</div>
+ </li>
+ <li>
+ <div class="label">${ls`Non-simple selectors`}</div>
+ <div class="value">${this._formatter.format(elementStyleStats.nonSimple.size)}</div>
+ </li>
+ </ul>
+ </div>
+
+ <div $="colors" class="results-section colors">
+ <h1>${ls`Colors`}</h1>
+ <h2>${ls`Unique background colors: ${nonTransparentBackgroundColors.length}`}</h2>
+ <ul>
+ ${nonTransparentBackgroundColors.map(this._colorsToFragment)}
+ </ul>
+
+ <h2>${ls`Unique text colors: ${nonTransparentTextColors.length}`}</h2>
+ <ul>
+ ${nonTransparentTextColors.map(this._colorsToFragment)}
+ </ul>
+ </div>
+
+ <div $="media-queries" class="results-section media-queries">
+ <h1>${ls`Media queries`}</h1>
+ ${this._mediaQueryGrid.element}
+ </div>
+ </div>`;
+
+ // Media Queries.
+ for (const mediaQuery of mediaQueries) {
+ const mediaQueryNode = new CssOverview.CSSOverviewCompletedView.MediaQueryNode(
+ this._mediaQueryGrid, mediaQuery, this._cssModel, this._linkifier);
+ mediaQueryNode.selectable = false;
+ this._mediaQueryGrid.insertChild(mediaQueryNode);
+ }
+
+ this._mainContainer.element.appendChild(this._fragment.element());
+ this._mediaQueryGrid.renderInline();
+ this._mediaQueryGrid.wasShown();
+ }
+
+ _colorsToFragment(color) {
+ const colorFormatted =
+ color.hasAlpha() ? color.asString(Common.Color.Format.HEXA) : color.asString(Common.Color.Format.HEX);
+ const blockFragment = UI.Fragment.build`<li>
+ <div class="block" $="color"></div>
+ <div class="block-title">${colorFormatted}</div>
+ </li>`;
+
+ const block = blockFragment.$('color');
+ block.style.backgroundColor = colorFormatted;
+
+ let [h, s, l] = color.hsla();
+ h = Math.round(h * 360);
+ s = Math.round(s * 100);
+ l = Math.round(l * 100);
+
+ // Reduce the lightness of the border to make sure that there's always a visible outline.
+ l = Math.max(0, l - 15);
+
+ const borderString = `1px solid hsl(${h}, ${s}%, ${l}%)`;
+ block.style.border = borderString;
+
+ return blockFragment;
+ }
+
+ _getNonTransparentColorStrings(srcColors) {
+ const colors = [];
+ for (const colorText of Array.from(srcColors)) {
+ const color = Common.Color.parse(colorText);
+ if (color.rgba()[3] === 0) {
+ continue;
+ }
+
+ colors.push(color);
+ }
+
+ return colors.sort((colorA, colorB) => {
+ return Common.Color.luminance(colorB.rgba()) - Common.Color.luminance(colorA.rgba());
+ });
+ }
+
+ setOverviewData(data) {
+ this._render(data);
+ }
+};
+
+CssOverview.CSSOverviewCompletedView.MediaQueryNode = class extends DataGrid.SortableDataGridNode {
+ /**
+ * @param {!DataGrid.SortableDataGrid} dataGrid
+ * @param {!Object<string,*>} mediaQueryData
+ * @param {!SDK.CSSModel} cssModel
+ * @param {!Components.Linkifier} linkifier
+ */
+ constructor(dataGrid, mediaQueryData, cssModel, linkifier) {
+ super(dataGrid, mediaQueryData.hasChildren);
+
+ this.data = mediaQueryData;
+ this._cssModel = cssModel;
+ this._linkifier = linkifier;
+ }
+
+ /**
+ * @override
+ * @param {string} columnId
+ * @return {!Element}
+ */
+ createCell(columnId) {
+ if (this.data.range && columnId === 'sourceURL') {
+ const cell = this.createTD(columnId);
+ const link = this._linkifyRuleLocation(
+ this._cssModel, this._linkifier, this.data.styleSheetId, TextUtils.TextRange.fromObject(this.data.range));
+
+ if (link.textContent !== '') {
+ cell.appendChild(link);
+ } else {
+ cell.textContent = `${this.data.sourceURL} (not available)`;
+ }
+ return cell;
+ }
+
+ return super.createCell(columnId);
+ }
+
+ _linkifyRuleLocation(cssModel, linkifier, styleSheetId, ruleLocation) {
+ const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
+ const lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
+ const columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
+ const matchingSelectorLocation = new SDK.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
+ return linkifier.linkifyCSSLocation(matchingSelectorLocation);
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewController.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewController.js
new file mode 100644
index 00000000000..3ff6f293b24
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewController.js
@@ -0,0 +1,25 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.OverviewController = class extends Common.Object {
+ constructor() {
+ super();
+
+ SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._reset, this);
+ }
+
+ _reset() {
+ this.dispatchEventToListeners(CssOverview.Events.Reset);
+ }
+};
+
+CssOverview.Events = {
+ RequestOverviewStart: Symbol('RequestOverviewStart'),
+ RequestOverviewCancel: Symbol('RequestOverviewCancel'),
+ OverviewCompleted: Symbol('OverviewCompleted'),
+ Reset: Symbol('Reset'),
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewModel.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewModel.js
new file mode 100644
index 00000000000..7881c0b3652
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewModel.js
@@ -0,0 +1,136 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.CSSOverviewModel = class extends SDK.SDKModel {
+ /**
+ * @param {!SDK.Target} target
+ */
+ constructor(target) {
+ super(target);
+
+ this._runtimeAgent = target.runtimeAgent();
+ this._cssAgent = target.cssAgent();
+ this._domAgent = target.domAgent();
+ }
+
+ getFlattenedDocument() {
+ return this._domAgent.getFlattenedDocument(-1, true);
+ }
+
+ getComputedStyleForNode(nodeId) {
+ return this._cssAgent.getComputedStyleForNode(nodeId);
+ }
+
+ async getMediaQueries() {
+ // Ignore media queries applied to stylesheets; instead only use declared media rules.
+ const queries = await this._cssAgent.getMediaQueries();
+ return queries.filter(query => query.source !== 'linkedSheet');
+ }
+
+ async getGlobalStylesheetStats() {
+ // There are no ways to pull CSSOM values directly today, due to its unserializable format,
+ // so instead we execute some JS within the page that extracts the relevant data and send that instead.
+ const expression = `(function() {
+ let styleRules = 0;
+ let inlineStyles = 0;
+ let externalSheets = 0;
+ for (const { rules, href } of document.styleSheets) {
+ if (href) {
+ externalSheets++;
+ } else {
+ inlineStyles++;
+ }
+
+ for (const rule of rules) {
+ if ('selectorText' in rule) {
+ styleRules++;
+ }
+ }
+ }
+
+ return {
+ styleRules,
+ inlineStyles,
+ externalSheets
+ }
+ })()`;
+ const {result} = await this._runtimeAgent.invoke_evaluate({expression, returnByValue: true});
+
+ // TODO(paullewis): Handle errors properly.
+ if (result.type !== 'object') {
+ return;
+ }
+
+ return result.value;
+ }
+
+ async getStylesStatsForNode(nodeId) {
+ const stats = {
+ // Simple.
+ type: new Set(),
+ class: new Set(),
+ id: new Set(),
+ universal: new Set(),
+ attribute: new Set(),
+
+ // Non-simple.
+ nonSimple: new Set()
+ };
+
+ const matches = await this._cssAgent.invoke_getMatchedStylesForNode({nodeId});
+ if (!matches || !matches.matchedCSSRules || !matches.matchedCSSRules.length) {
+ return;
+ }
+
+ matches.matchedCSSRules.forEach(cssRule => {
+ const {matchingSelectors} = cssRule;
+ const {origin, selectorList} = cssRule.rule;
+ const isExternalSheet = origin === 'regular';
+ if (!isExternalSheet || !selectorList) {
+ return;
+ }
+
+
+ const selectors = matchingSelectors.map(idx => selectorList.selectors[idx]);
+
+ // Each group of selectors, e.g. foo.baz, foo .bar, foo { ... }
+ for (const {text} of selectors) {
+ // Each group that was used.
+ for (const selectorGroup of text.split(',')) {
+ // Each selector in the group.
+ for (const selector of selectorGroup.split(/[\t\n\f\r ]+/g)) {
+ if (selector.startsWith('.')) {
+ // Class.
+ stats.class.add(selector);
+ } else if (selector.startsWith('#')) {
+ // Id.
+ stats.id.add(selector);
+ } else if (selector.startsWith('*')) {
+ // Universal.
+ stats.universal.add(selector);
+ } else if (selector.startsWith('[')) {
+ // Attribute.
+ stats.attribute.add(selector);
+ } else {
+ // Type or non-simple selector.
+ const specialChars = /[#\.:\[\]|\+>~]/;
+ if (specialChars.test(selector)) {
+ stats.nonSimple.add(selector);
+ } else {
+ stats.type.add(selector);
+ }
+ }
+ }
+ }
+ }
+ });
+
+ return stats;
+ }
+};
+
+SDK.SDKModel.register(CssOverview.CSSOverviewModel, SDK.Target.Capability.DOM, false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewPanel.js
new file mode 100644
index 00000000000..e69d43bc93e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewPanel.js
@@ -0,0 +1,173 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.CSSOverviewPanel = class extends UI.Panel {
+ constructor() {
+ super('css_overview');
+ this.registerRequiredCSS('css_overview/cssOverview.css');
+ this.element.classList.add('css-overview-panel');
+
+ const [model] = SDK.targetManager.models(CssOverview.CSSOverviewModel);
+ this._model = model;
+
+ this._controller = new CssOverview.OverviewController();
+ this._startView = new CssOverview.CSSOverviewStartView(this._controller);
+ this._processingView = new CssOverview.CSSOverviewProcessingView(this._controller);
+ this._completedView = new CssOverview.CSSOverviewCompletedView(this._controller, model.target());
+
+ this._controller.addEventListener(CssOverview.Events.RequestOverviewStart, this._startOverview, this);
+ this._controller.addEventListener(CssOverview.Events.RequestOverviewCancel, this._cancelOverview, this);
+ this._controller.addEventListener(CssOverview.Events.OverviewCompleted, this._overviewCompleted, this);
+ this._controller.addEventListener(CssOverview.Events.Reset, this._reset, this);
+
+ this._reset();
+ }
+
+ _reset() {
+ this._backgroundColors = new Set();
+ this._textColors = new Set();
+ this._fontSizes = new Map();
+ this._mediaQueries = [];
+ this._elementCount = 0;
+ this._elementStyleStats = {
+ // Simple.
+ type: new Set(),
+ class: new Set(),
+ id: new Set(),
+ universal: new Set(),
+ attribute: new Set(),
+
+ // Non-simple.
+ nonSimple: new Set()
+ };
+ this._cancelled = false;
+ this._globalStyleStats = {styleRules: 0, inlineStyles: 0, externalSheets: 0};
+ this._renderInitialView();
+ }
+
+ _renderInitialView() {
+ this._processingView.hideWidget();
+ this._completedView.hideWidget();
+
+ this._startView.show(this.contentElement);
+ }
+
+ _renderOverviewStartedView(elementsHandled = 0, total = 0) {
+ this._startView.hideWidget();
+ this._completedView.hideWidget();
+
+ this._processingView.show(this.contentElement);
+ this._processingView.setElementsHandled(elementsHandled, total);
+ }
+
+ _renderOverviewCompletedView() {
+ this._startView.hideWidget();
+ this._processingView.hideWidget();
+
+ this._completedView.show(this.contentElement);
+ this._completedView.setOverviewData({
+ backgroundColors: this._backgroundColors,
+ textColors: this._textColors,
+ globalStyleStats: this._globalStyleStats,
+ elementStyleStats: this._elementStyleStats,
+ fontSizes: this._fontSizes,
+ elementCount: this._elementCount,
+ mediaQueries: this._mediaQueries
+ });
+ }
+
+ async _startOverview() {
+ this._renderOverviewStartedView();
+
+ const document = await this._model.getFlattenedDocument();
+ if (this._cancelled) {
+ this._reset();
+ return;
+ }
+
+ // 1. Get the global style stats.
+ const globalStyleStats = await this._model.getGlobalStylesheetStats();
+ if (globalStyleStats) {
+ this._globalStyleStats = globalStyleStats;
+ }
+
+ const mediaQueries = await this._model.getMediaQueries();
+ if (mediaQueries) {
+ this._mediaQueries = mediaQueries;
+ }
+
+ // 2. Get the total element count.
+ this._elementCount = document.length;
+
+ // 3. Process every element in the doc.
+ for (let idx = 0; idx < document.length; idx++) {
+ if (this._cancelled) {
+ this._reset();
+ return;
+ }
+
+ const node = document[idx];
+ const [computedStyles, styleStats] = await Promise.all(
+ [this._model.getComputedStyleForNode(node.nodeId), this._model.getStylesStatsForNode(node.nodeId)]);
+
+ // 3a. Capture any colors from the computed styles.
+ if (computedStyles) {
+ const backgroundColor = this._getStyleValue(computedStyles, 'background-color');
+ if (backgroundColor) {
+ this._backgroundColors.add(backgroundColor);
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ const textColor = this._getStyleValue(computedStyles, 'color');
+ this._textColors.add(textColor);
+
+ const fontSize = this._getStyleValue(computedStyles, 'font-size');
+ if (!this._fontSizes.has(fontSize)) {
+ this._fontSizes.set(fontSize, 0);
+ }
+
+ this._fontSizes.set(fontSize, this._fontSizes.get(fontSize) + 1);
+ }
+ }
+
+ // 3b. Tally the selector stats.
+ if (styleStats) {
+ for (const section of Object.keys(this._elementStyleStats)) {
+ if (!styleStats[section]) {
+ continue;
+ }
+
+ for (const value of styleStats[section]) {
+ this._elementStyleStats[section].add(value);
+ }
+ }
+ }
+
+ this._renderOverviewStartedView(idx + 1, document.length);
+ }
+
+ // 4. Finish.
+ this._controller.dispatchEventToListeners(CssOverview.Events.OverviewCompleted);
+ }
+
+ _getStyleValue(styles, name) {
+ const item = styles.filter(style => style.name === name);
+ if (!item.length) {
+ return;
+ }
+
+ return item[0].value;
+ }
+
+ _cancelOverview() {
+ this._cancelled = true;
+ }
+
+ _overviewCompleted() {
+ this._renderOverviewCompletedView();
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewProcessingView.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewProcessingView.js
new file mode 100644
index 00000000000..169c363bcdc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewProcessingView.js
@@ -0,0 +1,44 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.CSSOverviewProcessingView = class extends UI.Widget {
+ constructor(controller) {
+ super();
+ this.registerRequiredCSS('css_overview/cssOverviewProcessingView.css');
+
+ this._formatter = new Intl.NumberFormat('en-US');
+ this._controller = controller;
+ this._render();
+ }
+
+ _render() {
+ const cancelButton = UI.createTextButton(
+ ls`Cancel`, () => this._controller.dispatchEventToListeners(CssOverview.Events.RequestOverviewCancel), '',
+ true /* primary */);
+ this.setDefaultFocusedElement(cancelButton);
+
+ this.fragment = UI.Fragment.build`
+ <div class="vbox overview-processing-view">
+ <h1>Processing page</h1>
+ <div>${cancelButton}</div>
+
+ <h2 $="processed"></h2>
+ </div>
+ `;
+
+ this.contentElement.appendChild(this.fragment.element());
+ this.contentElement.style.overflow = 'auto';
+ }
+
+ setElementsHandled(handled = 0, total = 0) {
+ // TODO(aerotwist): We might want to switch this to using Intl.PluralRules in the future
+ // @see https://v8.dev/features/intl-pluralrules
+ const elementsTotal = total > 0 ? ls`document elements` : ls`document element`;
+ this.fragment.$('processed').textContent =
+ ls`Processed ${this._formatter.format(handled)} of ${this._formatter.format(total)} ${elementsTotal}.`;
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewSidebarPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewSidebarPanel.js
new file mode 100644
index 00000000000..9e3631668c1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewSidebarPanel.js
@@ -0,0 +1,77 @@
+// 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.
+
+CssOverview.CSSOverviewSidebarPanel = class extends UI.VBox {
+ static get ITEM_CLASS_NAME() {
+ return 'overview-sidebar-panel-item';
+ }
+
+ static get SELECTED() {
+ return 'selected';
+ }
+
+ constructor() {
+ super(true);
+
+ this.registerRequiredCSS('css_overview/cssOverviewSidebarPanel.css');
+ this.contentElement.classList.add('overview-sidebar-panel');
+ this.contentElement.addEventListener('click', this._onItemClick.bind(this));
+
+ // Clear overview.
+ const clearResultsButton = new UI.ToolbarButton(ls`Clear overview`, 'largeicon-clear');
+ clearResultsButton.addEventListener(UI.ToolbarButton.Events.Click, this._reset, this);
+
+ // Toolbar.
+ const toolbarElement = this.contentElement.createChild('div', 'overview-toolbar');
+ const toolbar = new UI.Toolbar('', toolbarElement);
+ toolbar.appendToolbarItem(clearResultsButton);
+ }
+
+ addItem(name, id) {
+ const item = this.contentElement.createChild('div', CssOverview.CSSOverviewSidebarPanel.ITEM_CLASS_NAME);
+ item.textContent = name;
+ item.dataset.id = id;
+ }
+
+ _reset() {
+ this.dispatchEventToListeners(CssOverview.SidebarEvents.Reset);
+ }
+
+ _deselectAllItems() {
+ const items = this.contentElement.querySelectorAll(`.${CssOverview.CSSOverviewSidebarPanel.ITEM_CLASS_NAME}`);
+ for (const item of items) {
+ item.classList.remove(CssOverview.CSSOverviewSidebarPanel.SELECTED);
+ }
+ }
+
+ _onItemClick(event) {
+ const target = event.path[0];
+ if (!target.classList.contains(CssOverview.CSSOverviewSidebarPanel.ITEM_CLASS_NAME)) {
+ return;
+ }
+
+ const {id} = target.dataset;
+ this.select(id);
+ this.dispatchEventToListeners(CssOverview.SidebarEvents.ItemSelected, id);
+ }
+
+ select(id) {
+ const target = this.contentElement.querySelector(`[data-id=${CSS.escape(id)}]`);
+ if (!target) {
+ return;
+ }
+
+ if (target.classList.contains(CssOverview.CSSOverviewSidebarPanel.SELECTED)) {
+ return;
+ }
+
+ this._deselectAllItems();
+ target.classList.add(CssOverview.CSSOverviewSidebarPanel.SELECTED);
+ }
+};
+
+CssOverview.SidebarEvents = {
+ ItemSelected: Symbol('ItemSelected'),
+ Reset: Symbol('Reset')
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewStartView.js b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewStartView.js
new file mode 100644
index 00000000000..d19cc9eea31
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/CSSOverviewStartView.js
@@ -0,0 +1,34 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+CssOverview.CSSOverviewStartView = class extends UI.Widget {
+ constructor(controller) {
+ super();
+ this.registerRequiredCSS('css_overview/cssOverviewStartView.css');
+
+ this._controller = controller;
+ this._render();
+ }
+
+ _render() {
+ const startButton = UI.createTextButton(
+ ls`Capture overview`, () => this._controller.dispatchEventToListeners(CssOverview.Events.RequestOverviewStart),
+ '', true /* primary */);
+
+ this.setDefaultFocusedElement(startButton);
+
+ const fragment = UI.Fragment.build`
+ <div class="vbox overview-start-view">
+ <h1>${ls`CSS Overview`}</h1>
+ <div>${startButton}</div>
+ </div>
+ `;
+
+ this.contentElement.appendChild(fragment.element());
+ this.contentElement.style.overflow = 'auto';
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverview.css b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverview.css
new file mode 100644
index 00000000000..944bafacfcb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverview.css
@@ -0,0 +1,9 @@
+/**
+ * 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.
+ */
+
+.css-overview-panel {
+ overflow: hidden;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewCompletedView.css b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewCompletedView.css
new file mode 100644
index 00000000000..5967edfed00
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewCompletedView.css
@@ -0,0 +1,92 @@
+/**
+ * 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.
+ */
+
+.overview-completed-view {
+ overflow: auto;
+}
+
+.overview-completed-view .summary ul,
+.overview-completed-view .colors ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.overview-completed-view .summary ul {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, 140px);
+ grid-gap: 16px;
+}
+
+.overview-completed-view .colors ul li {
+ display: inline-block;
+ padding: 0;
+ margin: 0 0 16px 0;
+}
+
+.overview-completed-view .summary ul li {
+ display: flex;
+ flex-direction: column;
+ grid-column-start: auto;
+}
+
+.overview-completed-view li .label {
+ font-size: 12px;
+ padding-bottom: 2px;
+}
+
+.overview-completed-view li .value {
+ font-size: 17px;
+}
+
+.overview-completed-view ul li span {
+ font-weight: bold;
+}
+
+.media-query-grid .header-container,
+.media-query-grid .data-container,
+.media-query-grid table.data {
+ position: relative;
+}
+
+.media-query-grid .data-container {
+ top: 0;
+ max-height: 400px;
+}
+
+.block {
+ width: 65px;
+ height: 25px;
+ border-radius: 3px;
+ margin-right: 16px;
+}
+
+.block-title {
+ padding-top: 4px;
+ font-size: 12px;
+ color: #303942;
+ text-transform: uppercase;
+ letter-spacing: 0;
+}
+
+.results-section {
+ flex-shrink: 0;
+ padding: 28px;
+ border-bottom: 1px solid #E6E6E6;
+}
+
+.results-section h1 {
+ font-size: 15px;
+ font-weight: normal;
+ padding: 0;
+ margin: 0 0 20px 0;
+}
+
+.results-section.colors h2 {
+ margin-top: 20px;
+ font-size: 13px;
+ font-weight: normal;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewProcessingView.css b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewProcessingView.css
new file mode 100644
index 00000000000..a91165b196f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewProcessingView.css
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+.overview-processing-view {
+ overflow: hidden;
+}
+
+.overview-processing-view {
+ overflow: hidden;
+ padding: 16px;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+}
+
+.overview-processing-view h1 {
+ font-size: 16px;
+ text-align: center;
+ font-weight: normal;
+ margin: 0;
+ padding: 8px;
+}
+
+.overview-processing-view h2 {
+ font-size: 12px;
+ text-align: center;
+ font-weight: normal;
+ margin: 0;
+ padding-top: 32px;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewSidebarPanel.css b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewSidebarPanel.css
new file mode 100644
index 00000000000..45025dc5c6f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewSidebarPanel.css
@@ -0,0 +1,33 @@
+/**
+ * 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.
+ */
+
+.overview-sidebar-panel {
+ overflow: auto;
+ display: flex;
+ background: #F3F3F3;
+}
+
+.overview-sidebar-panel-item {
+ height: 30px;
+ padding-left: 30px;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+}
+
+.overview-sidebar-panel-item:hover,
+.overview-sidebar-panel-item:focus {
+ background: rgb(234, 234, 234);
+}
+
+.overview-sidebar-panel-item.selected {
+ background: #1A73E8;
+ color: #FFFFFF;
+}
+
+.overview-toolbar {
+ border-bottom: 1px solid rgb(204, 204, 204);
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewStartView.css b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewStartView.css
new file mode 100644
index 00000000000..1c3d870fedb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/cssOverviewStartView.css
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+
+.overview-start-view {
+ overflow: hidden;
+ padding: 16px;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+}
+
+.overview-start-view h1 {
+ font-size: 16px;
+ text-align: center;
+ font-weight: normal;
+ margin: 0;
+ padding: 8px;
+}
+
+.overview-start-view div {
+ font-size: 12px;
+ text-align: center;
+ font-weight: normal;
+ margin: 0;
+ padding-bottom: 44px;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/css_overview_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/css_overview_strings.grdp
new file mode 100644
index 00000000000..aa7d4062226
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/css_overview_strings.grdp
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_DEVTOOLS_01ac702a8b31775d1cdbc30ec453e611" desc="Label for the number of non-simple selectors in the CSS Overview report">
+ Non-simple selectors
+ </message>
+ <message name="IDS_DEVTOOLS_1049ae5279b7a1b50dddec905ed992df" desc="Label for the number ofstyle rules in CSS Overview report">
+ Style rules
+ </message>
+ <message name="IDS_DEVTOOLS_196c5897880c864a303527f5d8e7cb77" desc="Label for unique background colors in the CSS Overview report">
+ Unique background colors: <ph name="BACKGROUNDCOLORS_LENGTH">$1s<ex>17</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_1f1621cad66c8f661842bf9392d8559b" desc="Label for the summary in the CSS Overview report">
+ Overview summary
+ </message>
+ <message name="IDS_DEVTOOLS_23717568804f63f75e7596dcced3119e" desc="Label for the number of universal selectors in the CSS Overview report">
+ Universal selectors
+ </message>
+ <message name="IDS_DEVTOOLS_396ea220fc4d34d57a5a505de918bdde" desc="Singular of 'document element' in the processing update message">
+ document element
+ </message>
+ <message name="IDS_DEVTOOLS_4b3e6e4359cfb882a3b8b551f38a92c7" desc="Label for unique text colors in the CSS Overview Panel">
+ Unique text colors: <ph name="TEXTCOLORS_LENGTH">$1s<ex>32</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_52798275481d47b10f5b8e31310b155e" desc="Label for the update message in the processing stage of CSS Overview">
+ Processed <ph name="THIS__FORMATTER_FORMAT_HANDLED_">$1s<ex>23</ex></ph> of <ph name="THIS__FORMATTER_FORMAT_TOTAL_">$2s<ex>1,223</ex></ph> <ph name="ELEMENTSTOTAL">$3s<ex>document elements</ex></ph>.
+ </message>
+ <message name="IDS_DEVTOOLS_5d50889672f6f860d14f502de3de1957" desc="Title of colors subsection in the CSS Overview Panel">
+ Colors
+ </message>
+ <message name="IDS_DEVTOOLS_6ad170a0581c9c116ca254758bd0c5b9" desc="Label for the number of ID selectors in the CSS Overview report">
+ ID selectors
+ </message>
+ <message name="IDS_DEVTOOLS_811b0dc0576a9743353448d08b400f45" desc="Label for the number of Attribute selectors in the CSS Overview report">
+ Attribute selectors
+ </message>
+ <message name="IDS_DEVTOOLS_8781fdba66e6cf7177ce03ea3db8a35a" desc="Label for the number of class selectors in the CSS Overview report">
+ Class selectors
+ </message>
+ <message name="IDS_DEVTOOLS_8a2d39bc733e82310760e2767889673a" desc="Title of the CSS Overview Panel">
+ CSS Overview
+ </message>
+ <message name="IDS_DEVTOOLS_95d366a44bd7bad09d9916e05b512cc6" desc="Label for the number of External stylesheets in the CSS Overview report">
+ External stylesheets
+ </message>
+ <message name="IDS_DEVTOOLS_a9427e421abd9fd7ba45212c25ba55a5" desc="Plural of 'document element' in the processing update message">
+ document elements
+ </message>
+ <message name="IDS_DEVTOOLS_aff1062318f6d07520a0feba60f3f253" desc="Label for the number of type selectors in the CSS Overview report">
+ Type selectors
+ </message>
+ <message name="IDS_DEVTOOLS_cd9c2b5232bcbda828c542a9f5306f8e" desc="Label for the 'Elements processed' button in the CSS Overview report">
+ Elements processed
+ </message>
+ <message name="IDS_DEVTOOLS_d4a993a4b0d13c2cc4ce9387af1604ce" desc="Label for the 'Clear overview' button in the CSS Overview report">
+ Clear overview
+ </message>
+ <message name="IDS_DEVTOOLS_daee0f0fc555c02342c4e00a1dbf642a" desc="Label for the number of media rules in the CSS Overview report">
+ Media queries
+ </message>
+ <message name="IDS_DEVTOOLS_e9c6934e961dad71d311f68c679dfd3b" desc="Label for the capture button in the CSS Overview Panel">
+ Capture overview
+ </message>
+ <message name="IDS_DEVTOOLS_f1637e0528f8c9d37be5de8b50fd2926" desc="Label for the number of inline style elements in the CSS Overview report">
+ Inline style elements
+ </message>
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/css_overview/module.json b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/module.json
new file mode 100644
index 00000000000..7245192e077
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/css_overview/module.json
@@ -0,0 +1,35 @@
+{
+ "extensions": [
+ {
+ "type": "view",
+ "location": "panel",
+ "id": "cssoverview",
+ "title": "CSS Overview",
+ "className": "CssOverview.CSSOverviewPanel",
+ "order": 95,
+ "experiment": "cssOverview"
+ }
+ ],
+ "dependencies": [
+ "elements",
+ "ui",
+ "sdk",
+ "data_grid"
+ ],
+ "scripts": [
+ "CSSOverviewController.js",
+ "CSSOverviewModel.js",
+ "CSSOverviewStartView.js",
+ "CSSOverviewProcessingView.js",
+ "CSSOverviewCompletedView.js",
+ "CSSOverviewSidebarPanel.js",
+ "CSSOverviewPanel.js"
+ ],
+ "resources": [
+ "cssOverview.css",
+ "cssOverviewStartView.css",
+ "cssOverviewProcessingView.css",
+ "cssOverviewCompletedView.css",
+ "cssOverviewSidebarPanel.css"
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/LICENSE b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/LICENSE
index 1ed6f2a573f..77a97197316 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/LICENSE
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/LICENSE
@@ -1,5 +1,6 @@
-Copyright (c) 2014, sourceLair Limited (https://github.com/sourcelair/)
-Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
+MIT License
+
+Copyright (c) 2012-2014 Chris Pettitt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/README.md b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/README.md
new file mode 100644
index 00000000000..19a09096f23
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/README.md
@@ -0,0 +1,16 @@
+# Rolling Dagre
+
+## What is dagre?
+Dagre is a third-party graph layouting library, which is used by the graph visualizer of
+Chrome `DevTools/web_audio`. It implements several research papers about layouting graph.
+1. Size: The size of dagre.js 323 KB. The core of dagre.js is 83 KB.
+2. Github repo: https://github.com/dagrejs/dagre
+
+## Why should we add Dagre as a module, instead of a folder under web_audio?
+Dagre is used by both `DevTools/web_audio` and `DevTools/web_audio_worker`. Therefore,
+it seems better to be a module that can be used as a dependency. For example,
+`web_audio` constructs `dagre.graphlib.Graph` and sends to `web_audio_worker`, which is a Web Worker that runs `dagre.layout()`.
+
+## Updating Dagre
+1. Download from https://github.com/dagrejs/dagre/blob/master/dist/dagre.js
+2. Optionally add a comment "// clang-format off" at the beginning of `dagre.js`.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/dagre.js b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/dagre.js
new file mode 100644
index 00000000000..8843ea835f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/dagre.js
@@ -0,0 +1,11500 @@
+// clang-format off
+/* eslint-disable */
+(function(f) {
+if (typeof exports === 'object' && typeof module !== 'undefined') {
+ module.exports = f()
+} else if (typeof define === 'function' && define.amd) {
+ define([], f)
+} else {
+ var g;
+ if (typeof window !== 'undefined') {
+ g = window
+ } else if (typeof global !== 'undefined') {
+ g = global
+ } else if (typeof self !== 'undefined') {
+ g = self
+ } else {
+ g = this
+ }
+ g.dagre = f()
+}
+})(function() {
+var define, module, exports;
+return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c='function'==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error('Cannot find module \''+i+'\'');throw a.code='MODULE_NOT_FOUND',a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u='function'==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+/*
+Copyright (c) 2012-2014 Chris Pettitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+module.exports = {
+ graphlib: require('./lib/graphlib'),
+
+ layout: require('./lib/layout'),
+ debug: require('./lib/debug'),
+ util: {
+ time: require('./lib/util').time,
+ notime: require('./lib/util').notime
+ },
+ version: require('./lib/version')
+};
+
+},{'./lib/debug':6,'./lib/graphlib':7,'./lib/layout':9,'./lib/util':29,'./lib/version':30}],2:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash'),
+ greedyFAS = require('./greedy-fas');
+
+module.exports = {
+ run: run,
+ undo: undo
+};
+
+function run(g) {
+ var fas = (g.graph().acyclicer === 'greedy'
+ ? greedyFAS(g, weightFn(g))
+ : dfsFAS(g));
+ _.forEach(fas, function(e) {
+ var label = g.edge(e);
+ g.removeEdge(e);
+ label.forwardName = e.name;
+ label.reversed = true;
+ g.setEdge(e.w, e.v, label, _.uniqueId('rev'));
+ });
+
+ function weightFn(g) {
+ return function(e) {
+ return g.edge(e).weight;
+ };
+ }
+}
+
+function dfsFAS(g) {
+ var fas = [],
+ stack = {},
+ visited = {};
+
+ function dfs(v) {
+ if (_.has(visited, v)) {
+ return;
+ }
+ visited[v] = true;
+ stack[v] = true;
+ _.forEach(g.outEdges(v), function(e) {
+ if (_.has(stack, e.w)) {
+ fas.push(e);
+ } else {
+ dfs(e.w);
+ }
+ });
+ delete stack[v];
+ }
+
+ _.forEach(g.nodes(), dfs);
+ return fas;
+}
+
+function undo(g) {
+ _.forEach(g.edges(), function(e) {
+ var label = g.edge(e);
+ if (label.reversed) {
+ g.removeEdge(e);
+
+ var forwardName = label.forwardName;
+ delete label.reversed;
+ delete label.forwardName;
+ g.setEdge(e.w, e.v, label, forwardName);
+ }
+ });
+}
+
+},{'./greedy-fas':8,'./lodash':10}],3:[function(require,module,exports){
+var _ = require('./lodash'),
+ util = require('./util');
+
+module.exports = addBorderSegments;
+
+function addBorderSegments(g) {
+ function dfs(v) {
+ var children = g.children(v),
+ node = g.node(v);
+ if (children.length) {
+ _.forEach(children, dfs);
+ }
+
+ if (_.has(node, 'minRank')) {
+ node.borderLeft = [];
+ node.borderRight = [];
+ for (var rank = node.minRank, maxRank = node.maxRank + 1;
+ rank < maxRank;
+ ++rank) {
+ addBorderNode(g, 'borderLeft', '_bl', v, node, rank);
+ addBorderNode(g, 'borderRight', '_br', v, node, rank);
+ }
+ }
+ }
+
+ _.forEach(g.children(), dfs);
+}
+
+function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
+ var label = { width: 0, height: 0, rank: rank, borderType: prop },
+ prev = sgNode[prop][rank - 1],
+ curr = util.addDummyNode(g, 'border', label, prefix);
+ sgNode[prop][rank] = curr;
+ g.setParent(curr, sg);
+ if (prev) {
+ g.setEdge(prev, curr, { weight: 1 });
+ }
+}
+
+},{'./lodash':10,'./util':29}],4:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash');
+
+module.exports = {
+ adjust: adjust,
+ undo: undo
+};
+
+function adjust(g) {
+ var rankDir = g.graph().rankdir.toLowerCase();
+ if (rankDir === 'lr' || rankDir === 'rl') {
+ swapWidthHeight(g);
+ }
+}
+
+function undo(g) {
+ var rankDir = g.graph().rankdir.toLowerCase();
+ if (rankDir === 'bt' || rankDir === 'rl') {
+ reverseY(g);
+ }
+
+ if (rankDir === 'lr' || rankDir === 'rl') {
+ swapXY(g);
+ swapWidthHeight(g);
+ }
+}
+
+function swapWidthHeight(g) {
+ _.forEach(g.nodes(), function(v) { swapWidthHeightOne(g.node(v)); });
+ _.forEach(g.edges(), function(e) { swapWidthHeightOne(g.edge(e)); });
+}
+
+function swapWidthHeightOne(attrs) {
+ var w = attrs.width;
+ attrs.width = attrs.height;
+ attrs.height = w;
+}
+
+function reverseY(g) {
+ _.forEach(g.nodes(), function(v) { reverseYOne(g.node(v)); });
+
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.forEach(edge.points, reverseYOne);
+ if (_.has(edge, 'y')) {
+ reverseYOne(edge);
+ }
+ });
+}
+
+function reverseYOne(attrs) {
+ attrs.y = -attrs.y;
+}
+
+function swapXY(g) {
+ _.forEach(g.nodes(), function(v) { swapXYOne(g.node(v)); });
+
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.forEach(edge.points, swapXYOne);
+ if (_.has(edge, 'x')) {
+ swapXYOne(edge);
+ }
+ });
+}
+
+function swapXYOne(attrs) {
+ var x = attrs.x;
+ attrs.x = attrs.y;
+ attrs.y = x;
+}
+
+},{'./lodash':10}],5:[function(require,module,exports){
+/*
+ * Simple doubly linked list implementation derived from Cormen, et al.,
+ * "Introduction to Algorithms".
+ */
+
+module.exports = List;
+
+function List() {
+ var sentinel = {};
+ sentinel._next = sentinel._prev = sentinel;
+ this._sentinel = sentinel;
+}
+
+List.prototype.dequeue = function() {
+ var sentinel = this._sentinel,
+ entry = sentinel._prev;
+ if (entry !== sentinel) {
+ unlink(entry);
+ return entry;
+ }
+};
+
+List.prototype.enqueue = function(entry) {
+ var sentinel = this._sentinel;
+ if (entry._prev && entry._next) {
+ unlink(entry);
+ }
+ entry._next = sentinel._next;
+ sentinel._next._prev = entry;
+ sentinel._next = entry;
+ entry._prev = sentinel;
+};
+
+List.prototype.toString = function() {
+ var strs = [],
+ sentinel = this._sentinel,
+ curr = sentinel._prev;
+ while (curr !== sentinel) {
+ strs.push(JSON.stringify(curr, filterOutLinks));
+ curr = curr._prev;
+ }
+ return '[' + strs.join(', ') + ']';
+};
+
+function unlink(entry) {
+ entry._prev._next = entry._next;
+ entry._next._prev = entry._prev;
+ delete entry._next;
+ delete entry._prev;
+}
+
+function filterOutLinks(k, v) {
+ if (k !== '_next' && k !== '_prev') {
+ return v;
+ }
+}
+
+},{}],6:[function(require,module,exports){
+var _ = require('./lodash'),
+ util = require('./util'),
+ Graph = require('./graphlib').Graph;
+
+module.exports = {
+ debugOrdering: debugOrdering
+};
+
+/* istanbul ignore next */
+function debugOrdering(g) {
+ var layerMatrix = util.buildLayerMatrix(g);
+
+ var h = new Graph({ compound: true, multigraph: true }).setGraph({});
+
+ _.forEach(g.nodes(), function(v) {
+ h.setNode(v, { label: v });
+ h.setParent(v, 'layer' + g.node(v).rank);
+ });
+
+ _.forEach(g.edges(), function(e) {
+ h.setEdge(e.v, e.w, {}, e.name);
+ });
+
+ _.forEach(layerMatrix, function(layer, i) {
+ var layerV = 'layer' + i;
+ h.setNode(layerV, { rank: 'same' });
+ _.reduce(layer, function(u, v) {
+ h.setEdge(u, v, { style: 'invis' });
+ return v;
+ });
+ });
+
+ return h;
+}
+
+},{'./graphlib':7,'./lodash':10,'./util':29}],7:[function(require,module,exports){
+/* global window */
+
+var graphlib;
+
+if (typeof require === 'function') {
+ try {
+ graphlib = require('graphlib');
+ } catch (e) {}
+}
+
+if (!graphlib) {
+ graphlib = window.graphlib;
+}
+
+module.exports = graphlib;
+
+},{'graphlib':31}],8:[function(require,module,exports){
+var _ = require('./lodash'),
+ Graph = require('./graphlib').Graph,
+ List = require('./data/list');
+
+/*
+ * A greedy heuristic for finding a feedback arc set for a graph. A feedback
+ * arc set is a set of edges that can be removed to make a graph acyclic.
+ * The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
+ * effective heuristic for the feedback arc set problem." This implementation
+ * adjusts that from the paper to allow for weighted edges.
+ */
+module.exports = greedyFAS;
+
+var DEFAULT_WEIGHT_FN = _.constant(1);
+
+function greedyFAS(g, weightFn) {
+ if (g.nodeCount() <= 1) {
+ return [];
+ }
+ var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
+ var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
+
+ // Expand multi-edges
+ return _.flatten(_.map(results, function(e) {
+ return g.outEdges(e.v, e.w);
+ }), true);
+}
+
+function doGreedyFAS(g, buckets, zeroIdx) {
+ var results = [],
+ sources = buckets[buckets.length - 1],
+ sinks = buckets[0];
+
+ var entry;
+ while (g.nodeCount()) {
+ while ((entry = sinks.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
+ while ((entry = sources.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
+ if (g.nodeCount()) {
+ for (var i = buckets.length - 2; i > 0; --i) {
+ entry = buckets[i].dequeue();
+ if (entry) {
+ results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
+ break;
+ }
+ }
+ }
+ }
+
+ return results;
+}
+
+function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
+ var results = collectPredecessors ? [] : undefined;
+
+ _.forEach(g.inEdges(entry.v), function(edge) {
+ var weight = g.edge(edge),
+ uEntry = g.node(edge.v);
+
+ if (collectPredecessors) {
+ results.push({ v: edge.v, w: edge.w });
+ }
+
+ uEntry.out -= weight;
+ assignBucket(buckets, zeroIdx, uEntry);
+ });
+
+ _.forEach(g.outEdges(entry.v), function(edge) {
+ var weight = g.edge(edge),
+ w = edge.w,
+ wEntry = g.node(w);
+ wEntry['in'] -= weight;
+ assignBucket(buckets, zeroIdx, wEntry);
+ });
+
+ g.removeNode(entry.v);
+
+ return results;
+}
+
+function buildState(g, weightFn) {
+ var fasGraph = new Graph(),
+ maxIn = 0,
+ maxOut = 0;
+
+ _.forEach(g.nodes(), function(v) {
+ fasGraph.setNode(v, { v: v, 'in': 0, out: 0 });
+ });
+
+ // Aggregate weights on nodes, but also sum the weights across multi-edges
+ // into a single edge for the fasGraph.
+ _.forEach(g.edges(), function(e) {
+ var prevWeight = fasGraph.edge(e.v, e.w) || 0,
+ weight = weightFn(e),
+ edgeWeight = prevWeight + weight;
+ fasGraph.setEdge(e.v, e.w, edgeWeight);
+ maxOut = Math.max(maxOut, fasGraph.node(e.v).out += weight);
+ maxIn = Math.max(maxIn, fasGraph.node(e.w)['in'] += weight);
+ });
+
+ var buckets = _.range(maxOut + maxIn + 3).map(function() { return new List(); });
+ var zeroIdx = maxIn + 1;
+
+ _.forEach(fasGraph.nodes(), function(v) {
+ assignBucket(buckets, zeroIdx, fasGraph.node(v));
+ });
+
+ return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
+}
+
+function assignBucket(buckets, zeroIdx, entry) {
+ if (!entry.out) {
+ buckets[0].enqueue(entry);
+ } else if (!entry['in']) {
+ buckets[buckets.length - 1].enqueue(entry);
+ } else {
+ buckets[entry.out - entry['in'] + zeroIdx].enqueue(entry);
+ }
+}
+
+},{'./data/list':5,'./graphlib':7,'./lodash':10}],9:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash'),
+ acyclic = require('./acyclic'),
+ normalize = require('./normalize'),
+ rank = require('./rank'),
+ normalizeRanks = require('./util').normalizeRanks,
+ parentDummyChains = require('./parent-dummy-chains'),
+ removeEmptyRanks = require('./util').removeEmptyRanks,
+ nestingGraph = require('./nesting-graph'),
+ addBorderSegments = require('./add-border-segments'),
+ coordinateSystem = require('./coordinate-system'),
+ order = require('./order'),
+ position = require('./position'),
+ util = require('./util'),
+ Graph = require('./graphlib').Graph;
+
+module.exports = layout;
+
+function layout(g, opts) {
+ var time = opts && opts.debugTiming ? util.time : util.notime;
+ time('layout', function() {
+ var layoutGraph = time(' buildLayoutGraph',
+ function() { return buildLayoutGraph(g); });
+ time(' runLayout', function() { runLayout(layoutGraph, time); });
+ time(' updateInputGraph', function() { updateInputGraph(g, layoutGraph); });
+ });
+}
+
+function runLayout(g, time) {
+ time(' makeSpaceForEdgeLabels', function() { makeSpaceForEdgeLabels(g); });
+ time(' removeSelfEdges', function() { removeSelfEdges(g); });
+ time(' acyclic', function() { acyclic.run(g); });
+ time(' nestingGraph.run', function() { nestingGraph.run(g); });
+ time(' rank', function() { rank(util.asNonCompoundGraph(g)); });
+ time(' injectEdgeLabelProxies', function() { injectEdgeLabelProxies(g); });
+ time(' removeEmptyRanks', function() { removeEmptyRanks(g); });
+ time(' nestingGraph.cleanup', function() { nestingGraph.cleanup(g); });
+ time(' normalizeRanks', function() { normalizeRanks(g); });
+ time(' assignRankMinMax', function() { assignRankMinMax(g); });
+ time(' removeEdgeLabelProxies', function() { removeEdgeLabelProxies(g); });
+ time(' normalize.run', function() { normalize.run(g); });
+ time(' parentDummyChains', function() { parentDummyChains(g); });
+ time(' addBorderSegments', function() { addBorderSegments(g); });
+ time(' order', function() { order(g); });
+ time(' insertSelfEdges', function() { insertSelfEdges(g); });
+ time(' adjustCoordinateSystem', function() { coordinateSystem.adjust(g); });
+ time(' position', function() { position(g); });
+ time(' positionSelfEdges', function() { positionSelfEdges(g); });
+ time(' removeBorderNodes', function() { removeBorderNodes(g); });
+ time(' normalize.undo', function() { normalize.undo(g); });
+ time(' fixupEdgeLabelCoords', function() { fixupEdgeLabelCoords(g); });
+ time(' undoCoordinateSystem', function() { coordinateSystem.undo(g); });
+ time(' translateGraph', function() { translateGraph(g); });
+ time(' assignNodeIntersects', function() { assignNodeIntersects(g); });
+ time(' reversePoints', function() { reversePointsForReversedEdges(g); });
+ time(' acyclic.undo', function() { acyclic.undo(g); });
+}
+
+/*
+ * Copies final layout information from the layout graph back to the input
+ * graph. This process only copies whitelisted attributes from the layout graph
+ * to the input graph, so it serves as a good place to determine what
+ * attributes can influence layout.
+ */
+function updateInputGraph(inputGraph, layoutGraph) {
+ _.forEach(inputGraph.nodes(), function(v) {
+ var inputLabel = inputGraph.node(v),
+ layoutLabel = layoutGraph.node(v);
+
+ if (inputLabel) {
+ inputLabel.x = layoutLabel.x;
+ inputLabel.y = layoutLabel.y;
+
+ if (layoutGraph.children(v).length) {
+ inputLabel.width = layoutLabel.width;
+ inputLabel.height = layoutLabel.height;
+ }
+ }
+ });
+
+ _.forEach(inputGraph.edges(), function(e) {
+ var inputLabel = inputGraph.edge(e),
+ layoutLabel = layoutGraph.edge(e);
+
+ inputLabel.points = layoutLabel.points;
+ if (_.has(layoutLabel, 'x')) {
+ inputLabel.x = layoutLabel.x;
+ inputLabel.y = layoutLabel.y;
+ }
+ });
+
+ inputGraph.graph().width = layoutGraph.graph().width;
+ inputGraph.graph().height = layoutGraph.graph().height;
+}
+
+var graphNumAttrs = ['nodesep', 'edgesep', 'ranksep', 'marginx', 'marginy'],
+ graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: 'tb' },
+ graphAttrs = ['acyclicer', 'ranker', 'rankdir', 'align'],
+ nodeNumAttrs = ['width', 'height'],
+ nodeDefaults = { width: 0, height: 0 },
+ edgeNumAttrs = ['minlen', 'weight', 'width', 'height', 'labeloffset'],
+ edgeDefaults = {
+ minlen: 1, weight: 1, width: 0, height: 0,
+ labeloffset: 10, labelpos: 'r'
+ },
+ edgeAttrs = ['labelpos'];
+
+/*
+ * Constructs a new graph from the input graph, which can be used for layout.
+ * This process copies only whitelisted attributes from the input graph to the
+ * layout graph. Thus this function serves as a good place to determine what
+ * attributes can influence layout.
+ */
+function buildLayoutGraph(inputGraph) {
+ var g = new Graph({ multigraph: true, compound: true }),
+ graph = canonicalize(inputGraph.graph());
+
+ g.setGraph(_.merge({},
+ graphDefaults,
+ selectNumberAttrs(graph, graphNumAttrs),
+ _.pick(graph, graphAttrs)));
+
+ _.forEach(inputGraph.nodes(), function(v) {
+ var node = canonicalize(inputGraph.node(v));
+ g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults));
+ g.setParent(v, inputGraph.parent(v));
+ });
+
+ _.forEach(inputGraph.edges(), function(e) {
+ var edge = canonicalize(inputGraph.edge(e));
+ g.setEdge(e, _.merge({},
+ edgeDefaults,
+ selectNumberAttrs(edge, edgeNumAttrs),
+ _.pick(edge, edgeAttrs)));
+ });
+
+ return g;
+}
+
+/*
+ * This idea comes from the Gansner paper: to account for edge labels in our
+ * layout we split each rank in half by doubling minlen and halving ranksep.
+ * Then we can place labels at these mid-points between nodes.
+ *
+ * We also add some minimal padding to the width to push the label for the edge
+ * away from the edge itself a bit.
+ */
+function makeSpaceForEdgeLabels(g) {
+ var graph = g.graph();
+ graph.ranksep /= 2;
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ edge.minlen *= 2;
+ if (edge.labelpos.toLowerCase() !== 'c') {
+ if (graph.rankdir === 'TB' || graph.rankdir === 'BT') {
+ edge.width += edge.labeloffset;
+ } else {
+ edge.height += edge.labeloffset;
+ }
+ }
+ });
+}
+
+/*
+ * Creates temporary dummy nodes that capture the rank in which each edge's
+ * label is going to, if it has one of non-zero width and height. We do this
+ * so that we can safely remove empty ranks while preserving balance for the
+ * label's position.
+ */
+function injectEdgeLabelProxies(g) {
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.width && edge.height) {
+ var v = g.node(e.v),
+ w = g.node(e.w),
+ label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
+ util.addDummyNode(g, 'edge-proxy', label, '_ep');
+ }
+ });
+}
+
+function assignRankMinMax(g) {
+ var maxRank = 0;
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.borderTop) {
+ node.minRank = g.node(node.borderTop).rank;
+ node.maxRank = g.node(node.borderBottom).rank;
+ maxRank = _.max(maxRank, node.maxRank);
+ }
+ });
+ g.graph().maxRank = maxRank;
+}
+
+function removeEdgeLabelProxies(g) {
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.dummy === 'edge-proxy') {
+ g.edge(node.e).labelRank = node.rank;
+ g.removeNode(v);
+ }
+ });
+}
+
+function translateGraph(g) {
+ var minX = Number.POSITIVE_INFINITY,
+ maxX = 0,
+ minY = Number.POSITIVE_INFINITY,
+ maxY = 0,
+ graphLabel = g.graph(),
+ marginX = graphLabel.marginx || 0,
+ marginY = graphLabel.marginy || 0;
+
+ function getExtremes(attrs) {
+ var x = attrs.x,
+ y = attrs.y,
+ w = attrs.width,
+ h = attrs.height;
+ minX = Math.min(minX, x - w / 2);
+ maxX = Math.max(maxX, x + w / 2);
+ minY = Math.min(minY, y - h / 2);
+ maxY = Math.max(maxY, y + h / 2);
+ }
+
+ _.forEach(g.nodes(), function(v) { getExtremes(g.node(v)); });
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (_.has(edge, 'x')) {
+ getExtremes(edge);
+ }
+ });
+
+ minX -= marginX;
+ minY -= marginY;
+
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v);
+ node.x -= minX;
+ node.y -= minY;
+ });
+
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.forEach(edge.points, function(p) {
+ p.x -= minX;
+ p.y -= minY;
+ });
+ if (_.has(edge, 'x')) { edge.x -= minX; }
+ if (_.has(edge, 'y')) { edge.y -= minY; }
+ });
+
+ graphLabel.width = maxX - minX + marginX;
+ graphLabel.height = maxY - minY + marginY;
+}
+
+function assignNodeIntersects(g) {
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e),
+ nodeV = g.node(e.v),
+ nodeW = g.node(e.w),
+ p1, p2;
+ if (!edge.points) {
+ edge.points = [];
+ p1 = nodeW;
+ p2 = nodeV;
+ } else {
+ p1 = edge.points[0];
+ p2 = edge.points[edge.points.length - 1];
+ }
+ edge.points.unshift(util.intersectRect(nodeV, p1));
+ edge.points.push(util.intersectRect(nodeW, p2));
+ });
+}
+
+function fixupEdgeLabelCoords(g) {
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (_.has(edge, 'x')) {
+ if (edge.labelpos === 'l' || edge.labelpos === 'r') {
+ edge.width -= edge.labeloffset;
+ }
+ switch (edge.labelpos) {
+ case 'l': edge.x -= edge.width / 2 + edge.labeloffset; break;
+ case 'r': edge.x += edge.width / 2 + edge.labeloffset; break;
+ }
+ }
+ });
+}
+
+function reversePointsForReversedEdges(g) {
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.reversed) {
+ edge.points.reverse();
+ }
+ });
+}
+
+function removeBorderNodes(g) {
+ _.forEach(g.nodes(), function(v) {
+ if (g.children(v).length) {
+ var node = g.node(v),
+ t = g.node(node.borderTop),
+ b = g.node(node.borderBottom),
+ l = g.node(_.last(node.borderLeft)),
+ r = g.node(_.last(node.borderRight));
+
+ node.width = Math.abs(r.x - l.x);
+ node.height = Math.abs(b.y - t.y);
+ node.x = l.x + node.width / 2;
+ node.y = t.y + node.height / 2;
+ }
+ });
+
+ _.forEach(g.nodes(), function(v) {
+ if (g.node(v).dummy === 'border') {
+ g.removeNode(v);
+ }
+ });
+}
+
+function removeSelfEdges(g) {
+ _.forEach(g.edges(), function(e) {
+ if (e.v === e.w) {
+ var node = g.node(e.v);
+ if (!node.selfEdges) {
+ node.selfEdges = [];
+ }
+ node.selfEdges.push({ e: e, label: g.edge(e) });
+ g.removeEdge(e);
+ }
+ });
+}
+
+function insertSelfEdges(g) {
+ var layers = util.buildLayerMatrix(g);
+ _.forEach(layers, function(layer) {
+ var orderShift = 0;
+ _.forEach(layer, function(v, i) {
+ var node = g.node(v);
+ node.order = i + orderShift;
+ _.forEach(node.selfEdges, function(selfEdge) {
+ util.addDummyNode(g, 'selfedge', {
+ width: selfEdge.label.width,
+ height: selfEdge.label.height,
+ rank: node.rank,
+ order: i + (++orderShift),
+ e: selfEdge.e,
+ label: selfEdge.label
+ }, '_se');
+ });
+ delete node.selfEdges;
+ });
+ });
+}
+
+function positionSelfEdges(g) {
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.dummy === 'selfedge') {
+ var selfNode = g.node(node.e.v),
+ x = selfNode.x + selfNode.width / 2,
+ y = selfNode.y,
+ dx = node.x - x,
+ dy = selfNode.height / 2;
+ g.setEdge(node.e, node.label);
+ g.removeNode(v);
+ node.label.points = [
+ { x: x + 2 * dx / 3, y: y - dy },
+ { x: x + 5 * dx / 6, y: y - dy },
+ { x: x + dx , y: y },
+ { x: x + 5 * dx / 6, y: y + dy },
+ { x: x + 2 * dx / 3, y: y + dy }
+ ];
+ node.label.x = node.x;
+ node.label.y = node.y;
+ }
+ });
+}
+
+function selectNumberAttrs(obj, attrs) {
+ return _.mapValues(_.pick(obj, attrs), Number);
+}
+
+function canonicalize(attrs) {
+ var newAttrs = {};
+ _.forEach(attrs, function(v, k) {
+ newAttrs[k.toLowerCase()] = v;
+ });
+ return newAttrs;
+}
+
+},{'./acyclic':2,'./add-border-segments':3,'./coordinate-system':4,'./graphlib':7,'./lodash':10,'./nesting-graph':11,'./normalize':12,'./order':17,'./parent-dummy-chains':22,'./position':24,'./rank':26,'./util':29}],10:[function(require,module,exports){
+/* global window */
+
+var lodash;
+
+if (typeof require === 'function') {
+ try {
+ lodash = {
+ cloneDeep: require('lodash/cloneDeep'),
+ constant: require('lodash/constant'),
+ defaults: require('lodash/defaults'),
+ each: require('lodash/each'),
+ filter: require('lodash/filter'),
+ find: require('lodash/find'),
+ flatten: require('lodash/flatten'),
+ forEach: require('lodash/forEach'),
+ forIn: require('lodash/forIn'),
+ has: require('lodash/has'),
+ isUndefined: require('lodash/isUndefined'),
+ last: require('lodash/last'),
+ map: require('lodash/map'),
+ mapValues: require('lodash/mapValues'),
+ max: require('lodash/max'),
+ merge: require('lodash/merge'),
+ min: require('lodash/min'),
+ minBy: require('lodash/minBy'),
+ now: require('lodash/now'),
+ pick: require('lodash/pick'),
+ range: require('lodash/range'),
+ reduce: require('lodash/reduce'),
+ sortBy: require('lodash/sortBy'),
+ uniqueId: require('lodash/uniqueId'),
+ values: require('lodash/values'),
+ zipObject: require('lodash/zipObject'),
+ };
+ } catch (e) {}
+}
+
+if (!lodash) {
+ lodash = window._;
+}
+
+module.exports = lodash;
+
+},{'lodash/cloneDeep':227,'lodash/constant':228,'lodash/defaults':229,'lodash/each':230,'lodash/filter':232,'lodash/find':233,'lodash/flatten':235,'lodash/forEach':236,'lodash/forIn':237,'lodash/has':239,'lodash/isUndefined':258,'lodash/last':261,'lodash/map':262,'lodash/mapValues':263,'lodash/max':264,'lodash/merge':266,'lodash/min':267,'lodash/minBy':268,'lodash/now':270,'lodash/pick':271,'lodash/range':273,'lodash/reduce':274,'lodash/sortBy':276,'lodash/uniqueId':286,'lodash/values':287,'lodash/zipObject':288}],11:[function(require,module,exports){
+var _ = require('./lodash'),
+ util = require('./util');
+
+module.exports = {
+ run: run,
+ cleanup: cleanup
+};
+
+/*
+ * A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
+ * adds appropriate edges to ensure that all cluster nodes are placed between
+ * these boundries, and ensures that the graph is connected.
+ *
+ * In addition we ensure, through the use of the minlen property, that nodes
+ * and subgraph border nodes to not end up on the same rank.
+ *
+ * Preconditions:
+ *
+ * 1. Input graph is a DAG
+ * 2. Nodes in the input graph has a minlen attribute
+ *
+ * Postconditions:
+ *
+ * 1. Input graph is connected.
+ * 2. Dummy nodes are added for the tops and bottoms of subgraphs.
+ * 3. The minlen attribute for nodes is adjusted to ensure nodes do not
+ * get placed on the same rank as subgraph border nodes.
+ *
+ * The nesting graph idea comes from Sander, "Layout of Compound Directed
+ * Graphs."
+ */
+function run(g) {
+ var root = util.addDummyNode(g, 'root', {}, '_root');
+ var depths = treeDepths(g);
+ var height = _.max(_.values(depths)) - 1; // Note: depths is an Object not an array
+ var nodeSep = 2 * height + 1;
+
+ g.graph().nestingRoot = root;
+
+ // Multiply minlen by nodeSep to align nodes on non-border ranks.
+ _.forEach(g.edges(), function(e) { g.edge(e).minlen *= nodeSep; });
+
+ // Calculate a weight that is sufficient to keep subgraphs vertically compact
+ var weight = sumWeights(g) + 1;
+
+ // Create border nodes and link them up
+ _.forEach(g.children(), function(child) {
+ dfs(g, root, nodeSep, weight, height, depths, child);
+ });
+
+ // Save the multiplier for node layers for later removal of empty border
+ // layers.
+ g.graph().nodeRankFactor = nodeSep;
+}
+
+function dfs(g, root, nodeSep, weight, height, depths, v) {
+ var children = g.children(v);
+ if (!children.length) {
+ if (v !== root) {
+ g.setEdge(root, v, { weight: 0, minlen: nodeSep });
+ }
+ return;
+ }
+
+ var top = util.addBorderNode(g, '_bt'),
+ bottom = util.addBorderNode(g, '_bb'),
+ label = g.node(v);
+
+ g.setParent(top, v);
+ label.borderTop = top;
+ g.setParent(bottom, v);
+ label.borderBottom = bottom;
+
+ _.forEach(children, function(child) {
+ dfs(g, root, nodeSep, weight, height, depths, child);
+
+ var childNode = g.node(child),
+ childTop = childNode.borderTop ? childNode.borderTop : child,
+ childBottom = childNode.borderBottom ? childNode.borderBottom : child,
+ thisWeight = childNode.borderTop ? weight : 2 * weight,
+ minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
+
+ g.setEdge(top, childTop, {
+ weight: thisWeight,
+ minlen: minlen,
+ nestingEdge: true
+ });
+
+ g.setEdge(childBottom, bottom, {
+ weight: thisWeight,
+ minlen: minlen,
+ nestingEdge: true
+ });
+ });
+
+ if (!g.parent(v)) {
+ g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
+ }
+}
+
+function treeDepths(g) {
+ var depths = {};
+ function dfs(v, depth) {
+ var children = g.children(v);
+ if (children && children.length) {
+ _.forEach(children, function(child) {
+ dfs(child, depth + 1);
+ });
+ }
+ depths[v] = depth;
+ }
+ _.forEach(g.children(), function(v) { dfs(v, 1); });
+ return depths;
+}
+
+function sumWeights(g) {
+ return _.reduce(g.edges(), function(acc, e) {
+ return acc + g.edge(e).weight;
+ }, 0);
+}
+
+function cleanup(g) {
+ var graphLabel = g.graph();
+ g.removeNode(graphLabel.nestingRoot);
+ delete graphLabel.nestingRoot;
+ _.forEach(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.nestingEdge) {
+ g.removeEdge(e);
+ }
+ });
+}
+
+},{'./lodash':10,'./util':29}],12:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash'),
+ util = require('./util');
+
+module.exports = {
+ run: run,
+ undo: undo
+};
+
+/*
+ * Breaks any long edges in the graph into short segments that span 1 layer
+ * each. This operation is undoable with the denormalize function.
+ *
+ * Pre-conditions:
+ *
+ * 1. The input graph is a DAG.
+ * 2. Each node in the graph has a "rank" property.
+ *
+ * Post-condition:
+ *
+ * 1. All edges in the graph have a length of 1.
+ * 2. Dummy nodes are added where edges have been split into segments.
+ * 3. The graph is augmented with a "dummyChains" attribute which contains
+ * the first dummy in each chain of dummy nodes produced.
+ */
+function run(g) {
+ g.graph().dummyChains = [];
+ _.forEach(g.edges(), function(edge) { normalizeEdge(g, edge); });
+}
+
+function normalizeEdge(g, e) {
+ var v = e.v,
+ vRank = g.node(v).rank,
+ w = e.w,
+ wRank = g.node(w).rank,
+ name = e.name,
+ edgeLabel = g.edge(e),
+ labelRank = edgeLabel.labelRank;
+
+ if (wRank === vRank + 1) return;
+
+ g.removeEdge(e);
+
+ var dummy, attrs, i;
+ for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
+ edgeLabel.points = [];
+ attrs = {
+ width: 0, height: 0,
+ edgeLabel: edgeLabel, edgeObj: e,
+ rank: vRank
+ };
+ dummy = util.addDummyNode(g, 'edge', attrs, '_d');
+ if (vRank === labelRank) {
+ attrs.width = edgeLabel.width;
+ attrs.height = edgeLabel.height;
+ attrs.dummy = 'edge-label';
+ attrs.labelpos = edgeLabel.labelpos;
+ }
+ g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
+ if (i === 0) {
+ g.graph().dummyChains.push(dummy);
+ }
+ v = dummy;
+ }
+
+ g.setEdge(v, w, { weight: edgeLabel.weight }, name);
+}
+
+function undo(g) {
+ _.forEach(g.graph().dummyChains, function(v) {
+ var node = g.node(v),
+ origLabel = node.edgeLabel,
+ w;
+ g.setEdge(node.edgeObj, origLabel);
+ while (node.dummy) {
+ w = g.successors(v)[0];
+ g.removeNode(v);
+ origLabel.points.push({ x: node.x, y: node.y });
+ if (node.dummy === 'edge-label') {
+ origLabel.x = node.x;
+ origLabel.y = node.y;
+ origLabel.width = node.width;
+ origLabel.height = node.height;
+ }
+ v = w;
+ node = g.node(v);
+ }
+ });
+}
+
+},{'./lodash':10,'./util':29}],13:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = addSubgraphConstraints;
+
+function addSubgraphConstraints(g, cg, vs) {
+ var prev = {},
+ rootPrev;
+
+ _.forEach(vs, function(v) {
+ var child = g.parent(v),
+ parent,
+ prevChild;
+ while (child) {
+ parent = g.parent(child);
+ if (parent) {
+ prevChild = prev[parent];
+ prev[parent] = child;
+ } else {
+ prevChild = rootPrev;
+ rootPrev = child;
+ }
+ if (prevChild && prevChild !== child) {
+ cg.setEdge(prevChild, child);
+ return;
+ }
+ child = parent;
+ }
+ });
+
+ /*
+ function dfs(v) {
+ var children = v ? g.children(v) : g.children();
+ if (children.length) {
+ var min = Number.POSITIVE_INFINITY,
+ subgraphs = [];
+ _.each(children, function(child) {
+ var childMin = dfs(child);
+ if (g.children(child).length) {
+ subgraphs.push({ v: child, order: childMin });
+ }
+ min = Math.min(min, childMin);
+ });
+ _.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
+ cg.setEdge(prev.v, curr.v);
+ return curr;
+ });
+ return min;
+ }
+ return g.node(v).order;
+ }
+ dfs(undefined);
+ */
+}
+
+},{'../lodash':10}],14:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = barycenter;
+
+function barycenter(g, movable) {
+ return _.map(movable, function(v) {
+ var inV = g.inEdges(v);
+ if (!inV.length) {
+ return { v: v };
+ } else {
+ var result = _.reduce(inV, function(acc, e) {
+ var edge = g.edge(e),
+ nodeU = g.node(e.v);
+ return {
+ sum: acc.sum + (edge.weight * nodeU.order),
+ weight: acc.weight + edge.weight
+ };
+ }, { sum: 0, weight: 0 });
+
+ return {
+ v: v,
+ barycenter: result.sum / result.weight,
+ weight: result.weight
+ };
+ }
+ });
+}
+
+
+},{'../lodash':10}],15:[function(require,module,exports){
+var _ = require('../lodash'),
+ Graph = require('../graphlib').Graph;
+
+module.exports = buildLayerGraph;
+
+/*
+ * Constructs a graph that can be used to sort a layer of nodes. The graph will
+ * contain all base and subgraph nodes from the request layer in their original
+ * hierarchy and any edges that are incident on these nodes and are of the type
+ * requested by the "relationship" parameter.
+ *
+ * Nodes from the requested rank that do not have parents are assigned a root
+ * node in the output graph, which is set in the root graph attribute. This
+ * makes it easy to walk the hierarchy of movable nodes during ordering.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph is a DAG
+ * 2. Base nodes in the input graph have a rank attribute
+ * 3. Subgraph nodes in the input graph has minRank and maxRank attributes
+ * 4. Edges have an assigned weight
+ *
+ * Post-conditions:
+ *
+ * 1. Output graph has all nodes in the movable rank with preserved
+ * hierarchy.
+ * 2. Root nodes in the movable layer are made children of the node
+ * indicated by the root attribute of the graph.
+ * 3. Non-movable nodes incident on movable nodes, selected by the
+ * relationship parameter, are included in the graph (without hierarchy).
+ * 4. Edges incident on movable nodes, selected by the relationship
+ * parameter, are added to the output graph.
+ * 5. The weights for copied edges are aggregated as need, since the output
+ * graph is not a multi-graph.
+ */
+function buildLayerGraph(g, rank, relationship) {
+ var root = createRootNode(g),
+ result = new Graph({ compound: true }).setGraph({ root: root })
+ .setDefaultNodeLabel(function(v) { return g.node(v); });
+
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v),
+ parent = g.parent(v);
+
+ if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
+ result.setNode(v);
+ result.setParent(v, parent || root);
+
+ // This assumes we have only short edges!
+ _.forEach(g[relationship](v), function(e) {
+ var u = e.v === v ? e.w : e.v,
+ edge = result.edge(u, v),
+ weight = !_.isUndefined(edge) ? edge.weight : 0;
+ result.setEdge(u, v, { weight: g.edge(e).weight + weight });
+ });
+
+ if (_.has(node, 'minRank')) {
+ result.setNode(v, {
+ borderLeft: node.borderLeft[rank],
+ borderRight: node.borderRight[rank]
+ });
+ }
+ }
+ });
+
+ return result;
+}
+
+function createRootNode(g) {
+ var v;
+ while (g.hasNode((v = _.uniqueId('_root'))));
+ return v;
+}
+
+},{'../graphlib':7,'../lodash':10}],16:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash');
+
+module.exports = crossCount;
+
+/*
+ * A function that takes a layering (an array of layers, each with an array of
+ * ordererd nodes) and a graph and returns a weighted crossing count.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph must be simple (not a multigraph), directed, and include
+ * only simple edges.
+ * 2. Edges in the input graph must have assigned weights.
+ *
+ * Post-conditions:
+ *
+ * 1. The graph and layering matrix are left unchanged.
+ *
+ * This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
+ */
+function crossCount(g, layering) {
+ var cc = 0;
+ for (var i = 1; i < layering.length; ++i) {
+ cc += twoLayerCrossCount(g, layering[i-1], layering[i]);
+ }
+ return cc;
+}
+
+function twoLayerCrossCount(g, northLayer, southLayer) {
+ // Sort all of the edges between the north and south layers by their position
+ // in the north layer and then the south. Map these edges to the position of
+ // their head in the south layer.
+ var southPos = _.zipObject(southLayer,
+ _.map(southLayer, function (v, i) { return i; }));
+ var southEntries = _.flatten(_.map(northLayer, function(v) {
+ return _.sortBy(_.map(g.outEdges(v), function(e) {
+ return { pos: southPos[e.w], weight: g.edge(e).weight };
+ }), 'pos');
+ }), true);
+
+ // Build the accumulator tree
+ var firstIndex = 1;
+ while (firstIndex < southLayer.length) firstIndex <<= 1;
+ var treeSize = 2 * firstIndex - 1;
+ firstIndex -= 1;
+ var tree = _.map(new Array(treeSize), function() { return 0; });
+
+ // Calculate the weighted crossings
+ var cc = 0;
+ _.forEach(southEntries.forEach(function(entry) {
+ var index = entry.pos + firstIndex;
+ tree[index] += entry.weight;
+ var weightSum = 0;
+ while (index > 0) {
+ if (index % 2) {
+ weightSum += tree[index + 1];
+ }
+ index = (index - 1) >> 1;
+ tree[index] += entry.weight;
+ }
+ cc += entry.weight * weightSum;
+ }));
+
+ return cc;
+}
+
+},{'../lodash':10}],17:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash'),
+ initOrder = require('./init-order'),
+ crossCount = require('./cross-count'),
+ sortSubgraph = require('./sort-subgraph'),
+ buildLayerGraph = require('./build-layer-graph'),
+ addSubgraphConstraints = require('./add-subgraph-constraints'),
+ Graph = require('../graphlib').Graph,
+ util = require('../util');
+
+module.exports = order;
+
+/*
+ * Applies heuristics to minimize edge crossings in the graph and sets the best
+ * order solution as an order attribute on each node.
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be DAG
+ * 2. Graph nodes must be objects with a "rank" attribute
+ * 3. Graph edges must have the "weight" attribute
+ *
+ * Post-conditions:
+ *
+ * 1. Graph nodes will have an "order" attribute based on the results of the
+ * algorithm.
+ */
+function order(g) {
+ var maxRank = util.maxRank(g),
+ downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), 'inEdges'),
+ upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), 'outEdges');
+
+ var layering = initOrder(g);
+ assignOrder(g, layering);
+
+ var bestCC = Number.POSITIVE_INFINITY,
+ best;
+
+ for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
+ sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
+
+ layering = util.buildLayerMatrix(g);
+ var cc = crossCount(g, layering);
+ if (cc < bestCC) {
+ lastBest = 0;
+ best = _.cloneDeep(layering);
+ bestCC = cc;
+ }
+ }
+
+ assignOrder(g, best);
+}
+
+function buildLayerGraphs(g, ranks, relationship) {
+ return _.map(ranks, function(rank) {
+ return buildLayerGraph(g, rank, relationship);
+ });
+}
+
+function sweepLayerGraphs(layerGraphs, biasRight) {
+ var cg = new Graph();
+ _.forEach(layerGraphs, function(lg) {
+ var root = lg.graph().root;
+ var sorted = sortSubgraph(lg, root, cg, biasRight);
+ _.forEach(sorted.vs, function(v, i) {
+ lg.node(v).order = i;
+ });
+ addSubgraphConstraints(lg, cg, sorted.vs);
+ });
+}
+
+function assignOrder(g, layering) {
+ _.forEach(layering, function(layer) {
+ _.forEach(layer, function(v, i) {
+ g.node(v).order = i;
+ });
+ });
+}
+
+},{'../graphlib':7,'../lodash':10,'../util':29,'./add-subgraph-constraints':13,'./build-layer-graph':15,'./cross-count':16,'./init-order':18,'./sort-subgraph':20}],18:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash');
+
+module.exports = initOrder;
+
+/*
+ * Assigns an initial order value for each node by performing a DFS search
+ * starting from nodes in the first rank. Nodes are assigned an order in their
+ * rank as they are first visited.
+ *
+ * This approach comes from Gansner, et al., "A Technique for Drawing Directed
+ * Graphs."
+ *
+ * Returns a layering matrix with an array per layer and each layer sorted by
+ * the order of its nodes.
+ */
+function initOrder(g) {
+ var visited = {},
+ simpleNodes = _.filter(g.nodes(), function(v) {
+ return !g.children(v).length;
+ }),
+ maxRank = _.max(_.map(simpleNodes, function(v) { return g.node(v).rank; })),
+ layers = _.map(_.range(maxRank + 1), function() { return []; });
+
+ function dfs(v) {
+ if (_.has(visited, v)) return;
+ visited[v] = true;
+ var node = g.node(v);
+ layers[node.rank].push(v);
+ _.forEach(g.successors(v), dfs);
+ }
+
+ var orderedVs = _.sortBy(simpleNodes, function(v) { return g.node(v).rank; });
+ _.forEach(orderedVs, dfs);
+
+ return layers;
+}
+
+},{'../lodash':10}],19:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash');
+
+module.exports = resolveConflicts;
+
+/*
+ * Given a list of entries of the form {v, barycenter, weight} and a
+ * constraint graph this function will resolve any conflicts between the
+ * constraint graph and the barycenters for the entries. If the barycenters for
+ * an entry would violate a constraint in the constraint graph then we coalesce
+ * the nodes in the conflict into a new node that respects the contraint and
+ * aggregates barycenter and weight information.
+ *
+ * This implementation is based on the description in Forster, "A Fast and
+ * Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
+ * differs in some specific details.
+ *
+ * Pre-conditions:
+ *
+ * 1. Each entry has the form {v, barycenter, weight}, or if the node has
+ * no barycenter, then {v}.
+ *
+ * Returns:
+ *
+ * A new list of entries of the form {vs, i, barycenter, weight}. The list
+ * `vs` may either be a singleton or it may be an aggregation of nodes
+ * ordered such that they do not violate constraints from the constraint
+ * graph. The property `i` is the lowest original index of any of the
+ * elements in `vs`.
+ */
+function resolveConflicts(entries, cg) {
+ var mappedEntries = {};
+ _.forEach(entries, function(entry, i) {
+ var tmp = mappedEntries[entry.v] = {
+ indegree: 0,
+ 'in': [],
+ out: [],
+ vs: [entry.v],
+ i: i
+ };
+ if (!_.isUndefined(entry.barycenter)) {
+ tmp.barycenter = entry.barycenter;
+ tmp.weight = entry.weight;
+ }
+ });
+
+ _.forEach(cg.edges(), function(e) {
+ var entryV = mappedEntries[e.v],
+ entryW = mappedEntries[e.w];
+ if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
+ entryW.indegree++;
+ entryV.out.push(mappedEntries[e.w]);
+ }
+ });
+
+ var sourceSet = _.filter(mappedEntries, function(entry) {
+ return !entry.indegree;
+ });
+
+ return doResolveConflicts(sourceSet);
+}
+
+function doResolveConflicts(sourceSet) {
+ var entries = [];
+
+ function handleIn(vEntry) {
+ return function(uEntry) {
+ if (uEntry.merged) {
+ return;
+ }
+ if (_.isUndefined(uEntry.barycenter) ||
+ _.isUndefined(vEntry.barycenter) ||
+ uEntry.barycenter >= vEntry.barycenter) {
+ mergeEntries(vEntry, uEntry);
+ }
+ };
+ }
+
+ function handleOut(vEntry) {
+ return function(wEntry) {
+ wEntry['in'].push(vEntry);
+ if (--wEntry.indegree === 0) {
+ sourceSet.push(wEntry);
+ }
+ };
+ }
+
+ while (sourceSet.length) {
+ var entry = sourceSet.pop();
+ entries.push(entry);
+ _.forEach(entry['in'].reverse(), handleIn(entry));
+ _.forEach(entry.out, handleOut(entry));
+ }
+
+ return _.map(_.filter(entries, function(entry) { return !entry.merged; }),
+ function(entry) {
+ return _.pick(entry, ['vs', 'i', 'barycenter', 'weight']);
+ });
+
+}
+
+function mergeEntries(target, source) {
+ var sum = 0,
+ weight = 0;
+
+ if (target.weight) {
+ sum += target.barycenter * target.weight;
+ weight += target.weight;
+ }
+
+ if (source.weight) {
+ sum += source.barycenter * source.weight;
+ weight += source.weight;
+ }
+
+ target.vs = source.vs.concat(target.vs);
+ target.barycenter = sum / weight;
+ target.weight = weight;
+ target.i = Math.min(source.i, target.i);
+ source.merged = true;
+}
+
+},{'../lodash':10}],20:[function(require,module,exports){
+var _ = require('../lodash'),
+ barycenter = require('./barycenter'),
+ resolveConflicts = require('./resolve-conflicts'),
+ sort = require('./sort');
+
+module.exports = sortSubgraph;
+
+function sortSubgraph(g, v, cg, biasRight) {
+ var movable = g.children(v),
+ node = g.node(v),
+ bl = node ? node.borderLeft : undefined,
+ br = node ? node.borderRight: undefined,
+ subgraphs = {};
+
+ if (bl) {
+ movable = _.filter(movable, function(w) {
+ return w !== bl && w !== br;
+ });
+ }
+
+ var barycenters = barycenter(g, movable);
+ _.forEach(barycenters, function(entry) {
+ if (g.children(entry.v).length) {
+ var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
+ subgraphs[entry.v] = subgraphResult;
+ if (_.has(subgraphResult, 'barycenter')) {
+ mergeBarycenters(entry, subgraphResult);
+ }
+ }
+ });
+
+ var entries = resolveConflicts(barycenters, cg);
+ expandSubgraphs(entries, subgraphs);
+
+ var result = sort(entries, biasRight);
+
+ if (bl) {
+ result.vs = _.flatten([bl, result.vs, br], true);
+ if (g.predecessors(bl).length) {
+ var blPred = g.node(g.predecessors(bl)[0]),
+ brPred = g.node(g.predecessors(br)[0]);
+ if (!_.has(result, 'barycenter')) {
+ result.barycenter = 0;
+ result.weight = 0;
+ }
+ result.barycenter = (result.barycenter * result.weight +
+ blPred.order + brPred.order) / (result.weight + 2);
+ result.weight += 2;
+ }
+ }
+
+ return result;
+}
+
+function expandSubgraphs(entries, subgraphs) {
+ _.forEach(entries, function(entry) {
+ entry.vs = _.flatten(entry.vs.map(function(v) {
+ if (subgraphs[v]) {
+ return subgraphs[v].vs;
+ }
+ return v;
+ }), true);
+ });
+}
+
+function mergeBarycenters(target, other) {
+ if (!_.isUndefined(target.barycenter)) {
+ target.barycenter = (target.barycenter * target.weight +
+ other.barycenter * other.weight) /
+ (target.weight + other.weight);
+ target.weight += other.weight;
+ } else {
+ target.barycenter = other.barycenter;
+ target.weight = other.weight;
+ }
+}
+
+},{'../lodash':10,'./barycenter':14,'./resolve-conflicts':19,'./sort':21}],21:[function(require,module,exports){
+var _ = require('../lodash'),
+ util = require('../util');
+
+module.exports = sort;
+
+function sort(entries, biasRight) {
+ var parts = util.partition(entries, function(entry) {
+ return _.has(entry, 'barycenter');
+ });
+ var sortable = parts.lhs,
+ unsortable = _.sortBy(parts.rhs, function(entry) { return -entry.i; }),
+ vs = [],
+ sum = 0,
+ weight = 0,
+ vsIndex = 0;
+
+ sortable.sort(compareWithBias(!!biasRight));
+
+ vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
+
+ _.forEach(sortable, function (entry) {
+ vsIndex += entry.vs.length;
+ vs.push(entry.vs);
+ sum += entry.barycenter * entry.weight;
+ weight += entry.weight;
+ vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
+ });
+
+ var result = { vs: _.flatten(vs, true) };
+ if (weight) {
+ result.barycenter = sum / weight;
+ result.weight = weight;
+ }
+ return result;
+}
+
+function consumeUnsortable(vs, unsortable, index) {
+ var last;
+ while (unsortable.length && (last = _.last(unsortable)).i <= index) {
+ unsortable.pop();
+ vs.push(last.vs);
+ index++;
+ }
+ return index;
+}
+
+function compareWithBias(bias) {
+ return function(entryV, entryW) {
+ if (entryV.barycenter < entryW.barycenter) {
+ return -1;
+ } else if (entryV.barycenter > entryW.barycenter) {
+ return 1;
+ }
+
+ return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
+ };
+}
+
+},{'../lodash':10,'../util':29}],22:[function(require,module,exports){
+var _ = require('./lodash');
+
+module.exports = parentDummyChains;
+
+function parentDummyChains(g) {
+ var postorderNums = postorder(g);
+
+ _.forEach(g.graph().dummyChains, function(v) {
+ var node = g.node(v),
+ edgeObj = node.edgeObj,
+ pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w),
+ path = pathData.path,
+ lca = pathData.lca,
+ pathIdx = 0,
+ pathV = path[pathIdx],
+ ascending = true;
+
+ while (v !== edgeObj.w) {
+ node = g.node(v);
+
+ if (ascending) {
+ while ((pathV = path[pathIdx]) !== lca &&
+ g.node(pathV).maxRank < node.rank) {
+ pathIdx++;
+ }
+
+ if (pathV === lca) {
+ ascending = false;
+ }
+ }
+
+ if (!ascending) {
+ while (pathIdx < path.length - 1 &&
+ g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
+ pathIdx++;
+ }
+ pathV = path[pathIdx];
+ }
+
+ g.setParent(v, pathV);
+ v = g.successors(v)[0];
+ }
+ });
+}
+
+// Find a path from v to w through the lowest common ancestor (LCA). Return the
+// full path and the LCA.
+function findPath(g, postorderNums, v, w) {
+ var vPath = [],
+ wPath = [],
+ low = Math.min(postorderNums[v].low, postorderNums[w].low),
+ lim = Math.max(postorderNums[v].lim, postorderNums[w].lim),
+ parent,
+ lca;
+
+ // Traverse up from v to find the LCA
+ parent = v;
+ do {
+ parent = g.parent(parent);
+ vPath.push(parent);
+ } while (parent &&
+ (postorderNums[parent].low > low || lim > postorderNums[parent].lim));
+ lca = parent;
+
+ // Traverse from w to LCA
+ parent = w;
+ while ((parent = g.parent(parent)) !== lca) {
+ wPath.push(parent);
+ }
+
+ return { path: vPath.concat(wPath.reverse()), lca: lca };
+}
+
+function postorder(g) {
+ var result = {},
+ lim = 0;
+
+ function dfs(v) {
+ var low = lim;
+ _.forEach(g.children(v), dfs);
+ result[v] = { low: low, lim: lim++ };
+ }
+ _.forEach(g.children(), dfs);
+
+ return result;
+}
+
+},{'./lodash':10}],23:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash'),
+ Graph = require('../graphlib').Graph,
+ util = require('../util');
+
+/*
+ * This module provides coordinate assignment based on Brandes and Köpf, "Fast
+ * and Simple Horizontal Coordinate Assignment."
+ */
+
+module.exports = {
+ positionX: positionX,
+ findType1Conflicts: findType1Conflicts,
+ findType2Conflicts: findType2Conflicts,
+ addConflict: addConflict,
+ hasConflict: hasConflict,
+ verticalAlignment: verticalAlignment,
+ horizontalCompaction: horizontalCompaction,
+ alignCoordinates: alignCoordinates,
+ findSmallestWidthAlignment: findSmallestWidthAlignment,
+ balance: balance
+};
+
+/*
+ * Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
+ * property. A type-1 conflict is one where a non-inner segment crosses an
+ * inner segment. An inner segment is an edge with both incident nodes marked
+ * with the "dummy" property.
+ *
+ * This algorithm scans layer by layer, starting with the second, for type-1
+ * conflicts between the current layer and the previous layer. For each layer
+ * it scans the nodes from left to right until it reaches one that is incident
+ * on an inner segment. It then scans predecessors to determine if they have
+ * edges that cross that inner segment. At the end a final scan is done for all
+ * nodes on the current rank to see if they cross the last visited inner
+ * segment.
+ *
+ * This algorithm (safely) assumes that a dummy node will only be incident on a
+ * single node in the layers being scanned.
+ */
+function findType1Conflicts(g, layering) {
+ var conflicts = {};
+
+ function visitLayer(prevLayer, layer) {
+ var
+ // last visited node in the previous layer that is incident on an inner
+ // segment.
+ k0 = 0,
+ // Tracks the last node in this layer scanned for crossings with a type-1
+ // segment.
+ scanPos = 0,
+ prevLayerLength = prevLayer.length,
+ lastNode = _.last(layer);
+
+ _.forEach(layer, function(v, i) {
+ var w = findOtherInnerSegmentNode(g, v),
+ k1 = w ? g.node(w).order : prevLayerLength;
+
+ if (w || v === lastNode) {
+ _.forEach(layer.slice(scanPos, i +1), function(scanNode) {
+ _.forEach(g.predecessors(scanNode), function(u) {
+ var uLabel = g.node(u),
+ uPos = uLabel.order;
+ if ((uPos < k0 || k1 < uPos) &&
+ !(uLabel.dummy && g.node(scanNode).dummy)) {
+ addConflict(conflicts, u, scanNode);
+ }
+ });
+ });
+ scanPos = i + 1;
+ k0 = k1;
+ }
+ });
+
+ return layer;
+ }
+
+ _.reduce(layering, visitLayer);
+ return conflicts;
+}
+
+function findType2Conflicts(g, layering) {
+ var conflicts = {};
+
+ function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
+ var v;
+ _.forEach(_.range(southPos, southEnd), function(i) {
+ v = south[i];
+ if (g.node(v).dummy) {
+ _.forEach(g.predecessors(v), function(u) {
+ var uNode = g.node(u);
+ if (uNode.dummy &&
+ (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
+ addConflict(conflicts, u, v);
+ }
+ });
+ }
+ });
+ }
+
+
+ function visitLayer(north, south) {
+ var prevNorthPos = -1,
+ nextNorthPos,
+ southPos = 0;
+
+ _.forEach(south, function(v, southLookahead) {
+ if (g.node(v).dummy === 'border') {
+ var predecessors = g.predecessors(v);
+ if (predecessors.length) {
+ nextNorthPos = g.node(predecessors[0]).order;
+ scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
+ southPos = southLookahead;
+ prevNorthPos = nextNorthPos;
+ }
+ }
+ scan(south, southPos, south.length, nextNorthPos, north.length);
+ });
+
+ return south;
+ }
+
+ _.reduce(layering, visitLayer);
+ return conflicts;
+}
+
+function findOtherInnerSegmentNode(g, v) {
+ if (g.node(v).dummy) {
+ return _.find(g.predecessors(v), function(u) {
+ return g.node(u).dummy;
+ });
+ }
+}
+
+function addConflict(conflicts, v, w) {
+ if (v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+
+ var conflictsV = conflicts[v];
+ if (!conflictsV) {
+ conflicts[v] = conflictsV = {};
+ }
+ conflictsV[w] = true;
+}
+
+function hasConflict(conflicts, v, w) {
+ if (v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ return _.has(conflicts[v], w);
+}
+
+/*
+ * Try to align nodes into vertical "blocks" where possible. This algorithm
+ * attempts to align a node with one of its median neighbors. If the edge
+ * connecting a neighbor is a type-1 conflict then we ignore that possibility.
+ * If a previous node has already formed a block with a node after the node
+ * we're trying to form a block with, we also ignore that possibility - our
+ * blocks would be split in that scenario.
+ */
+function verticalAlignment(g, layering, conflicts, neighborFn) {
+ var root = {},
+ align = {},
+ pos = {};
+
+ // We cache the position here based on the layering because the graph and
+ // layering may be out of sync. The layering matrix is manipulated to
+ // generate different extreme alignments.
+ _.forEach(layering, function(layer) {
+ _.forEach(layer, function(v, order) {
+ root[v] = v;
+ align[v] = v;
+ pos[v] = order;
+ });
+ });
+
+ _.forEach(layering, function(layer) {
+ var prevIdx = -1;
+ _.forEach(layer, function(v) {
+ var ws = neighborFn(v);
+ if (ws.length) {
+ ws = _.sortBy(ws, function(w) { return pos[w]; });
+ var mp = (ws.length - 1) / 2;
+ for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
+ var w = ws[i];
+ if (align[v] === v &&
+ prevIdx < pos[w] &&
+ !hasConflict(conflicts, v, w)) {
+ align[w] = v;
+ align[v] = root[v] = root[w];
+ prevIdx = pos[w];
+ }
+ }
+ }
+ });
+ });
+
+ return { root: root, align: align };
+}
+
+function horizontalCompaction(g, layering, root, align, reverseSep) {
+ // This portion of the algorithm differs from BK due to a number of problems.
+ // Instead of their algorithm we construct a new block graph and do two
+ // sweeps. The first sweep places blocks with the smallest possible
+ // coordinates. The second sweep removes unused space by moving blocks to the
+ // greatest coordinates without violating separation.
+ var xs = {},
+ blockG = buildBlockGraph(g, layering, root, reverseSep),
+ borderType = reverseSep ? 'borderLeft' : 'borderRight';
+
+ function iterate(setXsFunc, nextNodesFunc) {
+ var stack = blockG.nodes();
+ var elem = stack.pop();
+ var visited = {};
+ while (elem) {
+ if (visited[elem]) {
+ setXsFunc(elem);
+ } else {
+ visited[elem] = true;
+ stack.push(elem);
+ stack = stack.concat(nextNodesFunc(elem));
+ }
+
+ elem = stack.pop();
+ }
+ }
+
+ // First pass, assign smallest coordinates
+ function pass1(elem) {
+ xs[elem] = blockG.inEdges(elem).reduce(function(acc, e) {
+ return Math.max(acc, xs[e.v] + blockG.edge(e));
+ }, 0);
+ }
+
+ // Second pass, assign greatest coordinates
+ function pass2(elem) {
+ var min = blockG.outEdges(elem).reduce(function(acc, e) {
+ return Math.min(acc, xs[e.w] - blockG.edge(e));
+ }, Number.POSITIVE_INFINITY);
+
+ var node = g.node(elem);
+ if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
+ xs[elem] = Math.max(xs[elem], min);
+ }
+ }
+
+ iterate(pass1, blockG.predecessors.bind(blockG));
+ iterate(pass2, blockG.successors.bind(blockG));
+
+ // Assign x coordinates to all nodes
+ _.forEach(align, function(v) {
+ xs[v] = xs[root[v]];
+ });
+
+ return xs;
+}
+
+
+function buildBlockGraph(g, layering, root, reverseSep) {
+ var blockGraph = new Graph(),
+ graphLabel = g.graph(),
+ sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
+
+ _.forEach(layering, function(layer) {
+ var u;
+ _.forEach(layer, function(v) {
+ var vRoot = root[v];
+ blockGraph.setNode(vRoot);
+ if (u) {
+ var uRoot = root[u],
+ prevMax = blockGraph.edge(uRoot, vRoot);
+ blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
+ }
+ u = v;
+ });
+ });
+
+ return blockGraph;
+}
+
+/*
+ * Returns the alignment that has the smallest width of the given alignments.
+ */
+function findSmallestWidthAlignment(g, xss) {
+ return _.minBy(_.values(xss), function (xs) {
+ var max = Number.NEGATIVE_INFINITY;
+ var min = Number.POSITIVE_INFINITY;
+
+ _.forIn(xs, function (x, v) {
+ var halfWidth = width(g, v) / 2;
+
+ max = Math.max(x + halfWidth, max);
+ min = Math.min(x - halfWidth, min);
+ });
+
+ return max - min;
+ });
+}
+
+/*
+ * Align the coordinates of each of the layout alignments such that
+ * left-biased alignments have their minimum coordinate at the same point as
+ * the minimum coordinate of the smallest width alignment and right-biased
+ * alignments have their maximum coordinate at the same point as the maximum
+ * coordinate of the smallest width alignment.
+ */
+function alignCoordinates(xss, alignTo) {
+ var alignToVals = _.values(alignTo),
+ alignToMin = _.min(alignToVals),
+ alignToMax = _.max(alignToVals);
+
+ _.forEach(['u', 'd'], function(vert) {
+ _.forEach(['l', 'r'], function(horiz) {
+ var alignment = vert + horiz,
+ xs = xss[alignment],
+ delta;
+ if (xs === alignTo) return;
+
+ var xsVals = _.values(xs);
+ delta = horiz === 'l' ? alignToMin - _.min(xsVals) : alignToMax - _.max(xsVals);
+
+ if (delta) {
+ xss[alignment] = _.mapValues(xs, function(x) { return x + delta; });
+ }
+ });
+ });
+}
+
+function balance(xss, align) {
+ return _.mapValues(xss.ul, function(ignore, v) {
+ if (align) {
+ return xss[align.toLowerCase()][v];
+ } else {
+ var xs = _.sortBy(_.map(xss, v));
+ return (xs[1] + xs[2]) / 2;
+ }
+ });
+}
+
+function positionX(g) {
+ var layering = util.buildLayerMatrix(g),
+ conflicts = _.merge(findType1Conflicts(g, layering),
+ findType2Conflicts(g, layering));
+
+ var xss = {},
+ adjustedLayering;
+ _.forEach(['u', 'd'], function(vert) {
+ adjustedLayering = vert === 'u' ? layering : _.values(layering).reverse();
+ _.forEach(['l', 'r'], function(horiz) {
+ if (horiz === 'r') {
+ adjustedLayering = _.map(adjustedLayering, function(inner) {
+ return _.values(inner).reverse();
+ });
+ }
+
+ var neighborFn = (vert === 'u' ? g.predecessors : g.successors).bind(g);
+ var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
+ var xs = horizontalCompaction(g, adjustedLayering,
+ align.root, align.align,
+ horiz === 'r');
+ if (horiz === 'r') {
+ xs = _.mapValues(xs, function(x) { return -x; });
+ }
+ xss[vert + horiz] = xs;
+ });
+ });
+
+ var smallestWidth = findSmallestWidthAlignment(g, xss);
+ alignCoordinates(xss, smallestWidth);
+ return balance(xss, g.graph().align);
+}
+
+function sep(nodeSep, edgeSep, reverseSep) {
+ return function(g, v, w) {
+ var vLabel = g.node(v),
+ wLabel = g.node(w),
+ sum = 0,
+ delta;
+
+ sum += vLabel.width / 2;
+ if (_.has(vLabel, 'labelpos')) {
+ switch (vLabel.labelpos.toLowerCase()) {
+ case 'l': delta = -vLabel.width / 2; break;
+ case 'r': delta = vLabel.width / 2; break;
+ }
+ }
+ if (delta) {
+ sum += reverseSep ? delta : -delta;
+ }
+ delta = 0;
+
+ sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
+ sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
+
+ sum += wLabel.width / 2;
+ if (_.has(wLabel, 'labelpos')) {
+ switch (wLabel.labelpos.toLowerCase()) {
+ case 'l': delta = wLabel.width / 2; break;
+ case 'r': delta = -wLabel.width / 2; break;
+ }
+ }
+ if (delta) {
+ sum += reverseSep ? delta : -delta;
+ }
+ delta = 0;
+
+ return sum;
+ };
+}
+
+function width(g, v) {
+ return g.node(v).width;
+}
+
+},{'../graphlib':7,'../lodash':10,'../util':29}],24:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash'),
+ util = require('../util'),
+ positionX = require('./bk').positionX;
+
+module.exports = position;
+
+function position(g) {
+ g = util.asNonCompoundGraph(g);
+
+ positionY(g);
+ _.forEach(positionX(g), function(x, v) {
+ g.node(v).x = x;
+ });
+}
+
+function positionY(g) {
+ var layering = util.buildLayerMatrix(g),
+ rankSep = g.graph().ranksep,
+ prevY = 0;
+ _.forEach(layering, function(layer) {
+ var maxHeight = _.max(_.map(layer, function(v) { return g.node(v).height; }));
+ _.forEach(layer, function(v) {
+ g.node(v).y = prevY + maxHeight / 2;
+ });
+ prevY += maxHeight + rankSep;
+ });
+}
+
+
+},{'../lodash':10,'../util':29,'./bk':23}],25:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash'),
+ Graph = require('../graphlib').Graph,
+ slack = require('./util').slack;
+
+module.exports = feasibleTree;
+
+/*
+ * Constructs a spanning tree with tight edges and adjusted the input node's
+ * ranks to achieve this. A tight edge is one that is has a length that matches
+ * its "minlen" attribute.
+ *
+ * The basic structure for this function is derived from Gansner, et al., "A
+ * Technique for Drawing Directed Graphs."
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be a DAG.
+ * 2. Graph must be connected.
+ * 3. Graph must have at least one node.
+ * 5. Graph nodes must have been previously assigned a "rank" property that
+ * respects the "minlen" property of incident edges.
+ * 6. Graph edges must have a "minlen" property.
+ *
+ * Post-conditions:
+ *
+ * - Graph nodes will have their rank adjusted to ensure that all edges are
+ * tight.
+ *
+ * Returns a tree (undirected graph) that is constructed using only "tight"
+ * edges.
+ */
+function feasibleTree(g) {
+ var t = new Graph({ directed: false });
+
+ // Choose arbitrary node from which to start our tree
+ var start = g.nodes()[0],
+ size = g.nodeCount();
+ t.setNode(start, {});
+
+ var edge, delta;
+ while (tightTree(t, g) < size) {
+ edge = findMinSlackEdge(t, g);
+ delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
+ shiftRanks(t, g, delta);
+ }
+
+ return t;
+}
+
+/*
+ * Finds a maximal tree of tight edges and returns the number of nodes in the
+ * tree.
+ */
+function tightTree(t, g) {
+ function dfs(v) {
+ _.forEach(g.nodeEdges(v), function(e) {
+ var edgeV = e.v,
+ w = (v === edgeV) ? e.w : edgeV;
+ if (!t.hasNode(w) && !slack(g, e)) {
+ t.setNode(w, {});
+ t.setEdge(v, w, {});
+ dfs(w);
+ }
+ });
+ }
+
+ _.forEach(t.nodes(), dfs);
+ return t.nodeCount();
+}
+
+/*
+ * Finds the edge with the smallest slack that is incident on tree and returns
+ * it.
+ */
+function findMinSlackEdge(t, g) {
+ return _.minBy(g.edges(), function(e) {
+ if (t.hasNode(e.v) !== t.hasNode(e.w)) {
+ return slack(g, e);
+ }
+ });
+}
+
+function shiftRanks(t, g, delta) {
+ _.forEach(t.nodes(), function(v) {
+ g.node(v).rank += delta;
+ });
+}
+
+},{'../graphlib':7,'../lodash':10,'./util':28}],26:[function(require,module,exports){
+'use strict';
+
+var rankUtil = require('./util'),
+ longestPath = rankUtil.longestPath,
+ feasibleTree = require('./feasible-tree'),
+ networkSimplex = require('./network-simplex');
+
+module.exports = rank;
+
+/*
+ * Assigns a rank to each node in the input graph that respects the "minlen"
+ * constraint specified on edges between nodes.
+ *
+ * This basic structure is derived from Gansner, et al., "A Technique for
+ * Drawing Directed Graphs."
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be a connected DAG
+ * 2. Graph nodes must be objects
+ * 3. Graph edges must have "weight" and "minlen" attributes
+ *
+ * Post-conditions:
+ *
+ * 1. Graph nodes will have a "rank" attribute based on the results of the
+ * algorithm. Ranks can start at any index (including negative), we'll
+ * fix them up later.
+ */
+function rank(g) {
+ switch(g.graph().ranker) {
+ case 'network-simplex': networkSimplexRanker(g); break;
+ case 'tight-tree': tightTreeRanker(g); break;
+ case 'longest-path': longestPathRanker(g); break;
+ default: networkSimplexRanker(g);
+ }
+}
+
+// A fast and simple ranker, but results are far from optimal.
+var longestPathRanker = longestPath;
+
+function tightTreeRanker(g) {
+ longestPath(g);
+ feasibleTree(g);
+}
+
+function networkSimplexRanker(g) {
+ networkSimplex(g);
+}
+
+},{'./feasible-tree':25,'./network-simplex':27,'./util':28}],27:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash'),
+ feasibleTree = require('./feasible-tree'),
+ slack = require('./util').slack,
+ initRank = require('./util').longestPath,
+ preorder = require('../graphlib').alg.preorder,
+ postorder = require('../graphlib').alg.postorder,
+ simplify = require('../util').simplify;
+
+module.exports = networkSimplex;
+
+// Expose some internals for testing purposes
+networkSimplex.initLowLimValues = initLowLimValues;
+networkSimplex.initCutValues = initCutValues;
+networkSimplex.calcCutValue = calcCutValue;
+networkSimplex.leaveEdge = leaveEdge;
+networkSimplex.enterEdge = enterEdge;
+networkSimplex.exchangeEdges = exchangeEdges;
+
+/*
+ * The network simplex algorithm assigns ranks to each node in the input graph
+ * and iteratively improves the ranking to reduce the length of edges.
+ *
+ * Preconditions:
+ *
+ * 1. The input graph must be a DAG.
+ * 2. All nodes in the graph must have an object value.
+ * 3. All edges in the graph must have "minlen" and "weight" attributes.
+ *
+ * Postconditions:
+ *
+ * 1. All nodes in the graph will have an assigned "rank" attribute that has
+ * been optimized by the network simplex algorithm. Ranks start at 0.
+ *
+ *
+ * A rough sketch of the algorithm is as follows:
+ *
+ * 1. Assign initial ranks to each node. We use the longest path algorithm,
+ * which assigns ranks to the lowest position possible. In general this
+ * leads to very wide bottom ranks and unnecessarily long edges.
+ * 2. Construct a feasible tight tree. A tight tree is one such that all
+ * edges in the tree have no slack (difference between length of edge
+ * and minlen for the edge). This by itself greatly improves the assigned
+ * rankings by shorting edges.
+ * 3. Iteratively find edges that have negative cut values. Generally a
+ * negative cut value indicates that the edge could be removed and a new
+ * tree edge could be added to produce a more compact graph.
+ *
+ * Much of the algorithms here are derived from Gansner, et al., "A Technique
+ * for Drawing Directed Graphs." The structure of the file roughly follows the
+ * structure of the overall algorithm.
+ */
+function networkSimplex(g) {
+ g = simplify(g);
+ initRank(g);
+ var t = feasibleTree(g);
+ initLowLimValues(t);
+ initCutValues(t, g);
+
+ var e, f;
+ while ((e = leaveEdge(t))) {
+ f = enterEdge(t, g, e);
+ exchangeEdges(t, g, e, f);
+ }
+}
+
+/*
+ * Initializes cut values for all edges in the tree.
+ */
+function initCutValues(t, g) {
+ var vs = postorder(t, t.nodes());
+ vs = vs.slice(0, vs.length - 1);
+ _.forEach(vs, function(v) {
+ assignCutValue(t, g, v);
+ });
+}
+
+function assignCutValue(t, g, child) {
+ var childLab = t.node(child),
+ parent = childLab.parent;
+ t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
+}
+
+/*
+ * Given the tight tree, its graph, and a child in the graph calculate and
+ * return the cut value for the edge between the child and its parent.
+ */
+function calcCutValue(t, g, child) {
+ var childLab = t.node(child),
+ parent = childLab.parent,
+ // True if the child is on the tail end of the edge in the directed graph
+ childIsTail = true,
+ // The graph's view of the tree edge we're inspecting
+ graphEdge = g.edge(child, parent),
+ // The accumulated cut value for the edge between this node and its parent
+ cutValue = 0;
+
+ if (!graphEdge) {
+ childIsTail = false;
+ graphEdge = g.edge(parent, child);
+ }
+
+ cutValue = graphEdge.weight;
+
+ _.forEach(g.nodeEdges(child), function(e) {
+ var isOutEdge = e.v === child,
+ other = isOutEdge ? e.w : e.v;
+
+ if (other !== parent) {
+ var pointsToHead = isOutEdge === childIsTail,
+ otherWeight = g.edge(e).weight;
+
+ cutValue += pointsToHead ? otherWeight : -otherWeight;
+ if (isTreeEdge(t, child, other)) {
+ var otherCutValue = t.edge(child, other).cutvalue;
+ cutValue += pointsToHead ? -otherCutValue : otherCutValue;
+ }
+ }
+ });
+
+ return cutValue;
+}
+
+function initLowLimValues(tree, root) {
+ if (arguments.length < 2) {
+ root = tree.nodes()[0];
+ }
+ dfsAssignLowLim(tree, {}, 1, root);
+}
+
+function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
+ var low = nextLim,
+ label = tree.node(v);
+
+ visited[v] = true;
+ _.forEach(tree.neighbors(v), function(w) {
+ if (!_.has(visited, w)) {
+ nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
+ }
+ });
+
+ label.low = low;
+ label.lim = nextLim++;
+ if (parent) {
+ label.parent = parent;
+ } else {
+ // TODO should be able to remove this when we incrementally update low lim
+ delete label.parent;
+ }
+
+ return nextLim;
+}
+
+function leaveEdge(tree) {
+ return _.find(tree.edges(), function(e) {
+ return tree.edge(e).cutvalue < 0;
+ });
+}
+
+function enterEdge(t, g, edge) {
+ var v = edge.v,
+ w = edge.w;
+
+ // For the rest of this function we assume that v is the tail and w is the
+ // head, so if we don't have this edge in the graph we should flip it to
+ // match the correct orientation.
+ if (!g.hasEdge(v, w)) {
+ v = edge.w;
+ w = edge.v;
+ }
+
+ var vLabel = t.node(v),
+ wLabel = t.node(w),
+ tailLabel = vLabel,
+ flip = false;
+
+ // If the root is in the tail of the edge then we need to flip the logic that
+ // checks for the head and tail nodes in the candidates function below.
+ if (vLabel.lim > wLabel.lim) {
+ tailLabel = wLabel;
+ flip = true;
+ }
+
+ var candidates = _.filter(g.edges(), function(edge) {
+ return flip === isDescendant(t, t.node(edge.v), tailLabel) &&
+ flip !== isDescendant(t, t.node(edge.w), tailLabel);
+ });
+
+ return _.minBy(candidates, function(edge) { return slack(g, edge); });
+}
+
+function exchangeEdges(t, g, e, f) {
+ var v = e.v,
+ w = e.w;
+ t.removeEdge(v, w);
+ t.setEdge(f.v, f.w, {});
+ initLowLimValues(t);
+ initCutValues(t, g);
+ updateRanks(t, g);
+}
+
+function updateRanks(t, g) {
+ var root = _.find(t.nodes(), function(v) { return !g.node(v).parent; }),
+ vs = preorder(t, root);
+ vs = vs.slice(1);
+ _.forEach(vs, function(v) {
+ var parent = t.node(v).parent,
+ edge = g.edge(v, parent),
+ flipped = false;
+
+ if (!edge) {
+ edge = g.edge(parent, v);
+ flipped = true;
+ }
+
+ g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
+ });
+}
+
+/*
+ * Returns true if the edge is in the tree.
+ */
+function isTreeEdge(tree, u, v) {
+ return tree.hasEdge(u, v);
+}
+
+/*
+ * Returns true if the specified node is descendant of the root node per the
+ * assigned low and lim attributes in the tree.
+ */
+function isDescendant(tree, vLabel, rootLabel) {
+ return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
+}
+
+},{'../graphlib':7,'../lodash':10,'../util':29,'./feasible-tree':25,'./util':28}],28:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lodash');
+
+module.exports = {
+ longestPath: longestPath,
+ slack: slack
+};
+
+/*
+ * Initializes ranks for the input graph using the longest path algorithm. This
+ * algorithm scales well and is fast in practice, it yields rather poor
+ * solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
+ * ranks wide and leaving edges longer than necessary. However, due to its
+ * speed, this algorithm is good for getting an initial ranking that can be fed
+ * into other algorithms.
+ *
+ * This algorithm does not normalize layers because it will be used by other
+ * algorithms in most cases. If using this algorithm directly, be sure to
+ * run normalize at the end.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph is a DAG.
+ * 2. Input graph node labels can be assigned properties.
+ *
+ * Post-conditions:
+ *
+ * 1. Each node will be assign an (unnormalized) "rank" property.
+ */
+function longestPath(g) {
+ var visited = {};
+
+ function dfs(v) {
+ var label = g.node(v);
+ if (_.has(visited, v)) {
+ return label.rank;
+ }
+ visited[v] = true;
+
+ var rank = _.min(_.map(g.outEdges(v), function(e) {
+ return dfs(e.w) - g.edge(e).minlen;
+ }));
+
+ if (rank === Number.POSITIVE_INFINITY || // return value of _.map([]) for Lodash 3
+ rank === undefined || // return value of _.map([]) for Lodash 4
+ rank === null) { // return value of _.map([null])
+ rank = 0;
+ }
+
+ return (label.rank = rank);
+ }
+
+ _.forEach(g.sources(), dfs);
+}
+
+/*
+ * Returns the amount of slack for the given edge. The slack is defined as the
+ * difference between the length of the edge and its minimum length.
+ */
+function slack(g, e) {
+ return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
+}
+
+},{'../lodash':10}],29:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash'),
+ Graph = require('./graphlib').Graph;
+
+module.exports = {
+ addDummyNode: addDummyNode,
+ simplify: simplify,
+ asNonCompoundGraph: asNonCompoundGraph,
+ successorWeights: successorWeights,
+ predecessorWeights: predecessorWeights,
+ intersectRect: intersectRect,
+ buildLayerMatrix: buildLayerMatrix,
+ normalizeRanks: normalizeRanks,
+ removeEmptyRanks: removeEmptyRanks,
+ addBorderNode: addBorderNode,
+ maxRank: maxRank,
+ partition: partition,
+ time: time,
+ notime: notime
+};
+
+/*
+ * Adds a dummy node to the graph and return v.
+ */
+function addDummyNode(g, type, attrs, name) {
+ var v;
+ do {
+ v = _.uniqueId(name);
+ } while (g.hasNode(v));
+
+ attrs.dummy = type;
+ g.setNode(v, attrs);
+ return v;
+}
+
+/*
+ * Returns a new graph with only simple edges. Handles aggregation of data
+ * associated with multi-edges.
+ */
+function simplify(g) {
+ var simplified = new Graph().setGraph(g.graph());
+ _.forEach(g.nodes(), function(v) { simplified.setNode(v, g.node(v)); });
+ _.forEach(g.edges(), function(e) {
+ var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 },
+ label = g.edge(e);
+ simplified.setEdge(e.v, e.w, {
+ weight: simpleLabel.weight + label.weight,
+ minlen: Math.max(simpleLabel.minlen, label.minlen)
+ });
+ });
+ return simplified;
+}
+
+function asNonCompoundGraph(g) {
+ var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
+ _.forEach(g.nodes(), function(v) {
+ if (!g.children(v).length) {
+ simplified.setNode(v, g.node(v));
+ }
+ });
+ _.forEach(g.edges(), function(e) {
+ simplified.setEdge(e, g.edge(e));
+ });
+ return simplified;
+}
+
+function successorWeights(g) {
+ var weightMap = _.map(g.nodes(), function(v) {
+ var sucs = {};
+ _.forEach(g.outEdges(v), function(e) {
+ sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
+ });
+ return sucs;
+ });
+ return _.zipObject(g.nodes(), weightMap);
+}
+
+function predecessorWeights(g) {
+ var weightMap = _.map(g.nodes(), function(v) {
+ var preds = {};
+ _.forEach(g.inEdges(v), function(e) {
+ preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
+ });
+ return preds;
+ });
+ return _.zipObject(g.nodes(), weightMap);
+}
+
+/*
+ * Finds where a line starting at point ({x, y}) would intersect a rectangle
+ * ({x, y, width, height}) if it were pointing at the rectangle's center.
+ */
+function intersectRect(rect, point) {
+ var x = rect.x;
+ var y = rect.y;
+
+ // Rectangle intersection algorithm from:
+ // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
+ var dx = point.x - x;
+ var dy = point.y - y;
+ var w = rect.width / 2;
+ var h = rect.height / 2;
+
+ if (!dx && !dy) {
+ throw new Error('Not possible to find intersection inside of the rectangle');
+ }
+
+ var sx, sy;
+ if (Math.abs(dy) * w > Math.abs(dx) * h) {
+ // Intersection is top or bottom of rect.
+ if (dy < 0) {
+ h = -h;
+ }
+ sx = h * dx / dy;
+ sy = h;
+ } else {
+ // Intersection is left or right of rect.
+ if (dx < 0) {
+ w = -w;
+ }
+ sx = w;
+ sy = w * dy / dx;
+ }
+
+ return { x: x + sx, y: y + sy };
+}
+
+/*
+ * Given a DAG with each node assigned "rank" and "order" properties, this
+ * function will produce a matrix with the ids of each node.
+ */
+function buildLayerMatrix(g) {
+ var layering = _.map(_.range(maxRank(g) + 1), function() { return []; });
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v),
+ rank = node.rank;
+ if (!_.isUndefined(rank)) {
+ layering[rank][node.order] = v;
+ }
+ });
+ return layering;
+}
+
+/*
+ * Adjusts the ranks for all nodes in the graph such that all nodes v have
+ * rank(v) >= 0 and at least one node w has rank(w) = 0.
+ */
+function normalizeRanks(g) {
+ var min = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
+ _.forEach(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (_.has(node, 'rank')) {
+ node.rank -= min;
+ }
+ });
+}
+
+function removeEmptyRanks(g) {
+ // Ranks may not start at 0, so we need to offset them
+ var offset = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
+
+ var layers = [];
+ _.forEach(g.nodes(), function(v) {
+ var rank = g.node(v).rank - offset;
+ if (!layers[rank]) {
+ layers[rank] = [];
+ }
+ layers[rank].push(v);
+ });
+
+ var delta = 0,
+ nodeRankFactor = g.graph().nodeRankFactor;
+ _.forEach(layers, function(vs, i) {
+ if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
+ --delta;
+ } else if (delta) {
+ _.forEach(vs, function(v) { g.node(v).rank += delta; });
+ }
+ });
+}
+
+function addBorderNode(g, prefix, rank, order) {
+ var node = {
+ width: 0,
+ height: 0
+ };
+ if (arguments.length >= 4) {
+ node.rank = rank;
+ node.order = order;
+ }
+ return addDummyNode(g, 'border', node, prefix);
+}
+
+function maxRank(g) {
+ return _.max(_.map(g.nodes(), function(v) {
+ var rank = g.node(v).rank;
+ if (!_.isUndefined(rank)) {
+ return rank;
+ }
+ }));
+}
+
+/*
+ * Partition a collection into two groups: `lhs` and `rhs`. If the supplied
+ * function returns true for an entry it goes into `lhs`. Otherwise it goes
+ * into `rhs.
+ */
+function partition(collection, fn) {
+ var result = { lhs: [], rhs: [] };
+ _.forEach(collection, function(value) {
+ if (fn(value)) {
+ result.lhs.push(value);
+ } else {
+ result.rhs.push(value);
+ }
+ });
+ return result;
+}
+
+/*
+ * Returns a new function that wraps `fn` with a timer. The wrapper logs the
+ * time it takes to execute the function.
+ */
+function time(name, fn) {
+ var start = _.now();
+ try {
+ return fn();
+ } finally {
+ console.log(name + ' time: ' + (_.now() - start) + 'ms');
+ }
+}
+
+function notime(name, fn) {
+ return fn();
+}
+
+},{'./graphlib':7,'./lodash':10}],30:[function(require,module,exports){
+module.exports = '0.8.4';
+
+},{}],31:[function(require,module,exports){
+/**
+ * Copyright (c) 2014, Chris Pettitt
+ * 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 the copyright holder 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 HOLDER 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.
+ */
+
+var lib = require('./lib');
+
+module.exports = {
+ Graph: lib.Graph,
+ json: require('./lib/json'),
+ alg: require('./lib/alg'),
+ version: lib.version
+};
+
+},{'./lib':47,'./lib/alg':38,'./lib/json':48}],32:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = components;
+
+function components(g) {
+ var visited = {},
+ cmpts = [],
+ cmpt;
+
+ function dfs(v) {
+ if (_.has(visited, v)) return;
+ visited[v] = true;
+ cmpt.push(v);
+ _.each(g.successors(v), dfs);
+ _.each(g.predecessors(v), dfs);
+ }
+
+ _.each(g.nodes(), function(v) {
+ cmpt = [];
+ dfs(v);
+ if (cmpt.length) {
+ cmpts.push(cmpt);
+ }
+ });
+
+ return cmpts;
+}
+
+},{'../lodash':49}],33:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = dfs;
+
+/*
+ * A helper that preforms a pre- or post-order traversal on the input graph
+ * and returns the nodes in the order they were visited. If the graph is
+ * undirected then this algorithm will navigate using neighbors. If the graph
+ * is directed then this algorithm will navigate using successors.
+ *
+ * Order must be one of "pre" or "post".
+ */
+function dfs(g, vs, order) {
+ if (!_.isArray(vs)) {
+ vs = [vs];
+ }
+
+ var navigation = (g.isDirected() ? g.successors : g.neighbors).bind(g);
+
+ var acc = [],
+ visited = {};
+ _.each(vs, function(v) {
+ if (!g.hasNode(v)) {
+ throw new Error('Graph does not have node: ' + v);
+ }
+
+ doDfs(g, v, order === 'post', visited, navigation, acc);
+ });
+ return acc;
+}
+
+function doDfs(g, v, postorder, visited, navigation, acc) {
+ if (!_.has(visited, v)) {
+ visited[v] = true;
+
+ if (!postorder) { acc.push(v); }
+ _.each(navigation(v), function(w) {
+ doDfs(g, w, postorder, visited, navigation, acc);
+ });
+ if (postorder) { acc.push(v); }
+ }
+}
+
+},{'../lodash':49}],34:[function(require,module,exports){
+var dijkstra = require('./dijkstra'),
+ _ = require('../lodash');
+
+module.exports = dijkstraAll;
+
+function dijkstraAll(g, weightFunc, edgeFunc) {
+ return _.transform(g.nodes(), function(acc, v) {
+ acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
+ }, {});
+}
+
+},{'../lodash':49,'./dijkstra':35}],35:[function(require,module,exports){
+var _ = require('../lodash'),
+ PriorityQueue = require('../data/priority-queue');
+
+module.exports = dijkstra;
+
+var DEFAULT_WEIGHT_FUNC = _.constant(1);
+
+function dijkstra(g, source, weightFn, edgeFn) {
+ return runDijkstra(g, String(source),
+ weightFn || DEFAULT_WEIGHT_FUNC,
+ edgeFn || function(v) { return g.outEdges(v); });
+}
+
+function runDijkstra(g, source, weightFn, edgeFn) {
+ var results = {},
+ pq = new PriorityQueue(),
+ v, vEntry;
+
+ var updateNeighbors = function(edge) {
+ var w = edge.v !== v ? edge.v : edge.w,
+ wEntry = results[w],
+ weight = weightFn(edge),
+ distance = vEntry.distance + weight;
+
+ if (weight < 0) {
+ throw new Error('dijkstra does not allow negative edge weights. ' +
+ 'Bad edge: ' + edge + ' Weight: ' + weight);
+ }
+
+ if (distance < wEntry.distance) {
+ wEntry.distance = distance;
+ wEntry.predecessor = v;
+ pq.decrease(w, distance);
+ }
+ };
+
+ g.nodes().forEach(function(v) {
+ var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
+ results[v] = { distance: distance };
+ pq.add(v, distance);
+ });
+
+ while (pq.size() > 0) {
+ v = pq.removeMin();
+ vEntry = results[v];
+ if (vEntry.distance === Number.POSITIVE_INFINITY) {
+ break;
+ }
+
+ edgeFn(v).forEach(updateNeighbors);
+ }
+
+ return results;
+}
+
+},{'../data/priority-queue':45,'../lodash':49}],36:[function(require,module,exports){
+var _ = require('../lodash'),
+ tarjan = require('./tarjan');
+
+module.exports = findCycles;
+
+function findCycles(g) {
+ return _.filter(tarjan(g), function(cmpt) {
+ return cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0]));
+ });
+}
+
+},{'../lodash':49,'./tarjan':43}],37:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = floydWarshall;
+
+var DEFAULT_WEIGHT_FUNC = _.constant(1);
+
+function floydWarshall(g, weightFn, edgeFn) {
+ return runFloydWarshall(g,
+ weightFn || DEFAULT_WEIGHT_FUNC,
+ edgeFn || function(v) { return g.outEdges(v); });
+}
+
+function runFloydWarshall(g, weightFn, edgeFn) {
+ var results = {},
+ nodes = g.nodes();
+
+ nodes.forEach(function(v) {
+ results[v] = {};
+ results[v][v] = { distance: 0 };
+ nodes.forEach(function(w) {
+ if (v !== w) {
+ results[v][w] = { distance: Number.POSITIVE_INFINITY };
+ }
+ });
+ edgeFn(v).forEach(function(edge) {
+ var w = edge.v === v ? edge.w : edge.v,
+ d = weightFn(edge);
+ results[v][w] = { distance: d, predecessor: v };
+ });
+ });
+
+ nodes.forEach(function(k) {
+ var rowK = results[k];
+ nodes.forEach(function(i) {
+ var rowI = results[i];
+ nodes.forEach(function(j) {
+ var ik = rowI[k];
+ var kj = rowK[j];
+ var ij = rowI[j];
+ var altDistance = ik.distance + kj.distance;
+ if (altDistance < ij.distance) {
+ ij.distance = altDistance;
+ ij.predecessor = kj.predecessor;
+ }
+ });
+ });
+ });
+
+ return results;
+}
+
+},{'../lodash':49}],38:[function(require,module,exports){
+module.exports = {
+ components: require('./components'),
+ dijkstra: require('./dijkstra'),
+ dijkstraAll: require('./dijkstra-all'),
+ findCycles: require('./find-cycles'),
+ floydWarshall: require('./floyd-warshall'),
+ isAcyclic: require('./is-acyclic'),
+ postorder: require('./postorder'),
+ preorder: require('./preorder'),
+ prim: require('./prim'),
+ tarjan: require('./tarjan'),
+ topsort: require('./topsort')
+};
+
+},{'./components':32,'./dijkstra':35,'./dijkstra-all':34,'./find-cycles':36,'./floyd-warshall':37,'./is-acyclic':39,'./postorder':40,'./preorder':41,'./prim':42,'./tarjan':43,'./topsort':44}],39:[function(require,module,exports){
+var topsort = require('./topsort');
+
+module.exports = isAcyclic;
+
+function isAcyclic(g) {
+ try {
+ topsort(g);
+ } catch (e) {
+ if (e instanceof topsort.CycleException) {
+ return false;
+ }
+ throw e;
+ }
+ return true;
+}
+
+},{'./topsort':44}],40:[function(require,module,exports){
+var dfs = require('./dfs');
+
+module.exports = postorder;
+
+function postorder(g, vs) {
+ return dfs(g, vs, 'post');
+}
+
+},{'./dfs':33}],41:[function(require,module,exports){
+var dfs = require('./dfs');
+
+module.exports = preorder;
+
+function preorder(g, vs) {
+ return dfs(g, vs, 'pre');
+}
+
+},{'./dfs':33}],42:[function(require,module,exports){
+var _ = require('../lodash'),
+ Graph = require('../graph'),
+ PriorityQueue = require('../data/priority-queue');
+
+module.exports = prim;
+
+function prim(g, weightFunc) {
+ var result = new Graph(),
+ parents = {},
+ pq = new PriorityQueue(),
+ v;
+
+ function updateNeighbors(edge) {
+ var w = edge.v === v ? edge.w : edge.v,
+ pri = pq.priority(w);
+ if (pri !== undefined) {
+ var edgeWeight = weightFunc(edge);
+ if (edgeWeight < pri) {
+ parents[w] = v;
+ pq.decrease(w, edgeWeight);
+ }
+ }
+ }
+
+ if (g.nodeCount() === 0) {
+ return result;
+ }
+
+ _.each(g.nodes(), function(v) {
+ pq.add(v, Number.POSITIVE_INFINITY);
+ result.setNode(v);
+ });
+
+ // Start from an arbitrary node
+ pq.decrease(g.nodes()[0], 0);
+
+ var init = false;
+ while (pq.size() > 0) {
+ v = pq.removeMin();
+ if (_.has(parents, v)) {
+ result.setEdge(v, parents[v]);
+ } else if (init) {
+ throw new Error('Input graph is not connected: ' + g);
+ } else {
+ init = true;
+ }
+
+ g.nodeEdges(v).forEach(updateNeighbors);
+ }
+
+ return result;
+}
+
+},{'../data/priority-queue':45,'../graph':46,'../lodash':49}],43:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = tarjan;
+
+function tarjan(g) {
+ var index = 0,
+ stack = [],
+ visited = {}, // node id -> { onStack, lowlink, index }
+ results = [];
+
+ function dfs(v) {
+ var entry = visited[v] = {
+ onStack: true,
+ lowlink: index,
+ index: index++
+ };
+ stack.push(v);
+
+ g.successors(v).forEach(function(w) {
+ if (!_.has(visited, w)) {
+ dfs(w);
+ entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
+ } else if (visited[w].onStack) {
+ entry.lowlink = Math.min(entry.lowlink, visited[w].index);
+ }
+ });
+
+ if (entry.lowlink === entry.index) {
+ var cmpt = [],
+ w;
+ do {
+ w = stack.pop();
+ visited[w].onStack = false;
+ cmpt.push(w);
+ } while (v !== w);
+ results.push(cmpt);
+ }
+ }
+
+ g.nodes().forEach(function(v) {
+ if (!_.has(visited, v)) {
+ dfs(v);
+ }
+ });
+
+ return results;
+}
+
+},{'../lodash':49}],44:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = topsort;
+topsort.CycleException = CycleException;
+
+function topsort(g) {
+ var visited = {},
+ stack = {},
+ results = [];
+
+ function visit(node) {
+ if (_.has(stack, node)) {
+ throw new CycleException();
+ }
+
+ if (!_.has(visited, node)) {
+ stack[node] = true;
+ visited[node] = true;
+ _.each(g.predecessors(node), visit);
+ delete stack[node];
+ results.push(node);
+ }
+ }
+
+ _.each(g.sinks(), visit);
+
+ if (_.size(visited) !== g.nodeCount()) {
+ throw new CycleException();
+ }
+
+ return results;
+}
+
+function CycleException() {}
+CycleException.prototype = new Error(); // must be an instance of Error to pass testing
+},{'../lodash':49}],45:[function(require,module,exports){
+var _ = require('../lodash');
+
+module.exports = PriorityQueue;
+
+/**
+ * A min-priority queue data structure. This algorithm is derived from Cormen,
+ * et al., "Introduction to Algorithms". The basic idea of a min-priority
+ * queue is that you can efficiently (in O(1) time) get the smallest key in
+ * the queue. Adding and removing elements takes O(log n) time. A key can
+ * have its priority decreased in O(log n) time.
+ */
+function PriorityQueue() {
+ this._arr = [];
+ this._keyIndices = {};
+}
+
+/**
+ * Returns the number of elements in the queue. Takes `O(1)` time.
+ */
+PriorityQueue.prototype.size = function() {
+ return this._arr.length;
+};
+
+/**
+ * Returns the keys that are in the queue. Takes `O(n)` time.
+ */
+PriorityQueue.prototype.keys = function() {
+ return this._arr.map(function(x) { return x.key; });
+};
+
+/**
+ * Returns `true` if **key** is in the queue and `false` if not.
+ */
+PriorityQueue.prototype.has = function(key) {
+ return _.has(this._keyIndices, key);
+};
+
+/**
+ * Returns the priority for **key**. If **key** is not present in the queue
+ * then this function returns `undefined`. Takes `O(1)` time.
+ *
+ * @param {Object} key
+ */
+PriorityQueue.prototype.priority = function(key) {
+ var index = this._keyIndices[key];
+ if (index !== undefined) {
+ return this._arr[index].priority;
+ }
+};
+
+/**
+ * Returns the key for the minimum element in this queue. If the queue is
+ * empty this function throws an Error. Takes `O(1)` time.
+ */
+PriorityQueue.prototype.min = function() {
+ if (this.size() === 0) {
+ throw new Error('Queue underflow');
+ }
+ return this._arr[0].key;
+};
+
+/**
+ * Inserts a new key into the priority queue. If the key already exists in
+ * the queue this function returns `false`; otherwise it will return `true`.
+ * Takes `O(n)` time.
+ *
+ * @param {Object} key the key to add
+ * @param {Number} priority the initial priority for the key
+ */
+PriorityQueue.prototype.add = function(key, priority) {
+ var keyIndices = this._keyIndices;
+ key = String(key);
+ if (!_.has(keyIndices, key)) {
+ var arr = this._arr;
+ var index = arr.length;
+ keyIndices[key] = index;
+ arr.push({key: key, priority: priority});
+ this._decrease(index);
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Removes and returns the smallest key in the queue. Takes `O(log n)` time.
+ */
+PriorityQueue.prototype.removeMin = function() {
+ this._swap(0, this._arr.length - 1);
+ var min = this._arr.pop();
+ delete this._keyIndices[min.key];
+ this._heapify(0);
+ return min.key;
+};
+
+/**
+ * Decreases the priority for **key** to **priority**. If the new priority is
+ * greater than the previous priority, this function will throw an Error.
+ *
+ * @param {Object} key the key for which to raise priority
+ * @param {Number} priority the new priority for the key
+ */
+PriorityQueue.prototype.decrease = function(key, priority) {
+ var index = this._keyIndices[key];
+ if (priority > this._arr[index].priority) {
+ throw new Error('New priority is greater than current priority. ' +
+ 'Key: ' + key + ' Old: ' + this._arr[index].priority + ' New: ' + priority);
+ }
+ this._arr[index].priority = priority;
+ this._decrease(index);
+};
+
+PriorityQueue.prototype._heapify = function(i) {
+ var arr = this._arr;
+ var l = 2 * i,
+ r = l + 1,
+ largest = i;
+ if (l < arr.length) {
+ largest = arr[l].priority < arr[largest].priority ? l : largest;
+ if (r < arr.length) {
+ largest = arr[r].priority < arr[largest].priority ? r : largest;
+ }
+ if (largest !== i) {
+ this._swap(i, largest);
+ this._heapify(largest);
+ }
+ }
+};
+
+PriorityQueue.prototype._decrease = function(index) {
+ var arr = this._arr;
+ var priority = arr[index].priority;
+ var parent;
+ while (index !== 0) {
+ parent = index >> 1;
+ if (arr[parent].priority < priority) {
+ break;
+ }
+ this._swap(index, parent);
+ index = parent;
+ }
+};
+
+PriorityQueue.prototype._swap = function(i, j) {
+ var arr = this._arr;
+ var keyIndices = this._keyIndices;
+ var origArrI = arr[i];
+ var origArrJ = arr[j];
+ arr[i] = origArrJ;
+ arr[j] = origArrI;
+ keyIndices[origArrJ.key] = i;
+ keyIndices[origArrI.key] = j;
+};
+
+},{'../lodash':49}],46:[function(require,module,exports){
+'use strict';
+
+var _ = require('./lodash');
+
+module.exports = Graph;
+
+var DEFAULT_EDGE_NAME = '\x00',
+ GRAPH_NODE = '\x00',
+ EDGE_KEY_DELIM = '\x01';
+
+// Implementation notes:
+//
+// * Node id query functions should return string ids for the nodes
+// * Edge id query functions should return an "edgeObj", edge object, that is
+// composed of enough information to uniquely identify an edge: {v, w, name}.
+// * Internally we use an "edgeId", a stringified form of the edgeObj, to
+// reference edges. This is because we need a performant way to look these
+// edges up and, object properties, which have string keys, are the closest
+// we're going to get to a performant hashtable in JavaScript.
+
+function Graph(opts) {
+ this._isDirected = _.has(opts, 'directed') ? opts.directed : true;
+ this._isMultigraph = _.has(opts, 'multigraph') ? opts.multigraph : false;
+ this._isCompound = _.has(opts, 'compound') ? opts.compound : false;
+
+ // Label for the graph itself
+ this._label = undefined;
+
+ // Defaults to be set when creating a new node
+ this._defaultNodeLabelFn = _.constant(undefined);
+
+ // Defaults to be set when creating a new edge
+ this._defaultEdgeLabelFn = _.constant(undefined);
+
+ // v -> label
+ this._nodes = {};
+
+ if (this._isCompound) {
+ // v -> parent
+ this._parent = {};
+
+ // v -> children
+ this._children = {};
+ this._children[GRAPH_NODE] = {};
+ }
+
+ // v -> edgeObj
+ this._in = {};
+
+ // u -> v -> Number
+ this._preds = {};
+
+ // v -> edgeObj
+ this._out = {};
+
+ // v -> w -> Number
+ this._sucs = {};
+
+ // e -> edgeObj
+ this._edgeObjs = {};
+
+ // e -> label
+ this._edgeLabels = {};
+}
+
+/* Number of nodes in the graph. Should only be changed by the implementation. */
+Graph.prototype._nodeCount = 0;
+
+/* Number of edges in the graph. Should only be changed by the implementation. */
+Graph.prototype._edgeCount = 0;
+
+
+/* === Graph functions ========= */
+
+Graph.prototype.isDirected = function() {
+ return this._isDirected;
+};
+
+Graph.prototype.isMultigraph = function() {
+ return this._isMultigraph;
+};
+
+Graph.prototype.isCompound = function() {
+ return this._isCompound;
+};
+
+Graph.prototype.setGraph = function(label) {
+ this._label = label;
+ return this;
+};
+
+Graph.prototype.graph = function() {
+ return this._label;
+};
+
+
+/* === Node functions ========== */
+
+Graph.prototype.setDefaultNodeLabel = function(newDefault) {
+ if (!_.isFunction(newDefault)) {
+ newDefault = _.constant(newDefault);
+ }
+ this._defaultNodeLabelFn = newDefault;
+ return this;
+};
+
+Graph.prototype.nodeCount = function() {
+ return this._nodeCount;
+};
+
+Graph.prototype.nodes = function() {
+ return _.keys(this._nodes);
+};
+
+Graph.prototype.sources = function() {
+ var self = this;
+ return _.filter(this.nodes(), function(v) {
+ return _.isEmpty(self._in[v]);
+ });
+};
+
+Graph.prototype.sinks = function() {
+ var self = this;
+ return _.filter(this.nodes(), function(v) {
+ return _.isEmpty(self._out[v]);
+ });
+};
+
+Graph.prototype.setNodes = function(vs, value) {
+ var args = arguments;
+ var self = this;
+ _.each(vs, function(v) {
+ if (args.length > 1) {
+ self.setNode(v, value);
+ } else {
+ self.setNode(v);
+ }
+ });
+ return this;
+};
+
+Graph.prototype.setNode = function(v, value) {
+ if (_.has(this._nodes, v)) {
+ if (arguments.length > 1) {
+ this._nodes[v] = value;
+ }
+ return this;
+ }
+
+ this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
+ if (this._isCompound) {
+ this._parent[v] = GRAPH_NODE;
+ this._children[v] = {};
+ this._children[GRAPH_NODE][v] = true;
+ }
+ this._in[v] = {};
+ this._preds[v] = {};
+ this._out[v] = {};
+ this._sucs[v] = {};
+ ++this._nodeCount;
+ return this;
+};
+
+Graph.prototype.node = function(v) {
+ return this._nodes[v];
+};
+
+Graph.prototype.hasNode = function(v) {
+ return _.has(this._nodes, v);
+};
+
+Graph.prototype.removeNode = function(v) {
+ var self = this;
+ if (_.has(this._nodes, v)) {
+ var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); };
+ delete this._nodes[v];
+ if (this._isCompound) {
+ this._removeFromParentsChildList(v);
+ delete this._parent[v];
+ _.each(this.children(v), function(child) {
+ self.setParent(child);
+ });
+ delete this._children[v];
+ }
+ _.each(_.keys(this._in[v]), removeEdge);
+ delete this._in[v];
+ delete this._preds[v];
+ _.each(_.keys(this._out[v]), removeEdge);
+ delete this._out[v];
+ delete this._sucs[v];
+ --this._nodeCount;
+ }
+ return this;
+};
+
+Graph.prototype.setParent = function(v, parent) {
+ if (!this._isCompound) {
+ throw new Error('Cannot set parent in a non-compound graph');
+ }
+
+ if (_.isUndefined(parent)) {
+ parent = GRAPH_NODE;
+ } else {
+ // Coerce parent to string
+ parent += '';
+ for (var ancestor = parent;
+ !_.isUndefined(ancestor);
+ ancestor = this.parent(ancestor)) {
+ if (ancestor === v) {
+ throw new Error('Setting ' + parent+ ' as parent of ' + v +
+ ' would create a cycle');
+ }
+ }
+
+ this.setNode(parent);
+ }
+
+ this.setNode(v);
+ this._removeFromParentsChildList(v);
+ this._parent[v] = parent;
+ this._children[parent][v] = true;
+ return this;
+};
+
+Graph.prototype._removeFromParentsChildList = function(v) {
+ delete this._children[this._parent[v]][v];
+};
+
+Graph.prototype.parent = function(v) {
+ if (this._isCompound) {
+ var parent = this._parent[v];
+ if (parent !== GRAPH_NODE) {
+ return parent;
+ }
+ }
+};
+
+Graph.prototype.children = function(v) {
+ if (_.isUndefined(v)) {
+ v = GRAPH_NODE;
+ }
+
+ if (this._isCompound) {
+ var children = this._children[v];
+ if (children) {
+ return _.keys(children);
+ }
+ } else if (v === GRAPH_NODE) {
+ return this.nodes();
+ } else if (this.hasNode(v)) {
+ return [];
+ }
+};
+
+Graph.prototype.predecessors = function(v) {
+ var predsV = this._preds[v];
+ if (predsV) {
+ return _.keys(predsV);
+ }
+};
+
+Graph.prototype.successors = function(v) {
+ var sucsV = this._sucs[v];
+ if (sucsV) {
+ return _.keys(sucsV);
+ }
+};
+
+Graph.prototype.neighbors = function(v) {
+ var preds = this.predecessors(v);
+ if (preds) {
+ return _.union(preds, this.successors(v));
+ }
+};
+
+Graph.prototype.isLeaf = function (v) {
+ var neighbors;
+ if (this.isDirected()) {
+ neighbors = this.successors(v);
+ } else {
+ neighbors = this.neighbors(v);
+ }
+ return neighbors.length === 0;
+};
+
+Graph.prototype.filterNodes = function(filter) {
+ var copy = new this.constructor({
+ directed: this._isDirected,
+ multigraph: this._isMultigraph,
+ compound: this._isCompound
+ });
+
+ copy.setGraph(this.graph());
+
+ var self = this;
+ _.each(this._nodes, function(value, v) {
+ if (filter(v)) {
+ copy.setNode(v, value);
+ }
+ });
+
+ _.each(this._edgeObjs, function(e) {
+ if (copy.hasNode(e.v) && copy.hasNode(e.w)) {
+ copy.setEdge(e, self.edge(e));
+ }
+ });
+
+ var parents = {};
+ function findParent(v) {
+ var parent = self.parent(v);
+ if (parent === undefined || copy.hasNode(parent)) {
+ parents[v] = parent;
+ return parent;
+ } else if (parent in parents) {
+ return parents[parent];
+ } else {
+ return findParent(parent);
+ }
+ }
+
+ if (this._isCompound) {
+ _.each(copy.nodes(), function(v) {
+ copy.setParent(v, findParent(v));
+ });
+ }
+
+ return copy;
+};
+
+/* === Edge functions ========== */
+
+Graph.prototype.setDefaultEdgeLabel = function(newDefault) {
+ if (!_.isFunction(newDefault)) {
+ newDefault = _.constant(newDefault);
+ }
+ this._defaultEdgeLabelFn = newDefault;
+ return this;
+};
+
+Graph.prototype.edgeCount = function() {
+ return this._edgeCount;
+};
+
+Graph.prototype.edges = function() {
+ return _.values(this._edgeObjs);
+};
+
+Graph.prototype.setPath = function(vs, value) {
+ var self = this,
+ args = arguments;
+ _.reduce(vs, function(v, w) {
+ if (args.length > 1) {
+ self.setEdge(v, w, value);
+ } else {
+ self.setEdge(v, w);
+ }
+ return w;
+ });
+ return this;
+};
+
+/*
+ * setEdge(v, w, [value, [name]])
+ * setEdge({ v, w, [name] }, [value])
+ */
+Graph.prototype.setEdge = function() {
+ var v, w, name, value,
+ valueSpecified = false,
+ arg0 = arguments[0];
+
+ if (typeof arg0 === 'object' && arg0 !== null && 'v' in arg0) {
+ v = arg0.v;
+ w = arg0.w;
+ name = arg0.name;
+ if (arguments.length === 2) {
+ value = arguments[1];
+ valueSpecified = true;
+ }
+ } else {
+ v = arg0;
+ w = arguments[1];
+ name = arguments[3];
+ if (arguments.length > 2) {
+ value = arguments[2];
+ valueSpecified = true;
+ }
+ }
+
+ v = '' + v;
+ w = '' + w;
+ if (!_.isUndefined(name)) {
+ name = '' + name;
+ }
+
+ var e = edgeArgsToId(this._isDirected, v, w, name);
+ if (_.has(this._edgeLabels, e)) {
+ if (valueSpecified) {
+ this._edgeLabels[e] = value;
+ }
+ return this;
+ }
+
+ if (!_.isUndefined(name) && !this._isMultigraph) {
+ throw new Error('Cannot set a named edge when isMultigraph = false');
+ }
+
+ // It didn't exist, so we need to create it.
+ // First ensure the nodes exist.
+ this.setNode(v);
+ this.setNode(w);
+
+ this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
+
+ var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
+ // Ensure we add undirected edges in a consistent way.
+ v = edgeObj.v;
+ w = edgeObj.w;
+
+ Object.freeze(edgeObj);
+ this._edgeObjs[e] = edgeObj;
+ incrementOrInitEntry(this._preds[w], v);
+ incrementOrInitEntry(this._sucs[v], w);
+ this._in[w][e] = edgeObj;
+ this._out[v][e] = edgeObj;
+ this._edgeCount++;
+ return this;
+};
+
+Graph.prototype.edge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name));
+ return this._edgeLabels[e];
+};
+
+Graph.prototype.hasEdge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name));
+ return _.has(this._edgeLabels, e);
+};
+
+Graph.prototype.removeEdge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name)),
+ edge = this._edgeObjs[e];
+ if (edge) {
+ v = edge.v;
+ w = edge.w;
+ delete this._edgeLabels[e];
+ delete this._edgeObjs[e];
+ decrementOrRemoveEntry(this._preds[w], v);
+ decrementOrRemoveEntry(this._sucs[v], w);
+ delete this._in[w][e];
+ delete this._out[v][e];
+ this._edgeCount--;
+ }
+ return this;
+};
+
+Graph.prototype.inEdges = function(v, u) {
+ var inV = this._in[v];
+ if (inV) {
+ var edges = _.values(inV);
+ if (!u) {
+ return edges;
+ }
+ return _.filter(edges, function(edge) { return edge.v === u; });
+ }
+};
+
+Graph.prototype.outEdges = function(v, w) {
+ var outV = this._out[v];
+ if (outV) {
+ var edges = _.values(outV);
+ if (!w) {
+ return edges;
+ }
+ return _.filter(edges, function(edge) { return edge.w === w; });
+ }
+};
+
+Graph.prototype.nodeEdges = function(v, w) {
+ var inEdges = this.inEdges(v, w);
+ if (inEdges) {
+ return inEdges.concat(this.outEdges(v, w));
+ }
+};
+
+function incrementOrInitEntry(map, k) {
+ if (map[k]) {
+ map[k]++;
+ } else {
+ map[k] = 1;
+ }
+}
+
+function decrementOrRemoveEntry(map, k) {
+ if (!--map[k]) { delete map[k]; }
+}
+
+function edgeArgsToId(isDirected, v_, w_, name) {
+ var v = '' + v_;
+ var w = '' + w_;
+ if (!isDirected && v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM +
+ (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name);
+}
+
+function edgeArgsToObj(isDirected, v_, w_, name) {
+ var v = '' + v_;
+ var w = '' + w_;
+ if (!isDirected && v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ var edgeObj = { v: v, w: w };
+ if (name) {
+ edgeObj.name = name;
+ }
+ return edgeObj;
+}
+
+function edgeObjToId(isDirected, edgeObj) {
+ return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
+}
+
+},{'./lodash':49}],47:[function(require,module,exports){
+// Includes only the "core" of graphlib
+module.exports = {
+ Graph: require('./graph'),
+ version: require('./version')
+};
+
+},{'./graph':46,'./version':50}],48:[function(require,module,exports){
+var _ = require('./lodash'),
+ Graph = require('./graph');
+
+module.exports = {
+ write: write,
+ read: read
+};
+
+function write(g) {
+ var json = {
+ options: {
+ directed: g.isDirected(),
+ multigraph: g.isMultigraph(),
+ compound: g.isCompound()
+ },
+ nodes: writeNodes(g),
+ edges: writeEdges(g)
+ };
+ if (!_.isUndefined(g.graph())) {
+ json.value = _.clone(g.graph());
+ }
+ return json;
+}
+
+function writeNodes(g) {
+ return _.map(g.nodes(), function(v) {
+ var nodeValue = g.node(v),
+ parent = g.parent(v),
+ node = { v: v };
+ if (!_.isUndefined(nodeValue)) {
+ node.value = nodeValue;
+ }
+ if (!_.isUndefined(parent)) {
+ node.parent = parent;
+ }
+ return node;
+ });
+}
+
+function writeEdges(g) {
+ return _.map(g.edges(), function(e) {
+ var edgeValue = g.edge(e),
+ edge = { v: e.v, w: e.w };
+ if (!_.isUndefined(e.name)) {
+ edge.name = e.name;
+ }
+ if (!_.isUndefined(edgeValue)) {
+ edge.value = edgeValue;
+ }
+ return edge;
+ });
+}
+
+function read(json) {
+ var g = new Graph(json.options).setGraph(json.value);
+ _.each(json.nodes, function(entry) {
+ g.setNode(entry.v, entry.value);
+ if (entry.parent) {
+ g.setParent(entry.v, entry.parent);
+ }
+ });
+ _.each(json.edges, function(entry) {
+ g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
+ });
+ return g;
+}
+
+},{'./graph':46,'./lodash':49}],49:[function(require,module,exports){
+/* global window */
+
+var lodash;
+
+if (typeof require === 'function') {
+ try {
+ lodash = {
+ clone: require('lodash/clone'),
+ constant: require('lodash/constant'),
+ each: require('lodash/each'),
+ filter: require('lodash/filter'),
+ has: require('lodash/has'),
+ isArray: require('lodash/isArray'),
+ isEmpty: require('lodash/isEmpty'),
+ isFunction: require('lodash/isFunction'),
+ isUndefined: require('lodash/isUndefined'),
+ keys: require('lodash/keys'),
+ map: require('lodash/map'),
+ reduce: require('lodash/reduce'),
+ size: require('lodash/size'),
+ transform: require('lodash/transform'),
+ union: require('lodash/union'),
+ values: require('lodash/values')
+ };
+ } catch (e) {}
+}
+
+if (!lodash) {
+ lodash = window._;
+}
+
+module.exports = lodash;
+
+},{'lodash/clone':226,'lodash/constant':228,'lodash/each':230,'lodash/filter':232,'lodash/has':239,'lodash/isArray':243,'lodash/isEmpty':247,'lodash/isFunction':248,'lodash/isUndefined':258,'lodash/keys':259,'lodash/map':262,'lodash/reduce':274,'lodash/size':275,'lodash/transform':284,'lodash/union':285,'lodash/values':287}],50:[function(require,module,exports){
+module.exports = '2.1.7';
+
+},{}],51:[function(require,module,exports){
+var getNative = require('./_getNative'),
+ root = require('./_root');
+
+/* Built-in method references that are verified to be native. */
+var DataView = getNative(root, 'DataView');
+
+module.exports = DataView;
+
+},{'./_getNative':163,'./_root':208}],52:[function(require,module,exports){
+var hashClear = require('./_hashClear'),
+ hashDelete = require('./_hashDelete'),
+ hashGet = require('./_hashGet'),
+ hashHas = require('./_hashHas'),
+ hashSet = require('./_hashSet');
+
+/**
+ * Creates a hash object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function Hash(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+// Add methods to `Hash`.
+Hash.prototype.clear = hashClear;
+Hash.prototype['delete'] = hashDelete;
+Hash.prototype.get = hashGet;
+Hash.prototype.has = hashHas;
+Hash.prototype.set = hashSet;
+
+module.exports = Hash;
+
+},{'./_hashClear':172,'./_hashDelete':173,'./_hashGet':174,'./_hashHas':175,'./_hashSet':176}],53:[function(require,module,exports){
+var listCacheClear = require('./_listCacheClear'),
+ listCacheDelete = require('./_listCacheDelete'),
+ listCacheGet = require('./_listCacheGet'),
+ listCacheHas = require('./_listCacheHas'),
+ listCacheSet = require('./_listCacheSet');
+
+/**
+ * Creates an list cache object.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function ListCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+// Add methods to `ListCache`.
+ListCache.prototype.clear = listCacheClear;
+ListCache.prototype['delete'] = listCacheDelete;
+ListCache.prototype.get = listCacheGet;
+ListCache.prototype.has = listCacheHas;
+ListCache.prototype.set = listCacheSet;
+
+module.exports = ListCache;
+
+},{'./_listCacheClear':188,'./_listCacheDelete':189,'./_listCacheGet':190,'./_listCacheHas':191,'./_listCacheSet':192}],54:[function(require,module,exports){
+var getNative = require('./_getNative'),
+ root = require('./_root');
+
+/* Built-in method references that are verified to be native. */
+var Map = getNative(root, 'Map');
+
+module.exports = Map;
+
+},{'./_getNative':163,'./_root':208}],55:[function(require,module,exports){
+var mapCacheClear = require('./_mapCacheClear'),
+ mapCacheDelete = require('./_mapCacheDelete'),
+ mapCacheGet = require('./_mapCacheGet'),
+ mapCacheHas = require('./_mapCacheHas'),
+ mapCacheSet = require('./_mapCacheSet');
+
+/**
+ * Creates a map cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function MapCache(entries) {
+ var index = -1,
+ length = entries == null ? 0 : entries.length;
+
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+}
+
+// Add methods to `MapCache`.
+MapCache.prototype.clear = mapCacheClear;
+MapCache.prototype['delete'] = mapCacheDelete;
+MapCache.prototype.get = mapCacheGet;
+MapCache.prototype.has = mapCacheHas;
+MapCache.prototype.set = mapCacheSet;
+
+module.exports = MapCache;
+
+},{'./_mapCacheClear':193,'./_mapCacheDelete':194,'./_mapCacheGet':195,'./_mapCacheHas':196,'./_mapCacheSet':197}],56:[function(require,module,exports){
+var getNative = require('./_getNative'),
+ root = require('./_root');
+
+/* Built-in method references that are verified to be native. */
+var Promise = getNative(root, 'Promise');
+
+module.exports = Promise;
+
+},{'./_getNative':163,'./_root':208}],57:[function(require,module,exports){
+var getNative = require('./_getNative'),
+ root = require('./_root');
+
+/* Built-in method references that are verified to be native. */
+var Set = getNative(root, 'Set');
+
+module.exports = Set;
+
+},{'./_getNative':163,'./_root':208}],58:[function(require,module,exports){
+var MapCache = require('./_MapCache'),
+ setCacheAdd = require('./_setCacheAdd'),
+ setCacheHas = require('./_setCacheHas');
+
+/**
+ *
+ * Creates an array cache object to store unique values.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [values] The values to cache.
+ */
+function SetCache(values) {
+ var index = -1,
+ length = values == null ? 0 : values.length;
+
+ this.__data__ = new MapCache;
+ while (++index < length) {
+ this.add(values[index]);
+ }
+}
+
+// Add methods to `SetCache`.
+SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
+SetCache.prototype.has = setCacheHas;
+
+module.exports = SetCache;
+
+},{'./_MapCache':55,'./_setCacheAdd':210,'./_setCacheHas':211}],59:[function(require,module,exports){
+var ListCache = require('./_ListCache'),
+ stackClear = require('./_stackClear'),
+ stackDelete = require('./_stackDelete'),
+ stackGet = require('./_stackGet'),
+ stackHas = require('./_stackHas'),
+ stackSet = require('./_stackSet');
+
+/**
+ * Creates a stack cache object to store key-value pairs.
+ *
+ * @private
+ * @constructor
+ * @param {Array} [entries] The key-value pairs to cache.
+ */
+function Stack(entries) {
+ var data = this.__data__ = new ListCache(entries);
+ this.size = data.size;
+}
+
+// Add methods to `Stack`.
+Stack.prototype.clear = stackClear;
+Stack.prototype['delete'] = stackDelete;
+Stack.prototype.get = stackGet;
+Stack.prototype.has = stackHas;
+Stack.prototype.set = stackSet;
+
+module.exports = Stack;
+
+},{'./_ListCache':53,'./_stackClear':215,'./_stackDelete':216,'./_stackGet':217,'./_stackHas':218,'./_stackSet':219}],60:[function(require,module,exports){
+var root = require('./_root');
+
+/** Built-in value references. */
+var Symbol = root.Symbol;
+
+module.exports = Symbol;
+
+},{'./_root':208}],61:[function(require,module,exports){
+var root = require('./_root');
+
+/** Built-in value references. */
+var Uint8Array = root.Uint8Array;
+
+module.exports = Uint8Array;
+
+},{'./_root':208}],62:[function(require,module,exports){
+var getNative = require('./_getNative'),
+ root = require('./_root');
+
+/* Built-in method references that are verified to be native. */
+var WeakMap = getNative(root, 'WeakMap');
+
+module.exports = WeakMap;
+
+},{'./_getNative':163,'./_root':208}],63:[function(require,module,exports){
+/**
+ * A faster alternative to `Function#apply`, this function invokes `func`
+ * with the `this` binding of `thisArg` and the arguments of `args`.
+ *
+ * @private
+ * @param {Function} func The function to invoke.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} args The arguments to invoke `func` with.
+ * @returns {*} Returns the result of `func`.
+ */
+function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0: return func.call(thisArg);
+ case 1: return func.call(thisArg, args[0]);
+ case 2: return func.call(thisArg, args[0], args[1]);
+ case 3: return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+}
+
+module.exports = apply;
+
+},{}],64:[function(require,module,exports){
+/**
+ * A specialized version of `_.forEach` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+}
+
+module.exports = arrayEach;
+
+},{}],65:[function(require,module,exports){
+/**
+ * A specialized version of `_.filter` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ resIndex = 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+}
+
+module.exports = arrayFilter;
+
+},{}],66:[function(require,module,exports){
+var baseIndexOf = require('./_baseIndexOf');
+
+/**
+ * A specialized version of `_.includes` for arrays without support for
+ * specifying an index to search from.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+function arrayIncludes(array, value) {
+ var length = array == null ? 0 : array.length;
+ return !!length && baseIndexOf(array, value, 0) > -1;
+}
+
+module.exports = arrayIncludes;
+
+},{'./_baseIndexOf':95}],67:[function(require,module,exports){
+/**
+ * This function is like `arrayIncludes` except that it accepts a comparator.
+ *
+ * @private
+ * @param {Array} [array] The array to inspect.
+ * @param {*} target The value to search for.
+ * @param {Function} comparator The comparator invoked per element.
+ * @returns {boolean} Returns `true` if `target` is found, else `false`.
+ */
+function arrayIncludesWith(array, value, comparator) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+module.exports = arrayIncludesWith;
+
+},{}],68:[function(require,module,exports){
+var baseTimes = require('./_baseTimes'),
+ isArguments = require('./isArguments'),
+ isArray = require('./isArray'),
+ isBuffer = require('./isBuffer'),
+ isIndex = require('./_isIndex'),
+ isTypedArray = require('./isTypedArray');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Creates an array of the enumerable property names of the array-like `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @param {boolean} inherited Specify returning inherited property names.
+ * @returns {Array} Returns the array of property names.
+ */
+function arrayLikeKeys(value, inherited) {
+ var isArr = isArray(value),
+ isArg = !isArr && isArguments(value),
+ isBuff = !isArr && !isArg && isBuffer(value),
+ isType = !isArr && !isArg && !isBuff && isTypedArray(value),
+ skipIndexes = isArr || isArg || isBuff || isType,
+ result = skipIndexes ? baseTimes(value.length, String) : [],
+ length = result.length;
+
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) &&
+ !(skipIndexes && (
+ // Safari 9 has enumerable `arguments.length` in strict mode.
+ key == 'length' ||
+ // Node.js 0.10 has enumerable non-index properties on buffers.
+ (isBuff && (key == 'offset' || key == 'parent')) ||
+ // PhantomJS 2 has enumerable non-index properties on typed arrays.
+ (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
+ // Skip index properties.
+ isIndex(key, length)
+ ))) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+module.exports = arrayLikeKeys;
+
+},{'./_baseTimes':125,'./_isIndex':181,'./isArguments':242,'./isArray':243,'./isBuffer':246,'./isTypedArray':257}],69:[function(require,module,exports){
+/**
+ * A specialized version of `_.map` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array == null ? 0 : array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+}
+
+module.exports = arrayMap;
+
+},{}],70:[function(require,module,exports){
+/**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+}
+
+module.exports = arrayPush;
+
+},{}],71:[function(require,module,exports){
+/**
+ * A specialized version of `_.reduce` for arrays without support for
+ * iteratee shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initAccum] Specify using the first element of `array` as
+ * the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+}
+
+module.exports = arrayReduce;
+
+},{}],72:[function(require,module,exports){
+/**
+ * A specialized version of `_.some` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+function arraySome(array, predicate) {
+ var index = -1,
+ length = array == null ? 0 : array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+module.exports = arraySome;
+
+},{}],73:[function(require,module,exports){
+var baseProperty = require('./_baseProperty');
+
+/**
+ * Gets the size of an ASCII `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+var asciiSize = baseProperty('length');
+
+module.exports = asciiSize;
+
+},{'./_baseProperty':117}],74:[function(require,module,exports){
+var baseAssignValue = require('./_baseAssignValue'),
+ eq = require('./eq');
+
+/**
+ * This function is like `assignValue` except that it doesn't assign
+ * `undefined` values.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+function assignMergeValue(object, key, value) {
+ if ((value !== undefined && !eq(object[key], value)) ||
+ (value === undefined && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+}
+
+module.exports = assignMergeValue;
+
+},{'./_baseAssignValue':79,'./eq':231}],75:[function(require,module,exports){
+var baseAssignValue = require('./_baseAssignValue'),
+ eq = require('./eq');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Assigns `value` to `key` of `object` if the existing value is not equivalent
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
+ (value === undefined && !(key in object))) {
+ baseAssignValue(object, key, value);
+ }
+}
+
+module.exports = assignValue;
+
+},{'./_baseAssignValue':79,'./eq':231}],76:[function(require,module,exports){
+var eq = require('./eq');
+
+/**
+ * Gets the index at which the `key` is found in `array` of key-value pairs.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} key The key to search for.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+}
+
+module.exports = assocIndexOf;
+
+},{'./eq':231}],77:[function(require,module,exports){
+var copyObject = require('./_copyObject'),
+ keys = require('./keys');
+
+/**
+ * The base implementation of `_.assign` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+}
+
+module.exports = baseAssign;
+
+},{'./_copyObject':143,'./keys':259}],78:[function(require,module,exports){
+var copyObject = require('./_copyObject'),
+ keysIn = require('./keysIn');
+
+/**
+ * The base implementation of `_.assignIn` without support for multiple sources
+ * or `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+function baseAssignIn(object, source) {
+ return object && copyObject(source, keysIn(source), object);
+}
+
+module.exports = baseAssignIn;
+
+},{'./_copyObject':143,'./keysIn':260}],79:[function(require,module,exports){
+var defineProperty = require('./_defineProperty');
+
+/**
+ * The base implementation of `assignValue` and `assignMergeValue` without
+ * value checks.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {string} key The key of the property to assign.
+ * @param {*} value The value to assign.
+ */
+function baseAssignValue(object, key, value) {
+ if (key == '__proto__' && defineProperty) {
+ defineProperty(object, key, {
+ 'configurable': true,
+ 'enumerable': true,
+ 'value': value,
+ 'writable': true
+ });
+ } else {
+ object[key] = value;
+ }
+}
+
+module.exports = baseAssignValue;
+
+},{'./_defineProperty':153}],80:[function(require,module,exports){
+var Stack = require('./_Stack'),
+ arrayEach = require('./_arrayEach'),
+ assignValue = require('./_assignValue'),
+ baseAssign = require('./_baseAssign'),
+ baseAssignIn = require('./_baseAssignIn'),
+ cloneBuffer = require('./_cloneBuffer'),
+ copyArray = require('./_copyArray'),
+ copySymbols = require('./_copySymbols'),
+ copySymbolsIn = require('./_copySymbolsIn'),
+ getAllKeys = require('./_getAllKeys'),
+ getAllKeysIn = require('./_getAllKeysIn'),
+ getTag = require('./_getTag'),
+ initCloneArray = require('./_initCloneArray'),
+ initCloneByTag = require('./_initCloneByTag'),
+ initCloneObject = require('./_initCloneObject'),
+ isArray = require('./isArray'),
+ isBuffer = require('./isBuffer'),
+ isMap = require('./isMap'),
+ isObject = require('./isObject'),
+ isSet = require('./isSet'),
+ keys = require('./keys');
+
+/** Used to compose bitmasks for cloning. */
+var CLONE_DEEP_FLAG = 1,
+ CLONE_FLAT_FLAG = 2,
+ CLONE_SYMBOLS_FLAG = 4;
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]',
+ weakMapTag = '[object WeakMap]';
+
+var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+/** Used to identify `toStringTag` values supported by `_.clone`. */
+var cloneableTags = {};
+cloneableTags[argsTag] = cloneableTags[arrayTag] =
+cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
+cloneableTags[boolTag] = cloneableTags[dateTag] =
+cloneableTags[float32Tag] = cloneableTags[float64Tag] =
+cloneableTags[int8Tag] = cloneableTags[int16Tag] =
+cloneableTags[int32Tag] = cloneableTags[mapTag] =
+cloneableTags[numberTag] = cloneableTags[objectTag] =
+cloneableTags[regexpTag] = cloneableTags[setTag] =
+cloneableTags[stringTag] = cloneableTags[symbolTag] =
+cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+cloneableTags[errorTag] = cloneableTags[funcTag] =
+cloneableTags[weakMapTag] = false;
+
+/**
+ * The base implementation of `_.clone` and `_.cloneDeep` which tracks
+ * traversed objects.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Deep clone
+ * 2 - Flatten inherited properties
+ * 4 - Clone symbols
+ * @param {Function} [customizer] The function to customize cloning.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The parent object of `value`.
+ * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+function baseClone(value, bitmask, customizer, key, object, stack) {
+ var result,
+ isDeep = bitmask & CLONE_DEEP_FLAG,
+ isFlat = bitmask & CLONE_FLAT_FLAG,
+ isFull = bitmask & CLONE_SYMBOLS_FLAG;
+
+ if (customizer) {
+ result = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result);
+ }
+ } else {
+ var tag = getTag(value),
+ isFunc = tag == funcTag || tag == genTag;
+
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ result = (isFlat || isFunc) ? {} : initCloneObject(value);
+ if (!isDeep) {
+ return isFlat
+ ? copySymbolsIn(value, baseAssignIn(result, value))
+ : copySymbols(value, baseAssign(result, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result = initCloneByTag(value, tag, isDeep);
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stack || (stack = new Stack);
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result);
+
+ if (isSet(value)) {
+ value.forEach(function(subValue) {
+ result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
+ });
+
+ return result;
+ }
+
+ if (isMap(value)) {
+ value.forEach(function(subValue, key) {
+ result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
+ });
+
+ return result;
+ }
+
+ var keysFunc = isFull
+ ? (isFlat ? getAllKeysIn : getAllKeys)
+ : (isFlat ? keysIn : keys);
+
+ var props = isArr ? undefined : keysFunc(value);
+ arrayEach(props || value, function(subValue, key) {
+ if (props) {
+ key = subValue;
+ subValue = value[key];
+ }
+ // Recursively populate clone (susceptible to call stack limits).
+ assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
+ });
+ return result;
+}
+
+module.exports = baseClone;
+
+},{'./_Stack':59,'./_arrayEach':64,'./_assignValue':75,'./_baseAssign':77,'./_baseAssignIn':78,'./_cloneBuffer':135,'./_copyArray':142,'./_copySymbols':144,'./_copySymbolsIn':145,'./_getAllKeys':159,'./_getAllKeysIn':160,'./_getTag':168,'./_initCloneArray':177,'./_initCloneByTag':178,'./_initCloneObject':179,'./isArray':243,'./isBuffer':246,'./isMap':250,'./isObject':251,'./isSet':254,'./keys':259}],81:[function(require,module,exports){
+var isObject = require('./isObject');
+
+/** Built-in value references. */
+var objectCreate = Object.create;
+
+/**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} proto The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+var baseCreate = (function() {
+ function object() {}
+ return function(proto) {
+ if (!isObject(proto)) {
+ return {};
+ }
+ if (objectCreate) {
+ return objectCreate(proto);
+ }
+ object.prototype = proto;
+ var result = new object;
+ object.prototype = undefined;
+ return result;
+ };
+}());
+
+module.exports = baseCreate;
+
+},{'./isObject':251}],82:[function(require,module,exports){
+var baseForOwn = require('./_baseForOwn'),
+ createBaseEach = require('./_createBaseEach');
+
+/**
+ * The base implementation of `_.forEach` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ */
+var baseEach = createBaseEach(baseForOwn);
+
+module.exports = baseEach;
+
+},{'./_baseForOwn':88,'./_createBaseEach':148}],83:[function(require,module,exports){
+var isSymbol = require('./isSymbol');
+
+/**
+ * The base implementation of methods like `_.max` and `_.min` which accepts a
+ * `comparator` to determine the extremum value.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The iteratee invoked per iteration.
+ * @param {Function} comparator The comparator used to compare values.
+ * @returns {*} Returns the extremum value.
+ */
+function baseExtremum(array, iteratee, comparator) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index],
+ current = iteratee(value);
+
+ if (current != null && (computed === undefined
+ ? (current === current && !isSymbol(current))
+ : comparator(current, computed)
+ )) {
+ var computed = current,
+ result = value;
+ }
+ }
+ return result;
+}
+
+module.exports = baseExtremum;
+
+},{'./isSymbol':256}],84:[function(require,module,exports){
+var baseEach = require('./_baseEach');
+
+/**
+ * The base implementation of `_.filter` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+function baseFilter(collection, predicate) {
+ var result = [];
+ baseEach(collection, function(value, index, collection) {
+ if (predicate(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ return result;
+}
+
+module.exports = baseFilter;
+
+},{'./_baseEach':82}],85:[function(require,module,exports){
+/**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 1 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+module.exports = baseFindIndex;
+
+},{}],86:[function(require,module,exports){
+var arrayPush = require('./_arrayPush'),
+ isFlattenable = require('./_isFlattenable');
+
+/**
+ * The base implementation of `_.flatten` with support for restricting flattening.
+ *
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {number} depth The maximum recursion depth.
+ * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
+ * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
+ * @param {Array} [result=[]] The initial result value.
+ * @returns {Array} Returns the new flattened array.
+ */
+function baseFlatten(array, depth, predicate, isStrict, result) {
+ var index = -1,
+ length = array.length;
+
+ predicate || (predicate = isFlattenable);
+ result || (result = []);
+
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && predicate(value)) {
+ if (depth > 1) {
+ // Recursively flatten arrays (susceptible to call stack limits).
+ baseFlatten(value, depth - 1, predicate, isStrict, result);
+ } else {
+ arrayPush(result, value);
+ }
+ } else if (!isStrict) {
+ result[result.length] = value;
+ }
+ }
+ return result;
+}
+
+module.exports = baseFlatten;
+
+},{'./_arrayPush':70,'./_isFlattenable':180}],87:[function(require,module,exports){
+var createBaseFor = require('./_createBaseFor');
+
+/**
+ * The base implementation of `baseForOwn` which iterates over `object`
+ * properties returned by `keysFunc` and invokes `iteratee` for each property.
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+var baseFor = createBaseFor();
+
+module.exports = baseFor;
+
+},{'./_createBaseFor':149}],88:[function(require,module,exports){
+var baseFor = require('./_baseFor'),
+ keys = require('./keys');
+
+/**
+ * The base implementation of `_.forOwn` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+function baseForOwn(object, iteratee) {
+ return object && baseFor(object, iteratee, keys);
+}
+
+module.exports = baseForOwn;
+
+},{'./_baseFor':87,'./keys':259}],89:[function(require,module,exports){
+var castPath = require('./_castPath'),
+ toKey = require('./_toKey');
+
+/**
+ * The base implementation of `_.get` without support for default values.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @returns {*} Returns the resolved value.
+ */
+function baseGet(object, path) {
+ path = castPath(path, object);
+
+ var index = 0,
+ length = path.length;
+
+ while (object != null && index < length) {
+ object = object[toKey(path[index++])];
+ }
+ return (index && index == length) ? object : undefined;
+}
+
+module.exports = baseGet;
+
+},{'./_castPath':133,'./_toKey':223}],90:[function(require,module,exports){
+var arrayPush = require('./_arrayPush'),
+ isArray = require('./isArray');
+
+/**
+ * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
+ * `keysFunc` and `symbolsFunc` to get the enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @param {Function} symbolsFunc The function to get the symbols of `object`.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result = keysFunc(object);
+ return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
+}
+
+module.exports = baseGetAllKeys;
+
+},{'./_arrayPush':70,'./isArray':243}],91:[function(require,module,exports){
+var Symbol = require('./_Symbol'),
+ getRawTag = require('./_getRawTag'),
+ objectToString = require('./_objectToString');
+
+/** `Object#toString` result references. */
+var nullTag = '[object Null]',
+ undefinedTag = '[object Undefined]';
+
+/** Built-in value references. */
+var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
+
+/**
+ * The base implementation of `getTag` without fallbacks for buggy environments.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined ? undefinedTag : nullTag;
+ }
+ return (symToStringTag && symToStringTag in Object(value))
+ ? getRawTag(value)
+ : objectToString(value);
+}
+
+module.exports = baseGetTag;
+
+},{'./_Symbol':60,'./_getRawTag':165,'./_objectToString':205}],92:[function(require,module,exports){
+/**
+ * The base implementation of `_.gt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`,
+ * else `false`.
+ */
+function baseGt(value, other) {
+ return value > other;
+}
+
+module.exports = baseGt;
+
+},{}],93:[function(require,module,exports){
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * The base implementation of `_.has` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+function baseHas(object, key) {
+ return object != null && hasOwnProperty.call(object, key);
+}
+
+module.exports = baseHas;
+
+},{}],94:[function(require,module,exports){
+/**
+ * The base implementation of `_.hasIn` without support for deep paths.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {Array|string} key The key to check.
+ * @returns {boolean} Returns `true` if `key` exists, else `false`.
+ */
+function baseHasIn(object, key) {
+ return object != null && key in Object(object);
+}
+
+module.exports = baseHasIn;
+
+},{}],95:[function(require,module,exports){
+var baseFindIndex = require('./_baseFindIndex'),
+ baseIsNaN = require('./_baseIsNaN'),
+ strictIndexOf = require('./_strictIndexOf');
+
+/**
+ * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function baseIndexOf(array, value, fromIndex) {
+ return value === value
+ ? strictIndexOf(array, value, fromIndex)
+ : baseFindIndex(array, baseIsNaN, fromIndex);
+}
+
+module.exports = baseIndexOf;
+
+},{'./_baseFindIndex':85,'./_baseIsNaN':101,'./_strictIndexOf':220}],96:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]';
+
+/**
+ * The base implementation of `_.isArguments`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ */
+function baseIsArguments(value) {
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
+}
+
+module.exports = baseIsArguments;
+
+},{'./_baseGetTag':91,'./isObjectLike':252}],97:[function(require,module,exports){
+var baseIsEqualDeep = require('./_baseIsEqualDeep'),
+ isObjectLike = require('./isObjectLike');
+
+/**
+ * The base implementation of `_.isEqual` which supports partial comparisons
+ * and tracks traversed objects.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {boolean} bitmask The bitmask flags.
+ * 1 - Unordered comparison
+ * 2 - Partial comparison
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @param {Object} [stack] Tracks traversed `value` and `other` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ */
+function baseIsEqual(value, other, bitmask, customizer, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+}
+
+module.exports = baseIsEqual;
+
+},{'./_baseIsEqualDeep':98,'./isObjectLike':252}],98:[function(require,module,exports){
+var Stack = require('./_Stack'),
+ equalArrays = require('./_equalArrays'),
+ equalByTag = require('./_equalByTag'),
+ equalObjects = require('./_equalObjects'),
+ getTag = require('./_getTag'),
+ isArray = require('./isArray'),
+ isBuffer = require('./isBuffer'),
+ isTypedArray = require('./isTypedArray');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1;
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ objectTag = '[object Object]';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
+ * deep comparisons and tracks traversed objects enabling objects with circular
+ * references to be compared.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} [stack] Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+ var objIsArr = isArray(object),
+ othIsArr = isArray(other),
+ objTag = objIsArr ? arrayTag : getTag(object),
+ othTag = othIsArr ? arrayTag : getTag(other);
+
+ objTag = objTag == argsTag ? objectTag : objTag;
+ othTag = othTag == argsTag ? objectTag : othTag;
+
+ var objIsObj = objTag == objectTag,
+ othIsObj = othTag == objectTag,
+ isSameTag = objTag == othTag;
+
+ if (isSameTag && isBuffer(object)) {
+ if (!isBuffer(other)) {
+ return false;
+ }
+ objIsArr = true;
+ objIsObj = false;
+ }
+ if (isSameTag && !objIsObj) {
+ stack || (stack = new Stack);
+ return (objIsArr || isTypedArray(object))
+ ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
+ : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+ }
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+ if (objIsWrapped || othIsWrapped) {
+ var objUnwrapped = objIsWrapped ? object.value() : object,
+ othUnwrapped = othIsWrapped ? other.value() : other;
+
+ stack || (stack = new Stack);
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack);
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+}
+
+module.exports = baseIsEqualDeep;
+
+},{'./_Stack':59,'./_equalArrays':154,'./_equalByTag':155,'./_equalObjects':156,'./_getTag':168,'./isArray':243,'./isBuffer':246,'./isTypedArray':257}],99:[function(require,module,exports){
+var getTag = require('./_getTag'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var mapTag = '[object Map]';
+
+/**
+ * The base implementation of `_.isMap` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ */
+function baseIsMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+}
+
+module.exports = baseIsMap;
+
+},{'./_getTag':168,'./isObjectLike':252}],100:[function(require,module,exports){
+var Stack = require('./_Stack'),
+ baseIsEqual = require('./_baseIsEqual');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+/**
+ * The base implementation of `_.isMatch` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Array} matchData The property names, values, and compare flags to match.
+ * @param {Function} [customizer] The function to customize comparisons.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length,
+ length = index,
+ noCustomizer = !customizer;
+
+ if (object == null) {
+ return !length;
+ }
+ object = Object(object);
+ while (index--) {
+ var data = matchData[index];
+ if ((noCustomizer && data[2])
+ ? data[1] !== object[data[0]]
+ : !(data[0] in object)
+ ) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0],
+ objValue = object[key],
+ srcValue = data[1];
+
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack;
+ if (customizer) {
+ var result = customizer(objValue, srcValue, key, object, source, stack);
+ }
+ if (!(result === undefined
+ ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
+ : result
+ )) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+module.exports = baseIsMatch;
+
+},{'./_Stack':59,'./_baseIsEqual':97}],101:[function(require,module,exports){
+/**
+ * The base implementation of `_.isNaN` without support for number objects.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ */
+function baseIsNaN(value) {
+ return value !== value;
+}
+
+module.exports = baseIsNaN;
+
+},{}],102:[function(require,module,exports){
+var isFunction = require('./isFunction'),
+ isMasked = require('./_isMasked'),
+ isObject = require('./isObject'),
+ toSource = require('./_toSource');
+
+/**
+ * Used to match `RegExp`
+ * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
+ */
+var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
+
+/** Used to detect host constructors (Safari). */
+var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+/** Used for built-in method references. */
+var funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var funcToString = funcProto.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Used to detect if a method is native. */
+var reIsNative = RegExp('^' +
+ funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+);
+
+/**
+ * The base implementation of `_.isNative` without bad shim checks.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function,
+ * else `false`.
+ */
+function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+}
+
+module.exports = baseIsNative;
+
+},{'./_isMasked':185,'./_toSource':224,'./isFunction':248,'./isObject':251}],103:[function(require,module,exports){
+var getTag = require('./_getTag'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var setTag = '[object Set]';
+
+/**
+ * The base implementation of `_.isSet` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ */
+function baseIsSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+}
+
+module.exports = baseIsSet;
+
+},{'./_getTag':168,'./isObjectLike':252}],104:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ isLength = require('./isLength'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ weakMapTag = '[object WeakMap]';
+
+var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+/** Used to identify `toStringTag` values of typed arrays. */
+var typedArrayTags = {};
+typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+typedArrayTags[uint32Tag] = true;
+typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
+typedArrayTags[errorTag] = typedArrayTags[funcTag] =
+typedArrayTags[mapTag] = typedArrayTags[numberTag] =
+typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
+typedArrayTags[setTag] = typedArrayTags[stringTag] =
+typedArrayTags[weakMapTag] = false;
+
+/**
+ * The base implementation of `_.isTypedArray` without Node.js optimizations.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ */
+function baseIsTypedArray(value) {
+ return isObjectLike(value) &&
+ isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
+}
+
+module.exports = baseIsTypedArray;
+
+},{'./_baseGetTag':91,'./isLength':249,'./isObjectLike':252}],105:[function(require,module,exports){
+var baseMatches = require('./_baseMatches'),
+ baseMatchesProperty = require('./_baseMatchesProperty'),
+ identity = require('./identity'),
+ isArray = require('./isArray'),
+ property = require('./property');
+
+/**
+ * The base implementation of `_.iteratee`.
+ *
+ * @private
+ * @param {*} [value=_.identity] The value to convert to an iteratee.
+ * @returns {Function} Returns the iteratee.
+ */
+function baseIteratee(value) {
+ // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
+ // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
+ if (typeof value == 'function') {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (typeof value == 'object') {
+ return isArray(value)
+ ? baseMatchesProperty(value[0], value[1])
+ : baseMatches(value);
+ }
+ return property(value);
+}
+
+module.exports = baseIteratee;
+
+},{'./_baseMatches':110,'./_baseMatchesProperty':111,'./identity':241,'./isArray':243,'./property':272}],106:[function(require,module,exports){
+var isPrototype = require('./_isPrototype'),
+ nativeKeys = require('./_nativeKeys');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result = [];
+ for (var key in Object(object)) {
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+module.exports = baseKeys;
+
+},{'./_isPrototype':186,'./_nativeKeys':202}],107:[function(require,module,exports){
+var isObject = require('./isObject'),
+ isPrototype = require('./_isPrototype'),
+ nativeKeysIn = require('./_nativeKeysIn');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object),
+ result = [];
+
+ for (var key in object) {
+ if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+module.exports = baseKeysIn;
+
+},{'./_isPrototype':186,'./_nativeKeysIn':203,'./isObject':251}],108:[function(require,module,exports){
+/**
+ * The base implementation of `_.lt` which doesn't coerce arguments.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`,
+ * else `false`.
+ */
+function baseLt(value, other) {
+ return value < other;
+}
+
+module.exports = baseLt;
+
+},{}],109:[function(require,module,exports){
+var baseEach = require('./_baseEach'),
+ isArrayLike = require('./isArrayLike');
+
+/**
+ * The base implementation of `_.map` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
+ });
+ return result;
+}
+
+module.exports = baseMap;
+
+},{'./_baseEach':82,'./isArrayLike':244}],110:[function(require,module,exports){
+var baseIsMatch = require('./_baseIsMatch'),
+ getMatchData = require('./_getMatchData'),
+ matchesStrictComparable = require('./_matchesStrictComparable');
+
+/**
+ * The base implementation of `_.matches` which doesn't clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new spec function.
+ */
+function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ return matchesStrictComparable(matchData[0][0], matchData[0][1]);
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+}
+
+module.exports = baseMatches;
+
+},{'./_baseIsMatch':100,'./_getMatchData':162,'./_matchesStrictComparable':199}],111:[function(require,module,exports){
+var baseIsEqual = require('./_baseIsEqual'),
+ get = require('./get'),
+ hasIn = require('./hasIn'),
+ isKey = require('./_isKey'),
+ isStrictComparable = require('./_isStrictComparable'),
+ matchesStrictComparable = require('./_matchesStrictComparable'),
+ toKey = require('./_toKey');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+/**
+ * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+function baseMatchesProperty(path, srcValue) {
+ if (isKey(path) && isStrictComparable(srcValue)) {
+ return matchesStrictComparable(toKey(path), srcValue);
+ }
+ return function(object) {
+ var objValue = get(object, path);
+ return (objValue === undefined && objValue === srcValue)
+ ? hasIn(object, path)
+ : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+ };
+}
+
+module.exports = baseMatchesProperty;
+
+},{'./_baseIsEqual':97,'./_isKey':183,'./_isStrictComparable':187,'./_matchesStrictComparable':199,'./_toKey':223,'./get':238,'./hasIn':240}],112:[function(require,module,exports){
+var Stack = require('./_Stack'),
+ assignMergeValue = require('./_assignMergeValue'),
+ baseFor = require('./_baseFor'),
+ baseMergeDeep = require('./_baseMergeDeep'),
+ isObject = require('./isObject'),
+ keysIn = require('./keysIn'),
+ safeGet = require('./_safeGet');
+
+/**
+ * The base implementation of `_.merge` without support for multiple sources.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ baseFor(source, function(srcValue, key) {
+ if (isObject(srcValue)) {
+ stack || (stack = new Stack);
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ }
+ else {
+ var newValue = customizer
+ ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ }, keysIn);
+}
+
+module.exports = baseMerge;
+
+},{'./_Stack':59,'./_assignMergeValue':74,'./_baseFor':87,'./_baseMergeDeep':113,'./_safeGet':209,'./isObject':251,'./keysIn':260}],113:[function(require,module,exports){
+var assignMergeValue = require('./_assignMergeValue'),
+ cloneBuffer = require('./_cloneBuffer'),
+ cloneTypedArray = require('./_cloneTypedArray'),
+ copyArray = require('./_copyArray'),
+ initCloneObject = require('./_initCloneObject'),
+ isArguments = require('./isArguments'),
+ isArray = require('./isArray'),
+ isArrayLikeObject = require('./isArrayLikeObject'),
+ isBuffer = require('./isBuffer'),
+ isFunction = require('./isFunction'),
+ isObject = require('./isObject'),
+ isPlainObject = require('./isPlainObject'),
+ isTypedArray = require('./isTypedArray'),
+ safeGet = require('./_safeGet'),
+ toPlainObject = require('./toPlainObject');
+
+/**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {number} srcIndex The index of `source`.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {Object} [stack] Tracks traversed source values and their merged
+ * counterparts.
+ */
+function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = safeGet(object, key),
+ srcValue = safeGet(source, key),
+ stacked = stack.get(srcValue);
+
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer
+ ? customizer(objValue, srcValue, (key + ''), object, source, stack)
+ : undefined;
+
+ var isCommon = newValue === undefined;
+
+ if (isCommon) {
+ var isArr = isArray(srcValue),
+ isBuff = !isArr && isBuffer(srcValue),
+ isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+
+ newValue = srcValue;
+ if (isArr || isBuff || isTyped) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ }
+ else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ }
+ else if (isBuff) {
+ isCommon = false;
+ newValue = cloneBuffer(srcValue, true);
+ }
+ else if (isTyped) {
+ isCommon = false;
+ newValue = cloneTypedArray(srcValue, true);
+ }
+ else {
+ newValue = [];
+ }
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ newValue = objValue;
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ }
+ else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
+ newValue = initCloneObject(srcValue);
+ }
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack['delete'](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+}
+
+module.exports = baseMergeDeep;
+
+},{'./_assignMergeValue':74,'./_cloneBuffer':135,'./_cloneTypedArray':139,'./_copyArray':142,'./_initCloneObject':179,'./_safeGet':209,'./isArguments':242,'./isArray':243,'./isArrayLikeObject':245,'./isBuffer':246,'./isFunction':248,'./isObject':251,'./isPlainObject':253,'./isTypedArray':257,'./toPlainObject':282}],114:[function(require,module,exports){
+var arrayMap = require('./_arrayMap'),
+ baseIteratee = require('./_baseIteratee'),
+ baseMap = require('./_baseMap'),
+ baseSortBy = require('./_baseSortBy'),
+ baseUnary = require('./_baseUnary'),
+ compareMultiple = require('./_compareMultiple'),
+ identity = require('./identity');
+
+/**
+ * The base implementation of `_.orderBy` without param guards.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {string[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+function baseOrderBy(collection, iteratees, orders) {
+ var index = -1;
+ iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(baseIteratee));
+
+ var result = baseMap(collection, function(value, key, collection) {
+ var criteria = arrayMap(iteratees, function(iteratee) {
+ return iteratee(value);
+ });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
+
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+}
+
+module.exports = baseOrderBy;
+
+},{'./_arrayMap':69,'./_baseIteratee':105,'./_baseMap':109,'./_baseSortBy':124,'./_baseUnary':127,'./_compareMultiple':141,'./identity':241}],115:[function(require,module,exports){
+var basePickBy = require('./_basePickBy'),
+ hasIn = require('./hasIn');
+
+/**
+ * The base implementation of `_.pick` without support for individual
+ * property identifiers.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @returns {Object} Returns the new object.
+ */
+function basePick(object, paths) {
+ return basePickBy(object, paths, function(value, path) {
+ return hasIn(object, path);
+ });
+}
+
+module.exports = basePick;
+
+},{'./_basePickBy':116,'./hasIn':240}],116:[function(require,module,exports){
+var baseGet = require('./_baseGet'),
+ baseSet = require('./_baseSet'),
+ castPath = require('./_castPath');
+
+/**
+ * The base implementation of `_.pickBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} paths The property paths to pick.
+ * @param {Function} predicate The function invoked per property.
+ * @returns {Object} Returns the new object.
+ */
+function basePickBy(object, paths, predicate) {
+ var index = -1,
+ length = paths.length,
+ result = {};
+
+ while (++index < length) {
+ var path = paths[index],
+ value = baseGet(object, path);
+
+ if (predicate(value, path)) {
+ baseSet(result, castPath(path, object), value);
+ }
+ }
+ return result;
+}
+
+module.exports = basePickBy;
+
+},{'./_baseGet':89,'./_baseSet':122,'./_castPath':133}],117:[function(require,module,exports){
+/**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined : object[key];
+ };
+}
+
+module.exports = baseProperty;
+
+},{}],118:[function(require,module,exports){
+var baseGet = require('./_baseGet');
+
+/**
+ * A specialized version of `baseProperty` which supports deep paths.
+ *
+ * @private
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ */
+function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+}
+
+module.exports = basePropertyDeep;
+
+},{'./_baseGet':89}],119:[function(require,module,exports){
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeCeil = Math.ceil,
+ nativeMax = Math.max;
+
+/**
+ * The base implementation of `_.range` and `_.rangeRight` which doesn't
+ * coerce arguments.
+ *
+ * @private
+ * @param {number} start The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} step The value to increment or decrement by.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the range of numbers.
+ */
+function baseRange(start, end, step, fromRight) {
+ var index = -1,
+ length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
+ result = Array(length);
+
+ while (length--) {
+ result[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result;
+}
+
+module.exports = baseRange;
+
+},{}],120:[function(require,module,exports){
+/**
+ * The base implementation of `_.reduce` and `_.reduceRight`, without support
+ * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} accumulator The initial value.
+ * @param {boolean} initAccum Specify using the first or last element of
+ * `collection` as the initial value.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the accumulated value.
+ */
+function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection) {
+ accumulator = initAccum
+ ? (initAccum = false, value)
+ : iteratee(accumulator, value, index, collection);
+ });
+ return accumulator;
+}
+
+module.exports = baseReduce;
+
+},{}],121:[function(require,module,exports){
+var identity = require('./identity'),
+ overRest = require('./_overRest'),
+ setToString = require('./_setToString');
+
+/**
+ * The base implementation of `_.rest` which doesn't validate or coerce arguments.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ */
+function baseRest(func, start) {
+ return setToString(overRest(func, start, identity), func + '');
+}
+
+module.exports = baseRest;
+
+},{'./_overRest':207,'./_setToString':213,'./identity':241}],122:[function(require,module,exports){
+var assignValue = require('./_assignValue'),
+ castPath = require('./_castPath'),
+ isIndex = require('./_isIndex'),
+ isObject = require('./isObject'),
+ toKey = require('./_toKey');
+
+/**
+ * The base implementation of `_.set`.
+ *
+ * @private
+ * @param {Object} object The object to modify.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @param {Function} [customizer] The function to customize path creation.
+ * @returns {Object} Returns `object`.
+ */
+function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]),
+ newValue = value;
+
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined;
+ if (newValue === undefined) {
+ newValue = isObject(objValue)
+ ? objValue
+ : (isIndex(path[index + 1]) ? [] : {});
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+}
+
+module.exports = baseSet;
+
+},{'./_assignValue':75,'./_castPath':133,'./_isIndex':181,'./_toKey':223,'./isObject':251}],123:[function(require,module,exports){
+var constant = require('./constant'),
+ defineProperty = require('./_defineProperty'),
+ identity = require('./identity');
+
+/**
+ * The base implementation of `setToString` without support for hot loop shorting.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+var baseSetToString = !defineProperty ? identity : function(func, string) {
+ return defineProperty(func, 'toString', {
+ 'configurable': true,
+ 'enumerable': false,
+ 'value': constant(string),
+ 'writable': true
+ });
+};
+
+module.exports = baseSetToString;
+
+},{'./_defineProperty':153,'./constant':228,'./identity':241}],124:[function(require,module,exports){
+/**
+ * The base implementation of `_.sortBy` which uses `comparer` to define the
+ * sort order of `array` and replaces criteria objects with their corresponding
+ * values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+function baseSortBy(array, comparer) {
+ var length = array.length;
+
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+}
+
+module.exports = baseSortBy;
+
+},{}],125:[function(require,module,exports){
+/**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+}
+
+module.exports = baseTimes;
+
+},{}],126:[function(require,module,exports){
+var Symbol = require('./_Symbol'),
+ arrayMap = require('./_arrayMap'),
+ isArray = require('./isArray'),
+ isSymbol = require('./isSymbol');
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0;
+
+/** Used to convert symbols to primitives and strings. */
+var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolToString = symbolProto ? symbolProto.toString : undefined;
+
+/**
+ * The base implementation of `_.toString` which doesn't convert nullish
+ * values to empty strings.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+function baseToString(value) {
+ // Exit early for strings to avoid a performance hit in some environments.
+ if (typeof value == 'string') {
+ return value;
+ }
+ if (isArray(value)) {
+ // Recursively convert values (susceptible to call stack limits).
+ return arrayMap(value, baseToString) + '';
+ }
+ if (isSymbol(value)) {
+ return symbolToString ? symbolToString.call(value) : '';
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+}
+
+module.exports = baseToString;
+
+},{'./_Symbol':60,'./_arrayMap':69,'./isArray':243,'./isSymbol':256}],127:[function(require,module,exports){
+/**
+ * The base implementation of `_.unary` without support for storing metadata.
+ *
+ * @private
+ * @param {Function} func The function to cap arguments for.
+ * @returns {Function} Returns the new capped function.
+ */
+function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+}
+
+module.exports = baseUnary;
+
+},{}],128:[function(require,module,exports){
+var SetCache = require('./_SetCache'),
+ arrayIncludes = require('./_arrayIncludes'),
+ arrayIncludesWith = require('./_arrayIncludesWith'),
+ cacheHas = require('./_cacheHas'),
+ createSet = require('./_createSet'),
+ setToArray = require('./_setToArray');
+
+/** Used as the size to enable large array optimizations. */
+var LARGE_ARRAY_SIZE = 200;
+
+/**
+ * The base implementation of `_.uniqBy` without support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The iteratee invoked per element.
+ * @param {Function} [comparator] The comparator invoked per element.
+ * @returns {Array} Returns the new duplicate free array.
+ */
+function baseUniq(array, iteratee, comparator) {
+ var index = -1,
+ includes = arrayIncludes,
+ length = array.length,
+ isCommon = true,
+ result = [],
+ seen = result;
+
+ if (comparator) {
+ isCommon = false;
+ includes = arrayIncludesWith;
+ }
+ else if (length >= LARGE_ARRAY_SIZE) {
+ var set = iteratee ? null : createSet(array);
+ if (set) {
+ return setToArray(set);
+ }
+ isCommon = false;
+ includes = cacheHas;
+ seen = new SetCache;
+ }
+ else {
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value) : value;
+
+ value = (comparator || value !== 0) ? value : 0;
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (!includes(seen, computed, comparator)) {
+ if (seen !== result) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+}
+
+module.exports = baseUniq;
+
+},{'./_SetCache':58,'./_arrayIncludes':66,'./_arrayIncludesWith':67,'./_cacheHas':131,'./_createSet':152,'./_setToArray':212}],129:[function(require,module,exports){
+var arrayMap = require('./_arrayMap');
+
+/**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+}
+
+module.exports = baseValues;
+
+},{'./_arrayMap':69}],130:[function(require,module,exports){
+/**
+ * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
+ *
+ * @private
+ * @param {Array} props The property identifiers.
+ * @param {Array} values The property values.
+ * @param {Function} assignFunc The function to assign values.
+ * @returns {Object} Returns the new object.
+ */
+function baseZipObject(props, values, assignFunc) {
+ var index = -1,
+ length = props.length,
+ valsLength = values.length,
+ result = {};
+
+ while (++index < length) {
+ var value = index < valsLength ? values[index] : undefined;
+ assignFunc(result, props[index], value);
+ }
+ return result;
+}
+
+module.exports = baseZipObject;
+
+},{}],131:[function(require,module,exports){
+/**
+ * Checks if a `cache` value for `key` exists.
+ *
+ * @private
+ * @param {Object} cache The cache to query.
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function cacheHas(cache, key) {
+ return cache.has(key);
+}
+
+module.exports = cacheHas;
+
+},{}],132:[function(require,module,exports){
+var identity = require('./identity');
+
+/**
+ * Casts `value` to `identity` if it's not a function.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {Function} Returns cast function.
+ */
+function castFunction(value) {
+ return typeof value == 'function' ? value : identity;
+}
+
+module.exports = castFunction;
+
+},{'./identity':241}],133:[function(require,module,exports){
+var isArray = require('./isArray'),
+ isKey = require('./_isKey'),
+ stringToPath = require('./_stringToPath'),
+ toString = require('./toString');
+
+/**
+ * Casts `value` to a path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {Array} Returns the cast property path array.
+ */
+function castPath(value, object) {
+ if (isArray(value)) {
+ return value;
+ }
+ return isKey(value, object) ? [value] : stringToPath(toString(value));
+}
+
+module.exports = castPath;
+
+},{'./_isKey':183,'./_stringToPath':222,'./isArray':243,'./toString':283}],134:[function(require,module,exports){
+var Uint8Array = require('./_Uint8Array');
+
+/**
+ * Creates a clone of `arrayBuffer`.
+ *
+ * @private
+ * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+function cloneArrayBuffer(arrayBuffer) {
+ var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer));
+ return result;
+}
+
+module.exports = cloneArrayBuffer;
+
+},{'./_Uint8Array':61}],135:[function(require,module,exports){
+var root = require('./_root');
+
+/** Detect free variable `exports`. */
+var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
+
+/** Detect free variable `module`. */
+var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
+
+/** Detect the popular CommonJS extension `module.exports`. */
+var moduleExports = freeModule && freeModule.exports === freeExports;
+
+/** Built-in value references. */
+var Buffer = moduleExports ? root.Buffer : undefined,
+ allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;
+
+/**
+ * Creates a clone of `buffer`.
+ *
+ * @private
+ * @param {Buffer} buffer The buffer to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Buffer} Returns the cloned buffer.
+ */
+function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var length = buffer.length,
+ result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
+
+ buffer.copy(result);
+ return result;
+}
+
+module.exports = cloneBuffer;
+
+},{'./_root':208}],136:[function(require,module,exports){
+var cloneArrayBuffer = require('./_cloneArrayBuffer');
+
+/**
+ * Creates a clone of `dataView`.
+ *
+ * @private
+ * @param {Object} dataView The data view to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned data view.
+ */
+function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+}
+
+module.exports = cloneDataView;
+
+},{'./_cloneArrayBuffer':134}],137:[function(require,module,exports){
+/** Used to match `RegExp` flags from their coerced string values. */
+var reFlags = /\w*$/;
+
+/**
+ * Creates a clone of `regexp`.
+ *
+ * @private
+ * @param {Object} regexp The regexp to clone.
+ * @returns {Object} Returns the cloned regexp.
+ */
+function cloneRegExp(regexp) {
+ var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result.lastIndex = regexp.lastIndex;
+ return result;
+}
+
+module.exports = cloneRegExp;
+
+},{}],138:[function(require,module,exports){
+var Symbol = require('./_Symbol');
+
+/** Used to convert symbols to primitives and strings. */
+var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
+
+/**
+ * Creates a clone of the `symbol` object.
+ *
+ * @private
+ * @param {Object} symbol The symbol object to clone.
+ * @returns {Object} Returns the cloned symbol object.
+ */
+function cloneSymbol(symbol) {
+ return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
+}
+
+module.exports = cloneSymbol;
+
+},{'./_Symbol':60}],139:[function(require,module,exports){
+var cloneArrayBuffer = require('./_cloneArrayBuffer');
+
+/**
+ * Creates a clone of `typedArray`.
+ *
+ * @private
+ * @param {Object} typedArray The typed array to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the cloned typed array.
+ */
+function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+}
+
+module.exports = cloneTypedArray;
+
+},{'./_cloneArrayBuffer':134}],140:[function(require,module,exports){
+var isSymbol = require('./isSymbol');
+
+/**
+ * Compares values to sort them in ascending order.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsDefined = value !== undefined,
+ valIsNull = value === null,
+ valIsReflexive = value === value,
+ valIsSymbol = isSymbol(value);
+
+ var othIsDefined = other !== undefined,
+ othIsNull = other === null,
+ othIsReflexive = other === other,
+ othIsSymbol = isSymbol(other);
+
+ if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
+ (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
+ (valIsNull && othIsDefined && othIsReflexive) ||
+ (!valIsDefined && othIsReflexive) ||
+ !valIsReflexive) {
+ return 1;
+ }
+ if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
+ (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
+ (othIsNull && valIsDefined && valIsReflexive) ||
+ (!othIsDefined && valIsReflexive) ||
+ !othIsReflexive) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+module.exports = compareAscending;
+
+},{'./isSymbol':256}],141:[function(require,module,exports){
+var compareAscending = require('./_compareAscending');
+
+/**
+ * Used by `_.orderBy` to compare multiple properties of a value to another
+ * and stable sort them.
+ *
+ * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
+ * specify an order of "desc" for descending or "asc" for ascending sort order
+ * of corresponding values.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {boolean[]|string[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
+
+ while (++index < length) {
+ var result = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ var order = orders[index];
+ return result * (order == 'desc' ? -1 : 1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+}
+
+module.exports = compareMultiple;
+
+},{'./_compareAscending':140}],142:[function(require,module,exports){
+/**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+function copyArray(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+}
+
+module.exports = copyArray;
+
+},{}],143:[function(require,module,exports){
+var assignValue = require('./_assignValue'),
+ baseAssignValue = require('./_baseAssignValue');
+
+/**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property identifiers to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @param {Function} [customizer] The function to customize copied values.
+ * @returns {Object} Returns `object`.
+ */
+function copyObject(source, props, object, customizer) {
+ var isNew = !object;
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+
+ var newValue = customizer
+ ? customizer(object[key], source[key], key, object, source)
+ : undefined;
+
+ if (newValue === undefined) {
+ newValue = source[key];
+ }
+ if (isNew) {
+ baseAssignValue(object, key, newValue);
+ } else {
+ assignValue(object, key, newValue);
+ }
+ }
+ return object;
+}
+
+module.exports = copyObject;
+
+},{'./_assignValue':75,'./_baseAssignValue':79}],144:[function(require,module,exports){
+var copyObject = require('./_copyObject'),
+ getSymbols = require('./_getSymbols');
+
+/**
+ * Copies own symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+}
+
+module.exports = copySymbols;
+
+},{'./_copyObject':143,'./_getSymbols':166}],145:[function(require,module,exports){
+var copyObject = require('./_copyObject'),
+ getSymbolsIn = require('./_getSymbolsIn');
+
+/**
+ * Copies own and inherited symbols of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy symbols from.
+ * @param {Object} [object={}] The object to copy symbols to.
+ * @returns {Object} Returns `object`.
+ */
+function copySymbolsIn(source, object) {
+ return copyObject(source, getSymbolsIn(source), object);
+}
+
+module.exports = copySymbolsIn;
+
+},{'./_copyObject':143,'./_getSymbolsIn':167}],146:[function(require,module,exports){
+var root = require('./_root');
+
+/** Used to detect overreaching core-js shims. */
+var coreJsData = root['__core-js_shared__'];
+
+module.exports = coreJsData;
+
+},{'./_root':208}],147:[function(require,module,exports){
+var baseRest = require('./_baseRest'),
+ isIterateeCall = require('./_isIterateeCall');
+
+/**
+ * Creates a function like `_.assign`.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+function createAssigner(assigner) {
+ return baseRest(function(object, sources) {
+ var index = -1,
+ length = sources.length,
+ customizer = length > 1 ? sources[length - 1] : undefined,
+ guard = length > 2 ? sources[2] : undefined;
+
+ customizer = (assigner.length > 3 && typeof customizer == 'function')
+ ? (length--, customizer)
+ : undefined;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined : customizer;
+ length = 1;
+ }
+ object = Object(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+}
+
+module.exports = createAssigner;
+
+},{'./_baseRest':121,'./_isIterateeCall':182}],148:[function(require,module,exports){
+var isArrayLike = require('./isArrayLike');
+
+/**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee);
+ }
+ var length = collection.length,
+ index = fromRight ? length : -1,
+ iterable = Object(collection);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+}
+
+module.exports = createBaseEach;
+
+},{'./isArrayLike':244}],149:[function(require,module,exports){
+/**
+ * Creates a base function for methods like `_.forIn` and `_.forOwn`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var index = -1,
+ iterable = Object(object),
+ props = keysFunc(object),
+ length = props.length;
+
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+}
+
+module.exports = createBaseFor;
+
+},{}],150:[function(require,module,exports){
+var baseIteratee = require('./_baseIteratee'),
+ isArrayLike = require('./isArrayLike'),
+ keys = require('./keys');
+
+/**
+ * Creates a `_.find` or `_.findLast` function.
+ *
+ * @private
+ * @param {Function} findIndexFunc The function to find the collection index.
+ * @returns {Function} Returns the new find function.
+ */
+function createFind(findIndexFunc) {
+ return function(collection, predicate, fromIndex) {
+ var iterable = Object(collection);
+ if (!isArrayLike(collection)) {
+ var iteratee = baseIteratee(predicate, 3);
+ collection = keys(collection);
+ predicate = function(key) { return iteratee(iterable[key], key, iterable); };
+ }
+ var index = findIndexFunc(collection, predicate, fromIndex);
+ return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
+ };
+}
+
+module.exports = createFind;
+
+},{'./_baseIteratee':105,'./isArrayLike':244,'./keys':259}],151:[function(require,module,exports){
+var baseRange = require('./_baseRange'),
+ isIterateeCall = require('./_isIterateeCall'),
+ toFinite = require('./toFinite');
+
+/**
+ * Creates a `_.range` or `_.rangeRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new range function.
+ */
+function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
+ end = step = undefined;
+ }
+ // Ensure the sign of `-0` is preserved.
+ start = toFinite(start);
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
+ return baseRange(start, end, step, fromRight);
+ };
+}
+
+module.exports = createRange;
+
+},{'./_baseRange':119,'./_isIterateeCall':182,'./toFinite':279}],152:[function(require,module,exports){
+var Set = require('./_Set'),
+ noop = require('./noop'),
+ setToArray = require('./_setToArray');
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0;
+
+/**
+ * Creates a set object of `values`.
+ *
+ * @private
+ * @param {Array} values The values to add to the set.
+ * @returns {Object} Returns the new set.
+ */
+var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
+ return new Set(values);
+};
+
+module.exports = createSet;
+
+},{'./_Set':57,'./_setToArray':212,'./noop':269}],153:[function(require,module,exports){
+var getNative = require('./_getNative');
+
+var defineProperty = (function() {
+ try {
+ var func = getNative(Object, 'defineProperty');
+ func({}, '', {});
+ return func;
+ } catch (e) {}
+}());
+
+module.exports = defineProperty;
+
+},{'./_getNative':163}],154:[function(require,module,exports){
+var SetCache = require('./_SetCache'),
+ arraySome = require('./_arraySome'),
+ cacheHas = require('./_cacheHas');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+/**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `array` and `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ arrLength = array.length,
+ othLength = other.length;
+
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(array);
+ if (stacked && stack.get(other)) {
+ return stacked == other;
+ }
+ var index = -1,
+ result = true,
+ seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
+
+ stack.set(array, other);
+ stack.set(other, array);
+
+ // Ignore non-index properties.
+ while (++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, arrValue, index, other, array, stack)
+ : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined) {
+ if (compared) {
+ continue;
+ }
+ result = false;
+ break;
+ }
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (seen) {
+ if (!arraySome(other, function(othValue, othIndex) {
+ if (!cacheHas(seen, othIndex) &&
+ (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+ return seen.push(othIndex);
+ }
+ })) {
+ result = false;
+ break;
+ }
+ } else if (!(
+ arrValue === othValue ||
+ equalFunc(arrValue, othValue, bitmask, customizer, stack)
+ )) {
+ result = false;
+ break;
+ }
+ }
+ stack['delete'](array);
+ stack['delete'](other);
+ return result;
+}
+
+module.exports = equalArrays;
+
+},{'./_SetCache':58,'./_arraySome':72,'./_cacheHas':131}],155:[function(require,module,exports){
+var Symbol = require('./_Symbol'),
+ Uint8Array = require('./_Uint8Array'),
+ eq = require('./eq'),
+ equalArrays = require('./_equalArrays'),
+ mapToArray = require('./_mapToArray'),
+ setToArray = require('./_setToArray');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1,
+ COMPARE_UNORDERED_FLAG = 2;
+
+/** `Object#toString` result references. */
+var boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]';
+
+var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]';
+
+/** Used to convert symbols to primitives and strings. */
+var symbolProto = Symbol ? Symbol.prototype : undefined,
+ symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
+
+/**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+ switch (tag) {
+ case dataViewTag:
+ if ((object.byteLength != other.byteLength) ||
+ (object.byteOffset != other.byteOffset)) {
+ return false;
+ }
+ object = object.buffer;
+ other = other.buffer;
+
+ case arrayBufferTag:
+ if ((object.byteLength != other.byteLength) ||
+ !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
+ return false;
+ }
+ return true;
+
+ case boolTag:
+ case dateTag:
+ case numberTag:
+ // Coerce booleans to `1` or `0` and dates to milliseconds.
+ // Invalid dates are coerced to `NaN`.
+ return eq(+object, +other);
+
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings, primitives and objects,
+ // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
+ // for more details.
+ return object == (other + '');
+
+ case mapTag:
+ var convert = mapToArray;
+
+ case setTag:
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
+ convert || (convert = setToArray);
+
+ if (object.size != other.size && !isPartial) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ bitmask |= COMPARE_UNORDERED_FLAG;
+
+ // Recursively compare objects (susceptible to call stack limits).
+ stack.set(object, other);
+ var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+ stack['delete'](object);
+ return result;
+
+ case symbolTag:
+ if (symbolValueOf) {
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
+ }
+ }
+ return false;
+}
+
+module.exports = equalByTag;
+
+},{'./_Symbol':60,'./_Uint8Array':61,'./_equalArrays':154,'./_mapToArray':198,'./_setToArray':212,'./eq':231}],156:[function(require,module,exports){
+var getAllKeys = require('./_getAllKeys');
+
+/** Used to compose bitmasks for value comparisons. */
+var COMPARE_PARTIAL_FLAG = 1;
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
+ * @param {Function} customizer The function to customize comparisons.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Object} stack Tracks traversed `object` and `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
+ objProps = getAllKeys(object),
+ objLength = objProps.length,
+ othProps = getAllKeys(other),
+ othLength = othProps.length;
+
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ // Assume cyclic values are equal.
+ var stacked = stack.get(object);
+ if (stacked && stack.get(other)) {
+ return stacked == other;
+ }
+ var result = true;
+ stack.set(object, other);
+ stack.set(other, object);
+
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key],
+ othValue = other[key];
+
+ if (customizer) {
+ var compared = isPartial
+ ? customizer(othValue, objValue, key, other, object, stack)
+ : customizer(objValue, othValue, key, object, other, stack);
+ }
+ // Recursively compare objects (susceptible to call stack limits).
+ if (!(compared === undefined
+ ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
+ : compared
+ )) {
+ result = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (result && !skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
+
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ result = false;
+ }
+ }
+ stack['delete'](object);
+ stack['delete'](other);
+ return result;
+}
+
+module.exports = equalObjects;
+
+},{'./_getAllKeys':159}],157:[function(require,module,exports){
+var flatten = require('./flatten'),
+ overRest = require('./_overRest'),
+ setToString = require('./_setToString');
+
+/**
+ * A specialized version of `baseRest` which flattens the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @returns {Function} Returns the new function.
+ */
+function flatRest(func) {
+ return setToString(overRest(func, undefined, flatten), func + '');
+}
+
+module.exports = flatRest;
+
+},{'./_overRest':207,'./_setToString':213,'./flatten':235}],158:[function(require,module,exports){
+(function (global){
+/** Detect free variable `global` from Node.js. */
+var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
+
+module.exports = freeGlobal;
+
+}).call(this,typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : {})
+},{}],159:[function(require,module,exports){
+var baseGetAllKeys = require('./_baseGetAllKeys'),
+ getSymbols = require('./_getSymbols'),
+ keys = require('./keys');
+
+/**
+ * Creates an array of own enumerable property names and symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+}
+
+module.exports = getAllKeys;
+
+},{'./_baseGetAllKeys':90,'./_getSymbols':166,'./keys':259}],160:[function(require,module,exports){
+var baseGetAllKeys = require('./_baseGetAllKeys'),
+ getSymbolsIn = require('./_getSymbolsIn'),
+ keysIn = require('./keysIn');
+
+/**
+ * Creates an array of own and inherited enumerable property names and
+ * symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names and symbols.
+ */
+function getAllKeysIn(object) {
+ return baseGetAllKeys(object, keysIn, getSymbolsIn);
+}
+
+module.exports = getAllKeysIn;
+
+},{'./_baseGetAllKeys':90,'./_getSymbolsIn':167,'./keysIn':260}],161:[function(require,module,exports){
+var isKeyable = require('./_isKeyable');
+
+/**
+ * Gets the data for `map`.
+ *
+ * @private
+ * @param {Object} map The map to query.
+ * @param {string} key The reference key.
+ * @returns {*} Returns the map data.
+ */
+function getMapData(map, key) {
+ var data = map.__data__;
+ return isKeyable(key)
+ ? data[typeof key == 'string' ? 'string' : 'hash']
+ : data.map;
+}
+
+module.exports = getMapData;
+
+},{'./_isKeyable':184}],162:[function(require,module,exports){
+var isStrictComparable = require('./_isStrictComparable'),
+ keys = require('./keys');
+
+/**
+ * Gets the property names, values, and compare flags of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the match data of `object`.
+ */
+function getMatchData(object) {
+ var result = keys(object),
+ length = result.length;
+
+ while (length--) {
+ var key = result[length],
+ value = object[key];
+
+ result[length] = [key, value, isStrictComparable(value)];
+ }
+ return result;
+}
+
+module.exports = getMatchData;
+
+},{'./_isStrictComparable':187,'./keys':259}],163:[function(require,module,exports){
+var baseIsNative = require('./_baseIsNative'),
+ getValue = require('./_getValue');
+
+/**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined;
+}
+
+module.exports = getNative;
+
+},{'./_baseIsNative':102,'./_getValue':169}],164:[function(require,module,exports){
+var overArg = require('./_overArg');
+
+/** Built-in value references. */
+var getPrototype = overArg(Object.getPrototypeOf, Object);
+
+module.exports = getPrototype;
+
+},{'./_overArg':206}],165:[function(require,module,exports){
+var Symbol = require('./_Symbol');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var nativeObjectToString = objectProto.toString;
+
+/** Built-in value references. */
+var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
+
+/**
+ * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the raw `toStringTag`.
+ */
+function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag),
+ tag = value[symToStringTag];
+
+ try {
+ value[symToStringTag] = undefined;
+ var unmasked = true;
+ } catch (e) {}
+
+ var result = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result;
+}
+
+module.exports = getRawTag;
+
+},{'./_Symbol':60}],166:[function(require,module,exports){
+var arrayFilter = require('./_arrayFilter'),
+ stubArray = require('./stubArray');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Built-in value references. */
+var propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeGetSymbols = Object.getOwnPropertySymbols;
+
+/**
+ * Creates an array of the own enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+ if (object == null) {
+ return [];
+ }
+ object = Object(object);
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
+ return propertyIsEnumerable.call(object, symbol);
+ });
+};
+
+module.exports = getSymbols;
+
+},{'./_arrayFilter':65,'./stubArray':277}],167:[function(require,module,exports){
+var arrayPush = require('./_arrayPush'),
+ getPrototype = require('./_getPrototype'),
+ getSymbols = require('./_getSymbols'),
+ stubArray = require('./stubArray');
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeGetSymbols = Object.getOwnPropertySymbols;
+
+/**
+ * Creates an array of the own and inherited enumerable symbols of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of symbols.
+ */
+var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+ var result = [];
+ while (object) {
+ arrayPush(result, getSymbols(object));
+ object = getPrototype(object);
+ }
+ return result;
+};
+
+module.exports = getSymbolsIn;
+
+},{'./_arrayPush':70,'./_getPrototype':164,'./_getSymbols':166,'./stubArray':277}],168:[function(require,module,exports){
+var DataView = require('./_DataView'),
+ Map = require('./_Map'),
+ Promise = require('./_Promise'),
+ Set = require('./_Set'),
+ WeakMap = require('./_WeakMap'),
+ baseGetTag = require('./_baseGetTag'),
+ toSource = require('./_toSource');
+
+/** `Object#toString` result references. */
+var mapTag = '[object Map]',
+ objectTag = '[object Object]',
+ promiseTag = '[object Promise]',
+ setTag = '[object Set]',
+ weakMapTag = '[object WeakMap]';
+
+var dataViewTag = '[object DataView]';
+
+/** Used to detect maps, sets, and weakmaps. */
+var dataViewCtorString = toSource(DataView),
+ mapCtorString = toSource(Map),
+ promiseCtorString = toSource(Promise),
+ setCtorString = toSource(Set),
+ weakMapCtorString = toSource(WeakMap);
+
+/**
+ * Gets the `toStringTag` of `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @returns {string} Returns the `toStringTag`.
+ */
+var getTag = baseGetTag;
+
+// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
+if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
+ (Map && getTag(new Map) != mapTag) ||
+ (Promise && getTag(Promise.resolve()) != promiseTag) ||
+ (Set && getTag(new Set) != setTag) ||
+ (WeakMap && getTag(new WeakMap) != weakMapTag)) {
+ getTag = function(value) {
+ var result = baseGetTag(value),
+ Ctor = result == objectTag ? value.constructor : undefined,
+ ctorString = Ctor ? toSource(Ctor) : '';
+
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString: return dataViewTag;
+ case mapCtorString: return mapTag;
+ case promiseCtorString: return promiseTag;
+ case setCtorString: return setTag;
+ case weakMapCtorString: return weakMapTag;
+ }
+ }
+ return result;
+ };
+}
+
+module.exports = getTag;
+
+},{'./_DataView':51,'./_Map':54,'./_Promise':56,'./_Set':57,'./_WeakMap':62,'./_baseGetTag':91,'./_toSource':224}],169:[function(require,module,exports){
+/**
+ * Gets the value at `key` of `object`.
+ *
+ * @private
+ * @param {Object} [object] The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+function getValue(object, key) {
+ return object == null ? undefined : object[key];
+}
+
+module.exports = getValue;
+
+},{}],170:[function(require,module,exports){
+var castPath = require('./_castPath'),
+ isArguments = require('./isArguments'),
+ isArray = require('./isArray'),
+ isIndex = require('./_isIndex'),
+ isLength = require('./isLength'),
+ toKey = require('./_toKey');
+
+/**
+ * Checks if `path` exists on `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @param {Function} hasFunc The function to check properties.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ */
+function hasPath(object, path, hasFunc) {
+ path = castPath(path, object);
+
+ var index = -1,
+ length = path.length,
+ result = false;
+
+ while (++index < length) {
+ var key = toKey(path[index]);
+ if (!(result = object != null && hasFunc(object, key))) {
+ break;
+ }
+ object = object[key];
+ }
+ if (result || ++index != length) {
+ return result;
+ }
+ length = object == null ? 0 : object.length;
+ return !!length && isLength(length) && isIndex(key, length) &&
+ (isArray(object) || isArguments(object));
+}
+
+module.exports = hasPath;
+
+},{'./_castPath':133,'./_isIndex':181,'./_toKey':223,'./isArguments':242,'./isArray':243,'./isLength':249}],171:[function(require,module,exports){
+/** Used to compose unicode character classes. */
+var rsAstralRange = '\\ud800-\\udfff',
+ rsComboMarksRange = '\\u0300-\\u036f',
+ reComboHalfMarksRange = '\\ufe20-\\ufe2f',
+ rsComboSymbolsRange = '\\u20d0-\\u20ff',
+ rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
+ rsVarRange = '\\ufe0e\\ufe0f';
+
+/** Used to compose unicode capture groups. */
+var rsZWJ = '\\u200d';
+
+/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
+var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
+
+/**
+ * Checks if `string` contains Unicode symbols.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {boolean} Returns `true` if a symbol is found, else `false`.
+ */
+function hasUnicode(string) {
+ return reHasUnicode.test(string);
+}
+
+module.exports = hasUnicode;
+
+},{}],172:[function(require,module,exports){
+var nativeCreate = require('./_nativeCreate');
+
+/**
+ * Removes all key-value entries from the hash.
+ *
+ * @private
+ * @name clear
+ * @memberOf Hash
+ */
+function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+ this.size = 0;
+}
+
+module.exports = hashClear;
+
+},{'./_nativeCreate':201}],173:[function(require,module,exports){
+/**
+ * Removes `key` and its value from the hash.
+ *
+ * @private
+ * @name delete
+ * @memberOf Hash
+ * @param {Object} hash The hash to modify.
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function hashDelete(key) {
+ var result = this.has(key) && delete this.__data__[key];
+ this.size -= result ? 1 : 0;
+ return result;
+}
+
+module.exports = hashDelete;
+
+},{}],174:[function(require,module,exports){
+var nativeCreate = require('./_nativeCreate');
+
+/** Used to stand-in for `undefined` hash values. */
+var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Gets the hash value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Hash
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result = data[key];
+ return result === HASH_UNDEFINED ? undefined : result;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined;
+}
+
+module.exports = hashGet;
+
+},{'./_nativeCreate':201}],175:[function(require,module,exports){
+var nativeCreate = require('./_nativeCreate');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Checks if a hash value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Hash
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
+}
+
+module.exports = hashHas;
+
+},{'./_nativeCreate':201}],176:[function(require,module,exports){
+var nativeCreate = require('./_nativeCreate');
+
+/** Used to stand-in for `undefined` hash values. */
+var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+/**
+ * Sets the hash `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Hash
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the hash instance.
+ */
+function hashSet(key, value) {
+ var data = this.__data__;
+ this.size += this.has(key) ? 0 : 1;
+ data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
+ return this;
+}
+
+module.exports = hashSet;
+
+},{'./_nativeCreate':201}],177:[function(require,module,exports){
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+function initCloneArray(array) {
+ var length = array.length,
+ result = new array.constructor(length);
+
+ // Add properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+}
+
+module.exports = initCloneArray;
+
+},{}],178:[function(require,module,exports){
+var cloneArrayBuffer = require('./_cloneArrayBuffer'),
+ cloneDataView = require('./_cloneDataView'),
+ cloneRegExp = require('./_cloneRegExp'),
+ cloneSymbol = require('./_cloneSymbol'),
+ cloneTypedArray = require('./_cloneTypedArray');
+
+/** `Object#toString` result references. */
+var boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]';
+
+var arrayBufferTag = '[object ArrayBuffer]',
+ dataViewTag = '[object DataView]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+/**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+
+ case mapTag:
+ return new Ctor;
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ return cloneRegExp(object);
+
+ case setTag:
+ return new Ctor;
+
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+}
+
+module.exports = initCloneByTag;
+
+},{'./_cloneArrayBuffer':134,'./_cloneDataView':136,'./_cloneRegExp':137,'./_cloneSymbol':138,'./_cloneTypedArray':139}],179:[function(require,module,exports){
+var baseCreate = require('./_baseCreate'),
+ getPrototype = require('./_getPrototype'),
+ isPrototype = require('./_isPrototype');
+
+/**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+function initCloneObject(object) {
+ return (typeof object.constructor == 'function' && !isPrototype(object))
+ ? baseCreate(getPrototype(object))
+ : {};
+}
+
+module.exports = initCloneObject;
+
+},{'./_baseCreate':81,'./_getPrototype':164,'./_isPrototype':186}],180:[function(require,module,exports){
+var Symbol = require('./_Symbol'),
+ isArguments = require('./isArguments'),
+ isArray = require('./isArray');
+
+/** Built-in value references. */
+var spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;
+
+/**
+ * Checks if `value` is a flattenable `arguments` object or array.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
+ */
+function isFlattenable(value) {
+ return isArray(value) || isArguments(value) ||
+ !!(spreadableSymbol && value && value[spreadableSymbol]);
+}
+
+module.exports = isFlattenable;
+
+},{'./_Symbol':60,'./isArguments':242,'./isArray':243}],181:[function(require,module,exports){
+/** Used as references for various `Number` constants. */
+var MAX_SAFE_INTEGER = 9007199254740991;
+
+/** Used to detect unsigned integer values. */
+var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+/**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+function isIndex(value, length) {
+ var type = typeof value;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+
+ return !!length &&
+ (type == 'number' ||
+ (type != 'symbol' && reIsUint.test(value))) &&
+ (value > -1 && value % 1 == 0 && value < length);
+}
+
+module.exports = isIndex;
+
+},{}],182:[function(require,module,exports){
+var eq = require('./eq'),
+ isArrayLike = require('./isArrayLike'),
+ isIndex = require('./_isIndex'),
+ isObject = require('./isObject');
+
+/**
+ * Checks if the given arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
+ * else `false`.
+ */
+function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)
+ ) {
+ return eq(object[index], value);
+ }
+ return false;
+}
+
+module.exports = isIterateeCall;
+
+},{'./_isIndex':181,'./eq':231,'./isArrayLike':244,'./isObject':251}],183:[function(require,module,exports){
+var isArray = require('./isArray'),
+ isSymbol = require('./isSymbol');
+
+/** Used to match property names within property paths. */
+var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/;
+
+/**
+ * Checks if `value` is a property name and not a property path.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ */
+function isKey(value, object) {
+ if (isArray(value)) {
+ return false;
+ }
+ var type = typeof value;
+ if (type == 'number' || type == 'symbol' || type == 'boolean' ||
+ value == null || isSymbol(value)) {
+ return true;
+ }
+ return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
+ (object != null && value in Object(object));
+}
+
+module.exports = isKey;
+
+},{'./isArray':243,'./isSymbol':256}],184:[function(require,module,exports){
+/**
+ * Checks if `value` is suitable for use as unique object key.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
+ */
+function isKeyable(value) {
+ var type = typeof value;
+ return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
+ ? (value !== '__proto__')
+ : (value === null);
+}
+
+module.exports = isKeyable;
+
+},{}],185:[function(require,module,exports){
+var coreJsData = require('./_coreJsData');
+
+/** Used to detect methods masquerading as native. */
+var maskSrcKey = (function() {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
+ return uid ? ('Symbol(src)_1.' + uid) : '';
+}());
+
+/**
+ * Checks if `func` has its source masked.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` is masked, else `false`.
+ */
+function isMasked(func) {
+ return !!maskSrcKey && (maskSrcKey in func);
+}
+
+module.exports = isMasked;
+
+},{'./_coreJsData':146}],186:[function(require,module,exports){
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+
+ return value === proto;
+}
+
+module.exports = isPrototype;
+
+},{}],187:[function(require,module,exports){
+var isObject = require('./isObject');
+
+/**
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
+ */
+function isStrictComparable(value) {
+ return value === value && !isObject(value);
+}
+
+module.exports = isStrictComparable;
+
+},{'./isObject':251}],188:[function(require,module,exports){
+/**
+ * Removes all key-value entries from the list cache.
+ *
+ * @private
+ * @name clear
+ * @memberOf ListCache
+ */
+function listCacheClear() {
+ this.__data__ = [];
+ this.size = 0;
+}
+
+module.exports = listCacheClear;
+
+},{}],189:[function(require,module,exports){
+var assocIndexOf = require('./_assocIndexOf');
+
+/** Used for built-in method references. */
+var arrayProto = Array.prototype;
+
+/** Built-in value references. */
+var splice = arrayProto.splice;
+
+/**
+ * Removes `key` and its value from the list cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf ListCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function listCacheDelete(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ --this.size;
+ return true;
+}
+
+module.exports = listCacheDelete;
+
+},{'./_assocIndexOf':76}],190:[function(require,module,exports){
+var assocIndexOf = require('./_assocIndexOf');
+
+/**
+ * Gets the list cache value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf ListCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function listCacheGet(key) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ return index < 0 ? undefined : data[index][1];
+}
+
+module.exports = listCacheGet;
+
+},{'./_assocIndexOf':76}],191:[function(require,module,exports){
+var assocIndexOf = require('./_assocIndexOf');
+
+/**
+ * Checks if a list cache value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf ListCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+}
+
+module.exports = listCacheHas;
+
+},{'./_assocIndexOf':76}],192:[function(require,module,exports){
+var assocIndexOf = require('./_assocIndexOf');
+
+/**
+ * Sets the list cache `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf ListCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the list cache instance.
+ */
+function listCacheSet(key, value) {
+ var data = this.__data__,
+ index = assocIndexOf(data, key);
+
+ if (index < 0) {
+ ++this.size;
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+}
+
+module.exports = listCacheSet;
+
+},{'./_assocIndexOf':76}],193:[function(require,module,exports){
+var Hash = require('./_Hash'),
+ ListCache = require('./_ListCache'),
+ Map = require('./_Map');
+
+/**
+ * Removes all key-value entries from the map.
+ *
+ * @private
+ * @name clear
+ * @memberOf MapCache
+ */
+function mapCacheClear() {
+ this.size = 0;
+ this.__data__ = {
+ 'hash': new Hash,
+ 'map': new (Map || ListCache),
+ 'string': new Hash
+ };
+}
+
+module.exports = mapCacheClear;
+
+},{'./_Hash':52,'./_ListCache':53,'./_Map':54}],194:[function(require,module,exports){
+var getMapData = require('./_getMapData');
+
+/**
+ * Removes `key` and its value from the map.
+ *
+ * @private
+ * @name delete
+ * @memberOf MapCache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function mapCacheDelete(key) {
+ var result = getMapData(this, key)['delete'](key);
+ this.size -= result ? 1 : 0;
+ return result;
+}
+
+module.exports = mapCacheDelete;
+
+},{'./_getMapData':161}],195:[function(require,module,exports){
+var getMapData = require('./_getMapData');
+
+/**
+ * Gets the map value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf MapCache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+}
+
+module.exports = mapCacheGet;
+
+},{'./_getMapData':161}],196:[function(require,module,exports){
+var getMapData = require('./_getMapData');
+
+/**
+ * Checks if a map value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf MapCache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+}
+
+module.exports = mapCacheHas;
+
+},{'./_getMapData':161}],197:[function(require,module,exports){
+var getMapData = require('./_getMapData');
+
+/**
+ * Sets the map `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf MapCache
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the map cache instance.
+ */
+function mapCacheSet(key, value) {
+ var data = getMapData(this, key),
+ size = data.size;
+
+ data.set(key, value);
+ this.size += data.size == size ? 0 : 1;
+ return this;
+}
+
+module.exports = mapCacheSet;
+
+},{'./_getMapData':161}],198:[function(require,module,exports){
+/**
+ * Converts `map` to its key-value pairs.
+ *
+ * @private
+ * @param {Object} map The map to convert.
+ * @returns {Array} Returns the key-value pairs.
+ */
+function mapToArray(map) {
+ var index = -1,
+ result = Array(map.size);
+
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+}
+
+module.exports = mapToArray;
+
+},{}],199:[function(require,module,exports){
+/**
+ * A specialized version of `matchesProperty` for source values suitable
+ * for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new spec function.
+ */
+function matchesStrictComparable(key, srcValue) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === srcValue &&
+ (srcValue !== undefined || (key in Object(object)));
+ };
+}
+
+module.exports = matchesStrictComparable;
+
+},{}],200:[function(require,module,exports){
+var memoize = require('./memoize');
+
+/** Used as the maximum memoize cache size. */
+var MAX_MEMOIZE_SIZE = 500;
+
+/**
+ * A specialized version of `_.memoize` which clears the memoized function's
+ * cache when it exceeds `MAX_MEMOIZE_SIZE`.
+ *
+ * @private
+ * @param {Function} func The function to have its output memoized.
+ * @returns {Function} Returns the new memoized function.
+ */
+function memoizeCapped(func) {
+ var result = memoize(func, function(key) {
+ if (cache.size === MAX_MEMOIZE_SIZE) {
+ cache.clear();
+ }
+ return key;
+ });
+
+ var cache = result.cache;
+ return result;
+}
+
+module.exports = memoizeCapped;
+
+},{'./memoize':265}],201:[function(require,module,exports){
+var getNative = require('./_getNative');
+
+/* Built-in method references that are verified to be native. */
+var nativeCreate = getNative(Object, 'create');
+
+module.exports = nativeCreate;
+
+},{'./_getNative':163}],202:[function(require,module,exports){
+var overArg = require('./_overArg');
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeKeys = overArg(Object.keys, Object);
+
+module.exports = nativeKeys;
+
+},{'./_overArg':206}],203:[function(require,module,exports){
+/**
+ * This function is like
+ * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * except that it includes inherited enumerable properties.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function nativeKeysIn(object) {
+ var result = [];
+ if (object != null) {
+ for (var key in Object(object)) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+module.exports = nativeKeysIn;
+
+},{}],204:[function(require,module,exports){
+var freeGlobal = require('./_freeGlobal');
+
+/** Detect free variable `exports`. */
+var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
+
+/** Detect free variable `module`. */
+var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
+
+/** Detect the popular CommonJS extension `module.exports`. */
+var moduleExports = freeModule && freeModule.exports === freeExports;
+
+/** Detect free variable `process` from Node.js. */
+var freeProcess = moduleExports && freeGlobal.process;
+
+/** Used to access faster Node.js helpers. */
+var nodeUtil = (function() {
+ try {
+ // Use `util.types` for Node.js 10+.
+ var types = freeModule && freeModule.require && freeModule.require('util').types;
+
+ if (types) {
+ return types;
+ }
+
+ // Legacy `process.binding('util')` for Node.js < 10.
+ return freeProcess && freeProcess.binding && freeProcess.binding('util');
+ } catch (e) {}
+}());
+
+module.exports = nodeUtil;
+
+},{'./_freeGlobal':158}],205:[function(require,module,exports){
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var nativeObjectToString = objectProto.toString;
+
+/**
+ * Converts `value` to a string using `Object.prototype.toString`.
+ *
+ * @private
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ */
+function objectToString(value) {
+ return nativeObjectToString.call(value);
+}
+
+module.exports = objectToString;
+
+},{}],206:[function(require,module,exports){
+/**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+}
+
+module.exports = overArg;
+
+},{}],207:[function(require,module,exports){
+var apply = require('./_apply');
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeMax = Math.max;
+
+/**
+ * A specialized version of `baseRest` which transforms the rest array.
+ *
+ * @private
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @param {Function} transform The rest array transform.
+ * @returns {Function} Returns the new function.
+ */
+function overRest(func, start, transform) {
+ start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ array = Array(length);
+
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = transform(array);
+ return apply(func, this, otherArgs);
+ };
+}
+
+module.exports = overRest;
+
+},{'./_apply':63}],208:[function(require,module,exports){
+var freeGlobal = require('./_freeGlobal');
+
+/** Detect free variable `self`. */
+var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
+
+/** Used as a reference to the global object. */
+var root = freeGlobal || freeSelf || Function('return this')();
+
+module.exports = root;
+
+},{'./_freeGlobal':158}],209:[function(require,module,exports){
+/**
+ * Gets the value at `key`, unless `key` is "__proto__".
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the property to get.
+ * @returns {*} Returns the property value.
+ */
+function safeGet(object, key) {
+ return key == '__proto__'
+ ? undefined
+ : object[key];
+}
+
+module.exports = safeGet;
+
+},{}],210:[function(require,module,exports){
+/** Used to stand-in for `undefined` hash values. */
+var HASH_UNDEFINED = '__lodash_hash_undefined__';
+
+/**
+ * Adds `value` to the array cache.
+ *
+ * @private
+ * @name add
+ * @memberOf SetCache
+ * @alias push
+ * @param {*} value The value to cache.
+ * @returns {Object} Returns the cache instance.
+ */
+function setCacheAdd(value) {
+ this.__data__.set(value, HASH_UNDEFINED);
+ return this;
+}
+
+module.exports = setCacheAdd;
+
+},{}],211:[function(require,module,exports){
+/**
+ * Checks if `value` is in the array cache.
+ *
+ * @private
+ * @name has
+ * @memberOf SetCache
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `true` if `value` is found, else `false`.
+ */
+function setCacheHas(value) {
+ return this.__data__.has(value);
+}
+
+module.exports = setCacheHas;
+
+},{}],212:[function(require,module,exports){
+/**
+ * Converts `set` to an array of its values.
+ *
+ * @private
+ * @param {Object} set The set to convert.
+ * @returns {Array} Returns the values.
+ */
+function setToArray(set) {
+ var index = -1,
+ result = Array(set.size);
+
+ set.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+}
+
+module.exports = setToArray;
+
+},{}],213:[function(require,module,exports){
+var baseSetToString = require('./_baseSetToString'),
+ shortOut = require('./_shortOut');
+
+/**
+ * Sets the `toString` method of `func` to return `string`.
+ *
+ * @private
+ * @param {Function} func The function to modify.
+ * @param {Function} string The `toString` result.
+ * @returns {Function} Returns `func`.
+ */
+var setToString = shortOut(baseSetToString);
+
+module.exports = setToString;
+
+},{'./_baseSetToString':123,'./_shortOut':214}],214:[function(require,module,exports){
+/** Used to detect hot functions by number of calls within a span of milliseconds. */
+var HOT_COUNT = 800,
+ HOT_SPAN = 16;
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeNow = Date.now;
+
+/**
+ * Creates a function that'll short out and invoke `identity` instead
+ * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
+ * milliseconds.
+ *
+ * @private
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new shortable function.
+ */
+function shortOut(func) {
+ var count = 0,
+ lastCalled = 0;
+
+ return function() {
+ var stamp = nativeNow(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return arguments[0];
+ }
+ } else {
+ count = 0;
+ }
+ return func.apply(undefined, arguments);
+ };
+}
+
+module.exports = shortOut;
+
+},{}],215:[function(require,module,exports){
+var ListCache = require('./_ListCache');
+
+/**
+ * Removes all key-value entries from the stack.
+ *
+ * @private
+ * @name clear
+ * @memberOf Stack
+ */
+function stackClear() {
+ this.__data__ = new ListCache;
+ this.size = 0;
+}
+
+module.exports = stackClear;
+
+},{'./_ListCache':53}],216:[function(require,module,exports){
+/**
+ * Removes `key` and its value from the stack.
+ *
+ * @private
+ * @name delete
+ * @memberOf Stack
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed, else `false`.
+ */
+function stackDelete(key) {
+ var data = this.__data__,
+ result = data['delete'](key);
+
+ this.size = data.size;
+ return result;
+}
+
+module.exports = stackDelete;
+
+},{}],217:[function(require,module,exports){
+/**
+ * Gets the stack value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf Stack
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the entry value.
+ */
+function stackGet(key) {
+ return this.__data__.get(key);
+}
+
+module.exports = stackGet;
+
+},{}],218:[function(require,module,exports){
+/**
+ * Checks if a stack value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf Stack
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+function stackHas(key) {
+ return this.__data__.has(key);
+}
+
+module.exports = stackHas;
+
+},{}],219:[function(require,module,exports){
+var ListCache = require('./_ListCache'),
+ Map = require('./_Map'),
+ MapCache = require('./_MapCache');
+
+/** Used as the size to enable large array optimizations. */
+var LARGE_ARRAY_SIZE = 200;
+
+/**
+ * Sets the stack `key` to `value`.
+ *
+ * @private
+ * @name set
+ * @memberOf Stack
+ * @param {string} key The key of the value to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns the stack cache instance.
+ */
+function stackSet(key, value) {
+ var data = this.__data__;
+ if (data instanceof ListCache) {
+ var pairs = data.__data__;
+ if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
+ pairs.push([key, value]);
+ this.size = ++data.size;
+ return this;
+ }
+ data = this.__data__ = new MapCache(pairs);
+ }
+ data.set(key, value);
+ this.size = data.size;
+ return this;
+}
+
+module.exports = stackSet;
+
+},{'./_ListCache':53,'./_Map':54,'./_MapCache':55}],220:[function(require,module,exports){
+/**
+ * A specialized version of `_.indexOf` which performs strict equality
+ * comparisons of values, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function strictIndexOf(array, value, fromIndex) {
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+module.exports = strictIndexOf;
+
+},{}],221:[function(require,module,exports){
+var asciiSize = require('./_asciiSize'),
+ hasUnicode = require('./_hasUnicode'),
+ unicodeSize = require('./_unicodeSize');
+
+/**
+ * Gets the number of symbols in `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the string size.
+ */
+function stringSize(string) {
+ return hasUnicode(string)
+ ? unicodeSize(string)
+ : asciiSize(string);
+}
+
+module.exports = stringSize;
+
+},{'./_asciiSize':73,'./_hasUnicode':171,'./_unicodeSize':225}],222:[function(require,module,exports){
+var memoizeCapped = require('./_memoizeCapped');
+
+/** Used to match property names within property paths. */
+var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
+
+/** Used to match backslashes in property paths. */
+var reEscapeChar = /\\(\\)?/g;
+
+/**
+ * Converts `string` to a property path array.
+ *
+ * @private
+ * @param {string} string The string to convert.
+ * @returns {Array} Returns the property path array.
+ */
+var stringToPath = memoizeCapped(function(string) {
+ var result = [];
+ if (string.charCodeAt(0) === 46 /* . */) {
+ result.push('');
+ }
+ string.replace(rePropName, function(match, number, quote, subString) {
+ result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+});
+
+module.exports = stringToPath;
+
+},{'./_memoizeCapped':200}],223:[function(require,module,exports){
+var isSymbol = require('./isSymbol');
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0;
+
+/**
+ * Converts `value` to a string key if it's not a string or symbol.
+ *
+ * @private
+ * @param {*} value The value to inspect.
+ * @returns {string|symbol} Returns the key.
+ */
+function toKey(value) {
+ if (typeof value == 'string' || isSymbol(value)) {
+ return value;
+ }
+ var result = (value + '');
+ return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
+}
+
+module.exports = toKey;
+
+},{'./isSymbol':256}],224:[function(require,module,exports){
+/** Used for built-in method references. */
+var funcProto = Function.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var funcToString = funcProto.toString;
+
+/**
+ * Converts `func` to its source code.
+ *
+ * @private
+ * @param {Function} func The function to convert.
+ * @returns {string} Returns the source code.
+ */
+function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {}
+ try {
+ return (func + '');
+ } catch (e) {}
+ }
+ return '';
+}
+
+module.exports = toSource;
+
+},{}],225:[function(require,module,exports){
+/** Used to compose unicode character classes. */
+var rsAstralRange = '\\ud800-\\udfff',
+ rsComboMarksRange = '\\u0300-\\u036f',
+ reComboHalfMarksRange = '\\ufe20-\\ufe2f',
+ rsComboSymbolsRange = '\\u20d0-\\u20ff',
+ rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
+ rsVarRange = '\\ufe0e\\ufe0f';
+
+/** Used to compose unicode capture groups. */
+var rsAstral = '[' + rsAstralRange + ']',
+ rsCombo = '[' + rsComboRange + ']',
+ rsFitz = '\\ud83c[\\udffb-\\udfff]',
+ rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
+ rsNonAstral = '[^' + rsAstralRange + ']',
+ rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
+ rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
+ rsZWJ = '\\u200d';
+
+/** Used to compose unicode regexes. */
+var reOptMod = rsModifier + '?',
+ rsOptVar = '[' + rsVarRange + ']?',
+ rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
+ rsSeq = rsOptVar + reOptMod + rsOptJoin,
+ rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
+
+/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
+var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
+
+/**
+ * Gets the size of a Unicode `string`.
+ *
+ * @private
+ * @param {string} string The string inspect.
+ * @returns {number} Returns the string size.
+ */
+function unicodeSize(string) {
+ var result = reUnicode.lastIndex = 0;
+ while (reUnicode.test(string)) {
+ ++result;
+ }
+ return result;
+}
+
+module.exports = unicodeSize;
+
+},{}],226:[function(require,module,exports){
+var baseClone = require('./_baseClone');
+
+/** Used to compose bitmasks for cloning. */
+var CLONE_SYMBOLS_FLAG = 4;
+
+/**
+ * Creates a shallow clone of `value`.
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
+ * and supports cloning arrays, array buffers, booleans, date objects, maps,
+ * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
+ * arrays. The own enumerable properties of `arguments` objects are cloned
+ * as plain objects. An empty object is returned for uncloneable values such
+ * as error objects, functions, DOM nodes, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @returns {*} Returns the cloned value.
+ * @see _.cloneDeep
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var shallow = _.clone(objects);
+ * console.log(shallow[0] === objects[0]);
+ * // => true
+ */
+function clone(value) {
+ return baseClone(value, CLONE_SYMBOLS_FLAG);
+}
+
+module.exports = clone;
+
+},{'./_baseClone':80}],227:[function(require,module,exports){
+var baseClone = require('./_baseClone');
+
+/** Used to compose bitmasks for cloning. */
+var CLONE_DEEP_FLAG = 1,
+ CLONE_SYMBOLS_FLAG = 4;
+
+/**
+ * This method is like `_.clone` except that it recursively clones `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.0.0
+ * @category Lang
+ * @param {*} value The value to recursively clone.
+ * @returns {*} Returns the deep cloned value.
+ * @see _.clone
+ * @example
+ *
+ * var objects = [{ 'a': 1 }, { 'b': 2 }];
+ *
+ * var deep = _.cloneDeep(objects);
+ * console.log(deep[0] === objects[0]);
+ * // => false
+ */
+function cloneDeep(value) {
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
+}
+
+module.exports = cloneDeep;
+
+},{'./_baseClone':80}],228:[function(require,module,exports){
+/**
+ * Creates a function that returns `value`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Util
+ * @param {*} value The value to return from the new function.
+ * @returns {Function} Returns the new constant function.
+ * @example
+ *
+ * var objects = _.times(2, _.constant({ 'a': 1 }));
+ *
+ * console.log(objects);
+ * // => [{ 'a': 1 }, { 'a': 1 }]
+ *
+ * console.log(objects[0] === objects[1]);
+ * // => true
+ */
+function constant(value) {
+ return function() {
+ return value;
+ };
+}
+
+module.exports = constant;
+
+},{}],229:[function(require,module,exports){
+var baseRest = require('./_baseRest'),
+ eq = require('./eq'),
+ isIterateeCall = require('./_isIterateeCall'),
+ keysIn = require('./keysIn');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Assigns own and inherited enumerable string keyed properties of source
+ * objects to the destination object for all destination properties that
+ * resolve to `undefined`. Source objects are applied from left to right.
+ * Once a property is set, additional values of the same property are ignored.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @see _.defaultsDeep
+ * @example
+ *
+ * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
+ * // => { 'a': 1, 'b': 2 }
+ */
+var defaults = baseRest(function(object, sources) {
+ object = Object(object);
+
+ var index = -1;
+ var length = sources.length;
+ var guard = length > 2 ? sources[2] : undefined;
+
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ length = 1;
+ }
+
+ while (++index < length) {
+ var source = sources[index];
+ var props = keysIn(source);
+ var propsIndex = -1;
+ var propsLength = props.length;
+
+ while (++propsIndex < propsLength) {
+ var key = props[propsIndex];
+ var value = object[key];
+
+ if (value === undefined ||
+ (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
+ object[key] = source[key];
+ }
+ }
+ }
+
+ return object;
+});
+
+module.exports = defaults;
+
+},{'./_baseRest':121,'./_isIterateeCall':182,'./eq':231,'./keysIn':260}],230:[function(require,module,exports){
+module.exports = require('./forEach');
+
+},{'./forEach':236}],231:[function(require,module,exports){
+/**
+ * Performs a
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * comparison between two values to determine if they are equivalent.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ * var other = { 'a': 1 };
+ *
+ * _.eq(object, object);
+ * // => true
+ *
+ * _.eq(object, other);
+ * // => false
+ *
+ * _.eq('a', 'a');
+ * // => true
+ *
+ * _.eq('a', Object('a'));
+ * // => false
+ *
+ * _.eq(NaN, NaN);
+ * // => true
+ */
+function eq(value, other) {
+ return value === other || (value !== value && other !== other);
+}
+
+module.exports = eq;
+
+},{}],232:[function(require,module,exports){
+var arrayFilter = require('./_arrayFilter'),
+ baseFilter = require('./_baseFilter'),
+ baseIteratee = require('./_baseIteratee'),
+ isArray = require('./isArray');
+
+/**
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * **Note:** Unlike `_.remove`, this method returns a new array.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ * @see _.reject
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, function(o) { return !o.active; });
+ * // => objects for ['fred']
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.filter(users, { 'age': 36, 'active': true });
+ * // => objects for ['barney']
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.filter(users, ['active', false]);
+ * // => objects for ['fred']
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.filter(users, 'active');
+ * // => objects for ['barney']
+ */
+function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, baseIteratee(predicate, 3));
+}
+
+module.exports = filter;
+
+},{'./_arrayFilter':65,'./_baseFilter':84,'./_baseIteratee':105,'./isArray':243}],233:[function(require,module,exports){
+var createFind = require('./_createFind'),
+ findIndex = require('./findIndex');
+
+/**
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.find(users, function(o) { return o.age < 40; });
+ * // => object for 'barney'
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.find(users, { 'age': 1, 'active': true });
+ * // => object for 'pebbles'
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.find(users, ['active', false]);
+ * // => object for 'fred'
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.find(users, 'active');
+ * // => object for 'barney'
+ */
+var find = createFind(findIndex);
+
+module.exports = find;
+
+},{'./_createFind':150,'./findIndex':234}],234:[function(require,module,exports){
+var baseFindIndex = require('./_baseFindIndex'),
+ baseIteratee = require('./_baseIteratee'),
+ toInteger = require('./toInteger');
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeMax = Math.max;
+
+/**
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.1.0
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {Function} [predicate=_.identity] The function invoked per iteration.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(o) { return o.user == 'barney'; });
+ * // => 0
+ *
+ * // The `_.matches` iteratee shorthand.
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // The `_.matchesProperty` iteratee shorthand.
+ * _.findIndex(users, ['active', false]);
+ * // => 0
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.findIndex(users, 'active');
+ * // => 2
+ */
+function findIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseFindIndex(array, baseIteratee(predicate, 3), index);
+}
+
+module.exports = findIndex;
+
+},{'./_baseFindIndex':85,'./_baseIteratee':105,'./toInteger':280}],235:[function(require,module,exports){
+var baseFlatten = require('./_baseFlatten');
+
+/**
+ * Flattens `array` a single level deep.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, [3, [4]], 5]]);
+ * // => [1, 2, [3, [4]], 5]
+ */
+function flatten(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, 1) : [];
+}
+
+module.exports = flatten;
+
+},{'./_baseFlatten':86}],236:[function(require,module,exports){
+var arrayEach = require('./_arrayEach'),
+ baseEach = require('./_baseEach'),
+ castFunction = require('./_castFunction'),
+ isArray = require('./isArray');
+
+/**
+ * Iterates over elements of `collection` and invokes `iteratee` for each element.
+ * The iteratee is invoked with three arguments: (value, index|key, collection).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * **Note:** As with other "Collections" methods, objects with a "length"
+ * property are iterated like arrays. To avoid this behavior use `_.forIn`
+ * or `_.forOwn` for object iteration.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @alias each
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array|Object} Returns `collection`.
+ * @see _.forEachRight
+ * @example
+ *
+ * _.forEach([1, 2], function(value) {
+ * console.log(value);
+ * });
+ * // => Logs `1` then `2`.
+ *
+ * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a' then 'b' (iteration order is not guaranteed).
+ */
+function forEach(collection, iteratee) {
+ var func = isArray(collection) ? arrayEach : baseEach;
+ return func(collection, castFunction(iteratee));
+}
+
+module.exports = forEach;
+
+},{'./_arrayEach':64,'./_baseEach':82,'./_castFunction':132,'./isArray':243}],237:[function(require,module,exports){
+var baseFor = require('./_baseFor'),
+ castFunction = require('./_castFunction'),
+ keysIn = require('./keysIn');
+
+/**
+ * Iterates over own and inherited enumerable string keyed properties of an
+ * object and invokes `iteratee` for each property. The iteratee is invoked
+ * with three arguments: (value, key, object). Iteratee functions may exit
+ * iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ * @see _.forInRight
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
+ */
+function forIn(object, iteratee) {
+ return object == null
+ ? object
+ : baseFor(object, castFunction(iteratee), keysIn);
+}
+
+module.exports = forIn;
+
+},{'./_baseFor':87,'./_castFunction':132,'./keysIn':260}],238:[function(require,module,exports){
+var baseGet = require('./_baseGet');
+
+/**
+ * Gets the value at `path` of `object`. If the resolved value is
+ * `undefined`, the `defaultValue` is returned in its place.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.7.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.get(object, 'a[0].b.c');
+ * // => 3
+ *
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
+ *
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
+ */
+function get(object, path, defaultValue) {
+ var result = object == null ? undefined : baseGet(object, path);
+ return result === undefined ? defaultValue : result;
+}
+
+module.exports = get;
+
+},{'./_baseGet':89}],239:[function(require,module,exports){
+var baseHas = require('./_baseHas'),
+ hasPath = require('./_hasPath');
+
+/**
+ * Checks if `path` is a direct property of `object`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = { 'a': { 'b': 2 } };
+ * var other = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.has(object, 'a');
+ * // => true
+ *
+ * _.has(object, 'a.b');
+ * // => true
+ *
+ * _.has(object, ['a', 'b']);
+ * // => true
+ *
+ * _.has(other, 'a');
+ * // => false
+ */
+function has(object, path) {
+ return object != null && hasPath(object, path, baseHas);
+}
+
+module.exports = has;
+
+},{'./_baseHas':93,'./_hasPath':170}],240:[function(require,module,exports){
+var baseHasIn = require('./_baseHasIn'),
+ hasPath = require('./_hasPath');
+
+/**
+ * Checks if `path` is a direct or inherited property of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` exists, else `false`.
+ * @example
+ *
+ * var object = _.create({ 'a': _.create({ 'b': 2 }) });
+ *
+ * _.hasIn(object, 'a');
+ * // => true
+ *
+ * _.hasIn(object, 'a.b');
+ * // => true
+ *
+ * _.hasIn(object, ['a', 'b']);
+ * // => true
+ *
+ * _.hasIn(object, 'b');
+ * // => false
+ */
+function hasIn(object, path) {
+ return object != null && hasPath(object, path, baseHasIn);
+}
+
+module.exports = hasIn;
+
+},{'./_baseHasIn':94,'./_hasPath':170}],241:[function(require,module,exports){
+/**
+ * This method returns the first argument it receives.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'a': 1 };
+ *
+ * console.log(_.identity(object) === object);
+ * // => true
+ */
+function identity(value) {
+ return value;
+}
+
+module.exports = identity;
+
+},{}],242:[function(require,module,exports){
+var baseIsArguments = require('./_baseIsArguments'),
+ isObjectLike = require('./isObjectLike');
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Built-in value references. */
+var propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
+/**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ * else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
+ return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
+ !propertyIsEnumerable.call(value, 'callee');
+};
+
+module.exports = isArguments;
+
+},{'./_baseIsArguments':96,'./isObjectLike':252}],243:[function(require,module,exports){
+/**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+var isArray = Array.isArray;
+
+module.exports = isArray;
+
+},{}],244:[function(require,module,exports){
+var isFunction = require('./isFunction'),
+ isLength = require('./isLength');
+
+/**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+}
+
+module.exports = isArrayLike;
+
+},{'./isFunction':248,'./isLength':249}],245:[function(require,module,exports){
+var isArrayLike = require('./isArrayLike'),
+ isObjectLike = require('./isObjectLike');
+
+/**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ * else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+}
+
+module.exports = isArrayLikeObject;
+
+},{'./isArrayLike':244,'./isObjectLike':252}],246:[function(require,module,exports){
+var root = require('./_root'),
+ stubFalse = require('./stubFalse');
+
+/** Detect free variable `exports`. */
+var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
+
+/** Detect free variable `module`. */
+var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
+
+/** Detect the popular CommonJS extension `module.exports`. */
+var moduleExports = freeModule && freeModule.exports === freeExports;
+
+/** Built-in value references. */
+var Buffer = moduleExports ? root.Buffer : undefined;
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;
+
+/**
+ * Checks if `value` is a buffer.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
+ * @example
+ *
+ * _.isBuffer(new Buffer(2));
+ * // => true
+ *
+ * _.isBuffer(new Uint8Array(2));
+ * // => false
+ */
+var isBuffer = nativeIsBuffer || stubFalse;
+
+module.exports = isBuffer;
+
+},{'./_root':208,'./stubFalse':278}],247:[function(require,module,exports){
+var baseKeys = require('./_baseKeys'),
+ getTag = require('./_getTag'),
+ isArguments = require('./isArguments'),
+ isArray = require('./isArray'),
+ isArrayLike = require('./isArrayLike'),
+ isBuffer = require('./isBuffer'),
+ isPrototype = require('./_isPrototype'),
+ isTypedArray = require('./isTypedArray');
+
+/** `Object#toString` result references. */
+var mapTag = '[object Map]',
+ setTag = '[object Set]';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Checks if `value` is an empty object, collection, map, or set.
+ *
+ * Objects are considered empty if they have no own enumerable string keyed
+ * properties.
+ *
+ * Array-like values such as `arguments` objects, arrays, buffers, strings, or
+ * jQuery-like collections are considered empty if they have a `length` of `0`.
+ * Similarly, maps and sets are considered empty if they have a `size` of `0`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty(null);
+ * // => true
+ *
+ * _.isEmpty(true);
+ * // => true
+ *
+ * _.isEmpty(1);
+ * // => true
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
+ */
+function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) &&
+ (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
+ isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+ return !value.length;
+ }
+ var tag = getTag(value);
+ if (tag == mapTag || tag == setTag) {
+ return !value.size;
+ }
+ if (isPrototype(value)) {
+ return !baseKeys(value).length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+module.exports = isEmpty;
+
+},{'./_baseKeys':106,'./_getTag':168,'./_isPrototype':186,'./isArguments':242,'./isArray':243,'./isArrayLike':244,'./isBuffer':246,'./isTypedArray':257}],248:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ isObject = require('./isObject');
+
+/** `Object#toString` result references. */
+var asyncTag = '[object AsyncFunction]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ proxyTag = '[object Proxy]';
+
+/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ if (!isObject(value)) {
+ return false;
+ }
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 9 which returns 'object' for typed arrays and other constructors.
+ var tag = baseGetTag(value);
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+}
+
+module.exports = isFunction;
+
+},{'./_baseGetTag':91,'./isObject':251}],249:[function(require,module,exports){
+/** Used as references for various `Number` constants. */
+var MAX_SAFE_INTEGER = 9007199254740991;
+
+/**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+}
+
+module.exports = isLength;
+
+},{}],250:[function(require,module,exports){
+var baseIsMap = require('./_baseIsMap'),
+ baseUnary = require('./_baseUnary'),
+ nodeUtil = require('./_nodeUtil');
+
+/* Node.js helper references. */
+var nodeIsMap = nodeUtil && nodeUtil.isMap;
+
+/**
+ * Checks if `value` is classified as a `Map` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a map, else `false`.
+ * @example
+ *
+ * _.isMap(new Map);
+ * // => true
+ *
+ * _.isMap(new WeakMap);
+ * // => false
+ */
+var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+
+module.exports = isMap;
+
+},{'./_baseIsMap':99,'./_baseUnary':127,'./_nodeUtil':204}],251:[function(require,module,exports){
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == 'object' || type == 'function');
+}
+
+module.exports = isObject;
+
+},{}],252:[function(require,module,exports){
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return value != null && typeof value == 'object';
+}
+
+module.exports = isObjectLike;
+
+},{}],253:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ getPrototype = require('./_getPrototype'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var objectTag = '[object Object]';
+
+/** Used for built-in method references. */
+var funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var funcToString = funcProto.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Used to infer the `Object` constructor. */
+var objectCtorString = funcToString.call(Object);
+
+/**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.8.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+function isPlainObject(value) {
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
+ return typeof Ctor == 'function' && Ctor instanceof Ctor &&
+ funcToString.call(Ctor) == objectCtorString;
+}
+
+module.exports = isPlainObject;
+
+},{'./_baseGetTag':91,'./_getPrototype':164,'./isObjectLike':252}],254:[function(require,module,exports){
+var baseIsSet = require('./_baseIsSet'),
+ baseUnary = require('./_baseUnary'),
+ nodeUtil = require('./_nodeUtil');
+
+/* Node.js helper references. */
+var nodeIsSet = nodeUtil && nodeUtil.isSet;
+
+/**
+ * Checks if `value` is classified as a `Set` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.3.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a set, else `false`.
+ * @example
+ *
+ * _.isSet(new Set);
+ * // => true
+ *
+ * _.isSet(new WeakSet);
+ * // => false
+ */
+var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+
+module.exports = isSet;
+
+},{'./_baseIsSet':103,'./_baseUnary':127,'./_nodeUtil':204}],255:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ isArray = require('./isArray'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var stringTag = '[object String]';
+
+/**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
+}
+
+module.exports = isString;
+
+},{'./_baseGetTag':91,'./isArray':243,'./isObjectLike':252}],256:[function(require,module,exports){
+var baseGetTag = require('./_baseGetTag'),
+ isObjectLike = require('./isObjectLike');
+
+/** `Object#toString` result references. */
+var symbolTag = '[object Symbol]';
+
+/**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && baseGetTag(value) == symbolTag);
+}
+
+module.exports = isSymbol;
+
+},{'./_baseGetTag':91,'./isObjectLike':252}],257:[function(require,module,exports){
+var baseIsTypedArray = require('./_baseIsTypedArray'),
+ baseUnary = require('./_baseUnary'),
+ nodeUtil = require('./_nodeUtil');
+
+/* Node.js helper references. */
+var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+
+/**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+
+module.exports = isTypedArray;
+
+},{'./_baseIsTypedArray':104,'./_baseUnary':127,'./_nodeUtil':204}],258:[function(require,module,exports){
+/**
+ * Checks if `value` is `undefined`.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ *
+ * _.isUndefined(null);
+ * // => false
+ */
+function isUndefined(value) {
+ return value === undefined;
+}
+
+module.exports = isUndefined;
+
+},{}],259:[function(require,module,exports){
+var arrayLikeKeys = require('./_arrayLikeKeys'),
+ baseKeys = require('./_baseKeys'),
+ isArrayLike = require('./isArrayLike');
+
+/**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+}
+
+module.exports = keys;
+
+},{'./_arrayLikeKeys':68,'./_baseKeys':106,'./isArrayLike':244}],260:[function(require,module,exports){
+var arrayLikeKeys = require('./_arrayLikeKeys'),
+ baseKeysIn = require('./_baseKeysIn'),
+ isArrayLike = require('./isArrayLike');
+
+/**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+}
+
+module.exports = keysIn;
+
+},{'./_arrayLikeKeys':68,'./_baseKeysIn':107,'./isArrayLike':244}],261:[function(require,module,exports){
+/**
+ * Gets the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
+ *
+ * _.last([1, 2, 3]);
+ * // => 3
+ */
+function last(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? array[length - 1] : undefined;
+}
+
+module.exports = last;
+
+},{}],262:[function(require,module,exports){
+var arrayMap = require('./_arrayMap'),
+ baseIteratee = require('./_baseIteratee'),
+ baseMap = require('./_baseMap'),
+ isArray = require('./isArray');
+
+/**
+ * Creates an array of values by running each element in `collection` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
+ * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
+ * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
+ * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * _.map([4, 8], square);
+ * // => [16, 64]
+ *
+ * _.map({ 'a': 4, 'b': 8 }, square);
+ * // => [16, 64] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
+ */
+function map(collection, iteratee) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, baseIteratee(iteratee, 3));
+}
+
+module.exports = map;
+
+},{'./_arrayMap':69,'./_baseIteratee':105,'./_baseMap':109,'./isArray':243}],263:[function(require,module,exports){
+var baseAssignValue = require('./_baseAssignValue'),
+ baseForOwn = require('./_baseForOwn'),
+ baseIteratee = require('./_baseIteratee');
+
+/**
+ * Creates an object with the same keys as `object` and values generated
+ * by running each own enumerable string keyed property of `object` thru
+ * `iteratee`. The iteratee is invoked with three arguments:
+ * (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @returns {Object} Returns the new mapped object.
+ * @see _.mapKeys
+ * @example
+ *
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
+ *
+ * _.mapValues(users, function(o) { return o.age; });
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ */
+function mapValues(object, iteratee) {
+ var result = {};
+ iteratee = baseIteratee(iteratee, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ baseAssignValue(result, key, iteratee(value, key, object));
+ });
+ return result;
+}
+
+module.exports = mapValues;
+
+},{'./_baseAssignValue':79,'./_baseForOwn':88,'./_baseIteratee':105}],264:[function(require,module,exports){
+var baseExtremum = require('./_baseExtremum'),
+ baseGt = require('./_baseGt'),
+ identity = require('./identity');
+
+/**
+ * Computes the maximum value of `array`. If `array` is empty or falsey,
+ * `undefined` is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * _.max([4, 2, 8, 6]);
+ * // => 8
+ *
+ * _.max([]);
+ * // => undefined
+ */
+function max(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, baseGt)
+ : undefined;
+}
+
+module.exports = max;
+
+},{'./_baseExtremum':83,'./_baseGt':92,'./identity':241}],265:[function(require,module,exports){
+var MapCache = require('./_MapCache');
+
+/** Error message constants. */
+var FUNC_ERROR_TEXT = 'Expected a function';
+
+/**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided, it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is used as the map cache key. The `func`
+ * is invoked with the `this` binding of the memoized function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the
+ * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
+ * method interface of `clear`, `delete`, `get`, `has`, and `set`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoized function.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2 };
+ * var other = { 'c': 3, 'd': 4 };
+ *
+ * var values = _.memoize(_.values);
+ * values(object);
+ * // => [1, 2]
+ *
+ * values(other);
+ * // => [3, 4]
+ *
+ * object.a = 2;
+ * values(object);
+ * // => [1, 2]
+ *
+ * // Modify the result cache.
+ * values.cache.set(object, ['a', 'b']);
+ * values(object);
+ * // => ['a', 'b']
+ *
+ * // Replace `_.memoize.Cache`.
+ * _.memoize.Cache = WeakMap;
+ */
+function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments,
+ key = resolver ? resolver.apply(this, args) : args[0],
+ cache = memoized.cache;
+
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result = func.apply(this, args);
+ memoized.cache = cache.set(key, result) || cache;
+ return result;
+ };
+ memoized.cache = new (memoize.Cache || MapCache);
+ return memoized;
+}
+
+// Expose `MapCache`.
+memoize.Cache = MapCache;
+
+module.exports = memoize;
+
+},{'./_MapCache':55}],266:[function(require,module,exports){
+var baseMerge = require('./_baseMerge'),
+ createAssigner = require('./_createAssigner');
+
+/**
+ * This method is like `_.assign` except that it recursively merges own and
+ * inherited enumerable string keyed properties of source objects into the
+ * destination object. Source properties that resolve to `undefined` are
+ * skipped if a destination value exists. Array and plain object properties
+ * are merged recursively. Other objects and value types are overridden by
+ * assignment. Source objects are applied from left to right. Subsequent
+ * sources overwrite property assignments of previous sources.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.5.0
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = {
+ * 'a': [{ 'b': 2 }, { 'd': 4 }]
+ * };
+ *
+ * var other = {
+ * 'a': [{ 'c': 3 }, { 'e': 5 }]
+ * };
+ *
+ * _.merge(object, other);
+ * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
+ */
+var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+});
+
+module.exports = merge;
+
+},{'./_baseMerge':112,'./_createAssigner':147}],267:[function(require,module,exports){
+var baseExtremum = require('./_baseExtremum'),
+ baseLt = require('./_baseLt'),
+ identity = require('./identity');
+
+/**
+ * Computes the minimum value of `array`. If `array` is empty or falsey,
+ * `undefined` is returned.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * _.min([4, 2, 8, 6]);
+ * // => 2
+ *
+ * _.min([]);
+ * // => undefined
+ */
+function min(array) {
+ return (array && array.length)
+ ? baseExtremum(array, identity, baseLt)
+ : undefined;
+}
+
+module.exports = min;
+
+},{'./_baseExtremum':83,'./_baseLt':108,'./identity':241}],268:[function(require,module,exports){
+var baseExtremum = require('./_baseExtremum'),
+ baseIteratee = require('./_baseIteratee'),
+ baseLt = require('./_baseLt');
+
+/**
+ * This method is like `_.min` except that it accepts `iteratee` which is
+ * invoked for each element in `array` to generate the criterion by which
+ * the value is ranked. The iteratee is invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Math
+ * @param {Array} array The array to iterate over.
+ * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * var objects = [{ 'n': 1 }, { 'n': 2 }];
+ *
+ * _.minBy(objects, function(o) { return o.n; });
+ * // => { 'n': 1 }
+ *
+ * // The `_.property` iteratee shorthand.
+ * _.minBy(objects, 'n');
+ * // => { 'n': 1 }
+ */
+function minBy(array, iteratee) {
+ return (array && array.length)
+ ? baseExtremum(array, baseIteratee(iteratee, 2), baseLt)
+ : undefined;
+}
+
+module.exports = minBy;
+
+},{'./_baseExtremum':83,'./_baseIteratee':105,'./_baseLt':108}],269:[function(require,module,exports){
+/**
+ * This method returns `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.3.0
+ * @category Util
+ * @example
+ *
+ * _.times(2, _.noop);
+ * // => [undefined, undefined]
+ */
+function noop() {
+ // No operation performed.
+}
+
+module.exports = noop;
+
+},{}],270:[function(require,module,exports){
+var root = require('./_root');
+
+/**
+ * Gets the timestamp of the number of milliseconds that have elapsed since
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Date
+ * @returns {number} Returns the timestamp.
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => Logs the number of milliseconds it took for the deferred invocation.
+ */
+var now = function() {
+ return root.Date.now();
+};
+
+module.exports = now;
+
+},{'./_root':208}],271:[function(require,module,exports){
+var basePick = require('./_basePick'),
+ flatRest = require('./_flatRest');
+
+/**
+ * Creates an object composed of the picked `object` properties.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {...(string|string[])} [paths] The property paths to pick.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': '2', 'c': 3 };
+ *
+ * _.pick(object, ['a', 'c']);
+ * // => { 'a': 1, 'c': 3 }
+ */
+var pick = flatRest(function(object, paths) {
+ return object == null ? {} : basePick(object, paths);
+});
+
+module.exports = pick;
+
+},{'./_basePick':115,'./_flatRest':157}],272:[function(require,module,exports){
+var baseProperty = require('./_baseProperty'),
+ basePropertyDeep = require('./_basePropertyDeep'),
+ isKey = require('./_isKey'),
+ toKey = require('./_toKey');
+
+/**
+ * Creates a function that returns the value at `path` of a given object.
+ *
+ * @static
+ * @memberOf _
+ * @since 2.4.0
+ * @category Util
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new accessor function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': 2 } },
+ * { 'a': { 'b': 1 } }
+ * ];
+ *
+ * _.map(objects, _.property('a.b'));
+ * // => [2, 1]
+ *
+ * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
+ * // => [1, 2]
+ */
+function property(path) {
+ return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
+}
+
+module.exports = property;
+
+},{'./_baseProperty':117,'./_basePropertyDeep':118,'./_isKey':183,'./_toKey':223}],273:[function(require,module,exports){
+var createRange = require('./_createRange');
+
+/**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to, but not including, `end`. A step of `-1` is used if a negative
+ * `start` is specified without an `end` or `step`. If `end` is not specified,
+ * it's set to `start` with `start` then set to `0`.
+ *
+ * **Note:** JavaScript follows the IEEE-754 standard for resolving
+ * floating-point values which can produce unexpected results.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the range of numbers.
+ * @see _.inRange, _.rangeRight
+ * @example
+ *
+ * _.range(4);
+ * // => [0, 1, 2, 3]
+ *
+ * _.range(-4);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 5);
+ * // => [1, 2, 3, 4]
+ *
+ * _.range(0, 20, 5);
+ * // => [0, 5, 10, 15]
+ *
+ * _.range(0, -4, -1);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.range(0);
+ * // => []
+ */
+var range = createRange();
+
+module.exports = range;
+
+},{'./_createRange':151}],274:[function(require,module,exports){
+var arrayReduce = require('./_arrayReduce'),
+ baseEach = require('./_baseEach'),
+ baseIteratee = require('./_baseIteratee'),
+ baseReduce = require('./_baseReduce'),
+ isArray = require('./isArray');
+
+/**
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` thru `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not given, the first element of `collection` is used as the initial
+ * value. The iteratee is invoked with four arguments:
+ * (accumulator, value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
+ * and `sortBy`
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @returns {*} Returns the accumulated value.
+ * @see _.reduceRight
+ * @example
+ *
+ * _.reduce([1, 2], function(sum, n) {
+ * return sum + n;
+ * }, 0);
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * return result;
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
+ */
+function reduce(collection, iteratee, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce,
+ initAccum = arguments.length < 3;
+
+ return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEach);
+}
+
+module.exports = reduce;
+
+},{'./_arrayReduce':71,'./_baseEach':82,'./_baseIteratee':105,'./_baseReduce':120,'./isArray':243}],275:[function(require,module,exports){
+var baseKeys = require('./_baseKeys'),
+ getTag = require('./_getTag'),
+ isArrayLike = require('./isArrayLike'),
+ isString = require('./isString'),
+ stringSize = require('./_stringSize');
+
+/** `Object#toString` result references. */
+var mapTag = '[object Map]',
+ setTag = '[object Set]';
+
+/**
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable string keyed properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @returns {number} Returns the collection size.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
+ */
+function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ return isString(collection) ? stringSize(collection) : collection.length;
+ }
+ var tag = getTag(collection);
+ if (tag == mapTag || tag == setTag) {
+ return collection.size;
+ }
+ return baseKeys(collection).length;
+}
+
+module.exports = size;
+
+},{'./_baseKeys':106,'./_getTag':168,'./_stringSize':221,'./isArrayLike':244,'./isString':255}],276:[function(require,module,exports){
+var baseFlatten = require('./_baseFlatten'),
+ baseOrderBy = require('./_baseOrderBy'),
+ baseRest = require('./_baseRest'),
+ isIterateeCall = require('./_isIterateeCall');
+
+/**
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection thru each iteratee. This method
+ * performs a stable sort, that is, it preserves the original sort order of
+ * equal elements. The iteratees are invoked with one argument: (value).
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {...(Function|Function[])} [iteratees=[_.identity]]
+ * The iteratees to sort by.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.sortBy(users, [function(o) { return o.user; }]);
+ * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
+ *
+ * _.sortBy(users, ['user', 'age']);
+ * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
+ */
+var sortBy = baseRest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees = [iteratees[0]];
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+});
+
+module.exports = sortBy;
+
+},{'./_baseFlatten':86,'./_baseOrderBy':114,'./_baseRest':121,'./_isIterateeCall':182}],277:[function(require,module,exports){
+/**
+ * This method returns a new empty array.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {Array} Returns the new empty array.
+ * @example
+ *
+ * var arrays = _.times(2, _.stubArray);
+ *
+ * console.log(arrays);
+ * // => [[], []]
+ *
+ * console.log(arrays[0] === arrays[1]);
+ * // => false
+ */
+function stubArray() {
+ return [];
+}
+
+module.exports = stubArray;
+
+},{}],278:[function(require,module,exports){
+/**
+ * This method returns `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.13.0
+ * @category Util
+ * @returns {boolean} Returns `false`.
+ * @example
+ *
+ * _.times(2, _.stubFalse);
+ * // => [false, false]
+ */
+function stubFalse() {
+ return false;
+}
+
+module.exports = stubFalse;
+
+},{}],279:[function(require,module,exports){
+var toNumber = require('./toNumber');
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0,
+ MAX_INTEGER = 1.7976931348623157e+308;
+
+/**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+}
+
+module.exports = toFinite;
+
+},{'./toNumber':281}],280:[function(require,module,exports){
+var toFinite = require('./toFinite');
+
+/**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+}
+
+module.exports = toInteger;
+
+},{'./toFinite':279}],281:[function(require,module,exports){
+var isObject = require('./isObject'),
+ isSymbol = require('./isSymbol');
+
+/** Used as references for various `Number` constants. */
+var NAN = 0 / 0;
+
+/** Used to match leading and trailing whitespace. */
+var reTrim = /^\s+|\s+$/g;
+
+/** Used to detect bad signed hexadecimal string values. */
+var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+/** Used to detect binary string values. */
+var reIsBinary = /^0b[01]+$/i;
+
+/** Used to detect octal string values. */
+var reIsOctal = /^0o[0-7]+$/i;
+
+/** Built-in method references without a dependency on `root`. */
+var freeParseInt = parseInt;
+
+/**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+}
+
+module.exports = toNumber;
+
+},{'./isObject':251,'./isSymbol':256}],282:[function(require,module,exports){
+var copyObject = require('./_copyObject'),
+ keysIn = require('./keysIn');
+
+/**
+ * Converts `value` to a plain object flattening inherited enumerable string
+ * keyed properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+}
+
+module.exports = toPlainObject;
+
+},{'./_copyObject':143,'./keysIn':260}],283:[function(require,module,exports){
+var baseToString = require('./_baseToString');
+
+/**
+ * Converts `value` to a string. An empty string is returned for `null`
+ * and `undefined` values. The sign of `-0` is preserved.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {string} Returns the converted string.
+ * @example
+ *
+ * _.toString(null);
+ * // => ''
+ *
+ * _.toString(-0);
+ * // => '-0'
+ *
+ * _.toString([1, 2, 3]);
+ * // => '1,2,3'
+ */
+function toString(value) {
+ return value == null ? '' : baseToString(value);
+}
+
+module.exports = toString;
+
+},{'./_baseToString':126}],284:[function(require,module,exports){
+var arrayEach = require('./_arrayEach'),
+ baseCreate = require('./_baseCreate'),
+ baseForOwn = require('./_baseForOwn'),
+ baseIteratee = require('./_baseIteratee'),
+ getPrototype = require('./_getPrototype'),
+ isArray = require('./isArray'),
+ isBuffer = require('./isBuffer'),
+ isFunction = require('./isFunction'),
+ isObject = require('./isObject'),
+ isTypedArray = require('./isTypedArray');
+
+/**
+ * An alternative to `_.reduce`; this method transforms `object` to a new
+ * `accumulator` object which is the result of running each of its own
+ * enumerable string keyed properties thru `iteratee`, with each invocation
+ * potentially mutating the `accumulator` object. If `accumulator` is not
+ * provided, a new object with the same `[[Prototype]]` will be used. The
+ * iteratee is invoked with four arguments: (accumulator, value, key, object).
+ * Iteratee functions may exit iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @since 1.3.0
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The custom accumulator value.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.transform([2, 3, 4], function(result, n) {
+ * result.push(n *= n);
+ * return n % 2 == 0;
+ * }, []);
+ * // => [4, 9]
+ *
+ * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
+ * (result[value] || (result[value] = [])).push(key);
+ * }, {});
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ */
+function transform(object, iteratee, accumulator) {
+ var isArr = isArray(object),
+ isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+
+ iteratee = baseIteratee(iteratee, 4);
+ if (accumulator == null) {
+ var Ctor = object && object.constructor;
+ if (isArrLike) {
+ accumulator = isArr ? new Ctor : [];
+ }
+ else if (isObject(object)) {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+ }
+ else {
+ accumulator = {};
+ }
+ }
+ (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ return iteratee(accumulator, value, index, object);
+ });
+ return accumulator;
+}
+
+module.exports = transform;
+
+},{'./_arrayEach':64,'./_baseCreate':81,'./_baseForOwn':88,'./_baseIteratee':105,'./_getPrototype':164,'./isArray':243,'./isBuffer':246,'./isFunction':248,'./isObject':251,'./isTypedArray':257}],285:[function(require,module,exports){
+var baseFlatten = require('./_baseFlatten'),
+ baseRest = require('./_baseRest'),
+ baseUniq = require('./_baseUniq'),
+ isArrayLikeObject = require('./isArrayLikeObject');
+
+/**
+ * Creates an array of unique values, in order, from all given arrays using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([2], [1, 2]);
+ * // => [2, 1]
+ */
+var union = baseRest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
+});
+
+module.exports = union;
+
+},{'./_baseFlatten':86,'./_baseRest':121,'./_baseUniq':128,'./isArrayLikeObject':245}],286:[function(require,module,exports){
+var toString = require('./toString');
+
+/** Used to generate unique IDs. */
+var idCounter = 0;
+
+/**
+ * Generates a unique ID. If `prefix` is given, the ID is appended to it.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Util
+ * @param {string} [prefix=''] The value to prefix the ID with.
+ * @returns {string} Returns the unique ID.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ *
+ * _.uniqueId();
+ * // => '105'
+ */
+function uniqueId(prefix) {
+ var id = ++idCounter;
+ return toString(prefix) + id;
+}
+
+module.exports = uniqueId;
+
+},{'./toString':283}],287:[function(require,module,exports){
+var baseValues = require('./_baseValues'),
+ keys = require('./keys');
+
+/**
+ * Creates an array of the own enumerable string keyed property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+function values(object) {
+ return object == null ? [] : baseValues(object, keys(object));
+}
+
+module.exports = values;
+
+},{'./_baseValues':129,'./keys':259}],288:[function(require,module,exports){
+var assignValue = require('./_assignValue'),
+ baseZipObject = require('./_baseZipObject');
+
+/**
+ * This method is like `_.fromPairs` except that it accepts two arrays,
+ * one of property identifiers and one of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.4.0
+ * @category Array
+ * @param {Array} [props=[]] The property identifiers.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObject(['a', 'b'], [1, 2]);
+ * // => { 'a': 1, 'b': 2 }
+ */
+function zipObject(props, values) {
+ return baseZipObject(props || [], values || [], assignValue);
+}
+
+module.exports = zipObject;
+
+},{'./_assignValue':75,'./_baseZipObject':130}]},{},[1])(1)
+});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/module.json b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/module.json
new file mode 100644
index 00000000000..28b605ad873
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dagre_layout/module.json
@@ -0,0 +1,8 @@
+{
+ "scripts": [
+ "dagre.js"
+ ],
+ "skip_compilation": [
+ "dagre.js"
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
index 33af6eb1da3..deaad64209f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/DataGrid.js
@@ -58,8 +58,9 @@ DataGrid.DataGrid = class extends Common.Object {
// FIXME: Add a createCallback which is different from editCallback and has different
// behavior when creating a new node.
- if (editCallback)
+ if (editCallback) {
this._dataTable.addEventListener('dblclick', this._ondblclick.bind(this), false);
+ }
this._dataTable.addEventListener('mousedown', this._mouseDownInDataTable.bind(this));
this._dataTable.addEventListener('click', this._clickInDataTable.bind(this), true);
@@ -131,7 +132,7 @@ DataGrid.DataGrid = class extends Common.Object {
*/
static setElementText(element, newText, longText) {
if (longText && newText.length > 1000) {
- element.textContent = newText.trimEnd(1000);
+ element.textContent = newText.trimEndWithMaxLength(1000);
element.title = newText;
element[DataGrid.DataGrid._longTextSymbol] = newText;
} else {
@@ -161,16 +162,19 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_innerAddColumn(column, position) {
const columnId = column.id;
- if (columnId in this._columns)
+ if (columnId in this._columns) {
this._innerRemoveColumn(columnId);
+ }
- if (position === undefined)
+ if (position === undefined) {
position = this._columnsArray.length;
+ }
this._columnsArray.splice(position, 0, column);
this._columns[columnId] = column;
- if (column.disclosure)
+ if (column.disclosure) {
this.disclosureColumnId = columnId;
+ }
const cell = createElement('th');
cell.className = columnId + '-column';
@@ -178,10 +182,11 @@ DataGrid.DataGrid = class extends Common.Object {
this._headerTableHeaders[columnId] = cell;
const div = createElement('div');
- if (column.titleDOMFragment)
+ if (column.titleDOMFragment) {
div.appendChild(column.titleDOMFragment);
- else
+ } else {
div.textContent = column.title;
+ }
cell.appendChild(div);
if (column.sort) {
@@ -211,14 +216,16 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_innerRemoveColumn(columnId) {
const column = this._columns[columnId];
- if (!column)
+ if (!column) {
return;
+ }
delete this._columns[columnId];
const index = this._columnsArray.findIndex(columnConfig => columnConfig.id === columnId);
this._columnsArray.splice(index, 1);
const cell = this._headerTableHeaders[columnId];
- if (cell.parentElement)
+ if (cell.parentElement) {
cell.parentElement.removeChild(cell);
+ }
delete this._headerTableHeaders[columnId];
}
@@ -276,8 +283,9 @@ DataGrid.DataGrid = class extends Common.Object {
setVerticalPadding(top, bottom) {
const topPx = top + 'px';
const bottomPx = (top || bottom) ? bottom + 'px' : 'auto';
- if (this._topFillerRow.style.height === topPx && this._bottomFillerRow.style.height === bottomPx)
+ if (this._topFillerRow.style.height === topPx && this._bottomFillerRow.style.height === bottomPx) {
return;
+ }
this._topFillerRow.style.height = topPx;
this._bottomFillerRow.style.height = bottomPx;
this.dispatchEventToListeners(DataGrid.DataGrid.Events.PaddingChanged);
@@ -314,12 +322,14 @@ DataGrid.DataGrid = class extends Common.Object {
* @param {!Event} event
*/
_ondblclick(event) {
- if (this._editing || this._editingNode)
+ if (this._editing || this._editingNode) {
return;
+ }
const columnId = this.columnIdFromNode(/** @type {!Node} */ (event.target));
- if (!columnId || !this._columns[columnId].editable)
+ if (!columnId || !this._columns[columnId].editable) {
return;
+ }
this._startEditing(/** @type {!Node} */ (event.target));
}
@@ -346,8 +356,9 @@ DataGrid.DataGrid = class extends Common.Object {
const column = this._columns[columnIdentifier];
const cellIndex = this._visibleColumnsArray.indexOf(column);
const nextEditableColumn = this._nextEditableColumn(cellIndex);
- if (nextEditableColumn !== -1)
+ if (nextEditableColumn !== -1) {
this._startEditingColumnOfDataGridNode(node, nextEditableColumn);
+ }
}
/**
@@ -355,13 +366,15 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_startEditing(target) {
const element = /** @type {?Element} */ (target.enclosingNodeOrSelfWithNodeName('td'));
- if (!element)
+ if (!element) {
return;
+ }
this._editingNode = this.dataGridNodeFromNode(target);
if (!this._editingNode) {
- if (!this.creationNode)
+ if (!this.creationNode) {
return;
+ }
this._editingNode = this.creationNode;
}
@@ -372,8 +385,9 @@ DataGrid.DataGrid = class extends Common.Object {
}
this._editing = true;
- if (element[DataGrid.DataGrid._longTextSymbol])
+ if (element[DataGrid.DataGrid._longTextSymbol]) {
element.textContent = element[DataGrid.DataGrid._longTextSymbol];
+ }
UI.InplaceEditor.startEditing(element, this._startEditingConfig(element));
element.getComponentSelection().selectAllChildren(element);
@@ -417,13 +431,15 @@ DataGrid.DataGrid = class extends Common.Object {
* @this {DataGrid.DataGrid}
*/
function moveToNextIfNeeded(wasChange) {
- if (!moveDirection)
+ if (!moveDirection) {
return;
+ }
if (moveDirection === 'forward') {
const firstEditableColumn = this._nextEditableColumn(-1);
- if (currentEditingNode.isCreationNode && cellIndex === firstEditableColumn && !wasChange)
+ if (currentEditingNode.isCreationNode && cellIndex === firstEditableColumn && !wasChange) {
return;
+ }
const nextEditableColumn = this._nextEditableColumn(cellIndex);
if (nextEditableColumn !== -1) {
@@ -453,8 +469,9 @@ DataGrid.DataGrid = class extends Common.Object {
const lastEditableColumn = this._nextEditableColumn(this._visibleColumnsArray.length, true);
const nextDataGridNode = currentEditingNode.traversePreviousNode(true, true);
- if (nextDataGridNode)
+ if (nextDataGridNode) {
this._startEditingColumnOfDataGridNode(nextDataGridNode, lastEditableColumn);
+ }
return;
}
}
@@ -475,8 +492,9 @@ DataGrid.DataGrid = class extends Common.Object {
// the text that used to be there, and the new text.
this._editCallback(this._editingNode, columnId, textBeforeEditing, newText);
- if (this._editingNode.isCreationNode)
+ if (this._editingNode.isCreationNode) {
this.addCreationNode(false);
+ }
this._editingCancelled(element);
moveToNextIfNeeded.call(this, true);
@@ -499,8 +517,9 @@ DataGrid.DataGrid = class extends Common.Object {
const increment = moveBackward ? -1 : 1;
const columns = this._visibleColumnsArray;
for (let i = cellIndex + increment; (i >= 0) && (i < columns.length); i += increment) {
- if (columns[i].editable)
+ if (columns[i].editable) {
return i;
+ }
}
return -1;
}
@@ -509,8 +528,9 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {?string}
*/
sortColumnId() {
- if (!this._sortColumnCell)
+ if (!this._sortColumnCell) {
return null;
+ }
return this._sortColumnCell[DataGrid.DataGrid._columnIdSymbol];
}
@@ -518,10 +538,12 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {?string}
*/
sortOrder() {
- if (!this._sortColumnCell || this._sortColumnCell.classList.contains(DataGrid.DataGrid.Order.Ascending))
+ if (!this._sortColumnCell || this._sortColumnCell.classList.contains(DataGrid.DataGrid.Order.Ascending)) {
return DataGrid.DataGrid.Order.Ascending;
- if (this._sortColumnCell.classList.contains(DataGrid.DataGrid.Order.Descending))
+ }
+ if (this._sortColumnCell.classList.contains(DataGrid.DataGrid.Order.Descending)) {
return DataGrid.DataGrid.Order.Descending;
+ }
return null;
}
@@ -539,18 +561,21 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {!Array.<number>}
*/
_autoSizeWidths(widths, minPercent, maxPercent) {
- if (minPercent)
+ if (minPercent) {
minPercent = Math.min(minPercent, Math.floor(100 / widths.length));
+ }
let totalWidth = 0;
- for (let i = 0; i < widths.length; ++i)
+ for (let i = 0; i < widths.length; ++i) {
totalWidth += widths[i];
+ }
let totalPercentWidth = 0;
for (let i = 0; i < widths.length; ++i) {
let width = Math.round(100 * widths[i] / totalWidth);
- if (minPercent && width < minPercent)
+ if (minPercent && width < minPercent) {
width = minPercent;
- else if (maxPercent && width > maxPercent)
+ } else if (maxPercent && width > maxPercent) {
width = maxPercent;
+ }
totalPercentWidth += width;
widths[i] = width;
}
@@ -561,8 +586,9 @@ DataGrid.DataGrid = class extends Common.Object {
if (widths[i] > minPercent) {
--widths[i];
--recoupPercent;
- if (!recoupPercent)
+ if (!recoupPercent) {
break;
+ }
}
}
}
@@ -572,8 +598,9 @@ DataGrid.DataGrid = class extends Common.Object {
if (widths[i] < maxPercent) {
++widths[i];
++recoupPercent;
- if (!recoupPercent)
+ if (!recoupPercent) {
break;
+ }
}
}
}
@@ -589,8 +616,9 @@ DataGrid.DataGrid = class extends Common.Object {
*/
autoSizeColumns(minPercent, maxPercent, maxDescentLevel) {
let widths = [];
- for (let i = 0; i < this._columnsArray.length; ++i)
+ for (let i = 0; i < this._columnsArray.length; ++i) {
widths.push((this._columnsArray[i].title || '').length);
+ }
maxDescentLevel = maxDescentLevel || 0;
const children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1);
@@ -598,15 +626,17 @@ DataGrid.DataGrid = class extends Common.Object {
const node = children[i];
for (let j = 0; j < this._columnsArray.length; ++j) {
const text = String(node.data[this._columnsArray[j].id]);
- if (text.length > widths[j])
+ if (text.length > widths[j]) {
widths[j] = text.length;
+ }
}
}
widths = this._autoSizeWidths(widths, minPercent, maxPercent);
- for (let i = 0; i < this._columnsArray.length; ++i)
+ for (let i = 0; i < this._columnsArray.length; ++i) {
this._columnsArray[i].weight = widths[i];
+ }
this._columnWidthsInitialized = false;
this.updateWidths();
}
@@ -618,12 +648,15 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {!Array<!NODE_TYPE>}
*/
_enumerateChildren(rootNode, result, maxLevel) {
- if (!rootNode._isRoot)
+ if (!rootNode._isRoot) {
result.push(rootNode);
- if (!maxLevel)
+ }
+ if (!maxLevel) {
return [];
- for (let i = 0; i < rootNode.children.length; ++i)
+ }
+ for (let i = 0; i < rootNode.children.length; ++i) {
this._enumerateChildren(rootNode.children[i], result, maxLevel - 1);
+ }
return result;
}
@@ -655,8 +688,9 @@ DataGrid.DataGrid = class extends Common.Object {
const numColumns = cells.length - 1; // Do not process corner column.
for (let i = 0; i < numColumns; i++) {
const column = this._visibleColumnsArray[i];
- if (!column.weight)
+ if (!column.weight) {
column.weight = 100 * cells[i].offsetWidth / tableWidth || 10;
+ }
}
this._columnWidthsInitialized = true;
}
@@ -672,21 +706,24 @@ DataGrid.DataGrid = class extends Common.Object {
}
_loadColumnWeights() {
- if (!this._columnWeightsSetting)
+ if (!this._columnWeightsSetting) {
return;
+ }
const weights = this._columnWeightsSetting.get();
for (let i = 0; i < this._columnsArray.length; ++i) {
const column = this._columnsArray[i];
const weight = weights[column.id];
- if (weight)
+ if (weight) {
column.weight = weight;
+ }
}
this._applyColumnWeights();
}
_saveColumnWeights() {
- if (!this._columnWeightsSetting)
+ if (!this._columnWeightsSetting) {
return;
+ }
const weights = {};
for (let i = 0; i < this._columnsArray.length; ++i) {
const column = this._columnsArray[i];
@@ -704,8 +741,9 @@ DataGrid.DataGrid = class extends Common.Object {
_applyColumnWeights() {
let tableWidth = this.element.offsetWidth - this._cornerWidth;
- if (tableWidth <= 0)
+ if (tableWidth <= 0) {
return;
+ }
let sumOfWeights = 0.0;
const fixedColumnWidths = [];
@@ -747,14 +785,16 @@ DataGrid.DataGrid = class extends Common.Object {
this._visibleColumnsArray = [];
for (let i = 0; i < this._columnsArray.length; ++i) {
const column = this._columnsArray[i];
- if (columnsVisibility[column.id])
+ if (columnsVisibility[column.id]) {
this._visibleColumnsArray.push(column);
+ }
}
this._refreshHeader();
this._applyColumnWeights();
const nodes = this._enumerateChildren(this.rootNode(), [], -1);
- for (let i = 0; i < nodes.length; ++i)
+ for (let i = 0; i < nodes.length; ++i) {
nodes[i].refresh();
+ }
}
get scrollContainer() {
@@ -767,8 +807,9 @@ DataGrid.DataGrid = class extends Common.Object {
const left = [];
const resizers = this._resizers;
- while (resizers.length > numColumns - 1)
+ while (resizers.length > numColumns - 1) {
resizers.pop().remove();
+ }
for (let i = 0; i < numColumns - 1; i++) {
// Get the width of the cell in the first (and only) row of the
@@ -801,12 +842,14 @@ DataGrid.DataGrid = class extends Common.Object {
}
addCreationNode(hasChildren) {
- if (this.creationNode)
+ if (this.creationNode) {
this.creationNode.makeNormal();
+ }
const emptyData = {};
- for (const column in this._columns)
+ for (const column in this._columns) {
emptyData[column] = null;
+ }
this.creationNode = new DataGrid.CreationDataGridNode(emptyData, hasChildren);
this.rootNode().appendChild(this.creationNode);
}
@@ -815,27 +858,31 @@ DataGrid.DataGrid = class extends Common.Object {
* @param {!Event} event
*/
_keyDown(event) {
- if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing || UI.isEditing())
+ if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing || UI.isEditing()) {
return;
+ }
let handled = false;
let nextSelectedNode;
if (event.key === 'ArrowUp' && !event.altKey) {
nextSelectedNode = this.selectedNode.traversePreviousNode(true);
- while (nextSelectedNode && !nextSelectedNode.selectable)
+ while (nextSelectedNode && !nextSelectedNode.selectable) {
nextSelectedNode = nextSelectedNode.traversePreviousNode(true);
+ }
handled = nextSelectedNode ? true : false;
} else if (event.key === 'ArrowDown' && !event.altKey) {
nextSelectedNode = this.selectedNode.traverseNextNode(true);
- while (nextSelectedNode && !nextSelectedNode.selectable)
+ while (nextSelectedNode && !nextSelectedNode.selectable) {
nextSelectedNode = nextSelectedNode.traverseNextNode(true);
+ }
handled = nextSelectedNode ? true : false;
} else if (event.key === 'ArrowLeft') {
if (this.selectedNode.expanded) {
- if (event.altKey)
+ if (event.altKey) {
this.selectedNode.collapseRecursively();
- else
+ } else {
this.selectedNode.collapse();
+ }
handled = true;
} else if (this.selectedNode.parent && !this.selectedNode.parent._isRoot) {
handled = true;
@@ -856,10 +903,11 @@ DataGrid.DataGrid = class extends Common.Object {
nextSelectedNode = this.selectedNode.children[0];
handled = nextSelectedNode ? true : false;
} else {
- if (event.altKey)
+ if (event.altKey) {
this.selectedNode.expandRecursively();
- else
+ } else {
this.selectedNode.expand();
+ }
}
}
} else if (event.keyCode === 8 || event.keyCode === 46) {
@@ -880,8 +928,9 @@ DataGrid.DataGrid = class extends Common.Object {
nextSelectedNode.reveal();
nextSelectedNode.select();
}
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -890,25 +939,30 @@ DataGrid.DataGrid = class extends Common.Object {
*/
updateSelectionBeforeRemoval(root, onlyAffectsSubtree) {
let ancestor = this.selectedNode;
- while (ancestor && ancestor !== root)
+ while (ancestor && ancestor !== root) {
ancestor = ancestor.parent;
+ }
// Selection is not in the subtree being deleted.
- if (!ancestor)
+ if (!ancestor) {
return;
+ }
let nextSelectedNode;
// Skip subtree being deleted when looking for the next selectable node.
for (ancestor = root; ancestor && !ancestor.nextSibling; ancestor = ancestor.parent) {
}
- if (ancestor)
+ if (ancestor) {
nextSelectedNode = ancestor.nextSibling;
- while (nextSelectedNode && !nextSelectedNode.selectable)
+ }
+ while (nextSelectedNode && !nextSelectedNode.selectable) {
nextSelectedNode = nextSelectedNode.traverseNextNode(true);
+ }
if (!nextSelectedNode || nextSelectedNode.isCreationNode) {
nextSelectedNode = root.traversePreviousNode(true);
- while (nextSelectedNode && !nextSelectedNode.selectable)
+ while (nextSelectedNode && !nextSelectedNode.selectable) {
nextSelectedNode = nextSelectedNode.traversePreviousNode(true);
+ }
}
if (nextSelectedNode) {
nextSelectedNode.reveal();
@@ -941,8 +995,9 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_clickInHeaderCell(event) {
const cell = event.target.enclosingNodeOrSelfWithNodeName('th');
- if (!cell)
+ if (!cell) {
return;
+ }
this._sortByColumnHeaderCell(cell);
}
@@ -950,15 +1005,18 @@ DataGrid.DataGrid = class extends Common.Object {
* @param {!Node} cell
*/
_sortByColumnHeaderCell(cell) {
- if ((cell[DataGrid.DataGrid._columnIdSymbol] === undefined) || !cell.classList.contains('sortable'))
+ if ((cell[DataGrid.DataGrid._columnIdSymbol] === undefined) || !cell.classList.contains('sortable')) {
return;
+ }
let sortOrder = DataGrid.DataGrid.Order.Ascending;
- if ((cell === this._sortColumnCell) && this.isSortOrderAscending())
+ if ((cell === this._sortColumnCell) && this.isSortOrderAscending()) {
sortOrder = DataGrid.DataGrid.Order.Descending;
+ }
- if (this._sortColumnCell)
+ if (this._sortColumnCell) {
this._sortColumnCell.classList.remove(DataGrid.DataGrid.Order.Ascending, DataGrid.DataGrid.Order.Descending);
+ }
this._sortColumnCell = cell;
cell.classList.add(sortOrder);
@@ -974,8 +1032,9 @@ DataGrid.DataGrid = class extends Common.Object {
* @param {!DataGrid.DataGrid.Order} sortOrder
*/
markColumnAsSortedBy(columnId, sortOrder) {
- if (this._sortColumnCell)
+ if (this._sortColumnCell) {
this._sortColumnCell.classList.remove(DataGrid.DataGrid.Order.Ascending, DataGrid.DataGrid.Order.Descending);
+ }
this._sortColumnCell = this._headerTableHeaders[columnId];
this._sortColumnCell.classList.add(sortOrder);
}
@@ -994,18 +1053,21 @@ DataGrid.DataGrid = class extends Common.Object {
_mouseDownInDataTable(event) {
const target = /** @type {!Node} */ (event.target);
const gridNode = this.dataGridNodeFromNode(target);
- if (!gridNode || !gridNode.selectable || gridNode.isEventWithinDisclosureTriangle(event))
+ if (!gridNode || !gridNode.selectable || gridNode.isEventWithinDisclosureTriangle(event)) {
return;
+ }
const columnId = this.columnIdFromNode(target);
- if (columnId && this._columns[columnId].nonSelectable)
+ if (columnId && this._columns[columnId].nonSelectable) {
return;
+ }
if (event.metaKey) {
- if (gridNode.selected)
+ if (gridNode.selected) {
gridNode.deselect();
- else
+ } else {
gridNode.select();
+ }
} else {
gridNode.select();
this.dispatchEventToListeners(DataGrid.DataGrid.Events.OpenedNode, gridNode);
@@ -1045,22 +1107,44 @@ DataGrid.DataGrid = class extends Common.Object {
}
}
- if (target.isSelfOrDescendant(this._headerTableBody)) {
- if (this._headerContextMenuCallback)
+ const isContextMenuKey = (event.button === 0);
+ if (!isContextMenuKey && target.isSelfOrDescendant(this._headerTableBody)) {
+ if (this._headerContextMenuCallback) {
this._headerContextMenuCallback(contextMenu);
- else
+ } else {
contextMenu.show();
+ }
return;
}
- const gridNode = this.dataGridNodeFromNode(target);
- if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode))
+ const gridNode = isContextMenuKey ? this.selectedNode : this.dataGridNodeFromNode(target);
+ if (isContextMenuKey && this.selectedNode) {
+ const boundingRowRect = this.selectedNode.existingElement().getBoundingClientRect();
+ if (boundingRowRect) {
+ const x = (boundingRowRect.right + boundingRowRect.left) / 2;
+ const y = (boundingRowRect.bottom + boundingRowRect.top) / 2;
+ contextMenu.setX(x);
+ contextMenu.setY(y);
+ }
+ }
+ if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode)) {
contextMenu.defaultSection().appendItem(Common.UIString('Refresh'), this._refreshCallback.bind(this));
+ }
if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) {
if (this._editCallback) {
if (gridNode === this.creationNode) {
contextMenu.defaultSection().appendItem(Common.UIString('Add new'), this._startEditing.bind(this, target));
+ } else if (isContextMenuKey) {
+ const firstEditColumnIndex = this._nextEditableColumn(-1);
+ if (firstEditColumnIndex > -1) {
+ const firstColumn = this._visibleColumnsArray[firstEditColumnIndex];
+ if (firstColumn && firstColumn.editable) {
+ contextMenu.defaultSection().appendItem(
+ ls`Edit "${firstColumn.title}"`,
+ this._startEditingColumnOfDataGridNode.bind(this, gridNode, firstEditColumnIndex));
+ }
+ }
} else {
const columnId = this.columnIdFromNode(target);
if (columnId && this._columns[columnId].editable) {
@@ -1069,10 +1153,12 @@ DataGrid.DataGrid = class extends Common.Object {
}
}
}
- if (this._deleteCallback && gridNode !== this.creationNode)
+ if (this._deleteCallback && gridNode !== this.creationNode) {
contextMenu.defaultSection().appendItem(Common.UIString('Delete'), this._deleteCallback.bind(this, gridNode));
- if (this._rowContextMenuCallback)
+ }
+ if (this._rowContextMenuCallback) {
this._rowContextMenuCallback(contextMenu, gridNode);
+ }
}
contextMenu.show();
@@ -1083,19 +1169,22 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_clickInDataTable(event) {
const gridNode = this.dataGridNodeFromNode(/** @type {!Node} */ (event.target));
- if (!gridNode || !gridNode.hasChildren() || !gridNode.isEventWithinDisclosureTriangle(event))
+ if (!gridNode || !gridNode.hasChildren() || !gridNode.isEventWithinDisclosureTriangle(event)) {
return;
+ }
if (gridNode.expanded) {
- if (event.altKey)
+ if (event.altKey) {
gridNode.collapseRecursively();
- else
+ } else {
gridNode.collapse();
+ }
} else {
- if (event.altKey)
+ if (event.altKey) {
gridNode.expandRecursively();
- else
+ } else {
gridNode.expand();
+ }
}
}
@@ -1125,8 +1214,9 @@ DataGrid.DataGrid = class extends Common.Object {
*/
_resizerDragging(event) {
const resizer = this._currentResizer;
- if (!resizer)
+ if (!resizer) {
return;
+ }
// Constrain the dragpoint to be within the containing div of the
// datagrid.
@@ -1137,8 +1227,9 @@ DataGrid.DataGrid = class extends Common.Object {
// column directly to the left and the column directly to the right.
let leftCellIndex = resizer.__index;
let rightCellIndex = leftCellIndex + 1;
- for (let i = 0; i < leftCellIndex; i++)
+ for (let i = 0; i < leftCellIndex; i++) {
leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
+ }
// Differences for other resize methods
if (this._resizeMethod === DataGrid.DataGrid.ResizeMethod.Last) {
@@ -1154,8 +1245,9 @@ DataGrid.DataGrid = class extends Common.Object {
// Give each column some padding so that they don't disappear.
const leftMinimum = leftEdgeOfPreviousColumn + DataGrid.DataGrid.ColumnResizePadding;
const rightMaximum = rightEdgeOfNextColumn - DataGrid.DataGrid.ColumnResizePadding;
- if (leftMinimum > rightMaximum)
+ if (leftMinimum > rightMaximum) {
return;
+ }
dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
@@ -1195,12 +1287,14 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {number}
*/
columnOffset(columnId) {
- if (!this.element.offsetWidth)
+ if (!this.element.offsetWidth) {
return 0;
+ }
for (let i = 1; i < this._visibleColumnsArray.length; ++i) {
if (columnId === this._visibleColumnsArray[i].id) {
- if (this._resizers[i - 1])
+ if (this._resizers[i - 1]) {
return this._resizers[i - 1].__position;
+ }
}
}
return 0;
@@ -1210,8 +1304,9 @@ DataGrid.DataGrid = class extends Common.Object {
* @return {!DataGrid.DataGridWidget}
*/
asWidget() {
- if (!this._dataGridWidget)
+ if (!this._dataGridWidget) {
this._dataGridWidget = new DataGrid.DataGridWidget(this);
+ }
return this._dataGridWidget;
}
@@ -1290,7 +1385,7 @@ DataGrid.DataGridNode = class extends Common.Object {
super();
/** @type {?Element} */
this._element = null;
- /** @type {boolean} */
+ /** @protected @type {boolean} @suppress {accessControls} */
this._expanded = false;
/** @type {boolean} */
this._selected = false;
@@ -1351,18 +1446,24 @@ DataGrid.DataGridNode = class extends Common.Object {
this._element = createElementWithClass('tr', 'data-grid-data-grid-node');
this._element._dataGridNode = this;
- if (this._hasChildren)
+ if (this._hasChildren) {
this._element.classList.add('parent');
- if (this.expanded)
+ }
+ if (this.expanded) {
this._element.classList.add('expanded');
- if (this.selected)
+ }
+ if (this.selected) {
this._element.classList.add('selected');
- if (this.revealed)
+ }
+ if (this.revealed) {
this._element.classList.add('revealed');
- if (this.dirty)
+ }
+ if (this.dirty) {
this._element.classList.add('dirty');
- if (this.inactive)
+ }
+ if (this.inactive) {
this._element.classList.add('inactive');
+ }
return this._element;
}
@@ -1387,8 +1488,9 @@ DataGrid.DataGridNode = class extends Common.Object {
createCells(element) {
element.removeChildren();
const columnsArray = this.dataGrid._visibleColumnsArray;
- for (let i = 0; i < columnsArray.length; ++i)
+ for (let i = 0; i < columnsArray.length; ++i) {
element.appendChild(this.createCell(columnsArray[i].id));
+ }
element.appendChild(this._createTDWithClass('corner'));
}
@@ -1411,8 +1513,9 @@ DataGrid.DataGridNode = class extends Common.Object {
* @return {boolean}
*/
get revealed() {
- if (this._revealed !== undefined)
+ if (this._revealed !== undefined) {
return this._revealed;
+ }
let currentAncestor = this.parent;
while (currentAncestor && !currentAncestor._isRoot) {
@@ -1432,16 +1535,19 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} x
*/
set revealed(x) {
- if (this._revealed === x)
+ if (this._revealed === x) {
return;
+ }
this._revealed = x;
- if (this._element)
+ if (this._element) {
this._element.classList.toggle('revealed', this._revealed);
+ }
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i].revealed = x && this.expanded;
+ }
}
/**
@@ -1455,15 +1561,18 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} dirty
*/
setDirty(dirty) {
- if (this._dirty === dirty)
+ if (this._dirty === dirty) {
return;
+ }
this._dirty = dirty;
- if (!this._element)
+ if (!this._element) {
return;
- if (dirty)
+ }
+ if (dirty) {
this._element.classList.add('dirty');
- else
+ } else {
this._element.classList.remove('dirty');
+ }
}
@@ -1478,15 +1587,18 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} inactive
*/
setInactive(inactive) {
- if (this._inactive === inactive)
+ if (this._inactive === inactive) {
return;
+ }
this._inactive = inactive;
- if (!this._element)
+ if (!this._element) {
return;
- if (inactive)
+ }
+ if (inactive) {
this._element.classList.add('inactive');
- else
+ } else {
this._element.classList.remove('inactive');
+ }
}
/**
@@ -1500,13 +1612,15 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} x
*/
setHasChildren(x) {
- if (this._hasChildren === x)
+ if (this._hasChildren === x) {
return;
+ }
this._hasChildren = x;
- if (!this._element)
+ if (!this._element) {
return;
+ }
this._element.classList.toggle('parent', this._hasChildren);
this._element.classList.toggle('expanded', this._hasChildren && this.expanded);
@@ -1516,12 +1630,14 @@ DataGrid.DataGridNode = class extends Common.Object {
* @return {number}
*/
get depth() {
- if (this._depth !== undefined)
+ if (this._depth !== undefined) {
return this._depth;
- if (this.parent && !this.parent._isRoot)
+ }
+ if (this.parent && !this.parent._isRoot) {
this._depth = this.parent.depth + 1;
- else
+ } else {
this._depth = 0;
+ }
return this._depth;
}
@@ -1544,8 +1660,9 @@ DataGrid.DataGridNode = class extends Common.Object {
*/
set shouldRefreshChildren(x) {
this._shouldRefreshChildren = x;
- if (x && this.expanded)
+ if (x && this.expanded) {
this.expand();
+ }
}
/**
@@ -1559,10 +1676,11 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} x
*/
set selected(x) {
- if (x)
+ if (x) {
this.select();
- else
+ } else {
this.deselect();
+ }
}
/**
@@ -1576,17 +1694,20 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean} x
*/
set expanded(x) {
- if (x)
+ if (x) {
this.expand();
- else
+ } else {
this.collapse();
+ }
}
refresh() {
- if (!this.dataGrid)
+ if (!this.dataGrid) {
this._element = null;
- if (!this._element)
+ }
+ if (!this._element) {
return;
+ }
this.createCells(this._element);
}
@@ -1597,8 +1718,9 @@ DataGrid.DataGridNode = class extends Common.Object {
_createTDWithClass(className) {
const cell = createElementWithClass('td', className);
const cellClass = this.dataGrid._cellClass;
- if (cellClass)
+ if (cellClass) {
cell.classList.add(cellClass);
+ }
return cell;
}
@@ -1611,13 +1733,15 @@ DataGrid.DataGridNode = class extends Common.Object {
cell[DataGrid.DataGrid._columnIdSymbol] = columnId;
const alignment = this.dataGrid._columns[columnId].align;
- if (alignment)
+ if (alignment) {
cell.classList.add(alignment);
+ }
if (columnId === this.dataGrid.disclosureColumnId) {
cell.classList.add('disclosure');
- if (this.leftPadding)
+ if (this.leftPadding) {
cell.style.setProperty('padding-left', this.leftPadding + 'px');
+ }
}
return cell;
@@ -1630,10 +1754,11 @@ DataGrid.DataGridNode = class extends Common.Object {
createCell(columnId) {
const cell = this.createTD(columnId);
const data = this.data[columnId];
- if (data instanceof Node)
+ if (data instanceof Node) {
cell.appendChild(data);
- else if (data !== null)
+ } else if (data !== null) {
DataGrid.DataGrid.setElementText(cell, /** @type {string} */ (data), !!this.dataGrid._columns[columnId].longText);
+ }
return cell;
}
@@ -1659,12 +1784,15 @@ DataGrid.DataGridNode = class extends Common.Object {
// @TODO(allada) This is a hack to make sure ViewportDataGrid can clean up these caches. Try Not To Use.
delete this._depth;
delete this._revealed;
- if (onlyCaches)
+ if (onlyCaches) {
return;
- if (this.previousSibling)
+ }
+ if (this.previousSibling) {
this.previousSibling.nextSibling = this.nextSibling;
- if (this.nextSibling)
+ }
+ if (this.nextSibling) {
this.nextSibling.previousSibling = this.previousSibling;
+ }
this.dataGrid = null;
this.parent = null;
this.nextSibling = null;
@@ -1677,16 +1805,20 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {number} index
*/
insertChild(child, index) {
- if (!child)
+ if (!child) {
throw 'insertChild: Node can\'t be undefined or null.';
+ }
if (child.parent === this) {
const currentIndex = this.children.indexOf(child);
- if (currentIndex < 0)
+ if (currentIndex < 0) {
console.assert(false, 'Inconsistent DataGrid state');
- if (currentIndex === index)
+ }
+ if (currentIndex === index) {
return;
- if (currentIndex < index)
+ }
+ if (currentIndex < index) {
--index;
+ }
}
child.remove();
@@ -1709,40 +1841,48 @@ DataGrid.DataGridNode = class extends Common.Object {
current = current.traverseNextNode(false, child, true);
}
- if (this.expanded)
+ if (this.expanded) {
child._attach();
- if (!this.revealed)
+ }
+ if (!this.revealed) {
child.revealed = false;
+ }
}
remove() {
- if (this.parent)
+ if (this.parent) {
this.parent.removeChild(this);
+ }
}
/**
* @param {!NODE_TYPE} child
*/
removeChild(child) {
- if (!child)
+ if (!child) {
throw 'removeChild: Node can\'t be undefined or null.';
- if (child.parent !== this)
+ }
+ if (child.parent !== this) {
throw 'removeChild: Node is not a child of this node.';
+ }
- if (this.dataGrid)
+ if (this.dataGrid) {
this.dataGrid.updateSelectionBeforeRemoval(child, false);
+ }
child._detach();
child.resetNode();
this.children.remove(child, true);
- if (this.children.length <= 0)
+ if (this.children.length <= 0) {
this.setHasChildren(false);
+ }
}
removeChildren() {
- if (this.dataGrid)
+ if (this.dataGrid) {
this.dataGrid.updateSelectionBeforeRemoval(this, true);
+ }
for (let i = 0; i < this.children.length; ++i) {
const child = this.children[i];
child._detach();
@@ -1757,37 +1897,44 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {number} myIndex
*/
recalculateSiblings(myIndex) {
- if (!this.parent)
+ if (!this.parent) {
return;
+ }
const previousChild = this.parent.children[myIndex - 1] || null;
- if (previousChild)
+ if (previousChild) {
previousChild.nextSibling = this;
+ }
this.previousSibling = previousChild;
const nextChild = this.parent.children[myIndex + 1] || null;
- if (nextChild)
+ if (nextChild) {
nextChild.previousSibling = this;
+ }
this.nextSibling = nextChild;
}
collapse() {
- if (this._isRoot)
+ if (this._isRoot) {
return;
- if (this._element)
+ }
+ if (this._element) {
this._element.classList.remove('expanded');
+ }
this._expanded = false;
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i].revealed = false;
+ }
}
collapseRecursively() {
let item = this;
while (item) {
- if (item.expanded)
+ if (item.expanded) {
item.collapse();
+ }
item = item.traverseNextNode(false, this, true);
}
}
@@ -1796,27 +1943,32 @@ DataGrid.DataGridNode = class extends Common.Object {
}
expand() {
- if (!this._hasChildren || this.expanded)
+ if (!this._hasChildren || this.expanded) {
return;
- if (this._isRoot)
+ }
+ if (this._isRoot) {
return;
+ }
if (this.revealed && !this._shouldRefreshChildren) {
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i].revealed = true;
+ }
}
if (this._shouldRefreshChildren) {
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i]._detach();
+ }
this.populate();
if (this._attached) {
for (let i = 0; i < this.children.length; ++i) {
const child = this.children[i];
- if (this.revealed)
+ if (this.revealed) {
child.revealed = true;
+ }
child._attach();
}
}
@@ -1824,8 +1976,9 @@ DataGrid.DataGridNode = class extends Common.Object {
this._shouldRefreshChildren = false;
}
- if (this._element)
+ if (this._element) {
this._element.classList.add('expanded');
+ }
this._expanded = true;
}
@@ -1839,12 +1992,14 @@ DataGrid.DataGridNode = class extends Common.Object {
}
reveal() {
- if (this._isRoot)
+ if (this._isRoot) {
return;
+ }
let currentAncestor = this.parent;
while (currentAncestor && !currentAncestor._isRoot) {
- if (!currentAncestor.expanded)
+ if (!currentAncestor.expanded) {
currentAncestor.expand();
+ }
currentAncestor = currentAncestor.parent;
}
@@ -1855,25 +2010,30 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean=} supressSelectedEvent
*/
select(supressSelectedEvent) {
- if (!this.dataGrid || !this.selectable || this.selected)
+ if (!this.dataGrid || !this.selectable || this.selected) {
return;
+ }
- if (this.dataGrid.selectedNode)
+ if (this.dataGrid.selectedNode) {
this.dataGrid.selectedNode.deselect();
+ }
this._selected = true;
this.dataGrid.selectedNode = this;
- if (this._element)
+ if (this._element) {
this._element.classList.add('selected');
+ }
- if (!supressSelectedEvent)
+ if (!supressSelectedEvent) {
this.dataGrid.dispatchEventToListeners(DataGrid.DataGrid.Events.SelectedNode, this);
+ }
}
revealAndSelect() {
- if (this._isRoot)
+ if (this._isRoot) {
return;
+ }
this.reveal();
this.select();
}
@@ -1882,17 +2042,20 @@ DataGrid.DataGridNode = class extends Common.Object {
* @param {boolean=} supressDeselectedEvent
*/
deselect(supressDeselectedEvent) {
- if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+ if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) {
return;
+ }
this._selected = false;
this.dataGrid.selectedNode = null;
- if (this._element)
+ if (this._element) {
this._element.classList.remove('selected');
+ }
- if (!supressDeselectedEvent)
+ if (!supressDeselectedEvent) {
this.dataGrid.dispatchEventToListeners(DataGrid.DataGrid.Events.DeselectedNode);
+ }
}
/**
@@ -1903,36 +2066,43 @@ DataGrid.DataGridNode = class extends Common.Object {
* @return {?NODE_TYPE}
*/
traverseNextNode(skipHidden, stayWithin, dontPopulate, info) {
- if (!dontPopulate && this._hasChildren)
+ if (!dontPopulate && this._hasChildren) {
this.populate();
+ }
- if (info)
+ if (info) {
info.depthChange = 0;
+ }
let node = (!skipHidden || this.revealed) ? this.children[0] : null;
if (node && (!skipHidden || this.expanded)) {
- if (info)
+ if (info) {
info.depthChange = 1;
+ }
return node;
}
- if (this === stayWithin)
+ if (this === stayWithin) {
return null;
+ }
node = (!skipHidden || this.revealed) ? this.nextSibling : null;
- if (node)
+ if (node) {
return node;
+ }
node = this;
while (node && !node._isRoot && !((!skipHidden || node.revealed) ? node.nextSibling : null) &&
node.parent !== stayWithin) {
- if (info)
+ if (info) {
info.depthChange -= 1;
+ }
node = node.parent;
}
- if (!node)
+ if (!node) {
return null;
+ }
return (!skipHidden || node.revealed) ? node.nextSibling : null;
}
@@ -1944,21 +2114,25 @@ DataGrid.DataGridNode = class extends Common.Object {
*/
traversePreviousNode(skipHidden, dontPopulate) {
let node = (!skipHidden || this.revealed) ? this.previousSibling : null;
- if (!dontPopulate && node && node._hasChildren)
+ if (!dontPopulate && node && node._hasChildren) {
node.populate();
+ }
while (node &&
((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
- if (!dontPopulate && node._hasChildren)
+ if (!dontPopulate && node._hasChildren) {
node.populate();
+ }
node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
}
- if (node)
+ if (node) {
return node;
+ }
- if (!this.parent || this.parent._isRoot)
+ if (!this.parent || this.parent._isRoot) {
return null;
+ }
return this.parent;
}
@@ -1968,19 +2142,22 @@ DataGrid.DataGridNode = class extends Common.Object {
* @return {boolean}
*/
isEventWithinDisclosureTriangle(event) {
- if (!this._hasChildren)
+ if (!this._hasChildren) {
return false;
+ }
const cell = event.target.enclosingNodeOrSelfWithNodeName('td');
- if (!cell || !cell.classList.contains('disclosure'))
+ if (!cell || !cell.classList.contains('disclosure')) {
return false;
+ }
const left = cell.totalOffsetLeft() + this.leftPadding;
return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
}
_attach() {
- if (!this.dataGrid || this._attached)
+ if (!this.dataGrid || this._attached) {
return;
+ }
this._attached = true;
@@ -1989,39 +2166,47 @@ DataGrid.DataGridNode = class extends Common.Object {
this.dataGrid.dataTableBody.insertBefore(this.element(), previousElement.nextSibling);
if (this.expanded) {
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i]._attach();
+ }
}
}
_detach() {
- if (!this._attached)
+ if (!this._attached) {
return;
+ }
this._attached = false;
- if (this._element)
+ if (this._element) {
this._element.remove();
+ }
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i]._detach();
+ }
}
savePosition() {
- if (this._savedPosition)
+ if (this._savedPosition) {
return;
+ }
- if (!this.parent)
+ if (!this.parent) {
throw 'savePosition: Node must have a parent.';
+ }
this._savedPosition = {parent: this.parent, index: this.parent.children.indexOf(this)};
}
restorePosition() {
- if (!this._savedPosition)
+ if (!this._savedPosition) {
return;
+ }
- if (this.parent !== this._savedPosition.parent)
+ if (this.parent !== this._savedPosition.parent) {
this._savedPosition.parent.insertChild(this, this._savedPosition.index);
+ }
this._savedPosition = null;
}
@@ -2091,8 +2276,9 @@ DataGrid.DataGridWidget = class extends UI.VBox {
*/
detachChildWidgets() {
super.detachChildWidgets();
- for (const dataGrid of this._dataGrids)
+ for (const dataGrid of this._dataGrids) {
this.element.removeChild(dataGrid.element);
+ }
this._dataGrids = [];
}
-};
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ShowMoreDataGridNode.js b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ShowMoreDataGridNode.js
index 0ac60d7c22b..f5ccb47acdb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ShowMoreDataGridNode.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ShowMoreDataGridNode.js
@@ -105,8 +105,9 @@ DataGrid.ShowMoreDataGridNode = class extends DataGrid.DataGridNode {
const cell = this.createTD(columnIdentifier);
if (!this._hasCells) {
this._hasCells = true;
- if (this.depth)
+ if (this.depth) {
cell.style.setProperty('padding-left', (this.depth * this.dataGrid.indentWidth) + 'px');
+ }
cell.appendChild(this.showNext);
cell.appendChild(this.showAll);
cell.appendChild(this.showLast);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/SortableDataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/SortableDataGrid.js
index 56df1218f37..b2f76edc663 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/SortableDataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/SortableDataGrid.js
@@ -76,18 +76,21 @@ DataGrid.SortableDataGrid = class extends DataGrid.ViewportDataGrid {
*/
static create(columnNames, values) {
const numColumns = columnNames.length;
- if (!numColumns)
+ if (!numColumns) {
return null;
+ }
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([]);
- for (let i = 0; i < columnNames.length; ++i)
+ for (let i = 0; i < columnNames.length; ++i) {
columns.push({id: String(i), title: columnNames[i], width: columnNames[i].length, sortable: true});
+ }
const nodes = [];
for (let i = 0; i < values.length / numColumns; ++i) {
const data = {};
- for (let j = 0; j < columnNames.length; ++j)
+ for (let j = 0; j < columnNames.length; ++j) {
data[j] = values[numColumns * i + j];
+ }
const node = new DataGrid.SortableDataGridNode(data);
node.selectable = false;
@@ -97,16 +100,18 @@ DataGrid.SortableDataGrid = class extends DataGrid.ViewportDataGrid {
const dataGrid = new DataGrid.SortableDataGrid(columns);
const length = nodes.length;
const rootNode = dataGrid.rootNode();
- for (let i = 0; i < length; ++i)
+ for (let i = 0; i < length; ++i) {
rootNode.appendChild(nodes[i]);
+ }
dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, sortDataGrid);
function sortDataGrid() {
const nodes = dataGrid.rootNode().children;
const sortColumnId = dataGrid.sortColumnId();
- if (!sortColumnId)
+ if (!sortColumnId) {
return;
+ }
let columnIsNumeric = true;
for (let i = 0; i < nodes.length; i++) {
@@ -167,9 +172,11 @@ DataGrid.SortableDataGridNode = class extends DataGrid.ViewportDataGridNode {
_sortChildren() {
this.children.sort(this.dataGrid._sortingFunction);
- for (let i = 0; i < this.children.length; ++i)
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i].recalculateSiblings(i);
- for (const child of this.children)
+ }
+ for (const child of this.children) {
child._sortChildren();
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ViewportDataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ViewportDataGrid.js
index 90a0ed18f13..4ee8468e2fd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ViewportDataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/ViewportDataGrid.js
@@ -17,10 +17,13 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
super(columnsArray, editCallback, deleteCallback, refreshCallback);
this._onScrollBound = this._onScroll.bind(this);
- this._scrollContainer.addEventListener('scroll', this._onScrollBound, true);
+ this.scrollContainer.addEventListener('scroll', this._onScrollBound, true);
/** @type {!Array.<!DataGrid.ViewportDataGridNode>} */
this._visibleNodes = [];
+ /**
+ * @type {boolean}
+ */
this._inline = false;
this._stickToBottom = false;
@@ -58,17 +61,21 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
* @param {!Element} scrollContainer
*/
setScrollContainer(scrollContainer) {
- this._scrollContainer.removeEventListener('scroll', this._onScrollBound, true);
+ this.scrollContainer.removeEventListener('scroll', this._onScrollBound, true);
+ /**
+ * @suppress {accessControls}
+ */
this._scrollContainer = scrollContainer;
- this._scrollContainer.addEventListener('scroll', this._onScrollBound, true);
+ this.scrollContainer.addEventListener('scroll', this._onScrollBound, true);
}
/**
* @override
*/
onResize() {
- if (this._stickToBottom)
- this._scrollContainer.scrollTop = this._scrollContainer.scrollHeight - this._scrollContainer.clientHeight;
+ if (this._stickToBottom) {
+ this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight;
+ }
this.scheduleUpdate();
super.onResize();
}
@@ -84,9 +91,10 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
* @param {?Event} event
*/
_onScroll(event) {
- this._stickToBottom = this._scrollContainer.isScrolledToBottom();
- if (this._lastScrollTop !== this._scrollContainer.scrollTop)
+ this._stickToBottom = this.scrollContainer.isScrolledToBottom();
+ if (this._lastScrollTop !== this.scrollContainer.scrollTop) {
this.scheduleUpdate(true);
+ }
}
/**
@@ -100,11 +108,13 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
* @param {boolean=} isFromUser
*/
scheduleUpdate(isFromUser) {
- if (this._stickToBottom && isFromUser)
- this._stickToBottom = this._scrollContainer.isScrolledToBottom();
+ if (this._stickToBottom && isFromUser) {
+ this._stickToBottom = this.scrollContainer.isScrolledToBottom();
+ }
this._updateIsFromUser = this._updateIsFromUser || isFromUser;
- if (this._updateAnimationFrameId)
+ if (this._updateAnimationFrameId) {
return;
+ }
this._updateAnimationFrameId = this.element.window().requestAnimationFrame(this._update.bind(this));
}
@@ -131,25 +141,29 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
*/
_calculateVisibleNodes(clientHeight, scrollTop) {
const nodes = this.rootNode().flatChildren();
- if (this._inline)
+ if (this._inline) {
return {topPadding: 0, bottomPadding: 0, contentHeight: 0, visibleNodes: nodes, offset: 0};
+ }
const size = nodes.length;
let i = 0;
let y = 0;
- for (; i < size && y + nodes[i].nodeSelfHeight() < scrollTop; ++i)
+ for (; i < size && y + nodes[i].nodeSelfHeight() < scrollTop; ++i) {
y += nodes[i].nodeSelfHeight();
+ }
const start = i;
const topPadding = y;
- for (; i < size && y < scrollTop + clientHeight; ++i)
+ for (; i < size && y < scrollTop + clientHeight; ++i) {
y += nodes[i].nodeSelfHeight();
+ }
const end = i;
let bottomPadding = 0;
- for (; i < size; ++i)
+ for (; i < size; ++i) {
bottomPadding += nodes[i].nodeSelfHeight();
+ }
return {
topPadding: topPadding,
@@ -166,8 +180,9 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
_contentHeight() {
const nodes = this.rootNode().flatChildren();
let result = 0;
- for (let i = 0, size = nodes.length; i < size; ++i)
+ for (let i = 0, size = nodes.length; i < size; ++i) {
result += nodes[i].nodeSelfHeight();
+ }
return result;
}
@@ -177,12 +192,13 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
delete this._updateAnimationFrameId;
}
- const clientHeight = this._scrollContainer.clientHeight;
- let scrollTop = this._scrollContainer.scrollTop;
+ const clientHeight = this.scrollContainer.clientHeight;
+ let scrollTop = this.scrollContainer.scrollTop;
const currentScrollTop = scrollTop;
const maxScrollTop = Math.max(0, this._contentHeight() - clientHeight);
- if (!this._updateIsFromUser && this._stickToBottom)
+ if (!this._updateIsFromUser && this._stickToBottom) {
scrollTop = maxScrollTop;
+ }
this._updateIsFromUser = false;
scrollTop = Math.min(maxScrollTop, scrollTop);
@@ -206,8 +222,9 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
const nodes = this.rootNode().flatChildren();
const index = nodes.indexOf(visibleNodes[0]);
this._updateStripesClass(!!(index % 2));
- if (this._stickToBottom && index !== -1 && !!(index % 2) !== this._firstVisibleIsStriped)
+ if (this._stickToBottom && index !== -1 && !!(index % 2) !== this._firstVisibleIsStriped) {
offset += 1;
+ }
}
this._firstVisibleIsStriped = !!(offset % 2);
@@ -216,16 +233,18 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
const node = visibleNodes[i];
const element = node.element();
node.setStriped((offset + i) % 2 === 0);
- if (element !== previousElement.nextSibling)
+ if (element !== previousElement.nextSibling) {
tBody.insertBefore(element, previousElement.nextSibling);
+ }
node.revealed = true;
previousElement = element;
}
this.setVerticalPadding(viewportState.topPadding, viewportState.bottomPadding);
this._lastScrollTop = scrollTop;
- if (scrollTop !== currentScrollTop)
- this._scrollContainer.scrollTop = scrollTop;
+ if (scrollTop !== currentScrollTop) {
+ this.scrollContainer.scrollTop = scrollTop;
+ }
const contentFits =
viewportState.contentHeight <= clientHeight && viewportState.topPadding + viewportState.bottomPadding === 0;
if (contentFits !== this.element.classList.contains('data-grid-fits-viewport')) {
@@ -242,24 +261,29 @@ DataGrid.ViewportDataGrid = class extends DataGrid.DataGrid {
_revealViewportNode(node) {
const nodes = this.rootNode().flatChildren();
const index = nodes.indexOf(node);
- if (index === -1)
+ if (index === -1) {
return;
+ }
let fromY = 0;
- for (let i = 0; i < index; ++i)
+ for (let i = 0; i < index; ++i) {
fromY += nodes[i].nodeSelfHeight();
+ }
const toY = fromY + node.nodeSelfHeight();
- let scrollTop = this._scrollContainer.scrollTop;
+ let scrollTop = this.scrollContainer.scrollTop;
if (scrollTop > fromY) {
scrollTop = fromY;
this._stickToBottom = false;
- } else if (scrollTop + this._scrollContainer.offsetHeight < toY) {
- scrollTop = toY - this._scrollContainer.offsetHeight;
+ } else if (scrollTop + this.scrollContainer.offsetHeight < toY) {
+ scrollTop = toY - this.scrollContainer.offsetHeight;
}
- this._scrollContainer.scrollTop = scrollTop;
+ this.scrollContainer.scrollTop = scrollTop;
}
};
+/**
+ * @override @suppress {checkPrototypalTypes} @enum {symbol}
+ */
DataGrid.ViewportDataGrid.Events = {
ViewportCalculated: Symbol('ViewportCalculated')
};
@@ -318,16 +342,18 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
clearFlatNodes() {
this._flatNodes = null;
const parent = /** @type {!DataGrid.ViewportDataGridNode} */ (this.parent);
- if (parent)
+ if (parent) {
parent.clearFlatNodes();
+ }
}
/**
* @return {!Array<!DataGrid.ViewportDataGridNode>}
*/
flatChildren() {
- if (this._flatNodes)
+ if (this._flatNodes) {
return this._flatNodes;
+ }
/** @type {!Array<!DataGrid.ViewportDataGridNode>} */
const flatNodes = [];
/** @type {!Array<!Array<!DataGrid.ViewportDataGridNode>>} */
@@ -342,7 +368,7 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
}
const node = children[depth][counters[depth]++];
flatNodes.push(node);
- if (node._expanded && node.children.length) {
+ if (node.expanded && node.children.length) {
depth++;
children[depth] = node.children;
counters[depth] = 0;
@@ -362,22 +388,27 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
this.clearFlatNodes();
if (child.parent === this) {
const currentIndex = this.children.indexOf(child);
- if (currentIndex < 0)
+ if (currentIndex < 0) {
console.assert(false, 'Inconsistent DataGrid state');
- if (currentIndex === index)
+ }
+ if (currentIndex === index) {
return;
- if (currentIndex < index)
+ }
+ if (currentIndex < index) {
--index;
+ }
}
child.remove();
child.parent = this;
child.dataGrid = this.dataGrid;
- if (!this.children.length)
+ if (!this.children.length) {
this.setHasChildren(true);
+ }
this.children.splice(index, 0, child);
child.recalculateSiblings(index);
- if (this._expanded)
+ if (this.expanded) {
this.dataGrid.scheduleUpdateStructure();
+ }
}
/**
@@ -386,22 +417,28 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
*/
removeChild(child) {
this.clearFlatNodes();
- if (this.dataGrid)
+ if (this.dataGrid) {
this.dataGrid.updateSelectionBeforeRemoval(child, false);
- if (child.previousSibling)
+ }
+ if (child.previousSibling) {
child.previousSibling.nextSibling = child.nextSibling;
- if (child.nextSibling)
+ }
+ if (child.nextSibling) {
child.nextSibling.previousSibling = child.previousSibling;
- if (child.parent !== this)
+ }
+ if (child.parent !== this) {
throw 'removeChild: Node is not a child of this node.';
+ }
this.children.remove(child, true);
child._unlink();
- if (!this.children.length)
+ if (!this.children.length) {
this.setHasChildren(false);
- if (this._expanded)
+ }
+ if (this.expanded) {
this.dataGrid.scheduleUpdateStructure();
+ }
}
/**
@@ -409,19 +446,23 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
*/
removeChildren() {
this.clearFlatNodes();
- if (this.dataGrid)
+ if (this.dataGrid) {
this.dataGrid.updateSelectionBeforeRemoval(this, true);
- for (let i = 0; i < this.children.length; ++i)
+ }
+ for (let i = 0; i < this.children.length; ++i) {
this.children[i]._unlink();
+ }
this.children = [];
- if (this._expanded)
+ if (this.expanded) {
this.dataGrid.scheduleUpdateStructure();
+ }
}
_unlink() {
- if (this.attached())
+ if (this.attached()) {
this.existingElement().remove();
+ }
this.resetNode();
}
@@ -429,12 +470,17 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
* @override
*/
collapse() {
- if (!this._expanded)
+ if (!this.expanded) {
return;
+ }
this.clearFlatNodes();
+ /**
+ * @suppress {accessControls}
+ */
this._expanded = false;
- if (this.existingElement())
+ if (this.existingElement()) {
this.existingElement().classList.remove('expanded');
+ }
this.dataGrid.scheduleUpdateStructure();
}
@@ -442,8 +488,9 @@ DataGrid.ViewportDataGridNode = class extends DataGrid.DataGridNode {
* @override
*/
expand() {
- if (this._expanded)
+ if (this.expanded) {
return;
+ }
this.dataGrid._stickToBottom = false;
this.clearFlatNodes();
super.expand();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
index d5918a93d18..c99b4a867a3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid/data_grid_strings.grdp
@@ -18,7 +18,4 @@
<message name="IDS_DEVTOOLS_ef61fb324d729c341ea8ab9901e23566" desc="A context menu item in the Data Grid of a data grid">
Add new
</message>
- <message name="IDS_DEVTOOLS_f2a6c498fb90ee345d997f888fce3b18" desc="A context menu item in the Data Grid of a data grid">
- Delete
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js
index 8a11a8f8cc7..2e802be8f5f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/data_grid_test_runner/DataGridTestRunner.js
@@ -8,22 +8,27 @@
*/
DataGridTestRunner.dumpDataGrid = function(root, descentIntoCollapsed, prefix) {
- if (!prefix)
+ if (!prefix) {
prefix = '';
+ }
const suffix = root.selected ? ' <- selected' : '';
const columnKeys = root.dataGrid._columnsArray.map(column => column.id);
const outputColumns = [];
for (const key of columnKeys) {
- if (key in root.data)
+ if (key in root.data) {
outputColumns.push(root.data[key]);
+ }
}
- if (outputColumns.length)
+ if (outputColumns.length) {
TestRunner.addResult(prefix + outputColumns.join(' | ') + suffix);
+ }
- if (!descentIntoCollapsed && !root.expanded)
+ if (!descentIntoCollapsed && !root.expanded) {
return;
- for (const child of root.children)
+ }
+ for (const child of root.children) {
DataGridTestRunner.dumpDataGrid(child, descentIntoCollapsed, prefix + ' ');
+ }
};
DataGridTestRunner.validateDataGrid = function(root) {
@@ -32,17 +37,21 @@ DataGridTestRunner.validateDataGrid = function(root) {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
- if (child.parent !== root)
+ if (child.parent !== root) {
throw 'Wrong parent for child ' + child.data.id + ' of ' + root.data.id;
+ }
- if (child.nextSibling !== ((i + 1 === children.length ? null : children[i + 1])))
+ if (child.nextSibling !== ((i + 1 === children.length ? null : children[i + 1]))) {
throw 'Wrong child.nextSibling for ' + child.data.id + ' (' + i + ' of ' + children.length + ') ';
+ }
- if (child.previousSibling !== ((i ? children[i - 1] : null)))
+ if (child.previousSibling !== ((i ? children[i - 1] : null))) {
throw 'Wrong child.previousSibling for ' + child.data.id + ' (' + i + ' of ' + children.length + ') ';
+ }
- if (child.parent && !child.parent._isRoot && child.depth !== root.depth + 1)
+ if (child.parent && !child.parent._isRoot && child.depth !== root.depth + 1) {
throw 'Wrong depth for ' + child.data.id + ' expected ' + (root.depth + 1) + ' but got ' + child.depth;
+ }
DataGridTestRunner.validateDataGrid(child);
}
@@ -50,14 +59,16 @@ DataGridTestRunner.validateDataGrid = function(root) {
const selectedNode = root.dataGrid.selectedNode;
if (!root.parent && selectedNode) {
- if (!selectedNode.selectable)
+ if (!selectedNode.selectable) {
throw 'Selected node is not selectable';
+ }
let node = selectedNode;
for (; node && node !== root; node = node.parent) {
}
- if (!node)
+ if (!node) {
throw 'Selected node (' + selectedNode.data.id + ') is not within the DataGrid';
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js b/chromium/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js
index 3b8e48086ad..20fa9eb7f39 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js
@@ -43,22 +43,22 @@ Devices.DevicesView = class extends UI.VBox {
this._updateFooter();
this._selectSidebarListItem(this._discoveryListItem, this._discoveryView);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged, this._devicesPortForwardingStatusChanged,
- this);
-
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged,
+ this._devicesPortForwardingStatusChanged, this);
}
/**
* @return {!Devices.DevicesView}
*/
static _instance() {
- if (!Devices.DevicesView._instanceObject)
+ if (!Devices.DevicesView._instanceObject) {
Devices.DevicesView._instanceObject = new Devices.DevicesView();
+ }
return Devices.DevicesView._instanceObject;
}
@@ -67,8 +67,9 @@ Devices.DevicesView = class extends UI.VBox {
* @param {!UI.Widget} view
*/
_selectSidebarListItem(listItem, view) {
- if (this._selectedListItem === listItem)
+ if (this._selectedListItem === listItem) {
return;
+ }
if (this._selectedListItem) {
this._selectedListItem.classList.remove('selected');
@@ -90,13 +91,15 @@ Devices.DevicesView = class extends UI.VBox {
.slice()
.filter(d => d.adbSerial.toUpperCase() !== 'WEBRTC' && d.adbSerial.toUpperCase() !== 'LOCALHOST');
for (const device of this._devices) {
- if (!device.adbConnected)
+ if (!device.adbConnected) {
device.adbModel = Common.UIString('Unknown');
+ }
}
const ids = new Set();
- for (const device of this._devices)
+ for (const device of this._devices) {
ids.add(device.id);
+ }
let selectedRemoved = false;
for (const deviceId of this._viewById.keys()) {
@@ -105,8 +108,9 @@ Devices.DevicesView = class extends UI.VBox {
this._listItemById.remove(deviceId);
this._viewById.remove(deviceId);
listItem.remove();
- if (listItem === this._selectedListItem)
+ if (listItem === this._selectedListItem) {
selectedRemoved = true;
+ }
}
}
@@ -129,8 +133,9 @@ Devices.DevicesView = class extends UI.VBox {
view.update(device);
}
- if (selectedRemoved)
+ if (selectedRemoved) {
this._selectSidebarListItem(this._discoveryListItem, this._discoveryView);
+ }
this._updateFooter();
}
@@ -162,13 +167,15 @@ Devices.DevicesView = class extends UI.VBox {
const status = /** @type {!Adb.PortForwardingStatus} */ (event.data);
for (const deviceId in status) {
const view = this._viewById.get(deviceId);
- if (view)
+ if (view) {
view.portForwardingStatusChanged(status[deviceId]);
+ }
}
for (const deviceId of this._viewById.keys()) {
const view = this._viewById.get(deviceId);
- if (view && !(deviceId in status))
+ if (view && !(deviceId in status)) {
view.portForwardingStatusChanged({ports: {}, browserId: ''});
+ }
}
}
@@ -184,7 +191,7 @@ Devices.DevicesView = class extends UI.VBox {
*/
wasShown() {
super.wasShown();
- InspectorFrontendHost.setDevicesUpdatesEnabled(true);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true);
}
/**
@@ -192,7 +199,7 @@ Devices.DevicesView = class extends UI.VBox {
*/
willHide() {
super.willHide();
- InspectorFrontendHost.setDevicesUpdatesEnabled(false);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false);
}
};
@@ -211,7 +218,7 @@ Devices.DevicesView.DiscoveryView = class extends UI.VBox {
this._discoverUsbDevicesCheckbox = discoverUsbDevicesCheckbox.checkboxElement;
this._discoverUsbDevicesCheckbox.addEventListener('click', () => {
this._config.discoverUsbDevices = this._discoverUsbDevicesCheckbox.checked;
- InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
+ Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
}, false);
const help = this.element.createChild('div', 'discovery-help');
@@ -226,9 +233,10 @@ Devices.DevicesView.DiscoveryView = class extends UI.VBox {
this._portForwardingView = new Devices.DevicesView.PortForwardingView((enabled, config) => {
this._config.portForwardingEnabled = enabled;
this._config.portForwardingConfig = {};
- for (const rule of config)
+ for (const rule of config) {
this._config.portForwardingConfig[rule.port] = rule.address;
- InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
+ }
+ Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
});
this._portForwardingView.show(this.element);
}
@@ -349,8 +357,9 @@ Devices.DevicesView.PortForwardingView = class extends UI.VBox {
commitEdit(rule, editor, isNew) {
rule.port = editor.control('port').value.trim();
rule.address = editor.control('address').value.trim();
- if (isNew)
+ if (isNew) {
this._portForwardingConfig.push(rule);
+ }
this._update();
}
@@ -370,8 +379,9 @@ Devices.DevicesView.PortForwardingView = class extends UI.VBox {
* @return {!UI.ListWidget.Editor<!Adb.PortForwardingRule>}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -404,8 +414,9 @@ Devices.DevicesView.PortForwardingView = class extends UI.VBox {
errorMessage = ls`Device port must be a number`;
} else {
const port = parseInt(match[1], 10);
- if (port < 1024 || port > 65535)
+ if (port < 1024 || port > 65535) {
errorMessage = ls`Device port number must be between 1024 and 65535`;
+ }
for (let i = 0; i < this._portForwardingConfig.length; ++i) {
if (i !== index && this._portForwardingConfig[i].port === value) {
errorMessage = ls`Device port numbers can only be used once`;
@@ -414,8 +425,9 @@ Devices.DevicesView.PortForwardingView = class extends UI.VBox {
}
}
- if (errorMessage)
+ if (errorMessage) {
return {valid: false, errorMessage};
+ }
return {valid: true};
}
@@ -437,12 +449,14 @@ Devices.DevicesView.PortForwardingView = class extends UI.VBox {
errorMessage = ls`Local address must match this pattern: dev.example.corp:3333`;
} else {
const port = parseInt(match[2], 10);
- if (port > 65535)
+ if (port > 65535) {
errorMessage = ls`Port number must be not greater than 65535`;
+ }
}
- if (errorMessage)
+ if (errorMessage) {
return {valid: false, errorMessage};
+ }
return {valid: true};
}
}
@@ -481,19 +495,22 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
* @param {!Adb.Device} device
*/
update(device) {
- if (!this._device || this._device.adbModel !== device.adbModel)
+ if (!this._device || this._device.adbModel !== device.adbModel) {
this._deviceTitle.textContent = device.adbModel;
+ }
- if (!this._device || this._device.adbSerial !== device.adbSerial)
+ if (!this._device || this._device.adbSerial !== device.adbSerial) {
this._deviceSerial.textContent = '#' + device.adbSerial;
+ }
this._deviceOffline.classList.toggle('hidden', device.adbConnected);
this._noBrowsers.classList.toggle('hidden', !device.adbConnected || !!device.browsers.length);
this._browsers.classList.toggle('hidden', !device.adbConnected || !device.browsers.length);
const browserIds = new Set();
- for (const browser of device.browsers)
+ for (const browser of device.browsers) {
browserIds.add(browser.id);
+ }
for (const browserId of this._browserById.keys()) {
if (!browserIds.has(browserId)) {
@@ -572,7 +589,7 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
function openNewTab() {
if (section.browser) {
- InspectorFrontendHost.openRemotePage(section.browser.id, newTabInput.value.trim() || 'about:blank');
+ Host.InspectorFrontendHost.openRemotePage(section.browser.id, newTabInput.value.trim() || 'about:blank');
newTabInput.value = '';
}
}
@@ -585,15 +602,17 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
_updateBrowserSection(section, browser) {
if (!section.browser || section.browser.adbBrowserName !== browser.adbBrowserName ||
section.browser.adbBrowserVersion !== browser.adbBrowserVersion) {
- if (browser.adbBrowserVersion)
+ if (browser.adbBrowserVersion) {
section.title.textContent = String.sprintf('%s (%s)', browser.adbBrowserName, browser.adbBrowserVersion);
- else
+ } else {
section.title.textContent = browser.adbBrowserName;
+ }
}
const pageIds = new Set();
- for (const page of browser.pages)
+ for (const page of browser.pages) {
pageIds.add(page.id);
+ }
for (const pageId of section.pageSections.keys()) {
if (!pageIds.has(pageId)) {
@@ -611,13 +630,15 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
section.pages.appendChild(pageSection.element);
}
this._updatePageSection(pageSection, page);
- if (!index && section.pages.firstChild !== pageSection.element)
+ if (!index && section.pages.firstChild !== pageSection.element) {
section.pages.insertBefore(pageSection.element, section.pages.firstChild);
+ }
}
const kViewMoreCount = 3;
- for (let index = 0, element = section.pages.firstChild; element; element = element.nextSibling, ++index)
+ for (let index = 0, element = section.pages.firstChild; element; element = element.nextSibling, ++index) {
element.classList.toggle('device-view-more-page', index >= kViewMoreCount);
+ }
section.viewMore.classList.toggle('device-needs-view-more', browser.pages.length > kViewMoreCount);
section.newTab.classList.toggle('hidden', !browser.adbBrowserChromeVersion);
section.browser = browser;
@@ -655,8 +676,9 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
* @param {string} action
*/
function doAction(action) {
- if (section.page)
- InspectorFrontendHost.performActionOnRemotePage(section.page.id, action);
+ if (section.page) {
+ Host.InspectorFrontendHost.performActionOnRemotePage(section.page.id, action);
+ }
}
}
@@ -683,8 +705,9 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
*/
portForwardingStatusChanged(status) {
const json = JSON.stringify(status);
- if (json === this._cachedPortStatus)
+ if (json === this._cachedPortStatus) {
return;
+ }
this._cachedPortStatus = json;
this._portStatus.removeChildren();
@@ -694,17 +717,19 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
const error = [];
let empty = true;
for (const port in status.ports) {
- if (!status.ports.hasOwnProperty(port))
+ if (!status.ports.hasOwnProperty(port)) {
continue;
+ }
empty = false;
const portStatus = status.ports[port];
const portNumber = createElementWithClass('div', 'device-view-port-number monospace');
portNumber.textContent = ':' + port;
- if (portStatus >= 0)
+ if (portStatus >= 0) {
this._portStatus.appendChild(portNumber);
- else
+ } else {
this._portStatus.insertBefore(portNumber, this._portStatus.firstChild);
+ }
const portIcon = createElementWithClass('div', 'device-view-port-icon');
if (portStatus >= 0) {
@@ -720,12 +745,15 @@ Devices.DevicesView.DeviceView = class extends UI.VBox {
}
const title = [];
- if (connected.length)
+ if (connected.length) {
title.push(Common.UIString('Connected: %s', connected.join(', ')));
- if (transient.length)
+ }
+ if (transient.length) {
title.push(Common.UIString('Transient: %s', transient.join(', ')));
- if (error.length)
+ }
+ if (error.length) {
title.push(Common.UIString('Error: %s', error.join(', ')));
+ }
this._portStatus.title = title.join('; ');
this._portStatus.classList.toggle('hidden', empty);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
index 065c7f51f13..1a3c208d36b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devices/devices_strings.grdp
@@ -4,7 +4,7 @@
Port Forwarding:
</message>
<message name="IDS_DEVTOOLS_034fd013261994214d1e8cb42571d191" desc="Text in Devices View of the Remote Devices tab">
- Need help? Read Chrome <ph name="DOCUMENTATIONLINK">$1s<ex>documentation link</ex></ph>.
+ Need help? Read <ph name="LOCKED_1">Chrome</ph> <ph name="DOCUMENTATIONLINK">$1s<ex>documentation link</ex></ph>.
</message>
<message name="IDS_DEVTOOLS_03fc5c0bd59679c442b86074c7a7cc3a" desc="Text in Devices View of the Remote Devices tab">
Port forwarding
@@ -45,12 +45,18 @@
<message name="IDS_DEVTOOLS_4d1c8263ba1036754f8db14a98f9f006" desc="A context menu item in the Devices View of the Remote Devices tab">
Reload
</message>
+ <message name="IDS_DEVTOOLS_532c28d5412dd75bf975fb951c740a30" desc="A tag of Remote Devices tool that can be searched in the command menu">
+ mobile
+ </message>
<message name="IDS_DEVTOOLS_588c54a3158082418d50afdfce55f954" desc="Error message for device port input box when add port forwarding rule">
Device port numbers can only be used once
</message>
<message name="IDS_DEVTOOLS_62e8d0a52dd33aa2b6548f7056739421" desc="Error message for device port input box when add port forwarding rule">
Device port number field is required
</message>
+ <message name="IDS_DEVTOOLS_62ed973d963913bb55111a7b8116ace1" desc="A tag of Remote Devices tool that can be searched in the command menu">
+ usb
+ </message>
<message name="IDS_DEVTOOLS_67afa587522e088dedac9f252362d16a" desc="Text in Devices View of the Remote Devices tab">
Discover USB devices
</message>
@@ -81,8 +87,8 @@
<message name="IDS_DEVTOOLS_bcca96534b404f08faf65d76be6aa782" desc="Text in Devices View of the Remote Devices tab">
1 device detected.
</message>
- <message name="IDS_DEVTOOLS_c03ca67dda321195d74c951097f240c6" desc="Text of a DOM element in Devices View of the Remote Devices tab">
- Devices
+ <message name="IDS_DEVTOOLS_c31b32364ce19ca8fcd150a417ecce58" desc="A tag of Remote Devices tool that can be searched in the command menu">
+ <ph name="LOCKED_1">android</ph>
</message>
<message name="IDS_DEVTOOLS_c3bf447eabe632720a3aa1a7ce401274" desc="Text of the new tab button in Devices View of the Remote Devices tab">
Open
@@ -105,18 +111,12 @@
<message name="IDS_DEVTOOLS_e1f70f4a4265cb51c1b219aa60eaa441" desc="New tab input placeholder in Devices View of the Remote Devices tab">
Enter URL
</message>
- <message name="IDS_DEVTOOLS_e24ee2487879116dcab772c0ac4fe341" desc="A context menu item in the Devices View of the Remote Devices tab">
- Focus
- </message>
<message name="IDS_DEVTOOLS_ed725244eec042fa550990c608639b38" desc="Text in Devices View of the Remote Devices tab">
Define the listening port on your device that maps to a port accessible from your development machine. Read <ph name="DOCUMENTATIONLINK">$1s<ex>documentation link</ex></ph> for more.
</message>
<message name="IDS_DEVTOOLS_f114563447e4786042d7e7ce05f1157c" desc="Text in Devices View of the Remote Devices tab">
Device port (3333)
</message>
- <message name="IDS_DEVTOOLS_f4f70727dc34561dfde1a3c529b6205c" desc="Discovery list item text content in Devices View of the Remote Devices tab">
- Settings
- </message>
<message name="IDS_DEVTOOLS_fa5ef75cf38d69be2973c570c1d47b29" desc="Error message for device port input box when add port forwarding rule">
Device port must be a number
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
index 81b6645e6a0..7387941327a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="devtools_app.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="devtools_app.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.js b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.js
index 17310fac140..75cbe26a15e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.js
@@ -1,4 +1,4 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Runtime.startApplication('devtools_app');
+Root.Runtime.startApplication('devtools_app');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.json b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.json
index 79074d565a1..a4039e33ff5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.json
@@ -8,7 +8,9 @@
{ "name": "animation" },
{ "name": "audits" },
{ "name": "browser_debugger" },
+ { "name": "css_overview" },
{ "name": "cookie_table" },
+ { "name": "dagre_layout", "type": "remote" },
{ "name": "devices" },
{ "name": "elements" },
{ "name": "emulated_devices" , "type": "remote" },
@@ -23,7 +25,8 @@
{ "name": "security" },
{ "name": "timeline" },
{ "name": "timeline_model" },
- { "name": "web_audio" }
+ { "name": "web_audio" },
+ { "name": "media" }
],
"extends": "shell",
"has_html": true
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js b/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
index ff6cc6df0e9..7335c20bb2f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
@@ -39,8 +39,9 @@
embedderMessageAck(id, arg) {
const callback = this._callbacks[id];
delete this._callbacks[id];
- if (callback)
+ if (callback) {
callback(arg);
+ }
}
/**
@@ -50,11 +51,13 @@
*/
sendMessageToEmbedder(method, args, callback) {
const callId = ++this._lastCallId;
- if (callback)
+ if (callback) {
this._callbacks[callId] = callback;
+ }
const message = {'id': callId, 'method': method};
- if (args.length)
+ if (args.length) {
message.params = args;
+ }
DevToolsHost.sendMessageToEmbedder(JSON.stringify(message));
}
@@ -80,10 +83,11 @@
// The addExtensions command is sent as the onload event happens for
// DevTools front-end. We should buffer this command until the frontend
// is ready for it.
- if (this._addExtensionCallback)
+ if (this._addExtensionCallback) {
extensions.forEach(this._addExtensionCallback);
- else
+ } else {
this._pendingExtensionDescriptors.pushAll(extensions);
+ }
}
}
@@ -249,6 +253,10 @@
}
}
+ reattachMainTarget() {
+ this._dispatchOnInspectorFrontendAPI('reattachMainTarget', []);
+ }
+
/**
* @param {boolean} hard
*/
@@ -287,10 +295,11 @@
*/
setInspectedTabId(tabId) {
// Support for legacy front-ends (<M41).
- if (window['WebInspector'] && window['WebInspector']['setInspectedTabId'])
+ if (window['WebInspector'] && window['WebInspector']['setInspectedTabId']) {
window['WebInspector']['setInspectedTabId'](tabId);
- else
+ } else {
this._dispatchOnInspectorFrontendAPI('setInspectedTabId', [tabId]);
+ }
}
/**
@@ -387,8 +396,9 @@
// Support for legacy (<57) frontends.
if (window.Runtime && window.Runtime.queryParam) {
const panelToOpen = window.Runtime.queryParam('panel');
- if (panelToOpen)
+ if (panelToOpen) {
window.DevToolsAPI.showPanel(panelToOpen);
+ }
}
}
@@ -558,8 +568,9 @@
*/
recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
// Support for M49 frontend.
- if (actionName === 'DevTools.DrawerShown')
+ if (actionName === 'DevTools.DrawerShown') {
return;
+ }
DevToolsAPI.sendMessageToEmbedder('recordEnumeratedHistogram', [actionName, actionCode, bucketSize], null);
}
@@ -1074,16 +1085,18 @@
function objectObserve(object, observer) {
if (window['WebInspector']) {
const settingPrototype = /** @type {!Object} */ (window['WebInspector']['Setting']['prototype']);
- if (typeof settingPrototype['remove'] === 'function')
+ if (typeof settingPrototype['remove'] === 'function') {
settingPrototype['remove'] = settingRemove;
+ }
}
/** @type {!Set<string>} */
const changedProperties = new Set();
let scheduled = false;
function scheduleObserver() {
- if (scheduled)
+ if (scheduled) {
return;
+ }
scheduled = true;
setImmediate(callObserver);
}
@@ -1129,8 +1142,9 @@
});
}
- for (let i = 0; i < properties.length; ++i)
+ for (let i = 0; i < properties.length; ++i) {
defineProperty(properties[i]);
+ }
}
window.Object.observe = objectObserve;
@@ -1202,20 +1216,23 @@
*/
function keyCodeToKeyIdentifier(keyCode) {
let result = staticKeyIdentifiers.get(keyCode);
- if (result !== undefined)
+ if (result !== undefined) {
return result;
+ }
result = 'U+';
const hexString = keyCode.toString(16).toUpperCase();
- for (let i = hexString.length; i < 4; ++i)
+ for (let i = hexString.length; i < 4; ++i) {
result += '0';
+ }
result += hexString;
return result;
}
function installBackwardsCompatibility() {
const majorVersion = getRemoteMajorVersion();
- if (!majorVersion)
+ if (!majorVersion) {
return;
+ }
/** @type {!Array<string>} */
const styleRules = [];
@@ -1236,15 +1253,17 @@
const origAdd = DOMTokenList.prototype.add;
DOMTokenList.prototype.add = function(...tokens) {
- if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header'))
+ if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) {
this._myElement.slot = '.' + tokens[0];
+ }
return origAdd.apply(this, tokens);
};
const origCreateElement = Document.prototype.createElement;
Document.prototype.createElement = function(tagName, ...rest) {
- if (tagName === 'content')
+ if (tagName === 'content') {
tagName = 'slot';
+ }
const element = origCreateElement.call(this, tagName, ...rest);
element.classList._myElement = element;
return element;
@@ -1256,31 +1275,33 @@
}
});
- // Document.prototype.createElementWithClass is a DevTools method, so we
- // need to wait for DOMContentLoaded in order to override it.
- if (window.document.head &&
- (window.document.readyState === 'complete' || window.document.readyState === 'interactive'))
- overrideCreateElementWithClass();
- else
- window.addEventListener('DOMContentLoaded', overrideCreateElementWithClass);
-
function overrideCreateElementWithClass() {
window.removeEventListener('DOMContentLoaded', overrideCreateElementWithClass);
const origCreateElementWithClass = Document.prototype.createElementWithClass;
Document.prototype.createElementWithClass = function(tagName, className, ...rest) {
- if (tagName !== 'button' || (className !== 'soft-dropdown' && className !== 'dropdown-button'))
+ if (tagName !== 'button' || (className !== 'soft-dropdown' && className !== 'dropdown-button')) {
return origCreateElementWithClass.call(this, tagName, className, ...rest);
+ }
const element = origCreateElementWithClass.call(this, 'div', className, ...rest);
element.tabIndex = 0;
element.role = 'button';
return element;
};
}
+
+ // Document.prototype.createElementWithClass is a DevTools method, so we
+ // need to wait for DOMContentLoaded in order to override it.
+ if (window.document.head &&
+ (window.document.readyState === 'complete' || window.document.readyState === 'interactive')) {
+ overrideCreateElementWithClass();
+ } else {
+ window.addEventListener('DOMContentLoaded', overrideCreateElementWithClass);
+ }
}
// Custom Elements V0 polyfill
- if (majorVersion <= 73 && !Document.prototype.registerElement) {
+ if (majorVersion <= 73 && !Document.prototype.hasOwnProperty('registerElement')) {
const fakeRegistry = new Map();
Document.prototype.registerElement = function(typeExtension, options) {
const {prototype, extends: localName} = options;
@@ -1289,13 +1310,15 @@
const element = document.createElement(localName || typeExtension);
const skip = new Set(['constructor', '__proto__']);
for (const key of Object.keys(Object.getOwnPropertyDescriptors(prototype.__proto__ || {}))) {
- if (skip.has(key))
+ if (skip.has(key)) {
continue;
+ }
element[key] = prototype[key];
}
element.setAttribute('is', typeExtension);
- if (element['createdCallback'])
+ if (element['createdCallback']) {
element['createdCallback']();
+ }
return element;
};
fakeRegistry.set(typeExtension, callback);
@@ -1305,8 +1328,9 @@
const origCreateElement = Document.prototype.createElement;
Document.prototype.createElement = function(tagName, fakeCustomElementType) {
const fakeConstructor = fakeRegistry.get(fakeCustomElementType);
- if (fakeConstructor)
+ if (fakeConstructor) {
return fakeConstructor();
+ }
return origCreateElement.call(this, tagName, fakeCustomElementType);
};
@@ -1316,8 +1340,9 @@
// classList.toggle('a');
const originalDOMTokenListToggle = DOMTokenList.prototype.toggle;
DOMTokenList.prototype.toggle = function(token, force) {
- if (arguments.length === 1)
+ if (arguments.length === 1) {
force = !this.contains(token);
+ }
return originalDOMTokenListToggle.call(this, token, !!force);
};
}
@@ -1335,8 +1360,9 @@
*/
ShadowRoot.prototype.elementFromPoint = function(x, y) {
const originalResult = ShadowRoot.prototype.__originalShadowRootElementFromPoint.apply(this, arguments);
- if (this.host && originalResult === this.host)
+ if (this.host && originalResult === this.host) {
return null;
+ }
return originalResult;
};
}
@@ -1354,8 +1380,9 @@
});
}
- if (majorVersion <= 50)
+ if (majorVersion <= 50) {
installObjectObserve();
+ }
if (majorVersion <= 45) {
/**
@@ -1389,8 +1416,9 @@
window.CSSPrimitiveValue = CSSPrimitiveValue;
}
- if (majorVersion <= 45)
+ if (majorVersion <= 45) {
styleRules.push('* { min-width: 0; min-height: 0; }');
+ }
if (majorVersion <= 51) {
// Support for quirky border-image behavior (<M51), see:
@@ -1404,8 +1432,9 @@
'.coverage-toolbar-container, .animation-timeline-toolbar-container, .computed-properties { flex-basis: auto; }');
}
- if (majorVersion <= 50)
+ if (majorVersion <= 50) {
Event.prototype.deepPath = undefined;
+ }
if (majorVersion <= 54) {
window.FileError = /** @type {!function (new: FileError) : ?} */ ({
@@ -1425,8 +1454,9 @@
function getRemoteMajorVersion() {
try {
const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
- if (!remoteVersion)
+ if (!remoteVersion) {
return null;
+ }
const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
return majorVersion;
} catch (e) {
@@ -1438,8 +1468,9 @@
* @param {!Array<string>} styleRules
*/
function installExtraStyleRules(styleRules) {
- if (!styleRules.length)
+ if (!styleRules.length) {
return;
+ }
const styleText = styleRules.join('\n');
document.head.appendChild(createStyleElement(styleText));
@@ -1457,7 +1488,6 @@
*/
function createStyleElement(styleText) {
const style = document.createElement('style');
- style.type = 'text/css';
style.textContent = styleText;
return style;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/diff/Diff.js b/chromium/third_party/blink/renderer/devtools/front_end/diff/Diff.js
index 0111d08f543..1bdced6d895 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/diff/Diff.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/diff/Diff.js
@@ -11,8 +11,9 @@ Diff.Diff = {
charDiff: function(text1, text2, cleanup) {
const differ = new diff_match_patch();
const diff = differ.diff_main(text1, text2);
- if (cleanup)
+ if (cleanup) {
differ.diff_cleanupSemantic(diff);
+ }
return diff;
},
@@ -31,8 +32,9 @@ Diff.Diff = {
const lineDiff = [];
for (let i = 0; i < diff.length; i++) {
const lines = [];
- for (let j = 0; j < diff[i][1].length; j++)
+ for (let j = 0; j < diff[i][1].length; j++) {
lines.push(idMap.fromChar(diff[i][1][j]));
+ }
lineDiff.push({0: diff[i][0], 1: lines});
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js b/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js
index a7006be660d..546bd61eeab 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/DOMExtension.js
@@ -42,15 +42,17 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
let endNode;
let endOffset = 0;
- if (!stayWithinNode)
+ if (!stayWithinNode) {
stayWithinNode = this;
+ }
if (!direction || direction === 'backward' || direction === 'both') {
let node = this;
while (node) {
if (node === stayWithinNode) {
- if (!startNode)
+ if (!startNode) {
startNode = stayWithinNode;
+ }
break;
}
@@ -65,8 +67,9 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
}
}
- if (startNode)
+ if (startNode) {
break;
+ }
node = node.traversePreviousNode(stayWithinNode);
}
@@ -84,8 +87,9 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
let node = this;
while (node) {
if (node === stayWithinNode) {
- if (!endNode)
+ if (!endNode) {
endNode = stayWithinNode;
+ }
break;
}
@@ -100,8 +104,9 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
}
}
- if (endNode)
+ if (endNode) {
break;
+ }
node = node.traverseNextNode(stayWithinNode);
}
@@ -129,11 +134,13 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di
*/
Node.prototype.traverseNextTextNode = function(stayWithin) {
let node = this.traverseNextNode(stayWithin);
- if (!node)
+ if (!node) {
return null;
+ }
const nonTextTags = {'STYLE': 1, 'SCRIPT': 1};
- while (node && (node.nodeType !== Node.TEXT_NODE || nonTextTags[node.parentElement.nodeName]))
+ while (node && (node.nodeType !== Node.TEXT_NODE || nonTextTags[node.parentElement.nodeName])) {
node = node.traverseNextNode(stayWithin);
+ }
return node;
};
@@ -145,23 +152,27 @@ Node.prototype.traverseNextTextNode = function(stayWithin) {
*/
Element.prototype.positionAt = function(x, y, relativeTo) {
let shift = {x: 0, y: 0};
- if (relativeTo)
+ if (relativeTo) {
shift = relativeTo.boxInWindow(this.ownerDocument.defaultView);
+ }
- if (typeof x === 'number')
+ if (typeof x === 'number') {
this.style.setProperty('left', (shift.x + x) + 'px');
- else
+ } else {
this.style.removeProperty('left');
+ }
- if (typeof y === 'number')
+ if (typeof y === 'number') {
this.style.setProperty('top', (shift.y + y) + 'px');
- else
+ } else {
this.style.removeProperty('top');
+ }
- if (typeof x === 'number' || typeof y === 'number')
+ if (typeof x === 'number' || typeof y === 'number') {
this.style.setProperty('position', 'absolute');
- else
+ } else {
this.style.removeProperty('position');
+ }
};
/**
@@ -183,8 +194,9 @@ Element.prototype.isScrolledToBottom = function() {
Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) {
for (let node = this; node && node !== this.ownerDocument; node = node.parentNodeOrShadowHost()) {
for (let i = 0; i < nameArray.length; ++i) {
- if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
+ if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) {
return node;
+ }
}
}
return null;
@@ -218,11 +230,13 @@ Node.prototype.enclosingNodeOrSelfWithClassList = function(classNames, stayWithi
if (node.nodeType === Node.ELEMENT_NODE) {
let containsAll = true;
for (let i = 0; i < classNames.length && containsAll; ++i) {
- if (!node.classList.contains(classNames[i]))
+ if (!node.classList.contains(classNames[i])) {
containsAll = false;
+ }
}
- if (containsAll)
+ if (containsAll) {
return /** @type {!Element} */ (node);
+ }
}
}
return null;
@@ -234,8 +248,9 @@ Node.prototype.enclosingNodeOrSelfWithClassList = function(classNames, stayWithi
Node.prototype.enclosingShadowRoot = function() {
let parentNode = this.parentNodeOrShadowHost();
while (parentNode) {
- if (parentNode instanceof ShadowRoot)
+ if (parentNode instanceof ShadowRoot) {
return parentNode;
+ }
parentNode = parentNode.parentNodeOrShadowHost();
}
return null;
@@ -253,15 +268,19 @@ Node.prototype.hasSameShadowRoot = function(node) {
* @return {?Element}
*/
Node.prototype.parentElementOrShadowHost = function() {
- if (this.nodeType === Node.DOCUMENT_FRAGMENT_NODE && this.host)
+ if (this.nodeType === Node.DOCUMENT_FRAGMENT_NODE && this.host) {
return /** @type {!Element} */ (this.host);
+ }
const node = this.parentNode;
- if (!node)
+ if (!node) {
return null;
- if (node.nodeType === Node.ELEMENT_NODE)
+ }
+ if (node.nodeType === Node.ELEMENT_NODE) {
return /** @type {!Element} */ (node);
- if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
+ }
+ if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
return /** @type {!Element} */ (node.host);
+ }
return null;
};
@@ -269,10 +288,12 @@ Node.prototype.parentElementOrShadowHost = function() {
* @return {?Node}
*/
Node.prototype.parentNodeOrShadowHost = function() {
- if (this.parentNode)
+ if (this.parentNode) {
return this.parentNode;
- if (this.nodeType === Node.DOCUMENT_FRAGMENT_NODE && this.host)
+ }
+ if (this.nodeType === Node.DOCUMENT_FRAGMENT_NODE && this.host) {
return this.host;
+ }
return null;
};
@@ -281,8 +302,9 @@ Node.prototype.parentNodeOrShadowHost = function() {
*/
Node.prototype.getComponentSelection = function() {
let parent = this.parentNode;
- while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE)
+ while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
parent = parent.parentNode;
+ }
return parent instanceof ShadowRoot ? parent.getSelection() : this.window().getSelection();
};
@@ -294,14 +316,16 @@ Node.prototype.hasSelection = function() {
if (this instanceof Element) {
const slots = this.querySelectorAll('slot');
for (const slot of slots) {
- if (Array.prototype.some.call(slot.assignedNodes(), node => node.hasSelection()))
+ if (Array.prototype.some.call(slot.assignedNodes(), node => node.hasSelection())) {
return true;
+ }
}
}
const selection = this.getComponentSelection();
- if (selection.type !== 'Range')
+ if (selection.type !== 'Range') {
return false;
+ }
return selection.containsNode(this, true) || selection.anchorNode.isSelfOrDescendant(this) ||
selection.focusNode.isSelfOrDescendant(this);
};
@@ -314,8 +338,9 @@ Node.prototype.window = function() {
};
Element.prototype.removeChildren = function() {
- if (this.firstChild)
+ if (this.firstChild) {
this.textContent = '';
+ }
};
/**
@@ -347,8 +372,9 @@ self.createTextNode = function(data) {
*/
Document.prototype.createElementWithClass = function(elementName, className, customElementType) {
const element = this.createElement(elementName, {is: customElementType});
- if (className)
+ if (className) {
element.className = className;
+ }
return element;
};
@@ -370,8 +396,9 @@ self.createElementWithClass = function(elementName, className, customElementType
*/
Document.prototype.createSVGElement = function(childType, className) {
const element = this.createElementNS('http://www.w3.org/2000/svg', childType);
- if (className)
+ if (className) {
element.setAttribute('class', className);
+ }
return element;
};
@@ -423,8 +450,9 @@ DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild;
* @param {...string} var_args
*/
Element.prototype.createTextChildren = function(var_args) {
- for (let i = 0, n = arguments.length; i < n; ++i)
+ for (let i = 0, n = arguments.length; i < n; ++i) {
this.createTextChild(arguments[i]);
+ }
};
DocumentFragment.prototype.createTextChildren = Element.prototype.createTextChildren;
@@ -487,33 +515,36 @@ var AnchorBox = class { // eslint-disable-line
contains(x, y) {
return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
}
-};
-/**
- * @param {!AnchorBox} box
- * @return {!AnchorBox}
- */
-AnchorBox.prototype.relativeTo = function(box) {
- return new AnchorBox(this.x - box.x, this.y - box.y, this.width, this.height);
-};
+ /**
+ * @param {!AnchorBox} box
+ * @return {!AnchorBox}
+ */
+ relativeTo(box) {
+ return new AnchorBox(this.x - box.x, this.y - box.y, this.width, this.height);
+ }
-/**
- * @param {!Element} element
- * @return {!AnchorBox}
- */
-AnchorBox.prototype.relativeToElement = function(element) {
- return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView));
-};
+ /**
+ * @param {!Element} element
+ * @return {!AnchorBox}
+ */
+ relativeToElement(element) {
+ return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView));
+ }
-/**
- * @param {?AnchorBox} anchorBox
- * @return {boolean}
- */
-AnchorBox.prototype.equals = function(anchorBox) {
- return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && this.width === anchorBox.width &&
- this.height === anchorBox.height;
+ /**
+ * @param {?AnchorBox} anchorBox
+ * @return {boolean}
+ */
+ equals(anchorBox) {
+ return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && this.width === anchorBox.width &&
+ this.height === anchorBox.height;
+ }
};
+/** @constructor */
+self.AnchorBox = AnchorBox;
+
/**
* @param {?Window=} targetWindow
* @return {!AnchorBox}
@@ -527,8 +558,9 @@ Element.prototype.boxInWindow = function(targetWindow) {
while (curWindow && curElement) {
anchorBox.x += curElement.totalOffsetLeft();
anchorBox.y += curElement.totalOffsetTop();
- if (curWindow === targetWindow)
+ if (curWindow === targetWindow) {
break;
+ }
curElement = curWindow.frameElement;
curWindow = curWindow.parent;
}
@@ -543,8 +575,9 @@ Element.prototype.boxInWindow = function(targetWindow) {
*/
Event.prototype.consume = function(preventDefault) {
this.stopImmediatePropagation();
- if (preventDefault)
+ if (preventDefault) {
this.preventDefault();
+ }
this.handled = true;
};
@@ -557,8 +590,9 @@ Text.prototype.select = function(start, end) {
start = start || 0;
end = end || this.textContent.length;
- if (start < 0)
+ if (start < 0) {
start = end + start;
+ }
const selection = this.getComponentSelection();
selection.removeAllRanges();
@@ -576,8 +610,9 @@ Element.prototype.selectionLeftOffset = function() {
// Calculate selection offset relative to the current element.
const selection = this.getComponentSelection();
- if (!selection.containsNode(this, true))
+ if (!selection.containsNode(this, true)) {
return null;
+ }
let leftOffset = selection.anchorOffset;
let node = selection.anchorNode;
@@ -597,8 +632,9 @@ Element.prototype.selectionLeftOffset = function() {
* @param {...!Node} var_args
*/
Node.prototype.appendChildren = function(var_args) {
- for (let i = 0, n = arguments.length; i < n; ++i)
+ for (let i = 0, n = arguments.length; i < n; ++i) {
this.appendChild(arguments[i]);
+ }
};
/**
@@ -620,8 +656,9 @@ Node.prototype.childTextNodes = function() {
const result = [];
const nonTextTags = {'STYLE': 1, 'SCRIPT': 1};
while (node) {
- if (!nonTextTags[node.parentElement.nodeName])
+ if (!nonTextTags[node.parentElement.nodeName]) {
result.push(node);
+ }
node = node.traverseNextTextNode(this);
}
return result;
@@ -632,13 +669,15 @@ Node.prototype.childTextNodes = function() {
* @return {boolean}
*/
Node.prototype.isAncestor = function(node) {
- if (!node)
+ if (!node) {
return false;
+ }
let currentNode = node.parentNodeOrShadowHost();
while (currentNode) {
- if (this === currentNode)
+ if (this === currentNode) {
return true;
+ }
currentNode = currentNode.parentNodeOrShadowHost();
}
return false;
@@ -673,25 +712,30 @@ Node.prototype.isSelfOrDescendant = function(node) {
* @return {?Node}
*/
Node.prototype.traverseNextNode = function(stayWithin) {
- if (this.shadowRoot)
+ if (this.shadowRoot) {
return this.shadowRoot;
+ }
const distributedNodes = this instanceof HTMLSlotElement ? this.assignedNodes() : [];
- if (distributedNodes.length)
+ if (distributedNodes.length) {
return distributedNodes[0];
+ }
- if (this.firstChild)
+ if (this.firstChild) {
return this.firstChild;
+ }
let node = this;
while (node) {
- if (stayWithin && node === stayWithin)
+ if (stayWithin && node === stayWithin) {
return null;
+ }
const sibling = nextSibling(node);
- if (sibling)
+ if (sibling) {
return sibling;
+ }
node = node.assignedSlot || node.parentNodeOrShadowHost();
}
@@ -701,13 +745,15 @@ Node.prototype.traverseNextNode = function(stayWithin) {
* @return {?Node}
*/
function nextSibling(node) {
- if (!node.assignedSlot)
+ if (!node.assignedSlot) {
return node.nextSibling;
+ }
const distributedNodes = node.assignedSlot.assignedNodes();
const position = Array.prototype.indexOf.call(distributedNodes, node);
- if (position + 1 < distributedNodes.length)
+ if (position + 1 < distributedNodes.length) {
return distributedNodes[position + 1];
+ }
return null;
}
@@ -719,13 +765,16 @@ Node.prototype.traverseNextNode = function(stayWithin) {
* @return {?Node}
*/
Node.prototype.traversePreviousNode = function(stayWithin) {
- if (stayWithin && this === stayWithin)
+ if (stayWithin && this === stayWithin) {
return null;
+ }
let node = this.previousSibling;
- while (node && node.lastChild)
+ while (node && node.lastChild) {
node = node.lastChild;
- if (node)
+ }
+ if (node) {
return node;
+ }
return this.parentNodeOrShadowHost();
};
@@ -754,8 +803,10 @@ Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder) {
*/
Event.prototype.deepElementFromPoint = function() {
// Some synthetic events have zero coordinates which lead to a wrong element. Better return nothing in this case.
- if (!this.which && !this.pageX && !this.pageY && !this.clientX && !this.clientY && !this.movementX && !this.movementY)
+ if (!this.which && !this.pageX && !this.pageY && !this.clientX && !this.clientY && !this.movementX &&
+ !this.movementY) {
return null;
+ }
const root = this.target && this.target.getComponentRoot();
return root ? root.deepElementFromPoint(this.pageX, this.pageY) : null;
};
@@ -770,8 +821,9 @@ Document.prototype.deepElementFromPoint = function(x, y) {
let node = null;
while (container) {
const innerNode = container.elementFromPoint(x, y);
- if (!innerNode || node === innerNode)
+ if (!innerNode || node === innerNode) {
break;
+ }
node = innerNode;
container = node.shadowRoot;
}
@@ -785,8 +837,9 @@ DocumentFragment.prototype.deepElementFromPoint = Document.prototype.deepElement
*/
Document.prototype.deepActiveElement = function() {
let activeElement = this.activeElement;
- while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
+ while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) {
activeElement = activeElement.shadowRoot.activeElement;
+ }
return activeElement;
};
@@ -805,8 +858,9 @@ Element.prototype.hasFocus = function() {
*/
Node.prototype.getComponentRoot = function() {
let node = this;
- while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeType !== Node.DOCUMENT_NODE)
+ while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeType !== Node.DOCUMENT_NODE) {
node = node.parentNode;
+ }
return /** @type {?Document|?DocumentFragment} */ (node);
};
@@ -814,13 +868,14 @@ Node.prototype.getComponentRoot = function() {
* @param {!Element} element
* @param {function(!Event)} callback
*/
-function onInvokeElement(element, callback) {
+self.onInvokeElement = function(element, callback) {
element.addEventListener('keydown', event => {
- if (self.isEnterOrSpaceKey(event))
+ if (self.isEnterOrSpaceKey(event)) {
callback(event);
+ }
});
element.addEventListener('click', event => callback(event));
-}
+};
/**
* @param {!Event} event
@@ -854,8 +909,9 @@ self.isEscKey = function(event) {
(function() {
const originalToggle = DOMTokenList.prototype.toggle;
DOMTokenList.prototype['toggle'] = function(token, force) {
- if (arguments.length === 1)
+ if (arguments.length === 1) {
force = !this.contains(token);
+ }
return originalToggle.call(this, token, !!force);
};
})();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/module.json b/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/module.json
index 7f64ee3cf1e..3d7c22e005a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/dom_extension/module.json
@@ -2,7 +2,8 @@
"dependencies": [
"platform"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
"DOMExtension.js"
]
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ClassesPaneWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ClassesPaneWidget.js
index ff33a6d13fa..6d3fd268ff0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ClassesPaneWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ClassesPaneWidget.js
@@ -48,19 +48,22 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
* @param {!Event} event
*/
_onKeyDown(event) {
- if (!isEnterKey(event) && !isEscKey(event))
+ if (!isEnterKey(event) && !isEscKey(event)) {
return;
+ }
if (isEnterKey(event)) {
event.consume();
- if (this._prompt.acceptAutoComplete())
+ if (this._prompt.acceptAutoComplete()) {
return;
+ }
}
let text = event.target.textContent;
if (isEscKey(event)) {
- if (!text.isWhitespace())
+ if (!text.isWhitespace()) {
event.consume(true);
+ }
text = '';
}
@@ -68,20 +71,23 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
event.target.textContent = '';
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return;
+ }
const classNames = this._splitTextIntoClasses(text);
- for (const className of classNames)
+ for (const className of classNames) {
this._toggleClass(node, className, true);
+ }
this._installNodeClasses(node);
this._update();
}
_onTextChanged() {
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return;
+ }
this._installNodeClasses(node);
}
@@ -90,8 +96,9 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
*/
_onDOMMutated(event) {
const node = /** @type {!SDK.DOMNode} */ (event.data);
- if (this._mutatingNodes.has(node))
+ if (this._mutatingNodes.has(node)) {
return;
+ }
delete node[Elements.ClassesPaneWidget._classesSymbol];
this._update();
}
@@ -116,18 +123,21 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
}
_update() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
let node = UI.context.flavor(SDK.DOMNode);
- if (node)
+ if (node) {
node = node.enclosingElementOrSelf();
+ }
this._classesContainer.removeChildren();
this._input.disabled = !node;
- if (!node)
+ if (!node) {
return;
+ }
const classes = this._nodeClasses(node);
const keys = classes.keysArray();
@@ -147,8 +157,9 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
*/
_onClick(className, event) {
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return;
+ }
const enabled = event.target.checked;
this._toggleClass(node, className, enabled);
this._installNodeClasses(node);
@@ -166,8 +177,9 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
result = new Map();
for (let i = 0; i < classes.length; ++i) {
const className = classes[i].trim();
- if (!className.length)
+ if (!className.length) {
continue;
+ }
result.set(className, true);
}
node[Elements.ClassesPaneWidget._classesSymbol] = result;
@@ -192,13 +204,15 @@ Elements.ClassesPaneWidget = class extends UI.Widget {
const classes = this._nodeClasses(node);
const activeClasses = new Set();
for (const className of classes.keys()) {
- if (classes.get(className))
+ if (classes.get(className)) {
activeClasses.add(className);
+ }
}
const additionalClasses = this._splitTextIntoClasses(this._prompt.textWithCurrentSuggestion());
- for (const className of additionalClasses)
+ for (const className of additionalClasses) {
activeClasses.add(className);
+ }
const newClasses = activeClasses.valuesArray();
newClasses.sort();
@@ -287,8 +301,9 @@ Elements.ClassesPaneWidget.ClassNamePrompt = class extends UI.TextPrompt {
const cssModel = selectedNode.domModel().cssModel();
const allStyleSheets = cssModel.allStyleSheets();
for (const stylesheet of allStyleSheets) {
- if (stylesheet.frameId !== this._selectedFrameId)
+ if (stylesheet.frameId !== this._selectedFrameId) {
continue;
+ }
const cssPromise = cssModel.classNamesPromise(stylesheet.id).then(classes => completions.addAll(classes));
promises.push(cssPromise);
}
@@ -307,22 +322,26 @@ Elements.ClassesPaneWidget.ClassNamePrompt = class extends UI.TextPrompt {
* @return {!Promise<!UI.SuggestBox.Suggestions>}
*/
_buildClassNameCompletions(expression, prefix, force) {
- if (!prefix || force)
+ if (!prefix || force) {
this._classNamesPromise = null;
+ }
const selectedNode = UI.context.flavor(SDK.DOMNode);
- if (!selectedNode || (!prefix && !force && !expression.trim()))
+ if (!selectedNode || (!prefix && !force && !expression.trim())) {
return Promise.resolve([]);
+ }
- if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frameId())
+ if (!this._classNamesPromise || this._selectedFrameId !== selectedNode.frameId()) {
this._classNamesPromise = this._getClassNames(selectedNode);
+ }
return this._classNamesPromise.then(completions => {
const classesMap = this._nodeClasses(/** @type {!SDK.DOMNode} */ (selectedNode));
completions = completions.filter(value => !classesMap.get(value));
- if (prefix[0] === '.')
+ if (prefix[0] === '.') {
completions = completions.map(value => '.' + value);
+ }
return completions.filter(value => value.startsWith(prefix)).sort().map(completion => ({text: completion}));
});
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ColorSwatchPopoverIcon.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ColorSwatchPopoverIcon.js
index c2bb78b4c3c..e8426ceb1e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ColorSwatchPopoverIcon.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ColorSwatchPopoverIcon.js
@@ -43,14 +43,16 @@ Elements.BezierPopoverIcon = class {
this._bezierEditor.addEventListener(InlineEditor.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
this._swatchPopoverHelper.show(this._bezierEditor, this._swatch.iconElement(), this._onPopoverHidden.bind(this));
this._scrollerElement = this._swatch.enclosingNodeOrSelfWithClass('style-panes-wrapper');
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
+ }
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.cssWorkspaceBinding.propertyUILocation(this._treeElement.property, false /* forName */);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
+ }
}
/**
@@ -72,8 +74,9 @@ Elements.BezierPopoverIcon = class {
* @param {boolean} commitEdit
*/
_onPopoverHidden(commitEdit) {
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
+ }
this._bezierEditor.removeEventListener(InlineEditor.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
delete this._bezierEditor;
@@ -120,14 +123,17 @@ Elements.ColorSwatchPopoverIcon = class {
const colors = [];
const colorNames = [];
for (const cssVariable of cssVariables) {
- if (cssVariable === this._treeElement.property.name)
+ if (cssVariable === this._treeElement.property.name) {
continue;
+ }
const value = matchedStyles.computeCSSVariable(style, cssVariable);
- if (!value)
+ if (!value) {
continue;
+ }
const color = Common.Color.parse(value);
- if (!color)
+ if (!color) {
continue;
+ }
colors.push(value);
colorNames.push(cssVariable);
}
@@ -165,8 +171,9 @@ Elements.ColorSwatchPopoverIcon = class {
const color = this._swatch.color();
let format = this._swatch.format();
- if (format === Common.Color.Format.Original)
+ if (format === Common.Color.Format.Original) {
format = color.format();
+ }
this._spectrum = new ColorPicker.Spectrum(this._contrastInfo);
this._spectrum.setColor(color, format);
this._spectrum.addPalette(this._generateCSSVariablesPalette());
@@ -175,14 +182,16 @@ Elements.ColorSwatchPopoverIcon = class {
this._spectrum.addEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
this._swatchPopoverHelper.show(this._spectrum, this._swatch.iconElement(), this._onPopoverHidden.bind(this));
this._scrollerElement = this._swatch.enclosingNodeOrSelfWithClass('style-panes-wrapper');
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
+ }
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.cssWorkspaceBinding.propertyUILocation(this._treeElement.property, false /* forName */);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
+ }
}
/**
@@ -197,12 +206,14 @@ Elements.ColorSwatchPopoverIcon = class {
*/
_spectrumChanged(event) {
const color = Common.Color.parse(/** @type {string} */ (event.data));
- if (!color)
+ if (!color) {
return;
+ }
this._swatch.setColor(color);
const colorName = this._spectrum.colorName();
- if (colorName && colorName.startsWith('--'))
+ if (colorName && colorName.startsWith('--')) {
this._swatch.setText(`var(${colorName})`);
+ }
this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
}
@@ -218,8 +229,9 @@ Elements.ColorSwatchPopoverIcon = class {
* @param {boolean} commitEdit
*/
_onPopoverHidden(commitEdit) {
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
+ }
this._spectrum.removeEventListener(ColorPicker.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
delete this._spectrum;
@@ -285,14 +297,16 @@ Elements.ShadowSwatchPopoverHelper = class {
this._cssShadowEditor.addEventListener(InlineEditor.CSSShadowEditor.Events.ShadowChanged, this._boundShadowChanged);
this._swatchPopoverHelper.show(this._cssShadowEditor, this._iconElement, this._onPopoverHidden.bind(this));
this._scrollerElement = this._iconElement.enclosingNodeOrSelfWithClass('style-panes-wrapper');
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.addEventListener('scroll', this._boundOnScroll, false);
+ }
this._originalPropertyText = this._treeElement.property.propertyText;
this._treeElement.parentPane().setEditingStyle(true);
const uiLocation = Bindings.cssWorkspaceBinding.propertyUILocation(this._treeElement.property, false /* forName */);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation, true /* omitFocus */);
+ }
}
/**
@@ -314,8 +328,9 @@ Elements.ShadowSwatchPopoverHelper = class {
* @param {boolean} commitEdit
*/
_onPopoverHidden(commitEdit) {
- if (this._scrollerElement)
+ if (this._scrollerElement) {
this._scrollerElement.removeEventListener('scroll', this._boundOnScroll, false);
+ }
this._cssShadowEditor.removeEventListener(
InlineEditor.CSSShadowEditor.Events.ShadowChanged, this._boundShadowChanged);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleModel.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleModel.js
index 6236deae954..f39900f5f82 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleModel.js
@@ -40,8 +40,9 @@ Elements.ComputedStyleModel = class extends Common.Object {
* @param {?SDK.CSSModel} cssModel
*/
_updateModel(cssModel) {
- if (this._cssModel === cssModel)
+ if (this._cssModel === cssModel) {
return;
+ }
Common.EventTarget.removeEventListeners(this._eventListeners);
this._cssModel = cssModel;
const domModel = cssModel ? cssModel.domModel() : null;
@@ -75,8 +76,10 @@ Elements.ComputedStyleModel = class extends Common.Object {
_onDOMModelChanged(event) {
// Any attribute removal or modification can affect the styles of "related" nodes.
const node = /** @type {!SDK.DOMNode} */ (event.data);
- if (!this._node || this._node !== node && node.parentNode !== this._node.parentNode && !node.isAncestor(this._node))
+ if (!this._node ||
+ this._node !== node && node.parentNode !== this._node.parentNode && !node.isAncestor(this._node)) {
return;
+ }
this._onComputedStyleChanged(null);
}
@@ -92,8 +95,9 @@ Elements.ComputedStyleModel = class extends Common.Object {
delete this._frameResizedTimer;
}
- if (this._frameResizedTimer)
+ if (this._frameResizedTimer) {
clearTimeout(this._frameResizedTimer);
+ }
this._frameResizedTimer = setTimeout(refreshContents.bind(this), 100);
}
@@ -111,8 +115,9 @@ Elements.ComputedStyleModel = class extends Common.Object {
fetchComputedStyle() {
const elementNode = this._elementNode();
const cssModel = this.cssModel();
- if (!elementNode || !cssModel)
+ if (!elementNode || !cssModel) {
return Promise.resolve(/** @type {?Elements.ComputedStyleModel.ComputedStyle} */ (null));
+ }
if (!this._computedStylePromise) {
this._computedStylePromise =
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
index 43d8b22ad8f..726d5adb766 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
@@ -109,8 +109,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
*/
_fetchMatchedCascade() {
const node = this._computedStyleModel.node();
- if (!node || !this._computedStyleModel.cssModel())
+ if (!node || !this._computedStyleModel.cssModel()) {
return Promise.resolve(/** @type {?SDK.CSSMatchedStyles} */ (null));
+ }
return this._computedStyleModel.cssModel().cachedMatchedCascadeForNode(node).then(validateStyles.bind(this));
@@ -130,8 +131,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
*/
_processColor(text) {
const color = Common.Color.parse(text);
- if (!color)
+ if (!color) {
return createTextNode(text);
+ }
const swatch = InlineEditor.ColorSwatch.create();
swatch.setColor(color);
swatch.setFormat(Common.Color.detectColorFormat(color));
@@ -146,8 +148,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
/** @type {!Set<string>} */
const expandedProperties = new Set();
for (const treeElement of this._propertiesOutline.rootElement().children()) {
- if (!treeElement.expanded)
+ if (!treeElement.expanded) {
continue;
+ }
const propertyName = treeElement[Elements.ComputedStyleWidget._propertySymbol].name;
expandedProperties.add(propertyName);
}
@@ -171,12 +174,15 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
const propertyValue = nodeStyle.computedStyle.get(propertyName);
const canonicalName = SDK.cssMetadata().canonicalPropertyName(propertyName);
const inherited = !inhertiedProperties.has(canonicalName);
- if (!showInherited && inherited && !(propertyName in this._alwaysShowComputedProperties))
+ if (!showInherited && inherited && !(propertyName in this._alwaysShowComputedProperties)) {
continue;
- if (!showInherited && propertyName.startsWith('--'))
+ }
+ if (!showInherited && propertyName.startsWith('--')) {
continue;
- if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName))
+ }
+ if (propertyName !== canonicalName && propertyValue === nodeStyle.computedStyle.get(canonicalName)) {
continue;
+ }
const propertyElement = createElement('div');
propertyElement.classList.add('computed-style-property');
@@ -208,8 +214,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
const isOdd = this._propertiesOutline.rootElement().children().length % 2 === 0;
treeElement.listItemElement.classList.toggle('odd-row', isOdd);
this._propertiesOutline.appendChild(treeElement);
- if (!this._propertiesOutline.selectedTreeElement)
+ if (!this._propertiesOutline.selectedTreeElement) {
treeElement.select(!hadFocus);
+ }
const trace = propertyTraces.get(propertyName);
if (trace) {
@@ -217,11 +224,14 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
treeElement.listItemElement.addEventListener('mousedown', e => e.consume(), false);
treeElement.listItemElement.addEventListener('dblclick', e => e.consume(), false);
treeElement.listItemElement.addEventListener('click', handleClick.bind(null, treeElement), false);
+ treeElement.listItemElement.addEventListener(
+ 'contextmenu', this._handleContextMenuEvent.bind(this, matchedStyles, activeProperty));
const gotoSourceElement = UI.Icon.create('mediumicon-arrow-in-circle', 'goto-source-icon');
gotoSourceElement.addEventListener('click', this._navigateToSource.bind(this, activeProperty));
propertyValueElement.appendChild(gotoSourceElement);
- if (expandedProperties.has(propertyName))
+ if (expandedProperties.has(propertyName)) {
treeElement.expand();
+ }
}
}
@@ -233,10 +243,12 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
* @return {number}
*/
function propertySorter(a, b) {
- if (a.startsWith('--') ^ b.startsWith('--'))
+ if (a.startsWith('--') ^ b.startsWith('--')) {
return a.startsWith('--') ? 1 : -1;
- if (a.startsWith('-webkit') ^ b.startsWith('-webkit'))
+ }
+ if (a.startsWith('-webkit') ^ b.startsWith('-webkit')) {
return a.startsWith('-webkit') ? 1 : -1;
+ }
const canonical1 = SDK.cssMetadata().canonicalPropertyName(a);
const canonical2 = SDK.cssMetadata().canonicalPropertyName(b);
return canonical1.compareTo(canonical2);
@@ -247,10 +259,11 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
* @param {!Event} event
*/
function handleClick(treeElement, event) {
- if (!treeElement.expanded)
+ if (!treeElement.expanded) {
treeElement.expand();
- else
+ } else {
treeElement.collapse();
+ }
event.consume();
}
}
@@ -277,10 +290,11 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
for (const property of tracedProperties) {
const trace = createElement('div');
trace.classList.add('property-trace');
- if (matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Overloaded)
+ if (matchedStyles.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.Overloaded) {
trace.classList.add('property-trace-inactive');
- else
+ } else {
activeProperty = property;
+ }
const renderer =
new Elements.StylesSidebarPropertyRenderer(null, node, property.name, /** @type {string} */ (property.value));
@@ -307,6 +321,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
const traceTreeElement = new UI.TreeElement();
traceTreeElement.title = trace;
+
+ traceTreeElement.listItemElement.addEventListener(
+ 'contextmenu', this._handleContextMenuEvent.bind(this, matchedStyles, property));
rootTreeElement.appendChild(traceTreeElement);
}
return /** @type {!SDK.CSSProperty} */ (activeProperty);
@@ -314,6 +331,28 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
/**
* @param {!SDK.CSSMatchedStyles} matchedStyles
+ * @param {!SDK.CSSProperty} property
+ * @param {!Event} event
+ */
+ _handleContextMenuEvent(matchedStyles, property, event) {
+ const contextMenu = new UI.ContextMenu(event);
+ const rule = property.ownerStyle.parentRule;
+
+ if (rule) {
+ const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;
+ if (header && !header.isAnonymousInlineStyleSheet()) {
+ contextMenu.defaultSection().appendItem(ls`Navigate to selector source`, () => {
+ Elements.StylePropertiesSection.tryNavigateToRuleLocation(matchedStyles, rule);
+ });
+ }
+ }
+
+ contextMenu.defaultSection().appendItem(ls`Navigate to style`, () => Common.Revealer.reveal(property));
+ contextMenu.show();
+ }
+
+ /**
+ * @param {!SDK.CSSMatchedStyles} matchedStyles
* @return {!Map<string, !Array<!SDK.CSSProperty>>}
*/
_computePropertyTraces(matchedStyles) {
@@ -321,10 +360,12 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
for (const style of matchedStyles.nodeStyles()) {
const allProperties = style.allProperties();
for (const property of allProperties) {
- if (!property.activeInStyle() || !matchedStyles.propertyState(property))
+ if (!property.activeInStyle() || !matchedStyles.propertyState(property)) {
continue;
- if (!result.has(property.name))
+ }
+ if (!result.has(property.name)) {
result.set(property.name, []);
+ }
result.get(property.name).push(property);
}
}
@@ -339,8 +380,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
const result = new Set();
for (const style of matchedStyles.nodeStyles()) {
for (const property of style.allProperties()) {
- if (!matchedStyles.propertyState(property))
+ if (!matchedStyles.propertyState(property)) {
continue;
+ }
result.add(SDK.cssMetadata().canonicalPropertyName(property.name));
}
}
@@ -359,7 +401,7 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
child.hidden = !matched;
hasMatch |= matched;
}
- this._noMatchesElement.classList.toggle('hidden', hasMatch);
+ this._noMatchesElement.classList.toggle('hidden', !!hasMatch);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
index a8301ac605a..0723d3ae637 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
@@ -12,8 +12,9 @@ Elements.DOMLinkifier = {};
Elements.DOMLinkifier.decorateNodeLabel = function(node, parentElement, tooltipContent) {
const originalNode = node;
const isPseudo = node.nodeType() === Node.ELEMENT_NODE && node.pseudoType();
- if (isPseudo && node.parentNode)
+ if (isPseudo && node.parentNode) {
node = node.parentNode;
+ }
let title = node.nodeNameInCorrectCase();
@@ -65,8 +66,9 @@ Elements.DOMLinkifier.decorateNodeLabel = function(node, parentElement, tooltipC
* @return {!Node}
*/
Elements.DOMLinkifier.linkifyNodeReference = function(node, options = {}) {
- if (!node)
+ if (!node) {
return createTextNode(Common.UIString('<node>'));
+ }
const root = createElementWithClass('span', 'monospace');
const shadowRoot = UI.createShadowRootWithCoreStyles(root, 'elements/domLinkifier.css');
@@ -127,10 +129,12 @@ Elements.DOMLinkifier.Linkifier = class {
* @return {!Node}
*/
linkify(object, options) {
- if (object instanceof SDK.DOMNode)
+ if (object instanceof SDK.DOMNode) {
return Elements.DOMLinkifier.linkifyNodeReference(object, options);
- if (object instanceof SDK.DeferredDOMNode)
+ }
+ if (object instanceof SDK.DeferredDOMNode) {
return Elements.DOMLinkifier.linkifyDeferredNodeReference(object, options);
+ }
throw new Error('Can\'t linkify non-node');
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMPath.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMPath.js
index 52c160793db..6ddbbaab36b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMPath.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMPath.js
@@ -10,8 +10,9 @@ Elements.DOMPath = {};
* @return {string}
*/
Elements.DOMPath.fullQualifiedSelector = function(node, justSelector) {
- if (node.nodeType() !== Node.ELEMENT_NODE)
+ if (node.nodeType() !== Node.ELEMENT_NODE) {
return node.localName() || node.nodeName().toLowerCase();
+ }
return Elements.DOMPath.cssPath(node, justSelector);
};
@@ -21,18 +22,21 @@ Elements.DOMPath.fullQualifiedSelector = function(node, justSelector) {
* @return {string}
*/
Elements.DOMPath.cssPath = function(node, optimized) {
- if (node.nodeType() !== Node.ELEMENT_NODE)
+ if (node.nodeType() !== Node.ELEMENT_NODE) {
return '';
+ }
const steps = [];
let contextNode = node;
while (contextNode) {
const step = Elements.DOMPath._cssPathStep(contextNode, !!optimized, contextNode === node);
- if (!step)
- break; // Error - bail out early.
+ if (!step) {
+ break;
+ } // Error - bail out early.
steps.push(step);
- if (step.optimized)
+ if (step.optimized) {
break;
+ }
contextNode = contextNode.parentNode;
}
@@ -47,8 +51,9 @@ Elements.DOMPath.cssPath = function(node, optimized) {
Elements.DOMPath.canGetJSPath = function(node) {
let wp = node;
while (wp) {
- if (wp.ancestorShadowRoot() && wp.ancestorShadowRoot().shadowRootType() !== SDK.DOMNode.ShadowRootTypes.Open)
+ if (wp.ancestorShadowRoot() && wp.ancestorShadowRoot().shadowRootType() !== SDK.DOMNode.ShadowRootTypes.Open) {
return false;
+ }
wp = wp.ancestorShadowHost();
}
return true;
@@ -60,8 +65,9 @@ Elements.DOMPath.canGetJSPath = function(node) {
* @return {string}
*/
Elements.DOMPath.jsPath = function(node, optimized) {
- if (node.nodeType() !== Node.ELEMENT_NODE)
+ if (node.nodeType() !== Node.ELEMENT_NODE) {
return '';
+ }
const path = [];
let wp = node;
@@ -73,10 +79,11 @@ Elements.DOMPath.jsPath = function(node, optimized) {
let result = '';
for (let i = 0; i < path.length; ++i) {
const string = JSON.stringify(path[i]);
- if (i)
+ if (i) {
result += `.shadowRoot.querySelector(${string})`;
- else
+ } else {
result += `document.querySelector(${string})`;
+ }
}
return result;
};
@@ -88,24 +95,29 @@ Elements.DOMPath.jsPath = function(node, optimized) {
* @return {?Elements.DOMPath.Step}
*/
Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
- if (node.nodeType() !== Node.ELEMENT_NODE)
+ if (node.nodeType() !== Node.ELEMENT_NODE) {
return null;
+ }
const id = node.getAttribute('id');
if (optimized) {
- if (id)
+ if (id) {
return new Elements.DOMPath.Step(idSelector(id), true);
+ }
const nodeNameLower = node.nodeName().toLowerCase();
- if (nodeNameLower === 'body' || nodeNameLower === 'head' || nodeNameLower === 'html')
+ if (nodeNameLower === 'body' || nodeNameLower === 'head' || nodeNameLower === 'html') {
return new Elements.DOMPath.Step(node.nodeNameInCorrectCase(), true);
+ }
}
const nodeName = node.nodeNameInCorrectCase();
- if (id)
+ if (id) {
return new Elements.DOMPath.Step(nodeName + idSelector(id), true);
+ }
const parent = node.parentNode;
- if (!parent || parent.nodeType() === Node.DOCUMENT_NODE)
+ if (!parent || parent.nodeType() === Node.DOCUMENT_NODE) {
return new Elements.DOMPath.Step(nodeName, true);
+ }
/**
* @param {!SDK.DOMNode} node
@@ -113,8 +125,9 @@ Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
*/
function prefixedElementClassNames(node) {
const classAttribute = node.getAttribute('class');
- if (!classAttribute)
+ if (!classAttribute) {
return [];
+ }
return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) {
// The prefix is required to store "__proto__" in a object-based map.
@@ -138,17 +151,20 @@ Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
const siblings = parent.children();
for (let i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) {
const sibling = siblings[i];
- if (sibling.nodeType() !== Node.ELEMENT_NODE)
+ if (sibling.nodeType() !== Node.ELEMENT_NODE) {
continue;
+ }
elementIndex += 1;
if (sibling === node) {
ownIndex = elementIndex;
continue;
}
- if (needsNthChild)
+ if (needsNthChild) {
continue;
- if (sibling.nodeNameInCorrectCase() !== nodeName)
+ }
+ if (sibling.nodeNameInCorrectCase() !== nodeName) {
continue;
+ }
needsClassNames = true;
const ownClassNames = new Set(prefixedOwnClassNamesArray);
@@ -159,8 +175,9 @@ Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
const siblingClassNamesArray = prefixedElementClassNames(sibling);
for (let j = 0; j < siblingClassNamesArray.length; ++j) {
const siblingClass = siblingClassNamesArray[j];
- if (!ownClassNames.has(siblingClass))
+ if (!ownClassNames.has(siblingClass)) {
continue;
+ }
ownClassNames.delete(siblingClass);
if (!ownClassNames.size) {
needsNthChild = true;
@@ -171,13 +188,15 @@ Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
let result = nodeName;
if (isTargetNode && nodeName.toLowerCase() === 'input' && node.getAttribute('type') && !node.getAttribute('id') &&
- !node.getAttribute('class'))
+ !node.getAttribute('class')) {
result += '[type=' + CSS.escape(node.getAttribute('type')) + ']';
+ }
if (needsNthChild) {
result += ':nth-child(' + (ownIndex + 1) + ')';
} else if (needsClassNames) {
- for (const prefixedName of prefixedOwnClassNamesArray)
+ for (const prefixedName of prefixedOwnClassNamesArray) {
result += '.' + CSS.escape(prefixedName.slice(1));
+ }
}
return new Elements.DOMPath.Step(result, false);
@@ -189,18 +208,21 @@ Elements.DOMPath._cssPathStep = function(node, optimized, isTargetNode) {
* @return {string}
*/
Elements.DOMPath.xPath = function(node, optimized) {
- if (node.nodeType() === Node.DOCUMENT_NODE)
+ if (node.nodeType() === Node.DOCUMENT_NODE) {
return '/';
+ }
const steps = [];
let contextNode = node;
while (contextNode) {
const step = Elements.DOMPath._xPathValue(contextNode, optimized);
- if (!step)
- break; // Error - bail out early.
+ if (!step) {
+ break;
+ } // Error - bail out early.
steps.push(step);
- if (step.optimized)
+ if (step.optimized) {
break;
+ }
contextNode = contextNode.parentNode;
}
@@ -216,13 +238,15 @@ Elements.DOMPath.xPath = function(node, optimized) {
Elements.DOMPath._xPathValue = function(node, optimized) {
let ownValue;
const ownIndex = Elements.DOMPath._xPathIndex(node);
- if (ownIndex === -1)
- return null; // Error.
+ if (ownIndex === -1) {
+ return null;
+ } // Error.
switch (node.nodeType()) {
case Node.ELEMENT_NODE:
- if (optimized && node.getAttribute('id'))
+ if (optimized && node.getAttribute('id')) {
return new Elements.DOMPath.Step('//*[@id="' + node.getAttribute('id') + '"]', true);
+ }
ownValue = node.localName();
break;
case Node.ATTRIBUTE_NODE:
@@ -246,8 +270,9 @@ Elements.DOMPath._xPathValue = function(node, optimized) {
break;
}
- if (ownIndex > 0)
+ if (ownIndex > 0) {
ownValue += '[' + ownIndex + ']';
+ }
return new Elements.DOMPath.Step(ownValue, node.nodeType() === Node.DOCUMENT_NODE);
};
@@ -259,14 +284,17 @@ Elements.DOMPath._xPathValue = function(node, optimized) {
Elements.DOMPath._xPathIndex = function(node) {
// Returns -1 in case of error, 0 if no siblings matching the same expression, <XPath index among the same expression-matching sibling nodes> otherwise.
function areNodesSimilar(left, right) {
- if (left === right)
+ if (left === right) {
return true;
+ }
- if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.ELEMENT_NODE)
+ if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.ELEMENT_NODE) {
return left.localName() === right.localName();
+ }
- if (left.nodeType() === right.nodeType())
+ if (left.nodeType() === right.nodeType()) {
return true;
+ }
// XPath treats CDATA as text nodes.
const leftType = left.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType();
@@ -275,8 +303,9 @@ Elements.DOMPath._xPathIndex = function(node) {
}
const siblings = node.parentNode ? node.parentNode.children() : null;
- if (!siblings)
- return 0; // Root node - no siblings.
+ if (!siblings) {
+ return 0;
+ } // Root node - no siblings.
let hasSameNamedElements;
for (let i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
@@ -284,13 +313,15 @@ Elements.DOMPath._xPathIndex = function(node) {
break;
}
}
- if (!hasSameNamedElements)
+ if (!hasSameNamedElements) {
return 0;
+ }
let ownIndex = 1; // XPath indices start with 1.
for (let i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(node, siblings[i])) {
- if (siblings[i] === node)
+ if (siblings[i] === node) {
return ownIndex;
+ }
++ownIndex;
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementStatePaneWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementStatePaneWidget.js
index a2fd799ddfa..ede77705f24 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementStatePaneWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementStatePaneWidget.js
@@ -20,8 +20,9 @@ Elements.ElementStatePaneWidget = class extends UI.Widget {
*/
function clickListener(event) {
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return;
+ }
node.domModel().cssModel().forcePseudoState(node, event.target.state, event.target.checked);
}
@@ -64,13 +65,16 @@ Elements.ElementStatePaneWidget = class extends UI.Widget {
* @param {?SDK.CSSModel} cssModel
*/
_updateModel(cssModel) {
- if (this._cssModel === cssModel)
+ if (this._cssModel === cssModel) {
return;
- if (this._cssModel)
+ }
+ if (this._cssModel) {
this._cssModel.removeEventListener(SDK.CSSModel.Events.PseudoStateForced, this._update, this);
+ }
this._cssModel = cssModel;
- if (this._cssModel)
+ if (this._cssModel) {
this._cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this._update, this);
+ }
}
/**
@@ -81,12 +85,14 @@ Elements.ElementStatePaneWidget = class extends UI.Widget {
}
_update() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
let node = UI.context.flavor(SDK.DOMNode);
- if (node)
+ if (node) {
node = node.enclosingElementOrSelf();
+ }
this._updateModel(node ? node.domModel().cssModel() : null);
if (node) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsBreadcrumbs.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsBreadcrumbs.js
index ec4017e7985..dd1d6bc9fc1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsBreadcrumbs.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsBreadcrumbs.js
@@ -28,8 +28,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
* @param {!Array.<!SDK.DOMNode>} nodes
*/
updateNodes(nodes) {
- if (!nodes.length)
+ if (!nodes.length) {
return;
+ }
const crumbs = this.crumbsElement;
for (let crumb = crumbs.firstChild; crumb; crumb = crumb.nextSibling) {
@@ -52,13 +53,15 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
const nodeUnderMouse = event.target;
const crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass('crumb');
const node = /** @type {?SDK.DOMNode} */ (crumbElement ? crumbElement[this._nodeSymbol] : null);
- if (node)
+ if (node) {
node.highlight();
+ }
}
_mouseMovedOutOfCrumbs(event) {
- if (this._currentDOMNode)
+ if (this._currentDOMNode) {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
}
@@ -82,8 +85,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
while (currentCrumb) {
const hidden = currentCrumb.classList.contains('hidden');
const collapsed = currentCrumb.classList.contains('collapsed');
- if (!hidden && !collapsed)
+ if (!hidden && !collapsed) {
break;
+ }
crumb = currentCrumb;
currentCrumb = currentCrumb.nextSiblingElement;
}
@@ -99,8 +103,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
_determineElementTitle(domNode) {
switch (domNode.nodeType()) {
case Node.ELEMENT_NODE:
- if (domNode.pseudoType())
+ if (domNode.pseudoType()) {
return '::' + domNode.pseudoType();
+ }
return null;
case Node.TEXT_NODE:
return Common.UIString('(text)');
@@ -119,8 +124,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
* @param {boolean=} force
*/
update(force) {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
const currentDOMNode = this._currentDOMNode;
const crumbs = this.crumbsElement;
@@ -148,8 +154,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
crumbs.removeChildren();
for (let current = currentDOMNode; current; current = current.parentNode) {
- if (current.nodeType() === Node.DOCUMENT_NODE)
+ if (current.nodeType() === Node.DOCUMENT_NODE) {
continue;
+ }
crumb = createElementWithClass('span', 'crumb');
crumb[this._nodeSymbol] = current;
@@ -165,8 +172,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
Elements.DOMLinkifier.decorateNodeLabel(current, crumb);
}
- if (current === currentDOMNode)
+ if (current === currentDOMNode) {
crumb.classList.add('selected');
+ }
crumbs.insertBefore(crumb, crumbs.firstChild);
}
@@ -193,8 +201,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
}
// Find the focused crumb index.
- if (crumb === focusedCrumb)
+ if (crumb === focusedCrumb) {
focusedIndex = i;
+ }
crumb.classList.remove('compact', 'collapsed', 'hidden');
}
@@ -248,12 +257,14 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
* @param {!Element=} focusedCrumb
*/
updateSizes(focusedCrumb) {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
const crumbs = this.crumbsElement;
- if (!crumbs.firstChild)
+ if (!crumbs.firstChild) {
return;
+ }
const selections = this._resetCrumbStylesAndFindSelections(focusedCrumb);
const sizes = this._measureElementSizes();
@@ -265,8 +276,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
let totalSize = 0;
for (let i = 0; i < crumbs.childNodes.length; ++i) {
const crumb = crumbs.childNodes[i];
- if (crumb.classList.contains('hidden'))
+ if (crumb.classList.contains('hidden')) {
continue;
+ }
if (crumb.classList.contains('collapsed')) {
totalSize += sizes.collapsed;
continue;
@@ -277,8 +289,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
return totalSize + rightPadding < sizes.available;
}
- if (crumbsAreSmallerThanContainer())
- return; // No need to compact the crumbs, they all fit at full size.
+ if (crumbsAreSmallerThanContainer()) {
+ return;
+ } // No need to compact the crumbs, they all fit at full size.
const BothSides = 0;
const AncestorSide = -1;
@@ -294,10 +307,12 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
function shrinkCrumbAtIndex(index) {
const shrinkCrumb = crumbs.children[index];
- if (shrinkCrumb && shrinkCrumb !== significantCrumb)
+ if (shrinkCrumb && shrinkCrumb !== significantCrumb) {
shrinkingFunction(shrinkCrumb);
- if (crumbsAreSmallerThanContainer())
- return true; // No need to compact the crumbs more.
+ }
+ if (crumbsAreSmallerThanContainer()) {
+ return true;
+ } // No need to compact the crumbs more.
return false;
}
@@ -307,8 +322,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
// Crumbs are shrunk on only one side (based on direction) of the signifcant crumb.
let index = (direction > 0 ? 0 : crumbs.childNodes.length - 1);
while (index !== significantIndex) {
- if (shrinkCrumbAtIndex(index))
+ if (shrinkCrumbAtIndex(index)) {
return true;
+ }
index += (direction > 0 ? 1 : -1);
}
} else {
@@ -320,12 +336,14 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
const startDistance = significantIndex - startIndex;
const endDistance = endIndex - significantIndex;
let index;
- if (startDistance >= endDistance)
+ if (startDistance >= endDistance) {
index = startIndex++;
- else
+ } else {
index = endIndex--;
- if (shrinkCrumbAtIndex(index))
+ }
+ if (shrinkCrumbAtIndex(index)) {
return true;
+ }
}
}
@@ -388,8 +406,9 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
* @param {!Element} crumb
*/
function compact(crumb) {
- if (crumb.classList.contains('hidden'))
+ if (crumb.classList.contains('hidden')) {
return;
+ }
crumb.classList.add('compact');
}
@@ -398,12 +417,14 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
* @param {boolean=} dontCoalesce
*/
function collapse(crumb, dontCoalesce) {
- if (crumb.classList.contains('hidden'))
+ if (crumb.classList.contains('hidden')) {
return;
+ }
crumb.classList.add('collapsed');
crumb.classList.remove('compact');
- if (!dontCoalesce)
+ if (!dontCoalesce) {
coalesceCollapsedCrumbs();
+ }
}
if (!focusedCrumb) {
@@ -411,29 +432,35 @@ Elements.ElementsBreadcrumbs = class extends UI.HBox {
// crumbs that the user might not care much about.
// Compact child crumbs.
- if (makeCrumbsSmaller(compact, ChildSide))
+ if (makeCrumbsSmaller(compact, ChildSide)) {
return;
+ }
// Collapse child crumbs.
- if (makeCrumbsSmaller(collapse, ChildSide))
+ if (makeCrumbsSmaller(collapse, ChildSide)) {
return;
+ }
}
// Compact ancestor crumbs, or from both sides if focused.
- if (makeCrumbsSmaller(compact, focusedCrumb ? BothSides : AncestorSide))
+ if (makeCrumbsSmaller(compact, focusedCrumb ? BothSides : AncestorSide)) {
return;
+ }
// Collapse ancestor crumbs, or from both sides if focused.
- if (makeCrumbsSmaller(collapse, focusedCrumb ? BothSides : AncestorSide))
+ if (makeCrumbsSmaller(collapse, focusedCrumb ? BothSides : AncestorSide)) {
return;
+ }
- if (!selectedCrumb)
+ if (!selectedCrumb) {
return;
+ }
// Compact the selected crumb.
compact(selectedCrumb);
- if (crumbsAreSmallerThanContainer())
+ if (crumbsAreSmallerThanContainer()) {
return;
+ }
// Collapse the selected crumb as a last resort. Pass true to prevent coalescing.
collapse(selectedCrumb, true);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
index 6835482d4ed..d75af071951 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
@@ -60,8 +60,9 @@ Elements.ElementsPanel = class extends UI.Panel {
this._contentElement.id = 'elements-content';
// FIXME: crbug.com/425984
- if (Common.moduleSetting('domWordWrap').get())
+ if (Common.moduleSetting('domWordWrap').get()) {
this._contentElement.classList.add('elements-wrap');
+ }
Common.moduleSetting('domWordWrap').addChangeListener(this._domWordWrapSettingChanged.bind(this));
crumbsContainer.id = 'elements-crumbs';
@@ -149,8 +150,9 @@ Elements.ElementsPanel = class extends UI.Panel {
treeOutline.wireToDOMModel(domModel);
// Perform attach if necessary.
- if (this.isShowing())
+ if (this.isShowing()) {
this.wasShown();
+ }
}
/**
@@ -160,12 +162,14 @@ Elements.ElementsPanel = class extends UI.Panel {
modelRemoved(domModel) {
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
treeOutline.unwireFromDOMModel(domModel);
- if (domModel.parentModel())
+ if (domModel.parentModel()) {
return;
+ }
this._treeOutlines.remove(treeOutline);
const header = this._treeOutlineHeaders.get(treeOutline);
- if (header)
+ if (header) {
header.remove();
+ }
this._treeOutlineHeaders.delete(treeOutline);
treeOutline.element.remove();
}
@@ -175,28 +179,34 @@ Elements.ElementsPanel = class extends UI.Panel {
*/
_targetNameChanged(target) {
const domModel = target.model(SDK.DOMModel);
- if (!domModel)
+ if (!domModel) {
return;
+ }
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
- if (!treeOutline)
+ if (!treeOutline) {
return;
+ }
const header = this._treeOutlineHeaders.get(treeOutline);
- if (!header)
+ if (!header) {
return;
+ }
header.removeChildren();
header.createChild('div', 'elements-tree-header-frame').textContent = Common.UIString('Frame');
header.appendChild(Components.Linkifier.linkifyURL(target.inspectedURL(), {text: target.name()}));
}
_updateTreeOutlineVisibleWidth() {
- if (!this._treeOutlines.length)
+ if (!this._treeOutlines.length) {
return;
+ }
let width = this._splitWidget.element.offsetWidth;
- if (this._splitWidget.isVertical())
+ if (this._splitWidget.isVertical()) {
width -= this._splitWidget.sidebarSize();
- for (let i = 0; i < this._treeOutlines.length; ++i)
+ }
+ for (let i = 0; i < this._treeOutlines.length; ++i) {
this._treeOutlines[i].setVisibleWidth(width);
+ }
this._breadcrumbs.updateSizes();
}
@@ -205,8 +215,9 @@ Elements.ElementsPanel = class extends UI.Panel {
* @override
*/
focus() {
- if (this._treeOutlines.length)
+ if (this._treeOutlines.length) {
this._treeOutlines[0].focus();
+ }
}
/**
@@ -228,8 +239,9 @@ Elements.ElementsPanel = class extends UI.Panel {
// Attach heavy component lazily
if (treeOutline.element.parentElement !== this._contentElement) {
const header = this._treeOutlineHeaders.get(treeOutline);
- if (header)
+ if (header) {
this._contentElement.appendChild(header);
+ }
this._contentElement.appendChild(treeOutline.element);
}
}
@@ -238,8 +250,9 @@ Elements.ElementsPanel = class extends UI.Panel {
const domModels = SDK.targetManager.models(SDK.DOMModel);
for (const domModel of domModels) {
- if (domModel.parentModel())
+ if (domModel.parentModel()) {
continue;
+ }
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(domModel);
treeOutline.setVisible(true);
@@ -265,11 +278,13 @@ Elements.ElementsPanel = class extends UI.Panel {
// Detach heavy component on hide
this._contentElement.removeChild(treeOutline.element);
const header = this._treeOutlineHeaders.get(treeOutline);
- if (header)
+ if (header) {
this._contentElement.removeChild(header);
+ }
}
- if (this._popoverHelper)
+ if (this._popoverHelper) {
this._popoverHelper.hidePopover();
+ }
super.willHide();
UI.context.setFlavor(Elements.ElementsPanel, null);
}
@@ -289,16 +304,18 @@ Elements.ElementsPanel = class extends UI.Panel {
const selectedNode = /** @type {?SDK.DOMNode} */ (event.data.node);
const focus = /** @type {boolean} */ (event.data.focus);
for (const treeOutline of this._treeOutlines) {
- if (!selectedNode || Elements.ElementsTreeOutline.forDOMModel(selectedNode.domModel()) !== treeOutline)
+ if (!selectedNode || Elements.ElementsTreeOutline.forDOMModel(selectedNode.domModel()) !== treeOutline) {
treeOutline.selectDOMNode(null);
+ }
}
this._breadcrumbs.setSelectedNode(selectedNode);
UI.context.setFlavor(SDK.DOMNode, selectedNode);
- if (!selectedNode)
+ if (!selectedNode) {
return;
+ }
selectedNode.setAsInspectedNode();
if (focus) {
this._selectedNodeOnReset = selectedNode;
@@ -330,15 +347,17 @@ Elements.ElementsPanel = class extends UI.Panel {
this._searchableView.resetSearch();
if (!domModel.existingDocument()) {
- if (this.isShowing())
+ if (this.isShowing()) {
domModel.requestDocument();
+ }
return;
}
this._hasNonDefaultSelectedNode = false;
- if (this._omitDefaultSelection)
+ if (this._omitDefaultSelection) {
return;
+ }
const savedSelectedNodeOnReset = this._selectedNodeOnReset;
restoreNode.call(this, domModel, this._selectedNodeOnReset);
@@ -353,8 +372,9 @@ Elements.ElementsPanel = class extends UI.Panel {
const restoredNodeId = nodePath ? await domModel.pushNodeByPathToFrontend(nodePath) : null;
- if (savedSelectedNodeOnReset !== this._selectedNodeOnReset)
+ if (savedSelectedNodeOnReset !== this._selectedNodeOnReset) {
return;
+ }
let node = restoredNodeId ? domModel.nodeForId(restoredNodeId) : null;
if (!node) {
const inspectedDocument = domModel.existingDocument();
@@ -372,14 +392,17 @@ Elements.ElementsPanel = class extends UI.Panel {
* @param {?SDK.DOMNode} node
*/
_setDefaultSelectedNode(node) {
- if (!node || this._hasNonDefaultSelectedNode || this._pendingNodeReveal)
+ if (!node || this._hasNonDefaultSelectedNode || this._pendingNodeReveal) {
return;
+ }
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
- if (!treeOutline)
+ if (!treeOutline) {
return;
+ }
this.selectDOMNode(node);
- if (treeOutline.selectedTreeElement)
+ if (treeOutline.selectedTreeElement) {
treeOutline.selectedTreeElement.expand();
+ }
}
/**
@@ -407,13 +430,15 @@ Elements.ElementsPanel = class extends UI.Panel {
const query = searchConfig.query;
const whitespaceTrimmedQuery = query.trim();
- if (!whitespaceTrimmedQuery.length)
+ if (!whitespaceTrimmedQuery.length) {
return;
+ }
- if (!this._searchConfig || this._searchConfig.query !== query)
+ if (!this._searchConfig || this._searchConfig.query !== query) {
this.searchCanceled();
- else
+ } else {
this._hideSearchHighlights();
+ }
this._searchConfig = searchConfig;
@@ -433,22 +458,26 @@ Elements.ElementsPanel = class extends UI.Panel {
this._searchResults = [];
for (let i = 0; i < resultCounts.length; ++i) {
const resultCount = resultCounts[i];
- for (let j = 0; j < resultCount; ++j)
+ for (let j = 0; j < resultCount; ++j) {
this._searchResults.push({domModel: domModels[i], index: j, node: undefined});
+ }
}
this._searchableView.updateSearchMatchesCount(this._searchResults.length);
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
- if (this._currentSearchResultIndex >= this._searchResults.length)
+ }
+ if (this._currentSearchResultIndex >= this._searchResults.length) {
this._currentSearchResultIndex = undefined;
+ }
let index = this._currentSearchResultIndex;
if (shouldJump) {
- if (this._currentSearchResultIndex === undefined)
+ if (this._currentSearchResultIndex === undefined) {
index = jumpBackwards ? -1 : 0;
- else
+ } else {
index = jumpBackwards ? index - 1 : index + 1;
+ }
this._jumpToSearchResult(index);
}
}
@@ -457,8 +486,9 @@ Elements.ElementsPanel = class extends UI.Panel {
_domWordWrapSettingChanged(event) {
// FIXME: crbug.com/425984
this._contentElement.classList.toggle('elements-wrap', event.data);
- for (let i = 0; i < this._treeOutlines.length; ++i)
+ for (let i = 0; i < this._treeOutlines.length; ++i) {
this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data));
+ }
}
switchToAndFocus(node) {
@@ -473,21 +503,25 @@ Elements.ElementsPanel = class extends UI.Panel {
*/
_getPopoverRequest(event) {
let link = event.target;
- while (link && !link[Elements.ElementsTreeElement.HrefSymbol])
+ while (link && !link[Elements.ElementsTreeElement.HrefSymbol]) {
link = link.parentElementOrShadowHost();
- if (!link)
+ }
+ if (!link) {
return null;
+ }
return {
box: link.boxInWindow(),
show: async popover => {
const node = this.selectedDOMNode();
- if (!node)
+ if (!node) {
return false;
+ }
const preview = await Components.ImagePreview.build(
node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true);
- if (preview)
+ if (preview) {
popover.contentElement.appendChild(preview);
+ }
return !!preview;
}
};
@@ -502,8 +536,9 @@ Elements.ElementsPanel = class extends UI.Panel {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchResults)
+ if (!this._searchResults) {
return;
+ }
this.performSearch(this._searchConfig, true);
}
@@ -511,8 +546,9 @@ Elements.ElementsPanel = class extends UI.Panel {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchResults)
+ if (!this._searchResults) {
return;
+ }
this.performSearch(this._searchConfig, true, true);
}
@@ -538,8 +574,9 @@ Elements.ElementsPanel = class extends UI.Panel {
const searchResult = searchResults[index];
this._searchableView.updateCurrentMatchIndex(index);
- if (searchResult.node === null)
+ if (searchResult.node === null) {
return;
+ }
if (typeof searchResult.node === 'undefined') {
// No data for slot, request it.
@@ -556,21 +593,25 @@ Elements.ElementsPanel = class extends UI.Panel {
treeElement.highlightSearchResults(this._searchConfig.query);
treeElement.reveal();
const matches = treeElement.listItemElement.getElementsByClassName(UI.highlightedSearchResultClassName);
- if (matches.length)
+ if (matches.length) {
matches[0].scrollIntoViewIfNeeded(false);
+ }
}
}
_hideSearchHighlights() {
- if (!this._searchResults || !this._searchResults.length || this._currentSearchResultIndex === undefined)
+ if (!this._searchResults || !this._searchResults.length || this._currentSearchResultIndex === undefined) {
return;
+ }
const searchResult = this._searchResults[this._currentSearchResultIndex];
- if (!searchResult.node)
+ if (!searchResult.node) {
return;
+ }
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(searchResult.node.domModel());
const treeElement = treeOutline.findTreeElement(searchResult.node);
- if (treeElement)
+ if (treeElement) {
treeElement.hideSearchHighlights();
+ }
}
/**
@@ -579,8 +620,9 @@ Elements.ElementsPanel = class extends UI.Panel {
selectedDOMNode() {
for (let i = 0; i < this._treeOutlines.length; ++i) {
const treeOutline = this._treeOutlines[i];
- if (treeOutline.selectedDOMNode())
+ if (treeOutline.selectedDOMNode()) {
return treeOutline.selectedDOMNode();
+ }
}
return null;
}
@@ -592,10 +634,11 @@ Elements.ElementsPanel = class extends UI.Panel {
selectDOMNode(node, focus) {
for (const treeOutline of this._treeOutlines) {
const outline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
- if (outline === treeOutline)
+ if (outline === treeOutline) {
treeOutline.selectDOMNode(node, focus);
- else
+ } else {
treeOutline.selectDOMNode(null);
+ }
}
}
@@ -620,8 +663,9 @@ Elements.ElementsPanel = class extends UI.Panel {
* @return {?Elements.ElementsTreeOutline}
*/
_treeOutlineForNode(node) {
- if (!node)
+ if (!node) {
return null;
+ }
return Elements.ElementsTreeOutline.forDOMModel(node.domModel());
}
@@ -640,8 +684,9 @@ Elements.ElementsPanel = class extends UI.Panel {
*/
_leaveUserAgentShadowDOM(node) {
let userAgentShadowRoot;
- while ((userAgentShadowRoot = node.ancestorUserAgentShadowRoot()) && userAgentShadowRoot.parentNode)
+ while ((userAgentShadowRoot = node.ancestorUserAgentShadowRoot()) && userAgentShadowRoot.parentNode) {
node = userAgentShadowRoot.parentNode;
+ }
return node;
}
@@ -655,8 +700,9 @@ Elements.ElementsPanel = class extends UI.Panel {
this._omitDefaultSelection = true;
node = Common.moduleSetting('showUAShadowDOM').get() ? node : this._leaveUserAgentShadowDOM(node);
- if (!omitHighlight)
+ if (!omitHighlight) {
node.highlightForTwoSeconds();
+ }
return UI.viewManager.showView('elements', false, !focus).then(() => {
this.selectDOMNode(node, focus);
@@ -665,15 +711,16 @@ Elements.ElementsPanel = class extends UI.Panel {
if (!this._notFirstInspectElement) {
Elements.ElementsPanel._firstInspectElementNodeNameForTest = node.nodeName();
Elements.ElementsPanel._firstInspectElementCompletedForTest();
- InspectorFrontendHost.inspectElementCompleted();
+ Host.InspectorFrontendHost.inspectElementCompleted();
}
this._notFirstInspectElement = true;
});
}
_showUAShadowDOMChanged() {
- for (let i = 0; i < this._treeOutlines.length; ++i)
+ for (let i = 0; i < this._treeOutlines.length; ++i) {
this._treeOutlines[i].update();
+ }
}
/**
@@ -686,13 +733,15 @@ Elements.ElementsPanel = class extends UI.Panel {
// Fallback to cover unforeseen cases where text selection has ended.
const uninstallHackOnMousemove = event => {
- if (event.buttons === 0)
+ if (event.buttons === 0) {
uninstallHack.call(this);
+ }
};
stylePaneWrapperElement.addEventListener('mousedown', event => {
- if (event.which !== 1)
+ if (event.which !== 1) {
return;
+ }
this._splitWidget.element.classList.add('disable-resizer-for-elements-hack');
stylePaneWrapperElement.style.setProperty('height', `${stylePaneWrapperElement.offsetHeight}px`);
const largeLength = 1000000;
@@ -729,20 +778,23 @@ Elements.ElementsPanel = class extends UI.Panel {
}
_updateSidebarPosition() {
- if (this.sidebarPaneView && this.sidebarPaneView.tabbedPane().shouldHideOnDetach())
- return; // We can't reparent extension iframes.
+ if (this.sidebarPaneView && this.sidebarPaneView.tabbedPane().shouldHideOnDetach()) {
+ return;
+ } // We can't reparent extension iframes.
let splitMode;
const position = Common.moduleSetting('sidebarPosition').get();
- if (position === 'right' || (position === 'auto' && UI.inspectorView.element.offsetWidth > 680))
+ if (position === 'right' || (position === 'auto' && UI.inspectorView.element.offsetWidth > 680)) {
splitMode = Elements.ElementsPanel._splitMode.Vertical;
- else if (UI.inspectorView.element.offsetWidth > 415)
+ } else if (UI.inspectorView.element.offsetWidth > 415) {
splitMode = Elements.ElementsPanel._splitMode.Horizontal;
- else
+ } else {
splitMode = Elements.ElementsPanel._splitMode.Slim;
+ }
- if (this.sidebarPaneView && splitMode === this._splitMode)
+ if (this.sidebarPaneView && splitMode === this._splitMode) {
return;
+ }
this._splitMode = splitMode;
const extensionSidebarPanes = Extensions.extensionServer.sidebarPanes();
@@ -770,10 +822,11 @@ Elements.ElementsPanel = class extends UI.Panel {
* @this {Elements.ElementsPanel}
*/
function showMetrics(inComputedStyle) {
- if (inComputedStyle)
+ if (inComputedStyle) {
this._metricsWidget.show(computedStylePanesWrapper.element, this._computedStyleWidget.element);
- else
+ } else {
this._metricsWidget.show(matchedStylePanesWrapper.element);
+ }
}
/**
@@ -782,22 +835,25 @@ Elements.ElementsPanel = class extends UI.Panel {
*/
function tabSelected(event) {
const tabId = /** @type {string} */ (event.data.tabId);
- if (tabId === Common.UIString('Computed'))
+ if (tabId === Common.UIString('Computed')) {
showMetrics.call(this, true);
- else if (tabId === Common.UIString('Styles'))
+ } else if (tabId === Common.UIString('Styles')) {
showMetrics.call(this, false);
+ }
}
this.sidebarPaneView = UI.viewManager.createTabbedLocation(() => UI.viewManager.showView('elements'));
const tabbedPane = this.sidebarPaneView.tabbedPane();
- if (this._popoverHelper)
+ if (this._popoverHelper) {
this._popoverHelper.hidePopover();
+ }
this._popoverHelper = new UI.PopoverHelper(tabbedPane.element, this._getPopoverRequest.bind(this));
this._popoverHelper.setHasPadding(true);
this._popoverHelper.setTimeout(0);
- if (this._splitMode !== Elements.ElementsPanel._splitMode.Vertical)
+ if (this._splitMode !== Elements.ElementsPanel._splitMode.Vertical) {
this._splitWidget.installResizer(tabbedPane.headerElement());
+ }
const stylesView = new UI.SimpleView(Common.UIString('Styles'));
this.sidebarPaneView.appendView(stylesView);
@@ -826,11 +882,13 @@ Elements.ElementsPanel = class extends UI.Panel {
showMetrics.call(this, this._splitMode === Elements.ElementsPanel._splitMode.Horizontal);
this.sidebarPaneView.appendApplicableItems('elements-sidebar');
- for (let i = 0; i < extensionSidebarPanes.length; ++i)
+ for (let i = 0; i < extensionSidebarPanes.length; ++i) {
this._addExtensionSidebarPane(extensionSidebarPanes[i]);
+ }
- if (lastSelectedTabId)
+ if (lastSelectedTabId) {
this.sidebarPaneView.tabbedPane().selectTab(lastSelectedTabId);
+ }
this._splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane());
}
@@ -847,8 +905,9 @@ Elements.ElementsPanel = class extends UI.Panel {
* @param {!Extensions.ExtensionSidebarPane} pane
*/
_addExtensionSidebarPane(pane) {
- if (pane.panelName() === this.name)
+ if (pane.panelName() === this.name) {
this.sidebarPaneView.appendView(pane);
+ }
}
};
@@ -877,12 +936,14 @@ Elements.ElementsPanel.ContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, object) {
if (!(object instanceof SDK.RemoteObject && (/** @type {!SDK.RemoteObject} */ (object)).isNode()) &&
- !(object instanceof SDK.DOMNode) && !(object instanceof SDK.DeferredDOMNode))
+ !(object instanceof SDK.DOMNode) && !(object instanceof SDK.DeferredDOMNode)) {
return;
+ }
// Skip adding "Reveal..." menu item for our own tree outline.
- if (Elements.ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target)))
+ if (Elements.ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target))) {
return;
+ }
const commandCallback = Common.Revealer.reveal.bind(Common.Revealer, object);
contextMenu.revealSection().appendItem(Common.UIString('Reveal in Elements panel'), commandCallback);
}
@@ -916,10 +977,11 @@ Elements.ElementsPanel.DOMNodeRevealer = class {
(/** @type {!SDK.DeferredDOMNode} */ (node)).resolve(onNodeResolved);
} else if (node instanceof SDK.RemoteObject) {
const domModel = /** @type {!SDK.RemoteObject} */ (node).runtimeModel().target().model(SDK.DOMModel);
- if (domModel)
+ if (domModel) {
domModel.pushObjectAsNodeToFrontend(node).then(onNodeResolved);
- else
+ } else {
reject(new Error('Could not resolve a node to reveal.'));
+ }
} else {
reject(new Error('Can\'t reveal a non-node.'));
panel._pendingNodeReveal = false;
@@ -931,6 +993,24 @@ Elements.ElementsPanel.DOMNodeRevealer = class {
function onNodeResolved(resolvedNode) {
panel._pendingNodeReveal = false;
+ // A detached node could still have a parent and ownerDocument
+ // properties, which means stepping up through the hierarchy to ensure
+ // that the root node is the document itself. Any break implies
+ // detachment.
+ let currentNode = resolvedNode;
+ while (currentNode.parentNode) {
+ currentNode = currentNode.parentNode;
+ }
+ const isDetached = !(currentNode instanceof SDK.DOMDocument);
+
+ const isDocument = node instanceof SDK.DOMDocument;
+ if (!isDocument && isDetached) {
+ const msg = ls`Node cannot be found in the current page.`;
+ Common.console.warn(msg);
+ reject(new Error(msg));
+ return;
+ }
+
if (resolvedNode) {
panel.revealAndSelectNode(resolvedNode, !omitFocus).then(resolve);
return;
@@ -971,11 +1051,13 @@ Elements.ElementsActionDelegate = class {
*/
handleAction(context, actionId) {
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return true;
+ }
const treeOutline = Elements.ElementsTreeOutline.forDOMModel(node.domModel());
- if (!treeOutline)
+ if (!treeOutline) {
return true;
+ }
switch (actionId) {
case 'elements.hide-element':
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsSidebarPane.js
index 1f76f3d0341..bda591c840e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsSidebarPane.js
@@ -43,8 +43,9 @@ Elements.ElementsSidebarPane = class extends UI.VBox {
update() {
this._updateWhenVisible = !this.isShowing();
- if (this._updateWhenVisible)
+ if (this._updateWhenVisible) {
return;
+ }
this._updateThrottler.schedule(innerUpdate.bind(this));
/**
@@ -61,8 +62,9 @@ Elements.ElementsSidebarPane = class extends UI.VBox {
*/
wasShown() {
super.wasShown();
- if (this._updateWhenVisible)
+ if (this._updateWhenVisible) {
this.update();
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
index 7cb307756e9..184a9b5d908 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
@@ -49,8 +49,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
this._elementCloseTag = elementCloseTag;
- if (this._node.nodeType() === Node.ELEMENT_NODE && !elementCloseTag)
+ if (this._node.nodeType() === Node.ELEMENT_NODE && !elementCloseTag) {
this._canAddAttributes = true;
+ }
this._searchQuery = null;
this._expandedChildrenLimit = Elements.ElementsTreeElement.InitialChildrenLimit;
this._decorationsThrottler = new Common.Throttler(100);
@@ -70,8 +71,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
*/
static visibleShadowRoots(node) {
let roots = node.shadowRoots();
- if (roots.length && !Common.moduleSetting('showUAShadowDOM').get())
+ if (roots.length && !Common.moduleSetting('showUAShadowDOM').get()) {
roots = roots.filter(filter);
+ }
/**
* @param {!SDK.DOMNode} root
@@ -88,16 +90,20 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
*/
static canShowInlineText(node) {
if (node.contentDocument() || node.importedDocument() || node.templateContent() ||
- Elements.ElementsTreeElement.visibleShadowRoots(node).length || node.hasPseudoElements())
+ Elements.ElementsTreeElement.visibleShadowRoots(node).length || node.hasPseudoElements()) {
return false;
- if (node.nodeType() !== Node.ELEMENT_NODE)
+ }
+ if (node.nodeType() !== Node.ELEMENT_NODE) {
return false;
- if (!node.firstChild || node.firstChild !== node.lastChild || node.firstChild.nodeType() !== Node.TEXT_NODE)
+ }
+ if (!node.firstChild || node.firstChild !== node.lastChild || node.firstChild.nodeType() !== Node.TEXT_NODE) {
return false;
+ }
const textChild = node.firstChild;
const maxInlineTextChildLength = 80;
- if (textChild.nodeValue().length < maxInlineTextChildLength)
+ if (textChild.nodeValue().length < maxInlineTextChildLength) {
return true;
+ }
return false;
}
@@ -156,8 +162,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {string} searchQuery
*/
highlightSearchResults(searchQuery) {
- if (this._searchQuery !== searchQuery)
+ if (this._searchQuery !== searchQuery) {
this._hideSearchHighlight();
+ }
this._searchQuery = searchQuery;
this._searchHighlightsVisible = true;
@@ -170,8 +177,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
_hideSearchHighlight() {
- if (!this._highlightResult)
+ if (!this._highlightResult) {
return;
+ }
function updateEntryHide(entry) {
switch (entry.type) {
@@ -184,8 +192,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
}
- for (let i = (this._highlightResult.length - 1); i >= 0; --i)
+ for (let i = (this._highlightResult.length - 1); i >= 0; --i) {
updateEntryHide(this._highlightResult[i]);
+ }
delete this._highlightResult;
}
@@ -194,8 +203,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {boolean} inClipboard
*/
setInClipboard(inClipboard) {
- if (this._inClipboard === inClipboard)
+ if (this._inClipboard === inClipboard) {
return;
+ }
this._inClipboard = inClipboard;
this.listItemElement.classList.toggle('in-clipboard', inClipboard);
}
@@ -205,8 +215,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
set hovered(x) {
- if (this._hovered === x)
+ if (this._hovered === x) {
return;
+ }
this._hovered = x;
@@ -236,8 +247,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
_createSelection() {
const listItemElement = this.listItemElement;
- if (!listItemElement)
+ if (!listItemElement) {
return;
+ }
if (!this.selectionElement) {
this.selectionElement = createElement('div');
@@ -260,16 +272,18 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @override
*/
onbind() {
- if (!this._elementCloseTag)
+ if (!this._elementCloseTag) {
this._node[this.treeOutline.treeElementSymbol()] = this;
+ }
}
/**
* @override
*/
onunbind() {
- if (this._node[this.treeOutline.treeElementSymbol()] === this)
+ if (this._node[this.treeOutline.treeElementSymbol()] === this) {
this._node[this.treeOutline.treeElementSymbol()] = null;
+ }
}
/**
@@ -305,8 +319,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @override
*/
onexpand() {
- if (this._elementCloseTag)
+ if (this._elementCloseTag) {
return;
+ }
this.updateTitle();
}
@@ -315,8 +330,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @override
*/
oncollapse() {
- if (this._elementCloseTag)
+ if (this._elementCloseTag) {
return;
+ }
this.updateTitle();
}
@@ -328,8 +344,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @return {boolean}
*/
select(omitFocus, selectedByUser) {
- if (this._editing)
+ if (this._editing) {
return false;
+ }
return super.select(omitFocus, selectedByUser);
}
@@ -368,8 +385,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
onenter() {
// On Enter or Return start editing the first attribute
// or create a new attribute on the selected element.
- if (this._editing)
+ if (this._editing) {
return false;
+ }
this._startEditing();
@@ -383,12 +401,14 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
selectOnMouseDown(event) {
super.selectOnMouseDown(event);
- if (this._editing)
+ if (this._editing) {
return;
+ }
// Prevent selecting the nearest word on double click.
- if (event.detail >= 2)
+ if (event.detail >= 2) {
event.preventDefault();
+ }
}
/**
@@ -396,14 +416,17 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @return {boolean}
*/
ondblclick(event) {
- if (this._editing || this._elementCloseTag)
+ if (this._editing || this._elementCloseTag) {
return false;
+ }
- if (this._startEditingTarget(/** @type {!Element} */ (event.target)))
+ if (this._startEditingTarget(/** @type {!Element} */ (event.target))) {
return false;
+ }
- if (this.isExpandable() && !this.expanded)
+ if (this.isExpandable() && !this.expanded) {
this.expand();
+ }
return false;
}
@@ -431,27 +454,33 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @return {boolean}
*/
_startEditingTarget(eventTarget) {
- if (this.treeOutline.selectedDOMNode() !== this._node)
+ if (this.treeOutline.selectedDOMNode() !== this._node) {
return false;
+ }
- if (this._node.nodeType() !== Node.ELEMENT_NODE && this._node.nodeType() !== Node.TEXT_NODE)
+ if (this._node.nodeType() !== Node.ELEMENT_NODE && this._node.nodeType() !== Node.TEXT_NODE) {
return false;
+ }
const textNode = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-text-node');
- if (textNode)
+ if (textNode) {
return this._startEditingTextNode(textNode);
+ }
const attribute = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-attribute');
- if (attribute)
+ if (attribute) {
return this._startEditingAttribute(attribute, eventTarget);
+ }
const tagName = eventTarget.enclosingNodeOrSelfWithClass('webkit-html-tag-name');
- if (tagName)
+ if (tagName) {
return this._startEditingTagName(tagName);
+ }
const newAttribute = eventTarget.enclosingNodeOrSelfWithClass('add-attribute');
- if (newAttribute)
+ if (newAttribute) {
return this._addNewAttribute();
+ }
return false;
}
@@ -505,13 +534,14 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
populateNodeContextMenu(contextMenu) {
// Add free-form node-related actions.
const isEditable = this.hasEditableNode();
- if (isEditable && !this._editing)
+ if (isEditable && !this._editing) {
contextMenu.editSection().appendItem(Common.UIString('Edit as HTML'), this._editAsHTML.bind(this));
+ }
const isShadowRoot = this._node.isShadowRoot();
// Place it here so that all "Copy"-ing items stick together.
const copyMenu = contextMenu.clipboardSection().appendSubMenuItem(Common.UIString('Copy'));
- const createShortcut = UI.KeyboardShortcut.shortcutToString;
+ const createShortcut = UI.KeyboardShortcut.shortcutToString.bind(null);
const modifier = UI.KeyboardShortcut.Modifiers.CtrlOrMeta;
const treeOutline = this.treeOutline;
let menuItem;
@@ -552,16 +582,18 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
treeOutline.isToggledToHidden(this._node));
menuItem.setShortcut(UI.shortcutRegistry.shortcutTitleForAction('elements.hide-element'));
- if (isEditable)
+ if (isEditable) {
contextMenu.editSection().appendItem(Common.UIString('Delete element'), this.remove.bind(this));
+ }
contextMenu.viewSection().appendItem(ls`Expand recursively`, this.expandRecursively.bind(this));
contextMenu.viewSection().appendItem(ls`Collapse children`, this.collapseChildren.bind(this));
}
_startEditing() {
- if (this.treeOutline.selectedDOMNode() !== this._node)
+ if (this.treeOutline.selectedDOMNode() !== this._node) {
return;
+ }
const listItem = this.listItemElement;
@@ -577,8 +609,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
if (this._node.nodeType() === Node.TEXT_NODE) {
const textNode = listItem.getElementsByClassName('webkit-html-text-node')[0];
- if (textNode)
+ if (textNode) {
return this._startEditingTextNode(textNode);
+ }
return;
}
}
@@ -603,11 +636,13 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
for (let i = 0, len = attributeElements.length; i < len; ++i) {
if (attributeElements[i].textContent === attributeName) {
for (let elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
- if (elem.nodeType !== Node.ELEMENT_NODE)
+ if (elem.nodeType !== Node.ELEMENT_NODE) {
continue;
+ }
- if (elem.classList.contains('webkit-html-attribute-value'))
+ if (elem.classList.contains('webkit-html-attribute-value')) {
return this._startEditingAttribute(elem.parentNode, elem);
+ }
}
}
}
@@ -616,12 +651,14 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
_startEditingAttribute(attribute, elementForSelection) {
console.assert(this.listItemElement.isAncestor(attribute));
- if (UI.isBeingEdited(attribute))
+ if (UI.isBeingEdited(attribute)) {
return true;
+ }
const attributeNameElement = attribute.getElementsByClassName('webkit-html-attribute-name')[0];
- if (!attributeNameElement)
+ if (!attributeNameElement) {
return false;
+ }
const attributeName = attributeNameElement.textContent;
const attributeValueElement = attribute.getElementsByClassName('webkit-html-attribute-value')[0];
@@ -636,11 +673,13 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
return;
}
- if (node.nodeType !== Node.ELEMENT_NODE)
+ if (node.nodeType !== Node.ELEMENT_NODE) {
return;
+ }
- for (let child = node.firstChild; child; child = child.nextSibling)
+ for (let child = node.firstChild; child; child = child.nextSibling) {
removeZeroWidthSpaceRecursive(child);
+ }
}
const attributeValue = attributeName && attributeValueElement ? this._node.getAttribute(attributeName) : undefined;
@@ -664,8 +703,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
return '';
}
- if (!attributeValueElement.textContent.asParsedURL())
+ if (!attributeValueElement.textContent.asParsedURL()) {
config.setPostKeydownFinishHandler(postKeyDownFinishHandler);
+ }
this._editing = UI.InplaceEditor.startEditing(attribute, config);
@@ -678,18 +718,21 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {!Element} textNodeElement
*/
_startEditingTextNode(textNodeElement) {
- if (UI.isBeingEdited(textNodeElement))
+ if (UI.isBeingEdited(textNodeElement)) {
return true;
+ }
let textNode = this._node;
// We only show text nodes inline in elements if the element only
// has a single child, and that child is a text node.
- if (textNode.nodeType() === Node.ELEMENT_NODE && textNode.firstChild)
+ if (textNode.nodeType() === Node.ELEMENT_NODE && textNode.firstChild) {
textNode = textNode.firstChild;
+ }
const container = textNodeElement.enclosingNodeOrSelfWithClass('webkit-html-text-node');
- if (container)
- container.textContent = textNode.nodeValue(); // Strip the CSS or JS highlighting if present.
+ if (container) {
+ container.textContent = textNode.nodeValue();
+ } // Strip the CSS or JS highlighting if present.
const config = new UI.InplaceEditor.Config(
this._textNodeEditingCommitted.bind(this, textNode), this._editingCancelled.bind(this));
this._editing = UI.InplaceEditor.startEditing(textNodeElement, config);
@@ -704,16 +747,19 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
_startEditingTagName(tagNameElement) {
if (!tagNameElement) {
tagNameElement = this.listItemElement.getElementsByClassName('webkit-html-tag-name')[0];
- if (!tagNameElement)
+ if (!tagNameElement) {
return false;
+ }
}
const tagName = tagNameElement.textContent;
- if (Elements.ElementsTreeElement.EditTagBlacklist.has(tagName.toLowerCase()))
+ if (Elements.ElementsTreeElement.EditTagBlacklist.has(tagName.toLowerCase())) {
return false;
+ }
- if (UI.isBeingEdited(tagNameElement))
+ if (UI.isBeingEdited(tagNameElement)) {
return true;
+ }
const closingTagElement = this._distinctClosingTagElement();
@@ -721,16 +767,18 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
function keyupListener(event) {
- if (closingTagElement)
+ if (closingTagElement) {
closingTagElement.textContent = '</' + tagNameElement.textContent + '>';
+ }
}
/**
* @param {!Event} event
*/
const keydownListener = event => {
- if (event.key !== ' ')
+ if (event.key !== ' ') {
return;
+ }
this._editing.commit();
event.consume(true);
};
@@ -770,11 +818,13 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {?string} maybeInitialValue
*/
_startEditingAsHTML(commitCallback, disposeCallback, maybeInitialValue) {
- if (maybeInitialValue === null)
+ if (maybeInitialValue === null) {
return;
+ }
let initialValue = maybeInitialValue; // To suppress a compiler warning.
- if (this._editing)
+ if (this._editing) {
return;
+ }
initialValue = this._convertWhitespaceToEntities(initialValue).text;
@@ -788,8 +838,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
child = child.nextSibling;
}
// Hide children item.
- if (this.childrenListElement)
+ if (this.childrenListElement) {
this.childrenListElement.style.display = 'none';
+ }
// Append editor.
this.listItemElement.appendChild(this._htmlEditElement);
@@ -816,8 +867,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
editor.widget().focus();
editor.widget().element.addEventListener('focusout', event => {
// The relatedTarget is null when no element gains focus, e.g. switching windows.
- if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(editor.widget().element))
+ if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(editor.widget().element)) {
this._editing.commit();
+ }
}, false);
editor.widget().element.addEventListener('keydown', keydown.bind(this), true);
@@ -852,8 +904,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
this.listItemElement.removeChild(this._htmlEditElement);
delete this._htmlEditElement;
// Unhide children item.
- if (this.childrenListElement)
+ if (this.childrenListElement) {
this.childrenListElement.style.removeProperty('display');
+ }
// Unhide header items.
let child = this.listItemElement.firstChild;
while (child) {
@@ -896,11 +949,13 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @this {Elements.ElementsTreeElement}
*/
function moveToNextAttributeIfNeeded(error) {
- if (error)
+ if (error) {
this._editingCancelled(element, attributeName);
+ }
- if (!moveDirection)
+ if (!moveDirection) {
return;
+ }
treeOutline.runPendingUpdates();
treeOutline.focus();
@@ -908,19 +963,22 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
// Search for the attribute's position, and then decide where to move to.
const attributes = this._node.attributes();
for (let i = 0; i < attributes.length; ++i) {
- if (attributes[i].name !== attributeName)
+ if (attributes[i].name !== attributeName) {
continue;
+ }
if (moveDirection === 'backward') {
- if (i === 0)
+ if (i === 0) {
this._startEditingTagName();
- else
+ } else {
this._triggerEditAttribute(attributes[i - 1].name);
+ }
} else {
- if (i === attributes.length - 1)
+ if (i === attributes.length - 1) {
this._addNewAttribute();
- else
+ } else {
this._triggerEditAttribute(attributes[i + 1].name);
+ }
}
return;
}
@@ -929,18 +987,21 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
if (moveDirection === 'backward') {
if (newText === ' ') {
// Moving from "New Attribute" that was not edited
- if (attributes.length > 0)
+ if (attributes.length > 0) {
this._triggerEditAttribute(attributes[attributes.length - 1].name);
+ }
} else {
// Moving from "New Attribute" that holds new value
- if (attributes.length > 1)
+ if (attributes.length > 1) {
this._triggerEditAttribute(attributes[attributes.length - 2].name);
+ }
}
} else if (moveDirection === 'forward') {
- if (!newText.isWhitespace())
+ if (!newText.isWhitespace()) {
this._addNewAttribute();
- else
+ } else {
this._startEditingTagName();
+ }
}
}
@@ -959,8 +1020,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
function cancel() {
const closingTagElement = self._distinctClosingTagElement();
- if (closingTagElement)
+ if (closingTagElement) {
closingTagElement.textContent = '</' + tagName + '>';
+ }
self._editingCancelled(element, tagName);
moveToNextAttributeIfNeeded.call(self);
@@ -976,10 +1038,11 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
const attributes = this._node.attributes();
- if (attributes.length > 0)
+ if (attributes.length > 0) {
this._triggerEditAttribute(attributes[0].name);
- else
+ } else {
this._addNewAttribute();
+ }
}
newText = newText.trim();
@@ -1056,8 +1119,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
updateTitle(updateRecord, onlySearchQueryChanged) {
// If we are editing, return early to prevent canceling the edit.
// After editing is committed updateTitle will be called.
- if (this._editing)
+ if (this._editing) {
return;
+ }
if (onlySearchQueryChanged) {
this._hideSearchHighlight();
@@ -1068,13 +1132,15 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
this.childrenListElement.classList.add('shadow-root');
let depth = 4;
for (let node = this._node; depth && node; node = node.parentNode) {
- if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE)
+ if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE) {
depth--;
+ }
}
- if (!depth)
+ if (!depth) {
this.childrenListElement.classList.add('shadow-root-deep');
- else
+ } else {
this.childrenListElement.classList.add('shadow-root-depth-' + depth);
+ }
}
const highlightElement = createElement('span');
highlightElement.className = 'highlight';
@@ -1112,11 +1178,13 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
updateDecorations() {
this._gutterContainer.style.left = (-this._computeLeftIndent()) + 'px';
- if (this.isClosingTag())
+ if (this.isClosingTag()) {
return;
+ }
- if (this._node.nodeType() !== Node.ELEMENT_NODE)
+ if (this._node.nodeType() !== Node.ELEMENT_NODE) {
return;
+ }
this._decorationsThrottler.schedule(this._updateDecorationsInternal.bind(this));
}
@@ -1125,14 +1193,15 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @return {!Promise}
*/
_updateDecorationsInternal() {
- if (!this.treeOutline)
+ if (!this.treeOutline) {
return Promise.resolve();
+ }
const node = this._node;
- if (!this.treeOutline._decoratorExtensions)
- /** @type {!Array.<!Runtime.Extension>} */
+ if (!this.treeOutline._decoratorExtensions) {
this.treeOutline._decoratorExtensions = self.runtime.extensions(Elements.MarkerDecorator);
+ }
const markerToExtension = new Map();
for (let i = 0; i < this.treeOutline._decoratorExtensions.length; ++i) {
@@ -1151,8 +1220,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
*/
function visitor(n, marker) {
const extension = markerToExtension.get(marker);
- if (!extension)
+ if (!extension) {
return;
+ }
promises.push(extension.instance().then(collectDecoration.bind(null, n)));
}
@@ -1162,8 +1232,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
*/
function collectDecoration(n, decorator) {
const decoration = decorator.decorate(n);
- if (!decoration)
+ if (!decoration) {
return;
+ }
(n === node ? decorations : descendantDecorations).push(decoration);
}
@@ -1177,8 +1248,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
this._decorationsElement.classList.add('hidden');
this._gutterContainer.classList.toggle('has-decorations', decorations.length || descendantDecorations.length);
- if (!decorations.length && !descendantDecorations.length)
+ if (!decorations.length && !descendantDecorations.length) {
return;
+ }
const colors = new Set();
const titles = createElement('div');
@@ -1188,8 +1260,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
titleElement.textContent = decoration.title;
colors.add(decoration.color);
}
- if (this.expanded && !decorations.length)
+ if (this.expanded && !decorations.length) {
return;
+ }
const descendantColors = new Set();
if (descendantDecorations.length) {
@@ -1205,8 +1278,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
let offset = 0;
processColors.call(this, colors, 'elements-gutter-decoration');
- if (!this.expanded)
+ if (!this.expanded) {
processColors.call(this, descendantColors, 'elements-gutter-decoration elements-has-decorated-children');
+ }
UI.Tooltip.install(this._decorationsElement, titles);
/**
@@ -1220,8 +1294,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
this._decorationsElement.classList.remove('hidden');
child.style.backgroundColor = color;
child.style.borderColor = color;
- if (offset)
+ if (offset) {
child.style.marginLeft = offset + 'px';
+ }
offset += 3;
}
}
@@ -1279,13 +1354,15 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
const attrNameElement = attrSpanElement.createChild('span', 'webkit-html-attribute-name');
attrNameElement.textContent = name;
- if (hasText)
+ if (hasText) {
attrSpanElement.createTextChild('=\u200B"');
+ }
const attrValueElement = attrSpanElement.createChild('span', 'webkit-html-attribute-value');
- if (updateRecord && updateRecord.isAttributeModified(name))
+ if (updateRecord && updateRecord.isAttributeModified(name)) {
UI.runCSSAnimationOnce(hasText ? attrValueElement : attrNameElement, 'dom-update-highlight');
+ }
/**
* @this {Elements.ElementsTreeElement}
@@ -1300,8 +1377,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
return span;
}
value = value.replace(closingPunctuationRegex, '$&\u200B');
- if (value.startsWith('data:'))
+ if (value.startsWith('data:')) {
value = value.trimMiddle(60);
+ }
const link = node.nodeName().toLowerCase() === 'a' ?
UI.XLink.create(rewrittenHref, value, '', true /* preventClick */) :
Components.Linkifier.linkifyURL(rewrittenHref, {text: value, preventClick: true});
@@ -1310,15 +1388,17 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
const nodeName = node ? node.nodeName().toLowerCase() : '';
- if (nodeName && (name === 'src' || name === 'href'))
+ if (nodeName && (name === 'src' || name === 'href')) {
attrValueElement.appendChild(linkifyValue.call(this, value));
- else if ((nodeName === 'img' || nodeName === 'source') && name === 'srcset')
+ } else if ((nodeName === 'img' || nodeName === 'source') && name === 'srcset') {
attrValueElement.appendChild(linkifySrcset.call(this, value));
- else
+ } else {
setValueWithEntities.call(this, attrValueElement, value);
+ }
- if (hasText)
+ if (hasText) {
attrSpanElement.createTextChild('"');
+ }
/**
* @param {string} value
@@ -1336,8 +1416,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
const fragment = createDocumentFragment();
let i = 0;
while (value.length) {
- if (i++ > 0)
+ if (i++ > 0) {
fragment.createTextChild(' ');
+ }
value = value.trim();
// The url and descriptor may end with a separating comma.
let url = '';
@@ -1350,10 +1431,11 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
} else {
url = value.substring(0, indexOfSpace);
const indexOfComma = value.indexOf(',', indexOfSpace);
- if (indexOfComma !== -1)
+ if (indexOfComma !== -1) {
descriptor = value.substring(indexOfSpace, indexOfComma + 1);
- else
+ } else {
descriptor = value.substring(indexOfSpace);
+ }
}
if (url) {
@@ -1365,8 +1447,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
fragment.appendChild(linkifyValue.call(this, url));
}
}
- if (descriptor)
+ if (descriptor) {
fragment.createTextChild(descriptor);
+ }
value = value.substring(url.length + descriptor.length);
}
return fragment;
@@ -1393,8 +1476,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
_buildTagDOM(parentElement, tagName, isClosingTag, isDistinctTreeElement, updateRecord) {
const node = this._node;
const classes = ['webkit-html-tag'];
- if (isClosingTag && isDistinctTreeElement)
+ if (isClosingTag && isDistinctTreeElement) {
classes.push('close');
+ }
const tagElement = parentElement.createChild('span', classes.join(' '));
tagElement.createTextChild('<');
const tagNameElement =
@@ -1412,8 +1496,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
if (updateRecord) {
let hasUpdates = updateRecord.hasRemovedAttributes() || updateRecord.hasRemovedChildren();
hasUpdates |= !this.expanded && updateRecord.hasChangedChildren();
- if (hasUpdates)
+ if (hasUpdates) {
UI.runCSSAnimationOnce(tagNameElement, 'dom-update-highlight');
+ }
}
}
@@ -1440,8 +1525,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
lastIndexAfterEntity = i + 1;
}
}
- if (result)
+ if (result) {
result += text.substring(lastIndexAfterEntity);
+ }
return {text: result || text, entityRanges: entityRanges};
}
@@ -1491,15 +1577,18 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
UI.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');
titleDOM.createTextChild('\u200B');
this._buildTagDOM(titleDOM, tagName, true, false, updateRecord);
- if (updateRecord && updateRecord.hasChangedChildren())
+ if (updateRecord && updateRecord.hasChangedChildren()) {
UI.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');
- if (updateRecord && updateRecord.isCharDataModified())
+ }
+ if (updateRecord && updateRecord.isCharDataModified()) {
UI.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');
+ }
break;
}
- if (this.treeOutline.isXMLMimeType || !Elements.ElementsTreeElement.ForbiddenClosingTagElements.has(tagName))
+ if (this.treeOutline.isXMLMimeType || !Elements.ElementsTreeElement.ForbiddenClosingTagElements.has(tagName)) {
this._buildTagDOM(titleDOM, tagName, true, false, updateRecord);
+ }
break;
case Node.TEXT_NODE:
@@ -1524,8 +1613,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
textNodeElement.textContent = result.text;
UI.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, 'webkit-html-entity-value');
titleDOM.createTextChild('"');
- if (updateRecord && updateRecord.isCharDataModified())
+ if (updateRecord && updateRecord.isCharDataModified()) {
UI.runCSSAnimationOnce(textNodeElement, 'dom-update-highlight');
+ }
}
break;
@@ -1539,14 +1629,16 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
docTypeElement.createTextChild('<!doctype ' + node.nodeName());
if (node.publicId) {
docTypeElement.createTextChild(' PUBLIC "' + node.publicId + '"');
- if (node.systemId)
+ if (node.systemId) {
docTypeElement.createTextChild(' "' + node.systemId + '"');
+ }
} else if (node.systemId) {
docTypeElement.createTextChild(' SYSTEM "' + node.systemId + '"');
}
- if (node.internalSubset)
+ if (node.internalSubset) {
docTypeElement.createTextChild(' [' + node.internalSubset + ']');
+ }
docTypeElement.createTextChild('>');
break;
@@ -1576,14 +1668,17 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
remove() {
- if (this._node.pseudoType())
+ if (this._node.pseudoType()) {
return;
+ }
const parentElement = this.parent;
- if (!parentElement)
+ if (!parentElement) {
return;
+ }
- if (!this._node.parentNode || this._node.parentNode.nodeType() === Node.DOCUMENT_NODE)
+ if (!this._node.parentNode || this._node.parentNode.nodeType() === Node.DOCUMENT_NODE) {
return;
+ }
this._node.removeNode();
}
@@ -1597,15 +1692,17 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
return;
}
- if (startEditing === false)
+ if (startEditing === false) {
return;
+ }
/**
* @param {?Protocol.Error} error
*/
function selectNode(error) {
- if (callback)
+ if (callback) {
callback(!error);
+ }
}
/**
@@ -1613,13 +1710,15 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @param {string} value
*/
function commitChange(initialValue, value) {
- if (initialValue !== value)
+ if (initialValue !== value) {
node.setOuterHTML(value, selectNode);
+ }
}
function disposeCallback() {
- if (callback)
+ if (callback) {
callback(false);
+ }
}
const node = this._node;
@@ -1627,48 +1726,54 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
_copyCSSPath() {
- InspectorFrontendHost.copyText(Elements.DOMPath.cssPath(this._node, true));
+ Host.InspectorFrontendHost.copyText(Elements.DOMPath.cssPath(this._node, true));
}
_copyJSPath() {
- InspectorFrontendHost.copyText(Elements.DOMPath.jsPath(this._node, true));
+ Host.InspectorFrontendHost.copyText(Elements.DOMPath.jsPath(this._node, true));
}
_copyXPath() {
- InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, true));
+ Host.InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, true));
}
_copyFullXPath() {
- InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, false));
+ Host.InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, false));
}
async _copyStyles() {
const node = this._node;
const cssModel = node.domModel().cssModel();
const cascade = await cssModel.cachedMatchedCascadeForNode(node);
- if (!cascade)
+ if (!cascade) {
return;
+ }
/** @type {!Array<string>} */
const lines = [];
for (const style of cascade.nodeStyles().reverse()) {
for (const property of style.leadingProperties()) {
- if (!property.parsedOk || property.disabled || !property.activeInStyle() || property.implicit)
+ if (!property.parsedOk || property.disabled || !property.activeInStyle() || property.implicit) {
continue;
- if (cascade.isInherited(style) && !SDK.cssMetadata().isPropertyInherited(property.name))
+ }
+ if (cascade.isInherited(style) && !SDK.cssMetadata().isPropertyInherited(property.name)) {
continue;
- if (style.parentRule && style.parentRule.isUserAgent())
+ }
+ if (style.parentRule && style.parentRule.isUserAgent()) {
continue;
- if (cascade.propertyState(property) !== SDK.CSSMatchedStyles.PropertyState.Active)
+ }
+ if (cascade.propertyState(property) !== SDK.CSSMatchedStyles.PropertyState.Active) {
continue;
+ }
lines.push(`${property.name}: ${property.value};`);
}
}
- InspectorFrontendHost.copyText(lines.join('\n'));
+ Host.InspectorFrontendHost.copyText(lines.join('\n'));
}
_highlightSearchResults() {
- if (!this._searchQuery || !this._searchHighlightsVisible)
+ if (!this._searchQuery || !this._searchHighlightsVisible) {
return;
+ }
this._hideSearchHighlight();
const text = this.listItemElement.textContent;
@@ -1682,8 +1787,9 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
}
// Fall back for XPath, etc. matches.
- if (!matchRanges.length)
+ if (!matchRanges.length) {
matchRanges.push(new TextUtils.SourceRange(0, text.length));
+ }
this._highlightResult = [];
UI.highlightSearchResults(this.listItemElement, matchRanges, this._highlightResult);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElementHighlighter.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElementHighlighter.js
index ab4d25da958..3786f5279a8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElementHighlighter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElementHighlighter.js
@@ -24,8 +24,9 @@ Elements.ElementsTreeElementHighlighter = class {
* @param {!Common.Event} event
*/
_highlightNode(event) {
- if (!Common.moduleSetting('highlightNodeOnHoverInOverlay').get())
+ if (!Common.moduleSetting('highlightNodeOnHoverInOverlay').get()) {
return;
+ }
const domNode = /** @type {!SDK.DOMNode} */ (event.data);
@@ -53,8 +54,9 @@ Elements.ElementsTreeElementHighlighter = class {
if (this._currentHighlightedElement) {
let currentTreeElement = this._currentHighlightedElement;
while (currentTreeElement !== this._alreadyExpandedParentElement) {
- if (currentTreeElement.expanded)
+ if (currentTreeElement.expanded) {
currentTreeElement.collapse();
+ }
currentTreeElement = currentTreeElement.parent;
}
@@ -66,8 +68,9 @@ Elements.ElementsTreeElementHighlighter = class {
let deepestExpandedParent = node;
const treeElementSymbol = this._treeOutline.treeElementSymbol();
while (deepestExpandedParent &&
- (!deepestExpandedParent[treeElementSymbol] || !deepestExpandedParent[treeElementSymbol].expanded))
+ (!deepestExpandedParent[treeElementSymbol] || !deepestExpandedParent[treeElementSymbol].expanded)) {
deepestExpandedParent = deepestExpandedParent.parentNode;
+ }
this._alreadyExpandedParentElement =
deepestExpandedParent ? deepestExpandedParent[treeElementSymbol] : this._treeOutline.rootElement();
@@ -76,15 +79,17 @@ Elements.ElementsTreeElementHighlighter = class {
this._currentHighlightedElement = treeElement;
this._treeOutline.setHoverEffect(treeElement);
- if (treeElement)
+ if (treeElement) {
treeElement.reveal(true);
+ }
this._isModifyingTreeOutline = false;
}
_clearState() {
- if (this._isModifyingTreeOutline)
+ if (this._isModifyingTreeOutline) {
return;
+ }
delete this._currentHighlightedElement;
delete this._alreadyExpandedParentElement;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
index 9380824a644..ccfbb845a41 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
@@ -47,8 +47,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
this._element = this.element;
this._element.classList.add('elements-tree-outline', 'source-code');
- if (hideGutter)
+ if (hideGutter) {
this._element.classList.add('elements-hide-gutter');
+ }
UI.ARIAUtils.setAccessibleName(this._element, Common.UIString('Page DOM'));
this._element.addEventListener('focusout', this._onfocusout.bind(this), false);
this._element.addEventListener('mousedown', this._onmousedown.bind(this), false);
@@ -102,8 +103,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_onShowHTMLCommentsChange() {
const selectedNode = this.selectedDOMNode();
- if (selectedNode && selectedNode.nodeType() === Node.COMMENT_NODE && !this._showHTMLCommentsSetting.get())
+ if (selectedNode && selectedNode.nodeType() === Node.COMMENT_NODE && !this._showHTMLCommentsSetting.get()) {
this.selectDOMNode(selectedNode.parentNode);
+ }
this.update();
}
@@ -141,8 +143,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
setVisibleWidth(width) {
this._visibleWidth = width;
- if (this._multilineEditing)
+ if (this._multilineEditing) {
this._multilineEditing.resize();
+ }
}
/**
@@ -151,15 +154,17 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_setClipboardData(data) {
if (this._clipboardNodeData) {
const treeElement = this.findTreeElement(this._clipboardNodeData.node);
- if (treeElement)
+ if (treeElement) {
treeElement.setInClipboard(false);
+ }
delete this._clipboardNodeData;
}
if (data) {
const treeElement = this.findTreeElement(data.node);
- if (treeElement)
+ if (treeElement) {
treeElement.setInClipboard(true);
+ }
this._clipboardNodeData = data;
}
}
@@ -168,8 +173,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {!SDK.DOMNode} removedNode
*/
resetClipboardIfNeeded(removedNode) {
- if (this._clipboardNodeData && this._clipboardNodeData.node === removedNode)
+ if (this._clipboardNodeData && this._clipboardNodeData.node === removedNode) {
this._setClipboardData(null);
+ }
}
/**
@@ -188,16 +194,19 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const originalEvent = event['original'];
// Don't prevent the normal copy if the user has a selection.
- if (originalEvent.target.hasSelection())
+ if (originalEvent.target.hasSelection()) {
return;
+ }
// Do not interfere with text editing.
- if (UI.isEditing())
+ if (UI.isEditing()) {
return;
+ }
const targetNode = this.selectedDOMNode();
- if (!targetNode)
+ if (!targetNode) {
return;
+ }
originalEvent.clipboardData.clearData();
event.handled = true;
@@ -210,8 +219,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {?SDK.DOMNode} node
*/
performCopyOrCut(isCut, node) {
- if (isCut && (node.isShadowRoot() || node.ancestorUserAgentShadowRoot()))
+ if (isCut && (node.isShadowRoot() || node.ancestorUserAgentShadowRoot())) {
return;
+ }
node.copyNode();
this._setClipboardData({node: node, isCut: isCut});
@@ -222,18 +232,22 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {boolean}
*/
canPaste(targetNode) {
- if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot())
+ if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot()) {
return false;
+ }
- if (!this._clipboardNodeData)
+ if (!this._clipboardNodeData) {
return false;
+ }
const node = this._clipboardNodeData.node;
- if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode)))
+ if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode))) {
return false;
+ }
- if (targetNode.domModel() !== node.domModel())
+ if (targetNode.domModel() !== node.domModel()) {
return false;
+ }
return true;
}
@@ -241,8 +255,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {!SDK.DOMNode} targetNode
*/
pasteNode(targetNode) {
- if (this.canPaste(targetNode))
+ if (this.canPaste(targetNode)) {
this._performPaste(targetNode);
+ }
}
/**
@@ -250,12 +265,14 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
_onPaste(event) {
// Do not interfere with text editing.
- if (UI.isEditing())
+ if (UI.isEditing()) {
return;
+ }
const targetNode = this.selectedDOMNode();
- if (!targetNode || !this.canPaste(targetNode))
+ if (!targetNode || !this.canPaste(targetNode)) {
return;
+ }
event.handled = true;
this._performPaste(targetNode);
@@ -278,11 +295,13 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @this {Elements.ElementsTreeOutline}
*/
function expandCallback(error, nodeId) {
- if (error)
+ if (error) {
return;
+ }
const pastedNode = targetNode.domModel().nodeForId(nodeId);
- if (!pastedNode)
+ if (!pastedNode) {
return;
+ }
this.selectDOMNode(pastedNode);
}
}
@@ -291,19 +310,22 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {boolean} visible
*/
setVisible(visible) {
- if (visible === this._visible)
+ if (visible === this._visible) {
return;
+ }
this._visible = visible;
if (!this._visible) {
this._popoverHelper.hidePopover();
- if (this._multilineEditing)
+ if (this._multilineEditing) {
this._multilineEditing.cancel();
+ }
return;
}
this.runPendingUpdates();
- if (this._selectedDOMNode)
+ if (this._selectedDOMNode) {
this._revealAndSelectNode(this._selectedDOMNode, false);
+ }
}
get rootDOMNode() {
@@ -311,8 +333,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
}
set rootDOMNode(x) {
- if (this._rootDOMNode === x)
+ if (this._rootDOMNode === x) {
return;
+ }
this._rootDOMNode = x;
@@ -349,8 +372,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
// and the select() call would change the selectedDOMNode and reenter this setter. So to
// avoid calling _selectedNodeChanged() twice, first check if _selectedDOMNode is the same
// node as the one passed in.
- if (this._selectedDOMNode === node)
+ if (this._selectedDOMNode === node) {
this._selectedNodeChanged(!!focus);
+ }
}
/**
@@ -358,19 +382,22 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
editing() {
const node = this.selectedDOMNode();
- if (!node)
+ if (!node) {
return false;
+ }
const treeElement = this.findTreeElement(node);
- if (!treeElement)
+ if (!treeElement) {
return false;
+ }
return treeElement.isEditing() || false;
}
update() {
const selectedNode = this.selectedDOMNode();
this.removeChildren();
- if (!this.rootDOMNode)
+ if (!this.rootDOMNode) {
return;
+ }
if (this._includeRootDOMNode) {
const treeElement = this._createElementTreeElement(this.rootDOMNode);
@@ -384,8 +411,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
}
}
- if (selectedNode)
+ if (selectedNode) {
this._revealAndSelectNode(selectedNode, true);
+ }
}
/**
@@ -422,12 +450,14 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {?UI.TreeElement}
*/
_lookUpTreeElement(node) {
- if (!node)
+ if (!node) {
return null;
+ }
const cachedElement = node[this._treeElementSymbol];
- if (cachedElement)
+ if (cachedElement) {
return cachedElement;
+ }
// Walk up the parent pointers from the desired node
const ancestors = [];
@@ -435,11 +465,14 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
for (currentNode = node.parentNode; currentNode; currentNode = currentNode.parentNode) {
ancestors.push(currentNode);
if (currentNode[this._treeElementSymbol]) // stop climbing as soon as we hit
+ {
break;
+ }
}
- if (!currentNode)
+ if (!currentNode) {
return null;
+ }
// Walk down to populate each ancestor's children, to fill in the tree and the cache.
for (let i = ancestors.length - 1; i >= 0; --i) {
@@ -447,8 +480,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const treeElement = ancestors[i][this._treeElementSymbol];
if (treeElement) {
treeElement.onpopulate(); // fill the cache with the children of treeElement
- if (child.index >= treeElement.expandedChildrenLimit())
+ if (child.index >= treeElement.expandedChildrenLimit()) {
this.setExpandedChildrenLimit(treeElement, child.index + 1);
+ }
}
}
@@ -461,18 +495,21 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
createTreeElementFor(node) {
let treeElement = this.findTreeElement(node);
- if (treeElement)
+ if (treeElement) {
return treeElement;
- if (!node.parentNode)
+ }
+ if (!node.parentNode) {
return null;
+ }
treeElement = this.createTreeElementFor(node.parentNode);
return treeElement ? this._showChild(treeElement, node) : null;
}
set suppressRevealAndSelect(x) {
- if (this._suppressRevealAndSelect === x)
+ if (this._suppressRevealAndSelect === x) {
return;
+ }
this._suppressRevealAndSelect = x;
}
@@ -481,16 +518,20 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {boolean} omitFocus
*/
_revealAndSelectNode(node, omitFocus) {
- if (this._suppressRevealAndSelect)
+ if (this._suppressRevealAndSelect) {
return;
+ }
- if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode)
+ if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode) {
node = this.rootDOMNode.firstChild;
- if (!node)
+ }
+ if (!node) {
return;
+ }
const treeElement = this.createTreeElementFor(node);
- if (!treeElement)
+ if (!treeElement) {
return;
+ }
treeElement.revealAndSelect(omitFocus);
}
@@ -515,10 +556,11 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const elementUnderMouse = this.treeElementFromPoint(x, y);
const elementAboveMouse = this.treeElementFromPoint(x, y - 2);
let element;
- if (elementUnderMouse === elementAboveMouse)
+ if (elementUnderMouse === elementAboveMouse) {
element = elementUnderMouse;
- else
+ } else {
element = this.treeElementFromPoint(x, y + 2);
+ }
return element;
}
@@ -529,10 +571,12 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
_getPopoverRequest(event) {
let link = event.target;
- while (link && !link[Elements.ElementsTreeElement.HrefSymbol])
+ while (link && !link[Elements.ElementsTreeElement.HrefSymbol]) {
link = link.parentElementOrShadowHost();
- if (!link)
+ }
+ if (!link) {
return null;
+ }
return {
box: link.boxInWindow(),
@@ -541,9 +585,10 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const node = /** @type {!Elements.ElementsTreeElement} */ (listItem.treeElement).node();
const precomputedFeatures = await Components.ImagePreview.loadDimensionsForNode(node);
const preview = await Components.ImagePreview.build(
- node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true, precomputedFeatures);
- if (preview)
+ node.domModel().target(), link[Elements.ElementsTreeElement.HrefSymbol], true, {precomputedFeatures});
+ if (preview) {
popover.contentElement.appendChild(preview);
+ }
return !!preview;
}
};
@@ -559,8 +604,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_onmousedown(event) {
const element = this._treeElementFromEvent(event);
- if (!element || element.isEventWithinDisclosureTriangle(event))
+ if (!element || element.isEventWithinDisclosureTriangle(event)) {
return;
+ }
element.select();
}
@@ -569,8 +615,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {?UI.TreeElement} treeElement
*/
setHoverEffect(treeElement) {
- if (this._previousHoveredElement === treeElement)
+ if (this._previousHoveredElement === treeElement) {
return;
+ }
if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
@@ -585,8 +632,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_onmousemove(event) {
const element = this._treeElementFromEvent(event);
- if (element && this._previousHoveredElement === element)
+ if (element && this._previousHoveredElement === element) {
return;
+ }
this.setHoverEffect(element);
this._highlightTreeElement(
@@ -603,8 +651,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
return;
}
- if (element instanceof Elements.ElementsTreeOutline.ShortcutTreeElement)
+ if (element instanceof Elements.ElementsTreeOutline.ShortcutTreeElement) {
element.domModel().overlayModel().highlightInOverlay({deferredNode: element.deferredNode()}, 'all', showInfo);
+ }
}
_onmouseleave(event) {
@@ -613,17 +662,21 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
}
_ondragstart(event) {
- if (event.target.hasSelection())
+ if (event.target.hasSelection()) {
return false;
- if (event.target.nodeName === 'A')
+ }
+ if (event.target.nodeName === 'A') {
return false;
+ }
const treeElement = this._validDragSourceOrTarget(this._treeElementFromEvent(event));
- if (!treeElement)
+ if (!treeElement) {
return false;
+ }
- if (treeElement.node().nodeName() === 'BODY' || treeElement.node().nodeName() === 'HEAD')
+ if (treeElement.node().nodeName() === 'BODY' || treeElement.node().nodeName() === 'HEAD') {
return false;
+ }
event.dataTransfer.setData('text/plain', treeElement.listItemElement.textContent.replace(/\u200b/g, ''));
event.dataTransfer.effectAllowed = 'copyMove';
@@ -635,17 +688,20 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
}
_ondragover(event) {
- if (!this._treeElementBeingDragged)
+ if (!this._treeElementBeingDragged) {
return false;
+ }
const treeElement = this._validDragSourceOrTarget(this._treeElementFromEvent(event));
- if (!treeElement)
+ if (!treeElement) {
return false;
+ }
let node = treeElement.node();
while (node) {
- if (node === this._treeElementBeingDragged._node)
+ if (node === this._treeElementBeingDragged._node) {
return false;
+ }
node = node.parentNode;
}
@@ -667,16 +723,19 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {?Elements.ElementsTreeElement}
*/
_validDragSourceOrTarget(treeElement) {
- if (!treeElement)
+ if (!treeElement) {
return null;
+ }
- if (!(treeElement instanceof Elements.ElementsTreeElement))
+ if (!(treeElement instanceof Elements.ElementsTreeElement)) {
return null;
+ }
const elementsTreeElement = /** @type {!Elements.ElementsTreeElement} */ (treeElement);
const node = elementsTreeElement.node();
- if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
+ if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE) {
return null;
+ }
return elementsTreeElement;
}
@@ -684,16 +743,18 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_ondrop(event) {
event.preventDefault();
const treeElement = this._treeElementFromEvent(event);
- if (treeElement instanceof Elements.ElementsTreeElement)
+ if (treeElement instanceof Elements.ElementsTreeElement) {
this._doMove(treeElement);
+ }
}
/**
* @param {!Elements.ElementsTreeElement} treeElement
*/
_doMove(treeElement) {
- if (!this._treeElementBeingDragged)
+ if (!this._treeElementBeingDragged) {
return;
+ }
let parentNode;
let anchorNode;
@@ -729,8 +790,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_contextMenuEventFired(event) {
const treeElement = this._treeElementFromEvent(event);
- if (treeElement instanceof Elements.ElementsTreeElement)
+ if (treeElement instanceof Elements.ElementsTreeElement) {
this.showContextMenu(treeElement, event);
+ }
}
/**
@@ -738,26 +800,29 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {!Event} event
*/
showContextMenu(treeElement, event) {
- if (UI.isEditing())
+ if (UI.isEditing()) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
const isPseudoElement = !!treeElement.node().pseudoType();
const isTag = treeElement.node().nodeType() === Node.ELEMENT_NODE && !isPseudoElement;
let textNode = event.target.enclosingNodeOrSelfWithClass('webkit-html-text-node');
- if (textNode && textNode.classList.contains('bogus'))
+ if (textNode && textNode.classList.contains('bogus')) {
textNode = null;
+ }
const commentNode = event.target.enclosingNodeOrSelfWithClass('webkit-html-comment');
contextMenu.saveSection().appendItem(
ls`Store as global variable`, this._saveNodeToTempVariable.bind(this, treeElement.node()));
- if (textNode)
+ if (textNode) {
treeElement.populateTextContextMenu(contextMenu, textNode);
- else if (isTag)
+ } else if (isTag) {
treeElement.populateTagContextMenu(contextMenu, event);
- else if (commentNode)
+ } else if (commentNode) {
treeElement.populateNodeContextMenu(contextMenu);
- else if (isPseudoElement)
+ } else if (isPseudoElement) {
treeElement.populateScrollIntoView(contextMenu);
+ }
contextMenu.appendApplicableItems(treeElement.node());
contextMenu.show();
@@ -780,14 +845,17 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
_onKeyDown(event) {
const keyboardEvent = /** @type {!KeyboardEvent} */ (event);
- if (UI.isEditing())
+ if (UI.isEditing()) {
return;
+ }
const node = this.selectedDOMNode();
- if (!node)
+ if (!node) {
return;
+ }
const treeElement = node[this._treeElementSymbol];
- if (!treeElement)
+ if (!treeElement) {
return;
+ }
if (UI.KeyboardShortcut.eventHasCtrlOrMeta(keyboardEvent) && node.parentNode) {
if (keyboardEvent.key === 'ArrowUp' && node.previousSibling) {
@@ -811,11 +879,13 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
*/
toggleEditAsHTML(node, startEditing, callback) {
const treeElement = node[this._treeElementSymbol];
- if (!treeElement || !treeElement.hasEditableNode())
+ if (!treeElement || !treeElement.hasEditableNode()) {
return;
+ }
- if (node.pseudoType())
+ if (node.pseudoType()) {
return;
+ }
const parentNode = node.parentNode;
const index = node.index;
@@ -828,24 +898,28 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {boolean} success
*/
function editingFinished(success) {
- if (callback)
+ if (callback) {
callback();
- if (!success)
+ }
+ if (!success) {
return;
+ }
// Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
this.runPendingUpdates();
const newNode = parentNode ? parentNode.children()[index] || parentNode : null;
- if (!newNode)
+ if (!newNode) {
return;
+ }
this.selectDOMNode(newNode, true);
if (wasExpanded) {
const newTreeItem = this.findTreeElement(newNode);
- if (newTreeItem)
+ if (newTreeItem) {
newTreeItem.expand();
+ }
}
}
}
@@ -857,21 +931,24 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {?Elements.ElementsTreeElement} nodeId
*/
selectNodeAfterEdit(wasExpanded, error, newNode) {
- if (error)
+ if (error) {
return null;
+ }
// Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
this.runPendingUpdates();
- if (!newNode)
+ if (!newNode) {
return null;
+ }
this.selectDOMNode(newNode, true);
const newTreeItem = this.findTreeElement(newNode);
if (wasExpanded) {
- if (newTreeItem)
+ if (newTreeItem) {
newTreeItem.expand();
+ }
}
return newTreeItem;
}
@@ -887,14 +964,16 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
async toggleHideElement(node) {
const pseudoType = node.pseudoType();
const effectiveNode = pseudoType ? node.parentNode : node;
- if (!effectiveNode)
+ if (!effectiveNode) {
return;
+ }
const hidden = node.marker('hidden-marker');
const object = await effectiveNode.resolveToObject('');
- if (!object)
+ if (!object) {
return;
+ }
await object.callFunction(toggleClassAndInjectStyleRule, [{value: pseudoType}, {value: !hidden}]);
object.release();
@@ -923,18 +1002,20 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
this.classList.toggle(className, hidden);
let localRoot = this;
- while (localRoot.parentNode)
+ while (localRoot.parentNode) {
localRoot = localRoot.parentNode;
- if (localRoot.nodeType === Node.DOCUMENT_NODE)
+ }
+ if (localRoot.nodeType === Node.DOCUMENT_NODE) {
localRoot = document.head;
+ }
let style = localRoot.querySelector('style#' + styleTagId);
- if (style)
+ if (style) {
return;
+ }
style = document.createElement('style');
style.id = styleTagId;
- style.type = 'text/css';
style.textContent = rule;
localRoot.appendChild(style);
@@ -1008,8 +1089,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {?Elements.ElementsTreeOutline.UpdateRecord}
*/
_updateRecordForHighlight(node) {
- if (!this._visible)
+ if (!this._visible) {
return null;
+ }
return this._updateRecords.get(node) || null;
}
@@ -1019,8 +1101,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_documentUpdated(event) {
const domModel = /** @type {!SDK.DOMModel} */ (event.data);
this._reset();
- if (domModel.existingDocument())
+ if (domModel.existingDocument()) {
this.rootDOMNode = domModel.existingDocument();
+ }
}
/**
@@ -1048,8 +1131,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const node = /** @type {!SDK.DOMNode} */ (event.data);
this._addUpdateRecord(node).charDataModified();
// Text could be large and force us to render itself as the child in the tree outline.
- if (node.parentNode && node.parentNode.firstChild === node.parentNode.lastChild)
+ if (node.parentNode && node.parentNode.firstChild === node.parentNode.lastChild) {
this._addUpdateRecord(node.parentNode).childrenModified();
+ }
this._updateModifiedNodesSoon();
}
@@ -1092,10 +1176,12 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
}
_updateModifiedNodesSoon() {
- if (!this._updateRecords.size)
+ if (!this._updateRecords.size) {
return;
- if (this._updateModifiedNodesTimeout)
+ }
+ if (this._updateModifiedNodesTimeout) {
return;
+ }
this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 50);
}
@@ -1121,17 +1207,19 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
this.update();
} else {
for (const node of this._updateRecords.keys()) {
- if (this._updateRecords.get(node).hasChangedChildren())
+ if (this._updateRecords.get(node).hasChangedChildren()) {
this._updateModifiedParentNode(node);
- else
+ } else {
this._updateModifiedNode(node);
+ }
}
}
if (hidePanelWhileUpdating) {
this._element.classList.remove('hidden');
- if (originalScrollTop)
+ if (originalScrollTop) {
treeOutlineContainerElement.scrollTop = originalScrollTop;
+ }
}
this._updateRecords.clear();
@@ -1140,8 +1228,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_updateModifiedNode(node) {
const treeElement = this.findTreeElement(node);
- if (treeElement)
+ if (treeElement) {
treeElement.updateTitle(this._updateRecordForHighlight(node));
+ }
}
_updateModifiedParentNode(node) {
@@ -1149,8 +1238,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
if (parentTreeElement) {
parentTreeElement.setExpandable(this._hasVisibleChildren(node));
parentTreeElement.updateTitle(this._updateRecordForHighlight(node));
- if (parentTreeElement.populated)
+ if (parentTreeElement.populated) {
this._updateChildren(parentTreeElement);
+ }
}
}
@@ -1159,8 +1249,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @returns {!Promise}
*/
populateTreeElement(treeElement) {
- if (treeElement.childCount() || !treeElement.isExpandable())
+ if (treeElement.childCount() || !treeElement.isExpandable()) {
return Promise.resolve();
+ }
return new Promise(resolve => {
treeElement.node().getChildNodes(() => {
@@ -1180,8 +1271,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const treeElement = new Elements.ElementsTreeElement(node, closingTag);
treeElement.setExpandable(!closingTag && this._hasVisibleChildren(node));
if (node.nodeType() === Node.ELEMENT_NODE && node.parentNode && node.parentNode.nodeType() === Node.DOCUMENT_NODE &&
- !node.parentNode.parentNode)
+ !node.parentNode.parentNode) {
treeElement.setCollapsible(false);
+ }
treeElement.selectable = this._selectEnabled;
return treeElement;
}
@@ -1192,15 +1284,18 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {?Elements.ElementsTreeElement}
*/
_showChild(treeElement, child) {
- if (treeElement.isClosingTag())
+ if (treeElement.isClosingTag()) {
return null;
+ }
const index = this._visibleChildren(treeElement.node()).indexOf(child);
- if (index === -1)
+ if (index === -1) {
return null;
+ }
- if (index >= treeElement.expandedChildrenLimit())
+ if (index >= treeElement.expandedChildrenLimit()) {
this.setExpandedChildrenLimit(treeElement, index + 1);
+ }
return /** @type {!Elements.ElementsTreeElement} */ (treeElement.childAt(index));
}
@@ -1212,32 +1307,38 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
let visibleChildren = Elements.ElementsTreeElement.visibleShadowRoots(node);
const contentDocument = node.contentDocument();
- if (contentDocument)
+ if (contentDocument) {
visibleChildren.push(contentDocument);
+ }
const importedDocument = node.importedDocument();
- if (importedDocument)
+ if (importedDocument) {
visibleChildren.push(importedDocument);
+ }
const templateContent = node.templateContent();
- if (templateContent)
+ if (templateContent) {
visibleChildren.push(templateContent);
+ }
const beforePseudoElement = node.beforePseudoElement();
- if (beforePseudoElement)
+ if (beforePseudoElement) {
visibleChildren.push(beforePseudoElement);
+ }
if (node.childNodeCount()) {
// Children may be stale when the outline is not wired to receive DOMModel updates.
let children = node.children() || [];
- if (!this._showHTMLCommentsSetting.get())
+ if (!this._showHTMLCommentsSetting.get()) {
children = children.filter(n => n.nodeType() !== Node.COMMENT_NODE);
+ }
visibleChildren = visibleChildren.concat(children);
}
const afterPseudoElement = node.afterPseudoElement();
- if (afterPseudoElement)
+ if (afterPseudoElement) {
visibleChildren.push(afterPseudoElement);
+ }
return visibleChildren;
}
@@ -1247,22 +1348,30 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @return {boolean}
*/
_hasVisibleChildren(node) {
- if (node.isIframe())
+ if (node.isIframe()) {
return true;
- if (node.isPortal())
+ }
+ if (node.isPortal()) {
return true;
- if (node.contentDocument())
+ }
+ if (node.contentDocument()) {
return true;
- if (node.importedDocument())
+ }
+ if (node.importedDocument()) {
return true;
- if (node.templateContent())
+ }
+ if (node.templateContent()) {
return true;
- if (Elements.ElementsTreeElement.visibleShadowRoots(node).length)
+ }
+ if (Elements.ElementsTreeElement.visibleShadowRoots(node).length) {
return true;
- if (node.hasPseudoElements())
+ }
+ if (node.hasPseudoElements()) {
return true;
- if (node.isInsertionPoint())
+ }
+ if (node.isInsertionPoint()) {
return true;
+ }
return !!node.childNodeCount() && !Elements.ElementsTreeElement.canShowInlineText(node);
}
@@ -1297,12 +1406,14 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {number} expandedChildrenLimit
*/
setExpandedChildrenLimit(treeElement, expandedChildrenLimit) {
- if (treeElement.expandedChildrenLimit() === expandedChildrenLimit)
+ if (treeElement.expandedChildrenLimit() === expandedChildrenLimit) {
return;
+ }
treeElement.setExpandedChildrenLimit(expandedChildrenLimit);
- if (treeElement.treeOutline && !this._treeElementsBeingUpdated.has(treeElement))
+ if (treeElement.treeOutline && !this._treeElementsBeingUpdated.has(treeElement)) {
this._updateModifiedParentNode(treeElement.node());
+ }
}
/**
@@ -1311,8 +1422,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_updateChildren(treeElement) {
if (!treeElement.isExpandable()) {
const selectedTreeElement = treeElement.treeOutline.selectedTreeElement;
- if (selectedTreeElement && selectedTreeElement.hasAncestor(treeElement))
+ if (selectedTreeElement && selectedTreeElement.hasAncestor(treeElement)) {
treeElement.select(true);
+ }
treeElement.removeChildren();
return;
}
@@ -1341,22 +1453,26 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
* @param {number} targetIndex
*/
_moveChild(treeElement, child, targetIndex) {
- if (treeElement.indexOfChild(child) === targetIndex)
+ if (treeElement.indexOfChild(child) === targetIndex) {
return;
+ }
const wasSelected = child.selected;
- if (child.parent)
+ if (child.parent) {
child.parent.removeChild(child);
+ }
treeElement.insertChild(child, targetIndex);
- if (wasSelected)
+ if (wasSelected) {
child.select();
+ }
}
/**
* @param {!Elements.ElementsTreeElement} treeElement
*/
_innerUpdateChildren(treeElement) {
- if (this._treeElementsBeingUpdated.has(treeElement))
+ if (this._treeElementsBeingUpdated.has(treeElement)) {
return;
+ }
this._treeElementsBeingUpdated.add(treeElement);
@@ -1394,11 +1510,13 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
} else {
// No existing element found, insert a new element.
const newElement = this.insertChildElement(treeElement, child, i);
- if (this._updateRecordForHighlight(node) && treeElement.expanded)
+ if (this._updateRecordForHighlight(node) && treeElement.expanded) {
Elements.ElementsTreeElement.animateOnDOMUpdate(newElement);
+ }
// If a node was inserted in the middle of existing list dynamically we might need to increase the limit.
- if (treeElement.childCount() > treeElement.expandedChildrenLimit())
+ if (treeElement.childCount() > treeElement.expandedChildrenLimit()) {
this.setExpandedChildrenLimit(treeElement, treeElement.expandedChildrenLimit() + 1);
+ }
}
}
@@ -1406,8 +1524,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
const expandedChildCount = treeElement.childCount();
if (visibleChildren.length > expandedChildCount) {
const targetButtonIndex = expandedChildCount;
- if (!treeElement.expandAllButtonElement)
+ if (!treeElement.expandAllButtonElement) {
treeElement.expandAllButtonElement = this._createExpandAllButtonTreeElement(treeElement);
+ }
treeElement.insertChild(treeElement.expandAllButtonElement, targetButtonIndex);
treeElement.expandAllButtonElement.button.textContent =
Common.UIString('Show All Nodes (%d More)', visibleChildren.length - expandedChildCount);
@@ -1417,13 +1536,15 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
// Insert shortcuts to distrubuted children.
if (node.isInsertionPoint()) {
- for (const distributedNode of node.distributedNodes())
+ for (const distributedNode of node.distributedNodes()) {
treeElement.appendChild(new Elements.ElementsTreeOutline.ShortcutTreeElement(distributedNode));
+ }
}
// Insert close tag.
- if (node.nodeType() === Node.ELEMENT_NODE && treeElement.isExpandable())
+ if (node.nodeType() === Node.ELEMENT_NODE && treeElement.isExpandable()) {
this.insertChildElement(treeElement, node, treeElement.childCount(), true);
+ }
this._treeElementsBeingUpdated.delete(treeElement);
}
@@ -1434,8 +1555,9 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
_markersChanged(event) {
const node = /** @type {!SDK.DOMNode} */ (event.data);
const treeElement = node[this._treeElementSymbol];
- if (treeElement)
+ if (treeElement) {
treeElement.updateDecorations();
+ }
}
};
@@ -1445,7 +1567,7 @@ Elements.ElementsTreeOutline._treeOutlineSymbol = Symbol('treeOutline');
/** @typedef {{node: !SDK.DOMNode, isCut: boolean}} */
Elements.ElementsTreeOutline.ClipboardData;
-/** @enum {symbol} */
+/** @override @suppress {checkPrototypalTypes} @enum {symbol} */
Elements.ElementsTreeOutline.Events = {
SelectedNodeChanged: Symbol('SelectedNodeChanged'),
ElementsTreeUpdated: Symbol('ElementsTreeUpdated')
@@ -1456,9 +1578,9 @@ Elements.ElementsTreeOutline.Events = {
* @type {!Object.<string, string>}
*/
Elements.ElementsTreeOutline.MappedCharToEntity = {
- '\u00a0': 'nbsp',
- '\u0093': '#147', // <control>
- '\u00ad': 'shy',
+ '\xA0': 'nbsp',
+ '\x93': '#147', // <control>
+ '\xAD': 'shy',
'\u2002': 'ensp',
'\u2003': 'emsp',
'\u2009': 'thinsp',
@@ -1484,10 +1606,12 @@ Elements.ElementsTreeOutline.UpdateRecord = class {
* @param {string} attrName
*/
attributeModified(attrName) {
- if (this._removedAttributes && this._removedAttributes.has(attrName))
+ if (this._removedAttributes && this._removedAttributes.has(attrName)) {
this._removedAttributes.delete(attrName);
- if (!this._modifiedAttributes)
+ }
+ if (!this._modifiedAttributes) {
this._modifiedAttributes = /** @type {!Set.<string>} */ (new Set());
+ }
this._modifiedAttributes.add(attrName);
}
@@ -1495,10 +1619,12 @@ Elements.ElementsTreeOutline.UpdateRecord = class {
* @param {string} attrName
*/
attributeRemoved(attrName) {
- if (this._modifiedAttributes && this._modifiedAttributes.has(attrName))
+ if (this._modifiedAttributes && this._modifiedAttributes.has(attrName)) {
this._modifiedAttributes.delete(attrName);
- if (!this._removedAttributes)
+ }
+ if (!this._removedAttributes) {
this._removedAttributes = /** @type {!Set.<string>} */ (new Set());
+ }
this._removedAttributes.add(attrName);
}
@@ -1576,12 +1702,13 @@ Elements.ElementsTreeOutline.Renderer = class {
* @param {function(!Error)} reject
*/
function renderPromise(resolve, reject) {
- if (object instanceof SDK.DOMNode)
+ if (object instanceof SDK.DOMNode) {
onNodeResolved(/** @type {!SDK.DOMNode} */ (object));
- else if (object instanceof SDK.DeferredDOMNode)
+ } else if (object instanceof SDK.DeferredDOMNode) {
(/** @type {!SDK.DeferredDOMNode} */ (object)).resolve(onNodeResolved);
- else
+ } else {
reject(new Error('Can\'t reveal not a node.'));
+ }
/**
@@ -1594,8 +1721,9 @@ Elements.ElementsTreeOutline.Renderer = class {
}
const treeOutline = new Elements.ElementsTreeOutline(false, true /* selectEnabled */, true /* hideGutter */);
treeOutline.rootDOMNode = node;
- if (!treeOutline.firstChild().isExpandable())
+ if (!treeOutline.firstChild().isExpandable()) {
treeOutline._element.classList.add('single-node');
+ }
treeOutline.setVisible(true);
treeOutline.element.treeElementForTest = treeOutline.firstChild();
treeOutline.setShowSelectionOnKeyboardFocus(true, true);
@@ -1617,8 +1745,9 @@ Elements.ElementsTreeOutline.ShortcutTreeElement = class extends UI.TreeElement
this.listItemElement.createChild('div', 'selection fill');
const title = this.listItemElement.createChild('span', 'elements-tree-shortcut-title');
let text = nodeShortcut.nodeName.toLowerCase();
- if (nodeShortcut.nodeType === Node.ELEMENT_NODE)
+ if (nodeShortcut.nodeType === Node.ELEMENT_NODE) {
text = '<' + text + '>';
+ }
title.textContent = '\u21AA ' + text;
const link = Elements.DOMLinkifier.linkifyDeferredNodeReference(nodeShortcut.deferredNode);
@@ -1640,8 +1769,9 @@ Elements.ElementsTreeOutline.ShortcutTreeElement = class extends UI.TreeElement
* @param {boolean} x
*/
set hovered(x) {
- if (this._hovered === x)
+ if (this._hovered === x) {
return;
+ }
this._hovered = x;
this.listItemElement.classList.toggle('hovered', x);
}
@@ -1666,8 +1796,9 @@ Elements.ElementsTreeOutline.ShortcutTreeElement = class extends UI.TreeElement
* @return {boolean}
*/
onselect(selectedByUser) {
- if (!selectedByUser)
+ if (!selectedByUser) {
return true;
+ }
this._nodeShortcut.deferredNode.highlight();
this._nodeShortcut.deferredNode.resolve(resolved.bind(this));
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/EventListenersWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/EventListenersWidget.js
index 921080746a2..2f897dd0ea3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/EventListenersWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/EventListenersWidget.js
@@ -54,8 +54,8 @@ Elements.EventListenersWidget = class extends UI.ThrottledWidget {
this._toolbarItems.push(new UI.ToolbarSettingCheckbox(
this._showForAncestorsSetting, Common.UIString('Show listeners on the ancestors'),
Common.UIString('Ancestors')));
- const dispatchFilter = new UI.ToolbarComboBox(this._onDispatchFilterTypeChanged.bind(this));
- dispatchFilter.setTitle(ls`Event listeners category`);
+ const dispatchFilter =
+ new UI.ToolbarComboBox(this._onDispatchFilterTypeChanged.bind(this), ls`Event listeners category`);
/**
* @param {string} name
@@ -63,9 +63,10 @@ Elements.EventListenersWidget = class extends UI.ThrottledWidget {
* @this {Elements.EventListenersWidget}
*/
function addDispatchFilterOption(name, value) {
- const option = dispatchFilter.createOption(name, '', value);
- if (value === this._dispatchFilterBySetting.get())
+ const option = dispatchFilter.createOption(name, value);
+ if (value === this._dispatchFilterBySetting.get()) {
dispatchFilter.select(option);
+ }
}
addDispatchFilterOption.call(this, Common.UIString('All'), Elements.EventListenersWidget.DispatchFilterBy.All);
addDispatchFilterOption.call(
@@ -150,8 +151,9 @@ Elements.EventListenersWidget = class extends UI.ThrottledWidget {
if (node.frameId()) {
for (let i = 0; i < executionContexts.length; ++i) {
const executionContext = executionContexts[i];
- if (executionContext.frameId === node.frameId() && executionContext.isDefault)
+ if (executionContext.frameId === node.frameId() && executionContext.isDefault) {
context = executionContext;
+ }
}
} else {
context = executionContexts[0];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/InspectElementModeController.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/InspectElementModeController.js
index 58fe9c5300d..900c89d5853 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/InspectElementModeController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/InspectElementModeController.js
@@ -47,10 +47,12 @@ Elements.InspectElementModeController = class {
this._showDetailedInspectTooltipSetting.addChangeListener(this._showDetailedInspectTooltipChanged.bind(this));
document.addEventListener('keydown', event => {
- if (event.keyCode !== UI.KeyboardShortcut.Keys.Esc.code)
+ if (event.keyCode !== UI.KeyboardShortcut.Keys.Esc.code) {
return;
- if (!this._isInInspectElementMode())
+ }
+ if (!this._isInInspectElementMode()) {
return;
+ }
this._setMode(Protocol.Overlay.InspectMode.None);
event.consume(true);
}, true);
@@ -63,8 +65,9 @@ Elements.InspectElementModeController = class {
modelAdded(overlayModel) {
// When DevTools are opening in the inspect element mode, the first target comes in
// much later than the InspectorFrontendAPI.enterInspectElementMode event.
- if (this._mode === Protocol.Overlay.InspectMode.None)
+ if (this._mode === Protocol.Overlay.InspectMode.None) {
return;
+ }
overlayModel.setInspectMode(this._mode, this._showDetailedInspectTooltipSetting.get());
}
@@ -101,17 +104,20 @@ Elements.InspectElementModeController = class {
* @param {!Protocol.Overlay.InspectMode} mode
*/
_setMode(mode) {
- if (SDK.targetManager.allTargetsSuspended())
+ if (SDK.targetManager.allTargetsSuspended()) {
return;
+ }
this._mode = mode;
- for (const overlayModel of SDK.targetManager.models(SDK.OverlayModel))
+ for (const overlayModel of SDK.targetManager.models(SDK.OverlayModel)) {
overlayModel.setInspectMode(mode, this._showDetailedInspectTooltipSetting.get());
+ }
this._toggleSearchAction.setToggled(this._isInInspectElementMode());
}
_suspendStateChanged() {
- if (!SDK.targetManager.allTargetsSuspended())
+ if (!SDK.targetManager.allTargetsSuspended()) {
return;
+ }
this._mode = Protocol.Overlay.InspectMode.None;
this._toggleSearchAction.setToggled(false);
@@ -141,16 +147,18 @@ Elements.InspectElementModeController.ToggleSearchActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- if (!Elements.inspectElementModeController)
+ if (!Elements.inspectElementModeController) {
return false;
- if (actionId === 'elements.toggle-element-search')
+ }
+ if (actionId === 'elements.toggle-element-search') {
Elements.inspectElementModeController._toggleInspectMode();
- else if (actionId === 'elements.capture-area-screenshot')
+ } else if (actionId === 'elements.capture-area-screenshot') {
Elements.inspectElementModeController._captureScreenshotMode();
+ }
return true;
}
};
/** @type {?Elements.InspectElementModeController} */
Elements.inspectElementModeController =
- Runtime.queryParam('isSharedWorker') ? null : new Elements.InspectElementModeController();
+ Root.Runtime.queryParam('isSharedWorker') ? null : new Elements.InspectElementModeController();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/MarkerDecorator.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/MarkerDecorator.js
index 1b67e5d503a..a39c9c7dab0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/MarkerDecorator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/MarkerDecorator.js
@@ -21,7 +21,7 @@ Elements.MarkerDecorator.prototype = {
*/
Elements.GenericDecorator = class {
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
constructor(extension) {
this._title = Common.UIString(extension.title());
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/MetricsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/MetricsSidebarPane.js
index 0b7eb871dc5..e6a08e0c8ac 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/MetricsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/MetricsSidebarPane.js
@@ -46,8 +46,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
doUpdate() {
// "style" attribute might have changed. Update metrics unless they are being edited
// (if a CSS property is added, a StyleSheetChanged event is dispatched).
- if (this._isEditingMetrics)
+ if (this._isEditingMetrics) {
return Promise.resolve();
+ }
// FIXME: avoid updates of a collapsed pane.
const node = this.node();
@@ -62,8 +63,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
* @this {Elements.MetricsSidebarPane}
*/
function callback(style) {
- if (!style || this.node() !== node)
+ if (!style || this.node() !== node) {
return;
+ }
this._updateMetrics(style);
}
/**
@@ -71,8 +73,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
* @this {Elements.MetricsSidebarPane}
*/
function inlineStyleCallback(inlineStyleResult) {
- if (inlineStyleResult && this.node() === node)
+ if (inlineStyleResult && this.node() === node) {
this._inlineStyle = inlineStyleResult.inlineStyle;
+ }
}
const promises = [
@@ -119,8 +122,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
_highlightDOMNode(showHighlight, mode, event) {
event.consume();
if (showHighlight && this.node()) {
- if (this._highlightMode === mode)
+ if (this._highlightMode === mode) {
return;
+ }
this._highlightMode = mode;
this.node().highlight(mode);
} else {
@@ -130,10 +134,11 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
for (let i = 0; this._boxElements && i < this._boxElements.length; ++i) {
const element = this._boxElements[i];
- if (!this.node() || mode === 'all' || element._name === mode)
+ if (!this.node() || mode === 'all' || element._name === mode) {
element.style.backgroundColor = element._backgroundColor;
- else
+ } else {
element.style.backgroundColor = '';
+ }
}
}
@@ -156,10 +161,11 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
function createBoxPartElement(style, name, side, suffix) {
const propertyName = (name !== 'position' ? name + '-' : '') + side + suffix;
let value = style.get(propertyName);
- if (value === '' || (name !== 'position' && value === '0px'))
+ if (value === '' || (name !== 'position' && value === '0px')) {
value = '\u2012';
- else if (name === 'position' && value === 'auto')
+ } else if (name === 'position' && value === 'auto') {
value = '\u2012';
+ }
value = value.replace(/px$/, '');
value = Number.toFixedIfFloating(value);
@@ -240,12 +246,15 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
for (let i = 0; i < boxes.length; ++i) {
const name = boxes[i];
- if (name === 'margin' && noMarginDisplayType[style.get('display')])
+ if (name === 'margin' && noMarginDisplayType[style.get('display')]) {
continue;
- if (name === 'padding' && noPaddingDisplayType[style.get('display')])
+ }
+ if (name === 'padding' && noPaddingDisplayType[style.get('display')]) {
continue;
- if (name === 'position' && noPositionType[style.get('position')])
+ }
+ if (name === 'position' && noPositionType[style.get('position')]) {
continue;
+ }
const boxElement = createElement('div');
boxElement.className = name;
@@ -282,8 +291,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
boxElement.appendChild(createElement('br'));
boxElement.appendChild(createBoxPartElement.call(this, style, name, 'left', suffix));
- if (previousBox)
+ if (previousBox) {
boxElement.appendChild(previousBox);
+ }
boxElement.appendChild(createBoxPartElement.call(this, style, name, 'right', suffix));
boxElement.appendChild(createElement('br'));
@@ -309,8 +319,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {!Map.<string, string>} computedStyle
*/
startEditing(targetElement, box, styleProperty, computedStyle) {
- if (UI.isBeingEdited(targetElement))
+ if (UI.isBeingEdited(targetElement)) {
return;
+ }
const context = {box: box, styleProperty: styleProperty, computedStyle: computedStyle};
const boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty);
@@ -345,8 +356,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
* @return {string}
*/
function customNumberHandler(prefix, number, suffix) {
- if (styleProperty !== 'margin' && number < 0)
+ if (styleProperty !== 'margin' && number < 0) {
number = 0;
+ }
return prefix + number + suffix;
}
@@ -365,8 +377,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
if (!this.originalPropertyData) {
// An added property, remove the last property in the style.
const pastLastSourcePropertyIndex = this._inlineStyle.pastLastSourcePropertyIndex();
- if (pastLastSourcePropertyIndex)
+ if (pastLastSourcePropertyIndex) {
this._inlineStyle.allProperties()[pastLastSourcePropertyIndex - 1].setText('', false);
+ }
} else {
this._inlineStyle.allProperties()[this.originalPropertyData.index].setText(
this.originalPropertyData.propertyText, false);
@@ -382,18 +395,21 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
return this.editingCancelled(element, context); // nothing changed, so cancel
}
- if (commitEditor && userInput === previousContent)
- return this.editingCancelled(element, context); // nothing changed, so cancel
+ if (commitEditor && userInput === previousContent) {
+ return this.editingCancelled(element, context);
+ } // nothing changed, so cancel
- if (context.box !== 'position' && (!userInput || userInput === '\u2012'))
+ if (context.box !== 'position' && (!userInput || userInput === '\u2012')) {
userInput = '0px';
- else if (context.box === 'position' && (!userInput || userInput === '\u2012'))
+ } else if (context.box === 'position' && (!userInput || userInput === '\u2012')) {
userInput = 'auto';
+ }
userInput = userInput.toLowerCase();
// Append a "px" unit if the user input was just a number.
- if (/^\d+$/.test(userInput))
+ if (/^\d+$/.test(userInput)) {
userInput += 'px';
+ }
const styleProperty = context.styleProperty;
const computedStyle = context.computedStyle;
@@ -408,12 +424,14 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
const borderBox = this._getBox(computedStyle, 'border');
const paddingBox = this._getBox(computedStyle, 'padding');
let userValuePx = Number(userInput.replace(/px$/, ''));
- if (isNaN(userValuePx))
+ if (isNaN(userValuePx)) {
return;
- if (styleProperty === 'width')
+ }
+ if (styleProperty === 'width') {
userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right;
- else
+ } else {
userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;
+ }
userInput = userValuePx + 'px';
}
@@ -423,8 +441,9 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
const allProperties = this._inlineStyle.allProperties();
for (let i = 0; i < allProperties.length; ++i) {
const property = allProperties[i];
- if (property.name !== context.styleProperty || !property.activeInStyle())
+ if (property.name !== context.styleProperty || !property.activeInStyle()) {
continue;
+ }
this.previousPropertyDataCandidate = property;
property.setValue(userInput, commitEditor, true, callback.bind(this));
@@ -438,16 +457,20 @@ Elements.MetricsSidebarPane = class extends Elements.ElementsSidebarPane {
* @this {Elements.MetricsSidebarPane}
*/
function callback(success) {
- if (!success)
+ if (!success) {
return;
- if (!('originalPropertyData' in this))
+ }
+ if (!('originalPropertyData' in this)) {
this.originalPropertyData = this.previousPropertyDataCandidate;
+ }
- if (typeof this._highlightMode !== 'undefined')
+ if (typeof this._highlightMode !== 'undefined') {
this.node().highlight(this._highlightMode);
+ }
- if (commitEditor)
+ if (commitEditor) {
this.update();
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/PlatformFontsWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/PlatformFontsWidget.js
index 3bec7d9c058..78ffdc0f335 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/PlatformFontsWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/PlatformFontsWidget.js
@@ -57,8 +57,9 @@ Elements.PlatformFontsWidget = class extends UI.ThrottledWidget {
doUpdate() {
const cssModel = this._sharedModel.cssModel();
const node = this._sharedModel.node();
- if (!node || !cssModel)
+ if (!node || !cssModel) {
return Promise.resolve();
+ }
return cssModel.platformFontsPromise(node.id).then(this._refreshUI.bind(this, node));
}
@@ -68,15 +69,17 @@ Elements.PlatformFontsWidget = class extends UI.ThrottledWidget {
* @param {?Array.<!Protocol.CSS.PlatformFontUsage>} platformFonts
*/
_refreshUI(node, platformFonts) {
- if (this._sharedModel.node() !== node)
+ if (this._sharedModel.node() !== node) {
return;
+ }
this._fontStatsSection.removeChildren();
const isEmptySection = !platformFonts || !platformFonts.length;
this._sectionTitle.classList.toggle('hidden', isEmptySection);
- if (isEmptySection)
+ if (isEmptySection) {
return;
+ }
platformFonts.sort(function(a, b) {
return b.glyphCount - a.glyphCount;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
index 199c94ca011..186227f13d3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
@@ -43,6 +43,16 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
SDK.DOMModel, SDK.DOMModel.Events.ChildNodeCountUpdated, this._onNodeChange, this);
UI.context.addFlavorChangeListener(SDK.DOMNode, this._setNode, this);
this._node = UI.context.flavor(SDK.DOMNode);
+
+ this._treeOutline = new ObjectUI.ObjectPropertiesSectionsTreeOutline({readOnly: true});
+ this._treeOutline.setShowSelectionOnKeyboardFocus(/* show */ true, /* preventTabOrder */ false);
+ this._expandController = new ObjectUI.ObjectPropertiesSectionsTreeExpandController(this._treeOutline);
+ this.contentElement.appendChild(this._treeOutline.element);
+
+ this._treeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, () => {
+ Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
+ });
+
this.update();
}
@@ -67,50 +77,48 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
if (!this._node) {
this.contentElement.removeChildren();
- this.sections = [];
return;
}
this._lastRequestedNode = this._node;
const object = await this._node.resolveToObject(Elements.PropertiesWidget._objectGroupName);
- if (!object)
+ if (!object) {
return;
+ }
const result = await object.callFunction(protoList);
object.release();
- if (!result.object || result.wasThrown)
+ if (!result.object || result.wasThrown) {
return;
+ }
const propertiesResult = await result.object.getOwnProperties(false /* generatePreview */);
result.object.release();
- if (!propertiesResult || !propertiesResult.properties)
+ if (!propertiesResult || !propertiesResult.properties) {
return;
+ }
const properties = propertiesResult.properties;
- const expanded = [];
- const sections = this.sections || [];
- for (let i = 0; i < sections.length; ++i)
- expanded.push(sections[i].expanded);
-
- this.contentElement.removeChildren();
- this.sections = [];
+ this._treeOutline.removeChildren();
+ let selected = false;
// Get array of property user-friendly names.
for (let i = 0; i < properties.length; ++i) {
- if (!parseInt(properties[i].name, 10))
+ if (!parseInt(properties[i].name, 10)) {
continue;
+ }
const property = properties[i].value;
let title = property.description;
title = title.replace(/Prototype$/, '');
- const section = new ObjectUI.ObjectPropertiesSection(property, title);
- section.element.classList.add('properties-widget-section');
- this.sections.push(section);
- this.contentElement.appendChild(section.element);
- if (expanded[this.sections.length - 1])
- section.expand();
- section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
+
+ const section = this._createSectionTreeElement(property, title);
+ this._treeOutline.appendChild(section);
+ if (!selected) {
+ section.select(/* omitFocus= */ true, /* selectedByUser= */ false);
+ selected = true;
+ }
}
/**
@@ -130,24 +138,33 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
}
/**
- * @param {!Common.Event} event
+ * @param {!SDK.RemoteObject} property
+ * @param {string} title
+ * @returns {!ObjectUI.ObjectPropertiesSection.RootElement}
*/
- _propertyExpanded(event) {
- Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
- for (const section of this.sections)
- section.removeEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
+ _createSectionTreeElement(property, title) {
+ const titleElement = createElementWithClass('span', 'tree-element-title');
+ titleElement.textContent = title;
+
+ const section = new ObjectUI.ObjectPropertiesSection.RootElement(property);
+ section.title = titleElement;
+ this._expandController.watchSection(title, section);
+
+ return section;
}
/**
* @param {!Common.Event} event
*/
_onNodeChange(event) {
- if (!this._node)
+ if (!this._node) {
return;
+ }
const data = event.data;
const node = /** @type {!SDK.DOMNode} */ (data instanceof SDK.DOMNode ? data : data.node);
- if (this._node !== node)
+ if (this._node !== node) {
return;
+ }
this.update();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyHighlighter.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyHighlighter.js
index 17839b420d5..91092f64560 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyHighlighter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyHighlighter.js
@@ -19,8 +19,9 @@ Elements.StylePropertyHighlighter = class {
// Expand all shorthands.
for (const section of this._styleSidebarPane.allSections()) {
for (let treeElement = section.propertiesTreeOutline.firstChild(); treeElement;
- treeElement = treeElement.nextSibling)
+ treeElement = treeElement.nextSibling) {
treeElement.onpopulate();
+ }
}
let highlightTreeElement = null;
for (const section of this._styleSidebarPane.allSections()) {
@@ -32,12 +33,14 @@ Elements.StylePropertyHighlighter = class {
}
treeElement = treeElement.traverseNextTreeElement(false, null, true);
}
- if (highlightTreeElement)
+ if (highlightTreeElement) {
break;
+ }
}
- if (!highlightTreeElement)
+ if (!highlightTreeElement) {
return;
+ }
highlightTreeElement.parent.expand();
highlightTreeElement.listItemElement.scrollIntoViewIfNeeded();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
index 8167ff6a0a4..e9f521fdfa4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylePropertyTreeElement.js
@@ -25,8 +25,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this.isShorthand = isShorthand;
this._applyStyleThrottler = new Common.Throttler(0);
this._newProperty = newProperty;
- if (this._newProperty)
+ if (this._newProperty) {
this.listItemElement.textContent = '';
+ }
this._expandedDueToFilter = false;
this.valueElement = null;
this.nameElement = null;
@@ -71,8 +72,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @param {boolean} x
*/
setOverloaded(x) {
- if (x === this._overloaded)
+ if (x === this._overloaded) {
return;
+ }
this._overloaded = x;
this._updateState();
}
@@ -95,12 +97,14 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this.onpopulate();
let hasMatchingChildren = false;
- for (let i = 0; i < this.childCount(); ++i)
+ for (let i = 0; i < this.childCount(); ++i) {
hasMatchingChildren |= this.childAt(i)._updateFilter();
+ }
if (!regex) {
- if (this._expandedDueToFilter)
+ if (this._expandedDueToFilter) {
this.collapse();
+ }
this._expandedDueToFilter = false;
} else if (hasMatchingChildren && !this.expanded) {
this.expand();
@@ -119,8 +123,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
_processColor(text) {
// We can be called with valid non-color values of |text| (like 'none' from border style)
const color = Common.Color.parse(text);
- if (!color)
+ if (!color) {
return createTextNode(text);
+ }
if (!this._editable()) {
const swatch = InlineEditor.ColorSwatch.create();
@@ -142,8 +147,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
_processVar(text) {
const computedValue = this._matchedStyles.computeValue(this._style, text);
- if (!computedValue)
+ if (!computedValue) {
return createTextNode(text);
+ }
const color = Common.Color.parse(computedValue);
if (!color) {
const node = createElement('span');
@@ -172,8 +178,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
async _addColorContrastInfo(swatch) {
const swatchPopoverHelper = this._parentPane.swatchPopoverHelper();
const swatchIcon = new Elements.ColorSwatchPopoverIcon(this, swatchPopoverHelper, swatch);
- if (this.property.name !== 'color' || !this._parentPane.cssModel() || !this.node())
+ if (this.property.name !== 'color' || !this._parentPane.cssModel() || !this.node()) {
return;
+ }
const cssModel = this._parentPane.cssModel();
const contrastInfo = new ColorPicker.ContrastInfo(await cssModel.backgroundColorsPromise(this.node().id));
swatchIcon.setContrastInfo(contrastInfo);
@@ -191,8 +198,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @return {!Node}
*/
_processBezier(text) {
- if (!this._editable() || !UI.Geometry.CubicBezier.parse(text))
+ if (!this._editable() || !UI.Geometry.CubicBezier.parse(text)) {
return createTextNode(text);
+ }
const swatchPopoverHelper = this._parentPane.swatchPopoverHelper();
const swatch = InlineEditor.BezierSwatch.create();
swatch.setBezierText(text);
@@ -206,27 +214,32 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @return {!Node}
*/
_processShadow(propertyValue, propertyName) {
- if (!this._editable())
+ if (!this._editable()) {
return createTextNode(propertyValue);
+ }
let shadows;
- if (propertyName === 'text-shadow')
+ if (propertyName === 'text-shadow') {
shadows = InlineEditor.CSSShadowModel.parseTextShadow(propertyValue);
- else
+ } else {
shadows = InlineEditor.CSSShadowModel.parseBoxShadow(propertyValue);
- if (!shadows.length)
+ }
+ if (!shadows.length) {
return createTextNode(propertyValue);
+ }
const container = createDocumentFragment();
const swatchPopoverHelper = this._parentPane.swatchPopoverHelper();
for (let i = 0; i < shadows.length; i++) {
- if (i !== 0)
- container.appendChild(createTextNode(', ')); // Add back commas and spaces between each shadow.
+ if (i !== 0) {
+ container.appendChild(createTextNode(', '));
+ } // Add back commas and spaces between each shadow.
// TODO(flandy): editing the property value should use the original value with all spaces.
const cssShadowSwatch = InlineEditor.CSSShadowSwatch.create();
cssShadowSwatch.setCSSShadow(shadows[i]);
new Elements.ShadowSwatchPopoverHelper(this, swatchPopoverHelper, cssShadowSwatch);
const colorSwatch = cssShadowSwatch.colorSwatch();
- if (colorSwatch)
+ if (colorSwatch) {
new Elements.ColorSwatchPopoverIcon(this, swatchPopoverHelper, colorSwatch);
+ }
container.appendChild(cssShadowSwatch);
}
return container;
@@ -239,8 +252,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
_processGrid(propertyValue, propertyName) {
const splitResult = TextUtils.TextUtils.splitStringByRegexes(propertyValue, [SDK.CSSMetadata.GridAreaRowRegex]);
- if (splitResult.length <= 1)
+ if (splitResult.length <= 1) {
return createTextNode(propertyValue);
+ }
const indent = Common.moduleSetting('textEditorIndent').get();
const container = createDocumentFragment();
@@ -253,35 +267,41 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
}
_updateState() {
- if (!this.listItemElement)
+ if (!this.listItemElement) {
return;
+ }
- if (this._style.isPropertyImplicit(this.name))
+ if (this._style.isPropertyImplicit(this.name)) {
this.listItemElement.classList.add('implicit');
- else
+ } else {
this.listItemElement.classList.remove('implicit');
+ }
const hasIgnorableError =
!this.property.parsedOk && Elements.StylesSidebarPane.ignoreErrorsForProperty(this.property);
- if (hasIgnorableError)
+ if (hasIgnorableError) {
this.listItemElement.classList.add('has-ignorable-error');
- else
+ } else {
this.listItemElement.classList.remove('has-ignorable-error');
+ }
- if (this.inherited())
+ if (this.inherited()) {
this.listItemElement.classList.add('inherited');
- else
+ } else {
this.listItemElement.classList.remove('inherited');
+ }
- if (this.overloaded())
+ if (this.overloaded()) {
this.listItemElement.classList.add('overloaded');
- else
+ } else {
this.listItemElement.classList.remove('overloaded');
+ }
- if (this.property.disabled)
+ if (this.property.disabled) {
this.listItemElement.classList.add('disabled');
- else
+ } else {
this.listItemElement.classList.remove('disabled');
+ }
}
/**
@@ -307,8 +327,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
_updatePane() {
const section = this.section();
- if (section)
+ if (section) {
section.refreshUpdate(this);
+ }
}
/**
@@ -316,15 +337,17 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
async _toggleDisabled(disabled) {
const oldStyleRange = this._style.range;
- if (!oldStyleRange)
+ if (!oldStyleRange) {
return;
+ }
this._parentPane.setUserOperation(true);
const success = await this.property.setDisabled(disabled);
this._parentPane.setUserOperation(false);
- if (!success)
+ if (!success) {
return;
+ }
this._matchedStyles.resetActiveProperties();
this._updatePane();
this.styleTextAppliedForTest();
@@ -336,8 +359,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
async onpopulate() {
// Only populate once and if this property is a shorthand.
- if (this.childCount() || !this.isShorthand)
+ if (this.childCount() || !this.isShorthand) {
return;
+ }
const longhandProperties = this._style.longhandProperties(this.name);
for (let i = 0; i < longhandProperties.length; ++i) {
@@ -365,13 +389,15 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this.updateTitle();
this.listItemElement.addEventListener('mousedown', event => {
- if (event.which === 1)
+ if (event.which === 1) {
this._parentPane[Elements.StylePropertyTreeElement.ActiveSymbol] = this;
+ }
}, false);
this.listItemElement.addEventListener('mouseup', this._mouseUp.bind(this));
this.listItemElement.addEventListener('click', event => {
- if (!event.target.hasSelection() && event.target !== this.listItemElement)
+ if (!event.target.hasSelection() && event.target !== this.listItemElement) {
event.consume(true);
+ }
});
}
@@ -390,18 +416,21 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
}
_updateExpandElement() {
- if (!this._expandElement)
+ if (!this._expandElement) {
return;
- if (this.expanded)
+ }
+ if (this.expanded) {
this._expandElement.setIconType('smallicon-triangle-down');
- else
+ } else {
this._expandElement.setIconType('smallicon-triangle-right');
+ }
}
updateTitleIfComputedValueChanged() {
const computedValue = this._matchedStyles.computeValue(this.property.ownerStyle, this.property.value);
- if (computedValue === this._lastComputedValue)
+ if (computedValue === this._lastComputedValue) {
return;
+ }
this._lastComputedValue = computedValue;
this._innerUpdateTitle();
}
@@ -413,10 +442,11 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
_innerUpdateTitle() {
this._updateState();
- if (this.isExpandable())
+ if (this.isExpandable()) {
this._expandElement = UI.Icon.create('smallicon-triangle-right', 'expand-icon');
- else
+ } else {
this._expandElement = null;
+ }
const propertyRenderer =
new Elements.StylesSidebarPropertyRenderer(this._style.parentRule, this.node(), this.name, this.value);
@@ -430,11 +460,13 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this.listItemElement.removeChildren();
this.nameElement = propertyRenderer.renderName();
- if (this.property.name.startsWith('--'))
+ if (this.property.name.startsWith('--')) {
this.nameElement.title = this._matchedStyles.computeCSSVariable(this._style, this.property.name) || '';
+ }
this.valueElement = propertyRenderer.renderValue();
- if (!this.treeOutline)
+ if (!this.treeOutline) {
return;
+ }
const indent = Common.moduleSetting('textEditorIndent').get();
this.listItemElement.createChild('span', 'styles-clipboard-only')
@@ -443,12 +475,14 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
const lineBreakValue = this.valueElement.firstElementChild && this.valueElement.firstElementChild.tagName === 'BR';
const separator = lineBreakValue ? ':' : ': ';
this.listItemElement.createChild('span', 'styles-name-value-separator').textContent = separator;
- if (this._expandElement)
+ if (this._expandElement) {
this.listItemElement.appendChild(this._expandElement);
+ }
this.listItemElement.appendChild(this.valueElement);
this.listItemElement.createTextChild(';');
- if (this.property.disabled)
+ if (this.property.disabled) {
this.listItemElement.createChild('span', 'styles-clipboard-only').createTextChild(' */');
+ }
if (!this.property.parsedOk) {
// Avoid having longhands under an invalid shorthand.
@@ -458,8 +492,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this.listItemElement.insertBefore(
Elements.StylesSidebarPane.createExclamationMark(this.property), this.listItemElement.firstChild);
}
- if (!this.property.activeInStyle())
+ if (!this.property.activeInStyle()) {
this.listItemElement.classList.add('inactive');
+ }
this._updateFilter();
if (this.property.parsedOk && this.section() && this.parent.root) {
@@ -484,17 +519,21 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
_mouseUp(event) {
const activeTreeElement = this._parentPane[Elements.StylePropertyTreeElement.ActiveSymbol];
this._parentPane[Elements.StylePropertyTreeElement.ActiveSymbol] = null;
- if (activeTreeElement !== this)
+ if (activeTreeElement !== this) {
return;
- if (this.listItemElement.hasSelection())
+ }
+ if (this.listItemElement.hasSelection()) {
return;
- if (UI.isBeingEdited(/** @type {!Node} */ (event.target)))
+ }
+ if (UI.isBeingEdited(/** @type {!Node} */ (event.target))) {
return;
+ }
event.consume(true);
- if (event.target === this.listItemElement)
+ if (event.target === this.listItemElement) {
return;
+ }
if (UI.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */ (event)) && this.section().navigable) {
this._navigateToSource(/** @type {!Element} */ (event.target));
@@ -529,12 +568,14 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @param {boolean=} omitFocus
*/
_navigateToSource(element, omitFocus) {
- if (!this.section().navigable)
+ if (!this.section().navigable) {
return;
+ }
const propertyNameClicked = element === this.nameElement;
const uiLocation = Bindings.cssWorkspaceBinding.propertyUILocation(this.property, propertyNameClicked);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation, omitFocus);
+ }
}
/**
@@ -542,30 +583,36 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
startEditing(selectElement) {
// FIXME: we don't allow editing of longhand properties under a shorthand right now.
- if (this.parent.isShorthand)
+ if (this.parent.isShorthand) {
return;
+ }
- if (this._expandElement && selectElement === this._expandElement)
+ if (this._expandElement && selectElement === this._expandElement) {
return;
+ }
const section = this.section();
- if (section && !section.editable)
+ if (section && !section.editable) {
return;
+ }
if (selectElement) {
selectElement = selectElement.enclosingNodeOrSelfWithClass('webkit-css-property') ||
selectElement.enclosingNodeOrSelfWithClass('value');
}
- if (!selectElement)
+ if (!selectElement) {
selectElement = this.nameElement;
+ }
- if (UI.isBeingEdited(selectElement))
+ if (UI.isBeingEdited(selectElement)) {
return;
+ }
const isEditingName = selectElement === this.nameElement;
if (!isEditingName) {
- if (SDK.cssMetadata().isGridAreaDefiningProperty(this.name))
+ if (SDK.cssMetadata().isGridAreaDefiningProperty(this.name)) {
this.valueElement.textContent = restoreGridIndents(this.value);
+ }
this.valueElement.textContent = restoreURLs(this.valueElement.textContent, this.value);
}
@@ -585,13 +632,15 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
function restoreURLs(fieldValue, modelValue) {
const urlRegex = /\b(url\([^)]*\))/g;
const splitFieldValue = fieldValue.split(urlRegex);
- if (splitFieldValue.length === 1)
+ if (splitFieldValue.length === 1) {
return fieldValue;
+ }
const modelUrlRegex = new RegExp(urlRegex);
for (let i = 1; i < splitFieldValue.length; i += 2) {
const match = modelUrlRegex.exec(modelValue);
- if (match)
+ if (match) {
splitFieldValue[i] = match[0];
+ }
}
return splitFieldValue.join('');
}
@@ -609,8 +658,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
// Lie about our children to prevent expanding on double click and to collapse shorthands.
this.setExpandable(false);
- if (selectElement.parentElement)
+ if (selectElement.parentElement) {
selectElement.parentElement.classList.add('child-editing');
+ }
selectElement.textContent = selectElement.textContent; // remove color swatch and the like
/**
@@ -620,11 +670,13 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
function pasteHandler(context, event) {
const data = event.clipboardData.getData('Text');
- if (!data)
+ if (!data) {
return;
+ }
const colonIdx = data.indexOf(':');
- if (colonIdx < 0)
+ if (colonIdx < 0) {
return;
+ }
const name = data.substring(0, colonIdx).trim();
const value = data.substring(colonIdx + 1).trim();
@@ -651,16 +703,18 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
function blurListener(context, event) {
let text = event.target.textContent;
- if (!context.isEditingName)
+ if (!context.isEditingName) {
text = this.value || text;
+ }
this._editingCommitted(text, context, '');
}
this._originalPropertyText = this.property.propertyText;
this._parentPane.setEditingStyle(true, this);
- if (selectElement.parentElement)
+ if (selectElement.parentElement) {
selectElement.parentElement.scrollIntoViewIfNeeded(false);
+ }
this._prompt = new Elements.StylesSidebarPane.CSSPropertyPrompt(this, isEditingName);
this._prompt.setAutocompletionTimeout(0);
@@ -685,8 +739,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_editingNameValueKeyDown(context, event) {
- if (event.handled)
+ if (event.handled) {
return;
+ }
let result;
@@ -738,12 +793,14 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
let openQuote = '';
for (let i = 0; i < cursorPosition; ++i) {
const ch = text[i];
- if (ch === '\\' && openQuote !== '')
- ++i; // skip next character inside string
- else if (!openQuote && (ch === '"' || ch === '\''))
+ if (ch === '\\' && openQuote !== '') {
+ ++i;
+ } // skip next character inside string
+ else if (!openQuote && (ch === '"' || ch === '\'')) {
openQuote = ch;
- else if (openQuote === ch)
+ } else if (openQuote === ch) {
openQuote = '';
+ }
}
return !openQuote;
}
@@ -766,8 +823,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @return {!Promise}
*/
async _applyFreeFlowStyleTextEdit(context) {
- if (!this._prompt || !this._parentPane.node())
+ if (!this._prompt || !this._parentPane.node()) {
return;
+ }
const enteredText = this._prompt.text();
if (context.isEditingName && enteredText.includes(':')) {
@@ -776,23 +834,27 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
}
const valueText = this._prompt.textWithCurrentSuggestion();
- if (valueText.includes(';'))
+ if (valueText.includes(';')) {
return;
+ }
// Prevent destructive side-effects during live-edit. crbug.com/433889
const isPseudo = !!this._parentPane.node().pseudoType();
if (isPseudo) {
- if (this.name.toLowerCase() === 'content')
+ if (this.name.toLowerCase() === 'content') {
return;
+ }
const lowerValueText = valueText.trim().toLowerCase();
- if (lowerValueText.startsWith('content:') || lowerValueText === 'display: none')
+ if (lowerValueText.startsWith('content:') || lowerValueText === 'display: none') {
return;
+ }
}
if (context.isEditingName) {
- if (valueText.includes(':'))
+ if (valueText.includes(':')) {
await this.applyStyleText(valueText, false);
- else if (this._hasBeenEditedIncrementally)
+ } else if (this._hasBeenEditedIncrementally) {
await this._applyOriginalStyle(context);
+ }
} else {
await this.applyStyleText(`${this.nameElement.textContent}: ${valueText}`, false);
}
@@ -811,12 +873,14 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
editingEnded(context) {
this.setExpandable(context.hasChildren);
- if (context.expanded)
+ if (context.expanded) {
this.expand();
+ }
const editedElement = context.isEditingName ? this.nameElement : this.valueElement;
// The proxyElement has been deleted, no need to remove listener.
- if (editedElement.parentElement)
+ if (editedElement.parentElement) {
editedElement.parentElement.classList.remove('child-editing');
+ }
this._parentPane.setEditingStyle(false);
}
@@ -828,10 +892,11 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
editingCancelled(element, context) {
this._removePrompt();
- if (this._hasBeenEditedIncrementally)
+ if (this._hasBeenEditedIncrementally) {
this._applyOriginalStyle(context);
- else if (this._newProperty)
+ } else if (this._newProperty) {
this.treeOutline.removeChild(this);
+ }
this.updateTitle();
// This should happen last, as it clears the info necessary to restore the property value after [Page]Up/Down changes.
@@ -851,9 +916,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
*/
_findSibling(moveDirection) {
let target = this;
- do
+ do {
target = (moveDirection === 'forward' ? target.nextSibling : target.previousSibling);
- while (target && target.inherited());
+ } while (target && target.inherited());
return target;
}
@@ -884,10 +949,11 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
moveDirection === 'backward' && isEditingName) {
moveTo = moveTo._findSibling(moveDirection);
if (!moveTo) {
- if (moveDirection === 'forward' && (!this._newProperty || userInput))
+ if (moveDirection === 'forward' && (!this._newProperty || userInput)) {
createNewProperty = true;
- else if (moveDirection === 'backward')
+ } else if (moveDirection === 'backward') {
moveToSelector = true;
+ }
}
}
@@ -905,20 +971,23 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
} else if (blankInput || (this._newProperty && this.valueElement.textContent.isWhitespace())) {
propertyText = '';
} else {
- if (isEditingName)
+ if (isEditingName) {
propertyText = userInput + ': ' + this.property.value;
- else
+ } else {
propertyText = this.property.name + ': ' + userInput;
+ }
}
await this.applyStyleText(propertyText, true);
moveToNextCallback.call(this, this._newProperty, !blankInput, section);
} else {
- if (isEditingName)
+ if (isEditingName) {
this.property.name = userInput;
- else
+ } else {
this.property.value = userInput;
- if (!isDataPasted && !this._newProperty)
+ }
+ if (!isDataPasted && !this._newProperty) {
this.updateTitle();
+ }
moveToNextCallback.call(this, this._newProperty, false, section);
}
@@ -930,8 +999,10 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @this {Elements.StylePropertyTreeElement}
*/
function moveToNextCallback(alreadyNew, valueChanged, section) {
- if (!moveDirection)
+ if (!moveDirection) {
+ this._parentPane.resetFocus();
return;
+ }
// User just tabbed through without changes.
if (moveTo && moveTo.parent) {
@@ -943,8 +1014,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
// Recalculate the new treeElement for the same property we were going to edit next.
if (moveTo && !moveTo.parent) {
const rootElement = section.propertiesTreeOutline.rootElement();
- if (moveDirection === 'forward' && blankInput && !isEditingName)
+ if (moveDirection === 'forward' && blankInput && !isEditingName) {
--moveToIndex;
+ }
if (moveToIndex >= rootElement.childCount() && !this._newProperty) {
createNewProperty = true;
} else {
@@ -952,8 +1024,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
if (treeElement) {
let elementToEdit =
!isEditingName || isPropertySplitPaste ? treeElement.nameElement : treeElement.valueElement;
- if (alreadyNew && blankInput)
+ if (alreadyNew && blankInput) {
elementToEdit = moveDirection === 'forward' ? treeElement.nameElement : treeElement.valueElement;
+ }
treeElement.startEditing(elementToEdit);
return;
} else if (!alreadyNew) {
@@ -964,8 +1037,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
// Create a new attribute in this section (or move to next editable selector if possible).
if (createNewProperty) {
- if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === 'backward')))
+ if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === 'backward'))) {
return;
+ }
section.addNewBlankProperty().startEditing();
return;
@@ -975,19 +1049,21 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
moveTo = this._findSibling(moveDirection);
const sectionToEdit = (moveTo || moveDirection === 'backward') ? section : section.nextEditableSibling();
if (sectionToEdit) {
- if (sectionToEdit.style().parentRule)
+ if (sectionToEdit.style().parentRule) {
sectionToEdit.startEditingSelector();
- else
+ } else {
sectionToEdit.moveEditorFromSelector(moveDirection);
+ }
}
return;
}
if (moveToSelector) {
- if (section.style().parentRule)
+ if (section.style().parentRule) {
section.startEditingSelector();
- else
+ } else {
section.moveEditorFromSelector(moveDirection);
+ }
}
}
}
@@ -1020,15 +1096,17 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
* @return {!Promise}
*/
async _innerApplyStyleText(styleText, majorChange, property) {
- if (!this.treeOutline)
+ if (!this.treeOutline) {
return;
+ }
const oldStyleRange = this._style.range;
- if (!oldStyleRange)
+ if (!oldStyleRange) {
return;
+ }
const hasBeenEditedIncrementally = this._hasBeenEditedIncrementally;
- styleText = styleText.replace(/[\u00a0\t]/g, ' ').trim(); // Replace &nbsp; with whitespace.
+ styleText = styleText.replace(/[\xA0\t]/g, ' ').trim(); // Replace &nbsp; with whitespace.
if (!styleText.length && majorChange && this._newProperty && !hasBeenEditedIncrementally) {
// The user deleted everything and never applied a new property value via Up/Down scrolling/live editing, so remove the tree element and update.
this.parent.removeChild(this);
@@ -1040,8 +1118,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
// Append a ";" if the new text does not end in ";".
// FIXME: this does not handle trailing comments.
- if (styleText.length && !/;\s*$/.test(styleText))
+ if (styleText.length && !/;\s*$/.test(styleText)) {
styleText += ';';
+ }
const overwriteProperty = !this._newProperty || hasBeenEditedIncrementally;
let success = await this.property.setText(styleText, majorChange, overwriteProperty);
// Revert to the original text if applying the new text failed
@@ -1054,10 +1133,11 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
if (!success) {
if (majorChange) {
// It did not apply, cancel editing.
- if (this._newProperty)
+ if (this._newProperty) {
this.treeOutline.removeChild(this);
- else
+ } else {
this.updateTitle();
+ }
}
this.styleTextAppliedForTest();
return;
@@ -1067,8 +1147,9 @@ Elements.StylePropertyTreeElement = class extends UI.TreeElement {
this._hasBeenEditedIncrementally = true;
this.property = property || this._style.propertyAt(this.property.index);
- if (currentNode === this.node())
+ if (currentNode === this.node()) {
this._updatePane();
+ }
this.styleTextAppliedForTest();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index ff86ecbd2bf..4d294ef807d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -97,8 +97,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
static createExclamationMark(property) {
const exclamationElement = createElement('span', 'dt-icon-label');
exclamationElement.className = 'exclamation-mark';
- if (!Elements.StylesSidebarPane.ignoreErrorsForProperty(property))
+ if (!Elements.StylesSidebarPane.ignoreErrorsForProperty(property)) {
exclamationElement.type = 'smallicon-warning';
+ }
exclamationElement.title = SDK.cssMetadata().isCSSPropertyName(property.name) ?
Common.UIString('Invalid property value') :
Common.UIString('Unknown property name');
@@ -120,26 +121,32 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
const name = property.name.toLowerCase();
// IE hack.
- if (name.charAt(0) === '_')
+ if (name.charAt(0) === '_') {
return true;
+ }
// IE has a different format for this.
- if (name === 'filter')
+ if (name === 'filter') {
return true;
+ }
// Common IE-specific property prefix.
- if (name.startsWith('scrollbar-'))
+ if (name.startsWith('scrollbar-')) {
return true;
- if (hasUnknownVendorPrefix(name))
+ }
+ if (hasUnknownVendorPrefix(name)) {
return true;
+ }
const value = property.value.toLowerCase();
// IE hack.
- if (value.endsWith('\\9'))
+ if (value.endsWith('\\9')) {
return true;
- if (hasUnknownVendorPrefix(value))
+ }
+ if (hasUnknownVendorPrefix(value)) {
return true;
+ }
return false;
}
@@ -164,8 +171,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {!Event} event
*/
function keydownHandler(event) {
- if (event.key !== 'Escape' || !input.value)
+ if (event.key !== 'Escape' || !input.value) {
return;
+ }
event.consume(true);
input.value = '';
searchHandler();
@@ -207,11 +215,13 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
*/
_sectionsContainerKeyDown(event) {
const activeElement = this._sectionsContainer.ownerDocument.deepActiveElement();
- if (!activeElement)
+ if (!activeElement) {
return;
+ }
const section = activeElement._section;
- if (!section)
+ if (!section) {
return;
+ }
switch (event.key) {
case 'ArrowUp':
@@ -239,10 +249,15 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
}
_sectionsContainerFocusChanged() {
+ this.resetFocus();
+ }
+
+ resetFocus() {
// When a styles section is focused, shift+tab should leave the section.
// Leaving tabIndex = 0 on the first element would cause it to be focused instead.
- if (this._sectionBlocks[0] && this._sectionBlocks[0].sections[0])
+ if (this._sectionBlocks[0] && this._sectionBlocks[0].sections[0]) {
this._sectionBlocks[0].sections[0].element.tabIndex = this._sectionsContainer.hasFocus() ? -1 : 0;
+ }
}
/**
@@ -250,8 +265,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
*/
_onAddButtonLongClick(event) {
const cssModel = this.cssModel();
- if (!cssModel)
+ if (!cssModel) {
return;
+ }
const headers = cssModel.styleSheetHeaders().filter(styleSheetResourceHeader);
/** @type {!Array.<{text: string, handler: function()}>} */
@@ -306,26 +322,31 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
_refreshUpdate(editedSection, editedTreeElement) {
if (editedTreeElement) {
for (const section of this.allSections()) {
- if (section.isBlank)
+ if (section.isBlank) {
continue;
+ }
section._updateVarFunctions(editedTreeElement);
}
}
- if (this._isEditingStyle)
+ if (this._isEditingStyle) {
return;
+ }
const node = this.node();
- if (!node)
+ if (!node) {
return;
+ }
for (const section of this.allSections()) {
- if (section.isBlank)
+ if (section.isBlank) {
continue;
+ }
section.update(section === editedSection);
}
- if (this._filterRegex)
+ if (this._filterRegex) {
this._updateFilter();
+ }
this._nodeStylesUpdatedForTest(node, false);
}
@@ -354,8 +375,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
}
_resetCache() {
- if (this.cssModel())
+ if (this.cssModel()) {
this.cssModel().discardCachedMatchedCascade();
+ }
}
/**
@@ -363,8 +385,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
*/
_fetchMatchedCascade() {
const node = this.node();
- if (!node || !this.cssModel())
+ if (!node || !this.cssModel()) {
return Promise.resolve(/** @type {?SDK.CSSMatchedStyles} */ (null));
+ }
return this.cssModel().cachedMatchedCascadeForNode(node).then(validateStyles.bind(this));
@@ -383,8 +406,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {!Elements.StylePropertyTreeElement=} treeElement
*/
setEditingStyle(editing, treeElement) {
- if (this._isEditingStyle === editing)
+ if (this._isEditingStyle === editing) {
return;
+ }
this.contentElement.classList.toggle('is-editing-style', editing);
this._isEditingStyle = editing;
this._setActiveProperty(null);
@@ -394,21 +418,25 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {?Elements.StylePropertyTreeElement} treeElement
*/
_setActiveProperty(treeElement) {
- if (this._isActivePropertyHighlighted)
+ if (this._isActivePropertyHighlighted) {
SDK.OverlayModel.hideDOMNodeHighlight();
+ }
this._isActivePropertyHighlighted = false;
- if (!this.node())
+ if (!this.node()) {
return;
+ }
- if (!treeElement || treeElement.overloaded() || treeElement.inherited())
+ if (!treeElement || treeElement.overloaded() || treeElement.inherited()) {
return;
+ }
const rule = treeElement.property.ownerStyle.parentRule;
const selectorList = rule ? rule.selectorText() : undefined;
for (const mode of ['padding', 'border', 'margin']) {
- if (!treeElement.name.startsWith(mode))
+ if (!treeElement.name.startsWith(mode)) {
continue;
+ }
this.node().domModel().overlayModel().highlightInOverlay(
{node: /** @type {!SDK.DOMNode} */ (this.node()), selectorList}, mode);
this._isActivePropertyHighlighted = true;
@@ -423,13 +451,15 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
onCSSModelChanged(event) {
const edit = event && event.data ? /** @type {?SDK.CSSModel.Edit} */ (event.data.edit) : null;
if (edit) {
- for (const section of this.allSections())
+ for (const section of this.allSections()) {
section._styleSheetEdited(edit);
+ }
return;
}
- if (this._userOperation || this._isEditingStyle)
+ if (this._userOperation || this._isEditingStyle) {
return;
+ }
this._resetCache();
this.update();
@@ -442,8 +472,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
let index = 0;
for (const block of this._sectionBlocks) {
for (const section of block.sections) {
- if (section.element.hasFocus())
+ if (section.element.hasFocus()) {
return index;
+ }
index++;
}
}
@@ -456,8 +487,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
*/
continueEditingElement(sectionIndex, propertyIndex) {
const section = this.allSections()[sectionIndex];
- if (section)
+ if (section) {
section.propertiesTreeOutline.rootElement().childAt(propertyIndex).startEditing();
+ }
}
/**
@@ -468,10 +500,11 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
// Elements.ElementsSidebarPane's throttler schedules this method. Usually,
// rebuild is suppressed while editing (see onCSSModelChanged()), but we need a
// 'force' flag since the currently running throttler process cannot be canceled.
- if (this._needsForceUpdate)
+ if (this._needsForceUpdate) {
this._needsForceUpdate = false;
- else if (this._isEditingStyle || this._userOperation)
+ } else if (this._isEditingStyle || this._userOperation) {
return;
+ }
const focusedIndex = this.focusedSectionIndex();
this._linkifier.reset();
@@ -488,8 +521,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
await this._rebuildSectionsForMatchedStyleRules(/** @type {!SDK.CSSMatchedStyles} */ (matchedStyles));
let pseudoTypes = [];
const keys = matchedStyles.pseudoTypes();
- if (keys.delete(Protocol.DOM.PseudoType.Before))
+ if (keys.delete(Protocol.DOM.PseudoType.Before)) {
pseudoTypes.push(Protocol.DOM.PseudoType.Before);
+ }
pseudoTypes = pseudoTypes.concat(keys.valuesArray().sort());
for (const pseudoType of pseudoTypes) {
const block = Elements.SectionBlock.createPseudoTypeBlock(pseudoType);
@@ -502,31 +536,36 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
for (const keyframesRule of matchedStyles.keyframes()) {
const block = Elements.SectionBlock.createKeyframesBlock(keyframesRule.name().text);
- for (const keyframe of keyframesRule.keyframes())
+ for (const keyframe of keyframesRule.keyframes()) {
block.sections.push(new Elements.KeyframePropertiesSection(this, matchedStyles, keyframe.style));
+ }
this._sectionBlocks.push(block);
}
let index = 0;
for (const block of this._sectionBlocks) {
const titleElement = block.titleElement();
- if (titleElement)
+ if (titleElement) {
this._sectionsContainer.appendChild(titleElement);
+ }
for (const section of block.sections) {
this._sectionsContainer.appendChild(section.element);
- if (index === focusedIndex)
+ if (index === focusedIndex) {
section.element.focus();
+ }
index++;
}
}
- if (focusedIndex >= index)
+ if (focusedIndex >= index) {
this._sectionBlocks[0].sections[0].element.focus();
+ }
this._sectionsContainerFocusChanged();
- if (this._filterRegex)
+ if (this._filterRegex) {
this._updateFilter();
- else
+ } else {
this._noMatchesElement.classList.toggle('hidden', this._sectionBlocks.length > 0);
+ }
this._nodeStylesUpdatedForTest(/** @type {!SDK.DOMNode} */ (node), true);
if (this._decorator) {
@@ -566,8 +605,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
async _createNewRuleInViaInspectorStyleSheet() {
const cssModel = this.cssModel();
const node = this.node();
- if (!cssModel || !node)
+ if (!cssModel || !node) {
return;
+ }
this.setUserOperation(true);
const styleSheetHeader = await cssModel.requestViaInspectorStylesheet(/** @type {!SDK.DOMNode} */ (node));
@@ -580,9 +620,11 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {?SDK.CSSStyleSheetHeader} styleSheetHeader
*/
async _createNewRuleInStyleSheet(styleSheetHeader) {
- if (!styleSheetHeader)
+ if (!styleSheetHeader) {
return;
- const text = await styleSheetHeader.requestContent() || '';
+ }
+
+ const text = (await styleSheetHeader.requestContent()).content || '';
const lines = text.split('\n');
const range = TextUtils.TextRange.createFromLocation(lines.length - 1, lines[lines.length - 1].length);
this._addBlankSection(this._sectionBlocks[0].sections[0], styleSheetHeader.id, range);
@@ -603,8 +645,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
for (const block of this._sectionBlocks) {
const index = block.sections.indexOf(insertAfterSection);
- if (index === -1)
+ if (index === -1) {
continue;
+ }
block.sections.splice(index + 1, 0, blankSection);
blankSection.startEditingSelector();
}
@@ -616,8 +659,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
removeSection(section) {
for (const block of this._sectionBlocks) {
const index = block.sections.indexOf(section);
- if (index === -1)
+ if (index === -1) {
continue;
+ }
block.sections.splice(index, 1);
section.element.remove();
}
@@ -632,9 +676,10 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
_updateFilter() {
let hasAnyVisibleBlock = false;
- for (const block of this._sectionBlocks)
+ for (const block of this._sectionBlocks) {
hasAnyVisibleBlock |= block.updateFilter();
- this._noMatchesElement.classList.toggle('hidden', hasAnyVisibleBlock);
+ }
+ this._noMatchesElement.classList.toggle('hidden', !!hasAnyVisibleBlock);
}
/**
@@ -650,8 +695,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
*/
allSections() {
let sections = [];
- for (const block of this._sectionBlocks)
+ for (const block of this._sectionBlocks) {
sections = sections.concat(block.sections);
+ }
return sections;
}
@@ -687,25 +733,29 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {?UI.ToolbarToggle} toggle
*/
showToolbarPane(widget, toggle) {
- if (this._pendingWidgetToggle)
+ if (this._pendingWidgetToggle) {
this._pendingWidgetToggle.setToggled(false);
+ }
this._pendingWidgetToggle = toggle;
- if (this._animatedToolbarPane)
+ if (this._animatedToolbarPane) {
this._pendingWidget = widget;
- else
+ } else {
this._startToolbarPaneAnimation(widget);
+ }
- if (widget && toggle)
+ if (widget && toggle) {
toggle.setToggled(true);
+ }
}
/**
* @param {?UI.Widget} widget
*/
_startToolbarPaneAnimation(widget) {
- if (widget === this._currentToolbarPane)
+ if (widget === this._currentToolbarPane) {
return;
+ }
if (widget && this._currentToolbarPane) {
this._currentToolbarPane.detach();
@@ -717,13 +767,15 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
this._animatedToolbarPane = widget;
- if (this._currentToolbarPane)
+ if (this._currentToolbarPane) {
this._toolbarPaneElement.style.animationName = 'styles-element-state-pane-slideout';
- else if (widget)
+ } else if (widget) {
this._toolbarPaneElement.style.animationName = 'styles-element-state-pane-slidein';
+ }
- if (widget)
+ if (widget) {
widget.show(this._toolbarPaneElement);
+ }
const listener = onAnimationEnd.bind(this);
this._toolbarPaneElement.addEventListener('animationend', listener, false);
@@ -735,12 +787,14 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
this._toolbarPaneElement.style.removeProperty('animation-name');
this._toolbarPaneElement.removeEventListener('animationend', listener, false);
- if (this._currentToolbarPane)
+ if (this._currentToolbarPane) {
this._currentToolbarPane.detach();
+ }
this._currentToolbarPane = this._animatedToolbarPane;
- if (this._currentToolbarPane)
+ if (this._currentToolbarPane) {
this._currentToolbarPane.focus();
+ }
this._animatedToolbarPane = null;
if (this._pendingWidget) {
@@ -802,11 +856,13 @@ Elements.SectionBlock = class {
*/
updateFilter() {
let hasAnyVisibleSection = false;
- for (const section of this.sections)
+ for (const section of this.sections) {
hasAnyVisibleSection |= section._updateFilter();
- if (this._titleElement)
+ }
+ if (this._titleElement) {
this._titleElement.classList.toggle('hidden', !hasAnyVisibleSection);
- return hasAnyVisibleSection;
+ }
+ return !!hasAnyVisibleSection;
}
/**
@@ -899,8 +955,9 @@ Elements.StylePropertiesSection = class {
this._titleElement.appendChild(selectorContainer);
this._selectorContainer = selectorContainer;
- if (this.navigable)
+ if (this.navigable) {
this.element.classList.add('navigable');
+ }
if (!this.editable) {
this.element.classList.add('read-only');
@@ -919,14 +976,11 @@ Elements.StylePropertiesSection = class {
* @return {!Node}
*/
static createRuleOriginNode(matchedStyles, linkifier, rule) {
- if (!rule)
+ if (!rule) {
return createTextNode('');
+ }
- let ruleLocation;
- if (rule instanceof SDK.CSSStyleRule)
- ruleLocation = rule.style.range;
- else if (rule instanceof SDK.CSSKeyframeRule)
- ruleLocation = rule.key().range;
+ const ruleLocation = this._getRuleLocationFromCSSRule(rule);
const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;
if (ruleLocation && rule.styleSheetId && header && !header.isAnonymousInlineStyleSheet()) {
@@ -934,12 +988,15 @@ Elements.StylePropertiesSection = class {
matchedStyles.cssModel(), linkifier, rule.styleSheetId, ruleLocation);
}
- if (rule.isUserAgent())
+ if (rule.isUserAgent()) {
return createTextNode(Common.UIString('user agent stylesheet'));
- if (rule.isInjected())
+ }
+ if (rule.isInjected()) {
return createTextNode(Common.UIString('injected stylesheet'));
- if (rule.isViaInspector())
+ }
+ if (rule.isViaInspector()) {
return createTextNode(Common.UIString('via inspector'));
+ }
if (header && header.ownerNode) {
const link = Elements.DOMLinkifier.linkifyDeferredNodeReference(header.ownerNode, {preventKeyboardFocus: true});
@@ -951,6 +1008,39 @@ Elements.StylePropertiesSection = class {
}
/**
+ * @param {!SDK.CSSRule} rule
+ * @return {?TextUtils.TextRange}
+ */
+ static _getRuleLocationFromCSSRule(rule) {
+ let ruleLocation = null;
+ if (rule instanceof SDK.CSSStyleRule) {
+ ruleLocation = rule.style.range;
+ } else if (rule instanceof SDK.CSSKeyframeRule) {
+ ruleLocation = rule.key().range;
+ }
+ return ruleLocation;
+ }
+
+ /**
+ * @param {!SDK.CSSMatchedStyles} matchedStyles
+ * @param {?SDK.CSSRule} rule
+ */
+ static tryNavigateToRuleLocation(matchedStyles, rule) {
+ if (!rule) {
+ return;
+ }
+
+ const ruleLocation = this._getRuleLocationFromCSSRule(rule);
+ const header = rule.styleSheetId ? matchedStyles.cssModel().styleSheetHeaderForId(rule.styleSheetId) : null;
+
+ if (ruleLocation && rule.styleSheetId && header && !header.isAnonymousInlineStyleSheet()) {
+ const matchingSelectorLocation =
+ this._getCSSSelectorLocation(matchedStyles.cssModel(), rule.styleSheetId, ruleLocation);
+ this._revealSelectorSource(matchingSelectorLocation, true);
+ }
+ }
+
+ /**
* @param {!SDK.CSSModel} cssModel
* @param {!Components.Linkifier} linkifier
* @param {string} styleSheetId
@@ -958,19 +1048,30 @@ Elements.StylePropertiesSection = class {
* @return {!Node}
*/
static _linkifyRuleLocation(cssModel, linkifier, styleSheetId, ruleLocation) {
+ const matchingSelectorLocation = this._getCSSSelectorLocation(cssModel, styleSheetId, ruleLocation);
+ return linkifier.linkifyCSSLocation(matchingSelectorLocation);
+ }
+
+ /**
+ * @param {!SDK.CSSModel} cssModel
+ * @param {string} styleSheetId
+ * @param {!TextUtils.TextRange} ruleLocation
+ * @return {!SDK.CSSLocation}
+ */
+ static _getCSSSelectorLocation(cssModel, styleSheetId, ruleLocation) {
const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);
const lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
const columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
- const matchingSelectorLocation = new SDK.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
- return linkifier.linkifyCSSLocation(matchingSelectorLocation);
+ return new SDK.CSSLocation(styleSheetHeader, lineNumber, columnNumber);
}
/**
* @param {!Event} event
*/
_onKeyDown(event) {
- if (UI.isEditing() || !this.editable || event.altKey || event.ctrlKey || event.metaKey)
+ if (UI.isEditing() || !this.editable || event.altKey || event.ctrlKey || event.metaKey) {
return;
+ }
switch (event.key) {
case 'Enter':
case ' ':
@@ -979,8 +1080,9 @@ Elements.StylePropertiesSection = class {
break;
default:
// Filter out non-printable key strokes.
- if (event.key.length === 1)
+ if (event.key.length === 1) {
this.addNewBlankProperty(0).startEditing();
+ }
break;
}
}
@@ -1013,20 +1115,23 @@ Elements.StylePropertiesSection = class {
this._setSectionHovered(hasCtrlOrMeta);
const treeElement = this.propertiesTreeOutline.treeElementFromEvent(event);
- if (treeElement instanceof Elements.StylePropertyTreeElement)
+ if (treeElement instanceof Elements.StylePropertyTreeElement) {
this._parentPane._setActiveProperty(/** @type {!Elements.StylePropertyTreeElement} */ (treeElement));
- else
+ } else {
this._parentPane._setActiveProperty(null);
- if (!this._selectedSinceMouseDown && this.element.getComponentSelection().toString())
+ }
+ if (!this._selectedSinceMouseDown && this.element.getComponentSelection().toString()) {
this._selectedSinceMouseDown = true;
+ }
}
/**
* @param {!Element} container
*/
_createHoverMenuToolbar(container) {
- if (!this.editable)
+ if (!this.editable) {
return;
+ }
const items = [];
const textShadowButton = new UI.ToolbarButton(Common.UIString('Add text-shadow'), 'largeicon-text-shadow');
@@ -1061,8 +1166,9 @@ Elements.StylePropertiesSection = class {
}
const sectionToolbar = new UI.Toolbar('sidebar-pane-section-toolbar', container);
- for (let i = 0; i < items.length; ++i)
+ for (let i = 0; i < items.length; ++i) {
sectionToolbar.appendToolbarItem(items[i]);
+ }
const menuButton = new UI.ToolbarButton('', 'largeicon-menu');
menuButton.element.tabIndex = -1;
@@ -1077,8 +1183,9 @@ Elements.StylePropertiesSection = class {
* @param {boolean} value
*/
function setItemsVisibility(items, value) {
- for (let i = 0; i < items.length; ++i)
+ for (let i = 0; i < items.length; ++i) {
items[i].setVisible(value);
+ }
menuButton.setVisible(!value);
}
}
@@ -1095,22 +1202,26 @@ Elements.StylePropertiesSection = class {
*/
_headerText() {
const node = this._matchedStyles.nodeForStyle(this._style);
- if (this._style.type === SDK.CSSStyleDeclaration.Type.Inline)
+ if (this._style.type === SDK.CSSStyleDeclaration.Type.Inline) {
return this._matchedStyles.isInherited(this._style) ? Common.UIString('Style Attribute') : 'element.style';
- if (this._style.type === SDK.CSSStyleDeclaration.Type.Attributes)
+ }
+ if (this._style.type === SDK.CSSStyleDeclaration.Type.Attributes) {
return ls`${node.nodeNameInCorrectCase()}[Attributes Style]`;
+ }
return this._style.parentRule.selectorText();
}
_onMouseOutSelector() {
- if (this._hoverTimer)
+ if (this._hoverTimer) {
clearTimeout(this._hoverTimer);
+ }
SDK.OverlayModel.hideDOMNodeHighlight();
}
_onMouseEnterSelector() {
- if (this._hoverTimer)
+ if (this._hoverTimer) {
clearTimeout(this._hoverTimer);
+ }
this._hoverTimer = setTimeout(this._highlight.bind(this), 300);
}
@@ -1120,8 +1231,9 @@ Elements.StylePropertiesSection = class {
_highlight(mode = 'all') {
SDK.OverlayModel.hideDOMNodeHighlight();
const node = this._parentPane.node();
- if (!node)
+ if (!node) {
return;
+ }
const selectorList = this._style.parentRule ? this._style.parentRule.selectorText() : undefined;
node.domModel().overlayModel().highlightInOverlay({node, selectorList}, mode);
}
@@ -1131,13 +1243,15 @@ Elements.StylePropertiesSection = class {
*/
firstSibling() {
const parent = this.element.parentElement;
- if (!parent)
+ if (!parent) {
return null;
+ }
let childElement = parent.firstChild;
while (childElement) {
- if (childElement._section)
+ if (childElement._section) {
return childElement._section;
+ }
childElement = childElement.nextSibling;
}
@@ -1149,13 +1263,15 @@ Elements.StylePropertiesSection = class {
*/
lastSibling() {
const parent = this.element.parentElement;
- if (!parent)
+ if (!parent) {
return null;
+ }
let childElement = parent.lastChild;
while (childElement) {
- if (childElement._section)
+ if (childElement._section) {
return childElement._section;
+ }
childElement = childElement.previousSibling;
}
@@ -1167,9 +1283,9 @@ Elements.StylePropertiesSection = class {
*/
nextSibling() {
let curElement = this.element;
- do
+ do {
curElement = curElement.nextSibling;
- while (curElement && !curElement._section);
+ } while (curElement && !curElement._section);
return curElement ? curElement._section : null;
}
@@ -1179,9 +1295,9 @@ Elements.StylePropertiesSection = class {
*/
previousSibling() {
let curElement = this.element;
- do
+ do {
curElement = curElement.previousSibling;
- while (curElement && !curElement._section);
+ } while (curElement && !curElement._section);
return curElement ? curElement._section : null;
}
@@ -1207,8 +1323,9 @@ Elements.StylePropertiesSection = class {
treeElement.property.value = '0 0 black';
treeElement.updateTitle();
const shadowSwatchPopoverHelper = Elements.ShadowSwatchPopoverHelper.forTreeElement(treeElement);
- if (shadowSwatchPopoverHelper)
+ if (shadowSwatchPopoverHelper) {
shadowSwatchPopoverHelper.showPopover();
+ }
}
/**
@@ -1221,8 +1338,9 @@ Elements.StylePropertiesSection = class {
treeElement.property.value = 'black';
treeElement.updateTitle();
const colorSwatch = Elements.ColorSwatchPopoverIcon.forTreeElement(treeElement);
- if (colorSwatch)
+ if (colorSwatch) {
colorSwatch.showPopover();
+ }
}
/**
@@ -1235,8 +1353,9 @@ Elements.StylePropertiesSection = class {
treeElement.property.value = 'white';
treeElement.updateTitle();
const colorSwatch = Elements.ColorSwatchPopoverIcon.forTreeElement(treeElement);
- if (colorSwatch)
+ if (colorSwatch) {
colorSwatch.showPopover();
+ }
}
/**
@@ -1244,10 +1363,11 @@ Elements.StylePropertiesSection = class {
*/
_styleSheetEdited(edit) {
const rule = this._style.parentRule;
- if (rule)
+ if (rule) {
rule.rebase(edit);
- else
+ } else {
this._style.rebase(edit);
+ }
this._updateMediaList();
this._updateRuleOrigin();
@@ -1260,8 +1380,9 @@ Elements.StylePropertiesSection = class {
for (let i = mediaRules.length - 1; i >= 0; --i) {
const media = mediaRules[i];
// Don't display trivial non-print media types.
- if (!media.text.includes('(') && media.text !== 'print')
+ if (!media.text.includes('(') && media.text !== 'print') {
continue;
+ }
const mediaDataElement = this._mediaListElement.createChild('div', 'media');
const mediaContainerElement = mediaDataElement.createChild('span');
const mediaTextElement = mediaContainerElement.createChild('span', 'media-text');
@@ -1290,8 +1411,9 @@ Elements.StylePropertiesSection = class {
_updateMediaList() {
this._mediaListElement.removeChildren();
- if (this._style.parentRule && this._style.parentRule instanceof SDK.CSSStyleRule)
+ if (this._style.parentRule && this._style.parentRule instanceof SDK.CSSStyleRule) {
this._createMediaList(this._style.parentRule.media);
+ }
}
/**
@@ -1312,14 +1434,15 @@ Elements.StylePropertiesSection = class {
*/
nextEditableSibling() {
let curSection = this;
- do
+ do {
curSection = curSection.nextSibling();
- while (curSection && !curSection.editable);
+ } while (curSection && !curSection.editable);
if (!curSection) {
curSection = this.firstSibling();
- while (curSection && !curSection.editable)
+ while (curSection && !curSection.editable) {
curSection = curSection.nextSibling();
+ }
}
return (curSection && curSection.editable) ? curSection : null;
@@ -1330,14 +1453,15 @@ Elements.StylePropertiesSection = class {
*/
previousEditableSibling() {
let curSection = this;
- do
+ do {
curSection = curSection.previousSibling();
- while (curSection && !curSection.editable);
+ } while (curSection && !curSection.editable);
if (!curSection) {
curSection = this.lastSibling();
- while (curSection && !curSection.editable)
+ while (curSection && !curSection.editable) {
curSection = curSection.previousSibling();
+ }
}
return (curSection && curSection.editable) ? curSection : null;
@@ -1356,8 +1480,9 @@ Elements.StylePropertiesSection = class {
_updateVarFunctions(editedTreeElement) {
let child = this.propertiesTreeOutline.firstChild();
while (child) {
- if (child !== editedTreeElement)
+ if (child !== editedTreeElement) {
child.updateTitleIfComputedValueChanged();
+ }
child = child.traverseNextTreeElement(false /* skipUnrevealed */, null /* stayWithin */, true /* dontPopulate */);
}
}
@@ -1384,10 +1509,12 @@ Elements.StylePropertiesSection = class {
* @param {!Event=} event
*/
_showAllItems(event) {
- if (event)
+ if (event) {
event.consume();
- if (this._forceShowAll)
+ }
+ if (this._forceShowAll) {
return;
+ }
this._forceShowAll = true;
this.onpopulate();
}
@@ -1402,14 +1529,16 @@ Elements.StylePropertiesSection = class {
Elements.StylePropertiesSection.MaxProperties + properties.length - this._originalPropertiesCount;
for (const property of properties) {
- if (!this._forceShowAll && count >= maxProperties)
+ if (!this._forceShowAll && count >= maxProperties) {
break;
+ }
count++;
const isShorthand = !!style.longhandProperties(property.name).length;
const inherited = this.isPropertyInherited(property.name);
const overloaded = this._isPropertyOverloaded(property);
- if (style.parentRule && style.parentRule.isUserAgent() && inherited)
+ if (style.parentRule && style.parentRule.isUserAgent() && inherited) {
continue;
+ }
const item = new Elements.StylePropertyTreeElement(
this._parentPane, this._matchedStyles, property, isShorthand, inherited, overloaded, false);
this.propertiesTreeOutline.appendChild(item);
@@ -1437,32 +1566,37 @@ Elements.StylePropertiesSection = class {
_updateFilter() {
let hasMatchingChild = false;
this._showAllItems();
- for (const child of this.propertiesTreeOutline.rootElement().children())
+ for (const child of this.propertiesTreeOutline.rootElement().children()) {
hasMatchingChild |= child._updateFilter();
+ }
const regex = this._parentPane.filterRegex();
const hideRule = !hasMatchingChild && !!regex && !regex.test(this.element.deepTextContent());
this.element.classList.toggle('hidden', hideRule);
- if (!hideRule && this._style.parentRule)
+ if (!hideRule && this._style.parentRule) {
this._markSelectorHighlights();
+ }
return !hideRule;
}
_markSelectorMatches() {
const rule = this._style.parentRule;
- if (!rule)
+ if (!rule) {
return;
+ }
this._mediaListElement.classList.toggle('media-matches', this._matchedStyles.mediaMatches(this._style));
const selectorTexts = rule.selectors.map(selector => selector.text);
const matchingSelectorIndexes = this._matchedStyles.matchingSelectors(/** @type {!SDK.CSSStyleRule} */ (rule));
const matchingSelectors = /** @type {!Array<boolean>} */ (new Array(selectorTexts.length).fill(false));
- for (const matchingIndex of matchingSelectorIndexes)
+ for (const matchingIndex of matchingSelectorIndexes) {
matchingSelectors[matchingIndex] = true;
+ }
- if (this._parentPane._isEditingStyle)
+ if (this._parentPane._isEditingStyle) {
return;
+ }
const fragment = this._hoverableSelectorsMode ? this._renderHoverableSelectors(selectorTexts, matchingSelectors) :
this._renderSimplifiedSelectors(selectorTexts, matchingSelectors);
@@ -1479,8 +1613,9 @@ Elements.StylePropertiesSection = class {
_renderHoverableSelectors(selectors, matchingSelectors) {
const fragment = createDocumentFragment();
for (let i = 0; i < selectors.length; ++i) {
- if (i)
+ if (i) {
fragment.createTextChild(', ');
+ }
fragment.appendChild(this._createSelectorElement(selectors[i], matchingSelectors[i], i));
}
return fragment;
@@ -1495,8 +1630,9 @@ Elements.StylePropertiesSection = class {
_createSelectorElement(text, isMatching, navigationIndex) {
const element = createElementWithClass('span', 'simple-selector');
element.classList.toggle('selector-matches', isMatching);
- if (typeof navigationIndex === 'number')
+ if (typeof navigationIndex === 'number') {
element._selectorIndex = navigationIndex;
+ }
element.textContent = text;
return element;
}
@@ -1518,8 +1654,9 @@ Elements.StylePropertiesSection = class {
currentMatching = matchingSelectors[i];
text += selectors[i] + (i === selectors.length - 1 ? '' : ', ');
}
- if (text)
+ if (text) {
fragment.appendChild(this._createSelectorElement(text, currentMatching));
+ }
return fragment;
}
@@ -1545,8 +1682,9 @@ Elements.StylePropertiesSection = class {
* @param {!Event} event
*/
_handleSelectorContainerClick(event) {
- if (this._checkWillCancelEditing() || !this.editable)
+ if (this._checkWillCancelEditing() || !this.editable) {
return;
+ }
if (event.target === this._selectorContainer) {
this.addNewBlankProperty(0).startEditing();
event.consume(true);
@@ -1574,8 +1712,10 @@ Elements.StylePropertiesSection = class {
* @param {!Event} event
*/
_handleEmptySpaceClick(event) {
- if (!this.editable || this.element.hasSelection() || this._checkWillCancelEditing() || this._selectedSinceMouseDown)
+ if (!this.editable || this.element.hasSelection() || this._checkWillCancelEditing() ||
+ this._selectedSinceMouseDown) {
return;
+ }
if (event.target.classList.contains('header') || this.element.classList.contains('read-only') ||
event.target.enclosingNodeOrSelfWithClass('media')) {
@@ -1583,10 +1723,11 @@ Elements.StylePropertiesSection = class {
return;
}
const deepTarget = event.deepElementFromPoint();
- if (deepTarget.treeElement)
+ if (deepTarget.treeElement) {
this.addNewBlankProperty(deepTarget.treeElement.property.index + 1).startEditing();
- else
+ } else {
this.addNewBlankProperty().startEditing();
+ }
event.consume(true);
}
@@ -1596,8 +1737,9 @@ Elements.StylePropertiesSection = class {
* @param {!Event} event
*/
_handleMediaRuleClick(media, element, event) {
- if (UI.isBeingEdited(element))
+ if (UI.isBeingEdited(element)) {
return;
+ }
if (UI.KeyboardShortcut.eventHasCtrlOrMeta(/** @type {!MouseEvent} */ (event)) && this.navigable) {
const location = media.rawLocation();
@@ -1606,14 +1748,16 @@ Elements.StylePropertiesSection = class {
return;
}
const uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(location);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation);
+ }
event.consume(true);
return;
}
- if (!this.editable)
+ if (!this.editable) {
return;
+ }
const config = new UI.InplaceEditor.Config(
this._editingMediaCommitted.bind(this, media), this._editingMediaCancelled.bind(this, element), undefined,
@@ -1669,8 +1813,9 @@ Elements.StylePropertiesSection = class {
this._parentPane.setEditingStyle(false);
this._editingMediaFinished(element);
- if (newContent)
+ if (newContent) {
newContent = newContent.trim();
+ }
/**
* @param {boolean} success
@@ -1703,8 +1848,9 @@ Elements.StylePropertiesSection = class {
event.consume(true);
return;
}
- if (this.element.hasSelection())
+ if (this.element.hasSelection()) {
return;
+ }
this._startEditingAtFirstPosition();
event.consume(true);
}
@@ -1717,17 +1863,28 @@ Elements.StylePropertiesSection = class {
const cssModel = this._parentPane.cssModel();
const rule = this._style.parentRule;
const header = cssModel.styleSheetHeaderForId(/** @type {string} */ (rule.styleSheetId));
- if (!header)
+ if (!header) {
return;
+ }
const rawLocation = new SDK.CSSLocation(header, rule.lineNumberInSource(index), rule.columnNumberInSource(index));
+ Elements.StylePropertiesSection._revealSelectorSource(rawLocation, focus);
+ }
+
+ /**
+ * @param {!SDK.CSSLocation} rawLocation
+ * @param {boolean} focus
+ */
+ static _revealSelectorSource(rawLocation, focus) {
const uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation, !focus);
+ }
}
_startEditingAtFirstPosition() {
- if (!this.editable)
+ if (!this.editable) {
return;
+ }
if (!this._style.parentRule) {
this.moveEditorFromSelector('forward');
@@ -1739,8 +1896,9 @@ Elements.StylePropertiesSection = class {
startEditingSelector() {
const element = this._selectorElement;
- if (UI.isBeingEdited(element))
+ if (UI.isBeingEdited(element)) {
return;
+ }
element.scrollIntoViewIfNeeded(false);
// Reset selector marks in group, and normalize whitespace.
@@ -1752,8 +1910,9 @@ Elements.StylePropertiesSection = class {
element.getComponentSelection().selectAllChildren(element);
this._parentPane.setEditingStyle(true);
- if (element.classList.contains('simple-selector'))
+ if (element.classList.contains('simple-selector')) {
this._navigateToSelectorSource(0, false);
+ }
}
/**
@@ -1762,21 +1921,25 @@ Elements.StylePropertiesSection = class {
moveEditorFromSelector(moveDirection) {
this._markSelectorMatches();
- if (!moveDirection)
+ if (!moveDirection) {
return;
+ }
if (moveDirection === 'forward') {
let firstChild = this.propertiesTreeOutline.firstChild();
- while (firstChild && firstChild.inherited())
+ while (firstChild && firstChild.inherited()) {
firstChild = firstChild.nextSibling;
- if (!firstChild)
+ }
+ if (!firstChild) {
this.addNewBlankProperty().startEditing();
- else
+ } else {
firstChild.startEditing(firstChild.nameElement);
+ }
} else {
const previousSection = this.previousEditableSibling();
- if (!previousSection)
+ if (!previousSection) {
return;
+ }
previousSection.addNewBlankProperty().startEditing();
}
@@ -1791,8 +1954,9 @@ Elements.StylePropertiesSection = class {
*/
editingSelectorCommitted(element, newContent, oldContent, context, moveDirection) {
this._editingSelectorEnded();
- if (newContent)
+ if (newContent) {
newContent = newContent.trim();
+ }
if (newContent === oldContent) {
// Revert to a trimmed version of the selector if need be.
this._selectorElement.textContent = newContent;
@@ -1800,8 +1964,9 @@ Elements.StylePropertiesSection = class {
return;
}
const rule = this._style.parentRule;
- if (!rule)
+ if (!rule) {
return;
+ }
/**
* @this {Elements.StylePropertiesSection}
@@ -1830,8 +1995,9 @@ Elements.StylePropertiesSection = class {
* @this {Elements.StylePropertiesSection}
*/
function onSelectorsUpdated(rule, success) {
- if (!success)
+ if (!success) {
return Promise.resolve();
+ }
return this._matchedStyles.recomputeMatchingSelectors(rule).then(updateSourceRanges.bind(this, rule));
}
@@ -1848,8 +2014,9 @@ Elements.StylePropertiesSection = class {
console.assert(rule instanceof SDK.CSSStyleRule);
const oldSelectorRange = rule.selectorRange();
- if (!oldSelectorRange)
+ if (!oldSelectorRange) {
return Promise.resolve();
+ }
return rule.setSelectorText(newContent)
.then(onSelectorsUpdated.bind(this, /** @type {!SDK.CSSStyleRule} */ (rule), oldSelectorRange));
}
@@ -1895,8 +2062,9 @@ Elements.BlankStylePropertiesSection = class extends Elements.StylePropertiesSec
this._selectorRefElement.removeChildren();
this._selectorRefElement.appendChild(Elements.StylePropertiesSection._linkifyRuleLocation(
cssModel, this._parentPane._linkifier, styleSheetId, this._actualRuleLocation()));
- if (insertAfterStyle && insertAfterStyle.parentRule)
+ if (insertAfterStyle && insertAfterStyle.parentRule) {
this._createMediaList(insertAfterStyle.parentRule.media);
+ }
this.element.classList.add('blank-section');
}
@@ -1961,22 +2129,26 @@ Elements.BlankStylePropertiesSection = class extends Elements.StylePropertiesSec
const doesSelectorAffectSelectedNode = this._matchedStyles.matchingSelectors(newRule).length > 0;
this._makeNormal(newRule);
- if (!doesSelectorAffectSelectedNode)
+ if (!doesSelectorAffectSelectedNode) {
this.propertiesTreeOutline.element.classList.add('no-affect');
+ }
this._updateRuleOrigin();
this._parentPane.setUserOperation(false);
this._editingSelectorEnded();
if (this.element.parentElement) // Might have been detached already.
+ {
this.moveEditorFromSelector(moveDirection);
+ }
this._markSelectorMatches();
this._editingSelectorCommittedForTest();
}
- if (newContent)
+ if (newContent) {
newContent = newContent.trim();
+ }
this._parentPane.setUserOperation(true);
const cssModel = this._parentPane.cssModel();
@@ -2041,15 +2213,17 @@ Elements.KeyframePropertiesSection = class extends Elements.StylePropertiesSecti
* @this {Elements.KeyframePropertiesSection}
*/
function updateSourceRanges(success) {
- if (!success)
+ if (!success) {
return;
+ }
this._parentPane._refreshUpdate(this);
}
console.assert(rule instanceof SDK.CSSKeyframeRule);
const oldRange = rule.key().range;
- if (!oldRange)
+ if (!oldRange) {
return Promise.resolve();
+ }
return rule.setKeyText(newContent).then(updateSourceRanges.bind(this));
}
@@ -2105,8 +2279,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
this._cssCompletions = [];
if (isEditingName) {
this._cssCompletions = SDK.cssMetadata().allProperties();
- if (!treeElement.node().isSVGNode())
+ if (!treeElement.node().isSVGNode()) {
this._cssCompletions = this._cssCompletions.filter(property => !SDK.cssMetadata().isSVGProperty(property));
+ }
} else {
this._cssCompletions = SDK.cssMetadata().propertyValues(treeElement.nameElement.textContent);
}
@@ -2114,10 +2289,11 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
this._treeElement = treeElement;
this._isEditingName = isEditingName;
this._cssVariables = treeElement.matchedStyles().availableCSSVariables(treeElement.property.ownerStyle);
- if (this._cssVariables.length < 1000)
+ if (this._cssVariables.length < 1000) {
this._cssVariables.sort(String.naturalOrderComparator);
- else
+ } else {
this._cssVariables.sort();
+ }
if (!isEditingName) {
this.disableDefaultSuggestionForEmptyInput();
@@ -2153,8 +2329,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
}
break;
case 'Enter':
- if (event.shiftKey)
+ if (event.shiftKey) {
return;
+ }
// Accept any available autocompletions and advance to the next field.
this.tabKeyPressed();
event.preventDefault();
@@ -2211,8 +2388,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
* @this {Elements.StylesSidebarPane.CSSPropertyPrompt}
*/
function customNumberHandler(prefix, number, suffix) {
- if (number !== 0 && !suffix.length && SDK.cssMetadata().isLengthProperty(this._treeElement.property.name))
+ if (number !== 0 && !suffix.length && SDK.cssMetadata().isLengthProperty(this._treeElement.property.name)) {
suffix = 'px';
+ }
return prefix + number + suffix;
}
@@ -2220,8 +2398,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
if (!this._isEditingName && this._treeElement.valueElement &&
UI.handleElementValueModifications(
event, this._treeElement.valueElement, finishHandler.bind(this), this._isValueSuggestion.bind(this),
- customNumberHandler.bind(this)))
+ customNumberHandler.bind(this))) {
return true;
+ }
return false;
}
@@ -2231,8 +2410,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
* @return {boolean}
*/
_isValueSuggestion(word) {
- if (!word)
+ if (!word) {
return false;
+ }
word = word.toLowerCase();
return this._cssCompletions.indexOf(word) !== -1 || word.startsWith('--');
}
@@ -2246,29 +2426,34 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
_buildPropertyCompletions(expression, query, force) {
const lowerQuery = query.toLowerCase();
const editingVariable = !this._isEditingName && expression.trim().endsWith('var(');
- if (!query && !force && !editingVariable && (this._isEditingName || expression))
+ if (!query && !force && !editingVariable && (this._isEditingName || expression)) {
return Promise.resolve([]);
+ }
const prefixResults = [];
const anywhereResults = [];
- if (!editingVariable)
+ if (!editingVariable) {
this._cssCompletions.forEach(completion => filterCompletions.call(this, completion, false /* variable */));
+ }
if (this._isEditingName) {
const nameValuePresets = SDK.cssMetadata().nameValuePresets(this._treeElement.node().isSVGNode());
nameValuePresets.forEach(
preset => filterCompletions.call(this, preset, false /* variable */, true /* nameValue */));
}
- if (this._isEditingName || editingVariable)
+ if (this._isEditingName || editingVariable) {
this._cssVariables.forEach(variable => filterCompletions.call(this, variable, true /* variable */));
+ }
const results = prefixResults.concat(anywhereResults);
- if (!this._isEditingName && !results.length && query.length > 1 && '!important'.startsWith(lowerQuery))
+ if (!this._isEditingName && !results.length && query.length > 1 && '!important'.startsWith(lowerQuery)) {
results.push({text: '!important'});
+ }
const userEnteredText = query.replace('-', '');
if (userEnteredText && (userEnteredText === userEnteredText.toUpperCase())) {
for (let i = 0; i < results.length; ++i) {
- if (!results[i].text.startsWith('--'))
+ if (!results[i].text.startsWith('--')) {
results[i].text = results[i].text.toUpperCase();
+ }
}
}
results.forEach(result => {
@@ -2286,8 +2471,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
});
if (this._isColorAware && !this._isEditingName) {
results.sort((a, b) => {
- if (!!a.subtitleRenderer === !!b.subtitleRenderer)
+ if (!!a.subtitleRenderer === !!b.subtitleRenderer) {
return 0;
+ }
return a.subtitleRenderer ? -1 : 1;
});
}
@@ -2307,12 +2493,14 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
this._treeElement.matchedStyles().computeCSSVariable(this._treeElement.property.ownerStyle, completion);
if (computedValue) {
const color = Common.Color.parse(computedValue);
- if (color)
+ if (color) {
result.subtitleRenderer = swatchRenderer.bind(null, color);
+ }
}
}
- if (nameValue)
+ if (nameValue) {
result.hideGhostText = true;
+ }
if (index === 0) {
result.priority = this._isEditingName ? SDK.cssMetadata().propertyUsageWeight(completion) : 1;
prefixResults.push(result);
@@ -2411,8 +2599,9 @@ Elements.StylesSidebarPropertyRenderer = class {
renderValue() {
const valueElement = createElement('span');
valueElement.className = 'value';
- if (!this._propertyValue)
+ if (!this._propertyValue) {
return valueElement;
+ }
if (this._shadowHandler && (this._propertyName === 'box-shadow' || this._propertyName === 'text-shadow' ||
this._propertyName === '-webkit-box-shadow') &&
@@ -2456,15 +2645,17 @@ Elements.StylesSidebarPropertyRenderer = class {
// Strip "url(" and ")" along with whitespace.
let url = text.substring(4, text.length - 1).trim();
const isQuoted = /^'.*'$/.test(url) || /^".*"$/.test(url);
- if (isQuoted)
+ if (isQuoted) {
url = url.substring(1, url.length - 1);
+ }
const container = createDocumentFragment();
container.createTextChild('url(');
let hrefUrl = null;
- if (this._rule && this._rule.resourceURL())
+ if (this._rule && this._rule.resourceURL()) {
hrefUrl = Common.ParsedURL.completeURL(this._rule.resourceURL(), url);
- else if (this._node)
+ } else if (this._node) {
hrefUrl = this._node.resolveURL(url);
+ }
container.appendChild(Components.Linkifier.linkifyURL(hrefUrl || url, {text: url, preventClick: true}));
container.createTextChild(')');
return container;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
index 21a0057e348..259985e1e6e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
@@ -32,3 +32,7 @@
.styles-sidebar-pane-filter-box > input:not(:placeholder-shown) {
box-shadow: var(--focus-ring-active-shadow);
}
+
+.styles-sidebar-pane-filter-box > input::placeholder {
+ color: rgba(0, 0, 0, 0.54);
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsTreeOutline.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsTreeOutline.css
index 6f81f436886..d4dd68393d5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsTreeOutline.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsTreeOutline.css
@@ -18,7 +18,7 @@
word-wrap: break-word;
position: relative;
min-height: 15px;
- line-height: 15px;
+ line-height: 1.36;
}
.elements-disclosure li.parent {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
index 7cdbcc7efaf..3da0626c3a5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/elements_strings.grdp
@@ -42,6 +42,9 @@
<message name="IDS_DEVTOOLS_26396cca3eae28fc6e39123edb2f1510" desc="Context menu item for style property in edit mode">
Reveal in Sources panel
</message>
+ <message name="IDS_DEVTOOLS_2864a2d95e17e3032a3a6e69a51d0256" desc="Context menu item in Elements panel to navigate to style in styles pane">
+ Navigate to style
+ </message>
<message name="IDS_DEVTOOLS_28c0a3050f784583d52339ddb0bc1274" desc="Text in Elements Tree Element of the Elements panel">
Paste element
</message>
@@ -72,21 +75,12 @@
<message name="IDS_DEVTOOLS_365fee797b55ffeac84d2ba82507b721" desc="Text in Styles Sidebar Pane of the Elements panel">
user agent stylesheet
</message>
- <message name="IDS_DEVTOOLS_3afbd9828e011526955ca93b48b57524" desc="A title of the 'Screenshot' action category">
- Screenshot
- </message>
- <message name="IDS_DEVTOOLS_3bb3e8c8a24891ba0f7608bcc96f8b0a" desc="Text in Elements Panel of the Elements panel">
- Frame
- </message>
<message name="IDS_DEVTOOLS_3e255d6c811a40b9ad197fedeadc342c" desc="Text in Platform Fonts Widget of the Elements panel">
Local file
</message>
<message name="IDS_DEVTOOLS_3e9bec182c7495247f5f93d3881d630b" desc="Text in Element State Pane Widget of the Elements panel">
:hov
</message>
- <message name="IDS_DEVTOOLS_3f8f88e3686b2345cecc9530e19e6172" desc="A context menu item in the Elements Tree Outline of the Elements panel">
- Store as global variable
- </message>
<message name="IDS_DEVTOOLS_417117e823d14c9b7c6533e4b04600a6" desc="Text in Elements Breadcrumbs of the Elements panel">
(text)
</message>
@@ -114,18 +108,9 @@
<message name="IDS_DEVTOOLS_4ca94080ccbd5784f5fe296bf1ae3e12" desc="Title of the 'Event Listeners' tool in the sidebar of the elements tool">
Event Listeners
</message>
- <message name="IDS_DEVTOOLS_4cf8e5f6ffbb182b5d480cbabae6a028" desc="A context menu item in the Elements Tree Element of the Elements panel">
- Edit attribute
- </message>
<message name="IDS_DEVTOOLS_4d9468d79ef34f71ba78a28688fa5d31" desc="Alternative title text of a setting in Event Listeners Widget of the Elements panel">
Ancestors
</message>
- <message name="IDS_DEVTOOLS_5134111907df828fc575c69e22480c1e" desc="Text in Elements Tree Element of the Elements panel">
- Hide element
- </message>
- <message name="IDS_DEVTOOLS_539dddc574d3cd85ba73df93df7a76d0" desc="Title of the Stack Trace widget in the Elements panel">
- Stack Trace
- </message>
<message name="IDS_DEVTOOLS_581b87189d0bd86aa707e42553032a3e" desc="Element text content in Elements Tree Element of the Elements panel">
Children:
</message>
@@ -138,24 +123,18 @@
<message name="IDS_DEVTOOLS_5c6236c705b0086fbbdb2df3133f8a06" desc="Title of a setting under the Elements category in Settings">
Reveal DOM node on hover
</message>
- <message name="IDS_DEVTOOLS_5de39fa1bce4bbf9232597a2120bc4d4" desc="Swatch icon element title in Color Swatch Popover Icon of the Elements panel">
- Open cubic bezier editor.
+ <message name="IDS_DEVTOOLS_5e1078f1bee74e1e385b7813280b0c74" desc="Text when node can not be found in page">
+ Node cannot be found in the current page.
</message>
<message name="IDS_DEVTOOLS_5eeb03a9c080c299d4804ac765c818c2" desc="No matches element text content in Styles Sidebar Pane of the Elements panel">
No matching selector or style
</message>
- <message name="IDS_DEVTOOLS_5fb63579fc981698f97d55bfecb213ea" desc="A context menu item in the Elements Tree Element of the Elements panel">
- Copy
- </message>
<message name="IDS_DEVTOOLS_6053f828a109e7d9da3690a7416e4eec" desc="Text in Elements Tree Element of the Elements panel">
Copy XPath
</message>
<message name="IDS_DEVTOOLS_605e072850e19521394f8bad7082acf4" desc="Text of a DOM element in Element State Pane Widget of the Elements panel">
Force element state
</message>
- <message name="IDS_DEVTOOLS_63041e09c8660107e507c9c27c08199c" desc="A context menu item in the Elements Tree Element of the Elements panel">
- Expand recursively
- </message>
<message name="IDS_DEVTOOLS_686676f33cf19ca00788564f43b992cb" desc="Aria accessible name in Computed Style Widget of the Elements panel">
Filter Computed Styles
</message>
@@ -210,15 +189,15 @@
<message name="IDS_DEVTOOLS_91d17eff6a1529e8a4f67a5aa4cabec7" desc="No matches element text content in Computed Style Widget of the Elements panel">
No matching property
</message>
+ <message name="IDS_DEVTOOLS_924843c5b24bc69ed7da2bff699de4f1" desc="Context menu item in Elements panel to navigate to css selector source">
+ Navigate to selector source
+ </message>
<message name="IDS_DEVTOOLS_97d28fbc573f9f331f5b1886b5c1eeef" desc="Text in Elements Tree Element of the Elements panel">
Copy full XPath
</message>
<message name="IDS_DEVTOOLS_9a0364b9e99bb480dd25e1f0284c8555" desc="Text in Metrics Sidebar Pane of the Elements panel">
content
</message>
- <message name="IDS_DEVTOOLS_9fc2d28c05ed9eb1d75ba4465abf15a9" desc="Title of the 'Properties' tool in the sidebar of the elements tool">
- Properties
- </message>
<message name="IDS_DEVTOOLS_a05fb8660778069f6d4a5c5b40a6dbc9" desc="Title of a setting under the Elements category in Settings">
Show user agent shadow DOM
</message>
@@ -231,24 +210,15 @@
<message name="IDS_DEVTOOLS_a98895bde5922dd43c82ad7050abc05a" desc="Tooltip text that appears on the setting when hovering over it in Event Listeners Widget of the Elements panel">
Show listeners on the ancestors
</message>
- <message name="IDS_DEVTOOLS_aa56a2e65d8106aef3c61e4f6bf94fdb" desc="A title of the 'Elements' @UI.ViewLocationResolver category">
- Elements
- </message>
<message name="IDS_DEVTOOLS_abdf882c25e08d9ba219fe33f17591fe" desc="Link text content in Elements Tree Outline of the Elements panel">
reveal
</message>
- <message name="IDS_DEVTOOLS_acc24772ac31677d076f17d9002b57cd" desc="A context menu item in the Elements Tree Element of the Elements panel">
- Collapse children
- </message>
<message name="IDS_DEVTOOLS_ad4ac01e4a5688063dace5ba5d0f04de" desc="Tooltip text that appears when hovering over the largeicon add button in the Styles Sidebar Pane of the Elements panel">
Insert Style Rule Below
</message>
<message name="IDS_DEVTOOLS_b0351810a5721f657b088608865849dd" desc="Text in Styles Sidebar Pane of the Elements panel">
via inspector
</message>
- <message name="IDS_DEVTOOLS_b1c94ca2fbc3e78fc30069c8d0f01680" desc="Text in Event Listeners Widget of the Elements panel">
- All
- </message>
<message name="IDS_DEVTOOLS_b70cdb878a204fecf91c7dd1af312421" desc="Text in Metrics Sidebar Pane of the Elements panel">
padding
</message>
@@ -303,9 +273,6 @@
<message name="IDS_DEVTOOLS_f750c8807bc5f4a7bd259788114a4ebd" desc="Tooltip text that appears when hovering over the largeicon background color button in the Styles Sidebar Pane of the Elements panel">
Add background-color
</message>
- <message name="IDS_DEVTOOLS_f80bc338b6146b566004a046f8137c85" desc="Text in Event Listeners Widget of the Elements panel">
- Passive
- </message>
<message name="IDS_DEVTOOLS_f8d0f1896a9e4ad16d43caa28534df32" desc="Show all button text content in Styles Sidebar Pane of the Elements panel">
Show All Properties (<ph name="PROPERTIES_LENGTH___COUNT">$1s<ex>3</ex></ph> more)
</message>
@@ -315,4 +282,4 @@
<message name="IDS_DEVTOOLS_fd9bcae718daadf263a2e73c7745f0a7" desc="Tree element expand all button element button text content in Elements Tree Outline of the Elements panel">
Show All Nodes (<ph name="VISIBLECHILDREN_LENGTH___EXPANDEDCHILDCOUNT">$1d<ex>3</ex></ph> More)
</message>
-</grit-part> \ No newline at end of file
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
index d5be8fdcd53..eb881b48735 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
@@ -188,6 +188,10 @@
box-shadow: var(--focus-ring-active-shadow);
}
+.styles-sidebar-pane-filter-box > input::placeholder {
+ color: rgba(0, 0, 0, 0.54);
+}
+
.styles-section.styles-panel-hovered:not(.read-only) span.simple-selector:hover,
.styles-section.styles-panel-hovered:not(.read-only) .media-text :hover{
text-decoration: underline;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/EditDOMTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/EditDOMTestRunner.js
index 56efb454dfe..d50240d9720 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/EditDOMTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/EditDOMTestRunner.js
@@ -57,8 +57,9 @@ ElementsTestRunner.editNodePart = function(node, className) {
const treeElement = ElementsTestRunner.firstElementsTreeOutline().findTreeElement(node);
let textElement = treeElement.listItemElement.getElementsByClassName(className)[0];
- if (!textElement && treeElement.childrenListElement)
+ if (!textElement && treeElement.childrenListElement) {
textElement = treeElement.childrenListElement.getElementsByClassName(className)[0];
+ }
treeElement._startEditingTarget(textElement);
return textElement;
@@ -69,8 +70,9 @@ ElementsTestRunner.editNodePartAndRun = function(node, className, newValue, step
editorElement.textContent = newValue;
editorElement.dispatchEvent(TestRunner.createKeyEvent('Enter'));
- if (useSniffer)
+ if (useSniffer) {
TestRunner.addSniffer(Elements.ElementsTreeOutline.prototype, '_updateModifiedNodes', step2);
- else
+ } else {
TestRunner.deprecatedRunAfterPendingDispatches(step2);
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js
index 335966c1046..c0134e6a31e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js
@@ -28,8 +28,9 @@ ElementsTestRunner.selectReloadAndDump = function(next, node) {
}
function maybeDumpSelectedNode() {
- if (!reloaded || !selected)
+ if (!reloaded || !selected) {
return;
+ }
const selectedElement = ElementsTestRunner.firstElementsTreeOutline().selectedTreeElement;
const nodeName = (selectedElement ? selectedElement.node().nodeNameInCorrectCase() : 'null');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js
index ad3b35fd5b9..ba5f6e09363 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/ElementsTestRunner.js
@@ -53,21 +53,24 @@ ElementsTestRunner.findNode = async function(matchFunction, callback) {
let pendingRequests = 0;
async function processChildren(node) {
try {
- if (result)
+ if (result) {
return;
+ }
- if (node._childDocumentPromiseForTesting)
+ if (node._childDocumentPromiseForTesting) {
await node._childDocumentPromiseForTesting;
+ }
const pseudoElementsMap = node.pseudoElements();
const pseudoElements = pseudoElementsMap ? pseudoElementsMap.valuesArray() : [];
const children = (node.children() || []).concat(node.shadowRoots()).concat(pseudoElements);
- if (node.templateContent())
+ if (node.templateContent()) {
children.push(node.templateContent());
- else if (node.contentDocument())
+ } else if (node.contentDocument()) {
children.push(node.contentDocument());
- else if (node.importedDocument())
+ } else if (node.importedDocument()) {
children.push(node.importedDocument());
+ }
for (let i = 0; i < children.length; ++i) {
const childNode = children[i];
@@ -83,8 +86,9 @@ ElementsTestRunner.findNode = async function(matchFunction, callback) {
pendingRequests--;
}
- if (!result && !pendingRequests)
+ if (!result && !pendingRequests) {
callback(null);
+ }
}
const doc = TestRunner.domModel.existingDocument() || await TestRunner.domModel.requestDocument();
@@ -111,8 +115,9 @@ ElementsTestRunner.expandAndDumpEventListeners = function(eventListenersView, ca
for (let i = 0; i < listenerTypes.length; ++i) {
listenerTypes[i].expand();
const listenerItems = listenerTypes[i].children();
- for (let j = 0; j < listenerItems.length; ++j)
+ for (let j = 0; j < listenerItems.length; ++j) {
listenerItems[j].expand();
+ }
}
TestRunner.deprecatedRunAfterPendingDispatches(objectsExpanded);
}
@@ -120,8 +125,9 @@ ElementsTestRunner.expandAndDumpEventListeners = function(eventListenersView, ca
function objectsExpanded() {
const listenerTypes = eventListenersView._treeOutline.rootElement().children();
for (let i = 0; i < listenerTypes.length; ++i) {
- if (!listenerTypes[i].children().length)
+ if (!listenerTypes[i].children().length) {
continue;
+ }
const eventType = listenerTypes[i]._title;
TestRunner.addResult('');
TestRunner.addResult('======== ' + eventType + ' ========');
@@ -142,6 +148,15 @@ ElementsTestRunner.expandAndDumpEventListeners = function(eventListenersView, ca
}
};
+/**
+ * @param {!EventListeners.EventListenersView} eventListenersView
+ * @param {boolean=} force
+ * @return {!Promise}
+ */
+ElementsTestRunner.expandAndDumpEventListenersPromise = function(eventListenersView, force) {
+ return new Promise(resolve => ElementsTestRunner.expandAndDumpEventListeners(eventListenersView, resolve, force));
+};
+
ElementsTestRunner.inlineStyleSection = function() {
return UI.panels.elements._stylesWidget._sectionBlocks[0].sections[0];
};
@@ -158,31 +173,35 @@ ElementsTestRunner.dumpComputedStyle = function(doNotAutoExpand, printInnerText)
for (const treeElement of children) {
const property = treeElement[Elements.ComputedStyleWidget._propertySymbol];
- if (property.name === 'width' || property.name === 'height')
+ if (property.name === 'width' || property.name === 'height') {
continue;
+ }
let dumpText = '';
dumpText += text(treeElement.title.querySelector('.property-name'));
dumpText += text(treeElement.title.querySelector('.property-value'));
TestRunner.addResult(dumpText);
- if (doNotAutoExpand && !treeElement.expanded)
+ if (doNotAutoExpand && !treeElement.expanded) {
continue;
+ }
for (const trace of treeElement.children()) {
const title = trace.title;
let dumpText = '';
- if (trace.title.classList.contains('property-trace-inactive'))
+ if (trace.title.classList.contains('property-trace-inactive')) {
dumpText += 'OVERLOADED ';
+ }
dumpText += text(title.querySelector('.property-trace-value'));
dumpText += ' - ';
dumpText += text(title.querySelector('.property-trace-selector'));
const link = title.querySelector('.trace-link');
- if (link)
+ if (link) {
dumpText += ' ' + extractLinkText(link);
+ }
TestRunner.addResult(' ' + dumpText);
}
@@ -201,8 +220,9 @@ ElementsTestRunner.findComputedPropertyWithName = function(name) {
for (const treeElement of children) {
const property = treeElement[Elements.ComputedStyleWidget._propertySymbol];
- if (property.name === name)
+ if (property.name === name) {
return treeElement;
+ }
}
return null;
@@ -362,8 +382,9 @@ ElementsTestRunner.dumpRenderedMatchedStyles = function() {
for (const block of sectionBlocks) {
for (const section of block.sections) {
- if (section.element.classList.contains('hidden'))
+ if (section.element.classList.contains('hidden')) {
continue;
+ }
dumpRenderedSection(section);
}
@@ -373,8 +394,9 @@ ElementsTestRunner.dumpRenderedMatchedStyles = function() {
TestRunner.addResult(section._selectorElement.textContent + ' {');
const rootElement = section.propertiesTreeOutline.rootElement();
- for (let i = 0; i < rootElement.childCount(); ++i)
+ for (let i = 0; i < rootElement.childCount(); ++i) {
dumpRenderedProperty(rootElement.childAt(i));
+ }
TestRunner.addResult('}');
}
@@ -384,20 +406,23 @@ ElementsTestRunner.dumpRenderedMatchedStyles = function() {
text += property.nameElement.textContent;
text += ':';
- if (property.isExpandable())
+ if (property.isExpandable()) {
text += (property.expanded ? 'v' : '>');
- else
+ } else {
text += ' ';
+ }
text += property.valueElement.textContent;
- if (property.listItemElement.classList.contains('filter-match'))
+ if (property.listItemElement.classList.contains('filter-match')) {
text = 'F' + text.substring(1);
+ }
TestRunner.addResult(text);
- if (!property.expanded)
+ if (!property.expanded) {
return;
+ }
const indent = new Array(8).join(' ');
@@ -406,8 +431,9 @@ ElementsTestRunner.dumpRenderedMatchedStyles = function() {
let text = indent;
text += String.sprintf('%s: %s', childProperty.nameElement.textContent, childProperty.valueElement.textContent);
- if (childProperty.listItemElement.classList.contains('filter-match'))
+ if (childProperty.listItemElement.classList.contains('filter-match')) {
text = 'F' + text.substring(1);
+ }
TestRunner.addResult(text);
}
@@ -418,19 +444,22 @@ ElementsTestRunner.dumpSelectedElementStyles = function(
excludeComputed, excludeMatched, omitLonghands, includeSelectorGroupMarks, printInnerText) {
const sectionBlocks = UI.panels.elements._stylesWidget._sectionBlocks;
- if (!excludeComputed)
+ if (!excludeComputed) {
ElementsTestRunner.dumpComputedStyle(false /* doNotAutoExpand */, printInnerText);
+ }
for (const block of sectionBlocks) {
for (const section of block.sections) {
- if (section.style().parentRule && excludeMatched)
+ if (section.style().parentRule && excludeMatched) {
continue;
+ }
if (section.element.previousSibling && section.element.previousSibling.className === 'sidebar-separator') {
let nodeDescription = '';
- if (section.element.previousSibling.firstElementChild)
+ if (section.element.previousSibling.firstElementChild) {
nodeDescription = text(section.element.previousSibling.firstElementChild.shadowRoot.lastChild);
+ }
TestRunner.addResult('======== ' + text(section.element.previousSibling) + nodeDescription + ' ========');
}
@@ -445,8 +474,9 @@ ElementsTestRunner.dumpSelectedElementStyles = function(
};
function printStyleSection(section, omitLonghands, includeSelectorGroupMarks, printInnerText) {
- if (!section)
+ if (!section) {
return;
+ }
TestRunner.addResult(
'[expanded] ' + ((section.propertiesTreeOutline.element.classList.contains('no-affect') ? '[no-affect] ' : '')));
@@ -470,8 +500,9 @@ function printStyleSection(section, omitLonghands, includeSelectorGroupMarks, pr
TestRunner.addResult(selectorText);
ElementsTestRunner.dumpStyleTreeOutline(section.propertiesTreeOutline, (omitLonghands ? 1 : 2), printInnerText);
- if (!section._showAllButton.classList.contains('hidden'))
+ if (!section._showAllButton.classList.contains('hidden')) {
TestRunner.addResult(text(section._showAllButton));
+ }
TestRunner.addResult('');
function text(node) {
@@ -482,8 +513,9 @@ function printStyleSection(section, omitLonghands, includeSelectorGroupMarks, pr
function extractLinkText(element) {
const anchor = element.querySelector('.devtools-link');
- if (!anchor)
+ if (!anchor) {
return element.textContent;
+ }
const anchorText = anchor.textContent;
const info = Components.Linkifier._linkInfo(anchor);
@@ -499,10 +531,11 @@ function buildMarkedSelectors(element) {
let result = '';
for (let node = element.firstChild; node; node = node.nextSibling) {
- if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('selector-matches'))
+ if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('selector-matches')) {
result += '[$' + node.textContent + '$]';
- else
+ } else {
result += node.textContent;
+ }
}
return result;
@@ -559,10 +592,11 @@ ElementsTestRunner.removeFirstEventListener = function() {
ElementsTestRunner.dumpObjectPropertySectionDeep = function(section) {
function domNodeToString(node) {
- if (node)
+ if (node) {
return '\'' + node.textContent + '\'';
- else
+ } else {
return 'null';
+ }
}
function dumpTreeElementRecursively(treeElement, prefix) {
@@ -573,14 +607,16 @@ ElementsTestRunner.dumpObjectPropertySectionDeep = function(section) {
TestRunner.addResult(prefix + treeElement.title);
}
- for (let i = 0; i < treeElement.childCount(); i++)
+ for (let i = 0; i < treeElement.childCount(); i++) {
dumpTreeElementRecursively(treeElement.childAt(i), prefix + ' ');
+ }
}
const childNodes = section.propertiesTreeOutline.rootElement().children();
- for (let i = 0; i < childNodes.length; i++)
+ for (let i = 0; i < childNodes.length; i++) {
dumpTreeElementRecursively(childNodes[i], '');
+ }
};
@@ -595,8 +631,9 @@ ElementsTestRunner.getMatchedStylePropertyTreeItem = function(propertyName) {
for (const section of block.sections) {
const treeItem = ElementsTestRunner.getFirstPropertyTreeItemForSection(section, propertyName);
- if (treeItem)
+ if (treeItem) {
return treeItem;
+ }
}
}
@@ -609,8 +646,9 @@ ElementsTestRunner.getFirstPropertyTreeItemForSection = function(section, proper
for (let i = 0; i < outline.childCount(); ++i) {
const treeItem = outline.childAt(i);
- if (treeItem.name === propertyName)
+ if (treeItem.name === propertyName) {
return treeItem;
+ }
}
return null;
@@ -619,28 +657,33 @@ ElementsTestRunner.getFirstPropertyTreeItemForSection = function(section, proper
ElementsTestRunner.dumpStyleTreeOutline = function(treeItem, depth, printInnerText) {
const children = treeItem.rootElement().children();
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
ElementsTestRunner.dumpStyleTreeItem(children[i], '', depth || 2, printInnerText);
+ }
};
ElementsTestRunner.dumpStyleTreeItem = function(treeItem, prefix, depth, printInnerText) {
const textContent = printInnerText ? treeItem.listItemElement.innerText :
TestRunner.textContentWithoutStyles(treeItem.listItemElement);
- if (textContent.indexOf(' width:') !== -1 || textContent.indexOf(' height:') !== -1)
+ if (textContent.indexOf(' width:') !== -1 || textContent.indexOf(' height:') !== -1) {
return;
+ }
- if (treeItem.listItemElement.classList.contains('inherited'))
+ if (treeItem.listItemElement.classList.contains('inherited')) {
return;
+ }
let typePrefix = '';
if (treeItem.listItemElement.classList.contains('overloaded') ||
treeItem.listItemElement.classList.contains('inactive') ||
- treeItem.listItemElement.classList.contains('not-parsed-ok'))
+ treeItem.listItemElement.classList.contains('not-parsed-ok')) {
typePrefix += '/-- overloaded --/ ';
+ }
- if (treeItem.listItemElement.classList.contains('disabled'))
+ if (treeItem.listItemElement.classList.contains('disabled')) {
typePrefix += '/-- disabled --/ ';
+ }
TestRunner.addResult(prefix + typePrefix + textContent);
@@ -648,8 +691,9 @@ ElementsTestRunner.dumpStyleTreeItem = function(treeItem, prefix, depth, printIn
treeItem.expand();
const children = treeItem.children();
- for (let i = 0; children && i < children.length; ++i)
+ for (let i = 0; children && i < children.length; ++i) {
ElementsTestRunner.dumpStyleTreeItem(children[i], prefix + ' ', depth);
+ }
}
};
@@ -661,18 +705,21 @@ ElementsTestRunner.dumpElementsTree = function(rootNode, depth, resultsArray) {
function dumpMap(name, map) {
const result = [];
- for (const id of map.keys())
+ for (const id of map.keys()) {
result.push(id + '=' + map.get(id));
+ }
- if (!result.length)
+ if (!result.length) {
return '';
+ }
return name + ':[' + result.join(',') + ']';
}
function markersDataDump(treeItem) {
- if (treeItem._elementCloseTag)
+ if (treeItem._elementCloseTag) {
return '';
+ }
let markers = '';
const node = treeItem._node;
@@ -682,14 +729,16 @@ ElementsTestRunner.dumpElementsTree = function(rootNode, depth, resultsArray) {
const dump = (node._subtreeMarkerCount ? 'subtreeMarkerCount:' + node._subtreeMarkerCount : '');
if (dump) {
- if (markers)
+ if (markers) {
markers += ', ';
+ }
markers += dump;
}
- if (markers)
+ if (markers) {
markers = ' [' + markers + ']';
+ }
}
return markers;
@@ -700,10 +749,11 @@ ElementsTestRunner.dumpElementsTree = function(rootNode, depth, resultsArray) {
let expander;
if (treeItem.isExpandable()) {
- if (treeItem.expanded)
+ if (treeItem.expanded) {
expander = '- ';
- else
+ } else {
expander = '+ ';
+ }
} else {
expander = ' ';
}
@@ -722,23 +772,26 @@ ElementsTestRunner.dumpElementsTree = function(rootNode, depth, resultsArray) {
}
}
- if (resultsArray)
+ if (resultsArray) {
resultsArray.push(value);
- else
+ } else {
TestRunner.addResult(value);
+ }
}
- if (!treeItem.expanded)
+ if (!treeItem.expanded) {
return;
+ }
const children = treeItem.children();
const newPrefix = (treeItem.root ? '' : prefix + ' ');
for (let i = 0; depth && children && i < children.length; ++i) {
- if (!children[i]._elementCloseTag)
+ if (!children[i]._elementCloseTag) {
print(children[i], newPrefix, depth - 1);
- else
+ } else {
print(children[i], prefix, depth);
+ }
}
}
@@ -755,11 +808,13 @@ ElementsTestRunner.dumpDOMUpdateHighlights = function(rootNode, callback, depth)
const treeOutline = ElementsTestRunner.firstElementsTreeOutline();
print((rootNode ? treeOutline.findTreeElement(rootNode) : treeOutline.rootElement()), '', depth || 10000);
- if (!hasHighlights)
+ if (!hasHighlights) {
TestRunner.addResult('<No highlights>');
+ }
- if (callback)
+ if (callback) {
callback();
+ }
}
function print(treeItem, prefix, depth) {
@@ -786,15 +841,17 @@ ElementsTestRunner.dumpDOMUpdateHighlights = function(rootNode, callback, depth)
}
}
- if (!treeItem.expanded)
+ if (!treeItem.expanded) {
return;
+ }
const children = treeItem.children();
const newPrefix = (treeItem.root ? '' : prefix + ' ');
for (let i = 0; depth && children && i < children.length; ++i) {
- if (!children[i]._elementCloseTag)
+ if (!children[i]._elementCloseTag) {
print(children[i], newPrefix, depth - 1);
+ }
}
}
};
@@ -841,39 +898,46 @@ ElementsTestRunner.expandAndDump = function() {
};
ElementsTestRunner.dumpDOMAgentTree = function(node) {
- if (!TestRunner.domModel._document)
+ if (!TestRunner.domModel._document) {
return;
+ }
function dump(node, prefix) {
TestRunner.addResult(prefix + node.nodeName());
prefix = prefix + ' ';
- if (node.templateContent())
+ if (node.templateContent()) {
dump(node.templateContent(), prefix);
+ }
- if (node.contentDocument())
+ if (node.contentDocument()) {
dump(node.contentDocument(), prefix);
+ }
- if (node.importedDocument())
+ if (node.importedDocument()) {
dump(node.importedDocument(), prefix);
+ }
const shadowRoots = node.shadowRoots();
- for (let i = 0; i < shadowRoots.length; ++i)
+ for (let i = 0; i < shadowRoots.length; ++i) {
dump(shadowRoots[i], prefix);
+ }
const children = node.children();
- for (let i = 0; children && i < children.length; ++i)
+ for (let i = 0; children && i < children.length; ++i) {
dump(children[i], prefix);
+ }
}
dump(node, '');
};
ElementsTestRunner.rangeText = function(range) {
- if (!range)
+ if (!range) {
return '[undefined-undefined]';
+ }
return '[' + range.startLine + ':' + range.startColumn + '-' + range.endLine + ':' + range.endColumn + ']';
};
@@ -941,31 +1005,36 @@ ElementsTestRunner.generateUndoTest = function(testBody) {
const indent = ' ';
ElementsTestRunner.dumpRulesArray = function(rules, currentIndent) {
- if (!rules)
+ if (!rules) {
return;
+ }
currentIndent = currentIndent || '';
- for (let i = 0; i < rules.length; ++i)
+ for (let i = 0; i < rules.length; ++i) {
ElementsTestRunner.dumpRule(rules[i], currentIndent);
+ }
};
ElementsTestRunner.dumpRuleMatchesArray = function(matches, currentIndent) {
- if (!matches)
+ if (!matches) {
return;
+ }
currentIndent = currentIndent || '';
- for (let i = 0; i < matches.length; ++i)
+ for (let i = 0; i < matches.length; ++i) {
ElementsTestRunner.dumpRule(matches[i].rule, currentIndent);
+ }
};
ElementsTestRunner.dumpRule = function(rule, currentIndent) {
function selectorRange() {
const selectors = rule.selectorList.selectors;
- if (!selectors || !selectors[0].range)
+ if (!selectors || !selectors[0].range) {
return '';
+ }
const ranges = [];
@@ -1071,8 +1140,9 @@ ElementsTestRunner.dumpCSSStyleDeclaration = function(style, currentIndent) {
};
ElementsTestRunner.dumpBreadcrumb = function(message) {
- if (message)
+ if (message) {
TestRunner.addResult(message + ':');
+ }
const result = [];
const crumbs = UI.panels.elements._breadcrumbs.crumbsElement;
@@ -1090,8 +1160,9 @@ ElementsTestRunner.matchingSelectors = function(matchedStyles, rule) {
const selectors = [];
const matchingSelectors = matchedStyles.matchingSelectors(rule);
- for (let i = 0; i < matchingSelectors.length; ++i)
+ for (let i = 0; i < matchingSelectors.length; ++i) {
selectors.push(rule.selectors[matchingSelectors[i]].text);
+ }
return '[' + selectors.join(', ') + ']';
};
@@ -1113,8 +1184,9 @@ ElementsTestRunner.addNewRule = function(selector, callback) {
function onBlankSection(selector, callback) {
const section = ElementsTestRunner.firstMatchedStyleSection();
- if (typeof selector === 'string')
+ if (typeof selector === 'string') {
section._selectorElement.textContent = selector;
+ }
section._selectorElement.dispatchEvent(TestRunner.createKeyEvent('Enter'));
ElementsTestRunner.waitForSelectorCommitted(callback.bind(null, section));
@@ -1139,8 +1211,9 @@ ElementsTestRunner.dumpInspectorDistanceJSON = function(idValue, callback) {
if (!info) {
TestRunner.addResult(`${idValue}: No distance info`);
} else {
- if (info['style'])
+ if (info['style']) {
info['style'] = '<style data>';
+ }
TestRunner.addResult(idValue + JSON.stringify(info, null, 2));
}
callback();
@@ -1154,8 +1227,9 @@ ElementsTestRunner.dumpInspectorHighlightStyleJSON = async function(idValue) {
if (!info) {
TestRunner.addResult(`${idValue}: No style info`);
} else {
- if (info['font-family'])
+ if (info['font-family']) {
info['font-family'] = '<font-family value>';
+ }
TestRunner.addResult(idValue + JSON.stringify(info, null, 2));
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js
index 485eba4cede..adf3f7d009a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/SetOuterHTMLTestRunner.js
@@ -28,8 +28,9 @@ ElementsTestRunner.setUpTestSuite = function(next) {
for (const key in SDK.DOMModel.Events) {
const eventName = SDK.DOMModel.Events[key];
- if (eventName === SDK.DOMModel.Events.MarkersChanged || eventName === SDK.DOMModel.Events.DOMMutated)
+ if (eventName === SDK.DOMModel.Events.MarkersChanged || eventName === SDK.DOMModel.Events.DOMMutated) {
continue;
+ }
TestRunner.domModel.addEventListener(
eventName, ElementsTestRunner.recordEvent.bind(ElementsTestRunner, eventName));
@@ -40,15 +41,17 @@ ElementsTestRunner.setUpTestSuite = function(next) {
};
ElementsTestRunner.recordEvent = function(eventName, event) {
- if (!event.data)
+ if (!event.data) {
return;
+ }
const node = event.data.node || event.data;
const parent = event.data.parent;
for (let currentNode = parent || node; currentNode; currentNode = currentNode.parentNode) {
- if (currentNode.getAttribute('id') === 'output')
+ if (currentNode.getAttribute('id') === 'output') {
return;
+ }
}
ElementsTestRunner.events.push('Event ' + eventName.toString() + ': ' + node.nodeName());
@@ -94,8 +97,9 @@ ElementsTestRunner._dumpOuterHTML = async function(last, next) {
TestRunner.addResult('Wrapper identity: ' + result.value);
ElementsTestRunner.events.sort();
- for (let i = 0; i < ElementsTestRunner.events.length; ++i)
+ for (let i = 0; i < ElementsTestRunner.events.length; ++i) {
TestRunner.addResult(ElementsTestRunner.events[i]);
+ }
ElementsTestRunner.events = [];
const text = await TestRunner.DOMAgent.getOuterHTML(ElementsTestRunner.containerId);
@@ -103,8 +107,9 @@ ElementsTestRunner._dumpOuterHTML = async function(last, next) {
TestRunner.addResult(text);
TestRunner.addResult('==========>8==========');
- if (last)
+ if (last) {
TestRunner.addResult('\n\n\n');
+ }
next();
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js
index 7e7e946317c..49eb5fff3fc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements_test_runner/StylesUpdateLinksTestRunner.js
@@ -14,8 +14,9 @@ function flattenRuleRanges(rule) {
for (let i = 0; i < medias.length; ++i) {
const media = medias[i];
- if (!media.range)
+ if (!media.range) {
continue;
+ }
ranges.push({range: media.range, name: 'media #' + i});
}
@@ -23,14 +24,16 @@ function flattenRuleRanges(rule) {
for (let i = 0; i < rule.selectors.length; ++i) {
const selector = rule.selectors[i];
- if (!selector.range)
+ if (!selector.range) {
continue;
+ }
ranges.push({range: selector.range, name: 'selector #' + i});
}
- if (rule.style.range)
+ if (rule.style.range) {
ranges.push({range: rule.style.range, name: 'style range'});
+ }
const properties = rule.style.allProperties();
@@ -38,8 +41,9 @@ function flattenRuleRanges(rule) {
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
- if (!property.range)
+ if (!property.range) {
continue;
+ }
ranges.push({range: property.range, name: 'property >>' + property.text + '<<'});
}
@@ -120,8 +124,9 @@ ElementsTestRunner.getMatchedRules = function() {
for (const section of block.sections) {
const rule = section.style().parentRule;
- if (rule)
+ if (rule) {
rules.push(rule);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp
index 053c7c38ee9..2a2c22605d3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulated_devices/emulated_devices_strings.grdp
@@ -4,99 +4,99 @@
Laptop with MDPI screen
</message>
<message name="IDS_DEVTOOLS_079a3d134d2387adc52b2b3895f85e55" desc="Title of the iPhone X device">
- iPhone X
+ <ph name="LOCKED_1">iPhone X</ph>
</message>
<message name="IDS_DEVTOOLS_0d1160fe394d87ddbc2ca8e7cc25379d" desc="Title of the Laptop with touch device">
Laptop with touch
</message>
<message name="IDS_DEVTOOLS_0e5aeadd53726e96d7d9faa671b423ae" desc="Title of the Kindle Fire HDX device">
- Kindle Fire HDX
+ <ph name="LOCKED_1">Kindle Fire HDX</ph>
</message>
<message name="IDS_DEVTOOLS_1b9018182a49e16ba85bb095f224867c" desc="Title of the iPad device">
- iPad
+ <ph name="LOCKED_1">iPad</ph>
</message>
<message name="IDS_DEVTOOLS_2235bd527cc1684230b1db146c570a9d" desc="Title of the Pixel 2 device">
- Pixel 2
+ <ph name="LOCKED_1">Pixel 2</ph>
</message>
<message name="IDS_DEVTOOLS_2c17ed2506add59c15ea763801cfafb1" desc="Title of the Nexus 6 device">
- Nexus 6
+ <ph name="LOCKED_1">Nexus 6</ph>
</message>
<message name="IDS_DEVTOOLS_2d1fbe61c136940101281ec1df805c01" desc="Title of the Nexus 5 device">
- Nexus 5
+ <ph name="LOCKED_1">Nexus 5</ph>
</message>
<message name="IDS_DEVTOOLS_2d9a25096b47a022c95787ab90308d6b" desc="Title of the LG Optimus L70 device">
- LG Optimus L70
+ <ph name="LOCKED_1">LG Optimus L70</ph>
</message>
<message name="IDS_DEVTOOLS_4a321c67ad4bac0f3386f5e257b1fba3" desc="Title of the Laptop with HiDPI screen device">
Laptop with HiDPI screen
</message>
<message name="IDS_DEVTOOLS_6247fa438881677e5f910b89db1974a7" desc="Title of the Nokia N9 device">
- Nokia N9
+ <ph name="LOCKED_1">Nokia N9</ph>
</message>
<message name="IDS_DEVTOOLS_659810deafc0279869114daf8446ef4a" desc="Title of the Nexus 10 device">
- Nexus 10
+ <ph name="LOCKED_1">Nexus 10</ph>
</message>
<message name="IDS_DEVTOOLS_6d9131a4a569108e7d19038b27111c86" desc="Title of the Nexus 5X device">
- Nexus 5X
+ <ph name="LOCKED_1">Nexus 5X</ph>
</message>
<message name="IDS_DEVTOOLS_71e3580e3c3a03f17798ebccaad9e6cb" desc="Title of the Nexus 7 device">
- Nexus 7
+ <ph name="LOCKED_1">Nexus 7</ph>
</message>
<message name="IDS_DEVTOOLS_71f859515e31ad9bb417977247315f0a" desc="Title of the iPad Pro device">
- iPad Pro
+ <ph name="LOCKED_1">iPad Pro</ph>
</message>
<message name="IDS_DEVTOOLS_76c4064f51952f873baa0f9a201b49a3" desc="Title of the Nokia Lumia 520 device">
- Nokia Lumia 520
+ <ph name="LOCKED_1">Nokia Lumia 520</ph>
</message>
<message name="IDS_DEVTOOLS_8be08fbcf1f787159e451a97a7c1cc90" desc="Title of the iPhone 6/7/8 Plus device">
- iPhone 6/7/8 Plus
+ <ph name="LOCKED_1">iPhone 6/7/8 Plus</ph>
</message>
<message name="IDS_DEVTOOLS_8d0c6a99bcfbb75724c123476d683d3f" desc="Title of the iPhone 4 device">
- iPhone 4
+ <ph name="LOCKED_1">iPhone 4</ph>
</message>
<message name="IDS_DEVTOOLS_99d1a0f994cdce14eea8b6ae823d5a76" desc="Title of the Galaxy S III device">
- Galaxy S III
+ <ph name="LOCKED_1">Galaxy S III</ph>
</message>
<message name="IDS_DEVTOOLS_a75624548994321c1cc7173b9933438b" desc="Title of the Microsoft Lumia 550 device">
- Microsoft Lumia 550
+ <ph name="LOCKED_1">Microsoft Lumia 550</ph>
</message>
<message name="IDS_DEVTOOLS_aa5fa1bdadb078da054c34752031a5e9" desc="Title of the iPhone 6/7/8 device">
- iPhone 6/7/8
+ <ph name="LOCKED_1">iPhone 6/7/8</ph>
</message>
<message name="IDS_DEVTOOLS_b9e5554cdd9d9f2d3df1f30914b617c2" desc="Title of the Galaxy Note 3 device">
- Galaxy Note 3
+ <ph name="LOCKED_1">Galaxy Note 3</ph>
</message>
<message name="IDS_DEVTOOLS_be6a9d69eff86af39e5a73345c585da6" desc="Title of the iPad Mini device">
- iPad Mini
+ <ph name="LOCKED_1">iPad Mini</ph>
</message>
<message name="IDS_DEVTOOLS_c99b8431589c0273278e87ebf44a7fd6" desc="Title of the iPhone 5/SE device">
- iPhone 5/SE
+ <ph name="LOCKED_1">iPhone 5/SE</ph>
</message>
<message name="IDS_DEVTOOLS_cc810fb8b8bc7c7d6a8327f0e7b2aead" desc="Title of the Nexus 6P device">
- Nexus 6P
+ <ph name="LOCKED_1">Nexus 6P</ph>
</message>
<message name="IDS_DEVTOOLS_d4f2f5453f28c5fd35c68f52e4da07cd" desc="Title of the BlackBerry Z30 device">
- BlackBerry Z30
+ <ph name="LOCKED_1">BlackBerry Z30</ph>
</message>
<message name="IDS_DEVTOOLS_d6162eb3dd4dc5a9bc67222e24f19b25" desc="Title of the Nexus 4 device">
- Nexus 4
+ <ph name="LOCKED_1">Nexus 4</ph>
</message>
<message name="IDS_DEVTOOLS_d8860bf736e83cfb5c13ee82a8f61a43" desc="Title of the Microsoft Lumia 950 device">
- Microsoft Lumia 950
+ <ph name="LOCKED_1">Microsoft Lumia 950</ph>
</message>
<message name="IDS_DEVTOOLS_dfd6e576e036db4f857c8c03c977d975" desc="Title of the Galaxy Note II device">
- Galaxy Note II
+ <ph name="LOCKED_1">Galaxy Note II</ph>
</message>
<message name="IDS_DEVTOOLS_e0261d2f1730ebff89bbde9a4bc74ac5" desc="Title of the JioPhone 2 device">
- JioPhone 2
+ <ph name="LOCKED_1">JioPhone 2</ph>
</message>
<message name="IDS_DEVTOOLS_e770076f957c87605ff906d0ed2c4b52" desc="Title of the Blackberry PlayBook device">
- Blackberry PlayBook
+ <ph name="LOCKED_1">Blackberry PlayBook</ph>
</message>
<message name="IDS_DEVTOOLS_eb850446088fbc75e974788cc2b39caa" desc="Title of the Pixel 2 XL device">
- Pixel 2 XL
+ <ph name="LOCKED_1">Pixel 2 XL</ph>
</message>
<message name="IDS_DEVTOOLS_f8896f769d62b6102e48039154c4ca5e" desc="Title of the Galaxy S5 device">
- Galaxy S5
+ <ph name="LOCKED_1">Galaxy S5</ph>
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js
index 80754b5ec6d..740d45a511d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js
@@ -15,8 +15,9 @@ Emulation.AdvancedApp = class {
* @return {!Emulation.AdvancedApp}
*/
static _instance() {
- if (!Emulation.AdvancedApp._appInstance)
+ if (!Emulation.AdvancedApp._appInstance) {
Emulation.AdvancedApp._appInstance = new Emulation.AdvancedApp();
+ }
return Emulation.AdvancedApp._appInstance;
}
@@ -56,11 +57,13 @@ Emulation.AdvancedApp = class {
* @param {!Common.Event} event
*/
_openToolboxWindow(event) {
- if (/** @type {string} */ (event.data.to) !== Components.DockController.State.Undocked)
+ if (/** @type {string} */ (event.data.to) !== Components.DockController.State.Undocked) {
return;
+ }
- if (this._toolboxWindow)
+ if (this._toolboxWindow) {
return;
+ }
const url = window.location.href.replace('devtools_app.html', 'toolbox.html');
this._toolboxWindow = window.open(url, undefined);
@@ -82,10 +85,11 @@ Emulation.AdvancedApp = class {
}
_updateDeviceModeView() {
- if (this._isDocked())
+ if (this._isDocked()) {
this._rootSplitWidget.setMainWidget(this._deviceModeView);
- else if (this._toolboxRootView)
+ } else if (this._toolboxRootView) {
this._deviceModeView.show(this._toolboxRootView.element);
+ }
}
/**
@@ -125,8 +129,9 @@ Emulation.AdvancedApp = class {
*/
_onAfterDockSideChange(event) {
// We may get here on the first dock side change while loading without BeforeDockSideChange.
- if (!this._changingDockSide)
+ if (!this._changingDockSide) {
return;
+ }
if (/** @type {string} */ (event.data.from) === Components.DockController.State.Undocked) {
// Restore docked layout in case of smooth transition.
this._updateForDocked(/** @type {string} */ (event.data.to));
@@ -169,16 +174,19 @@ Emulation.AdvancedApp = class {
* @param {!Common.Event} event
*/
_onSetInspectedPageBounds(event) {
- if (this._changingDockSide)
+ if (this._changingDockSide) {
return;
+ }
const window = this._inspectedPagePlaceholder.element.window();
- if (!window.innerWidth || !window.innerHeight)
+ if (!window.innerWidth || !window.innerHeight) {
return;
- if (!this._inspectedPagePlaceholder.isShowing())
+ }
+ if (!this._inspectedPagePlaceholder.isShowing()) {
return;
+ }
const bounds = /** @type {{x: number, y: number, width: number, height: number}} */ (event.data);
console.timeStamp('AdvancedApp.setInspectedPageBounds');
- InspectorFrontendHost.setInspectedPageBounds(bounds);
+ Host.InspectorFrontendHost.setInspectedPageBounds(bounds);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
index 27510aac0ed..7402b091cb1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeModel.js
@@ -20,22 +20,27 @@ Emulation.DeviceModeModel = class extends Common.Object {
this._scaleSetting = Common.settings.createSetting('emulation.deviceScale', 1);
// We've used to allow zero before.
- if (!this._scaleSetting.get())
+ if (!this._scaleSetting.get()) {
this._scaleSetting.set(1);
+ }
this._scaleSetting.addChangeListener(this._scaleSettingChanged, this);
this._widthSetting = Common.settings.createSetting('emulation.deviceWidth', 400);
- if (this._widthSetting.get() < Emulation.DeviceModeModel.MinDeviceSize)
+ if (this._widthSetting.get() < Emulation.DeviceModeModel.MinDeviceSize) {
this._widthSetting.set(Emulation.DeviceModeModel.MinDeviceSize);
- if (this._widthSetting.get() > Emulation.DeviceModeModel.MaxDeviceSize)
+ }
+ if (this._widthSetting.get() > Emulation.DeviceModeModel.MaxDeviceSize) {
this._widthSetting.set(Emulation.DeviceModeModel.MaxDeviceSize);
+ }
this._widthSetting.addChangeListener(this._widthSettingChanged, this);
this._heightSetting = Common.settings.createSetting('emulation.deviceHeight', 0);
- if (this._heightSetting.get() && this._heightSetting.get() < Emulation.DeviceModeModel.MinDeviceSize)
+ if (this._heightSetting.get() && this._heightSetting.get() < Emulation.DeviceModeModel.MinDeviceSize) {
this._heightSetting.set(Emulation.DeviceModeModel.MinDeviceSize);
- if (this._heightSetting.get() > Emulation.DeviceModeModel.MaxDeviceSize)
+ }
+ if (this._heightSetting.get() > Emulation.DeviceModeModel.MaxDeviceSize) {
this._heightSetting.set(Emulation.DeviceModeModel.MaxDeviceSize);
+ }
this._heightSetting.addChangeListener(this._heightSettingChanged, this);
this._uaSetting = Common.settings.createSetting('emulation.deviceUA', Emulation.DeviceModeModel.UA.Mobile);
@@ -75,14 +80,15 @@ Emulation.DeviceModeModel = class extends Common.Object {
let valid = false;
let errorMessage;
- if (!/^[\d]+$/.test(value))
+ if (!/^[\d]+$/.test(value)) {
errorMessage = ls`Width must be a number.`;
- else if (value > Emulation.DeviceModeModel.MaxDeviceSize)
+ } else if (value > Emulation.DeviceModeModel.MaxDeviceSize) {
errorMessage = ls`Width must be less than or equal to ${Emulation.DeviceModeModel.MaxDeviceSize}.`;
- else if (value < Emulation.DeviceModeModel.MinDeviceSize)
+ } else if (value < Emulation.DeviceModeModel.MinDeviceSize) {
errorMessage = ls`Width must be greater than or equal to ${Emulation.DeviceModeModel.MinDeviceSize}.`;
- else
+ } else {
valid = true;
+ }
return {valid, errorMessage};
}
@@ -95,14 +101,15 @@ Emulation.DeviceModeModel = class extends Common.Object {
let valid = false;
let errorMessage;
- if (!/^[\d]+$/.test(value))
+ if (!/^[\d]+$/.test(value)) {
errorMessage = ls`Height must be a number.`;
- else if (value > Emulation.DeviceModeModel.MaxDeviceSize)
+ } else if (value > Emulation.DeviceModeModel.MaxDeviceSize) {
errorMessage = ls`Height must be less than or equal to ${Emulation.DeviceModeModel.MaxDeviceSize}.`;
- else if (value < Emulation.DeviceModeModel.MinDeviceSize)
+ } else if (value < Emulation.DeviceModeModel.MinDeviceSize) {
errorMessage = ls`Height must be greater than or equal to ${Emulation.DeviceModeModel.MinDeviceSize}.`;
- else
+ } else {
valid = true;
+ }
return {valid, errorMessage};
}
@@ -114,10 +121,11 @@ Emulation.DeviceModeModel = class extends Common.Object {
static scaleValidator(value) {
let valid = false;
let errorMessage;
+ const parsedValue = Number(value.trim());
if (!value) {
valid = true;
- } else if (!/^[\d]+(\.\d+)?|\.\d+$/.test(value)) {
+ } else if (Number.isNaN(parsedValue)) {
errorMessage = ls`Device pixel ratio must be a number or blank.`;
} else if (value > Emulation.DeviceModeModel.MaxDeviceScaleFactor) {
errorMessage =
@@ -169,8 +177,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
this._mode = null;
}
- if (type !== Emulation.DeviceModeModel.Type.None)
+ if (type !== Emulation.DeviceModeModel.Type.None) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.DeviceModeEnabled);
+ }
this._calculateAndEmulate(resetPageScaleFactor);
}
@@ -198,8 +207,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
setHeight(height) {
const max = Math.min(Emulation.DeviceModeModel.MaxDeviceSize, this._preferredScaledHeight());
height = Math.max(Math.min(height, max), 0);
- if (height === this._preferredScaledHeight())
+ if (height === this._preferredScaledHeight()) {
height = 0;
+ }
this._heightSetting.set(height);
}
@@ -406,8 +416,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
* @param {!SDK.EmulationModel} emulationModel
*/
modelRemoved(emulationModel) {
- if (this._emulationModel === emulationModel)
+ if (this._emulationModel === emulationModel) {
this._emulationModel = null;
+ }
}
/**
@@ -460,11 +471,13 @@ Emulation.DeviceModeModel = class extends Common.Object {
*/
_currentOutline() {
let outline = new UI.Insets(0, 0, 0, 0);
- if (this._type !== Emulation.DeviceModeModel.Type.Device)
+ if (this._type !== Emulation.DeviceModeModel.Type.Device) {
return outline;
+ }
const orientation = this._device.orientationByName(this._mode.orientation);
- if (this._deviceOutlineSetting.get())
+ if (this._deviceOutlineSetting.get()) {
outline = orientation.outlineInsets || outline;
+ }
return outline;
}
@@ -472,8 +485,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
* @return {!UI.Insets}
*/
_currentInsets() {
- if (this._type !== Emulation.DeviceModeModel.Type.Device)
+ if (this._type !== Emulation.DeviceModeModel.Type.Device) {
return new UI.Insets(0, 0, 0, 0);
+ }
return this._mode.insets;
}
@@ -481,8 +495,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
* @param {boolean} resetPageScaleFactor
*/
_calculateAndEmulate(resetPageScaleFactor) {
- if (!this._emulationModel)
+ if (!this._emulationModel) {
this._onModelAvailable = this._calculateAndEmulate.bind(this, resetPageScaleFactor);
+ }
const mobile = this._isMobile();
if (this._type === Emulation.DeviceModeModel.Type.Device) {
const orientation = this._device.orientationByName(this._mode.orientation);
@@ -514,11 +529,13 @@ Emulation.DeviceModeModel = class extends Common.Object {
this._applyTouch(false, false);
} else if (this._type === Emulation.DeviceModeModel.Type.Responsive) {
let screenWidth = this._widthSetting.get();
- if (!screenWidth || screenWidth > this._preferredScaledWidth())
+ if (!screenWidth || screenWidth > this._preferredScaledWidth()) {
screenWidth = this._preferredScaledWidth();
+ }
let screenHeight = this._heightSetting.get();
- if (!screenHeight || screenHeight > this._preferredScaledHeight())
+ if (!screenHeight || screenHeight > this._preferredScaledHeight()) {
screenHeight = this._preferredScaledHeight();
+ }
const defaultDeviceScaleFactor = mobile ? Emulation.DeviceModeModel.defaultMobileScaleFactor : 0;
this._fitScale = this._calculateFitScale(this._widthSetting.get(), this._heightSetting.get());
this._appliedUserAgentType = this._uaSetting.get();
@@ -535,8 +552,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
this._uaSetting.get() === Emulation.DeviceModeModel.UA.Mobile);
}
const overlayModel = this._emulationModel ? this._emulationModel.overlayModel() : null;
- if (overlayModel)
+ if (overlayModel) {
overlayModel.setShowViewportSizeOnResize(this._type === Emulation.DeviceModeModel.Type.None);
+ }
this.dispatchEventToListeners(Emulation.DeviceModeModel.Events.Updated);
}
@@ -560,12 +578,15 @@ Emulation.DeviceModeModel = class extends Common.Object {
let sharpScale = scale;
while (sharpScale > scale * 0.7) {
let sharp = true;
- if (screenWidth)
+ if (screenWidth) {
sharp = sharp && Number.isInteger((screenWidth - insetsWidth) * sharpScale / 100);
- if (screenHeight)
+ }
+ if (screenHeight) {
sharp = sharp && Number.isInteger((screenHeight - insetsHeight) * sharpScale / 100);
- if (sharp)
+ }
+ if (sharp) {
return sharpScale / 100;
+ }
sharpScale -= 1;
}
return scale / 100;
@@ -646,11 +667,13 @@ Emulation.DeviceModeModel = class extends Common.Object {
pageHeight = 0;
}
- if (!this._emulationModel)
+ if (!this._emulationModel) {
return;
+ }
- if (resetPageScaleFactor)
+ if (resetPageScaleFactor) {
this._emulationModel.resetPageScaleFactor();
+ }
if (pageWidth || pageHeight || mobile || deviceScaleFactor || scale !== 1 || screenOrientation) {
const metrics = {
width: pageWidth,
@@ -664,8 +687,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
positionY: positionY,
dontSetVisibleSize: true
};
- if (screenOrientation)
+ if (screenOrientation) {
metrics.screenOrientation = {type: screenOrientation, angle: screenOrientationAngle};
+ }
this._emulationModel.emulateDevice(metrics);
} else {
this._emulationModel.emulateDevice(null);
@@ -680,19 +704,22 @@ Emulation.DeviceModeModel = class extends Common.Object {
async captureScreenshot(fullSize, clip) {
const screenCaptureModel =
this._emulationModel ? this._emulationModel.target().model(SDK.ScreenCaptureModel) : null;
- if (!screenCaptureModel)
+ if (!screenCaptureModel) {
return null;
+ }
const overlayModel = this._emulationModel ? this._emulationModel.overlayModel() : null;
- if (overlayModel)
+ if (overlayModel) {
overlayModel.setShowViewportSizeOnResize(false);
+ }
// Emulate full size device if necessary.
let deviceMetrics;
if (fullSize) {
const metrics = await screenCaptureModel.fetchLayoutMetrics();
- if (!metrics)
+ if (!metrics) {
return null;
+ }
// Cap the height to not hit the GPU limit.
const contentHeight = Math.min((1 << 14) / this._appliedDeviceScaleFactor, metrics.contentHeight);
@@ -739,8 +766,9 @@ Emulation.DeviceModeModel = class extends Common.Object {
_applyTouch(touchEnabled, mobile) {
this._touchEnabled = touchEnabled;
this._touchMobile = mobile;
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.emulateTouch(touchEnabled, mobile);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
index 00ce4a2d847..0d472806ce4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
@@ -117,8 +117,9 @@ Emulation.DeviceModeToolbar = class {
* @return {{valid: boolean, errorMessage: (string|undefined)}}
*/
function validateHeight(value) {
- if (!value)
+ if (!value) {
return {valid: true};
+ }
return Emulation.DeviceModeModel.heightValidator(value);
}
}
@@ -307,7 +308,7 @@ Emulation.DeviceModeToolbar = class {
contextMenu.appendItemsAtLocation('deviceModeMenu');
contextMenu.footerSection().appendItem(Common.UIString('Reset to defaults'), this._reset.bind(this));
contextMenu.footerSection().appendItem(
- ls`Close DevTools`, InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost));
+ ls`Close DevTools`, Host.InspectorFrontendHost.closeWindow.bind(Host.InspectorFrontendHost));
/**
* @param {!UI.ContextMenuSection} section
@@ -317,8 +318,9 @@ Emulation.DeviceModeToolbar = class {
* @param {boolean=} disabled
*/
function appendToggleItem(section, setting, title1, title2, disabled) {
- if (typeof disabled === 'undefined')
+ if (typeof disabled === 'undefined') {
disabled = model.type() === Emulation.DeviceModeModel.Type.None;
+ }
section.appendItem(setting.get() ? title1 : title2, setting.set.bind(setting, !setting.get()), disabled);
}
}
@@ -407,8 +409,9 @@ Emulation.DeviceModeToolbar = class {
* @this {Emulation.DeviceModeToolbar}
*/
function appendGroup(devices) {
- if (!devices.length)
+ if (!devices.length) {
return;
+ }
const section = contextMenu.section();
for (const device of devices) {
section.appendCheckboxItem(
@@ -422,15 +425,17 @@ Emulation.DeviceModeToolbar = class {
*/
_deviceListChanged() {
const device = this._model.device();
- if (!device)
+ if (!device) {
return;
+ }
const devices = this._allDevices();
if (devices.indexOf(device) === -1) {
- if (devices.length)
+ if (devices.length) {
this._emulateDevice(devices[0]);
- else
+ } else {
this._model.emulate(Emulation.DeviceModeModel.Type.Responsive, null, null);
+ }
}
}
@@ -481,13 +486,15 @@ Emulation.DeviceModeToolbar = class {
*/
function addOrientation(orientation, title) {
const modes = device.modesForOrientation(orientation);
- if (!modes.length)
+ if (!modes.length) {
return;
+ }
if (modes.length === 1) {
addMode(modes[0], title);
} else {
- for (let index = 0; index < modes.length; index++)
+ for (let index = 0; index < modes.length; index++) {
addMode(modes[index], title + ' \u2013 ' + modes[index].title);
+ }
}
}
@@ -556,10 +563,12 @@ Emulation.DeviceModeToolbar = class {
}
let deviceItemTitle = Common.UIString('None');
- if (this._model.type() === Emulation.DeviceModeModel.Type.Responsive)
+ if (this._model.type() === Emulation.DeviceModeModel.Type.Responsive) {
deviceItemTitle = Common.UIString('Responsive');
- if (this._model.type() === Emulation.DeviceModeModel.Type.Device)
+ }
+ if (this._model.type() === Emulation.DeviceModeModel.Type.Device) {
deviceItemTitle = this._model.device().title;
+ }
this._deviceSelectItem.setText(deviceItemTitle);
if (this._model.device() !== this._cachedModelDevice) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js
index 2691b18ff93..1ea2b779a2d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeView.js
@@ -116,10 +116,12 @@ Emulation.DeviceModeView = class extends UI.VBox {
const resizer = new UI.ResizerWidget();
resizer.addElement(element);
let cursor = widthFactor ? 'ew-resize' : 'ns-resize';
- if (widthFactor * heightFactor > 0)
+ if (widthFactor * heightFactor > 0) {
cursor = 'nwse-resize';
- if (widthFactor * heightFactor < 0)
+ }
+ if (widthFactor * heightFactor < 0) {
cursor = 'nesw-resize';
+ }
resizer.setCursor(cursor);
resizer.addEventListener(UI.ResizerWidget.Events.ResizeStart, this._onResizeStart, this);
resizer.addEventListener(
@@ -143,8 +145,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_onResizeUpdate(widthFactor, heightFactor, event) {
- if (event.data.shiftKey !== !!this._slowPositionStart)
+ if (event.data.shiftKey !== !!this._slowPositionStart) {
this._slowPositionStart = event.data.shiftKey ? {x: event.data.currentX, y: event.data.currentY} : null;
+ }
let cssOffsetX = event.data.currentX - event.data.startX;
let cssOffsetY = event.data.currentY - event.data.startY;
@@ -159,16 +162,19 @@ Emulation.DeviceModeView = class extends UI.VBox {
const dipOffsetX = cssOffsetX * UI.zoomManager.zoomFactor();
let newWidth = this._resizeStart.width + dipOffsetX * widthFactor;
newWidth = Math.round(newWidth / this._model.scale());
- if (newWidth >= Emulation.DeviceModeModel.MinDeviceSize && newWidth <= Emulation.DeviceModeModel.MaxDeviceSize)
+ if (newWidth >= Emulation.DeviceModeModel.MinDeviceSize && newWidth <= Emulation.DeviceModeModel.MaxDeviceSize) {
this._model.setWidth(newWidth);
+ }
}
if (heightFactor) {
const dipOffsetY = cssOffsetY * UI.zoomManager.zoomFactor();
let newHeight = this._resizeStart.height + dipOffsetY * heightFactor;
newHeight = Math.round(newHeight / this._model.scale());
- if (newHeight >= Emulation.DeviceModeModel.MinDeviceSize && newHeight <= Emulation.DeviceModeModel.MaxDeviceSize)
+ if (newHeight >= Emulation.DeviceModeModel.MinDeviceSize &&
+ newHeight <= Emulation.DeviceModeModel.MaxDeviceSize) {
this._model.setHeight(newHeight);
+ }
}
}
@@ -192,8 +198,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
element.style.height = rect.height + 'px';
}
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
const zoomFactor = UI.zoomManager.zoomFactor();
let callDoResize = false;
@@ -237,10 +244,11 @@ Emulation.DeviceModeView = class extends UI.VBox {
const mediaInspectorVisible =
this._showMediaInspectorSetting.get() && this._model.type() !== Emulation.DeviceModeModel.Type.None;
if (mediaInspectorVisible !== this._cachedMediaInspectorVisible) {
- if (mediaInspectorVisible)
+ if (mediaInspectorVisible) {
this._mediaInspector.show(this._mediaInspectorContainer);
- else
+ } else {
this._mediaInspector.detach();
+ }
contentAreaResized = true;
callDoResize = true;
this._cachedMediaInspectorVisible = mediaInspectorVisible;
@@ -263,8 +271,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
if (this._model.scale() !== this._cachedScale) {
updateRulers = true;
callDoResize = true;
- for (const block of this._presetBlocks)
+ for (const block of this._presetBlocks) {
block.style.width = block.__width * this._model.scale() + 'px';
+ }
this._cachedScale = this._model.scale();
}
@@ -272,8 +281,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
this._loadImage(this._screenImage, this._model.screenImage());
this._loadImage(this._outlineImage, this._model.outlineImage());
this._mediaInspector.setAxisTransform(this._model.scale());
- if (callDoResize)
+ if (callDoResize) {
this.doResize();
+ }
if (updateRulers) {
this._topRuler.render(this._model.scale());
this._leftRuler.render(this._model.scale());
@@ -284,8 +294,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
this._cachedCssScreenRect ? this._cachedCssScreenRect.left : 0,
this._cachedCssScreenRect ? this._cachedCssScreenRect.top : 0);
}
- if (contentAreaResized)
+ if (contentAreaResized) {
this._contentAreaResized();
+ }
}
/**
@@ -293,11 +304,13 @@ Emulation.DeviceModeView = class extends UI.VBox {
* @param {string} srcset
*/
_loadImage(element, srcset) {
- if (element.getAttribute('srcset') === srcset)
+ if (element.getAttribute('srcset') === srcset) {
return;
+ }
element.setAttribute('srcset', srcset);
- if (!srcset)
+ if (!srcset) {
element.classList.toggle('hidden', true);
+ }
}
/**
@@ -312,8 +325,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
* @param {!Element} element
*/
setNonEmulatedAvailableSize(element) {
- if (this._model.type() !== Emulation.DeviceModeModel.Type.None)
+ if (this._model.type() !== Emulation.DeviceModeModel.Type.None) {
return;
+ }
const zoomFactor = UI.zoomManager.zoomFactor();
const rect = element.getBoundingClientRect();
const availableSize = new UI.Size(Math.max(rect.width * zoomFactor, 1), Math.max(rect.height * zoomFactor, 1));
@@ -353,8 +367,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
* @override
*/
onResize() {
- if (this.isShowing())
+ if (this.isShowing()) {
this._contentAreaResized();
+ }
}
/**
@@ -377,8 +392,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
*/
async captureScreenshot() {
const screenshot = await this._model.captureScreenshot(false);
- if (screenshot === null)
+ if (screenshot === null) {
return;
+ }
const pageImage = new Image();
pageImage.src = 'data:image/png;base64,' + screenshot;
@@ -396,10 +412,12 @@ Emulation.DeviceModeView = class extends UI.VBox {
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
- if (this._model.outlineImage())
+ if (this._model.outlineImage()) {
await this._paintImage(ctx, this._model.outlineImage(), outlineRect.relativeTo(outlineRect));
- if (this._model.screenImage())
+ }
+ if (this._model.screenImage()) {
await this._paintImage(ctx, this._model.screenImage(), screenRect.relativeTo(outlineRect));
+ }
ctx.drawImage(pageImage, Math.floor(contentLeft), Math.floor(contentTop));
this._saveScreenshot(canvas);
};
@@ -410,8 +428,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
*/
async captureFullSizeScreenshot() {
const screenshot = await this._model.captureScreenshot(true);
- if (screenshot === null)
+ if (screenshot === null) {
return;
+ }
return this._saveScreenshotBase64(screenshot);
}
@@ -421,8 +440,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
*/
async captureAreaScreenshot(clip) {
const screenshot = await this._model.captureScreenshot(false, clip);
- if (screenshot === null)
+ if (screenshot === null) {
return;
+ }
return this._saveScreenshotBase64(screenshot);
}
@@ -468,8 +488,9 @@ Emulation.DeviceModeView = class extends UI.VBox {
_saveScreenshot(canvas) {
const url = this._model.inspectedURL();
let fileName = url ? url.trimURL().removeURLFragment() : '';
- if (this._model.type() === Emulation.DeviceModeModel.Type.Device)
+ if (this._model.type() === Emulation.DeviceModeModel.Type.Device) {
fileName += Common.UIString('(%s)', this._model.device().title);
+ }
const link = createElement('a');
link.download = fileName + '.png';
canvas.toBlob(blob => {
@@ -531,41 +552,50 @@ Emulation.DeviceModeView.Ruler = class extends UI.VBox {
const dipSize = size * zoomFactor / this._scale;
const count = Math.ceil(dipSize / 5);
let step = 1;
- if (this._scale < 0.8)
+ if (this._scale < 0.8) {
step = 2;
- if (this._scale < 0.6)
+ }
+ if (this._scale < 0.6) {
step = 4;
- if (this._scale < 0.4)
+ }
+ if (this._scale < 0.4) {
step = 8;
- if (this._scale < 0.2)
+ }
+ if (this._scale < 0.2) {
step = 16;
- if (this._scale < 0.1)
+ }
+ if (this._scale < 0.1) {
step = 32;
+ }
for (let i = count; i < this._count; i++) {
- if (!(i % step))
+ if (!(i % step)) {
this._contentElement.lastChild.remove();
+ }
}
for (let i = this._count; i < count; i++) {
- if (i % step)
+ if (i % step) {
continue;
+ }
const marker = this._contentElement.createChild('div', 'device-mode-ruler-marker');
if (i) {
- if (this._horizontal)
+ if (this._horizontal) {
marker.style.left = (5 * i) * this._scale / zoomFactor + 'px';
- else
+ } else {
marker.style.top = (5 * i) * this._scale / zoomFactor + 'px';
+ }
if (!(i % 20)) {
const text = marker.createChild('div', 'device-mode-ruler-text');
text.textContent = i * 5;
text.addEventListener('click', this._onMarkerClick.bind(this, i * 5), false);
}
}
- if (!(i % 10))
+ if (!(i % 10)) {
marker.classList.add('device-mode-ruler-marker-large');
- else if (!(i % 5))
+ } else if (!(i % 5)) {
marker.classList.add('device-mode-ruler-marker-medium');
+ }
}
this._count = count;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeWrapper.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeWrapper.js
index 742d0e13363..8dd08970a99 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeWrapper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeWrapper.js
@@ -17,7 +17,7 @@ Emulation.DeviceModeWrapper = class extends UI.VBox {
this._toggleDeviceModeAction = UI.actionRegistry.action('emulation.toggle-device-mode');
const model = self.singleton(Emulation.DeviceModeModel);
this._showDeviceModeSetting = model.enabledSetting();
- this._showDeviceModeSetting.setRequiresUserAction(!!Runtime.queryParam('hasOtherClients'));
+ this._showDeviceModeSetting.setRequiresUserAction(!!Root.Runtime.queryParam('hasOtherClients'));
this._showDeviceModeSetting.addChangeListener(this._update.bind(this, false));
SDK.targetManager.addModelListener(
SDK.OverlayModel, SDK.OverlayModel.Events.ScreenshotRequested, this._screenshotRequestedFromOverlay, this);
@@ -34,15 +34,17 @@ Emulation.DeviceModeWrapper = class extends UI.VBox {
* @return {boolean}
*/
_captureScreenshot(fullSize, clip) {
- if (!this._deviceModeView)
+ if (!this._deviceModeView) {
this._deviceModeView = new Emulation.DeviceModeView();
+ }
this._deviceModeView.setNonEmulatedAvailableSize(this._inspectedPagePlaceholder.element);
- if (fullSize)
+ if (fullSize) {
this._deviceModeView.captureFullSizeScreenshot();
- else if (clip)
+ } else if (clip) {
this._deviceModeView.captureAreaScreenshot(clip);
- else
+ } else {
this._deviceModeView.captureScreenshot();
+ }
return true;
}
@@ -61,19 +63,22 @@ Emulation.DeviceModeWrapper = class extends UI.VBox {
this._toggleDeviceModeAction.setToggled(this._showDeviceModeSetting.get());
if (!force) {
const showing = this._deviceModeView && this._deviceModeView.isShowing();
- if (this._showDeviceModeSetting.get() === showing)
+ if (this._showDeviceModeSetting.get() === showing) {
return;
+ }
}
if (this._showDeviceModeSetting.get()) {
- if (!this._deviceModeView)
+ if (!this._deviceModeView) {
this._deviceModeView = new Emulation.DeviceModeView();
+ }
this._deviceModeView.show(this.element);
this._inspectedPagePlaceholder.clearMinimumSize();
this._inspectedPagePlaceholder.show(this._deviceModeView.element);
} else {
- if (this._deviceModeView)
+ if (this._deviceModeView) {
this._deviceModeView.detach();
+ }
this._inspectedPagePlaceholder.restoreMinimumSize();
this._inspectedPagePlaceholder.show(this.element);
}
@@ -102,8 +107,9 @@ Emulation.DeviceModeWrapper.ActionDelegate = class {
case 'emulation.capture-node-screenshot': {
const node = UI.context.flavor(SDK.DOMNode);
- if (!node)
+ if (!node) {
return true;
+ }
async function captureClip() {
const object = await node.resolveToObject();
const result = await object.callFunction(function() {
@@ -117,7 +123,8 @@ Emulation.DeviceModeWrapper.ActionDelegate = class {
scale: 1
});
});
- const clip = /** @type {!Protocol.Page.Viewport} */ (JSON.parse(result.object.value));
+ const clip =
+ /** @type {!Protocol.Page.Viewport} */ (JSON.parse(/** @type {string} */ (result.object.value)));
const response = await node.domModel().target().pageAgent().invoke_getLayoutMetrics({});
const page_zoom = !response[Protocol.Error] && response.visualViewport.zoom || 1;
clip.x *= page_zoom;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DevicesSettingsTab.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DevicesSettingsTab.js
index d975994b1b4..3148155ab8f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DevicesSettingsTab.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DevicesSettingsTab.js
@@ -46,21 +46,24 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
}
_devicesUpdated() {
- if (this._muteUpdate)
+ if (this._muteUpdate) {
return;
+ }
this._list.clear();
let devices = this._emulatedDevicesList.custom().slice();
- for (let i = 0; i < devices.length; ++i)
+ for (let i = 0; i < devices.length; ++i) {
this._list.appendItem(devices[i], true);
+ }
this._list.appendSeparator();
devices = this._emulatedDevicesList.standard().slice();
devices.sort(Emulation.EmulatedDevice.deviceComparator);
- for (let i = 0; i < devices.length; ++i)
+ for (let i = 0; i < devices.length; ++i) {
this._list.appendItem(devices[i], false);
+ }
}
/**
@@ -68,10 +71,11 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
*/
_muteAndSaveDeviceList(custom) {
this._muteUpdate = true;
- if (custom)
+ if (custom) {
this._emulatedDevicesList.saveCustomDevices();
- else
+ } else {
this._emulatedDevicesList.saveStandardDevices();
+ }
this._muteUpdate = false;
}
@@ -154,14 +158,17 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
{title: '', orientation: Emulation.EmulatedDevice.Horizontal, insets: new UI.Insets(0, 0, 0, 0), image: null});
device.capabilities = [];
const uaType = editor.control('ua-type').value;
- if (uaType === Emulation.DeviceModeModel.UA.Mobile || uaType === Emulation.DeviceModeModel.UA.MobileNoTouch)
+ if (uaType === Emulation.DeviceModeModel.UA.Mobile || uaType === Emulation.DeviceModeModel.UA.MobileNoTouch) {
device.capabilities.push(Emulation.EmulatedDevice.Capability.Mobile);
- if (uaType === Emulation.DeviceModeModel.UA.Mobile || uaType === Emulation.DeviceModeModel.UA.DesktopTouch)
+ }
+ if (uaType === Emulation.DeviceModeModel.UA.Mobile || uaType === Emulation.DeviceModeModel.UA.DesktopTouch) {
device.capabilities.push(Emulation.EmulatedDevice.Capability.Touch);
- if (isNew)
+ }
+ if (isNew) {
this._emulatedDevicesList.addCustomDevice(device);
- else
+ } else {
this._emulatedDevicesList.saveCustomDevices();
+ }
this._addCustomButton.scrollIntoViewIfNeeded();
this._addCustomButton.focus();
}
@@ -180,10 +187,11 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
editor.control('scale').value = this._toNumericInputValue(device.deviceScaleFactor);
editor.control('user-agent').value = device.userAgent;
let uaType;
- if (device.mobile())
+ if (device.mobile()) {
uaType = device.touch() ? Emulation.DeviceModeModel.UA.Mobile : Emulation.DeviceModeModel.UA.MobileNoTouch;
- else
+ } else {
uaType = device.touch() ? Emulation.DeviceModeModel.UA.DesktopTouch : Emulation.DeviceModeModel.UA.Desktop;
+ }
editor.control('ua-type').value = uaType;
return editor;
}
@@ -192,8 +200,9 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -234,12 +243,13 @@ Emulation.DevicesSettingsTab = class extends UI.VBox {
let errorMessage;
const value = input.value.trim();
- if (value.length >= Emulation.DeviceModeModel.MaxDeviceNameLength)
+ if (value.length >= Emulation.DeviceModeModel.MaxDeviceNameLength) {
errorMessage = ls`Device name must be less than ${Emulation.DeviceModeModel.MaxDeviceNameLength} characters.`;
- else if (value.length === 0)
+ } else if (value.length === 0) {
errorMessage = ls`Device name cannot be empty.`;
- else
+ } else {
valid = true;
+ }
return {valid, errorMessage};
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/EmulatedDevices.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/EmulatedDevices.js
index 732abc9b869..1456deacc44 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/EmulatedDevices.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/EmulatedDevices.js
@@ -28,7 +28,7 @@ Emulation.EmulatedDevice = class {
/** @type {boolean} */
this._showByDefault = true;
- /** @type {?Runtime.Extension} */
+ /** @type {?Root.Runtime.Extension} */
this._extension = null;
}
@@ -47,13 +47,15 @@ Emulation.EmulatedDevice = class {
*/
function parseValue(object, key, type, defaultValue) {
if (typeof object !== 'object' || object === null || !object.hasOwnProperty(key)) {
- if (typeof defaultValue !== 'undefined')
+ if (typeof defaultValue !== 'undefined') {
return defaultValue;
+ }
throw new Error('Emulated device is missing required property \'' + key + '\'');
}
const value = object[key];
- if (typeof value !== type || value === null)
+ if (typeof value !== type || value === null) {
throw new Error('Emulated device property \'' + key + '\' has wrong type \'' + typeof value + '\'');
+ }
return value;
}
@@ -64,8 +66,9 @@ Emulation.EmulatedDevice = class {
*/
function parseIntValue(object, key) {
const value = /** @type {number} */ (parseValue(object, key, 'number'));
- if (value !== Math.abs(value))
+ if (value !== Math.abs(value)) {
throw new Error('Emulated device value \'' + key + '\' must be integer');
+ }
return value;
}
@@ -88,19 +91,22 @@ Emulation.EmulatedDevice = class {
result.width = parseIntValue(json, 'width');
if (result.width < 0 || result.width > Emulation.DeviceModeModel.MaxDeviceSize ||
- result.width < Emulation.DeviceModeModel.MinDeviceSize)
+ result.width < Emulation.DeviceModeModel.MinDeviceSize) {
throw new Error('Emulated device has wrong width: ' + result.width);
+ }
result.height = parseIntValue(json, 'height');
if (result.height < 0 || result.height > Emulation.DeviceModeModel.MaxDeviceSize ||
- result.height < Emulation.DeviceModeModel.MinDeviceSize)
+ result.height < Emulation.DeviceModeModel.MinDeviceSize) {
throw new Error('Emulated device has wrong height: ' + result.height);
+ }
const outlineInsets = parseValue(json['outline'], 'insets', 'object', null);
if (outlineInsets) {
result.outlineInsets = parseInsets(outlineInsets);
- if (result.outlineInsets.left < 0 || result.outlineInsets.top < 0)
+ if (result.outlineInsets.left < 0 || result.outlineInsets.top < 0) {
throw new Error('Emulated device has wrong outline insets');
+ }
result.outlineImage = /** @type {string} */ (parseValue(json['outline'], 'image', 'string'));
}
return /** @type {!Emulation.EmulatedDevice.Orientation} */ (result);
@@ -113,39 +119,45 @@ Emulation.EmulatedDevice = class {
result.userAgent = SDK.MultitargetNetworkManager.patchUserAgentWithChromeVersion(rawUserAgent);
const capabilities = parseValue(json, 'capabilities', 'object', []);
- if (!Array.isArray(capabilities))
+ if (!Array.isArray(capabilities)) {
throw new Error('Emulated device capabilities must be an array');
+ }
result.capabilities = [];
for (let i = 0; i < capabilities.length; ++i) {
- if (typeof capabilities[i] !== 'string')
+ if (typeof capabilities[i] !== 'string') {
throw new Error('Emulated device capability must be a string');
+ }
result.capabilities.push(capabilities[i]);
}
result.deviceScaleFactor = /** @type {number} */ (parseValue(json['screen'], 'device-pixel-ratio', 'number'));
- if (result.deviceScaleFactor < 0 || result.deviceScaleFactor > 100)
+ if (result.deviceScaleFactor < 0 || result.deviceScaleFactor > 100) {
throw new Error('Emulated device has wrong deviceScaleFactor: ' + result.deviceScaleFactor);
+ }
result.vertical = parseOrientation(parseValue(json['screen'], 'vertical', 'object'));
result.horizontal = parseOrientation(parseValue(json['screen'], 'horizontal', 'object'));
const modes = parseValue(json, 'modes', 'object', []);
- if (!Array.isArray(modes))
+ if (!Array.isArray(modes)) {
throw new Error('Emulated device modes must be an array');
+ }
result.modes = [];
for (let i = 0; i < modes.length; ++i) {
const mode = {};
mode.title = /** @type {string} */ (parseValue(modes[i], 'title', 'string'));
mode.orientation = /** @type {string} */ (parseValue(modes[i], 'orientation', 'string'));
if (mode.orientation !== Emulation.EmulatedDevice.Vertical &&
- mode.orientation !== Emulation.EmulatedDevice.Horizontal)
+ mode.orientation !== Emulation.EmulatedDevice.Horizontal) {
throw new Error('Emulated device mode has wrong orientation \'' + mode.orientation + '\'');
+ }
const orientation = result.orientationByName(mode.orientation);
mode.insets = parseInsets(parseValue(modes[i], 'insets', 'object'));
if (mode.insets.top < 0 || mode.insets.left < 0 || mode.insets.right < 0 || mode.insets.bottom < 0 ||
mode.insets.top + mode.insets.bottom > orientation.height ||
- mode.insets.left + mode.insets.right > orientation.width)
+ mode.insets.left + mode.insets.right > orientation.width) {
throw new Error('Emulated device mode \'' + mode.title + '\'has wrong mode insets');
+ }
mode.image = /** @type {string} */ (parseValue(modes[i], 'image', 'string', null));
result.modes.push(mode);
@@ -169,22 +181,24 @@ Emulation.EmulatedDevice = class {
static deviceComparator(device1, device2) {
const order1 = (device1._extension && device1._extension.descriptor()['order']) || -1;
const order2 = (device2._extension && device2._extension.descriptor()['order']) || -1;
- if (order1 > order2)
+ if (order1 > order2) {
return 1;
- if (order2 > order1)
+ }
+ if (order2 > order1) {
return -1;
+ }
return device1.title < device2.title ? -1 : (device1.title > device2.title ? 1 : 0);
}
/**
- * @return {?Runtime.Extension}
+ * @return {?Root.Runtime.Extension}
*/
extension() {
return this._extension;
}
/**
- * @param {?Runtime.Extension} extension
+ * @param {?Root.Runtime.Extension} extension
*/
setExtension(extension) {
this._extension = extension;
@@ -197,8 +211,9 @@ Emulation.EmulatedDevice = class {
modesForOrientation(orientation) {
const result = [];
for (let index = 0; index < this.modes.length; index++) {
- if (this.modes[index].orientation === orientation)
+ if (this.modes[index].orientation === orientation) {
result.push(this.modes[index]);
+ }
}
return result;
}
@@ -228,8 +243,9 @@ Emulation.EmulatedDevice = class {
mode['insets']['top'] = this.modes[i].insets.top;
mode['insets']['right'] = this.modes[i].insets.right;
mode['insets']['bottom'] = this.modes[i].insets.bottom;
- if (this.modes[i].image)
+ if (this.modes[i].image) {
mode['image'] = this.modes[i].image;
+ }
json['modes'].push(mode);
}
@@ -264,10 +280,12 @@ Emulation.EmulatedDevice = class {
* @return {string}
*/
modeImage(mode) {
- if (!mode.image)
+ if (!mode.image) {
return '';
- if (!this._extension)
+ }
+ if (!this._extension) {
return mode.image;
+ }
return this._extension.module().substituteURL(mode.image);
}
@@ -277,10 +295,12 @@ Emulation.EmulatedDevice = class {
*/
outlineImage(mode) {
const orientation = this.orientationByName(mode.orientation);
- if (!orientation.outlineImage)
+ if (!orientation.outlineImage) {
return '';
- if (!this._extension)
+ }
+ if (!this._extension) {
return orientation.outlineImage;
+ }
return this._extension.module().substituteURL(orientation.outlineImage);
}
@@ -296,8 +316,9 @@ Emulation.EmulatedDevice = class {
* @return {boolean}
*/
show() {
- if (this._show === Emulation.EmulatedDevice._Show.Default)
+ if (this._show === Emulation.EmulatedDevice._Show.Default) {
return this._showByDefault;
+ }
return this._show === Emulation.EmulatedDevice._Show.Always;
}
@@ -377,16 +398,18 @@ Emulation.EmulatedDevicesList = class extends Common.Object {
this._customSetting = Common.settings.createSetting('customEmulatedDeviceList', []);
/** @type {!Array.<!Emulation.EmulatedDevice>} */
this._custom = [];
- if (!this._listFromJSONV1(this._customSetting.get(), this._custom))
+ if (!this._listFromJSONV1(this._customSetting.get(), this._custom)) {
this.saveCustomDevices();
+ }
}
/**
* @return {!Emulation.EmulatedDevicesList}
*/
static instance() {
- if (!Emulation.EmulatedDevicesList._instance)
+ if (!Emulation.EmulatedDevicesList._instance) {
Emulation.EmulatedDevicesList._instance = new Emulation.EmulatedDevicesList();
+ }
return /** @type {!Emulation.EmulatedDevicesList} */ (Emulation.EmulatedDevicesList._instance);
}
@@ -409,8 +432,9 @@ Emulation.EmulatedDevicesList = class extends Common.Object {
* @return {boolean}
*/
_listFromJSONV1(jsonArray, result) {
- if (!Array.isArray(jsonArray))
+ if (!Array.isArray(jsonArray)) {
return false;
+ }
let success = true;
for (let i = 0; i < jsonArray.length; ++i) {
const device = Emulation.EmulatedDevice.fromJSONV1(jsonArray[i]);
@@ -493,13 +517,15 @@ Emulation.EmulatedDevicesList = class extends Common.Object {
*/
_copyShowValues(from, to) {
const deviceById = new Map();
- for (let i = 0; i < from.length; ++i)
+ for (let i = 0; i < from.length; ++i) {
deviceById.set(from[i].title, from[i]);
+ }
for (let i = 0; i < to.length; ++i) {
const title = to[i].title;
- if (deviceById.has(title))
+ if (deviceById.has(title)) {
to[i].copyShowFrom(/** @type {!Emulation.EmulatedDevice} */ (deviceById.get(title)));
+ }
}
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/GeolocationsSettingsTab.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/GeolocationsSettingsTab.js
index 1f1b28288ca..4c8cdd090bb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/GeolocationsSettingsTab.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/GeolocationsSettingsTab.js
@@ -40,14 +40,15 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
this._list.clear();
const conditions = this._customSetting.get();
- for (let i = 0; i < conditions.length; ++i)
+ for (let i = 0; i < conditions.length; ++i) {
this._list.appendItem(conditions[i], true);
+ }
this._list.appendSeparator();
}
_addButtonClicked() {
- this._list.addNewItem(this._customSetting.get().length, {title: '', lat: 0, long: 0});
+ this._list.addNewItem(this._customSetting.get().length, {title: '', lat: 0, long: 0, timezoneId: ''});
}
/**
@@ -67,6 +68,8 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
element.createChild('div', 'geolocations-list-text').textContent = geolocation.lat;
element.createChild('div', 'geolocations-list-separator');
element.createChild('div', 'geolocations-list-text').textContent = geolocation.long;
+ element.createChild('div', 'geolocations-list-separator');
+ element.createChild('div', 'geolocations-list-text').textContent = geolocation.timezoneId;
return element;
}
@@ -94,10 +97,13 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
geolocation.lat = lat ? parseFloat(lat) : 0;
const long = editor.control('long').value.trim();
geolocation.long = long ? parseFloat(long) : 0;
+ const timezoneId = editor.control('timezoneId').value.trim();
+ geolocation.timezoneId = timezoneId;
const list = this._customSetting.get();
- if (isNew)
+ if (isNew) {
list.push(geolocation);
+ }
this._customSetting.set(list);
}
@@ -112,6 +118,7 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
editor.control('title').value = geolocation.title;
editor.control('lat').value = String(geolocation.lat);
editor.control('long').value = String(geolocation.long);
+ editor.control('timezoneId').value = String(geolocation.timezoneId);
return editor;
}
@@ -119,8 +126,9 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -133,6 +141,8 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
titles.createChild('div', 'geolocations-list-text').textContent = Common.UIString('Lat');
titles.createChild('div', 'geolocations-list-separator geolocations-list-separator-invisible');
titles.createChild('div', 'geolocations-list-text').textContent = Common.UIString('Long');
+ titles.createChild('div', 'geolocations-list-separator geolocations-list-separator-invisible');
+ titles.createChild('div', 'geolocations-list-text').textContent = Common.UIString('Timezone ID');
const fields = content.createChild('div', 'geolocations-edit-row');
fields.createChild('div', 'geolocations-list-text geolocations-list-title')
@@ -146,6 +156,9 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
cell = fields.createChild('div', 'geolocations-list-text');
cell.appendChild(editor.createInput('long', 'text', ls`Longitude`, longValidator));
+ cell = fields.createChild('div', 'geolocations-list-text');
+ cell.appendChild(editor.createInput('timezoneId', 'text', ls`Timezone ID`, timezoneIdValidator));
+
return editor;
/**
@@ -159,13 +172,15 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
const value = input.value.trim();
let errorMessage;
- if (!value.length)
+ if (!value.length) {
errorMessage = ls`Location name cannot be empty`;
- else if (value.length > maxLength)
+ } else if (value.length > maxLength) {
errorMessage = ls`Location name must be less than ${maxLength} characters`;
+ }
- if (errorMessage)
+ if (errorMessage) {
return {valid: false, errorMessage};
+ }
return {valid: true};
}
@@ -179,20 +194,24 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
const minLat = -90;
const maxLat = 90;
const value = input.value.trim();
+ const parsedValue = Number(value);
- if (!value)
+ if (!value) {
return {valid: true};
+ }
let errorMessage;
- if (!/^-?[\d]+(\.\d+)?|\.\d+$/.test(value))
+ if (Number.isNaN(parsedValue)) {
errorMessage = ls`Latitude must be a number`;
- else if (parseFloat(value) < minLat)
+ } else if (parseFloat(value) < minLat) {
errorMessage = ls`Latitude must be greater than or equal to ${minLat}`;
- else if (parseFloat(value) > maxLat)
+ } else if (parseFloat(value) > maxLat) {
errorMessage = ls`Latitude must be less than or equal to ${maxLat}`;
+ }
- if (errorMessage)
+ if (errorMessage) {
return {valid: false, errorMessage};
+ }
return {valid: true};
}
@@ -206,24 +225,48 @@ Emulation.GeolocationsSettingsTab = class extends UI.VBox {
const minLong = -180;
const maxLong = 180;
const value = input.value.trim();
+ const parsedValue = Number(value);
- if (!value)
+ if (!value) {
return {valid: true};
+ }
let errorMessage;
- if (!/^-?[\d]+(\.\d+)?|\.\d+$/.test(value))
+ if (Number.isNaN(parsedValue)) {
errorMessage = ls`Longitude must be a number`;
- else if (parseFloat(value) < minLong)
+ } else if (parseFloat(value) < minLong) {
errorMessage = ls`Longitude must be greater than or equal to ${minLong}`;
- else if (parseFloat(value) > maxLong)
+ } else if (parseFloat(value) > maxLong) {
errorMessage = ls`Longitude must be less than or equal to ${maxLong}`;
+ }
- if (errorMessage)
+ if (errorMessage) {
return {valid: false, errorMessage};
+ }
return {valid: true};
}
+
+ /**
+ * @param {*} item
+ * @param {number} index
+ * @param {!HTMLInputElement|!HTMLSelectElement} input
+ * @return {!UI.ListWidget.ValidatorResult}
+ */
+ function timezoneIdValidator(item, index, input) {
+ const value = input.value.trim();
+ // Chromium uses ICU's timezone implementation, which is very
+ // liberal in what it accepts. ICU does not simply use an allowlist
+ // but instead tries to make sense of the input, even for
+ // weird-looking timezone IDs. There's not much point in validating
+ // the input other than checking if it contains at least one slash.
+ if (value === '' || value.includes('/')) {
+ return {valid: true};
+ }
+ const errorMessage = ls`Timezone ID must contain "/"`;
+ return {valid: false, errorMessage};
+ }
}
};
/** @typedef {{title: string, lat: number, long: number}} */
-Emulation.GeolocationsSettingsTab.Item; \ No newline at end of file
+Emulation.GeolocationsSettingsTab.Item;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/InspectedPagePlaceholder.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/InspectedPagePlaceholder.js
index d9f1787e2c3..15152641716 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/InspectedPagePlaceholder.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/InspectedPagePlaceholder.js
@@ -17,8 +17,9 @@ Emulation.InspectedPagePlaceholder = class extends UI.Widget {
* @override
*/
onResize() {
- if (this._updateId)
+ if (this._updateId) {
this.element.window().cancelAnimationFrame(this._updateId);
+ }
this._updateId = this.element.window().requestAnimationFrame(this.update.bind(this, false));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/MediaQueryInspector.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/MediaQueryInspector.js
index 04f62dac2e9..e8f9748586c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/MediaQueryInspector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/MediaQueryInspector.js
@@ -32,8 +32,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
*/
modelAdded(cssModel) {
// FIXME: adapt this to multiple targets.
- if (this._cssModel)
+ if (this._cssModel) {
return;
+ }
this._cssModel = cssModel;
this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._scheduleMediaQueriesUpdate, this);
this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._scheduleMediaQueriesUpdate, this);
@@ -47,8 +48,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
* @param {!SDK.CSSModel} cssModel
*/
modelRemoved(cssModel) {
- if (cssModel !== this._cssModel)
+ if (cssModel !== this._cssModel) {
return;
+ }
this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._scheduleMediaQueriesUpdate, this);
this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._scheduleMediaQueriesUpdate, this);
this._cssModel.removeEventListener(SDK.CSSModel.Events.StyleSheetChanged, this._scheduleMediaQueriesUpdate, this);
@@ -61,8 +63,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
* @param {number} scale
*/
setAxisTransform(scale) {
- if (Math.abs(this._scale - scale) < 1e-8)
+ if (Math.abs(this._scale - scale) < 1e-8) {
return;
+ }
this._scale = scale;
this._renderMediaQueries();
}
@@ -72,8 +75,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
*/
_onMediaQueryClicked(event) {
const mediaQueryMarker = event.target.enclosingNodeOrSelfWithClass('media-inspector-bar');
- if (!mediaQueryMarker)
+ if (!mediaQueryMarker) {
return;
+ }
const model = mediaQueryMarker._model;
if (model.section() === Emulation.MediaQueryInspector.Section.Max) {
@@ -85,29 +89,33 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
return;
}
const currentWidth = this._getWidthCallback();
- if (currentWidth !== model.minWidthExpression().computedLength())
+ if (currentWidth !== model.minWidthExpression().computedLength()) {
this._setWidthCallback(model.minWidthExpression().computedLength());
- else
+ } else {
this._setWidthCallback(model.maxWidthExpression().computedLength());
+ }
}
/**
* @param {!Event} event
*/
_onContextMenu(event) {
- if (!this._cssModel || !this._cssModel.isEnabled())
+ if (!this._cssModel || !this._cssModel.isEnabled()) {
return;
+ }
const mediaQueryMarker = event.target.enclosingNodeOrSelfWithClass('media-inspector-bar');
- if (!mediaQueryMarker)
+ if (!mediaQueryMarker) {
return;
+ }
const locations = mediaQueryMarker._locations;
const uiLocations = new Map();
for (let i = 0; i < locations.length; ++i) {
const uiLocation = Bindings.cssWorkspaceBinding.rawLocationToUILocation(locations[i]);
- if (!uiLocation)
+ if (!uiLocation) {
continue;
+ }
const descriptor = String.sprintf(
'%s:%d:%d', uiLocation.uiSourceCode.url(), uiLocation.lineNumber + 1, uiLocation.columnNumber + 1);
uiLocations.set(descriptor, uiLocation);
@@ -132,14 +140,16 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
}
_scheduleMediaQueriesUpdate() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
this._mediaThrottler.schedule(this._refetchMediaQueries.bind(this));
}
_refetchMediaQueries() {
- if (!this.isShowing() || !this._cssModel)
+ if (!this.isShowing() || !this._cssModel) {
return Promise.resolve();
+ }
return this._cssModel.mediaQueriesPromise().then(this._rebuildMediaQueries.bind(this));
}
@@ -152,8 +162,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
const filtered = [];
for (let i = 0; i < models.length; ++i) {
const last = filtered.peekLast();
- if (!last || !last.equals(models[i]))
+ if (!last || !last.equals(models[i])) {
filtered.push(models[i]);
+ }
}
return filtered;
}
@@ -165,23 +176,27 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
let queryModels = [];
for (let i = 0; i < cssMedias.length; ++i) {
const cssMedia = cssMedias[i];
- if (!cssMedia.mediaList)
+ if (!cssMedia.mediaList) {
continue;
+ }
for (let j = 0; j < cssMedia.mediaList.length; ++j) {
const mediaQuery = cssMedia.mediaList[j];
const queryModel = Emulation.MediaQueryInspector.MediaQueryUIModel.createFromMediaQuery(cssMedia, mediaQuery);
- if (queryModel && queryModel.rawLocation())
+ if (queryModel && queryModel.rawLocation()) {
queryModels.push(queryModel);
+ }
}
}
queryModels.sort(compareModels);
queryModels = this._squashAdjacentEqual(queryModels);
let allEqual = this._cachedQueryModels && this._cachedQueryModels.length === queryModels.length;
- for (let i = 0; allEqual && i < queryModels.length; ++i)
+ for (let i = 0; allEqual && i < queryModels.length; ++i) {
allEqual = allEqual && this._cachedQueryModels[i].equals(queryModels[i]);
- if (allEqual)
+ }
+ if (allEqual) {
return;
+ }
this._cachedQueryModels = queryModels;
this._renderMediaQueries();
@@ -196,8 +211,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
}
_renderMediaQueries() {
- if (!this._cachedQueryModels || !this.isShowing())
+ if (!this._cachedQueryModels || !this.isShowing()) {
return;
+ }
const markers = [];
let lastMarker = null;
@@ -216,8 +232,9 @@ Emulation.MediaQueryInspector = class extends UI.Widget {
let container = null;
for (let i = 0; i < markers.length; ++i) {
- if (!i || markers[i].model.section() !== markers[i - 1].model.section())
+ if (!i || markers[i].model.section() !== markers[i - 1].model.section()) {
container = this.contentElement.createChild('div', 'media-inspector-marker-container');
+ }
const marker = markers[i];
const bar = this._createElementFromMediaQueryModel(marker.model);
bar._model = marker.model;
@@ -329,12 +346,13 @@ Emulation.MediaQueryInspector.MediaQueryUIModel = class {
this._minWidthExpression = minWidthExpression;
this._maxWidthExpression = maxWidthExpression;
this._active = active;
- if (maxWidthExpression && !minWidthExpression)
+ if (maxWidthExpression && !minWidthExpression) {
this._section = Emulation.MediaQueryInspector.Section.Max;
- else if (minWidthExpression && maxWidthExpression)
+ } else if (minWidthExpression && maxWidthExpression) {
this._section = Emulation.MediaQueryInspector.Section.MinMax;
- else
+ } else {
this._section = Emulation.MediaQueryInspector.Section.Min;
+ }
}
/**
@@ -351,8 +369,9 @@ Emulation.MediaQueryInspector.MediaQueryUIModel = class {
for (let i = 0; i < expressions.length; ++i) {
const expression = expressions[i];
const feature = expression.feature();
- if (feature.indexOf('width') === -1)
+ if (feature.indexOf('width') === -1) {
continue;
+ }
const pixels = expression.computedLength();
if (feature.startsWith('max-') && pixels < maxWidthPixels) {
maxWidthExpression = expression;
@@ -362,8 +381,9 @@ Emulation.MediaQueryInspector.MediaQueryUIModel = class {
minWidthPixels = pixels;
}
}
- if (minWidthPixels > maxWidthPixels || (!maxWidthExpression && !minWidthExpression))
+ if (minWidthPixels > maxWidthPixels || (!maxWidthExpression && !minWidthExpression)) {
return null;
+ }
return new Emulation.MediaQueryInspector.MediaQueryUIModel(
cssMedia, minWidthExpression, maxWidthExpression, mediaQuery.active());
@@ -394,26 +414,33 @@ Emulation.MediaQueryInspector.MediaQueryUIModel = class {
* @return {number}
*/
compareTo(other) {
- if (this.section() !== other.section())
+ if (this.section() !== other.section()) {
return this.section() - other.section();
+ }
if (this.dimensionsEqual(other)) {
const myLocation = this.rawLocation();
const otherLocation = other.rawLocation();
- if (!myLocation && !otherLocation)
+ if (!myLocation && !otherLocation) {
return this.mediaText().compareTo(other.mediaText());
- if (myLocation && !otherLocation)
+ }
+ if (myLocation && !otherLocation) {
return 1;
- if (!myLocation && otherLocation)
+ }
+ if (!myLocation && otherLocation) {
return -1;
- if (this.active() !== other.active())
+ }
+ if (this.active() !== other.active()) {
return this.active() ? -1 : 1;
+ }
return myLocation.url.compareTo(otherLocation.url) || myLocation.lineNumber - otherLocation.lineNumber ||
myLocation.columnNumber - otherLocation.columnNumber;
}
- if (this.section() === Emulation.MediaQueryInspector.Section.Max)
+ if (this.section() === Emulation.MediaQueryInspector.Section.Max) {
return other.maxWidthExpression().computedLength() - this.maxWidthExpression().computedLength();
- if (this.section() === Emulation.MediaQueryInspector.Section.Min)
+ }
+ if (this.section() === Emulation.MediaQueryInspector.Section.Min) {
return this.minWidthExpression().computedLength() - other.minWidthExpression().computedLength();
+ }
return this.minWidthExpression().computedLength() - other.minWidthExpression().computedLength() ||
other.maxWidthExpression().computedLength() - this.maxWidthExpression().computedLength();
}
@@ -436,8 +463,9 @@ Emulation.MediaQueryInspector.MediaQueryUIModel = class {
* @return {?SDK.CSSLocation}
*/
rawLocation() {
- if (!this._rawLocation)
+ if (!this._rawLocation) {
this._rawLocation = this._cssMedia.rawLocation();
+ }
return this._rawLocation;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js
index a3d92356c04..15f9dd77760 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js
@@ -31,8 +31,9 @@ Emulation.SensorsView = class extends UI.VBox {
* @return {!Emulation.SensorsView}
*/
static instance() {
- if (!Emulation.SensorsView._instanceObject)
+ if (!Emulation.SensorsView._instanceObject) {
Emulation.SensorsView._instanceObject = new Emulation.SensorsView();
+ }
return Emulation.SensorsView._instanceObject;
}
@@ -65,8 +66,9 @@ Emulation.SensorsView = class extends UI.VBox {
fields.appendChild(manageButton);
const fillCustomSettings = () => {
this._customLocationsGroup.removeChildren();
- for (const geolocation of customGeolocations.get())
+ for (const geolocation of customGeolocations.get()) {
this._customLocationsGroup.appendChild(new Option(geolocation.title, JSON.stringify(geolocation)));
+ }
};
customGeolocations.addChangeListener(fillCustomSettings);
fillCustomSettings();
@@ -93,6 +95,10 @@ Emulation.SensorsView = class extends UI.VBox {
const latitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');
const longitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group');
+ const timezoneGroup = this._fieldsetElement.createChild('div', 'latlong-group');
+
+ const cmdOrCtrl = Host.isMac() ? '\u2318' : 'Ctrl';
+ const modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`;
this._latitudeInput = UI.createInput('', 'number');
latitudeGroup.appendChild(this._latitudeInput);
@@ -102,6 +108,8 @@ Emulation.SensorsView = class extends UI.VBox {
this._latitudeInput, this._applyGeolocationUserInput.bind(this),
SDK.EmulationModel.Geolocation.latitudeValidator, true, 0.1);
this._latitudeSetter(String(geolocation.latitude));
+ this._latitudeInput.title = modifierKeyMessage;
+ latitudeGroup.appendChild(UI.createLabel(ls`Latitude`, 'latlong-title', this._latitudeInput));
this._longitudeInput = UI.createInput('', 'number');
longitudeGroup.appendChild(this._longitudeInput);
@@ -111,14 +119,17 @@ Emulation.SensorsView = class extends UI.VBox {
this._longitudeInput, this._applyGeolocationUserInput.bind(this),
SDK.EmulationModel.Geolocation.longitudeValidator, true, 0.1);
this._longitudeSetter(String(geolocation.longitude));
-
- const cmdOrCtrl = Host.isMac() ? '\u2318' : 'Ctrl';
- const modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`;
- this._latitudeInput.title = modifierKeyMessage;
this._longitudeInput.title = modifierKeyMessage;
-
- latitudeGroup.appendChild(UI.createLabel(ls`Latitude`, 'latlong-title', this._latitudeInput));
longitudeGroup.appendChild(UI.createLabel(ls`Longitude`, 'latlong-title', this._longitudeInput));
+
+ this._timezoneInput = UI.createInput('', 'text');
+ timezoneGroup.appendChild(this._timezoneInput);
+ this._timezoneInput.value = 'Europe/Berlin';
+ this._timezoneSetter = UI.bindInput(
+ this._timezoneInput, this._applyGeolocationUserInput.bind(this),
+ SDK.EmulationModel.Geolocation.timezoneIdValidator, false);
+ this._timezoneSetter(String(geolocation.timezoneId));
+ timezoneGroup.appendChild(UI.createLabel(ls`Timezone ID`, 'timezone-title', this._timezoneInput));
}
_geolocationSelectChanged() {
@@ -130,31 +141,36 @@ Emulation.SensorsView = class extends UI.VBox {
} else if (value === Emulation.SensorsView.NonPresetOptions.Custom) {
this._geolocationOverrideEnabled = true;
const geolocation = SDK.EmulationModel.Geolocation.parseUserInput(
- this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), '');
- if (!geolocation)
+ this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim());
+ if (!geolocation) {
return;
+ }
this._geolocation = geolocation;
} else if (value === Emulation.SensorsView.NonPresetOptions.Unavailable) {
this._geolocationOverrideEnabled = true;
- this._geolocation = new SDK.EmulationModel.Geolocation(0, 0, true);
+ this._geolocation = new SDK.EmulationModel.Geolocation(0, 0, '', true);
} else {
this._geolocationOverrideEnabled = true;
const coordinates = JSON.parse(value);
- this._geolocation = new SDK.EmulationModel.Geolocation(coordinates.lat, coordinates.long, false);
+ this._geolocation =
+ new SDK.EmulationModel.Geolocation(coordinates.lat, coordinates.long, coordinates.timezoneId, false);
this._latitudeSetter(coordinates.lat);
this._longitudeSetter(coordinates.long);
+ this._timezoneSetter(coordinates.timezoneId);
}
this._applyGeolocation();
- if (value === Emulation.SensorsView.NonPresetOptions.Custom)
+ if (value === Emulation.SensorsView.NonPresetOptions.Custom) {
this._latitudeInput.focus();
+ }
}
_applyGeolocationUserInput() {
const geolocation = SDK.EmulationModel.Geolocation.parseUserInput(
- this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), '');
- if (!geolocation)
+ this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim());
+ if (!geolocation) {
return;
+ }
this._setSelectElementLabel(this._locationSelectElement, Emulation.SensorsView.NonPresetOptions.Custom);
this._geolocation = geolocation;
@@ -162,10 +178,12 @@ Emulation.SensorsView = class extends UI.VBox {
}
_applyGeolocation() {
- if (this._geolocationOverrideEnabled)
+ if (this._geolocationOverrideEnabled) {
this._geolocationSetting.set(this._geolocation.toSetting());
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ }
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.emulateGeolocation(this._geolocationOverrideEnabled ? this._geolocation : null);
+ }
}
_createDeviceOrientationSection() {
@@ -195,8 +213,9 @@ Emulation.SensorsView = class extends UI.VBox {
const groupElement = this._orientationSelectElement.createChild('optgroup');
groupElement.label = orientationGroups[i].title;
const group = orientationGroups[i].value;
- for (let j = 0; j < group.length; ++j)
+ for (let j = 0; j < group.length; ++j) {
groupElement.appendChild(new Option(group[j].title, group[j].orientation));
+ }
}
this._orientationSelectElement.selectedIndex = 0;
fields.appendChild(this._orientationSelectElement);
@@ -260,10 +279,12 @@ Emulation.SensorsView = class extends UI.VBox {
}
_applyDeviceOrientation() {
- if (this._deviceOrientationOverrideEnabled)
+ if (this._deviceOrientationOverrideEnabled) {
this._deviceOrientationSetting.set(this._deviceOrientation.toSetting());
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ }
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.emulateDeviceOrientation(this._deviceOrientationOverrideEnabled ? this._deviceOrientation : null);
+ }
}
/**
@@ -295,8 +316,9 @@ Emulation.SensorsView = class extends UI.VBox {
* @param {!Emulation.SensorsView.DeviceOrientationModificationSource} modificationSource
*/
_setDeviceOrientation(deviceOrientation, modificationSource) {
- if (!deviceOrientation)
+ if (!deviceOrientation) {
return;
+ }
/**
* @param {number} angle
@@ -371,10 +393,11 @@ Emulation.SensorsView = class extends UI.VBox {
* @param {boolean} animate
*/
_setBoxOrientation(deviceOrientation, animate) {
- if (animate)
+ if (animate) {
this._stageElement.classList.add('is-animating');
- else
+ } else {
this._stageElement.classList.remove('is-animating');
+ }
// The CSS transform should not depend on matrix3d, which does not interpolate well.
const matrix = new WebKitCSSMatrix();
@@ -390,8 +413,9 @@ Emulation.SensorsView = class extends UI.VBox {
*/
_onBoxDrag(event) {
const mouseMoveVector = this._calculateRadiusVector(event.x, event.y);
- if (!mouseMoveVector)
+ if (!mouseMoveVector) {
return true;
+ }
event.consume(true);
let axis, angle;
@@ -424,14 +448,16 @@ Emulation.SensorsView = class extends UI.VBox {
* @return {boolean}
*/
_onBoxDragStart(event) {
- if (!this._deviceOrientationOverrideEnabled)
+ if (!this._deviceOrientationOverrideEnabled) {
return false;
+ }
this._mouseDownVector = this._calculateRadiusVector(event.x, event.y);
this._originalBoxMatrix = this._boxMatrix;
- if (!this._mouseDownVector)
+ if (!this._mouseDownVector) {
return false;
+ }
event.consume(true);
return true;
@@ -448,8 +474,9 @@ Emulation.SensorsView = class extends UI.VBox {
const sphereX = (x - rect.left - rect.width / 2) / radius;
const sphereY = (y - rect.top - rect.height / 2) / radius;
const sqrSum = sphereX * sphereX + sphereY * sphereY;
- if (sqrSum > 0.5)
+ if (sqrSum > 0.5) {
return new UI.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum));
+ }
return new UI.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum));
}
@@ -471,8 +498,9 @@ Emulation.SensorsView = class extends UI.VBox {
UI.ARIAUtils.markAsAlert(reloadWarning);
function applyTouch() {
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.overrideEmulateTouch(select.value === 'enabled');
+ }
reloadWarning.classList.remove('hidden');
const resourceTreeModel = SDK.targetManager.models(SDK.ResourceTreeModel)[0];
if (resourceTreeModel) {
@@ -500,7 +528,7 @@ Emulation.SensorsView.NonPresetOptions = {
/** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */
Emulation.SensorsView.PresetOrientations = [{
- title: 'Presets',
+ title: ls`Presets`,
value: [
{title: Common.UIString('Portrait'), orientation: '[0, 90, 0]'},
{title: Common.UIString('Portrait upside down'), orientation: '[180, -90, 0]'},
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
index d12103de9a0..c73adc5c5b9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/emulation_strings.grdp
@@ -9,6 +9,9 @@
<message name="IDS_DEVTOOLS_0c78cd3aa4c94a64675bc6aa77802843" desc="Text in Sensors View of the Device Toolbar">
Device-based
</message>
+ <message name="IDS_DEVTOOLS_0e1275697d4c40b4b0640fbfa3907afa" desc="A tag of Sensors tool that can be searched in the command menu">
+ accelerometer
+ </message>
<message name="IDS_DEVTOOLS_0eb264d46c88af61e587c18f60662df0" desc="Title of device scale item in device mode toolbar of the device toolbar">
Device pixel ratio
</message>
@@ -48,12 +51,6 @@
<message name="IDS_DEVTOOLS_2496af30b64c3a4ff21e8505ea439a73" desc="Text in Device Mode Toolbar of the Device Toolbar">
50%
</message>
- <message name="IDS_DEVTOOLS_29260f495ba8adcc62fd1307c758ff4e" desc="Text in Device Mode Toolbar of the Device Toolbar">
- Show rulers
- </message>
- <message name="IDS_DEVTOOLS_29296fcb28eb4edf5d0049b6cac7bbd1" desc="Text in Device Mode Toolbar of the Device Toolbar">
- <ph name="THIS__MODEL_SCALE________">$1.0f<ex>13.0</ex></ph>%%
- </message>
<message name="IDS_DEVTOOLS_29eaeee66d8210c1261d748071fb7b0a" desc="Text in Sensors View of the Device Toolbar">
Landscape right
</message>
@@ -69,9 +66,6 @@
<message name="IDS_DEVTOOLS_31d0615d58891f425fd66979cfa5193b" desc="Error message in the Devices settings pane that declares the maximum value for the width input">
Width must be less than or equal to <ph name="EMULATION_DEVICEMODEMODEL_MAXDEVICESIZE">$1s<ex>9999</ex></ph>.
</message>
- <message name="IDS_DEVTOOLS_323d4eb70b252acb4a04eaf9e0882597" desc="Text in Sensors View of the Device Toolbar">
- Geolocation
- </message>
<message name="IDS_DEVTOOLS_32954654ac8fe66a1d09be19001de2d4" desc="Width input title in Device Mode Toolbar of the Device Toolbar">
Width
</message>
@@ -106,32 +100,41 @@
Latitude
</message>
<message name="IDS_DEVTOOLS_414b730ab2cf9123d9230740864ffeec" desc="A context menu item in the Device Mode Toolbar of the Device Toolbar">
- Close DevTools
- </message>
- <message name="IDS_DEVTOOLS_4252b72e6ebcd4d4b4c2e46a786f03d2" desc="Title of scale item in device mode toolbar of the device toolbar">
- Zoom
+ Close <ph name="LOCKED_1">DevTools</ph>
</message>
<message name="IDS_DEVTOOLS_45f80006d304f294d6c1de50c244856e" desc="Text of add geolocations button in Geolocations Settings Tab of the Device Toolbar">
Add location...
</message>
- <message name="IDS_DEVTOOLS_4dab36ac83853282fc0d7bae20c19e90" desc="Title of more options button in device mode toolbar of the device toolbar">
- More options
- </message>
<message name="IDS_DEVTOOLS_526d688f37a86d3c3f27d0c5016eb71d" desc="Text of orientation reset button in Sensors View of the Device Toolbar">
Reset
</message>
+ <message name="IDS_DEVTOOLS_5466ee572bcbc75830d044e66ab429bc" desc="City name in Geolocations Settings">
+ Shanghai
+ </message>
<message name="IDS_DEVTOOLS_58cc7602635a11277aa7531e14b32c97" desc="Text in Sensors View of the Device Toolbar">
Portrait upside down
</message>
<message name="IDS_DEVTOOLS_59c06928c1dcdb1a687bf21d73e53a09" desc="Text in Device Mode Toolbar of the Device Toolbar">
Show device frame
</message>
+ <message name="IDS_DEVTOOLS_59ead8d1e124ccfb79f3ace06f43e703" desc="City name in Geolocations Settings">
+ London
+ </message>
+ <message name="IDS_DEVTOOLS_5b4f1c0e2bd8bc1ba726cd51dd70c1a6" desc="City name in Geolocations Settings">
+ Mountain View
+ </message>
+ <message name="IDS_DEVTOOLS_5cacd64cfc65b4f4ea83306b6cebf0be" desc="A tag of Sensors tool that can be searched in the command menu">
+ timezones
+ </message>
<message name="IDS_DEVTOOLS_614103b76fd0d9de068d69034fb6f987" desc="Text in Device Mode View of the Device Toolbar">
(<ph name="THIS__MODEL_DEVICE___TITLE">$1s<ex>iPhone X</ex></ph>)
</message>
<message name="IDS_DEVTOOLS_6149711fb8edc5e2adeea7aa63ee11ff" desc="Text in Device Mode Toolbar of the Device Toolbar">
150%
</message>
+ <message name="IDS_DEVTOOLS_62413a57c5e3dc51177995fa175d3286" desc="City name in Geolocations Settings">
+ Tokyo
+ </message>
<message name="IDS_DEVTOOLS_62759e0d418d7391bf2d54e70cbcc05d" desc="Text in Device Mode Toolbar of the Device Toolbar">
Remove device type
</message>
@@ -144,9 +147,6 @@
<message name="IDS_DEVTOOLS_673a7b89eb57bf2bf891306c98cbecc3" desc="Error message in the Geolocations settings pane that declares that the value for the latitude input must be a number">
Latitude must be a number
</message>
- <message name="IDS_DEVTOOLS_6adf97f83acf6453d4a6a4b1070f3754" desc="Text in Device Mode Toolbar of the Device Toolbar">
- None
- </message>
<message name="IDS_DEVTOOLS_6e641146898080ed83f3007cd712f58f" desc="Error message in the Devices settings pane that declares the maximum value for the device pixel ratio input">
Device pixel ratio must be less than or equal to <ph name="EMULATION_DEVICEMODEMODEL_MAXDEVICESCALEFACTOR">$1s<ex>10</ex></ph>.
</message>
@@ -171,12 +171,21 @@
<message name="IDS_DEVTOOLS_7b4b2de0aae3a60aa3cf502a19f9c748" desc="Error message in the Devices settings pane that declares that the device name input must not be empty">
Device name cannot be empty.
</message>
+ <message name="IDS_DEVTOOLS_7e35e74e610188414ad24235dd787c78" desc="City name in Geolocations Settings">
+ Moscow
+ </message>
<message name="IDS_DEVTOOLS_7f163d0494446906a484df67e90c1d6b" desc="Text in Device Mode Toolbar of the Device Toolbar">
Hide device frame
</message>
+ <message name="IDS_DEVTOOLS_7fc2515293d99e95b1745e81d6abbdf4" desc="City name in Geolocations Settings">
+ São Paulo
+ </message>
<message name="IDS_DEVTOOLS_815dff01257e5ef182b25d4c1ef0a7a0" desc="Text in Device Mode Toolbar of the Device Toolbar">
Landscape
</message>
+ <message name="IDS_DEVTOOLS_8189965036f7d675e0b7af67a2a873a0" desc="Text in Sensors View of the Device Toolbar">
+ Timezone ID
+ </message>
<message name="IDS_DEVTOOLS_81c3744a7fe979d029d1e7b84afd613f" desc="Reload warning text content in Sensors View of the Device Toolbar">
*Requires reload
</message>
@@ -195,6 +204,9 @@
<message name="IDS_DEVTOOLS_8d7b5211545faceef57a041ee56a2f5e" desc="Title of an action in the emulation tool to capture full height screenshot">
Capture full size screenshot
</message>
+ <message name="IDS_DEVTOOLS_8ebaad59980c95ade797c903761fa815" desc="City name in Geolocations Settings">
+ Mumbai
+ </message>
<message name="IDS_DEVTOOLS_901bc0a4714ff81c24943a50e620de71" desc="Text in Devices Settings Tab of the Device Toolbar">
User agent string
</message>
@@ -237,6 +249,9 @@
<message name="IDS_DEVTOOLS_a88789aba0125292a7a2b8774a979b37" desc="Title of Geolocations settings">
Geolocations
</message>
+ <message name="IDS_DEVTOOLS_a9c9b04b4bb57da48b29b4f40ffb2e89" desc="A tag of Sensors tool that can be searched in the command menu">
+ device orientation
+ </message>
<message name="IDS_DEVTOOLS_af29aa178ae43211319e28f627e96590" desc="Title of an action in the emulation tool to show sensors">
Sensors
</message>
@@ -246,6 +261,9 @@
<message name="IDS_DEVTOOLS_b1596787a9a32a2626743258abf34e80" desc="Text in Sensors View of the Device Toolbar">
Landscape left
</message>
+ <message name="IDS_DEVTOOLS_b22a74a48cd2f1d35dac23d239312139" desc="A tag of Sensors tool that can be searched in the command menu">
+ geolocation
+ </message>
<message name="IDS_DEVTOOLS_b2b22e112d16f958f75ea888f9ce8eeb" desc="Text in Sensors View of the Device Toolbar">
Display down
</message>
@@ -297,6 +315,9 @@
<message name="IDS_DEVTOOLS_d15305d7a4e34e02489c74a5ef542f36" desc="Text in Sensors View of the Device Toolbar">
Off
</message>
+ <message name="IDS_DEVTOOLS_d9e39d238ea8f70b277a68d9c07b5046" desc="Error message in the Geolocations settings pane that declares timezone ID input invalid">
+ Timezone ID must contain &quot;/&quot;
+ </message>
<message name="IDS_DEVTOOLS_da31f3ff326e70f6b08748520c553920" desc="Text in Sensors View of the Device Toolbar">
γ (gamma)
</message>
@@ -312,6 +333,9 @@
<message name="IDS_DEVTOOLS_eccbc87e4b5ce2fe28308fd9f2a7baf3" desc="Text in Device Mode Toolbar of the Device Toolbar">
3
</message>
+ <message name="IDS_DEVTOOLS_ee1611b61f5688e70c12b40684dbb395" desc="City name in Geolocations Settings">
+ Berlin
+ </message>
<message name="IDS_DEVTOOLS_ee1cab1975e28575b1631ee8fc4ea749" desc="Title of an action in the emulation tool to capture node screenshot">
Capture node screenshot
</message>
@@ -324,12 +348,12 @@
<message name="IDS_DEVTOOLS_f01ee7fedba5e392f6f9adab7ec0c74a" desc="Error message in the Geolocations settings pane that declares the location name input must not be empty">
Location name cannot be empty
</message>
- <message name="IDS_DEVTOOLS_f0f31c9700c6b10d8a20dc487b2ae6a8" desc="Text in Sensors View of the Device Toolbar">
- Touch
- </message>
<message name="IDS_DEVTOOLS_f2a72a44f7b7d30829c0405ed2385345" desc="Text in Device Mode View of the Device Toolbar">
Mobile S
</message>
+ <message name="IDS_DEVTOOLS_f4334fdfa1c728eae375fe781e2e2d9d" desc="City name in Geolocations Settings">
+ San Francisco
+ </message>
<message name="IDS_DEVTOOLS_f819de81247be4a5428dc0e169de28b8" desc="Text in Device Mode Toolbar of the Device Toolbar">
75%
</message>
@@ -339,4 +363,4 @@
<message name="IDS_DEVTOOLS_fd37e9411d9f8a6af8fb4d3b787ccfc6" desc="Error message in the Devices settings pane that declares the minimum value for the width input">
Width must be greater than or equal to <ph name="EMULATION_DEVICEMODEMODEL_MINDEVICESIZE">$1s<ex>50</ex></ph>.
</message>
-</grit-part> \ No newline at end of file
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/geolocationsSettingsTab.css b/chromium/third_party/blink/renderer/devtools/front_end/emulation/geolocationsSettingsTab.css
index f6a0a37b958..47ec50d7a9e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/geolocationsSettingsTab.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/geolocationsSettingsTab.css
@@ -5,84 +5,87 @@
*/
:host {
- overflow:hidden;
+ overflow: hidden;
}
.header {
- padding: 0 0 6px;
- border-bottom: 1px solid #EEEEEE;
- font-size: 18px;
- font-weight: normal;
- flex: none;
+ padding: 0 0 6px;
+ border-bottom: 1px solid #EEEEEE;
+ font-size: 18px;
+ font-weight: normal;
+ flex: none;
}
.add-geolocations-button {
- flex: none;
- margin: 10px 2px;
- min-width: 140px;
- align-self: flex-start;
+ flex: none;
+ margin: 10px 2px;
+ min-width: 140px;
+ align-self: flex-start;
}
.geolocations-list {
- max-width: 500px;
- min-width: 340px;
- flex: auto;
+ max-width: 600px;
+ min-width: 340px;
+ flex: auto;
}
.geolocations-list-item {
- padding: 3px 5px 3px 5px;
- height: 30px;
- display: flex;
- align-items: center;
- position: relative;
- flex: auto 1 1;
+ padding: 3px 5px 3px 5px;
+ height: 30px;
+ display: flex;
+ align-items: center;
+ position: relative;
+ flex: auto 1 1;
}
.geolocations-list-text {
- white-space: nowrap;
- text-overflow: ellipsis;
- flex: 0 0 70px;
- -webkit-user-select: none;
- color: #222;
- text-align: end;
- position: relative;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ flex: 0 0 70px;
+ -webkit-user-select: none;
+ color: #222;
+ text-align: end;
+ position: relative;
+}
+
+.geolocations-list-text:last-child {
+ flex: 0 0 170px;
}
.geolocations-list-title {
- text-align: start;
- flex: auto;
- display: flex;
- align-items: flex-start;
+ text-align: start;
+ flex: auto;
+ display: flex;
+ align-items: flex-start;
}
.geolocations-list-title-text {
- overflow: hidden;
- flex: auto;
- white-space: nowrap;
- text-overflow: ellipsis;
+ overflow: hidden;
+ flex: auto;
+ white-space: nowrap;
+ text-overflow: ellipsis;
}
.geolocations-list-separator {
- flex: 0 0 1px;
- background-color: rgb(231, 231, 231);
- height: 30px;
- margin: 0 4px;
+ flex: 0 0 1px;
+ background-color: rgb(231, 231, 231);
+ height: 30px;
+ margin: 0 4px;
}
.geolocations-list-separator-invisible {
- visibility: hidden;
- height: 100% !important;
+ visibility: hidden;
+ height: 100% !important;
}
.geolocations-edit-row {
- flex: none;
- display: flex;
- flex-direction: row;
- margin: 6px 5px;
+ flex: none;
+ display: flex;
+ flex-direction: row;
+ margin: 6px 5px;
}
.geolocations-edit-row input {
- width: 100%;
- text-align: inherit;
+ width: 100%;
+ text-align: inherit;
}
-
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/module.json b/chromium/third_party/blink/renderer/devtools/front_end/emulation/module.json
index f79e7e454f7..25e72d10ac9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/module.json
@@ -146,25 +146,25 @@
"persistence": "closeable",
"order": 100,
"className": "Emulation.SensorsView",
- "tags": "geolocation, accelerometer, device orientation"
+ "tags": "geolocation, timezones, accelerometer, device orientation"
},
{
"type": "setting",
"settingName": "emulation.geolocations",
"settingType": "array",
"defaultValue": [
- {"title": "Berlin", "lat": 52.520007, "long": 13.404954},
- {"title": "London", "lat": 51.507351, "long": -0.127758},
- {"title": "Moscow", "lat": 55.755826, "long": 37.617300},
- {"title": "Mountain View", "lat": 37.386052, "long": -122.083851},
- {"title": "Mumbai", "lat": 19.075984, "long": 72.877656},
- {"title": "San Francisco", "lat": 37.774929, "long": -122.419416},
- {"title": "Shanghai", "lat": 31.230416, "long": 121.473701},
- {"title": "São Paulo", "lat": -23.550520, "long": -46.633309},
- {"title": "Tokyo", "lat": 35.689487, "long": 139.691706}
- ]
- },
- {
+ {"title": "Berlin", "lat": 52.520007, "long": 13.404954, "timezoneId": "Europe/Berlin"},
+ {"title": "London", "lat": 51.507351, "long": -0.127758, "timezoneId": "Europe/London"},
+ {"title": "Moscow", "lat": 55.755826, "long": 37.617300, "timezoneId": "Europe/Moscow"},
+ {"title": "Mountain View", "lat": 37.386052, "long": -122.083851, "timezoneId": "US/Pacific"},
+ {"title": "Mumbai", "lat": 19.075984, "long": 72.877656, "timezoneId": "Asia/Kolkata"},
+ {"title": "San Francisco", "lat": 37.774929, "long": -122.419416, "timezoneId": "US/Pacific"},
+ {"title": "Shanghai", "lat": 31.230416, "long": 121.473701, "timezoneId": "Asia/Shanghai"},
+ {"title": "São Paulo", "lat": -23.550520, "long": -46.633309, "timezoneId": "America/Sao_Paulo"},
+ {"title": "Tokyo", "lat": 35.689487, "long": 139.691706, "timezoneId": "Asia/Tokyo"}
+ ]
+ },
+ {
"type": "view",
"location": "settings-view",
"id": "emulation-geolocations",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/sensors.css b/chromium/third_party/blink/renderer/devtools/front_end/emulation/sensors.css
index f89c59e63b2..a0da0eb3a98 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/sensors.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/sensors.css
@@ -5,165 +5,164 @@
*/
.sensors-view {
- padding: 12px;
- display: block;
+ padding: 12px;
+ display: block;
}
.sensors-view input {
- width: 100%;
- max-width: 100px;
- margin: -5px 10px 0px 0px;
- text-align: end;
+ width: 100%;
+ max-width: 120px;
+ margin: -5px 10px 0px 0px;
+ text-align: end;
}
.sensors-view input[readonly] {
- background-color: rgb(235, 235, 228);
+ background-color: rgb(235, 235, 228);
}
.sensors-view fieldset {
- border: none;
- padding: 10px 0px;
- margin-left: 0;
- flex: 0 0 auto;
- margin: 0;
+ border: none;
+ padding: 10px 0px;
+ margin-left: 0;
+ flex: 0 0 auto;
+ margin: 0;
}
.sensors-view fieldset[disabled] {
- opacity: 0.5;
+ opacity: 0.5;
}
.sensors-view input:focus::-webkit-input-placeholder {
- color: transparent !important;
+ color: transparent !important;
}
.sensors-view .chrome-select {
- width: 200px;
+ width: 200px;
}
.sensors-group-title {
- width: 80px;
- line-height: 24px;
+ width: 80px;
+ line-height: 24px;
}
.sensors-group {
- display: flex;
- flex-wrap: wrap;
- margin-bottom: 10px;
+ display: flex;
+ flex-wrap: wrap;
+ margin-bottom: 10px;
}
.geo-fields {
- flex: 2 0 200px;
+ flex: 2 0 200px;
}
.latlong-group {
- display: flex;
- margin-bottom: 10px;
+ display: flex;
+ margin-bottom: 10px;
}
.latlong-title {
- width: 70px;
+ width: 70px;
}
/* Device Orientation */
.orientation-content {
- display: flex;
- flex-wrap: wrap;
+ display: flex;
+ flex-wrap: wrap;
}
.orientation-fields {
- margin-right: 10px;
+ margin-right: 10px;
}
.orientation-stage {
- -webkit-perspective: 700px;
- -webkit-perspective-origin: 50% 50%;
- width: 160px;
- height: 150px;
- background: linear-gradient(#E1F5FE 0%, #E1F5FE 64%, #b0Ebf3 64%, #DEF6F9 100%);
- transition: 0.2s ease opacity, 0.2s ease -webkit-filter;
- overflow: hidden;
- margin-bottom: 10px;
+ -webkit-perspective: 700px;
+ -webkit-perspective-origin: 50% 50%;
+ width: 160px;
+ height: 150px;
+ background: linear-gradient(#E1F5FE 0%, #E1F5FE 64%, #b0Ebf3 64%, #DEF6F9 100%);
+ transition: 0.2s ease opacity, 0.2s ease -webkit-filter;
+ overflow: hidden;
+ margin-bottom: 10px;
}
.orientation-stage.disabled {
- -webkit-filter: grayscale();
- opacity: 0.5;
- cursor: default !important;
+ -webkit-filter: grayscale();
+ opacity: 0.5;
+ cursor: default !important;
}
.orientation-element,
.orientation-element::before,
-.orientation-element::after
-{
- position: absolute;
- box-sizing: border-box;
- transform-style: preserve-3d;
- background: no-repeat;
- background-size: cover;
- backface-visibility: hidden;
+.orientation-element::after{
+ position: absolute;
+ box-sizing: border-box;
+ transform-style: preserve-3d;
+ background: no-repeat;
+ background-size: cover;
+ backface-visibility: hidden;
}
.orientation-box {
- width: 62px;
- height: 122px;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- margin: auto;
- transform: rotate3d(1, 0, 0, 90deg);
+ width: 62px;
+ height: 122px;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ transform: rotate3d(1, 0, 0, 90deg);
}
.orientation-box.is-animating, .is-animating .orientation-layer {
- transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
+ transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
}
.orientation-layer {
- width: 100%;
- height: 100%;
- transform-style: preserve-3d;
+ width: 100%;
+ height: 100%;
+ transform-style: preserve-3d;
}
.orientation-front,
.orientation-back
{
- width: 62px;
- height: 122px;
- border-radius: 8px;
+ width: 62px;
+ height: 122px;
+ border-radius: 8px;
}
.orientation-front {
- background-image: url(Images/accelerometer-front.svg);
+ background-image: url(Images/accelerometer-front.svg);
}
.orientation-back {
- transform: rotateY(180deg) translateZ(8px);
- background-image: url(Images/accelerometer-back.svg);
+ transform: rotateY(180deg) translateZ(8px);
+ background-image: url(Images/accelerometer-back.svg);
}
.orientation-left,
.orientation-right {
- width: 8px;
- height: 106px;
- top: 8px;
- background-position: center center;
+ width: 8px;
+ height: 106px;
+ top: 8px;
+ background-position: center center;
}
.orientation-left {
- left: -8px;
- transform-origin: right center;
- transform: rotateY(-90deg);
- background-image: url(Images/accelerometer-left.png);
+ left: -8px;
+ transform-origin: right center;
+ transform: rotateY(-90deg);
+ background-image: url(Images/accelerometer-left.png);
}
.orientation-right {
- right: -8px;
- transform-origin: left center;
- transform: rotateY(90deg);
- background-image: url(Images/accelerometer-right.png);
+ right: -8px;
+ transform-origin: left center;
+ transform: rotateY(90deg);
+ background-image: url(Images/accelerometer-right.png);
}
.orientation-left::before,
@@ -171,60 +170,60 @@
.orientation-right::before,
.orientation-right::after
{
- content: '';
- width: 8px;
- height: 6px;
+ content: '';
+ width: 8px;
+ height: 6px;
}
.orientation-left::before,
.orientation-left::after
{
- background-image: url(Images/accelerometer-left.png);
+ background-image: url(Images/accelerometer-left.png);
}
.orientation-right::before,
.orientation-right::after
{
- background-image: url(Images/accelerometer-right.png);
+ background-image: url(Images/accelerometer-right.png);
}
.orientation-left::before,
.orientation-right::before {
- top: -6px;
- transform-origin: center bottom;
- transform: rotateX(26deg);
- background-position: center top;
+ top: -6px;
+ transform-origin: center bottom;
+ transform: rotateX(26deg);
+ background-position: center top;
}
.orientation-left::after,
.orientation-right::after {
- bottom: -6px;
- transform-origin: center top;
- transform: rotateX(-25deg);
- background-position: center bottom;
+ bottom: -6px;
+ transform-origin: center top;
+ transform: rotateX(-25deg);
+ background-position: center bottom;
}
.orientation-top,
.orientation-bottom {
- width: 50px;
- height: 8px;
- left: 8px;
- background-position: center center;
+ width: 50px;
+ height: 8px;
+ left: 8px;
+ background-position: center center;
}
.orientation-top {
- top: -8px;
- transform-origin: center bottom;
- transform: rotateX(90deg);
- background-image: url(Images/accelerometer-top.png);
+ top: -8px;
+ transform-origin: center bottom;
+ transform: rotateX(90deg);
+ background-image: url(Images/accelerometer-top.png);
}
.orientation-bottom {
- bottom: -8px;
- transform-origin: center top;
- transform: rotateX(-90deg);
- background-image: url(Images/accelerometer-bottom.png);
+ bottom: -8px;
+ transform-origin: center top;
+ transform: rotateX(-90deg);
+ background-image: url(Images/accelerometer-bottom.png);
}
@@ -233,67 +232,67 @@
.orientation-bottom::before,
.orientation-bottom::after
{
- content: '';
- width: 8px;
- height: 8px;
+ content: '';
+ width: 8px;
+ height: 8px;
}
.orientation-top::before,
.orientation-top::after
{
- background-image: url(Images/accelerometer-top.png);
+ background-image: url(Images/accelerometer-top.png);
}
.orientation-bottom::before,
.orientation-bottom::after
{
- background-image: url(Images/accelerometer-bottom.png);
+ background-image: url(Images/accelerometer-bottom.png);
}
.orientation-top::before,
.orientation-bottom::before {
- left: -6px;
- transform-origin: right center;
- transform: rotateY(-26deg);
- background-position: left center;
+ left: -6px;
+ transform-origin: right center;
+ transform: rotateY(-26deg);
+ background-position: left center;
}
.orientation-top::after,
.orientation-bottom::after {
- right: -6px;
- transform-origin: left center;
- transform: rotateY(26deg);
- background-position: right center;
+ right: -6px;
+ transform-origin: left center;
+ transform: rotateY(26deg);
+ background-position: right center;
}
.orientation-axis-input-container {
- margin-bottom: 10px;
+ margin-bottom: 10px;
}
.orientation-axis-input-container input {
- max-width: 100px;
+ max-width: 120px;
}
.orientation-reset-button {
- min-width: 80px;
+ min-width: 80px;
}
fieldset.device-orientation-override-section {
- margin: 0;
- display: flex;
+ margin: 0;
+ display: flex;
}
.panel-section-separator {
- height: 2px;
- margin-bottom: 8px;
- background: #f1f1f1;
+ height: 2px;
+ margin-bottom: 8px;
+ background: #f1f1f1;
}
.reload-warning {
- align-self: center;
- margin-left: 10px;
+ align-self: center;
+ margin-left: 10px;
}
button.text-button {
- margin: 0 10px;
+ margin: 0 10px;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersUtils.js
index b74ba91e49c..c857ab58ba6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersUtils.js
@@ -40,16 +40,20 @@ EventListeners.frameworkEventListeners = function(object) {
* @return {!Promise<undefined>}
*/
function createEventListeners(result) {
- if (!result.properties)
+ if (!result.properties) {
throw new Error('Object properties is empty');
+ }
const promises = [];
for (const property of result.properties) {
- if (property.name === 'eventListeners' && property.value)
+ if (property.name === 'eventListeners' && property.value) {
promises.push(convertToEventListeners(property.value).then(storeEventListeners));
- if (property.name === 'internalHandlers' && property.value)
+ }
+ if (property.name === 'internalHandlers' && property.value) {
promises.push(convertToInternalHandlers(property.value).then(storeInternalHandlers));
- if (property.name === 'errorString' && property.value)
+ }
+ if (property.name === 'errorString' && property.value) {
printErrorString(property.value);
+ }
}
return /** @type {!Promise<undefined>} */ (Promise.all(promises));
}
@@ -162,8 +166,9 @@ EventListeners.frameworkEventListeners = function(object) {
* @param {!SDK.RemoteObject} functionObject
*/
function storeRemoveFunction(functionObject) {
- if (functionObject.type !== 'function')
+ if (functionObject.type !== 'function') {
return;
+ }
removeFunctionObject = functionObject;
}
@@ -173,8 +178,9 @@ EventListeners.frameworkEventListeners = function(object) {
* @return {!SDK.EventListener}
*/
function createEventListener() {
- if (!location)
+ if (!location) {
throw new Error('Empty event listener\'s location');
+ }
return new SDK.EventListener(
/** @type {!SDK.DOMDebuggerModel} */ (domDebuggerModel), object, type, useCapture, passive, once, handler,
originalHandler, location, removeFunctionObject, SDK.EventListener.Origin.FrameworkUser);
@@ -189,7 +195,7 @@ EventListeners.frameworkEventListeners = function(object) {
function convertToInternalHandlers(pageInternalHandlersObject) {
return SDK.RemoteArray.objectAsArray(pageInternalHandlersObject)
.map(toTargetFunction)
- .then(SDK.RemoteArray.createFromRemoteObjects);
+ .then(SDK.RemoteArray.createFromRemoteObjects.bind(null));
}
/**
@@ -233,8 +239,9 @@ EventListeners.frameworkEventListeners = function(object) {
* @return {!SDK.RemoteObject}
*/
function assertCallFunctionResult(result) {
- if (result.wasThrown || !result.object)
+ if (result.wasThrown || !result.object) {
throw new Error('Exception in callFunction or empty result');
+ }
return result.object;
}
@@ -290,8 +297,9 @@ EventListeners.frameworkEventListeners = function(object) {
let internalHandlers = [];
let fetchers = [jQueryFetcher];
try {
- if (self.devtoolsFrameworkEventListeners && isArrayLike(self.devtoolsFrameworkEventListeners))
+ if (self.devtoolsFrameworkEventListeners && isArrayLike(self.devtoolsFrameworkEventListeners)) {
fetchers = fetchers.concat(self.devtoolsFrameworkEventListeners);
+ }
} catch (e) {
errorLines.push('devtoolsFrameworkEventListeners call produced error: ' + toString(e));
}
@@ -312,8 +320,9 @@ EventListeners.frameworkEventListeners = function(object) {
}
}
const result = {eventListeners: eventListeners};
- if (internalHandlers.length)
+ if (internalHandlers.length) {
result.internalHandlers = internalHandlers;
+ }
if (errorLines.length) {
let errorString = 'Framework Event Listeners API Errors:\n\t' + errorLines.join('\n\t');
errorString = errorString.substr(0, errorString.length - 1);
@@ -326,8 +335,9 @@ EventListeners.frameworkEventListeners = function(object) {
* @return {boolean}
*/
function isArrayLike(obj) {
- if (!obj || typeof obj !== 'object')
+ if (!obj || typeof obj !== 'object') {
return false;
+ }
try {
if (typeof obj.splice === 'function') {
const len = obj.length;
@@ -345,26 +355,33 @@ EventListeners.frameworkEventListeners = function(object) {
function checkEventListener(eventListener) {
try {
let errorString = '';
- if (!eventListener)
+ if (!eventListener) {
errorString += 'empty event listener, ';
+ }
const type = eventListener.type;
- if (!type || (typeof type !== 'string'))
+ if (!type || (typeof type !== 'string')) {
errorString += 'event listener\'s type isn\'t string or empty, ';
+ }
const useCapture = eventListener.useCapture;
- if (typeof useCapture !== 'boolean')
+ if (typeof useCapture !== 'boolean') {
errorString += 'event listener\'s useCapture isn\'t boolean or undefined, ';
+ }
const passive = eventListener.passive;
- if (typeof passive !== 'boolean')
+ if (typeof passive !== 'boolean') {
errorString += 'event listener\'s passive isn\'t boolean or undefined, ';
+ }
const once = eventListener.once;
- if (typeof once !== 'boolean')
+ if (typeof once !== 'boolean') {
errorString += 'event listener\'s once isn\'t boolean or undefined, ';
+ }
const handler = eventListener.handler;
- if (!handler || (typeof handler !== 'function'))
+ if (!handler || (typeof handler !== 'function')) {
errorString += 'event listener\'s handler isn\'t a function or empty, ';
+ }
const remove = eventListener.remove;
- if (remove && (typeof remove !== 'function'))
+ if (remove && (typeof remove !== 'function')) {
errorString += 'event listener\'s remove isn\'t a function, ';
+ }
if (!errorString) {
return {type: type, useCapture: useCapture, passive: passive, once: once, handler: handler, remove: remove};
} else {
@@ -382,8 +399,9 @@ EventListeners.frameworkEventListeners = function(object) {
* @return {function()|null}
*/
function checkInternalHandler(handler) {
- if (handler && (typeof handler === 'function'))
+ if (handler && (typeof handler === 'function')) {
return handler;
+ }
errorLines.push('internal handler isn\'t a function or empty');
return null;
}
@@ -410,11 +428,13 @@ EventListeners.frameworkEventListeners = function(object) {
}
function jQueryFetcher(node) {
- if (!node || !(node instanceof Node))
+ if (!node || !(node instanceof Node)) {
return {eventListeners: []};
+ }
const jQuery = /** @type {?{fn,data,_data}}*/ (window['jQuery']);
- if (!jQuery || !jQuery.fn)
+ if (!jQuery || !jQuery.fn) {
return {eventListeners: []};
+ }
const jQueryFunction = /** @type {function(!Node)} */ (jQuery);
const data = jQuery._data || jQuery.data;
@@ -440,8 +460,9 @@ EventListeners.frameworkEventListeners = function(object) {
}
}
const nodeData = data(node);
- if (nodeData && typeof nodeData.handle === 'function')
+ if (nodeData && typeof nodeData.handle === 'function') {
internalHandlers.push(nodeData.handle);
+ }
}
const entry = jQueryFunction(node)[0];
if (entry) {
@@ -456,8 +477,9 @@ EventListeners.frameworkEventListeners = function(object) {
}
}
}
- if (entry && entry['$handle'])
+ if (entry && entry['$handle']) {
internalHandlers.push(entry['$handle']);
+ }
}
return {eventListeners: eventListeners, internalHandlers: internalHandlers};
}
@@ -469,12 +491,14 @@ EventListeners.frameworkEventListeners = function(object) {
* @this {?Object}
*/
function jQueryRemove(selector, type, handler) {
- if (!this || !(this instanceof Node))
+ if (!this || !(this instanceof Node)) {
return;
+ }
const node = /** @type {!Node} */ (this);
const jQuery = /** @type {?{fn,data,_data}}*/ (window['jQuery']);
- if (!jQuery || !jQuery.fn)
+ if (!jQuery || !jQuery.fn) {
return;
+ }
const jQueryFunction = /** @type {function(!Node)} */ (jQuery);
jQueryFunction(node).off(type, selector, handler);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersView.js b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersView.js
index 0d23a25c498..21a37960ff1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/EventListenersView.js
@@ -27,12 +27,24 @@ EventListeners.EventListenersView = class extends UI.VBox {
this.element.appendChild(this._treeOutline.element);
this._emptyHolder = createElementWithClass('div', 'gray-info-message');
this._emptyHolder.textContent = Common.UIString('No event listeners');
+ this._emptyHolder.tabIndex = -1;
this._linkifier = new Components.Linkifier();
/** @type {!Map<string, !EventListeners.EventListenersTreeElement>} */
this._treeItemMap = new Map();
}
/**
+ * @override
+ */
+ focus() {
+ if (!this._emptyHolder.parentNode) {
+ this._treeOutline.forceSelect();
+ } else {
+ this._emptyHolder.focus();
+ }
+ }
+
+ /**
* @param {!Array<?SDK.RemoteObject>} objects
* @return {!Promise<undefined>}
*/
@@ -56,8 +68,9 @@ EventListeners.EventListenersView = class extends UI.VBox {
const promises = [];
const domDebuggerModel = object.runtimeModel().target().model(SDK.DOMDebuggerModel);
// TODO(kozyatinskiy): figure out how this should work for |window| when there is no DOMDebugger.
- if (domDebuggerModel)
+ if (domDebuggerModel) {
promises.push(domDebuggerModel.eventListeners(object).then(storeEventListeners));
+ }
promises.push(EventListeners.frameworkEventListeners(object).then(storeFrameworkEventListenersObject));
return Promise.all(promises).then(markInternalEventListeners).then(addEventListeners.bind(this));
@@ -79,8 +92,9 @@ EventListeners.EventListenersView = class extends UI.VBox {
* @return {!Promise<undefined>}
*/
function markInternalEventListeners() {
- if (!frameworkEventListenersObject.internalHandlers)
+ if (!frameworkEventListenersObject.internalHandlers) {
return Promise.resolve(undefined);
+ }
return frameworkEventListenersObject.internalHandlers.object()
.callFunctionJSON(isInternalEventListener, eventListeners.map(handlerArgument))
.then(setIsInternal);
@@ -101,8 +115,9 @@ EventListeners.EventListenersView = class extends UI.VBox {
function isInternalEventListener() {
const isInternal = [];
const internalHandlersSet = new Set(this);
- for (const handler of arguments)
+ for (const handler of arguments) {
isInternal.push(internalHandlersSet.has(handler));
+ }
return isInternal;
}
@@ -111,8 +126,9 @@ EventListeners.EventListenersView = class extends UI.VBox {
*/
function setIsInternal(isInternal) {
for (let i = 0; i < eventListeners.length; ++i) {
- if (isInternal[i])
+ if (isInternal[i]) {
eventListeners[i].markAsFramework();
+ }
}
}
}
@@ -131,8 +147,9 @@ EventListeners.EventListenersView = class extends UI.VBox {
* @param {?Array<!SDK.EventListener>} eventListeners
*/
_addObjectEventListeners(object, eventListeners) {
- if (!eventListeners)
+ if (!eventListeners) {
return;
+ }
for (const eventListener of eventListeners) {
const treeItem = this._getOrCreateTreeElementForType(eventListener.type());
treeItem.addObjectEventListener(eventListener, object);
@@ -151,14 +168,18 @@ EventListeners.EventListenersView = class extends UI.VBox {
for (const listenerElement of eventType.children()) {
const listenerOrigin = listenerElement.eventListener().origin();
let hidden = false;
- if (listenerOrigin === SDK.EventListener.Origin.FrameworkUser && !showFramework)
+ if (listenerOrigin === SDK.EventListener.Origin.FrameworkUser && !showFramework) {
hidden = true;
- if (listenerOrigin === SDK.EventListener.Origin.Framework && showFramework)
+ }
+ if (listenerOrigin === SDK.EventListener.Origin.Framework && showFramework) {
hidden = true;
- if (!showPassive && listenerElement.eventListener().passive())
+ }
+ if (!showPassive && listenerElement.eventListener().passive()) {
hidden = true;
- if (!showBlocking && !listenerElement.eventListener().passive())
+ }
+ if (!showBlocking && !listenerElement.eventListener().passive()) {
hidden = true;
+ }
listenerElement.hidden = hidden;
hiddenEventType = hiddenEventType && hidden;
}
@@ -188,19 +209,23 @@ EventListeners.EventListenersView = class extends UI.VBox {
for (const eventType of this._treeOutline.rootElement().children()) {
eventType.hidden = !eventType.firstChild();
allHidden = allHidden && eventType.hidden;
- if (!firstVisibleChild && !eventType.hidden)
+ if (!firstVisibleChild && !eventType.hidden) {
firstVisibleChild = eventType;
+ }
}
- if (allHidden && !this._emptyHolder.parentNode)
+ if (allHidden && !this._emptyHolder.parentNode) {
this.element.appendChild(this._emptyHolder);
- if (firstVisibleChild)
+ }
+ if (firstVisibleChild) {
firstVisibleChild.select(true /* omitFocus */);
+ }
}
reset() {
const eventTypes = this._treeOutline.rootElement().children();
- for (const eventType of eventTypes)
+ for (const eventType of eventTypes) {
eventType.removeChildren();
+ }
this._linkifier.reset();
}
@@ -230,8 +255,9 @@ EventListeners.EventListenersTreeElement = class extends UI.TreeElement {
* @return {number}
*/
static comparator(element1, element2) {
- if (element1.title === element2.title)
+ if (element1.title === element2.title) {
return 0;
+ }
return element1.title > element2.title ? 1 : -1;
}
@@ -276,8 +302,9 @@ EventListeners.ObjectEventListenerBar = class extends UI.TreeElement {
properties.push(runtimeModel.createRemotePropertyFromPrimitiveValue('useCapture', eventListener.useCapture()));
properties.push(runtimeModel.createRemotePropertyFromPrimitiveValue('passive', eventListener.passive()));
properties.push(runtimeModel.createRemotePropertyFromPrimitiveValue('once', eventListener.once()));
- if (typeof eventListener.handler() !== 'undefined')
+ if (typeof eventListener.handler() !== 'undefined') {
properties.push(new SDK.RemoteObjectProperty('handler', eventListener.handler()));
+ }
ObjectUI.ObjectPropertyTreeElement.populateWithProperties(this, properties, [], true, null);
}
@@ -286,18 +313,23 @@ EventListeners.ObjectEventListenerBar = class extends UI.TreeElement {
* @param {!Components.Linkifier} linkifier
*/
_setTitle(object, linkifier) {
- const title = this.listItemElement.createChild('span');
+ const title = this.listItemElement.createChild('span', 'event-listener-details');
const subtitle = this.listItemElement.createChild('span', 'event-listener-tree-subtitle');
- subtitle.appendChild(linkifier.linkifyRawLocation(this._eventListener.location(), this._eventListener.sourceURL()));
+ const linkElement = linkifier.linkifyRawLocation(this._eventListener.location(), this._eventListener.sourceURL());
+ subtitle.appendChild(linkElement);
- title.appendChild(
- ObjectUI.ObjectPropertiesSection.createValueElement(object, false /* wasThrown */, false /* showPreview */));
+ this._valueTitle =
+ ObjectUI.ObjectPropertiesSection.createValueElement(object, false /* wasThrown */, false /* showPreview */);
+ title.appendChild(this._valueTitle);
if (this._eventListener.canRemove()) {
const deleteButton = title.createChild('span', 'event-listener-button');
deleteButton.textContent = Common.UIString('Remove');
deleteButton.title = Common.UIString('Delete event listener');
- deleteButton.addEventListener('click', removeListener.bind(this), false);
+ deleteButton.addEventListener('click', event => {
+ this._removeListener();
+ event.consume();
+ }, false);
title.appendChild(deleteButton);
}
@@ -305,39 +337,47 @@ EventListeners.ObjectEventListenerBar = class extends UI.TreeElement {
const passiveButton = title.createChild('span', 'event-listener-button');
passiveButton.textContent = Common.UIString('Toggle Passive');
passiveButton.title = Common.UIString('Toggle whether event listener is passive or blocking');
- passiveButton.addEventListener('click', togglePassiveListener.bind(this), false);
+ passiveButton.addEventListener('click', event => {
+ this._togglePassiveListener();
+ event.consume();
+ }, false);
title.appendChild(passiveButton);
}
- /**
- * @param {!Event} event
- * @this {EventListeners.ObjectEventListenerBar}
- */
- function removeListener(event) {
- event.consume();
- this._removeListenerBar();
- this._eventListener.remove();
- }
+ this.listItemElement.addEventListener('contextmenu', event => {
+ const menu = new UI.ContextMenu(event);
+ if (event.target !== linkElement) {
+ menu.appendApplicableItems(linkElement);
+ }
+ menu.defaultSection().appendItem(
+ ls`Delete event listener`, this._removeListener.bind(this), !this._eventListener.canRemove());
+ menu.defaultSection().appendCheckboxItem(
+ ls`Passive`, this._togglePassiveListener.bind(this), this._eventListener.passive(),
+ !this._eventListener.canTogglePassive());
+ menu.show();
+ });
+ }
- /**
- * @param {!Event} event
- * @this {EventListeners.ObjectEventListenerBar}
- */
- function togglePassiveListener(event) {
- event.consume();
- this._eventListener.togglePassive().then(this._changeCallback());
- }
+ _removeListener() {
+ this._removeListenerBar();
+ this._eventListener.remove();
+ }
+
+ _togglePassiveListener() {
+ this._eventListener.togglePassive().then(this._changeCallback());
}
_removeListenerBar() {
const parent = this.parent;
parent.removeChild(this);
- if (!parent.childCount())
+ if (!parent.childCount()) {
parent.collapse();
+ }
let allHidden = true;
for (let i = 0; i < parent.childCount(); ++i) {
- if (!parent.childAt(i).hidden)
+ if (!parent.childAt(i).hidden) {
allHidden = false;
+ }
}
parent.hidden = allHidden;
}
@@ -348,4 +388,16 @@ EventListeners.ObjectEventListenerBar = class extends UI.TreeElement {
eventListener() {
return this._eventListener;
}
+
+ /**
+ * @override
+ */
+ onenter() {
+ if (this._valueTitle) {
+ this._valueTitle.click();
+ return true;
+ }
+
+ return false;
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/eventListenersView.css b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/eventListenersView.css
index 4db4d89b896..9f43c975829 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/eventListenersView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/eventListenersView.css
@@ -7,8 +7,9 @@
.tree-outline-disclosure li {
padding: 2px 0 0 5px;
overflow: hidden;
- display: list-item;
+ display: flex;
min-height: 17px;
+ align-items: baseline;
}
.tree-outline-disclosure > li {
@@ -32,9 +33,19 @@
color: rgb(136, 19, 145);
}
+.tree-outline-disclosure .object-value-node {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.event-listener-details {
+ display: flex;
+}
+
.event-listener-tree-subtitle {
float: right;
margin-left: 5px;
+ flex-shrink: 0;
}
.event-listener-button {
@@ -43,12 +54,15 @@
border-radius: 3px;
border: 1px solid #c3c3c3;
margin-left: 10px;
- display: none;
+ display: block;
cursor: pointer;
+ opacity: 0.8;
+ flex-shrink: 0;
}
.event-listener-button:hover {
background-color: #e0e0e0;
+ opacity: 1;
}
.tree-outline-disclosure li:hover .event-listener-button {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
index 688e675d22b..0ae06b984d2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/event_listeners/event_listeners_strings.grdp
@@ -3,9 +3,6 @@
<message name="IDS_DEVTOOLS_0b9c1def3b0d84fe6234388ff8dfa8b7" desc="Passive button title in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
Toggle whether event listener is passive or blocking
</message>
- <message name="IDS_DEVTOOLS_1063e38cb53d94d386f21227fcd84717" desc="Delete button text content in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
- Remove
- </message>
<message name="IDS_DEVTOOLS_7667495b756ef15210cd60285d8de58a" desc="Empty holder text content in Event Listeners View of the Event Listener Debugging pane in the Sources panel">
No event listeners
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionAPI.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionAPI.js
index 0d3b2ad20d4..f89fd797f9b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionAPI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionAPI.js
@@ -28,11 +28,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* eslint-disable indent */
-
function defineCommonExtensionSymbols(apiPrivate) {
- if (!apiPrivate.panels)
+ if (!apiPrivate.panels) {
apiPrivate.panels = {};
+ }
apiPrivate.panels.SearchAction = {
CancelSearch: 'cancelSearch',
PerformSearch: 'performSearch',
@@ -94,12 +93,14 @@ function defineCommonExtensionSymbols(apiPrivate) {
* @param {function(!Object, !Object)} testHook
* @suppressGlobalPropertiesCheck
*/
-function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToForward, testHook, injectedScriptId) {
+self.injectedExtensionAPI = function(
+ extensionInfo, inspectedTabId, themeName, keysToForward, testHook, injectedScriptId) {
const keysToForwardSet = new Set(keysToForward);
const chrome = window.chrome || {};
const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
- if (devtools_descriptor)
+ if (devtools_descriptor) {
return;
+ }
const apiPrivate = {};
@@ -126,10 +127,12 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
EventSinkImpl.prototype = {
addListener: function(callback) {
- if (typeof callback !== 'function')
+ if (typeof callback !== 'function') {
throw 'addListener: callback is not a function';
- if (this._listeners.length === 0)
+ }
+ if (this._listeners.length === 0) {
extensionServer.sendRequest({command: commands.Subscribe, type: this._type});
+ }
this._listeners.push(callback);
extensionServer.registerHandler('notify-' + this._type, this._dispatch.bind(this));
},
@@ -143,8 +146,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
break;
}
}
- if (this._listeners.length === 0)
+ if (this._listeners.length === 0) {
extensionServer.sendRequest({command: commands.Unsubscribe, type: this._type});
+ }
},
/**
@@ -152,15 +156,17 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
*/
_fire: function(vararg) {
const listeners = this._listeners.slice();
- for (let i = 0; i < listeners.length; ++i)
+ for (let i = 0; i < listeners.length; ++i) {
listeners[i].apply(null, arguments);
+ }
},
_dispatch: function(request) {
- if (this._customDispatch)
+ if (this._customDispatch) {
this._customDispatch.call(this, request);
- else
+ } else {
this._fire.apply(this, request.arguments);
+ }
}
};
@@ -239,8 +245,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
function panelGetter(name) {
return panels[name];
}
- for (const panel in panels)
- this.__defineGetter__(panel, panelGetter.bind(null, panel));
+ for (const panel in panels) {
+ Object.defineProperty(this, panel, {get: panelGetter.bind(null, panel), enumerable: true});
+ }
this.applyStyleSheet = function(styleSheet) {
extensionServer.sendRequest({command: commands.ApplyStyleSheet, styleSheet: styleSheet});
};
@@ -266,14 +273,16 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
}
}
- if (!callback)
+ if (!callback) {
extensionServer.unregisterHandler(events.OpenResource);
- else
+ } else {
extensionServer.registerHandler(events.OpenResource, callbackWrapper);
+ }
// Only send command if we either removed an existing handler or added handler and had none before.
- if (hadHandler === !callback)
+ if (hadHandler === !callback) {
extensionServer.sendRequest({command: commands.SetOpenResourceHandler, 'handlerPresent': !!callback});
+ }
},
openResource: function(url, lineNumber, callback) {
@@ -296,10 +305,11 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
*/
function dispatchShowEvent(message) {
const frameIndex = message.arguments[0];
- if (typeof frameIndex === 'number')
+ if (typeof frameIndex === 'number') {
this._fire(window.parent.frames[frameIndex]);
- else
+ } else {
this._fire();
+ }
}
if (id) {
@@ -361,31 +371,27 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
const EventSink = declareInterfaceClass(EventSinkImpl);
const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
const ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
- const PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
+ /**
+ * @constructor
+ * @param {string} hostPanelName
+ */
+ const PanelWithSidebarClass = declareInterfaceClass(PanelWithSidebarImpl);
const Request = declareInterfaceClass(RequestImpl);
const Resource = declareInterfaceClass(ResourceImpl);
const TraceSession = declareInterfaceClass(TraceSessionImpl);
- /**
- * @constructor
- * @extends {PanelWithSidebar}
- */
- function ElementsPanel() {
- PanelWithSidebar.call(this, 'elements');
+ class ElementsPanel extends PanelWithSidebarClass {
+ constructor() {
+ super('elements');
+ }
}
- ElementsPanel.prototype = {__proto__: PanelWithSidebar.prototype};
-
- /**
- * @constructor
- * @extends {PanelWithSidebar}
- */
- function SourcesPanel() {
- PanelWithSidebar.call(this, 'sources');
+ class SourcesPanel extends PanelWithSidebarClass {
+ constructor() {
+ super('sources');
+ }
}
- SourcesPanel.prototype = {__proto__: PanelWithSidebar.prototype};
-
/**
* @constructor
* @extends {ExtensionViewImpl}
@@ -414,8 +420,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
},
show: function() {
- if (!userAction)
+ if (!userAction) {
return;
+ }
const request = {command: commands.ShowPanel, id: this._id};
extensionServer.sendRequest(request);
@@ -445,8 +452,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
rootTitle: rootTitle,
evaluateOnPage: true,
};
- if (typeof evaluateOptions === 'object')
+ if (typeof evaluateOptions === 'object') {
request.evaluateOptions = evaluateOptions;
+ }
extensionServer.sendRequest(request, extractCallbackArgument(arguments));
},
@@ -577,14 +585,16 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
eval: function(expression, evaluateOptions) {
const callback = extractCallbackArgument(arguments);
function callbackWrapper(result) {
- if (result.isError || result.isException)
+ if (result.isError || result.isException) {
callback(undefined, result);
- else
+ } else {
callback(result.value);
+ }
}
const request = {command: commands.EvaluateOnInspectedPage, expression: expression};
- if (typeof evaluateOptions === 'object')
+ if (typeof evaluateOptions === 'object') {
request.evaluateOptions = evaluateOptions;
+ }
extensionServer.sendRequest(request, callback && callbackWrapper);
return null;
},
@@ -640,18 +650,23 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
function forwardKeyboardEvent(event) {
let modifiers = 0;
- if (event.shiftKey)
+ if (event.shiftKey) {
modifiers |= 1;
- if (event.ctrlKey)
+ }
+ if (event.ctrlKey) {
modifiers |= 2;
- if (event.altKey)
+ }
+ if (event.altKey) {
modifiers |= 4;
- if (event.metaKey)
+ }
+ if (event.metaKey) {
modifiers |= 8;
+ }
const num = (event.keyCode & 255) | (modifiers << 8);
// We only care about global hotkeys, not about random text
- if (!keysToForwardSet.has(num))
+ if (!keysToForwardSet.has(num)) {
return;
+ }
event.preventDefault();
const requestPayload = {
eventType: event.type,
@@ -666,8 +681,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
keyCode: event.keyCode
};
keyboardEventRequestQueue.push(requestPayload);
- if (!forwardTimer)
+ if (!forwardTimer) {
forwardTimer = setTimeout(forwardEventQueue, 0);
+ }
}
function forwardEventQueue() {
@@ -704,8 +720,9 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
* @param {function()=} callback
*/
sendRequest: function(message, callback) {
- if (typeof callback === 'function')
+ if (typeof callback === 'function') {
message.requestId = this._registerCallback(callback);
+ }
this._port.postMessage(message);
},
@@ -748,27 +765,32 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
_onMessage: function(event) {
const request = event.data;
const handler = this._handlers[request.command];
- if (handler)
+ if (handler) {
handler.call(this, request);
+ }
}
};
function populateInterfaceClass(interfaze, implementation) {
for (const member in implementation) {
- if (member.charAt(0) === '_')
+ if (member.charAt(0) === '_') {
continue;
+ }
let descriptor = null;
// Traverse prototype chain until we find the owner.
- for (let owner = implementation; owner && !descriptor; owner = owner.__proto__)
+ for (let owner = implementation; owner && !descriptor; owner = owner.__proto__) {
descriptor = Object.getOwnPropertyDescriptor(owner, member);
- if (!descriptor)
+ }
+ if (!descriptor) {
continue;
- if (typeof descriptor.value === 'function')
+ }
+ if (typeof descriptor.value === 'function') {
interfaze[member] = descriptor.value.bind(implementation);
- else if (typeof descriptor.get === 'function')
+ } else if (typeof descriptor.get === 'function') {
interfaze.__defineGetter__(member, descriptor.get.bind(implementation));
- else
+ } else {
Object.defineProperty(interfaze, member, descriptor);
+ }
}
}
@@ -779,7 +801,7 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
// Only expose tabId on chrome.devtools.inspectedWindow, not webInspector.inspectedWindow.
chrome.devtools.inspectedWindow = {};
- chrome.devtools.inspectedWindow.__defineGetter__('tabId', getTabId);
+ Object.defineProperty(chrome.devtools.inspectedWindow, 'tabId', {get: getTabId});
chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
chrome.devtools.network = coreAPI.network;
chrome.devtools.panels = coreAPI.panels;
@@ -793,16 +815,18 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
const properties = Object.getOwnPropertyNames(coreAPI);
for (let i = 0; i < properties.length; ++i) {
const descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
- if (descriptor)
+ if (descriptor) {
Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
+ }
}
chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
}
- if (extensionInfo.exposeWebInspectorNamespace)
+ if (extensionInfo.exposeWebInspectorNamespace) {
window.webInspector = coreAPI;
+ }
testHook(extensionServer, coreAPI);
-}
+};
/**
* @param {!ExtensionDescriptor} extensionInfo
@@ -814,9 +838,19 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToFo
*/
self.buildExtensionAPIInjectedScript = function(extensionInfo, inspectedTabId, themeName, keysToForward, testHook) {
const argumentsJSON = [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
- if (!testHook)
+ if (!testHook) {
testHook = () => {};
+ }
return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString() + ';' +
- '(' + injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
+ '(' + self.injectedExtensionAPI.toString() + ')(' + argumentsJSON + ',' + testHook + ', injectedScriptId);' +
'})';
};
+
+/* Legacy exported object */
+self.Extensions = self.Extensions || {};
+
+/* Legacy exported object */
+Extensions = Extensions || {};
+
+Extensions.extensionAPI = {};
+defineCommonExtensionSymbols(Extensions.extensionAPI); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionPanel.js
index fa58d122a76..d849ee1e887 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionPanel.js
@@ -31,7 +31,7 @@
* @implements {UI.Searchable}
* @unrestricted
*/
-Extensions.ExtensionPanel = class extends UI.Panel {
+export default class ExtensionPanel extends UI.Panel {
/**
* @param {!Extensions.ExtensionServer} server
* @param {string} panelName
@@ -116,12 +116,12 @@ Extensions.ExtensionPanel = class extends UI.Panel {
supportsRegexSearch() {
return false;
}
-};
+}
/**
* @unrestricted
*/
-Extensions.ExtensionButton = class {
+export class ExtensionButton {
/**
* @param {!Extensions.ExtensionServer} server
* @param {string} id
@@ -144,12 +144,15 @@ Extensions.ExtensionButton = class {
* @param {boolean=} disabled
*/
update(iconURL, tooltip, disabled) {
- if (typeof iconURL === 'string')
+ if (typeof iconURL === 'string') {
this._toolbarButton.setBackgroundImage(iconURL);
- if (typeof tooltip === 'string')
+ }
+ if (typeof tooltip === 'string') {
this._toolbarButton.setTitle(tooltip);
- if (typeof disabled === 'boolean')
+ }
+ if (typeof disabled === 'boolean') {
this._toolbarButton.setEnabled(!disabled);
+ }
}
/**
@@ -158,12 +161,12 @@ Extensions.ExtensionButton = class {
toolbarButton() {
return this._toolbarButton;
}
-};
+}
/**
* @unrestricted
*/
-Extensions.ExtensionSidebarPane = class extends UI.SimpleView {
+export class ExtensionSidebarPane extends UI.SimpleView {
/**
* @param {!Extensions.ExtensionServer} server
* @param {string} panelName
@@ -223,14 +226,16 @@ Extensions.ExtensionSidebarPane = class extends UI.SimpleView {
this._objectPropertiesView.detach();
delete this._objectPropertiesView;
}
- if (this._extensionView)
+ if (this._extensionView) {
this._extensionView.detach(true);
+ }
this._extensionView = new Extensions.ExtensionView(this._server, this._id, url, 'extension fill');
this._extensionView.show(this.element);
- if (!this.element.style.height)
+ if (!this.element.style.height) {
this.setHeight('150px');
+ }
}
/**
@@ -248,15 +253,17 @@ Extensions.ExtensionSidebarPane = class extends UI.SimpleView {
* @param {boolean=} wasThrown
*/
_onEvaluate(title, callback, error, result, wasThrown) {
- if (error || !result)
+ if (error || !result) {
callback(error.toString());
- else
+ } else {
this._setObject(result, title, callback);
+ }
}
_createObjectPropertiesView() {
- if (this._objectPropertiesView)
+ if (this._objectPropertiesView) {
return;
+ }
if (this._extensionView) {
this._extensionView.detach(true);
delete this._extensionView;
@@ -282,10 +289,26 @@ Extensions.ExtensionSidebarPane = class extends UI.SimpleView {
callback();
return;
}
- if (result.tree && result.tree.firstChild())
+ if (result.tree && result.tree.firstChild()) {
result.tree.firstChild().expand();
+ }
this._objectPropertiesView.element.appendChild(result.node);
callback();
});
}
-};
+}
+
+/* Legacy exported object */
+self.Extensions = self.Extensions || {};
+
+/* Legacy exported object */
+Extensions = Extensions || {};
+
+/** @constructor */
+Extensions.ExtensionPanel = ExtensionPanel;
+
+/** @constructor */
+Extensions.ExtensionButton = ExtensionButton;
+
+/** @constructor */
+Extensions.ExtensionSidebarPane = ExtensionSidebarPane; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js
index 290f12561cc..62945a733b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Extensions.ExtensionServer = class extends Common.Object {
+export default class ExtensionServer extends Common.Object {
/**
* @suppressGlobalPropertiesCheck
*/
@@ -46,7 +46,7 @@ Extensions.ExtensionServer = class extends Common.Object {
this._requests = {};
this._lastRequestId = 0;
this._registeredExtensions = {};
- this._status = new Extensions.ExtensionStatus();
+ this._status = new ExtensionStatus();
/** @type {!Array<!Extensions.ExtensionSidebarPane>} */
this._sidebarPanes = [];
/** @type {!Array<!Extensions.ExtensionTraceProvider>} */
@@ -82,14 +82,14 @@ Extensions.ExtensionServer = class extends Common.Object {
this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this));
window.addEventListener('message', this._onWindowMessage.bind(this), false); // Only for main window.
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.SetInspectedTabId, this._setInspectedTabId, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.SetInspectedTabId, this._setInspectedTabId, this);
this._initExtensions();
}
initializeExtensions() {
- InspectorFrontendHost.setAddExtensionCallback(this._addExtension.bind(this));
+ Host.InspectorFrontendHost.setAddExtensionCallback(this._addExtension.bind(this));
}
/**
@@ -131,8 +131,9 @@ Extensions.ExtensionServer = class extends Common.Object {
}
_inspectedURLChanged(event) {
- if (event.data !== SDK.targetManager.mainTarget())
+ if (event.data !== SDK.targetManager.mainTarget()) {
return;
+ }
this._requests = {};
const url = event.data.inspectedURL();
this._postNotification(Extensions.extensionAPI.Events.InspectedURLChanged, url);
@@ -169,11 +170,13 @@ Extensions.ExtensionServer = class extends Common.Object {
*/
_postNotification(type, vararg) {
const subscribers = this._subscribers[type];
- if (!subscribers)
+ if (!subscribers) {
return;
+ }
const message = {command: 'notify-' + type, arguments: Array.prototype.slice.call(arguments, 1)};
- for (let i = 0; i < subscribers.length; ++i)
+ for (let i = 0; i < subscribers.length; ++i) {
subscribers[i].postMessage(message);
+ }
}
_onSubscribe(message, port) {
@@ -182,40 +185,46 @@ Extensions.ExtensionServer = class extends Common.Object {
subscribers.push(port);
} else {
this._subscribers[message.type] = [port];
- if (this._subscriptionStartHandlers[message.type])
+ if (this._subscriptionStartHandlers[message.type]) {
this._subscriptionStartHandlers[message.type]();
+ }
}
}
_onUnsubscribe(message, port) {
const subscribers = this._subscribers[message.type];
- if (!subscribers)
+ if (!subscribers) {
return;
+ }
subscribers.remove(port);
if (!subscribers.length) {
delete this._subscribers[message.type];
- if (this._subscriptionStopHandlers[message.type])
+ if (this._subscriptionStopHandlers[message.type]) {
this._subscriptionStopHandlers[message.type]();
+ }
}
}
_onAddRequestHeaders(message) {
const id = message.extensionId;
- if (typeof id !== 'string')
+ if (typeof id !== 'string') {
return this._status.E_BADARGTYPE('extensionId', typeof id, 'string');
+ }
let extensionHeaders = this._extraHeaders[id];
if (!extensionHeaders) {
extensionHeaders = {};
this._extraHeaders[id] = extensionHeaders;
}
- for (const name in message.headers)
+ for (const name in message.headers) {
extensionHeaders[name] = message.headers[name];
+ }
const allHeaders = /** @type {!Protocol.Network.Headers} */ ({});
for (const extension in this._extraHeaders) {
const headers = this._extraHeaders[extension];
for (const name in headers) {
- if (typeof headers[name] === 'string')
+ if (typeof headers[name] === 'string') {
allHeaders[name] = headers[name];
+ }
}
}
@@ -227,8 +236,9 @@ Extensions.ExtensionServer = class extends Common.Object {
* @suppressGlobalPropertiesCheck
*/
_onApplyStyleSheet(message) {
- if (!Runtime.experiments.isEnabled('applyCustomStylesheet'))
+ if (!Root.Runtime.experiments.isEnabled('applyCustomStylesheet')) {
return;
+ }
const styleSheet = createElement('style');
styleSheet.textContent = message.styleSheet;
document.head.appendChild(styleSheet);
@@ -236,8 +246,9 @@ Extensions.ExtensionServer = class extends Common.Object {
UI.themeSupport.addCustomStylesheet(message.styleSheet);
// Add to all the shadow roots that have already been created
for (let node = document.body; node; node = node.traverseNextNode(document.body)) {
- if (node instanceof ShadowRoot)
+ if (node instanceof ShadowRoot) {
UI.themeSupport.injectCustomStyleSheets(node);
+ }
}
}
@@ -245,13 +256,14 @@ Extensions.ExtensionServer = class extends Common.Object {
const id = message.id;
// The ids are generated on the client API side and must be unique, so the check below
// shouldn't be hit unless someone is bypassing the API.
- if (id in this._clientObjects || UI.inspectorView.hasPanel(id))
+ if (id in this._clientObjects || UI.inspectorView.hasPanel(id)) {
return this._status.E_EXISTS(id);
+ }
const page = this._expandResourcePath(port._extensionOrigin, message.page);
let persistentId = port._extensionOrigin + message.title;
persistentId = persistentId.replace(/\s/g, '');
- const panelView = new Extensions.ExtensionServerPanelView(
+ const panelView = new ExtensionServerPanelView(
persistentId, message.title, new Extensions.ExtensionPanel(this, persistentId, id, page));
this._clientObjects[id] = panelView;
UI.inspectorView.addPanel(panelView);
@@ -261,15 +273,17 @@ Extensions.ExtensionServer = class extends Common.Object {
_onShowPanel(message) {
let panelViewId = message.id;
const panelView = this._clientObjects[message.id];
- if (panelView && panelView instanceof Extensions.ExtensionServerPanelView)
+ if (panelView && panelView instanceof ExtensionServerPanelView) {
panelViewId = panelView.viewId();
+ }
UI.inspectorView.showPanel(panelViewId);
}
_onCreateToolbarButton(message, port) {
const panelView = this._clientObjects[message.panel];
- if (!panelView || !(panelView instanceof Extensions.ExtensionServerPanelView))
+ if (!panelView || !(panelView instanceof ExtensionServerPanelView)) {
return this._status.E_NOTFOUND(message.panel);
+ }
const button = new Extensions.ExtensionButton(
this, message.id, this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip,
message.disabled);
@@ -289,8 +303,9 @@ Extensions.ExtensionServer = class extends Common.Object {
_onUpdateButton(message, port) {
const button = this._clientObjects[message.id];
- if (!button || !(button instanceof Extensions.ExtensionButton))
+ if (!button || !(button instanceof Extensions.ExtensionButton)) {
return this._status.E_NOTFOUND(message.id);
+ }
button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled);
return this._status.OK();
}
@@ -300,20 +315,22 @@ Extensions.ExtensionServer = class extends Common.Object {
*/
_onCompleteTraceSession(message) {
const session = this._traceSessions.get(message.id);
- if (!session)
+ if (!session) {
return this._status.E_NOTFOUND(message.id);
+ }
this._traceSessions.delete(message.id);
session.complete(message.url, message.timeOffset);
}
_onCreateSidebarPane(message) {
- if (message.panel !== 'elements' && message.panel !== 'sources')
+ if (message.panel !== 'elements' && message.panel !== 'sources') {
return this._status.E_NOTFOUND(message.panel);
+ }
const id = message.id;
const sidebar = new Extensions.ExtensionSidebarPane(this, message.panel, message.title, id);
this._sidebarPanes.push(sidebar);
this._clientObjects[id] = sidebar;
- this.dispatchEventToListeners(Extensions.ExtensionServer.Events.SidebarPaneAdded, sidebar);
+ this.dispatchEventToListeners(Events.SidebarPaneAdded, sidebar);
return this._status.OK();
}
@@ -327,19 +344,21 @@ Extensions.ExtensionServer = class extends Common.Object {
_onSetSidebarHeight(message) {
const sidebar = this._clientObjects[message.id];
- if (!sidebar)
+ if (!sidebar) {
return this._status.E_NOTFOUND(message.id);
+ }
sidebar.setHeight(message.height);
return this._status.OK();
}
_onSetSidebarContent(message, port) {
const sidebar = this._clientObjects[message.id];
- if (!sidebar)
+ if (!sidebar) {
return this._status.E_NOTFOUND(message.id);
+ }
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function callback(error) {
const result = error ? this._status.E_FAILED(error) : this._status.OK();
@@ -354,8 +373,9 @@ Extensions.ExtensionServer = class extends Common.Object {
_onSetSidebarPage(message, port) {
const sidebar = this._clientObjects[message.id];
- if (!sidebar)
+ if (!sidebar) {
return this._status.E_NOTFOUND(message.id);
+ }
sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page));
}
@@ -383,10 +403,11 @@ Extensions.ExtensionServer = class extends Common.Object {
_onSetOpenResourceHandler(message, port) {
const name = this._registeredExtensions[port._extensionOrigin].name || ('Extension ' + port._extensionOrigin);
- if (message.handlerPresent)
+ if (message.handlerPresent) {
Components.Linkifier.registerLinkHandler(name, this._handleOpenURL.bind(this, port));
- else
+ } else {
Components.Linkifier.unregisterLinkHandler(name);
+ }
}
_handleOpenURL(port, contentProvider, lineNumber) {
@@ -399,8 +420,9 @@ Extensions.ExtensionServer = class extends Common.Object {
SDK.multitargetNetworkManager.setUserAgentOverride(typeof options.userAgent === 'string' ? options.userAgent : '');
let injectedScript;
- if (options.injectedScript)
+ if (options.injectedScript) {
injectedScript = '(function(){' + options.injectedScript + '})()';
+ }
SDK.ResourceTreeModel.reloadAllPages(!!options.ignoreCache, injectedScript);
return this._status.OK();
}
@@ -410,16 +432,17 @@ Extensions.ExtensionServer = class extends Common.Object {
* @param {?Protocol.Error} error
* @param {?SDK.RemoteObject} object
* @param {boolean} wasThrown
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function callback(error, object, wasThrown) {
let result;
- if (error || !object)
+ if (error || !object) {
result = this._status.E_PROTOCOLERROR(error.toString());
- else if (wasThrown)
+ } else if (wasThrown) {
result = {isException: true, value: object.description};
- else
+ } else {
result = {value: object.value};
+ }
this._dispatchCallback(message.requestId, port, result);
}
@@ -430,8 +453,9 @@ Extensions.ExtensionServer = class extends Common.Object {
async _onGetHAR() {
const requests = SDK.networkLog.requests();
const harLog = await SDK.HARLog.build(requests);
- for (let i = 0; i < harLog.entries.length; ++i)
+ for (let i = 0; i < harLog.entries.length; ++i) {
harLog.entries[i]._requestId = this._requestId(requests[i]);
+ }
return harLog;
}
@@ -450,18 +474,20 @@ Extensions.ExtensionServer = class extends Common.Object {
const resources = new Map();
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function pushResourceData(contentProvider) {
- if (!resources.has(contentProvider.contentURL()))
+ if (!resources.has(contentProvider.contentURL())) {
resources.set(contentProvider.contentURL(), this._makeResource(contentProvider));
+ }
}
let uiSourceCodes = Workspace.workspace.uiSourceCodesForProjectType(Workspace.projectTypes.Network);
uiSourceCodes =
uiSourceCodes.concat(Workspace.workspace.uiSourceCodesForProjectType(Workspace.projectTypes.ContentScripts));
uiSourceCodes.forEach(pushResourceData.bind(this));
- for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel))
+ for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
resourceTreeModel.forAllResources(pushResourceData.bind(this));
+ }
return resources.valuesArray();
}
@@ -471,30 +497,32 @@ Extensions.ExtensionServer = class extends Common.Object {
* @param {!MessagePort} port
*/
async _getResourceContent(contentProvider, message, port) {
- const content = await contentProvider.requestContent();
+ const {content} = await contentProvider.requestContent();
const encoded = await contentProvider.contentEncoded();
this._dispatchCallback(message.requestId, port, {encoding: encoded ? 'base64' : '', content: content});
}
_onGetRequestContent(message, port) {
const request = this._requestById(message.id);
- if (!request)
+ if (!request) {
return this._status.E_NOTFOUND(message.id);
+ }
this._getResourceContent(request, message, port);
}
_onGetResourceContent(message, port) {
const url = /** @type {string} */ (message.url);
const contentProvider = Workspace.workspace.uiSourceCodeForURL(url) || Bindings.resourceForURL(url);
- if (!contentProvider)
+ if (!contentProvider) {
return this._status.E_NOTFOUND(url);
+ }
this._getResourceContent(contentProvider, message, port);
}
_onSetResourceContent(message, port) {
/**
* @param {?Protocol.Error} error
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function callbackWrapper(error) {
const response = error ? this._status.E_FAILED(error) : this._status.OK();
@@ -505,13 +533,15 @@ Extensions.ExtensionServer = class extends Common.Object {
const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
if (!uiSourceCode || !uiSourceCode.contentType().isDocumentOrScriptOrStyleSheet()) {
const resource = SDK.ResourceTreeModel.resourceForURL(url);
- if (!resource)
+ if (!resource) {
return this._status.E_NOTFOUND(url);
+ }
return this._status.E_NOTSUPPORTED('Resource is not editable');
}
uiSourceCode.setWorkingCopy(message.content);
- if (message.commit)
+ if (message.commit) {
uiSourceCode.commitWorkingCopy();
+ }
callbackWrapper.call(this, null);
}
@@ -536,7 +566,7 @@ Extensions.ExtensionServer = class extends Common.Object {
port._extensionOrigin, message.id, message.categoryName, message.categoryTooltip);
this._clientObjects[message.id] = provider;
this._traceProviders.push(provider);
- this.dispatchEventToListeners(Extensions.ExtensionServer.Events.TraceProviderAdded, provider);
+ this.dispatchEventToListeners(Events.TraceProviderAdded, provider);
}
/**
@@ -574,16 +604,18 @@ Extensions.ExtensionServer = class extends Common.Object {
let keyCode = entry.keyCode;
if (!keyCode) {
// This is required only for synthetic events (e.g. dispatched in tests).
- if (entry.key === 'Escape')
+ if (entry.key === 'Escape') {
keyCode = 27;
+ }
}
return keyCode || 0;
}
}
_dispatchCallback(requestId, port, result) {
- if (requestId)
+ if (requestId) {
port.postMessage({command: 'callback', requestId: requestId, result: result});
+ }
}
_initExtensions() {
@@ -595,14 +627,14 @@ Extensions.ExtensionServer = class extends Common.Object {
SDK.NetworkManager.Events.RequestFinished, this._notifyRequestFinished);
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function onElementsSubscriptionStarted() {
UI.context.addFlavorChangeListener(SDK.DOMNode, this._notifyElementsSelectionChanged, this);
}
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function onElementsSubscriptionStopped() {
UI.context.removeFlavorChangeListener(SDK.DOMNode, this._notifyElementsSelectionChanged, this);
@@ -677,11 +709,10 @@ Extensions.ExtensionServer = class extends Common.Object {
const extensionOrigin = originMatch[1];
if (!this._registeredExtensions[extensionOrigin]) {
// See ExtensionAPI.js for details.
- const injectedAPI = buildExtensionAPIInjectedScript(
- extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(),
- UI.shortcutRegistry.globalShortcutKeys(),
+ const injectedAPI = self.buildExtensionAPIInjectedScript(
+ extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(), UI.shortcutRegistry.globalShortcutKeys(),
Extensions.extensionServer['_extensionAPITestHook']);
- InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI);
+ Host.InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI);
this._registeredExtensions[extensionOrigin] = {name: name};
}
const iframe = createElement('iframe');
@@ -698,7 +729,9 @@ Extensions.ExtensionServer = class extends Common.Object {
_registerExtension(origin, port) {
if (!this._registeredExtensions.hasOwnProperty(origin)) {
if (origin !== window.location.origin) // Just ignore inspector frames.
+ {
console.error('Ignoring unauthorized client request from ' + origin);
+ }
return;
}
port._extensionOrigin = origin;
@@ -707,21 +740,24 @@ Extensions.ExtensionServer = class extends Common.Object {
}
_onWindowMessage(event) {
- if (event.data === 'registerExtension')
+ if (event.data === 'registerExtension') {
this._registerExtension(event.origin, event.ports[0]);
+ }
}
async _onmessage(event) {
const message = event.data;
let result;
- if (message.command in this._handlers)
+ if (message.command in this._handlers) {
result = await this._handlers[message.command](message, event.target);
- else
+ } else {
result = this._status.E_NOTSUPPORTED(message.command);
+ }
- if (result && message.requestId)
+ if (result && message.requestId) {
this._dispatchCallback(message.requestId, event.target, result);
+ }
}
_registerHandler(command, callback) {
@@ -737,7 +773,7 @@ Extensions.ExtensionServer = class extends Common.Object {
/**
* @param {string} eventTopic
* @param {!Object} eventTarget
- * @param {string} frontendEventType
+ * @param {symbol} frontendEventType
* @param {function(!Common.Event)} handler
*/
_registerAutosubscriptionHandler(eventTopic, eventTarget, frontendEventType, handler) {
@@ -749,7 +785,7 @@ Extensions.ExtensionServer = class extends Common.Object {
/**
* @param {string} eventTopic
* @param {!Function} modelClass
- * @param {string} frontendEventType
+ * @param {symbol} frontendEventType
* @param {function(!Common.Event)} handler
*/
_registerAutosubscriptionTargetManagerHandler(eventTopic, modelClass, frontendEventType, handler) {
@@ -761,7 +797,7 @@ Extensions.ExtensionServer = class extends Common.Object {
_registerResourceContentCommittedHandler(handler) {
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function addFirstEventListener() {
Workspace.workspace.addEventListener(Workspace.Workspace.Events.WorkingCopyCommittedByUser, handler, this);
@@ -769,7 +805,7 @@ Extensions.ExtensionServer = class extends Common.Object {
}
/**
- * @this {Extensions.ExtensionServer}
+ * @this {ExtensionServer}
*/
function removeLastEventListener() {
Workspace.workspace.setHasResourceContentTrackingExtensions(false);
@@ -782,8 +818,9 @@ Extensions.ExtensionServer = class extends Common.Object {
}
_expandResourcePath(extensionPath, resourcePath) {
- if (!resourcePath)
+ if (!resourcePath) {
return;
+ }
return extensionPath + this._normalizePath(resourcePath);
}
@@ -792,15 +829,18 @@ Extensions.ExtensionServer = class extends Common.Object {
const result = [];
for (let i = 0; i < source.length; ++i) {
- if (source[i] === '.')
+ if (source[i] === '.') {
continue;
+ }
// Ignore empty path components resulting from //, as well as a leading and traling slashes.
- if (source[i] === '')
+ if (source[i] === '') {
continue;
- if (source[i] === '..')
+ }
+ if (source[i] === '..') {
result.pop();
- else
+ } else {
result.push(source[i]);
+ }
}
return '/' + result.join('/');
}
@@ -841,18 +881,20 @@ Extensions.ExtensionServer = class extends Common.Object {
frame = resourceTreeModel && resourceTreeModel.mainFrame;
}
if (!frame) {
- if (options.frameURL)
+ if (options.frameURL) {
console.warn('evaluate: there is no frame with URL ' + options.frameURL);
- else
+ } else {
console.warn('evaluate: the main frame is not yet available');
+ }
return this._status.E_NOTFOUND(options.frameURL || '<top>');
}
let contextSecurityOrigin;
- if (options.useContentScriptContext)
+ if (options.useContentScriptContext) {
contextSecurityOrigin = securityOrigin;
- else if (options.scriptExecutionContext)
+ } else if (options.scriptExecutionContext) {
contextSecurityOrigin = options.scriptExecutionContext;
+ }
const runtimeModel = frame.resourceTreeModel().target().model(SDK.RuntimeModel);
const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
@@ -860,8 +902,9 @@ Extensions.ExtensionServer = class extends Common.Object {
for (let i = 0; i < executionContexts.length; ++i) {
const executionContext = executionContexts[i];
if (executionContext.frameId === frame.id && executionContext.origin === contextSecurityOrigin &&
- !executionContext.isDefault)
+ !executionContext.isDefault) {
context = executionContext;
+ }
}
if (!context) {
console.warn('The JavaScript context ' + contextSecurityOrigin + ' was not found in the frame ' + frame.url);
@@ -870,11 +913,13 @@ Extensions.ExtensionServer = class extends Common.Object {
} else {
for (let i = 0; i < executionContexts.length; ++i) {
const executionContext = executionContexts[i];
- if (executionContext.frameId === frame.id && executionContext.isDefault)
+ if (executionContext.frameId === frame.id && executionContext.isDefault) {
context = executionContext;
+ }
}
- if (!context)
+ if (!context) {
return this._status.E_FAILED(frame.url + ' has no execution context');
+ }
}
context
@@ -901,10 +946,10 @@ Extensions.ExtensionServer = class extends Common.Object {
callback(null, result.object || null, !!result.exceptionDetails);
}
}
-};
+}
/** @enum {symbol} */
-Extensions.ExtensionServer.Events = {
+export const Events = {
SidebarPaneAdded: Symbol('SidebarPaneAdded'),
TraceProviderAdded: Symbol('TraceProviderAdded')
};
@@ -912,7 +957,7 @@ Extensions.ExtensionServer.Events = {
/**
* @unrestricted
*/
-Extensions.ExtensionServerPanelView = class extends UI.SimpleView {
+export class ExtensionServerPanelView extends UI.SimpleView {
/**
* @param {string} name
* @param {string} title
@@ -939,12 +984,12 @@ Extensions.ExtensionServerPanelView = class extends UI.SimpleView {
widget() {
return /** @type {!Promise.<!UI.Widget>} */ (Promise.resolve(this._panel));
}
-};
+}
/**
* @unrestricted
*/
-Extensions.ExtensionStatus = class {
+export class ExtensionStatus {
constructor() {
/**
* @param {string} code
@@ -970,15 +1015,30 @@ Extensions.ExtensionStatus = class {
this.E_PROTOCOLERROR = makeStatus.bind(null, 'E_PROTOCOLERROR', 'Inspector protocol error: %s');
this.E_FAILED = makeStatus.bind(null, 'E_FAILED', 'Operation failed: %s');
}
-};
+}
+
+/* Legacy exported object */
+self.Extensions = self.Extensions || {};
+
+/* Legacy exported object */
+Extensions = Extensions || {};
+
+/** @constructor */
+Extensions.ExtensionServer = ExtensionServer;
+
+/** @enum {symbol} */
+Extensions.ExtensionServer.Events = Events;
+
+/** @constructor */
+Extensions.ExtensionServerPanelView = ExtensionServerPanelView;
+
+/** @constructor */
+Extensions.ExtensionStatus = ExtensionStatus;
/**
* @typedef {{code: string, description: string, details: !Array.<*>}}
*/
Extensions.ExtensionStatus.Record;
-Extensions.extensionAPI = {};
-defineCommonExtensionSymbols(Extensions.extensionAPI);
-
-/** @type {!Extensions.ExtensionServer} */
+/** @type {!ExtensionServer} */
Extensions.extensionServer;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionTraceProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionTraceProvider.js
index db77fa9492a..afb42415967 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionTraceProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionTraceProvider.js
@@ -5,7 +5,7 @@
/**
* @unrestricted
*/
-Extensions.ExtensionTraceProvider = class {
+export default class ExtensionTraceProvider {
/**
* @param {string} extensionOrigin
* @param {string} id
@@ -20,10 +20,10 @@ Extensions.ExtensionTraceProvider = class {
}
/**
- * @param {!Extensions.TracingSession} session
+ * @param {!TracingSession} session
*/
start(session) {
- const sessionId = String(++Extensions.ExtensionTraceProvider._lastSessionId);
+ const sessionId = String(++_lastSessionId);
Extensions.extensionServer.startTraceRecording(this._id, sessionId, session);
}
@@ -51,19 +51,32 @@ Extensions.ExtensionTraceProvider = class {
persistentIdentifier() {
return `${this._extensionOrigin}/${this._categoryName}`;
}
-};
+}
-Extensions.ExtensionTraceProvider._lastSessionId = 0;
+export let _lastSessionId = 0;
/**
* @interface
*/
-Extensions.TracingSession = function() {};
-
-Extensions.TracingSession.prototype = {
+export class TracingSession {
/**
* @param {string} url
* @param {number} timeOffsetMicroseconds
*/
- complete: function(url, timeOffsetMicroseconds) {}
-};
+ complete(url, timeOffsetMicroseconds) {
+ }
+}
+
+/* Legacy exported object */
+self.Extensions = self.Extensions || {};
+
+/* Legacy exported object */
+Extensions = Extensions || {};
+
+/** @constructor */
+Extensions.ExtensionTraceProvider = ExtensionTraceProvider;
+
+Extensions.ExtensionTraceProvider._lastSessionId = _lastSessionId;
+
+/** @interface */
+Extensions.TracingSession = TracingSession;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionView.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionView.js
index f1ec73ef29c..d7dc6f01570 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/ExtensionView.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Extensions.ExtensionView = class extends UI.Widget {
+export default class ExtensionView extends UI.Widget {
/**
* @param {!Extensions.ExtensionServer} server
* @param {string} id
@@ -63,30 +63,33 @@ Extensions.ExtensionView = class extends UI.Widget {
* @override
*/
wasShown() {
- if (typeof this._frameIndex === 'number')
+ if (typeof this._frameIndex === 'number') {
this._server.notifyViewShown(this._id, this._frameIndex);
+ }
}
/**
* @override
*/
willHide() {
- if (typeof this._frameIndex === 'number')
+ if (typeof this._frameIndex === 'number') {
this._server.notifyViewHidden(this._id);
+ }
}
_onLoad() {
- const frames = /** @type {!Array.<!Window>} */ (window.frames);
+ const frames = window.frames;
this._frameIndex = Array.prototype.indexOf.call(frames, this._iframe.contentWindow);
- if (this.isShowing())
+ if (this.isShowing()) {
this._server.notifyViewShown(this._id, this._frameIndex);
+ }
}
-};
+}
/**
* @unrestricted
*/
-Extensions.ExtensionNotifierView = class extends UI.VBox {
+export class ExtensionNotifierView extends UI.VBox {
/**
* @param {!Extensions.ExtensionServer} server
* @param {string} id
@@ -111,4 +114,16 @@ Extensions.ExtensionNotifierView = class extends UI.VBox {
willHide() {
this._server.notifyViewHidden(this._id);
}
-};
+}
+
+/* Legacy exported object */
+self.Extensions = self.Extensions || {};
+
+/* Legacy exported object */
+Extensions = Extensions || {};
+
+/** @constructor */
+Extensions.ExtensionView = ExtensionView;
+
+/** @constructor */
+Extensions.ExtensionNotifierView = ExtensionNotifierView; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/extensions.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions/extensions.js
new file mode 100644
index 00000000000..71c229ec266
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/extensions.js
@@ -0,0 +1,16 @@
+// 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 './ExtensionAPI.js';
+import * as ExtensionPanel from './ExtensionPanel.js';
+import * as ExtensionServer from './ExtensionServer.js';
+import * as ExtensionTraceProvider from './ExtensionTraceProvider.js';
+import * as ExtensionView from './ExtensionView.js';
+
+export {
+ ExtensionPanel,
+ ExtensionServer,
+ ExtensionTraceProvider,
+ ExtensionView,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions/module.json b/chromium/third_party/blink/renderer/devtools/front_end/extensions/module.json
index 3d825f3fff4..3695a2574b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions/module.json
@@ -4,7 +4,9 @@
"browser_sdk",
"common"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "extensions.js",
"ExtensionAPI.js",
"ExtensionTraceProvider.js",
"ExtensionServer.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js
index da568e6faf4..875fb75b82a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/extensions_test_runner/ExtensionsTestRunner.js
@@ -36,8 +36,9 @@ function onEvaluate(message, port) {
}
ExtensionsTestRunner.showPanel = function(panelId) {
- if (panelId === 'extension')
+ if (panelId === 'extension') {
panelId = UI.inspectorView._tabbedPane._tabs[UI.inspectorView._tabbedPane._tabs.length - 1].id;
+ }
return UI.inspectorView.showPanel(panelId);
};
@@ -48,8 +49,9 @@ ExtensionsTestRunner.evaluateInExtension = function(code) {
ExtensionsTestRunner.runExtensionTests = async function(tests) {
const result = await TestRunner.RuntimeAgent.evaluate('location.href', 'console', false);
- if (!result)
+ if (!result) {
return;
+ }
ExtensionsTestRunner._pendingTests = (ExtensionsTestRunner._codeToEvaluateBeforeTests || '') + tests.join('\n');
const pageURL = result.value;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/externs.js b/chromium/third_party/blink/renderer/devtools/front_end/externs.js
index 3c8daa56ef1..7af8e06ba7b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/externs.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/externs.js
@@ -653,56 +653,6 @@ CodeMirror.defineMIME = function(mime, mode) {};
/** @type {boolean} */
window.dispatchStandaloneTestRunnerMessages;
-/**
- * Inserts the given HTML Element into the node at the location.
- * @param {string} where Where to insert the HTML text, one of 'beforeBegin',
- * 'afterBegin', 'beforeEnd', 'afterEnd'.
- * @param {!Element} element DOM Element to insert.
- * @return {?Element} The element that was inserted, or null, if the
- * insertion failed.
- * @see https://dom.spec.whatwg.org/#dom-element-insertadjacentelement
- */
-Node.prototype.insertAdjacentElement = function(where, element) {};
-
-/**
- * @param {Array.<Object>} keyframes
- * @param {number|Object} timing
- * @return {Object}
- */
-Element.prototype.animate = function(keyframes, timing) {};
-
-/**
- * @param {...!Node} nodes
- * @return {undefined}
- * @see https://dom.spec.whatwg.org/#dom-parentnode-append
- */
-Element.prototype.append = function(nodes) {};
-
-/**
- * @param {...!Node} nodes
- * @return {undefined}
- * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
- */
-Element.prototype.prepend = function(nodes) {};
-
-/**
- * @override
- * @param {string} type
- * @param {(!EventListener|!function (!Event): (boolean|undefined)|null)} listener
- * @param {(boolean|!{capture: (boolean|undefined), once: (boolean|undefined), passive: (boolean|undefined)})=} options
- * @this {EventTarget}
- */
-Element.prototype.addEventListener = function(type, listener, options) {};
-
-/**
- * @override
- * @param {string} type
- * @param {(!EventListener|!function (!Event): (boolean|undefined)|null)} listener
- * @param {(boolean|!{capture: (boolean|undefined), once: (boolean|undefined), passive: (boolean|undefined)})=} options
- * @this {EventTarget}
- */
-Element.prototype.removeEventListener = function(type, listener, options) {};
-
const acorn = {
/**
* @param {string} text
@@ -773,6 +723,38 @@ Acorn.Comment;
*/
Acorn.TokenOrComment;
+const dagre = {};
+dagre.graphlib = {};
+/**
+ * @constructor
+ */
+dagre.graphlib.Graph = function() {};
+
+dagre.graphlib.json = {};
+
+/**
+ * @param {string} graphData
+ * @return {!dagre.graphlib.Graph}
+ */
+dagre.graphlib.json.read = function(graphData) {};
+
+/**
+ * @param {!dagre.graphlib.Graph} graph
+ * @return {string}
+ */
+dagre.graphlib.json.write = function(graph) {};
+
+/**
+ * @param {!dagre.graphlib.Graph} graph
+ * @param {?Object=} options
+ */
+dagre.layout = function(graph, options) {};
+// Since the object types in JSDoc should use capitalized `Dagre`, dagre is renamed as Dagre below.
+// Note that `var Dagre={}` will be added in dagre_module.js, so to prevent variable redefinition,
+// the workaround is to name the module+folder as `dagre_layout`. This workaround is similar to
+// `cm` and `CodeMirror`.
+const Dagre = dagre;
+
const ESTree = {};
/**
@@ -1141,7 +1123,8 @@ ReportRenderer.RunnerResultArtifacts;
* @typedef {{
* lhr: !ReportRenderer.ReportJSON,
* artifacts: ReportRenderer.RunnerResultArtifacts,
- * report: string
+ * report: string,
+ * stack: string
* }}
*/
ReportRenderer.RunnerResult;
@@ -1197,20 +1180,6 @@ DetailsRenderer.NodeDetailsJSON;
*/
DetailsRenderer.OpportunitySummary;
-
-// Clipboard API
-
-/** @constructor */
-const Clipboard = function() {};
-/**
- * @param {string} data
- * @return {!Promise}
- */
-Clipboard.prototype.writeText = function(data) {};
-
-/** @type {Clipboard} */
-Navigator.prototype.clipboard;
-
const Lighthouse = {};
Lighthouse.ReportGenerator = {};
@@ -1227,3 +1196,340 @@ Lighthouse.ReportGenerator.generateReportHtml;
* @return {string}
*/
Lighthouse.ReportGenerator.replaceStrings;
+
+/** @interface */
+class InspectorFrontendHostAPI {
+ /**
+ * @param {string=} type
+ */
+ addFileSystem(type) {
+ }
+
+ loadCompleted() {
+ }
+
+ /**
+ * @param {number} requestId
+ * @param {string} fileSystemPath
+ * @param {string} excludedFolders
+ */
+ indexPath(requestId, fileSystemPath, excludedFolders) {
+ }
+
+ /**
+ * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
+ * @param {{x: number, y: number, width: number, height: number}} bounds
+ */
+ setInspectedPageBounds(bounds) {
+ }
+
+ /**
+ * @param {!Array<string>} certChain
+ */
+ showCertificateViewer(certChain) {
+ }
+
+ /**
+ * @param {string} shortcuts
+ */
+ setWhitelistedShortcuts(shortcuts) {
+ }
+
+ /**
+ * @param {boolean} active
+ */
+ setEyeDropperActive(active) {
+ }
+
+ inspectElementCompleted() {
+ }
+
+ /**
+ * @param {string} url
+ */
+ openInNewTab(url) {
+ }
+
+ /**
+ * @param {string} fileSystemPath
+ */
+ showItemInFolder(fileSystemPath) {
+ }
+
+ /**
+ * @param {string} fileSystemPath
+ */
+ removeFileSystem(fileSystemPath) {
+ }
+
+ requestFileSystems() {
+ }
+
+ /**
+ * @param {string} url
+ * @param {string} content
+ * @param {boolean} forceSaveAs
+ */
+ save(url, content, forceSaveAs) {
+ }
+
+ /**
+ * @param {string} url
+ * @param {string} content
+ */
+ append(url, content) {
+ }
+
+ /**
+ * @param {string} url
+ */
+ close(url) {
+ }
+
+ /**
+ * @param {number} requestId
+ * @param {string} fileSystemPath
+ * @param {string} query
+ */
+ searchInPath(requestId, fileSystemPath, query) {
+ }
+
+ /**
+ * @param {number} requestId
+ */
+ stopIndexing(requestId) {
+ }
+
+ bringToFront() {
+ }
+
+ closeWindow() {
+ }
+
+ copyText(text) {
+ }
+
+ /**
+ * @param {string} url
+ */
+ inspectedURLChanged(url) {
+ }
+
+ /**
+ * @param {string} fileSystemId
+ * @param {string} registeredName
+ * @return {?DOMFileSystem}
+ */
+ isolatedFileSystem(fileSystemId, registeredName) {
+ }
+
+ /**
+ * @param {string} url
+ * @param {string} headers
+ * @param {number} streamId
+ * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
+ */
+ loadNetworkResource(url, headers, streamId, callback) {
+ }
+
+ /**
+ * @param {function(!Object<string, string>)} callback
+ */
+ getPreferences(callback) {
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} value
+ */
+ setPreference(name, value) {
+ }
+
+ /**
+ * @param {string} name
+ */
+ removePreference(name) {
+ }
+
+ clearPreferences() {
+ }
+
+ /**
+ * @param {!FileSystem} fileSystem
+ */
+ upgradeDraggedFileSystemPermissions(fileSystem) {
+ }
+
+ /**
+ * @return {string}
+ */
+ platform() {
+ }
+
+ /**
+ * @param {string} actionName
+ * @param {number} actionCode
+ * @param {number} bucketSize
+ */
+ recordEnumeratedHistogram(actionName, actionCode, bucketSize) {
+ }
+
+ /**
+ * @param {string} histogramName
+ * @param {number} duration
+ */
+ recordPerformanceHistogram(histogramName, duration) {
+ }
+
+ /**
+ * @param {string} umaName
+ */
+ recordUserMetricsAction(umaName) {
+ }
+
+ /**
+ * @param {string} message
+ */
+ sendMessageToBackend(message) {
+ }
+
+ /**
+ * @param {!Adb.Config} config
+ */
+ setDevicesDiscoveryConfig(config) {
+ }
+
+ /**
+ * @param {boolean} enabled
+ */
+ setDevicesUpdatesEnabled(enabled) {
+ }
+
+ /**
+ * @param {string} pageId
+ * @param {string} action
+ */
+ performActionOnRemotePage(pageId, action) {
+ }
+
+ /**
+ * @param {string} browserId
+ * @param {string} url
+ */
+ openRemotePage(browserId, url) {
+ }
+
+ openNodeFrontend() {
+ }
+
+ /**
+ * @param {string} origin
+ * @param {string} script
+ */
+ setInjectedScriptForOrigin(origin, script) {
+ }
+
+ /**
+ * @param {boolean} isDocked
+ * @param {function()} callback
+ */
+ setIsDocked(isDocked, callback) {
+ }
+
+ /**
+ * @return {number}
+ */
+ zoomFactor() {
+ }
+
+ zoomIn() {
+ }
+
+ zoomOut() {
+ }
+
+ resetZoom() {
+ }
+
+ /**
+ * @param {number} x
+ * @param {number} y
+ * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
+ * @param {!Document} document
+ */
+ showContextMenuAtPoint(x, y, items, document) {
+ }
+
+ /**
+ * @param {function()} callback
+ */
+ reattach(callback) {
+ }
+
+ readyForTest() {
+ }
+
+ connectionReady() {
+ }
+
+ /**
+ * @param {boolean} value
+ */
+ setOpenNewWindowForPopups(value) {
+ }
+
+ /**
+ * @return {boolean}
+ */
+ isHostedMode() {
+ }
+
+ /**
+ * @param {function(!ExtensionDescriptor)} callback
+ */
+ setAddExtensionCallback(callback) {
+ }
+}
+
+/** @typedef
+{{
+ type: string,
+ id: (number|undefined),
+ label: (string|undefined),
+ enabled: (boolean|undefined),
+ checked: (boolean|undefined),
+ subItems: (!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>|undefined)
+}} */
+InspectorFrontendHostAPI.ContextMenuDescriptor;
+
+/** @typedef
+{{
+ statusCode: number,
+ headers: (!Object.<string, string>|undefined)
+}} */
+InspectorFrontendHostAPI.LoadNetworkResourceResult;
+
+/**
+ * @interface
+ */
+class ServicePort {
+ /**
+ * @param {function(string)} messageHandler
+ * @param {function(string)} closeHandler
+ */
+ setHandlers(messageHandler, closeHandler) {
+ }
+
+ /**
+ * @param {string} message
+ * @return {!Promise<boolean>}
+ */
+ send(message) {
+ }
+
+ /**
+ * @return {!Promise<boolean>}
+ */
+ close() {
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js
index 08aa4b487c4..038dc2da031 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter/FormatterWorkerPool.js
@@ -22,14 +22,17 @@ Formatter.FormatterWorkerPool = class {
}
_processNextTask() {
- if (!this._taskQueue.length)
+ if (!this._taskQueue.length) {
return;
+ }
let freeWorker = this._workerTasks.keysArray().find(worker => !this._workerTasks.get(worker));
- if (!freeWorker && this._workerTasks.size < Formatter.FormatterWorkerPool.MaxWorkers)
+ if (!freeWorker && this._workerTasks.size < Formatter.FormatterWorkerPool.MaxWorkers) {
freeWorker = this._createWorker();
- if (!freeWorker)
+ }
+ if (!freeWorker) {
return;
+ }
const task = this._taskQueue.shift();
this._workerTasks.set(freeWorker, task);
@@ -381,7 +384,8 @@ Formatter.FormatterWorkerPool.SCSSRule = class {
* @return {!Formatter.FormatterWorkerPool}
*/
Formatter.formatterWorkerPool = function() {
- if (!Formatter._formatterWorkerPool)
+ if (!Formatter._formatterWorkerPool) {
Formatter._formatterWorkerPool = new Formatter.FormatterWorkerPool();
+ }
return Formatter._formatterWorkerPool;
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter/ScriptFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter/ScriptFormatter.js
index 10627859438..da6b77f4f6b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter/ScriptFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter/ScriptFormatter.js
@@ -39,10 +39,11 @@ Formatter.Formatter = function() {};
* @param {function(string, !Formatter.FormatterSourceMapping)} callback
*/
Formatter.Formatter.format = function(contentType, mimeType, content, callback) {
- if (contentType.isDocumentOrScriptOrStyleSheet())
+ if (contentType.isDocumentOrScriptOrStyleSheet()) {
new Formatter.ScriptFormatter(mimeType, content, callback);
- else
+ } else {
new Formatter.ScriptIdentityFormatter(mimeType, content, callback);
+ }
};
/**
@@ -64,10 +65,11 @@ Formatter.Formatter.locationToPosition = function(lineEndings, lineNumber, colum
Formatter.Formatter.positionToLocation = function(lineEndings, position) {
const lineNumber = lineEndings.upperBound(position - 1);
let columnNumber;
- if (!lineNumber)
+ if (!lineNumber) {
columnNumber = position;
- else
+ } else {
columnNumber = position - lineEndings[lineNumber - 1] - 1;
+ }
return [lineNumber, columnNumber];
};
@@ -215,8 +217,9 @@ Formatter.FormatterSourceMappingImpl = class {
_convertPosition(positions1, positions2, position) {
const index = positions1.upperBound(position) - 1;
let convertedPosition = positions2[index] + position - positions1[index];
- if (index < positions2.length - 1 && convertedPosition > positions2[index + 1])
+ if (index < positions2.length - 1 && convertedPosition > positions2[index + 1]) {
convertedPosition = positions2[index + 1];
+ }
return convertedPosition;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker.js
index 644ad39258f..be9b3b58f46 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker.js
@@ -1,7 +1,9 @@
// 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.
+self.importScripts('platform/utilities.js');
// Release build has Runtime.js bundled.
-if (!self.Runtime)
+if (!self.Root || !self.Root.Runtime) {
self.importScripts('Runtime.js');
-Runtime.startWorker('formatter_worker');
+}
+Root.Runtime.startWorker('formatter_worker');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js
index e20b79d21f8..5ec5249ee82 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js
@@ -11,8 +11,7 @@ FormatterWorker.AcornTokenizer = class {
constructor(content) {
this._content = content;
this._comments = [];
- this._tokenizer =
- acorn.tokenizer(this._content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION, onComment: this._comments});
+ this._tokenizer = acorn.tokenizer(this._content, {onComment: this._comments});
this._textCursor = new TextUtils.TextCursor(this._content.computeLineEndings());
this._tokenLineStart = 0;
this._tokenLineEnd = 0;
@@ -69,8 +68,9 @@ FormatterWorker.AcornTokenizer = class {
* @return {!Acorn.TokenOrComment}
*/
_nextTokenInternal() {
- if (this._comments.length)
+ if (this._comments.length) {
return this._comments.shift();
+ }
const token = this._bufferedToken;
this._bufferedToken = this._tokenizer.getToken();
@@ -82,8 +82,9 @@ FormatterWorker.AcornTokenizer = class {
*/
nextToken() {
const token = this._nextTokenInternal();
- if (token.type === acorn.tokTypes.eof)
+ if (token.type === acorn.tokTypes.eof) {
return null;
+ }
this._textCursor.advance(token.start);
this._tokenLineStart = this._textCursor.lineNumber();
@@ -98,8 +99,9 @@ FormatterWorker.AcornTokenizer = class {
* @return {?Acorn.TokenOrComment}
*/
peekToken() {
- if (this._comments.length)
+ if (this._comments.length) {
return this._comments[0];
+ }
return this._bufferedToken.type !== acorn.tokTypes.eof ? this._bufferedToken : null;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSFormatter.js
index 194da088e27..a48db662c3d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSFormatter.js
@@ -65,29 +65,35 @@ FormatterWorker.CSSFormatter = class {
_tokenCallback(token, type, startPosition) {
startPosition += this._fromOffset;
const startLine = this._lineEndings.lowerBound(startPosition);
- if (startLine !== this._lastLine)
+ if (startLine !== this._lastLine) {
this._state.eatWhitespace = true;
- if (/^property/.test(type) && !this._state.inPropertyValue)
+ }
+ if (/^property/.test(type) && !this._state.inPropertyValue) {
this._state.seenProperty = true;
+ }
this._lastLine = startLine;
const isWhitespace = /^\s+$/.test(token);
if (isWhitespace) {
- if (!this._state.eatWhitespace)
+ if (!this._state.eatWhitespace) {
this._builder.addSoftSpace();
+ }
return;
}
this._state.eatWhitespace = false;
- if (token === '\n')
+ if (token === '\n') {
return;
+ }
if (token !== '}') {
- if (this._state.afterClosingBrace)
+ if (this._state.afterClosingBrace) {
this._builder.addNewLine(true);
+ }
this._state.afterClosingBrace = false;
}
if (token === '}') {
- if (this._state.inPropertyValue)
+ if (this._state.inPropertyValue) {
this._builder.addNewLine();
+ }
this._builder.decreaseNestingLevel();
this._state.afterClosingBrace = true;
this._state.inPropertyValue = false;
@@ -108,8 +114,9 @@ FormatterWorker.CSSFormatter = class {
this._builder.addToken(token, startPosition);
- if (type === 'comment' && !this._state.inPropertyValue && !this._state.seenProperty)
+ if (type === 'comment' && !this._state.inPropertyValue && !this._state.seenProperty) {
this._builder.addNewLine();
+ }
if (token === ';' && this._state.inPropertyValue) {
this._state.inPropertyValue = false;
this._builder.addNewLine();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSRuleParser.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSRuleParser.js
index b2c4c54ea61..40f4cf7bb5d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSRuleParser.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/CSSRuleParser.js
@@ -99,8 +99,9 @@ FormatterWorker._innerParseCSS = function(text, chunkCallback) {
} else if (tokenType.has('comment')) {
// The |processToken| is called per-line, so no token spans more than one line.
// Support only a one-line comments.
- if (tokenValue.substring(0, 2) !== '/*' || tokenValue.substring(tokenValue.length - 2) !== '*/')
+ if (tokenValue.substring(0, 2) !== '/*' || tokenValue.substring(tokenValue.length - 2) !== '*/') {
break;
+ }
const uncommentedText = tokenValue.substring(2, tokenValue.length - 2);
const fakeRule = 'a{\n' + uncommentedText + '}';
disabledRules = [];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/ESTreeWalker.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/ESTreeWalker.js
index 61169724c72..fcaa3060043 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/ESTreeWalker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/ESTreeWalker.js
@@ -40,8 +40,9 @@ FormatterWorker.ESTreeWalker = class {
node = /** @type {!ESTree.Node} */ (result);
}
- if (!node)
+ if (!node) {
return;
+ }
node.parent = parent;
if (this._beforeVisit.call(null, node) === FormatterWorker.ESTreeWalker.SkipSubtree) {
@@ -66,10 +67,11 @@ FormatterWorker.ESTreeWalker = class {
} else {
for (let i = 0; i < walkOrder.length; ++i) {
const entity = node[walkOrder[i]];
- if (Array.isArray(entity))
+ if (Array.isArray(entity)) {
this._walkArray(entity, node);
- else
+ } else {
this._innerWalk(entity, node);
+ }
}
}
@@ -81,8 +83,9 @@ FormatterWorker.ESTreeWalker = class {
* @param {?ESTree.Node} parentNode
*/
_walkArray(nodeArray, parentNode) {
- for (let i = 0; i < nodeArray.length; ++i)
+ for (let i = 0; i < nodeArray.length; ++i) {
this._innerWalk(nodeArray[i], parentNode);
+ }
}
};
@@ -129,6 +132,7 @@ FormatterWorker.ESTreeWalker._walkOrder = {
'ParenthesizedExpression': ['expression'],
'Program': ['body'],
'Property': ['key', 'value'],
+ 'RestElement': ['argument'],
'ReturnStatement': ['argument'],
'SequenceExpression': ['expressions'],
'SpreadElement': ['argument'],
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormattedContentBuilder.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormattedContentBuilder.js
index 4a2feb25b86..756fca5f6ac 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormattedContentBuilder.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormattedContentBuilder.js
@@ -45,8 +45,9 @@ FormatterWorker.FormattedContentBuilder = class {
*/
addToken(token, offset) {
const last = this._formattedContent.peekLast();
- if (this._enforceSpaceBetweenWords && last && /\w/.test(last[last.length - 1]) && /\w/.test(token))
+ if (this._enforceSpaceBetweenWords && last && /\w/.test(last[last.length - 1]) && /\w/.test(token)) {
this.addSoftSpace();
+ }
this._appendFormatting();
@@ -56,8 +57,9 @@ FormatterWorker.FormattedContentBuilder = class {
}
addSoftSpace() {
- if (!this._hardSpaces)
+ if (!this._hardSpaces) {
this._softSpace = true;
+ }
}
addHardSpace() {
@@ -70,12 +72,14 @@ FormatterWorker.FormattedContentBuilder = class {
*/
addNewLine(noSquash) {
// Avoid leading newlines.
- if (!this._formattedContentLength)
+ if (!this._formattedContentLength) {
return;
- if (noSquash)
+ }
+ if (noSquash) {
++this._newLines;
- else
+ } else {
this._newLines = this._newLines || 1;
+ }
}
increaseNestingLevel() {
@@ -83,21 +87,24 @@ FormatterWorker.FormattedContentBuilder = class {
}
decreaseNestingLevel() {
- if (this._nestingLevel > 0)
+ if (this._nestingLevel > 0) {
this._nestingLevel -= 1;
+ }
}
_appendFormatting() {
if (this._newLines) {
- for (let i = 0; i < this._newLines; ++i)
+ for (let i = 0; i < this._newLines; ++i) {
this._addText('\n');
+ }
this._addText(this._indent());
} else if (this._softSpace) {
this._addText(' ');
}
if (this._hardSpaces) {
- for (let i = 0; i < this._hardSpaces; ++i)
+ for (let i = 0; i < this._hardSpaces; ++i) {
this._addText(' ');
+ }
}
this._newLines = 0;
this._softSpace = false;
@@ -123,16 +130,19 @@ FormatterWorker.FormattedContentBuilder = class {
*/
_indent() {
const cachedValue = this._cachedIndents.get(this._nestingLevel);
- if (cachedValue)
+ if (cachedValue) {
return cachedValue;
+ }
let fullIndent = '';
- for (let i = 0; i < this._nestingLevel; ++i)
+ for (let i = 0; i < this._nestingLevel; ++i) {
fullIndent += this._indentString;
+ }
// Cache a maximum of 20 nesting level indents.
- if (this._nestingLevel <= 20)
+ if (this._nestingLevel <= 20) {
this._cachedIndents.set(this._nestingLevel, fullIndent);
+ }
return fullIndent;
}
@@ -148,8 +158,9 @@ FormatterWorker.FormattedContentBuilder = class {
* @param {number} originalPosition
*/
_addMappingIfNeeded(originalPosition) {
- if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition)
+ if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition) {
return;
+ }
this._mapping.original.push(originalPosition);
this._lastOriginalPosition = originalPosition;
this._mapping.formatted.push(this._formattedContentLength);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js
index debe39fb7d3..a4538911f83 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js
@@ -28,8 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-FormatterWorker.ACORN_ECMA_VERSION = 2018;
-
/**
* @param {string} mimeType
* @return {function(string, function(string, ?string, number, number):(!Object|undefined))}
@@ -46,8 +44,9 @@ FormatterWorker.createTokenizer = function(mimeType) {
while (!stream.eol()) {
const style = mode.token(stream, state);
const value = stream.current();
- if (callback(value, style, stream.start, stream.start + value.length) === FormatterWorker.AbortTokenization)
+ if (callback(value, style, stream.start, stream.start + value.length) === FormatterWorker.AbortTokenization) {
return;
+ }
stream.start = stream.pos;
}
}
@@ -59,8 +58,9 @@ FormatterWorker.AbortTokenization = {};
self.onmessage = function(event) {
const method = /** @type {string} */ (event.data.method);
const params = /** @type !{indentString: string, content: string, mimeType: string} */ (event.data.params);
- if (!method)
+ if (!method) {
return;
+ }
switch (method) {
case 'format':
@@ -112,12 +112,13 @@ FormatterWorker.parseJSONRelaxed = function(content) {
* @param {string} content
*/
FormatterWorker.evaluatableJavaScriptSubstring = function(content) {
- const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ const tokenizer = acorn.tokenizer(content, {});
let result = '';
try {
let token = tokenizer.getToken();
- while (token.type !== acorn.tokTypes.eof && FormatterWorker.AcornTokenizer.punctuator(token))
+ while (token.type !== acorn.tokTypes.eof && FormatterWorker.AcornTokenizer.punctuator(token)) {
token = tokenizer.getToken();
+ }
const startIndex = token.start;
let endIndex = token.end;
@@ -126,14 +127,16 @@ FormatterWorker.evaluatableJavaScriptSubstring = function(content) {
const isIdentifier = FormatterWorker.AcornTokenizer.identifier(token);
const isThis = FormatterWorker.AcornTokenizer.keyword(token, 'this');
const isString = token.type === acorn.tokTypes.string;
- if (!isThis && !isIdentifier && !isString)
+ if (!isThis && !isIdentifier && !isString) {
break;
+ }
endIndex = token.end;
token = tokenizer.getToken();
while (FormatterWorker.AcornTokenizer.punctuator(token, '.[]')) {
- if (FormatterWorker.AcornTokenizer.punctuator(token, '['))
+ if (FormatterWorker.AcornTokenizer.punctuator(token, '[')) {
openBracketsCounter++;
+ }
if (FormatterWorker.AcornTokenizer.punctuator(token, ']')) {
endIndex = openBracketsCounter > 0 ? token.end : endIndex;
@@ -158,7 +161,7 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
let root;
let body;
try {
- root = acorn.parse(wrapped, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ root = acorn.parse(wrapped, {});
body = root.body[0].expression.callee.body;
} catch (e) {
postMessage('');
@@ -169,8 +172,9 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
let containsReturn = false;
class Visitor {
ClassDeclaration(node) {
- if (node.parent === body)
+ if (node.parent === body) {
changes.push({text: node.id.name + '=', start: node.start, end: node.start});
+ }
}
FunctionDeclaration(node) {
changes.push({text: node.id.name + '=', start: node.start, end: node.start});
@@ -189,17 +193,20 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
containsAwait = true;
}
ForOfStatement(node) {
- if (node.await)
+ if (node.await) {
containsAwait = true;
+ }
}
ReturnStatement(node) {
containsReturn = true;
}
VariableDeclaration(node) {
- if (node.kind !== 'var' && node.parent !== body)
+ if (node.kind !== 'var' && node.parent !== body) {
return;
- if (node.parent.type === 'ForOfStatement' && node.parent.left === node)
+ }
+ if (node.parent.type === 'ForOfStatement' && node.parent.left === node) {
return;
+ }
const onlyOneDeclaration = node.declarations.length === 1;
changes.push(
{text: onlyOneDeclaration ? 'void' : 'void (', start: node.start, end: node.start + node.kind.length});
@@ -225,8 +232,9 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
* @this {Object}
*/
function visit(node) {
- if (node.type in this)
+ if (node.type in this) {
return this[node.type](node);
+ }
}
// Top-level return is not allowed.
if (!containsAwait || containsReturn) {
@@ -236,10 +244,11 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
const last = body.body[body.body.length - 1];
if (last.type === 'ExpressionStatement') {
changes.push({text: 'return (', start: last.start, end: last.start});
- if (wrapped[last.end - 1] !== ';')
+ if (wrapped[last.end - 1] !== ';') {
changes.push({text: ')', start: last.end, end: last.end});
- else
+ } else {
changes.push({text: ')', start: last.end - 1, end: last.end - 1});
+ }
}
while (changes.length) {
const change = changes.pop();
@@ -254,7 +263,7 @@ FormatterWorker.preprocessTopLevelAwaitExpressions = function(content) {
FormatterWorker.javaScriptIdentifiers = function(content) {
let root = null;
try {
- root = acorn.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ root = acorn.parse(content, {ranges: false});
} catch (e) {
}
@@ -276,17 +285,20 @@ FormatterWorker.javaScriptIdentifiers = function(content) {
*/
function beforeVisit(node) {
if (isFunction(node)) {
- if (node.id)
+ if (node.id) {
identifiers.push(node.id);
+ }
return FormatterWorker.ESTreeWalker.SkipSubtree;
}
- if (node.type !== 'Identifier')
+ if (node.type !== 'Identifier') {
return;
+ }
if (node.parent && node.parent.type === 'MemberExpression' && node.parent.property === node &&
- !node.parent.computed)
+ !node.parent.computed) {
return;
+ }
identifiers.push(node);
}
@@ -296,8 +308,9 @@ FormatterWorker.javaScriptIdentifiers = function(content) {
}
const functionNode = root.body[0];
- for (const param of functionNode.params)
+ for (const param of functionNode.params) {
walker.walk(param);
+ }
walker.walk(functionNode.body);
const reduced = identifiers.map(id => ({name: id.name, offset: id.start}));
postMessage(reduced);
@@ -351,10 +364,11 @@ FormatterWorker.format = function(mimeType, text, indentString) {
* @return {?{baseExpression: string, possibleSideEffects:boolean, receiver: string, argumentIndex: number, functionName: string}}
*/
FormatterWorker.findLastFunctionCall = function(content) {
- if (content.length > 10000)
+ if (content.length > 10000) {
return null;
+ }
try {
- const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ const tokenizer = acorn.tokenizer(content, {});
while (tokenizer.getToken().type !== acorn.tokTypes.eof) {
}
} catch (e) {
@@ -363,17 +377,19 @@ FormatterWorker.findLastFunctionCall = function(content) {
const suffix = '000)';
const base = FormatterWorker._lastCompleteExpression(content, suffix, new Set(['CallExpression', 'NewExpression']));
- if (!base)
+ if (!base) {
return null;
+ }
const callee = base.baseNode['callee'];
let functionName = '';
const functionProperty = callee.type === 'Identifier' ? callee : callee.property;
if (functionProperty) {
- if (functionProperty.type === 'Identifier')
+ if (functionProperty.type === 'Identifier') {
functionName = functionProperty.name;
- else if (functionProperty.type === 'Literal')
+ } else if (functionProperty.type === 'Literal') {
functionName = functionProperty.value;
+ }
}
const argumentIndex = base.baseNode['arguments'].length - 1;
@@ -394,36 +410,41 @@ FormatterWorker.findLastFunctionCall = function(content) {
* @return {!Array<string>}
*/
FormatterWorker.argumentsList = function(content) {
- if (content.length > 10000)
+ if (content.length > 10000) {
return [];
+ }
let parsed = null;
try {
// Try to parse as a function, anonymous function, or arrow function.
- parsed = acorn.parse(`(${content})`, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ parsed = acorn.parse(`(${content})`, {});
} catch (e) {
}
if (!parsed) {
try {
// Try to parse as a method.
- parsed = acorn.parse(`({${content}})`, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ parsed = acorn.parse(`({${content}})`, {});
} catch (e) {
}
}
- if (!parsed || !parsed.body || !parsed.body[0] || !parsed.body[0].expression)
+ if (!parsed || !parsed.body || !parsed.body[0] || !parsed.body[0].expression) {
return [];
+ }
const expression = parsed.body[0].expression;
let params = null;
switch (expression.type) {
case 'ClassExpression':
- if (!expression.body.body)
+ if (!expression.body.body) {
break;
+ }
const constructor = expression.body.body.find(method => method.kind === 'constructor');
- if (constructor)
+ if (constructor) {
params = constructor.value.params;
+ }
break;
case 'ObjectExpression':
- if (!expression.properties[0] || !expression.properties[0].value)
+ if (!expression.properties[0] || !expression.properties[0].value) {
break;
+ }
params = expression.properties[0].value.params;
break;
case 'FunctionExpression':
@@ -431,8 +452,9 @@ FormatterWorker.argumentsList = function(content) {
params = expression.params;
break;
}
- if (!params)
+ if (!params) {
return [];
+ }
return params.map(paramName);
function paramName(param) {
@@ -457,10 +479,11 @@ FormatterWorker.argumentsList = function(content) {
* @return {?{baseExpression: string, possibleSideEffects:boolean}}
*/
FormatterWorker.findLastExpression = function(content) {
- if (content.length > 10000)
+ if (content.length > 10000) {
return null;
+ }
try {
- const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ const tokenizer = acorn.tokenizer(content, {});
while (tokenizer.getToken().type !== acorn.tokTypes.eof) {
}
} catch (e) {
@@ -469,15 +492,17 @@ FormatterWorker.findLastExpression = function(content) {
const suffix = '.DEVTOOLS';
try {
- acorn.parse(content + suffix, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ acorn.parse(content + suffix, {});
} catch (parseError) {
// If this is an invalid location for a '.', don't attempt to give autocomplete
- if (parseError.message.startsWith('Unexpected token') && parseError.pos === content.length)
+ if (parseError.message.startsWith('Unexpected token') && parseError.pos === content.length) {
return null;
+ }
}
const base = FormatterWorker._lastCompleteExpression(content, suffix, new Set(['MemberExpression', 'Identifier']));
- if (!base)
+ if (!base) {
return null;
+ }
const {baseExpression, baseNode} = base;
const possibleSideEffects = FormatterWorker._nodeHasPossibleSideEffects(baseNode);
return {baseExpression, possibleSideEffects};
@@ -497,26 +522,31 @@ FormatterWorker._lastCompleteExpression = function(content, suffix, types) {
try {
// Wrap content in paren to successfully parse object literals
parsedContent = content[i] === '{' ? `(${content.substring(i)})${suffix}` : `${content.substring(i)}${suffix}`;
- ast = acorn.parse(parsedContent, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ ast = acorn.parse(parsedContent, {});
break;
} catch (e) {
}
}
- if (!ast)
+ if (!ast) {
return null;
+ }
let baseNode = null;
const walker = new FormatterWorker.ESTreeWalker(node => {
- if (baseNode || node.end < ast.end)
+ if (baseNode || node.end < ast.end) {
return FormatterWorker.ESTreeWalker.SkipSubtree;
- if (types.has(node.type))
+ }
+ if (types.has(node.type)) {
baseNode = node;
+ }
});
walker.walk(ast);
- if (!baseNode)
+ if (!baseNode) {
return null;
+ }
let baseExpression = parsedContent.substring(baseNode.start, parsedContent.length - suffix.length);
- if (baseExpression.startsWith('{'))
+ if (baseExpression.startsWith('{')) {
baseExpression = `(${baseExpression})`;
+ }
return {baseNode, baseExpression};
};
@@ -531,10 +561,12 @@ FormatterWorker._nodeHasPossibleSideEffects = function(baseNode) {
]);
let possibleSideEffects = false;
const sideEffectwalker = new FormatterWorker.ESTreeWalker(node => {
- if (!possibleSideEffects && !sideEffectFreeTypes.has(node.type))
+ if (!possibleSideEffects && !sideEffectFreeTypes.has(node.type)) {
possibleSideEffects = true;
- if (possibleSideEffects)
+ }
+ if (possibleSideEffects) {
return FormatterWorker.ESTreeWalker.SkipSubtree;
+ }
});
sideEffectwalker.walk(/** @type {!ESTree.Node} */ (baseNode));
return possibleSideEffects;
@@ -563,7 +595,7 @@ FormatterWorker.FormatterWorkerContentParser.parse = function(content, mimeType)
extension.instance().then(instance => instance.parse(content)).catchException(null).then(postMessage);
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @return {boolean}
*/
function findExtension(extension) {
@@ -572,6 +604,7 @@ FormatterWorker.FormatterWorkerContentParser.parse = function(content, mimeType)
};
(function disableLoggingForTest() {
- if (Runtime.queryParam('test'))
+ if (Root.Runtime.queryParam('test')) {
console.error = () => undefined;
+ }
})();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/HTMLFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/HTMLFormatter.js
index 8419e5ed67d..8c7a8e77331 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/HTMLFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/HTMLFormatter.js
@@ -40,13 +40,15 @@ FormatterWorker.HTMLFormatter = class {
* @param {!FormatterWorker.HTMLModel.Element} element
*/
_walk(element) {
- if (element.parent)
+ if (element.parent) {
this._formatTokensTill(element.parent, element.openTag.startOffset);
+ }
this._beforeOpenTag(element);
this._formatTokensTill(element, element.openTag.endOffset);
this._afterOpenTag(element);
- for (let i = 0; i < element.children.length; ++i)
+ for (let i = 0; i < element.children.length; ++i) {
this._walk(element.children[i]);
+ }
this._formatTokensTill(element, element.closeTag.startOffset);
this._beforeCloseTag(element);
@@ -58,8 +60,9 @@ FormatterWorker.HTMLFormatter = class {
* @param {!FormatterWorker.HTMLModel.Element} element
*/
_beforeOpenTag(element) {
- if (!element.children.length || element === this._model.document())
+ if (!element.children.length || element === this._model.document()) {
return;
+ }
this._builder.addNewLine();
}
@@ -67,8 +70,9 @@ FormatterWorker.HTMLFormatter = class {
* @param {!FormatterWorker.HTMLModel.Element} element
*/
_afterOpenTag(element) {
- if (!element.children.length || element === this._model.document())
+ if (!element.children.length || element === this._model.document()) {
return;
+ }
this._builder.increaseNestingLevel();
this._builder.addNewLine();
}
@@ -77,8 +81,9 @@ FormatterWorker.HTMLFormatter = class {
* @param {!FormatterWorker.HTMLModel.Element} element
*/
_beforeCloseTag(element) {
- if (!element.children.length || element === this._model.document())
+ if (!element.children.length || element === this._model.document()) {
return;
+ }
this._builder.decreaseNestingLevel();
this._builder.addNewLine();
}
@@ -95,8 +100,9 @@ FormatterWorker.HTMLFormatter = class {
* @param {!FormatterWorker.HTMLModel.Token} token
*/
_formatToken(element, token) {
- if (token.value.isWhitespace())
+ if (token.value.isWhitespace()) {
return;
+ }
if (token.type.has('comment') || token.type.has('meta')) {
this._builder.addNewLine();
this._builder.addToken(token.value.trim(), token.startOffset);
@@ -126,8 +132,9 @@ FormatterWorker.HTMLFormatter = class {
return;
}
- if (!isBodyToken && token.type.has('attribute'))
+ if (!isBodyToken && token.type.has('attribute')) {
this._builder.addSoftSpace();
+ }
this._builder.addToken(token.value, token.startOffset);
}
@@ -137,14 +144,17 @@ FormatterWorker.HTMLFormatter = class {
* @return {boolean}
*/
_scriptTagIsJavaScript(element) {
- if (!element.openTag.attributes.has('type'))
+ if (!element.openTag.attributes.has('type')) {
return true;
+ }
let type = element.openTag.attributes.get('type').toLowerCase();
- if (!type)
+ if (!type) {
return true;
+ }
const isWrappedInQuotes = /^(["\'])(.*)\1$/.exec(type.trim());
- if (isWrappedInQuotes)
+ if (isWrappedInQuotes) {
type = isWrappedInQuotes[2];
+ }
return FormatterWorker.HTMLFormatter.SupportedJavaScriptMimeTypes.has(type.trim());
}
};
@@ -187,12 +197,14 @@ FormatterWorker.HTMLModel = class {
while (true) {
tokenizer(text.substring(lastOffset), processToken.bind(this, lastOffset));
- if (lastOffset >= text.length)
+ if (lastOffset >= text.length) {
break;
+ }
const element = this._stack.peekLast();
lastOffset = lowerCaseText.indexOf('</' + element.name, lastOffset);
- if (lastOffset === -1)
+ if (lastOffset === -1) {
lastOffset = text.length;
+ }
const tokenStart = element.openTag.endOffset;
const tokenEnd = lastOffset;
const tokenValue = text.substring(tokenStart, tokenEnd);
@@ -226,8 +238,9 @@ FormatterWorker.HTMLModel = class {
const element = this._stack.peekLast();
if (element && (element.name === 'script' || element.name === 'style') &&
- element.openTag.endOffset === lastOffset)
+ element.openTag.endOffset === lastOffset) {
return FormatterWorker.AbortTokenization;
+ }
}
}
@@ -306,20 +319,23 @@ FormatterWorker.HTMLModel = class {
_onTagComplete(tag) {
if (tag.isOpenTag) {
const topElement = this._stack.peekLast();
- if (topElement !== this._document && topElement.openTag.selfClosingTag)
+ if (topElement !== this._document && topElement.openTag.selfClosingTag) {
this._popElement(autocloseTag(topElement, topElement.openTag.endOffset));
- else if (
+ } else if (
(topElement.name in FormatterWorker.HTMLModel.AutoClosingTags) &&
- FormatterWorker.HTMLModel.AutoClosingTags[topElement.name].has(tag.name))
+ FormatterWorker.HTMLModel.AutoClosingTags[topElement.name].has(tag.name)) {
this._popElement(autocloseTag(topElement, tag.startOffset));
+ }
this._pushElement(tag);
return;
}
- while (this._stack.length > 1 && this._stack.peekLast().name !== tag.name)
+ while (this._stack.length > 1 && this._stack.peekLast().name !== tag.name) {
this._popElement(autocloseTag(this._stack.peekLast(), tag.startOffset));
- if (this._stack.length === 1)
+ }
+ if (this._stack.length === 1) {
return;
+ }
this._popElement(tag);
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js
index 2ef7b325c9d..e735745f135 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js
@@ -51,8 +51,7 @@ FormatterWorker.JavaScriptFormatter = class {
this._content = text.substring(this._fromOffset, this._toOffset);
this._lastLineNumber = 0;
this._tokenizer = new FormatterWorker.AcornTokenizer(this._content);
- const ast = acorn.parse(
- this._content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION, preserveParens: true});
+ const ast = acorn.parse(this._content, {ranges: false, preserveParens: true});
const walker = new FormatterWorker.ESTreeWalker(this._beforeVisit.bind(this), this._afterVisit.bind(this));
walker.walk(ast);
}
@@ -74,8 +73,9 @@ FormatterWorker.JavaScriptFormatter = class {
} else if (format[i] === '<') {
this._builder.decreaseNestingLevel();
} else if (format[i] === 't') {
- if (this._tokenizer.tokenLineStart() - this._lastLineNumber > 1)
+ if (this._tokenizer.tokenLineStart() - this._lastLineNumber > 1) {
this._builder.addNewLine(true);
+ }
this._lastLineNumber = this._tokenizer.tokenLineEnd();
this._builder.addToken(this._content.substring(token.start, token.end), this._fromOffset + token.start);
}
@@ -86,8 +86,9 @@ FormatterWorker.JavaScriptFormatter = class {
* @param {!ESTree.Node} node
*/
_beforeVisit(node) {
- if (!node.parent)
+ if (!node.parent) {
return;
+ }
while (this._tokenizer.peekToken() && this._tokenizer.peekToken().start < node.start) {
const token = /** @type {!Acorn.TokenOrComment} */ (this._tokenizer.nextToken());
const format = this._formatToken(node.parent, token);
@@ -113,12 +114,15 @@ FormatterWorker.JavaScriptFormatter = class {
*/
_inForLoopHeader(node) {
const parent = node.parent;
- if (!parent)
+ if (!parent) {
return false;
- if (parent.type === 'ForStatement')
+ }
+ if (parent.type === 'ForStatement') {
return node === parent.init || node === parent.test || node === parent.update;
- if (parent.type === 'ForInStatement' || parent.type === 'ForOfStatement')
+ }
+ if (parent.type === 'ForInStatement' || parent.type === 'ForOfStatement') {
return node === parent.left || parent.right;
+ }
return false;
}
@@ -129,132 +133,172 @@ FormatterWorker.JavaScriptFormatter = class {
*/
_formatToken(node, token) {
const AT = FormatterWorker.AcornTokenizer;
- if (AT.lineComment(token))
+ if (AT.lineComment(token)) {
return 'tn';
- if (AT.blockComment(token))
+ }
+ if (AT.blockComment(token)) {
return 'tn';
+ }
if (node.type === 'ContinueStatement' || node.type === 'BreakStatement') {
return node.label && AT.keyword(token) ? 'ts' : 't';
} else if (node.type === 'Identifier') {
return 't';
} else if (node.type === 'ReturnStatement') {
- if (AT.punctuator(token, ';'))
+ if (AT.punctuator(token, ';')) {
return 't';
+ }
return node.argument ? 'ts' : 't';
} else if (node.type === 'Property') {
- if (AT.punctuator(token, ':'))
+ if (AT.punctuator(token, ':')) {
return 'ts';
+ }
return 't';
} else if (node.type === 'ArrayExpression') {
- if (AT.punctuator(token, ','))
+ if (AT.punctuator(token, ',')) {
return 'ts';
+ }
return 't';
} else if (node.type === 'LabeledStatement') {
- if (AT.punctuator(token, ':'))
+ if (AT.punctuator(token, ':')) {
return 'ts';
+ }
} else if (
node.type === 'LogicalExpression' || node.type === 'AssignmentExpression' || node.type === 'BinaryExpression') {
- if (AT.punctuator(token) && !AT.punctuator(token, '()'))
+ if (AT.punctuator(token) && !AT.punctuator(token, '()')) {
return 'sts';
+ }
} else if (node.type === 'ConditionalExpression') {
- if (AT.punctuator(token, '?:'))
+ if (AT.punctuator(token, '?:')) {
return 'sts';
+ }
} else if (node.type === 'VariableDeclarator') {
- if (AT.punctuator(token, '='))
+ if (AT.punctuator(token, '=')) {
return 'sts';
+ }
} else if (node.type === 'ObjectPattern') {
- if (node.parent && node.parent.type === 'VariableDeclarator' && AT.punctuator(token, '{'))
+ if (node.parent && node.parent.type === 'VariableDeclarator' && AT.punctuator(token, '{')) {
return 'st';
- if (AT.punctuator(token, ','))
+ }
+ if (AT.punctuator(token, ',')) {
return 'ts';
+ }
} else if (node.type === 'FunctionDeclaration') {
- if (AT.punctuator(token, ',)'))
+ if (AT.punctuator(token, ',)')) {
return 'ts';
+ }
} else if (node.type === 'FunctionExpression') {
- if (AT.punctuator(token, ',)'))
+ if (AT.punctuator(token, ',)')) {
return 'ts';
- if (AT.keyword(token, 'function'))
+ }
+ if (AT.keyword(token, 'function')) {
return node.id ? 'ts' : 't';
+ }
} else if (node.type === 'WithStatement') {
- if (AT.punctuator(token, ')'))
+ if (AT.punctuator(token, ')')) {
return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
+ }
} else if (node.type === 'SwitchStatement') {
- if (AT.punctuator(token, '{'))
+ if (AT.punctuator(token, '{')) {
return 'tn>';
- if (AT.punctuator(token, '}'))
+ }
+ if (AT.punctuator(token, '}')) {
return 'n<tn';
- if (AT.punctuator(token, ')'))
+ }
+ if (AT.punctuator(token, ')')) {
return 'ts';
+ }
} else if (node.type === 'SwitchCase') {
- if (AT.keyword(token, 'case'))
+ if (AT.keyword(token, 'case')) {
return 'n<ts';
- if (AT.keyword(token, 'default'))
+ }
+ if (AT.keyword(token, 'default')) {
return 'n<t';
- if (AT.punctuator(token, ':'))
+ }
+ if (AT.punctuator(token, ':')) {
return 'tn>';
+ }
} else if (node.type === 'VariableDeclaration') {
if (AT.punctuator(token, ',')) {
let allVariablesInitialized = true;
const declarations = /** @type {!Array.<!ESTree.Node>} */ (node.declarations);
- for (let i = 0; i < declarations.length; ++i)
+ for (let i = 0; i < declarations.length; ++i) {
allVariablesInitialized = allVariablesInitialized && !!declarations[i].init;
+ }
return !this._inForLoopHeader(node) && allVariablesInitialized ? 'nSSts' : 'ts';
}
} else if (node.type === 'BlockStatement') {
- if (AT.punctuator(token, '{'))
+ if (AT.punctuator(token, '{')) {
return node.body.length ? 'tn>' : 't';
- if (AT.punctuator(token, '}'))
+ }
+ if (AT.punctuator(token, '}')) {
return node.body.length ? 'n<t' : 't';
+ }
} else if (node.type === 'CatchClause') {
- if (AT.punctuator(token, ')'))
+ if (AT.punctuator(token, ')')) {
return 'ts';
+ }
} else if (node.type === 'ObjectExpression') {
- if (!node.properties.length)
+ if (!node.properties.length) {
return 't';
- if (AT.punctuator(token, '{'))
+ }
+ if (AT.punctuator(token, '{')) {
return 'tn>';
- if (AT.punctuator(token, '}'))
+ }
+ if (AT.punctuator(token, '}')) {
return 'n<t';
- if (AT.punctuator(token, ','))
+ }
+ if (AT.punctuator(token, ',')) {
return 'tn';
+ }
} else if (node.type === 'IfStatement') {
- if (AT.punctuator(token, ')'))
+ if (AT.punctuator(token, ')')) {
return node.consequent && node.consequent.type === 'BlockStatement' ? 'ts' : 'tn>';
+ }
if (AT.keyword(token, 'else')) {
const preFormat = node.consequent && node.consequent.type === 'BlockStatement' ? 'st' : 'n<t';
let postFormat = 'n>';
- if (node.alternate && (node.alternate.type === 'BlockStatement' || node.alternate.type === 'IfStatement'))
+ if (node.alternate && (node.alternate.type === 'BlockStatement' || node.alternate.type === 'IfStatement')) {
postFormat = 's';
+ }
return preFormat + postFormat;
}
} else if (node.type === 'CallExpression') {
- if (AT.punctuator(token, ','))
+ if (AT.punctuator(token, ',')) {
return 'ts';
+ }
} else if (node.type === 'SequenceExpression' && AT.punctuator(token, ',')) {
return node.parent && node.parent.type === 'SwitchCase' ? 'ts' : 'tn';
} else if (node.type === 'ForStatement' || node.type === 'ForOfStatement' || node.type === 'ForInStatement') {
- if (AT.punctuator(token, ';'))
+ if (AT.punctuator(token, ';')) {
return 'ts';
- if (AT.keyword(token, 'in') || AT.identifier(token, 'of'))
+ }
+ if (AT.keyword(token, 'in') || AT.identifier(token, 'of')) {
return 'sts';
+ }
- if (AT.punctuator(token, ')'))
+ if (AT.punctuator(token, ')')) {
return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
+ }
} else if (node.type === 'WhileStatement') {
- if (AT.punctuator(token, ')'))
+ if (AT.punctuator(token, ')')) {
return node.body && node.body.type === 'BlockStatement' ? 'ts' : 'tn>';
+ }
} else if (node.type === 'DoWhileStatement') {
const blockBody = node.body && node.body.type === 'BlockStatement';
- if (AT.keyword(token, 'do'))
+ if (AT.keyword(token, 'do')) {
return blockBody ? 'ts' : 'tn>';
- if (AT.keyword(token, 'while'))
+ }
+ if (AT.keyword(token, 'while')) {
return blockBody ? 'sts' : 'n<ts';
+ }
} else if (node.type === 'ClassBody') {
- if (AT.punctuator(token, '{'))
+ if (AT.punctuator(token, '{')) {
return 'stn>';
- if (AT.punctuator(token, '}'))
+ }
+ if (AT.punctuator(token, '}')) {
return '<ntn';
+ }
return 't';
} else if (node.type === 'YieldExpression') {
return 't';
@@ -270,43 +314,57 @@ FormatterWorker.JavaScriptFormatter = class {
*/
_finishNode(node) {
if (node.type === 'WithStatement') {
- if (node.body && node.body.type !== 'BlockStatement')
+ if (node.body && node.body.type !== 'BlockStatement') {
return 'n<';
+ }
} else if (node.type === 'VariableDeclaration') {
- if (!this._inForLoopHeader(node))
+ if (!this._inForLoopHeader(node)) {
return 'n';
+ }
} else if (node.type === 'ForStatement' || node.type === 'ForOfStatement' || node.type === 'ForInStatement') {
- if (node.body && node.body.type !== 'BlockStatement')
+ if (node.body && node.body.type !== 'BlockStatement') {
return 'n<';
+ }
} else if (node.type === 'BlockStatement') {
- if (node.parent && node.parent.type === 'IfStatement' && node.parent.alternate && node.parent.consequent === node)
+ if (node.parent && node.parent.type === 'IfStatement' && node.parent.alternate &&
+ node.parent.consequent === node) {
return '';
+ }
if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
- node.parent.parent.type === 'Property')
+ node.parent.parent.type === 'Property') {
return '';
+ }
if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
- node.parent.parent.type === 'VariableDeclarator')
+ node.parent.parent.type === 'VariableDeclarator') {
return '';
+ }
if (node.parent && node.parent.type === 'FunctionExpression' && node.parent.parent &&
- node.parent.parent.type === 'CallExpression')
+ node.parent.parent.type === 'CallExpression') {
return '';
- if (node.parent && node.parent.type === 'DoWhileStatement')
+ }
+ if (node.parent && node.parent.type === 'DoWhileStatement') {
return '';
- if (node.parent && node.parent.type === 'TryStatement' && node.parent.block === node)
+ }
+ if (node.parent && node.parent.type === 'TryStatement' && node.parent.block === node) {
return 's';
- if (node.parent && node.parent.type === 'CatchClause' && node.parent.parent.finalizer)
+ }
+ if (node.parent && node.parent.type === 'CatchClause' && node.parent.parent.finalizer) {
return 's';
+ }
return 'n';
} else if (node.type === 'WhileStatement') {
- if (node.body && node.body.type !== 'BlockStatement')
+ if (node.body && node.body.type !== 'BlockStatement') {
return 'n<';
+ }
} else if (node.type === 'IfStatement') {
if (node.alternate) {
- if (node.alternate.type !== 'BlockStatement' && node.alternate.type !== 'IfStatement')
+ if (node.alternate.type !== 'BlockStatement' && node.alternate.type !== 'IfStatement') {
return '<';
+ }
} else if (node.consequent) {
- if (node.consequent.type !== 'BlockStatement')
+ if (node.consequent.type !== 'BlockStatement') {
return '<';
+ }
}
} else if (
node.type === 'BreakStatement' || node.type === 'ContinueStatement' || node.type === 'ThrowStatement' ||
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js
index 8e3787f9ede..e15d00e37a1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js
@@ -11,9 +11,9 @@ FormatterWorker.javaScriptOutline = function(content) {
let ast;
try {
- ast = acorn.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ ast = acorn.parse(content, {ranges: false});
} catch (e) {
- ast = acorn.loose.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION});
+ ast = acorn.loose.parse(content, {ranges: false});
}
const textCursor = new TextUtils.TextCursor(content.computeLineEndings());
@@ -43,10 +43,12 @@ FormatterWorker.javaScriptOutline = function(content) {
(node.type === 'MethodDefinition' || node.type === 'Property') && isNameNode(node.key) &&
isFunctionNode(node.value)) {
const namePrefix = [];
- if (node.kind === 'get' || node.kind === 'set')
+ if (node.kind === 'get' || node.kind === 'set') {
namePrefix.push(node.kind);
- if (node.static)
+ }
+ if (node.static) {
namePrefix.push('static');
+ }
reportFunction(node.key, node.value, namePrefix.join(' '));
}
}
@@ -71,12 +73,15 @@ FormatterWorker.javaScriptOutline = function(content) {
*/
function reportFunction(nameNode, functionNode, namePrefix) {
let name = stringifyNameNode(nameNode);
- if (functionNode.generator)
+ if (functionNode.generator) {
name = '*' + name;
- if (namePrefix)
+ }
+ if (namePrefix) {
name = namePrefix + ' ' + name;
- if (functionNode.async)
+ }
+ if (functionNode.async) {
name = 'async ' + name;
+ }
textCursor.advance(nameNode.start);
addOutlineItem({
@@ -92,10 +97,12 @@ FormatterWorker.javaScriptOutline = function(content) {
* @return {boolean}
*/
function isNameNode(node) {
- if (!node)
+ if (!node) {
return false;
- if (node.type === 'MemberExpression')
+ }
+ if (node.type === 'MemberExpression') {
return !node.computed && node.property.type === 'Identifier';
+ }
return node.type === 'Identifier';
}
@@ -104,8 +111,9 @@ FormatterWorker.javaScriptOutline = function(content) {
* @return {boolean}
*/
function isFunctionNode(node) {
- if (!node)
+ if (!node) {
return false;
+ }
return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';
}
@@ -122,8 +130,9 @@ FormatterWorker.javaScriptOutline = function(content) {
* @return {string}
*/
function stringifyNameNode(node) {
- if (node.type === 'MemberExpression')
+ if (node.type === 'MemberExpression') {
node = /** @type {!ESTree.Node} */ (node.property);
+ }
console.assert(node.type === 'Identifier', 'Cannot extract identifier from unknown type: ' + node.type);
return /** @type {string} */ (node.name);
}
@@ -135,12 +144,13 @@ FormatterWorker.javaScriptOutline = function(content) {
function stringifyArguments(params) {
const result = [];
for (const param of params) {
- if (param.type === 'Identifier')
+ if (param.type === 'Identifier') {
result.push(param.name);
- else if (param.type === 'RestElement' && param.argument.type === 'Identifier')
+ } else if (param.type === 'RestElement' && param.argument.type === 'Identifier') {
result.push('...' + param.argument.name);
- else
+ } else {
console.error('Error: unexpected function parameter type: ' + param.type);
+ }
}
return '(' + result.join(', ') + ')';
}
@@ -150,8 +160,9 @@ FormatterWorker.javaScriptOutline = function(content) {
*/
function addOutlineItem(item) {
outlineChunk.push(item);
- if (textCursor.offset() - lastReportedOffset < chunkSize)
+ if (textCursor.offset() - lastReportedOffset < chunkSize) {
return;
+ }
postMessage({chunk: outlineChunk, isLastChunk: false});
outlineChunk = [];
lastReportedOffset = textCursor.offset();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/RelaxedJSONParser.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/RelaxedJSONParser.js
index cf080196527..812d4a81c1b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/RelaxedJSONParser.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/RelaxedJSONParser.js
@@ -50,8 +50,9 @@ FormatterWorker.RelaxedJSONParser.parse = function(content) {
walker.walk(root);
- if (hasExpression)
+ if (hasExpression) {
return null;
+ }
return rootTip.length ? rootTip[0] : null;
/**
@@ -71,10 +72,11 @@ FormatterWorker.RelaxedJSONParser.parse = function(content) {
*/
function applyValue(value) {
stackData.tip[stackData.key] = value;
- if (stackData.parentIsArray)
+ if (stackData.parentIsArray) {
stackData.key++;
- else
+ } else {
stackData.state = null;
+ }
}
/**
@@ -130,8 +132,9 @@ FormatterWorker.RelaxedJSONParser.parse = function(content) {
case 'ExpressionStatement':
break;
default:
- if (stackData.state === States.ExpectValue)
+ if (stackData.state === States.ExpectValue) {
applyValue(extractValue(node));
+ }
return FormatterWorker.ESTreeWalker.SkipSubtree;
}
}
@@ -140,8 +143,9 @@ FormatterWorker.RelaxedJSONParser.parse = function(content) {
* @param {!ESTree.Node} node
*/
function afterVisit(node) {
- if (node.type === 'ObjectExpression' || node.type === 'ArrayExpression')
+ if (node.type === 'ObjectExpression' || node.type === 'ArrayExpression') {
popStack();
+ }
}
/**
@@ -153,8 +157,9 @@ FormatterWorker.RelaxedJSONParser.parse = function(content) {
const originalNode = node;
let value;
if (node.type === 'UnaryExpression' && (node.operator === '-' || node.operator === '+')) {
- if (node.operator === '-')
+ if (node.operator === '-') {
isNegative = true;
+ }
node = /** @type {!ESTree.Node} */ (node.argument);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js
index 189c2221196..fae8eae0ade 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js
@@ -2,5312 +2,5002 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.acorn = {})));
-}(this, (function (exports) { 'use strict';
+ (global = global || self, factory(global.acorn = {}));
+}(this, function (exports) { 'use strict';
-// Reserved word lists for various dialects of the language
+ // Reserved word lists for various dialects of the language
-var reservedWords = {
- 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
- 5: "class enum extends super const export import",
- 6: "enum",
- strict: "implements interface let package private protected public static yield",
- strictBind: "eval arguments"
-};
-
-// And the keywords
+ var reservedWords = {
+ 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
+ 5: "class enum extends super const export import",
+ 6: "enum",
+ strict: "implements interface let package private protected public static yield",
+ strictBind: "eval arguments"
+ };
-var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
+ // And the keywords
-var keywords = {
- 5: ecma5AndLessKeywords,
- 6: ecma5AndLessKeywords + " const class extends export import super"
-};
+ var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
-var keywordRelationalOperator = /^in(stanceof)?$/;
+ var keywords = {
+ 5: ecma5AndLessKeywords,
+ "5module": ecma5AndLessKeywords + " export import",
+ 6: ecma5AndLessKeywords + " const class extends export import super"
+ };
-// ## Character categories
+ var keywordRelationalOperator = /^in(stanceof)?$/;
+
+ // ## Character categories
+
+ // Big ugly regular expressions that match characters in the
+ // whitespace, identifier, and identifier-start categories. These
+ // are only applied when a character is found to actually have a
+ // code point above 128.
+ // Generated by `bin/generate-identifier-regex.js`.
+ var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab67\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
+ var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
+
+ var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
+ var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
+
+ nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
+
+ // These are a run-length and offset encoded representation of the
+ // >0xffff code points that are a valid part of identifiers. The
+ // offset starts at 0x10000, and each pair of numbers represents an
+ // offset to the next range, and then a size of the range. They were
+ // generated by bin/generate-identifier-regex.js
+
+ // eslint-disable-next-line comma-spacing
+ var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,155,22,13,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,0,33,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,0,161,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,754,9486,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541];
+
+ // eslint-disable-next-line comma-spacing
+ var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,232,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,792487,239];
+
+ // This has a complexity linear to the value of the code. The
+ // assumption is that looking up astral identifier characters is
+ // rare.
+ function isInAstralSet(code, set) {
+ var pos = 0x10000;
+ for (var i = 0; i < set.length; i += 2) {
+ pos += set[i];
+ if (pos > code) { return false }
+ pos += set[i + 1];
+ if (pos >= code) { return true }
+ }
+ }
-// Big ugly regular expressions that match characters in the
-// whitespace, identifier, and identifier-start categories. These
-// are only applied when a character is found to actually have a
-// code point above 128.
-// Generated by `bin/generate-identifier-regex.js`.
+ // Test whether a given character code starts an identifier.
-var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
-var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
+ function isIdentifierStart(code, astral) {
+ if (code < 65) { return code === 36 }
+ if (code < 91) { return true }
+ if (code < 97) { return code === 95 }
+ if (code < 123) { return true }
+ if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
+ if (astral === false) { return false }
+ return isInAstralSet(code, astralIdentifierStartCodes)
+ }
-var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
-var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
+ // Test whether a given character is part of an identifier.
-nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
+ function isIdentifierChar(code, astral) {
+ if (code < 48) { return code === 36 }
+ if (code < 58) { return true }
+ if (code < 65) { return false }
+ if (code < 91) { return true }
+ if (code < 97) { return code === 95 }
+ if (code < 123) { return true }
+ if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
+ if (astral === false) { return false }
+ return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
+ }
-// These are a run-length and offset encoded representation of the
-// >0xffff code points that are a valid part of identifiers. The
-// offset starts at 0x10000, and each pair of numbers represents an
-// offset to the next range, and then a size of the range. They were
-// generated by bin/generate-identifier-regex.js
+ // ## Token types
-// eslint-disable-next-line comma-spacing
-var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,190,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,26,230,43,117,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,68,12,0,67,12,65,1,31,6129,15,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541];
+ // The assignment of fine-grained, information-carrying type objects
+ // allows the tokenizer to store the information it has about a
+ // token in a way that is very cheap for the parser to look up.
-// eslint-disable-next-line comma-spacing
-var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239];
+ // All token type variables start with an underscore, to make them
+ // easy to recognize.
-// This has a complexity linear to the value of the code. The
-// assumption is that looking up astral identifier characters is
-// rare.
-function isInAstralSet(code, set) {
- var pos = 0x10000;
- for (var i = 0; i < set.length; i += 2) {
- pos += set[i];
- if (pos > code) { return false }
- pos += set[i + 1];
- if (pos >= code) { return true }
- }
-}
-
-// Test whether a given character code starts an identifier.
-
-function isIdentifierStart(code, astral) {
- if (code < 65) { return code === 36 }
- if (code < 91) { return true }
- if (code < 97) { return code === 95 }
- if (code < 123) { return true }
- if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
- if (astral === false) { return false }
- return isInAstralSet(code, astralIdentifierStartCodes)
-}
-
-// Test whether a given character is part of an identifier.
-
-function isIdentifierChar(code, astral) {
- if (code < 48) { return code === 36 }
- if (code < 58) { return true }
- if (code < 65) { return false }
- if (code < 91) { return true }
- if (code < 97) { return code === 95 }
- if (code < 123) { return true }
- if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
- if (astral === false) { return false }
- return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
-}
-
-// ## Token types
-
-// The assignment of fine-grained, information-carrying type objects
-// allows the tokenizer to store the information it has about a
-// token in a way that is very cheap for the parser to look up.
-
-// All token type variables start with an underscore, to make them
-// easy to recognize.
-
-// The `beforeExpr` property is used to disambiguate between regular
-// expressions and divisions. It is set on all token types that can
-// be followed by an expression (thus, a slash after them would be a
-// regular expression).
-//
-// The `startsExpr` property is used to check if the token ends a
-// `yield` expression. It is set on all token types that either can
-// directly start an expression (like a quotation mark) or can
-// continue an expression (like the body of a string).
-//
-// `isLoop` marks a keyword as starting a loop, which is important
-// to know when parsing a label, in order to allow or disallow
-// continue jumps to that label.
-
-var TokenType = function TokenType(label, conf) {
- if ( conf === void 0 ) conf = {};
-
- this.label = label;
- this.keyword = conf.keyword;
- this.beforeExpr = !!conf.beforeExpr;
- this.startsExpr = !!conf.startsExpr;
- this.isLoop = !!conf.isLoop;
- this.isAssign = !!conf.isAssign;
- this.prefix = !!conf.prefix;
- this.postfix = !!conf.postfix;
- this.binop = conf.binop || null;
- this.updateContext = null;
-};
-
-function binop(name, prec) {
- return new TokenType(name, {beforeExpr: true, binop: prec})
-}
-var beforeExpr = {beforeExpr: true};
-var startsExpr = {startsExpr: true};
-
-// Map keyword names to token types.
-
-var keywords$1 = {};
-
-// Succinct definitions of keyword token types
-function kw(name, options) {
- if ( options === void 0 ) options = {};
-
- options.keyword = name;
- return keywords$1[name] = new TokenType(name, options)
-}
-
-var types = {
- num: new TokenType("num", startsExpr),
- regexp: new TokenType("regexp", startsExpr),
- string: new TokenType("string", startsExpr),
- name: new TokenType("name", startsExpr),
- eof: new TokenType("eof"),
-
- // Punctuation token types.
- bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
- bracketR: new TokenType("]"),
- braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
- braceR: new TokenType("}"),
- parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
- parenR: new TokenType(")"),
- comma: new TokenType(",", beforeExpr),
- semi: new TokenType(";", beforeExpr),
- colon: new TokenType(":", beforeExpr),
- dot: new TokenType("."),
- question: new TokenType("?", beforeExpr),
- arrow: new TokenType("=>", beforeExpr),
- template: new TokenType("template"),
- invalidTemplate: new TokenType("invalidTemplate"),
- ellipsis: new TokenType("...", beforeExpr),
- backQuote: new TokenType("`", startsExpr),
- dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
-
- // Operators. These carry several kinds of properties to help the
- // parser use them properly (the presence of these properties is
- // what categorizes them as operators).
- //
- // `binop`, when present, specifies that this operator is a binary
- // operator, and will refer to its precedence.
+ // The `beforeExpr` property is used to disambiguate between regular
+ // expressions and divisions. It is set on all token types that can
+ // be followed by an expression (thus, a slash after them would be a
+ // regular expression).
//
- // `prefix` and `postfix` mark the operator as a prefix or postfix
- // unary operator.
- //
- // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
- // binary operators with a very low precedence, that should result
- // in AssignmentExpression nodes.
-
- eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
- assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
- incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
- prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
- logicalOR: binop("||", 1),
- logicalAND: binop("&&", 2),
- bitwiseOR: binop("|", 3),
- bitwiseXOR: binop("^", 4),
- bitwiseAND: binop("&", 5),
- equality: binop("==/!=/===/!==", 6),
- relational: binop("</>/<=/>=", 7),
- bitShift: binop("<</>>/>>>", 8),
- plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
- modulo: binop("%", 10),
- star: binop("*", 10),
- slash: binop("/", 10),
- starstar: new TokenType("**", {beforeExpr: true}),
-
- // Keyword token types.
- _break: kw("break"),
- _case: kw("case", beforeExpr),
- _catch: kw("catch"),
- _continue: kw("continue"),
- _debugger: kw("debugger"),
- _default: kw("default", beforeExpr),
- _do: kw("do", {isLoop: true, beforeExpr: true}),
- _else: kw("else", beforeExpr),
- _finally: kw("finally"),
- _for: kw("for", {isLoop: true}),
- _function: kw("function", startsExpr),
- _if: kw("if"),
- _return: kw("return", beforeExpr),
- _switch: kw("switch"),
- _throw: kw("throw", beforeExpr),
- _try: kw("try"),
- _var: kw("var"),
- _const: kw("const"),
- _while: kw("while", {isLoop: true}),
- _with: kw("with"),
- _new: kw("new", {beforeExpr: true, startsExpr: true}),
- _this: kw("this", startsExpr),
- _super: kw("super", startsExpr),
- _class: kw("class", startsExpr),
- _extends: kw("extends", beforeExpr),
- _export: kw("export"),
- _import: kw("import"),
- _null: kw("null", startsExpr),
- _true: kw("true", startsExpr),
- _false: kw("false", startsExpr),
- _in: kw("in", {beforeExpr: true, binop: 7}),
- _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
- _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
- _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
- _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
-};
-
-// Matches a whole line break (where CRLF is considered a single
-// line break). Used to count lines.
-
-var lineBreak = /\r\n?|\n|\u2028|\u2029/;
-var lineBreakG = new RegExp(lineBreak.source, "g");
-
-function isNewLine(code, ecma2019String) {
- return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
-}
-
-var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
-
-var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
-
-var ref = Object.prototype;
-var hasOwnProperty = ref.hasOwnProperty;
-var toString = ref.toString;
-
-// Checks if an object has a property.
-
-function has(obj, propName) {
- return hasOwnProperty.call(obj, propName)
-}
-
-var isArray = Array.isArray || (function (obj) { return (
- toString.call(obj) === "[object Array]"
-); });
-
-// These are used when `options.locations` is on, for the
-// `startLoc` and `endLoc` properties.
-
-var Position = function Position(line, col) {
- this.line = line;
- this.column = col;
-};
-
-Position.prototype.offset = function offset (n) {
- return new Position(this.line, this.column + n)
-};
-
-var SourceLocation = function SourceLocation(p, start, end) {
- this.start = start;
- this.end = end;
- if (p.sourceFile !== null) { this.source = p.sourceFile; }
-};
-
-// The `getLineInfo` function is mostly useful when the
-// `locations` option is off (for performance reasons) and you
-// want to find the line/column position for a given character
-// offset. `input` should be the code string that the offset refers
-// into.
-
-function getLineInfo(input, offset) {
- for (var line = 1, cur = 0;;) {
- lineBreakG.lastIndex = cur;
- var match = lineBreakG.exec(input);
- if (match && match.index < offset) {
- ++line;
- cur = match.index + match[0].length;
- } else {
- return new Position(line, offset - cur)
- }
- }
-}
-
-// A second optional argument can be given to further configure
-// the parser process. These options are recognized:
-
-var defaultOptions = {
- // `ecmaVersion` indicates the ECMAScript version to parse. Must be
- // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
- // (2019). This influences support for strict mode, the set of
- // reserved words, and support for new syntax features. The default
- // is 9.
- ecmaVersion: 9,
- // `sourceType` indicates the mode the code should be parsed in.
- // Can be either `"script"` or `"module"`. This influences global
- // strict mode and parsing of `import` and `export` declarations.
- sourceType: "script",
- // `onInsertedSemicolon` can be a callback that will be called
- // when a semicolon is automatically inserted. It will be passed
- // th position of the comma as an offset, and if `locations` is
- // enabled, it is given the location as a `{line, column}` object
- // as second argument.
- onInsertedSemicolon: null,
- // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
- // trailing commas.
- onTrailingComma: null,
- // By default, reserved words are only enforced if ecmaVersion >= 5.
- // Set `allowReserved` to a boolean value to explicitly turn this on
- // an off. When this option has the value "never", reserved words
- // and keywords can also not be used as property names.
- allowReserved: null,
- // When enabled, a return at the top level is not considered an
- // error.
- allowReturnOutsideFunction: false,
- // When enabled, import/export statements are not constrained to
- // appearing at the top of the program.
- allowImportExportEverywhere: false,
- // When enabled, await identifiers are allowed to appear at the top-level scope,
- // but they are still not allowed in non-async functions.
- allowAwaitOutsideFunction: false,
- // When enabled, hashbang directive in the beginning of file
- // is allowed and treated as a line comment.
- allowHashBang: false,
- // When `locations` is on, `loc` properties holding objects with
- // `start` and `end` properties in `{line, column}` form (with
- // line being 1-based and column 0-based) will be attached to the
- // nodes.
- locations: false,
- // A function can be passed as `onToken` option, which will
- // cause Acorn to call that function with object in the same
- // format as tokens returned from `tokenizer().getToken()`. Note
- // that you are not allowed to call the parser from the
- // callback—that will corrupt its internal state.
- onToken: null,
- // A function can be passed as `onComment` option, which will
- // cause Acorn to call that function with `(block, text, start,
- // end)` parameters whenever a comment is skipped. `block` is a
- // boolean indicating whether this is a block (`/* */`) comment,
- // `text` is the content of the comment, and `start` and `end` are
- // character offsets that denote the start and end of the comment.
- // When the `locations` option is on, two more parameters are
- // passed, the full `{line, column}` locations of the start and
- // end of the comments. Note that you are not allowed to call the
- // parser from the callback—that will corrupt its internal state.
- onComment: null,
- // Nodes have their start and end characters offsets recorded in
- // `start` and `end` properties (directly on the node, rather than
- // the `loc` object, which holds line/column data. To also add a
- // [semi-standardized][range] `range` property holding a `[start,
- // end]` array with the same numbers, set the `ranges` option to
- // `true`.
+ // The `startsExpr` property is used to check if the token ends a
+ // `yield` expression. It is set on all token types that either can
+ // directly start an expression (like a quotation mark) or can
+ // continue an expression (like the body of a string).
//
- // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
- ranges: false,
- // It is possible to parse multiple files into a single AST by
- // passing the tree produced by parsing the first file as
- // `program` option in subsequent parses. This will add the
- // toplevel forms of the parsed file to the `Program` (top) node
- // of an existing parse tree.
- program: null,
- // When `locations` is on, you can pass this to record the source
- // file in every node's `loc` object.
- sourceFile: null,
- // This value, if given, is stored in every node, whether
- // `locations` is on or off.
- directSourceFile: null,
- // When enabled, parenthesized expressions are represented by
- // (non-standard) ParenthesizedExpression nodes
- preserveParens: false
-};
-
-// Interpret and default an options object
-
-function getOptions(opts) {
- var options = {};
-
- for (var opt in defaultOptions)
- { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
-
- if (options.ecmaVersion >= 2015)
- { options.ecmaVersion -= 2009; }
-
- if (options.allowReserved == null)
- { options.allowReserved = options.ecmaVersion < 5; }
-
- if (isArray(options.onToken)) {
- var tokens = options.onToken;
- options.onToken = function (token) { return tokens.push(token); };
+ // `isLoop` marks a keyword as starting a loop, which is important
+ // to know when parsing a label, in order to allow or disallow
+ // continue jumps to that label.
+
+ var TokenType = function TokenType(label, conf) {
+ if ( conf === void 0 ) conf = {};
+
+ this.label = label;
+ this.keyword = conf.keyword;
+ this.beforeExpr = !!conf.beforeExpr;
+ this.startsExpr = !!conf.startsExpr;
+ this.isLoop = !!conf.isLoop;
+ this.isAssign = !!conf.isAssign;
+ this.prefix = !!conf.prefix;
+ this.postfix = !!conf.postfix;
+ this.binop = conf.binop || null;
+ this.updateContext = null;
+ };
+
+ function binop(name, prec) {
+ return new TokenType(name, {beforeExpr: true, binop: prec})
+ }
+ var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true};
+
+ // Map keyword names to token types.
+
+ var keywords$1 = {};
+
+ // Succinct definitions of keyword token types
+ function kw(name, options) {
+ if ( options === void 0 ) options = {};
+
+ options.keyword = name;
+ return keywords$1[name] = new TokenType(name, options)
+ }
+
+ var types = {
+ num: new TokenType("num", startsExpr),
+ regexp: new TokenType("regexp", startsExpr),
+ string: new TokenType("string", startsExpr),
+ name: new TokenType("name", startsExpr),
+ eof: new TokenType("eof"),
+
+ // Punctuation token types.
+ bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
+ bracketR: new TokenType("]"),
+ braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
+ braceR: new TokenType("}"),
+ parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
+ parenR: new TokenType(")"),
+ comma: new TokenType(",", beforeExpr),
+ semi: new TokenType(";", beforeExpr),
+ colon: new TokenType(":", beforeExpr),
+ dot: new TokenType("."),
+ question: new TokenType("?", beforeExpr),
+ arrow: new TokenType("=>", beforeExpr),
+ template: new TokenType("template"),
+ invalidTemplate: new TokenType("invalidTemplate"),
+ ellipsis: new TokenType("...", beforeExpr),
+ backQuote: new TokenType("`", startsExpr),
+ dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),
+
+ // Operators. These carry several kinds of properties to help the
+ // parser use them properly (the presence of these properties is
+ // what categorizes them as operators).
+ //
+ // `binop`, when present, specifies that this operator is a binary
+ // operator, and will refer to its precedence.
+ //
+ // `prefix` and `postfix` mark the operator as a prefix or postfix
+ // unary operator.
+ //
+ // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
+ // binary operators with a very low precedence, that should result
+ // in AssignmentExpression nodes.
+
+ eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
+ assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
+ incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
+ prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
+ logicalOR: binop("||", 1),
+ logicalAND: binop("&&", 2),
+ bitwiseOR: binop("|", 3),
+ bitwiseXOR: binop("^", 4),
+ bitwiseAND: binop("&", 5),
+ equality: binop("==/!=/===/!==", 6),
+ relational: binop("</>/<=/>=", 7),
+ bitShift: binop("<</>>/>>>", 8),
+ plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
+ modulo: binop("%", 10),
+ star: binop("*", 10),
+ slash: binop("/", 10),
+ starstar: new TokenType("**", {beforeExpr: true}),
+
+ // Keyword token types.
+ _break: kw("break"),
+ _case: kw("case", beforeExpr),
+ _catch: kw("catch"),
+ _continue: kw("continue"),
+ _debugger: kw("debugger"),
+ _default: kw("default", beforeExpr),
+ _do: kw("do", {isLoop: true, beforeExpr: true}),
+ _else: kw("else", beforeExpr),
+ _finally: kw("finally"),
+ _for: kw("for", {isLoop: true}),
+ _function: kw("function", startsExpr),
+ _if: kw("if"),
+ _return: kw("return", beforeExpr),
+ _switch: kw("switch"),
+ _throw: kw("throw", beforeExpr),
+ _try: kw("try"),
+ _var: kw("var"),
+ _const: kw("const"),
+ _while: kw("while", {isLoop: true}),
+ _with: kw("with"),
+ _new: kw("new", {beforeExpr: true, startsExpr: true}),
+ _this: kw("this", startsExpr),
+ _super: kw("super", startsExpr),
+ _class: kw("class", startsExpr),
+ _extends: kw("extends", beforeExpr),
+ _export: kw("export"),
+ _import: kw("import", startsExpr),
+ _null: kw("null", startsExpr),
+ _true: kw("true", startsExpr),
+ _false: kw("false", startsExpr),
+ _in: kw("in", {beforeExpr: true, binop: 7}),
+ _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
+ _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
+ _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
+ _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
+ };
+
+ // Matches a whole line break (where CRLF is considered a single
+ // line break). Used to count lines.
+
+ var lineBreak = /\r\n?|\n|\u2028|\u2029/;
+ var lineBreakG = new RegExp(lineBreak.source, "g");
+
+ function isNewLine(code, ecma2019String) {
+ return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029))
}
- if (isArray(options.onComment))
- { options.onComment = pushComment(options, options.onComment); }
-
- return options
-}
-
-function pushComment(options, array) {
- return function(block, text, start, end, startLoc, endLoc) {
- var comment = {
- type: block ? "Block" : "Line",
- value: text,
- start: start,
- end: end
- };
- if (options.locations)
- { comment.loc = new SourceLocation(this, startLoc, endLoc); }
- if (options.ranges)
- { comment.range = [start, end]; }
- array.push(comment);
+
+ var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
+
+ var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
+
+ var ref = Object.prototype;
+ var hasOwnProperty = ref.hasOwnProperty;
+ var toString = ref.toString;
+
+ // Checks if an object has a property.
+
+ function has(obj, propName) {
+ return hasOwnProperty.call(obj, propName)
}
-}
-
-// Each scope gets a bitset that may contain these flags
-var SCOPE_TOP = 1;
-var SCOPE_FUNCTION = 2;
-var SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION;
-var SCOPE_ASYNC = 4;
-var SCOPE_GENERATOR = 8;
-var SCOPE_ARROW = 16;
-var SCOPE_SIMPLE_CATCH = 32;
-
-function functionFlags(async, generator) {
- return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
-}
-
-// Used in checkLVal and declareName to determine the type of a binding
-var BIND_NONE = 0;
-var BIND_VAR = 1;
-var BIND_LEXICAL = 2;
-var BIND_FUNCTION = 3;
-var BIND_SIMPLE_CATCH = 4;
-var BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
-
-function keywordRegexp(words) {
- return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
-}
-
-var Parser = function Parser(options, input, startPos) {
- this.options = options = getOptions(options);
- this.sourceFile = options.sourceFile;
- this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]);
- var reserved = "";
- if (!options.allowReserved) {
- for (var v = options.ecmaVersion;; v--)
- { if (reserved = reservedWords[v]) { break } }
- if (options.sourceType === "module") { reserved += " await"; }
+
+ var isArray = Array.isArray || (function (obj) { return (
+ toString.call(obj) === "[object Array]"
+ ); });
+
+ function wordsRegexp(words) {
+ return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}
- this.reservedWords = keywordRegexp(reserved);
- var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
- this.reservedWordsStrict = keywordRegexp(reservedStrict);
- this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind);
- this.input = String(input);
-
- // Used to signal to callers of `readWord1` whether the word
- // contained any escape sequences. This is needed because words with
- // escape sequences must not be interpreted as keywords.
- this.containsEsc = false;
-
- // Set up token state
-
- // The current position of the tokenizer in the input.
- if (startPos) {
- this.pos = startPos;
- this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
- this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
- } else {
- this.pos = this.lineStart = 0;
- this.curLine = 1;
+
+ // These are used when `options.locations` is on, for the
+ // `startLoc` and `endLoc` properties.
+
+ var Position = function Position(line, col) {
+ this.line = line;
+ this.column = col;
+ };
+
+ Position.prototype.offset = function offset (n) {
+ return new Position(this.line, this.column + n)
+ };
+
+ var SourceLocation = function SourceLocation(p, start, end) {
+ this.start = start;
+ this.end = end;
+ if (p.sourceFile !== null) { this.source = p.sourceFile; }
+ };
+
+ // The `getLineInfo` function is mostly useful when the
+ // `locations` option is off (for performance reasons) and you
+ // want to find the line/column position for a given character
+ // offset. `input` should be the code string that the offset refers
+ // into.
+
+ function getLineInfo(input, offset) {
+ for (var line = 1, cur = 0;;) {
+ lineBreakG.lastIndex = cur;
+ var match = lineBreakG.exec(input);
+ if (match && match.index < offset) {
+ ++line;
+ cur = match.index + match[0].length;
+ } else {
+ return new Position(line, offset - cur)
+ }
+ }
}
- // Properties of the current token:
- // Its type
- this.type = types.eof;
- // For tokens that include more information than their type, the value
- this.value = null;
- // Its start and end offset
- this.start = this.end = this.pos;
- // And, if locations are used, the {line, column} object
- // corresponding to those offsets
- this.startLoc = this.endLoc = this.curPosition();
-
- // Position information for the previous token
- this.lastTokEndLoc = this.lastTokStartLoc = null;
- this.lastTokStart = this.lastTokEnd = this.pos;
-
- // The context stack is used to superficially track syntactic
- // context to predict whether a regular expression is allowed in a
- // given position.
- this.context = this.initialContext();
- this.exprAllowed = true;
-
- // Figure out if it's a module code.
- this.inModule = options.sourceType === "module";
- this.strict = this.inModule || this.strictDirective(this.pos);
-
- // Used to signify the start of a potential arrow function
- this.potentialArrowAt = -1;
-
- // Positions to delayed-check that yield/await does not exist in default parameters.
- this.yieldPos = this.awaitPos = 0;
- // Labels in scope.
- this.labels = [];
-
- // If enabled, skip leading hashbang line.
- if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
- { this.skipLineComment(2); }
-
- // Scope tracking for duplicate variable names (see scope.js)
- this.scopeStack = [];
- this.enterScope(SCOPE_TOP);
-
- // For RegExp validation
- this.regexpState = null;
-};
-
-var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true } };
-
-Parser.prototype.parse = function parse () {
- var node = this.options.program || this.startNode();
- this.nextToken();
- return this.parseTopLevel(node)
-};
-
-prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
-prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
-prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
-
-Parser.extend = function extend () {
- var plugins = [], len = arguments.length;
- while ( len-- ) plugins[ len ] = arguments[ len ];
-
- var cls = this;
- for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
- return cls
-};
-
-Parser.parse = function parse (input, options) {
- return new this(options, input).parse()
-};
-
-Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
- var parser = new this(options, input, pos);
- parser.nextToken();
- return parser.parseExpression()
-};
-
-Parser.tokenizer = function tokenizer (input, options) {
- return new this(options, input)
-};
-
-Object.defineProperties( Parser.prototype, prototypeAccessors );
-
-var pp = Parser.prototype;
-
-// ## Parser utilities
-
-var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/;
-pp.strictDirective = function(start) {
- var this$1 = this;
-
- for (;;) {
- skipWhiteSpace.lastIndex = start;
- start += skipWhiteSpace.exec(this$1.input)[0].length;
- var match = literal.exec(this$1.input.slice(start));
- if (!match) { return false }
- if ((match[1] || match[2]) === "use strict") { return true }
- start += match[0].length;
+ // A second optional argument can be given to further configure
+ // the parser process. These options are recognized:
+
+ var defaultOptions = {
+ // `ecmaVersion` indicates the ECMAScript version to parse. Must be
+ // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10
+ // (2019). This influences support for strict mode, the set of
+ // reserved words, and support for new syntax features. The default
+ // is 10.
+ ecmaVersion: 10,
+ // `sourceType` indicates the mode the code should be parsed in.
+ // Can be either `"script"` or `"module"`. This influences global
+ // strict mode and parsing of `import` and `export` declarations.
+ sourceType: "script",
+ // `onInsertedSemicolon` can be a callback that will be called
+ // when a semicolon is automatically inserted. It will be passed
+ // the position of the comma as an offset, and if `locations` is
+ // enabled, it is given the location as a `{line, column}` object
+ // as second argument.
+ onInsertedSemicolon: null,
+ // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
+ // trailing commas.
+ onTrailingComma: null,
+ // By default, reserved words are only enforced if ecmaVersion >= 5.
+ // Set `allowReserved` to a boolean value to explicitly turn this on
+ // an off. When this option has the value "never", reserved words
+ // and keywords can also not be used as property names.
+ allowReserved: null,
+ // When enabled, a return at the top level is not considered an
+ // error.
+ allowReturnOutsideFunction: false,
+ // When enabled, import/export statements are not constrained to
+ // appearing at the top of the program.
+ allowImportExportEverywhere: false,
+ // When enabled, await identifiers are allowed to appear at the top-level scope,
+ // but they are still not allowed in non-async functions.
+ allowAwaitOutsideFunction: false,
+ // When enabled, hashbang directive in the beginning of file
+ // is allowed and treated as a line comment.
+ allowHashBang: false,
+ // When `locations` is on, `loc` properties holding objects with
+ // `start` and `end` properties in `{line, column}` form (with
+ // line being 1-based and column 0-based) will be attached to the
+ // nodes.
+ locations: false,
+ // A function can be passed as `onToken` option, which will
+ // cause Acorn to call that function with object in the same
+ // format as tokens returned from `tokenizer().getToken()`. Note
+ // that you are not allowed to call the parser from the
+ // callback—that will corrupt its internal state.
+ onToken: null,
+ // A function can be passed as `onComment` option, which will
+ // cause Acorn to call that function with `(block, text, start,
+ // end)` parameters whenever a comment is skipped. `block` is a
+ // boolean indicating whether this is a block (`/* */`) comment,
+ // `text` is the content of the comment, and `start` and `end` are
+ // character offsets that denote the start and end of the comment.
+ // When the `locations` option is on, two more parameters are
+ // passed, the full `{line, column}` locations of the start and
+ // end of the comments. Note that you are not allowed to call the
+ // parser from the callback—that will corrupt its internal state.
+ onComment: null,
+ // Nodes have their start and end characters offsets recorded in
+ // `start` and `end` properties (directly on the node, rather than
+ // the `loc` object, which holds line/column data. To also add a
+ // [semi-standardized][range] `range` property holding a `[start,
+ // end]` array with the same numbers, set the `ranges` option to
+ // `true`.
+ //
+ // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
+ ranges: false,
+ // It is possible to parse multiple files into a single AST by
+ // passing the tree produced by parsing the first file as
+ // `program` option in subsequent parses. This will add the
+ // toplevel forms of the parsed file to the `Program` (top) node
+ // of an existing parse tree.
+ program: null,
+ // When `locations` is on, you can pass this to record the source
+ // file in every node's `loc` object.
+ sourceFile: null,
+ // This value, if given, is stored in every node, whether
+ // `locations` is on or off.
+ directSourceFile: null,
+ // When enabled, parenthesized expressions are represented by
+ // (non-standard) ParenthesizedExpression nodes
+ preserveParens: false
+ };
+
+ // Interpret and default an options object
+
+ function getOptions(opts) {
+ var options = {};
+
+ for (var opt in defaultOptions)
+ { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }
+
+ if (options.ecmaVersion >= 2015)
+ { options.ecmaVersion -= 2009; }
+
+ if (options.allowReserved == null)
+ { options.allowReserved = options.ecmaVersion < 5; }
+
+ if (isArray(options.onToken)) {
+ var tokens = options.onToken;
+ options.onToken = function (token) { return tokens.push(token); };
+ }
+ if (isArray(options.onComment))
+ { options.onComment = pushComment(options, options.onComment); }
+
+ return options
+ }
+
+ function pushComment(options, array) {
+ return function(block, text, start, end, startLoc, endLoc) {
+ var comment = {
+ type: block ? "Block" : "Line",
+ value: text,
+ start: start,
+ end: end
+ };
+ if (options.locations)
+ { comment.loc = new SourceLocation(this, startLoc, endLoc); }
+ if (options.ranges)
+ { comment.range = [start, end]; }
+ array.push(comment);
+ }
}
-};
-// Predicate that tests whether the next token is of the given
-// type, and if yes, consumes it as a side effect.
+ // Each scope gets a bitset that may contain these flags
+ var
+ SCOPE_TOP = 1,
+ SCOPE_FUNCTION = 2,
+ SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION,
+ SCOPE_ASYNC = 4,
+ SCOPE_GENERATOR = 8,
+ SCOPE_ARROW = 16,
+ SCOPE_SIMPLE_CATCH = 32,
+ SCOPE_SUPER = 64,
+ SCOPE_DIRECT_SUPER = 128;
+
+ function functionFlags(async, generator) {
+ return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0)
+ }
+
+ // Used in checkLVal and declareName to determine the type of a binding
+ var
+ BIND_NONE = 0, // Not a binding
+ BIND_VAR = 1, // Var-style binding
+ BIND_LEXICAL = 2, // Let- or const-style binding
+ BIND_FUNCTION = 3, // Function declaration
+ BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding
+ BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
+
+ var Parser = function Parser(options, input, startPos) {
+ this.options = options = getOptions(options);
+ this.sourceFile = options.sourceFile;
+ this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]);
+ var reserved = "";
+ if (options.allowReserved !== true) {
+ for (var v = options.ecmaVersion;; v--)
+ { if (reserved = reservedWords[v]) { break } }
+ if (options.sourceType === "module") { reserved += " await"; }
+ }
+ this.reservedWords = wordsRegexp(reserved);
+ var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
+ this.reservedWordsStrict = wordsRegexp(reservedStrict);
+ this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind);
+ this.input = String(input);
+
+ // Used to signal to callers of `readWord1` whether the word
+ // contained any escape sequences. This is needed because words with
+ // escape sequences must not be interpreted as keywords.
+ this.containsEsc = false;
+
+ // Set up token state
+
+ // The current position of the tokenizer in the input.
+ if (startPos) {
+ this.pos = startPos;
+ this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
+ this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
+ } else {
+ this.pos = this.lineStart = 0;
+ this.curLine = 1;
+ }
+
+ // Properties of the current token:
+ // Its type
+ this.type = types.eof;
+ // For tokens that include more information than their type, the value
+ this.value = null;
+ // Its start and end offset
+ this.start = this.end = this.pos;
+ // And, if locations are used, the {line, column} object
+ // corresponding to those offsets
+ this.startLoc = this.endLoc = this.curPosition();
+
+ // Position information for the previous token
+ this.lastTokEndLoc = this.lastTokStartLoc = null;
+ this.lastTokStart = this.lastTokEnd = this.pos;
+
+ // The context stack is used to superficially track syntactic
+ // context to predict whether a regular expression is allowed in a
+ // given position.
+ this.context = this.initialContext();
+ this.exprAllowed = true;
+
+ // Figure out if it's a module code.
+ this.inModule = options.sourceType === "module";
+ this.strict = this.inModule || this.strictDirective(this.pos);
+
+ // Used to signify the start of a potential arrow function
+ this.potentialArrowAt = -1;
+
+ // Positions to delayed-check that yield/await does not exist in default parameters.
+ this.yieldPos = this.awaitPos = this.awaitIdentPos = 0;
+ // Labels in scope.
+ this.labels = [];
+ // Thus-far undefined exports.
+ this.undefinedExports = {};
+
+ // If enabled, skip leading hashbang line.
+ if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
+ { this.skipLineComment(2); }
+
+ // Scope tracking for duplicate variable names (see scope.js)
+ this.scopeStack = [];
+ this.enterScope(SCOPE_TOP);
+
+ // For RegExp validation
+ this.regexpState = null;
+ };
+
+ var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } };
+
+ Parser.prototype.parse = function parse () {
+ var node = this.options.program || this.startNode();
+ this.nextToken();
+ return this.parseTopLevel(node)
+ };
+
+ prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 };
+ prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 };
+ prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 };
+ prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 };
+ prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 };
+ prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) };
+
+ // Switch to a getter for 7.0.0.
+ Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 };
+
+ Parser.extend = function extend () {
+ var plugins = [], len = arguments.length;
+ while ( len-- ) plugins[ len ] = arguments[ len ];
+
+ var cls = this;
+ for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
+ return cls
+ };
+
+ Parser.parse = function parse (input, options) {
+ return new this(options, input).parse()
+ };
+
+ Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) {
+ var parser = new this(options, input, pos);
+ parser.nextToken();
+ return parser.parseExpression()
+ };
-pp.eat = function(type) {
- if (this.type === type) {
+ Parser.tokenizer = function tokenizer (input, options) {
+ return new this(options, input)
+ };
+
+ Object.defineProperties( Parser.prototype, prototypeAccessors );
+
+ var pp = Parser.prototype;
+
+ // ## Parser utilities
+
+ var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/;
+ pp.strictDirective = function(start) {
+ for (;;) {
+ // Try to find string literal.
+ skipWhiteSpace.lastIndex = start;
+ start += skipWhiteSpace.exec(this.input)[0].length;
+ var match = literal.exec(this.input.slice(start));
+ if (!match) { return false }
+ if ((match[1] || match[2]) === "use strict") { return true }
+ start += match[0].length;
+
+ // Skip semicolon, if any.
+ skipWhiteSpace.lastIndex = start;
+ start += skipWhiteSpace.exec(this.input)[0].length;
+ if (this.input[start] === ";")
+ { start++; }
+ }
+ };
+
+ // Predicate that tests whether the next token is of the given
+ // type, and if yes, consumes it as a side effect.
+
+ pp.eat = function(type) {
+ if (this.type === type) {
+ this.next();
+ return true
+ } else {
+ return false
+ }
+ };
+
+ // Tests whether parsed token is a contextual keyword.
+
+ pp.isContextual = function(name) {
+ return this.type === types.name && this.value === name && !this.containsEsc
+ };
+
+ // Consumes contextual keyword if possible.
+
+ pp.eatContextual = function(name) {
+ if (!this.isContextual(name)) { return false }
this.next();
return true
- } else {
- return false
- }
-};
+ };
-// Tests whether parsed token is a contextual keyword.
+ // Asserts that following token is given contextual keyword.
-pp.isContextual = function(name) {
- return this.type === types.name && this.value === name && !this.containsEsc
-};
+ pp.expectContextual = function(name) {
+ if (!this.eatContextual(name)) { this.unexpected(); }
+ };
-// Consumes contextual keyword if possible.
+ // Test whether a semicolon can be inserted at the current position.
-pp.eatContextual = function(name) {
- if (!this.isContextual(name)) { return false }
- this.next();
- return true
-};
+ pp.canInsertSemicolon = function() {
+ return this.type === types.eof ||
+ this.type === types.braceR ||
+ lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
+ };
-// Asserts that following token is given contextual keyword.
+ pp.insertSemicolon = function() {
+ if (this.canInsertSemicolon()) {
+ if (this.options.onInsertedSemicolon)
+ { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
+ return true
+ }
+ };
-pp.expectContextual = function(name) {
- if (!this.eatContextual(name)) { this.unexpected(); }
-};
+ // Consume a semicolon, or, failing that, see if we are allowed to
+ // pretend that there is a semicolon at this position.
-// Test whether a semicolon can be inserted at the current position.
+ pp.semicolon = function() {
+ if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
+ };
-pp.canInsertSemicolon = function() {
- return this.type === types.eof ||
- this.type === types.braceR ||
- lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
-};
+ pp.afterTrailingComma = function(tokType, notNext) {
+ if (this.type === tokType) {
+ if (this.options.onTrailingComma)
+ { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
+ if (!notNext)
+ { this.next(); }
+ return true
+ }
+ };
-pp.insertSemicolon = function() {
- if (this.canInsertSemicolon()) {
- if (this.options.onInsertedSemicolon)
- { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
- return true
- }
-};
+ // Expect a token of a given type. If found, consume it, otherwise,
+ // raise an unexpected token error.
-// Consume a semicolon, or, failing that, see if we are allowed to
-// pretend that there is a semicolon at this position.
+ pp.expect = function(type) {
+ this.eat(type) || this.unexpected();
+ };
-pp.semicolon = function() {
- if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
-};
+ // Raise an unexpected token error.
-pp.afterTrailingComma = function(tokType, notNext) {
- if (this.type === tokType) {
- if (this.options.onTrailingComma)
- { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
- if (!notNext)
- { this.next(); }
- return true
- }
-};
-
-// Expect a token of a given type. If found, consume it, otherwise,
-// raise an unexpected token error.
-
-pp.expect = function(type) {
- this.eat(type) || this.unexpected();
-};
-
-// Raise an unexpected token error.
-
-pp.unexpected = function(pos) {
- this.raise(pos != null ? pos : this.start, "Unexpected token");
-};
-
-function DestructuringErrors() {
- this.shorthandAssign =
- this.trailingComma =
- this.parenthesizedAssign =
- this.parenthesizedBind =
- this.doubleProto =
- -1;
-}
-
-pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
- if (!refDestructuringErrors) { return }
- if (refDestructuringErrors.trailingComma > -1)
- { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
- var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
- if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
-};
-
-pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
- if (!refDestructuringErrors) { return false }
- var shorthandAssign = refDestructuringErrors.shorthandAssign;
- var doubleProto = refDestructuringErrors.doubleProto;
- if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
- if (shorthandAssign >= 0)
- { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
- if (doubleProto >= 0)
- { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
-};
-
-pp.checkYieldAwaitInDefaultParams = function() {
- if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
- { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
- if (this.awaitPos)
- { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
-};
-
-pp.isSimpleAssignTarget = function(expr) {
- if (expr.type === "ParenthesizedExpression")
- { return this.isSimpleAssignTarget(expr.expression) }
- return expr.type === "Identifier" || expr.type === "MemberExpression"
-};
-
-var pp$1 = Parser.prototype;
-
-// ### Statement parsing
-
-// Parse a program. Initializes the parser, reads any number of
-// statements, and wraps them in a Program node. Optionally takes a
-// `program` argument. If present, the statements will be appended
-// to its body instead of creating a new node.
-
-pp$1.parseTopLevel = function(node) {
- var this$1 = this;
-
- var exports = {};
- if (!node.body) { node.body = []; }
- while (this.type !== types.eof) {
- var stmt = this$1.parseStatement(null, true, exports);
- node.body.push(stmt);
- }
- this.adaptDirectivePrologue(node.body);
- this.next();
- if (this.options.ecmaVersion >= 6) {
+ pp.unexpected = function(pos) {
+ this.raise(pos != null ? pos : this.start, "Unexpected token");
+ };
+
+ function DestructuringErrors() {
+ this.shorthandAssign =
+ this.trailingComma =
+ this.parenthesizedAssign =
+ this.parenthesizedBind =
+ this.doubleProto =
+ -1;
+ }
+
+ pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
+ if (!refDestructuringErrors) { return }
+ if (refDestructuringErrors.trailingComma > -1)
+ { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
+ var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
+ if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
+ };
+
+ pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
+ if (!refDestructuringErrors) { return false }
+ var shorthandAssign = refDestructuringErrors.shorthandAssign;
+ var doubleProto = refDestructuringErrors.doubleProto;
+ if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 }
+ if (shorthandAssign >= 0)
+ { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); }
+ if (doubleProto >= 0)
+ { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); }
+ };
+
+ pp.checkYieldAwaitInDefaultParams = function() {
+ if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
+ { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
+ if (this.awaitPos)
+ { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
+ };
+
+ pp.isSimpleAssignTarget = function(expr) {
+ if (expr.type === "ParenthesizedExpression")
+ { return this.isSimpleAssignTarget(expr.expression) }
+ return expr.type === "Identifier" || expr.type === "MemberExpression"
+ };
+
+ var pp$1 = Parser.prototype;
+
+ // ### Statement parsing
+
+ // Parse a program. Initializes the parser, reads any number of
+ // statements, and wraps them in a Program node. Optionally takes a
+ // `program` argument. If present, the statements will be appended
+ // to its body instead of creating a new node.
+
+ pp$1.parseTopLevel = function(node) {
+ var exports = {};
+ if (!node.body) { node.body = []; }
+ while (this.type !== types.eof) {
+ var stmt = this.parseStatement(null, true, exports);
+ node.body.push(stmt);
+ }
+ if (this.inModule)
+ { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1)
+ {
+ var name = list[i];
+
+ this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined"));
+ } }
+ this.adaptDirectivePrologue(node.body);
+ this.next();
node.sourceType = this.options.sourceType;
- }
- return this.finishNode(node, "Program")
-};
-
-var loopLabel = {kind: "loop"};
-var switchLabel = {kind: "switch"};
-
-pp$1.isLet = function() {
- if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
- skipWhiteSpace.lastIndex = this.pos;
- var skip = skipWhiteSpace.exec(this.input);
- var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
- if (nextCh === 91 || nextCh === 123) { return true } // '{' and '['
- if (isIdentifierStart(nextCh, true)) {
- var pos = next + 1;
- while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
- var ident = this.input.slice(next, pos);
- if (!keywordRelationalOperator.test(ident)) { return true }
- }
- return false
-};
-
-// check 'async [no LineTerminator here] function'
-// - 'async /*foo*/ function' is OK.
-// - 'async /*\n*/ function' is invalid.
-pp$1.isAsyncFunction = function() {
- if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
- { return false }
-
- skipWhiteSpace.lastIndex = this.pos;
- var skip = skipWhiteSpace.exec(this.input);
- var next = this.pos + skip[0].length;
- return !lineBreak.test(this.input.slice(this.pos, next)) &&
- this.input.slice(next, next + 8) === "function" &&
- (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
-};
-
-// Parse a single statement.
-//
-// If expecting a statement and finding a slash operator, parse a
-// regular expression literal. This is to handle cases like
-// `if (foo) /blah/.exec(foo)`, where looking at the previous token
-// does not help.
-
-pp$1.parseStatement = function(context, topLevel, exports) {
- var starttype = this.type, node = this.startNode(), kind;
-
- if (this.isLet()) {
- starttype = types._var;
- kind = "let";
- }
+ return this.finishNode(node, "Program")
+ };
- // Most types of statements are recognized by the keyword they
- // start with. Many are trivial to parse, some require a bit of
- // complexity.
-
- switch (starttype) {
- case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
- case types._debugger: return this.parseDebuggerStatement(node)
- case types._do: return this.parseDoStatement(node)
- case types._for: return this.parseForStatement(node)
- case types._function:
- if ((context && (this.strict || context !== "if")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
- return this.parseFunctionStatement(node, false, !context)
- case types._class:
- if (context) { this.unexpected(); }
- return this.parseClass(node, true)
- case types._if: return this.parseIfStatement(node)
- case types._return: return this.parseReturnStatement(node)
- case types._switch: return this.parseSwitchStatement(node)
- case types._throw: return this.parseThrowStatement(node)
- case types._try: return this.parseTryStatement(node)
- case types._const: case types._var:
- kind = kind || this.value;
- if (context && kind !== "var") { this.unexpected(); }
- return this.parseVarStatement(node, kind)
- case types._while: return this.parseWhileStatement(node)
- case types._with: return this.parseWithStatement(node)
- case types.braceL: return this.parseBlock(true, node)
- case types.semi: return this.parseEmptyStatement(node)
- case types._export:
- case types._import:
- if (!this.options.allowImportExportEverywhere) {
- if (!topLevel)
- { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
- if (!this.inModule)
- { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
- }
- return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
-
- // If the statement does not start with a statement keyword or a
- // brace, it's an ExpressionStatement or LabeledStatement. We
- // simply start parsing an expression, and afterwards, if the
- // next token is a colon and the expression was a simple
- // Identifier node, we switch to interpreting it as a label.
- default:
- if (this.isAsyncFunction()) {
+ var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
+
+ pp$1.isLet = function(context) {
+ if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false }
+ skipWhiteSpace.lastIndex = this.pos;
+ var skip = skipWhiteSpace.exec(this.input);
+ var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
+ // For ambiguous cases, determine if a LexicalDeclaration (or only a
+ // Statement) is allowed here. If context is not empty then only a Statement
+ // is allowed. However, `let [` is an explicit negative lookahead for
+ // ExpressionStatement, so special-case it first.
+ if (nextCh === 91) { return true } // '['
+ if (context) { return false }
+
+ if (nextCh === 123) { return true } // '{'
+ if (isIdentifierStart(nextCh, true)) {
+ var pos = next + 1;
+ while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
+ var ident = this.input.slice(next, pos);
+ if (!keywordRelationalOperator.test(ident)) { return true }
+ }
+ return false
+ };
+
+ // check 'async [no LineTerminator here] function'
+ // - 'async /*foo*/ function' is OK.
+ // - 'async /*\n*/ function' is invalid.
+ pp$1.isAsyncFunction = function() {
+ if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
+ { return false }
+
+ skipWhiteSpace.lastIndex = this.pos;
+ var skip = skipWhiteSpace.exec(this.input);
+ var next = this.pos + skip[0].length;
+ return !lineBreak.test(this.input.slice(this.pos, next)) &&
+ this.input.slice(next, next + 8) === "function" &&
+ (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
+ };
+
+ // Parse a single statement.
+ //
+ // If expecting a statement and finding a slash operator, parse a
+ // regular expression literal. This is to handle cases like
+ // `if (foo) /blah/.exec(foo)`, where looking at the previous token
+ // does not help.
+
+ pp$1.parseStatement = function(context, topLevel, exports) {
+ var starttype = this.type, node = this.startNode(), kind;
+
+ if (this.isLet(context)) {
+ starttype = types._var;
+ kind = "let";
+ }
+
+ // Most types of statements are recognized by the keyword they
+ // start with. Many are trivial to parse, some require a bit of
+ // complexity.
+
+ switch (starttype) {
+ case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
+ case types._debugger: return this.parseDebuggerStatement(node)
+ case types._do: return this.parseDoStatement(node)
+ case types._for: return this.parseForStatement(node)
+ case types._function:
+ // Function as sole body of either an if statement or a labeled statement
+ // works, but not when it is part of a labeled statement that is the sole
+ // body of an if statement.
+ if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); }
+ return this.parseFunctionStatement(node, false, !context)
+ case types._class:
if (context) { this.unexpected(); }
- this.next();
- return this.parseFunctionStatement(node, true, !context)
+ return this.parseClass(node, true)
+ case types._if: return this.parseIfStatement(node)
+ case types._return: return this.parseReturnStatement(node)
+ case types._switch: return this.parseSwitchStatement(node)
+ case types._throw: return this.parseThrowStatement(node)
+ case types._try: return this.parseTryStatement(node)
+ case types._const: case types._var:
+ kind = kind || this.value;
+ if (context && kind !== "var") { this.unexpected(); }
+ return this.parseVarStatement(node, kind)
+ case types._while: return this.parseWhileStatement(node)
+ case types._with: return this.parseWithStatement(node)
+ case types.braceL: return this.parseBlock(true, node)
+ case types.semi: return this.parseEmptyStatement(node)
+ case types._export:
+ case types._import:
+ if (this.options.ecmaVersion > 10 && starttype === types._import) {
+ skipWhiteSpace.lastIndex = this.pos;
+ var skip = skipWhiteSpace.exec(this.input);
+ var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
+ if (nextCh === 40) // '('
+ { return this.parseExpressionStatement(node, this.parseExpression()) }
+ }
+
+ if (!this.options.allowImportExportEverywhere) {
+ if (!topLevel)
+ { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
+ if (!this.inModule)
+ { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
+ }
+ return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)
+
+ // If the statement does not start with a statement keyword or a
+ // brace, it's an ExpressionStatement or LabeledStatement. We
+ // simply start parsing an expression, and afterwards, if the
+ // next token is a colon and the expression was a simple
+ // Identifier node, we switch to interpreting it as a label.
+ default:
+ if (this.isAsyncFunction()) {
+ if (context) { this.unexpected(); }
+ this.next();
+ return this.parseFunctionStatement(node, true, !context)
+ }
+
+ var maybeName = this.value, expr = this.parseExpression();
+ if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
+ { return this.parseLabeledStatement(node, maybeName, expr, context) }
+ else { return this.parseExpressionStatement(node, expr) }
}
+ };
- var maybeName = this.value, expr = this.parseExpression();
- if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
- { return this.parseLabeledStatement(node, maybeName, expr, context) }
- else { return this.parseExpressionStatement(node, expr) }
- }
-};
+ pp$1.parseBreakContinueStatement = function(node, keyword) {
+ var isBreak = keyword === "break";
+ this.next();
+ if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
+ else if (this.type !== types.name) { this.unexpected(); }
+ else {
+ node.label = this.parseIdent();
+ this.semicolon();
+ }
-pp$1.parseBreakContinueStatement = function(node, keyword) {
- var this$1 = this;
+ // Verify that there is an actual destination to break or
+ // continue to.
+ var i = 0;
+ for (; i < this.labels.length; ++i) {
+ var lab = this.labels[i];
+ if (node.label == null || lab.name === node.label.name) {
+ if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
+ if (node.label && isBreak) { break }
+ }
+ }
+ if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
+ return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
+ };
- var isBreak = keyword === "break";
- this.next();
- if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
- else if (this.type !== types.name) { this.unexpected(); }
- else {
- node.label = this.parseIdent();
+ pp$1.parseDebuggerStatement = function(node) {
+ this.next();
this.semicolon();
- }
+ return this.finishNode(node, "DebuggerStatement")
+ };
- // Verify that there is an actual destination to break or
- // continue to.
- var i = 0;
- for (; i < this.labels.length; ++i) {
- var lab = this$1.labels[i];
- if (node.label == null || lab.name === node.label.name) {
- if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
- if (node.label && isBreak) { break }
- }
- }
- if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
- return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
-};
-
-pp$1.parseDebuggerStatement = function(node) {
- this.next();
- this.semicolon();
- return this.finishNode(node, "DebuggerStatement")
-};
-
-pp$1.parseDoStatement = function(node) {
- this.next();
- this.labels.push(loopLabel);
- node.body = this.parseStatement("do");
- this.labels.pop();
- this.expect(types._while);
- node.test = this.parseParenExpression();
- if (this.options.ecmaVersion >= 6)
- { this.eat(types.semi); }
- else
- { this.semicolon(); }
- return this.finishNode(node, "DoWhileStatement")
-};
-
-// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
-// loop is non-trivial. Basically, we have to parse the init `var`
-// statement or expression, disallowing the `in` operator (see
-// the second parameter to `parseExpression`), and then check
-// whether the next token is `in` or `of`. When there is no init
-// part (semicolon immediately after the opening parenthesis), it
-// is a regular `for` loop.
-
-pp$1.parseForStatement = function(node) {
- this.next();
- var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
- this.labels.push(loopLabel);
- this.enterScope(0);
- this.expect(types.parenL);
- if (this.type === types.semi) {
- if (awaitAt > -1) { this.unexpected(awaitAt); }
- return this.parseFor(node, null)
- }
- var isLet = this.isLet();
- if (this.type === types._var || this.type === types._const || isLet) {
- var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
+ pp$1.parseDoStatement = function(node) {
this.next();
- this.parseVar(init$1, true, kind);
- this.finishNode(init$1, "VariableDeclaration");
- if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 &&
- !(kind !== "var" && init$1.declarations[0].init)) {
+ this.labels.push(loopLabel);
+ node.body = this.parseStatement("do");
+ this.labels.pop();
+ this.expect(types._while);
+ node.test = this.parseParenExpression();
+ if (this.options.ecmaVersion >= 6)
+ { this.eat(types.semi); }
+ else
+ { this.semicolon(); }
+ return this.finishNode(node, "DoWhileStatement")
+ };
+
+ // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
+ // loop is non-trivial. Basically, we have to parse the init `var`
+ // statement or expression, disallowing the `in` operator (see
+ // the second parameter to `parseExpression`), and then check
+ // whether the next token is `in` or `of`. When there is no init
+ // part (semicolon immediately after the opening parenthesis), it
+ // is a regular `for` loop.
+
+ pp$1.parseForStatement = function(node) {
+ this.next();
+ var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1;
+ this.labels.push(loopLabel);
+ this.enterScope(0);
+ this.expect(types.parenL);
+ if (this.type === types.semi) {
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ return this.parseFor(node, null)
+ }
+ var isLet = this.isLet();
+ if (this.type === types._var || this.type === types._const || isLet) {
+ var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
+ this.next();
+ this.parseVar(init$1, true, kind);
+ this.finishNode(init$1, "VariableDeclaration");
+ if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) {
+ if (this.options.ecmaVersion >= 9) {
+ if (this.type === types._in) {
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ } else { node.await = awaitAt > -1; }
+ }
+ return this.parseForIn(node, init$1)
+ }
+ if (awaitAt > -1) { this.unexpected(awaitAt); }
+ return this.parseFor(node, init$1)
+ }
+ var refDestructuringErrors = new DestructuringErrors;
+ var init = this.parseExpression(true, refDestructuringErrors);
+ if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
if (this.options.ecmaVersion >= 9) {
if (this.type === types._in) {
if (awaitAt > -1) { this.unexpected(awaitAt); }
} else { node.await = awaitAt > -1; }
}
- return this.parseForIn(node, init$1)
+ this.toAssignable(init, false, refDestructuringErrors);
+ this.checkLVal(init);
+ return this.parseForIn(node, init)
+ } else {
+ this.checkExpressionErrors(refDestructuringErrors, true);
}
if (awaitAt > -1) { this.unexpected(awaitAt); }
- return this.parseFor(node, init$1)
- }
- var refDestructuringErrors = new DestructuringErrors;
- var init = this.parseExpression(true, refDestructuringErrors);
- if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
- if (this.options.ecmaVersion >= 9) {
- if (this.type === types._in) {
- if (awaitAt > -1) { this.unexpected(awaitAt); }
- } else { node.await = awaitAt > -1; }
- }
- this.toAssignable(init, false, refDestructuringErrors);
- this.checkLVal(init);
- return this.parseForIn(node, init)
- } else {
- this.checkExpressionErrors(refDestructuringErrors, true);
- }
- if (awaitAt > -1) { this.unexpected(awaitAt); }
- return this.parseFor(node, init)
-};
-
-pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
- this.next();
- return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
-};
-
-pp$1.parseIfStatement = function(node) {
- this.next();
- node.test = this.parseParenExpression();
- // allow function declarations in branches, but only in non-strict mode
- node.consequent = this.parseStatement("if");
- node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
- return this.finishNode(node, "IfStatement")
-};
-
-pp$1.parseReturnStatement = function(node) {
- if (!this.inFunction && !this.options.allowReturnOutsideFunction)
- { this.raise(this.start, "'return' outside of function"); }
- this.next();
-
- // In `return` (and `break`/`continue`), the keywords with
- // optional arguments, we eagerly look for a semicolon or the
- // possibility to insert one.
-
- if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
- else { node.argument = this.parseExpression(); this.semicolon(); }
- return this.finishNode(node, "ReturnStatement")
-};
-
-pp$1.parseSwitchStatement = function(node) {
- var this$1 = this;
-
- this.next();
- node.discriminant = this.parseParenExpression();
- node.cases = [];
- this.expect(types.braceL);
- this.labels.push(switchLabel);
- this.enterScope(0);
-
- // Statements under must be grouped (by label) in SwitchCase
- // nodes. `cur` is used to keep the node that we are currently
- // adding statements to.
-
- var cur;
- for (var sawDefault = false; this.type !== types.braceR;) {
- if (this$1.type === types._case || this$1.type === types._default) {
- var isCase = this$1.type === types._case;
- if (cur) { this$1.finishNode(cur, "SwitchCase"); }
- node.cases.push(cur = this$1.startNode());
- cur.consequent = [];
- this$1.next();
- if (isCase) {
- cur.test = this$1.parseExpression();
+ return this.parseFor(node, init)
+ };
+
+ pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) {
+ this.next();
+ return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync)
+ };
+
+ pp$1.parseIfStatement = function(node) {
+ this.next();
+ node.test = this.parseParenExpression();
+ // allow function declarations in branches, but only in non-strict mode
+ node.consequent = this.parseStatement("if");
+ node.alternate = this.eat(types._else) ? this.parseStatement("if") : null;
+ return this.finishNode(node, "IfStatement")
+ };
+
+ pp$1.parseReturnStatement = function(node) {
+ if (!this.inFunction && !this.options.allowReturnOutsideFunction)
+ { this.raise(this.start, "'return' outside of function"); }
+ this.next();
+
+ // In `return` (and `break`/`continue`), the keywords with
+ // optional arguments, we eagerly look for a semicolon or the
+ // possibility to insert one.
+
+ if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
+ else { node.argument = this.parseExpression(); this.semicolon(); }
+ return this.finishNode(node, "ReturnStatement")
+ };
+
+ pp$1.parseSwitchStatement = function(node) {
+ this.next();
+ node.discriminant = this.parseParenExpression();
+ node.cases = [];
+ this.expect(types.braceL);
+ this.labels.push(switchLabel);
+ this.enterScope(0);
+
+ // Statements under must be grouped (by label) in SwitchCase
+ // nodes. `cur` is used to keep the node that we are currently
+ // adding statements to.
+
+ var cur;
+ for (var sawDefault = false; this.type !== types.braceR;) {
+ if (this.type === types._case || this.type === types._default) {
+ var isCase = this.type === types._case;
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ node.cases.push(cur = this.startNode());
+ cur.consequent = [];
+ this.next();
+ if (isCase) {
+ cur.test = this.parseExpression();
+ } else {
+ if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); }
+ sawDefault = true;
+ cur.test = null;
+ }
+ this.expect(types.colon);
} else {
- if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); }
- sawDefault = true;
- cur.test = null;
+ if (!cur) { this.unexpected(); }
+ cur.consequent.push(this.parseStatement(null));
}
- this$1.expect(types.colon);
- } else {
- if (!cur) { this$1.unexpected(); }
- cur.consequent.push(this$1.parseStatement(null));
}
- }
- this.exitScope();
- if (cur) { this.finishNode(cur, "SwitchCase"); }
- this.next(); // Closing brace
- this.labels.pop();
- return this.finishNode(node, "SwitchStatement")
-};
-
-pp$1.parseThrowStatement = function(node) {
- this.next();
- if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
- { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
- node.argument = this.parseExpression();
- this.semicolon();
- return this.finishNode(node, "ThrowStatement")
-};
-
-// Reused empty array added for node fields that are always empty.
-
-var empty = [];
-
-pp$1.parseTryStatement = function(node) {
- this.next();
- node.block = this.parseBlock();
- node.handler = null;
- if (this.type === types._catch) {
- var clause = this.startNode();
+ this.exitScope();
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ this.next(); // Closing brace
+ this.labels.pop();
+ return this.finishNode(node, "SwitchStatement")
+ };
+
+ pp$1.parseThrowStatement = function(node) {
this.next();
- if (this.eat(types.parenL)) {
- clause.param = this.parseBindingAtom();
- var simple = clause.param.type === "Identifier";
- this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
- this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
- this.expect(types.parenR);
- } else {
- if (this.options.ecmaVersion < 10) { this.unexpected(); }
- clause.param = null;
- this.enterScope(0);
+ if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
+ { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
+ node.argument = this.parseExpression();
+ this.semicolon();
+ return this.finishNode(node, "ThrowStatement")
+ };
+
+ // Reused empty array added for node fields that are always empty.
+
+ var empty = [];
+
+ pp$1.parseTryStatement = function(node) {
+ this.next();
+ node.block = this.parseBlock();
+ node.handler = null;
+ if (this.type === types._catch) {
+ var clause = this.startNode();
+ this.next();
+ if (this.eat(types.parenL)) {
+ clause.param = this.parseBindingAtom();
+ var simple = clause.param.type === "Identifier";
+ this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0);
+ this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL);
+ this.expect(types.parenR);
+ } else {
+ if (this.options.ecmaVersion < 10) { this.unexpected(); }
+ clause.param = null;
+ this.enterScope(0);
+ }
+ clause.body = this.parseBlock(false);
+ this.exitScope();
+ node.handler = this.finishNode(clause, "CatchClause");
+ }
+ node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
+ if (!node.handler && !node.finalizer)
+ { this.raise(node.start, "Missing catch or finally clause"); }
+ return this.finishNode(node, "TryStatement")
+ };
+
+ pp$1.parseVarStatement = function(node, kind) {
+ this.next();
+ this.parseVar(node, false, kind);
+ this.semicolon();
+ return this.finishNode(node, "VariableDeclaration")
+ };
+
+ pp$1.parseWhileStatement = function(node) {
+ this.next();
+ node.test = this.parseParenExpression();
+ this.labels.push(loopLabel);
+ node.body = this.parseStatement("while");
+ this.labels.pop();
+ return this.finishNode(node, "WhileStatement")
+ };
+
+ pp$1.parseWithStatement = function(node) {
+ if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
+ this.next();
+ node.object = this.parseParenExpression();
+ node.body = this.parseStatement("with");
+ return this.finishNode(node, "WithStatement")
+ };
+
+ pp$1.parseEmptyStatement = function(node) {
+ this.next();
+ return this.finishNode(node, "EmptyStatement")
+ };
+
+ pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
+ for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1)
+ {
+ var label = list[i$1];
+
+ if (label.name === maybeName)
+ { this.raise(expr.start, "Label '" + maybeName + "' is already declared");
+ } }
+ var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
+ for (var i = this.labels.length - 1; i >= 0; i--) {
+ var label$1 = this.labels[i];
+ if (label$1.statementStart === node.start) {
+ // Update information about previous labels on this node
+ label$1.statementStart = this.start;
+ label$1.kind = kind;
+ } else { break }
+ }
+ this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
+ node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
+ this.labels.pop();
+ node.label = expr;
+ return this.finishNode(node, "LabeledStatement")
+ };
+
+ pp$1.parseExpressionStatement = function(node, expr) {
+ node.expression = expr;
+ this.semicolon();
+ return this.finishNode(node, "ExpressionStatement")
+ };
+
+ // Parse a semicolon-enclosed block of statements, handling `"use
+ // strict"` declarations when `allowStrict` is true (used for
+ // function bodies).
+
+ pp$1.parseBlock = function(createNewLexicalScope, node) {
+ if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
+ if ( node === void 0 ) node = this.startNode();
+
+ node.body = [];
+ this.expect(types.braceL);
+ if (createNewLexicalScope) { this.enterScope(0); }
+ while (!this.eat(types.braceR)) {
+ var stmt = this.parseStatement(null);
+ node.body.push(stmt);
}
- clause.body = this.parseBlock(false);
+ if (createNewLexicalScope) { this.exitScope(); }
+ return this.finishNode(node, "BlockStatement")
+ };
+
+ // Parse a regular `for` loop. The disambiguation code in
+ // `parseStatement` will already have parsed the init statement or
+ // expression.
+
+ pp$1.parseFor = function(node, init) {
+ node.init = init;
+ this.expect(types.semi);
+ node.test = this.type === types.semi ? null : this.parseExpression();
+ this.expect(types.semi);
+ node.update = this.type === types.parenR ? null : this.parseExpression();
+ this.expect(types.parenR);
+ node.body = this.parseStatement("for");
this.exitScope();
- node.handler = this.finishNode(clause, "CatchClause");
- }
- node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
- if (!node.handler && !node.finalizer)
- { this.raise(node.start, "Missing catch or finally clause"); }
- return this.finishNode(node, "TryStatement")
-};
-
-pp$1.parseVarStatement = function(node, kind) {
- this.next();
- this.parseVar(node, false, kind);
- this.semicolon();
- return this.finishNode(node, "VariableDeclaration")
-};
-
-pp$1.parseWhileStatement = function(node) {
- this.next();
- node.test = this.parseParenExpression();
- this.labels.push(loopLabel);
- node.body = this.parseStatement("while");
- this.labels.pop();
- return this.finishNode(node, "WhileStatement")
-};
-
-pp$1.parseWithStatement = function(node) {
- if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
- this.next();
- node.object = this.parseParenExpression();
- node.body = this.parseStatement("with");
- return this.finishNode(node, "WithStatement")
-};
-
-pp$1.parseEmptyStatement = function(node) {
- this.next();
- return this.finishNode(node, "EmptyStatement")
-};
-
-pp$1.parseLabeledStatement = function(node, maybeName, expr, context) {
- var this$1 = this;
-
- for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1)
- {
- var label = list[i$1];
-
- if (label.name === maybeName)
- { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared");
- } }
- var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
- for (var i = this.labels.length - 1; i >= 0; i--) {
- var label$1 = this$1.labels[i];
- if (label$1.statementStart === node.start) {
- // Update information about previous labels on this node
- label$1.statementStart = this$1.start;
- label$1.kind = kind;
- } else { break }
- }
- this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
- node.body = this.parseStatement(context);
- if (node.body.type === "ClassDeclaration" ||
- node.body.type === "VariableDeclaration" && node.body.kind !== "var" ||
- node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator || node.body.async))
- { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); }
- this.labels.pop();
- node.label = expr;
- return this.finishNode(node, "LabeledStatement")
-};
-
-pp$1.parseExpressionStatement = function(node, expr) {
- node.expression = expr;
- this.semicolon();
- return this.finishNode(node, "ExpressionStatement")
-};
-
-// Parse a semicolon-enclosed block of statements, handling `"use
-// strict"` declarations when `allowStrict` is true (used for
-// function bodies).
-
-pp$1.parseBlock = function(createNewLexicalScope, node) {
- var this$1 = this;
- if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;
- if ( node === void 0 ) node = this.startNode();
-
- node.body = [];
- this.expect(types.braceL);
- if (createNewLexicalScope) { this.enterScope(0); }
- while (!this.eat(types.braceR)) {
- var stmt = this$1.parseStatement(null);
- node.body.push(stmt);
- }
- if (createNewLexicalScope) { this.exitScope(); }
- return this.finishNode(node, "BlockStatement")
-};
-
-// Parse a regular `for` loop. The disambiguation code in
-// `parseStatement` will already have parsed the init statement or
-// expression.
-
-pp$1.parseFor = function(node, init) {
- node.init = init;
- this.expect(types.semi);
- node.test = this.type === types.semi ? null : this.parseExpression();
- this.expect(types.semi);
- node.update = this.type === types.parenR ? null : this.parseExpression();
- this.expect(types.parenR);
- this.exitScope();
- node.body = this.parseStatement("for");
- this.labels.pop();
- return this.finishNode(node, "ForStatement")
-};
-
-// Parse a `for`/`in` and `for`/`of` loop, which are almost
-// same from parser's perspective.
-
-pp$1.parseForIn = function(node, init) {
- var type = this.type === types._in ? "ForInStatement" : "ForOfStatement";
- this.next();
- if (type === "ForInStatement") {
- if (init.type === "AssignmentPattern" ||
- (init.type === "VariableDeclaration" && init.declarations[0].init != null &&
- (this.strict || init.declarations[0].id.type !== "Identifier")))
- { this.raise(init.start, "Invalid assignment in for-in loop head"); }
- }
- node.left = init;
- node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign();
- this.expect(types.parenR);
- this.exitScope();
- node.body = this.parseStatement("for");
- this.labels.pop();
- return this.finishNode(node, type)
-};
-
-// Parse a list of variable declarations.
-
-pp$1.parseVar = function(node, isFor, kind) {
- var this$1 = this;
-
- node.declarations = [];
- node.kind = kind;
- for (;;) {
- var decl = this$1.startNode();
- this$1.parseVarId(decl, kind);
- if (this$1.eat(types.eq)) {
- decl.init = this$1.parseMaybeAssign(isFor);
- } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) {
- this$1.unexpected();
- } else if (decl.id.type !== "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) {
- this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value");
- } else {
- decl.init = null;
+ this.labels.pop();
+ return this.finishNode(node, "ForStatement")
+ };
+
+ // Parse a `for`/`in` and `for`/`of` loop, which are almost
+ // same from parser's perspective.
+
+ pp$1.parseForIn = function(node, init) {
+ var isForIn = this.type === types._in;
+ this.next();
+
+ if (
+ init.type === "VariableDeclaration" &&
+ init.declarations[0].init != null &&
+ (
+ !isForIn ||
+ this.options.ecmaVersion < 8 ||
+ this.strict ||
+ init.kind !== "var" ||
+ init.declarations[0].id.type !== "Identifier"
+ )
+ ) {
+ this.raise(
+ init.start,
+ ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer")
+ );
+ } else if (init.type === "AssignmentPattern") {
+ this.raise(init.start, "Invalid left-hand side in for-loop");
}
- node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
- if (!this$1.eat(types.comma)) { break }
- }
- return node
-};
-
-pp$1.parseVarId = function(decl, kind) {
- decl.id = this.parseBindingAtom(kind);
- this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
-};
-
-var FUNC_STATEMENT = 1;
-var FUNC_HANGING_STATEMENT = 2;
-var FUNC_NULLABLE_ID = 4;
-
-// Parse a function declaration or literal (depending on the
-// `isStatement` parameter).
-
-pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
- this.initFunction(node);
- if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync)
- { node.generator = this.eat(types.star); }
- if (this.options.ecmaVersion >= 8)
- { node.async = !!isAsync; }
-
- if (statement & FUNC_STATEMENT) {
- node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
- if (node.id && !(statement & FUNC_HANGING_STATEMENT))
- { this.checkLVal(node.id, this.inModule && !this.inFunction ? BIND_LEXICAL : BIND_FUNCTION); }
- }
+ node.left = init;
+ node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
+ this.expect(types.parenR);
+ node.body = this.parseStatement("for");
+ this.exitScope();
+ this.labels.pop();
+ return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement")
+ };
- var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
- this.yieldPos = 0;
- this.awaitPos = 0;
- this.enterScope(functionFlags(node.async, node.generator));
-
- if (!(statement & FUNC_STATEMENT))
- { node.id = this.type === types.name ? this.parseIdent() : null; }
-
- this.parseFunctionParams(node);
- this.parseFunctionBody(node, allowExpressionBody);
-
- this.yieldPos = oldYieldPos;
- this.awaitPos = oldAwaitPos;
- return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
-};
-
-pp$1.parseFunctionParams = function(node) {
- this.expect(types.parenL);
- node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
- this.checkYieldAwaitInDefaultParams();
-};
-
-// Parse a class declaration or literal (depending on the
-// `isStatement` parameter).
-
-pp$1.parseClass = function(node, isStatement) {
- var this$1 = this;
-
- this.next();
-
- this.parseClassId(node, isStatement);
- this.parseClassSuper(node);
- var classBody = this.startNode();
- var hadConstructor = false;
- classBody.body = [];
- this.expect(types.braceL);
- while (!this.eat(types.braceR)) {
- var element = this$1.parseClassElement();
- if (element) {
- classBody.body.push(element);
- if (element.type === "MethodDefinition" && element.kind === "constructor") {
- if (hadConstructor) { this$1.raise(element.start, "Duplicate constructor in the same class"); }
- hadConstructor = true;
+ // Parse a list of variable declarations.
+
+ pp$1.parseVar = function(node, isFor, kind) {
+ node.declarations = [];
+ node.kind = kind;
+ for (;;) {
+ var decl = this.startNode();
+ this.parseVarId(decl, kind);
+ if (this.eat(types.eq)) {
+ decl.init = this.parseMaybeAssign(isFor);
+ } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
+ this.unexpected();
+ } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) {
+ this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
+ } else {
+ decl.init = null;
}
+ node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
+ if (!this.eat(types.comma)) { break }
}
- }
- node.body = this.finishNode(classBody, "ClassBody");
- return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
-};
-
-pp$1.parseClassElement = function() {
- var this$1 = this;
-
- if (this.eat(types.semi)) { return null }
-
- var method = this.startNode();
- var tryContextual = function (k, noLineBreak) {
- if ( noLineBreak === void 0 ) noLineBreak = false;
-
- var start = this$1.start, startLoc = this$1.startLoc;
- if (!this$1.eatContextual(k)) { return false }
- if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
- if (method.key) { this$1.unexpected(); }
- method.computed = false;
- method.key = this$1.startNodeAt(start, startLoc);
- method.key.name = k;
- this$1.finishNode(method.key, "Identifier");
- return false
+ return node
};
- method.kind = "method";
- method.static = tryContextual("static");
- var isGenerator = this.eat(types.star);
- var isAsync = false;
- if (!isGenerator) {
- if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
- isAsync = true;
- isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
- } else if (tryContextual("get")) {
- method.kind = "get";
- } else if (tryContextual("set")) {
- method.kind = "set";
+ pp$1.parseVarId = function(decl, kind) {
+ decl.id = this.parseBindingAtom();
+ this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false);
+ };
+
+ var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4;
+
+ // Parse a function declaration or literal (depending on the
+ // `statement & FUNC_STATEMENT`).
+
+ // Remove `allowExpressionBody` for 7.0.0, as it is only called with false
+ pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) {
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
+ if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT))
+ { this.unexpected(); }
+ node.generator = this.eat(types.star);
}
- }
- if (!method.key) { this.parsePropertyName(method); }
- var key = method.key;
- if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
- key.type === "Literal" && key.value === "constructor")) {
- if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
- if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
- if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
- method.kind = "constructor";
- } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
- this.raise(key.start, "Classes may not have a static property named prototype");
- }
- this.parseClassMethod(method, isGenerator, isAsync);
- if (method.kind === "get" && method.value.params.length !== 0)
- { this.raiseRecoverable(method.value.start, "getter should have no params"); }
- if (method.kind === "set" && method.value.params.length !== 1)
- { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
- if (method.kind === "set" && method.value.params[0].type === "RestElement")
- { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
- return method
-};
-
-pp$1.parseClassMethod = function(method, isGenerator, isAsync) {
- method.value = this.parseMethod(isGenerator, isAsync);
- return this.finishNode(method, "MethodDefinition")
-};
-
-pp$1.parseClassId = function(node, isStatement) {
- node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null;
-};
-
-pp$1.parseClassSuper = function(node) {
- node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
-};
-
-// Parses module export declaration.
-
-pp$1.parseExport = function(node, exports) {
- var this$1 = this;
-
- this.next();
- // export * from '...'
- if (this.eat(types.star)) {
- this.expectContextual("from");
- if (this.type !== types.string) { this.unexpected(); }
- node.source = this.parseExprAtom();
- this.semicolon();
- return this.finishNode(node, "ExportAllDeclaration")
- }
- if (this.eat(types._default)) { // export default ...
- this.checkExport(exports, "default", this.lastTokStart);
- var isAsync;
- if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
- var fNode = this.startNode();
- this.next();
- if (isAsync) { this.next(); }
- node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync, true);
- } else if (this.type === types._class) {
- var cNode = this.startNode();
- node.declaration = this.parseClass(cNode, "nullableID");
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+
+ if (statement & FUNC_STATEMENT) {
+ node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent();
+ if (node.id && !(statement & FUNC_HANGING_STATEMENT))
+ // If it is a regular function declaration in sloppy mode, then it is
+ // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
+ // mode depends on properties of the current scope (see
+ // treatFunctionsAsVar).
+ { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); }
+ }
+
+ var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ this.awaitIdentPos = 0;
+ this.enterScope(functionFlags(node.async, node.generator));
+
+ if (!(statement & FUNC_STATEMENT))
+ { node.id = this.type === types.name ? this.parseIdent() : null; }
+
+ this.parseFunctionParams(node);
+ this.parseFunctionBody(node, allowExpressionBody, false);
+
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.awaitIdentPos = oldAwaitIdentPos;
+ return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression")
+ };
+
+ pp$1.parseFunctionParams = function(node) {
+ this.expect(types.parenL);
+ node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
+ this.checkYieldAwaitInDefaultParams();
+ };
+
+ // Parse a class declaration or literal (depending on the
+ // `isStatement` parameter).
+
+ pp$1.parseClass = function(node, isStatement) {
+ this.next();
+
+ // ecma-262 14.6 Class Definitions
+ // A class definition is always strict mode code.
+ var oldStrict = this.strict;
+ this.strict = true;
+
+ this.parseClassId(node, isStatement);
+ this.parseClassSuper(node);
+ var classBody = this.startNode();
+ var hadConstructor = false;
+ classBody.body = [];
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ var element = this.parseClassElement(node.superClass !== null);
+ if (element) {
+ classBody.body.push(element);
+ if (element.type === "MethodDefinition" && element.kind === "constructor") {
+ if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); }
+ hadConstructor = true;
+ }
+ }
+ }
+ node.body = this.finishNode(classBody, "ClassBody");
+ this.strict = oldStrict;
+ return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
+ };
+
+ pp$1.parseClassElement = function(constructorAllowsSuper) {
+ var this$1 = this;
+
+ if (this.eat(types.semi)) { return null }
+
+ var method = this.startNode();
+ var tryContextual = function (k, noLineBreak) {
+ if ( noLineBreak === void 0 ) noLineBreak = false;
+
+ var start = this$1.start, startLoc = this$1.startLoc;
+ if (!this$1.eatContextual(k)) { return false }
+ if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
+ if (method.key) { this$1.unexpected(); }
+ method.computed = false;
+ method.key = this$1.startNodeAt(start, startLoc);
+ method.key.name = k;
+ this$1.finishNode(method.key, "Identifier");
+ return false
+ };
+
+ method.kind = "method";
+ method.static = tryContextual("static");
+ var isGenerator = this.eat(types.star);
+ var isAsync = false;
+ if (!isGenerator) {
+ if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
+ } else if (tryContextual("get")) {
+ method.kind = "get";
+ } else if (tryContextual("set")) {
+ method.kind = "set";
+ }
+ }
+ if (!method.key) { this.parsePropertyName(method); }
+ var key = method.key;
+ var allowsDirectSuper = false;
+ if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" ||
+ key.type === "Literal" && key.value === "constructor")) {
+ if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); }
+ if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); }
+ if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); }
+ method.kind = "constructor";
+ allowsDirectSuper = constructorAllowsSuper;
+ } else if (method.static && key.type === "Identifier" && key.name === "prototype") {
+ this.raise(key.start, "Classes may not have a static property named prototype");
+ }
+ this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper);
+ if (method.kind === "get" && method.value.params.length !== 0)
+ { this.raiseRecoverable(method.value.start, "getter should have no params"); }
+ if (method.kind === "set" && method.value.params.length !== 1)
+ { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); }
+ if (method.kind === "set" && method.value.params[0].type === "RestElement")
+ { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
+ return method
+ };
+
+ pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) {
+ method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper);
+ return this.finishNode(method, "MethodDefinition")
+ };
+
+ pp$1.parseClassId = function(node, isStatement) {
+ if (this.type === types.name) {
+ node.id = this.parseIdent();
+ if (isStatement)
+ { this.checkLVal(node.id, BIND_LEXICAL, false); }
} else {
- node.declaration = this.parseMaybeAssign();
- this.semicolon();
+ if (isStatement === true)
+ { this.unexpected(); }
+ node.id = null;
}
- return this.finishNode(node, "ExportDefaultDeclaration")
- }
- // export var|const|let|function|class ...
- if (this.shouldParseExportStatement()) {
- node.declaration = this.parseStatement(null);
- if (node.declaration.type === "VariableDeclaration")
- { this.checkVariableExport(exports, node.declaration.declarations); }
- else
- { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
- node.specifiers = [];
- node.source = null;
- } else { // export { x, y as z } [from '...']
- node.declaration = null;
- node.specifiers = this.parseExportSpecifiers(exports);
- if (this.eatContextual("from")) {
+ };
+
+ pp$1.parseClassSuper = function(node) {
+ node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
+ };
+
+ // Parses module export declaration.
+
+ pp$1.parseExport = function(node, exports) {
+ this.next();
+ // export * from '...'
+ if (this.eat(types.star)) {
+ this.expectContextual("from");
if (this.type !== types.string) { this.unexpected(); }
node.source = this.parseExprAtom();
- } else {
- // check for keywords used as local names
- for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
- var spec = list[i];
+ this.semicolon();
+ return this.finishNode(node, "ExportAllDeclaration")
+ }
+ if (this.eat(types._default)) { // export default ...
+ this.checkExport(exports, "default", this.lastTokStart);
+ var isAsync;
+ if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
+ var fNode = this.startNode();
+ this.next();
+ if (isAsync) { this.next(); }
+ node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
+ } else if (this.type === types._class) {
+ var cNode = this.startNode();
+ node.declaration = this.parseClass(cNode, "nullableID");
+ } else {
+ node.declaration = this.parseMaybeAssign();
+ this.semicolon();
+ }
+ return this.finishNode(node, "ExportDefaultDeclaration")
+ }
+ // export var|const|let|function|class ...
+ if (this.shouldParseExportStatement()) {
+ node.declaration = this.parseStatement(null);
+ if (node.declaration.type === "VariableDeclaration")
+ { this.checkVariableExport(exports, node.declaration.declarations); }
+ else
+ { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
+ node.specifiers = [];
+ node.source = null;
+ } else { // export { x, y as z } [from '...']
+ node.declaration = null;
+ node.specifiers = this.parseExportSpecifiers(exports);
+ if (this.eatContextual("from")) {
+ if (this.type !== types.string) { this.unexpected(); }
+ node.source = this.parseExprAtom();
+ } else {
+ for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
+ // check for keywords used as local names
+ var spec = list[i];
+
+ this.checkUnreserved(spec.local);
+ // check if export is defined
+ this.checkLocalExport(spec.local);
+ }
- this$1.checkUnreserved(spec.local);
+ node.source = null;
}
+ this.semicolon();
+ }
+ return this.finishNode(node, "ExportNamedDeclaration")
+ };
- node.source = null;
+ pp$1.checkExport = function(exports, name, pos) {
+ if (!exports) { return }
+ if (has(exports, name))
+ { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
+ exports[name] = true;
+ };
+
+ pp$1.checkPatternExport = function(exports, pat) {
+ var type = pat.type;
+ if (type === "Identifier")
+ { this.checkExport(exports, pat.name, pat.start); }
+ else if (type === "ObjectPattern")
+ { for (var i = 0, list = pat.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this.checkPatternExport(exports, prop);
+ } }
+ else if (type === "ArrayPattern")
+ { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
+ var elt = list$1[i$1];
+
+ if (elt) { this.checkPatternExport(exports, elt); }
+ } }
+ else if (type === "Property")
+ { this.checkPatternExport(exports, pat.value); }
+ else if (type === "AssignmentPattern")
+ { this.checkPatternExport(exports, pat.left); }
+ else if (type === "RestElement")
+ { this.checkPatternExport(exports, pat.argument); }
+ else if (type === "ParenthesizedExpression")
+ { this.checkPatternExport(exports, pat.expression); }
+ };
+
+ pp$1.checkVariableExport = function(exports, decls) {
+ if (!exports) { return }
+ for (var i = 0, list = decls; i < list.length; i += 1)
+ {
+ var decl = list[i];
+
+ this.checkPatternExport(exports, decl.id);
+ }
+ };
+
+ pp$1.shouldParseExportStatement = function() {
+ return this.type.keyword === "var" ||
+ this.type.keyword === "const" ||
+ this.type.keyword === "class" ||
+ this.type.keyword === "function" ||
+ this.isLet() ||
+ this.isAsyncFunction()
+ };
+
+ // Parses a comma-separated list of module exports.
+
+ pp$1.parseExportSpecifiers = function(exports) {
+ var nodes = [], first = true;
+ // export { x, y as z } [from '...']
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this.expect(types.comma);
+ if (this.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var node = this.startNode();
+ node.local = this.parseIdent(true);
+ node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
+ this.checkExport(exports, node.exported.name, node.exported.start);
+ nodes.push(this.finishNode(node, "ExportSpecifier"));
+ }
+ return nodes
+ };
+
+ // Parses import declaration.
+
+ pp$1.parseImport = function(node) {
+ this.next();
+ // import '...'
+ if (this.type === types.string) {
+ node.specifiers = empty;
+ node.source = this.parseExprAtom();
+ } else {
+ node.specifiers = this.parseImportSpecifiers();
+ this.expectContextual("from");
+ node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
}
this.semicolon();
- }
- return this.finishNode(node, "ExportNamedDeclaration")
-};
-
-pp$1.checkExport = function(exports, name, pos) {
- if (!exports) { return }
- if (has(exports, name))
- { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
- exports[name] = true;
-};
-
-pp$1.checkPatternExport = function(exports, pat) {
- var this$1 = this;
-
- var type = pat.type;
- if (type === "Identifier")
- { this.checkExport(exports, pat.name, pat.start); }
- else if (type === "ObjectPattern")
- { for (var i = 0, list = pat.properties; i < list.length; i += 1)
- {
- var prop = list[i];
+ return this.finishNode(node, "ImportDeclaration")
+ };
- this$1.checkPatternExport(exports, prop);
- } }
- else if (type === "ArrayPattern")
- { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
- var elt = list$1[i$1];
+ // Parses a comma-separated list of module imports.
- if (elt) { this$1.checkPatternExport(exports, elt); }
- } }
- else if (type === "Property")
- { this.checkPatternExport(exports, pat.value); }
- else if (type === "AssignmentPattern")
- { this.checkPatternExport(exports, pat.left); }
- else if (type === "RestElement")
- { this.checkPatternExport(exports, pat.argument); }
- else if (type === "ParenthesizedExpression")
- { this.checkPatternExport(exports, pat.expression); }
-};
-
-pp$1.checkVariableExport = function(exports, decls) {
- var this$1 = this;
-
- if (!exports) { return }
- for (var i = 0, list = decls; i < list.length; i += 1)
- {
- var decl = list[i];
-
- this$1.checkPatternExport(exports, decl.id);
- }
-};
-
-pp$1.shouldParseExportStatement = function() {
- return this.type.keyword === "var" ||
- this.type.keyword === "const" ||
- this.type.keyword === "class" ||
- this.type.keyword === "function" ||
- this.isLet() ||
- this.isAsyncFunction()
-};
-
-// Parses a comma-separated list of module exports.
-
-pp$1.parseExportSpecifiers = function(exports) {
- var this$1 = this;
-
- var nodes = [], first = true;
- // export { x, y as z } [from '...']
- this.expect(types.braceL);
- while (!this.eat(types.braceR)) {
- if (!first) {
- this$1.expect(types.comma);
- if (this$1.afterTrailingComma(types.braceR)) { break }
- } else { first = false; }
-
- var node = this$1.startNode();
- node.local = this$1.parseIdent(true);
- node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local;
- this$1.checkExport(exports, node.exported.name, node.exported.start);
- nodes.push(this$1.finishNode(node, "ExportSpecifier"));
- }
- return nodes
-};
-
-// Parses import declaration.
-
-pp$1.parseImport = function(node) {
- this.next();
- // import '...'
- if (this.type === types.string) {
- node.specifiers = empty;
- node.source = this.parseExprAtom();
- } else {
- node.specifiers = this.parseImportSpecifiers();
- this.expectContextual("from");
- node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
- }
- this.semicolon();
- return this.finishNode(node, "ImportDeclaration")
-};
+ pp$1.parseImportSpecifiers = function() {
+ var nodes = [], first = true;
+ if (this.type === types.name) {
+ // import defaultObj, { x, y as z } from '...'
+ var node = this.startNode();
+ node.local = this.parseIdent();
+ this.checkLVal(node.local, BIND_LEXICAL);
+ nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
+ if (!this.eat(types.comma)) { return nodes }
+ }
+ if (this.type === types.star) {
+ var node$1 = this.startNode();
+ this.next();
+ this.expectContextual("as");
+ node$1.local = this.parseIdent();
+ this.checkLVal(node$1.local, BIND_LEXICAL);
+ nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
+ return nodes
+ }
+ this.expect(types.braceL);
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this.expect(types.comma);
+ if (this.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var node$2 = this.startNode();
+ node$2.imported = this.parseIdent(true);
+ if (this.eatContextual("as")) {
+ node$2.local = this.parseIdent();
+ } else {
+ this.checkUnreserved(node$2.imported);
+ node$2.local = node$2.imported;
+ }
+ this.checkLVal(node$2.local, BIND_LEXICAL);
+ nodes.push(this.finishNode(node$2, "ImportSpecifier"));
+ }
+ return nodes
+ };
+
+ // Set `ExpressionStatement#directive` property for directive prologues.
+ pp$1.adaptDirectivePrologue = function(statements) {
+ for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
+ statements[i].directive = statements[i].expression.raw.slice(1, -1);
+ }
+ };
+ pp$1.isDirectiveCandidate = function(statement) {
+ return (
+ statement.type === "ExpressionStatement" &&
+ statement.expression.type === "Literal" &&
+ typeof statement.expression.value === "string" &&
+ // Reject parenthesized strings.
+ (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
+ )
+ };
+
+ var pp$2 = Parser.prototype;
+
+ // Convert existing expression atom to assignable pattern
+ // if possible.
+
+ pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
+ if (this.options.ecmaVersion >= 6 && node) {
+ switch (node.type) {
+ case "Identifier":
+ if (this.inAsync && node.name === "await")
+ { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); }
+ break
-// Parses a comma-separated list of module imports.
+ case "ObjectPattern":
+ case "ArrayPattern":
+ case "RestElement":
+ break
+
+ case "ObjectExpression":
+ node.type = "ObjectPattern";
+ if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ for (var i = 0, list = node.properties; i < list.length; i += 1) {
+ var prop = list[i];
+
+ this.toAssignable(prop, isBinding);
+ // Early error:
+ // AssignmentRestProperty[Yield, Await] :
+ // `...` DestructuringAssignmentTarget[Yield, Await]
+ //
+ // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
+ if (
+ prop.type === "RestElement" &&
+ (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
+ ) {
+ this.raise(prop.argument.start, "Unexpected token");
+ }
+ }
+ break
+
+ case "Property":
+ // AssignmentProperty has type === "Property"
+ if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
+ this.toAssignable(node.value, isBinding);
+ break
+
+ case "ArrayExpression":
+ node.type = "ArrayPattern";
+ if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ this.toAssignableList(node.elements, isBinding);
+ break
+
+ case "SpreadElement":
+ node.type = "RestElement";
+ this.toAssignable(node.argument, isBinding);
+ if (node.argument.type === "AssignmentPattern")
+ { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
+ break
+
+ case "AssignmentExpression":
+ if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
+ node.type = "AssignmentPattern";
+ delete node.operator;
+ this.toAssignable(node.left, isBinding);
+ // falls through to AssignmentPattern
+
+ case "AssignmentPattern":
+ break
+
+ case "ParenthesizedExpression":
+ this.toAssignable(node.expression, isBinding, refDestructuringErrors);
+ break
+
+ case "MemberExpression":
+ if (!isBinding) { break }
+
+ default:
+ this.raise(node.start, "Assigning to rvalue");
+ }
+ } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
+ return node
+ };
+
+ // Convert list of expression atoms to binding list.
+
+ pp$2.toAssignableList = function(exprList, isBinding) {
+ var end = exprList.length;
+ for (var i = 0; i < end; i++) {
+ var elt = exprList[i];
+ if (elt) { this.toAssignable(elt, isBinding); }
+ }
+ if (end) {
+ var last = exprList[end - 1];
+ if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
+ { this.unexpected(last.argument.start); }
+ }
+ return exprList
+ };
-pp$1.parseImportSpecifiers = function() {
- var this$1 = this;
+ // Parses spread element.
- var nodes = [], first = true;
- if (this.type === types.name) {
- // import defaultObj, { x, y as z } from '...'
+ pp$2.parseSpread = function(refDestructuringErrors) {
var node = this.startNode();
- node.local = this.parseIdent();
- this.checkLVal(node.local, BIND_LEXICAL);
- nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
- if (!this.eat(types.comma)) { return nodes }
- }
- if (this.type === types.star) {
- var node$1 = this.startNode();
this.next();
- this.expectContextual("as");
- node$1.local = this.parseIdent();
- this.checkLVal(node$1.local, BIND_LEXICAL);
- nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
- return nodes
- }
- this.expect(types.braceL);
- while (!this.eat(types.braceR)) {
- if (!first) {
- this$1.expect(types.comma);
- if (this$1.afterTrailingComma(types.braceR)) { break }
- } else { first = false; }
-
- var node$2 = this$1.startNode();
- node$2.imported = this$1.parseIdent(true);
- if (this$1.eatContextual("as")) {
- node$2.local = this$1.parseIdent();
- } else {
- this$1.checkUnreserved(node$2.imported);
- node$2.local = node$2.imported;
+ node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
+ return this.finishNode(node, "SpreadElement")
+ };
+
+ pp$2.parseRestBinding = function() {
+ var node = this.startNode();
+ this.next();
+
+ // RestElement inside of a function parameter must be an identifier
+ if (this.options.ecmaVersion === 6 && this.type !== types.name)
+ { this.unexpected(); }
+
+ node.argument = this.parseBindingAtom();
+
+ return this.finishNode(node, "RestElement")
+ };
+
+ // Parses lvalue (assignable) atom.
+
+ pp$2.parseBindingAtom = function() {
+ if (this.options.ecmaVersion >= 6) {
+ switch (this.type) {
+ case types.bracketL:
+ var node = this.startNode();
+ this.next();
+ node.elements = this.parseBindingList(types.bracketR, true, true);
+ return this.finishNode(node, "ArrayPattern")
+
+ case types.braceL:
+ return this.parseObj(true)
+ }
}
- this$1.checkLVal(node$2.local, BIND_LEXICAL);
- nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
- }
- return nodes
-};
+ return this.parseIdent()
+ };
-// Set `ExpressionStatement#directive` property for directive prologues.
-pp$1.adaptDirectivePrologue = function(statements) {
- for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
- statements[i].directive = statements[i].expression.raw.slice(1, -1);
- }
-};
-pp$1.isDirectiveCandidate = function(statement) {
- return (
- statement.type === "ExpressionStatement" &&
- statement.expression.type === "Literal" &&
- typeof statement.expression.value === "string" &&
- // Reject parenthesized strings.
- (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
- )
-};
-
-var pp$2 = Parser.prototype;
-
-// Convert existing expression atom to assignable pattern
-// if possible.
-
-pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) {
- var this$1 = this;
-
- if (this.options.ecmaVersion >= 6 && node) {
- switch (node.type) {
+ pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
+ var elts = [], first = true;
+ while (!this.eat(close)) {
+ if (first) { first = false; }
+ else { this.expect(types.comma); }
+ if (allowEmpty && this.type === types.comma) {
+ elts.push(null);
+ } else if (allowTrailingComma && this.afterTrailingComma(close)) {
+ break
+ } else if (this.type === types.ellipsis) {
+ var rest = this.parseRestBinding();
+ this.parseBindingListItem(rest);
+ elts.push(rest);
+ if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
+ this.expect(close);
+ break
+ } else {
+ var elem = this.parseMaybeDefault(this.start, this.startLoc);
+ this.parseBindingListItem(elem);
+ elts.push(elem);
+ }
+ }
+ return elts
+ };
+
+ pp$2.parseBindingListItem = function(param) {
+ return param
+ };
+
+ // Parses assignment pattern around given atom if possible.
+
+ pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
+ left = left || this.parseBindingAtom();
+ if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
+ var node = this.startNodeAt(startPos, startLoc);
+ node.left = left;
+ node.right = this.parseMaybeAssign();
+ return this.finishNode(node, "AssignmentPattern")
+ };
+
+ // Verify that a node is an lval — something that can be assigned
+ // to.
+ // bindingType can be either:
+ // 'var' indicating that the lval creates a 'var' binding
+ // 'let' indicating that the lval creates a lexical ('let' or 'const') binding
+ // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
+
+ pp$2.checkLVal = function(expr, bindingType, checkClashes) {
+ if ( bindingType === void 0 ) bindingType = BIND_NONE;
+
+ switch (expr.type) {
case "Identifier":
- if (this.inAsync && node.name === "await")
- { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); }
+ if (bindingType === BIND_LEXICAL && expr.name === "let")
+ { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); }
+ if (this.strict && this.reservedWordsStrictBind.test(expr.name))
+ { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
+ if (checkClashes) {
+ if (has(checkClashes, expr.name))
+ { this.raiseRecoverable(expr.start, "Argument name clash"); }
+ checkClashes[expr.name] = true;
+ }
+ if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
break
- case "ObjectPattern":
- case "ArrayPattern":
- case "RestElement":
+ case "MemberExpression":
+ if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
break
- case "ObjectExpression":
- node.type = "ObjectPattern";
- if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
- for (var i = 0, list = node.properties; i < list.length; i += 1) {
- var prop = list[i];
-
- this$1.toAssignable(prop, isBinding);
- // Early error:
- // AssignmentRestProperty[Yield, Await] :
- // `...` DestructuringAssignmentTarget[Yield, Await]
- //
- // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
- if (
- prop.type === "RestElement" &&
- (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")
- ) {
- this$1.raise(prop.argument.start, "Unexpected token");
- }
- }
+ case "ObjectPattern":
+ for (var i = 0, list = expr.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this.checkLVal(prop, bindingType, checkClashes);
+ }
break
case "Property":
// AssignmentProperty has type === "Property"
- if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); }
- this.toAssignable(node.value, isBinding);
+ this.checkLVal(expr.value, bindingType, checkClashes);
break
- case "ArrayExpression":
- node.type = "ArrayPattern";
- if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
- this.toAssignableList(node.elements, isBinding);
- break
+ case "ArrayPattern":
+ for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
+ var elem = list$1[i$1];
- case "SpreadElement":
- node.type = "RestElement";
- this.toAssignable(node.argument, isBinding);
- if (node.argument.type === "AssignmentPattern")
- { this.raise(node.argument.start, "Rest elements cannot have a default value"); }
+ if (elem) { this.checkLVal(elem, bindingType, checkClashes); }
+ }
break
- case "AssignmentExpression":
- if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); }
- node.type = "AssignmentPattern";
- delete node.operator;
- this.toAssignable(node.left, isBinding);
- // falls through to AssignmentPattern
-
case "AssignmentPattern":
+ this.checkLVal(expr.left, bindingType, checkClashes);
break
- case "ParenthesizedExpression":
- this.toAssignable(node.expression, isBinding);
+ case "RestElement":
+ this.checkLVal(expr.argument, bindingType, checkClashes);
break
- case "MemberExpression":
- if (!isBinding) { break }
+ case "ParenthesizedExpression":
+ this.checkLVal(expr.expression, bindingType, checkClashes);
+ break
default:
- this.raise(node.start, "Assigning to rvalue");
+ this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
}
- } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); }
- return node
-};
+ };
-// Convert list of expression atoms to binding list.
+ // A recursive descent parser operates by defining functions for all
+
+ var pp$3 = Parser.prototype;
+
+ // Check if property name clashes with already added.
+ // Object/class getters and setters are not allowed to clash —
+ // either with each other or with an init property — and in
+ // strict mode, init properties are also not allowed to be repeated.
+
+ pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
+ if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
+ { return }
+ if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
+ { return }
+ var key = prop.key;
+ var name;
+ switch (key.type) {
+ case "Identifier": name = key.name; break
+ case "Literal": name = String(key.value); break
+ default: return
+ }
+ var kind = prop.kind;
+ if (this.options.ecmaVersion >= 6) {
+ if (name === "__proto__" && kind === "init") {
+ if (propHash.proto) {
+ if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; }
+ // Backwards-compat kludge. Can be removed in version 6.0
+ else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
+ }
+ propHash.proto = true;
+ }
+ return
+ }
+ name = "$" + name;
+ var other = propHash[name];
+ if (other) {
+ var redefinition;
+ if (kind === "init") {
+ redefinition = this.strict && other.init || other.get || other.set;
+ } else {
+ redefinition = other.init || other[kind];
+ }
+ if (redefinition)
+ { this.raiseRecoverable(key.start, "Redefinition of property"); }
+ } else {
+ other = propHash[name] = {
+ init: false,
+ get: false,
+ set: false
+ };
+ }
+ other[kind] = true;
+ };
-pp$2.toAssignableList = function(exprList, isBinding) {
- var this$1 = this;
+ // ### Expression parsing
+
+ // These nest, from the most general expression type at the top to
+ // 'atomic', nondivisible expression types at the bottom. Most of
+ // the functions will simply let the function(s) below them parse,
+ // and, *if* the syntactic construct they handle is present, wrap
+ // the AST node that the inner parser gave them in another node.
+
+ // Parse a full expression. The optional arguments are used to
+ // forbid the `in` operator (in for loops initalization expressions)
+ // and provide reference for storing '=' operator inside shorthand
+ // property assignment in contexts where both object expression
+ // and object pattern might appear (so it's possible to raise
+ // delayed syntax error at correct position).
+
+ pp$3.parseExpression = function(noIn, refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
+ if (this.type === types.comma) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.expressions = [expr];
+ while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); }
+ return this.finishNode(node, "SequenceExpression")
+ }
+ return expr
+ };
- var end = exprList.length;
- for (var i = 0; i < end; i++) {
- var elt = exprList[i];
- if (elt) { this$1.toAssignable(elt, isBinding); }
- }
- if (end) {
- var last = exprList[end - 1];
- if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
- { this.unexpected(last.argument.start); }
- }
- return exprList
-};
+ // Parse an assignment expression. This includes applications of
+ // operators like `+=`.
+
+ pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
+ if (this.isContextual("yield")) {
+ if (this.inGenerator) { return this.parseYield(noIn) }
+ // The tokenizer will assume an expression is allowed after
+ // `yield`, but this isn't that kind of yield
+ else { this.exprAllowed = false; }
+ }
+
+ var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldShorthandAssign = -1;
+ if (refDestructuringErrors) {
+ oldParenAssign = refDestructuringErrors.parenthesizedAssign;
+ oldTrailingComma = refDestructuringErrors.trailingComma;
+ oldShorthandAssign = refDestructuringErrors.shorthandAssign;
+ refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.shorthandAssign = -1;
+ } else {
+ refDestructuringErrors = new DestructuringErrors;
+ ownDestructuringErrors = true;
+ }
+
+ var startPos = this.start, startLoc = this.startLoc;
+ if (this.type === types.parenL || this.type === types.name)
+ { this.potentialArrowAt = this.start; }
+ var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
+ if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
+ if (this.type.isAssign) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.operator = this.value;
+ node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
+ if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); }
+ refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
+ this.checkLVal(left);
+ this.next();
+ node.right = this.parseMaybeAssign(noIn);
+ return this.finishNode(node, "AssignmentExpression")
+ } else {
+ if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
+ }
+ if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
+ if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
+ if (oldShorthandAssign > -1) { refDestructuringErrors.shorthandAssign = oldShorthandAssign; }
+ return left
+ };
+
+ // Parse a ternary conditional (`?:`) operator.
-// Parses spread element.
+ pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseExprOps(noIn, refDestructuringErrors);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ if (this.eat(types.question)) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.test = expr;
+ node.consequent = this.parseMaybeAssign();
+ this.expect(types.colon);
+ node.alternate = this.parseMaybeAssign(noIn);
+ return this.finishNode(node, "ConditionalExpression")
+ }
+ return expr
+ };
-pp$2.parseSpread = function(refDestructuringErrors) {
- var node = this.startNode();
- this.next();
- node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
- return this.finishNode(node, "SpreadElement")
-};
+ // Start the precedence parser.
-pp$2.parseRestBinding = function() {
- var node = this.startNode();
- this.next();
+ pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseMaybeUnary(refDestructuringErrors, false);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
+ };
- // RestElement inside of a function parameter must be an identifier
- if (this.options.ecmaVersion === 6 && this.type !== types.name)
- { this.unexpected(); }
+ // Parse binary operators with the operator precedence parsing
+ // algorithm. `left` is the left-hand side of the operator.
+ // `minPrec` provides context that allows the function to stop and
+ // defer further parser to one of its callers when it encounters an
+ // operator that has a lower precedence than the set it is parsing.
+
+ pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
+ var prec = this.type.binop;
+ if (prec != null && (!noIn || this.type !== types._in)) {
+ if (prec > minPrec) {
+ var logical = this.type === types.logicalOR || this.type === types.logicalAND;
+ var op = this.value;
+ this.next();
+ var startPos = this.start, startLoc = this.startLoc;
+ var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
+ var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
+ return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
+ }
+ }
+ return left
+ };
- node.argument = this.parseBindingAtom();
+ pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.left = left;
+ node.operator = op;
+ node.right = right;
+ return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
+ };
+
+ // Parse unary operators, both prefix and postfix.
+
+ pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
+ var startPos = this.start, startLoc = this.startLoc, expr;
+ if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
+ expr = this.parseAwait();
+ sawUnary = true;
+ } else if (this.type.prefix) {
+ var node = this.startNode(), update = this.type === types.incDec;
+ node.operator = this.value;
+ node.prefix = true;
+ this.next();
+ node.argument = this.parseMaybeUnary(null, true);
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ if (update) { this.checkLVal(node.argument); }
+ else if (this.strict && node.operator === "delete" &&
+ node.argument.type === "Identifier")
+ { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
+ else { sawUnary = true; }
+ expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
+ } else {
+ expr = this.parseExprSubscripts(refDestructuringErrors);
+ if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
+ while (this.type.postfix && !this.canInsertSemicolon()) {
+ var node$1 = this.startNodeAt(startPos, startLoc);
+ node$1.operator = this.value;
+ node$1.prefix = false;
+ node$1.argument = expr;
+ this.checkLVal(expr);
+ this.next();
+ expr = this.finishNode(node$1, "UpdateExpression");
+ }
+ }
+
+ if (!sawUnary && this.eat(types.starstar))
+ { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
+ else
+ { return expr }
+ };
+
+ // Parse call, dot, and `[]`-subscript expressions.
+
+ pp$3.parseExprSubscripts = function(refDestructuringErrors) {
+ var startPos = this.start, startLoc = this.startLoc;
+ var expr = this.parseExprAtom(refDestructuringErrors);
+ var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
+ if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr }
+ var result = this.parseSubscripts(expr, startPos, startLoc);
+ if (refDestructuringErrors && result.type === "MemberExpression") {
+ if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
+ if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
+ }
+ return result
+ };
+
+ pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
+ var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
+ this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
+ while (true) {
+ var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow);
+ if (element === base || element.type === "ArrowFunctionExpression") { return element }
+ base = element;
+ }
+ };
+
+ pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow) {
+ var computed = this.eat(types.bracketL);
+ if (computed || this.eat(types.dot)) {
+ var node = this.startNodeAt(startPos, startLoc);
+ node.object = base;
+ node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never");
+ node.computed = !!computed;
+ if (computed) { this.expect(types.bracketR); }
+ base = this.finishNode(node, "MemberExpression");
+ } else if (!noCalls && this.eat(types.parenL)) {
+ var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ this.awaitIdentPos = 0;
+ var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
+ if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
+ this.checkPatternErrors(refDestructuringErrors, false);
+ this.checkYieldAwaitInDefaultParams();
+ if (this.awaitIdentPos > 0)
+ { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); }
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.awaitIdentPos = oldAwaitIdentPos;
+ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true)
+ }
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ this.yieldPos = oldYieldPos || this.yieldPos;
+ this.awaitPos = oldAwaitPos || this.awaitPos;
+ this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
+ var node$1 = this.startNodeAt(startPos, startLoc);
+ node$1.callee = base;
+ node$1.arguments = exprList;
+ base = this.finishNode(node$1, "CallExpression");
+ } else if (this.type === types.backQuote) {
+ var node$2 = this.startNodeAt(startPos, startLoc);
+ node$2.tag = base;
+ node$2.quasi = this.parseTemplate({isTagged: true});
+ base = this.finishNode(node$2, "TaggedTemplateExpression");
+ }
+ return base
+ };
- return this.finishNode(node, "RestElement")
-};
+ // Parse an atomic expression — either a single token that is an
+ // expression, an expression started by a keyword like `function` or
+ // `new`, or an expression wrapped in punctuation like `()`, `[]`,
+ // or `{}`.
-// Parses lvalue (assignable) atom.
+ pp$3.parseExprAtom = function(refDestructuringErrors) {
+ // If a division operator appears in an expression position, the
+ // tokenizer got confused, and we force it to read a regexp instead.
+ if (this.type === types.slash) { this.readRegexp(); }
-pp$2.parseBindingAtom = function() {
- if (this.options.ecmaVersion >= 6) {
+ var node, canBeArrow = this.potentialArrowAt === this.start;
switch (this.type) {
+ case types._super:
+ if (!this.allowSuper)
+ { this.raise(this.start, "'super' keyword outside a method"); }
+ node = this.startNode();
+ this.next();
+ if (this.type === types.parenL && !this.allowDirectSuper)
+ { this.raise(node.start, "super() call outside constructor of a subclass"); }
+ // The `super` keyword can appear at below:
+ // SuperProperty:
+ // super [ Expression ]
+ // super . IdentifierName
+ // SuperCall:
+ // super ( Arguments )
+ if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
+ { this.unexpected(); }
+ return this.finishNode(node, "Super")
+
+ case types._this:
+ node = this.startNode();
+ this.next();
+ return this.finishNode(node, "ThisExpression")
+
+ case types.name:
+ var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
+ var id = this.parseIdent(false);
+ if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
+ { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
+ if (canBeArrow && !this.canInsertSemicolon()) {
+ if (this.eat(types.arrow))
+ { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
+ if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
+ id = this.parseIdent(false);
+ if (this.canInsertSemicolon() || !this.eat(types.arrow))
+ { this.unexpected(); }
+ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
+ }
+ }
+ return id
+
+ case types.regexp:
+ var value = this.value;
+ node = this.parseLiteral(value.value);
+ node.regex = {pattern: value.pattern, flags: value.flags};
+ return node
+
+ case types.num: case types.string:
+ return this.parseLiteral(this.value)
+
+ case types._null: case types._true: case types._false:
+ node = this.startNode();
+ node.value = this.type === types._null ? null : this.type === types._true;
+ node.raw = this.type.keyword;
+ this.next();
+ return this.finishNode(node, "Literal")
+
+ case types.parenL:
+ var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
+ if (refDestructuringErrors) {
+ if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
+ { refDestructuringErrors.parenthesizedAssign = start; }
+ if (refDestructuringErrors.parenthesizedBind < 0)
+ { refDestructuringErrors.parenthesizedBind = start; }
+ }
+ return expr
+
case types.bracketL:
- var node = this.startNode();
+ node = this.startNode();
this.next();
- node.elements = this.parseBindingList(types.bracketR, true, true);
- return this.finishNode(node, "ArrayPattern")
+ node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
+ return this.finishNode(node, "ArrayExpression")
case types.braceL:
- return this.parseObj(true)
- }
- }
- return this.parseIdent()
-};
-
-pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
- var this$1 = this;
-
- var elts = [], first = true;
- while (!this.eat(close)) {
- if (first) { first = false; }
- else { this$1.expect(types.comma); }
- if (allowEmpty && this$1.type === types.comma) {
- elts.push(null);
- } else if (allowTrailingComma && this$1.afterTrailingComma(close)) {
- break
- } else if (this$1.type === types.ellipsis) {
- var rest = this$1.parseRestBinding();
- this$1.parseBindingListItem(rest);
- elts.push(rest);
- if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
- this$1.expect(close);
- break
- } else {
- var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc);
- this$1.parseBindingListItem(elem);
- elts.push(elem);
- }
- }
- return elts
-};
-
-pp$2.parseBindingListItem = function(param) {
- return param
-};
-
-// Parses assignment pattern around given atom if possible.
-
-pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
- left = left || this.parseBindingAtom();
- if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
- var node = this.startNodeAt(startPos, startLoc);
- node.left = left;
- node.right = this.parseMaybeAssign();
- return this.finishNode(node, "AssignmentPattern")
-};
-
-// Verify that a node is an lval — something that can be assigned
-// to.
-// bindingType can be either:
-// 'var' indicating that the lval creates a 'var' binding
-// 'let' indicating that the lval creates a lexical ('let' or 'const') binding
-// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references
-
-pp$2.checkLVal = function(expr, bindingType, checkClashes) {
- var this$1 = this;
- if ( bindingType === void 0 ) bindingType = BIND_NONE;
-
- switch (expr.type) {
- case "Identifier":
- if (this.strict && this.reservedWordsStrictBind.test(expr.name))
- { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
- if (checkClashes) {
- if (has(checkClashes, expr.name))
- { this.raiseRecoverable(expr.start, "Argument name clash"); }
- checkClashes[expr.name] = true;
- }
- if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); }
- break
-
- case "MemberExpression":
- if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); }
- break
-
- case "ObjectPattern":
- for (var i = 0, list = expr.properties; i < list.length; i += 1)
- {
- var prop = list[i];
+ return this.parseObj(false, refDestructuringErrors)
- this$1.checkLVal(prop, bindingType, checkClashes);
- }
- break
+ case types._function:
+ node = this.startNode();
+ this.next();
+ return this.parseFunction(node, 0)
+
+ case types._class:
+ return this.parseClass(this.startNode(), false)
- case "Property":
- // AssignmentProperty has type === "Property"
- this.checkLVal(expr.value, bindingType, checkClashes);
- break
+ case types._new:
+ return this.parseNew()
- case "ArrayPattern":
- for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
- var elem = list$1[i$1];
+ case types.backQuote:
+ return this.parseTemplate()
- if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); }
+ case types._import:
+ if (this.options.ecmaVersion >= 11) {
+ return this.parseExprImport()
+ } else {
+ return this.unexpected()
+ }
+
+ default:
+ this.unexpected();
}
- break
+ };
- case "AssignmentPattern":
- this.checkLVal(expr.left, bindingType, checkClashes);
- break
+ pp$3.parseExprImport = function() {
+ var node = this.startNode();
+ this.next(); // skip `import`
+ switch (this.type) {
+ case types.parenL:
+ return this.parseDynamicImport(node)
+ default:
+ this.unexpected();
+ }
+ };
- case "RestElement":
- this.checkLVal(expr.argument, bindingType, checkClashes);
- break
+ pp$3.parseDynamicImport = function(node) {
+ this.next(); // skip `(`
- case "ParenthesizedExpression":
- this.checkLVal(expr.expression, bindingType, checkClashes);
- break
+ // Parse node.source.
+ node.source = this.parseMaybeAssign();
- default:
- this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
- }
-};
-
-// A recursive descent parser operates by defining functions for all
-// syntactic elements, and recursively calling those, each function
-// advancing the input stream and returning an AST node. Precedence
-// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
-// instead of `(!x)[1]` is handled by the fact that the parser
-// function that parses unary prefix operators is called first, and
-// in turn calls the function that parses `[]` subscripts — that
-// way, it'll receive the node for `x[1]` already parsed, and wraps
-// *that* in the unary operator node.
-//
-// Acorn uses an [operator precedence parser][opp] to handle binary
-// operator precedence, because it is much more compact than using
-// the technique outlined above, which uses different, nesting
-// functions to specify precedence, for all of the ten binary
-// precedence levels that JavaScript defines.
-//
-// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
-
-var pp$3 = Parser.prototype;
-
-// Check if property name clashes with already added.
-// Object/class getters and setters are not allowed to clash —
-// either with each other or with an init property — and in
-// strict mode, init properties are also not allowed to be repeated.
-
-pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) {
- if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
- { return }
- if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
- { return }
- var key = prop.key;
- var name;
- switch (key.type) {
- case "Identifier": name = key.name; break
- case "Literal": name = String(key.value); break
- default: return
- }
- var kind = prop.kind;
- if (this.options.ecmaVersion >= 6) {
- if (name === "__proto__" && kind === "init") {
- if (propHash.proto) {
- if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; }
- // Backwards-compat kludge. Can be removed in version 6.0
- else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
+ // Verify ending.
+ if (!this.eat(types.parenR)) {
+ var errorPos = this.start;
+ if (this.eat(types.comma) && this.eat(types.parenR)) {
+ this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
+ } else {
+ this.unexpected(errorPos);
}
- propHash.proto = true;
}
- return
- }
- name = "$" + name;
- var other = propHash[name];
- if (other) {
- var redefinition;
- if (kind === "init") {
- redefinition = this.strict && other.init || other.get || other.set;
- } else {
- redefinition = other.init || other[kind];
- }
- if (redefinition)
- { this.raiseRecoverable(key.start, "Redefinition of property"); }
- } else {
- other = propHash[name] = {
- init: false,
- get: false,
- set: false
- };
- }
- other[kind] = true;
-};
-
-// ### Expression parsing
-
-// These nest, from the most general expression type at the top to
-// 'atomic', nondivisible expression types at the bottom. Most of
-// the functions will simply let the function(s) below them parse,
-// and, *if* the syntactic construct they handle is present, wrap
-// the AST node that the inner parser gave them in another node.
-
-// Parse a full expression. The optional arguments are used to
-// forbid the `in` operator (in for loops initalization expressions)
-// and provide reference for storing '=' operator inside shorthand
-// property assignment in contexts where both object expression
-// and object pattern might appear (so it's possible to raise
-// delayed syntax error at correct position).
-
-pp$3.parseExpression = function(noIn, refDestructuringErrors) {
- var this$1 = this;
-
- var startPos = this.start, startLoc = this.startLoc;
- var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
- if (this.type === types.comma) {
- var node = this.startNodeAt(startPos, startLoc);
- node.expressions = [expr];
- while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); }
- return this.finishNode(node, "SequenceExpression")
- }
- return expr
-};
-
-// Parse an assignment expression. This includes applications of
-// operators like `+=`.
-
-pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
- if (this.isContextual("yield")) {
- if (this.inGenerator) { return this.parseYield() }
- // The tokenizer will assume an expression is allowed after
- // `yield`, but this isn't that kind of yield
- else { this.exprAllowed = false; }
- }
- var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
- if (refDestructuringErrors) {
- oldParenAssign = refDestructuringErrors.parenthesizedAssign;
- oldTrailingComma = refDestructuringErrors.trailingComma;
- refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
- } else {
- refDestructuringErrors = new DestructuringErrors;
- ownDestructuringErrors = true;
- }
+ return this.finishNode(node, "ImportExpression")
+ };
- var startPos = this.start, startLoc = this.startLoc;
- if (this.type === types.parenL || this.type === types.name)
- { this.potentialArrowAt = this.start; }
- var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
- if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
- if (this.type.isAssign) {
- var node = this.startNodeAt(startPos, startLoc);
- node.operator = this.value;
- node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left;
- if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); }
- refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
- this.checkLVal(left);
+ pp$3.parseLiteral = function(value) {
+ var node = this.startNode();
+ node.value = value;
+ node.raw = this.input.slice(this.start, this.end);
+ if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); }
this.next();
- node.right = this.parseMaybeAssign(noIn);
- return this.finishNode(node, "AssignmentExpression")
- } else {
- if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
- }
- if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
- if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
- return left
-};
-
-// Parse a ternary conditional (`?:`) operator.
-
-pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
- var startPos = this.start, startLoc = this.startLoc;
- var expr = this.parseExprOps(noIn, refDestructuringErrors);
- if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
- if (this.eat(types.question)) {
- var node = this.startNodeAt(startPos, startLoc);
- node.test = expr;
- node.consequent = this.parseMaybeAssign();
- this.expect(types.colon);
- node.alternate = this.parseMaybeAssign(noIn);
- return this.finishNode(node, "ConditionalExpression")
- }
- return expr
-};
-
-// Start the precedence parser.
-
-pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
- var startPos = this.start, startLoc = this.startLoc;
- var expr = this.parseMaybeUnary(refDestructuringErrors, false);
- if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
- return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
-};
-
-// Parse binary operators with the operator precedence parsing
-// algorithm. `left` is the left-hand side of the operator.
-// `minPrec` provides context that allows the function to stop and
-// defer further parser to one of its callers when it encounters an
-// operator that has a lower precedence than the set it is parsing.
-
-pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
- var prec = this.type.binop;
- if (prec != null && (!noIn || this.type !== types._in)) {
- if (prec > minPrec) {
- var logical = this.type === types.logicalOR || this.type === types.logicalAND;
- var op = this.value;
+ return this.finishNode(node, "Literal")
+ };
+
+ pp$3.parseParenExpression = function() {
+ this.expect(types.parenL);
+ var val = this.parseExpression();
+ this.expect(types.parenR);
+ return val
+ };
+
+ pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
+ var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
+ if (this.options.ecmaVersion >= 6) {
this.next();
- var startPos = this.start, startLoc = this.startLoc;
- var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
- var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
- return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
+
+ var innerStartPos = this.start, innerStartLoc = this.startLoc;
+ var exprList = [], first = true, lastIsComma = false;
+ var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ // Do not save awaitIdentPos to allow checking awaits nested in parameters
+ while (this.type !== types.parenR) {
+ first ? first = false : this.expect(types.comma);
+ if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) {
+ lastIsComma = true;
+ break
+ } else if (this.type === types.ellipsis) {
+ spreadStart = this.start;
+ exprList.push(this.parseParenItem(this.parseRestBinding()));
+ if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); }
+ break
+ } else {
+ exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
+ }
+ }
+ var innerEndPos = this.start, innerEndLoc = this.startLoc;
+ this.expect(types.parenR);
+
+ if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
+ this.checkPatternErrors(refDestructuringErrors, false);
+ this.checkYieldAwaitInDefaultParams();
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ return this.parseParenArrowList(startPos, startLoc, exprList)
+ }
+
+ if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
+ if (spreadStart) { this.unexpected(spreadStart); }
+ this.checkExpressionErrors(refDestructuringErrors, true);
+ this.yieldPos = oldYieldPos || this.yieldPos;
+ this.awaitPos = oldAwaitPos || this.awaitPos;
+
+ if (exprList.length > 1) {
+ val = this.startNodeAt(innerStartPos, innerStartLoc);
+ val.expressions = exprList;
+ this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
+ } else {
+ val = exprList[0];
+ }
+ } else {
+ val = this.parseParenExpression();
}
- }
- return left
-};
-
-pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
- var node = this.startNodeAt(startPos, startLoc);
- node.left = left;
- node.operator = op;
- node.right = right;
- return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
-};
-
-// Parse unary operators, both prefix and postfix.
-
-pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
- var this$1 = this;
-
- var startPos = this.start, startLoc = this.startLoc, expr;
- if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
- expr = this.parseAwait();
- sawUnary = true;
- } else if (this.type.prefix) {
- var node = this.startNode(), update = this.type === types.incDec;
- node.operator = this.value;
- node.prefix = true;
- this.next();
- node.argument = this.parseMaybeUnary(null, true);
- this.checkExpressionErrors(refDestructuringErrors, true);
- if (update) { this.checkLVal(node.argument); }
- else if (this.strict && node.operator === "delete" &&
- node.argument.type === "Identifier")
- { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
- else { sawUnary = true; }
- expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
- } else {
- expr = this.parseExprSubscripts(refDestructuringErrors);
- if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
- while (this.type.postfix && !this.canInsertSemicolon()) {
- var node$1 = this$1.startNodeAt(startPos, startLoc);
- node$1.operator = this$1.value;
- node$1.prefix = false;
- node$1.argument = expr;
- this$1.checkLVal(expr);
- this$1.next();
- expr = this$1.finishNode(node$1, "UpdateExpression");
+
+ if (this.options.preserveParens) {
+ var par = this.startNodeAt(startPos, startLoc);
+ par.expression = val;
+ return this.finishNode(par, "ParenthesizedExpression")
+ } else {
+ return val
}
- }
+ };
- if (!sawUnary && this.eat(types.starstar))
- { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
- else
- { return expr }
-};
-
-// Parse call, dot, and `[]`-subscript expressions.
-
-pp$3.parseExprSubscripts = function(refDestructuringErrors) {
- var startPos = this.start, startLoc = this.startLoc;
- var expr = this.parseExprAtom(refDestructuringErrors);
- var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
- if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr }
- var result = this.parseSubscripts(expr, startPos, startLoc);
- if (refDestructuringErrors && result.type === "MemberExpression") {
- if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
- if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
- }
- return result
-};
+ pp$3.parseParenItem = function(item) {
+ return item
+ };
-pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
- var this$1 = this;
+ pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
+ return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
+ };
- var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
- this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
- for (var computed = (void 0);;) {
- if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) {
- var node = this$1.startNodeAt(startPos, startLoc);
- node.object = base;
- node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true);
- node.computed = !!computed;
- if (computed) { this$1.expect(types.bracketR); }
- base = this$1.finishNode(node, "MemberExpression");
- } else if (!noCalls && this$1.eat(types.parenL)) {
- var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos;
- this$1.yieldPos = 0;
- this$1.awaitPos = 0;
- var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors);
- if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) {
- this$1.checkPatternErrors(refDestructuringErrors, false);
- this$1.checkYieldAwaitInDefaultParams();
- this$1.yieldPos = oldYieldPos;
- this$1.awaitPos = oldAwaitPos;
- return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true)
+ // New's precedence is slightly tricky. It must allow its argument to
+ // be a `[]` or dot subscript expression, but not a call — at least,
+ // not without wrapping it in parentheses. Thus, it uses the noCalls
+ // argument to parseSubscripts to prevent it from consuming the
+ // argument list.
+
+ var empty$1 = [];
+
+ pp$3.parseNew = function() {
+ var node = this.startNode();
+ var meta = this.parseIdent(true);
+ if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
+ node.meta = meta;
+ var containsEsc = this.containsEsc;
+ node.property = this.parseIdent(true);
+ if (node.property.name !== "target" || containsEsc)
+ { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
+ if (!this.inNonArrowFunction())
+ { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
+ return this.finishNode(node, "MetaProperty")
+ }
+ var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import;
+ node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
+ if (isImport && node.callee.type === "ImportExpression") {
+ this.raise(startPos, "Cannot use new with import()");
+ }
+ if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
+ else { node.arguments = empty$1; }
+ return this.finishNode(node, "NewExpression")
+ };
+
+ // Parse template expression.
+
+ pp$3.parseTemplateElement = function(ref) {
+ var isTagged = ref.isTagged;
+
+ var elem = this.startNode();
+ if (this.type === types.invalidTemplate) {
+ if (!isTagged) {
+ this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
}
- this$1.checkExpressionErrors(refDestructuringErrors, true);
- this$1.yieldPos = oldYieldPos || this$1.yieldPos;
- this$1.awaitPos = oldAwaitPos || this$1.awaitPos;
- var node$1 = this$1.startNodeAt(startPos, startLoc);
- node$1.callee = base;
- node$1.arguments = exprList;
- base = this$1.finishNode(node$1, "CallExpression");
- } else if (this$1.type === types.backQuote) {
- var node$2 = this$1.startNodeAt(startPos, startLoc);
- node$2.tag = base;
- node$2.quasi = this$1.parseTemplate({isTagged: true});
- base = this$1.finishNode(node$2, "TaggedTemplateExpression");
+ elem.value = {
+ raw: this.value,
+ cooked: null
+ };
} else {
- return base
+ elem.value = {
+ raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
+ cooked: this.value
+ };
}
- }
-};
-
-// Parse an atomic expression — either a single token that is an
-// expression, an expression started by a keyword like `function` or
-// `new`, or an expression wrapped in punctuation like `()`, `[]`,
-// or `{}`.
-
-pp$3.parseExprAtom = function(refDestructuringErrors) {
- var node, canBeArrow = this.potentialArrowAt === this.start;
- switch (this.type) {
- case types._super:
- if (!this.inFunction)
- { this.raise(this.start, "'super' outside of function or class"); }
- node = this.startNode();
this.next();
- // The `super` keyword can appear at below:
- // SuperProperty:
- // super [ Expression ]
- // super . IdentifierName
- // SuperCall:
- // super Arguments
- if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
- { this.unexpected(); }
- return this.finishNode(node, "Super")
+ elem.tail = this.type === types.backQuote;
+ return this.finishNode(elem, "TemplateElement")
+ };
+
+ pp$3.parseTemplate = function(ref) {
+ if ( ref === void 0 ) ref = {};
+ var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
- case types._this:
- node = this.startNode();
+ var node = this.startNode();
this.next();
- return this.finishNode(node, "ThisExpression")
-
- case types.name:
- var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
- var id = this.parseIdent(this.type !== types.name);
- if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
- { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) }
- if (canBeArrow && !this.canInsertSemicolon()) {
- if (this.eat(types.arrow))
- { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
- if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) {
- id = this.parseIdent();
- if (this.canInsertSemicolon() || !this.eat(types.arrow))
- { this.unexpected(); }
- return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
- }
+ node.expressions = [];
+ var curElt = this.parseTemplateElement({isTagged: isTagged});
+ node.quasis = [curElt];
+ while (!curElt.tail) {
+ if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); }
+ this.expect(types.dollarBraceL);
+ node.expressions.push(this.parseExpression());
+ this.expect(types.braceR);
+ node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged}));
}
- return id
+ this.next();
+ return this.finishNode(node, "TemplateLiteral")
+ };
- case types.regexp:
- var value = this.value;
- node = this.parseLiteral(value.value);
- node.regex = {pattern: value.pattern, flags: value.flags};
- return node
+ pp$3.isAsyncProp = function(prop) {
+ return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
+ (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) &&
+ !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
+ };
- case types.num: case types.string:
- return this.parseLiteral(this.value)
+ // Parse an object literal or binding pattern.
- case types._null: case types._true: case types._false:
- node = this.startNode();
- node.value = this.type === types._null ? null : this.type === types._true;
- node.raw = this.type.keyword;
+ pp$3.parseObj = function(isPattern, refDestructuringErrors) {
+ var node = this.startNode(), first = true, propHash = {};
+ node.properties = [];
this.next();
- return this.finishNode(node, "Literal")
+ while (!this.eat(types.braceR)) {
+ if (!first) {
+ this.expect(types.comma);
+ if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
+ } else { first = false; }
+
+ var prop = this.parseProperty(isPattern, refDestructuringErrors);
+ if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); }
+ node.properties.push(prop);
+ }
+ return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
+ };
- case types.parenL:
- var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
- if (refDestructuringErrors) {
- if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
- { refDestructuringErrors.parenthesizedAssign = start; }
- if (refDestructuringErrors.parenthesizedBind < 0)
- { refDestructuringErrors.parenthesizedBind = start; }
+ pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
+ var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
+ if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
+ if (isPattern) {
+ prop.argument = this.parseIdent(false);
+ if (this.type === types.comma) {
+ this.raise(this.start, "Comma is not permitted after the rest element");
+ }
+ return this.finishNode(prop, "RestElement")
+ }
+ // To disallow parenthesized identifier via `this.toAssignable()`.
+ if (this.type === types.parenL && refDestructuringErrors) {
+ if (refDestructuringErrors.parenthesizedAssign < 0) {
+ refDestructuringErrors.parenthesizedAssign = this.start;
+ }
+ if (refDestructuringErrors.parenthesizedBind < 0) {
+ refDestructuringErrors.parenthesizedBind = this.start;
+ }
+ }
+ // Parse argument.
+ prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
+ // To disallow trailing comma via `this.toAssignable()`.
+ if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
+ refDestructuringErrors.trailingComma = this.start;
+ }
+ // Finish
+ return this.finishNode(prop, "SpreadElement")
}
- return expr
+ if (this.options.ecmaVersion >= 6) {
+ prop.method = false;
+ prop.shorthand = false;
+ if (isPattern || refDestructuringErrors) {
+ startPos = this.start;
+ startLoc = this.startLoc;
+ }
+ if (!isPattern)
+ { isGenerator = this.eat(types.star); }
+ }
+ var containsEsc = this.containsEsc;
+ this.parsePropertyName(prop);
+ if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
+ this.parsePropertyName(prop, refDestructuringErrors);
+ } else {
+ isAsync = false;
+ }
+ this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
+ return this.finishNode(prop, "Property")
+ };
- case types.bracketL:
- node = this.startNode();
- this.next();
- node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
- return this.finishNode(node, "ArrayExpression")
+ pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
+ if ((isGenerator || isAsync) && this.type === types.colon)
+ { this.unexpected(); }
- case types.braceL:
- return this.parseObj(false, refDestructuringErrors)
+ if (this.eat(types.colon)) {
+ prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
+ prop.kind = "init";
+ } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
+ if (isPattern) { this.unexpected(); }
+ prop.kind = "init";
+ prop.method = true;
+ prop.value = this.parseMethod(isGenerator, isAsync);
+ } else if (!isPattern && !containsEsc &&
+ this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
+ (prop.key.name === "get" || prop.key.name === "set") &&
+ (this.type !== types.comma && this.type !== types.braceR)) {
+ if (isGenerator || isAsync) { this.unexpected(); }
+ prop.kind = prop.key.name;
+ this.parsePropertyName(prop);
+ prop.value = this.parseMethod(false);
+ var paramCount = prop.kind === "get" ? 0 : 1;
+ if (prop.value.params.length !== paramCount) {
+ var start = prop.value.start;
+ if (prop.kind === "get")
+ { this.raiseRecoverable(start, "getter should have no params"); }
+ else
+ { this.raiseRecoverable(start, "setter should have exactly one param"); }
+ } else {
+ if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
+ { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
+ }
+ } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
+ if (isGenerator || isAsync) { this.unexpected(); }
+ this.checkUnreserved(prop.key);
+ if (prop.key.name === "await" && !this.awaitIdentPos)
+ { this.awaitIdentPos = startPos; }
+ prop.kind = "init";
+ if (isPattern) {
+ prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
+ } else if (this.type === types.eq && refDestructuringErrors) {
+ if (refDestructuringErrors.shorthandAssign < 0)
+ { refDestructuringErrors.shorthandAssign = this.start; }
+ prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
+ } else {
+ prop.value = prop.key;
+ }
+ prop.shorthand = true;
+ } else { this.unexpected(); }
+ };
- case types._function:
- node = this.startNode();
- this.next();
- return this.parseFunction(node, 0)
+ pp$3.parsePropertyName = function(prop) {
+ if (this.options.ecmaVersion >= 6) {
+ if (this.eat(types.bracketL)) {
+ prop.computed = true;
+ prop.key = this.parseMaybeAssign();
+ this.expect(types.bracketR);
+ return prop.key
+ } else {
+ prop.computed = false;
+ }
+ }
+ return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never")
+ };
+
+ // Initialize empty function node.
- case types._class:
- return this.parseClass(this.startNode(), false)
+ pp$3.initFunction = function(node) {
+ node.id = null;
+ if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
+ if (this.options.ecmaVersion >= 8) { node.async = false; }
+ };
- case types._new:
- return this.parseNew()
+ // Parse object or class method.
- case types.backQuote:
- return this.parseTemplate()
+ pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) {
+ var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
- default:
- this.unexpected();
- }
-};
-
-pp$3.parseLiteral = function(value) {
- var node = this.startNode();
- node.value = value;
- node.raw = this.input.slice(this.start, this.end);
- this.next();
- return this.finishNode(node, "Literal")
-};
-
-pp$3.parseParenExpression = function() {
- this.expect(types.parenL);
- var val = this.parseExpression();
- this.expect(types.parenR);
- return val
-};
-
-pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
- var this$1 = this;
-
- var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
- if (this.options.ecmaVersion >= 6) {
- this.next();
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 6)
+ { node.generator = isGenerator; }
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
- var innerStartPos = this.start, innerStartLoc = this.startLoc;
- var exprList = [], first = true, lastIsComma = false;
- var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart;
this.yieldPos = 0;
this.awaitPos = 0;
- while (this.type !== types.parenR) {
- first ? first = false : this$1.expect(types.comma);
- if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) {
- lastIsComma = true;
- break
- } else if (this$1.type === types.ellipsis) {
- spreadStart = this$1.start;
- exprList.push(this$1.parseParenItem(this$1.parseRestBinding()));
- if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
- break
+ this.awaitIdentPos = 0;
+ this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0));
+
+ this.expect(types.parenL);
+ node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
+ this.checkYieldAwaitInDefaultParams();
+ this.parseFunctionBody(node, false, true);
+
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.awaitIdentPos = oldAwaitIdentPos;
+ return this.finishNode(node, "FunctionExpression")
+ };
+
+ // Parse arrow function expression with given parameters.
+
+ pp$3.parseArrowExpression = function(node, params, isAsync) {
+ var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
+
+ this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
+
+ this.yieldPos = 0;
+ this.awaitPos = 0;
+ this.awaitIdentPos = 0;
+
+ node.params = this.toAssignableList(params, true);
+ this.parseFunctionBody(node, true, false);
+
+ this.yieldPos = oldYieldPos;
+ this.awaitPos = oldAwaitPos;
+ this.awaitIdentPos = oldAwaitIdentPos;
+ return this.finishNode(node, "ArrowFunctionExpression")
+ };
+
+ // Parse function body and check parameters.
+
+ pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) {
+ var isExpression = isArrowFunction && this.type !== types.braceL;
+ var oldStrict = this.strict, useStrict = false;
+
+ if (isExpression) {
+ node.body = this.parseMaybeAssign();
+ node.expression = true;
+ this.checkParams(node, false);
+ } else {
+ var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
+ if (!oldStrict || nonSimple) {
+ useStrict = this.strictDirective(this.end);
+ // If this is a strict mode function, verify that argument names
+ // are not repeated, and it does not try to bind the words `eval`
+ // or `arguments`.
+ if (useStrict && nonSimple)
+ { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
+ }
+ // Start a new scope with regard to labels and the `inFunction`
+ // flag (restore them to their old value afterwards).
+ var oldLabels = this.labels;
+ this.labels = [];
+ if (useStrict) { this.strict = true; }
+
+ // Add the params to varDeclaredNames to ensure that an error is thrown
+ // if a let/const declaration in the function clashes with one of the params.
+ this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
+ node.body = this.parseBlock(false);
+ node.expression = false;
+ this.adaptDirectivePrologue(node.body.body);
+ this.labels = oldLabels;
+ }
+ this.exitScope();
+
+ // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
+ if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
+ this.strict = oldStrict;
+ };
+
+ pp$3.isSimpleParamList = function(params) {
+ for (var i = 0, list = params; i < list.length; i += 1)
+ {
+ var param = list[i];
+
+ if (param.type !== "Identifier") { return false
+ } }
+ return true
+ };
+
+ // Checks function params for various disallowed patterns such as using "eval"
+ // or "arguments" and duplicate parameters.
+
+ pp$3.checkParams = function(node, allowDuplicates) {
+ var nameHash = {};
+ for (var i = 0, list = node.params; i < list.length; i += 1)
+ {
+ var param = list[i];
+
+ this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
+ }
+ };
+
+ // Parses a comma-separated list of expressions, and returns them as
+ // an array. `close` is the token type that ends the list, and
+ // `allowEmpty` can be turned on to allow subsequent commas with
+ // nothing in between them to be parsed as `null` (which is needed
+ // for array literals).
+
+ pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
+ var elts = [], first = true;
+ while (!this.eat(close)) {
+ if (!first) {
+ this.expect(types.comma);
+ if (allowTrailingComma && this.afterTrailingComma(close)) { break }
+ } else { first = false; }
+
+ var elt = (void 0);
+ if (allowEmpty && this.type === types.comma)
+ { elt = null; }
+ else if (this.type === types.ellipsis) {
+ elt = this.parseSpread(refDestructuringErrors);
+ if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0)
+ { refDestructuringErrors.trailingComma = this.start; }
} else {
- exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem));
+ elt = this.parseMaybeAssign(false, refDestructuringErrors);
}
+ elts.push(elt);
}
- var innerEndPos = this.start, innerEndLoc = this.startLoc;
- this.expect(types.parenR);
+ return elts
+ };
- if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
- this.checkPatternErrors(refDestructuringErrors, false);
- this.checkYieldAwaitInDefaultParams();
- this.yieldPos = oldYieldPos;
- this.awaitPos = oldAwaitPos;
- return this.parseParenArrowList(startPos, startLoc, exprList)
+ pp$3.checkUnreserved = function(ref) {
+ var start = ref.start;
+ var end = ref.end;
+ var name = ref.name;
+
+ if (this.inGenerator && name === "yield")
+ { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); }
+ if (this.inAsync && name === "await")
+ { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); }
+ if (this.keywords.test(name))
+ { this.raise(start, ("Unexpected keyword '" + name + "'")); }
+ if (this.options.ecmaVersion < 6 &&
+ this.input.slice(start, end).indexOf("\\") !== -1) { return }
+ var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
+ if (re.test(name)) {
+ if (!this.inAsync && name === "await")
+ { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); }
+ this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
}
+ };
- if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
- if (spreadStart) { this.unexpected(spreadStart); }
- this.checkExpressionErrors(refDestructuringErrors, true);
- this.yieldPos = oldYieldPos || this.yieldPos;
- this.awaitPos = oldAwaitPos || this.awaitPos;
+ // Parse the next token as an identifier. If `liberal` is true (used
+ // when parsing properties), it will also convert keywords into
+ // identifiers.
- if (exprList.length > 1) {
- val = this.startNodeAt(innerStartPos, innerStartLoc);
- val.expressions = exprList;
- this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
+ pp$3.parseIdent = function(liberal, isBinding) {
+ var node = this.startNode();
+ if (this.type === types.name) {
+ node.name = this.value;
+ } else if (this.type.keyword) {
+ node.name = this.type.keyword;
+
+ // To fix https://github.com/acornjs/acorn/issues/575
+ // `class` and `function` keywords push new context into this.context.
+ // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
+ // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
+ if ((node.name === "class" || node.name === "function") &&
+ (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
+ this.context.pop();
+ }
} else {
- val = exprList[0];
+ this.unexpected();
}
- } else {
- val = this.parseParenExpression();
- }
+ this.next();
+ this.finishNode(node, "Identifier");
+ if (!liberal) {
+ this.checkUnreserved(node);
+ if (node.name === "await" && !this.awaitIdentPos)
+ { this.awaitIdentPos = node.start; }
+ }
+ return node
+ };
- if (this.options.preserveParens) {
- var par = this.startNodeAt(startPos, startLoc);
- par.expression = val;
- return this.finishNode(par, "ParenthesizedExpression")
- } else {
- return val
- }
-};
+ // Parses yield expression inside generator.
-pp$3.parseParenItem = function(item) {
- return item
-};
+ pp$3.parseYield = function(noIn) {
+ if (!this.yieldPos) { this.yieldPos = this.start; }
-pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
- return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
-};
+ var node = this.startNode();
+ this.next();
+ if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
+ node.delegate = false;
+ node.argument = null;
+ } else {
+ node.delegate = this.eat(types.star);
+ node.argument = this.parseMaybeAssign(noIn);
+ }
+ return this.finishNode(node, "YieldExpression")
+ };
-// New's precedence is slightly tricky. It must allow its argument to
-// be a `[]` or dot subscript expression, but not a call — at least,
-// not without wrapping it in parentheses. Thus, it uses the noCalls
-// argument to parseSubscripts to prevent it from consuming the
-// argument list.
+ pp$3.parseAwait = function() {
+ if (!this.awaitPos) { this.awaitPos = this.start; }
-var empty$1 = [];
+ var node = this.startNode();
+ this.next();
+ node.argument = this.parseMaybeUnary(null, true);
+ return this.finishNode(node, "AwaitExpression")
+ };
-pp$3.parseNew = function() {
- var node = this.startNode();
- var meta = this.parseIdent(true);
- if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
- node.meta = meta;
- var containsEsc = this.containsEsc;
- node.property = this.parseIdent(true);
- if (node.property.name !== "target" || containsEsc)
- { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
- if (!this.inNonArrowFunction())
- { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
- return this.finishNode(node, "MetaProperty")
- }
- var startPos = this.start, startLoc = this.startLoc;
- node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
- if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
- else { node.arguments = empty$1; }
- return this.finishNode(node, "NewExpression")
-};
-
-// Parse template expression.
-
-pp$3.parseTemplateElement = function(ref) {
- var isTagged = ref.isTagged;
-
- var elem = this.startNode();
- if (this.type === types.invalidTemplate) {
- if (!isTagged) {
- this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
- }
- elem.value = {
- raw: this.value,
- cooked: null
- };
- } else {
- elem.value = {
- raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
- cooked: this.value
- };
- }
- this.next();
- elem.tail = this.type === types.backQuote;
- return this.finishNode(elem, "TemplateElement")
-};
-
-pp$3.parseTemplate = function(ref) {
- var this$1 = this;
- if ( ref === void 0 ) ref = {};
- var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;
-
- var node = this.startNode();
- this.next();
- node.expressions = [];
- var curElt = this.parseTemplateElement({isTagged: isTagged});
- node.quasis = [curElt];
- while (!curElt.tail) {
- if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); }
- this$1.expect(types.dollarBraceL);
- node.expressions.push(this$1.parseExpression());
- this$1.expect(types.braceR);
- node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged}));
- }
- this.next();
- return this.finishNode(node, "TemplateLiteral")
-};
-
-pp$3.isAsyncProp = function(prop) {
- return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
- (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) &&
- !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
-};
-
-// Parse an object literal or binding pattern.
-
-pp$3.parseObj = function(isPattern, refDestructuringErrors) {
- var this$1 = this;
-
- var node = this.startNode(), first = true, propHash = {};
- node.properties = [];
- this.next();
- while (!this.eat(types.braceR)) {
- if (!first) {
- this$1.expect(types.comma);
- if (this$1.afterTrailingComma(types.braceR)) { break }
- } else { first = false; }
-
- var prop = this$1.parseProperty(isPattern, refDestructuringErrors);
- if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); }
- node.properties.push(prop);
- }
- return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
-};
-
-pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
- var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
- if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) {
- if (isPattern) {
- prop.argument = this.parseIdent(false);
- if (this.type === types.comma) {
- this.raise(this.start, "Comma is not permitted after the rest element");
- }
- return this.finishNode(prop, "RestElement")
+ var pp$4 = Parser.prototype;
+
+ // This function is used to raise exceptions on parse errors. It
+ // takes an offset integer (into the current `input`) to indicate
+ // the location of the error, attaches the position to the end
+ // of the error message, and then raises a `SyntaxError` with that
+ // message.
+
+ pp$4.raise = function(pos, message) {
+ var loc = getLineInfo(this.input, pos);
+ message += " (" + loc.line + ":" + loc.column + ")";
+ var err = new SyntaxError(message);
+ err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
+ throw err
+ };
+
+ pp$4.raiseRecoverable = pp$4.raise;
+
+ pp$4.curPosition = function() {
+ if (this.options.locations) {
+ return new Position(this.curLine, this.pos - this.lineStart)
}
- // To disallow parenthesized identifier via `this.toAssignable()`.
- if (this.type === types.parenL && refDestructuringErrors) {
- if (refDestructuringErrors.parenthesizedAssign < 0) {
- refDestructuringErrors.parenthesizedAssign = this.start;
- }
- if (refDestructuringErrors.parenthesizedBind < 0) {
- refDestructuringErrors.parenthesizedBind = this.start;
+ };
+
+ var pp$5 = Parser.prototype;
+
+ var Scope = function Scope(flags) {
+ this.flags = flags;
+ // A list of var-declared names in the current lexical scope
+ this.var = [];
+ // A list of lexically-declared names in the current lexical scope
+ this.lexical = [];
+ // A list of lexically-declared FunctionDeclaration names in the current lexical scope
+ this.functions = [];
+ };
+
+ // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
+
+ pp$5.enterScope = function(flags) {
+ this.scopeStack.push(new Scope(flags));
+ };
+
+ pp$5.exitScope = function() {
+ this.scopeStack.pop();
+ };
+
+ // The spec says:
+ // > At the top level of a function, or script, function declarations are
+ // > treated like var declarations rather than like lexical declarations.
+ pp$5.treatFunctionsAsVarInScope = function(scope) {
+ return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP)
+ };
+
+ pp$5.declareName = function(name, bindingType, pos) {
+ var redeclared = false;
+ if (bindingType === BIND_LEXICAL) {
+ var scope = this.currentScope();
+ redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
+ scope.lexical.push(name);
+ if (this.inModule && (scope.flags & SCOPE_TOP))
+ { delete this.undefinedExports[name]; }
+ } else if (bindingType === BIND_SIMPLE_CATCH) {
+ var scope$1 = this.currentScope();
+ scope$1.lexical.push(name);
+ } else if (bindingType === BIND_FUNCTION) {
+ var scope$2 = this.currentScope();
+ if (this.treatFunctionsAsVar)
+ { redeclared = scope$2.lexical.indexOf(name) > -1; }
+ else
+ { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; }
+ scope$2.functions.push(name);
+ } else {
+ for (var i = this.scopeStack.length - 1; i >= 0; --i) {
+ var scope$3 = this.scopeStack[i];
+ if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) ||
+ !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) {
+ redeclared = true;
+ break
+ }
+ scope$3.var.push(name);
+ if (this.inModule && (scope$3.flags & SCOPE_TOP))
+ { delete this.undefinedExports[name]; }
+ if (scope$3.flags & SCOPE_VAR) { break }
}
}
- // Parse argument.
- prop.argument = this.parseMaybeAssign(false, refDestructuringErrors);
- // To disallow trailing comma via `this.toAssignable()`.
- if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
- refDestructuringErrors.trailingComma = this.start;
+ if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
+ };
+
+ pp$5.checkLocalExport = function(id) {
+ // scope.functions must be empty as Module code is always strict.
+ if (this.scopeStack[0].lexical.indexOf(id.name) === -1 &&
+ this.scopeStack[0].var.indexOf(id.name) === -1) {
+ this.undefinedExports[id.name] = id;
}
- // Finish
- return this.finishNode(prop, "SpreadElement")
- }
- if (this.options.ecmaVersion >= 6) {
- prop.method = false;
- prop.shorthand = false;
- if (isPattern || refDestructuringErrors) {
- startPos = this.start;
- startLoc = this.startLoc;
- }
- if (!isPattern)
- { isGenerator = this.eat(types.star); }
- }
- var containsEsc = this.containsEsc;
- this.parsePropertyName(prop);
- if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
- isAsync = true;
- isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star);
- this.parsePropertyName(prop, refDestructuringErrors);
- } else {
- isAsync = false;
- }
- this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
- return this.finishNode(prop, "Property")
-};
-
-pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
- if ((isGenerator || isAsync) && this.type === types.colon)
- { this.unexpected(); }
-
- if (this.eat(types.colon)) {
- prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
- prop.kind = "init";
- } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
- if (isPattern) { this.unexpected(); }
- prop.kind = "init";
- prop.method = true;
- prop.value = this.parseMethod(isGenerator, isAsync);
- } else if (!isPattern && !containsEsc &&
- this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
- (prop.key.name === "get" || prop.key.name === "set") &&
- (this.type !== types.comma && this.type !== types.braceR)) {
- if (isGenerator || isAsync) { this.unexpected(); }
- prop.kind = prop.key.name;
- this.parsePropertyName(prop);
- prop.value = this.parseMethod(false);
- var paramCount = prop.kind === "get" ? 0 : 1;
- if (prop.value.params.length !== paramCount) {
- var start = prop.value.start;
- if (prop.kind === "get")
- { this.raiseRecoverable(start, "getter should have no params"); }
- else
- { this.raiseRecoverable(start, "setter should have exactly one param"); }
- } else {
- if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
- { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
- }
- } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
- this.checkUnreserved(prop.key);
- prop.kind = "init";
- if (isPattern) {
- prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
- } else if (this.type === types.eq && refDestructuringErrors) {
- if (refDestructuringErrors.shorthandAssign < 0)
- { refDestructuringErrors.shorthandAssign = this.start; }
- prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
- } else {
- prop.value = prop.key;
- }
- prop.shorthand = true;
- } else { this.unexpected(); }
-};
-
-pp$3.parsePropertyName = function(prop) {
- if (this.options.ecmaVersion >= 6) {
- if (this.eat(types.bracketL)) {
- prop.computed = true;
- prop.key = this.parseMaybeAssign();
- this.expect(types.bracketR);
- return prop.key
- } else {
- prop.computed = false;
+ };
+
+ pp$5.currentScope = function() {
+ return this.scopeStack[this.scopeStack.length - 1]
+ };
+
+ pp$5.currentVarScope = function() {
+ for (var i = this.scopeStack.length - 1;; i--) {
+ var scope = this.scopeStack[i];
+ if (scope.flags & SCOPE_VAR) { return scope }
}
- }
- return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true)
-};
-
-// Initialize empty function node.
-
-pp$3.initFunction = function(node) {
- node.id = null;
- if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; }
- if (this.options.ecmaVersion >= 8) { node.async = false; }
-};
-
-// Parse object or class method.
-
-pp$3.parseMethod = function(isGenerator, isAsync) {
- var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
-
- this.initFunction(node);
- if (this.options.ecmaVersion >= 6)
- { node.generator = isGenerator; }
- if (this.options.ecmaVersion >= 8)
- { node.async = !!isAsync; }
-
- this.yieldPos = 0;
- this.awaitPos = 0;
- this.enterScope(functionFlags(isAsync, node.generator));
-
- this.expect(types.parenL);
- node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
- this.checkYieldAwaitInDefaultParams();
- this.parseFunctionBody(node, false);
-
- this.yieldPos = oldYieldPos;
- this.awaitPos = oldAwaitPos;
- return this.finishNode(node, "FunctionExpression")
-};
-
-// Parse arrow function expression with given parameters.
-
-pp$3.parseArrowExpression = function(node, params, isAsync) {
- var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos;
-
- this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW);
- this.initFunction(node);
- if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; }
-
- this.yieldPos = 0;
- this.awaitPos = 0;
-
- node.params = this.toAssignableList(params, true);
- this.parseFunctionBody(node, true);
-
- this.yieldPos = oldYieldPos;
- this.awaitPos = oldAwaitPos;
- return this.finishNode(node, "ArrowFunctionExpression")
-};
-
-// Parse function body and check parameters.
-
-pp$3.parseFunctionBody = function(node, isArrowFunction) {
- var isExpression = isArrowFunction && this.type !== types.braceL;
- var oldStrict = this.strict, useStrict = false;
-
- if (isExpression) {
- node.body = this.parseMaybeAssign();
- node.expression = true;
- this.checkParams(node, false);
- } else {
- var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
- if (!oldStrict || nonSimple) {
- useStrict = this.strictDirective(this.end);
- // If this is a strict mode function, verify that argument names
- // are not repeated, and it does not try to bind the words `eval`
- // or `arguments`.
- if (useStrict && nonSimple)
- { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
- }
- // Start a new scope with regard to labels and the `inFunction`
- // flag (restore them to their old value afterwards).
- var oldLabels = this.labels;
- this.labels = [];
- if (useStrict) { this.strict = true; }
-
- // Add the params to varDeclaredNames to ensure that an error is thrown
- // if a let/const declaration in the function clashes with one of the params.
- this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params));
- node.body = this.parseBlock(false);
- node.expression = false;
- this.adaptDirectivePrologue(node.body.body);
- this.labels = oldLabels;
- }
- this.exitScope();
+ };
+
+ // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
+ pp$5.currentThisScope = function() {
+ for (var i = this.scopeStack.length - 1;; i--) {
+ var scope = this.scopeStack[i];
+ if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope }
+ }
+ };
- // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
- if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); }
- this.strict = oldStrict;
-};
+ var Node = function Node(parser, pos, loc) {
+ this.type = "";
+ this.start = pos;
+ this.end = 0;
+ if (parser.options.locations)
+ { this.loc = new SourceLocation(parser, loc); }
+ if (parser.options.directSourceFile)
+ { this.sourceFile = parser.options.directSourceFile; }
+ if (parser.options.ranges)
+ { this.range = [pos, 0]; }
+ };
-pp$3.isSimpleParamList = function(params) {
- for (var i = 0, list = params; i < list.length; i += 1)
- {
- var param = list[i];
+ // Start an AST node, attaching a start offset.
- if (param.type !== "Identifier") { return false
- } }
- return true
-};
+ var pp$6 = Parser.prototype;
-// Checks function params for various disallowed patterns such as using "eval"
-// or "arguments" and duplicate parameters.
+ pp$6.startNode = function() {
+ return new Node(this, this.start, this.startLoc)
+ };
-pp$3.checkParams = function(node, allowDuplicates) {
- var this$1 = this;
+ pp$6.startNodeAt = function(pos, loc) {
+ return new Node(this, pos, loc)
+ };
- var nameHash = {};
- for (var i = 0, list = node.params; i < list.length; i += 1)
- {
- var param = list[i];
+ // Finish an AST node, adding `type` and `end` properties.
- this$1.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash);
+ function finishNodeAt(node, type, pos, loc) {
+ node.type = type;
+ node.end = pos;
+ if (this.options.locations)
+ { node.loc.end = loc; }
+ if (this.options.ranges)
+ { node.range[1] = pos; }
+ return node
}
-};
-
-// Parses a comma-separated list of expressions, and returns them as
-// an array. `close` is the token type that ends the list, and
-// `allowEmpty` can be turned on to allow subsequent commas with
-// nothing in between them to be parsed as `null` (which is needed
-// for array literals).
-
-pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
- var this$1 = this;
-
- var elts = [], first = true;
- while (!this.eat(close)) {
- if (!first) {
- this$1.expect(types.comma);
- if (allowTrailingComma && this$1.afterTrailingComma(close)) { break }
- } else { first = false; }
-
- var elt = (void 0);
- if (allowEmpty && this$1.type === types.comma)
- { elt = null; }
- else if (this$1.type === types.ellipsis) {
- elt = this$1.parseSpread(refDestructuringErrors);
- if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0)
- { refDestructuringErrors.trailingComma = this$1.start; }
- } else {
- elt = this$1.parseMaybeAssign(false, refDestructuringErrors);
+
+ pp$6.finishNode = function(node, type) {
+ return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
+ };
+
+ // Finish node at given position
+
+ pp$6.finishNodeAt = function(node, type, pos, loc) {
+ return finishNodeAt.call(this, node, type, pos, loc)
+ };
+
+ // The algorithm used to determine whether a regexp can appear at a
+
+ var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
+ this.token = token;
+ this.isExpr = !!isExpr;
+ this.preserveSpace = !!preserveSpace;
+ this.override = override;
+ this.generator = !!generator;
+ };
+
+ var types$1 = {
+ b_stat: new TokContext("{", false),
+ b_expr: new TokContext("{", true),
+ b_tmpl: new TokContext("${", false),
+ p_stat: new TokContext("(", false),
+ p_expr: new TokContext("(", true),
+ q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
+ f_stat: new TokContext("function", false),
+ f_expr: new TokContext("function", true),
+ f_expr_gen: new TokContext("function", true, false, null, true),
+ f_gen: new TokContext("function", false, false, null, true)
+ };
+
+ var pp$7 = Parser.prototype;
+
+ pp$7.initialContext = function() {
+ return [types$1.b_stat]
+ };
+
+ pp$7.braceIsBlock = function(prevType) {
+ var parent = this.curContext();
+ if (parent === types$1.f_expr || parent === types$1.f_stat)
+ { return true }
+ if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
+ { return !parent.isExpr }
+
+ // The check for `tt.name && exprAllowed` detects whether we are
+ // after a `yield` or `of` construct. See the `updateContext` for
+ // `tt.name`.
+ if (prevType === types._return || prevType === types.name && this.exprAllowed)
+ { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
+ if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
+ { return true }
+ if (prevType === types.braceL)
+ { return parent === types$1.b_stat }
+ if (prevType === types._var || prevType === types._const || prevType === types.name)
+ { return false }
+ return !this.exprAllowed
+ };
+
+ pp$7.inGeneratorContext = function() {
+ for (var i = this.context.length - 1; i >= 1; i--) {
+ var context = this.context[i];
+ if (context.token === "function")
+ { return context.generator }
}
- elts.push(elt);
- }
- return elts
-};
-
-pp$3.checkUnreserved = function(ref) {
- var start = ref.start;
- var end = ref.end;
- var name = ref.name;
-
- if (this.inGenerator && name === "yield")
- { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); }
- if (this.inAsync && name === "await")
- { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); }
- if (this.keywords.test(name))
- { this.raise(start, ("Unexpected keyword '" + name + "'")); }
- if (this.options.ecmaVersion < 6 &&
- this.input.slice(start, end).indexOf("\\") !== -1) { return }
- var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
- if (re.test(name)) {
- if (!this.inAsync && name === "await")
- { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); }
- this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved"));
- }
-};
-
-// Parse the next token as an identifier. If `liberal` is true (used
-// when parsing properties), it will also convert keywords into
-// identifiers.
-
-pp$3.parseIdent = function(liberal, isBinding) {
- var node = this.startNode();
- if (liberal && this.options.allowReserved === "never") { liberal = false; }
- if (this.type === types.name) {
- node.name = this.value;
- } else if (this.type.keyword) {
- node.name = this.type.keyword;
-
- // To fix https://github.com/acornjs/acorn/issues/575
- // `class` and `function` keywords push new context into this.context.
- // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
- // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
- if ((node.name === "class" || node.name === "function") &&
- (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
- this.context.pop();
- }
- } else {
- this.unexpected();
- }
- this.next();
- this.finishNode(node, "Identifier");
- if (!liberal) { this.checkUnreserved(node); }
- return node
-};
-
-// Parses yield expression inside generator.
-
-pp$3.parseYield = function() {
- if (!this.yieldPos) { this.yieldPos = this.start; }
-
- var node = this.startNode();
- this.next();
- if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) {
- node.delegate = false;
- node.argument = null;
- } else {
- node.delegate = this.eat(types.star);
- node.argument = this.parseMaybeAssign();
- }
- return this.finishNode(node, "YieldExpression")
-};
-
-pp$3.parseAwait = function() {
- if (!this.awaitPos) { this.awaitPos = this.start; }
-
- var node = this.startNode();
- this.next();
- node.argument = this.parseMaybeUnary(null, true);
- return this.finishNode(node, "AwaitExpression")
-};
-
-var pp$4 = Parser.prototype;
-
-// This function is used to raise exceptions on parse errors. It
-// takes an offset integer (into the current `input`) to indicate
-// the location of the error, attaches the position to the end
-// of the error message, and then raises a `SyntaxError` with that
-// message.
-
-pp$4.raise = function(pos, message) {
- var loc = getLineInfo(this.input, pos);
- message += " (" + loc.line + ":" + loc.column + ")";
- var err = new SyntaxError(message);
- err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
- throw err
-};
-
-pp$4.raiseRecoverable = pp$4.raise;
-
-pp$4.curPosition = function() {
- if (this.options.locations) {
- return new Position(this.curLine, this.pos - this.lineStart)
- }
-};
-
-var pp$5 = Parser.prototype;
-
-var Scope = function Scope(flags) {
- this.flags = flags;
- // A list of var-declared names in the current lexical scope
- this.var = [];
- // A list of lexically-declared names in the current lexical scope
- this.lexical = [];
-};
-
-// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
-
-pp$5.enterScope = function(flags) {
- this.scopeStack.push(new Scope(flags));
-};
-
-pp$5.exitScope = function() {
- this.scopeStack.pop();
-};
-
-pp$5.declareName = function(name, bindingType, pos) {
- var this$1 = this;
-
- var redeclared = false;
- if (bindingType === BIND_LEXICAL) {
- var scope = this.currentScope();
- redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
- scope.lexical.push(name);
- } else if (bindingType === BIND_SIMPLE_CATCH) {
- var scope$1 = this.currentScope();
- scope$1.lexical.push(name);
- } else if (bindingType === BIND_FUNCTION) {
- var scope$2 = this.currentScope();
- redeclared = scope$2.lexical.indexOf(name) > -1;
- scope$2.var.push(name);
- } else {
- for (var i = this.scopeStack.length - 1; i >= 0; --i) {
- var scope$3 = this$1.scopeStack[i];
- if (scope$3.lexical.indexOf(name) > -1 && !(scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) { redeclared = true; }
- scope$3.var.push(name);
- if (scope$3.flags & SCOPE_VAR) { break }
+ return false
+ };
+
+ pp$7.updateContext = function(prevType) {
+ var update, type = this.type;
+ if (type.keyword && prevType === types.dot)
+ { this.exprAllowed = false; }
+ else if (update = type.updateContext)
+ { update.call(this, prevType); }
+ else
+ { this.exprAllowed = type.beforeExpr; }
+ };
+
+ // Token-specific context update code
+
+ types.parenR.updateContext = types.braceR.updateContext = function() {
+ if (this.context.length === 1) {
+ this.exprAllowed = true;
+ return
}
- }
- if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); }
-};
+ var out = this.context.pop();
+ if (out === types$1.b_stat && this.curContext().token === "function") {
+ out = this.context.pop();
+ }
+ this.exprAllowed = !out.isExpr;
+ };
-pp$5.currentScope = function() {
- return this.scopeStack[this.scopeStack.length - 1]
-};
+ types.braceL.updateContext = function(prevType) {
+ this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
+ this.exprAllowed = true;
+ };
-pp$5.currentVarScope = function() {
- var this$1 = this;
+ types.dollarBraceL.updateContext = function() {
+ this.context.push(types$1.b_tmpl);
+ this.exprAllowed = true;
+ };
- for (var i = this.scopeStack.length - 1;; i--) {
- var scope = this$1.scopeStack[i];
- if (scope.flags & SCOPE_VAR) { return scope }
- }
-};
-
-pp$5.inNonArrowFunction = function() {
- var this$1 = this;
-
- for (var i = this.scopeStack.length - 1; i >= 0; i--)
- { if (this$1.scopeStack[i].flags & SCOPE_FUNCTION && !(this$1.scopeStack[i].flags & SCOPE_ARROW)) { return true } }
- return false
-};
-
-var Node = function Node(parser, pos, loc) {
- this.type = "";
- this.start = pos;
- this.end = 0;
- if (parser.options.locations)
- { this.loc = new SourceLocation(parser, loc); }
- if (parser.options.directSourceFile)
- { this.sourceFile = parser.options.directSourceFile; }
- if (parser.options.ranges)
- { this.range = [pos, 0]; }
-};
-
-// Start an AST node, attaching a start offset.
-
-var pp$6 = Parser.prototype;
-
-pp$6.startNode = function() {
- return new Node(this, this.start, this.startLoc)
-};
-
-pp$6.startNodeAt = function(pos, loc) {
- return new Node(this, pos, loc)
-};
-
-// Finish an AST node, adding `type` and `end` properties.
-
-function finishNodeAt(node, type, pos, loc) {
- node.type = type;
- node.end = pos;
- if (this.options.locations)
- { node.loc.end = loc; }
- if (this.options.ranges)
- { node.range[1] = pos; }
- return node
-}
-
-pp$6.finishNode = function(node, type) {
- return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
-};
-
-// Finish node at given position
-
-pp$6.finishNodeAt = function(node, type, pos, loc) {
- return finishNodeAt.call(this, node, type, pos, loc)
-};
-
-// The algorithm used to determine whether a regexp can appear at a
-// given point in the program is loosely based on sweet.js' approach.
-// See https://github.com/mozilla/sweet.js/wiki/design
-
-var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
- this.token = token;
- this.isExpr = !!isExpr;
- this.preserveSpace = !!preserveSpace;
- this.override = override;
- this.generator = !!generator;
-};
-
-var types$1 = {
- b_stat: new TokContext("{", false),
- b_expr: new TokContext("{", true),
- b_tmpl: new TokContext("${", false),
- p_stat: new TokContext("(", false),
- p_expr: new TokContext("(", true),
- q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
- f_stat: new TokContext("function", false),
- f_expr: new TokContext("function", true),
- f_expr_gen: new TokContext("function", true, false, null, true),
- f_gen: new TokContext("function", false, false, null, true)
-};
-
-var pp$7 = Parser.prototype;
-
-pp$7.initialContext = function() {
- return [types$1.b_stat]
-};
-
-pp$7.braceIsBlock = function(prevType) {
- var parent = this.curContext();
- if (parent === types$1.f_expr || parent === types$1.f_stat)
- { return true }
- if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
- { return !parent.isExpr }
-
- // The check for `tt.name && exprAllowed` detects whether we are
- // after a `yield` or `of` construct. See the `updateContext` for
- // `tt.name`.
- if (prevType === types._return || prevType === types.name && this.exprAllowed)
- { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
- if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow)
- { return true }
- if (prevType === types.braceL)
- { return parent === types$1.b_stat }
- if (prevType === types._var || prevType === types.name)
- { return false }
- return !this.exprAllowed
-};
-
-pp$7.inGeneratorContext = function() {
- var this$1 = this;
-
- for (var i = this.context.length - 1; i >= 1; i--) {
- var context = this$1.context[i];
- if (context.token === "function")
- { return context.generator }
- }
- return false
-};
-
-pp$7.updateContext = function(prevType) {
- var update, type = this.type;
- if (type.keyword && prevType === types.dot)
- { this.exprAllowed = false; }
- else if (update = type.updateContext)
- { update.call(this, prevType); }
- else
- { this.exprAllowed = type.beforeExpr; }
-};
-
-// Token-specific context update code
-
-types.parenR.updateContext = types.braceR.updateContext = function() {
- if (this.context.length === 1) {
+ types.parenL.updateContext = function(prevType) {
+ var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
+ this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
this.exprAllowed = true;
- return
- }
- var out = this.context.pop();
- if (out === types$1.b_stat && this.curContext().token === "function") {
- out = this.context.pop();
- }
- this.exprAllowed = !out.isExpr;
-};
-
-types.braceL.updateContext = function(prevType) {
- this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
- this.exprAllowed = true;
-};
-
-types.dollarBraceL.updateContext = function() {
- this.context.push(types$1.b_tmpl);
- this.exprAllowed = true;
-};
-
-types.parenL.updateContext = function(prevType) {
- var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
- this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
- this.exprAllowed = true;
-};
-
-types.incDec.updateContext = function() {
- // tokExprAllowed stays unchanged
-};
-
-types._function.updateContext = types._class.updateContext = function(prevType) {
- if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
- !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
- { this.context.push(types$1.f_expr); }
- else
- { this.context.push(types$1.f_stat); }
- this.exprAllowed = false;
-};
-
-types.backQuote.updateContext = function() {
- if (this.curContext() === types$1.q_tmpl)
- { this.context.pop(); }
- else
- { this.context.push(types$1.q_tmpl); }
- this.exprAllowed = false;
-};
-
-types.star.updateContext = function(prevType) {
- if (prevType === types._function) {
- var index = this.context.length - 1;
- if (this.context[index] === types$1.f_expr)
- { this.context[index] = types$1.f_expr_gen; }
+ };
+
+ types.incDec.updateContext = function() {
+ // tokExprAllowed stays unchanged
+ };
+
+ types._function.updateContext = types._class.updateContext = function(prevType) {
+ if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
+ !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) &&
+ !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
+ { this.context.push(types$1.f_expr); }
else
- { this.context[index] = types$1.f_gen; }
- }
- this.exprAllowed = true;
-};
-
-types.name.updateContext = function(prevType) {
- var allowed = false;
- if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
- if (this.value === "of" && !this.exprAllowed ||
- this.value === "yield" && this.inGeneratorContext())
- { allowed = true; }
- }
- this.exprAllowed = allowed;
-};
-
-var data = {
- "$LONE": [
- "ASCII",
- "ASCII_Hex_Digit",
- "AHex",
- "Alphabetic",
- "Alpha",
- "Any",
- "Assigned",
- "Bidi_Control",
- "Bidi_C",
- "Bidi_Mirrored",
- "Bidi_M",
- "Case_Ignorable",
- "CI",
- "Cased",
- "Changes_When_Casefolded",
- "CWCF",
- "Changes_When_Casemapped",
- "CWCM",
- "Changes_When_Lowercased",
- "CWL",
- "Changes_When_NFKC_Casefolded",
- "CWKCF",
- "Changes_When_Titlecased",
- "CWT",
- "Changes_When_Uppercased",
- "CWU",
- "Dash",
- "Default_Ignorable_Code_Point",
- "DI",
- "Deprecated",
- "Dep",
- "Diacritic",
- "Dia",
- "Emoji",
- "Emoji_Component",
- "Emoji_Modifier",
- "Emoji_Modifier_Base",
- "Emoji_Presentation",
- "Extender",
- "Ext",
- "Grapheme_Base",
- "Gr_Base",
- "Grapheme_Extend",
- "Gr_Ext",
- "Hex_Digit",
- "Hex",
- "IDS_Binary_Operator",
- "IDSB",
- "IDS_Trinary_Operator",
- "IDST",
- "ID_Continue",
- "IDC",
- "ID_Start",
- "IDS",
- "Ideographic",
- "Ideo",
- "Join_Control",
- "Join_C",
- "Logical_Order_Exception",
- "LOE",
- "Lowercase",
- "Lower",
- "Math",
- "Noncharacter_Code_Point",
- "NChar",
- "Pattern_Syntax",
- "Pat_Syn",
- "Pattern_White_Space",
- "Pat_WS",
- "Quotation_Mark",
- "QMark",
- "Radical",
- "Regional_Indicator",
- "RI",
- "Sentence_Terminal",
- "STerm",
- "Soft_Dotted",
- "SD",
- "Terminal_Punctuation",
- "Term",
- "Unified_Ideograph",
- "UIdeo",
- "Uppercase",
- "Upper",
- "Variation_Selector",
- "VS",
- "White_Space",
- "space",
- "XID_Continue",
- "XIDC",
- "XID_Start",
- "XIDS"
- ],
- "General_Category": [
- "Cased_Letter",
- "LC",
- "Close_Punctuation",
- "Pe",
- "Connector_Punctuation",
- "Pc",
- "Control",
- "Cc",
- "cntrl",
- "Currency_Symbol",
- "Sc",
- "Dash_Punctuation",
- "Pd",
- "Decimal_Number",
- "Nd",
- "digit",
- "Enclosing_Mark",
- "Me",
- "Final_Punctuation",
- "Pf",
- "Format",
- "Cf",
- "Initial_Punctuation",
- "Pi",
- "Letter",
- "L",
- "Letter_Number",
- "Nl",
- "Line_Separator",
- "Zl",
- "Lowercase_Letter",
- "Ll",
- "Mark",
- "M",
- "Combining_Mark",
- "Math_Symbol",
- "Sm",
- "Modifier_Letter",
- "Lm",
- "Modifier_Symbol",
- "Sk",
- "Nonspacing_Mark",
- "Mn",
- "Number",
- "N",
- "Open_Punctuation",
- "Ps",
- "Other",
- "C",
- "Other_Letter",
- "Lo",
- "Other_Number",
- "No",
- "Other_Punctuation",
- "Po",
- "Other_Symbol",
- "So",
- "Paragraph_Separator",
- "Zp",
- "Private_Use",
- "Co",
- "Punctuation",
- "P",
- "punct",
- "Separator",
- "Z",
- "Space_Separator",
- "Zs",
- "Spacing_Mark",
- "Mc",
- "Surrogate",
- "Cs",
- "Symbol",
- "S",
- "Titlecase_Letter",
- "Lt",
- "Unassigned",
- "Cn",
- "Uppercase_Letter",
- "Lu"
- ],
- "Script": [
- "Adlam",
- "Adlm",
- "Ahom",
- "Anatolian_Hieroglyphs",
- "Hluw",
- "Arabic",
- "Arab",
- "Armenian",
- "Armn",
- "Avestan",
- "Avst",
- "Balinese",
- "Bali",
- "Bamum",
- "Bamu",
- "Bassa_Vah",
- "Bass",
- "Batak",
- "Batk",
- "Bengali",
- "Beng",
- "Bhaiksuki",
- "Bhks",
- "Bopomofo",
- "Bopo",
- "Brahmi",
- "Brah",
- "Braille",
- "Brai",
- "Buginese",
- "Bugi",
- "Buhid",
- "Buhd",
- "Canadian_Aboriginal",
- "Cans",
- "Carian",
- "Cari",
- "Caucasian_Albanian",
- "Aghb",
- "Chakma",
- "Cakm",
- "Cham",
- "Cherokee",
- "Cher",
- "Common",
- "Zyyy",
- "Coptic",
- "Copt",
- "Qaac",
- "Cuneiform",
- "Xsux",
- "Cypriot",
- "Cprt",
- "Cyrillic",
- "Cyrl",
- "Deseret",
- "Dsrt",
- "Devanagari",
- "Deva",
- "Duployan",
- "Dupl",
- "Egyptian_Hieroglyphs",
- "Egyp",
- "Elbasan",
- "Elba",
- "Ethiopic",
- "Ethi",
- "Georgian",
- "Geor",
- "Glagolitic",
- "Glag",
- "Gothic",
- "Goth",
- "Grantha",
- "Gran",
- "Greek",
- "Grek",
- "Gujarati",
- "Gujr",
- "Gurmukhi",
- "Guru",
- "Han",
- "Hani",
- "Hangul",
- "Hang",
- "Hanunoo",
- "Hano",
- "Hatran",
- "Hatr",
- "Hebrew",
- "Hebr",
- "Hiragana",
- "Hira",
- "Imperial_Aramaic",
- "Armi",
- "Inherited",
- "Zinh",
- "Qaai",
- "Inscriptional_Pahlavi",
- "Phli",
- "Inscriptional_Parthian",
- "Prti",
- "Javanese",
- "Java",
- "Kaithi",
- "Kthi",
- "Kannada",
- "Knda",
- "Katakana",
- "Kana",
- "Kayah_Li",
- "Kali",
- "Kharoshthi",
- "Khar",
- "Khmer",
- "Khmr",
- "Khojki",
- "Khoj",
- "Khudawadi",
- "Sind",
- "Lao",
- "Laoo",
- "Latin",
- "Latn",
- "Lepcha",
- "Lepc",
- "Limbu",
- "Limb",
- "Linear_A",
- "Lina",
- "Linear_B",
- "Linb",
- "Lisu",
- "Lycian",
- "Lyci",
- "Lydian",
- "Lydi",
- "Mahajani",
- "Mahj",
- "Malayalam",
- "Mlym",
- "Mandaic",
- "Mand",
- "Manichaean",
- "Mani",
- "Marchen",
- "Marc",
- "Masaram_Gondi",
- "Gonm",
- "Meetei_Mayek",
- "Mtei",
- "Mende_Kikakui",
- "Mend",
- "Meroitic_Cursive",
- "Merc",
- "Meroitic_Hieroglyphs",
- "Mero",
- "Miao",
- "Plrd",
- "Modi",
- "Mongolian",
- "Mong",
- "Mro",
- "Mroo",
- "Multani",
- "Mult",
- "Myanmar",
- "Mymr",
- "Nabataean",
- "Nbat",
- "New_Tai_Lue",
- "Talu",
- "Newa",
- "Nko",
- "Nkoo",
- "Nushu",
- "Nshu",
- "Ogham",
- "Ogam",
- "Ol_Chiki",
- "Olck",
- "Old_Hungarian",
- "Hung",
- "Old_Italic",
- "Ital",
- "Old_North_Arabian",
- "Narb",
- "Old_Permic",
- "Perm",
- "Old_Persian",
- "Xpeo",
- "Old_South_Arabian",
- "Sarb",
- "Old_Turkic",
- "Orkh",
- "Oriya",
- "Orya",
- "Osage",
- "Osge",
- "Osmanya",
- "Osma",
- "Pahawh_Hmong",
- "Hmng",
- "Palmyrene",
- "Palm",
- "Pau_Cin_Hau",
- "Pauc",
- "Phags_Pa",
- "Phag",
- "Phoenician",
- "Phnx",
- "Psalter_Pahlavi",
- "Phlp",
- "Rejang",
- "Rjng",
- "Runic",
- "Runr",
- "Samaritan",
- "Samr",
- "Saurashtra",
- "Saur",
- "Sharada",
- "Shrd",
- "Shavian",
- "Shaw",
- "Siddham",
- "Sidd",
- "SignWriting",
- "Sgnw",
- "Sinhala",
- "Sinh",
- "Sora_Sompeng",
- "Sora",
- "Soyombo",
- "Soyo",
- "Sundanese",
- "Sund",
- "Syloti_Nagri",
- "Sylo",
- "Syriac",
- "Syrc",
- "Tagalog",
- "Tglg",
- "Tagbanwa",
- "Tagb",
- "Tai_Le",
- "Tale",
- "Tai_Tham",
- "Lana",
- "Tai_Viet",
- "Tavt",
- "Takri",
- "Takr",
- "Tamil",
- "Taml",
- "Tangut",
- "Tang",
- "Telugu",
- "Telu",
- "Thaana",
- "Thaa",
- "Thai",
- "Tibetan",
- "Tibt",
- "Tifinagh",
- "Tfng",
- "Tirhuta",
- "Tirh",
- "Ugaritic",
- "Ugar",
- "Vai",
- "Vaii",
- "Warang_Citi",
- "Wara",
- "Yi",
- "Yiii",
- "Zanabazar_Square",
- "Zanb"
- ]
-};
-Array.prototype.push.apply(data.$LONE, data.General_Category);
-data.gc = data.General_Category;
-data.sc = data.Script_Extensions = data.scx = data.Script;
-
-var pp$9 = Parser.prototype;
-
-var RegExpValidationState = function RegExpValidationState(parser) {
- this.parser = parser;
- this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
- this.source = "";
- this.flags = "";
- this.start = 0;
- this.switchU = false;
- this.switchN = false;
- this.pos = 0;
- this.lastIntValue = 0;
- this.lastStringValue = "";
- this.lastAssertionIsQuantifiable = false;
- this.numCapturingParens = 0;
- this.maxBackReference = 0;
- this.groupNames = [];
- this.backReferenceNames = [];
-};
-
-RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
- var unicode = flags.indexOf("u") !== -1;
- this.start = start | 0;
- this.source = pattern + "";
- this.flags = flags;
- this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
- this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
-};
-
-RegExpValidationState.prototype.raise = function raise (message) {
- this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
-};
-
-// If u flag is given, this returns the code point at the index (it combines a surrogate pair).
-// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
-RegExpValidationState.prototype.at = function at (i) {
- var s = this.source;
- var l = s.length;
- if (i >= l) {
- return -1
- }
- var c = s.charCodeAt(i);
- if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
- return c
- }
- return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00
-};
-
-RegExpValidationState.prototype.nextIndex = function nextIndex (i) {
- var s = this.source;
- var l = s.length;
- if (i >= l) {
- return l
- }
- var c = s.charCodeAt(i);
- if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
- return i + 1
- }
- return i + 2
-};
+ { this.context.push(types$1.f_stat); }
+ this.exprAllowed = false;
+ };
-RegExpValidationState.prototype.current = function current () {
- return this.at(this.pos)
-};
+ types.backQuote.updateContext = function() {
+ if (this.curContext() === types$1.q_tmpl)
+ { this.context.pop(); }
+ else
+ { this.context.push(types$1.q_tmpl); }
+ this.exprAllowed = false;
+ };
-RegExpValidationState.prototype.lookahead = function lookahead () {
- return this.at(this.nextIndex(this.pos))
-};
+ types.star.updateContext = function(prevType) {
+ if (prevType === types._function) {
+ var index = this.context.length - 1;
+ if (this.context[index] === types$1.f_expr)
+ { this.context[index] = types$1.f_expr_gen; }
+ else
+ { this.context[index] = types$1.f_gen; }
+ }
+ this.exprAllowed = true;
+ };
+
+ types.name.updateContext = function(prevType) {
+ var allowed = false;
+ if (this.options.ecmaVersion >= 6 && prevType !== types.dot) {
+ if (this.value === "of" && !this.exprAllowed ||
+ this.value === "yield" && this.inGeneratorContext())
+ { allowed = true; }
+ }
+ this.exprAllowed = allowed;
+ };
-RegExpValidationState.prototype.advance = function advance () {
- this.pos = this.nextIndex(this.pos);
-};
+ // This file contains Unicode properties extracted from the ECMAScript
+ // specification. The lists are extracted like so:
+ // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
+
+ // #table-binary-unicode-properties
+ var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS";
+ var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
+ var ecma11BinaryProperties = ecma10BinaryProperties;
+ var unicodeBinaryProperties = {
+ 9: ecma9BinaryProperties,
+ 10: ecma10BinaryProperties,
+ 11: ecma11BinaryProperties
+ };
-RegExpValidationState.prototype.eat = function eat (ch) {
- if (this.current() === ch) {
- this.advance();
- return true
- }
- return false
-};
-
-function codePointToString$1(ch) {
- if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
- ch -= 0x10000;
- return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
-}
-
-/**
- * Validate the flags part of a given RegExpLiteral.
- *
- * @param {RegExpValidationState} state The state to validate RegExp.
- * @returns {void}
- */
-pp$9.validateRegExpFlags = function(state) {
- var this$1 = this;
-
- var validFlags = state.validFlags;
- var flags = state.flags;
-
- for (var i = 0; i < flags.length; i++) {
- var flag = flags.charAt(i);
- if (validFlags.indexOf(flag) === -1) {
- this$1.raise(state.start, "Invalid regular expression flag");
- }
- if (flags.indexOf(flag, i + 1) > -1) {
- this$1.raise(state.start, "Duplicate regular expression flag");
+ // #table-unicode-general-category-values
+ var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu";
+
+ // #table-unicode-script-values
+ var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb";
+ var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
+ var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
+ var unicodeScriptValues = {
+ 9: ecma9ScriptValues,
+ 10: ecma10ScriptValues,
+ 11: ecma11ScriptValues
+ };
+
+ var data = {};
+ function buildUnicodeData(ecmaVersion) {
+ var d = data[ecmaVersion] = {
+ binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
+ nonBinary: {
+ General_Category: wordsRegexp(unicodeGeneralCategoryValues),
+ Script: wordsRegexp(unicodeScriptValues[ecmaVersion])
+ }
+ };
+ d.nonBinary.Script_Extensions = d.nonBinary.Script;
+
+ d.nonBinary.gc = d.nonBinary.General_Category;
+ d.nonBinary.sc = d.nonBinary.Script;
+ d.nonBinary.scx = d.nonBinary.Script_Extensions;
+ }
+ buildUnicodeData(9);
+ buildUnicodeData(10);
+ buildUnicodeData(11);
+
+ var pp$8 = Parser.prototype;
+
+ var RegExpValidationState = function RegExpValidationState(parser) {
+ this.parser = parser;
+ this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : "");
+ this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion];
+ this.source = "";
+ this.flags = "";
+ this.start = 0;
+ this.switchU = false;
+ this.switchN = false;
+ this.pos = 0;
+ this.lastIntValue = 0;
+ this.lastStringValue = "";
+ this.lastAssertionIsQuantifiable = false;
+ this.numCapturingParens = 0;
+ this.maxBackReference = 0;
+ this.groupNames = [];
+ this.backReferenceNames = [];
+ };
+
+ RegExpValidationState.prototype.reset = function reset (start, pattern, flags) {
+ var unicode = flags.indexOf("u") !== -1;
+ this.start = start | 0;
+ this.source = pattern + "";
+ this.flags = flags;
+ this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
+ this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
+ };
+
+ RegExpValidationState.prototype.raise = function raise (message) {
+ this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message));
+ };
+
+ // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
+ // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
+ RegExpValidationState.prototype.at = function at (i) {
+ var s = this.source;
+ var l = s.length;
+ if (i >= l) {
+ return -1
}
- }
-};
-
-/**
- * Validate the pattern part of a given RegExpLiteral.
- *
- * @param {RegExpValidationState} state The state to validate RegExp.
- * @returns {void}
- */
-pp$9.validateRegExpPattern = function(state) {
- this.regexp_pattern(state);
-
- // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
- // parsing contains a |GroupName|, reparse with the goal symbol
- // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
- // exception if _P_ did not conform to the grammar, if any elements of _P_
- // were not matched by the parse, or if any Early Error conditions exist.
- if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
- state.switchN = true;
- this.regexp_pattern(state);
- }
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
-pp$9.regexp_pattern = function(state) {
- state.pos = 0;
- state.lastIntValue = 0;
- state.lastStringValue = "";
- state.lastAssertionIsQuantifiable = false;
- state.numCapturingParens = 0;
- state.maxBackReference = 0;
- state.groupNames.length = 0;
- state.backReferenceNames.length = 0;
-
- this.regexp_disjunction(state);
-
- if (state.pos !== state.source.length) {
- // Make the same messages as V8.
- if (state.eat(0x29 /* ) */)) {
- state.raise("Unmatched ')'");
- }
- if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) {
- state.raise("Lone quantifier brackets");
+ var c = s.charCodeAt(i);
+ if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
+ return c
}
- }
- if (state.maxBackReference > state.numCapturingParens) {
- state.raise("Invalid escape");
- }
- for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
- var name = list[i];
+ return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00
+ };
- if (state.groupNames.indexOf(name) === -1) {
- state.raise("Invalid named capture referenced");
+ RegExpValidationState.prototype.nextIndex = function nextIndex (i) {
+ var s = this.source;
+ var l = s.length;
+ if (i >= l) {
+ return l
}
- }
-};
+ var c = s.charCodeAt(i);
+ if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
+ return i + 1
+ }
+ return i + 2
+ };
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
-pp$9.regexp_disjunction = function(state) {
- var this$1 = this;
+ RegExpValidationState.prototype.current = function current () {
+ return this.at(this.pos)
+ };
- this.regexp_alternative(state);
- while (state.eat(0x7C /* | */)) {
- this$1.regexp_alternative(state);
- }
+ RegExpValidationState.prototype.lookahead = function lookahead () {
+ return this.at(this.nextIndex(this.pos))
+ };
- // Make the same message as V8.
- if (this.regexp_eatQuantifier(state, true)) {
- state.raise("Nothing to repeat");
- }
- if (state.eat(0x7B /* { */)) {
- state.raise("Lone quantifier brackets");
- }
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
-pp$9.regexp_alternative = function(state) {
- while (state.pos < state.source.length && this.regexp_eatTerm(state))
- { }
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
-pp$9.regexp_eatTerm = function(state) {
- if (this.regexp_eatAssertion(state)) {
- // Handle `QuantifiableAssertion Quantifier` alternative.
- // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
- // is a QuantifiableAssertion.
- if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
- // Make the same message as V8.
- if (state.switchU) {
- state.raise("Invalid quantifier");
+ RegExpValidationState.prototype.advance = function advance () {
+ this.pos = this.nextIndex(this.pos);
+ };
+
+ RegExpValidationState.prototype.eat = function eat (ch) {
+ if (this.current() === ch) {
+ this.advance();
+ return true
+ }
+ return false
+ };
+
+ function codePointToString(ch) {
+ if (ch <= 0xFFFF) { return String.fromCharCode(ch) }
+ ch -= 0x10000;
+ return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00)
+ }
+
+ /**
+ * Validate the flags part of a given RegExpLiteral.
+ *
+ * @param {RegExpValidationState} state The state to validate RegExp.
+ * @returns {void}
+ */
+ pp$8.validateRegExpFlags = function(state) {
+ var validFlags = state.validFlags;
+ var flags = state.flags;
+
+ for (var i = 0; i < flags.length; i++) {
+ var flag = flags.charAt(i);
+ if (validFlags.indexOf(flag) === -1) {
+ this.raise(state.start, "Invalid regular expression flag");
+ }
+ if (flags.indexOf(flag, i + 1) > -1) {
+ this.raise(state.start, "Duplicate regular expression flag");
}
}
- return true
- }
+ };
- if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
- this.regexp_eatQuantifier(state);
- return true
- }
+ /**
+ * Validate the pattern part of a given RegExpLiteral.
+ *
+ * @param {RegExpValidationState} state The state to validate RegExp.
+ * @returns {void}
+ */
+ pp$8.validateRegExpPattern = function(state) {
+ this.regexp_pattern(state);
- return false
-};
+ // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
+ // parsing contains a |GroupName|, reparse with the goal symbol
+ // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
+ // exception if _P_ did not conform to the grammar, if any elements of _P_
+ // were not matched by the parse, or if any Early Error conditions exist.
+ if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
+ state.switchN = true;
+ this.regexp_pattern(state);
+ }
+ };
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
-pp$9.regexp_eatAssertion = function(state) {
- var start = state.pos;
- state.lastAssertionIsQuantifiable = false;
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
+ pp$8.regexp_pattern = function(state) {
+ state.pos = 0;
+ state.lastIntValue = 0;
+ state.lastStringValue = "";
+ state.lastAssertionIsQuantifiable = false;
+ state.numCapturingParens = 0;
+ state.maxBackReference = 0;
+ state.groupNames.length = 0;
+ state.backReferenceNames.length = 0;
- // ^, $
- if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
- return true
- }
+ this.regexp_disjunction(state);
- // \b \B
- if (state.eat(0x5C /* \ */)) {
- if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
- return true
+ if (state.pos !== state.source.length) {
+ // Make the same messages as V8.
+ if (state.eat(0x29 /* ) */)) {
+ state.raise("Unmatched ')'");
+ }
+ if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) {
+ state.raise("Lone quantifier brackets");
+ }
}
- state.pos = start;
- }
+ if (state.maxBackReference > state.numCapturingParens) {
+ state.raise("Invalid escape");
+ }
+ for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) {
+ var name = list[i];
- // Lookahead / Lookbehind
- if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
- var lookbehind = false;
- if (this.options.ecmaVersion >= 9) {
- lookbehind = state.eat(0x3C /* < */);
+ if (state.groupNames.indexOf(name) === -1) {
+ state.raise("Invalid named capture referenced");
+ }
}
- if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
- this.regexp_disjunction(state);
- if (!state.eat(0x29 /* ) */)) {
- state.raise("Unterminated group");
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
+ pp$8.regexp_disjunction = function(state) {
+ this.regexp_alternative(state);
+ while (state.eat(0x7C /* | */)) {
+ this.regexp_alternative(state);
+ }
+
+ // Make the same message as V8.
+ if (this.regexp_eatQuantifier(state, true)) {
+ state.raise("Nothing to repeat");
+ }
+ if (state.eat(0x7B /* { */)) {
+ state.raise("Lone quantifier brackets");
+ }
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
+ pp$8.regexp_alternative = function(state) {
+ while (state.pos < state.source.length && this.regexp_eatTerm(state))
+ { }
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
+ pp$8.regexp_eatTerm = function(state) {
+ if (this.regexp_eatAssertion(state)) {
+ // Handle `QuantifiableAssertion Quantifier` alternative.
+ // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
+ // is a QuantifiableAssertion.
+ if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
+ // Make the same message as V8.
+ if (state.switchU) {
+ state.raise("Invalid quantifier");
+ }
}
- state.lastAssertionIsQuantifiable = !lookbehind;
return true
}
- }
- state.pos = start;
- return false
-};
+ if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
+ this.regexp_eatQuantifier(state);
+ return true
+ }
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
-pp$9.regexp_eatQuantifier = function(state, noError) {
- if ( noError === void 0 ) noError = false;
+ return false
+ };
- if (this.regexp_eatQuantifierPrefix(state, noError)) {
- state.eat(0x3F /* ? */);
- return true
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
-pp$9.regexp_eatQuantifierPrefix = function(state, noError) {
- return (
- state.eat(0x2A /* * */) ||
- state.eat(0x2B /* + */) ||
- state.eat(0x3F /* ? */) ||
- this.regexp_eatBracedQuantifier(state, noError)
- )
-};
-pp$9.regexp_eatBracedQuantifier = function(state, noError) {
- var start = state.pos;
- if (state.eat(0x7B /* { */)) {
- var min = 0, max = -1;
- if (this.regexp_eatDecimalDigits(state)) {
- min = state.lastIntValue;
- if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
- max = state.lastIntValue;
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
+ pp$8.regexp_eatAssertion = function(state) {
+ var start = state.pos;
+ state.lastAssertionIsQuantifiable = false;
+
+ // ^, $
+ if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) {
+ return true
+ }
+
+ // \b \B
+ if (state.eat(0x5C /* \ */)) {
+ if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) {
+ return true
}
- if (state.eat(0x7D /* } */)) {
- // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
- if (max !== -1 && max < min && !noError) {
- state.raise("numbers out of order in {} quantifier");
+ state.pos = start;
+ }
+
+ // Lookahead / Lookbehind
+ if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) {
+ var lookbehind = false;
+ if (this.options.ecmaVersion >= 9) {
+ lookbehind = state.eat(0x3C /* < */);
+ }
+ if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) {
+ this.regexp_disjunction(state);
+ if (!state.eat(0x29 /* ) */)) {
+ state.raise("Unterminated group");
}
+ state.lastAssertionIsQuantifiable = !lookbehind;
return true
}
}
- if (state.switchU && !noError) {
- state.raise("Incomplete quantifier");
- }
+
state.pos = start;
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
-pp$9.regexp_eatAtom = function(state) {
- return (
- this.regexp_eatPatternCharacters(state) ||
- state.eat(0x2E /* . */) ||
- this.regexp_eatReverseSolidusAtomEscape(state) ||
- this.regexp_eatCharacterClass(state) ||
- this.regexp_eatUncapturingGroup(state) ||
- this.regexp_eatCapturingGroup(state)
- )
-};
-pp$9.regexp_eatReverseSolidusAtomEscape = function(state) {
- var start = state.pos;
- if (state.eat(0x5C /* \ */)) {
- if (this.regexp_eatAtomEscape(state)) {
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
+ pp$8.regexp_eatQuantifier = function(state, noError) {
+ if ( noError === void 0 ) noError = false;
+
+ if (this.regexp_eatQuantifierPrefix(state, noError)) {
+ state.eat(0x3F /* ? */);
return true
}
- state.pos = start;
- }
- return false
-};
-pp$9.regexp_eatUncapturingGroup = function(state) {
- var start = state.pos;
- if (state.eat(0x28 /* ( */)) {
- if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
+ pp$8.regexp_eatQuantifierPrefix = function(state, noError) {
+ return (
+ state.eat(0x2A /* * */) ||
+ state.eat(0x2B /* + */) ||
+ state.eat(0x3F /* ? */) ||
+ this.regexp_eatBracedQuantifier(state, noError)
+ )
+ };
+ pp$8.regexp_eatBracedQuantifier = function(state, noError) {
+ var start = state.pos;
+ if (state.eat(0x7B /* { */)) {
+ var min = 0, max = -1;
+ if (this.regexp_eatDecimalDigits(state)) {
+ min = state.lastIntValue;
+ if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) {
+ max = state.lastIntValue;
+ }
+ if (state.eat(0x7D /* } */)) {
+ // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
+ if (max !== -1 && max < min && !noError) {
+ state.raise("numbers out of order in {} quantifier");
+ }
+ return true
+ }
+ }
+ if (state.switchU && !noError) {
+ state.raise("Incomplete quantifier");
+ }
+ state.pos = start;
+ }
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
+ pp$8.regexp_eatAtom = function(state) {
+ return (
+ this.regexp_eatPatternCharacters(state) ||
+ state.eat(0x2E /* . */) ||
+ this.regexp_eatReverseSolidusAtomEscape(state) ||
+ this.regexp_eatCharacterClass(state) ||
+ this.regexp_eatUncapturingGroup(state) ||
+ this.regexp_eatCapturingGroup(state)
+ )
+ };
+ pp$8.regexp_eatReverseSolidusAtomEscape = function(state) {
+ var start = state.pos;
+ if (state.eat(0x5C /* \ */)) {
+ if (this.regexp_eatAtomEscape(state)) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+ };
+ pp$8.regexp_eatUncapturingGroup = function(state) {
+ var start = state.pos;
+ if (state.eat(0x28 /* ( */)) {
+ if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) {
+ this.regexp_disjunction(state);
+ if (state.eat(0x29 /* ) */)) {
+ return true
+ }
+ state.raise("Unterminated group");
+ }
+ state.pos = start;
+ }
+ return false
+ };
+ pp$8.regexp_eatCapturingGroup = function(state) {
+ if (state.eat(0x28 /* ( */)) {
+ if (this.options.ecmaVersion >= 9) {
+ this.regexp_groupSpecifier(state);
+ } else if (state.current() === 0x3F /* ? */) {
+ state.raise("Invalid group");
+ }
this.regexp_disjunction(state);
if (state.eat(0x29 /* ) */)) {
+ state.numCapturingParens += 1;
return true
}
state.raise("Unterminated group");
}
- state.pos = start;
- }
- return false
-};
-pp$9.regexp_eatCapturingGroup = function(state) {
- if (state.eat(0x28 /* ( */)) {
- if (this.options.ecmaVersion >= 9) {
- this.regexp_groupSpecifier(state);
- } else if (state.current() === 0x3F /* ? */) {
- state.raise("Invalid group");
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
+ pp$8.regexp_eatExtendedAtom = function(state) {
+ return (
+ state.eat(0x2E /* . */) ||
+ this.regexp_eatReverseSolidusAtomEscape(state) ||
+ this.regexp_eatCharacterClass(state) ||
+ this.regexp_eatUncapturingGroup(state) ||
+ this.regexp_eatCapturingGroup(state) ||
+ this.regexp_eatInvalidBracedQuantifier(state) ||
+ this.regexp_eatExtendedPatternCharacter(state)
+ )
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
+ pp$8.regexp_eatInvalidBracedQuantifier = function(state) {
+ if (this.regexp_eatBracedQuantifier(state, true)) {
+ state.raise("Nothing to repeat");
}
- this.regexp_disjunction(state);
- if (state.eat(0x29 /* ) */)) {
- state.numCapturingParens += 1;
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
+ pp$8.regexp_eatSyntaxCharacter = function(state) {
+ var ch = state.current();
+ if (isSyntaxCharacter(ch)) {
+ state.lastIntValue = ch;
+ state.advance();
return true
}
- state.raise("Unterminated group");
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
-pp$9.regexp_eatExtendedAtom = function(state) {
- return (
- state.eat(0x2E /* . */) ||
- this.regexp_eatReverseSolidusAtomEscape(state) ||
- this.regexp_eatCharacterClass(state) ||
- this.regexp_eatUncapturingGroup(state) ||
- this.regexp_eatCapturingGroup(state) ||
- this.regexp_eatInvalidBracedQuantifier(state) ||
- this.regexp_eatExtendedPatternCharacter(state)
- )
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
-pp$9.regexp_eatInvalidBracedQuantifier = function(state) {
- if (this.regexp_eatBracedQuantifier(state, true)) {
- state.raise("Nothing to repeat");
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
-pp$9.regexp_eatSyntaxCharacter = function(state) {
- var ch = state.current();
- if (isSyntaxCharacter(ch)) {
- state.lastIntValue = ch;
- state.advance();
- return true
- }
- return false
-};
-function isSyntaxCharacter(ch) {
- return (
- ch === 0x24 /* $ */ ||
- ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
- ch === 0x2E /* . */ ||
- ch === 0x3F /* ? */ ||
- ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
- ch >= 0x7B /* { */ && ch <= 0x7D /* } */
- )
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
-// But eat eager.
-pp$9.regexp_eatPatternCharacters = function(state) {
- var start = state.pos;
- var ch = 0;
- while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
- state.advance();
- }
- return state.pos !== start
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
-pp$9.regexp_eatExtendedPatternCharacter = function(state) {
- var ch = state.current();
- if (
- ch !== -1 &&
- ch !== 0x24 /* $ */ &&
- !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
- ch !== 0x2E /* . */ &&
- ch !== 0x3F /* ? */ &&
- ch !== 0x5B /* [ */ &&
- ch !== 0x5E /* ^ */ &&
- ch !== 0x7C /* | */
- ) {
- state.advance();
- return true
- }
- return false
-};
-
-// GroupSpecifier[U] ::
-// [empty]
-// `?` GroupName[?U]
-pp$9.regexp_groupSpecifier = function(state) {
- if (state.eat(0x3F /* ? */)) {
- if (this.regexp_eatGroupName(state)) {
- if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
- state.raise("Duplicate capture group name");
- }
- state.groupNames.push(state.lastStringValue);
- return
+ return false
+ };
+ function isSyntaxCharacter(ch) {
+ return (
+ ch === 0x24 /* $ */ ||
+ ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ ||
+ ch === 0x2E /* . */ ||
+ ch === 0x3F /* ? */ ||
+ ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ ||
+ ch >= 0x7B /* { */ && ch <= 0x7D /* } */
+ )
+ }
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
+ // But eat eager.
+ pp$8.regexp_eatPatternCharacters = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
+ state.advance();
}
- state.raise("Invalid group");
- }
-};
-
-// GroupName[U] ::
-// `<` RegExpIdentifierName[?U] `>`
-// Note: this updates `state.lastStringValue` property with the eaten name.
-pp$9.regexp_eatGroupName = function(state) {
- state.lastStringValue = "";
- if (state.eat(0x3C /* < */)) {
- if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
+ return state.pos !== start
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
+ pp$8.regexp_eatExtendedPatternCharacter = function(state) {
+ var ch = state.current();
+ if (
+ ch !== -1 &&
+ ch !== 0x24 /* $ */ &&
+ !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) &&
+ ch !== 0x2E /* . */ &&
+ ch !== 0x3F /* ? */ &&
+ ch !== 0x5B /* [ */ &&
+ ch !== 0x5E /* ^ */ &&
+ ch !== 0x7C /* | */
+ ) {
+ state.advance();
return true
}
- state.raise("Invalid capture group name");
- }
- return false
-};
-
-// RegExpIdentifierName[U] ::
-// RegExpIdentifierStart[?U]
-// RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
-// Note: this updates `state.lastStringValue` property with the eaten name.
-pp$9.regexp_eatRegExpIdentifierName = function(state) {
- state.lastStringValue = "";
- if (this.regexp_eatRegExpIdentifierStart(state)) {
- state.lastStringValue += codePointToString$1(state.lastIntValue);
- while (this.regexp_eatRegExpIdentifierPart(state)) {
- state.lastStringValue += codePointToString$1(state.lastIntValue);
- }
- return true
- }
- return false
-};
-
-// RegExpIdentifierStart[U] ::
-// UnicodeIDStart
-// `$`
-// `_`
-// `\` RegExpUnicodeEscapeSequence[?U]
-pp$9.regexp_eatRegExpIdentifierStart = function(state) {
- var start = state.pos;
- var ch = state.current();
- state.advance();
-
- if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
- ch = state.lastIntValue;
- }
- if (isRegExpIdentifierStart(ch)) {
- state.lastIntValue = ch;
- return true
- }
+ return false
+ };
- state.pos = start;
- return false
-};
-function isRegExpIdentifierStart(ch) {
- return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
-}
-
-// RegExpIdentifierPart[U] ::
-// UnicodeIDContinue
-// `$`
-// `_`
-// `\` RegExpUnicodeEscapeSequence[?U]
-// <ZWNJ>
-// <ZWJ>
-pp$9.regexp_eatRegExpIdentifierPart = function(state) {
- var start = state.pos;
- var ch = state.current();
- state.advance();
-
- if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
- ch = state.lastIntValue;
- }
- if (isRegExpIdentifierPart(ch)) {
- state.lastIntValue = ch;
- return true
- }
+ // GroupSpecifier[U] ::
+ // [empty]
+ // `?` GroupName[?U]
+ pp$8.regexp_groupSpecifier = function(state) {
+ if (state.eat(0x3F /* ? */)) {
+ if (this.regexp_eatGroupName(state)) {
+ if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
+ state.raise("Duplicate capture group name");
+ }
+ state.groupNames.push(state.lastStringValue);
+ return
+ }
+ state.raise("Invalid group");
+ }
+ };
- state.pos = start;
- return false
-};
-function isRegExpIdentifierPart(ch) {
- return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
-pp$9.regexp_eatAtomEscape = function(state) {
- if (
- this.regexp_eatBackReference(state) ||
- this.regexp_eatCharacterClassEscape(state) ||
- this.regexp_eatCharacterEscape(state) ||
- (state.switchN && this.regexp_eatKGroupName(state))
- ) {
- return true
- }
- if (state.switchU) {
- // Make the same message as V8.
- if (state.current() === 0x63 /* c */) {
- state.raise("Invalid unicode escape");
+ // GroupName[U] ::
+ // `<` RegExpIdentifierName[?U] `>`
+ // Note: this updates `state.lastStringValue` property with the eaten name.
+ pp$8.regexp_eatGroupName = function(state) {
+ state.lastStringValue = "";
+ if (state.eat(0x3C /* < */)) {
+ if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) {
+ return true
+ }
+ state.raise("Invalid capture group name");
}
- state.raise("Invalid escape");
- }
- return false
-};
-pp$9.regexp_eatBackReference = function(state) {
- var start = state.pos;
- if (this.regexp_eatDecimalEscape(state)) {
- var n = state.lastIntValue;
- if (state.switchU) {
- // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
- if (n > state.maxBackReference) {
- state.maxBackReference = n;
+ return false
+ };
+
+ // RegExpIdentifierName[U] ::
+ // RegExpIdentifierStart[?U]
+ // RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
+ // Note: this updates `state.lastStringValue` property with the eaten name.
+ pp$8.regexp_eatRegExpIdentifierName = function(state) {
+ state.lastStringValue = "";
+ if (this.regexp_eatRegExpIdentifierStart(state)) {
+ state.lastStringValue += codePointToString(state.lastIntValue);
+ while (this.regexp_eatRegExpIdentifierPart(state)) {
+ state.lastStringValue += codePointToString(state.lastIntValue);
}
return true
}
- if (n <= state.numCapturingParens) {
+ return false
+ };
+
+ // RegExpIdentifierStart[U] ::
+ // UnicodeIDStart
+ // `$`
+ // `_`
+ // `\` RegExpUnicodeEscapeSequence[?U]
+ pp$8.regexp_eatRegExpIdentifierStart = function(state) {
+ var start = state.pos;
+ var ch = state.current();
+ state.advance();
+
+ if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+ ch = state.lastIntValue;
+ }
+ if (isRegExpIdentifierStart(ch)) {
+ state.lastIntValue = ch;
return true
}
+
state.pos = start;
- }
- return false
-};
-pp$9.regexp_eatKGroupName = function(state) {
- if (state.eat(0x6B /* k */)) {
- if (this.regexp_eatGroupName(state)) {
- state.backReferenceNames.push(state.lastStringValue);
- return true
+ return false
+ };
+ function isRegExpIdentifierStart(ch) {
+ return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */
+ }
+
+ // RegExpIdentifierPart[U] ::
+ // UnicodeIDContinue
+ // `$`
+ // `_`
+ // `\` RegExpUnicodeEscapeSequence[?U]
+ // <ZWNJ>
+ // <ZWJ>
+ pp$8.regexp_eatRegExpIdentifierPart = function(state) {
+ var start = state.pos;
+ var ch = state.current();
+ state.advance();
+
+ if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+ ch = state.lastIntValue;
}
- state.raise("Invalid named reference");
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
-pp$9.regexp_eatCharacterEscape = function(state) {
- return (
- this.regexp_eatControlEscape(state) ||
- this.regexp_eatCControlLetter(state) ||
- this.regexp_eatZero(state) ||
- this.regexp_eatHexEscapeSequence(state) ||
- this.regexp_eatRegExpUnicodeEscapeSequence(state) ||
- (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
- this.regexp_eatIdentityEscape(state)
- )
-};
-pp$9.regexp_eatCControlLetter = function(state) {
- var start = state.pos;
- if (state.eat(0x63 /* c */)) {
- if (this.regexp_eatControlLetter(state)) {
+ if (isRegExpIdentifierPart(ch)) {
+ state.lastIntValue = ch;
return true
}
+
state.pos = start;
+ return false
+ };
+ function isRegExpIdentifierPart(ch) {
+ return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */
}
- return false
-};
-pp$9.regexp_eatZero = function(state) {
- if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
- state.lastIntValue = 0;
- state.advance();
- return true
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
-pp$9.regexp_eatControlEscape = function(state) {
- var ch = state.current();
- if (ch === 0x74 /* t */) {
- state.lastIntValue = 0x09; /* \t */
- state.advance();
- return true
- }
- if (ch === 0x6E /* n */) {
- state.lastIntValue = 0x0A; /* \n */
- state.advance();
- return true
- }
- if (ch === 0x76 /* v */) {
- state.lastIntValue = 0x0B; /* \v */
- state.advance();
- return true
- }
- if (ch === 0x66 /* f */) {
- state.lastIntValue = 0x0C; /* \f */
- state.advance();
- return true
- }
- if (ch === 0x72 /* r */) {
- state.lastIntValue = 0x0D; /* \r */
- state.advance();
- return true
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
-pp$9.regexp_eatControlLetter = function(state) {
- var ch = state.current();
- if (isControlLetter(ch)) {
- state.lastIntValue = ch % 0x20;
- state.advance();
- return true
- }
- return false
-};
-function isControlLetter(ch) {
- return (
- (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
- (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
- )
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
-pp$9.regexp_eatRegExpUnicodeEscapeSequence = function(state) {
- var start = state.pos;
-
- if (state.eat(0x75 /* u */)) {
- if (this.regexp_eatFixedHexDigits(state, 4)) {
- var lead = state.lastIntValue;
- if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
- var leadSurrogateEnd = state.pos;
- if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
- var trail = state.lastIntValue;
- if (trail >= 0xDC00 && trail <= 0xDFFF) {
- state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
- return true
- }
- }
- state.pos = leadSurrogateEnd;
- state.lastIntValue = lead;
- }
- return true
- }
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
+ pp$8.regexp_eatAtomEscape = function(state) {
if (
- state.switchU &&
- state.eat(0x7B /* { */) &&
- this.regexp_eatHexDigits(state) &&
- state.eat(0x7D /* } */) &&
- isValidUnicode(state.lastIntValue)
+ this.regexp_eatBackReference(state) ||
+ this.regexp_eatCharacterClassEscape(state) ||
+ this.regexp_eatCharacterEscape(state) ||
+ (state.switchN && this.regexp_eatKGroupName(state))
) {
return true
}
if (state.switchU) {
- state.raise("Invalid unicode escape");
+ // Make the same message as V8.
+ if (state.current() === 0x63 /* c */) {
+ state.raise("Invalid unicode escape");
+ }
+ state.raise("Invalid escape");
}
- state.pos = start;
- }
+ return false
+ };
+ pp$8.regexp_eatBackReference = function(state) {
+ var start = state.pos;
+ if (this.regexp_eatDecimalEscape(state)) {
+ var n = state.lastIntValue;
+ if (state.switchU) {
+ // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
+ if (n > state.maxBackReference) {
+ state.maxBackReference = n;
+ }
+ return true
+ }
+ if (n <= state.numCapturingParens) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+ };
+ pp$8.regexp_eatKGroupName = function(state) {
+ if (state.eat(0x6B /* k */)) {
+ if (this.regexp_eatGroupName(state)) {
+ state.backReferenceNames.push(state.lastStringValue);
+ return true
+ }
+ state.raise("Invalid named reference");
+ }
+ return false
+ };
- return false
-};
-function isValidUnicode(ch) {
- return ch >= 0 && ch <= 0x10FFFF
-}
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
+ pp$8.regexp_eatCharacterEscape = function(state) {
+ return (
+ this.regexp_eatControlEscape(state) ||
+ this.regexp_eatCControlLetter(state) ||
+ this.regexp_eatZero(state) ||
+ this.regexp_eatHexEscapeSequence(state) ||
+ this.regexp_eatRegExpUnicodeEscapeSequence(state) ||
+ (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) ||
+ this.regexp_eatIdentityEscape(state)
+ )
+ };
+ pp$8.regexp_eatCControlLetter = function(state) {
+ var start = state.pos;
+ if (state.eat(0x63 /* c */)) {
+ if (this.regexp_eatControlLetter(state)) {
+ return true
+ }
+ state.pos = start;
+ }
+ return false
+ };
+ pp$8.regexp_eatZero = function(state) {
+ if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) {
+ state.lastIntValue = 0;
+ state.advance();
+ return true
+ }
+ return false
+ };
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
-pp$9.regexp_eatIdentityEscape = function(state) {
- if (state.switchU) {
- if (this.regexp_eatSyntaxCharacter(state)) {
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
+ pp$8.regexp_eatControlEscape = function(state) {
+ var ch = state.current();
+ if (ch === 0x74 /* t */) {
+ state.lastIntValue = 0x09; /* \t */
+ state.advance();
+ return true
+ }
+ if (ch === 0x6E /* n */) {
+ state.lastIntValue = 0x0A; /* \n */
+ state.advance();
+ return true
+ }
+ if (ch === 0x76 /* v */) {
+ state.lastIntValue = 0x0B; /* \v */
+ state.advance();
+ return true
+ }
+ if (ch === 0x66 /* f */) {
+ state.lastIntValue = 0x0C; /* \f */
+ state.advance();
return true
}
- if (state.eat(0x2F /* / */)) {
- state.lastIntValue = 0x2F; /* / */
+ if (ch === 0x72 /* r */) {
+ state.lastIntValue = 0x0D; /* \r */
+ state.advance();
return true
}
return false
- }
+ };
- var ch = state.current();
- if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
- state.lastIntValue = ch;
- state.advance();
- return true
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
+ pp$8.regexp_eatControlLetter = function(state) {
+ var ch = state.current();
+ if (isControlLetter(ch)) {
+ state.lastIntValue = ch % 0x20;
+ state.advance();
+ return true
+ }
+ return false
+ };
+ function isControlLetter(ch) {
+ return (
+ (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) ||
+ (ch >= 0x61 /* a */ && ch <= 0x7A /* z */)
+ )
+ }
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
+ pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state) {
+ var start = state.pos;
+
+ if (state.eat(0x75 /* u */)) {
+ if (this.regexp_eatFixedHexDigits(state, 4)) {
+ var lead = state.lastIntValue;
+ if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
+ var leadSurrogateEnd = state.pos;
+ if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) {
+ var trail = state.lastIntValue;
+ if (trail >= 0xDC00 && trail <= 0xDFFF) {
+ state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
+ return true
+ }
+ }
+ state.pos = leadSurrogateEnd;
+ state.lastIntValue = lead;
+ }
+ return true
+ }
+ if (
+ state.switchU &&
+ state.eat(0x7B /* { */) &&
+ this.regexp_eatHexDigits(state) &&
+ state.eat(0x7D /* } */) &&
+ isValidUnicode(state.lastIntValue)
+ ) {
+ return true
+ }
+ if (state.switchU) {
+ state.raise("Invalid unicode escape");
+ }
+ state.pos = start;
+ }
+
+ return false
+ };
+ function isValidUnicode(ch) {
+ return ch >= 0 && ch <= 0x10FFFF
}
- return false
-};
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
+ pp$8.regexp_eatIdentityEscape = function(state) {
+ if (state.switchU) {
+ if (this.regexp_eatSyntaxCharacter(state)) {
+ return true
+ }
+ if (state.eat(0x2F /* / */)) {
+ state.lastIntValue = 0x2F; /* / */
+ return true
+ }
+ return false
+ }
-// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
-pp$9.regexp_eatDecimalEscape = function(state) {
- state.lastIntValue = 0;
- var ch = state.current();
- if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
- do {
- state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
+ var ch = state.current();
+ if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) {
+ state.lastIntValue = ch;
state.advance();
- } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
- return true
- }
- return false
-};
+ return true
+ }
-// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
-pp$9.regexp_eatCharacterClassEscape = function(state) {
- var ch = state.current();
+ return false
+ };
- if (isCharacterClassEscape(ch)) {
- state.lastIntValue = -1;
- state.advance();
- return true
- }
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
+ pp$8.regexp_eatDecimalEscape = function(state) {
+ state.lastIntValue = 0;
+ var ch = state.current();
+ if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) {
+ do {
+ state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
+ state.advance();
+ } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */)
+ return true
+ }
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
+ pp$8.regexp_eatCharacterClassEscape = function(state) {
+ var ch = state.current();
+
+ if (isCharacterClassEscape(ch)) {
+ state.lastIntValue = -1;
+ state.advance();
+ return true
+ }
- if (
- state.switchU &&
- this.options.ecmaVersion >= 9 &&
- (ch === 0x50 /* P */ || ch === 0x70 /* p */)
- ) {
- state.lastIntValue = -1;
- state.advance();
if (
- state.eat(0x7B /* { */) &&
- this.regexp_eatUnicodePropertyValueExpression(state) &&
- state.eat(0x7D /* } */)
+ state.switchU &&
+ this.options.ecmaVersion >= 9 &&
+ (ch === 0x50 /* P */ || ch === 0x70 /* p */)
) {
- return true
+ state.lastIntValue = -1;
+ state.advance();
+ if (
+ state.eat(0x7B /* { */) &&
+ this.regexp_eatUnicodePropertyValueExpression(state) &&
+ state.eat(0x7D /* } */)
+ ) {
+ return true
+ }
+ state.raise("Invalid property name");
}
- state.raise("Invalid property name");
- }
- return false
-};
-function isCharacterClassEscape(ch) {
- return (
- ch === 0x64 /* d */ ||
- ch === 0x44 /* D */ ||
- ch === 0x73 /* s */ ||
- ch === 0x53 /* S */ ||
- ch === 0x77 /* w */ ||
- ch === 0x57 /* W */
- )
-}
-
-// UnicodePropertyValueExpression ::
-// UnicodePropertyName `=` UnicodePropertyValue
-// LoneUnicodePropertyNameOrValue
-pp$9.regexp_eatUnicodePropertyValueExpression = function(state) {
- var start = state.pos;
-
- // UnicodePropertyName `=` UnicodePropertyValue
- if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
- var name = state.lastStringValue;
- if (this.regexp_eatUnicodePropertyValue(state)) {
- var value = state.lastStringValue;
- this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
- return true
+ return false
+ };
+ function isCharacterClassEscape(ch) {
+ return (
+ ch === 0x64 /* d */ ||
+ ch === 0x44 /* D */ ||
+ ch === 0x73 /* s */ ||
+ ch === 0x53 /* S */ ||
+ ch === 0x77 /* w */ ||
+ ch === 0x57 /* W */
+ )
+ }
+
+ // UnicodePropertyValueExpression ::
+ // UnicodePropertyName `=` UnicodePropertyValue
+ // LoneUnicodePropertyNameOrValue
+ pp$8.regexp_eatUnicodePropertyValueExpression = function(state) {
+ var start = state.pos;
+
+ // UnicodePropertyName `=` UnicodePropertyValue
+ if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) {
+ var name = state.lastStringValue;
+ if (this.regexp_eatUnicodePropertyValue(state)) {
+ var value = state.lastStringValue;
+ this.regexp_validateUnicodePropertyNameAndValue(state, name, value);
+ return true
+ }
}
- }
- state.pos = start;
+ state.pos = start;
- // LoneUnicodePropertyNameOrValue
- if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
- var nameOrValue = state.lastStringValue;
- this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
- return true
- }
- return false
-};
-pp$9.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
- if (!data.hasOwnProperty(name) || data[name].indexOf(value) === -1) {
- state.raise("Invalid property name");
- }
-};
-pp$9.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
- if (data.$LONE.indexOf(nameOrValue) === -1) {
- state.raise("Invalid property name");
- }
-};
-
-// UnicodePropertyName ::
-// UnicodePropertyNameCharacters
-pp$9.regexp_eatUnicodePropertyName = function(state) {
- var ch = 0;
- state.lastStringValue = "";
- while (isUnicodePropertyNameCharacter(ch = state.current())) {
- state.lastStringValue += codePointToString$1(ch);
- state.advance();
- }
- return state.lastStringValue !== ""
-};
-function isUnicodePropertyNameCharacter(ch) {
- return isControlLetter(ch) || ch === 0x5F /* _ */
-}
-
-// UnicodePropertyValue ::
-// UnicodePropertyValueCharacters
-pp$9.regexp_eatUnicodePropertyValue = function(state) {
- var ch = 0;
- state.lastStringValue = "";
- while (isUnicodePropertyValueCharacter(ch = state.current())) {
- state.lastStringValue += codePointToString$1(ch);
- state.advance();
- }
- return state.lastStringValue !== ""
-};
-function isUnicodePropertyValueCharacter(ch) {
- return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
-}
-
-// LoneUnicodePropertyNameOrValue ::
-// UnicodePropertyValueCharacters
-pp$9.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
- return this.regexp_eatUnicodePropertyValue(state)
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
-pp$9.regexp_eatCharacterClass = function(state) {
- if (state.eat(0x5B /* [ */)) {
- state.eat(0x5E /* ^ */);
- this.regexp_classRanges(state);
- if (state.eat(0x5D /* [ */)) {
+ // LoneUnicodePropertyNameOrValue
+ if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
+ var nameOrValue = state.lastStringValue;
+ this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
return true
}
- // Unreachable since it threw "unterminated regular expression" error before.
- state.raise("Unterminated character class");
+ return false
+ };
+ pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) {
+ if (!has(state.unicodeProperties.nonBinary, name))
+ { state.raise("Invalid property name"); }
+ if (!state.unicodeProperties.nonBinary[name].test(value))
+ { state.raise("Invalid property value"); }
+ };
+ pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) {
+ if (!state.unicodeProperties.binary.test(nameOrValue))
+ { state.raise("Invalid property name"); }
+ };
+
+ // UnicodePropertyName ::
+ // UnicodePropertyNameCharacters
+ pp$8.regexp_eatUnicodePropertyName = function(state) {
+ var ch = 0;
+ state.lastStringValue = "";
+ while (isUnicodePropertyNameCharacter(ch = state.current())) {
+ state.lastStringValue += codePointToString(ch);
+ state.advance();
+ }
+ return state.lastStringValue !== ""
+ };
+ function isUnicodePropertyNameCharacter(ch) {
+ return isControlLetter(ch) || ch === 0x5F /* _ */
}
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
-// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
-// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
-pp$9.regexp_classRanges = function(state) {
- var this$1 = this;
-
- while (this.regexp_eatClassAtom(state)) {
- var left = state.lastIntValue;
- if (state.eat(0x2D /* - */) && this$1.regexp_eatClassAtom(state)) {
- var right = state.lastIntValue;
- if (state.switchU && (left === -1 || right === -1)) {
- state.raise("Invalid character class");
- }
- if (left !== -1 && right !== -1 && left > right) {
- state.raise("Range out of order in character class");
- }
+
+ // UnicodePropertyValue ::
+ // UnicodePropertyValueCharacters
+ pp$8.regexp_eatUnicodePropertyValue = function(state) {
+ var ch = 0;
+ state.lastStringValue = "";
+ while (isUnicodePropertyValueCharacter(ch = state.current())) {
+ state.lastStringValue += codePointToString(ch);
+ state.advance();
}
+ return state.lastStringValue !== ""
+ };
+ function isUnicodePropertyValueCharacter(ch) {
+ return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch)
}
-};
-// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
-// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
-pp$9.regexp_eatClassAtom = function(state) {
- var start = state.pos;
+ // LoneUnicodePropertyNameOrValue ::
+ // UnicodePropertyValueCharacters
+ pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) {
+ return this.regexp_eatUnicodePropertyValue(state)
+ };
- if (state.eat(0x5C /* \ */)) {
- if (this.regexp_eatClassEscape(state)) {
- return true
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
+ pp$8.regexp_eatCharacterClass = function(state) {
+ if (state.eat(0x5B /* [ */)) {
+ state.eat(0x5E /* ^ */);
+ this.regexp_classRanges(state);
+ if (state.eat(0x5D /* [ */)) {
+ return true
+ }
+ // Unreachable since it threw "unterminated regular expression" error before.
+ state.raise("Unterminated character class");
}
- if (state.switchU) {
- // Make the same message as V8.
- var ch$1 = state.current();
- if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
- state.raise("Invalid class escape");
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
+ pp$8.regexp_classRanges = function(state) {
+ while (this.regexp_eatClassAtom(state)) {
+ var left = state.lastIntValue;
+ if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) {
+ var right = state.lastIntValue;
+ if (state.switchU && (left === -1 || right === -1)) {
+ state.raise("Invalid character class");
+ }
+ if (left !== -1 && right !== -1 && left > right) {
+ state.raise("Range out of order in character class");
+ }
}
- state.raise("Invalid escape");
}
- state.pos = start;
- }
+ };
- var ch = state.current();
- if (ch !== 0x5D /* [ */) {
- state.lastIntValue = ch;
- state.advance();
- return true
- }
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
+ pp$8.regexp_eatClassAtom = function(state) {
+ var start = state.pos;
- return false
-};
+ if (state.eat(0x5C /* \ */)) {
+ if (this.regexp_eatClassEscape(state)) {
+ return true
+ }
+ if (state.switchU) {
+ // Make the same message as V8.
+ var ch$1 = state.current();
+ if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) {
+ state.raise("Invalid class escape");
+ }
+ state.raise("Invalid escape");
+ }
+ state.pos = start;
+ }
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
-pp$9.regexp_eatClassEscape = function(state) {
- var start = state.pos;
+ var ch = state.current();
+ if (ch !== 0x5D /* [ */) {
+ state.lastIntValue = ch;
+ state.advance();
+ return true
+ }
- if (state.eat(0x62 /* b */)) {
- state.lastIntValue = 0x08; /* <BS> */
- return true
- }
+ return false
+ };
- if (state.switchU && state.eat(0x2D /* - */)) {
- state.lastIntValue = 0x2D; /* - */
- return true
- }
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
+ pp$8.regexp_eatClassEscape = function(state) {
+ var start = state.pos;
- if (!state.switchU && state.eat(0x63 /* c */)) {
- if (this.regexp_eatClassControlLetter(state)) {
+ if (state.eat(0x62 /* b */)) {
+ state.lastIntValue = 0x08; /* <BS> */
return true
}
- state.pos = start;
- }
- return (
- this.regexp_eatCharacterClassEscape(state) ||
- this.regexp_eatCharacterEscape(state)
- )
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
-pp$9.regexp_eatClassControlLetter = function(state) {
- var ch = state.current();
- if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
- state.lastIntValue = ch % 0x20;
- state.advance();
- return true
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
-pp$9.regexp_eatHexEscapeSequence = function(state) {
- var start = state.pos;
- if (state.eat(0x78 /* x */)) {
- if (this.regexp_eatFixedHexDigits(state, 2)) {
+ if (state.switchU && state.eat(0x2D /* - */)) {
+ state.lastIntValue = 0x2D; /* - */
return true
}
- if (state.switchU) {
- state.raise("Invalid escape");
+
+ if (!state.switchU && state.eat(0x63 /* c */)) {
+ if (this.regexp_eatClassControlLetter(state)) {
+ return true
+ }
+ state.pos = start;
}
- state.pos = start;
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
-pp$9.regexp_eatDecimalDigits = function(state) {
- var start = state.pos;
- var ch = 0;
- state.lastIntValue = 0;
- while (isDecimalDigit(ch = state.current())) {
- state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
- state.advance();
- }
- return state.pos !== start
-};
-function isDecimalDigit(ch) {
- return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
-pp$9.regexp_eatHexDigits = function(state) {
- var start = state.pos;
- var ch = 0;
- state.lastIntValue = 0;
- while (isHexDigit(ch = state.current())) {
- state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
- state.advance();
- }
- return state.pos !== start
-};
-function isHexDigit(ch) {
- return (
- (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
- (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
- (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
- )
-}
-function hexToInt(ch) {
- if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
- return 10 + (ch - 0x41 /* A */)
+
+ return (
+ this.regexp_eatCharacterClassEscape(state) ||
+ this.regexp_eatCharacterEscape(state)
+ )
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
+ pp$8.regexp_eatClassControlLetter = function(state) {
+ var ch = state.current();
+ if (isDecimalDigit(ch) || ch === 0x5F /* _ */) {
+ state.lastIntValue = ch % 0x20;
+ state.advance();
+ return true
+ }
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
+ pp$8.regexp_eatHexEscapeSequence = function(state) {
+ var start = state.pos;
+ if (state.eat(0x78 /* x */)) {
+ if (this.regexp_eatFixedHexDigits(state, 2)) {
+ return true
+ }
+ if (state.switchU) {
+ state.raise("Invalid escape");
+ }
+ state.pos = start;
+ }
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
+ pp$8.regexp_eatDecimalDigits = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ state.lastIntValue = 0;
+ while (isDecimalDigit(ch = state.current())) {
+ state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */);
+ state.advance();
+ }
+ return state.pos !== start
+ };
+ function isDecimalDigit(ch) {
+ return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */
}
- if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
- return 10 + (ch - 0x61 /* a */)
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
+ pp$8.regexp_eatHexDigits = function(state) {
+ var start = state.pos;
+ var ch = 0;
+ state.lastIntValue = 0;
+ while (isHexDigit(ch = state.current())) {
+ state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
+ state.advance();
+ }
+ return state.pos !== start
+ };
+ function isHexDigit(ch) {
+ return (
+ (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) ||
+ (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) ||
+ (ch >= 0x61 /* a */ && ch <= 0x66 /* f */)
+ )
+ }
+ function hexToInt(ch) {
+ if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) {
+ return 10 + (ch - 0x41 /* A */)
+ }
+ if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) {
+ return 10 + (ch - 0x61 /* a */)
+ }
+ return ch - 0x30 /* 0 */
}
- return ch - 0x30 /* 0 */
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
-// Allows only 0-377(octal) i.e. 0-255(decimal).
-pp$9.regexp_eatLegacyOctalEscapeSequence = function(state) {
- if (this.regexp_eatOctalDigit(state)) {
- var n1 = state.lastIntValue;
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
+ // Allows only 0-377(octal) i.e. 0-255(decimal).
+ pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) {
if (this.regexp_eatOctalDigit(state)) {
- var n2 = state.lastIntValue;
- if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
- state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
+ var n1 = state.lastIntValue;
+ if (this.regexp_eatOctalDigit(state)) {
+ var n2 = state.lastIntValue;
+ if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
+ state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
+ } else {
+ state.lastIntValue = n1 * 8 + n2;
+ }
} else {
- state.lastIntValue = n1 * 8 + n2;
+ state.lastIntValue = n1;
}
- } else {
- state.lastIntValue = n1;
+ return true
}
- return true
- }
- return false
-};
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
-pp$9.regexp_eatOctalDigit = function(state) {
- var ch = state.current();
- if (isOctalDigit(ch)) {
- state.lastIntValue = ch - 0x30; /* 0 */
- state.advance();
- return true
- }
- state.lastIntValue = 0;
- return false
-};
-function isOctalDigit(ch) {
- return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
-// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
-// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
-pp$9.regexp_eatFixedHexDigits = function(state, length) {
- var start = state.pos;
- state.lastIntValue = 0;
- for (var i = 0; i < length; ++i) {
+ return false
+ };
+
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
+ pp$8.regexp_eatOctalDigit = function(state) {
var ch = state.current();
- if (!isHexDigit(ch)) {
- state.pos = start;
- return false
+ if (isOctalDigit(ch)) {
+ state.lastIntValue = ch - 0x30; /* 0 */
+ state.advance();
+ return true
}
- state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
- state.advance();
+ state.lastIntValue = 0;
+ return false
+ };
+ function isOctalDigit(ch) {
+ return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */
}
- return true
-};
-
-// Object type used to represent tokens. Note that normally, tokens
-// simply exist as properties on the parser object. This is only
-// used for the onToken callback and the external tokenizer.
-
-var Token = function Token(p) {
- this.type = p.type;
- this.value = p.value;
- this.start = p.start;
- this.end = p.end;
- if (p.options.locations)
- { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
- if (p.options.ranges)
- { this.range = [p.start, p.end]; }
-};
-
-// ## Tokenizer
-
-var pp$8 = Parser.prototype;
-
-// Move to the next token
-
-pp$8.next = function() {
- if (this.options.onToken)
- { this.options.onToken(new Token(this)); }
-
- this.lastTokEnd = this.end;
- this.lastTokStart = this.start;
- this.lastTokEndLoc = this.endLoc;
- this.lastTokStartLoc = this.startLoc;
- this.nextToken();
-};
-
-pp$8.getToken = function() {
- this.next();
- return new Token(this)
-};
-
-// If we're in an ES6 environment, make parsers iterable
-if (typeof Symbol !== "undefined")
- { pp$8[Symbol.iterator] = function() {
- var this$1 = this;
- return {
- next: function () {
- var token = this$1.getToken();
- return {
- done: token.type === types.eof,
- value: token
- }
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
+ // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
+ // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
+ pp$8.regexp_eatFixedHexDigits = function(state, length) {
+ var start = state.pos;
+ state.lastIntValue = 0;
+ for (var i = 0; i < length; ++i) {
+ var ch = state.current();
+ if (!isHexDigit(ch)) {
+ state.pos = start;
+ return false
}
+ state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
+ state.advance();
}
- }; }
+ return true
+ };
-// Toggle strict mode. Re-reads the next number or string to please
-// pedantic tests (`"use strict"; 010;` should fail).
+ // Object type used to represent tokens. Note that normally, tokens
+ // simply exist as properties on the parser object. This is only
+ // used for the onToken callback and the external tokenizer.
+
+ var Token = function Token(p) {
+ this.type = p.type;
+ this.value = p.value;
+ this.start = p.start;
+ this.end = p.end;
+ if (p.options.locations)
+ { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
+ if (p.options.ranges)
+ { this.range = [p.start, p.end]; }
+ };
-pp$8.curContext = function() {
- return this.context[this.context.length - 1]
-};
+ // ## Tokenizer
-// Read a single token, updating the parser object's token-related
-// properties.
+ var pp$9 = Parser.prototype;
-pp$8.nextToken = function() {
- var curContext = this.curContext();
- if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
+ // Move to the next token
- this.start = this.pos;
- if (this.options.locations) { this.startLoc = this.curPosition(); }
- if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
+ pp$9.next = function() {
+ if (this.options.onToken)
+ { this.options.onToken(new Token(this)); }
- if (curContext.override) { return curContext.override(this) }
- else { this.readToken(this.fullCharCodeAtPos()); }
-};
+ this.lastTokEnd = this.end;
+ this.lastTokStart = this.start;
+ this.lastTokEndLoc = this.endLoc;
+ this.lastTokStartLoc = this.startLoc;
+ this.nextToken();
+ };
-pp$8.readToken = function(code) {
- // Identifier or keyword. '\uXXXX' sequences are allowed in
- // identifiers, so '\' also dispatches to that.
- if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
- { return this.readWord() }
+ pp$9.getToken = function() {
+ this.next();
+ return new Token(this)
+ };
- return this.getTokenFromCode(code)
-};
+ // If we're in an ES6 environment, make parsers iterable
+ if (typeof Symbol !== "undefined")
+ { pp$9[Symbol.iterator] = function() {
+ var this$1 = this;
+
+ return {
+ next: function () {
+ var token = this$1.getToken();
+ return {
+ done: token.type === types.eof,
+ value: token
+ }
+ }
+ }
+ }; }
-pp$8.fullCharCodeAtPos = function() {
- var code = this.input.charCodeAt(this.pos);
- if (code <= 0xd7ff || code >= 0xe000) { return code }
- var next = this.input.charCodeAt(this.pos + 1);
- return (code << 10) + next - 0x35fdc00
-};
+ // Toggle strict mode. Re-reads the next number or string to please
+ // pedantic tests (`"use strict"; 010;` should fail).
-pp$8.skipBlockComment = function() {
- var this$1 = this;
+ pp$9.curContext = function() {
+ return this.context[this.context.length - 1]
+ };
- var startLoc = this.options.onComment && this.curPosition();
- var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
- if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
- this.pos = end + 2;
- if (this.options.locations) {
- lineBreakG.lastIndex = start;
- var match;
- while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
- ++this$1.curLine;
- this$1.lineStart = match.index + match[0].length;
- }
- }
- if (this.options.onComment)
- { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
- startLoc, this.curPosition()); }
-};
-
-pp$8.skipLineComment = function(startSkip) {
- var this$1 = this;
-
- var start = this.pos;
- var startLoc = this.options.onComment && this.curPosition();
- var ch = this.input.charCodeAt(this.pos += startSkip);
- while (this.pos < this.input.length && !isNewLine(ch)) {
- ch = this$1.input.charCodeAt(++this$1.pos);
- }
- if (this.options.onComment)
- { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
- startLoc, this.curPosition()); }
-};
+ // Read a single token, updating the parser object's token-related
+ // properties.
-// Called at the start of the parse and after every token. Skips
-// whitespace and comments, and.
+ pp$9.nextToken = function() {
+ var curContext = this.curContext();
+ if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }
-pp$8.skipSpace = function() {
- var this$1 = this;
+ this.start = this.pos;
+ if (this.options.locations) { this.startLoc = this.curPosition(); }
+ if (this.pos >= this.input.length) { return this.finishToken(types.eof) }
- loop: while (this.pos < this.input.length) {
- var ch = this$1.input.charCodeAt(this$1.pos);
- switch (ch) {
- case 32: case 160: // ' '
- ++this$1.pos;
- break
- case 13:
- if (this$1.input.charCodeAt(this$1.pos + 1) === 10) {
- ++this$1.pos;
- }
- case 10: case 8232: case 8233:
- ++this$1.pos;
- if (this$1.options.locations) {
- ++this$1.curLine;
- this$1.lineStart = this$1.pos;
+ if (curContext.override) { return curContext.override(this) }
+ else { this.readToken(this.fullCharCodeAtPos()); }
+ };
+
+ pp$9.readToken = function(code) {
+ // Identifier or keyword. '\uXXXX' sequences are allowed in
+ // identifiers, so '\' also dispatches to that.
+ if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
+ { return this.readWord() }
+
+ return this.getTokenFromCode(code)
+ };
+
+ pp$9.fullCharCodeAtPos = function() {
+ var code = this.input.charCodeAt(this.pos);
+ if (code <= 0xd7ff || code >= 0xe000) { return code }
+ var next = this.input.charCodeAt(this.pos + 1);
+ return (code << 10) + next - 0x35fdc00
+ };
+
+ pp$9.skipBlockComment = function() {
+ var startLoc = this.options.onComment && this.curPosition();
+ var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
+ if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
+ this.pos = end + 2;
+ if (this.options.locations) {
+ lineBreakG.lastIndex = start;
+ var match;
+ while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
+ ++this.curLine;
+ this.lineStart = match.index + match[0].length;
}
- break
- case 47: // '/'
- switch (this$1.input.charCodeAt(this$1.pos + 1)) {
- case 42: // '*'
- this$1.skipBlockComment();
+ }
+ if (this.options.onComment)
+ { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
+ startLoc, this.curPosition()); }
+ };
+
+ pp$9.skipLineComment = function(startSkip) {
+ var start = this.pos;
+ var startLoc = this.options.onComment && this.curPosition();
+ var ch = this.input.charCodeAt(this.pos += startSkip);
+ while (this.pos < this.input.length && !isNewLine(ch)) {
+ ch = this.input.charCodeAt(++this.pos);
+ }
+ if (this.options.onComment)
+ { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
+ startLoc, this.curPosition()); }
+ };
+
+ // Called at the start of the parse and after every token. Skips
+ // whitespace and comments, and.
+
+ pp$9.skipSpace = function() {
+ loop: while (this.pos < this.input.length) {
+ var ch = this.input.charCodeAt(this.pos);
+ switch (ch) {
+ case 32: case 160: // ' '
+ ++this.pos;
break
- case 47:
- this$1.skipLineComment(2);
+ case 13:
+ if (this.input.charCodeAt(this.pos + 1) === 10) {
+ ++this.pos;
+ }
+ case 10: case 8232: case 8233:
+ ++this.pos;
+ if (this.options.locations) {
+ ++this.curLine;
+ this.lineStart = this.pos;
+ }
+ break
+ case 47: // '/'
+ switch (this.input.charCodeAt(this.pos + 1)) {
+ case 42: // '*'
+ this.skipBlockComment();
+ break
+ case 47:
+ this.skipLineComment(2);
+ break
+ default:
+ break loop
+ }
break
default:
- break loop
+ if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
+ ++this.pos;
+ } else {
+ break loop
+ }
}
- break
- default:
- if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
- ++this$1.pos;
- } else {
- break loop
+ }
+ };
+
+ // Called at the end of every token. Sets `end`, `val`, and
+ // maintains `context` and `exprAllowed`, and skips the space after
+ // the token, so that the next one's `start` will point at the
+ // right position.
+
+ pp$9.finishToken = function(type, val) {
+ this.end = this.pos;
+ if (this.options.locations) { this.endLoc = this.curPosition(); }
+ var prevType = this.type;
+ this.type = type;
+ this.value = val;
+
+ this.updateContext(prevType);
+ };
+
+ // ### Token reading
+
+ // This is the function that is called to fetch the next token. It
+ // is somewhat obscure, because it works in character codes rather
+ // than characters, and because operator parsing has been inlined
+ // into it.
+ //
+ // All in the name of speed.
+ //
+ pp$9.readToken_dot = function() {
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next >= 48 && next <= 57) { return this.readNumber(true) }
+ var next2 = this.input.charCodeAt(this.pos + 2);
+ if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
+ this.pos += 3;
+ return this.finishToken(types.ellipsis)
+ } else {
+ ++this.pos;
+ return this.finishToken(types.dot)
+ }
+ };
+
+ pp$9.readToken_slash = function() { // '/'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.slash, 1)
+ };
+
+ pp$9.readToken_mult_modulo_exp = function(code) { // '%*'
+ var next = this.input.charCodeAt(this.pos + 1);
+ var size = 1;
+ var tokentype = code === 42 ? types.star : types.modulo;
+
+ // exponentiation operator ** and **=
+ if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
+ ++size;
+ tokentype = types.starstar;
+ next = this.input.charCodeAt(this.pos + 2);
+ }
+
+ if (next === 61) { return this.finishOp(types.assign, size + 1) }
+ return this.finishOp(tokentype, size)
+ };
+
+ pp$9.readToken_pipe_amp = function(code) { // '|&'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
+ };
+
+ pp$9.readToken_caret = function() { // '^'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.bitwiseXOR, 1)
+ };
+
+ pp$9.readToken_plus_min = function(code) { // '+-'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === code) {
+ if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
+ (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
+ // A `-->` line comment
+ this.skipLineComment(3);
+ this.skipSpace();
+ return this.nextToken()
}
+ return this.finishOp(types.incDec, 2)
}
- }
-};
-
-// Called at the end of every token. Sets `end`, `val`, and
-// maintains `context` and `exprAllowed`, and skips the space after
-// the token, so that the next one's `start` will point at the
-// right position.
-
-pp$8.finishToken = function(type, val) {
- this.end = this.pos;
- if (this.options.locations) { this.endLoc = this.curPosition(); }
- var prevType = this.type;
- this.type = type;
- this.value = val;
-
- this.updateContext(prevType);
-};
-
-// ### Token reading
-
-// This is the function that is called to fetch the next token. It
-// is somewhat obscure, because it works in character codes rather
-// than characters, and because operator parsing has been inlined
-// into it.
-//
-// All in the name of speed.
-//
-pp$8.readToken_dot = function() {
- var next = this.input.charCodeAt(this.pos + 1);
- if (next >= 48 && next <= 57) { return this.readNumber(true) }
- var next2 = this.input.charCodeAt(this.pos + 2);
- if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
- this.pos += 3;
- return this.finishToken(types.ellipsis)
- } else {
- ++this.pos;
- return this.finishToken(types.dot)
- }
-};
-
-pp$8.readToken_slash = function() { // '/'
- var next = this.input.charCodeAt(this.pos + 1);
- if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
- if (next === 61) { return this.finishOp(types.assign, 2) }
- return this.finishOp(types.slash, 1)
-};
-
-pp$8.readToken_mult_modulo_exp = function(code) { // '%*'
- var next = this.input.charCodeAt(this.pos + 1);
- var size = 1;
- var tokentype = code === 42 ? types.star : types.modulo;
-
- // exponentiation operator ** and **=
- if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
- ++size;
- tokentype = types.starstar;
- next = this.input.charCodeAt(this.pos + 2);
- }
+ if (next === 61) { return this.finishOp(types.assign, 2) }
+ return this.finishOp(types.plusMin, 1)
+ };
- if (next === 61) { return this.finishOp(types.assign, size + 1) }
- return this.finishOp(tokentype, size)
-};
-
-pp$8.readToken_pipe_amp = function(code) { // '|&'
- var next = this.input.charCodeAt(this.pos + 1);
- if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
- if (next === 61) { return this.finishOp(types.assign, 2) }
- return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
-};
-
-pp$8.readToken_caret = function() { // '^'
- var next = this.input.charCodeAt(this.pos + 1);
- if (next === 61) { return this.finishOp(types.assign, 2) }
- return this.finishOp(types.bitwiseXOR, 1)
-};
-
-pp$8.readToken_plus_min = function(code) { // '+-'
- var next = this.input.charCodeAt(this.pos + 1);
- if (next === code) {
- if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 &&
- (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
- // A `-->` line comment
- this.skipLineComment(3);
+ pp$9.readToken_lt_gt = function(code) { // '<>'
+ var next = this.input.charCodeAt(this.pos + 1);
+ var size = 1;
+ if (next === code) {
+ size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
+ if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
+ return this.finishOp(types.bitShift, size)
+ }
+ if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
+ this.input.charCodeAt(this.pos + 3) === 45) {
+ // `<!--`, an XML-style comment that should be interpreted as a line comment
+ this.skipLineComment(4);
this.skipSpace();
return this.nextToken()
}
- return this.finishOp(types.incDec, 2)
- }
- if (next === 61) { return this.finishOp(types.assign, 2) }
- return this.finishOp(types.plusMin, 1)
-};
-
-pp$8.readToken_lt_gt = function(code) { // '<>'
- var next = this.input.charCodeAt(this.pos + 1);
- var size = 1;
- if (next === code) {
- size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
- if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
- return this.finishOp(types.bitShift, size)
- }
- if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 &&
- this.input.charCodeAt(this.pos + 3) === 45) {
- // `<!--`, an XML-style comment that should be interpreted as a line comment
- this.skipLineComment(4);
- this.skipSpace();
- return this.nextToken()
- }
- if (next === 61) { size = 2; }
- return this.finishOp(types.relational, size)
-};
-
-pp$8.readToken_eq_excl = function(code) { // '=!'
- var next = this.input.charCodeAt(this.pos + 1);
- if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
- if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
- this.pos += 2;
- return this.finishToken(types.arrow)
- }
- return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
-};
-
-pp$8.getTokenFromCode = function(code) {
- switch (code) {
- // The interpretation of a dot depends on whether it is followed
- // by a digit or another two dots.
- case 46: // '.'
- return this.readToken_dot()
-
- // Punctuation tokens.
- case 40: ++this.pos; return this.finishToken(types.parenL)
- case 41: ++this.pos; return this.finishToken(types.parenR)
- case 59: ++this.pos; return this.finishToken(types.semi)
- case 44: ++this.pos; return this.finishToken(types.comma)
- case 91: ++this.pos; return this.finishToken(types.bracketL)
- case 93: ++this.pos; return this.finishToken(types.bracketR)
- case 123: ++this.pos; return this.finishToken(types.braceL)
- case 125: ++this.pos; return this.finishToken(types.braceR)
- case 58: ++this.pos; return this.finishToken(types.colon)
- case 63: ++this.pos; return this.finishToken(types.question)
-
- case 96: // '`'
- if (this.options.ecmaVersion < 6) { break }
- ++this.pos;
- return this.finishToken(types.backQuote)
+ if (next === 61) { size = 2; }
+ return this.finishOp(types.relational, size)
+ };
- case 48: // '0'
+ pp$9.readToken_eq_excl = function(code) { // '=!'
var next = this.input.charCodeAt(this.pos + 1);
- if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
- if (this.options.ecmaVersion >= 6) {
- if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
- if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
+ if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
+ if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
+ this.pos += 2;
+ return this.finishToken(types.arrow)
}
+ return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
+ };
- // Anything else beginning with a digit is an integer, octal
- // number, or float.
- case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
- return this.readNumber(false)
+ pp$9.getTokenFromCode = function(code) {
+ switch (code) {
+ // The interpretation of a dot depends on whether it is followed
+ // by a digit or another two dots.
+ case 46: // '.'
+ return this.readToken_dot()
+
+ // Punctuation tokens.
+ case 40: ++this.pos; return this.finishToken(types.parenL)
+ case 41: ++this.pos; return this.finishToken(types.parenR)
+ case 59: ++this.pos; return this.finishToken(types.semi)
+ case 44: ++this.pos; return this.finishToken(types.comma)
+ case 91: ++this.pos; return this.finishToken(types.bracketL)
+ case 93: ++this.pos; return this.finishToken(types.bracketR)
+ case 123: ++this.pos; return this.finishToken(types.braceL)
+ case 125: ++this.pos; return this.finishToken(types.braceR)
+ case 58: ++this.pos; return this.finishToken(types.colon)
+ case 63: ++this.pos; return this.finishToken(types.question)
+
+ case 96: // '`'
+ if (this.options.ecmaVersion < 6) { break }
+ ++this.pos;
+ return this.finishToken(types.backQuote)
+
+ case 48: // '0'
+ var next = this.input.charCodeAt(this.pos + 1);
+ if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
+ if (this.options.ecmaVersion >= 6) {
+ if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
+ if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
+ }
- // Quotes produce strings.
- case 34: case 39: // '"', "'"
- return this.readString(code)
+ // Anything else beginning with a digit is an integer, octal
+ // number, or float.
+ case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
+ return this.readNumber(false)
- // Operators are parsed inline in tiny state machines. '=' (61) is
- // often referred to. `finishOp` simply skips the amount of
- // characters it is given as second argument, and returns a token
- // of the type given by its first argument.
+ // Quotes produce strings.
+ case 34: case 39: // '"', "'"
+ return this.readString(code)
- case 47: // '/'
- return this.readToken_slash()
+ // Operators are parsed inline in tiny state machines. '=' (61) is
+ // often referred to. `finishOp` simply skips the amount of
+ // characters it is given as second argument, and returns a token
+ // of the type given by its first argument.
- case 37: case 42: // '%*'
- return this.readToken_mult_modulo_exp(code)
+ case 47: // '/'
+ return this.readToken_slash()
- case 124: case 38: // '|&'
- return this.readToken_pipe_amp(code)
+ case 37: case 42: // '%*'
+ return this.readToken_mult_modulo_exp(code)
- case 94: // '^'
- return this.readToken_caret()
+ case 124: case 38: // '|&'
+ return this.readToken_pipe_amp(code)
- case 43: case 45: // '+-'
- return this.readToken_plus_min(code)
+ case 94: // '^'
+ return this.readToken_caret()
- case 60: case 62: // '<>'
- return this.readToken_lt_gt(code)
+ case 43: case 45: // '+-'
+ return this.readToken_plus_min(code)
- case 61: case 33: // '=!'
- return this.readToken_eq_excl(code)
+ case 60: case 62: // '<>'
+ return this.readToken_lt_gt(code)
- case 126: // '~'
- return this.finishOp(types.prefix, 1)
- }
+ case 61: case 33: // '=!'
+ return this.readToken_eq_excl(code)
- this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
-};
-
-pp$8.finishOp = function(type, size) {
- var str = this.input.slice(this.pos, this.pos + size);
- this.pos += size;
- return this.finishToken(type, str)
-};
-
-pp$8.readRegexp = function() {
- var this$1 = this;
-
- var escaped, inClass, start = this.pos;
- for (;;) {
- if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); }
- var ch = this$1.input.charAt(this$1.pos);
- if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); }
- if (!escaped) {
- if (ch === "[") { inClass = true; }
- else if (ch === "]" && inClass) { inClass = false; }
- else if (ch === "/" && !inClass) { break }
- escaped = ch === "\\";
- } else { escaped = false; }
- ++this$1.pos;
- }
- var pattern = this.input.slice(start, this.pos);
- ++this.pos;
- var flagsStart = this.pos;
- var flags = this.readWord1();
- if (this.containsEsc) { this.unexpected(flagsStart); }
-
- // Validate pattern
- var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
- state.reset(start, pattern, flags);
- this.validateRegExpFlags(state);
- this.validateRegExpPattern(state);
-
- // Create Literal#value property value.
- var value = null;
- try {
- value = new RegExp(pattern, flags);
- } catch (e) {
- // ESTree requires null if it failed to instantiate RegExp object.
- // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
- }
+ case 126: // '~'
+ return this.finishOp(types.prefix, 1)
+ }
- return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
-};
-
-// Read an integer in the given radix. Return null if zero digits
-// were read, the integer value otherwise. When `len` is given, this
-// will return `null` unless the integer has exactly `len` digits.
-
-pp$8.readInt = function(radix, len) {
- var this$1 = this;
-
- var start = this.pos, total = 0;
- for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
- var code = this$1.input.charCodeAt(this$1.pos), val = (void 0);
- if (code >= 97) { val = code - 97 + 10; } // a
- else if (code >= 65) { val = code - 65 + 10; } // A
- else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
- else { val = Infinity; }
- if (val >= radix) { break }
- ++this$1.pos;
- total = total * radix + val;
- }
- if (this.pos === start || len != null && this.pos - start !== len) { return null }
-
- return total
-};
-
-pp$8.readRadixNumber = function(radix) {
- this.pos += 2; // 0x
- var val = this.readInt(radix);
- if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
- if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
- return this.finishToken(types.num, val)
-};
-
-// Read an integer, octal integer, or floating-point number.
-
-pp$8.readNumber = function(startsWithDot) {
- var start = this.pos;
- if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
- var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
- if (octal && this.strict) { this.raise(start, "Invalid number"); }
- if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
- var next = this.input.charCodeAt(this.pos);
- if (next === 46 && !octal) { // '.'
+ this.raise(this.pos, "Unexpected character '" + codePointToString$1(code) + "'");
+ };
+
+ pp$9.finishOp = function(type, size) {
+ var str = this.input.slice(this.pos, this.pos + size);
+ this.pos += size;
+ return this.finishToken(type, str)
+ };
+
+ pp$9.readRegexp = function() {
+ var escaped, inClass, start = this.pos;
+ for (;;) {
+ if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); }
+ var ch = this.input.charAt(this.pos);
+ if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); }
+ if (!escaped) {
+ if (ch === "[") { inClass = true; }
+ else if (ch === "]" && inClass) { inClass = false; }
+ else if (ch === "/" && !inClass) { break }
+ escaped = ch === "\\";
+ } else { escaped = false; }
+ ++this.pos;
+ }
+ var pattern = this.input.slice(start, this.pos);
++this.pos;
- this.readInt(10);
- next = this.input.charCodeAt(this.pos);
- }
- if ((next === 69 || next === 101) && !octal) { // 'eE'
- next = this.input.charCodeAt(++this.pos);
- if (next === 43 || next === 45) { ++this.pos; } // '+-'
- if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
- }
- if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
+ var flagsStart = this.pos;
+ var flags = this.readWord1();
+ if (this.containsEsc) { this.unexpected(flagsStart); }
+
+ // Validate pattern
+ var state = this.regexpState || (this.regexpState = new RegExpValidationState(this));
+ state.reset(start, pattern, flags);
+ this.validateRegExpFlags(state);
+ this.validateRegExpPattern(state);
+
+ // Create Literal#value property value.
+ var value = null;
+ try {
+ value = new RegExp(pattern, flags);
+ } catch (e) {
+ // ESTree requires null if it failed to instantiate RegExp object.
+ // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
+ }
- var str = this.input.slice(start, this.pos);
- var val = octal ? parseInt(str, 8) : parseFloat(str);
- return this.finishToken(types.num, val)
-};
+ return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value})
+ };
-// Read a string value, interpreting backslash-escapes.
+ // Read an integer in the given radix. Return null if zero digits
+ // were read, the integer value otherwise. When `len` is given, this
+ // will return `null` unless the integer has exactly `len` digits.
+
+ pp$9.readInt = function(radix, len) {
+ var start = this.pos, total = 0;
+ for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
+ var code = this.input.charCodeAt(this.pos), val = (void 0);
+ if (code >= 97) { val = code - 97 + 10; } // a
+ else if (code >= 65) { val = code - 65 + 10; } // A
+ else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
+ else { val = Infinity; }
+ if (val >= radix) { break }
+ ++this.pos;
+ total = total * radix + val;
+ }
+ if (this.pos === start || len != null && this.pos - start !== len) { return null }
-pp$8.readCodePoint = function() {
- var ch = this.input.charCodeAt(this.pos), code;
+ return total
+ };
- if (ch === 123) { // '{'
- if (this.options.ecmaVersion < 6) { this.unexpected(); }
- var codePos = ++this.pos;
- code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
- ++this.pos;
- if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
- } else {
- code = this.readHexChar(4);
- }
- return code
-};
-
-function codePointToString(code) {
- // UTF-16 Decoding
- if (code <= 0xFFFF) { return String.fromCharCode(code) }
- code -= 0x10000;
- return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
-}
-
-pp$8.readString = function(quote) {
- var this$1 = this;
-
- var out = "", chunkStart = ++this.pos;
- for (;;) {
- if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); }
- var ch = this$1.input.charCodeAt(this$1.pos);
- if (ch === quote) { break }
- if (ch === 92) { // '\'
- out += this$1.input.slice(chunkStart, this$1.pos);
- out += this$1.readEscapedChar(false);
- chunkStart = this$1.pos;
- } else {
- if (isNewLine(ch, this$1.options.ecmaVersion >= 10)) { this$1.raise(this$1.start, "Unterminated string constant"); }
- ++this$1.pos;
+ pp$9.readRadixNumber = function(radix) {
+ var start = this.pos;
+ this.pos += 2; // 0x
+ var val = this.readInt(radix);
+ if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
+ if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
+ val = typeof BigInt !== "undefined" ? BigInt(this.input.slice(start, this.pos)) : null;
+ ++this.pos;
+ } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
+ return this.finishToken(types.num, val)
+ };
+
+ // Read an integer, octal integer, or floating-point number.
+
+ pp$9.readNumber = function(startsWithDot) {
+ var start = this.pos;
+ if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
+ var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
+ if (octal && this.strict) { this.raise(start, "Invalid number"); }
+ if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; }
+ var next = this.input.charCodeAt(this.pos);
+ if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
+ var str$1 = this.input.slice(start, this.pos);
+ var val$1 = typeof BigInt !== "undefined" ? BigInt(str$1) : null;
+ ++this.pos;
+ if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
+ return this.finishToken(types.num, val$1)
}
- }
- out += this.input.slice(chunkStart, this.pos++);
- return this.finishToken(types.string, out)
-};
+ if (next === 46 && !octal) { // '.'
+ ++this.pos;
+ this.readInt(10);
+ next = this.input.charCodeAt(this.pos);
+ }
+ if ((next === 69 || next === 101) && !octal) { // 'eE'
+ next = this.input.charCodeAt(++this.pos);
+ if (next === 43 || next === 45) { ++this.pos; } // '+-'
+ if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
+ }
+ if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
+
+ var str = this.input.slice(start, this.pos);
+ var val = octal ? parseInt(str, 8) : parseFloat(str);
+ return this.finishToken(types.num, val)
+ };
-// Reads template string tokens.
+ // Read a string value, interpreting backslash-escapes.
-var INVALID_TEMPLATE_ESCAPE_ERROR = {};
+ pp$9.readCodePoint = function() {
+ var ch = this.input.charCodeAt(this.pos), code;
-pp$8.tryReadTemplateToken = function() {
- this.inTemplateElement = true;
- try {
- this.readTmplToken();
- } catch (err) {
- if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
- this.readInvalidTemplateToken();
+ if (ch === 123) { // '{'
+ if (this.options.ecmaVersion < 6) { this.unexpected(); }
+ var codePos = ++this.pos;
+ code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
+ ++this.pos;
+ if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
} else {
- throw err
+ code = this.readHexChar(4);
}
- }
+ return code
+ };
- this.inTemplateElement = false;
-};
+ function codePointToString$1(code) {
+ // UTF-16 Decoding
+ if (code <= 0xFFFF) { return String.fromCharCode(code) }
+ code -= 0x10000;
+ return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
+ }
+
+ pp$9.readString = function(quote) {
+ var out = "", chunkStart = ++this.pos;
+ for (;;) {
+ if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); }
+ var ch = this.input.charCodeAt(this.pos);
+ if (ch === quote) { break }
+ if (ch === 92) { // '\'
+ out += this.input.slice(chunkStart, this.pos);
+ out += this.readEscapedChar(false);
+ chunkStart = this.pos;
+ } else {
+ if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); }
+ ++this.pos;
+ }
+ }
+ out += this.input.slice(chunkStart, this.pos++);
+ return this.finishToken(types.string, out)
+ };
-pp$8.invalidStringToken = function(position, message) {
- if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
- throw INVALID_TEMPLATE_ESCAPE_ERROR
- } else {
- this.raise(position, message);
- }
-};
-
-pp$8.readTmplToken = function() {
- var this$1 = this;
-
- var out = "", chunkStart = this.pos;
- for (;;) {
- if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); }
- var ch = this$1.input.charCodeAt(this$1.pos);
- if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${'
- if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) {
- if (ch === 36) {
- this$1.pos += 2;
- return this$1.finishToken(types.dollarBraceL)
- } else {
- ++this$1.pos;
- return this$1.finishToken(types.backQuote)
+ // Reads template string tokens.
+
+ var INVALID_TEMPLATE_ESCAPE_ERROR = {};
+
+ pp$9.tryReadTemplateToken = function() {
+ this.inTemplateElement = true;
+ try {
+ this.readTmplToken();
+ } catch (err) {
+ if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
+ this.readInvalidTemplateToken();
+ } else {
+ throw err
+ }
+ }
+
+ this.inTemplateElement = false;
+ };
+
+ pp$9.invalidStringToken = function(position, message) {
+ if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
+ throw INVALID_TEMPLATE_ESCAPE_ERROR
+ } else {
+ this.raise(position, message);
+ }
+ };
+
+ pp$9.readTmplToken = function() {
+ var out = "", chunkStart = this.pos;
+ for (;;) {
+ if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); }
+ var ch = this.input.charCodeAt(this.pos);
+ if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${'
+ if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) {
+ if (ch === 36) {
+ this.pos += 2;
+ return this.finishToken(types.dollarBraceL)
+ } else {
+ ++this.pos;
+ return this.finishToken(types.backQuote)
+ }
}
+ out += this.input.slice(chunkStart, this.pos);
+ return this.finishToken(types.template, out)
}
- out += this$1.input.slice(chunkStart, this$1.pos);
- return this$1.finishToken(types.template, out)
- }
- if (ch === 92) { // '\'
- out += this$1.input.slice(chunkStart, this$1.pos);
- out += this$1.readEscapedChar(true);
- chunkStart = this$1.pos;
- } else if (isNewLine(ch)) {
- out += this$1.input.slice(chunkStart, this$1.pos);
- ++this$1.pos;
- switch (ch) {
- case 13:
- if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; }
- case 10:
- out += "\n";
- break
- default:
- out += String.fromCharCode(ch);
+ if (ch === 92) { // '\'
+ out += this.input.slice(chunkStart, this.pos);
+ out += this.readEscapedChar(true);
+ chunkStart = this.pos;
+ } else if (isNewLine(ch)) {
+ out += this.input.slice(chunkStart, this.pos);
+ ++this.pos;
+ switch (ch) {
+ case 13:
+ if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; }
+ case 10:
+ out += "\n";
+ break
+ default:
+ out += String.fromCharCode(ch);
+ break
+ }
+ if (this.options.locations) {
+ ++this.curLine;
+ this.lineStart = this.pos;
+ }
+ chunkStart = this.pos;
+ } else {
+ ++this.pos;
+ }
+ }
+ };
+
+ // Reads a template token to search for the end, without validating any escape sequences
+ pp$9.readInvalidTemplateToken = function() {
+ for (; this.pos < this.input.length; this.pos++) {
+ switch (this.input[this.pos]) {
+ case "\\":
+ ++this.pos;
break
+
+ case "$":
+ if (this.input[this.pos + 1] !== "{") {
+ break
+ }
+ // falls through
+
+ case "`":
+ return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos))
+
+ // no default
+ }
+ }
+ this.raise(this.start, "Unterminated template");
+ };
+
+ // Used to read escaped characters
+
+ pp$9.readEscapedChar = function(inTemplate) {
+ var ch = this.input.charCodeAt(++this.pos);
+ ++this.pos;
+ switch (ch) {
+ case 110: return "\n" // 'n' -> '\n'
+ case 114: return "\r" // 'r' -> '\r'
+ case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
+ case 117: return codePointToString$1(this.readCodePoint()) // 'u'
+ case 116: return "\t" // 't' -> '\t'
+ case 98: return "\b" // 'b' -> '\b'
+ case 118: return "\u000b" // 'v' -> '\u000b'
+ case 102: return "\f" // 'f' -> '\f'
+ case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
+ case 10: // ' \n'
+ if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
+ return ""
+ default:
+ if (ch >= 48 && ch <= 55) {
+ var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
+ var octal = parseInt(octalStr, 8);
+ if (octal > 255) {
+ octalStr = octalStr.slice(0, -1);
+ octal = parseInt(octalStr, 8);
+ }
+ this.pos += octalStr.length - 1;
+ ch = this.input.charCodeAt(this.pos);
+ if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
+ this.invalidStringToken(
+ this.pos - 1 - octalStr.length,
+ inTemplate
+ ? "Octal literal in template string"
+ : "Octal literal in strict mode"
+ );
+ }
+ return String.fromCharCode(octal)
}
- if (this$1.options.locations) {
- ++this$1.curLine;
- this$1.lineStart = this$1.pos;
+ if (isNewLine(ch)) {
+ // Unicode new line characters after \ get removed from output in both
+ // template literals and strings
+ return ""
}
- chunkStart = this$1.pos;
- } else {
- ++this$1.pos;
+ return String.fromCharCode(ch)
}
- }
-};
+ };
-// Reads a template token to search for the end, without validating any escape sequences
-pp$8.readInvalidTemplateToken = function() {
- var this$1 = this;
+ // Used to read character escape sequences ('\x', '\u', '\U').
- for (; this.pos < this.input.length; this.pos++) {
- switch (this$1.input[this$1.pos]) {
- case "\\":
- ++this$1.pos;
- break
+ pp$9.readHexChar = function(len) {
+ var codePos = this.pos;
+ var n = this.readInt(16, len);
+ if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
+ return n
+ };
- case "$":
- if (this$1.input[this$1.pos + 1] !== "{") {
+ // Read an identifier, and return it as a string. Sets `this.containsEsc`
+ // to whether the word contained a '\u' escape.
+ //
+ // Incrementally adds only escaped chars, adding other chunks as-is
+ // as a micro-optimization.
+
+ pp$9.readWord1 = function() {
+ this.containsEsc = false;
+ var word = "", first = true, chunkStart = this.pos;
+ var astral = this.options.ecmaVersion >= 6;
+ while (this.pos < this.input.length) {
+ var ch = this.fullCharCodeAtPos();
+ if (isIdentifierChar(ch, astral)) {
+ this.pos += ch <= 0xffff ? 1 : 2;
+ } else if (ch === 92) { // "\"
+ this.containsEsc = true;
+ word += this.input.slice(chunkStart, this.pos);
+ var escStart = this.pos;
+ if (this.input.charCodeAt(++this.pos) !== 117) // "u"
+ { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); }
+ ++this.pos;
+ var esc = this.readCodePoint();
+ if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
+ { this.invalidStringToken(escStart, "Invalid Unicode escape"); }
+ word += codePointToString$1(esc);
+ chunkStart = this.pos;
+ } else {
break
}
- // falls through
+ first = false;
+ }
+ return word + this.input.slice(chunkStart, this.pos)
+ };
- case "`":
- return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos))
+ // Read an identifier or keyword token. Will check for reserved
+ // words when necessary.
- // no default
- }
- }
- this.raise(this.start, "Unterminated template");
-};
-
-// Used to read escaped characters
-
-pp$8.readEscapedChar = function(inTemplate) {
- var ch = this.input.charCodeAt(++this.pos);
- ++this.pos;
- switch (ch) {
- case 110: return "\n" // 'n' -> '\n'
- case 114: return "\r" // 'r' -> '\r'
- case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
- case 117: return codePointToString(this.readCodePoint()) // 'u'
- case 116: return "\t" // 't' -> '\t'
- case 98: return "\b" // 'b' -> '\b'
- case 118: return "\u000b" // 'v' -> '\u000b'
- case 102: return "\f" // 'f' -> '\f'
- case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
- case 10: // ' \n'
- if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
- return ""
- default:
- if (ch >= 48 && ch <= 55) {
- var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
- var octal = parseInt(octalStr, 8);
- if (octal > 255) {
- octalStr = octalStr.slice(0, -1);
- octal = parseInt(octalStr, 8);
- }
- this.pos += octalStr.length - 1;
- ch = this.input.charCodeAt(this.pos);
- if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
- this.invalidStringToken(
- this.pos - 1 - octalStr.length,
- inTemplate
- ? "Octal literal in template string"
- : "Octal literal in strict mode"
- );
- }
- return String.fromCharCode(octal)
+ pp$9.readWord = function() {
+ var word = this.readWord1();
+ var type = types.name;
+ if (this.keywords.test(word)) {
+ if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); }
+ type = keywords$1[word];
}
- return String.fromCharCode(ch)
+ return this.finishToken(type, word)
+ };
+
+ // Acorn is a tiny, fast JavaScript parser written in JavaScript.
+
+ var version = "7.1.0";
+
+ Parser.acorn = {
+ Parser: Parser,
+ version: version,
+ defaultOptions: defaultOptions,
+ Position: Position,
+ SourceLocation: SourceLocation,
+ getLineInfo: getLineInfo,
+ Node: Node,
+ TokenType: TokenType,
+ tokTypes: types,
+ keywordTypes: keywords$1,
+ TokContext: TokContext,
+ tokContexts: types$1,
+ isIdentifierChar: isIdentifierChar,
+ isIdentifierStart: isIdentifierStart,
+ Token: Token,
+ isNewLine: isNewLine,
+ lineBreak: lineBreak,
+ lineBreakG: lineBreakG,
+ nonASCIIwhitespace: nonASCIIwhitespace
+ };
+
+ // The main exported interface (under `self.acorn` when in the
+ // browser) is a `parse` function that takes a code string and
+ // returns an abstract syntax tree as specified by [Mozilla parser
+ // API][api].
+ //
+ // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
+
+ function parse(input, options) {
+ return Parser.parse(input, options)
}
-};
-
-// Used to read character escape sequences ('\x', '\u', '\U').
-
-pp$8.readHexChar = function(len) {
- var codePos = this.pos;
- var n = this.readInt(16, len);
- if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
- return n
-};
-
-// Read an identifier, and return it as a string. Sets `this.containsEsc`
-// to whether the word contained a '\u' escape.
-//
-// Incrementally adds only escaped chars, adding other chunks as-is
-// as a micro-optimization.
-
-pp$8.readWord1 = function() {
- var this$1 = this;
-
- this.containsEsc = false;
- var word = "", first = true, chunkStart = this.pos;
- var astral = this.options.ecmaVersion >= 6;
- while (this.pos < this.input.length) {
- var ch = this$1.fullCharCodeAtPos();
- if (isIdentifierChar(ch, astral)) {
- this$1.pos += ch <= 0xffff ? 1 : 2;
- } else if (ch === 92) { // "\"
- this$1.containsEsc = true;
- word += this$1.input.slice(chunkStart, this$1.pos);
- var escStart = this$1.pos;
- if (this$1.input.charCodeAt(++this$1.pos) !== 117) // "u"
- { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); }
- ++this$1.pos;
- var esc = this$1.readCodePoint();
- if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
- { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); }
- word += codePointToString(esc);
- chunkStart = this$1.pos;
- } else {
- break
- }
- first = false;
+
+ // This function tries to parse a single expression at a given
+ // offset in a string. Useful for parsing mixed-language formats
+ // that embed JavaScript expressions.
+
+ function parseExpressionAt(input, pos, options) {
+ return Parser.parseExpressionAt(input, pos, options)
}
- return word + this.input.slice(chunkStart, this.pos)
-};
-
-// Read an identifier or keyword token. Will check for reserved
-// words when necessary.
-
-pp$8.readWord = function() {
- var word = this.readWord1();
- var type = types.name;
- if (this.keywords.test(word)) {
- if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); }
- type = keywords$1[word];
+
+ // Acorn is organized as a tokenizer and a recursive-descent parser.
+ // The `tokenizer` export provides an interface to the tokenizer.
+
+ function tokenizer(input, options) {
+ return Parser.tokenizer(input, options)
}
- return this.finishToken(type, word)
-};
-
-// Acorn is a tiny, fast JavaScript parser written in JavaScript.
-//
-// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
-// various contributors and released under an MIT license.
-//
-// Git repositories for Acorn are available at
-//
-// http://marijnhaverbeke.nl/git/acorn
-// https://github.com/acornjs/acorn.git
-//
-// Please use the [github bug tracker][ghbt] to report issues.
-//
-// [ghbt]: https://github.com/acornjs/acorn/issues
-//
-// [walk]: util/walk.js
-
-var version = "6.0.1";
-
-// The main exported interface (under `self.acorn` when in the
-// browser) is a `parse` function that takes a code string and
-// returns an abstract syntax tree as specified by [Mozilla parser
-// API][api].
-//
-// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
-
-function parse(input, options) {
- return Parser.parse(input, options)
-}
-
-// This function tries to parse a single expression at a given
-// offset in a string. Useful for parsing mixed-language formats
-// that embed JavaScript expressions.
-
-function parseExpressionAt(input, pos, options) {
- return Parser.parseExpressionAt(input, pos, options)
-}
-
-// Acorn is organized as a tokenizer and a recursive-descent parser.
-// The `tokenizer` export provides an interface to the tokenizer.
-
-function tokenizer(input, options) {
- return Parser.tokenizer(input, options)
-}
-
-exports.version = version;
-exports.parse = parse;
-exports.parseExpressionAt = parseExpressionAt;
-exports.tokenizer = tokenizer;
-exports.Parser = Parser;
-exports.defaultOptions = defaultOptions;
-exports.Position = Position;
-exports.SourceLocation = SourceLocation;
-exports.getLineInfo = getLineInfo;
-exports.Node = Node;
-exports.TokenType = TokenType;
-exports.tokTypes = types;
-exports.keywordTypes = keywords$1;
-exports.TokContext = TokContext;
-exports.tokContexts = types$1;
-exports.isIdentifierChar = isIdentifierChar;
-exports.isIdentifierStart = isIdentifierStart;
-exports.Token = Token;
-exports.isNewLine = isNewLine;
-exports.lineBreak = lineBreak;
-exports.lineBreakG = lineBreakG;
-exports.nonASCIIwhitespace = nonASCIIwhitespace;
-
-Object.defineProperty(exports, '__esModule', { value: true });
-
-})));
+
+ exports.Node = Node;
+ exports.Parser = Parser;
+ exports.Position = Position;
+ exports.SourceLocation = SourceLocation;
+ exports.TokContext = TokContext;
+ exports.Token = Token;
+ exports.TokenType = TokenType;
+ exports.defaultOptions = defaultOptions;
+ exports.getLineInfo = getLineInfo;
+ exports.isIdentifierChar = isIdentifierChar;
+ exports.isIdentifierStart = isIdentifierStart;
+ exports.isNewLine = isNewLine;
+ exports.keywordTypes = keywords$1;
+ exports.lineBreak = lineBreak;
+ exports.lineBreakG = lineBreakG;
+ exports.nonASCIIwhitespace = nonASCIIwhitespace;
+ exports.parse = parse;
+ exports.parseExpressionAt = parseExpressionAt;
+ exports.tokContexts = types$1;
+ exports.tokTypes = types;
+ exports.tokenizer = tokenizer;
+ exports.version = version;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
// clang-format on
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js
index 5038bc179d8..90bb8b43fa5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js
@@ -2,1430 +2,1384 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('acorn')) :
typeof define === 'function' && define.amd ? define(['exports', 'acorn'], factory) :
- (factory((global.acorn = global.acorn || {}, global.acorn.loose = {}),global.acorn));
-}(this, (function (exports,acorn) { 'use strict';
-
-function noop() {}
-
-var LooseParser = function LooseParser(input, options) {
- if ( options === void 0 ) options = {};
-
- this.toks = this.constructor.BaseParser.tokenizer(input, options);
- this.options = this.toks.options;
- this.input = this.toks.input;
- this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0};
- this.tok.validateRegExpFlags = noop;
- this.tok.validateRegExpPattern = noop;
- if (this.options.locations) {
- var here = this.toks.curPosition();
- this.tok.loc = new acorn.SourceLocation(this.toks, here, here);
- }
- this.ahead = []; // Tokens ahead
- this.context = []; // Indentation contexted
- this.curIndent = 0;
- this.curLineStart = 0;
- this.nextLineStart = this.lineEnd(this.curLineStart) + 1;
- this.inAsync = false;
- this.inFunction = false;
-};
-
-LooseParser.prototype.startNode = function startNode () {
- return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
-};
-
-LooseParser.prototype.storeCurrentPos = function storeCurrentPos () {
- return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
-};
-
-LooseParser.prototype.startNodeAt = function startNodeAt (pos) {
- if (this.options.locations) {
- return new acorn.Node(this.toks, pos[0], pos[1])
- } else {
- return new acorn.Node(this.toks, pos)
- }
-};
-
-LooseParser.prototype.finishNode = function finishNode (node, type) {
- node.type = type;
- node.end = this.last.end;
- if (this.options.locations)
- { node.loc.end = this.last.loc.end; }
- if (this.options.ranges)
- { node.range[1] = this.last.end; }
- return node
-};
-
-LooseParser.prototype.dummyNode = function dummyNode (type) {
- var dummy = this.startNode();
- dummy.type = type;
- dummy.end = dummy.start;
- if (this.options.locations)
- { dummy.loc.end = dummy.loc.start; }
- if (this.options.ranges)
- { dummy.range[1] = dummy.start; }
- this.last = {type: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc};
- return dummy
-};
-
-LooseParser.prototype.dummyIdent = function dummyIdent () {
- var dummy = this.dummyNode("Identifier");
- dummy.name = "✖";
- return dummy
-};
-
-LooseParser.prototype.dummyString = function dummyString () {
- var dummy = this.dummyNode("Literal");
- dummy.value = dummy.raw = "✖";
- return dummy
-};
-
-LooseParser.prototype.eat = function eat (type) {
- if (this.tok.type === type) {
- this.next();
+ (global = global || self, factory((global.acorn = global.acorn || {}, global.acorn.loose = {}), global.acorn));
+}(this, function (exports, acorn) { 'use strict';
+
+ function noop() {}
+
+ var LooseParser = function LooseParser(input, options) {
+ if ( options === void 0 ) options = {};
+
+ this.toks = this.constructor.BaseParser.tokenizer(input, options);
+ this.options = this.toks.options;
+ this.input = this.toks.input;
+ this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0};
+ this.tok.validateRegExpFlags = noop;
+ this.tok.validateRegExpPattern = noop;
+ if (this.options.locations) {
+ var here = this.toks.curPosition();
+ this.tok.loc = new acorn.SourceLocation(this.toks, here, here);
+ }
+ this.ahead = []; // Tokens ahead
+ this.context = []; // Indentation contexted
+ this.curIndent = 0;
+ this.curLineStart = 0;
+ this.nextLineStart = this.lineEnd(this.curLineStart) + 1;
+ this.inAsync = false;
+ this.inFunction = false;
+ };
+
+ LooseParser.prototype.startNode = function startNode () {
+ return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
+ };
+
+ LooseParser.prototype.storeCurrentPos = function storeCurrentPos () {
+ return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
+ };
+
+ LooseParser.prototype.startNodeAt = function startNodeAt (pos) {
+ if (this.options.locations) {
+ return new acorn.Node(this.toks, pos[0], pos[1])
+ } else {
+ return new acorn.Node(this.toks, pos)
+ }
+ };
+
+ LooseParser.prototype.finishNode = function finishNode (node, type) {
+ node.type = type;
+ node.end = this.last.end;
+ if (this.options.locations)
+ { node.loc.end = this.last.loc.end; }
+ if (this.options.ranges)
+ { node.range[1] = this.last.end; }
+ return node
+ };
+
+ LooseParser.prototype.dummyNode = function dummyNode (type) {
+ var dummy = this.startNode();
+ dummy.type = type;
+ dummy.end = dummy.start;
+ if (this.options.locations)
+ { dummy.loc.end = dummy.loc.start; }
+ if (this.options.ranges)
+ { dummy.range[1] = dummy.start; }
+ this.last = {type: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc};
+ return dummy
+ };
+
+ LooseParser.prototype.dummyIdent = function dummyIdent () {
+ var dummy = this.dummyNode("Identifier");
+ dummy.name = "✖";
+ return dummy
+ };
+
+ LooseParser.prototype.dummyString = function dummyString () {
+ var dummy = this.dummyNode("Literal");
+ dummy.value = dummy.raw = "✖";
+ return dummy
+ };
+
+ LooseParser.prototype.eat = function eat (type) {
+ if (this.tok.type === type) {
+ this.next();
+ return true
+ } else {
+ return false
+ }
+ };
+
+ LooseParser.prototype.isContextual = function isContextual (name) {
+ return this.tok.type === acorn.tokTypes.name && this.tok.value === name
+ };
+
+ LooseParser.prototype.eatContextual = function eatContextual (name) {
+ return this.tok.value === name && this.eat(acorn.tokTypes.name)
+ };
+
+ LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () {
+ return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR ||
+ acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start))
+ };
+
+ LooseParser.prototype.semicolon = function semicolon () {
+ return this.eat(acorn.tokTypes.semi)
+ };
+
+ LooseParser.prototype.expect = function expect (type) {
+ if (this.eat(type)) { return true }
+ for (var i = 1; i <= 2; i++) {
+ if (this.lookAhead(i).type === type) {
+ for (var j = 0; j < i; j++) { this.next(); }
+ return true
+ }
+ }
+ };
+
+ LooseParser.prototype.pushCx = function pushCx () {
+ this.context.push(this.curIndent);
+ };
+
+ LooseParser.prototype.popCx = function popCx () {
+ this.curIndent = this.context.pop();
+ };
+
+ LooseParser.prototype.lineEnd = function lineEnd (pos) {
+ while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; }
+ return pos
+ };
+
+ LooseParser.prototype.indentationAfter = function indentationAfter (pos) {
+ for (var count = 0;; ++pos) {
+ var ch = this.input.charCodeAt(pos);
+ if (ch === 32) { ++count; }
+ else if (ch === 9) { count += this.options.tabSize; }
+ else { return count }
+ }
+ };
+
+ LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) {
+ if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true }
+ return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
+ (!blockHeuristic || this.nextLineStart >= this.input.length ||
+ this.indentationAfter(this.nextLineStart) < indent)
+ };
+
+ LooseParser.prototype.tokenStartsLine = function tokenStartsLine () {
+ for (var p = this.tok.start - 1; p >= this.curLineStart; --p) {
+ var ch = this.input.charCodeAt(p);
+ if (ch !== 9 && ch !== 32) { return false }
+ }
return true
- } else {
- return false
- }
-};
-
-LooseParser.prototype.isContextual = function isContextual (name) {
- return this.tok.type === acorn.tokTypes.name && this.tok.value === name
-};
-
-LooseParser.prototype.eatContextual = function eatContextual (name) {
- return this.tok.value === name && this.eat(acorn.tokTypes.name)
-};
+ };
-LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () {
- return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR ||
- acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start))
-};
+ LooseParser.prototype.extend = function extend (name, f) {
+ this[name] = f(this[name]);
+ };
-LooseParser.prototype.semicolon = function semicolon () {
- return this.eat(acorn.tokTypes.semi)
-};
-
-LooseParser.prototype.expect = function expect (type) {
- var this$1 = this;
+ LooseParser.prototype.parse = function parse () {
+ this.next();
+ return this.parseTopLevel()
+ };
- if (this.eat(type)) { return true }
- for (var i = 1; i <= 2; i++) {
- if (this$1.lookAhead(i).type === type) {
- for (var j = 0; j < i; j++) { this$1.next(); }
- return true
- }
- }
-};
+ LooseParser.extend = function extend () {
+ var plugins = [], len = arguments.length;
+ while ( len-- ) plugins[ len ] = arguments[ len ];
-LooseParser.prototype.pushCx = function pushCx () {
- this.context.push(this.curIndent);
-};
+ var cls = this;
+ for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
+ return cls
+ };
-LooseParser.prototype.popCx = function popCx () {
- this.curIndent = this.context.pop();
-};
+ LooseParser.parse = function parse (input, options) {
+ return new this(input, options).parse()
+ };
-LooseParser.prototype.lineEnd = function lineEnd (pos) {
- while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; }
- return pos
-};
+ // Allows plugins to extend the base parser / tokenizer used
+ LooseParser.BaseParser = acorn.Parser;
-LooseParser.prototype.indentationAfter = function indentationAfter (pos) {
- var this$1 = this;
+ var lp = LooseParser.prototype;
- for (var count = 0;; ++pos) {
- var ch = this$1.input.charCodeAt(pos);
- if (ch === 32) { ++count; }
- else if (ch === 9) { count += this$1.options.tabSize; }
- else { return count }
+ function isSpace(ch) {
+ return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch)
}
-};
-LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) {
- if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true }
- return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
- (!blockHeuristic || this.nextLineStart >= this.input.length ||
- this.indentationAfter(this.nextLineStart) < indent)
-};
+ lp.next = function() {
+ this.last = this.tok;
+ if (this.ahead.length)
+ { this.tok = this.ahead.shift(); }
+ else
+ { this.tok = this.readToken(); }
+
+ if (this.tok.start >= this.nextLineStart) {
+ while (this.tok.start >= this.nextLineStart) {
+ this.curLineStart = this.nextLineStart;
+ this.nextLineStart = this.lineEnd(this.curLineStart) + 1;
+ }
+ this.curIndent = this.indentationAfter(this.curLineStart);
+ }
+ };
+
+ lp.readToken = function() {
+ for (;;) {
+ try {
+ this.toks.next();
+ if (this.toks.type === acorn.tokTypes.dot &&
+ this.input.substr(this.toks.end, 1) === "." &&
+ this.options.ecmaVersion >= 6) {
+ this.toks.end++;
+ this.toks.type = acorn.tokTypes.ellipsis;
+ }
+ return new acorn.Token(this.toks)
+ } catch (e) {
+ if (!(e instanceof SyntaxError)) { throw e }
+
+ // Try to skip some text, based on the error message, and then continue
+ var msg = e.message, pos = e.raisedAt, replace = true;
+ if (/unterminated/i.test(msg)) {
+ pos = this.lineEnd(e.pos + 1);
+ if (/string/.test(msg)) {
+ replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this.input.slice(e.pos + 1, pos)};
+ } else if (/regular expr/i.test(msg)) {
+ var re = this.input.slice(e.pos, pos);
+ try { re = new RegExp(re); } catch (e) { /* ignore compilation error due to new syntax */ }
+ replace = {start: e.pos, end: pos, type: acorn.tokTypes.regexp, value: re};
+ } else if (/template/.test(msg)) {
+ replace = {
+ start: e.pos,
+ end: pos,
+ type: acorn.tokTypes.template,
+ value: this.input.slice(e.pos, pos)
+ };
+ } else {
+ replace = false;
+ }
+ } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) {
+ while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; }
+ } else if (/character escape|expected hexadecimal/i.test(msg)) {
+ while (pos < this.input.length) {
+ var ch = this.input.charCodeAt(pos++);
+ if (ch === 34 || ch === 39 || acorn.isNewLine(ch)) { break }
+ }
+ } else if (/unexpected character/i.test(msg)) {
+ pos++;
+ replace = false;
+ } else if (/regular expression/i.test(msg)) {
+ replace = true;
+ } else {
+ throw e
+ }
+ this.resetTo(pos);
+ if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: "✖"}; }
+ if (replace) {
+ if (this.options.locations)
+ { replace.loc = new acorn.SourceLocation(
+ this.toks,
+ acorn.getLineInfo(this.input, replace.start),
+ acorn.getLineInfo(this.input, replace.end)); }
+ return replace
+ }
+ }
+ }
+ };
+
+ lp.resetTo = function(pos) {
+ this.toks.pos = pos;
+ var ch = this.input.charAt(pos - 1);
+ this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) ||
+ /[enwfd]/.test(ch) &&
+ /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos));
+
+ if (this.options.locations) {
+ this.toks.curLine = 1;
+ this.toks.lineStart = acorn.lineBreakG.lastIndex = 0;
+ var match;
+ while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) {
+ ++this.toks.curLine;
+ this.toks.lineStart = match.index + match[0].length;
+ }
+ }
+ };
-LooseParser.prototype.tokenStartsLine = function tokenStartsLine () {
- var this$1 = this;
+ lp.lookAhead = function(n) {
+ while (n > this.ahead.length)
+ { this.ahead.push(this.readToken()); }
+ return this.ahead[n - 1]
+ };
- for (var p = this.tok.start - 1; p >= this.curLineStart; --p) {
- var ch = this$1.input.charCodeAt(p);
- if (ch !== 9 && ch !== 32) { return false }
- }
- return true
-};
+ function isDummy(node) { return node.name === "✖" }
-LooseParser.prototype.extend = function extend (name, f) {
- this[name] = f(this[name]);
-};
+ var lp$1 = LooseParser.prototype;
-LooseParser.prototype.parse = function parse () {
- this.next();
- return this.parseTopLevel()
-};
+ lp$1.parseTopLevel = function() {
+ var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0);
+ node.body = [];
+ while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this.parseStatement()); }
+ this.toks.adaptDirectivePrologue(node.body);
+ this.last = this.tok;
+ node.sourceType = this.options.sourceType;
+ return this.finishNode(node, "Program")
+ };
-LooseParser.extend = function extend () {
- var plugins = [], len = arguments.length;
- while ( len-- ) plugins[ len ] = arguments[ len ];
+ lp$1.parseStatement = function() {
+ var starttype = this.tok.type, node = this.startNode(), kind;
- var cls = this;
- for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); }
- return cls
-};
+ if (this.toks.isLet()) {
+ starttype = acorn.tokTypes._var;
+ kind = "let";
+ }
-LooseParser.parse = function parse (input, options) {
- return new this(input, options).parse()
-};
+ switch (starttype) {
+ case acorn.tokTypes._break: case acorn.tokTypes._continue:
+ this.next();
+ var isBreak = starttype === acorn.tokTypes._break;
+ if (this.semicolon() || this.canInsertSemicolon()) {
+ node.label = null;
+ } else {
+ node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null;
+ this.semicolon();
+ }
+ return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
-// Allows plugins to extend the base parser / tokenizer used
-LooseParser.BaseParser = acorn.Parser;
+ case acorn.tokTypes._debugger:
+ this.next();
+ this.semicolon();
+ return this.finishNode(node, "DebuggerStatement")
-var lp = LooseParser.prototype;
+ case acorn.tokTypes._do:
+ this.next();
+ node.body = this.parseStatement();
+ node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent();
+ this.semicolon();
+ return this.finishNode(node, "DoWhileStatement")
+
+ case acorn.tokTypes._for:
+ this.next(); // `for` keyword
+ var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await");
+
+ this.pushCx();
+ this.expect(acorn.tokTypes.parenL);
+ if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) }
+ var isLet = this.toks.isLet();
+ if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const) {
+ var init$1 = this.parseVar(this.startNode(), true, isLet ? "let" : this.tok.value);
+ if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) {
+ if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
+ node.await = isAwait;
+ }
+ return this.parseForIn(node, init$1)
+ }
+ return this.parseFor(node, init$1)
+ }
+ var init = this.parseExpression(true);
+ if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) {
+ if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
+ node.await = isAwait;
+ }
+ return this.parseForIn(node, this.toAssignable(init))
+ }
+ return this.parseFor(node, init)
-function isSpace(ch) {
- return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch)
-}
+ case acorn.tokTypes._function:
+ this.next();
+ return this.parseFunction(node, true)
-lp.next = function() {
- var this$1 = this;
+ case acorn.tokTypes._if:
+ this.next();
+ node.test = this.parseParenExpression();
+ node.consequent = this.parseStatement();
+ node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null;
+ return this.finishNode(node, "IfStatement")
- this.last = this.tok;
- if (this.ahead.length)
- { this.tok = this.ahead.shift(); }
- else
- { this.tok = this.readToken(); }
+ case acorn.tokTypes._return:
+ this.next();
+ if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; }
+ else { node.argument = this.parseExpression(); this.semicolon(); }
+ return this.finishNode(node, "ReturnStatement")
- if (this.tok.start >= this.nextLineStart) {
- while (this.tok.start >= this.nextLineStart) {
- this$1.curLineStart = this$1.nextLineStart;
- this$1.nextLineStart = this$1.lineEnd(this$1.curLineStart) + 1;
- }
- this.curIndent = this.indentationAfter(this.curLineStart);
- }
-};
-
-lp.readToken = function() {
- var this$1 = this;
-
- for (;;) {
- try {
- this$1.toks.next();
- if (this$1.toks.type === acorn.tokTypes.dot &&
- this$1.input.substr(this$1.toks.end, 1) === "." &&
- this$1.options.ecmaVersion >= 6) {
- this$1.toks.end++;
- this$1.toks.type = acorn.tokTypes.ellipsis;
- }
- return new acorn.Token(this$1.toks)
- } catch (e) {
- if (!(e instanceof SyntaxError)) { throw e }
-
- // Try to skip some text, based on the error message, and then continue
- var msg = e.message, pos = e.raisedAt, replace = true;
- if (/unterminated/i.test(msg)) {
- pos = this$1.lineEnd(e.pos + 1);
- if (/string/.test(msg)) {
- replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)};
- } else if (/regular expr/i.test(msg)) {
- var re = this$1.input.slice(e.pos, pos);
- try { re = new RegExp(re); } catch (e) { /* ignore compilation error due to new syntax */ }
- replace = {start: e.pos, end: pos, type: acorn.tokTypes.regexp, value: re};
- } else if (/template/.test(msg)) {
- replace = {
- start: e.pos,
- end: pos,
- type: acorn.tokTypes.template,
- value: this$1.input.slice(e.pos, pos)
- };
+ case acorn.tokTypes._switch:
+ var blockIndent = this.curIndent, line = this.curLineStart;
+ this.next();
+ node.discriminant = this.parseParenExpression();
+ node.cases = [];
+ this.pushCx();
+ this.expect(acorn.tokTypes.braceL);
+
+ var cur;
+ while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) {
+ if (this.tok.type === acorn.tokTypes._case || this.tok.type === acorn.tokTypes._default) {
+ var isCase = this.tok.type === acorn.tokTypes._case;
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ node.cases.push(cur = this.startNode());
+ cur.consequent = [];
+ this.next();
+ if (isCase) { cur.test = this.parseExpression(); }
+ else { cur.test = null; }
+ this.expect(acorn.tokTypes.colon);
} else {
- replace = false;
- }
- } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) {
- while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; }
- } else if (/character escape|expected hexadecimal/i.test(msg)) {
- while (pos < this.input.length) {
- var ch = this$1.input.charCodeAt(pos++);
- if (ch === 34 || ch === 39 || acorn.isNewLine(ch)) { break }
+ if (!cur) {
+ node.cases.push(cur = this.startNode());
+ cur.consequent = [];
+ cur.test = null;
+ }
+ cur.consequent.push(this.parseStatement());
}
- } else if (/unexpected character/i.test(msg)) {
- pos++;
- replace = false;
- } else if (/regular expression/i.test(msg)) {
- replace = true;
- } else {
- throw e
}
- this$1.resetTo(pos);
- if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: "✖"}; }
- if (replace) {
- if (this$1.options.locations)
- { replace.loc = new acorn.SourceLocation(
- this$1.toks,
- acorn.getLineInfo(this$1.input, replace.start),
- acorn.getLineInfo(this$1.input, replace.end)); }
- return replace
- }
- }
- }
-};
-
-lp.resetTo = function(pos) {
- var this$1 = this;
-
- this.toks.pos = pos;
- var ch = this.input.charAt(pos - 1);
- this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) ||
- /[enwfd]/.test(ch) &&
- /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos));
-
- if (this.options.locations) {
- this.toks.curLine = 1;
- this.toks.lineStart = acorn.lineBreakG.lastIndex = 0;
- var match;
- while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) {
- ++this$1.toks.curLine;
- this$1.toks.lineStart = match.index + match[0].length;
- }
- }
-};
+ if (cur) { this.finishNode(cur, "SwitchCase"); }
+ this.popCx();
+ this.eat(acorn.tokTypes.braceR);
+ return this.finishNode(node, "SwitchStatement")
-lp.lookAhead = function(n) {
- var this$1 = this;
-
- while (n > this.ahead.length)
- { this$1.ahead.push(this$1.readToken()); }
- return this.ahead[n - 1]
-};
-
-function isDummy(node) { return node.name === "✖" }
+ case acorn.tokTypes._throw:
+ this.next();
+ node.argument = this.parseExpression();
+ this.semicolon();
+ return this.finishNode(node, "ThrowStatement")
-var lp$1 = LooseParser.prototype;
+ case acorn.tokTypes._try:
+ this.next();
+ node.block = this.parseBlock();
+ node.handler = null;
+ if (this.tok.type === acorn.tokTypes._catch) {
+ var clause = this.startNode();
+ this.next();
+ if (this.eat(acorn.tokTypes.parenL)) {
+ clause.param = this.toAssignable(this.parseExprAtom(), true);
+ this.expect(acorn.tokTypes.parenR);
+ } else {
+ clause.param = null;
+ }
+ clause.body = this.parseBlock();
+ node.handler = this.finishNode(clause, "CatchClause");
+ }
+ node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null;
+ if (!node.handler && !node.finalizer) { return node.block }
+ return this.finishNode(node, "TryStatement")
-lp$1.parseTopLevel = function() {
- var this$1 = this;
+ case acorn.tokTypes._var:
+ case acorn.tokTypes._const:
+ return this.parseVar(node, false, kind || this.tok.value)
- var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0);
- node.body = [];
- while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this$1.parseStatement()); }
- this.toks.adaptDirectivePrologue(node.body);
- this.last = this.tok;
- if (this.options.ecmaVersion >= 6) {
- node.sourceType = this.options.sourceType;
- }
- return this.finishNode(node, "Program")
-};
+ case acorn.tokTypes._while:
+ this.next();
+ node.test = this.parseParenExpression();
+ node.body = this.parseStatement();
+ return this.finishNode(node, "WhileStatement")
-lp$1.parseStatement = function() {
- var this$1 = this;
+ case acorn.tokTypes._with:
+ this.next();
+ node.object = this.parseParenExpression();
+ node.body = this.parseStatement();
+ return this.finishNode(node, "WithStatement")
- var starttype = this.tok.type, node = this.startNode(), kind;
+ case acorn.tokTypes.braceL:
+ return this.parseBlock()
- if (this.toks.isLet()) {
- starttype = acorn.tokTypes._var;
- kind = "let";
- }
+ case acorn.tokTypes.semi:
+ this.next();
+ return this.finishNode(node, "EmptyStatement")
- switch (starttype) {
- case acorn.tokTypes._break: case acorn.tokTypes._continue:
- this.next();
- var isBreak = starttype === acorn.tokTypes._break;
- if (this.semicolon() || this.canInsertSemicolon()) {
- node.label = null;
- } else {
- node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null;
- this.semicolon();
- }
- return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
+ case acorn.tokTypes._class:
+ return this.parseClass(true)
- case acorn.tokTypes._debugger:
- this.next();
- this.semicolon();
- return this.finishNode(node, "DebuggerStatement")
+ case acorn.tokTypes._import:
+ if (this.options.ecmaVersion > 10 && this.lookAhead(1).type === acorn.tokTypes.parenL) {
+ node.expression = this.parseExpression();
+ this.semicolon();
+ return this.finishNode(node, "ExpressionStatement")
+ }
- case acorn.tokTypes._do:
- this.next();
- node.body = this.parseStatement();
- node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent();
- this.semicolon();
- return this.finishNode(node, "DoWhileStatement")
+ return this.parseImport()
- case acorn.tokTypes._for:
- this.next(); // `for` keyword
- var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await");
+ case acorn.tokTypes._export:
+ return this.parseExport()
- this.pushCx();
- this.expect(acorn.tokTypes.parenL);
- if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) }
- var isLet = this.toks.isLet();
- if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const) {
- var init$1 = this.parseVar(this.startNode(), true, isLet ? "let" : this.tok.value);
- if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) {
- if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
- node.await = isAwait;
- }
- return this.parseForIn(node, init$1)
+ default:
+ if (this.toks.isAsyncFunction()) {
+ this.next();
+ this.next();
+ return this.parseFunction(node, true, true)
}
- return this.parseFor(node, init$1)
- }
- var init = this.parseExpression(true);
- if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) {
- if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) {
- node.await = isAwait;
+ var expr = this.parseExpression();
+ if (isDummy(expr)) {
+ this.next();
+ if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") }
+ return this.parseStatement()
+ } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.colon)) {
+ node.body = this.parseStatement();
+ node.label = expr;
+ return this.finishNode(node, "LabeledStatement")
+ } else {
+ node.expression = expr;
+ this.semicolon();
+ return this.finishNode(node, "ExpressionStatement")
}
- return this.parseForIn(node, this.toAssignable(init))
}
- return this.parseFor(node, init)
+ };
- case acorn.tokTypes._function:
- this.next();
- return this.parseFunction(node, true)
+ lp$1.parseBlock = function() {
+ var node = this.startNode();
+ this.pushCx();
+ this.expect(acorn.tokTypes.braceL);
+ var blockIndent = this.curIndent, line = this.curLineStart;
+ node.body = [];
+ while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true))
+ { node.body.push(this.parseStatement()); }
+ this.popCx();
+ this.eat(acorn.tokTypes.braceR);
+ return this.finishNode(node, "BlockStatement")
+ };
+
+ lp$1.parseFor = function(node, init) {
+ node.init = init;
+ node.test = node.update = null;
+ if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); }
+ if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); }
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ node.body = this.parseStatement();
+ return this.finishNode(node, "ForStatement")
+ };
- case acorn.tokTypes._if:
+ lp$1.parseForIn = function(node, init) {
+ var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement";
this.next();
- node.test = this.parseParenExpression();
- node.consequent = this.parseStatement();
- node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null;
- return this.finishNode(node, "IfStatement")
+ node.left = init;
+ node.right = this.parseExpression();
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ node.body = this.parseStatement();
+ return this.finishNode(node, type)
+ };
- case acorn.tokTypes._return:
+ lp$1.parseVar = function(node, noIn, kind) {
+ node.kind = kind;
this.next();
- if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; }
- else { node.argument = this.parseExpression(); this.semicolon(); }
- return this.finishNode(node, "ReturnStatement")
+ node.declarations = [];
+ do {
+ var decl = this.startNode();
+ decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent();
+ decl.init = this.eat(acorn.tokTypes.eq) ? this.parseMaybeAssign(noIn) : null;
+ node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
+ } while (this.eat(acorn.tokTypes.comma))
+ if (!node.declarations.length) {
+ var decl$1 = this.startNode();
+ decl$1.id = this.dummyIdent();
+ node.declarations.push(this.finishNode(decl$1, "VariableDeclarator"));
+ }
+ if (!noIn) { this.semicolon(); }
+ return this.finishNode(node, "VariableDeclaration")
+ };
- case acorn.tokTypes._switch:
- var blockIndent = this.curIndent, line = this.curLineStart;
+ lp$1.parseClass = function(isStatement) {
+ var node = this.startNode();
this.next();
- node.discriminant = this.parseParenExpression();
- node.cases = [];
+ if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
+ else if (isStatement === true) { node.id = this.dummyIdent(); }
+ else { node.id = null; }
+ node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null;
+ node.body = this.startNode();
+ node.body.body = [];
this.pushCx();
- this.expect(acorn.tokTypes.braceL);
-
- var cur;
- while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) {
- if (this$1.tok.type === acorn.tokTypes._case || this$1.tok.type === acorn.tokTypes._default) {
- var isCase = this$1.tok.type === acorn.tokTypes._case;
- if (cur) { this$1.finishNode(cur, "SwitchCase"); }
- node.cases.push(cur = this$1.startNode());
- cur.consequent = [];
- this$1.next();
- if (isCase) { cur.test = this$1.parseExpression(); }
- else { cur.test = null; }
- this$1.expect(acorn.tokTypes.colon);
+ var indent = this.curIndent + 1, line = this.curLineStart;
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
+ if (this.semicolon()) { continue }
+ var method = this.startNode(), isGenerator = (void 0), isAsync = (void 0);
+ if (this.options.ecmaVersion >= 6) {
+ method.static = false;
+ isGenerator = this.eat(acorn.tokTypes.star);
+ }
+ this.parsePropertyName(method);
+ if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(acorn.tokTypes.comma); continue }
+ if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
+ (this.tok.type !== acorn.tokTypes.parenL && this.tok.type !== acorn.tokTypes.braceL)) {
+ method.static = true;
+ isGenerator = this.eat(acorn.tokTypes.star);
+ this.parsePropertyName(method);
} else {
- if (!cur) {
- node.cases.push(cur = this$1.startNode());
- cur.consequent = [];
- cur.test = null;
+ method.static = false;
+ }
+ if (!method.computed &&
+ method.key.type === "Identifier" && method.key.name === "async" && this.tok.type !== acorn.tokTypes.parenL &&
+ !this.canInsertSemicolon()) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.star);
+ this.parsePropertyName(method);
+ } else {
+ isAsync = false;
+ }
+ if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
+ !method.computed && (method.key.name === "get" || method.key.name === "set") &&
+ this.tok.type !== acorn.tokTypes.parenL && this.tok.type !== acorn.tokTypes.braceL) {
+ method.kind = method.key.name;
+ this.parsePropertyName(method);
+ method.value = this.parseMethod(false);
+ } else {
+ if (!method.computed && !method.static && !isGenerator && !isAsync && (
+ method.key.type === "Identifier" && method.key.name === "constructor" ||
+ method.key.type === "Literal" && method.key.value === "constructor")) {
+ method.kind = "constructor";
+ } else {
+ method.kind = "method";
}
- cur.consequent.push(this$1.parseStatement());
+ method.value = this.parseMethod(isGenerator, isAsync);
}
+ node.body.body.push(this.finishNode(method, "MethodDefinition"));
}
- if (cur) { this.finishNode(cur, "SwitchCase"); }
this.popCx();
- this.eat(acorn.tokTypes.braceR);
- return this.finishNode(node, "SwitchStatement")
-
- case acorn.tokTypes._throw:
- this.next();
- node.argument = this.parseExpression();
+ if (!this.eat(acorn.tokTypes.braceR)) {
+ // If there is no closing brace, make the node span to the start
+ // of the next token (this is useful for Tern)
+ this.last.end = this.tok.start;
+ if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
+ }
this.semicolon();
- return this.finishNode(node, "ThrowStatement")
+ this.finishNode(node.body, "ClassBody");
+ return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
+ };
+
+ lp$1.parseFunction = function(node, isStatement, isAsync) {
+ var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 6) {
+ node.generator = this.eat(acorn.tokTypes.star);
+ }
+ if (this.options.ecmaVersion >= 8) {
+ node.async = !!isAsync;
+ }
+ if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
+ else if (isStatement === true) { node.id = this.dummyIdent(); }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.parseFunctionParams();
+ node.body = this.parseBlock();
+ this.toks.adaptDirectivePrologue(node.body.body);
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
+ };
- case acorn.tokTypes._try:
+ lp$1.parseExport = function() {
+ var node = this.startNode();
this.next();
- node.block = this.parseBlock();
- node.handler = null;
- if (this.tok.type === acorn.tokTypes._catch) {
- var clause = this.startNode();
- this.next();
- if (this.eat(acorn.tokTypes.parenL)) {
- clause.param = this.toAssignable(this.parseExprAtom(), true);
- this.expect(acorn.tokTypes.parenR);
+ if (this.eat(acorn.tokTypes.star)) {
+ node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString();
+ return this.finishNode(node, "ExportAllDeclaration")
+ }
+ if (this.eat(acorn.tokTypes._default)) {
+ // export default (function foo() {}) // This is FunctionExpression.
+ var isAsync;
+ if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) {
+ var fNode = this.startNode();
+ this.next();
+ if (isAsync) { this.next(); }
+ node.declaration = this.parseFunction(fNode, "nullableID", isAsync);
+ } else if (this.tok.type === acorn.tokTypes._class) {
+ node.declaration = this.parseClass("nullableID");
} else {
- clause.param = null;
+ node.declaration = this.parseMaybeAssign();
+ this.semicolon();
}
- clause.body = this.parseBlock();
- node.handler = this.finishNode(clause, "CatchClause");
+ return this.finishNode(node, "ExportDefaultDeclaration")
}
- node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null;
- if (!node.handler && !node.finalizer) { return node.block }
- return this.finishNode(node, "TryStatement")
-
- case acorn.tokTypes._var:
- case acorn.tokTypes._const:
- return this.parseVar(node, false, kind || this.tok.value)
-
- case acorn.tokTypes._while:
- this.next();
- node.test = this.parseParenExpression();
- node.body = this.parseStatement();
- return this.finishNode(node, "WhileStatement")
-
- case acorn.tokTypes._with:
- this.next();
- node.object = this.parseParenExpression();
- node.body = this.parseStatement();
- return this.finishNode(node, "WithStatement")
-
- case acorn.tokTypes.braceL:
- return this.parseBlock()
-
- case acorn.tokTypes.semi:
- this.next();
- return this.finishNode(node, "EmptyStatement")
-
- case acorn.tokTypes._class:
- return this.parseClass(true)
-
- case acorn.tokTypes._import:
- return this.parseImport()
-
- case acorn.tokTypes._export:
- return this.parseExport()
-
- default:
- if (this.toks.isAsyncFunction()) {
- this.next();
- this.next();
- return this.parseFunction(node, true, true)
- }
- var expr = this.parseExpression();
- if (isDummy(expr)) {
- this.next();
- if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") }
- return this.parseStatement()
- } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.colon)) {
- node.body = this.parseStatement();
- node.label = expr;
- return this.finishNode(node, "LabeledStatement")
+ if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) {
+ node.declaration = this.parseStatement();
+ node.specifiers = [];
+ node.source = null;
} else {
- node.expression = expr;
+ node.declaration = null;
+ node.specifiers = this.parseExportSpecifierList();
+ node.source = this.eatContextual("from") ? this.parseExprAtom() : null;
this.semicolon();
- return this.finishNode(node, "ExpressionStatement")
}
- }
-};
-
-lp$1.parseBlock = function() {
- var this$1 = this;
-
- var node = this.startNode();
- this.pushCx();
- this.expect(acorn.tokTypes.braceL);
- var blockIndent = this.curIndent, line = this.curLineStart;
- node.body = [];
- while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true))
- { node.body.push(this$1.parseStatement()); }
- this.popCx();
- this.eat(acorn.tokTypes.braceR);
- return this.finishNode(node, "BlockStatement")
-};
-
-lp$1.parseFor = function(node, init) {
- node.init = init;
- node.test = node.update = null;
- if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); }
- if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); }
- this.popCx();
- this.expect(acorn.tokTypes.parenR);
- node.body = this.parseStatement();
- return this.finishNode(node, "ForStatement")
-};
-
-lp$1.parseForIn = function(node, init) {
- var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement";
- this.next();
- node.left = init;
- node.right = this.parseExpression();
- this.popCx();
- this.expect(acorn.tokTypes.parenR);
- node.body = this.parseStatement();
- return this.finishNode(node, type)
-};
-
-lp$1.parseVar = function(node, noIn, kind) {
- var this$1 = this;
-
- node.kind = kind;
- this.next();
- node.declarations = [];
- do {
- var decl = this$1.startNode();
- decl.id = this$1.options.ecmaVersion >= 6 ? this$1.toAssignable(this$1.parseExprAtom(), true) : this$1.parseIdent();
- decl.init = this$1.eat(acorn.tokTypes.eq) ? this$1.parseMaybeAssign(noIn) : null;
- node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
- } while (this.eat(acorn.tokTypes.comma))
- if (!node.declarations.length) {
- var decl$1 = this.startNode();
- decl$1.id = this.dummyIdent();
- node.declarations.push(this.finishNode(decl$1, "VariableDeclarator"));
- }
- if (!noIn) { this.semicolon(); }
- return this.finishNode(node, "VariableDeclaration")
-};
-
-lp$1.parseClass = function(isStatement) {
- var this$1 = this;
-
- var node = this.startNode();
- this.next();
- if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
- else if (isStatement === true) { node.id = this.dummyIdent(); }
- else { node.id = null; }
- node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null;
- node.body = this.startNode();
- node.body.body = [];
- this.pushCx();
- var indent = this.curIndent + 1, line = this.curLineStart;
- this.eat(acorn.tokTypes.braceL);
- if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
- while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
- if (this$1.semicolon()) { continue }
- var method = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0);
- if (this$1.options.ecmaVersion >= 6) {
- method.static = false;
- isGenerator = this$1.eat(acorn.tokTypes.star);
- }
- this$1.parsePropertyName(method);
- if (isDummy(method.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue }
- if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
- (this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL)) {
- method.static = true;
- isGenerator = this$1.eat(acorn.tokTypes.star);
- this$1.parsePropertyName(method);
- } else {
- method.static = false;
- }
- if (!method.computed &&
- method.key.type === "Identifier" && method.key.name === "async" && this$1.tok.type !== acorn.tokTypes.parenL &&
- !this$1.canInsertSemicolon()) {
- isAsync = true;
- isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star);
- this$1.parsePropertyName(method);
- } else {
- isAsync = false;
- }
- if (this$1.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
- !method.computed && (method.key.name === "get" || method.key.name === "set") &&
- this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL) {
- method.kind = method.key.name;
- this$1.parsePropertyName(method);
- method.value = this$1.parseMethod(false);
+ return this.finishNode(node, "ExportNamedDeclaration")
+ };
+
+ lp$1.parseImport = function() {
+ var node = this.startNode();
+ this.next();
+ if (this.tok.type === acorn.tokTypes.string) {
+ node.specifiers = [];
+ node.source = this.parseExprAtom();
} else {
- if (!method.computed && !method.static && !isGenerator && !isAsync && (
- method.key.type === "Identifier" && method.key.name === "constructor" ||
- method.key.type === "Literal" && method.key.value === "constructor")) {
- method.kind = "constructor";
- } else {
- method.kind = "method";
+ var elt;
+ if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") {
+ elt = this.startNode();
+ elt.local = this.parseIdent();
+ this.finishNode(elt, "ImportDefaultSpecifier");
+ this.eat(acorn.tokTypes.comma);
}
- method.value = this$1.parseMethod(isGenerator, isAsync);
+ node.specifiers = this.parseImportSpecifiers();
+ node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString();
+ if (elt) { node.specifiers.unshift(elt); }
}
- node.body.body.push(this$1.finishNode(method, "MethodDefinition"));
- }
- this.popCx();
- if (!this.eat(acorn.tokTypes.braceR)) {
- // If there is no closing brace, make the node span to the start
- // of the next token (this is useful for Tern)
- this.last.end = this.tok.start;
- if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
- }
- this.semicolon();
- this.finishNode(node.body, "ClassBody");
- return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
-};
-
-lp$1.parseFunction = function(node, isStatement, isAsync) {
- var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
- this.initFunction(node);
- if (this.options.ecmaVersion >= 6) {
- node.generator = this.eat(acorn.tokTypes.star);
- }
- if (this.options.ecmaVersion >= 8) {
- node.async = !!isAsync;
- }
- if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); }
- else if (isStatement === true) { node.id = this.dummyIdent(); }
- this.inAsync = node.async;
- this.inFunction = true;
- node.params = this.parseFunctionParams();
- node.body = this.parseBlock();
- this.toks.adaptDirectivePrologue(node.body.body);
- this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
- return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
-};
-
-lp$1.parseExport = function() {
- var node = this.startNode();
- this.next();
- if (this.eat(acorn.tokTypes.star)) {
- node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString();
- return this.finishNode(node, "ExportAllDeclaration")
- }
- if (this.eat(acorn.tokTypes._default)) {
- // export default (function foo() {}) // This is FunctionExpression.
- var isAsync;
- if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) {
- var fNode = this.startNode();
+ this.semicolon();
+ return this.finishNode(node, "ImportDeclaration")
+ };
+
+ lp$1.parseImportSpecifiers = function() {
+ var elts = [];
+ if (this.tok.type === acorn.tokTypes.star) {
+ var elt = this.startNode();
this.next();
- if (isAsync) { this.next(); }
- node.declaration = this.parseFunction(fNode, "nullableID", isAsync);
- } else if (this.tok.type === acorn.tokTypes._class) {
- node.declaration = this.parseClass("nullableID");
+ elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
+ elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"));
} else {
- node.declaration = this.parseMaybeAssign();
- this.semicolon();
- }
- return this.finishNode(node, "ExportDefaultDeclaration")
- }
- if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) {
- node.declaration = this.parseStatement();
- node.specifiers = [];
- node.source = null;
- } else {
- node.declaration = null;
- node.specifiers = this.parseExportSpecifierList();
- node.source = this.eatContextual("from") ? this.parseExprAtom() : null;
- this.semicolon();
- }
- return this.finishNode(node, "ExportNamedDeclaration")
-};
-
-lp$1.parseImport = function() {
- var node = this.startNode();
- this.next();
- if (this.tok.type === acorn.tokTypes.string) {
- node.specifiers = [];
- node.source = this.parseExprAtom();
- } else {
- var elt;
- if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") {
- elt = this.startNode();
- elt.local = this.parseIdent();
- this.finishNode(elt, "ImportDefaultSpecifier");
- this.eat(acorn.tokTypes.comma);
+ var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
+ this.pushCx();
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
+ var elt$1 = this.startNode();
+ if (this.eat(acorn.tokTypes.star)) {
+ elt$1.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
+ this.finishNode(elt$1, "ImportNamespaceSpecifier");
+ } else {
+ if (this.isContextual("from")) { break }
+ elt$1.imported = this.parseIdent();
+ if (isDummy(elt$1.imported)) { break }
+ elt$1.local = this.eatContextual("as") ? this.parseIdent() : elt$1.imported;
+ this.finishNode(elt$1, "ImportSpecifier");
+ }
+ elts.push(elt$1);
+ this.eat(acorn.tokTypes.comma);
+ }
+ this.eat(acorn.tokTypes.braceR);
+ this.popCx();
}
- node.specifiers = this.parseImportSpecifiers();
- node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString();
- if (elt) { node.specifiers.unshift(elt); }
- }
- this.semicolon();
- return this.finishNode(node, "ImportDeclaration")
-};
-
-lp$1.parseImportSpecifiers = function() {
- var this$1 = this;
+ return elts
+ };
- var elts = [];
- if (this.tok.type === acorn.tokTypes.star) {
- var elt = this.startNode();
- this.next();
- elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
- elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"));
- } else {
+ lp$1.parseExportSpecifierList = function() {
+ var elts = [];
var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
this.pushCx();
this.eat(acorn.tokTypes.braceL);
if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
- var elt$1 = this$1.startNode();
- if (this$1.eat(acorn.tokTypes.star)) {
- elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : this$1.dummyIdent();
- this$1.finishNode(elt$1, "ImportNamespaceSpecifier");
- } else {
- if (this$1.isContextual("from")) { break }
- elt$1.imported = this$1.parseIdent();
- if (isDummy(elt$1.imported)) { break }
- elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : elt$1.imported;
- this$1.finishNode(elt$1, "ImportSpecifier");
- }
- elts.push(elt$1);
- this$1.eat(acorn.tokTypes.comma);
+ if (this.isContextual("from")) { break }
+ var elt = this.startNode();
+ elt.local = this.parseIdent();
+ if (isDummy(elt.local)) { break }
+ elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local;
+ this.finishNode(elt, "ExportSpecifier");
+ elts.push(elt);
+ this.eat(acorn.tokTypes.comma);
}
this.eat(acorn.tokTypes.braceR);
this.popCx();
- }
- return elts
-};
-
-lp$1.parseExportSpecifierList = function() {
- var this$1 = this;
-
- var elts = [];
- var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
- this.pushCx();
- this.eat(acorn.tokTypes.braceL);
- if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
- while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
- if (this$1.isContextual("from")) { break }
- var elt = this$1.startNode();
- elt.local = this$1.parseIdent();
- if (isDummy(elt.local)) { break }
- elt.exported = this$1.eatContextual("as") ? this$1.parseIdent() : elt.local;
- this$1.finishNode(elt, "ExportSpecifier");
- elts.push(elt);
- this$1.eat(acorn.tokTypes.comma);
- }
- this.eat(acorn.tokTypes.braceR);
- this.popCx();
- return elts
-};
-
-var lp$2 = LooseParser.prototype;
-
-lp$2.checkLVal = function(expr) {
- if (!expr) { return expr }
- switch (expr.type) {
- case "Identifier":
- case "MemberExpression":
- return expr
+ return elts
+ };
- case "ParenthesizedExpression":
- expr.expression = this.checkLVal(expr.expression);
- return expr
+ var lp$2 = LooseParser.prototype;
- default:
- return this.dummyIdent()
- }
-};
-
-lp$2.parseExpression = function(noIn) {
- var this$1 = this;
-
- var start = this.storeCurrentPos();
- var expr = this.parseMaybeAssign(noIn);
- if (this.tok.type === acorn.tokTypes.comma) {
- var node = this.startNodeAt(start);
- node.expressions = [expr];
- while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn)); }
- return this.finishNode(node, "SequenceExpression")
- }
- return expr
-};
-
-lp$2.parseParenExpression = function() {
- this.pushCx();
- this.expect(acorn.tokTypes.parenL);
- var val = this.parseExpression();
- this.popCx();
- this.expect(acorn.tokTypes.parenR);
- return val
-};
-
-lp$2.parseMaybeAssign = function(noIn) {
- if (this.toks.isContextual("yield")) {
- var node = this.startNode();
- this.next();
- if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) {
- node.delegate = false;
- node.argument = null;
- } else {
- node.delegate = this.eat(acorn.tokTypes.star);
- node.argument = this.parseMaybeAssign();
+ lp$2.checkLVal = function(expr) {
+ if (!expr) { return expr }
+ switch (expr.type) {
+ case "Identifier":
+ case "MemberExpression":
+ return expr
+
+ case "ParenthesizedExpression":
+ expr.expression = this.checkLVal(expr.expression);
+ return expr
+
+ default:
+ return this.dummyIdent()
}
- return this.finishNode(node, "YieldExpression")
- }
+ };
- var start = this.storeCurrentPos();
- var left = this.parseMaybeConditional(noIn);
- if (this.tok.type.isAssign) {
- var node$1 = this.startNodeAt(start);
- node$1.operator = this.tok.value;
- node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left);
- this.next();
- node$1.right = this.parseMaybeAssign(noIn);
- return this.finishNode(node$1, "AssignmentExpression")
- }
- return left
-};
-
-lp$2.parseMaybeConditional = function(noIn) {
- var start = this.storeCurrentPos();
- var expr = this.parseExprOps(noIn);
- if (this.eat(acorn.tokTypes.question)) {
- var node = this.startNodeAt(start);
- node.test = expr;
- node.consequent = this.parseMaybeAssign();
- node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent();
- return this.finishNode(node, "ConditionalExpression")
- }
- return expr
-};
-
-lp$2.parseExprOps = function(noIn) {
- var start = this.storeCurrentPos();
- var indent = this.curIndent, line = this.curLineStart;
- return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
-};
-
-lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
- if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left }
- var prec = this.tok.type.binop;
- if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) {
- if (prec > minPrec) {
+ lp$2.parseExpression = function(noIn) {
+ var start = this.storeCurrentPos();
+ var expr = this.parseMaybeAssign(noIn);
+ if (this.tok.type === acorn.tokTypes.comma) {
var node = this.startNodeAt(start);
- node.left = left;
- node.operator = this.tok.value;
+ node.expressions = [expr];
+ while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this.parseMaybeAssign(noIn)); }
+ return this.finishNode(node, "SequenceExpression")
+ }
+ return expr
+ };
+
+ lp$2.parseParenExpression = function() {
+ this.pushCx();
+ this.expect(acorn.tokTypes.parenL);
+ var val = this.parseExpression();
+ this.popCx();
+ this.expect(acorn.tokTypes.parenR);
+ return val
+ };
+
+ lp$2.parseMaybeAssign = function(noIn) {
+ if (this.toks.isContextual("yield")) {
+ var node = this.startNode();
this.next();
- if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) {
- node.right = this.dummyIdent();
+ if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) {
+ node.delegate = false;
+ node.argument = null;
} else {
- var rightStart = this.storeCurrentPos();
- node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line);
+ node.delegate = this.eat(acorn.tokTypes.star);
+ node.argument = this.parseMaybeAssign();
}
- this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");
- return this.parseExprOp(node, start, minPrec, noIn, indent, line)
- }
- }
- return left
-};
-
-lp$2.parseMaybeUnary = function(sawUnary) {
- var this$1 = this;
-
- var start = this.storeCurrentPos(), expr;
- if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") &&
- (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))
- ) {
- expr = this.parseAwait();
- sawUnary = true;
- } else if (this.tok.type.prefix) {
- var node = this.startNode(), update = this.tok.type === acorn.tokTypes.incDec;
- if (!update) { sawUnary = true; }
- node.operator = this.tok.value;
- node.prefix = true;
- this.next();
- node.argument = this.parseMaybeUnary(true);
- if (update) { node.argument = this.checkLVal(node.argument); }
- expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
- } else if (this.tok.type === acorn.tokTypes.ellipsis) {
- var node$1 = this.startNode();
- this.next();
- node$1.argument = this.parseMaybeUnary(sawUnary);
- expr = this.finishNode(node$1, "SpreadElement");
- } else {
- expr = this.parseExprSubscripts();
- while (this.tok.type.postfix && !this.canInsertSemicolon()) {
- var node$2 = this$1.startNodeAt(start);
- node$2.operator = this$1.tok.value;
- node$2.prefix = false;
- node$2.argument = this$1.checkLVal(expr);
- this$1.next();
- expr = this$1.finishNode(node$2, "UpdateExpression");
+ return this.finishNode(node, "YieldExpression")
}
- }
-
- if (!sawUnary && this.eat(acorn.tokTypes.starstar)) {
- var node$3 = this.startNodeAt(start);
- node$3.operator = "**";
- node$3.left = expr;
- node$3.right = this.parseMaybeUnary(false);
- return this.finishNode(node$3, "BinaryExpression")
- }
-
- return expr
-};
-
-lp$2.parseExprSubscripts = function() {
- var start = this.storeCurrentPos();
- return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
-};
-lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) {
- var this$1 = this;
+ var start = this.storeCurrentPos();
+ var left = this.parseMaybeConditional(noIn);
+ if (this.tok.type.isAssign) {
+ var node$1 = this.startNodeAt(start);
+ node$1.operator = this.tok.value;
+ node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left);
+ this.next();
+ node$1.right = this.parseMaybeAssign(noIn);
+ return this.finishNode(node$1, "AssignmentExpression")
+ }
+ return left
+ };
- for (;;) {
- if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) {
- if (this$1.tok.type === acorn.tokTypes.dot && this$1.curIndent === startIndent)
- { --startIndent; }
- else
- { return base }
+ lp$2.parseMaybeConditional = function(noIn) {
+ var start = this.storeCurrentPos();
+ var expr = this.parseExprOps(noIn);
+ if (this.eat(acorn.tokTypes.question)) {
+ var node = this.startNodeAt(start);
+ node.test = expr;
+ node.consequent = this.parseMaybeAssign();
+ node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent();
+ return this.finishNode(node, "ConditionalExpression")
}
+ return expr
+ };
- var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon();
-
- if (this$1.eat(acorn.tokTypes.dot)) {
- var node = this$1.startNodeAt(start);
- node.object = base;
- if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine())
- { node.property = this$1.dummyIdent(); }
- else
- { node.property = this$1.parsePropertyAccessor() || this$1.dummyIdent(); }
- node.computed = false;
- base = this$1.finishNode(node, "MemberExpression");
- } else if (this$1.tok.type === acorn.tokTypes.bracketL) {
- this$1.pushCx();
- this$1.next();
- var node$1 = this$1.startNodeAt(start);
- node$1.object = base;
- node$1.property = this$1.parseExpression();
- node$1.computed = true;
- this$1.popCx();
- this$1.expect(acorn.tokTypes.bracketR);
- base = this$1.finishNode(node$1, "MemberExpression");
- } else if (!noCalls && this$1.tok.type === acorn.tokTypes.parenL) {
- var exprList = this$1.parseExprList(acorn.tokTypes.parenR);
- if (maybeAsyncArrow && this$1.eat(acorn.tokTypes.arrow))
- { return this$1.parseArrowExpression(this$1.startNodeAt(start), exprList, true) }
- var node$2 = this$1.startNodeAt(start);
- node$2.callee = base;
- node$2.arguments = exprList;
- base = this$1.finishNode(node$2, "CallExpression");
- } else if (this$1.tok.type === acorn.tokTypes.backQuote) {
- var node$3 = this$1.startNodeAt(start);
- node$3.tag = base;
- node$3.quasi = this$1.parseTemplate();
- base = this$1.finishNode(node$3, "TaggedTemplateExpression");
+ lp$2.parseExprOps = function(noIn) {
+ var start = this.storeCurrentPos();
+ var indent = this.curIndent, line = this.curLineStart;
+ return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
+ };
+
+ lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
+ if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left }
+ var prec = this.tok.type.binop;
+ if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) {
+ if (prec > minPrec) {
+ var node = this.startNodeAt(start);
+ node.left = left;
+ node.operator = this.tok.value;
+ this.next();
+ if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) {
+ node.right = this.dummyIdent();
+ } else {
+ var rightStart = this.storeCurrentPos();
+ node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line);
+ }
+ this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");
+ return this.parseExprOp(node, start, minPrec, noIn, indent, line)
+ }
+ }
+ return left
+ };
+
+ lp$2.parseMaybeUnary = function(sawUnary) {
+ var start = this.storeCurrentPos(), expr;
+ if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") &&
+ (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))
+ ) {
+ expr = this.parseAwait();
+ sawUnary = true;
+ } else if (this.tok.type.prefix) {
+ var node = this.startNode(), update = this.tok.type === acorn.tokTypes.incDec;
+ if (!update) { sawUnary = true; }
+ node.operator = this.tok.value;
+ node.prefix = true;
+ this.next();
+ node.argument = this.parseMaybeUnary(true);
+ if (update) { node.argument = this.checkLVal(node.argument); }
+ expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
+ } else if (this.tok.type === acorn.tokTypes.ellipsis) {
+ var node$1 = this.startNode();
+ this.next();
+ node$1.argument = this.parseMaybeUnary(sawUnary);
+ expr = this.finishNode(node$1, "SpreadElement");
} else {
- return base
+ expr = this.parseExprSubscripts();
+ while (this.tok.type.postfix && !this.canInsertSemicolon()) {
+ var node$2 = this.startNodeAt(start);
+ node$2.operator = this.tok.value;
+ node$2.prefix = false;
+ node$2.argument = this.checkLVal(expr);
+ this.next();
+ expr = this.finishNode(node$2, "UpdateExpression");
+ }
}
- }
-};
-
-lp$2.parseExprAtom = function() {
- var node;
- switch (this.tok.type) {
- case acorn.tokTypes._this:
- case acorn.tokTypes._super:
- var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super";
- node = this.startNode();
- this.next();
- return this.finishNode(node, type)
- case acorn.tokTypes.name:
+ if (!sawUnary && this.eat(acorn.tokTypes.starstar)) {
+ var node$3 = this.startNodeAt(start);
+ node$3.operator = "**";
+ node$3.left = expr;
+ node$3.right = this.parseMaybeUnary(false);
+ return this.finishNode(node$3, "BinaryExpression")
+ }
+
+ return expr
+ };
+
+ lp$2.parseExprSubscripts = function() {
var start = this.storeCurrentPos();
- var id = this.parseIdent();
- var isAsync = false;
- if (id.name === "async" && !this.canInsertSemicolon()) {
- if (this.eat(acorn.tokTypes._function))
- { return this.parseFunction(this.startNodeAt(start), false, true) }
- if (this.tok.type === acorn.tokTypes.name) {
- id = this.parseIdent();
- isAsync = true;
+ return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
+ };
+
+ lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) {
+ for (;;) {
+ if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) {
+ if (this.tok.type === acorn.tokTypes.dot && this.curIndent === startIndent)
+ { --startIndent; }
+ else
+ { return base }
+ }
+
+ var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon();
+
+ if (this.eat(acorn.tokTypes.dot)) {
+ var node = this.startNodeAt(start);
+ node.object = base;
+ if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine())
+ { node.property = this.dummyIdent(); }
+ else
+ { node.property = this.parsePropertyAccessor() || this.dummyIdent(); }
+ node.computed = false;
+ base = this.finishNode(node, "MemberExpression");
+ } else if (this.tok.type === acorn.tokTypes.bracketL) {
+ this.pushCx();
+ this.next();
+ var node$1 = this.startNodeAt(start);
+ node$1.object = base;
+ node$1.property = this.parseExpression();
+ node$1.computed = true;
+ this.popCx();
+ this.expect(acorn.tokTypes.bracketR);
+ base = this.finishNode(node$1, "MemberExpression");
+ } else if (!noCalls && this.tok.type === acorn.tokTypes.parenL) {
+ var exprList = this.parseExprList(acorn.tokTypes.parenR);
+ if (maybeAsyncArrow && this.eat(acorn.tokTypes.arrow))
+ { return this.parseArrowExpression(this.startNodeAt(start), exprList, true) }
+ var node$2 = this.startNodeAt(start);
+ node$2.callee = base;
+ node$2.arguments = exprList;
+ base = this.finishNode(node$2, "CallExpression");
+ } else if (this.tok.type === acorn.tokTypes.backQuote) {
+ var node$3 = this.startNodeAt(start);
+ node$3.tag = base;
+ node$3.quasi = this.parseTemplate();
+ base = this.finishNode(node$3, "TaggedTemplateExpression");
+ } else {
+ return base
}
}
- return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id
-
- case acorn.tokTypes.regexp:
- node = this.startNode();
- var val = this.tok.value;
- node.regex = {pattern: val.pattern, flags: val.flags};
- node.value = val.value;
- node.raw = this.input.slice(this.tok.start, this.tok.end);
- this.next();
- return this.finishNode(node, "Literal")
+ };
+
+ lp$2.parseExprAtom = function() {
+ var node;
+ switch (this.tok.type) {
+ case acorn.tokTypes._this:
+ case acorn.tokTypes._super:
+ var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super";
+ node = this.startNode();
+ this.next();
+ return this.finishNode(node, type)
+
+ case acorn.tokTypes.name:
+ var start = this.storeCurrentPos();
+ var id = this.parseIdent();
+ var isAsync = false;
+ if (id.name === "async" && !this.canInsertSemicolon()) {
+ if (this.eat(acorn.tokTypes._function))
+ { return this.parseFunction(this.startNodeAt(start), false, true) }
+ if (this.tok.type === acorn.tokTypes.name) {
+ id = this.parseIdent();
+ isAsync = true;
+ }
+ }
+ return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id
+
+ case acorn.tokTypes.regexp:
+ node = this.startNode();
+ var val = this.tok.value;
+ node.regex = {pattern: val.pattern, flags: val.flags};
+ node.value = val.value;
+ node.raw = this.input.slice(this.tok.start, this.tok.end);
+ this.next();
+ return this.finishNode(node, "Literal")
- case acorn.tokTypes.num: case acorn.tokTypes.string:
- node = this.startNode();
- node.value = this.tok.value;
- node.raw = this.input.slice(this.tok.start, this.tok.end);
- this.next();
- return this.finishNode(node, "Literal")
+ case acorn.tokTypes.num: case acorn.tokTypes.string:
+ node = this.startNode();
+ node.value = this.tok.value;
+ node.raw = this.input.slice(this.tok.start, this.tok.end);
+ if (this.tok.type === acorn.tokTypes.num && node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); }
+ this.next();
+ return this.finishNode(node, "Literal")
- case acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false:
- node = this.startNode();
- node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true;
- node.raw = this.tok.type.keyword;
- this.next();
- return this.finishNode(node, "Literal")
+ case acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false:
+ node = this.startNode();
+ node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true;
+ node.raw = this.tok.type.keyword;
+ this.next();
+ return this.finishNode(node, "Literal")
- case acorn.tokTypes.parenL:
- var parenStart = this.storeCurrentPos();
- this.next();
- var inner = this.parseExpression();
- this.expect(acorn.tokTypes.parenR);
- if (this.eat(acorn.tokTypes.arrow)) {
- // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
- var params = inner.expressions || [inner];
- if (params.length && isDummy(params[params.length - 1]))
- { params.pop(); }
- return this.parseArrowExpression(this.startNodeAt(parenStart), params)
- }
- if (this.options.preserveParens) {
- var par = this.startNodeAt(parenStart);
- par.expression = inner;
- inner = this.finishNode(par, "ParenthesizedExpression");
- }
- return inner
+ case acorn.tokTypes.parenL:
+ var parenStart = this.storeCurrentPos();
+ this.next();
+ var inner = this.parseExpression();
+ this.expect(acorn.tokTypes.parenR);
+ if (this.eat(acorn.tokTypes.arrow)) {
+ // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
+ var params = inner.expressions || [inner];
+ if (params.length && isDummy(params[params.length - 1]))
+ { params.pop(); }
+ return this.parseArrowExpression(this.startNodeAt(parenStart), params)
+ }
+ if (this.options.preserveParens) {
+ var par = this.startNodeAt(parenStart);
+ par.expression = inner;
+ inner = this.finishNode(par, "ParenthesizedExpression");
+ }
+ return inner
- case acorn.tokTypes.bracketL:
- node = this.startNode();
- node.elements = this.parseExprList(acorn.tokTypes.bracketR, true);
- return this.finishNode(node, "ArrayExpression")
+ case acorn.tokTypes.bracketL:
+ node = this.startNode();
+ node.elements = this.parseExprList(acorn.tokTypes.bracketR, true);
+ return this.finishNode(node, "ArrayExpression")
- case acorn.tokTypes.braceL:
- return this.parseObj()
+ case acorn.tokTypes.braceL:
+ return this.parseObj()
- case acorn.tokTypes._class:
- return this.parseClass(false)
+ case acorn.tokTypes._class:
+ return this.parseClass(false)
- case acorn.tokTypes._function:
- node = this.startNode();
- this.next();
- return this.parseFunction(node, false)
+ case acorn.tokTypes._function:
+ node = this.startNode();
+ this.next();
+ return this.parseFunction(node, false)
- case acorn.tokTypes._new:
- return this.parseNew()
+ case acorn.tokTypes._new:
+ return this.parseNew()
- case acorn.tokTypes.backQuote:
- return this.parseTemplate()
+ case acorn.tokTypes.backQuote:
+ return this.parseTemplate()
- default:
- return this.dummyIdent()
- }
-};
-
-lp$2.parseNew = function() {
- var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart;
- var meta = this.parseIdent(true);
- if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) {
- node.meta = meta;
- node.property = this.parseIdent(true);
- return this.finishNode(node, "MetaProperty")
- }
- var start = this.storeCurrentPos();
- node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line);
- if (this.tok.type === acorn.tokTypes.parenL) {
- node.arguments = this.parseExprList(acorn.tokTypes.parenR);
- } else {
- node.arguments = [];
- }
- return this.finishNode(node, "NewExpression")
-};
-
-lp$2.parseTemplateElement = function() {
- var elem = this.startNode();
-
- // The loose parser accepts invalid unicode escapes even in untagged templates.
- if (this.tok.type === acorn.tokTypes.invalidTemplate) {
- elem.value = {
- raw: this.tok.value,
- cooked: null
- };
- } else {
- elem.value = {
- raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"),
- cooked: this.tok.value
- };
- }
- this.next();
- elem.tail = this.tok.type === acorn.tokTypes.backQuote;
- return this.finishNode(elem, "TemplateElement")
-};
-
-lp$2.parseTemplate = function() {
- var this$1 = this;
-
- var node = this.startNode();
- this.next();
- node.expressions = [];
- var curElt = this.parseTemplateElement();
- node.quasis = [curElt];
- while (!curElt.tail) {
- this$1.next();
- node.expressions.push(this$1.parseExpression());
- if (this$1.expect(acorn.tokTypes.braceR)) {
- curElt = this$1.parseTemplateElement();
- } else {
- curElt = this$1.startNode();
- curElt.value = {cooked: "", raw: ""};
- curElt.tail = true;
- this$1.finishNode(curElt, "TemplateElement");
+ case acorn.tokTypes._import:
+ if (this.options.ecmaVersion >= 11) {
+ return this.parseExprImport()
+ } else {
+ return this.dummyIdent()
+ }
+
+ default:
+ return this.dummyIdent()
}
- node.quasis.push(curElt);
- }
- this.expect(acorn.tokTypes.backQuote);
- return this.finishNode(node, "TemplateLiteral")
-};
-
-lp$2.parseObj = function() {
- var this$1 = this;
-
- var node = this.startNode();
- node.properties = [];
- this.pushCx();
- var indent = this.curIndent + 1, line = this.curLineStart;
- this.eat(acorn.tokTypes.braceL);
- if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
- while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
- var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0);
- if (this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.ellipsis)) {
- prop.argument = this$1.parseMaybeAssign();
- node.properties.push(this$1.finishNode(prop, "SpreadElement"));
- this$1.eat(acorn.tokTypes.comma);
- continue
+ };
+
+ lp$2.parseExprImport = function() {
+ var node = this.startNode();
+ this.next(); // skip `import`
+ switch (this.tok.type) {
+ case acorn.tokTypes.parenL:
+ return this.parseDynamicImport(node)
+ default:
+ node.name = "import";
+ return this.finishNode(node, "Identifier")
}
- if (this$1.options.ecmaVersion >= 6) {
- start = this$1.storeCurrentPos();
- prop.method = false;
- prop.shorthand = false;
- isGenerator = this$1.eat(acorn.tokTypes.star);
+ };
+
+ lp$2.parseDynamicImport = function(node) {
+ node.source = this.parseExprList(acorn.tokTypes.parenR)[0] || this.dummyString();
+ return this.finishNode(node, "ImportExpression")
+ };
+
+ lp$2.parseNew = function() {
+ var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart;
+ var meta = this.parseIdent(true);
+ if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) {
+ node.meta = meta;
+ node.property = this.parseIdent(true);
+ return this.finishNode(node, "MetaProperty")
}
- this$1.parsePropertyName(prop);
- if (this$1.toks.isAsyncProp(prop)) {
- isAsync = true;
- isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star);
- this$1.parsePropertyName(prop);
+ var start = this.storeCurrentPos();
+ node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line);
+ if (this.tok.type === acorn.tokTypes.parenL) {
+ node.arguments = this.parseExprList(acorn.tokTypes.parenR);
} else {
- isAsync = false;
+ node.arguments = [];
}
- if (isDummy(prop.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue }
- if (this$1.eat(acorn.tokTypes.colon)) {
- prop.kind = "init";
- prop.value = this$1.parseMaybeAssign();
- } else if (this$1.options.ecmaVersion >= 6 && (this$1.tok.type === acorn.tokTypes.parenL || this$1.tok.type === acorn.tokTypes.braceL)) {
- prop.kind = "init";
- prop.method = true;
- prop.value = this$1.parseMethod(isGenerator, isAsync);
- } else if (this$1.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
- !prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
- (this$1.tok.type !== acorn.tokTypes.comma && this$1.tok.type !== acorn.tokTypes.braceR && this$1.tok.type !== acorn.tokTypes.eq)) {
- prop.kind = prop.key.name;
- this$1.parsePropertyName(prop);
- prop.value = this$1.parseMethod(false);
+ return this.finishNode(node, "NewExpression")
+ };
+
+ lp$2.parseTemplateElement = function() {
+ var elem = this.startNode();
+
+ // The loose parser accepts invalid unicode escapes even in untagged templates.
+ if (this.tok.type === acorn.tokTypes.invalidTemplate) {
+ elem.value = {
+ raw: this.tok.value,
+ cooked: null
+ };
} else {
- prop.kind = "init";
- if (this$1.options.ecmaVersion >= 6) {
- if (this$1.eat(acorn.tokTypes.eq)) {
- var assign = this$1.startNodeAt(start);
- assign.operator = "=";
- assign.left = prop.key;
- assign.right = this$1.parseMaybeAssign();
- prop.value = this$1.finishNode(assign, "AssignmentExpression");
+ elem.value = {
+ raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"),
+ cooked: this.tok.value
+ };
+ }
+ this.next();
+ elem.tail = this.tok.type === acorn.tokTypes.backQuote;
+ return this.finishNode(elem, "TemplateElement")
+ };
+
+ lp$2.parseTemplate = function() {
+ var node = this.startNode();
+ this.next();
+ node.expressions = [];
+ var curElt = this.parseTemplateElement();
+ node.quasis = [curElt];
+ while (!curElt.tail) {
+ this.next();
+ node.expressions.push(this.parseExpression());
+ if (this.expect(acorn.tokTypes.braceR)) {
+ curElt = this.parseTemplateElement();
+ } else {
+ curElt = this.startNode();
+ curElt.value = {cooked: "", raw: ""};
+ curElt.tail = true;
+ this.finishNode(curElt, "TemplateElement");
+ }
+ node.quasis.push(curElt);
+ }
+ this.expect(acorn.tokTypes.backQuote);
+ return this.finishNode(node, "TemplateLiteral")
+ };
+
+ lp$2.parseObj = function() {
+ var node = this.startNode();
+ node.properties = [];
+ this.pushCx();
+ var indent = this.curIndent + 1, line = this.curLineStart;
+ this.eat(acorn.tokTypes.braceL);
+ if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
+ while (!this.closes(acorn.tokTypes.braceR, indent, line)) {
+ var prop = this.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0);
+ if (this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.ellipsis)) {
+ prop.argument = this.parseMaybeAssign();
+ node.properties.push(this.finishNode(prop, "SpreadElement"));
+ this.eat(acorn.tokTypes.comma);
+ continue
+ }
+ if (this.options.ecmaVersion >= 6) {
+ start = this.storeCurrentPos();
+ prop.method = false;
+ prop.shorthand = false;
+ isGenerator = this.eat(acorn.tokTypes.star);
+ }
+ this.parsePropertyName(prop);
+ if (this.toks.isAsyncProp(prop)) {
+ isAsync = true;
+ isGenerator = this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.star);
+ this.parsePropertyName(prop);
+ } else {
+ isAsync = false;
+ }
+ if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(acorn.tokTypes.comma); continue }
+ if (this.eat(acorn.tokTypes.colon)) {
+ prop.kind = "init";
+ prop.value = this.parseMaybeAssign();
+ } else if (this.options.ecmaVersion >= 6 && (this.tok.type === acorn.tokTypes.parenL || this.tok.type === acorn.tokTypes.braceL)) {
+ prop.kind = "init";
+ prop.method = true;
+ prop.value = this.parseMethod(isGenerator, isAsync);
+ } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
+ !prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
+ (this.tok.type !== acorn.tokTypes.comma && this.tok.type !== acorn.tokTypes.braceR && this.tok.type !== acorn.tokTypes.eq)) {
+ prop.kind = prop.key.name;
+ this.parsePropertyName(prop);
+ prop.value = this.parseMethod(false);
+ } else {
+ prop.kind = "init";
+ if (this.options.ecmaVersion >= 6) {
+ if (this.eat(acorn.tokTypes.eq)) {
+ var assign = this.startNodeAt(start);
+ assign.operator = "=";
+ assign.left = prop.key;
+ assign.right = this.parseMaybeAssign();
+ prop.value = this.finishNode(assign, "AssignmentExpression");
+ } else {
+ prop.value = prop.key;
+ }
} else {
- prop.value = prop.key;
+ prop.value = this.dummyIdent();
}
+ prop.shorthand = true;
+ }
+ node.properties.push(this.finishNode(prop, "Property"));
+ this.eat(acorn.tokTypes.comma);
+ }
+ this.popCx();
+ if (!this.eat(acorn.tokTypes.braceR)) {
+ // If there is no closing brace, make the node span to the start
+ // of the next token (this is useful for Tern)
+ this.last.end = this.tok.start;
+ if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
+ }
+ return this.finishNode(node, "ObjectExpression")
+ };
+
+ lp$2.parsePropertyName = function(prop) {
+ if (this.options.ecmaVersion >= 6) {
+ if (this.eat(acorn.tokTypes.bracketL)) {
+ prop.computed = true;
+ prop.key = this.parseExpression();
+ this.expect(acorn.tokTypes.bracketR);
+ return
} else {
- prop.value = this$1.dummyIdent();
+ prop.computed = false;
}
- prop.shorthand = true;
}
- node.properties.push(this$1.finishNode(prop, "Property"));
- this$1.eat(acorn.tokTypes.comma);
- }
- this.popCx();
- if (!this.eat(acorn.tokTypes.braceR)) {
- // If there is no closing brace, make the node span to the start
- // of the next token (this is useful for Tern)
- this.last.end = this.tok.start;
- if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
- }
- return this.finishNode(node, "ObjectExpression")
-};
-
-lp$2.parsePropertyName = function(prop) {
- if (this.options.ecmaVersion >= 6) {
- if (this.eat(acorn.tokTypes.bracketL)) {
- prop.computed = true;
- prop.key = this.parseExpression();
- this.expect(acorn.tokTypes.bracketR);
- return
+ var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent();
+ prop.key = key || this.dummyIdent();
+ };
+
+ lp$2.parsePropertyAccessor = function() {
+ if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() }
+ };
+
+ lp$2.parseIdent = function() {
+ var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword;
+ if (!name) { return this.dummyIdent() }
+ var node = this.startNode();
+ this.next();
+ node.name = name;
+ return this.finishNode(node, "Identifier")
+ };
+
+ lp$2.initFunction = function(node) {
+ node.id = null;
+ node.params = [];
+ if (this.options.ecmaVersion >= 6) {
+ node.generator = false;
+ node.expression = false;
+ }
+ if (this.options.ecmaVersion >= 8)
+ { node.async = false; }
+ };
+
+ // Convert existing expression atom to assignable pattern
+ // if possible.
+
+ lp$2.toAssignable = function(node, binding) {
+ if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) ; else if (node.type === "ParenthesizedExpression") {
+ this.toAssignable(node.expression, binding);
+ } else if (this.options.ecmaVersion < 6) {
+ return this.dummyIdent()
+ } else if (node.type === "ObjectExpression") {
+ node.type = "ObjectPattern";
+ for (var i = 0, list = node.properties; i < list.length; i += 1)
+ {
+ var prop = list[i];
+
+ this.toAssignable(prop, binding);
+ }
+ } else if (node.type === "ArrayExpression") {
+ node.type = "ArrayPattern";
+ this.toAssignableList(node.elements, binding);
+ } else if (node.type === "Property") {
+ this.toAssignable(node.value, binding);
+ } else if (node.type === "SpreadElement") {
+ node.type = "RestElement";
+ this.toAssignable(node.argument, binding);
+ } else if (node.type === "AssignmentExpression") {
+ node.type = "AssignmentPattern";
+ delete node.operator;
} else {
- prop.computed = false;
+ return this.dummyIdent()
}
- }
- var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent();
- prop.key = key || this.dummyIdent();
-};
-
-lp$2.parsePropertyAccessor = function() {
- if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() }
-};
-
-lp$2.parseIdent = function() {
- var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword;
- if (!name) { return this.dummyIdent() }
- var node = this.startNode();
- this.next();
- node.name = name;
- return this.finishNode(node, "Identifier")
-};
-
-lp$2.initFunction = function(node) {
- node.id = null;
- node.params = [];
- if (this.options.ecmaVersion >= 6) {
- node.generator = false;
- node.expression = false;
- }
- if (this.options.ecmaVersion >= 8)
- { node.async = false; }
-};
-
-// Convert existing expression atom to assignable pattern
-// if possible.
-
-lp$2.toAssignable = function(node, binding) {
- var this$1 = this;
-
- if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) {
- // Okay
- } else if (node.type === "ParenthesizedExpression") {
- this.toAssignable(node.expression, binding);
- } else if (this.options.ecmaVersion < 6) {
- return this.dummyIdent()
- } else if (node.type === "ObjectExpression") {
- node.type = "ObjectPattern";
- for (var i = 0, list = node.properties; i < list.length; i += 1)
+ return node
+ };
+
+ lp$2.toAssignableList = function(exprList, binding) {
+ for (var i = 0, list = exprList; i < list.length; i += 1)
{
- var prop = list[i];
+ var expr = list[i];
- this$1.toAssignable(prop, binding);
+ this.toAssignable(expr, binding);
}
- } else if (node.type === "ArrayExpression") {
- node.type = "ArrayPattern";
- this.toAssignableList(node.elements, binding);
- } else if (node.type === "Property") {
- this.toAssignable(node.value, binding);
- } else if (node.type === "SpreadElement") {
- node.type = "RestElement";
- this.toAssignable(node.argument, binding);
- } else if (node.type === "AssignmentExpression") {
- node.type = "AssignmentPattern";
- delete node.operator;
- } else {
- return this.dummyIdent()
- }
- return node
-};
-
-lp$2.toAssignableList = function(exprList, binding) {
- var this$1 = this;
-
- for (var i = 0, list = exprList; i < list.length; i += 1)
- {
- var expr = list[i];
-
- this$1.toAssignable(expr, binding);
- }
- return exprList
-};
-
-lp$2.parseFunctionParams = function(params) {
- params = this.parseExprList(acorn.tokTypes.parenR);
- return this.toAssignableList(params, true)
-};
-
-lp$2.parseMethod = function(isGenerator, isAsync) {
- var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction;
- this.initFunction(node);
- if (this.options.ecmaVersion >= 6)
- { node.generator = !!isGenerator; }
- if (this.options.ecmaVersion >= 8)
- { node.async = !!isAsync; }
- this.inAsync = node.async;
- this.inFunction = true;
- node.params = this.parseFunctionParams();
- node.body = this.parseBlock();
- this.toks.adaptDirectivePrologue(node.body.body);
- this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
- return this.finishNode(node, "FunctionExpression")
-};
-
-lp$2.parseArrowExpression = function(node, params, isAsync) {
- var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
- this.initFunction(node);
- if (this.options.ecmaVersion >= 8)
- { node.async = !!isAsync; }
- this.inAsync = node.async;
- this.inFunction = true;
- node.params = this.toAssignableList(params, true);
- node.expression = this.tok.type !== acorn.tokTypes.braceL;
- if (node.expression) {
- node.body = this.parseMaybeAssign();
- } else {
+ return exprList
+ };
+
+ lp$2.parseFunctionParams = function(params) {
+ params = this.parseExprList(acorn.tokTypes.parenR);
+ return this.toAssignableList(params, true)
+ };
+
+ lp$2.parseMethod = function(isGenerator, isAsync) {
+ var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 6)
+ { node.generator = !!isGenerator; }
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.parseFunctionParams();
node.body = this.parseBlock();
this.toks.adaptDirectivePrologue(node.body.body);
- }
- this.inAsync = oldInAsync;
- this.inFunction = oldInFunction;
- return this.finishNode(node, "ArrowFunctionExpression")
-};
-
-lp$2.parseExprList = function(close, allowEmpty) {
- var this$1 = this;
-
- this.pushCx();
- var indent = this.curIndent, line = this.curLineStart, elts = [];
- this.next(); // Opening bracket
- while (!this.closes(close, indent + 1, line)) {
- if (this$1.eat(acorn.tokTypes.comma)) {
- elts.push(allowEmpty ? null : this$1.dummyIdent());
- continue
- }
- var elt = this$1.parseMaybeAssign();
- if (isDummy(elt)) {
- if (this$1.closes(close, indent, line)) { break }
- this$1.next();
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, "FunctionExpression")
+ };
+
+ lp$2.parseArrowExpression = function(node, params, isAsync) {
+ var oldInAsync = this.inAsync, oldInFunction = this.inFunction;
+ this.initFunction(node);
+ if (this.options.ecmaVersion >= 8)
+ { node.async = !!isAsync; }
+ this.inAsync = node.async;
+ this.inFunction = true;
+ node.params = this.toAssignableList(params, true);
+ node.expression = this.tok.type !== acorn.tokTypes.braceL;
+ if (node.expression) {
+ node.body = this.parseMaybeAssign();
} else {
- elts.push(elt);
+ node.body = this.parseBlock();
+ this.toks.adaptDirectivePrologue(node.body.body);
}
- this$1.eat(acorn.tokTypes.comma);
- }
- this.popCx();
- if (!this.eat(close)) {
- // If there is no closing brace, make the node span to the start
- // of the next token (this is useful for Tern)
- this.last.end = this.tok.start;
- if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
+ this.inAsync = oldInAsync;
+ this.inFunction = oldInFunction;
+ return this.finishNode(node, "ArrowFunctionExpression")
+ };
+
+ lp$2.parseExprList = function(close, allowEmpty) {
+ this.pushCx();
+ var indent = this.curIndent, line = this.curLineStart, elts = [];
+ this.next(); // Opening bracket
+ while (!this.closes(close, indent + 1, line)) {
+ if (this.eat(acorn.tokTypes.comma)) {
+ elts.push(allowEmpty ? null : this.dummyIdent());
+ continue
+ }
+ var elt = this.parseMaybeAssign();
+ if (isDummy(elt)) {
+ if (this.closes(close, indent, line)) { break }
+ this.next();
+ } else {
+ elts.push(elt);
+ }
+ this.eat(acorn.tokTypes.comma);
+ }
+ this.popCx();
+ if (!this.eat(close)) {
+ // If there is no closing brace, make the node span to the start
+ // of the next token (this is useful for Tern)
+ this.last.end = this.tok.start;
+ if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
+ }
+ return elts
+ };
+
+ lp$2.parseAwait = function() {
+ var node = this.startNode();
+ this.next();
+ node.argument = this.parseMaybeUnary();
+ return this.finishNode(node, "AwaitExpression")
+ };
+
+ // Acorn: Loose parser
+
+ acorn.defaultOptions.tabSize = 4;
+
+ function parse(input, options) {
+ return LooseParser.parse(input, options)
}
- return elts
-};
-
-lp$2.parseAwait = function() {
- var node = this.startNode();
- this.next();
- node.argument = this.parseMaybeUnary();
- return this.finishNode(node, "AwaitExpression")
-};
-
-// Acorn: Loose parser
-//
-// This module provides an alternative parser that exposes that same
-// interface as the main module's `parse` function, but will try to
-// parse anything as JavaScript, repairing syntax error the best it
-// can. There are circumstances in which it will raise an error and
-// give up, but they are very rare. The resulting AST will be a mostly
-// valid JavaScript AST (as per the [Mozilla parser API][api], except
-// that:
-//
-// - Return outside functions is allowed
-//
-// - Label consistency (no conflicts, break only to existing labels)
-// is not enforced.
-//
-// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever
-// the parser got too confused to return anything meaningful.
-//
-// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
-//
-// The expected use for this is to *first* try `acorn.parse`, and only
-// if that fails switch to the loose parser. The loose parser might
-// parse badly indented code incorrectly, so **don't** use it as your
-// default parser.
-//
-// Quite a lot of acorn.js is duplicated here. The alternative was to
-// add a *lot* of extra cruft to that file, making it less readable
-// and slower. Copying and editing the code allowed me to make
-// invasive changes and simplifications without creating a complicated
-// tangle.
-
-acorn.defaultOptions.tabSize = 4;
-
-function parse(input, options) {
- return LooseParser.parse(input, options)
-}
-
-exports.parse = parse;
-exports.LooseParser = LooseParser;
-
-Object.defineProperty(exports, '__esModule', { value: true });
-
-})));
+
+ exports.LooseParser = LooseParser;
+ exports.parse = parse;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
// clang-format on
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARFormat.js b/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARFormat.js
index 1fa99ec1253..354b99fbcd0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARFormat.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARFormat.js
@@ -7,8 +7,9 @@ HARImporter.HARBase = class {
* @param {*} data
*/
constructor(data) {
- if (!data || typeof data !== 'object')
+ if (!data || typeof data !== 'object') {
throw 'First parameter is expected to be an object';
+ }
}
/**
@@ -17,8 +18,9 @@ HARImporter.HARBase = class {
*/
static _safeDate(data) {
const date = new Date(data);
- if (!Number.isNaN(date.getTime()))
+ if (!Number.isNaN(date.getTime())) {
return date;
+ }
throw 'Invalid date format';
}
@@ -28,8 +30,9 @@ HARImporter.HARBase = class {
*/
static _safeNumber(data) {
const result = Number(data);
- if (!Number.isNaN(result))
+ if (!Number.isNaN(result)) {
return result;
+ }
throw 'Casting to number results in NaN';
}
@@ -66,11 +69,13 @@ HARImporter.HARBase = class {
customAsNumber(name) {
// Har specification says starting with '_' is a custom property, but closure uses '_' as a private property.
let value = /** @type {!Object} */ (this)['_' + name];
- if (value === undefined)
+ if (value === undefined) {
return;
+ }
value = Number(value);
- if (Number.isNaN(value))
+ if (Number.isNaN(value)) {
return;
+ }
return value;
}
@@ -105,8 +110,9 @@ HARImporter.HARLog = class extends HARImporter.HARBase {
this.creator = new HARImporter.HARCreator(data['creator']);
this.browser = data['browser'] ? new HARImporter.HARCreator(data['browser']) : undefined;
this.pages = Array.isArray(data['pages']) ? data['pages'].map(page => new HARImporter.HARPage(page)) : [];
- if (!Array.isArray(data['entries']))
+ if (!Array.isArray(data['entries'])) {
throw 'log.entries is expected to be an array';
+ }
this.entries = data['entries'].map(entry => new HARImporter.HAREntry(entry));
this.comment = HARImporter.HARBase._optionalString(data['comment']);
}
@@ -180,8 +186,9 @@ HARImporter.HAREntry = class extends HARImporter.HARBase {
* @return {!HARImporter.HARInitiator|undefined}
*/
_importInitiator(initiator) {
- if (typeof initiator !== 'object')
+ if (typeof initiator !== 'object') {
return;
+ }
return new HARImporter.HARInitiator(initiator);
}
@@ -191,13 +198,15 @@ HARImporter.HAREntry = class extends HARImporter.HARBase {
* @return {!Array<!HARImporter.HARInitiator>|undefined}
*/
_importWebSocketMessages(inputMessages) {
- if (!Array.isArray(inputMessages))
+ if (!Array.isArray(inputMessages)) {
return;
+ }
const outputMessages = [];
for (const message of inputMessages) {
- if (typeof message !== 'object')
+ if (typeof message !== 'object') {
return;
+ }
outputMessages.push(new HARImporter.HARWebSocketMessage(message));
}
return outputMessages;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js b/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js
index 9d675efdf54..bd3508a9229 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/har_importer/HARImporter.js
@@ -10,8 +10,9 @@ HARImporter.Importer = class {
static requestsFromHARLog(log) {
/** @type {!Map<string, !HARImporter.HARPage>} */
const pages = new Map();
- for (const page of log.pages)
+ for (const page of log.pages) {
pages.set(page.id, page);
+ }
log.entries.sort((a, b) => a.startedDateTime - b.startedDateTime);
@@ -40,8 +41,9 @@ HARImporter.Importer = class {
pageLoads.set(entry.pageref, pageLoad);
}
HARImporter.Importer._fillRequestFromHAREntry(request, entry, pageLoad);
- if (pageLoad)
+ if (pageLoad) {
pageLoad.bindRequest(request);
+ }
requests.push(request);
}
return requests;
@@ -67,23 +69,26 @@ HARImporter.Importer = class {
*/
static _fillRequestFromHAREntry(request, entry, pageLoad) {
// Request data.
- if (entry.request.postData)
+ if (entry.request.postData) {
request.setRequestFormData(true, entry.request.postData.text);
- else
+ } else {
request.setRequestFormData(false, null);
+ }
request.connectionId = entry.connection || '';
request.requestMethod = entry.request.method;
request.setRequestHeaders(entry.request.headers);
// Response data.
- if (entry.response.content.mimeType && entry.response.content.mimeType !== 'x-unknown')
+ if (entry.response.content.mimeType && entry.response.content.mimeType !== 'x-unknown') {
request.mimeType = entry.response.content.mimeType;
+ }
request.responseHeaders = entry.response.headers;
request.statusCode = entry.response.status;
request.statusText = entry.response.statusText;
let protocol = entry.response.httpVersion.toLowerCase();
- if (protocol === 'http/2.0')
+ if (protocol === 'http/2.0') {
protocol = 'h2';
+ }
request.protocol = protocol.replace(/^http\/2\.0?\+quic/, 'http/2+quic');
// Timing data.
@@ -96,19 +101,22 @@ HARImporter.Importer = class {
const bodySize = entry.response.bodySize > 0 ? entry.response.bodySize : 0;
request.resourceSize = contentSize || (headersSize + bodySize);
let transferSize = entry.response.customAsNumber('transferSize');
- if (transferSize === undefined)
+ if (transferSize === undefined) {
transferSize = entry.response.headersSize + entry.response.bodySize;
+ }
request.setTransferSize(transferSize >= 0 ? transferSize : 0);
const fromCache = entry.customAsString('fromCache');
- if (fromCache === 'memory')
+ if (fromCache === 'memory') {
request.setFromMemoryCache();
- else if (fromCache === 'disk')
+ } else if (fromCache === 'disk') {
request.setFromDiskCache();
+ }
const contentData = {error: null, content: null, encoded: entry.response.content.encoding === 'base64'};
- if (entry.response.content.text !== undefined)
+ if (entry.response.content.text !== undefined) {
contentData.content = entry.response.content.text;
+ }
request.setContentDataProvider(async () => contentData);
// Timing data.
@@ -119,20 +127,25 @@ HARImporter.Importer = class {
request.setResourceType(HARImporter.Importer._getResourceType(request, entry, pageLoad));
const priority = entry.customAsString('priority');
- if (Protocol.Network.ResourcePriority.hasOwnProperty(priority))
+ if (Protocol.Network.ResourcePriority.hasOwnProperty(priority)) {
request.setPriority(/** @type {!Protocol.Network.ResourcePriority} */ (priority));
+ }
const messages = entry.customAsArray('webSocketMessages');
if (messages) {
for (const message of messages) {
- if (message.time === undefined)
+ if (message.time === undefined) {
continue;
- if (!Object.values(SDK.NetworkRequest.WebSocketFrameType).includes(message.type))
+ }
+ if (!Object.values(SDK.NetworkRequest.WebSocketFrameType).includes(message.type)) {
continue;
- if (message.opcode === undefined)
+ }
+ if (message.opcode === undefined) {
continue;
- if (message.data === undefined)
+ }
+ if (message.data === undefined) {
continue;
+ }
const mask = message.type === SDK.NetworkRequest.WebSocketFrameType.Send;
request.addFrame(
@@ -153,20 +166,24 @@ HARImporter.Importer = class {
const customResourceTypeName = entry.customAsString('resourceType');
if (customResourceTypeName) {
const customResourceType = Common.ResourceType.fromName(customResourceTypeName);
- if (customResourceType)
+ if (customResourceType) {
return customResourceType;
+ }
}
- if (pageLoad && pageLoad.mainRequest === request)
+ if (pageLoad && pageLoad.mainRequest === request) {
return Common.resourceTypes.Document;
+ }
const resourceTypeFromMime = Common.ResourceType.fromMimeType(entry.response.content.mimeType);
- if (resourceTypeFromMime !== Common.resourceTypes.Other)
+ if (resourceTypeFromMime !== Common.resourceTypes.Other) {
return resourceTypeFromMime;
+ }
const resourceTypeFromUrl = Common.ResourceType.fromURL(entry.request.url);
- if (resourceTypeFromUrl)
+ if (resourceTypeFromUrl) {
return resourceTypeFromUrl;
+ }
return Common.resourceTypes.Other;
}
@@ -183,8 +200,9 @@ HARImporter.Importer = class {
* @return {number}
*/
function accumulateTime(timing) {
- if (timing === undefined || timing < 0)
+ if (timing === undefined || timing < 0) {
return -1;
+ }
lastEntry += timing;
return lastEntry;
}
@@ -195,8 +213,9 @@ HARImporter.Importer = class {
// SSL is part of connect for both HAR and Chrome's format so subtract it here.
const ssl = timings.ssl >= 0 ? timings.ssl : 0;
- if (timings.connect > 0)
+ if (timings.connect > 0) {
timings.connect -= ssl;
+ }
const timing = {
proxyStart: proxy > 0 ? lastEntry - proxy : -1,
proxyEnd: proxy > 0 ? lastEntry : -1,
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
index 30509ab1443..e119b9c02a7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
@@ -135,14 +135,17 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
HeapProfilerTestRunner.HeapNode.prototype = {
linkNode: function(node, type, nameOrIndex) {
- if (!this._builder)
+ if (!this._builder) {
throw new Error('parent node is not connected to a snapshot');
+ }
- if (!node._builder)
+ if (!node._builder) {
node._setBuilder(this._builder);
+ }
- if (nameOrIndex === undefined)
+ if (nameOrIndex === undefined) {
nameOrIndex = this._edgesCount;
+ }
++this._edgesCount;
@@ -156,8 +159,9 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
},
_setBuilder: function(builder) {
- if (this._builder)
+ if (this._builder) {
throw new Error('node reusing is prohibited');
+ }
this._builder = builder;
this._ordinal = this._builder._registerNode(this);
@@ -172,8 +176,9 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
rawSnapshot.nodes.push(0);
rawSnapshot.nodes.push(Object.keys(this._edges).length);
- for (const i in this._edges)
+ for (const i in this._edges) {
this._edges[i]._serialize(rawSnapshot);
+ }
}
};
@@ -185,8 +190,9 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
HeapProfilerTestRunner.HeapEdge.prototype = {
_serialize: function(rawSnapshot) {
- if (!this._targetNode._builder)
+ if (!this._targetNode._builder) {
throw new Error('Inconsistent state of node: ' + this._name + ' no builder assigned');
+ }
const builder = this._targetNode._builder;
rawSnapshot.edges.push(builder.lookupEdgeType(this._type));
@@ -249,8 +255,9 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
'strings': []
};
- for (let i = 0; i < this._nodes.length; ++i)
+ for (let i = 0; i < this._nodes.length; ++i) {
this._nodes[i]._serialize(rawSnapshot);
+ }
rawSnapshot.strings = this._strings.slice();
const meta = rawSnapshot.snapshot.meta;
@@ -270,25 +277,29 @@ HeapProfilerTestRunner.createHeapSnapshotMockFactories = function() {
},
lookupNodeType: function(typeName) {
- if (typeName === undefined)
+ if (typeName === undefined) {
throw new Error('wrong node type: ' + typeName);
+ }
- if (!(typeName in this._nodeTypesMap))
+ if (!(typeName in this._nodeTypesMap)) {
throw new Error('wrong node type name: ' + typeName);
+ }
return this._nodeTypesMap[typeName];
},
lookupEdgeType: function(typeName) {
- if (!(typeName in this._edgeTypesMap))
+ if (!(typeName in this._edgeTypesMap)) {
throw new Error('wrong edge type name: ' + typeName);
+ }
return this._edgeTypesMap[typeName];
},
lookupOrAddString: function(string) {
- if (string in this._string2id)
+ if (string in this._string2id) {
return this._string2id[string];
+ }
this._string2id[string] = this._strings.length;
this._strings.push(string);
@@ -364,8 +375,9 @@ HeapProfilerTestRunner.runHeapSnapshotTestSuite = function(testSuite) {
function runner() {
if (!testSuiteTests.length) {
- if (completeTestStack)
+ if (completeTestStack) {
TestRunner.addResult('FAIL: test already completed at ' + completeTestStack);
+ }
HeapProfilerTestRunner.completeProfilerTest();
completeTestStack = new Error().stack;
@@ -387,13 +399,15 @@ HeapProfilerTestRunner.runHeapSnapshotTestSuite = function(testSuite) {
HeapProfilerTestRunner.assertColumnContentsEqual = function(reference, actual) {
const length = Math.min(reference.length, actual.length);
- for (let i = 0; i < length; ++i)
+ for (let i = 0; i < length; ++i) {
TestRunner.assertEquals(reference[i], actual[i], 'row ' + i);
+ }
- if (reference.length > length)
+ if (reference.length > length) {
TestRunner.addResult('extra rows in reference array:\n' + reference.slice(length).join('\n'));
- else if (actual.length > length)
+ } else if (actual.length > length) {
TestRunner.addResult('extra rows in actual array:\n' + actual.slice(length).join('\n'));
+ }
};
HeapProfilerTestRunner.checkArrayIsSorted = function(contents, sortType, sortOrder) {
@@ -515,13 +529,15 @@ HeapProfilerTestRunner.columnContents = function(column, row) {
const parent = row || this._currentGrid().rootNode();
for (let node = parent.children[0]; node; node = node.traverseNextNode(true, parent, true)) {
- if (!node.selectable)
+ if (!node.selectable) {
continue;
+ }
let content = node.element().children[columnOrdinal];
- if (content.firstElementChild)
+ if (content.firstElementChild) {
content = content.firstElementChild;
+ }
result.push(content.textContent);
}
@@ -537,8 +553,9 @@ HeapProfilerTestRunner.countDataRows = function(row, filter) {
};
for (let node = row.children[0]; node; node = node.traverseNextNode(true, row, true)) {
- if (filter(node))
+ if (filter(node)) {
++result;
+ }
}
return result;
@@ -549,10 +566,11 @@ HeapProfilerTestRunner.expandRow = function(row, callback) {
row.once(Profiler.HeapSnapshotGridNode.Events.PopulateComplete).then(() => setTimeout(() => callback(row), 0));
(function expand() {
- if (row.hasChildren())
+ if (row.hasChildren()) {
row.expand();
- else
+ } else {
setTimeout(expand, 0);
+ }
})();
};
@@ -578,8 +596,9 @@ HeapProfilerTestRunner.findAndExpandRow = async function(name, callback) {
HeapProfilerTestRunner.findButtonsNode = function(row, startNode) {
for (let node = startNode || row.children[0]; node; node = node.traverseNextNode(true, row, true)) {
- if (!node.selectable && node.showNext)
+ if (!node.selectable && node.showNext) {
return node;
+ }
}
return null;
};
@@ -592,8 +611,9 @@ HeapProfilerTestRunner.findMatchingRow = function(matcher, parent) {
parent = parent || this._currentGrid().rootNode();
for (let node = parent.children[0]; node; node = node.traverseNextNode(true, parent, true)) {
- if (matcher(node))
+ if (matcher(node)) {
return node;
+ }
}
return null;
@@ -625,8 +645,9 @@ HeapProfilerTestRunner.takeAndOpenSnapshot = async function(generator, callback)
HeapProfilerTestRunner._takeAndOpenSnapshotCallback = callback;
TestRunner.override(TestRunner.HeapProfilerAgent, 'takeHeapSnapshot', pushGeneratedSnapshot);
- if (!UI.context.flavor(SDK.HeapProfilerModel))
+ if (!UI.context.flavor(SDK.HeapProfilerModel)) {
await new Promise(resolve => UI.context.addFlavorChangeListener(SDK.HeapProfilerModel, resolve));
+ }
profileType._takeHeapSnapshot();
};
@@ -641,10 +662,12 @@ HeapProfilerTestRunner.takeSnapshotPromise = function() {
function finishHeapSnapshot() {
const profiles = heapProfileType.getProfiles();
- if (!profiles.length)
+ if (!profiles.length) {
throw 'FAILED: no profiles found.';
- if (profiles.length > 1)
+ }
+ if (profiles.length > 1) {
throw `FAILED: wrong number of recorded profiles was found. profiles.length = ${profiles.length}`;
+ }
const profile = profiles[0];
UI.panels.heap_profiler.showProfile(profile);
@@ -693,8 +716,9 @@ HeapProfilerTestRunner.showProfileWhenAdded = function(title) {
};
HeapProfilerTestRunner._profileHeaderAdded = function(profile) {
- if (HeapProfilerTestRunner._showProfileWhenAdded === profile.title)
+ if (HeapProfilerTestRunner._showProfileWhenAdded === profile.title) {
UI.panels.heap_profiler.showProfile(profile);
+ }
};
HeapProfilerTestRunner._waitUntilProfileViewIsShown = function(title, callback) {
@@ -702,10 +726,11 @@ HeapProfilerTestRunner._waitUntilProfileViewIsShown = function(title, callback)
const profilesPanel = UI.panels.heap_profiler;
if (profilesPanel.visibleView && profilesPanel.visibleView.profile &&
- profilesPanel.visibleView._profileHeader.title === title)
+ profilesPanel.visibleView._profileHeader.title === title) {
callback(profilesPanel.visibleView);
- else
+ } else {
HeapProfilerTestRunner._waitUntilProfileViewIsShownCallback = {title: title, callback: callback};
+ }
};
@@ -719,8 +744,9 @@ HeapProfilerTestRunner._profileViewRefresh = function() {
};
HeapProfilerTestRunner.startSamplingHeapProfiler = async function() {
- if (!UI.context.flavor(SDK.HeapProfilerModel))
+ if (!UI.context.flavor(SDK.HeapProfilerModel)) {
await new Promise(resolve => UI.context.addFlavorChangeListener(SDK.HeapProfilerModel, resolve));
+ }
Profiler.SamplingHeapProfileType.instance._startRecordingProfile();
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
index 44b9b2e61f3..9b449ceee2c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker.js
@@ -2,6 +2,68 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Release build has Runtime.js bundled.
-if (!self.Runtime)
+
+self.importScripts('platform/utilities.js');
+if (!self.Root || !self.Root.Runtime) {
self.importScripts('Runtime.js');
-Runtime.startWorker('heap_snapshot_worker');
+}
+
+// Due to a lack of ESM within workers the functionality required by the
+// worker is duplicated here from Common. When ESM lands in Workers, this code
+// can be replaced with the ESM equivalent.
+// TODO(https://crbug.com/680046) Remove the dupe code below.
+
+const _substitutionStrings = new WeakMap();
+
+/**
+ * @param {string} string
+ * @param {?ArrayLike} values
+ * @return {string}
+ */
+function serializeUIString(string, values = []) {
+ const messageParts = [string];
+ const serializedMessage = {messageParts, values};
+ return JSON.stringify(serializedMessage);
+}
+
+/**
+ * @param {string} serializedMessage
+ * @return {*}
+ */
+function deserializeUIString(serializedMessage) {
+ if (!serializedMessage) {
+ return {};
+ }
+
+ return JSON.parse(serializedMessage);
+}
+
+function localize(string) {
+ return string;
+}
+
+function UIString(string, vararg) {
+ return String.vsprintf(localize(string), Array.prototype.slice.call(arguments, 1));
+}
+
+/**
+ * @param {!Array<string>|string} strings
+ * @param {...*} vararg
+ * @return {string}
+ */
+self.ls = function(strings, vararg) {
+ if (typeof strings === 'string') {
+ return strings;
+ }
+ let substitutionString = _substitutionStrings.get(strings);
+ if (!substitutionString) {
+ substitutionString = strings.join('%s');
+ _substitutionStrings.set(strings, substitutionString);
+ }
+ return UIString(substitutionString, ...Array.prototype.slice.call(arguments, 1));
+};
+
+self.serializeUIString = serializeUIString;
+self.deserializeUIString = deserializeUIString;
+
+Root.Runtime.startWorker('heap_snapshot_worker');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/AllocationProfile.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/AllocationProfile.js
index dcb9c9c0d95..b58b29307c6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/AllocationProfile.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/AllocationProfile.js
@@ -96,8 +96,9 @@ HeapSnapshotWorker.AllocationProfile = class {
functionInfo.addTraceTopNode(result);
const rawChildren = rawNodeArray[nodeOffset + childrenOffset];
- for (let i = 0; i < rawChildren.length; i += nodeFieldCount)
+ for (let i = 0; i < rawChildren.length; i += nodeFieldCount) {
result.children.push(traverseNode(rawChildren, i, result));
+ }
return result;
}
@@ -109,14 +110,16 @@ HeapSnapshotWorker.AllocationProfile = class {
* @return {!Array.<!HeapSnapshotModel.SerializedAllocationNode>}
*/
serializeTraceTops() {
- if (this._traceTops)
+ if (this._traceTops) {
return this._traceTops;
+ }
const result = this._traceTops = [];
const functionInfos = this._functionInfos;
for (let i = 0; i < functionInfos.length; i++) {
const info = functionInfos[i];
- if (info.totalCount === 0)
+ if (info.totalCount === 0) {
continue;
+ }
const nodeId = this._nextNodeId++;
const isRoot = i === 0;
result.push(this._serializeNode(
@@ -143,8 +146,9 @@ HeapSnapshotWorker.AllocationProfile = class {
const branchingCallers = [];
const callers = node.callers();
- for (let i = 0; i < callers.length; i++)
+ for (let i = 0; i < callers.length; i++) {
branchingCallers.push(this._serializeCaller(callers[i]));
+ }
return new HeapSnapshotModel.AllocationNodeCallers(nodesWithSingleCaller, branchingCallers);
}
@@ -324,8 +328,9 @@ HeapSnapshotWorker.FunctionAllocationInfo = class {
* @param {!HeapSnapshotWorker.TopDownAllocationNode} node
*/
addTraceTopNode(node) {
- if (node.allocationCount === 0)
+ if (node.allocationCount === 0) {
return;
+ }
this._traceTops.push(node);
this.totalCount += node.allocationCount;
this.totalSize += node.allocationSize;
@@ -337,10 +342,12 @@ HeapSnapshotWorker.FunctionAllocationInfo = class {
* @return {?HeapSnapshotWorker.BottomUpAllocationNode}
*/
bottomUpRoot() {
- if (!this._traceTops.length)
+ if (!this._traceTops.length) {
return null;
- if (!this._bottomUpTree)
+ }
+ if (!this._bottomUpTree) {
this._buildAllocationTraceTree();
+ }
return this._bottomUpTree;
}
@@ -362,8 +369,9 @@ HeapSnapshotWorker.FunctionAllocationInfo = class {
bottomUpNode.liveSize += liveSize;
bottomUpNode.traceTopIds.push(traceId);
node = node.parent;
- if (node === null)
+ if (node === null) {
break;
+ }
bottomUpNode = bottomUpNode.addCaller(node);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
index 4be1eb4700c..2c8a778822d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
@@ -332,8 +332,9 @@ HeapSnapshotWorker.HeapSnapshotRetainerEdge = class {
* @param {number} retainerIndex
*/
setRetainerIndex(retainerIndex) {
- if (retainerIndex === this._retainerIndex)
+ if (retainerIndex === this._retainerIndex) {
return;
+ }
this._retainerIndex = retainerIndex;
this._globalEdgeIndex = this._snapshot._retainingEdges[retainerIndex];
this._retainingNodeIndex = this._snapshot._retainingNodes[retainerIndex];
@@ -349,14 +350,16 @@ HeapSnapshotWorker.HeapSnapshotRetainerEdge = class {
}
_node() {
- if (!this._nodeInstance)
+ if (!this._nodeInstance) {
this._nodeInstance = this._snapshot.createNode(this._retainingNodeIndex);
+ }
return this._nodeInstance;
}
_edge() {
- if (!this._edgeInstance)
+ if (!this._edgeInstance) {
this._edgeInstance = this._snapshot.createEdge(this._globalEdgeIndex);
+ }
return this._edgeInstance;
}
@@ -736,8 +739,9 @@ HeapSnapshotWorker.HeapSnapshotFilteredIterator = class {
}
_skipFilteredItems() {
- while (this._iterator.hasNext() && !this._filter(this._iterator.item()))
+ while (this._iterator.hasNext() && !this._filter(this._iterator.item())) {
this._iterator.next();
+ }
}
};
@@ -756,7 +760,7 @@ HeapSnapshotWorker.HeapSnapshotProgress = class {
* @param {string} status
*/
updateStatus(status) {
- this._sendUpdateEvent(Common.UIString(status));
+ this._sendUpdateEvent(self.serializeUIString(status));
}
/**
@@ -766,7 +770,7 @@ HeapSnapshotWorker.HeapSnapshotProgress = class {
*/
updateProgress(title, value, total) {
const percentValue = ((total ? (value / total) : 0) * 100).toFixed(0);
- this._sendUpdateEvent(Common.UIString(title, percentValue));
+ this._sendUpdateEvent(self.serializeUIString(title, [percentValue]));
}
/**
@@ -774,17 +778,19 @@ HeapSnapshotWorker.HeapSnapshotProgress = class {
*/
reportProblem(error) {
// May be undefined in tests.
- if (this._dispatcher)
+ if (this._dispatcher) {
this._dispatcher.sendEvent(HeapSnapshotModel.HeapSnapshotProgressEvent.BrokenSnapshot, error);
+ }
}
/**
- * @param {string} text
+ * @param {string} serializedText
*/
- _sendUpdateEvent(text) {
+ _sendUpdateEvent(serializedText) {
// May be undefined in tests.
- if (this._dispatcher)
- this._dispatcher.sendEvent(HeapSnapshotModel.HeapSnapshotProgressEvent.Update, text);
+ if (this._dispatcher) {
+ this._dispatcher.sendEvent(HeapSnapshotModel.HeapSnapshotProgressEvent.Update, serializedText);
+ }
}
};
@@ -803,8 +809,9 @@ HeapSnapshotWorker.HeapSnapshotProblemReport = class {
* @param {string} error
*/
addError(error) {
- if (this._errors.length > 100)
+ if (this._errors.length > 100) {
return;
+ }
this._errors.push(error);
}
@@ -844,8 +851,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
this._noDistance = -5;
this._rootNodeIndex = 0;
- if (profile.snapshot.root_index)
+ if (profile.snapshot.root_index) {
this._rootNodeIndex = profile.snapshot.root_index;
+ }
this._snapshotDiffs = {};
this._aggregatesForDiff = null;
@@ -912,34 +920,34 @@ HeapSnapshotWorker.HeapSnapshot = class {
this._firstDominatedNodeIndex = new Uint32Array(this.nodeCount + 1);
this._dominatedNodes = new Uint32Array(this.nodeCount - 1);
- this._progress.updateStatus('Building edge indexes\u2026');
+ this._progress.updateStatus(ls`Building edge indexes\u2026`);
this._buildEdgeIndexes();
- this._progress.updateStatus('Building retainers\u2026');
+ this._progress.updateStatus(ls`Building retainers\u2026`);
this._buildRetainers();
- this._progress.updateStatus('Calculating node flags\u2026');
+ this._progress.updateStatus(ls`Calculating node flags\u2026`);
this.calculateFlags();
- this._progress.updateStatus('Calculating distances\u2026');
+ this._progress.updateStatus(ls`Calculating distances\u2026`);
this.calculateDistances();
- this._progress.updateStatus('Building postorder index\u2026');
+ this._progress.updateStatus(ls`Building postorder index\u2026`);
const result = this._buildPostOrderIndex();
// Actually it is array that maps node ordinal number to dominator node ordinal number.
- this._progress.updateStatus('Building dominator tree\u2026');
+ this._progress.updateStatus(ls`Building dominator tree\u2026`);
this._dominatorsTree =
this._buildDominatorTree(result.postOrderIndex2NodeOrdinal, result.nodeOrdinal2PostOrderIndex);
- this._progress.updateStatus('Calculating retained sizes\u2026');
+ this._progress.updateStatus(ls`Calculating retained sizes\u2026`);
this._calculateRetainedSizes(result.postOrderIndex2NodeOrdinal);
- this._progress.updateStatus('Building dominated nodes\u2026');
+ this._progress.updateStatus(ls`Building dominated nodes\u2026`);
this._buildDominatedNodes();
- this._progress.updateStatus('Calculating statistics\u2026');
+ this._progress.updateStatus(ls`Calculating statistics\u2026`);
this.calculateStatistics();
- this._progress.updateStatus('Calculating samples\u2026');
+ this._progress.updateStatus(ls`Calculating samples\u2026`);
this._buildSamples();
- this._progress.updateStatus('Building locations\u2026');
+ this._progress.updateStatus(ls`Building locations\u2026`);
this._buildLocationMap();
- this._progress.updateStatus('Finished processing.');
+ this._progress.updateStatus(ls`Finished processing.`);
if (this._profile.snapshot.trace_function_count) {
- this._progress.updateStatus('Building allocation statistics\u2026');
+ this._progress.updateStatus(ls`Building allocation statistics\u2026`);
const nodes = this.nodes;
const nodesLength = nodes.length;
const nodeFieldCount = this._nodeFieldCount;
@@ -949,14 +957,15 @@ HeapSnapshotWorker.HeapSnapshot = class {
node.nodeIndex = nodeIndex;
const traceNodeId = node.traceNodeId();
let stats = liveObjects[traceNodeId];
- if (!stats)
+ if (!stats) {
liveObjects[traceNodeId] = stats = {count: 0, size: 0, ids: []};
+ }
stats.count++;
stats.size += node.selfSize();
stats.ids.push(node.id());
}
this._allocationProfile = new HeapSnapshotWorker.AllocationProfile(this._profile, liveObjects);
- this._progress.updateStatus('Done');
+ this._progress.updateStatus(ls`Done`);
}
}
@@ -991,8 +1000,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
for (let toNodeFieldIndex = edgeToNodeOffset, l = containmentEdges.length; toNodeFieldIndex < l;
toNodeFieldIndex += edgeFieldsCount) {
const toNodeIndex = containmentEdges[toNodeFieldIndex];
- if (toNodeIndex % nodeFieldCount)
+ if (toNodeIndex % nodeFieldCount) {
throw new Error('Invalid toNodeIndex ' + toNodeIndex);
+ }
++firstRetainerIndex[toNodeIndex / nodeFieldCount];
}
for (let i = 0, firstUnusedRetainerSlot = 0; i < nodeCount; i++) {
@@ -1010,8 +1020,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const srcNodeIndex = srcNodeOrdinal * nodeFieldCount;
for (let edgeIndex = firstEdgeIndex; edgeIndex < nextNodeFirstEdgeIndex; edgeIndex += edgeFieldsCount) {
const toNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
- if (toNodeIndex % nodeFieldCount)
+ if (toNodeIndex % nodeFieldCount) {
throw new Error('Invalid toNodeIndex ' + toNodeIndex);
+ }
const firstRetainerSlotIndex = firstRetainerIndex[toNodeIndex / nodeFieldCount];
const nextUnusedRetainerSlotIndex = firstRetainerSlotIndex + (--retainingNodes[firstRetainerSlotIndex]);
retainingNodes[nextUnusedRetainerSlotIndex] = srcNodeIndex;
@@ -1076,8 +1087,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
* @return {number}
*/
_getDominatedIndex(nodeIndex) {
- if (nodeIndex % this._nodeFieldCount)
+ if (nodeIndex % this._nodeFieldCount) {
throw new Error('Invalid nodeIndex: ' + nodeIndex);
+ }
return this._firstDominatedNodeIndex[nodeIndex / this._nodeFieldCount];
}
@@ -1109,23 +1121,26 @@ HeapSnapshotWorker.HeapSnapshot = class {
const query = searchConfig.query;
function filterString(matchedStringIndexes, string, index) {
- if (string.indexOf(query) !== -1)
+ if (string.indexOf(query) !== -1) {
matchedStringIndexes.add(index);
+ }
return matchedStringIndexes;
}
const regexp = searchConfig.isRegex ? new RegExp(query) : createPlainTextSearchRegex(query, 'i');
function filterRegexp(matchedStringIndexes, string, index) {
- if (regexp.test(string))
+ if (regexp.test(string)) {
matchedStringIndexes.add(index);
+ }
return matchedStringIndexes;
}
const stringFilter = (searchConfig.isRegex || !searchConfig.caseSensitive) ? filterRegexp : filterString;
const stringIndexes = this.strings.reduce(stringFilter, new Set());
- if (!stringIndexes.size)
+ if (!stringIndexes.size) {
return [];
+ }
const filter = this._createFilter(nodeFilter);
const nodeIds = [];
@@ -1138,10 +1153,12 @@ HeapSnapshotWorker.HeapSnapshot = class {
for (let nodeIndex = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
node.nodeIndex = nodeIndex;
- if (filter && !filter(node))
+ if (filter && !filter(node)) {
continue;
- if (stringIndexes.has(nodes[nodeIndex + nodeNameOffset]))
+ }
+ if (stringIndexes.has(nodes[nodeIndex + nodeNameOffset])) {
nodeIds.push(nodes[nodeIndex + nodeIdOffset]);
+ }
}
return nodeIds;
}
@@ -1179,11 +1196,13 @@ HeapSnapshotWorker.HeapSnapshot = class {
*/
_createAllocationStackFilter(bottomUpAllocationNodeId) {
const traceIds = this._allocationProfile.traceIds(bottomUpAllocationNodeId);
- if (!traceIds.length)
+ if (!traceIds.length) {
return undefined;
+ }
const set = {};
- for (let i = 0; i < traceIds.length; i++)
+ for (let i = 0; i < traceIds.length; i++) {
set[traceIds[i]] = true;
+ }
/**
* @param {!HeapSnapshotWorker.HeapSnapshotNode} node
* @return {boolean}
@@ -1206,14 +1225,16 @@ HeapSnapshotWorker.HeapSnapshot = class {
const aggregates = this._buildAggregates(filter);
this._calculateClassesRetainedSize(aggregates.aggregatesByClassIndex, filter);
aggregatesByClassName = aggregates.aggregatesByClassName;
- if (key)
+ if (key) {
this._aggregates[key] = aggregatesByClassName;
+ }
}
if (sortedIndexes && (!key || !this._aggregatesSortedFlags[key])) {
this._sortAggregateIndexes(aggregatesByClassName);
- if (key)
+ if (key) {
this._aggregatesSortedFlags[key] = sortedIndexes;
+ }
}
return aggregatesByClassName;
}
@@ -1240,8 +1261,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
allocationStack(nodeIndex) {
const node = this.createNode(nodeIndex);
const allocationNodeId = node.traceNodeId();
- if (!allocationNodeId)
+ if (!allocationNodeId) {
return null;
+ }
return this._allocationProfile.serializeAllocationStack(allocationNodeId);
}
@@ -1249,8 +1271,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
* @return {!Object.<string, !HeapSnapshotModel.AggregateForDiff>}
*/
aggregatesForDiff() {
- if (this._aggregatesForDiff)
+ if (this._aggregatesForDiff) {
return this._aggregatesForDiff;
+ }
const aggregatesByClassName = this.aggregates(true, 'allObjects');
this._aggregatesForDiff = {};
@@ -1288,8 +1311,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const nodeCount = this.nodeCount;
const distances = this._nodeDistances;
const noDistance = this._noDistance;
- for (let i = 0; i < nodeCount; ++i)
+ for (let i = 0; i < nodeCount; ++i) {
distances[i] = noDistance;
+ }
const nodesToVisit = new Uint32Array(this.nodeCount);
let nodesToVisitLength = 0;
@@ -1341,15 +1365,18 @@ HeapSnapshotWorker.HeapSnapshot = class {
node.nodeIndex = nodeIndex;
for (let edgeIndex = firstEdgeIndex; edgeIndex < edgesEnd; edgeIndex += edgeFieldsCount) {
const edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
- if (edgeType === edgeWeakType)
+ if (edgeType === edgeWeakType) {
continue;
+ }
const childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
const childNodeOrdinal = childNodeIndex / nodeFieldCount;
- if (distances[childNodeOrdinal] !== noDistance)
+ if (distances[childNodeOrdinal] !== noDistance) {
continue;
+ }
edge.edgeIndex = edgeIndex;
- if (filter && !filter(node, edge))
+ if (filter && !filter(node, edge)) {
continue;
+ }
distances[childNodeOrdinal] = distance;
nodesToVisit[nodesToVisitLength++] = childNodeIndex;
}
@@ -1380,11 +1407,13 @@ HeapSnapshotWorker.HeapSnapshot = class {
for (let nodeIndex = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
node.nodeIndex = nodeIndex;
- if (filter && !filter(node))
+ if (filter && !filter(node)) {
continue;
+ }
const selfSize = nodes[nodeIndex + selfSizeOffset];
- if (!selfSize && nodes[nodeIndex + nodeTypeOffset] !== nodeNativeType)
+ if (!selfSize && nodes[nodeIndex + nodeTypeOffset] !== nodeNativeType) {
continue;
+ }
const classIndex = node.classIndex();
const nodeOrdinal = nodeIndex / nodeFieldCount;
const distance = nodeDistances[nodeOrdinal];
@@ -1456,8 +1485,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
classes.push(classIndex);
}
}
- for (let i = dominatedIndexFrom; i < dominatedIndexTo; i++)
+ for (let i = dominatedIndexFrom; i < dominatedIndexTo; i++) {
list.push(dominatedNodes[i]);
+ }
const l = list.length;
while (sizes[sizes.length - 1] === l) {
@@ -1535,18 +1565,21 @@ HeapSnapshotWorker.HeapSnapshot = class {
if (edgeIndex < edgesEnd) {
stackCurrentEdge[stackTop] += edgeFieldsCount;
const edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
- if (!this._isEssentialEdge(nodeOrdinal * nodeFieldCount, edgeType))
+ if (!this._isEssentialEdge(nodeOrdinal * nodeFieldCount, edgeType)) {
continue;
+ }
const childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
const childNodeOrdinal = childNodeIndex / nodeFieldCount;
- if (visited[childNodeOrdinal])
+ if (visited[childNodeOrdinal]) {
continue;
+ }
const nodeFlag = !flags || (flags[nodeOrdinal] & flag);
const childNodeFlag = !flags || (flags[childNodeOrdinal] & flag);
// We are skipping the edges from non-page-owned nodes to page-owned nodes.
// Otherwise the dominators for the objects that also were retained by debugger would be affected.
- if (nodeOrdinal !== rootNodeOrdinal && childNodeFlag && !nodeFlag)
+ if (nodeOrdinal !== rootNodeOrdinal && childNodeFlag && !nodeFlag) {
continue;
+ }
++stackTop;
stackNodes[stackTop] = childNodeOrdinal;
stackCurrentEdge[stackTop] = firstEdgeIndexes[childNodeOrdinal];
@@ -1559,8 +1592,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
}
}
- if (postOrderIndex === nodeCount || iteration > 1)
+ if (postOrderIndex === nodeCount || iteration > 1) {
break;
+ }
const errors = new HeapSnapshotWorker.HeapSnapshotProblemReport(
`Heap snapshot: ${
nodeCount - postOrderIndex
@@ -1573,8 +1607,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
stackNodes[0] = rootNodeOrdinal;
stackCurrentEdge[0] = firstEdgeIndexes[rootNodeOrdinal + 1]; // no need to reiterate its edges
for (let i = 0; i < nodeCount; ++i) {
- if (visited[i] || !this._hasOnlyWeakRetainers(i))
+ if (visited[i] || !this._hasOnlyWeakRetainers(i)) {
continue;
+ }
// Add all nodes that have only weak retainers to traverse their subgraphs.
stackNodes[++stackTop] = i;
@@ -1583,8 +1618,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
dumpNode.nodeIndex = i * nodeFieldCount;
const retainers = [];
- for (let it = dumpNode.retainers(); it.hasNext(); it.next())
+ for (let it = dumpNode.retainers(); it.hasNext(); it.next()) {
retainers.push(`${it.item().node().name()}@${it.item().node().id()}.${it.item().name()}`);
+ }
errors.addError(`${dumpNode.name()} @${dumpNode.id()} weak retainers: ${retainers.join(', ')}`);
}
console.warn(errors.toString());
@@ -1599,8 +1635,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
// visited after all orphan nodes and their subgraphs.
--postOrderIndex;
for (let i = 0; i < nodeCount; ++i) {
- if (visited[i])
+ if (visited[i]) {
continue;
+ }
dumpNode.nodeIndex = i * nodeFieldCount;
errors.addError(dumpNode.name() + ' @' + dumpNode.id());
// Fix it by giving the node a postorder index anyway.
@@ -1633,8 +1670,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
for (let retainerIndex = beginRetainerIndex; retainerIndex < endRetainerIndex; ++retainerIndex) {
const retainerEdgeIndex = retainingEdges[retainerIndex];
const retainerEdgeType = containmentEdges[retainerEdgeIndex + edgeTypeOffset];
- if (retainerEdgeType !== edgeWeakType && retainerEdgeType !== edgeShortcutType)
+ if (retainerEdgeType !== edgeWeakType && retainerEdgeType !== edgeShortcutType) {
return false;
+ }
}
return true;
}
@@ -1666,8 +1704,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const rootPostOrderedIndex = nodesCount - 1;
const noEntry = nodesCount;
const dominators = new Uint32Array(nodesCount);
- for (let i = 0; i < rootPostOrderedIndex; ++i)
+ for (let i = 0; i < rootPostOrderedIndex; ++i) {
dominators[i] = noEntry;
+ }
dominators[rootPostOrderedIndex] = rootPostOrderedIndex;
// The affected array is used to mark entries which dominators
@@ -1680,8 +1719,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
for (let edgeIndex = firstEdgeIndexes[nodeOrdinal]; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
const edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
- if (!this._isEssentialEdge(this._rootNodeIndex, edgeType))
+ if (!this._isEssentialEdge(this._rootNodeIndex, edgeType)) {
continue;
+ }
const childNodeOrdinal = containmentEdges[edgeIndex + edgeToNodeOffset] / nodeFieldCount;
affected[nodeOrdinal2PostOrderIndex[childNodeOrdinal]] = 1;
}
@@ -1691,13 +1731,15 @@ HeapSnapshotWorker.HeapSnapshot = class {
while (changed) {
changed = false;
for (let postOrderIndex = rootPostOrderedIndex - 1; postOrderIndex >= 0; --postOrderIndex) {
- if (affected[postOrderIndex] === 0)
+ if (affected[postOrderIndex] === 0) {
continue;
+ }
affected[postOrderIndex] = 0;
// If dominator of the entry has already been set to root,
// then it can't propagate any further.
- if (dominators[postOrderIndex] === rootPostOrderedIndex)
+ if (dominators[postOrderIndex] === rootPostOrderedIndex) {
continue;
+ }
nodeOrdinal = postOrderIndex2NodeOrdinal[postOrderIndex];
const nodeFlag = !flags || (flags[nodeOrdinal] & flag);
let newDominatorIndex = noEntry;
@@ -1708,36 +1750,42 @@ HeapSnapshotWorker.HeapSnapshot = class {
const retainerEdgeIndex = retainingEdges[retainerIndex];
const retainerEdgeType = containmentEdges[retainerEdgeIndex + edgeTypeOffset];
const retainerNodeIndex = retainingNodes[retainerIndex];
- if (!this._isEssentialEdge(retainerNodeIndex, retainerEdgeType))
+ if (!this._isEssentialEdge(retainerNodeIndex, retainerEdgeType)) {
continue;
+ }
orphanNode = false;
const retainerNodeOrdinal = retainerNodeIndex / nodeFieldCount;
const retainerNodeFlag = !flags || (flags[retainerNodeOrdinal] & flag);
// We are skipping the edges from non-page-owned nodes to page-owned nodes.
// Otherwise the dominators for the objects that also were retained by debugger would be affected.
- if (retainerNodeIndex !== rootNodeIndex && nodeFlag && !retainerNodeFlag)
+ if (retainerNodeIndex !== rootNodeIndex && nodeFlag && !retainerNodeFlag) {
continue;
+ }
let retanerPostOrderIndex = nodeOrdinal2PostOrderIndex[retainerNodeOrdinal];
if (dominators[retanerPostOrderIndex] !== noEntry) {
if (newDominatorIndex === noEntry) {
newDominatorIndex = retanerPostOrderIndex;
} else {
while (retanerPostOrderIndex !== newDominatorIndex) {
- while (retanerPostOrderIndex < newDominatorIndex)
+ while (retanerPostOrderIndex < newDominatorIndex) {
retanerPostOrderIndex = dominators[retanerPostOrderIndex];
- while (newDominatorIndex < retanerPostOrderIndex)
+ }
+ while (newDominatorIndex < retanerPostOrderIndex) {
newDominatorIndex = dominators[newDominatorIndex];
+ }
}
}
// If idom has already reached the root, it doesn't make sense
// to check other retainers.
- if (newDominatorIndex === rootPostOrderedIndex)
+ if (newDominatorIndex === rootPostOrderedIndex) {
break;
+ }
}
}
// Make root dominator of orphans.
- if (orphanNode)
+ if (orphanNode) {
newDominatorIndex = rootPostOrderedIndex;
+ }
if (newDominatorIndex !== noEntry && dominators[postOrderIndex] !== newDominatorIndex) {
dominators[postOrderIndex] = newDominatorIndex;
changed = true;
@@ -1772,8 +1820,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const dominatorsTree = this._dominatorsTree;
const retainedSizes = this._retainedSizes;
- for (let nodeOrdinal = 0; nodeOrdinal < nodeCount; ++nodeOrdinal)
+ for (let nodeOrdinal = 0; nodeOrdinal < nodeCount; ++nodeOrdinal) {
retainedSizes[nodeOrdinal] = nodes[nodeOrdinal * nodeFieldCount + nodeSelfSizeOffset];
+ }
// Propagate retained sizes for each node excluding root.
for (let postOrderIndex = 0; postOrderIndex < nodeCount - 1; ++postOrderIndex) {
@@ -1801,14 +1850,16 @@ HeapSnapshotWorker.HeapSnapshot = class {
let fromNodeOrdinal = 0;
let toNodeOrdinal = this.nodeCount;
const rootNodeOrdinal = this._rootNodeIndex / nodeFieldCount;
- if (rootNodeOrdinal === fromNodeOrdinal)
+ if (rootNodeOrdinal === fromNodeOrdinal) {
fromNodeOrdinal = 1;
- else if (rootNodeOrdinal === toNodeOrdinal - 1)
+ } else if (rootNodeOrdinal === toNodeOrdinal - 1) {
toNodeOrdinal = toNodeOrdinal - 1;
- else
+ } else {
throw new Error('Root node is expected to be either first or last');
- for (let nodeOrdinal = fromNodeOrdinal; nodeOrdinal < toNodeOrdinal; ++nodeOrdinal)
+ }
+ for (let nodeOrdinal = fromNodeOrdinal; nodeOrdinal < toNodeOrdinal; ++nodeOrdinal) {
++indexArray[dominatorsTree[nodeOrdinal]];
+ }
// Put in the first slot of each dominatedNodes slice the count of entries
// that will be filled.
let firstDominatedNodeIndex = 0;
@@ -1830,8 +1881,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
_buildSamples() {
const samples = this._rawSamples;
- if (!samples || !samples.length)
+ if (!samples || !samples.length) {
return;
+ }
const sampleCount = samples.length / 2;
const sizeForRange = new Array(sampleCount);
const timestamps = new Array(sampleCount);
@@ -1854,8 +1906,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
const nodeId = node.id();
// JS objects have odd ids, skip native objects.
- if (nodeId % 2 === 0)
+ if (nodeId % 2 === 0) {
continue;
+ }
const rangeIndex = lastAssignedIds.lowerBound(nodeId);
if (rangeIndex === sampleCount) {
// TODO: make heap profiler not allocate while taking snapshot
@@ -1922,21 +1975,24 @@ HeapSnapshotWorker.HeapSnapshot = class {
*/
calculateSnapshotDiff(baseSnapshotId, baseSnapshotAggregates) {
let snapshotDiff = this._snapshotDiffs[baseSnapshotId];
- if (snapshotDiff)
+ if (snapshotDiff) {
return snapshotDiff;
+ }
snapshotDiff = {};
const aggregates = this.aggregates(true, 'allObjects');
for (const className in baseSnapshotAggregates) {
const baseAggregate = baseSnapshotAggregates[className];
const diff = this._calculateDiffForClass(baseAggregate, aggregates[className]);
- if (diff)
+ if (diff) {
snapshotDiff[className] = diff;
+ }
}
const emptyBaseAggregate = new HeapSnapshotModel.AggregateForDiff();
for (const className in aggregates) {
- if (className in baseSnapshotAggregates)
+ if (className in baseSnapshotAggregates) {
continue;
+ }
snapshotDiff[className] = this._calculateDiffForClass(emptyBaseAggregate, aggregates[className]);
}
@@ -1996,15 +2052,17 @@ HeapSnapshotWorker.HeapSnapshot = class {
}
diff.countDelta = diff.addedCount - diff.removedCount;
diff.sizeDelta = diff.addedSize - diff.removedSize;
- if (!diff.addedCount && !diff.removedCount)
+ if (!diff.addedCount && !diff.removedCount) {
return null;
+ }
return diff;
}
_nodeForSnapshotObjectId(snapshotObjectId) {
for (let it = this._allNodes(); it.hasNext(); it.next()) {
- if (it.node.id() === snapshotObjectId)
+ if (it.node.id() === snapshotObjectId) {
return it.node;
+ }
}
return null;
}
@@ -2015,8 +2073,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
*/
nodeClassName(snapshotObjectId) {
const node = this._nodeForSnapshotObjectId(snapshotObjectId);
- if (node)
+ if (node) {
return node.className();
+ }
return null;
}
@@ -2027,8 +2086,9 @@ HeapSnapshotWorker.HeapSnapshot = class {
idsOfObjectsWithName(name) {
const ids = [];
for (let it = this._allNodes(); it.hasNext(); it.next()) {
- if (it.item().name() === name)
+ if (it.item().name() === name) {
ids.push(it.item().id());
+ }
}
return ids;
}
@@ -2120,10 +2180,12 @@ HeapSnapshotWorker.HeapSnapshot = class {
for (let nodeIndex = this._nodeIdOffset; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
const nextId = nodes[nodeIndex];
// JS objects have odd ids, skip native objects.
- if (nextId % 2 === 0)
+ if (nextId % 2 === 0) {
continue;
- if (id < nextId)
+ }
+ if (id < nextId) {
id = nextId;
+ }
}
return id;
}
@@ -2199,11 +2261,13 @@ HeapSnapshotWorker.HeapSnapshotItemProvider = class {
}
_createIterationOrder() {
- if (this._iterationOrder)
+ if (this._iterationOrder) {
return;
+ }
this._iterationOrder = [];
- for (let iterator = this._iterator; iterator.hasNext(); iterator.next())
+ for (let iterator = this._iterator; iterator.hasNext(); iterator.next()) {
this._iterationOrder.push(iterator.item().itemIndex());
+ }
}
/**
@@ -2220,18 +2284,22 @@ HeapSnapshotWorker.HeapSnapshotItemProvider = class {
*/
serializeItemsRange(begin, end) {
this._createIterationOrder();
- if (begin > end)
+ if (begin > end) {
throw new Error('Start position > end position: ' + begin + ' > ' + end);
- if (end > this._iterationOrder.length)
+ }
+ if (end > this._iterationOrder.length) {
end = this._iterationOrder.length;
+ }
if (this._sortedPrefixLength < end && begin < this._iterationOrder.length - this._sortedSuffixLength) {
this.sort(
this._currentComparator, this._sortedPrefixLength, this._iterationOrder.length - 1 - this._sortedSuffixLength,
begin, end - 1);
- if (begin <= this._sortedPrefixLength)
+ if (begin <= this._sortedPrefixLength) {
this._sortedPrefixLength = end;
- if (end >= this._iterationOrder.length - this._sortedSuffixLength)
+ }
+ if (end >= this._iterationOrder.length - this._sortedSuffixLength) {
this._sortedSuffixLength = this._iterationOrder.length - begin;
+ }
}
let position = begin;
const count = end - begin;
@@ -2291,10 +2359,12 @@ HeapSnapshotWorker.HeapSnapshotEdgesProvider = class extends HeapSnapshotWorker.
function compareEdgeFieldName(ascending, indexA, indexB) {
edgeA.edgeIndex = indexA;
edgeB.edgeIndex = indexB;
- if (edgeB.name() === '__proto__')
+ if (edgeB.name() === '__proto__') {
return -1;
- if (edgeA.name() === '__proto__')
+ }
+ if (edgeA.name() === '__proto__') {
return 1;
+ }
const result = edgeA.hasStringName() === edgeB.hasStringName() ?
(edgeA.name() < edgeB.name() ? -1 : (edgeA.name() > edgeB.name() ? 1 : 0)) :
(edgeA.hasStringName() ? -1 : 1);
@@ -2316,37 +2386,44 @@ HeapSnapshotWorker.HeapSnapshotEdgesProvider = class extends HeapSnapshotWorker.
function compareEdgeAndNode(indexA, indexB) {
let result = compareEdgeFieldName(ascending1, indexA, indexB);
- if (result === 0)
+ if (result === 0) {
result = compareNodeField(fieldName2, ascending2, indexA, indexB);
- if (result === 0)
+ }
+ if (result === 0) {
return indexA - indexB;
+ }
return result;
}
function compareNodeAndEdge(indexA, indexB) {
let result = compareNodeField(fieldName1, ascending1, indexA, indexB);
- if (result === 0)
+ if (result === 0) {
result = compareEdgeFieldName(ascending2, indexA, indexB);
- if (result === 0)
+ }
+ if (result === 0) {
return indexA - indexB;
+ }
return result;
}
function compareNodeAndNode(indexA, indexB) {
let result = compareNodeField(fieldName1, ascending1, indexA, indexB);
- if (result === 0)
+ if (result === 0) {
result = compareNodeField(fieldName2, ascending2, indexA, indexB);
- if (result === 0)
+ }
+ if (result === 0) {
return indexA - indexB;
+ }
return result;
}
- if (fieldName1 === '!edgeName')
+ if (fieldName1 === '!edgeName') {
this._iterationOrder.sortRange(compareEdgeAndNode, leftBound, rightBound, windowLeft, windowRight);
- else if (fieldName2 === '!edgeName')
+ } else if (fieldName2 === '!edgeName') {
this._iterationOrder.sortRange(compareNodeAndEdge, leftBound, rightBound, windowLeft, windowRight);
- else
+ } else {
this._iterationOrder.sortRange(compareNodeAndNode, leftBound, rightBound, windowLeft, windowRight);
+ }
}
};
@@ -2375,17 +2452,20 @@ HeapSnapshotWorker.HeapSnapshotNodesProvider = class extends HeapSnapshotWorker.
let i = 0;
for (; i < this._iterationOrder.length; i++) {
node.nodeIndex = this._iterationOrder[i];
- if (node.id() === snapshotObjectId)
+ if (node.id() === snapshotObjectId) {
break;
+ }
}
- if (i === this._iterationOrder.length)
+ if (i === this._iterationOrder.length) {
return -1;
+ }
const targetNodeIndex = this._iterationOrder[i];
let smallerCount = 0;
const compare = this._buildCompareFunction(this._currentComparator);
for (let i = 0; i < this._iterationOrder.length; i++) {
- if (compare(this._iterationOrder[i], targetNodeIndex) < 0)
+ if (compare(this._iterationOrder[i], targetNodeIndex) < 0) {
++smallerCount;
+ }
}
return smallerCount;
}
@@ -2421,8 +2501,9 @@ HeapSnapshotWorker.HeapSnapshotNodesProvider = class extends HeapSnapshotWorker.
nodeA.nodeIndex = indexA;
nodeB.nodeIndex = indexB;
let result = sortByNodeField(fieldAccessor1, ascending1);
- if (result === 0)
+ if (result === 0) {
result = sortByNodeField(fieldAccessor2, ascending2);
+ }
return result || indexA - indexB;
}
@@ -2529,8 +2610,9 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
* @return {boolean}
*/
function filter(node, edge) {
- if (node.isHidden())
+ if (node.isHidden()) {
return edge.name() !== 'sloppy_function_map' || node.rawName() !== 'system / NativeContext';
+ }
if (node.isArray()) {
// DescriptorArrays are fixed arrays used to hold instance descriptors.
// The format of the these objects is:
@@ -2545,8 +2627,9 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
// links may not be valid for all the maps. We just skip
// all the descriptor links when calculating distances.
// For more details see http://crbug.com/413608
- if (node.rawName() !== '(map descriptors)')
+ if (node.rawName() !== '(map descriptors)') {
return true;
+ }
const index = edge.name();
return index < 2 || (index % 3) !== 1;
}
@@ -2591,11 +2674,13 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
const node = this.rootNode();
for (let nodeIndex = 0, ordinal = 0; nodeIndex < nodesLength; nodeIndex += nodeFieldCount, ordinal++) {
const nodeType = nodes[nodeIndex + nodeTypeOffset];
- if (nodeType !== nodeNativeType)
+ if (nodeType !== nodeNativeType) {
continue;
+ }
node.nodeIndex = nodeIndex;
- if (node.name().startsWith('Detached '))
+ if (node.name().startsWith('Detached ')) {
this._flags[ordinal] |= flag;
+ }
}
}
@@ -2619,25 +2704,30 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
const list = [];
for (let iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
- if (iter.edge.node().isUserRoot())
+ if (iter.edge.node().isUserRoot()) {
list.push(iter.edge.node().nodeIndex / nodeFieldCount);
+ }
}
while (list.length) {
const nodeOrdinal = list.pop();
- if (flags[nodeOrdinal] & flag)
+ if (flags[nodeOrdinal] & flag) {
continue;
+ }
flags[nodeOrdinal] |= flag;
const beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
const endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
for (let edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
const childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
const childNodeOrdinal = childNodeIndex / nodeFieldCount;
- if (flags[childNodeOrdinal] & flag)
+ if (flags[childNodeOrdinal] & flag) {
continue;
+ }
const type = containmentEdges[edgeIndex + edgeTypeOffset];
- if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType || type === weakEdgeType)
+ if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType ||
+ type === weakEdgeType) {
continue;
+ }
list.push(childNodeOrdinal);
}
}
@@ -2671,8 +2761,9 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
const nodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
if (edgeType === edgeElementType) {
node.nodeIndex = nodeIndex;
- if (!node.isDocumentDOMTreesRoot())
+ if (!node.isDocumentDOMTreesRoot()) {
continue;
+ }
} else if (edgeType !== edgeShortcutType) {
continue;
}
@@ -2689,11 +2780,13 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
for (let edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
const childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
const childNodeOrdinal = childNodeIndex / nodeFieldCount;
- if (flags[childNodeOrdinal] & pageObjectFlag)
+ if (flags[childNodeOrdinal] & pageObjectFlag) {
continue;
+ }
const type = containmentEdges[edgeIndex + edgeTypeOffset];
- if (type === edgeWeakType)
+ if (type === edgeWeakType) {
continue;
+ }
nodesToVisit[nodesToVisitLength++] = childNodeOrdinal;
flags[childNodeOrdinal] |= pageObjectFlag;
}
@@ -2729,14 +2822,15 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
}
const nodeType = nodes[nodeIndex + nodeTypeOffset];
node.nodeIndex = nodeIndex;
- if (nodeType === nodeNativeType)
+ if (nodeType === nodeNativeType) {
sizeNative += nodeSize;
- else if (nodeType === nodeCodeType)
+ } else if (nodeType === nodeCodeType) {
sizeCode += nodeSize;
- else if (nodeType === nodeConsStringType || nodeType === nodeSlicedStringType || node.type() === 'string')
+ } else if (nodeType === nodeConsStringType || nodeType === nodeSlicedStringType || node.type() === 'string') {
sizeStrings += nodeSize;
- else if (node.name() === 'Array')
+ } else if (node.name() === 'Array') {
sizeJSArrays += this._calculateArraySize(node);
+ }
}
this._statistics = new HeapSnapshotModel.Statistics();
this._statistics.total = this.totalSize;
@@ -2765,15 +2859,18 @@ HeapSnapshotWorker.JSHeapSnapshot = class extends HeapSnapshotWorker.HeapSnapsho
const edgeInternalType = this._edgeInternalType;
for (let edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
const edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
- if (edgeType !== edgeInternalType)
+ if (edgeType !== edgeInternalType) {
continue;
+ }
const edgeName = strings[containmentEdges[edgeIndex + edgeNameOffset]];
- if (edgeName !== 'elements')
+ if (edgeName !== 'elements') {
continue;
+ }
const elementsNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
node.nodeIndex = elementsNodeIndex;
- if (node.retainersCount() === 1)
+ if (node.retainersCount() === 1) {
size += node.selfSize();
+ }
break;
}
return size;
@@ -2869,10 +2966,11 @@ HeapSnapshotWorker.JSHeapSnapshotNode = class extends HeapSnapshotWorker.HeapSna
const edgeType = edges[edgeIndex + edgeTypeOffset];
if (edgeType === edgeInternalType) {
const edgeName = strings[edges[edgeIndex + edgeNameOffset]];
- if (edgeName === 'first')
+ if (edgeName === 'first') {
firstNodeIndex = edges[edgeIndex + edgeToNodeOffset];
- else if (edgeName === 'second')
+ } else if (edgeName === 'second') {
secondNodeIndex = edges[edgeIndex + edgeToNodeOffset];
+ }
}
}
nodesStack.push(secondNodeIndex);
@@ -2908,8 +3006,9 @@ HeapSnapshotWorker.JSHeapSnapshotNode = class extends HeapSnapshotWorker.HeapSna
const snapshot = this._snapshot;
const nodes = snapshot.nodes;
const type = nodes[this.nodeIndex + snapshot._nodeTypeOffset];
- if (type === snapshot._nodeObjectType || type === snapshot._nodeNativeType)
+ if (type === snapshot._nodeObjectType || type === snapshot._nodeNativeType) {
return nodes[this.nodeIndex + snapshot._nodeNameOffset];
+ }
return -1 - type;
}
@@ -2964,10 +3063,12 @@ HeapSnapshotWorker.JSHeapSnapshotNode = class extends HeapSnapshotWorker.HeapSna
serialize() {
const result = super.serialize();
const flags = this._snapshot._flagsOfNode(this);
- if (flags & this._snapshot._nodeFlags.canBeQueried)
+ if (flags & this._snapshot._nodeFlags.canBeQueried) {
result.canBeQueried = true;
- if (flags & this._snapshot._nodeFlags.detachedDOMTreeNode)
+ }
+ if (flags & this._snapshot._nodeFlags.detachedDOMTreeNode) {
result.detachedDOMTreeNode = true;
+ }
return result;
}
};
@@ -2998,8 +3099,9 @@ HeapSnapshotWorker.JSHeapSnapshotEdge = class extends HeapSnapshotWorker.HeapSna
* @return {boolean}
*/
hasStringName() {
- if (!this.isShortcut())
+ if (!this.isShortcut()) {
return this._hasStringName();
+ }
return isNaN(parseInt(this._name(), 10));
}
@@ -3051,8 +3153,9 @@ HeapSnapshotWorker.JSHeapSnapshotEdge = class extends HeapSnapshotWorker.HeapSna
*/
name() {
const name = this._name();
- if (!this.isShortcut())
+ if (!this.isShortcut()) {
return String(name);
+ }
const numName = parseInt(name, 10);
return String(isNaN(numName) ? name : numName);
}
@@ -3073,10 +3176,11 @@ HeapSnapshotWorker.JSHeapSnapshotEdge = class extends HeapSnapshotWorker.HeapSna
case 'property':
return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
case 'shortcut':
- if (typeof name === 'string')
+ if (typeof name === 'string') {
return name.indexOf(' ') === -1 ? '.' + name : '["' + name + '"]';
- else
+ } else {
return '[' + name + ']';
+ }
case 'internal':
case 'hidden':
case 'invisible':
@@ -3177,6 +3281,7 @@ HeapSnapshotWorker.JSHeapSnapshotRetainerEdge = class extends HeapSnapshotWorker
(function disableLoggingForTest() {
// Runtime doesn't exist because this file is loaded as a one-off
// file in some inspector-protocol tests.
- if (self.Runtime && Runtime.queryParam('test'))
+ if (self.Root && self.Root.Runtime && Root.Runtime.queryParam('test')) {
console.warn = () => undefined;
+ }
})();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js
index b7dd4f87015..249710ad084 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js
@@ -55,8 +55,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
close() {
this._done = true;
- if (this._dataCallback)
+ if (this._dataCallback) {
this._dataCallback('');
+ }
}
/**
@@ -94,8 +95,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
const startIndex = index;
while (index < length) {
const code = this._json.charCodeAt(index);
- if (char0 > code || code > char9)
+ if (char0 > code || code > char9) {
break;
+ }
nextNumber *= 10;
nextNumber += (code - char0);
++index;
@@ -109,10 +111,11 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
}
_parseStringsArray() {
- this._progress.updateStatus('Parsing strings\u2026');
+ this._progress.updateStatus(ls`Parsing strings\u2026`);
const closingBracketIndex = this._json.lastIndexOf(']');
- if (closingBracketIndex === -1)
+ if (closingBracketIndex === -1) {
throw new Error('Incomplete JSON');
+ }
this._json = this._json.slice(0, closingBracketIndex + 1);
this._snapshot.strings = JSON.parse(this._json);
}
@@ -122,8 +125,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
*/
write(chunk) {
this._buffer += chunk;
- if (!this._dataCallback)
+ if (!this._dataCallback) {
return;
+ }
this._dataCallback(this._buffer);
this._dataCallback = null;
this._buffer = '';
@@ -144,8 +148,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
async _findToken(token, startIndex) {
while (true) {
const pos = this._json.indexOf(token, startIndex || 0);
- if (pos !== -1)
+ if (pos !== -1) {
return pos;
+ }
startIndex = this._json.length - token.length + 1;
this._json += await this._fetchChunk();
}
@@ -175,8 +180,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
async _parseInput() {
const snapshotToken = '"snapshot"';
const snapshotTokenIndex = await this._findToken(snapshotToken);
- if (snapshotTokenIndex === -1)
+ if (snapshotTokenIndex === -1) {
throw new Error('Snapshot token not found');
+ }
this._progress.updateStatus(ls`Loading snapshot info\u2026`);
const json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
@@ -186,8 +192,9 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
this._snapshot.snapshot = /** @type {!HeapSnapshotWorker.HeapSnapshotHeader} */ (JSON.parse(metaJSON));
});
this._jsonTokenizer.write(json);
- while (this._jsonTokenizer)
+ while (this._jsonTokenizer) {
this._jsonTokenizer.write(await this._fetchChunk());
+ }
this._snapshot.nodes = await this._parseArray(
'"nodes"', ls`Loading nodes\u2026 %d%%`,
@@ -211,20 +218,23 @@ HeapSnapshotWorker.HeapSnapshotLoader = class {
this._json = this._json.slice(closeBracketIndex + 1);
}
- if (this._snapshot.snapshot.meta.sample_fields)
+ if (this._snapshot.snapshot.meta.sample_fields) {
this._snapshot.samples = await this._parseArray('"samples"', ls`Loading samples\u2026`);
+ }
- if (this._snapshot.snapshot.meta['location_fields'])
+ if (this._snapshot.snapshot.meta['location_fields']) {
this._snapshot.locations = await this._parseArray('"locations"', ls`Loading locations\u2026`);
- else
+ } else {
this._snapshot.locations = [];
+ }
this._progress.updateStatus(ls`Loading strings\u2026`);
const stringsTokenIndex = await this._findToken('"strings"');
const bracketIndex = await this._findToken('[', stringsTokenIndex);
this._json = this._json.slice(bracketIndex);
- while (!this._done)
+ while (!this._done) {
this._json += await this._fetchChunk();
+ }
this._parseStringsArray();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js
index 2eb618683fc..f2d3379f5ae 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.js
@@ -41,8 +41,9 @@ HeapSnapshotWorker.HeapSnapshotWorkerDispatcher = class {
_findFunction(name) {
const path = name.split('.');
let result = this._global;
- for (let i = 0; i < path.length; ++i)
+ for (let i = 0; i < path.length; ++i) {
result = result[path[i]];
+ }
return result;
}
@@ -75,8 +76,9 @@ HeapSnapshotWorker.HeapSnapshotWorkerDispatcher = class {
case 'factory': {
const object = this._objects[data.objectId];
const result = object[data.methodName].apply(object, data.methodArguments);
- if (result)
+ if (result) {
this._objects[data.newObjectId] = result;
+ }
response.result = !!result;
break;
}
@@ -96,8 +98,9 @@ HeapSnapshotWorker.HeapSnapshotWorkerDispatcher = class {
} catch (e) {
response.error = e.toString();
response.errorCallStack = e.stack;
- if (data.methodName)
+ if (data.methodName) {
response.errorMethodName = data.methodName;
+ }
}
this._postMessage(response);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp
index bea64f4b9e2..db239fb2e7c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp
@@ -1,27 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <message name="IDS_DEVTOOLS_0f705e2ea0d470cf4e78f85ce73abc3c" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Calculating samples…
+ </message>
+ <message name="IDS_DEVTOOLS_15e828e7c9470740e5da2bd96f26809f" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building locations…
+ </message>
+ <message name="IDS_DEVTOOLS_1e6dbaafd43ee6c7ce436757c5563160" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building retainers…
+ </message>
<message name="IDS_DEVTOOLS_239026e523e6f9780426e03637c5b4a4" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading strings…
</message>
+ <message name="IDS_DEVTOOLS_42b1c19d788d56dae8f4274ae0e06388" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building dominated nodes…
+ </message>
+ <message name="IDS_DEVTOOLS_508b42300b35ed4e3062adf330b76aad" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building dominator tree…
+ </message>
+ <message name="IDS_DEVTOOLS_58d7770bfad35df21bae2d5820e3be52" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building edge indexes…
+ </message>
<message name="IDS_DEVTOOLS_58e8a5ca400f834526b09d680ddbc5d5" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading samples…
</message>
+ <message name="IDS_DEVTOOLS_5e3a0ca620683b8428b4dbda33bf1f5d" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Finished processing.
+ </message>
<message name="IDS_DEVTOOLS_6a542856aa30e3e814eaed146e67b2fd" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading nodes… <ph name="PH1">$1d<ex>38</ex></ph>%%
</message>
<message name="IDS_DEVTOOLS_7da2f27d62adf93b01c2c041f37667b9" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Processing snapshot…
</message>
+ <message name="IDS_DEVTOOLS_82e20e6748434e5048a36bf2d4b33578" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Calculating retained sizes…
+ </message>
<message name="IDS_DEVTOOLS_84c0ec1ee2bc769daf265e63bd793201" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading snapshot info…
</message>
+ <message name="IDS_DEVTOOLS_93093f55895541ab4360826523fe066e" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building postorder index…
+ </message>
+ <message name="IDS_DEVTOOLS_991feea6b04d59d7115962d5427a64fe" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Calculating node flags…
+ </message>
<message name="IDS_DEVTOOLS_9bdae72f224411b7f1027a2c5c7c519b" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading locations…
</message>
<message name="IDS_DEVTOOLS_b0da59cea23d810234b75c2357748ad3" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading edges… <ph name="PH1">$1d<ex>30</ex></ph>%%
</message>
+ <message name="IDS_DEVTOOLS_bfb105e5a3da1a90bd1eb98b4fa36f3f" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Calculating statistics…
+ </message>
+ <message name="IDS_DEVTOOLS_d0622d0589a212a59cf8b5859e58c670" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Calculating distances…
+ </message>
<message name="IDS_DEVTOOLS_d67d63eca2747a30e1ffaeb04389c0bb" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot">
Loading allocation traces… <ph name="PH1">$1d<ex>30</ex></ph>%%
</message>
+ <message name="IDS_DEVTOOLS_d86c288a983db9a91432d2d13386170f" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Building allocation statistics…
+ </message>
+ <message name="IDS_DEVTOOLS_f92965e2c8a7afb3c1b9a5c09a263636" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Done
+ </message>
+ <message name="IDS_DEVTOOLS_fae03f5c27a9765eec716f3e6c600945" desc="Text to indicate the status of a heap snapshot in the Performance Pane">
+ Parsing strings…
+ </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/help/Help.js b/chromium/third_party/blink/renderer/devtools/front_end/help/Help.js
index dedbb7b655c..71b3bd3bcbf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/help/Help.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/help/Help.js
@@ -29,10 +29,12 @@ Help._innerShowReleaseNoteIfNeeded = function(lastSeenVersion, latestVersion, sh
Help._releaseNoteVersionSetting.set(latestVersion);
return;
}
- if (!showReleaseNote)
+ if (!showReleaseNote) {
return;
- if (lastSeenVersion >= latestVersion)
+ }
+ if (lastSeenVersion >= latestVersion) {
return;
+ }
Help._releaseNoteVersionSetting.set(latestVersion);
UI.viewManager.showView(Help.releaseNoteViewId, true);
};
@@ -59,9 +61,10 @@ Help.HelpLateInitialization = class {
/**
* @override
*/
- run() {
- if (!Host.isUnderTest())
+ async run() {
+ if (!Host.isUnderTest()) {
Help._showReleaseNoteIfNeeded();
+ }
}
};
@@ -76,7 +79,7 @@ Help.ReleaseNotesActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- InspectorFrontendHost.openInNewTab(Help.latestReleaseNote().link);
+ Host.InspectorFrontendHost.openInNewTab(Help.latestReleaseNote().link);
return true;
}
};
@@ -92,7 +95,8 @@ Help.ReportIssueActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- InspectorFrontendHost.openInNewTab('https://bugs.chromium.org/p/chromium/issues/entry?template=DevTools+issue');
+ Host.InspectorFrontendHost.openInNewTab(
+ 'https://bugs.chromium.org/p/chromium/issues/entry?template=DevTools+issue');
return true;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteText.js b/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteText.js
index 727bb003d18..e0395077dc8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteText.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteText.js
@@ -12,6 +12,50 @@ const commandMenuShortcut = Host.isMac() ? 'Command+Shift+P' : 'Control+Shift+P'
/** @type {!Array<!Help.ReleaseNote>} */
Help.releaseNoteText = [
+
+ {
+ version: 21,
+ header: 'Highlights from the Chrome 79 update',
+ highlights: [
+ {
+ title: 'Debug why a cookie was blocked',
+ subtitle: 'Click a resource in the Network panel and go to the updated Cookies tab.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#blockedcookies',
+ },
+ {
+ title: 'View cookie values',
+ subtitle: 'Click a row in the Cookies pane in the Application panel to see the cookie\'s value.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#cookiepreviews',
+ },
+ {
+ title: 'Simulate prefers-color-scheme and prefers-reduced-motion preferences',
+ subtitle: 'Open the Rendering tab to force your site into dark or light mode or set motion preferences.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#userpreferences',
+ },
+ {
+ title: 'Code coverage updates',
+ subtitle: 'More accessible colors, a filter text box, and a new integration with the Sources panel.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#coverage',
+ },
+ {
+ title: 'Debug why a network resource was requested',
+ subtitle: 'Click a resource in the Network panel and go to the new Initiator tab.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#initiator',
+ },
+ {
+ title: 'Console and Sources panels respect indentation preferences again',
+ subtitle: 'Set your preference in Settings > Preferences > Sources > Default Indentation.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#indentation',
+ },
+ {
+ title: 'New shortcuts for cursor navigation',
+ subtitle: 'Press Control+P or Control+N to move your cursor to the line above or below.',
+ link: 'https://developers.google.com/web/updates/2019/10/devtools#console',
+ },
+ ],
+ link: 'https://developers.google.com/web/updates/2019/10/devtools',
+ },
+
{
version: 20,
header: 'Highlights from the Chrome 78 update',
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js b/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js
index 41eb8db629b..dc0f50ddd29 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js
@@ -33,7 +33,7 @@ Help.ReleaseNoteView = class extends UI.VBox {
const actionContainer = container.createChild('div', 'release-note-action-container');
actionContainer.appendChild(UI.createTextButton(Common.UIString('Learn more'), event => {
event.consume(true);
- InspectorFrontendHost.openInNewTab(releaseNote.link);
+ Host.InspectorFrontendHost.openInNewTab(releaseNote.link);
}));
actionContainer.appendChild(UI.createTextButton(Common.UIString('Close'), event => {
event.consume(true);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
index 53ee7ea10f7..ad49d793ea5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/help/help_strings.grdp
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<message name="IDS_DEVTOOLS_8381815d48c2d49f31dce1807ae0507c" desc="Title of an action in the help tool to file an issue">
- Report a DevTools issue
+ Report a <ph name="LOCKED_1">DevTools</ph> issue
</message>
<message name="IDS_DEVTOOLS_7d0ee6fed10d3d4e5c9ee496729ab519" desc="Title of an action in the help tool to release notes">
Release notes
@@ -15,7 +15,7 @@
<message name="IDS_DEVTOOLS_91770f038cd944a1d3b9b347edeb2b10" desc="Title of the 'What's New' tool in the bottom drawer">
What&apos;s New
</message>
- <message name="IDS_DEVTOOLS_a1c58e94227389415de133efdf78ea6e" desc="A title of the 'Appearance' setting category">
- Appearance
+ <message name="IDS_DEVTOOLS_ae0e4bdad7b5f67141743366026d2ea5" desc="A search term referring to a software defect (i.e. bug) that can be entered in the command menu">
+ bug
</message>
</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
index af2b16336eb..c8e0eda582e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
@@ -31,25 +31,32 @@
* @implements {InspectorFrontendHostAPI}
* @unrestricted
*/
-Host.InspectorFrontendHostStub = class {
+export class InspectorFrontendHostStub {
/**
* @suppressGlobalPropertiesCheck
*/
constructor() {
/**
* @param {!Event} event
+ * @this {InspectorFrontendHostAPI}
*/
function stopEventPropagation(event) {
// Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode.
- const zoomModifier = Host.isMac() ? event.metaKey : event.ctrlKey;
- if (zoomModifier && (event.keyCode === 187 || event.keyCode === 189))
+ const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey;
+ if (zoomModifier && (event.keyCode === 187 || event.keyCode === 189)) {
event.stopPropagation();
+ }
}
- document.addEventListener('keydown', stopEventPropagation, true);
+ document.addEventListener('keydown', stopEventPropagation.bind(this), true);
/**
* @type {!Map<string, !Array<string>>}
*/
this._urlsBeingSaved = new Map();
+
+ /**
+ * @type {!Common.EventTarget}
+ */
+ this.events;
}
/**
@@ -58,11 +65,13 @@ Host.InspectorFrontendHostStub = class {
*/
platform() {
let match = navigator.userAgent.match(/Windows NT/);
- if (match)
+ if (match) {
return 'windows';
+ }
match = navigator.userAgent.match(/Mac OS X/);
- if (match)
+ if (match) {
return 'mac';
+ }
return 'linux';
}
@@ -128,10 +137,13 @@ Host.InspectorFrontendHostStub = class {
/**
* @override
- * @param {string} text
+ * @param {?(string|undefined)} text
* @suppressGlobalPropertiesCheck
*/
copyText(text) {
+ if (text === undefined || text === null) {
+ return;
+ }
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
} else if (document.queryCommandSupported('copy')) {
@@ -175,7 +187,7 @@ Host.InspectorFrontendHostStub = class {
this._urlsBeingSaved.set(url, buffer);
}
buffer.push(content);
- this.events.dispatchEventToListeners(InspectorFrontendHostAPI.Events.SavedURL, {url, fileSystemPath: url});
+ this.events.dispatchEventToListeners(Host.InspectorFrontendHostAPI.Events.SavedURL, {url, fileSystemPath: url});
}
/**
@@ -186,7 +198,7 @@ Host.InspectorFrontendHostStub = class {
append(url, content) {
const buffer = this._urlsBeingSaved.get(url);
buffer.push(content);
- this.events.dispatchEventToListeners(InspectorFrontendHostAPI.Events.AppendedToURL, url);
+ this.events.dispatchEventToListeners(Host.InspectorFrontendHostAPI.Events.AppendedToURL, url);
}
/**
@@ -239,7 +251,7 @@ Host.InspectorFrontendHostStub = class {
* @override
*/
requestFileSystems() {
- this.events.dispatchEventToListeners(InspectorFrontendHostAPI.Events.FileSystemsLoaded, []);
+ this.events.dispatchEventToListeners(Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, []);
}
/**
@@ -274,7 +286,7 @@ Host.InspectorFrontendHostStub = class {
* @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
*/
loadNetworkResource(url, headers, streamId, callback) {
- Runtime.loadResourcePromise(url)
+ Root.Runtime.loadResourcePromise(url)
.then(function(text) {
Host.ResourceLoader.streamWrite(streamId, text);
callback({statusCode: 200});
@@ -290,8 +302,9 @@ Host.InspectorFrontendHostStub = class {
*/
getPreferences(callback) {
const prefs = {};
- for (const name in window.localStorage)
+ for (const name in window.localStorage) {
prefs[name] = window.localStorage[name];
+ }
callback(prefs);
}
@@ -486,19 +499,25 @@ Host.InspectorFrontendHostStub = class {
setAddExtensionCallback(callback) {
// Extensions are not supported in hosted mode.
}
-};
+}
+
+/**
+ * @type {!InspectorFrontendHostStub}
+ */
+let _InspectorFrontendHost = window.InspectorFrontendHost;
/**
* @unrestricted
*/
-Host.InspectorFrontendAPIImpl = class {
+export class InspectorFrontendAPIImpl {
constructor() {
this._debugFrontend =
- !!Runtime.queryParam('debugFrontend') || (window['InspectorTest'] && window['InspectorTest']['debugTest']);
+ !!Root.Runtime.queryParam('debugFrontend') || (window['InspectorTest'] && window['InspectorTest']['debugTest']);
- const descriptors = InspectorFrontendHostAPI.EventDescriptors;
- for (let i = 0; i < descriptors.length; ++i)
+ const descriptors = Host.InspectorFrontendHostAPI.EventDescriptors;
+ for (let i = 0; i < descriptors.length; ++i) {
this[descriptors[i][1]] = this._dispatch.bind(this, descriptors[i][0], descriptors[i][2], descriptors[i][3]);
+ }
}
/**
@@ -509,26 +528,28 @@ Host.InspectorFrontendAPIImpl = class {
_dispatch(name, signature, runOnceLoaded) {
const params = Array.prototype.slice.call(arguments, 3);
- if (this._debugFrontend)
+ if (this._debugFrontend) {
setImmediate(innerDispatch);
- else
+ } else {
innerDispatch();
+ }
function innerDispatch() {
// Single argument methods get dispatched with the param.
if (signature.length < 2) {
try {
- InspectorFrontendHost.events.dispatchEventToListeners(name, params[0]);
+ _InspectorFrontendHost.events.dispatchEventToListeners(name, params[0]);
} catch (e) {
console.error(e + ' ' + e.stack);
}
return;
}
const data = {};
- for (let i = 0; i < signature.length; ++i)
+ for (let i = 0; i < signature.length; ++i) {
data[signature[i]] = params[i];
+ }
try {
- InspectorFrontendHost.events.dispatchEventToListeners(name, data);
+ _InspectorFrontendHost.events.dispatchEventToListeners(name, data);
} catch (e) {
console.error(e + ' ' + e.stack);
}
@@ -542,58 +563,69 @@ Host.InspectorFrontendAPIImpl = class {
streamWrite(id, chunk) {
Host.ResourceLoader.streamWrite(id, chunk);
}
-};
+}
-/**
- * @type {!InspectorFrontendHostAPI}
- */
-let InspectorFrontendHost = window.InspectorFrontendHost;
(function() {
function initializeInspectorFrontendHost() {
let proto;
- if (!InspectorFrontendHost) {
+ if (!_InspectorFrontendHost) {
// Instantiate stub for web-hosted mode if necessary.
- window.InspectorFrontendHost = InspectorFrontendHost = new Host.InspectorFrontendHostStub();
+ window.InspectorFrontendHost = _InspectorFrontendHost = new InspectorFrontendHostStub();
} else {
// Otherwise add stubs for missing methods that are declared in the interface.
- proto = Host.InspectorFrontendHostStub.prototype;
+ proto = InspectorFrontendHostStub.prototype;
for (const name of Object.getOwnPropertyNames(proto)) {
const stub = proto[name];
- if (typeof stub !== 'function' || InspectorFrontendHost[name])
+ if (typeof stub !== 'function' || _InspectorFrontendHost[name]) {
continue;
+ }
console.error(
- 'Incompatible embedder: method InspectorFrontendHost.' + name + ' is missing. Using stub instead.');
- InspectorFrontendHost[name] = stub;
+ 'Incompatible embedder: method Host.InspectorFrontendHost.' + name + ' is missing. Using stub instead.');
+ _InspectorFrontendHost[name] = stub;
}
}
// Attach the events object.
- InspectorFrontendHost.events = new Common.Object();
+ _InspectorFrontendHost.events = new Common.Object();
}
// FIXME: This file is included into both apps, since the devtools_app needs the InspectorFrontendHostAPI only,
// so the host instance should not initialized there.
initializeInspectorFrontendHost();
- window.InspectorFrontendAPI = new Host.InspectorFrontendAPIImpl();
+ window.InspectorFrontendAPI = new InspectorFrontendAPIImpl();
})();
/**
- * @type {!Common.EventTarget}
- */
-InspectorFrontendHost.events;
-
-/**
* @param {!Object<string, string>=} prefs
* @return {boolean}
*/
-Host.isUnderTest = function(prefs) {
+export function isUnderTest(prefs) {
// Integration tests rely on test queryParam.
- if (Runtime.queryParam('test'))
+ if (Root.Runtime.queryParam('test')) {
return true;
+ }
// Browser tests rely on prefs.
- if (prefs)
+ if (prefs) {
return prefs['isUnderTest'] === 'true';
+ }
return Common.settings && Common.settings.createSetting('isUnderTest', false).get();
-};
+}
+
+/* Legacy exported object */
+self.Host = self.Host || {};
+
+/* Legacy exported object */
+Host = Host || {};
+
+/** @type {!InspectorFrontendHostStub} */
+Host.InspectorFrontendHost = _InspectorFrontendHost;
+
+/** @constructor */
+Host.InspectorFrontendHostStub = InspectorFrontendHostStub;
+
+/** @constructor */
+Host.InspectorFrontendAPIImpl = InspectorFrontendAPIImpl;
+
+Host.isUnderTest = isUnderTest; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js
index f14863058da..3c0b0efbabb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js
@@ -1,30 +1,9 @@
// Copyright (c) 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.
-/** @interface */
-function InspectorFrontendHostAPI() {
-}
-window.InspectorFrontendHostAPI = InspectorFrontendHostAPI;
-/** @typedef
-{{
- type: string,
- id: (number|undefined),
- label: (string|undefined),
- enabled: (boolean|undefined),
- checked: (boolean|undefined),
- subItems: (!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>|undefined)
-}} */
-InspectorFrontendHostAPI.ContextMenuDescriptor;
-
-/** @typedef
-{{
- statusCode: number,
- headers: (!Object.<string, string>|undefined)
-}} */
-InspectorFrontendHostAPI.LoadNetworkResourceResult;
/** @enum {symbol} */
-InspectorFrontendHostAPI.Events = {
+export const Events = {
AppendedToURL: Symbol('appendedToURL'),
CanceledSaveURL: Symbol('canceledSaveURL'),
ContextMenuCleared: Symbol('contextMenuCleared'),
@@ -45,6 +24,7 @@ InspectorFrontendHostAPI.Events = {
IndexingWorked: Symbol('indexingWorked'),
IndexingDone: Symbol('indexingDone'),
KeyEventUnhandled: Symbol('keyEventUnhandled'),
+ ReattachMainTarget: Symbol('reattachMainTarget'),
ReloadInspectedPage: Symbol('reloadInspectedPage'),
RevealSourceLine: Symbol('revealSourceLine'),
SavedURL: Symbol('savedURL'),
@@ -54,282 +34,44 @@ InspectorFrontendHostAPI.Events = {
ShowPanel: Symbol('showPanel')
};
-InspectorFrontendHostAPI.EventDescriptors = [
- [InspectorFrontendHostAPI.Events.AppendedToURL, 'appendedToURL', ['url']],
- [InspectorFrontendHostAPI.Events.CanceledSaveURL, 'canceledSaveURL', ['url']],
- [InspectorFrontendHostAPI.Events.ContextMenuCleared, 'contextMenuCleared', []],
- [InspectorFrontendHostAPI.Events.ContextMenuItemSelected, 'contextMenuItemSelected', ['id']],
- [InspectorFrontendHostAPI.Events.DeviceCountUpdated, 'deviceCountUpdated', ['count']],
- [InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, 'devicesDiscoveryConfigChanged', ['config']],
- [
- InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged, 'devicesPortForwardingStatusChanged', ['status']
- ],
- [InspectorFrontendHostAPI.Events.DevicesUpdated, 'devicesUpdated', ['devices']],
- [InspectorFrontendHostAPI.Events.DispatchMessage, 'dispatchMessage', ['messageObject']],
- [InspectorFrontendHostAPI.Events.DispatchMessageChunk, 'dispatchMessageChunk', ['messageChunk', 'messageSize']],
- [InspectorFrontendHostAPI.Events.EnterInspectElementMode, 'enterInspectElementMode', []],
- [InspectorFrontendHostAPI.Events.EyeDropperPickedColor, 'eyeDropperPickedColor', ['color']],
- [InspectorFrontendHostAPI.Events.FileSystemsLoaded, 'fileSystemsLoaded', ['fileSystems']],
- [InspectorFrontendHostAPI.Events.FileSystemRemoved, 'fileSystemRemoved', ['fileSystemPath']],
- [InspectorFrontendHostAPI.Events.FileSystemAdded, 'fileSystemAdded', ['errorMessage', 'fileSystem']],
- [
- InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, 'fileSystemFilesChangedAddedRemoved',
- ['changed', 'added', 'removed']
- ],
- [
- InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, 'indexingTotalWorkCalculated',
- ['requestId', 'fileSystemPath', 'totalWork']
- ],
- [InspectorFrontendHostAPI.Events.IndexingWorked, 'indexingWorked', ['requestId', 'fileSystemPath', 'worked']],
- [InspectorFrontendHostAPI.Events.IndexingDone, 'indexingDone', ['requestId', 'fileSystemPath']],
- [InspectorFrontendHostAPI.Events.KeyEventUnhandled, 'keyEventUnhandled', ['event']],
- [InspectorFrontendHostAPI.Events.ReloadInspectedPage, 'reloadInspectedPage', ['hard']],
- [InspectorFrontendHostAPI.Events.RevealSourceLine, 'revealSourceLine', ['url', 'lineNumber', 'columnNumber']],
- [InspectorFrontendHostAPI.Events.SavedURL, 'savedURL', ['url', 'fileSystemPath']],
- [InspectorFrontendHostAPI.Events.SearchCompleted, 'searchCompleted', ['requestId', 'fileSystemPath', 'files']],
- [InspectorFrontendHostAPI.Events.SetInspectedTabId, 'setInspectedTabId', ['tabId']],
- [InspectorFrontendHostAPI.Events.SetUseSoftMenu, 'setUseSoftMenu', ['useSoftMenu']],
- [InspectorFrontendHostAPI.Events.ShowPanel, 'showPanel', ['panelName']]
+export const EventDescriptors = [
+ [Events.AppendedToURL, 'appendedToURL', ['url']],
+ [Events.CanceledSaveURL, 'canceledSaveURL', ['url']],
+ [Events.ContextMenuCleared, 'contextMenuCleared', []],
+ [Events.ContextMenuItemSelected, 'contextMenuItemSelected', ['id']],
+ [Events.DeviceCountUpdated, 'deviceCountUpdated', ['count']],
+ [Events.DevicesDiscoveryConfigChanged, 'devicesDiscoveryConfigChanged', ['config']],
+ [Events.DevicesPortForwardingStatusChanged, 'devicesPortForwardingStatusChanged', ['status']],
+ [Events.DevicesUpdated, 'devicesUpdated', ['devices']],
+ [Events.DispatchMessage, 'dispatchMessage', ['messageObject']],
+ [Events.DispatchMessageChunk, 'dispatchMessageChunk', ['messageChunk', 'messageSize']],
+ [Events.EnterInspectElementMode, 'enterInspectElementMode', []],
+ [Events.EyeDropperPickedColor, 'eyeDropperPickedColor', ['color']],
+ [Events.FileSystemsLoaded, 'fileSystemsLoaded', ['fileSystems']],
+ [Events.FileSystemRemoved, 'fileSystemRemoved', ['fileSystemPath']],
+ [Events.FileSystemAdded, 'fileSystemAdded', ['errorMessage', 'fileSystem']],
+ [Events.FileSystemFilesChangedAddedRemoved, 'fileSystemFilesChangedAddedRemoved', ['changed', 'added', 'removed']],
+ [Events.IndexingTotalWorkCalculated, 'indexingTotalWorkCalculated', ['requestId', 'fileSystemPath', 'totalWork']],
+ [Events.IndexingWorked, 'indexingWorked', ['requestId', 'fileSystemPath', 'worked']],
+ [Events.IndexingDone, 'indexingDone', ['requestId', 'fileSystemPath']],
+ [Events.KeyEventUnhandled, 'keyEventUnhandled', ['event']],
+ [Events.ReattachMainTarget, 'reattachMainTarget', []],
+ [Events.ReloadInspectedPage, 'reloadInspectedPage', ['hard']],
+ [Events.RevealSourceLine, 'revealSourceLine', ['url', 'lineNumber', 'columnNumber']],
+ [Events.SavedURL, 'savedURL', ['url', 'fileSystemPath']],
+ [Events.SearchCompleted, 'searchCompleted', ['requestId', 'fileSystemPath', 'files']],
+ [Events.SetInspectedTabId, 'setInspectedTabId', ['tabId']],
+ [Events.SetUseSoftMenu, 'setUseSoftMenu', ['useSoftMenu']],
+ [Events.ShowPanel, 'showPanel', ['panelName']]
];
-InspectorFrontendHostAPI.prototype = {
- /**
- * @param {string=} type
- */
- addFileSystem(type) {},
-
- loadCompleted() {},
-
- /**
- * @param {number} requestId
- * @param {string} fileSystemPath
- * @param {string} excludedFolders
- */
- indexPath(requestId, fileSystemPath, excludedFolders) {},
-
- /**
- * Requests inspected page to be placed atop of the inspector frontend with specified bounds.
- * @param {{x: number, y: number, width: number, height: number}} bounds
- */
- setInspectedPageBounds(bounds) {},
-
- /**
- * @param {!Array<string>} certChain
- */
- showCertificateViewer(certChain) {},
-
- /**
- * @param {string} shortcuts
- */
- setWhitelistedShortcuts(shortcuts) {},
-
- /**
- * @param {boolean} active
- */
- setEyeDropperActive(active) {},
-
- inspectElementCompleted() {},
-
- /**
- * @param {string} url
- */
- openInNewTab(url) {},
-
- /**
- * @param {string} fileSystemPath
- */
- showItemInFolder(fileSystemPath) {},
-
- /**
- * @param {string} fileSystemPath
- */
- removeFileSystem(fileSystemPath) {},
-
- requestFileSystems() {},
-
- /**
- * @param {string} url
- * @param {string} content
- * @param {boolean} forceSaveAs
- */
- save(url, content, forceSaveAs) {},
-
- /**
- * @param {string} url
- * @param {string} content
- */
- append(url, content) {},
-
- /**
- * @param {string} url
- */
- close(url) {},
-
- /**
- * @param {number} requestId
- * @param {string} fileSystemPath
- * @param {string} query
- */
- searchInPath(requestId, fileSystemPath, query) {},
-
- /**
- * @param {number} requestId
- */
- stopIndexing(requestId) {},
-
- bringToFront() {},
-
- closeWindow() {},
-
- copyText(text) {},
-
- /**
- * @param {string} url
- */
- inspectedURLChanged(url) {},
-
- /**
- * @param {string} fileSystemId
- * @param {string} registeredName
- * @return {?DOMFileSystem}
- */
- isolatedFileSystem(fileSystemId, registeredName) {},
-
- /**
- * @param {string} url
- * @param {string} headers
- * @param {number} streamId
- * @param {function(!InspectorFrontendHostAPI.LoadNetworkResourceResult)} callback
- */
- loadNetworkResource(url, headers, streamId, callback) {},
-
- /**
- * @param {function(!Object<string, string>)} callback
- */
- getPreferences(callback) {},
-
- /**
- * @param {string} name
- * @param {string} value
- */
- setPreference(name, value) {},
+/* Legacy exported object */
+self.Host = self.Host || {};
- /**
- * @param {string} name
- */
- removePreference(name) {},
+/* Legacy exported object */
+Host = Host || {};
- clearPreferences() {},
+Host.InspectorFrontendHostAPI = {};
- /**
- * @param {!FileSystem} fileSystem
- */
- upgradeDraggedFileSystemPermissions(fileSystem) {},
-
- /**
- * @return {string}
- */
- platform() {},
-
- /**
- * @param {string} actionName
- * @param {number} actionCode
- * @param {number} bucketSize
- */
- recordEnumeratedHistogram(actionName, actionCode, bucketSize) {},
-
- /**
- * @param {string} histogramName
- * @param {number} duration
- */
- recordPerformanceHistogram(histogramName, duration) {},
-
- /**
- * @param {string} umaName
- */
- recordUserMetricsAction(umaName) {},
-
- /**
- * @param {string} message
- */
- sendMessageToBackend(message) {},
-
- /**
- * @param {!Adb.Config} config
- */
- setDevicesDiscoveryConfig(config) {},
-
- /**
- * @param {boolean} enabled
- */
- setDevicesUpdatesEnabled(enabled) {},
-
- /**
- * @param {string} pageId
- * @param {string} action
- */
- performActionOnRemotePage(pageId, action) {},
-
- /**
- * @param {string} browserId
- * @param {string} url
- */
- openRemotePage(browserId, url) {},
-
- openNodeFrontend() {},
-
- /**
- * @param {string} origin
- * @param {string} script
- */
- setInjectedScriptForOrigin(origin, script) {},
-
- /**
- * @param {boolean} isDocked
- * @param {function()} callback
- */
- setIsDocked(isDocked, callback) {},
-
- /**
- * @return {number}
- */
- zoomFactor() {},
-
- zoomIn() {},
-
- zoomOut() {},
-
- resetZoom() {},
-
- /**
- * @param {number} x
- * @param {number} y
- * @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
- * @param {!Document} document
- */
- showContextMenuAtPoint(x, y, items, document) {},
-
- /**
- * @param {function()} callback
- */
- reattach(callback) {},
-
- readyForTest() {},
-
- connectionReady() {},
-
- /**
- * @param {boolean} value
- */
- setOpenNewWindowForPopups(value) {},
-
- /**
- * @return {boolean}
- */
- isHostedMode() {},
-
- /**
- * @param {function(!ExtensionDescriptor)} callback
- */
- setAddExtensionCallback(callback) {}
-};
+Host.InspectorFrontendHostAPI.Events = Events;
+Host.InspectorFrontendHostAPI.EventDescriptors = EventDescriptors;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/Platform.js b/chromium/third_party/blink/renderer/devtools/front_end/host/Platform.js
index c6fa64f6fa7..3f52f6a1389 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/Platform.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/Platform.js
@@ -25,60 +25,88 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+let _platform;
+
/**
* @return {string}
*/
-Host.platform = function() {
- if (!Host._platform)
- Host._platform = InspectorFrontendHost.platform();
- return Host._platform;
-};
+export function platform() {
+ if (!_platform) {
+ _platform = Host.InspectorFrontendHost.platform();
+ }
+ return _platform;
+}
+
+let _isMac;
/**
* @return {boolean}
*/
-Host.isMac = function() {
- if (typeof Host._isMac === 'undefined')
- Host._isMac = Host.platform() === 'mac';
+export function isMac() {
+ if (typeof _isMac === 'undefined') {
+ _isMac = platform() === 'mac';
+ }
+
+ return _isMac;
+}
- return Host._isMac;
-};
+let _isWin;
/**
* @return {boolean}
*/
-Host.isWin = function() {
- if (typeof Host._isWin === 'undefined')
- Host._isWin = Host.platform() === 'windows';
+export function isWin() {
+ if (typeof _isWin === 'undefined') {
+ _isWin = platform() === 'windows';
+ }
- return Host._isWin;
-};
+ return _isWin;
+}
+
+let _isCustomDevtoolsFrontend;
/**
* @return {boolean}
*/
-Host.isCustomDevtoolsFrontend = function() {
- if (typeof Host._isCustomDevtoolsFronend === 'undefined')
- Host._isCustomDevtoolsFronend = window.location.toString().startsWith('devtools://devtools/custom/');
- return Host._isCustomDevtoolsFronend;
-};
+export function isCustomDevtoolsFrontend() {
+ if (typeof _isCustomDevtoolsFrontend === 'undefined') {
+ _isCustomDevtoolsFrontend = window.location.toString().startsWith('devtools://devtools/custom/');
+ }
+ return _isCustomDevtoolsFrontend;
+}
+
+let _fontFamily;
/**
* @return {string}
*/
-Host.fontFamily = function() {
- if (Host._fontFamily)
- return Host._fontFamily;
- switch (Host.platform()) {
+export function fontFamily() {
+ if (_fontFamily) {
+ return _fontFamily;
+ }
+ switch (platform()) {
case 'linux':
- Host._fontFamily = 'Roboto, Ubuntu, Arial, sans-serif';
+ _fontFamily = 'Roboto, Ubuntu, Arial, sans-serif';
break;
case 'mac':
- Host._fontFamily = '\'Lucida Grande\', sans-serif';
+ _fontFamily = '\'Lucida Grande\', sans-serif';
break;
case 'windows':
- Host._fontFamily = '\'Segoe UI\', Tahoma, sans-serif';
+ _fontFamily = '\'Segoe UI\', Tahoma, sans-serif';
break;
}
- return Host._fontFamily;
-};
+ return _fontFamily;
+}
+
+/* Legacy exported object */
+self.Host = self.Host || {};
+
+/* Legacy exported object */
+Host = Host || {};
+
+Host.platform = platform;
+Host.isWin = isWin;
+Host.isMac = isMac;
+Host.isCustomDevtoolsFrontend = isCustomDevtoolsFrontend;
+Host.fontFamily = fontFamily;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js b/chromium/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js
index c382ec04d11..fb2fe37f29e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js
@@ -1,35 +1,37 @@
// Copyright (c) 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.
-Host.ResourceLoader = {};
+const ResourceLoader = {};
+export default ResourceLoader;
+
+export let _lastStreamId = 0;
-Host.ResourceLoader._lastStreamId = 0;
/** @type {!Object.<number, !Common.OutputStream>} */
-Host.ResourceLoader._boundStreams = {};
+export const _boundStreams = {};
/**
* @param {!Common.OutputStream} stream
* @return {number}
*/
-Host.ResourceLoader._bindOutputStream = function(stream) {
- Host.ResourceLoader._boundStreams[++Host.ResourceLoader._lastStreamId] = stream;
- return Host.ResourceLoader._lastStreamId;
+export const _bindOutputStream = function(stream) {
+ _boundStreams[++_lastStreamId] = stream;
+ return _lastStreamId;
};
/**
* @param {number} id
*/
-Host.ResourceLoader._discardOutputStream = function(id) {
- Host.ResourceLoader._boundStreams[id].close();
- delete Host.ResourceLoader._boundStreams[id];
+export const _discardOutputStream = function(id) {
+ _boundStreams[id].close();
+ delete _boundStreams[id];
};
/**
* @param {number} id
* @param {string} chunk
*/
-Host.ResourceLoader.streamWrite = function(id, chunk) {
- Host.ResourceLoader._boundStreams[id].write(chunk);
+export const streamWrite = function(id, chunk) {
+ _boundStreams[id].write(chunk);
};
/**
@@ -37,9 +39,9 @@ Host.ResourceLoader.streamWrite = function(id, chunk) {
* @param {?Object.<string, string>} headers
* @param {function(number, !Object.<string, string>, string)} callback
*/
-Host.ResourceLoader.load = function(url, headers, callback) {
+export function load(url, headers, callback) {
const stream = new Common.StringOutputStream();
- Host.ResourceLoader.loadAsStream(url, headers, stream, mycallback);
+ loadAsStream(url, headers, stream, mycallback);
/**
* @param {number} statusCode
@@ -48,7 +50,7 @@ Host.ResourceLoader.load = function(url, headers, callback) {
function mycallback(statusCode, headers) {
callback(statusCode, headers, stream.data());
}
-};
+}
/**
* @param {string} url
@@ -56,8 +58,8 @@ Host.ResourceLoader.load = function(url, headers, callback) {
* @param {!Common.OutputStream} stream
* @param {function(number, !Object.<string, string>)=} callback
*/
-Host.ResourceLoader.loadAsStream = function(url, headers, stream, callback) {
- const streamId = Host.ResourceLoader._bindOutputStream(stream);
+export const loadAsStream = function(url, headers, stream, callback) {
+ const streamId = _bindOutputStream(stream);
const parsedURL = new Common.ParsedURL(url);
if (parsedURL.isDataURL()) {
loadXHR(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed);
@@ -66,25 +68,27 @@ Host.ResourceLoader.loadAsStream = function(url, headers, stream, callback) {
const rawHeaders = [];
if (headers) {
- for (const key in headers)
+ for (const key in headers) {
rawHeaders.push(key + ': ' + headers[key]);
+ }
}
- InspectorFrontendHost.loadNetworkResource(url, rawHeaders.join('\r\n'), streamId, finishedCallback);
+ Host.InspectorFrontendHost.loadNetworkResource(url, rawHeaders.join('\r\n'), streamId, finishedCallback);
/**
* @param {!InspectorFrontendHostAPI.LoadNetworkResourceResult} response
*/
function finishedCallback(response) {
- if (callback)
+ if (callback) {
callback(response.statusCode, response.headers || {});
- Host.ResourceLoader._discardOutputStream(streamId);
+ }
+ _discardOutputStream(streamId);
}
/**
* @param {string} text
*/
function dataURLDecodeSuccessful(text) {
- Host.ResourceLoader.streamWrite(streamId, text);
+ streamWrite(streamId, text);
finishedCallback(/** @type {!InspectorFrontendHostAPI.LoadNetworkResourceResult} */ ({statusCode: 200}));
}
@@ -92,3 +96,48 @@ Host.ResourceLoader.loadAsStream = function(url, headers, stream, callback) {
finishedCallback(/** @type {!InspectorFrontendHostAPI.LoadNetworkResourceResult} */ ({statusCode: 404}));
}
};
+
+/* Legacy exported object */
+self.Host = self.Host || {};
+
+/* Legacy exported object */
+Host = Host || {};
+
+Host.ResourceLoader = ResourceLoader;
+
+Host.ResourceLoader._lastStreamId = _lastStreamId;
+
+/** @type {!Object.<number, !Common.OutputStream>} */
+Host.ResourceLoader._boundStreams = _boundStreams;
+
+/**
+ * @param {!Common.OutputStream} stream
+ * @return {number}
+ */
+Host.ResourceLoader._bindOutputStream = _bindOutputStream;
+
+/**
+ * @param {number} id
+ */
+Host.ResourceLoader._discardOutputStream = _discardOutputStream;
+
+/**
+ * @param {number} id
+ * @param {string} chunk
+ */
+Host.ResourceLoader.streamWrite = streamWrite;
+
+/**
+ * @param {string} url
+ * @param {?Object.<string, string>} headers
+ * @param {function(number, !Object.<string, string>, string)} callback
+ */
+Host.ResourceLoader.load = load;
+
+/**
+ * @param {string} url
+ * @param {?Object.<string, string>} headers
+ * @param {!Common.OutputStream} stream
+ * @param {function(number, !Object.<string, string>)=} callback
+ */
+Host.ResourceLoader.loadAsStream = loadAsStream;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js b/chromium/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js
index 954060ee105..23a918cf7e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js
@@ -31,14 +31,14 @@
/**
* @unrestricted
*/
-Host.UserMetrics = class {
+export default class UserMetrics {
/**
* @param {string} panelName
*/
panelShown(panelName) {
- const code = Host.UserMetrics._PanelCodes[panelName] || 0;
- const size = Object.keys(Host.UserMetrics._PanelCodes).length + 1;
- InspectorFrontendHost.recordEnumeratedHistogram('DevTools.PanelShown', code, size);
+ const code = _PanelCodes[panelName] || 0;
+ const size = Object.keys(_PanelCodes).length + 1;
+ Host.InspectorFrontendHost.recordEnumeratedHistogram('DevTools.PanelShown', code, size);
// Store that the user has changed the panel so we know launch histograms should not be fired.
this._panelChangedSinceLaunch = true;
}
@@ -51,11 +51,11 @@ Host.UserMetrics = class {
}
/**
- * @param {!Host.UserMetrics.Action} action
+ * @param {!Action} action
*/
actionTaken(action) {
- const size = Object.keys(Host.UserMetrics.Action).length + 1;
- InspectorFrontendHost.recordEnumeratedHistogram('DevTools.ActionTaken', action, size);
+ const size = Object.keys(Action).length + 1;
+ Host.InspectorFrontendHost.recordEnumeratedHistogram('DevTools.ActionTaken', action, size);
}
/**
@@ -64,8 +64,9 @@ Host.UserMetrics = class {
* @suppressGlobalPropertiesCheck
*/
panelLoaded(panelName, histogramName) {
- if (this._firedLaunchHistogram || panelName !== this._launchPanelName)
+ if (this._firedLaunchHistogram || panelName !== this._launchPanelName) {
return;
+ }
this._firedLaunchHistogram = true;
// Use rAF and setTimeout to ensure the marker is fired after layout and rendering.
@@ -76,11 +77,12 @@ Host.UserMetrics = class {
performance.mark(histogramName);
// If the user has switched panel before we finished loading, ignore the histogram,
// since the launch timings will have been affected and are no longer valid.
- if (this._panelChangedSinceLaunch)
+ if (this._panelChangedSinceLaunch) {
return;
+ }
// This fires the event for the appropriate launch histogram.
// The duration is measured as the time elapsed since the time origin of the document.
- InspectorFrontendHost.recordPerformanceHistogram(histogramName, performance.now());
+ Host.InspectorFrontendHost.recordPerformanceHistogram(histogramName, performance.now());
}, 0);
});
}
@@ -93,14 +95,14 @@ Host.UserMetrics = class {
// Other calls to panelLoaded will be ignored if the name does not match the one set here.
this._launchPanelName = panelName;
}
-};
+}
// Codes below are used to collect UMA histograms in the Chromium port.
// Do not change the values below, additional actions are needed on the Chromium side
// in order to add more codes.
/** @enum {number} */
-Host.UserMetrics.Action = {
+export const Action = {
WindowDocked: 1,
WindowUndocked: 2,
ScriptsBreakpointSet: 3,
@@ -135,9 +137,10 @@ Host.UserMetrics.Action = {
ShowedThirdPartyBadges: 31,
AuditsViewTrace: 32,
FilmStripStartedRecording: 33,
+ CoverageReportFiltered: 34,
};
-Host.UserMetrics._PanelCodes = {
+export const _PanelCodes = {
elements: 1,
resources: 2,
network: 3,
@@ -157,7 +160,31 @@ Host.UserMetrics._PanelCodes = {
security: 16,
js_profiler: 17,
audits: 18,
+ 'drawer-coverage': 19,
+ 'drawer-protocol-monitor': 20,
+ 'drawer-remote-devices': 21,
+ 'drawer-web-audio': 22,
+ 'drawer-changes.changes': 23,
+ 'drawer-performance.monitor': 24,
+ 'drawer-release-note': 25,
+ 'drawer-live_heap_profile': 26,
+ 'drawer-sources.quick': 27,
+ 'drawer-network.blocked-urls': 28,
};
+/* Legacy exported object */
+self.Host = self.Host || {};
+
+/* Legacy exported object */
+Host = Host || {};
+
+/** @constructor */
+Host.UserMetrics = UserMetrics;
+
+/** @enum {number} */
+Host.UserMetrics.Action = Action;
+
+Host.UserMetrics._PanelCodes = _PanelCodes;
+
/** @type {!Host.UserMetrics} */
-Host.userMetrics = new Host.UserMetrics();
+Host.userMetrics = new UserMetrics();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/host.js b/chromium/third_party/blink/renderer/devtools/front_end/host/host.js
new file mode 100644
index 00000000000..233da1f452b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/host.js
@@ -0,0 +1,21 @@
+// 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 './InspectorFrontendHostAPI.js';
+import './InspectorFrontendHost.js';
+import './ResourceLoader.js';
+import './UserMetrics.js';
+import './Platform.js';
+
+import * as InspectorFrontendHost from './InspectorFrontendHost.js';
+import * as Platform from './Platform.js';
+import * as ResourceLoader from './ResourceLoader.js';
+import * as UserMetrics from './UserMetrics.js';
+
+export {
+ InspectorFrontendHost,
+ Platform,
+ ResourceLoader,
+ UserMetrics,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp
index a88edbb9412..020a2ffb7d8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/host_strings.grdp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<message name="IDS_DEVTOOLS_92bb7e733a12d24684262f046afcc2fd" desc="Document title in Inspector Frontend Host of the DevTools window">
- DevTools - <ph name="URL_REPLACE___HTTPS____________">$1s<ex>example.com</ex></ph>
+ <ph name="LOCKED_1">DevTools</ph> - <ph name="URL_REPLACE___HTTPS____________">$1s<ex>example.com</ex></ph>
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/module.json b/chromium/third_party/blink/renderer/devtools/front_end/host/module.json
index 62febc3ede6..44459c4e0bb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/module.json
@@ -3,7 +3,9 @@
"common",
"platform"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "host.js",
"InspectorFrontendHostAPI.js",
"InspectorFrontendHost.js",
"Platform.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierEditor.js
index 05f06635852..671bd1117dc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierEditor.js
@@ -47,8 +47,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
* @param {?UI.Geometry.CubicBezier} bezier
*/
setBezier(bezier) {
- if (!bezier)
+ if (!bezier) {
return;
+ }
this._bezier = bezier;
this._updateUI();
}
@@ -173,8 +174,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
}
_unselectPresets() {
- for (const category of this._presetCategories)
+ for (const category of this._presetCategories) {
category.icon.classList.remove('bezier-preset-selected');
+ }
delete this._selectedCategory;
this._header.classList.remove('bezier-header-active');
}
@@ -184,8 +186,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
* @param {!Event=} event
*/
_presetCategorySelected(category, event) {
- if (this._selectedCategory === category)
+ if (this._selectedCategory === category) {
return;
+ }
this._unselectPresets();
this._header.classList.add('bezier-header-active');
this._selectedCategory = category;
@@ -193,8 +196,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
this.setBezier(UI.Geometry.CubicBezier.parse(category.presets[category.presetIndex].value));
this._onchange();
this._startPreviewAnimation();
- if (event)
+ if (event) {
event.consume(true);
+ }
}
/**
@@ -202,8 +206,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
* @param {!Event} event
*/
_presetModifyClicked(intensify, event) {
- if (!this._selectedCategory)
+ if (!this._selectedCategory) {
return;
+ }
const length = this._selectedCategory.presets.length;
this._selectedCategory.presetIndex = (this._selectedCategory.presetIndex + (intensify ? 1 : -1) + length) % length;
@@ -214,8 +219,9 @@ InlineEditor.BezierEditor = class extends UI.VBox {
}
_startPreviewAnimation() {
- if (this._previewAnimation)
+ if (this._previewAnimation) {
this._previewAnimation.cancel();
+ }
const animationDuration = 1600;
const numberOnionSlices = 20;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierUI.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierUI.js
index f5c88ca6787..28e2a08fc80 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierUI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/BezierUI.js
@@ -93,8 +93,9 @@ InlineEditor.BezierUI = class {
* @param {!Element} svg
*/
drawCurve(bezier, svg) {
- if (!bezier)
+ if (!bezier) {
return;
+ }
const width = this.curveWidth();
const height = this.curveHeight();
svg.setAttribute('width', this.width);
@@ -102,8 +103,9 @@ InlineEditor.BezierUI = class {
svg.removeChildren();
const group = svg.createSVGChild('g');
- if (this.linearLine)
+ if (this.linearLine) {
this._drawLine(group, 'linear-line', 0, height, width, 0);
+ }
const curve = group.createSVGChild('path', 'bezier-path');
const curvePoints = [
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowEditor.js
index 07ef71fef7f..9f2bf8b1980 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowEditor.js
@@ -155,8 +155,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
*/
_onButtonClick(event) {
const insetClicked = (event.currentTarget === this._insetButton);
- if (insetClicked && this._model.inset() || !insetClicked && !this._model.inset())
+ if (insetClicked && this._model.inset() || !insetClicked && !this._model.inset()) {
return;
+ }
this._model.setInset(insetClicked);
this._updateButtons();
this.dispatchEventToListeners(InlineEditor.CSSShadowEditor.Events.ShadowChanged, this._model);
@@ -167,13 +168,16 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
*/
_handleValueModification(event) {
const modifiedValue = UI.createReplacementString(event.currentTarget.value, event, customNumberHandler);
- if (!modifiedValue)
+ if (!modifiedValue) {
return;
+ }
const length = InlineEditor.CSSLength.parse(modifiedValue);
- if (!length)
+ if (!length) {
return;
- if (event.currentTarget === this._blurInput && length.amount < 0)
+ }
+ if (event.currentTarget === this._blurInput && length.amount < 0) {
length.amount = 0;
+ }
event.currentTarget.value = length.asCSSText();
event.currentTarget.selectionStart = 0;
event.currentTarget.selectionEnd = event.currentTarget.value.length;
@@ -187,8 +191,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
* @return {string}
*/
function customNumberHandler(prefix, number, suffix) {
- if (!suffix.length)
+ if (!suffix.length) {
suffix = InlineEditor.CSSShadowEditor.defaultUnit;
+ }
return prefix + number + suffix;
}
}
@@ -200,8 +205,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
this._changedElement = event.currentTarget;
this._changedElement.classList.remove('invalid');
const length = InlineEditor.CSSLength.parse(event.currentTarget.value);
- if (!length || event.currentTarget === this._blurInput && length.amount < 0)
+ if (!length || event.currentTarget === this._blurInput && length.amount < 0) {
return;
+ }
if (event.currentTarget === this._xInput) {
this._model.setOffsetX(length);
this._updateCanvas(false);
@@ -219,12 +225,14 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
}
_onTextBlur() {
- if (!this._changedElement)
+ if (!this._changedElement) {
return;
+ }
let length = !this._changedElement.value.trim() ? InlineEditor.CSSLength.zero() :
InlineEditor.CSSLength.parse(this._changedElement.value);
- if (!length)
+ if (!length) {
length = InlineEditor.CSSLength.parse(this._changedElement.value + InlineEditor.CSSShadowEditor.defaultUnit);
+ }
if (!length) {
this._changedElement.classList.add('invalid');
this._changedElement = null;
@@ -239,8 +247,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
this._yInput.value = length.asCSSText();
this._updateCanvas(false);
} else if (this._changedElement === this._blurInput) {
- if (length.amount < 0)
+ if (length.amount < 0) {
length = InlineEditor.CSSLength.zero();
+ }
this._model.setBlurRadius(length);
this._blurInput.value = length.asCSSText();
this._blurSlider.value = length.amount;
@@ -283,8 +292,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
this._xySlider.totalOffsetTop() + this._halfCanvasSize);
const clickedPoint = new UI.Geometry.Point(event.x - this._canvasOrigin.x, event.y - this._canvasOrigin.y);
const thumbPoint = this._sliderThumbPosition();
- if (clickedPoint.distanceTo(thumbPoint) >= InlineEditor.CSSShadowEditor.sliderThumbRadius)
+ if (clickedPoint.distanceTo(thumbPoint) >= InlineEditor.CSSShadowEditor.sliderThumbRadius) {
this._dragMove(event);
+ }
return true;
}
@@ -293,8 +303,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
*/
_dragMove(event) {
let point = new UI.Geometry.Point(event.x - this._canvasOrigin.x, event.y - this._canvasOrigin.y);
- if (event.shiftKey)
+ if (event.shiftKey) {
point = this._snapToClosestDirection(point);
+ }
const constrainedPoint = this._constrainPoint(point, this._innerCanvasSize);
const newX = Math.round((constrainedPoint.x / this._innerCanvasSize) * InlineEditor.CSSShadowEditor.maxRange);
const newY = Math.round((constrainedPoint.y / this._innerCanvasSize) * InlineEditor.CSSShadowEditor.maxRange);
@@ -332,25 +343,28 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
_onCanvasArrowKey(event) {
let shiftX = 0;
let shiftY = 0;
- if (event.key === 'ArrowRight')
+ if (event.key === 'ArrowRight') {
shiftX = 1;
- else if (event.key === 'ArrowLeft')
+ } else if (event.key === 'ArrowLeft') {
shiftX = -1;
- else if (event.key === 'ArrowUp')
+ } else if (event.key === 'ArrowUp') {
shiftY = -1;
- else if (event.key === 'ArrowDown')
+ } else if (event.key === 'ArrowDown') {
shiftY = 1;
+ }
- if (!shiftX && !shiftY)
+ if (!shiftX && !shiftY) {
return;
+ }
event.consume(true);
if (shiftX) {
const offsetX = this._model.offsetX();
const newAmount = Number.constrain(
offsetX.amount + shiftX, -InlineEditor.CSSShadowEditor.maxRange, InlineEditor.CSSShadowEditor.maxRange);
- if (newAmount === offsetX.amount)
+ if (newAmount === offsetX.amount) {
return;
+ }
this._model.setOffsetX(
new InlineEditor.CSSLength(newAmount, offsetX.unit || InlineEditor.CSSShadowEditor.defaultUnit));
this._xInput.value = this._model.offsetX().asCSSText();
@@ -360,8 +374,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
const offsetY = this._model.offsetY();
const newAmount = Number.constrain(
offsetY.amount + shiftY, -InlineEditor.CSSShadowEditor.maxRange, InlineEditor.CSSShadowEditor.maxRange);
- if (newAmount === offsetY.amount)
+ if (newAmount === offsetY.amount) {
return;
+ }
this._model.setOffsetY(
new InlineEditor.CSSLength(newAmount, offsetY.unit || InlineEditor.CSSShadowEditor.defaultUnit));
this._yInput.value = this._model.offsetY().asCSSText();
@@ -377,8 +392,9 @@ InlineEditor.CSSShadowEditor = class extends UI.VBox {
* @return {!UI.Geometry.Point}
*/
_constrainPoint(point, max) {
- if (Math.abs(point.x) <= max && Math.abs(point.y) <= max)
+ if (Math.abs(point.x) <= max && Math.abs(point.y) <= max) {
return new UI.Geometry.Point(point.x, point.y);
+ }
return point.scale(max / Math.max(Math.abs(point.x), Math.abs(point.y)));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowModel.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowModel.js
index bebe2d1933e..1b504aacc8a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/CSSShadowModel.js
@@ -65,13 +65,15 @@ InlineEditor.CSSShadowModel = class {
const result = results[j];
if (result.regexIndex === -1) {
// Don't allow anything other than inset, color, length values, and whitespace.
- if (/\S/.test(result.value))
+ if (/\S/.test(result.value)) {
return [];
+ }
// All parts must be separated by whitespace.
nextPartAllowed = true;
} else {
- if (!nextPartAllowed)
+ if (!nextPartAllowed) {
return [];
+ }
nextPartAllowed = false;
if (result.regexIndex === 0) {
@@ -79,14 +81,16 @@ InlineEditor.CSSShadowModel = class {
shadow._format.push(InlineEditor.CSSShadowModel._Part.Inset);
} else if (result.regexIndex === 1) {
const color = Common.Color.parse(result.value);
- if (!color)
+ if (!color) {
return [];
+ }
shadow._color = color;
shadow._format.push(InlineEditor.CSSShadowModel._Part.Color);
} else if (result.regexIndex === 2) {
const length = InlineEditor.CSSLength.parse(result.value);
- if (!length)
+ if (!length) {
return [];
+ }
const previousPart = shadow._format.length > 0 ? shadow._format[shadow._format.length - 1] : '';
if (previousPart === InlineEditor.CSSShadowModel._Part.OffsetX) {
shadow._offsetY = length;
@@ -109,8 +113,9 @@ InlineEditor.CSSShadowModel = class {
invalidCount(shadow, InlineEditor.CSSShadowModel._Part.Color, 0, 1) ||
invalidCount(shadow, InlineEditor.CSSShadowModel._Part.BlurRadius, 0, 1) ||
invalidCount(shadow, InlineEditor.CSSShadowModel._Part.Inset, 0, isBoxShadow ? 1 : 0) ||
- invalidCount(shadow, InlineEditor.CSSShadowModel._Part.SpreadRadius, 0, isBoxShadow ? 1 : 0))
+ invalidCount(shadow, InlineEditor.CSSShadowModel._Part.SpreadRadius, 0, isBoxShadow ? 1 : 0)) {
return [];
+ }
shadows.push(shadow);
}
return shadows;
@@ -125,8 +130,9 @@ InlineEditor.CSSShadowModel = class {
function invalidCount(shadow, part, min, max) {
let count = 0;
for (let i = 0; i < shadow._format.length; i++) {
- if (shadow._format[i] === part)
+ if (shadow._format[i] === part) {
count++;
+ }
}
return count < min || count > max;
}
@@ -137,8 +143,9 @@ InlineEditor.CSSShadowModel = class {
*/
setInset(inset) {
this._inset = inset;
- if (this._format.indexOf(InlineEditor.CSSShadowModel._Part.Inset) === -1)
+ if (this._format.indexOf(InlineEditor.CSSShadowModel._Part.Inset) === -1) {
this._format.unshift(InlineEditor.CSSShadowModel._Part.Inset);
+ }
}
/**
@@ -183,8 +190,9 @@ InlineEditor.CSSShadowModel = class {
*/
setColor(color) {
this._color = color;
- if (this._format.indexOf(InlineEditor.CSSShadowModel._Part.Color) === -1)
+ if (this._format.indexOf(InlineEditor.CSSShadowModel._Part.Color) === -1) {
this._format.push(InlineEditor.CSSShadowModel._Part.Color);
+ }
}
/**
@@ -243,18 +251,19 @@ InlineEditor.CSSShadowModel = class {
const parts = [];
for (let i = 0; i < this._format.length; i++) {
const part = this._format[i];
- if (part === InlineEditor.CSSShadowModel._Part.Inset && this._inset)
+ if (part === InlineEditor.CSSShadowModel._Part.Inset && this._inset) {
parts.push('inset');
- else if (part === InlineEditor.CSSShadowModel._Part.OffsetX)
+ } else if (part === InlineEditor.CSSShadowModel._Part.OffsetX) {
parts.push(this._offsetX.asCSSText());
- else if (part === InlineEditor.CSSShadowModel._Part.OffsetY)
+ } else if (part === InlineEditor.CSSShadowModel._Part.OffsetY) {
parts.push(this._offsetY.asCSSText());
- else if (part === InlineEditor.CSSShadowModel._Part.BlurRadius)
+ } else if (part === InlineEditor.CSSShadowModel._Part.BlurRadius) {
parts.push(this._blurRadius.asCSSText());
- else if (part === InlineEditor.CSSShadowModel._Part.SpreadRadius)
+ } else if (part === InlineEditor.CSSShadowModel._Part.SpreadRadius) {
parts.push(this._spreadRadius.asCSSText());
- else if (part === InlineEditor.CSSShadowModel._Part.Color)
+ } else if (part === InlineEditor.CSSShadowModel._Part.Color) {
parts.push(this._color.asString(this._color.format()));
+ }
}
return parts.join(' ');
}
@@ -293,10 +302,12 @@ InlineEditor.CSSLength = class {
static parse(text) {
const lengthRegex = new RegExp('^(?:' + InlineEditor.CSSLength.Regex.source + ')$', 'i');
const match = text.match(lengthRegex);
- if (!match)
+ if (!match) {
return null;
- if (match.length > 2 && match[2])
+ }
+ if (match.length > 2 && match[2]) {
return new InlineEditor.CSSLength(parseFloat(match[1]), match[2]);
+ }
return InlineEditor.CSSLength.zero();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/ColorSwatch.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/ColorSwatch.js
index 2dfc68abca0..3abcb32b47a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/ColorSwatch.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/ColorSwatch.js
@@ -57,8 +57,9 @@ InlineEditor.ColorSwatch = class extends HTMLSpanElement {
case cf.HSL:
case cf.HSLA:
- if (color.nickname())
+ if (color.nickname()) {
return cf.Nickname;
+ }
return color.detectHEXFormat();
case cf.ShortHEX:
@@ -148,8 +149,9 @@ InlineEditor.ColorSwatch = class extends HTMLSpanElement {
* @param {!Event} event
*/
_handleClick(event) {
- if (!event.shiftKey)
+ if (!event.shiftKey) {
return;
+ }
event.target.parentNode.parentNode.host.toggleNextFormat();
event.consume(true);
}
@@ -253,8 +255,9 @@ InlineEditor.CSSShadowSwatch = class extends HTMLSpanElement {
for (let i = 0; i < results.length; i++) {
const result = results[i];
if (result.regexIndex === 1) {
- if (!this._colorSwatch)
+ if (!this._colorSwatch) {
this._colorSwatch = InlineEditor.ColorSwatch.create();
+ }
this._colorSwatch.setColor(model.color());
this._contentElement.appendChild(this._colorSwatch);
} else {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/SwatchPopoverHelper.js b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/SwatchPopoverHelper.js
index 68848645a6e..f508e7fcded 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/SwatchPopoverHelper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inline_editor/SwatchPopoverHelper.js
@@ -23,8 +23,9 @@ InlineEditor.SwatchPopoverHelper = class extends Common.Object {
* @param {!Event} event
*/
_onFocusOut(event) {
- if (!event.relatedTarget || event.relatedTarget.isSelfOrDescendant(this._view.contentElement))
+ if (!event.relatedTarget || event.relatedTarget.isSelfOrDescendant(this._view.contentElement)) {
return;
+ }
this._hideProxy();
}
@@ -42,8 +43,9 @@ InlineEditor.SwatchPopoverHelper = class extends Common.Object {
*/
show(view, anchorElement, hiddenCallback) {
if (this._popover.isShowing()) {
- if (this._anchorElement === anchorElement)
+ if (this._anchorElement === anchorElement) {
return;
+ }
// Reopen the picker for another anchor element.
this.hide(true);
@@ -69,16 +71,18 @@ InlineEditor.SwatchPopoverHelper = class extends Common.Object {
this._popover.setContentAnchorBox(this._anchorElement.boxInWindow());
this._popover.show(this._anchorElement.ownerDocument);
this._view.contentElement.addEventListener('focusout', this._boundFocusOut, false);
- if (!this._focusRestorer)
+ if (!this._focusRestorer) {
this._focusRestorer = new UI.WidgetFocusRestorer(this._view);
+ }
}
/**
* @param {boolean=} commitEdit
*/
hide(commitEdit) {
- if (this._isHidden)
+ if (this._isHidden) {
return;
+ }
const document = this._popover.element.ownerDocument;
this._isHidden = true;
this._popover.hide();
@@ -86,8 +90,9 @@ InlineEditor.SwatchPopoverHelper = class extends Common.Object {
document.removeEventListener('mousedown', this._hideProxy, false);
document.defaultView.removeEventListener('resize', this._hideProxy, false);
- if (this._hiddenCallback)
+ if (this._hiddenCallback) {
this._hiddenCallback.call(null, !!commitEdit);
+ }
this._focusRestorer.restore();
delete this._anchorElement;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector.html b/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
index b5d6f04ede5..e26cd22c1bc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="inspector.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="inspector.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector.js b/chromium/third_party/blink/renderer/devtools/front_end/inspector.js
index c690b32c8ed..bfb7f060d7a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector.js
@@ -1,4 +1,4 @@
// 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.
-Runtime.startApplication('inspector');
+Root.Runtime.startApplication('inspector');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
index 6808e0b6908..15d5265fa55 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
@@ -12,22 +12,24 @@ InspectorMain.InspectorMain = class extends Common.Object {
async run() {
let firstCall = true;
await SDK.initMainConnection(async () => {
- const type = Runtime.queryParam('v8only') ? SDK.Target.Type.Node : SDK.Target.Type.Frame;
- const waitForDebuggerInPage = type === SDK.Target.Type.Frame && Runtime.queryParam('panel') === 'sources';
+ const type = Root.Runtime.queryParam('v8only') ? SDK.Target.Type.Node : SDK.Target.Type.Frame;
+ const waitForDebuggerInPage = type === SDK.Target.Type.Frame && Root.Runtime.queryParam('panel') === 'sources';
const target =
SDK.targetManager.createTarget('main', Common.UIString('Main'), type, null, undefined, waitForDebuggerInPage);
// Only resume target during the first connection,
// subsequent connections are due to connection hand-over,
// there is no need to pause in debugger.
- if (!firstCall)
+ if (!firstCall) {
return;
+ }
firstCall = false;
if (waitForDebuggerInPage) {
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel.isReadyToPause())
+ if (!debuggerModel.isReadyToPause()) {
await debuggerModel.once(SDK.DebuggerModel.Events.DebuggerIsReadyToPause);
+ }
debuggerModel.pause();
}
@@ -38,10 +40,11 @@ InspectorMain.InspectorMain = class extends Common.Object {
new InspectorMain.BackendSettingsSync();
new MobileThrottling.NetworkPanelIndicator();
- InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ReloadInspectedPage, event => {
- const hard = /** @type {boolean} */ (event.data);
- SDK.ResourceTreeModel.reloadAllPages(hard);
- });
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.ReloadInspectedPage, event => {
+ const hard = /** @type {boolean} */ (event.data);
+ SDK.ResourceTreeModel.reloadAllPages(hard);
+ });
}
};
@@ -94,7 +97,7 @@ InspectorMain.NodeIndicator = class {
const element = createElement('div');
const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'inspector_main/nodeIcon.css');
this._element = shadowRoot.createChild('div', 'node-icon');
- element.addEventListener('click', () => InspectorFrontendHost.openNodeFrontend(), false);
+ element.addEventListener('click', () => Host.InspectorFrontendHost.openNodeFrontend(), false);
this._button = new UI.ToolbarItem(element);
this._button.setTitle(Common.UIString('Open dedicated DevTools for Node.js'));
SDK.targetManager.addEventListener(
@@ -110,8 +113,9 @@ InspectorMain.NodeIndicator = class {
_update(targetInfos) {
const hasNode = !!targetInfos.find(target => target.type === 'node' && !target.attached);
this._element.classList.toggle('inactive', !hasNode);
- if (hasNode)
+ if (hasNode) {
this._button.setVisible(true);
+ }
}
/**
@@ -166,19 +170,21 @@ InspectorMain.BackendSettingsSync = class {
* @param {!SDK.Target} target
*/
_updateTarget(target) {
- if (target.type() !== SDK.Target.Type.Frame || target.parentTarget())
+ if (target.type() !== SDK.Target.Type.Frame || target.parentTarget()) {
return;
+ }
target.pageAgent().setAdBlockingEnabled(this._adBlockEnabledSetting.get());
target.emulationAgent().setFocusEmulationEnabled(this._emulatePageFocusSetting.get());
}
_updateAutoAttach() {
- InspectorFrontendHost.setOpenNewWindowForPopups(this._autoAttachSetting.get());
+ Host.InspectorFrontendHost.setOpenNewWindowForPopups(this._autoAttachSetting.get());
}
_update() {
- for (const target of SDK.targetManager.targets())
+ for (const target of SDK.targetManager.targets()) {
this._updateTarget(target);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/RenderingOptions.js b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/RenderingOptions.js
index 42c7c8e075c..d8111b32b92 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/RenderingOptions.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/RenderingOptions.js
@@ -62,14 +62,14 @@ InspectorMain.RenderingOptionsView = class extends UI.VBox {
Common.moduleSetting('showHitTestBorders'));
this.contentElement.createChild('div').classList.add('panel-section-separator');
- const mediaSetting = Common.moduleSetting('emulatedCSSMedia');
- const mediaSelect = UI.SettingsUI.createControlForSetting(mediaSetting);
- if (mediaSelect) {
- const mediaRow = this.contentElement.createChild('span', 'media-row');
- mediaRow.createChild('label').textContent = ls`Emulate CSS media`;
- mediaRow.createChild('p').textContent = ls`Forces media type for testing print and screen styles.`;
- mediaRow.appendChild(mediaSelect);
- }
+ this._appendSelect(
+ ls`Forces media type for testing print and screen styles`, Common.moduleSetting('emulatedCSSMedia'));
+ this._appendSelect(
+ ls`Forces CSS prefers-color-scheme media feature`,
+ Common.moduleSetting('emulatedCSSMediaFeaturePrefersColorScheme'));
+ this._appendSelect(
+ ls`Forces CSS prefers-reduced-motion media feature`,
+ Common.moduleSetting('emulatedCSSMediaFeaturePrefersReducedMotion'));
}
/**
@@ -82,4 +82,15 @@ InspectorMain.RenderingOptionsView = class extends UI.VBox {
UI.SettingsUI.bindCheckbox(checkboxLabel.checkboxElement, setting);
this.contentElement.appendChild(checkboxLabel);
}
+
+ /**
+ * @param {string} label
+ * @param {!Common.Setting} setting
+ */
+ _appendSelect(label, setting) {
+ const control = UI.SettingsUI.createControlForSetting(setting, label);
+ if (control) {
+ this.contentElement.appendChild(control);
+ }
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
index 6dd2a3ff73a..523ca9669c8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
@@ -13,7 +13,7 @@
Paint flashing
</message>
<message name="IDS_DEVTOOLS_0ef16a6645018dec4609e392c7e9bda1" desc="Title of a setting under the DevTools category that can be invoked through the Command Menu">
- Do not auto-open DevTools for popups
+ Do not auto-open <ph name="LOCKED_1">DevTools</ph> for popups
</message>
<message name="IDS_DEVTOOLS_1808fb32cf4e8a03daa326b48d4246eb" desc="Title of a setting under the Appearance category in Settings">
Disable paused state overlay
@@ -27,15 +27,21 @@
<message name="IDS_DEVTOOLS_36bec95bf12fb795a5a100251f0cc421" desc="Checkbox subtitle for 'Layer boarders' in the Rendering tool">
Shows layer borders (orange/olive) and tiles (cyan).
</message>
+ <message name="IDS_DEVTOOLS_417316246f12b8235535182cc9eebe45" desc="Accessibility subtitle for media select element in Rendering tool">
+ Forces media type for testing print and screen styles
+ </message>
<message name="IDS_DEVTOOLS_43f244627bf87f76a0dee86f364df473" desc="Checkbox subtitle for 'Layout Shift Regions' in the Rendering tool">
Highlights areas of the page (blue) that were shifted. May not be suitable for people prone to photosensitive epilepsy.
</message>
- <message name="IDS_DEVTOOLS_482a4dca0bbd8fcdda5acc6f95f3c279" desc="A title of the 'DevTools' setting category">
- DevTools
- </message>
<message name="IDS_DEVTOOLS_53f2f05226edcd77bd4351cb27d07ba8" desc="Text in Rendering Options">
Highlights frames (red) detected to be ads.
</message>
+ <message name="IDS_DEVTOOLS_5b67348d29677cd12d3e02b7e1d7cc87" desc="Subtitle for a select box under the Rendering drawer">
+ Forces CSS prefers-reduced-motion media feature
+ </message>
+ <message name="IDS_DEVTOOLS_616e08b00feb46b7abdca3c6190f63ac" desc="Subtitle for a select box under the Rendering drawer">
+ Forces CSS prefers-color-scheme media feature
+ </message>
<message name="IDS_DEVTOOLS_6526f858ca97d80241dacb00b40504bb" desc="Checkbox subtitle for 'Hit-test borders' in the Rendering tool">
Shows borders around hit-test regions.
</message>
@@ -46,7 +52,7 @@
Hit-test borders
</message>
<message name="IDS_DEVTOOLS_7e9495c56e55fa2c5236512bf80e5d2b" desc="Title of a setting under the Appearance category in Settings">
- Don&apos;t show Chrome Data Saver warning
+ Don&apos;t show <ph name="LOCKED_1">Chrome Data Saver</ph> warning
</message>
<message name="IDS_DEVTOOLS_8339f28e0c74e2c821b05332280c754b" desc="Title of a setting under the Network category in Settings">
Force ad blocking on this site
@@ -55,10 +61,7 @@
Navigation
</message>
<message name="IDS_DEVTOOLS_8634af2a16e41305fc8dca2d67360810" desc="Title of button in inspector main">
- Open dedicated DevTools for Node.js
- </message>
- <message name="IDS_DEVTOOLS_869a8b1ed99306604574dca474a13994" desc="Text in Rendering Options">
- Emulate CSS media
+ Open dedicated <ph name="LOCKED_1">DevTools</ph> for Node.js
</message>
<message name="IDS_DEVTOOLS_86f849e1a655c2df19f28cb3dfe07bc9" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Block ads on this site
@@ -72,31 +75,19 @@
<message name="IDS_DEVTOOLS_960568e27eb66ea554c3be4cfbefe3d0" desc="Text in Rendering Options">
Layer borders
</message>
- <message name="IDS_DEVTOOLS_a02c83a7dbd96295beaefb72c2bee2de" desc="Text in Inspector Main">
- Main
- </message>
<message name="IDS_DEVTOOLS_a15932c4dfbbcbc1ac6f5c27c6fa530f" desc="Text in Rendering Options">
Highlights elements (teal) that can slow down scrolling, including touch &amp; wheel event handlers and other main-thread scrolling situations.
</message>
<message name="IDS_DEVTOOLS_a4c766a2e6eb33e7575331b6affd9778" desc="Checkbox subtitle for 'Paint flashing' in the Rendering tool">
Highlights areas of the page (green) that need to be repainted. May not be suitable for people prone to photosensitive epilepsy.
</message>
- <message name="IDS_DEVTOOLS_a6e8f9aed2ac6481dc25a18a33342d03" desc="Title of the 'Rendering' tool in the bottom drawer">
- Rendering
- </message>
<message name="IDS_DEVTOOLS_cb835af5f855f79e8611dd3f8fec6aac" desc="Title of an action in the inspector main tool to reload">
Reload page
</message>
- <message name="IDS_DEVTOOLS_d013165b46f5c1f0f780ea3fc92c04f1" desc="Subtitle of 'Emulate CSS media' in the Rendering tool">
- Forces media type for testing print and screen styles.
- </message>
<message name="IDS_DEVTOOLS_d543dbe64db0c952d6e13c9519218b3e" desc="Title of an action in the inspector main tool to hard reload">
Hard reload page
</message>
- <message name="IDS_DEVTOOLS_ef95393ad48336d7c3543625354a3d56" desc="Text in Rendering Options">
- Highlight ad frames
- </message>
<message name="IDS_DEVTOOLS_f23c9ba06e7123f0b4c906de90fbcc9f" desc="Title of a setting under the DevTools category that can be invoked through the Command Menu">
- Auto-open DevTools for popups
+ Auto-open <ph name="LOCKED_1">DevTools</ph> for popups
</message>
-</grit-part> \ No newline at end of file
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/renderingOptions.css b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/renderingOptions.css
index b478b442ab8..a8f46cf5b5c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/renderingOptions.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/renderingOptions.css
@@ -5,27 +5,21 @@
*/
:host {
- padding: 12px;
+ padding: 12px;
}
[is=dt-checkbox] {
- margin: 0px 0px 10px 0px;
- flex: none;
+ margin: 0 0 10px 0;
+ flex: none;
}
-.media-row {
- margin-left: 22px;
- flex: none;
-}
-
-.media-row p {
- margin-top: 0;
- color: gray;
+.panel-section-separator {
+ height: 1px;
+ margin-bottom: 10px;
+ background: #f0f0f0;
+ flex: none;
}
-.panel-section-separator {
- height: 1px;
- margin-bottom: 10px;
- background: #f0f0f0;
- flex: none;
+.chrome-select-label {
+ margin-bottom: 16px;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
index ca7cc52183a..ebf13c4efe9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
@@ -8,8 +8,8 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
- <script src="Runtime.js"></script>
- <script src="integration_test_runner.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="integration_test_runner.js"></script>
</head>
<body id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.js b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.js
index 3eddfa014ea..f6f6a7a0f3a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.js
@@ -7,4 +7,4 @@ if (self.testRunner) {
testRunner.waitUntilDone();
}
-Runtime.startApplication('integration_test_runner');
+Root.Runtime.startApplication('integration_test_runner');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js b/chromium/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
index 022a911622c..bcfef8838e9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/javascript_metadata/JavaScriptMetadata.js
@@ -18,12 +18,14 @@ JavaScriptMetadata.JavaScriptMetadata = class {
if (!nativeFunction.receiver) {
this._uniqueFunctions.set(nativeFunction.name, nativeFunction.signatures);
} else if (nativeFunction.static) {
- if (!this._staticMethods.has(nativeFunction.receiver))
+ if (!this._staticMethods.has(nativeFunction.receiver)) {
this._staticMethods.set(nativeFunction.receiver, new Map());
+ }
this._staticMethods.get(nativeFunction.receiver).set(nativeFunction.name, nativeFunction.signatures);
} else {
- if (!this._instanceMethods.has(nativeFunction.receiver))
+ if (!this._instanceMethods.has(nativeFunction.receiver)) {
this._instanceMethods.set(nativeFunction.receiver, new Map());
+ }
this._instanceMethods.get(nativeFunction.receiver).set(nativeFunction.name, nativeFunction.signatures);
}
}
@@ -45,8 +47,9 @@ JavaScriptMetadata.JavaScriptMetadata = class {
* @return {?Array<!Array<string>>}
*/
signaturesForInstanceMethod(name, receiverClassName) {
- if (!this._instanceMethods.has(receiverClassName))
+ if (!this._instanceMethods.has(receiverClassName)) {
return null;
+ }
return this._instanceMethods.get(receiverClassName).get(name) || null;
}
@@ -57,8 +60,9 @@ JavaScriptMetadata.JavaScriptMetadata = class {
* @return {?Array<!Array<string>>}
*/
signaturesForStaticMethod(name, receiverConstructorName) {
- if (!this._staticMethods.has(receiverConstructorName))
+ if (!this._staticMethods.has(receiverConstructorName)) {
return null;
+ }
return this._staticMethods.get(receiverConstructorName).get(name) || null;
}
};
@@ -71,4 +75,4 @@ JavaScriptMetadata.JavaScriptMetadata = class {
* receiver: (string|undefined),
* }>}
*/
-JavaScriptMetadata.NativeFunctions; \ No newline at end of file
+JavaScriptMetadata.NativeFunctions;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/js_app.html b/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
index 710591871d5..8d7b199edf8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="js_app.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="js_app.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/js_app.js b/chromium/third_party/blink/renderer/devtools/front_end/js_app.js
index 11427a08858..076e3f77af9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/js_app.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/js_app.js
@@ -1,4 +1,4 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Runtime.startApplication('js_app');
+Root.Runtime.startApplication('js_app');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
index 1432b0986e3..3e09477206b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/js_profiler/js_profiler_strings.grdp
@@ -1,6 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_65b4c7424dd695c30efa73da8396c90c" desc="Title of the 'Profiler' tool">
- Profiler
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd b/chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
index 230b8e4496b..f1305d6f007 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
+++ b/chromium/third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd
@@ -19,11 +19,13 @@
<part file="../browser_sdk/browser_sdk_strings.grdp" />
<part file="../changes/changes_strings.grdp" />
<part file="../color_picker/color_picker_strings.grdp" />
+ <part file="../common/common_strings.grdp" />
<part file="../components/components_strings.grdp" />
<part file="../console/console_strings.grdp" />
<part file="../console_counters/console_counters_strings.grdp" />
<part file="../cookie_table/cookie_table_strings.grdp" />
<part file="../coverage/coverage_strings.grdp" />
+ <part file="../css_overview/css_overview_strings.grdp" />
<part file="../data_grid/data_grid_strings.grdp" />
<part file="../devices/devices_strings.grdp" />
<part file="../elements/elements_strings.grdp" />
@@ -39,6 +41,7 @@
<part file="../layer_viewer/layer_viewer_strings.grdp" />
<part file="../layers/layers_strings.grdp" />
<part file="../main/main_strings.grdp" />
+ <part file="../media/media_strings.grdp" />
<part file="../mobile_throttling/mobile_throttling_strings.grdp" />
<part file="../network/network_strings.grdp" />
<part file="../node_debugger/node_debugger_strings.grdp" />
@@ -60,13 +63,13 @@
<part file="../snippets/snippets_strings.grdp" />
<part file="../source_frame/source_frame_strings.grdp" />
<part file="../sources/sources_strings.grdp" />
- <part file="../terminal/terminal_strings.grdp" />
<part file="../text_editor/text_editor_strings.grdp" />
<part file="../timeline/timeline_strings.grdp" />
<part file="../timeline_model/timeline_model_strings.grdp" />
<part file="../ui/ui_strings.grdp" />
<part file="../web_audio/web_audio_strings.grdp" />
<part file="../workspace/workspace_strings.grdp" />
+ <part file="shared_strings.grdp" />
</messages>
</release>
</grit>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp
new file mode 100644
index 00000000000..981cbaed1e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/langpacks/shared_strings.grdp
@@ -0,0 +1,637 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Strings in this file are shared, i.e. they appear multiple times. -->
+<grit-part>
+ <message name="IDS_DEVTOOLS_007c41a9025be2c8e14b496ed3ee00f8" desc="Text to save an item">
+ Save…
+ </message>
+ <message name="IDS_DEVTOOLS_040c4b52a3c06c6067fac76c4c7c3a2c" desc="Title of the 'Network conditions' tool in the bottom drawer">
+ Network conditions
+ </message>
+ <message name="IDS_DEVTOOLS_0511551e6cf7d61acd9b62f9304efa93" desc="Tooltip text that appears on the setting to preserve log when hovering over the item">
+ Do not clear log on page reload / navigation
+ </message>
+ <message name="IDS_DEVTOOLS_07ba8a9247a0f91e025d8036a28c3b56" desc="A tag of Application Panel that can be searched in the command menu">
+ pwa
+ </message>
+ <message name="IDS_DEVTOOLS_0b484cfcf50c8fabff48c0aad426f544" desc="Text to dock the DevTools to the left of the browser tab">
+ Dock to left
+ </message>
+ <message name="IDS_DEVTOOLS_0ca08f8f4a8a19f7f1ae87c119494327" desc="Title as part of a tool to override existing configurations">
+ Overrides
+ </message>
+ <message name="IDS_DEVTOOLS_0eaadb4fcb48a0a0ed7bc9868be9fbaa" desc="Text to indicate an item is a warning">
+ Warning
+ </message>
+ <message name="IDS_DEVTOOLS_0f44e9e39cbe2f22bd1bd7b6070cf13d" desc="Text to enable blocking of network requests">
+ Enable request blocking
+ </message>
+ <message name="IDS_DEVTOOLS_105078d294d30c978ca2badf7f376934" desc="The action to scroll">
+ Scroll
+ </message>
+ <message name="IDS_DEVTOOLS_1063e38cb53d94d386f21227fcd84717" desc="Label for an item to remove something">
+ Remove
+ </message>
+ <message name="IDS_DEVTOOLS_11a755d598c0c417f9a36758c3da7481" desc="Text of an item that stops the running task">
+ Stop
+ </message>
+ <message name="IDS_DEVTOOLS_13348442cc6a27032d2b4aa28b75a5d3" desc="Title of a search bar or tool">
+ Search
+ </message>
+ <message name="IDS_DEVTOOLS_146ffe2fd9fa5bec3b63b52543793ec7" desc="Text to show more content">
+ Show more
+ </message>
+ <message name="IDS_DEVTOOLS_1583d36995134f9120fac115c08e0174" desc="Text when something is loading">
+ Loading…
+ </message>
+ <message name="IDS_DEVTOOLS_16f78b9465f03f7ec5a03c24918fbde3" desc="Status code of an event">
+ Status Code
+ </message>
+ <message name="IDS_DEVTOOLS_193cfc9be3b995831c6af2fea6650e60" desc="Text that refers to one or a group of webpages">
+ Page
+ </message>
+ <message name="IDS_DEVTOOLS_194f5394ae2e9c74dc3c441b92862d1d" desc="Text that appears on a button for the font resource type filter.">
+ Font
+ </message>
+ <message name="IDS_DEVTOOLS_1c481aa99d081c32182011a758f73d33" desc="Text that only contain a placeholder">
+ <ph name="DURATIONTEXT">$1s<ex>100ms (at 200ms)</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_1eaeeaeb638fdf7f6eeb047abbfd0f1a" desc="Time of a single activity, as opposed to the total time">
+ Self Time
+ </message>
+ <message name="IDS_DEVTOOLS_1ebc7540a5327b857144f04cf1435b4e" desc="Text to replay an XHR request">
+ Replay XHR
+ </message>
+ <message name="IDS_DEVTOOLS_1f1e990a1d2ba8ab4dd873a192237c30" desc="Time in miliseconds">
+ <ph name="VALUE">$1.1f<ex>30.1</ex></ph> ms
+ </message>
+ <message name="IDS_DEVTOOLS_22b6fe30dec1ae9c09480cce01cd4065" desc="Text to run commands">
+ Run command
+ </message>
+ <message name="IDS_DEVTOOLS_2310408a63388fe57e3a4177168a8798" desc="Text for the desktop platform, as opposed to mobile">
+ Desktop
+ </message>
+ <message name="IDS_DEVTOOLS_26ae7bdd1d6fb8c4886e6fde8d12601c" desc="Text for the latency of a task">
+ Latency
+ </message>
+ <message name="IDS_DEVTOOLS_290612199861c31d1036b185b4e69b75" desc="Text for the summary view">
+ Summary
+ </message>
+ <message name="IDS_DEVTOOLS_29260f495ba8adcc62fd1307c758ff4e" desc="Text to show the measuring rulers on the target">
+ Show rulers
+ </message>
+ <message name="IDS_DEVTOOLS_29296fcb28eb4edf5d0049b6cac7bbd1" desc="Text for a percentage value">
+ <ph name="SCALE">$1.0f<ex>13.0</ex></ph>%%
+ </message>
+ <message name="IDS_DEVTOOLS_29e9d8e295b1d5b3002d2d3d5baa4c37" desc="Text for keyboard shortcuts">
+ Shortcuts
+ </message>
+ <message name="IDS_DEVTOOLS_2ab5656e27a0ed871c8de44368f807c6" desc="Title of the styles side pane in Elements panel">
+ Styles Pane
+ </message>
+ <message name="IDS_DEVTOOLS_2ae207ddfe5cd256a768769d93a879e5" desc="Title of the paint profiler, old name of the performance pane">
+ Paint Profiler
+ </message>
+ <message name="IDS_DEVTOOLS_2b81bb9b3deebcbfa05edad7a845005a" desc="Text for rendering frames">
+ Frames
+ </message>
+ <message name="IDS_DEVTOOLS_2bbc845892f400626baab5af687527c5" desc="Text for the start time of an activity">
+ Start Time
+ </message>
+ <message name="IDS_DEVTOOLS_2c56c360580420d293172f42d85dfbed" desc="Text that appears on a button for the css resource type filter.">
+ CSS
+ </message>
+ <message name="IDS_DEVTOOLS_2ce2fc341b0bd9219a3634ff43a90bde" desc="Generic text with two placeholders separated by a comma">
+ <ph name="ITEM_LABEL">$1s<ex>1 613 680</ex></ph>, <ph name="CHECKEDSTATE">$2s<ex>44 %</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_2f04f3e6eee339eeb0ddb6c39606424d" desc="Text for searching with regular expressinn">
+ Use Regular Expression
+ </message>
+ <message name="IDS_DEVTOOLS_31fde7b05ac8952dacf4af8a704074ec" desc="Text for previewing items">
+ Preview
+ </message>
+ <message name="IDS_DEVTOOLS_323d4eb70b252acb4a04eaf9e0882597" desc="Title for a group of cities">
+ Geolocation
+ </message>
+ <message name="IDS_DEVTOOLS_340641a167ad6da1bcb4016357f4695d" desc="Title for a type of source files">
+ Content scripts
+ </message>
+ <message name="IDS_DEVTOOLS_36917e785bd31d786ab9dd7790a9a4c2" desc="Text for a heap profile type">
+ JS Heap
+ </message>
+ <message name="IDS_DEVTOOLS_382b0f5185773fa0f67a8ed8056c7759" desc="Text for something not available">
+ N/A
+ </message>
+ <message name="IDS_DEVTOOLS_393c3f5ea8ad35c02691d507bdbb31b0" desc="Text for revealing an item in its destination">
+ Reveal
+ </message>
+ <message name="IDS_DEVTOOLS_3afbd9828e011526955ca93b48b57524" desc="Text for one or a group of screenshots">
+ Screenshot
+ </message>
+ <message name="IDS_DEVTOOLS_3b563524fdb17b4a86590470d40bef74" desc="Text that appears on a button for the media resource type filter.">
+ Media
+ </message>
+ <message name="IDS_DEVTOOLS_3bb3e8c8a24891ba0f7608bcc96f8b0a" desc="Text for a rendering frame">
+ Frame
+ </message>
+ <message name="IDS_DEVTOOLS_3e3f8a3abd60f2389b744ca8ed0aa4d9" desc="Text for no network throttling">
+ No throttling
+ </message>
+ <message name="IDS_DEVTOOLS_3ec365dd533ddb7ef3d1c111186ce872" desc="Text for the details of something">
+ Details
+ </message>
+ <message name="IDS_DEVTOOLS_3edf8ca26a1ec14dd6e91dd277ae1de6" desc="Text for the origin of something">
+ Origin
+ </message>
+ <message name="IDS_DEVTOOLS_3f03ed88ee58335aa3df453443b9c8bc" desc="Text to indicate the progress of a profile">
+ Profiling…
+ </message>
+ <message name="IDS_DEVTOOLS_3f8f88e3686b2345cecc9530e19e6172" desc="Text to store an HTML element or JavaScript variable or expression result as a global variable">
+ Store as global variable
+ </message>
+ <message name="IDS_DEVTOOLS_41fdb410354e76ef7674f98e1cc84c8f" desc="Text for throttling the network">
+ Throttling
+ </message>
+ <message name="IDS_DEVTOOLS_4252b72e6ebcd4d4b4c2e46a786f03d2" desc="Text for zooming in">
+ Zoom
+ </message>
+ <message name="IDS_DEVTOOLS_46a2a41cc6e552044816a2d04634545d" desc="The current state of an item">
+ State
+ </message>
+ <message name="IDS_DEVTOOLS_4789f23283b3a61f858b641a1bef19a3" desc="Text for the memory of the page">
+ Memory
+ </message>
+ <message name="IDS_DEVTOOLS_47bda3033cb8fe0e76c45c293db011b5" desc="Text to indicate there are no breakpoints">
+ No breakpoints
+ </message>
+ <message name="IDS_DEVTOOLS_482a4dca0bbd8fcdda5acc6f95f3c279" desc="Title of the DevTools">
+ <ph name="LOCKED_1">DevTools</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_49ee3087348e8d44e1feda1917443987" desc="Text for the name of something">
+ Name
+ </message>
+ <message name="IDS_DEVTOOLS_4bd7c2ff07dcc66801a9368957d4bff8" desc="Text for the initiator of something">
+ Initiator
+ </message>
+ <message name="IDS_DEVTOOLS_4c3880bb027f159e801041b1021e88e8" desc="Text for one or a group of functions">
+ Method
+ </message>
+ <message name="IDS_DEVTOOLS_4cf8e5f6ffbb182b5d480cbabae6a028" desc="Text to modify the attribute of an item">
+ Edit attribute
+ </message>
+ <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="Text to find an item">
+ Find
+ </message>
+ <message name="IDS_DEVTOOLS_4d1b0b75a9737b7dcdc3a15a84fe856b" desc="Text to indicate the searching is in progress">
+ Searching…
+ </message>
+ <message name="IDS_DEVTOOLS_4dab36ac83853282fc0d7bae20c19e90" desc="Text to show more options">
+ More options
+ </message>
+ <message name="IDS_DEVTOOLS_502996d9790340c5fd7b86a5b93b1c9f" desc="Text to show the priority of an item">
+ Priority
+ </message>
+ <message name="IDS_DEVTOOLS_5134111907df828fc575c69e22480c1e" desc="Text to hide an element">
+ Hide element
+ </message>
+ <message name="IDS_DEVTOOLS_51360304ea03557e79bdf5ff9cd2e234" desc="Text for the issuer of an item">
+ Issuer
+ </message>
+ <message name="IDS_DEVTOOLS_52b3bc5e77aa070243c36cd40a4d6b6d" desc="Text for autocompletion">
+ Autocompletion
+ </message>
+ <message name="IDS_DEVTOOLS_539dddc574d3cd85ba73df93df7a76d0" desc="Text for the execution stack trace">
+ Stack Trace
+ </message>
+ <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="Text to indicate the source of an image">
+ Image from <ph name="URL">$1s<ex>example.com</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_54f664c70c22054ea0d8d26fc3997ce7" desc="Text to indicate the network connectivity is online">
+ Online
+ </message>
+ <message name="IDS_DEVTOOLS_597b56e53847cd6a4712ac183f61fa68" desc="Text for web cookies">
+ Cookies
+ </message>
+ <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="Text to pretty print a file">
+ Pretty print
+ </message>
+ <message name="IDS_DEVTOOLS_5a0a64ecca63ba9a006b6397cbdc2b8c" desc="Text to go to a given line">
+ Go to line
+ </message>
+ <message name="IDS_DEVTOOLS_5b6cf869265c13af8566f192b4ab3d2a" desc="Text for the documentation of something">
+ Documentation
+ </message>
+ <message name="IDS_DEVTOOLS_5bc06f5800d415cc95e1349edbaca425" desc="Text that appears on a button for the javascript resource type filter.">
+ JS
+ </message>
+ <message name="IDS_DEVTOOLS_5de39fa1bce4bbf9232597a2120bc4d4" desc="Text to open the cubic bezier editor">
+ Open cubic bezier editor.
+ </message>
+ <message name="IDS_DEVTOOLS_5ef0c737746fae2ca90e66c39333f8f6" desc="Text for errors">
+ Errors
+ </message>
+ <message name="IDS_DEVTOOLS_5f0ea62e5bc9f795512ef292ff162a2a" desc="Text to disable cache while DevTools is open">
+ Disable cache (while <ph name="LOCKED_1">DevTools</ph> is open)
+ </message>
+ <message name="IDS_DEVTOOLS_5f8442a46861496e9d2a3d11be13692b" desc="Text to indicate DevTools is writing to a file">
+ Writing file…
+ </message>
+ <message name="IDS_DEVTOOLS_5fb63579fc981698f97d55bfecb213ea" desc="Text for copying">
+ Copy
+ </message>
+ <message name="IDS_DEVTOOLS_63041e09c8660107e507c9c27c08199c" desc="Text to expand something recursively">
+ Expand recursively
+ </message>
+ <message name="IDS_DEVTOOLS_6311ae17c1ee52b36e68aaf4ad066387" desc="Text for other types of items">
+ Other
+ </message>
+ <message name="IDS_DEVTOOLS_63a6a88c066880c5ac42394a22803ca6" desc="Text to refresh the page">
+ Refresh
+ </message>
+ <message name="IDS_DEVTOOLS_6525b37c568c526bde7c02fac8195c73" desc="Text for percentage">
+ <ph name="PERCENTAGE">$1.1f<ex>20.1</ex></ph> %%
+ </message>
+ <message name="IDS_DEVTOOLS_65b4c7424dd695c30efa73da8396c90c" desc="Title of the Profiler tool">
+ Profiler
+ </message>
+ <message name="IDS_DEVTOOLS_686155af75a60a0f6e9d80c1f7edd3e9" desc="Text in Timeline Tree View of the Performance panel">
+ JavaScript
+ </message>
+ <message name="IDS_DEVTOOLS_689202409e48743b914713f96d93947c" desc="Text for the value of something">
+ Value
+ </message>
+ <message name="IDS_DEVTOOLS_6a0d9eaee314c567fd72fb97ee707a36" desc="Text to record a series of actions for analysis">
+ Record
+ </message>
+ <message name="IDS_DEVTOOLS_6a26f548831e6a8c26bfbbd9f6ec61e0" desc="Text for the viewing the help options">
+ Help
+ </message>
+ <message name="IDS_DEVTOOLS_6adf97f83acf6453d4a6a4b1070f3754" desc="Text to show there is nothing">
+ None
+ </message>
+ <message name="IDS_DEVTOOLS_6ba3a9ac3e0d57683c56299484b7ee3b" desc="Text to remove all breakpoints">
+ Remove all breakpoints
+ </message>
+ <message name="IDS_DEVTOOLS_6bb61b1a929f2a0186f2671cd8258bd9" desc="Text to show something is not optimized">
+ Not optimized: <ph name="REASON">$1s<ex>Optimized too many times</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_6f6cb72d544962fa333e2e34ce64f719" desc="Text for the size of something">
+ Size
+ </message>
+ <message name="IDS_DEVTOOLS_74540c79e377bea903e1023a46df5574" desc="Text to open a file">
+ Open file
+ </message>
+ <message name="IDS_DEVTOOLS_76c3e002d3c052bd6a909366a8dc3845" desc="Text that appears on a button for the manifest resource type filter.">
+ Manifest
+ </message>
+ <message name="IDS_DEVTOOLS_787ae37366b7a8c53f381abfd315c647" desc="Text that refers to the Elements Panel">
+ Elements Panel
+ </message>
+ <message name="IDS_DEVTOOLS_7a2ccf251ecb20b2b84ce0e3c3f72a29" desc="Text to show something is secure">
+ Secure
+ </message>
+ <message name="IDS_DEVTOOLS_7b3a6b02f467b95f2b5267aa94708c07" desc="Text for the name of a thread of the page">
+ Thread <ph name="TID">$1s<ex>1</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_7d341c08fd102f0b86285b5ff2e26ea7" desc="Text with two placeholders separated by a colon">
+ <ph name="BREAKPOINT_TYPE_LABEL">$1s<ex>Node removed</ex></ph>: <ph name="LINKIFIED_CONTENT">$2s<ex>div#id1</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_8166a4b3fb4979da3a24ed21ced7fdf7" desc="Text for an option to learn more about something">
+ Learn more
+ </message>
+ <message name="IDS_DEVTOOLS_81aa2078d1eceede831b2976dbf32e62" desc="Text to clear everything">
+ Clear all
+ </message>
+ <message name="IDS_DEVTOOLS_84d0c431d1472a0609d69b39dcb3a287" desc="Text for the index of something">
+ (index)
+ </message>
+ <message name="IDS_DEVTOOLS_850985cd851d0fe440f03f77762e2590" desc="Text for the network request Content-Length header">
+ <ph name="LOCKED_1">Content-Length</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_86408593c34af77fdd90df932f8b5261" desc="Text for a programming function">
+ Function
+ </message>
+ <message name="IDS_DEVTOOLS_87bfda183c4f851a101e97bbb1bbace7" desc="Title of the Layers tool">
+ Layers
+ </message>
+ <message name="IDS_DEVTOOLS_87d17f4624a514e81dc7c8e016a7405c" desc="Text for the mobile platform, as opposed to desktop">
+ Mobile
+ </message>
+ <message name="IDS_DEVTOOLS_883d7615c4d2de3fa1218f1298c46d0e" desc="Text for network request headers">
+ Headers
+ </message>
+ <message name="IDS_DEVTOOLS_884680dd63eae99eab1a407133df66b7" desc="Text to view a security certificate">
+ View certificate
+ </message>
+ <message name="IDS_DEVTOOLS_888a77f5ac0748b6c8001822417df8b6" desc="Text for security or network protocol">
+ Protocol
+ </message>
+ <message name="IDS_DEVTOOLS_8d9da4bc0e49a50e09ac9f7e56789d39" desc="Text to indicate the network connectivity is offline">
+ Offline
+ </message>
+ <message name="IDS_DEVTOOLS_902b0d55fddef6f8d651fe1035b7d4bd" desc="Text for errors">
+ Error
+ </message>
+ <message name="IDS_DEVTOOLS_90da6f38945a1c7e7ba11e3adcbe6919" desc="Text for pausing the debugger on exceptions">
+ Pause on exceptions
+ </message>
+ <message name="IDS_DEVTOOLS_913f9c49dcb544e2087cee284f4a00b7" desc="A tag of Mobile related settings that can be searched in the command menu">
+ device
+ </message>
+ <message name="IDS_DEVTOOLS_91e02cd2b8621d0c05197f645668c5c4" desc="A tag of Group Network by frame setting that can be searched in the command menu">
+ network
+ </message>
+ <message name="IDS_DEVTOOLS_93898e12951c906e5286ccb36d980ce5" desc="Text for scripts that should not be stepped into when debugging">
+ Blackbox script
+ </message>
+ <message name="IDS_DEVTOOLS_939aaa05e0943b39eab3a34fd609384d" desc="Text to scroll the displayed content into view">
+ Scroll into view
+ </message>
+ <message name="IDS_DEVTOOLS_9446a98ad14416153cc4d45ab8b531bf" desc="Text for the performance of something">
+ Performance
+ </message>
+ <message name="IDS_DEVTOOLS_95bbad55f11c237ed89546e748093ba7" desc="Text for the request animation frame event">
+ Request Animation Frame
+ </message>
+ <message name="IDS_DEVTOOLS_96b0141273eabab320119c467cdcaf17" desc="Text for sum">
+ Total
+ </message>
+ <message name="IDS_DEVTOOLS_96e9bc575b5d3ed541113a249da8bd24" desc="Text to take screenshots">
+ Capture screenshots
+ </message>
+ <message name="IDS_DEVTOOLS_9841bdc50c4226cb6ec5db76494249e6" desc="Title of the 'Coverage' tool in the bottom drawer">
+ Coverage
+ </message>
+ <message name="IDS_DEVTOOLS_997a8c473db4f81c5fb3d5900030d44d" desc="Text that shows there is no recording">
+ (no recordings)
+ </message>
+ <message name="IDS_DEVTOOLS_9aae9fe27dbf2db0ad90762b5b59d3a7" desc="Text to clear the console">
+ Clear console
+ </message>
+ <message name="IDS_DEVTOOLS_9d8c209e49e328528c39c273798e98c9" desc="Text to save content as a specific file type">
+ Save as...
+ </message>
+ <message name="IDS_DEVTOOLS_9df22f196a33acd0b372fe502de51211" desc="Text short for automatic">
+ auto
+ </message>
+ <message name="IDS_DEVTOOLS_9dffbf69ffba8bc38bc4e01abf4b1675" desc="Generic label for any text">
+ Text
+ </message>
+ <message name="IDS_DEVTOOLS_9e65b51e82f2a9b9f72ebe3e083582bb" desc="Text to show an item is empty">
+ (empty)
+ </message>
+ <message name="IDS_DEVTOOLS_9f29da220ed82809ec5dd70af4e52904" desc="Text for the total time of something">
+ Total Time
+ </message>
+ <message name="IDS_DEVTOOLS_9fc2d28c05ed9eb1d75ba4465abf15a9" desc="Title of the 'Properties' tool in the sidebar of the elements tool">
+ Properties
+ </message>
+ <message name="IDS_DEVTOOLS_a02c83a7dbd96295beaefb72c2bee2de" desc="Text that refers to the main target">
+ Main
+ </message>
+ <message name="IDS_DEVTOOLS_a1c58e94227389415de133efdf78ea6e" desc="Text for DevTools appearance">
+ Appearance
+ </message>
+ <message name="IDS_DEVTOOLS_a1fa27779242b4902f7ae3bdd5c6d508" desc="Text that refers to some types">
+ Type
+ </message>
+ <message name="IDS_DEVTOOLS_a2e4822a98337283e39f7b60acf85ec9" desc="Text to show an item is empty">
+ empty
+ </message>
+ <message name="IDS_DEVTOOLS_a3d5de3eac8bb00ae86fd1a1005f1500" desc="Text for timestamps of items">
+ Timestamp
+ </message>
+ <message name="IDS_DEVTOOLS_a4ecfc70574394990cf17bd83df499f7" desc="Text that refers to some events">
+ Event
+ </message>
+ <message name="IDS_DEVTOOLS_a6e8f9aed2ac6481dc25a18a33342d03" desc="Title of the Rendering tool">
+ Rendering
+ </message>
+ <message name="IDS_DEVTOOLS_a76d4ef5f3f6a672bbfab2865563e530" desc="Text that refers to the time">
+ Time
+ </message>
+ <message name="IDS_DEVTOOLS_aa56a2e65d8106aef3c61e4f6bf94fdb" desc="Title of the Elements Panel">
+ Elements
+ </message>
+ <message name="IDS_DEVTOOLS_aab112fba39c10ed5df335ae0e47f329" desc="Text that indicates something is not optimized">
+ Not optimized
+ </message>
+ <message name="IDS_DEVTOOLS_ab57fd0432e25d5b3013133a1c910d56" desc="A unit">
+ KB
+ </message>
+ <message name="IDS_DEVTOOLS_abbd64f40c34c537d3a571af068fce29" desc="Text for the orientation of something">
+ Orientation
+ </message>
+ <message name="IDS_DEVTOOLS_ac70412e939d72a9234cdebb1af5867b" desc="Text that refers to a file path">
+ Path
+ </message>
+ <message name="IDS_DEVTOOLS_acc24772ac31677d076f17d9002b57cd" desc="Text to collapse children of a parent group">
+ Collapse children
+ </message>
+ <message name="IDS_DEVTOOLS_af4bb376939e77df0e7c2332b837a866" desc="Text that refers to closure as a programming term">
+ Closure
+ </message>
+ <message name="IDS_DEVTOOLS_af9ccba3ec4346e3acf785f9bea514d8" desc="Text to show a tool or panel">
+ Show <ph name="EXTENSION_TITLE">$1s<ex>Audits</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_afb4ea732ebcf8bd51a3d99a1b8909a8" desc="Text to show something is linked to another">
+ Linked to <ph name="PATH">$1s<ex>example.url</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_b1c94ca2fbc3e78fc30069c8d0f01680" desc="Text for everything">
+ All
+ </message>
+ <message name="IDS_DEVTOOLS_b1d75786654fa93f10c31c3b544bbd03" desc="Text to run a code snippet">
+ Run snippet
+ </message>
+ <message name="IDS_DEVTOOLS_b2844b8e17ecaaeae68d018fe9418af0" desc="Text to indicate the expiry date">
+ Valid until
+ </message>
+ <message name="IDS_DEVTOOLS_b4e79b551a1ceae24b7de243ab1fd27c" desc="Text to add a breakpoint">
+ Add breakpoint
+ </message>
+ <message name="IDS_DEVTOOLS_b5a7adde1af5c87d7fd797b6245c2a39" desc="Text for the description of something">
+ Description
+ </message>
+ <message name="IDS_DEVTOOLS_b6434258c743f8673997b5aeb3721c27" desc="Text that refers to the network request method">
+ Request Method
+ </message>
+ <message name="IDS_DEVTOOLS_b94d8a074eddd267702810179875737f" desc="Text that refers to the debugger">
+ Debugger
+ </message>
+ <message name="IDS_DEVTOOLS_b9dee6bade160c89fb7f0e539d453513" desc="Text to dock the DevTools to the bottom of the browser tab">
+ Dock to bottom
+ </message>
+ <message name="IDS_DEVTOOLS_b9f5c797ebbf55adccdd8539a65a0241" desc="Text to indicate something is not enabled">
+ Disabled
+ </message>
+ <message name="IDS_DEVTOOLS_ba5b676ccf658f863ef2e3df082ee262" desc="Text for the event that an animation frame is fired">
+ Animation Frame Fired
+ </message>
+ <message name="IDS_DEVTOOLS_bc28aa52ba5b534ad9d198157c375d67" desc="Text to clear storage of the web page">
+ Clear storage
+ </message>
+ <message name="IDS_DEVTOOLS_bc955333ff170762be4971a8fde558cf" desc="Title of the WebAudio tool">
+ WebAudio
+ </message>
+ <message name="IDS_DEVTOOLS_bccaa4aa80831b76c11240a16447975f" desc="Title of the Console tool">
+ Console
+ </message>
+ <message name="IDS_DEVTOOLS_be53a0541a6d36f6ecb879fa2c584b08" desc="Text in Image View of the Sources panel">
+ Image
+ </message>
+ <message name="IDS_DEVTOOLS_be8545ae7ab0276e15898aae7acfbd7a" desc="Text that refers to the resources of the web page">
+ Resource
+ </message>
+ <message name="IDS_DEVTOOLS_c03ca67dda321195d74c951097f240c6" desc="Title of the Devices tab">
+ Devices
+ </message>
+ <message name="IDS_DEVTOOLS_c2cc7082a89c1ad6631a2f66af5f00c0" desc="Text that refers to the network connection">
+ Connection
+ </message>
+ <message name="IDS_DEVTOOLS_c3fe109bf99ade2d76a55e5737015e3e" desc="Text to stop preventing the debugger from stepping into library code">
+ Stop blackboxing
+ </message>
+ <message name="IDS_DEVTOOLS_c74ea6dbff701bfa23819583c52ebd97" desc="Text to show less content">
+ Show less
+ </message>
+ <message name="IDS_DEVTOOLS_c7892ebbb139886662c6f2fc8c450710" desc="Text that refers to the subject of a security certificate">
+ Subject
+ </message>
+ <message name="IDS_DEVTOOLS_c949475bc69a57c419ac976fe8870652" desc="Text to search by matching case of the input">
+ Match Case
+ </message>
+ <message name="IDS_DEVTOOLS_c9ad95228aa735bdda1aebf38da022af" desc="Text to parse something">
+ Parse
+ </message>
+ <message name="IDS_DEVTOOLS_c9cc8cce247e49bae79f15173ce97354" desc="Text to save something">
+ Save
+ </message>
+ <message name="IDS_DEVTOOLS_c9deece3e6de26d07ef6409b96f21fd0" desc="Title of Blackboxing settings">
+ Blackboxing
+ </message>
+ <message name="IDS_DEVTOOLS_ce82e07fa1f0521f5cee30e368fe2e73" desc="Text that starts with a colon and includes a placeholder">
+ : <ph name="AA_NUMBER">$1s<ex>3.0</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_d31827f0a164d52b636bb1f71ca4a351" desc="Text to cancel the animation frame">
+ Cancel Animation Frame
+ </message>
+ <message name="IDS_DEVTOOLS_d3d2e617335f08df83599665eef8a418" desc="Text to close something">
+ Close
+ </message>
+ <message name="IDS_DEVTOOLS_d59048f21fd887ad520398ce677be586" desc="Text that is usually a hyperlink to more documentation">
+ Learn more
+ </message>
+ <message name="IDS_DEVTOOLS_d5bfaaca8e28f8b9b9211038f86a4494" desc="Text to remove a breakpoint">
+ Remove breakpoint
+ </message>
+ <message name="IDS_DEVTOOLS_d64ed3e9c10229648e069f56e32f4c8e" desc="Text for a network response">
+ Response
+ </message>
+ <message name="IDS_DEVTOOLS_d6b6b668dbca9d4fe774bb654226ebe3" desc="Text that refers to the animation of the web page">
+ Animation
+ </message>
+ <message name="IDS_DEVTOOLS_d7778d0c64b6ba21494c97f77a66885a" desc="Text to filter result items">
+ Filter
+ </message>
+ <message name="IDS_DEVTOOLS_dc30bc0c7914db5918da4263fce93ad2" desc="Text to clear content">
+ Clear
+ </message>
+ <message name="IDS_DEVTOOLS_e02d2ae03de9d493df2b6b2d2813d302" desc="Text for the duration of something">
+ Duration
+ </message>
+ <message name="IDS_DEVTOOLS_e0ac20adce6ffee48c7151b070aa5737" desc="Text that refers to device such as a phone">
+ Device
+ </message>
+ <message name="IDS_DEVTOOLS_e0e4fc6213e8b3593495a7260c3a4c2e" desc="Text for accessibility of the web page">
+ Accessibility
+ </message>
+ <message name="IDS_DEVTOOLS_e24ee2487879116dcab772c0ac4fe341" desc="Text to focus on something">
+ Focus
+ </message>
+ <message name="IDS_DEVTOOLS_e402c138065e7eece783dc30c6079192" desc="Text that appears on a button for the xhr resource type filter.">
+ XHR
+ </message>
+ <message name="IDS_DEVTOOLS_e55f75a29310d7b60f7ac1d390c8ae42" desc="Text for a module, the programming concept">
+ Module
+ </message>
+ <message name="IDS_DEVTOOLS_e576c23d915755d83e2d1f47bd9f6c22" desc="Text to show no results have been found">
+ No results found
+ </message>
+ <message name="IDS_DEVTOOLS_e6b391a8d2c4d45902a23a8b6585703d" desc="Text for web URLs">
+ URL
+ </message>
+ <message name="IDS_DEVTOOLS_e77fef0167598bb39846637ac3915f4e" desc="Text to clear everything">
+ Clear All
+ </message>
+ <message name="IDS_DEVTOOLS_ea4788705e6873b424c65e91c2846b19" desc="Text to cancel something">
+ Cancel
+ </message>
+ <message name="IDS_DEVTOOLS_eae639a70006feff484a39363c977e24" desc="Text for the domain of a website">
+ Domain
+ </message>
+ <message name="IDS_DEVTOOLS_eb0f48a107df1a0f343d4cd513b555e6" desc="Text for a security certificate">
+ Certificate
+ </message>
+ <message name="IDS_DEVTOOLS_eb81441fe20963ff9e8e69c5b32fc625" desc="Title for a group of configuration options">
+ Presets
+ </message>
+ <message name="IDS_DEVTOOLS_eb902cf204f3e4dfffeb56d92a9b5c26" desc="Text to show since when an item is valid">
+ Valid from
+ </message>
+ <message name="IDS_DEVTOOLS_ec211f7c20af43e742bf2570c3cb84f9" desc="Text to add something">
+ Add
+ </message>
+ <message name="IDS_DEVTOOLS_ec53a8c4f07baed5d8825072c89799be" desc="Text for the status of something">
+ Status
+ </message>
+ <message name="IDS_DEVTOOLS_edd24cce7afedea5a1b2f90675880687" desc="Text to preserve the log after refreshing">
+ Preserve log
+ </message>
+ <message name="IDS_DEVTOOLS_ee33e909372d935d190f4fcb2a92d542" desc="The milisecond unit">
+ ms
+ </message>
+ <message name="IDS_DEVTOOLS_eec89088ee408b80387155272b113256" desc="Title of the Network tool">
+ Network
+ </message>
+ <message name="IDS_DEVTOOLS_ef95393ad48336d7c3543625354a3d56" desc="Text to highlight the rendering frames for ads">
+ Highlight ad frames
+ </message>
+ <message name="IDS_DEVTOOLS_f0f31c9700c6b10d8a20dc487b2ae6a8" desc="Text for the touch type to simulate on a device">
+ Touch
+ </message>
+ <message name="IDS_DEVTOOLS_f19dbf2edb3a0bd74b0524d960ff21eb" desc="Text to load something">
+ Load
+ </message>
+ <message name="IDS_DEVTOOLS_f28128b38efbc6134dc40751ee21fd29" desc="Text for documents, a type of resources">
+ Documents
+ </message>
+ <message name="IDS_DEVTOOLS_f2a6c498fb90ee345d997f888fce3b18" desc="Text to delete something">
+ Delete
+ </message>
+ <message name="IDS_DEVTOOLS_f31bbdd1b3e85bccd652680e16935819" desc="Text for the source of something">
+ Source
+ </message>
+ <message name="IDS_DEVTOOLS_f4f70727dc34561dfde1a3c529b6205c" desc="Title for a setting">
+ Settings
+ </message>
+ <message name="IDS_DEVTOOLS_f53944c3a55bdb5ad65c6226e358a626" desc="Text to undock the DevTools">
+ Undock into separate window
+ </message>
+ <message name="IDS_DEVTOOLS_f80bc338b6146b566004a046f8137c85" desc="Text in Event Listeners Widget of the Elements panel">
+ Passive
+ </message>
+ <message name="IDS_DEVTOOLS_f907e651164789346ae0a1e257c462d8" desc="Label for a group of JavaScript files">
+ Script
+ </message>
+ <message name="IDS_DEVTOOLS_fa6711f918fe2018131a4ad0380b9e56" desc="Name of an item from source map">
+ <ph name="DISPLAY_NAME">$1s<ex>compile.html</ex></ph> (from source map)
+ </message>
+ <message name="IDS_DEVTOOLS_fb61758d0f0fda4ba867c3d5a46c16a7" desc="Name of the Sources panel">
+ Sources
+ </message>
+ <message name="IDS_DEVTOOLS_fdbd92f0c6b67291ca954b74885d434e" desc="Name of a profile">
+ Profile <ph name="NUMBER">$1d<ex>2</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_fe7fb037b290768d6a6be30b237e183d" desc="Text to dock the DevTools to the right of the browser tab">
+ Dock to right
+ </message>
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerDetailsView.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerDetailsView.js
index 8daae62d161..268a15e52ee 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerDetailsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerDetailsView.js
@@ -57,8 +57,9 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
*/
selectObject(selection) {
this._selection = selection;
- if (this.isShowing())
+ if (this.isShowing()) {
this.update();
+ }
}
/**
@@ -81,14 +82,16 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
* @param {!Event} event
*/
_onScrollRectClicked(index, event) {
- if (event.which !== 1)
+ if (event.which !== 1) {
return;
+ }
this._layerViewHost.selectObject(new LayerViewer.LayerView.ScrollRectSelection(this._selection.layer(), index));
}
_onPaintProfilerButtonClicked() {
- if (this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot || this._selection.layer())
+ if (this._selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot || this._selection.layer()) {
this.dispatchEventToListeners(LayerViewer.LayerDetailsView.Events.PaintProfilerRequested, this._selection);
+ }
}
/**
@@ -96,11 +99,13 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
* @param {number} index
*/
_createScrollRectElement(scrollRect, index) {
- if (index)
+ if (index) {
this._scrollRectsCell.createTextChild(', ');
+ }
const element = this._scrollRectsCell.createChild('span', 'scroll-rect');
- if (this._selection.scrollRectIndex === index)
+ if (this._selection.scrollRectIndex === index) {
element.classList.add('active');
+ }
element.textContent = Common.UIString(
'%s %d × %d (at %d, %d)', LayerViewer.LayerDetailsView._slowScrollRectNames.get(scrollRect.type),
scrollRect.rect.x, scrollRect.rect.y, scrollRect.rect.width, scrollRect.rect.height);
@@ -113,8 +118,9 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
* @return {string}
*/
_formatStickyAncestorLayer(title, layer) {
- if (!layer)
+ if (!layer) {
return '';
+ }
const node = layer.nodeForSelfOrAncestor();
const name = node ? node.simpleSelector() : Common.UIString('<unnamed>');
@@ -126,8 +132,9 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
* @param {?SDK.Layer} layer
*/
_createStickyAncestorChild(title, layer) {
- if (!layer)
+ if (!layer) {
return;
+ }
this._stickyPositionConstraintCell.createTextChild(', ');
const child = this._stickyPositionConstraintCell.createChild('span');
@@ -139,8 +146,9 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
*/
_populateStickyPositionConstraintCell(constraint) {
this._stickyPositionConstraintCell.removeChildren();
- if (!constraint)
+ if (!constraint) {
return;
+ }
const stickyBoxRect = constraint.stickyBoxRect();
const stickyBoxRectElement = this._stickyPositionConstraintCell.createChild('span');
@@ -222,10 +230,12 @@ LayerViewer.LayerDetailsView = class extends UI.Widget {
this._compositingReasonsCell.removeChildren();
const list = this._compositingReasonsCell.createChild('ul');
for (let i = 0; i < compositingReasons.length; ++i) {
- let text = LayerViewer.LayerDetailsView.CompositingReasonDetail[compositingReasons[i]] || compositingReasons[i];
+ // The reason is coming straight from third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+ let text = compositingReasons[i];
// If the text is more than one word but does not terminate with period, add the period.
- if (/\s.*[^.]$/.test(text))
+ if (/\s.*[^.]$/.test(text)) {
text += '.';
+ }
list.createChild('li').textContent = text;
}
}
@@ -239,57 +249,6 @@ LayerViewer.LayerDetailsView.Events = {
PaintProfilerRequested: Symbol('PaintProfilerRequested')
};
-/**
- * @type {!Object.<string, string>}
- */
-LayerViewer.LayerDetailsView.CompositingReasonDetail = {
- 'transform3D': Common.UIString('Composition due to association with an element with a CSS 3D transform.'),
- 'video': Common.UIString('Composition due to association with a <video> element.'),
- 'canvas': Common.UIString('Composition due to the element being a <canvas> element.'),
- 'plugin': Common.UIString('Composition due to association with a plugin.'),
- 'iFrame': Common.UIString('Composition due to association with an <iframe> element.'),
- 'backfaceVisibilityHidden':
- Common.UIString('Composition due to association with an element with a "backface-visibility: hidden" style.'),
- 'animation': Common.UIString('Composition due to association with an animated element.'),
- 'filters': Common.UIString('Composition due to association with an element with CSS filters applied.'),
- 'scrollDependentPosition': Common.UIString(
- 'Composition due to association with an element with a "position: fixed" or "position: sticky" style.'),
- 'overflowScrollingTouch':
- Common.UIString('Composition due to association with an element with a "overflow-scrolling: touch" style.'),
- 'blending':
- Common.UIString('Composition due to association with an element that has blend mode other than "normal".'),
- 'assumedOverlap':
- Common.UIString('Composition due to association with an element that may overlap other composited elements.'),
- 'overlap': Common.UIString('Composition due to association with an element overlapping other composited elements.'),
- 'negativeZIndexChildren':
- Common.UIString('Composition due to association with an element with descendants that have a negative z-index.'),
- 'transformWithCompositedDescendants':
- Common.UIString('Composition due to association with an element with composited descendants.'),
- 'opacityWithCompositedDescendants': Common.UIString(
- 'Composition due to association with an element with opacity applied and composited descendants.'),
- 'maskWithCompositedDescendants':
- Common.UIString('Composition due to association with a masked element and composited descendants.'),
- 'reflectionWithCompositedDescendants':
- Common.UIString('Composition due to association with an element with a reflection and composited descendants.'),
- 'filterWithCompositedDescendants': Common.UIString(
- 'Composition due to association with an element with CSS filters applied and composited descendants.'),
- 'blendingWithCompositedDescendants': Common.UIString(
- 'Composition due to association with an element with CSS blending applied and composited descendants.'),
- 'clipsCompositingDescendants':
- Common.UIString('Composition due to association with an element clipping compositing descendants.'),
- 'perspective': Common.UIString('Composition due to association with an element with perspective applied.'),
- 'preserve3D':
- Common.UIString('Composition due to association with an element with a "transform-style: preserve-3d" style.'),
- 'root': Common.UIString('Root layer.'),
- 'layerForClip': Common.UIString('Layer for clip.'),
- 'layerForScrollbar': Common.UIString('Layer for scrollbar.'),
- 'layerForScrollingContainer': Common.UIString('Layer for scrolling container.'),
- 'layerForForeground': Common.UIString('Layer for foreground.'),
- 'layerForBackground': Common.UIString('Layer for background.'),
- 'layerForMask': Common.UIString('Layer for mask.'),
- 'layerForVideoOverlay': Common.UIString('Layer for video overlay.'),
-};
-
LayerViewer.LayerDetailsView._slowScrollRectNames = new Map([
[SDK.Layer.ScrollRectType.NonFastScrollable, Common.UIString('Non fast scrollable')],
[SDK.Layer.ScrollRectType.TouchEventHandler, Common.UIString('Touch event handler')],
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerTreeOutline.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerTreeOutline.js
index 94c19cc0307..5d88ddf33fe 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerTreeOutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerTreeOutline.js
@@ -63,10 +63,11 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
this.hoverObject(null);
const layer = selection && selection.layer();
const node = layer && layer[LayerViewer.LayerTreeElement._symbol];
- if (node)
+ if (node) {
node.revealAndSelect(true);
- else if (this._treeOutline.selectedTreeElement)
+ } else if (this._treeOutline.selectedTreeElement) {
this._treeOutline.selectedTreeElement.deselect();
+ }
}
/**
@@ -76,12 +77,15 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
hoverObject(selection) {
const layer = selection && selection.layer();
const node = layer && layer[LayerViewer.LayerTreeElement._symbol];
- if (node === this._lastHoveredNode)
+ if (node === this._lastHoveredNode) {
return;
- if (this._lastHoveredNode)
+ }
+ if (this._lastHoveredNode) {
this._lastHoveredNode.setHovered(false);
- if (node)
+ }
+ if (node) {
node.setHovered(true);
+ }
this._lastHoveredNode = node;
}
@@ -99,10 +103,12 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
const seenLayers = new Map();
let root = null;
if (this._layerTree) {
- if (!showInternalLayers)
+ if (!showInternalLayers) {
root = this._layerTree.contentRoot();
- if (!root)
+ }
+ if (!root) {
root = this._layerTree.root();
+ }
}
/**
@@ -110,16 +116,19 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
* @this {LayerViewer.LayerTreeOutline}
*/
function updateLayer(layer) {
- if (!layer.drawsContent() && !showInternalLayers)
+ if (!layer.drawsContent() && !showInternalLayers) {
return;
- if (seenLayers.get(layer))
+ }
+ if (seenLayers.get(layer)) {
console.assert(false, 'Duplicate layer: ' + layer.id());
+ }
seenLayers.set(layer, true);
let node = layer[LayerViewer.LayerTreeElement._symbol];
let parentLayer = layer.parent();
// Skip till nearest visible ancestor.
- while (parentLayer && parentLayer !== root && !parentLayer.drawsContent() && !showInternalLayers)
+ while (parentLayer && parentLayer !== root && !parentLayer.drawsContent() && !showInternalLayers) {
parentLayer = parentLayer.parent();
+ }
const parent =
layer === root ? this._treeOutline.rootElement() : parentLayer[LayerViewer.LayerTreeElement._symbol];
if (!parent) {
@@ -130,22 +139,26 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
node = new LayerViewer.LayerTreeElement(this, layer);
parent.appendChild(node);
// Expand all new non-content layers to expose content layers better.
- if (!layer.drawsContent())
+ if (!layer.drawsContent()) {
node.expand();
+ }
} else {
if (node.parent !== parent) {
const oldSelection = this._treeOutline.selectedTreeElement;
- if (node.parent)
+ if (node.parent) {
node.parent.removeChild(node);
+ }
parent.appendChild(node);
- if (oldSelection !== this._treeOutline.selectedTreeElement)
+ if (oldSelection !== this._treeOutline.selectedTreeElement) {
oldSelection.select();
+ }
}
node._update();
}
}
- if (root)
+ if (root) {
this._layerTree.forEachLayer(updateLayer.bind(this), root);
+ }
// Cleanup layers that don't exist anymore from tree.
const rootElement = this._treeOutline.rootElement();
for (let node = rootElement.firstChild(); node && !node.root;) {
@@ -154,15 +167,17 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
} else {
const nextNode = node.nextSibling || node.parent;
node.parent.removeChild(node);
- if (node === this._lastHoveredNode)
+ if (node === this._lastHoveredNode) {
this._lastHoveredNode = null;
+ }
node = nextNode;
}
}
if (!this._treeOutline.selectedTreeElement) {
const elementToSelect = this._layerTree.contentRoot() || this._layerTree.root();
- if (elementToSelect)
+ if (elementToSelect) {
elementToSelect[LayerViewer.LayerTreeElement._symbol].revealAndSelect(true);
+ }
}
}
@@ -171,8 +186,9 @@ LayerViewer.LayerTreeOutline = class extends Common.Object {
*/
_onMouseMove(event) {
const node = this._treeOutline.treeElementFromEvent(event);
- if (node === this._lastHoveredNode)
+ if (node === this._lastHoveredNode) {
return;
+ }
this._layerViewHost.hoverObject(this._selectionForNode(node));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerViewHost.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerViewHost.js
index 6aa3ee731bc..f92b464a1f9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerViewHost.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/LayerViewHost.js
@@ -182,37 +182,44 @@ LayerViewer.LayerViewHost = class {
setLayerTree(layerTree) {
this._target = layerTree.target();
const selectedLayer = this._selectedObject && this._selectedObject.layer();
- if (selectedLayer && (!layerTree || !layerTree.layerById(selectedLayer.id())))
+ if (selectedLayer && (!layerTree || !layerTree.layerById(selectedLayer.id()))) {
this.selectObject(null);
+ }
const hoveredLayer = this._hoveredObject && this._hoveredObject.layer();
- if (hoveredLayer && (!layerTree || !layerTree.layerById(hoveredLayer.id())))
+ if (hoveredLayer && (!layerTree || !layerTree.layerById(hoveredLayer.id()))) {
this.hoverObject(null);
- for (const view of this._views)
+ }
+ for (const view of this._views) {
view.setLayerTree(layerTree);
+ }
}
/**
* @param {?LayerViewer.LayerView.Selection} selection
*/
hoverObject(selection) {
- if (LayerViewer.LayerView.Selection.isEqual(this._hoveredObject, selection))
+ if (LayerViewer.LayerView.Selection.isEqual(this._hoveredObject, selection)) {
return;
+ }
this._hoveredObject = selection;
const layer = selection && selection.layer();
this._toggleNodeHighlight(layer ? layer.nodeForSelfOrAncestor() : null);
- for (const view of this._views)
+ for (const view of this._views) {
view.hoverObject(selection);
+ }
}
/**
* @param {?LayerViewer.LayerView.Selection} selection
*/
selectObject(selection) {
- if (LayerViewer.LayerView.Selection.isEqual(this._selectedObject, selection))
+ if (LayerViewer.LayerView.Selection.isEqual(this._selectedObject, selection)) {
return;
+ }
this._selectedObject = selection;
- for (const view of this._views)
+ for (const view of this._views) {
view.selectObject(selection);
+ }
}
/**
@@ -231,8 +238,9 @@ LayerViewer.LayerViewHost = class {
Common.UIString('Show internal layers'), this._toggleShowInternalLayers.bind(this),
this._showInternalLayersSetting.get());
const node = selection && selection.layer() && selection.layer().nodeForSelfOrAncestor();
- if (node)
+ if (node) {
contextMenu.appendApplicableItems(node);
+ }
contextMenu.show();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/Layers3DView.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/Layers3DView.js
index 779e227e165..b68f022aabb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/Layers3DView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/Layers3DView.js
@@ -80,8 +80,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
this._layerTree = layerTree;
this._layerTexture = null;
delete this._oldTextureScale;
- if (this._showPaints())
+ if (this._showPaints()) {
this._textureManager.setLayerTree(layerTree);
+ }
this._update();
}
@@ -122,8 +123,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
*/
wasShown() {
this._textureManager.resume();
- if (!this._needsUpdate)
+ if (!this._needsUpdate) {
return;
+ }
this._resizeCanvas();
this._update();
}
@@ -173,8 +175,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
}
if (selection.layer()) {
const promise = selection.layer().snapshots()[0];
- if (promise)
+ if (promise) {
return promise;
+ }
}
return /** @type {!Promise<?SDK.SnapshotWithRect>} */ (Promise.resolve(null));
}
@@ -185,8 +188,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
*/
_initGL(canvas) {
const gl = canvas.getContext('webgl');
- if (!gl)
+ if (!gl) {
return null;
+ }
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl.clearColor(0.0, 0.0, 0.0, 0.0);
@@ -264,8 +268,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
.translate(-baseWidth / 2, -baseHeight / 2, 0);
let bounds;
- for (let i = 0; i < this._rects.length; ++i)
+ for (let i = 0; i < this._rects.length; ++i) {
bounds = UI.Geometry.boundsForTransformedPoints(scaleAndRotationMatrix, this._rects[i].vertices, bounds);
+ }
this._transformController.clampOffsets(
(paddingX - bounds.maxX) / window.devicePixelRatio,
@@ -324,11 +329,13 @@ LayerViewer.Layers3DView = class extends UI.VBox {
* @return {?WebGLRenderingContext}
*/
_initGLIfNecessary() {
- if (this._gl)
+ if (this._gl) {
return this._gl;
+ }
this._gl = this._initGL(this._canvasElement);
- if (!this._gl)
+ if (!this._gl) {
return null;
+ }
this._initShaders();
this._initWhiteTexture();
this._initChromeTextures();
@@ -348,8 +355,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
this._visibleLayers = new Set();
while (queue.length > 0) {
const layer = queue.shift();
- if (showInternalLayers || layer.drawsContent())
+ if (showInternalLayers || layer.drawsContent()) {
this._visibleLayers.add(layer);
+ }
const children = layer.children();
for (let i = 0; i < children.length; ++i) {
this._depthByLayerId[children[i].id()] = ++depth;
@@ -392,8 +400,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
* @param {!SDK.Layer} layer
*/
_calculateLayerRect(layer) {
- if (!this._visibleLayers.has(layer))
+ if (!this._visibleLayers.has(layer)) {
return;
+ }
const selection = new LayerViewer.LayerView.LayerSelection(layer);
const rect = new LayerViewer.Layers3DView.Rectangle(selection);
rect.setVertices(layer.quad(), this._depthForLayer(layer));
@@ -448,8 +457,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
const tiles = this._textureManager.tilesForLayer(layer);
for (let i = 0; i < tiles.length; ++i) {
const tile = tiles[i];
- if (!tile.texture)
+ if (!tile.texture) {
continue;
+ }
const selection = new LayerViewer.LayerView.SnapshotSelection(layer, {rect: tile.rect, snapshot: tile.snapshot});
const rect = new LayerViewer.Layers3DView.Rectangle(selection);
rect.calculateVerticesFromRect(layer, tile.rect, this._depthForLayer(layer) + 1);
@@ -463,8 +473,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
this._dimensionsForAutoscale = {width: 0, height: 0};
this._layerTree.forEachLayer(this._calculateLayerRect.bind(this));
- if (this._showSlowScrollRectsSetting.get())
+ if (this._showSlowScrollRectsSetting.get()) {
this._layerTree.forEachLayer(this._calculateLayerScrollRects.bind(this));
+ }
if (this._layerTexture && this._visibleLayers.has(this._layerTexture.layer)) {
const layer = this._layerTexture.layer;
@@ -485,8 +496,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
_makeColorsArray(color) {
let colors = [];
const normalizedColor = [color[0] / 255, color[1] / 255, color[2] / 255, color[3]];
- for (let i = 0; i < 4; i++)
+ for (let i = 0; i < 4; i++) {
colors = colors.concat(normalizedColor);
+ }
return colors;
}
@@ -540,8 +552,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
_drawViewportAndChrome() {
const viewport = this._layerTree.viewportSize();
- if (!viewport)
+ if (!viewport) {
return;
+ }
const drawChrome = !Common.moduleSetting('frameViewerHideChromeWindow').get() && this._chromeTextures.length >= 3 &&
this._chromeTextures.indexOf(undefined) < 0;
@@ -552,8 +565,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
this._drawRectangle(
vertices, drawChrome ? this._gl.LINE_STRIP : this._gl.LINE_LOOP, LayerViewer.Layers3DView.ViewportBorderColor);
- if (!drawChrome)
+ if (!drawChrome) {
return;
+ }
const borderAdjustment = LayerViewer.Layers3DView.ViewportBorderWidth / 2;
const viewportWidth = this._layerTree.viewportSize().width + 2 * borderAdjustment;
@@ -565,8 +579,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
for (let i = 0; i < this._chromeTextures.length; ++i) {
const width = i === LayerViewer.Layers3DView.ChromeTexture.Middle ? middleFragmentWidth :
this._chromeTextures[i].image.naturalWidth;
- if (width < 0 || x + width > viewportWidth)
+ if (width < 0 || x + width > viewportWidth) {
break;
+ }
vertices = [x, y, z, x + width, y, z, x + width, y + chromeHeight, z, x, y + chromeHeight, z];
this._drawTexture(vertices, /** @type {!WebGLTexture} */ (this._chromeTextures[i]));
x += width;
@@ -578,13 +593,15 @@ LayerViewer.Layers3DView = class extends UI.VBox {
*/
_drawViewRect(rect) {
const vertices = rect.vertices;
- if (rect.texture)
+ if (rect.texture) {
this._drawTexture(vertices, rect.texture, rect.fillColor || undefined);
- else if (rect.fillColor)
+ } else if (rect.fillColor) {
this._drawRectangle(vertices, this._gl.TRIANGLE_FAN, rect.fillColor);
+ }
this._gl.lineWidth(rect.lineWidth);
- if (rect.borderColor)
+ if (rect.borderColor) {
this._drawRectangle(vertices, this._gl.LINE_LOOP, rect.borderColor);
+ }
}
_update() {
@@ -634,8 +651,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
* @return {?LayerViewer.LayerView.Selection}
*/
_selectionFromEventPoint(event) {
- if (!this._layerTree)
+ if (!this._layerTree) {
return null;
+ }
let closestIntersectionPoint = Infinity;
let closestObject = null;
const projectionMatrix =
@@ -647,8 +665,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
* @param {!LayerViewer.Layers3DView.Rectangle} rect
*/
function checkIntersection(rect) {
- if (!rect.relatedObject)
+ if (!rect.relatedObject) {
return;
+ }
const t = rect.intersectWithLine(projectionMatrix, x0, y0);
if (t < closestIntersectionPoint) {
closestIntersectionPoint = t;
@@ -678,10 +697,10 @@ LayerViewer.Layers3DView = class extends UI.VBox {
_initToolbar() {
this._panelToolbar = this._transformController.toolbar();
this.contentElement.appendChild(this._panelToolbar.element);
- this._showSlowScrollRectsSetting =
- this._createVisibilitySetting('Slow scroll rects', 'frameViewerShowSlowScrollRects', true, this._panelToolbar);
+ this._showSlowScrollRectsSetting = this._createVisibilitySetting(
+ ls`Slow scroll rects`, 'frameViewerShowSlowScrollRects', true, this._panelToolbar);
this._showPaintsSetting =
- this._createVisibilitySetting('Paints', 'frameViewerShowPaints', true, this._panelToolbar);
+ this._createVisibilitySetting(ls`Paints`, 'frameViewerShowPaints', true, this._panelToolbar);
this._showPaintsSetting.addChangeListener(this._updatePaints, this);
Common.moduleSetting('frameViewerHideChromeWindow').addChangeListener(this._update, this);
}
@@ -707,8 +726,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
* @param {!Event} event
*/
_onMouseMove(event) {
- if (event.which)
+ if (event.which) {
return;
+ }
this._layerViewHost.hoverObject(this._selectionFromEventPoint(event));
}
@@ -726,8 +746,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
_onMouseUp(event) {
const maxDistanceInPixels = 6;
if (this._mouseDownX && Math.abs(event.clientX - this._mouseDownX) < maxDistanceInPixels &&
- Math.abs(event.clientY - this._mouseDownY) < maxDistanceInPixels)
+ Math.abs(event.clientY - this._mouseDownY) < maxDistanceInPixels) {
this._layerViewHost.selectObject(this._selectionFromEventPoint(event));
+ }
delete this._mouseDownX;
delete this._mouseDownY;
}
@@ -737,8 +758,9 @@ LayerViewer.Layers3DView = class extends UI.VBox {
*/
_onDoubleClick(event) {
const selection = this._selectionFromEventPoint(event);
- if (selection && (selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot || selection.layer()))
+ if (selection && (selection.type() === LayerViewer.LayerView.Selection.Type.Snapshot || selection.layer())) {
this.dispatchEventToListeners(LayerViewer.Layers3DView.Events.PaintProfilerRequested, selection);
+ }
event.stopPropagation();
}
@@ -870,8 +892,9 @@ LayerViewer.LayerTextureManager = class {
}
reset() {
- if (this._tilesByLayer)
+ if (this._tilesByLayer) {
this.setLayerTree(null);
+ }
/** @type {!Map<!SDK.Layer, !Array<!LayerViewer.LayerTextureManager.Tile>>} */
this._tilesByLayer = new Map();
@@ -884,8 +907,9 @@ LayerViewer.LayerTextureManager = class {
*/
setContext(glContext) {
this._gl = glContext;
- if (this._scale)
+ if (this._scale) {
this._updateTextures();
+ }
}
suspend() {
@@ -894,8 +918,9 @@ LayerViewer.LayerTextureManager = class {
resume() {
this._active = true;
- if (this._queue.length)
+ if (this._queue.length) {
this._update();
+ }
}
/**
@@ -906,8 +931,9 @@ LayerViewer.LayerTextureManager = class {
const oldLayers = Array.from(this._tilesByLayer.keys());
if (layerTree) {
layerTree.forEachLayer(layer => {
- if (!layer.drawsContent())
+ if (!layer.drawsContent()) {
return;
+ }
newLayers.add(layer);
if (!this._tilesByLayer.has(layer)) {
this._tilesByLayer.set(layer, []);
@@ -915,11 +941,13 @@ LayerViewer.LayerTextureManager = class {
}
});
}
- if (!oldLayers.length)
+ if (!oldLayers.length) {
this.forceUpdate();
+ }
for (const layer of oldLayers) {
- if (newLayers.has(layer))
+ if (newLayers.has(layer)) {
continue;
+ }
this._tilesByLayer.get(layer).forEach(tile => tile.dispose());
this._tilesByLayer.delete(layer);
}
@@ -944,10 +972,12 @@ LayerViewer.LayerTextureManager = class {
}
}
this._tilesByLayer.set(layer, reusedTiles.concat(newTiles));
- for (const tile of oldSnapshotsToTiles.values())
+ for (const tile of oldSnapshotsToTiles.values()) {
tile.dispose();
- if (!this._gl || !this._scale)
+ }
+ if (!this._gl || !this._scale) {
return Promise.resolve();
+ }
return Promise.all(newTiles.map(tile => tile.update(this._gl, this._scale))).then(this._textureUpdatedCallback);
}
@@ -955,8 +985,9 @@ LayerViewer.LayerTextureManager = class {
* @param {number} scale
*/
setScale(scale) {
- if (this._scale && this._scale >= scale)
+ if (this._scale && this._scale >= scale) {
return;
+ }
this._scale = scale;
this._updateTextures();
}
@@ -973,10 +1004,12 @@ LayerViewer.LayerTextureManager = class {
* @param {!SDK.Layer} layer
*/
layerNeedsUpdate(layer) {
- if (this._queue.indexOf(layer) < 0)
+ if (this._queue.indexOf(layer) < 0) {
this._queue.push(layer);
- if (this._active)
+ }
+ if (this._active) {
this._throttler.schedule(this._update.bind(this));
+ }
}
forceUpdate() {
@@ -990,10 +1023,12 @@ LayerViewer.LayerTextureManager = class {
*/
_update() {
const layer = this._queue.shift();
- if (!layer)
+ if (!layer) {
return Promise.resolve();
- if (this._queue.length)
+ }
+ if (this._queue.length) {
this._throttler.schedule(this._update.bind(this));
+ }
return this._updateLayer(layer);
}
@@ -1007,16 +1042,19 @@ LayerViewer.LayerTextureManager = class {
}
_updateTextures() {
- if (!this._gl)
+ if (!this._gl) {
return;
- if (!this._scale)
+ }
+ if (!this._scale) {
return;
+ }
for (const tiles of this._tilesByLayer.values()) {
for (const tile of tiles) {
const promise = tile.updateScale(this._gl, this._scale);
- if (promise)
+ if (promise) {
promise.then(this._textureUpdatedCallback);
+ }
}
}
}
@@ -1129,8 +1167,9 @@ LayerViewer.Layers3DView.Rectangle = class {
for (i = 0; i < tVects.length; ++i) {
const product =
UI.Geometry.scalarProduct(normal, UI.Geometry.crossProduct(tVects[i], tVects[(i + 1) % tVects.length]));
- if (product < 0)
+ if (product < 0) {
return undefined;
+ }
}
return t;
}
@@ -1166,8 +1205,9 @@ LayerViewer.LayerTextureManager.Tile = class {
* @return {?Promise}
*/
updateScale(glContext, scale) {
- if (this.texture && this.scale >= scale)
+ if (this.texture && this.scale >= scale) {
return null;
+ }
return this.update(glContext, scale);
}
@@ -1180,7 +1220,7 @@ LayerViewer.LayerTextureManager.Tile = class {
this._gl = glContext;
this.scale = scale;
const imageURL = await this.snapshot.replay(scale);
- const image = imageURL && await UI.loadImage(imageURL);
- this.texture = image && LayerViewer.LayerTextureManager._createTextureForImage(glContext, image);
+ const image = imageURL ? await UI.loadImage(imageURL) : null;
+ this.texture = image ? LayerViewer.LayerTextureManager._createTextureForImage(glContext, image) : null;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/PaintProfilerView.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/PaintProfilerView.js
index 9d8c610559b..62e7a2696de 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/PaintProfilerView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/PaintProfilerView.js
@@ -68,8 +68,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
* @return {!Object.<string, !LayerViewer.PaintProfilerCategory>}
*/
static categories() {
- if (LayerViewer.PaintProfilerView._categories)
+ if (LayerViewer.PaintProfilerView._categories) {
return LayerViewer.PaintProfilerView._categories;
+ }
LayerViewer.PaintProfilerView._categories = {
shapes: new LayerViewer.PaintProfilerCategory('shapes', Common.UIString('Shapes'), 'rgb(255, 161, 129)'),
bitmap: new LayerViewer.PaintProfilerCategory('bitmap', Common.UIString('Bitmap'), 'rgb(136, 196, 255)'),
@@ -83,8 +84,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
* @return {!Object.<string, !LayerViewer.PaintProfilerCategory>}
*/
static _initLogItemCategories() {
- if (LayerViewer.PaintProfilerView._logItemCategoriesMap)
+ if (LayerViewer.PaintProfilerView._logItemCategoriesMap) {
return LayerViewer.PaintProfilerView._logItemCategoriesMap;
+ }
const categories = LayerViewer.PaintProfilerView.categories();
@@ -161,8 +163,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
async setSnapshotAndLog(snapshot, log, clipRect) {
this._reset();
this._snapshot = snapshot;
- if (this._snapshot)
+ if (this._snapshot) {
this._snapshot.addReference();
+ }
this._log = log;
this._logCategories = this._log.map(LayerViewer.PaintProfilerView._categoryForLogItem);
@@ -191,16 +194,18 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
const needsUpdate = scale > this._scale;
const predictiveGrowthFactor = 2;
this._pendingScale = Math.min(1, scale * predictiveGrowthFactor);
- if (needsUpdate && this._snapshot)
+ if (needsUpdate && this._snapshot) {
this._updateImage();
+ }
}
_update() {
this._canvas.width = this._canvasContainer.clientWidth * window.devicePixelRatio;
this._canvas.height = this._canvasContainer.clientHeight * window.devicePixelRatio;
this._samplesPerBar = 0;
- if (!this._profiles || !this._profiles.length)
+ if (!this._profiles || !this._profiles.length) {
return;
+ }
const maxBars = Math.floor((this._canvas.width - 2 * this._barPaddingWidth) / this._outerBarWidth);
const sampleCount = this._log.length;
@@ -223,14 +228,16 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
// Normalize by total number of samples accumulated.
const factor = this._profiles.length * (i - lastBarIndex);
lastBarTime /= factor;
- for (categoryName in heightByCategory)
+ for (categoryName in heightByCategory) {
heightByCategory[categoryName] /= factor;
+ }
barTimes.push(lastBarTime);
barHeightByCategory.push(heightByCategory);
- if (lastBarTime > maxBarTime)
+ if (lastBarTime > maxBarTime) {
maxBarTime = lastBarTime;
+ }
lastBarTime = 0;
heightByCategory = {};
lastBarIndex = i;
@@ -240,8 +247,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
const paddingHeight = 4 * window.devicePixelRatio;
const scale = (this._canvas.height - paddingHeight - this._minBarHeight) / maxBarTime;
for (let i = 0; i < barTimes.length; ++i) {
- for (const categoryName in barHeightByCategory[i])
+ for (const categoryName in barHeightByCategory[i]) {
barHeightByCategory[i][categoryName] *= (barTimes[i] * scale + this._minBarHeight) / barTimes[i];
+ }
this._renderBar(i, barHeightByCategory[i]);
}
}
@@ -255,8 +263,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
let currentHeight = 0;
const x = this._barPaddingWidth + index * this._outerBarWidth;
for (const categoryName in categories) {
- if (!heightByCategory[categoryName])
+ if (!heightByCategory[categoryName]) {
continue;
+ }
currentHeight += heightByCategory[categoryName];
const y = this._canvas.height - currentHeight;
this._context.fillStyle = categories[categoryName].color;
@@ -267,15 +276,17 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
_onWindowChanged() {
this.dispatchEventToListeners(LayerViewer.PaintProfilerView.Events.WindowChanged);
this._updatePieChart();
- if (this._updateImageTimer)
+ if (this._updateImageTimer) {
return;
+ }
this._updateImageTimer = setTimeout(this._updateImage.bind(this), 100);
}
_updatePieChart() {
const window = this.selectionWindow();
- if (!this._profiles || !this._profiles.length || !window)
+ if (!this._profiles || !this._profiles.length || !window) {
return;
+ }
let totalTime = 0;
const timeByCategory = {};
for (let i = window.left; i < window.right; ++i) {
@@ -289,8 +300,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
}
}
this._pieChart.setTotal(totalTime / this._profiles.length);
- for (const color in timeByCategory)
+ for (const color in timeByCategory) {
this._pieChart.addSlice(timeByCategory[color] / this._profiles.length, color);
+ }
}
/**
@@ -305,8 +317,9 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
* @return {?{left: number, right: number}}
*/
selectionWindow() {
- if (!this._log)
+ if (!this._log) {
return null;
+ }
const screenLeft = this._selectionWindow.windowLeft * this._canvas.width;
const screenRight = this._selectionWindow.windowRight * this._canvas.width;
@@ -329,16 +342,18 @@ LayerViewer.PaintProfilerView = class extends UI.HBox {
}
const scale = this._pendingScale;
this._snapshot.replay(scale, left, right).then(image => {
- if (!image)
+ if (!image) {
return;
+ }
this._scale = scale;
this._showImageCallback(image);
});
}
_reset() {
- if (this._snapshot)
+ if (this._snapshot) {
this._snapshot.release();
+ }
this._snapshot = null;
this._profiles = null;
this._selectionWindow.reset();
@@ -410,18 +425,21 @@ LayerViewer.PaintProfilerCommandLogView = class extends UI.ThrottledWidget {
const root = this._treeOutline.rootElement();
for (;;) {
const child = root.firstChild();
- if (!child || child._logItem.commandIndex >= this._selectionWindow.left)
+ if (!child || child._logItem.commandIndex >= this._selectionWindow.left) {
break;
+ }
root.removeChildAtIndex(0);
}
for (;;) {
const child = root.lastChild();
- if (!child || child._logItem.commandIndex < this._selectionWindow.right)
+ if (!child || child._logItem.commandIndex < this._selectionWindow.right) {
break;
+ }
root.removeChildAtIndex(root.children().length - 1);
}
- for (let i = this._selectionWindow.left, right = this._selectionWindow.right; i < right; ++i)
+ for (let i = this._selectionWindow.left, right = this._selectionWindow.right; i < right; ++i) {
this._appendLogItem(this._log[i]);
+ }
return Promise.resolve();
}
};
@@ -453,8 +471,9 @@ LayerViewer.LogTreeElement = class extends UI.TreeElement {
* @returns {!Promise}
*/
async onpopulate() {
- for (const param in this._logItem.params)
+ for (const param in this._logItem.params) {
LayerViewer.LogPropertyTreeElement._appendLogPropertyItem(this, param, this._logItem.params[param]);
+ }
}
/**
@@ -463,16 +482,19 @@ LayerViewer.LogTreeElement = class extends UI.TreeElement {
* @return {string}
*/
_paramToString(param, name) {
- if (typeof param !== 'object')
+ if (typeof param !== 'object') {
return typeof param === 'string' && param.length > 100 ? name : JSON.stringify(param);
+ }
let str = '';
let keyCount = 0;
for (const key in param) {
if (++keyCount > 4 || typeof param[key] === 'object' ||
- (typeof param[key] === 'string' && param[key].length > 100))
+ (typeof param[key] === 'string' && param[key].length > 100)) {
return name;
- if (str)
+ }
+ if (str) {
str += ', ';
+ }
str += param[key];
}
return str;
@@ -485,8 +507,9 @@ LayerViewer.LogTreeElement = class extends UI.TreeElement {
_paramsToString(params) {
let str = '';
for (const key in params) {
- if (str)
+ if (str) {
str += ', ';
+ }
str += this._paramToString(params[key], key);
}
return str;
@@ -520,8 +543,9 @@ LayerViewer.LogPropertyTreeElement = class extends UI.TreeElement {
const treeElement = new LayerViewer.LogPropertyTreeElement({name: name, value: value});
element.appendChild(treeElement);
if (value && typeof value === 'object') {
- for (const property in value)
+ for (const property in value) {
LayerViewer.LogPropertyTreeElement._appendLogPropertyItem(treeElement, property, value[property]);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/TransformController.js b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/TransformController.js
index a63494b74f5..8a04f6b7bfc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/TransformController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/TransformController.js
@@ -16,8 +16,9 @@ LayerViewer.TransformController = class extends Common.Object {
super();
this._shortcuts = {};
this.element = element;
- if (this.element.tabIndex < 0)
+ if (this.element.tabIndex < 0) {
this.element.tabIndex = 0;
+ }
this._registerShortcuts();
UI.installDragHandle(
element, this._onDragStart.bind(this), this._onDrag.bind(this), this._onDragEnd.bind(this), 'move', null);
@@ -67,18 +68,21 @@ LayerViewer.TransformController = class extends Common.Object {
const shortcutKey = UI.KeyboardShortcut.makeKeyFromEventIgnoringModifiers(event);
const handler = this._shortcuts[shortcutKey];
- if (handler && handler(event))
+ if (handler && handler(event)) {
event.consume();
+ }
}
_onKeyUp(event) {
- if (event.keyCode === UI.KeyboardShortcut.Keys.Shift.code)
+ if (event.keyCode === UI.KeyboardShortcut.Keys.Shift.code) {
this._toggleMode();
+ }
}
_addShortcuts(keys, handler) {
- for (let i = 0; i < keys.length; ++i)
+ for (let i = 0; i < keys.length; ++i) {
this._shortcuts[keys[i].key] = handler;
+ }
}
_registerShortcuts() {
@@ -121,16 +125,18 @@ LayerViewer.TransformController = class extends Common.Object {
* @param {!LayerViewer.TransformController.Modes} mode
*/
_setMode(mode) {
- if (this._mode === mode)
+ if (this._mode === mode) {
return;
+ }
this._mode = mode;
this._updateModeButtons();
this.element.focus();
}
_updateModeButtons() {
- for (const mode in this._modeButtons)
+ for (const mode in this._modeButtons) {
this._modeButtons[mode].setToggled(mode === this._mode);
+ }
}
/**
@@ -139,8 +145,9 @@ LayerViewer.TransformController = class extends Common.Object {
resetAndNotify(event) {
this._reset();
this._postChangeEvent();
- if (event)
+ if (event) {
event.preventDefault();
+ }
this.element.focus();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
index 33d1cdc6b03..b110d59cd08 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layer_viewer/layer_viewer_strings.grdp
@@ -1,56 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_05245b74ad79bb210a68107f7de0c27f" desc="Text in Layer Details View of the Layers panel">
- Layer for scrolling container.
- </message>
- <message name="IDS_DEVTOOLS_08415c56f6c6c2efb0218629836e31bc" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a &quot;backface-visibility: hidden&quot; style.
- </message>
- <message name="IDS_DEVTOOLS_0aa3ae694efd06789ae1867c80d30222" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a &quot;position: fixed&quot; or &quot;position: sticky&quot; style.
- </message>
<message name="IDS_DEVTOOLS_0b4eb322e51b61340668247151340346" desc="Tooltip text that appears when hovering over largeicon rotate button in Transform Controller of the Layers panel">
Rotate mode (V)
</message>
- <message name="IDS_DEVTOOLS_0dd70cbbb618cf0ea39d7e01238ca1b9" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an animated element.
- </message>
- <message name="IDS_DEVTOOLS_135d78fcc62ff8df8028c33c768900c5" desc="Text in Layer Details View of the Layers panel">
- Layer for background.
- </message>
<message name="IDS_DEVTOOLS_219e2fb2d37a581ab2bae57397b601f1" desc="Text in Layer Details View of the Layers panel">
&lt;unnamed&gt;
</message>
- <message name="IDS_DEVTOOLS_233612553595af00e5d227e136252422" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with composited descendants.
- </message>
<message name="IDS_DEVTOOLS_25d066be1268d5c07cae5cc26e06ad2b" desc="Text in Layer Details View of the Layers panel">
Slow scroll regions
</message>
- <message name="IDS_DEVTOOLS_28b5b4891eb05cc50f537526b24038a9" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with a masked element and composited descendants.
- </message>
- <message name="IDS_DEVTOOLS_2a2924d1d77c00d27ce2509c34861804" desc="Text in Layer Details View of the Layers panel">
- Layer for clip.
- </message>
- <message name="IDS_DEVTOOLS_2ae207ddfe5cd256a768769d93a879e5" desc="Paint profiler button text content in Layer Details View of the Layers panel">
- Paint Profiler
- </message>
- <message name="IDS_DEVTOOLS_2ca2308d45c04266f0fb51786e407287" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with CSS filters applied and composited descendants.
- </message>
<message name="IDS_DEVTOOLS_3228417bf9ed949e7447e7c8dcb17090" desc="Text in Layer Details View of the Layers panel">
Memory estimate
</message>
- <message name="IDS_DEVTOOLS_37de7295335e95cb7caf78303a1edad3" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a CSS 3D transform.
- </message>
- <message name="IDS_DEVTOOLS_398b889c147f3b2cb3c674cfb07315b5" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with opacity applied and composited descendants.
- </message>
- <message name="IDS_DEVTOOLS_3f03ed88ee58335aa3df453443b9c8bc" desc="Progress banner text content in Paint Profiler View of the Layers panel">
- Profiling…
- </message>
<message name="IDS_DEVTOOLS_441f5e043a240bac8dca50f90f7be3de" desc="Text in DView of the Layers panel">
repaints on scroll
</message>
@@ -72,18 +33,12 @@
<message name="IDS_DEVTOOLS_4ee55709b19d806bb2f83a264a8a0f75" desc="Sticky box rect element text content in Layer Details View of the Layers panel">
Sticky Box <ph name="STICKYBOXRECT_WIDTH">$1d<ex>10</ex></ph> × <ph name="STICKYBOXRECT_HEIGHT">$2d<ex>10</ex></ph> (at <ph name="STICKYBOXRECT_X">$3d<ex>10</ex></ph>, <ph name="STICKYBOXRECT_Y">$4d<ex>10</ex></ph>)
</message>
- <message name="IDS_DEVTOOLS_5337a3314b26561ccf364e1777455933" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with a &lt;video&gt; element.
- </message>
<message name="IDS_DEVTOOLS_5639e2813d9549835010567a48349127" desc="Details text content in Layer Tree Outline of the Layers panel">
''' (<ph name="THIS__LAYER_WIDTH__">$1d<ex>10</ex></ph> × <ph name="THIS__LAYER_HEIGHT__">$2d<ex>10</ex></ph>)
</message>
<message name="IDS_DEVTOOLS_602f4c0713480f019b24f09218dcc7e0" desc="A context menu item in the DView of the Layers panel">
Reset View
</message>
- <message name="IDS_DEVTOOLS_697e0fb75c6cf44734697517d44b5922" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element clipping compositing descendants.
- </message>
<message name="IDS_DEVTOOLS_6fac3a4381f0fb07bbf498a08d301d40" desc="Text in Layer Details View of the Layers panel">
Repaints on scroll
</message>
@@ -96,21 +51,12 @@
<message name="IDS_DEVTOOLS_71084df87a4cc161f7542a0f5295a950" desc="Text in Layer Details View of the Layers panel">
Select a layer to see its details
</message>
- <message name="IDS_DEVTOOLS_73c57dbc070bac535d75b4abe9f614a3" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element overlapping other composited elements.
- </message>
<message name="IDS_DEVTOOLS_74248c725e00bf9fe04df4e35b249a19" desc="Text in Paint Profiler View of the Layers panel">
Misc
</message>
<message name="IDS_DEVTOOLS_74ae7b35b54cd38a932ccc4f1d1c3775" desc="Text in Layer Details View of the Layers panel">
Touch event handler
</message>
- <message name="IDS_DEVTOOLS_791faaf55ae39199cc0b4edde837f07a" desc="Text in Layer Details View of the Layers panel">
- Layer for video overlay.
- </message>
- <message name="IDS_DEVTOOLS_7eb830853b9ed22a567e4d7582eafe7c" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with CSS filters applied.
- </message>
<message name="IDS_DEVTOOLS_82505980aa6b0cabf4cb8013a8a43b62" desc="Text in Layer Details View of the Layers panel">
Non fast scrollable
</message>
@@ -120,33 +66,15 @@
<message name="IDS_DEVTOOLS_86ee74baff479d85d18f2cda9f8a9518" desc="Text in Paint Profiler View of the Layers panel">
Bitmap
</message>
- <message name="IDS_DEVTOOLS_8810c4e0c498b81a6e4adaeabcb9f624" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a &quot;overflow-scrolling: touch&quot; style.
- </message>
- <message name="IDS_DEVTOOLS_894982f4a3bc0e770cece61dd12dde55" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an &lt;iframe&gt; element.
- </message>
<message name="IDS_DEVTOOLS_932a3ef55ce8133be7b33ded2992fd97" desc="Text in Layer Details View of the Layers panel">
Compositing Reasons
</message>
- <message name="IDS_DEVTOOLS_93c3341232864688bcea4d53dff1bf10" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with perspective applied.
- </message>
- <message name="IDS_DEVTOOLS_991bd14abd9e6004de4e7b9bc0769d9d" desc="Text in Layer Details View of the Layers panel">
- Layer for foreground.
- </message>
<message name="IDS_DEVTOOLS_9b8379825de60ccb900acf83934e1409" desc="Text in Layer View Host of the Layers panel">
Show internal layers
</message>
- <message name="IDS_DEVTOOLS_9dffbf69ffba8bc38bc4e01abf4b1675" desc="Text in Paint Profiler View of the Layers panel">
- Text
- </message>
<message name="IDS_DEVTOOLS_a673813c8d6c5f511cc4d80830fc4503" desc="Text in DView of the Layers panel">
Can&apos;t display layers,
</message>
- <message name="IDS_DEVTOOLS_aefd09cd861bbb01d381cfd74856e877" desc="Text in Layer Details View of the Layers panel">
- Composition due to the element being a &lt;canvas&gt; element.
- </message>
<message name="IDS_DEVTOOLS_b336b2cbaa7391e6e0dfef888d35a837" desc="Text in DView of the Layers panel">
touch event listener
</message>
@@ -171,21 +99,6 @@
<message name="IDS_DEVTOOLS_ce1efcf7f040106cc8cb2f24c9efee35" desc="A context menu item in the DView of the Layers panel">
Show Paint Profiler
</message>
- <message name="IDS_DEVTOOLS_cf4db365a841e7208aad0d474cbfa8e3" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with descendants that have a negative z-index.
- </message>
- <message name="IDS_DEVTOOLS_d446f65fe70f9a640908576792497e25" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a reflection and composited descendants.
- </message>
- <message name="IDS_DEVTOOLS_dd4d335a4deb975546acc9fb5aa3ffce" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element that may overlap other composited elements.
- </message>
- <message name="IDS_DEVTOOLS_dff689f21faf977ee865e312c011c84a" desc="Text in Layer Details View of the Layers panel">
- Root layer.
- </message>
- <message name="IDS_DEVTOOLS_e397c87a940fc2c10225a407c7f124a7" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with a plugin.
- </message>
<message name="IDS_DEVTOOLS_e763043c4af617c6f33da361d990a77b" desc="Tooltip text that appears when hovering over the largeicon center button in the Transform Controller of the Layers panel">
Reset transform (0)
</message>
@@ -195,19 +108,10 @@
<message name="IDS_DEVTOOLS_ed3a481889f16ef0aab2349f5d8b5f12" desc="Containing block rect element text content in Layer Details View of the Layers panel">
Containing Block <ph name="CONTAININGBLOCKRECT_WIDTH">$1d<ex>10</ex></ph> × <ph name="CONTAININGBLOCKRECT_HEIGHT">$2d<ex>10</ex></ph> (at <ph name="CONTAININGBLOCKRECT_X">$3d<ex>10</ex></ph>, <ph name="CONTAININGBLOCKRECT_Y">$4d<ex>10</ex></ph>)
</message>
- <message name="IDS_DEVTOOLS_f1eb415fdb8a15856c29cc2b679e416b" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with a &quot;transform-style: preserve-3d&quot; style.
- </message>
- <message name="IDS_DEVTOOLS_f2a4f55a424726ae504f2e694e3dc2a2" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element with CSS blending applied and composited descendants.
- </message>
- <message name="IDS_DEVTOOLS_fa055d01c0a331d642c2f55a39d4e1bb" desc="Text in Layer Details View of the Layers panel">
- Composition due to association with an element that has blend mode other than &quot;normal&quot;.
- </message>
- <message name="IDS_DEVTOOLS_fb8ed4e0cd9d6ac3630df425c80d9036" desc="Text in Layer Details View of the Layers panel">
- Layer for mask.
+ <message name="IDS_DEVTOOLS_a3ed19b48390aad906de764e0476142d" desc="Text for a checkbox in the toolbar of the Layers panel to show the paints of the page">
+ Paints
</message>
- <message name="IDS_DEVTOOLS_fd63c694ddc8073cf10bb8025aa9aaaf" desc="Text in Layer Details View of the Layers panel">
- Layer for scrollbar.
+ <message name="IDS_DEVTOOLS_4f6faa156251f75fbefe3270d94a7a28" desc="Text for a checkbox in the toolbar of the Layers panel to show the area of slow scroll rect">
+ Slow scroll rects
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerPaintProfilerView.js b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerPaintProfilerView.js
index 629ff48c445..23409eb59cc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerPaintProfilerView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerPaintProfilerView.js
@@ -36,8 +36,9 @@ Layers.LayerPaintProfilerView = class extends UI.SplitWidget {
function setSnapshotAndLog(snapshot, log) {
this._logTreeView.setCommandLog(log || []);
this._paintProfilerView.setSnapshotAndLog(snapshot, log || [], null);
- if (snapshot)
+ if (snapshot) {
snapshot.release();
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerTreeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerTreeModel.js
index db9d6e18f24..e222218c556 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerTreeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayerTreeModel.js
@@ -48,23 +48,26 @@ Layers.LayerTreeModel = class extends SDK.SDKModel {
}
disable() {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
this._enabled = false;
this._layerTreeAgent.disable();
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._enabled = true;
this._forceEnable();
}
_forceEnable() {
this._lastPaintRectByLayerId = {};
- if (!this._layerTree)
+ if (!this._layerTree) {
this._layerTree = new Layers.AgentLayerTree(this);
+ }
this._layerTreeAgent.enable();
}
@@ -79,8 +82,9 @@ Layers.LayerTreeModel = class extends SDK.SDKModel {
* @param {?Array.<!Protocol.LayerTree.Layer>} layers
*/
async _layerTreeChanged(layers) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
this._throttler.schedule(this._innerSetLayers.bind(this, layers));
}
@@ -95,8 +99,9 @@ Layers.LayerTreeModel = class extends SDK.SDKModel {
for (const layerId in this._lastPaintRectByLayerId) {
const lastPaintRect = this._lastPaintRectByLayerId[layerId];
const layer = layerTree.layerById(layerId);
- if (layer)
- layer._lastPaintRect = lastPaintRect;
+ if (layer) {
+ /** @type {!Layers.AgentLayer} */ (layer)._lastPaintRect = lastPaintRect;
+ }
}
this._lastPaintRectByLayerId = {};
@@ -108,10 +113,11 @@ Layers.LayerTreeModel = class extends SDK.SDKModel {
* @param {!Protocol.DOM.Rect} clipRect
*/
_layerPainted(layerId, clipRect) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
const layerTree = /** @type {!Layers.AgentLayerTree} */ (this._layerTree);
- const layer = layerTree.layerById(layerId);
+ const layer = /** @type {!Layers.AgentLayer} */ (layerTree.layerById(layerId));
if (!layer) {
this._lastPaintRectByLayerId[layerId] = clipRect;
return;
@@ -122,8 +128,9 @@ Layers.LayerTreeModel = class extends SDK.SDKModel {
_onMainFrameNavigated() {
this._layerTree = null;
- if (this._enabled)
+ if (this._enabled) {
this._forceEnable();
+ }
}
};
@@ -159,8 +166,9 @@ Layers.AgentLayerTree = class extends SDK.LayerTreeBase {
const idsToResolve = new Set();
for (let i = 0; i < payload.length; ++i) {
const backendNodeId = payload[i].backendNodeId;
- if (!backendNodeId || this.backendNodeIdToNode().has(backendNodeId))
+ if (!backendNodeId || this.backendNodeIdToNode().has(backendNodeId)) {
continue;
+ }
idsToResolve.add(backendNodeId);
}
await this.resolveBackendNodeIds(idsToResolve);
@@ -174,33 +182,39 @@ Layers.AgentLayerTree = class extends SDK.LayerTreeBase {
this.setRoot(null);
this.setContentRoot(null);
// Payload will be null when not in the composited mode.
- if (!layers)
+ if (!layers) {
return;
+ }
let root;
const oldLayersById = this._layersById;
this._layersById = {};
for (let i = 0; i < layers.length; ++i) {
const layerId = layers[i].layerId;
let layer = oldLayersById[layerId];
- if (layer)
+ if (layer) {
layer._reset(layers[i]);
- else
+ } else {
layer = new Layers.AgentLayer(this._layerTreeModel, layers[i]);
+ }
this._layersById[layerId] = layer;
const backendNodeId = layers[i].backendNodeId;
- if (backendNodeId)
+ if (backendNodeId) {
layer._setNode(this.backendNodeIdToNode().get(backendNodeId));
- if (!this.contentRoot() && layer.drawsContent())
+ }
+ if (!this.contentRoot() && layer.drawsContent()) {
this.setContentRoot(layer);
+ }
const parentId = layer.parentId();
if (parentId) {
const parent = this._layersById[parentId];
- if (!parent)
+ if (!parent) {
console.assert(parent, 'missing parent ' + parentId + ' for layer ' + layerId);
+ }
parent.addChild(layer);
} else {
- if (root)
+ if (root) {
console.assert(false, 'Multiple root layers');
+ }
root = layer;
}
}
@@ -267,11 +281,13 @@ Layers.AgentLayer = class {
/**
* @override
- * @param {!SDK.Layer} child
+ * @param {!SDK.Layer} childParam
*/
- addChild(child) {
- if (child._parent)
+ addChild(childParam) {
+ const child = /** @type {!Layers.AgentLayer} */ (childParam);
+ if (child._parent) {
console.assert(false, 'Child already has a parent');
+ }
this._children.push(child);
child._parent = this;
}
@@ -297,8 +313,9 @@ Layers.AgentLayer = class {
*/
nodeForSelfOrAncestor() {
for (let layer = this; layer; layer = layer._parent) {
- if (layer._node)
+ if (layer._node) {
return layer._node;
+ }
}
return null;
}
@@ -438,8 +455,9 @@ Layers.AgentLayer = class {
*/
snapshots() {
const promise = this._layerTreeModel._paintProfilerModel.makeSnapshot(this.id()).then(snapshot => {
- if (!snapshot)
+ if (!snapshot) {
return null;
+ }
return {rect: {x: 0, y: 0, width: this.width(), height: this.height()}, snapshot: snapshot};
});
return [promise];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayersPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayersPanel.js
index 413c0e049be..c40ea5c82d7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layers/LayersPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layers/LayersPanel.js
@@ -79,16 +79,18 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
*/
wasShown() {
super.wasShown();
- if (this._model)
+ if (this._model) {
this._model.enable();
+ }
}
/**
* @override
*/
willHide() {
- if (this._model)
+ if (this._model) {
this._model.disable();
+ }
super.willHide();
}
@@ -97,15 +99,18 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
* @param {!SDK.Target} target
*/
targetAdded(target) {
- if (this._model)
+ if (this._model) {
return;
+ }
this._model = target.model(Layers.LayerTreeModel);
- if (!this._model)
+ if (!this._model) {
return;
+ }
this._model.addEventListener(Layers.LayerTreeModel.Events.LayerTreeChanged, this._onLayerTreeUpdated, this);
this._model.addEventListener(Layers.LayerTreeModel.Events.LayerPainted, this._onLayerPainted, this);
- if (this.isShowing())
+ if (this.isShowing()) {
this._model.enable();
+ }
}
/**
@@ -113,8 +118,9 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
* @param {!SDK.Target} target
*/
targetRemoved(target) {
- if (!this._model || this._model.target() !== target)
+ if (!this._model || this._model.target() !== target) {
return;
+ }
this._model.removeEventListener(Layers.LayerTreeModel.Events.LayerTreeChanged, this._onLayerTreeUpdated, this);
this._model.removeEventListener(Layers.LayerTreeModel.Events.LayerPainted, this._onLayerPainted, this);
this._model.disable();
@@ -129,8 +135,9 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
* @return {!Promise<*>}
*/
_update() {
- if (this._model)
+ if (this._model) {
this._layerViewHost.setLayerTree(this._model.layerTree());
+ }
return Promise.resolve();
}
@@ -138,11 +145,13 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
* @param {!Common.Event} event
*/
_onLayerPainted(event) {
- if (!this._model)
+ if (!this._model) {
return;
+ }
const layer = /** @type {!SDK.Layer} */ (event.data);
- if (this._layerViewHost.selection() && this._layerViewHost.selection().layer() === layer)
+ if (this._layerViewHost.selection() && this._layerViewHost.selection().layer() === layer) {
this._layerDetailsView.update();
+ }
this._layers3DView.updateLayerSnapshot(layer);
}
@@ -152,8 +161,9 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
_onPaintProfileRequested(event) {
const selection = /** @type {!LayerViewer.LayerView.Selection} */ (event.data);
this._layers3DView.snapshotForSelection(selection).then(snapshotWithRect => {
- if (!snapshotWithRect)
+ if (!snapshotWithRect) {
return;
+ }
this._layerBeingProfiled = selection.layer();
if (!this._tabbedPane.hasTab(Layers.LayersPanel.DetailsViewTabs.Profiler)) {
this._tabbedPane.appendTab(
@@ -169,8 +179,9 @@ Layers.LayersPanel = class extends UI.PanelWithSidebar {
* @param {!Common.Event} event
*/
_onTabClosed(event) {
- if (event.data.tabId !== Layers.LayersPanel.DetailsViewTabs.Profiler || !this._layerBeingProfiled)
+ if (event.data.tabId !== Layers.LayersPanel.DetailsViewTabs.Profiler || !this._layerBeingProfiled) {
return;
+ }
this._paintProfilerView.reset();
this._layers3DView.showImageForLayer(this._layerBeingProfiled, undefined);
this._layerBeingProfiled = null;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
index 47b7838518e..3e09477206b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layers/layers_strings.grdp
@@ -1,9 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_3ec365dd533ddb7ef3d1c111186ce872" desc="Text in Layers Panel of the Layers panel">
- Details
- </message>
- <message name="IDS_DEVTOOLS_87bfda183c4f851a101e97bbb1bbace7" desc="Title of the 'Layers' tool">
- Layers
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/layers_test_runner/LayersTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/layers_test_runner/LayersTestRunner.js
index 20e51c3df12..31d6039d415 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/layers_test_runner/LayersTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/layers_test_runner/LayersTestRunner.js
@@ -8,8 +8,9 @@
*/
LayersTestRunner.layerTreeModel = function() {
- if (!LayersTestRunner._layerTreeModel)
+ if (!LayersTestRunner._layerTreeModel) {
LayersTestRunner._layerTreeModel = TestRunner.mainTarget.model(Layers.LayerTreeModel);
+ }
return LayersTestRunner._layerTreeModel;
};
@@ -20,18 +21,21 @@ LayersTestRunner.labelForLayer = function(layer) {
const height = layer.height();
const width = layer.width();
- if (height <= 200 && width <= 200)
+ if (height <= 200 && width <= 200) {
label += ' ' + height + 'x' + width;
+ }
- if (typeof layer.__extraData !== 'undefined')
+ if (typeof layer.__extraData !== 'undefined') {
label += ' (' + layer.__extraData + ')';
+ }
return label;
};
LayersTestRunner.dumpLayerTree = function(prefix, root) {
- if (!prefix)
+ if (!prefix) {
prefix = '';
+ }
if (!root) {
root = LayersTestRunner.layerTreeModel().layerTree().contentRoot();
@@ -48,17 +52,21 @@ LayersTestRunner.dumpLayerTree = function(prefix, root) {
};
LayersTestRunner.dumpLayers3DView = function(prefix, root) {
- if (!prefix)
+ if (!prefix) {
prefix = '';
+ }
- if (!root)
+ if (!root) {
root = UI.panels.layers._layers3DView._rotatingContainerElement;
+ }
- if (root.__layer)
+ if (root.__layer) {
TestRunner.addResult(prefix + LayersTestRunner.labelForLayer(root.__layer));
+ }
- for (let element = root.firstElementChild; element; element = element.nextSibling)
+ for (let element = root.firstElementChild; element; element = element.nextSibling) {
LayersTestRunner.dumpLayers3DView(prefix + ' ', element);
+ }
};
LayersTestRunner.evaluateAndWaitForTreeChange = async function(expression) {
@@ -72,11 +80,13 @@ LayersTestRunner.findLayerByNodeIdAttribute = function(nodeIdAttribute) {
function testLayer(layer) {
const node = layer.node();
- if (!node)
+ if (!node) {
return false;
+ }
- if (!node || node.getAttribute('id') !== nodeIdAttribute)
+ if (!node || node.getAttribute('id') !== nodeIdAttribute) {
return false;
+ }
result = layer;
return true;
@@ -84,8 +94,9 @@ LayersTestRunner.findLayerByNodeIdAttribute = function(nodeIdAttribute) {
LayersTestRunner.layerTreeModel().layerTree().forEachLayer(testLayer);
- if (!result)
+ if (!result) {
TestRunner.addResult('ERROR: No layer for ' + nodeIdAttribute);
+ }
return result;
};
@@ -134,10 +145,12 @@ LayersTestRunner.dispatchMouseEventToLayerTree = function(eventType, button, lay
LayersTestRunner.dumpSelectedStyles = function(message, element) {
const classes = [];
- if (element.classList.contains('selected'))
+ if (element.classList.contains('selected')) {
classes.push('selected');
- if (element.classList.contains('hovered'))
+ }
+ if (element.classList.contains('hovered')) {
classes.push('hovered');
+ }
TestRunner.addResult(message + ': ' + classes.join(', '));
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/main/ExecutionContextSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/main/ExecutionContextSelector.js
index 30e04f1af74..18547477869 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/main/ExecutionContextSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/main/ExecutionContextSelector.js
@@ -40,8 +40,9 @@ Main.ExecutionContextSelector = class {
*/
function deferred() {
// We always want the second context for the service worker targets.
- if (!this._context.flavor(SDK.Target))
+ if (!this._context.flavor(SDK.Target)) {
this._context.setFlavor(SDK.Target, runtimeModel.target());
+ }
}
}
@@ -51,12 +52,14 @@ Main.ExecutionContextSelector = class {
*/
modelRemoved(runtimeModel) {
const currentExecutionContext = this._context.flavor(SDK.ExecutionContext);
- if (currentExecutionContext && currentExecutionContext.runtimeModel === runtimeModel)
+ if (currentExecutionContext && currentExecutionContext.runtimeModel === runtimeModel) {
this._currentExecutionContextGone();
+ }
const models = this._targetManager.models(SDK.RuntimeModel);
- if (this._context.flavor(SDK.Target) === runtimeModel.target() && models.length)
+ if (this._context.flavor(SDK.Target) === runtimeModel.target() && models.length) {
this._context.setFlavor(SDK.Target, models[0].target());
+ }
}
/**
@@ -66,8 +69,9 @@ Main.ExecutionContextSelector = class {
const newContext = /** @type {?SDK.ExecutionContext} */ (event.data);
if (newContext) {
this._context.setFlavor(SDK.Target, newContext.target());
- if (!this._ignoreContextChanged)
+ if (!this._ignoreContextChanged) {
this._lastSelectedContextId = this._contextPersistentId(newContext);
+ }
}
}
@@ -86,22 +90,26 @@ Main.ExecutionContextSelector = class {
const newTarget = /** @type {?SDK.Target} */ (event.data);
const currentContext = this._context.flavor(SDK.ExecutionContext);
- if (!newTarget || (currentContext && currentContext.target() === newTarget))
+ if (!newTarget || (currentContext && currentContext.target() === newTarget)) {
return;
+ }
const runtimeModel = newTarget.model(SDK.RuntimeModel);
const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
- if (!executionContexts.length)
+ if (!executionContexts.length) {
return;
+ }
let newContext = null;
for (let i = 0; i < executionContexts.length && !newContext; ++i) {
- if (this._shouldSwitchToContext(executionContexts[i]))
+ if (this._shouldSwitchToContext(executionContexts[i])) {
newContext = executionContexts[i];
+ }
}
for (let i = 0; i < executionContexts.length && !newContext; ++i) {
- if (this._isDefaultContext(executionContexts[i]))
+ if (this._isDefaultContext(executionContexts[i])) {
newContext = executionContexts[i];
+ }
}
this._ignoreContextChanged = true;
this._context.setFlavor(SDK.ExecutionContext, newContext || executionContexts[0]);
@@ -113,10 +121,12 @@ Main.ExecutionContextSelector = class {
* @return {boolean}
*/
_shouldSwitchToContext(executionContext) {
- if (this._lastSelectedContextId && this._lastSelectedContextId === this._contextPersistentId(executionContext))
+ if (this._lastSelectedContextId && this._lastSelectedContextId === this._contextPersistentId(executionContext)) {
return true;
- if (!this._lastSelectedContextId && this._isDefaultContext(executionContext))
+ }
+ if (!this._lastSelectedContextId && this._isDefaultContext(executionContext)) {
return true;
+ }
return false;
}
@@ -125,14 +135,17 @@ Main.ExecutionContextSelector = class {
* @return {boolean}
*/
_isDefaultContext(executionContext) {
- if (!executionContext.isDefault || !executionContext.frameId)
+ if (!executionContext.isDefault || !executionContext.frameId) {
return false;
- if (executionContext.target().parentTarget())
+ }
+ if (executionContext.target().parentTarget()) {
return false;
+ }
const resourceTreeModel = executionContext.target().model(SDK.ResourceTreeModel);
const frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
- if (frame && frame.isTopFrame())
+ if (frame && frame.isTopFrame()) {
return true;
+ }
return false;
}
@@ -148,8 +161,9 @@ Main.ExecutionContextSelector = class {
*/
_onExecutionContextDestroyed(event) {
const executionContext = /** @type {!SDK.ExecutionContext}*/ (event.data);
- if (this._context.flavor(SDK.ExecutionContext) === executionContext)
+ if (this._context.flavor(SDK.ExecutionContext) === executionContext) {
this._currentExecutionContextGone();
+ }
}
/**
@@ -159,8 +173,9 @@ Main.ExecutionContextSelector = class {
const runtimeModel = /** @type {!SDK.RuntimeModel} */ (event.data);
const executionContexts = runtimeModel.executionContexts();
for (let i = 0; i < executionContexts.length; i++) {
- if (this._switchContextIfNecessary(executionContexts[i]))
+ if (this._switchContextIfNecessary(executionContexts[i])) {
break;
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js b/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
index 0c17d6a1415..d87913f57e2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -44,8 +44,9 @@ Main.Main = class {
* @param {string} label
*/
static time(label) {
- if (Host.isUnderTest())
+ if (Host.isUnderTest()) {
return;
+ }
console.time(label);
}
@@ -53,17 +54,18 @@ Main.Main = class {
* @param {string} label
*/
static timeEnd(label) {
- if (Host.isUnderTest())
+ if (Host.isUnderTest()) {
return;
+ }
console.timeEnd(label);
}
async _loaded() {
console.timeStamp('Main._loaded');
- await Runtime.appStarted();
- Runtime.setPlatform(Host.platform());
- Runtime.setL10nCallback(ls);
- InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
+ await Root.Runtime.appStarted();
+ Root.Runtime.setPlatform(Host.platform());
+ Root.Runtime.setL10nCallback(ls);
+ Host.InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
}
/**
@@ -71,8 +73,9 @@ Main.Main = class {
*/
_gotPreferences(prefs) {
console.timeStamp('Main._gotPreferences');
- if (Host.isUnderTest(prefs))
+ if (Host.isUnderTest(prefs)) {
self.runtime.useTestBase();
+ }
this._createSettings(prefs);
this._createAppUI();
}
@@ -84,10 +87,12 @@ Main.Main = class {
_createSettings(prefs) {
this._initializeExperiments();
let storagePrefix = '';
- if (Host.isCustomDevtoolsFrontend())
+ if (Host.isCustomDevtoolsFrontend()) {
storagePrefix = '__custom__';
- else if (!Runtime.queryParam('can_dock') && !!Runtime.queryParam('debugFrontend') && !Host.isUnderTest())
+ } else if (
+ !Root.Runtime.queryParam('can_dock') && !!Root.Runtime.queryParam('debugFrontend') && !Host.isUnderTest()) {
storagePrefix = '__bundled__';
+ }
let localStorage;
if (!Host.isUnderTest() && window.localStorage) {
@@ -97,57 +102,67 @@ Main.Main = class {
localStorage = new Common.SettingsStorage({}, undefined, undefined, undefined, storagePrefix);
}
const globalStorage = new Common.SettingsStorage(
- prefs, InspectorFrontendHost.setPreference, InspectorFrontendHost.removePreference,
- InspectorFrontendHost.clearPreferences, storagePrefix);
+ prefs, Host.InspectorFrontendHost.setPreference, Host.InspectorFrontendHost.removePreference,
+ Host.InspectorFrontendHost.clearPreferences, storagePrefix);
Common.settings = new Common.Settings(globalStorage, localStorage);
- if (!Host.isUnderTest())
+ if (!Host.isUnderTest()) {
new Common.VersionController().updateVersion();
+ }
}
_initializeExperiments() {
// Keep this sorted alphabetically: both keys and values.
- Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
- Runtime.experiments.register('captureNodeCreationStacks', 'Capture node creation stacks');
- Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
- Runtime.experiments.register('backgroundServices', 'Background web platform feature events', true);
- Runtime.experiments.register('backgroundServicesNotifications', 'Background services section for Notifications');
- Runtime.experiments.register('backgroundServicesPaymentHandler', 'Background services section for Payment Handler');
- Runtime.experiments.register('backgroundServicesPushMessaging', 'Background services section for Push Messaging');
- Runtime.experiments.register(
+ Root.Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
+ Root.Runtime.experiments.register('captureNodeCreationStacks', 'Capture node creation stacks');
+ Root.Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
+ Root.Runtime.experiments.register('backgroundServices', 'Background web platform feature events', true);
+ Root.Runtime.experiments.register(
+ 'backgroundServicesNotifications', 'Background services section for Notifications');
+ Root.Runtime.experiments.register(
+ 'backgroundServicesPaymentHandler', 'Background services section for Payment Handler');
+ Root.Runtime.experiments.register(
+ 'backgroundServicesPushMessaging', 'Background services section for Push Messaging');
+ Root.Runtime.experiments.register(
'backgroundServicesPeriodicBackgroundSync', 'Background services section for Periodic Background Sync');
- Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
- Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
- Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
- Runtime.experiments.register('liveHeapProfile', 'Live heap profile', true);
- Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
- Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
- Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
- Runtime.experiments.register('sourceDiff', 'Source diff');
- Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
- Runtime.experiments.register('spotlight', 'Spotlight', true);
- Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);
+ Root.Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
+ Root.Runtime.experiments.register('cssOverview', 'CSS Overview');
+ Root.Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
+ Root.Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
+ Root.Runtime.experiments.register('liveHeapProfile', 'Live heap profile', true);
+ Root.Runtime.experiments.register('mediaInspector', 'Media Element Inspection');
+ Root.Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
+ Root.Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
+ Root.Runtime.experiments.register(
+ 'recordCoverageWithPerformanceTracing', 'Record coverage while performance tracing');
+ Root.Runtime.experiments.register('samplingHeapProfilerTimeline', 'Sampling heap profiler timeline', true);
+ Root.Runtime.experiments.register('sourceDiff', 'Source diff');
+ Root.Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
+ Root.Runtime.experiments.register('spotlight', 'Spotlight', true);
// Timeline
- Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
- Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
- Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
- Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
- Runtime.experiments.register('timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
- Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
-
- Runtime.experiments.cleanUpStaleExperiments();
- const enabledExperiments = Runtime.queryParam('enabledExperiments');
- if (enabledExperiments)
- Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
- Runtime.experiments.setDefaultExperiments([
+ Root.Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
+ Root.Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
+ Root.Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
+ Root.Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
+ Root.Runtime.experiments.register(
+ 'timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);
+ Root.Runtime.experiments.register('timelineWebGL', 'Timeline: WebGL-based flamechart');
+
+ Root.Runtime.experiments.cleanUpStaleExperiments();
+ const enabledExperiments = Root.Runtime.queryParam('enabledExperiments');
+ if (enabledExperiments) {
+ Root.Runtime.experiments.setServerEnabledExperiments(enabledExperiments.split(';'));
+ }
+ Root.Runtime.experiments.setDefaultExperiments([
'backgroundServices',
'backgroundServicesNotifications',
'backgroundServicesPushMessaging',
'backgroundServicesPaymentHandler',
]);
- if (Host.isUnderTest() && Runtime.queryParam('test').includes('live-line-level-heap-profile.js'))
- Runtime.experiments.enableForTest('liveHeapProfile');
+ if (Host.isUnderTest() && Root.Runtime.queryParam('test').includes('live-line-level-heap-profile.js')) {
+ Root.Runtime.experiments.enableForTest('liveHeapProfile');
+ }
}
/**
@@ -169,8 +184,8 @@ Main.Main = class {
this._addMainEventListeners(document);
- const canDock = !!Runtime.queryParam('can_dock');
- UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost);
+ const canDock = !!Root.Runtime.queryParam('can_dock');
+ UI.zoomManager = new UI.ZoomManager(window, Host.InspectorFrontendHost);
UI.inspectorView = UI.InspectorView.instance();
UI.ContextMenu.initialize();
UI.ContextMenu.installHandler(document);
@@ -234,21 +249,22 @@ Main.Main = class {
const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
// TODO: we should not access actions from other modules.
if (toggleSearchNodeAction) {
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.EnterInspectElementMode,
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode,
toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
}
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);
UI.inspectorView.createToolbars();
- InspectorFrontendHost.loadCompleted();
+ Host.InspectorFrontendHost.loadCompleted();
const extensions = self.runtime.extensions(Common.QueryParamHandler);
for (const extension of extensions) {
- const value = Runtime.queryParam(extension.descriptor()['name']);
- if (value !== null)
+ const value = Root.Runtime.queryParam(extension.descriptor()['name']);
+ if (value !== null) {
extension.instance().then(handleQueryParam.bind(null, value));
+ }
}
/**
@@ -268,10 +284,11 @@ Main.Main = class {
Main.Main.time('Main._initializeTarget');
const instances =
await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
- for (const instance of instances)
+ for (const instance of instances) {
await /** @type {!Common.Runnable} */ (instance).run();
+ }
// Used for browser tests.
- InspectorFrontendHost.readyForTest();
+ Host.InspectorFrontendHost.readyForTest();
// Asynchronously run the extensions.
setTimeout(this._lateInitialization.bind(this), 100);
Main.Main.timeEnd('Main._initializeTarget');
@@ -293,8 +310,9 @@ Main.Main = class {
* @param {!Common.Event} event
*/
async function changeListener(event) {
- if (!event.data)
+ if (!event.data) {
return;
+ }
Common.settings.moduleSetting(setting).removeChangeListener(changeListener);
(/** @type {!Common.Runnable} */ (await extension.instance())).run();
}
@@ -318,7 +336,7 @@ Main.Main = class {
];
const actionKeys =
UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
- InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
+ Host.InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
}
_registerMessageSinkListener() {
@@ -329,8 +347,9 @@ Main.Main = class {
*/
function messageAdded(event) {
const message = /** @type {!Common.Console.Message} */ (event.data);
- if (message.show)
+ if (message.show) {
Common.console.show();
+ }
}
}
@@ -392,8 +411,9 @@ Main.Main = class {
const inspectElementModeShortcuts =
UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
- if (inspectElementModeShortcuts.length)
+ if (inspectElementModeShortcuts.length) {
section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));
+ }
const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
section.addKey(openResourceShortcut, Common.UIString('Go to source'));
@@ -408,8 +428,9 @@ Main.Main = class {
}
_postDocumentKeyDown(event) {
- if (!event.handled)
+ if (!event.handled) {
UI.shortcutRegistry.handleShortcut(event);
+ }
}
/**
@@ -420,15 +441,18 @@ Main.Main = class {
eventCopy['original'] = event;
const document = event.target && event.target.ownerDocument;
const target = document ? document.deepActiveElement() : null;
- if (target)
+ if (target) {
target.dispatchEvent(eventCopy);
- if (eventCopy.handled)
+ }
+ if (eventCopy.handled) {
event.preventDefault();
+ }
}
_contextMenuEventFired(event) {
- if (event.handled || event.target.classList.contains('popup-glasspane'))
+ if (event.handled || event.target.classList.contains('popup-glasspane')) {
event.preventDefault();
+ }
}
/**
@@ -461,18 +485,19 @@ Main.Main.ZoomActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- if (InspectorFrontendHost.isHostedMode())
+ if (Host.InspectorFrontendHost.isHostedMode()) {
return false;
+ }
switch (actionId) {
case 'main.zoom-in':
- InspectorFrontendHost.zoomIn();
+ Host.InspectorFrontendHost.zoomIn();
return true;
case 'main.zoom-out':
- InspectorFrontendHost.zoomOut();
+ Host.InspectorFrontendHost.zoomOut();
return true;
case 'main.zoom-reset':
- InspectorFrontendHost.resetZoom();
+ Host.InspectorFrontendHost.resetZoom();
return true;
}
return false;
@@ -494,8 +519,9 @@ Main.Main.SearchActionDelegate = class {
handleAction(context, actionId) {
const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
UI.inspectorView.currentPanelDeprecated().searchableView();
- if (!searchableView)
+ if (!searchableView) {
return false;
+ }
switch (actionId) {
case 'main.search-in-panel.find':
return searchableView.handleFindShortcut();
@@ -541,8 +567,9 @@ Main.Main.MainMenuItem = class {
'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
dockItemElement.appendChild(titleElement);
const dockItemToolbar = new UI.Toolbar('', dockItemElement);
- if (Host.isMac() && !UI.themeSupport.hasTheme())
+ if (Host.isMac() && !UI.themeSupport.hasTheme()) {
dockItemToolbar.makeBlueOnHover();
+ }
const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
@@ -569,12 +596,13 @@ Main.Main.MainMenuItem = class {
dockItemToolbar.appendToolbarItem(right);
dockItemElement.addEventListener('keydown', event => {
let dir = 0;
- if (event.key === 'ArrowLeft')
+ if (event.key === 'ArrowLeft') {
dir = -1;
- else if (event.key === 'ArrowRight')
+ } else if (event.key === 'ArrowRight') {
dir = 1;
- else
+ } else {
return;
+ }
const buttons = [undock, left, bottom, right];
let index = buttons.findIndex(button => button.element.hasFocus());
@@ -586,17 +614,29 @@ Main.Main.MainMenuItem = class {
contextMenu.headerSection().appendCustomItem(dockItemElement);
}
+
+ const button = this._item.element;
+
/**
* @param {string} side
+ * @suppressGlobalPropertiesCheck
*/
function setDockSide(side) {
+ const hadKeyboardFocus = document.deepActiveElement().hasAttribute('data-keyboard-focus');
+ Components.dockController.once(Components.DockController.Events.AfterDockSideChanged).then(() => {
+ button.focus();
+ if (hadKeyboardFocus) {
+ UI.markAsFocusedByKeyboard(button);
+ }
+ });
Components.dockController.setDockSide(side);
contextMenu.discard();
}
if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
- SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame)
+ SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().type() === SDK.Target.Type.Frame) {
contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));
+ }
contextMenu.defaultSection().appendAction(
'main.toggle-drawer',
@@ -607,10 +647,12 @@ Main.Main.MainMenuItem = class {
const extensions = self.runtime.extensions('view', undefined, true);
for (const extension of extensions) {
const descriptor = extension.descriptor();
- if (descriptor['persistence'] !== 'closeable')
+ if (descriptor['persistence'] !== 'closeable') {
continue;
- if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel')
+ }
+ if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel') {
continue;
+ }
moreTools.defaultSection().appendItem(
extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
}
@@ -650,8 +692,9 @@ Main.Main.PauseListener = class {
Main.sendOverProtocol = function(method, params) {
return new Promise((resolve, reject) => {
Protocol.test.sendRawMessage(method, params, (err, ...results) => {
- if (err)
+ if (err) {
return reject(err);
+ }
return resolve(results);
});
});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
index 7f943da2c63..808c2cdd05d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/main/main_strings.grdp
@@ -9,9 +9,6 @@
<message name="IDS_DEVTOOLS_0a0afb342478f201b92cbc89d19bf14d" desc="Title of a setting under the Appearance category that can be invoked through the Command Menu">
Switch to dark theme
</message>
- <message name="IDS_DEVTOOLS_13348442cc6a27032d2b4aa28b75a5d3" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut">
- Search
- </message>
<message name="IDS_DEVTOOLS_15fa1acc2a998159c4ed2a950c5c231d" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut">
Toggle drawer
</message>
@@ -21,8 +18,8 @@
<message name="IDS_DEVTOOLS_1cf59b16fd253d6ff4bbee7c237cea0d" desc="Text in Main">
Show console
</message>
- <message name="IDS_DEVTOOLS_2ab5656e27a0ed871c8de44368f807c6" desc="Text in Main">
- Styles Pane
+ <message name="IDS_DEVTOOLS_2ac43aa43bf473f9a9c09b4b608619d3" desc="A tag of theme preference settings that can be searched in the command menu">
+ light
</message>
<message name="IDS_DEVTOOLS_2ad9d63b69c4a10a5cc9cad923133bc4" desc="A drop-down menu option to dock to bottom">
Bottom
@@ -52,7 +49,7 @@
Go to the panel to the left/right
</message>
<message name="IDS_DEVTOOLS_586740a88e6502850bc64f9f2d04d380" desc="Title element title in Main">
- Placement of DevTools relative to the page. (<ph name="TOGGLEDOCKSIDESHORCUTS____NAME">$1s<ex>Ctrl+Shift+D</ex></ph> to restore last position)
+ Placement of <ph name="LOCKED_1">DevTools</ph> relative to the page. (<ph name="TOGGLEDOCKSIDESHORCUTS____NAME">$1s<ex>Ctrl+Shift+D</ex></ph> to restore last position)
</message>
<message name="IDS_DEVTOOLS_5bf4a92da989a6943e3fed84f18c3f0f" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut">
Search across all sources
@@ -69,9 +66,6 @@
<message name="IDS_DEVTOOLS_75def4784fa71c4ccde7762316ed0e3e" desc="Text in the Shortcuts page in settings to explain a keyboard shortcut in the Section">
Find next/previous
</message>
- <message name="IDS_DEVTOOLS_787ae37366b7a8c53f381abfd315c647" desc="Text in Main">
- Elements Panel
- </message>
<message name="IDS_DEVTOOLS_8645bf45e76c3f958ae99c114c419743" desc="Text in Main">
Hide console drawer
</message>
@@ -99,6 +93,9 @@
<message name="IDS_DEVTOOLS_a18366b217ebf811ad1886e4f4f865b2" desc="A drop-down menu option to switch to dark theme">
Dark
</message>
+ <message name="IDS_DEVTOOLS_a82fd95db10ff25dfad39f07372ebe37" desc="A tag of theme preference settings that can be searched in the command menu">
+ dark
+ </message>
<message name="IDS_DEVTOOLS_a9e4402481bd9b8e36752bf731f67eb6" desc="Title of a setting under the Appearance category in Settings">
Theme:
</message>
@@ -111,9 +108,6 @@
<message name="IDS_DEVTOOLS_b8da6df14bf06283cbf588df6998722e" desc="A title of the 'Panel' @UI.ViewLocationResolver category">
Panel
</message>
- <message name="IDS_DEVTOOLS_b94d8a074eddd267702810179875737f" desc="Text in Main">
- Debugger
- </message>
<message name="IDS_DEVTOOLS_b9cd538a753713464d2ea17d7e975041" desc="A context menu item in the Main">
More tools
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/main/module.json b/chromium/third_party/blink/renderer/devtools/front_end/main/module.json
index 2f51ce71e48..f1625822761 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/main/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/main/module.json
@@ -185,6 +185,14 @@
{
"platform": "mac",
"shortcut": "Meta+G"
+ },
+ {
+ "platform": "windows,linux",
+ "shortcut": "Ctrl+G"
+ },
+ {
+ "platform": "windows,linux",
+ "shortcut": "F3"
}
]
},
@@ -196,6 +204,14 @@
{
"platform": "mac",
"shortcut": "Meta+Shift+G"
+ },
+ {
+ "platform": "windows,linux",
+ "shortcut": "Ctrl+Shift+G"
+ },
+ {
+ "platform": "windows,linux",
+ "shortcut": "Shift+F3"
}
]
},
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/EventDisplayTable.js b/chromium/third_party/blink/renderer/devtools/front_end/media/EventDisplayTable.js
new file mode 100644
index 00000000000..746e9195124
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/EventDisplayTable.js
@@ -0,0 +1,154 @@
+// 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.
+
+/**
+ * @typedef {{
+ * id: string,
+ * title: string,
+ * sortable: boolean,
+ * weight: (number|undefined),
+ * sortingFunction: (!function(!Media.EventNode, !Media.EventNode):number|undefined),
+ * }}
+ */
+Media.EventDisplayColumnConfig;
+
+/**
+ * @typedef {{
+ * name: string,
+ * value: string,
+ * timestamp: (number|string|undefined)
+ * }}
+ */
+Media.Event;
+
+/**
+ * @unrestricted
+ */
+Media.EventNode = class extends DataGrid.SortableDataGridNode {
+ /**
+ * @param {!Media.Event} event
+ */
+ constructor(event) {
+ super(event, false);
+ }
+
+ /**
+ * @override
+ * @param {string} columnId
+ * @return {!Element}
+ */
+ createCell(columnId) {
+ const cell = this.createTD(columnId);
+ const cellData = /** @type string */ (this.data[columnId]);
+ cell.createTextChild(cellData);
+ return cell;
+ }
+
+ /**
+ * @override
+ * @return {number}
+ */
+ nodeSelfHeight() {
+ return 20;
+ }
+};
+
+/**
+ * @unrestricted
+ */
+Media.EventDisplayTable = class extends UI.VBox {
+ /**
+ * @param {!Array.<!Media.EventDisplayColumnConfig>} headerDescriptors
+ * @param {?string=} uniqueColumn
+ * @param {?string=} defaultSortingColumnId
+ */
+ constructor(headerDescriptors, uniqueColumn, defaultSortingColumnId) {
+ super();
+
+ // Set up element styles.
+ this.registerRequiredCSS('media/eventDisplayTable.css');
+ this.contentElement.classList.add('event-display-table-contents-table-container');
+
+ this._uniqueColumnEntryKey = uniqueColumn;
+ this._uniqueColumnMap = new Map();
+
+ this._dataGrid = this._createDataGrid(headerDescriptors, defaultSortingColumnId);
+ this._dataGrid.setStriped(true);
+ this._dataGrid.asWidget().show(this.contentElement);
+ }
+
+ /**
+ * @param {!Array.<!Media.EventDisplayColumnConfig>} headers
+ * @param {?string|undefined} default_sort
+ * @return !DataGrid.SortableDataGrid
+ */
+ _createDataGrid(headers, default_sort) {
+ const gridColumnDescs = [];
+ const sortFunctionMap = new Map();
+ for (const headerDesc of headers) {
+ gridColumnDescs.push(Media.EventDisplayTable._convertToGridDescriptor(headerDesc));
+ if (headerDesc.sortable) {
+ sortFunctionMap.set(headerDesc.id, headerDesc.sortingFunction);
+ if (!default_sort) {
+ default_sort = headerDesc.id;
+ }
+ }
+ }
+
+ const datagrid = new DataGrid.SortableDataGrid(gridColumnDescs);
+ if (default_sort) {
+ datagrid.sortNodes(sortFunctionMap.get(default_sort), !datagrid.isSortOrderAscending());
+
+ function sortGrid() {
+ const comparator = sortFunctionMap.get(datagrid.sortColumnId());
+ datagrid.sortNodes(comparator, !datagrid.isSortOrderAscending());
+ }
+
+ datagrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, sortGrid);
+ }
+ datagrid.asWidget().contentElement.classList.add('no-border-top-datagrid');
+ return datagrid;
+ }
+
+ /**
+ * @param {!Array.<!Media.Event>} events
+ */
+ addEvents(events) {
+ for (const event of events) {
+ this.addEvent(event);
+ }
+ }
+
+ /**
+ * @param {!Media.Event} event
+ */
+ addEvent(event) {
+ if (this._uniqueColumnEntryKey) {
+ const eventValue = event[this._uniqueColumnEntryKey];
+ if (this._uniqueColumnMap.has(eventValue)) {
+ this._uniqueColumnMap.get(eventValue).data = event;
+ return;
+ }
+ }
+ const node = new Media.EventNode(event);
+ this._dataGrid.rootNode().insertChildOrdered(node);
+ if (this._uniqueColumnEntryKey) {
+ this._uniqueColumnMap.set(event[this._uniqueColumnEntryKey], node);
+ }
+ }
+
+ /**
+ * @param {!Media.EventDisplayColumnConfig} columnConfig
+ * @return {!DataGrid.DataGrid.ColumnDescriptor}
+ */
+ static _convertToGridDescriptor(columnConfig) {
+ return /** @type {!DataGrid.DataGrid.ColumnDescriptor} */ ({
+ id: columnConfig.id,
+ title: columnConfig.title,
+ sortable: columnConfig.sortable,
+ weight: columnConfig.weight || 0,
+ sort: DataGrid.DataGrid.Order.Ascending
+ });
+ }
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/MainView.js b/chromium/third_party/blink/renderer/devtools/front_end/media/MainView.js
new file mode 100644
index 00000000000..2ae8ef7a8a3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/MainView.js
@@ -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.
+
+/**
+ * @implements {SDK.SDKModelObserver<!Media.MediaModel>}
+ */
+Media.MainView = class extends UI.PanelWithSidebar {
+ constructor() {
+ super('Media');
+ this.registerRequiredCSS('media/mediaView.css');
+
+ // Map<Media.PlayerDetailView>
+ this._detailPanels = new Map();
+
+ // Map<string>
+ this._deletedPlayers = new Set();
+
+ this._sidebar = new Media.PlayerListView(this);
+ this._sidebar.show(this.panelSidebarElement());
+
+ SDK.targetManager.observeModels(Media.MediaModel, this);
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {!Array.<!Media.Event>} changes
+ * @param {!Media.MediaModel.MediaChangeTypeKeys} changeType
+ */
+ renderChanges(playerID, changes, changeType) {
+ if (this._deletedPlayers.has(playerID)) {
+ return;
+ }
+
+ if (!this._detailPanels.has(playerID)) {
+ return;
+ }
+
+ this._sidebar.renderChanges(playerID, changes, changeType);
+ this._detailPanels.get(playerID).renderChanges(playerID, changes, changeType);
+ }
+
+ /**
+ * @param {string} playerID
+ */
+ renderMainPanel(playerID) {
+ if (!this._detailPanels.has(playerID)) {
+ return;
+ }
+ this.splitWidget().mainWidget().detachChildWidgets();
+ this._detailPanels.get(playerID).show(this.mainElement());
+ }
+
+ /**
+ * @param {string} playerID
+ */
+ _onPlayerCreated(playerID) {
+ this._sidebar.addMediaElementItem(playerID);
+ this._detailPanels.set(playerID, new Media.PlayerDetailView());
+ }
+
+ /**
+ * @override
+ */
+ wasShown() {
+ super.wasShown();
+ for (const model of SDK.targetManager.models(Media.MediaModel)) {
+ this._addEventListeners(model);
+ }
+ }
+
+ /**
+ * @override
+ */
+ willHide() {
+ for (const model of SDK.targetManager.models(Media.MediaModel)) {
+ this._removeEventListeners(model);
+ }
+ }
+
+ /**
+ * @override
+ * @param {!Media.MediaModel} mediaModel
+ */
+ modelAdded(mediaModel) {
+ if (this.isShowing()) {
+ this._addEventListeners(mediaModel);
+ }
+ }
+
+ /**
+ * @override
+ * @param {!Media.MediaModel} mediaModel
+ */
+ modelRemoved(mediaModel) {
+ this._removeEventListeners(mediaModel);
+ }
+
+ /**
+ * @param {!Media.MediaModel} mediaModel
+ */
+ _addEventListeners(mediaModel) {
+ mediaModel.ensureEnabled();
+ mediaModel.addEventListener(Media.MediaModel.Events.PlayerPropertiesChanged, this._propertiesChanged, this);
+ mediaModel.addEventListener(Media.MediaModel.Events.PlayerEventsAdded, this._eventsAdded, this);
+ mediaModel.addEventListener(Media.MediaModel.Events.PlayersCreated, this._playersCreated, this);
+ }
+
+ /**
+ * @param {!Media.MediaModel} mediaModel
+ */
+ _removeEventListeners(mediaModel) {
+ mediaModel.removeEventListener(Media.MediaModel.Events.PlayerPropertiesChanged, this._propertiesChanged, this);
+ mediaModel.removeEventListener(Media.MediaModel.Events.PlayerEventsAdded, this._eventsAdded, this);
+ mediaModel.removeEventListener(Media.MediaModel.Events.PlayersCreated, this._playersCreated, this);
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _propertiesChanged(event) {
+ this.renderChanges(event.data.playerId, event.data.properties, Media.MediaModel.MediaChangeTypeKeys.Property);
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _eventsAdded(event) {
+ this.renderChanges(event.data.playerId, event.data.events, Media.MediaModel.MediaChangeTypeKeys.Event);
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _playersCreated(event) {
+ const playerlist = /** @type {!Iterable.<string>} */ (event.data);
+ for (const playerID of playerlist) {
+ this._onPlayerCreated(playerID);
+ }
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/MediaModel.js b/chromium/third_party/blink/renderer/devtools/front_end/media/MediaModel.js
new file mode 100644
index 00000000000..8e31201f0c1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/MediaModel.js
@@ -0,0 +1,78 @@
+// 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.
+
+/**
+ * @implements {Protocol.MediaDispatcher}
+ */
+Media.MediaModel = class extends SDK.SDKModel {
+ /**
+ * @param {!SDK.Target} target
+ */
+ constructor(target) {
+ super(target);
+
+ this._enabled = false;
+ this._agent = target.mediaAgent();
+
+ target.registerMediaDispatcher(this);
+ }
+
+ /**
+ * @override
+ * @return {!Promise}
+ */
+ resumeModel() {
+ if (!this._enabled) {
+ return Promise.resolve();
+ }
+ return this._agent.enable();
+ }
+
+ ensureEnabled() {
+ this._agent.enable();
+ this._enabled = true;
+ }
+
+ /**
+ * @param {!Protocol.Media.PlayerId} playerId
+ * @param {!Array.<!Protocol.Media.PlayerProperty>} properties
+ * @override
+ */
+ playerPropertiesChanged(playerId, properties) {
+ this.dispatchEventToListeners(
+ Media.MediaModel.Events.PlayerPropertiesChanged, {playerId: playerId, properties: properties});
+ }
+
+ /**
+ * @param {!Protocol.Media.PlayerId} playerId
+ * @param {!Array.<!Protocol.Media.PlayerEvent>} events
+ * @override
+ */
+ playerEventsAdded(playerId, events) {
+ this.dispatchEventToListeners(Media.MediaModel.Events.PlayerEventsAdded, {playerId: playerId, events: events});
+ }
+
+ /**
+ * @param {!Array.<!Protocol.Media.PlayerId>} playerIds
+ * @override
+ */
+ playersCreated(playerIds) {
+ this.dispatchEventToListeners(Media.MediaModel.Events.PlayersCreated, playerIds);
+ }
+};
+
+SDK.SDKModel.register(Media.MediaModel, SDK.Target.Capability.DOM, false);
+
+/** @enum {symbol} */
+Media.MediaModel.Events = {
+ PlayerPropertiesChanged: Symbol('PlayerPropertiesChanged'),
+ PlayerEventsAdded: Symbol('PlayerEventsAdded'),
+ PlayersCreated: Symbol('PlayersCreated')
+};
+
+/** @enum {string} */
+Media.MediaModel.MediaChangeTypeKeys = {
+ Event: 'Events',
+ Property: 'Properties'
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/MediaTable.js b/chromium/third_party/blink/renderer/devtools/front_end/media/MediaTable.js
new file mode 100644
index 00000000000..d97250654d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/MediaTable.js
@@ -0,0 +1,75 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+Media.MediaPlayerPropertiesRenderer = class extends Media.EventDisplayTable {
+ constructor() {
+ super(
+ [
+ {
+ id: 'name',
+ title: 'Property Name',
+ sortable: true,
+ weight: 2,
+ sortingFunction: DataGrid.SortableDataGrid.StringComparator.bind(null, 'name')
+ },
+ {id: 'value', title: 'Value', sortable: false, weight: 7}
+ ],
+ 'name');
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {!Array.<!Media.Event>} changes
+ * @param {!Media.MediaModel.MediaChangeTypeKeys} change_type
+ */
+ renderChanges(playerID, changes, change_type) {
+ this.addEvents(changes);
+ }
+};
+
+/**
+ * @unrestricted
+ */
+Media.MediaPlayerEventTableRenderer = class extends Media.EventDisplayTable {
+ constructor() {
+ super([
+ {
+ id: 'timestamp',
+ title: 'Timestamp',
+ weight: 1,
+ sortable: true,
+ sortingFunction: DataGrid.SortableDataGrid.NumericComparator.bind(null, 'timestamp')
+ },
+ {id: 'name', title: 'Event Name', weight: 2, sortable: false},
+ {id: 'value', title: 'Value', weight: 7, sortable: false}
+ ]);
+
+ this._firstEventTime = 0;
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {!Array.<!Media.Event>} changes
+ * @param {!Media.MediaModel.MediaChangeTypeKeys} change_type
+ */
+ renderChanges(playerID, changes, change_type) {
+ if (this._firstEventTime === 0 && changes.length > 0) {
+ this._firstEventTime = changes[0].timestamp;
+ }
+
+ this.addEvents(changes.map(this._subtractFirstEventTime.bind(this, this._firstEventTime)));
+ }
+
+ /**
+ * @param {number|string|undefined} first_event_time
+ * @param {!Media.Event} event
+ */
+ _subtractFirstEventTime(first_event_time, event) {
+ event.timestamp = (event.timestamp - first_event_time).toFixed(3);
+ return event;
+ }
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerDetailView.js b/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerDetailView.js
new file mode 100644
index 00000000000..78af53564c7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerDetailView.js
@@ -0,0 +1,47 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+Media.PlayerDetailView = class extends UI.TabbedPane {
+ constructor() {
+ super();
+
+ const propertyTable = new Media.MediaPlayerPropertiesRenderer();
+ const eventTable = new Media.MediaPlayerEventTableRenderer();
+
+ // maps handler type to a list of panels that support rendering changes.
+ this._panels = new Map([
+ [Media.MediaModel.MediaChangeTypeKeys.Property, [propertyTable]],
+ [Media.MediaModel.MediaChangeTypeKeys.Event, [eventTable]]
+ ]);
+
+ this.appendTab(
+ Media.PlayerDetailView.Tabs.Properties, Common.UIString('Properties'), propertyTable,
+ Common.UIString('Player properties'));
+
+ this.appendTab(
+ Media.PlayerDetailView.Tabs.Events, Common.UIString('Events'), eventTable, Common.UIString('Player events'));
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {!Array.<!Media.Event>} changes
+ * @param {!Media.MediaModel.MediaChangeTypeKeys} changeType
+ */
+ renderChanges(playerID, changes, changeType) {
+ for (const panel of this._panels.get(changeType)) {
+ panel.renderChanges(playerID, changes, changeType);
+ }
+ }
+};
+
+/**
+ * @enum {string}
+ */
+Media.PlayerDetailView.Tabs = {
+ Events: 'events',
+ Properties: 'properties',
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerListView.js b/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerListView.js
new file mode 100644
index 00000000000..e131a30d9da
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/PlayerListView.js
@@ -0,0 +1,155 @@
+// 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.
+
+/**
+ * @typedef {{playerTitle: string, playerID: string, exists: boolean, playing: boolean, titleEdited: boolean}}
+ */
+Media.PlayerStatus;
+
+/**
+ * @typedef {{playerStatus: !Media.PlayerStatus, playerTitleElement: ?HTMLElement}}
+ */
+Media.PlayerStatusMapElement;
+
+
+Media.PlayerEntryTreeElement = class extends UI.TreeElement {
+ /**
+ * @param {!Media.PlayerStatus} playerStatus
+ * @param {!Media.MainView} displayContainer
+ */
+ constructor(playerStatus, displayContainer) {
+ super(playerStatus.playerTitle, false);
+ this.titleFromUrl = true;
+ this._playerStatus = playerStatus;
+ this._displayContainer = displayContainer;
+ this.setLeadingIcons([UI.Icon.create('smallicon-videoplayer-playing', 'media-player')]);
+ }
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ onselect(selectedByUser) {
+ this._displayContainer.renderMainPanel(this._playerStatus.playerID);
+ return true;
+ }
+};
+
+
+Media.PlayerListView = class extends UI.VBox {
+ /**
+ * @param {!Media.MainView} mainContainer
+ */
+ constructor(mainContainer) {
+ super(true);
+
+ this._playerStatuses = new Map();
+
+ // Container where new panels can be added based on clicks.
+ this._mainContainer = mainContainer;
+
+ // The parent tree for storing sections
+ this._sidebarTree = new UI.TreeOutlineInShadow();
+ this.contentElement.appendChild(this._sidebarTree.element);
+ this._sidebarTree.registerRequiredCSS('media/playerListView.css');
+
+ // Audio capture / output devices.
+ this._audioDevices = this._addListSection(Common.UIString('Audio I/O'));
+
+ // Video capture devices.
+ this._videoDevices = this._addListSection(Common.UIString('Video Capture Devices'));
+
+ // Players active in this tab.
+ this._playerList = this._addListSection(Common.UIString('Players'));
+ }
+
+ /**
+ * @param {string} title
+ * @return {!UI.TreeElement}
+ */
+ _addListSection(title) {
+ const treeElement = new UI.TreeElement(title, true);
+ treeElement.listItemElement.classList.add('storage-group-list-item');
+ treeElement.setCollapsible(false);
+ treeElement.selectable = false;
+ this._sidebarTree.appendChild(treeElement);
+ return treeElement;
+ }
+
+ /**
+ * @param {string} playerID
+ */
+ addMediaElementItem(playerID) {
+ const playerStatus = {playerTitle: playerID, playerID: playerID, exists: true, playing: false, titleEdited: false};
+ const playerElement = new Media.PlayerEntryTreeElement(playerStatus, this._mainContainer);
+ this._playerStatuses.set(playerID, playerElement);
+ this._playerList.appendChild(playerElement);
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {string} newTitle
+ * @param {boolean} isTitleExtractedFromUrl
+ */
+ setMediaElementPlayerTitle(playerID, newTitle, isTitleExtractedFromUrl) {
+ if (this._playerStatuses.has(playerID)) {
+ const sidebarEntry = this._playerStatuses.get(playerID);
+ if (!isTitleExtractedFromUrl || sidebarEntry.titleFromUrl) {
+ sidebarEntry.title = newTitle;
+ sidebarEntry.titleFromUrl = isTitleExtractedFromUrl;
+ }
+ }
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {string} iconName
+ */
+ setMediaElementPlayerIcon(playerID, iconName) {
+ if (this._playerStatuses.has(playerID)) {
+ const sidebarEntry = this._playerStatuses.get(playerID);
+ sidebarEntry.setLeadingIcons([UI.Icon.create('smallicon-videoplayer-' + iconName, 'media-player')]);
+ }
+ }
+
+ /**
+ * @param {string} playerID
+ * @param {!Array.<!Media.Event>} changes
+ * @param {string} changeType
+ */
+ renderChanges(playerID, changes, changeType) {
+ // We only want to try setting the title from the 'frame_title' and 'frame_url' properties.
+ if (changeType === Media.MediaModel.MediaChangeTypeKeys.Property) {
+ for (const change of changes) {
+ // Sometimes frame_title can be an empty string.
+ if (change.name === 'frame_title' && change.value) {
+ this.setMediaElementPlayerTitle(playerID, change.value, false);
+ }
+
+ if (change.name === 'frame_url') {
+ const url_path_component = change.value.substring(change.value.lastIndexOf('/') + 1);
+ this.setMediaElementPlayerTitle(playerID, url_path_component, true);
+ }
+ }
+ }
+
+ if (changeType === Media.MediaModel.MediaChangeTypeKeys.Event) {
+ let change_to = null;
+ for (const change of changes) {
+ if (change.name === 'Event') {
+ if (change.value === 'PLAY') {
+ change_to = 'playing';
+ } else if (change.value === 'PAUSE') {
+ change_to = 'paused';
+ } else if (change.value === 'WEBMEDIAPLAYER_DESTROYED') {
+ change_to = 'destroyed';
+ }
+ }
+ }
+ if (change_to) {
+ this.setMediaElementPlayerIcon(playerID, change_to);
+ }
+ }
+ }
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/eventDisplayTable.css b/chromium/third_party/blink/renderer/devtools/front_end/media/eventDisplayTable.css
new file mode 100644
index 00000000000..60c190e8ee8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/eventDisplayTable.css
@@ -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.
+ */
+
+.no-border-top-datagrid>.data-grid {
+ /* make sure there is no top border, it ruins the menu view */
+ border-top: 0px;
+}
+
+.event-display-table-contents-table-container>.widget>.data-grid {
+ height: 100%;
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/mediaView.css b/chromium/third_party/blink/renderer/devtools/front_end/media/mediaView.css
new file mode 100644
index 00000000000..2b08b3e9bf6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/mediaView.css
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+
+.playerlist-sidebar {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+}
+
+.playerlist-sidebar-header {
+ font-size: 22px;
+ padding: 8px 20px;
+ border-bottom:1px solid var(--divider-color);
+}
+
+.playerlist-entry-title>pre {
+ margin: 0px;
+}
+
+.playerlist-entry-title {
+ float: left;
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/media_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/media/media_strings.grdp
new file mode 100644
index 00000000000..2c6234155fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/media_strings.grdp
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_DEVTOOLS_421b47ffd946ca083b65cd668c6b17e6" desc="Video player">
+ video
+ </message>
+ <message name="IDS_DEVTOOLS_62933a2951ef01f4eafd9bdf4d3cd2f0" desc="Media player">
+ media
+ </message>
+ <message name="IDS_DEVTOOLS_83341e272df7a4f2982e7b96b7f26a4a" desc="Button text for viewing properties.">
+ Player properties
+ </message>
+ <message name="IDS_DEVTOOLS_87f9f735a1d36793ceaecd4e47124b63" desc="Button text for viewing events.">
+ Events
+ </message>
+ <message name="IDS_DEVTOOLS_cf6523ecab64a91c7a9b3d83b58f9e61" desc="Hover text for the Events button.">
+ Player events
+ </message>
+ <message name="IDS_DEVTOOLS_93ec972c68d5caca43370a9746a08cea" desc="Side-panel entry title text for the players section.">
+ Players
+ </message>
+ <message name="IDS_DEVTOOLS_a20467c4e87b5469cbb1a6c31775393c" desc="Side-panel entry title text for the audio devices section.">
+ Audio I/O
+ </message>
+ <message name="IDS_DEVTOOLS_d9f6db9c0f0579391eccedbac66aef9b" desc="Side-panel entry title text for the video capture devices section.">
+ Video Capture Devices
+ </message>
+</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/module.json b/chromium/third_party/blink/renderer/devtools/front_end/media/module.json
new file mode 100644
index 00000000000..c215352c521
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/module.json
@@ -0,0 +1,34 @@
+{
+ "extensions": [
+ {
+ "type": "view",
+ "location": "panel",
+ "id": "media",
+ "title": "Media",
+ "persistence": "closeable",
+ "order": 100,
+ "className": "Media.MainView",
+ "tags": "media, video",
+ "experiment": "mediaInspector"
+ }
+ ],
+ "dependencies": [
+ "components",
+ "sdk",
+ "ui",
+ "data_grid"
+ ],
+ "scripts": [
+ "EventDisplayTable.js",
+ "MainView.js",
+ "MediaTable.js",
+ "PlayerDetailView.js",
+ "PlayerListView.js",
+ "MediaModel.js"
+ ],
+ "resources": [
+ "eventDisplayTable.css",
+ "mediaView.css",
+ "playerListView.css"
+ ]
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/media/playerListView.css b/chromium/third_party/blink/renderer/devtools/front_end/media/playerListView.css
new file mode 100644
index 00000000000..2282d432cd3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/media/playerListView.css
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+.tree-outline {
+ padding-left: 0;
+ color: rgb(90, 90, 90);
+}
+
+li.storage-group-list-item {
+ padding: 10px 8px 6px 8px;
+}
+
+li.storage-group-list-item:not(:first-child) {
+ border-top: 1px solid rgb(230, 230, 230);
+}
+
+li.storage-group-list-item::before {
+ display: none;
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js
index 34654cc2657..f261b933395 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/NetworkPanelIndicator.js
@@ -5,8 +5,9 @@
MobileThrottling.NetworkPanelIndicator = class {
constructor() {
// TODO: we should not access network from other modules.
- if (!UI.inspectorView.hasPanel('network'))
+ if (!UI.inspectorView.hasPanel('network')) {
return;
+ }
const manager = SDK.multitargetNetworkManager;
manager.addEventListener(SDK.MultitargetNetworkManager.Events.ConditionsChanged, updateVisibility);
manager.addEventListener(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged, updateVisibility);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
index c2f0faa8689..d98a1331c25 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
@@ -54,11 +54,14 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
for (const conditions of group.items) {
const title = conditions.title;
const option = new Option(title, title);
+ UI.ARIAUtils.setAccessibleName(option, ls`${group.title}: ${title}`);
groupElement.appendChild(option);
options.push(conditions);
}
if (i === groups.length - 1) {
- groupElement.appendChild(new Option(Common.UIString('Add\u2026'), Common.UIString('Add\u2026')));
+ const option = new Option(ls`Add\u2026`, ls`Add\u2026`);
+ UI.ARIAUtils.setAccessibleName(option, ls`Add ${group.title}`);
+ groupElement.appendChild(option);
options.push(null);
}
}
@@ -66,18 +69,20 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
}
function optionSelected() {
- if (selectElement.selectedIndex === selectElement.options.length - 1)
+ if (selectElement.selectedIndex === selectElement.options.length - 1) {
selector.revealAndUpdate();
- else
+ } else {
selector.optionSelected(options[selectElement.selectedIndex]);
+ }
}
/**
* @param {number} index
*/
function select(index) {
- if (selectElement.selectedIndex !== index)
+ if (selectElement.selectedIndex !== index) {
selectElement.selectedIndex = index;
+ }
}
}
@@ -95,10 +100,11 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
* @this {!MobileThrottling.ThrottlingManager}
*/
function forceOffline() {
- if (checkbox.checked())
+ if (checkbox.checked()) {
SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions);
- else
+ } else {
SDK.multitargetNetworkManager.setNetworkConditions(this._lastNetworkThrottlingConditions);
+ }
}
function networkConditionsChanged() {
@@ -131,11 +137,13 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
function appendItems(contextMenu) {
for (let index = 0; index < options.length; ++index) {
const conditions = options[index];
- if (!conditions)
+ if (!conditions) {
continue;
+ }
if (conditions.title === MobileThrottling.CustomConditions.title &&
- conditions.description === MobileThrottling.CustomConditions.description)
+ conditions.description === MobileThrottling.CustomConditions.description) {
continue;
+ }
contextMenu.defaultSection().appendCheckboxItem(
Common.UIString(conditions.title),
selector.optionSelected.bind(selector, /** @type {!MobileThrottling.Conditions} */ (conditions)),
@@ -150,8 +158,9 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
function populate(groups) {
options = [];
for (const group of groups) {
- for (const conditions of group.items)
+ for (const conditions of group.items) {
options.push(conditions);
+ }
options.push(null);
}
return options;
@@ -179,8 +188,9 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
*/
setCPUThrottlingRate(rate) {
this._cpuThrottlingRate = rate;
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate);
+ }
let icon = null;
if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrottling) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.CpuThrottlingEnabled);
@@ -188,8 +198,9 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
icon.title = Common.UIString('CPU throttling is enabled');
}
const index = this._cpuThrottlingRates.indexOf(this._cpuThrottlingRate);
- for (const control of this._cpuThrottlingControls)
+ for (const control of this._cpuThrottlingControls) {
control.setSelectedIndex(index);
+ }
UI.inspectorView.setPanelIcon('timeline', icon);
this.dispatchEventToListeners(MobileThrottling.ThrottlingManager.Events.RateChanged, this._cpuThrottlingRate);
}
@@ -199,8 +210,9 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
* @param {!SDK.EmulationModel} emulationModel
*/
modelAdded(emulationModel) {
- if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrottling)
+ if (this._cpuThrottlingRate !== MobileThrottling.CPUThrottlingRates.NoThrottling) {
emulationModel.setCPUThrottlingRate(this._cpuThrottlingRate);
+ }
}
/**
@@ -215,7 +227,7 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
*/
createCPUThrottlingSelector() {
const control = new UI.ToolbarComboBox(
- event => this.setCPUThrottlingRate(this._cpuThrottlingRates[event.target.selectedIndex]));
+ event => this.setCPUThrottlingRate(this._cpuThrottlingRates[event.target.selectedIndex]), ls`CPU throttling`);
this._cpuThrottlingControls.add(control);
const currentRate = this._cpuThrottlingRate;
@@ -224,8 +236,9 @@ MobileThrottling.ThrottlingManager = class extends Common.Object {
const title = rate === 1 ? Common.UIString('No throttling') : Common.UIString('%d\xD7 slowdown', rate);
const option = control.createOption(title);
control.addOption(option);
- if (currentRate === rate)
+ if (currentRate === rate) {
control.setSelectedIndex(i);
+ }
}
return control;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingSettingsTab.js b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingSettingsTab.js
index 4c616008a80..44beae50a1a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingSettingsTab.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingSettingsTab.js
@@ -11,7 +11,9 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
super(true);
this.registerRequiredCSS('mobile_throttling/throttlingSettingsTab.css');
- this.contentElement.createChild('div', 'header').textContent = Common.UIString('Network Throttling Profiles');
+ const header = this.contentElement.createChild('div', 'header');
+ header.textContent = ls`Network Throttling Profiles`;
+ UI.ARIAUtils.markAsHeading(header, 1);
const addButton = UI.createTextButton(
Common.UIString('Add custom profile...'), this._addButtonClicked.bind(this), 'add-conditions-button');
@@ -26,7 +28,6 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
this._customSetting.addChangeListener(this._conditionsUpdated, this);
this.setDefaultFocusedElement(addButton);
- this.contentElement.tabIndex = 0;
}
/**
@@ -41,8 +42,9 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
this._list.clear();
const conditions = this._customSetting.get();
- for (let i = 0; i < conditions.length; ++i)
+ for (let i = 0; i < conditions.length; ++i) {
this._list.appendItem(conditions[i], true);
+ }
this._list.appendSeparator();
}
@@ -102,8 +104,9 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
conditions.latency = latency ? parseInt(latency, 10) : 0;
const list = this._customSetting.get();
- if (isNew)
+ if (isNew) {
list.push(conditions);
+ }
this._customSetting.set(list);
}
@@ -126,8 +129,9 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -208,13 +212,16 @@ MobileThrottling.ThrottlingSettingsTab = class extends UI.VBox {
* @return {string}
*/
MobileThrottling.throughputText = function(throughput, plainText) {
- if (throughput < 0)
+ if (throughput < 0) {
return '';
+ }
const throughputInKbps = throughput / (1024 / 8);
const delimiter = plainText ? '' : ' ';
- if (throughputInKbps < 1024)
+ if (throughputInKbps < 1024) {
return Common.UIString('%d%skb/s', throughputInKbps, delimiter);
- if (throughputInKbps < 1024 * 10)
+ }
+ if (throughputInKbps < 1024 * 10) {
return Common.UIString('%.1f%sMb/s', throughputInKbps / 1024, delimiter);
+ }
return Common.UIString('%d%sMb/s', (throughputInKbps / 1024) | 0, delimiter);
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
index f7d0938e183..290807349a8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/mobile_throttling_strings.grdp
@@ -12,9 +12,6 @@
<message name="IDS_DEVTOOLS_17f66753218a6a1e2762c6a60db3d7c4" desc="Text in Throttling Presets of the Network panel">
Mid-tier mobile
</message>
- <message name="IDS_DEVTOOLS_26ae7bdd1d6fb8c4886e6fde8d12601c" desc="Text in Throttling Settings Tab of the Network panel">
- Latency
- </message>
<message name="IDS_DEVTOOLS_275e2c1079aeffdb5f4e22580127b95b" desc="Text in Throttling Settings Tab of the Network panel">
<ph name="CONDITIONS_LATENCY">$1d<ex>3</ex></ph>ms
</message>
@@ -27,6 +24,9 @@
<message name="IDS_DEVTOOLS_38c8cb828795cd6ff1cddda9b4ffcfa8" desc="Text in Throttling Settings Tab of the Network panel">
<ph name="THROUGHPUTINKBPS___________">$1d<ex>25</ex></ph><ph name="DELIMITER">$2s<ex>''' '''</ex></ph>Mb/s
</message>
+ <message name="IDS_DEVTOOLS_4121424dddde880a0e380f82c57e9944" desc="Screen reader label for a select box that chooses the CPU throttling speed in the Performance panel">
+ CPU throttling
+ </message>
<message name="IDS_DEVTOOLS_4fafba98ddd8a8663d8775a928f2450e" desc="Icon title in Network Panel Indicator of the Network panel">
Requests may be blocked
</message>
@@ -42,9 +42,6 @@
<message name="IDS_DEVTOOLS_8493534a13107469ea63be99410bebfa" desc="Title of an action in the network conditions tool to network low end mobile">
Enable slow 3G throttling
</message>
- <message name="IDS_DEVTOOLS_8d9da4bc0e49a50e09ac9f7e56789d39" desc="Text in Throttling Manager of the Network panel">
- Offline
- </message>
<message name="IDS_DEVTOOLS_8fd93ea382b6642f13ff291b76f5bc85" desc="Text in Throttling Settings Tab of the Network panel">
Profile Name
</message>
@@ -60,9 +57,15 @@
<message name="IDS_DEVTOOLS_a808cbcba081a943f4faedda831298b5" desc="Text in Throttling Settings Tab of the Network panel">
kb/s
</message>
+ <message name="IDS_DEVTOOLS_b19f08b5e9906febcc6a8c717035f8ed" desc="A tag of Network related actions that can be searched in the command menu">
+ throttling
+ </message>
<message name="IDS_DEVTOOLS_b27fdc01c81857f96f3d5d37d323bcb6" desc="Title of an action in the network conditions tool to network mid tier mobile">
Enable fast 3G throttling
</message>
+ <message name="IDS_DEVTOOLS_b95c09fb28e80cc672fd533a62252d70" desc="Accessibility label for custom add network throttling option">
+ Add <ph name="GROUP_TITLE">$1s<ex>Custom</ex></ph>
+ </message>
<message name="IDS_DEVTOOLS_c47c85f963782364d32f428fcf7631ff" desc="Text in Throttling Presets of the Network panel">
No internet connectivity
</message>
@@ -84,12 +87,6 @@
<message name="IDS_DEVTOOLS_d57c24f3fe52d16e7169b912dd647f0d" desc="Text in Throttling Settings Tab of the Network panel">
optional
</message>
- <message name="IDS_DEVTOOLS_eb81441fe20963ff9e8e69c5b32fc625" desc="Text in Mobile Throttling Selector of the Network panel">
- Presets
- </message>
- <message name="IDS_DEVTOOLS_ee33e909372d935d190f4fcb2a92d542" desc="Text in Throttling Settings Tab of the Network panel">
- ms
- </message>
<message name="IDS_DEVTOOLS_f410c3f1a07f566591283f599701e4ab" desc="Text in Throttling Manager of the Network panel">
Add…
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
index ac0dee12f2e..9c25b868e24 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="ndb_app.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="ndb_app.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.js b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.js
index c3eb0e5672f..379d9b27f07 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.js
@@ -1,4 +1,4 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Runtime.startApplication('ndb_app');
+Root.Runtime.startApplication('ndb_app');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js
index 0e0f627d4ed..f9a2be59828 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js
@@ -40,10 +40,10 @@ Network.BinaryResourceView = class extends UI.VBox {
this._binaryResourceViewFactory.utf8.bind(this._binaryResourceViewFactory)),
];
this._binaryViewTypeSetting = Common.settings.createSetting('binaryViewType', 'hex');
- this._binaryViewTypeCombobox = new UI.ToolbarComboBox(this._binaryViewTypeChanged.bind(this));
+ this._binaryViewTypeCombobox = new UI.ToolbarComboBox(this._binaryViewTypeChanged.bind(this), ls`Binary view type`);
for (const viewObject of this._binaryViewObjects) {
this._binaryViewTypeCombobox.addOption(
- this._binaryViewTypeCombobox.createOption(viewObject.label, viewObject.label, viewObject.type));
+ this._binaryViewTypeCombobox.createOption(viewObject.label, viewObject.type));
}
this._toolbar.appendToolbarItem(this._binaryViewTypeCombobox);
@@ -78,7 +78,7 @@ Network.BinaryResourceView = class extends UI.VBox {
async _copySelectedViewToClipboard() {
const viewObject = this._getCurrentViewObject();
- InspectorFrontendHost.copyText(await viewObject.content());
+ Host.InspectorFrontendHost.copyText((await viewObject.content()).content);
this._copiedText.setText(viewObject.copiedMessage);
this._copiedText.element.classList.remove('fadeout');
/**
@@ -98,21 +98,25 @@ Network.BinaryResourceView = class extends UI.VBox {
* @override
*/
wasShown() {
- if (!this._empty)
+ if (!this._empty) {
this._updateView();
+ }
}
_updateView() {
const newViewObject = this._getCurrentViewObject();
- if (!newViewObject)
+ if (!newViewObject) {
return;
+ }
const newView = newViewObject.getView();
- if (newView === this._lastView)
+ if (newView === this._lastView) {
return;
+ }
- if (this._lastView)
+ if (this._lastView) {
this._lastView.detach();
+ }
this._lastView = newView;
newView.show(this.element, this._toolbar.element);
@@ -121,8 +125,9 @@ Network.BinaryResourceView = class extends UI.VBox {
_binaryViewTypeChanged() {
const newViewType = this._binaryViewTypeCombobox.selectedOption().value;
- if (this._binaryViewTypeSetting.get() === newViewType)
+ if (this._binaryViewTypeSetting.get() === newViewType) {
return;
+ }
this._binaryViewTypeSetting.set(newViewType);
this._updateView();
}
@@ -132,17 +137,24 @@ Network.BinaryResourceView = class extends UI.VBox {
* @param {string} submenuItemText
*/
addCopyToContextMenu(contextMenu, submenuItemText) {
- if (this._empty)
+ if (this._empty) {
return;
+ }
const copyMenu = contextMenu.clipboardSection().appendSubMenuItem(submenuItemText);
const footerSection = copyMenu.footerSection();
- footerSection.appendItem(
- ls`Copy as Base64`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.base64()));
- footerSection.appendItem(
- ls`Copy as Hex`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.hex()));
- footerSection.appendItem(
- ls`Copy as UTF-8`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.utf8()));
+ footerSection.appendItem(ls`Copy as Base64`, async () => {
+ const content = await this._binaryResourceViewFactory.base64();
+ Host.InspectorFrontendHost.copyText(content.content);
+ });
+ footerSection.appendItem(ls`Copy as Hex`, async () => {
+ const content = await this._binaryResourceViewFactory.hex();
+ Host.InspectorFrontendHost.copyText(content.content);
+ });
+ footerSection.appendItem(ls`Copy as UTF-8`, async () => {
+ const content = await this._binaryResourceViewFactory.utf8();
+ Host.InspectorFrontendHost.copyText(content.content);
+ });
}
};
@@ -152,13 +164,13 @@ Network.BinaryResourceView.BinaryViewObject = class {
* @param {string} label
* @param {string} copiedMessage
* @param {function():!UI.Widget} createViewFn
- * @param {function():Promise<string>} content
+ * @param {function():Promise<!Common.DeferredContent>} deferredContent
*/
- constructor(type, label, copiedMessage, createViewFn, content) {
+ constructor(type, label, copiedMessage, createViewFn, deferredContent) {
this.type = type;
this.label = label;
this.copiedMessage = copiedMessage;
- this.content = content;
+ this.content = deferredContent;
this._createViewFn = createViewFn;
/** @type {?UI.Widget} */
@@ -169,8 +181,9 @@ Network.BinaryResourceView.BinaryViewObject = class {
* @return {!UI.Widget}
*/
getView() {
- if (!this._view)
+ if (!this._view) {
this._view = this._createViewFn();
+ }
return this._view;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/BlockedURLsPane.js b/chromium/third_party/blink/renderer/devtools/front_end/network/BlockedURLsPane.js
index 2ec93c97259..b2425ae5727 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/BlockedURLsPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/BlockedURLsPane.js
@@ -50,15 +50,16 @@ Network.BlockedURLsPane = class extends UI.VBox {
*/
_createEmptyPlaceholder() {
const element = this.contentElement.createChild('div', 'no-blocked-urls');
- const addLink = UI.XLink.create('', ls`Add pattern`);
- addLink.addEventListener('click', this._addButtonClicked.bind(this), false);
- element.appendChild(UI.formatLocalized('Requests are not blocked. %s.', [addLink]));
+ const addButton = UI.createTextButton(ls`Add pattern`, this._addButtonClicked.bind(this), 'add-button');
+ UI.ARIAUtils.setAccessibleName(addButton, ls`Add request blocking pattern`);
+ element.appendChild(UI.formatLocalized('Requests are not blocked. %s', [addButton]));
return element;
}
static reset() {
- if (Network.BlockedURLsPane._instance)
+ if (Network.BlockedURLsPane._instance) {
Network.BlockedURLsPane._instance.reset();
+ }
}
_addButtonClicked() {
@@ -133,10 +134,11 @@ Network.BlockedURLsPane = class extends UI.VBox {
commitEdit(item, editor, isNew) {
const url = editor.control('url').value;
const patterns = this._manager.blockedPatterns();
- if (isNew)
+ if (isNew) {
patterns.push({enabled: true, url: url});
- else
+ } else {
patterns.splice(patterns.indexOf(item), 1, {enabled: true, url: url});
+ }
this._manager.setBlockedPatterns(patterns);
}
@@ -145,8 +147,9 @@ Network.BlockedURLsPane = class extends UI.VBox {
* @return {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
const content = editor.contentElement();
@@ -175,8 +178,9 @@ Network.BlockedURLsPane = class extends UI.VBox {
this._list.element.classList.toggle('blocking-disabled', !enabled && !!this._manager.blockedPatterns().length);
this._enabledCheckbox.setChecked(enabled);
this._list.clear();
- for (const pattern of this._manager.blockedPatterns())
+ for (const pattern of this._manager.blockedPatterns()) {
this._list.appendItem(pattern, true);
+ }
return Promise.resolve();
}
@@ -185,13 +189,15 @@ Network.BlockedURLsPane = class extends UI.VBox {
* @return {number}
*/
_blockedRequestsCount(url) {
- if (!url)
+ if (!url) {
return 0;
+ }
let result = 0;
for (const blockedUrl of this._blockedCountForUrl.keys()) {
- if (this._matches(url, blockedUrl))
+ if (this._matches(url, blockedUrl)) {
result += this._blockedCountForUrl.get(blockedUrl);
+ }
}
return result;
}
@@ -206,11 +212,13 @@ Network.BlockedURLsPane = class extends UI.VBox {
const parts = pattern.split('*');
for (let index = 0; index < parts.length; index++) {
const part = parts[index];
- if (!part.length)
+ if (!part.length) {
continue;
+ }
pos = url.indexOf(part, pos);
- if (pos === -1)
+ if (pos === -1) {
return false;
+ }
pos += part.length;
}
return true;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/EventSourceMessagesView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/EventSourceMessagesView.js
index 626519b73f0..355541827a5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/EventSourceMessagesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/EventSourceMessagesView.js
@@ -38,8 +38,9 @@ Network.EventSourceMessagesView = class extends UI.VBox {
wasShown() {
this._dataGrid.rootNode().removeChildren();
const messages = this._request.eventSourceMessages();
- for (let i = 0; i < messages.length; ++i)
+ for (let i = 0; i < messages.length; ++i) {
this._dataGrid.insertChild(new Network.EventSourceMessageNode(messages[i]));
+ }
this._request.addEventListener(SDK.NetworkRequest.Events.EventSourceMessageAdded, this._messageAdded, this);
}
@@ -61,11 +62,13 @@ Network.EventSourceMessagesView = class extends UI.VBox {
_sortItems() {
const sortColumnId = this._dataGrid.sortColumnId();
- if (!sortColumnId)
+ if (!sortColumnId) {
return;
+ }
const comparator = Network.EventSourceMessageNode.Comparators[sortColumnId];
- if (!comparator)
+ if (!comparator) {
return;
+ }
this._dataGrid.sortNodes(comparator, !this._dataGrid.isSortOrderAscending());
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/HARWriter.js b/chromium/third_party/blink/renderer/devtools/front_end/network/HARWriter.js
index b7f20e88d8a..a932827a124 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/HARWriter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/HARWriter.js
@@ -39,8 +39,9 @@ Network.HARWriter = class {
const compositeProgress = new Common.CompositeProgress(progress);
const content = await Network.HARWriter._harStringForRequests(requests, compositeProgress);
- if (progress.isCanceled())
+ if (progress.isCanceled()) {
return Promise.resolve();
+ }
return Network.HARWriter._writeToStream(stream, compositeProgress, content);
}
@@ -64,8 +65,9 @@ Network.HARWriter = class {
await Promise.all(promises);
progress.done();
- if (progress.isCanceled())
+ if (progress.isCanceled()) {
return '';
+ }
return JSON.stringify({log: harLog}, null, Network.HARWriter._jsonIndent);
function isValidCharacter(code_point) {
@@ -77,8 +79,9 @@ Network.HARWriter = class {
function needsEncoding(content) {
for (let i = 0; i < content.length; i++) {
- if (!isValidCharacter(content.charCodeAt(i)))
+ if (!isValidCharacter(content.charCodeAt(i))) {
return true;
+ }
}
return false;
}
@@ -98,8 +101,9 @@ Network.HARWriter = class {
}
entry.response.content.text = content;
}
- if (encoded)
+ if (encoded) {
entry.response.content.encoding = 'base64';
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkConfigView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkConfigView.js
index 07c25a8da35..dc0267075d9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkConfigView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkConfigView.js
@@ -73,8 +73,9 @@ Network.NetworkConfigView = class extends UI.VBox {
}
}
- if (!selectionRestored)
+ if (!selectionRestored) {
userAgentSelectElement.selectedIndex = 0;
+ }
}
function applyOtherUserAgent() {
@@ -95,8 +96,9 @@ Network.NetworkConfigView = class extends UI.VBox {
*/
_createSection(title, className) {
const section = this.contentElement.createChild('section', 'network-config-group');
- if (className)
+ if (className) {
section.classList.add(className);
+ }
section.createChild('div', 'network-config-title').textContent = title;
return section.createChild('div', 'network-config-fields');
}
@@ -125,8 +127,9 @@ Network.NetworkConfigView = class extends UI.VBox {
const customUserAgentSetting = Common.settings.createSetting('customUserAgent', '');
customUserAgentSetting.addChangeListener(() => {
- if (autoCheckbox.checked)
+ if (autoCheckbox.checked) {
return;
+ }
SDK.multitargetNetworkManager.setCustomUserAgentOverride(customUserAgentSetting.get());
});
const customUserAgentSelectBox = section.createChild('div', 'network-config-ua-custom');
@@ -151,236 +154,239 @@ Network.NetworkConfigView = class extends UI.VBox {
/** @type {!Array.<{title: string, values: !Array.<{title: string, value: string}>}>} */
Network.NetworkConfigView._userAgentGroups = [
{
- title: 'Android',
+ title: ls`Android`,
values: [
{
- title: 'Android (4.0.2) Browser \u2014 Galaxy Nexus',
+ title: ls`Android (4.0.2) Browser \u2014 Galaxy Nexus`,
value:
'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30'
},
{
- title: 'Android (2.3) Browser \u2014 Nexus S',
+ title: ls`Android (2.3) Browser \u2014 Nexus S`,
value:
'Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'
}
]
},
{
- title: 'BlackBerry',
+ title: ls`BlackBerry`,
values: [
{
- title: 'BlackBerry \u2014 BB10',
+ title: ls`BlackBerry \u2014 BB10`,
value:
'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.1+ (KHTML, like Gecko) Version/10.0.0.1337 Mobile Safari/537.1+'
},
{
- title: 'BlackBerry \u2014 PlayBook 2.1',
+ title: ls`BlackBerry \u2014 PlayBook 2.1`,
value:
'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+'
},
{
- title: 'BlackBerry \u2014 9900',
+ title: ls`BlackBerry \u2014 9900`,
value:
'Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.187 Mobile Safari/534.11+'
}
]
},
{
- title: 'Chrome',
+ title: ls`Chrome`,
values: [
{
- title: 'Chrome \u2014 Android Mobile',
+ title: ls`Chrome \u2014 Android Mobile`,
value:
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Mobile Safari/537.36'
},
{
- title: 'Chrome \u2014 Android Tablet',
+ title: ls`Chrome \u2014 Android Tablet`,
value:
'Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36'
},
{
- title: 'Chrome \u2014 iPhone',
+ title: ls`Chrome \u2014 iPhone`,
value:
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/%s Mobile/13B143 Safari/601.1.46'
},
{
- title: 'Chrome \u2014 iPad',
+ title: ls`Chrome \u2014 iPad`,
value:
'Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/%s Mobile/13B143 Safari/601.1.46'
},
{
- title: 'Chrome \u2014 Chrome OS',
+ title: ls`Chrome \u2014 Chrome OS`,
value: 'Mozilla/5.0 (X11; CrOS x86_64 10066.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36'
},
{
- title: 'Chrome \u2014 Mac',
+ title: ls`Chrome \u2014 Mac`,
value:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36'
},
{
- title: 'Chrome \u2014 Windows',
+ title: ls`Chrome \u2014 Windows`,
value: 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36'
}
]
},
{
- title: 'Firefox',
+ title: ls`Firefox`,
values: [
{
- title: 'Firefox \u2014 Android Mobile',
+ title: ls`Firefox \u2014 Android Mobile`,
value: 'Mozilla/5.0 (Android 4.4; Mobile; rv:46.0) Gecko/46.0 Firefox/46.0'
},
{
- title: 'Firefox \u2014 Android Tablet',
+ title: ls`Firefox \u2014 Android Tablet`,
value: 'Mozilla/5.0 (Android 4.4; Tablet; rv:46.0) Gecko/46.0 Firefox/46.0'
},
{
- title: 'Firefox \u2014 iPhone',
+ title: ls`Firefox \u2014 iPhone`,
value:
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
},
{
- title: 'Firefox \u2014 iPad',
+ title: ls`Firefox \u2014 iPad`,
value:
'Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
},
{
- title: 'Firefox \u2014 Mac',
+ title: ls`Firefox \u2014 Mac`,
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0'
},
{
- title: 'Firefox \u2014 Windows',
+ title: ls`Firefox \u2014 Windows`,
value: 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0'
}
]
},
{
- title: 'Googlebot',
+ title: ls`Googlebot`,
values: [
- {title: 'Googlebot', value: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'}, {
- title: 'Googlebot Smartphone',
+ {title: ls`Googlebot`, value: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'}, {
+ title: ls`Googlebot Smartphone`,
value:
'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
}
]
},
{
- title: 'Internet Explorer',
+ title: ls`Internet Explorer`,
values: [
- {title: 'Internet Explorer 11', value: 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'},
- {title: 'Internet Explorer 10', value: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'},
- {title: 'Internet Explorer 9', value: 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'},
- {title: 'Internet Explorer 8', value: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'},
- {title: 'Internet Explorer 7', value: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'}
+ {title: ls`Internet Explorer 11`, value: 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'},
+ {
+ title: ls`Internet Explorer 10`,
+ value: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'
+ },
+ {title: ls`Internet Explorer 9`, value: 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'},
+ {title: ls`Internet Explorer 8`, value: 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'},
+ {title: ls`Internet Explorer 7`, value: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'}
]
},
{
- title: 'Microsoft Edge',
+ title: ls`Microsoft Edge`,
values: [
{
- title: 'Microsoft Edge (Chromium) \u2014 Windows',
+ title: ls`Microsoft Edge (Chromium) \u2014 Windows`,
value:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36 Edg/%s'
},
{
- title: 'Microsoft Edge (Chromium) \u2014 Mac',
+ title: ls`Microsoft Edge (Chromium) \u2014 Mac`,
value:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36 Edg/%s'
},
{
- title: 'Microsoft Edge \u2014 iPhone',
+ title: ls`Microsoft Edge \u2014 iPhone`,
value:
'Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 EdgiOS/44.5.0.10 Mobile/15E148 Safari/604.1'
},
{
- title: 'Microsoft Edge \u2014 iPad',
+ title: ls`Microsoft Edge \u2014 iPad`,
value:
'Mozilla/5.0 (iPad; CPU OS 12_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 EdgiOS/44.5.2 Mobile/15E148 Safari/605.1.15'
},
{
- title: 'Microsoft Edge \u2014 Android Mobile',
+ title: ls`Microsoft Edge \u2014 Android Mobile`,
value:
'Mozilla/5.0 (Linux; Android 8.1.0; Pixel Build/OPM4.171019.021.D1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Mobile Safari/537.36 EdgA/42.0.0.2057'
},
{
- title: 'Microsoft Edge \u2014 Android Tablet',
+ title: ls`Microsoft Edge \u2014 Android Tablet`,
value:
'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.109 Safari/537.36 EdgA/42.0.0.2057'
},
{
- title: 'Microsoft Edge (EdgeHTML) \u2014 Windows',
+ title: ls`Microsoft Edge (EdgeHTML) \u2014 Windows`,
value:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'
},
{
- title: 'Microsoft Edge (EdgeHTML) \u2014 XBox',
+ title: ls`Microsoft Edge (EdgeHTML) \u2014 XBox`,
value:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'
}
]
},
{
- title: 'Opera',
+ title: ls`Opera`,
values: [
{
- title: 'Opera \u2014 Mac',
+ title: ls`Opera \u2014 Mac`,
value:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36 OPR/37.0.2178.31'
},
{
- title: 'Opera \u2014 Windows',
+ title: ls`Opera \u2014 Windows`,
value:
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36 OPR/37.0.2178.31'
},
{
- title: 'Opera (Presto) \u2014 Mac',
+ title: ls`Opera (Presto) \u2014 Mac`,
value: 'Opera/9.80 (Macintosh; Intel Mac OS X 10.9.1) Presto/2.12.388 Version/12.16'
},
- {title: 'Opera (Presto) \u2014 Windows', value: 'Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.16'}, {
- title: 'Opera Mobile \u2014 Android Mobile',
+ {title: ls`Opera (Presto) \u2014 Windows`, value: 'Opera/9.80 (Windows NT 6.1) Presto/2.12.388 Version/12.16'}, {
+ title: ls`Opera Mobile \u2014 Android Mobile`,
value: 'Opera/12.02 (Android 4.1; Linux; Opera Mobi/ADR-1111101157; U; en-US) Presto/2.9.201 Version/12.02'
},
{
- title: 'Opera Mini \u2014 iOS',
+ title: ls`Opera Mini \u2014 iOS`,
value: 'Opera/9.80 (iPhone; Opera Mini/8.0.0/34.2336; U; en) Presto/2.8.119 Version/11.10'
}
]
},
{
- title: 'Safari',
+ title: ls`Safari`,
values: [
{
- title: 'Safari \u2014 iPad iOS 9',
+ title: ls`Safari \u2014 iPad iOS 9`,
value:
'Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B137 Safari/601.1'
},
{
- title: 'Safari \u2014 iPhone iOS 9',
+ title: ls`Safari \u2014 iPhone iOS 9`,
value:
'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B137 Safari/601.1'
},
{
- title: 'Safari \u2014 Mac',
+ title: ls`Safari \u2014 Mac`,
value:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'
}
]
},
{
- title: 'UC Browser',
+ title: ls`UC Browser`,
values: [
{
- title: 'UC Browser \u2014 Android Mobile',
+ title: ls`UC Browser \u2014 Android Mobile`,
value:
'Mozilla/5.0 (Linux; U; Android 8.1.0; en-US; Nexus 6P Build/OPM7.181205.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.11.1.1197 Mobile Safari/537.36'
},
{
- title: 'UC Browser \u2014 iOS',
+ title: ls`UC Browser \u2014 iOS`,
value:
'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/16B92 UCBrowser/12.1.7.1109 Mobile AliApp(TUnionSDK/0.1.20.3)'
},
{
- title: 'UC Browser \u2014 Windows Phone',
+ title: ls`UC Browser \u2014 Windows Phone`,
value:
'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920) UCBrowser/10.1.0.563 Mobile'
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
index caef4c36b12..0b186951709 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
@@ -49,8 +49,9 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
* @return {!Network.NetworkNode._SupportedBackgroundColors}
*/
static _themedBackgroundColors() {
- if (Network.NetworkNode._themedBackgroundColorsCache)
+ if (Network.NetworkNode._themedBackgroundColorsCache) {
return Network.NetworkNode._themedBackgroundColorsCache;
+ }
const themedColors = {};
for (const name in Network.NetworkNode._backgroundColors) {
const color = Common.Color.fromRGBA(Network.NetworkNode._backgroundColors[name]);
@@ -92,25 +93,31 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
*/
backgroundColor() {
const bgColors = Network.NetworkNode._themedBackgroundColors();
- if (this.selected)
+ if (this.selected) {
return /** @type {string} */ (bgColors.Selected.asString(Common.Color.Format.HEX));
+ }
let color = this.isStriped() ? bgColors.Stripe : bgColors.Default;
- if (this.isNavigationRequest())
+ if (this.isNavigationRequest()) {
color = color.blendWith(bgColors.Navigation);
- if (this.hovered())
+ }
+ if (this.hovered()) {
color = color.blendWith(bgColors.Hovered);
- if (this.isOnInitiatorPath())
+ }
+ if (this.isOnInitiatorPath()) {
color = color.blendWith(bgColors.InitiatorPath);
- if (this.isOnInitiatedPath())
+ }
+ if (this.isOnInitiatedPath()) {
color = color.blendWith(bgColors.InitiatedPath);
+ }
return /** @type {string} */ (color.asString(Common.Color.Format.HEX));
}
_updateBackgroundColor() {
const element = this.existingElement();
- if (!element)
+ if (!element) {
return;
+ }
element.style.backgroundColor = this.backgroundColor();
this._parentView.stylesChanged();
}
@@ -158,12 +165,14 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
* @param {boolean} showInitiatorChain
*/
setHovered(hovered, showInitiatorChain) {
- if (this._isHovered === hovered && this._showingInitiatorChain === showInitiatorChain)
+ if (this._isHovered === hovered && this._showingInitiatorChain === showInitiatorChain) {
return;
+ }
if (this._isHovered !== hovered) {
this._isHovered = hovered;
- if (this.attached())
+ if (this.attached()) {
this.element().classList.toggle('hover', hovered);
+ }
}
if (this._showingInitiatorChain !== showInitiatorChain) {
this._showingInitiatorChain = showInitiatorChain;
@@ -220,8 +229,9 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
* @return {?SDK.NetworkRequest}
*/
requestOrFirstKnownChildRequest() {
- if (this._requestOrFirstKnownChildRequest)
+ if (this._requestOrFirstKnownChildRequest) {
return this._requestOrFirstKnownChildRequest;
+ }
let request = this.request();
if (request || !this.hasChildren()) {
this._requestOrFirstKnownChildRequest = request;
@@ -232,8 +242,9 @@ Network.NetworkNode = class extends DataGrid.SortableDataGridNode {
const flatChildren = this.flatChildren();
for (let i = 0; i < flatChildren.length; i++) {
request = flatChildren[i].request();
- if (!firstChildRequest || (request && request.issueTime() < firstChildRequest.issueTime()))
+ if (!firstChildRequest || (request && request.issueTime() < firstChildRequest.issueTime())) {
firstChildRequest = request;
+ }
}
this._requestOrFirstKnownChildRequest = firstChildRequest;
return this._requestOrFirstKnownChildRequest;
@@ -307,8 +318,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
if (aName === bName) {
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (aRequest && bRequest)
+ if (aRequest && bRequest) {
return aRequest.indentityCompare(bRequest);
+ }
return aRequest ? -1 : 1;
}
return aName < bName ? -1 : 1;
@@ -323,14 +335,17 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aRemoteAddress = aRequest.remoteAddress();
const bRemoteAddress = bRequest.remoteAddress();
- if (aRemoteAddress > bRemoteAddress)
+ if (aRemoteAddress > bRemoteAddress) {
return 1;
- if (bRemoteAddress > aRemoteAddress)
+ }
+ if (bRemoteAddress > aRemoteAddress) {
return -1;
+ }
return aRequest.indentityCompare(bRequest);
}
@@ -343,8 +358,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
static ProductComparator(productRegistry, a, b) {
const aRequest = a.request();
const bRequest = b.request();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aName = productRegistry.nameForUrl(aRequest.parsedURL) || '';
const bName = productRegistry.nameForUrl(bRequest.parsedURL) || '';
return aName.localeCompare(bName) || aRequest.indentityCompare(bRequest);
@@ -359,12 +375,15 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
- if (bRequest.cached() && !aRequest.cached())
+ }
+ if (bRequest.cached() && !aRequest.cached()) {
return 1;
- if (aRequest.cached() && !bRequest.cached())
+ }
+ if (aRequest.cached() && !bRequest.cached()) {
return -1;
+ }
return (aRequest.transferSize - bRequest.transferSize) || (aRequest.resourceSize - bRequest.resourceSize) ||
aRequest.indentityCompare(bRequest);
}
@@ -378,15 +397,18 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aSimpleType = a.displayType();
const bSimpleType = b.displayType();
- if (aSimpleType > bSimpleType)
+ if (aSimpleType > bSimpleType) {
return 1;
- if (bSimpleType > aSimpleType)
+ }
+ if (bSimpleType > aSimpleType) {
return -1;
+ }
return aRequest.indentityCompare(bRequest);
}
@@ -399,10 +421,12 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
- if (!a._initiatorCell || !b._initiatorCell)
+ }
+ if (!a._initiatorCell || !b._initiatorCell) {
return !a._initiatorCell ? -1 : 1;
+ }
const aText = a._linkifiedInitiatorAnchor ? a._linkifiedInitiatorAnchor.textContent : a._initiatorCell.title;
const bText = b._linkifiedInitiatorAnchor ? b._linkifiedInitiatorAnchor.textContent : b._initiatorCell.title;
return aText.localeCompare(bText);
@@ -417,8 +441,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aScore = aRequest.requestCookies ? aRequest.requestCookies.length : 0;
const bScore = bRequest.requestCookies ? bRequest.requestCookies.length : 0;
return (aScore - bScore) || aRequest.indentityCompare(bRequest);
@@ -434,8 +459,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aScore = aRequest.responseCookies ? aRequest.responseCookies.length : 0;
const bScore = bRequest.responseCookies ? bRequest.responseCookies.length : 0;
return (aScore - bScore) || aRequest.indentityCompare(bRequest);
@@ -450,8 +476,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aPriority = aRequest.priority();
let aScore = aPriority ? PerfUI.networkPriorityWeight(aPriority) : 0;
aScore = aScore || 0;
@@ -471,12 +498,14 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
static RequestPropertyComparator(propertyName, a, b) {
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aValue = aRequest[propertyName];
const bValue = bRequest[propertyName];
- if (aValue === bValue)
+ if (aValue === bValue) {
return aRequest.indentityCompare(bRequest);
+ }
return aValue > bValue ? 1 : -1;
}
@@ -490,8 +519,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aValue = String(aRequest.responseHeaderValue(propertyName) || '');
const bValue = String(bRequest.responseHeaderValue(propertyName) || '');
return aValue.localeCompare(bValue) || aRequest.indentityCompare(bRequest);
@@ -507,16 +537,18 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aValue = (aRequest.responseHeaderValue(propertyName) !== undefined) ?
parseFloat(aRequest.responseHeaderValue(propertyName)) :
-Infinity;
const bValue = (bRequest.responseHeaderValue(propertyName) !== undefined) ?
parseFloat(bRequest.responseHeaderValue(propertyName)) :
-Infinity;
- if (aValue === bValue)
+ if (aValue === bValue) {
return aRequest.indentityCompare(bRequest);
+ }
return aValue > bValue ? 1 : -1;
}
@@ -530,14 +562,16 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
// TODO(allada) Handle this properly for group nodes.
const aRequest = a.requestOrFirstKnownChildRequest();
const bRequest = b.requestOrFirstKnownChildRequest();
- if (!aRequest || !bRequest)
+ if (!aRequest || !bRequest) {
return !aRequest ? -1 : 1;
+ }
const aHeader = aRequest.responseHeaderValue(propertyName);
const bHeader = bRequest.responseHeaderValue(propertyName);
const aValue = aHeader ? new Date(aHeader).getTime() : -Infinity;
const bValue = bHeader ? new Date(bHeader).getTime() : -Infinity;
- if (aValue === bValue)
+ if (aValue === bValue) {
return aRequest.indentityCompare(bRequest);
+ }
return aValue > bValue ? 1 : -1;
}
@@ -549,19 +583,23 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
const initiatorGraph = SDK.networkLog.initiatorGraphForRequest(this._request);
for (const request of initiatorGraph.initiators) {
- if (request === this._request)
+ if (request === this._request) {
continue;
+ }
const node = this.parentView().nodeForRequest(request);
- if (!node)
+ if (!node) {
continue;
+ }
node._setIsOnInitiatorPath(showInitiatorChain);
}
for (const request of initiatorGraph.initiated) {
- if (request === this._request)
+ if (request === this._request) {
continue;
+ }
const node = this.parentView().nodeForRequest(request);
- if (!node)
+ if (!node) {
continue;
+ }
node._setIsOnInitiatedPath(showInitiatorChain);
}
}
@@ -570,8 +608,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
* @param {boolean} isOnInitiatorPath
*/
_setIsOnInitiatorPath(isOnInitiatorPath) {
- if (this._isOnInitiatorPath === isOnInitiatorPath || !this.attached())
+ if (this._isOnInitiatorPath === isOnInitiatorPath || !this.attached()) {
return;
+ }
this._isOnInitiatorPath = isOnInitiatorPath;
this._updateBackgroundColor();
}
@@ -588,8 +627,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
* @param {boolean} isOnInitiatedPath
*/
_setIsOnInitiatedPath(isOnInitiatedPath) {
- if (this._isOnInitiatedPath === isOnInitiatedPath || !this.attached())
+ if (this._isOnInitiatedPath === isOnInitiatedPath || !this.attached()) {
return;
+ }
this._isOnInitiatedPath = isOnInitiatedPath;
this._updateBackgroundColor();
}
@@ -610,8 +650,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
const resourceType = this._request.resourceType();
let simpleType = resourceType.name();
- if (resourceType === Common.resourceTypes.Other || resourceType === Common.resourceTypes.Image)
+ if (resourceType === Common.resourceTypes.Other || resourceType === Common.resourceTypes.Image) {
simpleType = mimeType.replace(/^(application|image)\//, '');
+ }
return simpleType;
}
@@ -762,19 +803,21 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
* @return {!Array.<!Object>}
*/
highlightMatchedSubstring(regexp) {
- if (!regexp)
+ if (!regexp) {
return [];
+ }
// Ensure element is created.
this.element();
const domChanges = [];
const matchInfo = this._nameCell.textContent.match(regexp);
- if (matchInfo)
+ if (matchInfo) {
UI.highlightSearchResult(this._nameCell, matchInfo.index, matchInfo[0].length, domChanges);
+ }
return domChanges;
}
_openInNewTab() {
- InspectorFrontendHost.openInNewTab(this._request.url());
+ Host.InspectorFrontendHost.openInNewTab(this._request.url());
}
/**
@@ -796,14 +839,14 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
let iconElement;
if (this._request.resourceType() === Common.resourceTypes.Image) {
const previewImage = createElementWithClass('img', 'image-network-icon-preview');
- UI.ARIAUtils.setAccessibleName(previewImage, this._request.resourceType().title());
+ previewImage.alt = this._request.resourceType().title();
this._request.populateImageSource(previewImage);
iconElement = createElementWithClass('div', 'icon');
iconElement.appendChild(previewImage);
} else {
iconElement = createElementWithClass('img', 'icon');
- UI.ARIAUtils.setAccessibleName(iconElement, this._request.resourceType().title());
+ iconElement.alt = this._request.resourceType().title();
}
iconElement.classList.add(this._request.resourceType().name());
@@ -889,8 +932,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
const initiator = SDK.networkLog.initiatorInfoForRequest(request);
const timing = request.timing;
- if (timing && timing.pushStart)
+ if (timing && timing.pushStart) {
cell.appendChild(createTextNode(Common.UIString('Push / ')));
+ }
switch (initiator.type) {
case SDK.NetworkRequest.InitiatorType.Parser:
cell.title = initiator.url + ':' + (initiator.lineNumber + 1);
@@ -1031,10 +1075,11 @@ Network.NetworkGroupNode = class extends Network.NetworkNode {
* @param {boolean=} supressSelectedEvent
*/
select(supressSelectedEvent) {
- if (this.expanded) {
- this.collapse();
- return;
+ super.select(supressSelectedEvent);
+ const firstChildNode = this.traverseNextNode(false, true);
+ if (firstChildNode && firstChildNode.request()) {
+ this.parentView().dispatchEventToListeners(
+ Network.NetworkLogView.Events.RequestSelected, firstChildNode.request());
}
- this.expand();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkFrameGrouper.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkFrameGrouper.js
index 0e39df650b9..8fd513230c2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkFrameGrouper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkFrameGrouper.js
@@ -22,11 +22,13 @@ Network.NetworkFrameGrouper = class {
*/
groupNodeForRequest(request) {
const frame = SDK.ResourceTreeModel.frameForRequest(request);
- if (!frame || frame.isTopFrame())
+ if (!frame || frame.isTopFrame()) {
return null;
+ }
let groupNode = this._activeGroups.get(frame);
- if (groupNode)
+ if (groupNode) {
return groupNode;
+ }
groupNode = new Network.FrameGroupNode(this._parentView, frame);
this._activeGroups.set(frame, groupNode);
return groupNode;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkItemView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkItemView.js
index 09955a6c9f9..5ae4dbbc835 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkItemView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkItemView.js
@@ -35,6 +35,7 @@ Network.NetworkItemView = class extends UI.TabbedPane {
*/
constructor(request, calculator) {
super();
+ this._request = request;
this.element.classList.add('network-item-view');
this._resourceViewTabSetting = Common.settings.createSetting('resourceViewTab', 'preview');
@@ -72,18 +73,14 @@ Network.NetworkItemView = class extends UI.TabbedPane {
Common.UIString('Raw response data'));
}
- if (request.requestCookies || request.responseCookies) {
- this._cookiesView = new Network.RequestCookiesView(request);
- this.appendTab(
- Network.NetworkItemView.Tabs.Cookies, Common.UIString('Cookies'), this._cookiesView,
- Common.UIString('Request and response cookies'));
- }
-
this.appendTab(
Network.NetworkItemView.Tabs.Timing, Common.UIString('Timing'),
new Network.RequestTimingView(request, calculator), Common.UIString('Request and response timeline'));
- this._request = request;
+ /** @type {?Network.RequestCookiesView} */
+ this._cookiesView = null;
+ /** @type {?Network.RequestInitiatorView} */
+ this._initiatorView = null;
}
/**
@@ -91,23 +88,62 @@ Network.NetworkItemView = class extends UI.TabbedPane {
*/
wasShown() {
super.wasShown();
+ this._request.addEventListener(
+ SDK.NetworkRequest.Events.RequestHeadersChanged, this._maybeAppendCookiesPanel, this);
+ this._request.addEventListener(
+ SDK.NetworkRequest.Events.ResponseHeadersChanged, this._maybeAppendCookiesPanel, this);
+ this._maybeAppendCookiesPanel();
+ this._maybeAppendInitiatorPanel();
this._selectTab();
}
/**
+ * @override
+ */
+ willHide() {
+ this._request.removeEventListener(
+ SDK.NetworkRequest.Events.RequestHeadersChanged, this._maybeAppendCookiesPanel, this);
+ this._request.removeEventListener(
+ SDK.NetworkRequest.Events.ResponseHeadersChanged, this._maybeAppendCookiesPanel, this);
+ }
+
+ _maybeAppendCookiesPanel() {
+ const cookiesPresent = this._request.requestCookies || this._request.responseCookies;
+ console.assert(cookiesPresent || !this._cookiesView, 'Cookies were introduced in headers and then removed!');
+ if (cookiesPresent && !this._cookiesView) {
+ this._cookiesView = new Network.RequestCookiesView(this._request);
+ this.appendTab(
+ Network.NetworkItemView.Tabs.Cookies, Common.UIString('Cookies'), this._cookiesView,
+ Common.UIString('Request and response cookies'));
+ }
+ }
+
+ _maybeAppendInitiatorPanel() {
+ const initiator = this._request.initiator();
+ if (initiator && initiator.stack && !this._initiatorView) {
+ this._initiatorView = new Network.RequestInitiatorView(this._request);
+ this.appendTab(
+ Network.NetworkItemView.Tabs.Initiator, ls`Initiator`, this._initiatorView, ls`Request initiator call stack`);
+ }
+ }
+
+ /**
* @param {string=} tabId
*/
_selectTab(tabId) {
- if (!tabId)
+ if (!tabId) {
tabId = this._resourceViewTabSetting.get();
+ }
- if (!this.selectTab(tabId))
+ if (!this.selectTab(tabId)) {
this.selectTab('headers');
+ }
}
_tabSelected(event) {
- if (!event.data.isUserGesture)
+ if (!event.data.isUserGesture) {
return;
+ }
this._resourceViewTabSetting.set(event.data.tabId);
}
@@ -124,8 +160,9 @@ Network.NetworkItemView = class extends UI.TabbedPane {
*/
async revealResponseBody(line) {
this._selectTab(Network.NetworkItemView.Tabs.Response);
- if (this._responseView && typeof line === 'number')
+ if (this._responseView && typeof line === 'number') {
await this._responseView.revealLine(/** @type {number} */ (line));
+ }
}
/**
@@ -152,6 +189,7 @@ Network.NetworkItemView.Tabs = {
Cookies: 'cookies',
EventSource: 'eventSource',
Headers: 'headers',
+ Initiator: 'initiator',
Preview: 'preview',
Response: 'response',
Timing: 'timing',
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
index 485d8fd6b59..6bce12d98c4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -194,8 +194,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @return {boolean}
*/
static _requestPathFilter(regex, request) {
- if (!regex)
+ if (!regex) {
return false;
+ }
return regex.test(request.path() + '/' + request.name());
}
@@ -313,14 +314,15 @@ Network.NetworkLogView = class extends UI.VBox {
* @return {boolean}
*/
static _requestMixedContentFilter(value, request) {
- if (value === Network.NetworkLogView.MixedContentFilterValues.Displayed)
+ if (value === Network.NetworkLogView.MixedContentFilterValues.Displayed) {
return request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable;
- else if (value === Network.NetworkLogView.MixedContentFilterValues.Blocked)
+ } else if (value === Network.NetworkLogView.MixedContentFilterValues.Blocked) {
return request.mixedContentType === Protocol.Security.MixedContentType.Blockable && request.wasBlocked();
- else if (value === Network.NetworkLogView.MixedContentFilterValues.BlockOverridden)
+ } else if (value === Network.NetworkLogView.MixedContentFilterValues.BlockOverridden) {
return request.mixedContentType === Protocol.Security.MixedContentType.Blockable && !request.wasBlocked();
- else if (value === Network.NetworkLogView.MixedContentFilterValues.All)
+ } else if (value === Network.NetworkLogView.MixedContentFilterValues.All) {
return request.mixedContentType !== Protocol.Security.MixedContentType.None;
+ }
return false;
}
@@ -342,8 +344,9 @@ Network.NetworkLogView = class extends UI.VBox {
static _requestSetCookieDomainFilter(value, request) {
const cookies = request.responseCookies;
for (let i = 0, l = cookies ? cookies.length : 0; i < l; ++i) {
- if (cookies[i].domain() === value)
+ if (cookies[i].domain() === value) {
return true;
+ }
}
return false;
}
@@ -356,8 +359,9 @@ Network.NetworkLogView = class extends UI.VBox {
static _requestSetCookieNameFilter(value, request) {
const cookies = request.responseCookies;
for (let i = 0, l = cookies ? cookies.length : 0; i < l; ++i) {
- if (cookies[i].name() === value)
+ if (cookies[i].name() === value) {
return true;
+ }
}
return false;
}
@@ -370,8 +374,9 @@ Network.NetworkLogView = class extends UI.VBox {
static _requestSetCookieValueFilter(value, request) {
const cookies = request.responseCookies;
for (let i = 0, l = cookies ? cookies.length : 0; i < l; ++i) {
- if (cookies[i].value() === value)
+ if (cookies[i].value() === value) {
return true;
+ }
}
return false;
}
@@ -409,10 +414,12 @@ Network.NetworkLogView = class extends UI.VBox {
* @return {boolean}
*/
static _requestTimeFilter(windowStart, windowEnd, request) {
- if (request.issueTime() > windowEnd)
+ if (request.issueTime() > windowEnd) {
return false;
- if (request.endTime !== -1 && request.endTime < windowStart)
+ }
+ if (request.endTime !== -1 && request.endTime < windowStart) {
return false;
+ }
return true;
}
@@ -420,14 +427,14 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {!SDK.NetworkRequest} request
*/
static _copyRequestHeaders(request) {
- InspectorFrontendHost.copyText(request.requestHeadersText());
+ Host.InspectorFrontendHost.copyText(request.requestHeadersText());
}
/**
* @param {!SDK.NetworkRequest} request
*/
static _copyResponseHeaders(request) {
- InspectorFrontendHost.copyText(request.responseHeadersText);
+ Host.InspectorFrontendHost.copyText(request.responseHeadersText);
}
/**
@@ -436,11 +443,12 @@ Network.NetworkLogView = class extends UI.VBox {
static async _copyResponse(request) {
const contentData = await request.contentData();
let content = contentData.content || '';
- if (!request.contentType().isTextType())
+ if (!request.contentType().isTextType()) {
content = Common.ContentProvider.contentAsDataURL(content, request.mimeType, contentData.encoded);
- else if (contentData.encoded)
+ } else if (contentData.encoded) {
content = window.atob(content);
- InspectorFrontendHost.copyText(content);
+ }
+ Host.InspectorFrontendHost.copyText(content);
}
/**
@@ -448,11 +456,13 @@ Network.NetworkLogView = class extends UI.VBox {
*/
_handleDrop(dataTransfer) {
const items = dataTransfer.items;
- if (!items.length)
+ if (!items.length) {
return;
+ }
const entry = items[0].webkitGetAsEntry();
- if (entry.isDirectory)
+ if (entry.isDirectory) {
return;
+ }
entry.file(this.onLoadFromFile.bind(this));
}
@@ -490,8 +500,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {?string} groupKey
*/
_setGrouping(groupKey) {
- if (this._activeGroupLookup)
+ if (this._activeGroupLookup) {
this._activeGroupLookup.reset();
+ }
const groupLookup = groupKey ? this._groupLookups.get(groupKey) || null : null;
this._activeGroupLookup = groupLookup;
this._invalidateAllItems();
@@ -533,8 +544,9 @@ Network.NetworkLogView = class extends UI.VBox {
*/
modelAdded(networkManager) {
// TODO(allada) Remove dependency on networkManager and instead use NetworkLog and PageLoad for needed data.
- if (networkManager.target().parentTarget())
+ if (networkManager.target().parentTarget()) {
return;
+ }
const resourceTreeModel = networkManager.target().model(SDK.ResourceTreeModel);
if (resourceTreeModel) {
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.Load, this._loadEventFired, this);
@@ -574,8 +586,9 @@ Network.NetworkLogView = class extends UI.VBox {
}
clearSelection() {
- if (this._dataGrid.selectedNode)
+ if (this._dataGrid.selectedNode) {
this._dataGrid.selectedNode.deselect();
+ }
}
_resetSuggestionBuilder() {
@@ -639,8 +652,9 @@ Network.NetworkLogView = class extends UI.VBox {
}
_hideRecordingHint() {
- if (this._recordingHint)
+ if (this._recordingHint) {
this._recordingHint.remove();
+ }
this._recordingHint = null;
}
@@ -650,7 +664,9 @@ Network.NetworkLogView = class extends UI.VBox {
*/
elementsToRestoreScrollPositionsFor() {
if (!this._dataGrid) // Not initialized yet.
+ {
return [];
+ }
return [this._dataGrid.scrollContainer];
}
@@ -661,8 +677,9 @@ Network.NetworkLogView = class extends UI.VBox {
_setupDataGrid() {
this._dataGrid.setRowContextMenuCallback((contextMenu, node) => {
const request = node.request();
- if (request)
+ if (request) {
this.handleContextMenuForRequest(contextMenu, request);
+ }
});
this._dataGrid.setStickToBottom(true);
this._dataGrid.setName('networkLog');
@@ -695,19 +712,22 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {boolean=} highlightInitiatorChain
*/
_setHoveredNode(node, highlightInitiatorChain) {
- if (this._hoveredNode)
+ if (this._hoveredNode) {
this._hoveredNode.setHovered(false, false);
+ }
this._hoveredNode = node;
- if (this._hoveredNode)
+ if (this._hoveredNode) {
this._hoveredNode.setHovered(true, !!highlightInitiatorChain);
+ }
}
/**
* @param {!Event} event
*/
_dataGridMouseDown(event) {
- if (!this._dataGrid.selectedNode && event.button)
+ if (!this._dataGrid.selectedNode && event.button) {
event.consume();
+ }
}
_updateSummaryBar() {
@@ -724,8 +744,9 @@ Network.NetworkLogView = class extends UI.VBox {
let nodeCount = 0;
for (const request of SDK.networkLog.requests()) {
const node = request[Network.NetworkLogView._networkNodeSymbol];
- if (!node)
+ if (!node) {
continue;
+ }
nodeCount++;
const requestTransferSize = request.transferSize;
transferSize += requestTransferSize;
@@ -740,10 +761,12 @@ Network.NetworkLogView = class extends UI.VBox {
// TODO(allada) inspectedURL should be stored in PageLoad used instead of target so HAR requests can have an
// inspected url.
if (networkManager && request.url() === networkManager.target().inspectedURL() &&
- request.resourceType() === Common.resourceTypes.Document && !networkManager.target().parentTarget())
+ request.resourceType() === Common.resourceTypes.Document && !networkManager.target().parentTarget()) {
baseTime = request.startTime;
- if (request.endTime > maxTime)
+ }
+ if (request.endTime > maxTime) {
maxTime = request.endTime;
+ }
}
if (!nodeCount) {
@@ -800,13 +823,15 @@ Network.NetworkLogView = class extends UI.VBox {
}
scheduleRefresh() {
- if (this._needsRefresh)
+ if (this._needsRefresh) {
return;
+ }
this._needsRefresh = true;
- if (this.isShowing() && !this._refreshRequestId)
+ if (this.isShowing() && !this._refreshRequestId) {
this._refreshRequestId = this.element.window().requestAnimationFrame(this._refresh.bind(this));
+ }
}
/**
@@ -828,8 +853,9 @@ Network.NetworkLogView = class extends UI.VBox {
}
_refreshIfNeeded() {
- if (this._needsRefresh)
+ if (this._needsRefresh) {
this._refresh();
+ }
}
/**
@@ -837,10 +863,11 @@ Network.NetworkLogView = class extends UI.VBox {
*/
_invalidateAllItems(deferUpdate) {
this._staleRequests = new Set(SDK.networkLog.requests());
- if (deferUpdate)
+ if (deferUpdate) {
this.scheduleRefresh();
- else
+ } else {
this._refresh();
+ }
}
/**
@@ -861,8 +888,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {!Network.NetworkTimeCalculator} x
*/
setCalculator(x) {
- if (!x || this._calculator === x)
+ if (!x || this._calculator === x) {
return;
+ }
if (this._calculator !== x) {
this._calculator = x;
@@ -870,10 +898,11 @@ Network.NetworkLogView = class extends UI.VBox {
}
this._calculator.reset();
- if (this._calculator.startAtZero)
+ if (this._calculator.startAtZero) {
this._columns.hideEventDividers();
- else
+ } else {
this._columns.showEventDividers();
+ }
this._invalidateAllItems();
}
@@ -882,8 +911,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_loadEventFired(event) {
- if (!this._recording)
+ if (!this._recording) {
return;
+ }
const time = /** @type {number} */ (event.data.loadTime);
if (time) {
@@ -896,8 +926,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_domContentLoadedEventFired(event) {
- if (!this._recording)
+ if (!this._recording) {
return;
+ }
const data = /** @type {number} */ (event.data);
if (data) {
this._mainRequestDOMContentLoadedTime = data;
@@ -967,24 +998,28 @@ Network.NetworkLogView = class extends UI.VBox {
const request = this._staleRequests.firstValue();
this._staleRequests.delete(request);
let node = request[Network.NetworkLogView._networkNodeSymbol];
- if (!node)
+ if (!node) {
node = this._createNodeForRequest(request);
+ }
staleNodes.add(node);
}
for (const node of staleNodes) {
const isFilteredOut = !this._applyFilter(node);
- if (isFilteredOut && node === this._hoveredNode)
+ if (isFilteredOut && node === this._hoveredNode) {
this._setHoveredNode(null);
+ }
- if (!isFilteredOut)
+ if (!isFilteredOut) {
nodesToRefresh.push(node);
+ }
const request = node.request();
this._timeCalculator.updateBoundaries(request);
this._durationCalculator.updateBoundaries(request);
const newParent = this._parentNodeForInsert(node);
- if (node[Network.NetworkLogView._isFilteredOutSymbol] === isFilteredOut && node.parent === newParent)
+ if (node[Network.NetworkLogView._isFilteredOutSymbol] === isFilteredOut && node.parent === newParent) {
continue;
+ }
node[Network.NetworkLogView._isFilteredOutSymbol] = isFilteredOut;
const removeFromParent = node.parent && (isFilteredOut || node.parent !== newParent);
if (removeFromParent) {
@@ -997,8 +1032,9 @@ Network.NetworkLogView = class extends UI.VBox {
}
}
- if (!newParent || isFilteredOut)
+ if (!newParent || isFilteredOut) {
continue;
+ }
if (!newParent.dataGrid && !nodesToInsert.has(newParent)) {
nodesToInsert.set(newParent, this._dataGrid.rootNode());
@@ -1007,16 +1043,19 @@ Network.NetworkLogView = class extends UI.VBox {
nodesToInsert.set(node, newParent);
}
- for (const node of nodesToInsert.keys())
+ for (const node of nodesToInsert.keys()) {
nodesToInsert.get(node).appendChild(node);
+ }
- for (const node of nodesToRefresh)
+ for (const node of nodesToRefresh) {
node.refresh();
+ }
this._updateSummaryBar();
- if (nodesToInsert.size)
+ if (nodesToInsert.size) {
this._columns.sortByCurrentColumn();
+ }
this._dataGrid.updateInstantly();
this._didRefreshForTest();
@@ -1030,12 +1069,14 @@ Network.NetworkLogView = class extends UI.VBox {
* @return {?Network.NetworkNode}
*/
_parentNodeForInsert(node) {
- if (!this._activeGroupLookup)
+ if (!this._activeGroupLookup) {
return this._dataGrid.rootNode();
+ }
const groupNode = this._activeGroupLookup.groupNodeForRequest(node.request());
- if (!groupNode)
+ if (!groupNode) {
return this._dataGrid.rootNode();
+ }
return groupNode;
}
@@ -1052,8 +1093,9 @@ Network.NetworkLogView = class extends UI.VBox {
this.linkifier.reset();
this.badgePool.reset();
- if (this._activeGroupLookup)
+ if (this._activeGroupLookup) {
this._activeGroupLookup.reset();
+ }
this._staleRequests.clear();
this._resetSuggestionBuilder();
@@ -1083,8 +1125,9 @@ Network.NetworkLogView = class extends UI.VBox {
request[Network.NetworkLogView._networkNodeSymbol] = node;
node[Network.NetworkLogView._isFilteredOutSymbol] = true;
- for (let redirect = request.redirectSource(); redirect; redirect = redirect.redirectSource())
+ for (let redirect = request.redirectSource(); redirect; redirect = redirect.redirectSource()) {
this._refreshRequest(redirect);
+ }
return node;
}
@@ -1131,8 +1174,9 @@ Network.NetworkLogView = class extends UI.VBox {
}
const responseHeaders = request.responseHeaders;
- for (let i = 0, l = responseHeaders.length; i < l; ++i)
+ for (let i = 0, l = responseHeaders.length; i < l; ++i) {
this._suggestionBuilder.addItem(Network.NetworkLogView.FilterType.HasResponseHeader, responseHeaders[i].name);
+ }
const cookies = request.responseCookies;
for (let i = 0, l = cookies ? cookies.length : 0; i < l; ++i) {
const cookie = cookies[i];
@@ -1169,7 +1213,8 @@ Network.NetworkLogView = class extends UI.VBox {
const footerSection = copyMenu.footerSection();
if (request) {
copyMenu.defaultSection().appendItem(
- UI.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, request.contentURL()));
+ UI.copyLinkAddressLabel(),
+ Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, request.contentURL()));
if (request.requestHeadersText()) {
copyMenu.defaultSection().appendItem(
Common.UIString('Copy request headers'), Network.NetworkLogView._copyRequestHeaders.bind(null, request));
@@ -1224,6 +1269,25 @@ Network.NetworkLogView = class extends UI.VBox {
const manager = SDK.multitargetNetworkManager;
let patterns = manager.blockedPatterns();
+ /**
+ * @param {string} url
+ */
+ function addBlockedURL(url) {
+ patterns.push({enabled: true, url: url});
+ manager.setBlockedPatterns(patterns);
+ manager.setBlockingEnabled(true);
+ UI.viewManager.showView('network.blocked-urls');
+ }
+
+ /**
+ * @param {string} url
+ */
+ function removeBlockedURL(url) {
+ patterns = patterns.filter(pattern => pattern.url !== url);
+ manager.setBlockedPatterns(patterns);
+ UI.viewManager.showView('network.blocked-urls');
+ }
+
const urlWithoutScheme = request.parsedURL.urlWithoutScheme();
if (urlWithoutScheme && !patterns.find(pattern => pattern.url === urlWithoutScheme)) {
contextMenu.debugSection().appendItem(
@@ -1248,25 +1312,6 @@ Network.NetworkLogView = class extends UI.VBox {
contextMenu.debugSection().appendItem(
Common.UIString('Replay XHR'), SDK.NetworkManager.replayRequest.bind(null, request));
}
-
- /**
- * @param {string} url
- */
- function addBlockedURL(url) {
- patterns.push({enabled: true, url: url});
- manager.setBlockedPatterns(patterns);
- manager.setBlockingEnabled(true);
- UI.viewManager.showView('network.blocked-urls');
- }
-
- /**
- * @param {string} url
- */
- function removeBlockedURL(url) {
- patterns = patterns.filter(pattern => pattern.url !== url);
- manager.setBlockedPatterns(patterns);
- UI.viewManager.showView('network.blocked-urls');
- }
}
}
@@ -1279,7 +1324,7 @@ Network.NetworkLogView = class extends UI.VBox {
async _copyAll() {
const harArchive = {log: await SDK.HARLog.build(this._harRequests())};
- InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2));
+ Host.InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2));
}
/**
@@ -1288,7 +1333,7 @@ Network.NetworkLogView = class extends UI.VBox {
*/
async _copyCurlCommand(request, platform) {
const command = await this._generateCurlCommand(request, platform);
- InspectorFrontendHost.copyText(command);
+ Host.InspectorFrontendHost.copyText(command);
}
/**
@@ -1296,7 +1341,7 @@ Network.NetworkLogView = class extends UI.VBox {
*/
async _copyAllCurlCommand(platform) {
const commands = await this._generateAllCurlCommand(SDK.networkLog.requests(), platform);
- InspectorFrontendHost.copyText(commands);
+ Host.InspectorFrontendHost.copyText(commands);
}
/**
@@ -1305,12 +1350,12 @@ Network.NetworkLogView = class extends UI.VBox {
*/
async _copyFetchCall(request, platform) {
const command = await this._generateFetchCall(request);
- InspectorFrontendHost.copyText(command);
+ Host.InspectorFrontendHost.copyText(command);
}
async _copyAllFetchCall() {
const commands = await this._generateAllFetchCall(SDK.networkLog.requests());
- InspectorFrontendHost.copyText(commands);
+ Host.InspectorFrontendHost.copyText(commands);
}
/**
@@ -1318,12 +1363,12 @@ Network.NetworkLogView = class extends UI.VBox {
*/
async _copyPowerShellCommand(request) {
const command = await this._generatePowerShellCommand(request);
- InspectorFrontendHost.copyText(command);
+ Host.InspectorFrontendHost.copyText(command);
}
async _copyAllPowerShellCommand() {
- const commands = this._generateAllPowerShellCommand(SDK.networkLog.requests());
- InspectorFrontendHost.copyText(commands);
+ const commands = await this._generateAllPowerShellCommand(SDK.networkLog.requests());
+ Host.InspectorFrontendHost.copyText(commands);
}
async exportAll() {
@@ -1332,8 +1377,9 @@ Network.NetworkLogView = class extends UI.VBox {
const filename = parsedURL ? parsedURL.host : 'network-log';
const stream = new Bindings.FileOutputStream();
- if (!await stream.open(filename + '.har'))
+ if (!await stream.open(filename + '.har')) {
return;
+ }
const progressIndicator = new UI.ProgressIndicator();
this._progressBarContainer.appendChild(progressIndicator.element);
@@ -1343,19 +1389,22 @@ Network.NetworkLogView = class extends UI.VBox {
}
_clearBrowserCache() {
- if (confirm(Common.UIString('Are you sure you want to clear browser cache?')))
+ if (confirm(Common.UIString('Are you sure you want to clear browser cache?'))) {
SDK.multitargetNetworkManager.clearBrowserCache();
+ }
}
_clearBrowserCookies() {
- if (confirm(Common.UIString('Are you sure you want to clear browser cookies?')))
+ if (confirm(Common.UIString('Are you sure you want to clear browser cookies?'))) {
SDK.multitargetNetworkManager.clearBrowserCookies();
+ }
}
_removeAllHighlights() {
this.removeAllNodeHighlights();
- for (let i = 0; i < this._highlightedSubstringChanges.length; ++i)
+ for (let i = 0; i < this._highlightedSubstringChanges.length; ++i) {
UI.revertDomChanges(this._highlightedSubstringChanges[i]);
+ }
this._highlightedSubstringChanges = [];
}
@@ -1365,18 +1414,23 @@ Network.NetworkLogView = class extends UI.VBox {
*/
_applyFilter(node) {
const request = node.request();
- if (this._timeFilter && !this._timeFilter(request))
+ if (this._timeFilter && !this._timeFilter(request)) {
return false;
+ }
const categoryName = request.resourceType().category().title;
- if (!this._resourceCategoryFilterUI.accept(categoryName))
+ if (!this._resourceCategoryFilterUI.accept(categoryName)) {
return false;
- if (this._dataURLFilterUI.checked() && (request.parsedURL.isDataURL() || request.parsedURL.isBlobURL()))
+ }
+ if (this._dataURLFilterUI.checked() && (request.parsedURL.isDataURL() || request.parsedURL.isBlobURL())) {
return false;
- if (request.statusText === 'Service Worker Fallback Required')
+ }
+ if (request.statusText === 'Service Worker Fallback Required') {
return false;
+ }
for (let i = 0; i < this._filters.length; ++i) {
- if (!this._filters[i](request))
+ if (!this._filters[i](request)) {
return false;
+ }
}
return true;
}
@@ -1418,14 +1472,18 @@ Network.NetworkLogView = class extends UI.VBox {
return Network.NetworkLogView._requestResponseHeaderFilter.bind(null, value);
case Network.NetworkLogView.FilterType.Is:
- if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.Running)
+ if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.Running) {
return Network.NetworkLogView._runningRequestFilter;
- if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.FromCache)
+ }
+ if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.FromCache) {
return Network.NetworkLogView._fromCacheRequestFilter;
- if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.ServiceWorkerIntercepted)
+ }
+ if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.ServiceWorkerIntercepted) {
return Network.NetworkLogView._interceptedByServiceWorkerFilter;
- if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.ServiceWorkerInitiated)
+ }
+ if (value.toLowerCase() === Network.NetworkLogView.IsFilterType.ServiceWorkerInitiated) {
return Network.NetworkLogView._initiatedByServiceWorkerFilter;
+ }
break;
case Network.NetworkLogView.FilterType.LargerThan:
@@ -1476,8 +1534,9 @@ Network.NetworkLogView = class extends UI.VBox {
value = value.substring(0, value.length - 1);
}
const quantity = Number(value);
- if (isNaN(quantity))
+ if (isNaN(quantity)) {
return null;
+ }
return Network.NetworkLogView._requestSizeLargerThanFilter.bind(null, quantity * multiplier);
}
@@ -1493,8 +1552,9 @@ Network.NetworkLogView = class extends UI.VBox {
_reveal(request) {
this.removeAllNodeHighlights();
const node = request[Network.NetworkLogView._networkNodeSymbol];
- if (!node || !node.dataGrid)
+ if (!node || !node.dataGrid) {
return null;
+ }
node.reveal();
return node;
}
@@ -1504,8 +1564,9 @@ Network.NetworkLogView = class extends UI.VBox {
*/
revealAndHighlightRequest(request) {
const node = this._reveal(request);
- if (node)
+ if (node) {
this._highlightNode(node);
+ }
}
/**
@@ -1514,8 +1575,9 @@ Network.NetworkLogView = class extends UI.VBox {
selectRequest(request) {
this.setTextFilterValue('');
const node = this._reveal(request);
- if (node)
+ if (node) {
node.select();
+ }
}
removeAllNodeHighlights() {
@@ -1587,15 +1649,17 @@ Network.NetworkLogView = class extends UI.VBox {
const headerData = requestHeaders.reduce((result, header) => {
const name = header.name;
- if (!ignoredHeaders[name.toLowerCase()] && !name.includes(':'))
+ if (!ignoredHeaders[name.toLowerCase()] && !name.includes(':')) {
result.append(name, header.value);
+ }
return result;
}, new Headers());
const headers = {};
- for (const headerArray of headerData)
+ for (const headerArray of headerData) {
headers[headerArray[0]] = headerArray[1];
+ }
const credentials =
request.requestCookies || requestHeaders.some(({name}) => credentialHeaders[name.toLowerCase()]) ? 'include' :
@@ -1695,8 +1759,9 @@ Network.NetworkLogView = class extends UI.VBox {
let hexString = code.toString(16);
// Zero pad to four digits to comply with ANSI-C Quoting:
// http://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html
- while (hexString.length < 4)
+ while (hexString.length < 4) {
hexString = '0' + hexString;
+ }
return '\\u' + hexString;
}
@@ -1747,16 +1812,18 @@ Network.NetworkLogView = class extends UI.VBox {
for (let i = 0; i < requestHeaders.length; i++) {
const header = requestHeaders[i];
const name = header.name.replace(/^:/, ''); // Translate SPDY v3 headers to HTTP headers.
- if (name.toLowerCase() in ignoredHeaders)
+ if (name.toLowerCase() in ignoredHeaders) {
continue;
+ }
command.push('-H');
command.push(escapeString(name + ': ' + header.value));
}
command = command.concat(data);
command.push('--compressed');
- if (request.securityState() === Protocol.Security.SecurityState.Insecure)
+ if (request.securityState() === Protocol.Security.SecurityState.Insecure) {
command.push('--insecure');
+ }
return command.join(' ');
}
@@ -1768,10 +1835,11 @@ Network.NetworkLogView = class extends UI.VBox {
async _generateAllCurlCommand(requests, platform) {
const nonBlobRequests = this._filterOutBlobRequests(requests);
const commands = await Promise.all(nonBlobRequests.map(request => this._generateCurlCommand(request, platform)));
- if (platform === 'win')
+ if (platform === 'win') {
return commands.join(' &\r\n');
- else
+ } else {
return commands.join(' ;\n');
+ }
}
/**
@@ -1804,8 +1872,9 @@ Network.NetworkLogView = class extends UI.VBox {
const headerNameValuePairs = [];
for (const header of requestHeaders) {
const name = header.name.replace(/^:/, ''); // Translate h2 headers to HTTP headers.
- if (ignoredHeaders.has(name.toLowerCase()))
+ if (ignoredHeaders.has(name.toLowerCase())) {
continue;
+ }
headerNameValuePairs.push(escapeString(name) + '=' + escapeString(header.value));
}
if (headerNameValuePairs.length) {
@@ -1823,10 +1892,11 @@ Network.NetworkLogView = class extends UI.VBox {
if (formData) {
command.push('-Body');
const body = escapeString(formData);
- if (/[^\x20-\x7E]/.test(formData))
+ if (/[^\x20-\x7E]/.test(formData)) {
command.push('([System.Text.Encoding]::UTF8.GetBytes(' + body + '))');
- else
+ } else {
command.push(body);
+ }
}
return command.join(' ');
@@ -1846,8 +1916,9 @@ Network.NetworkLogView = class extends UI.VBox {
* @return {string}
*/
static getDCLEventColor() {
- if (UI.themeSupport.themeName() === 'dark')
+ if (UI.themeSupport.themeName() === 'dark') {
return '#03A9F4';
+ }
return '#0867CB';
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
index 938940e45c5..ca2d64ada40 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
@@ -70,8 +70,9 @@ Network.NetworkLogViewColumns = class {
}
reset() {
- if (this._popoverHelper)
+ if (this._popoverHelper) {
this._popoverHelper.hidePopover();
+ }
this._eventDividers.clear();
}
@@ -85,8 +86,9 @@ Network.NetworkLogViewColumns = class {
const columnConfig = /** @type {!Network.NetworkLogViewColumns.Descriptor} */ (
Object.assign({}, defaultColumnConfig, currentConfigColumn));
columnConfig.id = columnConfig.id;
- if (columnConfig.subtitle)
+ if (columnConfig.subtitle) {
columnConfig.titleDOMFragment = this._makeHeaderFragment(columnConfig.title, columnConfig.subtitle);
+ }
this._columns.push(columnConfig);
}
this._loadCustomColumnsAndSettings();
@@ -99,8 +101,9 @@ Network.NetworkLogViewColumns = class {
this._dataGrid =
new DataGrid.SortableDataGrid(this._columns.map(Network.NetworkLogViewColumns._convertToDataGridDescriptor));
this._dataGrid.element.addEventListener('mousedown', event => {
- if (!this._dataGrid.selectedNode && event.button)
+ if (!this._dataGrid.selectedNode && event.button) {
event.consume();
+ }
}, true);
this._dataGridScroller = this._dataGrid.scrollContainer;
@@ -150,11 +153,13 @@ Network.NetworkLogViewColumns = class {
*/
function handleContextMenu(event) {
const node = this._waterfallColumn.getNodeFromPoint(event.offsetX, event.offsetY);
- if (!node)
+ if (!node) {
return;
+ }
const request = node.request();
- if (!request)
+ if (!request) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
this._networkLogView.handleContextMenuForRequest(contextMenu, request);
contextMenu.show();
@@ -166,8 +171,9 @@ Network.NetworkLogViewColumns = class {
* @param {!Event} event
*/
_onMouseWheel(shouldConsume, event) {
- if (shouldConsume)
+ if (shouldConsume) {
event.consume(true);
+ }
const hasRecentWheel = Date.now() - this._lastWheelTime < 80;
this._activeScroller.scrollBy({top: -event.wheelDeltaY, behavior: hasRecentWheel ? 'instant' : 'smooth'});
this._syncScrollers();
@@ -175,8 +181,9 @@ Network.NetworkLogViewColumns = class {
}
_syncScrollers() {
- if (!this._waterfallColumn.isShowing())
+ if (!this._waterfallColumn.isShowing()) {
return;
+ }
this._waterfallScrollerContent.style.height = this._dataGridScroller.scrollHeight + 'px';
this._updateScrollerWidthIfNeeded();
this._dataGridScroller.scrollTop = this._waterfallScroller.scrollTop;
@@ -272,10 +279,11 @@ Network.NetworkLogViewColumns = class {
this._networkLogView.removeAllNodeHighlights();
this._waterfallRequestsAreStale = true;
if (columnId === 'waterfall') {
- if (this._dataGrid.sortOrder() === DataGrid.DataGrid.Order.Ascending)
+ if (this._dataGrid.sortOrder() === DataGrid.DataGrid.Order.Ascending) {
this._waterfallColumnSortIcon.setIconType('smallicon-triangle-up');
- else
+ } else {
this._waterfallColumnSortIcon.setIconType('smallicon-triangle-down');
+ }
const sortFunction = Network.NetworkRequestNode.RequestPropertyComparator.bind(null, this._activeWaterfallSortId);
this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscending());
@@ -285,8 +293,9 @@ Network.NetworkLogViewColumns = class {
this._waterfallColumnSortIcon.setIconType('');
const columnConfig = this._columns.find(columnConfig => columnConfig.id === columnId);
- if (!columnConfig || !columnConfig.sortingFunction)
+ if (!columnConfig || !columnConfig.sortingFunction) {
return;
+ }
this._dataGrid.sortNodes(columnConfig.sortingFunction, !this._dataGrid.isSortOrderAscending());
this._dataGridSortedForTest();
@@ -296,12 +305,14 @@ Network.NetworkLogViewColumns = class {
}
_updateColumns() {
- if (!this._dataGrid)
+ if (!this._dataGrid) {
return;
+ }
const visibleColumns = /** @type {!Object.<string, boolean>} */ ({});
if (this._gridMode) {
- for (const columnConfig of this._columns)
+ for (const columnConfig of this._columns) {
visibleColumns[columnConfig.id] = columnConfig.visible;
+ }
} else {
visibleColumns.name = true;
}
@@ -312,13 +323,15 @@ Network.NetworkLogViewColumns = class {
* @param {boolean} gridMode
*/
switchViewMode(gridMode) {
- if (this._gridMode === gridMode)
+ if (this._gridMode === gridMode) {
return;
+ }
this._gridMode = gridMode;
if (gridMode) {
- if (this._dataGrid.selectedNode)
+ if (this._dataGrid.selectedNode) {
this._dataGrid.selectedNode.selected = false;
+ }
this._splitWidget.showBoth();
this._activeScroller = this._waterfallScroller;
this._waterfallScroller.scrollTop = this._dataGridScroller.scrollTop;
@@ -346,8 +359,9 @@ Network.NetworkLogViewColumns = class {
_saveColumnsSettings() {
const saveableSettings = {};
- for (const columnConfig of this._columns)
+ for (const columnConfig of this._columns) {
saveableSettings[columnConfig.id] = {visible: columnConfig.visible, title: columnConfig.title};
+ }
this._persistantSettings.set(saveableSettings);
}
@@ -358,12 +372,15 @@ Network.NetworkLogViewColumns = class {
for (const columnId of columnIds) {
const setting = savedSettings[columnId];
let columnConfig = this._columns.find(columnConfig => columnConfig.id === columnId);
- if (!columnConfig)
+ if (!columnConfig) {
columnConfig = this._addCustomHeader(setting.title, columnId);
- if (columnConfig.hideable && typeof setting.visible === 'boolean')
+ }
+ if (columnConfig.hideable && typeof setting.visible === 'boolean') {
columnConfig.visible = !!setting.visible;
- if (typeof setting.title === 'string')
+ }
+ if (typeof setting.title === 'string') {
columnConfig.title = setting.title;
+ }
}
}
@@ -428,8 +445,9 @@ Network.NetworkLogViewColumns = class {
function setWaterfallMode(sortId) {
let calculator = this._calculatorsMap.get(Network.NetworkLogViewColumns._calculatorTypes.Time);
const waterfallSortIds = Network.NetworkLogViewColumns.WaterfallSortIds;
- if (sortId === waterfallSortIds.Duration || sortId === waterfallSortIds.Latency)
+ if (sortId === waterfallSortIds.Duration || sortId === waterfallSortIds.Latency) {
calculator = this._calculatorsMap.get(Network.NetworkLogViewColumns._calculatorTypes.Duration);
+ }
this._networkLogView.setCalculator(calculator);
this._activeWaterfallSortId = sortId;
@@ -441,8 +459,9 @@ Network.NetworkLogViewColumns = class {
_manageCustomHeaderDialog() {
const customHeaders = [];
for (const columnConfig of this._columns) {
- if (columnConfig.isResponseHeader)
+ if (columnConfig.isResponseHeader) {
customHeaders.push({title: columnConfig.title, editable: columnConfig.isCustomHeader});
+ }
}
const manageCustomHeaders = new Network.NetworkManageCustomHeadersView(
customHeaders, headerTitle => !!this._addCustomHeader(headerTitle), this._changeCustomHeader.bind(this),
@@ -460,8 +479,9 @@ Network.NetworkLogViewColumns = class {
_removeCustomHeader(headerId) {
headerId = headerId.toLowerCase();
const index = this._columns.findIndex(columnConfig => columnConfig.id === headerId);
- if (index === -1)
+ if (index === -1) {
return false;
+ }
this._columns.splice(index, 1);
this._dataGrid.removeColumn(headerId);
this._saveColumnsSettings();
@@ -476,14 +496,17 @@ Network.NetworkLogViewColumns = class {
* @return {?Network.NetworkLogViewColumns.Descriptor}
*/
_addCustomHeader(headerTitle, headerId, index) {
- if (!headerId)
+ if (!headerId) {
headerId = headerTitle.toLowerCase();
- if (index === undefined)
+ }
+ if (index === undefined) {
index = this._columns.length - 1;
+ }
const currentColumnConfig = this._columns.find(columnConfig => columnConfig.id === headerId);
- if (currentColumnConfig)
+ if (currentColumnConfig) {
return null;
+ }
const columnConfig = /** @type {!Network.NetworkLogViewColumns.Descriptor} */ (
Object.assign({}, Network.NetworkLogViewColumns._defaultColumnConfig, {
@@ -495,8 +518,9 @@ Network.NetworkLogViewColumns = class {
sortingFunction: Network.NetworkRequestNode.ResponseHeaderStringComparator.bind(null, headerId)
}));
this._columns.splice(index, 0, columnConfig);
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.addColumn(Network.NetworkLogViewColumns._convertToDataGridDescriptor(columnConfig), index);
+ }
this._saveColumnsSettings();
this._updateColumns();
return columnConfig;
@@ -509,15 +533,17 @@ Network.NetworkLogViewColumns = class {
* @return {boolean}
*/
_changeCustomHeader(oldHeaderId, newHeaderTitle, newHeaderId) {
- if (!newHeaderId)
+ if (!newHeaderId) {
newHeaderId = newHeaderTitle.toLowerCase();
+ }
oldHeaderId = oldHeaderId.toLowerCase();
const oldIndex = this._columns.findIndex(columnConfig => columnConfig.id === oldHeaderId);
const oldColumnConfig = this._columns[oldIndex];
const currentColumnConfig = this._columns.find(columnConfig => columnConfig.id === newHeaderId);
- if (!oldColumnConfig || (currentColumnConfig && oldHeaderId !== newHeaderId))
+ if (!oldColumnConfig || (currentColumnConfig && oldHeaderId !== newHeaderId)) {
return false;
+ }
this._removeCustomHeader(oldHeaderId);
this._addCustomHeader(newHeaderTitle, newHeaderId, oldIndex);
@@ -529,25 +555,27 @@ Network.NetworkLogViewColumns = class {
* @return {?UI.PopoverRequest}
*/
_getPopoverRequest(event) {
- if (!this._gridMode)
+ if (!this._gridMode) {
return null;
+ }
const hoveredNode = this._networkLogView.hoveredNode();
- if (!hoveredNode)
+ if (!hoveredNode) {
return null;
+ }
const anchor = event.target.enclosingNodeOrSelfWithClass('network-script-initiated');
- if (!anchor)
+ if (!anchor) {
return null;
+ }
const request = hoveredNode.request();
- const initiator = request ? request.initiator() : null;
- if (!initiator || !initiator.stack)
+ if (!request) {
return null;
+ }
return {
box: anchor.boxInWindow(),
show: popover => {
- const manager = anchor.request ? SDK.NetworkManager.forRequest(anchor.request) : null;
- const content = Components.JSPresentationUtils.buildStackTracePreviewContents(
- manager ? manager.target() : null, this._popupLinkifier, initiator.stack,
+ const content = Network.RequestInitiatorView.createStackTracePreview(
+ /** @type {!SDK.NetworkRequest} */ (request), this._popupLinkifier, false,
() => popover.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent));
popover.contentElement.appendChild(content.element);
return Promise.resolve(true);
@@ -749,7 +777,9 @@ Network.NetworkLogViewColumns._defaultColumns = [
{
id: 'connection',
isResponseHeader: true,
- title: Common.UIString('Connection'),
+ // until IDs are supported for strings, the placeholder is used to workaround the limitation that
+ // having multiple translations for a string is not supported
+ title: ls`${'Connection'}`,
sortingFunction: Network.NetworkRequestNode.ResponseHeaderStringComparator.bind(null, 'connection')
},
{
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkManageCustomHeadersView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkManageCustomHeadersView.js
index 811684f4df6..3965abc2a67 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkManageCustomHeadersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkManageCustomHeadersView.js
@@ -93,15 +93,18 @@ Network.NetworkManageCustomHeadersView = class extends UI.VBox {
commitEdit(item, editor, isNew) {
const headerId = editor.control('header').value.trim();
let success;
- if (isNew)
+ if (isNew) {
success = this._addHeaderColumnCallback(headerId);
- else
+ } else {
success = this._changeHeaderColumnCallback(item.header, headerId);
+ }
- if (success && !isNew)
+ if (success && !isNew) {
this._columnConfigs.delete(item.header.toLowerCase());
- if (success)
+ }
+ if (success) {
this._columnConfigs.set(headerId.toLowerCase(), {title: headerId, editable: true});
+ }
this._headersUpdated();
}
@@ -121,8 +124,9 @@ Network.NetworkManageCustomHeadersView = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -147,8 +151,9 @@ Network.NetworkManageCustomHeadersView = class extends UI.VBox {
function validateHeader(item, index, input) {
let valid = true;
const headerId = editor.control('header').value.trim().toLowerCase();
- if (this._columnConfigs.has(headerId) && item.header !== headerId)
+ if (this._columnConfigs.has(headerId) && item.header !== headerId) {
valid = false;
+ }
return {valid};
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkOverview.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkOverview.js
index bcefb83c0fb..a06ec9faf74 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkOverview.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkOverview.js
@@ -49,8 +49,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
*/
_loadEventFired(event) {
const time = /** @type {number} */ (event.data.loadTime);
- if (time)
+ if (time) {
this._loadEvents.push(time * 1000);
+ }
this.scheduleUpdate();
}
@@ -59,8 +60,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
*/
_domContentLoadedEventFired(event) {
const data = /** @type {number} */ (event.data);
- if (data)
+ if (data) {
this._domContentLoadedEvents.push(data * 1000);
+ }
this.scheduleUpdate();
}
@@ -69,10 +71,12 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
* @return {number}
*/
_bandId(connectionId) {
- if (!connectionId || connectionId === '0')
+ if (!connectionId || connectionId === '0') {
return -1;
- if (this._bandMap.has(connectionId))
+ }
+ if (this._bandMap.has(connectionId)) {
return /** @type {number} */ (this._bandMap.get(connectionId));
+ }
const result = this._nextBand++;
this._bandMap.set(connectionId, result);
return result;
@@ -141,8 +145,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
* @protected
*/
scheduleUpdate() {
- if (this._updateScheduled || !this.isShowing())
+ if (this._updateScheduled || !this.isShowing()) {
return;
+ }
this._updateScheduled = true;
this.element.window().requestAnimationFrame(this.update.bind(this));
}
@@ -158,8 +163,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
const newBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
if (!this._lastBoundary || !newBoundary.equals(this._lastBoundary)) {
const span = calculator.boundarySpan();
- while (this._span < span)
+ while (this._span < span) {
this._span *= 1.25;
+ }
calculator.setBounds(calculator.minimumBoundary(), calculator.minimumBoundary() + this._span);
this._lastBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
@@ -175,8 +181,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
*/
function drawLines(type, strokeStyle) {
const lines = linesByType[type];
- if (!lines)
+ if (!lines) {
return;
+ }
const n = lines.length;
context.beginPath();
context.strokeStyle = strokeStyle;
@@ -184,8 +191,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
const y = lines[i++] * Network.NetworkOverview._bandHeight + paddingTop;
const startTime = lines[i++];
let endTime = lines[i++];
- if (endTime === Number.MAX_VALUE)
+ if (endTime === Number.MAX_VALUE) {
endTime = calculator.maximumBoundary();
+ }
context.moveTo(calculator.computePosition(startTime), y);
context.lineTo(calculator.computePosition(endTime) + 1, y);
}
@@ -217,8 +225,9 @@ Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
Network.RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());
for (let j = 0; j < timeRanges.length; ++j) {
const type = timeRanges[j].name;
- if (band !== -1 || type === Network.RequestTimeRangeNames.Total)
+ if (band !== -1 || type === Network.RequestTimeRangeNames.Total) {
addLine(type, y, timeRanges[j].start * 1000, timeRanges[j].end * 1000);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
index afc839c4414..5ead7e0ffdb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
@@ -98,8 +98,9 @@ Network.NetworkPanel = class extends UI.Panel {
tabbedPane.setMinimumSize(100, 25);
tabbedPane.element.classList.add('network-tabbed-pane');
tabbedPane.element.addEventListener('keydown', event => {
- if (event.key !== 'Escape')
+ if (event.key !== 'Escape') {
return;
+ }
splitWidget.hideSidebar();
event.consume();
});
@@ -160,8 +161,9 @@ Network.NetworkPanel = class extends UI.Panel {
static revealAndFilter(filters) {
const panel = Network.NetworkPanel._instance();
let filterString = '';
- for (const filter of filters)
+ for (const filter of filters) {
filterString += `${filter.filterType}:${filter.filterValue} `;
+ }
panel._networkLogView.setTextFilterValue(filterString);
UI.viewManager.showView('network');
}
@@ -190,7 +192,7 @@ Network.NetworkPanel = class extends UI.Panel {
}
_setupToolbarButtons(splitWidget) {
- const searchToggle = new UI.ToolbarToggle('Search', 'largeicon-search');
+ const searchToggle = new UI.ToolbarToggle(ls`Search`, 'largeicon-search');
function updateSidebarToggle() {
searchToggle.setToggled(splitWidget.showMode() !== UI.SplitWidget.ShowMode.OnlyMain);
}
@@ -204,10 +206,11 @@ Network.NetworkPanel = class extends UI.Panel {
updateSidebarToggle();
splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, updateSidebarToggle);
searchToggle.addEventListener(UI.ToolbarButton.Events.Click, () => {
- if (splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain)
+ if (splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain) {
splitWidget.showBoth();
- else
+ } else {
splitWidget.hideSidebar();
+ }
});
this._panelToolbar.appendToolbarItem(searchToggle);
this._panelToolbar.appendSeparator();
@@ -260,16 +263,16 @@ Network.NetworkPanel = class extends UI.Panel {
* @return {!UI.ToolbarComboBox}
*/
_createThrottlingConditionsSelect() {
- const toolbarItem = new UI.ToolbarComboBox(null);
- toolbarItem.setTitle(ls`Throttling`);
+ const toolbarItem = new UI.ToolbarComboBox(null, ls`Throttling`);
toolbarItem.setMaxWidth(160);
MobileThrottling.throttlingManager().decorateSelectWithNetworkThrottling(toolbarItem.selectElement());
return toolbarItem;
}
_toggleRecording() {
- if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled())
+ if (!this._preserveLogSetting.get() && !this._toggleRecordAction.toggled()) {
SDK.networkLog.reset();
+ }
this._toggleRecord(!this._toggleRecordAction.toggled());
}
@@ -279,8 +282,9 @@ Network.NetworkPanel = class extends UI.Panel {
_toggleRecord(toggled) {
this._toggleRecordAction.setToggled(toggled);
this._networkLogView.setRecording(toggled);
- if (!toggled && this._filmStripRecorder)
+ if (!toggled && this._filmStripRecorder) {
this._filmStripRecorder.stopRecording(this._filmStripAvailable.bind(this));
+ }
// TODO(einbinder) This should be moved to a setting/action that NetworkLog owns but NetworkPanel controls, but
// always be present in the command menu.
SDK.networkLog.setIsRecording(toggled);
@@ -290,8 +294,9 @@ Network.NetworkPanel = class extends UI.Panel {
* @param {?SDK.FilmStripModel} filmStripModel
*/
_filmStripAvailable(filmStripModel) {
- if (!filmStripModel)
+ if (!filmStripModel) {
return;
+ }
const calculator = this._networkLogView.timeCalculator();
this._filmStripView.setModel(filmStripModel, calculator.minimumBoundary() * 1000, calculator.boundarySpan() * 1000);
this._networkOverview.setFilmStripModel(filmStripModel);
@@ -314,8 +319,9 @@ Network.NetworkPanel = class extends UI.Panel {
this._calculator.reset();
this._overviewPane.reset();
}
- if (this._filmStripView)
+ if (this._filmStripView) {
this._resetFilmStripView();
+ }
}
/**
@@ -327,8 +333,9 @@ Network.NetworkPanel = class extends UI.Panel {
clearTimeout(this._pendingStopTimer);
delete this._pendingStopTimer;
}
- if (this.isShowing() && this._filmStripRecorder)
+ if (this.isShowing() && this._filmStripRecorder) {
this._filmStripRecorder.startRecording();
+ }
}
/**
@@ -352,10 +359,11 @@ Network.NetworkPanel = class extends UI.Panel {
_toggleShowOverview() {
const toggled = this._networkLogShowOverviewSetting.get();
- if (toggled)
+ if (toggled) {
this._overviewPane.show(this._overviewPlaceholderElement);
- else
+ } else {
this._overviewPane.detach();
+ }
this.doResize();
}
@@ -421,8 +429,9 @@ Network.NetworkPanel = class extends UI.Panel {
*/
revealAndHighlightRequest(request) {
this._showRequest(null);
- if (request)
+ if (request) {
this._networkLogView.revealAndHighlightRequest(request);
+ }
}
/**
@@ -499,28 +508,33 @@ Network.NetworkPanel = class extends UI.Panel {
contextMenu.revealSection().appendItem(Common.UIString('Reveal in Network panel'), reveal.bind(this, request));
}
- if (event.target.isSelfOrDescendant(this.element))
+ if (event.target.isSelfOrDescendant(this.element)) {
return;
+ }
if (target instanceof SDK.Resource) {
const resource = /** @type {!SDK.Resource} */ (target);
- if (resource.request)
+ if (resource.request) {
appendRevealItem.call(this, resource.request);
+ }
return;
}
if (target instanceof Workspace.UISourceCode) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (target);
const resource = Bindings.resourceForURL(uiSourceCode.url());
- if (resource && resource.request)
+ if (resource && resource.request) {
appendRevealItem.call(this, resource.request);
+ }
return;
}
- if (!(target instanceof SDK.NetworkRequest))
+ if (!(target instanceof SDK.NetworkRequest)) {
return;
+ }
const request = /** @type {!SDK.NetworkRequest} */ (target);
- if (this._networkItemView && this._networkItemView.isShowing() && this._networkItemView.request() === request)
+ if (this._networkItemView && this._networkItemView.isShowing() && this._networkItemView.request() === request) {
return;
+ }
appendRevealItem.call(this, request);
}
@@ -568,8 +582,9 @@ Network.NetworkPanel = class extends UI.Panel {
* @return {?UI.ViewLocation}
*/
resolveLocation(locationName) {
- if (locationName === 'network-sidebar')
+ if (locationName === 'network-sidebar') {
return this._sidebarLocation;
+ }
return null;
}
};
@@ -603,8 +618,9 @@ Network.NetworkPanel.RequestRevealer = class {
* @return {!Promise}
*/
reveal(request) {
- if (!(request instanceof SDK.NetworkRequest))
+ if (!(request instanceof SDK.NetworkRequest)) {
return Promise.reject(new Error('Internal error: not a network request'));
+ }
const panel = Network.NetworkPanel._instance();
return UI.viewManager.showView('network').then(panel.revealAndHighlightRequest.bind(panel, request));
}
@@ -637,22 +653,25 @@ Network.NetworkPanel.FilmStripRecorder = class {
* @param {!Array.<!SDK.TracingManager.EventPayload>} events
*/
traceEventsCollected(events) {
- if (this._tracingModel)
+ if (this._tracingModel) {
this._tracingModel.addEvents(events);
+ }
}
/**
* @override
*/
tracingComplete() {
- if (!this._tracingModel || !this._tracingManager)
+ if (!this._tracingModel || !this._tracingManager) {
return;
+ }
this._tracingModel.tracingComplete();
this._tracingManager = null;
this._callback(new SDK.FilmStripModel(this._tracingModel, this._timeCalculator.minimumBoundary() * 1000));
this._callback = null;
- if (this._resourceTreeModel)
+ if (this._resourceTreeModel) {
this._resourceTreeModel.resumeReload();
+ }
this._resourceTreeModel = null;
}
@@ -673,13 +692,15 @@ Network.NetworkPanel.FilmStripRecorder = class {
this._filmStripView.reset();
this._filmStripView.setStatusText(Common.UIString('Recording frames...'));
const tracingManagers = SDK.targetManager.models(SDK.TracingManager);
- if (this._tracingManager || !tracingManagers.length)
+ if (this._tracingManager || !tracingManagers.length) {
return;
+ }
this._tracingManager = tracingManagers[0];
this._resourceTreeModel = this._tracingManager.target().model(SDK.ResourceTreeModel);
- if (this._tracingModel)
+ if (this._tracingModel) {
this._tracingModel.dispose();
+ }
this._tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage());
this._tracingManager.start(this, '-*,disabled-by-default-devtools.screenshot', '');
@@ -697,12 +718,14 @@ Network.NetworkPanel.FilmStripRecorder = class {
* @param {function(?SDK.FilmStripModel)} callback
*/
stopRecording(callback) {
- if (!this._tracingManager)
+ if (!this._tracingManager) {
return;
+ }
this._tracingManager.stop();
- if (this._resourceTreeModel)
+ if (this._resourceTreeModel) {
this._resourceTreeModel.suspendReload();
+ }
this._callback = callback;
this._filmStripView.setStatusText(Common.UIString('Fetching frames...'));
}
@@ -726,15 +749,17 @@ Network.NetworkPanel.ActionDelegate = class {
panel._toggleRecording();
return true;
case 'network.hide-request-details':
- if (!panel._networkItemView)
+ if (!panel._networkItemView) {
return false;
+ }
panel._showRequest(null);
return true;
case 'network.search':
const selection = UI.inspectorView.element.window().getSelection();
let queryCandidate = '';
- if (selection.rangeCount)
+ if (selection.rangeCount) {
queryCandidate = selection.toString().replace(/\r?\n.*/, '');
+ }
Network.SearchNetworkView.openSearch(queryCandidate);
return true;
}
@@ -754,14 +779,18 @@ Network.NetworkPanel.RequestLocationRevealer = class {
async reveal(match) {
const location = /** @type {!Network.UIRequestLocation} */ (match);
const view = await Network.NetworkPanel._instance().selectRequest(location.request);
- if (!view)
+ if (!view) {
return;
- if (location.searchMatch)
+ }
+ if (location.searchMatch) {
await view.revealResponseBody(location.searchMatch.lineNumber);
- if (location.requestHeader)
+ }
+ if (location.requestHeader) {
view.revealRequestHeader(location.requestHeader.name);
- if (location.responseHeader)
+ }
+ if (location.responseHeader) {
view.revealResponseHeader(location.responseHeader.name);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js
index 57afb465813..fc0e3ccf177 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkSearchScope.js
@@ -36,8 +36,9 @@ Network.NetworkSearchScope = class {
return;
}
for (const result of results.sort((r1, r2) => r1.label().localeCompare(r2.label()))) {
- if (result.matchesCount() > 0)
+ if (result.matchesCount() > 0) {
searchResultCallback(result);
+ }
}
progress.done();
searchFinishedCallback(true);
@@ -55,21 +56,26 @@ Network.NetworkSearchScope = class {
bodyMatches =
await request.searchInContent(searchConfig.query(), !searchConfig.ignoreCase(), searchConfig.isRegex());
}
- if (progress.isCanceled())
+ if (progress.isCanceled()) {
return null;
+ }
const locations = [];
- if (stringMatchesQuery(request.url()))
+ if (stringMatchesQuery(request.url())) {
locations.push(Network.UIRequestLocation.urlMatch(request));
+ }
for (const header of request.requestHeaders()) {
- if (headerMatchesQuery(header))
+ if (headerMatchesQuery(header)) {
locations.push(Network.UIRequestLocation.requestHeaderMatch(request, header));
+ }
}
for (const header of request.responseHeaders) {
- if (headerMatchesQuery(header))
+ if (headerMatchesQuery(header)) {
locations.push(Network.UIRequestLocation.responseHeaderMatch(request, header));
+ }
}
- for (const match of bodyMatches)
+ for (const match of bodyMatches) {
locations.push(Network.UIRequestLocation.bodyMatch(request, match));
+ }
progress.worked();
return new Network.NetworkSearchResult(request, locations);
@@ -91,8 +97,9 @@ Network.NetworkSearchScope = class {
let pos = 0;
for (const regExp of regExps) {
const match = string.substr(pos).match(regExp);
- if (!match)
+ if (!match) {
return false;
+ }
pos += match.index + match[0].length;
}
return true;
@@ -189,8 +196,9 @@ Network.NetworkSearchResult = class {
*/
description() {
const parsedUrl = this._request.parsedURL;
- if (!parsedUrl)
+ if (!parsedUrl) {
return this._request.url();
+ }
return parsedUrl.urlWithoutScheme();
}
@@ -201,11 +209,13 @@ Network.NetworkSearchResult = class {
*/
matchLineContent(index) {
const location = this._locations[index];
- if (location.isUrlMatch)
+ if (location.isUrlMatch) {
return this._request.url();
+ }
const header = location.requestHeader || location.responseHeader;
- if (header)
+ if (header) {
return header.value;
+ }
return location.searchMatch.lineContent;
}
@@ -225,11 +235,13 @@ Network.NetworkSearchResult = class {
*/
matchLabel(index) {
const location = this._locations[index];
- if (location.isUrlMatch)
+ if (location.isUrlMatch) {
return Common.UIString('URL');
+ }
const header = location.requestHeader || location.responseHeader;
- if (header)
+ if (header) {
return `${header.name}:`;
+ }
return location.searchMatch.lineNumber + 1;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkTimeCalculator.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkTimeCalculator.js
index d1b2898a385..12869829655 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkTimeCalculator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkTimeCalculator.js
@@ -164,20 +164,23 @@ Network.NetworkTimeCalculator = class extends Common.Object {
let start;
let middle;
let end;
- if (request.startTime !== -1)
+ if (request.startTime !== -1) {
start = ((request.startTime - this.minimumBoundary()) / this.boundarySpan()) * 100;
- else
+ } else {
start = 0;
+ }
- if (request.responseReceivedTime !== -1)
+ if (request.responseReceivedTime !== -1) {
middle = ((request.responseReceivedTime - this.minimumBoundary()) / this.boundarySpan()) * 100;
- else
+ } else {
middle = (this.startAtZero ? start : 100);
+ }
- if (request.endTime !== -1)
+ if (request.endTime !== -1) {
end = ((request.endTime - this.minimumBoundary()) / this.boundarySpan()) * 100;
- else
+ } else {
end = (this.startAtZero ? middle : 100);
+ }
if (this.startAtZero) {
end -= start;
@@ -196,8 +199,9 @@ Network.NetworkTimeCalculator = class extends Common.Object {
// This function computes a percentage in terms of the total loading time
// of a specific event. If startAtZero is set, then this is useless, and we
// want to return 0.
- if (eventTime !== -1 && !this.startAtZero)
+ if (eventTime !== -1 && !this.startAtZero) {
return ((eventTime - this.minimumBoundary()) / this.boundarySpan()) * 100;
+ }
return 0;
}
@@ -227,8 +231,9 @@ Network.NetworkTimeCalculator = class extends Common.Object {
* @param {number} eventTime
*/
updateBoundariesForEventTime(eventTime) {
- if (eventTime === -1 || this.startAtZero)
+ if (eventTime === -1 || this.startAtZero) {
return;
+ }
if (this._maximumBoundary === undefined || eventTime > this._maximumBoundary) {
this._maximumBoundary = eventTime;
@@ -242,14 +247,16 @@ Network.NetworkTimeCalculator = class extends Common.Object {
*/
computeBarGraphLabels(request) {
let rightLabel = '';
- if (request.responseReceivedTime !== -1 && request.endTime !== -1)
+ if (request.responseReceivedTime !== -1 && request.endTime !== -1) {
rightLabel = Number.secondsToString(request.endTime - request.responseReceivedTime);
+ }
const hasLatency = request.latency > 0;
const leftLabel = hasLatency ? Number.secondsToString(request.latency) : rightLabel;
- if (request.timing)
+ if (request.timing) {
return {left: leftLabel, right: rightLabel};
+ }
let tooltip;
if (hasLatency && rightLabel) {
@@ -261,10 +268,11 @@ Network.NetworkTimeCalculator = class extends Common.Object {
tooltip = Network.NetworkTimeCalculator._downloadFormat.format(rightLabel);
}
- if (request.fetchedViaServiceWorker)
+ if (request.fetchedViaServiceWorker) {
tooltip = Network.NetworkTimeCalculator._fromServiceWorkerFormat.format(tooltip);
- else if (request.cached())
+ } else if (request.cached()) {
tooltip = Network.NetworkTimeCalculator._fromCacheFormat.format(tooltip);
+ }
return {left: leftLabel, right: rightLabel, tooltip: tooltip};
}
@@ -275,12 +283,15 @@ Network.NetworkTimeCalculator = class extends Common.Object {
const lowerBound = this._lowerBound(request);
const upperBound = this._upperBound(request);
let changed = false;
- if (lowerBound !== -1 || this.startAtZero)
+ if (lowerBound !== -1 || this.startAtZero) {
changed = this._extendBoundariesToIncludeTimestamp(this.startAtZero ? 0 : lowerBound);
- if (upperBound !== -1)
+ }
+ if (upperBound !== -1) {
changed = this._extendBoundariesToIncludeTimestamp(upperBound) || changed;
- if (changed)
+ }
+ if (changed) {
this._boundaryChanged();
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
index aea813d5a32..6cef179128d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
@@ -119,8 +119,9 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
for (const resourceType of Object.values(Common.resourceTypes)) {
let color = baseResourceTypeColors.get(resourceType.name());
- if (!color)
+ if (!color) {
color = baseResourceTypeColors.get('other');
+ }
const borderColor = toBorderColor(color);
waitingStyleMap.set(resourceType, {fillStyle: toWaitingColor(color), lineWidth: 1, borderColor: borderColor});
@@ -185,11 +186,13 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
* @return {?UI.PopoverRequest}
*/
_getPopoverRequest(event) {
- if (!this._hoveredNode)
+ if (!this._hoveredNode) {
return null;
+ }
const request = this._hoveredNode.request();
- if (!request)
+ if (!request) {
return null;
+ }
const useTimingBars = !Common.moduleSetting('networkColorCodeResourceTypes').get() && !this._calculator.startAtZero;
let range;
let start;
@@ -211,15 +214,17 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
end = end - halfWidth + 25;
}
- if (event.clientX < this._canvasPosition.left + start || event.clientX > this._canvasPosition.left + end)
+ if (event.clientX < this._canvasPosition.left + start || event.clientX > this._canvasPosition.left + end) {
return null;
+ }
const rowIndex = this._nodes.findIndex(node => node.hovered());
const barHeight = this._getBarHeight(range.name);
const y = this._headerHeight + (this._rowHeight * rowIndex - this._scrollTop) + ((this._rowHeight - barHeight) / 2);
- if (event.clientY < this._canvasPosition.top + y || event.clientY > this._canvasPosition.top + y + barHeight)
+ if (event.clientY < this._canvasPosition.top + y || event.clientY > this._canvasPosition.top + y + barHeight) {
return null;
+ }
const anchorBox = this.element.boxInWindow();
anchorBox.x += start;
@@ -243,11 +248,13 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
* @param {boolean} highlightInitiatorChain
*/
_setHoveredNode(node, highlightInitiatorChain) {
- if (this._hoveredNode)
+ if (this._hoveredNode) {
this._hoveredNode.setHovered(false, false);
+ }
this._hoveredNode = node;
- if (this._hoveredNode)
+ if (this._hoveredNode) {
this._hoveredNode.setHovered(true, highlightInitiatorChain);
+ }
}
/**
@@ -290,14 +297,16 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
* @return {?Network.NetworkNode}
*/
getNodeFromPoint(x, y) {
- if (y <= this._headerHeight)
+ if (y <= this._headerHeight) {
return null;
+ }
return this._nodes[Math.floor((this._scrollTop + y - this._headerHeight) / this._rowHeight)];
}
scheduleDraw() {
- if (this._updateRequestID)
+ if (this._updateRequestID) {
return;
+ }
this._updateRequestID = this.element.window().requestAnimationFrame(() => this.update());
}
@@ -315,8 +324,9 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
this._nodes = nodes;
this._calculateCanvasSize();
}
- if (eventDividers !== undefined)
+ if (eventDividers !== undefined) {
this._eventDividers = eventDividers;
+ }
if (this._updateRequestID) {
this.element.window().cancelAnimationFrame(this._updateRequestID);
delete this._updateRequestID;
@@ -385,22 +395,25 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
const node = nodes[i];
this._decorateRow(context, node, rowOffset - this._scrollTop);
let drawNodes = [];
- if (node.hasChildren() && !node.expanded)
+ if (node.hasChildren() && !node.expanded) {
drawNodes = /** @type {!Array<!Network.NetworkNode>} */ (node.flatChildren());
+ }
drawNodes.push(node);
for (const drawNode of drawNodes) {
- if (useTimingBars)
+ if (useTimingBars) {
this._buildTimingBarLayers(drawNode, rowOffset - this._scrollTop);
- else
+ } else {
this._buildSimplifiedBarLayers(context, drawNode, rowOffset - this._scrollTop);
+ }
}
}
this._drawLayers(context);
context.save();
context.fillStyle = UI.themeSupport.patchColorText('#888', UI.ThemeSupport.ColorUsage.Foreground);
- for (const textData of this._textLayers)
+ for (const textData of this._textLayers) {
context.fillText(textData.text, textData.x, textData.y);
+ }
context.restore();
this._drawEventDividers(context);
@@ -500,8 +513,9 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
*/
_buildSimplifiedBarLayers(context, node, y) {
const request = node.request();
- if (!request)
+ if (!request) {
return;
+ }
const borderWidth = 1;
const borderOffset = borderWidth % 2 === 0 ? 0 : 0.5;
@@ -579,13 +593,15 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
*/
_buildTimingBarLayers(node, y) {
const request = node.request();
- if (!request)
+ if (!request) {
return;
+ }
const ranges = Network.RequestTimingView.calculateRequestTimeRanges(request, 0);
for (const range of ranges) {
if (range.name === Network.RequestTimeRangeNames.Total || range.name === Network.RequestTimeRangeNames.Sending ||
- range.end - range.start === 0)
+ range.end - range.start === 0) {
continue;
+ }
const style = this._styleForTimeRangeName.get(range.name);
const path = this._pathForStyle.get(style);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestCookiesView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestCookiesView.js
index fee85965937..826a6545ec4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestCookiesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestCookiesView.js
@@ -28,10 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/**
- * @unrestricted
- */
-Network.RequestCookiesView = class extends UI.VBox {
+Network.RequestCookiesView = class extends UI.Widget {
/**
* @param {!SDK.NetworkRequest} request
*/
@@ -40,56 +37,243 @@ Network.RequestCookiesView = class extends UI.VBox {
this.registerRequiredCSS('network/requestCookiesView.css');
this.element.classList.add('request-cookies-view');
+ /** @type {!SDK.NetworkRequest} */
this._request = request;
+ /** @type {?Array<!SDK.Cookie>} */
+ this._detailedRequestCookies = null;
+ this._showFilteredOutCookiesSetting =
+ Common.settings.createSetting('show-filtered-out-request-cookies', /* defaultValue */ false);
+
+ this._emptyWidget = new UI.EmptyWidget(Common.UIString('This request has no cookies.'));
+ this._emptyWidget.show(this.element);
+
+ this._requestCookiesTitle = this.element.createChild('div');
+ const titleText = this._requestCookiesTitle.createChild('span', 'request-cookies-title');
+ titleText.textContent = ls`Request Cookies`;
+ titleText.title = ls`Cookies that were sent to the server in the 'cookie' header of the request`;
+
+ const requestCookiesCheckbox = UI.SettingsUI.createSettingCheckbox(
+ ls`show filtered out request cookies`, this._showFilteredOutCookiesSetting,
+ /* omitParagraphElement */ true);
+ requestCookiesCheckbox.checkboxElement.addEventListener('change', () => {
+ this._refreshRequestCookiesView();
+ });
+ this._requestCookiesTitle.appendChild(requestCookiesCheckbox);
+
+ this._requestCookiesEmpty = this.element.createChild('div', 'cookies-panel-item');
+ this._requestCookiesEmpty.textContent = ls`No request cookies were sent.`;
+
+ this._requestCookiesTable = new CookieTable.CookiesTable(/* renderInline */ true);
+ this._requestCookiesTable.contentElement.classList.add('cookie-table', 'cookies-panel-item');
+ this._requestCookiesTable.show(this.element);
+
+ this._responseCookiesTitle = this.element.createChild('div', 'request-cookies-title');
+ this._responseCookiesTitle.textContent = ls`Response Cookies`;
+ this._responseCookiesTitle.title =
+ ls`Cookies that were received from the server in the 'set-cookie' header of the response`;
+
+ this._responseCookiesTable = new CookieTable.CookiesTable(/* renderInline */ true);
+ this._responseCookiesTable.contentElement.classList.add('cookie-table', 'cookies-panel-item');
+ this._responseCookiesTable.show(this.element);
+
+ this._malformedResponseCookiesTitle = this.element.createChild('div', 'request-cookies-title');
+ this._malformedResponseCookiesTitle.textContent = ls`Malformed Response Cookies`;
+ this._malformedResponseCookiesTitle.title = ls
+ `Cookies that were received from the server in the 'set-cookie' header of the response but were malformed`;
+
+ this._malformedResponseCookiesList = this.element.createChild('div');
}
/**
- * @override
+ * @return {!{requestCookies: !Array<!SDK.Cookie>, requestCookieToBlockedReasons: !Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>}}
*/
- wasShown() {
- this._request.addEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshCookies, this);
- this._request.addEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshCookies, this);
+ _getRequestCookies() {
+ let requestCookies = [];
+ /** @type {!Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>} */
+ const requestCookieToBlockedReasons = new Map();
+
+ if (this._request.requestCookies) {
+ requestCookies = this._request.requestCookies.slice();
+
+ // request.requestCookies are generated from headers which are missing
+ // cookie attributes that we can fetch from the backend.
+ if (this._detailedRequestCookies) {
+ requestCookies = requestCookies.map(cookie => {
+ for (const detailedCookie of (this._detailedRequestCookies || [])) {
+ if (detailedCookie.name() === cookie.name() && detailedCookie.value() === cookie.value()) {
+ return detailedCookie;
+ }
+ }
+ return cookie;
+ });
- if (!this._gotCookies) {
- if (!this._emptyWidget) {
- this._emptyWidget = new UI.EmptyWidget(Common.UIString('This request has no cookies.'));
- this._emptyWidget.show(this.element);
+ } else {
+ const networkManager = SDK.NetworkManager.forRequest(this._request);
+ if (networkManager) {
+ const cookieModel = networkManager.target().model(SDK.CookieModel);
+ if (cookieModel) {
+ cookieModel.getCookies([this._request.url()]).then(cookies => {
+ this._detailedRequestCookies = cookies;
+ this._refreshRequestCookiesView();
+ });
+ }
+ }
}
+ }
+
+ if (this._showFilteredOutCookiesSetting.get()) {
+ for (const blockedCookie of this._request.blockedRequestCookies()) {
+ requestCookieToBlockedReasons.set(blockedCookie.cookie, blockedCookie.blockedReasons.map(blockedReason => {
+ return {
+ attribute: SDK.NetworkRequest.cookieBlockedReasonToAttribute(blockedReason),
+ uiString: SDK.NetworkRequest.cookieBlockedReasonToUiString(blockedReason)
+ };
+ }));
+ requestCookies.push(blockedCookie.cookie);
+ }
+ }
+
+ return {requestCookies, requestCookieToBlockedReasons};
+ }
+
+ /**
+ * @return {!{responseCookies: !Array<!SDK.Cookie>, responseCookieToBlockedReasons: !Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>, malformedResponseCookies: !Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>}}
+ */
+ _getResponseCookies() {
+ /** @type {!Array<!SDK.Cookie>} */
+ let responseCookies = [];
+ /** @type {!Map<!SDK.Cookie, !Array<!CookieTable.BlockedReason>>} */
+ const responseCookieToBlockedReasons = new Map();
+ /** @type {!Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>} */
+ const malformedResponseCookies = [];
+
+ if (this._request.responseCookies) {
+ const blockedCookieLines = this._request.blockedResponseCookies().map(blockedCookie => blockedCookie.cookieLine);
+ responseCookies = this._request.responseCookies.filter(cookie => {
+ // remove the regular cookies that would overlap with blocked cookies
+ if (blockedCookieLines.includes(cookie.getCookieLine())) {
+ blockedCookieLines.remove(cookie.getCookieLine(), /* firstOnly */ true);
+ return false;
+ }
+ return true;
+ });
+
+ for (const blockedCookie of this._request.blockedResponseCookies()) {
+ const parsedCookies = SDK.CookieParser.parseSetCookie(blockedCookie.cookieLine);
+ if (!parsedCookies.length ||
+ blockedCookie.blockedReasons.includes(Protocol.Network.SetCookieBlockedReason.SyntaxError)) {
+ malformedResponseCookies.push(blockedCookie);
+ continue;
+ }
+
+ const cookie = parsedCookies[0];
+ responseCookieToBlockedReasons.set(cookie, blockedCookie.blockedReasons.map(blockedReason => {
+ return {
+ attribute: SDK.NetworkRequest.setCookieBlockedReasonToAttribute(blockedReason),
+ uiString: SDK.NetworkRequest.setCookieBlockedReasonToUiString(blockedReason)
+ };
+ }));
+ responseCookies.push(cookie);
+ }
+ }
+
+ return {responseCookies, responseCookieToBlockedReasons, malformedResponseCookies};
+ }
+
+ _refreshRequestCookiesView() {
+ if (!this.isShowing()) {
return;
}
- if (!this._cookiesTable)
- this._buildCookiesTable();
+ const {requestCookies, requestCookieToBlockedReasons} = this._getRequestCookies();
+ const {responseCookies, responseCookieToBlockedReasons, malformedResponseCookies} = this._getResponseCookies();
+
+ if (requestCookies.length) {
+ this._requestCookiesTitle.classList.remove('hidden');
+ this._requestCookiesEmpty.classList.add('hidden');
+ this._requestCookiesTable.showWidget();
+ this._requestCookiesTable.setCookies(requestCookies, requestCookieToBlockedReasons);
+
+ } else if (this._request.blockedRequestCookies().length) {
+ this._requestCookiesTitle.classList.remove('hidden');
+ this._requestCookiesEmpty.classList.remove('hidden');
+ this._requestCookiesTable.hideWidget();
+
+ } else {
+ this._requestCookiesTitle.classList.add('hidden');
+ this._requestCookiesEmpty.classList.add('hidden');
+ this._requestCookiesTable.hideWidget();
+ }
+
+ if (responseCookies.length) {
+ this._responseCookiesTitle.classList.remove('hidden');
+ this._responseCookiesTable.showWidget();
+ this._responseCookiesTable.setCookies(responseCookies, responseCookieToBlockedReasons);
+ } else {
+ this._responseCookiesTitle.classList.add('hidden');
+ this._responseCookiesTable.hideWidget();
+ }
+
+ if (malformedResponseCookies.length) {
+ this._malformedResponseCookiesTitle.classList.remove('hidden');
+ this._malformedResponseCookiesList.classList.remove('hidden');
+
+ this._malformedResponseCookiesList.removeChildren();
+ for (const malformedCookie of malformedResponseCookies) {
+ const listItem = this._malformedResponseCookiesList.createChild('span', 'cookie-line source-code');
+ const icon = UI.Icon.create('smallicon-error', 'cookie-warning-icon');
+ listItem.appendChild(icon);
+ listItem.createTextChild(malformedCookie.cookieLine);
+ listItem.title =
+ SDK.NetworkRequest.setCookieBlockedReasonToUiString(Protocol.Network.SetCookieBlockedReason.SyntaxError);
+ }
+ } else {
+ this._malformedResponseCookiesTitle.classList.add('hidden');
+ this._malformedResponseCookiesList.classList.add('hidden');
+ }
}
/**
* @override
*/
- willHide() {
- this._request.removeEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshCookies, this);
- this._request.removeEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshCookies, this);
- }
+ wasShown() {
+ this._request.addEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._cookiesUpdated, this);
+ this._request.addEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this._cookiesUpdated, this);
- get _gotCookies() {
- return (this._request.requestCookies && this._request.requestCookies.length) ||
- (this._request.responseCookies && this._request.responseCookies.length);
+ if (this._gotCookies()) {
+ this._refreshRequestCookiesView();
+ this._emptyWidget.hideWidget();
+ } else {
+ this._emptyWidget.showWidget();
+ }
}
- _buildCookiesTable() {
- this.detachChildWidgets();
+ /**
+ * @override
+ */
+ willHide() {
+ this._request.removeEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._cookiesUpdated, this);
+ this._request.removeEventListener(SDK.NetworkRequest.Events.ResponseHeadersChanged, this._cookiesUpdated, this);
+ }
- this._cookiesTable = new CookieTable.CookiesTable();
- this._cookiesTable.setCookieFolders([
- {folderName: Common.UIString('Request Cookies'), cookies: this._request.requestCookies},
- {folderName: Common.UIString('Response Cookies'), cookies: this._request.responseCookies}
- ]);
- this._cookiesTable.show(this.element);
+ /**
+ * @return {boolean}
+ */
+ _gotCookies() {
+ return !!(this._request.requestCookies && this._request.requestCookies.length) ||
+ !!(this._request.responseCookies && this._request.responseCookies.length);
}
- _refreshCookies() {
- delete this._cookiesTable;
- if (!this._gotCookies || !this.isShowing())
+ _cookiesUpdated() {
+ if (!this.isShowing()) {
return;
- this._buildCookiesTable();
+ }
+
+ if (this._gotCookies()) {
+ this._refreshRequestCookiesView();
+ this._emptyWidget.hideWidget();
+ } else {
+ this._emptyWidget.showWidget();
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
index b0fa4033d67..4f3528d9d52 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
@@ -65,6 +65,7 @@ Network.RequestHTMLView = class extends UI.VBox {
iframe.setAttribute('sandbox', ''); // Forbid to run JavaScript and set unique origin.
iframe.setAttribute('src', this._dataURL);
iframe.setAttribute('tabIndex', -1);
+ UI.ARIAUtils.markAsPresentation(iframe);
this.contentElement.appendChild(iframe);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHeadersView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHeadersView.js
index acc989f9076..5c07f20993f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHeadersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHeadersView.js
@@ -137,12 +137,14 @@ Network.RequestHeadersView = class extends UI.VBox {
}
}
const div = createElementWithClass('div', className);
- if (value === '')
+ if (value === '') {
div.classList.add('empty-value');
- if (errorDecoding)
+ }
+ if (errorDecoding) {
div.createChild('span', 'header-decode-error').textContent = Common.UIString('(unable to decode value)');
- else
+ } else {
div.textContent = value;
+ }
return div;
}
@@ -165,8 +167,9 @@ Network.RequestHeadersView = class extends UI.VBox {
this._requestPayloadCategory.hidden = true;
const formData = await this._request.requestFormData();
- if (!formData)
+ if (!formData) {
return;
+ }
const formParameters = await this._request.formParameters();
if (formParameters) {
@@ -199,8 +202,9 @@ Network.RequestHeadersView = class extends UI.VBox {
sourceTreeElement.selectable = false;
treeElement.removeChildren();
treeElement.appendChild(sourceTreeElement);
- if (!trim)
+ if (!trim) {
return;
+ }
const showMoreButton = createElementWithClass('button', 'request-headers-show-more-button');
showMoreButton.textContent = Common.UIString('Show more');
@@ -224,7 +228,7 @@ Network.RequestHeadersView = class extends UI.VBox {
paramsTreeElement.listItemElement.createTextChild(title);
const headerCount = createElementWithClass('span', 'header-count');
- headerCount.textContent = Common.UIString('\u00A0(%d)', params.length);
+ headerCount.textContent = Common.UIString('\xA0(%d)', params.length);
paramsTreeElement.listItemElement.appendChild(headerCount);
/**
@@ -337,10 +341,11 @@ Network.RequestHeadersView = class extends UI.VBox {
});
const headersText = this._request.requestHeadersText();
- if (this._showRequestHeadersText && headersText)
+ if (this._showRequestHeadersText && headersText) {
this._refreshHeadersText(Common.UIString('Request Headers'), headers.length, headersText, treeElement);
- else
+ } else {
this._refreshHeaders(Common.UIString('Request Headers'), headers, treeElement, headersText === undefined);
+ }
if (headersText) {
const toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText);
@@ -356,10 +361,13 @@ Network.RequestHeadersView = class extends UI.VBox {
const headers = this._request.sortedResponseHeaders.slice();
const headersText = this._request.responseHeadersText;
- if (this._showResponseHeadersText)
+ if (this._showResponseHeadersText) {
this._refreshHeadersText(Common.UIString('Response Headers'), headers.length, headersText, treeElement);
- else
- this._refreshHeaders(Common.UIString('Response Headers'), headers, treeElement);
+ } else {
+ this._refreshHeaders(
+ Common.UIString('Response Headers'), headers, treeElement, /* provisional */ false,
+ this._request.blockedResponseCookies());
+ }
if (headersText) {
const toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText);
@@ -383,12 +391,13 @@ Network.RequestHeadersView = class extends UI.VBox {
const statusCodeImage = statusCodeFragment.createChild('span', 'resource-status-image', 'dt-icon-label');
statusCodeImage.title = this._request.statusCode + ' ' + this._request.statusText;
- if (this._request.statusCode < 300 || this._request.statusCode === 304)
+ if (this._request.statusCode < 300 || this._request.statusCode === 304) {
statusCodeImage.type = 'smallicon-green-ball';
- else if (this._request.statusCode < 400)
+ } else if (this._request.statusCode < 400) {
statusCodeImage.type = 'smallicon-orange-ball';
- else
+ } else {
statusCodeImage.type = 'smallicon-red-ball';
+ }
requestMethodElement.title = this._formatHeader(ls`Request Method`, this._request.requestMethod);
@@ -427,7 +436,7 @@ Network.RequestHeadersView = class extends UI.VBox {
headersTreeElement.listItemElement.removeChildren();
headersTreeElement.listItemElement.createTextChild(title);
- const headerCount = Common.UIString('\u00A0(%d)', headersLength);
+ const headerCount = Common.UIString('\xA0(%d)', headersLength);
headersTreeElement.listItemElement.createChild('span', 'header-count').textContent = headerCount;
}
@@ -436,8 +445,9 @@ Network.RequestHeadersView = class extends UI.VBox {
* @param {!Array.<!SDK.NetworkRequest.NameValue>} headers
* @param {!UI.TreeElement} headersTreeElement
* @param {boolean=} provisionalHeaders
+ * @param {!Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>=} blockedResponseCookies
*/
- _refreshHeaders(title, headers, headersTreeElement, provisionalHeaders) {
+ _refreshHeaders(title, headers, headersTreeElement, provisionalHeaders, blockedResponseCookies) {
headersTreeElement.removeChildren();
const length = headers.length;
@@ -453,12 +463,38 @@ Network.RequestHeadersView = class extends UI.VBox {
headersTreeElement.appendChild(cautionTreeElement);
}
+ /** @type {!Map<string, !Array<!Protocol.Network.SetCookieBlockedReason>>} */
+ const blockedCookieLineToReasons = new Map();
+ if (blockedResponseCookies) {
+ blockedResponseCookies.forEach(blockedCookie => {
+ blockedCookieLineToReasons.set(blockedCookie.cookieLine, blockedCookie.blockedReasons);
+ });
+ }
+
headersTreeElement.hidden = !length && !provisionalHeaders;
for (let i = 0; i < length; ++i) {
const headerTreeElement = new UI.TreeElement(this._formatHeader(headers[i].name, headers[i].value));
headerTreeElement.selectable = false;
- headersTreeElement.appendChild(headerTreeElement);
headerTreeElement[Network.RequestHeadersView._headerNameSymbol] = headers[i].name;
+
+ if (headers[i].name.toLowerCase() === 'set-cookie') {
+ const matchingBlockedReasons = blockedCookieLineToReasons.get(headers[i].value);
+ if (matchingBlockedReasons) {
+ const icon = UI.Icon.create('smallicon-warning', '');
+ headerTreeElement.listItemElement.appendChild(icon);
+
+ let titleText = '';
+ for (const blockedReason of matchingBlockedReasons) {
+ if (titleText) {
+ titleText += '\n';
+ }
+ titleText += SDK.NetworkRequest.setCookieBlockedReasonToUiString(blockedReason);
+ }
+ icon.title = titleText;
+ }
+ }
+
+ headersTreeElement.appendChild(headerTreeElement);
}
}
@@ -477,16 +513,18 @@ Network.RequestHeadersView = class extends UI.VBox {
const remoteAddress = this._request.remoteAddress();
const treeElement = this._remoteAddressItem;
treeElement.hidden = !remoteAddress;
- if (remoteAddress)
+ if (remoteAddress) {
treeElement.title = this._formatHeader(Common.UIString('Remote Address'), remoteAddress);
+ }
}
_refreshReferrerPolicy() {
const referrerPolicy = this._request.referrerPolicy();
const treeElement = this._referrerPolicyItem;
treeElement.hidden = !referrerPolicy;
- if (referrerPolicy)
+ if (referrerPolicy) {
treeElement.title = this._formatHeader(Common.UIString('Referrer Policy'), referrerPolicy);
+ }
}
/**
@@ -527,8 +565,9 @@ Network.RequestHeadersView = class extends UI.VBox {
}
_clearHighlight() {
- if (this._highlightedElement)
+ if (this._highlightedElement) {
this._highlightedElement.listItemElement.classList.remove('header-highlight');
+ }
this._highlightedElement = null;
}
@@ -540,8 +579,9 @@ Network.RequestHeadersView = class extends UI.VBox {
_revealAndHighlight(category, name) {
this._clearHighlight();
for (const element of category.children()) {
- if (element[Network.RequestHeadersView._headerNameSymbol] !== name)
+ if (element[Network.RequestHeadersView._headerNameSymbol] !== name) {
continue;
+ }
this._highlightedElement = element;
element.reveal();
element.listItemElement.classList.add('header-highlight');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestInitiatorView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestInitiatorView.js
new file mode 100644
index 00000000000..de3017f28bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestInitiatorView.js
@@ -0,0 +1,86 @@
+// 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.
+Network.RequestInitiatorView = class extends UI.VBox {
+ /**
+ * @param {!SDK.NetworkRequest} request
+ */
+ constructor(request) {
+ super();
+ this.registerRequiredCSS('network/requestInitiatorView.css');
+ this.element.classList.add('request-initiator-view');
+ /** @type {!Components.Linkifier} */
+ this._linkifier = new Components.Linkifier();
+ this._request = request;
+ /** @type {?{element: !Element, links: !Array<!Element>}} */
+ this._stackTracePreview = null;
+ /** @type {?SDK.NetworkLog.InitiatorGraph} */
+ this._initiatorGraph = null;
+ }
+
+ /**
+ * @param {!SDK.NetworkRequest} request
+ * @param {!Components.Linkifier} linkifier
+ * @param {boolean=} focusableLink
+ * @param {function()=} callback
+ * @return {?{element: !Element, links: !Array<!Element>}}
+ */
+ static createStackTracePreview(request, linkifier, focusableLink, callback) {
+ const initiator = request.initiator();
+ if (!initiator || !initiator.stack) {
+ return null;
+ }
+ const networkManager = SDK.NetworkManager.forRequest(request);
+ const target = networkManager ? networkManager.target() : null;
+ const stackTrace =
+ Components.JSPresentationUtils.buildStackTracePreviewContents(target, linkifier, initiator.stack, callback);
+ if (focusableLink) {
+ for (const link of stackTrace.links) {
+ link.tabIndex = 0;
+ }
+ }
+ return stackTrace;
+ }
+
+ /**
+ * @param {!Element} sectionContent
+ * @param {string} title
+ * @param {boolean} expanded
+ */
+ _appendExpandableSection(sectionContent, title, expanded) {
+ const section = createElementWithClass('div', 'request-initiator-view-section');
+ const icon = UI.Icon.create('smallicon-triangle-right');
+ const clickableElement = section.createChild('div', 'request-initiator-view-section-title');
+ clickableElement.appendChild(icon);
+ clickableElement.createTextChild(title);
+ clickableElement.tabIndex = 0;
+ sectionContent.classList.add('hidden', 'request-initiator-view-section-content');
+ section.appendChild(sectionContent);
+
+ const expand = expanded => {
+ icon.setIconType(expanded ? 'smallicon-triangle-down' : 'smallicon-triangle-right');
+ sectionContent.classList.toggle('hidden', !expanded);
+ };
+ self.onInvokeElement(clickableElement, event => {
+ expand(sectionContent.classList.contains('hidden'));
+ event.consume();
+ });
+
+ expand(expanded);
+ this.element.appendChild(section);
+ }
+
+ /**
+ * @override
+ */
+ wasShown() {
+ if (this._stackTracePreview) {
+ return;
+ }
+ this._stackTracePreview =
+ Network.RequestInitiatorView.createStackTracePreview(this._request, this._linkifier, true);
+ if (this._stackTracePreview) {
+ this._appendExpandableSection(this._stackTracePreview.element, ls`Request call stack`, true);
+ }
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
index ae4dd41f4df..631f9d7cd71 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
@@ -43,11 +43,13 @@ Network.RequestPreviewView = class extends Network.RequestResponseView {
*/
async showPreview() {
const view = await super.showPreview();
- if (!(view instanceof UI.SimpleView))
+ if (!(view instanceof UI.SimpleView)) {
return view;
+ }
const toolbar = new UI.Toolbar('network-item-preview-toolbar', this.element);
- for (const item of view.syncToolbarItems())
+ for (const item of view.syncToolbarItems()) {
toolbar.appendToolbarItem(item);
+ }
return view;
}
@@ -56,19 +58,23 @@ Network.RequestPreviewView = class extends Network.RequestResponseView {
*/
async _htmlPreview() {
const contentData = await this.request.contentData();
- if (contentData.error)
+ if (contentData.error) {
return new UI.EmptyWidget(Common.UIString('Failed to load response data'));
+ }
const whitelist = new Set(['text/html', 'text/plain', 'application/xhtml+xml']);
- if (!whitelist.has(this.request.mimeType))
+ if (!whitelist.has(this.request.mimeType)) {
return null;
+ }
- const content = contentData.encoded ? window.atob(contentData.content) : contentData.content;
+ const content = contentData.encoded ? window.atob(/** @type {string} */ (contentData.content)) :
+ /** @type {string} */ (contentData.content);
// http://crbug.com/767393 - DevTools should recognize JSON regardless of the content type
const jsonView = await SourceFrame.JSONView.createView(content);
- if (jsonView)
+ if (jsonView) {
return jsonView;
+ }
const dataURL = Common.ContentProvider.contentAsDataURL(
contentData.content, this.request.mimeType, contentData.encoded, this.request.charset());
@@ -81,16 +87,19 @@ Network.RequestPreviewView = class extends Network.RequestResponseView {
* @return {!Promise<!UI.Widget>}
*/
async createPreview() {
- if (this.request.signedExchangeInfo())
+ if (this.request.signedExchangeInfo()) {
return new Network.SignedExchangeInfoView(this.request);
+ }
const htmlErrorPreview = await this._htmlPreview();
- if (htmlErrorPreview)
+ if (htmlErrorPreview) {
return htmlErrorPreview;
+ }
const provided = await SourceFrame.PreviewFactory.createPreview(this.request, this.request.mimeType);
- if (provided)
+ if (provided) {
return provided;
+ }
return new UI.EmptyWidget(Common.UIString('Preview not available'));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
index 56050b06843..6e5ac3c322f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
@@ -49,28 +49,34 @@ Network.RequestResponseView = class extends UI.VBox {
static _hasTextContent(request, contentData) {
const mimeType = request.mimeType || '';
let resourceType = Common.ResourceType.fromMimeType(mimeType);
- if (resourceType === Common.resourceTypes.Other)
+ if (resourceType === Common.resourceTypes.Other) {
resourceType = request.contentType();
- if (resourceType === Common.resourceTypes.Image)
+ }
+ if (resourceType === Common.resourceTypes.Image) {
return mimeType.startsWith('image/svg');
- if (resourceType.isTextType())
+ }
+ if (resourceType.isTextType()) {
return true;
- if (contentData.error)
+ }
+ if (contentData.error) {
return false;
- if (resourceType === Common.resourceTypes.Other)
+ }
+ if (resourceType === Common.resourceTypes.Other) {
return !!contentData.content && !contentData.encoded;
+ }
return false;
}
/**
* @protected
* @param {!SDK.NetworkRequest} request
- * @return {!Promise<?UI.SearchableView>}
+ * @return {!Promise<?UI.Widget>}
*/
static async sourceViewForRequest(request) {
let sourceView = request[Network.RequestResponseView._sourceViewSymbol];
- if (sourceView !== undefined)
+ if (sourceView !== undefined) {
return sourceView;
+ }
const contentData = await request.contentData();
if (!Network.RequestResponseView._hasTextContent(request, contentData)) {
@@ -96,8 +102,9 @@ Network.RequestResponseView = class extends UI.VBox {
* @return {!Promise<!UI.Widget>}
*/
_doShowPreview() {
- if (!this._contentViewPromise)
+ if (!this._contentViewPromise) {
this._contentViewPromise = this.showPreview();
+ }
return this._contentViewPromise;
}
@@ -118,10 +125,12 @@ Network.RequestResponseView = class extends UI.VBox {
async createPreview() {
const contentData = await this.request.contentData();
const sourceView = await Network.RequestResponseView.sourceViewForRequest(this.request);
- if ((!contentData.content || !sourceView) && !contentData.error)
+ if ((!contentData.content || !sourceView) && !contentData.error) {
return new UI.EmptyWidget(Common.UIString('This request has no response data available.'));
- if (contentData.content && sourceView)
+ }
+ if (contentData.content && sourceView) {
return sourceView;
+ }
return new UI.EmptyWidget(Common.UIString('Failed to load response data'));
}
@@ -130,8 +139,9 @@ Network.RequestResponseView = class extends UI.VBox {
*/
async revealLine(line) {
const view = await this._doShowPreview();
- if (view instanceof SourceFrame.ResourceSourceFrame.SearchableContainer)
+ if (view instanceof SourceFrame.ResourceSourceFrame.SearchableContainer) {
view.revealPosition(line);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestTimingView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestTimingView.js
index 24b3a4ab90c..8b7a8d26aef 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestTimingView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestTimingView.js
@@ -96,8 +96,9 @@ Network.RequestTimingView = class extends UI.VBox {
* @param {number} end
*/
function addRange(name, start, end) {
- if (start < Number.MAX_VALUE && start <= end)
+ if (start < Number.MAX_VALUE && start <= end) {
result.push({name: name, start: start, end: end});
+ }
}
/**
@@ -106,8 +107,9 @@ Network.RequestTimingView = class extends UI.VBox {
*/
function firstPositive(numbers) {
for (let i = 0; i < numbers.length; ++i) {
- if (numbers[i] > 0)
+ if (numbers[i] > 0) {
return numbers[i];
+ }
}
return undefined;
}
@@ -118,8 +120,9 @@ Network.RequestTimingView = class extends UI.VBox {
* @param {number} end
*/
function addOffsetRange(name, start, end) {
- if (start >= 0 && end >= 0)
+ if (start >= 0 && end >= 0) {
addRange(name, startTime + (start / 1000), startTime + (end / 1000));
+ }
}
const timing = request.timing;
@@ -142,11 +145,13 @@ Network.RequestTimingView = class extends UI.VBox {
const pushEnd = timing.pushEnd || endTime;
// Only show the part of push that happened after the navigation/reload.
// Pushes that happened on the same connection before we started main request will not be shown.
- if (pushEnd > navigationStart)
+ if (pushEnd > navigationStart) {
addRange(Network.RequestTimeRangeNames.Push, Math.max(timing.pushStart, navigationStart), pushEnd);
+ }
}
- if (issueTime < startTime)
+ if (issueTime < startTime) {
addRange(Network.RequestTimeRangeNames.Queueing, issueTime, startTime);
+ }
const responseReceived = (request.responseReceivedTime - startTime) * 1000;
if (request.fetchedViaServiceWorker) {
@@ -229,14 +234,17 @@ Network.RequestTimingView = class extends UI.VBox {
if (rangeName === Network.RequestTimeRangeNames.Push) {
createHeader(Common.UIString('Server Push'));
} else if (rangeName === Network.RequestTimeRangeNames.Queueing) {
- if (!queueingHeader)
+ if (!queueingHeader) {
queueingHeader = createHeader(ls`Resource Scheduling`);
+ }
} else if (Network.RequestTimingView.ConnectionSetupRangeNames.has(rangeName)) {
- if (!connectionHeader)
+ if (!connectionHeader) {
connectionHeader = createHeader(Common.UIString('Connection Start'));
+ }
} else {
- if (!dataHeader)
+ if (!dataHeader) {
dataHeader = createHeader(Common.UIString('Request/Response'));
+ }
}
const left = (scale * (range.start - startTime));
@@ -271,8 +279,9 @@ Network.RequestTimingView = class extends UI.VBox {
footer.createChild('td').createTextChild(Number.secondsToString(totalDuration, true));
const serverTimings = request.serverTimings;
- if (!serverTimings)
+ if (!serverTimings) {
return tableElement;
+ }
const lastTimingRightEdge = right === undefined ? 100 : right;
@@ -301,19 +310,23 @@ Network.RequestTimingView = class extends UI.VBox {
const isTotal = serverTiming.metric.toLowerCase() === 'total';
const tr = tableElement.createChild('tr', isTotal ? 'network-timing-footer' : '');
const metric = tr.createChild('td', 'network-timing-metric');
- metric.createTextChild(serverTiming.description || serverTiming.metric);
+ const description = serverTiming.description || serverTiming.metric;
+ metric.createTextChild(description);
+ metric.title = description;
const row = tr.createChild('td').createChild('div', 'network-timing-row');
- if (serverTiming.value === null)
+ if (serverTiming.value === null) {
return;
+ }
const left = scale * (endTime - startTime - (serverTiming.value / 1000));
if (left >= 0) { // don't chart values too big or too small
const bar = row.createChild('span', 'network-timing-bar server-timing');
bar.style.left = left + '%';
bar.style.right = right + '%';
bar.textContent = '\u200B'; // Important for 0-time items to have 0 width.
- if (!isTotal)
+ if (!isTotal) {
bar.style.backgroundColor = colorGenerator.colorForID(serverTiming.metric);
+ }
}
const label = tr.createChild('td').createChild('div', 'network-timing-bar-title');
label.textContent = Number.millisToString(serverTiming.value, true);
@@ -354,8 +367,9 @@ Network.RequestTimingView = class extends UI.VBox {
}
_refresh() {
- if (this._tableElement)
+ if (this._tableElement) {
this._tableElement.remove();
+ }
this._tableElement = Network.RequestTimingView.createTimingTable(this._request, this._calculator);
this._tableElement.classList.add('resource-timing-table');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
index ae5f8d1c41a..9145383c23f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -64,16 +64,16 @@ Network.ResourceWebSocketFrameView = class extends UI.VBox {
this._clearAllButton.addEventListener(UI.ToolbarButton.Events.Click, this._clearFrames, this);
this._mainToolbar.appendToolbarItem(this._clearAllButton);
- this._filterTypeCombobox = new UI.ToolbarComboBox(this._updateFilterSetting.bind(this));
+ this._filterTypeCombobox = new UI.ToolbarComboBox(this._updateFilterSetting.bind(this), ls`Filter`);
for (const filterItem of Network.ResourceWebSocketFrameView._filterTypes) {
- const option = this._filterTypeCombobox.createOption(filterItem.label, filterItem.label, filterItem.name);
+ const option = this._filterTypeCombobox.createOption(filterItem.label, filterItem.name);
this._filterTypeCombobox.addOption(option);
}
this._mainToolbar.appendToolbarItem(this._filterTypeCombobox);
this._filterType = null;
const placeholder = 'Enter regex, for example: (web)?socket';
- this._filterTextInput = new UI.ToolbarInput(Common.UIString(placeholder), 0.4);
+ this._filterTextInput = new UI.ToolbarInput(Common.UIString(placeholder), '', 0.4);
this._filterTextInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._updateFilterSetting, this);
this._mainToolbar.appendToolbarItem(this._filterTextInput);
this._filterRegex = null;
@@ -103,7 +103,7 @@ Network.ResourceWebSocketFrameView = class extends UI.VBox {
} else {
contextMenu.clipboardSection().appendItem(
Common.UIString('Copy message'),
- InspectorFrontendHost.copyText.bind(InspectorFrontendHost, node.data.data));
+ Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, node.data.data));
}
contextMenu.footerSection().appendItem(Common.UIString('Clear all'), this._clearFrames.bind(this));
}
@@ -116,8 +116,9 @@ Network.ResourceWebSocketFrameView = class extends UI.VBox {
*/
static opCodeDescription(opCode, mask) {
const localizedDescription = Network.ResourceWebSocketFrameView.opCodeDescriptions[opCode] || '';
- if (mask)
+ if (mask) {
return ls`${localizedDescription} (Opcode ${opCode}, mask)`;
+ }
return ls`${localizedDescription} (Opcode ${opCode})`;
}
@@ -141,8 +142,9 @@ Network.ResourceWebSocketFrameView = class extends UI.VBox {
*/
_frameAdded(event) {
const frame = /** @type {!SDK.NetworkRequest.WebSocketFrame} */ (event.data);
- if (!this._frameFilter(frame))
+ if (!this._frameFilter(frame)) {
return;
+ }
this._dataGrid.insertChild(new Network.ResourceWebSocketFrameNode(this._request.url(), frame));
}
@@ -151,8 +153,9 @@ Network.ResourceWebSocketFrameView = class extends UI.VBox {
* @return {boolean}
*/
_frameFilter(frame) {
- if (this._filterType && frame.type !== this._filterType)
+ if (this._filterType && frame.type !== this._filterType) {
return false;
+ }
return !this._filterRegex || this._filterRegex.test(frame.text);
}
@@ -331,11 +334,13 @@ Network.ResourceWebSocketFrameNode = class extends DataGrid.SortableDataGridNode
* @return {?Network.BinaryResourceView}
*/
binaryView() {
- if (this._isTextFrame || this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Error)
+ if (this._isTextFrame || this._frame.type === SDK.NetworkRequest.WebSocketFrameType.Error) {
return null;
+ }
- if (!this._binaryView)
+ if (!this._binaryView) {
this._binaryView = new Network.BinaryResourceView(this._dataText, /* url */ '', Common.resourceTypes.WebSocket);
+ }
return this._binaryView;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
index 4186fc9d184..d86b5bca146 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
@@ -89,7 +89,7 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
const viewCertLink = certURLElement.createChild('span', 'devtools-link header-toggle');
viewCertLink.textContent = Common.UIString('View certificate');
viewCertLink.addEventListener(
- 'click', InspectorFrontendHost.showCertificateViewer.bind(null, signature.certificates), false);
+ 'click', Host.InspectorFrontendHost.showCertificateViewer.bind(null, signature.certificates), false);
}
signatureCategory.createLeaf(certURLElement);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/module.json b/chromium/third_party/blink/renderer/devtools/front_end/network/module.json
index a8acd65e9fd..84af072b242 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/module.json
@@ -201,6 +201,7 @@
"RequestCookiesView.js",
"RequestHeadersView.js",
"RequestHTMLView.js",
+ "RequestInitiatorView.js",
"RequestResponseView.js",
"RequestPreviewView.js",
"RequestTimingView.js",
@@ -222,6 +223,7 @@
"requestHeadersTree.css",
"requestHeadersView.css",
"requestHTMLView.css",
+ "requestInitiatorView.css",
"signedExchangeInfoTree.css",
"signedExchangeInfoView.css",
"webSocketFrameView.css"
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/networkLogView.css b/chromium/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
index 92379f56f0d..51ca47755fe 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/networkLogView.css
@@ -131,10 +131,19 @@
}
.network-error-row,
-.network-error-row .network-cell-subtitle {
- color: rgb(230, 0, 0);
+.network-error-row .network-cell-subtitle ,
+.network-log-grid.data-grid tr.selected.network-error-row,
+.network-log-grid.data-grid tr.selected.network-error-row .network-cell-subtitle,
+.network-log-grid.data-grid tr.selected.network-error-row .network-dim-cell {
+ color: rgb(230, 0, 0) !important;
}
+.network-log-grid.data-grid:focus tr.selected.network-error-row,
+.network-log-grid.data-grid:focus tr.selected.network-error-row .network-cell-subtitle,
+.network-log-grid.data-grid:focus tr.selected.network-error-row .network-dim-cell {
+ background: hsl(0, 100%, 97%) !important;
+ color: rgb(230, 0, 0) !important;
+}
.initiator-column .devtools-link {
color: inherit;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
index df07c9a2337..67b67517149 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/network_strings.grdp
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <message name="IDS_DEVTOOLS_008aa5b6435af8504757085a92b2eb28" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge (EdgeHTML) — XBox</ph>
+ </message>
<message name="IDS_DEVTOOLS_0194336f90a2b1de65553e3bec01becd" desc="Text in Network Log View of the Network panel">
Copy as fetch
</message>
@@ -9,12 +12,15 @@
<message name="IDS_DEVTOOLS_02d56cf7754ce16d7ce0193fbca7c90a" desc="Text in Network Config View of the Network panel">
Caching
</message>
- <message name="IDS_DEVTOOLS_040c4b52a3c06c6067fac76c4c7c3a2c" desc="Title of the 'Network conditions' tool in the bottom drawer">
- Network conditions
+ <message name="IDS_DEVTOOLS_0382c94481db9197dd5a72ea4bdd2ff0" desc="A tag of Network Conditions tool that can be searched in the command menu">
+ disk cache
</message>
<message name="IDS_DEVTOOLS_059f48d76d79fe0727740d75dc81fa94" desc="Text in Network Log View of the Network panel">
<ph name="SELECTEDTRANSFERSIZE">$1s<ex>25</ex></ph> B / <ph name="TRANSFERSIZE">$2s<ex>25</ex></ph> B transferred
</message>
+ <message name="IDS_DEVTOOLS_05ffb3b626077843c5f71d13185391d8" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Safari — iPad iOS 9</ph>
+ </message>
<message name="IDS_DEVTOOLS_06337a0bc6e91b2adb10567bee4d6f14" desc="Text in Network Log View of the Network panel">
Copy all as HAR
</message>
@@ -33,15 +39,18 @@
<message name="IDS_DEVTOOLS_0bcc4ec10c2e4cee4b9bbabd48501304" desc="Text in Resource Web Socket Frame View of the Network panel">
Select message to browse its content.
</message>
+ <message name="IDS_DEVTOOLS_0c1ac4502b106b89cbf1d3850f44ae12" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Android (4.0.2) Browser — Galaxy Nexus</ph>
+ </message>
<message name="IDS_DEVTOOLS_0db377921f4ce762c62526131097968f" desc="Text in Request Headers View of the Network panel">
General
</message>
- <message name="IDS_DEVTOOLS_0f44e9e39cbe2f22bd1bd7b6070cf13d" desc="Text in Blocked URLs Pane of the Network panel">
- Enable request blocking
- </message>
<message name="IDS_DEVTOOLS_0f591b1d87c91e77d4fa11dc6e44288c" desc="Text in Network Item View of the Network panel">
Request and response timeline
</message>
+ <message name="IDS_DEVTOOLS_100b560e280fea6e7d5ab12179d3f0e2" desc="Tooltip to explain what malformed response cookies are">
+ Cookies that were received from the server in the &apos;set-cookie&apos; header of the response but were malformed
+ </message>
<message name="IDS_DEVTOOLS_117068a6e55846888cbb60978fe82ca2" desc="Text in Request Timing View of the Network panel">
Stalled
</message>
@@ -51,8 +60,14 @@
<message name="IDS_DEVTOOLS_12881f9e98bb240671bc3e1787d64a03" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Color code by resource type
</message>
- <message name="IDS_DEVTOOLS_16f78b9465f03f7ec5a03c24918fbde3" desc="Text in Request Headers View of the Network panel">
- Status Code
+ <message name="IDS_DEVTOOLS_16c32be3b42643aee708e7ccdd52c9f4" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge — Android Mobile</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_17439cab6b197fcaff231614384c9dcc" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera (Presto) — Windows</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_1826c1f3d66791128e1f73f876147f2f" desc="A tag of Network color-code resource types that can be searched in the command menu">
+ color code
</message>
<message name="IDS_DEVTOOLS_1854180b02f297deebed0ec452090842" desc="Cell title in Network Data Grid Node of the Network panel">
Served from memory cache, resource size: <ph name="RESOURCESIZE">$1s<ex>50 B</ex></ph>
@@ -69,24 +84,39 @@
<message name="IDS_DEVTOOLS_1b581452e4e1158b75e514c99a760431" desc="Text in Request Headers View of the Network panel">
Request Payload
</message>
+ <message name="IDS_DEVTOOLS_1ba63dd21ea9a100c54e9f5ed8a0d469" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">UC Browser — Windows Phone</ph>
+ </message>
<message name="IDS_DEVTOOLS_1c047e32d57295a9f0319976c543162e" desc="Text in Network Data Grid Node of the Network panel">
(blocked:<ph name="REASON">$1s<ex>mixed-content</ex></ph>)
</message>
<message name="IDS_DEVTOOLS_1cb07ce276f37ba2acdfb8605aaefbb8" desc="Text in Network Log View of the Network panel">
<ph name="RESOURCESIZE">$1s<ex>10</ex></ph> B resources
</message>
+ <message name="IDS_DEVTOOLS_1cf0226d974af378b6aa6070bb2a37c3" desc="A tag of Network Conditions tool that can be searched in the command menu">
+ network throttling
+ </message>
+ <message name="IDS_DEVTOOLS_1d420bebb54e53a8d8a4d809576b58d5" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — Mac</ph>
+ </message>
<message name="IDS_DEVTOOLS_1dc4a71b18d2c3a1442267136158128e" desc="Text in Network Log View of the Network panel">
Copy all as cURL (cmd)
</message>
<message name="IDS_DEVTOOLS_1eb445fa6bd078346bf63ecac35fa77c" desc="Text in Binary Resource View of the Network panel">
Base64
</message>
+ <message name="IDS_DEVTOOLS_20ed2e30da35e48e723855c8e14bfdf1" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge — Android Tablet</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_21fd2e738b03921c90da8ac98319a04b" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — Windows</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_22f3e616a52e25632d98fd53d3f821ed" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Safari — Mac</ph>
+ </message>
<message name="IDS_DEVTOOLS_2537b3e6907e17001b7cdf121cd39dc0" desc="Text in Request Headers View of the Network panel">
(from ServiceWorker)
</message>
- <message name="IDS_DEVTOOLS_25f77a709e3c31285e8411402420b72d" desc="Text in Blocked URLs Pane of the Network panel">
- Requests are not blocked. <ph name="ADDLINK">$1s<ex>Add pattern</ex></ph>.
- </message>
<message name="IDS_DEVTOOLS_26b6b5ae2c6e2575b2a451c35e94df23" desc="Text in Request Timing View of the Network panel">
Waiting (TTFB)
</message>
@@ -96,8 +126,8 @@
<message name="IDS_DEVTOOLS_29d37bdcfeb74d25d56bcf841866ae32" desc="Cell title in Network Data Grid Node of the Network panel">
Served from ServiceWorker, resource size: <ph name="RESOURCESIZE">$1s<ex>4 B</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_2bbc845892f400626baab5af687527c5" desc="Text in Network Log View Columns of the Network panel">
- Start Time
+ <message name="IDS_DEVTOOLS_2ad7f735dd6d0dedb0d010a612854a17" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer 8</ph>
</message>
<message name="IDS_DEVTOOLS_2d13df6f8b5e4c5af9f87e0dc39df69d" desc="Text in Network Data Grid Node of the Network panel">
Pending
@@ -114,9 +144,6 @@
<message name="IDS_DEVTOOLS_31977081ea2c828cc70e6151ab5d7da8" desc="Text in Request Headers View of the Network panel">
view decoded
</message>
- <message name="IDS_DEVTOOLS_31fde7b05ac8952dacf4af8a704074ec" desc="Text in Network Item View of the Network panel">
- Preview
- </message>
<message name="IDS_DEVTOOLS_336439019ce67912717a20d54298bf24" desc="Text in Request Timing View of the Network panel">
Receiving Push
</message>
@@ -135,15 +162,24 @@
<message name="IDS_DEVTOOLS_37bb3bd9caf5dafb7c8f9eccb3b9800e" desc="Text in Request Headers View of the Network panel">
(unable to decode value)
</message>
+ <message name="IDS_DEVTOOLS_37eabd36dcdd3c4f4586c88a7354d10d" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge (Chromium) — Windows</ph>
+ </message>
<message name="IDS_DEVTOOLS_383fc50a38f1666adc3f06d0bdf71467" desc="Text in Network Log View of the Network panel">
Are you sure you want to clear browser cookies?
</message>
+ <message name="IDS_DEVTOOLS_39b8414d89adf80e97ec0024e13e3b86" desc="Text in Request Initiator view of the Network Panel">
+ Request call stack
+ </message>
<message name="IDS_DEVTOOLS_3b5904efd4efd03d09ee9a8f964f39d6" desc="Text in Network Log View of the Network panel">
<ph name="NUMBER_BYTESTOSTRING_RESOURCESIZE_">$1s<ex>4</ex></ph> resources
</message>
<message name="IDS_DEVTOOLS_3b83f6ae91bb21147fd97b8b8229287f" desc="Text in Signed Exchange Info View of the Network panel">
Certificate URL
</message>
+ <message name="IDS_DEVTOOLS_3b8fa30c5cdb1ef67ffdd3bf7ba9ff4b" desc="Screen reader label for a select box that chooses how to display binary data in the Network panel">
+ Binary view type
+ </message>
<message name="IDS_DEVTOOLS_3c06899dae839e1ca3051475a2b8fa05" desc="Text in Request Preview View of the Network panel">
Preview not available
</message>
@@ -159,6 +195,15 @@
<message name="IDS_DEVTOOLS_3e0dc7bd31f5ad41b900fef5b7aba791" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Don&apos;t group network log items by frame
</message>
+ <message name="IDS_DEVTOOLS_3ebfafd757759c5e0081920b36450c58" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — Android Mobile</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_408f8a4ecdacbe1d9989b800a0c12936" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer 11</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_4145ea54b6f576d7646d6a68eb39813f" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera (Presto) — Mac</ph>
+ </message>
<message name="IDS_DEVTOOLS_41de6d6cfb8953c021bbe4ba0701c8a1" desc="Text in Network Item View of the Network panel">
Messages
</message>
@@ -174,6 +219,9 @@
<message name="IDS_DEVTOOLS_44749712dbec183e983dcd78a7736c41" desc="Text in Signed Exchange Info View of the Network panel">
Date
</message>
+ <message name="IDS_DEVTOOLS_44bea05ea1f4af197ad4b6453e04a0eb" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — Android Tablet</ph>
+ </message>
<message name="IDS_DEVTOOLS_4566ce384ed4a889beb6f6432d5906d7" desc="The UI destination when right clicking an item that can be revealed">
Network panel
</message>
@@ -195,12 +243,6 @@
<message name="IDS_DEVTOOLS_4a7ba0d17eafde708ca8f5f34debcfef" desc="Text in Network Log View of the Network panel">
<ph name="TRANSFERSIZE">$1s<ex>4</ex></ph> B transferred
</message>
- <message name="IDS_DEVTOOLS_4bd7c2ff07dcc66801a9368957d4bff8" desc="Text in Network Log View Columns of the Network panel">
- Initiator
- </message>
- <message name="IDS_DEVTOOLS_4c3880bb027f159e801041b1021e88e8" desc="Text in Network Log View Columns of the Network panel">
- Method
- </message>
<message name="IDS_DEVTOOLS_4dea2ac78e9450e62e96c166ef9f5d4c" desc="Text in Network Log View Columns of the Network panel">
Manage Header Columns…
</message>
@@ -213,18 +255,21 @@
<message name="IDS_DEVTOOLS_5023e5b1d1c02cf168a9a67dda6d2d87" desc="Text in Network Panel of the Network panel">
Show overview
</message>
- <message name="IDS_DEVTOOLS_502996d9790340c5fd7b86a5b93b1c9f" desc="Text in Network Log View Columns of the Network panel">
- Priority
+ <message name="IDS_DEVTOOLS_50de9bc68c93dc32d8c7c90593471760" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Safari</ph>
</message>
<message name="IDS_DEVTOOLS_5101cdda28ea3097ac00cdbfdcedc353" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Use default colors
</message>
- <message name="IDS_DEVTOOLS_51360304ea03557e79bdf5ff9cd2e234" desc="Text in Signed Exchange Info View of the Network panel">
- Issuer
+ <message name="IDS_DEVTOOLS_52c2263c92c8b0f41e36892ccd8cb119" desc="Accessible label for the button to add request blocking patterns in the Request blocking tool">
+ Add request blocking pattern
</message>
<message name="IDS_DEVTOOLS_53fa249ce3d02c8a686b657b31d02ee7" desc="Text in Network Log View of the Network panel">
Copy response
</message>
+ <message name="IDS_DEVTOOLS_549fae23948f165d8dbb68c9a17b8c44" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — Android Mobile</ph>
+ </message>
<message name="IDS_DEVTOOLS_5639d3df5aea3d9e78027b843ee3cbb2" desc="Text in Resource Web Socket Frame View of the Network panel">
Receive
</message>
@@ -243,30 +288,27 @@
<message name="IDS_DEVTOOLS_59535aed1e49266dfd0b93172f5a7242" desc="Text in Network Panel of the Network panel">
Group by frame
</message>
- <message name="IDS_DEVTOOLS_597b56e53847cd6a4712ac183f61fa68" desc="Text in Network Item View of the Network panel">
- Cookies
+ <message name="IDS_DEVTOOLS_59f2df528ff5c941c8d6308288a83141" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — iPad</ph>
</message>
<message name="IDS_DEVTOOLS_5cb98890f19c13e5fce52287187d9803" desc="Text in Network Log View of the Network panel">
<ph name="SELECTEDNODENUMBER">$1s<ex>3</ex></ph> / <ph name="NODECOUNT">$2s<ex>5</ex></ph> requests
</message>
+ <message name="IDS_DEVTOOLS_5d849c6c271a039aba239a13132c5dd5" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — Mac</ph>
+ </message>
<message name="IDS_DEVTOOLS_5e2f683aacb9d5f3635b3f88583dec80" desc="Text in Network Config View of the Network panel">
Custom...
</message>
- <message name="IDS_DEVTOOLS_5f0ea62e5bc9f795512ef292ff162a2a" desc="Tooltip text that appears on the setting when hovering over it in Network Panel of the Network panel">
- Disable cache (while DevTools is open)
- </message>
<message name="IDS_DEVTOOLS_5f903b8316b9649547e1b3ceef934183" desc="Title of an action in the network tool to toggle recording">
Stop recording network log
</message>
<message name="IDS_DEVTOOLS_611a2b5dcde004cf68ffd56345584d40" desc="Text in Network Log View Columns of the Network panel">
- ETag
+ <ph name="LOCKED_1">ETag</ph>
</message>
<message name="IDS_DEVTOOLS_619d32de7168c6e770464dfc43e374d1" desc="Text in Request Headers View of the Network panel">
Request Headers
</message>
- <message name="IDS_DEVTOOLS_6311ae17c1ee52b36e68aaf4ad066387" desc="Cell title in Network Data Grid Node of the Network panel">
- Other
- </message>
<message name="IDS_DEVTOOLS_6490fac2ddb40e1e2a7e0c43fb661c7b" desc="Text in Request Preview View of the Network panel">
Failed to load response data
</message>
@@ -283,7 +325,10 @@
Header Name
</message>
<message name="IDS_DEVTOOLS_6a98894cd6b4628f0b5117412aab083e" desc="Text in Network Log View Columns of the Network panel">
- Cache-Control
+ <ph name="LOCKED_1">Cache-Control</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_6b41d86d21d49c95f5b106fb2ed95762" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer 10</ph>
</message>
<message name="IDS_DEVTOOLS_6c2a1bf87fb84c91fc7e1120f4e3d0c7" desc="Text in Request Timing View of the Network panel">
Content Download
@@ -294,15 +339,24 @@
<message name="IDS_DEVTOOLS_6dd7482f131dc036ea08395a7f3f5e08" desc="Other user agent element placeholder in Network Config View of the Network panel">
Enter a custom user agent
</message>
+ <message name="IDS_DEVTOOLS_6dec00f9ae08edb5af58e6efb699dba0" desc="Label for showing request cookies that were not actually sent">
+ show filtered out request cookies
+ </message>
<message name="IDS_DEVTOOLS_6e68a529a38966508d348e9f65d7ea31" desc="Title of an action in the network tool to toggle recording">
Record network log
</message>
+ <message name="IDS_DEVTOOLS_71f5989793ddede100da3fde07d1f9f9" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera Mini — iOS</ph>
+ </message>
<message name="IDS_DEVTOOLS_71fb2761cd2a446400a8069fe16cd45e" desc="A context menu item in the Network Log View of the Network panel">
Block request domain
</message>
<message name="IDS_DEVTOOLS_722e6ea747a62b7f93bb017d3dd04cbd" desc="Op codes continuation frame of map in Resource Web Socket Frame View of the Network panel">
Continuation Frame
</message>
+ <message name="IDS_DEVTOOLS_f5a6d40aab4d260009df79b7dab7e6a0" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge — iPhone</ph>
+ </message>
<message name="IDS_DEVTOOLS_72d569ab3718d10a89315f80cf05cc73" desc="Title of a setting under the Network category in Settings">
Group network log by frame
</message>
@@ -312,9 +366,15 @@
<message name="IDS_DEVTOOLS_7543ba96bb16a5f17f8fb25bdd995d3f" desc="Text in Binary Resource View of the Network panel">
Copy as Base64
</message>
+ <message name="IDS_DEVTOOLS_763f7f1aec350cd1a46238d1d5c3c229" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox</ph>
+ </message>
<message name="IDS_DEVTOOLS_76669aaf74dda2a59e3c363da10c3faf" desc="Text in Request Timing View of the Network panel">
Reading Push
</message>
+ <message name="IDS_DEVTOOLS_77c0ed7e4536e1c251279fa0c90bca50" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge (EdgeHTML) — Windows</ph>
+ </message>
<message name="IDS_DEVTOOLS_77f02f5047451625e1c6bb24884cdfe6" desc="Text in Binary Resource View of the Network panel">
Copied as Hex
</message>
@@ -327,6 +387,12 @@
<message name="IDS_DEVTOOLS_795f3202b17cb6bc3d4b771d8c6c9eaf" desc="Reason in Network Data Grid Node of the Network panel">
other
</message>
+ <message name="IDS_DEVTOOLS_7a4feae759066e44a88f2e6610d5a757" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera — Mac</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_7a8cfc6a08f7d15e1d612ea47e68b67c" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer 7</ph>
+ </message>
<message name="IDS_DEVTOOLS_7b5bea45778433caf34b0ba556a7d93b" desc="Text in Network Data Grid Node of the Network panel">
(failed)
</message>
@@ -339,14 +405,20 @@
<message name="IDS_DEVTOOLS_7e1c4c7b01e0fd0ad1e89ca7512f353e" desc="Op codes ping frame of map in Resource Web Socket Frame View of the Network panel">
Ping Message
</message>
+ <message name="IDS_DEVTOOLS_7e2709c4d40a9827390281d60aae22a7" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — iPhone</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_7ee22334256f1cf5538adc052ebf96bf" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Safari — iPhone iOS 9</ph>
+ </message>
<message name="IDS_DEVTOOLS_804910399e8d26511871e33416ccd127" desc="Cell title in Network Data Grid Node of the Network panel">
Served from disk cache, resource size: <ph name="RESOURCESIZE">$1s<ex>10 B</ex></ph>
</message>
<message name="IDS_DEVTOOLS_814f9c3c7e7aa04c21f2e61f5b2dcf18" desc="Text in Network Log View of the Network panel">
Copy response headers
</message>
- <message name="IDS_DEVTOOLS_8166a4b3fb4979da3a24ed21ced7fdf7" desc="Text in Signed Exchange Info View of the Network panel">
- Learn more
+ <message name="IDS_DEVTOOLS_81c1f883582dfa740bba882106414bd3" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">BlackBerry — PlayBook 2.1</ph>
</message>
<message name="IDS_DEVTOOLS_827452688eed02a12178e96f924ac529" desc="Text in Network Log View Columns of the Network panel">
Scheme
@@ -354,9 +426,6 @@
<message name="IDS_DEVTOOLS_838c672414343cdd527a63d910fb132c" desc="Text in Network Log View of the Network panel">
Hide data URLs
</message>
- <message name="IDS_DEVTOOLS_850985cd851d0fe440f03f77762e2590" desc="Text in Network Log View Columns of the Network panel">
- Content-Length
- </message>
<message name="IDS_DEVTOOLS_8644fe7afb1a31ea7274f5ee90dff50b" desc="Text in Request Headers View of the Network panel">
view URL encoded
</message>
@@ -366,15 +435,6 @@
<message name="IDS_DEVTOOLS_881e9a305ce80960413ab7f227ef879e" desc="Text in Network Config View of the Network panel">
User agent
</message>
- <message name="IDS_DEVTOOLS_883d7615c4d2de3fa1218f1298c46d0e" desc="Text in Network Item View of the Network panel">
- Headers
- </message>
- <message name="IDS_DEVTOOLS_884680dd63eae99eab1a407133df66b7" desc="View cert link text content in Signed Exchange Info View of the Network panel">
- View certificate
- </message>
- <message name="IDS_DEVTOOLS_888a77f5ac0748b6c8001822417df8b6" desc="Text in Network Log View Columns of the Network panel">
- Protocol
- </message>
<message name="IDS_DEVTOOLS_889f316cd1f0ac68f8ea3052e8568061" desc="Text in Network Log View of the Network panel">
Copy as PowerShell
</message>
@@ -382,7 +442,7 @@
Set Cookies
</message>
<message name="IDS_DEVTOOLS_8c074f405ad9737b1b59d35d6aab7cab" desc="Text in Network Log View Columns of the Network panel">
- Last-Modified
+ <ph name="LOCKED_1">Last-Modified</ph>
</message>
<message name="IDS_DEVTOOLS_8c09001c99ecb6fdd8d6023fcf039054" desc="Text in Signed Exchange Info View of the Network panel">
Signature
@@ -408,6 +468,9 @@
<message name="IDS_DEVTOOLS_90198f1c07c67e3a44ccc6853651ca2c" desc="A context menu item in the Network Log View Columns of the Network panel">
Response Headers
</message>
+ <message name="IDS_DEVTOOLS_91398186000d456abea27e5d8805dde7" desc="Tooltip for initiator view in Network panel">
+ Request initiator call stack
+ </message>
<message name="IDS_DEVTOOLS_9146d056f26c33effdc2f83dd9e79395" desc="Text in Network Log View of the Network panel">
Copy all as cURL (bash)
</message>
@@ -432,14 +495,11 @@
<message name="IDS_DEVTOOLS_94966d90747b97d1f0f206c98a8b1ac3" desc="Text in Resource Web Socket Frame View of the Network panel">
Send
</message>
- <message name="IDS_DEVTOOLS_96b0141273eabab320119c467cdcaf17" desc="Text in Request Timing View of the Network panel">
- Total
- </message>
<message name="IDS_DEVTOOLS_96d960cc2b3394824ebfbf25bb960a90" desc="Text in Resource Web Socket Frame View of the Network panel">
<ph name="LOCALIZEDDESCRIPTION">$1s<ex>Text Message</ex></ph> (Opcode <ph name="OPCODE">$2s<ex>0</ex></ph>, mask)
</message>
- <message name="IDS_DEVTOOLS_96e9bc575b5d3ed541113a249da8bd24" desc="Text in Network Panel of the Network panel">
- Capture screenshots
+ <message name="IDS_DEVTOOLS_9777b991eb3f0c11b20bab298b6a3077" desc="A tag of Network color-code resource types that can be searched in the command menu">
+ resource type
</message>
<message name="IDS_DEVTOOLS_97b7320892b0db86ff1d8dc28ba1af95" desc="Text in Network Log View of the Network panel">
Are you sure you want to clear browser cache?
@@ -447,6 +507,12 @@
<message name="IDS_DEVTOOLS_97f0a2ba508f8299c686818366ad712a" desc="Text in Network Data Grid Node of the Network panel">
(data)
</message>
+ <message name="IDS_DEVTOOLS_9813946564c3a3698618ad520f6d1e69" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">BlackBerry</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_9825e566e3304756959d9ba52b5903d3" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — Android Tablet</ph>
+ </message>
<message name="IDS_DEVTOOLS_985187565936a7c1e02c9f96852c0f9a" desc="Reason in Network Data Grid Node of the Network panel">
subresource-filter
</message>
@@ -456,6 +522,9 @@
<message name="IDS_DEVTOOLS_986491ef3610ed7ef82bd863e4ee00a2" desc="Title of the 'Request blocking' tool in the bottom drawer">
Request blocking
</message>
+ <message name="IDS_DEVTOOLS_986c37480b1f1c2e443504b38b6361b4" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome</ph>
+ </message>
<message name="IDS_DEVTOOLS_9979c41f94d4d232c06b4c87f2d0f951" desc="Text in Network Data Grid Node of the Network panel">
Push / '''
</message>
@@ -466,7 +535,7 @@
Parser
</message>
<message name="IDS_DEVTOOLS_9aa1b03934893d7134a660af4204f2a9" desc="Text in Network Log View Columns of the Network panel">
- Server
+ <ph name="LOCKED_1">Server</ph>
</message>
<message name="IDS_DEVTOOLS_9c1ab57e621c2bb257798752dbbe6f14" desc="Text in Request Headers View of the Network panel">
view source
@@ -477,9 +546,6 @@
<message name="IDS_DEVTOOLS_9e08e91089d39bc26c4c57e9780c2f60" desc="Text in Request Headers View of the Network panel">
(from memory cache)
</message>
- <message name="IDS_DEVTOOLS_9e65b51e82f2a9b9f72ebe3e083582bb" desc="Text in Request Headers View of the Network panel">
- (empty)
- </message>
<message name="IDS_DEVTOOLS_9ffaf77e2c524827dff95993361e7115" desc="Text in Network Item View of the Network panel">
Raw response data
</message>
@@ -492,6 +558,12 @@
<message name="IDS_DEVTOOLS_a09b75f1cd4e3d54099fa8e14ff5056d" desc="From service worker format in Network Time Calculator of the Network panel">
<ph name="PH1">$1s<ex>20ms latency</ex></ph> (from ServiceWorker)
</message>
+ <message name="IDS_DEVTOOLS_a12a6481ad87f558622dcf0a1a87982a" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">UC Browser — Android Mobile</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_a16761bfe43337abda8aedb823fe0a10" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">BlackBerry — 9900</ph>
+ </message>
<message name="IDS_DEVTOOLS_a217246afb12245a032617715f81923b" desc="Text in Network Manage Custom Headers View of the Network panel">
Manage Header Columns
</message>
@@ -504,6 +576,9 @@
<message name="IDS_DEVTOOLS_a299d2f506523f8104dc4202de7b0c64" desc="Tooltip text that appears when hovering over the largeicon download button in the Network Panel of the Network panel">
Export HAR...
</message>
+ <message name="IDS_DEVTOOLS_a5c41f715c1b8a880253846c025624e9" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge</ph>
+ </message>
<message name="IDS_DEVTOOLS_a5d6e0224f694699dde6d1bd34d608bd" desc="Text in Network Log View of the Network panel">
Copy as cURL
</message>
@@ -513,8 +588,8 @@
<message name="IDS_DEVTOOLS_a74e6894e1f36ce12a6773b9a6b9aea8" desc="Text in Network Log View of the Network panel">
<ph name="NODECOUNT">$1s<ex>6</ex></ph> requests
</message>
- <message name="IDS_DEVTOOLS_a76d4ef5f3f6a672bbfab2865563e530" desc="Text in Event Source Messages View of the Network panel">
- Time
+ <message name="IDS_DEVTOOLS_a956e985535b8d57732d14dfa0e4c71a" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera</ph>
</message>
<message name="IDS_DEVTOOLS_a976624c5265b8187b19aea9df9230eb" desc="Title of a setting under the Network category in Settings">
Color-code resource types
@@ -525,6 +600,9 @@
<message name="IDS_DEVTOOLS_ac5eb504b5a840271e066bf6fd3000b8" desc="Text in Request Headers View of the Network panel">
view parsed
</message>
+ <message name="IDS_DEVTOOLS_ac90a9ac36eb64388ce0e0a9047b295c" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Android (2.3) Browser — Nexus S</ph>
+ </message>
<message name="IDS_DEVTOOLS_ad86890fb40822a3b12627efaca4ecd7" desc="Text of a DOM element in Network Data Grid Node of the Network panel">
(disk cache)
</message>
@@ -534,6 +612,9 @@
<message name="IDS_DEVTOOLS_ae3b3df9970b49b6523e608759bc957d" desc="Text in Binary Resource View of the Network panel">
UTF-8
</message>
+ <message name="IDS_DEVTOOLS_ae89abb57630fcbd1af25cfc6684a5ff" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera Mobile — Android Mobile</ph>
+ </message>
<message name="IDS_DEVTOOLS_af0a229a0c5be77de07889743db3b409" desc="Text in Binary Resource View of the Network panel">
Copied as UTF-8
</message>
@@ -543,21 +624,27 @@
<message name="IDS_DEVTOOLS_b021df6aac4654c454f46c77646e745f" desc="Text in Signed Exchange Info View of the Network panel">
Label
</message>
+ <message name="IDS_DEVTOOLS_b04f746dac7a367d85c411341b6673f6" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Googlebot</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_b08687e344501a098d281a89e77aff6b" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Opera — Windows</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_b1b2ed29de5b9a2a8cf8ba5cf9e52624" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — Chrome OS</ph>
+ </message>
<message name="IDS_DEVTOOLS_b1f63146853f7f450d8622aae6a73408" desc="Text in Network Log View of the Network panel">
Copy as cURL (bash)
</message>
- <message name="IDS_DEVTOOLS_b2844b8e17ecaaeae68d018fe9418af0" desc="Text in Signed Exchange Info View of the Network panel">
- Valid until
- </message>
<message name="IDS_DEVTOOLS_b4774747599df05309e1de2e2734dd3e" desc="Text in Request Timing View of the Network panel">
Request to ServiceWorker
</message>
- <message name="IDS_DEVTOOLS_b6434258c743f8673997b5aeb3721c27" desc="Text in Request Headers View of the Network panel">
- Request Method
- </message>
<message name="IDS_DEVTOOLS_b72ac10807b29c77f5b7e4b80ea40414" desc="Text in Request Timing View of the Network panel">
Explanation
</message>
+ <message name="IDS_DEVTOOLS_b87b6ab319ae2ed428153cd7b6441a90" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — iPad</ph>
+ </message>
<message name="IDS_DEVTOOLS_b926fd82158cde57655d0cd1dd8dbc70" desc="Text in Request Headers View of the Network panel">
Query String Parameters
</message>
@@ -577,7 +664,7 @@
mixed-content
</message>
<message name="IDS_DEVTOOLS_bd9176ee57c46268a853e038b133966a" desc="Text in Network Log View Columns of the Network panel">
- Keep-Alive
+ <ph name="LOCKED_1">Keep-Alive</ph>
</message>
<message name="IDS_DEVTOOLS_bdaacef16991cfa4cf17a388579e7c06" desc="Text in Network Item View of the Network panel">
EventStream
@@ -585,8 +672,14 @@
<message name="IDS_DEVTOOLS_c02504bf83e5cc0d2f582f189a804aef" desc="Text in Request Cookies View of the Network panel">
Request Cookies
</message>
- <message name="IDS_DEVTOOLS_c2cc7082a89c1ad6631a2f66af5f00c0" desc="Text in Network Log View Columns of the Network panel">
- Connection
+ <message name="IDS_DEVTOOLS_c0c7145bdb8a2311e11528eaacf7f41d" desc="Tooltip to explain what request cookies are">
+ Cookies that were sent to the server in the &apos;cookie&apos; header of the request
+ </message>
+ <message name="IDS_DEVTOOLS_c0635a52980f98eff8adf2279c8ad8e0" desc="A tag of Network Conditions tool that can be searched in the command menu">
+ useragent
+ </message>
+ <message name="IDS_DEVTOOLS_c14108bc627e61f0e445dda0ff029f58" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Chrome — iPhone</ph>
</message>
<message name="IDS_DEVTOOLS_c3c14eb17a6cf9c6120f381790ed06eb" desc="Text in Network Log View of the Network panel">
Copy all as PowerShell
@@ -600,24 +693,33 @@
<message name="IDS_DEVTOOLS_c6f969f563d21beac9731f177053484c" desc="Text in Network Log View of the Network panel">
<ph name="SELECTEDRESOURCESIZE">$1s<ex>40</ex></ph> B / <ph name="RESOURCESIZE">$2s<ex>50</ex></ph> B resources
</message>
- <message name="IDS_DEVTOOLS_c7892ebbb139886662c6f2fc8c450710" desc="Text in Signed Exchange Info View of the Network panel">
- Subject
- </message>
<message name="IDS_DEVTOOLS_c81e295bfd7fbaec6257ea14992f4643" desc="Text in Network Item View of the Network panel">
Request and response cookies
</message>
<message name="IDS_DEVTOOLS_c84718b71b8ad70dde23736e79e25e83" desc="Op codes pong frame of map in Resource Web Socket Frame View of the Network panel">
Pong Message
</message>
+ <message name="IDS_DEVTOOLS_c89585ee0469e9a3824828ae8961555b" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge (Chromium) — Mac</ph>
+ </message>
<message name="IDS_DEVTOOLS_c91a577b72313356fad611c55f43c10f" desc="Text in Network Log View Columns of the Network panel">
End Time
</message>
+ <message name="IDS_DEVTOOLS_caae91004cd7ecb81b25a7c4536e289f" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">UC Browser — iOS</ph>
+ </message>
<message name="IDS_DEVTOOLS_cb64a2679b345ae476ea3a7fb6a70080" desc="Op codes binary frame of map in Resource Web Socket Frame View of the Network panel">
Binary Message
</message>
<message name="IDS_DEVTOOLS_cc0af601bfd673427a8abb171f62c707" desc="Reason in Network Data Grid Node of the Network panel">
content-type
</message>
+ <message name="IDS_DEVTOOLS_cc910147ba0845397ea686345faf7340" desc="Button to add a pattern to block requests in the Request Blocking tool">
+ Requests are not blocked. <ph name="ADD_BUTTON">$1s<ex>Add pattern</ex></ph>
+ </message>
+ <message name="IDS_DEVTOOLS_ce9d64b8fde226fd9e5fa4c0947c7ee0" desc="Tooltip to explain what response cookies are">
+ Cookies that were received from the server in the &apos;set-cookie&apos; header of the response
+ </message>
<message name="IDS_DEVTOOLS_cebd9a3a94f022d3600e0f81a9aa2060" desc="Text in Network Log View of the Network panel">
<ph name="NUMBER_BYTESTOSTRING_SELECTEDRESOURCESIZE_">$1s<ex>40MB</ex></ph> / <ph name="NUMBER_BYTESTOSTRING_RESOURCESIZE_">$2s<ex>50MB</ex></ph> resources
</message>
@@ -633,11 +735,14 @@
<message name="IDS_DEVTOOLS_d0e5383d7c91948cfab6cacccec8812d" desc="Text in Request Headers View of the Network panel">
(from signed-exchange)
</message>
+ <message name="IDS_DEVTOOLS_d21a4ca270bc9a879992b4b3d9510a60" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">UC Browser</ph>
+ </message>
<message name="IDS_DEVTOOLS_d3b69e993f4e9bf9c479c7e794ede387" desc="Text in Network Item View of the Network panel">
Timing
</message>
- <message name="IDS_DEVTOOLS_d64ed3e9c10229648e069f56e32f4c8e" desc="Text in Network Item View of the Network panel">
- Response
+ <message name="IDS_DEVTOOLS_d6c3c06d819624b743db87f8e1384f58" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Firefox — Windows</ph>
</message>
<message name="IDS_DEVTOOLS_d76e44f856d0114826e7436a630a3fa7" desc="Text of a DOM element in Network Data Grid Node of the Network panel">
(signed-exchange)
@@ -646,20 +751,26 @@
Record (<ph name="RECORDNODE">$1s<ex>Ctrl + E</ex></ph>) to display network activity.
</message>
<message name="IDS_DEVTOOLS_d82a834165b99c4ea0969316296a2bc2" desc="Text in Network Log View Columns of the Network panel">
- Vary
+ <ph name="LOCKED_1">Vary</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_d8e381f360a750d29368d3ec51346006" desc="Label for response cookies with invalid syntax">
+ Malformed Response Cookies
+ </message>
+ <message name="IDS_DEVTOOLS_db0f6f37ebeb6ea09489124345af2a45" desc="A tag of Group Network by frame setting that can be searched in the command menu">
+ group
</message>
<message name="IDS_DEVTOOLS_db67b2de0114bd82fe1383aa067fa6b2" desc="A context menu item in the Network Log View of the Network panel">
Unblock <ph name="CROPPEDURL">$1s<ex>example.com</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_dc30bc0c7914db5918da4263fce93ad2" desc="Tooltip text that appears when hovering over the largeicon clear button in the Network Panel of the Network panel">
- Clear
- </message>
<message name="IDS_DEVTOOLS_dc5d60b066d9a30e68dd648dcabf8579" desc="Text in Request Cookies View of the Network panel">
This request has no cookies.
</message>
<message name="IDS_DEVTOOLS_dc66e209093fbef0daa224f2b6401b39" desc="Text in Request Timing View of the Network panel">
Request/Response
</message>
+ <message name="IDS_DEVTOOLS_dcf3e36ee8115282aad46485cab6a4be" desc="A tag of Group Network by frame setting that can be searched in the command menu">
+ frame
+ </message>
<message name="IDS_DEVTOOLS_dd47445f60115097d07d4cf2e61d933b" desc="Text of a DOM element in Request Timing View of the Network panel">
CAUTION: request is not finished yet!
</message>
@@ -678,9 +789,6 @@
<message name="IDS_DEVTOOLS_df080c10e2e9f1e98c180fe2645f6132" desc="Text in Request Headers View of the Network panel">
Request URL
</message>
- <message name="IDS_DEVTOOLS_e02d2ae03de9d493df2b6b2d2813d302" desc="Text that labels the length of time a network request took.">
- Duration
- </message>
<message name="IDS_DEVTOOLS_e12d71bcdc8fd61f60b6fdccb4b5fedd" desc="Latency download total format in Network Time Calculator of the Network panel">
<ph name="PH1">$1s<ex>20ms</ex></ph> latency, <ph name="PH2">$2s<ex>20ms</ex></ph> download (<ph name="PH3">$3s<ex>40ms</ex></ph> total)
</message>
@@ -702,8 +810,11 @@
<message name="IDS_DEVTOOLS_e6fb9da54f521b9c33d41121d4fcd35c" desc="Text of a DOM element in Network Data Grid Node of the Network panel">
(memory cache)
</message>
- <message name="IDS_DEVTOOLS_e77fef0167598bb39846637ac3915f4e" desc="Tooltip text that appears when hovering over the largeicon clear button in the Resource Web Socket Frame View of the Network panel">
- Clear All
+ <message name="IDS_DEVTOOLS_e84e30b9390cdb64db6db2c9ab87846d" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Android</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_e930f2148ae22be78152a04aa1a290b7" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">BlackBerry — BB10</ph>
</message>
<message name="IDS_DEVTOOLS_ea52c36203c5f99c3ce2442d531b1a22" desc="Text in Request Timing View of the Network panel">
SSL
@@ -711,14 +822,11 @@
<message name="IDS_DEVTOOLS_eb0bd7de3ba805621bf9e03e4d16b510" desc="Text of a DOM element in Request Timing View of the Network panel">
Queued at <ph name="CALCULATOR_FORMATVALUE_REQUEST_ISSUETIME______">$1s<ex>120.39ms</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_eb0f48a107df1a0f343d4cd513b555e6" desc="Text in Signed Exchange Info View of the Network panel">
- Certificate
+ <message name="IDS_DEVTOOLS_ebe4f447bd3316e4f81ab2a6d2f26810" desc="A group title in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer</ph>
</message>
- <message name="IDS_DEVTOOLS_eb902cf204f3e4dfffeb56d92a9b5c26" desc="Text in Signed Exchange Info View of the Network panel">
- Valid from
- </message>
- <message name="IDS_DEVTOOLS_ec53a8c4f07baed5d8825072c89799be" desc="Text in Network Log View Columns of the Network panel">
- Status
+ <message name="IDS_DEVTOOLS_ec0492b0eb0336c99c83c68f109b3561" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Microsoft Edge — iPad</ph>
</message>
<message name="IDS_DEVTOOLS_ec559fc895e8cc77ef0c4d6fdff5bdcb" desc="Text in Request Headers View of the Network panel">
Form Data
@@ -727,7 +835,7 @@
Started at <ph name="CALCULATOR_FORMATVALUE_REQUEST_STARTTIME____">$1s<ex>120.39ms</ex></ph>
</message>
<message name="IDS_DEVTOOLS_edfffa5a1ffba7492b25869813e7e15e" desc="Text in Network Log View Columns of the Network panel">
- Content-Encoding
+ <ph name="LOCKED_1">Content-Encoding</ph>
</message>
<message name="IDS_DEVTOOLS_ef110dd7355d7315c73995a47fe77dfd" desc="Text in Request Timing View of the Network panel">
DNS Lookup
@@ -741,6 +849,9 @@
<message name="IDS_DEVTOOLS_f15c1cae7882448b3fb0404682e17e61" desc="Text in Network Log View Columns of the Network panel">
Content
</message>
+ <message name="IDS_DEVTOOLS_f2a4bb0e0bae2587046fb2bd377f3922" desc="A tag of Network Conditions tool that can be searched in the command menu">
+ user agent
+ </message>
<message name="IDS_DEVTOOLS_f312b3f268931a1367de22756237b197" desc="Text in Network Item View of the Network panel">
Headers and request body
</message>
@@ -762,15 +873,15 @@
<message name="IDS_DEVTOOLS_f6d1d4157b75f9b68298f7df187a177c" desc="Text in Network Log View of the Network panel">
Finish: <ph name="NUMBER_SECONDSTOSTRING_MAXTIME___BASETIME_">$1s<ex>120ms</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_f6ff4cc9a6290608b928788dd6972b75" desc="Text in Request Headers View of the Network Panel">
+ No request cookies were sent.
+ </message>
<message name="IDS_DEVTOOLS_f750833a940ae1ba3cd75b86d520fda3" desc="From cache format in Network Time Calculator of the Network panel">
<ph name="PH1">$1s<ex>20ms latency</ex></ph> (from cache)
</message>
<message name="IDS_DEVTOOLS_f9069c6541beaac49cce4b2542069f02" desc="Text in Request Headers View of the Network panel">
Referrer Policy
</message>
- <message name="IDS_DEVTOOLS_f907e651164789346ae0a1e257c462d8" desc="Text in Network Data Grid Node of the Network panel">
- Script
- </message>
<message name="IDS_DEVTOOLS_f95d3d09fc16ae9294fbef87ac8d17cb" desc="Text in Network Data Grid Node of the Network panel">
(pending)
</message>
@@ -789,4 +900,10 @@
<message name="IDS_DEVTOOLS_fe1bc3eb2f3e1a9a90b5401eb6baa5b9" desc="Text in Network Log View of the Network panel">
Copy all as cURL
</message>
-</grit-part> \ No newline at end of file
+ <message name="IDS_DEVTOOLS_fec7b18500d718dc2ba515971366d74e" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Internet Explorer 9</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_fef333b290196b891e522e03e5c9fd06" desc="An option in the user agent dropdown menu in the Network conditions tool">
+ <ph name="LOCKED_1">Googlebot Smartphone</ph>
+ </message>
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/requestCookiesView.css b/chromium/third_party/blink/renderer/devtools/front_end/network/requestCookiesView.css
index d771b1aa18c..c4023b2685f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/requestCookiesView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/requestCookiesView.css
@@ -5,17 +5,45 @@
*/
.request-cookies-view {
- display: flex;
overflow: auto;
- margin: 12px;
+ padding: 12px;
height: 100%;
}
-.request-cookies-view .data-grid {
- flex: auto;
- height: 100%;
+.request-cookies-view .request-cookies-title {
+ font-size: 12px;
+ font-weight: bold;
+ margin-right: 30px;
+ color: rgb(97, 97, 97);
}
-.request-cookies-view .data-grid .row-group {
- font-weight: bold;
+.request-cookies-view .cookie-line {
+ margin-top: 6px;
+ display: inline-block;
+}
+
+.request-cookies-view .cookies-panel-item {
+ margin-top: 6px;
+ margin-bottom: 16px;
+ flex: none;
+}
+
+.request-cookies-view .cookie-table .flagged-cookie-row {
+ background-color: yellow;
+}
+
+.cookie-warning-icon {
+ margin-right: 4px;
+}
+
+td.flagged-cookie-attribute-cell .cookie-warning-icon {
+ filter: grayscale();
+}
+
+.request-cookies-view tr.revealed.data-grid-data-grid-node.flagged-cookie-attribute-row:not(.selected):nth-child(odd) {
+ background-color: hsl(51, 85%, 80%);
+}
+
+.request-cookies-view tr.revealed.data-grid-data-grid-node.flagged-cookie-attribute-row:not(.selected):nth-child(even) {
+ background-color: rgb(255, 240, 155);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/requestInitiatorView.css b/chromium/third_party/blink/renderer/devtools/front_end/network/requestInitiatorView.css
new file mode 100644
index 00000000000..91a3c99047c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/requestInitiatorView.css
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+.request-initiator-view {
+ display: block;
+ margin: 6px;
+}
+
+.request-initiator-view-section-title {
+ font-weight: bold;
+ padding: 4px;
+}
+
+.request-initiator-view-section-title[data-keyboard-focus="true"]:focus {
+ background-color: var(--item-selection-bg-color);
+}
+
+.request-initiator-view-section-content {
+ margin-left: 6px;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
index ccacb538f8e..48c07eff120 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
@@ -8,8 +8,9 @@
*/
NetworkTestRunner.waitForRequestResponse = function(request) {
- if (request.responseReceivedTime !== -1)
+ if (request.responseReceivedTime !== -1) {
return Promise.resolve(request);
+ }
return TestRunner.waitForEvent(
SDK.NetworkManager.Events.RequestUpdated, TestRunner.networkManager,
@@ -20,8 +21,9 @@ NetworkTestRunner.waitForNetworkLogViewNodeForRequest = function(request) {
const networkLogView = UI.panels.network._networkLogView;
const node = networkLogView.nodeForRequest(request);
- if (node)
+ if (node) {
return Promise.resolve(node);
+ }
console.assert(networkLogView._staleRequests.has(request));
@@ -34,8 +36,9 @@ NetworkTestRunner.waitForNetworkLogViewNodeForRequest = function(request) {
NetworkTestRunner.waitForWebsocketFrameReceived = function(wsRequest, message) {
for (const frame of wsRequest.frames()) {
- if (checkFrame(frame))
+ if (checkFrame(frame)) {
return Promise.resolve(frame);
+ }
}
return TestRunner.waitForEvent(SDK.NetworkRequest.Events.WebsocketFrameAdded, wsRequest, checkFrame);
@@ -66,8 +69,9 @@ NetworkTestRunner.dumpNetworkRequests = function() {
TestRunner.addResult('resources count = ' + requests.length);
- for (i = 0; i < requests.length; i++)
+ for (i = 0; i < requests.length; i++) {
TestRunner.addResult(requests[i].url());
+ }
};
NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo = function() {
@@ -81,8 +85,9 @@ NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo = function() {
if (request.signedExchangeInfo().header) {
const header = request.signedExchangeInfo().header;
TestRunner.addResult(` Request URL: ${header.requestUrl}`);
- for (const signature of header.signatures)
+ for (const signature of header.signatures) {
TestRunner.addResult(` Certificate URL: ${signature.certUrl}`);
+ }
}
if (request.signedExchangeInfo().securityDetails) {
const securityDetails = request.signedExchangeInfo().securityDetails;
@@ -90,8 +95,9 @@ NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo = function() {
TestRunner.addResult(` Certificate Issuer: ${securityDetails.issuer}`);
}
if (request.signedExchangeInfo().errors) {
- for (const errorMessage of request.signedExchangeInfo().errors)
+ for (const errorMessage of request.signedExchangeInfo().errors) {
TestRunner.addResult(` Error: ${JSON.stringify(errorMessage)}`);
+ }
}
}
}
@@ -138,8 +144,9 @@ NetworkTestRunner.makeXHRImpl = function(method, url, async, args, callback) {
function innerCallback(msg) {
if (msg.messageText.indexOf('XHR loaded') !== -1) {
- if (callback)
+ if (callback) {
callback();
+ }
} else {
ConsoleTestRunner.addConsoleSniffer(innerCallback);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_app.html b/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
index 05aa91049df..f24991cafc4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="node_app.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="node_app.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_app.js b/chromium/third_party/blink/renderer/devtools/front_end/node_app.js
index 6517c7d7f6c..1125741b4f2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_app.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_app.js
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Runtime.startApplication('node_app');
+Root.Runtime.startApplication('node_app');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js
index 7c49dbb508e..ccb244498e2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js
@@ -13,8 +13,8 @@ NodeMain.NodeConnectionsPanel = class extends UI.Panel {
const image = container.createChild('img', 'node-panel-logo');
image.src = 'https://nodejs.org/static/images/logos/nodejs-new-pantone-black.png';
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
/** @type {!Adb.Config} */
this._config;
@@ -23,12 +23,12 @@ NodeMain.NodeConnectionsPanel = class extends UI.Panel {
this.setDefaultFocusedElement(this.contentElement);
// Trigger notification once.
- InspectorFrontendHost.setDevicesUpdatesEnabled(false);
- InspectorFrontendHost.setDevicesUpdatesEnabled(true);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true);
this._networkDiscoveryView = new NodeMain.NodeConnectionsView(config => {
this._config.networkDiscoveryConfig = config;
- InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
+ Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config);
});
this._networkDiscoveryView.show(container);
}
@@ -135,8 +135,9 @@ NodeMain.NodeConnectionsView = class extends UI.VBox {
*/
commitEdit(rule, editor, isNew) {
rule.address = editor.control('address').value.trim();
- if (isNew)
+ if (isNew) {
this._networkDiscoveryConfig.push(rule);
+ }
this._update();
}
@@ -155,8 +156,9 @@ NodeMain.NodeConnectionsView = class extends UI.VBox {
* @return {!UI.ListWidget.Editor<!Adb.PortForwardingRule>}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -174,8 +176,9 @@ NodeMain.NodeConnectionsView = class extends UI.VBox {
*/
function addressValidator(rule, index, input) {
const match = input.value.trim().match(/^([a-zA-Z0-9\.\-_]+):(\d+)$/);
- if (!match)
+ if (!match) {
return {valid: false};
+ }
const port = parseInt(match[2], 10);
return {valid: port <= 65535};
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
index 1b515281102..4786743b519 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
@@ -38,10 +38,10 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
parentTarget.registerTargetDispatcher(this);
this._targetAgent.setDiscoverTargets(true);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
- InspectorFrontendHost.setDevicesUpdatesEnabled(false);
- InspectorFrontendHost.setDevicesUpdatesEnabled(true);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false);
+ Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true);
}
/**
@@ -53,8 +53,9 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
for (const address of config.networkDiscoveryConfig) {
const parts = address.split(':');
const port = parseInt(parts[1], 10);
- if (parts[0] && port)
+ if (parts[0] && port) {
locations.push({host: parts[0], port: port});
+ }
}
this._targetAgent.setRemoteLocations(locations);
}
@@ -63,11 +64,12 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
* @override
*/
dispose() {
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
- for (const sessionId of this._childTargets.keys())
+ for (const sessionId of this._childTargets.keys()) {
this.detachedFromTarget(sessionId, undefined);
+ }
}
/**
@@ -75,8 +77,9 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
* @param {!Protocol.Target.TargetInfo} targetInfo
*/
targetCreated(targetInfo) {
- if (targetInfo.type === 'node' && !targetInfo.attached)
+ if (targetInfo.type === 'node' && !targetInfo.attached) {
this._targetAgent.attachToTarget(targetInfo.targetId, false /* flatten */);
+ }
}
/**
@@ -129,8 +132,9 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
receivedMessageFromTarget(sessionId, message, childTargetId) {
const connection = this._childConnections.get(sessionId);
const onMessage = connection ? connection._onMessage : null;
- if (onMessage)
+ if (onMessage) {
onMessage.call(null, message);
+ }
}
};
@@ -178,8 +182,9 @@ NodeMain.NodeConnection = class {
* @return {!Promise}
*/
disconnect() {
- if (this._onDisconnect)
+ if (this._onDisconnect) {
this._onDisconnect.call(null, 'force disconnect');
+ }
this._onDisconnect = null;
this._onMessage = null;
return this._targetAgent.detachFromTarget(this._sessionId);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp
index d55d7bfefe5..d7b6a6ae694 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_main/node_main_strings.grdp
@@ -4,7 +4,7 @@
Add connection
</message>
<message name="IDS_DEVTOOLS_3fd49f986cbd5dd3148c27c9aaaaa700" desc="Text in Node Connections Panel of the Sources panel when debugging a Node.js app">
- Network address (e.g. localhost:9229)
+ Network address (e.g. <ph name="LOCKED_1">localhost:9229</ph>)
</message>
<message name="IDS_DEVTOOLS_43d755260901476a60e28982f36b2913" desc="Text in Node Connections Panel of the Sources panel when debugging a Node.js app">
Node.js debugging guide
@@ -16,6 +16,9 @@
Node.js: <ph name="TARGETINFO_URL">$1s<ex>example.com</ex></ph>
</message>
<message name="IDS_DEVTOOLS_ed6b1cccfa7455e9506ff7e5127e1df4" desc="Text in Node Connections Panel of the Sources panel when debugging a Node.js app">
- Specify network endpoint and DevTools will connect to it automatically. Read <ph name="DOCUMENTATIONLINK">$1s<ex>Node.js debugging guide</ex></ph> to learn more.
+ Specify network endpoint and <ph name="LOCKED_1">DevTools</ph> will connect to it automatically. Read <ph name="DOCUMENTATIONLINK">$1s<ex>Node.js debugging guide</ex></ph> to learn more.
+ </message>
+ <message name="IDS_DEVTOOLS_36c4536996ca5615dcf9911f068786dc" desc="A tag of Node.js Connection Panel that can be searched in the command menu">
+ node
</message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/CustomPreviewComponent.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/CustomPreviewComponent.js
index 6a561df771c..fbf8f3332e5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/CustomPreviewComponent.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/CustomPreviewComponent.js
@@ -50,8 +50,9 @@ ObjectUI.CustomPreviewSection = class {
* @return {!Node}
*/
_renderJSONMLTag(jsonML) {
- if (!Array.isArray(jsonML))
+ if (!Array.isArray(jsonML)) {
return createTextNode(jsonML + '');
+ }
const array = /** @type {!Array.<*>} */ (jsonML);
return array[0] === 'object' ? this._layoutObjectTag(array) : this._renderElement(array);
@@ -73,8 +74,9 @@ ObjectUI.CustomPreviewSection = class {
const attributes = object.shift();
for (const key in attributes) {
const value = attributes[key];
- if ((key !== 'style') || (typeof value !== 'string'))
+ if ((key !== 'style') || (typeof value !== 'string')) {
continue;
+ }
element.setAttribute(key, value);
}
@@ -93,8 +95,9 @@ ObjectUI.CustomPreviewSection = class {
const attributes = objectTag.shift();
const remoteObject = this._object.runtimeModel().createRemoteObject(
/** @type {!Protocol.Runtime.RemoteObject} */ (attributes));
- if (remoteObject.customPreview())
+ if (remoteObject.customPreview()) {
return (new ObjectUI.CustomPreviewSection(remoteObject)).element();
+ }
const sectionElement = ObjectUI.ObjectPropertiesSection.defaultObjectPresentation(remoteObject);
sectionElement.classList.toggle('custom-expandable-section-standard-section', remoteObject.hasChildren);
@@ -106,8 +109,9 @@ ObjectUI.CustomPreviewSection = class {
* @param {!Array.<*>} jsonMLTags
*/
_appendJsonMLTags(parentElement, jsonMLTags) {
- for (let i = 0; i < jsonMLTags.length; ++i)
+ for (let i = 0; i < jsonMLTags.length; ++i) {
parentElement.appendChild(this._renderJSONMLTag(jsonMLTags[i]));
+ }
}
/**
@@ -115,20 +119,22 @@ ObjectUI.CustomPreviewSection = class {
*/
_onClick(event) {
event.consume(true);
- if (this._cachedContent)
+ if (this._cachedContent) {
this._toggleExpand();
- else
+ } else {
this._loadBody();
+ }
}
_toggleExpand() {
this._expanded = !this._expanded;
this._header.classList.toggle('expanded', this._expanded);
this._cachedContent.classList.toggle('hidden', !this._expanded);
- if (this._expanded)
+ if (this._expanded) {
this._expandIcon.setIconType('smallicon-triangle-down');
- else
+ } else {
this._expandIcon.setIconType('smallicon-triangle-right');
+ }
}
_loadBody() {
@@ -147,26 +153,30 @@ ObjectUI.CustomPreviewSection = class {
* @throws {string} error message
*/
function substituteObjectTagsInCustomPreview(jsonMLObject) {
- if (!jsonMLObject || (typeof jsonMLObject !== 'object') || (typeof jsonMLObject.splice !== 'function'))
+ if (!jsonMLObject || (typeof jsonMLObject !== 'object') || (typeof jsonMLObject.splice !== 'function')) {
return;
+ }
const obj = jsonMLObject.length;
- if (!(typeof obj === 'number' && obj >>> 0 === obj && (obj > 0 || 1 / obj > 0)))
+ if (!(typeof obj === 'number' && obj >>> 0 === obj && (obj > 0 || 1 / obj > 0))) {
return;
+ }
let startIndex = 1;
if (jsonMLObject[0] === 'object') {
const attributes = jsonMLObject[1];
const originObject = attributes['object'];
const config = attributes['config'];
- if (typeof originObject === 'undefined')
+ if (typeof originObject === 'undefined') {
throw 'Illegal format: obligatory attribute "object" isn\'t specified';
+ }
jsonMLObject[1] = bindRemoteObject(originObject, config);
startIndex = 2;
}
- for (let i = startIndex; i < jsonMLObject.length; ++i)
+ for (let i = startIndex; i < jsonMLObject.length; ++i) {
substituteObjectTagsInCustomPreview(jsonMLObject[i]);
+ }
}
try {
@@ -183,8 +193,9 @@ ObjectUI.CustomPreviewSection = class {
if (customPreview.bindRemoteObjectFunctionId && customPreview.formatterObjectId) {
// Support for V8 version < 7.3.
const args = [{objectId: customPreview.bindRemoteObjectFunctionId}, {objectId: customPreview.formatterObjectId}];
- if (customPreview.configObjectId)
+ if (customPreview.configObjectId) {
args.push({objectId: customPreview.configObjectId});
+ }
this._object.callFunctionJSON(load, args).then(onBodyLoaded.bind(this));
} else if (customPreview.bodyGetterId) {
this._object.callFunctionJSON(bodyGetter => bodyGetter(), [{objectId: customPreview.bodyGetterId}])
@@ -196,8 +207,9 @@ ObjectUI.CustomPreviewSection = class {
* @this {ObjectUI.CustomPreviewSection}
*/
function onBodyLoaded(bodyJsonML) {
- if (!bodyJsonML)
+ if (!bodyJsonML) {
return;
+ }
this._cachedContent = this._renderJSONMLTag(bodyJsonML);
this._sectionElement.appendChild(this._cachedContent);
@@ -224,8 +236,9 @@ ObjectUI.CustomPreviewComponent = class {
expandIfPossible() {
if ((this._object.customPreview().hasBody || this._object.customPreview().bodyGetterId) &&
- this._customPreviewSection)
+ this._customPreviewSection) {
this._customPreviewSection._loadBody();
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
index 4707e5dc89d..7d11587fd14 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
@@ -34,15 +34,17 @@ ObjectUI.JavaScriptAutocomplete = class {
/**
* @param {string} fullText
- * @return {!Promise<?{args: !Array<!Array<string>>, argumentIndex: number}>}
+ * @return {!Promise<?{args: !Array<!Array<string>>, argumentIndex: number}|undefined>}
*/
async argumentsHint(fullText) {
const functionCall = await Formatter.formatterWorkerPool().findLastFunctionCall(fullText);
- if (!functionCall)
+ if (!functionCall) {
return null;
+ }
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return null;
+ }
const result = await executionContext.evaluate(
{
expression: functionCall.baseExpression,
@@ -73,11 +75,12 @@ ObjectUI.JavaScriptAutocomplete = class {
timeout: functionCall.possibleSideEffects ? 500 : undefined
},
/* userGesture */ false, /* awaitPromise */ false);
- return (result && !result.exceptionDetails) ? result.object : null;
+ return (result && !result.exceptionDetails && result.object) ? result.object : null;
}, functionCall.functionName);
executionContext.runtimeModel.releaseObjectGroup('argumentsHint');
- if (!args.length || (args.length === 1 && !args[0].length))
+ if (!args.length || (args.length === 1 && !args[0].length)) {
return null;
+ }
return {args, argumentIndex: functionCall.argumentIndex};
}
@@ -89,8 +92,9 @@ ObjectUI.JavaScriptAutocomplete = class {
*/
async _argumentsForFunction(functionObject, receiverObjGetter, parsedFunctionName) {
const description = functionObject.description;
- if (!description.endsWith('{ [native code] }'))
+ if (!description.endsWith('{ [native code] }')) {
return [await Formatter.formatterWorkerPool().argumentsList(description)];
+ }
// Check if this is a bound function.
if (description === 'function () { [native code] }') {
@@ -106,10 +110,11 @@ ObjectUI.JavaScriptAutocomplete = class {
const clippedArgs = [];
for (const signature of originalSignatures) {
const restIndex = signature.slice(0, boundArgsLength).findIndex(arg => arg.startsWith('...'));
- if (restIndex !== -1)
+ if (restIndex !== -1) {
clippedArgs.push(signature.slice(restIndex));
- else
+ } else {
clippedArgs.push(signature.slice(boundArgsLength));
+ }
}
return clippedArgs;
}
@@ -117,22 +122,26 @@ ObjectUI.JavaScriptAutocomplete = class {
const javaScriptMetadata = await self.runtime.extension(Common.JavaScriptMetadata).instance();
const name = /^function ([^(]*)\(/.exec(description)[1] || parsedFunctionName;
- if (!name)
+ if (!name) {
return [];
+ }
const uniqueSignatures = javaScriptMetadata.signaturesForNativeFunction(name);
- if (uniqueSignatures)
+ if (uniqueSignatures) {
return uniqueSignatures;
+ }
const receiverObj = await receiverObjGetter();
const className = receiverObj.className;
- if (javaScriptMetadata.signaturesForInstanceMethod(name, className))
+ if (javaScriptMetadata.signaturesForInstanceMethod(name, className)) {
return javaScriptMetadata.signaturesForInstanceMethod(name, className);
+ }
// Check for static methods on a constructor.
if (receiverObj.type === 'function' && receiverObj.description.endsWith('{ [native code] }')) {
const receiverName = /^function ([^(]*)\(/.exec(receiverObj.description)[1];
const staticSignatures = javaScriptMetadata.signaturesForStaticMethod(name, receiverName);
- if (staticSignatures)
+ if (staticSignatures) {
return staticSignatures;
+ }
}
@@ -153,16 +162,18 @@ ObjectUI.JavaScriptAutocomplete = class {
protoNames = await receiverObj.callFunctionJSON(function() {
const result = [];
for (let object = this; object; object = Object.getPrototypeOf(object)) {
- if (typeof object === 'object' && object.constructor && object.constructor.name)
+ if (typeof object === 'object' && object.constructor && object.constructor.name) {
result[result.length] = object.constructor.name;
+ }
}
return result;
- });
+ }, []);
}
for (const proto of protoNames) {
const instanceSignatures = javaScriptMetadata.signaturesForInstanceMethod(name, proto);
- if (instanceSignatures)
+ if (instanceSignatures) {
return instanceSignatures;
+ }
}
return [];
}
@@ -175,12 +186,14 @@ ObjectUI.JavaScriptAutocomplete = class {
async _mapCompletions(text, query) {
const mapMatch = text.match(/\.\s*(get|set|delete)\s*\(\s*$/);
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext || !mapMatch)
+ if (!executionContext || !mapMatch) {
return [];
+ }
const expression = await Formatter.formatterWorkerPool().findLastExpression(text.substring(0, mapMatch.index));
- if (!expression)
+ if (!expression) {
return [];
+ }
const result = await executionContext.evaluate(
{
@@ -194,13 +207,15 @@ ObjectUI.JavaScriptAutocomplete = class {
timeout: expression.possibleSideEffects ? 500 : undefined
},
/* userGesture */ false, /* awaitPromise */ false);
- if (result.error || !!result.exceptionDetails || result.object.subtype !== 'map')
+ if (result.error || !!result.exceptionDetails || result.object.subtype !== 'map') {
return [];
+ }
const properties = await result.object.getOwnProperties(false);
const internalProperties = properties.internalProperties || [];
const entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
- if (!entriesProperty)
+ if (!entriesProperty) {
return [];
+ }
const keysObj = await entriesProperty.value.callFunctionJSON(getEntries);
executionContext.runtimeModel.releaseObjectGroup('mapCompletion');
return gotKeys(Object.keys(keysObj));
@@ -213,8 +228,9 @@ ObjectUI.JavaScriptAutocomplete = class {
function getEntries() {
const result = {__proto__: null};
for (let i = 0; i < this.length; i++) {
- if (typeof this[i].key === 'string')
+ if (typeof this[i].key === 'string') {
result[this[i].key] = true;
+ }
}
return result;
}
@@ -229,37 +245,43 @@ ObjectUI.JavaScriptAutocomplete = class {
const caseSensitiveAnywhere = [];
const caseInsensitiveAnywhere = [];
let quoteChar = '"';
- if (query.startsWith('\''))
+ if (query.startsWith('\'')) {
quoteChar = '\'';
+ }
let endChar = ')';
- if (mapMatch[0].indexOf('set') !== -1)
+ if (mapMatch[0].indexOf('set') !== -1) {
endChar = ', ';
+ }
const sorter = rawKeys.length < 1000 ? String.naturalOrderComparator : undefined;
const keys = rawKeys.sort(sorter).map(key => quoteChar + key + quoteChar);
for (const key of keys) {
- if (key.length < query.length)
+ if (key.length < query.length) {
continue;
- if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1)
+ }
+ if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1) {
continue;
+ }
// Substitute actual newlines with newline characters. @see crbug.com/498421
const title = key.split('\n').join('\\n');
const text = title + endChar;
- if (key.startsWith(query))
+ if (key.startsWith(query)) {
caseSensitivePrefix.push({text: text, title: title, priority: 4});
- else if (key.toLowerCase().startsWith(query.toLowerCase()))
+ } else if (key.toLowerCase().startsWith(query.toLowerCase())) {
caseInsensitivePrefix.push({text: text, title: title, priority: 3});
- else if (key.indexOf(query) !== -1)
+ } else if (key.indexOf(query) !== -1) {
caseSensitiveAnywhere.push({text: text, title: title, priority: 2});
- else
+ } else {
caseInsensitiveAnywhere.push({text: text, title: title, priority: 1});
+ }
}
const suggestions =
caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
- if (suggestions.length)
+ if (suggestions.length) {
suggestions[0].subtitle = Common.UIString('Keys');
+ }
return suggestions;
}
}
@@ -272,14 +294,17 @@ ObjectUI.JavaScriptAutocomplete = class {
*/
async _completionsForExpression(fullText, query, force) {
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return [];
+ }
let expression;
- if (fullText.endsWith('.') || fullText.endsWith('['))
+ if (fullText.endsWith('.') || fullText.endsWith('[')) {
expression = await Formatter.formatterWorkerPool().findLastExpression(fullText.substring(0, fullText.length - 1));
+ }
if (!expression) {
- if (fullText.endsWith('.'))
+ if (fullText.endsWith('.')) {
return [];
+ }
expression = {baseExpression: '', possibleSideEffects: false};
}
const needsNoSideEffects = expression.possibleSideEffects;
@@ -290,12 +315,14 @@ ObjectUI.JavaScriptAutocomplete = class {
const bracketNotation = !!expressionString && fullText.endsWith('[');
// User is entering float value, do not suggest anything.
- if ((expressionString && !isNaN(expressionString)) || (!expressionString && query && !isNaN(query)))
+ if ((expressionString && !isNaN(expressionString)) || (!expressionString && query && !isNaN(query))) {
return [];
+ }
- if (!query && !expressionString && !force)
+ if (!query && !expressionString && !force) {
return [];
+ }
const selectedFrame = executionContext.debuggerModel.selectedCallFrame();
let completionGroups;
const TEN_SECONDS = 10000;
@@ -332,8 +359,9 @@ ObjectUI.JavaScriptAutocomplete = class {
* @return {!Promise<!Array<!ObjectUI.JavaScriptAutocomplete.CompletionGroup>>}
*/
async function completionsOnGlobal(result) {
- if (result.error || !!result.exceptionDetails || !result.object)
+ if (result.error || !!result.exceptionDetails || !result.object) {
return [];
+ }
let object = result.object;
while (object && object.type === 'object' && object.subtype === 'proxy') {
@@ -342,8 +370,9 @@ ObjectUI.JavaScriptAutocomplete = class {
const target = internalProperties.find(property => property.name === '[[Target]]');
object = target ? target.value : null;
}
- if (!object)
+ if (!object) {
return [];
+ }
let completions = [];
if (object.type === 'object' || object.type === 'function') {
completions =
@@ -362,23 +391,26 @@ ObjectUI.JavaScriptAutocomplete = class {
},
/* userGesture */ false,
/* awaitPromise */ false);
- if (evaluateResult.object && !evaluateResult.exceptionDetails)
- completions = evaluateResult.object.value || [];
+ if (evaluateResult.object && !evaluateResult.exceptionDetails) {
+ completions = /** @type {!Iterable} */ (evaluateResult.object.value) || [];
+ }
}
executionContext.runtimeModel.releaseObjectGroup('completion');
if (!expressionString) {
const globalNames = await executionContext.globalLexicalScopeNames();
// Merge lexical scope names with first completion group on global object: let a and let b should be in the same group.
- if (completions.length)
+ if (completions.length) {
completions[0].items = completions[0].items.concat(globalNames);
- else
+ } else {
completions.push({items: globalNames.sort(), title: Common.UIString('Lexical scope variables')});
+ }
}
for (const group of completions) {
- for (let i = 0; i < group.items.length; i++)
+ for (let i = 0; i < group.items.length; i++) {
group.items[i] = group.items[i].replace(/\n/g, '\\n');
+ }
group.items.sort(group.items.length < 1000 ? this._itemComparator : undefined);
}
@@ -393,29 +425,33 @@ ObjectUI.JavaScriptAutocomplete = class {
*/
function getCompletions(type) {
let object;
- if (type === 'string')
+ if (type === 'string') {
object = new String('');
- else if (type === 'number')
+ } else if (type === 'number') {
object = new Number(0);
+ }
// Object-wrapped BigInts cannot be constructed via `new BigInt`.
- else if (type === 'bigint')
+ else if (type === 'bigint') {
object = Object(BigInt(0));
- else if (type === 'boolean')
+ } else if (type === 'boolean') {
object = new Boolean(false);
- else
+ } else {
object = this;
+ }
const result = [];
try {
for (let o = object; o; o = Object.getPrototypeOf(o)) {
- if ((type === 'array' || type === 'typedarray') && o === object && o.length > 9999)
+ if ((type === 'array' || type === 'typedarray') && o === object && o.length > 9999) {
continue;
+ }
const group = {items: [], __proto__: null};
try {
if (typeof o === 'object' && Object.prototype.hasOwnProperty.call(o, 'constructor') && o.constructor &&
- o.constructor.name)
+ o.constructor.name) {
group.title = o.constructor.name;
+ }
} catch (ee) {
// we could break upon cross origin check.
}
@@ -424,8 +460,9 @@ ObjectUI.JavaScriptAutocomplete = class {
const isArray = Array.isArray(o);
for (let i = 0; i < names.length && group.items.length < 10000; ++i) {
// Skip array elements indexes.
- if (isArray && /^[0-9]/.test(names[i]))
+ if (isArray && /^[0-9]/.test(names[i])) {
continue;
+ }
group.items[group.items.length] = names[i];
}
}
@@ -450,8 +487,9 @@ ObjectUI.JavaScriptAutocomplete = class {
}
const fullScopes = await Promise.all(groupPromises);
executionContext.runtimeModel.releaseObjectGroup('completion');
- for (const scope of fullScopes)
+ for (const scope of fullScopes) {
result.push({title: scope.name, items: scope.properties.map(property => property.name).sort()});
+ }
return result;
}
}
@@ -465,8 +503,9 @@ ObjectUI.JavaScriptAutocomplete = class {
* @return {!UI.SuggestBox.Suggestions}
*/
_receivedPropertyNames(propertyGroups, dotNotation, bracketNotation, expressionString, query) {
- if (!propertyGroups)
+ if (!propertyGroups) {
return [];
+ }
const includeCommandLineAPI = (!dotNotation && !bracketNotation);
if (includeCommandLineAPI) {
const commandLineAPI = [
@@ -542,32 +581,38 @@ ObjectUI.JavaScriptAutocomplete = class {
for (let i = 0; i < group.items.length; i++) {
let property = group.items[i];
// Assume that all non-ASCII characters are letters and thus can be used as part of identifier.
- if (!bracketNotation && !regex.test(property))
+ if (!bracketNotation && !regex.test(property)) {
continue;
+ }
if (bracketNotation) {
- if (!/^[0-9]+$/.test(property))
+ if (!/^[0-9]+$/.test(property)) {
property = quoteUsed + property.escapeCharacters(quoteUsed + '\\') + quoteUsed;
+ }
property += ']';
}
- if (allProperties.has(property))
+ if (allProperties.has(property)) {
continue;
+ }
- if (property.length < query.length)
+ if (property.length < query.length) {
continue;
+ }
const lowerCaseProperty = property.toLowerCase();
- if (query.length && lowerCaseProperty.indexOf(lowerCaseQuery) === -1)
+ if (query.length && lowerCaseProperty.indexOf(lowerCaseQuery) === -1) {
continue;
+ }
allProperties.add(property);
- if (property.startsWith(query))
+ if (property.startsWith(query)) {
caseSensitivePrefix.push({text: property, priority: property === query ? 5 : 4});
- else if (lowerCaseProperty.startsWith(lowerCaseQuery))
+ } else if (lowerCaseProperty.startsWith(lowerCaseQuery)) {
caseInsensitivePrefix.push({text: property, priority: 3});
- else if (property.indexOf(query) !== -1)
+ } else if (property.indexOf(query) !== -1) {
caseSensitiveAnywhere.push({text: property, priority: 2});
- else
+ } else {
caseInsensitiveAnywhere.push({text: property, priority: 1});
+ }
}
const structuredGroup =
caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere);
@@ -577,8 +622,9 @@ ObjectUI.JavaScriptAutocomplete = class {
}
result = result.concat(structuredGroup);
result.forEach(item => {
- if (item.text.endsWith(']'))
+ if (item.text.endsWith(']')) {
item.title = item.text.substring(0, item.text.length - 1);
+ }
});
}
return result;
@@ -592,10 +638,12 @@ ObjectUI.JavaScriptAutocomplete = class {
_itemComparator(a, b) {
const aStartsWithUnderscore = a.startsWith('_');
const bStartsWithUnderscore = b.startsWith('_');
- if (aStartsWithUnderscore && !bStartsWithUnderscore)
+ if (aStartsWithUnderscore && !bStartsWithUnderscore) {
return 1;
- if (bStartsWithUnderscore && !aStartsWithUnderscore)
+ }
+ if (bStartsWithUnderscore && !aStartsWithUnderscore) {
return -1;
+ }
return String.naturalOrderComparator(a, b);
}
@@ -605,12 +653,14 @@ ObjectUI.JavaScriptAutocomplete = class {
*/
static async isExpressionComplete(expression) {
const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!currentExecutionContext)
+ if (!currentExecutionContext) {
return true;
+ }
const result =
await currentExecutionContext.runtimeModel.compileScript(expression, '', false, currentExecutionContext.id);
- if (!result.exceptionDetails)
+ if (!result.exceptionDetails) {
return true;
+ }
const description = result.exceptionDetails.exception.description;
return !description.startsWith('SyntaxError: Unexpected end of input') &&
!description.startsWith('SyntaxError: Unterminated template literal');
@@ -650,14 +700,16 @@ ObjectUI.JavaScriptAutocompleteConfig = class {
*/
_substituteRange(lineNumber, columnNumber) {
const token = this._editor.tokenAtTextPosition(lineNumber, columnNumber);
- if (token && token.type === 'js-string')
+ if (token && token.type === 'js-string') {
return new TextUtils.TextRange(lineNumber, token.startColumn, lineNumber, columnNumber);
+ }
const lineText = this._editor.line(lineNumber);
let index;
for (index = columnNumber - 1; index >= 0; index--) {
- if (' =:[({;,!+-*/&|^<>.\t\r\n'.indexOf(lineText.charAt(index)) !== -1)
+ if (' =:[({;,!+-*/&|^<>.\t\r\n'.indexOf(lineText.charAt(index)) !== -1) {
break;
+ }
}
return new TextUtils.TextRange(lineNumber, index + 1, lineNumber, columnNumber);
}
@@ -675,19 +727,23 @@ ObjectUI.JavaScriptAutocompleteConfig = class {
if (token) {
const excludedTokens = new Set(['js-comment', 'js-string-2', 'js-def']);
const trimmedBefore = before.trim();
- if (!trimmedBefore.endsWith('[') && !trimmedBefore.match(/\.\s*(get|set|delete)\s*\(\s*$/))
+ if (!trimmedBefore.endsWith('[') && !trimmedBefore.match(/\.\s*(get|set|delete)\s*\(\s*$/)) {
excludedTokens.add('js-string');
- if (!trimmedBefore.endsWith('.'))
+ }
+ if (!trimmedBefore.endsWith('.')) {
excludedTokens.add('js-property');
- if (excludedTokens.has(token.type))
+ }
+ if (excludedTokens.has(token.type)) {
return [];
+ }
}
const queryAndAfter = this._editor.line(queryRange.startLine).substring(queryRange.startColumn);
const words = await ObjectUI.javaScriptAutocomplete.completionsForTextInCurrentContext(before, query, force);
if (!force && queryAndAfter && queryAndAfter !== query &&
- words.some(word => queryAndAfter.startsWith(word.text) && query.length !== word.text.length))
+ words.some(word => queryAndAfter.startsWith(word.text) && query.length !== word.text.length)) {
return [];
+ }
return words;
}
@@ -699,19 +755,22 @@ ObjectUI.JavaScriptAutocompleteConfig = class {
async _tooltipCallback(lineNumber, columnNumber) {
const before = this._editor.text(new TextUtils.TextRange(0, 0, lineNumber, columnNumber));
const result = await ObjectUI.javaScriptAutocomplete.argumentsHint(before);
- if (!result)
+ if (!result) {
return null;
+ }
const argumentIndex = result.argumentIndex;
const tooltip = createElement('div');
for (const args of result.args) {
const argumentsElement = createElement('span');
for (let i = 0; i < args.length; i++) {
- if (i === argumentIndex || (i < argumentIndex && args[i].startsWith('...')))
+ if (i === argumentIndex || (i < argumentIndex && args[i].startsWith('...'))) {
argumentsElement.appendChild(UI.html`<b>${args[i]}</b>`);
- else
+ } else {
argumentsElement.createTextChild(args[i]);
- if (i < args.length - 1)
+ }
+ if (i < args.length - 1) {
argumentsElement.createTextChild(', ');
+ }
}
tooltip.appendChild(UI.html`<div class='source-code'>\u0192(${argumentsElement})</div>`);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptREPL.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptREPL.js
index f0b73e69cad..dbe394cccf2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptREPL.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptREPL.js
@@ -9,8 +9,9 @@ ObjectUI.JavaScriptREPL = class {
*/
static wrapObjectLiteral(code) {
// Only parenthesize what appears to be an object literal.
- if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code)))
+ if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code))) {
return code;
+ }
const parse = (async () => 0).constructor;
try {
@@ -53,8 +54,9 @@ ObjectUI.JavaScriptREPL = class {
static async evaluateAndBuildPreview(text, throwOnSideEffect, timeout, allowErrors, objectGroup) {
const executionContext = UI.context.flavor(SDK.ExecutionContext);
const isTextLong = text.length > ObjectUI.JavaScriptREPL._MaxLengthForEvaluation;
- if (!text || !executionContext || (throwOnSideEffect && isTextLong))
+ if (!text || !executionContext || (throwOnSideEffect && isTextLong)) {
return {preview: createDocumentFragment(), result: null};
+ }
const wrappedResult = await ObjectUI.JavaScriptREPL.preprocessExpression(text);
const options = {
@@ -63,7 +65,8 @@ ObjectUI.JavaScriptREPL = class {
includeCommandLineAPI: true,
throwOnSideEffect: throwOnSideEffect,
timeout: timeout,
- objectGroup: objectGroup
+ objectGroup: objectGroup,
+ disableBreaks: true
};
const result = await executionContext.evaluate(
options, false /* userGesture */, wrappedResult.preprocessed /* awaitPromise */);
@@ -78,13 +81,15 @@ ObjectUI.JavaScriptREPL = class {
*/
static _buildEvaluationPreview(result, allowErrors) {
const fragment = createDocumentFragment();
- if (result.error)
+ if (result.error) {
return fragment;
+ }
if (result.exceptionDetails && result.exceptionDetails.exception && result.exceptionDetails.exception.description) {
const exception = result.exceptionDetails.exception.description;
- if (exception.startsWith('TypeError: ') || allowErrors)
+ if (exception.startsWith('TypeError: ') || allowErrors) {
fragment.createChild('span').textContent = result.exceptionDetails.text + ' ' + exception;
+ }
return fragment;
}
@@ -93,7 +98,7 @@ ObjectUI.JavaScriptREPL = class {
if (preview && type === 'object' && subtype !== 'node') {
formatter.appendObjectPreview(fragment, preview, false /* isEntry */);
} else {
- const nonObjectPreview = formatter.renderPropertyPreview(type, subtype, description.trimEnd(400));
+ const nonObjectPreview = formatter.renderPropertyPreview(type, subtype, description.trimEndWithMaxLength(400));
fragment.appendChild(nonObjectPreview);
}
return fragment;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
index 44b1ee92035..18a69cfa0a4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
@@ -39,10 +39,12 @@ ObjectUI.ObjectPopoverHelper = class {
}
dispose() {
- if (this._resultHighlightedAsDOM)
+ if (this._resultHighlightedAsDOM) {
SDK.OverlayModel.hideDOMNodeHighlight();
- if (this._linkifier)
+ }
+ if (this._linkifier) {
this._linkifier.dispose();
+ }
}
/**
@@ -51,7 +53,7 @@ ObjectUI.ObjectPopoverHelper = class {
* @return {!Promise<?ObjectUI.ObjectPopoverHelper>}
*/
static async buildObjectPopover(result, popover) {
- const description = result.description.trimEnd(ObjectUI.ObjectPopoverHelper.MaxPopoverTextLength);
+ const description = result.description.trimEndWithMaxLength(ObjectUI.ObjectPopoverHelper.MaxPopoverTextLength);
let popoverContentElement = null;
if (result.type === 'object') {
let linkifier = null;
@@ -89,10 +91,11 @@ ObjectUI.ObjectPopoverHelper = class {
const valueElement = popoverContentElement.createChild('span', 'monospace object-value-' + result.type);
valueElement.style.whiteSpace = 'pre';
- if (result.type === 'string')
+ if (result.type === 'string') {
valueElement.createTextChildren(`"${description}"`);
- else if (result.type !== 'function')
+ } else if (result.type !== 'function') {
valueElement.textContent = description;
+ }
if (result.type !== 'function') {
popover.contentElement.appendChild(popoverContentElement);
@@ -101,8 +104,9 @@ ObjectUI.ObjectPopoverHelper = class {
ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(result, valueElement, true);
const response = await result.debuggerModel().functionDetailsPromise(result);
- if (!response)
+ if (!response) {
return null;
+ }
const container = createElementWithClass('div', 'object-popover-container');
const title = container.createChild('div', 'function-popover-title source-code');
@@ -115,7 +119,8 @@ ObjectUI.ObjectPopoverHelper = class {
let linkifier = null;
if (sourceURL) {
linkifier = new Components.Linkifier();
- linkContainer.appendChild(linkifier.linkifyRawLocation(rawLocation, sourceURL));
+ linkContainer.appendChild(
+ linkifier.linkifyRawLocation(/** @type {!SDK.DebuggerModel.Location} */ (rawLocation), sourceURL));
}
container.appendChild(popoverContentElement);
popover.contentElement.appendChild(container);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
index 1dbd573fc31..957bd8b458d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -41,8 +41,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
super();
this._object = object;
this._editable = true;
- if (!showOverflow)
+ if (!showOverflow) {
this.hideOverflow();
+ }
this.setFocusable(true);
this.setShowSelectionOnKeyboardFocus(true);
this._objectTreeElement = new ObjectUI.ObjectPropertiesSection.RootElement(
@@ -55,8 +56,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
this.titleElement = title;
this.element.appendChild(title);
}
- if (!this.titleElement.hasAttribute('tabIndex'))
+ if (!this.titleElement.hasAttribute('tabIndex')) {
this.titleElement.tabIndex = -1;
+ }
this.element._section = this;
this.registerRequiredCSS('object_ui/objectValue.css');
@@ -72,21 +74,37 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
* @return {!Element}
*/
static defaultObjectPresentation(object, linkifier, skipProto, readOnly) {
- const componentRoot = createElementWithClass('span', 'source-code');
- const shadowRoot = UI.createShadowRootWithCoreStyles(componentRoot, 'object_ui/objectValue.css');
- shadowRoot.appendChild(
- ObjectUI.ObjectPropertiesSection.createValueElement(object, false /* wasThrown */, true /* showPreview */));
- if (!object.hasChildren)
- return componentRoot;
+ const objectPropertiesSection =
+ ObjectUI.ObjectPropertiesSection.defaultObjectPropertiesSection(object, linkifier, skipProto, readOnly);
+ if (!object.hasChildren) {
+ return objectPropertiesSection.titleElement;
+ } else {
+ return objectPropertiesSection.element;
+ }
+ }
- const objectPropertiesSection = new ObjectUI.ObjectPropertiesSection(object, componentRoot, linkifier);
+ /**
+ * @param {!SDK.RemoteObject} object
+ * @param {!Components.Linkifier=} linkifier
+ * @param {boolean=} skipProto
+ * @param {boolean=} readOnly
+ * @return {!ObjectUI.ObjectPropertiesSection}
+ */
+ static defaultObjectPropertiesSection(object, linkifier, skipProto, readOnly) {
+ const titleElement = createElementWithClass('span', 'source-code');
+ const shadowRoot = UI.createShadowRootWithCoreStyles(titleElement, 'object_ui/objectValue.css');
+ shadowRoot.appendChild(
+ ObjectUI.ObjectPropertiesSection.createValueElement(object, /* wasThrown */ false, /* showPreview */ true));
+ const objectPropertiesSection = new ObjectUI.ObjectPropertiesSection(object, titleElement, linkifier);
objectPropertiesSection.editable = false;
- if (skipProto)
+ if (skipProto) {
objectPropertiesSection.skipProto();
- if (readOnly)
+ }
+ if (readOnly) {
objectPropertiesSection.setEditable(false);
+ }
- return objectPropertiesSection.element;
+ return objectPropertiesSection;
}
/**
@@ -97,26 +115,36 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
static CompareProperties(propertyA, propertyB) {
const a = propertyA.name;
const b = propertyB.name;
- if (a === '__proto__')
+ if (a === '__proto__') {
return 1;
- if (b === '__proto__')
+ }
+ if (b === '__proto__') {
return -1;
- if (!propertyA.enumerable && propertyB.enumerable)
+ }
+ if (!propertyA.enumerable && propertyB.enumerable) {
return 1;
- if (!propertyB.enumerable && propertyA.enumerable)
+ }
+ if (!propertyB.enumerable && propertyA.enumerable) {
return -1;
- if (a.startsWith('_') && !b.startsWith('_'))
+ }
+ if (a.startsWith('_') && !b.startsWith('_')) {
return 1;
- if (b.startsWith('_') && !a.startsWith('_'))
+ }
+ if (b.startsWith('_') && !a.startsWith('_')) {
return -1;
- if (propertyA.symbol && !propertyB.symbol)
+ }
+ if (propertyA.symbol && !propertyB.symbol) {
return 1;
- if (propertyB.symbol && !propertyA.symbol)
+ }
+ if (propertyB.symbol && !propertyA.symbol) {
return -1;
- if (propertyA.private && !propertyB.private)
+ }
+ if (propertyA.private && !propertyB.private) {
return 1;
- if (propertyB.private && !propertyA.private)
+ }
+ if (propertyB.private && !propertyA.private) {
return -1;
+ }
return String.naturalOrderComparator(a, b);
}
@@ -126,10 +154,12 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
* @return {!Element}
*/
static createNameElement(name, isPrivate) {
- if (name === null)
+ if (name === null) {
return UI.html`<span class="name"></span>`;
- if (/^\s|\s$|^$|\n/.test(name))
+ }
+ if (/^\s|\s$|^$|\n/.test(name)) {
return UI.html`<span class="name">"${name.replace(/\n/g, '\u21B5')}"</span>`;
+ }
if (isPrivate) {
return UI.html`<span class="name">
<span class="private-property-hash">${name[0]}</span>${name.substring(1)}
@@ -167,8 +197,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
textAfterPrefix = text.substring('class'.length);
const classNameMatch = /^[^{\s]+/.exec(textAfterPrefix.trim());
let className = defaultName;
- if (classNameMatch)
+ if (classNameMatch) {
className = classNameMatch[0].trim() || defaultName;
+ }
addElements('class', textAfterPrefix, className);
} else if (asyncMatch) {
textAfterPrefix = text.substring(asyncMatch[1].length);
@@ -185,15 +216,16 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
} else if (isArrow) {
const maxArrowFunctionCharacterLength = 60;
let abbreviation = text;
- if (defaultName)
+ if (defaultName) {
abbreviation = defaultName + '()';
- else if (text.length > maxArrowFunctionCharacterLength)
+ } else if (text.length > maxArrowFunctionCharacterLength) {
abbreviation = text.substring(0, firstArrowIndex + 2) + ' {\u2026}';
+ }
addElements('', text, abbreviation);
} else {
addElements('\u0192', text, nameAndArguments(text));
}
- valueElement.title = description.trimEnd(500);
+ valueElement.title = description.trimEndWithMaxLength(500);
return valueElement;
/**
@@ -218,12 +250,14 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
*/
function addElements(prefix, body, abbreviation) {
const maxFunctionBodyLength = 200;
- if (prefix.length)
+ if (prefix.length) {
valueElement.createChild('span', 'object-value-function-prefix').textContent = prefix + ' ';
- if (includePreview)
- valueElement.createTextChild(body.trim().trimEnd(maxFunctionBodyLength));
- else
+ }
+ if (includePreview) {
+ valueElement.createTextChild(body.trim().trimEndWithMaxLength(maxFunctionBodyLength));
+ } else {
valueElement.createTextChild(abbreviation.replace(/\n/g, ' '));
+ }
}
}
@@ -260,8 +294,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
if (type === 'object' && subtype === 'internal#location') {
const rawLocation = value.debuggerModel().createRawLocationByScriptId(
value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
- if (rawLocation && linkifier)
+ if (rawLocation && linkifier) {
return linkifier.linkifyRawLocation(rawLocation, '');
+ }
valueElement = createUnknownInternalLocationElement();
} else if (type === 'string' && typeof description === 'string') {
valueElement = createStringElement();
@@ -272,7 +307,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
} else if (type === 'number' && description && description.indexOf('e') !== -1) {
valueElement = createNumberWithExponentElement();
if (parentElement) // FIXME: do it in the caller.
+ {
parentElement.classList.add('hbox');
+ }
} else {
valueElement = createElementWithClass('span', 'object-value-' + (subtype || type));
valueElement.title = description || '';
@@ -311,10 +348,11 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
const valueElement = createElementWithClass('span', 'object-value-string');
const text = description.replace(/\n/g, '\u21B5');
valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
- if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength)
+ if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength) {
valueElement.appendChild(UI.createExpandableText(text, 50));
- else
+ } else {
valueElement.createTextChild(text);
+ }
valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
valueElement.title = description || '';
return valueElement;
@@ -370,8 +408,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
// The includePreview flag is false for formats such as console.dir().
let defaultName = includePreview ? '' : 'anonymous';
- if (response && response.functionName)
+ if (response && response.functionName) {
defaultName = response.functionName;
+ }
const valueElement = ObjectUI.ObjectPropertiesSection.valueElementForFunctionDescription(
func.description, includePreview, defaultName);
element.appendChild(valueElement);
@@ -384,8 +423,9 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
* @return {boolean}
*/
static _isDisplayableProperty(property, parentProperty) {
- if (!parentProperty || !parentProperty.synthetic)
+ if (!parentProperty || !parentProperty.synthetic) {
return true;
+ }
const name = property.name;
const useless = (parentProperty.name === '[[Entries]]' && (name === 'length' || name === '__proto__'));
return !useless;
@@ -441,7 +481,27 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
ObjectUI.ObjectPropertiesSection._arrayLoadThreshold = 100;
/** @const */
ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = 10000;
+/**
+ * @typedef {{
+ * readOnly: (boolean|undefined),
+ * }}
+ */
+ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions;
+ObjectUI.ObjectPropertiesSectionsTreeOutline = class extends UI.TreeOutlineInShadow {
+ /**
+ * @param {?ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions=} options
+ */
+ constructor(options) {
+ super();
+ this.registerRequiredCSS('object_ui/objectValue.css');
+ this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
+ this._editable = !(options && options.readOnly);
+ this.contentElement.classList.add('source-code');
+ this.contentElement.classList.add('object-properties-section');
+ this.hideOverflow();
+ }
+};
/**
* @unrestricted
@@ -474,16 +534,18 @@ ObjectUI.ObjectPropertiesSection.RootElement = class extends UI.TreeElement {
* @override
*/
onexpand() {
- if (this.treeOutline)
+ if (this.treeOutline) {
this.treeOutline.element.classList.add('expanded');
+ }
}
/**
* @override
*/
oncollapse() {
- if (this.treeOutline)
+ if (this.treeOutline) {
this.treeOutline.element.classList.remove('expanded');
+ }
}
/**
@@ -546,19 +608,22 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
}
let allProperties;
- if (flattenProtoChain)
+ if (flattenProtoChain) {
allProperties = await value.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */);
- else
+ } else {
allProperties = await SDK.RemoteObject.loadFromObjectPerProto(value, true /* generatePreview */);
+ }
const properties = allProperties.properties;
const internalProperties = allProperties.internalProperties;
treeElement.removeChildren();
- if (!properties)
+ if (!properties) {
return;
+ }
extraProperties = extraProperties || [];
- for (let i = 0; i < extraProperties.length; ++i)
+ for (let i = 0; i < extraProperties.length; ++i) {
properties.push(extraProperties[i]);
+ }
ObjectUI.ObjectPropertyTreeElement.populateWithProperties(
treeElement, properties, internalProperties, skipProto, targetValue || value, linkifier, emptyPlaceholder);
@@ -581,7 +646,6 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
value,
linkifier,
emptyPlaceholder) {
- properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);
internalProperties = internalProperties || [];
const entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
@@ -598,8 +662,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
property.parentObject = value;
- if (!ObjectUI.ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property))
+ if (!ObjectUI.ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property)) {
continue;
+ }
if (property.name === '__proto__' && !property.isAccessorProperty()) {
protoProperty = property;
continue;
@@ -616,19 +681,23 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
tailProperties.push(setterProperty);
}
const canShowProperty = property.getter || !property.isAccessorProperty();
- if (canShowProperty && property.name !== '__proto__')
+ if (canShowProperty && property.name !== '__proto__') {
treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(property, linkifier));
+ }
}
- for (let i = 0; i < tailProperties.length; ++i)
+ for (let i = 0; i < tailProperties.length; ++i) {
treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(tailProperties[i], linkifier));
- if (!skipProto && protoProperty)
+ }
+ if (!skipProto && protoProperty) {
treeNode.appendChild(new ObjectUI.ObjectPropertyTreeElement(protoProperty, linkifier));
+ }
for (const property of internalProperties) {
property.parentObject = value;
const treeElement = new ObjectUI.ObjectPropertyTreeElement(property, linkifier);
- if (property.name === '[[Entries]]')
+ if (property.name === '[[Entries]]') {
continue;
+ }
treeNode.appendChild(treeElement);
}
@@ -640,8 +709,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
* @param {?string=} emptyPlaceholder
*/
static _appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder) {
- if (treeNode.childCount())
+ if (treeNode.childCount()) {
return;
+ }
const title = createElementWithClass('div', 'gray-info-message');
title.textContent = emptyPlaceholder || Common.UIString('No properties');
const infoElement = new UI.TreeElement(title);
@@ -658,8 +728,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
const rootElement = createElement('span');
const element = rootElement.createChild('span');
element.textContent = Common.UIString('(...)');
- if (!object)
+ if (!object) {
return rootElement;
+ }
element.classList.add('object-value-calculate-value-button');
element.title = Common.UIString('Invoke property getter');
element.addEventListener('click', onInvokeGetterClick, false);
@@ -677,8 +748,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
function invokeGetter(arrayStr) {
let result = this;
const properties = JSON.parse(arrayStr);
- for (let i = 0, n = properties.length; i < n; ++i)
+ for (let i = 0, n = properties.length; i < n; ++i) {
result = result[properties[i]];
+ }
return result;
}
@@ -692,14 +764,16 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
*/
setSearchRegex(regex, additionalCssClassName) {
let cssClasses = UI.highlightedSearchResultClassName;
- if (additionalCssClassName)
+ if (additionalCssClassName) {
cssClasses += ' ' + additionalCssClassName;
+ }
this.revertHighlightChanges();
this._applySearch(regex, this.nameElement, cssClasses);
const valueType = this.property.value.type;
- if (valueType !== 'object')
+ if (valueType !== 'object') {
this._applySearch(regex, this.valueElement, cssClasses);
+ }
return !!this._highlightChanges.length;
}
@@ -718,8 +792,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
ranges.push(new TextUtils.SourceRange(match.index, match[0].length));
match = regex.exec(content);
}
- if (ranges.length)
+ if (ranges.length) {
UI.highlightRangesWithStyleClass(element, ranges, cssClassName, this._highlightChanges);
+ }
}
revertHighlightChanges() {
@@ -747,8 +822,21 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
ondblclick(event) {
const inEditableElement = event.target.isSelfOrDescendant(this.valueElement) ||
(this.expandedValueElement && event.target.isSelfOrDescendant(this.expandedValueElement));
- if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter))
+ if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter)) {
this._startEditing();
+ }
+ return false;
+ }
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ onenter() {
+ if (!this.property.value.customPreview() && (this.property.writable || this.property.setter)) {
+ this._startEditing();
+ return true;
+ }
return false;
}
@@ -778,12 +866,14 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
* @param {boolean} value
*/
_showExpandedValueElement(value) {
- if (!this.expandedValueElement)
+ if (!this.expandedValueElement) {
return;
- if (value)
+ }
+ if (value) {
this._rowContainer.replaceChild(this.expandedValueElement, this.valueElement);
- else
+ } else {
this._rowContainer.replaceChild(this.valueElement, this.expandedValueElement);
+ }
}
/**
@@ -793,14 +883,16 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
_createExpandedValueElement(value) {
const needsAlternateValue = value.hasChildren && !value.customPreview() && value.subtype !== 'node' &&
value.type !== 'function' && (value.type !== 'object' || value.preview);
- if (!needsAlternateValue)
+ if (!needsAlternateValue) {
return null;
+ }
const valueElement = createElementWithClass('span', 'value');
- if (value.description === 'Object')
+ if (value.description === 'Object') {
valueElement.textContent = '';
- else
+ } else {
valueElement.setTextContentTruncatedIfNeeded(value.description || '');
+ }
valueElement.classList.add('object-value-' + (value.subtype || value.type));
valueElement.title = value.description || '';
return valueElement;
@@ -808,10 +900,12 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
update() {
this.nameElement = ObjectUI.ObjectPropertiesSection.createNameElement(this.property.name, this.property.private);
- if (!this.property.enumerable)
+ if (!this.property.enumerable) {
this.nameElement.classList.add('object-properties-section-dimmed');
- if (this.property.synthetic)
+ }
+ if (this.property.synthetic) {
this.nameElement.classList.add('synthetic-property');
+ }
this._updatePropertyPath();
@@ -832,20 +926,23 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
}
const valueText = this.valueElement.textContent;
- if (this.property.value && valueText && !this.property.wasThrown)
+ if (this.property.value && valueText && !this.property.wasThrown) {
this.expandedValueElement = this._createExpandedValueElement(this.property.value);
+ }
this.listItemElement.removeChildren();
- if (isInternalEntries)
+ if (isInternalEntries) {
this._rowContainer = UI.html`<span class='name-and-value'>${this.nameElement}</span>`;
- else
+ } else {
this._rowContainer = UI.html`<span class='name-and-value'>${this.nameElement}: ${this.valueElement}</span>`;
+ }
this.listItemElement.appendChild(this._rowContainer);
}
_updatePropertyPath() {
- if (this.nameElement.title)
+ if (this.nameElement.title) {
return;
+ }
const name = this.property.name;
@@ -860,12 +957,13 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
const parentPath =
(this.parent.nameElement && !this.parent.property.synthetic) ? this.parent.nameElement.title : '';
- if (this.property.private || useDotNotation.test(name))
+ if (this.property.private || useDotNotation.test(name)) {
this.nameElement.title = parentPath ? `${parentPath}.${name}` : name;
- else if (isInteger.test(name))
+ } else if (isInteger.test(name)) {
this.nameElement.title = parentPath + '[' + name + ']';
- else
+ } else {
this.nameElement.title = parentPath + '["' + JSON.stringify(name) + '"]';
+ }
}
/**
@@ -874,12 +972,15 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
_contextMenuFired(event) {
const contextMenu = new UI.ContextMenu(event);
contextMenu.appendApplicableItems(this);
- if (this.property.symbol)
+ if (this.property.symbol) {
contextMenu.appendApplicableItems(this.property.symbol);
- if (this.property.value)
+ }
+ if (this.property.value) {
contextMenu.appendApplicableItems(this.property.value);
+ }
if (!this.property.synthetic && this.nameElement && this.nameElement.title) {
- const copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title);
+ const copyPathHandler =
+ Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, this.nameElement.title);
contextMenu.clipboardSection().appendItem(ls`Copy property path`, copyPathHandler);
}
if (this.property.parentObject instanceof SDK.LocalJSONObject) {
@@ -890,14 +991,16 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
}
_startEditing() {
- if (this._prompt || !this.treeOutline._editable || this._readOnly)
+ if (this._prompt || !this.treeOutline._editable || this._readOnly) {
return;
+ }
this._editableDiv = this._rowContainer.createChild('span', 'editable-div');
let text = this.property.value.description;
- if (this.property.value.type === 'string' && typeof text === 'string')
+ if (this.property.value.type === 'string' && typeof text === 'string') {
text = '"' + text + '"';
+ }
this._editableDiv.setTextContentTruncatedIfNeeded(text, Common.UIString('<string is too large to edit>'));
const originalContent = this._editableDiv.textContent;
@@ -923,6 +1026,7 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
this._updateExpandable();
this.listItemElement.scrollLeft = 0;
this.listItemElement.classList.remove('editing-sub-part');
+ this.select();
}
_editingCancelled() {
@@ -971,8 +1075,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
if (this.property.synthetic) {
let invalidate = false;
- if (expression)
+ if (expression) {
invalidate = await this.property.setSyntheticValue(expression);
+ }
if (invalidate) {
const parent = this.parent;
parent.invalidateChildren();
@@ -1006,8 +1111,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
* @param {!SDK.CallFunctionResult} result
*/
_onInvokeGetterClick(result) {
- if (!result.object)
+ if (!result.object) {
return;
+ }
this.property.value = result.object;
this.property.wasThrown = result.wasThrown;
@@ -1105,16 +1211,18 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
function* arrayIndexes(object) {
if (toIndex - fromIndex < sparseIterationThreshold) {
for (let i = fromIndex; i <= toIndex; ++i) {
- if (i in object)
+ if (i in object) {
yield i;
+ }
}
} else {
ownPropertyNames = ownPropertyNames || Object.getOwnPropertyNames(object);
for (let i = 0; i < ownPropertyNames.length; ++i) {
const name = ownPropertyNames[i];
const index = name >>> 0;
- if (('' + index) === name && fromIndex <= index && index <= toIndex)
+ if (('' + index) === name && fromIndex <= index && index <= toIndex) {
yield index;
+ }
}
}
}
@@ -1128,18 +1236,20 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
}
let bucketSize = count;
- if (count <= bucketThreshold)
+ if (count <= bucketThreshold) {
bucketSize = count;
- else
+ } else {
bucketSize = Math.pow(bucketThreshold, Math.ceil(Math.log(count) / Math.log(bucketThreshold)) - 1);
+ }
const ranges = [];
if (consecutiveRange) {
for (let i = fromIndex; i <= toIndex; i += bucketSize) {
const groupStart = i;
let groupEnd = groupStart + bucketSize - 1;
- if (groupEnd > toIndex)
+ if (groupEnd > toIndex) {
groupEnd = toIndex;
+ }
ranges.push([groupStart, groupEnd, groupEnd - groupStart + 1]);
}
} else {
@@ -1147,8 +1257,9 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
let groupStart = -1;
let groupEnd = 0;
for (const i of arrayIndexes(this)) {
- if (groupStart === -1)
+ if (groupStart === -1) {
groupStart = i;
+ }
groupEnd = i;
if (++count === bucketSize) {
ranges.push([groupStart, groupEnd, count]);
@@ -1156,16 +1267,18 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
groupStart = -1;
}
}
- if (count > 0)
+ if (count > 0) {
ranges.push([groupStart, groupEnd, count]);
+ }
}
return {ranges: ranges, skipGetOwnPropertyNames: skipGetOwnPropertyNames};
}
async function callback(result) {
- if (!result)
+ if (!result) {
return;
+ }
const ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges);
if (ranges.length === 1) {
await ObjectUI.ArrayGroupingTreeElement._populateAsFragment(
@@ -1203,15 +1316,17 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
const result = await object.callFunction(
buildArrayFragment,
[{value: fromIndex}, {value: toIndex}, {value: ObjectUI.ArrayGroupingTreeElement._sparseIterationThreshold}]);
- if (!result.object || result.wasThrown)
+ if (!result.object || result.wasThrown) {
return;
+ }
const arrayFragment = result.object;
const allProperties =
await arrayFragment.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */);
arrayFragment.release();
const properties = allProperties.properties;
- if (!properties)
+ if (!properties) {
return;
+ }
properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);
for (let i = 0; i < properties.length; ++i) {
properties[i].parentObject = this._object;
@@ -1231,16 +1346,18 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
const result = Object.create(null);
if (toIndex - fromIndex < sparseIterationThreshold) {
for (let i = fromIndex; i <= toIndex; ++i) {
- if (i in this)
+ if (i in this) {
result[i] = this[i];
+ }
}
} else {
const ownPropertyNames = Object.getOwnPropertyNames(this);
for (let i = 0; i < ownPropertyNames.length; ++i) {
const name = ownPropertyNames[i];
const index = name >>> 0;
- if (String(index) === name && fromIndex <= index && index <= toIndex)
+ if (String(index) === name && fromIndex <= index && index <= toIndex) {
result[index] = this[index];
+ }
}
}
return result;
@@ -1257,18 +1374,21 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
*/
static async _populateNonIndexProperties(treeNode, object, skipGetOwnPropertyNames, linkifier) {
const result = await object.callFunction(buildObjectFragment, [{value: skipGetOwnPropertyNames}]);
- if (!result.object || result.wasThrown)
+ if (!result.object || result.wasThrown) {
return;
+ }
const allProperties = await result.object.getOwnProperties(true /* generatePreview */);
result.object.release();
- if (!allProperties.properties)
+ if (!allProperties.properties) {
return;
+ }
const properties = allProperties.properties;
properties.sort(ObjectUI.ObjectPropertiesSection.CompareProperties);
for (const property of properties) {
property.parentObject = this._object;
- if (!ObjectUI.ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property))
+ if (!ObjectUI.ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property)) {
continue;
+ }
const childTreeElement = new ObjectUI.ObjectPropertyTreeElement(property, linkifier);
childTreeElement._readOnly = true;
treeNode.appendChild(childTreeElement);
@@ -1281,17 +1401,20 @@ ObjectUI.ArrayGroupingTreeElement = class extends UI.TreeElement {
*/
function buildObjectFragment(skipGetOwnPropertyNames) {
const result = {__proto__: this.__proto__};
- if (skipGetOwnPropertyNames)
+ if (skipGetOwnPropertyNames) {
return result;
+ }
const names = Object.getOwnPropertyNames(this);
for (let i = 0; i < names.length; ++i) {
const name = names[i];
// Array index check according to the ES5-15.4.
- if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff)
+ if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff) {
continue;
+ }
const descriptor = Object.getOwnPropertyDescriptor(this, name);
- if (descriptor)
+ if (descriptor) {
Object.defineProperty(result, name, descriptor);
+ }
}
return result;
}
@@ -1352,10 +1475,11 @@ ObjectUI.ObjectPropertiesSectionExpandController = class {
section.addEventListener(UI.TreeOutline.Events.ElementAttached, this._elementAttached, this);
section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._elementExpanded, this);
section.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this);
- section[ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId] = id;
+ section[ObjectUI.ObjectPropertiesSectionsTreeExpandController._treeOutlineId] = id;
- if (this._expandedProperties.has(id))
+ if (this._expandedProperties.has(id)) {
section.expand();
+ }
}
/**
@@ -1363,8 +1487,9 @@ ObjectUI.ObjectPropertiesSectionExpandController = class {
*/
stopWatchSectionsWithId(id) {
for (const property of this._expandedProperties) {
- if (property.startsWith(id + ':'))
+ if (property.startsWith(id + ':')) {
this._expandedProperties.delete(property);
+ }
}
}
@@ -1373,8 +1498,9 @@ ObjectUI.ObjectPropertiesSectionExpandController = class {
*/
_elementAttached(event) {
const element = /** @type {!UI.TreeElement} */ (event.data);
- if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element)))
+ if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element))) {
element.expand();
+ }
}
/**
@@ -1398,9 +1524,10 @@ ObjectUI.ObjectPropertiesSectionExpandController = class {
* @return {string}
*/
_propertyPath(treeElement) {
- const cachedPropertyPath = treeElement[ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol];
- if (cachedPropertyPath)
+ const cachedPropertyPath = treeElement[ObjectUI.ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol];
+ if (cachedPropertyPath) {
return cachedPropertyPath;
+ }
let current = treeElement;
const rootElement = treeElement.treeOutline.objectTreeElement();
@@ -1409,23 +1536,123 @@ ObjectUI.ObjectPropertiesSectionExpandController = class {
while (current !== rootElement) {
let currentName = '';
- if (current.property)
+ if (current.property) {
currentName = current.property.name;
- else
+ } else {
currentName = typeof current.title === 'string' ? current.title : current.title.textContent;
+ }
result = currentName + (result ? '.' + result : '');
current = current.parent;
}
- const treeOutlineId = treeElement.treeOutline[ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId];
+ const treeOutlineId = treeElement.treeOutline[ObjectUI.ObjectPropertiesSectionsTreeExpandController._treeOutlineId];
result = treeOutlineId + (result ? ':' + result : '');
- treeElement[ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol] = result;
+ treeElement[ObjectUI.ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol] = result;
return result;
}
};
-ObjectUI.ObjectPropertiesSectionExpandController._cachedPathSymbol = Symbol('cachedPath');
-ObjectUI.ObjectPropertiesSectionExpandController._treeOutlineId = Symbol('treeOutlineId');
+/**
+ * @unrestricted
+ */
+ObjectUI.ObjectPropertiesSectionsTreeExpandController = class {
+ /**
+ * @param {!UI.TreeOutline} treeOutline
+ */
+ constructor(treeOutline) {
+ /** @type {!Set.<string>} */
+ this._expandedProperties = new Set();
+ treeOutline.addEventListener(UI.TreeOutline.Events.ElementAttached, this._elementAttached, this);
+ treeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._elementExpanded, this);
+ treeOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this);
+ }
+
+ /**
+ * @param {string} id
+ * @param {!ObjectUI.ObjectPropertiesSection.RootElement} section
+ */
+ watchSection(id, section) {
+ section[ObjectUI.ObjectPropertiesSectionsTreeExpandController._treeOutlineId] = id;
+
+ if (this._expandedProperties.has(id)) {
+ section.expand();
+ }
+ }
+
+ /**
+ * @param {string} id
+ */
+ stopWatchSectionsWithId(id) {
+ for (const property of this._expandedProperties) {
+ if (property.startsWith(id + ':')) {
+ this._expandedProperties.delete(property);
+ }
+ }
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _elementAttached(event) {
+ const element = /** @type {!UI.TreeElement} */ (event.data);
+ if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element))) {
+ element.expand();
+ }
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _elementExpanded(event) {
+ const element = /** @type {!UI.TreeElement} */ (event.data);
+ this._expandedProperties.add(this._propertyPath(element));
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _elementCollapsed(event) {
+ const element = /** @type {!UI.TreeElement} */ (event.data);
+ this._expandedProperties.delete(this._propertyPath(element));
+ }
+
+ /**
+ * @param {!UI.TreeElement} treeElement
+ * @return {string}
+ */
+ _propertyPath(treeElement) {
+ const cachedPropertyPath = treeElement[ObjectUI.ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol];
+ if (cachedPropertyPath) {
+ return cachedPropertyPath;
+ }
+
+ let current = treeElement;
+ let sectionRoot = current;
+ const rootElement = treeElement.treeOutline.rootElement();
+
+ let result;
+
+ while (current !== rootElement) {
+ let currentName = '';
+ if (current.property) {
+ currentName = current.property.name;
+ } else {
+ currentName = typeof current.title === 'string' ? current.title : current.title.textContent;
+ }
+
+ result = currentName + (result ? '.' + result : '');
+ sectionRoot = current;
+ current = current.parent;
+ }
+ const treeOutlineId = sectionRoot[ObjectUI.ObjectPropertiesSectionsTreeExpandController._treeOutlineId];
+ result = treeOutlineId + (result ? ':' + result : '');
+ treeElement[ObjectUI.ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol] = result;
+ return result;
+ }
+};
+
+ObjectUI.ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol = Symbol('cachedPath');
+ObjectUI.ObjectPropertiesSectionsTreeExpandController._treeOutlineId = Symbol('treeOutlineId');
/**
* @implements {UI.Renderer}
@@ -1438,13 +1665,15 @@ ObjectUI.ObjectPropertiesSection.Renderer = class {
* @return {!Promise<?{node: !Node, tree: ?UI.TreeOutline}>}
*/
render(object, options) {
- if (!(object instanceof SDK.RemoteObject))
+ if (!(object instanceof SDK.RemoteObject)) {
return Promise.reject(new Error('Can\'t render ' + object));
+ }
options = options || {};
const title = options.title;
const section = new ObjectUI.ObjectPropertiesSection(object, title);
- if (!title)
+ if (!title) {
section.titleLessMode();
+ }
section.editable = !!options.editable;
return Promise.resolve(
/** @type {?{node: !Node, tree: ?UI.TreeOutline}} */ ({node: section.element, tree: section}));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
index eb928dc6f3e..65172c855d0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/RemoteObjectPreviewFormatter.js
@@ -20,15 +20,17 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
function sortValue(property) {
// TODO(einbinder) expose whether preview properties are actually internal.
const internalName = ObjectUI.RemoteObjectPreviewFormatter._internalName;
- if (property.name === internalName.PromiseStatus)
+ if (property.name === internalName.PromiseStatus) {
return 1;
- else if (property.name === internalName.PromiseValue)
+ } else if (property.name === internalName.PromiseValue) {
return 2;
- else if (property.name === internalName.GeneratorStatus || property.name === internalName.PrimitiveValue)
+ } else if (property.name === internalName.GeneratorStatus || property.name === internalName.PrimitiveValue) {
return 3;
+ }
// TODO(einbinder) expose whether preview properties are actually private.
- else if (property.type !== 'function' && !property.name.startsWith('#'))
+ else if (property.type !== 'function' && !property.name.startsWith('#')) {
return 4;
+ }
return 5;
}
}
@@ -57,20 +59,22 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
const hideDescription = description === 'Object';
text = hideDescription ? '' : description;
}
- if (text.length > 0)
- parentElement.createChild('span', 'object-description').textContent = text + '\u00a0';
+ if (text.length > 0) {
+ parentElement.createChild('span', 'object-description').textContent = text + '\xA0';
+ }
}
const propertiesElement = parentElement.createChild('span', 'object-properties-preview');
propertiesElement.createTextChild(isArrayOrTypedArray ? '[' : '{');
- if (preview.entries)
+ if (preview.entries) {
this._appendEntriesPreview(propertiesElement, preview);
- else if (isArrayOrTypedArray)
+ } else if (isArrayOrTypedArray) {
this._appendArrayPropertiesPreview(propertiesElement, preview);
- else
+ } else {
this._appendObjectPropertiesPreview(propertiesElement, preview);
+ }
if (preview.overflow) {
- const ellipsisText = propertiesElement.textContent.length > 1 ? ',\u00a0\u2026' : '\u2026';
+ const ellipsisText = propertiesElement.textContent.length > 1 ? ',\xA0\u2026' : '\u2026';
propertiesElement.createChild('span').textContent = ellipsisText;
}
propertiesElement.createTextChild(isArrayOrTypedArray ? ']' : '}');
@@ -82,8 +86,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
*/
_abbreviateFullQualifiedClassName(description) {
const abbreviatedDescription = description.split('.');
- for (let i = 0; i < abbreviatedDescription.length - 1; ++i)
+ for (let i = 0; i < abbreviatedDescription.length - 1; ++i) {
abbreviatedDescription[i] = abbreviatedDescription[i].trimMiddle(3);
+ }
return abbreviatedDescription.join('.');
}
@@ -96,8 +101,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
const properties = preview.properties.filter(p => p.type !== 'accessor')
.sort(ObjectUI.RemoteObjectPreviewFormatter._objectPropertyComparator);
for (let i = 0; i < properties.length; ++i) {
- if (i > 0)
+ if (i > 0) {
parentElement.createTextChild(', ');
+ }
const property = properties[i];
const name = property.name;
@@ -149,8 +155,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
*/
function toArrayIndex(name) {
const index = name >>> 0;
- if (String(index) === name && index < arrayLength)
+ if (String(index) === name && index < arrayLength) {
return index;
+ }
return -1;
}
@@ -159,8 +166,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
let lastNonEmptyArrayIndex = -1;
let elementsAdded = false;
for (let i = 0; i < indexProperties.length; ++i) {
- if (elementsAdded)
+ if (elementsAdded) {
parentElement.createTextChild(', ');
+ }
const property = indexProperties[i];
const index = toArrayIndex(property.name);
@@ -178,14 +186,16 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
}
if (canShowGaps && arrayLength - lastNonEmptyArrayIndex > 1) {
- if (elementsAdded)
+ if (elementsAdded) {
parentElement.createTextChild(', ');
+ }
appendUndefined(arrayLength);
}
for (let i = 0; i < otherProperties.length; ++i) {
- if (elementsAdded)
+ if (elementsAdded) {
parentElement.createTextChild(', ');
+ }
const property = otherProperties[i];
parentElement.appendChild(this._renderDisplayName(property.name));
@@ -211,8 +221,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
*/
_appendEntriesPreview(parentElement, preview) {
for (let i = 0; i < preview.entries.length; ++i) {
- if (i > 0)
+ if (i > 0) {
parentElement.createTextChild(', ');
+ }
const entry = preview.entries[i];
if (entry.key) {
@@ -276,8 +287,9 @@ ObjectUI.RemoteObjectPreviewFormatter = class {
if (type === 'object' && !subtype) {
let preview = this._abbreviateFullQualifiedClassName(description);
- if (preview === 'Object')
+ if (preview === 'Object') {
preview = '{\u2026}';
+ }
span.textContent = preview;
span.title = description;
return span;
@@ -303,8 +315,10 @@ ObjectUI.RemoteObjectPreviewFormatter._internalName = {
ObjectUI.RemoteObjectPreviewFormatter.createSpansForNodeTitle = function(container, nodeTitle) {
const match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/);
container.createChild('span', 'webkit-html-tag-name').textContent = match[1];
- if (match[2])
+ if (match[2]) {
container.createChild('span', 'webkit-html-attribute-value').textContent = match[2];
- if (match[3])
+ }
+ if (match[3]) {
container.createChild('span', 'webkit-html-attribute-name').textContent = match[3];
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectValue.css b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectValue.css
index bfaf983b38b..e2dae873d90 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectValue.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectValue.css
@@ -48,7 +48,7 @@
.object-value-string,
.object-value-regexp,
.object-value-symbol {
- white-space: pre;
+ white-space: pre !important;
unicode-bidi: -webkit-isolate;
color: rgb(196, 26, 22);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
index 66386f92982..90a9d0cc9a0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/object_ui_strings.grdp
@@ -24,9 +24,6 @@
<message name="IDS_DEVTOOLS_59aeb2c9970b7b25be2fab2317e31fcb" desc="Text in Java Script Autocomplete">
keywords
</message>
- <message name="IDS_DEVTOOLS_a2e4822a98337283e39f7b60acf85ec9" desc="Text in Remote Object Preview Formatter">
- empty
- </message>
<message name="IDS_DEVTOOLS_a6565c5180039dd2ca1249796bba00a5" desc="Text in Object Properties Section">
No properties
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/ChartViewport.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/ChartViewport.js
index b1ad8cbc51f..12c774e36e6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/ChartViewport.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/ChartViewport.js
@@ -100,8 +100,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
_updateScrollBar() {
const showScroll = this._alwaysShowVerticalScroll || this._totalHeight > this._offsetHeight;
- if (this._vScrollElement.classList.contains('hidden') !== showScroll)
+ if (this._vScrollElement.classList.contains('hidden') !== showScroll) {
return;
+ }
this._vScrollElement.classList.toggle('hidden', !showScroll);
this._updateContentElementSize();
}
@@ -136,8 +137,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
_updateContentElementSize() {
let offsetWidth = this._vScrollElement.offsetLeft;
- if (!offsetWidth)
+ if (!offsetWidth) {
offsetWidth = this.contentElement.offsetWidth;
+ }
this._offsetWidth = offsetWidth;
this._offsetHeight = this.contentElement.offsetHeight;
this._delegate.setSize(this._offsetWidth, this._offsetHeight);
@@ -150,8 +152,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
this._totalHeight = totalHeight;
this._vScrollContent.style.height = totalHeight + 'px';
this._updateScrollBar();
- if (this._scrollTop + this._offsetHeight <= totalHeight)
+ if (this._scrollTop + this._offsetHeight <= totalHeight) {
return;
+ }
this._scrollTop = Math.max(0, totalHeight - this._offsetHeight);
this._vScrollElement.scrollTop = this._scrollTop;
}
@@ -162,10 +165,11 @@ PerfUI.ChartViewport = class extends UI.VBox {
*/
setScrollOffset(offset, height) {
height = height || 0;
- if (this._vScrollElement.scrollTop > offset)
+ if (this._vScrollElement.scrollTop > offset) {
this._vScrollElement.scrollTop = offset;
- else if (this._vScrollElement.scrollTop < offset - this._offsetHeight + height)
+ } else if (this._vScrollElement.scrollTop < offset - this._offsetHeight + height) {
this._vScrollElement.scrollTop = offset - this._offsetHeight + height;
+ }
}
/**
@@ -209,8 +213,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
* @return {boolean}
*/
_startDragging(event) {
- if (event.shiftKey)
+ if (event.shiftKey) {
return false;
+ }
this._isDragging = true;
this._dragStartPointX = event.pageX;
this._dragStartPointY = event.pageY;
@@ -239,8 +244,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
* @return {boolean}
*/
_startRangeSelection(event) {
- if (!event.shiftKey || !this._rangeSelectionEnabled)
+ if (!event.shiftKey || !this._rangeSelectionEnabled) {
return false;
+ }
this._isDragging = true;
this._selectionOffsetShiftX = event.offsetX - event.pageX;
this._selectionOffsetShiftY = event.offsetY - event.pageY;
@@ -269,8 +275,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
* @param {number} endTime
*/
setRangeSelection(startTime, endTime) {
- if (!this._rangeSelectionEnabled)
+ if (!this._rangeSelectionEnabled) {
return;
+ }
this._rangeSelectionStart = Math.min(startTime, endTime);
this._rangeSelectionEnd = Math.max(startTime, endTime);
this._updateRangeSelectionOverlay();
@@ -282,8 +289,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
*/
onClick(event) {
const time = this.pixelToTime(event.offsetX);
- if (this._rangeSelectionStart !== null && time >= this._rangeSelectionStart && time <= this._rangeSelectionEnd)
+ if (this._rangeSelectionStart !== null && time >= this._rangeSelectionStart && time <= this._rangeSelectionEnd) {
return;
+ }
this.hideRangeSelection();
}
@@ -385,8 +393,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
* @param {!Event} e
*/
_handleZoomPanKeys(e) {
- if (!UI.KeyboardShortcut.hasNoModifiers(e))
+ if (!UI.KeyboardShortcut.hasNoModifiers(e)) {
return;
+ }
const zoomFactor = e.shiftKey ? 0.8 : 0.3;
const panOffset = e.shiftKey ? 320 : 160;
switch (e.code) {
@@ -446,14 +455,16 @@ PerfUI.ChartViewport = class extends UI.VBox {
bounds.left = Math.max(bounds.left - bounds.right + maxBound, this._minimumBoundary);
bounds.right = maxBound;
}
- if (bounds.right - bounds.left < PerfUI.FlameChart.MinimalTimeWindowMs)
+ if (bounds.right - bounds.left < PerfUI.FlameChart.MinimalTimeWindowMs) {
return;
+ }
this._delegate.windowChanged(bounds.left, bounds.right, animate);
}
scheduleUpdate() {
- if (this._updateTimerId || this._cancelWindowTimesAnimation)
+ if (this._updateTimerId || this._cancelWindowTimesAnimation) {
return;
+ }
this._updateTimerId = this.element.window().requestAnimationFrame(() => {
this._updateTimerId = 0;
this._update();
@@ -471,8 +482,9 @@ PerfUI.ChartViewport = class extends UI.VBox {
* @param {boolean=} animate
*/
setWindowTimes(startTime, endTime, animate) {
- if (startTime === this._targetLeftTime && endTime === this._targetRightTime)
+ if (startTime === this._targetLeftTime && endTime === this._targetRightTime) {
return;
+ }
if (!animate || this._visibleLeftTime === 0 || this._visibleRightTime === Infinity ||
(startTime === 0 && endTime === Infinity) || (startTime === Infinity && endTime === Infinity)) {
// Skip animation, move instantly.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FilmStripView.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FilmStripView.js
index 3b120e74d87..ce967da96ae 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FilmStripView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FilmStripView.js
@@ -19,8 +19,9 @@ PerfUI.FilmStripView = class extends UI.HBox {
* @param {?string} data
*/
static _setImageData(imageElement, data) {
- if (data)
+ if (data) {
imageElement.src = 'data:image/jpg;base64,' + data;
+ }
}
/**
@@ -59,6 +60,7 @@ PerfUI.FilmStripView = class extends UI.HBox {
element.title = Common.UIString('Doubleclick to zoom image. Click to view preceding requests.');
element.createChild('div', 'time').textContent = Number.millisToString(time - this._zeroTime);
const imageElement = element.createChild('div', 'thumbnail').createChild('img');
+ imageElement.alt = ls`Screenshot`;
element.addEventListener(
'mousedown', this._onMouseEvent.bind(this, PerfUI.FilmStripView.Events.FrameSelected, time), false);
element.addEventListener(
@@ -99,11 +101,13 @@ PerfUI.FilmStripView = class extends UI.HBox {
}
update() {
- if (!this._model)
+ if (!this._model) {
return;
+ }
const frames = this._model.frames();
- if (!frames.length)
+ if (!frames.length) {
return;
+ }
if (this._mode === PerfUI.FilmStripView.Modes.FrameBased) {
Promise.all(frames.map(this.createFrameElement.bind(this))).then(appendElements.bind(this));
@@ -121,8 +125,9 @@ PerfUI.FilmStripView = class extends UI.HBox {
*/
function continueWhenFrameImageLoaded(element0) {
const frameWidth = Math.ceil(UI.measurePreferredSize(element0, this.contentElement).width);
- if (!frameWidth)
+ if (!frameWidth) {
return;
+ }
const promises = [];
for (let pos = frameWidth; pos < width; pos += frameWidth) {
@@ -146,8 +151,9 @@ PerfUI.FilmStripView = class extends UI.HBox {
*/
function appendElements(elements) {
this.contentElement.removeChildren();
- for (let i = 0; i < elements.length; ++i)
+ for (let i = 0; i < elements.length; ++i) {
this.contentElement.appendChild(elements[i]);
+ }
}
}
@@ -155,13 +161,14 @@ PerfUI.FilmStripView = class extends UI.HBox {
* @override
*/
onResize() {
- if (this._mode === PerfUI.FilmStripView.Modes.FrameBased)
+ if (this._mode === PerfUI.FilmStripView.Modes.FrameBased) {
return;
+ }
this.update();
}
/**
- * @param {string} eventName
+ * @param {string|symbol} eventName
* @param {number} timestamp
*/
_onMouseEvent(eventName, timestamp) {
@@ -253,17 +260,19 @@ PerfUI.FilmStripView.Dialog = class {
_keyDown(event) {
switch (event.key) {
case 'ArrowLeft':
- if (Host.isMac() && event.metaKey)
+ if (Host.isMac() && event.metaKey) {
this._onFirstFrame();
- else
+ } else {
this._onPrevFrame();
+ }
break;
case 'ArrowRight':
- if (Host.isMac() && event.metaKey)
+ if (Host.isMac() && event.metaKey) {
this._onLastFrame();
- else
+ } else {
this._onNextFrame();
+ }
break;
case 'Home':
@@ -277,14 +286,16 @@ PerfUI.FilmStripView.Dialog = class {
}
_onPrevFrame() {
- if (this._index > 0)
+ if (this._index > 0) {
--this._index;
+ }
this._render();
}
_onNextFrame() {
- if (this._index < this._frames.length - 1)
+ if (this._index < this._frames.length - 1) {
++this._index;
+ }
this._render();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
index 5b44340690d..f65970690c8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
@@ -73,7 +73,7 @@ PerfUI.FlameChart = class extends UI.VBox {
this._groupExpansionState = groupExpansionSetting && groupExpansionSetting.get() || {};
this._flameChartDelegate = flameChartDelegate;
- this._useWebGL = Runtime.experiments.isEnabled('timelineWebGL');
+ this._useWebGL = Root.Runtime.experiments.isEnabled('timelineWebGL');
this._chartViewport = new PerfUI.ChartViewport(this);
this._chartViewport.show(this.contentElement);
@@ -100,6 +100,13 @@ PerfUI.FlameChart = class extends UI.VBox {
this._markerHighlighElement = this._viewportElement.createChild('div', 'flame-chart-marker-highlight-element');
this._highlightElement = this._viewportElement.createChild('div', 'flame-chart-highlight-element');
this._selectedElement = this._viewportElement.createChild('div', 'flame-chart-selected-element');
+ this._canvas.addEventListener('focus', () => {
+ this._selectedElement.classList.remove('flame-chart-unfocused-selected-element');
+ this.dispatchEventToListeners(PerfUI.FlameChart.Events.CanvasFocused);
+ }, false);
+ this._canvas.addEventListener('blur', () => {
+ this._selectedElement.classList.add('flame-chart-unfocused-selected-element');
+ }, false);
UI.installDragHandle(
this._viewportElement, this._startDragging.bind(this), this._dragging.bind(this), this._endDragging.bind(this),
@@ -194,10 +201,12 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {number} entryIndex
*/
highlightEntry(entryIndex) {
- if (this._highlightedEntryIndex === entryIndex)
+ if (this._highlightedEntryIndex === entryIndex) {
return;
- if (!this._dataProvider.entryColor(entryIndex))
+ }
+ if (!this._dataProvider.entryColor(entryIndex)) {
return;
+ }
this._highlightedEntryIndex = entryIndex;
this._updateElementPosition(this._highlightElement, this._highlightedEntryIndex);
this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntryHighlighted, entryIndex);
@@ -286,11 +295,13 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {?PerfUI.FlameChart.TimelineData}
*/
_timelineData() {
- if (!this._dataProvider)
+ if (!this._dataProvider) {
return null;
+ }
const timelineData = this._dataProvider.timelineData();
- if (timelineData !== this._rawTimelineData || timelineData.entryStartTimes.length !== this._rawTimelineDataLength)
+ if (timelineData !== this._rawTimelineData || timelineData.entryStartTimes.length !== this._rawTimelineDataLength) {
this._processTimelineData(timelineData);
+ }
return this._rawTimelineData;
}
@@ -299,8 +310,9 @@ PerfUI.FlameChart = class extends UI.VBox {
*/
_revealEntry(entryIndex) {
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return;
+ }
const timeLeft = this._chartViewport.windowLeftTime();
const timeRight = this._chartViewport.windowRightTime();
const entryStartTime = timelineData.entryStartTimes[entryIndex];
@@ -339,10 +351,12 @@ PerfUI.FlameChart = class extends UI.VBox {
_onMouseMove(event) {
this._lastMouseOffsetX = event.offsetX;
this._lastMouseOffsetY = event.offsetY;
- if (!this._enabled())
+ if (!this._enabled()) {
return;
- if (this._chartViewport.isDragging())
+ }
+ if (this._chartViewport.isDragging()) {
return;
+ }
if (this._coordinatesToGroupIndex(event.offsetX, event.offsetY, true /* headerOnly */) >= 0) {
this.hideHighlight();
this._viewportElement.style.cursor = 'pointer';
@@ -357,14 +371,16 @@ PerfUI.FlameChart = class extends UI.VBox {
this.hideHighlight();
const group =
this._coordinatesToGroupIndex(this._lastMouseOffsetX, this._lastMouseOffsetY, false /* headerOnly */);
- if (group >= 0 && this._rawTimelineData.groups[group].selectable)
+ if (group >= 0 && this._rawTimelineData.groups[group].selectable) {
this._viewportElement.style.cursor = 'pointer';
- else
+ } else {
this._viewportElement.style.cursor = 'default';
+ }
return;
}
- if (this._chartViewport.isDragging())
+ if (this._chartViewport.isDragging()) {
return;
+ }
this._updatePopover(entryIndex);
this._viewportElement.style.cursor = this._dataProvider.canJumpToEntry(entryIndex) ? 'pointer' : 'default';
this.highlightEntry(entryIndex);
@@ -408,8 +424,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const dy = quadrant & 1 ? -offsetY - infoHeight : offsetY;
x = Number.constrain(mouseX + dx, 0, parentWidth - infoWidth);
y = Number.constrain(mouseY + dy, 0, parentHeight - infoHeight);
- if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight)
+ if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight) {
break;
+ }
}
this._entryInfo.style.left = x + 'px';
this._entryInfo.style.top = y + 'px';
@@ -424,8 +441,9 @@ PerfUI.FlameChart = class extends UI.VBox {
// So if there was drag (mouse move) in the middle of that events
// we skip the click. Otherwise we jump to the sources.
const /** @const */ clickThreshold = 5;
- if (this._maxDragOffset > clickThreshold)
+ if (this._maxDragOffset > clickThreshold) {
return;
+ }
this._selectGroup(this._coordinatesToGroupIndex(event.offsetX, event.offsetY, false /* headerOnly */));
this._toggleGroupExpand(this._coordinatesToGroupIndex(event.offsetX, event.offsetY, true /* headerOnly */));
@@ -436,7 +454,7 @@ PerfUI.FlameChart = class extends UI.VBox {
this._chartViewport.setRangeSelection(start, end);
} else {
this._chartViewport.onClick(event);
- this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntrySelected, this._highlightedEntryIndex);
+ this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntryInvoked, this._highlightedEntryIndex);
}
}
@@ -444,8 +462,9 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {number} groupIndex
*/
_selectGroup(groupIndex) {
- if (groupIndex < 0 || this._selectedGroup === groupIndex)
+ if (groupIndex < 0 || this._selectedGroup === groupIndex) {
return;
+ }
const groups = this._rawTimelineData.groups;
this._keyboardFocusedGroup = groupIndex;
if (!groups[groupIndex].selectable) {
@@ -485,8 +504,9 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {number} groupIndex
*/
_toggleGroupExpand(groupIndex) {
- if (groupIndex < 0 || !this._isGroupCollapsible(groupIndex))
+ if (groupIndex < 0 || !this._isGroupCollapsible(groupIndex)) {
return;
+ }
this._expandGroup(groupIndex, !this._rawTimelineData.groups[groupIndex].expanded /* setExpanded */);
}
@@ -497,16 +517,18 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {boolean=} propagatedExpand
*/
_expandGroup(groupIndex, setExpanded = true, propagatedExpand = false) {
- if (groupIndex < 0 || !this._isGroupCollapsible(groupIndex))
+ if (groupIndex < 0 || !this._isGroupCollapsible(groupIndex)) {
return;
+ }
const groups = this._rawTimelineData.groups;
const group = groups[groupIndex];
group.expanded = setExpanded;
this._groupExpansionState[group.name] = group.expanded;
- if (this._groupExpansionSetting)
+ if (this._groupExpansionSetting) {
this._groupExpansionSetting.set(this._groupExpansionState);
+ }
this._updateLevelPositions();
this._updateHighlight();
@@ -514,8 +536,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const timelineData = this._timelineData();
const level = timelineData.entryLevels[this._selectedEntryIndex];
if (this._selectedEntryIndex >= 0 && level >= group.startLevel &&
- (groupIndex >= groups.length - 1 || groups[groupIndex + 1].startLevel > level))
+ (groupIndex >= groups.length - 1 || groups[groupIndex + 1].startLevel > level)) {
this._selectedEntryIndex = -1;
+ }
}
this._updateHeight();
@@ -534,14 +557,16 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {!Event} e
*/
_onKeyDown(e) {
- if (!UI.KeyboardShortcut.hasNoModifiers(e) || !this._timelineData())
+ if (!UI.KeyboardShortcut.hasNoModifiers(e) || !this._timelineData()) {
return;
+ }
const eventHandled = this._handleSelectionNavigation(e);
// Handle keyboard navigation in groups
- if (!eventHandled && this._rawTimelineData && this._rawTimelineData.groups)
+ if (!eventHandled && this._rawTimelineData && this._rawTimelineData.groups) {
this._handleKeyboardGroupNavigation(e);
+ }
}
/**
@@ -571,11 +596,13 @@ PerfUI.FlameChart = class extends UI.VBox {
handled = entrySelected;
}
- if (handled && !entrySelected)
+ if (handled && !entrySelected) {
this._deselectAllEntries();
+ }
- if (handled)
+ if (handled) {
e.consume(true);
+ }
}
/**
@@ -584,23 +611,26 @@ PerfUI.FlameChart = class extends UI.VBox {
_selectFirstEntryInCurrentGroup() {
const allGroups = this._rawTimelineData.groups;
- if (this._keyboardFocusedGroup < 0)
+ if (this._keyboardFocusedGroup < 0) {
return false;
+ }
const group = allGroups[this._keyboardFocusedGroup];
const startLevelInGroup = group.startLevel;
// Return if no levels in this group
- if (startLevelInGroup < 0)
+ if (startLevelInGroup < 0) {
return false;
+ }
// Make sure this is the innermost nested group with this startLevel
// This is because a parent group also contains levels of all its child groups
// So check if the next group has the same level, if it does, user should
// go to that child group to select this entry
if (this._keyboardFocusedGroup < allGroups.length - 1 &&
- allGroups[this._keyboardFocusedGroup + 1].startLevel === startLevelInGroup)
+ allGroups[this._keyboardFocusedGroup + 1].startLevel === startLevelInGroup) {
return false;
+ }
// Get first (default) entry in startLevel of selected group
@@ -615,8 +645,9 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {boolean}
*/
_selectPreviousGroup() {
- if (this._keyboardFocusedGroup <= 0)
+ if (this._keyboardFocusedGroup <= 0) {
return false;
+ }
const groupIndexToSelect = this._getGroupIndexToSelect(-1 /* offset */);
this._selectGroup(groupIndexToSelect);
@@ -627,8 +658,9 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {boolean}
*/
_selectNextGroup() {
- if (this._keyboardFocusedGroup >= this._rawTimelineData.groups.length - 1)
+ if (this._keyboardFocusedGroup >= this._rawTimelineData.groups.length - 1) {
return false;
+ }
const groupIndexToSelect = this._getGroupIndexToSelect(1 /* offset */);
this._selectGroup(groupIndexToSelect);
@@ -657,8 +689,9 @@ PerfUI.FlameChart = class extends UI.VBox {
_selectFirstChild() {
const allGroups = this._rawTimelineData.groups;
- if (this._keyboardFocusedGroup < 0 || this._keyboardFocusedGroup >= allGroups.length - 1)
+ if (this._keyboardFocusedGroup < 0 || this._keyboardFocusedGroup >= allGroups.length - 1) {
return;
+ }
const groupIndexToSelect = this._keyboardFocusedGroup + 1;
if (allGroups[groupIndexToSelect].style.nestingLevel > allGroups[this._keyboardFocusedGroup].style.nestingLevel) {
@@ -672,11 +705,13 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {boolean}
*/
_handleSelectionNavigation(e) {
- if (this._selectedEntryIndex === -1)
+ if (this._selectedEntryIndex === -1) {
return false;
+ }
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return false;
+ }
/**
* @param {number} time
@@ -707,8 +742,9 @@ PerfUI.FlameChart = class extends UI.VBox {
let indexOnLevel = levelIndexes.lowerBound(this._selectedEntryIndex);
indexOnLevel += e.keyCode === keys.Left.code ? -1 : 1;
e.consume(true);
- if (indexOnLevel >= 0 && indexOnLevel < levelIndexes.length)
+ if (indexOnLevel >= 0 && indexOnLevel < levelIndexes.length) {
this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntrySelected, levelIndexes[indexOnLevel]);
+ }
return true;
}
if (e.keyCode === keys.Up.code || e.keyCode === keys.Down.code) {
@@ -727,8 +763,9 @@ PerfUI.FlameChart = class extends UI.VBox {
++indexOnLevel;
if (indexOnLevel >= levelIndexes.length ||
!entriesIntersect(this._selectedEntryIndex, levelIndexes[indexOnLevel])) {
- if (e.code === 'ArrowDown')
+ if (e.code === 'ArrowDown') {
return false;
+ }
// Stay in the current group and give focus to the parent group instead of entries
this._deselectAllEntries();
@@ -740,6 +777,11 @@ PerfUI.FlameChart = class extends UI.VBox {
this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntrySelected, levelIndexes[indexOnLevel]);
return true;
}
+ if (isEnterKey(e)) {
+ e.consume(true);
+ this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntryInvoked, this._selectedEntryIndex);
+ return true;
+ }
return false;
}
@@ -749,32 +791,39 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {number}
*/
_coordinatesToEntryIndex(x, y) {
- if (x < 0 || y < 0)
+ if (x < 0 || y < 0) {
return -1;
+ }
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return -1;
+ }
y += this._chartViewport.scrollOffset();
const cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1;
- if (cursorLevel < 0 || !this._visibleLevels[cursorLevel])
+ if (cursorLevel < 0 || !this._visibleLevels[cursorLevel]) {
return -1;
+ }
const offsetFromLevel = y - this._visibleLevelOffsets[cursorLevel];
- if (offsetFromLevel > this._levelHeight(cursorLevel))
+ if (offsetFromLevel > this._levelHeight(cursorLevel)) {
return -1;
+ }
// Check markers first.
for (const [index, pos] of this._markerPositions) {
- if (timelineData.entryLevels[index] !== cursorLevel)
+ if (timelineData.entryLevels[index] !== cursorLevel) {
continue;
- if (pos.x <= x && x < pos.x + pos.width)
+ }
+ if (pos.x <= x && x < pos.x + pos.width) {
return /** @type {number} */ (index);
+ }
}
// Check regular entries.
const entryStartTimes = timelineData.entryStartTimes;
const entriesOnLevel = this._timelineLevels[cursorLevel];
- if (!entriesOnLevel || !entriesOnLevel.length)
+ if (!entriesOnLevel || !entriesOnLevel.length) {
return -1;
+ }
const cursorTime = this._chartViewport.pixelToTime(x);
const indexOnLevel = Math.max(
@@ -786,8 +835,9 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {boolean}
*/
function checkEntryHit(entryIndex) {
- if (entryIndex === undefined)
+ if (entryIndex === undefined) {
return false;
+ }
const startTime = entryStartTimes[entryIndex];
const duration = timelineData.entryTotalTimes[entryIndex];
const startX = this._chartViewport.timeToPosition(startTime);
@@ -797,11 +847,13 @@ PerfUI.FlameChart = class extends UI.VBox {
}
let entryIndex = entriesOnLevel[indexOnLevel];
- if (checkEntryHit.call(this, entryIndex))
+ if (checkEntryHit.call(this, entryIndex)) {
return entryIndex;
+ }
entryIndex = entriesOnLevel[indexOnLevel + 1];
- if (checkEntryHit.call(this, entryIndex))
+ if (checkEntryHit.call(this, entryIndex)) {
return entryIndex;
+ }
return -1;
}
@@ -812,26 +864,31 @@ PerfUI.FlameChart = class extends UI.VBox {
* @return {number}
*/
_coordinatesToGroupIndex(x, y, headerOnly) {
- if (x < 0 || y < 0)
+ if (x < 0 || y < 0) {
return -1;
+ }
y += this._chartViewport.scrollOffset();
const groups = this._rawTimelineData.groups || [];
const group = this._groupOffsets.upperBound(y) - 1;
- if (group < 0 || group >= groups.length)
+ if (group < 0 || group >= groups.length) {
return -1;
+ }
const height = headerOnly ? groups[group].style.height : this._groupOffsets[group + 1] - this._groupOffsets[group];
- if (y - this._groupOffsets[group] >= height)
+ if (y - this._groupOffsets[group] >= height) {
return -1;
- if (!headerOnly)
+ }
+ if (!headerOnly) {
return group;
+ }
const context = /** @type {!CanvasRenderingContext2D} */ (this._canvas.getContext('2d'));
context.save();
context.font = groups[group].style.font;
const right = this._headerLeftPadding + this._labelWidthForGroup(context, groups[group]);
context.restore();
- if (x > right)
+ if (x > right) {
return -1;
+ }
return group;
}
@@ -842,8 +899,9 @@ PerfUI.FlameChart = class extends UI.VBox {
*/
_markerIndexAtPosition(x) {
const markers = this._timelineData().markers;
- if (!markers)
+ if (!markers) {
return -1;
+ }
const /** @const */ accurracyOffsetPx = 4;
const time = this._chartViewport.pixelToTime(x);
const leftTime = this._chartViewport.pixelToTime(x - accurracyOffsetPx);
@@ -872,8 +930,9 @@ PerfUI.FlameChart = class extends UI.VBox {
_draw() {
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return;
+ }
const width = this._offsetWidth;
const height = this._offsetHeight;
@@ -904,10 +963,12 @@ PerfUI.FlameChart = class extends UI.VBox {
/** @type {!Map<string, !Array<number>>} */
const colorBuckets = new Map();
for (let level = minVisibleBarLevel; level < this._dataProvider.maxStackDepth(); ++level) {
- if (this._levelToOffset(level) > top + height)
+ if (this._levelToOffset(level) > top + height) {
break;
- if (!this._visibleLevels[level])
+ }
+ if (!this._visibleLevels[level]) {
continue;
+ }
// Entries are ordered by start time within a level, so find the last visible entry.
const levelIndexes = this._timelineLevels[level];
@@ -923,20 +984,24 @@ PerfUI.FlameChart = class extends UI.VBox {
markerIndices.push(entryIndex);
continue;
}
- if (duration >= minTextWidthDuration || this._forceDecorationCache[entryIndex])
+ if (duration >= minTextWidthDuration || this._forceDecorationCache[entryIndex]) {
titleIndices.push(entryIndex);
+ }
const entryStartTime = entryStartTimes[entryIndex];
const entryOffsetRight = entryStartTime + duration;
- if (entryOffsetRight <= this._chartViewport.windowLeftTime())
+ if (entryOffsetRight <= this._chartViewport.windowLeftTime()) {
break;
- if (this._useWebGL)
+ }
+ if (this._useWebGL) {
continue;
+ }
const barX = this._timeToPositionClipped(entryStartTime);
// Check if the entry entirely fits into an already drawn pixel, we can just skip drawing it.
- if (barX >= lastDrawOffset)
+ if (barX >= lastDrawOffset) {
continue;
+ }
lastDrawOffset = barX;
const color = this._entryColorsCache[entryIndex];
@@ -966,8 +1031,9 @@ PerfUI.FlameChart = class extends UI.VBox {
for (let i = 0; i < indexes.length; ++i) {
const entryIndex = indexes[i];
const duration = entryTotalTimes[entryIndex];
- if (isNaN(duration))
+ if (isNaN(duration)) {
continue;
+ }
const entryStartTime = entryStartTimes[entryIndex];
const barX = this._timeToPositionClipped(entryStartTime);
const barLevel = entryLevels[entryIndex];
@@ -990,12 +1056,14 @@ PerfUI.FlameChart = class extends UI.VBox {
for (let m = markerIndices.length - 1; m >= 0; --m) {
const entryIndex = markerIndices[m];
const title = this._dataProvider.entryTitle(entryIndex);
- if (!title)
+ if (!title) {
continue;
+ }
const entryStartTime = entryStartTimes[entryIndex];
const level = entryLevels[entryIndex];
- if (lastMarkerLevel !== level)
+ if (lastMarkerLevel !== level) {
lastMarkerX = -Infinity;
+ }
const x = Math.max(this._chartViewport.timeToPosition(entryStartTime), lastMarkerX);
const y = this._levelToOffset(level);
const h = this._levelHeight(level);
@@ -1028,10 +1096,12 @@ PerfUI.FlameChart = class extends UI.VBox {
const unclippedBarX = this._chartViewport.timeToPosition(entryStartTime);
const barHeight = this._levelHeight(barLevel);
if (this._dataProvider.decorateEntry(
- entryIndex, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixel))
+ entryIndex, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixel)) {
continue;
- if (!text || !text.length)
+ }
+ if (!text || !text.length) {
continue;
+ }
context.fillStyle = this._dataProvider.textColor(entryIndex);
context.fillText(text, barX + textPadding, barY + barHeight - this._textBaseline);
}
@@ -1095,8 +1165,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
- if (gl.getShaderParameter(shader, gl.COMPILE_STATUS))
+ if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
return shader;
+ }
console.error('Shader compile error: ' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
@@ -1133,12 +1204,14 @@ PerfUI.FlameChart = class extends UI.VBox {
_setupGLGeometry() {
const gl = /** @type {?WebGLRenderingContext} */ (this._canvasGL.getContext('webgl'));
- if (!gl)
+ if (!gl) {
return;
+ }
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return;
+ }
const entryTotalTimes = timelineData.entryTotalTimes;
const entryStartTimes = timelineData.entryStartTimes;
@@ -1156,36 +1229,43 @@ PerfUI.FlameChart = class extends UI.VBox {
const collapsedOverviewLevels = new Array(this._visibleLevels.length);
const groups = this._rawTimelineData.groups || [];
this._forEachGroup((offset, index, group) => {
- if (group.style.useFirstLineForOverview || !this._isGroupCollapsible(index) || group.expanded)
+ if (group.style.useFirstLineForOverview || !this._isGroupCollapsible(index) || group.expanded) {
return;
+ }
let nextGroup = index + 1;
- while (nextGroup < groups.length && groups[nextGroup].style.nestingLevel > group.style.nestingLevel)
+ while (nextGroup < groups.length && groups[nextGroup].style.nestingLevel > group.style.nestingLevel) {
++nextGroup;
+ }
const endLevel = nextGroup < groups.length ? groups[nextGroup].startLevel : this._dataProvider.maxStackDepth();
- for (let i = group.startLevel; i < endLevel; ++i)
+ for (let i = group.startLevel; i < endLevel; ++i) {
collapsedOverviewLevels[i] = offset;
+ }
});
for (let i = 0; i < entryTotalTimes.length; ++i) {
const level = entryLevels[i];
const collapsedGroupOffset = collapsedOverviewLevels[level];
- if (!this._visibleLevels[level] && !collapsedGroupOffset)
+ if (!this._visibleLevels[level] && !collapsedGroupOffset) {
continue;
+ }
const color = this._entryColorsCache[i];
- if (!color)
+ if (!color) {
continue;
+ }
let colorIndex = parsedColorCache.get(color);
if (colorIndex === undefined) {
const rgba = Common.Color.parse(color).canonicalRGBA();
rgba[3] = Math.round(rgba[3] * 255);
colorIndex = colors.length / 4;
colors.push(...rgba);
- if (colorIndex === 256)
+ if (colorIndex === 256) {
colorArray = new Uint16Array(colorArray);
+ }
parsedColorCache.set(color, colorIndex);
}
- for (let j = 0; j < verticesPerBar; ++j)
+ for (let j = 0; j < verticesPerBar; ++j) {
colorArray[vertex + j] = colorIndex;
+ }
const vpos = vertex * 2;
const x0 = entryStartTimes[i] - this._minimumBoundary;
@@ -1223,8 +1303,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const colorIndexType = useShortForColors ? gl.UNSIGNED_SHORT : gl.UNSIGNED_BYTE;
if (useShortForColors) {
const factor = (1 << 16) / width;
- for (let i = 0; i < vertex; ++i)
+ for (let i = 0; i < vertex; ++i) {
colorArray[i] *= factor;
+ }
}
const pixels = new Uint8Array(width * 4);
@@ -1242,11 +1323,13 @@ PerfUI.FlameChart = class extends UI.VBox {
_drawGL() {
const gl = /** @type {?WebGLRenderingContext} */ (this._canvasGL.getContext('webgl'));
- if (!gl)
+ if (!gl) {
return;
+ }
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return;
+ }
if (!this._prevTimelineData || timelineData.entryTotalTimes !== this._prevTimelineData.entryTotalTimes) {
this._prevTimelineData = timelineData;
@@ -1255,8 +1338,9 @@ PerfUI.FlameChart = class extends UI.VBox {
gl.viewport(0, 0, this._canvasGL.width, this._canvasGL.height);
- if (!this._vertexCount)
+ if (!this._vertexCount) {
return;
+ }
const viewportScale = [2.0 / this.boundarySpan(), -2.0 * window.devicePixelRatio / this._canvasGL.height];
const viewportShift = [this.minimumBoundary() - this.zeroTime(), this._chartViewport.scrollOffset()];
@@ -1275,8 +1359,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const top = this._chartViewport.scrollOffset();
const ratio = window.devicePixelRatio;
const groups = this._rawTimelineData.groups || [];
- if (!groups.length)
+ if (!groups.length) {
return;
+ }
const groupOffsets = this._groupOffsets;
const lastGroupOffset = Array.prototype.peekLast.call(groupOffsets);
@@ -1291,26 +1376,30 @@ PerfUI.FlameChart = class extends UI.VBox {
context.fillStyle = UI.themeSupport.patchColorText('#fff', colorUsage.Background);
this._forEachGroupInViewport((offset, index, group) => {
const paddingHeight = group.style.padding;
- if (paddingHeight < 5)
+ if (paddingHeight < 5) {
return;
+ }
context.fillRect(0, offset - paddingHeight + 2, width, paddingHeight - 4);
});
- if (groups.length && lastGroupOffset < top + height)
+ if (groups.length && lastGroupOffset < top + height) {
context.fillRect(0, lastGroupOffset + 2, width, top + height - lastGroupOffset);
+ }
context.strokeStyle = UI.themeSupport.patchColorText('#eee', colorUsage.Background);
context.beginPath();
this._forEachGroupInViewport((offset, index, group, isFirst) => {
- if (isFirst || group.style.padding < 4)
+ if (isFirst || group.style.padding < 4) {
return;
+ }
hLine(offset - 2.5);
});
hLine(lastGroupOffset + 1.5);
context.stroke();
this._forEachGroupInViewport((offset, index, group) => {
- if (group.style.useFirstLineForOverview)
+ if (group.style.useFirstLineForOverview) {
return;
+ }
if (!this._isGroupCollapsible(index) || group.expanded) {
if (!group.style.shareHeaderLine && this._isGroupFocused(index)) {
context.fillStyle = group.style.backgroundColor;
@@ -1318,11 +1407,13 @@ PerfUI.FlameChart = class extends UI.VBox {
}
return;
}
- if (this._useWebGL)
+ if (this._useWebGL) {
return;
+ }
let nextGroup = index + 1;
- while (nextGroup < groups.length && groups[nextGroup].style.nestingLevel > group.style.nestingLevel)
+ while (nextGroup < groups.length && groups[nextGroup].style.nestingLevel > group.style.nestingLevel) {
nextGroup++;
+ }
const endLevel = nextGroup < groups.length ? groups[nextGroup].startLevel : this._dataProvider.maxStackDepth();
this._drawCollapsedOverviewForGroup(group, offset, endLevel);
});
@@ -1332,10 +1423,11 @@ PerfUI.FlameChart = class extends UI.VBox {
context.font = group.style.font;
if (this._isGroupCollapsible(index) && !group.expanded || group.style.shareHeaderLine) {
const width = this._labelWidthForGroup(context, group) + 2;
- if (this._isGroupFocused(index))
+ if (this._isGroupFocused(index)) {
context.fillStyle = this._selectedGroupBackroundColor;
- else
+ } else {
context.fillStyle = Common.Color.parse(group.style.backgroundColor).setAlpha(0.8).asString(null);
+ }
context.fillRect(
this._headerLeftPadding - this._headerLabelXPadding, offset + this._headerLabelYPadding, width,
@@ -1408,8 +1500,9 @@ PerfUI.FlameChart = class extends UI.VBox {
*/
_forEachGroup(callback) {
const groups = this._rawTimelineData.groups || [];
- if (!groups.length)
+ if (!groups.length) {
return;
+ }
const groupOffsets = this._groupOffsets;
/** @type !Array<{nestingLevel: number, visible: boolean}> */
const groupStack = [{nestingLevel: -1, visible: true}];
@@ -1425,8 +1518,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const thisGroupVisible = parentGroupVisible && (!this._isGroupCollapsible(i) || group.expanded);
groupStack.push({nestingLevel: group.style.nestingLevel, visible: thisGroupVisible});
const nextOffset = i === groups.length - 1 ? groupOffsets[i + 1] + group.style.padding : groupOffsets[i + 1];
- if (!parentGroupVisible)
+ if (!parentGroupVisible) {
continue;
+ }
callback(groupTop, i, group, firstGroup, nextOffset - groupTop);
}
}
@@ -1437,10 +1531,12 @@ PerfUI.FlameChart = class extends UI.VBox {
_forEachGroupInViewport(callback) {
const top = this._chartViewport.scrollOffset();
this._forEachGroup((groupTop, index, group, firstGroup, height) => {
- if (groupTop - group.style.padding > top + this._offsetHeight)
+ if (groupTop - group.style.padding > top + this._offsetHeight) {
return;
- if (groupTop + height < top)
+ }
+ if (groupTop + height < top) {
return;
+ }
callback(groupTop, index, group, firstGroup, height);
});
}
@@ -1481,10 +1577,12 @@ PerfUI.FlameChart = class extends UI.VBox {
const entryStartTime = entryStartTimes[entryIndex];
const barX = this._timeToPositionClipped(entryStartTime);
const entryEndTime = entryStartTime + entryTotalTimes[entryIndex];
- if (isNaN(entryEndTime) || barX >= lastDrawOffset)
+ if (isNaN(entryEndTime) || barX >= lastDrawOffset) {
continue;
- if (entryEndTime <= timeWindowLeft)
+ }
+ if (entryEndTime <= timeWindowLeft) {
break;
+ }
lastDrawOffset = barX;
const color = this._entryColorsCache[entryIndex];
const endBarX = this._timeToPositionClipped(entryEndTime);
@@ -1547,8 +1645,9 @@ PerfUI.FlameChart = class extends UI.VBox {
context.lineWidth = 0.5;
for (let i = 0; i < endIndex; ++i) {
- if (!td.flowEndTimes[i] || td.flowEndTimes[i] < this._chartViewport.windowLeftTime())
+ if (!td.flowEndTimes[i] || td.flowEndTimes[i] < this._chartViewport.windowLeftTime()) {
continue;
+ }
const startX = this._chartViewport.timeToPosition(td.flowStartTimes[i]);
const endX = this._chartViewport.timeToPosition(td.flowEndTimes[i]);
const startLevel = td.flowStartLevels[i];
@@ -1609,8 +1708,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const height = PerfUI.FlameChart.HeaderHeight - 1;
for (let i = left; i < markers.length; i++) {
const timestamp = markers[i].startTime();
- if (timestamp > rightBoundary)
+ if (timestamp > rightBoundary) {
break;
+ }
markers[i].draw(context, this._chartViewport.timeToPosition(timestamp), height, timeToPixel);
}
context.restore();
@@ -1618,11 +1718,13 @@ PerfUI.FlameChart = class extends UI.VBox {
_updateMarkerHighlight() {
const element = this._markerHighlighElement;
- if (element.parentElement)
+ if (element.parentElement) {
element.remove();
+ }
const markerIndex = this._highlightedMarkerIndex;
- if (markerIndex === -1)
+ if (markerIndex === -1) {
return;
+ }
const marker = this._timelineData().markers[markerIndex];
const barX = this._timeToPositionClipped(marker.startTime());
element.title = marker.title();
@@ -1661,8 +1763,9 @@ PerfUI.FlameChart = class extends UI.VBox {
}
const entryCounters = new Uint32Array(this._dataProvider.maxStackDepth() + 1);
- for (let i = 0; i < timelineData.entryLevels.length; ++i)
+ for (let i = 0; i < timelineData.entryLevels.length; ++i) {
++entryCounters[timelineData.entryLevels[i]];
+ }
const levelIndexes = new Array(entryCounters.length);
for (let i = 0; i < levelIndexes.length; ++i) {
levelIndexes[i] = new Uint32Array(entryCounters[i]);
@@ -1677,8 +1780,9 @@ PerfUI.FlameChart = class extends UI.VBox {
const groups = this._rawTimelineData.groups || [];
for (let i = 0; i < groups.length; ++i) {
const expanded = this._groupExpansionState[groups[i].name];
- if (expanded !== undefined)
+ if (expanded !== undefined) {
groups[i].expanded = expanded;
+ }
}
this._updateLevelPositions();
this._updateHeight();
@@ -1719,14 +1823,17 @@ PerfUI.FlameChart = class extends UI.VBox {
parentGroupIsVisible = groupStack.peekLast().visible;
visible = thisGroupIsVisible && parentGroupIsVisible;
groupStack.push({nestingLevel: style.nestingLevel, visible: visible});
- if (parentGroupIsVisible)
+ if (parentGroupIsVisible) {
currentOffset += nextLevel ? 0 : style.padding;
+ }
this._groupOffsets[groupIndex] = currentOffset;
- if (parentGroupIsVisible && !style.shareHeaderLine)
+ if (parentGroupIsVisible && !style.shareHeaderLine) {
currentOffset += style.height;
+ }
}
- if (level >= levelCount)
+ if (level >= levelCount) {
continue;
+ }
const isFirstOnLevel = groupIndex >= 0 && level === groups[groupIndex].startLevel;
const thisLevelIsVisible =
parentGroupIsVisible && (visible || isFirstOnLevel && groups[groupIndex].style.useFirstLineForOverview);
@@ -1743,14 +1850,17 @@ PerfUI.FlameChart = class extends UI.VBox {
this._visibleLevels[level] = thisLevelIsVisible;
this._visibleLevelOffsets[level] = currentOffset;
this._visibleLevelHeights[level] = height;
- if (thisLevelIsVisible || (parentGroupIsVisible && style && style.shareHeaderLine && isFirstOnLevel))
+ if (thisLevelIsVisible || (parentGroupIsVisible && style && style.shareHeaderLine && isFirstOnLevel)) {
currentOffset += this._visibleLevelHeights[level];
+ }
}
- if (groupIndex >= 0)
+ if (groupIndex >= 0) {
this._groupOffsets[groupIndex + 1] = currentOffset;
+ }
this._visibleLevelOffsets[level] = currentOffset;
- if (this._useWebGL)
+ if (this._useWebGL) {
this._setupGLGeometry();
+ }
}
/**
@@ -1759,14 +1869,17 @@ PerfUI.FlameChart = class extends UI.VBox {
_isGroupCollapsible(index) {
const groups = this._rawTimelineData.groups || [];
const style = groups[index].style;
- if (!style.shareHeaderLine || !style.collapsible)
+ if (!style.shareHeaderLine || !style.collapsible) {
return !!style.collapsible;
+ }
const isLastGroup = index + 1 >= groups.length;
- if (!isLastGroup && groups[index + 1].style.nestingLevel > style.nestingLevel)
+ if (!isLastGroup && groups[index + 1].style.nestingLevel > style.nestingLevel) {
return true;
+ }
const nextGroupLevel = isLastGroup ? this._dataProvider.maxStackDepth() : groups[index + 1].startLevel;
- if (nextGroupLevel !== groups[index].startLevel + 1)
+ if (nextGroupLevel !== groups[index].startLevel + 1) {
return true;
+ }
// For groups that only have one line and share header line, pretend these are not collapsible
// unless the itemsHeight does not match the headerHeight
return style.height !== style.itemsHeight;
@@ -1776,10 +1889,12 @@ PerfUI.FlameChart = class extends UI.VBox {
* @param {number} entryIndex
*/
setSelectedEntry(entryIndex) {
- if (this._selectedEntryIndex === entryIndex)
+ if (this._selectedEntryIndex === entryIndex) {
return;
- if (entryIndex !== -1)
+ }
+ if (entryIndex !== -1) {
this._chartViewport.hideRangeSelection();
+ }
this._selectedEntryIndex = entryIndex;
this._revealEntry(entryIndex);
this._updateElementPosition(this._selectedElement, this._selectedEntryIndex);
@@ -1792,8 +1907,9 @@ PerfUI.FlameChart = class extends UI.VBox {
_updateElementPosition(element, entryIndex) {
const elementMinWidthPx = 2;
element.classList.add('hidden');
- if (entryIndex === -1)
+ if (entryIndex === -1) {
return;
+ }
const timelineData = this._timelineData();
const startTime = timelineData.entryStartTimes[entryIndex];
const duration = timelineData.entryTotalTimes[entryIndex];
@@ -1812,8 +1928,9 @@ PerfUI.FlameChart = class extends UI.VBox {
barX = this._chartViewport.timeToPosition(startTime);
barWidth = duration * this._chartViewport.timeToPixel();
}
- if (barX + barWidth <= 0 || barX >= this._offsetWidth)
+ if (barX + barWidth <= 0 || barX >= this._offsetWidth) {
return;
+ }
const barCenter = barX + barWidth / 2;
barWidth = Math.max(barWidth, elementMinWidthPx);
barX = barCenter - barWidth / 2;
@@ -1875,14 +1992,16 @@ PerfUI.FlameChart = class extends UI.VBox {
* @override
*/
update() {
- if (!this._timelineData())
+ if (!this._timelineData()) {
return;
+ }
this._resetCanvas();
this._updateHeight();
this._updateBoundaries();
this._draw();
- if (!this._chartViewport.isDragging())
+ if (!this._chartViewport.isDragging()) {
this._updateHighlight();
+ }
}
reset() {
@@ -2137,6 +2256,8 @@ PerfUI.FlameChartMarker.prototype = {
/** @enum {symbol} */
PerfUI.FlameChart.Events = {
+ CanvasFocused: Symbol('CanvasFocused'),
+ EntryInvoked: Symbol('EntryInvoked'),
EntrySelected: Symbol('EntrySelected'),
EntryHighlighted: Symbol('EntryHighlighted')
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/GCActionDelegate.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/GCActionDelegate.js
index a443d0c9467..5d879e81747 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/GCActionDelegate.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/GCActionDelegate.js
@@ -13,8 +13,9 @@ PerfUI.GCActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- for (const heapProfilerModel of SDK.targetManager.models(SDK.HeapProfilerModel))
+ for (const heapProfilerModel of SDK.targetManager.models(SDK.HeapProfilerModel)) {
heapProfilerModel.collectGarbage();
+ }
return true;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js
index 5611239a16f..e2f85c3bbd5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js
@@ -25,8 +25,9 @@ PerfUI.LineLevelProfile.Performance = class {
for (let i = 0; i < nodes.length; ++i) {
const node = nodes[i];
nodesToGo.push(node);
- if (!node.url || !node.positionTicks)
+ if (!node.url || !node.positionTicks) {
continue;
+ }
for (let j = 0; j < node.positionTicks.length; ++j) {
const lineInfo = node.positionTicks[j];
const line = lineInfo.line;
@@ -49,12 +50,14 @@ PerfUI.LineLevelProfile.Performance = class {
const target = profile.target();
for (let i = 1; i < profile.samples.length; ++i) {
const line = profile.lines[i];
- if (!line)
+ if (!line) {
continue;
+ }
const node = profile.nodeByIndex(i);
const scriptIdOrUrl = node.scriptId || node.url;
- if (!scriptIdOrUrl)
+ if (!scriptIdOrUrl) {
continue;
+ }
const time = profile.timestamps[i] - profile.timestamps[i - 1];
this._helper.addLineData(target, scriptIdOrUrl, line, time);
}
@@ -85,11 +88,13 @@ PerfUI.LineLevelProfile.Memory = class {
*/
function processNode(node) {
node.children.forEach(processNode);
- if (!node.selfSize)
+ if (!node.selfSize) {
return;
+ }
const script = Number(node.callFrame.scriptId) || node.callFrame.url;
- if (!script)
+ if (!script) {
return;
+ }
const line = node.callFrame.lineNumber + 1;
helper.addLineData(target, script, line, node.selfSize);
}
@@ -135,8 +140,9 @@ PerfUI.LineLevelProfile._Helper = class {
}
scheduleUpdate() {
- if (this._updateTimer)
+ if (this._updateTimer) {
return;
+ }
this._updateTimer = setTimeout(() => {
this._updateTimer = null;
this._doUpdate();
@@ -158,8 +164,9 @@ PerfUI.LineLevelProfile._Helper = class {
const uiSourceCode = !debuggerModel && typeof scriptIdOrUrl === 'string' ?
Workspace.workspace.uiSourceCodeForURL(scriptIdOrUrl) :
null;
- if (!debuggerModel && !uiSourceCode)
+ if (!debuggerModel && !uiSourceCode) {
continue;
+ }
for (const lineToData of lineToDataMap) {
const line = /** @type {number} */ (lineToData[0]) - 1;
const data = /** @type {number} */ (lineToData[1]);
@@ -170,8 +177,9 @@ PerfUI.LineLevelProfile._Helper = class {
const rawLocation = typeof scriptIdOrUrl === 'string' ?
debuggerModel.createRawLocationByURL(scriptIdOrUrl, line, 0) :
debuggerModel.createRawLocationByScriptId(String(scriptIdOrUrl), line, 0);
- if (rawLocation)
+ if (rawLocation) {
new PerfUI.LineLevelProfile.Presentation(rawLocation, this._type, data, this._locationPool);
+ }
}
}
}
@@ -196,11 +204,13 @@ PerfUI.LineLevelProfile.Presentation = class {
* @param {!Bindings.LiveLocation} liveLocation
*/
updateLocation(liveLocation) {
- if (this._uiLocation)
+ if (this._uiLocation) {
this._uiLocation.uiSourceCode.removeDecorationsForType(this._type);
+ }
this._uiLocation = liveLocation.uiLocation();
- if (this._uiLocation)
+ if (this._uiLocation) {
this._uiLocation.uiSourceCode.addLineDecoration(this._uiLocation.lineNumber, this._type, this._time);
+ }
}
};
@@ -218,8 +228,9 @@ PerfUI.LineLevelProfile.LineDecorator = class {
const gutterType = `CodeMirror-gutter-${type}`;
const decorations = uiSourceCode.decorationsForType(type);
textEditor.uninstallGutter(gutterType);
- if (!decorations || !decorations.size)
+ if (!decorations || !decorations.size) {
return;
+ }
textEditor.installGutter(gutterType, false);
for (const decoration of decorations) {
const value = /** @type {number} */ (decoration.data());
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
index 71500858476..36f6553f9e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
@@ -13,8 +13,9 @@ PerfUI.LiveHeapProfile = class {
this._loadEventCallback = () => {};
this._setting = Common.settings.moduleSetting('memoryLiveHeapProfile');
this._setting.addChangeListener(event => event.data ? this._startProfiling() : this._stopProfiling());
- if (this._setting.get())
+ if (this._setting.get()) {
this._startProfiling();
+ }
}
/**
@@ -40,8 +41,9 @@ PerfUI.LiveHeapProfile = class {
}
async _startProfiling() {
- if (this._running)
+ if (this._running) {
return;
+ }
this._running = true;
const sessionId = this._sessionId;
SDK.targetManager.observeModels(SDK.HeapProfilerModel, this);
@@ -51,13 +53,15 @@ PerfUI.LiveHeapProfile = class {
do {
const models = SDK.targetManager.models(SDK.HeapProfilerModel);
const profiles = await Promise.all(models.map(model => model.getSamplingProfile()));
- if (sessionId !== this._sessionId)
+ if (sessionId !== this._sessionId) {
break;
+ }
const lineLevelProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Memory);
lineLevelProfile.reset();
for (let i = 0; i < profiles.length; ++i) {
- if (profiles[i])
+ if (profiles[i]) {
lineLevelProfile.appendHeapProfile(profiles[i], models[i].target());
+ }
}
await Promise.race([
new Promise(r => setTimeout(r, Host.isUnderTest() ? 10 : 5000)), new Promise(r => this._loadEventCallback = r)
@@ -67,14 +71,16 @@ PerfUI.LiveHeapProfile = class {
SDK.targetManager.unobserveModels(SDK.HeapProfilerModel, this);
SDK.targetManager.removeModelListener(
SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this._loadEventFired, this);
- for (const model of SDK.targetManager.models(SDK.HeapProfilerModel))
+ for (const model of SDK.targetManager.models(SDK.HeapProfilerModel)) {
model.stopSampling();
+ }
self.runtime.sharedInstance(PerfUI.LineLevelProfile.Memory).reset();
}
_stopProfiling() {
- if (!this._running)
+ if (!this._running) {
return;
+ }
this._running = 0;
this._sessionId++;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/NetworkPriorities.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/NetworkPriorities.js
index 16b3862f97c..e9c54f3249f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/NetworkPriorities.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/NetworkPriorities.js
@@ -27,8 +27,9 @@ PerfUI.uiLabelToNetworkPriority = function(priorityLabel) {
* @return {!Map<!Protocol.Network.ResourcePriority, string>}
*/
PerfUI._priorityUILabelMap = function() {
- if (PerfUI._priorityUILabelMapInstance)
+ if (PerfUI._priorityUILabelMapInstance) {
return PerfUI._priorityUILabelMapInstance;
+ }
/** @type {!Map<!Protocol.Network.ResourcePriority, string>} */
const map = new Map();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
index ca98103ab47..a9e224f8558 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
@@ -138,6 +138,8 @@ PerfUI.OverviewGrid.WindowScrollSpeedFactor = .3;
PerfUI.OverviewGrid.ResizerOffset = 3.5; // half pixel because offset values are not rounded but ceiled
+PerfUI.OverviewGrid.OffsetFromWindowEnds = 10;
+
/**
* @unrestricted
*/
@@ -172,11 +174,23 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
this._rightResizeElement, this._resizerElementStartDragging.bind(this),
this._rightResizeElementDragging.bind(this), null, 'ew-resize');
+ this._leftResizeElement.tabIndex = 0;
+ this._leftResizeElement.addEventListener('keydown', event => this._handleKeyboardResizing(event, false));
+
+ this._rightResizeElement.tabIndex = 0;
+ this._rightResizeElement.addEventListener('keydown', event => this._handleKeyboardResizing(event, true));
+ this._rightResizeElement.addEventListener('focus', this._onRightResizeElementFocused.bind(this));
+
this._leftCurtainElement = parentElement.createChild('div', 'window-curtain-left');
this._rightCurtainElement = parentElement.createChild('div', 'window-curtain-right');
this.reset();
}
+ _onRightResizeElementFocused() {
+ // To prevent browser focus from scrolling the element into view and shifting the contents of the strip
+ this._parentElement.scrollLeft = 0;
+ }
+
reset() {
this.windowLeft = 0.0;
this.windowRight = 1.0;
@@ -202,8 +216,9 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
* @param {!Event} event
*/
_resizerElementStartDragging(event) {
- if (!this._enabled)
+ if (!this._enabled) {
return false;
+ }
this._resizerParentOffsetLeft = event.pageX - event.offsetX - event.target.offsetLeft;
event.stopPropagation();
return true;
@@ -227,11 +242,56 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
/**
* @param {!Event} event
+ * @param {boolean=} moveRightResizer
+ */
+ _handleKeyboardResizing(event, moveRightResizer) {
+ let increment = false;
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
+ if (event.key === 'ArrowRight') {
+ increment = true;
+ }
+ const newPos = this._getNewResizerPosition(event.target.offsetLeft, increment, event.ctrlKey);
+ if (moveRightResizer) {
+ this._resizeWindowRight(newPos);
+ } else {
+ this._resizeWindowLeft(newPos);
+ }
+ event.consume(true);
+ }
+ }
+
+ /**
+ * @param {number} offset
+ * @param {boolean=} increment
+ * @param {boolean=} ctrlPressed
+ * @return {number}
+ */
+ _getNewResizerPosition(offset, increment, ctrlPressed) {
+ let newPos;
+ // We shift by 10px if the ctrlKey is pressed and 2 otherwise. 1px shifts result in noOp due to rounding in _updateCurtains
+ let pixelsToShift = ctrlPressed ? 10 : 2;
+ pixelsToShift = increment ? pixelsToShift : -Math.abs(pixelsToShift);
+ const offsetLeft = offset + PerfUI.OverviewGrid.ResizerOffset;
+ newPos = offsetLeft + pixelsToShift;
+ if (increment && newPos < PerfUI.OverviewGrid.OffsetFromWindowEnds) {
+ // When incrementing, snap to the window offset value (10px) if the new position is between 0px and 10px
+ newPos = PerfUI.OverviewGrid.OffsetFromWindowEnds;
+ } else if (!increment && newPos > this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds) {
+ // When decrementing, snap to the window offset value (10px) from the rightmost side if the new position is within 10px from the end.
+ newPos = this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds;
+ }
+
+ return newPos;
+ }
+
+ /**
+ * @param {!Event} event
* @return {boolean}
*/
_startWindowSelectorDragging(event) {
- if (!this._enabled)
+ if (!this._enabled) {
return false;
+ }
this._offsetLeft = this._parentElement.totalOffsetLeft();
const position = event.x - this._offsetLeft;
this._overviewWindowSelector = new PerfUI.OverviewGrid.WindowSelector(this._parentElement, position);
@@ -254,16 +314,18 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
delete this._overviewWindowSelector;
const clickThreshold = 3;
if (window.end - window.start < clickThreshold) {
- if (this._clickHandler && this._clickHandler.call(null, event))
+ if (this._clickHandler && this._clickHandler.call(null, event)) {
return;
+ }
const middle = window.end;
window.start = Math.max(0, middle - PerfUI.OverviewGrid.MinSelectableSize / 2);
window.end = Math.min(this._parentElement.clientWidth, middle + PerfUI.OverviewGrid.MinSelectableSize / 2);
} else if (window.end - window.start < PerfUI.OverviewGrid.MinSelectableSize) {
- if (this._parentElement.clientWidth - window.end > PerfUI.OverviewGrid.MinSelectableSize)
+ if (this._parentElement.clientWidth - window.end > PerfUI.OverviewGrid.MinSelectableSize) {
window.end = window.start + PerfUI.OverviewGrid.MinSelectableSize;
- else
+ } else {
window.start = window.end - PerfUI.OverviewGrid.MinSelectableSize;
+ }
}
this._setWindowPosition(window.start, window.end);
}
@@ -286,11 +348,13 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
_windowDragging(event) {
event.preventDefault();
let delta = (event.pageX - this._dragStartPoint) / this._parentElement.clientWidth;
- if (this._dragStartLeft + delta < 0)
+ if (this._dragStartLeft + delta < 0) {
delta = -this._dragStartLeft;
+ }
- if (this._dragStartRight + delta > 1)
+ if (this._dragStartRight + delta > 1) {
delta = 1 - this._dragStartRight;
+ }
this._setWindow(this._dragStartLeft + delta, this._dragStartRight + delta);
}
@@ -300,10 +364,11 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
*/
_resizeWindowLeft(start) {
// Glue to edge.
- if (start < 10)
+ if (start < PerfUI.OverviewGrid.OffsetFromWindowEnds) {
start = 0;
- else if (start > this._rightResizeElement.offsetLeft - 4)
+ } else if (start > this._rightResizeElement.offsetLeft - 4) {
start = this._rightResizeElement.offsetLeft - 4;
+ }
this._setWindowPosition(start, null);
}
@@ -312,10 +377,11 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
*/
_resizeWindowRight(end) {
// Glue to edge.
- if (end > this._parentElement.clientWidth - 10)
+ if (end > this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds) {
end = this._parentElement.clientWidth;
- else if (end < this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.MinSelectableSize)
+ } else if (end < this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.MinSelectableSize) {
end = this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.MinSelectableSize;
+ }
this._setWindowPosition(null, end);
}
@@ -339,13 +405,16 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
let right = this.windowRight;
const width = right - left;
- // We allow actual time window to be arbitrarily small but don't want the UI window to be too small.
- const widthInPixels = width * this._parentElement.clientWidth;
- const minWidthInPixels = PerfUI.OverviewGrid.MinSelectableSize / 2;
- if (widthInPixels < minWidthInPixels) {
- const factor = minWidthInPixels / widthInPixels;
- left = ((this.windowRight + this.windowLeft) - width * factor) / 2;
- right = ((this.windowRight + this.windowLeft) + width * factor) / 2;
+ // OverviewGrids that are instantiated before the parentElement is shown will have a parent element client width of 0 which throws off the 'factor' calculation
+ if (this._parentElement.clientWidth !== 0) {
+ // We allow actual time window to be arbitrarily small but don't want the UI window to be too small.
+ const widthInPixels = width * this._parentElement.clientWidth;
+ const minWidthInPixels = PerfUI.OverviewGrid.MinSelectableSize / 2;
+ if (widthInPixels < minWidthInPixels) {
+ const factor = minWidthInPixels / widthInPixels;
+ left = ((this.windowRight + this.windowLeft) - width * factor) / 2;
+ right = ((this.windowRight + this.windowLeft) + width * factor) / 2;
+ }
}
this._leftResizeElement.style.left = (100 * left).toFixed(2) + '%';
this._rightResizeElement.style.left = (100 * right).toFixed(2) + '%';
@@ -369,8 +438,9 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
* @param {!Event} event
*/
_onMouseWheel(event) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
if (typeof event.wheelDeltaY === 'number' && event.wheelDeltaY) {
const zoomFactor = 1.1;
const mouseWheelZoomSpeed = 1 / 120;
@@ -383,11 +453,13 @@ PerfUI.OverviewGrid.Window = class extends Common.Object {
const windowLeft = this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.ResizerOffset;
const windowRight = this._rightResizeElement.offsetLeft + PerfUI.OverviewGrid.ResizerOffset;
- if (windowLeft - offset < 0)
+ if (windowLeft - offset < 0) {
offset = windowLeft;
+ }
- if (windowRight - offset > this._parentElement.clientWidth)
+ if (windowRight - offset > this._parentElement.clientWidth) {
offset = windowRight - this._parentElement.clientWidth;
+ }
this._setWindowPosition(windowLeft - offset, windowRight - offset);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/PieChart.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/PieChart.js
index b629b2d164d..ad1a9b215e5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/PieChart.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/PieChart.js
@@ -65,8 +65,9 @@ PerfUI.PieChart = class {
this._formatter = formatter;
this._slices = [];
this._lastAngle = -Math.PI / 2;
- if (showLegend)
+ if (showLegend) {
this._legend = root.createChild('div', 'pie-chart-legend');
+ }
this._setSize(size);
}
@@ -74,16 +75,18 @@ PerfUI.PieChart = class {
* @param {number} totalValue
*/
setTotal(totalValue) {
- for (let i = 0; i < this._slices.length; ++i)
+ for (let i = 0; i < this._slices.length; ++i) {
this._slices[i].remove();
+ }
this._slices = [];
this._totalValue = totalValue;
this._lastAngle = -Math.PI / 2;
let totalString;
- if (totalValue)
+ if (totalValue) {
totalString = this._formatter ? this._formatter(totalValue) : totalValue;
- else
+ } else {
totalString = '';
+ }
this._totalElement.textContent = totalString;
if (this._legend) {
this._legend.removeChildren();
@@ -108,8 +111,9 @@ PerfUI.PieChart = class {
*/
addSlice(value, color, name) {
let sliceAngle = value / this._totalValue * 2 * Math.PI;
- if (!isFinite(sliceAngle))
+ if (!isFinite(sliceAngle)) {
return;
+ }
sliceAngle = Math.min(sliceAngle, 2 * Math.PI * 0.9999);
const path = this._createSVGChild(this._group, 'path');
const x1 = Math.cos(this._lastAngle);
@@ -127,8 +131,9 @@ PerfUI.PieChart = class {
`M${x1},${y1} A1,1,0,${largeArc},1,${x2},${y2} L${x3},${y3} A${r2},${r2},0,${largeArc},0,${x4},${y4} Z`);
path.setAttribute('fill', color);
this._slices.push(path);
- if (this._legend)
+ if (this._legend) {
this._addLegendItem(path, value, name, color);
+ }
}
/**
@@ -153,17 +158,19 @@ PerfUI.PieChart = class {
const node = this._legend.ownerDocument.createElement('div');
node.className = 'pie-chart-legend-row';
// make sure total always appears at the bottom
- if (this._legend.childElementCount)
+ if (this._legend.childElementCount) {
this._legend.insertBefore(node, this._legend.lastElementChild);
- else
+ } else {
this._legend.appendChild(node);
+ }
const sizeDiv = node.createChild('div', 'pie-chart-size');
const swatchDiv = node.createChild('div', 'pie-chart-swatch');
const nameDiv = node.createChild('div', 'pie-chart-name');
- if (color)
+ if (color) {
swatchDiv.style.backgroundColor = color;
- else
+ } else {
swatchDiv.classList.add('pie-chart-empty-swatch');
+ }
nameDiv.textContent = name;
const size = this._formatter ? this._formatter(value) : value;
sizeDiv.textContent = size;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineGrid.js
index af644ce0a23..113e9e0108c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineGrid.js
@@ -65,10 +65,12 @@ PerfUI.TimelineGrid = class {
const logGridSliceTime = Math.ceil(Math.log(gridSliceTime) / Math.LN10);
gridSliceTime = Math.pow(10, logGridSliceTime);
- if (gridSliceTime * pixelsPerTime >= 5 * minGridSlicePx)
+ if (gridSliceTime * pixelsPerTime >= 5 * minGridSlicePx) {
gridSliceTime = gridSliceTime / 5;
- if (gridSliceTime * pixelsPerTime >= 2 * minGridSlicePx)
+ }
+ if (gridSliceTime * pixelsPerTime >= 2 * minGridSlicePx) {
gridSliceTime = gridSliceTime / 2;
+ }
const firstDividerTime =
Math.ceil((calculator.minimumBoundary() - calculator.zeroTime()) / gridSliceTime) * gridSliceTime +
@@ -79,14 +81,16 @@ PerfUI.TimelineGrid = class {
lastDividerTime += minGridSlicePx / pixelsPerTime;
dividersCount = Math.ceil((lastDividerTime - firstDividerTime) / gridSliceTime);
- if (!gridSliceTime)
+ if (!gridSliceTime) {
dividersCount = 0;
+ }
const offsets = [];
for (let i = 0; i < dividersCount; ++i) {
const time = firstDividerTime + gridSliceTime * i;
- if (calculator.computePosition(time) < freeZoneAtLeft)
+ if (calculator.computePosition(time) < freeZoneAtLeft) {
continue;
+ }
offsets.push({position: Math.floor(calculator.computePosition(time)), time: time});
}
@@ -141,8 +145,9 @@ PerfUI.TimelineGrid = class {
const text = formatTimeFunction(offsetInfo.time);
const textWidth = context.measureText(text).width;
const textPosition = offsetInfo.position - textWidth - paddingRight;
- if (!freeZoneAtLeft || freeZoneAtLeft < textPosition)
+ if (!freeZoneAtLeft || freeZoneAtLeft < textPosition) {
context.fillText(text, textPosition, paddingTop);
+ }
}
context.restore();
}
@@ -229,8 +234,9 @@ PerfUI.TimelineGrid = class {
*/
addEventDividers(dividers) {
this._gridHeaderElement.removeChild(this._eventDividersElement);
- for (const divider of dividers)
+ for (const divider of dividers) {
this._eventDividersElement.appendChild(divider);
+ }
this._gridHeaderElement.appendChild(this._eventDividersElement);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineOverviewPane.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineOverviewPane.js
index a7325bf4355..397e4d5a1ef 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineOverviewPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/TimelineOverviewPane.js
@@ -65,8 +65,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
* @param {!Event} event
*/
_onMouseMove(event) {
- if (!this._cursorEnabled)
+ if (!this._cursorEnabled) {
return;
+ }
this._cursorPosition = event.offsetX + event.target.offsetLeft;
this._cursorElement.style.left = this._cursorPosition + 'px';
this._cursorElement.style.visibility = 'visible';
@@ -110,8 +111,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
*/
onResize() {
const width = this.element.offsetWidth;
- if (width === this._lastWidth)
+ if (width === this._lastWidth) {
return;
+ }
this._lastWidth = width;
this.scheduleUpdate();
}
@@ -120,8 +122,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
* @param {!Array.<!PerfUI.TimelineOverview>} overviewControls
*/
setOverviewControls(overviewControls) {
- for (let i = 0; i < this._overviewControls.length; ++i)
+ for (let i = 0; i < this._overviewControls.length; ++i) {
this._overviewControls[i].dispose();
+ }
for (let i = 0; i < overviewControls.length; ++i) {
overviewControls[i].setCalculator(this._overviewCalculator);
@@ -154,11 +157,13 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
}
_update() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
this._overviewCalculator.setDisplayWidth(this._overviewGrid.clientWidth());
- for (let i = 0; i < this._overviewControls.length; ++i)
+ for (let i = 0; i < this._overviewControls.length; ++i) {
this._overviewControls[i].update();
+ }
this._overviewGrid.updateDividers(this._overviewCalculator);
this._updateMarkers();
this._updateWindow();
@@ -177,8 +182,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
const marker = this._markers.get(time);
const position = Math.round(this._overviewCalculator.computePosition(time));
// Limit the number of markers to one per pixel.
- if (filteredMarkers.has(position))
+ if (filteredMarkers.has(position)) {
continue;
+ }
filteredMarkers.set(position, marker);
marker.style.left = position + 'px';
}
@@ -195,8 +201,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
this._cursorEnabled = false;
this._hideCursor();
this._markers = new Map();
- for (const control of this._overviewControls)
+ for (const control of this._overviewControls) {
control.reset();
+ }
this._overviewInfo.hide();
this.scheduleUpdate();
}
@@ -213,11 +220,13 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
* @param {!Common.Event} event
*/
_onWindowChanged(event) {
- if (this._muteOnWindowChanged)
+ if (this._muteOnWindowChanged) {
return;
+ }
// Always use first control as a time converter.
- if (!this._overviewControls.length)
+ if (!this._overviewControls.length) {
return;
+ }
const absoluteMin = this._overviewCalculator.minimumBoundary();
const timeSpan = this._overviewCalculator.maximumBoundary() - absoluteMin;
@@ -235,8 +244,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
* @param {number} endTime
*/
setWindowTimes(startTime, endTime) {
- if (startTime === this._windowStartTime && endTime === this._windowEndTime)
+ if (startTime === this._windowStartTime && endTime === this._windowEndTime) {
return;
+ }
this._windowStartTime = startTime;
this._windowEndTime = endTime;
this._updateWindow();
@@ -245,8 +255,9 @@ PerfUI.TimelineOverviewPane = class extends UI.VBox {
}
_updateWindow() {
- if (!this._overviewControls.length)
+ if (!this._overviewControls.length) {
return;
+ }
const absoluteMin = this._overviewCalculator.minimumBoundary();
const timeSpan = this._overviewCalculator.maximumBoundary() - absoluteMin;
const haveRecords = absoluteMin > 0;
@@ -466,8 +477,9 @@ PerfUI.TimelineOverviewBase = class extends UI.VBox {
}
resetCanvas() {
- if (this.element.clientWidth)
+ if (this.element.clientWidth) {
this.setCanvasSize(this.element.clientWidth, this.element.clientHeight);
+ }
}
/**
@@ -502,13 +514,15 @@ PerfUI.TimelineOverviewPane.OverviewInfo = class {
async setContent(contentPromise) {
this._visible = true;
const content = await contentPromise;
- if (!this._visible)
+ if (!this._visible) {
return;
+ }
this._element.removeChildren();
this._element.appendChild(content);
this._glassPane.setContentAnchorBox(this._anchorElement.boxInWindow());
- if (!this._glassPane.isShowing())
+ if (!this._glassPane.isShowing()) {
this._glassPane.show(/** @type {!Document} */ (this._anchorElement.ownerDocument));
+ }
}
hide() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/flameChart.css b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/flameChart.css
index d4dfb43f50d..4d9c03a2d4d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/flameChart.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/flameChart.css
@@ -36,6 +36,10 @@
background-color: rgba(56, 121, 217, 0.1);
}
+.flame-chart-unfocused-selected-element {
+ outline: 2px solid rgba(123, 123, 123, 1);
+}
+
.chart-cursor-element {
position: absolute;
top: 0;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
index fd09baf5b6d..3cb840cd65f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
@@ -24,6 +24,10 @@
z-index: 500;
}
+.overview-grid-window-resizer[data-keyboard-focus="true"]:focus {
+ background-color: var(--active-control-bg-color);
+}
+
.overview-grid-cursor-area {
position: absolute;
left: 0;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
index 7d323e6ce2e..7c20973ded1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/perf_ui_strings.grdp
@@ -3,9 +3,6 @@
<message name="IDS_DEVTOOLS_05dedc41542c728955023577fd58be7a" desc="Text for screen reader to announce a collapsed group">
<ph name="GROUPNAME">$1s<ex>Network</ex></ph> collapsed
</message>
- <message name="IDS_DEVTOOLS_105078d294d30c978ca2badf7f376934" desc="Title of a setting under the Performance category that can be invoked through the Command Menu">
- Scroll
- </message>
<message name="IDS_DEVTOOLS_28d0edd045e05cf5af64e35ae0c4c6ef" desc="Text in Network Priorities of the Performance panel">
Low
</message>
@@ -18,9 +15,6 @@
<message name="IDS_DEVTOOLS_3f21c340f01b96cb3325a5d38ece9da6" desc="Title of a setting under the Memory category in Settings">
Live memory allocation annotations
</message>
- <message name="IDS_DEVTOOLS_4789f23283b3a61f858b641a1bef19a3" desc="A title of the 'Memory' setting category">
- Memory
- </message>
<message name="IDS_DEVTOOLS_4a6d0345e7b6cfcf339237b9cf2d27b4" desc="Title of a setting under the Performance category in Settings">
Flamechart mouse wheel action:
</message>
@@ -54,9 +48,6 @@
<message name="IDS_DEVTOOLS_90c96ccfe47a731972d5e64deb5fea36" desc="Title of a setting under the Memory category that can be invoked through the Command Menu">
Hide live memory allocation annotations
</message>
- <message name="IDS_DEVTOOLS_ab57fd0432e25d5b3013133a1c910d56" desc="Units in Line Level Profile of the Performance panel">
- KB
- </message>
<message name="IDS_DEVTOOLS_b5b8e20937205384be7b9e0c29a28fdb" desc="Text in Network Priorities of the Performance panel">
Lowest
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js b/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js
index 500e1891ffe..735e855d5cc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/PerformanceMonitor.js
@@ -39,8 +39,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
* @override
*/
wasShown() {
- if (!this._model)
+ if (!this._model) {
return;
+ }
SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
this._model.enable();
this._suspendStateChanged();
@@ -50,8 +51,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
* @override
*/
willHide() {
- if (!this._model)
+ if (!this._model) {
return;
+ }
SDK.targetManager.removeEventListener(
SDK.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this);
this._stopPolling();
@@ -63,11 +65,13 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
* @param {!SDK.PerformanceMetricsModel} model
*/
modelAdded(model) {
- if (this._model)
+ if (this._model) {
return;
+ }
this._model = model;
- if (this.isShowing())
+ if (this.isShowing()) {
this.wasShown();
+ }
}
/**
@@ -75,19 +79,22 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
* @param {!SDK.PerformanceMetricsModel} model
*/
modelRemoved(model) {
- if (this._model !== model)
+ if (this._model !== model) {
return;
- if (this.isShowing())
+ }
+ if (this.isShowing()) {
this.willHide();
+ }
this._model = null;
}
_suspendStateChanged() {
const suspended = SDK.targetManager.allTargetsSuspended();
- if (suspended)
+ if (suspended) {
this._stopPolling();
- else
+ } else {
this._startPolling();
+ }
this.contentElement.classList.toggle('suspended', suspended);
}
@@ -121,7 +128,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
// Multiply by 2 as the pollInterval has some jitter and to have some extra samples if window is resized.
const maxCount = Math.ceil(millisPerWidth / this._pollIntervalMs * 2);
if (this._metricsBuffer.length > maxCount * 2) // Multiply by 2 to have a hysteresis.
+ {
this._metricsBuffer.splice(0, this._metricsBuffer.length - maxCount);
+ }
this._controlPane.updateMetrics(metrics);
}
@@ -133,8 +142,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
ctx.save();
ctx.translate(0, this._scaleHeight); // Reserve space for the scale bar.
for (const chartInfo of this._controlPane.charts()) {
- if (!this._controlPane.isActive(chartInfo.metrics[0].name))
+ if (!this._controlPane.isActive(chartInfo.metrics[0].name)) {
continue;
+ }
this._drawChart(ctx, chartInfo, this._graphHeight);
ctx.translate(0, this._graphHeight);
}
@@ -154,13 +164,15 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
const currentTime = Date.now() / 1000;
for (let sec = Math.ceil(currentTime);; --sec) {
const x = this._width - ((currentTime - sec) * 1000 - this._pollIntervalMs) * this._pixelsPerMs;
- if (x < -50)
+ if (x < -50) {
break;
+ }
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, this._height);
- if (sec >= 0 && sec % labelDistanceSeconds === 0)
+ if (sec >= 0 && sec % labelDistanceSeconds === 0) {
ctx.fillText(new Date(sec * 1000).toLocaleTimeString(), x + 4, 12);
+ }
ctx.strokeStyle = sec % labelDistanceSeconds ? lightGray : this._gridColor;
ctx.stroke();
}
@@ -212,8 +224,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
* @return {number}
*/
_calcMax(chartInfo) {
- if (chartInfo.max)
+ if (chartInfo.max) {
return chartInfo.max;
+ }
const width = this._width;
const startTime = performance.now() - this._pollIntervalMs - width / this._pixelsPerMs;
let max = -Infinity;
@@ -222,12 +235,14 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
const metrics = this._metricsBuffer[i];
const value = metrics.metrics.get(metricInfo.name);
max = Math.max(max, value);
- if (metrics.timestamp < startTime)
+ if (metrics.timestamp < startTime) {
break;
+ }
}
}
- if (!this._metricsBuffer.length)
+ if (!this._metricsBuffer.length) {
return 10;
+ }
const base10 = Math.pow(10, Math.floor(Math.log10(max)));
max = Math.ceil(max / base10 / 2) * base10 * 2;
@@ -246,8 +261,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
_drawVerticalGrid(ctx, height, max, info) {
let base = Math.pow(10, Math.floor(Math.log10(max)));
const firstDigit = Math.floor(max / base);
- if (firstDigit !== 1 && firstDigit % 2 === 1)
+ if (firstDigit !== 1 && firstDigit % 2 === 1) {
base *= 2;
+ }
let scaleValue = Math.floor(max / base) * base;
const span = max;
@@ -293,8 +309,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
const path = new Path2D();
const topPadding = 18;
const visibleHeight = height - topPadding;
- if (visibleHeight < 1)
+ if (visibleHeight < 1) {
return path;
+ }
const span = scaleMax;
const metricName = metricInfo.name;
const pixelsPerMs = this._pixelsPerMs;
@@ -332,8 +349,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
}
lastX = x;
lastY = y;
- if (timestamp < startTime)
+ if (timestamp < startTime) {
break;
+ }
}
return path;
@@ -359,8 +377,9 @@ PerformanceMonitor.PerformanceMonitor = class extends UI.HBox {
_recalcChartHeight() {
let height = this._scaleHeight;
for (const chartInfo of this._controlPane.charts()) {
- if (this._controlPane.isActive(chartInfo.metrics[0].name))
+ if (this._controlPane.isActive(chartInfo.metrics[0].name)) {
height += this._graphHeight;
+ }
}
this._height = Math.ceil(height * window.devicePixelRatio);
this._canvas.height = this._height;
@@ -436,8 +455,9 @@ PerformanceMonitor.PerformanceMonitor.ControlPane = class extends Common.Object
{title: Common.UIString('Style recalcs / sec'), metrics: [{name: 'RecalcStyleCount', color: 'deeppink'}]}
];
for (const info of this._chartsInfo) {
- for (const metric of info.metrics)
+ for (const metric of info.metrics) {
metric.color = UI.themeSupport.patchColorText(metric.color, UI.ThemeSupport.ColorUsage.Foreground);
+ }
}
/** @type {!Map<string, !PerformanceMonitor.PerformanceMonitor.MetricIndicator>} */
@@ -456,10 +476,11 @@ PerformanceMonitor.PerformanceMonitor.ControlPane = class extends Common.Object
* @param {boolean} active
*/
_onToggle(chartName, active) {
- if (active)
+ if (active) {
this._enabledCharts.add(chartName);
- else
+ } else {
this._enabledCharts.delete(chartName);
+ }
this._enabledChartsSetting.set(Array.from(this._enabledCharts));
this.dispatchEventToListeners(PerformanceMonitor.PerformanceMonitor.ControlPane.Events.MetricChanged);
}
@@ -484,8 +505,9 @@ PerformanceMonitor.PerformanceMonitor.ControlPane = class extends Common.Object
*/
updateMetrics(metrics) {
for (const name of this._indicators.keys()) {
- if (metrics.has(name))
+ if (metrics.has(name)) {
this._indicators.get(name).setValue(metrics.get(name));
+ }
}
}
};
@@ -564,8 +586,9 @@ PerformanceMonitor.PerformanceMonitor.MetricIndicator = class {
*/
_handleKeypress(event) {
const keyboardEvent = /** @type {!KeyboardEvent} */ (event);
- if (keyboardEvent.key === ' ' || keyboardEvent.key === 'Enter')
+ if (keyboardEvent.key === ' ' || keyboardEvent.key === 'Enter') {
this._toggleIndicator();
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
index f3773625e26..3cdedec3098 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/performance_monitor/performance_monitor_strings.grdp
@@ -3,6 +3,9 @@
<message name="IDS_DEVTOOLS_029ce83ef9e87df61fb9e580ac165b4a" desc="Text in Performance Monitor of the Performance monitor tab">
DOM Nodes
</message>
+ <message name="IDS_DEVTOOLS_08b5411f848a2581a41672a759c87380" desc="A tag of Performance Monitor that can be searched in the command menu">
+ monitor
+ </message>
<message name="IDS_DEVTOOLS_23ab71fd0704d52052b95e54f8e72fb9" desc="Title of the 'Performance monitor' tool in the bottom drawer">
Performance monitor
</message>
@@ -12,25 +15,34 @@
<message name="IDS_DEVTOOLS_5c1131c8862a07ce54be057f516c840e" desc="Text in Performance Monitor of the Performance monitor tab">
Layouts / sec
</message>
+ <message name="IDS_DEVTOOLS_69a256025f66e4ce5d15c9dd7225d357" desc="A tag of Performance Monitor that can be searched in the command menu">
+ activity
+ </message>
<message name="IDS_DEVTOOLS_6cce53fb6e5ccd4313ae3ec26fa42ca4" desc="Text in Performance Monitor of the Performance monitor tab">
JS event listeners
</message>
+ <message name="IDS_DEVTOOLS_7458af250519159f714c701acf91b317" desc="A tag of Performance Monitor that can be searched in the command menu">
+ system monitor
+ </message>
<message name="IDS_DEVTOOLS_81f2166e08f25234e2fbb2cd3175f83e" desc="Aria accessible name in Performance Monitor of the Performance monitor tab">
Graphs displaying a real-time view of performance metrics
</message>
<message name="IDS_DEVTOOLS_9ff3fcf082193aaf2b6889fb4662706a" desc="Text in Performance Monitor of the Performance monitor tab">
JS heap size
</message>
+ <message name="IDS_DEVTOOLS_aa59d67c2123f094d0d6798ffe651c4d" desc="A tag of Performance Monitor that can be searched in the command menu">
+ metrics
+ </message>
<message name="IDS_DEVTOOLS_ac2137ec7c503f6997ddb414265791a9" desc="Text in Performance Monitor of the Performance monitor tab">
CPU usage
</message>
<message name="IDS_DEVTOOLS_b4cb01a2ff8576df8cbad0872cc6e4a2" desc="Text in Performance Monitor of the Performance monitor tab">
Style recalcs / sec
</message>
+ <message name="IDS_DEVTOOLS_c05f6c233521207f6fe311afef550c3c" desc="A tag of Performance Monitor that can be searched in the command menu">
+ performance
+ </message>
<message name="IDS_DEVTOOLS_e99180abf47a8b3a856e0bcb2656990a" desc="Text in Performance Monitor of the Performance monitor tab">
Paused
</message>
- <message name="IDS_DEVTOOLS_f28128b38efbc6134dc40751ee21fd29" desc="Text in Performance Monitor of the Performance monitor tab">
- Documents
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js
index 1a96801f36c..ba228f10df7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js
@@ -57,8 +57,9 @@ PerformanceTestRunner.InvalidationFormatters = {
};
TestRunner.formatters.formatAsInvalidationCause = function(cause) {
- if (!cause)
+ if (!cause) {
return '<undefined>';
+ }
let stackTrace;
@@ -85,8 +86,9 @@ PerformanceTestRunner.invokeWithTracing = function(functionName, callback, addit
let categories = '-*,disabled-by-default-devtools.timeline*,devtools.timeline,blink.user_timing,' +
SDK.TracingModel.LegacyTopLevelEventCategory;
- if (additionalCategories)
+ if (additionalCategories) {
categories += ',' + additionalCategories;
+ }
const timelinePanel = UI.panels.timeline;
const timelineController = PerformanceTestRunner.createTimelineController();
@@ -174,15 +176,17 @@ PerformanceTestRunner.performActionsAndPrint = async function(actions, typeName,
PerformanceTestRunner.printTimelineRecords = function(name) {
for (const event of PerformanceTestRunner.timelineModel().inspectedTargetEvents()) {
- if (event.name === name)
+ if (event.name === name) {
PerformanceTestRunner.printTraceEventProperties(event);
+ }
}
};
PerformanceTestRunner.printTimelineRecordsWithDetails = function(name) {
for (const event of PerformanceTestRunner.timelineModel().inspectedTargetEvents()) {
- if (name === event.name)
+ if (name === event.name) {
PerformanceTestRunner.printTraceEventPropertiesWithDetails(event);
+ }
}
};
@@ -199,19 +203,22 @@ PerformanceTestRunner.walkTimelineEventTree = function(callback) {
PerformanceTestRunner.walkTimelineEventTreeUnderNode = function(callback, root, level) {
const event = root.event;
- if (event)
+ if (event) {
callback(event, level, root);
+ }
- for (const child of root.children().values())
+ for (const child of root.children().values()) {
PerformanceTestRunner.walkTimelineEventTreeUnderNode(callback, child, (level || 0) + 1);
+ }
};
PerformanceTestRunner.printTimestampRecords = function(typeName) {
const dividers = PerformanceTestRunner.timelineModel().timeMarkerEvents();
for (const event of dividers) {
- if (event.name === typeName)
+ if (event.name === typeName) {
PerformanceTestRunner.printTraceEventProperties(event);
+ }
}
};
@@ -219,13 +226,15 @@ PerformanceTestRunner.forAllEvents = function(events, callback) {
const eventStack = [];
for (const event of events) {
- while (eventStack.length && eventStack.peekLast().endTime <= event.startTime)
+ while (eventStack.length && eventStack.peekLast().endTime <= event.startTime) {
eventStack.pop();
+ }
callback(event, eventStack);
- if (event.endTime)
+ if (event.endTime) {
eventStack.push(event);
+ }
}
};
@@ -244,8 +253,9 @@ PerformanceTestRunner.printTraceEventProperties = function(traceEvent) {
};
for (const field in object) {
- if (object[field] === null || object[field] === undefined)
+ if (object[field] === null || object[field] === undefined) {
delete object[field];
+ }
}
TestRunner.addObject(object, PerformanceTestRunner.timelinePropertyFormatters);
@@ -257,15 +267,17 @@ PerformanceTestRunner.printTraceEventPropertiesWithDetails = function(event) {
event, SDK.targetManager.mainTarget(), new Components.Linkifier());
TestRunner.addResult(`Text details for ${event.name}: ${details}`);
- if (TimelineModel.TimelineData.forEvent(event).warning)
+ if (TimelineModel.TimelineData.forEvent(event).warning) {
TestRunner.addResult(`${event.name} has a warning`);
+ }
};
PerformanceTestRunner.mainTrack = function() {
let mainTrack;
for (const track of PerformanceTestRunner.timelineModel().tracks()) {
- if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame)
+ if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame) {
mainTrack = track;
+ }
}
return mainTrack;
};
@@ -282,8 +294,9 @@ PerformanceTestRunner.findChildEvent = function(events, parentIndex, name) {
const endTime = events[parentIndex].endTime;
for (let i = parentIndex + 1; i < events.length && (!events[i].endTime || events[i].endTime <= endTime); ++i) {
- if (events[i].name === name)
+ if (events[i].name === name) {
return events[i];
+ }
}
return null;
@@ -299,15 +312,17 @@ PerformanceTestRunner.dumpFrame = function(frame) {
const result = {};
for (const key in object) {
- if (fieldsToDump.indexOf(key) < 0)
+ if (fieldsToDump.indexOf(key) < 0) {
continue;
+ }
let value = object[key];
- if (typeof value === 'number')
+ if (typeof value === 'number') {
value = Number(value.toFixed(7));
- else if (typeof value === 'object' && value)
+ } else if (typeof value === 'object' && value) {
value = formatFields(value);
+ }
result[key] = value;
}
@@ -330,16 +345,18 @@ PerformanceTestRunner.dumpFlameChartProvider = function(provider, includeGroups)
const includeGroupsSet = includeGroups && new Set(includeGroups);
const timelineData = provider.timelineData();
const stackDepth = provider.maxStackDepth();
- const entriesByLevel = new Multimap();
+ const entriesByLevel = new Platform.Multimap();
- for (let i = 0; i < timelineData.entryLevels.length; ++i)
+ for (let i = 0; i < timelineData.entryLevels.length; ++i) {
entriesByLevel.set(timelineData.entryLevels[i], i);
+ }
for (let groupIndex = 0; groupIndex < timelineData.groups.length; ++groupIndex) {
const group = timelineData.groups[groupIndex];
- if (includeGroupsSet && !includeGroupsSet.has(group.name))
+ if (includeGroupsSet && !includeGroupsSet.has(group.name)) {
continue;
+ }
const maxLevel =
(groupIndex + 1 < timelineData.groups.length ? timelineData.groups[groupIndex + 1].startLevel : stackDepth);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/Automapping.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/Automapping.js
index 058f00c7b0f..88fa2930870 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/Automapping.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/Automapping.js
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.Automapping = class {
+export default class Automapping {
/**
* @param {!Workspace.Workspace} workspace
- * @param {function(!Persistence.AutomappingStatus)} onStatusAdded
- * @param {function(!Persistence.AutomappingStatus)} onStatusRemoved
+ * @param {function(!AutomappingStatus)} onStatusAdded
+ * @param {function(!AutomappingStatus)} onStatusRemoved
*/
constructor(workspace, onStatusAdded, onStatusRemoved) {
this._workspace = workspace;
this._onStatusAdded = onStatusAdded;
this._onStatusRemoved = onStatusRemoved;
- /** @type {!Set<!Persistence.AutomappingStatus>} */
+ /** @type {!Set<!AutomappingStatus>} */
this._statuses = new Set();
this._statusSymbol = Symbol('Automapping.Status');
this._processingPromiseSymbol = Symbol('Automapping.ProcessingPromise');
@@ -25,9 +25,9 @@ Persistence.Automapping = class {
this._sweepThrottler = new Common.Throttler(100);
const pathEncoder = new Persistence.PathEncoder();
- this._filesIndex = new Persistence.Automapping.FilePathIndex(pathEncoder);
- this._projectFoldersIndex = new Persistence.Automapping.FolderIndex(pathEncoder);
- this._activeFoldersIndex = new Persistence.Automapping.FolderIndex(pathEncoder);
+ this._filesIndex = new FilePathIndex(pathEncoder);
+ this._projectFoldersIndex = new FolderIndex(pathEncoder);
+ this._activeFoldersIndex = new FolderIndex(pathEncoder);
/** @type {!Array<function(!Workspace.UISourceCode):boolean>} */
this._interceptors = [];
@@ -46,10 +46,12 @@ Persistence.Automapping = class {
Workspace.Workspace.Events.ProjectRemoved,
event => this._onProjectRemoved(/** @type {!Workspace.Project} */ (event.data)), this);
- for (const fileSystem of workspace.projects())
+ for (const fileSystem of workspace.projects()) {
this._onProjectAdded(fileSystem);
- for (const uiSourceCode of workspace.uiSourceCodes())
+ }
+ for (const uiSourceCode of workspace.uiSourceCodes()) {
this._onUISourceCodeAdded(uiSourceCode);
+ }
}
/**
@@ -61,8 +63,9 @@ Persistence.Automapping = class {
}
scheduleRemap() {
- for (const status of this._statuses.valuesArray())
+ for (const status of this._statuses.valuesArray()) {
this._clearNetworkStatus(status.network);
+ }
this._scheduleSweep();
}
@@ -70,14 +73,15 @@ Persistence.Automapping = class {
this._sweepThrottler.schedule(sweepUnmapped.bind(this));
/**
- * @this {Persistence.Automapping}
+ * @this {Automapping}
* @return {!Promise}
*/
function sweepUnmapped() {
const networkProjects = this._workspace.projectsForType(Workspace.projectTypes.Network);
for (const networkProject of networkProjects) {
- for (const uiSourceCode of networkProject.uiSourceCodes())
+ for (const uiSourceCode of networkProject.uiSourceCodes()) {
this._computeNetworkStatus(uiSourceCode);
+ }
}
this._onSweepHappenedForTest();
return Promise.resolve();
@@ -91,13 +95,16 @@ Persistence.Automapping = class {
* @param {!Workspace.Project} project
*/
_onProjectRemoved(project) {
- for (const uiSourceCode of project.uiSourceCodes())
+ for (const uiSourceCode of project.uiSourceCodes()) {
this._onUISourceCodeRemoved(uiSourceCode);
- if (project.type() !== Workspace.projectTypes.FileSystem)
+ }
+ if (project.type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
const fileSystem = /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (project);
- for (const gitFolder of fileSystem.initialGitFolders())
+ for (const gitFolder of fileSystem.initialGitFolders()) {
this._projectFoldersIndex.removeFolder(gitFolder);
+ }
this._projectFoldersIndex.removeFolder(fileSystem.fileSystemPath());
this.scheduleRemap();
}
@@ -106,11 +113,13 @@ Persistence.Automapping = class {
* @param {!Workspace.Project} project
*/
_onProjectAdded(project) {
- if (project.type() !== Workspace.projectTypes.FileSystem)
+ if (project.type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
const fileSystem = /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (project);
- for (const gitFolder of fileSystem.initialGitFolders())
+ for (const gitFolder of fileSystem.initialGitFolders()) {
this._projectFoldersIndex.addFolder(gitFolder);
+ }
this._projectFoldersIndex.addFolder(fileSystem.fileSystemPath());
project.uiSourceCodes().forEach(this._onUISourceCodeAdded.bind(this));
this.scheduleRemap();
@@ -122,8 +131,9 @@ Persistence.Automapping = class {
_onUISourceCodeAdded(uiSourceCode) {
const project = uiSourceCode.project();
if (project.type() === Workspace.projectTypes.FileSystem) {
- if (!Persistence.FileSystemWorkspaceBinding.fileSystemSupportsAutomapping(project))
+ if (!Persistence.FileSystemWorkspaceBinding.fileSystemSupportsAutomapping(project)) {
return;
+ }
this._filesIndex.addPath(uiSourceCode.url());
this._fileSystemUISourceCodes.set(uiSourceCode.url(), uiSourceCode);
this._scheduleSweep();
@@ -140,8 +150,9 @@ Persistence.Automapping = class {
this._filesIndex.removePath(uiSourceCode.url());
this._fileSystemUISourceCodes.delete(uiSourceCode.url());
const status = uiSourceCode[this._statusSymbol];
- if (status)
+ if (status) {
this._clearNetworkStatus(status.network);
+ }
} else if (uiSourceCode.project().type() === Workspace.projectTypes.Network) {
this._clearNetworkStatus(uiSourceCode);
}
@@ -153,14 +164,16 @@ Persistence.Automapping = class {
_onUISourceCodeRenamed(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
const oldURL = /** @type {string} */ (event.data.oldURL);
- if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem)
+ if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
this._filesIndex.removePath(oldURL);
this._fileSystemUISourceCodes.delete(oldURL);
const status = uiSourceCode[this._statusSymbol];
- if (status)
+ if (status) {
this._clearNetworkStatus(status.network);
+ }
this._filesIndex.addPath(uiSourceCode.url());
this._fileSystemUISourceCodes.set(uiSourceCode.url(), uiSourceCode);
@@ -171,28 +184,34 @@ Persistence.Automapping = class {
* @param {!Workspace.UISourceCode} networkSourceCode
*/
_computeNetworkStatus(networkSourceCode) {
- if (networkSourceCode[this._processingPromiseSymbol] || networkSourceCode[this._statusSymbol])
+ if (networkSourceCode[this._processingPromiseSymbol] || networkSourceCode[this._statusSymbol]) {
return;
- if (this._interceptors.some(interceptor => interceptor(networkSourceCode)))
+ }
+ if (this._interceptors.some(interceptor => interceptor(networkSourceCode))) {
return;
- if (networkSourceCode.url().startsWith('wasm://'))
+ }
+ if (networkSourceCode.url().startsWith('wasm://')) {
return;
+ }
const createBindingPromise =
this._createBinding(networkSourceCode).then(validateStatus.bind(this)).then(onStatus.bind(this));
networkSourceCode[this._processingPromiseSymbol] = createBindingPromise;
/**
- * @param {?Persistence.AutomappingStatus} status
- * @return {!Promise<?Persistence.AutomappingStatus>}
- * @this {Persistence.Automapping}
+ * @param {?AutomappingStatus} status
+ * @return {!Promise<?AutomappingStatus>}
+ * @this {Automapping}
*/
async function validateStatus(status) {
- if (!status)
+ if (!status) {
return null;
- if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise)
+ }
+ if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise) {
return null;
- if (status.network.contentType().isFromSourceMap() || !status.fileSystem.contentType().isTextType())
+ }
+ if (status.network.contentType().isFromSourceMap() || !status.fileSystem.contentType().isTextType()) {
return status;
+ }
// At the time binding comes, there are multiple user scenarios:
// 1. Both network and fileSystem files are **not** dirty.
@@ -211,30 +230,30 @@ Persistence.Automapping = class {
// We consider this to be un-realistic scenario and in this case just fail gracefully.
//
// To support usecase (3), we need to validate against original network content.
- if (status.fileSystem.isDirty() && (status.network.isDirty() || status.network.hasCommits()))
+ if (status.fileSystem.isDirty() && (status.network.isDirty() || status.network.hasCommits())) {
return null;
+ }
- const contents = await Promise.all([
- status.fileSystem.requestContent(),
- new Promise(x => status.network.project().requestFileContent(status.network, x))
- ]);
- const fileSystemContent = contents[0];
- const networkContent = contents[1];
- if (fileSystemContent === null || networkContent === null)
+ const [fileSystemContent, networkContent] = await Promise.all(
+ [status.fileSystem.requestContent(), status.network.project().requestFileContent(status.network)]);
+ if (fileSystemContent.content === null || networkContent === null) {
return null;
+ }
- if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise)
+ if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise) {
return null;
+ }
const target = Bindings.NetworkProject.targetForUISourceCode(status.network);
let isValid = false;
+ const fileContent = fileSystemContent.content;
if (target && target.type() === SDK.Target.Type.Node) {
const rewrappedNetworkContent =
- Persistence.Persistence.rewrapNodeJSContent(status.fileSystem, fileSystemContent, networkContent);
- isValid = fileSystemContent === rewrappedNetworkContent;
+ Persistence.Persistence.rewrapNodeJSContent(status.fileSystem, fileContent, networkContent.content);
+ isValid = fileContent === rewrappedNetworkContent;
} else {
// Trim trailing whitespaces because V8 adds trailing newline.
- isValid = fileSystemContent.trimRight() === networkContent.trimRight();
+ isValid = fileContent.trimRight() === networkContent.content.trimRight();
}
if (!isValid) {
this._prevalidationFailedForTest(status);
@@ -244,20 +263,22 @@ Persistence.Automapping = class {
}
/**
- * @param {?Persistence.AutomappingStatus} status
- * @this {Persistence.Automapping}
+ * @param {?AutomappingStatus} status
+ * @this {Automapping}
*/
function onStatus(status) {
- if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise)
+ if (networkSourceCode[this._processingPromiseSymbol] !== createBindingPromise) {
return;
+ }
networkSourceCode[this._processingPromiseSymbol] = null;
if (!status) {
this._onBindingFailedForTest();
return;
}
// TODO(lushnikov): remove this check once there's a single uiSourceCode per url. @see crbug.com/670180
- if (status.network[this._statusSymbol] || status.fileSystem[this._statusSymbol])
+ if (status.network[this._statusSymbol] || status.fileSystem[this._statusSymbol]) {
return;
+ }
this._statuses.add(status);
status.network[this._statusSymbol] = status;
@@ -265,15 +286,16 @@ Persistence.Automapping = class {
if (status.exactMatch) {
const projectFolder = this._projectFoldersIndex.closestParentFolder(status.fileSystem.url());
const newFolderAdded = projectFolder ? this._activeFoldersIndex.addFolder(projectFolder) : false;
- if (newFolderAdded)
+ if (newFolderAdded) {
this._scheduleSweep();
+ }
}
this._onStatusAdded.call(null, status);
}
}
/**
- * @param {!Persistence.AutomappingStatus} binding
+ * @param {!AutomappingStatus} binding
*/
_prevalidationFailedForTest(binding) {
}
@@ -290,65 +312,74 @@ Persistence.Automapping = class {
return;
}
const status = networkSourceCode[this._statusSymbol];
- if (!status)
+ if (!status) {
return;
+ }
this._statuses.delete(status);
status.network[this._statusSymbol] = null;
status.fileSystem[this._statusSymbol] = null;
if (status.exactMatch) {
const projectFolder = this._projectFoldersIndex.closestParentFolder(status.fileSystem.url());
- if (projectFolder)
+ if (projectFolder) {
this._activeFoldersIndex.removeFolder(projectFolder);
+ }
}
this._onStatusRemoved.call(null, status);
}
/**
* @param {!Workspace.UISourceCode} networkSourceCode
- * @return {!Promise<?Persistence.AutomappingStatus>}
+ * @return {!Promise<?AutomappingStatus>}
*/
_createBinding(networkSourceCode) {
if (networkSourceCode.url().startsWith('file://') || networkSourceCode.url().startsWith('snippet://')) {
- const fileSourceCode = this._fileSystemUISourceCodes.get(networkSourceCode.url());
- const status =
- fileSourceCode ? new Persistence.AutomappingStatus(networkSourceCode, fileSourceCode, false) : null;
+ const decodedUrl = decodeURI(networkSourceCode.url());
+ const fileSourceCode = this._fileSystemUISourceCodes.get(decodedUrl);
+ const status = fileSourceCode ? new AutomappingStatus(networkSourceCode, fileSourceCode, false) : null;
return Promise.resolve(status);
}
let networkPath = Common.ParsedURL.extractPath(networkSourceCode.url());
- if (networkPath === null)
- return Promise.resolve(/** @type {?Persistence.AutomappingStatus} */ (null));
+ if (networkPath === null) {
+ return Promise.resolve(/** @type {?AutomappingStatus} */ (null));
+ }
- if (networkPath.endsWith('/'))
+ if (networkPath.endsWith('/')) {
networkPath += 'index.html';
+ }
+ const urlDecodedNetworkPath = decodeURI(networkPath);
const similarFiles =
- this._filesIndex.similarFiles(networkPath).map(path => this._fileSystemUISourceCodes.get(path));
- if (!similarFiles.length)
- return Promise.resolve(/** @type {?Persistence.AutomappingStatus} */ (null));
+ this._filesIndex.similarFiles(urlDecodedNetworkPath).map(path => this._fileSystemUISourceCodes.get(path));
+ if (!similarFiles.length) {
+ return Promise.resolve(/** @type {?AutomappingStatus} */ (null));
+ }
return this._pullMetadatas(similarFiles.concat(networkSourceCode)).then(onMetadatas.bind(this));
/**
- * @this {Persistence.Automapping}
+ * @this {Automapping}
*/
function onMetadatas() {
const activeFiles = similarFiles.filter(file => !!this._activeFoldersIndex.closestParentFolder(file.url()));
const networkMetadata = networkSourceCode[this._metadataSymbol];
if (!networkMetadata || (!networkMetadata.modificationTime && typeof networkMetadata.contentSize !== 'number')) {
// If networkSourceCode does not have metadata, try to match against active folders.
- if (activeFiles.length !== 1)
+ if (activeFiles.length !== 1) {
return null;
- return new Persistence.AutomappingStatus(networkSourceCode, activeFiles[0], false);
+ }
+ return new AutomappingStatus(networkSourceCode, activeFiles[0], false);
}
// Try to find exact matches, prioritizing active folders.
let exactMatches = this._filterWithMetadata(activeFiles, networkMetadata);
- if (!exactMatches.length)
+ if (!exactMatches.length) {
exactMatches = this._filterWithMetadata(similarFiles, networkMetadata);
- if (exactMatches.length !== 1)
+ }
+ if (exactMatches.length !== 1) {
return null;
- return new Persistence.AutomappingStatus(networkSourceCode, exactMatches[0], true);
+ }
+ return new AutomappingStatus(networkSourceCode, exactMatches[0], true);
}
}
@@ -370,8 +401,9 @@ Persistence.Automapping = class {
_filterWithMetadata(files, networkMetadata) {
return files.filter(file => {
const fileMetadata = file[this._metadataSymbol];
- if (!fileMetadata)
+ if (!fileMetadata) {
return false;
+ }
// Allow a second of difference due to network timestamps lack of precision.
const timeMatches = !networkMetadata.modificationTime ||
Math.abs(networkMetadata.modificationTime - fileMetadata.modificationTime) < 1000;
@@ -379,12 +411,12 @@ Persistence.Automapping = class {
return timeMatches && contentMatches;
});
}
-};
+}
/**
* @unrestricted
*/
-Persistence.Automapping.FilePathIndex = class {
+export class FilePathIndex {
/**
* @param {!Persistence.PathEncoder} encoder
*/
@@ -416,17 +448,18 @@ Persistence.Automapping.FilePathIndex = class {
similarFiles(networkPath) {
const encodedPath = this._encoder.encode(networkPath);
const longestCommonPrefix = this._reversedIndex.longestPrefix(encodedPath.reverse(), false);
- if (!longestCommonPrefix)
+ if (!longestCommonPrefix) {
return [];
+ }
return this._reversedIndex.words(longestCommonPrefix)
.map(encodedPath => this._encoder.decode(encodedPath.reverse()));
}
-};
+}
/**
* @unrestricted
*/
-Persistence.Automapping.FolderIndex = class {
+export class FolderIndex {
/**
* @param {!Persistence.PathEncoder} encoder
*/
@@ -442,8 +475,9 @@ Persistence.Automapping.FolderIndex = class {
* @return {boolean}
*/
addFolder(path) {
- if (path.endsWith('/'))
+ if (path.endsWith('/')) {
path = path.substring(0, path.length - 1);
+ }
const encodedPath = this._encoder.encode(path);
this._index.add(encodedPath);
const count = this._folderCount.get(encodedPath) || 0;
@@ -456,12 +490,14 @@ Persistence.Automapping.FolderIndex = class {
* @return {boolean}
*/
removeFolder(path) {
- if (path.endsWith('/'))
+ if (path.endsWith('/')) {
path = path.substring(0, path.length - 1);
+ }
const encodedPath = this._encoder.encode(path);
const count = this._folderCount.get(encodedPath) || 0;
- if (!count)
+ if (!count) {
return false;
+ }
if (count > 1) {
this._folderCount.set(encodedPath, count - 1);
return false;
@@ -480,12 +516,12 @@ Persistence.Automapping.FolderIndex = class {
const commonPrefix = this._index.longestPrefix(encodedPath, true);
return this._encoder.decode(commonPrefix);
}
-};
+}
/**
* @unrestricted
*/
-Persistence.AutomappingStatus = class {
+export class AutomappingStatus {
/**
* @param {!Workspace.UISourceCode} network
* @param {!Workspace.UISourceCode} fileSystem
@@ -496,4 +532,22 @@ Persistence.AutomappingStatus = class {
this.fileSystem = fileSystem;
this.exactMatch = exactMatch;
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.Automapping = Automapping;
+
+/** @constructor */
+Persistence.Automapping.FilePathIndex = FilePathIndex;
+
+/** @constructor */
+Persistence.Automapping.FolderIndex = FolderIndex;
+
+/** @constructor */
+Persistence.AutomappingStatus = AutomappingStatus;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/EditFileSystemView.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/EditFileSystemView.js
index fa3163a10bf..8d453f2a7a7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/EditFileSystemView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/EditFileSystemView.js
@@ -31,7 +31,7 @@
* @implements {UI.ListWidget.Delegate}
* @unrestricted
*/
-Persistence.EditFileSystemView = class extends UI.VBox {
+export default class EditFileSystemView extends UI.VBox {
/**
* @param {string} fileSystemPath
*/
@@ -68,8 +68,9 @@ Persistence.EditFileSystemView = class extends UI.VBox {
}
_update() {
- if (this._muteUpdate)
+ if (this._muteUpdate) {
return;
+ }
this._excludedFoldersList.clear();
this._excludedFolders = [];
@@ -143,8 +144,9 @@ Persistence.EditFileSystemView = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createExcludedFolderEditor() {
- if (this._excludedFolderEditor)
+ if (this._excludedFolderEditor) {
return this._excludedFolderEditor;
+ }
const editor = new UI.ListWidget.Editor();
this._excludedFolderEditor = editor;
@@ -164,19 +166,21 @@ Persistence.EditFileSystemView = class extends UI.VBox {
* @param {number} index
* @param {!HTMLInputElement|!HTMLSelectElement} input
* @return {!UI.ListWidget.ValidatorResult}
- * @this {Persistence.EditFileSystemView}
+ * @this {EditFileSystemView}
*/
function pathPrefixValidator(item, index, input) {
const prefix = this._normalizePrefix(input.value.trim());
- if (!prefix)
+ if (!prefix) {
return {valid: false, errorMessage: ls`Enter a path`};
+ }
const configurableCount =
Persistence.isolatedFileSystemManager.fileSystem(this._fileSystemPath).excludedFolders().size;
for (let i = 0; i < configurableCount; ++i) {
- if (i !== index && this._excludedFolders[i] === prefix)
+ if (i !== index && this._excludedFolders[i] === prefix) {
return {valid: false, errorMessage: ls`Enter a unique path`};
+ }
}
return {valid: true};
}
@@ -187,8 +191,18 @@ Persistence.EditFileSystemView = class extends UI.VBox {
* @return {string}
*/
_normalizePrefix(prefix) {
- if (!prefix)
+ if (!prefix) {
return '';
+ }
return prefix + (prefix[prefix.length - 1] === '/' ? '' : '/');
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.EditFileSystemView = EditFileSystemView;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/FileSystemWorkspaceBinding.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
index bbf6ce73481..4a500e18683 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/FileSystemWorkspaceBinding.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Persistence.FileSystemWorkspaceBinding = class {
+export default class FileSystemWorkspaceBinding {
/**
* @param {!Persistence.IsolatedFileSystemManager} isolatedFileSystemManager
* @param {!Workspace.Workspace} workspace
@@ -47,7 +47,7 @@ Persistence.FileSystemWorkspaceBinding = class {
this._isolatedFileSystemManager.addEventListener(
Persistence.IsolatedFileSystemManager.Events.FileSystemFilesChanged, this._fileSystemFilesChanged, this)
];
- /** @type {!Map.<string, !Persistence.FileSystemWorkspaceBinding.FileSystem>} */
+ /** @type {!Map.<string, !FileSystem>} */
this._boundFileSystems = new Map();
this._isolatedFileSystemManager.waitForFileSystems().then(this._onFileSystemsLoaded.bind(this));
}
@@ -66,7 +66,7 @@ Persistence.FileSystemWorkspaceBinding = class {
*/
static relativePath(uiSourceCode) {
const baseURL =
- /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (uiSourceCode.project())._fileSystemBaseURL;
+ /** @type {!FileSystem}*/ (uiSourceCode.project())._fileSystemBaseURL;
return uiSourceCode.url().substring(baseURL.length).split('/');
}
@@ -76,7 +76,7 @@ Persistence.FileSystemWorkspaceBinding = class {
*/
static tooltipForUISourceCode(uiSourceCode) {
const fileSystem =
- /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (uiSourceCode.project())._fileSystem;
+ /** @type {!FileSystem}*/ (uiSourceCode.project())._fileSystem;
return fileSystem.tooltipForURL(uiSourceCode.url());
}
@@ -86,7 +86,7 @@ Persistence.FileSystemWorkspaceBinding = class {
*/
static fileSystemType(project) {
const fileSystem =
- /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (project)._fileSystem;
+ /** @type {!FileSystem}*/ (project)._fileSystem;
return fileSystem.type();
}
@@ -96,7 +96,7 @@ Persistence.FileSystemWorkspaceBinding = class {
*/
static fileSystemSupportsAutomapping(project) {
const fileSystem =
- /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (project)._fileSystem;
+ /** @type {!FileSystem}*/ (project)._fileSystem;
return fileSystem.supportsAutomapping();
}
@@ -106,7 +106,7 @@ Persistence.FileSystemWorkspaceBinding = class {
* @return {string}
*/
static completeURL(project, relativePath) {
- const fsProject = /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (project);
+ const fsProject = /** @type {!FileSystem}*/ (project);
return fsProject._fileSystemBaseURL + relativePath;
}
@@ -129,8 +129,9 @@ Persistence.FileSystemWorkspaceBinding = class {
* @param {!Array<!Persistence.IsolatedFileSystem>} fileSystems
*/
_onFileSystemsLoaded(fileSystems) {
- for (const fileSystem of fileSystems)
+ for (const fileSystem of fileSystems) {
this._addFileSystem(fileSystem);
+ }
}
/**
@@ -145,7 +146,7 @@ Persistence.FileSystemWorkspaceBinding = class {
* @param {!Persistence.PlatformFileSystem} fileSystem
*/
_addFileSystem(fileSystem) {
- const boundFileSystem = new Persistence.FileSystemWorkspaceBinding.FileSystem(this, fileSystem, this._workspace);
+ const boundFileSystem = new FileSystem(this, fileSystem, this._workspace);
this._boundFileSystems.set(fileSystem.path(), boundFileSystem);
}
@@ -166,22 +167,25 @@ Persistence.FileSystemWorkspaceBinding = class {
const paths = /** @type {!Persistence.IsolatedFileSystemManager.FilesChangedData} */ (event.data);
for (const fileSystemPath of paths.changed.keysArray()) {
const fileSystem = this._boundFileSystems.get(fileSystemPath);
- if (!fileSystem)
+ if (!fileSystem) {
continue;
+ }
paths.changed.get(fileSystemPath).forEach(path => fileSystem._fileChanged(path));
}
for (const fileSystemPath of paths.added.keysArray()) {
const fileSystem = this._boundFileSystems.get(fileSystemPath);
- if (!fileSystem)
+ if (!fileSystem) {
continue;
+ }
paths.added.get(fileSystemPath).forEach(path => fileSystem._fileChanged(path));
}
for (const fileSystemPath of paths.removed.keysArray()) {
const fileSystem = this._boundFileSystems.get(fileSystemPath);
- if (!fileSystem)
+ if (!fileSystem) {
continue;
+ }
paths.removed.get(fileSystemPath).forEach(path => fileSystem.removeUISourceCode(path));
}
}
@@ -193,21 +197,21 @@ Persistence.FileSystemWorkspaceBinding = class {
this._boundFileSystems.remove(fileSystem._fileSystem.path());
}
}
-};
+}
/**
* @implements {Workspace.Project}
* @unrestricted
*/
-Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.ProjectStore {
+export class FileSystem extends Workspace.ProjectStore {
/**
- * @param {!Persistence.FileSystemWorkspaceBinding} fileSystemWorkspaceBinding
+ * @param {!FileSystemWorkspaceBinding} fileSystemWorkspaceBinding
* @param {!Persistence.PlatformFileSystem} isolatedFileSystem
* @param {!Workspace.Workspace} workspace
*/
constructor(fileSystemWorkspaceBinding, isolatedFileSystem, workspace) {
const fileSystemPath = isolatedFileSystem.path();
- const id = Persistence.FileSystemWorkspaceBinding.projectId(fileSystemPath);
+ const id = FileSystemWorkspaceBinding.projectId(fileSystemPath);
console.assert(!workspace.project(id));
const displayName = fileSystemPath.substr(fileSystemPath.lastIndexOf('/') + 1);
@@ -270,11 +274,12 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
* @return {!Promise<?Workspace.UISourceCodeMetadata>}
*/
requestMetadata(uiSourceCode) {
- if (uiSourceCode[Persistence.FileSystemWorkspaceBinding._metadata])
- return uiSourceCode[Persistence.FileSystemWorkspaceBinding._metadata];
+ if (uiSourceCode[_metadata]) {
+ return uiSourceCode[_metadata];
+ }
const relativePath = this._filePathForUISourceCode(uiSourceCode);
const promise = this._fileSystem.getMetadata(relativePath).then(onMetadata);
- uiSourceCode[Persistence.FileSystemWorkspaceBinding._metadata] = promise;
+ uiSourceCode[_metadata] = promise;
return promise;
/**
@@ -282,8 +287,9 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
* @return {?Workspace.UISourceCodeMetadata}
*/
function onMetadata(metadata) {
- if (!metadata)
+ if (!metadata) {
return null;
+ }
return new Workspace.UISourceCodeMetadata(metadata.modificationTime, metadata.size);
}
}
@@ -299,11 +305,11 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
/**
* @override
* @param {!Workspace.UISourceCode} uiSourceCode
- * @param {function(?string, boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(uiSourceCode, callback) {
+ requestFileContent(uiSourceCode) {
const filePath = this._filePathForUISourceCode(uiSourceCode);
- this._fileSystem.requestFileContent(filePath, callback);
+ return this._fileSystem.requestFileContent(filePath);
}
/**
@@ -333,7 +339,7 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
*/
fullDisplayName(uiSourceCode) {
const baseURL =
- /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem}*/ (uiSourceCode.project())._fileSystemParentURL;
+ /** @type {!FileSystem}*/ (uiSourceCode.project())._fileSystemParentURL;
return uiSourceCode.url().substring(baseURL.length);
}
@@ -363,7 +369,7 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
/**
* @param {boolean} success
* @param {string=} newName
- * @this {Persistence.FileSystemWorkspaceBinding.FileSystem}
+ * @this {FileSystem}
*/
function innerCallback(success, newName) {
if (!success || !newName) {
@@ -390,18 +396,13 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
* @param {boolean} isRegex
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
- searchInFileContent(uiSourceCode, query, caseSensitive, isRegex) {
- return new Promise(resolve => {
- const filePath = this._filePathForUISourceCode(uiSourceCode);
- this._fileSystem.requestFileContent(filePath, contentCallback);
-
- /**
- * @param {?string} content
- */
- function contentCallback(content) {
- resolve(content ? Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex) : []);
- }
- });
+ async searchInFileContent(uiSourceCode, query, caseSensitive, isRegex) {
+ const filePath = this._filePathForUISourceCode(uiSourceCode);
+ const {content} = await this._fileSystem.requestFileContent(filePath);
+ if (content) {
+ return Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
+ }
+ return [];
}
/**
@@ -414,8 +415,9 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
async findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, progress) {
let result = filesMathingFileQuery;
const queriesToRun = searchConfig.queries().slice();
- if (!queriesToRun.length)
+ if (!queriesToRun.length) {
queriesToRun.push('');
+ }
progress.setTotalWork(queriesToRun.length);
for (const query of queriesToRun) {
@@ -443,14 +445,16 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
/**
* @param {number} from
- * @this {Persistence.FileSystemWorkspaceBinding.FileSystem}
+ * @this {FileSystem}
*/
function reportFileChunk(from) {
const to = Math.min(from + chunkSize, filePaths.length);
- for (let i = from; i < to; ++i)
+ for (let i = from; i < to; ++i) {
this._addFile(filePaths[i]);
- if (to < filePaths.length)
+ }
+ if (to < filePaths.length) {
setTimeout(reportFileChunk.bind(this, to), 100);
+ }
}
}
@@ -460,17 +464,20 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
*/
excludeFolder(url) {
let relativeFolder = url.substring(this._fileSystemBaseURL.length);
- if (!relativeFolder.startsWith('/'))
+ if (!relativeFolder.startsWith('/')) {
relativeFolder = '/' + relativeFolder;
- if (!relativeFolder.endsWith('/'))
+ }
+ if (!relativeFolder.endsWith('/')) {
relativeFolder += '/';
+ }
this._fileSystem.addExcludedFolder(relativeFolder);
const uiSourceCodes = this.uiSourceCodes().slice();
for (let i = 0; i < uiSourceCodes.length; ++i) {
const uiSourceCode = uiSourceCodes[i];
- if (uiSourceCode.url().startsWith(url))
+ if (uiSourceCode.url().startsWith(url)) {
this.removeUISourceCode(uiSourceCode.url());
+ }
}
}
@@ -503,8 +510,9 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
const guardFileName = this._fileSystemPath + path + (!path.endsWith('/') ? '/' : '') + name;
this._creatingFilesGuard.add(guardFileName);
const filePath = await this._fileSystem.createFile(path, name);
- if (!filePath)
+ if (!filePath) {
return null;
+ }
const uiSourceCode = this._addFile(filePath);
uiSourceCode.setContent(content, !!isBase64);
this._creatingFilesGuard.delete(guardFileName);
@@ -518,8 +526,9 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
deleteFile(uiSourceCode) {
const relativePath = this._filePathForUISourceCode(uiSourceCode);
this._fileSystem.deleteFile(relativePath).then(success => {
- if (success)
+ if (success) {
this.removeUISourceCode(uiSourceCode.url());
+ }
});
}
@@ -546,15 +555,16 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
*/
_fileChanged(path) {
// Ignore files that are being created but do not have content yet.
- if (this._creatingFilesGuard.has(path))
+ if (this._creatingFilesGuard.has(path)) {
return;
+ }
const uiSourceCode = this.uiSourceCodeForURL(path);
if (!uiSourceCode) {
const contentType = this._fileSystem.contentType(path);
this.addUISourceCode(this.createUISourceCode(path, contentType));
return;
}
- uiSourceCode[Persistence.FileSystemWorkspaceBinding._metadata] = null;
+ uiSourceCode[_metadata] = null;
uiSourceCode.checkContentUpdated();
}
@@ -569,6 +579,20 @@ Persistence.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Proj
dispose() {
this.removeProject();
}
-};
+}
+
+export const _metadata = Symbol('FileSystemWorkspaceBinding.Metadata');
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.FileSystemWorkspaceBinding = FileSystemWorkspaceBinding;
+
+/** @constructor */
+Persistence.FileSystemWorkspaceBinding.FileSystem = FileSystem;
-Persistence.FileSystemWorkspaceBinding._metadata = Symbol('FileSystemWorkspaceBinding.Metadata');
+Persistence.FileSystemWorkspaceBinding._metadata = _metadata;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js
index 5756f749b99..1e0f98dc151 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js
@@ -30,7 +30,7 @@
/**
* @unrestricted
*/
-Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
+export default class IsolatedFileSystem extends Persistence.PlatformFileSystem {
/**
* @param {!Persistence.IsolatedFileSystemManager} manager
* @param {string} path
@@ -64,17 +64,18 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
* @param {string} type
* @param {string} name
* @param {string} rootURL
- * @return {!Promise<?Persistence.IsolatedFileSystem>}
+ * @return {!Promise<?IsolatedFileSystem>}
*/
static create(manager, path, embedderPath, type, name, rootURL) {
- const domFileSystem = InspectorFrontendHost.isolatedFileSystem(name, rootURL);
- if (!domFileSystem)
- return Promise.resolve(/** @type {?Persistence.IsolatedFileSystem} */ (null));
+ const domFileSystem = Host.InspectorFrontendHost.isolatedFileSystem(name, rootURL);
+ if (!domFileSystem) {
+ return Promise.resolve(/** @type {?IsolatedFileSystem} */ (null));
+ }
- const fileSystem = new Persistence.IsolatedFileSystem(manager, path, embedderPath, domFileSystem, type);
+ const fileSystem = new IsolatedFileSystem(manager, path, embedderPath, domFileSystem, type);
return fileSystem._initializeFilePaths()
.then(() => fileSystem)
- .catchException(/** @type {?Persistence.IsolatedFileSystem} */ (null));
+ .catchException(/** @type {?IsolatedFileSystem} */ (null));
}
/**
@@ -119,7 +120,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
* @param {!FileError} error
*/
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when getting file metadata \'' + path);
fulfill(null);
}
@@ -162,14 +163,15 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!Array.<!FileEntry>} entries
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function innerCallback(entries) {
for (let i = 0; i < entries.length; ++i) {
const entry = entries[i];
if (!entry.isDirectory) {
- if (this.isFileExcluded(entry.fullPath))
+ if (this.isFileExcluded(entry.fullPath)) {
continue;
+ }
this._initialFilePaths.add(entry.fullPath.substr(1));
} else {
if (entry.fullPath.endsWith('/.git')) {
@@ -186,8 +188,9 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
this._requestEntries(entry.fullPath, boundInnerCallback);
}
}
- if ((--pendingRequests === 0))
+ if ((--pendingRequests === 0)) {
fulfill();
+ }
}
}
@@ -199,15 +202,17 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
// Fast-path. If parent directory already exists we return it immidiatly.
let dirEntry = await new Promise(
resolve => this._domFileSystem.root.getDirectory(folderPath, undefined, resolve, () => resolve(null)));
- if (dirEntry)
+ if (dirEntry) {
return dirEntry;
+ }
const paths = folderPath.split('/');
let activePath = '';
for (const path of paths) {
activePath = activePath + '/' + path;
dirEntry = await this._innerCreateFolderIfNeeded(activePath);
- if (!dirEntry)
+ if (!dirEntry) {
return null;
+ }
}
return dirEntry;
}
@@ -219,7 +224,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
_innerCreateFolderIfNeeded(path) {
return new Promise(resolve => {
this._domFileSystem.root.getDirectory(path, {create: true}, dirEntry => resolve(dirEntry), error => {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' trying to create directory \'' + path + '\'');
resolve(null);
});
@@ -234,18 +239,20 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
*/
async createFile(path, name) {
const dirEntry = await this._createFoldersIfNotExist(path);
- if (!dirEntry)
+ if (!dirEntry) {
return null;
+ }
const fileEntry = await this._serializedFileOperation(path, createFileCandidate.bind(this, name || 'NewFile'));
- if (!fileEntry)
+ if (!fileEntry) {
return null;
+ }
return fileEntry.fullPath.substr(1);
/**
* @param {string} name
* @param {number=} newFileIndex
* @return {!Promise<?FileEntry>}
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function createFileCandidate(name, newFileIndex) {
return new Promise(resolve => {
@@ -255,7 +262,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
resolve(createFileCandidate.call(this, name, (newFileIndex ? newFileIndex + 1 : 1)));
return;
}
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(
errorMessage + ' when testing if file exists \'' + (this.path() + '/' + path + '/' + nameCandidate) +
'\'');
@@ -278,7 +285,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!FileEntry} fileEntry
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function fileEntryLoaded(fileEntry) {
fileEntry.remove(fileEntryRemoved, errorHandler.bind(this));
@@ -290,12 +297,12 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!FileError} error
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
* @suppress {checkTypes}
* TODO(jsbell): Update externs replacing FileError with DOMException. https://crbug.com/496901
*/
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when deleting file \'' + (this.path() + '/' + path) + '\'');
resolveCallback(false);
}
@@ -313,7 +320,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
}, errorHandler.bind(this));
/**
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function errorHandler(error) {
if (error.name === 'NotFoundError') {
@@ -321,7 +328,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
return;
}
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when getting content for file \'' + (this.path() + '/' + path) + '\'');
resolve(null);
}
@@ -331,45 +338,51 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @override
* @param {string} path
- * @param {function(?string,boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(path, callback) {
- const innerRequestFileContent = async () => {
- const blob = await this.requestFileBlob(path);
- if (!blob) {
- callback(null, false);
- return;
- }
+ requestFileContent(path) {
+ return this._serializedFileOperation(path, () => this._innerRequestFileContent(path));
+ }
- const reader = new FileReader();
- const extension = Common.ParsedURL.extractExtension(path);
- const encoded = Persistence.IsolatedFileSystem.BinaryExtensions.has(extension);
- const readPromise = new Promise(x => reader.onloadend = x);
- if (encoded)
- reader.readAsBinaryString(blob);
- else
- reader.readAsText(blob);
- await readPromise;
- if (reader.error) {
- console.error('Can\'t read file: ' + path + ': ' + reader.error);
- callback(null, false);
- return;
- }
- let result;
- try {
- result = reader.result;
- } catch (e) {
- result = null;
- console.error('Can\'t read file: ' + path + ': ' + e);
- }
- if (result === undefined || result === null) {
- callback(null, false);
- return;
- }
- callback(encoded ? btoa(result) : result, encoded);
- };
+ /**
+ * @param {string} path
+ * @return {!Promise<!Common.DeferredContent>}
+ */
+ async _innerRequestFileContent(path) {
+ const blob = await this.requestFileBlob(path);
+ if (!blob) {
+ return {error: ls`Blob could not be loaded.`, isEncoded: false};
+ }
- this._serializedFileOperation(path, innerRequestFileContent);
+ const reader = new FileReader();
+ const extension = Common.ParsedURL.extractExtension(path);
+ const encoded = Persistence.IsolatedFileSystem.BinaryExtensions.has(extension);
+ const readPromise = new Promise(x => reader.onloadend = x);
+ if (encoded) {
+ reader.readAsBinaryString(blob);
+ } else {
+ reader.readAsText(blob);
+ }
+ await readPromise;
+ if (reader.error) {
+ const error = ls`Can't read file: ${path}: ${reader.error}`;
+ console.error(error);
+ return {isEncoded: false, error};
+ }
+ let result = null;
+ let error = null;
+ try {
+ result = /** @type {string} */ (reader.result);
+ } catch (e) {
+ result = null;
+ error = ls`Can't read file: ${path}: ${e.message}`;
+ }
+ if (result === undefined || result === null) {
+ error = error || ls`Unknown error reading file: ${path}`;
+ console.error(error);
+ return {isEncoded: false, error};
+ }
+ return {isEncoded: encoded, content: encoded ? btoa(result) : result};
}
/**
@@ -391,7 +404,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!FileEntry} entry
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function fileEntryLoaded(entry) {
entry.createWriter(fileWriterCreated.bind(this), errorHandler.bind(this));
@@ -399,16 +412,17 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!FileWriter} fileWriter
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
async function fileWriterCreated(fileWriter) {
fileWriter.onerror = errorHandler.bind(this);
fileWriter.onwriteend = fileWritten;
let blob;
- if (isBase64)
- blob = await(await fetch(`data:application/octet-stream;base64,${content}`)).blob();
- else
+ if (isBase64) {
+ blob = await (await fetch(`data:application/octet-stream;base64,${content}`)).blob();
+ } else {
blob = new Blob([content], {type: 'text/plain'});
+ }
fileWriter.write(blob);
function fileWritten() {
@@ -418,10 +432,10 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
}
/**
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when setting content for file \'' + (this.path() + '/' + path) + '\'');
callback();
}
@@ -446,7 +460,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!FileEntry} entry
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function fileEntryLoaded(entry) {
if (entry.name === newName) {
@@ -460,7 +474,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!Entry} entry
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function dirEntryLoaded(entry) {
dirEntry = entry;
@@ -475,7 +489,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
}
/**
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function newFileEntryLoadErrorHandler(error) {
if (error.name !== 'NotFoundError') {
@@ -493,10 +507,10 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
}
/**
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when renaming file \'' + (this.path() + '/' + path) + '\' to \'' + newName + '\'');
callback(false);
}
@@ -526,7 +540,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
dirReader.readEntries(innerCallback, errorHandler);
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when reading directory \'' + dirEntry.fullPath + '\'');
callback([]);
}
@@ -541,14 +555,14 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @param {!DirectoryEntry} dirEntry
- * @this {Persistence.IsolatedFileSystem}
+ * @this {IsolatedFileSystem}
*/
function innerCallback(dirEntry) {
this._readDirectory(dirEntry, callback);
}
function errorHandler(error) {
- const errorMessage = Persistence.IsolatedFileSystem.errorMessage(error);
+ const errorMessage = IsolatedFileSystem.errorMessage(error);
console.error(errorMessage + ' when requesting entry \'' + path + '\'');
callback([]);
}
@@ -595,8 +609,9 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
* @return {boolean}
*/
isFileExcluded(folderPath) {
- if (this._excludedFolders.has(folderPath))
+ if (this._excludedFolders.has(folderPath)) {
return true;
+ }
const regex = this._manager.workspaceFolderExcludePatternSetting().asRegExp();
return !!(regex && regex.test(folderPath));
}
@@ -618,7 +633,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
searchInPath(query, progress) {
return new Promise(resolve => {
const requestId = this._manager.registerCallback(innerCallback);
- InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query);
+ Host.InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query);
/**
* @param {!Array<string>} files
@@ -637,7 +652,7 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
indexContent(progress) {
progress.setTotalWork(1);
const requestId = this._manager.registerProgress(progress);
- InspectorFrontendHost.indexPath(requestId, this._embedderPath, JSON.stringify(this._excludedEmbedderFolders));
+ Host.InspectorFrontendHost.indexPath(requestId, this._embedderPath, JSON.stringify(this._excludedEmbedderFolders));
}
/**
@@ -665,16 +680,19 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
*/
contentType(path) {
const extension = Common.ParsedURL.extractExtension(path);
- if (Persistence.IsolatedFileSystem._styleSheetExtensions.has(extension))
+ if (_styleSheetExtensions.has(extension)) {
return Common.resourceTypes.Stylesheet;
- if (Persistence.IsolatedFileSystem._documentExtensions.has(extension))
+ }
+ if (_documentExtensions.has(extension)) {
return Common.resourceTypes.Document;
- if (Persistence.IsolatedFileSystem.ImageExtensions.has(extension))
+ }
+ if (ImageExtensions.has(extension)) {
return Common.resourceTypes.Image;
- if (Persistence.IsolatedFileSystem._scriptExtensions.has(extension))
+ }
+ if (_scriptExtensions.has(extension)) {
return Common.resourceTypes.Script;
- return Persistence.IsolatedFileSystem.BinaryExtensions.has(extension) ? Common.resourceTypes.Other :
- Common.resourceTypes.Document;
+ }
+ return BinaryExtensions.has(extension) ? Common.resourceTypes.Other : Common.resourceTypes.Document;
}
/**
@@ -694,19 +712,19 @@ Persistence.IsolatedFileSystem = class extends Persistence.PlatformFileSystem {
supportsAutomapping() {
return this.type() !== 'overrides';
}
-};
+}
+
+export const _styleSheetExtensions = new Set(['css', 'scss', 'sass', 'less']);
+export const _documentExtensions = new Set(['htm', 'html', 'asp', 'aspx', 'phtml', 'jsp']);
-Persistence.IsolatedFileSystem._styleSheetExtensions = new Set(['css', 'scss', 'sass', 'less']);
-Persistence.IsolatedFileSystem._documentExtensions = new Set(['htm', 'html', 'asp', 'aspx', 'phtml', 'jsp']);
-Persistence.IsolatedFileSystem._scriptExtensions = new Set([
+export const _scriptExtensions = new Set([
'asp', 'aspx', 'c', 'cc', 'cljs', 'coffee', 'cpp', 'cs', 'dart', 'java', 'js',
'jsp', 'jsx', 'h', 'm', 'mjs', 'mm', 'py', 'sh', 'ts', 'tsx', 'ls'
]);
-Persistence.IsolatedFileSystem.ImageExtensions =
- new Set(['jpeg', 'jpg', 'svg', 'gif', 'webp', 'png', 'ico', 'tiff', 'tif', 'bmp']);
+export const ImageExtensions = new Set(['jpeg', 'jpg', 'svg', 'gif', 'webp', 'png', 'ico', 'tiff', 'tif', 'bmp']);
-Persistence.IsolatedFileSystem.BinaryExtensions = new Set([
+export const BinaryExtensions = new Set([
// Executable extensions, roughly taken from https://en.wikipedia.org/wiki/Comparison_of_executable_file_formats
'cmd', 'com', 'exe',
// Archive extensions, roughly taken from https://en.wikipedia.org/wiki/List_of_archive_formats
@@ -718,3 +736,18 @@ Persistence.IsolatedFileSystem.BinaryExtensions = new Set([
// Image file extensions
'jpeg', 'jpg', 'gif', 'webp', 'png', 'ico', 'tiff', 'tif', 'bmp'
]);
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.IsolatedFileSystem = IsolatedFileSystem;
+
+Persistence.IsolatedFileSystem._styleSheetExtensions = _styleSheetExtensions;
+Persistence.IsolatedFileSystem._documentExtensions = _documentExtensions;
+Persistence.IsolatedFileSystem._scriptExtensions = _scriptExtensions;
+Persistence.IsolatedFileSystem.ImageExtensions = ImageExtensions;
+Persistence.IsolatedFileSystem.BinaryExtensions = BinaryExtensions;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js
index 3ea1dc843db..bb73592bc6b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-Persistence.IsolatedFileSystemManager = class extends Common.Object {
+export default class IsolatedFileSystemManager extends Common.Object {
constructor() {
super();
@@ -42,20 +42,20 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
/** @type {!Map<number, !Common.Progress>} */
this._progresses = new Map();
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.FileSystemRemoved, this._onFileSystemRemoved, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.FileSystemAdded, this._onFileSystemAdded, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this._onFileSystemFilesChanged, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.IndexingWorked, this._onIndexingWorked, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.IndexingDone, this._onIndexingDone, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.SearchCompleted, this._onSearchCompleted, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this._onFileSystemRemoved, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.FileSystemAdded, this._onFileSystemAdded, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this._onFileSystemFilesChanged, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.IndexingWorked, this._onIndexingWorked, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.IndexingDone, this._onIndexingDone, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.SearchCompleted, this._onSearchCompleted, this);
this._initExcludePatterSetting();
@@ -70,20 +70,21 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
_requestFileSystems() {
let fulfill;
const promise = new Promise(f => fulfill = f);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.FileSystemsLoaded, onFileSystemsLoaded, this);
- InspectorFrontendHost.requestFileSystems();
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, onFileSystemsLoaded, this);
+ Host.InspectorFrontendHost.requestFileSystems();
return promise;
/**
* @param {!Common.Event} event
- * @this {Persistence.IsolatedFileSystemManager}
+ * @this {IsolatedFileSystemManager}
*/
function onFileSystemsLoaded(event) {
const fileSystems = /** @type {!Array.<!Persistence.IsolatedFileSystemManager.FileSystem>} */ (event.data);
const promises = [];
- for (let i = 0; i < fileSystems.length; ++i)
+ for (let i = 0; i < fileSystems.length; ++i) {
promises.push(this._innerAddFileSystem(fileSystems[i], false));
+ }
Promise.all(promises).then(onFileSystemsAdded);
}
@@ -102,7 +103,7 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
addFileSystem(type) {
return new Promise(resolve => {
this._fileSystemRequestResolve = resolve;
- InspectorFrontendHost.addFileSystem(type || '');
+ Host.InspectorFrontendHost.addFileSystem(type || '');
});
}
@@ -110,7 +111,7 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
* @param {!Persistence.PlatformFileSystem} fileSystem
*/
removeFileSystem(fileSystem) {
- InspectorFrontendHost.removeFileSystem(fileSystem.embedderPath());
+ Host.InspectorFrontendHost.removeFileSystem(fileSystem.embedderPath());
}
/**
@@ -134,14 +135,16 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
/**
* @param {?Persistence.PlatformFileSystem} fileSystem
- * @this {Persistence.IsolatedFileSystemManager}
+ * @this {IsolatedFileSystemManager}
*/
function storeFileSystem(fileSystem) {
- if (!fileSystem)
+ if (!fileSystem) {
return null;
+ }
this._fileSystems.set(fileSystemURL, fileSystem);
- if (dispatchEvent)
- this.dispatchEventToListeners(Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, fileSystem);
+ if (dispatchEvent) {
+ this.dispatchEventToListeners(Events.FileSystemAdded, fileSystem);
+ }
return fileSystem;
}
}
@@ -152,7 +155,7 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
*/
addPlatformFileSystem(fileSystemURL, fileSystem) {
this._fileSystems.set(fileSystemURL, fileSystem);
- this.dispatchEventToListeners(Persistence.IsolatedFileSystemManager.Events.FileSystemAdded, fileSystem);
+ this.dispatchEventToListeners(Events.FileSystemAdded, fileSystem);
}
/**
@@ -163,8 +166,9 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
let fileSystem = /** @type {?Persistence.IsolatedFileSystemManager.FileSystem} */ (event.data['fileSystem']);
if (errorMessage) {
Common.console.error(Common.UIString('Unable to add filesystem: %s', errorMessage));
- if (!this._fileSystemRequestResolve)
+ if (!this._fileSystemRequestResolve) {
return;
+ }
this._fileSystemRequestResolve.call(null, null);
this._fileSystemRequestResolve = null;
} else if (fileSystem) {
@@ -183,11 +187,12 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
const embedderPath = /** @type {string} */ (event.data);
const fileSystemPath = Common.ParsedURL.platformPathToURL(embedderPath);
const isolatedFileSystem = this._fileSystems.get(fileSystemPath);
- if (!isolatedFileSystem)
+ if (!isolatedFileSystem) {
return;
+ }
this._fileSystems.delete(fileSystemPath);
isolatedFileSystem.fileSystemRemoved();
- this.dispatchEventToListeners(Persistence.IsolatedFileSystemManager.Events.FileSystemRemoved, isolatedFileSystem);
+ this.dispatchEventToListeners(Events.FileSystemRemoved, isolatedFileSystem);
}
/**
@@ -200,23 +205,25 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
removed: groupFilePathsIntoFileSystemPaths.call(this, event.data.removed)
};
- this.dispatchEventToListeners(Persistence.IsolatedFileSystemManager.Events.FileSystemFilesChanged, urlPaths);
+ this.dispatchEventToListeners(Events.FileSystemFilesChanged, urlPaths);
/**
* @param {!Array<string>} embedderPaths
- * @return {!Multimap<string, string>}
- * @this {Persistence.IsolatedFileSystemManager}
+ * @return {!Platform.Multimap<string, string>}
+ * @this {IsolatedFileSystemManager}
*/
function groupFilePathsIntoFileSystemPaths(embedderPaths) {
- const paths = new Multimap();
+ const paths = new Platform.Multimap();
for (const embedderPath of embedderPaths) {
const filePath = Common.ParsedURL.platformPathToURL(embedderPath);
for (const fileSystemPath of this._fileSystems.keys()) {
- if (this._fileSystems.get(fileSystemPath).isFileExcluded(embedderPath))
+ if (this._fileSystems.get(fileSystemPath).isFileExcluded(embedderPath)) {
continue;
+ }
const pathPrefix = fileSystemPath.endsWith('/') ? fileSystemPath : fileSystemPath + '/';
- if (!filePath.startsWith(pathPrefix))
+ if (!filePath.startsWith(pathPrefix)) {
continue;
+ }
paths.set(fileSystemPath, filePath);
}
}
@@ -251,12 +258,13 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
];
const defaultLinuxExcludedFolders = ['/.*~$'];
let defaultExcludedFolders = defaultCommonExcludedFolders;
- if (Host.isWin())
+ if (Host.isWin()) {
defaultExcludedFolders = defaultExcludedFolders.concat(defaultWinExcludedFolders);
- else if (Host.isMac())
+ } else if (Host.isMac()) {
defaultExcludedFolders = defaultExcludedFolders.concat(defaultMacExcludedFolders);
- else
+ } else {
defaultExcludedFolders = defaultExcludedFolders.concat(defaultLinuxExcludedFolders);
+ }
const defaultExcludedFoldersPattern = defaultExcludedFolders.join('|');
this._workspaceFolderExcludePatternSetting = Common.settings.createRegExpSetting(
'workspaceFolderExcludePattern', defaultExcludedFoldersPattern, Host.isWin() ? 'i' : '');
@@ -274,7 +282,7 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
* @return {number}
*/
registerCallback(callback) {
- const requestId = ++Persistence.IsolatedFileSystemManager._lastRequestId;
+ const requestId = ++_lastRequestId;
this._callbacks.set(requestId, callback);
return requestId;
}
@@ -284,7 +292,7 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
* @return {number}
*/
registerProgress(progress) {
- const requestId = ++Persistence.IsolatedFileSystemManager._lastRequestId;
+ const requestId = ++_lastRequestId;
this._progresses.set(requestId, progress);
return requestId;
}
@@ -297,8 +305,9 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
const totalWork = /** @type {number} */ (event.data['totalWork']);
const progress = this._progresses.get(requestId);
- if (!progress)
+ if (!progress) {
return;
+ }
progress.setTotalWork(totalWork);
}
@@ -310,11 +319,12 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
const worked = /** @type {number} */ (event.data['worked']);
const progress = this._progresses.get(requestId);
- if (!progress)
+ if (!progress) {
return;
+ }
progress.worked(worked);
if (progress.isCanceled()) {
- InspectorFrontendHost.stopIndexing(requestId);
+ Host.InspectorFrontendHost.stopIndexing(requestId);
this._onIndexingDone(event);
}
}
@@ -326,8 +336,9 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
const requestId = /** @type {number} */ (event.data['requestId']);
const progress = this._progresses.get(requestId);
- if (!progress)
+ if (!progress) {
return;
+ }
progress.done();
this._progresses.delete(requestId);
}
@@ -340,21 +351,16 @@ Persistence.IsolatedFileSystemManager = class extends Common.Object {
const files = /** @type {!Array.<string>} */ (event.data['files']);
const callback = this._callbacks.get(requestId);
- if (!callback)
+ if (!callback) {
return;
+ }
callback.call(null, files);
this._callbacks.delete(requestId);
}
-};
-
-/** @typedef {!{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} */
-Persistence.IsolatedFileSystemManager.FileSystem;
-
-/** @typedef {!{changed:!Multimap<string, string>, added:!Multimap<string, string>, removed:!Multimap<string, string>}} */
-Persistence.IsolatedFileSystemManager.FilesChangedData;
+}
/** @enum {symbol} */
-Persistence.IsolatedFileSystemManager.Events = {
+export const Events = {
FileSystemAdded: Symbol('FileSystemAdded'),
FileSystemRemoved: Symbol('FileSystemRemoved'),
FileSystemFilesChanged: Symbol('FileSystemFilesChanged'),
@@ -362,9 +368,28 @@ Persistence.IsolatedFileSystemManager.Events = {
ExcludedFolderRemoved: Symbol('ExcludedFolderRemoved')
};
-Persistence.IsolatedFileSystemManager._lastRequestId = 0;
+export let _lastRequestId = 0;
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.IsolatedFileSystemManager = IsolatedFileSystemManager;
+
+/** @enum {symbol} */
+Persistence.IsolatedFileSystemManager.Events = Events;
+Persistence.IsolatedFileSystemManager._lastRequestId = _lastRequestId;
+
+/** @typedef {!{type: string, fileSystemName: string, rootURL: string, fileSystemPath: string}} */
+Persistence.IsolatedFileSystemManager.FileSystem;
+
+/** @typedef {!{changed:!Platform.Multimap<string, string>, added:!Platform.Multimap<string, string>, removed:!Platform.Multimap<string, string>}} */
+Persistence.IsolatedFileSystemManager.FilesChangedData;
/**
- * @type {!Persistence.IsolatedFileSystemManager}
+ * @type {!IsolatedFileSystemManager}
*/
Persistence.isolatedFileSystemManager;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/NetworkPersistenceManager.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/NetworkPersistenceManager.js
index 23d10fb58c5..afde0aa3b15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/NetworkPersistenceManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/NetworkPersistenceManager.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.NetworkPersistenceManager = class extends Common.Object {
+export default class NetworkPersistenceManager extends Common.Object {
/**
* @param {!Workspace.Workspace} workspace
*/
@@ -64,15 +64,17 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @return {?Promise<?string>}
*/
originalContentForUISourceCode(uiSourceCode) {
- if (!uiSourceCode[this._bindingSymbol])
+ if (!uiSourceCode[this._bindingSymbol]) {
return null;
+ }
const fileSystemUISourceCode = uiSourceCode[this._bindingSymbol].fileSystem;
return fileSystemUISourceCode[this._originalResponseContentPromiseSymbol] || null;
}
_enabledChanged() {
- if (this._enabled === this._enabledSetting.get())
+ if (this._enabled === this._enabledSetting.get()) {
return;
+ }
this._enabled = this._enabledSetting.get();
if (this._enabled) {
this._eventDescriptors = [
@@ -104,14 +106,16 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
_updateActiveProject() {
const wasActive = this._active;
this._active = !!(this._enabledSetting.get() && SDK.targetManager.mainTarget() && this._project);
- if (this._active === wasActive)
+ if (this._active === wasActive) {
return;
+ }
if (this._active) {
this._project.uiSourceCodes().forEach(this._filesystemUISourceCodeAdded.bind(this));
const networkProjects = this._workspace.projectsForType(Workspace.projectTypes.Network);
- for (const networkProject of networkProjects)
+ for (const networkProject of networkProjects) {
networkProject.uiSourceCodes().forEach(this._networkUISourceCodeAdded.bind(this));
+ }
} else if (this._project) {
this._project.uiSourceCodes().forEach(this._filesystemUISourceCodeRemoved.bind(this));
this._networkUISourceCodeForEncodedPath.clear();
@@ -124,11 +128,13 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @return {string}
*/
_encodedPathFromUrl(url) {
- if (!this._active)
+ if (!this._active) {
return '';
+ }
let urlPath = Common.ParsedURL.urlWithoutHash(url.replace(/^https?:\/\//, ''));
- if (urlPath.endsWith('/') && urlPath.indexOf('?') === -1)
+ if (urlPath.endsWith('/') && urlPath.indexOf('?') === -1) {
urlPath = urlPath + 'index.html';
+ }
let encodedPathParts = encodeUrlPathToLocalPathParts(urlPath);
const projectPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(this._project.id());
const encodedPath = encodedPathParts.join('/');
@@ -150,17 +156,20 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
function encodeUrlPathToLocalPathParts(urlPath) {
const encodedParts = [];
for (const pathPart of fileNamePartsFromUrlPath(urlPath)) {
- if (!pathPart)
+ if (!pathPart) {
continue;
+ }
// encodeURI() escapes all the unsafe filename characters except /:?*
let encodedName = encodeURI(pathPart).replace(/[\/:\?\*]/g, match => '%' + match[0].charCodeAt(0).toString(16));
// Windows does not allow a small set of filenames.
- if (Persistence.NetworkPersistenceManager._reservedFileNames.has(encodedName.toLowerCase()))
+ if (_reservedFileNames.has(encodedName.toLowerCase())) {
encodedName = encodedName.split('').map(char => '%' + char.charCodeAt(0).toString(16)).join('');
+ }
// Windows does not allow the file to end in a space or dot (space should already be encoded).
const lastChar = encodedName.charAt(encodedName.length - 1);
- if (lastChar === '.')
+ if (lastChar === '.') {
encodedName = encodedName.substr(0, encodedName.length - 1) + '%2e';
+ }
encodedParts.push(encodedName);
}
return encodedParts;
@@ -173,10 +182,12 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
function fileNamePartsFromUrlPath(urlPath) {
urlPath = Common.ParsedURL.urlWithoutHash(urlPath);
const queryIndex = urlPath.indexOf('?');
- if (queryIndex === -1)
+ if (queryIndex === -1) {
return urlPath.split('/');
- if (queryIndex === 0)
+ }
+ if (queryIndex === 0) {
return [urlPath];
+ }
const endSection = urlPath.substr(queryIndex);
const parts = urlPath.substr(0, urlPath.length - endSection.length).split('/');
parts[parts.length - 1] += endSection;
@@ -202,8 +213,9 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
*/
_unbind(uiSourceCode) {
const binding = uiSourceCode[this._bindingSymbol];
- if (!binding)
+ if (!binding) {
return;
+ }
delete binding.network[this._bindingSymbol];
delete binding.fileSystem[this._bindingSymbol];
Persistence.persistence.removeBinding(binding);
@@ -214,16 +226,18 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.UISourceCode} fileSystemUISourceCode
*/
async _bind(networkUISourceCode, fileSystemUISourceCode) {
- if (networkUISourceCode[this._bindingSymbol])
+ if (networkUISourceCode[this._bindingSymbol]) {
this._unbind(networkUISourceCode);
- if (fileSystemUISourceCode[this._bindingSymbol])
+ }
+ if (fileSystemUISourceCode[this._bindingSymbol]) {
this._unbind(fileSystemUISourceCode);
+ }
const binding = new Persistence.PersistenceBinding(networkUISourceCode, fileSystemUISourceCode);
networkUISourceCode[this._bindingSymbol] = binding;
fileSystemUISourceCode[this._bindingSymbol] = binding;
Persistence.persistence.addBinding(binding);
const uiSourceCodeOfTruth = networkUISourceCode[this._savingSymbol] ? networkUISourceCode : fileSystemUISourceCode;
- const [content, encoded] =
+ const [{content}, encoded] =
await Promise.all([uiSourceCodeOfTruth.requestContent(), uiSourceCodeOfTruth.contentEncoded()]);
Persistence.persistence.syncContent(uiSourceCodeOfTruth, content, encoded);
}
@@ -247,11 +261,12 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
async saveUISourceCodeForOverrides(uiSourceCode) {
- if (!this.canSaveUISourceCodeForOverrides(uiSourceCode))
+ if (!this.canSaveUISourceCodeForOverrides(uiSourceCode)) {
return;
+ }
uiSourceCode[this._savingSymbol] = true;
let encodedPath = this._encodedPathFromUrl(uiSourceCode.url());
- const content = await uiSourceCode.requestContent();
+ const content = (await uiSourceCode.requestContent()).content || '';
const encoded = await uiSourceCode.contentEncoded();
const lastIndexOfSlash = encodedPath.lastIndexOf('/');
const encodedFileName = encodedPath.substr(lastIndexOfSlash + 1);
@@ -274,10 +289,12 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
*/
_patternForFileSystemUISourceCode(uiSourceCode) {
const relativePathParts = Persistence.FileSystemWorkspaceBinding.relativePath(uiSourceCode);
- if (relativePathParts.length < 2)
+ if (relativePathParts.length < 2) {
return '';
- if (relativePathParts[1] === 'longurls' && relativePathParts.length !== 2)
+ }
+ if (relativePathParts[1] === 'longurls' && relativePathParts.length !== 2) {
return 'http?://' + relativePathParts[0] + '/*';
+ }
return 'http?://' + this._decodeLocalPathToUrlPath(relativePathParts.join('/'));
}
@@ -301,15 +318,18 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
*/
_networkUISourceCodeAdded(uiSourceCode) {
if (uiSourceCode.project().type() !== Workspace.projectTypes.Network ||
- !this._canHandleNetworkUISourceCode(uiSourceCode))
+ !this._canHandleNetworkUISourceCode(uiSourceCode)) {
return;
+ }
const url = Common.ParsedURL.urlWithoutHash(uiSourceCode.url());
this._networkUISourceCodeForEncodedPath.set(this._encodedPathFromUrl(url), uiSourceCode);
- const fileSystemUISourceCode =
- this._project.uiSourceCodeForURL(this._project.fileSystemPath() + '/' + this._encodedPathFromUrl(url));
- if (!fileSystemUISourceCode)
+ const fileSystemUISourceCode = this._project.uiSourceCodeForURL(
+ /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (this._project).fileSystemPath() + '/' +
+ this._encodedPathFromUrl(url));
+ if (!fileSystemUISourceCode) {
return;
+ }
this._bind(uiSourceCode, fileSystemUISourceCode);
}
@@ -317,33 +337,37 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_filesystemUISourceCodeAdded(uiSourceCode) {
- if (!this._active || uiSourceCode.project() !== this._project)
+ if (!this._active || uiSourceCode.project() !== this._project) {
return;
+ }
this._updateInterceptionPatterns();
const relativePath = Persistence.FileSystemWorkspaceBinding.relativePath(uiSourceCode);
const networkUISourceCode = this._networkUISourceCodeForEncodedPath.get(relativePath.join('/'));
- if (networkUISourceCode)
+ if (networkUISourceCode) {
this._bind(networkUISourceCode, uiSourceCode);
+ }
}
_updateInterceptionPatterns() {
this._updateInterceptionThrottler.schedule(innerUpdateInterceptionPatterns.bind(this));
/**
- * @this {Persistence.NetworkPersistenceManager}
+ * @this {NetworkPersistenceManager}
* @return {!Promise}
*/
function innerUpdateInterceptionPatterns() {
- if (!this._active)
+ if (!this._active) {
return SDK.multitargetNetworkManager.setInterceptionHandlerForPatterns([], this._interceptionHandlerBound);
+ }
const patterns = new Set();
const indexFileName = 'index.html';
for (const uiSourceCode of this._project.uiSourceCodes()) {
const pattern = this._patternForFileSystemUISourceCode(uiSourceCode);
patterns.add(pattern);
- if (pattern.endsWith('/' + indexFileName))
+ if (pattern.endsWith('/' + indexFileName)) {
patterns.add(pattern.substr(0, pattern.length - indexFileName.length));
+ }
}
return SDK.multitargetNetworkManager.setInterceptionHandlerForPatterns(
@@ -366,8 +390,9 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_networkUISourceCodeRemoved(uiSourceCode) {
- if (uiSourceCode.project().type() !== Workspace.projectTypes.Network)
+ if (uiSourceCode.project().type() !== Workspace.projectTypes.Network) {
return;
+ }
this._unbind(uiSourceCode);
this._networkUISourceCodeForEncodedPath.delete(this._encodedPathFromUrl(uiSourceCode.url()));
}
@@ -376,27 +401,31 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_filesystemUISourceCodeRemoved(uiSourceCode) {
- if (uiSourceCode.project() !== this._project)
+ if (uiSourceCode.project() !== this._project) {
return;
+ }
this._updateInterceptionPatterns();
delete uiSourceCode[this._originalResponseContentPromiseSymbol];
this._unbind(uiSourceCode);
}
_setProject(project) {
- if (project === this._project)
+ if (project === this._project) {
return;
+ }
- if (this._project)
+ if (this._project) {
this._project.uiSourceCodes().forEach(this._filesystemUISourceCodeRemoved.bind(this));
+ }
this._project = project;
- if (this._project)
+ if (this._project) {
this._project.uiSourceCodes().forEach(this._filesystemUISourceCodeAdded.bind(this));
+ }
this._updateActiveProject();
- this.dispatchEventToListeners(Persistence.NetworkPersistenceManager.Events.ProjectChanged, this._project);
+ this.dispatchEventToListeners(Events.ProjectChanged, this._project);
}
/**
@@ -404,13 +433,16 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
*/
_onProjectAdded(project) {
if (project.type() !== Workspace.projectTypes.FileSystem ||
- Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides')
+ Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides') {
return;
+ }
const fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(project.id());
- if (!fileSystemPath)
+ if (!fileSystemPath) {
return;
- if (this._project)
+ }
+ if (this._project) {
this._project.remove();
+ }
this._setProject(project);
}
@@ -419,8 +451,9 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
* @param {!Workspace.Project} project
*/
_onProjectRemoved(project) {
- if (project !== this._project)
+ if (project !== this._project) {
return;
+ }
this._setProject(null);
}
@@ -430,12 +463,15 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
*/
async _interceptionHandler(interceptedRequest) {
const method = interceptedRequest.request.method;
- if (!this._active || (method !== 'GET' && method !== 'POST'))
+ if (!this._active || (method !== 'GET' && method !== 'POST')) {
return;
- const path = this._project.fileSystemPath() + '/' + this._encodedPathFromUrl(interceptedRequest.request.url);
+ }
+ const path = /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (this._project).fileSystemPath() +
+ '/' + this._encodedPathFromUrl(interceptedRequest.request.url);
const fileSystemUISourceCode = this._project.uiSourceCodeForURL(path);
- if (!fileSystemUISourceCode)
+ if (!fileSystemUISourceCode) {
return;
+ }
let mimeType = '';
if (interceptedRequest.responseHeaders) {
@@ -446,32 +482,46 @@ Persistence.NetworkPersistenceManager = class extends Common.Object {
if (!mimeType) {
const expectedResourceType = Common.resourceTypes[interceptedRequest.resourceType] || Common.resourceTypes.Other;
mimeType = fileSystemUISourceCode.mimeType();
- if (Common.ResourceType.fromMimeType(mimeType) !== expectedResourceType)
+ if (Common.ResourceType.fromMimeType(mimeType) !== expectedResourceType) {
mimeType = expectedResourceType.canonicalMimeType();
+ }
}
const project =
/** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (fileSystemUISourceCode.project());
fileSystemUISourceCode[this._originalResponseContentPromiseSymbol] =
interceptedRequest.responseBody().then(response => {
- if (response.error || response.content === null)
+ if (response.error || response.content === null) {
return null;
+ }
return response.encoded ? atob(response.content) : response.content;
});
const blob = await project.requestFileBlob(fileSystemUISourceCode);
interceptedRequest.continueRequestWithContent(new Blob([blob], {type: mimeType}));
}
-};
+}
-Persistence.NetworkPersistenceManager._reservedFileNames = new Set([
+export const _reservedFileNames = new Set([
'con', 'prn', 'aux', 'nul', 'com1', 'com2', 'com3', 'com4', 'com5', 'com6', 'com7',
'com8', 'com9', 'lpt1', 'lpt2', 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9'
]);
-Persistence.NetworkPersistenceManager.Events = {
+export const Events = {
ProjectChanged: Symbol('ProjectChanged')
};
-/** @type {!Persistence.NetworkPersistenceManager} */
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.NetworkPersistenceManager = NetworkPersistenceManager;
+
+Persistence.NetworkPersistenceManager._reservedFileNames = _reservedFileNames;
+Persistence.NetworkPersistenceManager.Events = Events;
+
+/** @type {!NetworkPersistenceManager} */
Persistence.networkPersistenceManager;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js
index 53ebe75e759..df2e1b675fd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js
@@ -2,13 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.PersistenceActions = {};
-
/**
* @implements {UI.ContextMenu.Provider}
* @unrestricted
*/
-Persistence.PersistenceActions.ContextMenuProvider = class {
+export class ContextMenuProvider {
/**
* @override
* @param {!Event} event
@@ -18,18 +16,21 @@ Persistence.PersistenceActions.ContextMenuProvider = class {
appendApplicableItems(event, contextMenu, target) {
const contentProvider = /** @type {!Common.ContentProvider} */ (target);
async function saveAs() {
- if (contentProvider instanceof Workspace.UISourceCode)
+ if (contentProvider instanceof Workspace.UISourceCode) {
/** @type {!Workspace.UISourceCode} */ (contentProvider).commitWorkingCopy();
- let content = await contentProvider.requestContent();
- if (await contentProvider.contentEncoded())
+ }
+ let content = (await contentProvider.requestContent()).content || '';
+ if (await contentProvider.contentEncoded()) {
content = window.atob(content);
+ }
const url = contentProvider.contentURL();
Workspace.fileManager.save(url, /** @type {string} */ (content), true);
Workspace.fileManager.close(url);
}
- if (contentProvider.contentType().isDocumentOrScriptOrStyleSheet())
+ if (contentProvider.contentType().isDocumentOrScriptOrStyleSheet()) {
contextMenu.saveSection().appendItem(Common.UIString('Save as...'), saveAs);
+ }
// Retrieve uiSourceCode by URL to pick network resources everywhere.
const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(contentProvider.contentURL());
@@ -47,7 +48,18 @@ Persistence.PersistenceActions.ContextMenuProvider = class {
if (fileURL.startsWith('file://')) {
const path = Common.ParsedURL.urlToPlatformPath(fileURL, Host.isWin());
contextMenu.revealSection().appendItem(
- Common.UIString('Open in containing folder'), () => InspectorFrontendHost.showItemInFolder(path));
+ Common.UIString('Open in containing folder'), () => Host.InspectorFrontendHost.showItemInFolder(path));
}
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+Persistence.PersistenceActions = {};
+
+/** @constructor */
+Persistence.PersistenceActions.ContextMenuProvider = ContextMenuProvider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/Persistence.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceImpl.js
index a1154558d65..b15dda94f6d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/Persistence.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceImpl.js
@@ -5,7 +5,7 @@
/**
* @unrestricted
*/
-Persistence.Persistence = class extends Common.Object {
+export default class PersistenceImpl extends Common.Object {
/**
* @param {!Workspace.Workspace} workspace
* @param {!Bindings.BreakpointManager} breakpointManager
@@ -17,8 +17,8 @@ Persistence.Persistence = class extends Common.Object {
/** @type {!Map<string, number>} */
this._filePathPrefixesToBindingCount = new Map();
- /** @type {!Multimap<!Workspace.UISourceCode, function()>} */
- this._subscribedBindingEventListeners = new Multimap();
+ /** @type {!Platform.Multimap<!Workspace.UISourceCode, function()>} */
+ this._subscribedBindingEventListeners = new Platform.Multimap();
const linkDecorator = new Persistence.PersistenceUtils.LinkDecorator(this);
Components.Linkifier.setLinkDecorator(linkDecorator);
@@ -39,39 +39,39 @@ Persistence.Persistence = class extends Common.Object {
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
addBinding(binding) {
this._innerAddBinding(binding);
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
addBindingForTest(binding) {
this._innerAddBinding(binding);
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
removeBinding(binding) {
this._innerRemoveBinding(binding);
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
removeBindingForTest(binding) {
this._innerRemoveBinding(binding);
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
_innerAddBinding(binding) {
- binding.network[Persistence.Persistence._binding] = binding;
- binding.fileSystem[Persistence.Persistence._binding] = binding;
+ binding.network[_binding] = binding;
+ binding.fileSystem[_binding] = binding;
binding.fileSystem.forceLoadOnCheckContent();
@@ -100,21 +100,22 @@ Persistence.Persistence = class extends Common.Object {
this._notifyBindingEvent(binding.network);
this._notifyBindingEvent(binding.fileSystem);
- this.dispatchEventToListeners(Persistence.Persistence.Events.BindingCreated, binding);
+ this.dispatchEventToListeners(Events.BindingCreated, binding);
}
/**
- * @param {!Persistence.PersistenceBinding} binding
+ * @param {!PersistenceBinding} binding
*/
_innerRemoveBinding(binding) {
- if (binding.network[Persistence.Persistence._binding] !== binding)
+ if (binding.network[_binding] !== binding) {
return;
+ }
console.assert(
- binding.network[Persistence.Persistence._binding] === binding.fileSystem[Persistence.Persistence._binding],
+ binding.network[_binding] === binding.fileSystem[_binding],
'ERROR: inconsistent binding for networkURL ' + binding.network.url());
- binding.network[Persistence.Persistence._binding] = null;
- binding.fileSystem[Persistence.Persistence._binding] = null;
+ binding.network[_binding] = null;
+ binding.fileSystem[_binding] = null;
binding.network.removeEventListener(
Workspace.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
@@ -130,15 +131,15 @@ Persistence.Persistence = class extends Common.Object {
this._notifyBindingEvent(binding.network);
this._notifyBindingEvent(binding.fileSystem);
- this.dispatchEventToListeners(Persistence.Persistence.Events.BindingRemoved, binding);
+ this.dispatchEventToListeners(Events.BindingRemoved, binding);
}
/**
* @param {!Persistence.AutomappingStatus} status
*/
_onStatusAdded(status) {
- const binding = new Persistence.PersistenceBinding(status.network, status.fileSystem);
- status[Persistence.Persistence._binding] = binding;
+ const binding = new PersistenceBinding(status.network, status.fileSystem);
+ status[_binding] = binding;
this._innerAddBinding(binding);
}
@@ -146,7 +147,7 @@ Persistence.Persistence = class extends Common.Object {
* @param {!Persistence.AutomappingStatus} status
*/
_onStatusRemoved(status) {
- const binding = /** @type {!Persistence.PersistenceBinding} */ (status[Persistence.Persistence._binding]);
+ const binding = /** @type {!PersistenceBinding} */ (status[_binding]);
this._innerRemoveBinding(binding);
}
@@ -162,14 +163,15 @@ Persistence.Persistence = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_syncWorkingCopy(uiSourceCode) {
- const binding = uiSourceCode[Persistence.Persistence._binding];
- if (!binding || binding[Persistence.Persistence._muteWorkingCopy])
+ const binding = uiSourceCode[_binding];
+ if (!binding || binding[_muteWorkingCopy]) {
return;
+ }
const other = binding.network === uiSourceCode ? binding.fileSystem : binding.network;
if (!uiSourceCode.isDirty()) {
- binding[Persistence.Persistence._muteWorkingCopy] = true;
+ binding[_muteWorkingCopy] = true;
other.resetWorkingCopy();
- binding[Persistence.Persistence._muteWorkingCopy] = false;
+ binding[_muteWorkingCopy] = false;
this._contentSyncedForTest();
return;
}
@@ -178,7 +180,7 @@ Persistence.Persistence = class extends Common.Object {
if (target.type() === SDK.Target.Type.Node) {
const newContent = uiSourceCode.workingCopy();
other.requestContent().then(() => {
- const nodeJSContent = Persistence.Persistence.rewrapNodeJSContent(other, other.workingCopy(), newContent);
+ const nodeJSContent = PersistenceImpl.rewrapNodeJSContent(other, other.workingCopy(), newContent);
setWorkingCopy.call(this, () => nodeJSContent);
});
return;
@@ -188,12 +190,12 @@ Persistence.Persistence = class extends Common.Object {
/**
* @param {function():string} workingCopyGetter
- * @this {Persistence.Persistence}
+ * @this {PersistenceImpl}
*/
function setWorkingCopy(workingCopyGetter) {
- binding[Persistence.Persistence._muteWorkingCopy] = true;
+ binding[_muteWorkingCopy] = true;
other.setWorkingCopyGetter(workingCopyGetter);
- binding[Persistence.Persistence._muteWorkingCopy] = false;
+ binding[_muteWorkingCopy] = false;
this._contentSyncedForTest();
}
}
@@ -213,14 +215,15 @@ Persistence.Persistence = class extends Common.Object {
* @param {boolean} encoded
*/
syncContent(uiSourceCode, newContent, encoded) {
- const binding = uiSourceCode[Persistence.Persistence._binding];
- if (!binding || binding[Persistence.Persistence._muteCommit])
+ const binding = uiSourceCode[_binding];
+ if (!binding || binding[_muteCommit]) {
return;
+ }
const other = binding.network === uiSourceCode ? binding.fileSystem : binding.network;
const target = Bindings.NetworkProject.targetForUISourceCode(binding.network);
if (target.type() === SDK.Target.Type.Node) {
other.requestContent().then(currentContent => {
- const nodeJSContent = Persistence.Persistence.rewrapNodeJSContent(other, currentContent, newContent);
+ const nodeJSContent = PersistenceImpl.rewrapNodeJSContent(other, currentContent.content, newContent);
setContent.call(this, nodeJSContent);
});
return;
@@ -229,12 +232,12 @@ Persistence.Persistence = class extends Common.Object {
/**
* @param {string} newContent
- * @this {Persistence.Persistence}
+ * @this {PersistenceImpl}
*/
function setContent(newContent) {
- binding[Persistence.Persistence._muteCommit] = true;
+ binding[_muteCommit] = true;
other.setContent(newContent, encoded);
- binding[Persistence.Persistence._muteCommit] = false;
+ binding[_muteCommit] = false;
this._contentSyncedForTest();
}
}
@@ -247,19 +250,19 @@ Persistence.Persistence = class extends Common.Object {
*/
static rewrapNodeJSContent(uiSourceCode, currentContent, newContent) {
if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) {
- if (newContent.startsWith(Persistence.Persistence._NodePrefix) &&
- newContent.endsWith(Persistence.Persistence._NodeSuffix)) {
- newContent = newContent.substring(
- Persistence.Persistence._NodePrefix.length, newContent.length - Persistence.Persistence._NodeSuffix.length);
+ if (newContent.startsWith(_NodePrefix) && newContent.endsWith(_NodeSuffix)) {
+ newContent = newContent.substring(_NodePrefix.length, newContent.length - _NodeSuffix.length);
+ }
+ if (currentContent.startsWith(_NodeShebang)) {
+ newContent = _NodeShebang + newContent;
}
- if (currentContent.startsWith(Persistence.Persistence._NodeShebang))
- newContent = Persistence.Persistence._NodeShebang + newContent;
} else {
- if (newContent.startsWith(Persistence.Persistence._NodeShebang))
- newContent = newContent.substring(Persistence.Persistence._NodeShebang.length);
- if (currentContent.startsWith(Persistence.Persistence._NodePrefix) &&
- currentContent.endsWith(Persistence.Persistence._NodeSuffix))
- newContent = Persistence.Persistence._NodePrefix + newContent + Persistence.Persistence._NodeSuffix;
+ if (newContent.startsWith(_NodeShebang)) {
+ newContent = newContent.substring(_NodeShebang.length);
+ }
+ if (currentContent.startsWith(_NodePrefix) && currentContent.endsWith(_NodeSuffix)) {
+ newContent = _NodePrefix + newContent + _NodeSuffix;
+ }
}
return newContent;
}
@@ -286,21 +289,24 @@ Persistence.Persistence = class extends Common.Object {
* @return {boolean}
*/
hasUnsavedCommittedChanges(uiSourceCode) {
- if (this._workspace.hasResourceContentTrackingExtensions())
+ if (this._workspace.hasResourceContentTrackingExtensions()) {
return false;
- if (uiSourceCode.project().canSetFileContent())
+ }
+ if (uiSourceCode.project().canSetFileContent()) {
return false;
- if (uiSourceCode[Persistence.Persistence._binding])
+ }
+ if (uiSourceCode[_binding]) {
return false;
+ }
return !!uiSourceCode.hasCommits();
}
/**
* @param {!Workspace.UISourceCode} uiSourceCode
- * @return {?Persistence.PersistenceBinding}
+ * @return {?PersistenceBinding}
*/
binding(uiSourceCode) {
- return uiSourceCode[Persistence.Persistence._binding] || null;
+ return uiSourceCode[_binding] || null;
}
/**
@@ -323,11 +329,13 @@ Persistence.Persistence = class extends Common.Object {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_notifyBindingEvent(uiSourceCode) {
- if (!this._subscribedBindingEventListeners.has(uiSourceCode))
+ if (!this._subscribedBindingEventListeners.has(uiSourceCode)) {
return;
+ }
const listeners = Array.from(this._subscribedBindingEventListeners.get(uiSourceCode));
- for (const listener of listeners)
+ for (const listener of listeners) {
listener.call(null);
+ }
}
/**
@@ -368,10 +376,11 @@ Persistence.Persistence = class extends Common.Object {
for (const token of filePath.split('/')) {
relative += token + '/';
const count = this._filePathPrefixesToBindingCount.get(relative);
- if (count === 1)
+ if (count === 1) {
this._filePathPrefixesToBindingCount.delete(relative);
- else
+ } else {
this._filePathPrefixesToBindingCount.set(relative, count - 1);
+ }
}
}
@@ -380,21 +389,21 @@ Persistence.Persistence = class extends Common.Object {
* @return {boolean}
*/
filePathHasBindings(filePath) {
- if (!filePath.endsWith('/'))
+ if (!filePath.endsWith('/')) {
filePath += '/';
+ }
return this._filePathPrefixesToBindingCount.has(filePath);
}
-};
-
-Persistence.Persistence._binding = Symbol('Persistence.Binding');
-Persistence.Persistence._muteCommit = Symbol('Persistence.MuteCommit');
-Persistence.Persistence._muteWorkingCopy = Symbol('Persistence.MuteWorkingCopy');
+}
-Persistence.Persistence._NodePrefix = '(function (exports, require, module, __filename, __dirname) { ';
-Persistence.Persistence._NodeSuffix = '\n});';
-Persistence.Persistence._NodeShebang = '#!/usr/bin/env node';
+export const _binding = Symbol('Persistence.Binding');
+export const _muteCommit = Symbol('Persistence.MuteCommit');
+export const _muteWorkingCopy = Symbol('Persistence.MuteWorkingCopy');
+export const _NodePrefix = '(function (exports, require, module, __filename, __dirname) { ';
+export const _NodeSuffix = '\n});';
+export const _NodeShebang = '#!/usr/bin/env node';
-Persistence.Persistence.Events = {
+export const Events = {
BindingCreated: Symbol('BindingCreated'),
BindingRemoved: Symbol('BindingRemoved')
};
@@ -402,7 +411,7 @@ Persistence.Persistence.Events = {
/**
* @unrestricted
*/
-Persistence.PathEncoder = class {
+export class PathEncoder {
constructor() {
/** @type {!Common.CharacterIdMap<string>} */
this._encoder = new Common.CharacterIdMap();
@@ -423,12 +432,12 @@ Persistence.PathEncoder = class {
decode(path) {
return path.split('').map(token => this._encoder.fromChar(token)).join('/');
}
-};
+}
/**
* @unrestricted
*/
-Persistence.PersistenceBinding = class {
+export class PersistenceBinding {
/**
* @param {!Workspace.UISourceCode} network
* @param {!Workspace.UISourceCode} fileSystem
@@ -437,7 +446,30 @@ Persistence.PersistenceBinding = class {
this.network = network;
this.fileSystem = fileSystem;
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.Persistence = PersistenceImpl;
+
+Persistence.Persistence._binding = _binding;
+Persistence.Persistence._muteCommit = _muteCommit;
+Persistence.Persistence._muteWorkingCopy = _muteWorkingCopy;
+Persistence.Persistence._NodePrefix = _NodePrefix;
+Persistence.Persistence._NodeSuffix = _NodeSuffix;
+Persistence.Persistence._NodeShebang = _NodeShebang;
+Persistence.Persistence.Events = Events;
+
+/** @constructor */
+Persistence.PathEncoder = PathEncoder;
+
+/** @constructor */
+Persistence.PersistenceBinding = PersistenceBinding;
-/** @type {!Persistence.Persistence} */
+/** @type {!PersistenceImpl} */
Persistence.persistence;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceUtils.js
index ec923cf2a42..58b16c7a783 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PersistenceUtils.js
@@ -2,19 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.PersistenceUtils = class {
+export default class PersistenceUtils {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {string}
*/
static tooltipForUISourceCode(uiSourceCode) {
const binding = Persistence.persistence.binding(uiSourceCode);
- if (!binding)
+ if (!binding) {
return '';
- if (uiSourceCode === binding.network)
+ }
+ if (uiSourceCode === binding.network) {
return Persistence.FileSystemWorkspaceBinding.tooltipForUISourceCode(binding.fileSystem);
- if (binding.network.contentType().isFromSourceMap())
+ }
+ if (binding.network.contentType().isFromSourceMap()) {
return Common.UIString('Linked to source map: %s', binding.network.url().trimMiddle(150));
+ }
return Common.UIString('Linked to %s', binding.network.url().trimMiddle(150));
}
@@ -25,30 +28,33 @@ Persistence.PersistenceUtils = class {
static iconForUISourceCode(uiSourceCode) {
const binding = Persistence.persistence.binding(uiSourceCode);
if (binding) {
- if (!binding.fileSystem.url().startsWith('file://'))
+ if (!binding.fileSystem.url().startsWith('file://')) {
return null;
+ }
const icon = UI.Icon.create('mediumicon-file-sync');
- icon.title = Persistence.PersistenceUtils.tooltipForUISourceCode(binding.network);
+ icon.title = PersistenceUtils.tooltipForUISourceCode(binding.network);
// TODO(allada) This will not work properly with dark theme.
- if (Persistence.networkPersistenceManager.project() === binding.fileSystem.project())
+ if (Persistence.networkPersistenceManager.project() === binding.fileSystem.project()) {
icon.style.filter = 'hue-rotate(160deg)';
+ }
return icon;
}
if (uiSourceCode.project().type() !== Workspace.projectTypes.FileSystem ||
- !uiSourceCode.url().startsWith('file://'))
+ !uiSourceCode.url().startsWith('file://')) {
return null;
+ }
const icon = UI.Icon.create('mediumicon-file');
- icon.title = Persistence.PersistenceUtils.tooltipForUISourceCode(uiSourceCode);
+ icon.title = PersistenceUtils.tooltipForUISourceCode(uiSourceCode);
return icon;
}
-};
+}
/**
* @extends {Common.Object}
* @implements {Components.LinkDecorator}
*/
-Persistence.PersistenceUtils.LinkDecorator = class extends Common.Object {
+export class LinkDecorator extends Common.Object {
/**
* @param {!Persistence.Persistence} persistence
*/
@@ -72,6 +78,18 @@ Persistence.PersistenceUtils.LinkDecorator = class extends Common.Object {
* @return {?UI.Icon}
*/
linkIcon(uiSourceCode) {
- return Persistence.PersistenceUtils.iconForUISourceCode(uiSourceCode);
+ return PersistenceUtils.iconForUISourceCode(uiSourceCode);
}
-}; \ No newline at end of file
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.PersistenceUtils = PersistenceUtils;
+
+/** @constructor */
+Persistence.PersistenceUtils.LinkDecorator = LinkDecorator; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PlatformFileSystem.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PlatformFileSystem.js
index e37a4e54bee..2276225a6d0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/PlatformFileSystem.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/PlatformFileSystem.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.PlatformFileSystem = class {
+export default class PlatformFileSystem {
/**
* @param {string} path
* @param {string} type
@@ -83,10 +83,10 @@ Persistence.PlatformFileSystem = class {
/**
* @param {string} path
- * @param {function(?string,boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(path, callback) {
- callback(null, false);
+ async requestFileContent(path) {
+ return {error: ls`Unable to read files with this implementation.`, isEncoded: false};
}
/**
@@ -191,4 +191,13 @@ Persistence.PlatformFileSystem = class {
supportsAutomapping() {
throw new Error('Not implemented');
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.PlatformFileSystem = PlatformFileSystem;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/WorkspaceSettingsTab.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/WorkspaceSettingsTab.js
index f0e40db6177..ea4faf1c1b6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/WorkspaceSettingsTab.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/WorkspaceSettingsTab.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Persistence.WorkspaceSettingsTab = class extends UI.VBox {
+export default class WorkspaceSettingsTab extends UI.VBox {
constructor() {
super();
this.registerRequiredCSS('persistence/workspaceSettingsTab.css');
@@ -40,8 +40,9 @@ Persistence.WorkspaceSettingsTab = class extends UI.VBox {
this._mappingViewByPath = new Map();
const fileSystems = Persistence.isolatedFileSystemManager.fileSystems();
- for (let i = 0; i < fileSystems.length; ++i)
+ for (let i = 0; i < fileSystems.length; ++i) {
this._addItem(fileSystems[i]);
+ }
}
/**
@@ -82,12 +83,16 @@ Persistence.WorkspaceSettingsTab = class extends UI.VBox {
*/
_addItem(fileSystem) {
// Support managing only instances of IsolatedFileSystem.
- if (!(fileSystem instanceof Persistence.IsolatedFileSystem))
+ if (!(fileSystem instanceof Persistence.IsolatedFileSystem)) {
return;
+ }
const networkPersistenceProject = Persistence.networkPersistenceManager.project();
if (networkPersistenceProject &&
- Persistence.isolatedFileSystemManager.fileSystem(networkPersistenceProject.fileSystemPath()) === fileSystem)
+ Persistence.isolatedFileSystemManager.fileSystem(
+ /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (networkPersistenceProject)
+ .fileSystemPath()) === fileSystem) {
return;
+ }
const element = this._renderFileSystem(fileSystem);
this._elementByPath.set(fileSystem.path(), element);
@@ -161,4 +166,13 @@ Persistence.WorkspaceSettingsTab = class extends UI.VBox {
element.remove();
}
}
-};
+}
+
+/* Legacy exported object */
+self.Persistence = self.Persistence || {};
+
+/* Legacy exported object */
+Persistence = Persistence || {};
+
+/** @constructor */
+Persistence.WorkspaceSettingsTab = WorkspaceSettingsTab;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/module.json b/chromium/third_party/blink/renderer/devtools/front_end/persistence/module.json
index 9b3b1c9467c..7e5295781a0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/module.json
@@ -43,14 +43,16 @@
"className": "Persistence.PersistenceActions.ContextMenuProvider"
}
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "persistence.js",
"PlatformFileSystem.js",
"IsolatedFileSystem.js",
"IsolatedFileSystemManager.js",
"FileSystemWorkspaceBinding.js",
"Automapping.js",
"NetworkPersistenceManager.js",
- "Persistence.js",
+ "PersistenceImpl.js",
"PersistenceActions.js",
"PersistenceUtils.js",
"EditFileSystemView.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence.js b/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence.js
new file mode 100644
index 00000000000..56bbe274837
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence.js
@@ -0,0 +1,31 @@
+// 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 './PlatformFileSystem.js';
+
+import * as Automapping from './Automapping.js';
+import * as EditFileSystemView from './EditFileSystemView.js';
+import * as FileSystemWorkspaceBinding from './FileSystemWorkspaceBinding.js';
+import * as IsolatedFileSystem from './IsolatedFileSystem.js';
+import * as IsolatedFileSystemManager from './IsolatedFileSystemManager.js';
+import * as NetworkPersistenceManager from './NetworkPersistenceManager.js';
+import * as PersistenceActions from './PersistenceActions.js';
+import * as Persistence from './PersistenceImpl.js';
+import * as PersistenceUtils from './PersistenceUtils.js';
+import * as PlatformFileSystem from './PlatformFileSystem.js';
+import * as WorkspaceSettingsTab from './WorkspaceSettingsTab.js';
+
+export {
+ Automapping,
+ EditFileSystemView,
+ FileSystemWorkspaceBinding,
+ IsolatedFileSystem,
+ IsolatedFileSystemManager,
+ NetworkPersistenceManager,
+ Persistence,
+ PersistenceActions,
+ PersistenceUtils,
+ PlatformFileSystem,
+ WorkspaceSettingsTab,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
index 5bd615deda5..3e38b7152f1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/persistence/persistence_strings.grdp
@@ -9,15 +9,27 @@
<message name="IDS_DEVTOOLS_03ad5ac9c1a313e19064670f92981353" desc="Text of the add button in Workspace Settings Tab of the Workspace settings in Settings">
Add folder…
</message>
+ <message name="IDS_DEVTOOLS_10573b873d2fa5a365d558a45e328e47" desc="A tag of Enable Local Overrides setting that can be searched in the command menu">
+ request
+ </message>
<message name="IDS_DEVTOOLS_14f221497f99c10993cd293628adeefd" desc="A context menu item in the Persistence Actions of the Workspace settings in Settings">
Open in containing folder
</message>
<message name="IDS_DEVTOOLS_17d5f7dcd4ef6b9702a8b2ac7d237e5b" desc="Title of a setting under the Persistence category that can be invoked through the Command Menu">
Enable override network requests
</message>
+ <message name="IDS_DEVTOOLS_1c02bb01227ee7caca379039bfc5e85d" desc="Assertion error message when failing to load a file">
+ Unable to read files with this implementation.
+ </message>
+ <message name="IDS_DEVTOOLS_1c5594ed57047449210c4b4d803f7787" desc="A tag of Enable Local Overrides setting that can be searched in the command menu">
+ interception
+ </message>
<message name="IDS_DEVTOOLS_25ee7702f0b5dbe737d8f0f2ba3ce591" desc="A context menu item in the Persistence Actions of the Workspace settings in Settings">
Save for overrides
</message>
+ <message name="IDS_DEVTOOLS_3f117c10eacf50ac452cf2bea0295951" desc="Error message when failing to load a file">
+ Unknown error reading file: <ph name="PATH"><ex>c:\dir\file.js</ex>$1s</ph>
+ </message>
<message name="IDS_DEVTOOLS_57e01423e2b182ada052707cbb8d7b3a" desc="Error message when a file system path is an empty string.">
Enter a path
</message>
@@ -30,6 +42,12 @@
<message name="IDS_DEVTOOLS_62def4422771353f5e30763d92474b43" desc="Text in Persistence Utils of the Workspace settings in Settings">
Linked to source map: <ph name="BINDING_NETWORK_URL___TRIMMIDDLE_____">$1s<ex>example.url</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_6b8a6e4cad0454926dd845d32b525f04" desc="Error message when reading a file.">
+ Can&apos;t read file: <ph name="PATH"><ex>c:\dir\file.js</ex>$1s</ph>: <ph name="READER_ERROR"><ex>Underlying error</ex>$2s</ph>
+ </message>
+ <message name="IDS_DEVTOOLS_7b4639e8d528d7a3eedafe23e9cdfee1" desc="A tag of Enable Local Overrides setting that can be searched in the command menu">
+ rewrite
+ </message>
<message name="IDS_DEVTOOLS_8cf868306a4e5f1b685566867ff0e31d" desc="Error message when a file system path is identical to an existing path.">
Enter a unique path
</message>
@@ -39,9 +57,6 @@
<message name="IDS_DEVTOOLS_ab130072b340b847d8d45ec45d191c3b" desc="Text of a DOM element in Workspace Settings Tab of the Workspace settings in Settings">
Mappings are inferred automatically.
</message>
- <message name="IDS_DEVTOOLS_afb4ea732ebcf8bd51a3d99a1b8909a8" desc="Text in Isolated File System of the Workspace settings in Settings">
- Linked to <ph name="PATH">$1s<ex>example.url</ex></ph>
- </message>
<message name="IDS_DEVTOOLS_cf703cce77386955bfbff86f6ad9be03" desc="Text in Isolated File System Manager of the Workspace settings in Settings">
Unable to add filesystem: <ph name="ERRORMESSAGE">$1s<ex>folder does not exist</ex></ph>
</message>
@@ -54,8 +69,11 @@
<message name="IDS_DEVTOOLS_e2b63f5cab4f80fb6745f2f941105371" desc="Title of a setting under the Persistence category in Settings">
Enable Local Overrides
</message>
- <message name="IDS_DEVTOOLS_ec211f7c20af43e742bf2570c3cb84f9" desc="Text of add button in Edit File System View of the Workspace settings in Settings">
- Add
+ <message name="IDS_DEVTOOLS_e3b3f56615d1e5f2608d2f1130a7ef54" desc="A tag of Enable Local Overrides setting that can be searched in the command menu">
+ override
+ </message>
+ <message name="IDS_DEVTOOLS_ef1e313a589a406cf35afebfba156df5" desc="Error message when reading a remote blob">
+ Blob could not be loaded.
</message>
<message name="IDS_DEVTOOLS_fddede572fa09e1b1bb28504d8c43343" desc="Text in Edit File System View of the Workspace settings in Settings">
Folder path
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/platform/module.json b/chromium/third_party/blink/renderer/devtools/front_end/platform/module.json
index cbb4b4cf4e7..592d1b14ed4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/platform/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/platform/module.json
@@ -1,7 +1,8 @@
{
"dependencies": [
],
- "scripts": [
+ "scripts": [],
+ "modules": [
"utilities.js"
]
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js b/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
index 1ae145f08f3..775c33d1652 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
@@ -95,13 +95,15 @@ String.prototype.escapeCharacters = function(chars) {
}
}
- if (!foundChar)
+ if (!foundChar) {
return String(this);
+ }
let result = '';
for (let i = 0; i < this.length; ++i) {
- if (chars.indexOf(this.charAt(i)) !== -1)
+ if (chars.indexOf(this.charAt(i)) !== -1) {
result += '\\';
+ }
result += this.charAt(i);
}
@@ -131,10 +133,12 @@ String.filterRegex = function(query) {
let regexString = '';
for (let i = 0; i < query.length; ++i) {
let c = query.charAt(i);
- if (toEscape.indexOf(c) !== -1)
+ if (toEscape.indexOf(c) !== -1) {
c = '\\' + c;
- if (i)
+ }
+ if (i) {
regexString += '[^\\0' + c + ']*';
+ }
regexString += c;
}
return new RegExp(regexString, 'i');
@@ -148,19 +152,22 @@ String.escapeInvalidUnicodeCharacters = function(text) {
if (!String._invalidCharactersRegExp) {
// Escape orphan surrogates and invalid characters.
let invalidCharacters = '';
- for (let i = 0xfffe; i <= 0x10ffff; i += 0x10000)
+ for (let i = 0xfffe; i <= 0x10ffff; i += 0x10000) {
invalidCharacters += String.fromCodePoint(i, i + 1);
+ }
String._invalidCharactersRegExp = new RegExp(`[${invalidCharacters}\uD800-\uDFFF\uFDD0-\uFDEF]`, 'gu');
}
let result = '';
let lastPos = 0;
while (true) {
const match = String._invalidCharactersRegExp.exec(text);
- if (!match)
+ if (!match) {
break;
+ }
result += text.substring(lastPos, match.index) + '\\u' + text.charCodeAt(match.index).toString(16);
- if (match.index + 1 < String._invalidCharactersRegExp.lastIndex)
+ if (match.index + 1 < String._invalidCharactersRegExp.lastIndex) {
result += '\\u' + text.charCodeAt(match.index + 1).toString(16);
+ }
lastPos = String._invalidCharactersRegExp.lastIndex;
}
return result + text.substring(lastPos);
@@ -201,16 +208,18 @@ String.prototype.collapseWhitespace = function() {
* @return {string}
*/
String.prototype.trimMiddle = function(maxLength) {
- if (this.length <= maxLength)
+ if (this.length <= maxLength) {
return String(this);
+ }
let leftHalf = maxLength >> 1;
let rightHalf = maxLength - leftHalf - 1;
if (this.codePointAt(this.length - rightHalf - 1) >= 0x10000) {
--rightHalf;
++leftHalf;
}
- if (leftHalf > 0 && this.codePointAt(leftHalf - 1) >= 0x10000)
+ if (leftHalf > 0 && this.codePointAt(leftHalf - 1) >= 0x10000) {
--leftHalf;
+ }
return this.substr(0, leftHalf) + '\u2026' + this.substr(this.length - rightHalf, rightHalf);
};
@@ -218,9 +227,10 @@ String.prototype.trimMiddle = function(maxLength) {
* @param {number} maxLength
* @return {string}
*/
-String.prototype.trimEnd = function(maxLength) {
- if (this.length <= maxLength)
+String.prototype.trimEndWithMaxLength = function(maxLength) {
+ if (this.length <= maxLength) {
return String(this);
+ }
return this.substr(0, maxLength - 1) + '\u2026';
};
@@ -231,8 +241,9 @@ String.prototype.trimEnd = function(maxLength) {
String.prototype.trimURL = function(baseURLDomain) {
let result = this.replace(/^(https|http|file):\/\//i, '');
if (baseURLDomain) {
- if (result.toLowerCase().startsWith(baseURLDomain.toLowerCase()))
+ if (result.toLowerCase().startsWith(baseURLDomain.toLowerCase())) {
result = result.substr(baseURLDomain.length);
+ }
}
return result;
};
@@ -249,10 +260,12 @@ String.prototype.toTitleCase = function() {
* @return {number}
*/
String.prototype.compareTo = function(other) {
- if (this > other)
+ if (this > other) {
return 1;
- if (this < other)
+ }
+ if (this < other) {
return -1;
+ }
return 0;
};
@@ -261,8 +274,9 @@ String.prototype.compareTo = function(other) {
*/
String.prototype.removeURLFragment = function() {
let fragmentIndex = this.indexOf('#');
- if (fragmentIndex === -1)
+ if (fragmentIndex === -1) {
fragmentIndex = this.length;
+ }
return this.substring(0, fragmentIndex);
};
@@ -271,8 +285,9 @@ String.prototype.removeURLFragment = function() {
* @return {number}
*/
String.hashCode = function(string) {
- if (!string)
+ if (!string) {
return 0;
+ }
// Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in
// eingeschränkten Branchingprogrammmodellen" by Woelfe.
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
@@ -315,8 +330,9 @@ String.prototype.toBase64 = function() {
const data = encoder.encode(this.toString());
const n = data.length;
let encoded = '';
- if (n === 0)
+ if (n === 0) {
return encoded;
+ }
let shift;
let v = 0;
for (let i = 0; i < n; i++) {
@@ -328,10 +344,11 @@ String.prototype.toBase64 = function() {
v = 0;
}
}
- if (shift === 0)
+ if (shift === 0) {
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), 61, 61);
- else if (shift === 1)
+ } else if (shift === 1) {
encoded += String.fromCharCode(encodeBits(v >>> 18 & 63), encodeBits(v >>> 12 & 63), encodeBits(v >>> 6 & 63), 61);
+ }
return encoded;
};
@@ -345,31 +362,38 @@ String.naturalOrderComparator = function(a, b) {
let chunka, chunkb, anum, bnum;
while (1) {
if (a) {
- if (!b)
+ if (!b) {
return 1;
+ }
} else {
- if (b)
+ if (b) {
return -1;
- else
+ } else {
return 0;
+ }
}
chunka = a.match(chunk)[0];
chunkb = b.match(chunk)[0];
anum = !isNaN(chunka);
bnum = !isNaN(chunkb);
- if (anum && !bnum)
+ if (anum && !bnum) {
return -1;
- if (bnum && !anum)
+ }
+ if (bnum && !anum) {
return 1;
+ }
if (anum && bnum) {
const diff = chunka - chunkb;
- if (diff)
+ if (diff) {
return diff;
+ }
if (chunka.length !== chunkb.length) {
- if (! + chunka && ! + chunkb) // chunks are strings of all 0s (special case)
+ if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case)
+ {
return chunka.length - chunkb.length;
- else
+ } else {
return chunkb.length - chunka.length;
+ }
}
} else if (chunka !== chunkb) {
return (chunka < chunkb) ? -1 : 1;
@@ -387,8 +411,9 @@ String.naturalOrderComparator = function(a, b) {
String.caseInsensetiveComparator = function(a, b) {
a = a.toUpperCase();
b = b.toUpperCase();
- if (a === b)
+ if (a === b) {
return 0;
+ }
return a > b ? 1 : -1;
};
@@ -399,10 +424,11 @@ String.caseInsensetiveComparator = function(a, b) {
* @return {number}
*/
Number.constrain = function(num, min, max) {
- if (num < min)
+ if (num < min) {
num = min;
- else if (num > max)
+ } else if (num > max) {
num = max;
+ }
return num;
};
@@ -412,10 +438,11 @@ Number.constrain = function(num, min, max) {
* @return {number}
*/
Number.gcd = function(a, b) {
- if (b === 0)
+ if (b === 0) {
return a;
- else
+ } else {
return Number.gcd(b, a % b);
+ }
};
/**
@@ -423,8 +450,9 @@ Number.gcd = function(a, b) {
* @return {string}
*/
Number.toFixedIfFloating = function(value) {
- if (!value || isNaN(value))
+ if (!value || isNaN(value)) {
return value;
+ }
const number = Number(value);
return number % 1 ? number.toFixed(3) : String(number);
};
@@ -461,15 +489,17 @@ Object.defineProperty(Array.prototype, 'remove', {
*/
value: function(value, firstOnly) {
let index = this.indexOf(value);
- if (index === -1)
+ if (index === -1) {
return false;
+ }
if (firstOnly) {
this.splice(index, 1);
return true;
}
for (let i = index + 1, n = this.length; i < n; ++i) {
- if (this[i] !== value)
+ if (this[i] !== value) {
this[index++] = this[i];
+ }
}
this.length = index;
return true;
@@ -483,8 +513,9 @@ Object.defineProperty(Array.prototype, 'pushAll', {
* @template T
*/
value: function(array) {
- for (let i = 0; i < array.length; ++i)
+ for (let i = 0; i < array.length; ++i) {
this.push(array[i]);
+ }
}
});
@@ -497,8 +528,9 @@ Object.defineProperty(Array.prototype, 'rotate', {
*/
value: function(index) {
const result = [];
- for (let i = index; i < index + this.length; ++i)
+ for (let i = index; i < index + this.length; ++i) {
result.push(this[i % this.length]);
+ }
return result;
}
});
@@ -565,19 +597,23 @@ const sortRange = {
*/
value: function(comparator, leftBound, rightBound, sortWindowLeft, sortWindowRight) {
function quickSortRange(array, comparator, left, right, sortWindowLeft, sortWindowRight) {
- if (right <= left)
+ if (right <= left) {
return;
+ }
const pivotIndex = Math.floor(Math.random() * (right - left)) + left;
const pivotNewIndex = array.partition(comparator, left, right, pivotIndex);
- if (sortWindowLeft < pivotNewIndex)
+ if (sortWindowLeft < pivotNewIndex) {
quickSortRange(array, comparator, left, pivotNewIndex - 1, sortWindowLeft, sortWindowRight);
- if (pivotNewIndex < sortWindowRight)
+ }
+ if (pivotNewIndex < sortWindowRight) {
quickSortRange(array, comparator, pivotNewIndex + 1, right, sortWindowLeft, sortWindowRight);
+ }
}
- if (leftBound === 0 && rightBound === (this.length - 1) && sortWindowLeft === 0 && sortWindowRight >= rightBound)
+ if (leftBound === 0 && rightBound === (this.length - 1) && sortWindowLeft === 0 && sortWindowRight >= rightBound) {
this.sort(comparator);
- else
+ } else {
quickSortRange(this, comparator, leftBound, rightBound, sortWindowLeft, sortWindowRight);
+ }
return this;
}
};
@@ -611,10 +647,11 @@ Object.defineProperty(Array.prototype, 'lowerBound', {
let r = right !== undefined ? right : this.length;
while (l < r) {
const m = (l + r) >> 1;
- if (comparator(object, this[m]) > 0)
+ if (comparator(object, this[m]) > 0) {
l = m + 1;
- else
+ } else {
r = m;
+ }
}
return r;
}
@@ -646,10 +683,11 @@ Object.defineProperty(Array.prototype, 'upperBound', {
let r = right !== undefined ? right : this.length;
while (l < r) {
const m = (l + r) >> 1;
- if (comparator(object, this[m]) >= 0)
+ if (comparator(object, this[m]) >= 0) {
l = m + 1;
- else
+ } else {
r = m;
+ }
}
return r;
}
@@ -688,8 +726,9 @@ Object.defineProperty(Array.prototype, 'select', {
*/
value: function(field) {
const result = new Array(this.length);
- for (let i = 0; i < this.length; ++i)
+ for (let i = 0; i < this.length; ++i) {
result[i] = this[i][field];
+ }
return result;
}
});
@@ -720,18 +759,23 @@ Object.defineProperty(Array.prototype, 'peekLast', {
let j = 0;
while (i < array1.length && j < array2.length) {
const compareValue = comparator(array1[i], array2[j]);
- if (mergeNotIntersect || !compareValue)
+ if (mergeNotIntersect || !compareValue) {
result.push(compareValue <= 0 ? array1[i] : array2[j]);
- if (compareValue <= 0)
+ }
+ if (compareValue <= 0) {
i++;
- if (compareValue >= 0)
+ }
+ if (compareValue >= 0) {
j++;
+ }
}
if (mergeNotIntersect) {
- while (i < array1.length)
+ while (i < array1.length) {
result.push(array1[i++]);
- while (j < array2.length)
+ }
+ while (j < array2.length) {
result.push(array2[j++]);
+ }
}
return result;
}
@@ -781,12 +825,14 @@ String.tokenizeFormatString = function(format, formatters) {
const tokens = [];
function addStringToken(str) {
- if (!str)
+ if (!str) {
return;
- if (tokens.length && tokens[tokens.length - 1].type === 'string')
+ }
+ if (tokens.length && tokens[tokens.length - 1].type === 'string') {
tokens[tokens.length - 1].value += str;
- else
+ } else {
tokens.push({type: 'string', value: str});
+ }
}
function addSpecifierToken(specifier, precision, substitutionIndex) {
@@ -800,11 +846,13 @@ String.tokenizeFormatString = function(format, formatters) {
['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
const type = types[Math.floor(code / 10)];
- if (!type)
+ if (!type) {
return;
+ }
const color = colors[type][code % 10];
- if (!color)
+ if (!color) {
return;
+ }
tokens.push({
type: 'specifier',
specifier: 'c',
@@ -818,16 +866,18 @@ String.tokenizeFormatString = function(format, formatters) {
new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
for (let match = re.exec(format); !!match; match = re.exec(format)) {
const matchStart = match.index;
- if (matchStart > textStart)
+ if (matchStart > textStart) {
addStringToken(format.substring(textStart, matchStart));
+ }
if (match[0] === '%%') {
addStringToken('%');
} else if (match[0].startsWith('%')) {
// eslint-disable-next-line no-unused-vars
const [_, substitionString, precisionString, specifierString] = match;
- if (substitionString && Number(substitionString) > 0)
+ if (substitionString && Number(substitionString) > 0) {
substitutionIndex = Number(substitionString) - 1;
+ }
const precision = precisionString ? Number(precisionString) : -1;
addSpecifierToken(specifierString, precision, substitutionIndex);
++substitutionIndex;
@@ -853,8 +903,9 @@ String.standardFormatters = {
* @return {number}
*/
f: function(substitution, token) {
- if (substitution && token.precision > -1)
+ if (substitution && token.precision > -1) {
substitution = substitution.toFixed(token.precision);
+ }
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
},
@@ -892,8 +943,9 @@ String.vsprintf = function(format, substitutions) {
* @template T, Q
*/
String.format = function(format, substitutions, formatters, initialValue, append, tokenizedFormat) {
- if (!format || ((!substitutions || !substitutions.length) && format.search(/\u001b\[(\d+)m/) === -1))
+ if (!format || ((!substitutions || !substitutions.length) && format.search(/\u001b\[(\d+)m/) === -1)) {
return {formattedResult: append(initialValue, format), unusedSubstitutions: substitutions};
+ }
function prettyFunctionName() {
return 'String.format("' + format + '", "' + Array.prototype.join.call(substitutions, '", "') + '")';
@@ -934,8 +986,9 @@ String.format = function(format, substitutions, formatters, initialValue, append
continue;
}
- if (!token.value)
+ if (!token.value) {
usedSubstitutionIndexes[token.substitutionIndex] = true;
+ }
if (!(token.specifier in formatters)) {
// Encountered an unsupported format character, treat as a string.
@@ -949,8 +1002,9 @@ String.format = function(format, substitutions, formatters, initialValue, append
const unusedSubstitutions = [];
for (let i = 0; i < substitutions.length; ++i) {
- if (i in usedSubstitutionIndexes)
+ if (i in usedSubstitutionIndexes) {
continue;
+ }
unusedSubstitutions.push(substitutions[i]);
}
@@ -975,8 +1029,9 @@ self.createSearchRegex = function(query, caseSensitive, isRegex) {
}
}
- if (!regexObject)
+ if (!regexObject) {
regexObject = self.createPlainTextSearchRegex(query, regexFlags);
+ }
return regexObject;
};
@@ -992,8 +1047,9 @@ self.createPlainTextSearchRegex = function(query, flags) {
let regex = '';
for (let i = 0; i < query.length; ++i) {
const c = query.charAt(i);
- if (regexSpecialCharacters.indexOf(c) !== -1)
+ if (regexSpecialCharacters.indexOf(c) !== -1) {
regex += '\\';
+ }
regex += c;
}
return new RegExp(regex, flags || '');
@@ -1009,8 +1065,9 @@ self.countRegexMatches = function(regex, content) {
let result = 0;
let match;
while (text && (match = regex.exec(text))) {
- if (match[0].length > 0)
+ if (match[0].length > 0) {
++result;
+ }
text = text.substring(match.index + 1);
}
return result;
@@ -1021,7 +1078,7 @@ self.countRegexMatches = function(regex, content) {
* @return {string}
*/
self.spacesPadding = function(spacesCount) {
- return '\u00a0'.repeat(spacesCount);
+ return '\xA0'.repeat(spacesCount);
};
/**
@@ -1048,8 +1105,9 @@ Set.prototype.valuesArray = function() {
* @template T
*/
Set.prototype.firstValue = function() {
- if (!this.size)
+ if (!this.size) {
return null;
+ }
return this.values().next().value;
};
@@ -1058,8 +1116,9 @@ Set.prototype.firstValue = function() {
* @template T
*/
Set.prototype.addAll = function(iterable) {
- for (const e of iterable)
+ for (const e of iterable) {
this.add(e);
+ }
};
/**
@@ -1069,8 +1128,9 @@ Set.prototype.addAll = function(iterable) {
*/
Set.prototype.containsAll = function(iterable) {
for (const e of iterable) {
- if (!this.has(e))
+ if (!this.has(e)) {
return false;
+ }
}
return true;
};
@@ -1100,10 +1160,10 @@ Map.prototype.keysArray = function() {
};
/**
- * @return {!Multimap<!KEY, !VALUE>}
+ * @return {!Platform.Multimap<!KEY, !VALUE>}
*/
Map.prototype.inverse = function() {
- const result = new Multimap();
+ const result = new Platform.Multimap();
for (const key of this.keys()) {
const value = this.get(key);
result.set(value, key);
@@ -1112,104 +1172,107 @@ Map.prototype.inverse = function() {
};
/**
- * @constructor
* @template K, V
*/
-var Multimap = function() { // eslint-disable-line
- /** @type {!Map.<K, !Set.<!V>>} */
- this._map = new Map();
-};
+const Multimap = class {
+ constructor() {
+ /** @type {!Map.<K, !Set.<!V>>} */
+ this._map = new Map();
+ }
-Multimap.prototype = {
/**
* @param {K} key
* @param {V} value
*/
- set: function(key, value) {
+ set(key, value) {
let set = this._map.get(key);
if (!set) {
set = new Set();
this._map.set(key, set);
}
set.add(value);
- },
+ }
/**
* @param {K} key
* @return {!Set<!V>}
*/
- get: function(key) {
+ get(key) {
return this._map.get(key) || new Set();
- },
+ }
/**
* @param {K} key
* @return {boolean}
*/
- has: function(key) {
+ has(key) {
return this._map.has(key);
- },
+ }
/**
* @param {K} key
* @param {V} value
* @return {boolean}
*/
- hasValue: function(key, value) {
+ hasValue(key, value) {
const set = this._map.get(key);
- if (!set)
+ if (!set) {
return false;
+ }
return set.has(value);
- },
+ }
/**
* @return {number}
*/
get size() {
return this._map.size;
- },
+ }
/**
* @param {K} key
* @param {V} value
* @return {boolean}
*/
- delete: function(key, value) {
+ delete(key, value) {
const values = this.get(key);
- if (!values)
+ if (!values) {
return false;
+ }
const result = values.delete(value);
- if (!values.size)
+ if (!values.size) {
this._map.delete(key);
+ }
return result;
- },
+ }
/**
* @param {K} key
*/
- deleteAll: function(key) {
+ deleteAll(key) {
this._map.delete(key);
- },
+ }
/**
* @return {!Array.<K>}
*/
- keysArray: function() {
+ keysArray() {
return this._map.keysArray();
- },
+ }
/**
* @return {!Array.<!V>}
*/
- valuesArray: function() {
+ valuesArray() {
const result = [];
const keys = this.keysArray();
- for (let i = 0; i < keys.length; ++i)
+ for (let i = 0; i < keys.length; ++i) {
result.pushAll(this.get(keys[i]).valuesArray());
+ }
return result;
- },
+ }
- clear: function() {
+ clear() {
this._map.clear();
}
};
@@ -1223,8 +1286,9 @@ self.loadXHR = function(url) {
function load(successCallback, failureCallback) {
function onReadyStateChanged() {
- if (xhr.readyState !== XMLHttpRequest.DONE)
+ if (xhr.readyState !== XMLHttpRequest.DONE) {
return;
+ }
if (xhr.status !== 200) {
xhr.onreadystatechange = null;
failureCallback(new Error(xhr.status));
@@ -1340,10 +1404,11 @@ self.runOnWindowLoad = function(callback) {
callback();
}
- if (document.readyState === 'complete' || document.readyState === 'interactive')
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
callback();
- else
+ } else {
self.addEventListener('DOMContentLoaded', windowLoaded, false);
+ }
};
const _singletonSymbol = Symbol('singleton');
@@ -1354,8 +1419,9 @@ const _singletonSymbol = Symbol('singleton');
* @return {!T}
*/
self.singleton = function(constructorFunction) {
- if (_singletonSymbol in constructorFunction)
+ if (_singletonSymbol in constructorFunction) {
return constructorFunction[_singletonSymbol];
+ }
const instance = new constructorFunction();
constructorFunction[_singletonSymbol] = instance;
return instance;
@@ -1366,12 +1432,21 @@ self.singleton = function(constructorFunction) {
* @return {number}
*/
self.base64ToSize = function(content) {
- if (!content)
+ if (!content) {
return 0;
+ }
let size = content.length * 3 / 4;
- if (content[content.length - 1] === '=')
+ if (content[content.length - 1] === '=') {
size--;
- if (content.length > 1 && content[content.length - 2] === '=')
+ }
+ if (content.length > 1 && content[content.length - 2] === '=') {
size--;
+ }
return size;
};
+
+self.Platform = self.Platform || {};
+Platform = Platform || {};
+
+/** @constructor */
+Platform.Multimap = Multimap; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/BadgePool.js b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/BadgePool.js
index c5c06a9b0a5..58e2ced637d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/BadgePool.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/BadgePool.js
@@ -13,8 +13,9 @@ ProductRegistry.BadgePool = class {
if (!forceShow) {
this._setting = Common.settings.moduleSetting('product_registry.badges-visible');
this._setting.addChangeListener(this._settingUpdated.bind(this));
- if (this._setting.get())
+ if (this._setting.get()) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ShowedThirdPartyBadges);
+ }
}
}
@@ -74,8 +75,9 @@ ProductRegistry.BadgePool = class {
const entry = registry.entryForUrl(parsedUrl);
if (!entry) {
frame.findCreationCallFrame(callFrame => {
- if (!callFrame.url)
+ if (!callFrame.url) {
return false;
+ }
parsedUrl = new Common.ParsedURL(callFrame.url);
return !!registry.entryForUrl(parsedUrl);
});
@@ -95,15 +97,17 @@ ProductRegistry.BadgePool = class {
const parsedUrl = await this._badgeElements.get(badgeElement)();
const registry = await ProductRegistry.instance();
const entryName = parsedUrl && registry.nameForUrl(parsedUrl);
- if (!entryName)
+ if (!entryName) {
return;
+ }
const tokens = entryName.replace(/[a-z]*/g, '').split(' ');
let label;
- if (tokens.length > 1)
+ if (tokens.length > 1) {
label = tokens[0][0] + tokens[1][0];
- else
+ } else {
label = entryName;
+ }
const iconElement = badgeElement.createChild('span', 'product-registry-badge monospace');
iconElement.setAttribute('data-initial', label.substring(0, 2).toUpperCase());
@@ -115,8 +119,9 @@ ProductRegistry.BadgePool = class {
}
_settingUpdated() {
- for (const badgeElement of this._badgeElements.keys())
+ for (const badgeElement of this._badgeElements.keys()) {
this._renderBadge(badgeElement);
+ }
}
/**
@@ -139,8 +144,9 @@ ProductRegistry.BadgePool = class {
* @param {!Element} badgeElement
*/
async _showPopup(badgeElement) {
- if (!this._badgeElements.has(badgeElement))
+ if (!this._badgeElements.has(badgeElement)) {
return;
+ }
const registry = await ProductRegistry.instance();
const parsedUrl = await this._badgeElements.get(badgeElement)();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/ProductRegistry.js b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/ProductRegistry.js
index dd0183c97ea..92128a7006d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/ProductRegistry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/ProductRegistry.js
@@ -6,8 +6,9 @@
*/
ProductRegistry.instance = function() {
const extension = self.runtime.extension(ProductRegistry.Registry);
- if (extension)
+ if (extension) {
return extension.instance();
+ }
// TODO(tvanderlippe): Remove type-cast once Closure compiler is updated to latest version.
return Promise.resolve(/** @type {!ProductRegistry.Registry} */ (self.singleton(ProductRegistry.RegistryStub)));
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/badge.css b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/badge.css
index 10c9e53a7ff..3b229272e8e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/product_registry/badge.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/product_registry/badge.css
@@ -21,6 +21,10 @@
display: none;
}
+:host-context(.-theme-with-dark-background) .product-registry-badge::before {
+ color: #000;
+}
+
.product-registry-badge-title {
padding-left: 4px;
-} \ No newline at end of file
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/product_registry_impl/ProductRegistryImpl.js b/chromium/third_party/blink/renderer/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
index fb3f4939df0..0a8d28b7475 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/product_registry_impl/ProductRegistryImpl.js
@@ -16,8 +16,9 @@ ProductRegistryImpl.Registry = class {
*/
nameForUrl(parsedUrl) {
const entry = this.entryForUrl(parsedUrl);
- if (entry)
+ if (entry) {
return entry.name;
+ }
return null;
}
@@ -27,8 +28,9 @@ ProductRegistryImpl.Registry = class {
* @return {?ProductRegistry.Registry.ProductEntry}
*/
entryForUrl(parsedUrl) {
- if (parsedUrl.isDataURL() || !parsedUrl.isValid)
+ if (parsedUrl.isDataURL() || !parsedUrl.isValid) {
return null;
+ }
// TODO(allada) This should be expanded to allow paths as as well as domain to find a product.
const productsByDomainHash = ProductRegistryImpl._productsByDomainHash;
// Remove leading www. if it is the only subdomain.
@@ -43,21 +45,25 @@ ProductRegistryImpl.Registry = class {
const prefixes = productsByDomainHash.get(ProductRegistryImpl._hashForDomain(subDomain));
previousIndex = index;
index = nextIndex;
- if (!prefixes)
+ if (!prefixes) {
continue;
+ }
// Exact match domains are always highest priority.
- if ('' in prefixes && domain === subDomain)
+ if ('' in prefixes && domain === subDomain) {
return prefixes[''];
+ }
if (previousSubdomain) {
for (const prefix in prefixes) {
const domainPrefix = previousSubdomain.substr(0, prefix.length);
- if (domainPrefix === prefix && prefix !== '')
+ if (domainPrefix === prefix && prefix !== '') {
return prefixes[prefix];
+ }
}
}
// Process wildcard subdomain if no better match found.
- if (prefixes && '*' in prefixes)
+ if (prefixes && '*' in prefixes) {
return prefixes['*'];
+ }
}
return null;
}
@@ -69,8 +75,9 @@ ProductRegistryImpl.Registry = class {
*/
typeForUrl(parsedUrl) {
const entry = this.entryForUrl(parsedUrl);
- if (entry)
+ if (entry) {
return entry.type;
+ }
return null;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/BottomUpProfileDataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/BottomUpProfileDataGrid.js
index 66e697c7ef3..28a3c5a811b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/BottomUpProfileDataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/BottomUpProfileDataGrid.js
@@ -60,8 +60,9 @@ Profiler.BottomUpProfileDataGridNode = class extends Profiler.ProfileDataGridNod
child.self += focusNode.self;
- if (!totalAccountedFor)
+ if (!totalAccountedFor) {
child.total += focusNode.total;
+ }
} else {
// If not, add it as a true ancestor.
// In heavy mode, we take our visual identity from ancestor node...
@@ -111,21 +112,24 @@ Profiler.BottomUpProfileDataGridNode = class extends Profiler.ProfileDataGridNod
* @param {string} aCallUID
*/
_exclude(aCallUID) {
- if (this._remainingNodeInfos)
+ if (this._remainingNodeInfos) {
this.populate();
+ }
this.save();
const children = this.children;
let index = this.children.length;
- while (index--)
+ while (index--) {
children[index]._exclude(aCallUID);
+ }
const child = this.childrenByCallUID.get(aCallUID);
- if (child)
+ if (child) {
this.merge(child, true);
+ }
}
/**
@@ -134,8 +138,9 @@ Profiler.BottomUpProfileDataGridNode = class extends Profiler.ProfileDataGridNod
restore() {
super.restore();
- if (!this.children.length)
+ if (!this.children.length) {
this.setHasChildren(this._willHaveChildren(this.profileNode));
+ }
}
/**
@@ -193,8 +198,9 @@ Profiler.BottomUpProfileDataGridTree = class extends Profiler.ProfileDataGridTre
for (let index = 0; index < count; ++index) {
const profileNode = profileNodes[index];
- if (!profileNode.UID)
+ if (!profileNode.UID) {
profileNode.UID = ++profileNodeUIDs;
+ }
if (profileNode.parent) {
// The total time of this ancestor is accounted for if we're in any form of recursive cycle.
@@ -241,8 +247,9 @@ Profiler.BottomUpProfileDataGridTree = class extends Profiler.ProfileDataGridTre
* @param {!Profiler.ProfileDataGridNode} profileDataGridNode
*/
focus(profileDataGridNode) {
- if (!profileDataGridNode)
+ if (!profileDataGridNode) {
return;
+ }
this.save();
@@ -255,8 +262,9 @@ Profiler.BottomUpProfileDataGridTree = class extends Profiler.ProfileDataGridTre
focusNode = currentNode;
currentNode = currentNode.parent;
- if (currentNode instanceof Profiler.ProfileDataGridNode)
+ if (currentNode instanceof Profiler.ProfileDataGridNode) {
currentNode._keepOnlyChild(focusNode);
+ }
}
this.children = [focusNode];
@@ -267,8 +275,9 @@ Profiler.BottomUpProfileDataGridTree = class extends Profiler.ProfileDataGridTre
* @param {!Profiler.ProfileDataGridNode} profileDataGridNode
*/
exclude(profileDataGridNode) {
- if (!profileDataGridNode)
+ if (!profileDataGridNode) {
return;
+ }
this.save();
@@ -277,17 +286,20 @@ Profiler.BottomUpProfileDataGridTree = class extends Profiler.ProfileDataGridTre
// If we have a top level node that is excluded, get rid of it completely (not keeping children),
// since bottom up data relies entirely on the root node.
- if (excludedTopLevelChild)
+ if (excludedTopLevelChild) {
this.children.remove(excludedTopLevelChild);
+ }
const children = this.children;
const count = children.length;
- for (let index = 0; index < count; ++index)
+ for (let index = 0; index < count; ++index) {
children[index]._exclude(excludedCallUID);
+ }
- if (this.lastComparator)
+ if (this.lastComparator) {
this.sort(this.lastComparator, true);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileFlameChart.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileFlameChart.js
index b62826580d8..36a227d75cf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileFlameChart.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileFlameChart.js
@@ -215,6 +215,9 @@ Profiler.CPUProfileFlameChart = class extends UI.VBox {
this._mainPane.setTextPadding(2);
this._mainPane.show(this.element);
this._mainPane.addEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onEntrySelected, this);
+ this._mainPane.addEventListener(PerfUI.FlameChart.Events.EntryInvoked, this._onEntryInvoked, this);
+ this._entrySelected = false;
+ this._mainPane.addEventListener(PerfUI.FlameChart.Events.CanvasFocused, this._onEntrySelected, this);
this._overviewPane.addEventListener(PerfUI.OverviewGrid.Events.WindowChanged, this._onWindowChanged, this);
this._dataProvider = dataProvider;
this._searchResults = [];
@@ -248,7 +251,26 @@ Profiler.CPUProfileFlameChart = class extends UI.VBox {
* @param {!Common.Event} event
*/
_onEntrySelected(event) {
- this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntrySelected, event.data);
+ if (event.data) {
+ const eventIndex = Number(event.data);
+ this._mainPane.setSelectedEntry(eventIndex);
+ if (eventIndex === -1) {
+ this._entrySelected = false;
+ } else {
+ this._entrySelected = true;
+ }
+ } else if (!this._entrySelected) {
+ this._mainPane.setSelectedEntry(0);
+ this._entrySelected = true;
+ }
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _onEntryInvoked(event) {
+ this._onEntrySelected(event);
+ this.dispatchEventToListeners(PerfUI.FlameChart.Events.EntryInvoked, event.data);
}
update() {
@@ -269,14 +291,16 @@ Profiler.CPUProfileFlameChart = class extends UI.VBox {
this._searchResults = [];
const entriesCount = this._dataProvider._entryNodes.length;
for (let index = 0; index < entriesCount; ++index) {
- if (this._dataProvider.entryTitle(index).match(matcher))
+ if (this._dataProvider.entryTitle(index).match(matcher)) {
this._searchResults.push(index);
+ }
}
if (this._searchResults.length) {
this._searchResultIndex = this._searchResults.indexOf(selectedEntryIndex);
- if (this._searchResultIndex === -1)
+ if (this._searchResultIndex === -1) {
this._searchResultIndex = jumpBackwards ? this._searchResults.length - 1 : 0;
+ }
this._mainPane.setSelectedEntry(this._searchResults[this._searchResultIndex]);
} else {
this.searchCanceled();
@@ -484,16 +508,18 @@ Profiler.CPUProfileFlameChart.OverviewPane = class extends UI.VBox {
}
_scheduleUpdate() {
- if (this._updateTimerId)
+ if (this._updateTimerId) {
return;
+ }
this._updateTimerId = this.element.window().requestAnimationFrame(this.update.bind(this));
}
update() {
this._updateTimerId = 0;
const timelineData = this._timelineData();
- if (!timelineData)
+ if (!timelineData) {
return;
+ }
this._resetCanvas(
this._overviewContainer.clientWidth, this._overviewContainer.clientHeight - PerfUI.FlameChart.HeaderHeight);
this._overviewCalculator._updateBoundaries(this);
@@ -548,8 +574,9 @@ Profiler.CPUProfileFlameChart.OverviewPane = class extends UI.VBox {
const start = Math.floor((entryStartTimes[entryIndex] - minimumBoundary) * scaleFactor);
const finish =
Math.floor((entryStartTimes[entryIndex] - minimumBoundary + entryTotalTimes[entryIndex]) * scaleFactor);
- for (let x = start; x <= finish; ++x)
+ for (let x = start; x <= finish; ++x) {
drawData[x] = Math.max(drawData[x], entryLevels[entryIndex] + 1);
+ }
}
return drawData;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js
index 7c98db12e8c..ef16a3c99b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js
@@ -113,6 +113,9 @@ Profiler.CPUProfileType = class extends Profiler.ProfileType {
return '.cpuprofile';
}
+ /**
+ * @override
+ */
get buttonTooltip() {
return this._recording ? Common.UIString('Stop CPU profiling') : Common.UIString('Start CPU profiling');
}
@@ -131,10 +134,16 @@ Profiler.CPUProfileType = class extends Profiler.ProfileType {
}
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return Common.UIString('CPU PROFILES');
}
+ /**
+ * @override
+ */
get description() {
return Common.UIString('CPU profiles show where the execution time is spent in your page\'s JavaScript functions.');
}
@@ -152,8 +161,9 @@ Profiler.CPUProfileType = class extends Profiler.ProfileType {
_startRecordingProfile() {
const cpuProfilerModel = UI.context.flavor(SDK.CPUProfilerModel);
- if (this.profileBeingRecorded() || !cpuProfilerModel)
+ if (this.profileBeingRecorded() || !cpuProfilerModel) {
return;
+ }
const profile = new Profiler.CPUProfileHeader(cpuProfilerModel, this);
this.setProfileBeingRecorded(profile);
SDK.targetManager.suspendAllTargets();
@@ -166,8 +176,9 @@ Profiler.CPUProfileType = class extends Profiler.ProfileType {
async _stopRecordingProfile() {
this._recording = false;
- if (!this.profileBeingRecorded() || !this.profileBeingRecorded()._cpuProfilerModel)
+ if (!this.profileBeingRecorded() || !this.profileBeingRecorded()._cpuProfilerModel) {
return;
+ }
const profile = await this.profileBeingRecorded()._cpuProfilerModel.stopRecording();
const recordedProfile = this.profileBeingRecorded();
@@ -271,6 +282,15 @@ Profiler.CPUProfileView.NodeFormatter = class {
/**
* @override
* @param {number} value
+ * @return {string}
+ */
+ formatValueAccessibleText(value) {
+ return this.formatValue(value);
+ }
+
+ /**
+ * @override
+ * @param {number} value
* @param {!Profiler.ProfileDataGridNode} node
* @return {string}
*/
@@ -370,8 +390,9 @@ Profiler.CPUFlameChartDataProvider = class extends Profiler.ProfileFlameChartDat
prepareHighlightedEntryInfo(entryIndex) {
const timelineData = this._timelineData;
const node = this._entryNodes[entryIndex];
- if (!node)
+ if (!node) {
return null;
+ }
const entryInfo = [];
/**
@@ -386,10 +407,12 @@ Profiler.CPUFlameChartDataProvider = class extends Profiler.ProfileFlameChartDat
* @return {string}
*/
function millisecondsToString(ms) {
- if (ms === 0)
+ if (ms === 0) {
return '0';
- if (ms < 1000)
+ }
+ if (ms < 1000) {
return Common.UIString('%.1f\xa0ms', ms);
+ }
return Number.secondsToString(ms / 1000, true);
}
const name = UI.beautifyFunctionName(node.functionName);
@@ -401,13 +424,15 @@ Profiler.CPUFlameChartDataProvider = class extends Profiler.ProfileFlameChartDat
const linkifier = new Components.Linkifier();
const link = linkifier.maybeLinkifyConsoleCallFrame(
this._cpuProfilerModel && this._cpuProfilerModel.target(), node.callFrame);
- if (link)
+ if (link) {
pushEntryInfoRow(ls`URL`, link.textContent);
+ }
linkifier.dispose();
pushEntryInfoRow(ls`Aggregated self time`, Number.secondsToString(node.self / 1000, true));
pushEntryInfoRow(ls`Aggregated total time`, Number.secondsToString(node.total / 1000, true));
- if (node.deoptReason)
+ if (node.deoptReason) {
pushEntryInfoRow(ls`Not optimized`, node.deoptReason);
+ }
return Profiler.ProfileView.buildPopoverTable(entryInfo);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
index 4d614775a01..6cb924f9e94 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
@@ -21,8 +21,9 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
const isNativeProfile = this._profileType.id === Profiler.SamplingNativeHeapProfileType.TypeId ||
this._profileType.id === Profiler.SamplingNativeHeapSnapshotType.TypeId;
- if (isNativeProfile)
+ if (isNativeProfile) {
views.push(Profiler.ProfileView.ViewTypes.Text);
+ }
this.initialize(new Profiler.HeapProfileView.NodeFormatter(this), views);
const profile = new Profiler.SamplingHeapProfileModel(profileHeader._profile || profileHeader.protocolProfile());
@@ -31,7 +32,7 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
this._selectedSizeText = new UI.ToolbarText();
- if (Runtime.experiments.isEnabled('samplingHeapProfilerTimeline')) {
+ if (Root.Runtime.experiments.isEnabled('samplingHeapProfilerTimeline')) {
this._timelineOverview = new Profiler.HeapTimelineOverview();
this._timelineOverview.addEventListener(
Profiler.HeapTimelineOverview.IdsRangeChanged, this._onIdsRangeChanged.bind(this));
@@ -104,8 +105,9 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
}
this._max.push(this._sizes.peekLast());
- if (this._timestamps.peekLast() - this._timestamps[0] > this._totalTime)
+ if (this._timestamps.peekLast() - this._timestamps[0] > this._totalTime) {
this._totalTime *= 2;
+ }
const samples = /** @type {!Profiler.HeapTimelineOverview.Samples} */ ({
sizes: this._sizes,
@@ -158,8 +160,9 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
const modules = this.profile().modules.map(
m => Object.assign({address: BigInt(m.baseAddress), endAddress: BigInt(m.baseAddress) + BigInt(m.size)}, m));
modules.sort((m1, m2) => m1.address > m2.address ? 1 : m1.address < m2.address ? -1 : 0);
- for (const child of sortedChildren)
+ for (const child of sortedChildren) {
printTree(' ', child !== sortedChildren.peekLast(), child);
+ }
text += '\nBinary Images:\n';
for (const module of modules) {
@@ -186,27 +189,31 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
if (addressText) {
const address = BigInt(addressText);
const pos = modules.upperBound(address, (address, module) => address - module.address);
- if (pos > 0 && address < modules[pos - 1].endAddress)
+ if (pos > 0 && address < modules[pos - 1].endAddress) {
module = modules[pos - 1];
+ }
}
const functionName =
(addressText ? node.functionName.substr(addressText.length + 1) : node.functionName) || '???';
text += `${padding}${Math.round(node.total / 1024)} ${functionName} `;
if (module) {
const fileName = /[^/\\]*$/.exec(module.name);
- if (fileName)
+ if (fileName) {
text += `(in ${fileName}) `;
+ }
const offset = BigInt(addressText) - module.address;
text += `load address ${module.baseAddress} + 0x${offset.toString(16)} `;
}
- if (addressText)
+ if (addressText) {
text += `[${addressText}]`;
+ }
text += '\n';
const guideChar = drawGuide ? guides[padding.length / 2 % guides.length] : ' ';
const nextPadding = padding + guideChar + ' ';
const sortedChildren = node.children.sort((a, b) => b.total - a.total);
- for (const child of sortedChildren)
+ for (const child of sortedChildren) {
printTree(nextPadding, child !== sortedChildren.peekLast(), child);
+ }
}
}
};
@@ -248,6 +255,9 @@ Profiler.SamplingHeapProfileTypeBase = class extends Profiler.ProfileType {
return '.heapprofile';
}
+ /**
+ * @override
+ */
get buttonTooltip() {
return this._recording ? ls`Stop heap profiling` : ls`Start heap profiling`;
}
@@ -257,17 +267,19 @@ Profiler.SamplingHeapProfileTypeBase = class extends Profiler.ProfileType {
* @return {boolean}
*/
buttonClicked() {
- if (this._recording)
+ if (this._recording) {
this._stopRecordingProfile();
- else
+ } else {
this._startRecordingProfile();
+ }
return this._recording;
}
_startRecordingProfile() {
const heapProfilerModel = UI.context.flavor(SDK.HeapProfilerModel);
- if (this.profileBeingRecorded() || !heapProfilerModel)
+ if (this.profileBeingRecorded() || !heapProfilerModel) {
return;
+ }
const profileHeader = new Profiler.SamplingHeapProfileHeader(heapProfilerModel, this);
this.setProfileBeingRecorded(profileHeader);
this.addProfile(profileHeader);
@@ -283,8 +295,9 @@ Profiler.SamplingHeapProfileTypeBase = class extends Profiler.ProfileType {
async _stopRecordingProfile() {
this._recording = false;
- if (!this.profileBeingRecorded() || !this.profileBeingRecorded().heapProfilerModel())
+ if (!this.profileBeingRecorded() || !this.profileBeingRecorded().heapProfilerModel()) {
return;
+ }
this.profileBeingRecorded().updateStatus(ls`Stopping\u2026`);
const profile = await this._stopSampling();
@@ -338,10 +351,16 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
this._updateIntervalMs = 200;
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return ls`SAMPLING PROFILES`;
}
+ /**
+ * @override
+ */
get description() {
return ls`Record memory allocations using sampling method.
This profile type has minimal performance overhead and can be used for long running operations.
@@ -353,7 +372,7 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
* @return {boolean}
*/
hasTemporaryView() {
- return Runtime.experiments.isEnabled('samplingHeapProfilerTimeline');
+ return Root.Runtime.experiments.isEnabled('samplingHeapProfilerTimeline');
}
/**
@@ -361,8 +380,9 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
*/
_startSampling() {
this.profileBeingRecorded().heapProfilerModel().startSampling();
- if (Runtime.experiments.isEnabled('samplingHeapProfilerTimeline'))
+ if (Root.Runtime.experiments.isEnabled('samplingHeapProfilerTimeline')) {
this._updateTimer = setTimeout(this._updateStats.bind(this), this._updateIntervalMs);
+ }
}
/**
@@ -378,8 +398,9 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
async _updateStats() {
const profile = await this.profileBeingRecorded().heapProfilerModel().getSamplingProfile();
- if (!this._updateTimer)
+ if (!this._updateTimer) {
return;
+ }
this.dispatchEventToListeners(Profiler.SamplingHeapProfileType.Events.StatsUpdate, profile);
this._updateTimer = setTimeout(this._updateStats.bind(this), this._updateIntervalMs);
}
@@ -387,7 +408,7 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
Profiler.SamplingHeapProfileType.TypeId = 'SamplingHeap';
-/** @enum {symbol} */
+/** @override @suppress {checkPrototypalTypes} @enum {symbol} */
Profiler.SamplingHeapProfileType.Events = {
RecordingStopped: Symbol('RecordingStopped'),
StatsUpdate: Symbol('StatsUpdate')
@@ -402,10 +423,16 @@ Profiler.SamplingNativeHeapProfileType = class extends Profiler.SamplingHeapProf
Profiler.SamplingNativeHeapProfileType.instance = this;
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return ls`NATIVE SAMPLING PROFILES`;
}
+ /**
+ * @override
+ */
get description() {
return ls`Allocation profiles show sampled native memory allocations from the renderer process.`;
}
@@ -447,10 +474,16 @@ Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapPro
return true;
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return ls`NATIVE SNAPSHOTS`;
}
+ /**
+ * @override
+ */
get description() {
return ls`Native memory snapshots show sampled native allocations in the renderer process since start up.
Chrome has to be started with --memlog=all flag. Check flags at chrome://flags`;
@@ -469,11 +502,13 @@ Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapPro
* @return {!Promise}
*/
async _takeSnapshot() {
- if (this.profileBeingRecorded())
+ if (this.profileBeingRecorded()) {
return;
+ }
const heapProfilerModel = UI.context.flavor(SDK.HeapProfilerModel);
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return;
+ }
const profile =
new Profiler.SamplingHeapProfileHeader(heapProfilerModel, this, ls`Snapshot ${this.nextProfileUid()}`);
@@ -485,7 +520,7 @@ Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapPro
const recordedProfile = this.profileBeingRecorded();
if (recordedProfile) {
console.assert(protocolProfile);
- recordedProfile.setProtocolProfile(protocolProfile);
+ recordedProfile.setProtocolProfile(/** @type {!Protocol.Profiler.Profile} */ (protocolProfile));
recordedProfile.updateStatus('');
this.setProfileBeingRecorded(null);
}
@@ -618,8 +653,9 @@ Profiler.SamplingHeapProfileModel = class extends SDK.ProfileTreeModel {
minOrdinal = minOrdinal || 0;
maxOrdinal = maxOrdinal || Infinity;
for (const sample of profile.samples) {
- if (sample.ordinal < minOrdinal || sample.ordinal > maxOrdinal)
+ if (sample.ordinal < minOrdinal || sample.ordinal > maxOrdinal) {
continue;
+ }
const size = nodeIdToSizeMap.get(sample.nodeId) || 0;
nodeIdToSizeMap.set(sample.nodeId, size + sample.size);
}
@@ -640,8 +676,9 @@ Profiler.SamplingHeapProfileModel = class extends SDK.ProfileTreeModel {
const targetNode = targetNodeStack.pop();
targetNode.children = sourceNode.children.map(child => {
const targetChild = new Profiler.SamplingHeapProfileNode(child);
- if (nodeIdToSizeMap)
+ if (nodeIdToSizeMap) {
targetChild.self = nodeIdToSizeMap.get(child.id) || 0;
+ }
return targetChild;
});
sourceNodeStack.pushAll(sourceNode.children);
@@ -686,6 +723,15 @@ Profiler.HeapProfileView.NodeFormatter = class {
/**
* @override
* @param {number} value
+ * @return {string}
+ */
+ formatValueAccessibleText(value) {
+ return ls`${value} bytes`;
+ }
+
+ /**
+ * @override
+ * @param {number} value
* @param {!Profiler.ProfileDataGridNode} node
* @return {string}
*/
@@ -800,8 +846,9 @@ Profiler.HeapFlameChartDataProvider = class extends Profiler.ProfileFlameChartDa
*/
prepareHighlightedEntryInfo(entryIndex) {
const node = this._entryNodes[entryIndex];
- if (!node)
+ if (!node) {
return null;
+ }
const entryInfo = [];
/**
* @param {string} title
@@ -816,8 +863,9 @@ Profiler.HeapFlameChartDataProvider = class extends Profiler.ProfileFlameChartDa
const linkifier = new Components.Linkifier();
const link = linkifier.maybeLinkifyConsoleCallFrame(
this._heapProfilerModel ? this._heapProfilerModel.target() : null, node.callFrame);
- if (link)
+ if (link) {
pushEntryInfoRow(ls`URL`, link.textContent);
+ }
linkifier.dispose();
return Profiler.ProfileView.buildPopoverTable(entryInfo);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
index 0951dd56f8d..a9bfc1d7371 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
@@ -11,7 +11,7 @@ Profiler.HeapProfilerPanel = class extends Profiler.ProfilesPanel {
const registry = Profiler.ProfileTypeRegistry.instance;
const profileTypes =
[registry.heapSnapshotProfileType, registry.trackingHeapSnapshotProfileType, registry.samplingHeapProfileType];
- if (Runtime.experiments.isEnabled('nativeHeapProfiler')) {
+ if (Root.Runtime.experiments.isEnabled('nativeHeapProfiler')) {
profileTypes.push(registry.samplingNativeHeapProfileType);
profileTypes.push(registry.samplingNativeHeapSnapshotRendererType);
profileTypes.push(registry.samplingNativeHeapSnapshotBrowserType);
@@ -26,24 +26,29 @@ Profiler.HeapProfilerPanel = class extends Profiler.ProfilesPanel {
* @param {!Object} target
*/
appendApplicableItems(event, contextMenu, target) {
- if (!(target instanceof SDK.RemoteObject))
+ if (!(target instanceof SDK.RemoteObject)) {
return;
+ }
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
const object = /** @type {!SDK.RemoteObject} */ (target);
- if (!object.objectId)
+ if (!object.objectId) {
return;
+ }
const objectId = /** @type {string} */ (object.objectId);
const heapProfiles = Profiler.ProfileTypeRegistry.instance.heapSnapshotProfileType.getProfiles();
- if (!heapProfiles.length)
+ if (!heapProfiles.length) {
return;
+ }
const heapProfilerModel = object.runtimeModel().heapProfilerModel();
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return;
+ }
/**
* @param {string} viewName
@@ -51,8 +56,9 @@ Profiler.HeapProfilerPanel = class extends Profiler.ProfilesPanel {
*/
function revealInView(viewName) {
heapProfilerModel.snapshotObjectIdForObjectId(objectId).then(result => {
- if (this.isShowing() && result)
+ if (this.isShowing() && result) {
this.showObject(result, viewName);
+ }
});
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
index 51e47f2e679..ee5783d3911 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
@@ -46,8 +46,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
];
for (const info of tooltips) {
const headerCell = this.headerTableHeader(info[0]);
- if (headerCell)
+ if (headerCell) {
headerCell.setAttribute('title', info[1]);
+ }
}
/**
@@ -102,8 +103,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
_disposeAllNodes() {
const children = this.topLevelNodes();
- for (let i = 0, l = children.length; i < l; ++i)
+ for (let i = 0, l = children.length; i < l; ++i) {
children[i].dispose();
+ }
}
/**
@@ -114,8 +116,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
this._nameFilter.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onNameFilterChanged, this);
this.updateVisibleNodes(true);
}
- if (this._populatedAndSorted)
+ if (this._populatedAndSorted) {
this.dispatchEventToListeners(Profiler.HeapSnapshotSortableDataGrid.Events.ContentShown, this);
+ }
}
_sortingComplete() {
@@ -128,8 +131,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
* @override
*/
willHide() {
- if (this._nameFilter)
+ if (this._nameFilter) {
this._nameFilter.removeEventListener(UI.ToolbarInput.Event.TextChanged, this._onNameFilterChanged, this);
+ }
this._clearCurrentHighlight();
}
@@ -142,6 +146,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
contextMenu.revealSection().appendItem(ls`Reveal in Summary view`, () => {
this._dataDisplayDelegate.showObject(node.snapshotNodeId, ls`Summary`);
});
+ if (gridNode.linkElement && !contextMenu.containsTarget(gridNode.linkElement)) {
+ contextMenu.appendApplicableItems(gridNode.linkElement);
+ }
}
resetSortingCache() {
@@ -174,8 +181,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
}
_clearCurrentHighlight() {
- if (!this._highlightedNode)
+ if (!this._highlightedNode) {
return;
+ }
this._highlightedNode.element().classList.remove('highlighted-row');
this._highlightedNode = null;
}
@@ -191,8 +199,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
sortingChanged() {
const sortAscending = this.isSortOrderAscending();
const sortColumnId = this.sortColumnId();
- if (this._lastSortColumnId === sortColumnId && this._lastSortAscending === sortAscending)
+ if (this._lastSortColumnId === sortColumnId && this._lastSortAscending === sortAscending) {
return;
+ }
this._lastSortColumnId = sortColumnId;
this._lastSortAscending = sortAscending;
const sortFields = this._sortFields(sortColumnId, sortAscending);
@@ -201,15 +210,18 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
let field1 = nodeA[sortFields[0]];
let field2 = nodeB[sortFields[0]];
let result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
- if (!sortFields[1])
+ if (!sortFields[1]) {
result = -result;
- if (result !== 0)
+ }
+ if (result !== 0) {
return result;
+ }
field1 = nodeA[sortFields[2]];
field2 = nodeB[sortFields[2]];
result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
- if (!sortFields[3])
+ if (!sortFields[3]) {
result = -result;
+ }
return result;
}
this._performSorting(SortByTwoFields);
@@ -223,8 +235,9 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
for (let i = 0, l = children.length; i < l; ++i) {
const child = children[i];
this.appendChildAfterSorting(child);
- if (child.expanded)
+ if (child.expanded) {
child.sort();
+ }
}
this.recursiveSortingLeave();
}
@@ -240,10 +253,12 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
}
recursiveSortingLeave() {
- if (!this._recursiveSortingDepth)
+ if (!this._recursiveSortingDepth) {
return;
- if (--this._recursiveSortingDepth)
+ }
+ if (--this._recursiveSortingDepth) {
return;
+ }
this.updateVisibleNodes(true);
this.dispatchEventToListeners(Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete);
}
@@ -287,7 +302,7 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
}
};
-/** @enum {symbol} */
+/** @override @suppress {checkPrototypalTypes} @enum {symbol} */
Profiler.HeapSnapshotSortableDataGrid.Events = {
ContentShown: Symbol('ContentShown'),
SortingComplete: Symbol('SortingComplete')
@@ -338,8 +353,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
scrollBottom = Math.max(0, scrollBottom - guardZoneHeight);
let viewPortHeight = scrollHeight - scrollTop - scrollBottom;
// Do nothing if populated nodes still fit the viewport.
- if (!force && scrollTop >= this._topPaddingHeight && scrollBottom >= this._bottomPaddingHeight)
+ if (!force && scrollTop >= this._topPaddingHeight && scrollBottom >= this._bottomPaddingHeight) {
return;
+ }
const hysteresisHeight = 500;
scrollTop -= hysteresisHeight;
viewPortHeight += 2 * hysteresisHeight;
@@ -355,10 +371,11 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
if (selectedNode) {
// Keep selection even if the node is not in the current viewport.
- if (selectedNode.parent)
+ if (selectedNode.parent) {
selectedNode.select(true);
- else
+ } else {
this.selectedNode = selectedNode;
+ }
}
}
@@ -369,8 +386,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
* @return {number}
*/
_addVisibleNodes(parentNode, topBound, bottomBound) {
- if (!parentNode.expanded)
+ if (!parentNode.expanded) {
return 0;
+ }
const children = this.allChildren(parentNode);
let topPadding = 0;
@@ -380,11 +398,13 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
let i = 0;
for (; i < children.length; ++i) {
const child = children[i];
- if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue))
+ if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue)) {
continue;
+ }
const newTop = topPadding + this._nodeHeight(child);
- if (newTop > topBound)
+ if (newTop > topBound) {
break;
+ }
topPadding = newTop;
}
@@ -392,8 +412,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
let position = topPadding;
for (; i < children.length && position < bottomBound; ++i) {
const child = children[i];
- if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue))
+ if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue)) {
continue;
+ }
const hasChildren = child.hasChildren();
child.removeChildren();
child.setHasChildren(hasChildren);
@@ -406,8 +427,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
let bottomPadding = 0;
for (; i < children.length; ++i) {
const child = children[i];
- if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue))
+ if (nameFilterValue && child.filteredOut && child.filteredOut(nameFilterValue)) {
continue;
+ }
bottomPadding += this._nodeHeight(child);
}
@@ -422,11 +444,13 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
*/
_nodeHeight(node) {
let result = node.nodeSelfHeight();
- if (!node.expanded)
+ if (!node.expanded) {
return result;
+ }
const children = this.allChildren(node);
- for (let i = 0; i < children.length; i++)
+ for (let i = 0; i < children.length; i++) {
result += this._nodeHeight(children[i]);
+ }
return result;
}
@@ -439,8 +463,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
const node = /** @type {!Profiler.HeapSnapshotGridNode} */ (pathToReveal.peekLast());
const scrollTop = this.scrollContainer.scrollTop;
const scrollBottom = scrollTop + this.scrollContainer.offsetHeight;
- if (height >= scrollTop && height < scrollBottom)
+ if (height >= scrollTop && height < scrollBottom) {
return Promise.resolve(node);
+ }
const scrollGap = 40;
this.scrollContainer.scrollTop = Math.max(0, height - scrollGap);
@@ -449,8 +474,9 @@ Profiler.HeapSnapshotViewportDataGrid = class extends Profiler.HeapSnapshotSorta
this._scrollToResolveCallback = resolve.bind(null, node);
// Still resolve the promise if it does not scroll for some reason.
this.scrollContainer.window().requestAnimationFrame(() => {
- if (!this._scrollToResolveCallback)
+ if (!this._scrollToResolveCallback) {
return;
+ }
this._scrollToResolveCallback();
this._scrollToResolveCallback = null;
});
@@ -605,8 +631,9 @@ Profiler.HeapSnapshotContainmentDataGrid = class extends Profiler.HeapSnapshotSo
*/
sortingChanged() {
const rootNode = this.rootNode();
- if (rootNode.hasChildren())
+ if (rootNode.hasChildren()) {
rootNode.sort();
+ }
}
};
@@ -666,7 +693,7 @@ Profiler.HeapSnapshotRetainmentDataGrid = class extends Profiler.HeapSnapshotCon
}
};
-/** @enum {symbol} */
+/** @override @suppress {checkPrototypalTypes} @enum {symbol} */
Profiler.HeapSnapshotRetainmentDataGrid.Events = {
ExpandRetainersComplete: Symbol('ExpandRetainersComplete')
};
@@ -722,12 +749,14 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
}
const className = await this.snapshot.nodeClassName(parseInt(id, 10));
- if (!className)
+ if (!className) {
return null;
+ }
const parent = this.topLevelNodes().find(classNode => classNode._name === className);
- if (!parent)
+ if (!parent) {
return null;
+ }
const nodes = await parent.populateNodeBySnapshotObjectId(parseInt(id, 10));
return nodes.length ? this.revealTreeNode(nodes) : null;
@@ -744,8 +773,9 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
*/
setDataSource(snapshot) {
this.snapshot = snapshot;
- if (this._profileIndex === -1)
+ if (this._profileIndex === -1) {
this._populateChildren();
+ }
if (this._objectIdToSelect) {
this.revealObjectByHeapSnapshotId(this._objectIdToSelect);
@@ -804,8 +834,9 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
this._nextRequestedFilter = this._filterInProgress.equals(nodeFilter) ? null : nodeFilter;
return;
}
- if (this._lastFilter && this._lastFilter.equals(nodeFilter))
+ if (this._lastFilter && this._lastFilter.equals(nodeFilter)) {
return;
+ }
this._filterInProgress = nodeFilter;
const aggregates = await this.snapshot.aggregatesWithFilter(nodeFilter);
@@ -956,8 +987,9 @@ Profiler.AllocationDataGrid = class extends Profiler.HeapSnapshotViewportDataGri
this.removeTopLevelNodes();
const root = this.rootNode();
const tops = this._topNodes;
- for (const top of tops)
+ for (const top of tops) {
this.appendNode(root, new Profiler.AllocationGridNode(this, top));
+ }
this.updateVisibleNodes(true);
}
@@ -982,10 +1014,12 @@ Profiler.AllocationDataGrid = class extends Profiler.HeapSnapshotViewportDataGri
* @return {number}
*/
function compare(a, b) {
- if (a[fieldName] > b[fieldName])
+ if (a[fieldName] > b[fieldName]) {
return compareResult;
- if (a[fieldName] < b[fieldName])
+ }
+ if (a[fieldName] < b[fieldName]) {
return -compareResult;
+ }
return 0;
}
return compare;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
index 6806d5503b4..f6269f2244a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
@@ -89,8 +89,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
* @return {!Profiler.HeapSnapshotGridNode.ChildrenProvider}
*/
_provider() {
- if (!this._providerObject)
+ if (!this._providerObject) {
this._providerObject = this.createProvider();
+ }
return this._providerObject;
}
@@ -101,8 +102,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
*/
createCell(columnId) {
const cell = super.createCell(columnId);
- if (this._searchMatched)
+ if (this._searchMatched) {
cell.classList.add('highlight');
+ }
return cell;
}
@@ -123,11 +125,13 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
}
dispose() {
- if (this._providerObject)
+ if (this._providerObject) {
this._providerObject.dispose();
+ }
for (let node = this.children[0]; node; node = node.traverseNextNode(true, this, true)) {
- if (node.dispose)
+ if (node.dispose) {
node.dispose();
+ }
}
}
@@ -215,8 +219,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
* @override
*/
populate() {
- if (this._populated)
+ if (this._populated) {
return;
+ }
this._populated = true;
this._provider().sortAndRewind(this.comparator()).then(() => this._populateChildren());
}
@@ -249,8 +254,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
* @this {Profiler.HeapSnapshotGridNode}
*/
function serializeNextChunk() {
- if (firstNotSerializedPosition >= toPosition)
+ if (firstNotSerializedPosition >= toPosition) {
return;
+ }
const end = Math.min(firstNotSerializedPosition + this._dataGrid.defaultPopulateCount(), toPosition);
this._provider().serializeItemsRange(firstNotSerializedPosition, end).then(childrenRetrieved.bind(this));
firstNotSerializedPosition = end;
@@ -295,10 +301,12 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
insertShowMoreButton.call(this, 0, itemsRange.startPosition, insertionIndex++);
}
this._retrievedChildrenRanges.push({from: itemsRange.startPosition, to: itemsRange.endPosition});
- for (let i = 0, l = items.length; i < l; ++i)
+ for (let i = 0, l = items.length; i < l; ++i) {
insertRetrievedChild.call(this, items[i], insertionIndex++);
- if (itemsRange.endPosition < itemsRange.totalLength)
+ }
+ if (itemsRange.endPosition < itemsRange.totalLength) {
insertShowMoreButton.call(this, itemsRange.endPosition, itemsRange.totalLength, insertionIndex++);
+ }
} else {
let rangeIndex = 0;
let found = false;
@@ -311,8 +319,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
}
insertionIndex += range.to - range.from;
// Skip the button if there is one.
- if (range.to < itemsRange.totalLength)
+ if (range.to < itemsRange.totalLength) {
insertionIndex += 1;
+ }
++rangeIndex;
}
@@ -322,8 +331,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
insertShowMoreButton.call(
this, itemsRange.startPosition, found ? range.from : itemsRange.totalLength, insertionIndex);
range = {from: itemsRange.startPosition, to: itemsRange.startPosition};
- if (!found)
+ if (!found) {
rangeIndex = this._retrievedChildrenRanges.length;
+ }
this._retrievedChildrenRanges.splice(rangeIndex, 0, range);
} else {
insertionIndex += itemPosition - range.from;
@@ -342,8 +352,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
// We're at the position before button: ...<?node>x<button>
const nextRange = this._retrievedChildrenRanges[rangeIndex + 1];
let newEndOfRange = nextRange ? nextRange.from : itemsRange.totalLength;
- if (newEndOfRange > itemsRange.endPosition)
+ if (newEndOfRange > itemsRange.endPosition) {
newEndOfRange = itemsRange.endPosition;
+ }
while (itemPosition < newEndOfRange) {
insertRetrievedChild.call(this, items[itemIndex++], insertionIndex++);
++itemPosition;
@@ -358,10 +369,11 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
} else {
range.to = newEndOfRange;
// Remove or update next button.
- if (newEndOfRange === itemsRange.totalLength)
+ if (newEndOfRange === itemsRange.totalLength) {
this.removeChildByIndex(insertionIndex);
- else
+ } else {
this.allChildren()[insertionIndex].setStartPosition(itemsRange.endPosition);
+ }
}
}
}
@@ -373,8 +385,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
return;
}
- if (this.expanded)
+ if (this.expanded) {
this._dataGrid.updateVisibleNodes(true);
+ }
afterPopulate();
this.dispatchEventToListeners(Profiler.HeapSnapshotGridNode.Events.PopulateComplete);
}
@@ -385,10 +398,12 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
const children = this.allChildren();
for (let i = 0, l = children.length; i < l; ++i) {
const child = children[i];
- if (!child.expanded)
+ if (!child.expanded) {
continue;
- if (!this._savedChildren)
+ }
+ if (!this._savedChildren) {
this._savedChildren = {};
+ }
this._savedChildren[this._childHashForNode(child)] = child;
}
}
@@ -407,8 +422,9 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
await this._populateChildren(0, instanceCount);
for (const child of this.allChildren()) {
- if (child.expanded)
+ if (child.expanded) {
child.sort();
+ }
}
this._dataGrid.recursiveSortingLeave();
}
@@ -463,8 +479,9 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
constructor(dataGrid, node) {
super(dataGrid, false);
// node is null for DataGrid root nodes.
- if (!node)
+ if (!node) {
return;
+ }
this._name = node.name;
this._type = node.type;
this._distance = node.distance;
@@ -480,8 +497,9 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
} else if (node.canBeQueried) {
this._reachableFromWindow = true;
}
- if (node.detachedDOMTreeNode)
+ if (node.detachedDOMTreeNode) {
this.detachedDOMTreeNode = true;
+ }
const snapshot = dataGrid.snapshot;
const shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0;
@@ -510,8 +528,9 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
*/
createCell(columnId) {
const cell = columnId !== 'object' ? this._createValueCell(columnId) : this._createObjectCell();
- if (this._searchMatched)
+ if (this._searchMatched) {
cell.classList.add('highlight');
+ }
return cell;
}
@@ -570,12 +589,14 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
div.appendChild(UI.html
`<span class="heap-object-tag" title="${ls`User object reachable from window`}">🗖</span>`);
}
- if (this.detachedDOMTreeNode)
+ if (this.detachedDOMTreeNode) {
div.appendChild(UI.html`<span class="heap-object-tag" title="${ls`Detached from DOM tree`}">✀</span>`);
+ }
this._appendSourceLocation(div);
const cell = fragment.element();
- if (this.depth)
+ if (this.depth) {
cell.style.setProperty('padding-left', (this.depth * this.dataGrid.indentWidth) + 'px');
+ }
cell.heapSnapshotNode = this;
return cell;
}
@@ -593,10 +614,12 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
const linkContainer = UI.html`<span class="heap-object-source-link" />`;
div.appendChild(linkContainer);
const link = await this._dataGrid.dataDisplayDelegate().linkifyObject(this.snapshotNodeIndex);
- if (link)
+ if (link) {
linkContainer.appendChild(link);
- else
+ this.linkElement = link;
+ } else {
linkContainer.remove();
+ }
}
/**
@@ -608,10 +631,11 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
async queryObjectContent(heapProfilerModel, objectGroupName) {
const runtimeModel = heapProfilerModel.runtimeModel();
let result;
- if (this._type === 'string')
+ if (this._type === 'string') {
result = runtimeModel.createRemoteObjectFromPrimitiveValue(this._name);
- else
+ } else {
result = await heapProfilerModel.objectForSnapshotObjectId(String(this.snapshotNodeId), objectGroupName);
+ }
return result || runtimeModel.createRemoteObjectFromPrimitiveValue(ls`Preview is not available`);
}
@@ -628,12 +652,14 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
shortenWindowURL(fullName, hasObjectId) {
const startPos = fullName.indexOf('/');
const endPos = hasObjectId ? fullName.indexOf('@') : fullName.length;
- if (startPos === -1 || endPos === -1)
+ if (startPos === -1 || endPos === -1) {
return fullName;
+ }
const fullURL = fullName.substring(startPos + 1, endPos).trimLeft();
let url = fullURL.trimURL();
- if (url.length > 40)
+ if (url.length > 40) {
url = url.trimMiddle(40);
+ }
return fullName.substr(0, startPos + 2) + url + fullName.substr(endPos);
}
};
@@ -657,8 +683,9 @@ Profiler.HeapSnapshotObjectNode = class extends Profiler.HeapSnapshotGenericObje
this._parentObjectNode = parentObjectNode;
this._cycledWithAncestorGridNode = this._findAncestorWithSameSnapshotNodeId();
- if (!this._cycledWithAncestorGridNode)
+ if (!this._cycledWithAncestorGridNode) {
this.updateHasChildren();
+ }
const data = this.data;
data['count'] = '';
@@ -689,8 +716,9 @@ Profiler.HeapSnapshotObjectNode = class extends Profiler.HeapSnapshotGenericObje
_findAncestorWithSameSnapshotNodeId() {
let ancestor = this._parentObjectNode;
while (ancestor) {
- if (ancestor.snapshotNodeId === this.snapshotNodeId)
+ if (ancestor.snapshotNodeId === this.snapshotNodeId) {
return ancestor;
+ }
ancestor = ancestor._parentObjectNode;
}
return null;
@@ -757,8 +785,9 @@ Profiler.HeapSnapshotObjectNode = class extends Profiler.HeapSnapshotGenericObje
name = `[${name}]`;
break;
}
- if (this._cycledWithAncestorGridNode)
+ if (this._cycledWithAncestorGridNode) {
div.classList.add('cycled-ancessor-node');
+ }
div.prepend(UI.html`<span class="${nameClass}">${name}</span>
<span class="grayed">${this._edgeNodeSeparator()}</span>`);
}
@@ -1008,10 +1037,12 @@ Profiler.HeapSnapshotConstructorNode = class extends Profiler.HeapSnapshotGridNo
*/
createCell(columnId) {
const cell = columnId === 'object' ? super.createCell(columnId) : this._createValueCell(columnId);
- if (columnId === 'object' && this._count > 1)
+ if (columnId === 'object' && this._count > 1) {
cell.appendChild(UI.html`<span class="objects-count">×${this._count}</span>`);
- if (this._searchMatched)
+ }
+ if (this._searchMatched) {
cell.classList.add('highlight');
+ }
return cell;
}
@@ -1110,8 +1141,9 @@ Profiler.HeapSnapshotDiffNodesProvider = class {
if (beginPosition < this._addedCount) {
itemsRange = await this._addedNodesProvider.serializeItemsRange(beginPosition, endPosition);
- for (const item of itemsRange.items)
+ for (const item of itemsRange.items) {
item.isAddedNotRemoved = true;
+ }
if (itemsRange.endPosition >= endPosition) {
itemsRange.totalLength = this._addedCount + this._removedCount;
@@ -1126,10 +1158,12 @@ Profiler.HeapSnapshotDiffNodesProvider = class {
beginPosition - this._addedCount, endPosition - this._addedCount);
}
- if (!addedItems.items.length)
+ if (!addedItems.items.length) {
addedItems.startPosition = this._addedCount + itemsRange.startPosition;
- for (const item of itemsRange.items)
+ }
+ for (const item of itemsRange.items) {
item.isAddedNotRemoved = false;
+ }
addedItems.items.pushAll(itemsRange.items);
addedItems.endPosition = this._addedCount + itemsRange.endPosition;
addedItems.totalLength = this._addedCount + this._removedCount;
@@ -1195,8 +1229,9 @@ Profiler.HeapSnapshotDiffNode = class extends Profiler.HeapSnapshotGridNode {
*/
createCell(columnId) {
const cell = super.createCell(columnId);
- if (columnId !== 'object')
+ if (columnId !== 'object') {
cell.classList.add('numeric-column');
+ }
return cell;
}
@@ -1205,10 +1240,11 @@ Profiler.HeapSnapshotDiffNode = class extends Profiler.HeapSnapshotGridNode {
* @return {!Profiler.HeapSnapshotInstanceNode}
*/
_createChildNode(item) {
- if (item.isAddedNotRemoved)
+ if (item.isAddedNotRemoved) {
return new Profiler.HeapSnapshotInstanceNode(this._dataGrid, this._dataGrid.snapshot, item, false);
- else
+ } else {
return new Profiler.HeapSnapshotInstanceNode(this._dataGrid, this._dataGrid.baseSnapshot, item, true);
+ }
}
/**
@@ -1254,12 +1290,14 @@ Profiler.HeapSnapshotDiffNode = class extends Profiler.HeapSnapshotGridNode {
}
_signForDelta(delta) {
- if (delta === 0)
+ if (delta === 0) {
return '';
- if (delta > 0)
+ }
+ if (delta > 0) {
return '+';
- else
- return '\u2212'; // Math minus sign, same width as plus.
+ } else {
+ return '\u2212';
+ } // Math minus sign, same width as plus.
}
};
@@ -1288,8 +1326,9 @@ Profiler.AllocationGridNode = class extends Profiler.HeapSnapshotGridNode {
* @override
*/
populate() {
- if (this._populated)
+ if (this._populated) {
return;
+ }
this._doPopulate();
}
@@ -1306,14 +1345,16 @@ Profiler.AllocationGridNode = class extends Profiler.HeapSnapshotGridNode {
dataGrid.appendNode(parentNode, child);
parentNode = child;
parentNode._populated = true;
- if (this.expanded)
+ if (this.expanded) {
parentNode.expand();
+ }
}
const callersBranch = callers.branchingCallers;
callersBranch.sort(this._dataGrid._createComparator());
- for (const caller of callersBranch)
+ for (const caller of callersBranch) {
dataGrid.appendNode(parentNode, new Profiler.AllocationGridNode(dataGrid, caller));
+ }
dataGrid.updateVisibleNodes(true);
}
@@ -1322,8 +1363,9 @@ Profiler.AllocationGridNode = class extends Profiler.HeapSnapshotGridNode {
*/
expand() {
super.expand();
- if (this.children.length === 1)
+ if (this.children.length === 1) {
this.children[0].expand();
+ }
}
/**
@@ -1332,8 +1374,9 @@ Profiler.AllocationGridNode = class extends Profiler.HeapSnapshotGridNode {
* @return {!Element}
*/
createCell(columnId) {
- if (columnId !== 'name')
+ if (columnId !== 'name') {
return this._createValueCell(columnId);
+ }
const cell = super.createCell(columnId);
const allocationNode = this._allocationNode;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotProxy.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotProxy.js
index d6757820067..06a662701bc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotProxy.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotProxy.js
@@ -67,8 +67,9 @@ Profiler.HeapSnapshotWorkerProxy = class extends Common.Object {
dispose() {
this._worker.terminate();
- if (this._interval)
+ if (this._interval) {
clearInterval(this._interval);
+ }
}
disposeObject(objectId) {
@@ -133,8 +134,9 @@ Profiler.HeapSnapshotWorkerProxy = class extends Common.Object {
callMethod(callback, objectId, methodName) {
const callId = this._nextCallId++;
const methodArguments = Array.prototype.slice.call(arguments, 3);
- if (callback)
+ if (callback) {
this._callbacks.set(callId, callback);
+ }
this._postMessage({
callId: callId,
disposition: 'method',
@@ -145,21 +147,24 @@ Profiler.HeapSnapshotWorkerProxy = class extends Common.Object {
}
startCheckingForLongRunningCalls() {
- if (this._interval)
+ if (this._interval) {
return;
+ }
this._checkLongRunningCalls();
this._interval = setInterval(this._checkLongRunningCalls.bind(this), 300);
}
_checkLongRunningCalls() {
for (const callId of this._previousCallbacks) {
- if (!this._callbacks.has(callId))
+ if (!this._callbacks.has(callId)) {
this._previousCallbacks.delete(callId);
+ }
}
const hasLongRunningCalls = !!this._previousCallbacks.size;
this.dispatchEventToListeners(Profiler.HeapSnapshotWorkerProxy.Events.Wait, hasLongRunningCalls);
- for (const callId of this._callbacks.keysArray())
+ for (const callId of this._callbacks.keysArray()) {
this._previousCallbacks.add(callId);
+ }
}
/**
@@ -168,8 +173,9 @@ Profiler.HeapSnapshotWorkerProxy = class extends Common.Object {
_messageReceived(event) {
const data = event.data;
if (data.eventName) {
- if (this._eventHandler)
+ if (this._eventHandler) {
this._eventHandler(data.eventName, data.data);
+ }
return;
}
if (data.error) {
@@ -181,8 +187,9 @@ Profiler.HeapSnapshotWorkerProxy = class extends Common.Object {
this._callbacks.delete(data.callId);
return;
}
- if (!this._callbacks.has(data.callId))
+ if (!this._callbacks.has(data.callId)) {
return;
+ }
const callback = this._callbacks.get(data.callId);
this._callbacks.delete(data.callId);
callback(data.result);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
index 2922767c849..bc6169623f0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
@@ -50,8 +50,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
profileType.addEventListener(Profiler.ProfileType.Events.RemoveProfileHeader, this._onProfileHeaderRemoved, this);
const isHeapTimeline = profileType.id === Profiler.TrackingHeapSnapshotProfileType.TypeId;
- if (isHeapTimeline)
+ if (isHeapTimeline) {
this._createOverview();
+ }
this._parentDataDisplayDelegate = dataDisplayDelegate;
@@ -126,25 +127,27 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._perspectives = [];
this._comparisonPerspective = new Profiler.HeapSnapshotView.ComparisonPerspective();
this._perspectives.push(new Profiler.HeapSnapshotView.SummaryPerspective());
- if (profile.profileType() !== Profiler.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
+ if (profile.profileType() !== Profiler.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType) {
this._perspectives.push(this._comparisonPerspective);
+ }
this._perspectives.push(new Profiler.HeapSnapshotView.ContainmentPerspective());
- if (this._allocationWidget)
+ if (this._allocationWidget) {
this._perspectives.push(new Profiler.HeapSnapshotView.AllocationPerspective());
+ }
this._perspectives.push(new Profiler.HeapSnapshotView.StatisticsPerspective());
- this._perspectiveSelect = new UI.ToolbarComboBox(this._onSelectedPerspectiveChanged.bind(this));
+ this._perspectiveSelect = new UI.ToolbarComboBox(this._onSelectedPerspectiveChanged.bind(this), ls`Perspective`);
this._updatePerspectiveOptions();
- this._baseSelect = new UI.ToolbarComboBox(this._changeBase.bind(this));
+ this._baseSelect = new UI.ToolbarComboBox(this._changeBase.bind(this), ls`Base snapshot`);
this._baseSelect.setVisible(false);
this._updateBaseOptions();
- this._filterSelect = new UI.ToolbarComboBox(this._changeFilter.bind(this));
+ this._filterSelect = new UI.ToolbarComboBox(this._changeFilter.bind(this), ls`Filter`);
this._filterSelect.setVisible(false);
this._updateFilterOptions();
- this._classNameFilter = new UI.ToolbarInput('Class filter');
+ this._classNameFilter = new UI.ToolbarInput(ls`Class filter`);
this._classNameFilter.setVisible(false);
this._constructorsDataGrid.setNameFilter(this._classNameFilter);
this._diffDataGrid.setNameFilter(this._classNameFilter);
@@ -164,8 +167,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._populate();
this._searchThrottler = new Common.Throttler(0);
- for (const existingProfile of this._profiles())
+ for (const existingProfile of this._profiles()) {
existingProfile.addEventListener(Profiler.ProfileHeader.Events.ProfileTitleChanged, this._updateControls, this);
+ }
}
_createOverview() {
@@ -187,8 +191,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._onHeapStatsUpdate, this);
this._profile.profileType().removeEventListener(
Profiler.TrackingHeapSnapshotProfileType.TrackingStopped, this._onStopTracking, this);
- if (this._trackingOverviewGrid)
+ if (this._trackingOverviewGrid) {
this._trackingOverviewGrid.stop();
+ }
}
/**
@@ -196,8 +201,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
*/
_onHeapStatsUpdate(event) {
const samples = event.data;
- if (samples)
+ if (samples) {
this._trackingOverviewGrid.setSamples(event.data);
+ }
}
/**
@@ -222,10 +228,11 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
* @param {string} perspectiveName
*/
showObject(snapshotObjectId, perspectiveName) {
- if (snapshotObjectId <= this._profile.maxJSObjectId)
+ if (snapshotObjectId <= this._profile.maxJSObjectId) {
this.selectLiveObject(perspectiveName, snapshotObjectId);
- else
+ } else {
this._parentDataDisplayDelegate.showObject(snapshotObjectId, perspectiveName);
+ }
}
/**
@@ -236,16 +243,19 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
async linkifyObject(nodeIndex) {
const heapProfilerModel = this._profile.heapProfilerModel();
// heapProfilerModel is null if snapshot was loaded from file
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return null;
+ }
const location = await this._profile.getLocation(nodeIndex);
- if (!location)
+ if (!location) {
return null;
+ }
const debuggerModel = heapProfilerModel.runtimeModel().debuggerModel();
const rawLocation = debuggerModel.createRawLocationByScriptId(
String(location.scriptId), location.lineNumber, location.columnNumber);
- if (!rawLocation)
+ if (!rawLocation) {
return null;
+ }
const sourceURL = rawLocation.script() && rawLocation.script().sourceURL;
return sourceURL && this._linkifier ? this._linkifier.linkifyRawLocation(rawLocation, sourceURL) : null;
}
@@ -274,8 +284,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const list = this._profiles();
const profileIndex = list.indexOf(this._profile);
this._baseSelect.setSelectedIndex(Math.max(0, profileIndex - 1));
- if (this._trackingOverviewGrid)
+ if (this._trackingOverviewGrid) {
this._trackingOverviewGrid.updateGrid();
+ }
}
/**
@@ -300,8 +311,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const minId = event.data.minId;
const maxId = event.data.maxId;
this._selectedSizeText.setText(Common.UIString('Selected size: %s', Number.bytesToString(event.data.size)));
- if (this._constructorsDataGrid.snapshot)
+ if (this._constructorsDataGrid.snapshot) {
this._constructorsDataGrid.setSelectionRange(minId, maxId);
+ }
}
/**
@@ -310,8 +322,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
*/
syncToolbarItems() {
const result = [this._perspectiveSelect, this._classNameFilter];
- if (this._profile.profileType() !== Profiler.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType)
+ if (this._profile.profileType() !== Profiler.ProfileTypeRegistry.instance.trackingHeapSnapshotProfileType) {
result.push(this._baseSelect, this._filterSelect);
+ }
result.push(this._selectedSizeText);
return result;
}
@@ -352,8 +365,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
* @param {?Profiler.HeapSnapshotGridNode} node
*/
_selectRevealedNode(node) {
- if (node)
+ if (node) {
node.select();
+ }
}
/**
@@ -378,19 +392,22 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
// Call searchCanceled since it will reset everything we need before doing a new search.
this.searchCanceled();
- if (!this._currentPerspective.supportsSearch())
+ if (!this._currentPerspective.supportsSearch()) {
return;
+ }
this.currentQuery = nextQuery;
const query = nextQuery.query.trim();
- if (!query)
+ if (!query) {
return;
+ }
if (query.charAt(0) === '@') {
const snapshotNodeId = parseInt(query.substring(1), 10);
- if (isNaN(snapshotNodeId))
+ if (isNaN(snapshotNodeId)) {
return;
+ }
const node = await this._dataGrid.revealObjectByHeapSnapshotId(String(snapshotNodeId));
this._selectRevealedNode(node);
return;
@@ -399,8 +416,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._searchResults = await this._profile._snapshotProxy.search(this.currentQuery, this._dataGrid.nodeFilter());
this._searchableView.updateSearchMatchesCount(this._searchResults.length);
- if (this._searchResults.length)
+ if (this._searchResults.length) {
this._currentSearchResultIndex = nextQuery.jumpBackwards ? this._searchResults.length - 1 : 0;
+ }
await this._jumpToSearchResult(this._currentSearchResultIndex);
}
@@ -408,8 +426,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
+ }
this._currentSearchResultIndex = (this._currentSearchResultIndex + 1) % this._searchResults.length;
this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
}
@@ -418,8 +437,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
+ }
this._currentSearchResultIndex =
(this._currentSearchResultIndex + this._searchResults.length - 1) % this._searchResults.length;
this._searchThrottler.schedule(this._jumpToSearchResult.bind(this, this._currentSearchResultIndex));
@@ -431,15 +451,17 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
*/
async _jumpToSearchResult(searchResultIndex) {
this._searchableView.updateCurrentMatchIndex(searchResultIndex);
- if (searchResultIndex === -1)
+ if (searchResultIndex === -1) {
return;
+ }
const node = await this._dataGrid.revealObjectByHeapSnapshotId(String(this._searchResults[searchResultIndex]));
this._selectRevealedNode(node);
}
refreshVisibleData() {
- if (!this._dataGrid)
+ if (!this._dataGrid) {
return;
+ }
let child = this._dataGrid.rootNode().children[0];
while (child) {
child.refresh();
@@ -448,17 +470,20 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
}
_changeBase() {
- if (this._baseProfile === this._profiles()[this._baseSelect.selectedIndex()])
+ if (this._baseProfile === this._profiles()[this._baseSelect.selectedIndex()]) {
return;
+ }
this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
const dataGrid = /** @type {!Profiler.HeapSnapshotDiffDataGrid} */ (this._dataGrid);
// Change set base data source only if main data source is already set.
- if (dataGrid.snapshot)
+ if (dataGrid.snapshot) {
this._baseProfile._loadPromise.then(dataGrid.setBaseDataSource.bind(dataGrid));
+ }
- if (!this.currentQuery || !this._searchResults)
+ if (!this.currentQuery || !this._searchResults) {
return;
+ }
// The current search needs to be performed again. First negate out previous match
// count by calling the search finished callback with a negative number of matches.
@@ -470,8 +495,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const profileIndex = this._filterSelect.selectedIndex() - 1;
this._dataGrid.filterSelectIndexChanged(this._profiles(), profileIndex);
- if (!this.currentQuery || !this._searchResults)
+ if (!this.currentQuery || !this._searchResults) {
return;
+ }
// The current search needs to be performed again. First negate out previous match
// count by calling the search finished callback with a negative number of matches.
@@ -510,8 +536,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
_inspectedObjectChanged(event) {
const selectedNode = /** @type {!DataGrid.DataGridNode} */ (event.data);
const heapProfilerModel = this._profile.heapProfilerModel();
- if (heapProfilerModel && selectedNode instanceof Profiler.HeapSnapshotGenericObjectNode)
+ if (heapProfilerModel && selectedNode instanceof Profiler.HeapSnapshotGenericObjectNode) {
heapProfilerModel.addInspectedHeapObject(String(selectedNode.snapshotNodeId));
+ }
}
/**
@@ -521,11 +548,13 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const dataSource = nodeItem && nodeItem.retainersDataSource();
if (dataSource) {
this._retainmentDataGrid.setDataSource(dataSource.snapshot, dataSource.snapshotNodeIndex);
- if (this._allocationStackView)
+ if (this._allocationStackView) {
this._allocationStackView.setAllocatedObject(dataSource.snapshot, dataSource.snapshotNodeIndex);
+ }
} else {
- if (this._allocationStackView)
+ if (this._allocationStackView) {
this._allocationStackView.clear();
+ }
this._retainmentDataGrid.reset();
}
}
@@ -536,13 +565,14 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
*/
_changePerspectiveAndWait(perspectiveTitle) {
const perspectiveIndex = this._perspectives.findIndex(perspective => perspective.title() === perspectiveTitle);
- if (perspectiveIndex === -1 || this._currentPerspectiveIndex === perspectiveIndex)
+ if (perspectiveIndex === -1 || this._currentPerspectiveIndex === perspectiveIndex) {
return Promise.resolve();
+ }
const promise = this._perspectives[perspectiveIndex].masterGrid(this).once(
Profiler.HeapSnapshotSortableDataGrid.Events.ContentShown);
- const option = this._perspectiveSelect.options().find(option => option.value === perspectiveIndex);
+ const option = this._perspectiveSelect.options().find(option => option.value === String(perspectiveIndex));
this._perspectiveSelect.select(/** @type {!Element} */ (option));
this._changePerspective(perspectiveIndex);
return promise;
@@ -550,24 +580,30 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
async _updateDataSourceAndView() {
const dataGrid = this._dataGrid;
- if (!dataGrid || dataGrid.snapshot)
+ if (!dataGrid || dataGrid.snapshot) {
return;
+ }
const snapshotProxy = await this._profile._loadPromise;
- if (this._dataGrid !== dataGrid)
+ if (this._dataGrid !== dataGrid) {
return;
- if (dataGrid.snapshot !== snapshotProxy)
+ }
+ if (dataGrid.snapshot !== snapshotProxy) {
dataGrid.setDataSource(snapshotProxy);
- if (dataGrid !== this._diffDataGrid)
+ }
+ if (dataGrid !== this._diffDataGrid) {
return;
- if (!this._baseProfile)
+ }
+ if (!this._baseProfile) {
this._baseProfile = this._profiles()[this._baseSelect.selectedIndex()];
+ }
const baseSnapshotProxy = await this._baseProfile._loadPromise;
- if (this._diffDataGrid.baseSnapshot !== baseSnapshotProxy)
+ if (this._diffDataGrid.baseSnapshot !== baseSnapshotProxy) {
this._diffDataGrid.setBaseDataSource(baseSnapshotProxy);
+ }
}
/**
@@ -581,8 +617,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
* @param {number} selectedIndex
*/
_changePerspective(selectedIndex) {
- if (selectedIndex === this._currentPerspectiveIndex)
+ if (selectedIndex === this._currentPerspectiveIndex) {
return;
+ }
this._currentPerspectiveIndex = selectedIndex;
@@ -593,13 +630,15 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
perspective.activate(this);
this.refreshVisibleData();
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.updateWidths();
+ }
this._updateDataSourceAndView();
- if (!this.currentQuery || !this._searchResults)
+ if (!this.currentQuery || !this._searchResults) {
return;
+ }
// The current search needs to be performed again. First negate out previous match
// count by calling the search finished callback with a negative number of matches.
@@ -614,10 +653,11 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
async selectLiveObject(perspectiveName, snapshotObjectId) {
await this._changePerspectiveAndWait(perspectiveName);
const node = await this._dataGrid.revealObjectByHeapSnapshotId(snapshotObjectId);
- if (node)
+ if (node) {
node.select();
- else
+ } else {
Common.console.error('Cannot find corresponding heap snapshot node');
+ }
}
/**
@@ -628,16 +668,18 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const span = event.target.enclosingNodeOrSelfWithNodeName('span');
const row = event.target.enclosingNodeOrSelfWithNodeName('tr');
const heapProfilerModel = this._profile.heapProfilerModel();
- if (!row || !span || !heapProfilerModel)
+ if (!row || !span || !heapProfilerModel) {
return null;
+ }
const node = row._dataGridNode;
let objectPopoverHelper;
return {
box: span.boxInWindow(),
show: async popover => {
const remoteObject = await node.queryObjectContent(heapProfilerModel, 'popover');
- if (!remoteObject)
+ if (!remoteObject) {
return false;
+ }
objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(remoteObject, popover);
if (!objectPopoverHelper) {
heapProfilerModel.runtimeModel().releaseObjectGroup('popover');
@@ -656,8 +698,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const multipleSnapshots = this._profiles().length > 1;
this._perspectiveSelect.removeOptions();
this._perspectives.forEach((perspective, index) => {
- if (multipleSnapshots || perspective !== this._comparisonPerspective)
- this._perspectiveSelect.createOption(perspective.title(), '', String(index));
+ if (multipleSnapshots || perspective !== this._comparisonPerspective) {
+ this._perspectiveSelect.createOption(perspective.title(), String(index));
+ }
});
}
@@ -666,11 +709,13 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
const selectedIndex = this._baseSelect.selectedIndex();
this._baseSelect.removeOptions();
- for (const item of list)
+ for (const item of list) {
this._baseSelect.createOption(item.title);
+ }
- if (selectedIndex > -1)
+ if (selectedIndex > -1) {
this._baseSelect.setSelectedIndex(selectedIndex);
+ }
}
_updateFilterOptions() {
@@ -681,15 +726,17 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._filterSelect.createOption(Common.UIString('All objects'));
for (let i = 0; i < list.length; ++i) {
let title;
- if (!i)
+ if (!i) {
title = Common.UIString('Objects allocated before %s', list[i].title);
- else
+ } else {
title = Common.UIString('Objects allocated between %s and %s', list[i - 1].title, list[i].title);
+ }
this._filterSelect.createOption(title);
}
- if (selectedIndex > -1)
+ if (selectedIndex > -1) {
this._filterSelect.setSelectedIndex(selectedIndex);
+ }
}
_updateControls() {
@@ -765,12 +812,15 @@ Profiler.HeapSnapshotView.Perspective = class {
heapSnapshotView._baseSelect.setVisible(false);
heapSnapshotView._filterSelect.setVisible(false);
heapSnapshotView._classNameFilter.setVisible(false);
- if (heapSnapshotView._trackingOverviewGrid)
+ if (heapSnapshotView._trackingOverviewGrid) {
heapSnapshotView._trackingOverviewGrid.detach();
- if (heapSnapshotView._allocationWidget)
+ }
+ if (heapSnapshotView._allocationWidget) {
heapSnapshotView._allocationWidget.detach();
- if (heapSnapshotView._statisticsView)
+ }
+ if (heapSnapshotView._statisticsView) {
heapSnapshotView._statisticsView.detach();
+ }
heapSnapshotView._splitWidget.detach();
heapSnapshotView._splitWidget.detachChildWidgets();
@@ -817,8 +867,9 @@ Profiler.HeapSnapshotView.SummaryPerspective = class extends Profiler.HeapSnapsh
heapSnapshotView._splitWidget.show(heapSnapshotView._searchableView.element);
heapSnapshotView._filterSelect.setVisible(true);
heapSnapshotView._classNameFilter.setVisible(true);
- if (!heapSnapshotView._trackingOverviewGrid)
+ if (!heapSnapshotView._trackingOverviewGrid) {
return;
+ }
heapSnapshotView._trackingOverviewGrid.show(
heapSnapshotView._searchableView.element, heapSnapshotView._splitWidget.element);
heapSnapshotView._trackingOverviewGrid.update();
@@ -942,8 +993,9 @@ Profiler.HeapSnapshotView.AllocationPerspective = class extends Profiler.HeapSna
heapSnapshotView._constructorsDataGrid.clear();
const selectedNode = heapSnapshotView._allocationDataGrid.selectedNode;
- if (selectedNode)
+ if (selectedNode) {
heapSnapshotView._constructorsDataGrid.setAllocationNodeId(selectedNode.allocationNodeId());
+ }
}
/**
@@ -1043,6 +1095,9 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
return '.heapsnapshot';
}
+ /**
+ * @override
+ */
get buttonTooltip() {
return Common.UIString('Take heap snapshot');
}
@@ -1065,10 +1120,16 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
return false;
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return Common.UIString('HEAP SNAPSHOTS');
}
+ /**
+ * @override
+ */
get description() {
return Common.UIString(
'Heap snapshot profiles show memory distribution among your page\'s JavaScript objects and related DOM nodes.');
@@ -1084,11 +1145,13 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
}
async _takeHeapSnapshot() {
- if (this.profileBeingRecorded())
+ if (this.profileBeingRecorded()) {
return;
+ }
const heapProfilerModel = UI.context.flavor(SDK.HeapProfilerModel);
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return;
+ }
let profile = new Profiler.HeapProfileHeader(heapProfilerModel, this);
this.setProfileBeingRecorded(profile);
@@ -1108,8 +1171,9 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
* @param {!Common.Event} event
*/
_addHeapSnapshotChunk(event) {
- if (!this.profileBeingRecorded())
+ if (!this.profileBeingRecorded()) {
return;
+ }
const chunk = /** @type {string} */ (event.data);
this.profileBeingRecorded().transferChunk(chunk);
}
@@ -1119,12 +1183,14 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
*/
_reportHeapSnapshotProgress(event) {
const profile = this.profileBeingRecorded();
- if (!profile)
+ if (!profile) {
return;
+ }
const data = /** @type {{done: number, total: number, finished: boolean}} */ (event.data);
profile.updateStatus(Common.UIString('%.0f%%', (data.done / data.total) * 100), true);
- if (data.finished)
+ if (data.finished) {
profile._prepareToLoad();
+ }
}
/**
@@ -1133,14 +1199,16 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
_resetProfiles(event) {
const heapProfilerModel = /** @type {!SDK.HeapProfilerModel} */ (event.data);
for (const profile of this.getProfiles()) {
- if (profile.heapProfilerModel() === heapProfilerModel)
+ if (profile.heapProfilerModel() === heapProfilerModel) {
this.removeProfile(profile);
+ }
}
}
_snapshotReceived(profile) {
- if (this.profileBeingRecorded() === profile)
+ if (this.profileBeingRecorded() === profile) {
this.setProfileBeingRecorded(null);
+ }
this.dispatchEventToListeners(Profiler.HeapSnapshotProfileType.SnapshotReceived, profile);
}
};
@@ -1183,16 +1251,18 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
* @param {!Common.Event} event
*/
_heapStatsUpdate(event) {
- if (!this._profileSamples)
+ if (!this._profileSamples) {
return;
+ }
const samples = /** @type {!Array.<number>} */ (event.data);
let index;
for (let i = 0; i < samples.length; i += 3) {
index = samples[i];
const size = samples[i + 2];
this._profileSamples.sizes[index] = size;
- if (!this._profileSamples.max[index])
+ if (!this._profileSamples.max[index]) {
this._profileSamples.max[index] = size;
+ }
}
}
@@ -1201,8 +1271,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
*/
_lastSeenObjectId(event) {
const profileSamples = this._profileSamples;
- if (!profileSamples)
+ if (!profileSamples) {
return;
+ }
const data = /** @type {{lastSeenObjectId: number, timestamp: number}} */ (event.data);
const currentIndex = Math.max(profileSamples.ids.length, profileSamples.max.length - 1);
profileSamples.ids[currentIndex] = data.lastSeenObjectId;
@@ -1211,8 +1282,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
profileSamples.sizes[currentIndex] = 0;
}
profileSamples.timestamps[currentIndex] = data.timestamp;
- if (profileSamples.totalTime < data.timestamp - profileSamples.timestamps[0])
+ if (profileSamples.totalTime < data.timestamp - profileSamples.timestamps[0]) {
profileSamples.totalTime *= 2;
+ }
this.dispatchEventToListeners(Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate, this._profileSamples);
this.profileBeingRecorded().updateStatus(null, true);
}
@@ -1225,6 +1297,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
return true;
}
+ /**
+ * @override
+ */
get buttonTooltip() {
return this._recording ? ls`Stop recording heap profile` : ls`Start recording heap profile`;
}
@@ -1246,11 +1321,13 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
}
_startRecordingProfile() {
- if (this.profileBeingRecorded())
+ if (this.profileBeingRecorded()) {
return;
+ }
const heapProfilerModel = this._addNewProfile();
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return;
+ }
heapProfilerModel.startTrackingHeapObjects(this._recordAllocationStacksSetting.get());
}
@@ -1278,8 +1355,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
*/
_addNewProfile() {
const heapProfilerModel = UI.context.flavor(SDK.HeapProfilerModel);
- if (!heapProfilerModel)
+ if (!heapProfilerModel) {
return null;
+ }
this.setProfileBeingRecorded(new Profiler.HeapProfileHeader(heapProfilerModel, this, undefined));
this._profileSamples = new Profiler.HeapTimelineOverview.Samples();
this.profileBeingRecorded()._profileSamples = this._profileSamples;
@@ -1298,8 +1376,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
await stopPromise;
// ------------ ASYNC ------------
const profile = this.profileBeingRecorded();
- if (!profile)
+ if (!profile) {
return;
+ }
profile._finishLoad();
this._profileSamples = null;
this.setProfileBeingRecorded(null);
@@ -1307,10 +1386,11 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
}
_toggleRecording() {
- if (this._recording)
+ if (this._recording) {
this._stopRecordingProfile();
- else
+ } else {
this._startRecordingProfile();
+ }
return this._recording;
}
@@ -1322,10 +1402,16 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
return '.heaptimeline';
}
+ /**
+ * @override
+ */
get treeItemTitle() {
return ls`ALLOCATION TIMELINES`;
}
+ /**
+ * @override
+ */
get description() {
return ls`
Allocation timelines show instrumented JavaScript memory allocations over time.
@@ -1344,8 +1430,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
this.setProfileBeingRecorded(null);
super._resetProfiles(event);
this._profileSamples = null;
- if (wasRecording)
+ if (wasRecording) {
this._addNewProfile();
+ }
}
/**
@@ -1357,6 +1444,9 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
}
};
+/**
+ * @override
+ */
Profiler.TrackingHeapSnapshotProfileType.TypeId = 'HEAP-RECORD';
Profiler.TrackingHeapSnapshotProfileType.HeapStatsUpdate = 'HeapStatsUpdate';
@@ -1430,10 +1520,12 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
}
_finishLoad() {
- if (!this._wasDisposed)
+ if (!this._wasDisposed) {
this._receiver.close();
- if (!this._bufferedWriter)
+ }
+ if (!this._bufferedWriter) {
return;
+ }
this._didWriteToTempFile(this._bufferedWriter);
}
@@ -1442,13 +1534,15 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
*/
_didWriteToTempFile(tempFile) {
if (this._wasDisposed) {
- if (tempFile)
+ if (tempFile) {
tempFile.remove();
+ }
return;
}
this._tempFile = tempFile;
- if (!tempFile)
+ if (!tempFile) {
this._failedToCreateTempFile = true;
+ }
if (this._onTempFileReady) {
this._onTempFileReady();
this._onTempFileReady = null;
@@ -1479,25 +1573,29 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
return;
}
- if (HeapSnapshotModel.HeapSnapshotProgressEvent.Update !== eventName)
+ if (HeapSnapshotModel.HeapSnapshotProgressEvent.Update !== eventName) {
return;
- const subtitle = /** @type {string} */ (data);
- this.updateStatus(subtitle);
+ }
+ const serializedMessage = /** @type {string} */ (data);
+ const messageObject = Common.deserializeUIString(serializedMessage);
+ this.updateStatus(ls(messageObject.messageParts, messageObject.values));
}
/**
* @override
*/
dispose() {
- if (this._workerProxy)
+ if (this._workerProxy) {
this._workerProxy.dispose();
+ }
this.removeTempFile();
this._wasDisposed = true;
}
_didCompleteSnapshotTransfer() {
- if (!this._snapshotProxy)
+ if (!this._snapshotProxy) {
return;
+ }
this.updateStatus(Number.bytesToString(this._snapshotProxy.totalSize), false);
}
@@ -1505,8 +1603,9 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
* @param {string} chunk
*/
transferChunk(chunk) {
- if (!this._bufferedWriter)
+ if (!this._bufferedWriter) {
this._bufferedWriter = new Bindings.TempFile();
+ }
this._bufferedWriter.write([chunk]);
++this._totalNumberOfChunks;
@@ -1514,8 +1613,9 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
}
_snapshotReceived(snapshotProxy) {
- if (this._wasDisposed)
+ if (this._wasDisposed) {
return;
+ }
this._receiver = null;
this._snapshotProxy = snapshotProxy;
this.maxJSObjectId = snapshotProxy.maxJSObjectId();
@@ -1527,8 +1627,9 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
notifySnapshotReceived() {
this._fulfillLoad(this._snapshotProxy);
this.profileType()._snapshotReceived(this);
- if (this.canSaveToFile())
+ if (this.canSaveToFile()) {
this.dispatchEventToListeners(Profiler.ProfileHeader.Events.ProfileReceived);
+ }
}
/**
@@ -1552,8 +1653,9 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
* @this {Profiler.HeapProfileHeader}
*/
async function onOpen(accepted) {
- if (!accepted)
+ if (!accepted) {
return;
+ }
if (this._failedToCreateTempFile) {
Common.console.error('Failed to open temp file with heap snapshot');
fileOutputStream.close();
@@ -1561,8 +1663,9 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
}
if (this._tempFile) {
const error = await this._tempFile.copyToOutputStream(fileOutputStream, this._onChunkTransferred.bind(this));
- if (error)
+ if (error) {
Common.console.error('Failed to read heap snapshot from temp file: ' + error.message);
+ }
this._didCompleteSnapshotTransfer();
return;
}
@@ -1590,15 +1693,16 @@ Profiler.HeapProfileHeader = class extends Profiler.ProfileHeader {
/**
* @override
* @param {!File} file
- * @return {!Promise<?Error>}
+ * @return {!Promise<?FileError>}
*/
async loadFromFile(file) {
this.updateStatus(Common.UIString('Loading\u2026'), true);
this._setupWorker();
const reader = new Bindings.ChunkedFileReader(file, 10000000);
const success = await reader.read(/** @type {!Common.OutputStream} */ (this._receiver));
- if (!success)
+ if (!success) {
this.updateStatus(reader.error().message);
+ }
return success ? null : reader.error();
}
};
@@ -1653,6 +1757,65 @@ Profiler.HeapAllocationStackView = class extends UI.Widget {
super();
this._heapProfilerModel = heapProfilerModel;
this._linkifier = new Components.Linkifier();
+ /** @type {!Array<!Element>} */
+ this._frameElements = [];
+ }
+
+ /**
+ * @param {!Element} link
+ * @param {!Event} event
+ */
+ _onContextMenu(link, event) {
+ const contextMenu = new UI.ContextMenu(event);
+ if (!contextMenu.containsTarget(link)) {
+ contextMenu.appendApplicableItems(link);
+ }
+ contextMenu.show();
+ event.consume(true);
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ _onStackViewKeydown(event) {
+ const target = /** @type {?Element} */ (event.target);
+ if (!target) {
+ return;
+ }
+ if (isEnterKey(event)) {
+ const link = target._linkElement;
+ if (!link) {
+ return;
+ }
+ if (Components.Linkifier.invokeFirstAction(link)) {
+ event.consume(true);
+ }
+ return;
+ }
+
+ let navDown;
+ if (event.key === 'ArrowUp') {
+ navDown = false;
+ } else if (event.key === 'ArrowDown') {
+ navDown = true;
+ } else {
+ return;
+ }
+
+ const index = this._frameElements.indexOf(target);
+ if (index === -1) {
+ return;
+ }
+ const nextIndex = navDown ? index + 1 : index - 1;
+ if (nextIndex < 0 || nextIndex >= this._frameElements.length) {
+ return;
+ }
+
+ const nextFrame = this._frameElements[nextIndex];
+ nextFrame.tabIndex = 0;
+ target.tabIndex = -1;
+ nextFrame.focus();
+ event.consume(true);
}
/**
@@ -1671,21 +1834,29 @@ Profiler.HeapAllocationStackView = class extends UI.Widget {
}
const stackDiv = this.element.createChild('div', 'heap-allocation-stack');
+ stackDiv.addEventListener('keydown', this._onStackViewKeydown.bind(this), false);
for (const frame of frames) {
const frameDiv = stackDiv.createChild('div', 'stack-frame');
+ this._frameElements.push(frameDiv);
+ frameDiv.tabIndex = -1;
const name = frameDiv.createChild('div');
name.textContent = UI.beautifyFunctionName(frame.functionName);
- if (!frame.scriptId)
+ if (!frame.scriptId) {
continue;
+ }
const urlElement = this._linkifier.linkifyScriptLocation(
this._heapProfilerModel ? this._heapProfilerModel.target() : null, String(frame.scriptId), frame.scriptName,
frame.line - 1, frame.column - 1);
frameDiv.appendChild(urlElement);
+ frameDiv._linkElement = urlElement;
+ frameDiv.addEventListener('contextmenu', this._onContextMenu.bind(this, urlElement));
}
+ this._frameElements[0].tabIndex = 0;
}
clear() {
this.element.removeChildren();
+ this._frameElements = [];
this._linkifier.reset();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
index 09f2ed554dd..151c47d1c97 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapTimelineOverview.js
@@ -33,8 +33,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
this._running = true;
const drawFrame = () => {
this.update();
- if (this._running)
+ if (this._running) {
this.element.window().requestAnimationFrame(drawFrame);
+ }
};
drawFrame();
}
@@ -48,8 +49,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
*/
setSamples(samples) {
this._profileSamples = samples;
- if (!this._running)
+ if (!this._running) {
this.update();
+ }
}
/**
@@ -57,8 +59,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
* @param {number} height
*/
_drawOverviewCanvas(width, height) {
- if (!this._profileSamples)
+ if (!this._profileSamples) {
return;
+ }
const profileSamples = this._profileSamples;
const sizes = profileSamples.sizes;
const topSizes = profileSamples.max;
@@ -77,8 +80,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
for (let i = 1; i < timestamps.length; ++i) {
const x = Math.floor((timestamps[i] - startTime) * scaleFactor);
if (x !== currentX) {
- if (size)
+ if (size) {
callback(currentX, size);
+ }
size = 0;
currentX = x;
}
@@ -128,8 +132,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
// e.g. a round value 10KB is 10240 bytes.
gridValue = Math.pow(1024, Math.floor(Math.log(maxGridValue) / Math.log(1024)));
gridValue *= Math.pow(10, Math.floor(Math.log(maxGridValue / gridValue) / Math.LN10));
- if (gridValue * 5 <= maxGridValue)
+ if (gridValue * 5 <= maxGridValue) {
gridValue *= 5;
+ }
gridY = Math.round(height - gridValue * yScaleFactor - 0.5) + 0.5;
context.beginPath();
context.lineWidth = 1;
@@ -190,13 +195,15 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
}
_onWindowChanged() {
- if (!this._updateGridTimerId)
+ if (!this._updateGridTimerId) {
this._updateGridTimerId = setTimeout(this.updateGrid.bind(this), 10);
+ }
}
_scheduleUpdate() {
- if (this._updateTimerId)
+ if (this._updateTimerId) {
return;
+ }
this._updateTimerId = setTimeout(this.update.bind(this), 10);
}
@@ -208,8 +215,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
update() {
this._updateTimerId = null;
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
this._updateBoundaries();
this._overviewCalculator._updateBoundaries(this);
this._overviewGrid.updateDividers(this._overviewCalculator);
@@ -220,8 +228,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
this._updateGridTimerId = 0;
this._updateBoundaries();
const ids = this._profileSamples.ids;
- if (!ids.length)
+ if (!ids.length) {
return;
+ }
const timestamps = this._profileSamples.timestamps;
const sizes = this._profileSamples.sizes;
const startTime = timestamps[0];
@@ -231,8 +240,9 @@ Profiler.HeapTimelineOverview = class extends UI.VBox {
const minIndex = timestamps.lowerBound(timeLeft);
const maxIndex = timestamps.upperBound(timeRight);
let size = 0;
- for (let i = minIndex; i <= maxIndex; ++i)
+ for (let i = minIndex; i <= maxIndex; ++i) {
size += sizes[i];
+ }
const minId = minIndex > 0 ? ids[minIndex - 1] : 0;
const maxId = maxIndex < ids.length ? ids[maxIndex] : Infinity;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
index 849454468ce..04396e1d6c6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
@@ -59,8 +59,9 @@ Profiler.IsolateSelector = class extends UI.VBox {
const index = item.model().target() === SDK.targetManager.mainTarget() ? 0 : this._items.length;
this._items.insert(index, item);
this._itemByIsolate.set(isolate, item);
- if (this._items.length === 1)
+ if (this._items.length === 1) {
this._list.selectItem(item);
+ }
this._update();
}
@@ -91,12 +92,14 @@ Profiler.IsolateSelector = class extends UI.VBox {
_targetChanged(event) {
const target = /** @type {!SDK.Target} */ (event.data);
const model = target.model(SDK.RuntimeModel);
- if (!model)
+ if (!model) {
return;
+ }
const isolate = SDK.isolateManager.isolateByModel(model);
const item = isolate && this._itemByIsolate.get(isolate);
- if (item)
+ if (item) {
item.updateTitle();
+ }
}
/**
@@ -105,8 +108,9 @@ Profiler.IsolateSelector = class extends UI.VBox {
_heapStatsChanged(event) {
const isolate = /** @type {!SDK.IsolateManager.Isolate} */ (event.data);
const listItem = this._itemByIsolate.get(isolate);
- if (listItem)
+ if (listItem) {
listItem.updateStats();
+ }
this._updateTotal();
}
@@ -128,8 +132,9 @@ Profiler.IsolateSelector = class extends UI.VBox {
static _formatTrendElement(trendValueMs, element) {
const changeRateBytesPerSecond = trendValueMs * 1e3;
const changeRateThresholdBytesPerSecond = 1024;
- if (Math.abs(changeRateBytesPerSecond) < changeRateThresholdBytesPerSecond)
+ if (Math.abs(changeRateBytesPerSecond) < changeRateThresholdBytesPerSecond) {
return;
+ }
const changeRateText = Number.bytesToString(Math.abs(changeRateBytesPerSecond));
const changeText = changeRateBytesPerSecond > 0 ? ls`\u2B06${changeRateText}/s` : ls`\u2B07${changeRateText}/s`;
element.classList.toggle('increasing', changeRateBytesPerSecond > 0);
@@ -177,10 +182,12 @@ Profiler.IsolateSelector = class extends UI.VBox {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('selected');
+ }
const model = to && to.model();
UI.context.setFlavor(SDK.HeapProfilerModel, model && model.heapProfilerModel());
UI.context.setFlavor(SDK.CPUProfilerModel, model && model.target().model(SDK.CPUProfilerModel));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
index 5a360ba1a30..5e8f6dd2017 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
@@ -68,8 +68,9 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortingChanged, this);
for (const info of columns) {
const headerCell = dataGrid.headerTableHeader(info.id);
- if (headerCell)
+ if (headerCell) {
headerCell.setAttribute('title', info.tooltip);
+ }
}
return dataGrid;
}
@@ -103,8 +104,9 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
const isolates = Array.from(SDK.isolateManager.isolates());
const profiles = await Promise.all(
isolates.map(isolate => isolate.heapProfilerModel() && isolate.heapProfilerModel().getSamplingProfile()));
- if (this._currentPollId !== pollId)
+ if (this._currentPollId !== pollId) {
return;
+ }
this._update(isolates, profiles);
await new Promise(r => setTimeout(r, 3000));
} while (this._currentPollId === pollId);
@@ -118,8 +120,9 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
/** @type {!Map<string, !{size: number, isolates: !Set<!SDK.IsolateManager.Isolate>}>} */
const dataByUrl = new Map();
profiles.forEach((profile, index) => {
- if (profile)
+ if (profile) {
processNodeTree(isolates[index], '', profile.head);
+ }
});
const rootNode = this._dataGrid.rootNode();
@@ -144,8 +147,9 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
}
for (const node of rootNode.children.slice()) {
- if (!exisitingNodes.has(node))
+ if (!exisitingNodes.has(node)) {
node.remove();
+ }
this._gridNodeByUrl.delete(node);
}
@@ -159,8 +163,9 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
function processNodeTree(isolate, parentUrl, node) {
const url = node.callFrame.url || parentUrl || systemNodeName(node) || anonymousScriptName(node);
node.children.forEach(processNodeTree.bind(null, isolate, url));
- if (!node.selfSize)
+ if (!node.selfSize) {
return;
+ }
let data = dataByUrl.get(url);
if (!data) {
data = {size: 0, isolates: new Set()};
@@ -192,25 +197,29 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
* @param {!Event} event
*/
_onKeyDown(event) {
- if (!isEnterKey(event))
+ if (!isEnterKey(event)) {
return;
+ }
event.consume(true);
this._revealSourceForSelectedNode();
}
_revealSourceForSelectedNode() {
const node = this._dataGrid.selectedNode;
- if (!node || !node._url)
+ if (!node || !node._url) {
return;
+ }
const sourceCode = Workspace.workspace.uiSourceCodeForURL(node._url);
- if (sourceCode)
+ if (sourceCode) {
Common.Revealer.reveal(sourceCode);
+ }
}
_sortingChanged() {
const columnId = this._dataGrid.sortColumnId();
- if (!columnId)
+ if (!columnId) {
return;
+ }
const sortByUrl = (a, b) => b._url.localeCompare(a._url);
const sortBySize = (a, b) => b._size - a._size;
const sortFunction = columnId === 'url' ? sortByUrl : sortBySize;
@@ -219,10 +228,11 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
_toggleRecording() {
const enable = !this._setting.get();
- if (enable)
+ if (enable) {
this._startRecording(false);
- else
+ } else {
this._stopRecording();
+ }
}
/**
@@ -230,14 +240,17 @@ Profiler.LiveHeapProfileView = class extends UI.VBox {
*/
_startRecording(reload) {
this._setting.set(true);
- if (!reload)
+ if (!reload) {
return;
+ }
const mainTarget = SDK.targetManager.mainTarget();
- if (!mainTarget)
+ if (!mainTarget) {
return;
+ }
const resourceTreeModel = /** @type {?SDK.ResourceTreeModel} */ (mainTarget.model(SDK.ResourceTreeModel));
- if (resourceTreeModel)
+ if (resourceTreeModel) {
resourceTreeModel.reloadPage();
+ }
}
async _stopRecording() {
@@ -263,8 +276,9 @@ Profiler.LiveHeapProfileView.GridNode = class extends DataGrid.SortableDataGridN
* @param {number} isolateCount
*/
updateNode(size, isolateCount) {
- if (this._size === size && this._isolateCount === isolateCount)
+ if (this._size === size && this._isolateCount === isolateCount) {
return;
+ }
this._size = size;
this._isolateCount = isolateCount;
this.refresh();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileDataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileDataGrid.js
index 646b521634c..c69445bb03f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileDataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileDataGrid.js
@@ -51,6 +51,8 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
this.functionName = UI.beautifyFunctionName(profileNode.functionName);
this._deoptReason = profileNode.deoptReason || '';
this.url = profileNode.url;
+ /** @type {?Element} */
+ this.linkElement = null;
}
/**
@@ -70,8 +72,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
// If the grid node is collapsed, then don't sort children (save operation for later).
// If the grid node has the same sorting as previously, then there is no point in sorting it again.
if (!force && (!gridNode.expanded || gridNode.lastComparator === comparator)) {
- if (gridNode.children.length)
+ if (gridNode.children.length) {
gridNode.shouldRefreshChildren = true;
+ }
continue;
}
@@ -83,8 +86,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
if (childCount) {
children.sort(comparator);
- for (let childIndex = 0; childIndex < childCount; ++childIndex)
+ for (let childIndex = 0; childIndex < childCount; ++childIndex) {
children[childIndex].recalculateSiblings(childIndex);
+ }
gridNodeGroups.push(children);
}
@@ -100,8 +104,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
static merge(container, child, shouldAbsorb) {
container.self += child.self;
- if (!shouldAbsorb)
+ if (!shouldAbsorb) {
container.total += child.total;
+ }
let children = container.children.slice();
@@ -110,8 +115,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
let count = children.length;
for (let index = 0; index < count; ++index) {
- if (!shouldAbsorb || children[index] !== child)
+ if (!shouldAbsorb || children[index] !== child) {
container.appendChild(children[index]);
+ }
}
children = child.children.slice();
@@ -121,10 +127,11 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
const orphanedChild = children[index];
const existingChild = container.childrenByCallUID.get(orphanedChild.callUID);
- if (existingChild)
+ if (existingChild) {
existingChild.merge(/** @type{!Profiler.ProfileDataGridNode} */ (orphanedChild), false);
- else
+ } else {
container.appendChild(orphanedChild);
+ }
}
}
@@ -132,16 +139,18 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
* @param {!Profiler.ProfileDataGridNode|!Profiler.ProfileDataGridTree} container
*/
static populate(container) {
- if (container._populated)
+ if (container._populated) {
return;
+ }
container._populated = true;
container.populateChildren();
const currentComparator = container.tree.lastComparator;
- if (currentComparator)
+ if (currentComparator) {
container.sort(currentComparator, true);
+ }
}
/**
@@ -172,13 +181,16 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
cell.appendChild(warningIcon);
}
cell.createTextChild(this.functionName);
- if (this.profileNode.scriptId === '0')
+ if (this.profileNode.scriptId === '0') {
break;
+ }
const urlElement = this.tree._formatter.linkifyNode(this);
- if (!urlElement)
+ if (!urlElement) {
break;
+ }
urlElement.style.maxWidth = '75%';
cell.appendChild(urlElement);
+ this.linkElement = urlElement;
break;
default:
@@ -196,8 +208,16 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
_createValueCell(value, percent) {
const cell = createElementWithClass('td', 'numeric-column');
const div = cell.createChild('div', 'profile-multiple-values');
- div.createChild('span').textContent = this.tree._formatter.formatValue(value, this);
- div.createChild('span', 'percent-column').textContent = this.tree._formatter.formatPercent(percent, this);
+ const valueSpan = div.createChild('span');
+ const valueText = this.tree._formatter.formatValue(value, this);
+ valueSpan.textContent = valueText;
+ const percentSpan = div.createChild('span', 'percent-column');
+ const percentText = this.tree._formatter.formatPercent(percent, this);
+ percentSpan.textContent = percentText;
+ UI.ARIAUtils.markAsHidden(valueSpan);
+ UI.ARIAUtils.markAsHidden(percentSpan);
+ const valueAccessibleText = this.tree._formatter.formatValueAccessibleText(value, this);
+ UI.ARIAUtils.setAccessibleName(div, ls`${valueAccessibleText}, ${percentText}`);
return cell;
}
@@ -246,8 +266,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
* @return {?Profiler.ProfileDataGridNode}
*/
findChild(node) {
- if (!node)
+ if (!node) {
return null;
+ }
return this.childrenByCallUID.get(node.callUID);
}
@@ -276,8 +297,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
// This allows us to restore them all to their original state when we revert.
save() {
- if (this._savedChildren)
+ if (this._savedChildren) {
return;
+ }
this._savedSelf = this.self;
this._savedTotal = this.total;
@@ -291,8 +313,9 @@ Profiler.ProfileDataGridNode = class extends DataGrid.DataGridNode {
* @protected
*/
restore() {
- if (!this._savedChildren)
+ if (!this._savedChildren) {
return;
+ }
this.self = this._savedSelf;
this.total = this._savedTotal;
@@ -350,21 +373,25 @@ Profiler.ProfileDataGridTree = class {
if (!comparator) {
if (isAscending) {
comparator = function(lhs, rhs) {
- if (lhs[property] < rhs[property])
+ if (lhs[property] < rhs[property]) {
return -1;
+ }
- if (lhs[property] > rhs[property])
+ if (lhs[property] > rhs[property]) {
return 1;
+ }
return 0;
};
} else {
comparator = function(lhs, rhs) {
- if (lhs[property] > rhs[property])
+ if (lhs[property] > rhs[property]) {
return -1;
+ }
- if (lhs[property] < rhs[property])
+ if (lhs[property] < rhs[property]) {
return 1;
+ }
return 0;
};
@@ -402,8 +429,9 @@ Profiler.ProfileDataGridTree = class {
* @return {?Profiler.ProfileDataGridNode}
*/
findChild(node) {
- if (!node)
+ if (!node) {
return null;
+ }
return this.childrenByCallUID.get(node.callUID);
}
@@ -420,16 +448,18 @@ Profiler.ProfileDataGridTree = class {
* @protected
*/
save() {
- if (this._savedChildren)
+ if (this._savedChildren) {
return;
+ }
this._savedTotal = this.total;
this._savedChildren = this.children.slice();
}
restore() {
- if (!this._savedChildren)
+ if (!this._savedChildren) {
return;
+ }
this.children = this._savedChildren;
this.total = this._savedTotal;
@@ -437,8 +467,9 @@ Profiler.ProfileDataGridTree = class {
const children = this.children;
const count = children.length;
- for (let index = 0; index < count; ++index)
+ for (let index = 0; index < count; ++index) {
children[index].restore();
+ }
this._savedChildren = null;
}
@@ -449,8 +480,9 @@ Profiler.ProfileDataGridTree = class {
*/
_matchFunction(searchConfig) {
const query = searchConfig.query.trim();
- if (!query.length)
+ if (!query.length) {
return null;
+ }
const greaterThan = (query.startsWith('>'));
const lessThan = (query.startsWith('<'));
@@ -461,17 +493,19 @@ Profiler.ProfileDataGridTree = class {
let queryNumber = parseFloat(query);
if (greaterThan || lessThan || equalTo) {
- if (equalTo && (greaterThan || lessThan))
+ if (equalTo && (greaterThan || lessThan)) {
queryNumber = parseFloat(query.substring(2));
- else
+ } else {
queryNumber = parseFloat(query.substring(1));
+ }
}
const queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber);
// Make equalTo implicitly true if it wasn't specified there is no other operator.
- if (!isNaN(queryNumber) && !(greaterThan || lessThan))
+ if (!isNaN(queryNumber) && !(greaterThan || lessThan)) {
equalTo = true;
+ }
const matcher = createPlainTextSearchRegex(query, 'i');
@@ -486,47 +520,60 @@ Profiler.ProfileDataGridTree = class {
if (percentUnits) {
if (lessThan) {
- if (profileDataGridNode.selfPercent < queryNumber)
+ if (profileDataGridNode.selfPercent < queryNumber) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.totalPercent < queryNumber)
+ }
+ if (profileDataGridNode.totalPercent < queryNumber) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
} else if (greaterThan) {
- if (profileDataGridNode.selfPercent > queryNumber)
+ if (profileDataGridNode.selfPercent > queryNumber) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.totalPercent > queryNumber)
+ }
+ if (profileDataGridNode.totalPercent > queryNumber) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
}
if (equalTo) {
- if (profileDataGridNode.selfPercent === queryNumber)
+ if (profileDataGridNode.selfPercent === queryNumber) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.totalPercent === queryNumber)
+ }
+ if (profileDataGridNode.totalPercent === queryNumber) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
}
} else if (millisecondsUnits || secondsUnits) {
if (lessThan) {
- if (profileDataGridNode.self < queryNumberMilliseconds)
+ if (profileDataGridNode.self < queryNumberMilliseconds) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.total < queryNumberMilliseconds)
+ }
+ if (profileDataGridNode.total < queryNumberMilliseconds) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
} else if (greaterThan) {
- if (profileDataGridNode.self > queryNumberMilliseconds)
+ if (profileDataGridNode.self > queryNumberMilliseconds) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.total > queryNumberMilliseconds)
+ }
+ if (profileDataGridNode.total > queryNumberMilliseconds) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
}
if (equalTo) {
- if (profileDataGridNode.self === queryNumberMilliseconds)
+ if (profileDataGridNode.self === queryNumberMilliseconds) {
profileDataGridNode._searchMatchedSelfColumn = true;
- if (profileDataGridNode.total === queryNumberMilliseconds)
+ }
+ if (profileDataGridNode.total === queryNumberMilliseconds) {
profileDataGridNode._searchMatchedTotalColumn = true;
+ }
}
}
if (profileDataGridNode.functionName.match(matcher) ||
- (profileDataGridNode.url && profileDataGridNode.url.match(matcher)))
+ (profileDataGridNode.url && profileDataGridNode.url.match(matcher))) {
profileDataGridNode._searchMatchedFunctionColumn = true;
+ }
if (profileDataGridNode._searchMatchedSelfColumn || profileDataGridNode._searchMatchedTotalColumn ||
profileDataGridNode._searchMatchedFunctionColumn) {
@@ -548,14 +595,16 @@ Profiler.ProfileDataGridTree = class {
performSearch(searchConfig, shouldJump, jumpBackwards) {
this.searchCanceled();
const matchesQuery = this._matchFunction(searchConfig);
- if (!matchesQuery)
+ if (!matchesQuery) {
return;
+ }
this._searchResults = [];
const deepSearch = this.deepSearch;
for (let current = this.children[0]; current; current = current.traverseNextNode(!deepSearch, null, !deepSearch)) {
- if (matchesQuery(current))
+ if (matchesQuery(current)) {
this._searchResults.push({profileNode: current});
+ }
}
this._searchResultIndex = jumpBackwards ? 0 : this._searchResults.length - 1;
this._searchableView.updateSearchMatchesCount(this._searchResults.length);
@@ -584,8 +633,9 @@ Profiler.ProfileDataGridTree = class {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchResults || !this._searchResults.length)
+ if (!this._searchResults || !this._searchResults.length) {
return;
+ }
this._searchResultIndex = (this._searchResultIndex + 1) % this._searchResults.length;
this._jumpToSearchResult(this._searchResultIndex);
}
@@ -594,8 +644,9 @@ Profiler.ProfileDataGridTree = class {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchResults || !this._searchResults.length)
+ if (!this._searchResults || !this._searchResults.length) {
return;
+ }
this._searchResultIndex = (this._searchResultIndex - 1 + this._searchResults.length) % this._searchResults.length;
this._jumpToSearchResult(this._searchResultIndex);
}
@@ -621,8 +672,9 @@ Profiler.ProfileDataGridTree = class {
*/
_jumpToSearchResult(index) {
const searchResult = this._searchResults[index];
- if (!searchResult)
+ if (!searchResult) {
return;
+ }
const profileNode = searchResult.profileNode;
profileNode.revealAndSelect();
this._searchableView.updateCurrentMatchIndex(index);
@@ -647,6 +699,12 @@ Profiler.ProfileDataGridNode.Formatter.prototype = {
/**
* @param {number} value
+ * @return {string}
+ */
+ formatValueAccessibleText(value) {},
+
+ /**
+ * @param {number} value
* @param {!Profiler.ProfileDataGridNode} node
* @return {string}
*/
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileHeader.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileHeader.js
index 8498fbe8324..2c27663e256 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileHeader.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileHeader.js
@@ -60,8 +60,9 @@ Profiler.ProfileHeader = class extends Common.Object {
}
removeTempFile() {
- if (this._tempFile)
+ if (this._tempFile) {
this._tempFile.remove();
+ }
}
dispose() {
@@ -80,7 +81,7 @@ Profiler.ProfileHeader = class extends Common.Object {
/**
* @param {!File} file
- * @return {!Promise<?Error>}
+ * @return {!Promise<?Error|?FileError>}
*/
loadFromFile(file) {
throw new Error('Not implemented');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
index 4184522e3e5..eaeb62debd0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
@@ -71,10 +71,11 @@ Profiler.ProfileLauncherView = class extends UI.VBox {
}
_updateControls() {
- if (this._isEnabled && this._recordButtonEnabled)
+ if (this._isEnabled && this._recordButtonEnabled) {
this._controlButton.removeAttribute('disabled');
- else
+ } else {
this._controlButton.setAttribute('disabled', '');
+ }
this._controlButton.title = this._recordButtonEnabled ? '' : UI.anotherProfilerActiveLabel();
if (this._isInstantProfile) {
this._controlButton.classList.remove('running');
@@ -89,8 +90,9 @@ Profiler.ProfileLauncherView = class extends UI.VBox {
this._controlButton.classList.add('primary-button');
this._controlButton.textContent = Common.UIString('Start');
}
- for (const item of this._typeIdToOptionElement.values())
+ for (const item of this._typeIdToOptionElement.values()) {
item.disabled = !!this._isProfiling;
+ }
}
profileStarted() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
index 9bba187488b..6cbb9f49d3c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
@@ -21,8 +21,9 @@ Profiler.ProfileType = class extends Common.Object {
this._profileBeingRecorded = null;
this._nextProfileUid = 1;
- if (!window.opener)
+ if (!window.opener) {
window.addEventListener('unload', this._clearTempStorage.bind(this), false);
+ }
}
/**
@@ -135,21 +136,23 @@ Profiler.ProfileType = class extends Common.Object {
*/
getProfile(uid) {
for (let i = 0; i < this._profiles.length; ++i) {
- if (this._profiles[i].uid === uid)
+ if (this._profiles[i].uid === uid) {
return this._profiles[i];
+ }
}
return null;
}
/**
* @param {!File} file
- * @return {!Promise<?Error>}
+ * @return {!Promise<?Error|?FileError>}
*/
loadFromFile(file) {
let name = file.name;
const fileExtension = this.fileExtension();
- if (fileExtension && name.endsWith(fileExtension))
+ if (fileExtension && name.endsWith(fileExtension)) {
name = name.substr(0, name.length - fileExtension.length);
+ }
const profile = this.createProfileLoadedFromFile(name);
profile.setFromFile();
this.setProfileBeingRecorded(profile);
@@ -178,15 +181,17 @@ Profiler.ProfileType = class extends Common.Object {
*/
removeProfile(profile) {
const index = this._profiles.indexOf(profile);
- if (index === -1)
+ if (index === -1) {
return;
+ }
this._profiles.splice(index, 1);
this._disposeProfile(profile);
}
_clearTempStorage() {
- for (let i = 0; i < this._profiles.length; ++i)
+ for (let i = 0; i < this._profiles.length; ++i) {
this._profiles[i].removeTempFile();
+ }
}
/**
@@ -207,8 +212,9 @@ Profiler.ProfileType = class extends Common.Object {
}
reset() {
- for (const profile of this._profiles.slice())
+ for (const profile of this._profiles.slice()) {
this._disposeProfile(profile);
+ }
this._profiles = [];
this._nextProfileUid = 1;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
index ab3c2e8183d..43e5e6a1517 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
@@ -32,8 +32,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortProfile, this);
this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, this._nodeSelected.bind(this, true));
this.dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode, this._nodeSelected.bind(this, false));
+ this.dataGrid.setRowContextMenuCallback(this._populateContextMenu.bind(this));
- this.viewSelectComboBox = new UI.ToolbarComboBox(this._changeView.bind(this));
+ this.viewSelectComboBox = new UI.ToolbarComboBox(this._changeView.bind(this), ls`Profile view mode`);
this.focusButton = new UI.ToolbarButton(Common.UIString('Focus selected function'), 'largeicon-visibility');
this.focusButton.setEnabled(false);
@@ -103,24 +104,26 @@ Profiler.ProfileView = class extends UI.SimpleView {
]);
const options =
- new Map(viewTypes.map(type => [type, this.viewSelectComboBox.createOption(optionNames.get(type), '', type)]));
+ new Map(viewTypes.map(type => [type, this.viewSelectComboBox.createOption(optionNames.get(type), type)]));
const optionName = this._viewType.get() || viewTypes[0];
const option = options.get(optionName) || options.get(viewTypes[0]);
this.viewSelectComboBox.select(option);
this._changeView();
- if (this._flameChart)
+ if (this._flameChart) {
this._flameChart.update();
+ }
}
/**
* @override
*/
focus() {
- if (this._flameChart)
+ if (this._flameChart) {
this._flameChart.focus();
- else
+ } else {
super.focus();
+ }
}
/**
@@ -136,8 +139,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
* @param {number} timeRight
*/
selectRange(timeLeft, timeRight) {
- if (!this._flameChart)
+ if (!this._flameChart) {
return;
+ }
this._flameChart.selectRange(timeLeft, timeRight);
}
@@ -172,6 +176,17 @@ Profiler.ProfileView = class extends UI.SimpleView {
}
/**
+ * @param {!UI.ContextMenu} contextMenu
+ * @param {!DataGrid.DataGridNode} gridNode
+ */
+ _populateContextMenu(contextMenu, gridNode) {
+ const node = /** @type {!Profiler.ProfileDataGridNode} */ (gridNode);
+ if (node.linkElement && !contextMenu.containsTarget(node.linkElement)) {
+ contextMenu.appendApplicableItems(node.linkElement);
+ }
+ }
+
+ /**
* @override
*/
willHide() {
@@ -179,8 +194,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
}
refresh() {
- if (!this.profileDataGridTree)
+ if (!this.profileDataGridTree) {
return;
+ }
const selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;
this.dataGrid.rootNode().removeChildren();
@@ -188,11 +204,13 @@ Profiler.ProfileView = class extends UI.SimpleView {
const children = this.profileDataGridTree.children;
const count = children.length;
- for (let index = 0; index < count; ++index)
+ for (let index = 0; index < count; ++index) {
this.dataGrid.rootNode().appendChild(children[index]);
+ }
- if (selectedProfileNode)
+ if (selectedProfileNode) {
selectedProfileNode.selected = true;
+ }
}
refreshVisibleData() {
@@ -265,8 +283,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
}
_ensureTextViewCreated() {
- if (this._textView)
+ if (this._textView) {
return;
+ }
this._textView = new UI.SimpleView(ls`Call tree`);
this._textView.registerRequiredCSS('profiler/profilesPanel.css');
this.populateTextView(this._textView);
@@ -286,38 +305,43 @@ Profiler.ProfileView = class extends UI.SimpleView {
}
_ensureFlameChartCreated() {
- if (this._flameChart)
+ if (this._flameChart) {
return;
+ }
this._dataProvider = this.createFlameChartDataProvider();
this._flameChart = new Profiler.CPUProfileFlameChart(this._searchableView, this._dataProvider);
- this._flameChart.addEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onEntrySelected.bind(this));
+ this._flameChart.addEventListener(PerfUI.FlameChart.Events.EntryInvoked, this._onEntryInvoked.bind(this));
}
/**
* @param {!Common.Event} event
*/
- _onEntrySelected(event) {
+ _onEntryInvoked(event) {
const entryIndex = event.data;
const node = this._dataProvider._entryNodes[entryIndex];
const debuggerModel = this._profileHeader._debuggerModel;
- if (!node || !node.scriptId || !debuggerModel)
+ if (!node || !node.scriptId || !debuggerModel) {
return;
+ }
const script = debuggerModel.scriptForId(node.scriptId);
- if (!script)
+ if (!script) {
return;
+ }
const location = /** @type {!SDK.DebuggerModel.Location} */ (
debuggerModel.createRawLocation(script, node.lineNumber, node.columnNumber));
Common.Revealer.reveal(Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location));
}
_changeView() {
- if (!this._profile)
+ if (!this._profile) {
return;
+ }
this._searchableView.closeSearch();
- if (this._visibleView)
+ if (this._visibleView) {
this._visibleView.detach();
+ }
this._viewType.set(this.viewSelectComboBox.selectedOption().value);
switch (this._viewType.get()) {
@@ -365,8 +389,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
* @param {!Common.Event} event
*/
_focusClicked(event) {
- if (!this.dataGrid.selectedNode)
+ if (!this.dataGrid.selectedNode) {
return;
+ }
this.resetButton.setEnabled(true);
this.profileDataGridTree.focus(this.dataGrid.selectedNode);
@@ -381,8 +406,9 @@ Profiler.ProfileView = class extends UI.SimpleView {
_excludeClicked(event) {
const selectedNode = this.dataGrid.selectedNode;
- if (!selectedNode)
+ if (!selectedNode) {
return;
+ }
selectedNode.deselect();
@@ -502,11 +528,13 @@ Profiler.WritableProfileHeader = class extends Profiler.ProfileHeader {
this._fileName = this._fileName ||
`${this.profileType().typeName()}-${new Date().toISO8601Compact()}${this.profileType().fileExtension()}`;
const accepted = await fileOutputStream.open(this._fileName);
- if (!accepted || !this._tempFile)
+ if (!accepted || !this._tempFile) {
return;
+ }
const data = await this._tempFile.read();
- if (data)
+ if (data) {
await fileOutputStream.write(data);
+ }
fileOutputStream.close();
}
@@ -538,8 +566,9 @@ Profiler.WritableProfileHeader = class extends Profiler.ProfileHeader {
}
this._jsonifiedProfile = null;
- if (this.profileType().profileBeingRecorded() === this)
+ if (this.profileType().profileBeingRecorded() === this) {
this.profileType().setProfileBeingRecorded(null);
+ }
return error;
}
@@ -551,7 +580,8 @@ Profiler.WritableProfileHeader = class extends Profiler.ProfileHeader {
this._protocolProfile = profile;
this._tempFile = new Bindings.TempFile();
this._tempFile.write([JSON.stringify(profile)]);
- if (this.canSaveToFile())
+ if (this.canSaveToFile()) {
this.dispatchEventToListeners(Profiler.ProfileHeader.Events.ProfileReceived);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
index d3383a05d0b..78a85082a7e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
@@ -52,6 +52,8 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
this._sidebarTree.appendChild(this.profilesItemTreeElement);
+ this._sidebarTree.element.addEventListener('keydown', this._onKeyDown.bind(this), false);
+
this.profileViews = createElement('div');
this.profileViews.id = 'profile-views';
this.profileViews.classList.add('vbox');
@@ -86,8 +88,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
this._profileToView = [];
this._typeIdToSidebarSection = {};
const types = this._profileTypes;
- for (let i = 0; i < types.length; i++)
+ for (let i = 0; i < types.length; i++) {
this._registerProfileType(types[i]);
+ }
this._launcherView.restoreSelectedProfileType();
this.profilesItemTreeElement.select();
this._showLauncherView();
@@ -95,8 +98,6 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
this._createFileSelectorElement();
this.element.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), false);
- this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), false);
-
SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this);
UI.context.addFlavorChangeListener(SDK.CPUProfilerModel, this._updateProfileTypeSpecificUI, this);
UI.context.addFlavorChangeListener(SDK.HeapProfilerModel, this._updateProfileTypeSpecificUI, this);
@@ -107,12 +108,14 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
*/
_onKeyDown(event) {
let handled = false;
- if (event.key === 'ArrowDown' && !event.altKey)
+ if (event.key === 'ArrowDown' && !event.altKey) {
handled = this._sidebarTree.selectNext();
- else if (event.key === 'ArrowUp' && !event.altKey)
+ } else if (event.key === 'ArrowUp' && !event.altKey) {
handled = this._sidebarTree.selectPrevious();
- if (handled)
+ }
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -124,8 +127,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
}
_createFileSelectorElement() {
- if (this._fileSelectorElement)
+ if (this._fileSelectorElement) {
this.element.removeChild(this._fileSelectorElement);
+ }
this._fileSelectorElement = UI.createFileSelectorElement(this._loadFromFile.bind(this));
Profiler.ProfilesPanel._fileSelectorElement = this._fileSelectorElement;
this.element.appendChild(this._fileSelectorElement);
@@ -160,23 +164,26 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
}
const error = await profileType.loadFromFile(file);
- if (error)
+ if (error) {
UI.MessageDialog.show(Common.UIString('Profile loading failed: %s.', error.message));
+ }
}
/**
* @return {boolean}
*/
toggleRecord() {
- if (!this._toggleRecordAction.enabled())
+ if (!this._toggleRecordAction.enabled()) {
return true;
+ }
const type = this._selectedProfileType;
const isProfiling = type.buttonClicked();
this._updateToggleRecordAction(isProfiling);
if (isProfiling) {
this._launcherView.profileStarted();
- if (type.hasTemporaryView())
+ if (type.hasTemporaryView()) {
this.showProfile(type.profileBeingRecorded());
+ }
} else {
this._launcherView.profileFinished();
}
@@ -195,12 +202,14 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
const enable = toggled || (!SDK.targetManager.allTargetsSuspended() && hasSelectedTarget);
this._toggleRecordAction.setEnabled(enable);
this._toggleRecordAction.setToggled(toggled);
- if (enable)
+ if (enable) {
this._toggleRecordButton.setTitle(this._selectedProfileType ? this._selectedProfileType.buttonTooltip : '');
- else
+ } else {
this._toggleRecordButton.setTitle(UI.anotherProfilerActiveLabel());
- if (this._selectedProfileType)
+ }
+ if (this._selectedProfileType) {
this._launcherView.updateProfileType(this._selectedProfileType, enable);
+ }
}
_profileBeingRecordedRemoved() {
@@ -289,8 +298,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
profileType.addEventListener(Profiler.ProfileType.Events.ProfileComplete, profileComplete, this);
const profiles = profileType.getProfiles();
- for (let i = 0; i < profiles.length; i++)
+ for (let i = 0; i < profiles.length; i++) {
this._addProfileHeader(profiles[i]);
+ }
}
/**
@@ -316,20 +326,23 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
const profileType = profile.profileType();
const typeId = profileType.id;
this._typeIdToSidebarSection[typeId].addProfileHeader(profile);
- if (!this.visibleView || this.visibleView === this._launcherView)
+ if (!this.visibleView || this.visibleView === this._launcherView) {
this.showProfile(profile);
+ }
}
/**
* @param {!Profiler.ProfileHeader} profile
*/
_removeProfileHeader(profile) {
- if (profile.profileType().profileBeingRecorded() === profile)
+ if (profile.profileType().profileBeingRecorded() === profile) {
this._profileBeingRecordedRemoved();
+ }
const i = this._indexOfViewForProfile(profile);
- if (i !== -1)
+ if (i !== -1) {
this._profileToView.splice(i, 1);
+ }
const typeId = profile.profileType().id;
const sectionIsEmpty = this._typeIdToSidebarSection[typeId].removeProfileHeader(profile);
@@ -349,17 +362,18 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
*/
showProfile(profile) {
if (!profile ||
- (profile.profileType().profileBeingRecorded() === profile) && !profile.profileType().hasTemporaryView())
+ (profile.profileType().profileBeingRecorded() === profile) && !profile.profileType().hasTemporaryView()) {
return null;
+ }
const view = this.viewForProfile(profile);
- if (view === this.visibleView)
+ if (view === this.visibleView) {
return view;
+ }
this.closeVisibleView();
view.show(this.profileViews);
- view.focus();
this._toolbarElement.classList.remove('hidden');
this.visibleView = view;
@@ -370,8 +384,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
this._profileViewToolbar.removeToolbarItems();
const toolbarItems = view.syncToolbarItems();
- for (let i = 0; i < toolbarItems.length; ++i)
+ for (let i = 0; i < toolbarItems.length; ++i) {
this._profileViewToolbar.appendToolbarItem(toolbarItems[i]);
+ }
return view;
}
@@ -399,8 +414,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
*/
viewForProfile(profile) {
const index = this._indexOfViewForProfile(profile);
- if (index !== -1)
+ if (index !== -1) {
return this._profileToView[index].view;
+ }
const view = profile.createView(this);
view.element.classList.add('profile-view');
this._profileToView.push({profile: profile, view: view});
@@ -416,8 +432,9 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
}
closeVisibleView() {
- if (this.visibleView)
+ if (this.visibleView) {
this.visibleView.detach();
+ }
delete this.visibleView;
}
@@ -484,8 +501,9 @@ Profiler.ProfileTypeSidebarSection = class extends UI.TreeElement {
const selected = firstProfileTreeElement.selected;
this.removeChild(firstProfileTreeElement);
group.sidebarTreeElement.appendChild(firstProfileTreeElement);
- if (selected)
+ if (selected) {
firstProfileTreeElement.revealAndSelect();
+ }
firstProfileTreeElement.setSmall(true);
firstProfileTreeElement.setMainTitle(Common.UIString('Run %d', 1));
@@ -509,8 +527,9 @@ Profiler.ProfileTypeSidebarSection = class extends UI.TreeElement {
*/
removeProfileHeader(profile) {
const index = this._sidebarElementIndex(profile);
- if (index === -1)
+ if (index === -1) {
return false;
+ }
const profileTreeElement = this._profileTreeElements[index];
this._profileTreeElements.splice(index, 1);
@@ -529,14 +548,16 @@ Profiler.ProfileTypeSidebarSection = class extends UI.TreeElement {
groupElements[0].setMainTitle(profile.title);
this.removeChild(group.sidebarTreeElement);
}
- if (groupElements.length !== 0)
+ if (groupElements.length !== 0) {
sidebarParent = group.sidebarTreeElement;
+ }
}
sidebarParent.removeChild(profileTreeElement);
profileTreeElement.dispose();
- if (this.childCount())
+ if (this.childCount()) {
return false;
+ }
this.hidden = true;
return true;
}
@@ -557,8 +578,9 @@ Profiler.ProfileTypeSidebarSection = class extends UI.TreeElement {
_sidebarElementIndex(profile) {
const elements = this._profileTreeElements;
for (let i = 0; i < elements.length; i++) {
- if (elements[i].profile === profile)
+ if (elements[i].profile === profile) {
return i;
+ }
}
return -1;
}
@@ -597,19 +619,20 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
this._iconElement = createElementWithClass('div', 'icon');
this._titlesElement = createElementWithClass('div', 'titles no-subtitle');
this._titleContainer = this._titlesElement.createChild('span', 'title-container');
- this._titleElement = this._titleContainer.createChild('span', 'title');
+ this.titleElement = this._titleContainer.createChild('span', 'title');
this._subtitleElement = this._titlesElement.createChild('span', 'subtitle');
- this._titleElement.textContent = profile.title;
+ this.titleElement.textContent = profile.title;
this._className = className;
this._small = false;
this._dataDisplayDelegate = dataDisplayDelegate;
this.profile = profile;
profile.addEventListener(Profiler.ProfileHeader.Events.UpdateStatus, this._updateStatus, this);
- if (profile.canSaveToFile())
+ if (profile.canSaveToFile()) {
this._createSaveLink();
- else
+ } else {
profile.addEventListener(Profiler.ProfileHeader.Events.ProfileReceived, this._onProfileReceived, this);
+ }
}
_createSaveLink() {
@@ -631,8 +654,9 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
this._subtitleElement.textContent = statusUpdate.subtitle || '';
this._titlesElement.classList.toggle('no-subtitle', !statusUpdate.subtitle);
}
- if (typeof statusUpdate.wait === 'boolean' && this.listItemElement)
+ if (typeof statusUpdate.wait === 'boolean' && this.listItemElement) {
this.listItemElement.classList.toggle('wait', statusUpdate.wait);
+ }
}
/**
@@ -641,8 +665,9 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
* @return {boolean}
*/
ondblclick(event) {
- if (!this._editing)
+ if (!this._editing) {
this._startEditing(/** @type {!Element} */ (event.target));
+ }
return false;
}
@@ -651,8 +676,9 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
*/
_startEditing(eventTarget) {
const container = eventTarget.enclosingNodeOrSelfWithClass('title');
- if (!container)
+ if (!container) {
return;
+ }
const config = new UI.InplaceEditor.Config(this._editingCommitted.bind(this), this._editingCancelled.bind(this));
this._editing = UI.InplaceEditor.startEditing(container, config);
}
@@ -697,10 +723,12 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
* @override
*/
onattach() {
- if (this._className)
+ if (this._className) {
this.listItemElement.classList.add(this._className);
- if (this._small)
+ }
+ if (this._small) {
this.listItemElement.classList.add('small');
+ }
this.listItemElement.appendChildren(this._iconElement, this._titlesElement);
this.listItemElement.addEventListener('contextmenu', this._handleContextMenuEvent.bind(this), true);
}
@@ -715,8 +743,9 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
contextMenu.headerSection().appendItem(
Common.UIString('Load\u2026'),
Profiler.ProfilesPanel._fileSelectorElement.click.bind(Profiler.ProfilesPanel._fileSelectorElement));
- if (profile.canSaveToFile())
+ if (profile.canSaveToFile()) {
contextMenu.saveSection().appendItem(Common.UIString('Save\u2026'), profile.saveToFile.bind(profile));
+ }
contextMenu.footerSection().appendItem(Common.UIString('Delete'), this.ondelete.bind(this));
contextMenu.show();
}
@@ -730,15 +759,16 @@ Profiler.ProfileSidebarTreeElement = class extends UI.TreeElement {
*/
setSmall(small) {
this._small = small;
- if (this.listItemElement)
+ if (this.listItemElement) {
this.listItemElement.classList.toggle('small', this._small);
+ }
}
/**
* @param {string} title
*/
setMainTitle(title) {
- this._titleElement.textContent = title;
+ this.titleElement.textContent = title;
}
};
@@ -765,8 +795,9 @@ Profiler.ProfileGroupSidebarTreeElement = class extends UI.TreeElement {
*/
onselect() {
const hasChildren = this.childCount() > 0;
- if (hasChildren)
+ if (hasChildren) {
this._dataDisplayDelegate.showProfile(this.lastChild().profile);
+ }
return hasChildren;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/TopDownProfileDataGrid.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/TopDownProfileDataGrid.js
index b073b7e7142..f9d0c498046 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/TopDownProfileDataGrid.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/TopDownProfileDataGrid.js
@@ -59,21 +59,24 @@ Profiler.TopDownProfileDataGridNode = class extends Profiler.ProfileDataGridNode
* @param {string} aCallUID
*/
static _excludeRecursively(container, aCallUID) {
- if (container._remainingChildren)
+ if (container._remainingChildren) {
container.populate();
+ }
container.save();
const children = container.children;
let index = container.children.length;
- while (index--)
+ while (index--) {
Profiler.TopDownProfileDataGridNode._excludeRecursively(children[index], aCallUID);
+ }
const child = container.childrenByCallUID.get(aCallUID);
- if (child)
+ if (child) {
Profiler.ProfileDataGridNode.merge(container, child, true);
+ }
}
/**
@@ -105,8 +108,9 @@ Profiler.TopDownProfileDataGridTree = class extends Profiler.ProfileDataGridTree
* @param {!Profiler.ProfileDataGridNode} profileDataGridNode
*/
focus(profileDataGridNode) {
- if (!profileDataGridNode)
+ if (!profileDataGridNode) {
return;
+ }
this.save();
profileDataGridNode.savePosition();
@@ -119,23 +123,26 @@ Profiler.TopDownProfileDataGridTree = class extends Profiler.ProfileDataGridTree
* @param {!Profiler.ProfileDataGridNode} profileDataGridNode
*/
exclude(profileDataGridNode) {
- if (!profileDataGridNode)
+ if (!profileDataGridNode) {
return;
+ }
this.save();
Profiler.TopDownProfileDataGridNode._excludeRecursively(this, profileDataGridNode.callUID);
- if (this.lastComparator)
+ if (this.lastComparator) {
this.sort(this.lastComparator, true);
+ }
}
/**
* @override
*/
restore() {
- if (!this._savedChildren)
+ if (!this._savedChildren) {
return;
+ }
this.children[0].restorePosition();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css b/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
index 45027e45a0f..9db15fd15f3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
@@ -189,10 +189,27 @@
padding: 2px;
}
+.heap-allocation-stack .stack-frame:hover:not(:focus) {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.heap-allocation-stack .stack-frame:focus {
+ background-color: var(--selection-bg-color);
+ color: var(--selection-fg-color);
+}
+
+.heap-allocation-stack .stack-frame:focus:hover {
+ background-color: var(--accent-color-hover);
+}
+
.heap-allocation-stack .stack-frame .devtools-link {
color: rgb(33%, 33%, 33%);
}
+.heap-allocation-stack .stack-frame:focus .devtools-link {
+ color: var(--selection-fg-color);
+}
+
.no-heap-allocation-stack {
padding: 5px;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
index e282a629ada..d5a959bf7d8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
@@ -3,9 +3,6 @@
<message name="IDS_DEVTOOLS_00018e8c8fc32e1ec073c0cdbadb5575" desc="Text in Heap Profile View of a profiler tool">
<ph name="NUMBER_WITHTHOUSANDSSEPARATOR_VALUE________">$1s<ex>1,021</ex></ph> KB
</message>
- <message name="IDS_DEVTOOLS_007c41a9025be2c8e14b496ed3ee00f8" desc="A context menu item in the Profiles Panel of a profiler tool">
- Save…
- </message>
<message name="IDS_DEVTOOLS_02184526968aa861a744df910647fcf0" desc="Text in Heap Snapshot Data Grids of a profiler tool">
Freed Size
</message>
@@ -15,6 +12,9 @@
<message name="IDS_DEVTOOLS_030361ea56fa177ebcbefe708a45b0f2" desc="Text in Heap Snapshot Data Grids of a profiler tool">
# Deleted
</message>
+ <message name="IDS_DEVTOOLS_03301bd5f0d1517cf88b2f8348b82dfc" desc="Accessible text for the value in bytes of a Memory allocation.">
+ <ph name="VALUE">$1s<ex>12345</ex></ph> bytes
+ </message>
<message name="IDS_DEVTOOLS_04042b5589b3d4fd4e1e7e44265ad247" desc="Total trend div title in Isolate Selector of a profiler tool">
Total page JS heap size change trend over the last <ph name="TRENDINTERVALMINUTES">$1s<ex>3</ex></ph> minutes.
</message>
@@ -36,9 +36,6 @@
<message name="IDS_DEVTOOLS_0aa6f4210bf373c95eda00232e93cd98" desc="Text in Heap Snapshot Data Grids of a profiler tool">
Distance
</message>
- <message name="IDS_DEVTOOLS_11a755d598c0c417f9a36758c3da7481" desc="Control button text content in Profile Launcher View of a profiler tool">
- Stop
- </message>
<message name="IDS_DEVTOOLS_13b5bfe96f3e2fe411c9f66f4a582adf" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
in
</message>
@@ -57,21 +54,9 @@
<message name="IDS_DEVTOOLS_1d36783e12317ed400ebeddeb072a27b" desc="Text in Profile View of a profiler tool">
Chart
</message>
- <message name="IDS_DEVTOOLS_1eaeeaeb638fdf7f6eeb047abbfd0f1a" desc="Text in CPUProfile View of a profiler tool">
- Self Time
- </message>
- <message name="IDS_DEVTOOLS_1f1e990a1d2ba8ab4dd873a192237c30" desc="Text in CPUProfile View of a profiler tool">
- <ph name="VALUE">$1.1f<ex>30.1</ex></ph> ms
- </message>
<message name="IDS_DEVTOOLS_27c0ad7a8ff8f9df8e13bb2d974c95d0" desc="Text in Heap Snapshot View of a profiler tool">
Allocation
</message>
- <message name="IDS_DEVTOOLS_290612199861c31d1036b185b4e69b75" desc="Text in Heap Snapshot Data Grids of a profiler tool">
- Summary
- </message>
- <message name="IDS_DEVTOOLS_2ce2fc341b0bd9219a3634ff43a90bde" desc="Alternate text read when describing the size of a memory allocation and its percentage of heap.">
- <ph name="THIS_DATA_COLUMNID_">$1s<ex>1 613 680</ex></ph>, <ph name="THIS_DATA_PERCENTCOLUMN_">$2s<ex>44 %</ex></ph>
- </message>
<message name="IDS_DEVTOOLS_2d7b69664bc4226fb198124fb707e57c" desc="Text in Heap Profile View of a profiler tool">
Snapshot <ph name="THIS_NEXTPROFILEUID__">$1s<ex>1</ex></ph>
</message>
@@ -81,9 +66,15 @@
<message name="IDS_DEVTOOLS_2def01e5dee6051b68f5b1e5e2fc8ad4" desc="Text in Heap Snapshot View of a profiler tool">
System Objects
</message>
+ <message name="IDS_DEVTOOLS_2ebf8a926edeb0ca7de35c9b563ba797" desc="Filter label text in the Memory tool to filter class names for a heap snapshot">
+ Class filter
+ </message>
<message name="IDS_DEVTOOLS_2f318b400ebcb22420251535452efef0" desc="Text in Heap Snapshot View of a profiler tool">
Containment
</message>
+ <message name="IDS_DEVTOOLS_2f31c2eec148687f0ae649ecf35af762" desc="Screen reader label for a select box that chooses the snapshot to use as a base in the Memory panel when vieweing a Heap Snapshot">
+ Base snapshot
+ </message>
<message name="IDS_DEVTOOLS_30f4a219667bb46c6fc92f3d665a866c" desc="aria label for javascript VM instances target list in heap profiler">
JavaScript VM instances
</message>
@@ -93,9 +84,6 @@
<message name="IDS_DEVTOOLS_35066690e799cd4e59123262e41b29c5" desc="Text in CPUProfile View of a profiler tool">
Stop CPU profiling
</message>
- <message name="IDS_DEVTOOLS_36917e785bd31d786ab9dd7790a9a4c2" desc="Text in Live Heap Profile View of a profiler tool">
- JS Heap
- </message>
<message name="IDS_DEVTOOLS_3a9619400e054970a7ab8b67c4ce5109" desc="Tooltip text that appears when hovering over the largeicon refresh button in the Profile View of a profiler tool">
Restore all functions
</message>
@@ -194,10 +182,7 @@
</message>
<message name="IDS_DEVTOOLS_6b59ba1fcfd868474cae169876f9cbfa" desc="Text in Heap Profile View of a profiler tool">
Native memory snapshots show sampled native allocations in the renderer process since start up.
- Chrome has to be started with --memlog=all flag. Check flags at chrome://flags
- </message>
- <message name="IDS_DEVTOOLS_6bb61b1a929f2a0186f2671cd8258bd9" desc="Warning icon title in Profile Data Grid of a profiler tool">
- Not optimized: <ph name="THIS__DEOPTREASON">$1s<ex>Optimized too many times</ex></ph>
+ <ph name="LOCKED_1">Chrome</ph> has to be started with <ph name="LOCKED_2">--memlog=all</ph> flag. Check flags at <ph name="LOCKED_1">chrome://flags</ph>
</message>
<message name="IDS_DEVTOOLS_6d27e30b2f09c2a451a6d123c1a35805" desc="Text in Profiles Panel of a profiler tool">
Run <ph name="_">$1d<ex>2</ex></ph>
@@ -205,6 +190,9 @@
<message name="IDS_DEVTOOLS_6db0d0f1832acb4a56fc82f2317e61e6" desc="Text in Profile View of a profiler tool">
Parsing…
</message>
+ <message name="IDS_DEVTOOLS_6de06ad67fbc56af1a7a5b16a41d2f2c" desc="Aria-label for profiles view combobox in memory tool">
+ Profile view mode
+ </message>
<message name="IDS_DEVTOOLS_6e9dd9cf5419fd65f433f1e4bbc5e6ad" desc="Text in Heap Profile View of a profiler tool">
SAMPLING PROFILES
</message>
@@ -247,9 +235,6 @@
<message name="IDS_DEVTOOLS_85000e6433d4ac4033e6d7f5a3466f92" desc="A context menu item in the Heap Profiler Panel of a profiler tool">
Reveal in Summary view
</message>
- <message name="IDS_DEVTOOLS_86408593c34af77fdd90df932f8b5261" desc="Text in Heap Snapshot Data Grids of a profiler tool">
- Function
- </message>
<message name="IDS_DEVTOOLS_86a699c935e3e7e36e334bb61a336f02" desc="Text in Heap Profile View of a profiler tool">
Start heap profiling
</message>
@@ -297,9 +282,6 @@
<message name="IDS_DEVTOOLS_9e854bf5f75e670228f33f9fe857793d" desc="Text in Heap Snapshot Data Grids of a profiler tool">
Size of the object plus the graph it retains in bytes
</message>
- <message name="IDS_DEVTOOLS_9f29da220ed82809ec5dd70af4e52904" desc="Text in CPUProfile View of a profiler tool">
- Total Time
- </message>
<message name="IDS_DEVTOOLS_a6122a65eaa676f700ae68d393054a37" desc="Control button text content in Profile Launcher View of a profiler tool">
Start
</message>
@@ -309,6 +291,9 @@
<message name="IDS_DEVTOOLS_a7bd935a88c629dc11c52e0c16c2a8a0" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
<ph name="DISTANCE">$1d<ex>2</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_a80420eef88d11f77532f1b9cb467fa3" desc="Screen reader label for a select box that chooses the perspective in the Memory panel when vieweing a Heap Snapshot">
+ Perspective
+ </message>
<message name="IDS_DEVTOOLS_a8445619abd08f3ba0ebfcb31183f7f9" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
</message>
@@ -318,9 +303,6 @@
<message name="IDS_DEVTOOLS_a97cce5b0a66cd7d7b7b7d2e06b7605c" desc="Text in Profiles Panel of a profiler tool">
Can&apos;t load file. Supported file extensions: &apos;<ph name="ARRAY_FROM_EXTENSIONS__JOIN________">$1s<ex>'.js', '.json'</ex></ph>&apos;.
</message>
- <message name="IDS_DEVTOOLS_aab112fba39c10ed5df335ae0e47f329" desc="Text in CPUProfile View of a profiler tool">
- Not optimized
- </message>
<message name="IDS_DEVTOOLS_ad49e602302b1ca117245c4f19ef4450" desc="Retaining paths title text content in Heap Snapshot View of a profiler tool">
Retainers
</message>
@@ -354,9 +336,6 @@
<message name="IDS_DEVTOOLS_c33e404a441c6ba9648f88af3c68a1ca" desc="Text in Heap Snapshot View of a profiler tool">
Statistics
</message>
- <message name="IDS_DEVTOOLS_c9cc8cce247e49bae79f15173ce97354" desc="Save link element text content in Profiles Panel of a profiler tool">
- Save
- </message>
<message name="IDS_DEVTOOLS_ca0dbad92a874b2f69b549293387925e" desc="Text in Heap Snapshot View of a profiler tool">
Code
</message>
@@ -433,9 +412,6 @@
<message name="IDS_DEVTOOLS_ef15fd2f45e6bb5ce57587895ba64f93" desc="Text in Heap Profile View of a profiler tool">
Browser
</message>
- <message name="IDS_DEVTOOLS_f19dbf2edb3a0bd74b0524d960ff21eb" desc="Text of button in Profile Launcher View of a profiler tool">
- Load
- </message>
<message name="IDS_DEVTOOLS_f3e40bc520cf1f22e4d36d5c5f8d2618" desc="Text in Heap Snapshot Grid Nodes of a profiler tool">
User object reachable from window
</message>
@@ -454,9 +430,6 @@
<message name="IDS_DEVTOOLS_fbbe8b507083defdbfe14a341551c77b" desc="Text in CPUProfile View of a profiler tool">
CPU profiles show where the execution time is spent in your page&apos;s JavaScript functions.
</message>
- <message name="IDS_DEVTOOLS_fdbd92f0c6b67291ca954b74885d434e" desc="Text in Heap Profile View of a profiler tool">
- Profile <ph name="TYPE_NEXTPROFILEUID__">$1d<ex>2</ex></ph>
- </message>
<message name="IDS_DEVTOOLS_ffd4ebcdf9ad139d4cd2c84d853f4f34" desc="Text in Heap Profile View of a profiler tool">
Total Size (bytes)
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js b/chromium/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
index 54c6cb54ad5..943fc1615c7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
@@ -28,17 +28,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/** @typedef {string} */
-Protocol.Error = Symbol('Protocol.Error');
+/**
+ * @typedef {string}
+ * @suppress {checkTypes}
+ */
+export const ProtocolError = Symbol('Protocol.Error');
+export const DevToolsStubErrorCode = -32015;
+// TODO(dgozman): we are not reporting generic errors in tests, but we should
+// instead report them and just have some expected errors in test expectations.
+const _GenericError = -32000;
+const _ConnectionClosedErrorCode = -32001;
/**
* @unrestricted
*/
-Protocol.InspectorBackend = class {
+export default class InspectorBackend {
constructor() {
- /** @type {!Map<string, !Protocol.InspectorBackend._AgentPrototype>} */
+ /** @type {!Map<string, !_AgentPrototype>} */
this._agentPrototypes = new Map();
- /** @type {!Map<string, !Protocol.InspectorBackend._DispatcherPrototype>} */
+ /** @type {!Map<string, !_DispatcherPrototype>} */
this._dispatcherPrototypes = new Map();
this._initialized = false;
}
@@ -63,37 +71,38 @@ Protocol.InspectorBackend = class {
*/
_addAgentGetterMethodToProtocolTargetPrototype(domain) {
let upperCaseLength = 0;
- while (upperCaseLength < domain.length && domain[upperCaseLength].toLowerCase() !== domain[upperCaseLength])
+ while (upperCaseLength < domain.length && domain[upperCaseLength].toLowerCase() !== domain[upperCaseLength]) {
++upperCaseLength;
+ }
const methodName = domain.substr(0, upperCaseLength).toLowerCase() + domain.slice(upperCaseLength) + 'Agent';
/**
- * @this {Protocol.TargetBase}
+ * @this {TargetBase}
*/
function agentGetter() {
return this._agents[domain];
}
- Protocol.TargetBase.prototype[methodName] = agentGetter;
+ TargetBase.prototype[methodName] = agentGetter;
/**
- * @this {Protocol.TargetBase}
+ * @this {TargetBase}
*/
function registerDispatcher(dispatcher) {
this.registerDispatcher(domain, dispatcher);
}
- Protocol.TargetBase.prototype['register' + domain + 'Dispatcher'] = registerDispatcher;
+ TargetBase.prototype['register' + domain + 'Dispatcher'] = registerDispatcher;
}
/**
* @param {string} domain
- * @return {!Protocol.InspectorBackend._AgentPrototype}
+ * @return {!_AgentPrototype}
*/
_agentPrototype(domain) {
if (!this._agentPrototypes.has(domain)) {
- this._agentPrototypes.set(domain, new Protocol.InspectorBackend._AgentPrototype(domain));
+ this._agentPrototypes.set(domain, new _AgentPrototype(domain));
this._addAgentGetterMethodToProtocolTargetPrototype(domain);
}
@@ -102,11 +111,12 @@ Protocol.InspectorBackend = class {
/**
* @param {string} domain
- * @return {!Protocol.InspectorBackend._DispatcherPrototype}
+ * @return {!_DispatcherPrototype}
*/
_dispatcherPrototype(domain) {
- if (!this._dispatcherPrototypes.has(domain))
- this._dispatcherPrototypes.set(domain, new Protocol.InspectorBackend._DispatcherPrototype());
+ if (!this._dispatcherPrototypes.has(domain)) {
+ this._dispatcherPrototypes.set(domain, new _DispatcherPrototype());
+ }
return this._dispatcherPrototypes.get(domain);
}
@@ -129,8 +139,9 @@ Protocol.InspectorBackend = class {
registerEnum(type, values) {
const domainAndName = type.split('.');
const domain = domainAndName[0];
- if (!Protocol[domain])
+ if (!Protocol[domain]) {
Protocol[domain] = {};
+ }
Protocol[domain][domainAndName[1]] = values;
this._initialized = true;
@@ -166,47 +177,68 @@ Protocol.InspectorBackend = class {
clientCallback(defaultValue);
return;
}
- if (constructor)
+ if (constructor) {
clientCallback(new constructor(value));
- else
+ } else {
clientCallback(value);
+ }
}
return callbackWrapper;
}
-};
+}
-Protocol.DevToolsStubErrorCode = -32015;
-
-Protocol.inspectorBackend = new Protocol.InspectorBackend();
+/** @type {function():!Connection} */
+let _factory;
/**
* @interface
*/
-Protocol.Connection = function() {};
+export class Connection {
+ constructor() {
+ /** @type {?function(!Object)} */
+ this._onMessage;
+ }
-Protocol.Connection.prototype = {
/**
* @param {function((!Object|string))} onMessage
*/
- setOnMessage(onMessage) {},
+ setOnMessage(onMessage) {
+ }
/**
* @param {function(string)} onDisconnect
*/
- setOnDisconnect(onDisconnect) {},
+ setOnDisconnect(onDisconnect) {
+ }
/**
* @param {string} message
*/
- sendRawMessage(message) {},
+ sendRawMessage(message) {
+ }
/**
* @return {!Promise}
*/
- disconnect() {},
-};
+ disconnect() {
+ }
+
+ /**
+ * @param {function():!Connection} factory
+ */
+ static setFactory(factory) {
+ _factory = factory;
+ }
+
+ /**
+ * @return {function():!Connection}
+ */
+ static getFactory() {
+ return _factory;
+ }
+}
-Protocol.test = {
+const test = {
/**
* This will get called for every protocol message.
* Protocol.test.dumpProtocol = console.log
@@ -234,42 +266,20 @@ Protocol.test = {
/**
* Set to get notified about any messages sent over protocol.
- * @type {?function({domain: string, method: string, params: !Object, id: number})}
+ * @type {?function({domain: string, method: string, params: !Object, id: number}, ?TargetBase)}
*/
onMessageSent: null,
/**
* Set to get notified about any messages received over protocol.
- * @type {?function(!Object)}
+ * @type {?function(!Object, ?TargetBase)}
*/
onMessageReceived: null,
};
-/**
- * @param {function():!Protocol.Connection} factory
- */
-Protocol.Connection.setFactory = function(factory) {
- Protocol.Connection._factory = factory;
-};
-
-
-/** @type {function():!Protocol.Connection} */
-Protocol.Connection._factory;
-
-/**
- * Takes error and result.
- * @typedef {function(?Object, ?Object)}
- */
-Protocol._Callback;
-
-// TODO(dgozman): we are not reporting generic errors in tests, but we should
-// instead report them and just have some expected errors in test expectations.
-Protocol._GenericError = -32000;
-Protocol._ConnectionClosedErrorCode = -32001;
-
-Protocol.SessionRouter = class {
+export class SessionRouter {
/**
- * @param {!Protocol.Connection} connection
+ * @param {!Connection} connection
*/
constructor(connection) {
this._connection = connection;
@@ -277,28 +287,29 @@ Protocol.SessionRouter = class {
this._pendingResponsesCount = 0;
this._domainToLogger = new Map();
- /** @type {!Map<string, {target: !Protocol.TargetBase, callbacks: !Map<number, !Protocol._Callback>, proxyConnection: ?Protocol.Connection}>} */
+ /** @type {!Map<string, {target: !TargetBase, callbacks: !Map<number, !Protocol._Callback>, proxyConnection: ?Connection}>} */
this._sessions = new Map();
/** @type {!Array<function()>} */
this._pendingScripts = [];
- Protocol.test.deprecatedRunAfterPendingDispatches = this._deprecatedRunAfterPendingDispatches.bind(this);
- Protocol.test.sendRawMessage = this._sendRawMessageForTesting.bind(this);
+ test.deprecatedRunAfterPendingDispatches = this._deprecatedRunAfterPendingDispatches.bind(this);
+ test.sendRawMessage = this._sendRawMessageForTesting.bind(this);
this._connection.setOnMessage(this._onMessage.bind(this));
this._connection.setOnDisconnect(reason => {
const session = this._sessions.get('');
- if (session)
+ if (session) {
session.target.dispose(reason);
+ }
});
}
/**
- * @param {!Protocol.TargetBase} target
+ * @param {!TargetBase} target
* @param {string} sessionId
- * @param {?Protocol.Connection} proxyConnection
+ * @param {?Connection} proxyConnection
*/
registerSession(target, sessionId, proxyConnection) {
this._sessions.set(sessionId, {target, callbacks: new Map(), proxyConnection});
@@ -309,12 +320,25 @@ Protocol.SessionRouter = class {
*/
unregisterSession(sessionId) {
const session = this._sessions.get(sessionId);
- for (const callback of session.callbacks.values())
- Protocol.SessionRouter.dispatchConnectionError(callback);
+ for (const callback of session.callbacks.values()) {
+ SessionRouter.dispatchConnectionError(callback);
+ }
this._sessions.delete(sessionId);
}
/**
+ * @param {string} sessionId
+ * @return {?TargetBase}
+ */
+ _getTargetBySessionId(sessionId) {
+ const session = this._sessions.get(sessionId ? sessionId : '');
+ if (!session) {
+ return null;
+ }
+ return session.target;
+ }
+
+ /**
* @return {number}
*/
_nextMessageId() {
@@ -322,7 +346,7 @@ Protocol.SessionRouter = class {
}
/**
- * @return {!Protocol.Connection}
+ * @return {!Connection}
*/
connection() {
return this._connection;
@@ -340,17 +364,22 @@ Protocol.SessionRouter = class {
const messageId = this._nextMessageId();
messageObject.id = messageId;
messageObject.method = method;
- if (params)
+ if (params) {
messageObject.params = params;
- if (sessionId)
+ }
+ if (sessionId) {
messageObject.sessionId = sessionId;
+ }
- if (Protocol.test.dumpProtocol)
- Protocol.test.dumpProtocol('frontend: ' + JSON.stringify(messageObject));
+ if (test.dumpProtocol) {
+ test.dumpProtocol('frontend: ' + JSON.stringify(messageObject));
+ }
- if (Protocol.test.onMessageSent) {
+ if (test.onMessageSent) {
const paramsObject = JSON.parse(JSON.stringify(params || {}));
- Protocol.test.onMessageSent({domain, method, params: /** @type {!Object} */ (paramsObject), id: messageId});
+ test.onMessageSent(
+ {domain, method, params: /** @type {!Object} */ (paramsObject), id: messageId},
+ this._getTargetBySessionId(sessionId));
}
++this._pendingResponsesCount;
@@ -372,49 +401,76 @@ Protocol.SessionRouter = class {
* @param {!Object|string} message
*/
_onMessage(message) {
- if (Protocol.test.dumpProtocol)
- Protocol.test.dumpProtocol('backend: ' + ((typeof message === 'string') ? message : JSON.stringify(message)));
+ if (test.dumpProtocol) {
+ test.dumpProtocol('backend: ' + ((typeof message === 'string') ? message : JSON.stringify(message)));
+ }
- if (Protocol.test.onMessageReceived) {
+ if (test.onMessageReceived) {
const messageObjectCopy = JSON.parse((typeof message === 'string') ? message : JSON.stringify(message));
- Protocol.test.onMessageReceived(/** @type {!Object} */ (messageObjectCopy));
+ test.onMessageReceived(
+ /** @type {!Object} */ (messageObjectCopy), this._getTargetBySessionId(messageObjectCopy.sessionId));
}
const messageObject = /** @type {!Object} */ ((typeof message === 'string') ? JSON.parse(message) : message);
- const sessionId = messageObject.sessionId || '';
- const session = this._sessions.get(sessionId);
- if (!session) {
- Protocol.InspectorBackend.reportProtocolError('Protocol Error: the message with wrong session id', messageObject);
- return;
- }
+ // Send all messages to proxy connections.
+ let proxyConnectionIsActive = false;
+ for (const session of this._sessions.values()) {
+ if (!session.proxyConnection) {
+ continue;
+ }
- if (session.target._needsNodeJSPatching)
- Protocol.NodeURL.patch(messageObject);
+ // Only the Audits panel has use proxy connections. If it is ever possible to have multiple active at the
+ // same time, it should be test thoroughly.
+ if (proxyConnectionIsActive) {
+ Protocol.InspectorBackend.reportProtocolError(
+ 'Protocol Error: multiple proxy connections are not explicitly supported right now', messageObject);
+ }
- if (session.proxyConnection) {
if (session.proxyConnection._onMessage) {
session.proxyConnection._onMessage(messageObject);
+ proxyConnectionIsActive = true;
} else {
Protocol.InspectorBackend.reportProtocolError(
- 'Protocol Error: the message has a proxyConnection with no _onMessage', messageObject);
+ 'Protocol Error: the session has a proxyConnection with no _onMessage', messageObject);
+ }
+ }
+
+ const sessionId = messageObject.sessionId || '';
+ const session = this._sessions.get(sessionId);
+ if (!session) {
+ if (!proxyConnectionIsActive) {
+ Protocol.InspectorBackend.reportProtocolError(
+ 'Protocol Error: the message with wrong session id', messageObject);
}
return;
}
+ // If this message is directly for the target controlled by the proxy connection, don't handle it.
+ if (session.proxyConnection) {
+ return;
+ }
+
+ if (session.target._needsNodeJSPatching) {
+ Protocol.NodeURL.patch(messageObject);
+ }
+
if ('id' in messageObject) { // just a response for some request
const callback = session.callbacks.get(messageObject.id);
session.callbacks.delete(messageObject.id);
if (!callback) {
- Protocol.InspectorBackend.reportProtocolError('Protocol Error: the message with wrong id', messageObject);
+ if (!proxyConnectionIsActive) {
+ Protocol.InspectorBackend.reportProtocolError('Protocol Error: the message with wrong id', messageObject);
+ }
return;
}
callback(messageObject.error, messageObject.result);
--this._pendingResponsesCount;
- if (this._pendingScripts.length && !this._pendingResponsesCount)
+ if (this._pendingScripts.length && !this._pendingResponsesCount) {
this._deprecatedRunAfterPendingDispatches();
+ }
} else {
if (!('method' in messageObject)) {
Protocol.InspectorBackend.reportProtocolError('Protocol Error: the message without method', messageObject);
@@ -437,15 +493,17 @@ Protocol.SessionRouter = class {
* @param {function()=} script
*/
_deprecatedRunAfterPendingDispatches(script) {
- if (script)
+ if (script) {
this._pendingScripts.push(script);
+ }
// Execute all promises.
setTimeout(() => {
- if (!this._pendingResponsesCount)
+ if (!this._pendingResponsesCount) {
this._executeAfterPendingDispatches();
- else
+ } else {
this._deprecatedRunAfterPendingDispatches();
+ }
}, 0);
}
@@ -453,8 +511,9 @@ Protocol.SessionRouter = class {
if (!this._pendingResponsesCount) {
const scripts = this._pendingScripts;
this._pendingScripts = [];
- for (let id = 0; id < scripts.length; ++id)
+ for (let id = 0; id < scripts.length; ++id) {
scripts[id]();
+ }
}
}
@@ -464,48 +523,49 @@ Protocol.SessionRouter = class {
static dispatchConnectionError(callback) {
const error = {
message: 'Connection is closed, can\'t dispatch pending call',
- code: Protocol._ConnectionClosedErrorCode,
+ code: _ConnectionClosedErrorCode,
data: null
};
setTimeout(() => callback(error, null), 0);
}
-};
+}
/**
* @unrestricted
*/
-Protocol.TargetBase = class {
+export class TargetBase {
/**
* @param {boolean} needsNodeJSPatching
- * @param {?Protocol.TargetBase} parentTarget
+ * @param {?TargetBase} parentTarget
* @param {string} sessionId
- * @param {?Protocol.Connection} connection
+ * @param {?Connection} connection
*/
constructor(needsNodeJSPatching, parentTarget, sessionId, connection) {
this._needsNodeJSPatching = needsNodeJSPatching;
this._sessionId = sessionId;
- if ((!parentTarget && connection) || (!parentTarget && sessionId) || (connection && sessionId))
+ if ((!parentTarget && connection) || (!parentTarget && sessionId) || (connection && sessionId)) {
throw new Error('Either connection or sessionId (but not both) must be supplied for a child target');
- if (sessionId)
+ }
+ if (sessionId) {
this._router = parentTarget._router;
- else if (connection)
- this._router = new Protocol.SessionRouter(connection);
- else
- this._router = new Protocol.SessionRouter(Protocol.Connection._factory());
+ } else if (connection) {
+ this._router = new SessionRouter(connection);
+ } else {
+ this._router = new SessionRouter(_factory());
+ }
this._router.registerSession(this, this._sessionId);
this._agents = {};
for (const [domain, agentPrototype] of Protocol.inspectorBackend._agentPrototypes) {
- this._agents[domain] = Object.create(/** @type {!Protocol.InspectorBackend._AgentPrototype} */ (agentPrototype));
+ this._agents[domain] = Object.create(/** @type {!_AgentPrototype} */ (agentPrototype));
this._agents[domain]._target = this;
}
this._dispatchers = {};
for (const [domain, dispatcherPrototype] of Protocol.inspectorBackend._dispatcherPrototypes) {
- this._dispatchers[domain] =
- Object.create(/** @type {!Protocol.InspectorBackend._DispatcherPrototype} */ (dispatcherPrototype));
+ this._dispatchers[domain] = Object.create(/** @type {!_DispatcherPrototype} */ (dispatcherPrototype));
this._dispatchers[domain]._dispatchers = [];
}
}
@@ -515,8 +575,9 @@ Protocol.TargetBase = class {
* @param {!Object} dispatcher
*/
registerDispatcher(domain, dispatcher) {
- if (!this._dispatchers[domain])
+ if (!this._dispatchers[domain]) {
return;
+ }
this._dispatchers[domain].addDomainDispatcher(dispatcher);
}
@@ -540,17 +601,17 @@ Protocol.TargetBase = class {
}
/**
- * @return {!Protocol.SessionRouter}
+ * @return {!SessionRouter}
*/
router() {
return this._router;
}
-};
+}
/**
* @unrestricted
*/
-Protocol.InspectorBackend._AgentPrototype = class {
+export class _AgentPrototype {
/**
* @param {string} domain
*/
@@ -571,13 +632,12 @@ Protocol.InspectorBackend._AgentPrototype = class {
/**
* @param {...*} vararg
- * @this {Protocol.InspectorBackend._AgentPrototype}
+ * @this {_AgentPrototype}
* @return {!Promise.<*>}
*/
function sendMessagePromise(vararg) {
const params = Array.prototype.slice.call(arguments);
- return Protocol.InspectorBackend._AgentPrototype.prototype._sendMessageToBackendPromise.call(
- this, domainAndMethod, signature, params);
+ return _AgentPrototype.prototype._sendMessageToBackendPromise.call(this, domainAndMethod, signature, params);
}
this[methodName] = sendMessagePromise;
@@ -585,7 +645,7 @@ Protocol.InspectorBackend._AgentPrototype = class {
/**
* @param {!Object} request
* @return {!Promise}
- * @this {Protocol.InspectorBackend._AgentPrototype}
+ * @this {_AgentPrototype}
*/
function invoke(request) {
return this._invoke(domainAndMethod, request);
@@ -594,8 +654,9 @@ Protocol.InspectorBackend._AgentPrototype = class {
this['invoke_' + methodName] = invoke;
this._replyArgs[domainAndMethod] = replyArgs;
- if (hasErrorData)
+ if (hasErrorData) {
this._hasErrorData[domainAndMethod] = true;
+ }
}
/**
@@ -622,8 +683,9 @@ Protocol.InspectorBackend._AgentPrototype = class {
}
const value = args.shift();
- if (optionalFlag && typeof value === 'undefined')
+ if (optionalFlag && typeof value === 'undefined') {
continue;
+ }
if (typeof value !== typeName) {
errorCallback(
@@ -660,14 +722,16 @@ Protocol.InspectorBackend._AgentPrototype = class {
errorMessage = message;
}
const params = this._prepareParameters(method, signature, args, onError);
- if (errorMessage)
+ if (errorMessage) {
return Promise.resolve(null);
+ }
return new Promise(resolve => {
const callback = (error, result) => {
- if (error && !Protocol.test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode &&
- error.code !== Protocol._GenericError && error.code !== Protocol._ConnectionClosedErrorCode)
+ if (error && !test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode &&
+ error.code !== _GenericError && error.code !== _ConnectionClosedErrorCode) {
console.error('Request ' + method + ' failed. ' + JSON.stringify(error));
+ }
if (error) {
@@ -678,10 +742,11 @@ Protocol.InspectorBackend._AgentPrototype = class {
resolve(result && args.length ? result[args[0]] : undefined);
};
- if (!this._target._router)
- Protocol.SessionRouter.dispatchConnectionError(callback);
- else
+ if (!this._target._router) {
+ SessionRouter.dispatchConnectionError(callback);
+ } else {
this._target._router.sendMessage(this._target._sessionId, this._domain, method, params, callback);
+ }
});
}
@@ -693,30 +758,34 @@ Protocol.InspectorBackend._AgentPrototype = class {
_invoke(method, request) {
return new Promise(fulfill => {
const callback = (error, result) => {
- if (error && !Protocol.test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode &&
- error.code !== Protocol._GenericError && error.code !== Protocol._ConnectionClosedErrorCode)
+ if (error && !test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode &&
+ error.code !== _GenericError && error.code !== _ConnectionClosedErrorCode) {
console.error('Request ' + method + ' failed. ' + JSON.stringify(error));
+ }
- if (!result)
+ if (!result) {
result = {};
- if (error)
+ }
+ if (error) {
result[Protocol.Error] = error.message;
+ }
fulfill(result);
};
- if (!this._target._router)
- Protocol.SessionRouter.dispatchConnectionError(callback);
- else
+ if (!this._target._router) {
+ SessionRouter.dispatchConnectionError(callback);
+ } else {
this._target._router.sendMessage(this._target._sessionId, this._domain, method, request, callback);
+ }
});
}
-};
+}
/**
* @unrestricted
*/
-Protocol.InspectorBackend._DispatcherPrototype = class {
+export class _DispatcherPrototype {
constructor() {
this._eventArgs = {};
}
@@ -741,8 +810,9 @@ Protocol.InspectorBackend._DispatcherPrototype = class {
* @param {!Object} messageObject
*/
dispatch(functionName, messageObject) {
- if (!this._dispatchers.length)
+ if (!this._dispatchers.length) {
return;
+ }
if (!this._eventArgs[messageObject.method]) {
Protocol.InspectorBackend.reportProtocolError(
@@ -753,14 +823,59 @@ Protocol.InspectorBackend._DispatcherPrototype = class {
const params = [];
if (messageObject.params) {
const paramNames = this._eventArgs[messageObject.method];
- for (let i = 0; i < paramNames.length; ++i)
+ for (let i = 0; i < paramNames.length; ++i) {
params.push(messageObject.params[paramNames[i]]);
+ }
}
for (let index = 0; index < this._dispatchers.length; ++index) {
const dispatcher = this._dispatchers[index];
- if (functionName in dispatcher)
+ if (functionName in dispatcher) {
dispatcher[functionName].apply(dispatcher, params);
+ }
}
}
-};
+}
+
+/* Legacy exported object */
+self.Protocol = self.Protocol || {};
+
+/* Legacy exported object */
+Protocol = Protocol || {};
+
+Protocol.DevToolsStubErrorCode = DevToolsStubErrorCode;
+/** @typedef {string} */
+Protocol.Error = ProtocolError;
+
+/** @constructor */
+Protocol.InspectorBackend = InspectorBackend;
+
+/**
+ * @unrestricted
+ */
+Protocol.InspectorBackend._AgentPrototype = _AgentPrototype;
+
+/**
+ * @unrestricted
+ */
+Protocol.InspectorBackend._DispatcherPrototype = _DispatcherPrototype;
+
+/** @interface */
+Protocol.Connection = Connection;
+
+/** @type {!InspectorBackend} */
+Protocol.inspectorBackend = new InspectorBackend();
+
+Protocol.test = test;
+
+/** @constructor */
+Protocol.SessionRouter = SessionRouter;
+
+/** @constructor */
+Protocol.TargetBase = TargetBase;
+
+/**
+ * Takes error and result.
+ * @typedef {function(?Object, ?Object)}
+ */
+Protocol._Callback; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol/NodeURL.js b/chromium/third_party/blink/renderer/devtools/front_end/protocol/NodeURL.js
index e69d057cff2..d64cfc49806 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/protocol/NodeURL.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol/NodeURL.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Protocol.NodeURL = class {
+export default class NodeURL {
/**
* @param {!Object} object
*/
@@ -14,14 +14,16 @@ Protocol.NodeURL = class {
* @param {string} path
*/
function process(object, path) {
- if (object.url && Protocol.NodeURL._isPlatformPath(object.url, Host.isWin()))
+ if (object.url && NodeURL._isPlatformPath(object.url, Host.isWin())) {
object.url = Common.ParsedURL.platformPathToURL(object.url);
+ }
for (const entry of Object.entries(object)) {
const key = entry[0];
const value = entry[1];
const entryPath = path + '.' + key;
- if (entryPath !== '.result.result.value' && value !== null && typeof value === 'object')
+ if (entryPath !== '.result.result.value' && value !== null && typeof value === 'object') {
process(value, entryPath);
+ }
}
}
}
@@ -39,4 +41,13 @@ Protocol.NodeURL = class {
return fileSystemPath.length ? fileSystemPath[0] === '/' : false;
}
}
-};
+}
+
+/* Legacy exported object */
+self.Protocol = self.Protocol || {};
+
+/* Legacy exported object */
+Protocol = Protocol || {};
+
+/** @constructor */
+Protocol.NodeURL = NodeURL;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol/module.json b/chromium/third_party/blink/renderer/devtools/front_end/protocol/module.json
index 9dda4bdae09..6dc2f8e4114 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/protocol/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol/module.json
@@ -3,7 +3,9 @@
"common",
"host"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "protocol.js",
"NodeURL.js",
"InspectorBackend.js",
"../InspectorBackendCommands.js"
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol/protocol.js b/chromium/third_party/blink/renderer/devtools/front_end/protocol/protocol.js
new file mode 100644
index 00000000000..4b097555794
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol/protocol.js
@@ -0,0 +1,15 @@
+// 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 './InspectorBackend.js';
+import './NodeURL.js';
+import '../InspectorBackendCommands.js';
+
+import * as InspectorBackend from './InspectorBackend.js';
+import * as NodeURL from './NodeURL.js';
+
+export {
+ InspectorBackend,
+ NodeURL,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js b/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js
index cb0f4365af5..10be5aedb93 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js
@@ -15,7 +15,8 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
{id: 'direction', title: ls`Direction`, visible: false, sortable: true, hideable: true, weight: 30},
{id: 'request', title: ls`Request`, visible: true, hideable: true, weight: 60},
{id: 'response', title: ls`Response`, visible: true, hideable: true, weight: 60},
- {id: 'timestamp', title: ls`Timestamp`, visible: false, sortable: true, hideable: true, weight: 30}
+ {id: 'timestamp', title: ls`Timestamp`, visible: false, sortable: true, hideable: true, weight: 30},
+ {id: 'target', title: ls`Target`, visible: false, sortable: true, hideable: true, weight: 30}
];
this.registerRequiredCSS('protocol_monitor/protocolMonitor.css');
@@ -60,21 +61,24 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
this._filterParser = new TextUtils.FilterParser(keys);
this._suggestionBuilder = new UI.FilterSuggestionBuilder(keys);
- this._textFilterUI =
- new UI.ToolbarInput(ls`Filter`, 1, .2, '', this._suggestionBuilder.completions.bind(this._suggestionBuilder));
+ this._textFilterUI = new UI.ToolbarInput(
+ ls`Filter`, '', 1, .2, '', this._suggestionBuilder.completions.bind(this._suggestionBuilder));
this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, event => {
const query = /** @type {string} */ (event.data);
const filters = this._filterParser.parse(query);
this._filter = node => {
for (const {key, text, negative} of filters) {
- if (!text)
+ if (!text) {
continue;
+ }
const data = key ? node.data[key] : node.data;
- if (!data)
+ if (!data) {
continue;
+ }
const found = JSON.stringify(data).toLowerCase().indexOf(text.toLowerCase()) !== -1;
- if (found === negative)
+ if (found === negative) {
return false;
+ }
}
return true;
};
@@ -86,8 +90,9 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
_filterNodes() {
for (const node of this._nodes) {
if (this._filter(node)) {
- if (!node.parent)
+ if (!node.parent) {
this._dataGrid.insertChild(node);
+ }
} else {
node.remove();
}
@@ -117,7 +122,7 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
contextMenu.defaultSection().appendItem(ls`Documentation`, () => {
const [domain, method] = node.data.method.split('.');
const type = node.data.direction === 'sent' ? 'method' : 'event';
- InspectorFrontendHost.openInNewTab(
+ Host.InspectorFrontendHost.openInNewTab(
`https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}`);
});
}
@@ -132,15 +137,17 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
_updateColumnVisibility() {
const visibleColumns = /** @type {!Object.<string, boolean>} */ ({});
- for (const columnConfig of this._columns)
+ for (const columnConfig of this._columns) {
visibleColumns[columnConfig.id] = columnConfig.visible;
+ }
this._dataGrid.setColumnsVisiblity(visibleColumns);
}
_sortDataGrid() {
const sortColumnId = this._dataGrid.sortColumnId();
- if (!sortColumnId)
+ if (!sortColumnId) {
return;
+ }
let columnIsNumeric = true;
switch (sortColumnId) {
@@ -160,8 +167,9 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
* @override
*/
wasShown() {
- if (this._started)
+ if (this._started) {
return;
+ }
this._started = true;
this._startTime = Date.now();
this._setRecording(true);
@@ -180,43 +188,71 @@ ProtocolMonitor.ProtocolMonitor = class extends UI.VBox {
}
}
- _messageRecieved(message) {
+ /**
+ * @param {?SDK.Target} target
+ * @return {string}
+ */
+ _targetToString(target) {
+ if (!target) {
+ return '';
+ }
+ return target.decorateLabel(`${target.name()} ${target === SDK.targetManager.mainTarget() ? '' : target.id()}`);
+ }
+
+ /**
+ * @param {!Object} message
+ * @param {?Protocol.TargetBase} target
+ */
+ _messageRecieved(message, target) {
if ('id' in message) {
const node = this._nodeForId[message.id];
- if (!node)
+ if (!node) {
return;
+ }
node.data.response = message.result || message.error;
node.hasError = !!message.error;
node.refresh();
- if (this._dataGrid.selectedNode === node)
+ if (this._dataGrid.selectedNode === node) {
this._infoWidget.render(node.data);
+ }
return;
}
+
+ const sdkTarget = /** @type {?SDK.Target} */ (target);
const node = new ProtocolMonitor.ProtocolMonitor.ProtocolNode({
method: message.method,
direction: 'recieved',
response: message.params,
timestamp: Date.now() - this._startTime,
- request: ''
+ request: '',
+ target: this._targetToString(sdkTarget)
});
this._nodes.push(node);
- if (this._filter(node))
+ if (this._filter(node)) {
this._dataGrid.insertChild(node);
+ }
}
- _messageSent(message) {
+ /**
+ * @param {{domain: string, method: string, params: !Object, id: number}} message
+ * @param {?Protocol.TargetBase} target
+ */
+ _messageSent(message, target) {
+ const sdkTarget = /** @type {?SDK.Target} */ (target);
const node = new ProtocolMonitor.ProtocolMonitor.ProtocolNode({
method: message.method,
direction: 'sent',
request: message.params,
timestamp: Date.now() - this._startTime,
response: '(pending)',
- id: message.id
+ id: message.id,
+ target: this._targetToString(sdkTarget)
});
this._nodeForId[message.id] = node;
this._nodes.push(node);
- if (this._filter(node))
+ if (this._filter(node)) {
this._dataGrid.insertChild(node);
+ }
}
};
@@ -243,7 +279,7 @@ ProtocolMonitor.ProtocolMonitor.ProtocolNode = class extends DataGrid.SortableDa
case 'request': {
const cell = this.createTD(columnId);
const obj = SDK.RemoteObject.fromLocalObject(this.data[columnId]);
- cell.textContent = obj.description.trimEnd(50);
+ cell.textContent = obj.description.trimEndWithMaxLength(50);
cell.classList.add('source-code');
return cell;
}
@@ -292,8 +328,9 @@ ProtocolMonitor.ProtocolMonitor.InfoWidget = class extends UI.VBox {
this._tabbedPane.changeTabView('response', new UI.EmptyWidget(ls`No message selected`));
return;
}
- if (!requestEnabled)
+ if (!requestEnabled) {
this._tabbedPane.selectTab('response');
+ }
this._tabbedPane.changeTabView('request', SourceFrame.JSONView.createViewSync(data.request));
this._tabbedPane.changeTabView('response', SourceFrame.JSONView.createViewSync(data.response));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
index fae6e7b9d2b..66a3300a0fe 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/protocol_monitor/protocol_monitor_strings.grdp
@@ -9,19 +9,13 @@
<message name="IDS_DEVTOOLS_2448f896f98bcda2db043a999a00e1d2" desc="Cell text content in Protocol Monitor of the Protocol Monitor tab">
<ph name="THIS_DATA_COLUMNID_">$1s<ex>30</ex></ph> ms
</message>
- <message name="IDS_DEVTOOLS_5b6cf869265c13af8566f192b4ab3d2a" desc="A context menu item in the Protocol Monitor of the Protocol Monitor tab">
- Documentation
- </message>
- <message name="IDS_DEVTOOLS_6a0d9eaee314c567fd72fb97ee707a36" desc="Tooltip text that appears when hovering over largeicon start recording button in Protocol Monitor of the Protocol Monitor tab">
- Record
- </message>
- <message name="IDS_DEVTOOLS_a3d5de3eac8bb00ae86fd1a1005f1500" desc="Text in Protocol Monitor of the Protocol Monitor tab">
- Timestamp
- </message>
<message name="IDS_DEVTOOLS_a854885880458e27324853c6f46e28f7" desc="Text in Protocol Monitor of the Protocol Monitor tab">
No message selected
</message>
<message name="IDS_DEVTOOLS_c2474d3f42e95aac175f984da6d91cf5" desc="Title of the 'Protocol monitor' tool in the bottom drawer">
Protocol monitor
</message>
-</grit-part> \ No newline at end of file
+ <message name="IDS_DEVTOOLS_c41a31890959544c6523af684561abe5" desc="Text in Protocol Monitor of the Protocol Monitor tab">
+ Target
+ </message>
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js
index 488750da827..92b9080668c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js
@@ -20,13 +20,18 @@ QuickOpen.CommandMenu = class {
* @return {!QuickOpen.CommandMenu.Command}
*/
static createCommand(category, keys, title, shortcut, executeHandler, availableHandler) {
- // Separate keys by null character, to prevent fuzzy matching from matching across them.
- const key = keys.replace(/,/g, '\0');
+ // Get localized keys and separate by null character to prevent fuzzy matching from matching across them.
+ const keyList = keys.split(',');
+ let key = '';
+ keyList.forEach(k => {
+ key += (ls(k.trim()) + '\0');
+ });
+
return new QuickOpen.CommandMenu.Command(category, title, key, shortcut, executeHandler, availableHandler);
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @param {string} title
* @param {V} value
* @return {!QuickOpen.CommandMenu.Command}
@@ -37,7 +42,7 @@ QuickOpen.CommandMenu = class {
const tags = extension.descriptor()['tags'] || '';
const setting = Common.settings.moduleSetting(extension.descriptor()['settingName']);
return QuickOpen.CommandMenu.createCommand(
- category, tags, title, '', setting.set.bind(setting, value), availableHandler);
+ ls(category), tags, title, '', setting.set.bind(setting, value), availableHandler);
/**
* @return {boolean}
@@ -58,7 +63,7 @@ QuickOpen.CommandMenu = class {
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @param {string} category
* @return {!QuickOpen.CommandMenu.Command}
*/
@@ -75,24 +80,28 @@ QuickOpen.CommandMenu = class {
self.runtime.extensions(UI.ViewLocationResolver).forEach(extension => {
const category = extension.descriptor()['category'];
const name = extension.descriptor()['name'];
- if (category && name)
+ if (category && name) {
locations.set(name, category);
+ }
});
const viewExtensions = self.runtime.extensions('view');
for (const extension of viewExtensions) {
const category = locations.get(extension.descriptor()['location']);
- if (category)
- this._commands.push(QuickOpen.CommandMenu.createRevealViewCommand(extension, category));
+ if (category) {
+ this._commands.push(QuickOpen.CommandMenu.createRevealViewCommand(extension, ls(category)));
+ }
}
// Populate whitelisted settings.
const settingExtensions = self.runtime.extensions('setting');
for (const extension of settingExtensions) {
const options = extension.descriptor()['options'];
- if (!options || !extension.descriptor()['category'])
+ if (!options || !extension.descriptor()['category']) {
continue;
- for (const pair of options)
- this._commands.push(QuickOpen.CommandMenu.createSettingCommand(extension, pair['title'], pair['value']));
+ }
+ for (const pair of options) {
+ this._commands.push(QuickOpen.CommandMenu.createSettingCommand(extension, ls(pair['title']), pair['value']));
+ }
}
}
@@ -119,13 +128,15 @@ QuickOpen.CommandMenuProvider = class extends QuickOpen.FilteredListWidget.Provi
// Populate whitelisted actions.
const actions = UI.actionRegistry.availableActions();
for (const action of actions) {
- if (action.category())
+ if (action.category()) {
this._commands.push(QuickOpen.CommandMenu.createActionCommand(action));
+ }
}
for (const command of allCommands) {
- if (command.available())
+ if (command.available()) {
this._commands.push(command);
+ }
}
this._commands = this._commands.sort(commandComparator);
@@ -177,15 +188,17 @@ QuickOpen.CommandMenuProvider = class extends QuickOpen.FilteredListWidget.Provi
let score = 0;
// Score longer sequences higher.
for (let i = 0; i < opcodes.length; ++i) {
- if (opcodes[i][0] === Diff.Diff.Operation.Equal)
+ if (opcodes[i][0] === Diff.Diff.Operation.Equal) {
score += opcodes[i][1].length * opcodes[i][1].length;
+ }
}
// Score panel/drawer reveals above regular actions.
- if (command.category().startsWith('Panel'))
+ if (command.category().startsWith('Panel')) {
score += 2;
- else if (command.category().startsWith('Drawer'))
+ } else if (command.category().startsWith('Drawer')) {
score += 1;
+ }
return score;
}
@@ -215,8 +228,9 @@ QuickOpen.CommandMenuProvider = class extends QuickOpen.FilteredListWidget.Provi
* @param {string} promptValue
*/
selectItem(itemIndex, promptValue) {
- if (itemIndex === null)
+ if (itemIndex === null) {
return;
+ }
this._commands[itemIndex].execute();
Host.userMetrics.actionTaken(Host.UserMetrics.Action.SelectCommandFromCommandMenu);
}
@@ -226,7 +240,7 @@ QuickOpen.CommandMenuProvider = class extends QuickOpen.FilteredListWidget.Provi
* @return {string}
*/
notFoundText() {
- return Common.UIString('No commands found');
+ return ls`No commands found`;
}
};
@@ -312,7 +326,7 @@ QuickOpen.CommandMenu.ShowActionDelegate = class {
* @return {boolean}
*/
handleAction(context, actionId) {
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
QuickOpen.QuickOpen.show('>');
return true;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/FilteredListWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/FilteredListWidget.js
index c146b19dbc8..3101d9bdb9b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/FilteredListWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/FilteredListWidget.js
@@ -19,9 +19,11 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this.contentElement.classList.add('filtered-list-widget');
this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), true);
+ UI.ARIAUtils.markAsCombobox(this.contentElement);
this.registerRequiredCSS('quick_open/filteredListWidget.css');
this._promptElement = this.contentElement.createChild('div', 'filtered-list-widget-input');
+ UI.ARIAUtils.setAccessibleName(this._promptElement, ls`Quick open prompt`);
this._promptElement.setAttribute('spellcheck', 'false');
this._promptElement.setAttribute('contenteditable', 'plaintext-only');
this._prompt = new UI.TextPrompt();
@@ -42,6 +44,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this._itemElementsContainer.classList.add('container');
this._bottomElementsContainer.appendChild(this._itemElementsContainer);
this._itemElementsContainer.addEventListener('click', this._onClick.bind(this), false);
+ UI.ARIAUtils.markAsListBox(this._itemElementsContainer);
+ UI.ARIAUtils.setControls(this._promptElement, this._itemElementsContainer);
+ UI.ARIAUtils.setAutocomplete(this._promptElement, UI.ARIAUtils.AutocompleteInteractionModel.list);
this._notFoundElement = this._bottomElementsContainer.createChild('div', 'not-found-text');
this._notFoundElement.classList.add('hidden');
@@ -60,8 +65,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
* @return {boolean}
*/
static highlightRanges(element, query, caseInsensitive) {
- if (!query)
+ if (!query) {
return false;
+ }
/**
* @param {string} text
@@ -74,10 +80,11 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
const ranges = [];
for (let i = 0; i < opcodes.length; ++i) {
const opcode = opcodes[i];
- if (opcode[0] === Diff.Diff.Operation.Equal)
+ if (opcode[0] === Diff.Diff.Operation.Equal) {
ranges.push(new TextUtils.SourceRange(offset, opcode[1].length));
- else if (opcode[0] !== Diff.Diff.Operation.Insert)
+ } else if (opcode[0] !== Diff.Diff.Operation.Insert) {
return null;
+ }
offset += opcode[1].length;
}
return ranges;
@@ -85,8 +92,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
const text = element.textContent;
let ranges = rangesForMatch(text, query);
- if (!ranges || caseInsensitive)
+ if (!ranges || caseInsensitive) {
ranges = rangesForMatch(text.toUpperCase(), query.toUpperCase());
+ }
if (ranges) {
UI.highlightRangesWithStyleClass(element, ranges, 'highlight');
return true;
@@ -96,17 +104,20 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
/**
* @param {string} placeholder
+ * @param {string=} ariaPlaceholder
*/
- setPlaceholder(placeholder) {
- this._prompt.setPlaceholder(placeholder);
+ setPlaceholder(placeholder, ariaPlaceholder) {
+ this._prompt.setPlaceholder(placeholder, ariaPlaceholder);
}
showAsDialog() {
this._dialog = new UI.Dialog();
+ UI.ARIAUtils.setAccessibleName(this._dialog.contentElement, ls`Quick open`);
this._dialog.setMaxContentSize(new UI.Size(504, 340));
this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight);
this._dialog.setContentPosition(null, 22);
this.show(this._dialog.contentElement);
+ UI.ARIAUtils.setExpanded(this.contentElement, true);
this._dialog.show();
}
@@ -121,16 +132,19 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
* @param {?QuickOpen.FilteredListWidget.Provider} provider
*/
setProvider(provider) {
- if (provider === this._provider)
+ if (provider === this._provider) {
return;
+ }
- if (this._provider)
+ if (this._provider) {
this._provider.detach();
+ }
this._clearTimers();
this._provider = provider;
- if (this.isShowing())
+ if (this.isShowing()) {
this._attachProvider();
+ }
}
_attachProvider() {
@@ -165,9 +179,11 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
* @override
*/
willHide() {
- if (this._provider)
+ if (this._provider) {
this._provider.detach();
+ }
this._clearTimers();
+ UI.ARIAUtils.setExpanded(this.contentElement, false);
}
_clearTimers() {
@@ -184,21 +200,24 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
* @param {!Event} event
*/
_onEnter(event) {
- if (!this._provider)
+ if (!this._provider) {
return;
+ }
const selectedIndexInProvider = this._provider.itemCount() ? this._list.selectedItem() : null;
this._selectItem(selectedIndexInProvider);
- if (this._dialog)
+ if (this._dialog) {
this._dialog.hide();
+ }
}
/**
* @param {?QuickOpen.FilteredListWidget.Provider} provider
*/
_itemsLoaded(provider) {
- if (this._loadTimeout || provider !== this._provider)
+ if (this._loadTimeout || provider !== this._provider) {
return;
+ }
this._loadTimeout = setTimeout(this._updateAfterItemsLoaded.bind(this), 0);
}
@@ -219,6 +238,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
const subtitleElement = itemElement.createChild('div', 'filtered-list-widget-subtitle');
subtitleElement.textContent = '\u200B';
this._provider.renderItem(item, this._cleanValue(), titleElement, subtitleElement);
+ UI.ARIAUtils.markAsOption(itemElement);
return itemElement;
}
@@ -249,12 +269,13 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected');
+ }
if (toElement) {
toElement.classList.add('selected');
- UI.ARIAUtils.alert(toElement.textContent, toElement);
}
+ UI.ARIAUtils.setActiveDescendant(this._promptElement, toElement);
}
/**
@@ -262,13 +283,15 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
*/
_onClick(event) {
const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
- if (item === null)
+ if (item === null) {
return;
+ }
event.consume(true);
this._selectItem(item);
- if (this._dialog)
+ if (this._dialog) {
this._dialog.hide();
+ }
}
/**
@@ -294,8 +317,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
break;
}
}
- if (!completion)
+ if (!completion) {
return false;
+ }
this._prompt.focus();
this._prompt.setText(completion);
this._prompt.setDOMSelection(userEnteredText.length, completion.length);
@@ -313,8 +337,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
clearTimeout(this._scoringTimer);
delete this._scoringTimer;
- if (this._refreshListWithCurrentResult)
+ if (this._refreshListWithCurrentResult) {
this._refreshListWithCurrentResult();
+ }
}
if (!this._provider) {
@@ -367,13 +392,15 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
for (i = fromIndex; i < this._provider.itemCount() && workDone < maxWorkItems; ++i) {
// Filter out non-matching items quickly.
- if (filterRegex && !filterRegex.test(this._provider.itemKeyAt(i)))
+ if (filterRegex && !filterRegex.test(this._provider.itemKeyAt(i))) {
continue;
+ }
// Score item.
const score = this._provider.itemScoreAt(i, query);
- if (query)
+ if (query) {
workDone++;
+ }
// Find its index in the scores array (earlier elements have bigger scores).
if (score > minBestScore || bestScores.length < bestItemsToCollect) {
@@ -397,8 +424,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
// Process everything in chunks.
if (i < this._provider.itemCount()) {
this._scoringTimer = setTimeout(scoreItems.bind(this, i), 0);
- if (window.performance.now() - scoreStartTime > 50)
+ if (window.performance.now() - scoreStartTime > 50) {
this._progressBarElement.style.transform = 'scaleX(' + i / this._provider.itemCount() + ')';
+ }
return;
}
if (window.performance.now() - scoreStartTime > 100) {
@@ -422,10 +450,12 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this._updateNotFoundMessage(!!filteredItems.length);
const oldHeight = this._list.element.offsetHeight;
this._items.replaceAll(filteredItems);
- if (filteredItems.length)
+ if (filteredItems.length) {
this._list.selectItem(filteredItems[0]);
- if (this._list.element.offsetHeight !== oldHeight)
+ }
+ if (this._list.element.offsetHeight !== oldHeight) {
this._list.viewportResized();
+ }
this._itemsFilteredForTest();
}
@@ -435,8 +465,10 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
_updateNotFoundMessage(hasItems) {
this._list.element.classList.toggle('hidden', !hasItems);
this._notFoundElement.classList.toggle('hidden', hasItems);
- if (!hasItems)
+ if (!hasItems) {
this._notFoundElement.textContent = this._provider.notFoundText(this._cleanValue());
+ UI.ARIAUtils.alert(this._notFoundElement.textContent, this._notFoundElement);
+ }
}
_onInput() {
@@ -445,10 +477,12 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
}
_queryChanged() {
- if (this._queryChangedCallback)
+ if (this._queryChangedCallback) {
this._queryChangedCallback(this._value());
- if (this._provider)
+ }
+ if (this._provider) {
this._provider.queryChanged(this._cleanValue());
+ }
}
/**
@@ -476,13 +510,15 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
handled = this._list.selectItemNextPage(false);
break;
}
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
_scheduleFilter() {
- if (this._filterTimer)
+ if (this._filterTimer) {
return;
+ }
this._filterTimer = setTimeout(this._filterItems.bind(this), 0);
}
@@ -491,8 +527,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
*/
_selectItem(itemIndex) {
this._promptHistory.push(this._value());
- if (this._promptHistory.length > 100)
+ if (this._promptHistory.length > 100) {
this._promptHistory.shift();
+ }
this._provider.selectItem(itemIndex, this._cleanValue());
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/HelpQuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/HelpQuickOpen.js
index a8757e18b0d..9834c69d410 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/HelpQuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/HelpQuickOpen.js
@@ -10,11 +10,12 @@ QuickOpen.HelpQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
_addProvider(extension) {
- if (extension.title())
+ if (extension.title()) {
this._providers.push({prefix: extension.descriptor()['prefix'], title: extension.title()});
+ }
}
/**
@@ -64,8 +65,9 @@ QuickOpen.HelpQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
* @param {string} promptValue
*/
selectItem(itemIndex, promptValue) {
- if (itemIndex !== null)
+ if (itemIndex !== null) {
QuickOpen.QuickOpen.show(this._providers[itemIndex].prefix);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/QuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/QuickOpen.js
index 9f1160d1bcb..3f3fe2469bc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/QuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/QuickOpen.js
@@ -23,13 +23,14 @@ QuickOpen.QuickOpen = class {
const filteredListWidget =
new QuickOpen.FilteredListWidget(null, this._history, quickOpen._queryChanged.bind(quickOpen));
quickOpen._filteredListWidget = filteredListWidget;
- filteredListWidget.setPlaceholder(Common.UIString('Type \'?\' to see available commands'));
+ filteredListWidget.setPlaceholder(
+ ls`Type '?' to see available commands`, ls`Type question mark to see available commands`);
filteredListWidget.showAsDialog();
filteredListWidget.setQuery(query);
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
_addProvider(extension) {
const prefix = extension.descriptor()['prefix'];
@@ -44,15 +45,17 @@ QuickOpen.QuickOpen = class {
*/
_queryChanged(query) {
const prefix = this._prefixes.find(prefix => query.startsWith(prefix));
- if (typeof prefix !== 'string' || this._prefix === prefix)
+ if (typeof prefix !== 'string' || this._prefix === prefix) {
return;
+ }
this._prefix = prefix;
this._filteredListWidget.setPrefix(prefix);
this._filteredListWidget.setProvider(null);
this._providers.get(prefix)().then(provider => {
- if (this._prefix !== prefix)
+ if (this._prefix !== prefix) {
return;
+ }
this._filteredListWidget.setProvider(provider);
this._providerLoadedForTest(provider);
});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
index edeeb66778f..9bb91fc7d67 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/quick_open/quick_open_strings.grdp
@@ -3,19 +3,16 @@
<message name="IDS_DEVTOOLS_06f884351ae9dbaaca31602b74d0ed4e" desc="Text in Quick Open of the Command Menu">
Type &apos;?&apos; to see available commands
</message>
- <message name="IDS_DEVTOOLS_22b6fe30dec1ae9c09480cce01cd4065" desc="Title of the Filtered List WidgetProvider of Quick Open">
- Run command
+ <message name="IDS_DEVTOOLS_532ce4f18bb96f70d8ee338082ad7ed0" desc="Title of quick open dialog">
+ Quick open
</message>
- <message name="IDS_DEVTOOLS_74540c79e377bea903e1023a46df5574" desc="Title of an action in the quickOpen tool to show">
- Open file
+ <message name="IDS_DEVTOOLS_c986e2ac993abbee8febcc7e21ebb4d8" desc="Aria-placeholder text for quick open dialog prompt">
+ Type question mark to see available commands
+ </message>
+ <message name="IDS_DEVTOOLS_db1accfc3285ca06387a9b35f80523a7" desc="Aria label for quick open dialog prompt">
+ Quick open prompt
</message>
<message name="IDS_DEVTOOLS_8bb9829a676055080c3d4507e0b5f201" desc="Text in Command Menu of the Command Menu">
No commands found
</message>
- <message name="IDS_DEVTOOLS_af9ccba3ec4346e3acf785f9bea514d8" desc="Text in Command Menu of the Command Menu">
- Show <ph name="EXTENSION_TITLE__">$1s<ex>Audits</ex></ph>
- </message>
- <message name="IDS_DEVTOOLS_e576c23d915755d83e2d1f47bd9f6c22" desc="Text in Filtered List Widget of the Command Menu">
- No results found
- </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
index ac7599173da..ec6b0ab4876 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/AppManifestView.js
@@ -55,13 +55,15 @@ Resources.AppManifestView = class extends UI.VBox {
* @param {!SDK.Target} target
*/
targetAdded(target) {
- if (this._target)
+ if (this._target) {
return;
+ }
this._target = target;
this._resourceTreeModel = target.model(SDK.ResourceTreeModel);
this._serviceWorkerManager = target.model(SDK.ServiceWorkerManager);
- if (!this._resourceTreeModel || !this._serviceWorkerManager)
+ if (!this._resourceTreeModel || !this._serviceWorkerManager) {
return;
+ }
this._updateManifest(true);
@@ -78,10 +80,12 @@ Resources.AppManifestView = class extends UI.VBox {
* @param {!SDK.Target} target
*/
targetRemoved(target) {
- if (this._target !== target)
+ if (this._target !== target) {
return;
- if (!this._resourceTreeModel || !this._serviceWorkerManager)
+ }
+ if (!this._resourceTreeModel || !this._serviceWorkerManager) {
return;
+ }
delete this._resourceTreeModel;
delete this._serviceWorkerManager;
Common.EventTarget.removeEventListeners(this._registeredListeners);
@@ -121,11 +125,13 @@ Resources.AppManifestView = class extends UI.VBox {
UI.createIconLabel(error.message, error.critical ? 'smallicon-error' : 'smallicon-warning'));
}
- if (!data)
+ if (!data) {
return;
+ }
- if (data.charCodeAt(0) === 0xFEFF)
- data = data.slice(1); // Trim the BOM as per https://tools.ietf.org/html/rfc7159#section-8.1.
+ if (data.charCodeAt(0) === 0xFEFF) {
+ data = data.slice(1);
+ } // Trim the BOM as per https://tools.ietf.org/html/rfc7159#section-8.1.
const parsedManifest = JSON.parse(data);
this._nameField.textContent = stringProperty('name');
@@ -161,14 +167,16 @@ Resources.AppManifestView = class extends UI.VBox {
const title = (icon['sizes'] || '') + '\n' + (icon['type'] || '');
const field = this._iconsSection.appendField(title);
const image = await this._loadImage(Common.ParsedURL.completeURL(url, icon['src']));
- if (image)
+ if (image) {
field.appendChild(image);
+ }
}
this._installabilitySection.clearContent();
this._installabilitySection.element.classList.toggle('hidden', !installabilityErrors.length);
- for (const error of installabilityErrors)
+ for (const error of installabilityErrors) {
this._installabilitySection.appendRow().appendChild(UI.createIconLabel(error, 'smallicon-warning'));
+ }
/**
* @param {string} name
@@ -176,15 +184,16 @@ Resources.AppManifestView = class extends UI.VBox {
*/
function stringProperty(name) {
const value = parsedManifest[name];
- if (typeof value !== 'string')
+ if (typeof value !== 'string') {
return '';
+ }
return value;
}
}
/**
* @param {?string} url
- * @return {!Promise<?Image>}
+ * @return {!Promise<?Element>}
*/
async _loadImage(url) {
const image = createElement('img');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheItemsView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheItemsView.js
index f83a6b6660d..7d8e72d53bd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheItemsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheItemsView.js
@@ -85,8 +85,9 @@ Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
}
_maybeUpdate() {
- if (!this.isShowing() || !this._viewDirty)
+ if (!this.isShowing() || !this._viewDirty) {
return;
+ }
this._update();
this._viewDirty = false;
@@ -124,8 +125,9 @@ Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
this._statusIcon.textContent = info.text;
if (this.isShowing() && this._status === Resources.ApplicationCacheModel.IDLE &&
- (oldStatus === Resources.ApplicationCacheModel.UPDATEREADY || !this._resources))
+ (oldStatus === Resources.ApplicationCacheModel.UPDATEREADY || !this._resources)) {
this._markDirty();
+ }
this._maybeUpdate();
}
@@ -154,8 +156,9 @@ Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
this._emptyWidget.show(this.element);
this._deleteButton.setVisible(false);
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.element.classList.add('hidden');
+ }
return;
}
// FIXME: are these variables needed anywhere else?
@@ -165,8 +168,9 @@ Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
this._size = applicationCache.size;
this._resources = applicationCache.resources;
- if (!this._dataGrid)
+ if (!this._dataGrid) {
this._createDataGrid();
+ }
this._populateDataGrid();
this._dataGrid.autoSizeColumns(20, 80);
@@ -237,16 +241,18 @@ Resources.ApplicationCacheItemsView = class extends UI.SimpleView {
}
}
- if (!nodeToSelect && this._dataGrid.rootNode().children.length)
+ if (!nodeToSelect && this._dataGrid.rootNode().children.length) {
this._dataGrid.rootNode().children[0].selected = true;
+ }
}
/**
* @param {!Common.Event} event
*/
_deleteButtonClicked(event) {
- if (!this._dataGrid || !this._dataGrid.selectedNode)
+ if (!this._dataGrid || !this._dataGrid.selectedNode) {
return;
+ }
// FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?)
this._deleteCallback(this._dataGrid.selectedNode);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheModel.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheModel.js
index 41c076e3bef..946d0bb3864 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationCacheModel.js
@@ -63,8 +63,9 @@ Resources.ApplicationCacheModel = class extends SDK.SDKModel {
const frameId = frame.id;
const manifestURL = await this._agent.getManifestForFrame(frameId);
- if (manifestURL !== null && !manifestURL)
+ if (manifestURL !== null && !manifestURL) {
this._frameManifestRemoved(frameId);
+ }
}
/**
@@ -83,8 +84,9 @@ Resources.ApplicationCacheModel = class extends SDK.SDKModel {
async _mainFrameNavigated() {
const framesWithManifests = await this._agent.getFramesWithManifests();
- for (const frame of framesWithManifests || [])
+ for (const frame of framesWithManifests || []) {
this._frameManifestUpdated(frame.frameId, frame.manifestURL, frame.status);
+ }
}
/**
@@ -98,11 +100,13 @@ Resources.ApplicationCacheModel = class extends SDK.SDKModel {
return;
}
- if (!manifestURL)
+ if (!manifestURL) {
return;
+ }
- if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId])
+ if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId]) {
this._frameManifestRemoved(frameId);
+ }
const statusChanged = this._statuses[frameId] !== status;
this._statuses[frameId] = status;
@@ -112,16 +116,18 @@ Resources.ApplicationCacheModel = class extends SDK.SDKModel {
this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestAdded, frameId);
}
- if (statusChanged)
+ if (statusChanged) {
this.dispatchEventToListeners(Resources.ApplicationCacheModel.Events.FrameManifestStatusUpdated, frameId);
+ }
}
/**
* @param {string} frameId
*/
_frameManifestRemoved(frameId) {
- if (!this._manifestURLsByFrame[frameId])
+ if (!this._manifestURLsByFrame[frameId]) {
return;
+ }
delete this._manifestURLsByFrame[frameId];
delete this._statuses[frameId];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationPanelSidebar.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationPanelSidebar.js
index 53ee664a005..b52aed8bdd9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationPanelSidebar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ApplicationPanelSidebar.js
@@ -104,7 +104,7 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
cacheTreeElement.appendChild(this.applicationCacheListTreeElement);
- if (Runtime.experiments.isEnabled('backgroundServices')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServices')) {
const backgroundServiceTreeElement = this._addSidebarSection(ls`Background Services`);
this.backgroundFetchTreeElement =
@@ -114,22 +114,22 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
new Resources.BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.BackgroundSync);
backgroundServiceTreeElement.appendChild(this.backgroundSyncTreeElement);
- if (Runtime.experiments.isEnabled('backgroundServicesNotifications')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesNotifications')) {
this.notificationsTreeElement =
new Resources.BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.Notifications);
backgroundServiceTreeElement.appendChild(this.notificationsTreeElement);
}
- if (Runtime.experiments.isEnabled('backgroundServicesPaymentHandler')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPaymentHandler')) {
this.paymentHandlerTreeElement =
new Resources.BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PaymentHandler);
backgroundServiceTreeElement.appendChild(this.paymentHandlerTreeElement);
}
- if (Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync')) {
this.periodicBackgroundSyncTreeElement = new Resources.BackgroundServiceTreeElement(
panel, Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync);
backgroundServiceTreeElement.appendChild(this.periodicBackgroundSyncTreeElement);
}
- if (Runtime.experiments.isEnabled('backgroundServicesPushMessaging')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPushMessaging')) {
this.pushMessagingTreeElement =
new Resources.BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PushMessaging);
backgroundServiceTreeElement.appendChild(this.pushMessagingTreeElement);
@@ -157,8 +157,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this._frameNavigated, this);
const selection = this._panel.lastSelectedItemPath();
- if (!selection.length)
+ if (!selection.length) {
manifestTreeElement.select();
+ }
}
/**
@@ -179,8 +180,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
* @param {!SDK.Target} target
*/
targetAdded(target) {
- if (this._target)
+ if (this._target) {
return;
+ }
this._target = target;
this._databaseModel = target.model(Resources.DatabaseModel);
if (this._databaseModel) {
@@ -189,11 +191,13 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
}
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
- if (!resourceTreeModel)
+ if (!resourceTreeModel) {
return;
+ }
- if (resourceTreeModel.cachedResourcesLoaded())
+ if (resourceTreeModel.cachedResourcesLoaded()) {
this._initialize();
+ }
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this._initialize, this);
resourceTreeModel.addEventListener(
@@ -205,8 +209,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
* @param {!SDK.Target} target
*/
targetRemoved(target) {
- if (target !== this._target)
+ if (target !== this._target) {
return;
+ }
delete this._target;
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
@@ -232,17 +237,21 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
}
_initialize() {
- for (const frame of SDK.ResourceTreeModel.frames())
+ for (const frame of SDK.ResourceTreeModel.frames()) {
this._addCookieDocument(frame);
- if (this._databaseModel)
+ }
+ if (this._databaseModel) {
this._databaseModel.enable();
+ }
const cacheStorageModel = this._target.model(SDK.ServiceWorkerCacheModel);
- if (cacheStorageModel)
+ if (cacheStorageModel) {
cacheStorageModel.enable();
+ }
const resourceTreeModel = this._target.model(SDK.ResourceTreeModel);
- if (resourceTreeModel)
+ if (resourceTreeModel) {
this._populateApplicationCacheTree(resourceTreeModel);
+ }
SDK.targetManager.observeModels(Resources.DOMStorageModel, /** @type {!SDK.SDKModelObserver} */ ({
modelAdded: model => this._domStorageModelAdded(model),
modelRemoved: model => this._domStorageModelRemoved(model)
@@ -256,17 +265,21 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
const serviceWorkerCacheModel = this._target.model(SDK.ServiceWorkerCacheModel);
this.cacheStorageListTreeElement._initialize(serviceWorkerCacheModel);
const backgroundServiceModel = this._target.model(Resources.BackgroundServiceModel);
- if (Runtime.experiments.isEnabled('backgroundServices')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServices')) {
this.backgroundFetchTreeElement._initialize(backgroundServiceModel);
this.backgroundSyncTreeElement._initialize(backgroundServiceModel);
- if (Runtime.experiments.isEnabled('backgroundServicesNotifications'))
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesNotifications')) {
this.notificationsTreeElement._initialize(backgroundServiceModel);
- if (Runtime.experiments.isEnabled('backgroundServicesPaymentHandler'))
+ }
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPaymentHandler')) {
this.paymentHandlerTreeElement._initialize(backgroundServiceModel);
- if (Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync'))
+ }
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync')) {
this.periodicBackgroundSyncTreeElement._initialize(backgroundServiceModel);
- if (Runtime.experiments.isEnabled('backgroundServicesPushMessaging'))
+ }
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPushMessaging')) {
this.pushMessagingTreeElement._initialize(backgroundServiceModel);
+ }
}
}
@@ -308,8 +321,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
}
_resetAppCache() {
- for (const frameId of Object.keys(this._applicationCacheFrameElements))
+ for (const frameId of Object.keys(this._applicationCacheFrameElements)) {
this._applicationCacheFrameManifestRemoved({data: frameId});
+ }
this.applicationCacheListTreeElement.setExpandable(false);
}
@@ -318,16 +332,20 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
*/
_treeElementAdded(event) {
const selection = this._panel.lastSelectedItemPath();
- if (!selection.length)
+ if (!selection.length) {
return;
+ }
const element = event.data;
const index = selection.indexOf(element.itemURL);
- if (index < 0)
+ if (index < 0) {
return;
- for (let parent = element.parent; parent; parent = parent.parent)
+ }
+ for (let parent = element.parent; parent; parent = parent.parent) {
parent.expand();
- if (index > 0)
+ }
+ if (index > 0) {
element.expand();
+ }
element.select();
}
@@ -343,12 +361,14 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
_frameNavigated(event) {
const frame = /** @type {!SDK.ResourceTreeFrame} */ (event.data);
- if (frame.isTopFrame())
+ if (frame.isTopFrame()) {
this._reset();
+ }
const applicationCacheFrameTreeElement = this._applicationCacheFrameElements[frame.id];
- if (applicationCacheFrameTreeElement)
+ if (applicationCacheFrameTreeElement) {
applicationCacheFrameTreeElement.frameNavigated(frame);
+ }
this._addCookieDocument(frame);
}
@@ -367,8 +387,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
*/
_addCookieDocument(frame) {
const parsedURL = frame.url.asParsedURL();
- if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file'))
+ if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file')) {
return;
+ }
const domain = parsedURL.securityOrigin();
if (!this._domains[domain]) {
@@ -394,10 +415,11 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
const domStorageTreeElement = new Resources.DOMStorageTreeElement(this._panel, domStorage);
this._domStorageTreeElements.set(domStorage, domStorageTreeElement);
- if (domStorage.isLocalStorage)
+ if (domStorage.isLocalStorage) {
this.localStorageListTreeElement.appendChild(domStorageTreeElement);
- else
+ } else {
this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
+ }
}
/**
@@ -413,13 +435,15 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
*/
_removeDOMStorage(domStorage) {
const treeElement = this._domStorageTreeElements.get(domStorage);
- if (!treeElement)
+ if (!treeElement) {
return;
+ }
const wasSelected = treeElement.selected;
const parentListTreeElement = treeElement.parent;
parentListTreeElement.removeChild(treeElement);
- if (wasSelected)
+ if (wasSelected) {
parentListTreeElement.select();
+ }
this._domStorageTreeElements.remove(domStorage);
}
@@ -448,8 +472,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
* @param {string=} tableName
*/
_showDatabase(database, tableName) {
- if (!database)
+ if (!database) {
return;
+ }
let view;
if (tableName) {
@@ -495,38 +520,47 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
this._panel.showView(view);
}
- _updateDatabaseTables(event) {
- const database = event.data;
+ /**
+ * @param {!Common.Event} event
+ */
+ async _updateDatabaseTables(event) {
+ const database = /** @type {!Resources.Database} */ (event.data);
- if (!database)
+ if (!database) {
return;
+ }
const databasesTreeElement = this._databaseTreeElements.get(database);
- if (!databasesTreeElement)
+ if (!databasesTreeElement) {
return;
+ }
databasesTreeElement.invalidateChildren();
const tableViews = this._databaseTableViews.get(database);
- if (!tableViews)
+ if (!tableViews) {
return;
+ }
const tableNamesHash = {};
const panel = this._panel;
- function tableNamesCallback(tableNames) {
- const tableNamesLength = tableNames.length;
- for (let i = 0; i < tableNamesLength; ++i)
- tableNamesHash[tableNames[i]] = true;
-
- for (const tableName in tableViews) {
- if (!(tableName in tableNamesHash)) {
- if (panel.visibleView === tableViews[tableName])
- panel.showView(null);
- delete tableViews[tableName];
+ const tableNames = await database.tableNames();
+ const tableNamesLength = tableNames.length;
+
+ for (let i = 0; i < tableNamesLength; ++i) {
+ tableNamesHash[tableNames[i]] = true;
+ }
+
+ for (const tableName in tableViews) {
+ if (!(tableName in tableNamesHash)) {
+ if (panel.visibleView === tableViews[tableName]) {
+ panel.showView(null);
}
+ delete tableViews[tableName];
}
}
- database.getTableNames(tableNamesCallback);
+
+ await databasesTreeElement.updateChildren();
}
/**
@@ -575,8 +609,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
_applicationCacheFrameManifestRemoved(event) {
const frameId = event.data;
const frameTreeElement = this._applicationCacheFrameElements[frameId];
- if (!frameTreeElement)
+ if (!frameTreeElement) {
return;
+ }
const manifestURL = frameTreeElement.manifestURL;
delete this._applicationCacheFrameElements[frameId];
@@ -584,8 +619,9 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
frameTreeElement.parent.removeChild(frameTreeElement);
const manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
- if (manifestTreeElement.childCount())
+ if (manifestTreeElement.childCount()) {
return;
+ }
delete this._applicationCacheManifestElements[manifestURL];
manifestTreeElement.parent.removeChild(manifestTreeElement);
@@ -595,34 +631,40 @@ Resources.ApplicationPanelSidebar = class extends UI.VBox {
const frameId = event.data;
const status = this._applicationCacheModel.frameManifestStatus(frameId);
- if (this._applicationCacheViews[frameId])
+ if (this._applicationCacheViews[frameId]) {
this._applicationCacheViews[frameId].updateStatus(status);
+ }
}
_applicationCacheNetworkStateChanged(event) {
const isNowOnline = event.data;
- for (const manifestURL in this._applicationCacheViews)
+ for (const manifestURL in this._applicationCacheViews) {
this._applicationCacheViews[manifestURL].updateNetworkState(isNowOnline);
+ }
}
showView(view) {
- if (view)
+ if (view) {
this.showResource(view.resource);
+ }
}
_onmousemove(event) {
const nodeUnderMouse = event.target;
- if (!nodeUnderMouse)
+ if (!nodeUnderMouse) {
return;
+ }
const listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName('li');
- if (!listNode)
+ if (!listNode) {
return;
+ }
const element = listNode.treeElement;
- if (this._previousHoveredElement === element)
+ if (this._previousHoveredElement === element) {
return;
+ }
if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
@@ -662,14 +704,16 @@ Resources.BaseStorageTreeElement = class extends UI.TreeElement {
* @return {boolean}
*/
onselect(selectedByUser) {
- if (!selectedByUser)
+ if (!selectedByUser) {
return false;
+ }
const path = [];
for (let el = this; el; el = el.parent) {
const url = el.itemURL;
- if (!url)
+ if (!url) {
break;
+ }
path.push(url);
}
this._storagePanel.setLastSelectedItemPath(path);
@@ -726,8 +770,9 @@ Resources.StorageCategoryTreeElement = class extends Resources.BaseStorageTreeEl
*/
onattach() {
super.onattach();
- if (this._expandedSetting.get())
+ if (this._expandedSetting.get()) {
this.expand();
+ }
}
/**
@@ -798,8 +843,9 @@ Resources.BackgroundServiceTreeElement = class extends Resources.BaseStorageTree
_initialize(model) {
this._model = model;
// Show the view if the model was initialized after selection.
- if (this._selected && !this._view)
+ if (this._selected && !this._view) {
this.onselect(false);
+ }
}
/**
@@ -817,11 +863,13 @@ Resources.BackgroundServiceTreeElement = class extends Resources.BaseStorageTree
super.onselect(selectedByUser);
this._selected = true;
- if (!this._model)
+ if (!this._model) {
return false;
+ }
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.BackgroundServiceView(this._serviceName, this._model);
+ }
this.showView(this._view);
UI.context.setFlavor(Resources.BackgroundServiceView, this._view);
return false;
@@ -863,13 +911,15 @@ Resources.DatabaseTreeElement = class extends Resources.BaseStorageTreeElement {
* @override
*/
onexpand() {
- this._updateChildren();
+ this.updateChildren();
}
- async _updateChildren() {
+ async updateChildren() {
+ this.removeChildren();
const tableNames = await this._database.tableNames();
- for (const tableName of tableNames)
+ for (const tableName of tableNames) {
this.appendChild(new Resources.DatabaseTableTreeElement(this._sidebar, this._database, tableName));
+ }
}
};
@@ -929,8 +979,9 @@ Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategor
this._swCacheTreeElements = [];
this._swCacheModel = model;
if (model) {
- for (const cache of model.caches())
+ for (const cache of model.caches()) {
this._addCache(model, cache);
+ }
}
SDK.targetManager.addModelListener(
SDK.ServiceWorkerCacheModel, SDK.ServiceWorkerCacheModel.Events.CacheAdded, this._cacheAdded, this);
@@ -953,8 +1004,9 @@ Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategor
}
_refreshCaches() {
- if (this._swCacheModel)
+ if (this._swCacheModel) {
this._swCacheModel.refreshCacheNames();
+ }
}
/**
@@ -984,8 +1036,9 @@ Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategor
const model = /** @type {!SDK.ServiceWorkerCacheModel} */ (event.data.model);
const swCacheTreeElement = this._cacheTreeElement(model, cache);
- if (!swCacheTreeElement)
+ if (!swCacheTreeElement) {
return;
+ }
this.removeChild(swCacheTreeElement);
this._swCacheTreeElements.remove(swCacheTreeElement);
@@ -1006,8 +1059,9 @@ Resources.ServiceWorkerCacheTreeElement = class extends Resources.StorageCategor
break;
}
}
- if (index !== -1)
+ if (index !== -1) {
return this._swCacheTreeElements[i];
+ }
return null;
}
};
@@ -1056,8 +1110,9 @@ Resources.SWCacheTreeElement = class extends Resources.BaseStorageTreeElement {
*/
update(cache) {
this._cache = cache;
- if (this._view)
+ if (this._view) {
this._view.update(cache);
+ }
}
/**
@@ -1066,8 +1121,9 @@ Resources.SWCacheTreeElement = class extends Resources.BaseStorageTreeElement {
*/
onselect(selectedByUser) {
super.onselect(selectedByUser);
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.ServiceWorkerCacheView(this._model, this._cache);
+ }
this.showView(this._view);
return false;
@@ -1100,8 +1156,9 @@ Resources.ServiceWorkersTreeElement = class extends Resources.BaseStorageTreeEle
*/
onselect(selectedByUser) {
super.onselect(selectedByUser);
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.ServiceWorkersView();
+ }
this.showView(this._view);
return false;
}
@@ -1133,8 +1190,9 @@ Resources.AppManifestTreeElement = class extends Resources.BaseStorageTreeElemen
*/
onselect(selectedByUser) {
super.onselect(selectedByUser);
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.AppManifestView();
+ }
this.showView(this._view);
return false;
}
@@ -1166,8 +1224,9 @@ Resources.ClearStorageTreeElement = class extends Resources.BaseStorageTreeEleme
*/
onselect(selectedByUser) {
super.onselect(selectedByUser);
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.ClearStorageView();
+ }
this.showView(this._view);
return false;
}
@@ -1201,8 +1260,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
for (const indexedDBModel of SDK.targetManager.models(Resources.IndexedDBModel)) {
const databases = indexedDBModel.databases();
- for (let j = 0; j < databases.length; ++j)
+ for (let j = 0; j < databases.length; ++j) {
this._addIndexedDB(indexedDBModel, databases[j]);
+ }
}
}
@@ -1211,8 +1271,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
*/
removeIndexedDBForModel(model) {
const idbDatabaseTreeElements = this._idbDatabaseTreeElements.filter(element => element._model === model);
- for (const idbDatabaseTreeElement of idbDatabaseTreeElements)
+ for (const idbDatabaseTreeElement of idbDatabaseTreeElements) {
this._removeIDBDatabaseTreeElement(idbDatabaseTreeElement);
+ }
}
/**
@@ -1230,8 +1291,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
}
refreshIndexedDB() {
- for (const indexedDBModel of SDK.targetManager.models(Resources.IndexedDBModel))
+ for (const indexedDBModel of SDK.targetManager.models(Resources.IndexedDBModel)) {
indexedDBModel.refreshDatabaseNames();
+ }
}
/**
@@ -1262,8 +1324,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
const model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
const idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, databaseId);
- if (!idbDatabaseTreeElement)
+ if (!idbDatabaseTreeElement) {
return;
+ }
this._removeIDBDatabaseTreeElement(idbDatabaseTreeElement);
}
@@ -1286,8 +1349,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
const entriesUpdated = /** @type {boolean} */ (event.data.entriesUpdated);
const idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, database.databaseId);
- if (!idbDatabaseTreeElement)
+ if (!idbDatabaseTreeElement) {
return;
+ }
idbDatabaseTreeElement.update(database, entriesUpdated);
this._indexedDBLoadedForTest();
}
@@ -1305,8 +1369,9 @@ Resources.IndexedDBTreeElement = class extends Resources.StorageCategoryTreeElem
const model = /** @type {!Resources.IndexedDBModel} */ (event.data.model);
const idbDatabaseTreeElement = this._idbDatabaseTreeElement(model, databaseId);
- if (!idbDatabaseTreeElement)
+ if (!idbDatabaseTreeElement) {
return;
+ }
idbDatabaseTreeElement.indexedDBContentUpdated(objectStoreName);
}
@@ -1365,8 +1430,9 @@ Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElemen
* @param {string} objectStoreName
*/
indexedDBContentUpdated(objectStoreName) {
- if (this._idbObjectStoreTreeElements[objectStoreName])
+ if (this._idbObjectStoreTreeElements[objectStoreName]) {
this._idbObjectStoreTreeElements[objectStoreName].markNeedsRefresh();
+ }
}
/**
@@ -1389,21 +1455,24 @@ Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElemen
this._idbObjectStoreTreeElements[objectStore.name].update(objectStore, entriesUpdated);
}
for (const objectStoreName in this._idbObjectStoreTreeElements) {
- if (!objectStoreNames[objectStoreName])
+ if (!objectStoreNames[objectStoreName]) {
this._objectStoreRemoved(objectStoreName);
+ }
}
- if (this._view)
+ if (this._view) {
this._view.update(database);
+ }
this._updateTooltip();
}
_updateTooltip() {
- if (Object.keys(this._idbObjectStoreTreeElements).length === 0)
+ if (Object.keys(this._idbObjectStoreTreeElements).length === 0) {
this.tooltip = ls`Version: ${this._database.version} (empty)`;
- else
+ } else {
this.tooltip = ls`Version: ${this._database.version}`;
+ }
}
/**
@@ -1412,8 +1481,9 @@ Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElemen
*/
onselect(selectedByUser) {
super.onselect(selectedByUser);
- if (!this._view)
+ if (!this._view) {
this._view = new Resources.IDBDatabaseView(this._model, this._database);
+ }
this.showView(this._view);
return false;
@@ -1431,8 +1501,9 @@ Resources.IDBDatabaseTreeElement = class extends Resources.BaseStorageTreeElemen
}
clear() {
- for (const objectStoreName in this._idbObjectStoreTreeElements)
+ for (const objectStoreName in this._idbObjectStoreTreeElements) {
this._objectStoreRemoved(objectStoreName);
+ }
}
};
@@ -1469,10 +1540,12 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
}
markNeedsRefresh() {
- if (this._view)
+ if (this._view) {
this._view.markNeedsRefresh();
- for (const indexName in this._idbIndexTreeElements)
+ }
+ for (const indexName in this._idbIndexTreeElements) {
this._idbIndexTreeElements[indexName].markNeedsRefresh();
+ }
}
_handleContextMenuEvent(event) {
@@ -1482,10 +1555,12 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
}
_refreshObjectStore() {
- if (this._view)
+ if (this._view) {
this._view.refreshData();
- for (const indexName in this._idbIndexTreeElements)
+ }
+ for (const indexName in this._idbIndexTreeElements) {
this._idbIndexTreeElements[indexName].refreshIndex();
+ }
}
async _clearObjectStore() {
@@ -1514,8 +1589,9 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
this._idbIndexTreeElements[index.name].update(this._objectStore, index, entriesUpdated);
}
for (const indexName in this._idbIndexTreeElements) {
- if (!indexNames[indexName])
+ if (!indexNames[indexName]) {
this._indexRemoved(indexName);
+ }
}
for (const indexName in this._idbIndexTreeElements) {
if (!indexNames[indexName]) {
@@ -1524,11 +1600,13 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
}
}
- if (this.childCount())
+ if (this.childCount()) {
this.expand();
+ }
- if (this._view && entriesUpdated)
+ if (this._view && entriesUpdated) {
this._view.update(this._objectStore, null);
+ }
this._updateTooltip();
}
@@ -1536,8 +1614,9 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
_updateTooltip() {
const keyPathString = this._objectStore.keyPathString;
let tooltipString = keyPathString !== null ? ls`Key path: ${keyPathString}` : '';
- if (this._objectStore.autoIncrement)
+ if (this._objectStore.autoIncrement) {
tooltipString += '\n' + Common.UIString('autoIncrement');
+ }
this.tooltip = tooltipString;
}
@@ -1567,10 +1646,12 @@ Resources.IDBObjectStoreTreeElement = class extends Resources.BaseStorageTreeEle
}
clear() {
- for (const indexName in this._idbIndexTreeElements)
+ for (const indexName in this._idbIndexTreeElements) {
this._indexRemoved(indexName);
- if (this._view)
+ }
+ if (this._view) {
this._view.clear();
+ }
}
};
@@ -1601,13 +1682,15 @@ Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
}
markNeedsRefresh() {
- if (this._view)
+ if (this._view) {
this._view.markNeedsRefresh();
+ }
}
refreshIndex() {
- if (this._view)
+ if (this._view) {
this._view.refreshData();
+ }
}
/**
@@ -1619,8 +1702,9 @@ Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
this._objectStore = objectStore;
this._index = index;
- if (this._view && entriesUpdated)
+ if (this._view && entriesUpdated) {
this._view.update(this._objectStore, this._index);
+ }
this._updateTooltip();
}
@@ -1629,10 +1713,12 @@ Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
const tooltipLines = [];
const keyPathString = this._index.keyPathString;
tooltipLines.push(ls`Key path: ${keyPathString}`);
- if (this._index.unique)
+ if (this._index.unique) {
tooltipLines.push(Common.UIString('unique'));
- if (this._index.multiEntry)
+ }
+ if (this._index.multiEntry) {
tooltipLines.push(Common.UIString('multiEntry'));
+ }
this.tooltip = tooltipLines.join('\n');
}
@@ -1652,8 +1738,9 @@ Resources.IDBIndexTreeElement = class extends Resources.BaseStorageTreeElement {
}
clear() {
- if (this._view)
+ if (this._view) {
this._view.clear();
+ }
}
};
@@ -1862,10 +1949,12 @@ Resources.StorageCategoryView = class extends UI.VBox {
* @param {?string} link
*/
setLink(link) {
- if (link && !this._linkElement)
+ if (link && !this._linkElement) {
this._linkElement = this._emptyWidget.appendLink(link);
- if (!link && this._linkElement)
+ }
+ if (!link && this._linkElement) {
this._linkElement.classList.add('hidden');
+ }
if (link && this._linkElement) {
this._linkElement.setAttribute('href', link);
this._linkElement.classList.remove('hidden');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
index fec6f91763d..fe52daf5571 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
@@ -127,8 +127,9 @@ Resources.BackgroundServiceView = class extends UI.VBox {
_refreshView() {
this._clearView();
const events = this._model.getEvents(this._serviceName).filter(event => this._acceptEvent(event));
- for (const event of events)
+ for (const event of events) {
this._addEvent(event);
+ }
}
/**
@@ -161,11 +162,13 @@ Resources.BackgroundServiceView = class extends UI.VBox {
*/
_onRecordingStateChanged(event) {
const state = /** @type {!Resources.BackgroundServiceModel.RecordingState} */ (event.data);
- if (state.serviceName !== this._serviceName)
+ if (state.serviceName !== this._serviceName) {
return;
+ }
- if (state.isRecording === this._recordButton.toggled())
+ if (state.isRecording === this._recordButton.toggled()) {
return;
+ }
this._recordButton.setToggled(state.isRecording);
this._showPreview(this._selectedEventNode);
@@ -176,15 +179,17 @@ Resources.BackgroundServiceView = class extends UI.VBox {
*/
_onEventReceived(event) {
const serviceEvent = /** @type {!Protocol.BackgroundService.BackgroundServiceEvent} */ (event.data);
- if (!this._acceptEvent(serviceEvent))
+ if (!this._acceptEvent(serviceEvent)) {
return;
+ }
this._addEvent(serviceEvent);
}
_onOriginChanged() {
// No need to refresh the view if we are already showing all events.
- if (this._originCheckbox.checked())
+ if (this._originCheckbox.checked()) {
return;
+ }
this._refreshView();
}
@@ -234,8 +239,9 @@ Resources.BackgroundServiceView = class extends UI.VBox {
// Try to get the scope of the Service Worker registration to be more user-friendly.
const registration = this._serviceWorkerManager.registrations().get(serviceEvent.serviceWorkerRegistrationId);
- if (registration)
+ if (registration) {
swScope = registration.scopeURL.substr(registration.securityOrigin.length);
+ }
return {
id: this._dataGrid.rootNode().children.length + 1,
@@ -253,11 +259,13 @@ Resources.BackgroundServiceView = class extends UI.VBox {
* @return {boolean}
*/
_acceptEvent(event) {
- if (event.service !== this._serviceName)
+ if (event.service !== this._serviceName) {
return false;
+ }
- if (this._originCheckbox.checked())
+ if (this._originCheckbox.checked()) {
return true;
+ }
// Trim the trailing '/'.
const origin = event.origin.substr(0, event.origin.length - 1);
@@ -296,13 +304,15 @@ Resources.BackgroundServiceView = class extends UI.VBox {
* @param {?Resources.BackgroundServiceView.EventDataNode} dataNode
*/
_showPreview(dataNode) {
- if (this._selectedEventNode && this._selectedEventNode === dataNode)
+ if (this._selectedEventNode && this._selectedEventNode === dataNode) {
return;
+ }
this._selectedEventNode = dataNode;
- if (this._preview)
+ if (this._preview) {
this._preview.detach();
+ }
if (this._selectedEventNode) {
this._preview = this._selectedEventNode.createPreview();
@@ -349,8 +359,9 @@ Resources.BackgroundServiceView = class extends UI.VBox {
const stream = new Bindings.FileOutputStream();
const accepted = await stream.open(fileName);
- if (!accepted)
+ if (!accepted) {
return;
+ }
const events = this._model.getEvents(this._serviceName).filter(event => this._acceptEvent(event));
await stream.write(JSON.stringify(events, undefined, 2));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ClearStorageView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ClearStorageView.js
index 94c15bc7433..5966f5d426f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ClearStorageView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ClearStorageView.js
@@ -29,8 +29,9 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
this._securityOrigin = null;
this._settings = new Map();
- for (const type of Resources.ClearStorageView.AllStorageTypes)
+ for (const type of Resources.ClearStorageView.AllStorageTypes) {
this._settings.set(type, Common.settings.createSetting('clear-storage-' + type, true));
+ }
const quota = this._reportView.appendSection(Common.UIString('Usage'));
this._quotaRow = quota.appendSelectableRow();
@@ -84,8 +85,9 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
* @param {!SDK.Target} target
*/
targetAdded(target) {
- if (this._target)
+ if (this._target) {
return;
+ }
this._target = target;
const securityOriginManager = target.model(SDK.SecurityOriginManager);
this._updateOrigin(
@@ -99,8 +101,9 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
* @param {!SDK.Target} target
*/
targetRemoved(target) {
- if (this._target !== target)
+ if (this._target !== target) {
return;
+ }
const securityOriginManager = target.model(SDK.SecurityOriginManager);
securityOriginManager.removeEventListener(
SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this._originChanged, this);
@@ -132,16 +135,19 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
}
_clear() {
- if (!this._securityOrigin)
+ if (!this._securityOrigin) {
return;
+ }
const selectedStorageTypes = [];
for (const type of this._settings.keys()) {
- if (this._settings.get(type).get())
+ if (this._settings.get(type).get()) {
selectedStorageTypes.push(type);
+ }
}
- if (this._target)
+ if (this._target) {
Resources.ClearStorageView.clear(this._target, this._securityOrigin, selectedStorageTypes);
+ }
this._clearButton.disabled = true;
const label = this._clearButton.textContent;
@@ -164,22 +170,25 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
const hasAll = set.has(Protocol.Storage.StorageType.All);
if (set.has(Protocol.Storage.StorageType.Cookies) || hasAll) {
const cookieModel = target.model(SDK.CookieModel);
- if (cookieModel)
+ if (cookieModel) {
cookieModel.clear();
+ }
}
if (set.has(Protocol.Storage.StorageType.Indexeddb) || hasAll) {
for (const target of SDK.targetManager.targets()) {
const indexedDBModel = target.model(Resources.IndexedDBModel);
- if (indexedDBModel)
+ if (indexedDBModel) {
indexedDBModel.clearForOrigin(securityOrigin);
+ }
}
}
if (set.has(Protocol.Storage.StorageType.Local_storage) || hasAll) {
const storageModel = target.model(Resources.DOMStorageModel);
- if (storageModel)
+ if (storageModel) {
storageModel.clearForOrigin(securityOrigin);
+ }
}
if (set.has(Protocol.Storage.StorageType.Websql) || hasAll) {
@@ -193,14 +202,16 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
if (set.has(Protocol.Storage.StorageType.Cache_storage) || hasAll) {
const target = SDK.targetManager.mainTarget();
const model = target && target.model(SDK.ServiceWorkerCacheModel);
- if (model)
+ if (model) {
model.clearForOrigin(securityOrigin);
+ }
}
if (set.has(Protocol.Storage.StorageType.Appcache) || hasAll) {
const appcacheModel = target.model(Resources.ApplicationCacheModel);
- if (appcacheModel)
+ if (appcacheModel) {
appcacheModel.reset();
+ }
}
}
@@ -209,8 +220,9 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
* @return {!Promise<?>}
*/
async doUpdate() {
- if (!this._securityOrigin)
+ if (!this._securityOrigin) {
return;
+ }
const securityOrigin = /** @type {string} */ (this._securityOrigin);
const response = await this._target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});
@@ -220,7 +232,7 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
return;
}
this._quotaRow.textContent = Common.UIString(
- '%s used out of %s storage quota.\u00a0', Number.bytesToString(response.usage),
+ '%s used out of %s storage quota.\xA0', Number.bytesToString(response.usage),
Number.bytesToString(response.quota));
if (response.quota < 125829120) { // 120 MB
this._quotaRow.title = ls`Storage quota is limited in Incognito mode`;
@@ -232,8 +244,9 @@ Resources.ClearStorageView = class extends UI.ThrottledWidget {
this._resetPieChart(response.usage);
for (const usageForType of response.usageBreakdown.sort((a, b) => b.usage - a.usage)) {
const value = usageForType.usage;
- if (!value)
+ if (!value) {
continue;
+ }
const title = this._getStorageTypeName(usageForType.storageType);
const color = this._pieColors.get(usageForType.storageType) || '#ccc';
this._pieChart.addSlice(value, color, title);
@@ -313,14 +326,17 @@ Resources.ClearStorageView.ActionDelegate = class {
*/
_handleClear() {
const target = SDK.targetManager.mainTarget();
- if (!target)
+ if (!target) {
return false;
+ }
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
- if (!resourceTreeModel)
+ if (!resourceTreeModel) {
return false;
+ }
const securityOrigin = resourceTreeModel.getMainSecurityOrigin();
- if (!securityOrigin)
+ if (!securityOrigin) {
return false;
+ }
Resources.ClearStorageView.clear(target, securityOrigin, Resources.ClearStorageView.AllStorageTypes);
return true;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/CookieItemsView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/CookieItemsView.js
index fcb7abe2745..e6299eba33f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/CookieItemsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/CookieItemsView.js
@@ -35,6 +35,7 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
constructor(model, cookieDomain) {
super(Common.UIString('Cookies'), 'cookiesPanel');
+ this.registerRequiredCSS('resources/cookieItemsView.css');
this.element.classList.add('storage-view');
this._model = model;
@@ -42,10 +43,34 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
this._totalSize = 0;
/** @type {?CookieTable.CookiesTable} */
- this._cookiesTable = null;
+ this._cookiesTable = this._cookiesTable = new CookieTable.CookiesTable(
+ /* renderInline */ false, this._saveCookie.bind(this), this.refreshItems.bind(this),
+ this._handleCookieSelected.bind(this), this._deleteCookie.bind(this));
+
+ this._cookiesTable.setMinimumSize(0, 50);
+
+ this._splitWidget = new UI.SplitWidget(false, false);
+ this._splitWidget.show(this.element);
+ this._splitWidget.setSecondIsSidebar(true);
+
+ this._previewPanel = new UI.VBox();
+ const resizer = this._previewPanel.element.createChild('div', 'preview-panel-resizer');
+
+ this._splitWidget.setMainWidget(this._cookiesTable);
+ this._splitWidget.setSidebarWidget(this._previewPanel);
+ this._splitWidget.installResizer(resizer);
+
+
this._refreshThrottler = new Common.Throttler(300);
/** @type {!Array<!Common.EventTarget.EventDescriptor>} */
this._eventDescriptors = [];
+
+
+ /** @type {?UI.Widget} */
+ this._preview = null;
+ /** @type {?SDK.Cookie} */
+ this._previewValue = null;
+
this.setCookiesDomain(model, cookieDomain);
}
@@ -61,6 +86,60 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
const networkManager = model.target().model(SDK.NetworkManager);
this._eventDescriptors =
[networkManager.addEventListener(SDK.NetworkManager.Events.ResponseReceived, this._onResponseReceived, this)];
+
+ this._showPreview(null, null);
+ }
+
+ /**
+ * @param {?UI.Widget} preview
+ * @param {?SDK.Cookie} value
+ */
+ _showPreview(preview, value) {
+ if (this._preview && this._previewValue === value) {
+ return;
+ }
+
+ if (this._preview) {
+ this._preview.detach();
+ }
+
+ if (!preview) {
+ preview = new UI.EmptyWidget(ls`Select a cookie to preview its value`);
+ }
+
+ this._previewValue = value;
+ this._preview = preview;
+
+ preview.show(this._previewPanel.contentElement);
+ }
+
+ _handleCookieSelected() {
+ const cookie = this._cookiesTable.selectedCookie();
+ this.setCanDeleteSelected(!!cookie);
+
+ if (!cookie) {
+ this._showPreview(null, null);
+ return;
+ }
+
+ const value = createElementWithClass('div', 'cookie-value');
+ value.textContent = cookie.value();
+ value.addEventListener('dblclick', handleDblClickOnCookieValue);
+
+ const preview = new UI.VBox();
+ preview.contentElement.appendChild(value);
+
+ this._showPreview(preview, cookie);
+
+ /**
+ * @suppressGlobalPropertiesCheck
+ */
+ function handleDblClickOnCookieValue() {
+ const range = document.createRange();
+ range.selectNode(value);
+ window.getSelection().removeAllRanges();
+ window.getSelection().addRange(range);
+ }
}
/**
@@ -69,10 +148,12 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
* @return {!Promise<boolean>}
*/
_saveCookie(newCookie, oldCookie) {
- if (!this._model)
+ if (!this._model) {
return Promise.resolve(false);
- if (oldCookie && (newCookie.name() !== oldCookie.name() || newCookie.url() !== oldCookie.url()))
+ }
+ if (oldCookie && (newCookie.name() !== oldCookie.name() || newCookie.url() !== oldCookie.url())) {
this._model.deleteCookie(oldCookie);
+ }
return this._model.saveCookie(newCookie);
}
@@ -90,21 +171,12 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
_updateWithCookies(allCookies) {
this._totalSize = allCookies.reduce((size, cookie) => size + cookie.size(), 0);
- if (!this._cookiesTable) {
- this._cookiesTable = new CookieTable.CookiesTable(
- this._saveCookie.bind(this),
- this.refreshItems.bind(this),
- () => this.setCanDeleteSelected(!!this._cookiesTable.selectedCookie()),
- this._deleteCookie.bind(this));
- }
-
const parsedURL = this._cookieDomain.asParsedURL();
const host = parsedURL ? parsedURL.host : '';
this._cookiesTable.setCookieDomain(host);
const shownCookies = this.filter(allCookies, cookie => `${cookie.name()} ${cookie.value()} ${cookie.domain()}`);
this._cookiesTable.setCookies(shownCookies);
- this._cookiesTable.show(this.element);
this.setCanFilter(true);
this.setCanDeleteAll(true);
this.setCanDeleteSelected(!!this._cookiesTable.selectedCookie());
@@ -122,8 +194,9 @@ Resources.CookieItemsView = class extends Resources.StorageItemsView {
*/
deleteSelectedItem() {
const selectedCookie = this._cookiesTable.selectedCookie();
- if (selectedCookie)
+ if (selectedCookie) {
this._model.deleteCookie(selectedCookie, () => this.refreshItems());
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageItemsView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageItemsView.js
index 7b054ca45cd..6a22561f7c9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageItemsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageItemsView.js
@@ -91,8 +91,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
}
_domStorageItemsCleared() {
- if (!this.isShowing() || !this._dataGrid)
+ if (!this.isShowing() || !this._dataGrid) {
return;
+ }
this._dataGrid.rootNode().removeChildren();
this._dataGrid.addCreationNode(false);
@@ -103,8 +104,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
* @param {!Common.Event} event
*/
_domStorageItemRemoved(event) {
- if (!this.isShowing() || !this._dataGrid)
+ if (!this.isShowing() || !this._dataGrid) {
return;
+ }
const storageData = event.data;
const rootNode = this._dataGrid.rootNode();
@@ -124,16 +126,18 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
* @param {!Common.Event} event
*/
_domStorageItemAdded(event) {
- if (!this.isShowing() || !this._dataGrid)
+ if (!this.isShowing() || !this._dataGrid) {
return;
+ }
const storageData = event.data;
const rootNode = this._dataGrid.rootNode();
const children = rootNode.children;
for (let i = 0; i < children.length; ++i) {
- if (children[i].data.key === storageData.key)
+ if (children[i].data.key === storageData.key) {
return;
+ }
}
const childNode = new DataGrid.DataGridNode({key: storageData.key, value: storageData.value}, false);
@@ -144,18 +148,21 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
* @param {!Common.Event} event
*/
_domStorageItemUpdated(event) {
- if (!this.isShowing() || !this._dataGrid)
+ if (!this.isShowing() || !this._dataGrid) {
return;
+ }
const storageData = event.data;
const childNode = this._dataGrid.rootNode().children.find(child => child.data.key === storageData.key);
- if (!childNode || childNode.data.value === storageData.value)
+ if (!childNode || childNode.data.value === storageData.value) {
return;
+ }
childNode.data.value = storageData.value;
childNode.refresh();
- if (!childNode.selected)
+ if (!childNode.selected) {
return;
+ }
this._previewEntry(childNode);
this.setCanDeleteSelected(true);
}
@@ -167,8 +174,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
const rootNode = this._dataGrid.rootNode();
let selectedKey = null;
for (const node of rootNode.children) {
- if (!node.selected)
+ if (!node.selected) {
continue;
+ }
selectedKey = node.data.key;
break;
}
@@ -181,11 +189,13 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
const node = new DataGrid.DataGridNode({key: key, value: value}, false);
node.selectable = true;
rootNode.appendChild(node);
- if (!selectedNode || key === selectedKey)
+ if (!selectedNode || key === selectedKey) {
selectedNode = node;
+ }
}
- if (selectedNode)
+ if (selectedNode) {
selectedNode.selected = true;
+ }
this._dataGrid.addCreationNode(false);
this.setCanDeleteSelected(!!selectedNode);
}
@@ -194,8 +204,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
* @override
*/
deleteSelectedItem() {
- if (!this._dataGrid || !this._dataGrid.selectedNode)
+ if (!this._dataGrid || !this._dataGrid.selectedNode) {
return;
+ }
this._deleteCallback(this._dataGrid.selectedNode);
}
@@ -219,8 +230,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
_editingCallback(editingNode, columnIdentifier, oldText, newText) {
const domStorage = this._domStorage;
if (columnIdentifier === 'key') {
- if (typeof oldText === 'string')
+ if (typeof oldText === 'string') {
domStorage.removeItem(oldText);
+ }
domStorage.setItem(newText, editingNode.data.value || '');
this._removeDupes(editingNode);
} else {
@@ -236,17 +248,20 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
const children = rootNode.children;
for (let i = children.length - 1; i >= 0; --i) {
const childNode = children[i];
- if ((childNode.data.key === masterNode.data.key) && (masterNode !== childNode))
+ if ((childNode.data.key === masterNode.data.key) && (masterNode !== childNode)) {
rootNode.removeChild(childNode);
+ }
}
}
_deleteCallback(node) {
- if (!node || node.isCreationNode)
+ if (!node || node.isCreationNode) {
return;
+ }
- if (this._domStorage)
+ if (this._domStorage) {
this._domStorage.removeItem(node.data.key);
+ }
}
/**
@@ -254,12 +269,15 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
* @param {?string} value
*/
_showPreview(preview, value) {
- if (this._preview && this._previewValue === value)
+ if (this._preview && this._previewValue === value) {
return;
- if (this._preview)
+ }
+ if (this._preview) {
this._preview.detach();
- if (!preview)
+ }
+ if (!preview) {
preview = new UI.EmptyWidget(Common.UIString('Select a value to preview'));
+ }
this._previewValue = value;
this._preview = preview;
preview.show(this._previewPanel.contentElement);
@@ -280,8 +298,9 @@ Resources.DOMStorageItemsView = class extends Resources.StorageItemsView {
Common.StaticContentProvider.fromString(url, Common.resourceTypes.XHR, /** @type {string} */ (value));
const preview = await SourceFrame.PreviewFactory.createPreview(provider, 'text/plain');
// Selection could've changed while the preview was loaded
- if (!entry.selected)
+ if (!entry.selected) {
return;
+ }
this._showPreview(preview, value);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageModel.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageModel.js
index 176f1d117b3..c9a1cbfce21 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/DOMStorageModel.js
@@ -120,8 +120,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this.target().registerDOMStorageDispatcher(new Resources.DOMStorageDispatcher(this));
this._securityOriginManager.addEventListener(
@@ -129,8 +130,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
this._securityOriginManager.addEventListener(
SDK.SecurityOriginManager.Events.SecurityOriginRemoved, this._securityOriginRemoved, this);
- for (const securityOrigin of this._securityOriginManager.securityOrigins())
+ for (const securityOrigin of this._securityOriginManager.securityOrigins()) {
this._addOrigin(securityOrigin);
+ }
this._agent.enable();
this._enabled = true;
@@ -140,8 +142,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
* @param {string} origin
*/
clearForOrigin(origin) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
for (const isLocal of [true, false]) {
const key = this._storageKey(origin, isLocal);
const storage = this._storages[key];
@@ -164,8 +167,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
_addOrigin(securityOrigin) {
const parsed = new Common.ParsedURL(securityOrigin);
// These are "opaque" origins which are not supposed to support DOM storage.
- if (!parsed.isValid || parsed.scheme === 'data' || parsed.scheme === 'about' || parsed.scheme === 'javascript')
+ if (!parsed.isValid || parsed.scheme === 'data' || parsed.scheme === 'about' || parsed.scheme === 'javascript') {
return;
+ }
for (const isLocal of [true, false]) {
const key = this._storageKey(securityOrigin, isLocal);
@@ -190,8 +194,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
for (const isLocal of [true, false]) {
const key = this._storageKey(securityOrigin, isLocal);
const storage = this._storages[key];
- if (!storage)
+ if (!storage) {
continue;
+ }
delete this._storages[key];
this.dispatchEventToListeners(Resources.DOMStorageModel.Events.DOMStorageRemoved, storage);
}
@@ -211,8 +216,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
*/
_domStorageItemsCleared(storageId) {
const domStorage = this.storageForId(storageId);
- if (!domStorage)
+ if (!domStorage) {
return;
+ }
const eventData = {};
domStorage.dispatchEventToListeners(Resources.DOMStorage.Events.DOMStorageItemsCleared, eventData);
@@ -224,8 +230,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
*/
_domStorageItemRemoved(storageId, key) {
const domStorage = this.storageForId(storageId);
- if (!domStorage)
+ if (!domStorage) {
return;
+ }
const eventData = {key: key};
domStorage.dispatchEventToListeners(Resources.DOMStorage.Events.DOMStorageItemRemoved, eventData);
@@ -238,8 +245,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
*/
_domStorageItemAdded(storageId, key, value) {
const domStorage = this.storageForId(storageId);
- if (!domStorage)
+ if (!domStorage) {
return;
+ }
const eventData = {key: key, value: value};
domStorage.dispatchEventToListeners(Resources.DOMStorage.Events.DOMStorageItemAdded, eventData);
@@ -253,8 +261,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
*/
_domStorageItemUpdated(storageId, key, oldValue, value) {
const domStorage = this.storageForId(storageId);
- if (!domStorage)
+ if (!domStorage) {
return;
+ }
const eventData = {key: key, oldValue: oldValue, value: value};
domStorage.dispatchEventToListeners(Resources.DOMStorage.Events.DOMStorageItemUpdated, eventData);
@@ -273,8 +282,9 @@ Resources.DOMStorageModel = class extends SDK.SDKModel {
*/
storages() {
const result = [];
- for (const id in this._storages)
+ for (const id in this._storages) {
result.push(this._storages[id]);
+ }
return result;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseModel.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseModel.js
index 816abc53a42..cd3b1d3cbee 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseModel.js
@@ -106,12 +106,13 @@ Resources.Database = class {
return;
}
let message;
- if (sqlError.message)
+ if (sqlError.message) {
message = sqlError.message;
- else if (sqlError.code === 2)
+ } else if (sqlError.code === 2) {
message = Common.UIString('Database no longer has expected version.');
- else
+ } else {
message = Common.UIString('An unexpected error %s occurred.', sqlError.code);
+ }
onError(message);
}
};
@@ -132,15 +133,17 @@ Resources.DatabaseModel = class extends SDK.SDKModel {
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._agent.enable();
this._enabled = true;
}
disable() {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
this._enabled = false;
this._databases = [];
this._agent.disable();
@@ -152,8 +155,9 @@ Resources.DatabaseModel = class extends SDK.SDKModel {
*/
databases() {
const result = [];
- for (const database of this._databases)
+ for (const database of this._databases) {
result.push(database);
+ }
return result;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseQueryView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseQueryView.js
index 3921e9dbe28..bcbc5791b43 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseQueryView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseQueryView.js
@@ -51,8 +51,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
}
_messagesClicked() {
- if (!this._prompt.isCaretInsidePrompt() && !this.element.hasSelection())
+ if (!this._prompt.isCaretInsidePrompt() && !this.element.hasSelection()) {
this._prompt.moveCaretToEndOfPrompt();
+ }
}
/**
@@ -62,8 +63,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
* @return {!Promise<!UI.SuggestBox.Suggestions>}
*/
async completions(expression, prefix, force) {
- if (!prefix)
+ if (!prefix) {
return [];
+ }
prefix = prefix.toLowerCase();
const tableNames = await this.database.tableNames();
@@ -74,8 +76,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
}
_selectStart(event) {
- if (this._selectionTimeout)
+ if (this._selectionTimeout) {
clearTimeout(this._selectionTimeout);
+ }
this._prompt.clearAutocomplete();
@@ -84,8 +87,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
*/
function moveBackIfOutside() {
delete this._selectionTimeout;
- if (!this._prompt.isCaretInsidePrompt() && !this.element.hasSelection())
+ if (!this._prompt.isCaretInsidePrompt() && !this.element.hasSelection()) {
this._prompt.moveCaretToEndOfPrompt();
+ }
this._prompt.autoCompleteSoon();
}
@@ -105,8 +109,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
const query = this._prompt.textWithCurrentSuggestion();
this._prompt.clearAutocomplete();
- if (!query.length)
+ if (!query.length) {
return;
+ }
this._prompt.setEnabled(false);
try {
@@ -136,8 +141,9 @@ Resources.DatabaseQueryView = class extends UI.VBox {
}
this._appendViewQueryResult(trimmedQuery, view);
- if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
+ if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i)) {
this.dispatchEventToListeners(Resources.DatabaseQueryView.Events.SchemaUpdated, this.database);
+ }
}
/**
@@ -146,10 +152,11 @@ Resources.DatabaseQueryView = class extends UI.VBox {
*/
_appendViewQueryResult(query, view) {
const resultElement = this._appendQueryResult(query);
- if (view)
+ if (view) {
view.show(resultElement);
- else
+ } else {
resultElement.remove();
+ }
this._promptElement.scrollIntoView(false);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js
index 2fd959ea3e7..056a3b6b327 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js
@@ -39,7 +39,7 @@ Resources.DatabaseTableView = class extends UI.SimpleView {
this.refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh');
this.refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this);
- this._visibleColumnsInput = new UI.ToolbarInput(Common.UIString('Visible columns'), 1);
+ this._visibleColumnsInput = new UI.ToolbarInput(Common.UIString('Visible columns'), '', 1);
this._visibleColumnsInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onVisibleColumnsChanged, this);
}
@@ -88,8 +88,9 @@ Resources.DatabaseTableView = class extends UI.SimpleView {
this._dataGrid.autoSizeColumns(5);
this._columnsMap = new Map();
- for (let i = 1; i < columnNames.length; ++i)
+ for (let i = 1; i < columnNames.length; ++i) {
this._columnsMap.set(columnNames[i], String(i));
+ }
this._lastVisibleColumns = '';
const visibleColumnsText = this._visibleColumnsSetting.get()[this.tableName] || '';
this._visibleColumnsInput.setValue(visibleColumnsText);
@@ -97,8 +98,9 @@ Resources.DatabaseTableView = class extends UI.SimpleView {
}
_onVisibleColumnsChanged() {
- if (!this._dataGrid)
+ if (!this._dataGrid) {
return;
+ }
const text = this._visibleColumnsInput.value();
const parts = text.split(/[\s,]+/);
const matches = new Set();
@@ -113,11 +115,13 @@ Resources.DatabaseTableView = class extends UI.SimpleView {
}
const newVisibleColumns = matches.valuesArray().sort().join(', ');
if (newVisibleColumns.length === 0) {
- for (const v of this._columnsMap.values())
+ for (const v of this._columnsMap.values()) {
columnsVisibility[v] = true;
+ }
}
- if (newVisibleColumns === this._lastVisibleColumns)
+ if (newVisibleColumns === this._lastVisibleColumns) {
return;
+ }
const visibleColumnsRegistry = this._visibleColumnsSetting.get();
visibleColumnsRegistry[this.tableName] = text;
this._visibleColumnsSetting.set(visibleColumnsRegistry);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBModel.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBModel.js
index 8a95859c53e..52b4717edcc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBModel.js
@@ -63,8 +63,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
* }|undefined)}
*/
static keyFromIDBKey(idbKey) {
- if (typeof(idbKey) === 'undefined' || idbKey === null)
+ if (typeof (idbKey) === 'undefined' || idbKey === null) {
return undefined;
+ }
let type;
const key = {};
@@ -83,8 +84,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
type = Resources.IndexedDBModel.KeyTypes.DateType;
} else if (Array.isArray(idbKey)) {
key.array = [];
- for (let i = 0; i < idbKey.length; ++i)
+ for (let i = 0; i < idbKey.length; ++i) {
key.array.push(Resources.IndexedDBModel.keyFromIDBKey(idbKey[i]));
+ }
type = Resources.IndexedDBModel.KeyTypes.ArrayType;
}
break;
@@ -133,16 +135,19 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
* @return {?string}
*/
static keyPathStringFromIDBKeyPath(idbKeyPath) {
- if (typeof idbKeyPath === 'string')
+ if (typeof idbKeyPath === 'string') {
return '"' + idbKeyPath + '"';
- if (idbKeyPath instanceof Array)
+ }
+ if (idbKeyPath instanceof Array) {
return '["' + idbKeyPath.join('", "') + '"]';
+ }
return null;
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._indexedDBAgent.enable();
this._securityOriginManager.addEventListener(
@@ -150,8 +155,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
this._securityOriginManager.addEventListener(
SDK.SecurityOriginManager.Events.SecurityOriginRemoved, this._securityOriginRemoved, this);
- for (const securityOrigin of this._securityOriginManager.securityOrigins())
+ for (const securityOrigin of this._securityOriginManager.securityOrigins()) {
this._addOrigin(securityOrigin);
+ }
this._enabled = true;
}
@@ -160,8 +166,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
* @param {string} origin
*/
clearForOrigin(origin) {
- if (!this._enabled || !this._databaseNamesBySecurityOrigin[origin])
+ if (!this._enabled || !this._databaseNamesBySecurityOrigin[origin]) {
return;
+ }
this._removeOrigin(origin);
this._addOrigin(origin);
@@ -171,15 +178,17 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
* @param {!Resources.IndexedDBModel.DatabaseId} databaseId
*/
async deleteDatabase(databaseId) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
await this._indexedDBAgent.deleteDatabase(databaseId.securityOrigin, databaseId.name);
this._loadDatabaseNames(databaseId.securityOrigin);
}
async refreshDatabaseNames() {
- for (const securityOrigin in this._databaseNamesBySecurityOrigin)
+ for (const securityOrigin in this._databaseNamesBySecurityOrigin) {
await this._loadDatabaseNames(securityOrigin);
+ }
this.dispatchEventToListeners(Resources.IndexedDBModel.Events.DatabaseNamesRefreshed);
}
@@ -234,8 +243,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
console.assert(!this._databaseNamesBySecurityOrigin[securityOrigin]);
this._databaseNamesBySecurityOrigin[securityOrigin] = [];
this._loadDatabaseNames(securityOrigin);
- if (this._isValidSecurityOrigin(securityOrigin))
+ if (this._isValidSecurityOrigin(securityOrigin)) {
this._storageAgent.trackIndexedDBForOrigin(securityOrigin);
+ }
}
/**
@@ -243,11 +253,13 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
*/
_removeOrigin(securityOrigin) {
console.assert(this._databaseNamesBySecurityOrigin[securityOrigin]);
- for (let i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i)
+ for (let i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i) {
this._databaseRemoved(securityOrigin, this._databaseNamesBySecurityOrigin[securityOrigin][i]);
+ }
delete this._databaseNamesBySecurityOrigin[securityOrigin];
- if (this._isValidSecurityOrigin(securityOrigin))
+ if (this._isValidSecurityOrigin(securityOrigin)) {
this._storageAgent.untrackIndexedDBForOrigin(securityOrigin);
+ }
}
/**
@@ -270,12 +282,14 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
this._databaseNamesBySecurityOrigin[securityOrigin] = databaseNames;
for (const databaseName of oldDatabaseNames) {
- if (!newDatabaseNames.has(databaseName))
+ if (!newDatabaseNames.has(databaseName)) {
this._databaseRemoved(securityOrigin, databaseName);
+ }
}
for (const databaseName of newDatabaseNames) {
- if (!oldDatabaseNames.has(databaseName))
+ if (!oldDatabaseNames.has(databaseName)) {
this._databaseAdded(securityOrigin, databaseName);
+ }
}
}
@@ -286,8 +300,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
const result = [];
for (const securityOrigin in this._databaseNamesBySecurityOrigin) {
const databaseNames = this._databaseNamesBySecurityOrigin[securityOrigin];
- for (let i = 0; i < databaseNames.length; ++i)
+ for (let i = 0; i < databaseNames.length; ++i) {
result.push(new Resources.IndexedDBModel.DatabaseId(securityOrigin, databaseNames[i]));
+ }
}
return result;
}
@@ -317,10 +332,12 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
*/
async _loadDatabaseNames(securityOrigin) {
const databaseNames = await this._indexedDBAgent.requestDatabaseNames(securityOrigin);
- if (!databaseNames)
+ if (!databaseNames) {
return [];
- if (!this._databaseNamesBySecurityOrigin[securityOrigin])
+ }
+ if (!this._databaseNamesBySecurityOrigin[securityOrigin]) {
return [];
+ }
this._updateOriginDatabaseNames(securityOrigin, databaseNames);
return databaseNames;
}
@@ -333,10 +350,12 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
const databaseWithObjectStores =
await this._indexedDBAgent.requestDatabase(databaseId.securityOrigin, databaseId.name);
- if (!databaseWithObjectStores)
+ if (!databaseWithObjectStores) {
return;
- if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
+ }
+ if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin]) {
return;
+ }
const databaseModel = new Resources.IndexedDBModel.Database(databaseId, databaseWithObjectStores.version);
this._databases.set(databaseId, databaseModel);
@@ -414,8 +433,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
}
const runtimeModel = this.target().model(SDK.RuntimeModel);
- if (!runtimeModel || !this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
+ if (!runtimeModel || !this._databaseNamesBySecurityOrigin[databaseId.securityOrigin]) {
return;
+ }
const dataEntries = response.objectStoreDataEntries;
const entries = [];
for (const dataEntry of dataEntries) {
@@ -451,8 +471,9 @@ Resources.IndexedDBModel = class extends SDK.SDKModel {
*/
async _refreshDatabaseList(securityOrigin) {
const databaseNames = await this._loadDatabaseNames(securityOrigin);
- for (const databaseName of databaseNames)
+ for (const databaseName of databaseNames) {
this._loadDatabase(new Resources.IndexedDBModel.DatabaseId(securityOrigin, databaseName), false);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
index d0713123f65..61114e51329 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
@@ -58,8 +58,9 @@ Resources.IDBDatabaseView = class extends UI.VBox {
UI.createTextButton(ls`Refresh database`, () => this._refreshDatabaseButtonClicked(), ls`Refresh database`);
footer.appendChild(this._refreshButton);
- if (database)
+ if (database) {
this.update(database);
+ }
}
_refreshDatabase() {
@@ -89,8 +90,9 @@ Resources.IDBDatabaseView = class extends UI.VBox {
async _deleteDatabase() {
const ok = await UI.ConfirmDialog.show(
Common.UIString('Please confirm delete of "%s" database.', this._database.databaseId.name), this.element);
- if (ok)
+ if (ok) {
this._model.deleteDatabase(this._database.databaseId);
+ }
}
};
@@ -173,15 +175,17 @@ Resources.IDBDataView = class extends UI.SimpleView {
_keyColumnHeaderFragment(prefix, keyPath) {
const keyColumnHeaderFragment = createDocumentFragment();
keyColumnHeaderFragment.createTextChild(prefix);
- if (keyPath === null)
+ if (keyPath === null) {
return keyColumnHeaderFragment;
+ }
keyColumnHeaderFragment.createTextChild(' (' + Common.UIString('Key path: '));
if (Array.isArray(keyPath)) {
keyColumnHeaderFragment.createTextChild('[');
for (let i = 0; i < keyPath.length; ++i) {
- if (i !== 0)
+ if (i !== 0) {
keyColumnHeaderFragment.createTextChild(', ');
+ }
keyColumnHeaderFragment.appendChild(this._keyPathStringFragment(keyPath[i]));
}
keyColumnHeaderFragment.createTextChild(']');
@@ -222,7 +226,7 @@ Resources.IDBDataView = class extends UI.SimpleView {
this._pageForwardButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageForwardButtonClicked, this);
editorToolbar.appendToolbarItem(this._pageForwardButton);
- this._keyInput = new UI.ToolbarInput(ls`Start from key`, 0.5);
+ this._keyInput = new UI.ToolbarInput(ls`Start from key`, '', 0.5);
this._keyInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._updateData.bind(this, false));
editorToolbar.appendToolbarItem(this._keyInput);
editorToolbar.appendToolbarItem(new UI.ToolbarSeparator());
@@ -248,6 +252,22 @@ Resources.IDBDataView = class extends UI.SimpleView {
this._updateData(false);
}
+ /**
+ * @param {!UI.ContextMenu} contextMenu
+ * @param {!DataGrid.DataGridNode} gridNode
+ */
+ _populateContextMenu(contextMenu, gridNode) {
+ const node = /** @type {!Resources.IDBDataGridNode} */ (gridNode);
+ if (node.valueObjectPresentation) {
+ contextMenu.revealSection().appendItem(ls`Expand Recursively`, () => {
+ node.valueObjectPresentation.objectTreeElement().expandRecursively();
+ });
+ contextMenu.revealSection().appendItem(ls`Collapse`, () => {
+ node.valueObjectPresentation.objectTreeElement().collapse();
+ });
+ }
+ }
+
refreshData() {
this._updateData(true);
}
@@ -260,9 +280,11 @@ Resources.IDBDataView = class extends UI.SimpleView {
this._objectStore = objectStore;
this._index = index;
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.asWidget().detach();
+ }
this._dataGrid = this._createDataGrid();
+ this._dataGrid.setRowContextMenuCallback(this._populateContextMenu.bind(this));
this._dataGrid.asWidget().show(this.element);
this._skipCount = 0;
@@ -294,8 +316,9 @@ Resources.IDBDataView = class extends UI.SimpleView {
this._refreshButton.setEnabled(false);
this._clearButton.setEnabled(!this._isIndex);
- if (!force && this._lastKey === key && this._lastPageSize === pageSize && this._lastSkipCount === skipCount)
+ if (!force && this._lastKey === key && this._lastPageSize === pageSize && this._lastSkipCount === skipCount) {
return;
+ }
if (this._lastKey !== key || this._lastPageSize !== pageSize) {
skipCount = 0;
@@ -324,12 +347,14 @@ Resources.IDBDataView = class extends UI.SimpleView {
const node = new Resources.IDBDataGridNode(data);
this._dataGrid.rootNode().appendChild(node);
- if (data['number'] <= selected)
+ if (data['number'] <= selected) {
selectedNode = node;
+ }
}
- if (selectedNode)
+ if (selectedNode) {
selectedNode.select();
+ }
this._pageBackButton.setEnabled(!!skipCount);
this._pageForwardButton.setEnabled(hasMore);
this._needsRefresh.setVisible(false);
@@ -353,11 +378,13 @@ Resources.IDBDataView = class extends UI.SimpleView {
* @param {?Resources.IndexedDBModel.ObjectStoreMetadata} metadata
*/
_updateSummaryBar(metadata) {
- if (!this._summaryBarElement)
+ if (!this._summaryBarElement) {
this._summaryBarElement = this.element.createChild('div', 'object-store-summary-bar');
+ }
this._summaryBarElement.removeChildren();
- if (!metadata)
+ if (!metadata) {
return;
+ }
const separator = '\u2002\u2758\u2002';
@@ -401,8 +428,9 @@ Resources.IDBDataView = class extends UI.SimpleView {
async _deleteButtonClicked(node) {
if (!node) {
node = this._dataGrid.selectedNode;
- if (!node)
+ if (!node) {
return;
+ }
}
const key = /** @type {!SDK.RemoteObject} */ (this._isIndex ? node.data.primaryKey : node.data.key);
const keyValue = /** @type {!Array<?>|!Date|number|string} */ (key.value);
@@ -432,6 +460,8 @@ Resources.IDBDataGridNode = class extends DataGrid.DataGridNode {
constructor(data) {
super(data, false);
this.selectable = true;
+ /** @type {?ObjectUI.ObjectPropertiesSection} */
+ this.valueObjectPresentation = null;
}
/**
@@ -444,10 +474,17 @@ Resources.IDBDataGridNode = class extends DataGrid.DataGridNode {
switch (columnIdentifier) {
case 'value':
+ cell.removeChildren();
+ const objectPropSection = ObjectUI.ObjectPropertiesSection.defaultObjectPropertiesSection(
+ value, undefined /* linkifier */, true /* skipProto */, true /* readOnly */);
+ cell.appendChild(objectPropSection.element);
+ this.valueObjectPresentation = objectPropSection;
+ break;
case 'key':
case 'primaryKey':
cell.removeChildren();
- const objectElement = ObjectUI.ObjectPropertiesSection.defaultObjectPresentation(value, undefined, true, true);
+ const objectElement = ObjectUI.ObjectPropertiesSection.defaultObjectPresentation(
+ value, undefined /* linkifier */, true /* skipProto */, true /* readOnly */);
cell.appendChild(objectElement);
break;
default:
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesPanel.js
index 9dd82a4b4f4..a07c33b1fae 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesPanel.js
@@ -77,8 +77,9 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
}
resetView() {
- if (this.visibleView && Resources.ResourcesPanel._shouldCloseOnReset(this.visibleView))
+ if (this.visibleView && Resources.ResourcesPanel._shouldCloseOnReset(this.visibleView)) {
this.showView(null);
+ }
}
/**
@@ -86,20 +87,24 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
*/
showView(view) {
this._pendingViewPromise = null;
- if (this.visibleView === view)
+ if (this.visibleView === view) {
return;
+ }
- if (this.visibleView)
+ if (this.visibleView) {
this.visibleView.detach();
+ }
- if (view)
+ if (view) {
view.show(this.storageViews);
+ }
this.visibleView = view;
this._storageViewToolbar.removeToolbarItems();
const toolbarItems = (view instanceof UI.SimpleView && view.syncToolbarItems()) || [];
- for (let i = 0; i < toolbarItems.length; ++i)
+ for (let i = 0; i < toolbarItems.length; ++i) {
this._storageViewToolbar.appendToolbarItem(toolbarItems[i]);
+ }
this._storageViewToolbar.element.classList.toggle('hidden', !toolbarItems.length);
}
@@ -110,8 +115,9 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
async scheduleShowView(viewPromise) {
this._pendingViewPromise = viewPromise;
const view = await viewPromise;
- if (this._pendingViewPromise !== viewPromise)
+ if (this._pendingViewPromise !== viewPromise) {
return null;
+ }
this.showView(view);
return view;
}
@@ -121,8 +127,9 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
* @param {string|null} categoryLink
*/
showCategoryView(categoryName, categoryLink) {
- if (!this._categoryView)
+ if (!this._categoryView) {
this._categoryView = new Resources.StorageCategoryView();
+ }
this._categoryView.setText(categoryName);
this._categoryView.setLink(categoryLink);
this.showView(this._categoryView);
@@ -132,13 +139,15 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
* @param {!Resources.DOMStorage} domStorage
*/
showDOMStorage(domStorage) {
- if (!domStorage)
+ if (!domStorage) {
return;
+ }
- if (!this._domStorageView)
+ if (!this._domStorageView) {
this._domStorageView = new Resources.DOMStorageItemsView(domStorage);
- else
+ } else {
this._domStorageView.setStorage(domStorage);
+ }
this.showView(this._domStorageView);
}
@@ -148,12 +157,14 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
*/
showCookies(cookieFrameTarget, cookieDomain) {
const model = cookieFrameTarget.model(SDK.CookieModel);
- if (!model)
+ if (!model) {
return;
- if (!this._cookieView)
+ }
+ if (!this._cookieView) {
this._cookieView = new Resources.CookieItemsView(model, cookieDomain);
- else
+ } else {
this._cookieView.setCookiesDomain(model, cookieDomain);
+ }
this.showView(this._cookieView);
}
@@ -163,11 +174,13 @@ Resources.ResourcesPanel = class extends UI.PanelWithSidebar {
*/
clearCookies(target, cookieDomain) {
const model = target.model(SDK.CookieModel);
- if (!model)
+ if (!model) {
return;
+ }
model.clear(cookieDomain, () => {
- if (this._cookieView)
+ if (this._cookieView) {
this._cookieView.refreshItems();
+ }
});
}
};
@@ -182,8 +195,9 @@ Resources.ResourcesPanel.ResourceRevealer = class {
* @return {!Promise}
*/
async reveal(resource) {
- if (!(resource instanceof SDK.Resource))
+ if (!(resource instanceof SDK.Resource)) {
return Promise.reject(new Error('Internal error: not a resource'));
+ }
const sidebar = Resources.ResourcesPanel._instance()._sidebar;
await UI.viewManager.showView('resources');
await sidebar.showResource(resource);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js
index 40fe01ad1d1..83b2d20ffc6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js
@@ -24,8 +24,9 @@ Resources.ResourcesSection = class {
const mainTarget = SDK.targetManager.mainTarget();
const resourceTreeModel = mainTarget && mainTarget.model(SDK.ResourceTreeModel);
const mainFrame = resourceTreeModel && resourceTreeModel.mainFrame;
- if (mainFrame)
+ if (mainFrame) {
this._frameAdded(mainFrame);
+ }
}
/**
@@ -34,11 +35,13 @@ Resources.ResourcesSection = class {
*/
static _getParentFrame(frame) {
const parentFrame = frame.parentFrame;
- if (parentFrame)
+ if (parentFrame) {
return parentFrame;
+ }
const parentTarget = frame.resourceTreeModel().target().parentTarget();
- if (!parentTarget)
+ if (!parentTarget) {
return null;
+ }
return parentTarget.model(SDK.ResourceTreeModel).mainFrame;
}
@@ -47,14 +50,17 @@ Resources.ResourcesSection = class {
* @return {boolean}
*/
_expandFrame(frame) {
- if (!frame)
+ if (!frame) {
return false;
+ }
let treeElement = this._treeElementForFrameId.get(frame.id);
- if (!treeElement && !this._expandFrame(Resources.ResourcesSection._getParentFrame(frame)))
+ if (!treeElement && !this._expandFrame(Resources.ResourcesSection._getParentFrame(frame))) {
return false;
+ }
treeElement = this._treeElementForFrameId.get(frame.id);
- if (!treeElement)
+ if (!treeElement) {
return false;
+ }
treeElement.expand();
return true;
}
@@ -66,11 +72,13 @@ Resources.ResourcesSection = class {
* @return {!Promise}
*/
async revealResource(resource, line, column) {
- if (!this._expandFrame(resource.frame()))
+ if (!this._expandFrame(resource.frame())) {
return;
+ }
const resourceTreeElement = Resources.FrameResourceTreeElement.forResource(resource);
- if (resourceTreeElement)
+ if (resourceTreeElement) {
await resourceTreeElement.revealResource(line, column);
+ }
}
/**
@@ -79,8 +87,9 @@ Resources.ResourcesSection = class {
_frameAdded(frame) {
const parentFrame = Resources.ResourcesSection._getParentFrame(frame);
const parentTreeElement = parentFrame ? this._treeElementForFrameId.get(parentFrame.id) : this._treeElement;
- if (!parentTreeElement)
+ if (!parentTreeElement) {
return;
+ }
const frameTreeElement = new Resources.FrameTreeElement(this, frame);
this._treeElementForFrameId.set(frame.id, frameTreeElement);
parentTreeElement.appendChild(frameTreeElement);
@@ -91,12 +100,14 @@ Resources.ResourcesSection = class {
*/
_frameDetached(frame) {
const frameTreeElement = this._treeElementForFrameId.get(frame.id);
- if (!frameTreeElement)
+ if (!frameTreeElement) {
return;
+ }
this._treeElementForFrameId.remove(frame.id);
- if (frameTreeElement.parent)
+ if (frameTreeElement.parent) {
frameTreeElement.parent.removeChild(frameTreeElement);
+ }
}
/**
@@ -104,8 +115,9 @@ Resources.ResourcesSection = class {
*/
_frameNavigated(frame) {
const frameTreeElement = this._treeElementForFrameId.get(frame.id);
- if (frameTreeElement)
+ if (frameTreeElement) {
frameTreeElement.frameNavigated(frame);
+ }
}
/**
@@ -190,11 +202,13 @@ Resources.FrameTreeElement = class extends Resources.BaseStorageTreeElement {
* @param {!SDK.Resource} resource
*/
appendResource(resource) {
- if (!this._populated)
+ if (!this._populated) {
return;
+ }
const statusCode = resource['statusCode'];
- if (statusCode >= 301 && statusCode <= 303)
+ if (statusCode >= 301 && statusCode <= 303) {
return;
+ }
const resourceType = resource.resourceType();
const categoryName = resourceType.name();
@@ -224,18 +238,21 @@ Resources.FrameTreeElement = class extends Resources.BaseStorageTreeElement {
* @param {!UI.TreeElement} treeElement
*/
appendChild(treeElement) {
- if (!this._populated)
+ if (!this._populated) {
return;
+ }
this._insertInPresentationOrder(this, treeElement);
}
_insertInPresentationOrder(parentTreeElement, childTreeElement) {
// Insert in the alphabetical order, first frames, then resources. Document resource goes last.
function typeWeight(treeElement) {
- if (treeElement instanceof Resources.StorageCategoryTreeElement)
+ if (treeElement instanceof Resources.StorageCategoryTreeElement) {
return 2;
- if (treeElement instanceof Resources.FrameTreeElement)
+ }
+ if (treeElement instanceof Resources.FrameTreeElement) {
return 1;
+ }
return 3;
}
@@ -244,20 +261,22 @@ Resources.FrameTreeElement = class extends Resources.BaseStorageTreeElement {
const typeWeight2 = typeWeight(treeElement2);
let result;
- if (typeWeight1 > typeWeight2)
+ if (typeWeight1 > typeWeight2) {
result = 1;
- else if (typeWeight1 < typeWeight2)
+ } else if (typeWeight1 < typeWeight2) {
result = -1;
- else
+ } else {
result = treeElement1.titleAsText().localeCompare(treeElement2.titleAsText());
+ }
return result;
}
const childCount = parentTreeElement.childCount();
let i;
for (i = 0; i < childCount; ++i) {
- if (compare(childTreeElement, parentTreeElement.childAt(i)) < 0)
+ if (compare(childTreeElement, parentTreeElement.childAt(i)) < 0) {
break;
+ }
}
parentTreeElement.insertChild(childTreeElement, i);
}
@@ -268,10 +287,12 @@ Resources.FrameTreeElement = class extends Resources.BaseStorageTreeElement {
*/
async onpopulate() {
this._populated = true;
- for (const child of this._frame.childFrames)
+ for (const child of this._frame.childFrames) {
this._section._frameAdded(child);
- for (const resource of this._frame.resources())
+ }
+ for (const resource of this._frame.resources()) {
this.appendResource(resource);
+ }
}
};
@@ -311,12 +332,14 @@ Resources.FrameResourceTreeElement = class extends Resources.BaseStorageTreeElem
* @return {!Promise<!UI.Widget>}
*/
_preparePreview() {
- if (this._previewPromise)
+ if (this._previewPromise) {
return this._previewPromise;
+ }
const viewPromise = SourceFrame.PreviewFactory.createPreview(this._resource, this._resource.mimeType);
this._previewPromise = viewPromise.then(view => {
- if (view)
+ if (view) {
return view;
+ }
return new UI.EmptyWidget(this._resource.url);
});
return this._previewPromise;
@@ -337,7 +360,7 @@ Resources.FrameResourceTreeElement = class extends Resources.BaseStorageTreeElem
* @return {boolean}
*/
ondblclick(event) {
- InspectorFrontendHost.openInNewTab(this._resource.url);
+ Host.InspectorFrontendHost.openInNewTab(this._resource.url);
return false;
}
@@ -374,8 +397,9 @@ Resources.FrameResourceTreeElement = class extends Resources.BaseStorageTreeElem
async revealResource(line, column) {
this.revealAndSelect(true);
const view = await this._panel.scheduleShowView(this._preparePreview());
- if (!(view instanceof SourceFrame.ResourceSourceFrame) || typeof line !== 'number')
+ if (!(view instanceof SourceFrame.ResourceSourceFrame) || typeof line !== 'number') {
return;
+ }
view.revealPosition(line, column, true);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js
index 8b29e4ab097..528ee2a1649 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js
@@ -55,7 +55,7 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
this._deleteSelectedButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._deleteButtonClicked(null));
editorToolbar.appendToolbarItem(this._deleteSelectedButton);
- const entryPathFilterBox = new UI.ToolbarInput(ls`Filter by Path`, 1);
+ const entryPathFilterBox = new UI.ToolbarInput(ls`Filter by Path`, '', 1);
editorToolbar.appendToolbarItem(entryPathFilterBox);
const entryPathFilterThrottler = new Common.Throttler(300);
this._entryPathFilter = '';
@@ -76,8 +76,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
}
_resetDataGrid() {
- if (this._dataGrid)
+ if (this._dataGrid) {
this._dataGrid.asWidget().detach();
+ }
this._dataGrid = this._createDataGrid();
const dataGridWidget = this._dataGrid.asWidget();
this._splitWidget.setSidebarWidget(dataGridWidget);
@@ -106,12 +107,15 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
* @param {?UI.Widget} preview
*/
_showPreview(preview) {
- if (preview && this._preview === preview)
+ if (preview && this._preview === preview) {
return;
- if (this._preview)
+ }
+ if (this._preview) {
this._preview.detach();
- if (!preview)
+ }
+ if (!preview) {
preview = new UI.EmptyWidget(Common.UIString('Select a cache entry above to preview'));
+ }
this._preview = preview;
this._preview.show(this._previewPanel.element);
}
@@ -152,22 +156,24 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
}
_sortingChanged() {
- if (!this._dataGrid)
+ if (!this._dataGrid) {
return;
+ }
const accending = this._dataGrid.isSortOrderAscending();
const columnId = this._dataGrid.sortColumnId();
let comparator;
- if (columnId === 'name')
+ if (columnId === 'name') {
comparator = (a, b) => a._name.localeCompare(b._name);
- else if (columnId === 'contentType')
+ } else if (columnId === 'contentType') {
comparator = (a, b) => a.data.mimeType.localeCompare(b.data.mimeType);
- else if (columnId === 'contentLength')
+ } else if (columnId === 'contentLength') {
comparator = (a, b) => a.data.resourceSize - b.data.resourceSize;
- else if (columnId === 'responseTime')
+ } else if (columnId === 'responseTime') {
comparator = (a, b) => a.data.endTime - b.data.endTime;
- else if (columnId === 'responseType')
+ } else if (columnId === 'responseType') {
comparator = (a, b) => a._responseType.localeCompare(b._responseType);
+ }
const children = this._dataGrid.rootNode().children.slice();
this._dataGrid.rootNode().removeChildren();
@@ -200,8 +206,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
async _deleteButtonClicked(node) {
if (!node) {
node = this._dataGrid && this._dataGrid.selectedNode;
- if (!node)
+ if (!node) {
return;
+ }
}
await this._model.deleteCacheEntry(this._cache, /** @type {string} */ (node.data.url()));
node.remove();
@@ -217,15 +224,17 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
}
_updateSummaryBar() {
- if (!this._summaryBarElement)
+ if (!this._summaryBarElement) {
this._summaryBarElement = this.element.createChild('div', 'cache-storage-summary-bar');
+ }
this._summaryBarElement.removeChildren();
const span = this._summaryBarElement.createChild('span');
- if (this._entryPathFilter)
+ if (this._entryPathFilter) {
span.textContent = ls`Matching entries: ${this._returnCount}`;
- else
+ } else {
span.textContent = ls`Total entries: ${this._returnCount}`;
+ }
}
/**
@@ -245,8 +254,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
/** @type {!Map<string, !DataGrid.DataGridNode>} */
const oldEntries = new Map();
const rootNode = this._dataGrid.rootNode();
- for (const node of rootNode.children)
+ for (const node of rootNode.children) {
oldEntries.set(node.data.url, node);
+ }
rootNode.removeChildren();
let selectedNode = null;
for (let i = 0; i < entries.length; ++i) {
@@ -260,15 +270,17 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
node.data.number = i + this._skipCount;
}
rootNode.appendChild(node);
- if (entry.requestURL === selected)
+ if (entry.requestURL === selected) {
selectedNode = node;
+ }
}
this._pageBackButton.setEnabled(!!skipCount);
this._pageForwardButton.setEnabled(hasMore);
- if (!selectedNode)
+ if (!selectedNode) {
this._showPreview(null);
- else
+ } else {
selectedNode.revealAndSelect();
+ }
this._updatedForTest();
}
@@ -279,8 +291,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
const pageSize = this._pageSize;
let skipCount = this._skipCount;
- if (!force && this._lastPageSize === pageSize && this._lastSkipCount === skipCount)
+ if (!force && this._lastPageSize === pageSize && this._lastSkipCount === skipCount) {
return;
+ }
this._refreshButton.setEnabled(false);
if (this._lastPageSize !== pageSize) {
skipCount = 0;
@@ -309,8 +322,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
*/
_cacheContentUpdated(event) {
const nameAndOrigin = event.data;
- if (this._cache.securityOrigin !== nameAndOrigin.origin || this._cache.cacheName !== nameAndOrigin.cacheName)
+ if (this._cache.securityOrigin !== nameAndOrigin.origin || this._cache.cacheName !== nameAndOrigin.cacheName) {
return;
+ }
this._refreshThrottler.schedule(() => Promise.resolve(this._updateData(true)), true);
}
@@ -325,8 +339,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
}
// It is possible that table selection changes before the preview opens.
- if (request === this._dataGrid.selectedNode.data)
+ if (request === this._dataGrid.selectedNode.data) {
this._showPreview(preview);
+ }
}
/**
@@ -352,8 +367,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
request.resourceSize = (header && header.value) | 0;
let resourceType = Common.ResourceType.fromMimeType(contentType);
- if (!resourceType)
+ if (!resourceType) {
resourceType = Common.ResourceType.fromURL(entry.requestURL) || Common.resourceTypes.Other;
+ }
request.setResourceType(resourceType);
request.setContentDataProvider(this._requestContent.bind(this, request));
return request;
@@ -367,8 +383,9 @@ Resources.ServiceWorkerCacheView = class extends UI.SimpleView {
const isText = request.resourceType().isTextType();
const contentData = {error: null, content: null, encoded: !isText};
const response = await this._cache.requestCachedResponse(request.url(), request.requestHeaders());
- if (response)
+ if (response) {
contentData.content = isText ? window.atob(response.body) : response.body;
+ }
return contentData;
}
@@ -390,10 +407,11 @@ Resources.ServiceWorkerCacheView.DataGridNode = class extends DataGrid.DataGridN
super(request);
this._number = number;
const parsed = new Common.ParsedURL(request.url());
- if (parsed.isValid)
+ if (parsed.isValid) {
this._name = request.url().trimURL(parsed.domain());
- else
+ } else {
this._name = request.url();
+ }
this._request = request;
this._responseType = responseType;
}
@@ -411,12 +429,13 @@ Resources.ServiceWorkerCacheView.DataGridNode = class extends DataGrid.DataGridN
} else if (columnId === 'name') {
value = this._name;
} else if (columnId === 'responseType') {
- if (this._responseType === 'opaqueResponse')
+ if (this._responseType === 'opaqueResponse') {
value = 'opaque';
- else if (this._responseType === 'opaqueRedirect')
+ } else if (this._responseType === 'opaqueRedirect') {
value = 'opaqueredirect';
- else
+ } else {
value = this._responseType;
+ }
} else if (columnId === 'contentType') {
value = this._request.mimeType;
} else if (columnId === 'contentLength') {
@@ -458,15 +477,18 @@ Resources.ServiceWorkerCacheView.RequestView = class extends UI.VBox {
* @param {string=} tabId
*/
_selectTab(tabId) {
- if (!tabId)
+ if (!tabId) {
tabId = this._resourceViewTabSetting.get();
- if (!this._tabbedPane.selectTab(tabId))
+ }
+ if (!this._tabbedPane.selectTab(tabId)) {
this._tabbedPane.selectTab('headers');
+ }
}
_tabSelected(event) {
- if (!event.data.isUserGesture)
+ if (!event.data.isUserGesture) {
return;
+ }
this._resourceViewTabSetting.set(event.data.tabId);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
index 036398d13c5..7a9e2cc3030 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
@@ -37,13 +37,14 @@ Resources.ServiceWorkersView = class extends UI.VBox {
this._otherSWFilter.setAttribute('aria-checked', false);
const filterLabel = this._otherSWFilter.createChild('label', 'service-worker-filter-label');
filterLabel.textContent = Common.UIString('Service workers from other origins');
- onInvokeElement(this._otherSWFilter, event => {
- if (event.target === this._otherSWFilter || event.target === filterLabel)
+ self.onInvokeElement(this._otherSWFilter, event => {
+ if (event.target === this._otherSWFilter || event.target === filterLabel) {
this._toggleFilter();
+ }
});
const toolbar = new UI.Toolbar('service-worker-filter-toolbar', this._otherSWFilter);
- this._filter = new UI.ToolbarInput(ls`Filter service worker`, 1);
+ this._filter = new UI.ToolbarInput(ls`Filter service worker`, '', 1);
this._filter.addEventListener(UI.ToolbarInput.Event.TextChanged, () => this._filterChanged());
toolbar.appendToolbarItem(this._filter);
@@ -77,13 +78,15 @@ Resources.ServiceWorkersView = class extends UI.VBox {
* @param {!SDK.ServiceWorkerManager} serviceWorkerManager
*/
modelAdded(serviceWorkerManager) {
- if (this._manager)
+ if (this._manager) {
return;
+ }
this._manager = serviceWorkerManager;
this._securityOriginManager = serviceWorkerManager.target().model(SDK.SecurityOriginManager);
- for (const registration of this._manager.registrations().values())
+ for (const registration of this._manager.registrations().values()) {
this._updateRegistration(registration);
+ }
this._eventListeners.set(serviceWorkerManager, [
this._manager.addEventListener(
@@ -102,8 +105,9 @@ Resources.ServiceWorkersView = class extends UI.VBox {
* @param {!SDK.ServiceWorkerManager} serviceWorkerManager
*/
modelRemoved(serviceWorkerManager) {
- if (!this._manager || this._manager !== serviceWorkerManager)
+ if (!this._manager || this._manager !== serviceWorkerManager) {
return;
+ }
Common.EventTarget.removeEventListeners(this._eventListeners.get(serviceWorkerManager));
this._eventListeners.delete(serviceWorkerManager);
@@ -126,14 +130,15 @@ Resources.ServiceWorkersView = class extends UI.VBox {
const waiting = versions.get(SDK.ServiceWorkerVersion.Modes.Waiting);
const redundant = versions.get(SDK.ServiceWorkerVersion.Modes.Redundant);
- if (active)
+ if (active) {
timestamp = active.scriptResponseTime;
- else if (waiting)
+ } else if (waiting) {
timestamp = waiting.scriptResponseTime;
- else if (installing)
+ } else if (installing) {
timestamp = installing.scriptResponseTime;
- else if (redundant)
+ } else if (redundant) {
timestamp = redundant.scriptResponseTime;
+ }
return timestamp;
}
@@ -146,8 +151,9 @@ Resources.ServiceWorkersView = class extends UI.VBox {
const expectedView = this._getReportViewForOrigin(section._registration.securityOrigin);
hasOthers |= expectedView === this._otherWorkersView;
hasThis |= expectedView === this._currentWorkersView;
- if (section._section.parentWidget() !== expectedView)
+ if (section._section.parentWidget() !== expectedView) {
movedSections.push(section);
+ }
}
for (const section of movedSections) {
@@ -170,12 +176,13 @@ Resources.ServiceWorkersView = class extends UI.VBox {
});
for (const section of this._sections.values()) {
if (section._section.parentWidget() === this._currentWorkersView ||
- this._isRegistrationVisible(section._registration))
+ this._isRegistrationVisible(section._registration)) {
section._section.showWidget();
- else
+ } else {
section._section.hideWidget();
+ }
}
- this.contentElement.classList.toggle('service-worker-has-current', hasThis);
+ this.contentElement.classList.toggle('service-worker-has-current', !!hasThis);
this._otherWorkers.classList.toggle('hidden', !hasOthers);
this._updateListVisibility();
}
@@ -193,21 +200,24 @@ Resources.ServiceWorkersView = class extends UI.VBox {
let hasNonDeletedRegistrations = false;
const securityOrigins = new Set(this._securityOriginManager.securityOrigins());
for (const registration of this._manager.registrations().values()) {
- if (!securityOrigins.has(registration.securityOrigin) && !this._isRegistrationVisible(registration))
+ if (!securityOrigins.has(registration.securityOrigin) && !this._isRegistrationVisible(registration)) {
continue;
+ }
if (!registration.canBeRemoved()) {
hasNonDeletedRegistrations = true;
break;
}
}
- if (!hasNonDeletedRegistrations)
+ if (!hasNonDeletedRegistrations) {
return;
+ }
for (const registration of this._manager.registrations().values()) {
const visible = securityOrigins.has(registration.securityOrigin) || this._isRegistrationVisible(registration);
- if (!visible && registration.canBeRemoved())
+ if (!visible && registration.canBeRemoved()) {
this._removeRegistrationFromList(registration);
+ }
}
}
@@ -217,10 +227,11 @@ Resources.ServiceWorkersView = class extends UI.VBox {
*/
_getReportViewForOrigin(origin) {
if (this._securityOriginManager.securityOrigins().includes(origin) ||
- this._securityOriginManager.unreachableMainSecurityOrigin() === origin)
+ this._securityOriginManager.unreachableMainSecurityOrigin() === origin) {
return this._currentWorkersView;
- else
+ } else {
return this._otherWorkersView;
+ }
}
/**
@@ -232,13 +243,15 @@ Resources.ServiceWorkersView = class extends UI.VBox {
if (!section) {
const title = registration.scopeURL;
const uiSection = this._getReportViewForOrigin(registration.securityOrigin).appendSection(title);
+ uiSection.setUiGroupTitle(ls`Service worker for ${title}`);
uiSection[this._registrationSymbol] = registration;
section = new Resources.ServiceWorkersView.Section(
/** @type {!SDK.ServiceWorkerManager} */ (this._manager), uiSection, registration);
this._sections.set(registration, section);
}
- if (skipUpdate)
+ if (skipUpdate) {
return;
+ }
this._updateSectionVisibility();
section._scheduleUpdate();
}
@@ -256,8 +269,9 @@ Resources.ServiceWorkersView = class extends UI.VBox {
*/
_removeRegistrationFromList(registration) {
const section = this._sections.get(registration);
- if (section)
+ if (section) {
section._section.detach();
+ }
this._sections.delete(registration);
this._updateSectionVisibility();
}
@@ -268,8 +282,9 @@ Resources.ServiceWorkersView = class extends UI.VBox {
*/
_isRegistrationVisible(registration) {
const filterString = this._filter.value();
- if (!filterString || !registration.scopeURL)
+ if (!filterString || !registration.scopeURL) {
return true;
+ }
const regex = String.filterRegex(filterString);
return registration.scopeURL.match(regex);
@@ -283,10 +298,11 @@ Resources.ServiceWorkersView = class extends UI.VBox {
_updateCollapsedStyle() {
const expanded = this._otherSWFilter.getAttribute('aria-checked') === 'true';
this._otherWorkers.classList.toggle('service-worker-filter-collapsed', !expanded);
- if (expanded)
+ if (expanded) {
this._otherWorkersView.showWidget();
- else
+ } else {
this._otherWorkersView.hideWidget();
+ }
this._otherWorkersView.setHeaderVisible(false);
}
@@ -338,7 +354,7 @@ Resources.ServiceWorkersView.Section = class {
this._push.bind(this));
this._createSyncNotificationField(
Common.UIString('Sync'), this._syncTagNameSetting.get(), Common.UIString('Sync tag'), this._sync.bind(this));
- if (Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync')) {
+ if (Root.Runtime.experiments.isEnabled('backgroundServicesPeriodicBackgroundSync')) {
this._createSyncNotificationField(
ls`Periodic Sync`, this._periodicSyncTagNameSetting.get(), ls`Periodic Sync tag`,
tag => this._periodicSync(tag));
@@ -388,8 +404,9 @@ Resources.ServiceWorkersView.Section = class {
*/
_targetForVersionId(versionId) {
const version = this._manager.findVersion(versionId);
- if (!version || !version.targetId)
+ if (!version || !version.targetId) {
return null;
+ }
return SDK.targetManager.targetById(version.targetId);
}
@@ -437,7 +454,7 @@ Resources.ServiceWorkersView.Section = class {
errorsLabel.classList.add('link');
errorsLabel.tabIndex = 0;
UI.ARIAUtils.setAccessibleName(errorsLabel, ls`${this._registration.errors.length} registration errors`);
- onInvokeElement(errorsLabel, () => Common.console.show());
+ self.onInvokeElement(errorsLabel, () => Common.console.show());
name.appendChild(errorsLabel);
}
this._sourceField.createChild('div', 'report-field-value-subtitle').textContent =
@@ -449,8 +466,9 @@ Resources.ServiceWorkersView.Section = class {
*/
_update() {
const fingerprint = this._registration.fingerprint();
- if (fingerprint === this._fingerprint)
+ if (fingerprint === this._fingerprint) {
return Promise.resolve();
+ }
this._fingerprint = fingerprint;
this._toolbar.setEnabled(!this._registration.isDeleted);
@@ -471,14 +489,15 @@ Resources.ServiceWorkersView.Section = class {
if (active) {
this._updateSourceField(active);
+ const localizedRunningStatus = SDK.ServiceWorkerVersion.RunningStatus[active.runningStatus];
const activeEntry = this._addVersion(
- versionsStack, 'service-worker-active-circle',
- Common.UIString('#%s activated and is %s', active.id, active.runningStatus));
+ versionsStack, 'service-worker-active-circle', ls`#${active.id} activated and is ${localizedRunningStatus}`);
if (active.isRunning() || active.isStarting()) {
this._createLink(activeEntry, Common.UIString('stop'), this._stopButtonClicked.bind(this, active.id));
- if (!this._targetForVersionId(active.id))
+ if (!this._targetForVersionId(active.id)) {
this._createLink(activeEntry, Common.UIString('inspect'), this._inspectButtonClicked.bind(this, active.id));
+ }
} else if (active.isStartable()) {
this._createLink(activeEntry, Common.UIString('start'), this._startButtonClicked.bind(this));
}
@@ -496,8 +515,9 @@ Resources.ServiceWorkersView.Section = class {
this._createLink(waitingEntry, Common.UIString('skipWaiting'), this._skipButtonClicked.bind(this));
waitingEntry.createChild('div', 'service-worker-subtitle').textContent =
Common.UIString('Received %s', new Date(waiting.scriptResponseTime * 1000).toLocaleString());
- if (!this._targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting()))
+ if (!this._targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting())) {
this._createLink(waitingEntry, Common.UIString('inspect'), this._inspectButtonClicked.bind(this, waiting.id));
+ }
}
if (installing) {
const installingEntry = this._addVersion(
@@ -572,8 +592,9 @@ Resources.ServiceWorkersView.Section = class {
* @param {?Protocol.Target.TargetInfo} targetInfo
*/
_onClientInfo(element, targetInfo) {
- if (!targetInfo)
+ if (!targetInfo) {
return;
+ }
this._clientInfoCache.set(targetInfo.targetId, targetInfo);
this._updateClientInfo(element, targetInfo);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js
index 9137521725e..1e5fb3e4324 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js
@@ -16,7 +16,7 @@ Resources.StorageItemsView = class extends UI.VBox {
this._mainToolbar = new UI.Toolbar('top-resources-toolbar', this.element);
- this._filterItem = new UI.ToolbarInput(Common.UIString('Filter'), 0.4);
+ this._filterItem = new UI.ToolbarInput(Common.UIString('Filter'), '', 0.4);
this._filterItem.addEventListener(UI.ToolbarInput.Event.TextChanged, this._filterChanged, this);
const toolbarSeparator = new UI.ToolbarSeparator();
@@ -26,9 +26,9 @@ Resources.StorageItemsView = class extends UI.VBox {
const toolbarItems =
[this._refreshButton, this._filterItem, toolbarSeparator, this._deleteAllButton, this._deleteSelectedButton];
- for (const item of toolbarItems)
+ for (const item of toolbarItems) {
this._mainToolbar.appendToolbarItem(item);
-
+ }
}
/**
@@ -59,8 +59,9 @@ Resources.StorageItemsView = class extends UI.VBox {
* @protected
*/
filter(items, keyFunction) {
- if (!this._filterRegex)
+ if (!this._filterRegex) {
return items;
+ }
return items.filter(item => this._filterRegex.test(keyFunction(item)));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/cookieItemsView.css b/chromium/third_party/blink/renderer/devtools/front_end/resources/cookieItemsView.css
new file mode 100644
index 00000000000..b2b99302f65
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/cookieItemsView.css
@@ -0,0 +1,12 @@
+/*
+ * 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.
+ */
+
+.cookie-value {
+ padding: 2px 6px;
+ overflow: auto;
+ user-select: text;
+ min-height: 100%;
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/module.json b/chromium/third_party/blink/renderer/devtools/front_end/resources/module.json
index 9dbc5449a09..182c1a46780 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/module.json
@@ -100,6 +100,7 @@
"resourcesPanel.css",
"resourcesSidebar.css",
"serviceWorkerCacheViews.css",
- "serviceWorkersView.css"
+ "serviceWorkersView.css",
+ "cookieItemsView.css"
]
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
index 99eaeb8b546..c0ba907080c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/resources_strings.grdp
@@ -52,8 +52,8 @@ table is empty.
<message name="IDS_DEVTOOLS_29104d3ede0231043a4b92a90b9c2873" desc="Title of needs refresh in indexed dbviews of the application panel">
Some entries may have been modified
</message>
- <message name="IDS_DEVTOOLS_2b81bb9b3deebcbfa05edad7a845005a" desc="Text in Application Panel Sidebar of the Application panel">
- Frames
+ <message name="IDS_DEVTOOLS_2b31634e3cfef1bfdd7d0d2cdfdc3f9d" desc="Text in Context menu for collapsing objects in IndexedDB tables">
+ Collapse
</message>
<message name="IDS_DEVTOOLS_2bf0a735c3ff964861a2b55319edd355" desc="Text in Clear Storage View of the Application panel">
Unregister service workers
@@ -73,6 +73,9 @@ table is empty.
<message name="IDS_DEVTOOLS_368d9ac76af05f714092bc808a426bfc" desc="Text in App Manifest View of the Application panel">
Background color
</message>
+ <message name="IDS_DEVTOOLS_36e256f915286539621b57d8c80f0105" desc="Text in Context menu for expanding objects in IndexedDB tables">
+ Expand Recursively
+ </message>
<message name="IDS_DEVTOOLS_37acadd70183e7ed00222ff38248a6ff" desc="Quota row text content in Clear Storage View of the Application panel">
<ph name="NUMBER_BYTESTOSTRING_RESPONSE_USAGE_">$1s<ex>30 MB</ex></ph> used out of <ph name="NUMBER_BYTESTOSTRING_RESPONSE_QUOTA_">$2s<ex>100 MB</ex></ph> storage quota. '''
</message>
@@ -88,9 +91,6 @@ table is empty.
<message name="IDS_DEVTOOLS_3eab5d12656f2f4462f6594019e77355" desc="Text in Database Table View of the Application panel">
Visible columns
</message>
- <message name="IDS_DEVTOOLS_3edf8ca26a1ec14dd6e91dd277ae1de6" desc="Text in Background Service View of the Application panel">
- Origin
- </message>
<message name="IDS_DEVTOOLS_458efe6e41ed41835b8d84b28db3f394" desc="Filter label text content in Service Workers View of the Application panel">
Service workers from other origins
</message>
@@ -106,12 +106,6 @@ table is empty.
<message name="IDS_DEVTOOLS_536cf547cb6ecfe32be6ed3ffdabf893" desc="Text of button in Clear Storage View of the Application panel">
Clear site data
</message>
- <message name="IDS_DEVTOOLS_53cd8180752335dce4f9b9ed493ef58d" desc="Image alt in App Manifest View of the Application panel">
- Image from <ph name="URL">$1s<ex>example.com</ex></ph>
- </message>
- <message name="IDS_DEVTOOLS_54f664c70c22054ea0d8d26fc3997ce7" desc="Connectivity icon text content in Application Cache Items View of the Application panel">
- Online
- </message>
<message name="IDS_DEVTOOLS_55bce575c41275ddaf5fbd1beb7d6018" desc="Text in Service Workers View of the Application panel">
#<ph name="INSTALLING_ID">$1s<ex>2</ex></ph> trying to install
</message>
@@ -148,9 +142,6 @@ table is empty.
<message name="IDS_DEVTOOLS_76c18f2b1e4155961e10434e3d83317f" desc="Text in Indexed DBViews of the Application panel">
Key generator value: <ph name="STRING_METADATA_KEYGENERATORVALUE_">$1s<ex>2</ex></ph>
</message>
- <message name="IDS_DEVTOOLS_76c3e002d3c052bd6a909366a8dc3845" desc="Text in Application Panel Sidebar of the Application panel">
- Manifest
- </message>
<message name="IDS_DEVTOOLS_795a813f20a4d4b04f85ddb86287fce4" desc="Quota row title in Clear Storage View of the Application panel">
Storage quota is limited in Incognito mode
</message>
@@ -218,6 +209,9 @@ read the &quot;<ph name="THIS_TABLENAME">$1s<ex>database</ex></ph>&quot; table.
<message name="IDS_DEVTOOLS_9999106349673567ecaf1c32c07301a5" desc="Text in Service Workers View of the Application panel">
#<ph name="WAITING_ID">$1s<ex>2</ex></ph> waiting to activate
</message>
+ <message name="IDS_DEVTOOLS_99ccbbe2741019f0bbc87f4eb83dbc1d" desc="Screen reader title for a section of the Service Workers view of the Application panel">
+ Service worker for <ph name="TITLE"><ex>https://example.com</ex>$1s</ph>
+ </message>
<message name="IDS_DEVTOOLS_9b2a7456cec10d8b5ab8ce656598320b" desc="Text in Indexed DBViews of the Application panel">
Key path: '''
</message>
@@ -239,9 +233,6 @@ read the &quot;<ph name="THIS_TABLENAME">$1s<ex>database</ex></ph>&quot; table.
<message name="IDS_DEVTOOLS_a274f4d4670213a9045ce258c6c56b80" desc="Text in Background Service View of the Application panel">
Notifications
</message>
- <message name="IDS_DEVTOOLS_a4ecfc70574394990cf17bd83df499f7" desc="Text in Background Service View of the Application panel">
- Event
- </message>
<message name="IDS_DEVTOOLS_a7d5ee58baead2f3bc229d3d9c047875" desc="Text in Service Workers View of the Application panel">
Unregister service worker
</message>
@@ -249,7 +240,7 @@ read the &quot;<ph name="THIS_TABLENAME">$1s<ex>database</ex></ph>&quot; table.
Cache Storage
</message>
<message name="IDS_DEVTOOLS_a9cd2046f50376846feaa11c68e56e2f" desc="Inform users that DevTools are recording/waiting for events in the Periodic Background Sync tool of the Application panel">
- DevTools will record all <ph name="FEATURENAME">$1s<ex>Background Fetch</ex></ph> activity for up to 3 days, even when closed.
+ <ph name="LOCKED_1">DevTools</ph> will record all <ph name="FEATURENAME">$1s<ex>Background Fetch</ex></ph> activity for up to 3 days, even when closed.
</message>
<message name="IDS_DEVTOOLS_ab0cf104f39708eabd07b8cb67e149ba" desc="Text in Application Panel Sidebar of the Application panel">
Cache
@@ -282,14 +273,11 @@ read the &quot;<ph name="THIS_TABLENAME">$1s<ex>database</ex></ph>&quot; table.
Display
</message>
<message name="IDS_DEVTOOLS_ba8d2e1eca2bf52ab3cd0202d4d04c07" desc="Text in Service Workers View of the Application panel">
- Test push message from DevTools.
+ Test push message from <ph name="LOCKED_1">DevTools</ph>.
</message>
<message name="IDS_DEVTOOLS_bb8839cf9d324a22591ff426c28c5345" desc="Tooltip text that appears when hovering over the largeicon play button in the Indexed DBViews of the Application panel">
Show next page
</message>
- <message name="IDS_DEVTOOLS_be8545ae7ab0276e15898aae7acfbd7a" desc="Text in Application Cache Items View of the Application panel">
- Resource
- </message>
<message name="IDS_DEVTOOLS_bebc9b50966d8d2bd1913a3c25b707d4" desc="Text in Indexed DBViews of the Application panel">
Data may be stale
</message>
@@ -413,10 +401,10 @@ read the &quot;<ph name="THIS_TABLENAME">$1s<ex>database</ex></ph>&quot; table.
<message name="IDS_DEVTOOLS_ef399b2d446bb37b7c32ad2cc1b6045b" desc="Text in Service Workers View of the Application panel">
stop
</message>
- <message name="IDS_DEVTOOLS_f31bbdd1b3e85bccd652680e16935819" desc="Text in Service Workers View of the Application panel">
- Source
+ <message name="IDS_DEVTOOLS_f75623bb4626a57e8a7a3c0e1c092463" desc="Text in Cookie Items View of the Application panel">
+ Select a cookie to preview its value
</message>
<message name="IDS_DEVTOOLS_fb1508747fe448fd8b006e923ba1c3ef" desc="Text in Background Service View of the Application panel">
Payment Handler
</message>
-</grit-part> \ No newline at end of file
+</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/root.js b/chromium/third_party/blink/renderer/devtools/front_end/root.js
new file mode 100644
index 00000000000..d0e4750fb5e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/root.js
@@ -0,0 +1,21 @@
+// 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 './Runtime.js';
+import './platform/utilities.js';
+import './dom_extension/DOMExtension.js';
+import './common/common.js';
+import './host/host.js';
+import './protocol/protocol.js';
+import './sdk/sdk.js';
+import './ui/ui.js';
+
+import './services/services.js';
+import './workspace/workspace.js';
+import './bindings/bindings.js';
+import './components/components.js';
+import './persistence/persistence.js';
+import './browser_sdk/browser_sdk.js';
+import './extensions/extensions.js';
+import './console_counters/console_counters.js'; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/screencast/InputModel.js b/chromium/third_party/blink/renderer/devtools/front_end/screencast/InputModel.js
index e4d674ce917..4b6b28d03c9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/screencast/InputModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/screencast/InputModel.js
@@ -63,13 +63,16 @@ Screencast.InputModel = class extends SDK.SDKModel {
'mousemove': 'mouseMoved',
'mousewheel': 'mouseWheel'
};
- if (!(event.type in types) || !(event.which in buttons))
+ if (!(event.type in types) || !(event.which in buttons)) {
return;
- if (event.type !== 'mousewheel' && buttons[event.which] === 'none')
+ }
+ if (event.type !== 'mousewheel' && buttons[event.which] === 'none') {
return;
+ }
- if (event.type === 'mousedown' || this._activeTouchOffsetTop === null)
+ if (event.type === 'mousedown' || this._activeTouchOffsetTop === null) {
this._activeTouchOffsetTop = offsetTop;
+ }
const x = Math.round(event.offsetX / zoom);
let y = Math.round(event.offsetY / zoom);
@@ -88,8 +91,9 @@ Screencast.InputModel = class extends SDK.SDKModel {
} else {
this._activeTouchParams = params;
}
- if (event.type === 'mouseup')
+ if (event.type === 'mouseup') {
this._activeTouchOffsetTop = null;
+ }
this._inputAgent.invoke_emulateTouchFromMouseEvent(params);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastApp.js b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastApp.js
index c65f7febac6..725641b6f97 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastApp.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastApp.js
@@ -20,8 +20,9 @@ Screencast.ScreencastApp = class {
* @return {!Screencast.ScreencastApp}
*/
static _instance() {
- if (!Screencast.ScreencastApp._appInstance)
+ if (!Screencast.ScreencastApp._appInstance) {
Screencast.ScreencastApp._appInstance = new Screencast.ScreencastApp();
+ }
return Screencast.ScreencastApp._appInstance;
}
@@ -48,8 +49,9 @@ Screencast.ScreencastApp = class {
* @param {!SDK.ScreenCaptureModel} screenCaptureModel
*/
modelAdded(screenCaptureModel) {
- if (this._screenCaptureModel)
+ if (this._screenCaptureModel) {
return;
+ }
this._screenCaptureModel = screenCaptureModel;
this._toggleButton.setEnabled(true);
this._screencastView = new Screencast.ScreencastView(screenCaptureModel);
@@ -63,8 +65,9 @@ Screencast.ScreencastApp = class {
* @param {!SDK.ScreenCaptureModel} screenCaptureModel
*/
modelRemoved(screenCaptureModel) {
- if (this._screenCaptureModel !== screenCaptureModel)
+ if (this._screenCaptureModel !== screenCaptureModel) {
return;
+ }
delete this._screenCaptureModel;
this._toggleButton.setEnabled(false);
this._screencastView.detach();
@@ -79,14 +82,16 @@ Screencast.ScreencastApp = class {
}
_onScreencastEnabledChanged() {
- if (!this._rootSplitWidget)
+ if (!this._rootSplitWidget) {
return;
+ }
const enabled = this._enabledSetting.get() && this._screencastView;
this._toggleButton.setToggled(enabled);
- if (enabled)
+ if (enabled) {
this._rootSplitWidget.showBoth();
- else
+ } else {
this._rootSplitWidget.hideMain();
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
index 6378f85f867..d7fd5effe0d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
@@ -111,10 +111,12 @@ Screencast.ScreencastView = class extends UI.VBox {
}
_startCasting() {
- if (SDK.targetManager.allTargetsSuspended())
+ if (SDK.targetManager.allTargetsSuspended()) {
return;
- if (this._isCasting)
+ }
+ if (this._isCasting) {
return;
+ }
this._isCasting = true;
const maxImageDimension = 2048;
@@ -130,21 +132,26 @@ Screencast.ScreencastView = class extends UI.VBox {
'jpeg', 80, Math.floor(Math.min(maxImageDimension, dimensions.width)),
Math.floor(Math.min(maxImageDimension, dimensions.height)), undefined, this._screencastFrame.bind(this),
this._screencastVisibilityChanged.bind(this));
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.overrideEmulateTouch(true);
- if (this._overlayModel)
+ }
+ if (this._overlayModel) {
this._overlayModel.setHighlighter(this);
+ }
}
_stopCasting() {
- if (!this._isCasting)
+ if (!this._isCasting) {
return;
+ }
this._isCasting = false;
this._screenCaptureModel.stopScreencast();
- for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel))
+ for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) {
emulationModel.overrideEmulateTouch(false);
- if (this._overlayModel)
+ }
+ if (this._overlayModel) {
this._overlayModel.setHighlighter(null);
+ }
}
/**
@@ -166,8 +173,9 @@ Screencast.ScreencastView = class extends UI.VBox {
dimensionsCSS.height / (this._imageElement.naturalWidth * deviceSizeRatio));
this._viewportElement.classList.remove('hidden');
const bordersSize = Screencast.ScreencastView._bordersSize;
- if (this._imageZoom < 1.01 / window.devicePixelRatio)
+ if (this._imageZoom < 1.01 / window.devicePixelRatio) {
this._imageZoom = 1 / window.devicePixelRatio;
+ }
this._screenZoom = this._imageElement.naturalWidth * this._imageZoom / metadata.deviceWidth;
this._viewportElement.style.width = metadata.deviceWidth * this._screenZoom + bordersSize + 'px';
this._viewportElement.style.height = metadata.deviceHeight * this._screenZoom + bordersSize + 'px';
@@ -193,10 +201,11 @@ Screencast.ScreencastView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_onSuspendStateChange(event) {
- if (SDK.targetManager.allTargetsSuspended())
+ if (SDK.targetManager.allTargetsSuspended()) {
this._stopCasting();
- else
+ } else {
this._startCasting();
+ }
this._updateGlasspane();
}
@@ -221,15 +230,18 @@ Screencast.ScreencastView = class extends UI.VBox {
return;
}
- if (!this._pageScaleFactor || !this._domModel)
+ if (!this._pageScaleFactor || !this._domModel) {
return;
+ }
if (!this._inspectModeConfig || event.type === 'mousewheel') {
- if (this._inputModel)
+ if (this._inputModel) {
this._inputModel.emitTouchFromMouseEvent(event, this._screenOffsetTop, this._screenZoom);
+ }
event.preventDefault();
- if (event.type === 'mousedown')
+ if (event.type === 'mousedown') {
this._canvasElement.focus();
+ }
return;
}
@@ -240,8 +252,9 @@ Screencast.ScreencastView = class extends UI.VBox {
Math.floor(position.y / this._pageScaleFactor + this._scrollOffsetY),
Common.moduleSetting('showUAShadowDOM').get());
- if (!node)
+ if (!node) {
return;
+ }
if (event.type === 'mousemove') {
this.highlightInOverlay({node}, this._inspectModeConfig);
this._domModel.overlayModel().nodeHighlightRequested(node.id);
@@ -266,8 +279,9 @@ Screencast.ScreencastView = class extends UI.VBox {
return;
}
- if (this._inputModel)
+ if (this._inputModel) {
this._inputModel.emitKeyEvent(event);
+ }
event.consume();
this._canvasElement.focus();
}
@@ -283,8 +297,9 @@ Screencast.ScreencastView = class extends UI.VBox {
* @param {!Event} event
*/
_handleBlurEvent(event) {
- if (this._inputModel)
+ if (this._inputModel) {
this._inputModel.cancelTouch();
+ }
}
/**
@@ -327,12 +342,14 @@ Screencast.ScreencastView = class extends UI.VBox {
async _highlightInOverlay(data, config) {
const {node: n, deferredNode, object} = data;
let node = n;
- if (!node && deferredNode)
+ if (!node && deferredNode) {
node = await deferredNode.resolvePromise();
+ }
if (!node && object) {
const domModel = object.runtimeModel().target().model(SDK.DOMModel);
- if (domModel)
+ if (domModel) {
node = await domModel.pushObjectAsNodeToFrontend(object);
+ }
}
this._highlightNode = node;
@@ -406,19 +423,25 @@ Screencast.ScreencastView = class extends UI.VBox {
this._context.save();
const transparentColor = 'rgba(0, 0, 0, 0)';
const quads = [];
- if (model.content && config.contentColor !== transparentColor)
+ if (model.content && config.contentColor !== transparentColor) {
quads.push({quad: model.content, color: config.contentColor});
- if (model.padding && config.paddingColor !== transparentColor)
+ }
+ if (model.padding && config.paddingColor !== transparentColor) {
quads.push({quad: model.padding, color: config.paddingColor});
- if (model.border && config.borderColor !== transparentColor)
+ }
+ if (model.border && config.borderColor !== transparentColor) {
quads.push({quad: model.border, color: config.borderColor});
- if (model.margin && config.marginColor !== transparentColor)
+ }
+ if (model.margin && config.marginColor !== transparentColor) {
quads.push({quad: model.margin, color: config.marginColor});
+ }
- for (let i = quads.length - 1; i > 0; --i)
+ for (let i = quads.length - 1; i > 0; --i) {
this._drawOutlinedQuadWithClip(quads[i].quad, quads[i - 1].quad, quads[i].color);
- if (quads.length > 0)
+ }
+ if (quads.length > 0) {
this._drawOutlinedQuad(quads[0].quad, quads[0].color);
+ }
this._context.restore();
this._drawElementTitle();
@@ -437,8 +460,9 @@ Screencast.ScreencastView = class extends UI.VBox {
* @return {string}
*/
_cssColor(color) {
- if (!color)
+ if (!color) {
return 'transparent';
+ }
return Common.Color.fromRGBA([color.r, color.g, color.b, color.a]).asString(Common.Color.Format.RGBA) || '';
}
@@ -486,8 +510,9 @@ Screencast.ScreencastView = class extends UI.VBox {
}
_drawElementTitle() {
- if (!this._node)
+ if (!this._node) {
return;
+ }
const canvasWidth = this._canvasElement.getBoundingClientRect().width;
const canvasHeight = this._canvasElement.getBoundingClientRect().height;
@@ -497,8 +522,9 @@ Screencast.ScreencastView = class extends UI.VBox {
this._nodeIdElement.textContent = this._node.getAttribute('id') ? '#' + this._node.getAttribute('id') : '';
this._nodeIdElement.textContent = this._node.getAttribute('id') ? '#' + this._node.getAttribute('id') : '';
let className = this._node.getAttribute('class');
- if (className && className.length > 50)
+ if (className && className.length > 50) {
className = className.substring(0, 50) + '\u2026';
+ }
this._classNameElement.textContent = className || '';
this._nodeWidthElement.textContent = this._model.width;
this._nodeHeightElement.textContent = this._model.height;
@@ -515,8 +541,9 @@ Screencast.ScreencastView = class extends UI.VBox {
let renderArrowDown = false;
let boxX = Math.max(2, this._model.margin[0]);
- if (boxX + titleWidth > canvasWidth)
+ if (boxX + titleWidth > canvasWidth) {
boxX = canvasWidth - titleWidth - 2;
+ }
let boxY;
if (anchorTop > canvasHeight) {
@@ -643,8 +670,9 @@ Screencast.ScreencastView = class extends UI.VBox {
*/
_navigateToHistoryEntry(offset) {
const newIndex = this._historyIndex + offset;
- if (newIndex < 0 || newIndex >= this._historyEntries.length)
+ if (newIndex < 0 || newIndex >= this._historyEntries.length) {
return;
+ }
this._resourceTreeModel.navigateToHistoryEntry(this._historyEntries[newIndex]);
this._requestNavigationHistory();
}
@@ -657,21 +685,25 @@ Screencast.ScreencastView = class extends UI.VBox {
* @param {!Event} event
*/
_navigationUrlKeyUp(event) {
- if (event.key !== 'Enter')
+ if (event.key !== 'Enter') {
return;
+ }
let url = this._navigationUrl.value;
- if (!url)
+ if (!url) {
return;
- if (!url.match(Screencast.ScreencastView._SchemeRegex))
+ }
+ if (!url.match(Screencast.ScreencastView._SchemeRegex)) {
url = 'http://' + url;
+ }
this._resourceTreeModel.navigate(url);
this._canvasElement.focus();
}
async _requestNavigationHistory() {
const history = await this._resourceTreeModel.navigationHistory();
- if (!history)
+ if (!history) {
return;
+ }
this._historyIndex = history.currentIndex;
this._historyEntries = history.entries;
@@ -681,9 +713,10 @@ Screencast.ScreencastView = class extends UI.VBox {
let url = this._historyEntries[this._historyIndex].url;
const match = url.match(Screencast.ScreencastView._HttpRegex);
- if (match)
+ if (match) {
url = match[1];
- InspectorFrontendHost.inspectedURLChanged(url);
+ }
+ Host.InspectorFrontendHost.inspectedURLChanged(url);
this._navigationUrl.value = url;
}
@@ -736,8 +769,9 @@ Screencast.ScreencastView.ProgressTracker = class {
delete this._requestIds;
this._updateProgress(1); // Display 100% progress on load, hide it in 0.5s.
setTimeout(function() {
- if (!this._navigationProgressVisible())
+ if (!this._navigationProgressVisible()) {
this._displayProgress(0);
+ }
}.bind(this), 500);
}
@@ -746,22 +780,26 @@ Screencast.ScreencastView.ProgressTracker = class {
}
_onRequestStarted(event) {
- if (!this._navigationProgressVisible())
+ if (!this._navigationProgressVisible()) {
return;
+ }
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
// Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
- if (request.type === Common.resourceTypes.WebSocket)
+ if (request.type === Common.resourceTypes.WebSocket) {
return;
+ }
this._requestIds[request.requestId()] = request;
++this._startedRequests;
}
_onRequestFinished(event) {
- if (!this._navigationProgressVisible())
+ if (!this._navigationProgressVisible()) {
return;
+ }
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
- if (!(request.requestId() in this._requestIds))
+ if (!(request.requestId() in this._requestIds)) {
return;
+ }
++this._finishedRequests;
setTimeout(function() {
this._updateProgress(
@@ -770,10 +808,12 @@ Screencast.ScreencastView.ProgressTracker = class {
}
_updateProgress(progress) {
- if (!this._navigationProgressVisible())
+ if (!this._navigationProgressVisible()) {
return;
- if (this._maxDisplayedProgress >= progress)
+ }
+ if (this._maxDisplayedProgress >= progress) {
return;
+ }
this._maxDisplayedProgress = progress;
this._displayProgress(progress);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
index 98d78b852ed..e5090985d16 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.CPUProfileNode = class extends SDK.ProfileNode {
+export class CPUProfileNode extends SDK.ProfileNode {
/**
* @param {!Protocol.Profiler.ProfileNode} node
* @param {number} sampleTime
@@ -25,12 +25,12 @@ SDK.CPUProfileNode = class extends SDK.ProfileNode {
// Compatibility: legacy backends could provide "no reason" for optimized functions.
this.deoptReason = node.deoptReason && node.deoptReason !== 'no reason' ? node.deoptReason : null;
}
-};
+}
/**
* @unrestricted
*/
-SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
+export default class CPUProfileDataModel extends SDK.ProfileTreeModel {
/**
* @param {!Protocol.Profiler.Profile} profile
* @param {?SDK.Target} target
@@ -68,8 +68,9 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
* @param {!Protocol.Profiler.Profile} profile
*/
_compatibilityConversionHeadToNodes(profile) {
- if (!profile.head || profile.nodes)
+ if (!profile.head || profile.nodes) {
return;
+ }
/** @type {!Array<!Protocol.Profiler.ProfileNode>} */
const nodes = [];
convertNodesTree(profile.head);
@@ -91,8 +92,9 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
* @return {?Array<number>}
*/
_convertTimeDeltas(profile) {
- if (!profile.timeDeltas)
+ if (!profile.timeDeltas) {
return null;
+ }
let lastTimeUsec = profile.startTime;
const timestamps = new Array(profile.timeDeltas.length);
for (let i = 0; i < profile.timeDeltas.length; ++i) {
@@ -104,7 +106,7 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
/**
* @param {!Array<!Protocol.Profiler.ProfileNode>} nodes
- * @return {!SDK.CPUProfileNode}
+ * @return {!CPUProfileNode}
*/
_translateProfileTree(nodes) {
/**
@@ -112,8 +114,9 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
* @return {boolean}
*/
function isNativeNode(node) {
- if (node.callFrame)
+ if (node.callFrame) {
return !!node.callFrame.url && node.callFrame.url.startsWith('native ');
+ }
return !!node['url'] && node['url'].startsWith('native ');
}
@@ -121,16 +124,18 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
* @param {!Array<!Protocol.Profiler.ProfileNode>} nodes
*/
function buildChildrenFromParents(nodes) {
- if (nodes[0].children)
+ if (nodes[0].children) {
return;
+ }
nodes[0].children = [];
for (let i = 1; i < nodes.length; ++i) {
const node = nodes[i];
const parentNode = nodeByIdMap.get(node.parent);
- if (parentNode.children)
+ if (parentNode.children) {
parentNode.children.push(node.id);
- else
+ } else {
parentNode.children = [node.id];
+ }
}
}
@@ -139,13 +144,16 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
* @param {!Array<number>|undefined} samples
*/
function buildHitCountFromSamples(nodes, samples) {
- if (typeof(nodes[0].hitCount) === 'number')
+ if (typeof (nodes[0].hitCount) === 'number') {
return;
+ }
console.assert(samples, 'Error: Neither hitCount nor samples are present in profile.');
- for (let i = 0; i < nodes.length; ++i)
+ for (let i = 0; i < nodes.length; ++i) {
nodes[i].hitCount = 0;
- for (let i = 0; i < samples.length; ++i)
+ }
+ for (let i = 0; i < samples.length; ++i) {
++nodeByIdMap.get(samples[i]).hitCount;
+ }
}
/** @type {!Map<number, !Protocol.Profiler.ProfileNode>} */
@@ -163,15 +171,16 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
const root = nodes[0];
/** @type {!Map<number, number>} */
const idMap = new Map([[root.id, root.id]]);
- const resultRoot = new SDK.CPUProfileNode(root, sampleTime);
+ const resultRoot = new CPUProfileNode(root, sampleTime);
const parentNodeStack = root.children.map(() => resultRoot);
const sourceNodeStack = root.children.map(id => nodeByIdMap.get(id));
while (sourceNodeStack.length) {
let parentNode = parentNodeStack.pop();
const sourceNode = sourceNodeStack.pop();
- if (!sourceNode.children)
+ if (!sourceNode.children) {
sourceNode.children = [];
- const targetNode = new SDK.CPUProfileNode(sourceNode, sampleTime);
+ }
+ const targetNode = new CPUProfileNode(sourceNode, sampleTime);
if (keepNatives || !isNativeNode(sourceNode)) {
parentNode.children.push(targetNode);
parentNode = targetNode;
@@ -182,22 +191,25 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
parentNodeStack.push.apply(parentNodeStack, sourceNode.children.map(() => parentNode));
sourceNodeStack.push.apply(sourceNodeStack, sourceNode.children.map(id => nodeByIdMap.get(id)));
}
- if (this.samples)
+ if (this.samples) {
this.samples = this.samples.map(id => idMap.get(id));
+ }
return resultRoot;
}
_sortSamples() {
const timestamps = this.timestamps;
- if (!timestamps)
+ if (!timestamps) {
return;
+ }
const samples = this.samples;
const indices = timestamps.map((x, index) => index);
indices.sort((a, b) => timestamps[a] - timestamps[b]);
for (let i = 0; i < timestamps.length; ++i) {
let index = indices[i];
- if (index === i)
+ if (index === i) {
continue;
+ }
// Move items in a cycle.
const savedTimestamp = timestamps[i];
const savedSample = samples[i];
@@ -222,15 +234,17 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
const profileStartTime = this.profileStartTime;
const interval = (this.profileEndTime - profileStartTime) / this.samples.length;
timestamps = new Float64Array(this.samples.length + 1);
- for (let i = 0; i < timestamps.length; ++i)
+ for (let i = 0; i < timestamps.length; ++i) {
timestamps[i] = profileStartTime + i * interval;
+ }
this.timestamps = timestamps;
return;
}
// Convert samples from usec to msec
- for (let i = 0; i < timestamps.length; ++i)
+ for (let i = 0; i < timestamps.length; ++i) {
timestamps[i] /= 1000;
+ }
if (this.samples.length === timestamps.length) {
// Support for a legacy format where were no timeDeltas.
// Add an extra timestamp used to calculate the last sample duration.
@@ -242,7 +256,7 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
}
_buildIdToNodeMap() {
- /** @type {!Map<number, !SDK.CPUProfileNode>} */
+ /** @type {!Map<number, !CPUProfileNode>} */
this._idToNode = new Map();
const idToNode = this._idToNode;
const stack = [this.profileHead];
@@ -257,12 +271,13 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
const topLevelNodes = this.profileHead.children;
for (let i = 0; i < topLevelNodes.length && !(this.gcNode && this.programNode && this.idleNode); i++) {
const node = topLevelNodes[i];
- if (node.functionName === '(garbage collector)')
+ if (node.functionName === '(garbage collector)') {
this.gcNode = node;
- else if (node.functionName === '(program)')
+ } else if (node.functionName === '(program)') {
this.programNode = node;
- else if (node.functionName === '(idle)')
+ } else if (node.functionName === '(idle)') {
this.idleNode = node;
+ }
}
}
@@ -275,8 +290,9 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
// with the preceeding sample.
const samples = this.samples;
const samplesCount = samples.length;
- if (!this.programNode || samplesCount < 3)
+ if (!this.programNode || samplesCount < 3) {
return;
+ }
const idToNode = this._idToNode;
const programNodeId = this.programNode.id;
const gcNodeId = this.gcNode ? this.gcNode.id : -1;
@@ -294,15 +310,17 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
prevNodeId = nodeId;
nodeId = nextNodeId;
}
- if (count)
+ if (count) {
Common.console.warn(ls`DevTools: CPU profile parser is fixing ${count} missing samples.`);
+ }
/**
* @param {!SDK.ProfileNode} node
* @return {!SDK.ProfileNode}
*/
function bottomNode(node) {
- while (node.parent && node.parent.parent)
+ while (node.parent && node.parent.parent) {
node = node.parent;
+ }
return node;
}
/**
@@ -315,14 +333,15 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
}
/**
- * @param {function(number, !SDK.CPUProfileNode, number)} openFrameCallback
- * @param {function(number, !SDK.CPUProfileNode, number, number, number)} closeFrameCallback
+ * @param {function(number, !CPUProfileNode, number)} openFrameCallback
+ * @param {function(number, !CPUProfileNode, number, number, number)} closeFrameCallback
* @param {number=} startTime
* @param {number=} stopTime
*/
forEachFrame(openFrameCallback, closeFrameCallback, startTime, stopTime) {
- if (!this.profileHead || !this.samples)
+ if (!this.profileHead || !this.samples) {
return;
+ }
startTime = startTime || 0;
stopTime = stopTime || Infinity;
@@ -341,22 +360,26 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
// Extra slots for gc being put on top,
// and one at the bottom to allow safe stackTop-1 access.
const stackDepth = this.maxDepth + 3;
- if (!this._stackStartTimes)
+ if (!this._stackStartTimes) {
this._stackStartTimes = new Float64Array(stackDepth);
+ }
const stackStartTimes = this._stackStartTimes;
- if (!this._stackChildrenDuration)
+ if (!this._stackChildrenDuration) {
this._stackChildrenDuration = new Float64Array(stackDepth);
+ }
const stackChildrenDuration = this._stackChildrenDuration;
let node;
let sampleIndex;
for (sampleIndex = startIndex; sampleIndex < samplesCount; sampleIndex++) {
sampleTime = timestamps[sampleIndex];
- if (sampleTime >= stopTime)
+ if (sampleTime >= stopTime) {
break;
+ }
const id = samples[sampleIndex];
- if (id === prevId)
+ if (id === prevId) {
continue;
+ }
node = idToNode.get(id);
let prevNode = idToNode.get(prevId);
@@ -392,7 +415,7 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
const duration = sampleTime - start;
stackChildrenDuration[stackTop - 1] += duration;
closeFrameCallback(
- prevNode.depth, /** @type {!SDK.CPUProfileNode} */ (prevNode), start, duration,
+ prevNode.depth, /** @type {!CPUProfileNode} */ (prevNode), start, duration,
duration - stackChildrenDuration[stackTop]);
--stackTop;
if (node.depth === prevNode.depth) {
@@ -428,7 +451,7 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
const duration = sampleTime - start;
stackChildrenDuration[stackTop - 1] += duration;
closeFrameCallback(
- node.depth, /** @type {!SDK.CPUProfileNode} */ (node), start, duration,
+ node.depth, /** @type {!CPUProfileNode} */ (node), start, duration,
duration - stackChildrenDuration[stackTop]);
--stackTop;
}
@@ -436,9 +459,21 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
/**
* @param {number} index
- * @return {?SDK.CPUProfileNode}
+ * @return {?CPUProfileNode}
*/
nodeByIndex(index) {
return this._idToNode.get(this.samples[index]) || null;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CPUProfileDataModel = CPUProfileDataModel;
+
+/** @constructor */
+SDK.CPUProfileNode = CPUProfileNode; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfilerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfilerModel.js
index 5377bbbca44..1b23cc98676 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfilerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfilerModel.js
@@ -29,7 +29,7 @@
/**
* @implements {Protocol.ProfilerDispatcher}
*/
-SDK.CPUProfilerModel = class extends SDK.SDKModel {
+export default class CPUProfilerModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -69,7 +69,7 @@ SDK.CPUProfilerModel = class extends SDK.SDKModel {
title = Common.UIString('Profile %d', this._nextAnonymousConsoleProfileNumber++);
this._anonymousConsoleProfileIdToTitle.set(id, title);
}
- this._dispatchProfileEvent(SDK.CPUProfilerModel.Events.ConsoleProfileStarted, id, scriptLocation, title);
+ this._dispatchProfileEvent(Events.ConsoleProfileStarted, id, scriptLocation, title);
}
/**
@@ -86,8 +86,7 @@ SDK.CPUProfilerModel = class extends SDK.SDKModel {
}
// Make sure ProfilesPanel is initialized and CPUProfileType is created.
self.runtime.loadModulePromise('profiler').then(() => {
- this._dispatchProfileEvent(
- SDK.CPUProfilerModel.Events.ConsoleProfileFinished, id, scriptLocation, title, cpuProfile);
+ this._dispatchProfileEvent(Events.ConsoleProfileFinished, id, scriptLocation, title, cpuProfile);
});
}
@@ -160,15 +159,27 @@ SDK.CPUProfilerModel = class extends SDK.SDKModel {
bestEffortCoverage() {
return this._profilerAgent.getBestEffortCoverage().then(result => result || []);
}
-};
-
-SDK.SDKModel.register(SDK.CPUProfilerModel, SDK.Target.Capability.JS, true);
+}
/** @enum {symbol} */
-SDK.CPUProfilerModel.Events = {
+export const Events = {
ConsoleProfileStarted: Symbol('ConsoleProfileStarted'),
ConsoleProfileFinished: Symbol('ConsoleProfileFinished')
};
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CPUProfilerModel = CPUProfilerModel;
+
+/** @enum {symbol} */
+SDK.CPUProfilerModel.Events = Events;
+
+SDK.SDKModel.register(SDK.CPUProfilerModel, SDK.Target.Capability.JS, true);
+
/** @typedef {!{id: string, scriptLocation: !SDK.DebuggerModel.Location, title: string, cpuProfile: (!Protocol.Profiler.Profile|undefined), cpuProfilerModel: !SDK.CPUProfilerModel}} */
-SDK.CPUProfilerModel.EventData;
+SDK.CPUProfilerModel.EventData; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js
index eb3e595c067..aaa227d0fa1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.CSSMatchedStyles = class {
+export default class CSSMatchedStyles {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!SDK.DOMNode} node
@@ -31,8 +31,9 @@ SDK.CSSMatchedStyles = class {
/** @type {!Map<!Protocol.DOM.NodeId, !Map<string, boolean>>} */
this._matchingSelectors = new Map();
this._keyframes = [];
- if (animationsPayload)
+ if (animationsPayload) {
this._keyframes = animationsPayload.map(rule => new SDK.CSSKeyframesRule(cssModel, rule));
+ }
/** @type {!Map<!SDK.CSSStyleDeclaration, ?SDK.DOMNode>} */
this._nodeForStyle = new Map();
@@ -40,17 +41,19 @@ SDK.CSSMatchedStyles = class {
this._inheritedStyles = new Set();
matchedPayload = cleanUserAgentPayload(matchedPayload);
- for (const inheritedResult of inheritedPayload)
+ for (const inheritedResult of inheritedPayload) {
inheritedResult.matchedCSSRules = cleanUserAgentPayload(inheritedResult.matchedCSSRules);
+ }
this._mainDOMCascade = this._buildMainCascade(inlinePayload, attributesPayload, matchedPayload, inheritedPayload);
this._pseudoDOMCascades = this._buildPseudoCascades(pseudoPayload);
- /** @type {!Map<!SDK.CSSStyleDeclaration, !SDK.CSSMatchedStyles.DOMInheritanceCascade>} */
+ /** @type {!Map<!SDK.CSSStyleDeclaration, !DOMInheritanceCascade>} */
this._styleToDOMCascade = new Map();
for (const domCascade of Array.from(this._pseudoDOMCascades.values()).concat(this._mainDOMCascade)) {
- for (const style of domCascade.styles())
+ for (const style of domCascade.styles()) {
this._styleToDOMCascade.set(style, domCascade);
+ }
}
/**
@@ -58,8 +61,9 @@ SDK.CSSMatchedStyles = class {
* @return {!Array<!Protocol.CSS.RuleMatch>}
*/
function cleanUserAgentPayload(payload) {
- for (const ruleMatch of payload)
+ for (const ruleMatch of payload) {
cleanUserAgentSelectors(ruleMatch);
+ }
// Merge UA rules that are sequential and have similar selector/media.
const cleanMatchedPayload = [];
@@ -82,14 +86,18 @@ SDK.CSSMatchedStyles = class {
function mergeRule(from, to) {
const shorthands = /** @type {!Map<string, string>} */ (new Map());
const properties = /** @type {!Map<string, string>} */ (new Map());
- for (const entry of to.rule.style.shorthandEntries)
+ for (const entry of to.rule.style.shorthandEntries) {
shorthands.set(entry.name, entry.value);
- for (const entry of to.rule.style.cssProperties)
+ }
+ for (const entry of to.rule.style.cssProperties) {
properties.set(entry.name, entry.value);
- for (const entry of from.rule.style.shorthandEntries)
+ }
+ for (const entry of from.rule.style.shorthandEntries) {
shorthands.set(entry.name, entry.value);
- for (const entry of from.rule.style.cssProperties)
+ }
+ for (const entry of from.rule.style.cssProperties) {
properties.set(entry.name, entry.value);
+ }
to.rule.style.shorthandEntries = shorthands.keysArray().map(name => ({name, value: shorthands.get(name)}));
to.rule.style.cssProperties = properties.keysArray().map(name => ({name, value: properties.get(name)}));
}
@@ -99,8 +107,9 @@ SDK.CSSMatchedStyles = class {
* @return {?string}
*/
function mediaText(ruleMatch) {
- if (!ruleMatch.rule.media)
+ if (!ruleMatch.rule.media) {
return null;
+ }
return ruleMatch.rule.media.map(media => media.text).join(', ');
}
@@ -109,8 +118,9 @@ SDK.CSSMatchedStyles = class {
*/
function cleanUserAgentSelectors(ruleMatch) {
const {matchingSelectors, rule} = ruleMatch;
- if (rule.origin !== 'user-agent' || !matchingSelectors.length)
+ if (rule.origin !== 'user-agent' || !matchingSelectors.length) {
return;
+ }
rule.selectorList.selectors = rule.selectorList.selectors.filter((item, i) => matchingSelectors.includes(i));
rule.selectorList.text = rule.selectorList.selectors.map(item => item.text).join(', ');
ruleMatch.matchingSelectors = matchingSelectors.map((item, i) => i);
@@ -123,21 +133,22 @@ SDK.CSSMatchedStyles = class {
* @param {?Protocol.CSS.CSSStyle} attributesPayload
* @param {!Array.<!Protocol.CSS.RuleMatch>} matchedPayload
* @param {!Array.<!Protocol.CSS.InheritedStyleEntry>} inheritedPayload
- * @return {!SDK.CSSMatchedStyles.DOMInheritanceCascade}
+ * @return {!DOMInheritanceCascade}
*/
_buildMainCascade(inlinePayload, attributesPayload, matchedPayload, inheritedPayload) {
- /** @type {!Array<!SDK.CSSMatchedStyles.NodeCascade>} */
+ /** @type {!Array<!NodeCascade>} */
const nodeCascades = [];
/** @type {!Array<!SDK.CSSStyleDeclaration>} */
const nodeStyles = [];
/**
- * @this {SDK.CSSMatchedStyles}
+ * @this {CSSMatchedStyles}
*/
function addAttributesStyle() {
- if (!attributesPayload)
+ if (!attributesPayload) {
return;
+ }
const style =
new SDK.CSSStyleDeclaration(this._cssModel, null, attributesPayload, SDK.CSSStyleDeclaration.Type.Attributes);
this._nodeForStyle.set(style, this._node);
@@ -166,9 +177,10 @@ SDK.CSSMatchedStyles = class {
this._addMatchingSelectors(this._node, rule, matchedPayload[i].matchingSelectors);
}
- if (!addedAttributesStyle)
+ if (!addedAttributesStyle) {
addAttributesStyle.call(this);
- nodeCascades.push(new SDK.CSSMatchedStyles.NodeCascade(this, nodeStyles, false /* isInherited */));
+ }
+ nodeCascades.push(new NodeCascade(this, nodeStyles, false /* isInherited */));
// Walk the node structure and identify styles with inherited properties.
let parentNode = this._node.parentNode;
@@ -189,19 +201,22 @@ SDK.CSSMatchedStyles = class {
for (let j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) {
const inheritedRule = new SDK.CSSStyleRule(this._cssModel, inheritedMatchedCSSRules[j].rule);
this._addMatchingSelectors(parentNode, inheritedRule, inheritedMatchedCSSRules[j].matchingSelectors);
- if (!this._containsInherited(inheritedRule.style))
+ if (!this._containsInherited(inheritedRule.style)) {
continue;
- if (containsStyle(nodeStyles, inheritedRule.style) || containsStyle(this._inheritedStyles, inheritedRule.style))
+ }
+ if (containsStyle(nodeStyles, inheritedRule.style) ||
+ containsStyle(this._inheritedStyles, inheritedRule.style)) {
continue;
+ }
this._nodeForStyle.set(inheritedRule.style, parentNode);
inheritedStyles.push(inheritedRule.style);
this._inheritedStyles.add(inheritedRule.style);
}
parentNode = parentNode.parentNode;
- nodeCascades.push(new SDK.CSSMatchedStyles.NodeCascade(this, inheritedStyles, true /* isInherited */));
+ nodeCascades.push(new NodeCascade(this, inheritedStyles, true /* isInherited */));
}
- return new SDK.CSSMatchedStyles.DOMInheritanceCascade(nodeCascades);
+ return new DOMInheritanceCascade(nodeCascades);
/**
* @param {!Array<!SDK.CSSStyleDeclaration>|!Set<!SDK.CSSStyleDeclaration>} styles
@@ -209,11 +224,13 @@ SDK.CSSMatchedStyles = class {
* @return {boolean}
*/
function containsStyle(styles, query) {
- if (!query.styleSheetId || !query.range)
+ if (!query.styleSheetId || !query.range) {
return false;
+ }
for (const style of styles) {
- if (query.styleSheetId === style.styleSheetId && style.range && query.range.equal(style.range))
+ if (query.styleSheetId === style.styleSheetId && style.range && query.range.equal(style.range)) {
return true;
+ }
}
return false;
}
@@ -221,13 +238,14 @@ SDK.CSSMatchedStyles = class {
/**
* @param {!Array.<!Protocol.CSS.PseudoElementMatches>} pseudoPayload
- * @return {!Map<!Protocol.DOM.PseudoType, !SDK.CSSMatchedStyles.DOMInheritanceCascade>}
+ * @return {!Map<!Protocol.DOM.PseudoType, !DOMInheritanceCascade>}
*/
_buildPseudoCascades(pseudoPayload) {
- /** @type {!Map<!Protocol.DOM.PseudoType, !SDK.CSSMatchedStyles.DOMInheritanceCascade>} */
+ /** @type {!Map<!Protocol.DOM.PseudoType, !DOMInheritanceCascade>} */
const pseudoCascades = new Map();
- if (!pseudoPayload)
+ if (!pseudoPayload) {
return pseudoCascades;
+ }
for (let i = 0; i < pseudoPayload.length; ++i) {
const entryPayload = pseudoPayload[i];
// PseudoElement nodes are not created unless "content" css property is set.
@@ -238,11 +256,12 @@ SDK.CSSMatchedStyles = class {
const pseudoRule = new SDK.CSSStyleRule(this._cssModel, rules[j].rule);
pseudoStyles.push(pseudoRule.style);
this._nodeForStyle.set(pseudoRule.style, pseudoElement);
- if (pseudoElement)
+ if (pseudoElement) {
this._addMatchingSelectors(pseudoElement, pseudoRule, rules[j].matchingSelectors);
+ }
}
- const nodeCascade = new SDK.CSSMatchedStyles.NodeCascade(this, pseudoStyles, false /* isInherited */);
- pseudoCascades.set(entryPayload.pseudoType, new SDK.CSSMatchedStyles.DOMInheritanceCascade([nodeCascade]));
+ const nodeCascade = new NodeCascade(this, pseudoStyles, false /* isInherited */);
+ pseudoCascades.set(entryPayload.pseudoType, new DOMInheritanceCascade([nodeCascade]));
}
return pseudoCascades;
}
@@ -251,7 +270,7 @@ SDK.CSSMatchedStyles = class {
* @param {!SDK.DOMNode} node
* @param {!SDK.CSSStyleRule} rule
* @param {!Array<number>} matchingSelectorIndices
- * @this {SDK.CSSMatchedStyles}
+ * @this {CSSMatchedStyles}
*/
_addMatchingSelectors(node, rule, matchingSelectorIndices) {
for (const matchingSelectorIndex of matchingSelectorIndices) {
@@ -289,15 +308,18 @@ SDK.CSSMatchedStyles = class {
*/
matchingSelectors(rule) {
const node = this.nodeForStyle(rule.style);
- if (!node)
+ if (!node) {
return [];
+ }
const map = this._matchingSelectors.get(node.id);
- if (!map)
+ if (!map) {
return [];
+ }
const result = [];
for (let i = 0; i < rule.selectors.length; ++i) {
- if (map.get(rule.selectors[i].text))
+ if (map.get(rule.selectors[i].text)) {
result.push(i);
+ }
}
return result;
}
@@ -308,30 +330,34 @@ SDK.CSSMatchedStyles = class {
*/
recomputeMatchingSelectors(rule) {
const node = this.nodeForStyle(rule.style);
- if (!node)
+ if (!node) {
return Promise.resolve();
+ }
const promises = [];
- for (const selector of rule.selectors)
+ for (const selector of rule.selectors) {
promises.push(querySelector.call(this, node, selector.text));
+ }
return Promise.all(promises);
/**
* @param {!SDK.DOMNode} node
* @param {string} selectorText
- * @this {SDK.CSSMatchedStyles}
+ * @this {CSSMatchedStyles}
*/
async function querySelector(node, selectorText) {
const ownerDocument = node.ownerDocument || null;
// We assume that "matching" property does not ever change during the
// MatchedStyleResult's lifetime.
const map = this._matchingSelectors.get(node.id);
- if ((map && map.has(selectorText)) || !ownerDocument)
+ if ((map && map.has(selectorText)) || !ownerDocument) {
return;
+ }
const matchingNodeIds = await this._node.domModel().querySelectorAll(ownerDocument.id, selectorText);
- if (matchingNodeIds)
+ if (matchingNodeIds) {
this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(node.id) !== -1);
+ }
}
}
@@ -366,8 +392,9 @@ SDK.CSSMatchedStyles = class {
mediaMatches(style) {
const media = style.parentRule ? style.parentRule.media : [];
for (let i = 0; media && i < media.length; ++i) {
- if (!media[i].active())
+ if (!media[i].active()) {
return false;
+ }
}
return true;
}
@@ -411,8 +438,9 @@ SDK.CSSMatchedStyles = class {
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
// Does this style contain non-overridden inherited property?
- if (property.activeInStyle() && SDK.cssMetadata().isPropertyInherited(property.name))
+ if (property.activeInStyle() && SDK.cssMetadata().isPropertyInherited(property.name)) {
return true;
+ }
}
return false;
}
@@ -464,7 +492,7 @@ SDK.CSSMatchedStyles = class {
/**
* @param {!SDK.CSSProperty} property
- * @return {?SDK.CSSMatchedStyles.PropertyState}
+ * @return {?PropertyState}
*/
propertyState(property) {
const domCascade = this._styleToDOMCascade.get(property.ownerStyle);
@@ -473,14 +501,15 @@ SDK.CSSMatchedStyles = class {
resetActiveProperties() {
this._mainDOMCascade.reset();
- for (const domCascade of this._pseudoDOMCascades.values())
+ for (const domCascade of this._pseudoDOMCascades.values()) {
domCascade.reset();
+ }
}
-};
+}
-SDK.CSSMatchedStyles.NodeCascade = class {
+export class NodeCascade {
/**
- * @param {!SDK.CSSMatchedStyles} matchedStyles
+ * @param {!CSSMatchedStyles} matchedStyles
* @param {!Array<!SDK.CSSStyleDeclaration>} styles
* @param {boolean} isInherited
*/
@@ -488,7 +517,7 @@ SDK.CSSMatchedStyles.NodeCascade = class {
this._matchedStyles = matchedStyles;
this._styles = styles;
this._isInherited = isInherited;
- /** @type {!Map<!SDK.CSSProperty, !SDK.CSSMatchedStyles.PropertyState>} */
+ /** @type {!Map<!SDK.CSSProperty, !PropertyState>} */
this._propertiesState = new Map();
/** @type {!Map.<string, !SDK.CSSProperty>} */
this._activeProperties = new Map();
@@ -501,56 +530,61 @@ SDK.CSSMatchedStyles.NodeCascade = class {
for (const style of this._styles) {
const rule = style.parentRule;
// Compute cascade for CSSStyleRules only.
- if (rule && !(rule instanceof SDK.CSSStyleRule))
+ if (rule && !(rule instanceof SDK.CSSStyleRule)) {
continue;
- if (rule && !this._matchedStyles.hasMatchingSelectors(rule))
+ }
+ if (rule && !this._matchedStyles.hasMatchingSelectors(rule)) {
continue;
+ }
for (const property of style.allProperties()) {
// Do not pick non-inherited properties from inherited styles.
- if (this._isInherited && !SDK.cssMetadata().isPropertyInherited(property.name))
+ if (this._isInherited && !SDK.cssMetadata().isPropertyInherited(property.name)) {
continue;
+ }
if (!property.activeInStyle()) {
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded);
+ this._propertiesState.set(property, PropertyState.Overloaded);
continue;
}
const canonicalName = SDK.cssMetadata().canonicalPropertyName(property.name);
const activeProperty = this._activeProperties.get(canonicalName);
if (activeProperty && (activeProperty.important || !property.important)) {
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded);
+ this._propertiesState.set(property, PropertyState.Overloaded);
continue;
}
- if (activeProperty)
- this._propertiesState.set(activeProperty, SDK.CSSMatchedStyles.PropertyState.Overloaded);
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Active);
+ if (activeProperty) {
+ this._propertiesState.set(activeProperty, PropertyState.Overloaded);
+ }
+ this._propertiesState.set(property, PropertyState.Active);
this._activeProperties.set(canonicalName, property);
}
}
}
-};
+}
-SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
+export class DOMInheritanceCascade {
/**
- * @param {!Array<!SDK.CSSMatchedStyles.NodeCascade>} nodeCascades
+ * @param {!Array<!NodeCascade>} nodeCascades
*/
constructor(nodeCascades) {
this._nodeCascades = nodeCascades;
- /** @type {!Map<!SDK.CSSProperty, !SDK.CSSMatchedStyles.PropertyState>} */
+ /** @type {!Map<!SDK.CSSProperty, !PropertyState>} */
this._propertiesState = new Map();
- /** @type {!Map<!SDK.CSSMatchedStyles.NodeCascade, !Map<string, string>>} */
+ /** @type {!Map<!NodeCascade, !Map<string, string>>} */
this._availableCSSVariables = new Map();
- /** @type {!Map<!SDK.CSSMatchedStyles.NodeCascade, !Map<string, ?string>>} */
+ /** @type {!Map<!NodeCascade, !Map<string, ?string>>} */
this._computedCSSVariables = new Map();
this._initialized = false;
- /** @type {!Map<!SDK.CSSStyleDeclaration, !SDK.CSSMatchedStyles.NodeCascade>} */
+ /** @type {!Map<!SDK.CSSStyleDeclaration, !NodeCascade>} */
this._styleToNodeCascade = new Map();
for (const nodeCascade of nodeCascades) {
- for (const style of nodeCascade._styles)
+ for (const style of nodeCascade._styles) {
this._styleToNodeCascade.set(style, nodeCascade);
+ }
}
}
@@ -560,8 +594,9 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
*/
availableCSSVariables(style) {
const nodeCascade = this._styleToNodeCascade.get(style);
- if (!nodeCascade)
+ if (!nodeCascade) {
return [];
+ }
this._ensureInitialized();
return Array.from(this._availableCSSVariables.get(nodeCascade).keys());
}
@@ -573,8 +608,9 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
*/
computeCSSVariable(style, variableName) {
const nodeCascade = this._styleToNodeCascade.get(style);
- if (!nodeCascade)
+ if (!nodeCascade) {
return null;
+ }
this._ensureInitialized();
const availableCSSVariables = this._availableCSSVariables.get(nodeCascade);
const computedCSSVariables = this._computedCSSVariables.get(nodeCascade);
@@ -588,8 +624,9 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
*/
computeValue(style, value) {
const nodeCascade = this._styleToNodeCascade.get(style);
- if (!nodeCascade)
+ if (!nodeCascade) {
return null;
+ }
this._ensureInitialized();
const availableCSSVariables = this._availableCSSVariables.get(nodeCascade);
const computedCSSVariables = this._computedCSSVariables.get(nodeCascade);
@@ -603,10 +640,12 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
* @return {?string}
*/
_innerComputeCSSVariable(availableCSSVariables, computedCSSVariables, variableName) {
- if (!availableCSSVariables.has(variableName))
+ if (!availableCSSVariables.has(variableName)) {
return null;
- if (computedCSSVariables.has(variableName))
+ }
+ if (computedCSSVariables.has(variableName)) {
return computedCSSVariables.get(variableName);
+ }
// Set dummy value to avoid infinite recursion.
computedCSSVariables.set(variableName, null);
const definedValue = availableCSSVariables.get(variableName);
@@ -631,16 +670,19 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
}
// process var() function
const regexMatch = result.value.match(/^var\((--[a-zA-Z0-9-_]+)[,]?\s*(.*)\)$/);
- if (!regexMatch)
+ if (!regexMatch) {
return null;
+ }
const cssVariable = regexMatch[1];
const computedValue = this._innerComputeCSSVariable(availableCSSVariables, computedCSSVariables, cssVariable);
- if (computedValue === null && !regexMatch[2])
+ if (computedValue === null && !regexMatch[2]) {
return null;
- if (computedValue === null)
+ }
+ if (computedValue === null) {
tokens.push(regexMatch[2]);
- else
+ } else {
tokens.push(computedValue);
+ }
}
return tokens.map(token => token.trim()).join(' ');
}
@@ -654,7 +696,7 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
/**
* @param {!SDK.CSSProperty} property
- * @return {?SDK.CSSMatchedStyles.PropertyState}
+ * @return {?PropertyState}
*/
propertyState(property) {
this._ensureInitialized();
@@ -669,8 +711,9 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
}
_ensureInitialized() {
- if (this._initialized)
+ if (this._initialized) {
return;
+ }
this._initialized = true;
const activeProperties = new Map();
@@ -678,18 +721,18 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
nodeCascade._computeActiveProperties();
for (const entry of nodeCascade._propertiesState.entries()) {
const property = /** @type {!SDK.CSSProperty} */ (entry[0]);
- const state = /** @type {!SDK.CSSMatchedStyles.PropertyState} */ (entry[1]);
- if (state === SDK.CSSMatchedStyles.PropertyState.Overloaded) {
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded);
+ const state = /** @type {!PropertyState} */ (entry[1]);
+ if (state === PropertyState.Overloaded) {
+ this._propertiesState.set(property, PropertyState.Overloaded);
continue;
}
const canonicalName = SDK.cssMetadata().canonicalPropertyName(property.name);
if (activeProperties.has(canonicalName)) {
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Overloaded);
+ this._propertiesState.set(property, PropertyState.Overloaded);
continue;
}
activeProperties.set(canonicalName, property);
- this._propertiesState.set(property, SDK.CSSMatchedStyles.PropertyState.Active);
+ this._propertiesState.set(property, PropertyState.Active);
}
}
// If every longhand of the shorthand is not active, then the shorthand is not active too.
@@ -698,23 +741,26 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
const shorthandProperty = /** @type {!SDK.CSSProperty} */ (entry[1]);
const shorthandStyle = shorthandProperty.ownerStyle;
const longhands = shorthandStyle.longhandProperties(shorthandProperty.name);
- if (!longhands.length)
+ if (!longhands.length) {
continue;
+ }
let hasActiveLonghands = false;
for (const longhand of longhands) {
const longhandCanonicalName = SDK.cssMetadata().canonicalPropertyName(longhand.name);
const longhandActiveProperty = activeProperties.get(longhandCanonicalName);
- if (!longhandActiveProperty)
+ if (!longhandActiveProperty) {
continue;
+ }
if (longhandActiveProperty.ownerStyle === shorthandStyle) {
hasActiveLonghands = true;
break;
}
}
- if (hasActiveLonghands)
+ if (hasActiveLonghands) {
continue;
+ }
activeProperties.delete(canonicalName);
- this._propertiesState.set(shorthandProperty, SDK.CSSMatchedStyles.PropertyState.Overloaded);
+ this._propertiesState.set(shorthandProperty, PropertyState.Overloaded);
}
// Work inheritance chain backwards to compute visible CSS Variables.
@@ -724,17 +770,36 @@ SDK.CSSMatchedStyles.DOMInheritanceCascade = class {
for (const entry of nodeCascade._activeProperties.entries()) {
const propertyName = /** @type {string} */ (entry[0]);
const property = /** @type {!SDK.CSSProperty} */ (entry[1]);
- if (propertyName.startsWith('--'))
+ if (propertyName.startsWith('--')) {
accumulatedCSSVariables.set(propertyName, property.value);
+ }
}
this._availableCSSVariables.set(nodeCascade, new Map(accumulatedCSSVariables));
this._computedCSSVariables.set(nodeCascade, new Map());
}
}
-};
+}
/** @enum {string} */
-SDK.CSSMatchedStyles.PropertyState = {
+export const PropertyState = {
Active: 'Active',
Overloaded: 'Overloaded'
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSMatchedStyles = CSSMatchedStyles;
+
+/** @constructor */
+SDK.CSSMatchedStyles.NodeCascade = NodeCascade;
+
+/** @constructor */
+SDK.CSSMatchedStyles.DOMInheritanceCascade = DOMInheritanceCascade;
+
+/** @enum {string} */
+SDK.CSSMatchedStyles.PropertyState = PropertyState;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMedia.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMedia.js
index c6f71182adc..a56d0208a5c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMedia.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMedia.js
@@ -4,23 +4,24 @@
/**
* @unrestricted
*/
-SDK.CSSMediaQuery = class {
+export class CSSMediaQuery {
/**
* @param {!Protocol.CSS.MediaQuery} payload
*/
constructor(payload) {
this._active = payload.active;
this._expressions = [];
- for (let j = 0; j < payload.expressions.length; ++j)
- this._expressions.push(SDK.CSSMediaQueryExpression.parsePayload(payload.expressions[j]));
+ for (let j = 0; j < payload.expressions.length; ++j) {
+ this._expressions.push(CSSMediaQueryExpression.parsePayload(payload.expressions[j]));
+ }
}
/**
* @param {!Protocol.CSS.MediaQuery} payload
- * @return {!SDK.CSSMediaQuery}
+ * @return {!CSSMediaQuery}
*/
static parsePayload(payload) {
- return new SDK.CSSMediaQuery(payload);
+ return new CSSMediaQuery(payload);
}
/**
@@ -31,18 +32,18 @@ SDK.CSSMediaQuery = class {
}
/**
- * @return {!Array.<!SDK.CSSMediaQueryExpression>}
+ * @return {!Array.<!CSSMediaQueryExpression>}
*/
expressions() {
return this._expressions;
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSMediaQueryExpression = class {
+export class CSSMediaQueryExpression {
/**
* @param {!Protocol.CSS.MediaQueryExpression} payload
*/
@@ -56,10 +57,10 @@ SDK.CSSMediaQueryExpression = class {
/**
* @param {!Protocol.CSS.MediaQueryExpression} payload
- * @return {!SDK.CSSMediaQueryExpression}
+ * @return {!CSSMediaQueryExpression}
*/
static parsePayload(payload) {
- return new SDK.CSSMediaQueryExpression(payload);
+ return new CSSMediaQueryExpression(payload);
}
/**
@@ -96,13 +97,13 @@ SDK.CSSMediaQueryExpression = class {
computedLength() {
return this._computedLength;
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSMedia = class {
+export default class CSSMedia {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSMedia} payload
@@ -115,21 +116,22 @@ SDK.CSSMedia = class {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSMedia} payload
- * @return {!SDK.CSSMedia}
+ * @return {!CSSMedia}
*/
static parsePayload(cssModel, payload) {
- return new SDK.CSSMedia(cssModel, payload);
+ return new CSSMedia(cssModel, payload);
}
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Array.<!Protocol.CSS.CSSMedia>} payload
- * @return {!Array.<!SDK.CSSMedia>}
+ * @return {!Array.<!CSSMedia>}
*/
static parseMediaArrayPayload(cssModel, payload) {
const result = [];
- for (let i = 0; i < payload.length; ++i)
- result.push(SDK.CSSMedia.parsePayload(cssModel, payload[i]));
+ for (let i = 0; i < payload.length; ++i) {
+ result.push(CSSMedia.parsePayload(cssModel, payload[i]));
+ }
return result;
}
@@ -145,8 +147,9 @@ SDK.CSSMedia = class {
this.mediaList = null;
if (payload.mediaList) {
this.mediaList = [];
- for (let i = 0; i < payload.mediaList.length; ++i)
- this.mediaList.push(SDK.CSSMediaQuery.parsePayload(payload.mediaList[i]));
+ for (let i = 0; i < payload.mediaList.length; ++i) {
+ this.mediaList.push(CSSMediaQuery.parsePayload(payload.mediaList[i]));
+ }
}
}
@@ -154,21 +157,24 @@ SDK.CSSMedia = class {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.styleSheetId !== edit.styleSheetId || !this.range)
+ if (this.styleSheetId !== edit.styleSheetId || !this.range) {
return;
- if (edit.oldRange.equal(this.range))
+ }
+ if (edit.oldRange.equal(this.range)) {
this._reinitialize(/** @type {!Protocol.CSS.CSSMedia} */ (edit.payload));
- else
+ } else {
this.range = this.range.rebaseAfterTextEdit(edit.oldRange, edit.newRange);
+ }
}
/**
- * @param {!SDK.CSSMedia} other
+ * @param {!CSSMedia} other
* @return {boolean}
*/
equal(other) {
- if (!this.styleSheetId || !this.range || !other.range)
+ if (!this.styleSheetId || !this.range || !other.range) {
return false;
+ }
return this.styleSheetId === other.styleSheetId && this.range.equal(other.range);
}
@@ -176,11 +182,13 @@ SDK.CSSMedia = class {
* @return {boolean}
*/
active() {
- if (!this.mediaList)
+ if (!this.mediaList) {
return true;
+ }
for (let i = 0; i < this.mediaList.length; ++i) {
- if (this.mediaList[i].active())
+ if (this.mediaList[i].active()) {
return true;
+ }
}
return false;
}
@@ -189,11 +197,13 @@ SDK.CSSMedia = class {
* @return {number|undefined}
*/
lineNumberInSource() {
- if (!this.range)
+ if (!this.range) {
return undefined;
+ }
const header = this.header();
- if (!header)
+ if (!header) {
return undefined;
+ }
return header.lineNumberInSource(this.range.startLine);
}
@@ -201,11 +211,13 @@ SDK.CSSMedia = class {
* @return {number|undefined}
*/
columnNumberInSource() {
- if (!this.range)
+ if (!this.range) {
return undefined;
+ }
const header = this.header();
- if (!header)
+ if (!header) {
return undefined;
+ }
return header.columnNumberInSource(this.range.startLine, this.range.startColumn);
}
@@ -221,16 +233,34 @@ SDK.CSSMedia = class {
*/
rawLocation() {
const header = this.header();
- if (!header || this.lineNumberInSource() === undefined)
+ if (!header || this.lineNumberInSource() === undefined) {
return null;
+ }
const lineNumber = Number(this.lineNumberInSource());
return new SDK.CSSLocation(header, lineNumber, this.columnNumberInSource());
}
-};
+}
-SDK.CSSMedia.Source = {
+export const Source = {
LINKED_SHEET: 'linkedSheet',
INLINE_SHEET: 'inlineSheet',
MEDIA_RULE: 'mediaRule',
IMPORT_RULE: 'importRule'
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSMediaQuery = CSSMediaQuery;
+
+/** @constructor */
+SDK.CSSMediaQueryExpression = CSSMediaQueryExpression;
+
+/** @constructor */
+SDK.CSSMedia = CSSMedia;
+
+SDK.CSSMedia.Source = Source;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
index b4d70fcfe6c..d4414d76ccf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSMetadata.js
@@ -33,7 +33,7 @@
/**
* @unrestricted
*/
-SDK.CSSMetadata = class {
+export default class CSSMetadata {
/**
* @param {!Array.<!{name: string, longhands: !Array.<string>, inherited: boolean, svg: boolean}>} properties
*/
@@ -50,14 +50,17 @@ SDK.CSSMetadata = class {
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
const propertyName = property.name;
- if (!CSS.supports(propertyName, 'initial'))
+ if (!CSS.supports(propertyName, 'initial')) {
continue;
+ }
this._values.push(propertyName);
- if (property.inherited)
+ if (property.inherited) {
this._inherited.add(propertyName);
- if (property.svg)
+ }
+ if (property.svg) {
this._svgProperties.add(propertyName);
+ }
const longhands = properties[i].longhands;
if (longhands) {
@@ -73,7 +76,7 @@ SDK.CSSMetadata = class {
}
}
}
- this._values.sort(SDK.CSSMetadata._sortPrefixesToEnd);
+ this._values.sort(CSSMetadata._sortPrefixesToEnd);
this._valuesSet = new Set(this._values);
/** @type {!Array<string>} */
@@ -83,10 +86,11 @@ SDK.CSSMetadata = class {
for (const name of this._valuesSet) {
const values = this._specificPropertyValues(name)
.filter(value => CSS.supports(name, value))
- .sort(SDK.CSSMetadata._sortPrefixesToEnd);
+ .sort(CSSMetadata._sortPrefixesToEnd);
const presets = values.map(value => `${name}: ${value}`);
- if (!this.isSVGProperty(name))
+ if (!this.isSVGProperty(name)) {
this._nameValuePresets.pushAll(presets);
+ }
this._nameValuePresetsIncludingSVG.pushAll(presets);
}
}
@@ -98,10 +102,12 @@ SDK.CSSMetadata = class {
static _sortPrefixesToEnd(a, b) {
const aIsPrefixed = a.startsWith('-webkit-');
const bIsPrefixed = b.startsWith('-webkit-');
- if (aIsPrefixed && !bIsPrefixed)
+ if (aIsPrefixed && !bIsPrefixed) {
return 1;
- if (!aIsPrefixed && bIsPrefixed)
+ }
+ if (!aIsPrefixed && bIsPrefixed) {
return -1;
+ }
return a < b ? -1 : (a > b ? 1 : 0);
}
@@ -150,8 +156,7 @@ SDK.CSSMetadata = class {
* @return {boolean}
*/
isColorAwareProperty(propertyName) {
- return !!SDK.CSSMetadata._colorAwareProperties.has(propertyName.toLowerCase()) ||
- this.isCustomProperty(propertyName.toLowerCase());
+ return !!_colorAwareProperties.has(propertyName.toLowerCase()) || this.isCustomProperty(propertyName.toLowerCase());
}
/**
@@ -169,9 +174,10 @@ SDK.CSSMetadata = class {
*/
isLengthProperty(propertyName) {
propertyName = propertyName.toLowerCase();
- if (propertyName === 'line-height')
+ if (propertyName === 'line-height') {
return false;
- return SDK.CSSMetadata._distanceProperties.has(propertyName) || propertyName.startsWith('margin') ||
+ }
+ return _distanceProperties.has(propertyName) || propertyName.startsWith('margin') ||
propertyName.startsWith('padding') || propertyName.indexOf('width') !== -1 ||
propertyName.indexOf('height') !== -1;
}
@@ -182,7 +188,7 @@ SDK.CSSMetadata = class {
*/
isBezierAwareProperty(propertyName) {
propertyName = propertyName.toLowerCase();
- return !!SDK.CSSMetadata._bezierAwareProperties.has(propertyName) || this.isCustomProperty(propertyName);
+ return !!_bezierAwareProperties.has(propertyName) || this.isCustomProperty(propertyName);
}
/**
@@ -198,12 +204,17 @@ SDK.CSSMetadata = class {
* @return {string}
*/
canonicalPropertyName(name) {
+ if (this.isCustomProperty(name)) {
+ return name;
+ }
name = name.toLowerCase();
- if (!name || name.length < 9 || name.charAt(0) !== '-')
+ if (!name || name.length < 9 || name.charAt(0) !== '-') {
return name;
+ }
const match = name.match(/(?:-webkit-)(.+)/);
- if (!match || !this._valuesSet.has(match[1]))
+ if (!match || !this._valuesSet.has(match[1])) {
return name;
+ }
return match[1];
}
@@ -214,8 +225,9 @@ SDK.CSSMetadata = class {
isCSSPropertyName(propertyName) {
propertyName = propertyName.toLowerCase();
if (propertyName.startsWith('-moz-') || propertyName.startsWith('-o-') || propertyName.startsWith('-webkit-') ||
- propertyName.startsWith('-ms-'))
+ propertyName.startsWith('-ms-')) {
return true;
+ }
return this._valuesSet.has(propertyName);
}
@@ -235,11 +247,12 @@ SDK.CSSMetadata = class {
*/
_specificPropertyValues(propertyName) {
const unprefixedName = propertyName.replace(/^-webkit-/, '');
- const entry = SDK.CSSMetadata._propertyDataMap[propertyName] || SDK.CSSMetadata._propertyDataMap[unprefixedName];
+ const entry = _propertyDataMap[propertyName] || _propertyDataMap[unprefixedName];
const keywords = entry && entry.values ? entry.values.slice() : [];
for (const commonKeyword of ['auto', 'none']) {
- if (CSS.supports(propertyName, commonKeyword))
+ if (CSS.supports(propertyName, commonKeyword)) {
keywords.push(commonKeyword);
+ }
}
return keywords;
}
@@ -254,10 +267,11 @@ SDK.CSSMetadata = class {
acceptedKeywords.pushAll(this._specificPropertyValues(propertyName));
if (this.isColorAwareProperty(propertyName)) {
acceptedKeywords.push('currentColor');
- for (const color in Common.Color.Nicknames)
+ for (const color in Common.Color.Nicknames) {
acceptedKeywords.push(color);
+ }
}
- return acceptedKeywords.sort(SDK.CSSMetadata._sortPrefixesToEnd);
+ return acceptedKeywords.sort(CSSMetadata._sortPrefixesToEnd);
}
/**
@@ -265,7 +279,7 @@ SDK.CSSMetadata = class {
* @return {number}
*/
propertyUsageWeight(property) {
- return SDK.CSSMetadata.Weight[property] || SDK.CSSMetadata.Weight[this.canonicalPropertyName(property)] || 0;
+ return Weight[property] || Weight[this.canonicalPropertyName(property)] || 0;
}
/**
@@ -274,10 +288,11 @@ SDK.CSSMetadata = class {
* @return {?{text: string, startColumn: number, endColumn: number}}
*/
getValuePreset(key, value) {
- const values = SDK.CSSMetadata._valuePresets.get(key);
+ const values = _valuePresets.get(key);
let text = values ? values.get(value) : null;
- if (!text)
+ if (!text) {
return null;
+ }
let startColumn = text.length;
let endColumn = text.length;
if (text) {
@@ -288,10 +303,10 @@ SDK.CSSMetadata = class {
}
return {text, startColumn, endColumn};
}
-};
+}
-SDK.CSSMetadata.VariableRegex = /(var\(--.*?\))/g;
-SDK.CSSMetadata.URLRegex = /url\(\s*('.+?'|".+?"|[^)]+)\s*\)/g;
+export const VariableRegex = /(var\(--.*?\))/g;
+export const URLRegex = /url\(\s*('.+?'|".+?"|[^)]+)\s*\)/g;
/**
* Matches an instance of a grid area 'row' definition.
@@ -301,21 +316,22 @@ SDK.CSSMetadata.URLRegex = /url\(\s*('.+?'|".+?"|[^)]+)\s*\)/g;
* 'grid', 'grid-template', e.g.
* [track-name] "a a ." minmax(50px, auto) [track-name]
*/
-SDK.CSSMetadata.GridAreaRowRegex = /((?:\[[\w\- ]+\]\s*)*(?:"[^"]+"|'[^']+'))[^'"\[]*\[?[^'"\[]*/;
+export const GridAreaRowRegex = /((?:\[[\w\- ]+\]\s*)*(?:"[^"]+"|'[^']+'))[^'"\[]*\[?[^'"\[]*/;
/**
- * @return {!SDK.CSSMetadata}
+ * @return {!CSSMetadata}
*/
-SDK.cssMetadata = function() {
- if (!SDK.CSSMetadata._instance)
- SDK.CSSMetadata._instance = new SDK.CSSMetadata(SDK.CSSMetadata._generatedProperties || []);
- return SDK.CSSMetadata._instance;
-};
+export function cssMetadata() {
+ if (!CSSMetadata._instance) {
+ CSSMetadata._instance = new CSSMetadata(CSSMetadata._generatedProperties || []);
+ }
+ return CSSMetadata._instance;
+}
/**
* The pipe character '|' indicates where text selection should be set.
*/
-SDK.CSSMetadata._imageValuePresetMap = new Map([
+export const _imageValuePresetMap = new Map([
['linear-gradient', 'linear-gradient(|45deg, black, transparent|)'],
['radial-gradient', 'radial-gradient(|black, transparent|)'],
['repeating-linear-gradient', 'repeating-linear-gradient(|45deg, black, transparent 100px|)'],
@@ -323,7 +339,7 @@ SDK.CSSMetadata._imageValuePresetMap = new Map([
['url', 'url(||)'],
]);
-SDK.CSSMetadata._valuePresets = new Map([
+export const _valuePresets = new Map([
[
'filter', new Map([
['blur', 'blur(|1px|)'],
@@ -339,8 +355,8 @@ SDK.CSSMetadata._valuePresets = new Map([
['url', 'url(||)'],
])
],
- ['background', SDK.CSSMetadata._imageValuePresetMap], ['background-image', SDK.CSSMetadata._imageValuePresetMap],
- ['-webkit-mask-image', SDK.CSSMetadata._imageValuePresetMap],
+ ['background', _imageValuePresetMap], ['background-image', _imageValuePresetMap],
+ ['-webkit-mask-image', _imageValuePresetMap],
[
'transform', new Map([
['scale', 'scale(|1.5|)'],
@@ -367,18 +383,18 @@ SDK.CSSMetadata._valuePresets = new Map([
]
]);
-SDK.CSSMetadata._distanceProperties = new Set([
+export const _distanceProperties = new Set([
'background-position', 'border-spacing', 'bottom', 'font-size', 'height', 'left', 'letter-spacing', 'max-height',
'max-width', 'min-height', 'min-width', 'right', 'text-indent', 'top', 'width', 'word-spacing', 'grid-row-gap',
'grid-column-gap', 'row-gap'
]);
-SDK.CSSMetadata._bezierAwareProperties = new Set([
+export const _bezierAwareProperties = new Set([
'animation', 'animation-timing-function', 'transition', 'transition-timing-function', '-webkit-animation',
'-webkit-animation-timing-function', '-webkit-transition', '-webkit-transition-timing-function'
]);
-SDK.CSSMetadata._colorAwareProperties = new Set([
+export const _colorAwareProperties = new Set([
'backdrop-filter',
'background',
'background-color',
@@ -401,7 +417,6 @@ SDK.CSSMetadata._colorAwareProperties = new Set([
'column-rule',
'column-rule-color',
'fill',
- 'list-style',
'list-style-image',
'outline',
'outline-color',
@@ -433,7 +448,7 @@ SDK.CSSMetadata._colorAwareProperties = new Set([
'-webkit-text-stroke-color'
]);
-SDK.CSSMetadata._propertyDataMap = {
+export const _propertyDataMap = {
'table-layout': {values: ['fixed']},
'visibility': {values: ['hidden', 'visible', 'collapse']},
'background-repeat': {values: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space', 'round']},
@@ -1226,7 +1241,7 @@ SDK.CSSMetadata._propertyDataMap = {
};
// Weight of CSS properties based on their usage from https://www.chromestatus.com/metrics/css/popularity
-SDK.CSSMetadata.Weight = {
+export const Weight = {
'align-content': 57,
'align-items': 129,
'align-self': 55,
@@ -1481,3 +1496,25 @@ SDK.CSSMetadata.Weight = {
'z-index': 239,
'zoom': 200
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSMetadata = CSSMetadata;
+
+SDK.CSSMetadata.VariableRegex = VariableRegex;
+SDK.CSSMetadata.URLRegex = URLRegex;
+SDK.CSSMetadata.GridAreaRowRegex = GridAreaRowRegex;
+SDK.CSSMetadata._imageValuePresetMap = _imageValuePresetMap;
+SDK.CSSMetadata._valuePresets = _valuePresets;
+SDK.CSSMetadata._distanceProperties = _distanceProperties;
+SDK.CSSMetadata._bezierAwareProperties = _bezierAwareProperties;
+SDK.CSSMetadata._colorAwareProperties = _colorAwareProperties;
+SDK.CSSMetadata._propertyDataMap = _propertyDataMap;
+SDK.CSSMetadata.Weight = Weight;
+
+SDK.cssMetadata = cssMetadata; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSModel.js
index 755da8ed13a..3fece49cb56 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSModel.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-SDK.CSSModel = class extends SDK.SDKModel {
+export default class CSSModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -41,15 +41,16 @@ SDK.CSSModel = class extends SDK.SDKModel {
/** @type {!SDK.SourceMapManager<!SDK.CSSStyleSheetHeader>} */
this._sourceMapManager = new SDK.SourceMapManager(target);
this._agent = target.cssAgent();
- this._styleLoader = new SDK.CSSModel.ComputedStyleLoader(this);
+ this._styleLoader = new ComputedStyleLoader(this);
this._resourceTreeModel = target.model(SDK.ResourceTreeModel);
if (this._resourceTreeModel) {
this._resourceTreeModel.addEventListener(
SDK.ResourceTreeModel.Events.MainFrameNavigated, this._resetStyleSheets, this);
}
- target.registerCSSDispatcher(new SDK.CSSDispatcher(this));
- if (!target.suspended())
+ target.registerCSSDispatcher(new CSSDispatcher(this));
+ if (!target.suspended()) {
this._enable();
+ }
/** @type {!Map.<string, !SDK.CSSStyleSheetHeader>} */
this._styleSheetIdToHeader = new Map();
/** @type {!Map.<string, !Object.<!Protocol.Page.FrameId, !Array.<!Protocol.CSS.StyleSheetId>>>} */
@@ -67,6 +68,57 @@ SDK.CSSModel = class extends SDK.SDKModel {
}
/**
+ * @param {string} sourceURL
+ * @return {!Array<!SDK.CSSStyleSheetHeader>}
+ */
+ headersForSourceURL(sourceURL) {
+ const headers = [];
+ for (const headerId of this.styleSheetIdsForURL(sourceURL)) {
+ const header = this.styleSheetHeaderForId(headerId);
+ if (header) {
+ headers.push(header);
+ }
+ }
+ return headers;
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {!Array<!CSSLocation>}
+ */
+ createRawLocationsByURL(sourceURL, lineNumber, columnNumber) {
+ const headers = this.headersForSourceURL(sourceURL);
+ headers.sort(stylesheetComparator);
+ const compareToArgLocation = (_, header) => lineNumber - header.startLine || columnNumber - header.startColumn;
+ const endIndex = headers.upperBound(undefined, compareToArgLocation);
+ if (!endIndex) {
+ return [];
+ }
+ const locations = [];
+ const last = headers[endIndex - 1];
+ for (let index = endIndex - 1;
+ index >= 0 && headers[index].startLine === last.startLine && headers[index].startColumn === last.startColumn;
+ --index) {
+ if (headers[index].containsLocation(lineNumber, columnNumber)) {
+ locations.push(new SDK.CSSLocation(headers[index], lineNumber, columnNumber));
+ }
+ }
+
+
+ return locations;
+ /**
+ * @param {!SDK.CSSStyleSheetHeader} a
+ * @param {!SDK.CSSStyleSheetHeader} b
+ * @return {number}
+ */
+ function stylesheetComparator(a, b) {
+ return a.startLine - b.startLine || a.startColumn - b.startColumn || a.id.localeCompare(b.id);
+ }
+ }
+
+ /**
* @return {!SDK.SourceMapManager<!SDK.CSSStyleSheetHeader>}
*/
sourceMapManager() {
@@ -81,16 +133,19 @@ SDK.CSSModel = class extends SDK.SDKModel {
let sourceURLIndex = text.lastIndexOf('/*# sourceURL=');
if (sourceURLIndex === -1) {
sourceURLIndex = text.lastIndexOf('/*@ sourceURL=');
- if (sourceURLIndex === -1)
+ if (sourceURLIndex === -1) {
return text;
+ }
}
const sourceURLLineIndex = text.lastIndexOf('\n', sourceURLIndex);
- if (sourceURLLineIndex === -1)
+ if (sourceURLLineIndex === -1) {
return text;
+ }
const sourceURLLine = text.substr(sourceURLLineIndex + 1).split('\n', 1)[0];
const sourceURLRegex = /[\040\t]*\/\*[#@] sourceURL=[\040\t]*([^\s]*)[\040\t]*\*\/[\040\t]*$/;
- if (sourceURLLine.search(sourceURLRegex) === -1)
+ if (sourceURLLine.search(sourceURLRegex) === -1) {
return text;
+ }
return text.substr(0, sourceURLLineIndex) + text.substr(sourceURLLineIndex + sourceURLLine.length + 1);
}
@@ -114,11 +169,12 @@ SDK.CSSModel = class extends SDK.SDKModel {
const stylePayloads =
await this._agent.setStyleTexts([{styleSheetId: styleSheetId, range: range.serializeToObject(), text: text}]);
- if (!stylePayloads || stylePayloads.length !== 1)
+ if (!stylePayloads || stylePayloads.length !== 1) {
return false;
+ }
this._domModel.markUndoableState(!majorChange);
- const edit = new SDK.CSSModel.Edit(styleSheetId, range, text, stylePayloads[0]);
+ const edit = new Edit(styleSheetId, range, text, stylePayloads[0]);
this._fireStyleSheetChanged(styleSheetId, edit);
return true;
} catch (e) {
@@ -139,10 +195,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
await this._ensureOriginalStyleSheetText(styleSheetId);
const selectorPayload = await this._agent.setRuleSelector(styleSheetId, range, text);
- if (!selectorPayload)
+ if (!selectorPayload) {
return false;
+ }
this._domModel.markUndoableState();
- const edit = new SDK.CSSModel.Edit(styleSheetId, range, text, selectorPayload);
+ const edit = new Edit(styleSheetId, range, text, selectorPayload);
this._fireStyleSheetChanged(styleSheetId, edit);
return true;
} catch (e) {
@@ -163,10 +220,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
await this._ensureOriginalStyleSheetText(styleSheetId);
const payload = await this._agent.setKeyframeKey(styleSheetId, range, text);
- if (!payload)
+ if (!payload) {
return false;
+ }
this._domModel.markUndoableState();
- const edit = new SDK.CSSModel.Edit(styleSheetId, range, text, payload);
+ const edit = new Edit(styleSheetId, range, text, payload);
this._fireStyleSheetChanged(styleSheetId, edit);
return true;
} catch (e) {
@@ -215,9 +273,10 @@ SDK.CSSModel = class extends SDK.SDKModel {
async _enable() {
await this._agent.enable();
this._isEnabled = true;
- if (this._isRuleUsageTrackingEnabled)
+ if (this._isRuleUsageTrackingEnabled) {
await this.startCoverage();
- this.dispatchEventToListeners(SDK.CSSModel.Events.ModelWasEnabled);
+ }
+ this.dispatchEventToListeners(Events.ModelWasEnabled);
}
/**
@@ -227,12 +286,14 @@ SDK.CSSModel = class extends SDK.SDKModel {
async matchedStylesPromise(nodeId) {
const response = await this._agent.invoke_getMatchedStylesForNode({nodeId});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return null;
+ }
const node = this._domModel.nodeForId(nodeId);
- if (!node)
+ if (!node) {
return null;
+ }
return new SDK.CSSMatchedStyles(
this, /** @type {!SDK.DOMNode} */ (node), response.inlineStyle || null, response.attributesStyle || null,
@@ -258,12 +319,13 @@ SDK.CSSModel = class extends SDK.SDKModel {
/**
* @param {number} nodeId
- * @return {!Promise<?SDK.CSSModel.ContrastInfo>}
+ * @return {!Promise<?CSSModel.ContrastInfo>}
*/
async backgroundColorsPromise(nodeId) {
const response = this._agent.invoke_getBackgroundColors({nodeId});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return null;
+ }
return response;
}
@@ -287,10 +349,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
* @return {number}
*/
function styleSheetComparator(a, b) {
- if (a.sourceURL < b.sourceURL)
+ if (a.sourceURL < b.sourceURL) {
return -1;
- else if (a.sourceURL > b.sourceURL)
+ } else if (a.sourceURL > b.sourceURL) {
return 1;
+ }
return a.startLine - b.startLine || a.startColumn - b.startColumn;
}
values.sort(styleSheetComparator);
@@ -300,19 +363,20 @@ SDK.CSSModel = class extends SDK.SDKModel {
/**
* @param {!Protocol.DOM.NodeId} nodeId
- * @return {!Promise<?SDK.CSSModel.InlineStyleResult>}
+ * @return {!Promise<?InlineStyleResult>}
*/
async inlineStylesPromise(nodeId) {
const response = await this._agent.invoke_getInlineStylesForNode({nodeId});
- if (response[Protocol.Error] || !response.inlineStyle)
+ if (response[Protocol.Error] || !response.inlineStyle) {
return null;
+ }
const inlineStyle =
new SDK.CSSStyleDeclaration(this, null, response.inlineStyle, SDK.CSSStyleDeclaration.Type.Inline);
const attributesStyle = response.attributesStyle ?
new SDK.CSSStyleDeclaration(this, null, response.attributesStyle, SDK.CSSStyleDeclaration.Type.Attributes) :
null;
- return new SDK.CSSModel.InlineStyleResult(inlineStyle, attributesStyle);
+ return new InlineStyleResult(inlineStyle, attributesStyle);
}
/**
@@ -322,25 +386,27 @@ SDK.CSSModel = class extends SDK.SDKModel {
* @return {boolean}
*/
forcePseudoState(node, pseudoClass, enable) {
- const pseudoClasses = node.marker(SDK.CSSModel.PseudoStateMarker) || [];
+ const pseudoClasses = node.marker(PseudoStateMarker) || [];
if (enable) {
- if (pseudoClasses.indexOf(pseudoClass) >= 0)
+ if (pseudoClasses.indexOf(pseudoClass) >= 0) {
return false;
+ }
pseudoClasses.push(pseudoClass);
- node.setMarker(SDK.CSSModel.PseudoStateMarker, pseudoClasses);
+ node.setMarker(PseudoStateMarker, pseudoClasses);
} else {
- if (pseudoClasses.indexOf(pseudoClass) < 0)
+ if (pseudoClasses.indexOf(pseudoClass) < 0) {
return false;
+ }
pseudoClasses.remove(pseudoClass);
- if (pseudoClasses.length)
- node.setMarker(SDK.CSSModel.PseudoStateMarker, pseudoClasses);
- else
- node.setMarker(SDK.CSSModel.PseudoStateMarker, null);
+ if (pseudoClasses.length) {
+ node.setMarker(PseudoStateMarker, pseudoClasses);
+ } else {
+ node.setMarker(PseudoStateMarker, null);
+ }
}
this._agent.forcePseudoState(node.id, pseudoClasses);
- this.dispatchEventToListeners(
- SDK.CSSModel.Events.PseudoStateForced, {node: node, pseudoClass: pseudoClass, enable: enable});
+ this.dispatchEventToListeners(Events.PseudoStateForced, {node: node, pseudoClass: pseudoClass, enable: enable});
return true;
}
@@ -349,7 +415,7 @@ SDK.CSSModel = class extends SDK.SDKModel {
* @return {?Array<string>} state
*/
pseudoState(node) {
- return node.marker(SDK.CSSModel.PseudoStateMarker) || [];
+ return node.marker(PseudoStateMarker) || [];
}
/**
@@ -365,10 +431,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
await this._ensureOriginalStyleSheetText(styleSheetId);
const mediaPayload = await this._agent.setMediaText(styleSheetId, range, newMediaText);
- if (!mediaPayload)
+ if (!mediaPayload) {
return false;
+ }
this._domModel.markUndoableState();
- const edit = new SDK.CSSModel.Edit(styleSheetId, range, newMediaText, mediaPayload);
+ const edit = new Edit(styleSheetId, range, newMediaText, mediaPayload);
this._fireStyleSheetChanged(styleSheetId, edit);
return true;
} catch (e) {
@@ -387,10 +454,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
await this._ensureOriginalStyleSheetText(styleSheetId);
const rulePayload = await this._agent.addRule(styleSheetId, ruleText, ruleLocation);
- if (!rulePayload)
+ if (!rulePayload) {
return null;
+ }
this._domModel.markUndoableState();
- const edit = new SDK.CSSModel.Edit(styleSheetId, ruleLocation, ruleText, rulePayload);
+ const edit = new Edit(styleSheetId, ruleLocation, ruleText, rulePayload);
this._fireStyleSheetChanged(styleSheetId, edit);
return new SDK.CSSStyleRule(this, rulePayload);
} catch (e) {
@@ -406,8 +474,9 @@ SDK.CSSModel = class extends SDK.SDKModel {
const frameId = node.frameId() || (this._resourceTreeModel ? this._resourceTreeModel.mainFrame.id : '');
const headers = this._styleSheetIdToHeader.valuesArray();
const styleSheetHeader = headers.find(header => header.frameId === frameId && header.isViaInspector());
- if (styleSheetHeader)
+ if (styleSheetHeader) {
return styleSheetHeader;
+ }
try {
const styleSheetId = await this._agent.createStyleSheet(frameId);
@@ -418,11 +487,11 @@ SDK.CSSModel = class extends SDK.SDKModel {
}
mediaQueryResultChanged() {
- this.dispatchEventToListeners(SDK.CSSModel.Events.MediaQueryResultChanged);
+ this.dispatchEventToListeners(Events.MediaQueryResultChanged);
}
fontsUpdated() {
- this.dispatchEventToListeners(SDK.CSSModel.Events.FontsUpdated);
+ this.dispatchEventToListeners(Events.FontsUpdated);
}
/**
@@ -442,10 +511,10 @@ SDK.CSSModel = class extends SDK.SDKModel {
/**
* @param {!Protocol.CSS.StyleSheetId} styleSheetId
- * @param {!SDK.CSSModel.Edit=} edit
+ * @param {!Edit=} edit
*/
_fireStyleSheetChanged(styleSheetId, edit) {
- this.dispatchEventToListeners(SDK.CSSModel.Events.StyleSheetChanged, {styleSheetId: styleSheetId, edit: edit});
+ this.dispatchEventToListeners(Events.StyleSheetChanged, {styleSheetId: styleSheetId, edit: edit});
}
/**
@@ -454,8 +523,9 @@ SDK.CSSModel = class extends SDK.SDKModel {
*/
_ensureOriginalStyleSheetText(styleSheetId) {
const header = this.styleSheetHeaderForId(styleSheetId);
- if (!header)
+ if (!header) {
return Promise.resolve(/** @type {?string} */ (null));
+ }
let promise = this._originalStyleSheetText.get(header);
if (!promise) {
promise = this.getStyleSheetText(header.id);
@@ -487,8 +557,9 @@ SDK.CSSModel = class extends SDK.SDKModel {
const styleSheetHeader = new SDK.CSSStyleSheetHeader(this, header);
this._styleSheetIdToHeader.set(header.styleSheetId, styleSheetHeader);
const url = styleSheetHeader.resourceURL();
- if (!this._styleSheetIdsForURL.get(url))
+ if (!this._styleSheetIdsForURL.get(url)) {
this._styleSheetIdsForURL.set(url, {});
+ }
const frameIdToStyleSheetIds = this._styleSheetIdsForURL.get(url);
let styleSheetIds = frameIdToStyleSheetIds[styleSheetHeader.frameId];
if (!styleSheetIds) {
@@ -497,7 +568,7 @@ SDK.CSSModel = class extends SDK.SDKModel {
}
styleSheetIds.push(styleSheetHeader.id);
this._sourceMapManager.attachSourceMap(styleSheetHeader, styleSheetHeader.sourceURL, styleSheetHeader.sourceMapURL);
- this.dispatchEventToListeners(SDK.CSSModel.Events.StyleSheetAdded, styleSheetHeader);
+ this.dispatchEventToListeners(Events.StyleSheetAdded, styleSheetHeader);
}
/**
@@ -506,8 +577,9 @@ SDK.CSSModel = class extends SDK.SDKModel {
_styleSheetRemoved(id) {
const header = this._styleSheetIdToHeader.get(id);
console.assert(header);
- if (!header)
+ if (!header) {
return;
+ }
this._styleSheetIdToHeader.remove(id);
const url = header.resourceURL();
const frameIdToStyleSheetIds =
@@ -517,12 +589,13 @@ SDK.CSSModel = class extends SDK.SDKModel {
frameIdToStyleSheetIds[header.frameId].remove(id);
if (!frameIdToStyleSheetIds[header.frameId].length) {
delete frameIdToStyleSheetIds[header.frameId];
- if (!Object.keys(frameIdToStyleSheetIds).length)
+ if (!Object.keys(frameIdToStyleSheetIds).length) {
this._styleSheetIdsForURL.remove(url);
+ }
}
this._originalStyleSheetText.remove(header);
this._sourceMapManager.detachSourceMap(header);
- this.dispatchEventToListeners(SDK.CSSModel.Events.StyleSheetRemoved, header);
+ this.dispatchEventToListeners(Events.StyleSheetRemoved, header);
}
/**
@@ -531,12 +604,14 @@ SDK.CSSModel = class extends SDK.SDKModel {
*/
styleSheetIdsForURL(url) {
const frameIdToStyleSheetIds = this._styleSheetIdsForURL.get(url);
- if (!frameIdToStyleSheetIds)
+ if (!frameIdToStyleSheetIds) {
return [];
+ }
let result = [];
- for (const frameId in frameIdToStyleSheetIds)
+ for (const frameId in frameIdToStyleSheetIds) {
result = result.concat(frameIdToStyleSheetIds[frameId]);
+ }
return result;
}
@@ -549,9 +624,10 @@ SDK.CSSModel = class extends SDK.SDKModel {
async setStyleSheetText(styleSheetId, newText, majorChange) {
const header = /** @type {!SDK.CSSStyleSheetHeader} */ (this._styleSheetIdToHeader.get(styleSheetId));
console.assert(header);
- newText = SDK.CSSModel.trimSourceURL(newText);
- if (header.hasSourceURL)
+ newText = CSSModel.trimSourceURL(newText);
+ if (header.hasSourceURL) {
newText += '\n/*# sourceURL=' + header.sourceURL + ' */';
+ }
await this._ensureOriginalStyleSheetText(styleSheetId);
const response = await this._agent.invoke_setStyleSheetText({styleSheetId: header.id, text: newText});
@@ -560,8 +636,9 @@ SDK.CSSModel = class extends SDK.SDKModel {
this._sourceMapManager.detachSourceMap(header);
header.setSourceMapURL(sourceMapURL);
this._sourceMapManager.attachSourceMap(header, header.sourceURL, header.sourceMapURL);
- if (sourceMapURL === null)
+ if (sourceMapURL === null) {
return 'Error in CSS.setStyleSheetText';
+ }
this._domModel.markUndoableState(!majorChange);
this._fireStyleSheetChanged(styleSheetId);
return null;
@@ -574,7 +651,7 @@ SDK.CSSModel = class extends SDK.SDKModel {
async getStyleSheetText(styleSheetId) {
try {
const text = await this._agent.getStyleSheetText(styleSheetId);
- return text && SDK.CSSModel.trimSourceURL(text);
+ return text && CSSModel.trimSourceURL(text);
} catch (e) {
return null;
}
@@ -586,7 +663,7 @@ SDK.CSSModel = class extends SDK.SDKModel {
this._styleSheetIdToHeader.clear();
for (let i = 0; i < headers.length; ++i) {
this._sourceMapManager.detachSourceMap(headers[i]);
- this.dispatchEventToListeners(SDK.CSSModel.Events.StyleSheetRemoved, headers[i]);
+ this.dispatchEventToListeners(Events.StyleSheetRemoved, headers[i]);
}
}
@@ -621,11 +698,13 @@ SDK.CSSModel = class extends SDK.SDKModel {
* @return {!Promise.<?SDK.CSSMatchedStyles>}
*/
cachedMatchedCascadeForNode(node) {
- if (this._cachedMatchedCascadeNode !== node)
+ if (this._cachedMatchedCascadeNode !== node) {
this.discardCachedMatchedCascade();
+ }
this._cachedMatchedCascadeNode = node;
- if (!this._cachedMatchedCascadePromise)
+ if (!this._cachedMatchedCascadePromise) {
this._cachedMatchedCascadePromise = this.matchedStylesPromise(node.id);
+ }
return this._cachedMatchedCascadePromise;
}
@@ -641,18 +720,10 @@ SDK.CSSModel = class extends SDK.SDKModel {
super.dispose();
this._sourceMapManager.dispose();
}
-};
-
-SDK.SDKModel.register(SDK.CSSModel, SDK.Target.Capability.DOM, true);
-
-/** @typedef {!{range: !Protocol.CSS.SourceRange, styleSheetId: !Protocol.CSS.StyleSheetId, wasUsed: boolean}} */
-SDK.CSSModel.RuleUsage;
-
-/** @typedef {{backgroundColors: ?Array<string>, computedFontSize: string, computedFontWeights: string}} */
-SDK.CSSModel.ContrastInfo;
+}
/** @enum {symbol} */
-SDK.CSSModel.Events = {
+export const Events = {
FontsUpdated: Symbol('FontsUpdated'),
MediaQueryResultChanged: Symbol('MediaQueryResultChanged'),
ModelWasEnabled: Symbol('ModelWasEnabled'),
@@ -662,15 +733,14 @@ SDK.CSSModel.Events = {
StyleSheetRemoved: Symbol('StyleSheetRemoved')
};
-SDK.CSSModel.MediaTypes =
+export const MediaTypes =
['all', 'braille', 'embossed', 'handheld', 'print', 'projection', 'screen', 'speech', 'tty', 'tv'];
-
-SDK.CSSModel.PseudoStateMarker = 'pseudo-state-marker';
+export const PseudoStateMarker = 'pseudo-state-marker';
/**
* @unrestricted
*/
-SDK.CSSModel.Edit = class {
+export class Edit {
/**
* @param {!Protocol.CSS.StyleSheetId} styleSheetId
* @param {!TextUtils.TextRange} oldRange
@@ -684,9 +754,9 @@ SDK.CSSModel.Edit = class {
this.newText = newText;
this.payload = payload;
}
-};
+}
-SDK.CSSLocation = class {
+export class CSSLocation {
/**
* @param {!SDK.CSSStyleSheetHeader} header
* @param {number} lineNumber
@@ -701,7 +771,7 @@ SDK.CSSLocation = class {
}
/**
- * @return {!SDK.CSSModel}
+ * @return {!CSSModel}
*/
cssModel() {
return this._cssModel;
@@ -713,15 +783,15 @@ SDK.CSSLocation = class {
header() {
return this._cssModel.styleSheetHeaderForId(this.styleSheetId);
}
-};
+}
/**
* @implements {Protocol.CSSDispatcher}
* @unrestricted
*/
-SDK.CSSDispatcher = class {
+export class CSSDispatcher {
/**
- * @param {!SDK.CSSModel} cssModel
+ * @param {!CSSModel} cssModel
*/
constructor(cssModel) {
this._cssModel = cssModel;
@@ -764,14 +834,14 @@ SDK.CSSDispatcher = class {
styleSheetRemoved(id) {
this._cssModel._styleSheetRemoved(id);
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSModel.ComputedStyleLoader = class {
+export class ComputedStyleLoader {
/**
- * @param {!SDK.CSSModel} cssModel
+ * @param {!CSSModel} cssModel
*/
constructor(cssModel) {
this._cssModel = cssModel;
@@ -785,8 +855,9 @@ SDK.CSSModel.ComputedStyleLoader = class {
*/
computedStylePromise(nodeId) {
let promise = this._nodeIdToPromise.get(nodeId);
- if (promise)
+ if (promise) {
return promise;
+ }
promise = this._cssModel._agent.getComputedStyleForNode(nodeId).then(parsePayload.bind(this));
this._nodeIdToPromise.set(nodeId, promise);
return promise;
@@ -794,24 +865,26 @@ SDK.CSSModel.ComputedStyleLoader = class {
/**
* @param {?Array<!Protocol.CSS.CSSComputedStyleProperty>} computedPayload
* @return {?Map<string, string>}
- * @this {SDK.CSSModel.ComputedStyleLoader}
+ * @this {ComputedStyleLoader}
*/
function parsePayload(computedPayload) {
this._nodeIdToPromise.delete(nodeId);
- if (!computedPayload || !computedPayload.length)
+ if (!computedPayload || !computedPayload.length) {
return null;
+ }
const result = new Map();
- for (const property of computedPayload)
+ for (const property of computedPayload) {
result.set(property.name, property.value);
+ }
return result;
}
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSModel.InlineStyleResult = class {
+export class InlineStyleResult {
/**
* @param {?SDK.CSSStyleDeclaration} inlineStyle
* @param {?SDK.CSSStyleDeclaration} attributesStyle
@@ -820,4 +893,42 @@ SDK.CSSModel.InlineStyleResult = class {
this.inlineStyle = inlineStyle;
this.attributesStyle = attributesStyle;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSModel = CSSModel;
+
+/** @enum {symbol} */
+SDK.CSSModel.Events = Events;
+
+SDK.CSSModel.MediaTypes = MediaTypes;
+SDK.CSSModel.PseudoStateMarker = PseudoStateMarker;
+
+/** @constructor */
+SDK.CSSModel.Edit = Edit;
+
+/** @constructor */
+SDK.CSSModel.ComputedStyleLoader = ComputedStyleLoader;
+
+/** @constructor */
+SDK.CSSModel.InlineStyleResult = InlineStyleResult;
+
+/** @constructor */
+SDK.CSSLocation = CSSLocation;
+
+/** @constructor */
+SDK.CSSDispatcher = CSSDispatcher;
+
+SDK.SDKModel.register(SDK.CSSModel, SDK.Target.Capability.DOM, true);
+
+/** @typedef {!{range: !Protocol.CSS.SourceRange, styleSheetId: !Protocol.CSS.StyleSheetId, wasUsed: boolean}} */
+SDK.CSSModel.RuleUsage;
+
+/** @typedef {{backgroundColors: ?Array<string>, computedFontSize: string, computedFontWeight: string}} */
+SDK.CSSModel.ContrastInfo;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSProperty.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSProperty.js
index e386ab33bfc..36fe7eb6ae6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSProperty.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSProperty.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.CSSProperty = class {
+export default class CSSProperty {
/**
* @param {!SDK.CSSStyleDeclaration} ownerStyle
* @param {number} index
@@ -37,7 +37,7 @@ SDK.CSSProperty = class {
* @param {!SDK.CSSStyleDeclaration} ownerStyle
* @param {number} index
* @param {!Protocol.CSS.CSSProperty} payload
- * @return {!SDK.CSSProperty}
+ * @return {!CSSProperty}
*/
static parsePayload(ownerStyle, index, payload) {
// The following default field values are used in the payload:
@@ -45,24 +45,27 @@ SDK.CSSProperty = class {
// parsedOk: true
// implicit: false
// disabled: false
- const result = new SDK.CSSProperty(
+ const result = new CSSProperty(
ownerStyle, index, payload.name, payload.value, payload.important || false, payload.disabled || false,
('parsedOk' in payload) ? !!payload.parsedOk : true, !!payload.implicit, payload.text, payload.range);
return result;
}
_ensureRanges() {
- if (this._nameRange && this._valueRange)
+ if (this._nameRange && this._valueRange) {
return;
+ }
const range = this.range;
const text = this.text ? new TextUtils.Text(this.text) : null;
- if (!range || !text)
+ if (!range || !text) {
return;
+ }
const nameIndex = text.value().indexOf(this.name);
const valueIndex = text.value().lastIndexOf(this.value);
- if (nameIndex === -1 || valueIndex === -1 || nameIndex > valueIndex)
+ if (nameIndex === -1 || valueIndex === -1 || nameIndex > valueIndex) {
return;
+ }
const nameSourceRange = new TextUtils.SourceRange(nameIndex, this.name.length);
const valueSourceRange = new TextUtils.SourceRange(valueIndex, this.value.length);
@@ -107,10 +110,12 @@ SDK.CSSProperty = class {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.ownerStyle.styleSheetId !== edit.styleSheetId)
+ if (this.ownerStyle.styleSheetId !== edit.styleSheetId) {
return;
- if (this.range)
+ }
+ if (this.range) {
this.range = this.range.rebaseAfterTextEdit(edit.oldRange, edit.newRange);
+ }
}
/**
@@ -121,11 +126,13 @@ SDK.CSSProperty = class {
}
get propertyText() {
- if (this.text !== undefined)
+ if (this.text !== undefined) {
return this.text;
+ }
- if (this.name === '')
+ if (this.name === '') {
return '';
+ }
return this.name + ': ' + this.value + (this.important ? ' !important' : '') + ';';
}
@@ -143,17 +150,21 @@ SDK.CSSProperty = class {
* @return {!Promise.<boolean>}
*/
async setText(propertyText, majorChange, overwrite) {
- if (!this.ownerStyle)
+ if (!this.ownerStyle) {
return Promise.reject(new Error('No ownerStyle for property'));
+ }
- if (!this.ownerStyle.styleSheetId)
+ if (!this.ownerStyle.styleSheetId) {
return Promise.reject(new Error('No owner style id'));
+ }
- if (!this.range || !this.ownerStyle.range)
+ if (!this.range || !this.ownerStyle.range) {
return Promise.reject(new Error('Style not editable'));
+ }
- if (majorChange)
+ if (majorChange) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.StyleRuleEdited);
+ }
if (overwrite && propertyText === this.propertyText) {
this.ownerStyle.cssModel().domModel().markUndoableState(!majorChange);
@@ -168,7 +179,7 @@ SDK.CSSProperty = class {
const newStyleText = text.replaceRange(range, String.sprintf(';%s;', propertyText));
const tokenizerFactory = await self.runtime.extension(TextUtils.TokenizerFactory).instance();
- const styleText = SDK.CSSProperty._formatStyle(newStyleText, indentation, endIndentation, tokenizerFactory);
+ const styleText = CSSProperty._formatStyle(newStyleText, indentation, endIndentation, tokenizerFactory);
return this.ownerStyle.setText(styleText, majorChange);
}
@@ -181,8 +192,9 @@ SDK.CSSProperty = class {
*/
static _formatStyle(styleText, indentation, endIndentation, tokenizerFactory) {
const doubleIndent = indentation.substring(endIndentation.length) + indentation;
- if (indentation)
+ if (indentation) {
indentation = '\n' + indentation;
+ }
let result = '';
let propertyName = '';
let propertyText;
@@ -191,8 +203,9 @@ SDK.CSSProperty = class {
const tokenize = tokenizerFactory.createTokenizer('text/css');
tokenize('*{' + styleText + '}', processToken);
- if (insideProperty)
+ if (insideProperty) {
result += propertyText;
+ }
result = result.substring(2, result.length - 1).trimRight();
return result + (indentation ? '\n' + endIndentation : '');
@@ -215,11 +228,13 @@ SDK.CSSProperty = class {
propertyText = token;
} else if (token !== ';' || needsSemi) {
result += token;
- if (token.trim() && !(tokenType && tokenType.includes('css-comment')))
+ if (token.trim() && !(tokenType && tokenType.includes('css-comment'))) {
needsSemi = token !== ';';
+ }
}
- if (token === '{' && !tokenType)
+ if (token === '{' && !tokenType) {
needsSemi = false;
+ }
return;
}
@@ -228,16 +243,19 @@ SDK.CSSProperty = class {
needsSemi = false;
insideProperty = false;
propertyName = '';
- if (token === '}')
+ if (token === '}') {
result += '}';
+ }
} else {
if (SDK.cssMetadata().isGridAreaDefiningProperty(propertyName)) {
const rowResult = SDK.CSSMetadata.GridAreaRowRegex.exec(token);
- if (rowResult && rowResult.index === 0 && !propertyText.trimRight().endsWith(']'))
+ if (rowResult && rowResult.index === 0 && !propertyText.trimRight().endsWith(']')) {
propertyText = propertyText.trimRight() + '\n' + doubleIndent;
+ }
}
- if (!propertyName && token === ':')
+ if (!propertyName && token === ':') {
propertyName = propertyText;
+ }
propertyText += token;
}
}
@@ -248,8 +266,9 @@ SDK.CSSProperty = class {
*/
function isDisabledProperty(text) {
const colon = text.indexOf(':');
- if (colon === -1)
+ if (colon === -1) {
return false;
+ }
const propertyName = text.substring(2, colon).trim();
return SDK.cssMetadata().isCSSPropertyName(propertyName);
}
@@ -261,8 +280,9 @@ SDK.CSSProperty = class {
*/
_detectIndentation(text) {
const lines = text.split('\n');
- if (lines.length < 2)
+ if (lines.length < 2) {
return '';
+ }
return TextUtils.TextUtils.lineIndent(lines[1]);
}
@@ -282,12 +302,23 @@ SDK.CSSProperty = class {
* @return {!Promise.<boolean>}
*/
setDisabled(disabled) {
- if (!this.ownerStyle)
+ if (!this.ownerStyle) {
return Promise.resolve(false);
- if (disabled === this.disabled)
+ }
+ if (disabled === this.disabled) {
return Promise.resolve(true);
+ }
const propertyText = this.text.trim();
const text = disabled ? '/* ' + propertyText + ' */' : this.text.substring(2, propertyText.length - 2).trim();
return this.setText(text, true, true);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSProperty = CSSProperty;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSRule.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSRule.js
index bb866f919e3..9a861bc722c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSRule.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSRule.js
@@ -1,33 +1,11 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/**
- * @unrestricted
- */
-SDK.CSSValue = class {
- /**
- * @param {!Protocol.CSS.Value} payload
- */
- constructor(payload) {
- this.text = payload.text;
- if (payload.range)
- this.range = TextUtils.TextRange.fromObject(payload.range);
- }
-
- /**
- * @param {!SDK.CSSModel.Edit} edit
- */
- rebase(edit) {
- if (!this.range)
- return;
- this.range = this.range.rebaseAfterTextEdit(edit.oldRange, edit.newRange);
- }
-};
/**
* @unrestricted
*/
-SDK.CSSRule = class {
+export default class CSSRule {
/**
* @param {!SDK.CSSModel} cssModel
* @param {{style: !Protocol.CSS.CSSStyle, styleSheetId: (string|undefined), origin: !Protocol.CSS.StyleSheetOrigin}} payload
@@ -48,8 +26,9 @@ SDK.CSSRule = class {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.styleSheetId !== edit.styleSheetId)
+ if (this.styleSheetId !== edit.styleSheetId) {
return;
+ }
this.style.rebase(edit);
}
@@ -57,8 +36,9 @@ SDK.CSSRule = class {
* @return {string}
*/
resourceURL() {
- if (!this.styleSheetId)
+ if (!this.styleSheetId) {
return '';
+ }
const styleSheetHeader = this._cssModel.styleSheetHeaderForId(this.styleSheetId);
return styleSheetHeader.resourceURL();
}
@@ -97,12 +77,37 @@ SDK.CSSRule = class {
cssModel() {
return this._cssModel;
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSStyleRule = class extends SDK.CSSRule {
+export class CSSValue {
+ /**
+ * @param {!Protocol.CSS.Value} payload
+ */
+ constructor(payload) {
+ this.text = payload.text;
+ if (payload.range) {
+ this.range = TextUtils.TextRange.fromObject(payload.range);
+ }
+ }
+
+ /**
+ * @param {!SDK.CSSModel.Edit} edit
+ */
+ rebase(edit) {
+ if (!this.range) {
+ return;
+ }
+ this.range = this.range.rebaseAfterTextEdit(edit.oldRange, edit.newRange);
+ }
+}
+
+/**
+ * @unrestricted
+ */
+export class CSSStyleRule extends CSSRule {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSRule} payload
@@ -119,7 +124,7 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
/**
* @param {!SDK.CSSModel} cssModel
* @param {string} selectorText
- * @return {!SDK.CSSStyleRule}
+ * @return {!CSSStyleRule}
*/
static createDummyRule(cssModel, selectorText) {
const dummyPayload = {
@@ -128,17 +133,18 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
},
style: {styleSheetId: '0', range: new TextUtils.TextRange(0, 0, 0, 0), shorthandEntries: [], cssProperties: []}
};
- return new SDK.CSSStyleRule(cssModel, /** @type {!Protocol.CSS.CSSRule} */ (dummyPayload));
+ return new CSSStyleRule(cssModel, /** @type {!Protocol.CSS.CSSRule} */ (dummyPayload));
}
/**
* @param {!Protocol.CSS.SelectorList} selectorList
*/
_reinitializeSelectors(selectorList) {
- /** @type {!Array.<!SDK.CSSValue>} */
+ /** @type {!Array.<!CSSValue>} */
this.selectors = [];
- for (let i = 0; i < selectorList.selectors.length; ++i)
- this.selectors.push(new SDK.CSSValue(selectorList.selectors[i]));
+ for (let i = 0; i < selectorList.selectors.length; ++i) {
+ this.selectors.push(new CSSValue(selectorList.selectors[i]));
+ }
}
/**
@@ -147,11 +153,13 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
*/
setSelectorText(newSelector) {
const styleSheetId = this.styleSheetId;
- if (!styleSheetId)
+ if (!styleSheetId) {
throw 'No rule stylesheet id';
+ }
const range = this.selectorRange();
- if (!range)
+ if (!range) {
throw 'Rule selector is not editable';
+ }
return this._cssModel.setSelectorText(styleSheetId, range, newSelector);
}
@@ -167,8 +175,9 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
*/
selectorRange() {
const firstRange = this.selectors[0].range;
- if (!firstRange)
+ if (!firstRange) {
return null;
+ }
const lastRange = this.selectors.peekLast().range;
return new TextUtils.TextRange(
firstRange.startLine, firstRange.startColumn, lastRange.endLine, lastRange.endColumn);
@@ -180,8 +189,9 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
*/
lineNumberInSource(selectorIndex) {
const selector = this.selectors[selectorIndex];
- if (!selector || !selector.range || !this.styleSheetId)
+ if (!selector || !selector.range || !this.styleSheetId) {
return 0;
+ }
const styleSheetHeader = this._cssModel.styleSheetHeaderForId(this.styleSheetId);
return styleSheetHeader.lineNumberInSource(selector.range.startLine);
}
@@ -192,8 +202,9 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
*/
columnNumberInSource(selectorIndex) {
const selector = this.selectors[selectorIndex];
- if (!selector || !selector.range || !this.styleSheetId)
+ if (!selector || !selector.range || !this.styleSheetId) {
return undefined;
+ }
const styleSheetHeader = this._cssModel.styleSheetHeaderForId(this.styleSheetId);
console.assert(styleSheetHeader);
return styleSheetHeader.columnNumberInSource(selector.range.startLine, selector.range.startColumn);
@@ -204,55 +215,58 @@ SDK.CSSStyleRule = class extends SDK.CSSRule {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.styleSheetId !== edit.styleSheetId)
+ if (this.styleSheetId !== edit.styleSheetId) {
return;
+ }
if (this.selectorRange().equal(edit.oldRange)) {
this._reinitializeSelectors(/** @type {!Protocol.CSS.SelectorList} */ (edit.payload));
} else {
- for (let i = 0; i < this.selectors.length; ++i)
+ for (let i = 0; i < this.selectors.length; ++i) {
this.selectors[i].rebase(edit);
+ }
}
- for (const media of this.media)
+ for (const media of this.media) {
media.rebase(edit);
+ }
super.rebase(edit);
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSKeyframesRule = class {
+export class CSSKeyframesRule {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSKeyframesRule} payload
*/
constructor(cssModel, payload) {
this._cssModel = cssModel;
- this._animationName = new SDK.CSSValue(payload.animationName);
- this._keyframes = payload.keyframes.map(keyframeRule => new SDK.CSSKeyframeRule(cssModel, keyframeRule));
+ this._animationName = new CSSValue(payload.animationName);
+ this._keyframes = payload.keyframes.map(keyframeRule => new CSSKeyframeRule(cssModel, keyframeRule));
}
/**
- * @return {!SDK.CSSValue}
+ * @return {!CSSValue}
*/
name() {
return this._animationName;
}
/**
- * @return {!Array.<!SDK.CSSKeyframeRule>}
+ * @return {!Array.<!CSSKeyframeRule>}
*/
keyframes() {
return this._keyframes;
}
-};
+}
/**
* @unrestricted
*/
-SDK.CSSKeyframeRule = class extends SDK.CSSRule {
+export class CSSKeyframeRule extends CSSRule {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSKeyframeRule} payload
@@ -263,7 +277,7 @@ SDK.CSSKeyframeRule = class extends SDK.CSSRule {
}
/**
- * @return {!SDK.CSSValue}
+ * @return {!CSSValue}
*/
key() {
return this._keyText;
@@ -273,7 +287,7 @@ SDK.CSSKeyframeRule = class extends SDK.CSSRule {
* @param {!Protocol.CSS.Value} payload
*/
_reinitializeKey(payload) {
- this._keyText = new SDK.CSSValue(payload);
+ this._keyText = new CSSValue(payload);
}
/**
@@ -281,12 +295,14 @@ SDK.CSSKeyframeRule = class extends SDK.CSSRule {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.styleSheetId !== edit.styleSheetId || !this._keyText.range)
+ if (this.styleSheetId !== edit.styleSheetId || !this._keyText.range) {
return;
- if (edit.oldRange.equal(this._keyText.range))
+ }
+ if (edit.oldRange.equal(this._keyText.range)) {
this._reinitializeKey(/** @type {!Protocol.CSS.Value} */ (edit.payload));
- else
+ } else {
this._keyText.rebase(edit);
+ }
super.rebase(edit);
}
@@ -297,11 +313,34 @@ SDK.CSSKeyframeRule = class extends SDK.CSSRule {
*/
setKeyText(newKeyText) {
const styleSheetId = this.styleSheetId;
- if (!styleSheetId)
+ if (!styleSheetId) {
throw 'No rule stylesheet id';
+ }
const range = this._keyText.range;
- if (!range)
+ if (!range) {
throw 'Keyframe key is not editable';
+ }
return this._cssModel.setKeyframeKey(styleSheetId, range, newKeyText);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSRule = CSSRule;
+
+/** @constructor */
+SDK.CSSValue = CSSValue;
+
+/** @constructor */
+SDK.CSSStyleRule = CSSStyleRule;
+
+/** @constructor */
+SDK.CSSKeyframesRule = CSSKeyframesRule;
+
+/** @constructor */
+SDK.CSSKeyframeRule = CSSKeyframeRule; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
index d02bd35692a..a6e02f4be2a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
@@ -1,12 +1,13 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-SDK.CSSStyleDeclaration = class {
+
+export default class CSSStyleDeclaration {
/**
* @param {!SDK.CSSModel} cssModel
* @param {?SDK.CSSRule} parentRule
* @param {!Protocol.CSS.CSSStyle} payload
- * @param {!SDK.CSSStyleDeclaration.Type} type
+ * @param {!Type} type
*/
constructor(cssModel, parentRule, payload, type) {
this._cssModel = cssModel;
@@ -35,14 +36,16 @@ SDK.CSSStyleDeclaration = class {
* @param {!SDK.CSSModel.Edit} edit
*/
rebase(edit) {
- if (this.styleSheetId !== edit.styleSheetId || !this.range)
+ if (this.styleSheetId !== edit.styleSheetId || !this.range) {
return;
+ }
if (edit.oldRange.equal(this.range)) {
this._reinitialize(/** @type {!Protocol.CSS.CSSStyle} */ (edit.payload));
} else {
this.range = this.range.rebaseAfterTextEdit(edit.oldRange, edit.newRange);
- for (let i = 0; i < this._allProperties.length; ++i)
+ for (let i = 0; i < this._allProperties.length; ++i) {
this._allProperties[i].rebase(edit);
+ }
}
}
@@ -58,8 +61,9 @@ SDK.CSSStyleDeclaration = class {
this._shorthandIsImportant = new Set();
for (let i = 0; i < shorthandEntries.length; ++i) {
this._shorthandValues.set(shorthandEntries[i].name, shorthandEntries[i].value);
- if (shorthandEntries[i].important)
+ if (shorthandEntries[i].important) {
this._shorthandIsImportant.add(shorthandEntries[i].name);
+ }
}
this._allProperties = [];
@@ -77,8 +81,9 @@ SDK.CSSStyleDeclaration = class {
}
parseUnusedText.call(this, cssText, start.line, start.column, this.range.endLine, this.range.endColumn);
} else {
- for (const cssProperty of payload.cssProperties)
+ for (const cssProperty of payload.cssProperties) {
this._allProperties.push(SDK.CSSProperty.parsePayload(this, this._allProperties.length, cssProperty));
+ }
}
this._generateSyntheticPropertiesIfNeeded();
@@ -86,8 +91,9 @@ SDK.CSSStyleDeclaration = class {
this._activePropertyMap = new Map();
for (const property of this._allProperties) {
- if (!property.activeInStyle())
+ if (!property.activeInStyle()) {
continue;
+ }
this._activePropertyMap.set(property.name, property);
}
@@ -95,7 +101,7 @@ SDK.CSSStyleDeclaration = class {
this._leadingProperties = null;
/**
- * @this {SDK.CSSStyleDeclaration}
+ * @this {CSSStyleDeclaration}
* @param {!TextUtils.Text} cssText
* @param {number} startLine
* @param {number} startColumn
@@ -162,15 +168,18 @@ SDK.CSSStyleDeclaration = class {
}
_generateSyntheticPropertiesIfNeeded() {
- if (this.range)
+ if (this.range) {
return;
+ }
- if (!this._shorthandValues.size)
+ if (!this._shorthandValues.size) {
return;
+ }
const propertiesSet = new Set();
- for (const property of this._allProperties)
+ for (const property of this._allProperties) {
propertiesSet.add(property.name);
+ }
const generatedProperties = [];
// For style-based properties, generate shorthands with values when possible.
@@ -178,11 +187,13 @@ SDK.CSSStyleDeclaration = class {
// For style-based properties, try generating shorthands.
const shorthands = SDK.cssMetadata().shorthands(property.name) || [];
for (const shorthand of shorthands) {
- if (propertiesSet.has(shorthand))
- continue; // There already is a shorthand this longhands falls under.
+ if (propertiesSet.has(shorthand)) {
+ continue;
+ } // There already is a shorthand this longhands falls under.
const shorthandValue = this._shorthandValues.get(shorthand);
- if (!shorthandValue)
- continue; // Never generate synthetic shorthands when no value is available.
+ if (!shorthandValue) {
+ continue;
+ } // Never generate synthetic shorthands when no value is available.
// Generate synthetic shorthand we have a value for.
const shorthandImportance = !!this._shorthandIsImportant.has(shorthand);
@@ -207,8 +218,9 @@ SDK.CSSStyleDeclaration = class {
return !!property.range;
}
- if (this.range)
+ if (this.range) {
return this._allProperties.filter(propertyHasRange);
+ }
const leadingProperties = [];
for (const property of this._allProperties) {
@@ -220,8 +232,9 @@ SDK.CSSStyleDeclaration = class {
break;
}
}
- if (!belongToAnyShorthand)
+ if (!belongToAnyShorthand) {
leadingProperties.push(property);
+ }
}
return leadingProperties;
@@ -231,8 +244,9 @@ SDK.CSSStyleDeclaration = class {
* @return {!Array.<!SDK.CSSProperty>}
*/
leadingProperties() {
- if (!this._leadingProperties)
+ if (!this._leadingProperties) {
this._leadingProperties = this._computeLeadingProperties();
+ }
return this._leadingProperties;
}
@@ -305,8 +319,9 @@ SDK.CSSStyleDeclaration = class {
const result = [];
for (let i = 0; longhands && i < longhands.length; ++i) {
const property = this._activePropertyMap.get(longhands[i]);
- if (property)
+ if (property) {
result.push(property);
+ }
}
return result;
}
@@ -324,8 +339,9 @@ SDK.CSSStyleDeclaration = class {
*/
pastLastSourcePropertyIndex() {
for (let i = this.allProperties().length - 1; i >= 0; --i) {
- if (this.allProperties()[i].range)
+ if (this.allProperties()[i].range) {
return i + 1;
+ }
}
return 0;
}
@@ -356,8 +372,9 @@ SDK.CSSStyleDeclaration = class {
* @return {!Promise.<boolean>}
*/
setText(text, majorChange) {
- if (!this.range || !this.styleSheetId)
+ if (!this.range || !this.styleSheetId) {
return Promise.resolve(false);
+ }
return this._cssModel.setStyleText(this.styleSheetId, this.range, text, majorChange);
}
@@ -379,11 +396,23 @@ SDK.CSSStyleDeclaration = class {
appendProperty(name, value, userCallback) {
this.insertPropertyAt(this.allProperties().length, name, value, userCallback);
}
-};
+}
/** @enum {string} */
-SDK.CSSStyleDeclaration.Type = {
+export const Type = {
Regular: 'Regular',
Inline: 'Inline',
Attributes: 'Attributes'
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSStyleDeclaration = CSSStyleDeclaration;
+
+/** @enum {string} */
+SDK.CSSStyleDeclaration.Type = Type;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleSheetHeader.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleSheetHeader.js
index 7219fc6f6bc..fe65dc1de53 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleSheetHeader.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleSheetHeader.js
@@ -5,7 +5,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-SDK.CSSStyleSheetHeader = class {
+export default class CSSStyleSheetHeader {
/**
* @param {!SDK.CSSModel} cssModel
* @param {!Protocol.CSS.CSSStyleSheetHeader} payload
@@ -22,9 +22,12 @@ SDK.CSSStyleSheetHeader = class {
this.isInline = payload.isInline;
this.startLine = payload.startLine;
this.startColumn = payload.startColumn;
+ this.endLine = payload.endLine;
+ this.endColumn = payload.endColumn;
this.contentLength = payload.length;
- if (payload.ownerNode)
+ if (payload.ownerNode) {
this.ownerNode = new SDK.DeferredDOMNode(cssModel.target(), payload.ownerNode);
+ }
this.setSourceMapURL(payload.sourceMapURL);
}
@@ -33,9 +36,15 @@ SDK.CSSStyleSheetHeader = class {
*/
originalContentProvider() {
if (!this._originalContentProvider) {
- const lazyContent = this._cssModel.originalStyleSheetText.bind(this._cssModel, this);
- this._originalContentProvider = new Common.StaticContentProvider(
- this.contentURL(), this.contentType(), /** @type {function():!Promise<?string>} */ (lazyContent));
+ const lazyContent = /** @type {function():!Promise<!Common.DeferredContent>} */ (async () => {
+ const originalText = await this._cssModel.originalStyleSheetText(this);
+ if (!originalText) {
+ return {error: ls`Could not find the original style sheet.`, isEncoded: false};
+ }
+ return {content: originalText, isEncoded: false};
+ });
+ this._originalContentProvider =
+ new Common.StaticContentProvider(this.contentURL(), this.contentType(), lazyContent);
}
return this._originalContentProvider;
}
@@ -76,8 +85,9 @@ SDK.CSSStyleSheetHeader = class {
console.assert(frame);
const parsedURL = new Common.ParsedURL(frame.url);
let fakeURL = 'inspector://' + parsedURL.host + parsedURL.folderPathComponents;
- if (!fakeURL.endsWith('/'))
+ if (!fakeURL.endsWith('/')) {
fakeURL += '/';
+ }
fakeURL += 'inspector-stylesheet';
return fakeURL;
}
@@ -100,6 +110,20 @@ SDK.CSSStyleSheetHeader = class {
}
/**
+ * Checks whether the position is in this style sheet. Assumes that the
+ * position's columnNumber is consistent with line endings.
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {boolean}
+ */
+ containsLocation(lineNumber, columnNumber) {
+ const afterStart =
+ (lineNumber === this.startLine && columnNumber >= this.startColumn) || lineNumber > this.startLine;
+ const beforeEnd = lineNumber < this.endLine || (lineNumber === this.endLine && columnNumber <= this.endColumn);
+ return afterStart && beforeEnd;
+ }
+
+ /**
* @override
* @return {string}
*/
@@ -125,10 +149,18 @@ SDK.CSSStyleSheetHeader = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
- requestContent() {
- return this._cssModel.getStyleSheetText(this.id);
+ async requestContent() {
+ try {
+ const cssText = await this._cssModel.getStyleSheetText(this.id);
+ return {content: /** @type{string} */ (cssText), isEncoded: false};
+ } catch (err) {
+ return {
+ error: ls`There was an error retrieving the source styles.`,
+ isEncoded: false,
+ };
+ }
}
/**
@@ -139,8 +171,8 @@ SDK.CSSStyleSheetHeader = class {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- const content = await this.requestContent();
- return Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
+ const {content} = await this.requestContent();
+ return Common.ContentProvider.performSearchInContent(content || '', query, caseSensitive, isRegex);
}
/**
@@ -149,4 +181,13 @@ SDK.CSSStyleSheetHeader = class {
isViaInspector() {
return this.origin === 'inspector';
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CSSStyleSheetHeader = CSSStyleSheetHeader;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
index 15bb50c56f3..e5c75ee8222 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+export let _lastAnonymousTargetId = 0;
+
/**
* @implements {Protocol.TargetDispatcher}
*/
-SDK.ChildTargetManager = class extends SDK.SDKModel {
+export default class ChildTargetManager extends SDK.SDKModel {
/**
* @param {!SDK.Target} parentTarget
*/
@@ -63,8 +65,9 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @override
*/
dispose() {
- for (const sessionId of this._childTargets.keys())
+ for (const sessionId of this._childTargets.keys()) {
this.detachedFromTarget(sessionId, undefined);
+ }
}
/**
@@ -112,8 +115,9 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @return {!Promise<string>}
*/
async _getParentTargetId() {
- if (!this._parentTargetId)
+ if (!this._parentTargetId) {
this._parentTargetId = (await this._parentTarget.targetAgent().getTargetInfo()).targetId;
+ }
return this._parentTargetId;
}
@@ -124,28 +128,30 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
* @param {boolean} waitingForDebugger
*/
attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
- if (this._parentTargetId === targetInfo.targetId)
+ if (this._parentTargetId === targetInfo.targetId) {
return;
+ }
let targetName = '';
if (targetInfo.type === 'worker' && targetInfo.title && targetInfo.title !== targetInfo.url) {
targetName = targetInfo.title;
} else if (targetInfo.type !== 'iframe') {
const parsedURL = targetInfo.url.asParsedURL();
- targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() :
- '#' + (++SDK.ChildTargetManager._lastAnonymousTargetId);
+ targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() : '#' + (++_lastAnonymousTargetId);
}
let type = SDK.Target.Type.Browser;
- if (targetInfo.type === 'iframe')
+ if (targetInfo.type === 'iframe') {
type = SDK.Target.Type.Frame;
+ }
// TODO(lfg): ensure proper capabilities for child pages (e.g. portals).
- else if (targetInfo.type === 'page')
+ else if (targetInfo.type === 'page') {
type = SDK.Target.Type.Frame;
- else if (targetInfo.type === 'worker')
+ } else if (targetInfo.type === 'worker') {
type = SDK.Target.Type.Worker;
- else if (targetInfo.type === 'service_worker')
+ } else if (targetInfo.type === 'service_worker') {
type = SDK.Target.Type.ServiceWorker;
+ }
const target =
this._targetManager.createTarget(targetInfo.targetId, targetName, type, this._parentTarget, sessionId);
@@ -185,7 +191,7 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
}
/**
- * @param {function(!Object)} onMessage
+ * @param {function((!Object|string))} onMessage
* @return {!Promise<!Protocol.Connection>}
*/
async createParallelConnection(onMessage) {
@@ -207,18 +213,27 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
async _createParallelConnectionAndSessionForTarget(target, targetId) {
const targetAgent = target.targetAgent();
const targetRouter = target.router();
- const sessionId = await targetAgent.attachToTarget(targetId, true /* flatten */);
+ const sessionId = /** @type {string} */ (await targetAgent.attachToTarget(targetId, true /* flatten */));
const connection = new SDK.ParallelConnection(targetRouter.connection(), sessionId);
targetRouter.registerSession(target, sessionId, connection);
- connection.setOnDisconnect(async () => {
- await targetAgent.detachFromTarget(sessionId);
+ connection.setOnDisconnect(() => {
+ targetAgent.detachFromTarget(sessionId);
targetRouter.unregisterSession(sessionId);
});
return {connection, sessionId};
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ChildTargetManager = ChildTargetManager;
-SDK.ChildTargetManager._lastAnonymousTargetId = 0;
+SDK.ChildTargetManager._lastAnonymousTargetId = _lastAnonymousTargetId;
/** @type {function({target: !SDK.Target, waitingForDebugger: boolean})|undefined} */
-SDK.ChildTargetManager._attachCallback;
+SDK.ChildTargetManager._attachCallback; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ContentProviders.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CompilerSourceMappingContentProvider.js
index 5cd03c9f160..c4a0b02b2bd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ContentProviders.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CompilerSourceMappingContentProvider.js
@@ -31,7 +31,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-SDK.CompilerSourceMappingContentProvider = class {
+export class CompilerSourceMappingContentProvider {
/**
* @param {string} sourceURL
* @param {!Common.ResourceType} contentType
@@ -67,31 +67,28 @@ SDK.CompilerSourceMappingContentProvider = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
- let callback;
- const promise = new Promise(fulfill => callback = fulfill);
- SDK.multitargetNetworkManager.loadResource(this._sourceURL, contentLoaded.bind(this));
- return promise;
-
- /**
- * @param {number} statusCode
- * @param {!Object.<string, string>} headers
- * @param {string} content
- * @this {SDK.CompilerSourceMappingContentProvider}
- */
- function contentLoaded(statusCode, headers, content) {
- if (statusCode >= 400) {
- console.error(
- 'Could not load content for ' + this._sourceURL + ' : ' +
- 'HTTP status code: ' + statusCode);
- callback(null);
- return;
- }
-
- callback(content);
- }
+ return new Promise(resolve => {
+ SDK.multitargetNetworkManager.loadResource(
+ this._sourceURL,
+ /**
+ * @param {number} statusCode
+ * @param {!Object.<string, string>} _headers (unused)
+ * @param {string} content
+ * @this {SDK.CompilerSourceMappingContentProvider}
+ */
+ (statusCode, _headers, content) => {
+ if (statusCode >= 400) {
+ const error = ls`Could not load content for ${this._sourceURL} : HTTP status code: ${statusCode}`;
+ console.error(error);
+ resolve({error, isEncoded: false});
+ } else {
+ resolve({content, isEncoded: false});
+ }
+ });
+ });
}
/**
@@ -102,9 +99,19 @@ SDK.CompilerSourceMappingContentProvider = class {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- const content = await this.requestContent();
- if (typeof content !== 'string')
+ const {content} = await this.requestContent();
+ if (typeof content !== 'string') {
return [];
+ }
return Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CompilerSourceMappingContentProvider = CompilerSourceMappingContentProvider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Connections.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Connections.js
index be2a939df34..ebc594873b4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Connections.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Connections.js
@@ -5,17 +5,17 @@
/**
* @implements {Protocol.Connection}
*/
-SDK.MainConnection = class {
+export class MainConnection {
constructor() {
this._onMessage = null;
this._onDisconnect = null;
this._messageBuffer = '';
this._messageSize = 0;
this._eventListeners = [
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DispatchMessage, this._dispatchMessage, this),
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.DispatchMessageChunk, this._dispatchMessageChunk, this),
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DispatchMessage, this._dispatchMessage, this),
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.DispatchMessageChunk, this._dispatchMessageChunk, this),
];
}
@@ -40,16 +40,18 @@ SDK.MainConnection = class {
* @param {string} message
*/
sendRawMessage(message) {
- if (this._onMessage)
- InspectorFrontendHost.sendMessageToBackend(message);
+ if (this._onMessage) {
+ Host.InspectorFrontendHost.sendMessageToBackend(message);
+ }
}
/**
* @param {!Common.Event} event
*/
_dispatchMessage(event) {
- if (this._onMessage)
+ if (this._onMessage) {
this._onMessage.call(null, /** @type {string} */ (event.data));
+ }
}
/**
@@ -80,16 +82,17 @@ SDK.MainConnection = class {
this._onDisconnect = null;
this._onMessage = null;
- if (onDisconnect)
+ if (onDisconnect) {
onDisconnect.call(null, 'force disconnect');
+ }
return Promise.resolve();
}
-};
+}
/**
* @implements {Protocol.Connection}
*/
-SDK.WebSocketConnection = class {
+export class WebSocketConnection {
/**
* @param {string} url
* @param {function()} onWebSocketDisconnect
@@ -99,8 +102,9 @@ SDK.WebSocketConnection = class {
this._socket.onerror = this._onError.bind(this);
this._socket.onopen = this._onOpen.bind(this);
this._socket.onmessage = messageEvent => {
- if (this._onMessage)
+ if (this._onMessage) {
this._onMessage.call(null, /** @type {string} */ (messageEvent.data));
+ }
};
this._socket.onclose = this._onClose.bind(this);
@@ -137,8 +141,9 @@ SDK.WebSocketConnection = class {
_onOpen() {
this._socket.onerror = console.error;
this._connected = true;
- for (const message of this._messages)
+ for (const message of this._messages) {
this._socket.send(message);
+ }
this._messages = [];
}
@@ -166,10 +171,11 @@ SDK.WebSocketConnection = class {
* @param {string} message
*/
sendRawMessage(message) {
- if (this._connected)
+ if (this._connected) {
this._socket.send(message);
- else
+ } else {
this._messages.push(message);
+ }
}
/**
@@ -180,18 +186,19 @@ SDK.WebSocketConnection = class {
let fulfill;
const promise = new Promise(f => fulfill = f);
this._close(() => {
- if (this._onDisconnect)
+ if (this._onDisconnect) {
this._onDisconnect.call(null, 'force disconnect');
+ }
fulfill();
});
return promise;
}
-};
+}
/**
* @implements {Protocol.Connection}
*/
-SDK.StubConnection = class {
+export class StubConnection {
constructor() {
this._onMessage = null;
this._onDisconnect = null;
@@ -231,8 +238,9 @@ SDK.StubConnection = class {
code: Protocol.DevToolsStubErrorCode,
data: messageObject
};
- if (this._onMessage)
+ if (this._onMessage) {
this._onMessage.call(null, {id: messageObject.id, error: error});
+ }
}
/**
@@ -240,18 +248,19 @@ SDK.StubConnection = class {
* @return {!Promise}
*/
disconnect() {
- if (this._onDisconnect)
+ if (this._onDisconnect) {
this._onDisconnect.call(null, 'force disconnect');
+ }
this._onDisconnect = null;
this._onMessage = null;
return Promise.resolve();
}
-};
+}
/**
* @implements {Protocol.Connection}
*/
-SDK.ParallelConnection = class {
+export class ParallelConnection {
/**
* @param {!Protocol.Connection} connection
* @param {string} sessionId
@@ -285,7 +294,10 @@ SDK.ParallelConnection = class {
*/
sendRawMessage(message) {
const messageObject = JSON.parse(message);
- messageObject.sessionId = this._sessionId;
+ // If the message isn't for a specific session, it must be for the root session.
+ if (!messageObject.sessionId) {
+ messageObject.sessionId = this._sessionId;
+ }
this._connection.sendRawMessage(JSON.stringify(messageObject));
}
@@ -294,39 +306,65 @@ SDK.ParallelConnection = class {
* @return {!Promise}
*/
disconnect() {
- if (this._onDisconnect)
+ if (this._onDisconnect) {
this._onDisconnect.call(null, 'force disconnect');
+ }
this._onDisconnect = null;
this._onMessage = null;
return Promise.resolve();
}
-};
+}
/**
* @param {function():!Promise<undefined>} createMainTarget
* @param {function()} websocketConnectionLost
* @return {!Promise}
*/
-SDK.initMainConnection = async function(createMainTarget, websocketConnectionLost) {
- Protocol.Connection.setFactory(SDK._createMainConnection.bind(null, websocketConnectionLost));
+export async function initMainConnection(createMainTarget, websocketConnectionLost) {
+ Protocol.Connection.setFactory(_createMainConnection.bind(null, websocketConnectionLost));
await createMainTarget();
- InspectorFrontendHost.connectionReady();
+ Host.InspectorFrontendHost.connectionReady();
+ Host.InspectorFrontendHost.events.addEventListener(Host.InspectorFrontendHostAPI.Events.ReattachMainTarget, () => {
+ SDK.targetManager.mainTarget().router().connection().disconnect();
+ createMainTarget();
+ });
return Promise.resolve();
-};
+}
/**
* @param {function()} websocketConnectionLost
* @return {!Protocol.Connection}
*/
-SDK._createMainConnection = function(websocketConnectionLost) {
- const wsParam = Runtime.queryParam('ws');
- const wssParam = Runtime.queryParam('wss');
+export function _createMainConnection(websocketConnectionLost) {
+ const wsParam = Root.Runtime.queryParam('ws');
+ const wssParam = Root.Runtime.queryParam('wss');
if (wsParam || wssParam) {
const ws = wsParam ? `ws://${wsParam}` : `wss://${wssParam}`;
- return new SDK.WebSocketConnection(ws, websocketConnectionLost);
- } else if (InspectorFrontendHost.isHostedMode()) {
- return new SDK.StubConnection();
+ return new WebSocketConnection(ws, websocketConnectionLost);
+ } else if (Host.InspectorFrontendHost.isHostedMode()) {
+ return new StubConnection();
}
- return new SDK.MainConnection();
-};
+ return new MainConnection();
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.MainConnection = MainConnection;
+
+/** @constructor */
+SDK.WebSocketConnection = WebSocketConnection;
+
+/** @constructor */
+SDK.StubConnection = StubConnection;
+
+/** @constructor */
+SDK.ParallelConnection = ParallelConnection;
+
+SDK.initMainConnection = initMainConnection;
+SDK._createMainConnection = _createMainConnection; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js
index e77e21b3fd3..391e0887b4a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js
@@ -28,16 +28,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+export const _events = Symbol('SDK.ConsoleModel.events');
+
/**
* @implements {SDK.TargetManager.Observer}
*/
-SDK.ConsoleModel = class extends Common.Object {
+export default class ConsoleModel extends Common.Object {
constructor() {
super();
- /** @type {!Array.<!SDK.ConsoleMessage>} */
+ /** @type {!Array.<!ConsoleMessage>} */
this._messages = [];
- /** @type {!Map<!SDK.RuntimeModel, !Map<number, !SDK.ConsoleMessage>>} */
+ /** @type {!Map<!SDK.RuntimeModel, !Map<number, !ConsoleMessage>>} */
this._messageByExceptionId = new Map();
this._warnings = 0;
this._errors = 0;
@@ -101,7 +103,7 @@ SDK.ConsoleModel = class extends Common.Object {
SDK.RuntimeModel.Events.QueryObjectRequested, this._queryObjectRequested.bind(this, runtimeModel)));
}
- target[SDK.ConsoleModel._events] = eventListeners;
+ target[_events] = eventListeners;
}
/**
@@ -110,14 +112,15 @@ SDK.ConsoleModel = class extends Common.Object {
*/
targetRemoved(target) {
const runtimeModel = target.model(SDK.RuntimeModel);
- if (runtimeModel)
+ if (runtimeModel) {
this._messageByExceptionId.delete(runtimeModel);
- Common.EventTarget.removeEventListeners(target[SDK.ConsoleModel._events] || []);
+ }
+ Common.EventTarget.removeEventListeners(target[_events] || []);
}
/**
* @param {!SDK.ExecutionContext} executionContext
- * @param {!SDK.ConsoleMessage} originatingMessage
+ * @param {!ConsoleMessage} originatingMessage
* @param {string} expression
* @param {boolean} useCommandLineAPI
* @param {boolean} awaitPromise
@@ -134,35 +137,36 @@ SDK.ConsoleModel = class extends Common.Object {
},
Common.settings.moduleSetting('consoleUserActivationEval').get(), awaitPromise);
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConsoleEvaluated);
- if (result.error)
+ if (result.error) {
return;
+ }
await Common.console.showPromise();
this.dispatchEventToListeners(
- SDK.ConsoleModel.Events.CommandEvaluated,
+ Events.CommandEvaluated,
{result: result.object, commandMessage: originatingMessage, exceptionDetails: result.exceptionDetails});
}
/**
* @param {!SDK.ExecutionContext} executionContext
* @param {string} text
- * @return {!SDK.ConsoleMessage}
+ * @return {!ConsoleMessage}
*/
addCommandMessage(executionContext, text) {
- const commandMessage = new SDK.ConsoleMessage(
- executionContext.runtimeModel, SDK.ConsoleMessage.MessageSource.JS, null, text,
- SDK.ConsoleMessage.MessageType.Command);
+ const commandMessage =
+ new ConsoleMessage(executionContext.runtimeModel, MessageSource.JS, null, text, MessageType.Command);
commandMessage.setExecutionContextId(executionContext.id);
this.addMessage(commandMessage);
return commandMessage;
}
/**
- * @param {!SDK.ConsoleMessage} msg
+ * @param {!ConsoleMessage} msg
*/
addMessage(msg) {
msg._pageLoadSequenceNumber = this._pageLoadSequenceNumber;
- if (msg.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI && msg.type === SDK.ConsoleMessage.MessageType.Clear)
+ if (msg.source === MessageSource.ConsoleAPI && msg.type === MessageType.Clear) {
this._clearIfNecessary();
+ }
this._messages.push(msg);
const runtimeModel = msg.runtimeModel();
@@ -175,7 +179,7 @@ SDK.ConsoleModel = class extends Common.Object {
modelMap.set(msg._exceptionId, msg);
}
this._incrementErrorWarningCount(msg);
- this.dispatchEventToListeners(SDK.ConsoleModel.Events.MessageAdded, msg);
+ this.dispatchEventToListeners(Events.MessageAdded, msg);
}
/**
@@ -184,7 +188,7 @@ SDK.ConsoleModel = class extends Common.Object {
*/
_exceptionThrown(runtimeModel, event) {
const exceptionWithTimestamp = /** @type {!SDK.RuntimeModel.ExceptionWithTimestamp} */ (event.data);
- const consoleMessage = SDK.ConsoleMessage.fromException(
+ const consoleMessage = ConsoleMessage.fromException(
runtimeModel, exceptionWithTimestamp.details, undefined, exceptionWithTimestamp.timestamp, undefined);
consoleMessage.setExceptionId(exceptionWithTimestamp.details.exceptionId);
this.addMessage(consoleMessage);
@@ -198,11 +202,12 @@ SDK.ConsoleModel = class extends Common.Object {
const exceptionId = /** @type {number} */ (event.data);
const modelMap = this._messageByExceptionId.get(runtimeModel);
const exceptionMessage = modelMap ? modelMap.get(exceptionId) : null;
- if (!exceptionMessage)
+ if (!exceptionMessage) {
return;
+ }
this._errors--;
- exceptionMessage.level = SDK.ConsoleMessage.MessageLevel.Verbose;
- this.dispatchEventToListeners(SDK.ConsoleModel.Events.MessageUpdated, exceptionMessage);
+ exceptionMessage.level = MessageLevel.Verbose;
+ this.dispatchEventToListeners(Events.MessageUpdated, exceptionMessage);
}
/**
@@ -211,25 +216,27 @@ SDK.ConsoleModel = class extends Common.Object {
*/
_consoleAPICalled(runtimeModel, event) {
const call = /** @type {!SDK.RuntimeModel.ConsoleAPICall} */ (event.data);
- let level = SDK.ConsoleMessage.MessageLevel.Info;
- if (call.type === SDK.ConsoleMessage.MessageType.Debug)
- level = SDK.ConsoleMessage.MessageLevel.Verbose;
- else if (call.type === SDK.ConsoleMessage.MessageType.Error || call.type === SDK.ConsoleMessage.MessageType.Assert)
- level = SDK.ConsoleMessage.MessageLevel.Error;
- else if (call.type === SDK.ConsoleMessage.MessageType.Warning)
- level = SDK.ConsoleMessage.MessageLevel.Warning;
- else if (call.type === SDK.ConsoleMessage.MessageType.Info || call.type === SDK.ConsoleMessage.MessageType.Log)
- level = SDK.ConsoleMessage.MessageLevel.Info;
+ let level = MessageLevel.Info;
+ if (call.type === MessageType.Debug) {
+ level = MessageLevel.Verbose;
+ } else if (call.type === MessageType.Error || call.type === MessageType.Assert) {
+ level = MessageLevel.Error;
+ } else if (call.type === MessageType.Warning) {
+ level = MessageLevel.Warning;
+ } else if (call.type === MessageType.Info || call.type === MessageType.Log) {
+ level = MessageLevel.Info;
+ }
let message = '';
- if (call.args.length && call.args[0].unserializableValue)
+ if (call.args.length && call.args[0].unserializableValue) {
message = call.args[0].unserializableValue;
- else if (call.args.length && (typeof call.args[0].value !== 'object' || call.args[0].value === null))
+ } else if (call.args.length && (typeof call.args[0].value !== 'object' || call.args[0].value === null)) {
message = call.args[0].value + '';
- else if (call.args.length && call.args[0].description)
+ } else if (call.args.length && call.args[0].description) {
message = call.args[0].description;
+ }
const callFrame = call.stackTrace && call.stackTrace.callFrames.length ? call.stackTrace.callFrames[0] : null;
- const consoleMessage = new SDK.ConsoleMessage(
- runtimeModel, SDK.ConsoleMessage.MessageSource.ConsoleAPI, level,
+ const consoleMessage = new ConsoleMessage(
+ runtimeModel, MessageSource.ConsoleAPI, level,
/** @type {string} */ (message), call.type, callFrame ? callFrame.url : undefined,
callFrame ? callFrame.lineNumber : undefined, callFrame ? callFrame.columnNumber : undefined, call.args,
call.stackTrace, call.timestamp, call.executionContextId, undefined, undefined, call.context);
@@ -241,15 +248,16 @@ SDK.ConsoleModel = class extends Common.Object {
* @param {!Common.Event} event
*/
_queryObjectRequested(runtimeModel, event) {
- const consoleMessage = new SDK.ConsoleMessage(
- runtimeModel, SDK.ConsoleMessage.MessageSource.ConsoleAPI, SDK.ConsoleMessage.MessageLevel.Info, '',
- SDK.ConsoleMessage.MessageType.QueryObjectResult, undefined, undefined, undefined, [event.data.objects]);
+ const consoleMessage = new ConsoleMessage(
+ runtimeModel, MessageSource.ConsoleAPI, MessageLevel.Info, '', MessageType.QueryObjectResult, undefined,
+ undefined, undefined, [event.data.objects]);
this.addMessage(consoleMessage);
}
_clearIfNecessary() {
- if (!Common.moduleSetting('preserveConsoleLog').get())
+ if (!Common.moduleSetting('preserveConsoleLog').get()) {
this._clear();
+ }
++this._pageLoadSequenceNumber;
}
@@ -257,8 +265,9 @@ SDK.ConsoleModel = class extends Common.Object {
* @param {!Common.Event} event
*/
_mainFrameNavigated(event) {
- if (Common.moduleSetting('preserveConsoleLog').get())
+ if (Common.moduleSetting('preserveConsoleLog').get()) {
Common.console.log(Common.UIString('Navigated to %s', event.data.url));
+ }
}
/**
@@ -268,7 +277,7 @@ SDK.ConsoleModel = class extends Common.Object {
_consoleProfileStarted(cpuProfilerModel, event) {
const data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
this._addConsoleProfileMessage(
- cpuProfilerModel, SDK.ConsoleMessage.MessageType.Profile, data.scriptLocation,
+ cpuProfilerModel, MessageType.Profile, data.scriptLocation,
Common.UIString('Profile \'%s\' started.', data.title));
}
@@ -279,7 +288,7 @@ SDK.ConsoleModel = class extends Common.Object {
_consoleProfileFinished(cpuProfilerModel, event) {
const data = /** @type {!SDK.CPUProfilerModel.EventData} */ (event.data);
this._addConsoleProfileMessage(
- cpuProfilerModel, SDK.ConsoleMessage.MessageType.ProfileEnd, data.scriptLocation,
+ cpuProfilerModel, MessageType.ProfileEnd, data.scriptLocation,
Common.UIString('Profile \'%s\' finished.', data.title));
}
@@ -297,41 +306,43 @@ SDK.ConsoleModel = class extends Common.Object {
lineNumber: scriptLocation.lineNumber,
columnNumber: scriptLocation.columnNumber || 0
}];
- this.addMessage(new SDK.ConsoleMessage(
- cpuProfilerModel.runtimeModel(), SDK.ConsoleMessage.MessageSource.ConsoleAPI,
- SDK.ConsoleMessage.MessageLevel.Info, messageText, type, undefined, undefined, undefined, stackTrace));
+ this.addMessage(new ConsoleMessage(
+ cpuProfilerModel.runtimeModel(), MessageSource.ConsoleAPI, MessageLevel.Info, messageText, type, undefined,
+ undefined, undefined, stackTrace));
}
/**
- * @param {!SDK.ConsoleMessage} msg
+ * @param {!ConsoleMessage} msg
*/
_incrementErrorWarningCount(msg) {
- if (msg.source === SDK.ConsoleMessage.MessageSource.Violation) {
+ if (msg.source === MessageSource.Violation) {
this._violations++;
return;
}
switch (msg.level) {
- case SDK.ConsoleMessage.MessageLevel.Warning:
+ case MessageLevel.Warning:
this._warnings++;
break;
- case SDK.ConsoleMessage.MessageLevel.Error:
+ case MessageLevel.Error:
this._errors++;
break;
}
}
/**
- * @return {!Array.<!SDK.ConsoleMessage>}
+ * @return {!Array.<!ConsoleMessage>}
*/
messages() {
return this._messages;
}
requestClearMessages() {
- for (const logModel of SDK.targetManager.models(SDK.LogModel))
+ for (const logModel of SDK.targetManager.models(SDK.LogModel)) {
logModel.requestClear();
- for (const runtimeModel of SDK.targetManager.models(SDK.RuntimeModel))
+ }
+ for (const runtimeModel of SDK.targetManager.models(SDK.RuntimeModel)) {
runtimeModel.discardConsoleEntries();
+ }
this._clear();
}
@@ -341,7 +352,7 @@ SDK.ConsoleModel = class extends Common.Object {
this._errors = 0;
this._warnings = 0;
this._violations = 0;
- this.dispatchEventToListeners(SDK.ConsoleModel.Events.ConsoleCleared);
+ this.dispatchEventToListeners(Events.ConsoleCleared);
}
/**
@@ -394,8 +405,9 @@ SDK.ConsoleModel = class extends Common.Object {
this.evaluateCommandInConsole(
executionContext, message, text, /* useCommandLineAPI */ false, /* awaitPromise */ false);
}
- if (callFunctionResult.object)
+ if (callFunctionResult.object) {
callFunctionResult.object.release();
+ }
/**
* @suppressReceiverCheck
@@ -404,8 +416,9 @@ SDK.ConsoleModel = class extends Common.Object {
function saveVariable(value) {
const prefix = 'temp';
let index = 1;
- while ((prefix + index) in this)
+ while ((prefix + index) in this) {
++index;
+ }
const name = prefix + index;
this[name] = value;
return name;
@@ -416,15 +429,16 @@ SDK.ConsoleModel = class extends Common.Object {
*/
function failedToSave(result) {
let message = Common.UIString('Failed to save to temp variable.');
- if (result)
+ if (result) {
message += ' ' + result.description;
+ }
Common.console.error(message);
}
}
-};
+}
/** @enum {symbol} */
-SDK.ConsoleModel.Events = {
+export const Events = {
ConsoleCleared: Symbol('ConsoleCleared'),
MessageAdded: Symbol('MessageAdded'),
MessageUpdated: Symbol('MessageUpdated'),
@@ -435,7 +449,7 @@ SDK.ConsoleModel.Events = {
/**
* @unrestricted
*/
-SDK.ConsoleMessage = class {
+export class ConsoleMessage {
/**
* @param {?SDK.RuntimeModel} runtimeModel
* @param {string} source
@@ -458,9 +472,9 @@ SDK.ConsoleMessage = class {
executionContextId, scriptId, workerId, context) {
this._runtimeModel = runtimeModel;
this.source = source;
- this.level = /** @type {?SDK.ConsoleMessage.MessageLevel} */ (level);
+ this.level = /** @type {?MessageLevel} */ (level);
this.messageText = messageText;
- this.type = type || SDK.ConsoleMessage.MessageType.Log;
+ this.type = type || MessageType.Log;
/** @type {string|undefined} */
this.url = url || undefined;
/** @type {number} */
@@ -476,14 +490,16 @@ SDK.ConsoleMessage = class {
this.workerId = workerId || null;
if (!this.executionContextId && this._runtimeModel) {
- if (this.scriptId)
+ if (this.scriptId) {
this.executionContextId = this._runtimeModel.executionContextIdForScriptId(this.scriptId);
- else if (this.stackTrace)
+ } else if (this.stackTrace) {
this.executionContextId = this._runtimeModel.executionContextForStackTrace(this.stackTrace);
+ }
}
- if (context)
+ if (context) {
this.context = context.match(/[^#]*/)[0];
+ }
}
/**
@@ -492,13 +508,12 @@ SDK.ConsoleMessage = class {
* @param {string=} messageType
* @param {number=} timestamp
* @param {string=} forceUrl
- * @return {!SDK.ConsoleMessage}
+ * @return {!ConsoleMessage}
*/
static fromException(runtimeModel, exceptionDetails, messageType, timestamp, forceUrl) {
- return new SDK.ConsoleMessage(
- runtimeModel, SDK.ConsoleMessage.MessageSource.JS, SDK.ConsoleMessage.MessageLevel.Error,
- SDK.RuntimeModel.simpleTextFromException(exceptionDetails), messageType, forceUrl || exceptionDetails.url,
- exceptionDetails.lineNumber, exceptionDetails.columnNumber,
+ return new ConsoleMessage(
+ runtimeModel, MessageSource.JS, MessageLevel.Error, SDK.RuntimeModel.simpleTextFromException(exceptionDetails),
+ messageType, forceUrl || exceptionDetails.url, exceptionDetails.lineNumber, exceptionDetails.columnNumber,
exceptionDetails.exception ?
[SDK.RemoteObject.fromLocalObject(exceptionDetails.text), exceptionDetails.exception] :
undefined,
@@ -520,7 +535,7 @@ SDK.ConsoleMessage = class {
}
/**
- * @param {!SDK.ConsoleMessage} originatingMessage
+ * @param {!ConsoleMessage} originatingMessage
*/
setOriginatingMessage(originatingMessage) {
this._originatingConsoleMessage = originatingMessage;
@@ -542,7 +557,7 @@ SDK.ConsoleMessage = class {
}
/**
- * @return {?SDK.ConsoleMessage}
+ * @return {?ConsoleMessage}
*/
originatingMessage() {
return this._originatingConsoleMessage;
@@ -552,38 +567,33 @@ SDK.ConsoleMessage = class {
* @return {boolean}
*/
isGroupMessage() {
- return this.type === SDK.ConsoleMessage.MessageType.StartGroup ||
- this.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed ||
- this.type === SDK.ConsoleMessage.MessageType.EndGroup;
+ return this.type === MessageType.StartGroup || this.type === MessageType.StartGroupCollapsed ||
+ this.type === MessageType.EndGroup;
}
/**
* @return {boolean}
*/
isGroupStartMessage() {
- return this.type === SDK.ConsoleMessage.MessageType.StartGroup ||
- this.type === SDK.ConsoleMessage.MessageType.StartGroupCollapsed;
+ return this.type === MessageType.StartGroup || this.type === MessageType.StartGroupCollapsed;
}
/**
* @return {boolean}
*/
isErrorOrWarning() {
- return (
- this.level === SDK.ConsoleMessage.MessageLevel.Warning || this.level === SDK.ConsoleMessage.MessageLevel.Error);
+ return (this.level === MessageLevel.Warning || this.level === MessageLevel.Error);
}
/**
* @return {boolean}
*/
isGroupable() {
- const isUngroupableError = this.level === SDK.ConsoleMessage.MessageLevel.Error &&
- (this.source === SDK.ConsoleMessage.MessageSource.JS ||
- this.source === SDK.ConsoleMessage.MessageSource.Network);
+ const isUngroupableError = this.level === MessageLevel.Error &&
+ (this.source === MessageSource.JS || this.source === MessageSource.Network);
return (
- this.source !== SDK.ConsoleMessage.MessageSource.ConsoleAPI &&
- this.type !== SDK.ConsoleMessage.MessageType.Command && this.type !== SDK.ConsoleMessage.MessageType.Result &&
- this.type !== SDK.ConsoleMessage.MessageType.System && !isUngroupableError);
+ this.source !== MessageSource.ConsoleAPI && this.type !== MessageType.Command &&
+ this.type !== MessageType.Result && this.type !== MessageType.System && !isUngroupableError);
}
/**
@@ -594,29 +604,34 @@ SDK.ConsoleMessage = class {
}
/**
- * @param {?SDK.ConsoleMessage} msg
+ * @param {?ConsoleMessage} msg
* @return {boolean}
*/
isEqual(msg) {
- if (!msg)
+ if (!msg) {
return false;
+ }
- if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace))
+ if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace)) {
return false;
+ }
if (this.parameters) {
- if (!msg.parameters || this.parameters.length !== msg.parameters.length)
+ if (!msg.parameters || this.parameters.length !== msg.parameters.length) {
return false;
+ }
for (let i = 0; i < msg.parameters.length; ++i) {
// Never treat objects as equal - their properties might change over time. Errors can be treated as equal
// since they are always formatted as strings.
- if (msg.parameters[i].type === 'object' && msg.parameters[i].subtype !== 'error')
+ if (msg.parameters[i].type === 'object' && msg.parameters[i].subtype !== 'error') {
return false;
+ }
if (this.parameters[i].type !== msg.parameters[i].type ||
this.parameters[i].value !== msg.parameters[i].value ||
- this.parameters[i].description !== msg.parameters[i].description)
+ this.parameters[i].description !== msg.parameters[i].description) {
return false;
+ }
}
}
@@ -632,29 +647,33 @@ SDK.ConsoleMessage = class {
* @return {boolean}
*/
_isEqualStackTraces(stackTrace1, stackTrace2) {
- if (!stackTrace1 !== !stackTrace2)
+ if (!stackTrace1 !== !stackTrace2) {
return false;
- if (!stackTrace1)
+ }
+ if (!stackTrace1) {
return true;
+ }
const callFrames1 = stackTrace1.callFrames;
const callFrames2 = stackTrace2.callFrames;
- if (callFrames1.length !== callFrames2.length)
+ if (callFrames1.length !== callFrames2.length) {
return false;
+ }
for (let i = 0, n = callFrames1.length; i < n; ++i) {
if (callFrames1[i].url !== callFrames2[i].url || callFrames1[i].functionName !== callFrames2[i].functionName ||
callFrames1[i].lineNumber !== callFrames2[i].lineNumber ||
- callFrames1[i].columnNumber !== callFrames2[i].columnNumber)
+ callFrames1[i].columnNumber !== callFrames2[i].columnNumber) {
return false;
+ }
}
return this._isEqualStackTraces(stackTrace1.parent, stackTrace2.parent);
}
-};
+}
// Note: Keep these constants in sync with the ones in ConsoleTypes.h
/**
* @enum {string}
*/
-SDK.ConsoleMessage.MessageSource = {
+export const MessageSource = {
XML: 'xml',
JS: 'javascript',
Network: 'network',
@@ -675,7 +694,7 @@ SDK.ConsoleMessage.MessageSource = {
/**
* @enum {string}
*/
-SDK.ConsoleMessage.MessageType = {
+export const MessageType = {
Log: 'log',
Debug: 'debug',
Info: 'info',
@@ -701,30 +720,57 @@ SDK.ConsoleMessage.MessageType = {
/**
* @enum {string}
*/
-SDK.ConsoleMessage.MessageLevel = {
+export const MessageLevel = {
Verbose: 'verbose',
Info: 'info',
Warning: 'warning',
Error: 'error'
};
-/** @type {!Map<!SDK.ConsoleMessage.MessageSource, string>} */
-SDK.ConsoleMessage.MessageSourceDisplayName = new Map([
- [SDK.ConsoleMessage.MessageSource.XML, 'xml'], [SDK.ConsoleMessage.MessageSource.JS, 'javascript'],
- [SDK.ConsoleMessage.MessageSource.Network, 'network'], [SDK.ConsoleMessage.MessageSource.ConsoleAPI, 'console-api'],
- [SDK.ConsoleMessage.MessageSource.Storage, 'storage'], [SDK.ConsoleMessage.MessageSource.AppCache, 'appcache'],
- [SDK.ConsoleMessage.MessageSource.Rendering, 'rendering'], [SDK.ConsoleMessage.MessageSource.CSS, 'css'],
- [SDK.ConsoleMessage.MessageSource.Security, 'security'],
- [SDK.ConsoleMessage.MessageSource.Deprecation, 'deprecation'], [SDK.ConsoleMessage.MessageSource.Worker, 'worker'],
- [SDK.ConsoleMessage.MessageSource.Violation, 'violation'],
- [SDK.ConsoleMessage.MessageSource.Intervention, 'intervention'],
- [SDK.ConsoleMessage.MessageSource.Recommendation, 'recommendation'],
- [SDK.ConsoleMessage.MessageSource.Other, 'other']
+/** @type {!Map<!MessageSource, string>} */
+export const MessageSourceDisplayName = new Map([
+ [MessageSource.XML, 'xml'], [MessageSource.JS, 'javascript'], [MessageSource.Network, 'network'],
+ [MessageSource.ConsoleAPI, 'console-api'], [MessageSource.Storage, 'storage'], [MessageSource.AppCache, 'appcache'],
+ [MessageSource.Rendering, 'rendering'], [MessageSource.CSS, 'css'], [MessageSource.Security, 'security'],
+ [MessageSource.Deprecation, 'deprecation'], [MessageSource.Worker, 'worker'], [MessageSource.Violation, 'violation'],
+ [MessageSource.Intervention, 'intervention'], [MessageSource.Recommendation, 'recommendation'],
+ [MessageSource.Other, 'other']
]);
-SDK.ConsoleModel._events = Symbol('SDK.ConsoleModel.events');
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ConsoleModel = ConsoleModel;
+
+/** @constructor */
+SDK.ConsoleMessage = ConsoleMessage;
+
+/** @enum {symbol} */
+SDK.ConsoleModel.Events = Events;
+
+/**
+ * @enum {string}
+ */
+SDK.ConsoleMessage.MessageSource = MessageSource;
+
+/**
+ * @enum {string}
+ */
+SDK.ConsoleMessage.MessageType = MessageType;
+
+/**
+ * @enum {string}
+ */
+SDK.ConsoleMessage.MessageLevel = MessageLevel;
+
+SDK.ConsoleMessage.MessageSourceDisplayName = MessageSourceDisplayName;
+SDK.ConsoleModel._events = _events;
/**
* @type {!SDK.ConsoleModel}
*/
-SDK.consoleModel;
+SDK.consoleModel; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieModel.js
index 44e68236f27..05c895bd123 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieModel.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-SDK.CookieModel = class extends SDK.SDKModel {
+export default class CookieModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -11,35 +11,15 @@ SDK.CookieModel = class extends SDK.SDKModel {
}
/**
- * @param {!Protocol.Network.Cookie} protocolCookie
- * @return {!SDK.Cookie}
- */
- static _parseProtocolCookie(protocolCookie) {
- const cookie = new SDK.Cookie(protocolCookie.name, protocolCookie.value, null);
- cookie.addAttribute('domain', protocolCookie['domain']);
- cookie.addAttribute('path', protocolCookie['path']);
- cookie.addAttribute('port', protocolCookie['port']);
- if (protocolCookie['expires'])
- cookie.addAttribute('expires', protocolCookie['expires'] * 1000);
- if (protocolCookie['httpOnly'])
- cookie.addAttribute('httpOnly');
- if (protocolCookie['secure'])
- cookie.addAttribute('secure');
- if (protocolCookie['sameSite'])
- cookie.addAttribute('sameSite', protocolCookie['sameSite']);
- cookie.setSize(protocolCookie['size']);
- return cookie;
- }
-
- /**
* @param {!SDK.Cookie} cookie
* @param {string} resourceURL
* @return {boolean}
*/
static cookieMatchesResourceURL(cookie, resourceURL) {
const url = resourceURL.asParsedURL();
- if (!url || !SDK.CookieModel.cookieDomainMatchesResourceDomain(cookie.domain(), url.host))
+ if (!url || !CookieModel.cookieDomainMatchesResourceDomain(cookie.domain(), url.host)) {
return false;
+ }
return (
url.path.startsWith(cookie.path()) && (!cookie.port() || url.port === cookie.port()) &&
(!cookie.secure() || url.scheme === 'https'));
@@ -51,8 +31,9 @@ SDK.CookieModel = class extends SDK.SDKModel {
* @return {boolean}
*/
static cookieDomainMatchesResourceDomain(cookieDomain, resourceDomain) {
- if (cookieDomain.charAt(0) !== '.')
+ if (cookieDomain.charAt(0) !== '.') {
return resourceDomain === cookieDomain;
+ }
return !!resourceDomain.match(
new RegExp('^([^\\.]+\\.)*' + cookieDomain.substring(1).escapeForRegExp() + '$', 'i'));
}
@@ -63,7 +44,7 @@ SDK.CookieModel = class extends SDK.SDKModel {
*/
getCookies(urls) {
return this.target().networkAgent().getCookies(urls).then(
- cookies => (cookies || []).map(cookie => SDK.CookieModel._parseProtocolCookie(cookie)));
+ cookies => (cookies || []).map(cookie => SDK.Cookie.fromProtocolCookie(cookie)));
}
/**
@@ -88,11 +69,13 @@ SDK.CookieModel = class extends SDK.SDKModel {
*/
saveCookie(cookie) {
let domain = cookie.domain();
- if (!domain.startsWith('.'))
+ if (!domain.startsWith('.')) {
domain = '';
+ }
let expires = undefined;
- if (cookie.expires())
+ if (cookie.expires()) {
expires = Math.floor(Date.parse(cookie.expires()) / 1000);
+ }
return this.target()
.networkAgent()
.setCookie(
@@ -113,12 +96,14 @@ SDK.CookieModel = class extends SDK.SDKModel {
*/
function populateResourceURLs(resource) {
const documentURL = resource.documentURL.asParsedURL();
- if (documentURL && (!domain || documentURL.securityOrigin() === domain))
+ if (documentURL && (!domain || documentURL.securityOrigin() === domain)) {
resourceURLs.push(resource.url);
+ }
}
const resourceTreeModel = this.target().model(SDK.ResourceTreeModel);
- if (resourceTreeModel)
+ if (resourceTreeModel) {
resourceTreeModel.forAllResources(populateResourceURLs);
+ }
return this.getCookies(resourceURLs);
}
@@ -133,6 +118,15 @@ SDK.CookieModel = class extends SDK.SDKModel {
cookies.map(cookie => networkAgent.deleteCookies(cookie.name(), undefined, cookie.domain(), cookie.path())))
.then(callback || function() {});
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CookieModel = CookieModel;
-SDK.SDKModel.register(SDK.CookieModel, SDK.Target.Capability.Network, false);
+SDK.SDKModel.register(SDK.CookieModel, SDK.Target.Capability.Network, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieParser.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieParser.js
index f5f0d76e09e..33cdca7d446 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieParser.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CookieParser.js
@@ -37,7 +37,7 @@
/**
* @unrestricted
*/
-SDK.CookieParser = class {
+export default class CookieParser {
constructor() {
}
@@ -46,7 +46,7 @@ SDK.CookieParser = class {
* @return {?Array<!SDK.Cookie>}
*/
static parseCookie(header) {
- return (new SDK.CookieParser()).parseCookie(header);
+ return (new CookieParser()).parseCookie(header);
}
/**
@@ -54,7 +54,7 @@ SDK.CookieParser = class {
* @return {?Array<!SDK.Cookie>}
*/
static parseSetCookie(header) {
- return (new SDK.CookieParser()).parseSetCookie(header);
+ return (new CookieParser()).parseSetCookie(header);
}
/**
@@ -69,14 +69,16 @@ SDK.CookieParser = class {
* @return {?Array<!SDK.Cookie>}
*/
parseCookie(cookieHeader) {
- if (!this._initialize(cookieHeader))
+ if (!this._initialize(cookieHeader)) {
return null;
+ }
for (let kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
- if (kv.key.charAt(0) === '$' && this._lastCookie)
+ if (kv.key.charAt(0) === '$' && this._lastCookie) {
this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
- else if (kv.key.toLowerCase() !== '$version' && typeof kv.value === 'string')
- this._addCookie(kv, SDK.Cookie.Type.Request);
+ } else if (kv.key.toLowerCase() !== '$version' && typeof kv.value === 'string') {
+ this._addCookie(kv, Type.Request);
+ }
this._advanceAndCheckCookieDelimiter();
}
this._flushCookie();
@@ -88,15 +90,18 @@ SDK.CookieParser = class {
* @return {?Array<!SDK.Cookie>}
*/
parseSetCookie(setCookieHeader) {
- if (!this._initialize(setCookieHeader))
+ if (!this._initialize(setCookieHeader)) {
return null;
+ }
for (let kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
- if (this._lastCookie)
+ if (this._lastCookie) {
this._lastCookie.addAttribute(kv.key, kv.value);
- else
- this._addCookie(kv, SDK.Cookie.Type.Response);
- if (this._advanceAndCheckCookieDelimiter())
+ } else {
+ this._addCookie(kv, Type.Response);
+ }
+ if (this._advanceAndCheckCookieDelimiter()) {
this._flushCookie();
+ }
}
this._flushCookie();
return this._cookies;
@@ -108,26 +113,32 @@ SDK.CookieParser = class {
*/
_initialize(headerValue) {
this._input = headerValue;
- if (typeof headerValue !== 'string')
+ if (typeof headerValue !== 'string') {
return false;
+ }
this._cookies = [];
this._lastCookie = null;
+ this._lastCookieLine = '';
this._originalInputLength = this._input.length;
return true;
}
_flushCookie() {
- if (this._lastCookie)
+ if (this._lastCookie) {
this._lastCookie.setSize(this._originalInputLength - this._input.length - this._lastCookiePosition);
+ this._lastCookie._setCookieLine(this._lastCookieLine.replace('\n', ''));
+ }
this._lastCookie = null;
+ this._lastCookieLine = '';
}
/**
- * @return {?SDK.CookieParser.KeyValue}
+ * @return {?KeyValue}
*/
_extractKeyValue() {
- if (!this._input || !this._input.length)
+ if (!this._input || !this._input.length) {
return null;
+ }
// Note: RFCs offer an option for quoted values that may contain commas and semicolons.
// Many browsers/platforms do not support this, however (see http://webkit.org/b/16699
// and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox,
@@ -139,8 +150,9 @@ SDK.CookieParser = class {
return null;
}
- const result = new SDK.CookieParser.KeyValue(
+ const result = new KeyValue(
keyValueMatch[1], keyValueMatch[2] && keyValueMatch[2].trim(), this._originalInputLength - this._input.length);
+ this._lastCookieLine += keyValueMatch[0];
this._input = this._input.slice(keyValueMatch[0].length);
return result;
}
@@ -150,19 +162,22 @@ SDK.CookieParser = class {
*/
_advanceAndCheckCookieDelimiter() {
const match = /^\s*[\n;]\s*/.exec(this._input);
- if (!match)
+ if (!match) {
return false;
+ }
+ this._lastCookieLine += match[0];
this._input = this._input.slice(match[0].length);
return match[0].match('\n') !== null;
}
/**
- * @param {!SDK.CookieParser.KeyValue} keyValue
- * @param {!SDK.Cookie.Type} type
+ * @param {!KeyValue} keyValue
+ * @param {!Type} type
*/
_addCookie(keyValue, type) {
- if (this._lastCookie)
+ if (this._lastCookie) {
this._lastCookie.setSize(keyValue.position - this._lastCookiePosition);
+ }
// Mozilla bug 169091: Mozilla, IE and Chrome treat single token (w/o "=") as
// specifying a value for a cookie with empty name.
@@ -171,12 +186,12 @@ SDK.CookieParser = class {
this._lastCookiePosition = keyValue.position;
this._cookies.push(this._lastCookie);
}
-};
+}
/**
* @unrestricted
*/
-SDK.CookieParser.KeyValue = class {
+export class KeyValue {
/**
* @param {string} key
* @param {string|undefined} value
@@ -187,17 +202,17 @@ SDK.CookieParser.KeyValue = class {
this.value = value;
this.position = position;
}
-};
+}
/**
* @unrestricted
*/
-SDK.Cookie = class {
+export class Cookie {
/**
* @param {string} name
* @param {string} value
- * @param {?SDK.Cookie.Type} type
+ * @param {?Type} type
*/
constructor(name, value, type) {
this._name = name;
@@ -205,6 +220,33 @@ SDK.Cookie = class {
this._type = type;
this._attributes = {};
this._size = 0;
+ /** @type {string|null} */
+ this._cookieLine = null;
+ }
+
+ /**
+ * @param {!Protocol.Network.Cookie} protocolCookie
+ * @return {!SDK.Cookie}
+ */
+ static fromProtocolCookie(protocolCookie) {
+ const cookie = new SDK.Cookie(protocolCookie.name, protocolCookie.value, null);
+ cookie.addAttribute('domain', protocolCookie['domain']);
+ cookie.addAttribute('path', protocolCookie['path']);
+ cookie.addAttribute('port', protocolCookie['port']);
+ if (protocolCookie['expires']) {
+ cookie.addAttribute('expires', protocolCookie['expires'] * 1000);
+ }
+ if (protocolCookie['httpOnly']) {
+ cookie.addAttribute('httpOnly');
+ }
+ if (protocolCookie['secure']) {
+ cookie.addAttribute('secure');
+ }
+ if (protocolCookie['sameSite']) {
+ cookie.addAttribute('sameSite', protocolCookie['sameSite']);
+ }
+ cookie.setSize(protocolCookie['size']);
+ return cookie;
}
/**
@@ -222,7 +264,7 @@ SDK.Cookie = class {
}
/**
- * @return {?SDK.Cookie.Type}
+ * @return {?Type}
*/
type() {
return this._type;
@@ -325,8 +367,9 @@ SDK.Cookie = class {
return new Date(targetDate.getTime() + 1000 * this.maxAge());
}
- if (this.expires())
+ if (this.expires()) {
return new Date(this.expires());
+ }
return null;
}
@@ -345,12 +388,66 @@ SDK.Cookie = class {
addAttribute(key, value) {
this._attributes[key.toLowerCase()] = value;
}
-};
+
+ /**
+ * @param {string} cookieLine
+ */
+ _setCookieLine(cookieLine) {
+ this._cookieLine = cookieLine;
+ }
+
+ /**
+ * @return {string|null}
+ */
+ getCookieLine() {
+ return this._cookieLine;
+ }
+}
/**
* @enum {number}
*/
-SDK.Cookie.Type = {
+export const Type = {
Request: 0,
Response: 1
};
+
+/**
+ * @enum {string}
+ */
+export const Attributes = {
+ Name: 'name',
+ Value: 'value',
+ Size: 'size',
+ Domain: 'domain',
+ Path: 'path',
+ Expires: 'expires',
+ HttpOnly: 'httpOnly',
+ Secure: 'secure',
+ SameSite: 'sameSite',
+};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.CookieParser = CookieParser;
+
+/** @constructor */
+SDK.CookieParser.KeyValue = KeyValue;
+
+/** @constructor */
+SDK.Cookie = Cookie;
+
+/**
+ * @enum {number}
+ */
+SDK.Cookie.Type = Type;
+
+/**
+ * @enum {string}
+ */
+SDK.Cookie.Attributes = Attributes;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
index e8a5fc04c1b..bf482925034 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-SDK.DOMDebuggerModel = class extends SDK.SDKModel {
+export default class DOMDebuggerModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -14,11 +14,12 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
this._domModel.addEventListener(SDK.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
this._domModel.addEventListener(SDK.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
- /** @type {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>} */
+ /** @type {!Array<!DOMBreakpoint>} */
this._domBreakpoints = [];
this._domBreakpointsSetting = Common.settings.createLocalSetting('domBreakpoints', []);
- if (this._domModel.existingDocument())
+ if (this._domModel.existingDocument()) {
this._documentUpdated();
+ }
}
/**
@@ -34,16 +35,18 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
*/
async eventListeners(remoteObject) {
console.assert(remoteObject.runtimeModel() === this._runtimeModel);
- if (!remoteObject.objectId)
+ if (!remoteObject.objectId) {
return [];
+ }
const payloads = await this._agent.getEventListeners(/** @type {string} */ (remoteObject.objectId));
const eventListeners = [];
for (const payload of payloads || []) {
const location = this._runtimeModel.debuggerModel().createRawLocationByScriptId(
payload.scriptId, payload.lineNumber, payload.columnNumber);
- if (!location)
+ if (!location) {
continue;
+ }
eventListeners.push(new SDK.EventListener(
this, remoteObject, payload.type, payload.useCapture, payload.passive, payload.once,
payload.handler ? this._runtimeModel.createRemoteObject(payload.handler) : null,
@@ -58,7 +61,7 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
}
/**
- * @return {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>}
+ * @return {!Array<!DOMBreakpoint>}
*/
domBreakpoints() {
return this._domBreakpoints.slice();
@@ -76,7 +79,7 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
/**
* @param {!SDK.DOMNode} node
* @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type
- * @return {!SDK.DOMDebuggerModel.DOMBreakpoint}
+ * @return {!DOMBreakpoint}
*/
setDOMBreakpoint(node, type) {
for (const breakpoint of this._domBreakpoints) {
@@ -85,11 +88,11 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
return breakpoint;
}
}
- const breakpoint = new SDK.DOMDebuggerModel.DOMBreakpoint(this, node, type, true);
+ const breakpoint = new DOMBreakpoint(this, node, type, true);
this._domBreakpoints.push(breakpoint);
this._saveDOMBreakpoints();
this._enableDOMBreakpoint(breakpoint);
- this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, breakpoint);
+ this.dispatchEventToListeners(Events.DOMBreakpointAdded, breakpoint);
return breakpoint;
}
@@ -106,35 +109,36 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
}
/**
- * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
+ * @param {!DOMBreakpoint} breakpoint
* @param {boolean} enabled
*/
toggleDOMBreakpoint(breakpoint, enabled) {
- if (enabled === breakpoint.enabled)
+ if (enabled === breakpoint.enabled) {
return;
+ }
breakpoint.enabled = enabled;
- if (enabled)
+ if (enabled) {
this._enableDOMBreakpoint(breakpoint);
- else
+ } else {
this._disableDOMBreakpoint(breakpoint);
- this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointToggled, breakpoint);
+ }
+ this.dispatchEventToListeners(Events.DOMBreakpointToggled, breakpoint);
}
/**
- * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
+ * @param {!DOMBreakpoint} breakpoint
*/
_enableDOMBreakpoint(breakpoint) {
this._agent.setDOMBreakpoint(breakpoint.node.id, breakpoint.type);
- breakpoint.node.setMarker(SDK.DOMDebuggerModel.DOMBreakpoint.Marker, true);
+ breakpoint.node.setMarker(Marker, true);
}
/**
- * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
+ * @param {!DOMBreakpoint} breakpoint
*/
_disableDOMBreakpoint(breakpoint) {
this._agent.removeDOMBreakpoint(breakpoint.node.id, breakpoint.type);
- breakpoint.node.setMarker(
- SDK.DOMDebuggerModel.DOMBreakpoint.Marker, this._nodeHasBreakpoints(breakpoint.node) ? true : null);
+ breakpoint.node.setMarker(Marker, this._nodeHasBreakpoints(breakpoint.node) ? true : null);
}
/**
@@ -143,8 +147,9 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
*/
_nodeHasBreakpoints(node) {
for (const breakpoint of this._domBreakpoints) {
- if (breakpoint.node === node && breakpoint.enabled)
+ if (breakpoint.node === node && breakpoint.enabled) {
return true;
+ }
}
return false;
}
@@ -156,8 +161,9 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
resolveDOMBreakpointData(auxData) {
const type = auxData['type'];
const node = this._domModel.nodeForId(auxData['nodeId']);
- if (!type || !node)
+ if (!type || !node) {
return null;
+ }
let targetNode = null;
let insertion = false;
if (type === SDK.DOMDebuggerModel.DOMBreakpoint.Type.SubtreeModified) {
@@ -178,33 +184,36 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
_documentUpdated() {
const removed = this._domBreakpoints;
this._domBreakpoints = [];
- this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved, removed);
+ this.dispatchEventToListeners(Events.DOMBreakpointsRemoved, removed);
const currentURL = this._currentURL();
for (const breakpoint of this._domBreakpointsSetting.get()) {
- if (breakpoint.url === currentURL)
+ if (breakpoint.url === currentURL) {
this._domModel.pushNodeByPathToFrontend(breakpoint.path).then(appendBreakpoint.bind(this, breakpoint));
+ }
}
/**
* @param {!{type: !SDK.DOMDebuggerModel.DOMBreakpoint.Type, enabled: boolean}} breakpoint
* @param {?number} nodeId
- * @this {SDK.DOMDebuggerModel}
+ * @this {DOMDebuggerModel}
*/
function appendBreakpoint(breakpoint, nodeId) {
const node = nodeId ? this._domModel.nodeForId(nodeId) : null;
- if (!node)
+ if (!node) {
return;
- const domBreakpoint = new SDK.DOMDebuggerModel.DOMBreakpoint(this, node, breakpoint.type, breakpoint.enabled);
+ }
+ const domBreakpoint = new DOMBreakpoint(this, node, breakpoint.type, breakpoint.enabled);
this._domBreakpoints.push(domBreakpoint);
- if (breakpoint.enabled)
+ if (breakpoint.enabled) {
this._enableDOMBreakpoint(domBreakpoint);
- this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, domBreakpoint);
+ }
+ this.dispatchEventToListeners(Events.DOMBreakpointAdded, domBreakpoint);
}
}
/**
- * @param {function(!SDK.DOMDebuggerModel.DOMBreakpoint):boolean} filter
+ * @param {function(!DOMBreakpoint):boolean} filter
*/
_removeDOMBreakpoints(filter) {
const removed = [];
@@ -221,11 +230,12 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
}
}
- if (!removed.length)
+ if (!removed.length) {
return;
+ }
this._domBreakpoints = left;
this._saveDOMBreakpoints();
- this.dispatchEventToListeners(SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved, removed);
+ this.dispatchEventToListeners(Events.DOMBreakpointsRemoved, removed);
}
/**
@@ -246,20 +256,20 @@ SDK.DOMDebuggerModel = class extends SDK.SDKModel {
}
this._domBreakpointsSetting.set(breakpoints);
}
-};
-
-SDK.SDKModel.register(SDK.DOMDebuggerModel, SDK.Target.Capability.DOM, false);
+}
/** @enum {symbol} */
-SDK.DOMDebuggerModel.Events = {
+export const Events = {
DOMBreakpointAdded: Symbol('DOMBreakpointAdded'),
DOMBreakpointToggled: Symbol('DOMBreakpointToggled'),
DOMBreakpointsRemoved: Symbol('DOMBreakpointsRemoved'),
};
-SDK.DOMDebuggerModel.DOMBreakpoint = class {
+export const Marker = 'breakpoint-marker';
+
+export class DOMBreakpoint {
/**
- * @param {!SDK.DOMDebuggerModel} domDebuggerModel
+ * @param {!DOMDebuggerModel} domDebuggerModel
* @param {!SDK.DOMNode} node
* @param {!SDK.DOMDebuggerModel.DOMBreakpoint.Type} type
* @param {boolean} enabled
@@ -270,16 +280,11 @@ SDK.DOMDebuggerModel.DOMBreakpoint = class {
this.type = type;
this.enabled = enabled;
}
-};
-
-/** @typedef {Protocol.DOMDebugger.DOMBreakpointType} */
-SDK.DOMDebuggerModel.DOMBreakpoint.Type = Protocol.DOMDebugger.DOMBreakpointType;
-
-SDK.DOMDebuggerModel.DOMBreakpoint.Marker = 'breakpoint-marker';
+}
-SDK.EventListener = class {
+export class EventListener {
/**
- * @param {!SDK.DOMDebuggerModel} domDebuggerModel
+ * @param {!DOMDebuggerModel} domDebuggerModel
* @param {!SDK.RemoteObject} eventTarget
* @param {string} type
* @param {boolean} useCapture
@@ -289,7 +294,7 @@ SDK.EventListener = class {
* @param {?SDK.RemoteObject} originalHandler
* @param {!SDK.DebuggerModel.Location} location
* @param {?SDK.RemoteObject} customRemoveFunction
- * @param {!SDK.EventListener.Origin=} origin
+ * @param {!EventListener.Origin=} origin
*/
constructor(
domDebuggerModel, eventTarget, type, useCapture, passive, once, handler, originalHandler, location,
@@ -306,11 +311,11 @@ SDK.EventListener = class {
const script = location.script();
this._sourceURL = script ? script.contentURL() : '';
this._customRemoveFunction = customRemoveFunction;
- this._origin = origin || SDK.EventListener.Origin.Raw;
+ this._origin = origin || EventListener.Origin.Raw;
}
/**
- * @return {!SDK.DOMDebuggerModel}
+ * @return {!DOMDebuggerModel}
*/
domDebuggerModel() {
return this._domDebuggerModel;
@@ -376,17 +381,18 @@ SDK.EventListener = class {
* @return {boolean}
*/
canRemove() {
- return !!this._customRemoveFunction || this._origin !== SDK.EventListener.Origin.FrameworkUser;
+ return !!this._customRemoveFunction || this._origin !== EventListener.Origin.FrameworkUser;
}
/**
* @return {!Promise<undefined>}
*/
remove() {
- if (!this.canRemove())
+ if (!this.canRemove()) {
return Promise.resolve();
+ }
- if (this._origin !== SDK.EventListener.Origin.FrameworkUser) {
+ if (this._origin !== EventListener.Origin.FrameworkUser) {
/**
* @param {string} type
* @param {function()} listener
@@ -396,8 +402,9 @@ SDK.EventListener = class {
*/
function removeListener(type, listener, useCapture) {
this.removeEventListener(type, listener, useCapture);
- if (this['on' + type])
+ if (this['on' + type]) {
this['on' + type] = undefined;
+ }
}
return /** @type {!Promise<undefined>} */ (this._eventTarget.callFunction(removeListener, [
@@ -434,7 +441,7 @@ SDK.EventListener = class {
* @return {boolean}
*/
canTogglePassive() {
- return this._origin !== SDK.EventListener.Origin.FrameworkUser;
+ return this._origin !== EventListener.Origin.FrameworkUser;
}
/**
@@ -463,14 +470,14 @@ SDK.EventListener = class {
}
/**
- * @return {!SDK.EventListener.Origin}
+ * @return {!EventListener.Origin}
*/
origin() {
return this._origin;
}
markAsFramework() {
- this._origin = SDK.EventListener.Origin.Framework;
+ this._origin = EventListener.Origin.Framework;
}
/**
@@ -480,16 +487,16 @@ SDK.EventListener = class {
return this._type === 'touchstart' || this._type === 'touchmove' || this._type === 'mousewheel' ||
this._type === 'wheel';
}
-};
+}
/** @enum {string} */
-SDK.EventListener.Origin = {
+EventListener.Origin = {
Raw: 'Raw',
Framework: 'Framework',
FrameworkUser: 'FrameworkUser'
};
-SDK.DOMDebuggerModel.EventListenerBreakpoint = class {
+export class EventListenerBreakpoint {
/**
* @param {string} instrumentationName
* @param {string} eventName
@@ -524,28 +531,32 @@ SDK.DOMDebuggerModel.EventListenerBreakpoint = class {
* @param {boolean} enabled
*/
setEnabled(enabled) {
- if (this._enabled === enabled)
+ if (this._enabled === enabled) {
return;
+ }
this._enabled = enabled;
- for (const model of SDK.targetManager.models(SDK.DOMDebuggerModel))
+ for (const model of SDK.targetManager.models(DOMDebuggerModel)) {
this._updateOnModel(model);
+ }
}
/**
- * @param {!SDK.DOMDebuggerModel} model
+ * @param {!DOMDebuggerModel} model
*/
_updateOnModel(model) {
if (this._instrumentationName) {
- if (this._enabled)
+ if (this._enabled) {
model._agent.setInstrumentationBreakpoint(this._instrumentationName);
- else
+ } else {
model._agent.removeInstrumentationBreakpoint(this._instrumentationName);
+ }
} else {
for (const eventTargetName of this._eventTargetNames) {
- if (this._enabled)
+ if (this._enabled) {
model._agent.setEventListenerBreakpoint(this._eventName, eventTargetName);
- else
+ } else {
model._agent.removeEventListenerBreakpoint(this._eventName, eventTargetName);
+ }
}
}
}
@@ -556,23 +567,24 @@ SDK.DOMDebuggerModel.EventListenerBreakpoint = class {
title() {
return this._title;
}
-};
+}
-SDK.DOMDebuggerModel.EventListenerBreakpoint._listener = 'listener:';
-SDK.DOMDebuggerModel.EventListenerBreakpoint._instrumentation = 'instrumentation:';
+EventListenerBreakpoint._listener = 'listener:';
+EventListenerBreakpoint._instrumentation = 'instrumentation:';
/**
- * @implements {SDK.SDKModelObserver<!SDK.DOMDebuggerModel>}
+ * @implements {SDK.SDKModelObserver<!DOMDebuggerModel>}
*/
-SDK.DOMDebuggerManager = class {
+export class DOMDebuggerManager {
constructor() {
this._xhrBreakpointsSetting = Common.settings.createLocalSetting('xhrBreakpoints', []);
/** @type {!Map<string, boolean>} */
this._xhrBreakpoints = new Map();
- for (const breakpoint of this._xhrBreakpointsSetting.get())
+ for (const breakpoint of this._xhrBreakpointsSetting.get()) {
this._xhrBreakpoints.set(breakpoint.url, breakpoint.enabled);
+ }
- /** @type {!Array<!SDK.DOMDebuggerModel.EventListenerBreakpoint>} */
+ /** @type {!Array<!EventListenerBreakpoint>} */
this._eventListenerBreakpoints = [];
this._createInstrumentationBreakpoints(
Common.UIString('Animation'),
@@ -694,7 +706,7 @@ SDK.DOMDebuggerManager = class {
_createInstrumentationBreakpoints(category, instrumentationNames) {
for (const instrumentationName of instrumentationNames) {
this._eventListenerBreakpoints.push(
- new SDK.DOMDebuggerModel.EventListenerBreakpoint(instrumentationName, '', [], category, instrumentationName));
+ new EventListenerBreakpoint(instrumentationName, '', [], category, instrumentationName));
}
}
@@ -706,14 +718,14 @@ SDK.DOMDebuggerManager = class {
_createEventListenerBreakpoints(category, eventNames, eventTargetNames) {
for (const eventName of eventNames) {
this._eventListenerBreakpoints.push(
- new SDK.DOMDebuggerModel.EventListenerBreakpoint('', eventName, eventTargetNames, category, eventName));
+ new EventListenerBreakpoint('', eventName, eventTargetNames, category, eventName));
}
}
/**
* @param {string} eventName
* @param {string=} eventTargetName
- * @return {?SDK.DOMDebuggerModel.EventListenerBreakpoint}
+ * @return {?EventListenerBreakpoint}
*/
_resolveEventListenerBreakpoint(eventName, eventTargetName) {
const instrumentationPrefix = 'instrumentation:';
@@ -730,20 +742,23 @@ SDK.DOMDebuggerManager = class {
eventTargetName = (eventTargetName || '*').toLowerCase();
let result = null;
for (const breakpoint of this._eventListenerBreakpoints) {
- if (instrumentationName && breakpoint._instrumentationName === instrumentationName)
+ if (instrumentationName && breakpoint._instrumentationName === instrumentationName) {
result = breakpoint;
+ }
if (eventName && breakpoint._eventName === eventName &&
- breakpoint._eventTargetNames.indexOf(eventTargetName) !== -1)
+ breakpoint._eventTargetNames.indexOf(eventTargetName) !== -1) {
result = breakpoint;
+ }
if (!result && eventName && breakpoint._eventName === eventName &&
- breakpoint._eventTargetNames.indexOf('*') !== -1)
+ breakpoint._eventTargetNames.indexOf('*') !== -1) {
result = breakpoint;
+ }
}
return result;
}
/**
- * @return {!Array<!SDK.DOMDebuggerModel.EventListenerBreakpoint>}
+ * @return {!Array<!EventListenerBreakpoint>}
*/
eventListenerBreakpoints() {
return this._eventListenerBreakpoints.slice();
@@ -761,19 +776,22 @@ SDK.DOMDebuggerManager = class {
errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, '$1');
return Common.UIString('WebGL Error Fired (%s)', errorName);
}
- if (id === 'instrumentation:scriptBlockedByCSP' && auxData['directiveText'])
+ if (id === 'instrumentation:scriptBlockedByCSP' && auxData['directiveText']) {
return Common.UIString('Script blocked due to Content Security Policy directive: %s', auxData['directiveText']);
+ }
const breakpoint = this._resolveEventListenerBreakpoint(id, auxData['targetName']);
- if (!breakpoint)
+ if (!breakpoint) {
return '';
- if (auxData['targetName'])
+ }
+ if (auxData['targetName']) {
return auxData['targetName'] + '.' + breakpoint._title;
+ }
return breakpoint._title;
}
/**
* @param {!Object} auxData
- * @return {?SDK.DOMDebuggerModel.EventListenerBreakpoint}
+ * @return {?EventListenerBreakpoint}
*/
resolveEventListenerBreakpoint(auxData) {
return this._resolveEventListenerBreakpoint(auxData['eventName'], auxData['targetName']);
@@ -788,8 +806,9 @@ SDK.DOMDebuggerManager = class {
_saveXHRBreakpoints() {
const breakpoints = [];
- for (const url of this._xhrBreakpoints.keys())
+ for (const url of this._xhrBreakpoints.keys()) {
breakpoints.push({url: url, enabled: this._xhrBreakpoints.get(url)});
+ }
this._xhrBreakpointsSetting.set(breakpoints);
}
@@ -800,8 +819,9 @@ SDK.DOMDebuggerManager = class {
addXHRBreakpoint(url, enabled) {
this._xhrBreakpoints.set(url, enabled);
if (enabled) {
- for (const model of SDK.targetManager.models(SDK.DOMDebuggerModel))
+ for (const model of SDK.targetManager.models(DOMDebuggerModel)) {
model._agent.setXHRBreakpoint(url);
+ }
}
this._saveXHRBreakpoints();
}
@@ -813,8 +833,9 @@ SDK.DOMDebuggerManager = class {
const enabled = this._xhrBreakpoints.get(url);
this._xhrBreakpoints.delete(url);
if (enabled) {
- for (const model of SDK.targetManager.models(SDK.DOMDebuggerModel))
+ for (const model of SDK.targetManager.models(DOMDebuggerModel)) {
model._agent.removeXHRBreakpoint(url);
+ }
}
this._saveXHRBreakpoints();
}
@@ -825,37 +846,71 @@ SDK.DOMDebuggerManager = class {
*/
toggleXHRBreakpoint(url, enabled) {
this._xhrBreakpoints.set(url, enabled);
- for (const model of SDK.targetManager.models(SDK.DOMDebuggerModel)) {
- if (enabled)
+ for (const model of SDK.targetManager.models(DOMDebuggerModel)) {
+ if (enabled) {
model._agent.setXHRBreakpoint(url);
- else
+ } else {
model._agent.removeXHRBreakpoint(url);
+ }
}
this._saveXHRBreakpoints();
}
/**
* @override
- * @param {!SDK.DOMDebuggerModel} domDebuggerModel
+ * @param {!DOMDebuggerModel} domDebuggerModel
*/
modelAdded(domDebuggerModel) {
for (const url of this._xhrBreakpoints.keys()) {
- if (this._xhrBreakpoints.get(url))
+ if (this._xhrBreakpoints.get(url)) {
domDebuggerModel._agent.setXHRBreakpoint(url);
+ }
}
for (const breakpoint of this._eventListenerBreakpoints) {
- if (breakpoint._enabled)
+ if (breakpoint._enabled) {
breakpoint._updateOnModel(domDebuggerModel);
+ }
}
}
/**
* @override
- * @param {!SDK.DOMDebuggerModel} domDebuggerModel
+ * @param {!DOMDebuggerModel} domDebuggerModel
*/
modelRemoved(domDebuggerModel) {
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.DOMDebuggerModel = DOMDebuggerModel;
+
+/** @enum {symbol} */
+SDK.DOMDebuggerModel.Events = Events;
+
+/** @constructor */
+SDK.DOMDebuggerModel.DOMBreakpoint = DOMBreakpoint;
+
+SDK.DOMDebuggerModel.DOMBreakpoint.Marker = Marker;
+
+/** @constructor */
+SDK.DOMDebuggerModel.EventListenerBreakpoint = EventListenerBreakpoint;
+
+/** @constructor */
+SDK.EventListener = EventListener;
+
+/** @constructor */
+SDK.DOMDebuggerManager = DOMDebuggerManager;
+
+SDK.SDKModel.register(SDK.DOMDebuggerModel, SDK.Target.Capability.DOM, false);
+
+/** @typedef {Protocol.DOMDebugger.DOMBreakpointType} */
+SDK.DOMDebuggerModel.DOMBreakpoint.Type = Protocol.DOMDebugger.DOMBreakpointType;
/** @type {!SDK.DOMDebuggerManager} */
SDK.domDebuggerManager;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
index ef298decac4..328d0284810 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
@@ -32,17 +32,17 @@
/**
* @unrestricted
*/
-SDK.DOMNode = class {
+export class DOMNode {
/**
- * @param {!SDK.DOMModel} domModel
+ * @param {!DOMModel} domModel
*/
constructor(domModel) {
this._domModel = domModel;
}
/**
- * @param {!SDK.DOMModel} domModel
- * @param {?SDK.DOMDocument} doc
+ * @param {!DOMModel} domModel
+ * @param {?DOMDocument} doc
* @param {boolean} isInShadowTree
* @param {!Protocol.DOM.Node} payload
* @return {!SDK.DOMNode}
@@ -54,7 +54,7 @@ SDK.DOMNode = class {
}
/**
- * @param {?SDK.DOMDocument} doc
+ * @param {?DOMDocument} doc
* @param {boolean} isInShadowTree
* @param {!Protocol.DOM.Node} payload
*/
@@ -81,8 +81,9 @@ SDK.DOMNode = class {
this._attributes = [];
this._attributesMap = {};
- if (payload.attributes)
+ if (payload.attributes) {
this._setAttributesPayload(payload.attributes);
+ }
/** @type {!Map<string, ?>} */
this._markers = new Map();
@@ -113,14 +114,15 @@ SDK.DOMNode = class {
}
if (payload.contentDocument) {
- this._contentDocument = new SDK.DOMDocument(this._domModel, payload.contentDocument);
+ this._contentDocument = new DOMDocument(this._domModel, payload.contentDocument);
this._contentDocument.parentNode = this;
this._children = [];
} else if ((payload.nodeName === 'IFRAME' || payload.nodeName === 'PORTAL') && payload.frameId) {
const childTarget = SDK.targetManager.targetById(payload.frameId);
- const childModel = childTarget ? childTarget.model(SDK.DOMModel) : null;
- if (childModel)
+ const childModel = childTarget ? childTarget.model(DOMModel) : null;
+ if (childModel) {
this._childDocumentPromiseForTesting = childModel.requestDocument();
+ }
this._children = [];
}
@@ -130,20 +132,24 @@ SDK.DOMNode = class {
this._children = [];
}
- if (payload.distributedNodes)
+ if (payload.distributedNodes) {
this._setDistributedNodePayloads(payload.distributedNodes);
+ }
- if (payload.children)
+ if (payload.children) {
this._setChildrenPayload(payload.children);
+ }
this._setPseudoElements(payload.pseudoElements);
if (this._nodeType === Node.ELEMENT_NODE) {
// HTML and BODY from internal iframes should not overwrite top-level ones.
- if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === 'HTML')
+ if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === 'HTML') {
this.ownerDocument.documentElement = this;
- if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === 'BODY')
+ }
+ if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === 'BODY') {
this.ownerDocument.body = this;
+ }
} else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
this.publicId = payload.publicId;
this.systemId = payload.systemId;
@@ -165,8 +171,9 @@ SDK.DOMNode = class {
* @return {!Promise<?Protocol.Runtime.StackTrace>}
*/
creationStackTrace() {
- if (this._creationStackTrace)
+ if (this._creationStackTrace) {
return this._creationStackTrace;
+ }
const stackTracesPromise = this._agent.invoke_getNodeStackTraces({nodeId: this.id});
this._creationStackTrace = stackTracesPromise.then(res => res.creation);
@@ -174,7 +181,7 @@ SDK.DOMNode = class {
}
/**
- * @return {!SDK.DOMModel}
+ * @return {!DOMModel}
*/
domModel() {
return this._domModel;
@@ -296,8 +303,9 @@ SDK.DOMNode = class {
* @return {?SDK.DOMNode}
*/
beforePseudoElement() {
- if (!this._pseudoElements)
+ if (!this._pseudoElements) {
return null;
+ }
return this._pseudoElements.get(SDK.DOMNode.PseudoElementNames.Before);
}
@@ -305,8 +313,9 @@ SDK.DOMNode = class {
* @return {?SDK.DOMNode}
*/
afterPseudoElement() {
- if (!this._pseudoElements)
+ if (!this._pseudoElements) {
return null;
+ }
return this._pseudoElements.get(SDK.DOMNode.PseudoElementNames.After);
}
@@ -319,7 +328,7 @@ SDK.DOMNode = class {
}
/**
- * @return {!Array.<!SDK.DOMNodeShortcut>}
+ * @return {!Array.<!DOMNodeShortcut>}
*/
distributedNodes() {
return this._distributedNodes || [];
@@ -344,12 +353,14 @@ SDK.DOMNode = class {
* @return {?SDK.DOMNode}
*/
ancestorShadowRoot() {
- if (!this._isInShadowTree)
+ if (!this._isInShadowTree) {
return null;
+ }
let current = this;
- while (current && !current.isShadowRoot())
+ while (current && !current.isShadowRoot()) {
current = current.parentNode;
+ }
return current;
}
@@ -358,8 +369,9 @@ SDK.DOMNode = class {
*/
ancestorUserAgentShadowRoot() {
const ancestorShadowRoot = this.ancestorShadowRoot();
- if (!ancestorShadowRoot)
+ if (!ancestorShadowRoot) {
return null;
+ }
return ancestorShadowRoot.shadowRootType() === SDK.DOMNode.ShadowRootTypes.UserAgent ? ancestorShadowRoot : null;
}
@@ -382,16 +394,19 @@ SDK.DOMNode = class {
*/
nodeNameInCorrectCase() {
const shadowRootType = this.shadowRootType();
- if (shadowRootType)
+ if (shadowRootType) {
return '#shadow-root (' + shadowRootType + ')';
+ }
// If there is no local name, it's case sensitive
- if (!this.localName())
+ if (!this.localName()) {
return this.nodeName();
+ }
// If the names are different lengths, there is a prefix and it's case sensitive
- if (this.localName().length !== this.nodeName().length)
+ if (this.localName().length !== this.nodeName().length) {
return this.nodeName();
+ }
// Return the localname, which will be case insensitive if its an html node
return this.localName();
@@ -403,10 +418,12 @@ SDK.DOMNode = class {
*/
setNodeName(name, callback) {
this._agent.invoke_setNodeName({nodeId: this.id, name}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null, this._domModel.nodeForId(response.nodeId));
+ }
});
}
@@ -430,10 +447,12 @@ SDK.DOMNode = class {
*/
setNodeValue(value, callback) {
this._agent.invoke_setNodeValue({nodeId: this.id, value}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null);
+ }
});
}
@@ -453,10 +472,12 @@ SDK.DOMNode = class {
*/
setAttribute(name, text, callback) {
this._agent.invoke_setAttributesAsText({nodeId: this.id, text, name}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null);
+ }
});
}
@@ -467,10 +488,12 @@ SDK.DOMNode = class {
*/
setAttributeValue(name, value, callback) {
this._agent.invoke_setAttributeValue({nodeId: this.id, name, value}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null);
+ }
});
}
@@ -496,12 +519,14 @@ SDK.DOMNode = class {
*/
async removeAttribute(name) {
const response = await this._agent.invoke_removeAttribute({nodeId: this.id, name});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return;
+ }
delete this._attributesMap[name];
const index = this._attributes.findIndex(attr => attr.name === name);
- if (index !== -1)
+ if (index !== -1) {
this._attributes.splice(index, 1);
+ }
this._domModel.markUndoableState();
}
@@ -541,10 +566,12 @@ SDK.DOMNode = class {
*/
setOuterHTML(html, callback) {
this._agent.invoke_setOuterHTML({nodeId: this.id, outerHTML: html}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null);
+ }
});
}
@@ -553,10 +580,12 @@ SDK.DOMNode = class {
*/
removeNode(callback) {
this._agent.invoke_removeNode({nodeId: this.id}).then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null);
+ }
});
}
@@ -565,8 +594,9 @@ SDK.DOMNode = class {
*/
async copyNode() {
const text = await this._agent.getOuterHTML(this.id);
- if (text !== null)
- InspectorFrontendHost.copyText(text);
+ if (text !== null) {
+ Host.InspectorFrontendHost.copyText(text);
+ }
return text;
}
@@ -599,13 +629,15 @@ SDK.DOMNode = class {
* @return {boolean}
*/
isAncestor(node) {
- if (!node)
+ if (!node) {
return false;
+ }
let currentNode = node.parentNode;
while (currentNode) {
- if (this === currentNode)
+ if (this === currentNode) {
return true;
+ }
currentNode = currentNode.parentNode;
}
return false;
@@ -624,8 +656,9 @@ SDK.DOMNode = class {
*/
frameId() {
let node = this.parentNode || this;
- while (!node._frameOwnerFrameId && node.parentNode)
+ while (!node._frameOwnerFrameId && node.parentNode) {
node = node.parentNode;
+ }
return node._frameOwnerFrameId;
}
@@ -645,11 +678,13 @@ SDK.DOMNode = class {
const value = attrs[i + 1];
this._addAttribute(name, value);
- if (attributesChanged)
+ if (attributesChanged) {
continue;
+ }
- if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value)
+ if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value) {
attributesChanged = true;
+ }
}
return attributesChanged;
}
@@ -683,8 +718,9 @@ SDK.DOMNode = class {
}
node.parentNode = null;
this._subtreeMarkerCount -= node._subtreeMarkerCount;
- if (node._subtreeMarkerCount)
- this._domModel.dispatchEventToListeners(SDK.DOMModel.Events.MarkersChanged, this);
+ if (node._subtreeMarkerCount) {
+ this._domModel.dispatchEventToListeners(Events.MarkersChanged, this);
+ }
this._renumber();
}
@@ -706,8 +742,9 @@ SDK.DOMNode = class {
*/
_setPseudoElements(payloads) {
this._pseudoElements = new Map();
- if (!payloads)
+ if (!payloads) {
return;
+ }
for (let i = 0; i < payloads.length; ++i) {
const node = SDK.DOMNode.create(this._domModel, this.ownerDocument, this._isInShadowTree, payloads[i]);
@@ -723,7 +760,7 @@ SDK.DOMNode = class {
this._distributedNodes = [];
for (const payload of payloads) {
this._distributedNodes.push(
- new SDK.DOMNodeShortcut(this._domModel.target(), payload.backendNodeId, payload.nodeType, payload.nodeName));
+ new DOMNodeShortcut(this._domModel.target(), payload.backendNodeId, payload.nodeType, payload.nodeName));
}
}
@@ -761,10 +798,11 @@ SDK.DOMNode = class {
*/
_setAttribute(name, value) {
const attr = this._attributesMap[name];
- if (attr)
+ if (attr) {
attr.value = value;
- else
+ } else {
this._addAttribute(name, value);
+ }
}
/**
@@ -788,10 +826,12 @@ SDK.DOMNode = class {
.invoke_copyTo(
{nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined})
.then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null, response.nodeId);
+ }
});
}
@@ -805,10 +845,12 @@ SDK.DOMNode = class {
.invoke_moveTo(
{nodeId: this.id, targetNodeId: targetNode.id, insertBeforeNodeId: anchorNode ? anchorNode.id : undefined})
.then(response => {
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._domModel.markUndoableState();
- if (callback)
+ }
+ if (callback) {
callback(response[Protocol.Error] || null, this._domModel.nodeForId(response.nodeId));
+ }
});
}
@@ -825,24 +867,29 @@ SDK.DOMNode = class {
*/
setMarker(name, value) {
if (value === null) {
- if (!this._markers.has(name))
+ if (!this._markers.has(name)) {
return;
+ }
this._markers.delete(name);
- for (let node = this; node; node = node.parentNode)
+ for (let node = this; node; node = node.parentNode) {
--node._subtreeMarkerCount;
- for (let node = this; node; node = node.parentNode)
- this._domModel.dispatchEventToListeners(SDK.DOMModel.Events.MarkersChanged, node);
+ }
+ for (let node = this; node; node = node.parentNode) {
+ this._domModel.dispatchEventToListeners(Events.MarkersChanged, node);
+ }
return;
}
if (this.parentNode && !this._markers.has(name)) {
- for (let node = this; node; node = node.parentNode)
+ for (let node = this; node; node = node.parentNode) {
++node._subtreeMarkerCount;
+ }
}
this._markers.set(name, value);
- for (let node = this; node; node = node.parentNode)
- this._domModel.dispatchEventToListeners(SDK.DOMModel.Events.MarkersChanged, node);
+ for (let node = this; node; node = node.parentNode) {
+ this._domModel.dispatchEventToListeners(Events.MarkersChanged, node);
+ }
}
/**
@@ -862,14 +909,18 @@ SDK.DOMNode = class {
* @param {!SDK.DOMNode} node
*/
function traverse(node) {
- if (!node._subtreeMarkerCount)
+ if (!node._subtreeMarkerCount) {
return;
- for (const marker of node._markers.keys())
+ }
+ for (const marker of node._markers.keys()) {
visitor(node, marker);
- if (!node._children)
+ }
+ if (!node._children) {
return;
- for (const child of node._children)
+ }
+ for (const child of node._children) {
traverse(child);
+ }
}
traverse(this);
}
@@ -879,11 +930,13 @@ SDK.DOMNode = class {
* @return {?string}
*/
resolveURL(url) {
- if (!url)
+ if (!url) {
return url;
+ }
for (let frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
- if (frameOwnerCandidate.baseURL)
+ if (frameOwnerCandidate.baseURL) {
return Common.ParsedURL.completeURL(frameOwnerCandidate.baseURL, url);
+ }
}
return null;
}
@@ -919,11 +972,13 @@ SDK.DOMNode = class {
let node = this;
while (true) {
let ancestor = node.ancestorUserAgentShadowRoot();
- if (!ancestor)
+ if (!ancestor) {
break;
+ }
ancestor = node.ancestorShadowHost();
- if (!ancestor)
+ if (!ancestor) {
break;
+ }
// User agent shadow root, keep climbing up.
node = ancestor;
}
@@ -935,19 +990,22 @@ SDK.DOMNode = class {
*/
enclosingElementOrSelf() {
let node = this;
- if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
+ if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) {
node = node.parentNode;
+ }
- if (node && node.nodeType() !== Node.ELEMENT_NODE)
+ if (node && node.nodeType() !== Node.ELEMENT_NODE) {
node = null;
+ }
return node;
}
async scrollIntoView() {
const node = this.enclosingElementOrSelf();
const object = await node.resolveToObject();
- if (!object)
+ if (!object) {
return;
+ }
object.callFunction(scrollIntoView);
object.release();
node.highlightForTwoSeconds();
@@ -964,8 +1022,9 @@ SDK.DOMNode = class {
async focus() {
const node = this.enclosingElementOrSelf();
const object = await node.resolveToObject();
- if (!object)
+ if (!object) {
return;
+ }
await object.callFunction(focusInPage);
object.release();
node.highlightForTwoSeconds();
@@ -985,25 +1044,28 @@ SDK.DOMNode = class {
*/
simpleSelector() {
const lowerCaseName = this.localName() || this.nodeName().toLowerCase();
- if (this.nodeType() !== Node.ELEMENT_NODE)
+ if (this.nodeType() !== Node.ELEMENT_NODE) {
return lowerCaseName;
+ }
if (lowerCaseName === 'input' && this.getAttribute('type') && !this.getAttribute('id') &&
- !this.getAttribute('class'))
+ !this.getAttribute('class')) {
return lowerCaseName + '[type="' + this.getAttribute('type') + '"]';
- if (this.getAttribute('id'))
+ }
+ if (this.getAttribute('id')) {
return lowerCaseName + '#' + this.getAttribute('id');
+ }
if (this.getAttribute('class')) {
return (lowerCaseName === 'div' ? '' : lowerCaseName) + '.' +
this.getAttribute('class').trim().replace(/\s+/g, '.');
}
return lowerCaseName;
}
-};
+}
/**
* @enum {string}
*/
-SDK.DOMNode.PseudoElementNames = {
+DOMNode.PseudoElementNames = {
Before: 'before',
After: 'after'
};
@@ -1011,25 +1073,22 @@ SDK.DOMNode.PseudoElementNames = {
/**
* @enum {string}
*/
-SDK.DOMNode.ShadowRootTypes = {
+DOMNode.ShadowRootTypes = {
UserAgent: 'user-agent',
Open: 'open',
Closed: 'closed'
};
-/** @typedef {{name: string, value: string, _node: SDK.DOMNode}} */
-SDK.DOMNode.Attribute;
-
/**
* @unrestricted
*/
-SDK.DeferredDOMNode = class {
+export class DeferredDOMNode {
/**
* @param {!SDK.Target} target
* @param {number} backendNodeId
*/
constructor(target, backendNodeId) {
- this._domModel = /** @type {!SDK.DOMModel} */ (target.model(SDK.DOMModel));
+ this._domModel = /** @type {!DOMModel} */ (target.model(DOMModel));
this._backendNodeId = backendNodeId;
}
@@ -1056,7 +1115,7 @@ SDK.DeferredDOMNode = class {
}
/**
- * @return {!SDK.DOMModel}
+ * @return {!DOMModel}
*/
domModel() {
return this._domModel;
@@ -1065,12 +1124,12 @@ SDK.DeferredDOMNode = class {
highlight() {
this._domModel.overlayModel().highlightInOverlay({deferredNode: this});
}
-};
+}
/**
* @unrestricted
*/
-SDK.DOMNodeShortcut = class {
+export class DOMNodeShortcut {
/**
* @param {!SDK.Target} target
* @param {number} backendNodeId
@@ -1082,14 +1141,14 @@ SDK.DOMNodeShortcut = class {
this.nodeName = nodeName;
this.deferredNode = new SDK.DeferredDOMNode(target, backendNodeId);
}
-};
+}
/**
* @unrestricted
*/
-SDK.DOMDocument = class extends SDK.DOMNode {
+export class DOMDocument extends DOMNode {
/**
- * @param {!SDK.DOMModel} domModel
+ * @param {!DOMModel} domModel
* @param {!Protocol.DOM.Node} payload
*/
constructor(domModel, payload) {
@@ -1098,12 +1157,12 @@ SDK.DOMDocument = class extends SDK.DOMNode {
this.documentURL = payload.documentURL || '';
this.baseURL = payload.baseURL || '';
}
-};
+}
/**
* @unrestricted
*/
-SDK.DOMModel = class extends SDK.SDKModel {
+export default class DOMModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -1114,19 +1173,21 @@ SDK.DOMModel = class extends SDK.SDKModel {
/** @type {!Object.<number, !SDK.DOMNode>} */
this._idToDOMNode = {};
- /** @type {?SDK.DOMDocument} */
+ /** @type {?DOMDocument} */
this._document = null;
/** @type {!Set<number>} */
this._attributeLoadNodeIds = new Set();
- target.registerDOMDispatcher(new SDK.DOMDispatcher(this));
+ target.registerDOMDispatcher(new DOMDispatcher(this));
this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
- if (!target.suspended())
+ if (!target.suspended()) {
this._agent.enable();
+ }
- if (Runtime.experiments.isEnabled('captureNodeCreationStacks'))
+ if (Root.Runtime.experiments.isEnabled('captureNodeCreationStacks')) {
this._agent.setNodeStackTracesEnabled(true);
+ }
}
/**
@@ -1151,53 +1212,59 @@ SDK.DOMModel = class extends SDK.SDKModel {
}
static cancelSearch() {
- for (const domModel of SDK.targetManager.models(SDK.DOMModel))
+ for (const domModel of SDK.targetManager.models(DOMModel)) {
domModel._cancelSearch();
+ }
}
/**
* @param {!SDK.DOMNode} node
*/
_scheduleMutationEvent(node) {
- if (!this.hasEventListeners(SDK.DOMModel.Events.DOMMutated))
+ if (!this.hasEventListeners(Events.DOMMutated)) {
return;
+ }
this._lastMutationId = (this._lastMutationId || 0) + 1;
Promise.resolve().then(callObserve.bind(this, node, this._lastMutationId));
/**
- * @this {SDK.DOMModel}
+ * @this {DOMModel}
* @param {!SDK.DOMNode} node
* @param {number} mutationId
*/
function callObserve(node, mutationId) {
- if (!this.hasEventListeners(SDK.DOMModel.Events.DOMMutated) || this._lastMutationId !== mutationId)
+ if (!this.hasEventListeners(Events.DOMMutated) || this._lastMutationId !== mutationId) {
return;
+ }
- this.dispatchEventToListeners(SDK.DOMModel.Events.DOMMutated, node);
+ this.dispatchEventToListeners(Events.DOMMutated, node);
}
}
/**
- * @return {!Promise<!SDK.DOMDocument>}
+ * @return {!Promise<!DOMDocument>}
*/
requestDocument() {
- if (this._document)
+ if (this._document) {
return Promise.resolve(this._document);
- if (!this._pendingDocumentRequestPromise)
+ }
+ if (!this._pendingDocumentRequestPromise) {
this._pendingDocumentRequestPromise = this._requestDocument();
+ }
return this._pendingDocumentRequestPromise;
}
/**
- * @return {!Promise<!SDK.DOMDocument>}
+ * @return {!Promise<?DOMDocument>}
*/
async _requestDocument() {
const documentPayload = await this._agent.getDocument();
delete this._pendingDocumentRequestPromise;
- if (documentPayload)
+ if (documentPayload) {
this._setDocument(documentPayload);
+ }
if (!this._document) {
console.error('No document');
return null;
@@ -1207,8 +1274,9 @@ SDK.DOMModel = class extends SDK.SDKModel {
if (parentModel && !this._frameOwnerNode) {
await parentModel.requestDocument();
const response = await parentModel._agent.invoke_getFrameOwner({frameId: this.target().id()});
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._frameOwnerNode = parentModel.nodeForId(response.nodeId);
+ }
}
// Document could have been cleared by now.
@@ -1218,17 +1286,16 @@ SDK.DOMModel = class extends SDK.SDKModel {
this._frameOwnerNode._children = [];
if (this._document) {
this._document.parentNode = this._frameOwnerNode;
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeInserted, this._document);
+ this.dispatchEventToListeners(Events.NodeInserted, this._document);
} else if (oldDocument) {
- this.dispatchEventToListeners(
- SDK.DOMModel.Events.NodeRemoved, {node: oldDocument, parent: this._frameOwnerNode});
+ this.dispatchEventToListeners(Events.NodeRemoved, {node: oldDocument, parent: this._frameOwnerNode});
}
}
return this._document;
}
/**
- * @return {?SDK.DOMDocument}
+ * @return {?DOMDocument}
*/
existingDocument() {
return this._document;
@@ -1260,13 +1327,15 @@ SDK.DOMModel = class extends SDK.SDKModel {
await this.requestDocument();
const backendNodeIdsArray = backendNodeIds.valuesArray();
const nodeIds = await this._agent.pushNodesByBackendIdsToFrontend(backendNodeIdsArray);
- if (!nodeIds)
+ if (!nodeIds) {
return null;
+ }
/** @type {!Map<number, ?SDK.DOMNode>} */
const map = new Map();
for (let i = 0; i < nodeIds.length; ++i) {
- if (nodeIds[i])
+ if (nodeIds[i]) {
map.set(backendNodeIdsArray[i], this.nodeForId(nodeIds[i]));
+ }
}
return map;
}
@@ -1296,11 +1365,12 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_attributeModified(nodeId, name, value) {
const node = this._idToDOMNode[nodeId];
- if (!node)
+ if (!node) {
return;
+ }
node._setAttribute(name, value);
- this.dispatchEventToListeners(SDK.DOMModel.Events.AttrModified, {node: node, name: name});
+ this.dispatchEventToListeners(Events.AttrModified, {node: node, name: name});
this._scheduleMutationEvent(node);
}
@@ -1310,10 +1380,11 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_attributeRemoved(nodeId, name) {
const node = this._idToDOMNode[nodeId];
- if (!node)
+ if (!node) {
return;
+ }
node._removeAttribute(name);
- this.dispatchEventToListeners(SDK.DOMModel.Events.AttrRemoved, {node: node, name: name});
+ this.dispatchEventToListeners(Events.AttrRemoved, {node: node, name: name});
this._scheduleMutationEvent(node);
}
@@ -1322,8 +1393,9 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_inlineStyleInvalidated(nodeIds) {
this._attributeLoadNodeIds.addAll(nodeIds);
- if (!this._loadNodeAttributesTimeout)
+ if (!this._loadNodeAttributesTimeout) {
this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 20);
+ }
}
_loadNodeAttributes() {
@@ -1335,10 +1407,11 @@ SDK.DOMModel = class extends SDK.SDKModel {
return;
}
const node = this._idToDOMNode[nodeId];
- if (!node)
+ if (!node) {
return;
+ }
if (node._setAttributesPayload(attributes)) {
- this.dispatchEventToListeners(SDK.DOMModel.Events.AttrModified, {node: node, name: 'style'});
+ this.dispatchEventToListeners(Events.AttrModified, {node: node, name: 'style'});
this._scheduleMutationEvent(node);
}
});
@@ -1353,7 +1426,7 @@ SDK.DOMModel = class extends SDK.SDKModel {
_characterDataModified(nodeId, newValue) {
const node = this._idToDOMNode[nodeId];
node._nodeValue = newValue;
- this.dispatchEventToListeners(SDK.DOMModel.Events.CharacterDataModified, node);
+ this.dispatchEventToListeners(Events.CharacterDataModified, node);
this._scheduleMutationEvent(node);
}
@@ -1370,8 +1443,9 @@ SDK.DOMModel = class extends SDK.SDKModel {
// if it hits backend post document update, it will contain most recent result.
const documentWasRequested = this._document || this._pendingDocumentRequestPromise;
this._setDocument(null);
- if (this.parentModel() && documentWasRequested)
+ if (this.parentModel() && documentWasRequested) {
this.requestDocument();
+ }
}
/**
@@ -1379,24 +1453,27 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_setDocument(payload) {
this._idToDOMNode = {};
- if (payload && 'nodeId' in payload)
- this._document = new SDK.DOMDocument(this, payload);
- else
+ if (payload && 'nodeId' in payload) {
+ this._document = new DOMDocument(this, payload);
+ } else {
this._document = null;
+ }
SDK.domModelUndoStack._dispose(this);
- if (!this.parentModel())
- this.dispatchEventToListeners(SDK.DOMModel.Events.DocumentUpdated, this);
+ if (!this.parentModel()) {
+ this.dispatchEventToListeners(Events.DocumentUpdated, this);
+ }
}
/**
* @param {!Protocol.DOM.Node} payload
*/
_setDetachedRoot(payload) {
- if (payload.nodeName === '#document')
- new SDK.DOMDocument(this, payload);
- else
+ if (payload.nodeName === '#document') {
+ new DOMDocument(this, payload);
+ } else {
SDK.DOMNode.create(this, null, false, payload);
+ }
}
/**
@@ -1420,7 +1497,7 @@ SDK.DOMModel = class extends SDK.SDKModel {
_childNodeCountUpdated(nodeId, newValue) {
const node = this._idToDOMNode[nodeId];
node._childNodeCount = newValue;
- this.dispatchEventToListeners(SDK.DOMModel.Events.ChildNodeCountUpdated, node);
+ this.dispatchEventToListeners(Events.ChildNodeCountUpdated, node);
this._scheduleMutationEvent(node);
}
@@ -1434,7 +1511,7 @@ SDK.DOMModel = class extends SDK.SDKModel {
const prev = this._idToDOMNode[prevId];
const node = parent._insertChild(prev, payload);
this._idToDOMNode[node.id] = node;
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeInserted, node);
+ this.dispatchEventToListeners(Events.NodeInserted, node);
this._scheduleMutationEvent(node);
}
@@ -1447,7 +1524,7 @@ SDK.DOMModel = class extends SDK.SDKModel {
const node = this._idToDOMNode[nodeId];
parent._removeChild(node);
this._unbind(node);
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeRemoved, {node: node, parent: parent});
+ this.dispatchEventToListeners(Events.NodeRemoved, {node: node, parent: parent});
this._scheduleMutationEvent(node);
}
@@ -1457,13 +1534,14 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_shadowRootPushed(hostId, root) {
const host = this._idToDOMNode[hostId];
- if (!host)
+ if (!host) {
return;
+ }
const node = SDK.DOMNode.create(this, host.ownerDocument, true, root);
node.parentNode = host;
this._idToDOMNode[node.id] = node;
host._shadowRoots.unshift(node);
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeInserted, node);
+ this.dispatchEventToListeners(Events.NodeInserted, node);
this._scheduleMutationEvent(node);
}
@@ -1473,14 +1551,16 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_shadowRootPopped(hostId, rootId) {
const host = this._idToDOMNode[hostId];
- if (!host)
+ if (!host) {
return;
+ }
const root = this._idToDOMNode[rootId];
- if (!root)
+ if (!root) {
return;
+ }
host._removeChild(root);
this._unbind(root);
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeRemoved, {node: root, parent: host});
+ this.dispatchEventToListeners(Events.NodeRemoved, {node: root, parent: host});
this._scheduleMutationEvent(root);
}
@@ -1490,14 +1570,15 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_pseudoElementAdded(parentId, pseudoElement) {
const parent = this._idToDOMNode[parentId];
- if (!parent)
+ if (!parent) {
return;
+ }
const node = SDK.DOMNode.create(this, parent.ownerDocument, false, pseudoElement);
node.parentNode = parent;
this._idToDOMNode[node.id] = node;
console.assert(!parent._pseudoElements.get(node.pseudoType()));
parent._pseudoElements.set(node.pseudoType(), node);
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeInserted, node);
+ this.dispatchEventToListeners(Events.NodeInserted, node);
this._scheduleMutationEvent(node);
}
@@ -1507,14 +1588,16 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_pseudoElementRemoved(parentId, pseudoElementId) {
const parent = this._idToDOMNode[parentId];
- if (!parent)
+ if (!parent) {
return;
+ }
const pseudoElement = this._idToDOMNode[pseudoElementId];
- if (!pseudoElement)
+ if (!pseudoElement) {
return;
+ }
parent._removeChild(pseudoElement);
this._unbind(pseudoElement);
- this.dispatchEventToListeners(SDK.DOMModel.Events.NodeRemoved, {node: pseudoElement, parent: parent});
+ this.dispatchEventToListeners(Events.NodeRemoved, {node: pseudoElement, parent: parent});
this._scheduleMutationEvent(pseudoElement);
}
@@ -1524,10 +1607,11 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_distributedNodesUpdated(insertionPointId, distributedNodes) {
const insertionPoint = this._idToDOMNode[insertionPointId];
- if (!insertionPoint)
+ if (!insertionPoint) {
return;
+ }
insertionPoint._setDistributedNodePayloads(distributedNodes);
- this.dispatchEventToListeners(SDK.DOMModel.Events.DistributedNodesChanged, insertionPoint);
+ this.dispatchEventToListeners(Events.DistributedNodesChanged, insertionPoint);
this._scheduleMutationEvent(insertionPoint);
}
@@ -1536,15 +1620,19 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
_unbind(node) {
delete this._idToDOMNode[node.id];
- for (let i = 0; node._children && i < node._children.length; ++i)
+ for (let i = 0; node._children && i < node._children.length; ++i) {
this._unbind(node._children[i]);
- for (let i = 0; i < node._shadowRoots.length; ++i)
+ }
+ for (let i = 0; i < node._shadowRoots.length; ++i) {
this._unbind(node._shadowRoots[i]);
+ }
const pseudoElements = node.pseudoElements();
- for (const value of pseudoElements.values())
+ for (const value of pseudoElements.values()) {
this._unbind(value);
- if (node._templateContent)
+ }
+ if (node._templateContent) {
this._unbind(node._templateContent);
+ }
}
/**
@@ -1554,8 +1642,9 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
async performSearch(query, includeUserAgentShadowDOM) {
const response = await this._agent.invoke_performSearch({query, includeUserAgentShadowDOM});
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this._searchId = response.searchId;
+ }
return response[Protocol.Error] ? 0 : response.resultCount;
}
@@ -1564,15 +1653,17 @@ SDK.DOMModel = class extends SDK.SDKModel {
* @return {!Promise<?SDK.DOMNode>}
*/
async searchResult(index) {
- if (!this._searchId)
+ if (!this._searchId) {
return null;
+ }
const nodeIds = await this._agent.getSearchResults(this._searchId, index, index + 1);
return nodeIds && nodeIds.length === 1 ? this.nodeForId(nodeIds[0]) : null;
}
_cancelSearch() {
- if (!this._searchId)
+ if (!this._searchId) {
return;
+ }
this._agent.discardSearchResults(this._searchId);
delete this._searchId;
}
@@ -1618,8 +1709,9 @@ SDK.DOMModel = class extends SDK.SDKModel {
*/
async nodeForLocation(x, y, includeUserAgentShadowDOM) {
const response = await this._agent.invoke_getNodeForLocation({x, y, includeUserAgentShadowDOM});
- if (response[Protocol.Error] || !response.nodeId)
+ if (response[Protocol.Error] || !response.nodeId) {
return null;
+ }
return this.nodeForId(response.nodeId);
}
@@ -1655,18 +1747,16 @@ SDK.DOMModel = class extends SDK.SDKModel {
}
/**
- * @return {?SDK.DOMModel}
+ * @return {?DOMModel}
*/
parentModel() {
const parentTarget = this.target().parentTarget();
- return parentTarget ? parentTarget.model(SDK.DOMModel) : null;
+ return parentTarget ? parentTarget.model(DOMModel) : null;
}
-};
-
-SDK.SDKModel.register(SDK.DOMModel, SDK.Target.Capability.DOM, true);
+}
/** @enum {symbol} */
-SDK.DOMModel.Events = {
+export const Events = {
AttrModified: Symbol('AttrModified'),
AttrRemoved: Symbol('AttrRemoved'),
CharacterDataModified: Symbol('CharacterDataModified'),
@@ -1679,14 +1769,13 @@ SDK.DOMModel.Events = {
MarkersChanged: Symbol('MarkersChanged')
};
-
/**
* @implements {Protocol.DOMDispatcher}
* @unrestricted
*/
-SDK.DOMDispatcher = class {
+export class DOMDispatcher {
/**
- * @param {!SDK.DOMModel} domModel
+ * @param {!DOMModel} domModel
*/
constructor(domModel) {
this._domModel = domModel;
@@ -1816,19 +1905,19 @@ SDK.DOMDispatcher = class {
distributedNodesUpdated(insertionPointId, distributedNodes) {
this._domModel._distributedNodesUpdated(insertionPointId, distributedNodes);
}
-};
+}
-SDK.DOMModelUndoStack = class {
+export class DOMModelUndoStack {
constructor() {
- /** @type {!Array<!SDK.DOMModel>} */
+ /** @type {!Array<!DOMModel>} */
this._stack = [];
this._index = 0;
- /** @type {?SDK.DOMModel} */
+ /** @type {?DOMModel} */
this._lastModelWithMinorChange = null;
}
/**
- * @param {!SDK.DOMModel} model
+ * @param {!DOMModel} model
* @param {boolean} minorChange
*/
_markUndoableState(model, minorChange) {
@@ -1840,8 +1929,9 @@ SDK.DOMModelUndoStack = class {
}
// Previous minor change is already in the stack.
- if (minorChange && this._lastModelWithMinorChange === model)
+ if (minorChange && this._lastModelWithMinorChange === model) {
return;
+ }
this._stack = this._stack.slice(0, this._index);
this._stack.push(model);
@@ -1861,8 +1951,9 @@ SDK.DOMModelUndoStack = class {
* @return {!Promise}
*/
undo() {
- if (this._index === 0)
+ if (this._index === 0) {
return Promise.resolve();
+ }
--this._index;
this._lastModelWithMinorChange = null;
return this._stack[this._index]._agent.undo();
@@ -1872,27 +1963,65 @@ SDK.DOMModelUndoStack = class {
* @return {!Promise}
*/
redo() {
- if (this._index >= this._stack.length)
+ if (this._index >= this._stack.length) {
return Promise.resolve();
+ }
++this._index;
this._lastModelWithMinorChange = null;
return this._stack[this._index - 1]._agent.redo();
}
/**
- * @param {!SDK.DOMModel} model
+ * @param {!DOMModel} model
*/
_dispose(model) {
let shift = 0;
for (let i = 0; i < this._index; ++i) {
- if (this._stack[i] === model)
+ if (this._stack[i] === model) {
++shift;
+ }
}
this._stack.remove(model);
this._index -= shift;
- if (this._lastModelWithMinorChange === model)
+ if (this._lastModelWithMinorChange === model) {
this._lastModelWithMinorChange = null;
+ }
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.DOMModel = DOMModel;
+
+/** @enum {symbol} */
+SDK.DOMModel.Events = Events;
+
+/** @constructor */
+SDK.DeferredDOMNode = DeferredDOMNode;
+
+/** @constructor */
+SDK.DOMNodeShortcut = DOMNodeShortcut;
+
+/** @constructor */
+SDK.DOMDocument = DOMDocument;
+
+/** @constructor */
+SDK.DOMDispatcher = DOMDispatcher;
+
+/** @constructor */
+SDK.DOMModelUndoStack = DOMModelUndoStack;
+
+/** @constructor */
+SDK.DOMNode = DOMNode;
+
+SDK.domModelUndoStack = new DOMModelUndoStack();
+
+/** @typedef {{name: string, value: string, _node: SDK.DOMNode}} */
+SDK.DOMNode.Attribute;
-SDK.domModelUndoStack = new SDK.DOMModelUndoStack();
+SDK.SDKModel.register(DOMModel, SDK.Target.Capability.DOM, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
index d294bfa2a35..c983db03f87 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
@@ -31,14 +31,14 @@
/**
* @unrestricted
*/
-SDK.DebuggerModel = class extends SDK.SDKModel {
+export default class DebuggerModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
- target.registerDebuggerDispatcher(new SDK.DebuggerDispatcher(this));
+ target.registerDebuggerDispatcher(new DebuggerDispatcher(this));
this._agent = target.debuggerAgent();
this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));
@@ -47,7 +47,7 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
/** @type {!Map<string, !SDK.Script>} */
this._sourceMapIdToScript = new Map();
- /** @type {?SDK.DebuggerPausedDetails} */
+ /** @type {?DebuggerPausedDetails} */
this._debuggerPausedDetails = null;
/** @type {!Map<string, !SDK.Script>} */
this._scripts = new Map();
@@ -65,8 +65,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
Common.moduleSetting('disableAsyncStackTraces').addChangeListener(this._asyncStackTracesStateChanged, this);
Common.moduleSetting('breakpointsActive').addChangeListener(this._breakpointsActiveChanged, this);
- if (!target.suspended())
+ if (!target.suspended()) {
this._enableDebugger();
+ }
/** @type {!Map<string, string>} */
this._stringMap = new Map();
@@ -82,8 +83,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @return {?string}
*/
static _sourceMapId(executionContextId, sourceURL, sourceMapURL) {
- if (!sourceMapURL)
+ if (!sourceMapURL) {
return null;
+ }
return executionContextId + ':' + sourceURL + ':' + sourceMapURL;
}
@@ -112,23 +114,26 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
_enableDebugger() {
- if (this._debuggerEnabled)
+ if (this._debuggerEnabled) {
return Promise.resolve();
+ }
this._debuggerEnabled = true;
// Set a limit for the total size of collected script sources retained by debugger.
// 10MB for remote frontends, 100MB for others.
- const isRemoteFrontend = Runtime.queryParam('remoteFrontend') || Runtime.queryParam('ws');
+ const isRemoteFrontend = Root.Runtime.queryParam('remoteFrontend') || Root.Runtime.queryParam('ws');
const maxScriptsCacheSize = isRemoteFrontend ? 10e6 : 100e6;
const enablePromise = this._agent.enable(maxScriptsCacheSize);
enablePromise.then(this._registerDebugger.bind(this));
this._pauseOnExceptionStateChanged();
this._asyncStackTracesStateChanged();
- if (!Common.moduleSetting('breakpointsActive').get())
+ if (!Common.moduleSetting('breakpointsActive').get()) {
this._breakpointsActiveChanged();
- if (SDK.DebuggerModel._scheduledPauseOnAsyncCall)
+ }
+ if (SDK.DebuggerModel._scheduledPauseOnAsyncCall) {
this._pauseOnAsyncCall(SDK.DebuggerModel._scheduledPauseOnAsyncCall);
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerWasEnabled, this);
+ }
+ this.dispatchEventToListeners(Events.DebuggerWasEnabled, this);
return enablePromise;
}
@@ -136,11 +141,12 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @param {string|null} debuggerId
*/
_registerDebugger(debuggerId) {
- if (!debuggerId)
+ if (!debuggerId) {
return;
+ }
SDK.DebuggerModel._debuggerIdToModel.set(debuggerId, this);
this._debuggerId = debuggerId;
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerIsReadyToPause, this);
+ this.dispatchEventToListeners(Events.DebuggerIsReadyToPause, this);
}
/**
@@ -152,7 +158,7 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
/**
* @param {string} debuggerId
- * @return {?SDK.DebuggerModel}
+ * @return {?DebuggerModel}
*/
static modelForDebuggerId(debuggerId) {
return SDK.DebuggerModel._debuggerIdToModel.get(debuggerId) || null;
@@ -162,15 +168,16 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
_disableDebugger() {
- if (!this._debuggerEnabled)
+ if (!this._debuggerEnabled) {
return Promise.resolve();
+ }
this._debuggerEnabled = false;
const disablePromise = this._agent.disable();
this._isPausing = false;
this._asyncStackTracesStateChanged();
this.globalObjectCleared();
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerWasDisabled);
+ this.dispatchEventToListeners(Events.DebuggerWasDisabled);
SDK.DebuggerModel._debuggerIdToModel.delete(this._debuggerId);
return disablePromise;
}
@@ -190,8 +197,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @param {number} timeout
*/
skipAllPausesUntilReloadOrTimeout(timeout) {
- if (this._skipAllPausesTimeout)
+ if (this._skipAllPausesTimeout) {
clearTimeout(this._skipAllPausesTimeout);
+ }
this._agent.setSkipAllPauses(true);
// If reload happens before the timeout, the flag will be already unset and the timeout callback won't change anything.
this._skipAllPausesTimeout = setTimeout(this._skipAllPauses.bind(this, false), timeout);
@@ -199,12 +207,13 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
_pauseOnExceptionStateChanged() {
let state;
- if (!Common.moduleSetting('pauseOnExceptionEnabled').get())
- state = SDK.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions;
- else if (Common.moduleSetting('pauseOnCaughtException').get())
- state = SDK.DebuggerModel.PauseOnExceptionsState.PauseOnAllExceptions;
- else
- state = SDK.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtExceptions;
+ if (!Common.moduleSetting('pauseOnExceptionEnabled').get()) {
+ state = PauseOnExceptionsState.DontPauseOnExceptions;
+ } else if (Common.moduleSetting('pauseOnCaughtException').get()) {
+ state = PauseOnExceptionsState.PauseOnAllExceptions;
+ } else {
+ state = PauseOnExceptionsState.PauseOnUncaughtExceptions;
+ }
this._agent.setPauseOnExceptions(state);
}
@@ -273,8 +282,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
const scripts = this._scriptsBySourceURL.get(url) || [];
for (let i = 0, l = scripts.length; i < l; ++i) {
const script = scripts[i];
- if (lineNumber === script.lineOffset)
+ if (lineNumber === script.lineOffset) {
minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset;
+ }
}
columnNumber = Math.max(columnNumber, minColumnNumber);
const response = await this._agent.invoke_setBreakpointByUrl({
@@ -284,11 +294,13 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
columnNumber: columnNumber,
condition: condition
});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return {locations: [], breakpointId: null};
- let locations;
- if (response.locations)
- locations = response.locations.map(payload => SDK.DebuggerModel.Location.fromPayload(this, payload));
+ }
+ let locations = [];
+ if (response.locations) {
+ locations = response.locations.map(payload => Location.fromPayload(this, payload));
+ }
return {locations: locations, breakpointId: response.breakpointId};
}
@@ -306,13 +318,15 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
const error = response[Protocol.Error];
if (error) {
// Old V8 backend doesn't support scriptHash argument.
- if (error !== 'Either url or urlRegex must be specified.')
+ if (error !== 'Either url or urlRegex must be specified.') {
return {locations: [], breakpointId: null};
+ }
return this._setBreakpointBySourceId(scriptId, lineNumber, columnNumber, condition);
}
- let locations;
- if (response.locations)
- locations = response.locations.map(payload => SDK.DebuggerModel.Location.fromPayload(this, payload));
+ let locations = [];
+ if (response.locations) {
+ locations = response.locations.map(payload => Location.fromPayload(this, payload));
+ }
return {locations: locations, breakpointId: response.breakpointId};
}
@@ -327,11 +341,13 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
// This method is required for backward compatibility with V8 before 6.3.275.
const response = await this._agent.invoke_setBreakpoint(
{location: {scriptId: scriptId, lineNumber: lineNumber, columnNumber: columnNumber}, condition: condition});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return {breakpointId: null, locations: []};
+ }
let actualLocation = [];
- if (response.actualLocation)
- actualLocation = [SDK.DebuggerModel.Location.fromPayload(this, response.actualLocation)];
+ if (response.actualLocation) {
+ actualLocation = [Location.fromPayload(this, response.actualLocation)];
+ }
return {locations: actualLocation, breakpointId: response.breakpointId};
}
@@ -341,15 +357,16 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
*/
async removeBreakpoint(breakpointId) {
const response = await this._agent.invoke_removeBreakpoint({breakpointId});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
console.error('Failed to remove breakpoint: ' + response[Protocol.Error]);
+ }
}
/**
- * @param {!SDK.DebuggerModel.Location} startLocation
- * @param {?SDK.DebuggerModel.Location} endLocation
+ * @param {!Location} startLocation
+ * @param {?Location} endLocation
* @param {boolean} restrictToFunction
- * @return {!Promise<!Array<!SDK.DebuggerModel.BreakLocation>>}
+ * @return {!Promise<!Array<!BreakLocation>>}
*/
async getPossibleBreakpoints(startLocation, endLocation, restrictToFunction) {
const response = await this._agent.invoke_getPossibleBreakpoints({
@@ -357,9 +374,10 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
end: endLocation ? endLocation.payload() : undefined,
restrictToFunction: restrictToFunction
});
- if (response[Protocol.Error] || !response.locations)
+ if (response[Protocol.Error] || !response.locations) {
return [];
- return response.locations.map(location => SDK.DebuggerModel.BreakLocation.fromPayload(this, location));
+ }
+ return response.locations.map(location => BreakLocation.fromPayload(this, location));
}
/**
@@ -376,20 +394,20 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @param {!Protocol.Debugger.Location} location
*/
_breakpointResolved(breakpointId, location) {
- this._breakpointResolvedEventTarget.dispatchEventToListeners(
- breakpointId, SDK.DebuggerModel.Location.fromPayload(this, location));
+ this._breakpointResolvedEventTarget.dispatchEventToListeners(breakpointId, Location.fromPayload(this, location));
}
globalObjectCleared() {
this._setDebuggerPausedDetails(null);
this._reset();
// TODO(dgozman): move clients to ExecutionContextDestroyed/ScriptCollected events.
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.GlobalObjectCleared, this);
+ this.dispatchEventToListeners(Events.GlobalObjectCleared, this);
}
_reset() {
- for (const scriptWithSourceMap of this._sourceMapIdToScript.values())
+ for (const scriptWithSourceMap of this._sourceMapIdToScript.values()) {
this._sourceMapManager.detachSourceMap(scriptWithSourceMap);
+ }
this._sourceMapIdToScript.clear();
this._scripts.clear();
@@ -417,8 +435,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @return {!Array.<!SDK.Script>}
*/
scriptsForSourceURL(sourceURL) {
- if (!sourceURL)
+ if (!sourceURL) {
return [];
+ }
return this._scriptsBySourceURL.get(sourceURL) || [];
}
@@ -429,8 +448,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
scriptsForExecutionContext(executionContext) {
const result = [];
for (const script of this._scripts.values()) {
- if (script.executionContextId === executionContext.id)
+ if (script.executionContextId === executionContext.id) {
result.push(script);
+ }
}
return result;
}
@@ -473,42 +493,44 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
}
/**
- * @return {?Array.<!SDK.DebuggerModel.CallFrame>}
+ * @return {?Array.<!CallFrame>}
*/
get callFrames() {
return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null;
}
/**
- * @return {?SDK.DebuggerPausedDetails}
+ * @return {?DebuggerPausedDetails}
*/
debuggerPausedDetails() {
return this._debuggerPausedDetails;
}
/**
- * @param {?SDK.DebuggerPausedDetails} debuggerPausedDetails
+ * @param {?DebuggerPausedDetails} debuggerPausedDetails
* @return {boolean}
*/
_setDebuggerPausedDetails(debuggerPausedDetails) {
this._isPausing = false;
this._debuggerPausedDetails = debuggerPausedDetails;
if (this._debuggerPausedDetails) {
- if (Runtime.experiments.isEnabled('emptySourceMapAutoStepping') && this._beforePausedCallback) {
- if (!this._beforePausedCallback.call(null, this._debuggerPausedDetails))
+ if (Root.Runtime.experiments.isEnabled('emptySourceMapAutoStepping') && this._beforePausedCallback) {
+ if (!this._beforePausedCallback.call(null, this._debuggerPausedDetails)) {
return false;
+ }
}
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerPaused, this);
+ this.dispatchEventToListeners(Events.DebuggerPaused, this);
}
- if (debuggerPausedDetails)
+ if (debuggerPausedDetails) {
this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]);
- else
+ } else {
this.setSelectedCallFrame(null);
+ }
return true;
}
/**
- * @param {?function(!SDK.DebuggerPausedDetails):boolean} callback
+ * @param {?function(!DebuggerPausedDetails):boolean} callback
*/
setBeforePausedCallback(callback) {
this._beforePausedCallback = callback;
@@ -526,34 +548,38 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
async _pausedScript(
callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId) {
if (asyncCallStackTraceId) {
+ // Note: this is only to support old backends. Newer ones do not send asyncCallStackTraceId.
SDK.DebuggerModel._scheduledPauseOnAsyncCall = asyncCallStackTraceId;
const promises = [];
- for (const model of SDK.DebuggerModel._debuggerIdToModel.values())
+ for (const model of SDK.DebuggerModel._debuggerIdToModel.values()) {
promises.push(model._pauseOnAsyncCall(asyncCallStackTraceId));
+ }
await Promise.all(promises);
this.resume();
return;
}
- const pausedDetails = new SDK.DebuggerPausedDetails(
- this, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId);
+ const pausedDetails =
+ new DebuggerPausedDetails(this, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId);
if (pausedDetails && this._continueToLocationCallback) {
const callback = this._continueToLocationCallback;
delete this._continueToLocationCallback;
- if (callback(pausedDetails))
+ if (callback(pausedDetails)) {
return;
+ }
}
- if (!this._setDebuggerPausedDetails(pausedDetails))
+ if (!this._setDebuggerPausedDetails(pausedDetails)) {
this._agent.stepInto();
+ }
SDK.DebuggerModel._scheduledPauseOnAsyncCall = null;
}
_resumedScript() {
this._setDebuggerPausedDetails(null);
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerResumed, this);
+ this.dispatchEventToListeners(Events.DebuggerResumed, this);
}
/**
@@ -578,18 +604,20 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURLComment, hasSyntaxError, length,
originStackTrace) {
- if (this._scripts.has(scriptId))
+ if (this._scripts.has(scriptId)) {
return this._scripts.get(scriptId);
+ }
let isContentScript = false;
- if (executionContextAuxData && ('isDefault' in executionContextAuxData))
+ if (executionContextAuxData && ('isDefault' in executionContextAuxData)) {
isContentScript = !executionContextAuxData['isDefault'];
+ }
sourceURL = this._internString(sourceURL);
const script = new SDK.Script(
this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId,
this._internString(hash), isContentScript, isLiveEdit, sourceMapURL, hasSourceURLComment, length,
originStackTrace);
this._registerScript(script);
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.ParsedScriptSource, script);
+ this.dispatchEventToListeners(Events.ParsedScriptSource, script);
const sourceMapId =
SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
@@ -597,8 +625,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
// Consecutive script evaluations in the same execution context with the same sourceURL
// and sourceMappingURL should result in source map reloading.
const previousScript = this._sourceMapIdToScript.get(sourceMapId);
- if (previousScript)
+ if (previousScript) {
this._sourceMapManager.detachSourceMap(previousScript);
+ }
this._sourceMapIdToScript.set(sourceMapId, script);
this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
}
@@ -617,14 +646,16 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
*/
setSourceMapURL(script, newSourceMapURL) {
let sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
- if (sourceMapId && this._sourceMapIdToScript.get(sourceMapId) === script)
+ if (sourceMapId && this._sourceMapIdToScript.get(sourceMapId) === script) {
this._sourceMapIdToScript.delete(sourceMapId);
+ }
this._sourceMapManager.detachSourceMap(script);
script.sourceMapURL = newSourceMapURL;
sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
- if (!sourceMapId)
+ if (!sourceMapId) {
return;
+ }
this._sourceMapIdToScript.set(sourceMapId, script);
this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
}
@@ -648,8 +679,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
*/
_registerScript(script) {
this._scripts.set(script.scriptId, script);
- if (script.isAnonymousScript())
+ if (script.isAnonymousScript()) {
return;
+ }
let scripts = this._scriptsBySourceURL.get(script.sourceURL);
if (!scripts) {
@@ -668,12 +700,13 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
}
_collectDiscardedScripts() {
- if (this._discardableScripts.length < 1000)
+ if (this._discardableScripts.length < 1000) {
return;
+ }
const scriptsToDiscard = this._discardableScripts.splice(0, 100);
for (const script of scriptsToDiscard) {
this._unregisterScript(script);
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.DiscardedAnonymousScriptSource, script);
+ this.dispatchEventToListeners(Events.DiscardedAnonymousScriptSource, script);
}
}
@@ -681,41 +714,43 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @param {!SDK.Script} script
* @param {number} lineNumber
* @param {number} columnNumber
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
createRawLocation(script, lineNumber, columnNumber) {
- return new SDK.DebuggerModel.Location(this, script.scriptId, lineNumber, columnNumber);
+ return new Location(this, script.scriptId, lineNumber, columnNumber);
}
/**
* @param {string} sourceURL
* @param {number} lineNumber
* @param {number} columnNumber
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
createRawLocationByURL(sourceURL, lineNumber, columnNumber) {
let closestScript = null;
const scripts = this._scriptsBySourceURL.get(sourceURL) || [];
for (let i = 0, l = scripts.length; i < l; ++i) {
const script = scripts[i];
- if (!closestScript)
+ if (!closestScript) {
closestScript = script;
- if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber))
+ }
+ if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber)) {
continue;
- if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber))
+ }
+ if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber)) {
continue;
+ }
closestScript = script;
break;
}
- return closestScript ? new SDK.DebuggerModel.Location(this, closestScript.scriptId, lineNumber, columnNumber) :
- null;
+ return closestScript ? new Location(this, closestScript.scriptId, lineNumber, columnNumber) : null;
}
/**
* @param {!Protocol.Runtime.ScriptId} scriptId
* @param {number} lineNumber
* @param {number} columnNumber
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
createRawLocationByScriptId(scriptId, lineNumber, columnNumber) {
const script = this.scriptForId(scriptId);
@@ -724,21 +759,23 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
/**
* @param {!Protocol.Runtime.StackTrace} stackTrace
- * @return {!Array<!SDK.DebuggerModel.Location>}
+ * @return {!Array<!Location>}
*/
createRawLocationsByStackTrace(stackTrace) {
const frames = [];
while (stackTrace) {
- for (const frame of stackTrace.callFrames)
+ for (const frame of stackTrace.callFrames) {
frames.push(frame);
+ }
stackTrace = stackTrace.parent;
}
const rawLocations = [];
for (const frame of frames) {
const rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber);
- if (rawLocation)
+ if (rawLocation) {
rawLocations.push(rawLocation);
+ }
}
return rawLocations;
}
@@ -758,17 +795,18 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
}
/**
- * @param {?SDK.DebuggerModel.CallFrame} callFrame
+ * @param {?CallFrame} callFrame
*/
setSelectedCallFrame(callFrame) {
- if (this._selectedCallFrame === callFrame)
+ if (this._selectedCallFrame === callFrame) {
return;
+ }
this._selectedCallFrame = callFrame;
- this.dispatchEventToListeners(SDK.DebuggerModel.Events.CallFrameSelected, this);
+ this.dispatchEventToListeners(Events.CallFrameSelected, this);
}
/**
- * @return {?SDK.DebuggerModel.CallFrame}
+ * @return {?CallFrame}
*/
selectedCallFrame() {
return this._selectedCallFrame;
@@ -793,23 +831,26 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
/**
* @param {!SDK.GetPropertiesResult} response
* @return {?SDK.DebuggerModel.FunctionDetails}
- * @this {!SDK.DebuggerModel}
+ * @this {!DebuggerModel}
*/
function buildDetails(response) {
- if (!response)
+ if (!response) {
return null;
+ }
let location = null;
if (response.internalProperties) {
for (const prop of response.internalProperties) {
- if (prop.name === '[[FunctionLocation]]')
+ if (prop.name === '[[FunctionLocation]]') {
location = prop.value;
+ }
}
}
let functionName = null;
if (response.properties) {
for (const prop of response.properties) {
- if (prop.name === 'name' && prop.value && prop.value.type === 'string')
+ if (prop.name === 'name' && prop.value && prop.value.type === 'string') {
functionName = prop.value;
+ }
if (prop.name === 'displayName' && prop.value && prop.value.type === 'string') {
functionName = prop.value;
break;
@@ -835,8 +876,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
async setVariableValue(scopeNumber, variableName, newValue, callFrameId) {
const response = await this._agent.invoke_setVariableValue({scopeNumber, variableName, newValue, callFrameId});
const error = response[Protocol.Error];
- if (error)
+ if (error) {
console.error(error);
+ }
return error;
}
@@ -865,8 +907,9 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
async setBlackboxPatterns(patterns) {
const response = await this._agent.invoke_setBlackboxPatterns({patterns});
const error = response[Protocol.Error];
- if (error)
+ if (error) {
console.error(error);
+ }
return !error;
}
@@ -902,36 +945,32 @@ SDK.DebuggerModel = class extends SDK.SDKModel {
* @return {string} string
*/
_internString(string) {
- if (!this._stringMap.has(string))
+ if (!this._stringMap.has(string)) {
this._stringMap.set(string, string);
+ }
return this._stringMap.get(string);
}
-};
+}
/** @type {!Map<string, !SDK.DebuggerModel>} */
-SDK.DebuggerModel._debuggerIdToModel = new Map();
+export const _debuggerIdToModel = new Map();
/** @type {?Protocol.Runtime.StackTraceId} */
-SDK.DebuggerModel._scheduledPauseOnAsyncCall = null;
-
-SDK.SDKModel.register(SDK.DebuggerModel, SDK.Target.Capability.JS, true);
-
-/** @typedef {{location: ?SDK.DebuggerModel.Location, functionName: string}} */
-SDK.DebuggerModel.FunctionDetails;
+export const _scheduledPauseOnAsyncCall = null;
/**
* Keep these in sync with WebCore::V8Debugger
*
* @enum {string}
*/
-SDK.DebuggerModel.PauseOnExceptionsState = {
+export const PauseOnExceptionsState = {
DontPauseOnExceptions: 'none',
PauseOnAllExceptions: 'all',
PauseOnUncaughtExceptions: 'uncaught'
};
/** @enum {symbol} */
-SDK.DebuggerModel.Events = {
+export const Events = {
DebuggerWasEnabled: Symbol('DebuggerWasEnabled'),
DebuggerWasDisabled: Symbol('DebuggerWasDisabled'),
DebuggerPaused: Symbol('DebuggerPaused'),
@@ -946,7 +985,7 @@ SDK.DebuggerModel.Events = {
};
/** @enum {string} */
-SDK.DebuggerModel.BreakReason = {
+export const BreakReason = {
DOM: 'DOM',
EventListener: 'EventListener',
XHR: 'XHR',
@@ -959,37 +998,30 @@ SDK.DebuggerModel.BreakReason = {
};
/** @enum {string} */
-SDK.DebuggerModel.BreakLocationType = {
+export const BreakLocationType = {
Return: 'return',
Call: 'call',
DebuggerStatement: 'debuggerStatement'
};
-SDK.DebuggerEventTypes = {
+export const DebuggerEventTypes = {
JavaScriptPause: 0,
JavaScriptBreakpoint: 1,
NativeBreakpoint: 2
};
-SDK.DebuggerModel.ContinueToLocationTargetCallFrames = {
+export const ContinueToLocationTargetCallFrames = {
Any: 'any',
Current: 'current'
};
-/** @typedef {{
- * breakpointId: ?Protocol.Debugger.BreakpointId,
- * locations: !Array<!SDK.DebuggerModel.Location>
- * }}
- */
-SDK.DebuggerModel.SetBreakpointResult;
-
/**
* @extends {Protocol.DebuggerDispatcher}
* @unrestricted
*/
-SDK.DebuggerDispatcher = class {
+export class DebuggerDispatcher {
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
*/
constructor(debuggerModel) {
this._debuggerModel = debuggerModel;
@@ -1076,14 +1108,14 @@ SDK.DebuggerDispatcher = class {
breakpointResolved(breakpointId, location) {
this._debuggerModel._breakpointResolved(breakpointId, location);
}
-};
+}
/**
* @unrestricted
*/
-SDK.DebuggerModel.Location = class {
+export class Location {
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {string} scriptId
* @param {number} lineNumber
* @param {number=} columnNumber
@@ -1096,12 +1128,12 @@ SDK.DebuggerModel.Location = class {
}
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {!Protocol.Debugger.Location} payload
- * @return {!SDK.DebuggerModel.Location}
+ * @return {!Location}
*/
static fromPayload(debuggerModel, payload) {
- return new SDK.DebuggerModel.Location(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber);
+ return new Location(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber);
}
/**
@@ -1122,15 +1154,15 @@ SDK.DebuggerModel.Location = class {
* @param {function()=} pausedCallback
*/
continueToLocation(pausedCallback) {
- if (pausedCallback)
+ if (pausedCallback) {
this.debuggerModel._continueToLocationCallback = this._paused.bind(this, pausedCallback);
- this.debuggerModel._agent.continueToLocation(
- this.payload(), SDK.DebuggerModel.ContinueToLocationTargetCallFrames.Current);
+ }
+ this.debuggerModel._agent.continueToLocation(this.payload(), ContinueToLocationTargetCallFrames.Current);
}
/**
* @param {function()|undefined} pausedCallback
- * @param {!SDK.DebuggerPausedDetails} debuggerPausedDetails
+ * @param {!DebuggerPausedDetails} debuggerPausedDetails
* @return {boolean}
*/
_paused(pausedCallback, debuggerPausedDetails) {
@@ -1149,14 +1181,14 @@ SDK.DebuggerModel.Location = class {
id() {
return this.debuggerModel.target().id() + ':' + this.scriptId + ':' + this.lineNumber + ':' + this.columnNumber;
}
-};
+}
/**
* @unrestricted
*/
-SDK.DebuggerModel.BreakLocation = class extends SDK.DebuggerModel.Location {
+export class BreakLocation extends Location {
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {string} scriptId
* @param {number} lineNumber
* @param {number=} columnNumber
@@ -1164,27 +1196,28 @@ SDK.DebuggerModel.BreakLocation = class extends SDK.DebuggerModel.Location {
*/
constructor(debuggerModel, scriptId, lineNumber, columnNumber, type) {
super(debuggerModel, scriptId, lineNumber, columnNumber);
- if (type)
+ if (type) {
this.type = type;
+ }
}
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @override
+ * @param {!DebuggerModel} debuggerModel
* @param {!Protocol.Debugger.BreakLocation} payload
- * @return {!SDK.DebuggerModel.BreakLocation}
+ * @return {!BreakLocation}
*/
static fromPayload(debuggerModel, payload) {
- return new SDK.DebuggerModel.BreakLocation(
- debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber, payload.type);
+ return new BreakLocation(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber, payload.type);
}
-};
+}
/**
* @unrestricted
*/
-SDK.DebuggerModel.CallFrame = class {
+export class CallFrame {
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {!SDK.Script} script
* @param {!Protocol.Debugger.CallFrame} payload
*/
@@ -1192,33 +1225,36 @@ SDK.DebuggerModel.CallFrame = class {
this.debuggerModel = debuggerModel;
this._script = script;
this._payload = payload;
- this._location = SDK.DebuggerModel.Location.fromPayload(debuggerModel, payload.location);
+ this._location = Location.fromPayload(debuggerModel, payload.location);
this._scopeChain = [];
this._localScope = null;
for (let i = 0; i < payload.scopeChain.length; ++i) {
- const scope = new SDK.DebuggerModel.Scope(this, i);
+ const scope = new Scope(this, i);
this._scopeChain.push(scope);
- if (scope.type() === Protocol.Debugger.ScopeType.Local)
+ if (scope.type() === Protocol.Debugger.ScopeType.Local) {
this._localScope = scope;
+ }
+ }
+ if (payload.functionLocation) {
+ this._functionLocation = Location.fromPayload(debuggerModel, payload.functionLocation);
}
- if (payload.functionLocation)
- this._functionLocation = SDK.DebuggerModel.Location.fromPayload(debuggerModel, payload.functionLocation);
this._returnValue =
payload.returnValue ? this.debuggerModel._runtimeModel.createRemoteObject(payload.returnValue) : null;
}
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
- * @return {!Array.<!SDK.DebuggerModel.CallFrame>}
+ * @return {!Array.<!CallFrame>}
*/
static fromPayloadArray(debuggerModel, callFrames) {
const result = [];
for (let i = 0; i < callFrames.length; ++i) {
const callFrame = callFrames[i];
const script = debuggerModel.scriptForId(callFrame.location.scriptId);
- if (script)
- result.push(new SDK.DebuggerModel.CallFrame(debuggerModel, script, callFrame));
+ if (script) {
+ result.push(new CallFrame(debuggerModel, script, callFrame));
+ }
}
return result;
}
@@ -1238,14 +1274,14 @@ SDK.DebuggerModel.CallFrame = class {
}
/**
- * @return {!Array.<!SDK.DebuggerModel.Scope>}
+ * @return {!Array.<!Scope>}
*/
scopeChain() {
return this._scopeChain;
}
/**
- * @return {?SDK.DebuggerModel.Scope}
+ * @return {?Scope}
*/
localScope() {
return this._localScope;
@@ -1270,16 +1306,19 @@ SDK.DebuggerModel.CallFrame = class {
* @return {!Promise<?SDK.RemoteObject>}
*/
async setReturnValue(expression) {
- if (!this._returnValue)
+ if (!this._returnValue) {
return null;
+ }
const evaluateResponse = await this.debuggerModel._agent.invoke_evaluateOnCallFrame(
{callFrameId: this.id, expression: expression, silent: true, objectGroup: 'backtrace'});
- if (evaluateResponse[Protocol.Error] || evaluateResponse.exceptionDetails)
+ if (evaluateResponse[Protocol.Error] || evaluateResponse.exceptionDetails) {
return null;
+ }
const response = await this.debuggerModel._agent.invoke_setReturnValue({newValue: evaluateResponse.result});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return null;
+ }
this._returnValue = this.debuggerModel._runtimeModel.createRemoteObject(evaluateResponse.result);
return this._returnValue;
}
@@ -1292,14 +1331,14 @@ SDK.DebuggerModel.CallFrame = class {
}
/**
- * @return {!SDK.DebuggerModel.Location}
+ * @return {!Location}
*/
location() {
return this._location;
}
/**
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
functionLocation() {
return this._functionLocation || null;
@@ -1315,8 +1354,9 @@ SDK.DebuggerModel.CallFrame = class {
const needsTerminationOptions = !!options.throwOnSideEffect || options.timeout !== undefined;
if (needsTerminationOptions &&
(runtimeModel.hasSideEffectSupport() === false ||
- (runtimeModel.hasSideEffectSupport() === null && !await runtimeModel.checkSideEffectSupport())))
+ (runtimeModel.hasSideEffectSupport() === null && !await runtimeModel.checkSideEffectSupport()))) {
return {error: 'Side-effect checks not supported by backend.'};
+ }
const response = await this.debuggerModel._agent.invoke_evaluateOnCallFrame({
callFrameId: this.id,
@@ -1339,18 +1379,18 @@ SDK.DebuggerModel.CallFrame = class {
async restart() {
const response = await this.debuggerModel._agent.invoke_restartFrame({callFrameId: this._payload.callFrameId});
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
this.debuggerModel.stepInto();
+ }
}
-};
-
+}
/**
* @unrestricted
*/
-SDK.DebuggerModel.Scope = class {
+export class Scope {
/**
- * @param {!SDK.DebuggerModel.CallFrame} callFrame
+ * @param {!CallFrame} callFrame
* @param {number} ordinal
*/
constructor(callFrame, ordinal) {
@@ -1359,16 +1399,14 @@ SDK.DebuggerModel.Scope = class {
this._type = this._payload.type;
this._name = this._payload.name;
this._ordinal = ordinal;
- this._startLocation = this._payload.startLocation ?
- SDK.DebuggerModel.Location.fromPayload(callFrame.debuggerModel, this._payload.startLocation) :
- null;
- this._endLocation = this._payload.endLocation ?
- SDK.DebuggerModel.Location.fromPayload(callFrame.debuggerModel, this._payload.endLocation) :
- null;
+ this._startLocation =
+ this._payload.startLocation ? Location.fromPayload(callFrame.debuggerModel, this._payload.startLocation) : null;
+ this._endLocation =
+ this._payload.endLocation ? Location.fromPayload(callFrame.debuggerModel, this._payload.endLocation) : null;
}
/**
- * @return {!SDK.DebuggerModel.CallFrame}
+ * @return {!CallFrame}
*/
callFrame() {
return this._callFrame;
@@ -1415,14 +1453,14 @@ SDK.DebuggerModel.Scope = class {
}
/**
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
startLocation() {
return this._startLocation;
}
/**
- * @return {?SDK.DebuggerModel.Location}
+ * @return {?Location}
*/
endLocation() {
return this._endLocation;
@@ -1432,8 +1470,9 @@ SDK.DebuggerModel.Scope = class {
* @return {!SDK.RemoteObject}
*/
object() {
- if (this._object)
+ if (this._object) {
return this._object;
+ }
const runtimeModel = this._callFrame.debuggerModel._runtimeModel;
const declarativeScope =
@@ -1456,14 +1495,14 @@ SDK.DebuggerModel.Scope = class {
this._type !== Protocol.Debugger.ScopeType.With && this._type !== Protocol.Debugger.ScopeType.Global;
return declarativeScope ? '' : (this._payload.object.description || '');
}
-};
+}
/**
* @unrestricted
*/
-SDK.DebuggerPausedDetails = class {
+export class DebuggerPausedDetails {
/**
- * @param {!SDK.DebuggerModel} debuggerModel
+ * @param {!DebuggerModel} debuggerModel
* @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
* @param {string} reason
* @param {!Object|undefined} auxData
@@ -1473,12 +1512,13 @@ SDK.DebuggerPausedDetails = class {
*/
constructor(debuggerModel, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId) {
this.debuggerModel = debuggerModel;
- this.callFrames = SDK.DebuggerModel.CallFrame.fromPayloadArray(debuggerModel, callFrames);
+ this.callFrames = CallFrame.fromPayloadArray(debuggerModel, callFrames);
this.reason = reason;
this.auxData = auxData;
this.breakpointIds = breakpointIds;
- if (asyncStackTrace)
+ if (asyncStackTrace) {
this.asyncStackTrace = this._cleanRedundantFrames(asyncStackTrace);
+ }
this.asyncStackTraceId = asyncStackTraceId;
}
@@ -1486,9 +1526,9 @@ SDK.DebuggerPausedDetails = class {
* @return {?SDK.RemoteObject}
*/
exception() {
- if (this.reason !== SDK.DebuggerModel.BreakReason.Exception &&
- this.reason !== SDK.DebuggerModel.BreakReason.PromiseRejection)
+ if (this.reason !== BreakReason.Exception && this.reason !== BreakReason.PromiseRejection) {
return null;
+ }
return this.debuggerModel._runtimeModel.createRemoteObject(
/** @type {!Protocol.Runtime.RemoteObject} */ (this.auxData));
}
@@ -1501,14 +1541,77 @@ SDK.DebuggerPausedDetails = class {
let stack = asyncStackTrace;
let previous = null;
while (stack) {
- if (stack.description === 'async function' && stack.callFrames.length)
+ if (stack.description === 'async function' && stack.callFrames.length) {
stack.callFrames.shift();
- if (previous && !stack.callFrames.length)
+ }
+ if (previous && !stack.callFrames.length) {
previous.parent = stack.parent;
- else
+ } else {
previous = stack;
+ }
stack = stack.parent;
}
return asyncStackTrace;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.DebuggerModel = DebuggerModel;
+
+/** @enum {string} */
+SDK.DebuggerModel.PauseOnExceptionsState = PauseOnExceptionsState;
+
+/** @enum {symbol} */
+SDK.DebuggerModel.Events = Events;
+
+/** @enum {string} */
+SDK.DebuggerModel.BreakReason = BreakReason;
+
+/** @enum {string} */
+SDK.DebuggerModel.BreakLocationType = BreakLocationType;
+
+SDK.DebuggerModel.ContinueToLocationTargetCallFrames = ContinueToLocationTargetCallFrames;
+
+/** @constructor */
+SDK.DebuggerModel.Location = Location;
+
+/** @constructor */
+SDK.DebuggerModel.BreakLocation = BreakLocation;
+
+/** @constructor */
+SDK.DebuggerModel.CallFrame = CallFrame;
+
+/** @constructor */
+SDK.DebuggerModel.Scope = Scope;
+
+/** @constructor */
+SDK.DebuggerPausedDetails = DebuggerPausedDetails;
+
+/** @constructor */
+SDK.DebuggerDispatcher = DebuggerDispatcher;
+
+SDK.DebuggerEventTypes = DebuggerEventTypes;
+
+SDK.SDKModel.register(SDK.DebuggerModel, SDK.Target.Capability.JS, true);
+
+/** @typedef {{location: ?Location, functionName: string}} */
+SDK.DebuggerModel.FunctionDetails;
+
+/** @typedef {{
+ * breakpointId: ?Protocol.Debugger.BreakpointId,
+ * locations: !Array<!Location>
+ * }}
+ */
+SDK.DebuggerModel.SetBreakpointResult;
+
+/** @type {!Map<string, !SDK.DebuggerModel>} */
+SDK.DebuggerModel._debuggerIdToModel = _debuggerIdToModel;
+
+/** @type {?Protocol.Runtime.StackTraceId} */
+SDK.DebuggerModel._scheduledPauseOnAsyncCall = _scheduledPauseOnAsyncCall; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/EmulationModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/EmulationModel.js
index 9e788d1cd18..0c23e2752d5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/EmulationModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/EmulationModel.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-SDK.EmulationModel = class extends SDK.SDKModel {
+export default class EmulationModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -13,19 +13,42 @@ SDK.EmulationModel = class extends SDK.SDKModel {
this._deviceOrientationAgent = target.deviceOrientationAgent();
this._cssModel = target.model(SDK.CSSModel);
this._overlayModel = target.model(SDK.OverlayModel);
- if (this._overlayModel)
+ if (this._overlayModel) {
this._overlayModel.addEventListener(SDK.OverlayModel.Events.InspectModeWillBeToggled, this._updateTouch, this);
+ }
const disableJavascriptSetting = Common.settings.moduleSetting('javaScriptDisabled');
disableJavascriptSetting.addChangeListener(
() => this._emulationAgent.setScriptExecutionDisabled(disableJavascriptSetting.get()));
- if (disableJavascriptSetting.get())
+ if (disableJavascriptSetting.get()) {
this._emulationAgent.setScriptExecutionDisabled(true);
+ }
- const mediaSetting = Common.moduleSetting('emulatedCSSMedia');
- mediaSetting.addChangeListener(() => this._emulateCSSMedia(mediaSetting.get()));
- if (mediaSetting.get())
- this._emulateCSSMedia(mediaSetting.get());
+ const mediaTypeSetting = Common.moduleSetting('emulatedCSSMedia');
+ const mediaFeaturePrefersColorSchemeSetting = Common.moduleSetting('emulatedCSSMediaFeaturePrefersColorScheme');
+ const mediaFeaturePrefersReducedMotionSetting = Common.moduleSetting('emulatedCSSMediaFeaturePrefersReducedMotion');
+ // Note: this uses a different format than what the CDP API expects,
+ // because we want to update these values per media type/feature
+ // without having to search the `features` array (inefficient) or
+ // hardcoding the indices (not readable/maintainable).
+ this._mediaConfiguration = new Map([
+ ['type', mediaTypeSetting.get()],
+ ['prefers-color-scheme', mediaFeaturePrefersColorSchemeSetting.get()],
+ ['prefers-reduced-motion', mediaFeaturePrefersReducedMotionSetting.get()],
+ ]);
+ mediaTypeSetting.addChangeListener(() => {
+ this._mediaConfiguration.set('type', mediaTypeSetting.get());
+ this._updateCssMedia();
+ });
+ mediaFeaturePrefersColorSchemeSetting.addChangeListener(() => {
+ this._mediaConfiguration.set('prefers-color-scheme', mediaFeaturePrefersColorSchemeSetting.get());
+ this._updateCssMedia();
+ });
+ mediaFeaturePrefersReducedMotionSetting.addChangeListener(() => {
+ this._mediaConfiguration.set('prefers-reduced-motion', mediaFeaturePrefersReducedMotionSetting.get());
+ this._updateCssMedia();
+ });
+ this._updateCssMedia();
this._touchEnabled = false;
this._touchMobile = false;
@@ -52,10 +75,11 @@ SDK.EmulationModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
emulateDevice(metrics) {
- if (metrics)
+ if (metrics) {
return this._emulationAgent.invoke_setDeviceMetricsOverride(metrics);
- else
+ } else {
return this._emulationAgent.clearDeviceMetricsOverride();
+ }
}
/**
@@ -66,24 +90,27 @@ SDK.EmulationModel = class extends SDK.SDKModel {
}
/**
- * @param {?SDK.EmulationModel.Geolocation} geolocation
+ * @param {?Geolocation} geolocation
*/
emulateGeolocation(geolocation) {
if (!geolocation) {
this._emulationAgent.clearGeolocationOverride();
+ this._emulationAgent.setTimezoneOverride('');
return;
}
if (geolocation.error) {
this._emulationAgent.setGeolocationOverride();
+ this._emulationAgent.setTimezoneOverride('');
} else {
this._emulationAgent.setGeolocationOverride(
- geolocation.latitude, geolocation.longitude, SDK.EmulationModel.Geolocation.DefaultMockAccuracy);
+ geolocation.latitude, geolocation.longitude, Geolocation.DefaultMockAccuracy);
+ this._emulationAgent.setTimezoneOverride(geolocation.timezoneId);
}
}
/**
- * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation
+ * @param {?DeviceOrientation} deviceOrientation
*/
emulateDeviceOrientation(deviceOrientation) {
if (deviceOrientation) {
@@ -95,12 +122,14 @@ SDK.EmulationModel = class extends SDK.SDKModel {
}
/**
- * @param {string} media
+ * @param {string} type
+ * @param {!Array<{name: string, value: string}>} features
*/
- _emulateCSSMedia(media) {
- this._emulationAgent.setEmulatedMedia(media);
- if (this._cssModel)
+ _emulateCSSMedia(type, features) {
+ this._emulationAgent.setEmulatedMedia(type, features);
+ if (this._cssModel) {
this._cssModel.mediaQueryResultChanged();
+ }
}
/**
@@ -133,74 +162,91 @@ SDK.EmulationModel = class extends SDK.SDKModel {
enabled: this._touchEnabled,
configuration: this._touchMobile ? 'mobile' : 'desktop',
};
- if (this._customTouchEnabled)
+ if (this._customTouchEnabled) {
configuration = {enabled: true, configuration: 'mobile'};
+ }
- if (this._overlayModel && this._overlayModel.inspectModeEnabled())
+ if (this._overlayModel && this._overlayModel.inspectModeEnabled()) {
configuration = {enabled: false, configuration: 'mobile'};
+ }
- if (!this._touchConfiguration.enabled && !configuration.enabled)
+ if (!this._touchConfiguration.enabled && !configuration.enabled) {
return;
+ }
if (this._touchConfiguration.enabled && configuration.enabled &&
- this._touchConfiguration.configuration === configuration.configuration)
+ this._touchConfiguration.configuration === configuration.configuration) {
return;
+ }
this._touchConfiguration = configuration;
this._emulationAgent.setTouchEmulationEnabled(configuration.enabled, 1);
this._emulationAgent.setEmitTouchEventsForMouse(configuration.enabled, configuration.configuration);
}
-};
-SDK.SDKModel.register(SDK.EmulationModel, SDK.Target.Capability.Emulation, true);
+ _updateCssMedia() {
+ // See the note above, where this._mediaConfiguration is defined.
+ const type = this._mediaConfiguration.get('type');
+ const features = [
+ {
+ name: 'prefers-color-scheme',
+ value: this._mediaConfiguration.get('prefers-color-scheme'),
+ },
+ {
+ name: 'prefers-reduced-motion',
+ value: this._mediaConfiguration.get('prefers-reduced-motion'),
+ },
+ ];
+ this._emulateCSSMedia(type, features);
+ }
+}
-SDK.EmulationModel.Geolocation = class {
+export class Geolocation {
/**
* @param {number} latitude
* @param {number} longitude
+ * @param {string} timezoneId
* @param {boolean} error
*/
- constructor(latitude, longitude, error) {
+ constructor(latitude, longitude, timezoneId, error) {
this.latitude = latitude;
this.longitude = longitude;
+ this.timezoneId = timezoneId;
this.error = error;
}
/**
- * @return {!SDK.EmulationModel.Geolocation}
+ * @return {!Geolocation}
*/
static parseSetting(value) {
if (value) {
- const splitError = value.split(':');
- if (splitError.length === 2) {
- const splitPosition = splitError[0].split('@');
- if (splitPosition.length === 2) {
- return new SDK.EmulationModel.Geolocation(
- parseFloat(splitPosition[0]), parseFloat(splitPosition[1]), !!splitError[1]);
- }
- }
+ const [position, timezoneId, error] = value.split(':');
+ const [latitude, longitude] = position.split('@');
+ return new Geolocation(parseFloat(latitude), parseFloat(longitude), timezoneId, Boolean(error));
}
- return new SDK.EmulationModel.Geolocation(0, 0, false);
+ return new Geolocation(0, 0, '', false);
}
/**
* @param {string} latitudeString
* @param {string} longitudeString
- * @param {string} errorStatus
- * @return {?SDK.EmulationModel.Geolocation}
+ * @param {string} timezoneId
+ * @return {?Geolocation}
*/
- static parseUserInput(latitudeString, longitudeString, errorStatus) {
- if (!latitudeString && !longitudeString)
+ static parseUserInput(latitudeString, longitudeString, timezoneId) {
+ if (!latitudeString && !longitudeString) {
return null;
+ }
- const {valid: isLatitudeValid} = SDK.EmulationModel.Geolocation.latitudeValidator(latitudeString);
- const {valid: isLongitudeValid} = SDK.EmulationModel.Geolocation.longitudeValidator(longitudeString);
+ const {valid: isLatitudeValid} = Geolocation.latitudeValidator(latitudeString);
+ const {valid: isLongitudeValid} = Geolocation.longitudeValidator(longitudeString);
- if (!isLatitudeValid && !isLongitudeValid)
+ if (!isLatitudeValid && !isLongitudeValid) {
return null;
+ }
const latitude = isLatitudeValid ? parseFloat(latitudeString) : -1;
const longitude = isLongitudeValid ? parseFloat(longitudeString) : -1;
- return new SDK.EmulationModel.Geolocation(latitude, longitude, !!errorStatus);
+ return new Geolocation(latitude, longitude, timezoneId, false);
}
/**
@@ -224,16 +270,30 @@ SDK.EmulationModel.Geolocation = class {
}
/**
+ * @param {string} value
+ * @return {{valid: boolean, errorMessage: (string|undefined)}}
+ */
+ static timezoneIdValidator(value) {
+ // Chromium uses ICU's timezone implementation, which is very
+ // liberal in what it accepts. ICU does not simply use an allowlist
+ // but instead tries to make sense of the input, even for
+ // weird-looking timezone IDs. There's not much point in validating
+ // the input other than checking if it contains at least one slash.
+ const valid = value.includes('/');
+ return {valid};
+ }
+
+ /**
* @return {string}
*/
toSetting() {
- return this.latitude + '@' + this.longitude + ':' + (this.error || '');
+ return `${this.latitude}@${this.longitude}:${this.timezoneId}:${this.error || ''}`;
}
-};
+}
-SDK.EmulationModel.Geolocation.DefaultMockAccuracy = 150;
+Geolocation.DefaultMockAccuracy = 150;
-SDK.EmulationModel.DeviceOrientation = class {
+export class DeviceOrientation {
/**
* @param {number} alpha
* @param {number} beta
@@ -246,35 +306,37 @@ SDK.EmulationModel.DeviceOrientation = class {
}
/**
- * @return {!SDK.EmulationModel.DeviceOrientation}
+ * @return {!DeviceOrientation}
*/
static parseSetting(value) {
if (value) {
const jsonObject = JSON.parse(value);
- return new SDK.EmulationModel.DeviceOrientation(jsonObject.alpha, jsonObject.beta, jsonObject.gamma);
+ return new DeviceOrientation(jsonObject.alpha, jsonObject.beta, jsonObject.gamma);
}
- return new SDK.EmulationModel.DeviceOrientation(0, 0, 0);
+ return new DeviceOrientation(0, 0, 0);
}
/**
- * @return {?SDK.EmulationModel.DeviceOrientation}
+ * @return {?DeviceOrientation}
*/
static parseUserInput(alphaString, betaString, gammaString) {
- if (!alphaString && !betaString && !gammaString)
+ if (!alphaString && !betaString && !gammaString) {
return null;
+ }
- const {valid: isAlphaValid} = SDK.EmulationModel.DeviceOrientation.validator(alphaString);
- const {valid: isBetaValid} = SDK.EmulationModel.DeviceOrientation.validator(betaString);
- const {valid: isGammaValid} = SDK.EmulationModel.DeviceOrientation.validator(gammaString);
+ const {valid: isAlphaValid} = DeviceOrientation.validator(alphaString);
+ const {valid: isBetaValid} = DeviceOrientation.validator(betaString);
+ const {valid: isGammaValid} = DeviceOrientation.validator(gammaString);
- if (!isAlphaValid && !isBetaValid && !isGammaValid)
+ if (!isAlphaValid && !isBetaValid && !isGammaValid) {
return null;
+ }
const alpha = isAlphaValid ? parseFloat(alphaString) : -1;
const beta = isBetaValid ? parseFloat(betaString) : -1;
const gamma = isGammaValid ? parseFloat(gammaString) : -1;
- return new SDK.EmulationModel.DeviceOrientation(alpha, beta, gamma);
+ return new DeviceOrientation(alpha, beta, gamma);
}
/**
@@ -292,4 +354,21 @@ SDK.EmulationModel.DeviceOrientation = class {
toSetting() {
return JSON.stringify(this);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.EmulationModel = EmulationModel;
+
+/** @constructor */
+SDK.EmulationModel.Geolocation = Geolocation;
+
+/** @constructor */
+SDK.EmulationModel.DeviceOrientation = DeviceOrientation;
+
+SDK.SDKModel.register(EmulationModel, SDK.Target.Capability.Emulation, true);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/FilmStripModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/FilmStripModel.js
index 71c7237f957..c8fe3f866d2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/FilmStripModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/FilmStripModel.js
@@ -7,7 +7,7 @@
/**
* @unrestricted
*/
-SDK.FilmStripModel = class {
+export default class FilmStripModel {
/**
* @param {!SDK.TracingModel} tracingModel
* @param {number=} zeroTime
@@ -24,32 +24,36 @@ SDK.FilmStripModel = class {
this._zeroTime = zeroTime || tracingModel.minimumRecordTime();
this._spanTime = tracingModel.maximumRecordTime() - this._zeroTime;
- /** @type {!Array<!SDK.FilmStripModel.Frame>} */
+ /** @type {!Array<!Frame>} */
this._frames = [];
const browserMain = SDK.TracingModel.browserMainThread(tracingModel);
- if (!browserMain)
+ if (!browserMain) {
return;
+ }
const events = browserMain.events();
for (let i = 0; i < events.length; ++i) {
const event = events[i];
- if (event.startTime < this._zeroTime)
+ if (event.startTime < this._zeroTime) {
continue;
- if (!event.hasCategory(SDK.FilmStripModel._category))
+ }
+ if (!event.hasCategory(_category)) {
continue;
- if (event.name === SDK.FilmStripModel.TraceEvents.CaptureFrame) {
+ }
+ if (event.name === TraceEvents.CaptureFrame) {
const data = event.args['data'];
- if (data)
- this._frames.push(SDK.FilmStripModel.Frame._fromEvent(this, event, this._frames.length));
- } else if (event.name === SDK.FilmStripModel.TraceEvents.Screenshot) {
- this._frames.push(SDK.FilmStripModel.Frame._fromSnapshot(
- this, /** @type {!SDK.TracingModel.ObjectSnapshot} */ (event), this._frames.length));
+ if (data) {
+ this._frames.push(Frame._fromEvent(this, event, this._frames.length));
+ }
+ } else if (event.name === TraceEvents.Screenshot) {
+ this._frames.push(
+ Frame._fromSnapshot(this, /** @type {!SDK.TracingModel.ObjectSnapshot} */ (event), this._frames.length));
}
}
}
/**
- * @return {!Array<!SDK.FilmStripModel.Frame>}
+ * @return {!Array<!Frame>}
*/
frames() {
return this._frames;
@@ -71,17 +75,17 @@ SDK.FilmStripModel = class {
/**
* @param {number} timestamp
- * @return {?SDK.FilmStripModel.Frame}
+ * @return {?Frame}
*/
frameByTimestamp(timestamp) {
const index = this._frames.upperBound(timestamp, (timestamp, frame) => timestamp - frame.timestamp) - 1;
return index >= 0 ? this._frames[index] : null;
}
-};
+}
-SDK.FilmStripModel._category = 'disabled-by-default-devtools.screenshot';
+export const _category = 'disabled-by-default-devtools.screenshot';
-SDK.FilmStripModel.TraceEvents = {
+export const TraceEvents = {
CaptureFrame: 'CaptureFrame',
Screenshot: 'Screenshot'
};
@@ -89,9 +93,9 @@ SDK.FilmStripModel.TraceEvents = {
/**
* @unrestricted
*/
-SDK.FilmStripModel.Frame = class {
+export class Frame {
/**
- * @param {!SDK.FilmStripModel} model
+ * @param {!FilmStripModel} model
* @param {number} timestamp
* @param {number} index
*/
@@ -106,31 +110,31 @@ SDK.FilmStripModel.Frame = class {
}
/**
- * @param {!SDK.FilmStripModel} model
+ * @param {!FilmStripModel} model
* @param {!SDK.TracingModel.Event} event
* @param {number} index
- * @return {!SDK.FilmStripModel.Frame}
+ * @return {!Frame}
*/
static _fromEvent(model, event, index) {
- const frame = new SDK.FilmStripModel.Frame(model, event.startTime, index);
+ const frame = new Frame(model, event.startTime, index);
frame._imageData = event.args['data'];
return frame;
}
/**
- * @param {!SDK.FilmStripModel} model
+ * @param {!FilmStripModel} model
* @param {!SDK.TracingModel.ObjectSnapshot} snapshot
* @param {number} index
- * @return {!SDK.FilmStripModel.Frame}
+ * @return {!Frame}
*/
static _fromSnapshot(model, snapshot, index) {
- const frame = new SDK.FilmStripModel.Frame(model, snapshot.startTime, index);
+ const frame = new Frame(model, snapshot.startTime, index);
frame._snapshot = snapshot;
return frame;
}
/**
- * @return {!SDK.FilmStripModel}
+ * @return {!FilmStripModel}
*/
model() {
return this._model;
@@ -140,9 +144,25 @@ SDK.FilmStripModel.Frame = class {
* @return {!Promise<?string>}
*/
imageDataPromise() {
- if (this._imageData || !this._snapshot)
+ if (this._imageData || !this._snapshot) {
return Promise.resolve(this._imageData);
+ }
return /** @type {!Promise<?string>} */ (this._snapshot.objectPromise());
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.FilmStripModel = FilmStripModel;
+
+SDK.FilmStripModel._category = _category;
+SDK.FilmStripModel.TraceEvents = TraceEvents;
+
+/** @constructor */
+SDK.FilmStripModel.Frame = Frame;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js
index 21fa0e73b38..eb6e145b260 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HARLog.js
@@ -36,7 +36,7 @@
/**
* @unrestricted
*/
-SDK.HARLog = class {
+export default class HARLog {
/**
* @param {!SDK.NetworkRequest} request
* @param {number} monotonicTime
@@ -51,10 +51,11 @@ SDK.HARLog = class {
* @return {!Promise<!Object>}
*/
static async build(requests) {
- const log = new SDK.HARLog();
+ const log = new HARLog();
const entryPromises = [];
- for (const request of requests)
- entryPromises.push(SDK.HARLog.Entry.build(request));
+ for (const request of requests) {
+ entryPromises.push(Entry.build(request));
+ }
const entries = await Promise.all(entryPromises);
return {version: '1.2', creator: log._creator(), pages: log._buildPages(requests), entries: entries};
}
@@ -75,8 +76,9 @@ SDK.HARLog = class {
for (let i = 0; i < requests.length; ++i) {
const request = requests[i];
const page = SDK.NetworkLog.PageLoad.forRequest(request);
- if (!page || seenIdentifiers[page.id])
+ if (!page || seenIdentifiers[page.id]) {
continue;
+ }
seenIdentifiers[page.id] = true;
pages.push(this._convertPage(page, request));
}
@@ -90,7 +92,7 @@ SDK.HARLog = class {
*/
_convertPage(page, request) {
return {
- startedDateTime: SDK.HARLog.pseudoWallTime(request, page.startTime).toJSON(),
+ startedDateTime: HARLog.pseudoWallTime(request, page.startTime).toJSON(),
id: 'page_' + page.id,
title: page.url, // We don't have actual page title here. URL is probably better than nothing.
pageTimings: {
@@ -107,16 +109,17 @@ SDK.HARLog = class {
*/
_pageEventTime(page, time) {
const startTime = page.startTime;
- if (time === -1 || startTime === -1)
+ if (time === -1 || startTime === -1) {
return -1;
- return SDK.HARLog.Entry._toMilliseconds(time - startTime);
+ }
+ return Entry._toMilliseconds(time - startTime);
}
-};
+}
/**
* @unrestricted
*/
-SDK.HARLog.Entry = class {
+export class Entry {
/**
* @param {!SDK.NetworkRequest} request
*/
@@ -137,30 +140,35 @@ SDK.HARLog.Entry = class {
* @return {!Promise<!Object>}
*/
static async build(request) {
- const harEntry = new SDK.HARLog.Entry(request);
+ const harEntry = new Entry(request);
let ipAddress = harEntry._request.remoteAddress();
const portPositionInString = ipAddress.lastIndexOf(':');
- if (portPositionInString !== -1)
+ if (portPositionInString !== -1) {
ipAddress = ipAddress.substr(0, portPositionInString);
+ }
const timings = harEntry._buildTimings();
let time = 0;
// "ssl" is included in the connect field, so do not double count it.
- for (const t of [timings.blocked, timings.dns, timings.connect, timings.send, timings.wait, timings.receive])
+ for (const t of [timings.blocked, timings.dns, timings.connect, timings.send, timings.wait, timings.receive]) {
time += Math.max(t, 0);
+ }
const initiator = harEntry._request.initiator();
const exportedInitiator = {};
exportedInitiator.type = initiator.type;
- if (initiator.url !== undefined)
+ if (initiator.url !== undefined) {
exportedInitiator.url = initiator.url;
- if (initiator.lineNumber !== undefined)
+ }
+ if (initiator.lineNumber !== undefined) {
exportedInitiator.lineNumber = initiator.lineNumber;
- if (initiator.stack)
+ }
+ if (initiator.stack) {
exportedInitiator.stack = initiator.stack;
+ }
const entry = {
- startedDateTime: SDK.HARLog.pseudoWallTime(harEntry._request, harEntry._request.issueTime()).toJSON(),
+ startedDateTime: HARLog.pseudoWallTime(harEntry._request, harEntry._request.issueTime()).toJSON(),
time: time,
request: await harEntry._buildRequest(),
response: harEntry._buildResponse(),
@@ -175,20 +183,24 @@ SDK.HARLog.Entry = class {
// Chrome specific.
- if (harEntry._request.cached())
+ if (harEntry._request.cached()) {
entry._fromCache = harEntry._request.cachedInMemory() ? 'memory' : 'disk';
+ }
- if (harEntry._request.connectionId !== '0')
+ if (harEntry._request.connectionId !== '0') {
entry.connection = harEntry._request.connectionId;
+ }
const page = SDK.NetworkLog.PageLoad.forRequest(harEntry._request);
- if (page)
+ if (page) {
entry.pageref = 'page_' + page.id;
+ }
if (harEntry._request.resourceType() === Common.resourceTypes.WebSocket) {
const messages = [];
- for (const message of harEntry._request.frames())
+ for (const message of harEntry._request.frames()) {
messages.push({type: message.type, time: message.time, opcode: message.opCode, data: message.text});
+ }
entry._webSocketMessages = messages;
}
@@ -211,8 +223,9 @@ SDK.HARLog.Entry = class {
bodySize: await this._requestBodySize()
};
const postData = await this._buildPostData();
- if (postData)
+ if (postData) {
res.postData = postData;
+ }
return res;
}
@@ -247,8 +260,9 @@ SDK.HARLog.Entry = class {
// text: this._request.content // TODO: pull out into a boolean flag, as content can be huge (and needs to be requested with an async call)
};
const compression = this.responseCompression;
- if (typeof compression === 'number')
+ if (typeof compression === 'number') {
content.compression = compression;
+ }
return content;
}
@@ -264,22 +278,25 @@ SDK.HARLog.Entry = class {
const result = {blocked: -1, dns: -1, ssl: -1, connect: -1, send: 0, wait: 0, receive: 0, _blocked_queueing: -1};
const queuedTime = (issueTime < startTime) ? startTime - issueTime : -1;
- result.blocked = SDK.HARLog.Entry._toMilliseconds(queuedTime);
- result._blocked_queueing = SDK.HARLog.Entry._toMilliseconds(queuedTime);
+ result.blocked = Entry._toMilliseconds(queuedTime);
+ result._blocked_queueing = Entry._toMilliseconds(queuedTime);
let highestTime = 0;
if (timing) {
// "blocked" here represents both queued + blocked/stalled + proxy (ie: anything before request was started).
// We pick the better of when the network request start was reported and pref timing.
const blockedStart = leastNonNegative([timing.dnsStart, timing.connectStart, timing.sendStart]);
- if (blockedStart !== Infinity)
+ if (blockedStart !== Infinity) {
result.blocked += blockedStart;
+ }
// Proxy is part of blocked but sometimes (like quic) blocked is -1 but has proxy timings.
- if (timing.proxyEnd !== -1)
+ if (timing.proxyEnd !== -1) {
result._blocked_proxy = timing.proxyEnd - timing.proxyStart;
- if (result._blocked_proxy && result._blocked_proxy > result.blocked)
+ }
+ if (result._blocked_proxy && result._blocked_proxy > result.blocked) {
result.blocked = result._blocked_proxy;
+ }
const dnsStart = timing.dnsEnd >= 0 ? blockedStart : 0;
const dnsEnd = timing.dnsEnd >= 0 ? timing.dnsEnd : -1;
@@ -299,8 +316,9 @@ SDK.HARLog.Entry = class {
const sendEnd = timing.sendEnd >= 0 ? timing.sendEnd : 0;
result.send = sendEnd - sendStart;
// Quic sometimes says that sendStart is before connectionEnd (see: crbug.com/740792)
- if (result.send < 0)
+ if (result.send < 0) {
result.send = 0;
+ }
highestTime = Math.max(sendEnd, connectEnd, sslEnd, dnsEnd, blockedStart, 0);
} else if (this._request.responseReceivedTime === -1) {
// Means that we don't have any more details after blocked, so attribute all to blocked.
@@ -310,11 +328,11 @@ SDK.HARLog.Entry = class {
const requestTime = timing ? timing.requestTime : startTime;
const waitStart = highestTime;
- const waitEnd = SDK.HARLog.Entry._toMilliseconds(this._request.responseReceivedTime - requestTime);
+ const waitEnd = Entry._toMilliseconds(this._request.responseReceivedTime - requestTime);
result.wait = waitEnd - waitStart;
const receiveStart = waitEnd;
- const receiveEnd = SDK.HARLog.Entry._toMilliseconds(this._request.endTime - requestTime);
+ const receiveEnd = Entry._toMilliseconds(this._request.endTime - requestTime);
result.receive = Math.max(receiveEnd - receiveStart, 0);
return result;
@@ -329,16 +347,18 @@ SDK.HARLog.Entry = class {
}
/**
- * @return {!Promise<!Object>}
+ * @return {!Promise<?Object>}
*/
async _buildPostData() {
const postData = await this._request.requestFormData();
- if (!postData)
+ if (!postData) {
return null;
+ }
const res = {mimeType: this._request.requestContentType() || '', text: postData};
const formParameters = await this._request.formParameters();
- if (formParameters)
+ if (formParameters) {
res.params = this._buildParameters(formParameters);
+ }
return res;
}
@@ -376,12 +396,13 @@ SDK.HARLog.Entry = class {
value: cookie.value(),
path: cookie.path(),
domain: cookie.domain(),
- expires: cookie.expiresDate(SDK.HARLog.pseudoWallTime(this._request, this._request.startTime)),
+ expires: cookie.expiresDate(HARLog.pseudoWallTime(this._request, this._request.startTime)),
httpOnly: cookie.httpOnly(),
secure: cookie.secure()
};
- if (cookie.sameSite())
+ if (cookie.sameSite()) {
c.sameSite = cookie.sameSite();
+ }
return c;
}
@@ -390,8 +411,9 @@ SDK.HARLog.Entry = class {
*/
async _requestBodySize() {
const postData = await this._request.requestFormData();
- if (!postData)
+ if (!postData) {
return 0;
+ }
// As per the har spec, returns the length in bytes of the posted data.
// TODO(jarhar): This will be wrong if the underlying encoding is not UTF-8. NetworkRequest.requestFormData is
@@ -404,10 +426,12 @@ SDK.HARLog.Entry = class {
* @return {number}
*/
get responseBodySize() {
- if (this._request.cached() || this._request.statusCode === 304)
+ if (this._request.cached() || this._request.statusCode === 304) {
return 0;
- if (!this._request.responseHeadersText)
+ }
+ if (!this._request.responseHeadersText) {
return -1;
+ }
return this._request.transferSize - this._request.responseHeadersText.length;
}
@@ -415,13 +439,27 @@ SDK.HARLog.Entry = class {
* @return {number|undefined}
*/
get responseCompression() {
- if (this._request.cached() || this._request.statusCode === 304 || this._request.statusCode === 206)
+ if (this._request.cached() || this._request.statusCode === 304 || this._request.statusCode === 206) {
return;
- if (!this._request.responseHeadersText)
+ }
+ if (!this._request.responseHeadersText) {
return;
+ }
return this._request.resourceSize - this.responseBodySize;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.HARLog = HARLog;
+
+/** @constructor */
+SDK.HARLog.Entry = Entry;
/** @typedef {!{
blocked: number,
@@ -434,4 +472,4 @@ SDK.HARLog.Entry = class {
_blocked_queueing: number,
_blocked_proxy: (number|undefined)
}} */
-SDK.HARLog.Entry.Timing;
+SDK.HARLog.Entry.Timing; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
index 6919fa79dd6..05de2ea5d23 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
@@ -1,13 +1,13 @@
/**
* @unrestricted
*/
-SDK.HeapProfilerModel = class extends SDK.SDKModel {
+export default class HeapProfilerModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
- target.registerHeapProfilerDispatcher(new SDK.HeapProfilerDispatcher(this));
+ target.registerHeapProfilerDispatcher(new HeapProfilerDispatcher(this));
this._enabled = false;
this._heapProfilerAgent = target.heapProfilerAgent();
this._memoryAgent = target.memoryAgent();
@@ -30,8 +30,9 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._enabled = true;
this._heapProfilerAgent.enable();
@@ -41,8 +42,9 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @param {number=} samplingRateInBytes
*/
startSampling(samplingRateInBytes) {
- if (this._samplingProfilerDepth++)
+ if (this._samplingProfilerDepth++) {
return;
+ }
const defaultSamplingIntervalInBytes = 16384;
this._heapProfilerAgent.startSampling(samplingRateInBytes || defaultSamplingIntervalInBytes);
}
@@ -51,10 +53,12 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>}
*/
stopSampling() {
- if (!this._samplingProfilerDepth)
+ if (!this._samplingProfilerDepth) {
throw new Error('Sampling profiler is not running.');
- if (--this._samplingProfilerDepth)
+ }
+ if (--this._samplingProfilerDepth) {
return this.getSamplingProfile();
+ }
return this._heapProfilerAgent.stopSampling();
}
@@ -71,33 +75,35 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
}
/**
- * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
+ * @return {!Promise<!NativeHeapProfile>}
*/
async stopNativeSampling() {
- const rawProfile = await this._memoryAgent.getSamplingProfile();
+ const rawProfile = /** @type {!Protocol.Memory.SamplingProfile} */ (await this._memoryAgent.getSamplingProfile());
this._memoryAgent.stopSampling();
return this._convertNativeProfile(rawProfile);
}
/**
- * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
+ * @return {!Promise<!NativeHeapProfile>}
*/
async takeNativeSnapshot() {
- const rawProfile = await this._memoryAgent.getAllTimeSamplingProfile();
+ const rawProfile =
+ /** @type {!Protocol.Memory.SamplingProfile} */ (await this._memoryAgent.getAllTimeSamplingProfile());
return this._convertNativeProfile(rawProfile);
}
/**
- * @return {!Promise<!SDK.HeapProfilerModel.NativeHeapProfile>}
+ * @return {!Promise<!NativeHeapProfile>}
*/
async takeNativeBrowserSnapshot() {
- const rawProfile = await this._memoryAgent.getBrowserSamplingProfile();
+ const rawProfile =
+ /** @type {!Protocol.Memory.SamplingProfile} */ (await this._memoryAgent.getBrowserSamplingProfile());
return this._convertNativeProfile(rawProfile);
}
/**
* @param {!Protocol.Memory.SamplingProfile} rawProfile
- * @return {!SDK.HeapProfilerModel.NativeHeapProfile}
+ * @return {!NativeHeapProfile}
*/
_convertNativeProfile(rawProfile) {
const head = /** @type {!Protocol.HeapProfiler.SamplingHeapProfileNode} */
@@ -105,8 +111,9 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
for (const sample of rawProfile.samples) {
const node = sample.stack.reverse().reduce((node, name) => {
let child = node.children.get(name);
- if (child)
+ if (child) {
return child;
+ }
const namespace = /^([^:]*)::/.exec(name);
child = {
children: new Map(),
@@ -125,7 +132,7 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
}
convertChildren(head);
- return new SDK.HeapProfilerModel.NativeHeapProfile(head, rawProfile.modules);
+ return new NativeHeapProfile(head, rawProfile.modules);
}
/**
@@ -189,7 +196,7 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @param {!Array<number>} samples
*/
heapStatsUpdate(samples) {
- this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.HeapStatsUpdate, samples);
+ this.dispatchEventToListeners(Events.HeapStatsUpdate, samples);
}
/**
@@ -197,15 +204,14 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @param {number} timestamp
*/
lastSeenObjectId(lastSeenObjectId, timestamp) {
- this.dispatchEventToListeners(
- SDK.HeapProfilerModel.Events.LastSeenObjectId, {lastSeenObjectId: lastSeenObjectId, timestamp: timestamp});
+ this.dispatchEventToListeners(Events.LastSeenObjectId, {lastSeenObjectId: lastSeenObjectId, timestamp: timestamp});
}
/**
* @param {string} chunk
*/
addHeapSnapshotChunk(chunk) {
- this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.AddHeapSnapshotChunk, chunk);
+ this.dispatchEventToListeners(Events.AddHeapSnapshotChunk, chunk);
}
/**
@@ -214,19 +220,16 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @param {boolean=} finished
*/
reportHeapSnapshotProgress(done, total, finished) {
- this.dispatchEventToListeners(
- SDK.HeapProfilerModel.Events.ReportHeapSnapshotProgress, {done: done, total: total, finished: finished});
+ this.dispatchEventToListeners(Events.ReportHeapSnapshotProgress, {done: done, total: total, finished: finished});
}
resetProfiles() {
- this.dispatchEventToListeners(SDK.HeapProfilerModel.Events.ResetProfiles, this);
+ this.dispatchEventToListeners(Events.ResetProfiles, this);
}
-};
-
-SDK.SDKModel.register(SDK.HeapProfilerModel, SDK.Target.Capability.JS, false);
+}
/** @enum {symbol} */
-SDK.HeapProfilerModel.Events = {
+export const Events = {
HeapStatsUpdate: Symbol('HeapStatsUpdate'),
LastSeenObjectId: Symbol('LastSeenObjectId'),
AddHeapSnapshotChunk: Symbol('AddHeapSnapshotChunk'),
@@ -235,9 +238,10 @@ SDK.HeapProfilerModel.Events = {
};
/**
+ * @implements {Protocol.Profiler.Profile}
* @extends {Protocol.HeapProfiler.SamplingHeapProfile}
*/
-SDK.HeapProfilerModel.NativeHeapProfile = class {
+export class NativeHeapProfile {
/**
* @param {!Protocol.HeapProfiler.SamplingHeapProfileNode} head
* @param {!Array<!Protocol.Memory.Module>} modules
@@ -246,13 +250,13 @@ SDK.HeapProfilerModel.NativeHeapProfile = class {
this.head = head;
this.modules = modules;
}
-};
+}
/**
* @extends {Protocol.HeapProfilerDispatcher}
* @unrestricted
*/
-SDK.HeapProfilerDispatcher = class {
+export class HeapProfilerDispatcher {
constructor(model) {
this._heapProfilerModel = model;
}
@@ -298,4 +302,27 @@ SDK.HeapProfilerDispatcher = class {
resetProfiles() {
this._heapProfilerModel.resetProfiles();
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.HeapProfilerModel = HeapProfilerModel;
+
+/** @enum {symbol} */
+SDK.HeapProfilerModel.Events = Events;
+
+/**
+ * @implements {Protocol.Profiler.Profile}
+ * @extends {Protocol.HeapProfiler.SamplingHeapProfile}
+ */
+SDK.HeapProfilerModel.NativeHeapProfile = NativeHeapProfile;
+
+/** @constructor */
+SDK.HeapProfilerDispatcher = HeapProfilerDispatcher;
+
+SDK.SDKModel.register(SDK.HeapProfilerModel, SDK.Target.Capability.JS, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js
index 992bcdb5839..9ebbf10ca14 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/IsolateManager.js
@@ -5,41 +5,45 @@
/**
* @implements {SDK.SDKModelObserver}
*/
-SDK.IsolateManager = class extends Common.Object {
+export default class IsolateManager extends Common.Object {
constructor() {
super();
console.assert(!SDK.isolateManager, 'Use SDK.isolateManager singleton.');
- /** @type {!Map<string, !SDK.IsolateManager.Isolate>} */
+ /** @type {!Map<string, !Isolate>} */
this._isolates = new Map();
// _isolateIdByModel contains null while the isolateId is being retrieved.
/** @type {!Map<!SDK.RuntimeModel, ?string>} */
this._isolateIdByModel = new Map();
- /** @type {!Set<!SDK.IsolateManager.Observer>} */
+ /** @type {!Set<!Observer>} */
this._observers = new Set();
SDK.targetManager.observeModels(SDK.RuntimeModel, this);
this._pollId = 0;
}
/**
- * @param {!SDK.IsolateManager.Observer} observer
+ * @param {!Observer} observer
*/
observeIsolates(observer) {
- if (this._observers.has(observer))
+ if (this._observers.has(observer)) {
throw new Error('Observer can only be registered once');
- if (!this._observers.size)
+ }
+ if (!this._observers.size) {
this._poll();
+ }
this._observers.add(observer);
- for (const isolate of this._isolates.values())
+ for (const isolate of this._isolates.values()) {
observer.isolateAdded(isolate);
+ }
}
/**
- * @param {!SDK.IsolateManager.Observer} observer
+ * @param {!Observer} observer
*/
unobserveIsolates(observer) {
this._observers.delete(observer);
- if (!this._observers.size)
- ++this._pollId; // Stops the current polling loop.
+ if (!this._observers.size) {
+ ++this._pollId;
+ } // Stops the current polling loop.
}
/**
@@ -67,16 +71,18 @@ SDK.IsolateManager = class extends Common.Object {
this._isolateIdByModel.set(model, isolateId);
let isolate = this._isolates.get(isolateId);
if (!isolate) {
- isolate = new SDK.IsolateManager.Isolate(isolateId);
+ isolate = new Isolate(isolateId);
this._isolates.set(isolateId, isolate);
}
isolate._models.add(model);
if (isolate._models.size === 1) {
- for (const observer of this._observers)
+ for (const observer of this._observers) {
observer.isolateAdded(isolate);
+ }
} else {
- for (const observer of this._observers)
+ for (const observer of this._observers) {
observer.isolateChanged(isolate);
+ }
}
}
@@ -87,30 +93,33 @@ SDK.IsolateManager = class extends Common.Object {
modelRemoved(model) {
const isolateId = this._isolateIdByModel.get(model);
this._isolateIdByModel.delete(model);
- if (!isolateId)
+ if (!isolateId) {
return;
+ }
const isolate = this._isolates.get(isolateId);
isolate._models.delete(model);
if (isolate._models.size) {
- for (const observer of this._observers)
+ for (const observer of this._observers) {
observer.isolateChanged(isolate);
+ }
return;
}
- for (const observer of this._observers)
+ for (const observer of this._observers) {
observer.isolateRemoved(isolate);
+ }
this._isolates.delete(isolateId);
}
/**
* @param {!SDK.RuntimeModel} model
- * @return {?SDK.IsolateManager.Isolate}
+ * @return {?Isolate}
*/
isolateByModel(model) {
return this._isolates.get(this._isolateIdByModel.get(model) || '') || null;
}
/**
- * @return {!IteratorIterable<!SDK.IsolateManager.Isolate>}
+ * @return {!IteratorIterable<!Isolate>}
*/
isolates() {
return this._isolates.values();
@@ -120,41 +129,42 @@ SDK.IsolateManager = class extends Common.Object {
const pollId = this._pollId;
while (pollId === this._pollId) {
await Promise.all(Array.from(this.isolates(), isolate => isolate._update()));
- await new Promise(r => setTimeout(r, SDK.IsolateManager.PollIntervalMs));
+ await new Promise(r => setTimeout(r, PollIntervalMs));
}
}
-};
+}
/**
* @interface
*/
-SDK.IsolateManager.Observer = function() {};
-
-SDK.IsolateManager.Observer.prototype = {
+export class Observer {
/**
- * @param {!SDK.IsolateManager.Isolate} isolate
+ * @param {!Isolate} isolate
*/
- isolateAdded(isolate) {},
+ isolateAdded(isolate) {
+ }
/**
- * @param {!SDK.IsolateManager.Isolate} isolate
+ * @param {!Isolate} isolate
*/
- isolateRemoved(isolate) {},
+ isolateRemoved(isolate) {
+ }
/**
- * @param {!SDK.IsolateManager.Isolate} isolate
+ * @param {!Isolate} isolate
*/
- isolateChanged(isolate) {},
-};
+ isolateChanged(isolate) {
+ }
+}
/** @enum {symbol} */
-SDK.IsolateManager.Events = {
+export const Events = {
MemoryChanged: Symbol('MemoryChanged')
};
-SDK.IsolateManager.MemoryTrendWindowMs = 120e3;
-SDK.IsolateManager.PollIntervalMs = 2e3;
+export const MemoryTrendWindowMs = 120e3;
+export const PollIntervalMs = 2e3;
-SDK.IsolateManager.Isolate = class {
+export class Isolate {
/**
* @param {string} id
*/
@@ -163,8 +173,8 @@ SDK.IsolateManager.Isolate = class {
/** @type {!Set<!SDK.RuntimeModel>} */
this._models = new Set();
this._usedHeapSize = 0;
- const count = SDK.IsolateManager.MemoryTrendWindowMs / SDK.IsolateManager.PollIntervalMs;
- this._memoryTrend = new SDK.IsolateManager.MemoryTrend(count);
+ const count = MemoryTrendWindowMs / PollIntervalMs;
+ this._memoryTrend = new MemoryTrend(count);
}
/**
@@ -199,11 +209,12 @@ SDK.IsolateManager.Isolate = class {
async _update() {
const model = this.runtimeModel();
const usage = model && await model.heapUsage();
- if (!usage)
+ if (!usage) {
return;
+ }
this._usedHeapSize = usage.usedSize;
this._memoryTrend.add(this._usedHeapSize);
- SDK.isolateManager.dispatchEventToListeners(SDK.IsolateManager.Events.MemoryChanged, this);
+ SDK.isolateManager.dispatchEventToListeners(Events.MemoryChanged, this);
}
/**
@@ -226,12 +237,12 @@ SDK.IsolateManager.Isolate = class {
usedHeapSizeGrowRate() {
return this._memoryTrend.fitSlope();
}
-};
+}
/**
* @unrestricted
*/
-SDK.IsolateManager.MemoryTrend = class {
+export class MemoryTrend {
/**
* @param {number} maxCount
*/
@@ -293,6 +304,30 @@ SDK.IsolateManager.MemoryTrend = class {
const n = this.count();
return n < 2 ? 0 : (this._sxy - this._sx * this._sy / n) / (this._sxx - this._sx * this._sx / n);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.IsolateManager = IsolateManager;
+
+/** @interface */
+SDK.IsolateManager.Observer = Observer;
+
+/** @enum {symbol} */
+SDK.IsolateManager.Events = Events;
+
+SDK.IsolateManager.MemoryTrendWindowMs = MemoryTrendWindowMs;
+SDK.IsolateManager.PollIntervalMs = PollIntervalMs;
+
+/** @constructor */
+SDK.IsolateManager.Isolate = Isolate;
+
+/** @constructor */
+SDK.IsolateManager.MemoryTrend = MemoryTrend;
-SDK.isolateManager = new SDK.IsolateManager();
+SDK.isolateManager = new IsolateManager(); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/LayerTreeBase.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/LayerTreeBase.js
index d8d45f57818..cdd4a23c142 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/LayerTreeBase.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/LayerTreeBase.js
@@ -1,150 +1,165 @@
// 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.
-/** @typedef {!{
- rect: !Protocol.DOM.Rect,
- snapshot: !SDK.PaintProfilerSnapshot
- }}
-*/
-SDK.SnapshotWithRect;
/**
* @interface
*/
-SDK.Layer = function() {};
-
-SDK.Layer.prototype = {
+export class Layer {
/**
* @return {string}
*/
- id() {},
+ id() {
+ }
/**
* @return {?string}
*/
- parentId() {},
+ parentId() {
+ }
/**
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
- parent() {},
+ parent() {
+ }
/**
* @return {boolean}
*/
- isRoot() {},
+ isRoot() {
+ }
/**
- * @return {!Array.<!SDK.Layer>}
+ * @return {!Array.<!Layer>}
*/
- children() {},
+ children() {
+ }
/**
- * @param {!SDK.Layer} child
+ * @param {!Layer} child
*/
- addChild(child) {},
+ addChild(child) {
+ }
/**
* @return {?SDK.DOMNode}
*/
- node() {},
+ node() {
+ }
/**
* @return {?SDK.DOMNode}
*/
- nodeForSelfOrAncestor() {},
+ nodeForSelfOrAncestor() {
+ }
/**
* @return {number}
*/
- offsetX() {},
+ offsetX() {
+ }
/**
* @return {number}
*/
- offsetY() {},
+ offsetY() {
+ }
/**
* @return {number}
*/
- width() {},
+ width() {
+ }
/**
* @return {number}
*/
- height() {},
+ height() {
+ }
/**
* @return {?Array.<number>}
*/
- transform() {},
+ transform() {
+ }
/**
* @return {!Array.<number>}
*/
- quad() {},
+ quad() {
+ }
/**
* @return {!Array.<number>}
*/
- anchorPoint() {},
+ anchorPoint() {
+ }
/**
* @return {boolean}
*/
- invisible() {},
+ invisible() {
+ }
/**
* @return {number}
*/
- paintCount() {},
+ paintCount() {
+ }
/**
* @return {?Protocol.DOM.Rect}
*/
- lastPaintRect() {},
+ lastPaintRect() {
+ }
/**
* @return {!Array.<!Protocol.LayerTree.ScrollRect>}
*/
- scrollRects() {},
+ scrollRects() {
+ }
/**
- * @return {?SDK.Layer.StickyPositionConstraint}
+ * @return {?Layer.StickyPositionConstraint}
*/
- stickyPositionConstraint() {},
+ stickyPositionConstraint() {
+ }
/**
* @return {number}
*/
- gpuMemoryUsage() {},
+ gpuMemoryUsage() {
+ }
/**
* @return {!Promise<!Array<string>>}
*/
- requestCompositingReasons() {},
+ requestCompositingReasons() {
+ }
/**
* @return {boolean}
*/
- drawsContent() {},
+ drawsContent() {
+ }
/**
* @return {!Array<!Promise<?SDK.SnapshotWithRect>>}
*/
snapshots() {}
-};
+}
-SDK.Layer.ScrollRectType = {
+Layer.ScrollRectType = {
NonFastScrollable: 'NonFastScrollable',
TouchEventHandler: 'TouchEventHandler',
WheelEventHandler: 'WheelEventHandler',
RepaintsOnScroll: 'RepaintsOnScroll'
};
-SDK.Layer.StickyPositionConstraint = class {
+export class StickyPositionConstraint {
/**
- * @param {?SDK.LayerTreeBase} layerTree
+ * @param {?LayerTreeBase} layerTree
* @param {!Protocol.LayerTree.StickyPositionConstraint} constraint
* @struct
*/
@@ -153,15 +168,17 @@ SDK.Layer.StickyPositionConstraint = class {
this._stickyBoxRect = constraint.stickyBoxRect;
/** @type {!Protocol.DOM.Rect} */
this._containingBlockRect = constraint.containingBlockRect;
- /** @type {?SDK.Layer} */
+ /** @type {?Layer} */
this._nearestLayerShiftingStickyBox = null;
- if (layerTree && constraint.nearestLayerShiftingStickyBox)
+ if (layerTree && constraint.nearestLayerShiftingStickyBox) {
this._nearestLayerShiftingStickyBox = layerTree.layerById(constraint.nearestLayerShiftingStickyBox);
+ }
- /** @type {?SDK.Layer} */
+ /** @type {?Layer} */
this._nearestLayerShiftingContainingBlock = null;
- if (layerTree && constraint.nearestLayerShiftingContainingBlock)
+ if (layerTree && constraint.nearestLayerShiftingContainingBlock) {
this._nearestLayerShiftingContainingBlock = layerTree.layerById(constraint.nearestLayerShiftingContainingBlock);
+ }
}
/**
@@ -179,24 +196,24 @@ SDK.Layer.StickyPositionConstraint = class {
}
/**
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
nearestLayerShiftingStickyBox() {
return this._nearestLayerShiftingStickyBox;
}
/**
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
nearestLayerShiftingContainingBlock() {
return this._nearestLayerShiftingContainingBlock;
}
-};
+}
/**
* @unrestricted
*/
-SDK.LayerTreeBase = class {
+export default class LayerTreeBase {
/**
* @param {?SDK.Target} target
*/
@@ -218,14 +235,14 @@ SDK.LayerTreeBase = class {
}
/**
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
root() {
return this._root;
}
/**
- * @param {?SDK.Layer} root
+ * @param {?Layer} root
* @protected
*/
setRoot(root) {
@@ -233,14 +250,14 @@ SDK.LayerTreeBase = class {
}
/**
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
contentRoot() {
return this._contentRoot;
}
/**
- * @param {?SDK.Layer} contentRoot
+ * @param {?Layer} contentRoot
* @protected
*/
setContentRoot(contentRoot) {
@@ -248,22 +265,23 @@ SDK.LayerTreeBase = class {
}
/**
- * @param {function(!SDK.Layer)} callback
- * @param {?SDK.Layer=} root
+ * @param {function(!Layer)} callback
+ * @param {?Layer=} root
* @return {boolean}
*/
forEachLayer(callback, root) {
if (!root) {
root = this.root();
- if (!root)
+ if (!root) {
return false;
+ }
}
return callback(root) || root.children().some(this.forEachLayer.bind(this, callback));
}
/**
* @param {string} id
- * @return {?SDK.Layer}
+ * @return {?Layer}
*/
layerById(id) {
return this._layersById[id] || null;
@@ -274,15 +292,18 @@ SDK.LayerTreeBase = class {
* @return {!Promise}
*/
async resolveBackendNodeIds(requestedNodeIds) {
- if (!requestedNodeIds.size || !this._domModel)
+ if (!requestedNodeIds.size || !this._domModel) {
return;
+ }
const nodesMap = await this._domModel.pushNodesByBackendIdsToFrontend(requestedNodeIds);
- if (!nodesMap)
+ if (!nodesMap) {
return;
- for (const nodeId of nodesMap.keysArray())
+ }
+ for (const nodeId of nodesMap.keysArray()) {
this._backendNodeIdToNode.set(nodeId, nodesMap.get(nodeId) || null);
+ }
}
/**
@@ -313,4 +334,26 @@ SDK.LayerTreeBase = class {
_nodeForId(id) {
return this._domModel ? this._domModel.nodeForId(id) : null;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @interface */
+SDK.Layer = Layer;
+
+/** @constructor */
+SDK.LayerTreeBase = LayerTreeBase;
+
+/** @constructor */
+SDK.Layer.StickyPositionConstraint = StickyPositionConstraint;
+
+/** @typedef {!{
+ rect: !Protocol.DOM.Rect,
+ snapshot: !SDK.PaintProfilerSnapshot
+ }}
+*/
+SDK.SnapshotWithRect; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/LogModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/LogModel.js
index dd9ec8c28f8..18778a1660c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/LogModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/LogModel.js
@@ -5,7 +5,7 @@
/**
* @implements {Protocol.LogDispatcher}
*/
-SDK.LogModel = class extends SDK.SDKModel {
+export default class LogModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -28,17 +28,29 @@ SDK.LogModel = class extends SDK.SDKModel {
* @param {!Protocol.Log.LogEntry} payload
*/
entryAdded(payload) {
- this.dispatchEventToListeners(SDK.LogModel.Events.EntryAdded, {logModel: this, entry: payload});
+ this.dispatchEventToListeners(Events.EntryAdded, {logModel: this, entry: payload});
}
requestClear() {
this._logAgent.clear();
}
-};
-
-SDK.SDKModel.register(SDK.LogModel, SDK.Target.Capability.Log, true);
+}
/** @enum {symbol} */
-SDK.LogModel.Events = {
+export const Events = {
EntryAdded: Symbol('EntryAdded')
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.LogModel = LogModel;
+
+/** @enum {symbol} */
+SDK.LogModel.Events = Events;
+
+SDK.SDKModel.register(SDK.LogModel, SDK.Target.Capability.Log, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js
index 64e0f1be453..34c53a22a2e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkLog.js
@@ -31,14 +31,14 @@
/**
* @implements {SDK.SDKModelObserver<!SDK.NetworkManager>}
*/
-SDK.NetworkLog = class extends Common.Object {
+export default class NetworkLog extends Common.Object {
constructor() {
super();
/** @type {!Array<!SDK.NetworkRequest>} */
this._requests = [];
/** @type {!Set<!SDK.NetworkRequest>} */
this._requestsSet = new Set();
- /** @type {!Map<!SDK.NetworkManager, !SDK.NetworkLog.PageLoad>} */
+ /** @type {!Map<!SDK.NetworkManager, !PageLoad>} */
this._pageLoadForManager = new Map();
this._isRecording = true;
SDK.targetManager.observeModels(SDK.NetworkManager, this);
@@ -72,7 +72,7 @@ SDK.NetworkLog = class extends Common.Object {
SDK.ResourceTreeModel.Events.DOMContentLoaded, this._onDOMContentLoaded.bind(this, resourceTreeModel)));
}
- networkManager[SDK.NetworkLog._events] = eventListeners;
+ networkManager[_events] = eventListeners;
}
/**
@@ -87,15 +87,16 @@ SDK.NetworkLog = class extends Common.Object {
* @param {!SDK.NetworkManager} networkManager
*/
_removeNetworkManagerListeners(networkManager) {
- Common.EventTarget.removeEventListeners(networkManager[SDK.NetworkLog._events]);
+ Common.EventTarget.removeEventListeners(networkManager[_events]);
}
/**
* @param {boolean} enabled
*/
setIsRecording(enabled) {
- if (this._isRecording === enabled)
+ if (this._isRecording === enabled) {
return;
+ }
this._isRecording = enabled;
if (enabled) {
SDK.targetManager.observeModels(SDK.NetworkManager, this);
@@ -129,8 +130,9 @@ SDK.NetworkLog = class extends Common.Object {
// We itterate backwards because the last item will likely be the one needed for console network request lookups.
for (let i = this._requests.length - 1; i >= 0; i--) {
const request = this._requests[i];
- if (requestId === request.requestId() && networkManager === SDK.NetworkManager.forRequest(request))
+ if (requestId === request.requestId() && networkManager === SDK.NetworkManager.forRequest(request)) {
return request;
+ }
}
return null;
}
@@ -142,8 +144,9 @@ SDK.NetworkLog = class extends Common.Object {
*/
_requestByManagerAndURL(networkManager, url) {
for (const request of this._requests) {
- if (url === request.url() && networkManager === SDK.NetworkManager.forRequest(request))
+ if (url === request.url() && networkManager === SDK.NetworkManager.forRequest(request)) {
return request;
+ }
}
return null;
}
@@ -152,9 +155,9 @@ SDK.NetworkLog = class extends Common.Object {
* @param {!SDK.NetworkRequest} request
*/
_initializeInitiatorSymbolIfNeeded(request) {
- if (!request[SDK.NetworkLog._initiatorDataSymbol]) {
+ if (!request[_initiatorDataSymbol]) {
/** @type {!{info: ?SDK.NetworkLog._InitiatorInfo, chain: !Set<!SDK.NetworkRequest>, request: (?SDK.NetworkRequest|undefined)}} */
- request[SDK.NetworkLog._initiatorDataSymbol] = {
+ request[_initiatorDataSymbol] = {
info: null,
chain: null,
request: undefined,
@@ -168,8 +171,9 @@ SDK.NetworkLog = class extends Common.Object {
*/
initiatorInfoForRequest(request) {
this._initializeInitiatorSymbolIfNeeded(request);
- if (request[SDK.NetworkLog._initiatorDataSymbol].info)
- return request[SDK.NetworkLog._initiatorDataSymbol].info;
+ if (request[_initiatorDataSymbol].info) {
+ return request[_initiatorDataSymbol].info;
+ }
let type = SDK.NetworkRequest.InitiatorType.Other;
let url = '';
@@ -191,8 +195,9 @@ SDK.NetworkLog = class extends Common.Object {
} else if (initiator.type === Protocol.Network.InitiatorType.Script) {
for (let stack = initiator.stack; stack; stack = stack.parent) {
const topFrame = stack.callFrames.length ? stack.callFrames[0] : null;
- if (!topFrame)
+ if (!topFrame) {
continue;
+ }
type = SDK.NetworkRequest.InitiatorType.Script;
url = topFrame.url || Common.UIString('<anonymous>');
lineNumber = topFrame.lineNumber;
@@ -205,8 +210,9 @@ SDK.NetworkLog = class extends Common.Object {
url = initiator.url;
lineNumber = initiator.lineNumber || 0;
}
- if (initiator.stack && initiator.stack.callFrames && initiator.stack.callFrames.length)
+ if (initiator.stack && initiator.stack.callFrames && initiator.stack.callFrames.length) {
initiatorStack = initiator.stack || null;
+ }
} else if (initiator.type === Protocol.Network.InitiatorType.Preload) {
type = SDK.NetworkRequest.InitiatorType.Preload;
} else if (initiator.type === Protocol.Network.InitiatorType.SignedExchange) {
@@ -215,7 +221,7 @@ SDK.NetworkLog = class extends Common.Object {
}
}
- request[SDK.NetworkLog._initiatorDataSymbol].info = {
+ request[_initiatorDataSymbol].info = {
type: type,
url: url,
lineNumber: lineNumber,
@@ -223,7 +229,7 @@ SDK.NetworkLog = class extends Common.Object {
scriptId: scriptId,
stack: initiatorStack
};
- return request[SDK.NetworkLog._initiatorDataSymbol].info;
+ return request[_initiatorDataSymbol].info;
}
/**
@@ -236,8 +242,9 @@ SDK.NetworkLog = class extends Common.Object {
const networkManager = SDK.NetworkManager.forRequest(request);
for (const otherRequest of this._requests) {
const otherRequestManager = SDK.NetworkManager.forRequest(request);
- if (networkManager === otherRequestManager && this._initiatorChain(otherRequest).has(request))
+ if (networkManager === otherRequestManager && this._initiatorChain(otherRequest).has(request)) {
initiated.add(otherRequest);
+ }
}
return {initiators: this._initiatorChain(request), initiated: initiated};
}
@@ -249,24 +256,26 @@ SDK.NetworkLog = class extends Common.Object {
_initiatorChain(request) {
this._initializeInitiatorSymbolIfNeeded(request);
let initiatorChainCache =
- /** @type {?Set<!SDK.NetworkRequest>} */ (request[SDK.NetworkLog._initiatorDataSymbol].chain);
- if (initiatorChainCache)
+ /** @type {?Set<!SDK.NetworkRequest>} */ (request[_initiatorDataSymbol].chain);
+ if (initiatorChainCache) {
return initiatorChainCache;
+ }
initiatorChainCache = new Set();
let checkRequest = request;
do {
- if (checkRequest[SDK.NetworkLog._initiatorDataSymbol].chain) {
- initiatorChainCache.addAll(checkRequest[SDK.NetworkLog._initiatorDataSymbol].chain);
+ if (checkRequest[_initiatorDataSymbol].chain) {
+ initiatorChainCache.addAll(checkRequest[_initiatorDataSymbol].chain);
break;
}
- if (initiatorChainCache.has(checkRequest))
+ if (initiatorChainCache.has(checkRequest)) {
break;
+ }
initiatorChainCache.add(checkRequest);
checkRequest = this._initiatorRequest(checkRequest);
} while (checkRequest);
- request[SDK.NetworkLog._initiatorDataSymbol].chain = initiatorChainCache;
+ request[_initiatorDataSymbol].chain = initiatorChainCache;
return initiatorChainCache;
}
@@ -276,18 +285,19 @@ SDK.NetworkLog = class extends Common.Object {
*/
_initiatorRequest(request) {
this._initializeInitiatorSymbolIfNeeded(request);
- if (request[SDK.NetworkLog._initiatorDataSymbol].request !== undefined)
- return request[SDK.NetworkLog._initiatorDataSymbol].request;
+ if (request[_initiatorDataSymbol].request !== undefined) {
+ return request[_initiatorDataSymbol].request;
+ }
const url = this.initiatorInfoForRequest(request).url;
const networkManager = SDK.NetworkManager.forRequest(request);
- request[SDK.NetworkLog._initiatorDataSymbol].request =
- networkManager ? this._requestByManagerAndURL(networkManager, url) : null;
- return request[SDK.NetworkLog._initiatorDataSymbol].request;
+ request[_initiatorDataSymbol].request = networkManager ? this._requestByManagerAndURL(networkManager, url) : null;
+ return request[_initiatorDataSymbol].request;
}
_willReloadPage() {
- if (!Common.moduleSetting('network_log.preserve-log').get())
+ if (!Common.moduleSetting('network_log.preserve-log').get()) {
this.reset();
+ }
}
/**
@@ -296,24 +306,26 @@ SDK.NetworkLog = class extends Common.Object {
_onMainFrameNavigated(event) {
const mainFrame = /** @type {!SDK.ResourceTreeFrame} */ (event.data);
const manager = mainFrame.resourceTreeModel().target().model(SDK.NetworkManager);
- if (!manager || mainFrame.resourceTreeModel().target().parentTarget())
+ if (!manager || mainFrame.resourceTreeModel().target().parentTarget()) {
return;
+ }
const oldRequests = this._requests;
const oldManagerRequests = this._requests.filter(request => SDK.NetworkManager.forRequest(request) === manager);
const oldRequestsSet = this._requestsSet;
this._requests = [];
this._requestsSet = new Set();
- this.dispatchEventToListeners(SDK.NetworkLog.Events.Reset);
+ this.dispatchEventToListeners(Events.Reset);
// Preserve requests from the new session.
let currentPageLoad = null;
const requestsToAdd = [];
for (const request of oldManagerRequests) {
- if (request.loaderId !== mainFrame.loaderId)
+ if (request.loaderId !== mainFrame.loaderId) {
continue;
+ }
if (!currentPageLoad) {
- currentPageLoad = new SDK.NetworkLog.PageLoad(request);
+ currentPageLoad = new PageLoad(request);
let redirectSource = request.redirectSource();
while (redirectSource) {
requestsToAdd.push(redirectSource);
@@ -326,14 +338,16 @@ SDK.NetworkLog = class extends Common.Object {
// Preserve service worker requests from the new session.
const serviceWorkerRequestsToAdd = [];
for (const swRequest of oldRequests) {
- if (!swRequest.initiatedByServiceWorker())
+ if (!swRequest.initiatedByServiceWorker()) {
continue;
+ }
// If there is a matching request that came before this one, keep it.
const keepRequest = requestsToAdd.some(
request => request.url() === swRequest.url() && request.issueTime() <= swRequest.issueTime());
- if (keepRequest)
+ if (keepRequest) {
serviceWorkerRequestsToAdd.push(swRequest);
+ }
}
requestsToAdd.push(...serviceWorkerRequestsToAdd);
@@ -342,19 +356,20 @@ SDK.NetworkLog = class extends Common.Object {
this._requests.push(request);
this._requestsSet.add(request);
currentPageLoad.bindRequest(request);
- this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request);
+ this.dispatchEventToListeners(Events.RequestAdded, request);
}
if (Common.moduleSetting('network_log.preserve-log').get()) {
for (const request of oldRequestsSet) {
this._requests.push(request);
this._requestsSet.add(request);
- this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request);
+ this.dispatchEventToListeners(Events.RequestAdded, request);
}
}
- if (currentPageLoad)
+ if (currentPageLoad) {
this._pageLoadForManager.set(manager, currentPageLoad);
+ }
}
/**
@@ -367,7 +382,7 @@ SDK.NetworkLog = class extends Common.Object {
for (const request of requests) {
this._requests.push(request);
this._requestsSet.add(request);
- this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request);
+ this.dispatchEventToListeners(Events.RequestAdded, request);
}
}
@@ -380,9 +395,10 @@ SDK.NetworkLog = class extends Common.Object {
this._requestsSet.add(request);
const manager = SDK.NetworkManager.forRequest(request);
const pageLoad = manager ? this._pageLoadForManager.get(manager) : null;
- if (pageLoad)
+ if (pageLoad) {
pageLoad.bindRequest(request);
- this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestAdded, request);
+ }
+ this.dispatchEventToListeners(Events.RequestAdded, request);
}
/**
@@ -390,9 +406,10 @@ SDK.NetworkLog = class extends Common.Object {
*/
_onRequestUpdated(event) {
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
- if (!this._requestsSet.has(request))
+ if (!this._requestsSet.has(request)) {
return;
- this.dispatchEventToListeners(SDK.NetworkLog.Events.RequestUpdated, request);
+ }
+ this.dispatchEventToListeners(Events.RequestUpdated, request);
}
/**
@@ -400,7 +417,7 @@ SDK.NetworkLog = class extends Common.Object {
*/
_onRequestRedirect(event) {
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
- delete request[SDK.NetworkLog._initiatorDataSymbol];
+ delete request[_initiatorDataSymbol];
}
/**
@@ -410,8 +427,9 @@ SDK.NetworkLog = class extends Common.Object {
_onDOMContentLoaded(resourceTreeModel, event) {
const networkManager = resourceTreeModel.target().model(SDK.NetworkManager);
const pageLoad = networkManager ? this._pageLoadForManager.get(networkManager) : null;
- if (pageLoad)
+ if (pageLoad) {
pageLoad.contentLoadTime = /** @type {number} */ (event.data);
+ }
}
/**
@@ -420,8 +438,9 @@ SDK.NetworkLog = class extends Common.Object {
_onLoad(event) {
const networkManager = event.data.resourceTreeModel.target().model(SDK.NetworkManager);
const pageLoad = networkManager ? this._pageLoadForManager.get(networkManager) : null;
- if (pageLoad)
+ if (pageLoad) {
pageLoad.loadTime = /** @type {number} */ (event.data.loadTime);
+ }
}
reset() {
@@ -429,11 +448,12 @@ SDK.NetworkLog = class extends Common.Object {
this._requestsSet.clear();
const managers = new Set(SDK.targetManager.models(SDK.NetworkManager));
for (const manager of this._pageLoadForManager.keys()) {
- if (!managers.has(manager))
+ if (!managers.has(manager)) {
this._pageLoadForManager.delete(manager);
+ }
}
- this.dispatchEventToListeners(SDK.NetworkLog.Events.Reset);
+ this.dispatchEventToListeners(Events.Reset);
}
/**
@@ -457,12 +477,14 @@ SDK.NetworkLog = class extends Common.Object {
associateConsoleMessageWithRequest(consoleMessage, requestId) {
const target = consoleMessage.target();
const networkManager = target ? target.model(SDK.NetworkManager) : null;
- if (!networkManager)
+ if (!networkManager) {
return;
+ }
const request = this.requestByManagerAndId(networkManager, requestId);
- if (!request)
+ if (!request) {
return;
- consoleMessage[SDK.NetworkLog._requestSymbol] = request;
+ }
+ consoleMessage[_requestSymbol] = request;
const initiator = request.initiator();
if (initiator) {
consoleMessage.stackTrace = initiator.stack || undefined;
@@ -478,16 +500,16 @@ SDK.NetworkLog = class extends Common.Object {
* @return {?SDK.NetworkRequest}
*/
static requestForConsoleMessage(consoleMessage) {
- return consoleMessage[SDK.NetworkLog._requestSymbol] || null;
+ return consoleMessage[_requestSymbol] || null;
}
-};
+}
-SDK.NetworkLog.PageLoad = class {
+export class PageLoad {
/**
* @param {!SDK.NetworkRequest} mainRequest
*/
constructor(mainRequest) {
- this.id = ++SDK.NetworkLog.PageLoad._lastIdentifier;
+ this.id = ++PageLoad._lastIdentifier;
this.url = mainRequest.url();
this.startTime = mainRequest.startTime;
/** @type {number} */
@@ -501,58 +523,77 @@ SDK.NetworkLog.PageLoad = class {
async _showDataSaverWarningIfNeeded() {
const manager = SDK.NetworkManager.forRequest(this.mainRequest);
- if (!manager)
+ if (!manager) {
return;
- if (!this.mainRequest.finished)
+ }
+ if (!this.mainRequest.finished) {
await this.mainRequest.once(SDK.NetworkRequest.Events.FinishedLoading);
+ }
const saveDataHeader = this.mainRequest.requestHeaderValue('Save-Data');
- if (!SDK.NetworkLog.PageLoad._dataSaverMessageWasShown && saveDataHeader && saveDataHeader === 'on') {
+ if (!PageLoad._dataSaverMessageWasShown && saveDataHeader && saveDataHeader === 'on') {
const message = Common.UIString(
'Consider disabling %s while debugging. For more info see: %s', Common.UIString('Chrome Data Saver'),
'https://support.google.com/chrome/?p=datasaver');
manager.dispatchEventToListeners(
SDK.NetworkManager.Events.MessageGenerated,
{message: message, requestId: this.mainRequest.requestId(), warning: true});
- SDK.NetworkLog.PageLoad._dataSaverMessageWasShown = true;
+ PageLoad._dataSaverMessageWasShown = true;
}
}
/**
* @param {!SDK.NetworkRequest} request
- * @return {?SDK.NetworkLog.PageLoad}
+ * @return {?PageLoad}
*/
static forRequest(request) {
- return request[SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol] || null;
+ return request[PageLoad._pageLoadForRequestSymbol] || null;
}
/**
* @param {!SDK.NetworkRequest} request
*/
bindRequest(request) {
- request[SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol] = this;
+ request[PageLoad._pageLoadForRequestSymbol] = this;
}
-};
+}
-SDK.NetworkLog.PageLoad._lastIdentifier = 0;
-SDK.NetworkLog.PageLoad._pageLoadForRequestSymbol = Symbol('PageLoadForRequest');
-SDK.NetworkLog._requestSymbol = Symbol('_request');
+PageLoad._lastIdentifier = 0;
+PageLoad._pageLoadForRequestSymbol = Symbol('PageLoadForRequest');
+PageLoad._dataSaverMessageWasShown = false;
-SDK.NetworkLog.PageLoad._dataSaverMessageWasShown = false;
+export const _requestSymbol = Symbol('_request');
-/** @typedef {!{initiators: !Set<!SDK.NetworkRequest>, initiated: !Set<!SDK.NetworkRequest>}} */
-SDK.NetworkLog.InitiatorGraph;
-
-SDK.NetworkLog.Events = {
+export const Events = {
Reset: Symbol('Reset'),
RequestAdded: Symbol('RequestAdded'),
RequestUpdated: Symbol('RequestUpdated')
};
-/** @typedef {!{type: !SDK.NetworkRequest.InitiatorType, url: string, lineNumber: number, columnNumber: number, scriptId: ?string, stack: ?Protocol.Runtime.StackTrace}} */
-SDK.NetworkLog._InitiatorInfo;
+export const _initiatorDataSymbol = Symbol('InitiatorData');
+export const _events = Symbol('SDK.NetworkLog.events');
-SDK.NetworkLog._initiatorDataSymbol = Symbol('InitiatorData');
-SDK.NetworkLog._events = Symbol('SDK.NetworkLog.events');
+/* Legacy exported object */
+self.SDK = self.SDK || {};
-/** @type {!SDK.NetworkLog} */
-SDK.networkLog = new SDK.NetworkLog();
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.NetworkLog = NetworkLog;
+
+/** @constructor */
+SDK.NetworkLog.PageLoad = PageLoad;
+
+SDK.NetworkLog._requestSymbol = _requestSymbol;
+SDK.NetworkLog.Events = Events;
+SDK.NetworkLog._initiatorDataSymbol = _initiatorDataSymbol;
+SDK.NetworkLog._events = _events;
+
+/** @type {!NetworkLog} */
+SDK.networkLog = new NetworkLog();
+
+/** @typedef {!{initiators: !Set<!SDK.NetworkRequest>, initiated: !Set<!SDK.NetworkRequest>}} */
+SDK.NetworkLog.InitiatorGraph;
+
+/** @typedef {!{type: !SDK.NetworkRequest.InitiatorType, url: string, lineNumber: number, columnNumber: number, scriptId: ?string, stack: ?Protocol.Runtime.StackTrace}} */
+SDK.NetworkLog._InitiatorInfo;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
index 16f1d666c7d..7580ef22e12 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
@@ -31,23 +31,25 @@
/**
* @unrestricted
*/
-SDK.NetworkManager = class extends SDK.SDKModel {
+export default class NetworkManager extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
- this._dispatcher = new SDK.NetworkDispatcher(this);
+ this._dispatcher = new NetworkDispatcher(this);
this._networkAgent = target.networkAgent();
target.registerNetworkDispatcher(this._dispatcher);
- if (Common.moduleSetting('cacheDisabled').get())
+ if (Common.moduleSetting('cacheDisabled').get()) {
this._networkAgent.setCacheDisabled(true);
+ }
- this._networkAgent.enable(undefined, undefined, SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH);
+ this._networkAgent.enable(undefined, undefined, MAX_EAGER_POST_REQUEST_BODY_LENGTH);
this._bypassServiceWorkerSetting = Common.settings.createSetting('bypassServiceWorker', false);
- if (this._bypassServiceWorkerSetting.get())
+ if (this._bypassServiceWorkerSetting.get()) {
this._bypassServiceWorkerChanged();
+ }
this._bypassServiceWorkerSetting.addChangeListener(this._bypassServiceWorkerChanged, this);
Common.moduleSetting('cacheDisabled').addChangeListener(this._cacheDisabledSettingChanged, this);
@@ -55,10 +57,10 @@ SDK.NetworkManager = class extends SDK.SDKModel {
/**
* @param {!SDK.NetworkRequest} request
- * @return {?SDK.NetworkManager}
+ * @return {?NetworkManager}
*/
static forRequest(request) {
- return request[SDK.NetworkManager._networkManagerForRequestSymbol];
+ return request[_networkManagerForRequestSymbol];
}
/**
@@ -66,17 +68,17 @@ SDK.NetworkManager = class extends SDK.SDKModel {
* @return {boolean}
*/
static canReplayRequest(request) {
- return !!request[SDK.NetworkManager._networkManagerForRequestSymbol] &&
- request.resourceType() === Common.resourceTypes.XHR;
+ return !!request[_networkManagerForRequestSymbol] && request.resourceType() === Common.resourceTypes.XHR;
}
/**
* @param {!SDK.NetworkRequest} request
*/
static replayRequest(request) {
- const manager = request[SDK.NetworkManager._networkManagerForRequestSymbol];
- if (!manager)
+ const manager = request[_networkManagerForRequestSymbol];
+ if (!manager) {
return;
+ }
manager._networkAgent.replayXHR(request.requestId());
}
@@ -88,9 +90,10 @@ SDK.NetworkManager = class extends SDK.SDKModel {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
static async searchInRequest(request, query, caseSensitive, isRegex) {
- const manager = SDK.NetworkManager.forRequest(request);
- if (!manager)
+ const manager = NetworkManager.forRequest(request);
+ if (!manager) {
return [];
+ }
const response = await manager._networkAgent.invoke_searchInResponseBody(
{requestId: request.requestId(), query: query, caseSensitive: caseSensitive, isRegex: isRegex});
return response.result || [];
@@ -101,13 +104,16 @@ SDK.NetworkManager = class extends SDK.SDKModel {
* @return {!Promise<!SDK.NetworkRequest.ContentData>}
*/
static async requestContentData(request) {
- if (request.resourceType() === Common.resourceTypes.WebSocket)
+ if (request.resourceType() === Common.resourceTypes.WebSocket) {
return {error: 'Content for WebSockets is currently not supported', content: null, encoded: false};
- if (!request.finished)
+ }
+ if (!request.finished) {
await request.once(SDK.NetworkRequest.Events.FinishedLoading);
- const manager = SDK.NetworkManager.forRequest(request);
- if (!manager)
+ }
+ const manager = NetworkManager.forRequest(request);
+ if (!manager) {
return {error: 'No network manager for request', content: null, encoded: false};
+ }
const response = await manager._networkAgent.invoke_getResponseBody({requestId: request.requestId()});
const error = response[Protocol.Error] || null;
return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
@@ -118,9 +124,10 @@ SDK.NetworkManager = class extends SDK.SDKModel {
* @return {!Promise<?string>}
*/
static requestPostData(request) {
- const manager = SDK.NetworkManager.forRequest(request);
- if (manager)
+ const manager = NetworkManager.forRequest(request);
+ if (manager) {
return manager._networkAgent.getRequestPostData(request.backendRequestId());
+ }
console.error('No network manager for request');
return /** @type {!Promise<?string>} */ (Promise.resolve(null));
}
@@ -131,12 +138,13 @@ SDK.NetworkManager = class extends SDK.SDKModel {
* TODO(allada): this belongs to NetworkConditionsSelector, which should hardcode/guess it.
*/
static _connectionType(conditions) {
- if (!conditions.download && !conditions.upload)
+ if (!conditions.download && !conditions.upload) {
return Protocol.Network.ConnectionType.None;
- let types = SDK.NetworkManager._connectionTypes;
+ }
+ let types = NetworkManager._connectionTypes;
if (!types) {
- SDK.NetworkManager._connectionTypes = [];
- types = SDK.NetworkManager._connectionTypes;
+ NetworkManager._connectionTypes = [];
+ types = NetworkManager._connectionTypes;
types.push(['2g', Protocol.Network.ConnectionType.Cellular2g]);
types.push(['3g', Protocol.Network.ConnectionType.Cellular3g]);
types.push(['4g', Protocol.Network.ConnectionType.Cellular4g]);
@@ -145,8 +153,9 @@ SDK.NetworkManager = class extends SDK.SDKModel {
types.push(['wimax', Protocol.Network.ConnectionType.Wimax]);
}
for (const type of types) {
- if (conditions.title.toLowerCase().indexOf(type[0]) !== -1)
+ if (conditions.title.toLowerCase().indexOf(type[0]) !== -1) {
return type[1];
+ }
}
return Protocol.Network.ConnectionType.Other;
}
@@ -157,8 +166,9 @@ SDK.NetworkManager = class extends SDK.SDKModel {
*/
static lowercaseHeaders(headers) {
const newHeaders = {};
- for (const headerName in headers)
+ for (const headerName in headers) {
newHeaders[headerName.toLowerCase()] = headers[headerName];
+ }
return newHeaders;
}
@@ -188,12 +198,10 @@ SDK.NetworkManager = class extends SDK.SDKModel {
_bypassServiceWorkerChanged() {
this._networkAgent.setBypassServiceWorker(this._bypassServiceWorkerSetting.get());
}
-};
-
-SDK.SDKModel.register(SDK.NetworkManager, SDK.Target.Capability.Network, true);
+}
/** @enum {symbol} */
-SDK.NetworkManager.Events = {
+export const Events = {
RequestStarted: Symbol('RequestStarted'),
RequestUpdated: Symbol('RequestUpdated'),
RequestFinished: Symbol('RequestFinished'),
@@ -203,10 +211,7 @@ SDK.NetworkManager.Events = {
RequestRedirected: Symbol('RequestRedirected'),
};
-/** @typedef {{message: string, requestId: string, warning: boolean}} */
-SDK.NetworkManager.Message;
-
-SDK.NetworkManager._MIMETypes = {
+export const _MIMETypes = {
'text/html': {'document': true},
'text/xml': {'document': true},
'text/plain': {'document': true},
@@ -217,18 +222,8 @@ SDK.NetworkManager._MIMETypes = {
'text/vtt': {'texttrack': true},
};
-/**
- * @typedef {{
- * download: number,
- * upload: number,
- * latency: number,
- * title: string,
- * }}
- **/
-SDK.NetworkManager.Conditions;
-
/** @type {!SDK.NetworkManager.Conditions} */
-SDK.NetworkManager.NoThrottlingConditions = {
+export const NoThrottlingConditions = {
title: ls`Online`,
download: -1,
upload: -1,
@@ -236,7 +231,7 @@ SDK.NetworkManager.NoThrottlingConditions = {
};
/** @type {!SDK.NetworkManager.Conditions} */
-SDK.NetworkManager.OfflineConditions = {
+export const OfflineConditions = {
title: Common.UIString('Offline'),
download: 0,
upload: 0,
@@ -244,7 +239,7 @@ SDK.NetworkManager.OfflineConditions = {
};
/** @type {!SDK.NetworkManager.Conditions} */
-SDK.NetworkManager.Slow3GConditions = {
+export const Slow3GConditions = {
title: Common.UIString('Slow 3G'),
download: 500 * 1024 / 8 * .8,
upload: 500 * 1024 / 8 * .8,
@@ -252,27 +247,23 @@ SDK.NetworkManager.Slow3GConditions = {
};
/** @type {!SDK.NetworkManager.Conditions} */
-SDK.NetworkManager.Fast3GConditions = {
+export const Fast3GConditions = {
title: Common.UIString('Fast 3G'),
download: 1.6 * 1024 * 1024 / 8 * .9,
upload: 750 * 1024 / 8 * .9,
latency: 150 * 3.75,
};
-/** @typedef {{url: string, enabled: boolean}} */
-SDK.NetworkManager.BlockedPattern;
-
-SDK.NetworkManager._networkManagerForRequestSymbol = Symbol('NetworkManager');
-
-SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH = 64 * 1024; // bytes
+export const _networkManagerForRequestSymbol = Symbol('NetworkManager');
+export const MAX_EAGER_POST_REQUEST_BODY_LENGTH = 64 * 1024; // bytes
/**
* @implements {Protocol.NetworkDispatcher}
* @unrestricted
*/
-SDK.NetworkDispatcher = class {
+export class NetworkDispatcher {
/**
- * @param {!SDK.NetworkManager} manager
+ * @param {!NetworkManager} manager
*/
constructor(manager) {
this._manager = manager;
@@ -292,8 +283,9 @@ SDK.NetworkDispatcher = class {
const result = [];
for (const name in headersMap) {
const values = headersMap[name].split('\n');
- for (let i = 0; i < values.length; ++i)
+ for (let i = 0; i < values.length; ++i) {
result.push({name: name, value: values[i]});
+ }
}
return result;
}
@@ -316,20 +308,23 @@ SDK.NetworkDispatcher = class {
* @param {!Protocol.Network.Response=} response
*/
_updateNetworkRequestWithResponse(networkRequest, response) {
- if (response.url && networkRequest.url() !== response.url)
+ if (response.url && networkRequest.url() !== response.url) {
networkRequest.setUrl(response.url);
+ }
networkRequest.mimeType = response.mimeType;
networkRequest.statusCode = response.status;
networkRequest.statusText = response.statusText;
- if (!networkRequest.hasExtraResponseInfo())
+ if (!networkRequest.hasExtraResponseInfo()) {
networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers);
+ }
- if (response.encodedDataLength >= 0)
+ if (response.encodedDataLength >= 0) {
networkRequest.setTransferSize(response.encodedDataLength);
+ }
if (response.requestHeaders && !networkRequest.hasExtraRequestInfo()) {
- // TODO(http://crbug.com/991471): Stop using response.requestHeaders and
- // response.requestHeadersText once service workers and shared workers
+ // TODO(http://crbug.com/1004979): Stop using response.requestHeaders and
+ // response.requestHeadersText once shared workers
// emit Network.*ExtraInfo events for their network requests.
networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
networkRequest.setRequestHeadersText(response.requestHeadersText || '');
@@ -337,21 +332,25 @@ SDK.NetworkDispatcher = class {
networkRequest.connectionReused = response.connectionReused;
networkRequest.connectionId = String(response.connectionId);
- if (response.remoteIPAddress)
+ if (response.remoteIPAddress) {
networkRequest.setRemoteAddress(response.remoteIPAddress, response.remotePort || -1);
+ }
- if (response.fromServiceWorker)
+ if (response.fromServiceWorker) {
networkRequest.fetchedViaServiceWorker = true;
+ }
- if (response.fromDiskCache)
+ if (response.fromDiskCache) {
networkRequest.setFromDiskCache();
+ }
- if (response.fromPrefetchCache)
+ if (response.fromPrefetchCache) {
networkRequest.setFromPrefetchCache();
+ }
networkRequest.timing = response.timing;
- networkRequest.protocol = response.protocol;
+ networkRequest.protocol = response.protocol || '';
networkRequest.setSecurityState(response.securityState);
@@ -360,12 +359,12 @@ SDK.NetworkDispatcher = class {
'Resource interpreted as %s but transferred with MIME type %s: "%s".', networkRequest.resourceType().title(),
networkRequest.mimeType, networkRequest.url());
this._manager.dispatchEventToListeners(
- SDK.NetworkManager.Events.MessageGenerated,
- {message: message, requestId: networkRequest.requestId(), warning: true});
+ Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: true});
}
- if (response.securityDetails)
+ if (response.securityDetails) {
networkRequest.setSecurityDetails(response.securityDetails);
+ }
}
/**
@@ -379,20 +378,24 @@ SDK.NetworkDispatcher = class {
// Also, if a URL like http://localhost/wiki/load.php?debug=true&lang=en produces text/css and gets reloaded,
// it is 304 Not Modified and its guessed mime-type is text/php, which is wrong.
// Don't check for mime-types in 304-resources.
- if (networkRequest.hasErrorStatusCode() || networkRequest.statusCode === 304 || networkRequest.statusCode === 204)
+ if (networkRequest.hasErrorStatusCode() || networkRequest.statusCode === 304 || networkRequest.statusCode === 204) {
return true;
+ }
const resourceType = networkRequest.resourceType();
if (resourceType !== Common.resourceTypes.Stylesheet && resourceType !== Common.resourceTypes.Document &&
- resourceType !== Common.resourceTypes.TextTrack)
+ resourceType !== Common.resourceTypes.TextTrack) {
return true;
+ }
- if (!networkRequest.mimeType)
- return true; // Might be not known for cached resources with null responses.
+ if (!networkRequest.mimeType) {
+ return true;
+ } // Might be not known for cached resources with null responses.
- if (networkRequest.mimeType in SDK.NetworkManager._MIMETypes)
- return resourceType.name() in SDK.NetworkManager._MIMETypes[networkRequest.mimeType];
+ if (networkRequest.mimeType in _MIMETypes) {
+ return resourceType.name() in _MIMETypes[networkRequest.mimeType];
+ }
return false;
}
@@ -405,8 +408,9 @@ SDK.NetworkDispatcher = class {
*/
resourceChangedPriority(requestId, newPriority, timestamp) {
const networkRequest = this._inflightRequestsById[requestId];
- if (networkRequest)
+ if (networkRequest) {
networkRequest.setPriority(newPriority);
+ }
}
/**
@@ -432,15 +436,16 @@ SDK.NetworkDispatcher = class {
// process and DevTools to find the matching request.
if (!networkRequest) {
networkRequest = this._inflightRequestsByURL[info.outerResponse.url];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
}
networkRequest.setSignedExchangeInfo(info);
networkRequest.setResourceType(Common.resourceTypes.SignedExchange);
this._updateNetworkRequestWithResponse(networkRequest, info.outerResponse);
this._updateNetworkRequest(networkRequest);
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.ResponseReceived, networkRequest);
+ this._manager.dispatchEventToListeners(Events.ResponseReceived, networkRequest);
}
/**
@@ -461,8 +466,9 @@ SDK.NetworkDispatcher = class {
let networkRequest = this._inflightRequestsById[requestId];
if (networkRequest) {
// FIXME: move this check to the backend.
- if (!redirectResponse)
+ if (!redirectResponse) {
return;
+ }
// If signedExchangeReceived event has already been sent for the request,
// ignores the internally generated |redirectResponse|. The
// |outerResponse| of SignedExchangeInfo was set to |networkRequest| in
@@ -472,7 +478,7 @@ SDK.NetworkDispatcher = class {
requestId, loaderId, time, Protocol.Network.ResourceType.Other, redirectResponse, frameId);
}
networkRequest = this._appendRedirect(requestId, time, request.url);
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestRedirected, networkRequest);
+ this._manager.dispatchEventToListeners(Events.RequestRedirected, networkRequest);
} else {
networkRequest =
this._createNetworkRequest(requestId, frameId || '', loaderId, request.url, documentURL, initiator);
@@ -494,8 +500,9 @@ SDK.NetworkDispatcher = class {
*/
requestServedFromCache(requestId) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.setFromMemoryCache();
}
@@ -511,7 +518,7 @@ SDK.NetworkDispatcher = class {
*/
responseReceived(requestId, loaderId, time, resourceType, response, frameId) {
const networkRequest = this._inflightRequestsById[requestId];
- const lowercaseHeaders = SDK.NetworkManager.lowercaseHeaders(response.headers);
+ const lowercaseHeaders = NetworkManager.lowercaseHeaders(response.headers);
if (!networkRequest) {
// We missed the requestWillBeSent.
const eventData = {};
@@ -522,7 +529,7 @@ SDK.NetworkDispatcher = class {
eventData.mimeType = response.mimeType;
const lastModifiedHeader = lowercaseHeaders['last-modified'];
eventData.lastModified = lastModifiedHeader ? new Date(lastModifiedHeader) : null;
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestUpdateDropped, eventData);
+ this._manager.dispatchEventToListeners(Events.RequestUpdateDropped, eventData);
return;
}
@@ -533,20 +540,21 @@ SDK.NetworkDispatcher = class {
if ('set-cookie' in lowercaseHeaders && lowercaseHeaders['set-cookie'].length > 4096) {
const values = lowercaseHeaders['set-cookie'].split('\n');
for (let i = 0; i < values.length; ++i) {
- if (values[i].length <= 4096)
+ if (values[i].length <= 4096) {
continue;
+ }
const message = Common.UIString(
'Set-Cookie header is ignored in response from url: %s. Cookie length should be less than or equal to 4096 characters.',
response.url);
this._manager.dispatchEventToListeners(
- SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
+ Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
}
}
this._updateNetworkRequestWithResponse(networkRequest, response);
this._updateNetworkRequest(networkRequest);
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.ResponseReceived, networkRequest);
+ this._manager.dispatchEventToListeners(Events.ResponseReceived, networkRequest);
}
/**
@@ -558,14 +566,17 @@ SDK.NetworkDispatcher = class {
*/
dataReceived(requestId, time, dataLength, encodedDataLength) {
let networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
networkRequest = this._maybeAdoptMainResourceRequest(requestId);
- if (!networkRequest)
+ }
+ if (!networkRequest) {
return;
+ }
networkRequest.resourceSize += dataLength;
- if (encodedDataLength !== -1)
+ if (encodedDataLength !== -1) {
networkRequest.increaseTransferSize(encodedDataLength);
+ }
networkRequest.endTime = time;
this._updateNetworkRequest(networkRequest);
@@ -580,10 +591,12 @@ SDK.NetworkDispatcher = class {
*/
loadingFinished(requestId, finishTime, encodedDataLength, shouldReportCorbBlocking) {
let networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
networkRequest = this._maybeAdoptMainResourceRequest(requestId);
- if (!networkRequest)
+ }
+ if (!networkRequest) {
return;
+ }
this._getExtraInfoBuilder(requestId).finished();
this._finishNetworkRequest(networkRequest, finishTime, encodedDataLength, shouldReportCorbBlocking);
}
@@ -599,8 +612,9 @@ SDK.NetworkDispatcher = class {
*/
loadingFailed(requestId, time, resourceType, localizedDescription, canceled, blockedReason) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.failed = true;
networkRequest.setResourceType(Common.resourceTypes[resourceType]);
@@ -610,7 +624,7 @@ SDK.NetworkDispatcher = class {
if (blockedReason === Protocol.Network.BlockedReason.Inspector) {
const message = Common.UIString('Request was blocked by DevTools: "%s".', networkRequest.url());
this._manager.dispatchEventToListeners(
- SDK.NetworkManager.Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
+ Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
}
}
networkRequest.localizedFailDescription = localizedDescription;
@@ -626,7 +640,7 @@ SDK.NetworkDispatcher = class {
*/
webSocketCreated(requestId, requestURL, initiator) {
const networkRequest = new SDK.NetworkRequest(requestId, requestURL, '', '', '', initiator || null);
- networkRequest[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager;
+ networkRequest[_networkManagerForRequestSymbol] = this._manager;
networkRequest.setResourceType(Common.resourceTypes.WebSocket);
this._startNetworkRequest(networkRequest);
}
@@ -640,8 +654,9 @@ SDK.NetworkDispatcher = class {
*/
webSocketWillSendHandshakeRequest(requestId, time, wallTime, request) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.requestMethod = 'GET';
networkRequest.setRequestHeaders(this._headersMapToHeadersArray(request.headers));
@@ -658,17 +673,20 @@ SDK.NetworkDispatcher = class {
*/
webSocketHandshakeResponseReceived(requestId, time, response) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.statusCode = response.status;
networkRequest.statusText = response.statusText;
networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers);
networkRequest.responseHeadersText = response.headersText || '';
- if (response.requestHeaders)
+ if (response.requestHeaders) {
networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
- if (response.requestHeadersText)
+ }
+ if (response.requestHeadersText) {
networkRequest.setRequestHeadersText(response.requestHeadersText);
+ }
networkRequest.responseReceivedTime = time;
networkRequest.protocol = 'websocket';
@@ -683,8 +701,9 @@ SDK.NetworkDispatcher = class {
*/
webSocketFrameReceived(requestId, time, response) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.addProtocolFrame(response, time, false);
networkRequest.responseReceivedTime = time;
@@ -700,8 +719,9 @@ SDK.NetworkDispatcher = class {
*/
webSocketFrameSent(requestId, time, response) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.addProtocolFrame(response, time, true);
networkRequest.responseReceivedTime = time;
@@ -717,8 +737,9 @@ SDK.NetworkDispatcher = class {
*/
webSocketFrameError(requestId, time, errorMessage) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.addProtocolFrameError(errorMessage, time);
networkRequest.responseReceivedTime = time;
@@ -733,8 +754,9 @@ SDK.NetworkDispatcher = class {
*/
webSocketClosed(requestId, time) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
this._finishNetworkRequest(networkRequest, time, -1);
}
@@ -748,8 +770,9 @@ SDK.NetworkDispatcher = class {
*/
eventSourceMessageReceived(requestId, time, eventName, eventId, data) {
const networkRequest = this._inflightRequestsById[requestId];
- if (!networkRequest)
+ if (!networkRequest) {
return;
+ }
networkRequest.addEventSourceMessage(time, eventName, eventId, data);
}
@@ -771,7 +794,7 @@ SDK.NetworkDispatcher = class {
requestIntercepted(
interceptionId, request, frameId, resourceType, isNavigationRequest, isDownload, redirectUrl, authChallenge,
responseErrorReason, responseStatusCode, responseHeaders, requestId) {
- SDK.multitargetNetworkManager._requestIntercepted(new SDK.MultitargetNetworkManager.InterceptedRequest(
+ SDK.multitargetNetworkManager._requestIntercepted(new InterceptedRequest(
this._manager.target().networkAgent(), interceptionId, request, frameId, resourceType, isNavigationRequest,
isDownload, redirectUrl, authChallenge, responseErrorReason, responseStatusCode, responseHeaders, requestId));
}
@@ -785,7 +808,12 @@ SDK.NetworkDispatcher = class {
requestWillBeSentExtraInfo(requestId, blockedCookies, headers) {
/** @type {!SDK.NetworkRequest.ExtraRequestInfo} */
const extraRequestInfo = {
- blockedRequestCookies: blockedCookies,
+ blockedRequestCookies: blockedCookies.map(blockedCookie => {
+ return {
+ blockedReasons: blockedCookie.blockedReasons,
+ cookie: SDK.Cookie.fromProtocolCookie(blockedCookie.cookie)
+ };
+ }),
requestHeaders: this._headersMapToHeadersArray(headers)
};
this._getExtraInfoBuilder(requestId).addRequestExtraInfo(extraRequestInfo);
@@ -801,7 +829,13 @@ SDK.NetworkDispatcher = class {
responseReceivedExtraInfo(requestId, blockedCookies, headers, headersText) {
/** @type {!SDK.NetworkRequest.ExtraResponseInfo} */
const extraResponseInfo = {
- blockedResponseCookies: blockedCookies,
+ blockedResponseCookies: blockedCookies.map(blockedCookie => {
+ return {
+ blockedReasons: blockedCookie.blockedReasons,
+ cookieLine: blockedCookie.cookieLine,
+ cookie: blockedCookie.cookie ? SDK.Cookie.fromProtocolCookie(blockedCookie.cookie) : null
+ };
+ }),
responseHeaders: this._headersMapToHeadersArray(headers),
responseHeadersText: headersText
};
@@ -831,8 +865,9 @@ SDK.NetworkDispatcher = class {
_appendRedirect(requestId, time, redirectURL) {
const originalNetworkRequest = this._inflightRequestsById[requestId];
let redirectCount = 0;
- for (let redirect = originalNetworkRequest.redirectSource(); redirect; redirect = redirect.redirectSource())
+ for (let redirect = originalNetworkRequest.redirectSource(); redirect; redirect = redirect.redirectSource()) {
redirectCount++;
+ }
originalNetworkRequest.markAsRedirect(redirectCount);
this._finishNetworkRequest(originalNetworkRequest, time, -1);
@@ -850,14 +885,15 @@ SDK.NetworkDispatcher = class {
*/
_maybeAdoptMainResourceRequest(requestId) {
const request = SDK.multitargetNetworkManager._inflightMainResourceRequests.get(requestId);
- if (!request)
+ if (!request) {
return null;
- const oldDispatcher = SDK.NetworkManager.forRequest(request)._dispatcher;
+ }
+ const oldDispatcher = NetworkManager.forRequest(request)._dispatcher;
delete oldDispatcher._inflightRequestsById[requestId];
delete oldDispatcher._inflightRequestsByURL[request.url()];
this._inflightRequestsById[requestId] = request;
this._inflightRequestsByURL[request.url()] = request;
- request[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager;
+ request[_networkManagerForRequestSymbol] = this._manager;
return request;
}
@@ -869,17 +905,18 @@ SDK.NetworkDispatcher = class {
this._inflightRequestsByURL[networkRequest.url()] = networkRequest;
// The following relies on the fact that loaderIds and requestIds are
// globally unique and that the main request has them equal.
- if (networkRequest.loaderId === networkRequest.requestId())
+ if (networkRequest.loaderId === networkRequest.requestId()) {
SDK.multitargetNetworkManager._inflightMainResourceRequests.set(networkRequest.requestId(), networkRequest);
+ }
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestStarted, networkRequest);
+ this._manager.dispatchEventToListeners(Events.RequestStarted, networkRequest);
}
/**
* @param {!SDK.NetworkRequest} networkRequest
*/
_updateNetworkRequest(networkRequest) {
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestUpdated, networkRequest);
+ this._manager.dispatchEventToListeners(Events.RequestUpdated, networkRequest);
}
/**
@@ -901,7 +938,7 @@ SDK.NetworkDispatcher = class {
networkRequest.setTransferSize(encodedDataLength);
}
}
- this._manager.dispatchEventToListeners(SDK.NetworkManager.Events.RequestFinished, networkRequest);
+ this._manager.dispatchEventToListeners(Events.RequestFinished, networkRequest);
delete this._inflightRequestsById[networkRequest.requestId()];
delete this._inflightRequestsByURL[networkRequest.url()];
SDK.multitargetNetworkManager._inflightMainResourceRequests.delete(networkRequest.requestId());
@@ -911,8 +948,7 @@ SDK.NetworkDispatcher = class {
`Cross-Origin Read Blocking (CORB) blocked cross-origin response %s with MIME type %s. See https://www.chromestatus.com/feature/5629709824032768 for more details.`,
networkRequest.url(), networkRequest.mimeType);
this._manager.dispatchEventToListeners(
- SDK.NetworkManager.Events.MessageGenerated,
- {message: message, requestId: networkRequest.requestId(), warning: true});
+ Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: true});
}
if (Common.moduleSetting('monitoringXHREnabled').get() &&
@@ -930,8 +966,7 @@ SDK.NetworkDispatcher = class {
}
this._manager.dispatchEventToListeners(
- SDK.NetworkManager.Events.MessageGenerated,
- {message: message, requestId: networkRequest.requestId(), warning: false});
+ Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: false});
}
}
@@ -945,16 +980,16 @@ SDK.NetworkDispatcher = class {
*/
_createNetworkRequest(requestId, frameId, loaderId, url, documentURL, initiator) {
const request = new SDK.NetworkRequest(requestId, url, documentURL, frameId, loaderId, initiator);
- request[SDK.NetworkManager._networkManagerForRequestSymbol] = this._manager;
+ request[_networkManagerForRequestSymbol] = this._manager;
return request;
}
-};
+}
/**
- * @implements {SDK.SDKModelObserver<!SDK.NetworkManager>}
+ * @implements {SDK.SDKModelObserver<!NetworkManager>}
* @unrestricted
*/
-SDK.MultitargetNetworkManager = class extends Common.Object {
+export class MultitargetNetworkManager extends Common.Object {
constructor() {
super();
this._userAgentOverride = '';
@@ -963,7 +998,7 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
/** @type {!Map<string, !SDK.NetworkRequest>} */
this._inflightMainResourceRequests = new Map();
/** @type {!SDK.NetworkManager.Conditions} */
- this._networkConditions = SDK.NetworkManager.NoThrottlingConditions;
+ this._networkConditions = NoThrottlingConditions;
/** @type {?Promise} */
this._updatingInterceptionPatternsPromise = null;
@@ -973,10 +1008,10 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
this._effectiveBlockedURLs = [];
this._updateBlockedPatterns();
- /** @type {!Multimap<!SDK.MultitargetNetworkManager.RequestInterceptor, !SDK.MultitargetNetworkManager.InterceptionPattern>} */
- this._urlsForRequestInterceptor = new Multimap();
+ /** @type {!Platform.Multimap<!SDK.MultitargetNetworkManager.RequestInterceptor, !SDK.MultitargetNetworkManager.InterceptionPattern>} */
+ this._urlsForRequestInterceptor = new Platform.Multimap();
- SDK.targetManager.observeModels(SDK.NetworkManager, this);
+ SDK.targetManager.observeModels(NetworkManager, this);
}
/**
@@ -999,32 +1034,38 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
/**
* @override
- * @param {!SDK.NetworkManager} networkManager
+ * @param {!NetworkManager} networkManager
*/
modelAdded(networkManager) {
const networkAgent = networkManager.target().networkAgent();
- if (this._extraHeaders)
+ if (this._extraHeaders) {
networkAgent.setExtraHTTPHeaders(this._extraHeaders);
- if (this._currentUserAgent())
+ }
+ if (this._currentUserAgent()) {
networkAgent.setUserAgentOverride(this._currentUserAgent());
- if (this._effectiveBlockedURLs.length)
+ }
+ if (this._effectiveBlockedURLs.length) {
networkAgent.setBlockedURLs(this._effectiveBlockedURLs);
- if (this.isIntercepting())
+ }
+ if (this.isIntercepting()) {
networkAgent.setRequestInterception(this._urlsForRequestInterceptor.valuesArray());
+ }
this._agents.add(networkAgent);
- if (this.isThrottling())
+ if (this.isThrottling()) {
this._updateNetworkConditions(networkAgent);
+ }
}
/**
* @override
- * @param {!SDK.NetworkManager} networkManager
+ * @param {!NetworkManager} networkManager
*/
modelRemoved(networkManager) {
for (const entry of this._inflightMainResourceRequests) {
- const manager = SDK.NetworkManager.forRequest(/** @type {!SDK.NetworkRequest} */ (entry[1]));
- if (manager !== networkManager)
+ const manager = NetworkManager.forRequest(/** @type {!SDK.NetworkRequest} */ (entry[1]));
+ if (manager !== networkManager) {
continue;
+ }
this._inflightMainResourceRequests.delete(/** @type {string} */ (entry[0]));
}
this._agents.delete(networkManager.target().networkAgent());
@@ -1050,9 +1091,10 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
*/
setNetworkConditions(conditions) {
this._networkConditions = conditions;
- for (const agent of this._agents)
+ for (const agent of this._agents) {
this._updateNetworkConditions(agent);
- this.dispatchEventToListeners(SDK.MultitargetNetworkManager.Events.ConditionsChanged);
+ }
+ this.dispatchEventToListeners(MultitargetNetworkManager.Events.ConditionsChanged);
}
/**
@@ -1072,7 +1114,7 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
} else {
networkAgent.emulateNetworkConditions(
this.isOffline(), conditions.latency, conditions.download < 0 ? 0 : conditions.download,
- conditions.upload < 0 ? 0 : conditions.upload, SDK.NetworkManager._connectionType(conditions));
+ conditions.upload < 0 ? 0 : conditions.upload, NetworkManager._connectionType(conditions));
}
}
@@ -1081,8 +1123,9 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
*/
setExtraHTTPHeaders(headers) {
this._extraHeaders = headers;
- for (const agent of this._agents)
+ for (const agent of this._agents) {
agent.setExtraHTTPHeaders(this._extraHeaders);
+ }
}
/**
@@ -1094,20 +1137,23 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
_updateUserAgentOverride() {
const userAgent = this._currentUserAgent();
- for (const agent of this._agents)
+ for (const agent of this._agents) {
agent.setUserAgentOverride(userAgent);
+ }
}
/**
* @param {string} userAgent
*/
setUserAgentOverride(userAgent) {
- if (this._userAgentOverride === userAgent)
+ if (this._userAgentOverride === userAgent) {
return;
+ }
this._userAgentOverride = userAgent;
- if (!this._customUserAgent)
+ if (!this._customUserAgent) {
this._updateUserAgentOverride();
- this.dispatchEventToListeners(SDK.MultitargetNetworkManager.Events.UserAgentChanged);
+ }
+ this.dispatchEventToListeners(MultitargetNetworkManager.Events.UserAgentChanged);
}
/**
@@ -1153,34 +1199,38 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
setBlockedPatterns(patterns) {
this._blockedPatternsSetting.set(patterns);
this._updateBlockedPatterns();
- this.dispatchEventToListeners(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged);
+ this.dispatchEventToListeners(MultitargetNetworkManager.Events.BlockedPatternsChanged);
}
/**
* @param {boolean} enabled
*/
setBlockingEnabled(enabled) {
- if (this._blockingEnabledSetting.get() === enabled)
+ if (this._blockingEnabledSetting.get() === enabled) {
return;
+ }
this._blockingEnabledSetting.set(enabled);
this._updateBlockedPatterns();
- this.dispatchEventToListeners(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged);
+ this.dispatchEventToListeners(MultitargetNetworkManager.Events.BlockedPatternsChanged);
}
_updateBlockedPatterns() {
const urls = [];
if (this._blockingEnabledSetting.get()) {
for (const pattern of this._blockedPatternsSetting.get()) {
- if (pattern.enabled)
+ if (pattern.enabled) {
urls.push(pattern.url);
+ }
}
}
- if (!urls.length && !this._effectiveBlockedURLs.length)
+ if (!urls.length && !this._effectiveBlockedURLs.length) {
return;
+ }
this._effectiveBlockedURLs = urls;
- for (const agent of this._agents)
+ for (const agent of this._agents) {
agent.setBlockedURLs(this._effectiveBlockedURLs);
+ }
}
/**
@@ -1198,8 +1248,9 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
setInterceptionHandlerForPatterns(patterns, requestInterceptor) {
// Note: requestInterceptors may recieve interception requests for patterns they did not subscribe to.
this._urlsForRequestInterceptor.deleteAll(requestInterceptor);
- for (const newPattern of patterns)
+ for (const newPattern of patterns) {
this._urlsForRequestInterceptor.set(requestInterceptor, newPattern);
+ }
return this._updateInterceptionPatternsOnNextTick();
}
@@ -1208,8 +1259,9 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
*/
_updateInterceptionPatternsOnNextTick() {
// This is used so we can register and unregister patterns in loops without sending lots of protocol messages.
- if (!this._updatingInterceptionPatternsPromise)
+ if (!this._updatingInterceptionPatternsPromise) {
this._updatingInterceptionPatternsPromise = Promise.resolve().then(this._updateInterceptionPatterns.bind(this));
+ }
return this._updatingInterceptionPatternsPromise;
}
@@ -1217,37 +1269,43 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
* @return {!Promise}
*/
_updateInterceptionPatterns() {
- if (!Common.moduleSetting('cacheDisabled').get())
+ if (!Common.moduleSetting('cacheDisabled').get()) {
Common.moduleSetting('cacheDisabled').set(true);
+ }
this._updatingInterceptionPatternsPromise = null;
const promises = /** @type {!Array<!Promise>} */ ([]);
- for (const agent of this._agents)
+ for (const agent of this._agents) {
promises.push(agent.setRequestInterception(this._urlsForRequestInterceptor.valuesArray()));
- this.dispatchEventToListeners(SDK.MultitargetNetworkManager.Events.InterceptorsChanged);
+ }
+ this.dispatchEventToListeners(MultitargetNetworkManager.Events.InterceptorsChanged);
return Promise.all(promises);
}
/**
- * @param {!SDK.MultitargetNetworkManager.InterceptedRequest} interceptedRequest
+ * @param {!InterceptedRequest} interceptedRequest
*/
async _requestIntercepted(interceptedRequest) {
for (const requestInterceptor of this._urlsForRequestInterceptor.keysArray()) {
await requestInterceptor(interceptedRequest);
- if (interceptedRequest.hasResponded())
+ if (interceptedRequest.hasResponded()) {
return;
+ }
}
- if (!interceptedRequest.hasResponded())
+ if (!interceptedRequest.hasResponded()) {
interceptedRequest.continueRequestWithoutChange();
+ }
}
clearBrowserCache() {
- for (const agent of this._agents)
+ for (const agent of this._agents) {
agent.clearBrowserCache();
+ }
}
clearBrowserCookies() {
- for (const agent of this._agents)
+ for (const agent of this._agents) {
agent.clearBrowserCookies();
+ }
}
/**
@@ -1267,25 +1325,27 @@ SDK.MultitargetNetworkManager = class extends Common.Object {
const headers = {};
const currentUserAgent = this._currentUserAgent();
- if (currentUserAgent)
+ if (currentUserAgent) {
headers['User-Agent'] = currentUserAgent;
+ }
- if (Common.moduleSetting('cacheDisabled').get())
+ if (Common.moduleSetting('cacheDisabled').get()) {
headers['Cache-Control'] = 'no-cache';
+ }
Host.ResourceLoader.load(url, headers, callback);
}
-};
+}
/** @enum {symbol} */
-SDK.MultitargetNetworkManager.Events = {
+MultitargetNetworkManager.Events = {
BlockedPatternsChanged: Symbol('BlockedPatternsChanged'),
ConditionsChanged: Symbol('ConditionsChanged'),
UserAgentChanged: Symbol('UserAgentChanged'),
InterceptorsChanged: Symbol('InterceptorsChanged')
};
-SDK.MultitargetNetworkManager.InterceptedRequest = class {
+export class InterceptedRequest {
/**
* @param {!Protocol.NetworkAgent} networkAgent
* @param {!Protocol.Network.InterceptionId} interceptionId
@@ -1389,7 +1449,7 @@ SDK.MultitargetNetworkManager.InterceptedRequest = class {
const error = response[Protocol.Error] || null;
return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
}
-};
+}
/**
* Helper class to match requests created from requestWillBeSent with
@@ -1450,8 +1510,9 @@ class RedirectExtraInfoBuilder {
*/
_sync(index) {
const req = this._requests[index];
- if (!req)
+ if (!req) {
return;
+ }
const requestExtraInfo = this._requestExtraInfos[index];
if (requestExtraInfo) {
@@ -1469,26 +1530,84 @@ class RedirectExtraInfoBuilder {
}
_deleteIfComplete() {
- if (!this._finished)
+ if (!this._finished) {
return;
+ }
if (this._hasExtraInfo) {
// if we haven't gotten the last responseExtraInfo event, we have to wait for it.
- if (!this._requests.peekLast().hasExtraResponseInfo())
+ if (!this._requests.peekLast().hasExtraResponseInfo()) {
return;
+ }
}
this._deleteCallback();
}
}
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.NetworkManager = NetworkManager;
+
+/** @enum {symbol} */
+SDK.NetworkManager.Events = Events;
+
+SDK.NetworkManager._MIMETypes = _MIMETypes;
+
+/** @type {!SDK.NetworkManager.Conditions} */
+SDK.NetworkManager.NoThrottlingConditions = NoThrottlingConditions;
+
+/** @type {!SDK.NetworkManager.Conditions} */
+SDK.NetworkManager.OfflineConditions = OfflineConditions;
+
+/** @type {!SDK.NetworkManager.Conditions} */
+SDK.NetworkManager.Slow3GConditions = Slow3GConditions;
+
+/** @type {!SDK.NetworkManager.Conditions} */
+SDK.NetworkManager.Fast3GConditions = Fast3GConditions;
+
+SDK.NetworkManager._networkManagerForRequestSymbol = _networkManagerForRequestSymbol;
+SDK.NetworkManager.MAX_EAGER_POST_REQUEST_BODY_LENGTH = MAX_EAGER_POST_REQUEST_BODY_LENGTH;
+
+/** @constructor */
+SDK.NetworkDispatcher = NetworkDispatcher;
+
+/** @constructor */
+SDK.MultitargetNetworkManager = MultitargetNetworkManager;
+
+/** @constructor */
+SDK.MultitargetNetworkManager.InterceptedRequest = InterceptedRequest;
+
+/** @typedef {{url: string, enabled: boolean}} */
+SDK.NetworkManager.BlockedPattern;
+
+/**
+ * @typedef {{
+ * download: number,
+ * upload: number,
+ * latency: number,
+ * title: string,
+ * }}
+ */
+SDK.NetworkManager.Conditions;
+
+/** @typedef {{message: string, requestId: string, warning: boolean}} */
+SDK.NetworkManager.Message;
+
/** @typedef {!{urlPattern: string, interceptionStage: !Protocol.Network.InterceptionStage}} */
SDK.MultitargetNetworkManager.InterceptionPattern;
-/** @typedef {!function(!SDK.MultitargetNetworkManager.InterceptedRequest):!Promise} */
+/** @typedef {!function(!InterceptedRequest):!Promise} */
SDK.MultitargetNetworkManager.RequestInterceptor;
/**
- * @type {!SDK.MultitargetNetworkManager}
+ * @type {!MultitargetNetworkManager}
*/
SDK.multitargetNetworkManager;
+
+SDK.SDKModel.register(SDK.NetworkManager, SDK.Target.Capability.Network, true);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
index 8ec92501691..fb9d05d1dbd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
@@ -31,7 +31,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-SDK.NetworkRequest = class extends Common.Object {
+export default class NetworkRequest extends Common.Object {
/**
* @param {!Protocol.Network.RequestId} requestId
* @param {string} url
@@ -51,9 +51,9 @@ SDK.NetworkRequest = class extends Common.Object {
this._loaderId = loaderId;
/** @type {?Protocol.Network.Initiator} */
this._initiator = initiator;
- /** @type {?SDK.NetworkRequest} */
+ /** @type {?NetworkRequest} */
this._redirectSource = null;
- /** @type {?SDK.NetworkRequest} */
+ /** @type {?NetworkRequest} */
this._redirectDestination = null;
this._issueTime = -1;
this._startTime = -1;
@@ -65,6 +65,7 @@ SDK.NetworkRequest = class extends Common.Object {
this.statusText = '';
this.requestMethod = '';
this.requestTime = 0;
+ /** @type {string} */
this.protocol = '';
/** @type {!Protocol.Security.MixedContentType} */
this.mixedContentType = Protocol.Security.MixedContentType.None;
@@ -117,19 +118,26 @@ SDK.NetworkRequest = class extends Common.Object {
this._hasExtraRequestInfo = false;
/** @type {boolean} */
this._hasExtraResponseInfo = false;
+
+ /** @type {!Array<!SDK.NetworkRequest.BlockedCookieWithReason>} */
+ this._blockedRequestCookies = [];
+ /** @type {!Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>} */
+ this._blockedResponseCookies = [];
}
/**
- * @param {!SDK.NetworkRequest} other
+ * @param {!NetworkRequest} other
* @return {number}
*/
indentityCompare(other) {
const thisId = this.requestId();
const thatId = other.requestId();
- if (thisId > thatId)
+ if (thisId > thatId) {
return 1;
- if (thisId < thatId)
+ }
+ if (thisId < thatId) {
return -1;
+ }
return 0;
}
@@ -165,8 +173,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @param {string} x
*/
setUrl(x) {
- if (this._url === x)
+ if (this._url === x) {
return;
+ }
this._url = x;
this._parsedURL = new Common.ParsedURL(x);
@@ -207,7 +216,7 @@ SDK.NetworkRequest = class extends Common.Object {
*/
setRemoteAddress(ip, port) {
this._remoteAddress = ip + ':' + port;
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.RemoteAddressChanged, this);
+ this.dispatchEventToListeners(Events.RemoteAddressChanged, this);
}
/**
@@ -322,18 +331,20 @@ SDK.NetworkRequest = class extends Common.Object {
} else {
// Prefer endTime since it might be from the network stack.
this._endTime = x;
- if (this._responseReceivedTime > x)
+ if (this._responseReceivedTime > x) {
this._responseReceivedTime = x;
+ }
}
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.TimingChanged, this);
+ this.dispatchEventToListeners(Events.TimingChanged, this);
}
/**
* @return {number}
*/
get duration() {
- if (this._endTime === -1 || this._startTime === -1)
+ if (this._endTime === -1 || this._startTime === -1) {
return -1;
+ }
return this._endTime - this._startTime;
}
@@ -341,8 +352,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {number}
*/
get latency() {
- if (this._responseReceivedTime === -1 || this._startTime === -1)
+ if (this._responseReceivedTime === -1 || this._startTime === -1) {
return -1;
+ }
return this._responseReceivedTime - this._startTime;
}
@@ -392,13 +404,15 @@ SDK.NetworkRequest = class extends Common.Object {
* @param {boolean} x
*/
set finished(x) {
- if (this._finished === x)
+ if (this._finished === x) {
return;
+ }
this._finished = x;
- if (x)
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.FinishedLoading, this);
+ if (x) {
+ this.dispatchEventToListeners(Events.FinishedLoading, this);
+ }
}
/**
@@ -506,8 +520,9 @@ SDK.NetworkRequest = class extends Common.Object {
*/
initiatedByServiceWorker() {
const networkManager = SDK.NetworkManager.forRequest(this);
- if (!networkManager)
+ if (!networkManager) {
return false;
+ }
return networkManager.target().type() === SDK.Target.Type.ServiceWorker;
}
@@ -522,19 +537,22 @@ SDK.NetworkRequest = class extends Common.Object {
* @param {!Protocol.Network.ResourceTiming|undefined} timingInfo
*/
set timing(timingInfo) {
- if (!timingInfo || this._fromMemoryCache)
+ if (!timingInfo || this._fromMemoryCache) {
return;
+ }
// Take startTime and responseReceivedTime from timing data for better accuracy.
// Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis.
this._startTime = timingInfo.requestTime;
const headersReceivedTime = timingInfo.requestTime + timingInfo.receiveHeadersEnd / 1000.0;
- if ((this._responseReceivedTime || -1) < 0 || this._responseReceivedTime > headersReceivedTime)
+ if ((this._responseReceivedTime || -1) < 0 || this._responseReceivedTime > headersReceivedTime) {
this._responseReceivedTime = headersReceivedTime;
- if (this._startTime > this._responseReceivedTime)
+ }
+ if (this._startTime > this._responseReceivedTime) {
this._responseReceivedTime = this._startTime;
+ }
this._timing = timingInfo;
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.TimingChanged, this);
+ this.dispatchEventToListeners(Events.TimingChanged, this);
}
/**
@@ -562,8 +580,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {string}
*/
name() {
- if (this._name)
+ if (this._name) {
return this._name;
+ }
this._parseNameAndPathFromURL();
return this._name;
}
@@ -572,8 +591,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {string}
*/
path() {
- if (this._path)
+ if (this._path) {
return this._path;
+ }
this._parseNameAndPathFromURL();
return this._path;
}
@@ -615,8 +635,9 @@ SDK.NetworkRequest = class extends Common.Object {
get folder() {
let path = this._parsedURL.path;
const indexOfQuery = path.indexOf('?');
- if (indexOfQuery !== -1)
+ if (indexOfQuery !== -1) {
path = path.substring(0, indexOfQuery);
+ }
const lastSlashIndex = path.lastIndexOf('/');
return lastSlashIndex !== -1 ? path.substring(0, lastSlashIndex) : '';
}
@@ -650,28 +671,28 @@ SDK.NetworkRequest = class extends Common.Object {
}
/**
- * @return {?SDK.NetworkRequest}
+ * @return {?NetworkRequest}
*/
redirectSource() {
return this._redirectSource;
}
/**
- * @param {?SDK.NetworkRequest} originatingRequest
+ * @param {?NetworkRequest} originatingRequest
*/
setRedirectSource(originatingRequest) {
this._redirectSource = originatingRequest;
}
/**
- * @return {?SDK.NetworkRequest}
+ * @return {?NetworkRequest}
*/
redirectDestination() {
return this._redirectDestination;
}
/**
- * @param {?SDK.NetworkRequest} redirectDestination
+ * @param {?NetworkRequest} redirectDestination
*/
setRedirectDestination(redirectDestination) {
this._redirectDestination = redirectDestination;
@@ -691,7 +712,7 @@ SDK.NetworkRequest = class extends Common.Object {
this._requestHeaders = headers;
delete this._requestCookies;
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.RequestHeadersChanged);
+ this.dispatchEventToListeners(Events.RequestHeadersChanged);
}
/**
@@ -707,7 +728,7 @@ SDK.NetworkRequest = class extends Common.Object {
setRequestHeadersText(text) {
this._requestHeadersText = text;
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.RequestHeadersChanged);
+ this.dispatchEventToListeners(Events.RequestHeadersChanged);
}
/**
@@ -715,18 +736,20 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {string|undefined}
*/
requestHeaderValue(headerName) {
- if (headerName in this._requestHeaderValues)
+ if (this._requestHeaderValues[headerName]) {
return this._requestHeaderValues[headerName];
+ }
this._requestHeaderValues[headerName] = this._computeHeaderValue(this.requestHeaders(), headerName);
return this._requestHeaderValues[headerName];
}
/**
- * @return {!Array.<!SDK.Cookie>}
+ * @return {?Array.<!SDK.Cookie>}
*/
get requestCookies() {
- if (!this._requestCookies)
+ if (!this._requestCookies) {
this._requestCookies = SDK.CookieParser.parseCookie(this.requestHeaderValue('Cookie'));
+ }
return this._requestCookies;
}
@@ -734,8 +757,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {!Promise<?string>}
*/
requestFormData() {
- if (!this._requestFormDataPromise)
+ if (!this._requestFormDataPromise) {
this._requestFormDataPromise = SDK.NetworkManager.requestPostData(this);
+ }
return this._requestFormDataPromise;
}
@@ -753,8 +777,9 @@ SDK.NetworkRequest = class extends Common.Object {
*/
_filteredProtocolName() {
const protocol = this.protocol.toLowerCase();
- if (protocol === 'h2')
+ if (protocol === 'h2') {
return 'http/2.0';
+ }
return protocol.replace(/^http\/2(\.0)?\+/, 'http/2.0+');
}
@@ -765,8 +790,9 @@ SDK.NetworkRequest = class extends Common.Object {
const headersText = this.requestHeadersText();
if (!headersText) {
const version = this.requestHeaderValue('version') || this.requestHeaderValue(':version');
- if (version)
+ if (version) {
return version;
+ }
return this._filteredProtocolName();
}
const firstLine = headersText.split(/\r\n/)[0];
@@ -791,7 +817,7 @@ SDK.NetworkRequest = class extends Common.Object {
delete this._responseCookies;
this._responseHeaderValues = {};
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.ResponseHeadersChanged);
+ this.dispatchEventToListeners(Events.ResponseHeadersChanged);
}
/**
@@ -807,15 +833,16 @@ SDK.NetworkRequest = class extends Common.Object {
set responseHeadersText(x) {
this._responseHeadersText = x;
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.ResponseHeadersChanged);
+ this.dispatchEventToListeners(Events.ResponseHeadersChanged);
}
/**
* @return {!Array.<!SDK.NetworkRequest.NameValue>}
*/
get sortedResponseHeaders() {
- if (this._sortedResponseHeaders !== undefined)
+ if (this._sortedResponseHeaders !== undefined) {
return this._sortedResponseHeaders;
+ }
this._sortedResponseHeaders = this.responseHeaders.slice();
this._sortedResponseHeaders.sort(function(a, b) {
@@ -829,8 +856,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {string|undefined}
*/
responseHeaderValue(headerName) {
- if (headerName in this._responseHeaderValues)
+ if (headerName in this._responseHeaderValues) {
return this._responseHeaderValues[headerName];
+ }
this._responseHeaderValues[headerName] = this._computeHeaderValue(this.responseHeaders, headerName);
return this._responseHeaderValues[headerName];
}
@@ -839,8 +867,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {!Array.<!SDK.Cookie>}
*/
get responseCookies() {
- if (!this._responseCookies)
+ if (!this._responseCookies) {
this._responseCookies = SDK.CookieParser.parseSetCookie(this.responseHeaderValue('Set-Cookie'));
+ }
return this._responseCookies;
}
@@ -855,8 +884,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {?Array.<!SDK.ServerTiming>}
*/
get serverTimings() {
- if (typeof this._serverTimings === 'undefined')
+ if (typeof this._serverTimings === 'undefined') {
this._serverTimings = SDK.ServerTiming.parseHeaders(this.responseHeaders);
+ }
return this._serverTimings;
}
@@ -864,8 +894,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {?string}
*/
queryString() {
- if (this._queryString !== undefined)
+ if (this._queryString !== undefined) {
return this._queryString;
+ }
let queryString = null;
const url = this.url();
@@ -873,8 +904,9 @@ SDK.NetworkRequest = class extends Common.Object {
if (questionMarkPosition !== -1) {
queryString = url.substring(questionMarkPosition + 1);
const hashSignPosition = queryString.indexOf('#');
- if (hashSignPosition !== -1)
+ if (hashSignPosition !== -1) {
queryString = queryString.substring(0, hashSignPosition);
+ }
}
this._queryString = queryString;
return this._queryString;
@@ -884,11 +916,13 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {?Array.<!SDK.NetworkRequest.NameValue>}
*/
get queryParameters() {
- if (this._parsedQueryParameters)
+ if (this._parsedQueryParameters) {
return this._parsedQueryParameters;
+ }
const queryString = this.queryString();
- if (!queryString)
+ if (!queryString) {
return null;
+ }
this._parsedQueryParameters = this._parseParameters(queryString);
return this._parsedQueryParameters;
}
@@ -899,14 +933,16 @@ SDK.NetworkRequest = class extends Common.Object {
async _parseFormParameters() {
const requestContentType = this.requestContentType();
- if (!requestContentType)
+ if (!requestContentType) {
return null;
+ }
// Handling application/x-www-form-urlencoded request bodies.
if (requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)) {
const formData = await this.requestFormData();
- if (!formData)
+ if (!formData) {
return null;
+ }
return this._parseParameters(formData);
}
@@ -914,16 +950,19 @@ SDK.NetworkRequest = class extends Common.Object {
// Handling multipart/form-data request bodies.
const multipartDetails = requestContentType.match(/^multipart\/form-data\s*;\s*boundary\s*=\s*(\S+)\s*$/);
- if (!multipartDetails)
+ if (!multipartDetails) {
return null;
+ }
const boundary = multipartDetails[1];
- if (!boundary)
+ if (!boundary) {
return null;
+ }
const formData = await this.requestFormData();
- if (!formData)
+ if (!formData) {
return null;
+ }
return this._parseMultipartFormDataParameters(formData, boundary);
}
@@ -932,8 +971,9 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {!Promise<?Array<!SDK.NetworkRequest.NameValue>>}
*/
formParameters() {
- if (!this._formParametersPromise)
+ if (!this._formParametersPromise) {
this._formParametersPromise = this._parseFormParameters();
+ }
return this._formParametersPromise;
}
@@ -944,8 +984,9 @@ SDK.NetworkRequest = class extends Common.Object {
const headersText = this._responseHeadersText;
if (!headersText) {
const version = this.responseHeaderValue('version') || this.responseHeaderValue(':version');
- if (version)
+ if (version) {
return version;
+ }
return this._filteredProtocolName();
}
const firstLine = headersText.split(/\r\n/)[0];
@@ -960,10 +1001,11 @@ SDK.NetworkRequest = class extends Common.Object {
_parseParameters(queryString) {
function parseNameValue(pair) {
const position = pair.indexOf('=');
- if (position === -1)
+ if (position === -1) {
return {name: pair, value: ''};
- else
+ } else {
return {name: pair.substring(0, position), value: pair.substring(position + 1)};
+ }
}
return queryString.split('&').map(parseNameValue);
}
@@ -1010,8 +1052,9 @@ SDK.NetworkRequest = class extends Common.Object {
function parseMultipartField(result, field) {
const [match, name, filename, contentType, value] = field.match(keyValuePattern) || [];
- if (!match)
+ if (!match) {
return result;
+ }
const processedValue = (filename || contentType) ? ls`(binary)` : value;
result.push({name, value: processedValue});
@@ -1030,14 +1073,17 @@ SDK.NetworkRequest = class extends Common.Object {
const values = [];
for (let i = 0; i < headers.length; ++i) {
- if (headers[i].name.toLowerCase() === headerName)
+ if (headers[i].name.toLowerCase() === headerName) {
values.push(headers[i].value);
+ }
}
- if (!values.length)
+ if (!values.length) {
return undefined;
+ }
// Set-Cookie values should be separated by '\n', not comma, otherwise cookies could not be parsed.
- if (headerName === 'set-cookie')
+ if (headerName === 'set-cookie') {
return values.join('\n');
+ }
return values.join(', ');
}
@@ -1045,12 +1091,14 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {!Promise<!SDK.NetworkRequest.ContentData>}
*/
contentData() {
- if (this._contentData)
+ if (this._contentData) {
return this._contentData;
- if (this._contentDataProvider)
+ }
+ if (this._contentDataProvider) {
this._contentData = this._contentDataProvider();
- else
+ } else {
this._contentData = SDK.NetworkManager.requestContentData(this);
+ }
return this._contentData;
}
@@ -1088,10 +1136,15 @@ SDK.NetworkRequest = class extends Common.Object {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
async requestContent() {
- return (await this.contentData()).content;
+ const {content, error, encoded} = await this.contentData();
+ return /** @type{!Common.DeferredContent} */ ({
+ content,
+ error,
+ isEncoded: encoded,
+ });
}
/**
@@ -1102,15 +1155,18 @@ SDK.NetworkRequest = class extends Common.Object {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- if (!this._contentDataProvider)
+ if (!this._contentDataProvider) {
return SDK.NetworkManager.searchInRequest(this, query, caseSensitive, isRegex);
+ }
const contentData = await this.contentData();
let content = contentData.content;
- if (!content)
+ if (!content) {
return [];
- if (contentData.encoded)
+ }
+ if (contentData.encoded) {
content = window.atob(content);
+ }
return Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
}
@@ -1185,11 +1241,13 @@ SDK.NetworkRequest = class extends Common.Object {
let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, encoded);
if (imageSrc === null && !this._failed) {
const cacheControl = this.responseHeaderValue('cache-control') || '';
- if (!cacheControl.includes('no-cache'))
+ if (!cacheControl.includes('no-cache')) {
imageSrc = this._url;
+ }
}
- if (imageSrc !== null)
+ if (imageSrc !== null) {
image.src = imageSrc;
+ }
}
/**
@@ -1211,13 +1269,8 @@ SDK.NetworkRequest = class extends Common.Object {
* @param {number} time
*/
addProtocolFrameError(errorMessage, time) {
- this.addFrame({
- type: SDK.NetworkRequest.WebSocketFrameType.Error,
- text: errorMessage,
- time: this.pseudoWallTime(time),
- opCode: -1,
- mask: false
- });
+ this.addFrame(
+ {type: WebSocketFrameType.Error, text: errorMessage, time: this.pseudoWallTime(time), opCode: -1, mask: false});
}
/**
@@ -1226,7 +1279,7 @@ SDK.NetworkRequest = class extends Common.Object {
* @param {boolean} sent
*/
addProtocolFrame(response, time, sent) {
- const type = sent ? SDK.NetworkRequest.WebSocketFrameType.Send : SDK.NetworkRequest.WebSocketFrameType.Receive;
+ const type = sent ? WebSocketFrameType.Send : WebSocketFrameType.Receive;
this.addFrame({
type: type,
text: response.payloadData,
@@ -1241,7 +1294,7 @@ SDK.NetworkRequest = class extends Common.Object {
*/
addFrame(frame) {
this._frames.push(frame);
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.WebsocketFrameAdded, frame);
+ this.dispatchEventToListeners(Events.WebsocketFrameAdded, frame);
}
/**
@@ -1260,7 +1313,7 @@ SDK.NetworkRequest = class extends Common.Object {
addEventSourceMessage(time, eventName, eventId, data) {
const message = {time: this.pseudoWallTime(time), eventName: eventName, eventId: eventId, data: data};
this._eventSourceMessages.push(message);
- this.dispatchEventToListeners(SDK.NetworkRequest.Events.EventSourceMessageAdded, message);
+ this.dispatchEventToListeners(Events.EventSourceMessageAdded, message);
}
/**
@@ -1283,15 +1336,17 @@ SDK.NetworkRequest = class extends Common.Object {
*/
charset() {
const contentTypeHeader = this.responseHeaderValue('content-type');
- if (!contentTypeHeader)
+ if (!contentTypeHeader) {
return null;
+ }
const responseCharsets = contentTypeHeader.replace(/ /g, '')
.split(';')
.filter(parameter => parameter.toLowerCase().startsWith('charset='))
.map(parameter => parameter.slice('charset='.length));
- if (responseCharsets.length)
+ if (responseCharsets.length) {
return responseCharsets[0];
+ }
return null;
}
@@ -1314,6 +1369,13 @@ SDK.NetworkRequest = class extends Common.Object {
}
/**
+ * @return {!Array<!SDK.NetworkRequest.BlockedCookieWithReason>}
+ */
+ blockedRequestCookies() {
+ return this._blockedRequestCookies;
+ }
+
+ /**
* @param {!SDK.NetworkRequest.ExtraResponseInfo} extraResponseInfo
*/
addExtraResponseInfo(extraResponseInfo) {
@@ -1327,12 +1389,14 @@ SDK.NetworkRequest = class extends Common.Object {
// Generate request headers text from raw headers in extra request info because
// Network.requestWillBeSentExtraInfo doesn't include headers text.
let requestHeadersText = `${this.requestMethod} ${this.parsedURL.path}`;
- if (this.parsedURL.queryParams)
+ if (this.parsedURL.queryParams) {
requestHeadersText += `?${this.parsedURL.queryParams}`;
+ }
requestHeadersText += ` HTTP/1.1\r\n`;
- for (const {name, value} of this.requestHeaders())
+ for (const {name, value} of this.requestHeaders()) {
requestHeadersText += `${name}: ${value}\r\n`;
+ }
this.setRequestHeadersText(requestHeadersText);
}
}
@@ -1346,10 +1410,17 @@ SDK.NetworkRequest = class extends Common.Object {
hasExtraResponseInfo() {
return this._hasExtraResponseInfo;
}
-};
+
+ /**
+ * @return {!Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>}
+ */
+ blockedResponseCookies() {
+ return this._blockedResponseCookies;
+ }
+}
/** @enum {symbol} */
-SDK.NetworkRequest.Events = {
+export const Events = {
FinishedLoading: Symbol('FinishedLoading'),
TimingChanged: Symbol('TimingChanged'),
RemoteAddressChanged: Symbol('RemoteAddressChanged'),
@@ -1360,7 +1431,7 @@ SDK.NetworkRequest.Events = {
};
/** @enum {string} */
-SDK.NetworkRequest.InitiatorType = {
+export const InitiatorType = {
Other: 'other',
Parser: 'parser',
Redirect: 'redirect',
@@ -1369,17 +1440,171 @@ SDK.NetworkRequest.InitiatorType = {
SignedExchange: 'signedExchange'
};
-/** @typedef {!{name: string, value: string}} */
-SDK.NetworkRequest.NameValue;
-
/** @enum {string} */
-SDK.NetworkRequest.WebSocketFrameType = {
+export const WebSocketFrameType = {
Send: 'send',
Receive: 'receive',
Error: 'error'
};
-/** @typedef {!{type: SDK.NetworkRequest.WebSocketFrameType, time: number, text: string, opCode: number, mask: boolean}} */
+/**
+ * @param {!Protocol.Network.CookieBlockedReason} blockedReason
+ * @return {string}
+ */
+export const cookieBlockedReasonToUiString = function(blockedReason) {
+ switch (blockedReason) {
+ case Protocol.Network.CookieBlockedReason.SecureOnly:
+ return ls`This cookie had the "Secure" attribute and the connection was not secure.`;
+ case Protocol.Network.CookieBlockedReason.NotOnPath:
+ return ls`This cookie's path was not within the request url's path.`;
+ case Protocol.Network.CookieBlockedReason.DomainMismatch:
+ return ls
+ `This cookie's domain is not configured to match the request url's domain, even though they share a common TLD+1 (TLD+1 of foo.bar.example.com is example.com).`;
+ case Protocol.Network.CookieBlockedReason.SameSiteStrict:
+ return ls
+ `This cookie had the "SameSite=Strict" attribute and the request was made on on a different site. This includes navigation requests initiated by other sites.`;
+ case Protocol.Network.CookieBlockedReason.SameSiteLax:
+ return ls
+ `This cookie had the "SameSite=Lax" attribute and the request was made on a different site. This does not include navigation requests initiated by other sites.`;
+ case Protocol.Network.CookieBlockedReason.SameSiteExtended:
+ return ls
+ `This cookie had the "SameSite=Extended" attribute and the request was made on a different site. The different site is outside of the cookie's trusted first-party set.`;
+ case Protocol.Network.CookieBlockedReason.SameSiteUnspecifiedTreatedAsLax:
+ return ls
+ `This cookie didn't specify a SameSite attribute when it was stored and was defaulted to "SameSite=Lax" and broke the same rules specified in the SameSiteLax value. The cookie had to have been set with "SameSite=None" to enable third-party usage.`;
+ case Protocol.Network.CookieBlockedReason.SameSiteNoneInsecure:
+ return ls
+ `This cookie had the "SameSite=None" attribute but was not marked "Secure". Cookies without SameSite restrictions must be marked "Secure" and sent over a secure connection.`;
+ case Protocol.Network.CookieBlockedReason.UserPreferences:
+ return ls`This cookie was not sent due to user preferences.`;
+ case Protocol.Network.CookieBlockedReason.UnknownError:
+ return ls`An unknown error was encountered when trying to send this cookie.`;
+ }
+ return '';
+};
+
+/**
+ * @param {!Protocol.Network.SetCookieBlockedReason} blockedReason
+ * @return {string}
+ */
+export const setCookieBlockedReasonToUiString = function(blockedReason) {
+ switch (blockedReason) {
+ case Protocol.Network.SetCookieBlockedReason.SecureOnly:
+ return ls
+ `This set-cookie had the "Secure" attribute but was not received over a secure connection.`;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteStrict:
+ return ls
+ `This set-cookie had the "SameSite=Strict" attribute but came from a cross-origin response. This includes navigation requests intitiated by other origins.`;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteLax:
+ return ls`This set-cookie had the "SameSite=Lax" attribute but came from a cross-origin response.`;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteExtended:
+ return ls`This set-cookie had the "SameSite=Extended" attribute but came from a cross-origin response.`;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteUnspecifiedTreatedAsLax:
+ return ls
+ `This set-cookie didn't specify a "SameSite" attribute and was defaulted to "SameSite=Lax" and broke the same rules specified in the SameSiteLax value.`;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteNoneInsecure:
+ return ls
+ `This set-cookie had the "SameSite=None" attribute but did not have the "Secure" attribute, which is required in order to use "SameSite=None".`;
+ case Protocol.Network.SetCookieBlockedReason.UserPreferences:
+ return ls`This set-cookie was not stored due to user preferences.`;
+ case Protocol.Network.SetCookieBlockedReason.SyntaxError:
+ return ls`This set-cookie had invalid syntax.`;
+ case Protocol.Network.SetCookieBlockedReason.SchemeNotSupported:
+ return ls`The scheme of this connection is not allowed to store cookies.`;
+ case Protocol.Network.SetCookieBlockedReason.OverwriteSecure:
+ return ls
+ `This set-cookie was not sent over a secure connection and would have overwritten a cookie with the Secure attribute.`;
+ case Protocol.Network.SetCookieBlockedReason.InvalidDomain:
+ return ls`This set-cookie's Domain attribute was invalid with regards to the current host url.`;
+ case Protocol.Network.SetCookieBlockedReason.InvalidPrefix:
+ return ls
+ `This set-cookie used the "__Secure-" or "__Host-" prefix in its name and broke the additional rules applied to cookies with these prefixes as defined in https://tools.ietf.org/html/draft-west-cookie-prefixes-05.`;
+ case Protocol.Network.SetCookieBlockedReason.UnknownError:
+ return ls`An unknown error was encountered when trying to store this cookie.`;
+ }
+ return '';
+};
+
+/**
+ * @param {!Protocol.Network.CookieBlockedReason} blockedReason
+ * @return {?SDK.Cookie.Attributes}
+ */
+export const cookieBlockedReasonToAttribute = function(blockedReason) {
+ switch (blockedReason) {
+ case Protocol.Network.CookieBlockedReason.SecureOnly:
+ return SDK.Cookie.Attributes.Secure;
+ case Protocol.Network.CookieBlockedReason.NotOnPath:
+ return SDK.Cookie.Attributes.Path;
+ case Protocol.Network.CookieBlockedReason.DomainMismatch:
+ return SDK.Cookie.Attributes.Domain;
+ case Protocol.Network.CookieBlockedReason.SameSiteStrict:
+ case Protocol.Network.CookieBlockedReason.SameSiteLax:
+ case Protocol.Network.CookieBlockedReason.SameSiteExtended:
+ case Protocol.Network.CookieBlockedReason.SameSiteUnspecifiedTreatedAsLax:
+ case Protocol.Network.CookieBlockedReason.SameSiteNoneInsecure:
+ return SDK.Cookie.Attributes.SameSite;
+ case Protocol.Network.CookieBlockedReason.UserPreferences:
+ case Protocol.Network.CookieBlockedReason.UnknownError:
+ return null;
+ }
+ return null;
+};
+
+/**
+ * @param {!Protocol.Network.SetCookieBlockedReason} blockedReason
+ * @return {?SDK.Cookie.Attributes}
+ */
+export const setCookieBlockedReasonToAttribute = function(blockedReason) {
+ switch (blockedReason) {
+ case Protocol.Network.SetCookieBlockedReason.SecureOnly:
+ case Protocol.Network.SetCookieBlockedReason.OverwriteSecure:
+ return SDK.Cookie.Attributes.Secure;
+ case Protocol.Network.SetCookieBlockedReason.SameSiteStrict:
+ case Protocol.Network.SetCookieBlockedReason.SameSiteLax:
+ case Protocol.Network.SetCookieBlockedReason.SameSiteExtended:
+ case Protocol.Network.SetCookieBlockedReason.SameSiteUnspecifiedTreatedAsLax:
+ case Protocol.Network.SetCookieBlockedReason.SameSiteNoneInsecure:
+ return SDK.Cookie.Attributes.SameSite;
+ case Protocol.Network.SetCookieBlockedReason.InvalidDomain:
+ return SDK.Cookie.Attributes.Domain;
+ case Protocol.Network.SetCookieBlockedReason.InvalidPrefix:
+ return SDK.Cookie.Attributes.Name;
+ case Protocol.Network.SetCookieBlockedReason.UserPreferences:
+ case Protocol.Network.SetCookieBlockedReason.SyntaxError:
+ case Protocol.Network.SetCookieBlockedReason.SchemeNotSupported:
+ case Protocol.Network.SetCookieBlockedReason.UnknownError:
+ return null;
+ }
+ return null;
+};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.NetworkRequest = NetworkRequest;
+
+/** @enum {symbol} */
+SDK.NetworkRequest.Events = Events;
+
+/** @enum {string} */
+SDK.NetworkRequest.InitiatorType = InitiatorType;
+
+/** @enum {string} */
+SDK.NetworkRequest.WebSocketFrameType = WebSocketFrameType;
+
+SDK.NetworkRequest.cookieBlockedReasonToUiString = cookieBlockedReasonToUiString;
+SDK.NetworkRequest.setCookieBlockedReasonToUiString = setCookieBlockedReasonToUiString;
+SDK.NetworkRequest.cookieBlockedReasonToAttribute = cookieBlockedReasonToAttribute;
+SDK.NetworkRequest.setCookieBlockedReasonToAttribute = setCookieBlockedReasonToAttribute;
+
+/** @typedef {!{name: string, value: string}} */
+SDK.NetworkRequest.NameValue;
+
+/** @typedef {!{type: WebSocketFrameType, time: number, text: string, opCode: number, mask: boolean}} */
SDK.NetworkRequest.WebSocketFrame;
/** @typedef {!{time: number, eventName: string, eventId: string, data: string}} */
@@ -1390,17 +1615,34 @@ SDK.NetworkRequest.ContentData;
/**
* @typedef {!{
- * blockedRequestCookies: !Array<!Protocol.Network.BlockedCookieWithReason>,
- * requestHeaders: !Array<!SDK.NetworkRequest.NameValue>
- * }}
- */
+ * blockedReasons: !Array<!Protocol.Network.CookieBlockedReason>,
+ * cookie: !SDK.Cookie
+ * }}
+ */
+SDK.NetworkRequest.BlockedCookieWithReason;
+
+/**
+ * @typedef {!{
+ * blockedRequestCookies: !Array<!SDK.NetworkRequest.BlockedCookieWithReason>,
+ * requestHeaders: !Array<!SDK.NetworkRequest.NameValue>
+ * }}
+ */
SDK.NetworkRequest.ExtraRequestInfo;
/**
- * @typedef {!{
- * blockedResponseCookies: !Array<!Protocol.Network.BlockedSetCookieWithReason>,
- * responseHeaders: !Array<!SDK.NetworkRequest.NameValue>,
- * responseHeadersText: (string|undefined)
- * }}
- */
-SDK.NetworkRequest.ExtraResponseInfo;
+ * @typedef {!{
+ * blockedReasons: !Array<!Protocol.Network.SetCookieBlockedReason>,
+ * cookieLine: string,
+ * cookie: ?SDK.Cookie
+ * }}
+ */
+SDK.NetworkRequest.BlockedSetCookieWithReason;
+
+/**
+ * @typedef {!{
+ * blockedResponseCookies: !Array<!SDK.NetworkRequest.BlockedSetCookieWithReason>,
+ * responseHeaders: !Array<!SDK.NetworkRequest.NameValue>,
+ * responseHeadersText: (string|undefined)
+ * }}
+ */
+SDK.NetworkRequest.ExtraResponseInfo; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js
index f40c10437c2..ce130adbf08 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/OverlayModel.js
@@ -5,7 +5,7 @@
/**
* @implements {Protocol.OverlayDispatcher}
*/
-SDK.OverlayModel = class extends SDK.SDKModel {
+export default class OverlayModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -30,7 +30,7 @@ SDK.OverlayModel = class extends SDK.SDKModel {
this._inspectModeEnabled = false;
this._hideHighlightTimeout = null;
- this._defaultHighlighter = new SDK.OverlayModel.DefaultHighlighter(this);
+ this._defaultHighlighter = new DefaultHighlighter(this);
this._highlighter = this._defaultHighlighter;
this._showPaintRectsSetting = Common.moduleSetting('showPaintRects');
@@ -54,21 +54,23 @@ SDK.OverlayModel = class extends SDK.SDKModel {
*/
static highlightObjectAsDOMNode(object) {
const domModel = object.runtimeModel().target().model(SDK.DOMModel);
- if (domModel)
+ if (domModel) {
domModel.overlayModel().highlightInOverlay({object});
+ }
}
static hideDOMNodeHighlight() {
- for (const overlayModel of SDK.targetManager.models(SDK.OverlayModel))
+ for (const overlayModel of SDK.targetManager.models(OverlayModel)) {
overlayModel._delayedHideHighlight(0);
+ }
}
static async muteHighlight() {
- return Promise.all(SDK.targetManager.models(SDK.OverlayModel).map(model => model.suspendModel()));
+ return Promise.all(SDK.targetManager.models(OverlayModel).map(model => model.suspendModel()));
}
static async unmuteHighlight() {
- return Promise.all(SDK.targetManager.models(SDK.OverlayModel).map(model => model.resumeModel()));
+ return Promise.all(SDK.targetManager.models(OverlayModel).map(model => model.resumeModel()));
}
/**
@@ -92,22 +94,30 @@ SDK.OverlayModel = class extends SDK.SDKModel {
() => this._overlayAgent.setShowHitTestBorders(this._showHitTestBordersSetting.get()))
];
- if (this._showPaintRectsSetting.get())
+ if (this._showPaintRectsSetting.get()) {
this._overlayAgent.setShowPaintRects(true);
- if (this._showLayoutShiftRegionsSetting.get())
+ }
+ if (this._showLayoutShiftRegionsSetting.get()) {
this._overlayAgent.setShowLayoutShiftRegions(true);
- if (this._showAdHighlightsSetting.get())
+ }
+ if (this._showAdHighlightsSetting.get()) {
this._overlayAgent.setShowAdHighlights(true);
- if (this._showDebugBordersSetting.get())
+ }
+ if (this._showDebugBordersSetting.get()) {
this._overlayAgent.setShowDebugBorders(true);
- if (this._showFPSCounterSetting.get())
+ }
+ if (this._showFPSCounterSetting.get()) {
this._overlayAgent.setShowFPSCounter(true);
- if (this._showScrollBottleneckRectsSetting.get())
+ }
+ if (this._showScrollBottleneckRectsSetting.get()) {
this._overlayAgent.setShowScrollBottleneckRects(true);
- if (this._showHitTestBordersSetting.get())
+ }
+ if (this._showHitTestBordersSetting.get()) {
this._overlayAgent.setShowHitTestBorders(true);
- if (this._debuggerModel.isPaused())
+ }
+ if (this._debuggerModel.isPaused()) {
this._updatePausedInDebuggerMessage();
+ }
return this._overlayAgent.setShowViewportSizeOnResize(this._showViewportSizeOnResize);
}
@@ -134,8 +144,9 @@ SDK.OverlayModel = class extends SDK.SDKModel {
*/
setShowViewportSizeOnResize(show) {
this._showViewportSizeOnResize = show;
- if (this.target().suspended())
+ if (this.target().suspended()) {
return;
+ }
this._overlayAgent.setShowViewportSizeOnResize(show);
}
@@ -143,8 +154,9 @@ SDK.OverlayModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
_updatePausedInDebuggerMessage() {
- if (this.target().suspended())
+ if (this.target().suspended()) {
return Promise.resolve();
+ }
const message = this._debuggerModel.isPaused() && !Common.moduleSetting('disablePausedStateOverlay').get() ?
Common.UIString('Paused in debugger') :
undefined;
@@ -152,7 +164,7 @@ SDK.OverlayModel = class extends SDK.SDKModel {
}
/**
- * @param {?SDK.OverlayModel.Highlighter} highlighter
+ * @param {?Highlighter} highlighter
*/
setHighlighter(highlighter) {
this._highlighter = highlighter || this._defaultHighlighter;
@@ -166,7 +178,7 @@ SDK.OverlayModel = class extends SDK.SDKModel {
async setInspectMode(mode, showStyles = true) {
await this._domModel.requestDocument();
this._inspectModeEnabled = mode !== Protocol.Overlay.InspectMode.None;
- this.dispatchEventToListeners(SDK.OverlayModel.Events.InspectModeWillBeToggled, this);
+ this.dispatchEventToListeners(Events.InspectModeWillBeToggled, this);
this._highlighter.setInspectMode(mode, this._buildHighlightConfig('all', showStyles));
}
@@ -188,8 +200,9 @@ SDK.OverlayModel = class extends SDK.SDKModel {
this._hideHighlightTimeout = null;
}
const highlightConfig = this._buildHighlightConfig(mode);
- if (typeof showInfo !== 'undefined')
+ if (typeof showInfo !== 'undefined') {
highlightConfig.showInfo = showInfo;
+ }
this._highlighter.highlightInOverlay(data, highlightConfig);
}
@@ -205,8 +218,9 @@ SDK.OverlayModel = class extends SDK.SDKModel {
* @param {number} delay
*/
_delayedHideHighlight(delay) {
- if (this._hideHighlightTimeout === null)
+ if (this._hideHighlightTimeout === null) {
this._hideHighlightTimeout = setTimeout(() => this.highlightInOverlay({}), delay);
+ }
}
/**
@@ -229,17 +243,21 @@ SDK.OverlayModel = class extends SDK.SDKModel {
const showRulers = Common.moduleSetting('showMetricsRulers').get();
const highlightConfig =
{showInfo: mode === 'all', showRulers: showRulers, showStyles, showExtensionLines: showRulers};
- if (mode === 'all' || mode === 'content')
+ if (mode === 'all' || mode === 'content') {
highlightConfig.contentColor = Common.Color.PageHighlight.Content.toProtocolRGBA();
+ }
- if (mode === 'all' || mode === 'padding')
+ if (mode === 'all' || mode === 'padding') {
highlightConfig.paddingColor = Common.Color.PageHighlight.Padding.toProtocolRGBA();
+ }
- if (mode === 'all' || mode === 'border')
+ if (mode === 'all' || mode === 'border') {
highlightConfig.borderColor = Common.Color.PageHighlight.Border.toProtocolRGBA();
+ }
- if (mode === 'all' || mode === 'margin')
+ if (mode === 'all' || mode === 'margin') {
highlightConfig.marginColor = Common.Color.PageHighlight.Margin.toProtocolRGBA();
+ }
if (mode === 'all') {
highlightConfig.eventTargetColor = Common.Color.PageHighlight.EventTarget.toProtocolRGBA();
@@ -247,8 +265,9 @@ SDK.OverlayModel = class extends SDK.SDKModel {
highlightConfig.shapeMarginColor = Common.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
}
- if (mode === 'all')
+ if (mode === 'all') {
highlightConfig.cssGridColor = Common.Color.PageHighlight.CssGrid.toProtocolRGBA();
+ }
return highlightConfig;
}
@@ -259,15 +278,16 @@ SDK.OverlayModel = class extends SDK.SDKModel {
*/
nodeHighlightRequested(nodeId) {
const node = this._domModel.nodeForId(nodeId);
- if (node)
- this.dispatchEventToListeners(SDK.OverlayModel.Events.HighlightNodeRequested, node);
+ if (node) {
+ this.dispatchEventToListeners(Events.HighlightNodeRequested, node);
+ }
}
/**
* @param {function(!SDK.DOMNode)} handler
*/
static setInspectNodeHandler(handler) {
- SDK.OverlayModel._inspectNodeHandler = handler;
+ OverlayModel._inspectNodeHandler = handler;
}
/**
@@ -276,15 +296,16 @@ SDK.OverlayModel = class extends SDK.SDKModel {
*/
inspectNodeRequested(backendNodeId) {
const deferredNode = new SDK.DeferredDOMNode(this.target(), backendNodeId);
- if (SDK.OverlayModel._inspectNodeHandler) {
+ if (OverlayModel._inspectNodeHandler) {
deferredNode.resolvePromise().then(node => {
- if (node)
- SDK.OverlayModel._inspectNodeHandler(node);
+ if (node) {
+ OverlayModel._inspectNodeHandler(node);
+ }
});
} else {
Common.Revealer.reveal(deferredNode);
}
- this.dispatchEventToListeners(SDK.OverlayModel.Events.ExitedInspectMode);
+ this.dispatchEventToListeners(Events.ExitedInspectMode);
}
/**
@@ -292,22 +313,20 @@ SDK.OverlayModel = class extends SDK.SDKModel {
* @param {!Protocol.Page.Viewport} viewport
*/
screenshotRequested(viewport) {
- this.dispatchEventToListeners(SDK.OverlayModel.Events.ScreenshotRequested, viewport);
- this.dispatchEventToListeners(SDK.OverlayModel.Events.ExitedInspectMode);
+ this.dispatchEventToListeners(Events.ScreenshotRequested, viewport);
+ this.dispatchEventToListeners(Events.ExitedInspectMode);
}
/**
* @override
*/
inspectModeCanceled() {
- this.dispatchEventToListeners(SDK.OverlayModel.Events.ExitedInspectMode);
+ this.dispatchEventToListeners(Events.ExitedInspectMode);
}
-};
-
-SDK.SDKModel.register(SDK.OverlayModel, SDK.Target.Capability.DOM, true);
+}
/** @enum {symbol} */
-SDK.OverlayModel.Events = {
+export const Events = {
InspectModeWillBeToggled: Symbol('InspectModeWillBeToggled'),
ExitedInspectMode: Symbol('InspectModeExited'),
HighlightNodeRequested: Symbol('HighlightNodeRequested'),
@@ -317,40 +336,34 @@ SDK.OverlayModel.Events = {
/**
* @interface
*/
-SDK.OverlayModel.Highlighter = function() {};
-
-/** @typedef {{node: (!SDK.DOMNode|undefined),
- deferredNode: (!SDK.DeferredDOMNode|undefined),
- selectorList: (string|undefined),
- object:(!SDK.RemoteObject|undefined)}} */
-SDK.OverlayModel.HighlightData;
-
-SDK.OverlayModel.Highlighter.prototype = {
+export class Highlighter {
/**
* @param {!SDK.OverlayModel.HighlightData} data
* @param {!Protocol.Overlay.HighlightConfig} config
*/
- highlightInOverlay(data, config) {},
+ highlightInOverlay(data, config) {
+ }
/**
* @param {!Protocol.Overlay.InspectMode} mode
* @param {!Protocol.Overlay.HighlightConfig} config
* @return {!Promise}
*/
- setInspectMode(mode, config) {},
+ setInspectMode(mode, config) {
+ }
/**
* @param {!Protocol.Page.FrameId} frameId
*/
highlightFrame(frameId) {}
-};
+}
/**
- * @implements {SDK.OverlayModel.Highlighter}
+ * @implements {Highlighter}
*/
-SDK.OverlayModel.DefaultHighlighter = class {
+export class DefaultHighlighter {
/**
- * @param {!SDK.OverlayModel} model
+ * @param {!OverlayModel} model
*/
constructor(model) {
this._model = model;
@@ -366,10 +379,11 @@ SDK.OverlayModel.DefaultHighlighter = class {
const nodeId = node ? node.id : undefined;
const backendNodeId = deferredNode ? deferredNode.backendNodeId() : undefined;
const objectId = object ? object.objectId : undefined;
- if (nodeId || backendNodeId || objectId)
+ if (nodeId || backendNodeId || objectId) {
this._model._overlayAgent.highlightNode(config, nodeId, backendNodeId, objectId, selectorList);
- else
+ } else {
this._model._overlayAgent.hideHighlight();
+ }
}
/**
@@ -391,4 +405,34 @@ SDK.OverlayModel.DefaultHighlighter = class {
frameId, Common.Color.PageHighlight.Content.toProtocolRGBA(),
Common.Color.PageHighlight.ContentOutline.toProtocolRGBA());
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.OverlayModel = OverlayModel;
+
+/** @enum {symbol} */
+SDK.OverlayModel.Events = Events;
+
+/**
+ * @interface
+ */
+SDK.OverlayModel.Highlighter = Highlighter;
+
+/**
+ * @implements {Highlighter}
+ */
+SDK.OverlayModel.DefaultHighlighter = DefaultHighlighter;
+
+SDK.SDKModel.register(SDK.OverlayModel, SDK.Target.Capability.DOM, true);
+
+/** @typedef {{node: (!SDK.DOMNode|undefined),
+ deferredNode: (!SDK.DeferredDOMNode|undefined),
+ selectorList: (string|undefined),
+ object:(!SDK.RemoteObject|undefined)}} */
+SDK.OverlayModel.HighlightData; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/PaintProfiler.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/PaintProfiler.js
index c4371d596fc..7743cdb935e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/PaintProfiler.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/PaintProfiler.js
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SDK.PaintProfilerModel = class extends SDK.SDKModel {
+export class PaintProfilerModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -39,16 +39,16 @@ SDK.PaintProfilerModel = class extends SDK.SDKModel {
/**
* @param {!Array.<!SDK.PictureFragment>} fragments
- * @return {!Promise<?SDK.PaintProfilerSnapshot>}
+ * @return {!Promise<?PaintProfilerSnapshot>}
*/
async loadSnapshotFromFragments(fragments) {
const snapshotId = await this._layerTreeAgent.loadSnapshot(fragments);
- return snapshotId && new SDK.PaintProfilerSnapshot(this, snapshotId);
+ return snapshotId && new PaintProfilerSnapshot(this, snapshotId);
}
/**
* @param {string} encodedPicture
- * @return {!Promise<?SDK.PaintProfilerSnapshot>}
+ * @return {!Promise<?PaintProfilerSnapshot>}
*/
loadSnapshot(encodedPicture) {
const fragment = {x: 0, y: 0, picture: encodedPicture};
@@ -57,24 +57,17 @@ SDK.PaintProfilerModel = class extends SDK.SDKModel {
/**
* @param {string} layerId
- * @return {!Promise<?SDK.PaintProfilerSnapshot>}
+ * @return {!Promise<?PaintProfilerSnapshot>}
*/
async makeSnapshot(layerId) {
const snapshotId = await this._layerTreeAgent.makeSnapshot(layerId);
- return snapshotId && new SDK.PaintProfilerSnapshot(this, snapshotId);
+ return snapshotId && new PaintProfilerSnapshot(this, snapshotId);
}
-};
+}
-SDK.SDKModel.register(SDK.PaintProfilerModel, SDK.Target.Capability.DOM, false);
-
-/**
- * @typedef {!{x: number, y: number, picture: string}}
- */
-SDK.PictureFragment;
-
-SDK.PaintProfilerSnapshot = class {
+export class PaintProfilerSnapshot {
/**
- * @param {!SDK.PaintProfilerModel} paintProfilerModel
+ * @param {!PaintProfilerModel} paintProfilerModel
* @param {string} snapshotId
*/
constructor(paintProfilerModel, snapshotId) {
@@ -85,8 +78,9 @@ SDK.PaintProfilerSnapshot = class {
release() {
console.assert(this._refCount > 0, 'release is already called on the object');
- if (!--this._refCount)
+ if (!--this._refCount) {
this._paintProfilerModel._layerTreeAgent.releaseSnapshot(this._id);
+ }
}
addReference() {
@@ -113,23 +107,19 @@ SDK.PaintProfilerSnapshot = class {
}
/**
- * @return {!Promise<?Array<!SDK.PaintProfilerLogItem>>}
+ * @return {!Promise<?Array<!PaintProfilerLogItem>>}
*/
async commandLog() {
const log = await this._paintProfilerModel._layerTreeAgent.snapshotCommandLog(this._id);
- return log && log.map((entry, index) => new SDK.PaintProfilerLogItem(entry, index));
+ return log &&
+ log.map((entry, index) => new PaintProfilerLogItem(/** @type {!SDK.RawPaintProfilerLogItem} */ (entry), index));
}
-};
-
-/**
- * @typedef {!{method: string, params: ?Object<string, *>}}
- */
-SDK.RawPaintProfilerLogItem;
+}
/**
* @unrestricted
*/
-SDK.PaintProfilerLogItem = class {
+export class PaintProfilerLogItem {
/**
* @param {!SDK.RawPaintProfilerLogItem} rawEntry
* @param {number} commandIndex
@@ -139,4 +129,31 @@ SDK.PaintProfilerLogItem = class {
this.params = rawEntry.params;
this.commandIndex = commandIndex;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.PaintProfilerModel = PaintProfilerModel;
+
+/** @constructor */
+SDK.PaintProfilerSnapshot = PaintProfilerSnapshot;
+
+/** @constructor */
+SDK.PaintProfilerLogItem = PaintProfilerLogItem;
+
+/**
+ * @typedef {!{x: number, y: number, picture: string}}
+ */
+SDK.PictureFragment;
+
+/**
+ * @typedef {!{method: string, params: ?Object<string, *>}}
+ */
+SDK.RawPaintProfilerLogItem;
+
+SDK.SDKModel.register(PaintProfilerModel, SDK.Target.Capability.DOM, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/PerformanceMetricsModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/PerformanceMetricsModel.js
index 8eb49d48e8e..0cef26863cc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/PerformanceMetricsModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/PerformanceMetricsModel.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-SDK.PerformanceMetricsModel = class extends SDK.SDKModel {
+export default class PerformanceMetricsModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -10,8 +10,8 @@ SDK.PerformanceMetricsModel = class extends SDK.SDKModel {
super(target);
this._agent = target.performanceAgent();
- const mode = SDK.PerformanceMetricsModel.MetricMode;
- /** @type {!Map<string, !SDK.PerformanceMetricsModel.MetricMode>} */
+ const mode = MetricMode;
+ /** @type {!Map<string, !MetricMode>} */
this._metricModes = new Map([
['TaskDuration', mode.CumulativeTime], ['ScriptDuration', mode.CumulativeTime],
['LayoutDuration', mode.CumulativeTime], ['RecalcStyleDuration', mode.CumulativeTime],
@@ -51,14 +51,14 @@ SDK.PerformanceMetricsModel = class extends SDK.SDKModel {
}
let value;
switch (this._metricModes.get(metric.name)) {
- case SDK.PerformanceMetricsModel.MetricMode.CumulativeTime:
+ case MetricMode.CumulativeTime:
value = data.lastTimestamp ?
Number.constrain((metric.value - data.lastValue) * 1000 / (timestamp - data.lastTimestamp), 0, 1) :
0;
data.lastValue = metric.value;
data.lastTimestamp = timestamp;
break;
- case SDK.PerformanceMetricsModel.MetricMode.CumulativeCount:
+ case MetricMode.CumulativeCount:
value = data.lastTimestamp ?
Math.max(0, (metric.value - data.lastValue) * 1000 / (timestamp - data.lastTimestamp)) :
0;
@@ -73,12 +73,24 @@ SDK.PerformanceMetricsModel = class extends SDK.SDKModel {
}
return {metrics: metrics, timestamp: timestamp};
}
-};
+}
/** @enum {symbol} */
-SDK.PerformanceMetricsModel.MetricMode = {
+export const MetricMode = {
CumulativeTime: Symbol('CumulativeTime'),
CumulativeCount: Symbol('CumulativeCount'),
};
-SDK.SDKModel.register(SDK.PerformanceMetricsModel, SDK.Target.Capability.DOM, false);
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.PerformanceMetricsModel = PerformanceMetricsModel;
+
+/** @enum {symbol} */
+SDK.PerformanceMetricsModel.MetricMode = MetricMode;
+
+SDK.SDKModel.register(SDK.PerformanceMetricsModel, SDK.Target.Capability.DOM, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
index 4f646b23979..df9ead5bc03 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.ProfileNode = class {
+export class ProfileNode {
/**
* @param {!Protocol.Runtime.CallFrame} callFrame
*/
@@ -19,9 +19,9 @@ SDK.ProfileNode = class {
this.total = 0;
/** @type {number} */
this.id = 0;
- /** @type {?SDK.ProfileNode} */
+ /** @type {?ProfileNode} */
this.parent = null;
- /** @type {!Array<!SDK.ProfileNode>} */
+ /** @type {!Array<!ProfileNode>} */
this.children = [];
}
@@ -59,12 +59,12 @@ SDK.ProfileNode = class {
get columnNumber() {
return this.callFrame.columnNumber;
}
-};
+}
/**
* @unrestricted
*/
-SDK.ProfileTreeModel = class {
+export default class ProfileTreeModel {
/**
* @param {?SDK.Target=} target
*/
@@ -73,7 +73,7 @@ SDK.ProfileTreeModel = class {
}
/**
- * @param {!SDK.ProfileNode} root
+ * @param {!ProfileNode} root
* @protected
*/
initialize(root) {
@@ -91,22 +91,24 @@ SDK.ProfileTreeModel = class {
while (nodesToTraverse.length) {
const parent = nodesToTraverse.pop();
const depth = parent.depth + 1;
- if (depth > this.maxDepth)
+ if (depth > this.maxDepth) {
this.maxDepth = depth;
+ }
const children = parent.children;
const length = children.length;
for (let i = 0; i < length; ++i) {
const child = children[i];
child.depth = depth;
child.parent = parent;
- if (child.children.length)
+ if (child.children.length) {
nodesToTraverse.push(child);
+ }
}
}
}
/**
- * @param {!SDK.ProfileNode} root
+ * @param {!ProfileNode} root
* @return {number}
*/
_calculateTotals(root) {
@@ -131,4 +133,16 @@ SDK.ProfileTreeModel = class {
target() {
return this._target;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ProfileTreeModel = ProfileTreeModel;
+
+/** @constructor */
+SDK.ProfileNode = ProfileNode; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
index b44adf8e085..c97ff79bff8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
@@ -27,40 +27,33 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/**
- * @typedef {{object: ?SDK.RemoteObject, wasThrown: (boolean|undefined)}}
- */
-SDK.CallFunctionResult;
-/**
- * @typedef {{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties: ?Array<!SDK.RemoteObjectProperty>}}
- */
-SDK.GetPropertiesResult;
-
-SDK.RemoteObject = class {
+export default class RemoteObject {
/**
* This may not be an interface due to "instanceof SDK.RemoteObject" checks in the code.
*/
/**
* @param {*} value
- * @return {!SDK.RemoteObject}
+ * @return {!RemoteObject}
*/
static fromLocalObject(value) {
- return new SDK.LocalJSONObject(value);
+ return new LocalJSONObject(value);
}
/**
- * @param {!SDK.RemoteObject} remoteObject
+ * @param {!RemoteObject} remoteObject
* @return {string}
*/
static type(remoteObject) {
- if (remoteObject === null)
+ if (remoteObject === null) {
return 'null';
+ }
const type = typeof remoteObject;
- if (type !== 'object' && type !== 'function')
+ if (type !== 'object' && type !== 'function') {
return type;
+ }
return remoteObject.type;
}
@@ -70,21 +63,21 @@ SDK.RemoteObject = class {
* @return {string}
*/
static arrayNameFromDescription(description) {
- return description.replace(SDK.RemoteObject._descriptionLengthParenRegex, '')
- .replace(SDK.RemoteObject._descriptionLengthSquareRegex, '');
+ return description.replace(_descriptionLengthParenRegex, '').replace(_descriptionLengthSquareRegex, '');
}
/**
- * @param {!SDK.RemoteObject|!Protocol.Runtime.RemoteObject|!Protocol.Runtime.ObjectPreview} object
+ * @param {!RemoteObject|!Protocol.Runtime.RemoteObject|!Protocol.Runtime.ObjectPreview} object
* @return {number}
*/
static arrayLength(object) {
- if (object.subtype !== 'array' && object.subtype !== 'typedarray')
+ if (object.subtype !== 'array' && object.subtype !== 'typedarray') {
return 0;
+ }
// Array lengths in V8-generated descriptions switched from square brackets to parentheses.
// Both formats are checked in case the front end is dealing with an old version of V8.
- const parenMatches = object.description.match(SDK.RemoteObject._descriptionLengthParenRegex);
- const squareMatches = object.description.match(SDK.RemoteObject._descriptionLengthSquareRegex);
+ const parenMatches = object.description.match(_descriptionLengthParenRegex);
+ const squareMatches = object.description.match(_descriptionLengthSquareRegex);
return parenMatches ? parseInt(parenMatches[1], 10) : (squareMatches ? parseInt(squareMatches[1], 10) : 0);
}
@@ -96,58 +89,67 @@ SDK.RemoteObject = class {
const type = typeof object;
if (type === 'number') {
const description = String(object);
- if (object === 0 && 1 / object < 0)
- return SDK.RemoteObject.UnserializableNumber.Negative0;
- if (description === SDK.RemoteObject.UnserializableNumber.NaN ||
- description === SDK.RemoteObject.UnserializableNumber.Infinity ||
- description === SDK.RemoteObject.UnserializableNumber.NegativeInfinity)
+ if (object === 0 && 1 / object < 0) {
+ return UnserializableNumber.Negative0;
+ }
+ if (description === UnserializableNumber.NaN || description === UnserializableNumber.Infinity ||
+ description === UnserializableNumber.NegativeInfinity) {
return description;
+ }
}
- if (type === 'bigint')
+ if (type === 'bigint') {
return object + 'n';
+ }
return null;
}
/**
- * @param {!Protocol.Runtime.RemoteObject|!SDK.RemoteObject|number|string|boolean|undefined|null|bigint} object
+ * @param {!Protocol.Runtime.RemoteObject|!RemoteObject|number|string|boolean|undefined|null|bigint} object
* @return {!Protocol.Runtime.CallArgument}
*/
static toCallArgument(object) {
const type = typeof object;
- if (type === 'undefined')
+ if (type === 'undefined') {
return {};
- const unserializableDescription = SDK.RemoteObject.unserializableDescription(object);
+ }
+ const unserializableDescription = RemoteObject.unserializableDescription(object);
if (type === 'number') {
- if (unserializableDescription !== null)
+ if (unserializableDescription !== null) {
return {unserializableValue: unserializableDescription};
+ }
return {value: object};
}
- if (type === 'bigint')
+ if (type === 'bigint') {
return {unserializableValue: /** @type {!Protocol.Runtime.UnserializableValue} */ (unserializableDescription)};
- if (type === 'string' || type === 'boolean')
+ }
+ if (type === 'string' || type === 'boolean') {
return {value: object};
+ }
- if (!object)
+ if (!object) {
return {value: null};
+ }
- // The unserializableValue is a function on SDK.RemoteObject's and a simple property on
+ // The unserializableValue is a function on RemoteObject's and a simple property on
// Protocol.Runtime.RemoteObject's.
- if (object instanceof SDK.RemoteObject) {
+ if (object instanceof RemoteObject) {
const unserializableValue = object.unserializableValue();
- if (unserializableValue !== undefined)
+ if (unserializableValue !== undefined) {
return {unserializableValue: unserializableValue};
+ }
} else if (object.unserializableValue !== undefined) {
return {unserializableValue: object.unserializableValue};
}
- if (typeof object.objectId !== 'undefined')
+ if (typeof object.objectId !== 'undefined') {
return {objectId: object.objectId};
+ }
return {value: object.value};
}
/**
- * @param {!SDK.RemoteObject} object
+ * @param {!RemoteObject} object
* @param {boolean} generatePreview
* @return {!Promise<!SDK.GetPropertiesResult>}
*/
@@ -159,25 +161,29 @@ SDK.RemoteObject = class {
const accessorProperties = result[0].properties;
const ownProperties = result[1].properties;
const internalProperties = result[1].internalProperties;
- if (!ownProperties || !accessorProperties)
+ if (!ownProperties || !accessorProperties) {
return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
+ }
const propertiesMap = new Map();
const propertySymbols = [];
for (let i = 0; i < accessorProperties.length; i++) {
const property = accessorProperties[i];
- if (property.symbol)
+ if (property.symbol) {
propertySymbols.push(property);
- else
+ } else {
propertiesMap.set(property.name, property);
+ }
}
for (let i = 0; i < ownProperties.length; i++) {
const property = ownProperties[i];
- if (property.isAccessorProperty())
+ if (property.isAccessorProperty()) {
continue;
- if (property.symbol)
+ }
+ if (property.symbol) {
propertySymbols.push(property);
- else
+ } else {
propertiesMap.set(property.name, property);
+ }
}
return {
properties: propertiesMap.valuesArray().concat(propertySymbols),
@@ -324,10 +330,9 @@ SDK.RemoteObject = class {
isNode() {
return false;
}
-};
+}
-
-SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
+export class RemoteObjectImpl extends RemoteObject {
/**
* @param {!SDK.RuntimeModel} runtimeModel
* @param {string|undefined} objectId
@@ -358,22 +363,25 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
this._preview = preview;
} else {
this._description = description;
- if (!this.description && unserializableValue)
+ if (!this.description && unserializableValue) {
this._description = unserializableValue;
- if (!this._description && (typeof value !== 'object' || value === null))
+ }
+ if (!this._description && (typeof value !== 'object' || value === null)) {
this._description = value + '';
+ }
this._hasChildren = false;
if (typeof unserializableValue === 'string') {
this._unserializableValue = unserializableValue;
- if (unserializableValue === SDK.RemoteObject.UnserializableNumber.Infinity ||
- unserializableValue === SDK.RemoteObject.UnserializableNumber.NegativeInfinity ||
- unserializableValue === SDK.RemoteObject.UnserializableNumber.Negative0 ||
- unserializableValue === SDK.RemoteObject.UnserializableNumber.NaN)
+ if (unserializableValue === UnserializableNumber.Infinity ||
+ unserializableValue === UnserializableNumber.NegativeInfinity ||
+ unserializableValue === UnserializableNumber.Negative0 ||
+ unserializableValue === UnserializableNumber.NaN) {
this._value = Number(unserializableValue);
- else if (type === 'bigint' && unserializableValue.endsWith('n'))
+ } else if (type === 'bigint' && unserializableValue.endsWith('n')) {
this._value = BigInt(unserializableValue.substring(0, unserializableValue.length - 1));
- else
+ } else {
this._value = unserializableValue;
+ }
} else {
this._value = value;
@@ -489,13 +497,15 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
* @return {!Promise<!SDK.GetPropertiesResult>}
*/
async doGetProperties(ownProperties, accessorPropertiesOnly, generatePreview) {
- if (!this._objectId)
+ if (!this._objectId) {
return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
+ }
const response = await this._runtimeAgent.invoke_getProperties(
{objectId: this._objectId, ownProperties, accessorPropertiesOnly, generatePreview});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
+ }
if (response.exceptionDetails) {
this._runtimeModel.exceptionThrown(Date.now(), response.exceptionDetails);
return /** @type {!SDK.GetPropertiesResult} */ ({properties: null, internalProperties: null});
@@ -505,34 +515,38 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
for (const property of properties) {
const propertyValue = property.value ? this._runtimeModel.createRemoteObject(property.value) : null;
const propertySymbol = property.symbol ? this._runtimeModel.createRemoteObject(property.symbol) : null;
- const remoteProperty = new SDK.RemoteObjectProperty(
+ const remoteProperty = new RemoteObjectProperty(
property.name, propertyValue, !!property.enumerable, !!property.writable, !!property.isOwn,
!!property.wasThrown, propertySymbol);
if (typeof property.value === 'undefined') {
- if (property.get && property.get.type !== 'undefined')
+ if (property.get && property.get.type !== 'undefined') {
remoteProperty.getter = this._runtimeModel.createRemoteObject(property.get);
- if (property.set && property.set.type !== 'undefined')
+ }
+ if (property.set && property.set.type !== 'undefined') {
remoteProperty.setter = this._runtimeModel.createRemoteObject(property.set);
+ }
}
result.push(remoteProperty);
}
for (const property of privateProperties) {
const propertyValue = this._runtimeModel.createRemoteObject(property.value);
- const remoteProperty = new SDK.RemoteObjectProperty(
+ const remoteProperty = new RemoteObjectProperty(
property.name, propertyValue, true, true, true, false, undefined, false, undefined, true);
result.push(remoteProperty);
}
const internalPropertiesResult = [];
for (const property of internalProperties) {
- if (!property.value)
+ if (!property.value) {
continue;
- if (property.name === '[[StableObjectId]]')
+ }
+ if (property.name === '[[StableObjectId]]') {
continue;
+ }
const propertyValue = this._runtimeModel.createRemoteObject(property.value);
- internalPropertiesResult.push(new SDK.RemoteObjectProperty(
- property.name, propertyValue, true, false, undefined, undefined, undefined, true));
+ internalPropertiesResult.push(
+ new RemoteObjectProperty(property.name, propertyValue, true, false, undefined, undefined, undefined, true));
}
return {properties: result, internalProperties: internalPropertiesResult};
}
@@ -544,8 +558,9 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
* @return {!Promise<string|undefined>}
*/
async setPropertyValue(name, value) {
- if (!this._objectId)
+ if (!this._objectId) {
return `Can't set a property of non-object.`;
+ }
const response = await this._runtimeAgent.invoke_evaluate({expression: value, silent: true});
if (response[Protocol.Error] || response.exceptionDetails) {
@@ -554,13 +569,15 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
/** @type {string} */ (response.result.value));
}
- if (typeof name === 'string')
- name = SDK.RemoteObject.toCallArgument(name);
+ if (typeof name === 'string') {
+ name = RemoteObject.toCallArgument(name);
+ }
const resultPromise = this.doSetObjectPropertyValue(response.result, name);
- if (response.result.objectId)
+ if (response.result.objectId) {
this._runtimeAgent.releaseObject(response.result.objectId);
+ }
return resultPromise;
}
@@ -577,7 +594,7 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
// where property was defined; so do we.
const setPropertyValueFunction = 'function(a, b) { this[a] = b; }';
- const argv = [name, SDK.RemoteObject.toCallArgument(result)];
+ const argv = [name, RemoteObject.toCallArgument(result)];
const response = await this._runtimeAgent.invoke_callFunctionOn(
{objectId: this._objectId, functionDeclaration: setPropertyValueFunction, arguments: argv, silent: true});
const error = response[Protocol.Error];
@@ -590,18 +607,21 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
* @return {!Promise<string|undefined>}
*/
async deleteProperty(name) {
- if (!this._objectId)
+ if (!this._objectId) {
return `Can't delete a property of non-object.`;
+ }
const deletePropertyFunction = 'function(a) { delete this[a]; return !(a in this); }';
const response = await this._runtimeAgent.invoke_callFunctionOn(
{objectId: this._objectId, functionDeclaration: deletePropertyFunction, arguments: [name], silent: true});
- if (response[Protocol.Error] || response.exceptionDetails)
+ if (response[Protocol.Error] || response.exceptionDetails) {
return response[Protocol.Error] || response.result.description;
+ }
- if (!response.result.value)
+ if (!response.result.value) {
return 'Failed to delete property.';
+ }
}
/**
@@ -613,8 +633,9 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
async callFunction(functionDeclaration, args) {
const response = await this._runtimeAgent.invoke_callFunctionOn(
{objectId: this._objectId, functionDeclaration: functionDeclaration.toString(), arguments: args, silent: true});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return {object: null, wasThrown: false};
+ }
// TODO: release exceptionDetails object
return {object: this._runtimeModel.createRemoteObject(response.result), wasThrown: !!response.exceptionDetails};
}
@@ -641,8 +662,9 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
* @override
*/
release() {
- if (!this._objectId)
+ if (!this._objectId) {
return;
+ }
this._runtimeAgent.releaseObject(this._objectId);
}
@@ -651,7 +673,7 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
* @return {number}
*/
arrayLength() {
- return SDK.RemoteObject.arrayLength(this);
+ return RemoteObject.arrayLength(this);
}
/**
@@ -677,14 +699,13 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
isNode() {
return !!this._objectId && this.type === 'object' && this.subtype === 'node';
}
-};
-
+}
-SDK.ScopeRemoteObject = class extends SDK.RemoteObjectImpl {
+export class ScopeRemoteObject extends RemoteObjectImpl {
/**
* @param {!SDK.RuntimeModel} runtimeModel
* @param {string|undefined} objectId
- * @param {!SDK.ScopeRef} scopeRef
+ * @param {!ScopeRef} scopeRef
* @param {string} type
* @param {string|undefined} subtype
* @param {*} value
@@ -706,8 +727,9 @@ SDK.ScopeRemoteObject = class extends SDK.RemoteObjectImpl {
* @return {!Promise<!SDK.GetPropertiesResult>}
*/
async doGetProperties(ownProperties, accessorPropertiesOnly, generatePreview) {
- if (accessorPropertiesOnly)
+ if (accessorPropertiesOnly) {
return /** @type {!SDK.GetPropertiesResult} */ ({properties: [], internalProperties: []});
+ }
if (this._savedScopeProperties) {
// No need to reload scope variables, as the remote object never
@@ -721,8 +743,9 @@ SDK.ScopeRemoteObject = class extends SDK.RemoteObjectImpl {
if (this._scopeRef && Array.isArray(allProperties.properties)) {
this._savedScopeProperties = allProperties.properties.slice();
if (!this._scopeRef.callFrameId) {
- for (const property of this._savedScopeProperties)
+ for (const property of this._savedScopeProperties) {
property.writable = false;
+ }
}
}
return allProperties;
@@ -737,19 +760,21 @@ SDK.ScopeRemoteObject = class extends SDK.RemoteObjectImpl {
async doSetObjectPropertyValue(result, argumentName) {
const name = /** @type {string} */ (argumentName.value);
const error = await this.debuggerModel().setVariableValue(
- this._scopeRef.number, name, SDK.RemoteObject.toCallArgument(result), this._scopeRef.callFrameId);
- if (error)
+ this._scopeRef.number, name, RemoteObject.toCallArgument(result), this._scopeRef.callFrameId);
+ if (error) {
return error;
+ }
if (this._savedScopeProperties) {
for (const property of this._savedScopeProperties) {
- if (property.name === name)
+ if (property.name === name) {
property.value = this._runtimeModel.createRemoteObject(result);
+ }
}
}
}
-};
+}
-SDK.ScopeRef = class {
+export class ScopeRef {
/**
* @param {number} number
* @param {string=} callFrameId
@@ -758,38 +783,41 @@ SDK.ScopeRef = class {
this.number = number;
this.callFrameId = callFrameId;
}
-};
+}
/**
* @unrestricted
*/
-SDK.RemoteObjectProperty = class {
+export class RemoteObjectProperty {
/**
* @param {string} name
- * @param {?SDK.RemoteObject} value
+ * @param {?RemoteObject} value
* @param {boolean=} enumerable
* @param {boolean=} writable
* @param {boolean=} isOwn
* @param {boolean=} wasThrown
- * @param {?SDK.RemoteObject=} symbol
+ * @param {?RemoteObject=} symbol
* @param {boolean=} synthetic
- * @param {function(string):!Promise<?SDK.RemoteObject>=} syntheticSetter
+ * @param {function(string):!Promise<?RemoteObject>=} syntheticSetter
* @param {boolean=} isPrivate
*/
constructor(name, value, enumerable, writable, isOwn, wasThrown, symbol, synthetic, syntheticSetter, isPrivate) {
this.name = name;
- if (value !== null)
+ if (value !== null) {
this.value = value;
+ }
this.enumerable = typeof enumerable !== 'undefined' ? enumerable : true;
const isNonSyntheticOrSyntheticWritable = !synthetic || !!syntheticSetter;
this.writable = typeof writable !== 'undefined' ? writable : isNonSyntheticOrSyntheticWritable;
this.isOwn = !!isOwn;
this.wasThrown = !!wasThrown;
- if (symbol)
+ if (symbol) {
this.symbol = symbol;
+ }
this.synthetic = !!synthetic;
- if (syntheticSetter)
+ if (syntheticSetter) {
this.syntheticSetter = syntheticSetter;
+ }
this.private = !!isPrivate;
}
@@ -798,11 +826,13 @@ SDK.RemoteObjectProperty = class {
* @return {!Promise<boolean>}
*/
async setSyntheticValue(expression) {
- if (!this.syntheticSetter)
+ if (!this.syntheticSetter) {
return false;
+ }
const result = await this.syntheticSetter(expression);
- if (result)
+ if (result) {
this.value = result;
+ }
return !!result;
}
@@ -812,7 +842,7 @@ SDK.RemoteObjectProperty = class {
isAccessorProperty() {
return !!(this.getter || this.setter);
}
-};
+}
// Below is a wrapper around a local object that implements the RemoteObject interface,
// which can be used by the UI code (primarily ObjectPropertiesSection).
@@ -820,7 +850,7 @@ SDK.RemoteObjectProperty = class {
// for traversing prototypes, extracting class names via constructor, handling properties
// or functions.
-SDK.LocalJSONObject = class extends SDK.RemoteObject {
+export class LocalJSONObject extends RemoteObject {
/**
* @param {*} value
*/
@@ -829,7 +859,7 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
this._value = value;
/** @type {string} */
this._cachedDescription;
- /** @type {!Array<!SDK.RemoteObjectProperty>} */
+ /** @type {!Array<!RemoteObjectProperty>} */
this._cachedChildren;
}
@@ -854,7 +884,7 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
* @return {string|undefined}
*/
unserializableValue() {
- const unserializableDescription = SDK.RemoteObject.unserializableDescription(this._value);
+ const unserializableDescription = RemoteObject.unserializableDescription(this._value);
return unserializableDescription || undefined;
}
@@ -863,27 +893,29 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
* @return {string}
*/
get description() {
- if (this._cachedDescription)
+ if (this._cachedDescription) {
return this._cachedDescription;
+ }
/**
- * @param {!SDK.RemoteObjectProperty} property
+ * @param {!RemoteObjectProperty} property
* @return {string}
- * @this {SDK.LocalJSONObject}
+ * @this {LocalJSONObject}
*/
function formatArrayItem(property) {
return this._formatValue(property.value);
}
/**
- * @param {!SDK.RemoteObjectProperty} property
+ * @param {!RemoteObjectProperty} property
* @return {string}
- * @this {SDK.LocalJSONObject}
+ * @this {LocalJSONObject}
*/
function formatObjectItem(property) {
let name = property.name;
- if (/^\s|\s$|^$|\n/.test(name))
+ if (/^\s|\s$|^$|\n/.test(name)) {
name = '"' + name.replace(/\n/g, '\u21B5') + '"';
+ }
return name + ': ' + this._formatValue(property.value);
}
@@ -909,22 +941,24 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
}
/**
- * @param {?SDK.RemoteObject} value
+ * @param {?RemoteObject} value
* @return {string}
*/
_formatValue(value) {
- if (!value)
+ if (!value) {
return 'undefined';
+ }
const description = value.description || '';
- if (value.type === 'string')
+ if (value.type === 'string') {
return '"' + description.replace(/\n/g, '\u21B5') + '"';
+ }
return description;
}
/**
* @param {string} prefix
* @param {string} suffix
- * @param {function(!SDK.RemoteObjectProperty)} formatProperty
+ * @param {function(!RemoteObjectProperty)} formatProperty
* @return {string}
*/
_concatenate(prefix, suffix, formatProperty) {
@@ -938,8 +972,9 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
buffer += ',\u2026';
break;
}
- if (i)
+ if (i) {
buffer += ', ';
+ }
buffer += itemDescription;
}
buffer += suffix;
@@ -959,14 +994,17 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
* @return {string|undefined}
*/
get subtype() {
- if (this._value === null)
+ if (this._value === null) {
return 'null';
+ }
- if (Array.isArray(this._value))
+ if (Array.isArray(this._value)) {
return 'array';
+ }
- if (this._value instanceof Date)
+ if (this._value instanceof Date) {
return 'date';
+ }
return undefined;
}
@@ -976,8 +1014,9 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
* @return {boolean}
*/
get hasChildren() {
- if ((typeof this._value !== 'object') || (this._value === null))
+ if ((typeof this._value !== 'object') || (this._value === null)) {
return false;
+ }
return !!Object.keys(/** @type {!Object} */ (this._value)).length;
}
@@ -1007,25 +1046,28 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
}
/**
- * @return {!Array.<!SDK.RemoteObjectProperty>}
+ * @return {!Array.<!RemoteObjectProperty>}
*/
_children() {
- if (!this.hasChildren)
+ if (!this.hasChildren) {
return [];
+ }
const value = /** @type {!Object} */ (this._value);
/**
* @param {string} propName
- * @return {!SDK.RemoteObjectProperty}
+ * @return {!RemoteObjectProperty}
*/
function buildProperty(propName) {
let propValue = value[propName];
- if (!(propValue instanceof SDK.RemoteObject))
- propValue = SDK.RemoteObject.fromLocalObject(propValue);
- return new SDK.RemoteObjectProperty(propName, propValue);
+ if (!(propValue instanceof RemoteObject)) {
+ propValue = RemoteObject.fromLocalObject(propValue);
+ }
+ return new RemoteObjectProperty(propName, propValue);
}
- if (!this._cachedChildren)
+ if (!this._cachedChildren) {
this._cachedChildren = Object.keys(value).map(buildProperty);
+ }
return this._cachedChildren;
}
@@ -1055,8 +1097,10 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
wasThrown = true;
}
- return Promise.resolve(/** @type {!SDK.CallFunctionResult} */ (
- {object: SDK.RemoteObject.fromLocalObject(result), wasThrown: wasThrown}));
+ const object = RemoteObject.fromLocalObject(result);
+
+ return Promise.resolve(
+ /** @type {!SDK.CallFunctionResult} */ ({object, wasThrown}));
}
/**
@@ -1079,66 +1123,72 @@ SDK.LocalJSONObject = class extends SDK.RemoteObject {
return Promise.resolve(result);
}
-};
+}
-SDK.RemoteArray = class {
+export class RemoteArray {
/**
- * @param {!SDK.RemoteObject} object
+ * @param {!RemoteObject} object
*/
constructor(object) {
this._object = object;
}
/**
- * @param {?SDK.RemoteObject} object
- * @return {!SDK.RemoteArray}
+ * @param {?RemoteObject} object
+ * @return {!RemoteArray}
*/
static objectAsArray(object) {
- if (!object || object.type !== 'object' || (object.subtype !== 'array' && object.subtype !== 'typedarray'))
+ if (!object || object.type !== 'object' || (object.subtype !== 'array' && object.subtype !== 'typedarray')) {
throw new Error('Object is empty or not an array');
- return new SDK.RemoteArray(object);
+ }
+ return new RemoteArray(object);
}
/**
- * @param {!Array<!SDK.RemoteObject>} objects
- * @return {!Promise<!SDK.RemoteArray>}
+ * @param {!Array<!RemoteObject>} objects
+ * @return {!Promise<!RemoteArray>}
*/
static createFromRemoteObjects(objects) {
- if (!objects.length)
+ if (!objects.length) {
throw new Error('Input array is empty');
+ }
const objectArguments = [];
- for (let i = 0; i < objects.length; ++i)
- objectArguments.push(SDK.RemoteObject.toCallArgument(objects[i]));
+ for (let i = 0; i < objects.length; ++i) {
+ objectArguments.push(RemoteObject.toCallArgument(objects[i]));
+ }
return objects[0].callFunction(createArray, objectArguments).then(returnRemoteArray);
/**
* @return {!Array<*>}
*/
function createArray() {
- if (arguments.length > 1)
+ if (arguments.length > 1) {
return new Array(arguments);
+ }
return [arguments[0]];
}
/**
* @param {!SDK.CallFunctionResult} result
- * @return {!SDK.RemoteArray}
+ * @return {!RemoteArray}
*/
function returnRemoteArray(result) {
- if (result.wasThrown || !result.object)
+ if (result.wasThrown || !result.object) {
throw new Error('Call function throws exceptions or returns empty value');
- return SDK.RemoteArray.objectAsArray(result.object);
+ }
+ return RemoteArray.objectAsArray(result.object);
}
}
/**
* @param {number} index
- * @return {!Promise<!SDK.RemoteObject>}
+ * @return {!Promise<!RemoteObject>}
*/
at(index) {
- if (index < 0 || index > this._object.arrayLength())
+ if (index < 0 || index > this._object.arrayLength()) {
throw new Error('Out of range');
- return this._object.callFunction(at, [SDK.RemoteObject.toCallArgument(index)]).then(assertCallFunctionResult);
+ }
+ return this._object.callFunction(at, [RemoteObject.toCallArgument(index)]).then(assertCallFunctionResult);
/**
* @suppressReceiverCheck
@@ -1152,11 +1202,12 @@ SDK.RemoteArray = class {
/**
* @param {!SDK.CallFunctionResult} result
- * @return {!SDK.RemoteObject}
+ * @return {!RemoteObject}
*/
function assertCallFunctionResult(result) {
- if (result.wasThrown || !result.object)
+ if (result.wasThrown || !result.object) {
throw new Error('Exception in callFunction or result value is empty');
+ }
return result.object;
}
}
@@ -1169,62 +1220,65 @@ SDK.RemoteArray = class {
}
/**
- * @param {function(!SDK.RemoteObject):!Promise<T>} func
+ * @param {function(!RemoteObject):!Promise<T>} func
* @return {!Promise<!Array<T>>}
* @template T
*/
map(func) {
const promises = [];
- for (let i = 0; i < this.length(); ++i)
+ for (let i = 0; i < this.length(); ++i) {
promises.push(this.at(i).then(func));
+ }
return Promise.all(promises);
}
/**
- * @return {!SDK.RemoteObject}
+ * @return {!RemoteObject}
*/
object() {
return this._object;
}
-};
+}
-
-SDK.RemoteFunction = class {
+export class RemoteFunction {
/**
- * @param {!SDK.RemoteObject} object
+ * @param {!RemoteObject} object
*/
constructor(object) {
this._object = object;
}
/**
- * @param {?SDK.RemoteObject} object
- * @return {!SDK.RemoteFunction}
+ * @param {?RemoteObject} object
+ * @return {!RemoteFunction}
*/
static objectAsFunction(object) {
- if (!object || object.type !== 'function')
+ if (!object || object.type !== 'function') {
throw new Error('Object is empty or not a function');
- return new SDK.RemoteFunction(object);
+ }
+ return new RemoteFunction(object);
}
/**
- * @return {!Promise<!SDK.RemoteObject>}
+ * @return {!Promise<!RemoteObject>}
*/
targetFunction() {
return this._object.getOwnProperties(false /* generatePreview */).then(targetFunction.bind(this));
/**
* @param {!SDK.GetPropertiesResult} ownProperties
- * @return {!SDK.RemoteObject}
- * @this {SDK.RemoteFunction}
+ * @return {!RemoteObject}
+ * @this {RemoteFunction}
*/
function targetFunction(ownProperties) {
- if (!ownProperties.internalProperties)
+ if (!ownProperties.internalProperties) {
return this._object;
+ }
const internalProperties = ownProperties.internalProperties;
for (const property of internalProperties) {
- if (property.name === '[[TargetFunction]]')
+ if (property.name === '[[TargetFunction]]') {
return property.value;
+ }
}
return this._object;
}
@@ -1237,9 +1291,9 @@ SDK.RemoteFunction = class {
return this.targetFunction().then(functionDetails.bind(this));
/**
- * @param {!SDK.RemoteObject} targetFunction
+ * @param {!RemoteObject} targetFunction
* @return {!Promise<?SDK.DebuggerModel.FunctionDetails>}
- * @this {SDK.RemoteFunction}
+ * @this {RemoteFunction}
*/
function functionDetails(targetFunction) {
const boundReleaseFunctionDetails =
@@ -1248,44 +1302,89 @@ SDK.RemoteFunction = class {
}
/**
- * @param {?SDK.RemoteObject} targetFunction
+ * @param {?RemoteObject} targetFunction
* @param {?SDK.DebuggerModel.FunctionDetails} functionDetails
* @return {?SDK.DebuggerModel.FunctionDetails}
*/
function releaseTargetFunction(targetFunction, functionDetails) {
- if (targetFunction)
+ if (targetFunction) {
targetFunction.release();
+ }
return functionDetails;
}
}
/**
- * @return {!SDK.RemoteObject}
+ * @return {!RemoteObject}
*/
object() {
return this._object;
}
-};
+}
/**
* @const
* @type {!RegExp}
*/
-SDK.RemoteObject._descriptionLengthParenRegex = /\(([0-9]+)\)/;
+export const _descriptionLengthParenRegex = /\(([0-9]+)\)/;
/**
* @const
* @type {!RegExp}
*/
-SDK.RemoteObject._descriptionLengthSquareRegex = /\[([0-9]+)\]/;
+export const _descriptionLengthSquareRegex = /\[([0-9]+)\]/;
/**
* @const
* @enum {!Protocol.Runtime.UnserializableValue}
*/
-SDK.RemoteObject.UnserializableNumber = {
+export const UnserializableNumber = {
Negative0: /** @type {!Protocol.Runtime.UnserializableValue} */ ('-0'),
NaN: /** @type {!Protocol.Runtime.UnserializableValue} */ ('NaN'),
Infinity: /** @type {!Protocol.Runtime.UnserializableValue} */ ('Infinity'),
NegativeInfinity: /** @type {!Protocol.Runtime.UnserializableValue} */ ('-Infinity')
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.RemoteObject = RemoteObject;
+
+SDK.RemoteObject._descriptionLengthParenRegex = _descriptionLengthParenRegex;
+SDK.RemoteObject._descriptionLengthSquareRegex = _descriptionLengthSquareRegex;
+SDK.RemoteObject.UnserializableNumber = UnserializableNumber;
+
+/** @constructor */
+SDK.RemoteObjectImpl = RemoteObjectImpl;
+
+/** @constructor */
+SDK.ScopeRemoteObject = ScopeRemoteObject;
+
+/** @constructor */
+SDK.ScopeRef = ScopeRef;
+
+/** @constructor */
+SDK.RemoteObjectProperty = RemoteObjectProperty;
+
+/** @constructor */
+SDK.LocalJSONObject = LocalJSONObject;
+
+/** @constructor */
+SDK.RemoteArray = RemoteArray;
+
+/** @constructor */
+SDK.RemoteFunction = RemoteFunction;
+
+/**
+ * @typedef {{object: ?RemoteObject, wasThrown: (boolean|undefined)}}
+ */
+SDK.CallFunctionResult;
+
+/**
+ * @typedef {{properties: ?Array<!RemoteObjectProperty>, internalProperties: ?Array<!RemoteObjectProperty>}}
+ */
+SDK.GetPropertiesResult; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Resource.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
index 10a265725a3..df5cac5b29f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
@@ -29,7 +29,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-SDK.Resource = class {
+export default class Resource {
/**
* @param {!SDK.ResourceTreeModel} resourceTreeModel
* @param {?SDK.NetworkRequest} request
@@ -57,18 +57,21 @@ SDK.Resource = class {
this._contentSize = contentSize;
/** @type {?string} */ this._content;
+ /** @type {?string} */ this._contentLoadError;
/** @type {boolean} */ this._contentEncoded;
this._pendingContentCallbacks = [];
- if (this._request && !this._request.finished)
+ if (this._request && !this._request.finished) {
this._request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._requestFinished, this);
+ }
}
/**
* @return {?Date}
*/
lastModified() {
- if (this._lastModified || !this._request)
+ if (this._lastModified || !this._request) {
return this._lastModified;
+ }
const lastModifiedHeader = this._request.responseLastModified();
const date = lastModifiedHeader ? new Date(lastModifiedHeader) : null;
this._lastModified = date && date.isValid() ? date : null;
@@ -79,8 +82,9 @@ SDK.Resource = class {
* @return {?number}
*/
contentSize() {
- if (typeof this._contentSize === 'number' || !this._request)
+ if (typeof this._contentSize === 'number' || !this._request) {
return this._contentSize;
+ }
return this._request.resourceSize;
}
@@ -172,8 +176,9 @@ SDK.Resource = class {
* @return {!Common.ResourceType}
*/
contentType() {
- if (this.resourceType() === Common.resourceTypes.Document && this.mimeType.indexOf('javascript') !== -1)
+ if (this.resourceType() === Common.resourceTypes.Document && this.mimeType.indexOf('javascript') !== -1) {
return Common.resourceTypes.Script;
+ }
return this.resourceType();
}
@@ -188,17 +193,19 @@ SDK.Resource = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
- if (typeof this._content !== 'undefined')
- return Promise.resolve(this._content);
+ if (typeof this._content !== 'undefined') {
+ return Promise.resolve({content: /** @type {string} */ (this._content), isEncoded: this._contentEncoded});
+ }
let callback;
const promise = new Promise(fulfill => callback = fulfill);
this._pendingContentCallbacks.push(callback);
- if (!this._request || this._request.finished)
+ if (!this._request || this._request.finished) {
this._innerRequestContent();
+ }
return promise;
}
@@ -217,10 +224,12 @@ SDK.Resource = class {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- if (!this.frameId)
+ if (!this.frameId) {
return [];
- if (this.request)
+ }
+ if (this.request) {
return this.request.searchInContent(query, caseSensitive, isRegex);
+ }
const result = await this._resourceTreeModel.target().pageAgent().searchInResource(
this.frameId, this.url, query, caseSensitive, isRegex);
return result || [];
@@ -230,38 +239,54 @@ SDK.Resource = class {
* @param {!Element} image
*/
async populateImageSource(image) {
- const content = await this.requestContent();
+ const {content} = await this.requestContent();
const encoded = this._contentEncoded;
image.src = Common.ContentProvider.contentAsDataURL(content, this._mimeType, encoded) || this._url;
}
_requestFinished() {
this._request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._requestFinished, this);
- if (this._pendingContentCallbacks.length)
+ if (this._pendingContentCallbacks.length) {
this._innerRequestContent();
+ }
}
async _innerRequestContent() {
- if (this._contentRequested)
+ if (this._contentRequested) {
return;
+ }
this._contentRequested = true;
+ /** @type {!Common.DeferredContent} */
+ let loadResult;
if (this.request) {
const contentData = await this.request.contentData();
this._content = contentData.content;
this._contentEncoded = contentData.encoded;
+ loadResult = {content: /** @type{string} */ (contentData.content), isEncoded: contentData.encoded};
} else {
const response = await this._resourceTreeModel.target().pageAgent().invoke_getResourceContent(
{frameId: this.frameId, url: this.url});
- this._content = response[Protocol.Error] ? null : response.content;
+ if (response[Protocol.Error]) {
+ this._contentLoadError = response[Protocol.Error];
+ this._content = null;
+ loadResult = {error: response[Protocol.Error], isEncoded: false};
+ } else {
+ this._content = response.content;
+ this._contentLoadError = null;
+ loadResult = {content: response.content, isEncoded: response.base64Encoded};
+ }
this._contentEncoded = response.base64Encoded;
}
- if (this._content === null)
+ if (this._content === null) {
this._contentEncoded = false;
+ }
+
+ for (const callback of this._pendingContentCallbacks.splice(0)) {
+ callback(loadResult);
+ }
- for (const callback of this._pendingContentCallbacks.splice(0))
- callback(this._content);
delete this._contentRequested;
}
@@ -269,10 +294,12 @@ SDK.Resource = class {
* @return {boolean}
*/
hasTextContent() {
- if (this._type.isTextType())
+ if (this._type.isTextType()) {
return true;
- if (this._type === Common.resourceTypes.Other)
+ }
+ if (this._type === Common.resourceTypes.Other) {
return !!this._content && !this._contentEncoded;
+ }
return false;
}
@@ -282,4 +309,13 @@ SDK.Resource = class {
frame() {
return this._resourceTreeModel.frameForId(this._frameId);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.Resource = Resource;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
index f465d82f485..01d14df9989 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-SDK.ResourceTreeModel = class extends SDK.SDKModel {
+export default class ResourceTreeModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -47,13 +47,13 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
target.registerPageDispatcher(new SDK.PageDispatcher(this));
- /** @type {!Map<string, !SDK.ResourceTreeFrame>} */
+ /** @type {!Map<string, !ResourceTreeFrame>} */
this._frames = new Map();
this._cachedResourcesProcessed = false;
this._pendingReloadOptions = null;
this._reloadSuspensionCount = 0;
this._isInterstitialShowing = false;
- /** @type {?SDK.ResourceTreeFrame} */
+ /** @type {?ResourceTreeFrame} */
this.mainFrame = null;
this._agent.getResourceTree().then(this._processCachedResources.bind(this));
@@ -61,23 +61,25 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
/**
* @param {!SDK.NetworkRequest} request
- * @return {?SDK.ResourceTreeFrame}
+ * @return {?ResourceTreeFrame}
*/
static frameForRequest(request) {
const networkManager = SDK.NetworkManager.forRequest(request);
- const resourceTreeModel = networkManager ? networkManager.target().model(SDK.ResourceTreeModel) : null;
- if (!resourceTreeModel)
+ const resourceTreeModel = networkManager ? networkManager.target().model(ResourceTreeModel) : null;
+ if (!resourceTreeModel) {
return null;
+ }
return resourceTreeModel.frameForId(request.frameId);
}
/**
- * @return {!Array.<!SDK.ResourceTreeFrame>}
+ * @return {!Array.<!ResourceTreeFrame>}
*/
static frames() {
let result = [];
- for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel))
+ for (const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)) {
result = result.concat(resourceTreeModel._frames.valuesArray());
+ }
return result;
}
@@ -86,11 +88,12 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
* @return {?SDK.Resource}
*/
static resourceForURL(url) {
- for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
+ for (const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)) {
const mainFrame = resourceTreeModel.mainFrame;
const result = mainFrame ? mainFrame.resourceForURL(url) : null;
- if (result)
+ if (result) {
return result;
+ }
}
return null;
}
@@ -100,9 +103,10 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
* @param {string=} scriptToEvaluateOnLoad
*/
static reloadAllPages(bypassCache, scriptToEvaluateOnLoad) {
- for (const resourceTreeModel of SDK.targetManager.models(SDK.ResourceTreeModel)) {
- if (!resourceTreeModel.target().parentTarget())
+ for (const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)) {
+ if (!resourceTreeModel.target().parentTarget()) {
resourceTreeModel.reloadPage(bypassCache, scriptToEvaluateOnLoad);
+ }
}
}
@@ -118,7 +122,7 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
*/
_processCachedResources(mainFramePayload) {
if (mainFramePayload) {
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillLoadCachedResources);
+ this.dispatchEventToListeners(Events.WillLoadCachedResources);
this._addFramesRecursively(null, mainFramePayload);
this.target().setInspectedURL(mainFramePayload.frame.url);
}
@@ -128,7 +132,7 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
runtimeModel.setExecutionContextComparator(this._executionContextComparator.bind(this));
runtimeModel.fireExecutionContextOrderChanged();
}
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this);
+ this.dispatchEventToListeners(Events.CachedResourcesLoaded, this);
}
/**
@@ -146,14 +150,15 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
}
/**
- * @param {!SDK.ResourceTreeFrame} frame
+ * @param {!ResourceTreeFrame} frame
* @param {boolean=} aboutToNavigate
*/
_addFrame(frame, aboutToNavigate) {
this._frames.set(frame.id, frame);
- if (frame.isMainFrame())
+ if (frame.isMainFrame()) {
this.mainFrame = frame;
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.FrameAdded, frame);
+ }
+ this.dispatchEventToListeners(Events.FrameAdded, frame);
this._updateSecurityOrigins();
}
@@ -161,19 +166,22 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
* @param {!Protocol.Page.FrameId} frameId
* @param {?Protocol.Page.FrameId} parentFrameId
* @param {!Protocol.Runtime.StackTrace=} stackTrace
- * @return {?SDK.ResourceTreeFrame}
+ * @return {?ResourceTreeFrame}
*/
_frameAttached(frameId, parentFrameId, stackTrace) {
const parentFrame = parentFrameId ? (this._frames.get(parentFrameId) || null) : null;
// Do nothing unless cached resource tree is processed - it will overwrite everything.
- if (!this._cachedResourcesProcessed && parentFrame)
+ if (!this._cachedResourcesProcessed && parentFrame) {
return null;
- if (this._frames.has(frameId))
+ }
+ if (this._frames.has(frameId)) {
return null;
+ }
- const frame = new SDK.ResourceTreeFrame(this, parentFrame, frameId, null, stackTrace || null);
- if (parentFrameId && !parentFrame)
+ const frame = new ResourceTreeFrame(this, parentFrame, frameId, null, stackTrace || null);
+ if (parentFrameId && !parentFrame) {
frame._crossTargetParentFrameId = parentFrameId;
+ }
if (frame.isMainFrame() && this.mainFrame) {
// Navigation to the new backend process.
this._frameDetached(this.mainFrame.id);
@@ -188,8 +196,9 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
_frameNavigated(framePayload) {
const parentFrame = framePayload.parentId ? (this._frames.get(framePayload.parentId) || null) : null;
// Do nothing unless cached resource tree is processed - it will overwrite everything.
- if (!this._cachedResourcesProcessed && parentFrame)
+ if (!this._cachedResourcesProcessed && parentFrame) {
return;
+ }
let frame = this._frames.get(framePayload.id);
if (!frame) {
// Simulate missed "frameAttached" for a main frame navigation to the new backend process.
@@ -197,20 +206,23 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
console.assert(frame);
}
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.FrameWillNavigate, frame);
+ this.dispatchEventToListeners(Events.FrameWillNavigate, frame);
frame._navigate(framePayload);
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.FrameNavigated, frame);
+ this.dispatchEventToListeners(Events.FrameNavigated, frame);
- if (frame.isMainFrame())
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.MainFrameNavigated, frame);
+ if (frame.isMainFrame()) {
+ this.dispatchEventToListeners(Events.MainFrameNavigated, frame);
+ }
// Fill frame with retained resources (the ones loaded using new loader).
const resources = frame.resources();
- for (let i = 0; i < resources.length; ++i)
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.ResourceAdded, resources[i]);
+ for (let i = 0; i < resources.length; ++i) {
+ this.dispatchEventToListeners(Events.ResourceAdded, resources[i]);
+ }
- if (frame.isMainFrame())
+ if (frame.isMainFrame()) {
this.target().setInspectedURL(frame.url);
+ }
this._updateSecurityOrigins();
}
@@ -219,17 +231,20 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
*/
_frameDetached(frameId) {
// Do nothing unless cached resource tree is processed - it will overwrite everything.
- if (!this._cachedResourcesProcessed)
+ if (!this._cachedResourcesProcessed) {
return;
+ }
const frame = this._frames.get(frameId);
- if (!frame)
+ if (!frame) {
return;
+ }
- if (frame.parentFrame)
+ if (frame.parentFrame) {
frame.parentFrame._removeChildFrame(frame);
- else
+ } else {
frame._remove();
+ }
this._updateSecurityOrigins();
}
@@ -237,33 +252,39 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
* @param {!Common.Event} event
*/
_onRequestFinished(event) {
- if (!this._cachedResourcesProcessed)
+ if (!this._cachedResourcesProcessed) {
return;
+ }
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
- if (request.failed || request.resourceType() === Common.resourceTypes.XHR)
+ if (request.failed || request.resourceType() === Common.resourceTypes.XHR) {
return;
+ }
const frame = this._frames.get(request.frameId);
- if (frame)
+ if (frame) {
frame._addRequest(request);
+ }
}
/**
* @param {!Common.Event} event
*/
_onRequestUpdateDropped(event) {
- if (!this._cachedResourcesProcessed)
+ if (!this._cachedResourcesProcessed) {
return;
+ }
const frameId = event.data.frameId;
const frame = this._frames.get(frameId);
- if (!frame)
+ if (!frame) {
return;
+ }
const url = event.data.url;
- if (frame._resourcesMap[url])
+ if (frame._resourcesMap[url]) {
return;
+ }
const resource = new SDK.Resource(
this, null, url, frame.url, frameId, event.data.loaderId, Common.resourceTypes[event.data.resourceType],
@@ -273,7 +294,7 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
/**
* @param {!Protocol.Page.FrameId} frameId
- * @return {!SDK.ResourceTreeFrame}
+ * @return {!ResourceTreeFrame}
*/
frameForId(frameId) {
return this._frames.get(frameId);
@@ -284,13 +305,14 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
* @return {boolean}
*/
forAllResources(callback) {
- if (this.mainFrame)
+ if (this.mainFrame) {
return this.mainFrame._callForFrameResources(callback);
+ }
return false;
}
/**
- * @return {!Array<!SDK.ResourceTreeFrame>}
+ * @return {!Array<!ResourceTreeFrame>}
*/
frames() {
return this._frames.valuesArray();
@@ -306,18 +328,20 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
}
/**
- * @param {?SDK.ResourceTreeFrame} parentFrame
+ * @param {?ResourceTreeFrame} parentFrame
* @param {!Protocol.Page.FrameResourceTree} frameTreePayload
*/
_addFramesRecursively(parentFrame, frameTreePayload) {
const framePayload = frameTreePayload.frame;
- const frame = new SDK.ResourceTreeFrame(this, parentFrame, framePayload.id, framePayload, null);
- if (!parentFrame && framePayload.parentId)
+ const frame = new ResourceTreeFrame(this, parentFrame, framePayload.id, framePayload, null);
+ if (!parentFrame && framePayload.parentId) {
frame._crossTargetParentFrameId = framePayload.parentId;
+ }
this._addFrame(frame);
- for (let i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
+ for (let i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i) {
this._addFramesRecursively(frame, frameTreePayload.childFrames[i]);
+ }
for (let i = 0; i < frameTreePayload.resources.length; ++i) {
const subresource = frameTreePayload.resources[i];
@@ -356,8 +380,9 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
resumeReload() {
this._reloadSuspensionCount--;
console.assert(this._reloadSuspensionCount >= 0, 'Unbalanced call to ResourceTreeModel.resumeReload()');
- if (!this._reloadSuspensionCount && this._pendingReloadOptions)
+ if (!this._reloadSuspensionCount && this._pendingReloadOptions) {
this.reloadPage.apply(this, this._pendingReloadOptions);
+ }
}
/**
@@ -366,14 +391,15 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
*/
reloadPage(bypassCache, scriptToEvaluateOnLoad) {
// Only dispatch PageReloadRequested upon first reload request to simplify client logic.
- if (!this._pendingReloadOptions)
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.PageReloadRequested, this);
+ if (!this._pendingReloadOptions) {
+ this.dispatchEventToListeners(Events.PageReloadRequested, this);
+ }
if (this._reloadSuspensionCount) {
this._pendingReloadOptions = [bypassCache, scriptToEvaluateOnLoad];
return;
}
this._pendingReloadOptions = null;
- this.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage);
+ this.dispatchEventToListeners(Events.WillReloadPage);
this._agent.reload(bypassCache, scriptToEvaluateOnLoad);
}
@@ -386,12 +412,13 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
}
/**
- * @return {!Promise<?{currentIndex: number, entries: !Protocol.Page.NavigationEntry}>}
+ * @return {!Promise<?{currentIndex: number, entries: !Array<!Protocol.Page.NavigationEntry>}>}
*/
async navigationHistory() {
const response = await this._agent.invoke_getNavigationHistory({});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return null;
+ }
return {currentIndex: response.currentIndex, entries: response.entries};
}
@@ -407,8 +434,9 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
*/
async fetchAppManifest() {
const response = await this._agent.invoke_getAppManifest({});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return {url: response.url, data: null, errors: []};
+ }
return {url: response.url, data: response.data || null, errors: response.errors};
}
@@ -427,8 +455,8 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
*/
_executionContextComparator(a, b) {
/**
- * @param {!SDK.ResourceTreeFrame} frame
- * @return {!Array<!SDK.ResourceTreeFrame>}
+ * @param {!ResourceTreeFrame} frame
+ * @return {!Array<!ResourceTreeFrame>}
*/
function framePath(frame) {
let currentFrame = frame;
@@ -440,8 +468,9 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
return parents.reverse();
}
- if (a.target() !== b.target())
+ if (a.target() !== b.target()) {
return SDK.ExecutionContext.comparator(a, b);
+ }
const framesA = a.frameId ? framePath(this.frameForId(a.frameId)) : [];
const framesB = b.frameId ? framePath(this.frameForId(b.frameId)) : [];
@@ -454,14 +483,17 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
break;
}
}
- if (!frameA && frameB)
+ if (!frameA && frameB) {
return -1;
+ }
- if (!frameB && frameA)
+ if (!frameB && frameA) {
return 1;
+ }
- if (frameA && frameB)
+ if (frameA && frameB) {
return frameA.id.localeCompare(frameB.id);
+ }
return SDK.ExecutionContext.comparator(a, b);
}
@@ -477,8 +509,9 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
let unreachableMainSecurityOrigin = null;
for (const frame of this._frames.values()) {
const origin = frame.securityOrigin;
- if (!origin)
+ if (!origin) {
continue;
+ }
securityOrigins.add(origin);
if (frame.isMainFrame()) {
@@ -510,22 +543,10 @@ SDK.ResourceTreeModel = class extends SDK.SDKModel {
const data = this._getSecurityOriginData();
return data.mainSecurityOrigin || data.unreachableMainSecurityOrigin;
}
-};
-
-SDK.SDKModel.register(SDK.ResourceTreeModel, SDK.Target.Capability.DOM, true);
-
-
-/**
- * @typedef {{
- * securityOrigins: !Set<string>,
- * mainSecurityOrigin: ?string,
- * unreachableMainSecurityOrigin: ?string
- * }}
- */
-SDK.ResourceTreeModel.SecurityOriginData;
+}
/** @enum {symbol} */
-SDK.ResourceTreeModel.Events = {
+export const Events = {
FrameAdded: Symbol('FrameAdded'),
FrameNavigated: Symbol('FrameNavigated'),
FrameDetached: Symbol('FrameDetached'),
@@ -544,14 +565,13 @@ SDK.ResourceTreeModel.Events = {
InterstitialHidden: Symbol('InterstitialHidden')
};
-
/**
* @unrestricted
*/
-SDK.ResourceTreeFrame = class {
+export class ResourceTreeFrame {
/**
- * @param {!SDK.ResourceTreeModel} model
- * @param {?SDK.ResourceTreeFrame} parentFrame
+ * @param {!ResourceTreeModel} model
+ * @param {?ResourceTreeFrame} parentFrame
* @param {!Protocol.Page.FrameId} frameId
* @param {?Protocol.Page.Frame} payload
* @param {?Protocol.Runtime.StackTrace} creationStackTrace
@@ -575,7 +595,7 @@ SDK.ResourceTreeFrame = class {
this._creationStackTrace = creationStackTrace;
/**
- * @type {!Array.<!SDK.ResourceTreeFrame>}
+ * @type {!Array.<!ResourceTreeFrame>}
*/
this._childFrames = [];
@@ -584,8 +604,9 @@ SDK.ResourceTreeFrame = class {
*/
this._resourcesMap = {};
- if (this._parentFrame)
+ if (this._parentFrame) {
this._parentFrame._childFrames.push(this);
+ }
}
@@ -602,12 +623,13 @@ SDK.ResourceTreeFrame = class {
const mainResource = this._resourcesMap[this._url];
this._resourcesMap = {};
this._removeChildFrames();
- if (mainResource && mainResource.loaderId === this._loaderId)
+ if (mainResource && mainResource.loaderId === this._loaderId) {
this.addResource(mainResource);
+ }
}
/**
- * @return {!SDK.ResourceTreeModel}
+ * @return {!ResourceTreeModel}
*/
resourceTreeModel() {
return this._model;
@@ -656,30 +678,33 @@ SDK.ResourceTreeFrame = class {
}
/**
- * @return {?SDK.ResourceTreeFrame}
+ * @return {?ResourceTreeFrame}
*/
get parentFrame() {
return this._parentFrame;
}
/**
- * @return {!Array.<!SDK.ResourceTreeFrame>}
+ * @return {!Array.<!ResourceTreeFrame>}
*/
get childFrames() {
return this._childFrames;
}
/**
- * @return {?SDK.ResourceTreeFrame}
+ * @return {?ResourceTreeFrame}
*/
crossTargetParentFrame() {
- if (!this._crossTargetParentFrameId)
+ if (!this._crossTargetParentFrameId) {
return null;
- if (!this._model.target().parentTarget())
+ }
+ if (!this._model.target().parentTarget()) {
return null;
- const parentModel = this._model.target().parentTarget().model(SDK.ResourceTreeModel);
- if (!parentModel)
+ }
+ const parentModel = this._model.target().parentTarget().model(ResourceTreeModel);
+ if (!parentModel) {
return null;
+ }
// Note that parent model has already processed cached resources:
// - when parent target was created, we issued getResourceTree call;
// - strictly after we issued setAutoAttach call;
@@ -697,8 +722,9 @@ SDK.ResourceTreeFrame = class {
let stackTrace = this._creationStackTrace;
while (stackTrace) {
const foundEntry = stackTrace.callFrames.find(searchFn);
- if (foundEntry)
+ if (foundEntry) {
return foundEntry;
+ }
stackTrace = this.parent;
}
return null;
@@ -723,7 +749,7 @@ SDK.ResourceTreeFrame = class {
}
/**
- * @param {!SDK.ResourceTreeFrame} frame
+ * @param {!ResourceTreeFrame} frame
*/
_removeChildFrame(frame) {
this._childFrames.remove(frame);
@@ -733,14 +759,15 @@ SDK.ResourceTreeFrame = class {
_removeChildFrames() {
const frames = this._childFrames;
this._childFrames = [];
- for (let i = 0; i < frames.length; ++i)
+ for (let i = 0; i < frames.length; ++i) {
frames[i]._remove();
+ }
}
_remove() {
this._removeChildFrames();
this._model._frames.delete(this.id);
- this._model.dispatchEventToListeners(SDK.ResourceTreeModel.Events.FrameDetached, this);
+ this._model.dispatchEventToListeners(Events.FrameDetached, this);
}
/**
@@ -752,7 +779,7 @@ SDK.ResourceTreeFrame = class {
return;
}
this._resourcesMap[resource.url] = resource;
- this._model.dispatchEventToListeners(SDK.ResourceTreeModel.Events.ResourceAdded, resource);
+ this._model.dispatchEventToListeners(Events.ResourceAdded, resource);
}
/**
@@ -768,7 +795,7 @@ SDK.ResourceTreeFrame = class {
this._model, request, request.url(), request.documentURL, request.frameId, request.loaderId,
request.resourceType(), request.mimeType, null, null);
this._resourcesMap[resource.url] = resource;
- this._model.dispatchEventToListeners(SDK.ResourceTreeModel.Events.ResourceAdded, resource);
+ this._model.dispatchEventToListeners(Events.ResourceAdded, resource);
}
/**
@@ -776,8 +803,9 @@ SDK.ResourceTreeFrame = class {
*/
resources() {
const result = [];
- for (const url in this._resourcesMap)
+ for (const url in this._resourcesMap) {
result.push(this._resourcesMap[url]);
+ }
return result;
}
@@ -787,10 +815,12 @@ SDK.ResourceTreeFrame = class {
*/
resourceForURL(url) {
let resource = this._resourcesMap[url] || null;
- if (resource)
+ if (resource) {
return resource;
- for (let i = 0; !resource && i < this._childFrames.length; ++i)
+ }
+ for (let i = 0; !resource && i < this._childFrames.length; ++i) {
resource = this._childFrames[i].resourceForURL(url);
+ }
return resource;
}
@@ -800,13 +830,15 @@ SDK.ResourceTreeFrame = class {
*/
_callForFrameResources(callback) {
for (const url in this._resourcesMap) {
- if (callback(this._resourcesMap[url]))
+ if (callback(this._resourcesMap[url])) {
return true;
+ }
}
for (let i = 0; i < this._childFrames.length; ++i) {
- if (this._childFrames[i]._callForFrameResources(callback))
+ if (this._childFrames[i]._callForFrameResources(callback)) {
return true;
+ }
}
return false;
}
@@ -815,26 +847,27 @@ SDK.ResourceTreeFrame = class {
* @return {string}
*/
displayName() {
- if (this.isTopFrame())
+ if (this.isTopFrame()) {
return Common.UIString('top');
+ }
const subtitle = new Common.ParsedURL(this._url).displayName;
if (subtitle) {
- if (!this._name)
+ if (!this._name) {
return subtitle;
+ }
return this._name + ' (' + subtitle + ')';
}
return Common.UIString('<iframe>');
}
-};
-
+}
/**
* @implements {Protocol.PageDispatcher}
* @unrestricted
*/
-SDK.PageDispatcher = class {
+export class PageDispatcher {
/**
- * @param {!SDK.ResourceTreeModel} resourceTreeModel
+ * @param {!ResourceTreeModel} resourceTreeModel
*/
constructor(resourceTreeModel) {
this._resourceTreeModel = resourceTreeModel;
@@ -845,7 +878,7 @@ SDK.PageDispatcher = class {
* @param {number} time
*/
domContentEventFired(time) {
- this._resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.DOMContentLoaded, time);
+ this._resourceTreeModel.dispatchEventToListeners(Events.DOMContentLoaded, time);
}
/**
@@ -854,7 +887,7 @@ SDK.PageDispatcher = class {
*/
loadEventFired(time) {
this._resourceTreeModel.dispatchEventToListeners(
- SDK.ResourceTreeModel.Events.Load, {resourceTreeModel: this._resourceTreeModel, loadTime: time});
+ Events.Load, {resourceTreeModel: this._resourceTreeModel, loadTime: time});
}
/**
@@ -865,7 +898,7 @@ SDK.PageDispatcher = class {
* @param {number} time
*/
lifecycleEvent(frameId, loaderId, name, time) {
- this._resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.LifecycleEvent, {frameId, name});
+ this._resourceTreeModel.dispatchEventToListeners(Events.LifecycleEvent, {frameId, name});
}
/**
@@ -942,7 +975,7 @@ SDK.PageDispatcher = class {
* @override
*/
frameResized() {
- this._resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.FrameResized, null);
+ this._resourceTreeModel.dispatchEventToListeners(Events.FrameResized, null);
}
/**
@@ -954,8 +987,9 @@ SDK.PageDispatcher = class {
* @param {string=} prompt
*/
javascriptDialogOpening(url, message, dialogType, hasBrowserHandler, prompt) {
- if (!hasBrowserHandler)
+ if (!hasBrowserHandler) {
this._resourceTreeModel._agent.handleJavaScriptDialog(false);
+ }
}
/**
@@ -987,7 +1021,7 @@ SDK.PageDispatcher = class {
*/
interstitialShown() {
this._resourceTreeModel._isInterstitialShowing = true;
- this._resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.InterstitialShown);
+ this._resourceTreeModel.dispatchEventToListeners(Events.InterstitialShown);
}
/**
@@ -995,7 +1029,7 @@ SDK.PageDispatcher = class {
*/
interstitialHidden() {
this._resourceTreeModel._isInterstitialShowing = false;
- this._resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.InterstitialHidden);
+ this._resourceTreeModel.dispatchEventToListeners(Events.InterstitialHidden);
}
/**
@@ -1030,4 +1064,33 @@ SDK.PageDispatcher = class {
*/
downloadWillBegin(frameId, url) {
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ResourceTreeModel = ResourceTreeModel;
+
+/** @enum {symbol} */
+SDK.ResourceTreeModel.Events = Events;
+
+/** @constructor */
+SDK.ResourceTreeFrame = ResourceTreeFrame;
+
+/** @constructor */
+SDK.PageDispatcher = PageDispatcher;
+
+/**
+ * @typedef {{
+ * securityOrigins: !Set<string>,
+ * mainSecurityOrigin: ?string,
+ * unreachableMainSecurityOrigin: ?string
+ * }}
+ */
+SDK.ResourceTreeModel.SecurityOriginData;
+
+SDK.SDKModel.register(ResourceTreeModel, SDK.Target.Capability.DOM, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
index b3779939726..8783f912235 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-SDK.RuntimeModel = class extends SDK.SDKModel {
+export default class RuntimeModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -39,22 +39,24 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
super(target);
this._agent = target.runtimeAgent();
- this.target().registerRuntimeDispatcher(new SDK.RuntimeDispatcher(this));
+ this.target().registerRuntimeDispatcher(new RuntimeDispatcher(this));
this._agent.enable();
- /** @type {!Map<number, !SDK.ExecutionContext>} */
+ /** @type {!Map<number, !ExecutionContext>} */
this._executionContextById = new Map();
- this._executionContextComparator = SDK.ExecutionContext.comparator;
+ this._executionContextComparator = ExecutionContext.comparator;
/** @type {?boolean} */
this._hasSideEffectSupport = null;
- if (Common.moduleSetting('customFormatters').get())
+ if (Common.moduleSetting('customFormatters').get()) {
this._agent.setCustomObjectFormatterEnabled(true);
+ }
Common.moduleSetting('customFormatters').addChangeListener(this._customFormattersStateChanged.bind(this));
}
/**
* @param {!SDK.RuntimeModel.EvaluationResult} response
+ * @return {boolean}
*/
static isSideEffectFailure(response) {
const exceptionDetails = !response[Protocol.Error] && response.exceptionDetails;
@@ -78,40 +80,41 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
}
/**
- * @return {!Array.<!SDK.ExecutionContext>}
+ * @return {!Array.<!ExecutionContext>}
*/
executionContexts() {
return this._executionContextById.valuesArray().sort(this.executionContextComparator());
}
/**
- * @param {function(!SDK.ExecutionContext,!SDK.ExecutionContext)} comparator
+ * @param {function(!ExecutionContext,!ExecutionContext)} comparator
*/
setExecutionContextComparator(comparator) {
this._executionContextComparator = comparator;
}
/**
- * @return {function(!SDK.ExecutionContext,!SDK.ExecutionContext)} comparator
+ * @return {function(!ExecutionContext,!ExecutionContext)} comparator
*/
executionContextComparator() {
return this._executionContextComparator;
}
/**
- * @return {?SDK.ExecutionContext}
+ * @return {?ExecutionContext}
*/
defaultExecutionContext() {
for (const context of this.executionContexts()) {
- if (context.isDefault)
+ if (context.isDefault) {
return context;
+ }
}
return null;
}
/**
* @param {!Protocol.Runtime.ExecutionContextId} id
- * @return {?SDK.ExecutionContext}
+ * @return {?ExecutionContext}
*/
executionContext(id) {
return this._executionContextById.get(id) || null;
@@ -123,9 +126,9 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
_executionContextCreated(context) {
const data = context.auxData || {isDefault: true};
const executionContext =
- new SDK.ExecutionContext(this, context.id, context.name, context.origin, data['isDefault'], data['frameId']);
+ new ExecutionContext(this, context.id, context.name, context.origin, data['isDefault'], data['frameId']);
this._executionContextById.set(executionContext.id, executionContext);
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextCreated, executionContext);
+ this.dispatchEventToListeners(Events.ExecutionContextCreated, executionContext);
}
/**
@@ -133,23 +136,25 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
*/
_executionContextDestroyed(executionContextId) {
const executionContext = this._executionContextById.get(executionContextId);
- if (!executionContext)
+ if (!executionContext) {
return;
+ }
this.debuggerModel().executionContextDestroyed(executionContext);
this._executionContextById.delete(executionContextId);
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextDestroyed, executionContext);
+ this.dispatchEventToListeners(Events.ExecutionContextDestroyed, executionContext);
}
fireExecutionContextOrderChanged() {
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextOrderChanged, this);
+ this.dispatchEventToListeners(Events.ExecutionContextOrderChanged, this);
}
_executionContextsCleared() {
this.debuggerModel().globalObjectCleared();
const contexts = this.executionContexts();
this._executionContextById.clear();
- for (let i = 0; i < contexts.length; ++i)
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextDestroyed, contexts[i]);
+ for (let i = 0; i < contexts.length; ++i) {
+ this.dispatchEventToListeners(Events.ExecutionContextDestroyed, contexts[i]);
+ }
}
/**
@@ -182,10 +187,12 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
const type = typeof value;
let unserializableValue = undefined;
const unserializableDescription = SDK.RemoteObject.unserializableDescription(value);
- if (unserializableDescription !== null)
+ if (unserializableDescription !== null) {
unserializableValue = /** @type {!Protocol.Runtime.UnserializableValue} */ (unserializableDescription);
- if (typeof unserializableValue !== 'undefined')
+ }
+ if (typeof unserializableValue !== 'undefined') {
value = undefined;
+ }
return new SDK.RemoteObjectImpl(this, undefined, type, undefined, value, unserializableValue);
}
@@ -213,8 +220,9 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
* @param {!SDK.RuntimeModel.EvaluationResult} result
*/
releaseEvaluationResult(result) {
- if (result.object)
+ if (result.object) {
result.object.release();
+ }
if (result.exceptionDetails && result.exceptionDetails.exception) {
const exception = result.exceptionDetails.exception;
const exceptionObject = this.createRemoteObject({type: exception.type, objectId: exception.objectId});
@@ -239,7 +247,7 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
* @param {string} sourceURL
* @param {boolean} persistScript
* @param {number} executionContextId
- * @return {?Promise<!SDK.RuntimeModel.CompileScriptResult>}
+ * @return {!Promise<?SDK.RuntimeModel.CompileScriptResult>}
*/
async compileScript(expression, sourceURL, persistScript, executionContextId) {
const response = await this._agent.invoke_compileScript({
@@ -294,8 +302,9 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
* @return {!Promise<!SDK.RuntimeModel.QueryObjectResult>}
*/
async queryObjects(prototype) {
- if (!prototype.objectId)
+ if (!prototype.objectId) {
return {error: 'Prototype should be an Object.'};
+ }
const response = await this._agent.invoke_queryObjects(
{prototypeObjectId: /** @type {string} */ (prototype.objectId), objectGroup: 'console'});
const error = response[Protocol.Error];
@@ -353,8 +362,9 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
*/
function didGetDetails(response) {
object.release();
- if (!response || !response.location)
+ if (!response || !response.location) {
return;
+ }
Common.Revealer.reveal(response.location);
}
object.release();
@@ -365,11 +375,11 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
*/
_copyRequested(object) {
if (!object.objectId) {
- InspectorFrontendHost.copyText(object.unserializableValue() || object.value);
+ Host.InspectorFrontendHost.copyText(object.unserializableValue() || /** @type {string} */ (object.value));
return;
}
object.callFunctionJSON(toStringForClipboard, [{value: object.subtype}])
- .then(InspectorFrontendHost.copyText.bind(InspectorFrontendHost));
+ .then(Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost));
/**
* @param {string} subtype
@@ -377,10 +387,12 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
* @suppressReceiverCheck
*/
function toStringForClipboard(subtype) {
- if (subtype === 'node')
+ if (subtype === 'node') {
return this.outerHTML;
- if (subtype && typeof this === 'undefined')
+ }
+ if (subtype && typeof this === 'undefined') {
return subtype + '';
+ }
try {
return JSON.stringify(this, null, ' ');
} catch (e) {
@@ -399,7 +411,7 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
Common.console.error(result.error);
return;
}
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.QueryObjectRequested, {objects: result.objects});
+ this.dispatchEventToListeners(Events.QueryObjectRequested, {objects: result.objects});
}
/**
@@ -410,8 +422,9 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
let text = exceptionDetails.text;
if (exceptionDetails.exception && exceptionDetails.exception.description) {
let description = exceptionDetails.exception.description;
- if (description.indexOf('\n') !== -1)
+ if (description.indexOf('\n') !== -1) {
description = description.substring(0, description.indexOf('\n'));
+ }
text += ' ' + description;
}
return text;
@@ -423,14 +436,14 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
*/
exceptionThrown(timestamp, exceptionDetails) {
const exceptionWithTimestamp = {timestamp: timestamp, details: exceptionDetails};
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExceptionThrown, exceptionWithTimestamp);
+ this.dispatchEventToListeners(Events.ExceptionThrown, exceptionWithTimestamp);
}
/**
* @param {number} exceptionId
*/
_exceptionRevoked(exceptionId) {
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExceptionRevoked, exceptionId);
+ this.dispatchEventToListeners(Events.ExceptionRevoked, exceptionId);
}
/**
@@ -450,7 +463,7 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
stackTrace: stackTrace,
context: context
};
- this.dispatchEventToListeners(SDK.RuntimeModel.Events.ConsoleAPICalled, consoleAPICall);
+ this.dispatchEventToListeners(Events.ConsoleAPICalled, consoleAPICall);
}
/**
@@ -467,10 +480,12 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
* @return {number}
*/
executionContextForStackTrace(stackTrace) {
- while (stackTrace && !stackTrace.callFrames.length)
+ while (stackTrace && !stackTrace.callFrames.length) {
stackTrace = stackTrace.parent;
- if (!stackTrace || !stackTrace.callFrames.length)
+ }
+ if (!stackTrace || !stackTrace.callFrames.length) {
return 0;
+ }
return this.executionContextIdForScriptId(stackTrace.callFrames[0].scriptId);
}
@@ -486,16 +501,17 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
*/
async checkSideEffectSupport() {
const testContext = this.executionContexts().peekLast();
- if (!testContext)
+ if (!testContext) {
return false;
+ }
// Check for a positive throwOnSideEffect response without triggering side effects.
const response = await this._agent.invoke_evaluate({
- expression: String.escapeInvalidUnicodeCharacters(SDK.RuntimeModel._sideEffectTestExpression),
+ expression: String.escapeInvalidUnicodeCharacters(_sideEffectTestExpression),
contextId: testContext.id,
throwOnSideEffect: true
});
- this._hasSideEffectSupport = SDK.RuntimeModel.isSideEffectFailure(response);
+ this._hasSideEffectSupport = RuntimeModel.isSideEffectFailure(response);
return this._hasSideEffectSupport;
}
@@ -505,9 +521,7 @@ SDK.RuntimeModel = class extends SDK.SDKModel {
terminateExecution() {
return this._agent.invoke_terminateExecution({});
}
-};
-
-SDK.SDKModel.register(SDK.RuntimeModel, SDK.Target.Capability.JS, true);
+}
/**
* This expression:
@@ -517,10 +531,10 @@ SDK.SDKModel.register(SDK.RuntimeModel, SDK.Target.Capability.JS, true);
* @const
* @type {string}
*/
-SDK.RuntimeModel._sideEffectTestExpression = '(async function(){ await 1; })()';
+export const _sideEffectTestExpression = '(async function(){ await 1; })()';
/** @enum {symbol} */
-SDK.RuntimeModel.Events = {
+export const Events = {
ExecutionContextCreated: Symbol('ExecutionContextCreated'),
ExecutionContextDestroyed: Symbol('ExecutionContextDestroyed'),
ExecutionContextChanged: Symbol('ExecutionContextChanged'),
@@ -531,62 +545,13 @@ SDK.RuntimeModel.Events = {
QueryObjectRequested: Symbol('QueryObjectRequested'),
};
-/** @typedef {{timestamp: number, details: !Protocol.Runtime.ExceptionDetails}} */
-SDK.RuntimeModel.ExceptionWithTimestamp;
-
-/** @typedef {{
- * scriptId: (Protocol.Runtime.ScriptId|undefined),
- * exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)
- * }}
- */
-SDK.RuntimeModel.CompileScriptResult;
-
-/** @typedef {{
- * expression: string,
- * objectGroup: (string|undefined),
- * includeCommandLineAPI: (boolean|undefined),
- * silent: (boolean|undefined),
- * returnByValue: (boolean|undefined),
- * generatePreview: (boolean|undefined),
- * throwOnSideEffect: (boolean|undefined),
- * timeout: (number|undefined)
- * }}
- */
-SDK.RuntimeModel.EvaluationOptions;
-
-/** @typedef {{
- * object: (!SDK.RemoteObject|undefined),
- * exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined),
- * error: (!Protocol.Error|undefined)}
- * }}
- */
-SDK.RuntimeModel.EvaluationResult;
-
-/** @typedef {{
- * objects: (!SDK.RemoteObject|undefined),
- * error: (!Protocol.Error|undefined)}
- * }}
- */
-SDK.RuntimeModel.QueryObjectResult;
-
-/**
- * @typedef {{
- * type: string,
- * args: !Array<!Protocol.Runtime.RemoteObject>,
- * executionContextId: number,
- * timestamp: number,
- * stackTrace: (!Protocol.Runtime.StackTrace|undefined)
- * }}
- */
-SDK.RuntimeModel.ConsoleAPICall;
-
/**
* @extends {Protocol.RuntimeDispatcher}
* @unrestricted
*/
-SDK.RuntimeDispatcher = class {
+export class RuntimeDispatcher {
/**
- * @param {!SDK.RuntimeModel} runtimeModel
+ * @param {!RuntimeModel} runtimeModel
*/
constructor(runtimeModel) {
this._runtimeModel = runtimeModel;
@@ -654,14 +619,14 @@ SDK.RuntimeDispatcher = class {
inspectRequested(payload, hints) {
this._runtimeModel._inspectRequested(payload, hints);
}
-};
+}
/**
* @unrestricted
*/
-SDK.ExecutionContext = class {
+export class ExecutionContext {
/**
- * @param {!SDK.RuntimeModel} runtimeModel
+ * @param {!RuntimeModel} runtimeModel
* @param {number} id
* @param {string} name
* @param {string} origin
@@ -687,8 +652,8 @@ SDK.ExecutionContext = class {
}
/**
- * @param {!SDK.ExecutionContext} a
- * @param {!SDK.ExecutionContext} b
+ * @param {!ExecutionContext} a
+ * @param {!ExecutionContext} b
* @return {number}
*/
static comparator(a, b) {
@@ -697,14 +662,18 @@ SDK.ExecutionContext = class {
* @return {number}
*/
function targetWeight(target) {
- if (!target.parentTarget())
+ if (!target.parentTarget()) {
return 5;
- if (target.type() === SDK.Target.Type.Frame)
+ }
+ if (target.type() === SDK.Target.Type.Frame) {
return 4;
- if (target.type() === SDK.Target.Type.ServiceWorker)
+ }
+ if (target.type() === SDK.Target.Type.ServiceWorker) {
return 3;
- if (target.type() === SDK.Target.Type.Worker)
+ }
+ if (target.type() === SDK.Target.Type.Worker) {
return 2;
+ }
return 1;
}
@@ -733,24 +702,29 @@ SDK.ExecutionContext = class {
break;
}
}
- if (!targetA && targetB)
+ if (!targetA && targetB) {
return -1;
+ }
- if (!targetB && targetA)
+ if (!targetB && targetA) {
return 1;
+ }
if (targetA && targetB) {
const weightDiff = targetWeight(targetA) - targetWeight(targetB);
- if (weightDiff)
+ if (weightDiff) {
return -weightDiff;
+ }
return targetA.id().localeCompare(targetB.id());
}
// Main world context should always go first.
- if (a.isDefault)
+ if (a.isDefault) {
return -1;
- if (b.isDefault)
+ }
+ if (b.isDefault) {
return +1;
+ }
return a.name.localeCompare(b.name);
}
@@ -762,21 +736,25 @@ SDK.ExecutionContext = class {
*/
evaluate(options, userGesture, awaitPromise) {
// FIXME: It will be moved to separate ExecutionContext.
- if (this.debuggerModel.selectedCallFrame())
+ if (this.debuggerModel.selectedCallFrame()) {
return this.debuggerModel.evaluateOnSelectedCallFrame(options);
+ }
// Assume backends either support both throwOnSideEffect and timeout options or neither.
const needsTerminationOptions = !!options.throwOnSideEffect || options.timeout !== undefined;
- if (!needsTerminationOptions || this.runtimeModel.hasSideEffectSupport())
+ if (!needsTerminationOptions || this.runtimeModel.hasSideEffectSupport()) {
return this._evaluateGlobal(options, userGesture, awaitPromise);
+ }
/** @type {!SDK.RuntimeModel.EvaluationResult} */
const unsupportedError = {error: 'Side-effect checks not supported by backend.'};
- if (this.runtimeModel.hasSideEffectSupport() === false)
+ if (this.runtimeModel.hasSideEffectSupport() === false) {
return Promise.resolve(unsupportedError);
+ }
return this.runtimeModel.checkSideEffectSupport().then(() => {
- if (this.runtimeModel.hasSideEffectSupport())
+ if (this.runtimeModel.hasSideEffectSupport()) {
return this._evaluateGlobal(options, userGesture, awaitPromise);
+ }
return Promise.resolve(unsupportedError);
});
}
@@ -822,7 +800,8 @@ SDK.ExecutionContext = class {
userGesture: userGesture,
awaitPromise: awaitPromise,
throwOnSideEffect: options.throwOnSideEffect,
- timeout: options.timeout
+ timeout: options.timeout,
+ disableBreaks: options.disableBreaks
});
const error = response[Protocol.Error];
@@ -853,7 +832,7 @@ SDK.ExecutionContext = class {
*/
setLabel(label) {
this._setLabel(label);
- this.runtimeModel.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextChanged, this);
+ this.runtimeModel.dispatchEventToListeners(Events.ExecutionContextChanged, this);
}
/**
@@ -871,4 +850,76 @@ SDK.ExecutionContext = class {
const parsedUrl = this.origin.asParsedURL();
this._label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : '';
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.RuntimeModel = RuntimeModel;
+
+SDK.RuntimeModel._sideEffectTestExpression = _sideEffectTestExpression;
+
+/** @enum {symbol} */
+SDK.RuntimeModel.Events = Events;
+
+/** @constructor */
+SDK.RuntimeDispatcher = RuntimeDispatcher;
+
+/** @constructor */
+SDK.ExecutionContext = ExecutionContext;
+
+/** @typedef {{
+ * scriptId: (Protocol.Runtime.ScriptId|undefined),
+ * exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)
+ * }}
+ */
+SDK.RuntimeModel.CompileScriptResult;
+
+/** @typedef {{
+ * expression: string,
+ * objectGroup: (string|undefined),
+ * includeCommandLineAPI: (boolean|undefined),
+ * silent: (boolean|undefined),
+ * returnByValue: (boolean|undefined),
+ * generatePreview: (boolean|undefined),
+ * throwOnSideEffect: (boolean|undefined),
+ * timeout: (number|undefined),
+ * disableBreaks: (boolean|undefined)
+ * }}
+ */
+SDK.RuntimeModel.EvaluationOptions;
+
+/** @typedef {{
+ * object: (!SDK.RemoteObject|undefined),
+ * exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined),
+ * error: (!Protocol.Error|undefined)}
+ * }}
+ */
+SDK.RuntimeModel.EvaluationResult;
+
+/** @typedef {{
+ * objects: (!SDK.RemoteObject|undefined),
+ * error: (!Protocol.Error|undefined)}
+ * }}
+ */
+SDK.RuntimeModel.QueryObjectResult;
+
+/**
+ * @typedef {{
+ * type: string,
+ * args: !Array<!Protocol.Runtime.RemoteObject>,
+ * executionContextId: number,
+ * timestamp: number,
+ * stackTrace: (!Protocol.Runtime.StackTrace|undefined)
+ * }}
+ */
+SDK.RuntimeModel.ConsoleAPICall;
+
+/** @typedef {{timestamp: number, details: !Protocol.Runtime.ExceptionDetails}} */
+SDK.RuntimeModel.ExceptionWithTimestamp;
+
+SDK.SDKModel.register(SDK.RuntimeModel, SDK.Target.Capability.JS, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SDKModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SDKModel.js
new file mode 100644
index 00000000000..3964134d9ae
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SDKModel.js
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+/** @type {!Map<function(new:SDK.SDKModel, !SDK.Target), !{capabilities: number, autostart: boolean}>} */
+const _registeredModels = new Map();
+
+/**
+ * @unrestricted
+ */
+export default class SDKModel extends Common.Object {
+ /**
+ * @param {!SDK.Target} target
+ */
+ constructor(target) {
+ super();
+ this._target = target;
+ }
+
+ /**
+ * @return {!SDK.Target}
+ */
+ target() {
+ return this._target;
+ }
+
+ /**
+ * Override this method to perform tasks that are required to suspend the
+ * model and that still need other models in an unsuspended state.
+ * @param {string=} reason - optionally provide a reason, the model can respond accordingly
+ * @return {!Promise}
+ */
+ preSuspendModel(reason) {
+ return Promise.resolve();
+ }
+
+ /**
+ * @param {string=} reason - optionally provide a reason, the model can respond accordingly
+ * @return {!Promise}
+ */
+ suspendModel(reason) {
+ return Promise.resolve();
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ resumeModel() {
+ return Promise.resolve();
+ }
+
+ /**
+ * Override this method to perform tasks that are required to after resuming
+ * the model and that require all models already in an unsuspended state.
+ * @return {!Promise}
+ */
+ postResumeModel() {
+ return Promise.resolve();
+ }
+
+ dispose() {
+ }
+
+ /**
+ * @param {function(new:SDKModel, !SDK.Target)} modelClass
+ * @param {number} capabilities
+ * @param {boolean} autostart
+ */
+ static register(modelClass, capabilities, autostart) {
+ _registeredModels.set(modelClass, {capabilities, autostart});
+ }
+
+ static get registeredModels() {
+ return _registeredModels;
+ }
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.SDKModel = SDKModel;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
index 6c2fecd7ff6..306a0c8914c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
@@ -5,7 +5,7 @@
/**
* @implements {Protocol.PageDispatcher}
*/
-SDK.ScreenCaptureModel = class extends SDK.SDKModel {
+export default class ScreenCaptureModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -58,8 +58,9 @@ SDK.ScreenCaptureModel = class extends SDK.SDKModel {
*/
async fetchLayoutMetrics() {
const response = await this._agent.invoke_getLayoutMetrics({});
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
return null;
+ }
return {
viewportX: response.visualViewport.pageX,
viewportY: response.visualViewport.pageY,
@@ -77,8 +78,9 @@ SDK.ScreenCaptureModel = class extends SDK.SDKModel {
*/
screencastFrame(data, metadata, sessionId) {
this._agent.screencastFrameAck(sessionId);
- if (this._onScreencastFrame)
+ if (this._onScreencastFrame) {
this._onScreencastFrame.call(null, data, metadata);
+ }
}
/**
@@ -86,8 +88,9 @@ SDK.ScreenCaptureModel = class extends SDK.SDKModel {
* @param {boolean} visible
*/
screencastVisibilityChanged(visible) {
- if (this._onScreencastVisibilityChanged)
+ if (this._onScreencastVisibilityChanged) {
this._onScreencastVisibilityChanged.call(null, visible);
+ }
}
/**
@@ -250,6 +253,15 @@ SDK.ScreenCaptureModel = class extends SDK.SDKModel {
*/
downloadWillBegin(frameId, url) {
}
-};
+}
-SDK.SDKModel.register(SDK.ScreenCaptureModel, SDK.Target.Capability.ScreenCapture, false);
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ScreenCaptureModel = ScreenCaptureModel;
+
+SDK.SDKModel.register(SDK.ScreenCaptureModel, SDK.Target.Capability.ScreenCapture, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Script.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Script.js
index 14c5d7d2f08..12862e7a6f1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Script.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Script.js
@@ -27,7 +27,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-SDK.Script = class {
+export default class Script {
/**
* @param {!SDK.DebuggerModel} debuggerModel
* @param {string} scriptId
@@ -76,16 +76,19 @@ SDK.Script = class {
let sourceURLIndex = source.lastIndexOf('//# sourceURL=');
if (sourceURLIndex === -1) {
sourceURLIndex = source.lastIndexOf('//@ sourceURL=');
- if (sourceURLIndex === -1)
+ if (sourceURLIndex === -1) {
return source;
+ }
}
const sourceURLLineIndex = source.lastIndexOf('\n', sourceURLIndex);
- if (sourceURLLineIndex === -1)
+ if (sourceURLLineIndex === -1) {
return source;
- const sourceURLLine = source.substr(sourceURLLineIndex + 1).split('\n', 1)[0];
- if (sourceURLLine.search(SDK.Script.sourceURLRegex) === -1)
+ }
+ const sourceURLLine = source.substr(sourceURLLineIndex + 1);
+ if (!sourceURLLine.match(sourceURLRegex)) {
return source;
- return source.substr(0, sourceURLLineIndex) + source.substr(sourceURLLineIndex + sourceURLLine.length + 1);
+ }
+ return source.substr(0, sourceURLLineIndex);
}
/**
@@ -135,21 +138,31 @@ SDK.Script = class {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
async requestContent() {
- if (this._source)
- return this._source;
- if (!this.scriptId)
- return '';
- const source = await this.debuggerModel.target().debuggerAgent().getScriptSource(this.scriptId);
- if (source && this.hasSourceURL)
- this._source = SDK.Script._trimSourceURLComment(source);
- else
- this._source = source || '';
- if (this._originalSource === null)
- this._originalSource = this._source;
- return this._source;
+ if (this._source) {
+ return {content: this._source, isEncoded: false};
+ }
+ if (!this.scriptId) {
+ return {error: ls`Script removed or deleted.`, isEncoded: false};
+ }
+
+ try {
+ const source = await this.debuggerModel.target().debuggerAgent().getScriptSource(this.scriptId);
+ if (source && this.hasSourceURL) {
+ this._source = SDK.Script._trimSourceURLComment(source);
+ } else {
+ this._source = source || '';
+ }
+
+ if (this._originalSource === null) {
+ this._originalSource = this._source;
+ }
+ return {content: this._source, isEncoded: false};
+ } catch (err) {
+ return {error: ls`Unable to fetch script source.`, isEncoded: false};
+ }
}
/**
@@ -157,7 +170,12 @@ SDK.Script = class {
*/
originalContentProvider() {
if (!this._originalContentProvider) {
- const lazyContent = () => this.requestContent().then(() => this._originalSource);
+ const lazyContent = () => this.requestContent().then(() => {
+ return {
+ content: this._originalSource,
+ isEncoded: false,
+ };
+ });
this._originalContentProvider =
new Common.StaticContentProvider(this.contentURL(), this.contentType(), lazyContent);
}
@@ -172,8 +190,9 @@ SDK.Script = class {
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
async searchInContent(query, caseSensitive, isRegex) {
- if (!this.scriptId)
+ if (!this.scriptId) {
return [];
+ }
const matches =
await this.debuggerModel.target().debuggerAgent().searchInContent(this.scriptId, query, caseSensitive, isRegex);
@@ -185,8 +204,9 @@ SDK.Script = class {
* @return {string}
*/
_appendSourceURLCommentIfNeeded(source) {
- if (!this.hasSourceURL)
+ if (!this.hasSourceURL) {
return source;
+ }
return source + '\n //# sourceURL=' + this.sourceURL;
}
@@ -195,7 +215,7 @@ SDK.Script = class {
* @param {function(?Protocol.Error, !Protocol.Runtime.ExceptionDetails=, !Array.<!Protocol.Debugger.CallFrame>=, !Protocol.Runtime.StackTrace=, !Protocol.Runtime.StackTraceId=, boolean=)} callback
*/
async editSource(newSource, callback) {
- newSource = SDK.Script._trimSourceURLComment(newSource);
+ newSource = Script._trimSourceURLComment(newSource);
// We append correct sourceURL to script for consistency only. It's not actually needed for things to work correctly.
newSource = this._appendSourceURLCommentIfNeeded(newSource);
@@ -212,8 +232,9 @@ SDK.Script = class {
const response = await this.debuggerModel.target().debuggerAgent().invoke_setScriptSource(
{scriptId: this.scriptId, scriptSource: newSource});
- if (!response[Protocol.Error] && !response.exceptionDetails)
+ if (!response[Protocol.Error] && !response.exceptionDetails) {
this._source = newSource;
+ }
const needsStepIn = !!response.stackChanged;
callback(
@@ -261,6 +282,24 @@ SDK.Script = class {
{scriptId: this.scriptId, positions});
return !response[Protocol.Error];
}
-};
-SDK.Script.sourceURLRegex = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
+ containsLocation(lineNumber, columnNumber) {
+ const afterStart =
+ (lineNumber === this.lineOffset && columnNumber >= this.columnOffset) || lineNumber > this.lineOffset;
+ const beforeEnd = lineNumber < this.endLine || (lineNumber === this.endLine && columnNumber <= this.endColumn);
+ return afterStart && beforeEnd;
+ }
+}
+
+export const sourceURLRegex = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/;
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.Script = Script;
+
+SDK.Script.sourceURLRegex = sourceURLRegex;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SecurityOriginManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SecurityOriginManager.js
index f4727f166d0..6ac8b113411 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SecurityOriginManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SecurityOriginManager.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.SecurityOriginManager = class extends SDK.SDKModel {
+export default class SecurityOriginManager extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
@@ -30,13 +30,15 @@ SDK.SecurityOriginManager = class extends SDK.SDKModel {
this._securityOrigins = securityOrigins;
for (const origin of oldOrigins) {
- if (!this._securityOrigins.has(origin))
- this.dispatchEventToListeners(SDK.SecurityOriginManager.Events.SecurityOriginRemoved, origin);
+ if (!this._securityOrigins.has(origin)) {
+ this.dispatchEventToListeners(Events.SecurityOriginRemoved, origin);
+ }
}
for (const origin of this._securityOrigins) {
- if (!oldOrigins.has(origin))
- this.dispatchEventToListeners(SDK.SecurityOriginManager.Events.SecurityOriginAdded, origin);
+ if (!oldOrigins.has(origin)) {
+ this.dispatchEventToListeners(Events.SecurityOriginAdded, origin);
+ }
}
}
@@ -68,19 +70,31 @@ SDK.SecurityOriginManager = class extends SDK.SDKModel {
setMainSecurityOrigin(securityOrigin, unreachableSecurityOrigin) {
this._mainSecurityOrigin = securityOrigin;
this._unreachableMainSecurityOrigin = unreachableSecurityOrigin || null;
- this.dispatchEventToListeners(SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, {
+ this.dispatchEventToListeners(Events.MainSecurityOriginChanged, {
mainSecurityOrigin: this._mainSecurityOrigin,
unreachableMainSecurityOrigin: this._unreachableMainSecurityOrigin
});
}
-};
-
-// TODO(jarhar): this is the only usage of Capability.None. Do something about it!
-SDK.SDKModel.register(SDK.SecurityOriginManager, SDK.Target.Capability.None, false);
+}
/** @enum {symbol} */
-SDK.SecurityOriginManager.Events = {
+export const Events = {
SecurityOriginAdded: Symbol('SecurityOriginAdded'),
SecurityOriginRemoved: Symbol('SecurityOriginRemoved'),
MainSecurityOriginChanged: Symbol('MainSecurityOriginChanged')
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.SecurityOriginManager = SecurityOriginManager;
+
+/** @enum {symbol} */
+SDK.SecurityOriginManager.Events = Events;
+
+// TODO(jarhar): this is the only usage of Capability.None. Do something about it!
+SDK.SDKModel.register(SDK.SecurityOriginManager, SDK.Target.Capability.None, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServerTiming.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServerTiming.js
index 8a8a12fa395..c055a47d26c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServerTiming.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServerTiming.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-SDK.ServerTiming = class {
+export default class ServerTiming {
/**
* @param {string} metric
* @param {?number} value
@@ -18,17 +18,18 @@ SDK.ServerTiming = class {
/**
* @param {!Array<!SDK.NetworkRequest.NameValue>} headers
- * @return {?Array<!SDK.ServerTiming>}
+ * @return {?Array<!ServerTiming>}
*/
static parseHeaders(headers) {
const rawServerTimingHeaders = headers.filter(item => item.name.toLowerCase() === 'server-timing');
- if (!rawServerTimingHeaders.length)
+ if (!rawServerTimingHeaders.length) {
return null;
+ }
const serverTimings = rawServerTimingHeaders.reduce((memo, header) => {
const timing = this.createFromHeaderValue(header.value);
memo.pushAll(timing.map(function(entry) {
- return new SDK.ServerTiming(
+ return new ServerTiming(
entry.name, entry.hasOwnProperty('dur') ? entry.dur : null, entry.hasOwnProperty('desc') ? entry.desc : '');
}));
return memo;
@@ -48,8 +49,9 @@ SDK.ServerTiming = class {
function consumeDelimiter(char) {
console.assert(char.length === 1);
trimLeadingWhiteSpace();
- if (valueString.charAt(0) !== char)
+ if (valueString.charAt(0) !== char) {
return false;
+ }
valueString = valueString.substring(1);
return true;
@@ -57,16 +59,18 @@ SDK.ServerTiming = class {
function consumeToken() {
// https://tools.ietf.org/html/rfc7230#appendix-B
const result = /^(?:\s*)([\w!#$%&'*+\-.^`|~]+)(?:\s*)(.*)/.exec(valueString);
- if (!result)
+ if (!result) {
return null;
+ }
valueString = result[2];
return result[1];
}
function consumeTokenOrQuotedString() {
trimLeadingWhiteSpace();
- if (valueString.charAt(0) === '"')
+ if (valueString.charAt(0) === '"') {
return consumeQuotedString();
+ }
return consumeToken();
}
@@ -97,8 +101,9 @@ SDK.ServerTiming = class {
}
function consumeExtraneous() {
const result = /([,;].*)/.exec(valueString);
- if (result)
+ if (result) {
valueString = result[1];
+ }
}
const result = [];
@@ -106,13 +111,15 @@ SDK.ServerTiming = class {
while ((name = consumeToken()) !== null) {
const entry = {name};
- if (valueString.charAt(0) === '=')
+ if (valueString.charAt(0) === '=') {
this.showWarning(ls`Deprecated syntax found. Please use: <name>;dur=<duration>;desc=<description>`);
+ }
while (consumeDelimiter(';')) {
let paramName;
- if ((paramName = consumeToken()) === null)
+ if ((paramName = consumeToken()) === null) {
continue;
+ }
paramName = paramName.toLowerCase();
const parseParameter = this.getParserForParameter(paramName);
@@ -130,8 +137,9 @@ SDK.ServerTiming = class {
continue;
}
- if (paramValue === null)
+ if (paramValue === null) {
this.showWarning(ls`No value found for parameter \"${paramName}\".`);
+ }
parseParameter.call(this, entry, paramValue);
} else {
@@ -141,12 +149,14 @@ SDK.ServerTiming = class {
}
result.push(entry);
- if (!consumeDelimiter(','))
+ if (!consumeDelimiter(',')) {
break;
+ }
}
- if (valueString.length)
+ if (valueString.length) {
this.showWarning(ls`Extraneous trailing characters.`);
+ }
return result;
}
@@ -185,4 +195,13 @@ SDK.ServerTiming = class {
static showWarning(msg) {
Common.console.warn(Common.UIString(`ServerTiming: ${msg}`));
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ServerTiming = ServerTiming;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerCacheModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerCacheModel.js
index e2fa197bc2c..c432d20e0d2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerCacheModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerCacheModel.js
@@ -5,7 +5,7 @@
* @implements {Protocol.StorageDispatcher}
* @unrestricted
*/
-SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
+export default class ServiceWorkerCacheModel extends SDK.SDKModel {
/**
* Invariant: This model can only be constructed on a ServiceWorker target.
* @param {!SDK.Target} target
@@ -14,7 +14,7 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
super(target);
target.registerStorageDispatcher(this);
- /** @type {!Map<string, !SDK.ServiceWorkerCacheModel.Cache>} */
+ /** @type {!Map<string, !Cache>} */
this._caches = new Map();
this._cacheAgent = target.cacheStorageAgent();
@@ -30,16 +30,18 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._securityOriginManager.addEventListener(
SDK.SecurityOriginManager.Events.SecurityOriginAdded, this._securityOriginAdded, this);
this._securityOriginManager.addEventListener(
SDK.SecurityOriginManager.Events.SecurityOriginRemoved, this._securityOriginRemoved, this);
- for (const securityOrigin of this._securityOriginManager.securityOrigins())
+ for (const securityOrigin of this._securityOriginManager.securityOrigins()) {
this._addOrigin(securityOrigin);
+ }
this._enabled = true;
}
@@ -52,16 +54,18 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
}
refreshCacheNames() {
- for (const cache of this._caches.values())
+ for (const cache of this._caches.values()) {
this._cacheRemoved(cache);
+ }
this._caches.clear();
const securityOrigins = this._securityOriginManager.securityOrigins();
- for (const securityOrigin of securityOrigins)
+ for (const securityOrigin of securityOrigins) {
this._loadCacheNames(securityOrigin);
+ }
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
*/
async deleteCache(cache) {
const response = await this._cacheAgent.invoke_deleteCache({cacheId: cache.cacheId});
@@ -74,21 +78,22 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
* @param {string} request
* @return {!Promise}
*/
async deleteCacheEntry(cache, request) {
const response = await this._cacheAgent.invoke_deleteEntry({cacheId: cache.cacheId, request});
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
return;
+ }
Common.console.error(Common.UIString(
'ServiceWorkerCacheAgent error deleting cache entry %s in cache: %s', cache.toString(),
response[Protocol.Error]));
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
* @param {number} skipCount
* @param {number} pageSize
* @param {string} pathFilter
@@ -99,12 +104,13 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
}
/**
- * @return {!Array.<!SDK.ServiceWorkerCacheModel.Cache>}
+ * @return {!Array.<!Cache>}
*/
caches() {
const caches = new Array();
- for (const cache of this._caches.values())
+ for (const cache of this._caches.values()) {
caches.push(cache);
+ }
return caches;
}
@@ -112,8 +118,9 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
* @override
*/
dispose() {
- for (const cache of this._caches.values())
+ for (const cache of this._caches.values()) {
this._cacheRemoved(cache);
+ }
this._caches.clear();
if (this._enabled) {
this._securityOriginManager.removeEventListener(
@@ -125,8 +132,9 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
_addOrigin(securityOrigin) {
this._loadCacheNames(securityOrigin);
- if (this._isValidSecurityOrigin(securityOrigin))
+ if (this._isValidSecurityOrigin(securityOrigin)) {
this._storageAgent.trackCacheStorageForOrigin(securityOrigin);
+ }
}
/**
@@ -140,8 +148,9 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
this._cacheRemoved(cache);
}
}
- if (this._isValidSecurityOrigin(securityOrigin))
+ if (this._isValidSecurityOrigin(securityOrigin)) {
this._storageAgent.untrackCacheStorageForOrigin(securityOrigin);
+ }
}
/**
@@ -158,8 +167,9 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
*/
async _loadCacheNames(securityOrigin) {
const caches = await this._cacheAgent.requestCacheNames(securityOrigin);
- if (!caches)
+ if (!caches) {
return;
+ }
this._updateCacheNames(securityOrigin, caches);
}
@@ -169,8 +179,8 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
*/
_updateCacheNames(securityOrigin, cachesJson) {
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
- * @this {SDK.ServiceWorkerCacheModel}
+ * @param {!Cache} cache
+ * @this {ServiceWorkerCacheModel}
*/
function deleteAndSaveOldCaches(cache) {
if (cache.securityOrigin === securityOrigin && !updatingCachesIds.has(cache.cacheId)) {
@@ -181,17 +191,17 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
/** @type {!Set<string>} */
const updatingCachesIds = new Set();
- /** @type {!Map<string, !SDK.ServiceWorkerCacheModel.Cache>} */
+ /** @type {!Map<string, !Cache>} */
const newCaches = new Map();
- /** @type {!Map<string, !SDK.ServiceWorkerCacheModel.Cache>} */
+ /** @type {!Map<string, !Cache>} */
const oldCaches = new Map();
for (const cacheJson of cachesJson) {
- const cache =
- new SDK.ServiceWorkerCacheModel.Cache(this, cacheJson.securityOrigin, cacheJson.cacheName, cacheJson.cacheId);
+ const cache = new Cache(this, cacheJson.securityOrigin, cacheJson.cacheName, cacheJson.cacheId);
updatingCachesIds.add(cache.cacheId);
- if (this._caches.has(cache.cacheId))
+ if (this._caches.has(cache.cacheId)) {
continue;
+ }
newCaches.set(cache.cacheId, cache);
this._caches.set(cache.cacheId, cache);
}
@@ -217,21 +227,21 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
*/
_cacheAdded(cache) {
- this.dispatchEventToListeners(SDK.ServiceWorkerCacheModel.Events.CacheAdded, {model: this, cache: cache});
+ this.dispatchEventToListeners(Events.CacheAdded, {model: this, cache: cache});
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
*/
_cacheRemoved(cache) {
- this.dispatchEventToListeners(SDK.ServiceWorkerCacheModel.Events.CacheRemoved, {model: this, cache: cache});
+ this.dispatchEventToListeners(Events.CacheRemoved, {model: this, cache: cache});
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
* @param {number} skipCount
* @param {number} pageSize
* @param {string} pathFilter
@@ -267,8 +277,7 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
* @override
*/
cacheStorageContentUpdated(origin, cacheName) {
- this.dispatchEventToListeners(
- SDK.ServiceWorkerCacheModel.Events.CacheStorageContentUpdated, {origin: origin, cacheName: cacheName});
+ this.dispatchEventToListeners(Events.CacheStorageContentUpdated, {origin: origin, cacheName: cacheName});
}
/**
@@ -286,12 +295,10 @@ SDK.ServiceWorkerCacheModel = class extends SDK.SDKModel {
*/
indexedDBContentUpdated(origin, databaseName, objectStoreName) {
}
-};
-
-SDK.SDKModel.register(SDK.ServiceWorkerCacheModel, SDK.Target.Capability.Storage, false);
+}
/** @enum {symbol} */
-SDK.ServiceWorkerCacheModel.Events = {
+export const Events = {
CacheAdded: Symbol('CacheAdded'),
CacheRemoved: Symbol('CacheRemoved'),
CacheStorageContentUpdated: Symbol('CacheStorageContentUpdated')
@@ -300,9 +307,9 @@ SDK.ServiceWorkerCacheModel.Events = {
/**
* @unrestricted
*/
-SDK.ServiceWorkerCacheModel.Cache = class {
+export class Cache {
/**
- * @param {!SDK.ServiceWorkerCacheModel} model
+ * @param {!ServiceWorkerCacheModel} model
* @param {string} securityOrigin
* @param {string} cacheName
* @param {string} cacheId
@@ -315,7 +322,7 @@ SDK.ServiceWorkerCacheModel.Cache = class {
}
/**
- * @param {!SDK.ServiceWorkerCacheModel.Cache} cache
+ * @param {!Cache} cache
* @return {boolean}
*/
equals(cache) {
@@ -338,4 +345,21 @@ SDK.ServiceWorkerCacheModel.Cache = class {
requestCachedResponse(url, requestHeaders) {
return this._model._cacheAgent.requestCachedResponse(this.cacheId, url, requestHeaders);
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ServiceWorkerCacheModel = ServiceWorkerCacheModel;
+
+/** @enum {symbol} */
+SDK.ServiceWorkerCacheModel.Events = Events;
+
+/** @constructor */
+SDK.ServiceWorkerCacheModel.Cache = Cache;
+
+SDK.SDKModel.register(SDK.ServiceWorkerCacheModel, SDK.Target.Capability.Storage, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerManager.js
index a5914df0493..3cc255cf37d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ServiceWorkerManager.js
@@ -31,42 +31,45 @@
/**
* @unrestricted
*/
-SDK.ServiceWorkerManager = class extends SDK.SDKModel {
+export default class ServiceWorkerManager extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
- target.registerServiceWorkerDispatcher(new SDK.ServiceWorkerDispatcher(this));
+ target.registerServiceWorkerDispatcher(new ServiceWorkerDispatcher(this));
this._lastAnonymousTargetId = 0;
this._agent = target.serviceWorkerAgent();
- /** @type {!Map.<string, !SDK.ServiceWorkerRegistration>} */
+ /** @type {!Map.<string, !ServiceWorkerRegistration>} */
this._registrations = new Map();
this.enable();
this._forceUpdateSetting = Common.settings.createSetting('serviceWorkerUpdateOnReload', false);
- if (this._forceUpdateSetting.get())
+ if (this._forceUpdateSetting.get()) {
this._forceUpdateSettingChanged();
+ }
this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this);
- new SDK.ServiceWorkerContextNamer(target, this);
+ new ServiceWorkerContextNamer(target, this);
}
enable() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._enabled = true;
this._agent.enable();
}
disable() {
- if (!this._enabled)
+ if (!this._enabled) {
return;
+ }
this._enabled = false;
this._registrations.clear();
this._agent.disable();
}
/**
- * @return {!Map.<string, !SDK.ServiceWorkerRegistration>}
+ * @return {!Map.<string, !ServiceWorkerRegistration>}
*/
registrations() {
return this._registrations;
@@ -78,21 +81,23 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
hasRegistrationForURLs(urls) {
for (const registration of this._registrations.values()) {
- if (urls.filter(url => url && url.startsWith(registration.scopeURL)).length === urls.length)
+ if (urls.filter(url => url && url.startsWith(registration.scopeURL)).length === urls.length) {
return true;
+ }
}
return false;
}
/**
* @param {string} versionId
- * @return {?SDK.ServiceWorkerVersion}
+ * @return {?ServiceWorkerVersion}
*/
findVersion(versionId) {
for (const registration of this.registrations().values()) {
const version = registration.versions.get(versionId);
- if (version)
+ if (version) {
return version;
+ }
}
return null;
}
@@ -102,16 +107,18 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
deleteRegistration(registrationId) {
const registration = this._registrations.get(registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
if (registration._isRedundant()) {
this._registrations.delete(registrationId);
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration);
+ this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
return;
}
registration._deleting = true;
- for (const version of registration.versions.values())
+ for (const version of registration.versions.values()) {
this.stopWorker(version.id);
+ }
this._unregister(registration.scopeURL);
}
@@ -120,8 +127,9 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
updateRegistration(registrationId) {
const registration = this._registrations.get(registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
this._agent.updateRegistration(registration.scopeURL);
}
@@ -131,8 +139,9 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
deliverPushMessage(registrationId, data) {
const registration = this._registrations.get(registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
this._agent.deliverPushMessage(origin, registrationId, data);
}
@@ -144,8 +153,9 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
dispatchSyncEvent(registrationId, tag, lastChance) {
const registration = this._registrations.get(registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
this._agent.dispatchSyncEvent(origin, registrationId, tag, lastChance);
}
@@ -156,8 +166,9 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
dispatchPeriodicSyncEvent(registrationId, tag) {
const registration = this._registrations.get(registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
const origin = Common.ParsedURL.extractOrigin(registration.scopeURL);
this._agent.dispatchPeriodicSyncEvent(origin, registrationId, tag);
}
@@ -204,18 +215,18 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
for (const payload of registrations) {
let registration = this._registrations.get(payload.registrationId);
if (!registration) {
- registration = new SDK.ServiceWorkerRegistration(payload);
+ registration = new ServiceWorkerRegistration(payload);
this._registrations.set(payload.registrationId, registration);
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration);
+ this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
continue;
}
registration._update(payload);
if (registration._shouldBeRemoved()) {
this._registrations.delete(registration.id);
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration);
+ this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
} else {
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration);
+ this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
}
}
}
@@ -224,21 +235,22 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
* @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerVersion>} versions
*/
_workerVersionUpdated(versions) {
- /** @type {!Set.<!SDK.ServiceWorkerRegistration>} */
+ /** @type {!Set.<!ServiceWorkerRegistration>} */
const registrations = new Set();
for (const payload of versions) {
const registration = this._registrations.get(payload.registrationId);
- if (!registration)
+ if (!registration) {
continue;
+ }
registration._updateVersion(payload);
registrations.add(registration);
}
for (const registration of registrations) {
if (registration._shouldBeRemoved()) {
this._registrations.delete(registration.id);
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration);
+ this.dispatchEventToListeners(Events.RegistrationDeleted, registration);
} else {
- this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration);
+ this.dispatchEventToListeners(Events.RegistrationUpdated, registration);
}
}
}
@@ -248,11 +260,11 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
*/
_workerErrorReported(payload) {
const registration = this._registrations.get(payload.registrationId);
- if (!registration)
+ if (!registration) {
return;
+ }
registration.errors.push(payload);
- this.dispatchEventToListeners(
- SDK.ServiceWorkerManager.Events.RegistrationErrorAdded, {registration: registration, error: payload});
+ this.dispatchEventToListeners(Events.RegistrationErrorAdded, {registration: registration, error: payload});
}
/**
@@ -265,12 +277,10 @@ SDK.ServiceWorkerManager = class extends SDK.SDKModel {
_forceUpdateSettingChanged() {
this._agent.setForceUpdateOnPageLoad(this._forceUpdateSetting.get());
}
-};
-
-SDK.SDKModel.register(SDK.ServiceWorkerManager, SDK.Target.Capability.ServiceWorker, true);
+}
/** @enum {symbol} */
-SDK.ServiceWorkerManager.Events = {
+export const Events = {
RegistrationUpdated: Symbol('RegistrationUpdated'),
RegistrationErrorAdded: Symbol('RegistrationErrorAdded'),
RegistrationDeleted: Symbol('RegistrationDeleted')
@@ -280,9 +290,9 @@ SDK.ServiceWorkerManager.Events = {
* @implements {Protocol.ServiceWorkerDispatcher}
* @unrestricted
*/
-SDK.ServiceWorkerDispatcher = class {
+export class ServiceWorkerDispatcher {
/**
- * @param {!SDK.ServiceWorkerManager} manager
+ * @param {!ServiceWorkerManager} manager
*/
constructor(manager) {
this._manager = manager;
@@ -311,14 +321,14 @@ SDK.ServiceWorkerDispatcher = class {
workerErrorReported(errorMessage) {
this._manager._workerErrorReported(errorMessage);
}
-};
+}
/**
* @unrestricted
*/
-SDK.ServiceWorkerVersion = class {
+export class ServiceWorkerVersion {
/**
- * @param {!SDK.ServiceWorkerRegistration} registration
+ * @param {!ServiceWorkerRegistration} registration
* @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload
*/
constructor(registration, payload) {
@@ -339,8 +349,9 @@ SDK.ServiceWorkerVersion = class {
this.scriptLastModified = payload.scriptLastModified;
this.scriptResponseTime = payload.scriptResponseTime;
this.controlledClients = [];
- for (let i = 0; i < payload.controlledClients.length; ++i)
+ for (let i = 0; i < payload.controlledClients.length; ++i) {
this.controlledClients.push(payload.controlledClients[i]);
+ }
this.targetId = payload.targetId || null;
}
@@ -433,20 +444,31 @@ SDK.ServiceWorkerVersion = class {
* @return {string}
*/
mode() {
- if (this.isNew() || this.isInstalling())
- return SDK.ServiceWorkerVersion.Modes.Installing;
- else if (this.isInstalled())
- return SDK.ServiceWorkerVersion.Modes.Waiting;
- else if (this.isActivating() || this.isActivated())
- return SDK.ServiceWorkerVersion.Modes.Active;
- return SDK.ServiceWorkerVersion.Modes.Redundant;
+ if (this.isNew() || this.isInstalling()) {
+ return ServiceWorkerVersion.Modes.Installing;
+ } else if (this.isInstalled()) {
+ return ServiceWorkerVersion.Modes.Waiting;
+ } else if (this.isActivating() || this.isActivated()) {
+ return ServiceWorkerVersion.Modes.Active;
+ }
+ return ServiceWorkerVersion.Modes.Redundant;
}
+}
+
+/**
+ * @type {!Object<string, string>}
+ */
+ServiceWorkerVersion.RunningStatus = {
+ [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Running]: ls`running`,
+ [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Starting]: ls`starting`,
+ [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped]: ls`stopped`,
+ [Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopping]: ls`stopping`,
};
/**
* @enum {string}
*/
-SDK.ServiceWorkerVersion.Modes = {
+ServiceWorkerVersion.Modes = {
Installing: 'installing',
Waiting: 'waiting',
Active: 'active',
@@ -456,13 +478,13 @@ SDK.ServiceWorkerVersion.Modes = {
/**
* @unrestricted
*/
-SDK.ServiceWorkerRegistration = class {
+export class ServiceWorkerRegistration {
/**
* @param {!Protocol.ServiceWorker.ServiceWorkerRegistration} payload
*/
constructor(payload) {
this._update(payload);
- /** @type {!Map.<string, !SDK.ServiceWorkerVersion>} */
+ /** @type {!Map.<string, !ServiceWorkerVersion>} */
this.versions = new Map();
this._deleting = false;
/** @type {!Array<!Protocol.ServiceWorker.ServiceWorkerErrorMessage>} */
@@ -490,25 +512,26 @@ SDK.ServiceWorkerRegistration = class {
}
/**
- * @return {!Map<string, !SDK.ServiceWorkerVersion>}
+ * @return {!Map<string, !ServiceWorkerVersion>}
*/
versionsByMode() {
- /** @type {!Map<string, !SDK.ServiceWorkerVersion>} */
+ /** @type {!Map<string, !ServiceWorkerVersion>} */
const result = new Map();
- for (const version of this.versions.values())
+ for (const version of this.versions.values()) {
result.set(version.mode(), version);
+ }
return result;
}
/**
* @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload
- * @return {!SDK.ServiceWorkerVersion}
+ * @return {!ServiceWorkerVersion}
*/
_updateVersion(payload) {
this._fingerprint = Symbol('fingerprint');
let version = this.versions.get(payload.versionId);
if (!version) {
- version = new SDK.ServiceWorkerVersion(this, payload);
+ version = new ServiceWorkerVersion(this, payload);
this.versions.set(payload.versionId, version);
return version;
}
@@ -521,8 +544,9 @@ SDK.ServiceWorkerRegistration = class {
*/
_isRedundant() {
for (const version of this.versions.values()) {
- if (!version.isStoppedAndRedundant())
+ if (!version.isStoppedAndRedundant()) {
return false;
+ }
}
return true;
}
@@ -546,25 +570,23 @@ SDK.ServiceWorkerRegistration = class {
this._fingerprint = Symbol('fingerprint');
this.errors = [];
}
-};
+}
/**
* @unrestricted
*/
-SDK.ServiceWorkerContextNamer = class {
+export class ServiceWorkerContextNamer {
/**
* @param {!SDK.Target} target
- * @param {!SDK.ServiceWorkerManager} serviceWorkerManager
+ * @param {!ServiceWorkerManager} serviceWorkerManager
*/
constructor(target, serviceWorkerManager) {
this._target = target;
this._serviceWorkerManager = serviceWorkerManager;
- /** @type {!Map<string, !SDK.ServiceWorkerVersion>} */
+ /** @type {!Map<string, !ServiceWorkerVersion>} */
this._versionByTargetId = new Map();
- serviceWorkerManager.addEventListener(
- SDK.ServiceWorkerManager.Events.RegistrationUpdated, this._registrationsUpdated, this);
- serviceWorkerManager.addEventListener(
- SDK.ServiceWorkerManager.Events.RegistrationDeleted, this._registrationsUpdated, this);
+ serviceWorkerManager.addEventListener(Events.RegistrationUpdated, this._registrationsUpdated, this);
+ serviceWorkerManager.addEventListener(Events.RegistrationDeleted, this._registrationsUpdated, this);
SDK.targetManager.addModelListener(
SDK.RuntimeModel, SDK.RuntimeModel.Events.ExecutionContextCreated, this._executionContextCreated, this);
}
@@ -578,8 +600,9 @@ SDK.ServiceWorkerContextNamer = class {
for (const registration of registrations) {
const versions = registration.versions.valuesArray();
for (const version of versions) {
- if (version.targetId)
+ if (version.targetId) {
this._versionByTargetId.set(version.targetId, version);
+ }
}
}
this._updateAllContextLabels();
@@ -591,8 +614,9 @@ SDK.ServiceWorkerContextNamer = class {
_executionContextCreated(event) {
const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data);
const serviceWorkerTargetId = this._serviceWorkerTargetId(executionContext.target());
- if (!serviceWorkerTargetId)
+ if (!serviceWorkerTargetId) {
return;
+ }
this._updateContextLabel(executionContext, this._versionByTargetId.get(serviceWorkerTargetId) || null);
}
@@ -601,27 +625,30 @@ SDK.ServiceWorkerContextNamer = class {
* @return {?string}
*/
_serviceWorkerTargetId(target) {
- if (target.parentTarget() !== this._target || target.type() !== SDK.Target.Type.ServiceWorker)
+ if (target.parentTarget() !== this._target || target.type() !== SDK.Target.Type.ServiceWorker) {
return null;
+ }
return target.id();
}
_updateAllContextLabels() {
for (const target of SDK.targetManager.targets()) {
const serviceWorkerTargetId = this._serviceWorkerTargetId(target);
- if (!serviceWorkerTargetId)
+ if (!serviceWorkerTargetId) {
continue;
+ }
const version = this._versionByTargetId.get(serviceWorkerTargetId) || null;
const runtimeModel = target.model(SDK.RuntimeModel);
const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
- for (const context of executionContexts)
+ for (const context of executionContexts) {
this._updateContextLabel(context, version);
+ }
}
}
/**
* @param {!SDK.ExecutionContext} context
- * @param {?SDK.ServiceWorkerVersion} version
+ * @param {?ServiceWorkerVersion} version
*/
_updateContextLabel(context, version) {
if (!version) {
@@ -632,4 +659,30 @@ SDK.ServiceWorkerContextNamer = class {
const label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : context.name;
context.setLabel(label + ' #' + version.id + ' (' + version.status + ')');
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.ServiceWorkerManager = ServiceWorkerManager;
+
+/** @enum {symbol} */
+SDK.ServiceWorkerManager.Events = Events;
+
+/** @constructor */
+SDK.ServiceWorkerDispatcher = ServiceWorkerDispatcher;
+
+/** @constructor */
+SDK.ServiceWorkerVersion = ServiceWorkerVersion;
+
+/** @constructor */
+SDK.ServiceWorkerRegistration = ServiceWorkerRegistration;
+
+/** @constructor */
+SDK.ServiceWorkerContextNamer = ServiceWorkerContextNamer;
+
+SDK.SDKModel.register(ServiceWorkerManager, SDK.Target.Capability.ServiceWorker, true); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
index 56e691de580..ecb06a454de 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMap.js
@@ -29,34 +29,80 @@
*/
/**
+ * @interface
+ */
+export default class SourceMap {
+ /**
+ * @return {string}
+ */
+ compiledURL() {
+ }
+
+ /**
+ * @return {string}
+ */
+ url() {
+ }
+
+ /**
+ * @return {!Array<string>}
+ */
+ sourceURLs() {
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @param {!Common.ResourceType} contentType
+ * @return {!Common.ContentProvider}
+ */
+ sourceContentProvider(sourceURL, contentType) {
+ }
+
+ /**
+ * @param {string} sourceURL
+ * @return {?string}
+ */
+ embeddedContentByURL(sourceURL) {
+ }
+
+ /**
+ * @param {number} lineNumber in compiled resource
+ * @param {number} columnNumber in compiled resource
+ * @return {?SourceMapEntry}
+ */
+ findEntry(lineNumber, columnNumber) {
+ }
+}
+
+/**
* @unrestricted
*/
-SDK.SourceMapV3 = class {
+export class SourceMapV3 {
constructor() {
/** @type {number} */ this.version;
/** @type {string|undefined} */ this.file;
/** @type {!Array.<string>} */ this.sources;
- /** @type {!Array.<!SDK.SourceMapV3.Section>|undefined} */ this.sections;
+ /** @type {!Array.<!SourceMapV3.Section>|undefined} */ this.sections;
/** @type {string} */ this.mappings;
/** @type {string|undefined} */ this.sourceRoot;
/** @type {!Array.<string>|undefined} */ this.names;
}
-};
+}
/**
* @unrestricted
*/
-SDK.SourceMapV3.Section = class {
+SourceMapV3.Section = class {
constructor() {
- /** @type {!SDK.SourceMapV3} */ this.map;
- /** @type {!SDK.SourceMapV3.Offset} */ this.offset;
+ /** @type {!SourceMapV3} */ this.map;
+ /** @type {!SourceMapV3.Offset} */ this.offset;
}
};
/**
* @unrestricted
*/
-SDK.SourceMapV3.Offset = class {
+SourceMapV3.Offset = class {
constructor() {
/** @type {number} */ this.line;
/** @type {number} */ this.column;
@@ -66,7 +112,7 @@ SDK.SourceMapV3.Offset = class {
/**
* @unrestricted
*/
-SDK.SourceMapEntry = class {
+export class SourceMapEntry {
/**
* @param {number} lineNumber
* @param {number} columnNumber
@@ -85,65 +131,24 @@ SDK.SourceMapEntry = class {
}
/**
- * @param {!SDK.SourceMapEntry} entry1
- * @param {!SDK.SourceMapEntry} entry2
+ * @param {!SourceMapEntry} entry1
+ * @param {!SourceMapEntry} entry2
* @return {number}
*/
static compare(entry1, entry2) {
- if (entry1.lineNumber !== entry2.lineNumber)
+ if (entry1.lineNumber !== entry2.lineNumber) {
return entry1.lineNumber - entry2.lineNumber;
+ }
return entry1.columnNumber - entry2.columnNumber;
}
-};
-
-/**
- * @interface
- */
-SDK.SourceMap = function() {};
-
-SDK.SourceMap.prototype = {
- /**
- * @return {string}
- */
- compiledURL() {},
-
- /**
- * @return {string}
- */
- url() {},
-
- /**
- * @return {!Array<string>}
- */
- sourceURLs() {},
-
- /**
- * @param {string} sourceURL
- * @param {!Common.ResourceType} contentType
- * @return {!Common.ContentProvider}
- */
- sourceContentProvider(sourceURL, contentType) {},
-
- /**
- * @param {string} sourceURL
- * @return {?string}
- */
- embeddedContentByURL(sourceURL) {},
-
- /**
- * @param {number} lineNumber in compiled resource
- * @param {number} columnNumber in compiled resource
- * @return {?SDK.SourceMapEntry}
- */
- findEntry(lineNumber, columnNumber) {},
-};
+}
/**
* @unrestricted
*/
-SDK.SourceMap.EditResult = class {
+export class EditResult {
/**
- * @param {!SDK.SourceMap} map
+ * @param {!SourceMap} map
* @param {!Array<!TextUtils.SourceEdit>} compiledEdits
* @param {!Map<string, string>} newSources
*/
@@ -152,26 +157,27 @@ SDK.SourceMap.EditResult = class {
this.compiledEdits = compiledEdits;
this.newSources = newSources;
}
-};
+}
/**
- * @implements {SDK.SourceMap}
+ * @implements {SourceMap}
* @unrestricted
*/
-SDK.TextSourceMap = class {
+export class TextSourceMap {
/**
* Implements Source Map V3 model. See https://github.com/google/closure-compiler/wiki/Source-Maps
* for format description.
* @param {string} compiledURL
* @param {string} sourceMappingURL
- * @param {!SDK.SourceMapV3} payload
+ * @param {!SourceMapV3} payload
*/
constructor(compiledURL, sourceMappingURL, payload) {
- if (!SDK.TextSourceMap._base64Map) {
+ if (!TextSourceMap._base64Map) {
const base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
- SDK.TextSourceMap._base64Map = {};
- for (let i = 0; i < base64Digits.length; ++i)
- SDK.TextSourceMap._base64Map[base64Digits.charAt(i)] = i;
+ TextSourceMap._base64Map = {};
+ for (let i = 0; i < base64Digits.length; ++i) {
+ TextSourceMap._base64Map[base64Digits.charAt(i)] = i;
+ }
}
this._json = payload;
@@ -179,14 +185,15 @@ SDK.TextSourceMap = class {
this._sourceMappingURL = sourceMappingURL;
this._baseURL = sourceMappingURL.startsWith('data:') ? compiledURL : sourceMappingURL;
- /** @type {?Array<!SDK.SourceMapEntry>} */
+ /** @type {?Array<!SourceMapEntry>} */
this._mappings = null;
- /** @type {!Map<string, !SDK.TextSourceMap.SourceInfo>} */
+ /** @type {!Map<string, !TextSourceMap.SourceInfo>} */
this._sourceInfos = new Map();
if (this._json.sections) {
const sectionWithURL = !!this._json.sections.find(section => !!section.url);
- if (sectionWithURL)
+ if (sectionWithURL) {
Common.console.warn(`SourceMap "${sourceMappingURL}" contains unsupported "URL" field in one of its sections.`);
+ }
}
this._eachSection(this._parseSources.bind(this));
}
@@ -194,8 +201,8 @@ SDK.TextSourceMap = class {
/**
* @param {string} sourceMapURL
* @param {string} compiledURL
- * @return {!Promise<?SDK.TextSourceMap>}
- * @this {SDK.TextSourceMap}
+ * @return {!Promise<?TextSourceMap>}
+ * @this {TextSourceMap}
*/
static load(sourceMapURL, compiledURL) {
let callback;
@@ -214,11 +221,12 @@ SDK.TextSourceMap = class {
return;
}
- if (content.slice(0, 3) === ')]}')
+ if (content.slice(0, 3) === ')]}') {
content = content.substring(content.indexOf('\n'));
+ }
try {
- const payload = /** @type {!SDK.SourceMapV3} */ (JSON.parse(content));
- callback(new SDK.TextSourceMap(compiledURL, sourceMapURL, payload));
+ const payload = /** @type {!SourceMapV3} */ (JSON.parse(content));
+ callback(new TextSourceMap(compiledURL, sourceMapURL, payload));
} catch (e) {
console.error(e);
Common.console.warn('DevTools failed to parse SourceMap: ' + sourceMapURL);
@@ -259,8 +267,9 @@ SDK.TextSourceMap = class {
*/
sourceContentProvider(sourceURL, contentType) {
const info = this._sourceInfos.get(sourceURL);
- if (info.content)
+ if (info.content) {
return Common.StaticContentProvider.fromString(sourceURL, contentType, info.content);
+ }
return new SDK.CompilerSourceMappingContentProvider(sourceURL, contentType);
}
@@ -270,8 +279,9 @@ SDK.TextSourceMap = class {
* @return {?string}
*/
embeddedContentByURL(sourceURL) {
- if (!this._sourceInfos.has(sourceURL))
+ if (!this._sourceInfos.has(sourceURL)) {
return null;
+ }
return this._sourceInfos.get(sourceURL).content;
}
@@ -279,7 +289,7 @@ SDK.TextSourceMap = class {
* @override
* @param {number} lineNumber in compiled resource
* @param {number} columnNumber in compiled resource
- * @return {?SDK.SourceMapEntry}
+ * @return {?SourceMapEntry}
*/
findEntry(lineNumber, columnNumber) {
const mappings = this.mappings();
@@ -292,24 +302,26 @@ SDK.TextSourceMap = class {
* @param {string} sourceURL
* @param {number} lineNumber
* @param {number} columnNumber
- * @return {?SDK.SourceMapEntry}
+ * @return {?SourceMapEntry}
*/
sourceLineMapping(sourceURL, lineNumber, columnNumber) {
const mappings = this._reversedMappings(sourceURL);
const first = mappings.lowerBound(lineNumber, lineComparator);
const last = mappings.upperBound(lineNumber, lineComparator);
- if (first >= mappings.length || mappings[first].sourceLineNumber !== lineNumber)
+ if (first >= mappings.length || mappings[first].sourceLineNumber !== lineNumber) {
return null;
+ }
const columnMappings = mappings.slice(first, last);
- if (!columnMappings.length)
+ if (!columnMappings.length) {
return null;
+ }
const index =
columnMappings.lowerBound(columnNumber, (columnNumber, mapping) => columnNumber - mapping.sourceColumnNumber);
return index >= columnMappings.length ? columnMappings[columnMappings.length - 1] : columnMappings[index];
/**
* @param {number} lineNumber
- * @param {!SDK.SourceMapEntry} mapping
+ * @param {!SourceMapEntry} mapping
* @return {number}
*/
function lineComparator(lineNumber, mapping) {
@@ -321,7 +333,7 @@ SDK.TextSourceMap = class {
* @param {string} sourceURL
* @param {number} lineNumber
* @param {number} columnNumber
- * @return {!Array<!SDK.SourceMapEntry>}
+ * @return {!Array<!SourceMapEntry>}
*/
findReverseEntries(sourceURL, lineNumber, columnNumber) {
const mappings = this._reversedMappings(sourceURL);
@@ -329,14 +341,15 @@ SDK.TextSourceMap = class {
undefined, (unused, entry) => lineNumber - entry.sourceLineNumber || columnNumber - entry.sourceColumnNumber);
let startIndex = endIndex;
while (startIndex > 0 && mappings[startIndex - 1].sourceLineNumber === mappings[endIndex - 1].sourceLineNumber &&
- mappings[startIndex - 1].sourceColumnNumber === mappings[endIndex - 1].sourceColumnNumber)
+ mappings[startIndex - 1].sourceColumnNumber === mappings[endIndex - 1].sourceColumnNumber) {
--startIndex;
+ }
return mappings.slice(startIndex, endIndex);
}
/**
- * @return {!Array<!SDK.SourceMapEntry>}
+ * @return {!Array<!SourceMapEntry>}
*/
mappings() {
if (this._mappings === null) {
@@ -344,75 +357,83 @@ SDK.TextSourceMap = class {
this._eachSection(this._parseMap.bind(this));
this._json = null;
}
- return /** @type {!Array<!SDK.SourceMapEntry>} */ (this._mappings);
+ return /** @type {!Array<!SourceMapEntry>} */ (this._mappings);
}
/**
* @param {string} sourceURL
- * @return {!Array.<!SDK.SourceMapEntry>}
+ * @return {!Array.<!SourceMapEntry>}
*/
_reversedMappings(sourceURL) {
- if (!this._sourceInfos.has(sourceURL))
+ if (!this._sourceInfos.has(sourceURL)) {
return [];
+ }
const mappings = this.mappings();
const info = this._sourceInfos.get(sourceURL);
- if (info.reverseMappings === null)
+ if (info.reverseMappings === null) {
info.reverseMappings = mappings.filter(mapping => mapping.sourceURL === sourceURL).sort(sourceMappingComparator);
+ }
return info.reverseMappings;
/**
- * @param {!SDK.SourceMapEntry} a
- * @param {!SDK.SourceMapEntry} b
+ * @param {!SourceMapEntry} a
+ * @param {!SourceMapEntry} b
* @return {number}
*/
function sourceMappingComparator(a, b) {
- if (a.sourceLineNumber !== b.sourceLineNumber)
+ if (a.sourceLineNumber !== b.sourceLineNumber) {
return a.sourceLineNumber - b.sourceLineNumber;
- if (a.sourceColumnNumber !== b.sourceColumnNumber)
+ }
+ if (a.sourceColumnNumber !== b.sourceColumnNumber) {
return a.sourceColumnNumber - b.sourceColumnNumber;
+ }
- if (a.lineNumber !== b.lineNumber)
+ if (a.lineNumber !== b.lineNumber) {
return a.lineNumber - b.lineNumber;
+ }
return a.columnNumber - b.columnNumber;
}
}
/**
- * @param {function(!SDK.SourceMapV3, number, number)} callback
+ * @param {function(!SourceMapV3, number, number)} callback
*/
_eachSection(callback) {
if (!this._json.sections) {
callback(this._json, 0, 0);
return;
}
- for (const section of this._json.sections)
+ for (const section of this._json.sections) {
callback(section.map, section.offset.line, section.offset.column);
+ }
}
/**
- * @param {!SDK.SourceMapV3} sourceMap
+ * @param {!SourceMapV3} sourceMap
*/
_parseSources(sourceMap) {
const sourcesList = [];
let sourceRoot = sourceMap.sourceRoot || '';
- if (sourceRoot && !sourceRoot.endsWith('/'))
+ if (sourceRoot && !sourceRoot.endsWith('/')) {
sourceRoot += '/';
+ }
for (let i = 0; i < sourceMap.sources.length; ++i) {
const href = sourceRoot + sourceMap.sources[i];
let url = Common.ParsedURL.completeURL(this._baseURL, href) || href;
const source = sourceMap.sourcesContent && sourceMap.sourcesContent[i];
- if (url === this._compiledURL && source)
+ if (url === this._compiledURL && source) {
url += Common.UIString('? [sm]');
- this._sourceInfos.set(url, new SDK.TextSourceMap.SourceInfo(source, null));
+ }
+ this._sourceInfos.set(url, new TextSourceMap.SourceInfo(source, null));
sourcesList.push(url);
}
- sourceMap[SDK.TextSourceMap._sourcesListSymbol] = sourcesList;
+ sourceMap[TextSourceMap._sourcesListSymbol] = sourcesList;
}
/**
- * @param {!SDK.SourceMapV3} map
+ * @param {!SourceMapV3} map
* @param {number} lineNumber
* @param {number} columnNumber
*/
@@ -421,9 +442,9 @@ SDK.TextSourceMap = class {
let sourceLineNumber = 0;
let sourceColumnNumber = 0;
let nameIndex = 0;
- const sources = map[SDK.TextSourceMap._sourcesListSymbol];
+ const sources = map[TextSourceMap._sourcesListSymbol];
const names = map.names || [];
- const stringCharIterator = new SDK.TextSourceMap.StringCharIterator(map.mappings);
+ const stringCharIterator = new TextSourceMap.StringCharIterator(map.mappings);
let sourceURL = sources[sourceIndex];
while (true) {
@@ -435,13 +456,14 @@ SDK.TextSourceMap = class {
columnNumber = 0;
stringCharIterator.next();
}
- if (!stringCharIterator.hasNext())
+ if (!stringCharIterator.hasNext()) {
break;
+ }
}
columnNumber += this._decodeVLQ(stringCharIterator);
if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
- this._mappings.push(new SDK.SourceMapEntry(lineNumber, columnNumber));
+ this._mappings.push(new SourceMapEntry(lineNumber, columnNumber));
continue;
}
@@ -455,17 +477,17 @@ SDK.TextSourceMap = class {
if (!stringCharIterator.hasNext() || this._isSeparator(stringCharIterator.peek())) {
this._mappings.push(
- new SDK.SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber));
+ new SourceMapEntry(lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber));
continue;
}
nameIndex += this._decodeVLQ(stringCharIterator);
- this._mappings.push(new SDK.SourceMapEntry(
+ this._mappings.push(new SourceMapEntry(
lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber, names[nameIndex]));
}
// As per spec, mappings are not necessarily sorted.
- this._mappings.sort(SDK.SourceMapEntry.compare);
+ this._mappings.sort(SourceMapEntry.compare);
}
/**
@@ -477,7 +499,7 @@ SDK.TextSourceMap = class {
}
/**
- * @param {!SDK.TextSourceMap.StringCharIterator} stringCharIterator
+ * @param {!TextSourceMap.StringCharIterator} stringCharIterator
* @return {number}
*/
_decodeVLQ(stringCharIterator) {
@@ -486,10 +508,10 @@ SDK.TextSourceMap = class {
let shift = 0;
let digit;
do {
- digit = SDK.TextSourceMap._base64Map[stringCharIterator.next()];
- result += (digit & SDK.TextSourceMap._VLQ_BASE_MASK) << shift;
- shift += SDK.TextSourceMap._VLQ_BASE_SHIFT;
- } while (digit & SDK.TextSourceMap._VLQ_CONTINUATION_MASK);
+ digit = TextSourceMap._base64Map[stringCharIterator.next()];
+ result += (digit & TextSourceMap._VLQ_BASE_MASK) << shift;
+ shift += TextSourceMap._VLQ_BASE_SHIFT;
+ } while (digit & TextSourceMap._VLQ_CONTINUATION_MASK);
// Fix the sign.
const negative = result & 1;
@@ -505,12 +527,13 @@ SDK.TextSourceMap = class {
reverseMapTextRange(url, textRange) {
/**
* @param {!{lineNumber: number, columnNumber: number}} position
- * @param {!SDK.SourceMapEntry} mapping
+ * @param {!SourceMapEntry} mapping
* @return {number}
*/
function comparator(position, mapping) {
- if (position.lineNumber !== mapping.sourceLineNumber)
+ if (position.lineNumber !== mapping.sourceLineNumber) {
return position.lineNumber - mapping.sourceLineNumber;
+ }
return position.columnNumber - mapping.sourceColumnNumber;
}
@@ -526,17 +549,16 @@ SDK.TextSourceMap = class {
return new TextUtils.TextRange(
startMapping.lineNumber, startMapping.columnNumber, endMapping.lineNumber, endMapping.columnNumber);
}
-};
-
-SDK.TextSourceMap._VLQ_BASE_SHIFT = 5;
-SDK.TextSourceMap._VLQ_BASE_MASK = (1 << 5) - 1;
-SDK.TextSourceMap._VLQ_CONTINUATION_MASK = 1 << 5;
+}
+TextSourceMap._VLQ_BASE_SHIFT = 5;
+TextSourceMap._VLQ_BASE_MASK = (1 << 5) - 1;
+TextSourceMap._VLQ_CONTINUATION_MASK = 1 << 5;
/**
* @unrestricted
*/
-SDK.TextSourceMap.StringCharIterator = class {
+TextSourceMap.StringCharIterator = class {
/**
* @param {string} string
*/
@@ -570,10 +592,10 @@ SDK.TextSourceMap.StringCharIterator = class {
/**
* @unrestricted
*/
-SDK.TextSourceMap.SourceInfo = class {
+TextSourceMap.SourceInfo = class {
/**
* @param {?string} content
- * @param {?Array<!SDK.SourceMapEntry>} reverseMappings
+ * @param {?Array<!SourceMapEntry>} reverseMappings
*/
constructor(content, reverseMappings) {
this.content = content;
@@ -581,4 +603,25 @@ SDK.TextSourceMap.SourceInfo = class {
}
};
-SDK.TextSourceMap._sourcesListSymbol = Symbol('sourcesList');
+TextSourceMap._sourcesListSymbol = Symbol('sourcesList');
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @interface */
+SDK.SourceMap = SourceMap;
+
+/** @constructor */
+SDK.SourceMapV3 = SourceMapV3;
+
+/** @constructor */
+SDK.SourceMapEntry = SourceMapEntry;
+
+/** @constructor */
+SDK.TextSourceMap = TextSourceMap;
+
+/** @constructor */
+SDK.SourceMap.EditResult = EditResult;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMapManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMapManager.js
index 6024d21cd0e..7d72611a0c4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMapManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/SourceMapManager.js
@@ -5,7 +5,7 @@
/**
* @template T
*/
-SDK.SourceMapManager = class extends Common.Object {
+export default class SourceMapManager extends Common.Object {
/**
* @param {!SDK.Target} target
*/
@@ -20,14 +20,14 @@ SDK.SourceMapManager = class extends Common.Object {
/** @type {!Map<!T, string>} */
this._relativeSourceMapURL = new Map();
/** @type {!Map<!T, string>} */
- this._resolvedSourceMapURL = new Map();
+ this._resolvedSourceMapId = new Map();
/** @type {!Map<string, !SDK.SourceMap>} */
- this._sourceMapByURL = new Map();
- /** @type {!Multimap<string, !T>} */
- this._sourceMapURLToLoadingClients = new Multimap();
- /** @type {!Multimap<string, !T>} */
- this._sourceMapURLToClients = new Multimap();
+ this._sourceMapById = new Map();
+ /** @type {!Platform.Multimap<string, !T>} */
+ this._sourceMapIdToLoadingClients = new Platform.Multimap();
+ /** @type {!Platform.Multimap<string, !T>} */
+ this._sourceMapIdToClients = new Platform.Multimap();
SDK.targetManager.addEventListener(SDK.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this);
}
@@ -36,10 +36,14 @@ SDK.SourceMapManager = class extends Common.Object {
* @param {boolean} isEnabled
*/
setEnabled(isEnabled) {
- if (isEnabled === this._isEnabled)
+ if (isEnabled === this._isEnabled) {
return;
+ }
this._isEnabled = isEnabled;
- const clients = Array.from(this._resolvedSourceMapURL.keys());
+ // We need this copy, because `this._resolvedSourceMapId` is getting modified
+ // in the loop body and trying to iterate over it at the same time leads to
+ // an infinite loop.
+ const clients = [...this._resolvedSourceMapId.keys()];
for (const client of clients) {
const relativeSourceURL = this._relativeSourceURL.get(client);
const relativeSourceMapURL = this._relativeSourceMapURL.get(client);
@@ -52,16 +56,19 @@ SDK.SourceMapManager = class extends Common.Object {
* @param {!Common.Event} event
*/
_inspectedURLChanged(event) {
- if (event.data !== this._target)
+ if (event.data !== this._target) {
return;
+ }
- const clients = Array.from(this._resolvedSourceMapURL.keys());
- for (const client of clients) {
+ // We need this copy, because `this._resolvedSourceMapId` is getting modified
+ // in the loop body and trying to iterate over it at the same time leads to
+ // an infinite loop.
+ const prevSourceMapIds = new Map(this._resolvedSourceMapId);
+ for (const [client, prevSourceMapId] of prevSourceMapIds) {
const relativeSourceURL = this._relativeSourceURL.get(client);
const relativeSourceMapURL = this._relativeSourceMapURL.get(client);
- const resolvedSourceMapURL = this._resolvedSourceMapURL.get(client);
- const sourceMapURL = this._resolveRelativeURLs(relativeSourceURL, relativeSourceMapURL).sourceMapURL;
- if (sourceMapURL !== resolvedSourceMapURL) {
+ const {sourceMapId} = this._resolveRelativeURLs(relativeSourceURL, relativeSourceMapURL);
+ if (prevSourceMapId !== sourceMapId) {
this.detachSourceMap(client);
this.attachSourceMap(client, relativeSourceURL, relativeSourceMapURL);
}
@@ -73,8 +80,11 @@ SDK.SourceMapManager = class extends Common.Object {
* @return {?SDK.SourceMap}
*/
sourceMapForClient(client) {
- const sourceMapURL = this._resolvedSourceMapURL.get(client);
- return sourceMapURL ? this._sourceMapByURL.get(sourceMapURL) || null : null;
+ const sourceMapId = this._resolvedSourceMapId.get(client);
+ if (!sourceMapId) {
+ return null;
+ }
+ return this._sourceMapById.get(sourceMapId) || null;
}
/**
@@ -82,100 +92,112 @@ SDK.SourceMapManager = class extends Common.Object {
* @return {!Array<!T>}
*/
clientsForSourceMap(sourceMap) {
- if (this._sourceMapURLToClients.has(sourceMap.url()))
- return this._sourceMapURLToClients.get(sourceMap.url()).valuesArray();
- return this._sourceMapURLToLoadingClients.get(sourceMap.url()).valuesArray();
+ const sourceMapId = this._getSourceMapId(sourceMap.compiledURL(), sourceMap.url());
+ if (this._sourceMapIdToClients.has(sourceMapId)) {
+ return this._sourceMapIdToClients.get(sourceMapId).valuesArray();
+ }
+ return this._sourceMapIdToLoadingClients.get(sourceMapId).valuesArray();
}
/**
- * @param {!SDK.SourceMap.EditResult} editResult
+ * @param {string} sourceURL
+ * @param {string} sourceMapURL
*/
- applySourceMapEdit(editResult) {
- console.assert(
- this._sourceMapByURL.has(editResult.map.url()), 'Cannot apply edit result for non-existing source map');
- this._sourceMapByURL.set(editResult.map.url(), editResult.map);
- this.dispatchEventToListeners(
- SDK.SourceMapManager.Events.SourceMapChanged, {sourceMap: editResult.map, newSources: editResult.newSources});
+ _getSourceMapId(sourceURL, sourceMapURL) {
+ return `${sourceURL}:${sourceMapURL}`;
}
/**
* @param {string} sourceURL
* @param {string} sourceMapURL
- * @return {!{sourceURL: ?string, sourceMapURL: ?string}}
+ * @return {?{sourceURL: string, sourceMapURL: string, sourceMapId: string}}
*/
_resolveRelativeURLs(sourceURL, sourceMapURL) {
// |sourceURL| can be a random string, but is generally an absolute path.
// Complete it to inspected page url for relative links.
const resolvedSourceURL = Common.ParsedURL.completeURL(this._target.inspectedURL(), sourceURL);
- const resolvedSourceMapURL =
- resolvedSourceURL ? Common.ParsedURL.completeURL(resolvedSourceURL, sourceMapURL) : null;
- return {sourceURL: resolvedSourceURL, sourceMapURL: resolvedSourceMapURL};
+ if (!resolvedSourceURL) {
+ return null;
+ }
+ const resolvedSourceMapURL = Common.ParsedURL.completeURL(resolvedSourceURL, sourceMapURL);
+ if (!resolvedSourceMapURL) {
+ return null;
+ }
+ return {
+ sourceURL: resolvedSourceURL,
+ sourceMapURL: resolvedSourceMapURL,
+ sourceMapId: this._getSourceMapId(resolvedSourceURL, resolvedSourceMapURL)
+ };
}
/**
* @param {!T} client
- * @param {string} sourceURL
- * @param {?string} sourceMapURL
+ * @param {string} relativeSourceURL
+ * @param {?string} relativeSourceMapURL
*/
- attachSourceMap(client, sourceURL, sourceMapURL) {
- if (!sourceMapURL)
+ attachSourceMap(client, relativeSourceURL, relativeSourceMapURL) {
+ if (!relativeSourceMapURL) {
return;
- console.assert(!this._resolvedSourceMapURL.has(client), 'SourceMap is already attached to client');
- const resolvedURLs = this._resolveRelativeURLs(sourceURL, sourceMapURL);
- if (!resolvedURLs.sourceURL || !resolvedURLs.sourceMapURL)
+ }
+ console.assert(!this._resolvedSourceMapId.has(client), 'SourceMap is already attached to client');
+ const resolvedURLs = this._resolveRelativeURLs(relativeSourceURL, relativeSourceMapURL);
+ if (!resolvedURLs) {
return;
- this._relativeSourceURL.set(client, sourceURL);
- this._relativeSourceMapURL.set(client, sourceMapURL);
- this._resolvedSourceMapURL.set(client, resolvedURLs.sourceMapURL);
+ }
+ this._relativeSourceURL.set(client, relativeSourceURL);
+ this._relativeSourceMapURL.set(client, relativeSourceMapURL);
- sourceURL = resolvedURLs.sourceURL;
- sourceMapURL = resolvedURLs.sourceMapURL;
- if (!this._isEnabled)
+ const {sourceURL, sourceMapURL, sourceMapId} = resolvedURLs;
+ this._resolvedSourceMapId.set(client, sourceMapId);
+
+ if (!this._isEnabled) {
return;
+ }
- this.dispatchEventToListeners(SDK.SourceMapManager.Events.SourceMapWillAttach, client);
+ this.dispatchEventToListeners(Events.SourceMapWillAttach, client);
- if (this._sourceMapByURL.has(sourceMapURL)) {
- attach.call(this, sourceMapURL, client);
+ if (this._sourceMapById.has(sourceMapId)) {
+ attach.call(this, sourceMapId, client);
return;
}
- if (!this._sourceMapURLToLoadingClients.has(sourceMapURL)) {
- SDK.TextSourceMap.load(sourceMapURL, sourceURL)
- .then(onSourceMap.bind(this, sourceMapURL));
+ if (!this._sourceMapIdToLoadingClients.has(sourceMapId)) {
+ SDK.TextSourceMap.load(sourceMapURL, sourceURL).then(onSourceMap.bind(this, sourceMapId));
}
- this._sourceMapURLToLoadingClients.set(sourceMapURL, client);
+ this._sourceMapIdToLoadingClients.set(sourceMapId, client);
/**
- * @param {string} sourceMapURL
+ * @param {string} sourceMapId
* @param {?SDK.SourceMap} sourceMap
- * @this {SDK.SourceMapManager}
+ * @this {SourceMapManager}
*/
- function onSourceMap(sourceMapURL, sourceMap) {
+ function onSourceMap(sourceMapId, sourceMap) {
this._sourceMapLoadedForTest();
- const clients = this._sourceMapURLToLoadingClients.get(sourceMapURL);
- this._sourceMapURLToLoadingClients.deleteAll(sourceMapURL);
- if (!clients.size)
+ const clients = this._sourceMapIdToLoadingClients.get(sourceMapId);
+ this._sourceMapIdToLoadingClients.deleteAll(sourceMapId);
+ if (!clients.size) {
return;
+ }
if (!sourceMap) {
- for (const client of clients)
- this.dispatchEventToListeners(SDK.SourceMapManager.Events.SourceMapFailedToAttach, client);
+ for (const client of clients) {
+ this.dispatchEventToListeners(Events.SourceMapFailedToAttach, client);
+ }
return;
}
- this._sourceMapByURL.set(sourceMapURL, sourceMap);
- for (const client of clients)
- attach.call(this, sourceMapURL, client);
+ this._sourceMapById.set(sourceMapId, sourceMap);
+ for (const client of clients) {
+ attach.call(this, sourceMapId, client);
+ }
}
/**
- * @param {string} sourceMapURL
+ * @param {string} sourceMapId
* @param {!T} client
- * @this {SDK.SourceMapManager}
+ * @this {SourceMapManager}
*/
- function attach(sourceMapURL, client) {
- this._sourceMapURLToClients.set(sourceMapURL, client);
- const sourceMap = this._sourceMapByURL.get(sourceMapURL);
- this.dispatchEventToListeners(
- SDK.SourceMapManager.Events.SourceMapAttached, {client: client, sourceMap: sourceMap});
+ function attach(sourceMapId, client) {
+ this._sourceMapIdToClients.set(sourceMapId, client);
+ const sourceMap = this._sourceMapById.get(sourceMapId);
+ this.dispatchEventToListeners(Events.SourceMapAttached, {client: client, sourceMap: sourceMap});
}
}
@@ -183,24 +205,26 @@ SDK.SourceMapManager = class extends Common.Object {
* @param {!T} client
*/
detachSourceMap(client) {
- const sourceMapURL = this._resolvedSourceMapURL.get(client);
+ const sourceMapId = this._resolvedSourceMapId.get(client);
this._relativeSourceURL.delete(client);
this._relativeSourceMapURL.delete(client);
- this._resolvedSourceMapURL.delete(client);
+ this._resolvedSourceMapId.delete(client);
- if (!sourceMapURL)
+ if (!sourceMapId) {
return;
- if (!this._sourceMapURLToClients.hasValue(sourceMapURL, client)) {
- if (this._sourceMapURLToLoadingClients.delete(sourceMapURL, client))
- this.dispatchEventToListeners(SDK.SourceMapManager.Events.SourceMapFailedToAttach, client);
+ }
+ if (!this._sourceMapIdToClients.hasValue(sourceMapId, client)) {
+ if (this._sourceMapIdToLoadingClients.delete(sourceMapId, client)) {
+ this.dispatchEventToListeners(Events.SourceMapFailedToAttach, client);
+ }
return;
}
- this._sourceMapURLToClients.delete(sourceMapURL, client);
- const sourceMap = this._sourceMapByURL.get(sourceMapURL);
- if (!this._sourceMapURLToClients.has(sourceMapURL))
- this._sourceMapByURL.delete(sourceMapURL);
- this.dispatchEventToListeners(
- SDK.SourceMapManager.Events.SourceMapDetached, {client: client, sourceMap: sourceMap});
+ this._sourceMapIdToClients.delete(sourceMapId, client);
+ const sourceMap = this._sourceMapById.get(sourceMapId);
+ if (!this._sourceMapIdToClients.has(sourceMapId)) {
+ this._sourceMapById.delete(sourceMapId);
+ }
+ this.dispatchEventToListeners(Events.SourceMapDetached, {client: client, sourceMap: sourceMap});
}
_sourceMapLoadedForTest() {
@@ -210,12 +234,23 @@ SDK.SourceMapManager = class extends Common.Object {
SDK.targetManager.removeEventListener(
SDK.TargetManager.Events.InspectedURLChanged, this._inspectedURLChanged, this);
}
-};
+}
-SDK.SourceMapManager.Events = {
+export const Events = {
SourceMapWillAttach: Symbol('SourceMapWillAttach'),
SourceMapFailedToAttach: Symbol('SourceMapFailedToAttach'),
SourceMapAttached: Symbol('SourceMapAttached'),
SourceMapDetached: Symbol('SourceMapDetached'),
SourceMapChanged: Symbol('SourceMapChanged')
};
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.SourceMapManager = SourceMapManager;
+
+SDK.SourceMapManager.Events = Events;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
index 4680a1f064c..715eff01a26 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
@@ -7,53 +7,52 @@
/**
* @unrestricted
*/
-SDK.Target = class extends Protocol.TargetBase {
+export default class Target extends Protocol.TargetBase {
/**
* @param {!SDK.TargetManager} targetManager
* @param {string} id
* @param {string} name
- * @param {!SDK.Target.Type} type
+ * @param {!Type} type
* @param {?SDK.Target} parentTarget
* @param {string} sessionId
* @param {boolean} suspended
* @param {?Protocol.Connection} connection
*/
constructor(targetManager, id, name, type, parentTarget, sessionId, suspended, connection) {
- const needsNodeJSPatching = type === SDK.Target.Type.Node;
+ const needsNodeJSPatching = type === Type.Node;
super(needsNodeJSPatching, parentTarget, sessionId, connection);
this._targetManager = targetManager;
this._name = name;
this._inspectedURL = '';
this._capabilitiesMask = 0;
switch (type) {
- case SDK.Target.Type.Frame:
- this._capabilitiesMask = SDK.Target.Capability.Browser | SDK.Target.Capability.Storage |
- SDK.Target.Capability.DOM | SDK.Target.Capability.JS | SDK.Target.Capability.Log |
- SDK.Target.Capability.Network | SDK.Target.Capability.Target | SDK.Target.Capability.Tracing |
- SDK.Target.Capability.Emulation | SDK.Target.Capability.Input | SDK.Target.Capability.Inspector;
+ case Type.Frame:
+ this._capabilitiesMask = Capability.Browser | Capability.Storage | Capability.DOM | Capability.JS |
+ Capability.Log | Capability.Network | Capability.Target | Capability.Tracing | Capability.Emulation |
+ Capability.Input | Capability.Inspector;
if (!parentTarget) {
// This matches backend exposing certain capabilities only for the main frame.
- this._capabilitiesMask |= SDK.Target.Capability.DeviceEmulation | SDK.Target.Capability.ScreenCapture |
- SDK.Target.Capability.Security | SDK.Target.Capability.ServiceWorker;
+ this._capabilitiesMask |=
+ Capability.DeviceEmulation | Capability.ScreenCapture | Capability.Security | Capability.ServiceWorker;
// TODO(dgozman): we report service workers for the whole frame tree on the main frame,
// while we should be able to only cover the subtree corresponding to the target.
}
break;
- case SDK.Target.Type.ServiceWorker:
- this._capabilitiesMask = SDK.Target.Capability.JS | SDK.Target.Capability.Log | SDK.Target.Capability.Network |
- SDK.Target.Capability.Target | SDK.Target.Capability.Inspector;
- if (!parentTarget)
- this._capabilitiesMask |= SDK.Target.Capability.Browser;
+ case Type.ServiceWorker:
+ this._capabilitiesMask =
+ Capability.JS | Capability.Log | Capability.Network | Capability.Target | Capability.Inspector;
+ if (!parentTarget) {
+ this._capabilitiesMask |= Capability.Browser;
+ }
break;
- case SDK.Target.Type.Worker:
- this._capabilitiesMask = SDK.Target.Capability.JS | SDK.Target.Capability.Log | SDK.Target.Capability.Network |
- SDK.Target.Capability.Target;
+ case Type.Worker:
+ this._capabilitiesMask = Capability.JS | Capability.Log | Capability.Network | Capability.Target;
break;
- case SDK.Target.Type.Node:
- this._capabilitiesMask = SDK.Target.Capability.JS;
+ case Type.Node:
+ this._capabilitiesMask = Capability.JS;
break;
- case SDK.Target.Type.Browser:
- this._capabilitiesMask = SDK.Target.Capability.Target;
+ case Type.Browser:
+ this._capabilitiesMask = Capability.Target;
break;
}
this._type = type;
@@ -67,11 +66,12 @@ SDK.Target = class extends Protocol.TargetBase {
this._creatingModels = true;
// TODO(dgozman): fix this in bindings layer.
this.model(SDK.ResourceTreeModel);
- const registered = Array.from(SDK.SDKModel._registeredModels.keys());
+ const registered = Array.from(SDK.SDKModel.registeredModels.keys());
for (const modelClass of registered) {
- const info = SDK.SDKModel._registeredModels.get(modelClass);
- if (info.autostart || required.has(modelClass))
+ const info = SDK.SDKModel.registeredModels.get(modelClass);
+ if (info.autostart || required.has(modelClass)) {
this.model(modelClass);
+ }
}
this._creatingModels = false;
}
@@ -91,7 +91,7 @@ SDK.Target = class extends Protocol.TargetBase {
}
/**
- * @return {!SDK.Target.Type}
+ * @return {!Type}
*/
type() {
return this._type;
@@ -102,7 +102,7 @@ SDK.Target = class extends Protocol.TargetBase {
*/
markAsNodeJSForTest() {
super.markAsNodeJSForTest();
- this._type = SDK.Target.Type.Node;
+ this._type = Type.Node;
}
/**
@@ -127,8 +127,7 @@ SDK.Target = class extends Protocol.TargetBase {
* @return {string}
*/
decorateLabel(label) {
- return (this._type === SDK.Target.Type.Worker || this._type === SDK.Target.Type.ServiceWorker) ? '\u2699 ' + label :
- label;
+ return (this._type === Type.Worker || this._type === Type.ServiceWorker) ? '\u2699 ' + label : label;
}
/**
@@ -145,8 +144,9 @@ SDK.Target = class extends Protocol.TargetBase {
dispose(reason) {
super.dispose(reason);
this._targetManager.removeTarget(this);
- for (const model of this._modelByConstructor.valuesArray())
+ for (const model of this._modelByConstructor.valuesArray()) {
model.dispose();
+ }
}
/**
@@ -156,14 +156,16 @@ SDK.Target = class extends Protocol.TargetBase {
*/
model(modelClass) {
if (!this._modelByConstructor.get(modelClass)) {
- const info = SDK.SDKModel._registeredModels.get(modelClass);
- if (info === undefined)
+ const info = SDK.SDKModel.registeredModels.get(modelClass);
+ if (info === undefined) {
throw 'Model class is not registered @' + new Error().stack;
+ }
if ((this._capabilitiesMask & info.capabilities) === info.capabilities) {
const model = new modelClass(this);
this._modelByConstructor.set(modelClass, model);
- if (!this._creatingModels)
+ if (!this._creatingModels) {
this._targetManager.modelAdded(this, modelClass, model);
+ }
}
}
return this._modelByConstructor.get(modelClass) || null;
@@ -190,39 +192,40 @@ SDK.Target = class extends Protocol.TargetBase {
this._inspectedURL = inspectedURL;
const parsedURL = inspectedURL.asParsedURL();
this._inspectedURLName = parsedURL ? parsedURL.lastPathComponentWithFragment() : '#' + this._id;
- if (!this.parentTarget())
- InspectorFrontendHost.inspectedURLChanged(inspectedURL || '');
+ if (!this.parentTarget()) {
+ Host.InspectorFrontendHost.inspectedURLChanged(inspectedURL || '');
+ }
this._targetManager.dispatchEventToListeners(SDK.TargetManager.Events.InspectedURLChanged, this);
- if (!this._name)
+ if (!this._name) {
this._targetManager.dispatchEventToListeners(SDK.TargetManager.Events.NameChanged, this);
+ }
}
/**
+ * @param {string=} reason - optionally provide a reason, so models can respond accordingly
* @return {!Promise}
*/
- suspend() {
- if (this._isSuspended)
+ async suspend(reason) {
+ if (this._isSuspended) {
return Promise.resolve();
+ }
this._isSuspended = true;
- const promises = [];
- for (const model of this.models().values())
- promises.push(model.suspendModel());
- return Promise.all(promises);
+ await Promise.all(Array.from(this.models().values(), m => m.preSuspendModel(reason)));
+ await Promise.all(Array.from(this.models().values(), m => m.suspendModel(reason)));
}
/**
* @return {!Promise}
*/
- resume() {
- if (!this._isSuspended)
+ async resume() {
+ if (!this._isSuspended) {
return Promise.resolve();
+ }
this._isSuspended = false;
- const promises = [];
- for (const model of this.models().values())
- promises.push(model.resumeModel());
- return Promise.all(promises);
+ await Promise.all(Array.from(this.models().values(), m => m.resumeModel()));
+ await Promise.all(Array.from(this.models().values(), m => m.postResumeModel()));
}
/**
@@ -231,12 +234,12 @@ SDK.Target = class extends Protocol.TargetBase {
suspended() {
return this._isSuspended;
}
-};
+}
/**
* @enum {number}
*/
-SDK.Target.Capability = {
+export const Capability = {
Browser: 1 << 0,
DOM: 1 << 1,
JS: 1 << 2,
@@ -259,7 +262,7 @@ SDK.Target.Capability = {
/**
* @enum {string}
*/
-SDK.Target.Type = {
+export const Type = {
Frame: 'frame',
ServiceWorker: 'service-worker',
Worker: 'worker',
@@ -267,54 +270,21 @@ SDK.Target.Type = {
Browser: 'browser',
};
-/**
- * @unrestricted
- */
-SDK.SDKModel = class extends Common.Object {
- /**
- * @param {!SDK.Target} target
- */
- constructor(target) {
- super();
- this._target = target;
- }
-
- /**
- * @return {!SDK.Target}
- */
- target() {
- return this._target;
- }
-
- /**
- * @return {!Promise}
- */
- suspendModel() {
- return Promise.resolve();
- }
+/* Legacy exported object */
+self.SDK = self.SDK || {};
- /**
- * @return {!Promise}
- */
- resumeModel() {
- return Promise.resolve();
- }
-
- dispose() {
- }
-};
+/* Legacy exported object */
+SDK = SDK || {};
+/** @constructor */
+SDK.Target = Target;
/**
- * @param {function(new:SDK.SDKModel, !SDK.Target)} modelClass
- * @param {number} capabilities
- * @param {boolean} autostart
+ * @enum {number}
*/
-SDK.SDKModel.register = function(modelClass, capabilities, autostart) {
- if (!SDK.SDKModel._registeredModels)
- SDK.SDKModel._registeredModels = new Map();
- SDK.SDKModel._registeredModels.set(modelClass, {capabilities: capabilities, autostart: autostart});
-};
+SDK.Target.Capability = Capability;
-/** @type {!Map<function(new:SDK.SDKModel, !SDK.Target), !{capabilities: number, autostart: boolean}>} */
-SDK.SDKModel._registeredModels;
+/**
+ * @enum {string}
+ */
+SDK.Target.Type = Type;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
index 1e8196d5bf6..bcb3d0bf49d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
@@ -4,39 +4,42 @@
* found in the LICENSE file.
*/
-SDK.TargetManager = class extends Common.Object {
+export default class TargetManager extends Common.Object {
constructor() {
super();
/** @type {!Array.<!SDK.Target>} */
this._targets = [];
- /** @type {!Array.<!SDK.TargetManager.Observer>} */
+ /** @type {!Array.<!Observer>} */
this._observers = [];
- /** @type {!Multimap<symbol, !{modelClass: !Function, thisObject: (!Object|undefined), listener: function(!Common.Event)}>} */
- this._modelListeners = new Multimap();
- /** @type {!Multimap<function(new:SDK.SDKModel, !SDK.Target), !SDK.SDKModelObserver>} */
- this._modelObservers = new Multimap();
+ /** @type {!Platform.Multimap<symbol, !{modelClass: !Function, thisObject: (!Object|undefined), listener: function(!Common.Event)}>} */
+ this._modelListeners = new Platform.Multimap();
+ /** @type {!Platform.Multimap<function(new:SDK.SDKModel, !SDK.Target), !SDKModelObserver>} */
+ this._modelObservers = new Platform.Multimap();
this._isSuspended = false;
}
/**
+ * @param {string=} reason - optionally provide a reason, so targets can respond accordingly
* @return {!Promise}
*/
- suspendAllTargets() {
- if (this._isSuspended)
+ suspendAllTargets(reason) {
+ if (this._isSuspended) {
return Promise.resolve();
+ }
this._isSuspended = true;
- this.dispatchEventToListeners(SDK.TargetManager.Events.SuspendStateChanged);
- return Promise.all(this._targets.map(target => target.suspend()));
+ this.dispatchEventToListeners(Events.SuspendStateChanged);
+ return Promise.all(this._targets.map(target => target.suspend(reason)));
}
/**
* @return {!Promise}
*/
resumeAllTargets() {
- if (!this._isSuspended)
+ if (!this._isSuspended) {
return Promise.resolve();
+ }
this._isSuspended = false;
- this.dispatchEventToListeners(SDK.TargetManager.Events.SuspendStateChanged);
+ this.dispatchEventToListeners(Events.SuspendStateChanged);
return Promise.all(this._targets.map(target => target.resume()));
}
@@ -56,8 +59,9 @@ SDK.TargetManager = class extends Common.Object {
const result = [];
for (let i = 0; i < this._targets.length; ++i) {
const model = this._targets[i].model(modelClass);
- if (model)
+ if (model) {
result.push(model);
+ }
}
return result;
}
@@ -71,19 +75,20 @@ SDK.TargetManager = class extends Common.Object {
/**
* @param {function(new:T,!SDK.Target)} modelClass
- * @param {!SDK.SDKModelObserver<T>} observer
+ * @param {!SDKModelObserver<T>} observer
* @template T
*/
observeModels(modelClass, observer) {
const models = this.models(modelClass);
this._modelObservers.set(modelClass, observer);
- for (const model of models)
+ for (const model of models) {
observer.modelAdded(model);
+ }
}
/**
* @param {function(new:T,!SDK.Target)} modelClass
- * @param {!SDK.SDKModelObserver<T>} observer
+ * @param {!SDKModelObserver<T>} observer
* @template T
*/
unobserveModels(modelClass, observer) {
@@ -96,8 +101,9 @@ SDK.TargetManager = class extends Common.Object {
* @param {!SDK.SDKModel} model
*/
modelAdded(target, modelClass, model) {
- for (const observer of this._modelObservers.get(modelClass).valuesArray())
+ for (const observer of this._modelObservers.get(modelClass).valuesArray()) {
observer.modelAdded(model);
+ }
}
/**
@@ -106,8 +112,9 @@ SDK.TargetManager = class extends Common.Object {
* @param {!SDK.SDKModel} model
*/
_modelRemoved(target, modelClass, model) {
- for (const observer of this._modelObservers.get(modelClass).valuesArray())
+ for (const observer of this._modelObservers.get(modelClass).valuesArray()) {
observer.modelRemoved(model);
+ }
}
/**
@@ -119,8 +126,9 @@ SDK.TargetManager = class extends Common.Object {
addModelListener(modelClass, eventType, listener, thisObject) {
for (let i = 0; i < this._targets.length; ++i) {
const model = this._targets[i].model(modelClass);
- if (model)
+ if (model) {
model.addEventListener(eventType, listener, thisObject);
+ }
}
this._modelListeners.set(eventType, {modelClass: modelClass, thisObject: thisObject, listener: listener});
}
@@ -132,34 +140,39 @@ SDK.TargetManager = class extends Common.Object {
* @param {!Object=} thisObject
*/
removeModelListener(modelClass, eventType, listener, thisObject) {
- if (!this._modelListeners.has(eventType))
+ if (!this._modelListeners.has(eventType)) {
return;
+ }
for (let i = 0; i < this._targets.length; ++i) {
const model = this._targets[i].model(modelClass);
- if (model)
+ if (model) {
model.removeEventListener(eventType, listener, thisObject);
+ }
}
for (const info of this._modelListeners.get(eventType)) {
- if (info.modelClass === modelClass && info.listener === listener && info.thisObject === thisObject)
+ if (info.modelClass === modelClass && info.listener === listener && info.thisObject === thisObject) {
this._modelListeners.delete(eventType, info);
+ }
}
}
/**
- * @param {!SDK.TargetManager.Observer} targetObserver
+ * @param {!Observer} targetObserver
*/
observeTargets(targetObserver) {
- if (this._observers.indexOf(targetObserver) !== -1)
+ if (this._observers.indexOf(targetObserver) !== -1) {
throw new Error('Observer can only be registered once');
- for (const target of this._targets)
+ }
+ for (const target of this._targets) {
targetObserver.targetAdded(target);
+ }
this._observers.push(targetObserver);
}
/**
- * @param {!SDK.TargetManager.Observer} targetObserver
+ * @param {!Observer} targetObserver
*/
unobserveTargets(targetObserver) {
this._observers.remove(targetObserver);
@@ -178,23 +191,27 @@ SDK.TargetManager = class extends Common.Object {
createTarget(id, name, type, parentTarget, sessionId, waitForDebuggerInPage, connection) {
const target =
new SDK.Target(this, id, name, type, parentTarget, sessionId || '', this._isSuspended, connection || null);
- if (waitForDebuggerInPage)
+ if (waitForDebuggerInPage) {
target.pageAgent().waitForDebugger();
+ }
target.createModels(new Set(this._modelObservers.keysArray()));
this._targets.push(target);
const copy = this._observers.slice(0);
- for (const observer of copy)
+ for (const observer of copy) {
observer.targetAdded(target);
+ }
- for (const modelClass of target.models().keys())
+ for (const modelClass of target.models().keys()) {
this.modelAdded(target, modelClass, target.models().get(modelClass));
+ }
for (const key of this._modelListeners.keysArray()) {
for (const info of this._modelListeners.get(key)) {
const model = target.model(info.modelClass);
- if (model)
+ if (model) {
model.addEventListener(key, info.listener, info.thisObject);
+ }
}
}
@@ -205,22 +222,26 @@ SDK.TargetManager = class extends Common.Object {
* @param {!SDK.Target} target
*/
removeTarget(target) {
- if (!this._targets.includes(target))
+ if (!this._targets.includes(target)) {
return;
+ }
this._targets.remove(target);
- for (const modelClass of target.models().keys())
+ for (const modelClass of target.models().keys()) {
this._modelRemoved(target, modelClass, target.models().get(modelClass));
+ }
const copy = this._observers.slice(0);
- for (const observer of copy)
+ for (const observer of copy) {
observer.targetRemoved(target);
+ }
for (const key of this._modelListeners.keysArray()) {
for (const info of this._modelListeners.get(key)) {
const model = target.model(info.modelClass);
- if (model)
+ if (model) {
model.removeEventListener(key, info.listener, info.thisObject);
+ }
}
}
}
@@ -239,8 +260,9 @@ SDK.TargetManager = class extends Common.Object {
targetById(id) {
// TODO(dgozman): add a map id -> target.
for (let i = 0; i < this._targets.length; ++i) {
- if (this._targets[i].id() === id)
+ if (this._targets[i].id() === id) {
return this._targets[i];
+ }
}
return null;
}
@@ -251,10 +273,10 @@ SDK.TargetManager = class extends Common.Object {
mainTarget() {
return this._targets[0] || null;
}
-};
+}
/** @enum {symbol} */
-SDK.TargetManager.Events = {
+export const Events = {
AvailableTargetsChanged: Symbol('AvailableTargetsChanged'),
InspectedURLChanged: Symbol('InspectedURLChanged'),
NameChanged: Symbol('NameChanged'),
@@ -264,39 +286,57 @@ SDK.TargetManager.Events = {
/**
* @interface
*/
-SDK.TargetManager.Observer = function() {};
-
-SDK.TargetManager.Observer.prototype = {
+export class Observer {
/**
* @param {!SDK.Target} target
*/
- targetAdded(target) {},
+ targetAdded(target) {
+ }
/**
* @param {!SDK.Target} target
*/
- targetRemoved(target) {},
-};
+ targetRemoved(target) {
+ }
+}
/**
* @interface
* @template T
*/
-SDK.SDKModelObserver = function() {};
-
-SDK.SDKModelObserver.prototype = {
+export class SDKModelObserver {
/**
* @param {!T} model
*/
- modelAdded(model) {},
+ modelAdded(model) {
+ }
/**
* @param {!T} model
*/
- modelRemoved(model) {},
-};
+ modelRemoved(model) {
+ }
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.TargetManager = TargetManager;
+
+/** @enum {symbol} */
+SDK.TargetManager.Events = Events;
+
+/** @interface */
+SDK.TargetManager.Observer = Observer;
+
+/** @interface */
+SDK.SDKModelObserver = SDKModelObserver;
/**
- * @type {!SDK.TargetManager}
+ * @type {!TargetManager}
*/
-SDK.targetManager = new SDK.TargetManager();
+SDK.targetManager = new TargetManager(); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingManager.js
index d324dc2dcc6..7bf2c7c2f84 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingManager.js
@@ -3,40 +3,20 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-/**
- * @interface
- */
-SDK.TracingManagerClient = function() {};
-
-SDK.TracingManagerClient.prototype = {
- /**
- * @param {!Array.<!SDK.TracingManager.EventPayload>} events
- */
- traceEventsCollected(events) {},
- tracingComplete() {},
- /**
- * @param {number} usage
- */
- tracingBufferUsage(usage) {},
- /**
- * @param {number} progress
- */
- eventsRetrievalProgress(progress) {}
-};
/**
* @unrestricted
*/
-SDK.TracingManager = class extends SDK.SDKModel {
+export default class TracingManager extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
this._tracingAgent = target.tracingAgent();
- target.registerTracingDispatcher(new SDK.TracingDispatcher(this));
+ target.registerTracingDispatcher(new TracingDispatcher(this));
- /** @type {?SDK.TracingManagerClient} */
+ /** @type {?TracingManagerClient} */
this._activeClient = null;
this._eventBufferSize = 0;
this._eventsRetrieved = 0;
@@ -63,8 +43,9 @@ SDK.TracingManager = class extends SDK.SDKModel {
return;
}
- if (this._eventsRetrieved > this._eventBufferSize)
+ if (this._eventsRetrieved > this._eventBufferSize) {
this._eventsRetrieved = this._eventBufferSize;
+ }
this._activeClient.eventsRetrievalProgress(this._eventsRetrieved / this._eventBufferSize);
}
@@ -77,70 +58,78 @@ SDK.TracingManager = class extends SDK.SDKModel {
}
/**
- * @param {!SDK.TracingManagerClient} client
+ * @param {!TracingManagerClient} client
* @param {string} categoryFilter
* @param {string} options
* @return {!Promise<!Object>}
*/
async start(client, categoryFilter, options) {
- if (this._activeClient)
+ if (this._activeClient) {
throw new Error('Tracing is already started');
+ }
const bufferUsageReportingIntervalMs = 500;
this._activeClient = client;
const args = {
bufferUsageReportingInterval: bufferUsageReportingIntervalMs,
categories: categoryFilter,
options: options,
- transferMode: SDK.TracingManager.TransferMode.ReportEvents
+ transferMode: TransferMode.ReportEvents
};
const response = await this._tracingAgent.invoke_start(args);
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
this._activeClient = null;
+ }
return response;
}
stop() {
- if (!this._activeClient)
+ if (!this._activeClient) {
throw new Error('Tracing is not started');
- if (this._finishing)
+ }
+ if (this._finishing) {
throw new Error('Tracing is already being stopped');
+ }
this._finishing = true;
this._tracingAgent.end();
}
-};
-
-SDK.SDKModel.register(SDK.TracingManager, SDK.Target.Capability.Tracing, false);
+}
-/** @typedef {!{
- cat: (string|undefined),
- pid: number,
- tid: number,
- ts: number,
- ph: string,
- name: string,
- args: !Object,
- dur: number,
- id: string,
- id2: (!{global: (string|undefined), local: (string|undefined)}|undefined),
- scope: string,
- bind_id: string,
- s: string
- }}
- */
-SDK.TracingManager.EventPayload;
-
-SDK.TracingManager.TransferMode = {
+export const TransferMode = {
ReportEvents: 'ReportEvents',
ReturnAsStream: 'ReturnAsStream'
};
/**
+ * @interface
+ */
+export class TracingManagerClient {
+ /**
+ * @param {!Array.<!SDK.TracingManager.EventPayload>} events
+ */
+ traceEventsCollected(events) {
+ }
+
+ tracingComplete() {
+ }
+ /**
+ * @param {number} usage
+ */
+ tracingBufferUsage(usage) {
+ }
+ /**
+ * @param {number} progress
+ */
+ eventsRetrievalProgress(progress) {
+ }
+}
+
+/**
* @implements {Protocol.TracingDispatcher}
* @unrestricted
*/
-SDK.TracingDispatcher = class {
+export class TracingDispatcher {
/**
- * @param {!SDK.TracingManager} tracingManager
+ * @param {!TracingManager} tracingManager
*/
constructor(tracingManager) {
this._tracingManager = tracingManager;
@@ -170,4 +159,41 @@ SDK.TracingDispatcher = class {
tracingComplete() {
this._tracingManager._tracingComplete();
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.TracingManager = TracingManager;
+
+SDK.TracingManager.TransferMode = TransferMode;
+
+/** @interface */
+SDK.TracingManagerClient = TracingManagerClient;
+
+/** @constructor */
+SDK.TracingDispatcher = TracingDispatcher;
+
+/** @typedef {!{
+ cat: (string|undefined),
+ pid: number,
+ tid: number,
+ ts: number,
+ ph: string,
+ name: string,
+ args: !Object,
+ dur: number,
+ id: string,
+ id2: (!{global: (string|undefined), local: (string|undefined)}|undefined),
+ scope: string,
+ bind_id: string,
+ s: string
+ }}
+ */
+SDK.TracingManager.EventPayload;
+
+SDK.SDKModel.register(SDK.TracingManager, SDK.Target.Capability.Tracing, false); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
index 7ec290a905c..9f262ee3072 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
@@ -4,27 +4,27 @@
* found in the LICENSE file.
*/
-SDK.TracingModel = class {
+export default class TracingModel {
/**
- * @param {!SDK.BackingStorage} backingStorage
+ * @param {!BackingStorage} backingStorage
*/
constructor(backingStorage) {
this._backingStorage = backingStorage;
// Avoid extra reset of the storage as it's expensive.
this._firstWritePending = true;
- /** @type {!Map<(number|string), !SDK.TracingModel.Process>} */
+ /** @type {!Map<(number|string), !Process>} */
this._processById = new Map();
this._processByName = new Map();
this._minimumRecordTime = 0;
this._maximumRecordTime = 0;
this._devToolsMetadataEvents = [];
- /** @type {!Array<!SDK.TracingModel.Event>} */
+ /** @type {!Array<!Event>} */
this._asyncEvents = [];
- /** @type {!Map<string, !SDK.TracingModel.AsyncEvent>} */
+ /** @type {!Map<string, !AsyncEvent>} */
this._openAsyncEvents = new Map();
- /** @type {!Map<string, !Array<!SDK.TracingModel.AsyncEvent>>} */
+ /** @type {!Map<string, !Array<!AsyncEvent>>} */
this._openNestableAsyncEvents = new Map();
- /** @type {!Map<string, !SDK.TracingModel.ProfileEventsGroup>} */
+ /** @type {!Map<string, !ProfileEventsGroup>} */
this._profileGroups = new Map();
/** @type {!Map<string, !Set<string>>} */
this._parsedCategories = new Map();
@@ -51,8 +51,7 @@ SDK.TracingModel = class {
* @return {boolean}
*/
static isAsyncPhase(phase) {
- return SDK.TracingModel.isNestableAsyncPhase(phase) || phase === 'S' || phase === 'T' || phase === 'F' ||
- phase === 'p';
+ return TracingModel.isNestableAsyncPhase(phase) || phase === 'S' || phase === 'T' || phase === 'F' || phase === 'p';
}
/**
@@ -64,13 +63,13 @@ SDK.TracingModel = class {
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
* @return {boolean}
*/
static isTopLevelEvent(event) {
- return event.hasCategory(SDK.TracingModel.DevToolsTimelineEventCategory) && event.name === 'RunTask' ||
- event.hasCategory(SDK.TracingModel.LegacyTopLevelEventCategory) ||
- event.hasCategory(SDK.TracingModel.DevToolsMetadataEventCategory) &&
+ return event.hasCategory(DevToolsTimelineEventCategory) && event.name === 'RunTask' ||
+ event.hasCategory(LegacyTopLevelEventCategory) ||
+ event.hasCategory(DevToolsMetadataEventCategory) &&
event.name === 'Program'; // Older timelines may have this instead of toplevel.
}
@@ -80,8 +79,9 @@ SDK.TracingModel = class {
*/
static _extractId(payload) {
const scope = payload.scope || '';
- if (typeof payload.id2 === 'undefined')
+ if (typeof payload.id2 === 'undefined') {
return scope && payload.id ? `${scope}@${payload.id}` : payload.id;
+ }
const id2 = payload.id2;
if (typeof id2 === 'object' && ('global' in id2) !== ('local' in id2)) {
return typeof id2['global'] !== 'undefined' ? `:${scope}:${id2['global']}` :
@@ -92,8 +92,8 @@ SDK.TracingModel = class {
}
/**
- * @param {!SDK.TracingModel} tracingModel
- * @return {?SDK.TracingModel.Thread}
+ * @param {!TracingModel} tracingModel
+ * @return {?Thread}
*
* TODO: Move this to a better place. This is here just for convenience o
* re-use between modules. This really belongs to a higher level, since it
@@ -102,30 +102,35 @@ SDK.TracingModel = class {
static browserMainThread(tracingModel) {
const processes = tracingModel.sortedProcesses();
// Avoid warning for an empty model.
- if (!processes.length)
+ if (!processes.length) {
return null;
+ }
const browserMainThreadName = 'CrBrowserMain';
const browserProcesses = [];
const browserMainThreads = [];
for (const process of processes) {
- if (process.name().toLowerCase().endsWith('browser'))
+ if (process.name().toLowerCase().endsWith('browser')) {
browserProcesses.push(process);
+ }
browserMainThreads.push(...process.sortedThreads().filter(t => t.name() === browserMainThreadName));
}
- if (browserMainThreads.length === 1)
+ if (browserMainThreads.length === 1) {
return browserMainThreads[0];
- if (browserProcesses.length === 1)
+ }
+ if (browserProcesses.length === 1) {
return browserProcesses[0].threadByName(browserMainThreadName);
+ }
const tracingStartedInBrowser =
tracingModel.devToolsMetadataEvents().filter(e => e.name === 'TracingStartedInBrowser');
- if (tracingStartedInBrowser.length === 1)
+ if (tracingStartedInBrowser.length === 1) {
return tracingStartedInBrowser[0].thread;
+ }
Common.console.error('Failed to find browser main thread in trace, some timeline features may be unavailable');
return null;
}
/**
- * @return {!Array.<!SDK.TracingModel.Event>}
+ * @return {!Array.<!Event>}
*/
devToolsMetadataEvents() {
return this._devToolsMetadataEvents;
@@ -135,8 +140,9 @@ SDK.TracingModel = class {
* @param {!Array.<!SDK.TracingManager.EventPayload>} events
*/
addEvents(events) {
- for (let i = 0; i < events.length; ++i)
+ for (let i = 0; i < events.length; ++i) {
this._addEvent(events[i]);
+ }
}
tracingComplete() {
@@ -145,14 +151,16 @@ SDK.TracingModel = class {
this._backingStorage.finishWriting();
this._firstWritePending = false;
for (const process of this._processById.values()) {
- for (const thread of process._threads.values())
+ for (const thread of process._threads.values()) {
thread.tracingComplete();
+ }
}
}
dispose() {
- if (!this._firstWritePending)
+ if (!this._firstWritePending) {
this._backingStorage.reset();
+ }
}
/**
@@ -165,13 +173,15 @@ SDK.TracingModel = class {
for (const thread of process._threads.values()) {
for (const event of thread.events()) {
event.startTime += offset;
- if (typeof event.endTime === 'number')
+ if (typeof event.endTime === 'number') {
event.endTime += offset;
+ }
}
for (const event of thread.asyncEvents()) {
event.startTime += offset;
- if (typeof event.endTime === 'number')
+ if (typeof event.endTime === 'number') {
event.endTime += offset;
+ }
}
}
}
@@ -183,11 +193,11 @@ SDK.TracingModel = class {
_addEvent(payload) {
let process = this._processById.get(payload.pid);
if (!process) {
- process = new SDK.TracingModel.Process(this, payload.pid);
+ process = new Process(this, payload.pid);
this._processById.set(payload.pid, process);
}
- const phase = SDK.TracingModel.Phase;
+ const phase = Phase;
const eventsDelimiter = ',\n';
this._backingStorage.appendString(this._firstWritePending ? '[' : eventsDelimiter);
this._firstWritePending = false;
@@ -195,22 +205,25 @@ SDK.TracingModel = class {
const isAccessible = payload.ph === phase.SnapshotObject;
let backingStorage = null;
const keepStringsLessThan = 10000;
- if (isAccessible && stringPayload.length > keepStringsLessThan)
+ if (isAccessible && stringPayload.length > keepStringsLessThan) {
backingStorage = this._backingStorage.appendAccessibleString(stringPayload);
- else
+ } else {
this._backingStorage.appendString(stringPayload);
+ }
const timestamp = payload.ts / 1000;
// We do allow records for unrelated threads to arrive out-of-order,
// so there's a chance we're getting records from the past.
if (timestamp && (!this._minimumRecordTime || timestamp < this._minimumRecordTime) &&
- (payload.ph === phase.Begin || payload.ph === phase.Complete || payload.ph === phase.Instant))
+ (payload.ph === phase.Begin || payload.ph === phase.Complete || payload.ph === phase.Instant)) {
this._minimumRecordTime = timestamp;
+ }
const endTimeStamp = (payload.ts + (payload.dur || 0)) / 1000;
this._maximumRecordTime = Math.max(this._maximumRecordTime, endTimeStamp);
const event = process._addEvent(payload);
- if (!event)
+ if (!event) {
return;
+ }
if (payload.ph === phase.Sample) {
this._addSampleEvent(event);
return;
@@ -218,48 +231,52 @@ SDK.TracingModel = class {
// Build async event when we've got events from all threads & processes, so we can sort them and process in the
// chronological order. However, also add individual async events to the thread flow (above), so we can easily
// display them on the same chart as other events, should we choose so.
- if (SDK.TracingModel.isAsyncPhase(payload.ph))
+ if (TracingModel.isAsyncPhase(payload.ph)) {
this._asyncEvents.push(event);
+ }
event._setBackingStorage(backingStorage);
- if (event.hasCategory(SDK.TracingModel.DevToolsMetadataEventCategory))
+ if (event.hasCategory(DevToolsMetadataEventCategory)) {
this._devToolsMetadataEvents.push(event);
+ }
- if (payload.ph !== phase.Metadata)
+ if (payload.ph !== phase.Metadata) {
return;
+ }
switch (payload.name) {
- case SDK.TracingModel.MetadataEvent.ProcessSortIndex:
+ case MetadataEvent.ProcessSortIndex:
process._setSortIndex(payload.args['sort_index']);
break;
- case SDK.TracingModel.MetadataEvent.ProcessName:
+ case MetadataEvent.ProcessName:
const processName = payload.args['name'];
process._setName(processName);
this._processByName.set(processName, process);
break;
- case SDK.TracingModel.MetadataEvent.ThreadSortIndex:
+ case MetadataEvent.ThreadSortIndex:
process.threadById(payload.tid)._setSortIndex(payload.args['sort_index']);
break;
- case SDK.TracingModel.MetadataEvent.ThreadName:
+ case MetadataEvent.ThreadName:
process.threadById(payload.tid)._setName(payload.args['name']);
break;
}
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
_addSampleEvent(event) {
const id = `${event.thread.process().id()}:${event.id}`;
const group = this._profileGroups.get(id);
- if (group)
+ if (group) {
group._addChild(event);
- else
- this._profileGroups.set(id, new SDK.TracingModel.ProfileEventsGroup(event));
+ } else {
+ this._profileGroups.set(id, new ProfileEventsGroup(event));
+ }
}
/**
- * @param {!SDK.TracingModel.Event} event
- * @return {?SDK.TracingModel.ProfileEventsGroup}
+ * @param {!Event} event
+ * @return {?ProfileEventsGroup}
*/
profileGroup(event) {
return this._profileGroups.get(`${event.thread.process().id()}:${event.id}`) || null;
@@ -280,15 +297,15 @@ SDK.TracingModel = class {
}
/**
- * @return {!Array.<!SDK.TracingModel.Process>}
+ * @return {!Array.<!Process>}
*/
sortedProcesses() {
- return SDK.TracingModel.NamedObject._sort(this._processById.valuesArray());
+ return NamedObject._sort(this._processById.valuesArray());
}
/**
* @param {string} name
- * @return {?SDK.TracingModel.Process}
+ * @return {?Process}
*/
processByName(name) {
return this._processByName.get(name);
@@ -296,7 +313,7 @@ SDK.TracingModel = class {
/**
* @param {number} pid
- * @return {?SDK.TracingModel.Process}
+ * @return {?Process}
*/
processById(pid) {
return this._processById.get(pid) || null;
@@ -305,7 +322,7 @@ SDK.TracingModel = class {
/**
* @param {string} processName
* @param {string} threadName
- * @return {?SDK.TracingModel.Thread}
+ * @return {?Thread}
*/
threadByName(processName, threadName) {
const process = this.processByName(processName);
@@ -313,13 +330,14 @@ SDK.TracingModel = class {
}
_processPendingAsyncEvents() {
- this._asyncEvents.sort(SDK.TracingModel.Event.compareStartTime);
+ this._asyncEvents.sort(Event.compareStartTime);
for (let i = 0; i < this._asyncEvents.length; ++i) {
const event = this._asyncEvents[i];
- if (SDK.TracingModel.isNestableAsyncPhase(event.phase))
+ if (TracingModel.isNestableAsyncPhase(event.phase)) {
this._addNestableAsyncEvent(event);
- else
+ } else {
this._addAsyncEvent(event);
+ }
}
this._asyncEvents = [];
this._closeOpenAsyncEvents();
@@ -335,17 +353,18 @@ SDK.TracingModel = class {
this._openAsyncEvents.clear();
for (const eventStack of this._openNestableAsyncEvents.values()) {
- while (eventStack.length)
+ while (eventStack.length) {
eventStack.pop().setEndTime(this._maximumRecordTime);
+ }
}
this._openNestableAsyncEvents.clear();
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
_addNestableAsyncEvent(event) {
- const phase = SDK.TracingModel.Phase;
+ const phase = Phase;
const key = event.categoriesString + '.' + event.id;
let openEventsStack = this._openNestableAsyncEvents.get(key);
@@ -355,19 +374,21 @@ SDK.TracingModel = class {
openEventsStack = [];
this._openNestableAsyncEvents.set(key, openEventsStack);
}
- const asyncEvent = new SDK.TracingModel.AsyncEvent(event);
+ const asyncEvent = new AsyncEvent(event);
openEventsStack.push(asyncEvent);
event.thread._addAsyncEvent(asyncEvent);
break;
case phase.NestableAsyncInstant:
- if (openEventsStack && openEventsStack.length)
+ if (openEventsStack && openEventsStack.length) {
openEventsStack.peekLast()._addStep(event);
+ }
break;
case phase.NestableAsyncEnd:
- if (!openEventsStack || !openEventsStack.length)
+ if (!openEventsStack || !openEventsStack.length) {
break;
+ }
const top = openEventsStack.pop();
if (top.name !== event.name) {
console.error(
@@ -379,10 +400,10 @@ SDK.TracingModel = class {
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
_addAsyncEvent(event) {
- const phase = SDK.TracingModel.Phase;
+ const phase = Phase;
const key = event.categoriesString + '.' + event.name + '.' + event.id;
let asyncEvent = this._openAsyncEvents.get(key);
@@ -391,7 +412,7 @@ SDK.TracingModel = class {
console.error(`Event ${event.name} has already been started`);
return;
}
- asyncEvent = new SDK.TracingModel.AsyncEvent(event);
+ asyncEvent = new AsyncEvent(event);
this._openAsyncEvents.set(key, asyncEvent);
event.thread._addAsyncEvent(asyncEvent);
return;
@@ -420,7 +441,7 @@ SDK.TracingModel = class {
}
/**
- * @return {!SDK.BackingStorage}
+ * @return {!BackingStorage}
*/
backingStorage() {
return this._backingStorage;
@@ -438,12 +459,12 @@ SDK.TracingModel = class {
}
return parsedCategories;
}
-};
+}
/**
* @enum {string}
*/
-SDK.TracingModel.Phase = {
+export const Phase = {
Begin: 'B',
End: 'E',
Complete: 'X',
@@ -466,7 +487,7 @@ SDK.TracingModel.Phase = {
DeleteObject: 'D'
};
-SDK.TracingModel.MetadataEvent = {
+export const MetadataEvent = {
ProcessSortIndex: 'process_sort_index',
ProcessName: 'process_name',
ThreadSortIndex: 'thread_sort_index',
@@ -475,43 +496,45 @@ SDK.TracingModel.MetadataEvent = {
// TODO(alph): LegacyTopLevelEventCategory is not recorded since M74 and used for loading
// legacy profiles. Drop at some point.
-SDK.TracingModel.LegacyTopLevelEventCategory = 'toplevel';
-SDK.TracingModel.DevToolsMetadataEventCategory = 'disabled-by-default-devtools.timeline';
-SDK.TracingModel.DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';
-SDK.TracingModel.FrameLifecycleEventCategory = 'cc,devtools';
+export const LegacyTopLevelEventCategory = 'toplevel';
+
+export const DevToolsMetadataEventCategory = 'disabled-by-default-devtools.timeline';
+export const DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';
+export const FrameLifecycleEventCategory = 'cc,devtools';
/**
* @interface
*/
-SDK.BackingStorage = function() {};
-
-SDK.BackingStorage.prototype = {
+export class BackingStorage {
/**
* @param {string} string
*/
- appendString(string) {},
+ appendString(string) {
+ }
/**
* @param {string} string
* @return {function():!Promise.<?string>}
*/
- appendAccessibleString(string) {},
+ appendAccessibleString(string) {
+ }
- finishWriting() {},
+ finishWriting() {
+ }
reset() {}
-};
+}
/**
* @unrestricted
*/
-SDK.TracingModel.Event = class {
+export class Event {
/**
* @param {string|undefined} categories
* @param {string} name
- * @param {!SDK.TracingModel.Phase} phase
+ * @param {!Phase} phase
* @param {number} startTime
- * @param {!SDK.TracingModel.Thread} thread
+ * @param {!Thread} thread
*/
constructor(categories, name, phase, startTime, thread) {
/** @type {string} */
@@ -520,11 +543,11 @@ SDK.TracingModel.Event = class {
this._parsedCategories = thread._model._parsedCategoriesForString(this.categoriesString);
/** @type {string} */
this.name = name;
- /** @type {!SDK.TracingModel.Phase} */
+ /** @type {!Phase} */
this.phase = phase;
/** @type {number} */
this.startTime = startTime;
- /** @type {!SDK.TracingModel.Thread} */
+ /** @type {!Thread} */
this.thread = thread;
/** @type {!Object} */
this.args = {};
@@ -534,29 +557,33 @@ SDK.TracingModel.Event = class {
}
/**
+ * @this {null}
* @param {!SDK.TracingManager.EventPayload} payload
- * @param {!SDK.TracingModel.Thread} thread
- * @return {!SDK.TracingModel.Event}
+ * @param {!Thread} thread
+ * @return {!Event}
*/
static fromPayload(payload, thread) {
- const event = new SDK.TracingModel.Event(
- payload.cat, payload.name, /** @type {!SDK.TracingModel.Phase} */ (payload.ph), payload.ts / 1000, thread);
- if (payload.args)
+ const event = new Event(payload.cat, payload.name, /** @type {!Phase} */ (payload.ph), payload.ts / 1000, thread);
+ if (payload.args) {
event.addArgs(payload.args);
- if (typeof payload.dur === 'number')
+ }
+ if (typeof payload.dur === 'number') {
event.setEndTime((payload.ts + payload.dur) / 1000);
- const id = SDK.TracingModel._extractId(payload);
- if (typeof id !== 'undefined')
+ }
+ const id = TracingModel._extractId(payload);
+ if (typeof id !== 'undefined') {
event.id = id;
- if (payload.bind_id)
+ }
+ if (payload.bind_id) {
event.bind_id = payload.bind_id;
+ }
return event;
}
/**
- * @param {!SDK.TracingModel.Event} a
- * @param {!SDK.TracingModel.Event} b
+ * @param {!Event} a
+ * @param {!Event} b
* @return {number}
*/
static compareStartTime(a, b) {
@@ -564,8 +591,8 @@ SDK.TracingModel.Event = class {
}
/**
- * @param {!SDK.TracingModel.Event} a
- * @param {!SDK.TracingModel.Event} b
+ * @param {!Event} a
+ * @param {!Event} b
* @return {number}
*/
static orderedCompareStartTime(a, b) {
@@ -601,20 +628,22 @@ SDK.TracingModel.Event = class {
addArgs(args) {
// Shallow copy args to avoid modifying original payload which may be saved to file.
for (const name in args) {
- if (name in this.args)
+ if (name in this.args) {
console.error('Same argument name (' + name + ') is used for begin and end phases of ' + this.name);
+ }
this.args[name] = args[name];
}
}
/**
- * @param {!SDK.TracingModel.Event} endEvent
+ * @param {!Event} endEvent
*/
_complete(endEvent) {
- if (endEvent.args)
+ if (endEvent.args) {
this.addArgs(endEvent.args);
- else
+ } else {
console.error('Missing mandatory event argument \'args\' at ' + endEvent.startTime);
+ }
this.setEndTime(endEvent.startTime);
}
@@ -623,17 +652,17 @@ SDK.TracingModel.Event = class {
*/
_setBackingStorage(backingStorage) {
}
-};
+}
-SDK.TracingModel.ObjectSnapshot = class extends SDK.TracingModel.Event {
+export class ObjectSnapshot extends Event {
/**
* @param {string|undefined} category
* @param {string} name
* @param {number} startTime
- * @param {!SDK.TracingModel.Thread} thread
+ * @param {!Thread} thread
*/
constructor(category, name, startTime, thread) {
- super(category, name, SDK.TracingModel.Phase.SnapshotObject, startTime, thread);
+ super(category, name, Phase.SnapshotObject, startTime, thread);
/** @type {?function():!Promise<?string>} */
this._backingStorage = null;
/** @type {string} */
@@ -643,21 +672,25 @@ SDK.TracingModel.ObjectSnapshot = class extends SDK.TracingModel.Event {
}
/**
+ * @override
+ * @this {null}
* @param {!SDK.TracingManager.EventPayload} payload
- * @param {!SDK.TracingModel.Thread} thread
- * @return {!SDK.TracingModel.ObjectSnapshot}
+ * @param {!Thread} thread
+ * @return {!ObjectSnapshot}
*/
static fromPayload(payload, thread) {
- const snapshot = new SDK.TracingModel.ObjectSnapshot(payload.cat, payload.name, payload.ts / 1000, thread);
- const id = SDK.TracingModel._extractId(payload);
- if (typeof id !== 'undefined')
+ const snapshot = new ObjectSnapshot(payload.cat, payload.name, payload.ts / 1000, thread);
+ const id = TracingModel._extractId(payload);
+ if (typeof id !== 'undefined') {
snapshot.id = id;
+ }
if (!payload.args || !payload.args['snapshot']) {
console.error('Missing mandatory \'snapshot\' argument at ' + payload.ts / 1000);
return snapshot;
}
- if (payload.args)
+ if (payload.args) {
snapshot.addArgs(payload.args);
+ }
return snapshot;
}
@@ -693,8 +726,9 @@ SDK.TracingModel.ObjectSnapshot = class extends SDK.TracingModel.Event {
* @return {!Promise<?>}
*/
objectPromise() {
- if (!this._objectPromise)
+ if (!this._objectPromise) {
this._objectPromise = new Promise(this.requestObject.bind(this));
+ }
return this._objectPromise;
}
@@ -703,20 +737,20 @@ SDK.TracingModel.ObjectSnapshot = class extends SDK.TracingModel.Event {
* @param {?function():!Promise.<?>} backingStorage
*/
_setBackingStorage(backingStorage) {
- if (!backingStorage)
+ if (!backingStorage) {
return;
+ }
this._backingStorage = backingStorage;
this.args = {};
}
-};
-
+}
/**
* @unrestricted
*/
-SDK.TracingModel.AsyncEvent = class extends SDK.TracingModel.Event {
+export class AsyncEvent extends Event {
/**
- * @param {!SDK.TracingModel.Event} startEvent
+ * @param {!Event} startEvent
*/
constructor(startEvent) {
super(startEvent.categoriesString, startEvent.name, startEvent.phase, startEvent.startTime, startEvent.thread);
@@ -725,42 +759,42 @@ SDK.TracingModel.AsyncEvent = class extends SDK.TracingModel.Event {
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
_addStep(event) {
this.steps.push(event);
- if (event.phase === SDK.TracingModel.Phase.AsyncEnd || event.phase === SDK.TracingModel.Phase.NestableAsyncEnd) {
+ if (event.phase === Phase.AsyncEnd || event.phase === Phase.NestableAsyncEnd) {
this.setEndTime(event.startTime);
// FIXME: ideally, we shouldn't do this, but this makes the logic of converting
// async console events to sync ones much simpler.
this.steps[0].setEndTime(event.startTime);
}
}
-};
+}
/**
* @unrestricted
*/
-SDK.TracingModel.ProfileEventsGroup = class {
+export class ProfileEventsGroup {
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
constructor(event) {
- /** @type {!Array<!SDK.TracingModel.Event>} */
+ /** @type {!Array<!Event>} */
this.children = [event];
}
/**
- * @param {!SDK.TracingModel.Event} event
+ * @param {!Event} event
*/
_addChild(event) {
this.children.push(event);
}
-};
+}
-SDK.TracingModel.NamedObject = class {
+export class NamedObject {
/**
- * @param {!SDK.TracingModel} model
+ * @param {!TracingModel} model
* @param {number} id
*/
constructor(model, id) {
@@ -771,12 +805,12 @@ SDK.TracingModel.NamedObject = class {
}
/**
- * @param {!Array.<!SDK.TracingModel.NamedObject>} array
+ * @param {!Array.<!NamedObject>} array
*/
static _sort(array) {
/**
- * @param {!SDK.TracingModel.NamedObject} a
- * @param {!SDK.TracingModel.NamedObject} b
+ * @param {!NamedObject} a
+ * @param {!NamedObject} b
*/
function comparator(a, b) {
return a._sortIndex !== b._sortIndex ? a._sortIndex - b._sortIndex : a.name().localeCompare(b.name());
@@ -804,16 +838,16 @@ SDK.TracingModel.NamedObject = class {
_setSortIndex(sortIndex) {
this._sortIndex = sortIndex;
}
-};
+}
-SDK.TracingModel.Process = class extends SDK.TracingModel.NamedObject {
+export class Process extends NamedObject {
/**
- * @param {!SDK.TracingModel} model
+ * @param {!TracingModel} model
* @param {number} id
*/
constructor(model, id) {
super(model, id);
- /** @type {!Map<number, !SDK.TracingModel.Thread>} */
+ /** @type {!Map<number, !Thread>} */
this._threads = new Map();
this._threadByName = new Map();
}
@@ -827,12 +861,12 @@ SDK.TracingModel.Process = class extends SDK.TracingModel.NamedObject {
/**
* @param {number} id
- * @return {!SDK.TracingModel.Thread}
+ * @return {!Thread}
*/
threadById(id) {
let thread = this._threads.get(id);
if (!thread) {
- thread = new SDK.TracingModel.Thread(this, id);
+ thread = new Thread(this, id);
this._threads.set(id, thread);
}
return thread;
@@ -840,7 +874,7 @@ SDK.TracingModel.Process = class extends SDK.TracingModel.NamedObject {
/**
* @param {string} name
- * @return {?SDK.TracingModel.Thread}
+ * @return {?Thread}
*/
threadByName(name) {
return this._threadByName.get(name) || null;
@@ -848,7 +882,7 @@ SDK.TracingModel.Process = class extends SDK.TracingModel.NamedObject {
/**
* @param {string} name
- * @param {!SDK.TracingModel.Thread} thread
+ * @param {!Thread} thread
*/
_setThreadByName(name, thread) {
this._threadByName.set(name, thread);
@@ -856,23 +890,23 @@ SDK.TracingModel.Process = class extends SDK.TracingModel.NamedObject {
/**
* @param {!SDK.TracingManager.EventPayload} payload
- * @return {?SDK.TracingModel.Event} event
+ * @return {?Event} event
*/
_addEvent(payload) {
return this.threadById(payload.tid)._addEvent(payload);
}
/**
- * @return {!Array.<!SDK.TracingModel.Thread>}
+ * @return {!Array.<!Thread>}
*/
sortedThreads() {
- return SDK.TracingModel.NamedObject._sort(this._threads.valuesArray());
+ return NamedObject._sort(this._threads.valuesArray());
}
-};
+}
-SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
+export class Thread extends NamedObject {
/**
- * @param {!SDK.TracingModel.Process} process
+ * @param {!Process} process
* @param {number} id
*/
constructor(process, id) {
@@ -884,9 +918,9 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
}
tracingComplete() {
- this._asyncEvents.sort(SDK.TracingModel.Event.compareStartTime);
- this._events.sort(SDK.TracingModel.Event.compareStartTime);
- const phases = SDK.TracingModel.Phase;
+ this._asyncEvents.sort(Event.compareStartTime);
+ this._events.sort(Event.compareStartTime);
+ const phases = Phase;
const stack = [];
for (let i = 0; i < this._events.length; ++i) {
const e = this._events[i];
@@ -895,8 +929,9 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
case phases.End:
this._events[i] = null; // Mark for removal.
// Quietly ignore unbalanced close events, they're legit (we could have missed start one).
- if (!stack.length)
+ if (!stack.length) {
continue;
+ }
const top = stack.pop();
if (top.name !== e.name || top.categoriesString !== e.categoriesString) {
console.error(
@@ -911,23 +946,24 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
break;
}
}
- while (stack.length)
+ while (stack.length) {
stack.pop().setEndTime(this._model.maximumRecordTime());
+ }
this._events.remove(null, false);
}
/**
* @param {!SDK.TracingManager.EventPayload} payload
- * @return {?SDK.TracingModel.Event} event
+ * @return {?Event} event
*/
_addEvent(payload) {
- const event = payload.ph === SDK.TracingModel.Phase.SnapshotObject ?
- SDK.TracingModel.ObjectSnapshot.fromPayload(payload, this) :
- SDK.TracingModel.Event.fromPayload(payload, this);
- if (SDK.TracingModel.isTopLevelEvent(event)) {
+ const event = payload.ph === Phase.SnapshotObject ? ObjectSnapshot.fromPayload(payload, this) :
+ Event.fromPayload(payload, this);
+ if (TracingModel.isTopLevelEvent(event)) {
// Discard nested "top-level" events.
- if (this._lastTopLevelEvent && this._lastTopLevelEvent.endTime > event.startTime)
+ if (this._lastTopLevelEvent && this._lastTopLevelEvent.endTime > event.startTime) {
return null;
+ }
this._lastTopLevelEvent = event;
}
this._events.push(event);
@@ -935,7 +971,7 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
}
/**
- * @param {!SDK.TracingModel.AsyncEvent} asyncEvent
+ * @param {!AsyncEvent} asyncEvent
*/
_addAsyncEvent(asyncEvent) {
this._asyncEvents.push(asyncEvent);
@@ -958,23 +994,63 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
}
/**
- * @return {!SDK.TracingModel.Process}
+ * @return {!Process}
*/
process() {
return this._process;
}
/**
- * @return {!Array.<!SDK.TracingModel.Event>}
+ * @return {!Array.<!Event>}
*/
events() {
return this._events;
}
/**
- * @return {!Array.<!SDK.TracingModel.AsyncEvent>}
+ * @return {!Array.<!AsyncEvent>}
*/
asyncEvents() {
return this._asyncEvents;
}
-};
+}
+
+/* Legacy exported object */
+self.SDK = self.SDK || {};
+
+/* Legacy exported object */
+SDK = SDK || {};
+
+/** @constructor */
+SDK.TracingModel = TracingModel;
+
+SDK.TracingModel.Phase = Phase;
+SDK.TracingModel.MetadataEvent = MetadataEvent;
+SDK.TracingModel.LegacyTopLevelEventCategory = LegacyTopLevelEventCategory;
+SDK.TracingModel.DevToolsMetadataEventCategory = DevToolsMetadataEventCategory;
+SDK.TracingModel.DevToolsTimelineEventCategory = DevToolsTimelineEventCategory;
+SDK.TracingModel.FrameLifecycleEventCategory = FrameLifecycleEventCategory;
+
+/** @constructor */
+SDK.TracingModel.Event = Event;
+
+/** @constructor */
+SDK.TracingModel.ObjectSnapshot = ObjectSnapshot;
+
+/** @constructor */
+SDK.TracingModel.AsyncEvent = AsyncEvent;
+
+/** @constructor */
+SDK.TracingModel.ProfileEventsGroup = ProfileEventsGroup;
+
+/** @constructor */
+SDK.TracingModel.NamedObject = NamedObject;
+
+/** @constructor */
+SDK.TracingModel.Process = Process;
+
+/** @constructor */
+SDK.TracingModel.Thread = Thread;
+
+/** @interface */
+SDK.BackingStorage = BackingStorage;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/module.json b/chromium/third_party/blink/renderer/devtools/front_end/sdk/module.json
index 1fd3f4f4a04..a286bdffdd0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/module.json
@@ -264,7 +264,57 @@
"value": "screen"
}
],
- "tags": "query"
+ "tags": "query",
+ "title": "Emulate CSS media type"
+ },
+ {
+ "type": "setting",
+ "category": "Rendering",
+ "settingName": "emulatedCSSMediaFeaturePrefersColorScheme",
+ "settingType": "enum",
+ "storageType": "session",
+ "defaultValue": "",
+ "options": [
+ {
+ "title": "Do not emulate CSS prefers-color-scheme",
+ "text": "No emulation",
+ "value": ""
+ },
+ {
+ "title": "Emulate CSS prefers-color-scheme: light",
+ "text": "prefers-color-scheme: light",
+ "value": "light"
+ },
+ {
+ "title": "Emulate CSS prefers-color-scheme: dark",
+ "text": "prefers-color-scheme: dark",
+ "value": "dark"
+ }
+ ],
+ "tags": "query",
+ "title": "Emulate CSS media feature prefers-color-scheme"
+ },
+ {
+ "type": "setting",
+ "category": "Rendering",
+ "settingName": "emulatedCSSMediaFeaturePrefersReducedMotion",
+ "settingType": "enum",
+ "storageType": "session",
+ "defaultValue": "",
+ "options": [
+ {
+ "title": "Do not emulate CSS prefers-reduced-motion",
+ "text": "No emulation",
+ "value": ""
+ },
+ {
+ "title": "Emulate CSS prefers-reduced-motion: reduce",
+ "text": "prefers-reduced-motion: reduce",
+ "value": "reduce"
+ }
+ ],
+ "tags": "query",
+ "title": "Emulate CSS media feature prefers-reduced-motion"
},
{
"type": "setting",
@@ -314,11 +364,14 @@
]
}
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "sdk.js",
+ "SDKModel.js",
"Target.js",
"TargetManager.js",
"Connections.js",
- "ContentProviders.js",
+ "CompilerSourceMappingContentProvider.js",
"CookieModel.js",
"CookieParser.js",
"ProfileTreeModel.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk.js
new file mode 100644
index 00000000000..b4653c745c0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk.js
@@ -0,0 +1,115 @@
+// 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 './SDKModel.js';
+import './CSSMetadata.js';
+import '../SupportedCSSProperties.js';
+import './Target.js';
+import './TargetManager.js';
+import './ProfileTreeModel.js';
+import './NetworkRequest.js';
+import './NetworkManager.js';
+import './RuntimeModel.js';
+
+import * as ChildTargetManager from './ChildTargetManager.js';
+import * as CompilerSourceMappingContentProvider from './CompilerSourceMappingContentProvider.js';
+import * as Connections from './Connections.js';
+import * as ConsoleModel from './ConsoleModel.js';
+import * as CookieModel from './CookieModel.js';
+import * as CookieParser from './CookieParser.js';
+import * as CPUProfileDataModel from './CPUProfileDataModel.js';
+import * as CPUProfilerModel from './CPUProfilerModel.js';
+import * as CSSMatchedStyles from './CSSMatchedStyles.js';
+import * as CSSMedia from './CSSMedia.js';
+import * as CSSMetadata from './CSSMetadata.js';
+import * as CSSModel from './CSSModel.js';
+import * as CSSProperty from './CSSProperty.js';
+import * as CSSRule from './CSSRule.js';
+import * as CSSStyleDeclaration from './CSSStyleDeclaration.js';
+import * as CSSStyleSheetHeader from './CSSStyleSheetHeader.js';
+import * as DebuggerModel from './DebuggerModel.js';
+import * as DOMDebuggerModel from './DOMDebuggerModel.js';
+import * as DOMModel from './DOMModel.js';
+import * as EmulationModel from './EmulationModel.js';
+import * as FilmStripModel from './FilmStripModel.js';
+import * as HARLog from './HARLog.js';
+import * as HeapProfilerModel from './HeapProfilerModel.js';
+import * as IsolateManager from './IsolateManager.js';
+import * as LayerTreeBase from './LayerTreeBase.js';
+import * as LogModel from './LogModel.js';
+import * as NetworkLog from './NetworkLog.js';
+import * as NetworkManager from './NetworkManager.js';
+import * as NetworkRequest from './NetworkRequest.js';
+import * as OverlayModel from './OverlayModel.js';
+import * as PaintProfiler from './PaintProfiler.js';
+import * as PerformanceMetricsModel from './PerformanceMetricsModel.js';
+import * as ProfileTreeModel from './ProfileTreeModel.js';
+import * as RemoteObject from './RemoteObject.js';
+import * as Resource from './Resource.js';
+import * as ResourceTreeModel from './ResourceTreeModel.js';
+import * as RuntimeModel from './RuntimeModel.js';
+import * as ScreenCaptureModel from './ScreenCaptureModel.js';
+import * as Script from './Script.js';
+import * as SecurityOriginManager from './SecurityOriginManager.js';
+import * as ServerTiming from './ServerTiming.js';
+import * as ServiceWorkerCacheModel from './ServiceWorkerCacheModel.js';
+import * as ServiceWorkerManager from './ServiceWorkerManager.js';
+import * as SourceMap from './SourceMap.js';
+import * as SourceMapManager from './SourceMapManager.js';
+import * as Target from './Target.js';
+import * as TargetManager from './TargetManager.js';
+import * as TracingManager from './TracingManager.js';
+import * as TracingModel from './TracingModel.js';
+
+export {
+ ChildTargetManager,
+ CompilerSourceMappingContentProvider,
+ Connections,
+ ConsoleModel,
+ CookieModel,
+ CookieParser,
+ CPUProfileDataModel,
+ CPUProfilerModel,
+ CSSMatchedStyles,
+ CSSMedia,
+ CSSMetadata,
+ CSSModel,
+ CSSProperty,
+ CSSRule,
+ CSSStyleDeclaration,
+ CSSStyleSheetHeader,
+ DebuggerModel,
+ DOMDebuggerModel,
+ DOMModel,
+ EmulationModel,
+ FilmStripModel,
+ HARLog,
+ HeapProfilerModel,
+ IsolateManager,
+ LayerTreeBase,
+ LogModel,
+ NetworkLog,
+ NetworkManager,
+ NetworkRequest,
+ OverlayModel,
+ PaintProfiler,
+ PerformanceMetricsModel,
+ ProfileTreeModel,
+ RemoteObject,
+ Resource,
+ ResourceTreeModel,
+ RuntimeModel,
+ ScreenCaptureModel,
+ Script,
+ SecurityOriginManager,
+ ServerTiming,
+ ServiceWorkerCacheModel,
+ ServiceWorkerManager,
+ SourceMap,
+ SourceMapManager,
+ Target,
+ TargetManager,
+ TracingManager,
+ TracingModel,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
index 2a703ce4e83..2df36d8c51d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
@@ -1,5 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
+ <message name="IDS_DEVTOOLS_0203e27fe44545283879b18e7084391b" desc="Error message when failing to load a script source text">
+ Unable to fetch script source.
+ </message>
+ <message name="IDS_DEVTOOLS_021aa7730980fe55529e460ee1367179" desc="Tooltip to explain why a cookie was blocked">
+ This cookie had the &quot;SameSite=Extended&quot; attribute and the request was made on a different site. The different site is outside of the cookie&apos;s trusted first-party set.
+ </message>
+ <message name="IDS_DEVTOOLS_04608e209233c72a33b9a80e8ff2bd58" desc="Tooltip to explain why a cookie was blocked">
+ This cookie had the &quot;SameSite=None&quot; attribute but was not marked &quot;Secure&quot;. Cookies without SameSite restrictions must be marked &quot;Secure&quot; and sent over a secure connection.
+ </message>
+ <message name="IDS_DEVTOOLS_0568216cb82d1edfc0a9482db7b99ba1" desc="Error message when failing to load a script source text via the network">
+ Could not load content for <ph name="THIS__SOURCEURL"><ex>https://example.com</ex>$1s</ph> : HTTP status code: <ph name="STATUSCODE"><ex>404</ex>$2s</ph>
+ </message>
<message name="IDS_DEVTOOLS_07553a11db31a4433684be32cc4716e3" desc="Text in Network Manager">
Cross-Origin Read Blocking (CORB) blocked cross-origin response <ph name="NETWORKREQUEST_URL__">$1s<ex>https://example.com</ex></ph> with MIME type <ph name="NETWORKREQUEST_MIMETYPE">$2s<ex>application</ex></ph>. See https://www.chromestatus.com/feature/5629709824032768 for more details.
</message>
@@ -9,18 +21,33 @@
<message name="IDS_DEVTOOLS_09cdd6a7321c64bae05b8cca859f1461" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Enable cache
</message>
+ <message name="IDS_DEVTOOLS_0b4e8f2008c602c781fee001c917dbf9" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had invalid syntax.
+ </message>
+ <message name="IDS_DEVTOOLS_0d66520dddd8718f59f517582fafaebb" desc="Title of a media query that can be emulated via the Rendering drawer">
+ prefers-color-scheme: light
+ </message>
<message name="IDS_DEVTOOLS_0fe1f9158e2f164da1332501f9e65702" desc="Text in Console Model">
Navigated to <ph name="EVENT_DATA_URL">$1s<ex>https://example.com</ex></ph>
</message>
<message name="IDS_DEVTOOLS_1023bf87beb1d2947824df00fa0898ad" desc="Title of a setting under the Debugger category in Settings">
Disable async stack traces
</message>
+ <message name="IDS_DEVTOOLS_10bdea5cc4e1689c7db90eb7bf7f45c0" desc="Title of a setting under the Rendering drawer">
+ Emulate CSS media type
+ </message>
<message name="IDS_DEVTOOLS_185bf49541541933dc3fd1fb89d3fea3" desc="Title of a setting under the Console category in Settings">
Enable custom formatters
</message>
<message name="IDS_DEVTOOLS_1985576209a186984f171efd81e91e3d" desc="Text in Network Log">
&lt;anonymous&gt;
</message>
+ <message name="IDS_DEVTOOLS_1a4157cb54ce78ee862a88ecd1a66916" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie used the &quot;__Secure-&quot; or &quot;__Host-&quot; prefix in its name and broke the additional rules applied to cookies with these prefixes as defined in https://tools.ietf.org/html/draft-west-cookie-prefixes-05.
+ </message>
+ <message name="IDS_DEVTOOLS_1ee85f6c60017a7f0646ba8dc5824de6" desc="Service worker running status displayed in the Service Workers view in the Application panel">
+ starting
+ </message>
<message name="IDS_DEVTOOLS_21070fd87b02611a5426d726a70a5502" desc="Text in Server Timing">
No value found for parameter &quot;<ph name="PARAMNAME">$1s<ex>https</ex></ph>&quot;.
</message>
@@ -33,12 +60,30 @@
<message name="IDS_DEVTOOLS_23e8e5daea7e9dc939ae4298a6f74e36" desc="Text in Server Timing">
ServerTiming: <ph name="MSG">$1s<ex>Extraneous trailing characters.</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_242dd6b02f1ff7db7cbba7f7226abb4a" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Do not emulate CSS prefers-color-scheme
+ </message>
+ <message name="IDS_DEVTOOLS_25121e2acd3c495847c5592661c2a2f9" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie&apos;s Domain attribute was invalid with regards to the current host url.
+ </message>
+ <message name="IDS_DEVTOOLS_27d7b4e470e9a00b0fc6cf26fb3c5100" desc="Tooltip to explain why a cookie was blocked">
+ This cookie&apos;s domain is not configured to match the request url&apos;s domain, even though they share a common TLD+1 (TLD+1 of foo.bar.example.com is example.com).
+ </message>
<message name="IDS_DEVTOOLS_28e486be4b3bad598b6e9eaa34ebec76" desc="Text in Network Manager">
Set-Cookie header is ignored in response from url: <ph name="RESPONSE_URL">$1s<ex>https://example.com</ex></ph>. Cookie length should be less than or equal to 4096 characters.
</message>
<message name="IDS_DEVTOOLS_2973958e77629e3a167a1a4c60dd5c5f" desc="Text in Network Manager">
Slow 3G
</message>
+ <message name="IDS_DEVTOOLS_2cc895b2288b4709e1620a1510322de0" desc="Tooltip to explain why a cookie was blocked">
+ This cookie was not sent due to user preferences.
+ </message>
+ <message name="IDS_DEVTOOLS_5e53467e9b005376370c28e92b42b6f5" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Emulate CSS prefers-reduced-motion: reduce
+ </message>
+ <message name="IDS_DEVTOOLS_685c645cb0cb322c5b9989eb12bada19" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Emulate CSS media feature prefers-color-scheme
+ </message>
<message name="IDS_DEVTOOLS_3034e08ec0b14678ddb50284eef02ee4" desc="Title of a setting under the Console category that can be invoked through the Command Menu">
Do not preserve log upon navigation
</message>
@@ -54,18 +99,27 @@
<message name="IDS_DEVTOOLS_38fe155e13d77298cfd5688c3378fa85" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Emulate CSS screen media type
</message>
- <message name="IDS_DEVTOOLS_3b563524fdb17b4a86590470d40bef74" desc="Text in DOMDebugger Model">
- Media
+ <message name="IDS_DEVTOOLS_3b2a3c8ed19fc3647432e72885d633e7" desc="Service worker running status displayed in the Service Workers view in the Application panel">
+ stopping
+ </message>
+ <message name="IDS_DEVTOOLS_3c000cf06aef2d48a8bfe568e1d6ef65" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie was not sent over a secure connection and would have overwritten a cookie with the Secure attribute.
+ </message>
+ <message name="IDS_DEVTOOLS_3c2de12122c9b36f60cb989a6e0589b9" desc="Tooltip to explain why a cookie was blocked">
+ This cookie&apos;s path was not within the request url&apos;s path.
</message>
<message name="IDS_DEVTOOLS_3d9320c6e796b65a6c91fcd64e27fa88" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Hide frames per second (FPS) meter
</message>
<message name="IDS_DEVTOOLS_3ff9f750075f426831f71818a8f4ff12" desc="Text in Network Manager">
- Request was blocked by DevTools: &quot;<ph name="NETWORKREQUEST_URL__">$1s<ex>https://example.com</ex></ph>&quot;.
+ Request was blocked by <ph name="LOCKED_1">DevTools</ph>: &quot;<ph name="NETWORKREQUEST_URL__">$1s<ex>https://example.com</ex></ph>&quot;.
</message>
<message name="IDS_DEVTOOLS_40dba446b661ae69dea3a8e026f76dfd" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Hide paint flashing rectangles
</message>
+ <message name="IDS_DEVTOOLS_41b61424daffc7d27c709bdd4f1ad0ec" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Emulate CSS prefers-color-scheme: dark
+ </message>
<message name="IDS_DEVTOOLS_4249b3308a0ed3e1e90e0a91ca11cf21" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
WebGL Error Fired
</message>
@@ -84,15 +138,27 @@
<message name="IDS_DEVTOOLS_4cc6684df7b4a92b1dec6fce3264fac8" desc="Text in Debugger Model">
Global
</message>
+ <message name="IDS_DEVTOOLS_50103f373f2d49a21139259d81f472d9" desc="Tooltip to explain why a cookie was blocked">
+ This cookie had the &quot;Secure&quot; attribute and the connection was not secure.
+ </message>
<message name="IDS_DEVTOOLS_509820290d57f333403f490dde7316f4" desc="Text in Debugger Model">
Local
</message>
<message name="IDS_DEVTOOLS_509a7f125ba127d220887938738af707" desc="Text in Console Model">
Failed to save to temp variable.
</message>
+ <message name="IDS_DEVTOOLS_51a81ec0bbeea1b79ef6a0cc91a7b9a8" desc="Error message for when a script can't be loaded which had been previously">
+ Script removed or deleted.
+ </message>
<message name="IDS_DEVTOOLS_52da3e7fcf6abefc2a8807df4b759ef8" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
setInterval fired
</message>
+ <message name="IDS_DEVTOOLS_58b76a3d0e2c9313c7742f409bc0afa9" desc="Error message to display when a source CSS file could not be retrieved.">
+ There was an error retrieving the source styles.
+ </message>
+ <message name="IDS_DEVTOOLS_58c00b9a5a2a60122f4ac08e4610d9e2" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had the &quot;SameSite=Extended&quot; attribute but came from a cross-origin response.
+ </message>
<message name="IDS_DEVTOOLS_599eba19aa93a929cb8589f148b8a6c4" desc="A drop-down menu option to emulate css screen media type">
screen
</message>
@@ -105,17 +171,23 @@
<message name="IDS_DEVTOOLS_61cf8510205077b6f5491d38cd44c0f7" desc="Text in DOMDebugger Model">
Pointer
</message>
+ <message name="IDS_DEVTOOLS_6242258a3bddacbd457df5c049591257" desc="Tooltip to explain why a cookie was blocked">
+ An unknown error was encountered when trying to store this cookie.
+ </message>
<message name="IDS_DEVTOOLS_62efb9ec331e364b96efe68c8b03ca20" desc="Text in DOMDebugger Model">
Worker
</message>
<message name="IDS_DEVTOOLS_62fce3f916fe47f75c391fd5e4fc3eca" desc="Text in Network Log">
Consider disabling <ph name="COMMON_UISTRING__CHROME_DATA_SAVER__">$1s<ex>Chrome Data Saver</ex></ph> while debugging. For more info see: <ph name="_HTTPS___SUPPORT_GOOGLE_COM_CHROME__P_DATASAVER_">$2s<ex>https://example.com</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_646554c61e2132b9c32db710eaca838b" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie was not stored due to user preferences.
+ </message>
<message name="IDS_DEVTOOLS_6617a779f50f7afb7949c7ea3ad52b28" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Show hit-test borders
</message>
<message name="IDS_DEVTOOLS_6948a469c79f7dd5426e4f291cba3db1" desc="Text in Network Log">
- Chrome Data Saver
+ <ph name="LOCKED_1">Chrome Data Saver</ph>
</message>
<message name="IDS_DEVTOOLS_6ce4d85a628a88bbdb3ac24a8e5a9c2e" desc="Text in DOMDebugger Model">
Keyboard
@@ -132,24 +204,39 @@
<message name="IDS_DEVTOOLS_7121afd196f5c52bef488d5a0f4c097b" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
Script First Statement
</message>
+ <message name="IDS_DEVTOOLS_75101dcdfc88455bcafc9e53e0b06689" desc="Service worker running status displayed in the Service Workers view in the Application panel">
+ running
+ </message>
+ <message name="IDS_DEVTOOLS_75ce94bc789367b63d0fc1c8daa996df" desc="Error message for when a CSS file can't be loaded">
+ Could not find the original style sheet.
+ </message>
+ <message name="IDS_DEVTOOLS_77454122d17d16885c51c0d57f5c7bd3" desc="Tooltip to explain why a cookie was blocked">
+ This cookie had the &quot;SameSite=Strict&quot; attribute and the request was made on on a different site. This includes navigation requests initiated by other sites.
+ </message>
+ <message name="IDS_DEVTOOLS_792c21f9d971ea4d5a4fa7891dcebe02" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie didn&apos;t specify a &quot;SameSite&quot; attribute and was defaulted to &quot;SameSite=Lax&quot; and broke the same rules specified in the SameSiteLax value.
+ </message>
<message name="IDS_DEVTOOLS_794f64c7f20487f6e13679201deeab3d" desc="Text in DOMDebugger Model">
Picture-in-Picture
</message>
<message name="IDS_DEVTOOLS_7c2bc755363ab11a1611bfa369654ff8" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Show frames per second (FPS) meter
</message>
+ <message name="IDS_DEVTOOLS_7d38391da564c2d9f767c440bbe531f9" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had the &quot;SameSite=None&quot; attribute but did not have the &quot;Secure&quot; attribute, which is required in order to use &quot;SameSite=None&quot;.
+ </message>
<message name="IDS_DEVTOOLS_81961fe251f4d1cb4df131561dedf319" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Hide layer borders
</message>
+ <message name="IDS_DEVTOOLS_829450ef4b9cf5fb35bbc1da8aeec72c" desc="Tooltip to explain why a cookie was blocked">
+ The scheme of this connection is not allowed to store cookies.
+ </message>
<message name="IDS_DEVTOOLS_83f2229658949472d34f78e19475fcdd" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Show layer borders
</message>
<message name="IDS_DEVTOOLS_9028784c589c0c809700c7fbc66a5d96" desc="Text in Network Manager">
Resource interpreted as <ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s<ex>application</ex></ph> but transferred with MIME type <ph name="NETWORKREQUEST_MIMETYPE">$2s<ex>image</ex></ph>: &quot;<ph name="NETWORKREQUEST_URL__">$3s<ex>https://example.com</ex></ph>&quot;.
</message>
- <message name="IDS_DEVTOOLS_90da6f38945a1c7e7ba11e3adcbe6919" desc="Title of a setting under the Debugger category that can be invoked through the Command Menu">
- Pause on exceptions
- </message>
<message name="IDS_DEVTOOLS_9108ae673b7efa9620aec771edc9d4de" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
setTimeout fired
</message>
@@ -162,15 +249,15 @@
<message name="IDS_DEVTOOLS_93dee6366d66361f36985cf5c88346aa" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
Create AudioContext
</message>
- <message name="IDS_DEVTOOLS_95bbad55f11c237ed89546e748093ba7" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
- Request Animation Frame
- </message>
<message name="IDS_DEVTOOLS_96d008db67fc0b5551a926842bbb6a71" desc="Text in DOMDebugger Model">
Notification
</message>
<message name="IDS_DEVTOOLS_9850063efe194af1c63d2aa61ef94c62" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
Create canvas context
</message>
+ <message name="IDS_DEVTOOLS_9995eb02238160b5b11b6097b8eb5008" desc="Tooltip to explain why a cookie was blocked">
+ This cookie didn&apos;t specify a SameSite attribute when it was stored and was defaulted to &quot;SameSite=Lax&quot; and broke the same rules specified in the SameSiteLax value. The cookie had to have been set with &quot;SameSite=None&quot; to enable third-party usage.
+ </message>
<message name="IDS_DEVTOOLS_9dd7b9f5cc1c19a830f153c3e8f1ad89" desc="Text in Network Manager">
Fast 3G
</message>
@@ -186,11 +273,17 @@
<message name="IDS_DEVTOOLS_a720fc15eb9ec85751969e8615ace9e1" desc="Text in Server Timing">
Duplicate parameter &quot;<ph name="PARAMNAME">$1s<ex>https</ex></ph>&quot; ignored.
</message>
+ <message name="IDS_DEVTOOLS_ab91d7ba3d80985f31629857bb57db5a" desc="Tooltip to explain why a cookie was blocked">
+ This cookie had the &quot;SameSite=Lax&quot; attribute and the request was made on a different site. This does not include navigation requests initiated by other sites.
+ </message>
<message name="IDS_DEVTOOLS_ac4aac1ba23d844f4976e9fcd1fd4a61" desc="Text in DOMDebugger Model">
WebGL Error Fired (<ph name="ERRORNAME">$1s<ex>Snag Error</ex></ph>)
</message>
- <message name="IDS_DEVTOOLS_af4bb376939e77df0e7c2332b837a866" desc="Text in Debugger Model">
- Closure
+ <message name="IDS_DEVTOOLS_ae0d59f889c8a03301b9adb5ff1f5bd2" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had the &quot;SameSite=Strict&quot; attribute but came from a cross-origin response. This includes navigation requests intitiated by other origins.
+ </message>
+ <message name="IDS_DEVTOOLS_b1d4660db82a3d7b85dca58e8635ce13" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had the &quot;SameSite=Lax&quot; attribute but came from a cross-origin response.
</message>
<message name="IDS_DEVTOOLS_b28354b543375bfa94dabaeda722927f" desc="Text in Resource Tree Model">
top
@@ -210,11 +303,11 @@
<message name="IDS_DEVTOOLS_ba50636875d999db0c9218b48b23027d" desc="Title of a setting under the Debugger category that can be invoked through the Command Menu">
Do not capture async stack traces
</message>
- <message name="IDS_DEVTOOLS_ba5b676ccf658f863ef2e3df082ee262" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
- Animation Frame Fired
+ <message name="IDS_DEVTOOLS_be06029749b376cc5dec53b60a0cf135" desc="Title of a media query that can be emulated via the Rendering drawer">
+ prefers-reduced-motion: reduce
</message>
- <message name="IDS_DEVTOOLS_bc955333ff170762be4971a8fde558cf" desc="Text in DOMDebugger Model">
- WebAudio
+ <message name="IDS_DEVTOOLS_beff15b1acf49b84bf1080cceb920ebf" desc="Title of a media query that can be emulated via the Rendering drawer">
+ prefers-color-scheme: dark
</message>
<message name="IDS_DEVTOOLS_c432f4e5fdec5760a2f06b38f646168e" desc="Text in Console Model">
Profile &apos;<ph name="DATA_TITLE">$1s<ex>title</ex></ph>&apos; started.
@@ -228,8 +321,14 @@
<message name="IDS_DEVTOOLS_c89686a387d2b12b3c729ce35a0bcb5b" desc="Text in DOMDebugger Model">
Window
</message>
- <message name="IDS_DEVTOOLS_c9ad95228aa735bdda1aebf38da022af" desc="Text in DOMDebugger Model">
- Parse
+ <message name="IDS_DEVTOOLS_ccab918ce9f085b521a52ac13f653c0b" desc="Tooltip to explain why a cookie was blocked">
+ An unknown error was encountered when trying to send this cookie.
+ </message>
+ <message name="IDS_DEVTOOLS_cdb227ce6e015a5e5570e286ccd8866c" desc="Title of a setting under the Rendering drawer">
+ Emulate CSS media feature prefers-reduced-motion
+ </message>
+ <message name="IDS_DEVTOOLS_ceb19b7234304452f0c748bac8ba3fb8" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Do not emulate CSS prefers-reduced-motion
</message>
<message name="IDS_DEVTOOLS_cedab6b9e4e794e93bba797e8aff218a" desc="Message in Network Manager">
<ph name="NETWORKREQUEST_RESOURCETYPE___TITLE__">$1s<ex>XHR</ex></ph> finished loading: <ph name="NETWORKREQUEST_REQUESTMETHOD">$2s<ex>GET</ex></ph> &quot;<ph name="NETWORKREQUEST_URL__">$3s<ex>https://example.com</ex></ph>&quot;.
@@ -237,39 +336,33 @@
<message name="IDS_DEVTOOLS_d24a22fef757966373800aa9795458dc" desc="Text in Source Map">
? [sm]
</message>
- <message name="IDS_DEVTOOLS_d31827f0a164d52b636bb1f71ca4a351" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
- Cancel Animation Frame
- </message>
<message name="IDS_DEVTOOLS_d4fad802fc7bf0248d34c685533bd56f" desc="Title of a setting under the Network category that can be invoked through the Command Menu">
Disable request blocking
</message>
- <message name="IDS_DEVTOOLS_d6b6b668dbca9d4fe774bb654226ebe3" desc="Text in DOMDebugger Model">
- Animation
- </message>
<message name="IDS_DEVTOOLS_dcd9c13c4f8ae68ea7ae92edf9191264" desc="Text in Server Timing">
Deprecated syntax found. Please use: &lt;name&gt;;dur=&lt;duration&gt;;desc=&lt;description&gt;
</message>
<message name="IDS_DEVTOOLS_df9f4292c1d025cbada13b25744d34e5" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Do not emulate CSS media type
</message>
+ <message name="IDS_DEVTOOLS_dfc84699a635ac79c7512494a2ebec91" desc="Tooltip to explain why a cookie was blocked">
+ This set-cookie had the &quot;Secure&quot; attribute but was not received over a secure connection.
+ </message>
<message name="IDS_DEVTOOLS_e1e4c8c9ccd9fc39c391da4bcd093fb2" desc="Text in Debugger Model">
Block
</message>
<message name="IDS_DEVTOOLS_e2b60c37530e144372a7943df0f6017d" desc="Text in Resource Tree Model">
&lt;iframe&gt;
</message>
- <message name="IDS_DEVTOOLS_e402c138065e7eece783dc30c6079192" desc="Text in DOMDebugger Model">
- XHR
- </message>
<message name="IDS_DEVTOOLS_e485c975c1d6c17d9dfd81128b83f63a" desc="Text in the Event Listener Breakpoints Panel of the JavaScript Debugger in the Sources Panel">
Set innerHTML
</message>
- <message name="IDS_DEVTOOLS_e55f75a29310d7b60f7ac1d390c8ae42" desc="Text in Debugger Model">
- Module
- </message>
<message name="IDS_DEVTOOLS_e69d85cd1acdf030f0cede48b61d7720" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Hide scroll performance bottlenecks
</message>
+ <message name="IDS_DEVTOOLS_e8e741c8bebb2da4dc93e5f9c1cecd8c" desc="Title of a setting under the Rendering drawer that can be invoked through the Command Menu">
+ Emulate CSS prefers-color-scheme: light
+ </message>
<message name="IDS_DEVTOOLS_edb020d2175281d94054136e09a3e132" desc="Title of a setting under the Debugger category that can be invoked through the Command Menu">
Do not pause on exceptions
</message>
@@ -282,6 +375,9 @@
<message name="IDS_DEVTOOLS_eff8d530f562a22a45fbf1ee83299353" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Show scroll performance bottlenecks
</message>
+ <message name="IDS_DEVTOOLS_f0a0bfe6bc7d2c58d2989034f83183e0" desc="Service worker running status displayed in the Service Workers view in the Application panel">
+ stopped
+ </message>
<message name="IDS_DEVTOOLS_f107ac919ab14339cdb22cd00fccd215" desc="Title of a setting under the Rendering category that can be invoked through the Command Menu">
Show paint flashing rectangles
</message>
@@ -289,7 +385,7 @@
Mouse
</message>
<message name="IDS_DEVTOOLS_f6137609f4decf877ede5bd3a3125629" desc="Text in CPUProfile Data Model">
- DevTools: CPU profile parser is fixing <ph name="COUNT">$1s<ex>2</ex></ph> missing samples.
+ <ph name="LOCKED_1">DevTools</ph>: CPU profile parser is fixing <ph name="COUNT">$1s<ex>2</ex></ph> missing samples.
</message>
<message name="IDS_DEVTOOLS_f7531e2d0ea27233ce00b5f01c5bf335" desc="A drop-down menu option to emulate css print media type">
print
@@ -306,4 +402,7 @@
<message name="IDS_DEVTOOLS_ff92304ed0236a5f972fd90e9b47fae4" desc="Text in Server Timing">
Unrecognized parameter &quot;<ph name="PARAMNAME">$1s<ex>https</ex></ph>&quot;.
</message>
+ <message name="IDS_DEVTOOLS_1b1cc7f086b3f074da452bc3129981eb" desc="A tag of Emulate CSS screen media type setting that can be searched in the command menu">
+ query
+ </message>
</grit-part>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk_test_runner/PageMockTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk_test_runner/PageMockTestRunner.js
index bc5263a36b2..88850796d6b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk_test_runner/PageMockTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk_test_runner/PageMockTestRunner.js
@@ -48,13 +48,13 @@ SDKTestRunner.PageMock = class {
this._enabledDomains.clear();
SDK.targetManager._targets = [];
- const oldFactory = Protocol.Connection._factory;
- Protocol.Connection._factory = () => {
+ const oldFactory = Protocol.Connection.getFactory();
+ Protocol.Connection.setFactory(() => {
this._connection = new MockPageConnection(this);
return this._connection;
- };
+ });
const target = SDK.targetManager.createTarget(nextId('mock-target-'), targetName, this._type, null);
- Protocol.Connection._factory = oldFactory;
+ Protocol.Connection.setFactory(oldFactory);
this._target = target;
return target;
@@ -131,8 +131,9 @@ SDKTestRunner.PageMock = class {
reload() {
this._fireEvent('Page.frameStartedLoading', {frameId: this._mainFrame.id});
- for (const context of this._executionContexts)
+ for (const context of this._executionContexts) {
this._fireEvent('Runtime.executionContextDestroyed', {executionContextId: context.id});
+ }
this._scripts = [];
@@ -141,8 +142,9 @@ SDKTestRunner.PageMock = class {
this._fireEvent('Runtime.executionContextsCleared', {});
this._executionContexts.push(this._createExecutionContext(this._mainFrame, false));
- for (const context of this._executionContexts)
+ for (const context of this._executionContexts) {
this._fireEvent('Runtime.executionContextCreated', {context: context});
+ }
this._fireEvent('Page.frameNavigated', {frame: this._mainFrame});
@@ -169,8 +171,9 @@ SDKTestRunner.PageMock = class {
this._enabledDomains.add('Debugger');
this._sendResponse(id, {});
- for (const script of this._scripts)
+ for (const script of this._scripts) {
this._fireEvent('Debugger.scriptParsed', script);
+ }
}
_debuggerGetScriptSource(id, params) {
@@ -189,8 +192,9 @@ SDKTestRunner.PageMock = class {
this._enabledDomains.add('Runtime');
this._sendResponse(id, {});
- for (const context of this._executionContexts)
+ for (const context of this._executionContexts) {
this._fireEvent('Runtime.executionContextCreated', {context: context});
+ }
}
_pageEnable(id, params) {
@@ -207,8 +211,9 @@ SDKTestRunner.PageMock = class {
_isSupportedDomain(methodName) {
const domain = methodName.split('.')[0];
- if (domain === 'Page')
+ if (domain === 'Page') {
return this._type === SDK.Target.Type.Frame;
+ }
return true;
}
@@ -216,15 +221,17 @@ SDKTestRunner.PageMock = class {
_dispatch(sessionId, id, methodName, params) {
if (sessionId) {
const child = this._children.get(sessionId);
- if (child)
+ if (child) {
child._dispatch('', id, methodName, params);
+ }
return;
}
const handler = (this._isSupportedDomain(methodName) ? this._dispatchMap[methodName] : null);
- if (handler)
+ if (handler) {
return handler.call(this, id, params);
+ }
this._sendResponse(
id, undefined, {message: 'Can\'t handle command ' + methodName, code: Protocol.DevToolsStubErrorCode});
@@ -243,8 +250,9 @@ SDKTestRunner.PageMock = class {
_fireEvent(methodName, params) {
const domain = methodName.split('.')[0];
- if (!this._enabledDomains.has(domain))
+ if (!this._enabledDomains.has(domain)) {
return;
+ }
const message = {method: methodName, params: params};
if (this._root) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchConfig.js b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchConfig.js
index 0ba3f5c35d2..27b9c386529 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchConfig.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchConfig.js
@@ -83,8 +83,9 @@ Search.SearchConfig = class {
for (let i = 0; i < queryParts.length; ++i) {
const queryPart = queryParts[i];
- if (!queryPart)
+ if (!queryPart) {
continue;
+ }
const fileQuery = this._parseFileQuery(queryPart);
if (fileQuery) {
this._fileQueries.push(fileQuery);
@@ -99,8 +100,9 @@ Search.SearchConfig = class {
continue;
}
if (queryPart.startsWith('"')) {
- if (!queryPart.endsWith('"'))
+ if (!queryPart.endsWith('"')) {
continue;
+ }
this._queries.push(this._parseQuotedQuery(queryPart));
continue;
}
@@ -114,11 +116,13 @@ Search.SearchConfig = class {
* @return {boolean}
*/
filePathMatchesFileQuery(filePath) {
- if (!this._fileRegexQueries)
+ if (!this._fileRegexQueries) {
return true;
+ }
for (let i = 0; i < this._fileRegexQueries.length; ++i) {
- if (!!filePath.match(this._fileRegexQueries[i].regex) === this._fileRegexQueries[i].isNegative)
+ if (!!filePath.match(this._fileRegexQueries[i].regex) === this._fileRegexQueries[i].isNegative) {
return false;
+ }
}
return true;
}
@@ -145,8 +149,9 @@ Search.SearchConfig = class {
*/
_parseFileQuery(query) {
const match = query.match(Search.SearchConfig.FilePatternRegex);
- if (!match)
+ if (!match) {
return null;
+ }
const isNegative = !!match[1];
query = match[3];
let result = '';
@@ -157,11 +162,13 @@ Search.SearchConfig = class {
} else if (char === '\\') {
++i;
const nextChar = query[i];
- if (nextChar === ' ')
+ if (nextChar === ' ') {
result += ' ';
+ }
} else {
- if (String.regexSpecialCharacters().indexOf(query.charAt(i)) !== -1)
+ if (String.regexSpecialCharacters().indexOf(query.charAt(i)) !== -1) {
result += '\\';
+ }
result += query.charAt(i);
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchResultsPane.js b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchResultsPane.js
index 47030cad988..edad9c48d15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchResultsPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchResultsPane.js
@@ -34,8 +34,9 @@ Search.SearchResultsPane = class extends UI.VBox {
const treeElement = new Search.SearchResultsPane.SearchResultsTreeElement(this._searchConfig, searchResult);
this._treeOutline.appendChild(treeElement);
// Expand until at least a certain number of matches is expanded.
- if (this._matchesExpandedCount < Search.SearchResultsPane._matchesExpandedByDefault)
+ if (this._matchesExpandedCount < Search.SearchResultsPane._matchesExpandedByDefault) {
treeElement.expand();
+ }
this._matchesExpandedCount += searchResult.matchesCount();
}
};
@@ -62,8 +63,9 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
* @override
*/
onexpand() {
- if (this._initialized)
+ if (this._initialized) {
return;
+ }
this._updateMatchesUI();
this._initialized = true;
@@ -100,10 +102,12 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
matchesCountSpan.className = 'search-result-matches-count';
matchesCountSpan.textContent = `${this._searchResult.matchesCount()}`;
+ UI.ARIAUtils.setAccessibleName(matchesCountSpan, ls`Matches Count ${this._searchResult.matchesCount()}`);
this.listItemElement.appendChild(matchesCountSpan);
- if (this.expanded)
+ if (this.expanded) {
this._updateMatchesUI();
+ }
/**
* @param {string} text
@@ -127,21 +131,29 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
const queries = this._searchConfig.queries();
const regexes = [];
- for (let i = 0; i < queries.length; ++i)
+ for (let i = 0; i < queries.length; ++i) {
regexes.push(createSearchRegex(queries[i], !this._searchConfig.ignoreCase(), this._searchConfig.isRegex()));
+ }
for (let i = fromIndex; i < toIndex; ++i) {
const lineContent = searchResult.matchLineContent(i).trim();
let matchRanges = [];
- for (let j = 0; j < regexes.length; ++j)
+ for (let j = 0; j < regexes.length; ++j) {
matchRanges = matchRanges.concat(this._regexMatchRanges(lineContent, regexes[j]));
+ }
const anchor = Components.Linkifier.linkifyRevealable(searchResult.matchRevealable(i), '');
anchor.classList.add('search-match-link');
- const lineNumberSpan = createElement('span');
- lineNumberSpan.classList.add('search-match-line-number');
- lineNumberSpan.textContent = searchResult.matchLabel(i);
- anchor.appendChild(lineNumberSpan);
+ const labelSpan = createElement('span');
+ labelSpan.classList.add('search-match-line-number');
+ const resultLabel = searchResult.matchLabel(i);
+ labelSpan.textContent = resultLabel;
+ if (typeof resultLabel === 'number' && !isNaN(resultLabel)) {
+ UI.ARIAUtils.setAccessibleName(labelSpan, ls`Line ${resultLabel}`);
+ } else {
+ UI.ARIAUtils.setAccessibleName(labelSpan, ls`${resultLabel}`);
+ }
+ anchor.appendChild(labelSpan);
const contentSpan = this._createContentSpan(lineContent, matchRanges);
anchor.appendChild(contentSpan);
@@ -175,8 +187,9 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
*/
_createContentSpan(lineContent, matchRanges) {
let trimBy = 0;
- if (matchRanges.length > 0 && matchRanges[0].offset > 20)
+ if (matchRanges.length > 0 && matchRanges[0].offset > 20) {
trimBy = 15;
+ }
lineContent = lineContent.substring(trimBy, 1000 + trimBy);
if (trimBy) {
matchRanges = matchRanges.map(range => new TextUtils.SourceRange(range.offset - trimBy + 1, range.length));
@@ -185,6 +198,7 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
const contentSpan = createElement('span');
contentSpan.className = 'search-match-content';
contentSpan.textContent = lineContent;
+ UI.ARIAUtils.setAccessibleName(contentSpan, `${lineContent} line`);
UI.highlightRangesWithStyleClass(contentSpan, matchRanges, 'highlighted-match');
return contentSpan;
}
@@ -198,8 +212,9 @@ Search.SearchResultsPane.SearchResultsTreeElement = class extends UI.TreeElement
regex.lastIndex = 0;
let match;
const matchRanges = [];
- while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent)))
+ while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent))) {
matchRanges.push(new TextUtils.SourceRange(match.index, match[0].length));
+ }
return matchRanges;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchView.js b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchView.js
index 4e8c5dd0ff1..16bbe6c935f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/search/SearchView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/search/SearchView.js
@@ -49,6 +49,7 @@ Search.SearchView = class extends UI.VBox {
this._search.setAttribute('type', 'text');
this._search.setAttribute('results', '0');
this._search.setAttribute('size', 42);
+ UI.ARIAUtils.setAccessibleName(this._search, ls`Search Query`);
const searchItem = new UI.ToolbarItem(searchContainer);
const toolbar = new UI.Toolbar('search-toolbar', this._searchPanelElement);
@@ -106,18 +107,21 @@ Search.SearchView = class extends UI.VBox {
* @param {boolean=} searchImmediately
*/
async toggle(queryCandidate, searchImmediately) {
- if (queryCandidate)
+ if (queryCandidate) {
this._search.value = queryCandidate;
- if (this.isShowing())
+ }
+ if (this.isShowing()) {
this.focus();
- else
+ } else {
this._focusOnShow = true;
+ }
this._initScope();
- if (searchImmediately)
+ if (searchImmediately) {
this._onAction();
- else
+ } else {
this._startIndexing();
+ }
}
/**
@@ -148,10 +152,12 @@ Search.SearchView = class extends UI.VBox {
this._progressIndicator = null;
this._isIndexing = false;
this._indexingFinished(finished);
- if (!finished)
+ if (!finished) {
this._pendingSearchConfig = null;
- if (!this._pendingSearchConfig)
+ }
+ if (!this._pendingSearchConfig) {
return;
+ }
const searchConfig = this._pendingSearchConfig;
this._pendingSearchConfig = null;
this._innerStartSearch(searchConfig);
@@ -159,8 +165,9 @@ Search.SearchView = class extends UI.VBox {
_startIndexing() {
this._isIndexing = true;
- if (this._progressIndicator)
+ if (this._progressIndicator) {
this._progressIndicator.done();
+ }
this._progressIndicator = new UI.ProgressIndicator();
this._searchMessageElement.textContent = Common.UIString('Indexing\u2026');
this._progressIndicator.show(this._searchProgressPlaceholderElement);
@@ -178,15 +185,17 @@ Search.SearchView = class extends UI.VBox {
* @param {!Search.SearchResult} searchResult
*/
_onSearchResult(searchId, searchResult) {
- if (searchId !== this._searchId || !this._progressIndicator)
+ if (searchId !== this._searchId || !this._progressIndicator) {
return;
+ }
if (this._progressIndicator && this._progressIndicator.isCanceled()) {
this._onIndexingFinished();
return;
}
this._addSearchResult(searchResult);
- if (!searchResult.matchesCount())
+ if (!searchResult.matchesCount()) {
return;
+ }
if (!this._searchResultsPane) {
this._searchResultsPane = new Search.SearchResultsPane(/** @type {!Search.SearchConfig} */ (this._searchConfig));
this._showPane(this._searchResultsPane);
@@ -199,12 +208,17 @@ Search.SearchView = class extends UI.VBox {
* @param {boolean} finished
*/
_onSearchFinished(searchId, finished) {
- if (searchId !== this._searchId || !this._progressIndicator)
+ if (searchId !== this._searchId || !this._progressIndicator) {
return;
- if (!this._searchResultsPane)
+ }
+ if (!this._searchResultsPane) {
this._nothingFound();
+ }
this._searchFinished(finished);
this._searchConfig = null;
+ UI.ARIAUtils.alert(
+ this._searchMessageElement.textContent + ' ' + this._searchResultsMessageElement.textContent,
+ this._searchMessageElement);
}
/**
@@ -214,15 +228,17 @@ Search.SearchView = class extends UI.VBox {
this._resetSearch();
++this._searchId;
this._initScope();
- if (!this._isIndexing)
+ if (!this._isIndexing) {
this._startIndexing();
+ }
this._pendingSearchConfig = searchConfig;
}
_innerStartSearch(searchConfig) {
this._searchConfig = searchConfig;
- if (this._progressIndicator)
+ if (this._progressIndicator) {
this._progressIndicator.done();
+ }
this._progressIndicator = new UI.ProgressIndicator();
this._searchStarted(this._progressIndicator);
this._searchScope.performSearch(
@@ -237,10 +253,12 @@ Search.SearchView = class extends UI.VBox {
}
_stopSearch() {
- if (this._progressIndicator && !this._isIndexing)
+ if (this._progressIndicator && !this._isIndexing) {
this._progressIndicator.cancel();
- if (this._searchScope)
+ }
+ if (this._searchScope) {
this._searchScope.stopSearch();
+ }
this._searchConfig = null;
}
@@ -249,8 +267,9 @@ Search.SearchView = class extends UI.VBox {
*/
_searchStarted(progressIndicator) {
this._resetCounters();
- if (!this._searchingView)
+ if (!this._searchingView) {
this._searchingView = new UI.EmptyWidget(Common.UIString('Searching\u2026'));
+ }
this._showPane(this._searchingView);
this._searchMessageElement.textContent = Common.UIString('Searching\u2026');
progressIndicator.show(this._searchProgressPlaceholderElement);
@@ -284,10 +303,12 @@ Search.SearchView = class extends UI.VBox {
* @param {?UI.Widget} panel
*/
_showPane(panel) {
- if (this._visiblePane)
+ if (this._visiblePane) {
this._visiblePane.detach();
- if (panel)
+ }
+ if (panel) {
panel.show(this._searchResultsElement);
+ }
this._visiblePane = panel;
}
@@ -298,8 +319,9 @@ Search.SearchView = class extends UI.VBox {
}
_nothingFound() {
- if (!this._notFoundView)
+ if (!this._notFoundView) {
this._notFoundView = new UI.EmptyWidget(Common.UIString('No matches found.'));
+ }
this._showPane(this._notFoundView);
this._searchResultsMessageElement.textContent = Common.UIString('No matches found.');
}
@@ -311,8 +333,9 @@ Search.SearchView = class extends UI.VBox {
const matchesCount = searchResult.matchesCount();
this._searchMatchesCount += matchesCount;
this._searchResultsCount++;
- if (matchesCount)
+ if (matchesCount) {
this._nonEmptySearchResultsCount++;
+ }
this._updateSearchResultsMessage();
}
@@ -362,9 +385,12 @@ Search.SearchView = class extends UI.VBox {
}
_onAction() {
+ // Resetting alert variable to prime for next search query result.
+ UI.ARIAUtils.alert(' ', this._searchMessageElement);
const searchConfig = this._buildSearchConfig();
- if (!searchConfig.query() || !searchConfig.query().length)
+ if (!searchConfig.query() || !searchConfig.query().length) {
return;
+ }
this._save();
this._startSearch(searchConfig);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
index f5e416f33b4..82ffb6b892f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/search/search_strings.grdp
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_2f04f3e6eee339eeb0ddb6c39606424d" desc="Text in Search View of the Search tab">
- Use Regular Expression
+ <message name="IDS_DEVTOOLS_34e2aa72db15bdd577141c4379e189c7" desc="Search result label for results in the Search tool">
+ Line <ph name="RESULTLABEL">$1s<ex>2</ex></ph>
</message>
<message name="IDS_DEVTOOLS_44b4e531d5b06deb40b631e4aa3c7e36" desc="Text in Search Results Pane of the Search tab">
Show <ph name="MATCHESLEFTCOUNT">$1d<ex>2</ex></ph> more
@@ -9,6 +9,9 @@
<message name="IDS_DEVTOOLS_617778f774bc264b169dde60f223285f" desc="Search message element text content in Search View of the Search tab">
Indexing…
</message>
+ <message name="IDS_DEVTOOLS_886d9914946169e5ca8a0f33654d2240" desc="Accessibility label for number of matches in each file in search results pane">
+ Matches Count <ph name="THIS__SEARCHRESULT_MATCHESCOUNT__">$1s<ex>2</ex></ph>
+ </message>
<message name="IDS_DEVTOOLS_9fc52b55092ab8a92303e86722013b36" desc="Text in Search View of the Search tab">
Search interrupted.
</message>
@@ -21,12 +24,12 @@
<message name="IDS_DEVTOOLS_c440d4f6fc7dd9239ada58277b900249" desc="Search results message element text content in Search View of the Search tab">
Found <ph name="THIS__SEARCHMATCHESCOUNT">$1d<ex>2</ex></ph> matching lines in 1 file.
</message>
- <message name="IDS_DEVTOOLS_c949475bc69a57c419ac976fe8870652" desc="Text in Search View of the Search tab">
- Match Case
- </message>
<message name="IDS_DEVTOOLS_d1e64da6074bf343a0a6bd2cd6515189" desc="Text in Search View of the Search tab">
Indexing interrupted.
</message>
+ <message name="IDS_DEVTOOLS_eb918b4adda22d388aa3bf548dacd71c" desc="Accessibility label for search query text box">
+ Search Query
+ </message>
<message name="IDS_DEVTOOLS_f4c8ff50c8f0b548e3297aeaf3b304b4" desc="Search results message element text content in Search View of the Search tab">
Found 1 matching line in 1 file.
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityModel.js b/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityModel.js
index 0e476593f54..fc4b6a812f5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityModel.js
@@ -48,8 +48,9 @@ Security.SecurityModel = class extends SDK.SDKModel {
// and so that failed/cancelled requests appear at the bottom of the origins list.
Protocol.Security.SecurityState.Unknown
];
- for (let i = 0; i < ordering.length; i++)
+ for (let i = 0; i < ordering.length; i++) {
securityStateMap.set(ordering[i], i + 1);
+ }
Security.SecurityModel._symbolicToNumericSecurityState = securityStateMap;
}
const aScore = securityStateMap.get(a) || 0;
@@ -105,6 +106,12 @@ Security.SecurityDispatcher = class {
this._model.dispatchEventToListeners(Security.SecurityModel.Events.SecurityStateChanged, pageSecurityState);
}
+ /**
+ * @override
+ * @param {!Protocol.Security.VisibleSecurityState} visibleSecurityState
+ */
+ visibleSecurityStateChanged(visibleSecurityState) {
+ }
/**
* @override
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
index fdcc33cb5d8..81aae1bc71a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
@@ -47,8 +47,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
const certificateButton = UI.createTextButton(text, async e => {
e.consume();
const names = await SDK.multitargetNetworkManager.getCertificate(origin);
- if (names.length > 0)
- InspectorFrontendHost.showCertificateViewer(names);
+ if (names.length > 0) {
+ Host.InspectorFrontendHost.showCertificateViewer(names);
+ }
}, 'origin-button');
UI.ARIAUtils.markAsMenuButton(certificateButton);
return certificateButton;
@@ -62,7 +63,7 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
static createCertificateViewerButtonForCert(text, names) {
const certificateButton = UI.createTextButton(text, e => {
e.consume();
- InspectorFrontendHost.showCertificateViewer(names);
+ Host.InspectorFrontendHost.showCertificateViewer(names);
}, 'security-certificate-button');
UI.ARIAUtils.markAsMenuButton(certificateButton);
return certificateButton;
@@ -125,8 +126,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
*/
showOrigin(origin) {
const originState = this._origins.get(origin);
- if (!originState.originView)
+ if (!originState.originView) {
originState.originView = new Security.SecurityOriginView(this, origin, originState);
+ }
this._setVisibleView(originState.originView);
}
@@ -136,8 +138,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
*/
wasShown() {
super.wasShown();
- if (!this._visibleView)
+ if (!this._visibleView) {
this.selectAndSwitchToMainView();
+ }
}
/**
@@ -151,16 +154,19 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
* @param {!UI.VBox} view
*/
_setVisibleView(view) {
- if (this._visibleView === view)
+ if (this._visibleView === view) {
return;
+ }
- if (this._visibleView)
+ if (this._visibleView) {
this._visibleView.detach();
+ }
this._visibleView = view;
- if (view)
+ if (view) {
this.splitWidget().setMainWidget(view);
+ }
}
/**
@@ -168,8 +174,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
*/
_onResponseReceived(event) {
const request = /** @type {!SDK.NetworkRequest} */ (event.data);
- if (request.resourceType() === Common.resourceTypes.Document)
+ if (request.resourceType() === Common.resourceTypes.Document) {
this._lastResponseReceivedForLoaderId.set(request.loaderId, request);
+ }
}
/**
@@ -186,8 +193,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
let securityState = /** @type {!Protocol.Security.SecurityState} */ (request.securityState());
if (request.mixedContentType === Protocol.Security.MixedContentType.Blockable ||
- request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable)
+ request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable) {
securityState = Protocol.Security.SecurityState.Insecure;
+ }
if (this._origins.has(origin)) {
const originState = this._origins.get(origin);
@@ -195,11 +203,13 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
originState.securityState = this._securityStateMin(oldSecurityState, securityState);
if (oldSecurityState !== originState.securityState) {
const securityDetails = /** @type {?Protocol.Network.SecurityDetails} */ (request.securityDetails());
- if (securityDetails)
+ if (securityDetails) {
originState.securityDetails = securityDetails;
+ }
this._sidebarTree.updateOrigin(origin, securityState);
- if (originState.originView)
+ if (originState.originView) {
originState.originView.setSecurityState(securityState);
+ }
}
} else {
// This stores the first security details we see for an origin, but we should
@@ -209,8 +219,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
originState.securityState = securityState;
const securityDetails = request.securityDetails();
- if (securityDetails)
+ if (securityDetails) {
originState.securityDetails = securityDetails;
+ }
originState.loadedFromCache = request.cached();
@@ -235,22 +246,25 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
* @param {!SDK.NetworkRequest} request
*/
_updateFilterRequestCounts(request) {
- if (request.mixedContentType === Protocol.Security.MixedContentType.None)
+ if (request.mixedContentType === Protocol.Security.MixedContentType.None) {
return;
+ }
/** @type {!Network.NetworkLogView.MixedContentFilterValues} */
let filterKey = Network.NetworkLogView.MixedContentFilterValues.All;
- if (request.wasBlocked())
+ if (request.wasBlocked()) {
filterKey = Network.NetworkLogView.MixedContentFilterValues.Blocked;
- else if (request.mixedContentType === Protocol.Security.MixedContentType.Blockable)
+ } else if (request.mixedContentType === Protocol.Security.MixedContentType.Blockable) {
filterKey = Network.NetworkLogView.MixedContentFilterValues.BlockOverridden;
- else if (request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable)
+ } else if (request.mixedContentType === Protocol.Security.MixedContentType.OptionallyBlockable) {
filterKey = Network.NetworkLogView.MixedContentFilterValues.Displayed;
+ }
- if (!this._filterRequestCounts.has(filterKey))
+ if (!this._filterRequestCounts.has(filterKey)) {
this._filterRequestCounts.set(filterKey, 1);
- else
+ } else {
this._filterRequestCounts.set(filterKey, this._filterRequestCounts.get(filterKey) + 1);
+ }
this._mainView.refreshExplanations();
}
@@ -277,8 +291,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
* @param {!Security.SecurityModel} securityModel
*/
modelAdded(securityModel) {
- if (this._securityModel)
+ if (this._securityModel) {
return;
+ }
this._securityModel = securityModel;
const resourceTreeModel = securityModel.resourceTreeModel();
@@ -296,8 +311,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this),
];
- if (resourceTreeModel.isInterstitialShowing())
+ if (resourceTreeModel.isInterstitialShowing()) {
this._onInterstitialShown();
+ }
}
/**
@@ -305,8 +321,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
* @param {!Security.SecurityModel} securityModel
*/
modelRemoved(securityModel) {
- if (this._securityModel !== securityModel)
+ if (this._securityModel !== securityModel) {
return;
+ }
delete this._securityModel;
Common.EventTarget.removeEventListeners(this._eventListeners);
@@ -334,8 +351,9 @@ Security.SecurityPanel = class extends UI.PanelWithSidebar {
const origin = Common.ParsedURL.extractOrigin(request ? request.url() : frame.url);
this._sidebarTree.setMainOrigin(origin);
- if (request)
+ if (request) {
this._processRequest(request);
+ }
}
_onInterstitialShown() {
@@ -428,8 +446,9 @@ Security.SecurityPanelSidebarTree = class extends UI.TreeOutlineInShadow {
* @param {boolean} hidden
*/
toggleOriginsList(hidden) {
- for (const element of this._originGroups.values())
+ for (const element of this._originGroups.values()) {
element.hidden = hidden;
+ }
}
/**
@@ -464,10 +483,11 @@ Security.SecurityPanelSidebarTree = class extends UI.TreeOutlineInShadow {
let newParent;
if (origin === this._mainOrigin) {
newParent = this._originGroups.get(Security.SecurityPanelSidebarTree.OriginGroup.MainOrigin);
- if (securityState === Protocol.Security.SecurityState.Secure)
+ if (securityState === Protocol.Security.SecurityState.Secure) {
newParent.title = ls`Main origin (secure)`;
- else
+ } else {
newParent.title = ls`Main origin (non-secure)`;
+ }
} else {
switch (securityState) {
case Protocol.Security.SecurityState.Secure:
@@ -486,8 +506,9 @@ Security.SecurityPanelSidebarTree = class extends UI.TreeOutlineInShadow {
if (oldParent !== newParent) {
if (oldParent) {
oldParent.removeChild(originElement);
- if (oldParent.childCount() === 0)
+ if (oldParent.childCount() === 0) {
oldParent.hidden = true;
+ }
}
newParent.appendChild(originElement);
newParent.hidden = false;
@@ -510,7 +531,7 @@ Security.SecurityPanelSidebarTree = class extends UI.TreeOutlineInShadow {
}
};
-/** @enum */
+/** @enum {symbol} */
Security.SecurityPanelSidebarTree.OriginGroup = {
MainOrigin: Symbol('MainOrigin'),
NonSecure: Symbol('NonSecure'),
@@ -552,8 +573,9 @@ Security.SecurityPanelSidebarTreeElement = class extends UI.TreeElement {
* @param {!Protocol.Security.SecurityState} newSecurityState
*/
setSecurityState(newSecurityState) {
- if (this._securityState)
+ if (this._securityState) {
this._iconElement.classList.remove(this._cssPrefix + '-' + this._securityState);
+ }
this._securityState = newSecurityState;
this._iconElement.classList.add(this._cssPrefix + '-' + newSecurityState);
@@ -652,8 +674,9 @@ Security.SecurityMainView = class extends UI.VBox {
if (explanation.recommendations && explanation.recommendations.length) {
const recommendationList = text.createChild('ul', 'security-explanation-recommendations');
- for (const recommendation of explanation.recommendations)
+ for (const recommendation of explanation.recommendations) {
recommendationList.createChild('li').textContent = recommendation;
+ }
}
return text;
}
@@ -746,15 +769,17 @@ Security.SecurityMainView = class extends UI.VBox {
const requestsAnchor = element.createChild('div', 'security-mixed-content devtools-link');
UI.ARIAUtils.markAsLink(requestsAnchor);
requestsAnchor.tabIndex = 0;
- if (filterRequestCount === 1)
+ if (filterRequestCount === 1) {
requestsAnchor.textContent = Common.UIString('View %d request in Network Panel', filterRequestCount);
- else
+ } else {
requestsAnchor.textContent = Common.UIString('View %d requests in Network Panel', filterRequestCount);
+ }
requestsAnchor.addEventListener('click', this.showNetworkFilter.bind(this, filterKey));
requestsAnchor.addEventListener('keydown', event => {
- if (isEnterKey(event))
+ if (isEnterKey(event)) {
this.showNetworkFilter(filterKey, event);
+ }
});
}
@@ -799,16 +824,17 @@ Security.SecurityOriginView = class extends UI.VBox {
originDisplay.appendChild(Security.SecurityPanel.createHighlightedUrl(origin, originState.securityState));
const originNetworkDiv = titleSection.createChild('div', 'view-network-button');
- const originNetworkButton = UI.createTextButton('View requests in Network Panel', e => {
+ const originNetworkLink = originNetworkDiv.createChild('span', 'devtools-link origin-button');
+ originNetworkLink.textContent = ls`View requests in Network Panel`;
+ originNetworkLink.addEventListener('click', e => {
e.consume();
const parsedURL = new Common.ParsedURL(origin);
Network.NetworkPanel.revealAndFilter([
{filterType: Network.NetworkLogView.FilterType.Domain, filterValue: parsedURL.host},
{filterType: Network.NetworkLogView.FilterType.Scheme, filterValue: parsedURL.scheme}
]);
- }, 'origin-button');
- UI.ARIAUtils.markAsLink(originNetworkButton);
- originNetworkDiv.appendChild(originNetworkButton);
+ });
+ UI.ARIAUtils.markAsLink(originNetworkLink);
if (originState.securityDetails) {
const connectionSection = this.element.createChild('div', 'origin-view-section');
@@ -819,10 +845,12 @@ Security.SecurityOriginView = class extends UI.VBox {
let table = new Security.SecurityDetailsTable();
connectionSection.appendChild(table.element());
table.addRow(Common.UIString('Protocol'), originState.securityDetails.protocol);
- if (originState.securityDetails.keyExchange)
+ if (originState.securityDetails.keyExchange) {
table.addRow(Common.UIString('Key exchange'), originState.securityDetails.keyExchange);
- if (originState.securityDetails.keyExchangeGroup)
+ }
+ if (originState.securityDetails.keyExchangeGroup) {
table.addRow(Common.UIString('Key exchange group'), originState.securityDetails.keyExchangeGroup);
+ }
table.addRow(
Common.UIString('Cipher'),
originState.securityDetails.cipher +
@@ -862,8 +890,9 @@ Security.SecurityOriginView = class extends UI.VBox {
Security.SecurityPanel.createCertificateViewerButtonForOrigin(
Common.UIString('Open full certificate details'), origin));
- if (!sctSection)
+ if (!sctSection) {
return;
+ }
// Show summary of SCT(s) of Certificate Transparency.
const sctSummaryTable = new Security.SecurityDetailsTable();
@@ -896,10 +925,11 @@ Security.SecurityOriginView = class extends UI.VBox {
if (sctListLength) {
function toggleSctDetailsDisplay() {
const isDetailsShown = !sctTableWrapper.classList.contains('hidden');
- if (isDetailsShown)
+ if (isDetailsShown) {
toggleSctsDetailsLink.textContent = ls`Show full details`;
- else
+ } else {
toggleSctsDetailsLink.textContent = ls`Hide full details`;
+ }
sctSummaryTable.element().classList.toggle('hidden');
sctTableWrapper.classList.toggle('hidden');
}
@@ -969,20 +999,27 @@ Security.SecurityOriginView = class extends UI.VBox {
for (let i = 0; i < sanList.length; i++) {
const span = sanDiv.createChild('span', 'san-entry');
span.textContent = sanList[i];
- if (listIsTruncated && i >= truncatedNumToShow)
+ if (listIsTruncated && i >= truncatedNumToShow) {
span.classList.add('truncated-entry');
+ }
}
if (listIsTruncated) {
function toggleSANTruncation() {
if (sanDiv.classList.contains('truncated-san')) {
sanDiv.classList.remove('truncated-san');
+ truncatedSANToggle.classList.remove('show-more');
+ truncatedSANToggle.classList.add('show-less');
truncatedSANToggle.textContent = ls`Show less`;
} else {
sanDiv.classList.add('truncated-san');
+ truncatedSANToggle.classList.add('show-more');
+ truncatedSANToggle.classList.remove('show-less');
truncatedSANToggle.textContent = ls`Show more (${sanList.length} total)`;
}
}
- const truncatedSANToggle = UI.createTextButton(ls`Show more (${sanList.length} total)`, toggleSANTruncation);
+
+ const truncatedSANToggle = sanDiv.createChild('span', 'devtools-link');
+ truncatedSANToggle.addEventListener('click', toggleSANTruncation);
sanDiv.appendChild(truncatedSANToggle);
toggleSANTruncation();
}
@@ -995,8 +1032,9 @@ Security.SecurityOriginView = class extends UI.VBox {
*/
setSecurityState(newSecurityState) {
for (const className of Array.prototype.slice.call(this._originLockIcon.classList)) {
- if (className.startsWith('security-property-'))
+ if (className.startsWith('security-property-')) {
this._originLockIcon.classList.remove(className);
+ }
}
this._originLockIcon.classList.add('security-property-' + newSecurityState);
@@ -1028,9 +1066,10 @@ Security.SecurityDetailsTable = class {
row.createChild('div').textContent = key;
const valueDiv = row.createChild('div');
- if (typeof value === 'string')
+ if (typeof value === 'string') {
valueDiv.textContent = value;
- else
+ } else {
valueDiv.appendChild(value);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security/mainView.css b/chromium/third_party/blink/renderer/devtools/front_end/security/mainView.css
index e3e17aa96af..7282dbce836 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security/mainView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security/mainView.css
@@ -141,6 +141,7 @@
.security-certificate-button {
margin-top: 8px;
+ margin-left: 0;
}
.security-explanation .security-property {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security/originView.css b/chromium/third_party/blink/renderer/devtools/front_end/security/originView.css
index b5495d0fab9..7b970b7887f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security/originView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security/originView.css
@@ -39,7 +39,7 @@
.security-origin-view .origin-display {
font-size: 12px;
- padding-left: 38px;
+ padding-left: 32px;
display: flex;
align-items: center;
}
@@ -52,7 +52,7 @@
display: inline-block;
vertical-align: middle;
position: absolute;
- left: 16px;
+ left: 13px;
}
.security-origin-view .origin-view-section-title {
@@ -118,8 +118,29 @@
.origin-button {
margin-top: 4px;
+ margin-left: 0;
}
.origin-view-section:last-child {
border-bottom:none;
}
+
+.devtools-link {
+ display: inline-flex;
+}
+
+.devtools-link.show-less:after,
+.devtools-link.show-more:after {
+ content: '';
+ width: 0;
+ height: 0;
+ border: 4px solid transparent;
+ border-top-color:rgb(17, 85, 204);
+ align-self: center;
+ transform: translateY(25%);
+ margin-left: 8px;
+}
+
+.devtools-link.show-less:after {
+ transform: rotate(180deg) translateY(25%);
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
index 33b7dc14366..8eb546c50ca 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security/security_strings.grdp
@@ -97,7 +97,7 @@
View <ph name="FILTERREQUESTCOUNT">$1d<ex>2</ex></ph> requests in Network Panel
</message>
<message name="IDS_DEVTOOLS_a10edd2a3893a9ba446fb26e7c27556a" desc="Text in Security Panel of the Security panel">
- This request complies with Chrome&apos;s Certificate Transparency policy.
+ This request complies with <ph name="LOCKED_1">Chrome</ph>&apos;s Certificate Transparency policy.
</message>
<message name="IDS_DEVTOOLS_a2b16c6b3db371738d0e5c3f3ba2b54d" desc="Text in Security Panel of the Security panel">
This response was loaded from cache. Some security details might be missing.
@@ -115,7 +115,7 @@
Show more (<ph name="SANLIST_LENGTH">$1s<ex>2</ex></ph> total)
</message>
<message name="IDS_DEVTOOLS_b92f649b203ca680d444432324771186" desc="Text in Security Panel of the Security panel">
- This request does not comply with Chrome&apos;s Certificate Transparency policy.
+ This request does not comply with <ph name="LOCKED_1">Chrome</ph>&apos;s Certificate Transparency policy.
</message>
<message name="IDS_DEVTOOLS_c3db8a95444ea6caa45cc7dcb6e78d64" desc="Summary div text content in Security Panel of the Security panel">
Security overview
@@ -129,6 +129,9 @@
<message name="IDS_DEVTOOLS_d42c8bbf1d0f4a65f4dec450f2bc4439" desc="Text in Security Panel of the Security panel">
Key exchange
</message>
+ <message name="IDS_DEVTOOLS_daa52ee980b16f68bc0d3a9b5cc8deb7" desc="Text in Security Panel of the Security panel">
+ View requests in Network Panel
+ </message>
<message name="IDS_DEVTOOLS_decb9f523d4cf5dc037b61cb555e6bf3" desc="Not secure div text content in Security Panel of the Security panel">
Not secure
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/security_test_runner/SecurityTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/security_test_runner/SecurityTestRunner.js
index 1842949f9d8..c968246a916 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/security_test_runner/SecurityTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/security_test_runner/SecurityTestRunner.js
@@ -12,15 +12,17 @@ SecurityTestRunner.dumpSecurityPanelSidebarOrigins = function() {
const originGroup = Security.SecurityPanelSidebarTree.OriginGroup[key];
const element = Security.SecurityPanel._instance()._sidebarTree._originGroups.get(originGroup);
- if (element.hidden)
+ if (element.hidden) {
continue;
+ }
TestRunner.addResult('Group: ' + element.title);
const originTitles = element.childrenListElement.getElementsByTagName('span');
for (const originTitle of originTitles) {
- if (originTitle.className !== 'tree-element-title')
+ if (originTitle.className !== 'tree-element-title') {
TestRunner.dumpDeepInnerHTML(originTitle);
+ }
}
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/services/ServiceManager.js b/chromium/third_party/blink/renderer/devtools/front_end/services/ServiceManager.js
index b1425330560..c7213b81e22 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/services/ServiceManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/services/ServiceManager.js
@@ -4,20 +4,19 @@
/**
* @unrestricted
*/
-Services.ServiceManager = class {
+export default class ServiceManager {
/**
* @param {string} serviceName
- * @return {!Promise<?Services.ServiceManager.Service>}
+ * @return {!Promise<?Service>}
*/
createRemoteService(serviceName) {
if (!this._remoteConnection) {
- const url = Runtime.queryParam('service-backend');
+ const url = Root.Runtime.queryParam('service-backend');
if (!url) {
console.error('No endpoint address specified');
- return /** @type {!Promise<?Services.ServiceManager.Service>} */ (Promise.resolve(null));
+ return /** @type {!Promise<?Service>} */ (Promise.resolve(null));
}
- this._remoteConnection =
- new Services.ServiceManager.Connection(new Services.ServiceManager.RemoteServicePort(url));
+ this._remoteConnection = new Connection(new RemoteServicePort(url));
}
return this._remoteConnection._createService(serviceName);
}
@@ -25,35 +24,39 @@ Services.ServiceManager = class {
/**
* @param {string} appName
* @param {string} serviceName
- * @return {!Promise<?Services.ServiceManager.Service>}
+ * @return {!Promise<?Service>}
*/
createAppService(appName, serviceName) {
let url = appName + '.js';
- const remoteBase = Runtime.queryParam('remoteBase');
- const debugFrontend = Runtime.queryParam('debugFrontend');
+ const remoteBase = Root.Runtime.queryParam('remoteBase');
+ const debugFrontend = Root.Runtime.queryParam('debugFrontend');
const isUnderTest = Host.isUnderTest();
const queryParams = [];
- if (remoteBase)
+ if (remoteBase) {
queryParams.push('remoteBase=' + remoteBase);
- if (debugFrontend)
+ }
+ if (debugFrontend) {
queryParams.push('debugFrontend=' + debugFrontend);
- if (isUnderTest)
+ }
+ if (isUnderTest) {
queryParams.push('isUnderTest=true');
+ }
- if (queryParams.length)
+ if (queryParams.length) {
url += `?${queryParams.join('&')}`;
+ }
const worker = new Worker(url);
- const connection = new Services.ServiceManager.Connection(new Services.ServiceManager.WorkerServicePort(worker));
+ const connection = new Connection(new WorkerServicePort(worker));
return connection._createService(serviceName);
}
-};
+}
/**
* @unrestricted
*/
-Services.ServiceManager.Connection = class {
+export class Connection {
/**
* @param {!ServicePort} port
*/
@@ -64,13 +67,13 @@ Services.ServiceManager.Connection = class {
this._lastId = 1;
/** @type {!Map<number, function(?Object)>}*/
this._callbacks = new Map();
- /** @type {!Map<string, !Services.ServiceManager.Service>}*/
+ /** @type {!Map<string, !Service>}*/
this._services = new Map();
}
/**
* @param {string} serviceName
- * @return {!Promise<?Services.ServiceManager.Service>}
+ * @return {!Promise<?Service>}
*/
_createService(serviceName) {
return this._sendCommand(serviceName + '.create').then(result => {
@@ -78,14 +81,14 @@ Services.ServiceManager.Connection = class {
console.error('Could not initialize service: ' + serviceName);
return null;
}
- const service = new Services.ServiceManager.Service(this, serviceName, result.id);
+ const service = new Service(this, serviceName, result.id);
this._services.set(serviceName + ':' + result.id, service);
return service;
});
}
/**
- * @param {!Services.ServiceManager.Service} service
+ * @param {!Service} service
*/
_serviceDisposed(service) {
this._services.delete(service._serviceName + ':' + service._objectId);
@@ -104,8 +107,9 @@ Services.ServiceManager.Connection = class {
const id = this._lastId++;
const message = JSON.stringify({id: id, method: method, params: params || {}});
return this._port.send(message).then(success => {
- if (!success)
+ if (!success) {
return Promise.resolve(null);
+ }
return new Promise(fulfill => this._callbacks.set(id, fulfill));
});
}
@@ -122,8 +126,9 @@ Services.ServiceManager.Connection = class {
return;
}
if (object.id) {
- if (object.error)
+ if (object.error) {
console.error('Service error: ' + object.error);
+ }
this._callbacks.get(object.id)(object.error ? null : object.result);
this._callbacks.delete(object.id);
return;
@@ -141,21 +146,23 @@ Services.ServiceManager.Connection = class {
}
_connectionClosed() {
- for (const callback of this._callbacks.values())
+ for (const callback of this._callbacks.values()) {
callback(null);
+ }
this._callbacks.clear();
- for (const service of this._services.values())
+ for (const service of this._services.values()) {
service._dispatchNotification('disposed');
+ }
this._services.clear();
}
-};
+}
/**
* @unrestricted
*/
-Services.ServiceManager.Service = class {
+export class Service {
/**
- * @param {!Services.ServiceManager.Connection} connection
+ * @param {!Connection} connection
* @param {string} serviceName
* @param {string} objectId
*/
@@ -208,13 +215,13 @@ Services.ServiceManager.Service = class {
}
handler(params);
}
-};
+}
/**
* @implements {ServicePort}
* @unrestricted
*/
-Services.ServiceManager.RemoteServicePort = class {
+export class RemoteServicePort {
/**
* @param {string} url
*/
@@ -236,13 +243,14 @@ Services.ServiceManager.RemoteServicePort = class {
* @return {!Promise<boolean>}
*/
_open() {
- if (!this._connectionPromise)
+ if (!this._connectionPromise) {
this._connectionPromise = new Promise(promiseBody.bind(this));
+ }
return this._connectionPromise;
/**
* @param {function(boolean)} fulfill
- * @this {Services.ServiceManager.RemoteServicePort}
+ * @this {RemoteServicePort}
*/
function promiseBody(fulfill) {
let socket;
@@ -256,7 +264,7 @@ Services.ServiceManager.RemoteServicePort = class {
}
/**
- * @this {Services.ServiceManager.RemoteServicePort}
+ * @this {RemoteServicePort}
*/
function onConnect() {
this._socket = socket;
@@ -265,18 +273,19 @@ Services.ServiceManager.RemoteServicePort = class {
/**
* @param {!Event} event
- * @this {Services.ServiceManager.RemoteServicePort}
+ * @this {RemoteServicePort}
*/
function onMessage(event) {
this._messageHandler(event.data);
}
/**
- * @this {Services.ServiceManager.RemoteServicePort}
+ * @this {RemoteServicePort}
*/
function onClose() {
- if (!this._socket)
+ if (!this._socket) {
fulfill(false);
+ }
this._socketClosed(!!this._socket);
}
}
@@ -317,16 +326,17 @@ Services.ServiceManager.RemoteServicePort = class {
_socketClosed(notifyClient) {
this._socket = null;
delete this._connectionPromise;
- if (notifyClient)
+ if (notifyClient) {
this._closeHandler();
+ }
}
-};
+}
/**
* @implements {ServicePort}
* @unrestricted
*/
-Services.ServiceManager.WorkerServicePort = class {
+export class WorkerServicePort {
/**
* @param {!Worker} worker
*/
@@ -341,7 +351,7 @@ Services.ServiceManager.WorkerServicePort = class {
/**
* @param {!Event} event
- * @this {Services.ServiceManager.WorkerServicePort}
+ * @this {WorkerServicePort}
*/
function onMessage(event) {
if (event.data === 'workerReady') {
@@ -384,11 +394,33 @@ Services.ServiceManager.WorkerServicePort = class {
*/
close() {
return this._workerPromise.then(() => {
- if (this._worker)
+ if (this._worker) {
this._worker.terminate();
+ }
return false;
});
}
-};
+}
+
+/* Legacy exported object */
+self.Services = self.Services || {};
+
+/* Legacy exported object */
+Services = Services || {};
+
+/** @constructor */
+Services.ServiceManager = ServiceManager;
+
+/** @constructor */
+Services.ServiceManager.Connection = Connection;
+
+/** @constructor */
+Services.ServiceManager.Service = Service;
+
+/** @constructor */
+Services.ServiceManager.RemoteServicePort = RemoteServicePort;
+
+/** @constructor */
+Services.ServiceManager.WorkerServicePort = WorkerServicePort;
-Services.serviceManager = new Services.ServiceManager();
+Services.serviceManager = new ServiceManager();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/services/module.json b/chromium/third_party/blink/renderer/devtools/front_end/services/module.json
index 633b25470ff..85648ae4786 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/services/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/services/module.json
@@ -3,7 +3,9 @@
"common",
"host"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "services.js",
"ServiceManager.js"
]
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/services/services.js b/chromium/third_party/blink/renderer/devtools/front_end/services/services.js
new file mode 100644
index 00000000000..90e00f603d9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/services/services.js
@@ -0,0 +1,9 @@
+// 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 * as ServiceManager from './ServiceManager.js';
+
+export {
+ ServiceManager,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js b/chromium/third_party/blink/renderer/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js
index c2a998ed8bc..fc3f1c29ddf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/settings/FrameworkBlackboxSettingsTab.js
@@ -55,8 +55,9 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
_settingUpdated() {
this._list.clear();
const patterns = this._setting.getAsArray();
- for (let i = 0; i < patterns.length; ++i)
+ for (let i = 0; i < patterns.length; ++i) {
this._list.appendItem(patterns[i], true);
+ }
}
_addButtonClicked() {
@@ -77,8 +78,9 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
element.createChild('div', 'blackbox-separator');
element.createChild('div', 'blackbox-behavior').textContent =
item.disabled ? this._disabledLabel : this._blackboxLabel;
- if (item.disabled)
+ if (item.disabled) {
element.classList.add('blackbox-disabled');
+ }
return element;
}
@@ -104,8 +106,9 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
item.disabled = editor.control('behavior').value === this._disabledLabel;
const list = this._setting.getAsArray();
- if (isNew)
+ if (isNew) {
list.push(item);
+ }
this._setting.setAsArray(list);
}
@@ -125,8 +128,9 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
* @return {!UI.ListWidget.Editor}
*/
_createEditor() {
- if (this._editor)
+ if (this._editor) {
return this._editor;
+ }
const editor = new UI.ListWidget.Editor();
this._editor = editor;
@@ -159,12 +163,14 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
const pattern = input.value.trim();
const patterns = this._setting.getAsArray();
- if (!pattern.length)
+ if (!pattern.length) {
return {valid: false, errorMessage: ls`Pattern cannot be empty`};
+ }
for (let i = 0; i < patterns.length; ++i) {
- if (i !== index && patterns[i].pattern === pattern)
+ if (i !== index && patterns[i].pattern === pattern) {
return {valid: false, errorMessage: ls`Pattern already exists`};
+ }
}
let regex;
@@ -172,10 +178,11 @@ Settings.FrameworkBlackboxSettingsTab = class extends UI.VBox {
regex = new RegExp(pattern);
} catch (e) {
}
- if (!regex)
+ if (!regex) {
return {valid: false, errorMessage: ls`Pattern must be a valid regular expression`};
- else
+ } else {
return {valid: true};
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js b/chromium/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js
index bbcabfdaf5d..728a7b8999d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js
@@ -36,7 +36,6 @@ Settings.SettingsScreen = class extends UI.VBox {
super(true);
this.registerRequiredCSS('settings/settingsScreen.css');
- this.contentElement.tabIndex = 0;
this.contentElement.classList.add('settings-window-main');
this.contentElement.classList.add('vbox');
@@ -69,9 +68,11 @@ Settings.SettingsScreen = class extends UI.VBox {
static _showSettingsScreen(name) {
const settingsScreen =
/** @type {!Settings.SettingsScreen} */ (self.runtime.sharedInstance(Settings.SettingsScreen));
- if (settingsScreen.isShowing())
+ if (settingsScreen.isShowing()) {
return;
+ }
const dialog = new UI.Dialog();
+ dialog.contentElement.tabIndex = -1;
dialog.addCloseButton();
settingsScreen.show(dialog.contentElement);
dialog.show();
@@ -99,8 +100,9 @@ Settings.SettingsScreen = class extends UI.VBox {
*/
_keyDown(event) {
const shiftKeyCode = 16;
- if (event.keyCode === shiftKeyCode && ++this._developerModeCounter > 5)
+ if (event.keyCode === shiftKeyCode && ++this._developerModeCounter > 5) {
this.contentElement.classList.add('settings-developer-mode');
+ }
}
};
@@ -116,8 +118,9 @@ Settings.SettingsTab = class extends UI.VBox {
constructor(name, id) {
super();
this.element.classList.add('settings-tab-container');
- if (id)
+ if (id) {
this.element.id = id;
+ }
const header = this.element.createChild('header');
header.createChild('h1').createTextChild(name);
this.containerElement = this.element.createChild('div', 'settings-container-wrapper')
@@ -153,8 +156,9 @@ Settings.GenericSettingsTab = class extends Settings.SettingsTab {
['', 'Appearance', 'Sources', 'Elements', 'Network', 'Performance', 'Console', 'Extensions'];
/** @type {!Map<string, !Element>} */
this._nameToSection = new Map();
- for (const sectionName of explicitSectionOrder)
+ for (const sectionName of explicitSectionOrder) {
this._sectionElement(sectionName);
+ }
self.runtime.extensions('setting').forEach(this._addSetting.bind(this));
self.runtime.extensions(UI.SettingUI).forEach(this._addSettingUI.bind(this));
@@ -168,33 +172,37 @@ Settings.GenericSettingsTab = class extends Settings.SettingsTab {
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @return {boolean}
*/
static isSettingVisible(extension) {
const descriptor = extension.descriptor();
- if (!('title' in descriptor))
+ if (!('title' in descriptor)) {
return false;
- if (!('category' in descriptor))
+ }
+ if (!('category' in descriptor)) {
return false;
+ }
return true;
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
_addSetting(extension) {
- if (!Settings.GenericSettingsTab.isSettingVisible(extension))
+ if (!Settings.GenericSettingsTab.isSettingVisible(extension)) {
return;
+ }
const sectionElement = this._sectionElement(extension.descriptor()['category']);
const setting = Common.moduleSetting(extension.descriptor()['settingName']);
const settingControl = UI.SettingsUI.createControlForSetting(setting);
- if (settingControl)
+ if (settingControl) {
sectionElement.appendChild(settingControl);
+ }
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
_addSettingUI(extension) {
const descriptor = extension.descriptor();
@@ -208,8 +216,9 @@ Settings.GenericSettingsTab = class extends Settings.SettingsTab {
function appendCustomSetting(object) {
const settingUI = /** @type {!UI.SettingUI} */ (object);
const element = settingUI.settingElement();
- if (element)
+ if (element) {
this._sectionElement(sectionName).appendChild(element);
+ }
}
}
@@ -235,12 +244,13 @@ Settings.ExperimentsSettingsTab = class extends Settings.SettingsTab {
constructor() {
super(Common.UIString('Experiments'), 'experiments-tab-content');
- const experiments = Runtime.experiments.allConfigurableExperiments();
+ const experiments = Root.Runtime.experiments.allConfigurableExperiments();
if (experiments.length) {
const experimentsSection = this._appendSection();
experimentsSection.appendChild(this._createExperimentsWarningSubsection());
- for (let i = 0; i < experiments.length; ++i)
+ for (let i = 0; i < experiments.length; ++i) {
experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i]));
+ }
}
}
@@ -290,7 +300,7 @@ Settings.SettingsScreen.ActionDelegate = class {
Settings.SettingsScreen._showSettingsScreen();
return true;
case 'settings.documentation':
- InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/');
+ Host.InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/');
return true;
case 'settings.shortcuts':
Settings.SettingsScreen._showSettingsScreen(Common.UIString('Shortcuts'));
@@ -322,40 +332,42 @@ Settings.SettingsScreen.Revealer = class {
return success ? Promise.resolve() : Promise.reject();
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
function revealModuleSetting(extension) {
- if (!Settings.GenericSettingsTab.isSettingVisible(extension))
+ if (!Settings.GenericSettingsTab.isSettingVisible(extension)) {
return;
+ }
if (extension.descriptor()['settingName'] === setting.name) {
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
Settings.SettingsScreen._showSettingsScreen();
success = true;
}
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
function revealSettingUI(extension) {
const settings = extension.descriptor()['settings'];
if (settings && settings.indexOf(setting.name) !== -1) {
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
Settings.SettingsScreen._showSettingsScreen();
success = true;
}
}
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
function revealSettingsView(extension) {
const location = extension.descriptor()['location'];
- if (location !== 'settings-view')
+ if (location !== 'settings-view') {
return;
+ }
const settings = extension.descriptor()['settings'];
if (settings && settings.indexOf(setting.name) !== -1) {
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
Settings.SettingsScreen._showSettingsScreen(extension.descriptor()['id']);
success = true;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
index 1249bdaacaa..275b8d8b492 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/settings/settings_strings.grdp
@@ -3,9 +3,6 @@
<message name="IDS_DEVTOOLS_0f653ae68147586eb189d7baf37a696a" desc="Text of button in Settings Screen of the Settings">
Restore defaults and reload
</message>
- <message name="IDS_DEVTOOLS_29e9d8e295b1d5b3002d2d3d5baa4c37" desc="Text in Settings Screen of the Settings">
- Shortcuts
- </message>
<message name="IDS_DEVTOOLS_2cce43a6505a5d1bdf7ea98bf7fd1bc8" desc="Blackbox label in Framework Blackbox Settings Tab of the Settings">
Blackbox
</message>
@@ -42,9 +39,6 @@
<message name="IDS_DEVTOOLS_c745d3ac390f120535d734cd14e2f6aa" desc="Blackbox content scripts title in Framework Blackbox Settings Tab of the Settings">
Blackbox content scripts (extension scripts in the page)
</message>
- <message name="IDS_DEVTOOLS_c9deece3e6de26d07ef6409b96f21fd0" desc="Title of Blackboxing settings">
- Blackboxing
- </message>
<message name="IDS_DEVTOOLS_d0834fcec6337785ee749c8f5464f6f6" desc="Text in Settings Screen of the Settings">
Preferences
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/shell.json b/chromium/third_party/blink/renderer/devtools/front_end/shell.json
index eaeb2dd4698..98efbd34174 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/shell.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/shell.json
@@ -41,7 +41,6 @@
{ "name": "snippets" },
{ "name": "source_frame" },
{ "name": "sources" },
- { "name": "terminal", "type": "remote" },
{ "name": "text_editor" },
{ "name": "workspace_diff" },
{ "name": "protocol_monitor"}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js b/chromium/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
index a6d611d035d..fd00ef5683e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/snippets/ScriptSnippetFileSystem.js
@@ -28,7 +28,7 @@ Snippets.SnippetFileSystem = class extends Persistence.PlatformFileSystem {
const nextId = this._lastSnippetIdentifierSetting.get() + 1;
this._lastSnippetIdentifierSetting.set(nextId);
- const snippetName = `Script snippet #${nextId}`;
+ const snippetName = ls`Script snippet #${nextId}`;
const snippets = this._snippetsSetting.get();
snippets.push({name: snippetName, content: ''});
this._snippetsSetting.set(snippets);
@@ -55,12 +55,12 @@ Snippets.SnippetFileSystem = class extends Persistence.PlatformFileSystem {
/**
* @override
* @param {string} path
- * @param {function(?string,boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(path, callback) {
+ async requestFileContent(path) {
const name = unescape(path.substring(1));
const snippet = this._snippetsSetting.get().find(snippet => snippet.name === name);
- callback(snippet ? snippet.content : null, /* encoded */ false);
+ return {content: snippet ? snippet.content : null, isEncoded: false};
}
/**
@@ -153,15 +153,16 @@ Snippets.SnippetFileSystem = class extends Persistence.PlatformFileSystem {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
Snippets.evaluateScriptSnippet = async function(uiSourceCode) {
- if (!uiSourceCode.url().startsWith('snippet://'))
+ if (!uiSourceCode.url().startsWith('snippet://')) {
return;
+ }
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return;
+ }
const runtimeModel = executionContext.runtimeModel;
-
await uiSourceCode.requestContent();
uiSourceCode.commitWorkingCopy();
const expression = uiSourceCode.workingCopy();
@@ -186,8 +187,9 @@ Snippets.evaluateScriptSnippet = async function(uiSourceCode) {
runtimeModel, result.exceptionDetails, /* messageType */ undefined, /* timestamp */ undefined, url));
return;
}
- if (!result.object)
+ if (!result.object) {
return;
+ }
const scripts = executionContext.debuggerModel.scriptsForSourceURL(url);
const scriptId = scripts[scripts.length - 1].scriptId;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/snippets/SnippetsQuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/snippets/SnippetsQuickOpen.js
index c48bf1ab339..c2c3228e4c6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/snippets/SnippetsQuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/snippets/SnippetsQuickOpen.js
@@ -14,8 +14,9 @@ Snippets.SnippetsQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
* @param {string} promptValue
*/
selectItem(itemIndex, promptValue) {
- if (itemIndex === null)
+ if (itemIndex === null) {
return;
+ }
Snippets.evaluateScriptSnippet(this._snippets[itemIndex]);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
index 0ec05112d12..770ad825957 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/snippets/snippets_strings.grdp
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_DEVTOOLS_b1d75786654fa93f10c31c3b544bbd03" desc="Title of the Filtered List WidgetProvider of Quick Open">
- Run snippet
+ <message name="IDS_DEVTOOLS_a8c377be97611cba090c400b4b54f753" desc="Default snippet name when a new snippet is created in the Sources panel">
+ Script snippet #<ph name="NEXTID">$1s<ex>1</ex></ph>
</message>
<message name="IDS_DEVTOOLS_e0fe9b9cadde935642ad15a85c79d7b1" desc="Text in Snippets Quick Open of the Sources panel when opening snippets">
No snippets found.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/BinaryResourceViewFactory.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/BinaryResourceViewFactory.js
index 855bc2ad58d..cdc7209b5a4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/BinaryResourceViewFactory.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/BinaryResourceViewFactory.js
@@ -16,7 +16,7 @@ SourceFrame.BinaryResourceViewFactory = class {
this._arrayPromise = null;
/** @type {?Promise<string>} */
this._hexPromise = null;
- /** @type {?Promise<string>} */
+ /** @type {?Promise<!Common.DeferredContent>} */
this._utf8Promise = null;
}
@@ -31,14 +31,14 @@ SourceFrame.BinaryResourceViewFactory = class {
}
/**
- * @return {!Promise<string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
async hex() {
if (!this._hexPromise) {
this._hexPromise = new Promise(async resolve => {
const content = await this._fetchContentAsArray();
const hexString = SourceFrame.BinaryResourceViewFactory.uint8ArrayToHexString(content);
- resolve(hexString);
+ resolve({content: hexString, isEncoded: false});
});
}
@@ -46,21 +46,21 @@ SourceFrame.BinaryResourceViewFactory = class {
}
/**
- * @return {!Promise<string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
async base64() {
- return this._base64content;
+ return {content: this._base64content, isEncoded: true};
}
/**
- * @return {!Promise<string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
async utf8() {
if (!this._utf8Promise) {
this._utf8Promise = new Promise(async resolve => {
const content = await this._fetchContentAsArray();
const utf8String = new TextDecoder('utf8').decode(content);
- resolve(utf8String);
+ resolve({content: utf8String, isEncoded: false});
});
}
@@ -80,9 +80,12 @@ SourceFrame.BinaryResourceViewFactory = class {
* @return {!SourceFrame.ResourceSourceFrame}
*/
createHexView() {
- const hexViewerContentProvider = new Common.StaticContentProvider(
- this._contentUrl, this._resourceType,
- async () => SourceFrame.BinaryResourceViewFactory.uint8ArrayToHexViewer(await this._fetchContentAsArray()));
+ const hexViewerContentProvider =
+ new Common.StaticContentProvider(this._contentUrl, this._resourceType, async () => {
+ const contentAsArray = await this._fetchContentAsArray();
+ const content = SourceFrame.BinaryResourceViewFactory.uint8ArrayToHexViewer(contentAsArray);
+ return {content, isEncoded: false};
+ });
return new SourceFrame.ResourceSourceFrame(
hexViewerContentProvider,
/* autoPrettyPrint */ false, {lineNumbers: false, lineWrapping: false});
@@ -92,7 +95,7 @@ SourceFrame.BinaryResourceViewFactory = class {
* @return {!SourceFrame.ResourceSourceFrame}
*/
createUtf8View() {
- const utf8fn = /** @type {function():!Promise<?string>} */ (this.utf8.bind(this));
+ const utf8fn = this.utf8.bind(this);
const utf8ContentProvider = new Common.StaticContentProvider(this._contentUrl, this._resourceType, utf8fn);
return new SourceFrame.ResourceSourceFrame(
utf8ContentProvider,
@@ -105,8 +108,9 @@ SourceFrame.BinaryResourceViewFactory = class {
*/
static uint8ArrayToHexString(uint8Array) {
let output = '';
- for (let i = 0; i < uint8Array.length; i++)
+ for (let i = 0; i < uint8Array.length; i++) {
output += SourceFrame.BinaryResourceViewFactory.numberToHex(uint8Array[i], 2);
+ }
return output;
}
@@ -117,8 +121,9 @@ SourceFrame.BinaryResourceViewFactory = class {
*/
static numberToHex(number, padding) {
let hex = number.toString(16);
- while (hex.length < padding)
+ while (hex.length < padding) {
hex = '0' + hex;
+ }
return hex;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
index 227860389c9..50e4ad44238 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/FontView.js
@@ -55,28 +55,33 @@ SourceFrame.FontView = class extends UI.SimpleView {
/**
* @param {string} uniqueFontName
- * @param {?string} content
+ * @param {!Common.DeferredContent} deferredContent
*/
- _onFontContentLoaded(uniqueFontName, content) {
+ _onFontContentLoaded(uniqueFontName, deferredContent) {
+ const {content} = deferredContent;
const url = content ? Common.ContentProvider.contentAsDataURL(content, this._mimeType, true) : this._url;
this.fontStyleElement.textContent =
String.sprintf('@font-face { font-family: "%s"; src: url(%s); }', uniqueFontName, url);
}
_createContentIfNeeded() {
- if (this.fontPreviewElement)
+ if (this.fontPreviewElement) {
return;
+ }
const uniqueFontName = 'WebInspectorFontPreview' + (++SourceFrame.FontView._fontId);
this.fontStyleElement = createElement('style');
- this._contentProvider.requestContent().then(this._onFontContentLoaded.bind(this, uniqueFontName));
+ this._contentProvider.requestContent().then(deferredContent => {
+ this._onFontContentLoaded(uniqueFontName, deferredContent);
+ });
this.element.appendChild(this.fontStyleElement);
const fontPreview = createElement('div');
for (let i = 0; i < SourceFrame.FontView._fontPreviewLines.length; ++i) {
- if (i > 0)
+ if (i > 0) {
fontPreview.createChild('br');
+ }
fontPreview.createTextChild(SourceFrame.FontView._fontPreviewLines[i]);
}
this.fontPreviewElement = fontPreview.cloneNode(true);
@@ -109,8 +114,9 @@ SourceFrame.FontView = class extends UI.SimpleView {
* @override
*/
onResize() {
- if (this._inResize)
+ if (this._inResize) {
return;
+ }
this._inResize = true;
try {
@@ -129,8 +135,9 @@ SourceFrame.FontView = class extends UI.SimpleView {
}
updateFontPreviewSize() {
- if (!this.fontPreviewElement || !this.isShowing())
+ if (!this.fontPreviewElement || !this.isShowing()) {
return;
+ }
this.fontPreviewElement.style.removeProperty('visibility');
const dimension = this._measureElement();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
index c6f5e86d7f6..43c8af66fcf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
@@ -94,15 +94,17 @@ SourceFrame.ImageView = class extends UI.SimpleView {
}
async _updateContentIfNeeded() {
- const content = await this._contentProvider.requestContent();
- if (this._cachedContent === content)
+ const {content} = await this._contentProvider.requestContent();
+ if (this._cachedContent === content) {
return;
+ }
const contentEncoded = await this._contentProvider.contentEncoded();
this._cachedContent = content;
let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, contentEncoded);
- if (content === null)
+ if (content === null) {
imageSrc = this._url;
+ }
const loadPromise = new Promise(x => this._imagePreviewElement.onload = x);
this._imagePreviewElement.src = imageSrc;
const size = content && !contentEncoded ? content.length : base64ToSize(content);
@@ -114,8 +116,9 @@ SourceFrame.ImageView = class extends UI.SimpleView {
_contextMenu(event) {
const contextMenu = new UI.ContextMenu(event);
- if (!this._parsedURL.isDataURL())
+ if (!this._parsedURL.isDataURL()) {
contextMenu.clipboardSection().appendItem(Common.UIString('Copy image URL'), this._copyImageURL.bind(this));
+ }
if (this._imagePreviewElement.src) {
contextMenu.clipboardSection().appendItem(
Common.UIString('Copy image as data URI'), this._copyImageAsDataURL.bind(this));
@@ -127,11 +130,11 @@ SourceFrame.ImageView = class extends UI.SimpleView {
}
_copyImageAsDataURL() {
- InspectorFrontendHost.copyText(this._imagePreviewElement.src);
+ Host.InspectorFrontendHost.copyText(this._imagePreviewElement.src);
}
_copyImageURL() {
- InspectorFrontendHost.copyText(this._url);
+ Host.InspectorFrontendHost.copyText(this._url);
}
_saveImage() {
@@ -142,7 +145,7 @@ SourceFrame.ImageView = class extends UI.SimpleView {
}
_openInNewTab() {
- InspectorFrontendHost.openInNewTab(this._url);
+ Host.InspectorFrontendHost.openInNewTab(this._url);
}
/**
@@ -150,8 +153,9 @@ SourceFrame.ImageView = class extends UI.SimpleView {
*/
async _handleDrop(dataTransfer) {
const items = dataTransfer.items;
- if (!items.length || items[0].kind !== 'file')
+ if (!items.length || items[0].kind !== 'file') {
return;
+ }
const entry = items[0].webkitGetAsEntry();
const encoded = !entry.name.endsWith('.svg');
@@ -165,14 +169,16 @@ SourceFrame.ImageView = class extends UI.SimpleView {
result = null;
console.error('Can\'t read file: ' + e);
}
- if (typeof result !== 'string')
+ if (typeof result !== 'string') {
return;
+ }
this._uiSourceCode.setContent(encoded ? btoa(result) : result, encoded);
};
- if (encoded)
+ if (encoded) {
reader.readAsBinaryString(file);
- else
+ } else {
reader.readAsText(file);
+ }
});
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
index 53fe8183333..f709ee18a33 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/JSONView.js
@@ -60,8 +60,9 @@ SourceFrame.JSONView = class extends UI.VBox {
static async createView(content) {
// We support non-strict JSON parsing by parsing an AST tree which is why we offload it to a worker.
const parsedJSON = await SourceFrame.JSONView._parseJSON(content);
- if (!parsedJSON || typeof parsedJSON.data !== 'object')
+ if (!parsedJSON || typeof parsedJSON.data !== 'object') {
return null;
+ }
const jsonView = new SourceFrame.JSONView(parsedJSON);
const searchableView = new UI.SearchableView(jsonView);
@@ -91,10 +92,12 @@ SourceFrame.JSONView = class extends UI.VBox {
*/
static _parseJSON(text) {
let returnObj = null;
- if (text)
+ if (text) {
returnObj = SourceFrame.JSONView._extractJSON(/** @type {string} */ (text));
- if (!returnObj)
+ }
+ if (!returnObj) {
return Promise.resolve(/** @type {?SourceFrame.ParsedJSON} */ (null));
+ }
return Formatter.formatterWorkerPool().parseJSONRelaxed(returnObj.data).then(handleReturnedJSON);
/**
@@ -102,8 +105,9 @@ SourceFrame.JSONView = class extends UI.VBox {
* @return {?SourceFrame.ParsedJSON}
*/
function handleReturnedJSON(data) {
- if (!data)
+ if (!data) {
return null;
+ }
returnObj.data = data;
return returnObj;
}
@@ -115,23 +119,26 @@ SourceFrame.JSONView = class extends UI.VBox {
*/
static _extractJSON(text) {
// Do not treat HTML as JSON.
- if (text.startsWith('<'))
+ if (text.startsWith('<')) {
return null;
+ }
let inner = SourceFrame.JSONView._findBrackets(text, '{', '}');
const inner2 = SourceFrame.JSONView._findBrackets(text, '[', ']');
inner = inner2.length > inner.length ? inner2 : inner;
// Return on blank payloads or on payloads significantly smaller than original text.
- if (inner.length === -1 || text.length - inner.length > 80)
+ if (inner.length === -1 || text.length - inner.length > 80) {
return null;
+ }
const prefix = text.substring(0, inner.start);
const suffix = text.substring(inner.end + 1);
text = text.substring(inner.start, inner.end + 1);
// Only process valid JSONP.
- if (suffix.trim().length && !(suffix.trim().startsWith(')') && prefix.trim().endsWith('(')))
+ if (suffix.trim().length && !(suffix.trim().startsWith(')') && prefix.trim().endsWith('('))) {
return null;
+ }
return new SourceFrame.ParsedJSON(text, prefix, suffix);
}
@@ -146,8 +153,9 @@ SourceFrame.JSONView = class extends UI.VBox {
const start = text.indexOf(open);
const end = text.lastIndexOf(close);
let length = end - start - 1;
- if (start === -1 || end === -1 || end < start)
+ if (start === -1 || end === -1 || end < start) {
length = -1;
+ }
return {start: start, end: end, length: length};
}
@@ -159,8 +167,9 @@ SourceFrame.JSONView = class extends UI.VBox {
}
_initialize() {
- if (this._initialized)
+ if (this._initialized) {
return;
+ }
this._initialized = true;
const obj = SDK.RemoteObject.fromLocalObject(this._parsedJSON.data);
@@ -178,11 +187,13 @@ SourceFrame.JSONView = class extends UI.VBox {
* @param {number} index
*/
_jumpToMatch(index) {
- if (!this._searchRegex)
+ if (!this._searchRegex) {
return;
+ }
const previousFocusElement = this._currentSearchTreeElements[this._currentSearchFocusIndex];
- if (previousFocusElement)
+ if (previousFocusElement) {
previousFocusElement.setSearchRegex(this._searchRegex);
+ }
const newFocusElement = this._currentSearchTreeElements[index];
if (newFocusElement) {
@@ -198,8 +209,9 @@ SourceFrame.JSONView = class extends UI.VBox {
* @param {number} count
*/
_updateSearchCount(count) {
- if (!this._searchableView)
+ if (!this._searchableView) {
return;
+ }
this._searchableView.updateSearchMatchesCount(count);
}
@@ -208,8 +220,9 @@ SourceFrame.JSONView = class extends UI.VBox {
*/
_updateSearchIndex(index) {
this._currentSearchFocusIndex = index;
- if (!this._searchableView)
+ if (!this._searchableView) {
return;
+ }
this._searchableView.updateCurrentMatchIndex(index);
}
@@ -221,8 +234,9 @@ SourceFrame.JSONView = class extends UI.VBox {
this._currentSearchTreeElements = [];
for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
- if (!(element instanceof ObjectUI.ObjectPropertyTreeElement))
+ if (!(element instanceof ObjectUI.ObjectPropertyTreeElement)) {
continue;
+ }
element.revertHighlightChanges();
}
this._updateSearchCount(0);
@@ -242,17 +256,20 @@ SourceFrame.JSONView = class extends UI.VBox {
this._searchRegex = searchConfig.toSearchRegex(true);
for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
- if (!(element instanceof ObjectUI.ObjectPropertyTreeElement))
+ if (!(element instanceof ObjectUI.ObjectPropertyTreeElement)) {
continue;
+ }
const hasMatch = element.setSearchRegex(this._searchRegex);
- if (hasMatch)
+ if (hasMatch) {
this._currentSearchTreeElements.push(element);
+ }
if (previousSearchFocusElement === element) {
const currentIndex = this._currentSearchTreeElements.length - 1;
- if (hasMatch || jumpBackwards)
+ if (hasMatch || jumpBackwards) {
newIndex = currentIndex;
- else
+ } else {
newIndex = currentIndex + 1;
+ }
}
}
this._updateSearchCount(this._currentSearchTreeElements.length);
@@ -270,8 +287,9 @@ SourceFrame.JSONView = class extends UI.VBox {
* @override
*/
jumpToNextSearchResult() {
- if (!this._currentSearchTreeElements.length)
+ if (!this._currentSearchTreeElements.length) {
return;
+ }
const newIndex = mod(this._currentSearchFocusIndex + 1, this._currentSearchTreeElements.length);
this._jumpToMatch(newIndex);
}
@@ -280,8 +298,9 @@ SourceFrame.JSONView = class extends UI.VBox {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._currentSearchTreeElements.length)
+ if (!this._currentSearchTreeElements.length) {
return;
+ }
const newIndex = mod(this._currentSearchFocusIndex - 1, this._currentSearchTreeElements.length);
this._jumpToMatch(newIndex);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
index 8d274466eb1..0f4a9dc68bc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
@@ -10,8 +10,9 @@ SourceFrame.PreviewFactory = class {
*/
static async createPreview(provider, mimeType) {
let resourceType = Common.ResourceType.fromMimeType(mimeType);
- if (resourceType === Common.resourceTypes.Other)
+ if (resourceType === Common.resourceTypes.Other) {
resourceType = provider.contentType();
+ }
switch (resourceType) {
case Common.resourceTypes.Image:
@@ -20,20 +21,27 @@ SourceFrame.PreviewFactory = class {
return new SourceFrame.FontView(mimeType, provider);
}
- let content = await provider.requestContent();
- if (!content)
+ const deferredContent = await provider.requestContent();
+ if (deferredContent.error) {
+ return new UI.EmptyWidget(deferredContent.error);
+ } else if (!deferredContent.content) {
return new UI.EmptyWidget(Common.UIString('Nothing to preview'));
+ }
- if (await provider.contentEncoded())
+ let content = deferredContent.content;
+ if (await provider.contentEncoded()) {
content = window.atob(content);
+ }
const parsedXML = SourceFrame.XMLView.parseXML(content, mimeType);
- if (parsedXML)
+ if (parsedXML) {
return SourceFrame.XMLView.createSearchableView(parsedXML);
+ }
const jsonView = await SourceFrame.JSONView.createView(content);
- if (jsonView)
+ if (jsonView) {
return jsonView;
+ }
if (resourceType.isTextType()) {
const highlighterType =
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
index a9640e8f9d3..37347aac7bf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
@@ -38,10 +38,11 @@ SourceFrame.ResourceSourceFrame = class extends SourceFrame.SourceFrame {
*/
constructor(resource, autoPrettyPrint, codeMirrorOptions) {
super(async () => {
- let content = await resource.requestContent();
- if (await resource.contentEncoded())
+ let content = (await resource.requestContent()).content || '';
+ if (await resource.contentEncoded()) {
content = window.atob(content);
- return content;
+ }
+ return {content, isEncoded: false};
}, codeMirrorOptions);
this._resource = resource;
this.setCanPrettyPrint(this._resource.contentType().isDocumentOrScriptOrStyleSheet(), autoPrettyPrint);
@@ -95,8 +96,9 @@ SourceFrame.ResourceSourceFrame.SearchableContainer = class extends UI.VBox {
searchableView.show(this.contentElement);
const toolbar = new UI.Toolbar('toolbar', this.contentElement);
- for (const item of sourceFrame.syncToolbarItems())
+ for (const item of sourceFrame.syncToolbarItems()) {
toolbar.appendToolbarItem(item);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceCodeDiff.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceCodeDiff.js
index ea77057df03..beadc0d8708 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceCodeDiff.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceCodeDiff.js
@@ -19,20 +19,23 @@ SourceFrame.SourceCodeDiff = class {
* @param {?string} newContent
*/
highlightModifiedLines(oldContent, newContent) {
- if (typeof oldContent !== 'string' || typeof newContent !== 'string')
+ if (typeof oldContent !== 'string' || typeof newContent !== 'string') {
return;
+ }
const diff =
SourceFrame.SourceCodeDiff.computeDiff(Diff.Diff.lineDiff(oldContent.split('\n'), newContent.split('\n')));
const changedLines = [];
for (let i = 0; i < diff.length; ++i) {
const diffEntry = diff[i];
- if (diffEntry.type === SourceFrame.SourceCodeDiff.EditType.Delete)
+ if (diffEntry.type === SourceFrame.SourceCodeDiff.EditType.Delete) {
continue;
+ }
for (let lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNumber) {
const position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
- if (position)
+ if (position) {
changedLines.push(position);
+ }
}
}
this._updateHighlightedLines(changedLines);
@@ -44,8 +47,9 @@ SourceFrame.SourceCodeDiff = class {
* @param {!Array<!TextEditor.TextEditorPositionHandle>} newLines
*/
_updateHighlightedLines(newLines) {
- if (this._animationTimeout)
+ if (this._animationTimeout) {
clearTimeout(this._animationTimeout);
+ }
this._animationTimeout = null;
this._textEditor.operation(operation.bind(this));
@@ -65,8 +69,9 @@ SourceFrame.SourceCodeDiff = class {
function toggleLines(value) {
for (let i = 0; i < this._animatedLines.length; ++i) {
const location = this._animatedLines[i].resolve();
- if (location)
+ if (location) {
this._textEditor.toggleLineClass(location.lineNumber, 'highlight-line-modification', value);
+ }
}
}
}
@@ -85,8 +90,9 @@ SourceFrame.SourceCodeDiff = class {
for (let i = 0; i < diff.length; ++i) {
const token = diff[i];
if (token[0] === Diff.Diff.Operation.Equal) {
- if (isInsideBlock)
+ if (isInsideBlock) {
flush();
+ }
currentLineNumber += token[1].length;
continue;
}
@@ -103,8 +109,9 @@ SourceFrame.SourceCodeDiff = class {
hasAdded = true;
}
}
- if (isInsideBlock)
+ if (isInsideBlock) {
flush();
+ }
if (result.length > 1 && result[0].from === 0 && result[1].from === 0) {
const merged = {type: SourceFrame.SourceCodeDiff.EditType.Modify, from: 0, to: result[1].to};
result.splice(0, 2, merged);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
index 7b7e6625d18..f48a1e299a5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
@@ -35,7 +35,7 @@
*/
SourceFrame.SourceFrame = class extends UI.SimpleView {
/**
- * @param {function(): !Promise<?string>} lazyContent
+ * @param {function(): !Promise<!Common.DeferredContent>} lazyContent
* @param {!UI.TextEditor.Options=} codeMirrorOptions
*/
constructor(lazyContent, codeMirrorOptions) {
@@ -69,14 +69,16 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
this._currentSearchResultIndex = -1;
this._searchResults = [];
this._searchRegex = null;
+ this._loadError = false;
this._textEditor.addEventListener(
SourceFrame.SourcesTextEditor.Events.EditorFocused, this._resetCurrentSearchResultIndex, this);
this._textEditor.addEventListener(
SourceFrame.SourcesTextEditor.Events.SelectionChanged, this._updateSourcePosition, this);
this._textEditor.addEventListener(UI.TextEditor.Events.TextChanged, event => {
- if (!this._muteChangeEventsForSetContent)
+ if (!this._muteChangeEventsForSetContent) {
this.onTextChanged(event.data.oldRange, event.data.newRange);
+ }
});
/** @type {boolean} */
this._muteChangeEventsForSetContent = false;
@@ -105,8 +107,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {!Array<number>}
*/
editorToRawLocation: (editorLineNumber, editorColumnNumber = 0) => {
- if (!this._pretty)
+ if (!this._pretty) {
return [editorLineNumber, editorColumnNumber];
+ }
return this._prettyToRawLocation(editorLineNumber, editorColumnNumber);
},
@@ -116,8 +119,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {!Array<number>}
*/
rawToEditorLocation: (lineNumber, columnNumber = 0) => {
- if (!this._pretty)
+ if (!this._pretty) {
return [lineNumber, columnNumber];
+ }
return this._rawToPrettyLocation(lineNumber, columnNumber);
}
};
@@ -146,13 +150,13 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
if (this._pretty) {
const formatInfo = await this._requestFormattedContent();
this._formattedMap = formatInfo.map;
- this.setContent(formatInfo.content);
+ this.setContent(formatInfo.content, null);
this._prettyCleanGeneration = this._textEditor.markClean();
const start = this._rawToPrettyLocation(selection.startLine, selection.startColumn);
const end = this._rawToPrettyLocation(selection.endLine, selection.endColumn);
newSelection = new TextUtils.TextRange(start[0], start[1], end[0], end[1]);
} else {
- this.setContent(this._rawContent);
+ this.setContent(this._rawContent, null);
this._cleanGeneration = this._textEditor.markClean();
const start = this._prettyToRawLocation(selection.startLine, selection.startColumn);
const end = this._prettyToRawLocation(selection.endLine, selection.endColumn);
@@ -172,10 +176,12 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
if (this._pretty) {
this._textEditor.setLineNumberFormatter(lineNumber => {
const line = this._prettyToRawLocation(lineNumber - 1, 0)[0] + 1;
- if (lineNumber === 1)
+ if (lineNumber === 1) {
return String(line);
- if (line !== this._prettyToRawLocation(lineNumber - 2, 0)[0] + 1)
+ }
+ if (line !== this._prettyToRawLocation(lineNumber - 2, 0)[0] + 1) {
return String(line);
+ }
return '-';
});
} else {
@@ -199,8 +205,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {!Array<number>}
*/
_prettyToRawLocation(line, column) {
- if (!this._formattedMap)
+ if (!this._formattedMap) {
return [line, column];
+ }
return this._formattedMap.formattedToOriginal(line, column);
}
@@ -210,8 +217,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {!Array<number>}
*/
_rawToPrettyLocation(line, column) {
- if (!this._formattedMap)
+ if (!this._formattedMap) {
return [line, column];
+ }
return this._formattedMap.originalToFormatted(line, column);
}
@@ -221,8 +229,16 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
*/
setEditable(editable) {
this._editable = editable;
- if (this._loaded)
+ if (this._loaded) {
this._textEditor.setReadOnly(!editable);
+ }
+ }
+
+ /**
+ * @return {boolean}
+ */
+ hasLoadError() {
+ return this._loadError;
}
/**
@@ -268,15 +284,33 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
async _ensureContentLoaded() {
if (!this._contentRequested) {
this._contentRequested = true;
- const content = await this._lazyContent();
- this._rawContent = content || '';
+ const {content, error} = (await this._lazyContent());
+ this._rawContent = error || content || '';
this._formattedContentPromise = null;
this._formattedMap = null;
this._prettyToggle.setEnabled(true);
- if (this._shouldAutoPrettyPrint && TextUtils.isMinified(content))
- await this._setPretty(true);
- else
- this.setContent(this._rawContent);
+
+ if (error) {
+ this.setContent(null, error);
+ this._prettyToggle.setEnabled(false);
+
+ // Occasionally on load, there can be a race in which it appears the CodeMirror plugin
+ // runs the highlighter type assignment out of order. In case of an error then, set
+ // the highlighter type after a short delay. This appears to only occur the first
+ // time that CodeMirror is initialized, likely because the highlighter type was first
+ // initialized based on the file type, and the syntax highlighting is in a race
+ // with the new highlighter assignment. As the option is just an option and is not
+ // observable, we can't handle waiting for it here.
+ // https://github.com/codemirror/CodeMirror/issues/6019
+ // CRBug 1011445
+ setTimeout(() => this.setHighlighterType('text/plain'), 50);
+ } else {
+ if (this._shouldAutoPrettyPrint && TextUtils.isMinified(content || '')) {
+ await this._setPretty(true);
+ } else {
+ this.setContent(this._rawContent, null);
+ }
+ }
}
}
@@ -284,8 +318,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {!Promise<{content: string, map: !Formatter.FormatterSourceMapping}>}
*/
_requestFormattedContent() {
- if (this._formattedContentPromise)
+ if (this._formattedContentPromise) {
return this._formattedContentPromise;
+ }
let fulfill;
this._formattedContentPromise = new Promise(x => fulfill = x);
new Formatter.ScriptFormatter(this._highlighterType, this._rawContent || '', (content, map) => {
@@ -307,11 +342,13 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
}
_innerRevealPositionIfNeeded() {
- if (!this._positionToReveal)
+ if (!this._positionToReveal) {
return;
+ }
- if (!this.loaded || !this.isShowing())
+ if (!this.loaded || !this.isShowing()) {
return;
+ }
const [line, column] =
this._transformer.rawToEditorLocation(this._positionToReveal.line, this._positionToReveal.column);
@@ -378,12 +415,14 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
onTextChanged(oldRange, newRange) {
const wasPretty = this.pretty;
this._pretty = this._prettyCleanGeneration !== null && this.textEditor.isClean(this._prettyCleanGeneration);
- if (this._pretty !== wasPretty)
+ if (this._pretty !== wasPretty) {
this._updatePrettyPrintState();
+ }
this._prettyToggle.setEnabled(this.isClean());
- if (this._searchConfig && this._searchableView)
+ if (this._searchConfig && this._searchableView) {
this.performSearch(this._searchConfig, false, false);
+ }
}
/**
@@ -413,13 +452,23 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @return {string}
*/
_simplifyMimeType(content, mimeType) {
- if (!mimeType)
+ if (!mimeType) {
return '';
- if (mimeType.indexOf('javascript') >= 0 || mimeType.indexOf('jscript') >= 0 || mimeType.indexOf('ecmascript') >= 0)
- return 'text/javascript';
+ }
+ // There are plenty of instances where TSX/JSX files are served with out the trailing x, i.e. JSX with a 'js' suffix
+ // which breaks the formatting. Therefore, if the mime type is TypeScript or JavaScript, we switch to the TSX/JSX
+ // superset so that we don't break formatting.
+ if (mimeType.indexOf('typescript') >= 0) {
+ return 'text/typescript-jsx';
+ }
+ if (mimeType.indexOf('javascript') >= 0 || mimeType.indexOf('jscript') >= 0 ||
+ mimeType.indexOf('ecmascript') >= 0) {
+ return 'text/jsx';
+ }
// A hack around the fact that files with "php" extension might be either standalone or html embedded php scripts.
- if (mimeType === 'text/x-php' && content.match(/\<\?.*\?\>/g))
+ if (mimeType === 'text/x-php' && content.match(/\<\?.*\?\>/g)) {
return 'application/x-httpd-php';
+ }
return mimeType;
}
@@ -448,14 +497,23 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
/**
* @param {?string} content
+ * @param {?string} loadError
*/
- setContent(content) {
+ setContent(content, loadError) {
this._muteChangeEventsForSetContent = true;
if (!this._loaded) {
this._loaded = true;
- this._textEditor.setText(content || '');
- this._cleanGeneration = this._textEditor.markClean();
- this._textEditor.setReadOnly(!this._editable);
+ if (!loadError) {
+ this._textEditor.setText(content || '');
+ this._cleanGeneration = this._textEditor.markClean();
+ this._textEditor.setReadOnly(!this._editable);
+ this._loadError = false;
+ } else {
+ this._textEditor.setText(loadError || '');
+ this._highlighterType = 'text/plain';
+ this._textEditor.setReadOnly(true);
+ this._loadError = true;
+ }
} else {
const scrollTop = this._textEditor.scrollTop();
const selection = this._textEditor.selection();
@@ -494,17 +552,19 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
this._searchRegex = regex;
this._searchResults = this._collectRegexMatches(regex);
- if (this._searchableView)
+ if (this._searchableView) {
this._searchableView.updateSearchMatchesCount(this._searchResults.length);
+ }
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
this._textEditor.cancelSearchResultsHighlight();
- else if (shouldJump && jumpBackwards)
+ } else if (shouldJump && jumpBackwards) {
this.jumpToPreviousSearchResult();
- else if (shouldJump)
+ } else if (shouldJump) {
this.jumpToNextSearchResult();
- else
+ } else {
this._textEditor.highlightSearchResults(regex, null);
+ }
}
/**
@@ -514,25 +574,29 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
* @param {boolean=} jumpBackwards
*/
performSearch(searchConfig, shouldJump, jumpBackwards) {
- if (this._searchableView)
+ if (this._searchableView) {
this._searchableView.updateSearchMatchesCount(0);
+ }
this._resetSearch();
this._searchConfig = searchConfig;
- if (this.loaded)
+ if (this.loaded) {
this._doFindSearchMatches(searchConfig, shouldJump, !!jumpBackwards);
- else
+ } else {
this._delayedFindSearchMatches = this._doFindSearchMatches.bind(this, searchConfig, shouldJump, !!jumpBackwards);
+ }
this._ensureContentLoaded();
}
_resetCurrentSearchResultIndex() {
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
+ }
this._currentSearchResultIndex = -1;
- if (this._searchableView)
+ if (this._searchableView) {
this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIndex);
+ }
this._textEditor.highlightSearchResults(/** @type {!RegExp} */ (this._searchRegex), null);
}
@@ -550,11 +614,13 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
searchCanceled() {
const range = this._currentSearchResultIndex !== -1 ? this._searchResults[this._currentSearchResultIndex] : null;
this._resetSearch();
- if (!this.loaded)
+ if (!this.loaded) {
return;
+ }
this._textEditor.cancelSearchResultsHighlight();
- if (range)
+ if (range) {
this.setSelection(range);
+ }
}
jumpToLastSearchResult() {
@@ -602,11 +668,13 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
}
jumpToSearchResult(index) {
- if (!this.loaded || !this._searchResults.length)
+ if (!this.loaded || !this._searchResults.length) {
return;
+ }
this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
- if (this._searchableView)
+ if (this._searchableView) {
this._searchableView.updateCurrentMatchIndex(this._currentSearchResultIndex);
+ }
this._textEditor.highlightSearchResults(
/** @type {!RegExp} */ (this._searchRegex), this._searchResults[this._currentSearchResultIndex]);
}
@@ -618,8 +686,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
*/
replaceSelectionWith(searchConfig, replacement) {
const range = this._searchResults[this._currentSearchResultIndex];
- if (!range)
+ if (!range) {
return;
+ }
this._textEditor.highlightSearchResults(/** @type {!RegExp} */ (this._searchRegex), null);
const oldText = this._textEditor.text(range);
@@ -658,8 +727,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
}
const ranges = this._collectRegexMatches(regex);
- if (!ranges.length)
+ if (!ranges.length) {
return;
+ }
// Calculate the position of the end of the last range to be edited.
const currentRangeIndex = ranges.lowerBound(this._textEditor.selection(), TextUtils.TextRange.comparator);
@@ -689,8 +759,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
match = regexObject.exec(line);
if (match) {
const matchEndIndex = match.index + Math.max(match[0].length, 1);
- if (match[0].length)
+ if (match[0].length) {
ranges.push(new TextUtils.TextRange(i, offset + match.index, i, offset + matchEndIndex));
+ }
offset += matchEndIndex;
line = line.substring(matchEndIndex);
}
@@ -724,8 +795,9 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
_updateSourcePosition() {
const selections = this._textEditor.selections();
- if (!selections.length)
+ if (!selections.length) {
return;
+ }
if (selections.length > 1) {
this._sourcePosition.setText(Common.UIString('%d selection regions', selections.length));
return;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourcesTextEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourcesTextEditor.js
index ec9551e9131..fb09994c998 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourcesTextEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourcesTextEditor.js
@@ -16,8 +16,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
bracketMatchingSetting: Common.moduleSetting('textEditorBracketMatching'),
padBottom: true
};
- if (codeMirrorOptions)
+ if (codeMirrorOptions) {
Object.assign(defaultCodeMirrorOptions, codeMirrorOptions);
+ }
super(defaultCodeMirrorOptions);
@@ -46,7 +47,7 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
this._tokenHighlighter = new SourceFrame.SourcesTextEditor.TokenHighlighter(this, this.codeMirror());
/** @type {!Array<string>} */
- this._gutters = ['CodeMirror-linenumbers'];
+ this._gutters = [SourceFrame.SourcesTextEditor.lineNumbersGutterType];
this.codeMirror().setOption('gutters', this._gutters.slice());
this.codeMirror().setOption('electricChars', false);
@@ -95,32 +96,39 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
const indents = {};
for (let lineNumber = 0; lineNumber < lines.length; ++lineNumber) {
const text = lines[lineNumber];
- if (text.length === 0 || !TextUtils.TextUtils.isSpaceChar(text[0]))
+ if (text.length === 0 || !TextUtils.TextUtils.isSpaceChar(text[0])) {
continue;
+ }
if (tabRegex.test(text)) {
++tabLines;
continue;
}
let i = 0;
- while (i < text.length && TextUtils.TextUtils.isSpaceChar(text[i]))
+ while (i < text.length && TextUtils.TextUtils.isSpaceChar(text[i])) {
++i;
- if (i % 2 !== 0)
+ }
+ if (i % 2 !== 0) {
continue;
+ }
indents[i] = 1 + (indents[i] || 0);
}
const linesCountPerIndentThreshold = 3 * lines.length / 100;
- if (tabLines && tabLines > linesCountPerIndentThreshold)
+ if (tabLines && tabLines > linesCountPerIndentThreshold) {
return '\t';
+ }
let minimumIndent = Infinity;
for (const i in indents) {
- if (indents[i] < linesCountPerIndentThreshold)
+ if (indents[i] < linesCountPerIndentThreshold) {
continue;
+ }
const indent = parseInt(i, 10);
- if (minimumIndent > indent)
+ if (minimumIndent > indent) {
minimumIndent = indent;
+ }
}
- if (minimumIndent === Infinity)
+ if (minimumIndent === Infinity) {
return Common.moduleSetting('textEditorIndent').get();
+ }
return ' '.repeat(minimumIndent);
}
@@ -151,16 +159,18 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
function innerHighlightRegex() {
if (range) {
this.scrollLineIntoView(range.startLine);
- if (range.endColumn > TextEditor.CodeMirrorTextEditor.maxHighlightLength)
+ if (range.endColumn > TextEditor.CodeMirrorTextEditor.maxHighlightLength) {
this.setSelection(range);
- else
+ } else {
this.setSelection(TextUtils.TextRange.createFromLocation(range.startLine, range.startColumn));
+ }
}
this._tokenHighlighter.highlightSearchResults(regex, range);
}
- if (!this._selectionBeforeSearch)
+ if (!this._selectionBeforeSearch) {
this._selectionBeforeSearch = this.selection();
+ }
this.codeMirror().operation(innerHighlightRegex.bind(this));
}
@@ -199,13 +209,15 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
* @param {boolean} leftToNumbers
*/
installGutter(type, leftToNumbers) {
- if (this._gutters.indexOf(type) !== -1)
+ if (this._gutters.indexOf(type) !== -1) {
return;
+ }
- if (leftToNumbers)
+ if (leftToNumbers) {
this._gutters.unshift(type);
- else
+ } else {
this._gutters.push(type);
+ }
this.codeMirror().setOption('gutters', this._gutters.slice());
this.refresh();
@@ -216,8 +228,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
*/
uninstallGutter(type) {
const index = this._gutters.indexOf(type);
- if (index === -1)
+ if (index === -1) {
return;
+ }
this.codeMirror().clearGutter(type);
this._gutters.splice(index, 1);
this.codeMirror().setOption('gutters', this._gutters.slice());
@@ -242,8 +255,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
this.clearPositionHighlight();
this._executionLine = this.codeMirror().getLineHandle(lineNumber);
- if (!this._executionLine)
+ if (!this._executionLine) {
return;
+ }
this.showExecutionLineBackground();
this.codeMirror().addLineClass(this._executionLine, 'wrap', 'cm-execution-line-outline');
@@ -251,28 +265,32 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
if (token && !token.type && token.startColumn + 1 === token.endColumn) {
const tokenContent = this.codeMirror().getLine(lineNumber)[token.startColumn];
- if (tokenContent === '.' || tokenContent === '(')
+ if (tokenContent === '.' || tokenContent === '(') {
token = this.tokenAtTextPosition(lineNumber, token.endColumn + 1);
+ }
}
let endColumn;
- if (token && token.type)
+ if (token && token.type) {
endColumn = token.endColumn;
- else
+ } else {
endColumn = this.codeMirror().getLine(lineNumber).length;
+ }
this._executionLineTailMarker = this.codeMirror().markText(
{line: lineNumber, ch: columnNumber}, {line: lineNumber, ch: endColumn}, {className: 'cm-execution-line-tail'});
}
showExecutionLineBackground() {
- if (this._executionLine)
+ if (this._executionLine) {
this.codeMirror().addLineClass(this._executionLine, 'wrap', 'cm-execution-line');
+ }
}
hideExecutionLineBackground() {
- if (this._executionLine)
+ if (this._executionLine) {
this.codeMirror().removeLineClass(this._executionLine, 'wrap', 'cm-execution-line');
+ }
}
clearExecutionLine() {
@@ -284,8 +302,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
}
delete this._executionLine;
- if (this._executionLineTailMarker)
+ if (this._executionLineTailMarker) {
this._executionLineTailMarker.clear();
+ }
delete this._executionLineTailMarker;
}
@@ -295,12 +314,14 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
* @param {boolean} toggled
*/
toggleLineClass(lineNumber, className, toggled) {
- if (this.hasLineClass(lineNumber, className) === toggled)
+ if (this.hasLineClass(lineNumber, className) === toggled) {
return;
+ }
const lineHandle = this.codeMirror().getLineHandle(lineNumber);
- if (!lineHandle)
+ if (!lineHandle) {
return;
+ }
if (toggled) {
this.codeMirror().addLineClass(lineHandle, 'gutter', className);
@@ -323,11 +344,8 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
return classNames.indexOf(className) !== -1;
}
- _gutterClick(instance, lineNumber, gutter, event) {
- if (gutter !== 'CodeMirror-linenumbers')
- return;
- this.dispatchEventToListeners(
- SourceFrame.SourcesTextEditor.Events.GutterClick, {lineNumber: lineNumber, event: event});
+ _gutterClick(instance, lineNumber, gutterType, event) {
+ this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.GutterClick, {gutterType, lineNumber, event});
}
_contextMenu(event) {
@@ -363,8 +381,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
*/
editRange(range, text, origin) {
const newRange = super.editRange(range, text, origin);
- if (Common.moduleSetting('textEditorAutoDetectIndent').get())
+ if (Common.moduleSetting('textEditorAutoDetectIndent').get()) {
this._onUpdateEditorIndentation();
+ }
return newRange;
}
@@ -380,8 +399,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
_setEditorIndentation(lines) {
const extraKeys = {};
let indent = Common.moduleSetting('textEditorIndent').get();
- if (Common.moduleSetting('textEditorAutoDetectIndent').get())
+ if (Common.moduleSetting('textEditorAutoDetectIndent').get()) {
indent = SourceFrame.SourcesTextEditor._guessIndentationLevel(lines);
+ }
if (indent === TextUtils.TextUtils.Indent.TabCharacter) {
this.codeMirror().setOption('indentWithTabs', true);
@@ -390,8 +410,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
this.codeMirror().setOption('indentWithTabs', false);
this.codeMirror().setOption('indentUnit', indent.length);
extraKeys.Tab = function(codeMirror) {
- if (codeMirror.somethingSelected())
+ if (codeMirror.somethingSelected()) {
return CodeMirror.Pass;
+ }
const pos = codeMirror.getCursor('head');
codeMirror.replaceRange(indent.substring(pos.ch % indent.length), codeMirror.getCursor());
};
@@ -413,8 +434,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
for (let i = 0; i < this._autoAppendedSpaces.length; ++i) {
const position = this._autoAppendedSpaces[i].resolve();
- if (!position)
+ if (!position) {
continue;
+ }
const line = this.line(position.lineNumber);
if (line.length === position.columnNumber && TextUtils.TextUtils.lineIndent(line).length === line.length) {
this.codeMirror().replaceRange(
@@ -432,8 +454,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
}
_cursorActivity() {
- if (!this._isSearchActive())
+ if (!this._isSearchActive()) {
this.codeMirror().operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));
+ }
const start = this.codeMirror().getCursor('anchor');
const end = this.codeMirror().getCursor('head');
@@ -446,8 +469,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
* @param {?TextUtils.TextRange} to
*/
_reportJump(from, to) {
- if (from && to && from.equal(to))
+ if (from && to && from.equal(to)) {
return;
+ }
this.dispatchEventToListeners(SourceFrame.SourcesTextEditor.Events.JumpHappened, {from: from, to: to});
}
@@ -469,10 +493,12 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
* @param {{ranges: !Array.<{head: !CodeMirror.Pos, anchor: !CodeMirror.Pos}>}} selection
*/
_fireBeforeSelectionChanged(codeMirror, selection) {
- if (!this._isHandlingMouseDownEvent)
+ if (!this._isHandlingMouseDownEvent) {
return;
- if (!selection.ranges.length)
+ }
+ if (!selection.ranges.length) {
return;
+ }
const primarySelection = selection.ranges[0];
this._reportJump(
@@ -530,10 +556,11 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
const whitespaceMode = Common.moduleSetting('showWhitespacesInEditor').get();
this.element.classList.toggle('show-whitespaces', whitespaceMode === 'all');
- if (whitespaceMode === 'all')
+ if (whitespaceMode === 'all') {
return this._allWhitespaceOverlayMode(mimeType);
- else if (whitespaceMode === 'trailing')
+ } else if (whitespaceMode === 'trailing') {
return this._trailingWhitespaceOverlayMode(mimeType);
+ }
return mimeType;
}
@@ -547,8 +574,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
(CodeMirror.mimeModes[mimeType].name || CodeMirror.mimeModes[mimeType]) :
CodeMirror.mimeModes['text/plain'];
modeName += '+all-whitespaces';
- if (CodeMirror.modes[modeName])
+ if (CodeMirror.modes[modeName]) {
return modeName;
+ }
function modeConstructor(config, parserConfig) {
function nextToken(stream) {
@@ -561,8 +589,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
}
return 'whitespace whitespace-' + spaces;
}
- while (!stream.eol() && stream.peek() !== ' ')
+ while (!stream.eol() && stream.peek() !== ' ') {
stream.next();
+ }
return null;
}
const whitespaceMode = {token: nextToken};
@@ -581,16 +610,18 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
(CodeMirror.mimeModes[mimeType].name || CodeMirror.mimeModes[mimeType]) :
CodeMirror.mimeModes['text/plain'];
modeName += '+trailing-whitespaces';
- if (CodeMirror.modes[modeName])
+ if (CodeMirror.modes[modeName]) {
return modeName;
+ }
function modeConstructor(config, parserConfig) {
function nextToken(stream) {
- if (stream.match(/^\s+$/, true))
+ if (stream.match(/^\s+$/, true)) {
return true ? 'trailing-whitespace' : null;
- do
+ }
+ do {
stream.next();
- while (!stream.eol() && stream.peek() !== ' ');
+ } while (!stream.eol() && stream.peek() !== ' ');
return null;
}
const whitespaceMode = {token: nextToken};
@@ -602,8 +633,9 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
_setupWhitespaceHighlight() {
const doc = this.element.ownerDocument;
- if (doc._codeMirrorWhitespaceStyleInjected || !Common.moduleSetting('showWhitespacesInEditor').get())
+ if (doc._codeMirrorWhitespaceStyleInjected || !Common.moduleSetting('showWhitespacesInEditor').get()) {
return;
+ }
doc._codeMirrorWhitespaceStyleInjected = true;
const classBase = '.show-whitespaces .CodeMirror .cm-whitespace-';
const spaceChar = '·';
@@ -634,7 +666,7 @@ SourceFrame.SourcesTextEditor = class extends TextEditor.CodeMirrorTextEditor {
}
};
-/** @typedef {{lineNumber: number, event: !Event}} */
+/** @typedef {{gutterType: string, lineNumber: number, event: !Event}} */
SourceFrame.SourcesTextEditor.GutterClickEventData;
/** @enum {symbol} */
@@ -692,8 +724,9 @@ CodeMirror.commands.smartNewlineAndIndent = function(codeMirror) {
* @return {!Object|undefined}
*/
CodeMirror.commands.sourcesDismiss = function(codemirror) {
- if (codemirror.listSelections().length === 1 && codemirror._codeMirrorTextEditor._isSearchActive())
+ if (codemirror.listSelections().length === 1 && codemirror._codeMirrorTextEditor._isSearchActive()) {
return CodeMirror.Pass;
+ }
return CodeMirror.commands.dismiss(codemirror);
};
@@ -714,16 +747,18 @@ SourceFrame.SourcesTextEditor._BlockIndentController = {
const indent = TextUtils.TextUtils.lineIndent(line);
let indentToInsert = '\n' + indent + codeMirror._codeMirrorTextEditor.indent();
let isCollapsedBlock = false;
- if (selection.head.ch === 0)
+ if (selection.head.ch === 0) {
return CodeMirror.Pass;
+ }
if (line.substr(selection.head.ch - 1, 2) === '{}') {
indentToInsert += '\n' + indent;
isCollapsedBlock = true;
} else if (line.substr(selection.head.ch - 1, 1) !== '{') {
return CodeMirror.Pass;
}
- if (i > 0 && allSelectionsAreCollapsedBlocks !== isCollapsedBlock)
+ if (i > 0 && allSelectionsAreCollapsedBlocks !== isCollapsedBlock) {
return CodeMirror.Pass;
+ }
replacements.push(indentToInsert);
allSelectionsAreCollapsedBlocks = isCollapsedBlock;
}
@@ -748,15 +783,17 @@ SourceFrame.SourcesTextEditor._BlockIndentController = {
* @return {*}
*/
'\'}\'': function(codeMirror) {
- if (codeMirror.somethingSelected())
+ if (codeMirror.somethingSelected()) {
return CodeMirror.Pass;
+ }
let selections = codeMirror.listSelections();
let replacements = [];
for (let i = 0; i < selections.length; ++i) {
const selection = selections[i];
const line = codeMirror.getLine(selection.head.line);
- if (line !== TextUtils.TextUtils.lineIndent(line))
+ if (line !== TextUtils.TextUtils.lineIndent(line)) {
return CodeMirror.Pass;
+ }
replacements.push('}');
}
codeMirror.replaceSelections(replacements);
@@ -766,8 +803,9 @@ SourceFrame.SourcesTextEditor._BlockIndentController = {
for (let i = 0; i < selections.length; ++i) {
const selection = selections[i];
const matchingBracket = codeMirror.findMatchingBracket(selection.head);
- if (!matchingBracket || !matchingBracket.match)
+ if (!matchingBracket || !matchingBracket.match) {
return;
+ }
updatedSelections.push({head: selection.head, anchor: new CodeMirror.Pos(selection.head.line, 0)});
const line = codeMirror.getLine(matchingBracket.to.line);
const indent = TextUtils.TextUtils.lineIndent(line);
@@ -804,17 +842,20 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
this._searchResultMarker.clear();
delete this._searchResultMarker;
}
- if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
+ if (this._highlightDescriptor && this._highlightDescriptor.selectionStart) {
this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, 'wrap', 'cm-line-with-selection');
+ }
const selectionStart = this._highlightRange ?
new CodeMirror.Pos(this._highlightRange.startLine, this._highlightRange.startColumn) :
null;
- if (selectionStart)
+ if (selectionStart) {
this._codeMirror.addLineClass(selectionStart.line, 'wrap', 'cm-line-with-selection');
+ }
if (oldRegex && this._highlightRegex.toString() === oldRegex.toString()) {
// Do not re-add overlay mode if regex did not change for better performance.
- if (this._highlightDescriptor)
+ if (this._highlightDescriptor) {
this._highlightDescriptor.selectionStart = selectionStart;
+ }
} else {
this._removeHighlight();
this._setHighlighter(this._searchHighlighter.bind(this, this._highlightRegex), selectionStart);
@@ -835,22 +876,27 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
highlightSelectedTokens() {
delete this._highlightRegex;
delete this._highlightRange;
- if (this._highlightDescriptor && this._highlightDescriptor.selectionStart)
+ if (this._highlightDescriptor && this._highlightDescriptor.selectionStart) {
this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, 'wrap', 'cm-line-with-selection');
+ }
this._removeHighlight();
const selectionStart = this._codeMirror.getCursor('start');
const selectionEnd = this._codeMirror.getCursor('end');
- if (selectionStart.line !== selectionEnd.line)
+ if (selectionStart.line !== selectionEnd.line) {
return;
- if (selectionStart.ch === selectionEnd.ch)
+ }
+ if (selectionStart.ch === selectionEnd.ch) {
return;
+ }
const selections = this._codeMirror.getSelections();
- if (selections.length > 1)
+ if (selections.length > 1) {
return;
+ }
const selectedText = selections[0];
if (this._isWord(selectedText, selectionStart.line, selectionStart.ch, selectionEnd.ch)) {
- if (selectionStart)
+ if (selectionStart) {
this._codeMirror.addLineClass(selectionStart.line, 'wrap', 'cm-line-with-selection');
+ }
this._setHighlighter(this._tokenHighlighter.bind(this, selectedText, selectionStart), selectionStart);
}
}
@@ -880,12 +926,14 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
* @param {!CodeMirror.StringStream} stream
*/
_searchHighlighter(regex, stream) {
- if (stream.column() === 0)
+ if (stream.column() === 0) {
delete this._searchMatchLength;
+ }
if (this._searchMatchLength) {
if (this._searchMatchLength > 2) {
- for (let i = 0; i < this._searchMatchLength - 2; ++i)
+ for (let i = 0; i < this._searchMatchLength - 2; ++i) {
stream.next();
+ }
this._searchMatchLength = 1;
return 'search-highlight';
} else {
@@ -898,8 +946,9 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
if (match) {
stream.next();
const matchLength = match[0].length;
- if (matchLength === 1)
+ if (matchLength === 1) {
return 'search-highlight search-highlight-full';
+ }
this._searchMatchLength = matchLength;
return 'search-highlight search-highlight-start';
}
@@ -914,12 +963,13 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
*/
_tokenHighlighter(token, selectionStart, stream) {
const tokenFirstChar = token.charAt(0);
- if (stream.match(token) && (stream.eol() || !TextUtils.TextUtils.isWordChar(stream.peek())))
+ if (stream.match(token) && (stream.eol() || !TextUtils.TextUtils.isWordChar(stream.peek()))) {
return stream.column() === selectionStart.ch ? 'token-highlight column-with-selection' : 'token-highlight';
+ }
let eatenChar;
- do
+ do {
eatenChar = stream.next();
- while (eatenChar && (TextUtils.TextUtils.isWordChar(eatenChar) || stream.peek() !== tokenFirstChar));
+ } while (eatenChar && (TextUtils.TextUtils.isWordChar(eatenChar) || stream.peek() !== tokenFirstChar));
}
/**
@@ -935,3 +985,4 @@ SourceFrame.SourcesTextEditor.TokenHighlighter = class {
SourceFrame.SourcesTextEditor.LinesToScanForIndentationGuessing = 1000;
SourceFrame.SourcesTextEditor.MaximumNumberOfWhitespacesPerSingleSpan = 16;
+SourceFrame.SourcesTextEditor.lineNumbersGutterType = 'CodeMirror-linenumbers';
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
index 75feb5c3b6d..f82d39f88ef 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/XMLView.js
@@ -55,8 +55,9 @@ SourceFrame.XMLView = class extends UI.Widget {
} catch (e) {
return null;
}
- if (parsedXML.body)
+ if (parsedXML.body) {
return null;
+ }
return parsedXML;
}
@@ -65,18 +66,21 @@ SourceFrame.XMLView = class extends UI.Widget {
* @param {boolean} shouldJump
*/
_jumpToMatch(index, shouldJump) {
- if (!this._searchConfig)
+ if (!this._searchConfig) {
return;
+ }
const regex = this._searchConfig.toSearchRegex(true);
const previousFocusElement = this._currentSearchTreeElements[this._currentSearchFocusIndex];
- if (previousFocusElement)
+ if (previousFocusElement) {
previousFocusElement.setSearchRegex(regex);
+ }
const newFocusElement = this._currentSearchTreeElements[index];
if (newFocusElement) {
this._updateSearchIndex(index);
- if (shouldJump)
+ if (shouldJump) {
newFocusElement.reveal(true);
+ }
newFocusElement.setSearchRegex(regex, UI.highlightedCurrentSearchResultClassName);
} else {
this._updateSearchIndex(0);
@@ -87,8 +91,9 @@ SourceFrame.XMLView = class extends UI.Widget {
* @param {number} count
*/
_updateSearchCount(count) {
- if (!this._searchableView)
+ if (!this._searchableView) {
return;
+ }
this._searchableView.updateSearchMatchesCount(count);
}
@@ -97,8 +102,9 @@ SourceFrame.XMLView = class extends UI.Widget {
*/
_updateSearchIndex(index) {
this._currentSearchFocusIndex = index;
- if (!this._searchableView)
+ if (!this._searchableView) {
return;
+ }
this._searchableView.updateCurrentMatchIndex(index);
}
@@ -107,8 +113,9 @@ SourceFrame.XMLView = class extends UI.Widget {
* @param {boolean=} jumpBackwards
*/
_innerPerformSearch(shouldJump, jumpBackwards) {
- if (!this._searchConfig)
+ if (!this._searchConfig) {
return;
+ }
let newIndex = this._currentSearchFocusIndex;
const previousSearchFocusElement = this._currentSearchTreeElements[newIndex];
this._innerSearchCanceled();
@@ -116,17 +123,20 @@ SourceFrame.XMLView = class extends UI.Widget {
const regex = this._searchConfig.toSearchRegex(true);
for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
- if (!(element instanceof SourceFrame.XMLView.Node))
+ if (!(element instanceof SourceFrame.XMLView.Node)) {
continue;
+ }
const hasMatch = element.setSearchRegex(regex);
- if (hasMatch)
+ if (hasMatch) {
this._currentSearchTreeElements.push(element);
+ }
if (previousSearchFocusElement === element) {
const currentIndex = this._currentSearchTreeElements.length - 1;
- if (hasMatch || jumpBackwards)
+ if (hasMatch || jumpBackwards) {
newIndex = currentIndex;
- else
+ } else {
newIndex = currentIndex + 1;
+ }
}
}
this._updateSearchCount(this._currentSearchTreeElements.length);
@@ -142,8 +152,9 @@ SourceFrame.XMLView = class extends UI.Widget {
_innerSearchCanceled() {
for (let element = this._treeOutline.rootElement(); element; element = element.traverseNextTreeElement(false)) {
- if (!(element instanceof SourceFrame.XMLView.Node))
+ if (!(element instanceof SourceFrame.XMLView.Node)) {
continue;
+ }
element.revertHighlightChanges();
}
this._updateSearchCount(0);
@@ -174,8 +185,9 @@ SourceFrame.XMLView = class extends UI.Widget {
* @override
*/
jumpToNextSearchResult() {
- if (!this._currentSearchTreeElements.length)
+ if (!this._currentSearchTreeElements.length) {
return;
+ }
const newIndex = mod(this._currentSearchFocusIndex + 1, this._currentSearchTreeElements.length);
this._jumpToMatch(newIndex, true);
@@ -185,8 +197,9 @@ SourceFrame.XMLView = class extends UI.Widget {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._currentSearchTreeElements.length)
+ if (!this._currentSearchTreeElements.length) {
return;
+ }
const newIndex = mod(this._currentSearchFocusIndex - 1, this._currentSearchTreeElements.length);
this._jumpToMatch(newIndex, true);
@@ -242,11 +255,13 @@ SourceFrame.XMLView.Node = class extends UI.TreeElement {
node = node.nextSibling;
const nodeType = currentNode.nodeType;
// ignore empty TEXT
- if (nodeType === 3 && currentNode.nodeValue.match(/\s+/))
+ if (nodeType === 3 && currentNode.nodeValue.match(/\s+/)) {
continue;
+ }
// ignore ATTRIBUTE, ENTITY_REFERENCE, ENTITY, DOCUMENT, DOCUMENT_TYPE, DOCUMENT_FRAGMENT, NOTATION
- if ((nodeType !== 1) && (nodeType !== 3) && (nodeType !== 4) && (nodeType !== 7) && (nodeType !== 8))
+ if ((nodeType !== 1) && (nodeType !== 3) && (nodeType !== 4) && (nodeType !== 7) && (nodeType !== 8)) {
continue;
+ }
root.appendChild(new SourceFrame.XMLView.Node(currentNode, false, xmlView));
}
}
@@ -258,14 +273,17 @@ SourceFrame.XMLView.Node = class extends UI.TreeElement {
*/
setSearchRegex(regex, additionalCssClassName) {
this.revertHighlightChanges();
- if (!regex)
+ if (!regex) {
return false;
- if (this._closeTag && this.parent && !this.parent.expanded)
+ }
+ if (this._closeTag && this.parent && !this.parent.expanded) {
return false;
+ }
regex.lastIndex = 0;
let cssClasses = UI.highlightedSearchResultClassName;
- if (additionalCssClassName)
+ if (additionalCssClassName) {
cssClasses += ' ' + additionalCssClassName;
+ }
const content = this.listItemElement.textContent.replace(/\xA0/g, ' ');
let match = regex.exec(content);
const ranges = [];
@@ -273,8 +291,9 @@ SourceFrame.XMLView.Node = class extends UI.TreeElement {
ranges.push(new TextUtils.SourceRange(match.index, match[0].length));
match = regex.exec(content);
}
- if (ranges.length)
+ if (ranges.length) {
UI.highlightRangesWithStyleClass(this.listItemElement, ranges, cssClasses, this._highlightChanges);
+ }
return !!this._highlightChanges.length;
}
@@ -297,7 +316,7 @@ SourceFrame.XMLView.Node = class extends UI.TreeElement {
for (let i = 0; i < attributes.length; ++i) {
const attributeNode = attributes.item(i);
titleItems.push(
- '\u00a0', 'shadow-xml-view-tag', attributeNode.name, 'shadow-xml-view-attribute-name', '="',
+ '\xA0', 'shadow-xml-view-tag', attributeNode.name, 'shadow-xml-view-attribute-name', '="',
'shadow-xml-view-tag', attributeNode.value, 'shadow-xml-view-attribute-value', '"',
'shadow-xml-view-tag');
}
@@ -338,8 +357,9 @@ SourceFrame.XMLView.Node = class extends UI.TreeElement {
*/
_setTitle(items) {
const titleFragment = createDocumentFragment();
- for (let i = 0; i < items.length; i += 2)
+ for (let i = 0; i < items.length; i += 2) {
titleFragment.createChild('span', items[i + 1]).textContent = items[i];
+ }
this.title = titleFragment;
this._xmlView._innerPerformSearch(false, false);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
index d6ec6d3bb26..a1ab4661563 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/source_frame_strings.grdp
@@ -3,9 +3,6 @@
<message name="IDS_DEVTOOLS_0818b6e40afc14684d727176bd222aa0" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
Set indentation to 2 spaces
</message>
- <message name="IDS_DEVTOOLS_194f5394ae2e9c74dc3c441b92862d1d" desc="Text in Font View of the Sources panel">
- Font
- </message>
<message name="IDS_DEVTOOLS_22a4f3a07431f171506336782f211c61" desc="Text that appears when user drag and drop something (for example, a file) in Image View of the Sources panel">
Drop image file here
</message>
@@ -15,12 +12,6 @@
<message name="IDS_DEVTOOLS_33443fc55632401a517b16878389f2f6" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
Set indentation to 4 spaces
</message>
- <message name="IDS_DEVTOOLS_4cfa6c981549e990fe2344e4c805405e" desc="Text in JSONView of the Sources panel">
- Find
- </message>
- <message name="IDS_DEVTOOLS_59cc7cb8dfb2491cc5dfe8ebc546d797" desc="Tooltip text that appears when hovering over largeicon pretty print button in Source Frame of the Sources panel">
- Pretty print
- </message>
<message name="IDS_DEVTOOLS_5ada9c9e1dad2e7e20aaa7688d7bd6c7" desc="Text in Source Frame of the Sources panel">
Line <ph name="LOCATION_______">$1s<ex>2</ex></ph>, Column <ph name="LOCATION_______">$2s<ex>2</ex></ph>
</message>
@@ -54,9 +45,6 @@
<message name="IDS_DEVTOOLS_af70cf4b9f56cd69eb56ae32f21e8416" desc="Text in Source Frame of the Sources panel">
<ph name="SELECTIONS_LENGTH">$1d<ex>2</ex></ph> selection regions
</message>
- <message name="IDS_DEVTOOLS_be53a0541a6d36f6ecb879fa2c584b08" desc="Text in Image View of the Sources panel">
- Image
- </message>
<message name="IDS_DEVTOOLS_c144a6b9ff31ca0302b1cf94d4d540a0" desc="Text in Source Frame of the Sources panel">
<ph name="TEXTRANGE_ENDLINE___TEXTRANGE_STARTLINE____">$1d<ex>2</ex></ph> lines, <ph name="SELECTEDTEXT_LENGTH">$2d<ex>2</ex></ph> characters selected
</message>
@@ -69,9 +57,6 @@
<message name="IDS_DEVTOOLS_fb49df2db96d183474fb9e954a9f0e52" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
Set indentation to tab character
</message>
- <message name="IDS_DEVTOOLS_fb61758d0f0fda4ba867c3d5a46c16a7" desc="A title of the 'Sources' setting category">
- Sources
- </message>
<message name="IDS_DEVTOOLS_fe81050cdc3adc7c1912fc08b7aec77f" desc="A drop-down menu option to set indentation to 4 spaces">
4 spaces
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js
index 8391a26a0bd..0e5128a8686 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js
@@ -23,20 +23,21 @@ Sources.BreakpointEditDialog = class extends UI.Widget {
const logpointPrefix = Sources.BreakpointEditDialog.LogpointPrefix;
const logpointSuffix = Sources.BreakpointEditDialog._LogpointSuffix;
this._isLogpoint = oldCondition.startsWith(logpointPrefix) && oldCondition.endsWith(logpointSuffix);
- if (this._isLogpoint)
+ if (this._isLogpoint) {
oldCondition = oldCondition.substring(logpointPrefix.length, oldCondition.length - logpointSuffix.length);
+ }
this._isLogpoint = this._isLogpoint || preferLogpoint;
this.element.classList.add('sources-edit-breakpoint-dialog');
const toolbar = new UI.Toolbar('source-frame-breakpoint-toolbar', this.contentElement);
toolbar.appendText(`Line ${editorLineNumber + 1}:`);
- this._typeSelector = new UI.ToolbarComboBox(this._onTypeChanged.bind(this));
- this._typeSelector.createOption(ls`Breakpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Breakpoint);
+ this._typeSelector = new UI.ToolbarComboBox(this._onTypeChanged.bind(this), ls`Breakpoint type`);
+ this._typeSelector.createOption(ls`Breakpoint`, Sources.BreakpointEditDialog.BreakpointType.Breakpoint);
const conditionalOption = this._typeSelector.createOption(
- ls`Conditional breakpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Conditional);
+ ls`Conditional breakpoint`, Sources.BreakpointEditDialog.BreakpointType.Conditional);
const logpointOption =
- this._typeSelector.createOption(ls`Logpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Logpoint);
+ this._typeSelector.createOption(ls`Logpoint`, Sources.BreakpointEditDialog.BreakpointType.Logpoint);
this._typeSelector.select(this._isLogpoint ? logpointOption : conditionalOption);
toolbar.appendToolbarItem(this._typeSelector);
@@ -46,15 +47,18 @@ Sources.BreakpointEditDialog = class extends UI.Widget {
this._updatePlaceholder();
this._editor.widget().element.classList.add('condition-editor');
this._editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor));
- if (oldCondition)
+ if (oldCondition) {
this._editor.setText(oldCondition);
+ }
+ this._editor.widget().markAsExternallyManaged();
this._editor.widget().show(this.contentElement);
this._editor.setSelection(this._editor.fullRange());
this._editor.widget().focus();
this._editor.widget().element.addEventListener('keydown', this._onKeyDown.bind(this), true);
this.contentElement.addEventListener('blur', event => {
- if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this.element))
+ if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this.element)) {
this._finishEditing(true);
+ }
}, true);
});
}
@@ -92,13 +96,15 @@ Sources.BreakpointEditDialog = class extends UI.Widget {
* @param {boolean} committed
*/
_finishEditing(committed) {
- if (this._finished)
+ if (this._finished) {
return;
+ }
this._finished = true;
this._editor.widget().detach();
let condition = this._editor.text();
- if (this._isLogpoint)
+ if (this._isLogpoint) {
condition = Sources.BreakpointEditDialog._conditionForLogpoint(condition);
+ }
this._onFinish({committed, condition});
}
@@ -109,13 +115,15 @@ Sources.BreakpointEditDialog = class extends UI.Widget {
if (isEnterKey(event) && !event.shiftKey) {
event.consume(true);
const expression = this._editor.text();
- if (event.ctrlKey || await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(expression))
+ if (event.ctrlKey || await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(expression)) {
this._finishEditing(true);
- else
+ } else {
this._editor.newlineAndIndent();
+ }
}
- if (isEscKey(event))
+ if (isEscKey(event)) {
this._finishEditing(false);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/CSSPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/CSSPlugin.js
index fea8b45c8cc..3dcbb65fc40 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/CSSPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/CSSPlugin.js
@@ -70,14 +70,18 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_registerShortcuts() {
const shortcutKeys = UI.ShortcutsScreen.SourcesPanelShortcuts;
- for (const descriptor of shortcutKeys.IncreaseCSSUnitByOne)
+ for (const descriptor of shortcutKeys.IncreaseCSSUnitByOne) {
this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, 1);
- for (const descriptor of shortcutKeys.DecreaseCSSUnitByOne)
+ }
+ for (const descriptor of shortcutKeys.DecreaseCSSUnitByOne) {
this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, -1);
- for (const descriptor of shortcutKeys.IncreaseCSSUnitByTen)
+ }
+ for (const descriptor of shortcutKeys.IncreaseCSSUnitByTen) {
this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, 10);
- for (const descriptor of shortcutKeys.DecreaseCSSUnitByTen)
+ }
+ for (const descriptor of shortcutKeys.DecreaseCSSUnitByTen) {
this._shortcuts[descriptor.key] = this._handleUnitModification.bind(this, -10);
+ }
}
/**
@@ -86,13 +90,15 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_handleKeyDown(event) {
const shortcutKey = UI.KeyboardShortcut.makeKeyFromEvent(/** @type {!KeyboardEvent} */ (event));
const handler = this._shortcuts[shortcutKey];
- if (handler && handler())
+ if (handler && handler()) {
event.consume(true);
+ }
}
_textEditorScrolled() {
- if (this._swatchPopoverHelper.isShowing())
+ if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
+ }
}
/**
@@ -102,8 +108,9 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_modifyUnit(unit, change) {
const unitValue = parseInt(unit, 10);
- if (isNaN(unitValue))
+ if (isNaN(unitValue)) {
return null;
+ }
const tail = unit.substring((unitValue).toString().length);
return String.sprintf('%d%s', unitValue + change, tail);
}
@@ -116,20 +123,24 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const selection = this._textEditor.selection().normalize();
let token = this._textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn);
if (!token) {
- if (selection.startColumn > 0)
+ if (selection.startColumn > 0) {
token = this._textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn - 1);
- if (!token)
+ }
+ if (!token) {
return false;
+ }
}
- if (token.type !== 'css-number')
+ if (token.type !== 'css-number') {
return false;
+ }
const cssUnitRange =
new TextUtils.TextRange(selection.startLine, token.startColumn, selection.startLine, token.endColumn);
const cssUnitText = this._textEditor.text(cssUnitRange);
const newUnitText = this._modifyUnit(cssUnitText, change);
- if (!newUnitText)
+ if (!newUnitText) {
return false;
+ }
this._textEditor.editRange(cssUnitRange, newUnitText);
selection.startColumn = token.startColumn;
selection.endColumn = selection.startColumn + newUnitText.length;
@@ -156,17 +167,20 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const results = TextUtils.TextUtils.splitStringByRegexes(line, regexes);
for (let i = 0; i < results.length; i++) {
const result = results[i];
- if (result.regexIndex === -1 || !handlers.has(regexes[result.regexIndex]))
+ if (result.regexIndex === -1 || !handlers.has(regexes[result.regexIndex])) {
continue;
+ }
const delimiters = /[\s:;,(){}]/;
const positionBefore = result.position - 1;
const positionAfter = result.position + result.value.length;
if (positionBefore >= 0 && !delimiters.test(line.charAt(positionBefore)) ||
- positionAfter < line.length && !delimiters.test(line.charAt(positionAfter)))
+ positionAfter < line.length && !delimiters.test(line.charAt(positionAfter))) {
continue;
+ }
const swatch = handlers.get(regexes[result.regexIndex])(result.value);
- if (!swatch)
+ if (!swatch) {
continue;
+ }
swatches.push(swatch);
swatchPositions.push(TextUtils.TextRange.createFromLocation(lineNumber, result.position));
}
@@ -196,8 +210,9 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_createColorSwatch(text) {
const color = Common.Color.parse(text);
- if (!color)
+ if (!color) {
return null;
+ }
const swatch = InlineEditor.ColorSwatch.create();
swatch.setColor(color);
swatch.iconElement().title = Common.UIString('Open color picker.');
@@ -211,8 +226,9 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @return {?InlineEditor.BezierSwatch}
*/
_createBezierSwatch(text) {
- if (!UI.Geometry.CubicBezier.parse(text))
+ if (!UI.Geometry.CubicBezier.parse(text)) {
return null;
+ }
const swatch = InlineEditor.BezierSwatch.create();
swatch.setBezierText(text);
swatch.iconElement().title = Common.UIString('Open cubic bezier editor.');
@@ -235,10 +251,11 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._editedSwatchTextRange.endColumn += swatch.textContent.length;
this._currentSwatch = swatch;
- if (swatch instanceof InlineEditor.ColorSwatch)
+ if (swatch instanceof InlineEditor.ColorSwatch) {
this._showSpectrum(swatch);
- else if (swatch instanceof InlineEditor.BezierSwatch)
+ } else if (swatch instanceof InlineEditor.BezierSwatch) {
this._showBezierEditor(swatch);
+ }
}
/**
@@ -267,8 +284,9 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_spectrumChanged(event) {
const colorString = /** @type {string} */ (event.data);
const color = Common.Color.parse(colorString);
- if (!color)
+ if (!color) {
return;
+ }
this._currentSwatch.setColor(color);
this._changeSwatchText(colorString);
}
@@ -314,16 +332,18 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_swatchPopoverHidden(commitEdit) {
this._muteSwatchProcessing = false;
- if (!commitEdit && this._hadSwatchChange)
+ if (!commitEdit && this._hadSwatchChange) {
this._textEditor.undo();
+ }
}
/**
* @param {!Common.Event} event
*/
_onTextChanged(event) {
- if (!this._muteSwatchProcessing)
+ if (!this._muteSwatchProcessing) {
this._updateSwatches(event.data.newRange.startLine, event.data.newRange.endLine);
+ }
}
/**
@@ -341,12 +361,14 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_cssSuggestions(prefixRange, substituteRange) {
const prefix = this._textEditor.text(prefixRange);
- if (prefix.startsWith('$'))
+ if (prefix.startsWith('$')) {
return null;
+ }
const propertyToken = this._backtrackPropertyToken(prefixRange.startLine, prefixRange.startColumn - 1);
- if (!propertyToken)
+ if (!propertyToken) {
return null;
+ }
const line = this._textEditor.line(prefixRange.startLine);
const tokenContent = line.substring(propertyToken.startColumn, propertyToken.endColumn);
@@ -367,18 +389,22 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
for (let i = 0; i < backtrackDepth && tokenPosition >= 0; ++i) {
const token = this._textEditor.tokenAtTextPosition(lineNumber, tokenPosition);
- if (!token)
+ if (!token) {
return null;
- if (token.type === 'css-property')
+ }
+ if (token.type === 'css-property') {
return seenColon ? token : null;
- if (token.type && !(token.type.indexOf('whitespace') !== -1 || token.type.startsWith('css-comment')))
+ }
+ if (token.type && !(token.type.indexOf('whitespace') !== -1 || token.type.startsWith('css-comment'))) {
return null;
+ }
if (!token.type && line.substring(token.startColumn, token.endColumn) === ':') {
- if (!seenColon)
+ if (!seenColon) {
seenColon = true;
- else
+ } else {
return null;
+ }
}
tokenPosition = token.startColumn - 1;
}
@@ -389,8 +415,9 @@ Sources.CSSPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @override
*/
dispose() {
- if (this._swatchPopoverHelper.isShowing())
+ if (this._swatchPopoverHelper.isShowing()) {
this._swatchPopoverHelper.hide(true);
+ }
this._textEditor.removeEventListener(
SourceFrame.SourcesTextEditor.Events.ScrollChanged, this._textEditorScrolled, this);
this._textEditor.removeEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js
index c0285a1c80b..e30fa8818a9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js
@@ -104,8 +104,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
let asyncStackTrace = details.asyncStackTrace;
if (!asyncStackTrace && details.asyncStackTraceId) {
- if (details.asyncStackTraceId.debuggerId)
+ if (details.asyncStackTraceId.debuggerId) {
debuggerModel = SDK.DebuggerModel.modelForDebuggerId(details.asyncStackTraceId.debuggerId);
+ }
asyncStackTrace = debuggerModel ? await debuggerModel.fetchAsyncStackTrace(details.asyncStackTraceId) : null;
}
let peviousStackTrace = details.callFrames;
@@ -129,8 +130,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
if (asyncStackTrace.parent) {
asyncStackTrace = asyncStackTrace.parent;
} else if (asyncStackTrace.parentId) {
- if (asyncStackTrace.parentId.debuggerId)
+ if (asyncStackTrace.parentId.debuggerId) {
debuggerModel = SDK.DebuggerModel.modelForDebuggerId(asyncStackTrace.parentId.debuggerId);
+ }
asyncStackTrace = debuggerModel ? await debuggerModel.fetchAsyncStackTrace(asyncStackTrace.parentId) : null;
} else {
asyncStackTrace = null;
@@ -138,8 +140,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
}
this._showMoreMessageElement.classList.toggle('hidden', !asyncStackTrace);
this._items.replaceAll(items);
- if (this._maxAsyncStackChainDepth === Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth)
+ if (this._maxAsyncStackChainDepth === Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth) {
this._list.selectNextItem(true /* canWrap */, false /* center */);
+ }
this._updatedForTest();
}
@@ -164,16 +167,18 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
this._muteActivateItem = true;
if (!this._showBlackboxed && this._items.every(item => item.isBlackboxed)) {
this._showBlackboxed = true;
- for (let i = 0; i < this._items.length; ++i)
+ for (let i = 0; i < this._items.length; ++i) {
this._list.refreshItemByIndex(i);
+ }
this._blackboxedMessageElement.classList.toggle('hidden', true);
} else {
const itemsSet = new Set(items);
let hasBlackboxed = false;
for (let i = 0; i < this._items.length; ++i) {
const item = this._items.at(i);
- if (itemsSet.has(item))
+ if (itemsSet.has(item)) {
this._list.refreshItemByIndex(i);
+ }
hasBlackboxed = hasBlackboxed || item.isBlackboxed;
}
this._blackboxedMessageElement.classList.toggle('hidden', this._showBlackboxed || !hasBlackboxed);
@@ -232,12 +237,15 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('selected');
- if (to)
+ }
+ if (to) {
this._activateItem(to);
+ }
}
/**
@@ -250,8 +258,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
showAllLink.textContent = Common.UIString('Show blackboxed frames');
showAllLink.addEventListener('click', () => {
this._showBlackboxed = true;
- for (const item of this._items)
+ for (const item of this._items) {
this._refreshItem(item);
+ }
this._blackboxedMessageElement.classList.toggle('hidden', true);
});
return element;
@@ -277,15 +286,18 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
*/
_onContextMenu(event) {
const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
- if (!item)
+ if (!item) {
return;
+ }
const contextMenu = new UI.ContextMenu(event);
const debuggerCallFrame = item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol];
- if (debuggerCallFrame)
+ if (debuggerCallFrame) {
contextMenu.defaultSection().appendItem(Common.UIString('Restart frame'), () => debuggerCallFrame.restart());
+ }
contextMenu.defaultSection().appendItem(Common.UIString('Copy stack trace'), this._copyStackTrace.bind(this));
- if (item.uiLocation)
+ if (item.uiLocation) {
this.appendBlackboxURLContextMenuItems(contextMenu, item.uiLocation.uiSourceCode);
+ }
contextMenu.show();
}
@@ -294,8 +306,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
*/
_onClick(event) {
const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
- if (item)
+ if (item) {
this._activateItem(item);
+ }
}
/**
@@ -303,8 +316,9 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
*/
_activateItem(item) {
const uiLocation = item.uiLocation;
- if (this._muteActivateItem || !uiLocation)
+ if (this._muteActivateItem || !uiLocation) {
return;
+ }
const debuggerCallFrame = item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol];
if (debuggerCallFrame && UI.context.flavor(SDK.DebuggerModel.CallFrame) !== debuggerCallFrame) {
debuggerCallFrame.debuggerModel.setSelectedCallFrame(debuggerCallFrame);
@@ -320,10 +334,12 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
*/
appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode) {
const binding = Persistence.persistence.binding(uiSourceCode);
- if (binding)
+ if (binding) {
uiSourceCode = binding.network;
- if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem)
+ }
+ if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) {
return;
+ }
const canBlackbox = Bindings.blackboxManager.canBlackboxUISourceCode(uiSourceCode);
const isBlackboxed = Bindings.blackboxManager.isBlackboxedUISourceCode(uiSourceCode);
const isContentScript = uiSourceCode.project().type() === Workspace.projectTypes.ContentScripts;
@@ -367,11 +383,12 @@ Sources.CallStackSidebarPane = class extends UI.SimpleView {
const text = [];
for (const item of this._items) {
let itemText = item.title;
- if (item.uiLocation)
+ if (item.uiLocation) {
itemText += ' (' + item.uiLocation.linkText(true /* skipTrim */) + ')';
+ }
text.push(itemText);
}
- InspectorFrontendHost.copyText(text.join('\n'));
+ Host.InspectorFrontendHost.copyText(text.join('\n'));
}
};
@@ -464,8 +481,9 @@ Sources.CallStackSidebarPane.Item = class {
items.add(item);
}
asyncHeaderItem.isBlackboxed = asyncHeaderItem[whiteboxedItemsSymbol].size === 0;
- if (shouldUpdate)
+ if (shouldUpdate) {
updateDelegate(asyncHeaderItem);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPausedMessage.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPausedMessage.js
index 282cdb98461..62126fafdb5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPausedMessage.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPausedMessage.js
@@ -9,6 +9,7 @@ Sources.DebuggerPausedMessage = class {
this._element = createElementWithClass('div', 'paused-message flex-none');
const root = UI.createShadowRootWithCoreStyles(this._element, 'sources/debuggerPausedMessage.css');
this._contentElement = root.createChild('div');
+ UI.ARIAUtils.markAsPoliteLiveRegion(this._element);
}
/**
@@ -34,11 +35,13 @@ Sources.DebuggerPausedMessage = class {
static async _createDOMBreakpointHitMessage(details) {
const messageWrapper = createElement('span');
const domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel);
- if (!details.auxData || !domDebuggerModel)
+ if (!details.auxData || !domDebuggerModel) {
return messageWrapper;
+ }
const data = domDebuggerModel.resolveDOMBreakpointData(/** @type {!Object} */ (details.auxData));
- if (!data)
+ if (!data) {
return messageWrapper;
+ }
const mainElement = messageWrapper.createChild('div', 'status-main');
mainElement.appendChild(UI.Icon.create('smallicon-info', 'status-icon'));
@@ -53,10 +56,11 @@ Sources.DebuggerPausedMessage = class {
const targetNodeLink = await Common.Linkifier.linkify(data.targetNode);
let messageElement;
if (data.insertion) {
- if (data.targetNode === data.node)
+ if (data.targetNode === data.node) {
messageElement = UI.formatLocalized('Child %s added', [targetNodeLink]);
- else
+ } else {
messageElement = UI.formatLocalized('Descendant %s added', [targetNodeLink]);
+ }
} else {
messageElement = UI.formatLocalized('Descendant %s removed', [targetNodeLink]);
}
@@ -75,8 +79,9 @@ Sources.DebuggerPausedMessage = class {
async render(details, debuggerWorkspaceBinding, breakpointManager) {
this._contentElement.removeChildren();
this._contentElement.hidden = !details;
- if (!details)
+ if (!details) {
return;
+ }
const status = this._contentElement.createChild('div', 'paused-status');
@@ -121,8 +126,9 @@ Sources.DebuggerPausedMessage = class {
}
status.classList.toggle('error-reason', errorLike);
- if (messageWrapper)
+ if (messageWrapper) {
status.appendChild(messageWrapper);
+ }
/**
* @param {string} mainText
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
index dd11ff7e059..3b31a7f86f2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
@@ -54,8 +54,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._scriptsPanel = Sources.SourcesPanel.instance();
this._breakpointManager = Bindings.breakpointManager;
- if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger)
+ if (uiSourceCode.project().type() === Workspace.projectTypes.Debugger) {
this._textEditor.element.classList.add('source-frame-debugger-script');
+ }
this._popoverHelper = new UI.PopoverHelper(this._scriptsPanel.element, this._getPopoverRequest.bind(this));
this._popoverHelper.setDisableOnClick(true);
@@ -75,8 +76,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._boundBlur = this._onBlur.bind(this);
this._textEditor.element.addEventListener('focusout', this._boundBlur, false);
this._boundWheel = event => {
- if (this._executionLocation && UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
+ if (this._executionLocation && UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
event.preventDefault();
+ }
};
this._textEditor.element.addEventListener('wheel', this._boundWheel, true);
@@ -130,12 +132,13 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._showBlackboxInfobarIfNeeded();
const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
- for (let i = 0; i < scriptFiles.length; ++i)
+ for (let i = 0; i < scriptFiles.length; ++i) {
scriptFiles[i].checkMapping();
+ }
this._hasLineWithoutMapping = false;
this._updateLinesWithoutMappingHighlight();
- if (!Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
+ if (!Root.Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
/** @type {?UI.Infobar} */
this._prettyPrintInfobar = null;
this._detectMinified();
@@ -153,16 +156,18 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_showBlackboxInfobarIfNeeded() {
const uiSourceCode = this._uiSourceCode;
- if (!uiSourceCode.contentType().hasScripts())
+ if (!uiSourceCode.contentType().hasScripts()) {
return;
+ }
const projectType = uiSourceCode.project().type();
if (!Bindings.blackboxManager.isBlackboxedUISourceCode(uiSourceCode)) {
this._hideBlackboxInfobar();
return;
}
- if (this._blackboxInfobar)
+ if (this._blackboxInfobar) {
this._blackboxInfobar.dispose();
+ }
const infobar = new UI.Infobar(UI.Infobar.Type.Warning, Common.UIString('This script is blackboxed in debugger'));
this._blackboxInfobar = infobar;
@@ -171,8 +176,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
Common.UIString('Debugger will skip stepping through this script, and will not stop on exceptions'));
const scriptFile = this._scriptFileForDebuggerModel.size ? this._scriptFileForDebuggerModel.valuesArray()[0] : null;
- if (scriptFile && scriptFile.hasSourceMapURL())
+ if (scriptFile && scriptFile.hasSourceMapURL()) {
infobar.createDetailsRowMessage(Common.UIString('Source map found, but ignored for blackboxed file.'));
+ }
infobar.createDetailsRowMessage();
infobar.createDetailsRowMessage(Common.UIString('Possible ways to cancel this behavior are:'));
@@ -184,15 +190,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
function unblackbox() {
Bindings.blackboxManager.unblackboxUISourceCode(uiSourceCode);
- if (projectType === Workspace.projectTypes.ContentScripts)
+ if (projectType === Workspace.projectTypes.ContentScripts) {
Bindings.blackboxManager.unblackboxContentScripts();
+ }
}
this._textEditor.attachInfobar(this._blackboxInfobar);
}
_hideBlackboxInfobar() {
- if (!this._blackboxInfobar)
+ if (!this._blackboxInfobar) {
return;
+ }
this._blackboxInfobar.dispose();
this._blackboxInfobar = null;
}
@@ -293,8 +301,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {string} url
*/
function addSourceMapURLDialogCallback(scriptFile, url) {
- if (!url)
+ if (!url) {
return;
+ }
scriptFile.addSourceMapURL(url);
}
@@ -318,13 +327,15 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
_workingCopyChanged() {
- if (this._scriptFileForDebuggerModel.size)
+ if (this._scriptFileForDebuggerModel.size) {
return;
+ }
- if (this._uiSourceCode.isDirty())
+ if (this._uiSourceCode.isDirty()) {
this._muteBreakpointsWhileEditing();
- else
+ } else {
this._restoreBreakpointsAfterEditing();
+ }
}
/**
@@ -332,8 +343,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_workingCopyCommitted(event) {
this._scriptsPanel.updateLastModificationTime();
- if (!this._scriptFileForDebuggerModel.size)
+ if (!this._scriptFileForDebuggerModel.size) {
this._restoreBreakpointsAfterEditing();
+ }
}
_didMergeToVM() {
@@ -345,18 +357,21 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
_muteBreakpointsWhileEditing() {
- if (this._muted)
+ if (this._muted) {
return;
- for (const decoration of this._breakpointDecorations)
+ }
+ for (const decoration of this._breakpointDecorations) {
this._updateBreakpointDecoration(decoration);
+ }
this._muted = true;
}
_restoreBreakpointsIfConsistentScripts() {
const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
for (let i = 0; i < scriptFiles.length; ++i) {
- if (scriptFiles[i].hasDivergedFromVM() || scriptFiles[i].isMergingToVM())
+ if (scriptFiles[i].hasDivergedFromVM() || scriptFiles[i].isMergingToVM()) {
return;
+ }
}
this._restoreBreakpointsAfterEditing();
@@ -373,13 +388,15 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._breakpointDecorations.clear();
this._textEditor.operation(() => decorations.map(decoration => decoration.hide()));
for (const decoration of decorations) {
- if (!decoration.breakpoint)
+ if (!decoration.breakpoint) {
continue;
+ }
const enabled = decoration.enabled;
decoration.breakpoint.remove();
const location = decoration.handle.resolve();
- if (location)
+ if (location) {
this._setBreakpoint(location.lineNumber, location.columnNumber, decoration.condition, enabled);
+ }
}
}
@@ -396,16 +413,19 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @return {?UI.PopoverRequest}
*/
_getPopoverRequest(event) {
- if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
+ if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
return null;
+ }
const target = UI.context.flavor(SDK.Target);
const debuggerModel = target ? target.model(SDK.DebuggerModel) : null;
- if (!debuggerModel || !debuggerModel.isPaused())
+ if (!debuggerModel || !debuggerModel.isPaused()) {
return null;
+ }
const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
- if (!textPosition)
+ if (!textPosition) {
return null;
+ }
const mouseLine = textPosition.startLine;
const mouseColumn = textPosition.startColumn;
@@ -415,10 +435,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
let startHighlight;
let endHighlight;
+ const selectedCallFrame =
+ /** @type {!SDK.DebuggerModel.CallFrame} */ (UI.context.flavor(SDK.DebuggerModel.CallFrame));
+ if (!selectedCallFrame) {
+ return null;
+ }
+
if (textSelection && !textSelection.isEmpty()) {
if (textSelection.startLine !== textSelection.endLine || textSelection.startLine !== mouseLine ||
- mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn)
+ mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn) {
return null;
+ }
const leftCorner =
this._textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn);
@@ -429,15 +456,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
endHighlight = textSelection.endColumn - 1;
} else {
const token = this._textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn);
- if (!token || !token.type)
+ if (!token || !token.type) {
return null;
+ }
editorLineNumber = textPosition.startLine;
const line = this._textEditor.line(editorLineNumber);
const tokenContent = line.substring(token.startColumn, token.endColumn);
const isIdentifier = this._isIdentifier(token.type);
- if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this'))
+ if (!isIdentifier && (token.type !== 'js-keyword' || tokenContent !== 'this')) {
return null;
+ }
const leftCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.startColumn);
const rightCorner = this._textEditor.cursorPositionToCoordinates(editorLineNumber, token.endColumn - 1);
@@ -447,10 +476,27 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
endHighlight = token.endColumn - 1;
while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.') {
const tokenBefore = this._textEditor.tokenAtTextPosition(editorLineNumber, startHighlight - 2);
- if (!tokenBefore || !tokenBefore.type)
+ if (!tokenBefore || !tokenBefore.type) {
return null;
- if (tokenBefore.type === 'js-meta')
+ }
+ if (tokenBefore.type === 'js-meta') {
break;
+ }
+ if (tokenBefore.type === 'js-string-2') {
+ // If we hit a template literal, find the opening ` in this line.
+ // TODO(bmeurer): We should eventually replace this tokenization
+ // approach with a proper soluation based on parsing, maybe reusing
+ // the Parser and AST inside V8 for this (or potentially relying on
+ // acorn to do the job).
+ if (tokenBefore.endColumn < 2) {
+ return null;
+ }
+ startHighlight = line.lastIndexOf('`', tokenBefore.endColumn - 2);
+ if (startHighlight < 0) {
+ return null;
+ }
+ break;
+ }
startHighlight = tokenBefore.startColumn;
}
}
@@ -461,13 +507,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
return {
box: anchorBox,
show: async popover => {
- const selectedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
- if (!selectedCallFrame)
- return false;
const evaluationText = this._textEditor.line(editorLineNumber).substring(startHighlight, endHighlight + 1);
const resolvedText = await Sources.SourceMapNamesResolver.resolveExpression(
- /** @type {!SDK.DebuggerModel.CallFrame} */ (selectedCallFrame), evaluationText, this._uiSourceCode,
- editorLineNumber, startHighlight, endHighlight);
+ selectedCallFrame, evaluationText, this._uiSourceCode, editorLineNumber, startHighlight, endHighlight);
const result = await selectedCallFrame.evaluate({
expression: resolvedText || evaluationText,
objectGroup: 'popover',
@@ -476,14 +518,16 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
returnByValue: false,
generatePreview: false
});
- if (!result.object)
+ if (!result.object || (result.object.type === 'object' && result.object.subtype === 'error')) {
return false;
+ }
objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(result.object, popover);
const potentiallyUpdatedCallFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
if (!objectPopoverHelper || selectedCallFrame !== potentiallyUpdatedCallFrame) {
debuggerModel.runtimeModel().releaseObjectGroup('popover');
- if (objectPopoverHelper)
+ if (objectPopoverHelper) {
objectPopoverHelper.dispose();
+ }
return false;
}
const highlightRange =
@@ -515,30 +559,34 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
if (UI.shortcutRegistry.eventMatchesAction(event, 'debugger.toggle-breakpoint')) {
const selection = this._textEditor.selection();
- if (!selection)
+ if (!selection) {
return;
+ }
this._toggleBreakpoint(selection.startLine, false);
event.consume(true);
return;
}
if (UI.shortcutRegistry.eventMatchesAction(event, 'debugger.toggle-breakpoint-enabled')) {
const selection = this._textEditor.selection();
- if (!selection)
+ if (!selection) {
return;
+ }
this._toggleBreakpoint(selection.startLine, true);
event.consume(true);
return;
}
if (UI.shortcutRegistry.eventMatchesAction(event, 'debugger.breakpoint-input-window')) {
const selection = this._textEditor.selection();
- if (!selection)
+ if (!selection) {
return;
+ }
const breakpoints = this._lineBreakpointDecorations(selection.startLine)
.map(decoration => decoration.breakpoint)
.filter(breakpoint => !!breakpoint);
let breakpoint;
- if (breakpoints.length)
+ if (breakpoints.length) {
breakpoint = breakpoints[0];
+ }
const isLogpoint =
breakpoint ? breakpoint.condition().includes(Sources.BreakpointEditDialog.LogpointPrefix) : false;
this._editBreakpointCondition(selection.startLine, breakpoint, null, isLogpoint);
@@ -550,8 +598,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._controlDown = true;
if (event.key === (Host.isMac() ? 'Meta' : 'Control')) {
this._controlTimeout = setTimeout(() => {
- if (this._executionLocation && this._controlDown)
+ if (this._executionLocation && this._controlDown) {
this._showContinueToLocations();
+ }
}, 150);
}
}
@@ -562,8 +611,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_onMouseMove(event) {
if (this._executionLocation && this._controlDown && UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
- if (!this._continueToLocationDecorations)
+ if (!this._continueToLocationDecorations) {
this._showContinueToLocations();
+ }
}
if (this._continueToLocationDecorations) {
const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
@@ -577,32 +627,39 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {boolean} hovered
*/
_setAsyncStepInHoveredLine(editorLineNumber, hovered) {
- if (this._asyncStepInHoveredLine === editorLineNumber && this._asyncStepInHovered === hovered)
+ if (this._asyncStepInHoveredLine === editorLineNumber && this._asyncStepInHovered === hovered) {
return;
- if (this._asyncStepInHovered && this._asyncStepInHoveredLine)
+ }
+ if (this._asyncStepInHovered && this._asyncStepInHoveredLine) {
this._textEditor.toggleLineClass(this._asyncStepInHoveredLine, 'source-frame-async-step-in-hovered', false);
+ }
this._asyncStepInHoveredLine = editorLineNumber;
this._asyncStepInHovered = hovered;
- if (this._asyncStepInHovered && this._asyncStepInHoveredLine)
+ if (this._asyncStepInHovered && this._asyncStepInHoveredLine) {
this._textEditor.toggleLineClass(this._asyncStepInHoveredLine, 'source-frame-async-step-in-hovered', true);
+ }
}
/**
* @param {!MouseEvent} event
*/
_onMouseDown(event) {
- if (!this._executionLocation || !UI.KeyboardShortcut.eventHasCtrlOrMeta(event))
+ if (!this._executionLocation || !UI.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
return;
- if (!this._continueToLocationDecorations)
+ }
+ if (!this._continueToLocationDecorations) {
return;
+ }
event.consume();
const textPosition = this._textEditor.coordinatesToCursorPosition(event.x, event.y);
- if (!textPosition)
+ if (!textPosition) {
return;
+ }
for (const decoration of this._continueToLocationDecorations.keys()) {
const range = decoration.find();
- if (range.from.line !== textPosition.startLine || range.to.line !== textPosition.startLine)
+ if (range.from.line !== textPosition.startLine || range.to.line !== textPosition.startLine) {
continue;
+ }
if (range.from.ch <= textPosition.startColumn && textPosition.startColumn <= range.to.ch) {
this._continueToLocationDecorations.get(decoration)();
break;
@@ -614,8 +671,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {!Event} event
*/
_onBlur(event) {
- if (this._textEditor.element.isAncestor(/** @type {!Node} */ (event.target)))
+ if (this._textEditor.element.isAncestor(/** @type {!Node} */ (event.target))) {
return;
+ }
this._clearControlDown();
}
@@ -644,16 +702,19 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const dialog = new Sources.BreakpointEditDialog(editorLineNumber, oldCondition, !!preferLogpoint, result => {
dialog.detach();
this._textEditor.removeDecoration(decorationElement, editorLineNumber);
- if (!result.committed)
+ if (!result.committed) {
return;
- if (breakpoint)
+ }
+ if (breakpoint) {
breakpoint.setCondition(result.condition);
- else if (location)
+ } else if (location) {
this._setBreakpoint(location.lineNumber, location.columnNumber, result.condition, true);
- else
+ } else {
this._createNewBreakpoint(editorLineNumber, result.condition, true);
+ }
});
this._textEditor.addDecoration(decorationElement, editorLineNumber);
+ dialog.markAsExternallyManaged();
dialog.show(decorationElement);
}
@@ -674,23 +735,27 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
if (this._textEditor.isShowing()) {
// We need SourcesTextEditor to be initialized prior to this call. @see crbug.com/506566
setImmediate(() => {
- if (this._controlDown)
+ if (this._controlDown) {
this._showContinueToLocations();
- else
+ } else {
this._generateValuesInSource();
+ }
});
}
}
_generateValuesInSource() {
- if (!Common.moduleSetting('inlineVariableValues').get())
+ if (!Common.moduleSetting('inlineVariableValues').get()) {
return;
+ }
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return;
+ }
const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
- if (!callFrame)
+ if (!callFrame) {
return;
+ }
const localScope = callFrame.localScope();
const functionLocation = callFrame.functionLocation();
@@ -704,11 +769,13 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_showContinueToLocations() {
this._popoverHelper.hidePopover();
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return;
+ }
const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
- if (!callFrame)
+ if (!callFrame) {
return;
+ }
const start = callFrame.functionLocation() || callFrame.location();
const debuggerModel = callFrame.debuggerModel;
debuggerModel.getPossibleBreakpoints(start, null, true)
@@ -728,30 +795,35 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
for (const location of locations) {
const editorLocation = this._transformer.rawToEditorLocation(location.lineNumber, location.columnNumber);
let token = this._textEditor.tokenAtTextPosition(editorLocation[0], editorLocation[1]);
- if (!token)
+ if (!token) {
continue;
+ }
const line = this._textEditor.line(editorLocation[0]);
let tokenContent = line.substring(token.startColumn, token.endColumn);
if (!token.type && tokenContent === '.') {
token = this._textEditor.tokenAtTextPosition(editorLocation[0], token.endColumn + 1);
tokenContent = line.substring(token.startColumn, token.endColumn);
}
- if (!token.type)
+ if (!token.type) {
continue;
+ }
const validKeyword = token.type === 'js-keyword' &&
(tokenContent === 'this' || tokenContent === 'return' || tokenContent === 'new' ||
tokenContent === 'continue' || tokenContent === 'break');
- if (!validKeyword && !this._isIdentifier(token.type))
+ if (!validKeyword && !this._isIdentifier(token.type)) {
continue;
- if (previousCallLine === editorLocation[0] && location.type !== Protocol.Debugger.BreakLocationType.Call)
+ }
+ if (previousCallLine === editorLocation[0] && location.type !== Protocol.Debugger.BreakLocationType.Call) {
continue;
+ }
let highlightRange =
new TextUtils.TextRange(editorLocation[0], token.startColumn, editorLocation[0], token.endColumn - 1);
let decoration = this._textEditor.highlightRange(highlightRange, 'source-frame-continue-to-location');
this._continueToLocationDecorations.set(decoration, location.continueToLocation.bind(location));
- if (location.type === Protocol.Debugger.BreakLocationType.Call)
+ if (location.type === Protocol.Debugger.BreakLocationType.Call) {
previousCallLine = editorLocation[0];
+ }
let isAsyncCall = (line[token.startColumn - 1] === '.' && tokenContent === 'then') ||
tokenContent === 'setTimeout' || tokenContent === 'setInterval' || tokenContent === 'postMessage';
@@ -798,42 +870,52 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
let position = line.indexOf('(', column);
const argumentsStart = position;
- if (position === -1)
+ if (position === -1) {
return null;
+ }
position++;
skipWhitespace();
- if (position >= line.length)
+ if (position >= line.length) {
return null;
+ }
nextToken();
- if (!token)
+ if (!token) {
return null;
+ }
from = token.startColumn;
if (token.type === 'js-keyword' && tokenText === 'async') {
skipWhitespace();
- if (position >= line.length)
+ if (position >= line.length) {
return {from: from, to: to};
+ }
nextToken();
- if (!token)
+ if (!token) {
return {from: from, to: to};
+ }
}
- if (token.type === 'js-keyword' && tokenText === 'function')
+ if (token.type === 'js-keyword' && tokenText === 'function') {
return {from: from, to: to};
+ }
- if (token.type === 'js-string')
+ if (token.type === 'js-string') {
return {from: argumentsStart, to: to};
+ }
- if (token.type && this._isIdentifier(token.type))
+ if (token.type && this._isIdentifier(token.type)) {
return {from: from, to: to};
+ }
- if (tokenText !== '(')
+ if (tokenText !== '(') {
return null;
+ }
const closeParen = line.indexOf(')', position);
- if (closeParen === -1 || line.substring(position, closeParen).indexOf('(') !== -1)
+ if (closeParen === -1 || line.substring(position, closeParen).indexOf('(') !== -1) {
return {from: from, to: to};
+ }
return {from: from, to: closeParen + 1};
function nextToken() {
@@ -866,10 +948,11 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {boolean} isCurrentPosition
*/
_asyncStepIn(location, isCurrentPosition) {
- if (!isCurrentPosition)
+ if (!isCurrentPosition) {
location.continueToLocation(asyncStepIn);
- else
+ } else {
asyncStepIn();
+ }
function asyncStepIn() {
location.debuggerModel.scheduleStepIntoAsync();
@@ -883,15 +966,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_prepareScopeVariables(callFrame, allProperties) {
const properties = allProperties.properties;
this._clearValueWidgets();
- if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing())
+ if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing()) {
return;
+ }
const functionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(
/** @type {!SDK.DebuggerModel.Location} */ (callFrame.functionLocation()));
const executionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(callFrame.location());
if (!functionUILocation || !executionUILocation || functionUILocation.uiSourceCode !== this._uiSourceCode ||
- executionUILocation.uiSourceCode !== this._uiSourceCode)
+ executionUILocation.uiSourceCode !== this._uiSourceCode) {
return;
+ }
const functionEditorLocation =
this._transformer.rawToEditorLocation(functionUILocation.lineNumber, functionUILocation.columnNumber);
@@ -900,20 +985,23 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const fromLine = functionEditorLocation[0];
const fromColumn = functionEditorLocation[1];
const toLine = executionEditorLocation[0];
- if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount)
+ if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount) {
return;
+ }
const valuesMap = new Map();
- for (const property of properties)
+ for (const property of properties) {
valuesMap.set(property.name, property.value);
+ }
/** @type {!Map.<number, !Set<string>>} */
const namesPerLine = new Map();
let skipObjectProperty = false;
const tokenizer = new TextEditor.CodeMirrorUtils.TokenizerFactory().createTokenizer('text/javascript');
tokenizer(this._textEditor.line(fromLine).substring(fromColumn), processToken.bind(this, fromLine));
- for (let i = fromLine + 1; i < toLine; ++i)
+ for (let i = fromLine + 1; i < toLine; ++i) {
tokenizer(this._textEditor.line(i), processToken.bind(this, i));
+ }
/**
* @param {number} editorLineNumber
@@ -966,12 +1054,15 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
let renderedNameCount = 0;
for (const name of names) {
- if (renderedNameCount > 10)
+ if (renderedNameCount > 10) {
break;
- if (namesPerLine.get(i - 1) && namesPerLine.get(i - 1).has(name))
- continue; // Only render name once in the given continuous block.
- if (renderedNameCount)
+ }
+ if (namesPerLine.get(i - 1) && namesPerLine.get(i - 1).has(name)) {
+ continue;
+ } // Only render name once in the given continuous block.
+ if (renderedNameCount) {
widget.createTextChild(', ');
+ }
const nameValuePair = widget.createChild('span');
widget.__nameToToken.set(name, nameValuePair);
nameValuePair.createTextChild(name + ' = ');
@@ -1014,8 +1105,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_clearExecutionLine() {
this._textEditor.operation(() => {
- if (this._executionLocation)
+ if (this._executionLocation) {
this._textEditor.clearExecutionLine();
+ }
this._executionLocation = null;
if (this._clearValueWidgetsTimer) {
clearTimeout(this._clearValueWidgetsTimer);
@@ -1030,26 +1122,30 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
clearTimeout(this._clearValueWidgetsTimer);
this._clearValueWidgetsTimer = null;
this._textEditor.operation(() => {
- for (const line of this._valueWidgets.keys())
+ for (const line of this._valueWidgets.keys()) {
this._textEditor.removeDecoration(this._valueWidgets.get(line), line);
+ }
this._valueWidgets.clear();
});
}
_clearContinueToLocationsNoRestore() {
- if (!this._continueToLocationDecorations)
+ if (!this._continueToLocationDecorations) {
return;
+ }
this._textEditor.operation(() => {
- for (const decoration of this._continueToLocationDecorations.keys())
+ for (const decoration of this._continueToLocationDecorations.keys()) {
this._textEditor.removeHighlight(decoration);
+ }
this._continueToLocationDecorations = null;
this._setAsyncStepInHoveredLine(null, false);
});
}
_clearContinueToLocations() {
- if (!this._continueToLocationDecorations)
+ if (!this._continueToLocationDecorations) {
return;
+ }
this._textEditor.operation(() => {
this._textEditor.showExecutionLineBackground();
this._generateValuesInSource();
@@ -1074,10 +1170,12 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_breakpointDecoration(editorLineNumber, editorColumnNumber) {
for (const decoration of this._breakpointDecorations) {
const location = decoration.handle.resolve();
- if (!location)
+ if (!location) {
continue;
- if (location.lineNumber === editorLineNumber && location.columnNumber === editorColumnNumber)
+ }
+ if (location.lineNumber === editorLineNumber && location.columnNumber === editorColumnNumber) {
return decoration;
+ }
}
return null;
}
@@ -1097,13 +1195,15 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @this {Sources.DebuggerPlugin}
*/
function update() {
- if (!this._scheduledBreakpointDecorationUpdates)
+ if (!this._scheduledBreakpointDecorationUpdates) {
return;
+ }
const editorLineNumbers = new Set();
for (const decoration of this._scheduledBreakpointDecorationUpdates) {
const location = decoration.handle.resolve();
- if (!location)
+ if (!location) {
continue;
+ }
editorLineNumbers.add(location.lineNumber);
}
this._scheduledBreakpointDecorationUpdates = null;
@@ -1117,8 +1217,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
updateInlineDecorations.call(this, lineNumber, decorations);
}
- if (!waitingForInlineDecorations)
+ if (!waitingForInlineDecorations) {
this._breakpointDecorationsUpdatedForTest();
+ }
}
/**
@@ -1153,18 +1254,21 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
new TextUtils.TextRange(editorLineNumber, 0, editorLineNumber, lineEnd),
Sources.DebuggerPlugin.BreakpointDecoration.bookmarkSymbol);
for (const bookmark of bookmarks) {
- if (!actualBookmarks.has(bookmark))
+ if (!actualBookmarks.has(bookmark)) {
bookmark.clear();
+ }
}
- if (!decorations.length)
+ if (!decorations.length) {
return;
+ }
if (decorations.length > 1) {
for (const decoration of decorations) {
decoration.update();
- if (!this._muted)
+ if (!this._muted) {
decoration.show();
- else
+ } else {
decoration.hide();
+ }
}
} else {
decorations[0].update();
@@ -1183,14 +1287,16 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_inlineBreakpointClick(decoration, event) {
event.consume(true);
if (decoration.breakpoint) {
- if (event.shiftKey)
+ if (event.shiftKey) {
decoration.breakpoint.setEnabled(!decoration.breakpoint.enabled());
- else
+ } else {
decoration.breakpoint.remove();
+ }
} else {
const editorLocation = decoration.handle.resolve();
- if (!editorLocation)
+ if (!editorLocation) {
return;
+ }
const location = this._transformer.editorToRawLocation(editorLocation.lineNumber, editorLocation.columnNumber);
this._setBreakpoint(location[0], location[1], decoration.condition, true);
}
@@ -1203,8 +1309,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_inlineBreakpointContextMenu(decoration, event) {
event.consume(true);
const editorLocation = decoration.handle.resolve();
- if (!editorLocation)
+ if (!editorLocation) {
return;
+ }
const location = this._transformer.editorToRawLocation(editorLocation[0], editorLocation[1]);
const contextMenu = new UI.ContextMenu(event);
if (decoration.breakpoint) {
@@ -1231,14 +1338,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
_shouldIgnoreExternalBreakpointEvents(event) {
const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
- if (uiLocation.uiSourceCode !== this._uiSourceCode)
+ if (uiLocation.uiSourceCode !== this._uiSourceCode) {
return true;
- if (this._muted)
+ }
+ if (this._muted) {
return true;
+ }
const scriptFiles = this._scriptFileForDebuggerModel.valuesArray();
for (let i = 0; i < scriptFiles.length; ++i) {
- if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM())
+ if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM()) {
return true;
+ }
}
return false;
}
@@ -1247,8 +1357,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {!Common.Event} event
*/
_breakpointAdded(event) {
- if (this._shouldIgnoreExternalBreakpointEvents(event))
+ if (this._shouldIgnoreExternalBreakpointEvents(event)) {
return;
+ }
const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
const breakpoint = /** @type {!Bindings.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
this._addBreakpoint(uiLocation, breakpoint);
@@ -1294,22 +1405,26 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
function addInlineDecorations(editorLineNumber, possibleLocations) {
this._possibleBreakpointsRequested.delete(editorLineNumber);
const decorations = this._lineBreakpointDecorations(editorLineNumber);
- for (const decoration of decorations)
+ for (const decoration of decorations) {
this._updateBreakpointDecoration(decoration);
- if (!decorations.some(decoration => !!decoration.breakpoint))
+ }
+ if (!decorations.some(decoration => !!decoration.breakpoint)) {
return;
+ }
/** @type {!Set<number>} */
const columns = new Set();
for (const decoration of decorations) {
const editorLocation = decoration.handle.resolve();
- if (!editorLocation)
+ if (!editorLocation) {
continue;
+ }
columns.add(editorLocation.columnNumber);
}
for (const location of possibleLocations) {
const editorLocation = this._transformer.rawToEditorLocation(location.lineNumber, location.columnNumber);
- if (columns.has(editorLocation[1]))
+ if (columns.has(editorLocation[1])) {
continue;
+ }
const handle = this._textEditor.textEditorPositionHandle(editorLocation[0], editorLocation[1]);
const decoration = new Sources.DebuggerPlugin.BreakpointDecoration(this._textEditor, handle, '', false, null);
decoration.element.addEventListener('click', this._inlineBreakpointClick.bind(this, decoration), true);
@@ -1325,13 +1440,15 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {!Common.Event} event
*/
_breakpointRemoved(event) {
- if (this._shouldIgnoreExternalBreakpointEvents(event))
+ if (this._shouldIgnoreExternalBreakpointEvents(event)) {
return;
+ }
const uiLocation = /** @type {!Workspace.UILocation} */ (event.data.uiLocation);
const breakpoint = /** @type {!Bindings.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
const decoration = this._decorationByBreakpoint.get(breakpoint);
- if (!decoration)
+ if (!decoration) {
return;
+ }
this._decorationByBreakpoint.delete(breakpoint);
const editorLocation = this._transformer.rawToEditorLocation(uiLocation.lineNumber, uiLocation.columnNumber);
@@ -1351,29 +1468,34 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
_initializeBreakpoints() {
const breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode);
- for (const breakpointLocation of breakpointLocations)
+ for (const breakpointLocation of breakpointLocations) {
this._addBreakpoint(breakpointLocation.uiLocation, breakpointLocation.breakpoint);
+ }
}
_updateLinesWithoutMappingHighlight() {
const isSourceMapSource = !!Bindings.CompilerScriptMapping.uiSourceCodeOrigin(this._uiSourceCode);
- if (!isSourceMapSource)
+ if (!isSourceMapSource) {
return;
+ }
const linesCount = this._textEditor.linesCount;
for (let i = 0; i < linesCount; ++i) {
const lineHasMapping = Bindings.CompilerScriptMapping.uiLineHasMapping(this._uiSourceCode, i);
- if (!lineHasMapping)
+ if (!lineHasMapping) {
this._hasLineWithoutMapping = true;
- if (this._hasLineWithoutMapping)
+ }
+ if (this._hasLineWithoutMapping) {
this._textEditor.toggleLineClass(i, 'cm-line-without-source-mapping', !lineHasMapping);
+ }
}
}
_updateScriptFiles() {
for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)) {
const scriptFile = Bindings.debuggerWorkspaceBinding.scriptFile(this._uiSourceCode, debuggerModel);
- if (scriptFile)
+ if (scriptFile) {
this._updateScriptFile(debuggerModel);
+ }
}
}
@@ -1388,27 +1510,32 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
oldScriptFile.removeEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
oldScriptFile.removeEventListener(
Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
- if (this._muted && !this._uiSourceCode.isDirty())
+ if (this._muted && !this._uiSourceCode.isDirty()) {
this._restoreBreakpointsIfConsistentScripts();
+ }
}
- if (!newScriptFile)
+ if (!newScriptFile) {
return;
+ }
this._scriptFileForDebuggerModel.set(debuggerModel, newScriptFile);
newScriptFile.addEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
newScriptFile.addEventListener(Bindings.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
newScriptFile.checkMapping();
- if (newScriptFile.hasSourceMapURL())
+ if (newScriptFile.hasSourceMapURL()) {
this._showSourceMapInfobar();
+ }
}
_showSourceMapInfobar() {
- if (this._sourceMapInfobar)
+ if (this._sourceMapInfobar) {
return;
+ }
this._sourceMapInfobar = UI.Infobar.create(
UI.Infobar.Type.Info, Common.UIString('Source Map detected.'),
Common.settings.createSetting('sourceMapInfobarDisabled', false));
- if (!this._sourceMapInfobar)
+ if (!this._sourceMapInfobar) {
return;
+ }
this._sourceMapInfobar.createDetailsRowMessage(Common.UIString(
'Associated files should be added to the file tree. You can debug these resolved source files as regular JavaScript files.'));
this._sourceMapInfobar.createDetailsRowMessage(Common.UIString(
@@ -1419,15 +1546,17 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
_detectMinified() {
- const content = this._uiSourceCode.content();
- if (!content || !TextUtils.isMinified(content))
+ const {content} = this._uiSourceCode.content();
+ if (!content || !TextUtils.isMinified(content)) {
return;
+ }
this._prettyPrintInfobar = UI.Infobar.create(
UI.Infobar.Type.Info, Common.UIString('Pretty-print this minified file?'),
Common.settings.createSetting('prettyPrintInfobarDisabled', false));
- if (!this._prettyPrintInfobar)
+ if (!this._prettyPrintInfobar) {
return;
+ }
this._prettyPrintInfobar.setCloseCallback(() => this._prettyPrintInfobar = null);
const toolbar = new UI.Toolbar('');
@@ -1437,6 +1566,7 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
toolbar.element.style.verticalAlign = 'middle';
toolbar.element.style.marginBottom = '3px';
toolbar.element.style.pointerEvents = 'none';
+ toolbar.element.tabIndex = -1;
const element = this._prettyPrintInfobar.createDetailsRowMessage();
element.appendChild(UI.formatLocalized(
'You can click the %s button on the bottom status bar, and continue debugging with the new formatted source.',
@@ -1448,15 +1578,20 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {!Common.Event} event
*/
_handleGutterClick(event) {
- if (this._muted)
+ if (this._muted) {
return;
+ }
const eventData = /** @type {!SourceFrame.SourcesTextEditor.GutterClickEventData} */ (event.data);
+ if (eventData.gutterType !== SourceFrame.SourcesTextEditor.lineNumbersGutterType) {
+ return;
+ }
const editorLineNumber = eventData.lineNumber;
const eventObject = eventData.event;
- if (eventObject.button !== 0 || eventObject.altKey || eventObject.ctrlKey || eventObject.metaKey)
+ if (eventObject.button !== 0 || eventObject.altKey || eventObject.ctrlKey || eventObject.metaKey) {
return;
+ }
this._toggleBreakpoint(editorLineNumber, eventObject.shiftKey);
eventObject.consume(true);
@@ -1475,10 +1610,11 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const hasDisabled = this._textEditor.hasLineClass(editorLineNumber, 'cm-breakpoint-disabled');
const breakpoints = decorations.map(decoration => decoration.breakpoint).filter(breakpoint => !!breakpoint);
for (const breakpoint of breakpoints) {
- if (onlyDisable)
+ if (onlyDisable) {
breakpoint.setEnabled(hasDisabled);
- else
+ } else {
breakpoint.remove();
+ }
}
}
@@ -1508,12 +1644,14 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {boolean} onlyDisable
*/
toggleBreakpointOnCurrentLine(onlyDisable) {
- if (this._muted)
+ if (this._muted) {
return;
+ }
const selection = this._textEditor.selection();
- if (!selection)
+ if (!selection) {
return;
+ }
this._toggleBreakpoint(selection.startLine, onlyDisable);
}
@@ -1524,8 +1662,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {boolean} enabled
*/
_setBreakpoint(lineNumber, columnNumber, condition, enabled) {
- if (!Bindings.CompilerScriptMapping.uiLineHasMapping(this._uiSourceCode, lineNumber))
+ if (!Bindings.CompilerScriptMapping.uiLineHasMapping(this._uiSourceCode, lineNumber)) {
return;
+ }
Common.moduleSetting('breakpointsActive').set(true);
this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, columnNumber, condition, enabled);
@@ -1557,20 +1696,24 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @override
*/
dispose() {
- for (const decoration of this._breakpointDecorations)
+ for (const decoration of this._breakpointDecorations) {
decoration.dispose();
+ }
this._breakpointDecorations.clear();
if (this._scheduledBreakpointDecorationUpdates) {
- for (const decoration of this._scheduledBreakpointDecorationUpdates)
+ for (const decoration of this._scheduledBreakpointDecorationUpdates) {
decoration.dispose();
+ }
this._scheduledBreakpointDecorationUpdates.clear();
}
this._hideBlackboxInfobar();
- if (this._sourceMapInfobar)
+ if (this._sourceMapInfobar) {
this._sourceMapInfobar.dispose();
- if (this._prettyPrintInfobar)
+ }
+ if (this._prettyPrintInfobar) {
this._prettyPrintInfobar.dispose();
+ }
this._scriptsPanel.element.removeEventListener('scroll', this._boundPopoverHelperHide, true);
for (const script of this._scriptFileForDebuggerModel.values()) {
script.removeEventListener(Bindings.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
@@ -1640,27 +1783,32 @@ Sources.DebuggerPlugin.BreakpointDecoration = class {
* @return {number}
*/
static mostSpecificFirst(decoration1, decoration2) {
- if (decoration1.enabled !== decoration2.enabled)
+ if (decoration1.enabled !== decoration2.enabled) {
return decoration1.enabled ? -1 : 1;
- if (!!decoration1.condition !== !!decoration2.condition)
+ }
+ if (!!decoration1.condition !== !!decoration2.condition) {
return !!decoration1.condition ? -1 : 1;
+ }
return 0;
}
update() {
- if (!this.condition)
+ if (!this.condition) {
this.element.setIconType('smallicon-inline-breakpoint');
- else
+ } else {
this.element.setIconType('smallicon-inline-breakpoint-conditional');
+ }
this.element.classList.toggle('cm-inline-disabled', !this.enabled);
}
show() {
- if (this.bookmark)
+ if (this.bookmark) {
return;
+ }
const editorLocation = this.handle.resolve();
- if (!editorLocation)
+ if (!editorLocation) {
return;
+ }
this.bookmark = this._textEditor.addBookmark(
editorLocation.lineNumber, editorLocation.columnNumber, this.element,
Sources.DebuggerPlugin.BreakpointDecoration.bookmarkSymbol);
@@ -1668,8 +1816,9 @@ Sources.DebuggerPlugin.BreakpointDecoration = class {
}
hide() {
- if (!this.bookmark)
+ if (!this.bookmark) {
return;
+ }
this.bookmark.clear();
this.bookmark = null;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/EditingLocationHistoryManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/EditingLocationHistoryManager.js
index 7c282a367ce..3ee065a6857 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/EditingLocationHistoryManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/EditingLocationHistoryManager.js
@@ -54,10 +54,12 @@ Sources.EditingLocationHistoryManager = class {
* @param {!Common.Event} event
*/
_onJumpHappened(event) {
- if (event.data.from)
+ if (event.data.from) {
this._updateActiveState(event.data.from);
- if (event.data.to)
+ }
+ if (event.data.to) {
this._pushActiveState(event.data.to);
+ }
}
rollback() {
@@ -70,15 +72,17 @@ Sources.EditingLocationHistoryManager = class {
updateCurrentState() {
const sourceFrame = this._currentSourceFrameCallback();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
this._updateActiveState(sourceFrame.textEditor.selection());
}
pushNewState() {
const sourceFrame = this._currentSourceFrameCallback();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
this._pushActiveState(sourceFrame.textEditor.selection());
}
@@ -87,11 +91,13 @@ Sources.EditingLocationHistoryManager = class {
*/
_updateActiveState(selection) {
const active = this._historyManager.active();
- if (!active)
+ if (!active) {
return;
+ }
const sourceFrame = this._currentSourceFrameCallback();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
const entry = new Sources.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
active.merge(entry);
}
@@ -101,8 +107,9 @@ Sources.EditingLocationHistoryManager = class {
*/
_pushActiveState(selection) {
const sourceFrame = this._currentSourceFrameCallback();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
const entry = new Sources.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
this._historyManager.push(entry);
}
@@ -147,8 +154,9 @@ Sources.EditingLocationHistoryEntry = class {
* @param {!Sources.HistoryEntry} entry
*/
merge(entry) {
- if (this._projectId !== entry._projectId || this._url !== entry._url)
+ if (this._projectId !== entry._projectId || this._url !== entry._url) {
return;
+ }
this._positionHandle = entry._positionHandle;
}
@@ -176,8 +184,9 @@ Sources.EditingLocationHistoryEntry = class {
reveal() {
const position = this._positionHandle.resolve();
const uiSourceCode = Workspace.workspace.uiSourceCode(this._projectId, this._url);
- if (!position || !uiSourceCode)
+ if (!position || !uiSourceCode) {
return;
+ }
this._editingLocationManager.updateCurrentState();
this._sourcesView.showSourceLocation(uiSourceCode, position.lineNumber, position.columnNumber);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/FilePathScoreFunction.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/FilePathScoreFunction.js
index d9c3b8c32fa..769c7aa0f2d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/FilePathScoreFunction.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/FilePathScoreFunction.js
@@ -50,8 +50,9 @@ Sources.FilePathScoreFunction = class {
* @return {number}
*/
score(data, matchIndexes) {
- if (!data || !this._query)
+ if (!data || !this._query) {
return 0;
+ }
const n = this._query.length;
const m = data.length;
if (!this._score || this._score.length < n * m) {
@@ -77,8 +78,9 @@ Sources.FilePathScoreFunction = class {
}
}
}
- if (matchIndexes)
+ if (matchIndexes) {
this._restoreMatchIndexes(sequence, n, m, matchIndexes);
+ }
const maxDataLength = 256;
return score[n * m - 1] * maxDataLength + (maxDataLength - data.length);
}
@@ -89,8 +91,9 @@ Sources.FilePathScoreFunction = class {
* @return {boolean}
*/
_testWordStart(data, j) {
- if (j === 0)
+ if (j === 0) {
return true;
+ }
const prevChar = data.charAt(j - 1);
return prevChar === '_' || prevChar === '-' || prevChar === '/' ||
@@ -133,19 +136,25 @@ Sources.FilePathScoreFunction = class {
const isPathTokenStart = j === 0 || data[j - 1] === '/';
const isCapsMatch = query[i] === data[j] && query[i] === this._queryUpperCase[i];
let score = 10;
- if (isPathTokenStart)
+ if (isPathTokenStart) {
score += 4;
- if (isWordStart)
+ }
+ if (isWordStart) {
score += 2;
- if (isCapsMatch)
+ }
+ if (isCapsMatch) {
score += 6;
- if (isFileName)
+ }
+ if (isFileName) {
score += 4;
+ }
// promote the case of making the whole match in the filename
- if (j === this._fileNameIndex + 1 && i === 0)
+ if (j === this._fileNameIndex + 1 && i === 0) {
score += 5;
- if (isFileName && isWordStart)
+ }
+ if (isFileName && isWordStart) {
score += 3;
+ }
return score;
}
@@ -161,10 +170,12 @@ Sources.FilePathScoreFunction = class {
const isFileName = j > this._fileNameIndex;
const isPathTokenStart = j === 0 || data[j - 1] === '/';
let score = 10;
- if (isFileName)
+ if (isFileName) {
score += 4;
- if (isPathTokenStart)
+ }
+ if (isPathTokenStart) {
score += 5;
+ }
score += sequenceLength * 4;
return score;
}
@@ -178,12 +189,14 @@ Sources.FilePathScoreFunction = class {
* @return {number}
*/
_match(query, data, i, j, consecutiveMatch) {
- if (this._queryUpperCase[i] !== this._dataUpperCase[j])
+ if (this._queryUpperCase[i] !== this._dataUpperCase[j]) {
return 0;
+ }
- if (!consecutiveMatch)
+ if (!consecutiveMatch) {
return this._singleCharScore(query, data, i, j);
- else
+ } else {
return this._sequenceCharScore(query, data, i, j - consecutiveMatch, consecutiveMatch);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/FilteredUISourceCodeListProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/FilteredUISourceCodeListProvider.js
index 0dfdcb397b3..8961db94605 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/FilteredUISourceCodeListProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/FilteredUISourceCodeListProvider.js
@@ -33,8 +33,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
this._uiSourceCodes = [];
const projects = Workspace.workspace.projects().filter(this.filterProject.bind(this));
for (let i = 0; i < projects.length; ++i) {
- if (skipProject && projects[i] === skipProject)
+ if (skipProject && projects[i] === skipProject) {
continue;
+ }
const uiSourceCodes = projects[i].uiSourceCodes().filter(this._filterUISourceCode.bind(this));
this._uiSourceCodes = this._uiSourceCodes.concat(uiSourceCodes);
}
@@ -101,8 +102,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
itemScoreAt(itemIndex, query) {
const uiSourceCode = this._uiSourceCodes[itemIndex];
const score = this._defaultScores ? (this._defaultScores.get(uiSourceCode) || 0) : 0;
- if (!query || query.length < 2)
+ if (!query || query.length < 2) {
return score;
+ }
if (this._query !== query) {
this._query = query;
@@ -111,8 +113,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
let multiplier = 10;
if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem &&
- !Persistence.persistence.binding(uiSourceCode))
+ !Persistence.persistence.binding(uiSourceCode)) {
multiplier = 5;
+ }
const fullDisplayName = uiSourceCode.fullDisplayName();
return score + multiplier * this._scorer.score(fullDisplayName, null);
@@ -139,12 +142,14 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
this._renderSubtitleElement(subtitleElement, fullDisplayName);
subtitleElement.title = fullDisplayName;
const ranges = [];
- for (let i = 0; i < indexes.length; ++i)
+ for (let i = 0; i < indexes.length; ++i) {
ranges.push({offset: indexes[i], length: 1});
+ }
if (indexes[0] > fileNameIndex) {
- for (let i = 0; i < ranges.length; ++i)
+ for (let i = 0; i < ranges.length; ++i) {
ranges[i].offset -= fileNameIndex + 1;
+ }
UI.highlightRangesWithStyleClass(titleElement, ranges, 'highlight');
} else {
UI.highlightRangesWithStyleClass(subtitleElement, ranges, 'highlight');
@@ -158,8 +163,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
_renderSubtitleElement(element, text) {
element.removeChildren();
let splitPosition = text.lastIndexOf('/');
- if (text.length > 55)
+ if (text.length > 55) {
splitPosition = text.length - 55;
+ }
const first = element.createChild('div', 'first-part');
first.textContent = text.substring(0, splitPosition);
const second = element.createChild('div', 'second-part');
@@ -174,15 +180,18 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
*/
selectItem(itemIndex, promptValue) {
const parsedExpression = promptValue.trim().match(/^([^:]*)(:\d+)?(:\d+)?$/);
- if (!parsedExpression)
+ if (!parsedExpression) {
return;
+ }
let lineNumber;
let columnNumber;
- if (parsedExpression[2])
+ if (parsedExpression[2]) {
lineNumber = parseInt(parsedExpression[2].substr(1), 10) - 1;
- if (parsedExpression[3])
+ }
+ if (parsedExpression[3]) {
columnNumber = parseInt(parsedExpression[3].substr(1), 10) - 1;
+ }
const uiSourceCode = itemIndex !== null ? this._uiSourceCodes[itemIndex] : null;
this.uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber);
}
@@ -194,8 +203,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
*/
rewriteQuery(query) {
query = query ? query.trim() : '';
- if (!query || query === ':')
+ if (!query || query === ':') {
return '';
+ }
const lineNumberMatch = query.match(/^([^:]+)((?::[^:]*){0,2})$/);
this._queryLineNumberAndColumnNumber = lineNumberMatch ? lineNumberMatch[2] : '';
return lineNumberMatch ? lineNumberMatch[1] : query;
@@ -206,8 +216,9 @@ Sources.FilteredUISourceCodeListProvider = class extends QuickOpen.FilteredListW
*/
_uiSourceCodeAdded(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
- if (!this._filterUISourceCode(uiSourceCode) || !this.filterProject(uiSourceCode.project()))
+ if (!this._filterUISourceCode(uiSourceCode) || !this.filterProject(uiSourceCode.project())) {
return;
+ }
this._uiSourceCodes.push(uiSourceCode);
this.refresh();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/GoToLineQuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/GoToLineQuickOpen.js
index 6b11376b3ea..5410af67120 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/GoToLineQuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/GoToLineQuickOpen.js
@@ -10,11 +10,13 @@ Sources.GoToLineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
*/
selectItem(itemIndex, promptValue) {
const uiSourceCode = this._currentUISourceCode();
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
const position = this._parsePosition(promptValue);
- if (!position)
+ if (!position) {
return;
+ }
Common.Revealer.reveal(uiSourceCode.uiLocation(position.line - 1, position.column - 1));
}
@@ -24,19 +26,22 @@ Sources.GoToLineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
* @return {string}
*/
notFoundText(query) {
- if (!this._currentUISourceCode())
+ if (!this._currentUISourceCode()) {
return Common.UIString('No file selected.');
+ }
const position = this._parsePosition(query);
if (!position) {
const sourceFrame = this._currentSourceFrame();
- if (!sourceFrame)
+ if (!sourceFrame) {
return ls`Type a number to go to that line.`;
+ }
const currentLineNumber = sourceFrame.textEditor.currentLineNumber() + 1;
const linesCount = sourceFrame.textEditor.linesCount;
return ls`Current line: ${currentLineNumber}. Type a line number between 1 and ${linesCount} to navigate to.`;
}
- if (position.column && position.column > 1)
+ if (position.column && position.column > 1) {
return ls`Go to line ${position.line} and column ${position.column}.`;
+ }
return ls`Go to line ${position.line}.`;
}
@@ -46,12 +51,14 @@ Sources.GoToLineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
*/
_parsePosition(query) {
const parts = query.match(/([0-9]+)(\:[0-9]*)?/);
- if (!parts || !parts[0] || parts[0].length !== query.length)
+ if (!parts || !parts[0] || parts[0].length !== query.length) {
return null;
+ }
const line = parseInt(parts[1], 10);
let column;
- if (parts[2])
+ if (parts[2]) {
column = parseInt(parts[2].substring(1), 10);
+ }
return {line: Math.max(line | 0, 1), column: Math.max(column | 0, 1)};
}
@@ -60,8 +67,9 @@ Sources.GoToLineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
*/
_currentUISourceCode() {
const sourcesView = UI.context.flavor(Sources.SourcesView);
- if (!sourcesView)
+ if (!sourcesView) {
return null;
+ }
return sourcesView.currentUISourceCode();
}
@@ -70,8 +78,9 @@ Sources.GoToLineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider
*/
_currentSourceFrame() {
const sourcesView = UI.context.flavor(Sources.SourcesView);
- if (!sourcesView)
+ if (!sourcesView) {
return null;
+ }
return sourcesView.currentSourceFrame();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js
index 4ce427719d4..7aef92da49e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/GutterDiffPlugin.js
@@ -21,6 +21,7 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
/**
+ * @override
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {boolean}
*/
@@ -36,18 +37,21 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._textEditor.operation(operation);
function operation() {
- for (const decoration of removed)
+ for (const decoration of removed) {
decoration.remove();
- for (const decoration of added)
+ }
+ for (const decoration of added) {
decoration.install();
+ }
}
}
_update() {
- if (this._uiSourceCode)
+ if (this._uiSourceCode) {
this._workspaceDiff.requestDiff(this._uiSourceCode).then(this._innerUpdate.bind(this));
- else
+ } else {
this._innerUpdate(null);
+ }
}
/**
@@ -65,8 +69,9 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
for (let i = 0; i < this._decorations.length; ++i) {
const decoration = this._decorations[i];
const lineNumber = decoration.lineNumber();
- if (lineNumber === -1)
+ if (lineNumber === -1) {
continue;
+ }
oldDecorations.set(lineNumber, decoration);
}
@@ -76,8 +81,9 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const newDecorations = new Map();
for (let i = 0; i < diff.length; ++i) {
const diffEntry = diff[i];
- for (let lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNumber)
+ for (let lineNumber = diffEntry.from; lineNumber < diffEntry.to; ++lineNumber) {
newDecorations.set(lineNumber, {lineNumber: lineNumber, type: diffEntry.type});
+ }
}
const decorationDiff = oldDecorations.diff(newDecorations, (e1, e2) => e1.type === e2.type);
@@ -117,8 +123,9 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
}
static _appendRevealDiffContextMenu(contextMenu, uiSourceCode) {
- if (!WorkspaceDiff.workspaceDiff().isUISourceCodeModified(uiSourceCode))
+ if (!WorkspaceDiff.workspaceDiff().isUISourceCodeModified(uiSourceCode)) {
return;
+ }
contextMenu.revealSection().appendItem(ls`Local Modifications...`, () => {
Common.Revealer.reveal(new WorkspaceDiff.DiffUILocation(uiSourceCode));
});
@@ -128,8 +135,9 @@ Sources.GutterDiffPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @override
*/
dispose() {
- for (const decoration of this._decorations)
+ for (const decoration of this._decorations) {
decoration.remove();
+ }
WorkspaceDiff.workspaceDiff().unsubscribeFromDiffChange(this._uiSourceCode, this._update, this);
}
};
@@ -144,12 +152,13 @@ Sources.GutterDiffPlugin.GutterDecoration = class {
this._textEditor = textEditor;
this._position = this._textEditor.textEditorPositionHandle(lineNumber, 0);
this._className = '';
- if (type === SourceFrame.SourceCodeDiff.EditType.Insert)
+ if (type === SourceFrame.SourceCodeDiff.EditType.Insert) {
this._className = 'diff-entry-insert';
- else if (type === SourceFrame.SourceCodeDiff.EditType.Delete)
+ } else if (type === SourceFrame.SourceCodeDiff.EditType.Delete) {
this._className = 'diff-entry-delete';
- else if (type === SourceFrame.SourceCodeDiff.EditType.Modify)
+ } else if (type === SourceFrame.SourceCodeDiff.EditType.Modify) {
this._className = 'diff-entry-modify';
+ }
this.type = type;
}
@@ -158,25 +167,28 @@ Sources.GutterDiffPlugin.GutterDecoration = class {
*/
lineNumber() {
const location = this._position.resolve();
- if (!location)
+ if (!location) {
return -1;
+ }
return location.lineNumber;
}
install() {
const location = this._position.resolve();
- if (!location)
+ if (!location) {
return;
+ }
const element = createElementWithClass('div', 'diff-marker');
- element.textContent = '\u00A0';
+ element.textContent = '\xA0';
this._textEditor.setGutterDecoration(location.lineNumber, Sources.GutterDiffPlugin.DiffGutterType, element);
this._textEditor.toggleLineClass(location.lineNumber, this._className, true);
}
remove() {
const location = this._position.resolve();
- if (!location)
+ if (!location) {
return;
+ }
this._textEditor.setGutterDecoration(location.lineNumber, Sources.GutterDiffPlugin.DiffGutterType, null);
this._textEditor.toggleLineClass(location.lineNumber, this._className, false);
}
@@ -199,8 +211,9 @@ Sources.GutterDiffPlugin.ContextMenuProvider = class {
appendApplicableItems(event, contextMenu, target) {
let uiSourceCode = /** @type {!Workspace.UISourceCode} */ (target);
const binding = Persistence.persistence.binding(uiSourceCode);
- if (binding)
+ if (binding) {
uiSourceCode = binding.network;
+ }
Sources.GutterDiffPlugin._appendRevealDiffContextMenu(contextMenu, uiSourceCode);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/InplaceFormatterEditorAction.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/InplaceFormatterEditorAction.js
index aa3578f1a92..adeda44d817 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/InplaceFormatterEditorAction.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/InplaceFormatterEditorAction.js
@@ -19,8 +19,9 @@ Sources.InplaceFormatterEditorAction = class {
*/
_editorClosed(event) {
const wasSelected = /** @type {boolean} */ (event.data.wasSelected);
- if (wasSelected)
+ if (wasSelected) {
this._updateButton(null);
+ }
}
/**
@@ -36,8 +37,9 @@ Sources.InplaceFormatterEditorAction = class {
* @return {!UI.ToolbarButton}
*/
button(sourcesView) {
- if (this._button)
+ if (this._button) {
return this._button;
+ }
this._sourcesView = sourcesView;
this._sourcesView.addEventListener(Sources.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
@@ -55,12 +57,15 @@ Sources.InplaceFormatterEditorAction = class {
* @return {boolean}
*/
_isFormattable(uiSourceCode) {
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return false;
- if (uiSourceCode.project().canSetFileContent())
+ }
+ if (uiSourceCode.project().canSetFileContent()) {
return true;
- if (Persistence.persistence.binding(uiSourceCode))
+ }
+ if (Persistence.persistence.binding(uiSourceCode)) {
return true;
+ }
return uiSourceCode.contentType().isStyleSheet();
}
@@ -69,40 +74,49 @@ Sources.InplaceFormatterEditorAction = class {
*/
_formatSourceInPlace(event) {
const uiSourceCode = this._sourcesView.currentUISourceCode();
- if (!this._isFormattable(uiSourceCode))
+ if (!this._isFormattable(uiSourceCode)) {
return;
+ }
- if (uiSourceCode.isDirty())
- contentLoaded.call(this, uiSourceCode.workingCopy());
- else
- uiSourceCode.requestContent().then(contentLoaded.bind(this));
-
- /**
- * @this {Sources.InplaceFormatterEditorAction}
- * @param {?string} content
- */
- function contentLoaded(content) {
- const highlighterType = uiSourceCode.mimeType();
- Formatter.Formatter.format(uiSourceCode.contentType(), highlighterType, content || '', innerCallback.bind(this));
+ if (uiSourceCode.isDirty()) {
+ this._contentLoaded(uiSourceCode, uiSourceCode.workingCopy());
+ } else {
+ uiSourceCode.requestContent().then(deferredContent => {
+ this._contentLoaded(uiSourceCode, deferredContent.content);
+ });
}
+ }
- /**
- * @this {Sources.InplaceFormatterEditorAction}
+ /**
+ * @param {?Workspace.UISourceCode} uiSourceCode
+ * @param {string} content
+ */
+ _contentLoaded(uiSourceCode, content) {
+ const highlighterType = uiSourceCode.mimeType();
+ Formatter.Formatter.format(
+ uiSourceCode.contentType(), highlighterType, content, (formattedContent, formatterMapping) => {
+ this._formattingComplete(uiSourceCode, formattedContent, formatterMapping);
+ });
+ }
+
+ /**
+ * Post-format callback
+ * @param {?Workspace.UISourceCode} uiSourceCode
* @param {string} formattedContent
* @param {!Formatter.FormatterSourceMapping} formatterMapping
*/
- function innerCallback(formattedContent, formatterMapping) {
- if (uiSourceCode.workingCopy() === formattedContent)
- return;
- const sourceFrame = this._sourcesView.viewForFile(uiSourceCode);
- let start = [0, 0];
- if (sourceFrame) {
- const selection = sourceFrame.selection();
- start = formatterMapping.originalToFormatted(selection.startLine, selection.startColumn);
- }
- uiSourceCode.setWorkingCopy(formattedContent);
-
- this._sourcesView.showSourceLocation(uiSourceCode, start[0], start[1]);
+ _formattingComplete(uiSourceCode, formattedContent, formatterMapping) {
+ if (uiSourceCode.workingCopy() === formattedContent) {
+ return;
}
+ const sourceFrame = this._sourcesView.viewForFile(uiSourceCode);
+ let start = [0, 0];
+ if (sourceFrame) {
+ const selection = sourceFrame.selection();
+ start = formatterMapping.originalToFormatted(selection.startLine, selection.startColumn);
+ }
+ uiSourceCode.setWorkingCopy(formattedContent);
+
+ this._sourcesView.showSourceLocation(uiSourceCode, start[0], start[1]);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
index 6eff15b7f68..60b042f6980 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
@@ -46,11 +46,11 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
breakpointLocations.sort((item1, item2) => item1.uiLocation.compareTo(item2.uiLocation));
- /** @type {!Multimap<string, string>} */
- const breakpointEntriesForLine = new Multimap();
+ /** @type {!Platform.Multimap<string, string>} */
+ const breakpointEntriesForLine = new Platform.Multimap();
- /** @type {!Multimap<string, !{breakpoint: !Bindings.BreakpointManager.Breakpoint, uiLocation: !Workspace.UILocation}>} */
- const locationForEntry = new Multimap();
+ /** @type {!Platform.Multimap<string, !{breakpoint: !Bindings.BreakpointManager.Breakpoint, uiLocation: !Workspace.UILocation}>} */
+ const locationForEntry = new Platform.Multimap();
for (const breakpointLocation of breakpointLocations) {
const uiLocation = breakpointLocation.uiLocation;
const entryDescriptor = `${uiLocation.uiSourceCode.url()}:${uiLocation.lineNumber}:${uiLocation.columnNumber}`;
@@ -91,8 +91,9 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
promises.push(
this._resetEntry(/** @type {!Element}*/ (entry), uiLocation, isSelected, hasEnabled, hasDisabled, showCoumn));
entry[Sources.JavaScriptBreakpointsSidebarPane._breakpointLocationsSymbol] = locations;
- if (isSelected)
+ if (isSelected) {
shouldShowView = true;
+ }
entry = entry.nextSibling;
}
while (entry) {
@@ -100,8 +101,9 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
entry.remove();
entry = next;
}
- if (shouldShowView)
+ if (shouldShowView) {
UI.viewManager.showView('sources.jsBreakpoints');
+ }
this._listElement.classList.toggle(
'breakpoints-list-deactivated', !Common.moduleSetting('breakpointsActive').get());
return Promise.all(promises).then(() => this._didUpdateForTest());
@@ -127,14 +129,14 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
checkboxLabel.checkboxElement.indeterminate = hasEnabled && hasDisabled;
const snippetElement = element[Sources.JavaScriptBreakpointsSidebarPane._snippetElementSymbol];
- const content = await uiLocation.uiSourceCode.requestContent();
+ const {content} = await uiLocation.uiSourceCode.requestContent();
const lineNumber = uiLocation.lineNumber;
const text = new TextUtils.Text(content || '');
if (lineNumber < text.lineCount()) {
const lineText = text.lineAt(lineNumber);
const maxSnippetLength = 200;
snippetElement.textContent =
- lineText.substring(showColumn ? uiLocation.columnNumber : 0).trimEnd(maxSnippetLength);
+ lineText.substring(showColumn ? uiLocation.columnNumber : 0).trimEndWithMaxLength(maxSnippetLength);
}
}
@@ -144,8 +146,9 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
*/
_breakpointLocations(event) {
const node = event.target.enclosingNodeOrSelfWithClass('breakpoint-entry');
- if (!node)
+ if (!node) {
return [];
+ }
return node[Sources.JavaScriptBreakpointsSidebarPane._breakpointLocationsSymbol] || [];
}
@@ -155,8 +158,9 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
_breakpointCheckboxClicked(event) {
const breakpoints = this._breakpointLocations(event).map(breakpointLocation => breakpointLocation.breakpoint);
const newState = event.target.checkboxElement.checked;
- for (const breakpoint of breakpoints)
+ for (const breakpoint of breakpoints) {
breakpoint.setEnabled(newState);
+ }
event.consume();
}
@@ -167,11 +171,13 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
const uiLocations = this._breakpointLocations(event).map(breakpointLocation => breakpointLocation.uiLocation);
let uiLocation = null;
for (const uiLocationCandidate of uiLocations) {
- if (!uiLocation || uiLocationCandidate.columnNumber < uiLocation.columnNumber)
+ if (!uiLocation || uiLocationCandidate.columnNumber < uiLocation.columnNumber) {
uiLocation = uiLocationCandidate;
+ }
}
- if (uiLocation)
+ if (uiLocation) {
Common.Revealer.reveal(uiLocation);
+ }
}
/**
@@ -212,13 +218,15 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
* @param {boolean} toggleState
*/
_toggleAllBreakpoints(toggleState) {
- for (const breakpointLocation of this._breakpointManager.allBreakpointLocations())
+ for (const breakpointLocation of this._breakpointManager.allBreakpointLocations()) {
breakpointLocation.breakpoint.setEnabled(toggleState);
+ }
}
_removeAllBreakpoints() {
- for (const breakpointLocation of this._breakpointManager.allBreakpointLocations())
+ for (const breakpointLocation of this._breakpointManager.allBreakpointLocations()) {
breakpointLocation.breakpoint.remove(false /* keepInStorage */);
+ }
}
/**
@@ -226,8 +234,9 @@ Sources.JavaScriptBreakpointsSidebarPane = class extends UI.ThrottledWidget {
*/
_removeOtherBreakpoints(selectedBreakpoints) {
for (const breakpointLocation of this._breakpointManager.allBreakpointLocations()) {
- if (!selectedBreakpoints.has(breakpointLocation.breakpoint))
+ if (!selectedBreakpoints.has(breakpointLocation.breakpoint)) {
breakpointLocation.breakpoint.remove(false /* keepInStorage */);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptCompilerPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptCompilerPlugin.js
index 9e87115e507..69f1edb5560 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptCompilerPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/JavaScriptCompilerPlugin.js
@@ -19,8 +19,9 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
this._disposed = false;
this._textEditor.addEventListener(UI.TextEditor.Events.TextChanged, this._scheduleCompile, this);
- if (this._uiSourceCode.hasCommits() || this._uiSourceCode.isDirty())
+ if (this._uiSourceCode.hasCommits() || this._uiSourceCode.isDirty()) {
this._scheduleCompile();
+ }
}
/**
@@ -29,13 +30,16 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
* @return {boolean}
*/
static accepts(uiSourceCode) {
- if (uiSourceCode.extension() === 'js')
+ if (uiSourceCode.extension() === 'js') {
return true;
- if (Snippets.isSnippetsUISourceCode(uiSourceCode))
+ }
+ if (Snippets.isSnippetsUISourceCode(uiSourceCode)) {
return true;
+ }
for (const debuggerModel of SDK.targetManager.models(SDK.DebuggerModel)) {
- if (Bindings.debuggerWorkspaceBinding.scriptFile(uiSourceCode, debuggerModel))
+ if (Bindings.debuggerWorkspaceBinding.scriptFile(uiSourceCode, debuggerModel)) {
return true;
+ }
}
return false;
}
@@ -45,8 +49,9 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
this._recompileScheduled = true;
return;
}
- if (this._timeout)
+ if (this._timeout) {
clearTimeout(this._timeout);
+ }
this._timeout = setTimeout(this._compile.bind(this), Sources.JavaScriptCompilerPlugin.CompileDelay);
}
@@ -57,23 +62,27 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
const debuggerModels = SDK.targetManager.models(SDK.DebuggerModel);
for (let i = 0; i < debuggerModels.length; ++i) {
const scriptFile = Bindings.debuggerWorkspaceBinding.scriptFile(this._uiSourceCode, debuggerModels[i]);
- if (scriptFile)
+ if (scriptFile) {
return debuggerModels[i].runtimeModel();
+ }
}
return SDK.targetManager.mainTarget() ? SDK.targetManager.mainTarget().model(SDK.RuntimeModel) : null;
}
async _compile() {
const runtimeModel = this._findRuntimeModel();
- if (!runtimeModel)
+ if (!runtimeModel) {
return;
+ }
const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!currentExecutionContext)
+ if (!currentExecutionContext) {
return;
+ }
const code = this._textEditor.text();
- if (code.length > 1024 * 100)
+ if (code.length > 1024 * 100) {
return;
+ }
this._compiling = true;
const result = await runtimeModel.compileScript(code, '', false, currentExecutionContext.id);
@@ -84,10 +93,12 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
this._scheduleCompile();
return;
}
- if (this._message)
+ if (this._message) {
this._uiSourceCode.removeMessage(this._message);
- if (this._disposed || !result || !result.exceptionDetails)
+ }
+ if (this._disposed || !result || !result.exceptionDetails) {
return;
+ }
const exceptionDetails = result.exceptionDetails;
const text = SDK.RuntimeModel.simpleTextFromException(exceptionDetails);
@@ -104,11 +115,13 @@ Sources.JavaScriptCompilerPlugin = class extends Sources.UISourceCodeFrame.Plugi
*/
dispose() {
this._textEditor.removeEventListener(UI.TextEditor.Events.TextChanged, this._scheduleCompile, this);
- if (this._message)
+ if (this._message) {
this._uiSourceCode.removeMessage(this._message);
+ }
this._disposed = true;
- if (this._timeout)
+ if (this._timeout) {
clearTimeout(this._timeout);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js
index 45309a2ad9f..b4c6eabb5e1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js
@@ -42,8 +42,8 @@ Sources.NavigatorView = class extends UI.VBox {
this.contentElement.appendChild(this._scriptsTree.element);
this.setDefaultFocusedElement(this._scriptsTree.element);
- /** @type {!Multimap<!Workspace.UISourceCode, !Sources.NavigatorUISourceCodeTreeNode>} */
- this._uiSourceCodeNodes = new Multimap();
+ /** @type {!Platform.Multimap<!Workspace.UISourceCode, !Sources.NavigatorUISourceCodeTreeNode>} */
+ this._uiSourceCodeNodes = new Platform.Multimap();
/** @type {!Map.<string, !Sources.NavigatorFolderTreeNode>} */
this._subfolderNodes = new Map();
@@ -81,8 +81,9 @@ Sources.NavigatorView = class extends UI.VBox {
* @param {!UI.TreeElement} treeElement
*/
static _treeElementOrder(treeElement) {
- if (treeElement._boostOrder)
+ if (treeElement._boostOrder) {
return 0;
+ }
if (!Sources.NavigatorView._typeOrders) {
const weights = {};
@@ -102,14 +103,15 @@ Sources.NavigatorView = class extends UI.VBox {
let order = Sources.NavigatorView._typeOrders[treeElement._nodeType];
if (treeElement._uiSourceCode) {
const contentType = treeElement._uiSourceCode.contentType();
- if (contentType.isDocument())
+ if (contentType.isDocument()) {
order += 3;
- else if (contentType.isScript())
+ } else if (contentType.isScript()) {
order += 5;
- else if (contentType.isStyleSheet())
+ } else if (contentType.isStyleSheet()) {
order += 10;
- else
+ } else {
order += 15;
+ }
}
return order;
@@ -141,10 +143,12 @@ Sources.NavigatorView = class extends UI.VBox {
const typeWeight1 = Sources.NavigatorView._treeElementOrder(treeElement1);
const typeWeight2 = Sources.NavigatorView._treeElementOrder(treeElement2);
- if (typeWeight1 > typeWeight2)
+ if (typeWeight1 > typeWeight2) {
return 1;
- if (typeWeight1 < typeWeight2)
+ }
+ if (typeWeight1 < typeWeight2) {
return -1;
+ }
return treeElement1.titleAsText().compareTo(treeElement2.titleAsText());
}
@@ -164,10 +168,11 @@ Sources.NavigatorView = class extends UI.VBox {
*/
function updateVisibility() {
const showTree = this._scriptsTree.firstChild();
- if (showTree)
+ if (showTree) {
placeholder.hideWidget();
- else
+ } else {
placeholder.showWidget();
+ }
this._scriptsTree.element.classList.toggle('hidden', !showTree);
}
}
@@ -180,11 +185,13 @@ Sources.NavigatorView = class extends UI.VBox {
// Update UISourceCode titles.
const networkNodes = this._uiSourceCodeNodes.get(binding.network);
- for (const networkNode of networkNodes)
+ for (const networkNode of networkNodes) {
networkNode.updateTitle();
+ }
const fileSystemNodes = this._uiSourceCodeNodes.get(binding.fileSystem);
- for (const fileSystemNode of fileSystemNodes)
+ for (const fileSystemNode of fileSystemNodes) {
fileSystemNode.updateTitle();
+ }
// Update folder titles.
const pathTokens = Persistence.FileSystemWorkspaceBinding.relativePath(binding.fileSystem);
@@ -194,15 +201,17 @@ Sources.NavigatorView = class extends UI.VBox {
const folderId =
this._folderNodeId(binding.fileSystem.project(), null, null, binding.fileSystem.origin(), folderPath);
const folderNode = this._subfolderNodes.get(folderId);
- if (folderNode)
+ if (folderNode) {
folderNode.updateTitle();
+ }
folderPath += '/';
}
// Update fileSystem root title.
const fileSystemRoot = this._rootNode.child(binding.fileSystem.project().id());
- if (fileSystemRoot)
+ if (fileSystemRoot) {
fileSystemRoot.updateTitle();
+ }
}
/**
@@ -222,14 +231,16 @@ Sources.NavigatorView = class extends UI.VBox {
this._workspace.addEventListener(Workspace.Workspace.Events.ProjectAdded, event => {
const project = /** @type {!Workspace.Project} */ (event.data);
this._projectAdded(project);
- if (project.type() === Workspace.projectTypes.FileSystem)
+ if (project.type() === Workspace.projectTypes.FileSystem) {
this._computeUniqueFileSystemProjectNames();
+ }
});
this._workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, event => {
const project = /** @type {!Workspace.Project} */ (event.data);
this._removeProject(project);
- if (project.type() === Workspace.projectTypes.FileSystem)
+ if (project.type() === Workspace.projectTypes.FileSystem) {
this._computeUniqueFileSystemProjectNames();
+ }
});
this._workspace.projects().forEach(this._projectAdded.bind(this));
this._computeUniqueFileSystemProjectNames();
@@ -256,8 +267,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_frameAttributionAdded(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
- if (!this._acceptsUISourceCode(uiSourceCode))
+ if (!this._acceptsUISourceCode(uiSourceCode)) {
return;
+ }
const addedFrame = /** @type {?SDK.ResourceTreeFrame} */ (event.data.frame);
// This event does not happen for UISourceCodes without initial attribution.
@@ -269,8 +281,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_frameAttributionRemoved(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
- if (!this._acceptsUISourceCode(uiSourceCode))
+ if (!this._acceptsUISourceCode(uiSourceCode)) {
return;
+ }
const removedFrame = /** @type {?SDK.ResourceTreeFrame} */ (event.data.frame);
const node = Array.from(this._uiSourceCodeNodes.get(uiSourceCode)).find(node => node.frame() === removedFrame);
@@ -289,13 +302,15 @@ Sources.NavigatorView = class extends UI.VBox {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_addUISourceCode(uiSourceCode) {
- if (!this._acceptsUISourceCode(uiSourceCode))
+ if (!this._acceptsUISourceCode(uiSourceCode)) {
return;
+ }
const frames = Bindings.NetworkProject.framesForUISourceCode(uiSourceCode);
if (frames.length) {
- for (const frame of frames)
+ for (const frame of frames) {
this._addUISourceCodeNode(uiSourceCode, frame);
+ }
} else {
this._addUISourceCodeNode(uiSourceCode, null);
}
@@ -309,10 +324,11 @@ Sources.NavigatorView = class extends UI.VBox {
_addUISourceCodeNode(uiSourceCode, frame) {
const isFromSourceMap = uiSourceCode.contentType().isFromSourceMap();
let path;
- if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem)
+ if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) {
path = Persistence.FileSystemWorkspaceBinding.relativePath(uiSourceCode).slice(0, -1);
- else
+ } else {
path = Common.ParsedURL.extractPath(uiSourceCode.url()).split('/').slice(1, -1);
+ }
const project = uiSourceCode.project();
const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
@@ -360,8 +376,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_projectAdded(project) {
if (!this.acceptProject(project) || project.type() !== Workspace.projectTypes.FileSystem ||
- Snippets.isSnippetsProject(project) || this._rootNode.child(project.id()))
+ Snippets.isSnippetsProject(project) || this._rootNode.child(project.id())) {
return;
+ }
this._rootNode.appendChild(new Sources.NavigatorGroupTreeNode(
this, project, project.id(), Sources.NavigatorView.Types.FileSystem, project.displayName()));
this._selectDefaultTreeNode();
@@ -370,22 +387,25 @@ Sources.NavigatorView = class extends UI.VBox {
// TODO(einbinder) remove this code after crbug.com/964075 is fixed
_selectDefaultTreeNode() {
const children = this._rootNode.children();
- if (children.length && !this._scriptsTree.selectedTreeElement)
+ if (children.length && !this._scriptsTree.selectedTreeElement) {
children[0].treeNode().select(true /* omitFocus */, false /* selectedByUser */);
+ }
}
_computeUniqueFileSystemProjectNames() {
const fileSystemProjects = this._workspace.projectsForType(Workspace.projectTypes.FileSystem);
- if (!fileSystemProjects.length)
+ if (!fileSystemProjects.length) {
return;
+ }
const encoder = new Persistence.PathEncoder();
const reversedPaths = fileSystemProjects.map(project => {
const fileSystem = /** @type {!Persistence.FileSystemWorkspaceBinding.FileSystem} */ (project);
return encoder.encode(fileSystem.fileSystemPath()).reverse();
});
const reversedIndex = new Common.Trie();
- for (const reversedPath of reversedPaths)
+ for (const reversedPath of reversedPaths) {
reversedIndex.add(reversedPath);
+ }
for (let i = 0; i < fileSystemProjects.length; ++i) {
const reversedPath = reversedPaths[i];
@@ -395,8 +415,9 @@ Sources.NavigatorView = class extends UI.VBox {
reversedIndex.add(reversedPath);
const path = encoder.decode(reversedPath.substring(0, commonPrefix.length + 1).reverse());
const fileSystemNode = this._rootNode.child(project.id());
- if (fileSystemNode)
+ if (fileSystemNode) {
fileSystemNode.setTitle(path);
+ }
}
}
@@ -405,13 +426,16 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_removeProject(project) {
const uiSourceCodes = project.uiSourceCodes();
- for (let i = 0; i < uiSourceCodes.length; ++i)
+ for (let i = 0; i < uiSourceCodes.length; ++i) {
this._removeUISourceCode(uiSourceCodes[i]);
- if (project.type() !== Workspace.projectTypes.FileSystem)
+ }
+ if (project.type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
const fileSystemNode = this._rootNode.child(project.id());
- if (!fileSystemNode)
+ if (!fileSystemNode) {
return;
+ }
this._rootNode.removeChild(fileSystemNode);
}
@@ -441,29 +465,34 @@ Sources.NavigatorView = class extends UI.VBox {
* @return {!Sources.NavigatorTreeNode}
*/
_folderNode(uiSourceCode, project, target, frame, projectOrigin, path, fromSourceMap) {
- if (Snippets.isSnippetsUISourceCode(uiSourceCode))
+ if (Snippets.isSnippetsUISourceCode(uiSourceCode)) {
return this._rootNode;
+ }
- if (target && !this._groupByFolder && !fromSourceMap)
+ if (target && !this._groupByFolder && !fromSourceMap) {
return this._domainNode(uiSourceCode, project, target, frame, projectOrigin);
+ }
const folderPath = path.join('/');
const folderId = this._folderNodeId(project, target, frame, projectOrigin, folderPath);
let folderNode = this._subfolderNodes.get(folderId);
- if (folderNode)
+ if (folderNode) {
return folderNode;
+ }
if (!path.length) {
- if (target)
+ if (target) {
return this._domainNode(uiSourceCode, project, target, frame, projectOrigin);
+ }
return /** @type {!Sources.NavigatorTreeNode} */ (this._rootNode.child(project.id()));
}
const parentNode =
this._folderNode(uiSourceCode, project, target, frame, projectOrigin, path.slice(0, -1), fromSourceMap);
let type = fromSourceMap ? Sources.NavigatorView.Types.SourceMapFolder : Sources.NavigatorView.Types.NetworkFolder;
- if (project.type() === Workspace.projectTypes.FileSystem)
+ if (project.type() === Workspace.projectTypes.FileSystem) {
type = Sources.NavigatorView.Types.FileSystemFolder;
+ }
const name = path[path.length - 1];
folderNode = new Sources.NavigatorFolderTreeNode(this, project, folderId, type, folderPath, name);
@@ -482,17 +511,20 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_domainNode(uiSourceCode, project, target, frame, projectOrigin) {
const frameNode = this._frameNode(project, target, frame);
- if (!this._groupByDomain)
+ if (!this._groupByDomain) {
return frameNode;
+ }
let domainNode = frameNode.child(projectOrigin);
- if (domainNode)
+ if (domainNode) {
return domainNode;
+ }
domainNode = new Sources.NavigatorGroupTreeNode(
this, project, projectOrigin, Sources.NavigatorView.Types.Domain,
this._computeProjectDisplayName(target, projectOrigin));
- if (frame && projectOrigin === Common.ParsedURL.extractOrigin(frame.url))
+ if (frame && projectOrigin === Common.ParsedURL.extractOrigin(frame.url)) {
domainNode.treeNode()._boostOrder = true;
+ }
frameNode.appendChild(domainNode);
return domainNode;
}
@@ -504,12 +536,14 @@ Sources.NavigatorView = class extends UI.VBox {
* @return {!Sources.NavigatorTreeNode}
*/
_frameNode(project, target, frame) {
- if (!this._groupByFrame || !frame)
+ if (!this._groupByFrame || !frame) {
return this._targetNode(project, target);
+ }
let frameNode = this._frameNodes.get(frame);
- if (frameNode)
+ if (frameNode) {
return frameNode;
+ }
frameNode = new Sources.NavigatorGroupTreeNode(
this, project, target.id() + ':' + frame.id, Sources.NavigatorView.Types.Frame, frame.displayName());
@@ -530,8 +564,9 @@ Sources.NavigatorView = class extends UI.VBox {
function hoverCallback(hovered) {
if (hovered) {
const overlayModel = target.model(SDK.OverlayModel);
- if (overlayModel)
+ if (overlayModel) {
overlayModel.highlightFrame(frame.id);
+ }
} else {
SDK.OverlayModel.hideDOMNodeHighlight();
}
@@ -545,8 +580,9 @@ Sources.NavigatorView = class extends UI.VBox {
* @return {!Sources.NavigatorTreeNode}
*/
_targetNode(project, target) {
- if (target === SDK.targetManager.mainTarget())
+ if (target === SDK.targetManager.mainTarget()) {
return this._rootNode;
+ }
let targetNode = this._rootNode.child('target:' + target.id());
if (!targetNode) {
@@ -569,12 +605,14 @@ Sources.NavigatorView = class extends UI.VBox {
const runtimeModel = target.model(SDK.RuntimeModel);
const executionContexts = runtimeModel ? runtimeModel.executionContexts() : [];
for (const context of executionContexts) {
- if (context.name && context.origin && projectOrigin.startsWith(context.origin))
+ if (context.name && context.origin && projectOrigin.startsWith(context.origin)) {
return context.name;
+ }
}
- if (!projectOrigin)
+ if (!projectOrigin) {
return Common.UIString('(no domain)');
+ }
const parsedURL = new Common.ParsedURL(projectOrigin);
const prettyURL = parsedURL.isValid ? parsedURL.host + (parsedURL.port ? (':' + parsedURL.port) : '') : '';
@@ -590,10 +628,12 @@ Sources.NavigatorView = class extends UI.VBox {
revealUISourceCode(uiSourceCode, select) {
const nodes = this._uiSourceCodeNodes.get(uiSourceCode);
const node = nodes.firstValue();
- if (!node)
+ if (!node) {
return null;
- if (this._scriptsTree.selectedTreeElement)
+ }
+ if (this._scriptsTree.selectedTreeElement) {
this._scriptsTree.selectedTreeElement.deselect();
+ }
this._lastSelectedUISourceCode = uiSourceCode;
// TODO(dgozman): figure out revealing multiple.
node.reveal(select);
@@ -614,8 +654,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_removeUISourceCode(uiSourceCode) {
const nodes = this._uiSourceCodeNodes.get(uiSourceCode);
- for (const node of nodes)
+ for (const node of nodes) {
this._removeUISourceCodeNode(node);
+ }
}
/**
@@ -634,12 +675,15 @@ Sources.NavigatorView = class extends UI.VBox {
while (node) {
parentNode = node.parent;
- if (!parentNode || !node.isEmpty())
+ if (!parentNode || !node.isEmpty()) {
break;
- if (parentNode === this._rootNode && project.type() === Workspace.projectTypes.FileSystem)
+ }
+ if (parentNode === this._rootNode && project.type() === Workspace.projectTypes.FileSystem) {
break;
- if (!(node instanceof Sources.NavigatorGroupTreeNode || node instanceof Sources.NavigatorFolderTreeNode))
+ }
+ if (!(node instanceof Sources.NavigatorGroupTreeNode || node instanceof Sources.NavigatorFolderTreeNode)) {
break;
+ }
if (node._type === Sources.NavigatorView.Types.Frame) {
this._discardFrame(/** @type {!SDK.ResourceTreeFrame} */ (frame));
break;
@@ -653,8 +697,9 @@ Sources.NavigatorView = class extends UI.VBox {
}
reset() {
- for (const node of this._uiSourceCodeNodes.valuesArray())
+ for (const node of this._uiSourceCodeNodes.valuesArray()) {
node.dispose();
+ }
this._scriptsTree.removeChildren();
this._uiSourceCodeNodes.clear();
@@ -674,8 +719,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_renameShortcut() {
const node = this._scriptsTree.selectedTreeElement && this._scriptsTree.selectedTreeElement._node;
- if (!node || !node._uiSourceCode || !node._uiSourceCode.canRename())
+ if (!node || !node._uiSourceCode || !node._uiSourceCode.canRename()) {
return false;
+ }
this.rename(node, false);
return true;
}
@@ -719,8 +765,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_handleContextMenuDelete(uiSourceCode) {
const shouldDelete = window.confirm(Common.UIString('Are you sure you want to delete this file?'));
- if (shouldDelete)
+ if (shouldDelete) {
uiSourceCode.project().deleteFile(uiSourceCode);
+ }
}
/**
@@ -755,15 +802,17 @@ Sources.NavigatorView = class extends UI.VBox {
const contextMenu = new UI.ContextMenu(event);
- Sources.NavigatorView.appendSearchItem(contextMenu, path);
-
- const folderPath = Common.ParsedURL.urlToPlatformPath(
- Persistence.FileSystemWorkspaceBinding.completeURL(project, path), Host.isWin());
- contextMenu.revealSection().appendItem(
- Common.UIString('Open folder'), () => InspectorFrontendHost.showItemInFolder(folderPath));
- if (project.canCreateFile()) {
- contextMenu.defaultSection().appendItem(
- Common.UIString('New file'), this._handleContextMenuCreate.bind(this, project, path));
+ if (project.type() === Workspace.projectTypes.FileSystem) {
+ Sources.NavigatorView.appendSearchItem(contextMenu, path);
+
+ const folderPath = Common.ParsedURL.urlToPlatformPath(
+ Persistence.FileSystemWorkspaceBinding.completeURL(project, path), Host.isWin());
+ contextMenu.revealSection().appendItem(
+ Common.UIString('Open folder'), () => Host.InspectorFrontendHost.showItemInFolder(folderPath));
+ if (project.canCreateFile()) {
+ contextMenu.defaultSection().appendItem(
+ Common.UIString('New file'), this._handleContextMenuCreate.bind(this, project, path));
+ }
}
if (project.canExcludeFolder(path)) {
@@ -773,14 +822,16 @@ Sources.NavigatorView = class extends UI.VBox {
function removeFolder() {
const shouldRemove = window.confirm(Common.UIString('Are you sure you want to remove this folder?'));
- if (shouldRemove)
+ if (shouldRemove) {
project.remove();
+ }
}
if (project.type() === Workspace.projectTypes.FileSystem) {
contextMenu.defaultSection().appendAction('sources.add-folder-to-workspace', undefined, true);
- if (node instanceof Sources.NavigatorGroupTreeNode)
+ if (node instanceof Sources.NavigatorGroupTreeNode) {
contextMenu.defaultSection().appendItem(Common.UIString('Remove folder from workspace'), removeFolder);
+ }
}
contextMenu.show();
@@ -800,12 +851,14 @@ Sources.NavigatorView = class extends UI.VBox {
* @param {boolean} committed
*/
function callback(committed) {
- if (!creatingNewUISourceCode)
+ if (!creatingNewUISourceCode) {
return;
- if (!committed)
+ }
+ if (!committed) {
uiSourceCode.remove();
- else if (node._treeElement.listItemElement.hasFocus())
+ } else if (node._treeElement.listItemElement.hasFocus()) {
this._sourceSelected(uiSourceCode, true);
+ }
}
}
@@ -816,15 +869,18 @@ Sources.NavigatorView = class extends UI.VBox {
*/
async create(project, path, uiSourceCodeToCopy) {
let content = '';
- if (uiSourceCodeToCopy)
- content = (await uiSourceCodeToCopy.requestContent()) || '';
+ if (uiSourceCodeToCopy) {
+ content = (await uiSourceCodeToCopy.requestContent()).content || '';
+ }
const uiSourceCode = await project.createFile(path, null, content);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
this._sourceSelected(uiSourceCode, false);
const node = this.revealUISourceCode(uiSourceCode, true);
- if (node)
+ if (node) {
this.rename(node, true);
+ }
}
_groupingChanged() {
@@ -849,14 +905,17 @@ Sources.NavigatorView = class extends UI.VBox {
*/
_discardFrame(frame) {
const node = this._frameNodes.get(frame);
- if (!node)
+ if (!node) {
return;
+ }
- if (node.parent)
+ if (node.parent) {
node.parent.removeChild(node);
+ }
this._frameNodes.delete(frame);
- for (const child of frame.childFrames)
+ for (const child of frame.childFrames) {
this._discardFrame(child);
+ }
}
/**
@@ -872,8 +931,9 @@ Sources.NavigatorView = class extends UI.VBox {
*/
targetRemoved(target) {
const targetNode = this._rootNode.child('target:' + target.id());
- if (targetNode)
+ if (targetNode) {
this._rootNode.removeChild(targetNode);
+ }
}
/**
@@ -882,8 +942,9 @@ Sources.NavigatorView = class extends UI.VBox {
_targetNameChanged(event) {
const target = /** @type {!SDK.Target} */ (event.data);
const targetNode = this._rootNode.child('target:' + target.id());
- if (targetNode)
+ if (targetNode) {
targetNode.setTitle(target.name());
+ }
}
};
@@ -918,12 +979,13 @@ Sources.NavigatorFolderTreeElement = class extends UI.TreeElement {
this._navigatorView = navigatorView;
this._hoverCallback = hoverCallback;
let iconType = 'largeicon-navigator-folder';
- if (type === Sources.NavigatorView.Types.Domain)
+ if (type === Sources.NavigatorView.Types.Domain) {
iconType = 'largeicon-navigator-domain';
- else if (type === Sources.NavigatorView.Types.Frame)
+ } else if (type === Sources.NavigatorView.Types.Frame) {
iconType = 'largeicon-navigator-frame';
- else if (type === Sources.NavigatorView.Types.Worker)
+ } else if (type === Sources.NavigatorView.Types.Worker) {
iconType = 'largeicon-navigator-worker';
+ }
this.setLeadingIcons([UI.Icon.create(iconType, 'icon')]);
}
@@ -964,8 +1026,9 @@ Sources.NavigatorFolderTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_handleContextMenuEvent(event) {
- if (!this._node)
+ if (!this._node) {
return;
+ }
this.select();
this._navigatorView.handleFolderContextMenu(event, this._node);
}
@@ -974,8 +1037,9 @@ Sources.NavigatorFolderTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_mouseMove(event) {
- if (this._hovered || !this._hoverCallback)
+ if (this._hovered || !this._hoverCallback) {
return;
+ }
this._hovered = true;
this._hoverCallback(true);
}
@@ -984,8 +1048,9 @@ Sources.NavigatorFolderTreeElement = class extends UI.TreeElement {
* @param {!Event} event
*/
_mouseLeave(event) {
- if (!this._hoverCallback)
+ if (!this._hoverCallback) {
return;
+ }
this._hovered = false;
this._hoverCallback(false);
}
@@ -1019,21 +1084,24 @@ Sources.NavigatorSourceTreeElement = class extends UI.TreeElement {
if (binding) {
const container = createElementWithClass('span', 'icon-stack');
let iconType = 'largeicon-navigator-file-sync';
- if (Snippets.isSnippetsUISourceCode(binding.fileSystem))
+ if (Snippets.isSnippetsUISourceCode(binding.fileSystem)) {
iconType = 'largeicon-navigator-snippet';
+ }
const icon = UI.Icon.create(iconType, 'icon');
const badge = UI.Icon.create('badge-navigator-file-sync', 'icon-badge');
// TODO(allada) This does not play well with dark theme. Add an actual icon and use it.
- if (Persistence.networkPersistenceManager.project() === binding.fileSystem.project())
+ if (Persistence.networkPersistenceManager.project() === binding.fileSystem.project()) {
badge.style.filter = 'hue-rotate(160deg)';
+ }
container.appendChild(icon);
container.appendChild(badge);
container.title = Persistence.PersistenceUtils.tooltipForUISourceCode(this._uiSourceCode);
this.setLeadingIcons([container]);
} else {
let iconType = 'largeicon-navigator-file';
- if (Snippets.isSnippetsUISourceCode(this._uiSourceCode))
+ if (Snippets.isSnippetsUISourceCode(this._uiSourceCode)) {
iconType = 'largeicon-navigator-snippet';
+ }
const defaultIcon = UI.Icon.create(iconType, 'icon');
this.setLeadingIcons([defaultIcon]);
}
@@ -1057,8 +1125,9 @@ Sources.NavigatorSourceTreeElement = class extends UI.TreeElement {
}
_shouldRenameOnMouseDown() {
- if (!this._uiSourceCode.canRename())
+ if (!this._uiSourceCode.canRename()) {
return false;
+ }
const isSelected = this === this.treeOutline.selectedTreeElement;
return isSelected && this.treeOutline.element.hasFocus() && !UI.isBeingEdited(this.treeOutline.element);
}
@@ -1077,8 +1146,9 @@ Sources.NavigatorSourceTreeElement = class extends UI.TreeElement {
* @this {Sources.NavigatorSourceTreeElement}
*/
function rename() {
- if (this._shouldRenameOnMouseDown())
+ if (this._shouldRenameOnMouseDown()) {
this._navigatorView.rename(this._node, false);
+ }
}
}
@@ -1192,34 +1262,39 @@ Sources.NavigatorTreeNode = class {
}
populate() {
- if (this.isPopulated())
+ if (this.isPopulated()) {
return;
- if (this.parent)
+ }
+ if (this.parent) {
this.parent.populate();
+ }
this._populated = true;
this.wasPopulated();
}
wasPopulated() {
const children = this.children();
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
this.treeNode().appendChild(/** @type {!UI.TreeElement} */ (children[i].treeNode()));
+ }
}
/**
* @param {!Sources.NavigatorTreeNode} node
*/
didAddChild(node) {
- if (this.isPopulated())
+ if (this.isPopulated()) {
this.treeNode().appendChild(/** @type {!UI.TreeElement} */ (node.treeNode()));
+ }
}
/**
* @param {!Sources.NavigatorTreeNode} node
*/
willRemoveChild(node) {
- if (this.isPopulated())
+ if (this.isPopulated()) {
this.treeNode().removeChild(/** @type {!UI.TreeElement} */ (node.treeNode()));
+ }
}
/**
@@ -1341,8 +1416,9 @@ Sources.NavigatorUISourceCodeTreeNode = class extends Sources.NavigatorTreeNode
* @return {!UI.TreeElement}
*/
treeNode() {
- if (this._treeElement)
+ if (this._treeElement) {
return this._treeElement;
+ }
this._treeElement = new Sources.NavigatorSourceTreeElement(this._navigatorView, this._uiSourceCode, '', this);
this.updateTitle();
@@ -1360,19 +1436,22 @@ Sources.NavigatorUISourceCodeTreeNode = class extends Sources.NavigatorTreeNode
* @param {boolean=} ignoreIsDirty
*/
updateTitle(ignoreIsDirty) {
- if (!this._treeElement)
+ if (!this._treeElement) {
return;
+ }
let titleText = this._uiSourceCode.displayName();
- if (!ignoreIsDirty && this._uiSourceCode.isDirty())
+ if (!ignoreIsDirty && this._uiSourceCode.isDirty()) {
titleText = '*' + titleText;
+ }
this._treeElement.title = titleText;
this._treeElement.updateIcon();
let tooltip = this._uiSourceCode.url();
- if (this._uiSourceCode.contentType().isFromSourceMap())
+ if (this._uiSourceCode.contentType().isFromSourceMap()) {
tooltip = Common.UIString('%s (from source map)', this._uiSourceCode.displayName());
+ }
this._treeElement.tooltip = tooltip;
}
@@ -1398,16 +1477,18 @@ Sources.NavigatorUISourceCodeTreeNode = class extends Sources.NavigatorTreeNode
this.parent.populate();
this.parent.treeNode().expand();
this._treeElement.reveal(true);
- if (select)
+ if (select) {
this._treeElement.select(true);
+ }
}
/**
* @param {function(boolean)=} callback
*/
rename(callback) {
- if (!this._treeElement)
+ if (!this._treeElement) {
return;
+ }
this._treeElement.listItemElement.focus();
@@ -1451,8 +1532,9 @@ Sources.NavigatorUISourceCodeTreeNode = class extends Sources.NavigatorTreeNode
function afterEditing(committed) {
UI.markBeingEdited(treeOutlineElement, false);
this.updateTitle();
- if (callback)
+ if (callback) {
callback(committed);
+ }
}
this.updateTitle(true);
@@ -1486,16 +1568,18 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
* @return {!UI.TreeElement}
*/
treeNode() {
- if (this._treeElement)
+ if (this._treeElement) {
return this._treeElement;
+ }
this._treeElement = this._createTreeElement(this._title, this);
this.updateTitle();
return this._treeElement;
}
updateTitle() {
- if (!this._treeElement || this._project.type() !== Workspace.projectTypes.FileSystem)
+ if (!this._treeElement || this._project.type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
const absoluteFileSystemPath =
Persistence.FileSystemWorkspaceBinding.fileSystemPath(this._project.id()) + '/' + this._folderPath;
const hasMappedFiles = Persistence.persistence.filePathHasBindings(absoluteFileSystemPath);
@@ -1521,8 +1605,9 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
* @override
*/
wasPopulated() {
- if (!this._treeElement || this._treeElement._node !== this)
+ if (!this._treeElement || this._treeElement._node !== this) {
return;
+ }
this._addChildrenRecursive();
}
@@ -1531,8 +1616,9 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
for (let i = 0; i < children.length; ++i) {
const child = children[i];
this.didAddChild(child);
- if (child instanceof Sources.NavigatorFolderTreeNode)
+ if (child instanceof Sources.NavigatorFolderTreeNode) {
child._addChildrenRecursive();
+ }
}
}
@@ -1549,8 +1635,9 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
return node._title;
}
- if (!this._treeElement)
+ if (!this._treeElement) {
return;
+ }
let children = this.children();
@@ -1563,8 +1650,9 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
}
let oldNode;
- if (children.length === 2)
+ if (children.length === 2) {
oldNode = children[0] !== node ? children[0] : children[1];
+ }
if (oldNode && oldNode._isMerged) {
delete oldNode._isMerged;
const mergedToNodes = [];
@@ -1596,19 +1684,22 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
}
const oldTreeElement = this._treeElement;
const treeElement = this._createTreeElement(titleText, this);
- for (let i = 0; i < mergedToNodes.length; ++i)
+ for (let i = 0; i < mergedToNodes.length; ++i) {
mergedToNodes[i]._treeElement = treeElement;
+ }
oldTreeElement.parent.appendChild(treeElement);
oldTreeElement.setNode(nodes[nodes.length - 1]);
oldTreeElement.title = nodes.map(titleForNode).join('/');
oldTreeElement.parent.removeChild(oldTreeElement);
this._treeElement.appendChild(oldTreeElement);
- if (oldTreeElement.expanded)
+ if (oldTreeElement.expanded) {
treeElement.expand();
+ }
}
- if (this.isPopulated())
+ if (this.isPopulated()) {
this._treeElement.appendChild(node.treeNode());
+ }
}
/**
@@ -1616,8 +1707,9 @@ Sources.NavigatorFolderTreeNode = class extends Sources.NavigatorTreeNode {
* @param {!Sources.NavigatorTreeNode} node
*/
willRemoveChild(node) {
- if (node._isMerged || !this.isPopulated())
+ if (node._isMerged || !this.isPopulated()) {
return;
+ }
this._treeElement.removeChild(node._treeElement);
}
};
@@ -1653,8 +1745,9 @@ Sources.NavigatorGroupTreeNode = class extends Sources.NavigatorTreeNode {
* @return {!UI.TreeElement}
*/
treeNode() {
- if (this._treeElement)
+ if (this._treeElement) {
return this._treeElement;
+ }
this._treeElement =
new Sources.NavigatorFolderTreeElement(this._navigatorView, this._type, this._title, this._hoverCallback);
this._treeElement.setNode(this);
@@ -1669,20 +1762,24 @@ Sources.NavigatorGroupTreeNode = class extends Sources.NavigatorTreeNode {
}
updateTitle() {
- if (!this._treeElement || this._project.type() !== Workspace.projectTypes.FileSystem)
+ if (!this._treeElement || this._project.type() !== Workspace.projectTypes.FileSystem) {
return;
+ }
const fileSystemPath = Persistence.FileSystemWorkspaceBinding.fileSystemPath(this._project.id());
const wasActive = this._treeElement.listItemElement.classList.contains('has-mapped-files');
const isActive = Persistence.persistence.filePathHasBindings(fileSystemPath);
- if (wasActive === isActive)
+ if (wasActive === isActive) {
return;
+ }
this._treeElement.listItemElement.classList.toggle('has-mapped-files', isActive);
- if (this._treeElement.childrenListElement.hasFocus())
+ if (this._treeElement.childrenListElement.hasFocus()) {
return;
- if (isActive)
+ }
+ if (isActive) {
this._treeElement.expand();
- else
+ } else {
this._treeElement.collapse();
+ }
}
/**
@@ -1691,7 +1788,8 @@ Sources.NavigatorGroupTreeNode = class extends Sources.NavigatorTreeNode {
*/
setTitle(title) {
this._title = title;
- if (this._treeElement)
+ if (this._treeElement) {
this._treeElement.title = this._title;
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/OpenFileQuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/OpenFileQuickOpen.js
index 39dfe708c2a..0afe84f776c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/OpenFileQuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/OpenFileQuickOpen.js
@@ -22,12 +22,14 @@ Sources.OpenFileQuickOpen = class extends Sources.FilteredUISourceCodeListProvid
uiSourceCodeSelected(uiSourceCode, lineNumber, columnNumber) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.SelectFileFromFilePicker);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
- if (typeof lineNumber === 'number')
+ }
+ if (typeof lineNumber === 'number') {
Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
- else
+ } else {
Common.Revealer.reveal(uiSourceCode);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/OutlineQuickOpen.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/OutlineQuickOpen.js
index f5a525c3be3..ac5c1495b30 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/OutlineQuickOpen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/OutlineQuickOpen.js
@@ -63,8 +63,9 @@ Sources.OutlineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
itemScoreAt(itemIndex, query) {
const item = this._items[itemIndex];
const methodName = query.split('(')[0];
- if (methodName.toLowerCase() === item.title.toLowerCase())
+ if (methodName.toLowerCase() === item.title.toLowerCase()) {
return 1 / (1 + item.line);
+ }
return -item.line - 1;
}
@@ -88,14 +89,17 @@ Sources.OutlineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
* @param {string} promptValue
*/
selectItem(itemIndex, promptValue) {
- if (itemIndex === null)
+ if (itemIndex === null) {
return;
+ }
const uiSourceCode = this._currentUISourceCode();
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
const lineNumber = this._items[itemIndex].line;
- if (!isNaN(lineNumber) && lineNumber >= 0)
+ if (!isNaN(lineNumber) && lineNumber >= 0) {
Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, this._items[itemIndex].column));
+ }
}
@@ -104,8 +108,9 @@ Sources.OutlineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
*/
_currentUISourceCode() {
const sourcesView = UI.context.flavor(Sources.SourcesView);
- if (!sourcesView)
+ if (!sourcesView) {
return null;
+ }
return sourcesView.currentUISourceCode();
}
@@ -114,10 +119,12 @@ Sources.OutlineQuickOpen = class extends QuickOpen.FilteredListWidget.Provider {
* @return {string}
*/
notFoundText() {
- if (!this._currentUISourceCode())
+ if (!this._currentUISourceCode()) {
return Common.UIString('No file selected.');
- if (!this._active)
+ }
+ if (!this._active) {
return Common.UIString('Open a JavaScript or CSS file to see symbols');
+ }
return Common.UIString('No results found');
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScopeChainSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScopeChainSidebarPane.js
index f1ac92297cc..0c333e638c6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScopeChainSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScopeChainSidebarPane.js
@@ -79,8 +79,9 @@ Sources.ScopeChainSidebarPane = class extends UI.VBox {
case Protocol.Debugger.ScopeType.Local:
foundLocalScope = true;
emptyPlaceholder = Common.UIString('No variables');
- if (thisObject)
+ if (thisObject) {
extraProperties.push(new SDK.RemoteObjectProperty('this', thisObject));
+ }
if (i === 0) {
const exception = details.exception();
if (exception) {
@@ -98,17 +99,19 @@ Sources.ScopeChainSidebarPane = class extends UI.VBox {
break;
case Protocol.Debugger.ScopeType.Closure:
const scopeName = scope.name();
- if (scopeName)
+ if (scopeName) {
title = Common.UIString('Closure (%s)', UI.beautifyFunctionName(scopeName));
- else
+ } else {
title = Common.UIString('Closure');
+ }
emptyPlaceholder = Common.UIString('No variables');
break;
}
let subtitle = scope.description();
- if (!title || title === subtitle)
+ if (!title || title === subtitle) {
subtitle = undefined;
+ }
const titleElement = createElementWithClass('div', 'scope-chain-sidebar-pane-section-header');
titleElement.createChild('div', 'scope-chain-sidebar-pane-section-subtitle').textContent = subtitle;
@@ -119,10 +122,11 @@ Sources.ScopeChainSidebarPane = class extends UI.VBox {
true, extraProperties);
this._expandController.watchSection(title + (subtitle ? ':' + subtitle : ''), section);
- if (scope.type() === Protocol.Debugger.ScopeType.Global)
+ if (scope.type() === Protocol.Debugger.ScopeType.Global) {
section.objectTreeElement().collapse();
- else if (!foundLocalScope || scope.type() === Protocol.Debugger.ScopeType.Local)
+ } else if (!foundLocalScope || scope.type() === Protocol.Debugger.ScopeType.Local) {
section.objectTreeElement().expand();
+ }
section.element.classList.add('scope-chain-sidebar-pane-section');
this.contentElement.appendChild(section.element);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptFormatterEditorAction.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptFormatterEditorAction.js
index 9706b77884b..fc9a168531a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptFormatterEditorAction.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptFormatterEditorAction.js
@@ -20,8 +20,9 @@ Sources.ScriptFormatterEditorAction = class {
this._updateButton(uiSourceCode);
if (this._isFormatableScript(uiSourceCode) && this._pathsToFormatOnLoad.has(uiSourceCode.url()) &&
- !Sources.sourceFormatter.hasFormatted(uiSourceCode))
+ !Sources.sourceFormatter.hasFormatted(uiSourceCode)) {
this._showFormatted(uiSourceCode);
+ }
}
/**
@@ -31,11 +32,13 @@ Sources.ScriptFormatterEditorAction = class {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data.uiSourceCode);
const wasSelected = /** @type {boolean} */ (event.data.wasSelected);
- if (wasSelected)
+ if (wasSelected) {
this._updateButton(null);
+ }
const original = Sources.sourceFormatter.discardFormattedUISourceCode(uiSourceCode);
- if (original)
+ if (original) {
this._pathsToFormatOnLoad.delete(original.url());
+ }
}
/**
@@ -51,8 +54,9 @@ Sources.ScriptFormatterEditorAction = class {
* @return {!UI.ToolbarButton}
*/
button(sourcesView) {
- if (this._button)
+ if (this._button) {
return this._button;
+ }
this._sourcesView = sourcesView;
this._sourcesView.addEventListener(Sources.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
@@ -70,14 +74,18 @@ Sources.ScriptFormatterEditorAction = class {
* @return {boolean}
*/
_isFormatableScript(uiSourceCode) {
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return false;
- if (uiSourceCode.project().canSetFileContent())
+ }
+ if (uiSourceCode.project().canSetFileContent()) {
return false;
- if (uiSourceCode.project().type() === Workspace.projectTypes.Formatter)
+ }
+ if (uiSourceCode.project().type() === Workspace.projectTypes.Formatter) {
return false;
- if (Persistence.persistence.binding(uiSourceCode))
+ }
+ if (Persistence.persistence.binding(uiSourceCode)) {
return false;
+ }
return uiSourceCode.contentType().hasScripts();
}
@@ -86,8 +94,9 @@ Sources.ScriptFormatterEditorAction = class {
*/
_toggleFormatScriptSource(event) {
const uiSourceCode = this._sourcesView.currentUISourceCode();
- if (!this._isFormatableScript(uiSourceCode))
+ if (!this._isFormatableScript(uiSourceCode)) {
return;
+ }
this._pathsToFormatOnLoad.add(uiSourceCode.url());
this._showFormatted(uiSourceCode);
}
@@ -97,8 +106,9 @@ Sources.ScriptFormatterEditorAction = class {
*/
async _showFormatted(uiSourceCode) {
const formatData = await Sources.sourceFormatter.format(uiSourceCode);
- if (uiSourceCode !== this._sourcesView.currentUISourceCode())
+ if (uiSourceCode !== this._sourcesView.currentUISourceCode()) {
return;
+ }
const sourceFrame = this._sourcesView.viewForFile(uiSourceCode);
let start = [0, 0];
if (sourceFrame) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptOriginPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptOriginPlugin.js
index 706d4f29c96..48132dfabae 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptOriginPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/ScriptOriginPlugin.js
@@ -35,8 +35,9 @@ Sources.ScriptOriginPlugin = class extends Sources.UISourceCodeFrame.Plugin {
// Handle anonymous scripts with an originStackTrace.
const script = Sources.ScriptOriginPlugin._script(this._uiSourceCode);
- if (!script || !script.originStackTrace)
+ if (!script || !script.originStackTrace) {
return [];
+ }
const link = Sources.ScriptOriginPlugin._linkifier.linkifyStackTraceTopFrame(
script.debuggerModel.target(), script.originStackTrace);
return [new UI.ToolbarItem(link)];
@@ -50,8 +51,9 @@ Sources.ScriptOriginPlugin = class extends Sources.UISourceCodeFrame.Plugin {
const locations = Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(uiSourceCode, 0, 0);
for (const location of locations) {
const script = location.script();
- if (script.originStackTrace)
+ if (script && script.originStackTrace) {
return script;
+ }
}
return null;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SearchSourcesView.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SearchSourcesView.js
index a6c0a3cc443..c27d3bf704c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SearchSourcesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SearchSourcesView.js
@@ -54,8 +54,9 @@ Sources.SearchSourcesView.ActionDelegate = class {
_showSearch() {
const selection = UI.inspectorView.element.window().getSelection();
let queryCandidate = '';
- if (selection.rangeCount)
+ if (selection.rangeCount) {
queryCandidate = selection.toString().replace(/\r?\n.*/, '');
+ }
return Sources.SearchSourcesView.openSearch(queryCandidate);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SimpleHistoryManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SimpleHistoryManager.js
index eb1ca5627fe..8cd47747c94 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SimpleHistoryManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SimpleHistoryManager.js
@@ -74,15 +74,17 @@ Sources.SimpleHistoryManager = class {
* @param {function(!Sources.HistoryEntry):boolean} filterOutCallback
*/
filterOut(filterOutCallback) {
- if (this.readOnly())
+ if (this.readOnly()) {
return;
+ }
const filteredEntries = [];
let removedBeforeActiveEntry = 0;
for (let i = 0; i < this._entries.length; ++i) {
- if (!filterOutCallback(this._entries[i]))
+ if (!filterOutCallback(this._entries[i])) {
filteredEntries.push(this._entries[i]);
- else if (i <= this._activeEntryIndex)
+ } else if (i <= this._activeEntryIndex) {
++removedBeforeActiveEntry;
+ }
}
this._entries = filteredEntries;
this._activeEntryIndex = Math.max(0, this._activeEntryIndex - removedBeforeActiveEntry);
@@ -106,13 +108,16 @@ Sources.SimpleHistoryManager = class {
* @param {!Sources.HistoryEntry} entry
*/
push(entry) {
- if (this.readOnly())
+ if (this.readOnly()) {
return;
- if (!this.empty())
+ }
+ if (!this.empty()) {
this._entries.splice(this._activeEntryIndex + 1);
+ }
this._entries.push(entry);
- if (this._entries.length > this._historyDepth)
+ if (this._entries.length > this._historyDepth) {
this._entries.shift();
+ }
this._activeEntryIndex = this._entries.length - 1;
}
@@ -120,14 +125,17 @@ Sources.SimpleHistoryManager = class {
* @return {boolean}
*/
rollback() {
- if (this.empty())
+ if (this.empty()) {
return false;
+ }
let revealIndex = this._activeEntryIndex - 1;
- while (revealIndex >= 0 && !this._entries[revealIndex].valid())
+ while (revealIndex >= 0 && !this._entries[revealIndex].valid()) {
--revealIndex;
- if (revealIndex < 0)
+ }
+ if (revealIndex < 0) {
return false;
+ }
this.readOnlyLock();
this._entries[revealIndex].reveal();
@@ -143,10 +151,12 @@ Sources.SimpleHistoryManager = class {
rollover() {
let revealIndex = this._activeEntryIndex + 1;
- while (revealIndex < this._entries.length && !this._entries[revealIndex].valid())
+ while (revealIndex < this._entries.length && !this._entries[revealIndex].valid()) {
++revealIndex;
- if (revealIndex >= this._entries.length)
+ }
+ if (revealIndex >= this._entries.length) {
return false;
+ }
this.readOnlyLock();
this._entries[revealIndex].reveal();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceFormatter.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceFormatter.js
index 86e202c3860..dca9ea6d51d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceFormatter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceFormatter.js
@@ -50,8 +50,9 @@ Sources.SourceFormatter = class {
_onUISourceCodeRemoved(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
const cacheEntry = this._formattedSourceCodes.get(uiSourceCode);
- if (cacheEntry && cacheEntry.formatData)
+ if (cacheEntry && cacheEntry.formatData) {
this._discardFormatData(cacheEntry.formatData);
+ }
this._formattedSourceCodes.remove(uiSourceCode);
}
@@ -61,8 +62,9 @@ Sources.SourceFormatter = class {
*/
discardFormattedUISourceCode(formattedUISourceCode) {
const formatData = Sources.SourceFormatData._for(formattedUISourceCode);
- if (!formatData)
+ if (!formatData) {
return null;
+ }
this._discardFormatData(formatData);
this._formattedSourceCodes.remove(formatData.originalSourceCode);
return formatData.originalSourceCode;
@@ -92,15 +94,16 @@ Sources.SourceFormatter = class {
*/
async format(uiSourceCode) {
const cacheEntry = this._formattedSourceCodes.get(uiSourceCode);
- if (cacheEntry)
+ if (cacheEntry) {
return cacheEntry.promise;
+ }
let fulfillFormatPromise;
const resultPromise = new Promise(fulfill => {
fulfillFormatPromise = fulfill;
});
this._formattedSourceCodes.set(uiSourceCode, {promise: resultPromise, formatData: null});
- const content = await uiSourceCode.requestContent();
+ const {content} = await uiSourceCode.requestContent();
// ------------ ASYNC ------------
Formatter.Formatter.format(
uiSourceCode.contentType(), uiSourceCode.mimeType(), content || '', formatDone.bind(this));
@@ -113,8 +116,9 @@ Sources.SourceFormatter = class {
*/
function formatDone(formattedContent, formatterMapping) {
const cacheEntry = this._formattedSourceCodes.get(uiSourceCode);
- if (!cacheEntry || cacheEntry.promise !== resultPromise)
+ if (!cacheEntry || cacheEntry.promise !== resultPromise) {
return;
+ }
let formattedURL;
let count = 0;
let suffix = '';
@@ -163,8 +167,9 @@ Sources.SourceFormatter.ScriptMapping = class {
rawLocationToUILocation(rawLocation) {
const script = rawLocation.script();
const formatData = script && Sources.SourceFormatData._for(script);
- if (!formatData)
+ if (!formatData) {
return null;
+ }
const lineNumber = rawLocation.lineNumber;
const columnNumber = rawLocation.columnNumber || 0;
const formattedLocation = formatData.mapping.originalToFormatted(lineNumber, columnNumber);
@@ -180,14 +185,13 @@ Sources.SourceFormatter.ScriptMapping = class {
*/
uiLocationToRawLocations(uiSourceCode, lineNumber, columnNumber) {
const formatData = Sources.SourceFormatData._for(uiSourceCode);
- if (!formatData)
- return [];
- const originalLocation = formatData.mapping.formattedToOriginal(lineNumber, columnNumber);
- const scripts = this._scriptsForUISourceCode(formatData.originalSourceCode);
- if (!scripts.length)
+ if (!formatData) {
return [];
- return scripts.map(
- script => script.debuggerModel.createRawLocation(script, originalLocation[0], originalLocation[1]));
+ }
+ const [originalLine, originalColumn] = formatData.mapping.formattedToOriginal(lineNumber, columnNumber);
+ const scripts = this._scriptsForUISourceCode(formatData.originalSourceCode)
+ .filter(script => script.containsLocation(originalLine, originalColumn));
+ return scripts.map(script => script.debuggerModel.createRawLocation(script, originalLine, originalColumn));
}
/**
@@ -196,17 +200,21 @@ Sources.SourceFormatter.ScriptMapping = class {
*/
_setSourceMappingEnabled(formatData, enabled) {
const scripts = this._scriptsForUISourceCode(formatData.originalSourceCode);
- if (!scripts.length)
+ if (!scripts.length) {
return;
+ }
if (enabled) {
- for (const script of scripts)
+ for (const script of scripts) {
script[Sources.SourceFormatData._formatDataSymbol] = formatData;
+ }
} else {
- for (const script of scripts)
+ for (const script of scripts) {
delete script[Sources.SourceFormatData._formatDataSymbol];
+ }
}
- for (const script of scripts)
+ for (const script of scripts) {
Bindings.debuggerWorkspaceBinding.updateLocations(script);
+ }
}
/**
@@ -225,7 +233,7 @@ Sources.SourceFormatter.ScriptMapping = class {
}
if (uiSourceCode.contentType().isScript()) {
const rawLocations = Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(uiSourceCode, 0, 0);
- return rawLocations.map(location => location.script());
+ return rawLocations.map(location => location.script()).filter(script => !!script);
}
return [];
}
@@ -248,8 +256,9 @@ Sources.SourceFormatter.StyleMapping = class {
rawLocationToUILocation(rawLocation) {
const styleHeader = rawLocation.header();
const formatData = styleHeader && Sources.SourceFormatData._for(styleHeader);
- if (!formatData)
+ if (!formatData) {
return null;
+ }
const formattedLocation =
formatData.mapping.originalToFormatted(rawLocation.lineNumber, rawLocation.columnNumber || 0);
return formatData.formattedSourceCode.uiLocation(formattedLocation[0], formattedLocation[1]);
@@ -262,11 +271,14 @@ Sources.SourceFormatter.StyleMapping = class {
*/
uiLocationToRawLocations(uiLocation) {
const formatData = Sources.SourceFormatData._for(uiLocation.uiSourceCode);
- if (!formatData)
+ if (!formatData) {
return [];
- const originalLocation = formatData.mapping.formattedToOriginal(uiLocation.lineNumber, uiLocation.columnNumber);
- const headers = formatData.originalSourceCode[this._headersSymbol];
- return headers.map(header => new SDK.CSSLocation(header, originalLocation[0], originalLocation[1]));
+ }
+ const [originalLine, originalColumn] =
+ formatData.mapping.formattedToOriginal(uiLocation.lineNumber, uiLocation.columnNumber);
+ const headers = formatData.originalSourceCode[this._headersSymbol].filter(
+ header => header.containsLocation(originalLine, originalColumn));
+ return headers.map(header => new SDK.CSSLocation(header, originalLine, originalColumn));
}
/**
@@ -275,10 +287,7 @@ Sources.SourceFormatter.StyleMapping = class {
*/
_setSourceMappingEnabled(formatData, enable) {
const original = formatData.originalSourceCode;
- const rawLocations = Bindings.cssWorkspaceBinding.uiLocationToRawLocations(original.uiLocation(0, 0));
- const headers = rawLocations.map(rawLocation => rawLocation.header()).filter(header => !!header);
- if (!headers.length)
- return;
+ const headers = this._headersForUISourceCode(original);
if (enable) {
original[this._headersSymbol] = headers;
headers.forEach(header => header[Sources.SourceFormatData._formatDataSymbol] = formatData);
@@ -288,6 +297,25 @@ Sources.SourceFormatter.StyleMapping = class {
}
headers.forEach(header => Bindings.cssWorkspaceBinding.updateLocations(header));
}
+
+ /**
+ * @param {!Workspace.UISourceCode} uiSourceCode
+ * @return {!Array<!SDK.CSSStyleSheetHeader>}
+ */
+ _headersForUISourceCode(uiSourceCode) {
+ if (uiSourceCode.contentType() === Common.resourceTypes.Document) {
+ const target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode);
+ const cssModel = target && target.model(SDK.CSSModel);
+ if (cssModel) {
+ return cssModel.headersForSourceURL(uiSourceCode.url())
+ .filter(header => header.isInline && !header.hasSourceURL);
+ }
+ } else if (uiSourceCode.contentType().isStyleSheet()) {
+ const rawLocations = Bindings.cssWorkspaceBinding.uiLocationToRawLocations(uiSourceCode.uiLocation(0, 0));
+ return rawLocations.map(rawLocation => rawLocation.header()).filter(header => !!header);
+ }
+ return [];
+ }
};
Sources.sourceFormatter = new Sources.SourceFormatter();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceMapNamesResolver.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceMapNamesResolver.js
index cfd256f079b..a7812a4f115 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceMapNamesResolver.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourceMapNamesResolver.js
@@ -32,20 +32,23 @@ Sources.SourceMapNamesResolver._scopeIdentifiers = function(scope) {
if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocation || !endLocation ||
!startLocation.script() || !startLocation.script().sourceMapURL ||
- (startLocation.script() !== endLocation.script()))
+ (startLocation.script() !== endLocation.script())) {
return Promise.resolve(/** @type {!Array<!Sources.SourceMapNamesResolver.Identifier>}*/ ([]));
+ }
const script = startLocation.script();
return script.requestContent().then(onContent);
/**
- * @param {?string} content
+ * @param {!Common.DeferredContent} deferredContent
* @return {!Promise<!Array<!Sources.SourceMapNamesResolver.Identifier>>}
*/
- function onContent(content) {
- if (!content)
+ function onContent(deferredContent) {
+ if (!deferredContent.content) {
return Promise.resolve(/** @type {!Array<!Sources.SourceMapNamesResolver.Identifier>}*/ ([]));
+ }
+ const content = deferredContent.content;
const text = new TextUtils.Text(content);
const scopeRange = new TextUtils.TextRange(
startLocation.lineNumber, startLocation.columnNumber, endLocation.lineNumber, endLocation.columnNumber);
@@ -69,8 +72,9 @@ Sources.SourceMapNamesResolver._scopeIdentifiers = function(scope) {
const cursor = new TextUtils.TextCursor(text.lineEndings());
for (let i = 0; i < identifiers.length; ++i) {
const id = identifiers[i];
- if (id.offset < prefix.length)
+ if (id.offset < prefix.length) {
continue;
+ }
const start = scopeStart + id.offset - prefix.length;
cursor.resetTo(start);
result.push(new Sources.SourceMapNamesResolver.Identifier(id.name, cursor.lineNumber(), cursor.columnNumber()));
@@ -85,13 +89,15 @@ Sources.SourceMapNamesResolver._scopeIdentifiers = function(scope) {
*/
Sources.SourceMapNamesResolver._resolveScope = function(scope) {
let identifiersPromise = scope[Sources.SourceMapNamesResolver._cachedIdentifiersSymbol];
- if (identifiersPromise)
+ if (identifiersPromise) {
return identifiersPromise;
+ }
const script = scope.callFrame().script;
const sourceMap = Bindings.debuggerWorkspaceBinding.sourceMapForScript(script);
- if (!sourceMap)
+ if (!sourceMap) {
return Promise.resolve(new Map());
+ }
/** @type {!Map<string, !TextUtils.Text>} */
const textCache = new Map();
@@ -109,16 +115,18 @@ Sources.SourceMapNamesResolver._resolveScope = function(scope) {
for (let i = 0; i < identifiers.length; ++i) {
const id = identifiers[i];
const entry = sourceMap.findEntry(id.lineNumber, id.columnNumber);
- if (entry && entry.name)
+ if (entry && entry.name) {
namesMapping.set(id.name, entry.name);
+ }
}
// Resolve missing identifier names from sourcemap ranges.
const promises = [];
for (let i = 0; i < identifiers.length; ++i) {
const id = identifiers[i];
- if (namesMapping.has(id.name))
+ if (namesMapping.has(id.name)) {
continue;
+ }
const promise = resolveSourceName(id).then(onSourceNameResolved.bind(null, namesMapping, id));
promises.push(promise);
}
@@ -133,8 +141,9 @@ Sources.SourceMapNamesResolver._resolveScope = function(scope) {
* @param {?string} sourceName
*/
function onSourceNameResolved(namesMapping, id, sourceName) {
- if (!sourceName)
+ if (!sourceName) {
return;
+ }
namesMapping.set(id.name, sourceName);
}
@@ -147,17 +156,22 @@ Sources.SourceMapNamesResolver._resolveScope = function(scope) {
const endEntry = sourceMap.findEntry(id.lineNumber, id.columnNumber + id.name.length);
if (!startEntry || !endEntry || !startEntry.sourceURL || startEntry.sourceURL !== endEntry.sourceURL ||
!startEntry.sourceLineNumber || !startEntry.sourceColumnNumber || !endEntry.sourceLineNumber ||
- !endEntry.sourceColumnNumber)
+ !endEntry.sourceColumnNumber) {
return Promise.resolve(/** @type {?string} */ (null));
+ }
const sourceTextRange = new TextUtils.TextRange(
startEntry.sourceLineNumber, startEntry.sourceColumnNumber, endEntry.sourceLineNumber,
endEntry.sourceColumnNumber);
const uiSourceCode = Bindings.debuggerWorkspaceBinding.uiSourceCodeForSourceMapSourceURL(
script.debuggerModel, startEntry.sourceURL, script.isContentScript());
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return Promise.resolve(/** @type {?string} */ (null));
+ }
- return uiSourceCode.requestContent().then(onSourceContent.bind(null, sourceTextRange));
+ return uiSourceCode.requestContent().then(deferredContent => {
+ const content = deferredContent.content;
+ return onSourceContent(sourceTextRange, content);
+ });
}
/**
@@ -166,8 +180,9 @@ Sources.SourceMapNamesResolver._resolveScope = function(scope) {
* @return {?string}
*/
function onSourceContent(sourceTextRange, content) {
- if (!content)
+ if (!content) {
return null;
+ }
let text = textCache.get(content);
if (!text) {
text = new TextUtils.Text(content);
@@ -186,13 +201,15 @@ Sources.SourceMapNamesResolver._scopeResolvedForTest = function() {};
*/
Sources.SourceMapNamesResolver._allVariablesInCallFrame = function(callFrame) {
const cached = callFrame[Sources.SourceMapNamesResolver._cachedMapSymbol];
- if (cached)
+ if (cached) {
return Promise.resolve(cached);
+ }
const promises = [];
const scopeChain = callFrame.scopeChain();
- for (let i = 0; i < scopeChain.length; ++i)
+ for (let i = 0; i < scopeChain.length; ++i) {
promises.push(Sources.SourceMapNamesResolver._resolveScope(scopeChain[i]));
+ }
return Promise.all(promises).then(mergeVariables);
@@ -205,8 +222,9 @@ Sources.SourceMapNamesResolver._allVariablesInCallFrame = function(callFrame) {
for (const map of nameMappings) {
for (const compiledName of map.keys()) {
const originalName = map.get(compiledName);
- if (!reverseMapping.has(originalName))
+ if (!reverseMapping.has(originalName)) {
reverseMapping.set(originalName, compiledName);
+ }
}
}
callFrame[Sources.SourceMapNamesResolver._cachedMapSymbol] = reverseMapping;
@@ -225,8 +243,9 @@ Sources.SourceMapNamesResolver._allVariablesInCallFrame = function(callFrame) {
*/
Sources.SourceMapNamesResolver.resolveExpression = function(
callFrame, originalText, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber) {
- if (!uiSourceCode.contentType().isFromSourceMap())
+ if (!uiSourceCode.contentType().isFromSourceMap()) {
return Promise.resolve('');
+ }
return Sources.SourceMapNamesResolver._allVariablesInCallFrame(callFrame).then(
reverseMapping => findCompiledName(callFrame.debuggerModel, reverseMapping));
@@ -237,8 +256,9 @@ Sources.SourceMapNamesResolver.resolveExpression = function(
* @return {!Promise<string>}
*/
function findCompiledName(debuggerModel, reverseMapping) {
- if (reverseMapping.has(originalText))
+ if (reverseMapping.has(originalText)) {
return Promise.resolve(reverseMapping.get(originalText) || '');
+ }
return Sources.SourceMapNamesResolver._resolveExpression(
debuggerModel, uiSourceCode, lineNumber, startColumnNumber, endColumnNumber);
@@ -258,32 +278,38 @@ Sources.SourceMapNamesResolver._resolveExpression = function(
const rawLocations =
Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(uiSourceCode, lineNumber, startColumnNumber);
const rawLocation = rawLocations.find(location => location.debuggerModel === debuggerModel);
- if (!rawLocation)
+ if (!rawLocation) {
return Promise.resolve('');
+ }
const script = rawLocation.script();
- if (!script)
+ if (!script) {
return Promise.resolve('');
- const sourceMap = Bindings.debuggerWorkspaceBinding.sourceMapForScript(script);
- if (!sourceMap)
+ }
+ const sourceMap = /** @type {!SDK.TextSourceMap} */ (Bindings.debuggerWorkspaceBinding.sourceMapForScript(script));
+ if (!sourceMap) {
return Promise.resolve('');
+ }
return script.requestContent().then(onContent);
/**
- * @param {?string} content
+ * @param {!Common.DeferredContent} deferredContent
* @return {!Promise<string>}
*/
- function onContent(content) {
- if (!content)
+ function onContent(deferredContent) {
+ const content = deferredContent.content;
+ if (!content) {
return Promise.resolve('');
+ }
const text = new TextUtils.Text(content);
const textRange = sourceMap.reverseMapTextRange(
uiSourceCode.url(), new TextUtils.TextRange(lineNumber, startColumnNumber, lineNumber, endColumnNumber));
const originalText = text.extract(textRange);
- if (!originalText)
+ if (!originalText) {
return Promise.resolve('');
+ }
return Formatter.formatterWorkerPool().evaluatableJavaScriptSubstring(originalText);
}
};
@@ -293,10 +319,12 @@ Sources.SourceMapNamesResolver._resolveExpression = function(
* @return {!Promise<?SDK.RemoteObject>}
*/
Sources.SourceMapNamesResolver.resolveThisObject = function(callFrame) {
- if (!callFrame)
+ if (!callFrame) {
return Promise.resolve(/** @type {?SDK.RemoteObject} */ (null));
- if (!callFrame.scopeChain().length)
+ }
+ if (!callFrame.scopeChain().length) {
return Promise.resolve(callFrame.thisObject());
+ }
return Sources.SourceMapNamesResolver._resolveScope(callFrame.scopeChain()[0]).then(onScopeResolved);
@@ -306,8 +334,9 @@ Sources.SourceMapNamesResolver.resolveThisObject = function(callFrame) {
*/
function onScopeResolved(namesMapping) {
const thisMappings = namesMapping.inverse().get('this');
- if (!thisMappings || thisMappings.size !== 1)
+ if (!thisMappings || thisMappings.size !== 1) {
return Promise.resolve(callFrame.thisObject());
+ }
const thisMapping = thisMappings.valuesArray()[0];
return callFrame
@@ -341,8 +370,9 @@ Sources.SourceMapNamesResolver.resolveScopeInObject = function(scope) {
if (scope.type() === Protocol.Debugger.ScopeType.Global || !startLocation || !endLocation ||
!startLocation.script() || !startLocation.script().sourceMapURL ||
- startLocation.script() !== endLocation.script())
+ startLocation.script() !== endLocation.script()) {
return scope.object();
+ }
return new Sources.SourceMapNamesResolver.RemoteObject(scope);
};
@@ -475,10 +505,11 @@ Sources.SourceMapNamesResolver.RemoteObject = class extends SDK.RemoteObject {
const namesMapping = await Sources.SourceMapNamesResolver._resolveScope(this._scope);
let name;
- if (typeof argumentName === 'string')
+ if (typeof argumentName === 'string') {
name = argumentName;
- else
+ } else {
name = /** @type {string} */ (argumentName.value);
+ }
let actualName = name;
for (const compiledName of namesMapping.keys()) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesNavigator.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesNavigator.js
index d229f381db2..0e8c052077e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesNavigator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesNavigator.js
@@ -52,14 +52,17 @@ Sources.NetworkNavigatorView = class extends Sources.NavigatorView {
*/
_inspectedURLChanged(event) {
const mainTarget = SDK.targetManager.mainTarget();
- if (event.data !== mainTarget)
+ if (event.data !== mainTarget) {
return;
+ }
const inspectedURL = mainTarget && mainTarget.inspectedURL();
- if (!inspectedURL)
+ if (!inspectedURL) {
return;
+ }
for (const uiSourceCode of this.workspace().uiSourceCodes()) {
- if (this.acceptProject(uiSourceCode.project()) && uiSourceCode.url() === inspectedURL)
+ if (this.acceptProject(uiSourceCode.project()) && uiSourceCode.url() === inspectedURL) {
this.revealUISourceCode(uiSourceCode, true);
+ }
}
}
@@ -70,10 +73,12 @@ Sources.NetworkNavigatorView = class extends Sources.NavigatorView {
uiSourceCodeAdded(uiSourceCode) {
const mainTarget = SDK.targetManager.mainTarget();
const inspectedURL = mainTarget && mainTarget.inspectedURL();
- if (!inspectedURL)
+ if (!inspectedURL) {
return;
- if (uiSourceCode.url() === inspectedURL)
+ }
+ if (uiSourceCode.url() === inspectedURL) {
this.revealUISourceCode(uiSourceCode, true);
+ }
}
};
@@ -92,8 +97,9 @@ Sources.FilesNavigatorView = class extends Sources.NavigatorView {
const toolbar = new UI.Toolbar('navigator-toolbar');
toolbar.appendItemsAtLocation('files-navigator-toolbar').then(() => {
- if (!toolbar.empty())
+ if (!toolbar.empty()) {
this.contentElement.insertBefore(toolbar.element, this.contentElement.firstChild);
+ }
});
}
@@ -146,16 +152,18 @@ Sources.OverridesNavigatorView = class extends Sources.NavigatorView {
_onProjectAddOrRemoved(event) {
const project = /** @type {!Workspace.Project} */ (event.data);
if (project && project.type() === Workspace.projectTypes.FileSystem &&
- Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides')
+ Persistence.FileSystemWorkspaceBinding.fileSystemType(project) !== 'overrides') {
return;
+ }
this._updateUI();
}
_updateProjectAndUI() {
this.reset();
const project = Persistence.networkPersistenceManager.project();
- if (project)
+ if (project) {
this.tryAddProject(project);
+ }
this._updateUI();
}
@@ -183,8 +191,9 @@ Sources.OverridesNavigatorView = class extends Sources.NavigatorView {
async _setupNewWorkspace() {
const fileSystem = await Persistence.isolatedFileSystemManager.addFileSystem('overrides');
- if (!fileSystem)
+ if (!fileSystem) {
return;
+ }
Common.settings.moduleSetting('persistenceNetworkOverridesEnabled').set(true);
}
@@ -282,8 +291,8 @@ Sources.SnippetsNavigatorView = class extends Sources.NavigatorView {
*/
async _handleSaveAs(uiSourceCode) {
uiSourceCode.commitWorkingCopy();
- const content = await uiSourceCode.requestContent();
- Workspace.fileManager.save(uiSourceCode.url(), content, true);
+ const {content} = await uiSourceCode.requestContent();
+ Workspace.fileManager.save(uiSourceCode.url(), content || '', true);
Workspace.fileManager.close(uiSourceCode.url());
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
index 9cd80f6ebcb..40d1e8236f1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
@@ -65,7 +65,6 @@ Sources.SourcesPanel = class extends UI.Panel {
const initialNavigatorWidth = 225;
this.editorView = new UI.SplitWidget(true, false, 'sourcesPanelNavigatorSplitViewState', initialNavigatorWidth);
this.editorView.enableShowModeSaving();
- this.editorView.element.tabIndex = 0;
this._splitWidget.setMainWidget(this.editorView);
// Create navigator tabbed pane with toolbar.
@@ -133,8 +132,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @return {!Sources.SourcesPanel}
*/
static instance() {
- if (Sources.SourcesPanel._instance)
+ if (Sources.SourcesPanel._instance) {
return Sources.SourcesPanel._instance;
+ }
return /** @type {!Sources.SourcesPanel} */ (self.runtime.sharedInstance(Sources.SourcesPanel));
}
@@ -146,16 +146,18 @@ Sources.SourcesPanel = class extends UI.Panel {
panel._sourcesView.rightToolbar().removeToolbarItems();
panel._sourcesView.bottomToolbar().removeToolbarItems();
const isInWrapper = Sources.SourcesPanel.WrapperView.isShowing() && !UI.inspectorView.isDrawerMinimized();
- if (panel._splitWidget.isVertical() || isInWrapper)
+ if (panel._splitWidget.isVertical() || isInWrapper) {
panel._splitWidget.uninstallResizer(panel._sourcesView.toolbarContainerElement());
- else
+ } else {
panel._splitWidget.installResizer(panel._sourcesView.toolbarContainerElement());
+ }
if (!isInWrapper) {
panel._sourcesView.leftToolbar().appendToolbarItem(panel._toggleNavigatorSidebarButton);
- if (panel._splitWidget.isVertical())
+ if (panel._splitWidget.isVertical()) {
panel._sourcesView.rightToolbar().appendToolbarItem(panel._toggleDebuggerSidebarButton);
- else
+ } else {
panel._sourcesView.bottomToolbar().appendToolbarItem(panel._toggleDebuggerSidebarButton);
+ }
}
}
@@ -188,11 +190,13 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {?SDK.Target} target
*/
_setTarget(target) {
- if (!target)
+ if (!target) {
return;
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return;
+ }
if (debuggerModel.isPaused()) {
this._showDebuggerPausedDetails(
@@ -252,20 +256,23 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
resolveLocation(locationName) {
if (locationName === 'sources.sidebar-top' || locationName === 'sources.sidebar-bottom' ||
- locationName === 'sources.sidebar-tabs')
+ locationName === 'sources.sidebar-tabs') {
return this._sidebarPaneStack;
- else
+ } else {
return this._navigatorTabbedLocation;
+ }
}
/**
* @return {boolean}
*/
_ensureSourcesViewVisible() {
- if (Sources.SourcesPanel.WrapperView.isShowing())
+ if (Sources.SourcesPanel.WrapperView.isShowing()) {
return true;
- if (!UI.inspectorView.canSelectPanel('sources'))
+ }
+ if (!UI.inspectorView.canSelectPanel('sources')) {
return false;
+ }
UI.viewManager.showView('sources');
return true;
}
@@ -274,8 +281,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @override
*/
onResize() {
- if (Common.moduleSetting('sidebarPosition').get() === 'auto')
- this.element.window().requestAnimationFrame(this._updateSidebarPosition.bind(this)); // Do not force layout.
+ if (Common.moduleSetting('sidebarPosition').get() === 'auto') {
+ this.element.window().requestAnimationFrame(this._updateSidebarPosition.bind(this));
+ } // Do not force layout.
}
/**
@@ -292,13 +300,15 @@ Sources.SourcesPanel = class extends UI.Panel {
_debuggerPaused(event) {
const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
const details = debuggerModel.debuggerPausedDetails();
- if (!this._paused)
+ if (!this._paused) {
this._setAsCurrentPanel();
+ }
- if (UI.context.flavor(SDK.Target) === debuggerModel.target())
+ if (UI.context.flavor(SDK.Target) === debuggerModel.target()) {
this._showDebuggerPausedDetails(/** @type {!SDK.DebuggerPausedDetails} */ (details));
- else if (!this._paused)
+ } else if (!this._paused) {
UI.context.setFlavor(SDK.Target, debuggerModel.target());
+ }
}
/**
@@ -311,7 +321,7 @@ Sources.SourcesPanel = class extends UI.Panel {
this._toggleDebuggerSidebarButton.setEnabled(false);
this._revealDebuggerSidebar();
window.focus();
- InspectorFrontendHost.bringToFront();
+ Host.InspectorFrontendHost.bringToFront();
}
/**
@@ -319,8 +329,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_debuggerResumed(debuggerModel) {
const target = debuggerModel.target();
- if (UI.context.flavor(SDK.Target) !== target)
+ if (UI.context.flavor(SDK.Target) !== target) {
return;
+ }
this._paused = false;
this._clearInterface();
this._toggleDebuggerSidebarButton.setEnabled(true);
@@ -332,8 +343,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_debuggerWasEnabled(event) {
const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
- if (UI.context.flavor(SDK.Target) !== debuggerModel.target())
+ if (UI.context.flavor(SDK.Target) !== debuggerModel.target()) {
return;
+ }
this._updateDebuggerButtonsAndStatus();
}
@@ -355,8 +367,9 @@ Sources.SourcesPanel = class extends UI.Panel {
if (omitFocus) {
const wrapperShowing =
Sources.SourcesPanel.WrapperView._instance && Sources.SourcesPanel.WrapperView._instance.isShowing();
- if (!this.isShowing() && !wrapperShowing)
+ if (!this.isShowing() && !wrapperShowing) {
return;
+ }
} else {
this._showEditor();
}
@@ -364,8 +377,9 @@ Sources.SourcesPanel = class extends UI.Panel {
}
_showEditor() {
- if (Sources.SourcesPanel.WrapperView._instance && Sources.SourcesPanel.WrapperView._instance.isShowing())
+ if (Sources.SourcesPanel.WrapperView._instance && Sources.SourcesPanel.WrapperView._instance.isShowing()) {
return;
+ }
this._setAsCurrentPanel();
}
@@ -395,10 +409,11 @@ Sources.SourcesPanel = class extends UI.Panel {
const viewId = extensions[i].descriptor()['viewId'];
if (navigatorView.acceptProject(uiSourceCode.project())) {
navigatorView.revealUISourceCode(uiSourceCode, true);
- if (skipReveal)
+ if (skipReveal) {
this._navigatorTabbedLocation.tabbedPane().selectTab(viewId);
- else
+ } else {
UI.viewManager.showView(viewId);
+ }
}
}
}
@@ -431,10 +446,12 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_executionLineChanged(liveLocation) {
const uiLocation = liveLocation.uiLocation();
- if (!uiLocation)
+ if (!uiLocation) {
return;
- if (window.performance.now() - this._lastModificationTime < Sources.SourcesPanel._lastModificationTimeout)
+ }
+ if (window.performance.now() - this._lastModificationTime < Sources.SourcesPanel._lastModificationTimeout) {
return;
+ }
this._sourcesView.showSourceLocation(
uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, undefined, true);
}
@@ -449,10 +466,12 @@ Sources.SourcesPanel = class extends UI.Panel {
_callFrameChanged() {
const callFrame = UI.context.flavor(SDK.DebuggerModel.CallFrame);
- if (!callFrame)
+ if (!callFrame) {
return;
- if (this._executionLineLocation)
+ }
+ if (this._executionLineLocation) {
this._executionLineLocation.dispose();
+ }
this._executionLineLocation = Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(
callFrame.location(), this._executionLineChanged.bind(this), this._liveLocationPool);
}
@@ -491,8 +510,9 @@ Sources.SourcesPanel = class extends UI.Panel {
const details = currentDebuggerModel ? currentDebuggerModel.debuggerPausedDetails() : null;
await this._debuggerPausedMessage.render(details, Bindings.debuggerWorkspaceBinding, Bindings.breakpointManager);
- if (details)
+ if (details) {
this._updateDebuggerButtonsAndStatusForTest();
+ }
}
_updateDebuggerButtonsAndStatusForTest() {
@@ -502,8 +522,9 @@ Sources.SourcesPanel = class extends UI.Panel {
this._updateDebuggerButtonsAndStatus();
UI.context.setFlavor(SDK.DebuggerPausedDetails, null);
- if (this._switchToPausedTargetTimeout)
+ if (this._switchToPausedTargetTimeout) {
clearTimeout(this._switchToPausedTargetTimeout);
+ }
this._liveLocationPool.disposeAll();
}
@@ -512,10 +533,12 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_switchToPausedTarget(debuggerModel) {
delete this._switchToPausedTargetTimeout;
- if (this._paused)
+ if (this._paused) {
return;
- if (debuggerModel.isPaused())
+ }
+ if (debuggerModel.isPaused()) {
return;
+ }
const debuggerModels = SDK.targetManager.models(SDK.DebuggerModel);
for (let i = 0; i < debuggerModels.length; ++i) {
if (debuggerModels[i].isPaused()) {
@@ -531,8 +554,9 @@ Sources.SourcesPanel = class extends UI.Panel {
_runSnippet() {
const uiSourceCode = this._sourcesView.currentUISourceCode();
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
Snippets.evaluateScriptSnippet(uiSourceCode);
}
@@ -541,8 +565,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_editorSelected(event) {
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
- if (this.editorView.mainWidget() && Common.moduleSetting('autoRevealInNavigator').get())
+ if (this.editorView.mainWidget() && Common.moduleSetting('autoRevealInNavigator').get()) {
this._revealInNavigator(uiSourceCode, true);
+ }
}
/**
@@ -550,11 +575,13 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_togglePause() {
const target = UI.context.flavor(SDK.Target);
- if (!target)
+ if (!target) {
return true;
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return true;
+ }
if (this._paused) {
this._paused = false;
@@ -572,8 +599,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @return {?SDK.DebuggerModel}
*/
_prepareToResume() {
- if (!this._paused)
+ if (!this._paused) {
return null;
+ }
this._paused = false;
@@ -587,8 +615,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_longResume(event) {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return;
+ }
debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
debuggerModel.resume();
@@ -599,8 +628,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_terminateExecution(event) {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return;
+ }
debuggerModel.runtimeModel().terminateExecution();
debuggerModel.resume();
}
@@ -610,8 +640,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_stepOver() {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return true;
+ }
debuggerModel.stepOver();
return true;
@@ -622,8 +653,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_stepInto() {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return true;
+ }
debuggerModel.stepInto();
return true;
@@ -634,8 +666,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_stepIntoAsync() {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return true;
+ }
debuggerModel.scheduleStepIntoAsync();
return true;
}
@@ -645,8 +678,9 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_stepOut() {
const debuggerModel = this._prepareToResume();
- if (!debuggerModel)
+ if (!debuggerModel) {
return true;
+ }
debuggerModel.stepOut();
return true;
@@ -657,16 +691,19 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_continueToLocation(uiLocation) {
const executionContext = UI.context.flavor(SDK.ExecutionContext);
- if (!executionContext)
+ if (!executionContext) {
return;
+ }
// Always use 0 column.
const rawLocations =
Bindings.debuggerWorkspaceBinding.uiLocationToRawLocations(uiLocation.uiSourceCode, uiLocation.lineNumber, 0);
const rawLocation = rawLocations.find(location => location.debuggerModel === executionContext.debuggerModel);
- if (!rawLocation)
+ if (!rawLocation) {
return;
- if (!this._prepareToResume())
+ }
+ if (!this._prepareToResume()) {
return;
+ }
rawLocation.continueToLocation();
}
@@ -741,8 +778,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Object} target
*/
_appendUISourceCodeItems(event, contextMenu, target) {
- if (!(target instanceof Workspace.UISourceCode))
+ if (!(target instanceof Workspace.UISourceCode)) {
return;
+ }
const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (target);
if (!uiSourceCode.project().isServiceProject() &&
@@ -758,10 +796,12 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Object} target
*/
_appendUISourceCodeFrameItems(event, contextMenu, target) {
- if (!(target instanceof Sources.UISourceCodeFrame))
+ if (!(target instanceof Sources.UISourceCodeFrame)) {
return;
- if (target.uiSourceCode().contentType().isFromSourceMap() || target.textEditor.selection().isEmpty())
+ }
+ if (target.uiSourceCode().contentType().isFromSourceMap() || target.textEditor.selection().isEmpty()) {
return;
+ }
contextMenu.debugSection().appendAction('debugger.evaluate-selection');
}
@@ -770,8 +810,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Object} object
*/
appendUILocationItems(contextMenu, object) {
- if (!(object instanceof Workspace.UILocation))
+ if (!(object instanceof Workspace.UILocation)) {
return;
+ }
const uiLocation = /** @type {!Workspace.UILocation} */ (object);
const uiSourceCode = uiLocation.uiSourceCode;
@@ -801,8 +842,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Object} target
*/
_appendRemoteObjectItems(contextMenu, target) {
- if (!(target instanceof SDK.RemoteObject))
+ if (!(target instanceof SDK.RemoteObject)) {
return;
+ }
const remoteObject = /** @type {!SDK.RemoteObject} */ (target);
const executionContext = UI.context.flavor(SDK.ExecutionContext);
contextMenu.debugSection().appendItem(
@@ -818,12 +860,14 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Object} target
*/
_appendNetworkRequestItems(contextMenu, target) {
- if (!(target instanceof SDK.NetworkRequest))
+ if (!(target instanceof SDK.NetworkRequest)) {
return;
+ }
const request = /** @type {!SDK.NetworkRequest} */ (target);
const uiSourceCode = this._workspace.uiSourceCodeForURL(request.url());
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
const openText = Common.UIString('Open in Sources panel');
contextMenu.revealSection().appendItem(openText, this.showUILocation.bind(this, uiSourceCode.uiLocation(0, 0)));
}
@@ -839,16 +883,19 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {?{location: ?SDK.DebuggerModel.Location}} response
*/
_didGetFunctionDetails(response) {
- if (!response || !response.location)
+ if (!response || !response.location) {
return;
+ }
const location = response.location;
- if (!location)
+ if (!location) {
return;
+ }
const uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location);
- if (uiLocation)
+ if (uiLocation) {
this.showUILocation(uiLocation);
+ }
}
_revealNavigatorSidebar() {
@@ -864,21 +911,25 @@ Sources.SourcesPanel = class extends UI.Panel {
_updateSidebarPosition() {
let vertically;
const position = Common.moduleSetting('sidebarPosition').get();
- if (position === 'right')
+ if (position === 'right') {
vertically = false;
- else if (position === 'bottom')
+ } else if (position === 'bottom') {
vertically = true;
- else
+ } else {
vertically = UI.inspectorView.element.offsetWidth < 680;
+ }
- if (this.sidebarPaneView && vertically === !this._splitWidget.isVertical())
+ if (this.sidebarPaneView && vertically === !this._splitWidget.isVertical()) {
return;
+ }
- if (this.sidebarPaneView && this.sidebarPaneView.shouldHideOnDetach())
- return; // We can't reparent extension iframes.
+ if (this.sidebarPaneView && this.sidebarPaneView.shouldHideOnDetach()) {
+ return;
+ } // We can't reparent extension iframes.
- if (this.sidebarPaneView)
+ if (this.sidebarPaneView) {
this.sidebarPaneView.detach();
+ }
this._splitWidget.setVertical(!vertically);
this._splitWidget.element.classList.toggle('sources-split-view-vertical', vertically);
@@ -887,20 +938,24 @@ Sources.SourcesPanel = class extends UI.Panel {
// Create vertical box with stack.
const vbox = new UI.VBox();
+ vbox.element.appendChild(this._debugToolbar.element);
vbox.element.appendChild(this._debugToolbarDrawer);
- vbox.setMinimumAndPreferredSizes(25, 25, Sources.SourcesPanel.minToolbarWidth, 100);
+
+ vbox.setMinimumAndPreferredSizes(
+ Sources.SourcesPanel.minToolbarWidth, 25, Sources.SourcesPanel.minToolbarWidth, 100);
this._sidebarPaneStack = UI.viewManager.createStackLocation(this._revealDebuggerSidebar.bind(this));
this._sidebarPaneStack.widget().element.classList.add('overflow-auto');
this._sidebarPaneStack.widget().show(vbox.element);
this._sidebarPaneStack.widget().element.appendChild(this._debuggerPausedMessage.element());
this._sidebarPaneStack.appendApplicableItems('sources.sidebar-top');
- vbox.element.appendChild(this._debugToolbar.element);
- if (this._threadsSidebarPane)
+ if (this._threadsSidebarPane) {
this._sidebarPaneStack.showView(this._threadsSidebarPane);
+ }
- if (!vertically)
+ if (!vertically) {
this._sidebarPaneStack.appendView(this._watchSidebarPane);
+ }
this._sidebarPaneStack.showView(this._callstackPane);
const jsBreakpoints = /** @type {!UI.View} */ (UI.viewManager.view('sources.jsBreakpoints'));
@@ -939,8 +994,9 @@ Sources.SourcesPanel = class extends UI.Panel {
this._sidebarPaneStack.appendApplicableItems('sources.sidebar-bottom');
const extensionSidebarPanes = Extensions.extensionServer.sidebarPanes();
- for (let i = 0; i < extensionSidebarPanes.length; ++i)
+ for (let i = 0; i < extensionSidebarPanes.length; ++i) {
this._addExtensionSidebarPane(extensionSidebarPanes[i]);
+ }
this._splitWidget.setSidebarWidget(this.sidebarPaneView);
}
@@ -964,8 +1020,9 @@ Sources.SourcesPanel = class extends UI.Panel {
* @param {!Extensions.ExtensionSidebarPane} pane
*/
_addExtensionSidebarPane(pane) {
- if (pane.panelName() === this.name)
+ if (pane.panelName() === this.name) {
this._extensionSidebarPanesContainer.appendView(pane);
+ }
}
/**
@@ -980,12 +1037,14 @@ Sources.SourcesPanel = class extends UI.Panel {
*/
_handleDrop(dataTransfer) {
const items = dataTransfer.items;
- if (!items.length)
+ if (!items.length) {
return;
+ }
const entry = items[0].webkitGetAsEntry();
- if (!entry.isDirectory)
+ if (!entry.isDirectory) {
return;
- InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
+ }
+ Host.InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
}
};
@@ -1005,8 +1064,9 @@ Sources.SourcesPanel.UILocationRevealer = class {
* @return {!Promise}
*/
reveal(uiLocation, omitFocus) {
- if (!(uiLocation instanceof Workspace.UILocation))
+ if (!(uiLocation instanceof Workspace.UILocation)) {
return Promise.reject(new Error('Internal error: not a ui location'));
+ }
Sources.SourcesPanel.instance().showUILocation(uiLocation, omitFocus);
return Promise.resolve();
}
@@ -1024,11 +1084,13 @@ Sources.SourcesPanel.DebuggerLocationRevealer = class {
* @return {!Promise}
*/
reveal(rawLocation, omitFocus) {
- if (!(rawLocation instanceof SDK.DebuggerModel.Location))
+ if (!(rawLocation instanceof SDK.DebuggerModel.Location)) {
return Promise.reject(new Error('Internal error: not a debugger location'));
+ }
const uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(rawLocation);
- if (!uiLocation)
+ if (!uiLocation) {
return Promise.resolve();
+ }
Sources.SourcesPanel.instance().showUILocation(uiLocation, omitFocus);
return Promise.resolve();
}
@@ -1046,8 +1108,9 @@ Sources.SourcesPanel.UISourceCodeRevealer = class {
* @return {!Promise}
*/
reveal(uiSourceCode, omitFocus) {
- if (!(uiSourceCode instanceof Workspace.UISourceCode))
+ if (!(uiSourceCode instanceof Workspace.UISourceCode)) {
return Promise.reject(new Error('Internal error: not a ui source code'));
+ }
Sources.SourcesPanel.instance().showUISourceCode(uiSourceCode, undefined, undefined, omitFocus);
return Promise.resolve();
}
@@ -1081,8 +1144,9 @@ Sources.SourcesPanel.RevealingActionDelegate = class {
*/
handleAction(context, actionId) {
const panel = Sources.SourcesPanel.instance();
- if (!panel._ensureSourcesViewVisible())
+ if (!panel._ensureSourcesViewVisible()) {
return false;
+ }
switch (actionId) {
case 'debugger.toggle-pause':
panel._togglePause();
@@ -1165,10 +1229,11 @@ Sources.SourcesPanel.WrapperView = class extends UI.VBox {
* @override
*/
wasShown() {
- if (!Sources.SourcesPanel.instance().isShowing())
+ if (!Sources.SourcesPanel.instance().isShowing()) {
this._showViewInWrapper();
- else
+ } else {
UI.inspectorView.setDrawerMinimized(true);
+ }
Sources.SourcesPanel.updateResizerAndSidebarButtons(Sources.SourcesPanel.instance());
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesSearchScope.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesSearchScope.js
index 3d19de6f8c9..39187c7602b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesSearchScope.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesSearchScope.js
@@ -48,22 +48,27 @@ Sources.SourcesSearchScope = class {
* @return {number}
*/
static _filesComparator(uiSourceCode1, uiSourceCode2) {
- if (uiSourceCode1.isDirty() && !uiSourceCode2.isDirty())
+ if (uiSourceCode1.isDirty() && !uiSourceCode2.isDirty()) {
return -1;
- if (!uiSourceCode1.isDirty() && uiSourceCode2.isDirty())
+ }
+ if (!uiSourceCode1.isDirty() && uiSourceCode2.isDirty()) {
return 1;
+ }
const isFileSystem1 = uiSourceCode1.project().type() === Workspace.projectTypes.FileSystem &&
!Persistence.persistence.binding(uiSourceCode1);
const isFileSystem2 = uiSourceCode2.project().type() === Workspace.projectTypes.FileSystem &&
!Persistence.persistence.binding(uiSourceCode2);
- if (isFileSystem1 !== isFileSystem2)
+ if (isFileSystem1 !== isFileSystem2) {
return isFileSystem1 ? 1 : -1;
+ }
const url1 = uiSourceCode1.url();
const url2 = uiSourceCode2.url();
- if (url1 && !url2)
+ if (url1 && !url2) {
return -1;
- if (!url1 && url2)
+ }
+ if (!url1 && url2) {
return 1;
+ }
return String.naturalOrderComparator(uiSourceCode1.fullDisplayName(), uiSourceCode2.fullDisplayName());
}
@@ -90,12 +95,15 @@ Sources.SourcesSearchScope = class {
const searchInAnonymousAndContentScripts = Common.moduleSetting('searchInAnonymousAndContentScripts').get();
return Workspace.workspace.projects().filter(project => {
- if (project.type() === Workspace.projectTypes.Service)
+ if (project.type() === Workspace.projectTypes.Service) {
return false;
- if (!searchInAnonymousAndContentScripts && project.isServiceProject())
+ }
+ if (!searchInAnonymousAndContentScripts && project.isServiceProject()) {
return false;
- if (!searchInAnonymousAndContentScripts && project.type() === Workspace.projectTypes.ContentScripts)
+ }
+ if (!searchInAnonymousAndContentScripts && project.type() === Workspace.projectTypes.ContentScripts) {
return false;
+ }
return true;
});
}
@@ -145,15 +153,19 @@ Sources.SourcesSearchScope = class {
const uiSourceCodes = project.uiSourceCodes();
for (let i = 0; i < uiSourceCodes.length; ++i) {
const uiSourceCode = uiSourceCodes[i];
- if (!uiSourceCode.contentType().isTextType())
+ if (!uiSourceCode.contentType().isTextType()) {
continue;
+ }
const binding = Persistence.persistence.binding(uiSourceCode);
- if (binding && binding.network === uiSourceCode)
+ if (binding && binding.network === uiSourceCode) {
continue;
- if (dirtyOnly && !uiSourceCode.isDirty())
+ }
+ if (dirtyOnly && !uiSourceCode.isDirty()) {
continue;
- if (searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayName()))
+ }
+ if (searchConfig.filePathMatchesFileQuery(uiSourceCode.fullDisplayName())) {
result.push(uiSourceCode.url());
+ }
}
result.sort(String.naturalOrderComparator);
return result;
@@ -180,11 +192,13 @@ Sources.SourcesSearchScope = class {
const uiSourceCodes = [];
for (const file of files) {
const uiSourceCode = project.uiSourceCodeForURL(file);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
continue;
+ }
const script = Bindings.DefaultScriptMapping.scriptForUISourceCode(uiSourceCode);
- if (script && !script.isAnonymousScript())
+ if (script && !script.isAnonymousScript()) {
continue;
+ }
uiSourceCodes.push(uiSourceCode);
}
uiSourceCodes.sort(Sources.SourcesSearchScope._filesComparator);
@@ -216,18 +230,22 @@ Sources.SourcesSearchScope = class {
const maxFileContentRequests = 20;
let callbacksLeft = 0;
- for (let i = 0; i < maxFileContentRequests && i < files.length; ++i)
+ for (let i = 0; i < maxFileContentRequests && i < files.length; ++i) {
scheduleSearchInNextFileOrFinish.call(this);
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @this {Sources.SourcesSearchScope}
*/
function searchInNextFile(uiSourceCode) {
- if (uiSourceCode.isDirty())
+ if (uiSourceCode.isDirty()) {
contentLoaded.call(this, uiSourceCode, uiSourceCode.workingCopy());
- else
- uiSourceCode.requestContent().then(contentLoaded.bind(this, uiSourceCode));
+ } else {
+ uiSourceCode.requestContent().then(deferredContent => {
+ contentLoaded.call(this, uiSourceCode, deferredContent.content || '');
+ });
+ }
}
/**
@@ -250,7 +268,7 @@ Sources.SourcesSearchScope = class {
/**
* @param {!Workspace.UISourceCode} uiSourceCode
- * @param {?string} content
+ * @param {string} content
* @this {Sources.SourcesSearchScope}
*/
function contentLoaded(uiSourceCode, content) {
@@ -344,7 +362,7 @@ Sources.FileBasedSearchResult = class {
*/
matchRevealable(index) {
const match = this._searchMatches[index];
- return this._uiSourceCode.uiLocation(match.lineNumber, match.columnNumber);
+ return this._uiSourceCode.uiLocation(match.lineNumber, undefined);
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesView.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesView.js
index f02e8d4d8ad..a2ebb02c270 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/SourcesView.js
@@ -27,7 +27,8 @@ Sources.SourcesView = class extends UI.VBox {
this._sourceViewByUISourceCode = new Map();
this._editorContainer = new Sources.TabbedEditorContainer(
- this, Common.settings.createLocalSetting('previouslyViewedFiles', []), this._placeholderElement());
+ this, Common.settings.createLocalSetting('previouslyViewedFiles', []), this._placeholderElement(),
+ this._focusedPlaceholderElement);
this._editorContainer.show(this._searchableView.element);
this._editorContainer.addEventListener(
Sources.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
@@ -36,7 +37,7 @@ Sources.SourcesView = class extends UI.VBox {
this._historyManager = new Sources.EditingLocationHistoryManager(this, this.currentSourceFrame.bind(this));
this._toolbarContainerElement = this.element.createChild('div', 'sources-toolbar');
- if (!Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
+ if (!Root.Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
this._toolbarEditorActions = new UI.Toolbar('', this._toolbarContainerElement);
self.runtime.allInstances(Sources.SourcesView.EditorAction).then(appendButtonsForExtensions.bind(this));
}
@@ -45,8 +46,9 @@ Sources.SourcesView = class extends UI.VBox {
* @this {Sources.SourcesView}
*/
function appendButtonsForExtensions(actions) {
- for (let i = 0; i < actions.length; ++i)
+ for (let i = 0; i < actions.length; ++i) {
this._toolbarEditorActions.appendToolbarItem(actions[i].button(this));
+ }
}
this._scriptViewToolbar = new UI.Toolbar('', this._toolbarContainerElement);
this._scriptViewToolbar.element.style.flex = 'auto';
@@ -67,8 +69,9 @@ Sources.SourcesView = class extends UI.VBox {
* @param {!Event} event
*/
function handleBeforeUnload(event) {
- if (event.returnValue)
+ if (event.returnValue) {
return;
+ }
let unsavedSourceCodes = [];
const projects = Workspace.workspace.projectsForType(Workspace.projectTypes.FileSystem);
@@ -77,17 +80,20 @@ Sources.SourcesView = class extends UI.VBox {
unsavedSourceCodes.concat(projects[i].uiSourceCodes().filter(sourceCode => sourceCode.isDirty()));
}
- if (!unsavedSourceCodes.length)
+ if (!unsavedSourceCodes.length) {
return;
+ }
event.returnValue = Common.UIString('DevTools have unsaved changes that will be permanently lost.');
UI.viewManager.showView('sources');
- for (let i = 0; i < unsavedSourceCodes.length; ++i)
+ for (let i = 0; i < unsavedSourceCodes.length; ++i) {
Common.Revealer.reveal(unsavedSourceCodes[i]);
+ }
}
- if (!window.opener)
+ if (!window.opener) {
window.addEventListener('beforeunload', handleBeforeUnload, true);
+ }
this._shortcuts = {};
this.element.addEventListener('keydown', this._handleKeyDown.bind(this), false);
@@ -97,19 +103,44 @@ Sources.SourcesView = class extends UI.VBox {
* @return {!Element}
*/
_placeholderElement() {
+ /** @type {!Array.<{element: !Element, handler: !Function}>} */
+ this._placeholderOptionArray = [];
+
const shortcuts = [
- {actionId: 'quickOpen.show', description: Common.UIString('Open file')},
- {actionId: 'commandMenu.show', description: Common.UIString('Run command')}
+ {actionId: 'quickOpen.show', description: ls`Open file`},
+ {actionId: 'commandMenu.show', description: ls`Run command`},
+ {actionId: 'sources.add-folder-to-workspace', description: ls`Drop in a folder to add to workspace`}
];
- const element = createElementWithClass('span', 'tabbed-pane-placeholder');
- for (const shortcut of shortcuts) {
+ const element = createElementWithClass('div');
+ const list = element.createChild('div', 'tabbed-pane-placeholder');
+ list.addEventListener('keydown', this._placeholderOnKeyDown.bind(this), false);
+ UI.ARIAUtils.markAsList(list);
+ UI.ARIAUtils.setAccessibleName(list, ls`Empty Source View Actions`);
+
+ for (let i = 0; i < shortcuts.length; i++) {
+ const shortcut = shortcuts[i];
const shortcutKeyText = UI.shortcutRegistry.shortcutTitleForAction(shortcut.actionId);
- const row = element.createChild('div', 'tabbed-pane-placeholder-row');
- row.createChild('div', 'tabbed-pane-placeholder-key').textContent = shortcutKeyText;
- row.createChild('div', 'tabbed-pane-placeholder-value').textContent = shortcut.description;
+ const listItemElement = list.createChild('div');
+ UI.ARIAUtils.markAsListitem(listItemElement);
+ const row = listItemElement.createChild('div', 'tabbed-pane-placeholder-row');
+ row.tabIndex = -1;
+ UI.ARIAUtils.markAsButton(row);
+ if (shortcutKeyText) {
+ row.createChild('div', 'tabbed-pane-placeholder-key').textContent = shortcutKeyText;
+ row.createChild('div', 'tabbed-pane-placeholder-value').textContent = shortcut.description;
+ } else {
+ row.createChild('div', 'tabbed-pane-no-shortcut').textContent = shortcut.description;
+ }
+ const action = UI.actionRegistry.action(shortcut.actionId);
+ const actionHandler = action.execute.bind(action);
+ this._placeholderOptionArray.push({element: row, handler: actionHandler});
}
- element.createChild('div').textContent = Common.UIString('Drop in a folder to add to workspace');
+
+ const firstElement = this._placeholderOptionArray[0].element;
+ firstElement.tabIndex = 0;
+ this._focusedPlaceholderElement = firstElement;
+ this._selectedIndex = 0;
element.appendChild(UI.XLink.create(
'https://developers.google.com/web/tools/chrome-devtools/sources?utm_source=devtools&utm_campaign=2018Q1',
@@ -119,6 +150,41 @@ Sources.SourcesView = class extends UI.VBox {
}
/**
+ * @param {!Event} event
+ */
+ _placeholderOnKeyDown(event) {
+ if (isEnterOrSpaceKey(event)) {
+ this._placeholderOptionArray[this._selectedIndex].handler.call();
+ return;
+ }
+
+ let offset = 0;
+ if (event.key === 'ArrowDown') {
+ offset = 1;
+ } else if (event.key === 'ArrowUp') {
+ offset = -1;
+ }
+
+ const newIndex = Math.max(Math.min(this._placeholderOptionArray.length - 1, this._selectedIndex + offset), 0);
+ const newElement = this._placeholderOptionArray[newIndex].element;
+ const oldElement = this._placeholderOptionArray[this._selectedIndex].element;
+ if (newElement !== oldElement) {
+ oldElement.tabIndex = -1;
+ newElement.tabIndex = 0;
+ UI.ARIAUtils.setSelected(oldElement, false);
+ UI.ARIAUtils.setSelected(newElement, true);
+ this._selectedIndex = newIndex;
+ newElement.focus();
+ }
+ }
+
+ _resetPlaceholderState() {
+ this._placeholderOptionArray[this._selectedIndex].element.tabIndex = -1;
+ this._placeholderOptionArray[0].element.tabIndex = 0;
+ this._selectedIndex = 0;
+ }
+
+ /**
* @return {!Map.<!Workspace.UISourceCode, number>}
*/
static defaultUISourceCodeScores() {
@@ -128,7 +194,9 @@ Sources.SourcesView = class extends UI.VBox {
if (sourcesView) {
const uiSourceCodes = sourcesView._editorContainer.historyUISourceCodes();
for (let i = 1; i < uiSourceCodes.length; ++i) // Skip current element
+ {
defaultScores.set(uiSourceCodes[i], uiSourceCodes.length - i);
+ }
}
return defaultScores;
}
@@ -159,15 +227,17 @@ Sources.SourcesView = class extends UI.VBox {
* @param {function(!Event=):boolean} handler
*/
_registerShortcuts(keys, handler) {
- for (let i = 0; i < keys.length; ++i)
+ for (let i = 0; i < keys.length; ++i) {
this._shortcuts[keys[i].key] = handler;
+ }
}
_handleKeyDown(event) {
const shortcutKey = UI.KeyboardShortcut.makeKeyFromEvent(event);
const handler = this._shortcuts[shortcutKey];
- if (handler && handler())
+ if (handler && handler()) {
event.consume(true);
+ }
}
/**
@@ -183,6 +253,7 @@ Sources.SourcesView = class extends UI.VBox {
*/
willHide() {
UI.context.setFlavor(Sources.SourcesView, null);
+ this._resetPlaceholderState();
super.willHide();
}
@@ -212,8 +283,9 @@ Sources.SourcesView = class extends UI.VBox {
*/
currentSourceFrame() {
const view = this.visibleView();
- if (!(view instanceof Sources.UISourceCodeFrame))
+ if (!(view instanceof Sources.UISourceCodeFrame)) {
return null;
+ }
return /** @type {!Sources.UISourceCodeFrame} */ (view);
}
@@ -229,8 +301,9 @@ Sources.SourcesView = class extends UI.VBox {
*/
_onCloseEditorTab() {
const uiSourceCode = this._editorContainer.currentFile();
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return false;
+ }
this._editorContainer.closeFile(uiSourceCode);
return true;
}
@@ -255,11 +328,13 @@ Sources.SourcesView = class extends UI.VBox {
* @param {!Workspace.UISourceCode} uiSourceCode
*/
_addUISourceCode(uiSourceCode) {
- if (uiSourceCode.project().isServiceProject())
+ if (uiSourceCode.project().isServiceProject()) {
return;
+ }
if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem &&
- Persistence.FileSystemWorkspaceBinding.fileSystemType(uiSourceCode.project()) === 'overrides')
+ Persistence.FileSystemWorkspaceBinding.fileSystemType(uiSourceCode.project()) === 'overrides') {
return;
+ }
this._editorContainer.addUISourceCode(uiSourceCode);
}
@@ -289,8 +364,9 @@ Sources.SourcesView = class extends UI.VBox {
this._scriptViewToolbar.removeToolbarItems();
const view = this.visibleView();
if (view instanceof UI.SimpleView) {
- for (const item of (/** @type {?UI.SimpleView} */ (view)).syncToolbarItems())
+ for (const item of (/** @type {?UI.SimpleView} */ (view)).syncToolbarItems()) {
this._scriptViewToolbar.appendToolbarItem(item);
+ }
}
}
@@ -305,11 +381,13 @@ Sources.SourcesView = class extends UI.VBox {
this._historyManager.updateCurrentState();
this._editorContainer.showFile(uiSourceCode);
const currentSourceFrame = this.currentSourceFrame();
- if (currentSourceFrame && typeof lineNumber === 'number')
+ if (currentSourceFrame && typeof lineNumber === 'number') {
currentSourceFrame.revealPosition(lineNumber, columnNumber, !omitHighlight);
+ }
this._historyManager.pushNewState();
- if (!omitFocus)
+ if (!omitFocus) {
this.visibleView().focus();
+ }
}
/**
@@ -321,15 +399,17 @@ Sources.SourcesView = class extends UI.VBox {
let sourceView;
const contentType = uiSourceCode.contentType();
- if (contentType === Common.resourceTypes.Image)
+ if (contentType === Common.resourceTypes.Image) {
sourceView = new SourceFrame.ImageView(uiSourceCode.mimeType(), uiSourceCode);
- else if (contentType === Common.resourceTypes.Font)
+ } else if (contentType === Common.resourceTypes.Font) {
sourceView = new SourceFrame.FontView(uiSourceCode.mimeType(), uiSourceCode);
- else
+ } else {
sourceFrame = new Sources.UISourceCodeFrame(uiSourceCode);
+ }
- if (sourceFrame)
+ if (sourceFrame) {
this._historyManager.trackSourceFrameCursorJumps(sourceFrame);
+ }
const widget = /** @type {!UI.Widget} */ (sourceFrame || sourceView);
this._sourceViewByUISourceCode.set(uiSourceCode, widget);
@@ -370,8 +450,9 @@ Sources.SourcesView = class extends UI.VBox {
_removeSourceFrame(uiSourceCode) {
const sourceView = this._sourceViewByUISourceCode.get(uiSourceCode);
this._sourceViewByUISourceCode.remove(uiSourceCode);
- if (sourceView && sourceView instanceof Sources.UISourceCodeFrame)
+ if (sourceView && sourceView instanceof Sources.UISourceCodeFrame) {
/** @type {!Sources.UISourceCodeFrame} */ (sourceView).dispose();
+ }
}
/**
@@ -382,8 +463,9 @@ Sources.SourcesView = class extends UI.VBox {
this._historyManager.removeHistoryForSourceCode(uiSourceCode);
let wasSelected = false;
- if (!this._editorContainer.currentFile())
+ if (!this._editorContainer.currentFile()) {
wasSelected = true;
+ }
// SourcesNavigator does not need to update on EditorClosed.
this._removeToolbarChangedListener();
@@ -402,12 +484,14 @@ Sources.SourcesView = class extends UI.VBox {
_editorSelected(event) {
const previousSourceFrame =
event.data.previousView instanceof Sources.UISourceCodeFrame ? event.data.previousView : null;
- if (previousSourceFrame)
+ if (previousSourceFrame) {
previousSourceFrame.setSearchableView(null);
+ }
const currentSourceFrame =
event.data.currentView instanceof Sources.UISourceCodeFrame ? event.data.currentView : null;
- if (currentSourceFrame)
+ if (currentSourceFrame) {
currentSourceFrame.setSearchableView(this._searchableView);
+ }
this._searchableView.setReplaceable(!!currentSourceFrame && currentSourceFrame.canEditSource());
this._searchableView.refreshSearch();
@@ -418,16 +502,18 @@ Sources.SourcesView = class extends UI.VBox {
}
_removeToolbarChangedListener() {
- if (this._toolbarChangedListener)
+ if (this._toolbarChangedListener) {
Common.EventTarget.removeEventListeners([this._toolbarChangedListener]);
+ }
this._toolbarChangedListener = null;
}
_updateToolbarChangedListener() {
this._removeToolbarChangedListener();
const sourceFrame = this.currentSourceFrame();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
this._toolbarChangedListener = sourceFrame.addEventListener(
Sources.UISourceCodeFrame.Events.ToolbarItemsChanged, this._updateScriptViewToolbarItems, this);
}
@@ -436,8 +522,9 @@ Sources.SourcesView = class extends UI.VBox {
* @override
*/
searchCanceled() {
- if (this._searchView)
+ if (this._searchView) {
this._searchView.searchCanceled();
+ }
delete this._searchView;
delete this._searchConfig;
@@ -451,8 +538,9 @@ Sources.SourcesView = class extends UI.VBox {
*/
performSearch(searchConfig, shouldJump, jumpBackwards) {
const sourceFrame = this.currentSourceFrame();
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
+ }
this._searchView = sourceFrame;
this._searchConfig = searchConfig;
@@ -464,8 +552,9 @@ Sources.SourcesView = class extends UI.VBox {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchView)
+ if (!this._searchView) {
return;
+ }
if (this._searchView !== this.currentSourceFrame()) {
this.performSearch(this._searchConfig, true);
@@ -479,13 +568,15 @@ Sources.SourcesView = class extends UI.VBox {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchView)
+ if (!this._searchView) {
return;
+ }
if (this._searchView !== this.currentSourceFrame()) {
this.performSearch(this._searchConfig, true);
- if (this._searchView)
+ if (this._searchView) {
this._searchView.jumpToLastSearchResult();
+ }
return;
}
@@ -541,8 +632,9 @@ Sources.SourcesView = class extends UI.VBox {
}
_showGoToLineQuickOpen() {
- if (this._editorContainer.currentFile())
+ if (this._editorContainer.currentFile()) {
QuickOpen.QuickOpen.show(':');
+ }
}
_save() {
@@ -558,8 +650,9 @@ Sources.SourcesView = class extends UI.VBox {
* @param {?UI.Widget} sourceFrame
*/
_saveSourceFrame(sourceFrame) {
- if (!(sourceFrame instanceof Sources.UISourceCodeFrame))
+ if (!(sourceFrame instanceof Sources.UISourceCodeFrame)) {
return;
+ }
const uiSourceCodeFrame = /** @type {!Sources.UISourceCodeFrame} */ (sourceFrame);
uiSourceCodeFrame.commitEditing();
}
@@ -618,10 +711,12 @@ Sources.SourcesView.SwitchFileActionDelegate = class {
const namePrefix = fileNamePrefix(name);
for (let i = 0; i < uiSourceCodes.length; ++i) {
const uiSourceCode = uiSourceCodes[i];
- if (url !== uiSourceCode.parentURL())
+ if (url !== uiSourceCode.parentURL()) {
continue;
- if (fileNamePrefix(uiSourceCode.name()) === namePrefix)
+ }
+ if (fileNamePrefix(uiSourceCode.name()) === namePrefix) {
candidates.push(uiSourceCode.name());
+ }
}
candidates.sort(String.naturalOrderComparator);
const index = mod(candidates.indexOf(name) + 1, candidates.length);
@@ -639,11 +734,13 @@ Sources.SourcesView.SwitchFileActionDelegate = class {
handleAction(context, actionId) {
const sourcesView = UI.context.flavor(Sources.SourcesView);
const currentUISourceCode = sourcesView.currentUISourceCode();
- if (!currentUISourceCode)
+ if (!currentUISourceCode) {
return false;
+ }
const nextUISourceCode = Sources.SourcesView.SwitchFileActionDelegate._nextFile(currentUISourceCode);
- if (!nextUISourceCode)
+ if (!nextUISourceCode) {
return false;
+ }
sourcesView.showSourceLocation(nextUISourceCode);
return true;
}
@@ -663,8 +760,9 @@ Sources.SourcesView.ActionDelegate = class {
*/
handleAction(context, actionId) {
const sourcesView = UI.context.flavor(Sources.SourcesView);
- if (!sourcesView)
+ if (!sourcesView) {
return false;
+ }
switch (actionId) {
case 'sources.close-all':
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/TabbedEditorContainer.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/TabbedEditorContainer.js
index ce8cb058c4f..4e00fb5fc70 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/TabbedEditorContainer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/TabbedEditorContainer.js
@@ -52,13 +52,14 @@ Sources.TabbedEditorContainer = class extends Common.Object {
* @param {!Sources.TabbedEditorContainerDelegate} delegate
* @param {!Common.Setting} setting
* @param {!Element} placeholderElement
+ * @param {!Element=} focusedPlaceholderElement
*/
- constructor(delegate, setting, placeholderElement) {
+ constructor(delegate, setting, placeholderElement, focusedPlaceholderElement) {
super();
this._delegate = delegate;
this._tabbedPane = new UI.TabbedPane();
- this._tabbedPane.setPlaceholderElement(placeholderElement);
+ this._tabbedPane.setPlaceholderElement(placeholderElement, focusedPlaceholderElement);
this._tabbedPane.setTabDelegate(new Sources.EditorContainerTabDelegate(this));
this._tabbedPane.setCloseableTabs(true);
@@ -94,8 +95,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
const currentScrollLineNumber = this._history.scrollLineNumber(binding.network.url());
this._history.remove(binding.network.url());
- if (!networkTabId)
+ if (!networkTabId) {
return;
+ }
if (!fileSystemTabId) {
const networkView = this._tabbedPane.tabView(networkTabId);
@@ -111,8 +113,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
}
this._closeTabs([networkTabId], true);
- if (wasSelectedInNetwork)
+ if (wasSelectedInNetwork) {
this._tabbedPane.selectTab(fileSystemTabId, false);
+ }
this._updateHistory();
}
@@ -179,8 +182,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
*/
closeFile(uiSourceCode) {
const tabId = this._tabIds.get(uiSourceCode);
- if (!tabId)
+ if (!tabId) {
return;
+ }
this._closeTabs([tabId]);
}
@@ -203,15 +207,17 @@ Sources.TabbedEditorContainer = class extends Common.Object {
const uris = this._history._urls();
for (let i = 0; i < uris.length; ++i) {
const uiSourceCode = uriToUISourceCode[uris[i]];
- if (uiSourceCode)
+ if (uiSourceCode) {
result.push(uiSourceCode);
+ }
}
return result;
}
_addViewListeners() {
- if (!this._currentView || !this._currentView.textEditor)
+ if (!this._currentView || !this._currentView.textEditor) {
return;
+ }
this._currentView.textEditor.addEventListener(
SourceFrame.SourcesTextEditor.Events.ScrollChanged, this._scrollChanged, this);
this._currentView.textEditor.addEventListener(
@@ -219,8 +225,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
}
_removeViewListeners() {
- if (!this._currentView || !this._currentView.textEditor)
+ if (!this._currentView || !this._currentView.textEditor) {
return;
+ }
this._currentView.textEditor.removeEventListener(
SourceFrame.SourcesTextEditor.Events.ScrollChanged, this._scrollChanged, this);
this._currentView.textEditor.removeEventListener(
@@ -231,8 +238,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
* @param {!Common.Event} event
*/
_scrollChanged(event) {
- if (this._scrollTimer)
+ if (this._scrollTimer) {
clearTimeout(this._scrollTimer);
+ }
const lineNumber = /** @type {number} */ (event.data);
this._scrollTimer = setTimeout(saveHistory.bind(this), 100);
this._history.updateScrollLineNumber(this._currentFile.url(), lineNumber);
@@ -263,8 +271,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
_innerShowFile(uiSourceCode, userGesture) {
const binding = Persistence.persistence.binding(uiSourceCode);
uiSourceCode = binding ? binding.fileSystem : uiSourceCode;
- if (this._currentFile === uiSourceCode)
+ if (this._currentFile === uiSourceCode) {
return;
+ }
this._removeViewListeners();
this._currentFile = uiSourceCode;
@@ -272,8 +281,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
const tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, userGesture);
this._tabbedPane.selectTab(tabId, userGesture);
- if (userGesture)
+ if (userGesture) {
this._editorSelectedByUserAction();
+ }
const previousView = this._currentView;
this._currentView = this.visibleView;
@@ -295,8 +305,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
_titleForFile(uiSourceCode) {
const maxDisplayNameLength = 30;
let title = uiSourceCode.displayName(true).trimMiddle(maxDisplayNameLength);
- if (uiSourceCode.isDirty())
+ if (uiSourceCode.isDirty()) {
title += '*';
+ }
return title;
}
@@ -311,8 +322,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
if (!shouldPrompt ||
confirm(Common.UIString('Are you sure you want to close unsaved file: %s?', uiSourceCode.name()))) {
uiSourceCode.resetWorkingCopy();
- if (nextTabId)
+ if (nextTabId) {
this._tabbedPane.selectTab(nextTabId, true);
+ }
this._tabbedPane.closeTab(id, true);
return true;
}
@@ -329,18 +341,21 @@ Sources.TabbedEditorContainer = class extends Common.Object {
for (let i = 0; i < ids.length; ++i) {
const id = ids[i];
const uiSourceCode = this._files[id];
- if (!forceCloseDirtyTabs && uiSourceCode.isDirty())
+ if (!forceCloseDirtyTabs && uiSourceCode.isDirty()) {
dirtyTabs.push(id);
- else
+ } else {
cleanTabs.push(id);
+ }
}
- if (dirtyTabs.length)
+ if (dirtyTabs.length) {
this._tabbedPane.selectTab(dirtyTabs[0], true);
+ }
this._tabbedPane.closeTabs(cleanTabs, true);
for (let i = 0; i < dirtyTabs.length; ++i) {
const nextTabId = i + 1 < dirtyTabs.length ? dirtyTabs[i + 1] : null;
- if (!this._maybeCloseTab(dirtyTabs[i], nextTabId))
+ if (!this._maybeCloseTab(dirtyTabs[i], nextTabId)) {
break;
+ }
}
}
@@ -350,8 +365,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
*/
_onContextMenu(tabId, contextMenu) {
const uiSourceCode = this._files[tabId];
- if (uiSourceCode)
+ if (uiSourceCode) {
contextMenu.appendApplicableItems(uiSourceCode);
+ }
}
/**
@@ -360,16 +376,19 @@ Sources.TabbedEditorContainer = class extends Common.Object {
addUISourceCode(uiSourceCode) {
const binding = Persistence.persistence.binding(uiSourceCode);
uiSourceCode = binding ? binding.fileSystem : uiSourceCode;
- if (this._currentFile === uiSourceCode)
+ if (this._currentFile === uiSourceCode) {
return;
+ }
const uri = uiSourceCode.url();
const index = this._history.index(uri);
- if (index === -1)
+ if (index === -1) {
return;
+ }
- if (!this._tabIds.has(uiSourceCode))
+ if (!this._tabIds.has(uiSourceCode)) {
this._appendFileTab(uiSourceCode, false);
+ }
// Select tab if this file was the last to be shown.
if (!index) {
@@ -377,13 +396,15 @@ Sources.TabbedEditorContainer = class extends Common.Object {
return;
}
- if (!this._currentFile)
+ if (!this._currentFile) {
return;
+ }
const currentProjectIsSnippets = Snippets.isSnippetsUISourceCode(this._currentFile);
const addedProjectIsSnippets = Snippets.isSnippetsUISourceCode(uiSourceCode);
- if (this._history.index(this._currentFile.url()) && currentProjectIsSnippets && !addedProjectIsSnippets)
+ if (this._history.index(this._currentFile.url()) && currentProjectIsSnippets && !addedProjectIsSnippets) {
this._innerShowFile(uiSourceCode, false);
+ }
}
/**
@@ -401,8 +422,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
for (let i = 0; i < uiSourceCodes.length; ++i) {
const uiSourceCode = uiSourceCodes[i];
const tabId = this._tabIds.get(uiSourceCode);
- if (tabId)
+ if (tabId) {
tabIds.push(tabId);
+ }
}
this._tabbedPane.closeTabs(tabIds);
}
@@ -469,10 +491,28 @@ Sources.TabbedEditorContainer = class extends Common.Object {
this._updateFileTitle(uiSourceCode);
this._addUISourceCodeListeners(uiSourceCode);
+ if (uiSourceCode.loadError()) {
+ this._addLoadErrorIcon(tabId);
+ } else if (!uiSourceCode.contentLoaded()) {
+ uiSourceCode.requestContent().then(content => {
+ if (uiSourceCode.loadError()) {
+ this._addLoadErrorIcon(tabId);
+ }
+ });
+ }
return tabId;
}
/**
+ * @param {string} tabId
+ */
+ _addLoadErrorIcon(tabId) {
+ const icon = UI.Icon.create('smallicon-error');
+ icon.title = ls`Unable to load this content.`;
+ this._tabbedPane.setTabIcon(tabId, icon);
+ }
+
+ /**
* @param {!UI.Widget} editorView
* @param {!TextUtils.TextRange=} selection
* @param {number=} firstLineNumber
@@ -480,12 +520,15 @@ Sources.TabbedEditorContainer = class extends Common.Object {
_restoreEditorProperties(editorView, selection, firstLineNumber) {
const sourceFrame =
editorView instanceof SourceFrame.SourceFrame ? /** @type {!SourceFrame.SourceFrame} */ (editorView) : null;
- if (!sourceFrame)
+ if (!sourceFrame) {
return;
- if (selection)
+ }
+ if (selection) {
sourceFrame.setSelection(selection);
- if (typeof firstLineNumber === 'number')
+ }
+ if (typeof firstLineNumber === 'number') {
sourceFrame.scrollToLine(firstLineNumber);
+ }
}
/**
@@ -508,8 +551,9 @@ Sources.TabbedEditorContainer = class extends Common.Object {
this.dispatchEventToListeners(Sources.TabbedEditorContainer.Events.EditorClosed, uiSourceCode);
- if (userGesture)
+ if (userGesture) {
this._editorClosedByUserAction(uiSourceCode);
+ }
}
/**
@@ -552,9 +596,13 @@ Sources.TabbedEditorContainer = class extends Common.Object {
const tabId = this._tabIds.get(uiSourceCode);
if (tabId) {
const title = this._titleForFile(uiSourceCode);
- this._tabbedPane.changeTabTitle(tabId, title);
+ const tooltip = this._tooltipForFile(uiSourceCode);
+ this._tabbedPane.changeTabTitle(tabId, title, tooltip);
let icon = null;
- if (Persistence.persistence.hasUnsavedCommittedChanges(uiSourceCode)) {
+ if (uiSourceCode.loadError()) {
+ icon = UI.Icon.create('smallicon-error');
+ icon.title = ls`Unable to load this content.`;
+ } else if (Persistence.persistence.hasUnsavedCommittedChanges(uiSourceCode)) {
icon = UI.Icon.create('smallicon-warning');
icon.title = Common.UIString('Changes to this file were not saved to file system.');
} else {
@@ -647,8 +695,9 @@ Sources.TabbedEditorContainer.HistoryItem = class {
* @return {?Object}
*/
serializeToObject() {
- if (!this._isSerializable)
+ if (!this._isSerializable) {
return null;
+ }
const serializedHistoryItem = {};
serializedHistoryItem.url = this.url;
serializedHistoryItem.selectionRange = this.selectionRange;
@@ -678,8 +727,9 @@ Sources.TabbedEditorContainer.History = class {
*/
static fromObject(serializedHistory) {
const items = [];
- for (let i = 0; i < serializedHistory.length; ++i)
+ for (let i = 0; i < serializedHistory.length; ++i) {
items.push(Sources.TabbedEditorContainer.HistoryItem.fromObject(serializedHistory[i]));
+ }
return new Sources.TabbedEditorContainer.History(items);
}
@@ -714,11 +764,13 @@ Sources.TabbedEditorContainer.History = class {
* @param {!TextUtils.TextRange=} selectionRange
*/
updateSelectionRange(url, selectionRange) {
- if (!selectionRange)
+ if (!selectionRange) {
return;
+ }
const index = this.index(url);
- if (index === -1)
+ if (index === -1) {
return;
+ }
this._items[index].selectionRange = selectionRange;
}
@@ -737,8 +789,9 @@ Sources.TabbedEditorContainer.History = class {
*/
updateScrollLineNumber(url, scrollLineNumber) {
const index = this.index(url);
- if (index === -1)
+ if (index === -1) {
return;
+ }
this._items[index].scrollLineNumber = scrollLineNumber;
}
@@ -785,10 +838,12 @@ Sources.TabbedEditorContainer.History = class {
const serializedHistory = [];
for (let i = 0; i < this._items.length; ++i) {
const serializedItem = this._items[i].serializeToObject();
- if (serializedItem)
+ if (serializedItem) {
serializedHistory.push(serializedItem);
- if (serializedHistory.length === Sources.TabbedEditorContainer.maximalPreviouslyViewedFilesCount)
+ }
+ if (serializedHistory.length === Sources.TabbedEditorContainer.maximalPreviouslyViewedFilesCount) {
break;
+ }
}
return serializedHistory;
}
@@ -798,8 +853,9 @@ Sources.TabbedEditorContainer.History = class {
*/
_urls() {
const result = [];
- for (let i = 0; i < this._items.length; ++i)
+ for (let i = 0; i < this._items.length; ++i) {
result.push(this._items[i].url);
+ }
return result;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/ThreadsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/ThreadsSidebarPane.js
index fdeef9ac40c..229325bad81 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/ThreadsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/ThreadsSidebarPane.js
@@ -53,8 +53,9 @@ Sources.ThreadsSidebarPane = class extends UI.VBox {
*/
function targetNameChanged(event) {
const target = /** @type {!SDK.Target} */ (event.data);
- if (target === debuggerModel.target())
+ if (target === debuggerModel.target()) {
updateTitle();
+ }
}
debuggerModel.addEventListener(SDK.DebuggerModel.Events.DebuggerPaused, updatePausedState);
@@ -94,12 +95,15 @@ Sources.ThreadsSidebarPane = class extends UI.VBox {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('selected');
- if (to)
+ }
+ if (to) {
UI.context.setFlavor(SDK.Target, to.target());
+ }
}
/**
@@ -109,8 +113,9 @@ Sources.ThreadsSidebarPane = class extends UI.VBox {
modelAdded(debuggerModel) {
this._items.insert(this._items.length, debuggerModel);
const currentTarget = UI.context.flavor(SDK.Target);
- if (currentTarget === debuggerModel.target())
+ if (currentTarget === debuggerModel.target()) {
this._list.selectItem(debuggerModel);
+ }
}
/**
@@ -127,7 +132,8 @@ Sources.ThreadsSidebarPane = class extends UI.VBox {
_targetFlavorChanged(event) {
const target = /** @type {!SDK.Target} */ (event.data);
const debuggerModel = target.model(SDK.DebuggerModel);
- if (debuggerModel)
+ if (debuggerModel) {
this._list.selectItem(debuggerModel);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/UISourceCodeFrame.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/UISourceCodeFrame.js
index 727fe808798..7ae2ace8fe1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/UISourceCodeFrame.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/UISourceCodeFrame.js
@@ -34,8 +34,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
super(workingCopy);
this._uiSourceCode = uiSourceCode;
- if (Runtime.experiments.isEnabled('sourceDiff'))
+ if (Root.Runtime.experiments.isEnabled('sourceDiff')) {
this._diff = new SourceFrame.SourceCodeDiff(this.textEditor);
+ }
this._muteSourceCodeEvents = false;
this._isSettingContent = false;
@@ -74,11 +75,12 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
this._initializeUISourceCode();
/**
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
function workingCopy() {
- if (uiSourceCode.isDirty())
- return /** @type {!Promise<?string>} */ (Promise.resolve(uiSourceCode.workingCopy()));
+ if (uiSourceCode.isDirty()) {
+ return Promise.resolve({content: uiSourceCode.workingCopy(), isEncoded: false});
+ }
return uiSourceCode.requestContent();
}
}
@@ -125,14 +127,17 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
this._unloadUISourceCode();
this._uiSourceCode = uiSourceCode;
if (uiSourceCode.contentLoaded()) {
- if (uiSourceCode.workingCopy() !== this.textEditor.text())
+ if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
this._innerSetContent(uiSourceCode.workingCopy());
+ }
} else {
uiSourceCode.requestContent().then(() => {
- if (this._uiSourceCode !== uiSourceCode)
+ if (this._uiSourceCode !== uiSourceCode) {
return;
- if (uiSourceCode.workingCopy() !== this.textEditor.text())
+ }
+ if (uiSourceCode.workingCopy() !== this.textEditor.text()) {
this._innerSetContent(uiSourceCode.workingCopy());
+ }
});
}
this._initializeUISourceCode();
@@ -140,8 +145,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
_unloadUISourceCode() {
this._disposePlugins();
- for (const message of this._allMessages())
+ for (const message of this._allMessages()) {
this._removeMessageFromSource(message);
+ }
Common.EventTarget.removeEventListeners(this._messageAndDecorationListeners);
Common.EventTarget.removeEventListeners(this._uiSourceCodeEventListeners);
this._uiSourceCode.removeWorkingCopyGetter();
@@ -159,13 +165,14 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
];
Persistence.persistence.subscribeForBindingEvent(this._uiSourceCode, this._boundOnBindingChanged);
- for (const message of this._allMessages())
+ for (const message of this._allMessages()) {
this._addMessageToSource(message);
+ }
this._installMessageAndDecorationListeners();
this._updateStyle();
this._decorateAllTypes();
this._refreshHighlighterType();
- if (Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
+ if (Root.Runtime.experiments.isEnabled('sourcesPrettyPrint')) {
const supportedPrettyTypes = new Set(['text/html', 'text/css', 'text/javascript']);
this.setCanPrettyPrint(supportedPrettyTypes.has(this.highlighterType()), true);
}
@@ -180,16 +187,18 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
// We need CodeMirrorTextEditor to be initialized prior to this call as it calls |cursorPositionToCoordinates| internally. @see crbug.com/506566
setImmediate(this._updateBucketDecorations.bind(this));
this.setEditable(this._canEditSource());
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
plugin.wasShown();
+ }
}
/**
* @override
*/
willHide() {
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
plugin.willHide();
+ }
super.willHide();
UI.context.setFlavor(Sources.UISourceCodeFrame, null);
this._uiSourceCode.removeWorkingCopyGetter();
@@ -198,8 +207,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
_refreshHighlighterType() {
const binding = Persistence.persistence.binding(this._uiSourceCode);
const highlighterType = binding ? binding.network.mimeType() : this._uiSourceCode.mimeType();
- if (this.highlighterType() === highlighterType)
+ if (this.highlighterType() === highlighterType) {
return;
+ }
this._disposePlugins();
this.setHighlighterType(highlighterType);
this._ensurePluginsLoaded();
@@ -209,18 +219,26 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @return {boolean}
*/
_canEditSource() {
- if (Persistence.persistence.binding(this._uiSourceCode))
+ if (this.hasLoadError()) {
+ return false;
+ }
+ if (Persistence.persistence.binding(this._uiSourceCode)) {
return true;
- if (this._uiSourceCode.project().canSetFileContent())
+ }
+ if (this._uiSourceCode.project().canSetFileContent()) {
return true;
- if (this._uiSourceCode.project().isServiceProject())
+ }
+ if (this._uiSourceCode.project().isServiceProject()) {
return false;
+ }
if (this._uiSourceCode.project().type() === Workspace.projectTypes.Network &&
- Persistence.networkPersistenceManager.active())
+ Persistence.networkPersistenceManager.active()) {
return true;
+ }
// Because live edit fails on large whitespace changes, pretty printed scripts are not editable.
- if (this.pretty && this._uiSourceCode.contentType().hasScripts())
+ if (this.pretty && this._uiSourceCode.contentType().hasScripts()) {
return false;
+ }
return this._uiSourceCode.contentType() !== Common.resourceTypes.Document;
}
@@ -229,8 +247,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
}
commitEditing() {
- if (!this._uiSourceCode.isDirty())
+ if (!this._uiSourceCode.isDirty()) {
return;
+ }
this._muteSourceCodeEvents = true;
this._uiSourceCode.commitWorkingCopy();
@@ -240,13 +259,15 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
/**
* @override
* @param {?string} content
+ * @param {?string} loadError
*/
- setContent(content) {
+ setContent(content, loadError) {
this._disposePlugins();
this._rowMessageBuckets.clear();
- super.setContent(content);
- for (const message of this._allMessages())
+ super.setContent(content, loadError);
+ for (const message of this._allMessages()) {
this._addMessageToSource(message);
+ }
this._decorateAllTypes();
this._ensurePluginsLoaded();
}
@@ -272,14 +293,16 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
const wasPretty = this.pretty;
super.onTextChanged(oldRange, newRange);
this._errorPopoverHelper.hidePopover();
- if (this._isSettingContent)
+ if (this._isSettingContent) {
return;
+ }
Sources.SourcesPanel.instance().updateLastModificationTime();
this._muteSourceCodeEvents = true;
- if (this.isClean())
+ if (this.isClean()) {
this._uiSourceCode.resetWorkingCopy();
- else
+ } else {
this._uiSourceCode.setWorkingCopyGetter(this.textEditor.text.bind(this.textEditor));
+ }
this._muteSourceCodeEvents = false;
if (wasPretty !== this.pretty) {
this._updateStyle();
@@ -292,8 +315,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @param {!Common.Event} event
*/
_onWorkingCopyChanged(event) {
- if (this._muteSourceCodeEvents)
+ if (this._muteSourceCodeEvents) {
return;
+ }
this._innerSetContent(this._uiSourceCode.workingCopy());
}
@@ -301,51 +325,62 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @param {!Common.Event} event
*/
_onWorkingCopyCommitted(event) {
- if (!this._muteSourceCodeEvents)
+ if (!this._muteSourceCodeEvents) {
this._innerSetContent(this._uiSourceCode.workingCopy());
+ }
this.contentCommitted();
this._updateStyle();
}
_ensurePluginsLoaded() {
- if (!this.loaded || this._plugins.length)
+ if (!this.loaded || this._plugins.length) {
return;
+ }
const binding = Persistence.persistence.binding(this._uiSourceCode);
const pluginUISourceCode = binding ? binding.network : this._uiSourceCode;
// The order of these plugins matters for toolbar items
- if (Sources.DebuggerPlugin.accepts(pluginUISourceCode))
+ if (Sources.DebuggerPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.DebuggerPlugin(this.textEditor, pluginUISourceCode, this.transformer()));
- if (Sources.CSSPlugin.accepts(pluginUISourceCode))
+ }
+ if (Sources.CSSPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.CSSPlugin(this.textEditor));
- if (!this.pretty && Sources.JavaScriptCompilerPlugin.accepts(pluginUISourceCode))
+ }
+ if (!this.pretty && Sources.JavaScriptCompilerPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.JavaScriptCompilerPlugin(this.textEditor, pluginUISourceCode));
- if (Sources.SnippetsPlugin.accepts(pluginUISourceCode))
+ }
+ if (Sources.SnippetsPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.SnippetsPlugin(this.textEditor, pluginUISourceCode));
- if (Sources.ScriptOriginPlugin.accepts(pluginUISourceCode))
+ }
+ if (Sources.ScriptOriginPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.ScriptOriginPlugin(this.textEditor, pluginUISourceCode));
- if (!this.pretty && Runtime.experiments.isEnabled('sourceDiff') &&
- Sources.GutterDiffPlugin.accepts(pluginUISourceCode))
+ }
+ if (!this.pretty && Root.Runtime.experiments.isEnabled('sourceDiff') &&
+ Sources.GutterDiffPlugin.accepts(pluginUISourceCode)) {
this._plugins.push(new Sources.GutterDiffPlugin(this.textEditor, pluginUISourceCode));
+ }
this.dispatchEventToListeners(Sources.UISourceCodeFrame.Events.ToolbarItemsChanged);
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
plugin.wasShown();
+ }
}
_disposePlugins() {
this.textEditor.operation(() => {
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
plugin.dispose();
+ }
});
this._plugins = [];
}
_onBindingChanged() {
const binding = Persistence.persistence.binding(this._uiSourceCode);
- if (binding === this._persistenceBinding)
+ if (binding === this._persistenceBinding) {
return;
+ }
this._unloadUISourceCode();
this._persistenceBinding = binding;
this._initializeUISourceCode();
@@ -361,10 +396,12 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
_innerSetContent(content) {
this._isSettingContent = true;
const oldContent = this.textEditor.text();
- if (this._diff)
+ if (this._diff) {
this._diff.highlightModifiedLines(oldContent, content);
- if (oldContent !== content)
- this.setContent(content);
+ }
+ if (oldContent !== content) {
+ this.setContent(content, null);
+ }
this._isSettingContent = false;
}
@@ -378,8 +415,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
const location = this.transformer().editorToRawLocation(editorLineNumber, editorColumnNumber);
contextMenu.appendApplicableItems(new Workspace.UILocation(this._uiSourceCode, location[0], location[1]));
contextMenu.appendApplicableItems(this);
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
await plugin.populateTextAreaContextMenu(contextMenu, editorLineNumber, editorColumnNumber);
+ }
}
dispose() {
@@ -403,14 +441,17 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @param {!Workspace.UISourceCode.Message} message
*/
_addMessageToSource(message) {
- if (!this.loaded)
+ if (!this.loaded) {
return;
+ }
const editorLocation = this.transformer().rawToEditorLocation(message.lineNumber(), message.columnNumber());
let editorLineNumber = editorLocation[0];
- if (editorLineNumber >= this.textEditor.linesCount)
+ if (editorLineNumber >= this.textEditor.linesCount) {
editorLineNumber = this.textEditor.linesCount - 1;
- if (editorLineNumber < 0)
+ }
+ if (editorLineNumber < 0) {
editorLineNumber = 0;
+ }
let messageBucket = this._rowMessageBuckets.get(editorLineNumber);
if (!messageBucket) {
@@ -432,19 +473,23 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @param {!Workspace.UISourceCode.Message} message
*/
_removeMessageFromSource(message) {
- if (!this.loaded)
+ if (!this.loaded) {
return;
+ }
const editorLocation = this.transformer().rawToEditorLocation(message.lineNumber(), message.columnNumber());
let editorLineNumber = editorLocation[0];
- if (editorLineNumber >= this.textEditor.linesCount)
+ if (editorLineNumber >= this.textEditor.linesCount) {
editorLineNumber = this.textEditor.linesCount - 1;
- if (editorLineNumber < 0)
+ }
+ if (editorLineNumber < 0) {
editorLineNumber = 0;
+ }
const messageBucket = this._rowMessageBuckets.get(editorLineNumber);
- if (!messageBucket)
+ if (!messageBucket) {
return;
+ }
messageBucket.removeMessage(message);
if (!messageBucket.uniqueMessagesCount()) {
messageBucket.detachFromEditor();
@@ -459,8 +504,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
_getErrorPopoverContent(event) {
const element = event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ||
event.target.enclosingNodeOrSelfWithClass('text-editor-line-decoration-wave');
- if (!element)
+ if (!element) {
return null;
+ }
const anchor = element.enclosingNodeOrSelfWithClass('text-editor-line-decoration-icon') ?
element.boxInWindow() :
new AnchorBox(event.clientX, event.clientY, 1, 1);
@@ -476,8 +522,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
}
_updateBucketDecorations() {
- for (const bucket of this._rowMessageBuckets.values())
+ for (const bucket of this._rowMessageBuckets.values()) {
bucket._updateDecoration();
+ }
}
/**
@@ -500,8 +547,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
* @param {string} type
*/
async _decorateTypeThrottled(type) {
- if (this._typeDecorationsPending.has(type))
+ if (this._typeDecorationsPending.has(type)) {
return;
+ }
this._typeDecorationsPending.add(type);
const decorator = await self.runtime.extensions(SourceFrame.LineDecorator)
.find(extension => extension.descriptor()['decoratorType'] === type)
@@ -514,12 +562,14 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
}
_decorateAllTypes() {
- if (!this.loaded)
+ if (!this.loaded) {
return;
+ }
for (const extension of self.runtime.extensions(SourceFrame.LineDecorator)) {
const type = extension.descriptor()['decoratorType'];
- if (this._uiSourceCode.decorationsForType(type))
+ if (this._uiSourceCode.decorationsForType(type)) {
this._decorateTypeThrottled(type);
+ }
}
}
@@ -535,8 +585,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
rightToolbarItems.pushAll(plugin.rightToolbarItems());
}
- if (!rightToolbarItems.length)
+ if (!rightToolbarItems.length) {
return leftToolbarItems;
+ }
return [...leftToolbarItems, new UI.ToolbarSeparator(true), ...rightToolbarItems];
}
@@ -549,8 +600,9 @@ Sources.UISourceCodeFrame = class extends SourceFrame.SourceFrame {
*/
async populateLineGutterContextMenu(contextMenu, lineNumber) {
await super.populateLineGutterContextMenu(contextMenu, lineNumber);
- for (const plugin of this._plugins)
+ for (const plugin of this._plugins) {
await plugin.populateLineGutterContextMenu(contextMenu, lineNumber);
+ }
}
};
@@ -607,8 +659,9 @@ Sources.UISourceCodeFrame.RowMessage = class {
}
setRepeatCount(repeatCount) {
- if (this._repeatCount === repeatCount)
+ if (this._repeatCount === repeatCount) {
return;
+ }
this._repeatCount = repeatCount;
this._updateMessageRepeatCount();
}
@@ -655,10 +708,12 @@ Sources.UISourceCodeFrame.RowMessageBucket = class {
columnNumber = Math.min(columnNumber, lineText.length);
const lineIndent = TextUtils.TextUtils.lineIndent(lineText).length;
const startColumn = Math.max(columnNumber - 1, lineIndent);
- if (this._decorationStartColumn === startColumn)
+ if (this._decorationStartColumn === startColumn) {
return;
- if (this._decorationStartColumn !== null)
+ }
+ if (this._decorationStartColumn !== null) {
this.textEditor.removeDecoration(this._decoration, editorLineNumber);
+ }
this.textEditor.addDecoration(this._decoration, editorLineNumber, startColumn);
this._decorationStartColumn = startColumn;
}
@@ -669,16 +724,18 @@ Sources.UISourceCodeFrame.RowMessageBucket = class {
messagesDescription() {
this._messagesDescriptionElement.removeChildren();
UI.appendStyle(this._messagesDescriptionElement, 'source_frame/messagesPopover.css');
- for (let i = 0; i < this._messages.length; ++i)
+ for (let i = 0; i < this._messages.length; ++i) {
this._messagesDescriptionElement.appendChild(this._messages[i].element);
+ }
return this._messagesDescriptionElement;
}
detachFromEditor() {
const position = this._lineHandle.resolve();
- if (!position)
+ if (!position) {
return;
+ }
const editorLineNumber = position.lineNumber;
if (this._level) {
this.textEditor.toggleLineClass(
@@ -720,24 +777,29 @@ Sources.UISourceCodeFrame.RowMessageBucket = class {
removeMessage(message) {
for (let i = 0; i < this._messages.length; ++i) {
const rowMessage = this._messages[i];
- if (!rowMessage.message().isEqual(message))
+ if (!rowMessage.message().isEqual(message)) {
continue;
+ }
rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
- if (!rowMessage.repeatCount())
+ if (!rowMessage.repeatCount()) {
this._messages.splice(i, 1);
+ }
this._updateDecoration();
return;
}
}
_updateDecoration() {
- if (!this._sourceFrame.isShowing())
+ if (!this._sourceFrame.isShowing()) {
return;
- if (!this._messages.length)
+ }
+ if (!this._messages.length) {
return;
+ }
const position = this._lineHandle.resolve();
- if (!position)
+ if (!position) {
return;
+ }
const editorLineNumber = position.lineNumber;
let columnNumber = Number.MAX_VALUE;
@@ -747,21 +809,24 @@ Sources.UISourceCodeFrame.RowMessageBucket = class {
const editorLocation =
this._sourceFrame.transformer().rawToEditorLocation(editorLineNumber, message.columnNumber());
columnNumber = Math.min(columnNumber, editorLocation[1]);
- if (!maxMessage || Workspace.UISourceCode.Message.messageLevelComparator(maxMessage, message) < 0)
+ if (!maxMessage || Workspace.UISourceCode.Message.messageLevelComparator(maxMessage, message) < 0) {
maxMessage = message;
+ }
}
this._updateWavePosition(editorLineNumber, columnNumber);
- if (this._level === maxMessage.level())
+ if (this._level === maxMessage.level()) {
return;
+ }
if (this._level) {
this.textEditor.toggleLineClass(
editorLineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], false);
this._icon.type = '';
}
this._level = maxMessage.level();
- if (!this._level)
+ if (!this._level) {
return;
+ }
this.textEditor.toggleLineClass(editorLineNumber, Sources.UISourceCodeFrame._lineClassPerLevel[this._level], true);
this._icon.type = Sources.UISourceCodeFrame._iconClassPerLevel[this._level];
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
index 73737625680..565b60bbe13 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -76,8 +76,9 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
_saveExpressions() {
const toSave = [];
for (let i = 0; i < this._watchExpressions.length; i++) {
- if (this._watchExpressions[i].expression())
+ if (this._watchExpressions[i].expression()) {
toSave.push(this._watchExpressions[i].expression());
+ }
}
this._watchExpressionsSetting.set(toSave);
@@ -101,8 +102,9 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
const watchExpressionStrings = this._watchExpressionsSetting.get();
for (let i = 0; i < watchExpressionStrings.length; ++i) {
const expression = watchExpressionStrings[i];
- if (!expression)
+ if (!expression) {
continue;
+ }
this._createWatchExpression(expression);
}
@@ -152,11 +154,13 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
*/
_populateContextMenu(contextMenu, event) {
let isEditing = false;
- for (const watchExpression of this._watchExpressions)
+ for (const watchExpression of this._watchExpressions) {
isEditing |= watchExpression.isEditing();
+ }
- if (!isEditing)
+ if (!isEditing) {
contextMenu.debugSection().appendItem(Common.UIString('Add watch expression'), this._addButtonClicked.bind(this));
+ }
if (this._watchExpressions.length > 1) {
contextMenu.debugSection().appendItem(
@@ -165,11 +169,13 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
const target = event.deepElementFromPoint();
- if (!target)
+ if (!target) {
return;
+ }
for (const watchExpression of this._watchExpressions) {
- if (watchExpression.element().isSelfOrAncestor(target))
+ if (watchExpression.element().isSelfOrAncestor(target)) {
watchExpression._populateContextMenu(contextMenu, event);
+ }
}
}
@@ -204,8 +210,9 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
*/
handleAction(context, actionId) {
const frame = UI.context.flavor(Sources.UISourceCodeFrame);
- if (!frame)
+ if (!frame) {
return false;
+ }
const text = frame.textEditor.text(frame.textEditor.selection());
this._focusAndAddExpressionToWatch(text);
return true;
@@ -231,8 +238,9 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
}
const frame = UI.context.flavor(Sources.UISourceCodeFrame);
- if (!frame || frame.textEditor.selection().isEmpty())
+ if (!frame || frame.textEditor.selection().isEmpty()) {
return;
+ }
contextMenu.debugSection().appendAction('sources.add-to-watch');
}
@@ -317,8 +325,9 @@ Sources.WatchExpression = class extends Common.Object {
* @param {boolean=} canceled
*/
_finishEditing(event, canceled) {
- if (event)
+ if (event) {
event.consume(canceled);
+ }
this._editing = false;
this._textPrompt.detach();
@@ -334,16 +343,18 @@ Sources.WatchExpression = class extends Common.Object {
*/
_dblClickOnWatchExpression(event) {
event.consume();
- if (!this.isEditing())
+ if (!this.isEditing()) {
this.startEditing();
+ }
}
/**
* @param {?string} newExpression
*/
_updateExpression(newExpression) {
- if (this._expression)
+ if (this._expression) {
this._expandController.stopWatchSectionsWithId(this._expression);
+ }
this._expression = newExpression;
this.update();
this.dispatchEventToListeners(Sources.WatchExpression.Events.ExpressionUpdated, this);
@@ -420,14 +431,16 @@ Sources.WatchExpression = class extends Common.Object {
* @this {Sources.WatchExpression}
*/
function handleClick() {
- if (!this._objectPropertiesSection)
+ if (!this._objectPropertiesSection) {
return;
+ }
const objectTreeElement = this._objectPropertiesSection.objectTreeElement();
- if (objectTreeElement.expanded)
+ if (objectTreeElement.expanded) {
objectTreeElement.collapse();
- else
+ } else {
objectTreeElement.expand();
+ }
}
}
@@ -435,8 +448,9 @@ Sources.WatchExpression = class extends Common.Object {
* @param {!Event} event
*/
_promptKeyDown(event) {
- if (isEnterKey(event) || isEscKey(event))
+ if (isEnterKey(event) || isEscKey(event)) {
this._finishEditing(event, isEscKey(event));
+ }
}
/**
@@ -450,16 +464,18 @@ Sources.WatchExpression = class extends Common.Object {
}
- if (!this.isEditing() && this._result && (this._result.type === 'number' || this._result.type === 'string'))
+ if (!this.isEditing() && this._result && (this._result.type === 'number' || this._result.type === 'string')) {
contextMenu.clipboardSection().appendItem(Common.UIString('Copy value'), this._copyValueButtonClicked.bind(this));
+ }
const target = event.deepElementFromPoint();
- if (target && this._valueElement.isSelfOrAncestor(target))
+ if (target && this._valueElement.isSelfOrAncestor(target)) {
contextMenu.appendApplicableItems(this._result);
+ }
}
_copyValueButtonClicked() {
- InspectorFrontendHost.copyText(this._valueElement.textContent);
+ Host.InspectorFrontendHost.copyText(this._valueElement.textContent);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/sourcesPanel.css b/chromium/third_party/blink/renderer/devtools/front_end/sources/sourcesPanel.css
index 05c22cdaa68..258325bd7e2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/sourcesPanel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/sourcesPanel.css
@@ -51,11 +51,15 @@
}
.scripts-debug-toolbar-drawer > [is=dt-checkbox] {
- display: flex;
+ display: none;
padding-left: 3px;
height: 28px;
}
+.scripts-debug-toolbar-drawer.expanded > [is=dt-checkbox] {
+ display: flex;
+}
+
.cursor-auto {
cursor: auto;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
index d940c10093f..bc0719240a3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/sources_strings.grdp
@@ -63,6 +63,9 @@
<message name="IDS_DEVTOOLS_1f15646f60fc3c1dea747963f02d51ac" desc="Text in Sources Panel of the Sources panel">
Group by folder
</message>
+ <message name="IDS_DEVTOOLS_1fbbb6684f67ee895ff5dc2e429697ce" desc="Screen reader label for a select box that chooses the breakpoint type in the Sources panel when editing a breakpoint">
+ Breakpoint type
+ </message>
<message name="IDS_DEVTOOLS_216a9080bf22a993b2d7f9331d34cc68" desc="Text in Sources Panel of the Sources panel">
Don&apos;t pause on exceptions
</message>
@@ -148,7 +151,7 @@
Override page assets with files from a local folder
</message>
<message name="IDS_DEVTOOLS_49a4a1505587da9f4475db7ee9958853" desc="Text in Sources Navigator of the Sources panel">
- Sync changes in DevTools with the local filesystem
+ Sync changes in <ph name="LOCKED_1">DevTools</ph> with the local filesystem
</message>
<message name="IDS_DEVTOOLS_4b3812a22a58f04fb5a0598658a3bd27" desc="Title of the Filtered List WidgetProvider of Quick Open">
Go to symbol
@@ -165,18 +168,12 @@
<message name="IDS_DEVTOOLS_520d0db389f362bf79ef56ca0af3dcab" desc="Tooltip text that appears when hovering over the largeicon pretty print button in the Inplace Formatter Editor Action of the Sources panel">
Format
</message>
- <message name="IDS_DEVTOOLS_52b3bc5e77aa070243c36cd40a4d6b6d" desc="Title of a setting under the Sources category in Settings">
- Autocompletion
- </message>
<message name="IDS_DEVTOOLS_58943fa26a94bc86f7f45106080e4496" desc="Title of an action under the Debugger category that can be invoked through the Command Menu">
Resume script execution
</message>
<message name="IDS_DEVTOOLS_590d0b32e1139c6c3bcb0f99ed978dff" desc="Text in Debugger Paused Message of the Sources panel">
subtree modifications
</message>
- <message name="IDS_DEVTOOLS_5a0a64ecca63ba9a006b6397cbdc2b8c" desc="Title of the Filtered List WidgetProvider of Quick Open">
- Go to line
- </message>
<message name="IDS_DEVTOOLS_5a3bb6a64da384e59876cd0bc00a6eae" desc="Unblackbox link text content in Debugger Plugin of the Sources panel">
Unblackbox this script
</message>
@@ -388,7 +385,7 @@
Remove other breakpoints
</message>
<message name="IDS_DEVTOOLS_b9947e230aa5ac451e3b0649bdb1c7fc" desc="Event return value in Sources View of the Sources panel">
- DevTools have unsaved changes that will be permanently lost.
+ <ph name="LOCKED_1">DevTools</ph> have unsaved changes that will be permanently lost.
</message>
<message name="IDS_DEVTOOLS_bb9f288b958ce8c8d250cb392e2f1309" desc="Text in Debugger Plugin of the Sources panel">
You can click the <ph name="TOOLBAR_ELEMENT">$1s<ex>{}</ex></ph> button on the bottom status bar, and continue debugging with the new formatted source.
@@ -426,6 +423,9 @@
<message name="IDS_DEVTOOLS_cd26a6a87959e99fdf99f5ccccef0464" desc="Text in Debugger Plugin of the Sources panel">
Disable breakpoint
</message>
+ <message name="IDS_DEVTOOLS_d016c1bd981f59db972acf1b83201591" desc="Accessible label for Sources placeholder view actions list">
+ Empty Source View Actions
+ </message>
<message name="IDS_DEVTOOLS_d07d651006c823c6f008158f6eb63056" desc="Tooltip text that appears when hovering over the largeicon play button in the Sources Panel of the Sources panel">
Resume with all pauses blocked for 500 ms
</message>
@@ -474,6 +474,9 @@
<message name="IDS_DEVTOOLS_e68f8487d76aeb933b5b06d7999a0e44" desc="Title of a setting under the Sources category that can be invoked through the Command Menu">
Enable JavaScript source maps
</message>
+ <message name="IDS_DEVTOOLS_eb2f2225858078738d498794cd737d18" desc="Error message for tooltip showing that a file in Sources could not be loaded">
+ Unable to load this content.
+ </message>
<message name="IDS_DEVTOOLS_ed5eceb0fe85ceeeabf4b4b93eeca711" desc="A context menu item in the Sources Panel of the Sources panel">
Continue to here
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js
index 496c83b39cb..2169afb668f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/AutocompleteTestRunner.js
@@ -22,8 +22,9 @@ SourcesTestRunner.dumpSuggestions = function(textEditor, lines) {
}
}
- if (lineNumber === -1)
+ if (lineNumber === -1) {
throw new Error('Test case is invalid: cursor position is not marked with \'|\' symbol.');
+ }
textEditor.setText(lines.join('\n').replace('|', ''));
textEditor.setSelection(TextUtils.TextRange.createFromLocation(lineNumber, columnNumber));
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/DebuggerTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
index 0c423a99706..fcfe514d27f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
@@ -10,8 +10,9 @@
SourcesTestRunner.startDebuggerTest = function(callback, quiet) {
console.assert(TestRunner.debuggerModel.debuggerEnabled(), 'Debugger has to be enabled');
- if (quiet !== undefined)
+ if (quiet !== undefined) {
SourcesTestRunner._quiet = quiet;
+ }
UI.viewManager.showView('sources');
TestRunner.addSniffer(SDK.DebuggerModel.prototype, '_pausedScript', SourcesTestRunner._pausedScript, true);
@@ -139,10 +140,11 @@ SourcesTestRunner.waitUntilPausedNextTime = function(callback) {
SourcesTestRunner.waitUntilPaused = function(callback) {
callback = TestRunner.safeWrap(callback);
- if (SourcesTestRunner._pausedScriptArguments)
+ if (SourcesTestRunner._pausedScriptArguments) {
callback.apply(callback, SourcesTestRunner._pausedScriptArguments);
- else
+ } else {
SourcesTestRunner._waitUntilPausedCallback = callback;
+ }
};
SourcesTestRunner.waitUntilPausedPromise = function() {
@@ -156,10 +158,11 @@ SourcesTestRunner.waitUntilResumedNextTime = function(callback) {
SourcesTestRunner.waitUntilResumed = function(callback) {
callback = TestRunner.safeWrap(callback);
- if (!SourcesTestRunner._pausedScriptArguments)
+ if (!SourcesTestRunner._pausedScriptArguments) {
callback();
- else
+ } else {
SourcesTestRunner._waitUntilResumedCallback = callback;
+ }
};
SourcesTestRunner.waitUntilResumedPromise = function() {
@@ -167,8 +170,9 @@ SourcesTestRunner.waitUntilResumedPromise = function() {
};
SourcesTestRunner.resumeExecution = function(callback) {
- if (UI.panels.sources.paused())
+ if (UI.panels.sources.paused()) {
UI.panels.sources._togglePause();
+ }
SourcesTestRunner.waitUntilResumed(callback);
};
@@ -184,16 +188,18 @@ SourcesTestRunner.waitUntilPausedAndDumpStackAndResume = function(callback, opti
const statusElement = this.element.querySelector('.paused-message');
caption = statusElement.deepTextContent();
- if (callFrames)
+ if (callFrames) {
step1();
+ }
}
function paused(frames, reason, breakpointIds, async) {
callFrames = frames;
asyncStackTrace = async;
- if (typeof caption === 'string')
+ if (typeof caption === 'string') {
step1();
+ }
}
function step1() {
@@ -248,8 +254,9 @@ SourcesTestRunner.waitUntilPausedAndPerformSteppingActions = function(actions, c
SourcesTestRunner.captureStackTrace(callFrames, asyncStackTrace);
TestRunner.addResult('');
- while (action === 'Print')
+ while (action === 'Print') {
action = actions.shift();
+ }
}
if (!action) {
@@ -302,8 +309,9 @@ SourcesTestRunner.captureStackTraceIntoString = function(callFrames, asyncStackT
const isFramework =
uiLocation ? Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode) : false;
- if (options.dropFrameworkCallFrames && isFramework)
+ if (options.dropFrameworkCallFrames && isFramework) {
continue;
+ }
let url;
let lineNumber;
@@ -321,14 +329,16 @@ SourcesTestRunner.captureStackTraceIntoString = function(callFrames, asyncStackT
s = s.replace(/scheduleTestFunction.+$/, 'scheduleTestFunction <omitted>');
results.push(s);
- if (options.printReturnValue && returnValueFunction && returnValueFunction.call(frame))
+ if (options.printReturnValue && returnValueFunction && returnValueFunction.call(frame)) {
results.push(' <return>: ' + returnValueFunction.call(frame).description);
+ }
if (frame.functionName === 'scheduleTestFunction') {
const remainingFrames = callFrames.length - 1 - i;
- if (remainingFrames)
+ if (remainingFrames) {
results.push(' <... skipped remaining frames ...>');
+ }
break;
}
@@ -349,8 +359,9 @@ SourcesTestRunner.captureStackTraceIntoString = function(callFrames, asyncStackT
results.push(' [' + (asyncStackTrace.description || 'Async Call') + ']');
const printed = printCallFrames(asyncStackTrace.callFrames, runtimeCallFramePosition);
- if (!printed)
+ if (!printed) {
results.pop();
+ }
asyncStackTrace = asyncStackTrace.parent;
}
@@ -362,15 +373,17 @@ SourcesTestRunner.dumpSourceFrameContents = function(sourceFrame) {
TestRunner.addResult('==Source frame contents start==');
const textEditor = sourceFrame._textEditor;
- for (let i = 0; i < textEditor.linesCount; ++i)
+ for (let i = 0; i < textEditor.linesCount; ++i) {
TestRunner.addResult(textEditor.line(i));
+ }
TestRunner.addResult('==Source frame contents end==');
};
SourcesTestRunner._pausedScript = function(callFrames, reason, auxData, breakpointIds, asyncStackTrace) {
- if (!SourcesTestRunner._quiet)
+ if (!SourcesTestRunner._quiet) {
TestRunner.addResult('Script execution paused.');
+ }
const debuggerModel = this.target().model(SDK.DebuggerModel);
SourcesTestRunner._pausedScriptArguments = [
@@ -386,8 +399,9 @@ SourcesTestRunner._pausedScript = function(callFrames, reason, auxData, breakpoi
};
SourcesTestRunner._resumedScript = function() {
- if (!SourcesTestRunner._quiet)
+ if (!SourcesTestRunner._quiet) {
TestRunner.addResult('Script execution resumed.');
+ }
delete SourcesTestRunner._pausedScriptArguments;
@@ -403,10 +417,11 @@ SourcesTestRunner.showUISourceCode = function(uiSourceCode, callback) {
panel.showUISourceCode(uiSourceCode);
const sourceFrame = panel.visibleView;
- if (sourceFrame.loaded)
+ if (sourceFrame.loaded) {
callback(sourceFrame);
- else
+ } else {
TestRunner.addSniffer(sourceFrame, 'setContent', callback && callback.bind(null, sourceFrame));
+ }
};
SourcesTestRunner.showUISourceCodePromise = function(uiSourceCode) {
@@ -433,8 +448,9 @@ SourcesTestRunner.waitForScriptSource = function(scriptName, callback) {
const uiSourceCodes = panel._workspace.uiSourceCodes();
for (let i = 0; i < uiSourceCodes.length; ++i) {
- if (uiSourceCodes[i].project().type() === Workspace.projectTypes.Service)
+ if (uiSourceCodes[i].project().type() === Workspace.projectTypes.Service) {
continue;
+ }
if (uiSourceCodes[i].name() === scriptName) {
callback(uiSourceCodes[i]);
@@ -457,8 +473,9 @@ SourcesTestRunner.objectForPopover = function(sourceFrame, lineNumber, columnNum
SourcesTestRunner.setBreakpoint = function(sourceFrame, lineNumber, condition, enabled) {
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
- if (!debuggerPlugin._muted)
+ if (!debuggerPlugin._muted) {
debuggerPlugin._setBreakpoint(lineNumber, 0, condition, enabled);
+ }
};
SourcesTestRunner.removeBreakpoint = function(sourceFrame, lineNumber) {
@@ -480,8 +497,9 @@ SourcesTestRunner.createNewBreakpoint = function(sourceFrame, lineNumber, condit
SourcesTestRunner.toggleBreakpoint = function(sourceFrame, lineNumber, disableOnly) {
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
- if (!debuggerPlugin._muted)
+ if (!debuggerPlugin._muted) {
debuggerPlugin._toggleBreakpoint(lineNumber, disableOnly);
+ }
};
SourcesTestRunner.waitBreakpointSidebarPane = function(waitUntilResolved) {
@@ -491,12 +509,14 @@ SourcesTestRunner.waitBreakpointSidebarPane = function(waitUntilResolved) {
.then(checkIfReady);
function checkIfReady() {
- if (!waitUntilResolved)
+ if (!waitUntilResolved) {
return;
+ }
for (const {breakpoint} of Bindings.breakpointManager.allBreakpointLocations()) {
- if (breakpoint._uiLocations.size === 0 && breakpoint.enabled())
+ if (breakpoint._uiLocations.size === 0 && breakpoint.enabled()) {
return SourcesTestRunner.waitBreakpointSidebarPane();
+ }
}
}
};
@@ -505,8 +525,9 @@ SourcesTestRunner.breakpointsSidebarPaneContent = function() {
const paneElement = self.runtime.sharedInstance(Sources.JavaScriptBreakpointsSidebarPane).contentElement;
const empty = paneElement.querySelector('.gray-info-message');
- if (empty)
+ if (empty) {
return TestRunner.textContentWithLineBreaks(empty);
+ }
const entries = Array.from(paneElement.querySelectorAll('.breakpoint-entry'));
return entries.map(TestRunner.textContentWithLineBreaks).join('\n');
@@ -525,11 +546,13 @@ SourcesTestRunner.dumpScopeVariablesSidebarPane = function() {
const textContent = TestRunner.textContentWithLineBreaks(sections[i].element);
const text = TestRunner.clearSpecificInfoFromStackFrames(textContent);
- if (text.length > 0)
+ if (text.length > 0) {
TestRunner.addResult(text);
+ }
- if (!sections[i].objectTreeElement().expanded)
+ if (!sections[i].objectTreeElement().expanded) {
TestRunner.addResult(' <section collapsed>');
+ }
}
};
@@ -537,8 +560,9 @@ SourcesTestRunner.scopeChainSections = function() {
const children = self.runtime.sharedInstance(Sources.ScopeChainSidebarPane).contentElement.children;
const sections = [];
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
sections.push(children[i]._section);
+ }
return sections;
};
@@ -546,8 +570,9 @@ SourcesTestRunner.scopeChainSections = function() {
SourcesTestRunner.expandScopeVariablesSidebarPane = function(callback) {
const sections = SourcesTestRunner.scopeChainSections();
- for (let i = 0; i < sections.length - 1; ++i)
+ for (let i = 0; i < sections.length - 1; ++i) {
sections[i].expand();
+ }
TestRunner.deprecatedRunAfterPendingDispatches(callback);
};
@@ -597,8 +622,9 @@ SourcesTestRunner._findChildPropertyTreeElement = function(parent, childName) {
const treeElement = children[i];
const property = treeElement.property;
- if (property.name === childName)
+ if (property.name === childName) {
return treeElement;
+ }
}
};
@@ -629,11 +655,12 @@ SourcesTestRunner.createScriptMock = function(
script.requestContent = function() {
const trimmedSource = SDK.Script._trimSourceURLComment(source);
- return Promise.resolve(trimmedSource);
+ return Promise.resolve({content: trimmedSource, isEncoded: false});
};
- if (preRegisterCallback)
+ if (preRegisterCallback) {
preRegisterCallback(script);
+ }
debuggerModel._registerScript(script);
return script;
@@ -665,8 +692,9 @@ SourcesTestRunner.checkUILocation = function(uiSourceCode, lineNumber, columnNum
SourcesTestRunner.scriptFormatter = function() {
return self.runtime.allInstances(Sources.SourcesView.EditorAction).then(function(editorActions) {
for (let i = 0; i < editorActions.length; ++i) {
- if (editorActions[i] instanceof Sources.ScriptFormatterEditorAction)
+ if (editorActions[i] instanceof Sources.ScriptFormatterEditorAction) {
return editorActions[i];
+ }
}
return null;
@@ -707,8 +735,9 @@ SourcesTestRunner.waitDebuggerPluginBreakpoints = function(sourceFrame) {
function checkIfReady() {
for (const {breakpoint} of Bindings.breakpointManager.allBreakpointLocations()) {
- if (breakpoint._uiLocations.size === 0 && breakpoint.enabled())
+ if (breakpoint._uiLocations.size === 0 && breakpoint.enabled()) {
return SourcesTestRunner.waitDebuggerPluginDecorations().then(checkIfReady);
+ }
}
return Promise.resolve();
@@ -719,8 +748,9 @@ SourcesTestRunner.dumpDebuggerPluginBreakpoints = function(sourceFrame) {
const textEditor = sourceFrame._textEditor;
for (let lineNumber = 0; lineNumber < textEditor.linesCount; ++lineNumber) {
- if (!textEditor.hasLineClass(lineNumber, 'cm-breakpoint'))
+ if (!textEditor.hasLineClass(lineNumber, 'cm-breakpoint')) {
continue;
+ }
const disabled = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-disabled');
const conditional = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-conditional');
@@ -765,8 +795,9 @@ SourcesTestRunner.debuggerPlugin = function(sourceFrame) {
};
SourcesTestRunner.waitUntilDebuggerPluginLoaded = async function(sourceFrame) {
- while (!SourcesTestRunner.debuggerPlugin(sourceFrame))
+ while (!SourcesTestRunner.debuggerPlugin(sourceFrame)) {
await TestRunner.addSnifferPromise(sourceFrame, '_ensurePluginsLoaded');
+ }
return SourcesTestRunner.debuggerPlugin(sourceFrame);
};
@@ -775,8 +806,9 @@ SourcesTestRunner.setEventListenerBreakpoint = function(id, enabled, targetName)
const auxData = {'eventName': id};
- if (targetName)
+ if (targetName) {
auxData.targetName = targetName;
+ }
const breakpoint = SDK.domDebuggerManager.resolveEventListenerBreakpoint(auxData);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
index a693414fc80..ef5308480a0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
@@ -18,8 +18,9 @@ SourcesTestRunner.createTestEditor = function(clientHeight, textEditorDelegate)
};
function textWithSelection(text, selections) {
- if (!selections.length)
+ if (!selections.length) {
return text;
+ }
function lineWithCursor(line, column, cursorChar) {
return line.substring(0, column) + cursorChar + line.substring(column);
@@ -34,8 +35,9 @@ function textWithSelection(text, selections) {
const endCursorChar = (selection.isEmpty() ? '|' : '<');
lines[selection.endLine] = lineWithCursor(lines[selection.endLine], selection.endColumn, endCursorChar);
- if (!selection.isEmpty())
+ if (!selection.isEmpty()) {
lines[selection.startLine] = lineWithCursor(lines[selection.startLine], selection.startColumn, '>');
+ }
}
return lines.join('\n');
@@ -44,8 +46,9 @@ function textWithSelection(text, selections) {
SourcesTestRunner.dumpTextWithSelection = function(textEditor, dumpWhiteSpaces) {
let text = textWithSelection(textEditor.text(), textEditor.selections());
- if (dumpWhiteSpaces)
+ if (dumpWhiteSpaces) {
text = text.replace(/ /g, '.');
+ }
TestRunner.addResult(text);
};
@@ -121,8 +124,9 @@ function createCodeMirrorFakeEvent(editor, eventType, code, charCode, modifiers)
};
if (modifiers) {
- for (let i = 0; i < modifiers.length; ++i)
+ for (let i = 0; i < modifiers.length; ++i) {
event[modifiers[i]] = true;
+ }
}
return event;
@@ -149,8 +153,9 @@ function fakeCodeMirrorKeyEvent(editor, eventType, code, charCode, modifiers) {
}
function fakeCodeMirrorInputEvent(editor, character) {
- if (typeof character !== 'string')
+ if (typeof character !== 'string') {
return;
+ }
const input = editor._codeMirror.display.input;
const value = input.textarea.value;
const newValue =
@@ -181,8 +186,9 @@ SourcesTestRunner.fakeKeyEvent = function(editor, originalCode, modifiers, callb
code = code || eventCodes[originalCode] || originalCode;
- if (typeof code === 'string')
+ if (typeof code === 'string') {
code = code.charCodeAt(0);
+ }
if (fakeCodeMirrorKeyEvent(editor, 'keydown', code, charCode, modifiers)) {
callback();
@@ -220,10 +226,11 @@ SourcesTestRunner.dumpSelectionStats = function(textEditor) {
for (let i = 0; i < sortedKeys.length; ++i) {
let keyName = sortedKeys[i];
- if (!keyName.length)
+ if (!keyName.length) {
keyName = '<Empty string>';
- else
+ } else {
keyName = '\'' + keyName + '\'';
+ }
TestRunner.addResult(keyName + ': ' + listHashMap[sortedKeys[i]]);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/LiveEditTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/LiveEditTestRunner.js
index 3136a0a42b3..bb975c67d7a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/LiveEditTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/LiveEditTestRunner.js
@@ -14,8 +14,9 @@ SourcesTestRunner.replaceInSource = function(sourceFrame, string, replacement) {
const line = sourceFrame._textEditor.line(i);
const column = line.indexOf(string);
- if (column === -1)
+ if (column === -1) {
continue;
+ }
const range = new TextUtils.TextRange(i, column, i, column + string.length);
sourceFrame._textEditor.editRange(range, replacement);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SearchTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SearchTestRunner.js
index 5a601dd69ae..5849ddf14b7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SearchTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SearchTestRunner.js
@@ -55,8 +55,9 @@ SourcesTestRunner.runSearchAndDumpResults = function(scope, searchConfig, callba
const uiSourceCode = searchResult._uiSourceCode;
const searchMatches = searchResult._searchMatches;
- if (!searchMatches.length)
+ if (!searchMatches.length) {
continue;
+ }
TestRunner.addResult(
'Search result #' + (i + 1) + ': uiSourceCode.url = ' + uiSourceCode.url().replace(/VM\d+/, 'VMXX'));
@@ -76,14 +77,17 @@ SourcesTestRunner.runSearchAndDumpResults = function(scope, searchConfig, callba
SourcesTestRunner.replaceAndDumpChange = function(sourceFrame, searchConfig, replacement, replaceAll) {
const modifiers = [];
- if (searchConfig.isRegex)
+ if (searchConfig.isRegex) {
modifiers.push('regex');
+ }
- if (searchConfig.caseSensitive)
+ if (searchConfig.caseSensitive) {
modifiers.push('caseSensitive');
+ }
- if (replaceAll)
+ if (replaceAll) {
modifiers.push('replaceAll');
+ }
const modifiersString = (modifiers.length ? ' (' + modifiers.join(', ') + ')' : '');
TestRunner.addResult(
@@ -91,8 +95,9 @@ SourcesTestRunner.replaceAndDumpChange = function(sourceFrame, searchConfig, rep
editor = sourceFrame._textEditor;
const oldLines = [];
- for (let i = 0; i < editor.linesCount; ++i)
+ for (let i = 0; i < editor.linesCount; ++i) {
oldLines.push(editor.line(i));
+ }
const searchableView = UI.panels.sources.sourcesView().searchableView();
searchableView.showSearchField();
@@ -104,33 +109,38 @@ SourcesTestRunner.replaceAndDumpChange = function(sourceFrame, searchConfig, rep
searchableView._replaceInputElement.value = replacement;
searchableView._performSearch(true, true);
- if (replaceAll)
+ if (replaceAll) {
searchableView._replaceAll();
- else
+ } else {
searchableView._replace();
+ }
const newLines = [];
- for (let i = 0; i < editor.linesCount; ++i)
+ for (let i = 0; i < editor.linesCount; ++i) {
newLines.push(editor.line(i));
+ }
for (let i = 0; i < newLines.length; ++i) {
- if (oldLines[i] === newLines[i])
+ if (oldLines[i] === newLines[i]) {
continue;
+ }
const oldLine = oldLines[i];
const newLine = newLines[i];
let prefixLength = 0;
- for (let j = 0; j < oldLine.length && j < newLine.length && newLine[j] === oldLine[j]; ++j)
+ for (let j = 0; j < oldLine.length && j < newLine.length && newLine[j] === oldLine[j]; ++j) {
++prefixLength;
+ }
let postfixLength = 0;
for (let j = 0; j < oldLine.length && j < newLine.length &&
newLine[newLine.length - j - 1] === oldLine[oldLine.length - j - 1];
- ++j)
+ ++j) {
++postfixLength;
+ }
const prefix = oldLine.substring(0, prefixLength);
const removed = oldLine.substring(prefixLength, oldLine.length - postfixLength);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SourcesTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SourcesTestRunner.js
index d5898083494..0d35fd1f56d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SourcesTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/SourcesTestRunner.js
@@ -24,21 +24,24 @@ SourcesTestRunner.dumpNavigatorView = function(navigatorView, dumpIcons) {
let icons = treeElement._leadingIconsElement.querySelectorAll('[is=ui-icon]');
icons = Array.prototype.slice.call(icons);
const iconTypes = icons.map(icon => icon._iconType);
- if (iconTypes.length)
+ if (iconTypes.length) {
titleText = titleText + '[' + iconTypes.join(', ') + '] ';
+ }
}
titleText += treeElement.title;
if (treeElement._nodeType === Sources.NavigatorView.Types.FileSystem ||
treeElement._nodeType === Sources.NavigatorView.Types.FileSystemFolder) {
const hasMappedFiles = treeElement.listItemElement.classList.contains('has-mapped-files');
- if (!hasMappedFiles)
+ if (!hasMappedFiles) {
titleText += ' [dimmed]';
+ }
}
TestRunner.addResult(prefix + titleText);
treeElement.expand();
const children = treeElement.children();
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
dumpNavigatorTreeElement(prefix + ' ', children[i]);
+ }
}
/**
@@ -46,8 +49,9 @@ SourcesTestRunner.dumpNavigatorView = function(navigatorView, dumpIcons) {
*/
function dumpNavigatorTreeOutline(treeOutline) {
const children = treeOutline.rootElement().children();
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
dumpNavigatorTreeElement('', children[i]);
+ }
}
};
@@ -82,8 +86,9 @@ SourcesTestRunner.dumpNavigatorViewInMode = function(view, mode) {
*/
SourcesTestRunner.addScriptUISourceCode = function(url, content, isContentScript, worldId) {
content += '\n//# sourceURL=' + url;
- if (isContentScript)
+ if (isContentScript) {
content = `testRunner.evaluateScriptInIsolatedWorld(${worldId}, \`${content}\`)`;
+ }
TestRunner.evaluateInPageAnonymously(content);
return TestRunner.waitForUISourceCode(url);
};
@@ -97,10 +102,11 @@ function testSourceMapping(text1, text2, mapping, testToken) {
Formatter.Formatter.locationToPosition(text2.computeLineEndings(), formattedLocation[0], formattedLocation[1]);
const expectedFormattedPosition = text2.indexOf(testToken);
- if (expectedFormattedPosition === formattedPosition)
+ if (expectedFormattedPosition === formattedPosition) {
TestRunner.addResult(String.sprintf('Correct mapping for <%s>', testToken));
- else
+ } else {
TestRunner.addResult(String.sprintf('ERROR: Wrong mapping for <%s>', testToken));
+ }
}
SourcesTestRunner.testPrettyPrint = function(mimeType, text, mappingQueries, next) {
@@ -111,8 +117,9 @@ SourcesTestRunner.testPrettyPrint = function(mimeType, text, mappingQueries, nex
TestRunner.addResult(formattedSource);
TestRunner.addResult('------ >8 ======');
- while (mappingQueries && mappingQueries.length)
+ while (mappingQueries && mappingQueries.length) {
testSourceMapping(text, formattedSource, mapping, mappingQueries.shift());
+ }
next();
}
@@ -128,15 +135,17 @@ SourcesTestRunner.testJavascriptOutline = function(text) {
function onChunk(isLastChunk, outlineItems) {
items.pushAll(outlineItems);
- if (!isLastChunk)
+ if (!isLastChunk) {
return;
+ }
TestRunner.addResult('Text:');
TestRunner.addResult(text.split('\n').map(line => ' ' + line).join('\n'));
TestRunner.addResult('Outline:');
- for (const item of items)
+ for (const item of items) {
TestRunner.addResult(' ' + item.name + (item.arguments || '') + ':' + item.line + ':' + item.column);
+ }
fulfill();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/module.json b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/module.json
index 52a978abdbb..a260418c221 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/module.json
@@ -5,6 +5,7 @@
"workspace",
"source_frame",
"text_utils",
+ "cm_modes",
"browser_debugger"
],
"scripts": [
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/TerminalWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/terminal/TerminalWidget.js
deleted file mode 100644
index 1d7bfe35985..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/TerminalWidget.js
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-/**
- * @unrestricted
- */
-Terminal.TerminalWidget = class extends UI.VBox {
- constructor() {
- super(true);
- this.registerRequiredCSS('terminal/xterm.js/build/xterm.css');
- this.registerRequiredCSS('terminal/terminal.css');
- this.element.classList.add('terminal-root');
- this._init();
- this._linkifier = new Components.Linkifier();
- this._config = {attributes: true, childList: true, characterData: true, subtree: true};
- }
-
- async _init() {
- const backend = await Services.serviceManager.createRemoteService('Terminal');
- this._initialized(backend);
- }
-
- /**
- * @param {?Services.ServiceManager.Service} backend
- */
- _initialized(backend) {
- if (!backend) {
- if (!this._unavailableLabel) {
- this._unavailableLabel = this.contentElement.createChild('div', 'terminal-error-message fill');
- this._unavailableLabel.createChild('div').textContent = Common.UIString('Terminal service is not available');
- }
- setTimeout(this._init.bind(this), 2000);
- return;
- }
-
- if (this._unavailableLabel) {
- this._unavailableLabel.remove();
- delete this._unavailableLabel;
- }
-
- this._backend = backend;
-
- if (!this._term) {
- this._term = new Terminal({cursorBlink: true});
- this._term.open(this.contentElement);
- this._mutationObserver = new MutationObserver(this._linkify.bind(this));
- this._mutationObserver.observe(this.contentElement, this._config);
- this._term.on('data', data => {
- this._backend.send('write', {data: data});
- });
- this._term.fit();
- this._term.on('resize', size => {
- this._backend.send('resize', {cols: size.cols, rows: size.rows});
- });
- }
-
- this._backend.send('init', {cols: this._term.cols, rows: this._term.rows});
- this._backend.on('data', result => {
- this._term.write(result.data);
- });
- this._backend.on('disposed', this._disposed.bind(this));
- }
-
- /**
- * @override
- */
- onResize() {
- if (this._term)
- this._term.fit();
- }
-
- _disposed() {
- this._initialized(null);
- }
-
- /**
- * @override
- */
- ownerViewDisposed() {
- if (this._backend)
- this._backend.dispose();
- }
-
- _linkify() {
- this._mutationObserver.takeRecords();
- this._mutationObserver.disconnect();
- this._linkifier.reset();
- const rows = this._term['rowContainer'].children;
- for (let i = 0; i < rows.length; i++)
- this._linkifyTerminalLine(rows[i]);
- this._mutationObserver.observe(this.contentElement, this._config);
- }
-
- /**
- * @param {string} string
- */
- _linkifyText(string) {
- const regex1 = /([/\w\.-]*)+\:([\d]+)(?:\:([\d]+))?/;
- const regex2 = /([/\w\.-]*)+\(([\d]+),([\d]+)\)/;
- const container = createDocumentFragment();
-
- while (string) {
- const linkString = regex1.exec(string) || regex2.exec(string);
- if (!linkString)
- break;
-
- const text = linkString[0];
- const path = linkString[1];
- const lineNumber = parseInt(linkString[2], 10) - 1 || 0;
- const columnNumber = parseInt(linkString[3], 10) - 1 || 0;
-
- const uiSourceCode = Workspace.workspace.uiSourceCodes().find(uisc => uisc.url().endsWith(path));
- const linkIndex = string.indexOf(text);
- const nonLink = string.substring(0, linkIndex);
- container.appendChild(createTextNode(nonLink));
-
- if (uiSourceCode) {
- container.appendChild(Components.Linkifier.linkifyURL(
- uiSourceCode.url(),
- {text, lineNumber, columnNumber, maxLengh: Number.MAX_VALUE, className: 'terminal-link'}));
- } else {
- container.appendChild(createTextNode(text));
- }
- string = string.substring(linkIndex + text.length);
- }
-
- if (string)
- container.appendChild(createTextNode(string));
- return container;
- }
-
- /**
- * @param {!Node} line
- */
- _linkifyTerminalLine(line) {
- let node = line.firstChild;
- while (node) {
- if (node.nodeType !== Node.TEXT_NODE) {
- node = node.nextSibling;
- continue;
- }
- const nextNode = node.nextSibling;
- node.remove();
- const linkified = this._linkifyText(node.textContent);
- line.insertBefore(linkified, nextNode);
- node = nextNode;
- }
- }
-};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/module.json b/chromium/third_party/blink/renderer/devtools/front_end/terminal/module.json
deleted file mode 100644
index 6802e2b4246..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/module.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "extensions": [
- {
- "type": "view",
- "location": "drawer-sidebar",
- "id": "drawer.xterm",
- "title": "Terminal",
- "order": 10,
- "factoryName": "Terminal.TerminalWidget"
- }
- ],
- "dependencies": [
- "components",
- "ui",
- "services"
- ],
- "experiment": "terminalInDrawer",
- "scripts": [
- "xterm.js/build/xterm.js",
- "xterm.js/addons/fit/fit.js",
- "TerminalWidget.js"
- ],
- "skip_compilation": [
- "xterm.js/build/xterm.js",
- "xterm.js/addons/fit/fit.js"
- ],
- "resources": [
- "terminal.css",
- "xterm.js/build/xterm.css"
- ]
-}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal.css b/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal.css
deleted file mode 100644
index 17fa5a91ef2..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal.css
+++ /dev/null
@@ -1,37 +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.
- */
-
-.terminal-root {
- background-color: #111;
- color: #fafafa;
- padding: 2px;
- -webkit-user-select: text;
- white-space: nowrap;
-}
-
-.terminal-error-message {
- display: flex;
- align-items: center;
- padding: 10px;
- background-color: rgba(255, 255, 255, 0.8);
- justify-content: center;
- font-size: 16px;
- color: #222;
-}
-
-.terminal-error-message div {
- padding-right: 10px;
-}
-
-.terminal-link {
- color: inherit;
- text-decoration: inherit;
-}
-
-.terminal-link:hover {
- text-decoration: underline;
- cursor: pointer;
-}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp
deleted file mode 100644
index 5561a9f80a1..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/terminal_strings.grdp
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<grit-part>
- <message name="IDS_DEVTOOLS_514d8a494f087c0d549b9536c2ef3bd9" desc="Title of the 'Terminal' tool in the sidebar of the drawer tool">
- Terminal
- </message>
- <message name="IDS_DEVTOOLS_69685b2a57646d0d0bc125b5f94f3931" desc="Text in Terminal Widget of the web version terminal">
- Terminal service is not available
- </message>
-</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/README.chromium b/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/README.chromium
deleted file mode 100644
index 662bc38541a..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/README.chromium
+++ /dev/null
@@ -1,7 +0,0 @@
-Name: Xterm.js is a terminal front-end component written in JavaScript that works in the browser.
-Short Name: xterm.js
-URL: https://github.com/sourcelair/xterm.js
-License: MIT
-Security Critical: no
-
-This directory contains Chrome's version of xterm.js with tests, demo and some addons folders removed.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/fit.js b/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/fit.js
deleted file mode 100644
index 46b79e9b3be..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/fit.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Fit terminal columns and rows to the dimensions of its DOM element.
- *
- * ## Approach
- * - Rows: Truncate the division of the terminal parent element height by the terminal row height.
- *
- * - Columns: Truncate the division of the terminal parent element width by the terminal character
- * width (apply display: inline at the terminal row and truncate its width with the current
- * number of columns).
- * @module xterm/addons/fit/fit
- * @license MIT
- */
-
-(function (fit) {
- if (typeof exports === 'object' && typeof module === 'object') {
- /*
- * CommonJS environment
- */
- module.exports = fit(require('../../xterm'));
- } else if (typeof define == 'function') {
- /*
- * Require.js is available
- */
- define(['../../xterm'], fit);
- } else {
- /*
- * Plain browser environment
- */
- fit(window.Terminal);
- }
-})(function (Xterm) {
- var exports = {};
-
- exports.proposeGeometry = function (term) {
- if (!term.element.parentElement) {
- return null;
- }
- var parentElementStyle = window.getComputedStyle(term.element.parentElement),
- parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
- parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17),
- elementStyle = window.getComputedStyle(term.element),
- elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
- elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')),
- availableHeight = parentElementHeight - elementPaddingVer,
- availableWidth = parentElementWidth - elementPaddingHor,
- container = term.rowContainer,
- subjectRow = term.rowContainer.firstElementChild,
- contentBuffer = subjectRow.innerHTML,
- characterHeight,
- rows,
- characterWidth,
- cols,
- geometry;
-
- subjectRow.style.display = 'inline';
- subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
- characterWidth = subjectRow.getBoundingClientRect().width;
- subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
- characterHeight = subjectRow.getBoundingClientRect().height;
- subjectRow.innerHTML = contentBuffer;
-
- rows = parseInt(availableHeight / characterHeight);
- cols = parseInt(availableWidth / characterWidth);
-
- geometry = {cols: cols, rows: rows};
- return geometry;
- };
-
- exports.fit = function (term) {
- var geometry = exports.proposeGeometry(term);
-
- if (geometry) {
- term.resize(geometry.cols, geometry.rows);
- }
- };
-
- Xterm.prototype.proposeGeometry = function () {
- return exports.proposeGeometry(this);
- };
-
- Xterm.prototype.fit = function () {
- return exports.fit(this);
- };
-
- return exports;
-});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/package.json b/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/package.json
deleted file mode 100644
index f7cb5bc8c9a..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/addons/fit/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "xterm.fit",
- "main": "fit.js",
- "private": true
-}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.css b/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.css
deleted file mode 100644
index efdc016982a..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.css
+++ /dev/null
@@ -1,2248 +0,0 @@
-/**
- * xterm.js: xterm, in the browser
- * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)
- * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
- * https://github.com/chjj/term.js
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * Originally forked from (with the author's permission):
- * Fabrice Bellard's javascript vt100 for jslinux:
- * http://bellard.org/jslinux/
- * Copyright (c) 2011 Fabrice Bellard
- * The original design remains. The terminal itself
- * has been extended to include xterm CSI codes, among
- * other features.
- */
-
-/*
- * Default style for xterm.js
- */
-
-.terminal {
- background-color: #000;
- color: #fff;
- font-family: courier-new, courier, monospace;
- font-feature-settings: "liga" 0;
- position: relative;
-}
-
-.terminal.focus,
-.terminal:focus {
- outline: none;
-}
-
-.terminal .xterm-helpers {
- position: absolute;
- top: 0;
-}
-
-.terminal .xterm-helper-textarea {
- /*
- * HACK: to fix IE's blinking cursor
- * Move textarea out of the screen to the far left, so that the cursor is not visible.
- */
- position: absolute;
- opacity: 0;
- left: -9999em;
- top: 0;
- width: 0;
- height: 0;
- z-index: -10;
- /** Prevent wrapping so the IME appears against the textarea at the correct position */
- white-space: nowrap;
- overflow: hidden;
- resize: none;
-}
-
-.terminal a {
- color: inherit;
- text-decoration: none;
-}
-
-.terminal a:hover {
- cursor: pointer;
- text-decoration: underline;
-}
-
-.terminal a.xterm-invalid-link:hover {
- cursor: text;
- text-decoration: none;
-}
-
-.terminal.focus:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor {
- background-color: #fff;
- color: #000;
-}
-
-.terminal:not(.focus) .terminal-cursor {
- outline: 1px solid #fff;
- outline-offset: -1px;
- background-color: transparent;
-}
-
-.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink-on .terminal-cursor {
- background-color: transparent;
- color: inherit;
-}
-
-.terminal.xterm-cursor-style-bar .terminal-cursor,
-.terminal.xterm-cursor-style-underline .terminal-cursor {
- position: relative;
-}
-.terminal.xterm-cursor-style-bar .terminal-cursor::before,
-.terminal.xterm-cursor-style-underline .terminal-cursor::before {
- content: "";
- display: block;
- position: absolute;
- background-color: #fff;
-}
-.terminal.xterm-cursor-style-bar .terminal-cursor::before {
- top: 0;
- bottom: 0;
- left: 0;
- width: 1px;
-}
-.terminal.xterm-cursor-style-underline .terminal-cursor::before {
- bottom: 0;
- left: 0;
- right: 0;
- height: 1px;
-}
-.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before,
-.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before {
- background-color: transparent;
-}
-.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,
-.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before {
- background-color: #fff;
-}
-
-.terminal .composition-view {
- background: #000;
- color: #FFF;
- display: none;
- position: absolute;
- white-space: nowrap;
- z-index: 1;
-}
-
-.terminal .composition-view.active {
- display: block;
-}
-
-.terminal .xterm-viewport {
- /* On OS X this is required in order for the scroll bar to appear fully opaque */
- background-color: #000;
- overflow-y: scroll;
-}
-
-.terminal .xterm-wide-char,
-.terminal .xterm-normal-char {
- display: inline-block;
-}
-
-.terminal .xterm-rows {
- position: absolute;
- left: 0;
- top: 0;
-}
-
-.terminal .xterm-rows > div {
- /* Lines containing spans and text nodes ocassionally wrap despite being the same width (#327) */
- white-space: nowrap;
-}
-
-.terminal .xterm-scroll-area {
- visibility: hidden;
-}
-
-.terminal .xterm-char-measure-element {
- display: inline-block;
- visibility: hidden;
- position: absolute;
- left: -9999em;
-}
-
-/*
- * Determine default colors for xterm.js
- */
-.terminal .xterm-bold {
- font-weight: bold;
-}
-
-.terminal .xterm-underline {
- text-decoration: underline;
-}
-
-.terminal .xterm-blink {
- text-decoration: blink;
-}
-
-.terminal .xterm-hidden {
- visibility: hidden;
-}
-
-.terminal .xterm-color-0 {
- color: #2e3436;
-}
-
-.terminal .xterm-bg-color-0 {
- background-color: #2e3436;
-}
-
-.terminal .xterm-color-1 {
- color: #cc0000;
-}
-
-.terminal .xterm-bg-color-1 {
- background-color: #cc0000;
-}
-
-.terminal .xterm-color-2 {
- color: #4e9a06;
-}
-
-.terminal .xterm-bg-color-2 {
- background-color: #4e9a06;
-}
-
-.terminal .xterm-color-3 {
- color: #c4a000;
-}
-
-.terminal .xterm-bg-color-3 {
- background-color: #c4a000;
-}
-
-.terminal .xterm-color-4 {
- color: #3465a4;
-}
-
-.terminal .xterm-bg-color-4 {
- background-color: #3465a4;
-}
-
-.terminal .xterm-color-5 {
- color: #75507b;
-}
-
-.terminal .xterm-bg-color-5 {
- background-color: #75507b;
-}
-
-.terminal .xterm-color-6 {
- color: #06989a;
-}
-
-.terminal .xterm-bg-color-6 {
- background-color: #06989a;
-}
-
-.terminal .xterm-color-7 {
- color: #d3d7cf;
-}
-
-.terminal .xterm-bg-color-7 {
- background-color: #d3d7cf;
-}
-
-.terminal .xterm-color-8 {
- color: #555753;
-}
-
-.terminal .xterm-bg-color-8 {
- background-color: #555753;
-}
-
-.terminal .xterm-color-9 {
- color: #ef2929;
-}
-
-.terminal .xterm-bg-color-9 {
- background-color: #ef2929;
-}
-
-.terminal .xterm-color-10 {
- color: #8ae234;
-}
-
-.terminal .xterm-bg-color-10 {
- background-color: #8ae234;
-}
-
-.terminal .xterm-color-11 {
- color: #fce94f;
-}
-
-.terminal .xterm-bg-color-11 {
- background-color: #fce94f;
-}
-
-.terminal .xterm-color-12 {
- color: #729fcf;
-}
-
-.terminal .xterm-bg-color-12 {
- background-color: #729fcf;
-}
-
-.terminal .xterm-color-13 {
- color: #ad7fa8;
-}
-
-.terminal .xterm-bg-color-13 {
- background-color: #ad7fa8;
-}
-
-.terminal .xterm-color-14 {
- color: #34e2e2;
-}
-
-.terminal .xterm-bg-color-14 {
- background-color: #34e2e2;
-}
-
-.terminal .xterm-color-15 {
- color: #eeeeec;
-}
-
-.terminal .xterm-bg-color-15 {
- background-color: #eeeeec;
-}
-
-.terminal .xterm-color-16 {
- color: #000000;
-}
-
-.terminal .xterm-bg-color-16 {
- background-color: #000000;
-}
-
-.terminal .xterm-color-17 {
- color: #00005f;
-}
-
-.terminal .xterm-bg-color-17 {
- background-color: #00005f;
-}
-
-.terminal .xterm-color-18 {
- color: #000087;
-}
-
-.terminal .xterm-bg-color-18 {
- background-color: #000087;
-}
-
-.terminal .xterm-color-19 {
- color: #0000af;
-}
-
-.terminal .xterm-bg-color-19 {
- background-color: #0000af;
-}
-
-.terminal .xterm-color-20 {
- color: #0000d7;
-}
-
-.terminal .xterm-bg-color-20 {
- background-color: #0000d7;
-}
-
-.terminal .xterm-color-21 {
- color: #0000ff;
-}
-
-.terminal .xterm-bg-color-21 {
- background-color: #0000ff;
-}
-
-.terminal .xterm-color-22 {
- color: #005f00;
-}
-
-.terminal .xterm-bg-color-22 {
- background-color: #005f00;
-}
-
-.terminal .xterm-color-23 {
- color: #005f5f;
-}
-
-.terminal .xterm-bg-color-23 {
- background-color: #005f5f;
-}
-
-.terminal .xterm-color-24 {
- color: #005f87;
-}
-
-.terminal .xterm-bg-color-24 {
- background-color: #005f87;
-}
-
-.terminal .xterm-color-25 {
- color: #005faf;
-}
-
-.terminal .xterm-bg-color-25 {
- background-color: #005faf;
-}
-
-.terminal .xterm-color-26 {
- color: #005fd7;
-}
-
-.terminal .xterm-bg-color-26 {
- background-color: #005fd7;
-}
-
-.terminal .xterm-color-27 {
- color: #005fff;
-}
-
-.terminal .xterm-bg-color-27 {
- background-color: #005fff;
-}
-
-.terminal .xterm-color-28 {
- color: #008700;
-}
-
-.terminal .xterm-bg-color-28 {
- background-color: #008700;
-}
-
-.terminal .xterm-color-29 {
- color: #00875f;
-}
-
-.terminal .xterm-bg-color-29 {
- background-color: #00875f;
-}
-
-.terminal .xterm-color-30 {
- color: #008787;
-}
-
-.terminal .xterm-bg-color-30 {
- background-color: #008787;
-}
-
-.terminal .xterm-color-31 {
- color: #0087af;
-}
-
-.terminal .xterm-bg-color-31 {
- background-color: #0087af;
-}
-
-.terminal .xterm-color-32 {
- color: #0087d7;
-}
-
-.terminal .xterm-bg-color-32 {
- background-color: #0087d7;
-}
-
-.terminal .xterm-color-33 {
- color: #0087ff;
-}
-
-.terminal .xterm-bg-color-33 {
- background-color: #0087ff;
-}
-
-.terminal .xterm-color-34 {
- color: #00af00;
-}
-
-.terminal .xterm-bg-color-34 {
- background-color: #00af00;
-}
-
-.terminal .xterm-color-35 {
- color: #00af5f;
-}
-
-.terminal .xterm-bg-color-35 {
- background-color: #00af5f;
-}
-
-.terminal .xterm-color-36 {
- color: #00af87;
-}
-
-.terminal .xterm-bg-color-36 {
- background-color: #00af87;
-}
-
-.terminal .xterm-color-37 {
- color: #00afaf;
-}
-
-.terminal .xterm-bg-color-37 {
- background-color: #00afaf;
-}
-
-.terminal .xterm-color-38 {
- color: #00afd7;
-}
-
-.terminal .xterm-bg-color-38 {
- background-color: #00afd7;
-}
-
-.terminal .xterm-color-39 {
- color: #00afff;
-}
-
-.terminal .xterm-bg-color-39 {
- background-color: #00afff;
-}
-
-.terminal .xterm-color-40 {
- color: #00d700;
-}
-
-.terminal .xterm-bg-color-40 {
- background-color: #00d700;
-}
-
-.terminal .xterm-color-41 {
- color: #00d75f;
-}
-
-.terminal .xterm-bg-color-41 {
- background-color: #00d75f;
-}
-
-.terminal .xterm-color-42 {
- color: #00d787;
-}
-
-.terminal .xterm-bg-color-42 {
- background-color: #00d787;
-}
-
-.terminal .xterm-color-43 {
- color: #00d7af;
-}
-
-.terminal .xterm-bg-color-43 {
- background-color: #00d7af;
-}
-
-.terminal .xterm-color-44 {
- color: #00d7d7;
-}
-
-.terminal .xterm-bg-color-44 {
- background-color: #00d7d7;
-}
-
-.terminal .xterm-color-45 {
- color: #00d7ff;
-}
-
-.terminal .xterm-bg-color-45 {
- background-color: #00d7ff;
-}
-
-.terminal .xterm-color-46 {
- color: #00ff00;
-}
-
-.terminal .xterm-bg-color-46 {
- background-color: #00ff00;
-}
-
-.terminal .xterm-color-47 {
- color: #00ff5f;
-}
-
-.terminal .xterm-bg-color-47 {
- background-color: #00ff5f;
-}
-
-.terminal .xterm-color-48 {
- color: #00ff87;
-}
-
-.terminal .xterm-bg-color-48 {
- background-color: #00ff87;
-}
-
-.terminal .xterm-color-49 {
- color: #00ffaf;
-}
-
-.terminal .xterm-bg-color-49 {
- background-color: #00ffaf;
-}
-
-.terminal .xterm-color-50 {
- color: #00ffd7;
-}
-
-.terminal .xterm-bg-color-50 {
- background-color: #00ffd7;
-}
-
-.terminal .xterm-color-51 {
- color: #00ffff;
-}
-
-.terminal .xterm-bg-color-51 {
- background-color: #00ffff;
-}
-
-.terminal .xterm-color-52 {
- color: #5f0000;
-}
-
-.terminal .xterm-bg-color-52 {
- background-color: #5f0000;
-}
-
-.terminal .xterm-color-53 {
- color: #5f005f;
-}
-
-.terminal .xterm-bg-color-53 {
- background-color: #5f005f;
-}
-
-.terminal .xterm-color-54 {
- color: #5f0087;
-}
-
-.terminal .xterm-bg-color-54 {
- background-color: #5f0087;
-}
-
-.terminal .xterm-color-55 {
- color: #5f00af;
-}
-
-.terminal .xterm-bg-color-55 {
- background-color: #5f00af;
-}
-
-.terminal .xterm-color-56 {
- color: #5f00d7;
-}
-
-.terminal .xterm-bg-color-56 {
- background-color: #5f00d7;
-}
-
-.terminal .xterm-color-57 {
- color: #5f00ff;
-}
-
-.terminal .xterm-bg-color-57 {
- background-color: #5f00ff;
-}
-
-.terminal .xterm-color-58 {
- color: #5f5f00;
-}
-
-.terminal .xterm-bg-color-58 {
- background-color: #5f5f00;
-}
-
-.terminal .xterm-color-59 {
- color: #5f5f5f;
-}
-
-.terminal .xterm-bg-color-59 {
- background-color: #5f5f5f;
-}
-
-.terminal .xterm-color-60 {
- color: #5f5f87;
-}
-
-.terminal .xterm-bg-color-60 {
- background-color: #5f5f87;
-}
-
-.terminal .xterm-color-61 {
- color: #5f5faf;
-}
-
-.terminal .xterm-bg-color-61 {
- background-color: #5f5faf;
-}
-
-.terminal .xterm-color-62 {
- color: #5f5fd7;
-}
-
-.terminal .xterm-bg-color-62 {
- background-color: #5f5fd7;
-}
-
-.terminal .xterm-color-63 {
- color: #5f5fff;
-}
-
-.terminal .xterm-bg-color-63 {
- background-color: #5f5fff;
-}
-
-.terminal .xterm-color-64 {
- color: #5f8700;
-}
-
-.terminal .xterm-bg-color-64 {
- background-color: #5f8700;
-}
-
-.terminal .xterm-color-65 {
- color: #5f875f;
-}
-
-.terminal .xterm-bg-color-65 {
- background-color: #5f875f;
-}
-
-.terminal .xterm-color-66 {
- color: #5f8787;
-}
-
-.terminal .xterm-bg-color-66 {
- background-color: #5f8787;
-}
-
-.terminal .xterm-color-67 {
- color: #5f87af;
-}
-
-.terminal .xterm-bg-color-67 {
- background-color: #5f87af;
-}
-
-.terminal .xterm-color-68 {
- color: #5f87d7;
-}
-
-.terminal .xterm-bg-color-68 {
- background-color: #5f87d7;
-}
-
-.terminal .xterm-color-69 {
- color: #5f87ff;
-}
-
-.terminal .xterm-bg-color-69 {
- background-color: #5f87ff;
-}
-
-.terminal .xterm-color-70 {
- color: #5faf00;
-}
-
-.terminal .xterm-bg-color-70 {
- background-color: #5faf00;
-}
-
-.terminal .xterm-color-71 {
- color: #5faf5f;
-}
-
-.terminal .xterm-bg-color-71 {
- background-color: #5faf5f;
-}
-
-.terminal .xterm-color-72 {
- color: #5faf87;
-}
-
-.terminal .xterm-bg-color-72 {
- background-color: #5faf87;
-}
-
-.terminal .xterm-color-73 {
- color: #5fafaf;
-}
-
-.terminal .xterm-bg-color-73 {
- background-color: #5fafaf;
-}
-
-.terminal .xterm-color-74 {
- color: #5fafd7;
-}
-
-.terminal .xterm-bg-color-74 {
- background-color: #5fafd7;
-}
-
-.terminal .xterm-color-75 {
- color: #5fafff;
-}
-
-.terminal .xterm-bg-color-75 {
- background-color: #5fafff;
-}
-
-.terminal .xterm-color-76 {
- color: #5fd700;
-}
-
-.terminal .xterm-bg-color-76 {
- background-color: #5fd700;
-}
-
-.terminal .xterm-color-77 {
- color: #5fd75f;
-}
-
-.terminal .xterm-bg-color-77 {
- background-color: #5fd75f;
-}
-
-.terminal .xterm-color-78 {
- color: #5fd787;
-}
-
-.terminal .xterm-bg-color-78 {
- background-color: #5fd787;
-}
-
-.terminal .xterm-color-79 {
- color: #5fd7af;
-}
-
-.terminal .xterm-bg-color-79 {
- background-color: #5fd7af;
-}
-
-.terminal .xterm-color-80 {
- color: #5fd7d7;
-}
-
-.terminal .xterm-bg-color-80 {
- background-color: #5fd7d7;
-}
-
-.terminal .xterm-color-81 {
- color: #5fd7ff;
-}
-
-.terminal .xterm-bg-color-81 {
- background-color: #5fd7ff;
-}
-
-.terminal .xterm-color-82 {
- color: #5fff00;
-}
-
-.terminal .xterm-bg-color-82 {
- background-color: #5fff00;
-}
-
-.terminal .xterm-color-83 {
- color: #5fff5f;
-}
-
-.terminal .xterm-bg-color-83 {
- background-color: #5fff5f;
-}
-
-.terminal .xterm-color-84 {
- color: #5fff87;
-}
-
-.terminal .xterm-bg-color-84 {
- background-color: #5fff87;
-}
-
-.terminal .xterm-color-85 {
- color: #5fffaf;
-}
-
-.terminal .xterm-bg-color-85 {
- background-color: #5fffaf;
-}
-
-.terminal .xterm-color-86 {
- color: #5fffd7;
-}
-
-.terminal .xterm-bg-color-86 {
- background-color: #5fffd7;
-}
-
-.terminal .xterm-color-87 {
- color: #5fffff;
-}
-
-.terminal .xterm-bg-color-87 {
- background-color: #5fffff;
-}
-
-.terminal .xterm-color-88 {
- color: #870000;
-}
-
-.terminal .xterm-bg-color-88 {
- background-color: #870000;
-}
-
-.terminal .xterm-color-89 {
- color: #87005f;
-}
-
-.terminal .xterm-bg-color-89 {
- background-color: #87005f;
-}
-
-.terminal .xterm-color-90 {
- color: #870087;
-}
-
-.terminal .xterm-bg-color-90 {
- background-color: #870087;
-}
-
-.terminal .xterm-color-91 {
- color: #8700af;
-}
-
-.terminal .xterm-bg-color-91 {
- background-color: #8700af;
-}
-
-.terminal .xterm-color-92 {
- color: #8700d7;
-}
-
-.terminal .xterm-bg-color-92 {
- background-color: #8700d7;
-}
-
-.terminal .xterm-color-93 {
- color: #8700ff;
-}
-
-.terminal .xterm-bg-color-93 {
- background-color: #8700ff;
-}
-
-.terminal .xterm-color-94 {
- color: #875f00;
-}
-
-.terminal .xterm-bg-color-94 {
- background-color: #875f00;
-}
-
-.terminal .xterm-color-95 {
- color: #875f5f;
-}
-
-.terminal .xterm-bg-color-95 {
- background-color: #875f5f;
-}
-
-.terminal .xterm-color-96 {
- color: #875f87;
-}
-
-.terminal .xterm-bg-color-96 {
- background-color: #875f87;
-}
-
-.terminal .xterm-color-97 {
- color: #875faf;
-}
-
-.terminal .xterm-bg-color-97 {
- background-color: #875faf;
-}
-
-.terminal .xterm-color-98 {
- color: #875fd7;
-}
-
-.terminal .xterm-bg-color-98 {
- background-color: #875fd7;
-}
-
-.terminal .xterm-color-99 {
- color: #875fff;
-}
-
-.terminal .xterm-bg-color-99 {
- background-color: #875fff;
-}
-
-.terminal .xterm-color-100 {
- color: #878700;
-}
-
-.terminal .xterm-bg-color-100 {
- background-color: #878700;
-}
-
-.terminal .xterm-color-101 {
- color: #87875f;
-}
-
-.terminal .xterm-bg-color-101 {
- background-color: #87875f;
-}
-
-.terminal .xterm-color-102 {
- color: #878787;
-}
-
-.terminal .xterm-bg-color-102 {
- background-color: #878787;
-}
-
-.terminal .xterm-color-103 {
- color: #8787af;
-}
-
-.terminal .xterm-bg-color-103 {
- background-color: #8787af;
-}
-
-.terminal .xterm-color-104 {
- color: #8787d7;
-}
-
-.terminal .xterm-bg-color-104 {
- background-color: #8787d7;
-}
-
-.terminal .xterm-color-105 {
- color: #8787ff;
-}
-
-.terminal .xterm-bg-color-105 {
- background-color: #8787ff;
-}
-
-.terminal .xterm-color-106 {
- color: #87af00;
-}
-
-.terminal .xterm-bg-color-106 {
- background-color: #87af00;
-}
-
-.terminal .xterm-color-107 {
- color: #87af5f;
-}
-
-.terminal .xterm-bg-color-107 {
- background-color: #87af5f;
-}
-
-.terminal .xterm-color-108 {
- color: #87af87;
-}
-
-.terminal .xterm-bg-color-108 {
- background-color: #87af87;
-}
-
-.terminal .xterm-color-109 {
- color: #87afaf;
-}
-
-.terminal .xterm-bg-color-109 {
- background-color: #87afaf;
-}
-
-.terminal .xterm-color-110 {
- color: #87afd7;
-}
-
-.terminal .xterm-bg-color-110 {
- background-color: #87afd7;
-}
-
-.terminal .xterm-color-111 {
- color: #87afff;
-}
-
-.terminal .xterm-bg-color-111 {
- background-color: #87afff;
-}
-
-.terminal .xterm-color-112 {
- color: #87d700;
-}
-
-.terminal .xterm-bg-color-112 {
- background-color: #87d700;
-}
-
-.terminal .xterm-color-113 {
- color: #87d75f;
-}
-
-.terminal .xterm-bg-color-113 {
- background-color: #87d75f;
-}
-
-.terminal .xterm-color-114 {
- color: #87d787;
-}
-
-.terminal .xterm-bg-color-114 {
- background-color: #87d787;
-}
-
-.terminal .xterm-color-115 {
- color: #87d7af;
-}
-
-.terminal .xterm-bg-color-115 {
- background-color: #87d7af;
-}
-
-.terminal .xterm-color-116 {
- color: #87d7d7;
-}
-
-.terminal .xterm-bg-color-116 {
- background-color: #87d7d7;
-}
-
-.terminal .xterm-color-117 {
- color: #87d7ff;
-}
-
-.terminal .xterm-bg-color-117 {
- background-color: #87d7ff;
-}
-
-.terminal .xterm-color-118 {
- color: #87ff00;
-}
-
-.terminal .xterm-bg-color-118 {
- background-color: #87ff00;
-}
-
-.terminal .xterm-color-119 {
- color: #87ff5f;
-}
-
-.terminal .xterm-bg-color-119 {
- background-color: #87ff5f;
-}
-
-.terminal .xterm-color-120 {
- color: #87ff87;
-}
-
-.terminal .xterm-bg-color-120 {
- background-color: #87ff87;
-}
-
-.terminal .xterm-color-121 {
- color: #87ffaf;
-}
-
-.terminal .xterm-bg-color-121 {
- background-color: #87ffaf;
-}
-
-.terminal .xterm-color-122 {
- color: #87ffd7;
-}
-
-.terminal .xterm-bg-color-122 {
- background-color: #87ffd7;
-}
-
-.terminal .xterm-color-123 {
- color: #87ffff;
-}
-
-.terminal .xterm-bg-color-123 {
- background-color: #87ffff;
-}
-
-.terminal .xterm-color-124 {
- color: #af0000;
-}
-
-.terminal .xterm-bg-color-124 {
- background-color: #af0000;
-}
-
-.terminal .xterm-color-125 {
- color: #af005f;
-}
-
-.terminal .xterm-bg-color-125 {
- background-color: #af005f;
-}
-
-.terminal .xterm-color-126 {
- color: #af0087;
-}
-
-.terminal .xterm-bg-color-126 {
- background-color: #af0087;
-}
-
-.terminal .xterm-color-127 {
- color: #af00af;
-}
-
-.terminal .xterm-bg-color-127 {
- background-color: #af00af;
-}
-
-.terminal .xterm-color-128 {
- color: #af00d7;
-}
-
-.terminal .xterm-bg-color-128 {
- background-color: #af00d7;
-}
-
-.terminal .xterm-color-129 {
- color: #af00ff;
-}
-
-.terminal .xterm-bg-color-129 {
- background-color: #af00ff;
-}
-
-.terminal .xterm-color-130 {
- color: #af5f00;
-}
-
-.terminal .xterm-bg-color-130 {
- background-color: #af5f00;
-}
-
-.terminal .xterm-color-131 {
- color: #af5f5f;
-}
-
-.terminal .xterm-bg-color-131 {
- background-color: #af5f5f;
-}
-
-.terminal .xterm-color-132 {
- color: #af5f87;
-}
-
-.terminal .xterm-bg-color-132 {
- background-color: #af5f87;
-}
-
-.terminal .xterm-color-133 {
- color: #af5faf;
-}
-
-.terminal .xterm-bg-color-133 {
- background-color: #af5faf;
-}
-
-.terminal .xterm-color-134 {
- color: #af5fd7;
-}
-
-.terminal .xterm-bg-color-134 {
- background-color: #af5fd7;
-}
-
-.terminal .xterm-color-135 {
- color: #af5fff;
-}
-
-.terminal .xterm-bg-color-135 {
- background-color: #af5fff;
-}
-
-.terminal .xterm-color-136 {
- color: #af8700;
-}
-
-.terminal .xterm-bg-color-136 {
- background-color: #af8700;
-}
-
-.terminal .xterm-color-137 {
- color: #af875f;
-}
-
-.terminal .xterm-bg-color-137 {
- background-color: #af875f;
-}
-
-.terminal .xterm-color-138 {
- color: #af8787;
-}
-
-.terminal .xterm-bg-color-138 {
- background-color: #af8787;
-}
-
-.terminal .xterm-color-139 {
- color: #af87af;
-}
-
-.terminal .xterm-bg-color-139 {
- background-color: #af87af;
-}
-
-.terminal .xterm-color-140 {
- color: #af87d7;
-}
-
-.terminal .xterm-bg-color-140 {
- background-color: #af87d7;
-}
-
-.terminal .xterm-color-141 {
- color: #af87ff;
-}
-
-.terminal .xterm-bg-color-141 {
- background-color: #af87ff;
-}
-
-.terminal .xterm-color-142 {
- color: #afaf00;
-}
-
-.terminal .xterm-bg-color-142 {
- background-color: #afaf00;
-}
-
-.terminal .xterm-color-143 {
- color: #afaf5f;
-}
-
-.terminal .xterm-bg-color-143 {
- background-color: #afaf5f;
-}
-
-.terminal .xterm-color-144 {
- color: #afaf87;
-}
-
-.terminal .xterm-bg-color-144 {
- background-color: #afaf87;
-}
-
-.terminal .xterm-color-145 {
- color: #afafaf;
-}
-
-.terminal .xterm-bg-color-145 {
- background-color: #afafaf;
-}
-
-.terminal .xterm-color-146 {
- color: #afafd7;
-}
-
-.terminal .xterm-bg-color-146 {
- background-color: #afafd7;
-}
-
-.terminal .xterm-color-147 {
- color: #afafff;
-}
-
-.terminal .xterm-bg-color-147 {
- background-color: #afafff;
-}
-
-.terminal .xterm-color-148 {
- color: #afd700;
-}
-
-.terminal .xterm-bg-color-148 {
- background-color: #afd700;
-}
-
-.terminal .xterm-color-149 {
- color: #afd75f;
-}
-
-.terminal .xterm-bg-color-149 {
- background-color: #afd75f;
-}
-
-.terminal .xterm-color-150 {
- color: #afd787;
-}
-
-.terminal .xterm-bg-color-150 {
- background-color: #afd787;
-}
-
-.terminal .xterm-color-151 {
- color: #afd7af;
-}
-
-.terminal .xterm-bg-color-151 {
- background-color: #afd7af;
-}
-
-.terminal .xterm-color-152 {
- color: #afd7d7;
-}
-
-.terminal .xterm-bg-color-152 {
- background-color: #afd7d7;
-}
-
-.terminal .xterm-color-153 {
- color: #afd7ff;
-}
-
-.terminal .xterm-bg-color-153 {
- background-color: #afd7ff;
-}
-
-.terminal .xterm-color-154 {
- color: #afff00;
-}
-
-.terminal .xterm-bg-color-154 {
- background-color: #afff00;
-}
-
-.terminal .xterm-color-155 {
- color: #afff5f;
-}
-
-.terminal .xterm-bg-color-155 {
- background-color: #afff5f;
-}
-
-.terminal .xterm-color-156 {
- color: #afff87;
-}
-
-.terminal .xterm-bg-color-156 {
- background-color: #afff87;
-}
-
-.terminal .xterm-color-157 {
- color: #afffaf;
-}
-
-.terminal .xterm-bg-color-157 {
- background-color: #afffaf;
-}
-
-.terminal .xterm-color-158 {
- color: #afffd7;
-}
-
-.terminal .xterm-bg-color-158 {
- background-color: #afffd7;
-}
-
-.terminal .xterm-color-159 {
- color: #afffff;
-}
-
-.terminal .xterm-bg-color-159 {
- background-color: #afffff;
-}
-
-.terminal .xterm-color-160 {
- color: #d70000;
-}
-
-.terminal .xterm-bg-color-160 {
- background-color: #d70000;
-}
-
-.terminal .xterm-color-161 {
- color: #d7005f;
-}
-
-.terminal .xterm-bg-color-161 {
- background-color: #d7005f;
-}
-
-.terminal .xterm-color-162 {
- color: #d70087;
-}
-
-.terminal .xterm-bg-color-162 {
- background-color: #d70087;
-}
-
-.terminal .xterm-color-163 {
- color: #d700af;
-}
-
-.terminal .xterm-bg-color-163 {
- background-color: #d700af;
-}
-
-.terminal .xterm-color-164 {
- color: #d700d7;
-}
-
-.terminal .xterm-bg-color-164 {
- background-color: #d700d7;
-}
-
-.terminal .xterm-color-165 {
- color: #d700ff;
-}
-
-.terminal .xterm-bg-color-165 {
- background-color: #d700ff;
-}
-
-.terminal .xterm-color-166 {
- color: #d75f00;
-}
-
-.terminal .xterm-bg-color-166 {
- background-color: #d75f00;
-}
-
-.terminal .xterm-color-167 {
- color: #d75f5f;
-}
-
-.terminal .xterm-bg-color-167 {
- background-color: #d75f5f;
-}
-
-.terminal .xterm-color-168 {
- color: #d75f87;
-}
-
-.terminal .xterm-bg-color-168 {
- background-color: #d75f87;
-}
-
-.terminal .xterm-color-169 {
- color: #d75faf;
-}
-
-.terminal .xterm-bg-color-169 {
- background-color: #d75faf;
-}
-
-.terminal .xterm-color-170 {
- color: #d75fd7;
-}
-
-.terminal .xterm-bg-color-170 {
- background-color: #d75fd7;
-}
-
-.terminal .xterm-color-171 {
- color: #d75fff;
-}
-
-.terminal .xterm-bg-color-171 {
- background-color: #d75fff;
-}
-
-.terminal .xterm-color-172 {
- color: #d78700;
-}
-
-.terminal .xterm-bg-color-172 {
- background-color: #d78700;
-}
-
-.terminal .xterm-color-173 {
- color: #d7875f;
-}
-
-.terminal .xterm-bg-color-173 {
- background-color: #d7875f;
-}
-
-.terminal .xterm-color-174 {
- color: #d78787;
-}
-
-.terminal .xterm-bg-color-174 {
- background-color: #d78787;
-}
-
-.terminal .xterm-color-175 {
- color: #d787af;
-}
-
-.terminal .xterm-bg-color-175 {
- background-color: #d787af;
-}
-
-.terminal .xterm-color-176 {
- color: #d787d7;
-}
-
-.terminal .xterm-bg-color-176 {
- background-color: #d787d7;
-}
-
-.terminal .xterm-color-177 {
- color: #d787ff;
-}
-
-.terminal .xterm-bg-color-177 {
- background-color: #d787ff;
-}
-
-.terminal .xterm-color-178 {
- color: #d7af00;
-}
-
-.terminal .xterm-bg-color-178 {
- background-color: #d7af00;
-}
-
-.terminal .xterm-color-179 {
- color: #d7af5f;
-}
-
-.terminal .xterm-bg-color-179 {
- background-color: #d7af5f;
-}
-
-.terminal .xterm-color-180 {
- color: #d7af87;
-}
-
-.terminal .xterm-bg-color-180 {
- background-color: #d7af87;
-}
-
-.terminal .xterm-color-181 {
- color: #d7afaf;
-}
-
-.terminal .xterm-bg-color-181 {
- background-color: #d7afaf;
-}
-
-.terminal .xterm-color-182 {
- color: #d7afd7;
-}
-
-.terminal .xterm-bg-color-182 {
- background-color: #d7afd7;
-}
-
-.terminal .xterm-color-183 {
- color: #d7afff;
-}
-
-.terminal .xterm-bg-color-183 {
- background-color: #d7afff;
-}
-
-.terminal .xterm-color-184 {
- color: #d7d700;
-}
-
-.terminal .xterm-bg-color-184 {
- background-color: #d7d700;
-}
-
-.terminal .xterm-color-185 {
- color: #d7d75f;
-}
-
-.terminal .xterm-bg-color-185 {
- background-color: #d7d75f;
-}
-
-.terminal .xterm-color-186 {
- color: #d7d787;
-}
-
-.terminal .xterm-bg-color-186 {
- background-color: #d7d787;
-}
-
-.terminal .xterm-color-187 {
- color: #d7d7af;
-}
-
-.terminal .xterm-bg-color-187 {
- background-color: #d7d7af;
-}
-
-.terminal .xterm-color-188 {
- color: #d7d7d7;
-}
-
-.terminal .xterm-bg-color-188 {
- background-color: #d7d7d7;
-}
-
-.terminal .xterm-color-189 {
- color: #d7d7ff;
-}
-
-.terminal .xterm-bg-color-189 {
- background-color: #d7d7ff;
-}
-
-.terminal .xterm-color-190 {
- color: #d7ff00;
-}
-
-.terminal .xterm-bg-color-190 {
- background-color: #d7ff00;
-}
-
-.terminal .xterm-color-191 {
- color: #d7ff5f;
-}
-
-.terminal .xterm-bg-color-191 {
- background-color: #d7ff5f;
-}
-
-.terminal .xterm-color-192 {
- color: #d7ff87;
-}
-
-.terminal .xterm-bg-color-192 {
- background-color: #d7ff87;
-}
-
-.terminal .xterm-color-193 {
- color: #d7ffaf;
-}
-
-.terminal .xterm-bg-color-193 {
- background-color: #d7ffaf;
-}
-
-.terminal .xterm-color-194 {
- color: #d7ffd7;
-}
-
-.terminal .xterm-bg-color-194 {
- background-color: #d7ffd7;
-}
-
-.terminal .xterm-color-195 {
- color: #d7ffff;
-}
-
-.terminal .xterm-bg-color-195 {
- background-color: #d7ffff;
-}
-
-.terminal .xterm-color-196 {
- color: #ff0000;
-}
-
-.terminal .xterm-bg-color-196 {
- background-color: #ff0000;
-}
-
-.terminal .xterm-color-197 {
- color: #ff005f;
-}
-
-.terminal .xterm-bg-color-197 {
- background-color: #ff005f;
-}
-
-.terminal .xterm-color-198 {
- color: #ff0087;
-}
-
-.terminal .xterm-bg-color-198 {
- background-color: #ff0087;
-}
-
-.terminal .xterm-color-199 {
- color: #ff00af;
-}
-
-.terminal .xterm-bg-color-199 {
- background-color: #ff00af;
-}
-
-.terminal .xterm-color-200 {
- color: #ff00d7;
-}
-
-.terminal .xterm-bg-color-200 {
- background-color: #ff00d7;
-}
-
-.terminal .xterm-color-201 {
- color: #ff00ff;
-}
-
-.terminal .xterm-bg-color-201 {
- background-color: #ff00ff;
-}
-
-.terminal .xterm-color-202 {
- color: #ff5f00;
-}
-
-.terminal .xterm-bg-color-202 {
- background-color: #ff5f00;
-}
-
-.terminal .xterm-color-203 {
- color: #ff5f5f;
-}
-
-.terminal .xterm-bg-color-203 {
- background-color: #ff5f5f;
-}
-
-.terminal .xterm-color-204 {
- color: #ff5f87;
-}
-
-.terminal .xterm-bg-color-204 {
- background-color: #ff5f87;
-}
-
-.terminal .xterm-color-205 {
- color: #ff5faf;
-}
-
-.terminal .xterm-bg-color-205 {
- background-color: #ff5faf;
-}
-
-.terminal .xterm-color-206 {
- color: #ff5fd7;
-}
-
-.terminal .xterm-bg-color-206 {
- background-color: #ff5fd7;
-}
-
-.terminal .xterm-color-207 {
- color: #ff5fff;
-}
-
-.terminal .xterm-bg-color-207 {
- background-color: #ff5fff;
-}
-
-.terminal .xterm-color-208 {
- color: #ff8700;
-}
-
-.terminal .xterm-bg-color-208 {
- background-color: #ff8700;
-}
-
-.terminal .xterm-color-209 {
- color: #ff875f;
-}
-
-.terminal .xterm-bg-color-209 {
- background-color: #ff875f;
-}
-
-.terminal .xterm-color-210 {
- color: #ff8787;
-}
-
-.terminal .xterm-bg-color-210 {
- background-color: #ff8787;
-}
-
-.terminal .xterm-color-211 {
- color: #ff87af;
-}
-
-.terminal .xterm-bg-color-211 {
- background-color: #ff87af;
-}
-
-.terminal .xterm-color-212 {
- color: #ff87d7;
-}
-
-.terminal .xterm-bg-color-212 {
- background-color: #ff87d7;
-}
-
-.terminal .xterm-color-213 {
- color: #ff87ff;
-}
-
-.terminal .xterm-bg-color-213 {
- background-color: #ff87ff;
-}
-
-.terminal .xterm-color-214 {
- color: #ffaf00;
-}
-
-.terminal .xterm-bg-color-214 {
- background-color: #ffaf00;
-}
-
-.terminal .xterm-color-215 {
- color: #ffaf5f;
-}
-
-.terminal .xterm-bg-color-215 {
- background-color: #ffaf5f;
-}
-
-.terminal .xterm-color-216 {
- color: #ffaf87;
-}
-
-.terminal .xterm-bg-color-216 {
- background-color: #ffaf87;
-}
-
-.terminal .xterm-color-217 {
- color: #ffafaf;
-}
-
-.terminal .xterm-bg-color-217 {
- background-color: #ffafaf;
-}
-
-.terminal .xterm-color-218 {
- color: #ffafd7;
-}
-
-.terminal .xterm-bg-color-218 {
- background-color: #ffafd7;
-}
-
-.terminal .xterm-color-219 {
- color: #ffafff;
-}
-
-.terminal .xterm-bg-color-219 {
- background-color: #ffafff;
-}
-
-.terminal .xterm-color-220 {
- color: #ffd700;
-}
-
-.terminal .xterm-bg-color-220 {
- background-color: #ffd700;
-}
-
-.terminal .xterm-color-221 {
- color: #ffd75f;
-}
-
-.terminal .xterm-bg-color-221 {
- background-color: #ffd75f;
-}
-
-.terminal .xterm-color-222 {
- color: #ffd787;
-}
-
-.terminal .xterm-bg-color-222 {
- background-color: #ffd787;
-}
-
-.terminal .xterm-color-223 {
- color: #ffd7af;
-}
-
-.terminal .xterm-bg-color-223 {
- background-color: #ffd7af;
-}
-
-.terminal .xterm-color-224 {
- color: #ffd7d7;
-}
-
-.terminal .xterm-bg-color-224 {
- background-color: #ffd7d7;
-}
-
-.terminal .xterm-color-225 {
- color: #ffd7ff;
-}
-
-.terminal .xterm-bg-color-225 {
- background-color: #ffd7ff;
-}
-
-.terminal .xterm-color-226 {
- color: #ffff00;
-}
-
-.terminal .xterm-bg-color-226 {
- background-color: #ffff00;
-}
-
-.terminal .xterm-color-227 {
- color: #ffff5f;
-}
-
-.terminal .xterm-bg-color-227 {
- background-color: #ffff5f;
-}
-
-.terminal .xterm-color-228 {
- color: #ffff87;
-}
-
-.terminal .xterm-bg-color-228 {
- background-color: #ffff87;
-}
-
-.terminal .xterm-color-229 {
- color: #ffffaf;
-}
-
-.terminal .xterm-bg-color-229 {
- background-color: #ffffaf;
-}
-
-.terminal .xterm-color-230 {
- color: #ffffd7;
-}
-
-.terminal .xterm-bg-color-230 {
- background-color: #ffffd7;
-}
-
-.terminal .xterm-color-231 {
- color: #ffffff;
-}
-
-.terminal .xterm-bg-color-231 {
- background-color: #ffffff;
-}
-
-.terminal .xterm-color-232 {
- color: #080808;
-}
-
-.terminal .xterm-bg-color-232 {
- background-color: #080808;
-}
-
-.terminal .xterm-color-233 {
- color: #121212;
-}
-
-.terminal .xterm-bg-color-233 {
- background-color: #121212;
-}
-
-.terminal .xterm-color-234 {
- color: #1c1c1c;
-}
-
-.terminal .xterm-bg-color-234 {
- background-color: #1c1c1c;
-}
-
-.terminal .xterm-color-235 {
- color: #262626;
-}
-
-.terminal .xterm-bg-color-235 {
- background-color: #262626;
-}
-
-.terminal .xterm-color-236 {
- color: #303030;
-}
-
-.terminal .xterm-bg-color-236 {
- background-color: #303030;
-}
-
-.terminal .xterm-color-237 {
- color: #3a3a3a;
-}
-
-.terminal .xterm-bg-color-237 {
- background-color: #3a3a3a;
-}
-
-.terminal .xterm-color-238 {
- color: #444444;
-}
-
-.terminal .xterm-bg-color-238 {
- background-color: #444444;
-}
-
-.terminal .xterm-color-239 {
- color: #4e4e4e;
-}
-
-.terminal .xterm-bg-color-239 {
- background-color: #4e4e4e;
-}
-
-.terminal .xterm-color-240 {
- color: #585858;
-}
-
-.terminal .xterm-bg-color-240 {
- background-color: #585858;
-}
-
-.terminal .xterm-color-241 {
- color: #626262;
-}
-
-.terminal .xterm-bg-color-241 {
- background-color: #626262;
-}
-
-.terminal .xterm-color-242 {
- color: #6c6c6c;
-}
-
-.terminal .xterm-bg-color-242 {
- background-color: #6c6c6c;
-}
-
-.terminal .xterm-color-243 {
- color: #767676;
-}
-
-.terminal .xterm-bg-color-243 {
- background-color: #767676;
-}
-
-.terminal .xterm-color-244 {
- color: #808080;
-}
-
-.terminal .xterm-bg-color-244 {
- background-color: #808080;
-}
-
-.terminal .xterm-color-245 {
- color: #8a8a8a;
-}
-
-.terminal .xterm-bg-color-245 {
- background-color: #8a8a8a;
-}
-
-.terminal .xterm-color-246 {
- color: #949494;
-}
-
-.terminal .xterm-bg-color-246 {
- background-color: #949494;
-}
-
-.terminal .xterm-color-247 {
- color: #9e9e9e;
-}
-
-.terminal .xterm-bg-color-247 {
- background-color: #9e9e9e;
-}
-
-.terminal .xterm-color-248 {
- color: #a8a8a8;
-}
-
-.terminal .xterm-bg-color-248 {
- background-color: #a8a8a8;
-}
-
-.terminal .xterm-color-249 {
- color: #b2b2b2;
-}
-
-.terminal .xterm-bg-color-249 {
- background-color: #b2b2b2;
-}
-
-.terminal .xterm-color-250 {
- color: #bcbcbc;
-}
-
-.terminal .xterm-bg-color-250 {
- background-color: #bcbcbc;
-}
-
-.terminal .xterm-color-251 {
- color: #c6c6c6;
-}
-
-.terminal .xterm-bg-color-251 {
- background-color: #c6c6c6;
-}
-
-.terminal .xterm-color-252 {
- color: #d0d0d0;
-}
-
-.terminal .xterm-bg-color-252 {
- background-color: #d0d0d0;
-}
-
-.terminal .xterm-color-253 {
- color: #dadada;
-}
-
-.terminal .xterm-bg-color-253 {
- background-color: #dadada;
-}
-
-.terminal .xterm-color-254 {
- color: #e4e4e4;
-}
-
-.terminal .xterm-bg-color-254 {
- background-color: #e4e4e4;
-}
-
-.terminal .xterm-color-255 {
- color: #eeeeee;
-}
-
-.terminal .xterm-bg-color-255 {
- background-color: #eeeeee;
-}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.js b/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.js
deleted file mode 100644
index 7dfaab5abf6..00000000000
--- a/chromium/third_party/blink/renderer/devtools/front_end/terminal/xterm.js/build/xterm.js
+++ /dev/null
@@ -1,4318 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.CHARSETS = {};
-exports.DEFAULT_CHARSET = exports.CHARSETS['B'];
-exports.CHARSETS['0'] = {
- '`': '\u25c6',
- 'a': '\u2592',
- 'b': '\u0009',
- 'c': '\u000c',
- 'd': '\u000d',
- 'e': '\u000a',
- 'f': '\u00b0',
- 'g': '\u00b1',
- 'h': '\u2424',
- 'i': '\u000b',
- 'j': '\u2518',
- 'k': '\u2510',
- 'l': '\u250c',
- 'm': '\u2514',
- 'n': '\u253c',
- 'o': '\u23ba',
- 'p': '\u23bb',
- 'q': '\u2500',
- 'r': '\u23bc',
- 's': '\u23bd',
- 't': '\u251c',
- 'u': '\u2524',
- 'v': '\u2534',
- 'w': '\u252c',
- 'x': '\u2502',
- 'y': '\u2264',
- 'z': '\u2265',
- '{': '\u03c0',
- '|': '\u2260',
- '}': '\u00a3',
- '~': '\u00b7'
-};
-exports.CHARSETS['A'] = {
- '#': '£'
-};
-exports.CHARSETS['B'] = null;
-exports.CHARSETS['4'] = {
- '#': '£',
- '@': '¾',
- '[': 'ij',
- '\\': '½',
- ']': '|',
- '{': '¨',
- '|': 'f',
- '}': '¼',
- '~': '´'
-};
-exports.CHARSETS['C'] =
- exports.CHARSETS['5'] = {
- '[': 'Ä',
- '\\': 'Ö',
- ']': 'Å',
- '^': 'Ü',
- '`': 'é',
- '{': 'ä',
- '|': 'ö',
- '}': 'å',
- '~': 'ü'
- };
-exports.CHARSETS['R'] = {
- '#': '£',
- '@': 'à',
- '[': '°',
- '\\': 'ç',
- ']': '§',
- '{': 'é',
- '|': 'ù',
- '}': 'è',
- '~': '¨'
-};
-exports.CHARSETS['Q'] = {
- '@': 'à',
- '[': 'â',
- '\\': 'ç',
- ']': 'ê',
- '^': 'î',
- '`': 'ô',
- '{': 'é',
- '|': 'ù',
- '}': 'è',
- '~': 'û'
-};
-exports.CHARSETS['K'] = {
- '@': '§',
- '[': 'Ä',
- '\\': 'Ö',
- ']': 'Ü',
- '{': 'ä',
- '|': 'ö',
- '}': 'ü',
- '~': 'ß'
-};
-exports.CHARSETS['Y'] = {
- '#': '£',
- '@': '§',
- '[': '°',
- '\\': 'ç',
- ']': 'é',
- '`': 'ù',
- '{': 'à',
- '|': 'ò',
- '}': 'è',
- '~': 'ì'
-};
-exports.CHARSETS['E'] =
- exports.CHARSETS['6'] = {
- '@': 'Ä',
- '[': 'Æ',
- '\\': 'Ø',
- ']': 'Å',
- '^': 'Ü',
- '`': 'ä',
- '{': 'æ',
- '|': 'ø',
- '}': 'å',
- '~': 'ü'
- };
-exports.CHARSETS['Z'] = {
- '#': '£',
- '@': '§',
- '[': '¡',
- '\\': 'Ñ',
- ']': '¿',
- '{': '°',
- '|': 'ñ',
- '}': 'ç'
-};
-exports.CHARSETS['H'] =
- exports.CHARSETS['7'] = {
- '@': 'É',
- '[': 'Ä',
- '\\': 'Ö',
- ']': 'Å',
- '^': 'Ü',
- '`': 'é',
- '{': 'ä',
- '|': 'ö',
- '}': 'å',
- '~': 'ü'
- };
-exports.CHARSETS['='] = {
- '#': 'ù',
- '@': 'à',
- '[': 'é',
- '\\': 'ç',
- ']': 'ê',
- '^': 'î',
- '_': 'è',
- '`': 'ô',
- '{': 'ä',
- '|': 'ö',
- '}': 'ü',
- '~': 'û'
-};
-
-
-
-},{}],2:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var CompositionHelper = (function () {
- function CompositionHelper(textarea, compositionView, terminal) {
- this.textarea = textarea;
- this.compositionView = compositionView;
- this.terminal = terminal;
- this.isComposing = false;
- this.isSendingComposition = false;
- this.compositionPosition = { start: null, end: null };
- }
- CompositionHelper.prototype.compositionstart = function () {
- this.isComposing = true;
- this.compositionPosition.start = this.textarea.value.length;
- this.compositionView.textContent = '';
- this.compositionView.classList.add('active');
- };
- CompositionHelper.prototype.compositionupdate = function (ev) {
- var _this = this;
- this.compositionView.textContent = ev.data;
- this.updateCompositionElements();
- setTimeout(function () {
- _this.compositionPosition.end = _this.textarea.value.length;
- }, 0);
- };
- CompositionHelper.prototype.compositionend = function () {
- this.finalizeComposition(true);
- };
- CompositionHelper.prototype.keydown = function (ev) {
- if (this.isComposing || this.isSendingComposition) {
- if (ev.keyCode === 229) {
- return false;
- }
- else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {
- return false;
- }
- else {
- this.finalizeComposition(false);
- }
- }
- if (ev.keyCode === 229) {
- this.handleAnyTextareaChanges();
- return false;
- }
- return true;
- };
- CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) {
- var _this = this;
- this.compositionView.classList.remove('active');
- this.isComposing = false;
- this.clearTextareaPosition();
- if (!waitForPropogation) {
- this.isSendingComposition = false;
- var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end);
- this.terminal.handler(input);
- }
- else {
- var currentCompositionPosition_1 = {
- start: this.compositionPosition.start,
- end: this.compositionPosition.end,
- };
- this.isSendingComposition = true;
- setTimeout(function () {
- if (_this.isSendingComposition) {
- _this.isSendingComposition = false;
- var input = void 0;
- if (_this.isComposing) {
- input = _this.textarea.value.substring(currentCompositionPosition_1.start, currentCompositionPosition_1.end);
- }
- else {
- input = _this.textarea.value.substring(currentCompositionPosition_1.start);
- }
- _this.terminal.handler(input);
- }
- }, 0);
- }
- };
- CompositionHelper.prototype.handleAnyTextareaChanges = function () {
- var _this = this;
- var oldValue = this.textarea.value;
- setTimeout(function () {
- if (!_this.isComposing) {
- var newValue = _this.textarea.value;
- var diff = newValue.replace(oldValue, '');
- if (diff.length > 0) {
- _this.terminal.handler(diff);
- }
- }
- }, 0);
- };
- CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) {
- var _this = this;
- if (!this.isComposing) {
- return;
- }
- var cursor = this.terminal.element.querySelector('.terminal-cursor');
- if (cursor) {
- var xtermRows = this.terminal.element.querySelector('.xterm-rows');
- var cursorTop = xtermRows.offsetTop + cursor.offsetTop;
- this.compositionView.style.left = cursor.offsetLeft + 'px';
- this.compositionView.style.top = cursorTop + 'px';
- this.compositionView.style.height = cursor.offsetHeight + 'px';
- this.compositionView.style.lineHeight = cursor.offsetHeight + 'px';
- var compositionViewBounds = this.compositionView.getBoundingClientRect();
- this.textarea.style.left = cursor.offsetLeft + 'px';
- this.textarea.style.top = cursorTop + 'px';
- this.textarea.style.width = compositionViewBounds.width + 'px';
- this.textarea.style.height = compositionViewBounds.height + 'px';
- this.textarea.style.lineHeight = compositionViewBounds.height + 'px';
- }
- if (!dontRecurse) {
- setTimeout(function () { return _this.updateCompositionElements(true); }, 0);
- }
- };
- ;
- CompositionHelper.prototype.clearTextareaPosition = function () {
- this.textarea.style.left = '';
- this.textarea.style.top = '';
- };
- ;
- return CompositionHelper;
-}());
-exports.CompositionHelper = CompositionHelper;
-
-
-
-},{}],3:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var C0;
-(function (C0) {
- C0.NUL = '\x00';
- C0.SOH = '\x01';
- C0.STX = '\x02';
- C0.ETX = '\x03';
- C0.EOT = '\x04';
- C0.ENQ = '\x05';
- C0.ACK = '\x06';
- C0.BEL = '\x07';
- C0.BS = '\x08';
- C0.HT = '\x09';
- C0.LF = '\x0a';
- C0.VT = '\x0b';
- C0.FF = '\x0c';
- C0.CR = '\x0d';
- C0.SO = '\x0e';
- C0.SI = '\x0f';
- C0.DLE = '\x10';
- C0.DC1 = '\x11';
- C0.DC2 = '\x12';
- C0.DC3 = '\x13';
- C0.DC4 = '\x14';
- C0.NAK = '\x15';
- C0.SYN = '\x16';
- C0.ETB = '\x17';
- C0.CAN = '\x18';
- C0.EM = '\x19';
- C0.SUB = '\x1a';
- C0.ESC = '\x1b';
- C0.FS = '\x1c';
- C0.GS = '\x1d';
- C0.RS = '\x1e';
- C0.US = '\x1f';
- C0.SP = '\x20';
- C0.DEL = '\x7f';
-})(C0 = exports.C0 || (exports.C0 = {}));
-;
-
-
-
-},{}],4:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-;
-var EventEmitter = (function () {
- function EventEmitter() {
- this._events = this._events || {};
- }
- EventEmitter.prototype.on = function (type, listener) {
- this._events[type] = this._events[type] || [];
- this._events[type].push(listener);
- };
- EventEmitter.prototype.off = function (type, listener) {
- if (!this._events[type]) {
- return;
- }
- var obj = this._events[type];
- var i = obj.length;
- while (i--) {
- if (obj[i] === listener || obj[i].listener === listener) {
- obj.splice(i, 1);
- return;
- }
- }
- };
- EventEmitter.prototype.removeAllListeners = function (type) {
- if (this._events[type]) {
- delete this._events[type];
- }
- };
- EventEmitter.prototype.once = function (type, listener) {
- function on() {
- var args = Array.prototype.slice.call(arguments);
- this.off(type, on);
- return listener.apply(this, args);
- }
- on.listener = listener;
- return this.on(type, on);
- };
- EventEmitter.prototype.emit = function (type) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- if (!this._events[type]) {
- return;
- }
- var obj = this._events[type];
- for (var i = 0; i < obj.length; i++) {
- obj[i].apply(this, args);
- }
- };
- EventEmitter.prototype.listeners = function (type) {
- return this._events[type] || [];
- };
- return EventEmitter;
-}());
-exports.EventEmitter = EventEmitter;
-
-
-
-},{}],5:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var EscapeSequences_1 = require("./EscapeSequences");
-var Charsets_1 = require("./Charsets");
-var InputHandler = (function () {
- function InputHandler(_terminal) {
- this._terminal = _terminal;
- }
- InputHandler.prototype.addChar = function (char, code) {
- if (char >= ' ') {
- var ch_width = wcwidth(code);
- if (this._terminal.charset && this._terminal.charset[char]) {
- char = this._terminal.charset[char];
- }
- var row = this._terminal.y + this._terminal.ybase;
- if (!ch_width && this._terminal.x) {
- if (this._terminal.lines.get(row)[this._terminal.x - 1]) {
- if (!this._terminal.lines.get(row)[this._terminal.x - 1][2]) {
- if (this._terminal.lines.get(row)[this._terminal.x - 2])
- this._terminal.lines.get(row)[this._terminal.x - 2][1] += char;
- }
- else {
- this._terminal.lines.get(row)[this._terminal.x - 1][1] += char;
- }
- this._terminal.updateRange(this._terminal.y);
- }
- return;
- }
- if (this._terminal.x + ch_width - 1 >= this._terminal.cols) {
- if (this._terminal.wraparoundMode) {
- this._terminal.x = 0;
- this._terminal.y++;
- if (this._terminal.y > this._terminal.scrollBottom) {
- this._terminal.y--;
- this._terminal.scroll();
- }
- }
- else {
- if (ch_width === 2)
- return;
- }
- }
- row = this._terminal.y + this._terminal.ybase;
- if (this._terminal.insertMode) {
- for (var moves = 0; moves < ch_width; ++moves) {
- var removed = this._terminal.lines.get(this._terminal.y + this._terminal.ybase).pop();
- if (removed[2] === 0
- && this._terminal.lines.get(row)[this._terminal.cols - 2]
- && this._terminal.lines.get(row)[this._terminal.cols - 2][2] === 2)
- this._terminal.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1];
- this._terminal.lines.get(row).splice(this._terminal.x, 0, [this._terminal.curAttr, ' ', 1]);
- }
- }
- this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, char, ch_width];
- this._terminal.x++;
- this._terminal.updateRange(this._terminal.y);
- if (ch_width === 2) {
- this._terminal.lines.get(row)[this._terminal.x] = [this._terminal.curAttr, '', 0];
- this._terminal.x++;
- }
- }
- };
- InputHandler.prototype.bell = function () {
- var _this = this;
- if (!this._terminal.visualBell) {
- return;
- }
- this._terminal.element.style.borderColor = 'white';
- setTimeout(function () { return _this._terminal.element.style.borderColor = ''; }, 10);
- if (this._terminal.popOnBell) {
- this._terminal.focus();
- }
- };
- InputHandler.prototype.lineFeed = function () {
- if (this._terminal.convertEol) {
- this._terminal.x = 0;
- }
- this._terminal.y++;
- if (this._terminal.y > this._terminal.scrollBottom) {
- this._terminal.y--;
- this._terminal.scroll();
- }
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x--;
- }
- };
- InputHandler.prototype.carriageReturn = function () {
- this._terminal.x = 0;
- };
- InputHandler.prototype.backspace = function () {
- if (this._terminal.x > 0) {
- this._terminal.x--;
- }
- };
- InputHandler.prototype.tab = function () {
- this._terminal.x = this._terminal.nextStop();
- };
- InputHandler.prototype.shiftOut = function () {
- this._terminal.setgLevel(1);
- };
- InputHandler.prototype.shiftIn = function () {
- this._terminal.setgLevel(0);
- };
- InputHandler.prototype.insertChars = function (params) {
- var param, row, j, ch;
- param = params[0];
- if (param < 1)
- param = 1;
- row = this._terminal.y + this._terminal.ybase;
- j = this._terminal.x;
- ch = [this._terminal.eraseAttr(), ' ', 1];
- while (param-- && j < this._terminal.cols) {
- this._terminal.lines.get(row).splice(j++, 0, ch);
- this._terminal.lines.get(row).pop();
- }
- };
- InputHandler.prototype.cursorUp = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y -= param;
- if (this._terminal.y < 0) {
- this._terminal.y = 0;
- }
- };
- InputHandler.prototype.cursorDown = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y += param;
- if (this._terminal.y >= this._terminal.rows) {
- this._terminal.y = this._terminal.rows - 1;
- }
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x--;
- }
- };
- InputHandler.prototype.cursorForward = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.x += param;
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x = this._terminal.cols - 1;
- }
- };
- InputHandler.prototype.cursorBackward = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x--;
- }
- this._terminal.x -= param;
- if (this._terminal.x < 0) {
- this._terminal.x = 0;
- }
- };
- InputHandler.prototype.cursorNextLine = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y += param;
- if (this._terminal.y >= this._terminal.rows) {
- this._terminal.y = this._terminal.rows - 1;
- }
- this._terminal.x = 0;
- };
- ;
- InputHandler.prototype.cursorPrecedingLine = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y -= param;
- if (this._terminal.y < 0) {
- this._terminal.y = 0;
- }
- this._terminal.x = 0;
- };
- ;
- InputHandler.prototype.cursorCharAbsolute = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.x = param - 1;
- };
- InputHandler.prototype.cursorPosition = function (params) {
- var row, col;
- row = params[0] - 1;
- if (params.length >= 2) {
- col = params[1] - 1;
- }
- else {
- col = 0;
- }
- if (row < 0) {
- row = 0;
- }
- else if (row >= this._terminal.rows) {
- row = this._terminal.rows - 1;
- }
- if (col < 0) {
- col = 0;
- }
- else if (col >= this._terminal.cols) {
- col = this._terminal.cols - 1;
- }
- this._terminal.x = col;
- this._terminal.y = row;
- };
- InputHandler.prototype.cursorForwardTab = function (params) {
- var param = params[0] || 1;
- while (param--) {
- this._terminal.x = this._terminal.nextStop();
- }
- };
- InputHandler.prototype.eraseInDisplay = function (params) {
- var j;
- switch (params[0]) {
- case 0:
- this._terminal.eraseRight(this._terminal.x, this._terminal.y);
- j = this._terminal.y + 1;
- for (; j < this._terminal.rows; j++) {
- this._terminal.eraseLine(j);
- }
- break;
- case 1:
- this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
- j = this._terminal.y;
- while (j--) {
- this._terminal.eraseLine(j);
- }
- break;
- case 2:
- j = this._terminal.rows;
- while (j--)
- this._terminal.eraseLine(j);
- break;
- case 3:
- var scrollBackSize = this._terminal.lines.length - this._terminal.rows;
- if (scrollBackSize > 0) {
- this._terminal.lines.trimStart(scrollBackSize);
- this._terminal.ybase = Math.max(this._terminal.ybase - scrollBackSize, 0);
- this._terminal.ydisp = Math.max(this._terminal.ydisp - scrollBackSize, 0);
- }
- break;
- }
- };
- InputHandler.prototype.eraseInLine = function (params) {
- switch (params[0]) {
- case 0:
- this._terminal.eraseRight(this._terminal.x, this._terminal.y);
- break;
- case 1:
- this._terminal.eraseLeft(this._terminal.x, this._terminal.y);
- break;
- case 2:
- this._terminal.eraseLine(this._terminal.y);
- break;
- }
- };
- InputHandler.prototype.insertLines = function (params) {
- var param, row, j;
- param = params[0];
- if (param < 1) {
- param = 1;
- }
- row = this._terminal.y + this._terminal.ybase;
- j = this._terminal.rows - 1 - this._terminal.scrollBottom;
- j = this._terminal.rows - 1 + this._terminal.ybase - j + 1;
- while (param--) {
- if (this._terminal.lines.length === this._terminal.lines.maxLength) {
- this._terminal.lines.trimStart(1);
- this._terminal.ybase--;
- this._terminal.ydisp--;
- row--;
- j--;
- }
- this._terminal.lines.splice(row, 0, this._terminal.blankLine(true));
- this._terminal.lines.splice(j, 1);
- }
- this._terminal.updateRange(this._terminal.y);
- this._terminal.updateRange(this._terminal.scrollBottom);
- };
- InputHandler.prototype.deleteLines = function (params) {
- var param, row, j;
- param = params[0];
- if (param < 1) {
- param = 1;
- }
- row = this._terminal.y + this._terminal.ybase;
- j = this._terminal.rows - 1 - this._terminal.scrollBottom;
- j = this._terminal.rows - 1 + this._terminal.ybase - j;
- while (param--) {
- if (this._terminal.lines.length === this._terminal.lines.maxLength) {
- this._terminal.lines.trimStart(1);
- this._terminal.ybase -= 1;
- this._terminal.ydisp -= 1;
- }
- this._terminal.lines.splice(j + 1, 0, this._terminal.blankLine(true));
- this._terminal.lines.splice(row, 1);
- }
- this._terminal.updateRange(this._terminal.y);
- this._terminal.updateRange(this._terminal.scrollBottom);
- };
- InputHandler.prototype.deleteChars = function (params) {
- var param, row, ch;
- param = params[0];
- if (param < 1) {
- param = 1;
- }
- row = this._terminal.y + this._terminal.ybase;
- ch = [this._terminal.eraseAttr(), ' ', 1];
- while (param--) {
- this._terminal.lines.get(row).splice(this._terminal.x, 1);
- this._terminal.lines.get(row).push(ch);
- }
- };
- InputHandler.prototype.scrollUp = function (params) {
- var param = params[0] || 1;
- while (param--) {
- this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 1);
- this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 0, this._terminal.blankLine());
- }
- this._terminal.updateRange(this._terminal.scrollTop);
- this._terminal.updateRange(this._terminal.scrollBottom);
- };
- InputHandler.prototype.scrollDown = function (params) {
- var param = params[0] || 1;
- while (param--) {
- this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollBottom, 1);
- this._terminal.lines.splice(this._terminal.ybase + this._terminal.scrollTop, 0, this._terminal.blankLine());
- }
- this._terminal.updateRange(this._terminal.scrollTop);
- this._terminal.updateRange(this._terminal.scrollBottom);
- };
- InputHandler.prototype.eraseChars = function (params) {
- var param, row, j, ch;
- param = params[0];
- if (param < 1) {
- param = 1;
- }
- row = this._terminal.y + this._terminal.ybase;
- j = this._terminal.x;
- ch = [this._terminal.eraseAttr(), ' ', 1];
- while (param-- && j < this._terminal.cols) {
- this._terminal.lines.get(row)[j++] = ch;
- }
- };
- InputHandler.prototype.cursorBackwardTab = function (params) {
- var param = params[0] || 1;
- while (param--) {
- this._terminal.x = this._terminal.prevStop();
- }
- };
- InputHandler.prototype.charPosAbsolute = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.x = param - 1;
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x = this._terminal.cols - 1;
- }
- };
- InputHandler.prototype.HPositionRelative = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.x += param;
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x = this._terminal.cols - 1;
- }
- };
- InputHandler.prototype.repeatPrecedingCharacter = function (params) {
- var param = params[0] || 1, line = this._terminal.lines.get(this._terminal.ybase + this._terminal.y), ch = line[this._terminal.x - 1] || [this._terminal.defAttr, ' ', 1];
- while (param--) {
- line[this._terminal.x++] = ch;
- }
- };
- InputHandler.prototype.sendDeviceAttributes = function (params) {
- if (params[0] > 0) {
- return;
- }
- if (!this._terminal.prefix) {
- if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {
- this._terminal.send(EscapeSequences_1.C0.ESC + '[?1;2c');
- }
- else if (this._terminal.is('linux')) {
- this._terminal.send(EscapeSequences_1.C0.ESC + '[?6c');
- }
- }
- else if (this._terminal.prefix === '>') {
- if (this._terminal.is('xterm')) {
- this._terminal.send(EscapeSequences_1.C0.ESC + '[>0;276;0c');
- }
- else if (this._terminal.is('rxvt-unicode')) {
- this._terminal.send(EscapeSequences_1.C0.ESC + '[>85;95;0c');
- }
- else if (this._terminal.is('linux')) {
- this._terminal.send(params[0] + 'c');
- }
- else if (this._terminal.is('screen')) {
- this._terminal.send(EscapeSequences_1.C0.ESC + '[>83;40003;0c');
- }
- }
- };
- InputHandler.prototype.linePosAbsolute = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y = param - 1;
- if (this._terminal.y >= this._terminal.rows) {
- this._terminal.y = this._terminal.rows - 1;
- }
- };
- InputHandler.prototype.VPositionRelative = function (params) {
- var param = params[0];
- if (param < 1) {
- param = 1;
- }
- this._terminal.y += param;
- if (this._terminal.y >= this._terminal.rows) {
- this._terminal.y = this._terminal.rows - 1;
- }
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x--;
- }
- };
- InputHandler.prototype.HVPosition = function (params) {
- if (params[0] < 1)
- params[0] = 1;
- if (params[1] < 1)
- params[1] = 1;
- this._terminal.y = params[0] - 1;
- if (this._terminal.y >= this._terminal.rows) {
- this._terminal.y = this._terminal.rows - 1;
- }
- this._terminal.x = params[1] - 1;
- if (this._terminal.x >= this._terminal.cols) {
- this._terminal.x = this._terminal.cols - 1;
- }
- };
- InputHandler.prototype.tabClear = function (params) {
- var param = params[0];
- if (param <= 0) {
- delete this._terminal.tabs[this._terminal.x];
- }
- else if (param === 3) {
- this._terminal.tabs = {};
- }
- };
- InputHandler.prototype.setMode = function (params) {
- if (params.length > 1) {
- for (var i = 0; i < params.length; i++) {
- this.setMode([params[i]]);
- }
- return;
- }
- if (!this._terminal.prefix) {
- switch (params[0]) {
- case 4:
- this._terminal.insertMode = true;
- break;
- case 20:
- break;
- }
- }
- else if (this._terminal.prefix === '?') {
- switch (params[0]) {
- case 1:
- this._terminal.applicationCursor = true;
- break;
- case 2:
- this._terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET);
- this._terminal.setgCharset(1, Charsets_1.DEFAULT_CHARSET);
- this._terminal.setgCharset(2, Charsets_1.DEFAULT_CHARSET);
- this._terminal.setgCharset(3, Charsets_1.DEFAULT_CHARSET);
- break;
- case 3:
- this._terminal.savedCols = this._terminal.cols;
- this._terminal.resize(132, this._terminal.rows);
- break;
- case 6:
- this._terminal.originMode = true;
- break;
- case 7:
- this._terminal.wraparoundMode = true;
- break;
- case 12:
- break;
- case 66:
- this._terminal.log('Serial port requested application keypad.');
- this._terminal.applicationKeypad = true;
- this._terminal.viewport.syncScrollArea();
- break;
- case 9:
- case 1000:
- case 1002:
- case 1003:
- this._terminal.x10Mouse = params[0] === 9;
- this._terminal.vt200Mouse = params[0] === 1000;
- this._terminal.normalMouse = params[0] > 1000;
- this._terminal.mouseEvents = true;
- this._terminal.element.style.cursor = 'default';
- this._terminal.log('Binding to mouse events.');
- break;
- case 1004:
- this._terminal.sendFocus = true;
- break;
- case 1005:
- this._terminal.utfMouse = true;
- break;
- case 1006:
- this._terminal.sgrMouse = true;
- break;
- case 1015:
- this._terminal.urxvtMouse = true;
- break;
- case 25:
- this._terminal.cursorHidden = false;
- break;
- case 1049:
- ;
- case 47:
- case 1047:
- if (!this._terminal.normal) {
- var normal = {
- lines: this._terminal.lines,
- ybase: this._terminal.ybase,
- ydisp: this._terminal.ydisp,
- x: this._terminal.x,
- y: this._terminal.y,
- scrollTop: this._terminal.scrollTop,
- scrollBottom: this._terminal.scrollBottom,
- tabs: this._terminal.tabs
- };
- this._terminal.reset();
- this._terminal.viewport.syncScrollArea();
- this._terminal.normal = normal;
- this._terminal.showCursor();
- }
- break;
- }
- }
- };
- InputHandler.prototype.resetMode = function (params) {
- if (params.length > 1) {
- for (var i = 0; i < params.length; i++) {
- this.resetMode([params[i]]);
- }
- return;
- }
- if (!this._terminal.prefix) {
- switch (params[0]) {
- case 4:
- this._terminal.insertMode = false;
- break;
- case 20:
- break;
- }
- }
- else if (this._terminal.prefix === '?') {
- switch (params[0]) {
- case 1:
- this._terminal.applicationCursor = false;
- break;
- case 3:
- if (this._terminal.cols === 132 && this._terminal.savedCols) {
- this._terminal.resize(this._terminal.savedCols, this._terminal.rows);
- }
- delete this._terminal.savedCols;
- break;
- case 6:
- this._terminal.originMode = false;
- break;
- case 7:
- this._terminal.wraparoundMode = false;
- break;
- case 12:
- break;
- case 66:
- this._terminal.log('Switching back to normal keypad.');
- this._terminal.applicationKeypad = false;
- this._terminal.viewport.syncScrollArea();
- break;
- case 9:
- case 1000:
- case 1002:
- case 1003:
- this._terminal.x10Mouse = false;
- this._terminal.vt200Mouse = false;
- this._terminal.normalMouse = false;
- this._terminal.mouseEvents = false;
- this._terminal.element.style.cursor = '';
- break;
- case 1004:
- this._terminal.sendFocus = false;
- break;
- case 1005:
- this._terminal.utfMouse = false;
- break;
- case 1006:
- this._terminal.sgrMouse = false;
- break;
- case 1015:
- this._terminal.urxvtMouse = false;
- break;
- case 25:
- this._terminal.cursorHidden = true;
- break;
- case 1049:
- ;
- case 47:
- case 1047:
- if (this._terminal.normal) {
- this._terminal.lines = this._terminal.normal.lines;
- this._terminal.ybase = this._terminal.normal.ybase;
- this._terminal.ydisp = this._terminal.normal.ydisp;
- this._terminal.x = this._terminal.normal.x;
- this._terminal.y = this._terminal.normal.y;
- this._terminal.scrollTop = this._terminal.normal.scrollTop;
- this._terminal.scrollBottom = this._terminal.normal.scrollBottom;
- this._terminal.tabs = this._terminal.normal.tabs;
- this._terminal.normal = null;
- this._terminal.refresh(0, this._terminal.rows - 1);
- this._terminal.viewport.syncScrollArea();
- this._terminal.showCursor();
- }
- break;
- }
- }
- };
- InputHandler.prototype.charAttributes = function (params) {
- if (params.length === 1 && params[0] === 0) {
- this._terminal.curAttr = this._terminal.defAttr;
- return;
- }
- var l = params.length, i = 0, flags = this._terminal.curAttr >> 18, fg = (this._terminal.curAttr >> 9) & 0x1ff, bg = this._terminal.curAttr & 0x1ff, p;
- for (; i < l; i++) {
- p = params[i];
- if (p >= 30 && p <= 37) {
- fg = p - 30;
- }
- else if (p >= 40 && p <= 47) {
- bg = p - 40;
- }
- else if (p >= 90 && p <= 97) {
- p += 8;
- fg = p - 90;
- }
- else if (p >= 100 && p <= 107) {
- p += 8;
- bg = p - 100;
- }
- else if (p === 0) {
- flags = this._terminal.defAttr >> 18;
- fg = (this._terminal.defAttr >> 9) & 0x1ff;
- bg = this._terminal.defAttr & 0x1ff;
- }
- else if (p === 1) {
- flags |= 1;
- }
- else if (p === 4) {
- flags |= 2;
- }
- else if (p === 5) {
- flags |= 4;
- }
- else if (p === 7) {
- flags |= 8;
- }
- else if (p === 8) {
- flags |= 16;
- }
- else if (p === 22) {
- flags &= ~1;
- }
- else if (p === 24) {
- flags &= ~2;
- }
- else if (p === 25) {
- flags &= ~4;
- }
- else if (p === 27) {
- flags &= ~8;
- }
- else if (p === 28) {
- flags &= ~16;
- }
- else if (p === 39) {
- fg = (this._terminal.defAttr >> 9) & 0x1ff;
- }
- else if (p === 49) {
- bg = this._terminal.defAttr & 0x1ff;
- }
- else if (p === 38) {
- if (params[i + 1] === 2) {
- i += 2;
- fg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff);
- if (fg === -1)
- fg = 0x1ff;
- i += 2;
- }
- else if (params[i + 1] === 5) {
- i += 2;
- p = params[i] & 0xff;
- fg = p;
- }
- }
- else if (p === 48) {
- if (params[i + 1] === 2) {
- i += 2;
- bg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff);
- if (bg === -1)
- bg = 0x1ff;
- i += 2;
- }
- else if (params[i + 1] === 5) {
- i += 2;
- p = params[i] & 0xff;
- bg = p;
- }
- }
- else if (p === 100) {
- fg = (this._terminal.defAttr >> 9) & 0x1ff;
- bg = this._terminal.defAttr & 0x1ff;
- }
- else {
- this._terminal.error('Unknown SGR attribute: %d.', p);
- }
- }
- this._terminal.curAttr = (flags << 18) | (fg << 9) | bg;
- };
- InputHandler.prototype.deviceStatus = function (params) {
- if (!this._terminal.prefix) {
- switch (params[0]) {
- case 5:
- this._terminal.send(EscapeSequences_1.C0.ESC + '[0n');
- break;
- case 6:
- this._terminal.send(EscapeSequences_1.C0.ESC + '['
- + (this._terminal.y + 1)
- + ';'
- + (this._terminal.x + 1)
- + 'R');
- break;
- }
- }
- else if (this._terminal.prefix === '?') {
- switch (params[0]) {
- case 6:
- this._terminal.send(EscapeSequences_1.C0.ESC + '[?'
- + (this._terminal.y + 1)
- + ';'
- + (this._terminal.x + 1)
- + 'R');
- break;
- case 15:
- break;
- case 25:
- break;
- case 26:
- break;
- case 53:
- break;
- }
- }
- };
- InputHandler.prototype.softReset = function (params) {
- this._terminal.cursorHidden = false;
- this._terminal.insertMode = false;
- this._terminal.originMode = false;
- this._terminal.wraparoundMode = true;
- this._terminal.applicationKeypad = false;
- this._terminal.viewport.syncScrollArea();
- this._terminal.applicationCursor = false;
- this._terminal.scrollTop = 0;
- this._terminal.scrollBottom = this._terminal.rows - 1;
- this._terminal.curAttr = this._terminal.defAttr;
- this._terminal.x = this._terminal.y = 0;
- this._terminal.charset = null;
- this._terminal.glevel = 0;
- this._terminal.charsets = [null];
- };
- InputHandler.prototype.setCursorStyle = function (params) {
- var param = params[0] < 1 ? 1 : params[0];
- switch (param) {
- case 1:
- case 2:
- this._terminal.setOption('cursorStyle', 'block');
- break;
- case 3:
- case 4:
- this._terminal.setOption('cursorStyle', 'underline');
- break;
- case 5:
- case 6:
- this._terminal.setOption('cursorStyle', 'bar');
- break;
- }
- var isBlinking = param % 2 === 1;
- this._terminal.setOption('cursorBlink', isBlinking);
- };
- InputHandler.prototype.setScrollRegion = function (params) {
- if (this._terminal.prefix)
- return;
- this._terminal.scrollTop = (params[0] || 1) - 1;
- this._terminal.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1;
- this._terminal.x = 0;
- this._terminal.y = 0;
- };
- InputHandler.prototype.saveCursor = function (params) {
- this._terminal.savedX = this._terminal.x;
- this._terminal.savedY = this._terminal.y;
- };
- InputHandler.prototype.restoreCursor = function (params) {
- this._terminal.x = this._terminal.savedX || 0;
- this._terminal.y = this._terminal.savedY || 0;
- };
- return InputHandler;
-}());
-exports.InputHandler = InputHandler;
-var wcwidth = (function (opts) {
- var COMBINING = [
- [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],
- [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],
- [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],
- [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],
- [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],
- [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],
- [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],
- [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],
- [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],
- [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],
- [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],
- [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],
- [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],
- [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],
- [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],
- [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],
- [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],
- [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],
- [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],
- [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],
- [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],
- [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],
- [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],
- [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],
- [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],
- [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],
- [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],
- [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],
- [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],
- [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],
- [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],
- [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],
- [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],
- [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],
- [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],
- [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],
- [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],
- [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],
- [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],
- [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],
- [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],
- [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],
- [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB],
- [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],
- [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],
- [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],
- [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],
- [0xE0100, 0xE01EF]
- ];
- function bisearch(ucs) {
- var min = 0;
- var max = COMBINING.length - 1;
- var mid;
- if (ucs < COMBINING[0][0] || ucs > COMBINING[max][1])
- return false;
- while (max >= min) {
- mid = Math.floor((min + max) / 2);
- if (ucs > COMBINING[mid][1])
- min = mid + 1;
- else if (ucs < COMBINING[mid][0])
- max = mid - 1;
- else
- return true;
- }
- return false;
- }
- function wcwidth(ucs) {
- if (ucs === 0)
- return opts.nul;
- if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
- return opts.control;
- if (bisearch(ucs))
- return 0;
- if (isWide(ucs)) {
- return 2;
- }
- return 1;
- }
- function isWide(ucs) {
- return (ucs >= 0x1100 && (ucs <= 0x115f ||
- ucs === 0x2329 ||
- ucs === 0x232a ||
- (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) ||
- (ucs >= 0xac00 && ucs <= 0xd7a3) ||
- (ucs >= 0xf900 && ucs <= 0xfaff) ||
- (ucs >= 0xfe10 && ucs <= 0xfe19) ||
- (ucs >= 0xfe30 && ucs <= 0xfe6f) ||
- (ucs >= 0xff00 && ucs <= 0xff60) ||
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2fffd) ||
- (ucs >= 0x30000 && ucs <= 0x3fffd)));
- }
- return wcwidth;
-})({ nul: 0, control: 0 });
-
-
-
-},{"./Charsets":1,"./EscapeSequences":3}],6:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var INVALID_LINK_CLASS = 'xterm-invalid-link';
-var protocolClause = '(https?:\\/\\/)';
-var domainCharacterSet = '[\\da-z\\.-]+';
-var negatedDomainCharacterSet = '[^\\da-z\\.-]+';
-var domainBodyClause = '(' + domainCharacterSet + ')';
-var tldClause = '([a-z\\.]{2,6})';
-var ipClause = '((\\d{1,3}\\.){3}\\d{1,3})';
-var localHostClause = '(localhost)';
-var portClause = '(:\\d{1,5})';
-var hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?';
-var pathClause = '(\\/[\\/\\w\\.\\-%~]*)*';
-var queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*';
-var queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?';
-var hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?';
-var negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+';
-var bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause;
-var start = '(?:^|' + negatedDomainCharacterSet + ')(';
-var end = ')($|' + negatedPathCharacterSet + ')';
-var strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end);
-var HYPERTEXT_LINK_MATCHER_ID = 0;
-var Linkifier = (function () {
- function Linkifier() {
- this._nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID;
- this._rowTimeoutIds = [];
- this._linkMatchers = [];
- this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 });
- }
- Linkifier.prototype.attachToDom = function (document, rows) {
- this._document = document;
- this._rows = rows;
- };
- Linkifier.prototype.linkifyRow = function (rowIndex) {
- if (!this._document) {
- return;
- }
- var timeoutId = this._rowTimeoutIds[rowIndex];
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
- this._rowTimeoutIds[rowIndex] = setTimeout(this._linkifyRow.bind(this, rowIndex), Linkifier.TIME_BEFORE_LINKIFY);
- };
- Linkifier.prototype.setHypertextLinkHandler = function (handler) {
- this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler;
- };
- Linkifier.prototype.setHypertextValidationCallback = function (callback) {
- this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback;
- };
- Linkifier.prototype.registerLinkMatcher = function (regex, handler, options) {
- if (options === void 0) { options = {}; }
- if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) {
- throw new Error('handler must be defined');
- }
- var matcher = {
- id: this._nextLinkMatcherId++,
- regex: regex,
- handler: handler,
- matchIndex: options.matchIndex,
- validationCallback: options.validationCallback,
- priority: options.priority || 0
- };
- this._addLinkMatcherToList(matcher);
- return matcher.id;
- };
- Linkifier.prototype._addLinkMatcherToList = function (matcher) {
- if (this._linkMatchers.length === 0) {
- this._linkMatchers.push(matcher);
- return;
- }
- for (var i = this._linkMatchers.length - 1; i >= 0; i--) {
- if (matcher.priority <= this._linkMatchers[i].priority) {
- this._linkMatchers.splice(i + 1, 0, matcher);
- return;
- }
- }
- this._linkMatchers.splice(0, 0, matcher);
- };
- Linkifier.prototype.deregisterLinkMatcher = function (matcherId) {
- for (var i = 1; i < this._linkMatchers.length; i++) {
- if (this._linkMatchers[i].id === matcherId) {
- this._linkMatchers.splice(i, 1);
- return true;
- }
- }
- return false;
- };
- Linkifier.prototype._linkifyRow = function (rowIndex) {
- var row = this._rows[rowIndex];
- if (!row) {
- return;
- }
- var text = row.textContent;
- for (var i = 0; i < this._linkMatchers.length; i++) {
- var matcher = this._linkMatchers[i];
- var linkElements = this._doLinkifyRow(row, matcher);
- if (linkElements.length > 0) {
- if (matcher.validationCallback) {
- var _loop_1 = function (j) {
- var element = linkElements[j];
- matcher.validationCallback(element.textContent, element, function (isValid) {
- if (!isValid) {
- element.classList.add(INVALID_LINK_CLASS);
- }
- });
- };
- for (var j = 0; j < linkElements.length; j++) {
- _loop_1(j);
- }
- }
- return;
- }
- }
- };
- Linkifier.prototype._doLinkifyRow = function (row, matcher) {
- var result = [];
- var isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID;
- var nodes = row.childNodes;
- var match = row.textContent.match(matcher.regex);
- if (!match || match.length === 0) {
- return result;
- }
- var uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex];
- var rowStartIndex = match.index + uri.length;
- for (var i = 0; i < nodes.length; i++) {
- var node = nodes[i];
- var searchIndex = node.textContent.indexOf(uri);
- if (searchIndex >= 0) {
- var linkElement = this._createAnchorElement(uri, matcher.handler, isHttpLinkMatcher);
- if (node.textContent.length === uri.length) {
- if (node.nodeType === 3) {
- this._replaceNode(node, linkElement);
- }
- else {
- var element = node;
- if (element.nodeName === 'A') {
- return result;
- }
- element.innerHTML = '';
- element.appendChild(linkElement);
- }
- }
- else {
- var nodesAdded = this._replaceNodeSubstringWithNode(node, linkElement, uri, searchIndex);
- i += nodesAdded;
- }
- result.push(linkElement);
- match = row.textContent.substring(rowStartIndex).match(matcher.regex);
- if (!match || match.length === 0) {
- return result;
- }
- uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex];
- rowStartIndex += match.index + uri.length;
- }
- }
- return result;
- };
- Linkifier.prototype._createAnchorElement = function (uri, handler, isHypertextLinkHandler) {
- var element = this._document.createElement('a');
- element.textContent = uri;
- element.draggable = false;
- if (isHypertextLinkHandler) {
- element.href = uri;
- element.target = '_blank';
- element.addEventListener('click', function (event) {
- if (handler) {
- return handler(event, uri);
- }
- });
- }
- else {
- element.addEventListener('click', function (event) {
- if (element.classList.contains(INVALID_LINK_CLASS)) {
- return;
- }
- return handler(event, uri);
- });
- }
- return element;
- };
- Linkifier.prototype._replaceNode = function (oldNode) {
- var newNodes = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- newNodes[_i - 1] = arguments[_i];
- }
- var parent = oldNode.parentNode;
- for (var i = 0; i < newNodes.length; i++) {
- parent.insertBefore(newNodes[i], oldNode);
- }
- parent.removeChild(oldNode);
- };
- Linkifier.prototype._replaceNodeSubstringWithNode = function (targetNode, newNode, substring, substringIndex) {
- var node = targetNode;
- if (node.nodeType !== 3) {
- node = node.childNodes[0];
- }
- if (node.childNodes.length === 0 && node.nodeType !== 3) {
- throw new Error('targetNode must be a text node or only contain a single text node');
- }
- var fullText = node.textContent;
- if (substringIndex === 0) {
- var rightText_1 = fullText.substring(substring.length);
- var rightTextNode_1 = this._document.createTextNode(rightText_1);
- this._replaceNode(node, newNode, rightTextNode_1);
- return 0;
- }
- if (substringIndex === targetNode.textContent.length - substring.length) {
- var leftText_1 = fullText.substring(0, substringIndex);
- var leftTextNode_1 = this._document.createTextNode(leftText_1);
- this._replaceNode(node, leftTextNode_1, newNode);
- return 0;
- }
- var leftText = fullText.substring(0, substringIndex);
- var leftTextNode = this._document.createTextNode(leftText);
- var rightText = fullText.substring(substringIndex + substring.length);
- var rightTextNode = this._document.createTextNode(rightText);
- this._replaceNode(node, leftTextNode, newNode, rightTextNode);
- return 1;
- };
- return Linkifier;
-}());
-Linkifier.TIME_BEFORE_LINKIFY = 200;
-exports.Linkifier = Linkifier;
-
-
-
-},{}],7:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var EscapeSequences_1 = require("./EscapeSequences");
-var Charsets_1 = require("./Charsets");
-var normalStateHandler = {};
-normalStateHandler[EscapeSequences_1.C0.BEL] = function (parser, handler) { return handler.bell(); };
-normalStateHandler[EscapeSequences_1.C0.LF] = function (parser, handler) { return handler.lineFeed(); };
-normalStateHandler[EscapeSequences_1.C0.VT] = normalStateHandler[EscapeSequences_1.C0.LF];
-normalStateHandler[EscapeSequences_1.C0.FF] = normalStateHandler[EscapeSequences_1.C0.LF];
-normalStateHandler[EscapeSequences_1.C0.CR] = function (parser, handler) { return handler.carriageReturn(); };
-normalStateHandler[EscapeSequences_1.C0.BS] = function (parser, handler) { return handler.backspace(); };
-normalStateHandler[EscapeSequences_1.C0.HT] = function (parser, handler) { return handler.tab(); };
-normalStateHandler[EscapeSequences_1.C0.SO] = function (parser, handler) { return handler.shiftOut(); };
-normalStateHandler[EscapeSequences_1.C0.SI] = function (parser, handler) { return handler.shiftIn(); };
-normalStateHandler[EscapeSequences_1.C0.ESC] = function (parser, handler) { return parser.setState(ParserState.ESCAPED); };
-var escapedStateHandler = {};
-escapedStateHandler['['] = function (parser, terminal) {
- terminal.params = [];
- terminal.currentParam = 0;
- parser.setState(ParserState.CSI_PARAM);
-};
-escapedStateHandler[']'] = function (parser, terminal) {
- terminal.params = [];
- terminal.currentParam = 0;
- parser.setState(ParserState.OSC);
-};
-escapedStateHandler['P'] = function (parser, terminal) {
- terminal.params = [];
- terminal.currentParam = 0;
- parser.setState(ParserState.DCS);
-};
-escapedStateHandler['_'] = function (parser, terminal) {
- parser.setState(ParserState.IGNORE);
-};
-escapedStateHandler['^'] = function (parser, terminal) {
- parser.setState(ParserState.IGNORE);
-};
-escapedStateHandler['c'] = function (parser, terminal) {
- terminal.reset();
-};
-escapedStateHandler['E'] = function (parser, terminal) {
- terminal.x = 0;
- terminal.index();
- parser.setState(ParserState.NORMAL);
-};
-escapedStateHandler['D'] = function (parser, terminal) {
- terminal.index();
- parser.setState(ParserState.NORMAL);
-};
-escapedStateHandler['M'] = function (parser, terminal) {
- terminal.reverseIndex();
- parser.setState(ParserState.NORMAL);
-};
-escapedStateHandler['%'] = function (parser, terminal) {
- terminal.setgLevel(0);
- terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET);
- parser.setState(ParserState.NORMAL);
- parser.skipNextChar();
-};
-escapedStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); };
-var csiParamStateHandler = {};
-csiParamStateHandler['?'] = function (parser) { return parser.setPrefix('?'); };
-csiParamStateHandler['>'] = function (parser) { return parser.setPrefix('>'); };
-csiParamStateHandler['!'] = function (parser) { return parser.setPrefix('!'); };
-csiParamStateHandler['0'] = function (parser) { return parser.setParam(parser.getParam() * 10); };
-csiParamStateHandler['1'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 1); };
-csiParamStateHandler['2'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 2); };
-csiParamStateHandler['3'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 3); };
-csiParamStateHandler['4'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 4); };
-csiParamStateHandler['5'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 5); };
-csiParamStateHandler['6'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 6); };
-csiParamStateHandler['7'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 7); };
-csiParamStateHandler['8'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 8); };
-csiParamStateHandler['9'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 9); };
-csiParamStateHandler['$'] = function (parser) { return parser.setPostfix('$'); };
-csiParamStateHandler['"'] = function (parser) { return parser.setPostfix('"'); };
-csiParamStateHandler[' '] = function (parser) { return parser.setPostfix(' '); };
-csiParamStateHandler['\''] = function (parser) { return parser.setPostfix('\''); };
-csiParamStateHandler[';'] = function (parser) { return parser.finalizeParam(); };
-csiParamStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); };
-var csiStateHandler = {};
-csiStateHandler['@'] = function (handler, params, prefix) { return handler.insertChars(params); };
-csiStateHandler['A'] = function (handler, params, prefix) { return handler.cursorUp(params); };
-csiStateHandler['B'] = function (handler, params, prefix) { return handler.cursorDown(params); };
-csiStateHandler['C'] = function (handler, params, prefix) { return handler.cursorForward(params); };
-csiStateHandler['D'] = function (handler, params, prefix) { return handler.cursorBackward(params); };
-csiStateHandler['E'] = function (handler, params, prefix) { return handler.cursorNextLine(params); };
-csiStateHandler['F'] = function (handler, params, prefix) { return handler.cursorPrecedingLine(params); };
-csiStateHandler['G'] = function (handler, params, prefix) { return handler.cursorCharAbsolute(params); };
-csiStateHandler['H'] = function (handler, params, prefix) { return handler.cursorPosition(params); };
-csiStateHandler['I'] = function (handler, params, prefix) { return handler.cursorForwardTab(params); };
-csiStateHandler['J'] = function (handler, params, prefix) { return handler.eraseInDisplay(params); };
-csiStateHandler['K'] = function (handler, params, prefix) { return handler.eraseInLine(params); };
-csiStateHandler['L'] = function (handler, params, prefix) { return handler.insertLines(params); };
-csiStateHandler['M'] = function (handler, params, prefix) { return handler.deleteLines(params); };
-csiStateHandler['P'] = function (handler, params, prefix) { return handler.deleteChars(params); };
-csiStateHandler['S'] = function (handler, params, prefix) { return handler.scrollUp(params); };
-csiStateHandler['T'] = function (handler, params, prefix) {
- if (params.length < 2 && !prefix) {
- handler.scrollDown(params);
- }
-};
-csiStateHandler['X'] = function (handler, params, prefix) { return handler.eraseChars(params); };
-csiStateHandler['Z'] = function (handler, params, prefix) { return handler.cursorBackwardTab(params); };
-csiStateHandler['`'] = function (handler, params, prefix) { return handler.charPosAbsolute(params); };
-csiStateHandler['a'] = function (handler, params, prefix) { return handler.HPositionRelative(params); };
-csiStateHandler['b'] = function (handler, params, prefix) { return handler.repeatPrecedingCharacter(params); };
-csiStateHandler['c'] = function (handler, params, prefix) { return handler.sendDeviceAttributes(params); };
-csiStateHandler['d'] = function (handler, params, prefix) { return handler.linePosAbsolute(params); };
-csiStateHandler['e'] = function (handler, params, prefix) { return handler.VPositionRelative(params); };
-csiStateHandler['f'] = function (handler, params, prefix) { return handler.HVPosition(params); };
-csiStateHandler['g'] = function (handler, params, prefix) { return handler.tabClear(params); };
-csiStateHandler['h'] = function (handler, params, prefix) { return handler.setMode(params); };
-csiStateHandler['l'] = function (handler, params, prefix) { return handler.resetMode(params); };
-csiStateHandler['m'] = function (handler, params, prefix) { return handler.charAttributes(params); };
-csiStateHandler['n'] = function (handler, params, prefix) { return handler.deviceStatus(params); };
-csiStateHandler['p'] = function (handler, params, prefix) {
- switch (prefix) {
- case '!':
- handler.softReset(params);
- break;
- }
-};
-csiStateHandler['q'] = function (handler, params, prefix, postfix) {
- if (postfix === ' ') {
- handler.setCursorStyle(params);
- }
-};
-csiStateHandler['r'] = function (handler, params) { return handler.setScrollRegion(params); };
-csiStateHandler['s'] = function (handler, params) { return handler.saveCursor(params); };
-csiStateHandler['u'] = function (handler, params) { return handler.restoreCursor(params); };
-csiStateHandler[EscapeSequences_1.C0.CAN] = function (handler, params, prefix, postfix, parser) { return parser.setState(ParserState.NORMAL); };
-var ParserState;
-(function (ParserState) {
- ParserState[ParserState["NORMAL"] = 0] = "NORMAL";
- ParserState[ParserState["ESCAPED"] = 1] = "ESCAPED";
- ParserState[ParserState["CSI_PARAM"] = 2] = "CSI_PARAM";
- ParserState[ParserState["CSI"] = 3] = "CSI";
- ParserState[ParserState["OSC"] = 4] = "OSC";
- ParserState[ParserState["CHARSET"] = 5] = "CHARSET";
- ParserState[ParserState["DCS"] = 6] = "DCS";
- ParserState[ParserState["IGNORE"] = 7] = "IGNORE";
-})(ParserState || (ParserState = {}));
-var Parser = (function () {
- function Parser(_inputHandler, _terminal) {
- this._inputHandler = _inputHandler;
- this._terminal = _terminal;
- this._state = ParserState.NORMAL;
- }
- Parser.prototype.parse = function (data) {
- var l = data.length, j, cs, ch, code, low;
- this._position = 0;
- if (this._terminal.surrogate_high) {
- data = this._terminal.surrogate_high + data;
- this._terminal.surrogate_high = '';
- }
- for (; this._position < l; this._position++) {
- ch = data[this._position];
- code = data.charCodeAt(this._position);
- if (0xD800 <= code && code <= 0xDBFF) {
- low = data.charCodeAt(this._position + 1);
- if (isNaN(low)) {
- this._terminal.surrogate_high = ch;
- continue;
- }
- code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
- ch += data.charAt(this._position + 1);
- }
- if (0xDC00 <= code && code <= 0xDFFF)
- continue;
- switch (this._state) {
- case ParserState.NORMAL:
- if (ch in normalStateHandler) {
- normalStateHandler[ch](this, this._inputHandler);
- }
- else {
- this._inputHandler.addChar(ch, code);
- }
- break;
- case ParserState.ESCAPED:
- if (ch in escapedStateHandler) {
- escapedStateHandler[ch](this, this._terminal);
- break;
- }
- switch (ch) {
- case '(':
- case ')':
- case '*':
- case '+':
- case '-':
- case '.':
- switch (ch) {
- case '(':
- this._terminal.gcharset = 0;
- break;
- case ')':
- this._terminal.gcharset = 1;
- break;
- case '*':
- this._terminal.gcharset = 2;
- break;
- case '+':
- this._terminal.gcharset = 3;
- break;
- case '-':
- this._terminal.gcharset = 1;
- break;
- case '.':
- this._terminal.gcharset = 2;
- break;
- }
- this._state = ParserState.CHARSET;
- break;
- case '/':
- this._terminal.gcharset = 3;
- this._state = ParserState.CHARSET;
- this._position--;
- break;
- case 'N':
- break;
- case 'O':
- break;
- case 'n':
- this._terminal.setgLevel(2);
- break;
- case 'o':
- this._terminal.setgLevel(3);
- break;
- case '|':
- this._terminal.setgLevel(3);
- break;
- case '}':
- this._terminal.setgLevel(2);
- break;
- case '~':
- this._terminal.setgLevel(1);
- break;
- case '7':
- this._inputHandler.saveCursor();
- this._state = ParserState.NORMAL;
- break;
- case '8':
- this._inputHandler.restoreCursor();
- this._state = ParserState.NORMAL;
- break;
- case '#':
- this._state = ParserState.NORMAL;
- this._position++;
- break;
- case 'H':
- this._terminal.tabSet();
- this._state = ParserState.NORMAL;
- break;
- case '=':
- this._terminal.log('Serial port requested application keypad.');
- this._terminal.applicationKeypad = true;
- this._terminal.viewport.syncScrollArea();
- this._state = ParserState.NORMAL;
- break;
- case '>':
- this._terminal.log('Switching back to normal keypad.');
- this._terminal.applicationKeypad = false;
- this._terminal.viewport.syncScrollArea();
- this._state = ParserState.NORMAL;
- break;
- default:
- this._state = ParserState.NORMAL;
- this._terminal.error('Unknown ESC control: %s.', ch);
- break;
- }
- break;
- case ParserState.CHARSET:
- if (ch in Charsets_1.CHARSETS) {
- cs = Charsets_1.CHARSETS[ch];
- if (ch === '/') {
- this.skipNextChar();
- }
- }
- else {
- cs = Charsets_1.DEFAULT_CHARSET;
- }
- this._terminal.setgCharset(this._terminal.gcharset, cs);
- this._terminal.gcharset = null;
- this._state = ParserState.NORMAL;
- break;
- case ParserState.OSC:
- if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
- if (ch === EscapeSequences_1.C0.ESC)
- this._position++;
- this._terminal.params.push(this._terminal.currentParam);
- switch (this._terminal.params[0]) {
- case 0:
- case 1:
- case 2:
- if (this._terminal.params[1]) {
- this._terminal.title = this._terminal.params[1];
- this._terminal.handleTitle(this._terminal.title);
- }
- break;
- case 3:
- break;
- case 4:
- case 5:
- break;
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- break;
- case 46:
- break;
- case 50:
- break;
- case 51:
- break;
- case 52:
- break;
- case 104:
- case 105:
- case 110:
- case 111:
- case 112:
- case 113:
- case 114:
- case 115:
- case 116:
- case 117:
- case 118:
- break;
- }
- this._terminal.params = [];
- this._terminal.currentParam = 0;
- this._state = ParserState.NORMAL;
- }
- else {
- if (!this._terminal.params.length) {
- if (ch >= '0' && ch <= '9') {
- this._terminal.currentParam =
- this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48;
- }
- else if (ch === ';') {
- this._terminal.params.push(this._terminal.currentParam);
- this._terminal.currentParam = '';
- }
- }
- else {
- this._terminal.currentParam += ch;
- }
- }
- break;
- case ParserState.CSI_PARAM:
- if (ch in csiParamStateHandler) {
- csiParamStateHandler[ch](this);
- break;
- }
- this.finalizeParam();
- this._state = ParserState.CSI;
- case ParserState.CSI:
- if (ch in csiStateHandler) {
- csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this);
- }
- else {
- this._terminal.error('Unknown CSI code: %s.', ch);
- }
- this._state = ParserState.NORMAL;
- this._terminal.prefix = '';
- this._terminal.postfix = '';
- break;
- case ParserState.DCS:
- if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
- if (ch === EscapeSequences_1.C0.ESC)
- this._position++;
- var pt = void 0;
- var valid = void 0;
- switch (this._terminal.prefix) {
- case '':
- break;
- case '$q':
- pt = this._terminal.currentParam;
- valid = false;
- switch (pt) {
- case '"q':
- pt = '0"q';
- break;
- case '"p':
- pt = '61"p';
- break;
- case 'r':
- pt = ''
- + (this._terminal.scrollTop + 1)
- + ';'
- + (this._terminal.scrollBottom + 1)
- + 'r';
- break;
- case 'm':
- pt = '0m';
- break;
- default:
- this._terminal.error('Unknown DCS Pt: %s.', pt);
- pt = '';
- break;
- }
- this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '$r' + pt + EscapeSequences_1.C0.ESC + '\\');
- break;
- case '+p':
- break;
- case '+q':
- pt = this._terminal.currentParam;
- valid = false;
- this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '+r' + pt + EscapeSequences_1.C0.ESC + '\\');
- break;
- default:
- this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix);
- break;
- }
- this._terminal.currentParam = 0;
- this._terminal.prefix = '';
- this._state = ParserState.NORMAL;
- }
- else if (!this._terminal.currentParam) {
- if (!this._terminal.prefix && ch !== '$' && ch !== '+') {
- this._terminal.currentParam = ch;
- }
- else if (this._terminal.prefix.length === 2) {
- this._terminal.currentParam = ch;
- }
- else {
- this._terminal.prefix += ch;
- }
- }
- else {
- this._terminal.currentParam += ch;
- }
- break;
- case ParserState.IGNORE:
- if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) {
- if (ch === EscapeSequences_1.C0.ESC)
- this._position++;
- this._state = ParserState.NORMAL;
- }
- break;
- }
- }
- return this._state;
- };
- Parser.prototype.setState = function (state) {
- this._state = state;
- };
- Parser.prototype.setPrefix = function (prefix) {
- this._terminal.prefix = prefix;
- };
- Parser.prototype.setPostfix = function (postfix) {
- this._terminal.postfix = postfix;
- };
- Parser.prototype.setParam = function (param) {
- this._terminal.currentParam = param;
- };
- Parser.prototype.getParam = function () {
- return this._terminal.currentParam;
- };
- Parser.prototype.finalizeParam = function () {
- this._terminal.params.push(this._terminal.currentParam);
- this._terminal.currentParam = 0;
- };
- Parser.prototype.skipNextChar = function () {
- this._position++;
- };
- return Parser;
-}());
-exports.Parser = Parser;
-
-
-
-},{"./Charsets":1,"./EscapeSequences":3}],8:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var DomElementObjectPool_1 = require("./utils/DomElementObjectPool");
-var MAX_REFRESH_FRAME_SKIP = 5;
-var FLAGS;
-(function (FLAGS) {
- FLAGS[FLAGS["BOLD"] = 1] = "BOLD";
- FLAGS[FLAGS["UNDERLINE"] = 2] = "UNDERLINE";
- FLAGS[FLAGS["BLINK"] = 4] = "BLINK";
- FLAGS[FLAGS["INVERSE"] = 8] = "INVERSE";
- FLAGS[FLAGS["INVISIBLE"] = 16] = "INVISIBLE";
-})(FLAGS || (FLAGS = {}));
-;
-var brokenBold = null;
-var Renderer = (function () {
- function Renderer(_terminal) {
- this._terminal = _terminal;
- this._refreshRowsQueue = [];
- this._refreshFramesSkipped = 0;
- this._refreshAnimationFrame = null;
- this._spanElementObjectPool = new DomElementObjectPool_1.DomElementObjectPool('span');
- if (brokenBold === null) {
- brokenBold = checkBoldBroken(this._terminal.element);
- }
- this._spanElementObjectPool = new DomElementObjectPool_1.DomElementObjectPool('span');
- }
- Renderer.prototype.queueRefresh = function (start, end) {
- this._refreshRowsQueue.push({ start: start, end: end });
- if (!this._refreshAnimationFrame) {
- this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this));
- }
- };
- Renderer.prototype._refreshLoop = function () {
- var skipFrame = this._terminal.writeBuffer.length > 0 && this._refreshFramesSkipped++ <= MAX_REFRESH_FRAME_SKIP;
- if (skipFrame) {
- this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this));
- return;
- }
- this._refreshFramesSkipped = 0;
- var start;
- var end;
- if (this._refreshRowsQueue.length > 4) {
- start = 0;
- end = this._terminal.rows - 1;
- }
- else {
- start = this._refreshRowsQueue[0].start;
- end = this._refreshRowsQueue[0].end;
- for (var i = 1; i < this._refreshRowsQueue.length; i++) {
- if (this._refreshRowsQueue[i].start < start) {
- start = this._refreshRowsQueue[i].start;
- }
- if (this._refreshRowsQueue[i].end > end) {
- end = this._refreshRowsQueue[i].end;
- }
- }
- }
- this._refreshRowsQueue = [];
- this._refreshAnimationFrame = null;
- this._refresh(start, end);
- };
- Renderer.prototype._refresh = function (start, end) {
- var parent;
- if (end - start >= this._terminal.rows / 2) {
- parent = this._terminal.element.parentNode;
- if (parent) {
- this._terminal.element.removeChild(this._terminal.rowContainer);
- }
- }
- var width = this._terminal.cols;
- var y = start;
- if (end >= this._terminal.rows) {
- this._terminal.log('`end` is too large. Most likely a bad CSR.');
- end = this._terminal.rows - 1;
- }
- for (; y <= end; y++) {
- var row = y + this._terminal.ydisp;
- var line = this._terminal.lines.get(row);
- var x = void 0;
- if (this._terminal.y === y - (this._terminal.ybase - this._terminal.ydisp) &&
- this._terminal.cursorState &&
- !this._terminal.cursorHidden) {
- x = this._terminal.x;
- }
- else {
- x = -1;
- }
- var attr = this._terminal.defAttr;
- var documentFragment = document.createDocumentFragment();
- var innerHTML = '';
- var currentElement = void 0;
- while (this._terminal.children[y].children.length) {
- var child = this._terminal.children[y].children[0];
- this._terminal.children[y].removeChild(child);
- this._spanElementObjectPool.release(child);
- }
- for (var i = 0; i < width; i++) {
- var data = line[i][0];
- var ch = line[i][1];
- var ch_width = line[i][2];
- if (!ch_width) {
- continue;
- }
- if (i === x) {
- data = -1;
- }
- if (data !== attr) {
- if (attr !== this._terminal.defAttr) {
- if (innerHTML) {
- currentElement.innerHTML = innerHTML;
- innerHTML = '';
- }
- documentFragment.appendChild(currentElement);
- currentElement = null;
- }
- if (data !== this._terminal.defAttr) {
- if (innerHTML && !currentElement) {
- currentElement = this._spanElementObjectPool.acquire();
- }
- if (currentElement) {
- if (innerHTML) {
- currentElement.innerHTML = innerHTML;
- innerHTML = '';
- }
- documentFragment.appendChild(currentElement);
- }
- currentElement = this._spanElementObjectPool.acquire();
- if (data === -1) {
- currentElement.classList.add('reverse-video', 'terminal-cursor');
- }
- else {
- var bg = data & 0x1ff;
- var fg = (data >> 9) & 0x1ff;
- var flags = data >> 18;
- if (flags & FLAGS.BOLD) {
- if (!brokenBold) {
- currentElement.classList.add('xterm-bold');
- }
- if (fg < 8) {
- fg += 8;
- }
- }
- if (flags & FLAGS.UNDERLINE) {
- currentElement.classList.add('xterm-underline');
- }
- if (flags & FLAGS.BLINK) {
- currentElement.classList.add('xterm-blink');
- }
- if (flags & FLAGS.INVERSE) {
- var temp = bg;
- bg = fg;
- fg = temp;
- if ((flags & 1) && fg < 8) {
- fg += 8;
- }
- }
- if (flags & FLAGS.INVISIBLE) {
- currentElement.classList.add('xterm-hidden');
- }
- if (flags & FLAGS.INVERSE) {
- if (bg === 257) {
- bg = 15;
- }
- if (fg === 256) {
- fg = 0;
- }
- }
- if (bg < 256) {
- currentElement.classList.add("xterm-bg-color-" + bg);
- }
- if (fg < 256) {
- currentElement.classList.add("xterm-color-" + fg);
- }
- }
- }
- }
- if (ch_width === 2) {
- innerHTML += "<span class=\"xterm-wide-char\">" + ch + "</span>";
- }
- else if (ch.charCodeAt(0) > 255) {
- innerHTML += "<span class=\"xterm-normal-char\">" + ch + "</span>";
- }
- else {
- switch (ch) {
- case '&':
- innerHTML += '&amp;';
- break;
- case '<':
- innerHTML += '&lt;';
- break;
- case '>':
- innerHTML += '&gt;';
- break;
- default:
- if (ch <= ' ') {
- innerHTML += '&nbsp;';
- }
- else {
- innerHTML += ch;
- }
- break;
- }
- }
- attr = data;
- }
- if (innerHTML && !currentElement) {
- currentElement = this._spanElementObjectPool.acquire();
- }
- if (currentElement) {
- if (innerHTML) {
- currentElement.innerHTML = innerHTML;
- innerHTML = '';
- }
- documentFragment.appendChild(currentElement);
- currentElement = null;
- }
- this._terminal.children[y].appendChild(documentFragment);
- }
- if (parent) {
- this._terminal.element.appendChild(this._terminal.rowContainer);
- }
- this._terminal.emit('refresh', { element: this._terminal.element, start: start, end: end });
- };
- ;
- return Renderer;
-}());
-exports.Renderer = Renderer;
-function checkBoldBroken(terminal) {
- var document = terminal.ownerDocument;
- var el = document.createElement('span');
- el.innerHTML = 'hello world';
- terminal.appendChild(el);
- var w1 = el.offsetWidth;
- var h1 = el.offsetHeight;
- el.style.fontWeight = 'bold';
- var w2 = el.offsetWidth;
- var h2 = el.offsetHeight;
- terminal.removeChild(el);
- return w1 !== w2 || h1 !== h2;
-}
-
-
-
-},{"./utils/DomElementObjectPool":14}],9:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Viewport = (function () {
- function Viewport(terminal, viewportElement, scrollArea, charMeasure) {
- var _this = this;
- this.terminal = terminal;
- this.viewportElement = viewportElement;
- this.scrollArea = scrollArea;
- this.charMeasure = charMeasure;
- this.currentRowHeight = 0;
- this.lastRecordedBufferLength = 0;
- this.lastRecordedViewportHeight = 0;
- this.terminal.on('scroll', this.syncScrollArea.bind(this));
- this.terminal.on('resize', this.syncScrollArea.bind(this));
- this.viewportElement.addEventListener('scroll', this.onScroll.bind(this));
- setTimeout(function () { return _this.syncScrollArea(); }, 0);
- }
- Viewport.prototype.refresh = function () {
- if (this.charMeasure.height > 0) {
- var rowHeightChanged = this.charMeasure.height !== this.currentRowHeight;
- if (rowHeightChanged) {
- this.currentRowHeight = this.charMeasure.height;
- this.viewportElement.style.lineHeight = this.charMeasure.height + 'px';
- this.terminal.rowContainer.style.lineHeight = this.charMeasure.height + 'px';
- }
- var viewportHeightChanged = this.lastRecordedViewportHeight !== this.terminal.rows;
- if (rowHeightChanged || viewportHeightChanged) {
- this.lastRecordedViewportHeight = this.terminal.rows;
- this.viewportElement.style.height = this.charMeasure.height * this.terminal.rows + 'px';
- }
- this.scrollArea.style.height = (this.charMeasure.height * this.lastRecordedBufferLength) + 'px';
- }
- };
- Viewport.prototype.syncScrollArea = function () {
- if (this.lastRecordedBufferLength !== this.terminal.lines.length) {
- this.lastRecordedBufferLength = this.terminal.lines.length;
- this.refresh();
- }
- else if (this.lastRecordedViewportHeight !== this.terminal.rows) {
- this.refresh();
- }
- else {
- if (this.charMeasure.height !== this.currentRowHeight) {
- this.refresh();
- }
- }
- var scrollTop = this.terminal.ydisp * this.currentRowHeight;
- if (this.viewportElement.scrollTop !== scrollTop) {
- this.viewportElement.scrollTop = scrollTop;
- }
- };
- Viewport.prototype.onScroll = function (ev) {
- var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight);
- var diff = newRow - this.terminal.ydisp;
- this.terminal.scrollDisp(diff, true);
- };
- Viewport.prototype.onWheel = function (ev) {
- if (ev.deltaY === 0) {
- return;
- }
- var multiplier = 1;
- if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {
- multiplier = this.currentRowHeight;
- }
- else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
- multiplier = this.currentRowHeight * this.terminal.rows;
- }
- this.viewportElement.scrollTop += ev.deltaY * multiplier;
- ev.preventDefault();
- };
- ;
- return Viewport;
-}());
-exports.Viewport = Viewport;
-
-
-
-},{}],10:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-function prepareTextForClipboard(text) {
- var space = String.fromCharCode(32), nonBreakingSpace = String.fromCharCode(160), allNonBreakingSpaces = new RegExp(nonBreakingSpace, 'g'), processedText = text.split('\n').map(function (line) {
- var processedLine = line.replace(/\s+$/g, '').replace(allNonBreakingSpaces, space);
- return processedLine;
- }).join('\n');
- return processedText;
-}
-exports.prepareTextForClipboard = prepareTextForClipboard;
-function prepareTextForTerminal(text, isMSWindows) {
- if (isMSWindows) {
- return text.replace(/\r?\n/g, '\n');
- }
- return text;
-}
-exports.prepareTextForTerminal = prepareTextForTerminal;
-function copyHandler(ev, term) {
- var copiedText = window.getSelection().toString(), text = prepareTextForClipboard(copiedText);
- if (term.browser.isMSIE) {
- window.clipboardData.setData('Text', text);
- }
- else {
- ev.clipboardData.setData('text/plain', text);
- }
- ev.preventDefault();
-}
-exports.copyHandler = copyHandler;
-function pasteHandler(ev, term) {
- ev.stopPropagation();
- var text;
- var dispatchPaste = function (text) {
- text = prepareTextForTerminal(text, term.browser.isMSWindows);
- term.handler(text);
- term.textarea.value = '';
- term.emit('paste', text);
- return term.cancel(ev);
- };
- if (term.browser.isMSIE) {
- if (window.clipboardData) {
- text = window.clipboardData.getData('Text');
- dispatchPaste(text);
- }
- }
- else {
- if (ev.clipboardData) {
- text = ev.clipboardData.getData('text/plain');
- dispatchPaste(text);
- }
- }
-}
-exports.pasteHandler = pasteHandler;
-function rightClickHandler(ev, term) {
- var s = document.getSelection(), selectedText = prepareTextForClipboard(s.toString()), clickIsOnSelection = false, x = ev.clientX, y = ev.clientY;
- if (s.rangeCount) {
- var r = s.getRangeAt(0), cr = r.getClientRects();
- for (var i = 0; i < cr.length; i++) {
- var rect = cr[i];
- clickIsOnSelection = ((x > rect.left) && (x < rect.right) &&
- (y > rect.top) && (y < rect.bottom));
- if (clickIsOnSelection) {
- break;
- }
- }
- if (selectedText.match(/^\s$/) || !selectedText.length) {
- clickIsOnSelection = false;
- }
- }
- if (!clickIsOnSelection) {
- term.textarea.style.position = 'fixed';
- term.textarea.style.width = '20px';
- term.textarea.style.height = '20px';
- term.textarea.style.left = (x - 10) + 'px';
- term.textarea.style.top = (y - 10) + 'px';
- term.textarea.style.zIndex = '1000';
- term.textarea.focus();
- setTimeout(function () {
- term.textarea.style.position = null;
- term.textarea.style.width = null;
- term.textarea.style.height = null;
- term.textarea.style.left = null;
- term.textarea.style.top = null;
- term.textarea.style.zIndex = null;
- }, 4);
- }
-}
-exports.rightClickHandler = rightClickHandler;
-
-
-
-},{}],11:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Generic_1 = require("./Generic");
-var isNode = (typeof navigator === 'undefined') ? true : false;
-var userAgent = (isNode) ? 'node' : navigator.userAgent;
-var platform = (isNode) ? 'node' : navigator.platform;
-exports.isFirefox = !!~userAgent.indexOf('Firefox');
-exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident');
-exports.isMac = Generic_1.contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);
-exports.isIpad = platform === 'iPad';
-exports.isIphone = platform === 'iPhone';
-exports.isMSWindows = Generic_1.contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
-
-
-
-},{"./Generic":15}],12:[function(require,module,exports){
-"use strict";
-var __extends = (this && this.__extends) || (function () {
- var extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
- return function (d, b) {
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
-})();
-Object.defineProperty(exports, "__esModule", { value: true });
-var EventEmitter_js_1 = require("../EventEmitter.js");
-var CharMeasure = (function (_super) {
- __extends(CharMeasure, _super);
- function CharMeasure(document, parentElement) {
- var _this = _super.call(this) || this;
- _this._document = document;
- _this._parentElement = parentElement;
- return _this;
- }
- Object.defineProperty(CharMeasure.prototype, "width", {
- get: function () {
- return this._width;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(CharMeasure.prototype, "height", {
- get: function () {
- return this._height;
- },
- enumerable: true,
- configurable: true
- });
- CharMeasure.prototype.measure = function () {
- var _this = this;
- if (!this._measureElement) {
- this._measureElement = this._document.createElement('span');
- this._measureElement.style.position = 'absolute';
- this._measureElement.style.top = '0';
- this._measureElement.style.left = '-9999em';
- this._measureElement.textContent = 'W';
- this._measureElement.setAttribute('aria-hidden', 'true');
- this._parentElement.appendChild(this._measureElement);
- setTimeout(function () { return _this._doMeasure(); }, 0);
- }
- else {
- this._doMeasure();
- }
- };
- CharMeasure.prototype._doMeasure = function () {
- var geometry = this._measureElement.getBoundingClientRect();
- if (geometry.width === 0 || geometry.height === 0) {
- return;
- }
- if (this._width !== geometry.width || this._height !== geometry.height) {
- this._width = geometry.width;
- this._height = geometry.height;
- this.emit('charsizechanged');
- }
- };
- return CharMeasure;
-}(EventEmitter_js_1.EventEmitter));
-exports.CharMeasure = CharMeasure;
-
-
-
-},{"../EventEmitter.js":4}],13:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var CircularList = (function () {
- function CircularList(maxLength) {
- this._array = new Array(maxLength);
- this._startIndex = 0;
- this._length = 0;
- }
- Object.defineProperty(CircularList.prototype, "maxLength", {
- get: function () {
- return this._array.length;
- },
- set: function (newMaxLength) {
- var newArray = new Array(newMaxLength);
- for (var i = 0; i < Math.min(newMaxLength, this.length); i++) {
- newArray[i] = this._array[this._getCyclicIndex(i)];
- }
- this._array = newArray;
- this._startIndex = 0;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(CircularList.prototype, "length", {
- get: function () {
- return this._length;
- },
- set: function (newLength) {
- if (newLength > this._length) {
- for (var i = this._length; i < newLength; i++) {
- this._array[i] = undefined;
- }
- }
- this._length = newLength;
- },
- enumerable: true,
- configurable: true
- });
- Object.defineProperty(CircularList.prototype, "forEach", {
- get: function () {
- return this._array.forEach;
- },
- enumerable: true,
- configurable: true
- });
- CircularList.prototype.get = function (index) {
- return this._array[this._getCyclicIndex(index)];
- };
- CircularList.prototype.set = function (index, value) {
- this._array[this._getCyclicIndex(index)] = value;
- };
- CircularList.prototype.push = function (value) {
- this._array[this._getCyclicIndex(this._length)] = value;
- if (this._length === this.maxLength) {
- this._startIndex++;
- if (this._startIndex === this.maxLength) {
- this._startIndex = 0;
- }
- }
- else {
- this._length++;
- }
- };
- CircularList.prototype.pop = function () {
- return this._array[this._getCyclicIndex(this._length-- - 1)];
- };
- CircularList.prototype.splice = function (start, deleteCount) {
- var items = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- items[_i - 2] = arguments[_i];
- }
- if (deleteCount) {
- for (var i = start; i < this._length - deleteCount; i++) {
- this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)];
- }
- this._length -= deleteCount;
- }
- if (items && items.length) {
- for (var i = this._length - 1; i >= start; i--) {
- this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)];
- }
- for (var i = 0; i < items.length; i++) {
- this._array[this._getCyclicIndex(start + i)] = items[i];
- }
- if (this._length + items.length > this.maxLength) {
- this._startIndex += (this._length + items.length) - this.maxLength;
- this._length = this.maxLength;
- }
- else {
- this._length += items.length;
- }
- }
- };
- CircularList.prototype.trimStart = function (count) {
- if (count > this._length) {
- count = this._length;
- }
- this._startIndex += count;
- this._length -= count;
- };
- CircularList.prototype.shiftElements = function (start, count, offset) {
- if (count <= 0) {
- return;
- }
- if (start < 0 || start >= this._length) {
- throw new Error('start argument out of range');
- }
- if (start + offset < 0) {
- throw new Error('Cannot shift elements in list beyond index 0');
- }
- if (offset > 0) {
- for (var i = count - 1; i >= 0; i--) {
- this.set(start + i + offset, this.get(start + i));
- }
- var expandListBy = (start + count + offset) - this._length;
- if (expandListBy > 0) {
- this._length += expandListBy;
- while (this._length > this.maxLength) {
- this._length--;
- this._startIndex++;
- }
- }
- }
- else {
- for (var i = 0; i < count; i++) {
- this.set(start + i + offset, this.get(start + i));
- }
- }
- };
- CircularList.prototype._getCyclicIndex = function (index) {
- return (this._startIndex + index) % this.maxLength;
- };
- return CircularList;
-}());
-exports.CircularList = CircularList;
-
-
-
-},{}],14:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var DomElementObjectPool = (function () {
- function DomElementObjectPool(type) {
- this.type = type;
- this._type = type;
- this._pool = [];
- this._inUse = {};
- }
- DomElementObjectPool.prototype.acquire = function () {
- var element;
- if (this._pool.length === 0) {
- element = this._createNew();
- }
- else {
- element = this._pool.pop();
- }
- this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)] = element;
- return element;
- };
- DomElementObjectPool.prototype.release = function (element) {
- if (!this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)]) {
- throw new Error('Could not release an element not yet acquired');
- }
- delete this._inUse[element.getAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE)];
- this._cleanElement(element);
- this._pool.push(element);
- };
- DomElementObjectPool.prototype._createNew = function () {
- var element = document.createElement(this._type);
- var id = DomElementObjectPool._objectCount++;
- element.setAttribute(DomElementObjectPool.OBJECT_ID_ATTRIBUTE, id.toString(10));
- return element;
- };
- DomElementObjectPool.prototype._cleanElement = function (element) {
- element.className = '';
- element.innerHTML = '';
- };
- return DomElementObjectPool;
-}());
-DomElementObjectPool.OBJECT_ID_ATTRIBUTE = 'data-obj-id';
-DomElementObjectPool._objectCount = 0;
-exports.DomElementObjectPool = DomElementObjectPool;
-
-
-
-},{}],15:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-function contains(arr, el) {
- return arr.indexOf(el) >= 0;
-}
-exports.contains = contains;
-;
-
-
-
-},{}],16:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-function getCoords(event, rowContainer, charMeasure) {
- if (event.pageX == null) {
- return null;
- }
- var x = event.pageX;
- var y = event.pageY;
- var el = rowContainer;
- while (el && el !== self.document.documentElement) {
- x -= el.offsetLeft;
- y -= el.offsetTop;
- el = 'offsetParent' in el ? el.offsetParent : el.parentElement;
- }
- x = Math.ceil(x / charMeasure.width);
- y = Math.ceil(y / charMeasure.height);
- return [x, y];
-}
-exports.getCoords = getCoords;
-function getRawByteCoords(event, rowContainer, charMeasure, colCount, rowCount) {
- var coords = getCoords(event, rowContainer, charMeasure);
- var x = coords[0];
- var y = coords[1];
- x = Math.min(Math.max(x, 0), colCount);
- y = Math.min(Math.max(y, 0), rowCount);
- x += 32;
- y += 32;
- return { x: x, y: y };
-}
-exports.getRawByteCoords = getRawByteCoords;
-
-
-
-},{}],17:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var CompositionHelper_1 = require("./CompositionHelper");
-var EventEmitter_1 = require("./EventEmitter");
-var Viewport_1 = require("./Viewport");
-var Clipboard_1 = require("./handlers/Clipboard");
-var CircularList_1 = require("./utils/CircularList");
-var EscapeSequences_1 = require("./EscapeSequences");
-var InputHandler_1 = require("./InputHandler");
-var Parser_1 = require("./Parser");
-var Renderer_1 = require("./Renderer");
-var Linkifier_1 = require("./Linkifier");
-var CharMeasure_1 = require("./utils/CharMeasure");
-var Browser = require("./utils/Browser");
-var Mouse_1 = require("./utils/Mouse");
-var document = (typeof window != 'undefined') ? window.document : null;
-var WRITE_BUFFER_PAUSE_THRESHOLD = 5;
-var WRITE_BATCH_SIZE = 300;
-var CURSOR_BLINK_INTERVAL = 600;
-function Terminal(options) {
- var self = this;
- if (!(this instanceof Terminal)) {
- return new Terminal(arguments[0], arguments[1], arguments[2]);
- }
- self.browser = Browser;
- self.cancel = Terminal.cancel;
- EventEmitter_1.EventEmitter.call(this);
- if (typeof options === 'number') {
- options = {
- cols: arguments[0],
- rows: arguments[1],
- handler: arguments[2]
- };
- }
- options = options || {};
- Object.keys(Terminal.defaults).forEach(function (key) {
- if (options[key] == null) {
- options[key] = Terminal.options[key];
- if (Terminal[key] !== Terminal.defaults[key]) {
- options[key] = Terminal[key];
- }
- }
- self[key] = options[key];
- });
- if (options.colors.length === 8) {
- options.colors = options.colors.concat(Terminal._colors.slice(8));
- }
- else if (options.colors.length === 16) {
- options.colors = options.colors.concat(Terminal._colors.slice(16));
- }
- else if (options.colors.length === 10) {
- options.colors = options.colors.slice(0, -2).concat(Terminal._colors.slice(8, -2), options.colors.slice(-2));
- }
- else if (options.colors.length === 18) {
- options.colors = options.colors.concat(Terminal._colors.slice(16, -2), options.colors.slice(-2));
- }
- this.colors = options.colors;
- this.options = options;
- this.parent = options.body || options.parent || (document ? document.getElementsByTagName('body')[0] : null);
- this.cols = options.cols || options.geometry[0];
- this.rows = options.rows || options.geometry[1];
- this.geometry = [this.cols, this.rows];
- if (options.handler) {
- this.on('data', options.handler);
- }
- this.ybase = 0;
- this.ydisp = 0;
- this.x = 0;
- this.y = 0;
- this.cursorState = 0;
- this.cursorHidden = false;
- this.convertEol;
- this.queue = '';
- this.scrollTop = 0;
- this.scrollBottom = this.rows - 1;
- this.customKeydownHandler = null;
- this.cursorBlinkInterval = null;
- this.applicationKeypad = false;
- this.applicationCursor = false;
- this.originMode = false;
- this.insertMode = false;
- this.wraparoundMode = true;
- this.normal = null;
- this.charset = null;
- this.gcharset = null;
- this.glevel = 0;
- this.charsets = [null];
- this.decLocator;
- this.x10Mouse;
- this.vt200Mouse;
- this.vt300Mouse;
- this.normalMouse;
- this.mouseEvents;
- this.sendFocus;
- this.utfMouse;
- this.sgrMouse;
- this.urxvtMouse;
- this.element;
- this.children;
- this.refreshStart;
- this.refreshEnd;
- this.savedX;
- this.savedY;
- this.savedCols;
- this.readable = true;
- this.writable = true;
- this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);
- this.curAttr = this.defAttr;
- this.params = [];
- this.currentParam = 0;
- this.prefix = '';
- this.postfix = '';
- this.inputHandler = new InputHandler_1.InputHandler(this);
- this.parser = new Parser_1.Parser(this.inputHandler, this);
- this.renderer = this.renderer || null;
- this.linkifier = this.linkifier || new Linkifier_1.Linkifier();
- this.writeBuffer = [];
- this.writeInProgress = false;
- this.xoffSentToCatchUp = false;
- this.writeStopped = false;
- this.surrogate_high = '';
- this.lines = new CircularList_1.CircularList(this.scrollback);
- var i = this.rows;
- while (i--) {
- this.lines.push(this.blankLine());
- }
- this.tabs;
- this.setupStops();
- this.userScrolling = false;
-}
-inherits(Terminal, EventEmitter_1.EventEmitter);
-Terminal.prototype.eraseAttr = function () {
- return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);
-};
-Terminal.tangoColors = [
- '#2e3436',
- '#cc0000',
- '#4e9a06',
- '#c4a000',
- '#3465a4',
- '#75507b',
- '#06989a',
- '#d3d7cf',
- '#555753',
- '#ef2929',
- '#8ae234',
- '#fce94f',
- '#729fcf',
- '#ad7fa8',
- '#34e2e2',
- '#eeeeec'
-];
-Terminal.colors = (function () {
- var colors = Terminal.tangoColors.slice(), r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff], i;
- i = 0;
- for (; i < 216; i++) {
- out(r[(i / 36) % 6 | 0], r[(i / 6) % 6 | 0], r[i % 6]);
- }
- i = 0;
- for (; i < 24; i++) {
- r = 8 + i * 10;
- out(r, r, r);
- }
- function out(r, g, b) {
- colors.push('#' + hex(r) + hex(g) + hex(b));
- }
- function hex(c) {
- c = c.toString(16);
- return c.length < 2 ? '0' + c : c;
- }
- return colors;
-})();
-Terminal._colors = Terminal.colors.slice();
-Terminal.vcolors = (function () {
- var out = [], colors = Terminal.colors, i = 0, color;
- for (; i < 256; i++) {
- color = parseInt(colors[i].substring(1), 16);
- out.push([
- (color >> 16) & 0xff,
- (color >> 8) & 0xff,
- color & 0xff
- ]);
- }
- return out;
-})();
-Terminal.defaults = {
- colors: Terminal.colors,
- theme: 'default',
- convertEol: false,
- termName: 'xterm',
- geometry: [80, 24],
- cursorBlink: false,
- cursorStyle: 'block',
- visualBell: false,
- popOnBell: false,
- scrollback: 1000,
- screenKeys: false,
- debug: false,
- cancelEvents: false,
- disableStdin: false,
- useFlowControl: false,
- tabStopWidth: 8
-};
-Terminal.options = {};
-Terminal.focus = null;
-each(keys(Terminal.defaults), function (key) {
- Terminal[key] = Terminal.defaults[key];
- Terminal.options[key] = Terminal.defaults[key];
-});
-Terminal.prototype.focus = function () {
- return this.textarea.focus();
-};
-Terminal.prototype.getOption = function (key, value) {
- if (!(key in Terminal.defaults)) {
- throw new Error('No option with key "' + key + '"');
- }
- if (typeof this.options[key] !== 'undefined') {
- return this.options[key];
- }
- return this[key];
-};
-Terminal.prototype.setOption = function (key, value) {
- if (!(key in Terminal.defaults)) {
- throw new Error('No option with key "' + key + '"');
- }
- switch (key) {
- case 'scrollback':
- if (this.options[key] !== value) {
- if (this.lines.length > value) {
- var amountToTrim = this.lines.length - value;
- var needsRefresh = (this.ydisp - amountToTrim < 0);
- this.lines.trimStart(amountToTrim);
- this.ybase = Math.max(this.ybase - amountToTrim, 0);
- this.ydisp = Math.max(this.ydisp - amountToTrim, 0);
- if (needsRefresh) {
- this.refresh(0, this.rows - 1);
- }
- }
- this.lines.maxLength = value;
- this.viewport.syncScrollArea();
- }
- break;
- }
- this[key] = value;
- this.options[key] = value;
- switch (key) {
- case 'cursorBlink':
- this.setCursorBlinking(value);
- break;
- case 'cursorStyle':
- this.element.classList.toggle("xterm-cursor-style-underline", value === 'underline');
- this.element.classList.toggle("xterm-cursor-style-bar", value === 'bar');
- break;
- case 'tabStopWidth':
- this.setupStops();
- break;
- }
-};
-Terminal.prototype.restartCursorBlinking = function () {
- this.setCursorBlinking(this.options.cursorBlink);
-};
-Terminal.prototype.setCursorBlinking = function (enabled) {
- this.element.classList.toggle('xterm-cursor-blink', enabled);
- this.clearCursorBlinkingInterval();
- if (enabled) {
- var self = this;
- this.cursorBlinkInterval = setInterval(function () {
- self.element.classList.toggle('xterm-cursor-blink-on');
- }, CURSOR_BLINK_INTERVAL);
- }
-};
-Terminal.prototype.clearCursorBlinkingInterval = function () {
- this.element.classList.remove('xterm-cursor-blink-on');
- if (this.cursorBlinkInterval) {
- clearInterval(this.cursorBlinkInterval);
- this.cursorBlinkInterval = null;
- }
-};
-Terminal.bindFocus = function (term) {
- on(term.textarea, 'focus', function (ev) {
- if (term.sendFocus) {
- term.send(EscapeSequences_1.C0.ESC + '[I');
- }
- term.element.classList.add('focus');
- term.showCursor();
- term.restartCursorBlinking.apply(term);
- Terminal.focus = term;
- term.emit('focus', { terminal: term });
- });
-};
-Terminal.prototype.blur = function () {
- return this.textarea.blur();
-};
-Terminal.bindBlur = function (term) {
- on(term.textarea, 'blur', function (ev) {
- term.refresh(term.y, term.y);
- if (term.sendFocus) {
- term.send(EscapeSequences_1.C0.ESC + '[O');
- }
- term.element.classList.remove('focus');
- term.clearCursorBlinkingInterval.apply(term);
- Terminal.focus = null;
- term.emit('blur', { terminal: term });
- });
-};
-Terminal.prototype.initGlobal = function () {
- var term = this;
- Terminal.bindKeys(this);
- Terminal.bindFocus(this);
- Terminal.bindBlur(this);
- on(this.element, 'copy', function (ev) {
- Clipboard_1.copyHandler.call(this, ev, term);
- });
- on(this.textarea, 'paste', function (ev) {
- Clipboard_1.pasteHandler.call(this, ev, term);
- });
- on(this.element, 'paste', function (ev) {
- Clipboard_1.pasteHandler.call(this, ev, term);
- });
- function rightClickHandlerWrapper(ev) {
- Clipboard_1.rightClickHandler.call(this, ev, term);
- }
- if (term.browser.isFirefox) {
- on(this.element, 'mousedown', function (ev) {
- if (ev.button == 2) {
- rightClickHandlerWrapper(ev);
- }
- });
- }
- else {
- on(this.element, 'contextmenu', rightClickHandlerWrapper);
- }
-};
-Terminal.bindKeys = function (term) {
- on(term.element, 'keydown', function (ev) {
- if (document.activeElement != this) {
- return;
- }
- term.keyDown(ev);
- }, true);
- on(term.element, 'keypress', function (ev) {
- if (document.activeElement != this) {
- return;
- }
- term.keyPress(ev);
- }, true);
- on(term.element, 'keyup', function (ev) {
- if (!wasMondifierKeyOnlyEvent(ev)) {
- term.focus(term);
- }
- }, true);
- on(term.textarea, 'keydown', function (ev) {
- term.keyDown(ev);
- }, true);
- on(term.textarea, 'keypress', function (ev) {
- term.keyPress(ev);
- this.value = '';
- }, true);
- on(term.textarea, 'compositionstart', term.compositionHelper.compositionstart.bind(term.compositionHelper));
- on(term.textarea, 'compositionupdate', term.compositionHelper.compositionupdate.bind(term.compositionHelper));
- on(term.textarea, 'compositionend', term.compositionHelper.compositionend.bind(term.compositionHelper));
- term.on('refresh', term.compositionHelper.updateCompositionElements.bind(term.compositionHelper));
- term.on('refresh', function (data) {
- term.queueLinkification(data.start, data.end);
- });
-};
-Terminal.prototype.insertRow = function (row) {
- if (typeof row != 'object') {
- row = document.createElement('div');
- }
- this.rowContainer.appendChild(row);
- this.children.push(row);
- return row;
-};
-Terminal.prototype.open = function (parent, focus) {
- var self = this, i = 0, div;
- this.parent = parent || this.parent;
- if (!this.parent) {
- throw new Error('Terminal requires a parent element.');
- }
- this.context = this.parent.ownerDocument.defaultView;
- this.document = this.parent.ownerDocument;
- this.body = this.document.getElementsByTagName('body')[0];
- this.element = this.document.createElement('div');
- this.element.classList.add('terminal');
- this.element.classList.add('xterm');
- this.element.classList.add('xterm-theme-' + this.theme);
- this.setCursorBlinking(this.options.cursorBlink);
- this.element.style.height;
- this.element.setAttribute('tabindex', 0);
- this.viewportElement = document.createElement('div');
- this.viewportElement.classList.add('xterm-viewport');
- this.element.appendChild(this.viewportElement);
- this.viewportScrollArea = document.createElement('div');
- this.viewportScrollArea.classList.add('xterm-scroll-area');
- this.viewportElement.appendChild(this.viewportScrollArea);
- this.rowContainer = document.createElement('div');
- this.rowContainer.classList.add('xterm-rows');
- this.element.appendChild(this.rowContainer);
- this.children = [];
- this.linkifier.attachToDom(document, this.children);
- this.helperContainer = document.createElement('div');
- this.helperContainer.classList.add('xterm-helpers');
- this.element.appendChild(this.helperContainer);
- this.textarea = document.createElement('textarea');
- this.textarea.classList.add('xterm-helper-textarea');
- this.textarea.setAttribute('autocorrect', 'off');
- this.textarea.setAttribute('autocapitalize', 'off');
- this.textarea.setAttribute('spellcheck', 'false');
- this.textarea.tabIndex = 0;
- this.textarea.addEventListener('focus', function () {
- self.emit('focus', { terminal: self });
- });
- this.textarea.addEventListener('blur', function () {
- self.emit('blur', { terminal: self });
- });
- this.helperContainer.appendChild(this.textarea);
- this.compositionView = document.createElement('div');
- this.compositionView.classList.add('composition-view');
- this.compositionHelper = new CompositionHelper_1.CompositionHelper(this.textarea, this.compositionView, this);
- this.helperContainer.appendChild(this.compositionView);
- this.charSizeStyleElement = document.createElement('style');
- this.helperContainer.appendChild(this.charSizeStyleElement);
- for (; i < this.rows; i++) {
- this.insertRow();
- }
- this.parent.appendChild(this.element);
- this.charMeasure = new CharMeasure_1.CharMeasure(document, this.helperContainer);
- this.charMeasure.on('charsizechanged', function () {
- self.updateCharSizeCSS();
- });
- this.charMeasure.measure();
- this.viewport = new Viewport_1.Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
- this.renderer = new Renderer_1.Renderer(this);
- this.refresh(0, this.rows - 1);
- this.initGlobal();
- if (typeof focus == 'undefined') {
- var message = 'You did not pass the `focus` argument in `Terminal.prototype.open()`.\n';
- message += 'The `focus` argument now defaults to `true` but starting with xterm.js 3.0 ';
- message += 'it will default to `false`.';
- console.warn(message);
- focus = true;
- }
- if (focus) {
- this.focus();
- }
- on(this.element, 'click', function () {
- var selection = document.getSelection(), collapsed = selection.isCollapsed, isRange = typeof collapsed == 'boolean' ? !collapsed : selection.type == 'Range';
- if (!isRange) {
- self.focus();
- }
- });
- this.bindMouse();
- this.emit('open');
-};
-Terminal.loadAddon = function (addon, callback) {
- if (typeof exports === 'object' && typeof module === 'object') {
- return require('./addons/' + addon + '/' + addon);
- }
- else if (typeof define == 'function') {
- return require(['./addons/' + addon + '/' + addon], callback);
- }
- else {
- console.error('Cannot load a module without a CommonJS or RequireJS environment.');
- return false;
- }
-};
-Terminal.prototype.updateCharSizeCSS = function () {
- this.charSizeStyleElement.textContent =
- ".xterm-wide-char{width:" + this.charMeasure.width * 2 + "px;}" +
- (".xterm-normal-char{width:" + this.charMeasure.width + "px;}");
-};
-Terminal.prototype.bindMouse = function () {
- var el = this.element, self = this, pressed = 32;
- function sendButton(ev) {
- var button, pos;
- button = getButton(ev);
- pos = Mouse_1.getRawByteCoords(ev, self.rowContainer, self.charMeasure, self.cols, self.rows);
- if (!pos)
- return;
- sendEvent(button, pos);
- switch (ev.overrideType || ev.type) {
- case 'mousedown':
- pressed = button;
- break;
- case 'mouseup':
- pressed = 32;
- break;
- case 'wheel':
- break;
- }
- }
- function sendMove(ev) {
- var button = pressed, pos;
- pos = Mouse_1.getRawByteCoords(ev, self.rowContainer, self.charMeasure, self.cols, self.rows);
- if (!pos)
- return;
- button += 32;
- sendEvent(button, pos);
- }
- function encode(data, ch) {
- if (!self.utfMouse) {
- if (ch === 255)
- return data.push(0);
- if (ch > 127)
- ch = 127;
- data.push(ch);
- }
- else {
- if (ch === 2047)
- return data.push(0);
- if (ch < 127) {
- data.push(ch);
- }
- else {
- if (ch > 2047)
- ch = 2047;
- data.push(0xC0 | (ch >> 6));
- data.push(0x80 | (ch & 0x3F));
- }
- }
- }
- function sendEvent(button, pos) {
- if (self.vt300Mouse) {
- button &= 3;
- pos.x -= 32;
- pos.y -= 32;
- var data = EscapeSequences_1.C0.ESC + '[24';
- if (button === 0)
- data += '1';
- else if (button === 1)
- data += '3';
- else if (button === 2)
- data += '5';
- else if (button === 3)
- return;
- else
- data += '0';
- data += '~[' + pos.x + ',' + pos.y + ']\r';
- self.send(data);
- return;
- }
- if (self.decLocator) {
- button &= 3;
- pos.x -= 32;
- pos.y -= 32;
- if (button === 0)
- button = 2;
- else if (button === 1)
- button = 4;
- else if (button === 2)
- button = 6;
- else if (button === 3)
- button = 3;
- self.send(EscapeSequences_1.C0.ESC + '['
- + button
- + ';'
- + (button === 3 ? 4 : 0)
- + ';'
- + pos.y
- + ';'
- + pos.x
- + ';'
- + (pos.page || 0)
- + '&w');
- return;
- }
- if (self.urxvtMouse) {
- pos.x -= 32;
- pos.y -= 32;
- pos.x++;
- pos.y++;
- self.send(EscapeSequences_1.C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M');
- return;
- }
- if (self.sgrMouse) {
- pos.x -= 32;
- pos.y -= 32;
- self.send(EscapeSequences_1.C0.ESC + '[<'
- + (((button & 3) === 3 ? button & ~3 : button) - 32)
- + ';'
- + pos.x
- + ';'
- + pos.y
- + ((button & 3) === 3 ? 'm' : 'M'));
- return;
- }
- var data = [];
- encode(data, button);
- encode(data, pos.x);
- encode(data, pos.y);
- self.send(EscapeSequences_1.C0.ESC + '[M' + String.fromCharCode.apply(String, data));
- }
- function getButton(ev) {
- var button, shift, meta, ctrl, mod;
- switch (ev.overrideType || ev.type) {
- case 'mousedown':
- button = ev.button != null
- ? +ev.button
- : ev.which != null
- ? ev.which - 1
- : null;
- if (self.browser.isMSIE) {
- button = button === 1 ? 0 : button === 4 ? 1 : button;
- }
- break;
- case 'mouseup':
- button = 3;
- break;
- case 'DOMMouseScroll':
- button = ev.detail < 0
- ? 64
- : 65;
- break;
- case 'wheel':
- button = ev.wheelDeltaY > 0
- ? 64
- : 65;
- break;
- }
- shift = ev.shiftKey ? 4 : 0;
- meta = ev.metaKey ? 8 : 0;
- ctrl = ev.ctrlKey ? 16 : 0;
- mod = shift | meta | ctrl;
- if (self.vt200Mouse) {
- mod &= ctrl;
- }
- else if (!self.normalMouse) {
- mod = 0;
- }
- button = (32 + (mod << 2)) + button;
- return button;
- }
- on(el, 'mousedown', function (ev) {
- if (!self.mouseEvents)
- return;
- sendButton(ev);
- self.focus();
- if (self.vt200Mouse) {
- ev.overrideType = 'mouseup';
- sendButton(ev);
- return self.cancel(ev);
- }
- if (self.normalMouse)
- on(self.document, 'mousemove', sendMove);
- if (!self.x10Mouse) {
- on(self.document, 'mouseup', function up(ev) {
- sendButton(ev);
- if (self.normalMouse)
- off(self.document, 'mousemove', sendMove);
- off(self.document, 'mouseup', up);
- return self.cancel(ev);
- });
- }
- return self.cancel(ev);
- });
- on(el, 'wheel', function (ev) {
- if (!self.mouseEvents)
- return;
- if (self.x10Mouse
- || self.vt300Mouse
- || self.decLocator)
- return;
- sendButton(ev);
- return self.cancel(ev);
- });
- on(el, 'wheel', function (ev) {
- if (self.mouseEvents)
- return;
- self.viewport.onWheel(ev);
- return self.cancel(ev);
- });
-};
-Terminal.prototype.destroy = function () {
- this.readable = false;
- this.writable = false;
- this._events = {};
- this.handler = function () { };
- this.write = function () { };
- if (this.element && this.element.parentNode) {
- this.element.parentNode.removeChild(this.element);
- }
-};
-Terminal.prototype.refresh = function (start, end) {
- if (this.renderer) {
- this.renderer.queueRefresh(start, end);
- }
-};
-Terminal.prototype.queueLinkification = function (start, end) {
- if (this.linkifier) {
- for (var i = start; i <= end; i++) {
- this.linkifier.linkifyRow(i);
- }
- }
-};
-Terminal.prototype.showCursor = function () {
- if (!this.cursorState) {
- this.cursorState = 1;
- this.refresh(this.y, this.y);
- }
-};
-Terminal.prototype.scroll = function () {
- var row;
- if (this.lines.length === this.lines.maxLength) {
- this.lines.trimStart(1);
- this.ybase--;
- if (this.ydisp !== 0) {
- this.ydisp--;
- }
- }
- this.ybase++;
- if (!this.userScrolling) {
- this.ydisp = this.ybase;
- }
- row = this.ybase + this.rows - 1;
- row -= this.rows - 1 - this.scrollBottom;
- if (row === this.lines.length) {
- this.lines.push(this.blankLine());
- }
- else {
- this.lines.splice(row, 0, this.blankLine());
- }
- if (this.scrollTop !== 0) {
- if (this.ybase !== 0) {
- this.ybase--;
- if (!this.userScrolling) {
- this.ydisp = this.ybase;
- }
- }
- this.lines.splice(this.ybase + this.scrollTop, 1);
- }
- this.updateRange(this.scrollTop);
- this.updateRange(this.scrollBottom);
- this.emit('scroll', this.ydisp);
-};
-Terminal.prototype.scrollDisp = function (disp, suppressScrollEvent) {
- if (disp < 0) {
- this.userScrolling = true;
- }
- else if (disp + this.ydisp >= this.ybase) {
- this.userScrolling = false;
- }
- this.ydisp += disp;
- if (this.ydisp > this.ybase) {
- this.ydisp = this.ybase;
- }
- else if (this.ydisp < 0) {
- this.ydisp = 0;
- }
- if (!suppressScrollEvent) {
- this.emit('scroll', this.ydisp);
- }
- this.refresh(0, this.rows - 1);
-};
-Terminal.prototype.scrollPages = function (pageCount) {
- this.scrollDisp(pageCount * (this.rows - 1));
-};
-Terminal.prototype.scrollToTop = function () {
- this.scrollDisp(-this.ydisp);
-};
-Terminal.prototype.scrollToBottom = function () {
- this.scrollDisp(this.ybase - this.ydisp);
-};
-Terminal.prototype.write = function (data) {
- this.writeBuffer.push(data);
- if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) {
- this.send(EscapeSequences_1.C0.DC3);
- this.xoffSentToCatchUp = true;
- }
- if (!this.writeInProgress && this.writeBuffer.length > 0) {
- this.writeInProgress = true;
- var self = this;
- setTimeout(function () {
- self.innerWrite();
- });
- }
-};
-Terminal.prototype.innerWrite = function () {
- var writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE);
- while (writeBatch.length > 0) {
- var data = writeBatch.shift();
- var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row;
- if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) {
- this.send(EscapeSequences_1.C0.DC1);
- this.xoffSentToCatchUp = false;
- }
- this.refreshStart = this.y;
- this.refreshEnd = this.y;
- var state = this.parser.parse(data);
- this.parser.setState(state);
- this.updateRange(this.y);
- this.refresh(this.refreshStart, this.refreshEnd);
- }
- if (this.writeBuffer.length > 0) {
- var self = this;
- setTimeout(function () {
- self.innerWrite();
- }, 0);
- }
- else {
- this.writeInProgress = false;
- }
-};
-Terminal.prototype.writeln = function (data) {
- this.write(data + '\r\n');
-};
-Terminal.prototype.attachCustomKeydownHandler = function (customKeydownHandler) {
- this.customKeydownHandler = customKeydownHandler;
-};
-Terminal.prototype.setHypertextLinkHandler = function (handler) {
- if (!this.linkifier) {
- throw new Error('Cannot attach a hypertext link handler before Terminal.open is called');
- }
- this.linkifier.setHypertextLinkHandler(handler);
- this.refresh(0, this.rows - 1);
-};
-Terminal.prototype.setHypertextValidationCallback = function (handler) {
- if (!this.linkifier) {
- throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called');
- }
- this.linkifier.setHypertextValidationCallback(handler);
- this.refresh(0, this.rows - 1);
-};
-Terminal.prototype.registerLinkMatcher = function (regex, handler, options) {
- if (this.linkifier) {
- var matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);
- this.refresh(0, this.rows - 1);
- return matcherId;
- }
-};
-Terminal.prototype.deregisterLinkMatcher = function (matcherId) {
- if (this.linkifier) {
- if (this.linkifier.deregisterLinkMatcher(matcherId)) {
- this.refresh(0, this.rows - 1);
- }
- }
-};
-Terminal.prototype.keyDown = function (ev) {
- if (this.customKeydownHandler && this.customKeydownHandler(ev) === false) {
- return false;
- }
- this.restartCursorBlinking();
- if (!this.compositionHelper.keydown.bind(this.compositionHelper)(ev)) {
- if (this.ybase !== this.ydisp) {
- this.scrollToBottom();
- }
- return false;
- }
- var self = this;
- var result = this.evaluateKeyEscapeSequence(ev);
- if (result.key === EscapeSequences_1.C0.DC3) {
- this.writeStopped = true;
- }
- else if (result.key === EscapeSequences_1.C0.DC1) {
- this.writeStopped = false;
- }
- if (result.scrollDisp) {
- this.scrollDisp(result.scrollDisp);
- return this.cancel(ev, true);
- }
- if (isThirdLevelShift(this, ev)) {
- return true;
- }
- if (result.cancel) {
- this.cancel(ev, true);
- }
- if (!result.key) {
- return true;
- }
- this.emit('keydown', ev);
- this.emit('key', result.key, ev);
- this.showCursor();
- this.handler(result.key);
- return this.cancel(ev, true);
-};
-Terminal.prototype.evaluateKeyEscapeSequence = function (ev) {
- var result = {
- cancel: false,
- key: undefined,
- scrollDisp: undefined
- };
- var modifiers = ev.shiftKey << 0 | ev.altKey << 1 | ev.ctrlKey << 2 | ev.metaKey << 3;
- switch (ev.keyCode) {
- case 8:
- if (ev.shiftKey) {
- result.key = EscapeSequences_1.C0.BS;
- break;
- }
- result.key = EscapeSequences_1.C0.DEL;
- break;
- case 9:
- if (ev.shiftKey) {
- result.key = EscapeSequences_1.C0.ESC + '[Z';
- break;
- }
- result.key = EscapeSequences_1.C0.HT;
- result.cancel = true;
- break;
- case 13:
- result.key = EscapeSequences_1.C0.CR;
- result.cancel = true;
- break;
- case 27:
- result.key = EscapeSequences_1.C0.ESC;
- result.cancel = true;
- break;
- case 37:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'D';
- if (result.key == EscapeSequences_1.C0.ESC + '[1;3D') {
- result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'b' : EscapeSequences_1.C0.ESC + '[1;5D';
- }
- }
- else if (this.applicationCursor) {
- result.key = EscapeSequences_1.C0.ESC + 'OD';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[D';
- }
- break;
- case 39:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'C';
- if (result.key == EscapeSequences_1.C0.ESC + '[1;3C') {
- result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'f' : EscapeSequences_1.C0.ESC + '[1;5C';
- }
- }
- else if (this.applicationCursor) {
- result.key = EscapeSequences_1.C0.ESC + 'OC';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[C';
- }
- break;
- case 38:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'A';
- if (result.key == EscapeSequences_1.C0.ESC + '[1;3A') {
- result.key = EscapeSequences_1.C0.ESC + '[1;5A';
- }
- }
- else if (this.applicationCursor) {
- result.key = EscapeSequences_1.C0.ESC + 'OA';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[A';
- }
- break;
- case 40:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'B';
- if (result.key == EscapeSequences_1.C0.ESC + '[1;3B') {
- result.key = EscapeSequences_1.C0.ESC + '[1;5B';
- }
- }
- else if (this.applicationCursor) {
- result.key = EscapeSequences_1.C0.ESC + 'OB';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[B';
- }
- break;
- case 45:
- if (!ev.shiftKey && !ev.ctrlKey) {
- result.key = EscapeSequences_1.C0.ESC + '[2~';
- }
- break;
- case 46:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[3;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[3~';
- }
- break;
- case 36:
- if (modifiers)
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'H';
- else if (this.applicationCursor)
- result.key = EscapeSequences_1.C0.ESC + 'OH';
- else
- result.key = EscapeSequences_1.C0.ESC + '[H';
- break;
- case 35:
- if (modifiers)
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'F';
- else if (this.applicationCursor)
- result.key = EscapeSequences_1.C0.ESC + 'OF';
- else
- result.key = EscapeSequences_1.C0.ESC + '[F';
- break;
- case 33:
- if (ev.shiftKey) {
- result.scrollDisp = -(this.rows - 1);
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[5~';
- }
- break;
- case 34:
- if (ev.shiftKey) {
- result.scrollDisp = this.rows - 1;
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[6~';
- }
- break;
- case 112:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'P';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + 'OP';
- }
- break;
- case 113:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'Q';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + 'OQ';
- }
- break;
- case 114:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'R';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + 'OR';
- }
- break;
- case 115:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'S';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + 'OS';
- }
- break;
- case 116:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[15;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[15~';
- }
- break;
- case 117:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[17;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[17~';
- }
- break;
- case 118:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[18;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[18~';
- }
- break;
- case 119:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[19;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[19~';
- }
- break;
- case 120:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[20;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[20~';
- }
- break;
- case 121:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[21;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[21~';
- }
- break;
- case 122:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[23;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[23~';
- }
- break;
- case 123:
- if (modifiers) {
- result.key = EscapeSequences_1.C0.ESC + '[24;' + (modifiers + 1) + '~';
- }
- else {
- result.key = EscapeSequences_1.C0.ESC + '[24~';
- }
- break;
- default:
- if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
- if (ev.keyCode >= 65 && ev.keyCode <= 90) {
- result.key = String.fromCharCode(ev.keyCode - 64);
- }
- else if (ev.keyCode === 32) {
- result.key = String.fromCharCode(0);
- }
- else if (ev.keyCode >= 51 && ev.keyCode <= 55) {
- result.key = String.fromCharCode(ev.keyCode - 51 + 27);
- }
- else if (ev.keyCode === 56) {
- result.key = String.fromCharCode(127);
- }
- else if (ev.keyCode === 219) {
- result.key = String.fromCharCode(27);
- }
- else if (ev.keyCode === 220) {
- result.key = String.fromCharCode(28);
- }
- else if (ev.keyCode === 221) {
- result.key = String.fromCharCode(29);
- }
- }
- else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {
- if (ev.keyCode >= 65 && ev.keyCode <= 90) {
- result.key = EscapeSequences_1.C0.ESC + String.fromCharCode(ev.keyCode + 32);
- }
- else if (ev.keyCode === 192) {
- result.key = EscapeSequences_1.C0.ESC + '`';
- }
- else if (ev.keyCode >= 48 && ev.keyCode <= 57) {
- result.key = EscapeSequences_1.C0.ESC + (ev.keyCode - 48);
- }
- }
- break;
- }
- return result;
-};
-Terminal.prototype.setgLevel = function (g) {
- this.glevel = g;
- this.charset = this.charsets[g];
-};
-Terminal.prototype.setgCharset = function (g, charset) {
- this.charsets[g] = charset;
- if (this.glevel === g) {
- this.charset = charset;
- }
-};
-Terminal.prototype.keyPress = function (ev) {
- var key;
- this.cancel(ev);
- if (ev.charCode) {
- key = ev.charCode;
- }
- else if (ev.which == null) {
- key = ev.keyCode;
- }
- else if (ev.which !== 0 && ev.charCode !== 0) {
- key = ev.which;
- }
- else {
- return false;
- }
- if (!key || ((ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this, ev))) {
- return false;
- }
- key = String.fromCharCode(key);
- this.emit('keypress', key, ev);
- this.emit('key', key, ev);
- this.showCursor();
- this.handler(key);
- return false;
-};
-Terminal.prototype.send = function (data) {
- var self = this;
- if (!this.queue) {
- setTimeout(function () {
- self.handler(self.queue);
- self.queue = '';
- }, 1);
- }
- this.queue += data;
-};
-Terminal.prototype.bell = function () {
- if (!this.visualBell)
- return;
- var self = this;
- this.element.style.borderColor = 'white';
- setTimeout(function () {
- self.element.style.borderColor = '';
- }, 10);
- if (this.popOnBell)
- this.focus();
-};
-Terminal.prototype.log = function () {
- if (!this.debug)
- return;
- if (!this.context.console || !this.context.console.log)
- return;
- var args = Array.prototype.slice.call(arguments);
- this.context.console.log.apply(this.context.console, args);
-};
-Terminal.prototype.error = function () {
- if (!this.debug)
- return;
- if (!this.context.console || !this.context.console.error)
- return;
- var args = Array.prototype.slice.call(arguments);
- this.context.console.error.apply(this.context.console, args);
-};
-Terminal.prototype.resize = function (x, y) {
- if (isNaN(x) || isNaN(y)) {
- return;
- }
- var line, el, i, j, ch, addToY;
- if (x === this.cols && y === this.rows) {
- return;
- }
- if (x < 1)
- x = 1;
- if (y < 1)
- y = 1;
- j = this.cols;
- if (j < x) {
- ch = [this.defAttr, ' ', 1];
- i = this.lines.length;
- while (i--) {
- while (this.lines.get(i).length < x) {
- this.lines.get(i).push(ch);
- }
- }
- }
- this.cols = x;
- this.setupStops(this.cols);
- j = this.rows;
- addToY = 0;
- if (j < y) {
- el = this.element;
- while (j++ < y) {
- if (this.lines.length < y + this.ybase) {
- if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
- this.ybase--;
- addToY++;
- if (this.ydisp > 0) {
- this.ydisp--;
- }
- }
- else {
- this.lines.push(this.blankLine());
- }
- }
- if (this.children.length < y) {
- this.insertRow();
- }
- }
- }
- else {
- while (j-- > y) {
- if (this.lines.length > y + this.ybase) {
- if (this.lines.length > this.ybase + this.y + 1) {
- this.lines.pop();
- }
- else {
- this.ybase++;
- this.ydisp++;
- }
- }
- if (this.children.length > y) {
- el = this.children.shift();
- if (!el)
- continue;
- el.parentNode.removeChild(el);
- }
- }
- }
- this.rows = y;
- if (this.y >= y) {
- this.y = y - 1;
- }
- if (addToY) {
- this.y += addToY;
- }
- if (this.x >= x) {
- this.x = x - 1;
- }
- this.scrollTop = 0;
- this.scrollBottom = y - 1;
- this.charMeasure.measure();
- this.refresh(0, this.rows - 1);
- this.normal = null;
- this.geometry = [this.cols, this.rows];
- this.emit('resize', { terminal: this, cols: x, rows: y });
-};
-Terminal.prototype.updateRange = function (y) {
- if (y < this.refreshStart)
- this.refreshStart = y;
- if (y > this.refreshEnd)
- this.refreshEnd = y;
-};
-Terminal.prototype.maxRange = function () {
- this.refreshStart = 0;
- this.refreshEnd = this.rows - 1;
-};
-Terminal.prototype.setupStops = function (i) {
- if (i != null) {
- if (!this.tabs[i]) {
- i = this.prevStop(i);
- }
- }
- else {
- this.tabs = {};
- i = 0;
- }
- for (; i < this.cols; i += this.getOption('tabStopWidth')) {
- this.tabs[i] = true;
- }
-};
-Terminal.prototype.prevStop = function (x) {
- if (x == null)
- x = this.x;
- while (!this.tabs[--x] && x > 0)
- ;
- return x >= this.cols
- ? this.cols - 1
- : x < 0 ? 0 : x;
-};
-Terminal.prototype.nextStop = function (x) {
- if (x == null)
- x = this.x;
- while (!this.tabs[++x] && x < this.cols)
- ;
- return x >= this.cols
- ? this.cols - 1
- : x < 0 ? 0 : x;
-};
-Terminal.prototype.eraseRight = function (x, y) {
- var line = this.lines.get(this.ybase + y);
- if (!line) {
- return;
- }
- var ch = [this.eraseAttr(), ' ', 1];
- for (; x < this.cols; x++) {
- line[x] = ch;
- }
- this.updateRange(y);
-};
-Terminal.prototype.eraseLeft = function (x, y) {
- var line = this.lines.get(this.ybase + y);
- if (!line) {
- return;
- }
- var ch = [this.eraseAttr(), ' ', 1];
- x++;
- while (x--) {
- line[x] = ch;
- }
- this.updateRange(y);
-};
-Terminal.prototype.clear = function () {
- if (this.ybase === 0 && this.y === 0) {
- return;
- }
- this.lines.set(0, this.lines.get(this.ybase + this.y));
- this.lines.length = 1;
- this.ydisp = 0;
- this.ybase = 0;
- this.y = 0;
- for (var i = 1; i < this.rows; i++) {
- this.lines.push(this.blankLine());
- }
- this.refresh(0, this.rows - 1);
- this.emit('scroll', this.ydisp);
-};
-Terminal.prototype.eraseLine = function (y) {
- this.eraseRight(0, y);
-};
-Terminal.prototype.blankLine = function (cur) {
- var attr = cur
- ? this.eraseAttr()
- : this.defAttr;
- var ch = [attr, ' ', 1], line = [], i = 0;
- for (; i < this.cols; i++) {
- line[i] = ch;
- }
- return line;
-};
-Terminal.prototype.ch = function (cur) {
- return cur
- ? [this.eraseAttr(), ' ', 1]
- : [this.defAttr, ' ', 1];
-};
-Terminal.prototype.is = function (term) {
- var name = this.termName;
- return (name + '').indexOf(term) === 0;
-};
-Terminal.prototype.handler = function (data) {
- if (this.options.disableStdin) {
- return;
- }
- if (this.ybase !== this.ydisp) {
- this.scrollToBottom();
- }
- this.emit('data', data);
-};
-Terminal.prototype.handleTitle = function (title) {
- this.emit('title', title);
-};
-Terminal.prototype.index = function () {
- this.y++;
- if (this.y > this.scrollBottom) {
- this.y--;
- this.scroll();
- }
- if (this.x >= this.cols) {
- this.x--;
- }
-};
-Terminal.prototype.reverseIndex = function () {
- var j;
- if (this.y === this.scrollTop) {
- this.lines.shiftElements(this.y + this.ybase, this.rows - 1, 1);
- this.lines.set(this.y + this.ybase, this.blankLine(true));
- this.updateRange(this.scrollTop);
- this.updateRange(this.scrollBottom);
- }
- else {
- this.y--;
- }
-};
-Terminal.prototype.reset = function () {
- this.options.rows = this.rows;
- this.options.cols = this.cols;
- var customKeydownHandler = this.customKeydownHandler;
- var cursorBlinkInterval = this.cursorBlinkInterval;
- Terminal.call(this, this.options);
- this.customKeydownHandler = customKeydownHandler;
- this.cursorBlinkInterval = cursorBlinkInterval;
- this.refresh(0, this.rows - 1);
- this.viewport.syncScrollArea();
-};
-Terminal.prototype.tabSet = function () {
- this.tabs[this.x] = true;
-};
-function on(el, type, handler, capture) {
- if (!Array.isArray(el)) {
- el = [el];
- }
- el.forEach(function (element) {
- element.addEventListener(type, handler, capture || false);
- });
-}
-function off(el, type, handler, capture) {
- el.removeEventListener(type, handler, capture || false);
-}
-function cancel(ev, force) {
- if (!this.cancelEvents && !force) {
- return;
- }
- ev.preventDefault();
- ev.stopPropagation();
- return false;
-}
-function inherits(child, parent) {
- function f() {
- this.constructor = child;
- }
- f.prototype = parent.prototype;
- child.prototype = new f;
-}
-function indexOf(obj, el) {
- var i = obj.length;
- while (i--) {
- if (obj[i] === el)
- return i;
- }
- return -1;
-}
-function isThirdLevelShift(term, ev) {
- var thirdLevelKey = (term.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
- (term.browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
- if (ev.type == 'keypress') {
- return thirdLevelKey;
- }
- return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
-}
-Terminal.prototype.matchColor = matchColor;
-function matchColor(r1, g1, b1) {
- var hash = (r1 << 16) | (g1 << 8) | b1;
- if (matchColor._cache[hash] != null) {
- return matchColor._cache[hash];
- }
- var ldiff = Infinity, li = -1, i = 0, c, r2, g2, b2, diff;
- for (; i < Terminal.vcolors.length; i++) {
- c = Terminal.vcolors[i];
- r2 = c[0];
- g2 = c[1];
- b2 = c[2];
- diff = matchColor.distance(r1, g1, b1, r2, g2, b2);
- if (diff === 0) {
- li = i;
- break;
- }
- if (diff < ldiff) {
- ldiff = diff;
- li = i;
- }
- }
- return matchColor._cache[hash] = li;
-}
-matchColor._cache = {};
-matchColor.distance = function (r1, g1, b1, r2, g2, b2) {
- return Math.pow(30 * (r1 - r2), 2)
- + Math.pow(59 * (g1 - g2), 2)
- + Math.pow(11 * (b1 - b2), 2);
-};
-function each(obj, iter, con) {
- if (obj.forEach)
- return obj.forEach(iter, con);
- for (var i = 0; i < obj.length; i++) {
- iter.call(con, obj[i], i, obj);
- }
-}
-function wasMondifierKeyOnlyEvent(ev) {
- return ev.keyCode === 16 ||
- ev.keyCode === 17 ||
- ev.keyCode === 18;
-}
-function keys(obj) {
- if (Object.keys)
- return Object.keys(obj);
- var key, keys = [];
- for (key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
- keys.push(key);
- }
- }
- return keys;
-}
-Terminal.EventEmitter = EventEmitter_1.EventEmitter;
-Terminal.inherits = inherits;
-Terminal.on = on;
-Terminal.off = off;
-Terminal.cancel = cancel;
-module.exports = Terminal;
-
-
-
-},{"./CompositionHelper":2,"./EscapeSequences":3,"./EventEmitter":4,"./InputHandler":5,"./Linkifier":6,"./Parser":7,"./Renderer":8,"./Viewport":9,"./handlers/Clipboard":10,"./utils/Browser":11,"./utils/CharMeasure":12,"./utils/CircularList":13,"./utils/Mouse":16}]},{},[17])(17)
-});
-//# sourceMappingURL=xterm.js.map
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
index abb4457fdac..894c2d3db3c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
@@ -30,7 +30,7 @@ TestRunner.setupStartupTest = function(path) {
};
TestRunner._executeTestScript = function() {
- const testScriptURL = /** @type {string} */ (Runtime.queryParam('test'));
+ const testScriptURL = /** @type {string} */ (Root.Runtime.queryParam('test'));
fetch(testScriptURL)
.then(data => data.text())
.then(testScript => {
@@ -39,17 +39,19 @@ TestRunner._executeTestScript = function() {
TestRunner.completeTest = () => console.log('Test completed');
// Auto-start unit tests
- if (!self.testRunner)
+ if (!self.testRunner) {
eval(`(function test(){${testScript}})()\n//# sourceURL=${testScriptURL}`);
- else
+ } else {
self.eval(`function test(){${testScript}}\n//# sourceURL=${testScriptURL}`);
+ }
return;
}
// Convert the test script into an expression (if needed)
testScript = testScript.trimRight();
- if (testScript.endsWith(';'))
+ if (testScript.endsWith(';')) {
testScript = testScript.slice(0, testScript.length - 1);
+ }
(async function() {
try {
@@ -107,10 +109,12 @@ TestRunner.addResult = function(text) {
* @param {!Array<string>} textArray
*/
TestRunner.addResults = function(textArray) {
- if (!textArray)
+ if (!textArray) {
return;
- for (let i = 0, size = textArray.length; i < size; ++i)
+ }
+ for (let i = 0, size = textArray.length; i < size; ++i) {
TestRunner.addResult(textArray[i]);
+ }
};
/**
@@ -127,8 +131,9 @@ TestRunner.runTests = function(tests) {
}
TestRunner.addResult('\ntest: ' + test.name);
let testPromise = test();
- if (!(testPromise instanceof Promise))
+ if (!(testPromise instanceof Promise)) {
testPromise = Promise.resolve();
+ }
testPromise.then(nextTest);
}
};
@@ -143,16 +148,18 @@ TestRunner.addSniffer = function(receiver, methodName, override, opt_sticky) {
override = TestRunner.safeWrap(override);
const original = receiver[methodName];
- if (typeof original !== 'function')
+ if (typeof original !== 'function') {
throw new Error('Cannot find method to override: ' + methodName);
+ }
receiver[methodName] = function(var_args) {
let result;
try {
result = original.apply(this, arguments);
} finally {
- if (!opt_sticky)
+ if (!opt_sticky) {
receiver[methodName] = original;
+ }
}
// In case of exception the override won't be called.
try {
@@ -208,8 +215,9 @@ TestRunner._resolveOnFinishInits;
TestRunner.loadModule = async function(module) {
const promise = new Promise(resolve => TestRunner._resolveOnFinishInits = resolve);
await self.runtime.loadModulePromise(module);
- if (!TestRunner._pendingInits)
+ if (!TestRunner._pendingInits) {
return;
+ }
return promise;
};
@@ -253,17 +261,19 @@ TestRunner.safeWrap = function(func, onexception) {
* @this {*}
*/
function result() {
- if (!func)
+ if (!func) {
return;
+ }
const wrapThis = this;
try {
return func.apply(wrapThis, arguments);
} catch (e) {
TestRunner.addResult('Exception while running: ' + func + '\n' + (e.stack || e));
- if (onexception)
+ if (onexception) {
TestRunner.safeWrap(onexception)();
- else
+ } else {
TestRunner.completeTest();
+ }
}
}
return result;
@@ -281,8 +291,9 @@ TestRunner.safeAsyncWrap = function(func) {
* @this {*}
*/
async function result() {
- if (!func)
+ if (!func) {
return;
+ }
const wrapThis = this;
try {
return await func.apply(wrapThis, arguments);
@@ -303,8 +314,9 @@ TestRunner.textContentWithLineBreaks = function(node) {
let result = 0;
while (currentNode && currentNode !== node) {
if (currentNode.nodeName === 'OL' &&
- !(currentNode.classList && currentNode.classList.contains('object-properties-section')))
+ !(currentNode.classList && currentNode.classList.contains('object-properties-section'))) {
++result;
+ }
currentNode = currentNode.parentNode;
}
return Array(result * 4 + 1).join(' ');
@@ -318,10 +330,11 @@ TestRunner.textContentWithLineBreaks = function(node) {
if (currentNode.nodeType === Node.TEXT_NODE) {
buffer += currentNode.nodeValue;
} else if (currentNode.nodeName === 'LI' || currentNode.nodeName === 'TR') {
- if (!ignoreFirst)
+ if (!ignoreFirst) {
buffer += '\n' + padding(currentNode);
- else
+ } else {
ignoreFirst = false;
+ }
} else if (currentNode.nodeName === 'STYLE') {
currentNode = currentNode.traverseNextNode(node);
continue;
@@ -341,10 +354,11 @@ TestRunner.textContentWithoutStyles = function(node) {
let currentNode = node;
while (currentNode.traverseNextNode(node)) {
currentNode = currentNode.traverseNextNode(node);
- if (currentNode.nodeType === Node.TEXT_NODE)
+ if (currentNode.nodeType === Node.TEXT_NODE) {
buffer += currentNode.nodeValue;
- else if (currentNode.nodeName === 'STYLE')
+ } else if (currentNode.nodeName === 'STYLE') {
currentNode = currentNode.traverseNextNode(node);
+ }
}
return buffer;
};
@@ -407,14 +421,14 @@ TestRunner._evaluateInPageCounter = 0;
/**
* @param {string} code
- * @return {!Promise<{response: !SDK.RemoteObject,
+ * @return {!Promise<undefined|{response: (!SDK.RemoteObject|undefined),
* exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)}>}
*/
TestRunner._evaluateInPage = async function(code) {
const lines = new Error().stack.split('at ');
// Handles cases where the function is safe wrapped
- const testScriptURL = /** @type {string} */ (Runtime.queryParam('test'));
+ const testScriptURL = /** @type {string} */ (Root.Runtime.queryParam('test'));
const functionLine = lines.reduce((acc, line) => line.includes(testScriptURL) ? line : acc, lines[lines.length - 2]);
const components = functionLine.trim().split('/');
@@ -423,8 +437,9 @@ TestRunner._evaluateInPage = async function(code) {
const sourceURL = `test://evaluations/${TestRunner._evaluateInPageCounter++}/` + fileName;
const lineOffset = parseInt(source[1], 10);
code = '\n'.repeat(lineOffset - 1) + code;
- if (code.indexOf('sourceURL=') === -1)
+ if (code.indexOf('sourceURL=') === -1) {
code += `//# sourceURL=${sourceURL}`;
+ }
const response = await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console'});
const error = response[Protocol.Error];
if (error) {
@@ -445,8 +460,9 @@ TestRunner._evaluateInPage = async function(code) {
TestRunner.evaluateInPageAnonymously = async function(code, userGesture) {
const response =
await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console', userGesture});
- if (!response[Protocol.Error])
+ if (!response[Protocol.Error]) {
return response.result.value;
+ }
TestRunner.addResult(
'Error: ' +
(response.exceptionDetails && response.exceptionDetails.text || 'exception from evaluateInPageAnonymously.'));
@@ -470,8 +486,9 @@ TestRunner.evaluateInPageAsync = async function(code) {
{expression: code, objectGroup: 'console', includeCommandLineAPI: false, awaitPromise: true});
const error = response[Protocol.Error];
- if (!error && !response.exceptionDetails)
+ if (!error && !response.exceptionDetails) {
return response.result.value;
+ }
TestRunner.addResult(
'Error: ' +
(error || response.exceptionDetails && response.exceptionDetails.text || 'exception while evaluation in page.'));
@@ -523,8 +540,9 @@ TestRunner.evaluateFunctionInOverlay = function(func, callback) {
* @param {string} failureText
*/
TestRunner.check = function(passCondition, failureText) {
- if (!passCondition)
+ if (!passCondition) {
TestRunner.addResult('FAIL: ' + failureText);
+ }
};
/**
@@ -546,10 +564,11 @@ TestRunner.loadHTML = function(html) {
// <!DOCTYPE...> tag needs to be first
const doctypeRegex = /(<!DOCTYPE.*?>)/i;
const baseTag = `<base href="${TestRunner.url()}">`;
- if (html.match(doctypeRegex))
+ if (html.match(doctypeRegex)) {
html = html.replace(doctypeRegex, '$1' + baseTag);
- else
+ } else {
html = baseTag + html;
+ }
}
html = html.replace(/'/g, '\\\'').replace(/\n/g, '\\n');
return TestRunner.evaluateInPageAnonymously(`document.write(\`${html}\`);document.close();`);
@@ -577,14 +596,13 @@ TestRunner.addScriptTag = function(path) {
TestRunner.addStylesheetTag = function(path) {
return TestRunner.evaluateInPageAsync(`
(function(){
- let link = document.createElement('link');
+ const link = document.createElement('link');
link.rel = 'stylesheet';
- link.type = 'text/css';
link.href = '${path}';
link.onload = onload;
document.head.append(link);
let resolve;
- let promise = new Promise(r => resolve = r);
+ const promise = new Promise(r => resolve = r);
function onload() {
// TODO(chenwilliam): It shouldn't be necessary to force
// style recalc here but some tests rely on it.
@@ -603,10 +621,10 @@ TestRunner.addStylesheetTag = function(path) {
TestRunner.addHTMLImport = function(path) {
return TestRunner.evaluateInPageAsync(`
(function(){
- let link = document.createElement('link');
+ const link = document.createElement('link');
link.rel = 'import';
link.href = '${path}';
- let promise = new Promise(r => link.onload = r);
+ const promise = new Promise(r => link.onload = r);
document.body.append(link);
return promise;
})();
@@ -626,7 +644,7 @@ TestRunner.addIframe = function(path, options = {}) {
options.name = options.name || '';
return TestRunner.evaluateInPageAsync(`
(function(){
- let iframe = document.createElement('iframe');
+ const iframe = document.createElement('iframe');
iframe.src = '${path}';
iframe.id = '${options.id}';
iframe.name = '${options.name}';
@@ -657,8 +675,9 @@ TestRunner.deprecatedInitAsync = async function(code) {
TestRunner._pendingInits++;
await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console'});
TestRunner._pendingInits--;
- if (!TestRunner._pendingInits)
+ if (!TestRunner._pendingInits) {
TestRunner._resolveOnFinishInits();
+ }
};
/**
@@ -698,8 +717,9 @@ TestRunner.formatters.formatAsTypeName = function(value) {
* @return {string}
*/
TestRunner.formatters.formatAsTypeNameOrNull = function(value) {
- if (value === null)
+ if (value === null) {
return 'null';
+ }
return TestRunner.formatters.formatAsTypeName(value);
};
@@ -708,8 +728,9 @@ TestRunner.formatters.formatAsTypeNameOrNull = function(value) {
* @return {string|!Date}
*/
TestRunner.formatters.formatAsRecentTime = function(value) {
- if (typeof value !== 'object' || !(value instanceof Date))
+ if (typeof value !== 'object' || !(value instanceof Date)) {
return TestRunner.formatters.formatAsTypeName(value);
+ }
const delta = Date.now() - value;
return 0 <= delta && delta < 30 * 60 * 1000 ? '<plausible>' : value;
};
@@ -719,11 +740,13 @@ TestRunner.formatters.formatAsRecentTime = function(value) {
* @return {string}
*/
TestRunner.formatters.formatAsURL = function(value) {
- if (!value)
+ if (!value) {
return value;
+ }
const lastIndex = value.lastIndexOf('devtools/');
- if (lastIndex < 0)
+ if (lastIndex < 0) {
return value;
+ }
return '.../' + value.substr(lastIndex);
};
@@ -732,8 +755,9 @@ TestRunner.formatters.formatAsURL = function(value) {
* @return {string}
*/
TestRunner.formatters.formatAsDescription = function(value) {
- if (!value)
+ if (!value) {
return value;
+ }
return '"' + value.replace(/^function [gs]et /, 'function ') + '"';
};
@@ -756,8 +780,9 @@ TestRunner.addObject = function(object, customFormatters, prefix, firstLinePrefi
propertyNames.sort();
for (let i = 0; i < propertyNames.length; ++i) {
const prop = propertyNames[i];
- if (!object.hasOwnProperty(prop))
+ if (!object.hasOwnProperty(prop)) {
continue;
+ }
const prefixWithName = ' ' + prefix + prop + ' : ';
const propValue = object[prop];
if (customFormatters && customFormatters[prop]) {
@@ -783,8 +808,9 @@ TestRunner.addArray = function(array, customFormatters, prefix, firstLinePrefix)
prefix = prefix || '';
firstLinePrefix = firstLinePrefix || prefix;
TestRunner.addResult(firstLinePrefix + '[');
- for (let i = 0; i < array.length; ++i)
+ for (let i = 0; i < array.length; ++i) {
TestRunner.dump(array[i], customFormatters, prefix + ' ');
+ }
TestRunner.addResult(prefix + ']');
};
@@ -799,21 +825,25 @@ TestRunner.dumpDeepInnerHTML = function(node) {
function innerHTML(prefix, node) {
const openTag = [];
if (node.nodeType === Node.TEXT_NODE) {
- if (!node.parentElement || node.parentElement.nodeName !== 'STYLE')
+ if (!node.parentElement || node.parentElement.nodeName !== 'STYLE') {
TestRunner.addResult(node.nodeValue);
+ }
return;
}
openTag.push('<' + node.nodeName);
const attrs = node.attributes;
- for (let i = 0; attrs && i < attrs.length; ++i)
+ for (let i = 0; attrs && i < attrs.length; ++i) {
openTag.push(attrs[i].name + '=' + attrs[i].value);
+ }
openTag.push('>');
TestRunner.addResult(prefix + openTag.join(' '));
- for (let child = node.firstChild; child; child = child.nextSibling)
+ for (let child = node.firstChild; child; child = child.nextSibling) {
innerHTML(prefix + ' ', child);
- if (node.shadowRoot)
+ }
+ if (node.shadowRoot) {
innerHTML(prefix + ' ', node.shadowRoot);
+ }
TestRunner.addResult(prefix + '</' + node.nodeName + '>');
}
innerHTML('', node);
@@ -824,16 +854,20 @@ TestRunner.dumpDeepInnerHTML = function(node) {
* @return {string}
*/
TestRunner.deepTextContent = function(node) {
- if (!node)
+ if (!node) {
return '';
- if (node.nodeType === Node.TEXT_NODE && node.nodeValue)
+ }
+ if (node.nodeType === Node.TEXT_NODE && node.nodeValue) {
return !node.parentElement || node.parentElement.nodeName !== 'STYLE' ? node.nodeValue : '';
+ }
let res = '';
const children = node.childNodes;
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
res += TestRunner.deepTextContent(children[i]);
- if (node.shadowRoot)
+ }
+ if (node.shadowRoot) {
res += TestRunner.deepTextContent(node.shadowRoot);
+ }
return res;
};
@@ -849,16 +883,17 @@ TestRunner.dump = function(value, customFormatters, prefix, prefixWithName) {
TestRunner.addResult(prefixWithName + 'was skipped due to prefix length limit');
return;
}
- if (value === null)
+ if (value === null) {
TestRunner.addResult(prefixWithName + 'null');
- else if (value && value.constructor && value.constructor.name === 'Array')
+ } else if (value && value.constructor && value.constructor.name === 'Array') {
TestRunner.addArray(/** @type {!Array} */ (value), customFormatters, prefix, prefixWithName);
- else if (typeof value === 'object')
+ } else if (typeof value === 'object') {
TestRunner.addObject(/** @type {!Object} */ (value), customFormatters, prefix, prefixWithName);
- else if (typeof value === 'string')
+ } else if (typeof value === 'string') {
TestRunner.addResult(prefixWithName + '"' + value + '"');
- else
+ } else {
TestRunner.addResult(prefixWithName + value);
+ }
};
/**
@@ -877,25 +912,26 @@ TestRunner.dumpObjectPropertyTreeElement = function(treeElement) {
};
/**
- * @param {symbol} event
+ * @param {symbol} eventName
* @param {!Common.Object} obj
* @param {function(?):boolean=} condition
* @return {!Promise}
*/
-TestRunner.waitForEvent = function(event, obj, condition) {
+TestRunner.waitForEvent = function(eventName, obj, condition) {
condition = condition || function() {
return true;
};
return new Promise(resolve => {
- obj.addEventListener(event, onEventFired);
+ obj.addEventListener(eventName, onEventFired);
/**
* @param {!Common.Event} event
*/
function onEventFired(event) {
- if (!condition(event.data))
+ if (!condition(event.data)) {
return;
- obj.removeEventListener(event, onEventFired);
+ }
+ obj.removeEventListener(eventName, onEventFired);
resolve(event.data);
}
});
@@ -908,8 +944,9 @@ TestRunner.waitForEvent = function(event, obj, condition) {
TestRunner.waitForTarget = function(filter) {
filter = filter || (target => true);
for (const target of SDK.targetManager.targets()) {
- if (filter(target))
+ if (filter(target)) {
return Promise.resolve(target);
+ }
}
return new Promise(fulfill => {
const observer = /** @type {!SDK.TargetManager.Observer} */ ({
@@ -949,8 +986,9 @@ TestRunner.waitForTargetRemoved = function(targetToRemove) {
* @return {!Promise}
*/
TestRunner.waitForExecutionContext = function(runtimeModel) {
- if (runtimeModel.executionContexts().length)
+ if (runtimeModel.executionContexts().length) {
return Promise.resolve(runtimeModel.executionContexts()[0]);
+ }
return runtimeModel.once(SDK.RuntimeModel.Events.ExecutionContextCreated);
};
@@ -960,8 +998,9 @@ TestRunner.waitForExecutionContext = function(runtimeModel) {
*/
TestRunner.waitForExecutionContextDestroyed = function(context) {
const runtimeModel = context.runtimeModel;
- if (runtimeModel.executionContexts().indexOf(context) === -1)
+ if (runtimeModel.executionContexts().indexOf(context) === -1) {
return Promise.resolve();
+ }
return TestRunner.waitForEvent(
SDK.RuntimeModel.Events.ExecutionContextDestroyed, runtimeModel,
destroyedContext => destroyedContext === context);
@@ -973,8 +1012,9 @@ TestRunner.waitForExecutionContextDestroyed = function(context) {
* @param {string=} message
*/
TestRunner.assertGreaterOrEqual = function(a, b, message) {
- if (a < b)
+ if (a < b) {
TestRunner.addResult('FAILED: ' + (message ? message + ': ' : '') + a + ' < ' + b);
+ }
};
/**
@@ -1074,8 +1114,9 @@ TestRunner.waitForPageLoad = function(callback) {
TestRunner.runWhenPageLoads = function(callback) {
const oldCallback = TestRunner._pageLoadedCallback;
function chainedCallback() {
- if (oldCallback)
+ if (oldCallback) {
oldCallback();
+ }
callback();
}
TestRunner._pageLoadedCallback = TestRunner.safeWrap(chainedCallback);
@@ -1123,14 +1164,16 @@ TestRunner.runAsyncTestSuite = async function(testSuite) {
* @param {string} message
*/
TestRunner.assertEquals = function(expected, found, message) {
- if (expected === found)
+ if (expected === found) {
return;
+ }
let error;
- if (message)
+ if (message) {
error = 'Failure (' + message + '):';
- else
+ } else {
error = 'Failure:';
+ }
throw new Error(error + ' expected <' + expected + '> found <' + found + '>');
};
@@ -1153,8 +1196,9 @@ TestRunner.override = function(receiver, methodName, override, opt_sticky) {
override = TestRunner.safeWrap(override);
const original = receiver[methodName];
- if (typeof original !== 'function')
+ if (typeof original !== 'function') {
throw new Error('Cannot find method to override: ' + methodName);
+ }
receiver[methodName] = function(var_args) {
try {
@@ -1162,8 +1206,9 @@ TestRunner.override = function(receiver, methodName, override, opt_sticky) {
} catch (e) {
throw new Error('Exception in overriden method \'' + methodName + '\': ' + e);
} finally {
- if (!opt_sticky)
+ if (!opt_sticky) {
receiver[methodName] = original;
+ }
}
};
@@ -1251,7 +1296,7 @@ TestRunner.MockSetting = class {
};
/**
- * @return {!Array<!Runtime.Module>}
+ * @return {!Array<!Root.Runtime.Module>}
*/
TestRunner.loadedModules = function() {
return self.runtime._modules.filter(module => module._loadedForTest)
@@ -1260,8 +1305,8 @@ TestRunner.loadedModules = function() {
};
/**
- * @param {!Array<!Runtime.Module>} relativeTo
- * @return {!Array<!Runtime.Module>}
+ * @param {!Array<!Root.Runtime.Module>} relativeTo
+ * @return {!Array<!Root.Runtime.Module>}
*/
TestRunner.dumpLoadedModules = function(relativeTo) {
const previous = new Set(relativeTo || []);
@@ -1272,8 +1317,9 @@ TestRunner.dumpLoadedModules = function(relativeTo) {
TestRunner.addResult('Loaded modules:');
const loadedModules = TestRunner.loadedModules().sort(moduleSorter);
for (const module of loadedModules) {
- if (previous.has(module))
+ if (previous.has(module)) {
continue;
+ }
TestRunner.addResult(' ' + module._descriptor.name);
}
return loadedModules;
@@ -1290,18 +1336,22 @@ TestRunner.waitForUISourceCode = function(urlSuffix, projectType) {
* @return {boolean}
*/
function matches(uiSourceCode) {
- if (projectType && uiSourceCode.project().type() !== projectType)
+ if (projectType && uiSourceCode.project().type() !== projectType) {
return false;
- if (!projectType && uiSourceCode.project().type() === Workspace.projectTypes.Service)
+ }
+ if (!projectType && uiSourceCode.project().type() === Workspace.projectTypes.Service) {
return false;
- if (urlSuffix && !uiSourceCode.url().endsWith(urlSuffix))
+ }
+ if (urlSuffix && !uiSourceCode.url().endsWith(urlSuffix)) {
return false;
+ }
return true;
}
for (const uiSourceCode of Workspace.workspace.uiSourceCodes()) {
- if (urlSuffix && matches(uiSourceCode))
+ if (urlSuffix && matches(uiSourceCode)) {
return Promise.resolve(uiSourceCode);
+ }
}
return TestRunner.waitForEvent(Workspace.Workspace.Events.UISourceCodeAdded, Workspace.workspace, matches);
@@ -1319,7 +1369,7 @@ TestRunner.waitForUISourceCodeRemoved = function(callback) {
* @return {string}
*/
TestRunner.url = function(url = '') {
- const testScriptURL = /** @type {string} */ (Runtime.queryParam('test'));
+ const testScriptURL = /** @type {string} */ (Root.Runtime.queryParam('test'));
// This handles relative (e.g. "../file"), root (e.g. "/resource"),
// absolute (e.g. "http://", "data:") and empty (e.g. "") paths
@@ -1342,10 +1392,11 @@ TestRunner.dumpSyntaxHighlight = function(str, mimeType) {
const node_parts = [];
for (let i = 0; i < node.childNodes.length; i++) {
- if (node.childNodes[i].getAttribute)
+ if (node.childNodes[i].getAttribute) {
node_parts.push(node.childNodes[i].getAttribute('class'));
- else
+ } else {
node_parts.push('*');
+ }
}
TestRunner.addResult(str + ': ' + node_parts.join(', '));
@@ -1365,8 +1416,9 @@ TestRunner._consoleOutputHook = function(messageType) {
* messages printed at the top of the test expectation file (default behavior).
*/
TestRunner._printDevToolsConsole = function() {
- if (TestRunner._isDebugTest())
+ if (TestRunner._isDebugTest()) {
return;
+ }
console.log = TestRunner._consoleOutputHook.bind(TestRunner, 'log');
console.error = TestRunner._consoleOutputHook.bind(TestRunner, 'error');
console.info = TestRunner._consoleOutputHook.bind(TestRunner, 'info');
@@ -1392,12 +1444,16 @@ TestRunner._TestObserver = class {
* @override
*/
targetAdded(target) {
- if (TestRunner._startedTest)
+ if (target.id() === 'main') {
+ TestRunner._setupTestHelpers(target);
+ }
+ if (TestRunner._startedTest) {
return;
+ }
TestRunner._startedTest = true;
- TestRunner._setupTestHelpers(target);
- if (TestRunner._isStartupTest())
+ if (TestRunner._isStartupTest()) {
return;
+ }
TestRunner
.loadHTML(`
<head>
@@ -1420,14 +1476,14 @@ TestRunner._TestObserver = class {
* @return {boolean}
*/
TestRunner._isDebugTest = function() {
- return !self.testRunner || !!Runtime.queryParam('debugFrontend');
+ return !self.testRunner || !!Root.Runtime.queryParam('debugFrontend');
};
/**
* @return {boolean}
*/
TestRunner._isStartupTest = function() {
- return Runtime.queryParam('test').includes('/startup/');
+ return Root.Runtime.queryParam('test').includes('/startup/');
};
(async function() {
@@ -1446,8 +1502,9 @@ TestRunner._isStartupTest = function() {
self['onerror'] = completeTestOnError;
TestRunner._printDevToolsConsole();
SDK.targetManager.observeTargets(new TestRunner._TestObserver());
- if (!TestRunner._isStartupTest())
+ if (!TestRunner._isStartupTest()) {
return;
+ }
/**
* Startup test initialization:
* 1. Wait for DevTools app UI to load
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
index f3c027c23ce..0f7721a6d1b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -42,6 +42,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
this.registerRequiredCSS('cm/codemirror.css');
this.registerRequiredCSS('text_editor/cmdevtools.css');
+ const {indentWithTabs, indentUnit} =
+ TextEditor.CodeMirrorTextEditor._getIndentation(Common.moduleSetting('textEditorIndent').get());
+
this._codeMirror = new CodeMirror(this.element, {
devtoolsAccessibleName: options.devtoolsAccessibleName,
lineNumbers: options.lineNumbers,
@@ -50,7 +53,8 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
styleSelectedText: true,
electricChars: true,
styleActiveLine: true,
- indentUnit: 4,
+ indentUnit,
+ indentWithTabs,
lineWrapping: options.lineWrapping,
lineWiseCopyCut: false,
tabIndex: 0,
@@ -61,6 +65,8 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
this._codeMirror._codeMirrorTextEditor = this;
+ Common.moduleSetting('textEditorIndent').addChangeListener(this._updateIndentSize.bind(this));
+
CodeMirror.keyMap['devtools-common'] = {
'Left': 'goCharLeft',
'Right': 'goCharRight',
@@ -72,7 +78,7 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
'PageDown': 'goSmartPageDown',
'Delete': 'delCharAfter',
'Backspace': 'delCharBefore',
- 'Tab': 'defaultTab',
+ 'Tab': 'UserIndent',
'Shift-Tab': 'indentLessOrPass',
'Enter': 'newlineAndIndent',
'Ctrl-Space': 'autocomplete',
@@ -123,6 +129,8 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
'Ctrl-D': 'delCharAfter',
'Ctrl-K': 'killLine',
'Ctrl-T': 'transposeChars',
+ 'Ctrl-P': 'goLineUp',
+ 'Ctrl-N': 'goLineDown',
'Shift-Ctrl-Left': 'selectCamelLeft',
'Shift-Ctrl-Right': 'selectCamelRight',
'Cmd-Left': 'goLineStartSmart',
@@ -136,8 +144,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
fallthrough: 'devtools-common'
};
- if (options.bracketMatchingSetting)
+ if (options.bracketMatchingSetting) {
options.bracketMatchingSetting.addChangeListener(this._enableBracketMatchingIfNeeded, this);
+ }
this._enableBracketMatchingIfNeeded();
this._codeMirror.setOption('keyMap', Host.isMac() ? 'devtools-mac' : 'devtools-pc');
@@ -145,8 +154,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
this._codeMirror.setOption('flattenSpans', false);
let maxHighlightLength = options.maxHighlightLength;
- if (typeof maxHighlightLength !== 'number')
+ if (typeof maxHighlightLength !== 'number') {
maxHighlightLength = TextEditor.CodeMirrorTextEditor.maxHighlightLength;
+ }
this._codeMirror.setOption('maxHighlightLength', maxHighlightLength);
this._codeMirror.setOption('mode', null);
this._codeMirror.setOption('crudeMeasuringFrom', 1000);
@@ -169,8 +179,8 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
this._codeMirrorElement.classList.add('source-code');
this._codeMirrorElement.classList.add('fill');
- /** @type {!Multimap<number, !TextEditor.CodeMirrorTextEditor.Decoration>} */
- this._decorations = new Multimap();
+ /** @type {!Platform.Multimap<number, !TextEditor.CodeMirrorTextEditor.Decoration>} */
+ this._decorations = new Platform.Multimap();
this.element.addEventListener('keydown', this._handleKeyDown.bind(this), true);
this.element.addEventListener('keydown', this._handlePostKeyDown.bind(this), false);
@@ -180,10 +190,12 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
this._readOnly = false;
this._mimeType = '';
- if (options.mimeType)
+ if (options.mimeType) {
this.setMimeType(options.mimeType);
- if (options.autoHeight)
+ }
+ if (options.autoHeight) {
this._codeMirror.setSize(null, 'auto');
+ }
this._placeholderElement = null;
if (options.placeholder) {
@@ -199,8 +211,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
*/
static autocompleteCommand(codeMirror) {
const autocompleteController = codeMirror._codeMirrorTextEditor._autocompleteController;
- if (autocompleteController)
+ if (autocompleteController) {
autocompleteController.autocomplete(true);
+ }
}
/**
@@ -234,21 +247,32 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
/**
+ * @param {string} indentationValue
+ */
+ static _getIndentation(indentationValue) {
+ const indentWithTabs = /\t/.test(indentationValue);
+ const indentUnit = indentWithTabs ? 4 : indentationValue.length;
+ return {indentWithTabs, indentUnit};
+ }
+
+ /**
* @param {string} modeName
* @param {string} tokenPrefix
*/
static _overrideModeWithPrefixedTokens(modeName, tokenPrefix) {
const oldModeName = modeName + '-old';
- if (CodeMirror.modes[oldModeName])
+ if (CodeMirror.modes[oldModeName]) {
return;
+ }
CodeMirror.defineMode(oldModeName, CodeMirror.modes[modeName]);
CodeMirror.defineMode(modeName, modeConstructor);
function modeConstructor(config, parserConfig) {
const innerConfig = {};
- for (const i in parserConfig)
+ for (const i in parserConfig) {
innerConfig[i] = parserConfig[i];
+ }
innerConfig.name = oldModeName;
const codeMirrorMode = CodeMirror.getMode(config, innerConfig);
codeMirrorMode.name = modeName;
@@ -264,35 +288,38 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
/**
* @param {string} mimeType
- * @return {!Array<!Runtime.Extension>}}
+ * @return {!Array<!Root.Runtime.Extension>}}
*/
static _collectUninstalledModes(mimeType) {
const installed = TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions;
const nameToExtension = new Map();
const extensions = self.runtime.extensions(TextEditor.CodeMirrorMimeMode);
- for (const extension of extensions)
+ for (const extension of extensions) {
nameToExtension.set(extension.descriptor()['fileName'], extension);
+ }
const modesToLoad = new Set();
for (const extension of extensions) {
const descriptor = extension.descriptor();
- if (installed.has(extension) || descriptor['mimeTypes'].indexOf(mimeType) === -1)
+ if (installed.has(extension) || descriptor['mimeTypes'].indexOf(mimeType) === -1) {
continue;
+ }
modesToLoad.add(extension);
const deps = descriptor['dependencies'] || [];
for (let i = 0; i < deps.length; ++i) {
const extension = nameToExtension.get(deps[i]);
- if (extension && !installed.has(extension))
+ if (extension && !installed.has(extension)) {
modesToLoad.add(extension);
+ }
}
}
return Array.from(modesToLoad);
}
/**
- * @param {!Array<!Runtime.Extension>} extensions
+ * @param {!Array<!Root.Runtime.Extension>} extensions
* @return {!Promise}
*/
static _installMimeTypeModes(extensions) {
@@ -300,12 +327,13 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
return Promise.all(promises);
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @param {!Object} instance
*/
function installMode(extension, instance) {
- if (TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions.has(extension))
+ if (TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions.has(extension)) {
return;
+ }
const mode = /** @type {!TextEditor.CodeMirrorMimeMode} */ (instance);
mode.install(extension);
TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions.add(extension);
@@ -327,8 +355,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
const skippedText = codeMirror.getRange(newCursor, cursor, '#');
- if (/^\s+$/.test(skippedText))
+ if (/^\s+$/.test(skippedText)) {
codeMirror.execCommand('goGroupLeft');
+ }
codeMirror.setExtending(false);
}
@@ -343,8 +372,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
const skippedText = codeMirror.getRange(cursor, newCursor, '#');
- if (/^\s+$/.test(skippedText))
+ if (/^\s+$/.test(skippedText)) {
codeMirror.execCommand('goGroupRight');
+ }
codeMirror.setExtending(false);
}
@@ -464,34 +494,42 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
const text = this.line(lineNumber);
const length = text.length;
- if ((columnNumber === length && direction === 1) || (columnNumber === 0 && direction === -1))
+ if ((columnNumber === length && direction === 1) || (columnNumber === 0 && direction === -1)) {
return this._normalizePositionForOverlappingColumn(lineNumber, length, columnNumber + direction);
+ }
let charNumber = direction === 1 ? columnNumber : columnNumber - 1;
// Move through initial spaces if any.
- while (valid(charNumber, length) && TextUtils.TextUtils.isSpaceChar(text[charNumber]))
+ while (valid(charNumber, length) && TextUtils.TextUtils.isSpaceChar(text[charNumber])) {
charNumber += direction;
- if (!valid(charNumber, length))
+ }
+ if (!valid(charNumber, length)) {
return constrainPosition(lineNumber, length, charNumber);
+ }
if (TextUtils.TextUtils.isStopChar(text[charNumber])) {
- while (valid(charNumber, length) && TextUtils.TextUtils.isStopChar(text[charNumber]))
+ while (valid(charNumber, length) && TextUtils.TextUtils.isStopChar(text[charNumber])) {
charNumber += direction;
- if (!valid(charNumber, length))
+ }
+ if (!valid(charNumber, length)) {
return constrainPosition(lineNumber, length, charNumber);
+ }
return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
}
charNumber += direction;
while (valid(charNumber, length) && !isWordStart(text, charNumber) && !isWordEnd(text, charNumber) &&
- TextUtils.TextUtils.isWordChar(text[charNumber]))
+ TextUtils.TextUtils.isWordChar(text[charNumber])) {
charNumber += direction;
+ }
- if (!valid(charNumber, length))
+ if (!valid(charNumber, length)) {
return constrainPosition(lineNumber, length, charNumber);
- if (isWordStart(text, charNumber) || isWordEnd(text, charNumber))
+ }
+ if (isWordStart(text, charNumber) || isWordEnd(text, charNumber)) {
return {lineNumber: lineNumber, columnNumber: charNumber};
+ }
return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
@@ -508,15 +546,17 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
const move = this._camelCaseMoveFromPosition(selection.endLine, selection.endColumn, direction);
selection.endLine = move.lineNumber;
selection.endColumn = move.columnNumber;
- if (!shift)
+ if (!shift) {
selections[i] = selection.collapseToEnd();
+ }
}
this.setSelections(selections);
}
dispose() {
- if (this._options.bracketMatchingSetting)
+ if (this._options.bracketMatchingSetting) {
this._options.bracketMatchingSetting.removeChangeListener(this._enableBracketMatchingIfNeeded, this);
+ }
}
_enableBracketMatchingIfNeeded() {
@@ -530,8 +570,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @override
*/
wasShown() {
- if (this._needsRefresh)
+ if (this._needsRefresh) {
this.refresh();
+ }
}
/**
@@ -569,16 +610,18 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
e.consume(false);
return;
}
- if (this._autocompleteController && this._autocompleteController.keyDown(e))
+ if (this._autocompleteController && this._autocompleteController.keyDown(e)) {
e.consume(true);
+ }
}
/**
* @param {!Event} e
*/
_handlePostKeyDown(e) {
- if (e.defaultPrevented)
+ if (e.defaultPrevented) {
e.consume(true);
+ }
}
/**
@@ -591,8 +634,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
delete this._autocompleteController;
}
- if (config)
+ if (config) {
this._autocompleteController = new TextEditor.TextEditorAutocompleteController(this, this._codeMirror, config);
+ }
}
/**
@@ -602,8 +646,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
*/
cursorPositionToCoordinates(lineNumber, column) {
if (lineNumber >= this._codeMirror.lineCount() || lineNumber < 0 || column < 0 ||
- column > this._codeMirror.getLine(lineNumber).length)
+ column > this._codeMirror.getLine(lineNumber).length) {
return null;
+ }
const metrics = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, column));
return {x: metrics.left, y: metrics.top, height: metrics.bottom - metrics.top};
}
@@ -615,12 +660,14 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
*/
coordinatesToCursorPosition(x, y) {
const element = this.element.ownerDocument.elementFromPoint(x, y);
- if (!element || !element.isSelfOrDescendant(this._codeMirror.getWrapperElement()))
+ if (!element || !element.isSelfOrDescendant(this._codeMirror.getWrapperElement())) {
return null;
+ }
const gutterBox = this._codeMirror.getGutterElement().boxInWindow();
if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width && y >= gutterBox.y &&
- y <= gutterBox.y + gutterBox.height)
+ y <= gutterBox.y + gutterBox.height) {
return null;
+ }
const coords = this._codeMirror.coordsChar({left: x, top: y});
return TextEditor.CodeMirrorUtils.toRange(coords, coords);
}
@@ -643,11 +690,13 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @return {?{startColumn: number, endColumn: number, type: string}}
*/
tokenAtTextPosition(lineNumber, columnNumber) {
- if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount())
+ if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount()) {
return null;
+ }
const token = this._codeMirror.getTokenAt(new CodeMirror.Pos(lineNumber, (columnNumber || 0) + 1));
- if (!token)
+ if (!token) {
return null;
+ }
return {startColumn: token.start, endColumn: token.end, type: token.type};
}
@@ -671,8 +720,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
*/
_hasLongLines() {
function lineIterator(lineHandle) {
- if (lineHandle.text.length > TextEditor.CodeMirrorTextEditor.LongLineModeLineLengthThreshold)
+ if (lineHandle.text.length > TextEditor.CodeMirrorTextEditor.LongLineModeLineLengthThreshold) {
hasLongLines = true;
+ }
return hasLongLines;
}
let hasLongLines = false;
@@ -689,24 +739,37 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
/**
+ * @param {!{data: *}} updatedValue
+ */
+ _updateIndentSize(updatedValue) {
+ const {indentWithTabs, indentUnit} =
+ TextEditor.CodeMirrorTextEditor._getIndentation(/** @type {string} */ (updatedValue.data));
+
+ this._codeMirror.setOption('indentUnit', indentUnit);
+ this._codeMirror.setOption('indentWithTabs', indentWithTabs);
+ }
+
+ /**
* @param {string} mimeType
*/
setMimeType(mimeType) {
this._mimeType = mimeType;
const modesToLoad = TextEditor.CodeMirrorTextEditor._collectUninstalledModes(mimeType);
- if (!modesToLoad.length)
+ if (!modesToLoad.length) {
setMode.call(this);
- else
+ } else {
TextEditor.CodeMirrorTextEditor._installMimeTypeModes(modesToLoad).then(setMode.bind(this));
+ }
/**
* @this {TextEditor.CodeMirrorTextEditor}
*/
function setMode() {
const rewrittenMimeType = this.rewriteMimeType(mimeType);
- if (this._codeMirror.options.mode !== rewrittenMimeType)
+ if (this._codeMirror.options.mode !== rewrittenMimeType) {
this._codeMirror.setOption('mode', rewrittenMimeType);
+ }
}
}
@@ -739,8 +802,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @param {boolean} readOnly
*/
setReadOnly(readOnly) {
- if (this._readOnly === readOnly)
+ if (this._readOnly === readOnly) {
return;
+ }
this.clearPositionHighlight();
this._readOnly = readOnly;
this.element.classList.toggle('CodeMirror-readonly', readOnly);
@@ -802,8 +866,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
const bookmarks = [];
for (let i = 0; i < markers.length; i++) {
const bookmark = markers[i][TextEditor.TextEditorBookMark._symbol];
- if (bookmark && (!type || bookmark.type() === type))
+ if (bookmark && (!type || bookmark.type() === type)) {
bookmarks.push(bookmark);
+ }
}
return bookmarks;
}
@@ -864,8 +929,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
const widget = this._codeMirror.addLineWidget(lineNumber, element);
let update = null;
if (typeof startColumn !== 'undefined') {
- if (typeof endColumn === 'undefined')
+ if (typeof endColumn === 'undefined') {
endColumn = Infinity;
+ }
update = this._updateFloatingDecoration.bind(this, element, lineNumber, startColumn, endColumn);
update();
}
@@ -897,8 +963,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @param {!TextEditor.CodeMirrorTextEditor.Decoration} decoration
*/
function innerUpdateDecorations(decoration) {
- if (decoration.update)
+ if (decoration.update) {
decoration.update();
+ }
}
}
@@ -914,8 +981,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @param {!TextEditor.CodeMirrorTextEditor.Decoration} decoration
*/
function innerRemoveDecoration(decoration) {
- if (decoration.element !== element)
+ if (decoration.element !== element) {
return;
+ }
this._codeMirror.removeLineWidget(decoration.widget);
this._decorations.delete(lineNumber, decoration);
}
@@ -928,27 +996,31 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
*/
revealPosition(lineNumber, columnNumber, shouldHighlight) {
lineNumber = Number.constrain(lineNumber, 0, this._codeMirror.lineCount() - 1);
- if (typeof columnNumber !== 'number')
+ if (typeof columnNumber !== 'number') {
columnNumber = 0;
+ }
columnNumber = Number.constrain(columnNumber, 0, this._codeMirror.getLine(lineNumber).length);
this.clearPositionHighlight();
this._highlightedLine = this._codeMirror.getLineHandle(lineNumber);
- if (!this._highlightedLine)
+ if (!this._highlightedLine) {
return;
+ }
this.scrollLineIntoView(lineNumber);
if (shouldHighlight) {
this._codeMirror.addLineClass(
this._highlightedLine, null, this._readOnly ? 'cm-readonly-highlight' : 'cm-highlight');
- if (!this._readOnly)
+ if (!this._readOnly) {
this._clearHighlightTimeout = setTimeout(this.clearPositionHighlight.bind(this), 2000);
+ }
}
this.setSelection(TextUtils.TextRange.createFromLocation(lineNumber, columnNumber));
}
clearPositionHighlight() {
- if (this._clearHighlightTimeout)
+ if (this._clearHighlightTimeout) {
clearTimeout(this._clearHighlightTimeout);
+ }
delete this._clearHighlightTimeout;
if (this._highlightedLine) {
@@ -971,8 +1043,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @param {number} height
*/
_updatePaddingBottom(width, height) {
- if (!this._options.padBottom)
+ if (!this._options.padBottom) {
return;
+ }
const scrollInfo = this._codeMirror.getScrollInfo();
let newPaddingBottom;
const linesElement = this._codeMirrorElement.querySelector('.CodeMirror-lines');
@@ -990,8 +1063,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
_resizeEditor() {
const parentElement = this.element.parentElement;
- if (!parentElement || !this.isShowing())
+ if (!parentElement || !this.isShowing()) {
return;
+ }
this._codeMirror.operation(() => {
const scrollLeft = this._codeMirror.doc.scrollLeft;
const scrollTop = this._codeMirror.doc.scrollTop;
@@ -1011,8 +1085,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @override
*/
onResize() {
- if (this._autocompleteController)
+ if (this._autocompleteController) {
this._autocompleteController.clearAutocomplete();
+ }
this._resizeEditor();
this._editorSizeInSync = true;
if (this._selectionSetScheduled) {
@@ -1040,8 +1115,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @override
*/
clearAutocomplete() {
- if (this._autocompleteController)
+ if (this._autocompleteController) {
this._autocompleteController.clearAutocomplete();
+ }
}
/**
@@ -1055,12 +1131,14 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
let wordStart = column;
if (column !== 0 && isWordChar(line.charAt(column - 1))) {
wordStart = column - 1;
- while (wordStart > 0 && isWordChar(line.charAt(wordStart - 1)))
+ while (wordStart > 0 && isWordChar(line.charAt(wordStart - 1))) {
--wordStart;
+ }
}
let wordEnd = column;
- while (wordEnd < line.length && isWordChar(line.charAt(wordEnd)))
+ while (wordEnd < line.length && isWordChar(line.charAt(wordEnd))) {
++wordEnd;
+ }
return new TextUtils.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
}
@@ -1069,15 +1147,17 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @param {!Array.<!CodeMirror.ChangeObject>} changes
*/
_changes(codeMirror, changes) {
- if (!changes.length)
+ if (!changes.length) {
return;
+ }
this._updatePlaceholder();
// We do not show "scroll beyond end of file" span for one line documents, so we need to check if "document has one line" changed.
const hasOneLine = this._codeMirror.lineCount() === 1;
- if (hasOneLine !== this._hasOneLine)
+ if (hasOneLine !== this._hasOneLine) {
this._resizeEditor();
+ }
this._hasOneLine = hasOneLine;
this._decorations.valuesArray().forEach(decoration => this._codeMirror.removeLineWidget(decoration.widget));
@@ -1232,13 +1312,15 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
this._detectLineSeparator(text);
- if (this._hasLongLines())
+ if (this._hasLongLines()) {
this._enableLongLinesMode();
- else
+ } else {
this._disableLongLinesMode();
+ }
- if (!this.isShowing())
+ if (!this.isShowing()) {
this.refresh();
+ }
}
/**
@@ -1247,8 +1329,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @return {string}
*/
text(textRange) {
- if (!textRange)
+ if (!textRange) {
return this._codeMirror.getValue(this._lineSeparator);
+ }
const pos = TextEditor.CodeMirrorUtils.toPos(textRange.normalize());
return this._codeMirror.getRange(pos.start, pos.end, this._lineSeparator);
}
@@ -1258,8 +1341,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
* @return {string}
*/
textWithCurrentSuggestion() {
- if (!this._autocompleteController)
+ if (!this._autocompleteController) {
return this.text();
+ }
return this._autocompleteController.textWithCurrentSuggestion();
}
@@ -1314,8 +1398,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
}
_updatePlaceholder() {
- if (!this._placeholderElement)
+ if (!this._placeholderElement) {
return;
+ }
this._placeholderElement.remove();
@@ -1347,14 +1432,33 @@ CodeMirror.commands.selectCamelRight = TextEditor.CodeMirrorTextEditor.moveCamel
/**
* @param {!CodeMirror} codeMirror
+ */
+CodeMirror.commands.UserIndent = function(codeMirror) {
+ const ranges = codeMirror.listSelections();
+ if (ranges.length === 0) {
+ return;
+ }
+
+ if (codeMirror.somethingSelected()) {
+ codeMirror.indentSelection('add');
+ return;
+ }
+
+ const indentation = Common.moduleSetting('textEditorIndent').get();
+ codeMirror.replaceSelection(indentation);
+};
+
+/**
+ * @param {!CodeMirror} codeMirror
* @return {!Object|undefined}
*/
CodeMirror.commands.indentLessOrPass = function(codeMirror) {
const selections = codeMirror.listSelections();
if (selections.length === 1) {
const range = TextEditor.CodeMirrorUtils.toRange(selections[0].anchor, selections[0].head);
- if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine)))
+ if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine))) {
return CodeMirror.Pass;
+ }
}
codeMirror.execCommand('indentLess');
};
@@ -1388,8 +1492,9 @@ CodeMirror.commands.undoAndReveal = function(codemirror) {
const cursor = codemirror.getCursor('start');
codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
const autocompleteController = codemirror._codeMirrorTextEditor._autocompleteController;
- if (autocompleteController)
+ if (autocompleteController) {
autocompleteController.clearAutocomplete();
+ }
};
/**
@@ -1401,8 +1506,9 @@ CodeMirror.commands.redoAndReveal = function(codemirror) {
const cursor = codemirror.getCursor('start');
codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line, scrollInfo);
const autocompleteController = codemirror._codeMirrorTextEditor._autocompleteController;
- if (autocompleteController)
+ if (autocompleteController) {
autocompleteController.clearAutocomplete();
+ }
};
/**
@@ -1413,8 +1519,9 @@ CodeMirror.commands.dismiss = function(codemirror) {
const selections = codemirror.listSelections();
const selection = selections[0];
if (selections.length === 1) {
- if (TextEditor.CodeMirrorUtils.toRange(selection.anchor, selection.head).isEmpty())
+ if (TextEditor.CodeMirrorUtils.toRange(selection.anchor, selection.head).isEmpty()) {
return CodeMirror.Pass;
+ }
codemirror.setSelection(selection.anchor, selection.anchor, {scroll: false});
codemirror._codeMirrorTextEditor.scrollLineIntoView(selection.anchor.line);
return;
@@ -1429,8 +1536,9 @@ CodeMirror.commands.dismiss = function(codemirror) {
* @return {!Object|undefined}
*/
CodeMirror.commands.goSmartPageUp = function(codemirror) {
- if (codemirror._codeMirrorTextEditor.selection().equal(TextUtils.TextRange.createFromLocation(0, 0)))
+ if (codemirror._codeMirrorTextEditor.selection().equal(TextUtils.TextRange.createFromLocation(0, 0))) {
return CodeMirror.Pass;
+ }
codemirror.execCommand('goPageUp');
};
@@ -1439,8 +1547,10 @@ CodeMirror.commands.goSmartPageUp = function(codemirror) {
* @return {!Object|undefined}
*/
CodeMirror.commands.goSmartPageDown = function(codemirror) {
- if (codemirror._codeMirrorTextEditor.selection().equal(codemirror._codeMirrorTextEditor.fullRange().collapseToEnd()))
+ if (codemirror._codeMirrorTextEditor.selection().equal(
+ codemirror._codeMirrorTextEditor.fullRange().collapseToEnd())) {
return CodeMirror.Pass;
+ }
codemirror.execCommand('goPageDown');
};
@@ -1468,8 +1578,9 @@ TextEditor.CodeMirrorPositionHandle = class {
*/
resolve() {
const lineNumber = this._lineHandle ? this._codeMirror.getLineNumber(this._lineHandle) : null;
- if (typeof lineNumber !== 'number')
+ if (typeof lineNumber !== 'number') {
return null;
+ }
return {lineNumber: lineNumber, columnNumber: this._columnNumber};
}
@@ -1498,8 +1609,9 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
}
selectionWillChange() {
- if (!this._muteSelectionListener)
+ if (!this._muteSelectionListener) {
delete this._fullWordSelection;
+ }
}
/**
@@ -1509,8 +1621,9 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
*/
_findRange(selections, range) {
for (let i = 0; i < selections.length; ++i) {
- if (range.equal(selections[i]))
+ if (range.equal(selections[i])) {
return true;
+ }
}
return false;
}
@@ -1527,8 +1640,9 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
for (let i = 0; i < selections.length; ++i) {
const selection = selections[i];
anyEmptySelection = anyEmptySelection || selection.isEmpty();
- if (selection.startLine !== selection.endLine)
+ if (selection.startLine !== selection.endLine) {
return;
+ }
}
if (anyEmptySelection) {
this._expandSelectionsToWords(selections);
@@ -1537,12 +1651,13 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
const last = selections[selections.length - 1];
let next = last;
- do
+ do {
next = this._findNextOccurrence(next, !!this._fullWordSelection);
- while (next && this._findRange(selections, next) && !next.equal(last));
+ } while (next && this._findRange(selections, next) && !next.equal(last));
- if (!next)
+ if (!next) {
return;
+ }
selections.push(next);
this._muteSelectionListener = true;
@@ -1584,12 +1699,14 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
let matchedColumnNumber;
const textToFind = this._textEditor.text(range);
function findWordInLine(wordRegex, lineNumber, lineText, from, to) {
- if (typeof matchedLineNumber === 'number')
+ if (typeof matchedLineNumber === 'number') {
return true;
+ }
wordRegex.lastIndex = from;
const result = wordRegex.exec(lineText);
- if (!result || result.index + textToFind.length > to)
+ if (!result || result.index + textToFind.length > to) {
return false;
+ }
matchedLineNumber = lineNumber;
matchedColumnNumber = result.index;
return true;
@@ -1597,13 +1714,15 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
let iteratedLineNumber;
function lineIterator(regex, lineHandle) {
- if (findWordInLine(regex, iteratedLineNumber++, lineHandle.text, 0, lineHandle.text.length))
+ if (findWordInLine(regex, iteratedLineNumber++, lineHandle.text, 0, lineHandle.text.length)) {
return true;
+ }
}
let regexSource = textToFind.escapeForRegExp();
- if (fullWord)
+ if (fullWord) {
regexSource = '\\b' + regexSource + '\\b';
+ }
const wordRegex = new RegExp(regexSource, 'g');
const currentLineText = this._codeMirror.getLine(range.startLine);
@@ -1614,8 +1733,9 @@ TextEditor.CodeMirrorTextEditor.SelectNextOccurrenceController = class {
this._codeMirror.eachLine(0, range.startLine, lineIterator.bind(null, wordRegex));
findWordInLine(wordRegex, range.startLine, currentLineText, 0, range.startColumn);
- if (typeof matchedLineNumber !== 'number')
+ if (typeof matchedLineNumber !== 'number') {
return null;
+ }
return new TextUtils.TextRange(
matchedLineNumber, matchedColumnNumber, matchedLineNumber, matchedColumnNumber + textToFind.length);
}
@@ -1644,7 +1764,7 @@ TextEditor.CodeMirrorTextEditor._overrideModeWithPrefixedTokens('css', 'css-');
TextEditor.CodeMirrorTextEditor._overrideModeWithPrefixedTokens('javascript', 'js-');
TextEditor.CodeMirrorTextEditor._overrideModeWithPrefixedTokens('xml', 'xml-');
-/** @type {!Set<!Runtime.Extension>} */
+/** @type {!Set<!Root.Runtime.Extension>} */
TextEditor.CodeMirrorTextEditor._loadedMimeModeExtensions = new Set();
@@ -1655,7 +1775,7 @@ TextEditor.CodeMirrorMimeMode = function() {};
TextEditor.CodeMirrorMimeMode.prototype = {
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
install(extension) {}
};
@@ -1680,15 +1800,17 @@ TextEditor.TextEditorBookMark = class {
clear() {
const position = this._marker.find();
this._marker.clear();
- if (position)
+ if (position) {
this._editor._updateDecorations(position.line);
+ }
}
refresh() {
this._marker.changed();
const position = this._marker.find();
- if (position)
+ if (position) {
this._editor._updateDecorations(position.line);
+ }
}
/**
@@ -1752,8 +1874,9 @@ CodeMirror.inputStyles.devToolsAccessibleTextArea = class extends CodeMirror.inp
}
_onCompositionStart() {
- if (this.textarea.selectionEnd === this.textarea.value.length)
+ if (this.textarea.selectionEnd === this.textarea.value.length) {
return;
+ }
// CodeMirror always expects the caret to be at the end of the textarea
// When in IME composition mode, clip the textarea to how CodeMirror expects it,
// and then let CodeMirror do it's thing.
@@ -1797,16 +1920,19 @@ CodeMirror.inputStyles.devToolsAccessibleTextArea = class extends CodeMirror.inp
* @return {boolean}
*/
poll() {
- if (this.contextMenuPending || this.composing)
+ if (this.contextMenuPending || this.composing) {
return super.poll();
+ }
const text = this.textarea.value;
let start = 0;
const length = Math.min(this.prevInput.length, text.length);
- while (start < length && this.prevInput[start] === text[start])
+ while (start < length && this.prevInput[start] === text[start]) {
++start;
+ }
let end = 0;
- while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1])
+ while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1]) {
++end;
+ }
// CodeMirror expects the user to be typing into a blank <textarea>.
// Pass a fake textarea into super.poll that only contains the users input.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
index 531c5fbccd5..f36d48ea35f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
@@ -44,8 +44,9 @@ TextEditor.TextEditorAutocompleteController = class {
}
_initializeIfNeeded() {
- if (this._initialized)
+ if (this._initialized) {
return;
+ }
this._initialized = true;
this._codeMirror.on('scroll', this._onScroll);
this._codeMirror.on('cursorActivity', this._onCursorActivity);
@@ -79,8 +80,9 @@ TextEditor.TextEditorAutocompleteController = class {
_beforeChange(codeMirror, changeObject) {
this._updatedLines = this._updatedLines || {};
for (let i = changeObject.from.line; i <= changeObject.to.line; ++i) {
- if (this._updatedLines[i] === undefined)
+ if (this._updatedLines[i] === undefined) {
this._updatedLines[i] = this._codeMirror.getLine(i);
+ }
}
}
@@ -96,8 +98,9 @@ TextEditor.TextEditorAutocompleteController = class {
* @this {TextEditor.TextEditorAutocompleteController}
*/
function addWord(word) {
- if (word.length && (word[0] < '0' || word[0] > '9'))
+ if (word.length && (word[0] < '0' || word[0] > '9')) {
this._dictionary.addWord(word);
+ }
}
}
@@ -118,8 +121,9 @@ TextEditor.TextEditorAutocompleteController = class {
_substituteRange(lineNumber, columnNumber) {
let range =
this._config.substituteRangeCallback ? this._config.substituteRangeCallback(lineNumber, columnNumber) : null;
- if (!range && this._config.isWordChar)
+ if (!range && this._config.isWordChar) {
range = this._textEditor.wordRangeForCursorPosition(lineNumber, columnNumber, this._config.isWordChar);
+ }
return range;
}
@@ -132,16 +136,19 @@ TextEditor.TextEditorAutocompleteController = class {
_wordsWithQuery(queryRange, substituteRange, force) {
const external =
this._config.suggestionsCallback ? this._config.suggestionsCallback(queryRange, substituteRange, force) : null;
- if (external)
+ if (external) {
return external;
+ }
- if (!this._dictionary || (!force && queryRange.isEmpty()))
+ if (!this._dictionary || (!force && queryRange.isEmpty())) {
return Promise.resolve([]);
+ }
let completions = this._dictionary.wordsWithPrefix(this._textEditor.text(queryRange));
const substituteWord = this._textEditor.text(substituteRange);
- if (this._dictionary.wordCount(substituteWord) === 1)
+ if (this._dictionary.wordCount(substituteWord) === 1) {
completions = completions.filter(word => word !== substituteWord);
+ }
completions.sort((a, b) => this._dictionary.wordCount(b) - this._dictionary.wordCount(a) || a.length - b.length);
return Promise.resolve(completions.map(item => ({text: item})));
@@ -152,23 +159,27 @@ TextEditor.TextEditorAutocompleteController = class {
* @param {!Array.<!CodeMirror.ChangeObject>} changes
*/
_changes(codeMirror, changes) {
- if (!changes.length)
+ if (!changes.length) {
return;
+ }
if (this._dictionary && this._updatedLines) {
- for (const lineNumber in this._updatedLines)
+ for (const lineNumber in this._updatedLines) {
this._removeWordsFromText(this._updatedLines[lineNumber]);
+ }
delete this._updatedLines;
const linesToUpdate = {};
for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
const changeObject = changes[changeIndex];
const editInfo = TextEditor.CodeMirrorUtils.changeObjectToEditOperation(changeObject);
- for (let i = editInfo.newRange.startLine; i <= editInfo.newRange.endLine; ++i)
+ for (let i = editInfo.newRange.startLine; i <= editInfo.newRange.endLine; ++i) {
linesToUpdate[i] = this._codeMirror.getLine(i);
+ }
}
- for (const lineNumber in linesToUpdate)
+ for (const lineNumber in linesToUpdate) {
this._addWordsFromText(linesToUpdate[lineNumber]);
+ }
}
let singleCharInput = false;
@@ -189,18 +200,21 @@ TextEditor.TextEditorAutocompleteController = class {
}
}
if (this._queryRange) {
- if (singleCharInput)
+ if (singleCharInput) {
this._queryRange.endColumn++;
- else if (singleCharDelete)
+ } else if (singleCharDelete) {
this._queryRange.endColumn--;
- if (singleCharDelete || singleCharInput)
+ }
+ if (singleCharDelete || singleCharInput) {
this._setHint(this._lastHintText);
+ }
}
- if (singleCharInput || singleCharDelete)
+ if (singleCharInput || singleCharDelete) {
setImmediate(this.autocomplete.bind(this));
- else
+ } else {
this.clearAutocomplete();
+ }
}
_blur() {
@@ -213,16 +227,19 @@ TextEditor.TextEditorAutocompleteController = class {
*/
_validateSelectionsContexts(mainSelection) {
const selections = this._codeMirror.listSelections();
- if (selections.length <= 1)
+ if (selections.length <= 1) {
return true;
+ }
const mainSelectionContext = this._textEditor.text(mainSelection);
for (let i = 0; i < selections.length; ++i) {
const wordRange = this._substituteRange(selections[i].head.line, selections[i].head.ch);
- if (!wordRange)
+ if (!wordRange) {
return false;
+ }
const context = this._textEditor.text(wordRange);
- if (context !== mainSelectionContext)
+ if (context !== mainSelectionContext) {
return false;
+ }
}
return true;
}
@@ -248,8 +265,9 @@ TextEditor.TextEditorAutocompleteController = class {
queryRange.endColumn = cursor.ch;
const query = this._textEditor.text(queryRange);
let hadSuggestBox = false;
- if (this._suggestBox)
+ if (this._suggestBox) {
hadSuggestBox = true;
+ }
this._wordsWithQuery(queryRange, substituteRange, force).then(wordsAcquired.bind(this));
/**
@@ -265,18 +283,21 @@ TextEditor.TextEditorAutocompleteController = class {
}
if (!this._suggestBox) {
this._suggestBox = new UI.SuggestBox(this, 20);
- if (this._config.anchorBehavior)
+ if (this._config.anchorBehavior) {
this._suggestBox.setAnchorBehavior(this._config.anchorBehavior);
+ }
}
const oldQueryRange = this._queryRange;
this._queryRange = queryRange;
if (!oldQueryRange || queryRange.startLine !== oldQueryRange.startLine ||
- queryRange.startColumn !== oldQueryRange.startColumn)
+ queryRange.startColumn !== oldQueryRange.startColumn) {
this._updateAnchorBox();
+ }
this._suggestBox.updateSuggestions(this._anchorBox, wordsWithQuery, true, !this._isCursorAtEndOfLine(), query);
- if (this._suggestBox.visible)
+ if (this._suggestBox.visible) {
this._tooltipGlassPane.hide();
+ }
this._onSuggestionsShownForTest(wordsWithQuery);
}
}
@@ -291,7 +312,7 @@ TextEditor.TextEditorAutocompleteController = class {
return;
}
const suffix = hint.substring(query.length).split('\n')[0];
- this._hintElement.textContent = suffix.trimEnd(10000);
+ this._hintElement.textContent = suffix.trimEndWithMaxLength(10000);
const cursor = this._codeMirror.getCursor('to');
if (this._hintMarker) {
const position = this._hintMarker.position();
@@ -311,12 +332,14 @@ TextEditor.TextEditorAutocompleteController = class {
}
_clearHint() {
- if (!this._hintElement.textContent)
+ if (!this._hintElement.textContent) {
return;
+ }
this._lastHintText = '';
this._hintElement.textContent = '';
- if (this._hintMarker)
+ if (this._hintMarker) {
this._hintMarker.refresh();
+ }
}
/**
@@ -334,8 +357,9 @@ TextEditor.TextEditorAutocompleteController = class {
}
_hideSuggestBox() {
- if (!this._suggestBox)
+ if (!this._suggestBox) {
return;
+ }
this._suggestBox.hide();
this._suggestBox = null;
this._queryRange = null;
@@ -355,8 +379,9 @@ TextEditor.TextEditorAutocompleteController = class {
this._tooltipGlassPane.hide();
return true;
}
- if (!this._suggestBox)
+ if (!this._suggestBox) {
return false;
+ }
switch (event.keyCode) {
case UI.KeyboardShortcut.Keys.Tab.code:
this._suggestBox.acceptSuggestion();
@@ -400,8 +425,9 @@ TextEditor.TextEditorAutocompleteController = class {
const oldSuggestion = this._currentSuggestion;
this._currentSuggestion = suggestion;
this._setHint(suggestion ? suggestion.text : '');
- if ((oldSuggestion ? oldSuggestion.text : '') !== (suggestion ? suggestion.text : ''))
+ if ((oldSuggestion ? oldSuggestion.text : '') !== (suggestion ? suggestion.text : '')) {
this._textEditor.dispatchEventToListeners(UI.TextEditor.Events.SuggestionChanged);
+ }
}
/**
@@ -424,8 +450,9 @@ TextEditor.TextEditorAutocompleteController = class {
* @return {string}
*/
textWithCurrentSuggestion() {
- if (!this._queryRange || this._currentSuggestion === null)
+ if (!this._queryRange || this._currentSuggestion === null) {
return this._codeMirror.getValue();
+ }
const selections = this._codeMirror.listSelections().slice();
let last = {line: 0, column: 0};
@@ -445,8 +472,9 @@ TextEditor.TextEditorAutocompleteController = class {
_onScroll() {
this._tooltipGlassPane.hide();
- if (!this._suggestBox)
+ if (!this._suggestBox) {
return;
+ }
const cursor = this._codeMirror.getCursor();
const scrollInfo = this._codeMirror.getScrollInfo();
const topmostLineNumber = this._codeMirror.lineAtHeight(scrollInfo.top, 'local');
@@ -464,10 +492,12 @@ TextEditor.TextEditorAutocompleteController = class {
const tooltip = this._config.tooltipCallback ? await this._config.tooltipCallback(cursor.line, cursor.ch) : null;
const newCursor = this._codeMirror.getCursor();
- if (newCursor.line !== cursor.line && newCursor.ch !== cursor.ch)
+ if (newCursor.line !== cursor.line && newCursor.ch !== cursor.ch) {
return;
- if (this._suggestBox && this._suggestBox.visible)
+ }
+ if (this._suggestBox && this._suggestBox.visible) {
return;
+ }
if (!tooltip) {
this._tooltipGlassPane.hide();
@@ -487,8 +517,9 @@ TextEditor.TextEditorAutocompleteController = class {
_onCursorActivity() {
this._updateTooltip();
- if (!this._suggestBox)
+ if (!this._suggestBox) {
return;
+ }
const cursor = this._codeMirror.getCursor();
let shouldCloseAutocomplete =
!(cursor.line === this._queryRange.startLine && this._queryRange.startColumn <= cursor.ch &&
@@ -498,8 +529,9 @@ TextEditor.TextEditorAutocompleteController = class {
const line = this._codeMirror.getLine(cursor.line);
shouldCloseAutocomplete = this._config.isWordChar ? !this._config.isWordChar(line.charAt(cursor.ch - 1)) : false;
}
- if (shouldCloseAutocomplete)
+ if (shouldCloseAutocomplete) {
this.clearAutocomplete();
+ }
this._onCursorActivityHandledForTest();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css
index 0fad53747e8..78fa25a2e15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/cmdevtools.css
@@ -309,15 +309,6 @@ div.CodeMirror:focus-within span.CodeMirror-nonmatchingbracket {
background-color: rgb(171, 191, 254);
}
-.cm-execution-line .CodeMirror-linenumber::after {
- position: absolute;
- top:-1px;
- bottom:-1px;
- right:-1.5em;
- content:"";
- border-right: 1px solid rgb(64, 115, 244);
-}
-
:host-context(.-theme-with-dark-background) .cm-execution-line,
.-theme-with-dark-background .cm-execution-line {
background-color: #14522b;
@@ -437,7 +428,7 @@ div.CodeMirror:focus-within span.CodeMirror-nonmatchingbracket {
.CodeMirror .text-editor-coverage-unused-marker {
text-align: right;
padding-right: 2px;
- background-color: #E57373;
+ background-color: #EE442F;
}
.CodeMirror .text-editor-coverage-unused-marker::after {
@@ -447,7 +438,7 @@ div.CodeMirror:focus-within span.CodeMirror-nonmatchingbracket {
.CodeMirror .text-editor-coverage-used-marker {
text-align: right;
padding-right: 2px;
- background-color: #81C784;
+ background-color: #63ACBE;
}
.CodeMirror .text-editor-coverage-used-marker::after {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/Text.js b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/Text.js
index c1f2da29ac6..5476b97f0d9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/Text.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/Text.js
@@ -17,8 +17,9 @@ TextUtils.Text = class {
* @return {!Array<number>}
*/
lineEndings() {
- if (!this._lineEndings)
+ if (!this._lineEndings) {
this._lineEndings = this._value.computeLineEndings();
+ }
return this._lineEndings;
}
@@ -64,8 +65,9 @@ TextUtils.Text = class {
const lineStart = lineNumber > 0 ? lineEndings[lineNumber - 1] + 1 : 0;
const lineEnd = lineEndings[lineNumber];
let lineContent = this._value.substring(lineStart, lineEnd);
- if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === '\r')
+ if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === '\r') {
lineContent = lineContent.substring(0, lineContent.length - 1);
+ }
return lineContent;
}
@@ -140,8 +142,9 @@ TextUtils.TextCursor = class {
*/
advance(offset) {
this._offset = offset;
- while (this._lineNumber < this._lineEndings.length && this._lineEndings[this._lineNumber] < this._offset)
+ while (this._lineNumber < this._lineEndings.length && this._lineEndings[this._lineNumber] < this._offset) {
++this._lineNumber;
+ }
this._columnNumber = this._lineNumber ? this._offset - this._lineEndings[this._lineNumber - 1] - 1 : this._offset;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextRange.js b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextRange.js
index 9bc7f4146a2..b044f97feff 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextRange.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextRange.js
@@ -102,8 +102,9 @@ TextUtils.TextRange = class {
* @return {boolean}
*/
immediatelyPrecedes(range) {
- if (!range)
+ if (!range) {
return false;
+ }
return this.endLine === range.startLine && this.endColumn === range.startColumn;
}
@@ -112,8 +113,9 @@ TextUtils.TextRange = class {
* @return {boolean}
*/
immediatelyFollows(range) {
- if (!range)
+ if (!range) {
return false;
+ }
return range.immediatelyPrecedes(this);
}
@@ -150,10 +152,11 @@ TextUtils.TextRange = class {
* @return {!TextUtils.TextRange}
*/
normalize() {
- if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn))
+ if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn)) {
return new TextUtils.TextRange(this.endLine, this.endColumn, this.startLine, this.startColumn);
- else
+ } else {
return this.clone();
+ }
}
/**
@@ -180,14 +183,18 @@ TextUtils.TextRange = class {
* @return {number}
*/
compareTo(other) {
- if (this.startLine > other.startLine)
+ if (this.startLine > other.startLine) {
return 1;
- if (this.startLine < other.startLine)
+ }
+ if (this.startLine < other.startLine) {
return -1;
- if (this.startColumn > other.startColumn)
+ }
+ if (this.startColumn > other.startColumn) {
return 1;
- if (this.startColumn < other.startColumn)
+ }
+ if (this.startColumn < other.startColumn) {
return -1;
+ }
return 0;
}
@@ -197,10 +204,12 @@ TextUtils.TextRange = class {
* @return {number}
*/
compareToPosition(lineNumber, columnNumber) {
- if (lineNumber < this.startLine || (lineNumber === this.startLine && columnNumber < this.startColumn))
+ if (lineNumber < this.startLine || (lineNumber === this.startLine && columnNumber < this.startColumn)) {
return -1;
- if (lineNumber > this.endLine || (lineNumber === this.endLine && columnNumber > this.endColumn))
+ }
+ if (lineNumber > this.endLine || (lineNumber === this.endLine && columnNumber > this.endColumn)) {
return 1;
+ }
return 0;
}
@@ -221,10 +230,12 @@ TextUtils.TextRange = class {
relativeTo(line, column) {
const relative = this.clone();
- if (this.startLine === line)
+ if (this.startLine === line) {
relative.startColumn -= column;
- if (this.endLine === line)
+ }
+ if (this.endLine === line) {
relative.endColumn -= column;
+ }
relative.startLine -= line;
relative.endLine -= line;
@@ -239,10 +250,12 @@ TextUtils.TextRange = class {
relativeFrom(line, column) {
const relative = this.clone();
- if (this.startLine === 0)
+ if (this.startLine === 0) {
relative.startColumn += column;
- if (this.endLine === 0)
+ }
+ if (this.endLine === 0) {
relative.endColumn += column;
+ }
relative.startLine += line;
relative.endLine += line;
@@ -258,16 +271,19 @@ TextUtils.TextRange = class {
console.assert(originalRange.startLine === editedRange.startLine);
console.assert(originalRange.startColumn === editedRange.startColumn);
const rebase = this.clone();
- if (!this.follows(originalRange))
+ if (!this.follows(originalRange)) {
return rebase;
+ }
const lineDelta = editedRange.endLine - originalRange.endLine;
const columnDelta = editedRange.endColumn - originalRange.endColumn;
rebase.startLine += lineDelta;
rebase.endLine += lineDelta;
- if (rebase.startLine === editedRange.endLine)
+ if (rebase.startLine === editedRange.endLine) {
rebase.startColumn += columnDelta;
- if (rebase.endLine === editedRange.endLine)
+ }
+ if (rebase.endLine === editedRange.endLine) {
rebase.endColumn += columnDelta;
+ }
return rebase;
}
@@ -285,12 +301,15 @@ TextUtils.TextRange = class {
* @return {boolean}
*/
containsLocation(lineNumber, columnNumber) {
- if (this.startLine === this.endLine)
+ if (this.startLine === this.endLine) {
return this.startLine === lineNumber && this.startColumn <= columnNumber && columnNumber <= this.endColumn;
- if (this.startLine === lineNumber)
+ }
+ if (this.startLine === lineNumber) {
return this.startColumn <= columnNumber;
- if (this.endLine === lineNumber)
+ }
+ if (this.endLine === lineNumber) {
return columnNumber <= this.endColumn;
+ }
return this.startLine < lineNumber && lineNumber < this.endLine;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextUtils.js
index 1fb8f6d097c..e7be880718e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_utils/TextUtils.js
@@ -59,8 +59,9 @@ TextUtils.TextUtils = {
*/
isWord: function(word) {
for (let i = 0; i < word.length; ++i) {
- if (!TextUtils.TextUtils.isWordChar(word.charAt(i)))
+ if (!TextUtils.TextUtils.isWordChar(word.charAt(i))) {
return false;
+ }
}
return true;
},
@@ -98,15 +99,17 @@ TextUtils.TextUtils = {
let startWord = -1;
for (let i = 0; i < text.length; ++i) {
if (!isWordChar(text.charAt(i))) {
- if (startWord !== -1)
+ if (startWord !== -1) {
wordCallback(text.substring(startWord, i));
+ }
startWord = -1;
} else if (startWord === -1) {
startWord = i;
}
}
- if (startWord !== -1)
+ if (startWord !== -1) {
wordCallback(text.substring(startWord));
+ }
},
/**
@@ -115,8 +118,9 @@ TextUtils.TextUtils = {
*/
lineIndent: function(line) {
let indentation = 0;
- while (indentation < line.length && TextUtils.TextUtils.isSpaceChar(line.charAt(indentation)))
+ while (indentation < line.length && TextUtils.TextUtils.isSpaceChar(line.charAt(indentation))) {
++indentation;
+ }
return line.substr(0, indentation);
},
@@ -146,10 +150,11 @@ TextUtils.TextUtils = {
const globalRegexes = [];
for (let i = 0; i < regexes.length; i++) {
const regex = regexes[i];
- if (!regex.global)
+ if (!regex.global) {
globalRegexes.push(new RegExp(regex.source, regex.flags ? regex.flags + 'g' : 'g'));
- else
+ } else {
globalRegexes.push(regex);
+ }
}
doSplit(text, 0, 0);
return matches;
@@ -171,8 +176,9 @@ TextUtils.TextUtils = {
regex.lastIndex = 0;
while ((result = regex.exec(text)) !== null) {
const stringBeforeMatch = text.substring(currentIndex, result.index);
- if (stringBeforeMatch)
+ if (stringBeforeMatch) {
doSplit(stringBeforeMatch, regexIndex + 1, startIndex + currentIndex);
+ }
const match = result[0];
matches.push({
value: match,
@@ -183,8 +189,9 @@ TextUtils.TextUtils = {
currentIndex = result.index + match.length;
}
const stringAfterMatches = text.substring(currentIndex);
- if (stringAfterMatches)
+ if (stringAfterMatches) {
doSplit(stringAfterMatches, regexIndex + 1, startIndex + currentIndex);
+ }
}
}
};
@@ -217,14 +224,16 @@ TextUtils.FilterParser = class {
const filters = [];
for (let i = 0; i < splitResult.length; i++) {
const regexIndex = splitResult[i].regexIndex;
- if (regexIndex === -1)
+ if (regexIndex === -1) {
continue;
+ }
const result = splitResult[i].captureGroups;
if (regexIndex === 0) {
- if (this._keys.indexOf(/** @type {string} */ (result[1])) !== -1)
+ if (this._keys.indexOf(/** @type {string} */ (result[1])) !== -1) {
filters.push({key: result[1], text: result[2], negative: !!result[0]});
- else
+ } else {
filters.push({text: result[1] + ':' + result[2], negative: !!result[0]});
+ }
} else if (regexIndex === 1) {
try {
filters.push({regex: new RegExp(result[1], 'i'), negative: !!result[0]});
@@ -287,8 +296,9 @@ TextUtils.TextUtils.BalancedJSONTokenizer = class {
const character = buffer[index];
if (character === '"') {
this._closingDoubleQuoteRegex.lastIndex = index;
- if (!this._closingDoubleQuoteRegex.test(buffer))
+ if (!this._closingDoubleQuoteRegex.test(buffer)) {
break;
+ }
index = this._closingDoubleQuoteRegex.lastIndex - 1;
} else if (character === '{') {
++this._balance;
@@ -300,8 +310,9 @@ TextUtils.TextUtils.BalancedJSONTokenizer = class {
}
if (!this._balance) {
this._lastBalancedIndex = index + 1;
- if (!this._findMultiple)
+ if (!this._findMultiple) {
break;
+ }
}
} else if (character === ']' && !this._balance) {
this._reportBalanced();
@@ -314,8 +325,9 @@ TextUtils.TextUtils.BalancedJSONTokenizer = class {
}
_reportBalanced() {
- if (!this._lastBalancedIndex)
+ if (!this._lastBalancedIndex) {
return;
+ }
this._callback(this._buffer.slice(0, this._lastBalancedIndex));
this._buffer = this._buffer.slice(this._lastBalancedIndex);
this._index -= this._lastBalancedIndex;
@@ -353,10 +365,12 @@ TextUtils.isMinified = function(text) {
let lastPosition = 0;
do {
let eolIndex = text.indexOf('\n', lastPosition);
- if (eolIndex < 0)
+ if (eolIndex < 0) {
eolIndex = text.length;
- if (eolIndex - lastPosition > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#')
+ }
+ if (eolIndex - lastPosition > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#') {
return true;
+ }
lastPosition = eolIndex + 1;
} while (--linesToCheck >= 0 && lastPosition < text.length);
@@ -365,10 +379,12 @@ TextUtils.isMinified = function(text) {
lastPosition = text.length;
do {
let eolIndex = text.lastIndexOf('\n', lastPosition);
- if (eolIndex < 0)
+ if (eolIndex < 0) {
eolIndex = 0;
- if (lastPosition - eolIndex > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#')
+ }
+ if (lastPosition - eolIndex > kMaxNonMinifiedLength && text.substr(lastPosition, 3) !== '//#') {
return true;
+ }
lastPosition = eolIndex - 1;
} while (--linesToCheck >= 0 && lastPosition > 0);
return false;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/CountersGraph.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/CountersGraph.js
index aece6d0a321..8c012baf19b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/CountersGraph.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/CountersGraph.js
@@ -91,11 +91,13 @@ Timeline.CountersGraph = class extends UI.VBox {
*/
setModel(model, track) {
if (this._model !== model) {
- if (this._model)
+ if (this._model) {
this._model.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
+ }
this._model = model;
- if (this._model)
+ if (this._model) {
this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
+ }
}
this._calculator.setZeroTime(model ? model.timelineModel().minimumRecordTime() : 0);
for (let i = 0; i < this._counters.length; ++i) {
@@ -104,26 +106,31 @@ Timeline.CountersGraph = class extends UI.VBox {
}
this.scheduleRefresh();
this._track = track;
- if (!track)
+ if (!track) {
return;
+ }
const events = track.syncEvents();
for (let i = 0; i < events.length; ++i) {
const event = events[i];
- if (event.name !== TimelineModel.TimelineModel.RecordType.UpdateCounters)
+ if (event.name !== TimelineModel.TimelineModel.RecordType.UpdateCounters) {
continue;
+ }
const counters = event.args.data;
- if (!counters)
+ if (!counters) {
return;
+ }
for (const name in counters) {
const counter = this._countersByName[name];
- if (counter)
+ if (counter) {
counter.appendSample(event.startTime, counters[name]);
+ }
}
const gpuMemoryLimitCounterName = 'gpuMemoryLimitKB';
- if (gpuMemoryLimitCounterName in counters)
+ if (gpuMemoryLimitCounterName in counters) {
this._gpuMemoryCounter.setLimit(counters[gpuMemoryLimitCounterName]);
+ }
}
}
@@ -181,8 +188,9 @@ Timeline.CountersGraph = class extends UI.VBox {
counter._calculateVisibleIndexes(this._calculator);
counter._calculateXValues(this._canvas.width);
}
- for (const counterUI of this._counterUI)
+ for (const counterUI of this._counterUI) {
counterUI._drawGraph(this._canvas);
+ }
}
/**
@@ -193,8 +201,9 @@ Timeline.CountersGraph = class extends UI.VBox {
let minDistance = Infinity;
let bestTime;
for (const counterUI of this._counterUI) {
- if (!counterUI.counter.times.length)
+ if (!counterUI.counter.times.length) {
continue;
+ }
const index = counterUI._recordIndexAt(x);
const distance = Math.abs(x * window.devicePixelRatio - counterUI.counter.x[index]);
if (distance < minDistance) {
@@ -217,8 +226,9 @@ Timeline.CountersGraph = class extends UI.VBox {
}
_clearCurrentValueAndMarker() {
- for (let i = 0; i < this._counterUI.length; i++)
+ for (let i = 0; i < this._counterUI.length; i++) {
this._counterUI[i]._clearCurrentValueAndMarker();
+ }
}
/**
@@ -231,10 +241,12 @@ Timeline.CountersGraph = class extends UI.VBox {
}
_refreshCurrentValues() {
- if (this._markerXPosition === undefined)
+ if (this._markerXPosition === undefined) {
return;
- for (let i = 0; i < this._counterUI.length; ++i)
+ }
+ for (let i = 0; i < this._counterUI.length; ++i) {
this._counterUI[i].updateCurrentValue(this._markerXPosition);
+ }
}
refresh() {
@@ -263,8 +275,9 @@ Timeline.CountersGraph.Counter = class {
* @param {number} value
*/
appendSample(time, value) {
- if (this.values.length && this.values.peekLast() === value)
+ if (this.values.length && this.values.peekLast() === value) {
return;
+ }
this.times.push(time);
this.values.push(value);
}
@@ -289,16 +302,19 @@ Timeline.CountersGraph.Counter = class {
let minValue;
for (let i = this._minimumIndex; i <= this._maximumIndex; i++) {
const value = this.values[i];
- if (minValue === undefined || value < minValue)
+ if (minValue === undefined || value < minValue) {
minValue = value;
- if (maxValue === undefined || value > maxValue)
+ }
+ if (maxValue === undefined || value > maxValue) {
maxValue = value;
+ }
}
minValue = minValue || 0;
maxValue = maxValue || 1;
if (this._limitValue) {
- if (maxValue > this._limitValue * 0.5)
+ if (maxValue > this._limitValue * 0.5) {
maxValue = Math.max(maxValue, this._limitValue);
+ }
minValue = Math.min(minValue, this._limitValue);
}
return {min: minValue, max: maxValue};
@@ -326,14 +342,16 @@ Timeline.CountersGraph.Counter = class {
* @param {number} width
*/
_calculateXValues(width) {
- if (!this.values.length)
+ if (!this.values.length) {
return;
+ }
const xFactor = width / (this._maxTime - this._minTime);
this.x = new Array(this.values.length);
- for (let i = this._minimumIndex + 1; i <= this._maximumIndex; i++)
+ for (let i = this._minimumIndex + 1; i <= this._maximumIndex; i++) {
this.x[i] = xFactor * (this.times[i] - this._minTime);
+ }
}
};
@@ -416,8 +434,9 @@ Timeline.CountersGraph.CounterUI = class {
* @param {number} x
*/
updateCurrentValue(x) {
- if (!this.visible() || !this.counter.values.length || !this.counter.x)
+ if (!this.visible() || !this.counter.values.length || !this.counter.x) {
return;
+ }
const index = this._recordIndexAt(x);
const value = Number.withThousandsSeparator(this.counter.values[index]);
this._value.textContent = Common.UIString(this._currentValueLabel, value);
@@ -447,16 +466,18 @@ Timeline.CountersGraph.CounterUI = class {
const counter = this.counter;
const values = counter.values;
- if (!values.length)
+ if (!values.length) {
return;
+ }
const bounds = counter._calculateBounds();
const minValue = bounds.min;
const maxValue = bounds.max;
this.setRange(minValue, maxValue);
- if (!this.visible())
+ if (!this.visible()) {
return;
+ }
const yValues = this.graphYValues;
const maxYRange = maxValue - minValue;
@@ -464,8 +485,9 @@ Timeline.CountersGraph.CounterUI = class {
ctx.save();
ctx.lineWidth = window.devicePixelRatio;
- if (ctx.lineWidth % 2)
+ if (ctx.lineWidth % 2) {
ctx.translate(0.5, 0.5);
+ }
ctx.beginPath();
let value = values[counter._minimumIndex];
let currentY = Math.round(originY + height - (value - minValue) * yFactor);
@@ -475,8 +497,9 @@ Timeline.CountersGraph.CounterUI = class {
const x = Math.round(counter.x[i]);
ctx.lineTo(x, currentY);
const currentValue = values[i];
- if (typeof currentValue !== 'undefined')
+ if (typeof currentValue !== 'undefined') {
value = currentValue;
+ }
currentY = Math.round(originY + height - (value - minValue) * yFactor);
ctx.lineTo(x, currentY);
yValues[i] = currentY;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js
index 7d2fc21e49a..5476697e61c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js
@@ -45,6 +45,14 @@ Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
/**
* @override
+ * @return {string}
+ */
+ getToolbarInputAccessiblePlaceHolder() {
+ return ls`Filter event log`;
+ }
+
+ /**
+ * @override
* @return {!TimelineModel.TimelineProfileTree.Node}
*/
_buildTree() {
@@ -55,8 +63,9 @@ Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
_onFilterChanged() {
const selectedEvent = this.lastSelectedNode() && this.lastSelectedNode().event;
this.refreshTree();
- if (selectedEvent)
+ if (selectedEvent) {
this._selectEvent(selectedEvent, false);
+ }
}
/**
@@ -73,8 +82,9 @@ Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
continue;
}
const child = /** @type {!TimelineModel.TimelineProfileTree.Node} */ (iterator.value);
- if (child.event === event)
+ if (child.event === event) {
return child;
+ }
iterators.push(child.children().values());
}
return null;
@@ -86,11 +96,13 @@ Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
*/
_selectEvent(event, expand) {
const node = this._findNodeWithEvent(event);
- if (!node)
+ if (!node) {
return;
+ }
this.selectProfileNode(node, false);
- if (expand)
+ if (expand) {
this.dataGridNodeForTreeNode(node).expand();
+ }
}
/**
@@ -120,8 +132,9 @@ Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
*/
_showDetailsForNode(node) {
const traceEvent = node.event;
- if (!traceEvent)
+ if (!traceEvent) {
return false;
+ }
Timeline.TimelineUIUtils
.buildTraceEventDetails(traceEvent, this.model().timelineModel(), this._linkifier, this._badgePool, false)
.then(fragment => this._detailsView.element.appendChild(fragment));
@@ -159,23 +172,21 @@ Timeline.EventsTimelineTreeView.Filters = class extends Common.Object {
* @param {!UI.Toolbar} toolbar
*/
populateToolbar(toolbar) {
- const durationFilterUI = new UI.ToolbarComboBox(durationFilterChanged.bind(this));
+ const durationFilterUI = new UI.ToolbarComboBox(durationFilterChanged.bind(this), ls`Duration filter`);
for (const durationMs of Timeline.EventsTimelineTreeView.Filters._durationFilterPresetsMs) {
durationFilterUI.addOption(durationFilterUI.createOption(
durationMs ? Common.UIString('\u2265 %d\xa0ms', durationMs) : Common.UIString('All'),
- durationMs ? Common.UIString('Hide records shorter than %d\xa0ms', durationMs) :
- Common.UIString('Show all records'),
String(durationMs)));
}
- UI.ARIAUtils.setAccessibleName(durationFilterUI.selectElement(), ls`Duration filter`);
toolbar.appendToolbarItem(durationFilterUI);
const categoryFiltersUI = {};
const categories = Timeline.TimelineUIUtils.categories();
for (const categoryName in categories) {
const category = categories[categoryName];
- if (!category.visible)
+ if (!category.visible) {
continue;
+ }
const checkbox =
new UI.ToolbarCheckbox(category.title, undefined, categoriesFilterChanged.bind(this, categoryName));
checkbox.setChecked(true);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/ExtensionTracingSession.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/ExtensionTracingSession.js
index fffe10f746b..0c1add93a80 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/ExtensionTracingSession.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/ExtensionTracingSession.js
@@ -42,8 +42,9 @@ Timeline.ExtensionTracingSession = class {
* @param {?SDK.TracingModel} tracingModel
*/
loadingComplete(tracingModel) {
- if (!tracingModel)
+ if (!tracingModel) {
return;
+ }
this._performanceModel.addExtensionEvents(this._provider.longDisplayName(), tracingModel, this._timeOffset);
this._completionCallback();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/PerformanceModel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/PerformanceModel.js
index d3ad810d56b..0b8e574b248 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/PerformanceModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/PerformanceModel.js
@@ -37,6 +37,13 @@ Timeline.PerformanceModel = class extends Common.Object {
}
/**
+ * @return {?SDK.Target}
+ */
+ mainTarget() {
+ return this._mainTarget;
+ }
+
+ /**
* @param {number} time
*/
setRecordStartTime(time) {
@@ -82,13 +89,16 @@ Timeline.PerformanceModel = class extends Common.Object {
let inputEvents = null;
let animationEvents = null;
for (const track of this._timelineModel.tracks()) {
- if (track.type === TimelineModel.TimelineModel.TrackType.Input)
+ if (track.type === TimelineModel.TimelineModel.TrackType.Input) {
inputEvents = track.asyncEvents;
- if (track.type === TimelineModel.TimelineModel.TrackType.Animation)
+ }
+ if (track.type === TimelineModel.TimelineModel.TrackType.Animation) {
animationEvents = track.asyncEvents;
+ }
}
- if (inputEvents || animationEvents)
+ if (inputEvents || animationEvents) {
this._irModel.populate(inputEvents || [], animationEvents || []);
+ }
const mainTracks = this._timelineModel.tracks().filter(
track => track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame &&
@@ -113,8 +123,9 @@ Timeline.PerformanceModel = class extends Common.Object {
*/
addExtensionEvents(title, model, timeOffset) {
this._extensionTracingModels.push({model: model, title: title, timeOffset: timeOffset});
- if (!this._tracingModel)
+ if (!this._tracingModel) {
return;
+ }
model.adjustTime(this._tracingModel.minimumRecordTime() + (timeOffset / 1000) - this._recordStartTime);
this.dispatchEventToListeners(Timeline.PerformanceModel.Events.ExtensionDataAdded);
}
@@ -123,8 +134,9 @@ Timeline.PerformanceModel = class extends Common.Object {
* @return {!SDK.TracingModel}
*/
tracingModel() {
- if (!this._tracingModel)
+ if (!this._tracingModel) {
throw 'call setTracingModel before accessing PerformanceModel';
+ }
return this._tracingModel;
}
@@ -139,10 +151,12 @@ Timeline.PerformanceModel = class extends Common.Object {
* @return {!SDK.FilmStripModel} filmStripModel
*/
filmStripModel() {
- if (this._filmStripModel)
+ if (this._filmStripModel) {
return this._filmStripModel;
- if (!this._tracingModel)
+ }
+ if (!this._tracingModel) {
throw 'call setTracingModel before accessing PerformanceModel';
+ }
this._filmStripModel = new SDK.FilmStripModel(this._tracingModel);
return this._filmStripModel;
}
@@ -176,10 +190,12 @@ Timeline.PerformanceModel = class extends Common.Object {
}
dispose() {
- if (this._tracingModel)
+ if (this._tracingModel) {
this._tracingModel.dispose();
- for (const extensionEntry of this._extensionTracingModels)
+ }
+ for (const extensionEntry of this._extensionTracingModels) {
extensionEntry.model.dispose();
+ }
}
/**
@@ -223,8 +239,9 @@ Timeline.PerformanceModel = class extends Common.Object {
let tasks = [];
for (const track of timelineModel.tracks()) {
// Deliberately pick up last main frame's track.
- if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame)
+ if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame) {
tasks = track.tasks;
+ }
}
if (!tasks.length) {
this.setWindow({left: timelineModel.minimumRecordTime(), right: timelineModel.maximumRecordTime()});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
index 73e76be2606..7f203680456 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
@@ -59,34 +59,40 @@ Timeline.TimelineController = class {
];
categoriesArray.push(TimelineModel.TimelineModel.Category.LatencyInfo);
- if (Runtime.experiments.isEnabled('timelineFlowEvents'))
+ if (Root.Runtime.experiments.isEnabled('timelineFlowEvents')) {
categoriesArray.push('devtools.timeline.async');
+ }
- if (Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling)
+ if (Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling) {
categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));
- if (!Runtime.queryParam('timelineTracingJSProfileDisabled') && options.enableJSSampling) {
+ }
+ if (!Root.Runtime.queryParam('timelineTracingJSProfileDisabled') && options.enableJSSampling) {
categoriesArray.push(disabledByDefault('v8.cpu_profiler'));
- if (Common.moduleSetting('highResolutionCpuProfiling').get())
+ if (Common.moduleSetting('highResolutionCpuProfiling').get()) {
categoriesArray.push(disabledByDefault('v8.cpu_profiler.hires'));
+ }
}
categoriesArray.push(disabledByDefault('devtools.timeline.stack'));
- if (Runtime.experiments.isEnabled('timelineInvalidationTracking'))
+ if (Root.Runtime.experiments.isEnabled('timelineInvalidationTracking')) {
categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));
+ }
if (options.capturePictures) {
categoriesArray.push(
disabledByDefault('devtools.timeline.layers'), disabledByDefault('devtools.timeline.picture'),
disabledByDefault('blink.graphics_context_annotations'));
}
- if (options.captureFilmStrip)
+ if (options.captureFilmStrip) {
categoriesArray.push(disabledByDefault('devtools.screenshot'));
+ }
this._extensionSessions =
providers.map(provider => new Timeline.ExtensionTracingSession(provider, this._performanceModel));
this._extensionSessions.forEach(session => session.start());
this._performanceModel.setRecordStartTime(Date.now());
const response = await this._startRecordingWithCategories(categoriesArray.join(','), options.enableJSSampling);
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
await this._waitForTracingToStop(false);
+ }
return response;
}
@@ -94,8 +100,9 @@ Timeline.TimelineController = class {
* @return {!Promise<!Timeline.PerformanceModel>}
*/
async stopRecording() {
- if (this._tracingManager)
+ if (this._tracingManager) {
this._tracingManager.stop();
+ }
this._client.loadingStarted();
await this._waitForTracingToStop(true);
@@ -110,8 +117,9 @@ Timeline.TimelineController = class {
*/
_waitForTracingToStop(awaitTracingCompleteCallback) {
const tracingStoppedPromises = [];
- if (this._tracingManager && awaitTracingCompleteCallback)
+ if (this._tracingManager && awaitTracingCompleteCallback) {
tracingStoppedPromises.push(new Promise(resolve => this._tracingCompleteCallback = resolve));
+ }
tracingStoppedPromises.push(this._stopProfilingOnAllModels());
const extensionCompletionPromises = this._extensionSessions.map(session => session.stop());
@@ -127,8 +135,9 @@ Timeline.TimelineController = class {
* @param {!SDK.CPUProfilerModel} cpuProfilerModel
*/
modelAdded(cpuProfilerModel) {
- if (this._profiling)
+ if (this._profiling) {
cpuProfilerModel.startRecording();
+ }
}
/**
@@ -158,8 +167,9 @@ Timeline.TimelineController = class {
Common.console.warn(Common.UIString('CPU profile for a target is not available.'));
return;
}
- if (!this._cpuProfiles)
+ if (!this._cpuProfiles) {
this._cpuProfiles = new Map();
+ }
this._cpuProfiles.set(targetId, cpuProfile);
}
@@ -181,17 +191,19 @@ Timeline.TimelineController = class {
/**
* @param {string} categories
* @param {boolean=} enableJSSampling
- * @return {!Promise<!Object>}
+ * @return {!Promise<!Object|undefined>}
*/
async _startRecordingWithCategories(categories, enableJSSampling) {
// There might be a significant delay in the beginning of timeline recording
// caused by starting CPU profiler, that needs to traverse JS heap to collect
// all the functions data.
- SDK.targetManager.suspendAllTargets();
- if (enableJSSampling && Runtime.queryParam('timelineTracingJSProfileDisabled'))
+ await SDK.targetManager.suspendAllTargets('performance-timeline');
+ if (enableJSSampling && Root.Runtime.queryParam('timelineTracingJSProfileDisabled')) {
await this._startProfilingOnAllModels();
- if (!this._tracingManager)
+ }
+ if (!this._tracingManager) {
return;
+ }
const samplingFrequencyHz = Common.moduleSetting('highResolutionCpuProfiling').get() ? 10000 : 1000;
const options = 'sampling-frequency=' + samplingFrequencyHz;
@@ -235,8 +247,9 @@ Timeline.TimelineController = class {
* @param {?Protocol.Profiler.Profile} cpuProfile
*/
_injectCpuProfileEvent(pid, tid, cpuProfile) {
- if (!cpuProfile)
+ if (!cpuProfile) {
return;
+ }
const cpuProfileEvent = /** @type {!SDK.TracingManager.EventPayload} */ ({
cat: SDK.TracingModel.DevToolsMetadataEventCategory,
ph: SDK.TracingModel.Phase.Instant,
@@ -256,42 +269,48 @@ Timeline.TimelineController = class {
const metadataEventTypes = TimelineModel.TimelineModel.DevToolsMetadataEvent;
const metadataEvents = this._tracingModel.devToolsMetadataEvents();
const browserMetaEvent = metadataEvents.find(e => e.name === metadataEventTypes.TracingStartedInBrowser);
- if (!browserMetaEvent)
+ if (!browserMetaEvent) {
return null;
+ }
- /** @type {!Multimap<string, string>} */
- const pseudoPidToFrames = new Multimap();
+ /** @type {!Platform.Multimap<string, string>} */
+ const pseudoPidToFrames = new Platform.Multimap();
/** @type {!Map<string, number>} */
const targetIdToPid = new Map();
const frames = browserMetaEvent.args.data['frames'];
- for (const frameInfo of frames)
+ for (const frameInfo of frames) {
targetIdToPid.set(frameInfo.frame, frameInfo.processId);
+ }
for (const event of metadataEvents) {
const data = event.args.data;
switch (event.name) {
case metadataEventTypes.FrameCommittedInBrowser:
- if (data.processId)
+ if (data.processId) {
targetIdToPid.set(data.frame, data.processId);
- else
+ } else {
pseudoPidToFrames.set(data.processPseudoId, data.frame);
+ }
break;
case metadataEventTypes.ProcessReadyInBrowser:
- for (const frame of pseudoPidToFrames.get(data.processPseudoId) || [])
+ for (const frame of pseudoPidToFrames.get(data.processPseudoId) || []) {
targetIdToPid.set(frame, data.processId);
+ }
break;
}
}
const mainFrame = frames.find(frame => !frame.parent);
const mainRendererProcessId = mainFrame.processId;
const mainProcess = this._tracingModel.processById(mainRendererProcessId);
- if (mainProcess)
+ if (mainProcess) {
targetIdToPid.set(SDK.targetManager.mainTarget().id(), mainProcess.id());
+ }
return targetIdToPid;
}
_injectCpuProfileEvents() {
- if (!this._cpuProfiles)
+ if (!this._cpuProfiles) {
return;
+ }
const metadataEventTypes = TimelineModel.TimelineModel.DevToolsMetadataEvent;
const metadataEvents = this._tracingModel.devToolsMetadataEvents();
@@ -300,12 +319,14 @@ Timeline.TimelineController = class {
if (targetIdToPid) {
for (const [id, profile] of this._cpuProfiles) {
const pid = targetIdToPid.get(id);
- if (!pid)
+ if (!pid) {
continue;
+ }
const process = this._tracingModel.processById(pid);
const thread = process && process.threadByName(TimelineModel.TimelineModel.RendererMainThreadName);
- if (thread)
+ if (thread) {
this._injectCpuProfileEvent(pid, thread.id(), profile);
+ }
}
} else {
// Legacy backends support.
@@ -373,7 +394,8 @@ Timeline.TimelineController.Client.prototype = {
* @typedef {!{
* enableJSSampling: (boolean|undefined),
* capturePictures: (boolean|undefined),
- * captureFilmStrip: (boolean|undefined)
+ * captureFilmStrip: (boolean|undefined),
+ * startCoverage: (boolean|undefined)
* }}
*/
Timeline.TimelineController.RecordingOptions;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineDetailsView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineDetailsView.js
index fba7235466e..e32051ee4c4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineDetailsView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineDetailsView.js
@@ -54,17 +54,20 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
*/
setModel(model, track) {
if (this._model !== model) {
- if (this._model)
+ if (this._model) {
this._model.removeEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
+ }
this._model = model;
- if (this._model)
+ if (this._model) {
this._model.addEventListener(Timeline.PerformanceModel.Events.WindowChanged, this._onWindowChanged, this);
+ }
}
this._track = track;
this._tabbedPane.closeTabs(
[Timeline.TimelineDetailsView.Tab.PaintProfiler, Timeline.TimelineDetailsView.Tab.LayerViewer], false);
- for (const view of this._rangeDetailViews.values())
+ for (const view of this._rangeDetailViews.values()) {
view.setModel(model, track);
+ }
this._lazyPaintProfilerView = null;
this._lazyLayersView = null;
this.setSelection(null);
@@ -76,8 +79,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
_setContent(node) {
const allTabs = this._tabbedPane.otherTabs(Timeline.TimelineDetailsView.Tab.Details);
for (let i = 0; i < allTabs.length; ++i) {
- if (!this._rangeDetailViews.has(allTabs[i]))
+ if (!this._rangeDetailViews.has(allTabs[i])) {
this._tabbedPane.closeTab(allTabs[i]);
+ }
}
this._defaultDetailsContentElement.removeChildren();
this._defaultDetailsContentElement.appendChild(node);
@@ -99,8 +103,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
*/
_appendTab(id, tabTitle, view, isCloseable) {
this._tabbedPane.appendTab(id, tabTitle, view, undefined, undefined, isCloseable);
- if (this._preferredTabId !== this._tabbedPane.selectedTabId)
+ if (this._preferredTabId !== this._tabbedPane.selectedTabId) {
this._tabbedPane.selectTab(id);
+ }
}
/**
@@ -121,8 +126,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_onWindowChanged(event) {
- if (!this._selection)
+ if (!this._selection) {
this._updateContentsFromWindow();
+ }
}
_updateContentsFromWindow() {
@@ -160,8 +166,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
if (frame.layerTree) {
const layersView = this._layersView();
layersView.showLayerTree(frame.layerTree);
- if (!this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.LayerViewer))
+ if (!this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.LayerViewer)) {
this._appendTab(Timeline.TimelineDetailsView.Tab.LayerViewer, Common.UIString('Layers'), layersView);
+ }
}
break;
case Timeline.TimelineSelection.Type.NetworkRequest:
@@ -182,8 +189,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
* @param {!Common.Event} event
*/
_tabSelected(event) {
- if (!event.data.isUserGesture)
+ if (!event.data.isUserGesture) {
return;
+ }
this.setPreferredTab(event.data.tabId);
this._updateContents();
}
@@ -192,8 +200,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
* @return {!UI.Widget}
*/
_layersView() {
- if (this._lazyLayersView)
+ if (this._lazyLayersView) {
return this._lazyLayersView;
+ }
this._lazyLayersView =
new Timeline.TimelineLayersView(this._model.timelineModel(), this._showSnapshotInPaintProfiler.bind(this));
return this._lazyLayersView;
@@ -203,8 +212,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
* @return {!Timeline.TimelinePaintProfilerView}
*/
_paintProfilerView() {
- if (this._lazyPaintProfilerView)
+ if (this._lazyPaintProfilerView) {
return this._lazyPaintProfilerView;
+ }
this._lazyPaintProfilerView = new Timeline.TimelinePaintProfilerView(this._model.frameModel());
return this._lazyPaintProfilerView;
}
@@ -229,8 +239,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
_appendDetailsTabsForTraceEventAndShowDetails(event, content) {
this._setContent(content);
if (event.name === TimelineModel.TimelineModel.RecordType.Paint ||
- event.name === TimelineModel.TimelineModel.RecordType.RasterTask)
+ event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
this._showEventInPaintProfiler(event);
+ }
}
/**
@@ -238,14 +249,17 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
*/
_showEventInPaintProfiler(event) {
const paintProfilerModel = SDK.targetManager.models(SDK.PaintProfilerModel)[0];
- if (!paintProfilerModel)
+ if (!paintProfilerModel) {
return;
+ }
const paintProfilerView = this._paintProfilerView();
const hasProfileData = paintProfilerView.setEvent(paintProfilerModel, event);
- if (!hasProfileData)
+ if (!hasProfileData) {
return;
- if (this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.PaintProfiler))
+ }
+ if (this._tabbedPane.hasTab(Timeline.TimelineDetailsView.Tab.PaintProfiler)) {
return;
+ }
this._appendTab(
Timeline.TimelineDetailsView.Tab.PaintProfiler, Common.UIString('Paint Profiler'), paintProfilerView);
}
@@ -255,8 +269,9 @@ Timeline.TimelineDetailsView = class extends UI.VBox {
* @param {number} endTime
*/
_updateSelectedRangeStats(startTime, endTime) {
- if (!this._model || !this._track)
+ if (!this._model || !this._track) {
return;
+ }
const aggregatedStats = Timeline.TimelineUIUtils.statsForTimeRange(this._track.syncEvents(), startTime, endTime);
const startOffset = startTime - this._model.timelineModel().minimumRecordTime();
const endOffset = endTime - this._model.timelineModel().minimumRecordTime();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineEventOverview.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineEventOverview.js
index 63beaf92312..12e7600d5e9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineEventOverview.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineEventOverview.js
@@ -42,8 +42,9 @@ Timeline.TimelineEventOverview = class extends PerfUI.TimelineOverviewBase {
this.element.classList.add('overview-strip');
/** @type {?Timeline.PerformanceModel} */
this._model = null;
- if (title)
+ if (title) {
this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;
+ }
}
/**
@@ -82,16 +83,18 @@ Timeline.TimelineEventOverviewInput = class extends Timeline.TimelineEventOvervi
*/
update() {
super.update();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const height = this.height();
const descriptors = Timeline.TimelineUIUtils.eventDispatchDesciptors();
/** @type {!Map.<string,!Timeline.TimelineUIUtils.EventDispatchTypeDescriptor>} */
const descriptorsByType = new Map();
let maxPriority = -1;
for (const descriptor of descriptors) {
- for (const type of descriptor.eventTypes)
+ for (const type of descriptor.eventTypes) {
descriptorsByType.set(type, descriptor);
+ }
maxPriority = Math.max(maxPriority, descriptor.priority);
}
@@ -105,11 +108,13 @@ Timeline.TimelineEventOverviewInput = class extends Timeline.TimelineEventOvervi
for (const track of this._model.timelineModel().tracks()) {
for (let i = 0; i < track.events.length; ++i) {
const event = track.events[i];
- if (event.name !== TimelineModel.TimelineModel.RecordType.EventDispatch)
+ if (event.name !== TimelineModel.TimelineModel.RecordType.EventDispatch) {
continue;
+ }
const descriptor = descriptorsByType.get(event.args['data']['type']);
- if (!descriptor || descriptor.priority !== priority)
+ if (!descriptor || descriptor.priority !== priority) {
continue;
+ }
const start = Number.constrain(Math.floor((event.startTime - timeOffset) * scale), 0, canvasWidth);
const end = Number.constrain(Math.ceil((event.endTime - timeOffset) * scale), 0, canvasWidth);
const width = Math.max(end - start, minWidth);
@@ -133,8 +138,9 @@ Timeline.TimelineEventOverviewNetwork = class extends Timeline.TimelineEventOver
*/
update() {
super.update();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const timelineModel = this._model.timelineModel();
const bandHeight = this.height() / 2;
const timeOffset = timelineModel.minimumRecordTime();
@@ -185,8 +191,9 @@ Timeline.TimelineEventOverviewCPUActivity = class extends Timeline.TimelineEvent
*/
update() {
super.update();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const timelineModel = this._model.timelineModel();
const /** @const */ quantSizePx = 4 * window.devicePixelRatio;
const width = this.width();
@@ -197,19 +204,21 @@ Timeline.TimelineEventOverviewCPUActivity = class extends Timeline.TimelineEvent
const scale = width / timeSpan;
const quantTime = quantSizePx / scale;
const categories = Timeline.TimelineUIUtils.categories();
- const categoryOrder = ['idle', 'loading', 'painting', 'rendering', 'scripting', 'other'];
+ const categoryOrder = Timeline.TimelineUIUtils.getTimelineMainEventCategories();
const otherIndex = categoryOrder.indexOf('other');
const idleIndex = 0;
console.assert(idleIndex === categoryOrder.indexOf('idle'));
- for (let i = idleIndex + 1; i < categoryOrder.length; ++i)
+ for (let i = idleIndex + 1; i < categoryOrder.length; ++i) {
categories[categoryOrder[i]]._overviewIndex = i;
+ }
const backgroundContext = this._backgroundCanvas.getContext('2d');
for (const track of timelineModel.tracks()) {
- if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame)
+ if (track.type === TimelineModel.TimelineModel.TrackType.MainThread && track.forMainFrame) {
drawThreadEvents(this.context(), track.events);
- else
+ } else {
drawThreadEvents(backgroundContext, track.events);
+ }
}
applyPattern(backgroundContext);
@@ -299,8 +308,9 @@ Timeline.TimelineEventOverviewResponsiveness = class extends Timeline.TimelineEv
*/
update() {
super.update();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const height = this.height();
const timeOffset = this._model.timelineModel().minimumRecordTime();
@@ -313,16 +323,18 @@ Timeline.TimelineEventOverviewResponsiveness = class extends Timeline.TimelineEv
const markersPath = new Path2D();
for (let i = 0; i < frames.length; ++i) {
const frame = frames[i];
- if (!frame.hasWarnings())
+ if (!frame.hasWarnings()) {
continue;
+ }
paintWarningDecoration(frame.startTime, frame.duration);
}
for (const track of this._model.timelineModel().tracks()) {
const events = track.events;
for (let i = 0; i < events.length; ++i) {
- if (!TimelineModel.TimelineData.forEvent(events[i]).warning)
+ if (!TimelineModel.TimelineData.forEvent(events[i]).warning) {
continue;
+ }
paintWarningDecoration(events[i].startTime, events[i].duration);
}
}
@@ -362,16 +374,19 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
update() {
super.update();
const frames = this._model ? this._model.filmStripModel().frames() : [];
- if (!frames.length)
+ if (!frames.length) {
return;
+ }
const drawGeneration = Symbol('drawGeneration');
this._drawGeneration = drawGeneration;
this._imageByFrame(frames[0]).then(image => {
- if (this._drawGeneration !== drawGeneration)
+ if (this._drawGeneration !== drawGeneration) {
return;
- if (!image || !image.naturalWidth || !image.naturalHeight)
+ }
+ if (!image || !image.naturalWidth || !image.naturalHeight) {
return;
+ }
const imageHeight = this.height() - 2 * Timeline.TimelineFilmStripOverview.Padding;
const imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);
const popoverScale = Math.min(200 / image.naturalWidth, 1);
@@ -398,11 +413,13 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
* @param {number} imageHeight
*/
_drawFrames(imageWidth, imageHeight) {
- if (!imageWidth || !this._model)
+ if (!imageWidth || !this._model) {
return;
+ }
const filmStripModel = this._model.filmStripModel();
- if (!filmStripModel.frames().length)
+ if (!filmStripModel.frames().length) {
return;
+ }
const padding = Timeline.TimelineFilmStripOverview.Padding;
const width = this.width();
const zeroTime = filmStripModel.zeroTime();
@@ -415,8 +432,9 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
for (let x = padding; x < width; x += imageWidth + 2 * padding) {
const time = zeroTime + (x + imageWidth / 2) * scale;
const frame = filmStripModel.frameByTimestamp(time);
- if (!frame)
+ if (!frame) {
continue;
+ }
context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);
this._imageByFrame(frame).then(drawFrameImage.bind(this, x));
}
@@ -430,8 +448,9 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
*/
function drawFrameImage(x, image) {
// Ignore draws deferred from a previous update call.
- if (this._drawGeneration !== drawGeneration || !image)
+ if (this._drawGeneration !== drawGeneration || !image) {
return;
+ }
context.drawImage(image, x, 1, imageWidth, imageHeight);
}
}
@@ -442,13 +461,15 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
* @return {!Promise<?Element>}
*/
overviewInfoPromise(x) {
- if (!this._model || !this._model.filmStripModel().frames().length)
+ if (!this._model || !this._model.filmStripModel().frames().length) {
return Promise.resolve(/** @type {?Element} */ (null));
+ }
const time = this.calculator().positionToTime(x);
const frame = this._model.filmStripModel().frameByTimestamp(time);
- if (frame === this._lastFrame)
+ if (frame === this._lastFrame) {
return Promise.resolve(this._lastElement);
+ }
const imagePromise = frame ? this._imageByFrame(frame) : Promise.resolve(this._emptyImage);
return imagePromise.then(createFrameElement.bind(this));
@@ -459,8 +480,9 @@ Timeline.TimelineFilmStripOverview = class extends Timeline.TimelineEventOvervie
*/
function createFrameElement(image) {
const element = createElementWithClass('div', 'frame');
- if (image)
+ if (image) {
element.createChild('div', 'thumbnail').appendChild(image);
+ }
this._lastFrame = frame;
this._lastElement = element;
return element;
@@ -494,11 +516,13 @@ Timeline.TimelineEventOverviewFrames = class extends Timeline.TimelineEventOverv
*/
update() {
super.update();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const frames = this._model.frames();
- if (!frames.length)
+ if (!frames.length) {
return;
+ }
const height = this.height();
const /** @const */ padding = 1 * window.devicePixelRatio;
const /** @const */ baseFrameDurationMs = 1e3 / 60;
@@ -581,21 +605,24 @@ Timeline.TimelineEventOverviewMemory = class extends Timeline.TimelineEventOverv
function isUpdateCountersEvent(event) {
return event.name === TimelineModel.TimelineModel.RecordType.UpdateCounters;
}
- for (let i = 0; i < trackEvents.length; i++)
+ for (let i = 0; i < trackEvents.length; i++) {
trackEvents[i] = trackEvents[i].filter(isUpdateCountersEvent);
+ }
/**
* @param {!SDK.TracingModel.Event} event
*/
function calculateMinMaxSizes(event) {
const counters = event.args.data;
- if (!counters || !counters.jsHeapSizeUsed)
+ if (!counters || !counters.jsHeapSizeUsed) {
return;
+ }
maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);
minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);
}
- for (let i = 0; i < trackEvents.length; i++)
+ for (let i = 0; i < trackEvents.length; i++) {
trackEvents[i].forEach(calculateMinMaxSizes);
+ }
minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);
const lineWidth = 1;
@@ -611,15 +638,17 @@ Timeline.TimelineEventOverviewMemory = class extends Timeline.TimelineEventOverv
*/
function buildHistogram(event) {
const counters = event.args.data;
- if (!counters || !counters.jsHeapSizeUsed)
+ if (!counters || !counters.jsHeapSizeUsed) {
return;
+ }
const x = Math.round((event.startTime - minTime) * xFactor);
const y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);
// TODO(alph): use sum instead of max.
histogram[x] = Math.max(histogram[x] || 0, y);
}
- for (let i = 0; i < trackEvents.length; i++)
+ for (let i = 0; i < trackEvents.length; i++) {
trackEvents[i].forEach(buildHistogram);
+ }
const ctx = this.context();
const heightBeyondView = height + lowerOffset + lineWidth;
@@ -631,16 +660,18 @@ Timeline.TimelineEventOverviewMemory = class extends Timeline.TimelineEventOverv
let isFirstPoint = true;
let lastX = 0;
for (let x = 0; x < histogram.length; x++) {
- if (typeof histogram[x] === 'undefined')
+ if (typeof histogram[x] === 'undefined') {
continue;
+ }
if (isFirstPoint) {
isFirstPoint = false;
y = histogram[x];
ctx.lineTo(-lineWidth, height - y);
}
const nextY = histogram[x];
- if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1)
+ if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1) {
ctx.lineTo(x, height - y);
+ }
y = nextY;
ctx.lineTo(x, height - y);
lastX = x;
@@ -704,3 +735,142 @@ Timeline.Quantizer = class {
this._remainder = this._quantDuration - interval;
}
};
+
+/**
+ * @unrestricted
+ */
+Timeline.TimelineEventOverviewCoverage = class extends Timeline.TimelineEventOverview {
+ constructor() {
+ super('coverage', Common.UIString('COVERAGE'));
+ this._heapSizeLabel = this.element.createChild('div', 'timeline-overview-coverage-label');
+ }
+
+ resetHeapSizeLabels() {
+ this._heapSizeLabel.textContent = '';
+ }
+
+ /**
+ * @override
+ * @param {?Timeline.PerformanceModel} model
+ */
+ setModel(model) {
+ super.setModel(model);
+ if (this._model) {
+ this._coverageModel = model.mainTarget().model(Coverage.CoverageModel);
+ }
+ }
+
+ /**
+ * @override
+ */
+ update() {
+ super.update();
+ const ratio = window.devicePixelRatio;
+
+ if (!this._coverageModel) {
+ return;
+ }
+
+ let total = 0;
+ let total_used = 0;
+ /** @type {!Map<!Coverage.CoverageInfo>} */
+ const usedByTimestamp = new Map();
+ /** @type {!Map<!Coverage.CoverageInfo>} */
+ const totalByTimestamp = new Map();
+ for (const urlInfo of this._coverageModel.entries()) {
+ for (const info of urlInfo.entries()) {
+ total += info.size();
+ for (const [stamp, used] of info.usedByTimestamp()) {
+ total_used += used;
+
+ if (!totalByTimestamp.has(stamp)) {
+ totalByTimestamp.set(stamp, new Set());
+ }
+
+ totalByTimestamp.get(stamp).add(info);
+
+ if (!usedByTimestamp.has(stamp)) {
+ usedByTimestamp.set(stamp, used);
+ } else {
+ usedByTimestamp.set(stamp, usedByTimestamp.get(stamp) + used);
+ }
+ }
+ }
+ }
+
+ /** @type {!Set<!Coverage.CoverageInfo>} */
+ const seen = new Set();
+ /** @type {!Map<number, number>} */
+ const coverageByTimestamp = new Map();
+ let sumTotal = 0, sumUsed = 0;
+
+ const sortedByTimestamp = Array.from(totalByTimestamp.entries()).sort((a, b) => a[0] - b[0]);
+ for (const [stamp, infos] of sortedByTimestamp) {
+ for (const info of infos.values()) {
+ if (seen.has(info)) {
+ continue;
+ }
+
+ seen.add(info);
+ sumTotal += info.size();
+ }
+ sumUsed += usedByTimestamp.get(stamp);
+ coverageByTimestamp.set(stamp, sumUsed / sumTotal);
+ }
+
+ const percentUsed = total ? Math.round(100 * total_used / total) : 0;
+ const lowerOffset = 3 * ratio;
+
+ const minTime = this._model.recordStartTime();
+ const maxTime =
+ minTime + (this._model.timelineModel().maximumRecordTime() - this._model.timelineModel().minimumRecordTime());
+
+ const lineWidth = 1;
+ const width = this.width();
+ const height = this.height() - lowerOffset;
+ const xFactor = width / (maxTime - minTime);
+ const yFactor = height - lineWidth;
+
+ let yOffset = 0;
+ const ctx = this.context();
+ const heightBeyondView = height + lowerOffset + lineWidth;
+ ctx.translate(0.5, 0.5);
+ ctx.beginPath();
+ ctx.moveTo(-lineWidth, heightBeyondView);
+
+ ctx.lineTo(-lineWidth, height - yOffset);
+
+ for (const [stamp, coverage] of coverageByTimestamp) {
+ if (stamp > maxTime) {
+ break;
+ }
+ const x = (stamp - minTime) * xFactor;
+ yOffset = coverage * yFactor;
+ ctx.lineTo(x, height - yOffset);
+ }
+
+ ctx.lineTo(width + lineWidth, height - yOffset);
+ ctx.lineTo(width + lineWidth, heightBeyondView);
+ ctx.closePath();
+ ctx.fillStyle = 'hsla(220, 90%, 70%, 0.2)';
+ ctx.fill();
+ ctx.lineWidth = lineWidth;
+ ctx.strokeStyle = 'hsl(220, 90%, 70%)';
+ ctx.stroke();
+
+ for (const [stamp, coverage] of coverageByTimestamp) {
+ if (stamp > maxTime) {
+ break;
+ }
+ ctx.beginPath();
+ const x = (stamp - minTime) * xFactor;
+ const y = height - coverage * yFactor;
+ ctx.arc(x, y, 2 * lineWidth, 0, 2 * Math.PI, false);
+ ctx.closePath();
+ ctx.stroke();
+ ctx.fill();
+ }
+
+ this._heapSizeLabel.textContent = `${percentUsed}% used`;
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
index 5f51406c10e..3530f485511 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartDataProvider.js
@@ -112,20 +112,25 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const entryType = this._entryType(entryIndex);
if (entryType === entryTypes.Event) {
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
- if (event.phase === SDK.TracingModel.Phase.AsyncStepInto || event.phase === SDK.TracingModel.Phase.AsyncStepPast)
+ if (event.phase === SDK.TracingModel.Phase.AsyncStepInto ||
+ event.phase === SDK.TracingModel.Phase.AsyncStepPast) {
return event.name + ':' + event.args['step'];
- if (event._blackboxRoot)
+ }
+ if (event._blackboxRoot) {
return Common.UIString('Blackboxed');
- if (this._performanceModel.timelineModel().isMarkerEvent(event))
+ }
+ if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
return Timeline.TimelineUIUtils.markerShortTitle(event);
+ }
return Timeline.TimelineUIUtils.eventTitle(event);
}
if (entryType === entryTypes.ExtensionEvent) {
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
return event.name;
}
- if (entryType === entryTypes.Screenshot)
+ if (entryType === entryTypes.Screenshot) {
return '';
+ }
let title = this._entryIndexToTitle[entryIndex];
if (!title) {
title = Common.UIString('Unexpected entryIndex %d', entryIndex);
@@ -189,22 +194,25 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {!PerfUI.FlameChart.TimelineData}
*/
timelineData() {
- if (this._timelineData)
+ if (this._timelineData) {
return this._timelineData;
+ }
this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
- if (!this._model)
+ if (!this._model) {
return this._timelineData;
+ }
this._flowEventIndexById.clear();
this._minimumBoundary = this._model.minimumRecordTime();
this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTime() - this._minimumBoundary;
this._currentLevel = 0;
- if (this._model.isGenericTrace())
+ if (this._model.isGenericTrace()) {
this._processGenericTrace();
- else
+ } else {
this._processInspectorTrace();
+ }
return this._timelineData;
}
@@ -213,8 +221,8 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const processGroupStyle = this._buildGroupStyle({shareHeaderLine: false});
const threadGroupStyle = this._buildGroupStyle({padding: 2, nestingLevel: 1, shareHeaderLine: false});
const eventEntryType = Timeline.TimelineFlameChartDataProvider.EntryType.Event;
- /** @type {!Multimap<!SDK.TracingModel.Process, !TimelineModel.TimelineModel.Track>} */
- const tracksByProcess = new Multimap();
+ /** @type {!Platform.Multimap<!SDK.TracingModel.Process, !TimelineModel.TimelineModel.Track>} */
+ const tracksByProcess = new Platform.Multimap();
for (const track of this._model.tracks()) {
if (track.thread !== null) {
tracksByProcess.set(track.thread.process(), track);
@@ -231,8 +239,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
for (const track of tracksByProcess.get(process)) {
const group = this._appendSyncEvents(
track, track.events, track.name, threadGroupStyle, eventEntryType, true /* selectable */);
- if (!this._timelineData.selectedGroup || track.name === TimelineModel.TimelineModel.BrowserMainThreadName)
+ if (!this._timelineData.selectedGroup || track.name === TimelineModel.TimelineModel.BrowserMainThreadName) {
this._timelineData.selectedGroup = group;
+ }
}
}
}
@@ -297,8 +306,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const group = this._appendSyncEvents(
track, track.events, track.url ? ls`Main \u2014 ${track.url}` : ls`Main`, this._headerLevel1,
eventEntryType, true /* selectable */);
- if (group)
+ if (group) {
this._timelineData.selectedGroup = group;
+ }
} else {
this._appendSyncEvents(
track, track.events, track.url ? ls`Frame \u2014 ${track.url}` : ls`Subframe`, this._headerLevel1,
@@ -311,8 +321,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
this._headerLevel1, eventEntryType, true /* selectable */);
break;
case TimelineModel.TimelineModel.TrackType.Raster:
- if (!rasterCount)
+ if (!rasterCount) {
this._appendHeader(ls`Raster`, this._headerLevel1, false /* selectable */);
+ }
++rasterCount;
this._appendSyncEvents(
track, track.events, ls`Rasterizer Thread ${rasterCount}`, this._headerLevel2, eventEntryType,
@@ -330,11 +341,13 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
break;
}
}
- if (this._timelineData.selectedGroup)
+ if (this._timelineData.selectedGroup) {
this._timelineData.selectedGroup.expanded = true;
+ }
- for (let extensionIndex = 0; extensionIndex < this._extensionInfo.length; extensionIndex++)
+ for (let extensionIndex = 0; extensionIndex < this._extensionInfo.length; extensionIndex++) {
this._innerAppendExtensionEvents(extensionIndex);
+ }
this._markers.sort((a, b) => a.startTime() - b.startTime());
this._timelineData.markers = this._markers;
@@ -368,15 +381,19 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
this.timelineData();
for (let i = 0; i < this._entryData.length; ++i) {
- if (this._entryType(i) !== entryTypes.Event)
+ if (this._entryType(i) !== entryTypes.Event) {
continue;
+ }
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[i]);
- if (event.startTime > endTime)
+ if (event.startTime > endTime) {
continue;
- if ((event.endTime || event.startTime) < startTime)
+ }
+ if ((event.endTime || event.startTime) < startTime) {
continue;
- if (filter.accept(event))
+ }
+ if (filter.accept(event)) {
result.push(i);
+ }
}
result.sort(
(a, b) => SDK.TracingModel.Event.compareStartTime(
@@ -395,12 +412,13 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {?PerfUI.FlameChart.Group}
*/
_appendSyncEvents(track, events, title, style, entryType, selectable) {
- if (!events.length)
+ if (!events.length) {
return null;
+ }
const isExtension = entryType === Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;
const openEvents = [];
- const flowEventsEnabled = Runtime.experiments.isEnabled('timelineFlowEvents');
- const blackboxingEnabled = !isExtension && Runtime.experiments.isEnabled('blackboxJSFramesOnTimeline');
+ const flowEventsEnabled = Root.Runtime.experiments.isEnabled('timelineFlowEvents');
+ const blackboxingEnabled = !isExtension && Root.Runtime.experiments.isEnabled('blackboxJSFramesOnTimeline');
let maxStackDepth = 0;
let group = null;
if (track && track.type === TimelineModel.TimelineModel.TrackType.MainThread) {
@@ -415,40 +433,50 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
Timeline.TimelineUIUtils.markerStyleForEvent(e)));
}
if (!SDK.TracingModel.isFlowPhase(e.phase)) {
- if (!e.endTime && e.phase !== SDK.TracingModel.Phase.Instant)
+ if (!e.endTime && e.phase !== SDK.TracingModel.Phase.Instant) {
continue;
- if (SDK.TracingModel.isAsyncPhase(e.phase))
+ }
+ if (SDK.TracingModel.isAsyncPhase(e.phase)) {
continue;
- if (!isExtension && !this._performanceModel.isVisible(e))
+ }
+ if (!isExtension && !this._performanceModel.isVisible(e)) {
continue;
+ }
}
- while (openEvents.length && openEvents.peekLast().endTime <= e.startTime)
+ while (openEvents.length && openEvents.peekLast().endTime <= e.startTime) {
openEvents.pop();
+ }
e._blackboxRoot = false;
if (blackboxingEnabled && this._isBlackboxedEvent(e)) {
const parent = openEvents.peekLast();
- if (parent && parent._blackboxRoot)
+ if (parent && parent._blackboxRoot) {
continue;
+ }
e._blackboxRoot = true;
}
if (!group) {
group = this._appendHeader(title, style, selectable);
- if (selectable)
+ if (selectable) {
group._track = track;
+ }
}
const level = this._currentLevel + openEvents.length;
- if (flowEventsEnabled)
+ if (flowEventsEnabled) {
this._appendFlowEvent(e, level);
+ }
const index = this._appendEvent(e, level);
- if (openEvents.length)
+ if (openEvents.length) {
this._entryParent[index] = openEvents.peekLast();
- if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e))
+ }
+ if (!isExtension && this._performanceModel.timelineModel().isMarkerEvent(e)) {
this._timelineData.entryTotalTimes[this._entryData.length] = undefined;
+ }
maxStackDepth = Math.max(maxStackDepth, openEvents.length + 1);
- if (e.endTime)
+ if (e.endTime) {
openEvents.push(e);
+ }
}
this._entryTypeByLevel.length = this._currentLevel + maxStackDepth;
this._entryTypeByLevel.fill(entryType, this._currentLevel);
@@ -461,8 +489,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {boolean}
*/
_isBlackboxedEvent(event) {
- if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame)
+ if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame) {
return false;
+ }
const url = event.args['data']['url'];
return url && this._isBlackboxedURL(url);
}
@@ -485,18 +514,21 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {?PerfUI.FlameChart.Group}
*/
_appendAsyncEventsGroup(track, header, events, style, entryType, selectable) {
- if (!events.length)
+ if (!events.length) {
return null;
+ }
const lastUsedTimeByLevel = [];
let group = null;
for (let i = 0; i < events.length; ++i) {
const asyncEvent = events[i];
- if (!this._performanceModel.isVisible(asyncEvent))
+ if (!this._performanceModel.isVisible(asyncEvent)) {
continue;
+ }
if (!group && header) {
group = this._appendHeader(header, style, selectable);
- if (selectable)
+ if (selectable) {
group._track = track;
+ }
}
const startTime = asyncEvent.startTime;
let level;
@@ -513,8 +545,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
_appendInteractionRecords() {
const interactionRecords = this._performanceModel.interactionRecords();
- if (!interactionRecords.length)
+ if (!interactionRecords.length) {
return;
+ }
this._appendHeader(ls`Interactions`, this._interactionsHeaderLevel1, false /* selectable */);
for (const segment of interactionRecords) {
const index = this._entryData.length;
@@ -536,23 +569,35 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const timelineModel = this._performanceModel.timelineModel();
for (const track of this._model.tracks()) {
for (const event of track.events) {
- if (!timelineModel.isMarkerEvent(event))
+ if (!timelineModel.isMarkerEvent(event)) {
continue;
- if (timelineModel.isLCPCandidateEvent(event) || timelineModel.isLCPInvalidateEvent(event))
+ }
+ if (timelineModel.isLCPCandidateEvent(event) || timelineModel.isLCPInvalidateEvent(event)) {
lcpEvents.push(event);
- else
+ } else {
metricEvents.push(event);
+ }
}
}
// Only the LCP event with the largest candidate index is relevant.
// Do not record an LCP event if it is an invalidate event.
if (lcpEvents.length > 0) {
- const winning_event = lcpEvents.reduce(function(a, b) {
- return Number(a.args['data']['candidateIndex']) > Number(b.args['data']['candidateIndex']) ? a : b;
- });
- if (timelineModel.isLCPCandidateEvent(winning_event))
- metricEvents.push(winning_event);
+ /** @type {!Map<string, !SDK.TracingModel.Event>} */
+ const lcpEventsByNavigationId = new Map();
+ for (const e of lcpEvents) {
+ const key = e.args['data']['navigationId'];
+ const previousLastEvent = lcpEventsByNavigationId.get(key);
+
+ if (!previousLastEvent || previousLastEvent.args['data']['candidateIndex'] < e.args['data']['candidateIndex']) {
+ lcpEventsByNavigationId.set(key, e);
+ }
+ }
+
+ const latestCandidates = Array.from(lcpEventsByNavigationId.values());
+ const latestEvents = latestCandidates.filter(e => timelineModel.isLCPCandidateEvent(e));
+
+ metricEvents.push(...latestEvents);
}
metricEvents.sort(SDK.TracingModel.Event.compareStartTime);
@@ -581,8 +626,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
}
++this._currentLevel;
- if (!hasFilmStrip)
+ if (!hasFilmStrip) {
return;
+ }
this._appendHeader('', this._screenshotsHeader, false /* selectable */);
this._entryTypeByLevel[this._currentLevel] = Timeline.TimelineFlameChartDataProvider.EntryType.Screenshot;
let prevTimestamp;
@@ -590,12 +636,14 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
this._entryData.push(screenshot);
this._timelineData.entryLevels.push(this._currentLevel);
this._timelineData.entryStartTimes.push(screenshot.timestamp);
- if (prevTimestamp)
+ if (prevTimestamp) {
this._timelineData.entryTotalTimes.push(screenshot.timestamp - prevTimestamp);
+ }
prevTimestamp = screenshot.timestamp;
}
- if (screenshots.length)
+ if (screenshots.length) {
this._timelineData.entryTotalTimes.push(this._model.maximumRecordTime() - prevTimestamp);
+ }
++this._currentLevel;
}
@@ -628,10 +676,11 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
'%s (self %s)', Number.millisToString(totalTime, true), Number.millisToString(selfTime, true)) :
Number.millisToString(totalTime, true);
}
- if (this._performanceModel.timelineModel().isMarkerEvent(event))
+ if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
title = Timeline.TimelineUIUtils.eventTitle(event);
- else
+ } else {
title = this.entryTitle(entryIndex);
+ }
warning = Timeline.TimelineUIUtils.eventWarning(event);
} else if (type === Timeline.TimelineFlameChartDataProvider.EntryType.Frame) {
const frame = /** @type {!TimelineModel.TimelineFrame} */ (this._entryData[entryIndex]);
@@ -666,8 +715,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
// This is not annotated due to closure compiler failure to properly infer cache container's template type.
function patchColorAndCache(cache, key, lookupColor) {
let color = cache.get(key);
- if (color)
+ if (color) {
return color;
+ }
const parsedColor = Common.Color.parse(lookupColor(key));
color = parsedColor.setAlpha(0.7).asString(Common.Color.Format.RGBA) || '';
cache.set(key, color);
@@ -678,15 +728,19 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const type = this._entryType(entryIndex);
if (type === entryTypes.Event) {
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
- if (this._model.isGenericTrace())
+ if (this._model.isGenericTrace()) {
return this._genericTraceEventColor(event);
- if (this._performanceModel.timelineModel().isMarkerEvent(event))
+ }
+ if (this._performanceModel.timelineModel().isMarkerEvent(event)) {
return Timeline.TimelineUIUtils.markerStyleForEvent(event).color;
- if (!SDK.TracingModel.isAsyncPhase(event.phase))
+ }
+ if (!SDK.TracingModel.isAsyncPhase(event.phase)) {
return this._colorForEvent(event);
+ }
if (event.hasCategory(TimelineModel.TimelineModel.Category.Console) ||
- event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
+ event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)) {
return this._consoleColorGenerator.colorForID(event.name);
+ }
if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
const phase =
TimelineModel.TimelineIRModel.phaseForEvent(event) || TimelineModel.TimelineIRModel.Phases.Uncategorized;
@@ -696,10 +750,12 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const category = Timeline.TimelineUIUtils.eventStyle(event).category;
return patchColorAndCache(this._asyncColorByCategory, category, () => category.color);
}
- if (type === entryTypes.Frame)
+ if (type === entryTypes.Frame) {
return 'white';
- if (type === entryTypes.InteractionRecord)
+ }
+ if (type === entryTypes.InteractionRecord) {
return 'transparent';
+ }
if (type === entryTypes.ExtensionEvent) {
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
return this._extensionColorGenerator.colorForID(event.name);
@@ -761,8 +817,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
}
const image = this._screenshotImageCache.get(screenshot);
- if (!image)
+ if (!image) {
return;
+ }
const imageX = barX + 1;
const imageY = barY + 1;
const imageHeight = barHeight - 2;
@@ -826,8 +883,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
context.fillRect(barX, barY + barHeight - 3, width, 2);
}
}
- if (TimelineModel.TimelineData.forEvent(event).warning)
+ if (TimelineModel.TimelineData.forEvent(event).warning) {
paintWarningDecoration(barX, barWidth - 1.5);
+ }
}
/**
@@ -860,10 +918,12 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
forceDecoration(entryIndex) {
const entryTypes = Timeline.TimelineFlameChartDataProvider.EntryType;
const type = this._entryType(entryIndex);
- if (type === entryTypes.Frame)
+ if (type === entryTypes.Frame) {
return true;
- if (type === entryTypes.Screenshot)
+ }
+ if (type === entryTypes.Screenshot) {
return true;
+ }
if (type === entryTypes.Event) {
const event = /** @type {!SDK.TracingModel.Event} */ (this._entryData[entryIndex]);
@@ -877,8 +937,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
*/
appendExtensionEvents(entry) {
this._extensionInfo.push(entry);
- if (this._timelineData)
+ if (this._timelineData) {
this._innerAppendExtensionEvents(this._extensionInfo.length - 1);
+ }
}
/**
@@ -888,13 +949,15 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
const entry = this._extensionInfo[index];
const entryType = Timeline.TimelineFlameChartDataProvider.EntryType.ExtensionEvent;
const allThreads = [].concat(...entry.model.sortedProcesses().map(process => process.sortedThreads()));
- if (!allThreads.length)
+ if (!allThreads.length) {
return;
+ }
const singleTrack =
allThreads.length === 1 && (!allThreads[0].events().length || !allThreads[0].asyncEvents().length);
- if (!singleTrack)
+ if (!singleTrack) {
this._appendHeader(entry.title, this._headerLevel1, false /* selectable */);
+ }
const style = singleTrack ? this._headerLevel2 : this._headerLevel1;
let threadIndex = 0;
for (const thread of allThreads) {
@@ -1022,8 +1085,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
timelineSelection = Timeline.TimelineSelection.fromFrame(
/** @type {!TimelineModel.TimelineFrame} */ (this._entryData[entryIndex]));
}
- if (timelineSelection)
+ if (timelineSelection) {
this._lastSelection = new Timeline.TimelineFlameChartView.Selection(timelineSelection, entryIndex);
+ }
return timelineSelection;
}
@@ -1051,16 +1115,19 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {number}
*/
entryIndexForSelection(selection) {
- if (!selection || selection.type() === Timeline.TimelineSelection.Type.Range)
+ if (!selection || selection.type() === Timeline.TimelineSelection.Type.Range) {
return -1;
+ }
- if (this._lastSelection && this._lastSelection.timelineSelection.object() === selection.object())
+ if (this._lastSelection && this._lastSelection.timelineSelection.object() === selection.object()) {
return this._lastSelection.entryIndex;
+ }
const index = this._entryData.indexOf(
/** @type {!SDK.TracingModel.Event|!TimelineModel.TimelineFrame|!TimelineModel.TimelineIRModel.Phases} */
(selection.object()));
- if (index !== -1)
+ if (index !== -1) {
this._lastSelection = new Timeline.TimelineFlameChartView.Selection(selection, index);
+ }
return index;
}
@@ -1069,8 +1136,9 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
* @return {boolean}
*/
buildFlowForInitiator(entryIndex) {
- if (this._lastInitiatorEntry === entryIndex)
+ if (this._lastInitiatorEntry === entryIndex) {
return false;
+ }
this._lastInitiatorEntry = entryIndex;
let event = this.eventByIndex(entryIndex);
const td = this._timelineData;
@@ -1083,11 +1151,13 @@ Timeline.TimelineFlameChartDataProvider = class extends Common.Object {
let initiator;
for (; event; event = this._eventParent(event)) {
initiator = TimelineModel.TimelineData.forEvent(event).initiator();
- if (initiator)
+ if (initiator) {
break;
+ }
}
- if (!initiator)
+ if (!initiator) {
break;
+ }
const eventIndex = event[Timeline.TimelineFlameChartDataProvider._indexSymbol];
const initiatorIndex = initiator[Timeline.TimelineFlameChartDataProvider._indexSymbol];
td.flowStartTimes.push(initiator.endTime || initiator.startTime);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartNetworkDataProvider.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartNetworkDataProvider.js
index 10fb33e7562..70a3c4bd5b6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartNetworkDataProvider.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartNetworkDataProvider.js
@@ -60,13 +60,15 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
* @return {!PerfUI.FlameChart.TimelineData}
*/
timelineData() {
- if (this._timelineData)
+ if (this._timelineData) {
return this._timelineData;
+ }
/** @type {!Array<!TimelineModel.TimelineModel.NetworkRequest>} */
this._requests = [];
this._timelineData = new PerfUI.FlameChart.TimelineData([], [], [], []);
- if (this._model)
+ if (this._model) {
this._appendTimelineData();
+ }
return this._timelineData;
}
@@ -101,8 +103,9 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
* @return {?Timeline.TimelineSelection}
*/
createSelection(index) {
- if (index === -1)
+ if (index === -1) {
return null;
+ }
const request = this._requests[index];
this._lastSelection =
new Timeline.TimelineFlameChartView.Selection(Timeline.TimelineSelection.fromNetworkRequest(request), index);
@@ -114,14 +117,17 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
* @return {number}
*/
entryIndexForSelection(selection) {
- if (!selection)
+ if (!selection) {
return -1;
+ }
- if (this._lastSelection && this._lastSelection.timelineSelection.object() === selection.object())
+ if (this._lastSelection && this._lastSelection.timelineSelection.object() === selection.object()) {
return this._lastSelection.entryIndex;
+ }
- if (selection.type() !== Timeline.TimelineSelection.Type.NetworkRequest)
+ if (selection.type() !== Timeline.TimelineSelection.Type.NetworkRequest) {
return -1;
+ }
const request = /** @type{!TimelineModel.TimelineModel.NetworkRequest} */ (selection.object());
const index = this._requests.indexOf(request);
if (index !== -1) {
@@ -186,8 +192,9 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
*/
decorateEntry(index, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio) {
const request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]);
- if (!request.timing)
+ if (!request.timing) {
return false;
+ }
const beginTime = request.beginTime();
/**
@@ -279,8 +286,9 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
const /** @const */ minTextWidthPx = 20;
if (textWidth >= minTextWidthPx) {
text = this.entryTitle(index) || '';
- if (request.fromServiceWorker)
+ if (request.fromServiceWorker) {
text = '⚙ ' + text;
+ }
if (text) {
const /** @const */ textPadding = 4;
const /** @const */ textBaseline = 5;
@@ -311,15 +319,17 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
prepareHighlightedEntryInfo(index) {
const /** @const */ maxURLChars = 80;
const request = /** @type {!TimelineModel.TimelineModel.NetworkRequest} */ (this._requests[index]);
- if (!request.url)
+ if (!request.url) {
return null;
+ }
const element = createElement('div');
const root = UI.createShadowRootWithCoreStyles(element, 'timeline/timelineFlamechartPopover.css');
const contents = root.createChild('div', 'timeline-flamechart-popover');
const startTime = request.getStartTime();
const duration = request.endTime - startTime;
- if (startTime && isFinite(duration))
+ if (startTime && isFinite(duration)) {
contents.createChild('span', 'timeline-info-network-time').textContent = Number.millisToString(duration, true);
+ }
if (typeof request.priority === 'string') {
const div = contents.createChild('span');
div.textContent =
@@ -355,8 +365,9 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
}
_updateTimelineData() {
- if (!this._timelineData)
+ if (!this._timelineData) {
return;
+ }
const lastTimeByLevel = [];
let maxLevel = 0;
for (let i = 0; i < this._requests.length; ++i) {
@@ -367,15 +378,17 @@ Timeline.TimelineFlameChartNetworkDataProvider = class {
this._timelineData.entryLevels[i] = -1;
continue;
}
- while (lastTimeByLevel.length && lastTimeByLevel.peekLast() <= beginTime)
+ while (lastTimeByLevel.length && lastTimeByLevel.peekLast() <= beginTime) {
lastTimeByLevel.pop();
+ }
this._timelineData.entryLevels[i] = lastTimeByLevel.length;
lastTimeByLevel.push(r.endTime);
maxLevel = Math.max(maxLevel, lastTimeByLevel.length);
}
for (let i = 0; i < this._requests.length; ++i) {
- if (this._timelineData.entryLevels[i] === -1)
+ if (this._timelineData.entryLevels[i] === -1) {
this._timelineData.entryLevels[i] = maxLevel;
+ }
}
this._timelineData = new PerfUI.FlameChart.TimelineData(
this._timelineData.entryLevels, this._timelineData.entryTotalTimes, this._timelineData.entryStartTimes,
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartView.js
index afaea6a44ad..22ee9279949 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineFlameChartView.js
@@ -74,7 +74,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
this._onMainEntrySelected = this._onEntrySelected.bind(this, this._mainDataProvider);
this._onNetworkEntrySelected = this._onEntrySelected.bind(this, this._networkDataProvider);
this._mainFlameChart.addEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onMainEntrySelected, this);
+ this._mainFlameChart.addEventListener(PerfUI.FlameChart.Events.EntryInvoked, this._onMainEntrySelected, this);
this._networkFlameChart.addEventListener(PerfUI.FlameChart.Events.EntrySelected, this._onNetworkEntrySelected, this);
+ this._networkFlameChart.addEventListener(PerfUI.FlameChart.Events.EntryInvoked, this._onNetworkEntrySelected, this);
this._mainFlameChart.addEventListener(PerfUI.FlameChart.Events.EntryHighlighted, this._onEntryHighlighted, this);
this._nextExtensionIndex = 0;
@@ -92,8 +94,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
_updateColorMapper() {
/** @type {!Map<string, string>} */
this._urlToColorCache = new Map();
- if (!this._model)
+ if (!this._model) {
return;
+ }
const colorByProduct = this._groupBySetting.get() === Timeline.AggregatedTimelineTreeView.GroupBy.Product;
this._mainDataProvider.setEventColorMapping(
colorByProduct ? this._colorByProductForEvent.bind(this) : Timeline.TimelineUIUtils.eventColor);
@@ -146,8 +149,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
* @param {?PerfUI.FlameChart.Group} group
*/
updateSelectedGroup(flameChart, group) {
- if (flameChart !== this._mainFlameChart)
+ if (flameChart !== this._mainFlameChart) {
return;
+ }
const track = group ? this._mainDataProvider.groupTrack(group) : null;
this._selectedTrack = track;
this._updateTrack();
@@ -157,8 +161,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
* @param {?Timeline.PerformanceModel} model
*/
setModel(model) {
- if (model === this._model)
+ if (model === this._model) {
return;
+ }
Common.EventTarget.removeEventListeners(this._eventListeners);
this._model = model;
this._selectedTrack = null;
@@ -203,11 +208,13 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
}
_appendExtensionData() {
- if (!this._model)
+ if (!this._model) {
return;
+ }
const extensions = this._model.extensionInfo();
- while (this._nextExtensionIndex < extensions.length)
+ while (this._nextExtensionIndex < extensions.length) {
this._mainDataProvider.appendExtensionEvents(extensions[this._nextExtensionIndex++]);
+ }
this._mainFlameChart.scheduleUpdate();
}
@@ -218,15 +225,18 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
SDK.OverlayModel.hideDOMNodeHighlight();
const entryIndex = /** @type {number} */ (commonEvent.data);
const event = this._mainDataProvider.eventByIndex(entryIndex);
- if (!event)
+ if (!event) {
return;
+ }
const target = this._model && this._model.timelineModel().targetByEvent(event);
- if (!target)
+ if (!target) {
return;
+ }
const timelineData = TimelineModel.TimelineData.forEvent(event);
const backendNodeId = timelineData.backendNodeId;
- if (!backendNodeId)
+ if (!backendNodeId) {
return;
+ }
new SDK.DeferredDOMNode(target, backendNodeId).highlight();
}
@@ -236,10 +246,11 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
highlightEvent(event) {
const entryIndex =
event ? this._mainDataProvider.entryIndexForSelection(Timeline.TimelineSelection.fromTraceEvent(event)) : -1;
- if (entryIndex >= 0)
+ if (entryIndex >= 0) {
this._mainFlameChart.highlightEntry(entryIndex);
- else
+ } else {
this._mainFlameChart.hideHighlight();
+ }
}
/**
@@ -258,17 +269,19 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
this._networkFlameChartGroupExpansionSetting.addChangeListener(this.resizeToPreferredHeights, this);
this._showMemoryGraphSetting.addChangeListener(this._updateCountersGraphToggle, this);
Bindings.blackboxManager.addChangeListener(this._boundRefresh);
- if (this._needsResizeToPreferredHeights)
+ if (this._needsResizeToPreferredHeights) {
this.resizeToPreferredHeights();
+ }
this._mainFlameChart.scheduleUpdate();
this._networkFlameChart.scheduleUpdate();
}
_updateCountersGraphToggle() {
- if (this._showMemoryGraphSetting.get())
+ if (this._showMemoryGraphSetting.get()) {
this._chartSplitWidget.showBoth();
- else
+ } else {
this._chartSplitWidget.hideSidebar();
+ }
}
/**
@@ -279,8 +292,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
this._mainFlameChart.setSelectedEntry(index);
index = this._networkDataProvider.entryIndexForSelection(selection);
this._networkFlameChart.setSelectedEntry(index);
- if (this._detailsView)
+ if (this._detailsView) {
this._detailsView.setSelection(selection);
+ }
}
/**
@@ -289,9 +303,10 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
*/
_onEntrySelected(dataProvider, event) {
const entryIndex = /** @type{number} */ (event.data);
- if (Runtime.experiments.isEnabled('timelineEventInitiators') && dataProvider === this._mainDataProvider) {
- if (this._mainDataProvider.buildFlowForInitiator(entryIndex))
+ if (Root.Runtime.experiments.isEnabled('timelineEventInitiators') && dataProvider === this._mainDataProvider) {
+ if (this._mainDataProvider.buildFlowForInitiator(entryIndex)) {
this._mainFlameChart.scheduleUpdate();
+ }
}
this._delegate.select(dataProvider.createSelection(entryIndex));
}
@@ -322,8 +337,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchResults || !this._searchResults.length)
+ if (!this._searchResults || !this._searchResults.length) {
return;
+ }
const index = typeof this._selectedSearchResult !== 'undefined' ?
this._searchResults.indexOf(this._selectedSearchResult) :
-1;
@@ -334,8 +350,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchResults || !this._searchResults.length)
+ if (!this._searchResults || !this._searchResults.length) {
return;
+ }
const index =
typeof this._selectedSearchResult !== 'undefined' ? this._searchResults.indexOf(this._selectedSearchResult) : 0;
this._selectSearchResult(mod(index - 1, this._searchResults.length));
@@ -374,17 +391,20 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
const oldSelectedSearchResult = this._selectedSearchResult;
delete this._selectedSearchResult;
this._searchResults = [];
- if (!this._searchRegex || !this._model)
+ if (!this._searchRegex || !this._model) {
return;
+ }
const regExpFilter = new Timeline.TimelineFilters.RegExp(this._searchRegex);
const window = this._model.window();
this._searchResults = this._mainDataProvider.search(window.left, window.right, regExpFilter);
this._searchableView.updateSearchMatchesCount(this._searchResults.length);
- if (!shouldJump || !this._searchResults.length)
+ if (!shouldJump || !this._searchResults.length) {
return;
+ }
let selectedIndex = this._searchResults.indexOf(oldSelectedSearchResult);
- if (selectedIndex === -1)
+ if (selectedIndex === -1) {
selectedIndex = jumpBackwards ? this._searchResults.length - 1 : 0;
+ }
this._selectSearchResult(selectedIndex);
}
@@ -392,8 +412,9 @@ Timeline.TimelineFlameChartView = class extends UI.VBox {
* @override
*/
searchCanceled() {
- if (typeof this._selectedSearchResult !== 'undefined')
+ if (typeof this._selectedSearchResult !== 'undefined') {
this._delegate.select(null);
+ }
delete this._searchResults;
delete this._selectedSearchResult;
delete this._searchRegex;
@@ -466,8 +487,9 @@ Timeline.TimelineFlameChartMarker = class {
* @return {?string}
*/
title() {
- if (this._style.lowPriority)
+ if (this._style.lowPriority) {
return null;
+ }
const startTime = Number.millisToString(this._startOffset);
return ls`${this._style.title} at ${startTime}`;
}
@@ -482,8 +504,9 @@ Timeline.TimelineFlameChartMarker = class {
draw(context, x, height, pixelsPerMillisecond) {
const lowPriorityVisibilityThresholdInPixelsPerMs = 4;
- if (this._style.lowPriority && pixelsPerMillisecond < lowPriorityVisibilityThresholdInPixelsPerMs)
+ if (this._style.lowPriority && pixelsPerMillisecond < lowPriorityVisibilityThresholdInPixelsPerMs) {
return;
+ }
context.save();
if (this._style.tall) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
index ecd5308d74e..2834f25e291 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
@@ -33,8 +33,9 @@ Timeline.TimelineHistoryManager = class {
this._buildPreview(performanceModel);
this._button.setText(this._title(performanceModel));
this._updateState();
- if (this._recordings.length <= Timeline.TimelineHistoryManager._maxRecordings)
+ if (this._recordings.length <= Timeline.TimelineHistoryManager._maxRecordings) {
return;
+ }
const lruModel = this._recordings.reduce((a, b) => lastUsedTime(a) < lastUsedTime(b) ? a : b);
this._recordings.splice(this._recordings.indexOf(lruModel), 1);
lruModel.dispose();
@@ -73,13 +74,15 @@ Timeline.TimelineHistoryManager = class {
* @return {!Promise<?Timeline.PerformanceModel>}
*/
async showHistoryDropDown() {
- if (this._recordings.length < 2 || !this._enabled)
+ if (this._recordings.length < 2 || !this._enabled) {
return null;
+ }
const model = await Timeline.TimelineHistoryManager.DropDown.show(
this._recordings, /** @type {!Timeline.PerformanceModel} */ (this._lastActiveModel), this._button.element);
- if (!model)
+ if (!model) {
return null;
+ }
const index = this._recordings.indexOf(model);
if (index < 0) {
console.assert(false, `selected recording not found`);
@@ -98,11 +101,13 @@ Timeline.TimelineHistoryManager = class {
* @return {?Timeline.PerformanceModel}
*/
navigate(direction) {
- if (!this._enabled || !this._lastActiveModel)
+ if (!this._enabled || !this._lastActiveModel) {
return null;
+ }
const index = this._recordings.indexOf(this._lastActiveModel);
- if (index < 0)
+ if (index < 0) {
return null;
+ }
const newIndex = Number.constrain(index + direction, 0, this._recordings.length - 1);
const model = this._recordings[newIndex];
this._setCurrentModel(model);
@@ -140,11 +145,13 @@ Timeline.TimelineHistoryManager = class {
*/
static _coarseAge(time) {
const seconds = Math.round((Date.now() - time) / 1000);
- if (seconds < 50)
+ if (seconds < 50) {
return Common.UIString('moments');
+ }
const minutes = Math.round(seconds / 60);
- if (minutes < 50)
+ if (minutes < 50) {
return Common.UIString('%s m', minutes);
+ }
const hours = Math.round(minutes / 60);
return Common.UIString('%s h', hours);
}
@@ -207,8 +214,9 @@ Timeline.TimelineHistoryManager = class {
container.style.height = this._totalHeight + 'px';
const filmStripModel = performanceModel.filmStripModel();
const lastFrame = filmStripModel.frames().peekLast();
- if (!lastFrame)
+ if (!lastFrame) {
return container;
+ }
lastFrame.imageDataPromise()
.then(data => UI.loadImageFromData(data))
.then(image => image && container.appendChild(image));
@@ -297,15 +305,17 @@ Timeline.TimelineHistoryManager.DropDown = class {
* @return {!Promise<?Timeline.PerformanceModel>}
*/
static show(models, currentModel, anchor) {
- if (Timeline.TimelineHistoryManager.DropDown._instance)
+ if (Timeline.TimelineHistoryManager.DropDown._instance) {
return Promise.resolve(/** @type {?Timeline.PerformanceModel} */ (null));
+ }
const instance = new Timeline.TimelineHistoryManager.DropDown(models);
return instance._show(anchor, currentModel);
}
static cancelIfShowing() {
- if (!Timeline.TimelineHistoryManager.DropDown._instance)
+ if (!Timeline.TimelineHistoryManager.DropDown._instance) {
return;
+ }
Timeline.TimelineHistoryManager.DropDown._instance._close(null);
}
@@ -330,8 +340,9 @@ Timeline.TimelineHistoryManager.DropDown = class {
_onMouseMove(event) {
const node = event.target.enclosingNodeOrSelfWithClass('preview-item');
const listItem = node && this._listControl.itemForNode(node);
- if (!listItem)
+ if (!listItem) {
return;
+ }
this._listControl.selectItem(listItem);
}
@@ -339,8 +350,9 @@ Timeline.TimelineHistoryManager.DropDown = class {
* @param {!Event} event
*/
_onClick(event) {
- if (!event.target.enclosingNodeOrSelfWithClass('preview-item'))
+ if (!event.target.enclosingNodeOrSelfWithClass('preview-item')) {
return;
+ }
this._close(this._listControl.selectedItem());
}
@@ -408,10 +420,12 @@ Timeline.TimelineHistoryManager.DropDown = class {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('selected');
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLayersView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLayersView.js
index 29471166d50..9342274ebb9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLayersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLayersView.js
@@ -46,10 +46,11 @@ Timeline.TimelineLayersView = class extends UI.SplitWidget {
*/
showLayerTree(frameLayerTree) {
this._frameLayerTree = frameLayerTree;
- if (this.isShowing())
+ if (this.isShowing()) {
this._update();
- else
+ } else {
this._updateWhenVisible = true;
+ }
}
/**
@@ -68,8 +69,9 @@ Timeline.TimelineLayersView = class extends UI.SplitWidget {
_onPaintProfilerRequested(event) {
const selection = /** @type {!LayerViewer.LayerView.Selection} */ (event.data);
this._layers3DView.snapshotForSelection(selection).then(snapshotWithRect => {
- if (snapshotWithRect)
+ if (snapshotWithRect) {
this._showPaintProfilerCallback(snapshotWithRect.snapshot);
+ }
});
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLoader.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLoader.js
index 65bf6f98d41..5c61893ef5d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLoader.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineLoader.js
@@ -39,8 +39,9 @@ Timeline.TimelineLoader = class {
loader._canceledCallback = fileReader.cancel.bind(fileReader);
loader._totalSize = file.size;
fileReader.read(loader).then(success => {
- if (!success)
- this._reportErrorAndCancelLoading(fileReader.error().message);
+ if (!success) {
+ loader._reportErrorAndCancelLoading(fileReader.error().message);
+ }
});
return loader;
}
@@ -84,8 +85,9 @@ Timeline.TimelineLoader = class {
this._backingStorage.reset();
this._client.loadingComplete(null);
this._client = null;
- if (this._canceledCallback)
+ if (this._canceledCallback) {
this._canceledCallback();
+ }
}
/**
@@ -94,13 +96,15 @@ Timeline.TimelineLoader = class {
* @return {!Promise}
*/
write(chunk) {
- if (!this._client)
+ if (!this._client) {
return Promise.resolve();
+ }
this._loadedBytes += chunk.length;
- if (this._firstRawChunk)
+ if (this._firstRawChunk) {
this._client.loadingStarted();
- else
+ } else {
this._client.loadingProgress(this._totalSize ? this._loadedBytes / this._totalSize : undefined);
+ }
this._firstRawChunk = false;
if (this._state === Timeline.TimelineLoader.State.Initial) {
@@ -126,19 +130,23 @@ Timeline.TimelineLoader = class {
const startPos = this._buffer.length - objectName.length;
this._buffer += chunk;
const pos = this._buffer.indexOf(objectName, startPos);
- if (pos === -1)
+ if (pos === -1) {
return Promise.resolve();
+ }
chunk = this._buffer.slice(pos + objectName.length);
this._state = Timeline.TimelineLoader.State.ReadingEvents;
}
- if (this._state !== Timeline.TimelineLoader.State.ReadingEvents)
+ if (this._state !== Timeline.TimelineLoader.State.ReadingEvents) {
return Promise.resolve();
- if (this._jsonTokenizer.write(chunk))
+ }
+ if (this._jsonTokenizer.write(chunk)) {
return Promise.resolve();
+ }
this._state = Timeline.TimelineLoader.State.SkippingTail;
- if (this._firstChunk)
+ if (this._firstChunk) {
this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline input, wrong JSON brackets balance'));
+ }
return Promise.resolve();
}
@@ -150,8 +158,9 @@ Timeline.TimelineLoader = class {
if (!this._firstChunk) {
const commaIndex = json.indexOf(',');
- if (commaIndex !== -1)
+ if (commaIndex !== -1) {
json = json.slice(commaIndex + 1);
+ }
json = '[' + json;
}
@@ -182,8 +191,9 @@ Timeline.TimelineLoader = class {
* @param {string=} message
*/
_reportErrorAndCancelLoading(message) {
- if (message)
+ if (message) {
Common.console.error(message);
+ }
this.cancel();
}
@@ -198,9 +208,10 @@ Timeline.TimelineLoader = class {
/**
* @override
*/
- close() {
- if (!this._client)
+ async close() {
+ if (!this._client) {
return;
+ }
this._client.processingStarted();
setTimeout(() => this._finalizeTrace(), 0);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePaintProfilerView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePaintProfilerView.js
index c4c1153719b..da5e06bbcd6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePaintProfilerView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePaintProfilerView.js
@@ -70,18 +70,21 @@ Timeline.TimelinePaintProfilerView = class extends UI.SplitWidget {
this._event = event;
this._updateWhenVisible();
- if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint)
+ if (this._event.name === TimelineModel.TimelineModel.RecordType.Paint) {
return !!TimelineModel.TimelineData.forEvent(event).picture;
- if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask)
+ }
+ if (this._event.name === TimelineModel.TimelineModel.RecordType.RasterTask) {
return this._frameModel.hasRasterTile(this._event);
+ }
return false;
}
_updateWhenVisible() {
- if (this.isShowing())
+ if (this.isShowing()) {
this._update();
- else
+ } else {
this._needsUpdateWhenVisible = true;
+ }
}
_update() {
@@ -127,8 +130,9 @@ Timeline.TimelinePaintProfilerView = class extends UI.SplitWidget {
}
_releaseSnapshot() {
- if (!this._lastLoadedSnapshot)
+ if (!this._lastLoadedSnapshot) {
return;
+ }
this._lastLoadedSnapshot.release();
this._lastLoadedSnapshot = null;
}
@@ -160,8 +164,9 @@ Timeline.TimelinePaintImageView = class extends UI.Widget {
* @override
*/
onResize() {
- if (this._imageElement.src)
+ if (this._imageElement.src) {
this._updateImagePosition();
+ }
}
_updateImagePosition() {
@@ -207,8 +212,9 @@ Timeline.TimelinePaintImageView = class extends UI.Widget {
*/
showImage(imageURL) {
this._imageContainer.classList.toggle('hidden', !imageURL);
- if (imageURL)
+ if (imageURL) {
this._imageElement.src = imageURL;
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
index 2448593e2c7..3ed525b5717 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
@@ -70,6 +70,14 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._showScreenshotsSetting.setTitle(Common.UIString('Screenshots'));
this._showScreenshotsSetting.addChangeListener(this._updateOverviewControls, this);
+ this._startCoverage = Common.settings.createSetting('timelineStartCoverage', false);
+ this._startCoverage.setTitle(ls`Coverage`);
+
+ if (!Root.Runtime.experiments.isEnabled('recordCoverageWithPerformanceTracing')) {
+ this._startCoverage.set(false);
+ }
+
+
this._showMemorySetting = Common.settings.createSetting('timelineShowMemory', false);
this._showMemorySetting.setTitle(Common.UIString('Memory'));
this._showMemorySetting.addChangeListener(this._onModeChanged, this);
@@ -152,8 +160,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {!Array.<!SDK.TracingManager.EventPayload>} events
*/
loadFromEvents(events) {
- if (this._state !== Timeline.TimelinePanel.State.Idle)
+ if (this._state !== Timeline.TimelinePanel.State.Idle) {
return;
+ }
this._prepareToLoadTimeline();
this._loader = Timeline.TimelineLoader.loadFromEvents(events, this);
}
@@ -226,6 +235,12 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._createSettingCheckbox(this._showMemorySetting, Common.UIString('Show memory timeline'));
this._panelToolbar.appendToolbarItem(this._showMemoryToolbarCheckbox);
+ if (Root.Runtime.experiments.isEnabled('recordCoverageWithPerformanceTracing')) {
+ this._startCoverageCheckbox =
+ this._createSettingCheckbox(this._startCoverage, ls`Record coverage with performance trace`);
+ this._panelToolbar.appendToolbarItem(this._startCoverageCheckbox);
+ }
+
// GC
this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButtonForId('components.collect-garbage'));
@@ -306,7 +321,7 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @return {!UI.ToolbarComboBox}
*/
_createNetworkConditionsSelect() {
- const toolbarItem = new UI.ToolbarComboBox(null);
+ const toolbarItem = new UI.ToolbarComboBox(null, ls`Network conditions`);
toolbarItem.setMaxWidth(140);
MobileThrottling.throttlingManager().decorateSelectWithNetworkThrottling(toolbarItem.selectElement());
return toolbarItem;
@@ -322,8 +337,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
}
_createFileSelector() {
- if (this._fileSelectorElement)
+ if (this._fileSelectorElement) {
this._fileSelectorElement.remove();
+ }
this._fileSelectorElement = UI.createFileSelectorElement(this._loadFromFile.bind(this));
this._timelinePane.element.appendChild(this._fileSelectorElement);
}
@@ -337,32 +353,40 @@ Timeline.TimelinePanel = class extends UI.Panel {
contextMenu.show();
}
+ /**
+ * @suppress {deprecated}
+ */
async _saveToFile() {
- if (this._state !== Timeline.TimelinePanel.State.Idle)
+ if (this._state !== Timeline.TimelinePanel.State.Idle) {
return;
+ }
const performanceModel = this._performanceModel;
- if (!performanceModel)
+ if (!performanceModel) {
return;
+ }
const now = new Date();
const fileName = 'Profile-' + now.toISO8601Compact() + '.json';
const stream = new Bindings.FileOutputStream();
const accepted = await stream.open(fileName);
- if (!accepted)
+ if (!accepted) {
return;
+ }
const error = await performanceModel.save(stream);
- if (!error)
+ if (!error) {
return;
+ }
Common.console.error(
Common.UIString('Failed to save timeline: %s (%s, %s)', error.message, error.name, error.code));
}
async _showHistory() {
const model = await this._historyManager.showHistoryDropDown();
- if (model && model !== this._performanceModel)
+ if (model && model !== this._performanceModel) {
this._setModel(model);
+ }
}
/**
@@ -371,8 +395,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
*/
_navigateHistory(direction) {
const model = this._historyManager.navigate(direction);
- if (model && model !== this._performanceModel)
+ if (model && model !== this._performanceModel) {
this._setModel(model);
+ }
return true;
}
@@ -384,8 +409,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {!File} file
*/
_loadFromFile(file) {
- if (this._state !== Timeline.TimelinePanel.State.Idle)
+ if (this._state !== Timeline.TimelinePanel.State.Idle) {
return;
+ }
this._prepareToLoadTimeline();
this._loader = Timeline.TimelineLoader.loadFromFile(file, this);
this._createFileSelector();
@@ -395,8 +421,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {string} url
*/
_loadFromURL(url) {
- if (this._state !== Timeline.TimelinePanel.State.Idle)
+ if (this._state !== Timeline.TimelinePanel.State.Idle) {
return;
+ }
this._prepareToLoadTimeline();
this._loader = Timeline.TimelineLoader.loadFromURL(url, this);
}
@@ -404,18 +431,25 @@ Timeline.TimelinePanel = class extends UI.Panel {
_updateOverviewControls() {
this._overviewControls = [];
this._overviewControls.push(new Timeline.TimelineEventOverviewResponsiveness());
- if (Runtime.experiments.isEnabled('inputEventsOnTimelineOverview'))
+ if (Root.Runtime.experiments.isEnabled('inputEventsOnTimelineOverview')) {
this._overviewControls.push(new Timeline.TimelineEventOverviewInput());
+ }
this._overviewControls.push(new Timeline.TimelineEventOverviewFrames());
this._overviewControls.push(new Timeline.TimelineEventOverviewCPUActivity());
this._overviewControls.push(new Timeline.TimelineEventOverviewNetwork());
if (this._showScreenshotsSetting.get() && this._performanceModel &&
- this._performanceModel.filmStripModel().frames().length)
+ this._performanceModel.filmStripModel().frames().length) {
this._overviewControls.push(new Timeline.TimelineFilmStripOverview());
- if (this._showMemorySetting.get())
+ }
+ if (this._showMemorySetting.get()) {
this._overviewControls.push(new Timeline.TimelineEventOverviewMemory());
- for (const control of this._overviewControls)
+ }
+ if (this._startCoverage.get()) {
+ this._overviewControls.push(new Timeline.TimelineEventOverviewCoverage());
+ }
+ for (const control of this._overviewControls) {
control.setModel(this._performanceModel);
+ }
this._overviewPane.setOverviewControls(this._overviewControls);
}
@@ -426,22 +460,27 @@ Timeline.TimelinePanel = class extends UI.Panel {
}
_updateSettingsPaneVisibility() {
- if (this._showSettingsPaneSetting.get())
+ if (this._showSettingsPaneSetting.get()) {
this._settingsPane.showWidget();
- else
+ } else {
this._settingsPane.hideWidget();
+ }
}
_updateShowSettingsToolbarButton() {
const messages = [];
- if (MobileThrottling.throttlingManager().cpuThrottlingRate() !== 1)
+ if (MobileThrottling.throttlingManager().cpuThrottlingRate() !== 1) {
messages.push(Common.UIString('- CPU throttling is enabled'));
- if (SDK.multitargetNetworkManager.isThrottling())
+ }
+ if (SDK.multitargetNetworkManager.isThrottling()) {
messages.push(Common.UIString('- Network throttling is enabled'));
- if (this._captureLayersAndPicturesSetting.get())
+ }
+ if (this._captureLayersAndPicturesSetting.get()) {
messages.push(Common.UIString('- Significant overhead due to paint instrumentation'));
- if (this._disableCaptureJSProfileSetting.get())
+ }
+ if (this._disableCaptureJSProfileSetting.get()) {
messages.push(Common.UIString('- JavaScript sampling is disabled'));
+ }
this._showSettingsPaneButton.setDefaultWithRedColor(messages.length);
this._showSettingsPaneButton.setToggleWithRedColor(messages.length);
@@ -467,26 +506,39 @@ Timeline.TimelinePanel = class extends UI.Panel {
async _startRecording() {
console.assert(!this._statusPane, 'Status pane is already opened.');
this._setState(Timeline.TimelinePanel.State.StartPending);
- this._showRecordingStarted();
-
- const enabledTraceProviders = Extensions.extensionServer.traceProviders().filter(
- provider => Timeline.TimelinePanel._settingForTraceProvider(provider).get());
const recordingOptions = {
enableJSSampling: !this._disableCaptureJSProfileSetting.get(),
capturePictures: this._captureLayersAndPicturesSetting.get(),
- captureFilmStrip: this._showScreenshotsSetting.get()
+ captureFilmStrip: this._showScreenshotsSetting.get(),
+ startCoverage: this._startCoverage.get()
};
+ if (recordingOptions.startCoverage) {
+ await UI.viewManager.showView('coverage')
+ .then(() => UI.viewManager.view('coverage').widget())
+ .then(widget => widget.ensureRecordingStarted());
+ }
+
+ this._showRecordingStarted();
+
+ const enabledTraceProviders = Extensions.extensionServer.traceProviders().filter(
+ provider => Timeline.TimelinePanel._settingForTraceProvider(provider).get());
+
const mainTarget = /** @type {!SDK.Target} */ (SDK.targetManager.mainTarget());
- this._controller = new Timeline.TimelineController(mainTarget, this);
+ if (Timeline.UIDevtoolsUtils.isUiDevTools()) {
+ this._controller = new Timeline.UIDevtoolsController(mainTarget, this);
+ } else {
+ this._controller = new Timeline.TimelineController(mainTarget, this);
+ }
this._setUIControlsEnabled(false);
this._hideLandingPage();
const response = await this._controller.startRecording(recordingOptions, enabledTraceProviders);
- if (response[Protocol.Error])
+ if (response[Protocol.Error]) {
this._recordingFailed(response[Protocol.Error]);
- else
+ } else {
this._recordingStarted();
+ }
}
async _stopRecording() {
@@ -507,8 +559,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {string} error The error message to display
*/
_recordingFailed(error) {
- if (this._statusPane)
+ if (this._statusPane) {
this._statusPane.hide();
+ }
this._statusPane = new Timeline.TimelinePanel.StatusPane({description: error}, () => this.loadingComplete(null));
this._statusPane.showPane(this._statusPaneContainer);
this._statusPane.updateStatus(ls`Recording failed`);
@@ -550,8 +603,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
}
_recordReload() {
- if (this._state !== Timeline.TimelinePanel.State.Idle)
+ if (this._state !== Timeline.TimelinePanel.State.Idle) {
return;
+ }
this._recordingPageReload = true;
this._startRecording();
Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelinePageReloadStarted);
@@ -576,8 +630,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {!Timeline.PerformanceModel} model
*/
_applyFilters(model) {
- if (model.timelineModel().isGenericTrace() || Runtime.experiments.isEnabled('timelineShowAllEvents'))
+ if (model.timelineModel().isGenericTrace() || Root.Runtime.experiments.isEnabled('timelineShowAllEvents')) {
return;
+ }
model.setFilters([Timeline.TimelineUIUtils.visibleEventsFilter()]);
}
@@ -590,8 +645,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
Timeline.PerformanceModel.Events.WindowChanged, this._onModelWindowChanged, this);
}
this._performanceModel = model;
- if (model)
+ if (model) {
this._applyFilters(model);
+ }
this._flameChart.setModel(model);
this._updateOverviewControls();
@@ -603,16 +659,19 @@ Timeline.TimelinePanel = class extends UI.Panel {
model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime());
const lineLevelProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Performance);
lineLevelProfile.reset();
- for (const profile of model.timelineModel().cpuProfiles())
+ for (const profile of model.timelineModel().cpuProfiles()) {
lineLevelProfile.appendCPUProfile(profile);
+ }
this._setMarkers(model.timelineModel());
this._flameChart.setSelection(null);
this._overviewPane.setWindowTimes(model.window().left, model.window().right);
}
- for (const control of this._overviewControls)
+ for (const control of this._overviewControls) {
control.setModel(model);
- if (this._flameChart)
+ }
+ if (this._flameChart) {
this._flameChart.resizeToPreferredHeights();
+ }
this._updateTimelineControls();
}
@@ -620,8 +679,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
if (this._recordingPageReload) {
const target = this._controller.mainTarget();
const resourceModel = target.model(SDK.ResourceTreeModel);
- if (resourceModel)
+ if (resourceModel) {
resourceModel.reloadPage();
+ }
}
this._reset();
this._setState(Timeline.TimelinePanel.State.Recording);
@@ -694,14 +754,16 @@ Timeline.TimelinePanel = class extends UI.Panel {
loadingStarted() {
this._hideLandingPage();
- if (this._statusPane)
+ if (this._statusPane) {
this._statusPane.hide();
+ }
this._statusPane = new Timeline.TimelinePanel.StatusPane({showProgress: true}, this._cancelLoading.bind(this));
this._statusPane.showPane(this._statusPaneContainer);
this._statusPane.updateStatus(Common.UIString('Loading profile\u2026'));
// FIXME: make loading from backend cancelable as well.
- if (!this._loader)
+ if (!this._loader) {
this._statusPane.finish();
+ }
this.loadingProgress(0);
}
@@ -710,8 +772,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {number=} progress
*/
loadingProgress(progress) {
- if (typeof progress === 'number')
+ if (typeof progress === 'number') {
this._statusPane.updateProgressBar(Common.UIString('Received'), progress * 100);
+ }
}
/**
@@ -729,8 +792,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
delete this._loader;
this._setState(Timeline.TimelinePanel.State.Idle);
- if (this._statusPane)
+ if (this._statusPane) {
this._statusPane.hide();
+ }
delete this._statusPane;
if (!tracingModel) {
@@ -738,16 +802,25 @@ Timeline.TimelinePanel = class extends UI.Panel {
return;
}
- if (!this._performanceModel)
+ if (!this._performanceModel) {
this._performanceModel = new Timeline.PerformanceModel();
+ }
this._performanceModel.setTracingModel(tracingModel);
this._setModel(this._performanceModel);
this._historyManager.addRecording(this._performanceModel);
+
+ if (this._startCoverage.get()) {
+ UI.viewManager.showView('coverage')
+ .then(() => UI.viewManager.view('coverage').widget())
+ .then(widget => widget.stopRecording())
+ .then(() => this._updateOverviewControls());
+ }
}
_showRecordingStarted() {
- if (this._statusPane)
+ if (this._statusPane) {
return;
+ }
this._statusPane =
new Timeline.TimelinePanel.StatusPane({showTimer: true, showProgress: true}, this._stopRecording.bind(this));
this._statusPane.showPane(this._statusPaneContainer);
@@ -755,8 +828,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
}
_cancelLoading() {
- if (this._loader)
+ if (this._loader) {
this._loader.cancel();
+ }
}
/**
@@ -767,8 +841,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
const recordTypes = TimelineModel.TimelineModel.RecordType;
const zeroTime = timelineModel.minimumRecordTime();
for (const event of timelineModel.timeMarkerEvents()) {
- if (event.name === recordTypes.TimeStamp || event.name === recordTypes.ConsoleTime)
+ if (event.name === recordTypes.TimeStamp || event.name === recordTypes.ConsoleTime) {
continue;
+ }
markers.set(event.startTime, Timeline.TimelineUIUtils.createEventDivider(event, zeroTime));
}
this._overviewPane.setMarkers(markers);
@@ -779,14 +854,16 @@ Timeline.TimelinePanel = class extends UI.Panel {
*/
async _loadEventFired(event) {
if (this._state !== Timeline.TimelinePanel.State.Recording || !this._recordingPageReload ||
- this._controller.mainTarget() !== event.data.resourceTreeModel.target())
+ this._controller.mainTarget() !== event.data.resourceTreeModel.target()) {
return;
+ }
const controller = this._controller;
await new Promise(r => setTimeout(r, this._millisecondsToRecordAfterLoadEvent));
// Check if we're still in the same recording session.
- if (controller !== this._controller || this._state !== Timeline.TimelinePanel.State.Recording)
+ if (controller !== this._controller || this._state !== Timeline.TimelinePanel.State.Recording) {
return;
+ }
this._stopRecording();
}
@@ -813,8 +890,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
*/
_jumpToFrame(offset) {
const currentFrame = this._selection && this._frameForSelection(this._selection);
- if (!currentFrame)
+ if (!currentFrame) {
return;
+ }
const frames = this._performanceModel.frames();
let index = frames.indexOf(currentFrame);
console.assert(index >= 0, 'Can\'t find current frame in the frame list');
@@ -840,14 +918,16 @@ Timeline.TimelinePanel = class extends UI.Panel {
* @param {number} time
*/
selectEntryAtTime(events, time) {
- if (!events)
+ if (!events) {
return;
+ }
// Find best match, then backtrack to the first visible entry.
for (let index = events.upperBound(time, (time, event) => time - event.startTime) - 1; index >= 0; --index) {
const event = events[index];
const endTime = event.endTime || event.startTime;
- if (SDK.TracingModel.isTopLevelEvent(event) && endTime < time)
+ if (SDK.TracingModel.isTopLevelEvent(event) && endTime < time) {
break;
+ }
if (this._performanceModel.isVisible(event) && endTime >= time) {
this.select(Timeline.TimelineSelection.fromTraceEvent(event));
return;
@@ -871,10 +951,11 @@ Timeline.TimelinePanel = class extends UI.Panel {
_revealTimeRange(startTime, endTime) {
const window = this._performanceModel.window();
let offset = 0;
- if (window.right < endTime)
+ if (window.right < endTime) {
offset = endTime - window.right;
- else if (window.left > startTime)
+ } else if (window.left > startTime) {
offset = startTime - window.left;
+ }
this._performanceModel.setWindow({left: window.left + offset, right: window.right + offset}, /* animate */ true);
}
@@ -883,17 +964,20 @@ Timeline.TimelinePanel = class extends UI.Panel {
*/
_handleDrop(dataTransfer) {
const items = dataTransfer.items;
- if (!items.length)
+ if (!items.length) {
return;
+ }
const item = items[0];
if (item.kind === 'string') {
const url = dataTransfer.getData('text/uri-list');
- if (new Common.ParsedURL(url).isValid)
+ if (new Common.ParsedURL(url).isValid) {
this._loadFromURL(url);
+ }
} else if (item.kind === 'file') {
const entry = items[0].webkitGetAsEntry();
- if (!entry.isFile)
+ if (!entry.isFile) {
return;
+ }
entry.file(this._loadFromFile.bind(this));
}
}
@@ -1137,8 +1221,9 @@ Timeline.TimelinePanel.StatusPane = class extends UI.VBox {
}
_stopTimer() {
- if (!this._timeUpdateTimer)
+ if (!this._timeUpdateTimer) {
return;
+ }
clearInterval(this._timeUpdateTimer);
this._updateTimer(true);
delete this._timeUpdateTimer;
@@ -1148,8 +1233,9 @@ Timeline.TimelinePanel.StatusPane = class extends UI.VBox {
* @param {boolean=} precise
*/
_updateTimer(precise) {
- if (!this._timeUpdateTimer)
+ if (!this._timeUpdateTimer) {
return;
+ }
const elapsed = (Date.now() - this._startTime) / 1000;
this._time.textContent = Common.UIString('%s\xa0sec', elapsed.toFixed(precise ? 1 : 0));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js
index 376ada73e6a..58f1f3f5f02 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js
@@ -48,6 +48,13 @@ Timeline.TimelineTreeView = class extends UI.VBox {
}
/**
+ * @return {string}
+ */
+ getToolbarInputAccessiblePlaceHolder() {
+ return '';
+ }
+
+ /**
* @protected
* @return {?Timeline.PerformanceModel} model
*/
@@ -156,7 +163,7 @@ Timeline.TimelineTreeView = class extends UI.VBox {
* @param {!UI.Toolbar} toolbar
*/
populateToolbar(toolbar) {
- this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'));
+ this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'), this.getToolbarInputAccessiblePlaceHolder());
this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this);
toolbar.appendToolbarItem(this._textFilterUI);
@@ -196,11 +203,13 @@ Timeline.TimelineTreeView = class extends UI.VBox {
*/
_linkifyLocation(event) {
const target = this._model.timelineModel().targetByEvent(event);
- if (!target)
+ if (!target) {
return null;
+ }
const frame = TimelineModel.TimelineProfileTree.eventStackFrame(event);
- if (!frame)
+ if (!frame) {
return null;
+ }
return this._linkifier.maybeLinkifyConsoleCallFrame(target, frame);
}
@@ -210,12 +219,14 @@ Timeline.TimelineTreeView = class extends UI.VBox {
*/
selectProfileNode(treeNode, suppressSelectedEvent) {
const pathToRoot = [];
- for (let node = treeNode; node; node = node.parent)
+ for (let node = treeNode; node; node = node.parent) {
pathToRoot.push(node);
+ }
for (let i = pathToRoot.length - 1; i > 0; --i) {
const gridNode = this.dataGridNodeForTreeNode(pathToRoot[i]);
- if (gridNode && gridNode.dataGrid)
+ if (gridNode && gridNode.dataGrid) {
gridNode.expand();
+ }
}
const gridNode = this.dataGridNodeForTreeNode(treeNode);
if (gridNode.dataGrid) {
@@ -251,8 +262,13 @@ Timeline.TimelineTreeView = class extends UI.VBox {
}
this._sortingChanged();
this._updateDetailsForSelection();
- if (this._searchableView)
+ if (this._searchableView) {
this._searchableView.refreshSearch();
+ }
+ const rootNode = this._dataGrid.rootNode();
+ if (rootNode.children.length > 0) {
+ rootNode.children[0].select();
+ }
}
/**
@@ -285,8 +301,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
_sortingChanged() {
const columnId = this._dataGrid.sortColumnId();
- if (!columnId)
+ if (!columnId) {
return;
+ }
let sortFunction;
switch (columnId) {
case 'startTime':
@@ -345,8 +362,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
}
_onShowModeChanged() {
- if (this._splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain)
+ if (this._splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain) {
return;
+ }
this._lastSelectedNode = undefined;
this._updateDetailsForSelection();
}
@@ -355,15 +373,18 @@ Timeline.TimelineTreeView = class extends UI.VBox {
const selectedNode = this._dataGrid.selectedNode ?
/** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (this._dataGrid.selectedNode)._profileNode :
null;
- if (selectedNode === this._lastSelectedNode)
+ if (selectedNode === this._lastSelectedNode) {
return;
+ }
this._lastSelectedNode = selectedNode;
- if (this._splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain)
+ if (this._splitWidget.showMode() === UI.SplitWidget.ShowMode.OnlyMain) {
return;
+ }
this._detailsView.detachChildWidgets();
this._detailsView.element.removeChildren();
- if (selectedNode && this._showDetailsForNode(selectedNode))
+ if (selectedNode && this._showDetailsForNode(selectedNode)) {
return;
+ }
const banner = this._detailsView.element.createChild('div', 'full-widget-dimmed-banner');
banner.createTextChild(Common.UIString('Select item for details.'));
}
@@ -385,8 +406,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
this._dataGrid.dataGridNodeFromNode(/** @type {!Node} */ (event.target))) :
null;
const profileNode = gridNode && gridNode._profileNode;
- if (profileNode === this._lastHoveredProfileNode)
+ if (profileNode === this._lastHoveredProfileNode) {
return;
+ }
this._lastHoveredProfileNode = profileNode;
this._onHover(profileNode);
}
@@ -396,10 +418,13 @@ Timeline.TimelineTreeView = class extends UI.VBox {
* @param {!DataGrid.DataGridNode} gridNode
*/
_onContextMenu(contextMenu, gridNode) {
+ if (gridNode._linkElement && !contextMenu.containsTarget(gridNode._linkElement)) {
+ contextMenu.appendApplicableItems(gridNode._linkElement);
+ }
const profileNode = gridNode._profileNode;
- if (!profileNode)
- return;
- this._appendContextMenuItems(contextMenu, profileNode);
+ if (profileNode) {
+ this._appendContextMenuItems(contextMenu, profileNode);
+ }
}
/**
@@ -430,8 +455,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
performSearch(searchConfig, shouldJump, jumpBackwards) {
this._searchResults = [];
this._currentResult = 0;
- if (!this._root)
+ if (!this._root) {
return;
+ }
const searchRegex = searchConfig.toSearchRegex();
this._searchResults =
this._root.searchTree(event => Timeline.TimelineUIUtils.testContentMatching(event, searchRegex));
@@ -442,8 +468,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
* @override
*/
jumpToNextSearchResult() {
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
+ }
this.selectProfileNode(this._searchResults[this._currentResult], false);
this._currentResult = mod(this._currentResult + 1, this._searchResults.length);
}
@@ -452,8 +479,9 @@ Timeline.TimelineTreeView = class extends UI.VBox {
* @override
*/
jumpToPreviousSearchResult() {
- if (!this._searchResults.length)
+ if (!this._searchResults.length) {
return;
+ }
this.selectProfileNode(this._searchResults[this._currentResult], false);
this._currentResult = mod(this._currentResult - 1, this._searchResults.length);
}
@@ -494,6 +522,7 @@ Timeline.TimelineTreeView.GridNode = class extends DataGrid.SortableDataGridNode
this._grandTotalTime = grandTotalTime;
this._maxSelfTime = maxSelfTime;
this._maxTotalTime = maxTotalTime;
+ this._linkElement = null;
}
/**
@@ -502,8 +531,9 @@ Timeline.TimelineTreeView.GridNode = class extends DataGrid.SortableDataGridNode
* @return {!Element}
*/
createCell(columnId) {
- if (columnId === 'activity')
+ if (columnId === 'activity') {
return this._createNameCell(columnId);
+ }
return this._createValueCell(columnId) || super.createCell(columnId);
}
@@ -523,19 +553,25 @@ Timeline.TimelineTreeView.GridNode = class extends DataGrid.SortableDataGridNode
const info = treeView._displayInfoForGroupNode(this._profileNode);
name.textContent = info.name;
icon.style.backgroundColor = info.color;
- if (info.icon)
+ if (info.icon) {
iconContainer.insertBefore(info.icon, icon);
+ }
} else if (event) {
const data = event.args['data'];
const deoptReason = data && data['deoptReason'];
- if (deoptReason)
+ if (deoptReason) {
container.createChild('div', 'activity-warning').title = Common.UIString('Not optimized: %s', deoptReason);
+ }
name.textContent = Timeline.TimelineUIUtils.eventTitle(event);
- const link = this._treeView._linkifyLocation(event);
- if (link)
- container.createChild('div', 'activity-link').appendChild(link);
- icon.style.backgroundColor = Timeline.TimelineUIUtils.eventColor(event);
+ this._linkElement = this._treeView._linkifyLocation(event);
+ if (this._linkElement) {
+ container.createChild('div', 'activity-link').appendChild(this._linkElement);
+ }
+ const eventStyle = Timeline.TimelineUIUtils.eventStyle(event);
+ const eventCategory = eventStyle.category;
+ UI.ARIAUtils.setAccessibleName(icon, eventCategory.title);
+ icon.style.backgroundColor = eventCategory.color;
}
return cell;
}
@@ -545,8 +581,9 @@ Timeline.TimelineTreeView.GridNode = class extends DataGrid.SortableDataGridNode
* @return {?Element}
*/
_createValueCell(columnId) {
- if (columnId !== 'self' && columnId !== 'total' && columnId !== 'startTime')
+ if (columnId !== 'self' && columnId !== 'total' && columnId !== 'startTime') {
return null;
+ }
let showPercents = false;
let value;
@@ -607,11 +644,13 @@ Timeline.TimelineTreeView.TreeGridNode = class extends Timeline.TimelineTreeView
* @override
*/
populate() {
- if (this._populated)
+ if (this._populated) {
return;
+ }
this._populated = true;
- if (!this._profileNode.children)
+ if (!this._profileNode.children) {
return;
+ }
for (const node of this._profileNode.children().values()) {
const gridNode = new Timeline.TimelineTreeView.TreeGridNode(
node, this._grandTotalTime, this._maxSelfTime, this._maxTotalTime, this._treeView);
@@ -664,15 +703,17 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
this._updateExtensionResolver();
super.updateContents(selection);
const rootNode = this._dataGrid.rootNode();
- if (rootNode.children.length)
- rootNode.children[0].revealAndSelect();
+ if (rootNode.children.length) {
+ rootNode.children[0].select();
+ }
}
_updateExtensionResolver() {
this._executionContextNamesByOrigin = new Map();
for (const runtimeModel of SDK.targetManager.models(SDK.RuntimeModel)) {
- for (const context of runtimeModel.executionContexts())
+ for (const context of runtimeModel.executionContexts()) {
this._executionContextNamesByOrigin.set(context.origin, context.name);
+ }
}
}
@@ -682,12 +723,13 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
* @this {Timeline.AggregatedTimelineTreeView}
*/
_beautifyDomainName(name) {
- if (Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(name))
+ if (Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(name)) {
name = Common.UIString('[Chrome extensions overhead]');
- else if (Timeline.AggregatedTimelineTreeView._isV8NativeURL(name))
+ } else if (Timeline.AggregatedTimelineTreeView._isV8NativeURL(name)) {
name = Common.UIString('[V8 Runtime]');
- else if (name.startsWith('chrome-extension'))
+ } else if (name.startsWith('chrome-extension')) {
name = this._executionContextNamesByOrigin.get(name) || name;
+ }
return name;
}
@@ -701,19 +743,22 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
categories['other'].color;
const unattributed = Common.UIString('[unattributed]');
+ const id = typeof node.id === 'symbol' ? undefined : node.id;
+
switch (this._groupBySetting.get()) {
case Timeline.AggregatedTimelineTreeView.GroupBy.Category: {
- const category = categories[node.id] || categories['other'];
+ const category = id ? categories[id] || categories['other'] : unattributed;
return {name: category.title, color: category.color};
}
case Timeline.AggregatedTimelineTreeView.GroupBy.Domain:
case Timeline.AggregatedTimelineTreeView.GroupBy.Subdomain: {
- let domainName = this._beautifyDomainName(node.id);
+ let domainName = id ? this._beautifyDomainName(id) : undefined;
if (domainName) {
const productName = this._productByEvent(/** @type {!SDK.TracingModel.Event} */ (node.event));
- if (productName)
+ if (productName) {
domainName += ' \u2014 ' + productName;
+ }
}
return {name: domainName || unattributed, color: color};
}
@@ -742,7 +787,7 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
break;
case Timeline.AggregatedTimelineTreeView.GroupBy.Frame: {
- const frame = this._model.timelineModel().pageFrameById(node.id);
+ const frame = id ? this._model.timelineModel().pageFrameById(id) : undefined;
const frameName = frame ? Timeline.TimelineUIUtils.displayNameForFrame(frame, 80) : Common.UIString('Page');
return {name: frameName, color: color};
}
@@ -750,7 +795,7 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
default:
console.assert(false, 'Unexpected grouping type');
}
- return {name: node.id || unattributed, color: color};
+ return {name: id || unattributed, color: color};
}
/**
@@ -770,7 +815,7 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
{label: Common.UIString('Group by Subdomain'), value: groupBy.Subdomain},
{label: Common.UIString('Group by URL'), value: groupBy.URL},
];
- toolbar.appendToolbarItem(new UI.ToolbarSettingComboBox(options, this._groupBySetting));
+ toolbar.appendToolbarItem(new UI.ToolbarSettingComboBox(options, this._groupBySetting, ls`Group by`));
toolbar.appendSpacer();
toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton(Common.UIString('heaviest stack')));
}
@@ -783,8 +828,9 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
console.assert(!!treeNode.parent, 'Attempt to build stack for tree root');
let result = [];
// Do not add root to the stack, as it's the tree itself.
- for (let node = treeNode; node && node.parent; node = node.parent)
+ for (let node = treeNode; node && node.parent; node = node.parent) {
result.push(node);
+ }
result = result.reverse();
for (let node = treeNode; node && node.children() && node.children().size;) {
const children = Array.from(node.children().values());
@@ -804,8 +850,9 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
_onStackViewSelectionChanged() {
const treeNode = this._stackView.selectedTreeNode();
- if (treeNode)
+ if (treeNode) {
this.selectProfileNode(treeNode, true);
+ }
}
/**
@@ -856,21 +903,28 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
*/
_domainByEvent(groupSubdomains, event) {
const url = TimelineModel.TimelineProfileTree.eventURL(event);
- if (!url)
+ if (!url) {
return '';
- if (Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(url))
+ }
+ if (Timeline.AggregatedTimelineTreeView._isExtensionInternalURL(url)) {
return Timeline.AggregatedTimelineTreeView._extensionInternalPrefix;
- if (Timeline.AggregatedTimelineTreeView._isV8NativeURL(url))
+ }
+ if (Timeline.AggregatedTimelineTreeView._isV8NativeURL(url)) {
return Timeline.AggregatedTimelineTreeView._v8NativePrefix;
+ }
const parsedURL = url.asParsedURL();
- if (!parsedURL)
+ if (!parsedURL) {
return '';
- if (parsedURL.scheme === 'chrome-extension')
+ }
+ if (parsedURL.scheme === 'chrome-extension') {
return parsedURL.scheme + '://' + parsedURL.host;
- if (!groupSubdomains)
+ }
+ if (!groupSubdomains) {
return parsedURL.host;
- if (/^[.0-9]+$/.test(parsedURL.host))
+ }
+ if (/^[.0-9]+$/.test(parsedURL.host)) {
return parsedURL.host;
+ }
const domainMatch = /([^.]*\.)?[^.]*$/.exec(parsedURL.host);
return domainMatch && domainMatch[0] || '';
}
@@ -881,12 +935,15 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
*/
_productByEvent(event) {
const url = TimelineModel.TimelineProfileTree.eventURL(event);
- if (!url)
+ if (!url) {
return '';
- if (this._productByURLCache.has(url))
+ }
+ if (this._productByURLCache.has(url)) {
return this._productByURLCache.get(url);
- if (!this._productRegistry)
+ }
+ if (!this._productRegistry) {
return '';
+ }
const parsedURL = url.asParsedURL();
const name = parsedURL && this._productRegistry.nameForUrl(parsedURL) || '';
this._productByURLCache.set(url, name);
@@ -899,12 +956,14 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
*/
_productAndBadgeByEvent(event) {
const url = TimelineModel.TimelineProfileTree.eventURL(event);
- if (!url || !this._productRegistry)
+ if (!url || !this._productRegistry) {
return null;
+ }
const parsedURL = url.asParsedURL();
const name = parsedURL && this._productRegistry.nameForUrl(parsedURL) || this._domainByEvent(true, event);
- if (!name)
+ if (!name) {
return null;
+ }
const icon = parsedURL && this._badgePool.badgeForURL(parsedURL);
return {name: this._beautifyDomainName(name), badge: icon};
}
@@ -915,13 +974,16 @@ Timeline.AggregatedTimelineTreeView = class extends Timeline.TimelineTreeView {
* @param {!TimelineModel.TimelineProfileTree.Node} node
*/
_appendContextMenuItems(contextMenu, node) {
- if (this._groupBySetting.get() !== Timeline.AggregatedTimelineTreeView.GroupBy.Frame)
+ if (this._groupBySetting.get() !== Timeline.AggregatedTimelineTreeView.GroupBy.Frame) {
return;
- if (!node.isGroupNode())
+ }
+ if (!node.isGroupNode()) {
return;
- const frame = this._model.timelineModel().pageFrameById(node.id);
- if (!frame || !frame.ownerNode)
+ }
+ const frame = this._model.timelineModel().pageFrameById(/** @type {string} */ (node.id));
+ if (!frame || !frame.ownerNode) {
return;
+ }
contextMenu.appendApplicableItems(frame.ownerNode);
}
@@ -970,6 +1032,14 @@ Timeline.CallTreeTimelineTreeView = class extends Timeline.AggregatedTimelineTre
/**
* @override
+ * @return {string}
+ */
+ getToolbarInputAccessiblePlaceHolder() {
+ return ls`Filter call tree`;
+ }
+
+ /**
+ * @override
* @return {!TimelineModel.TimelineProfileTree.Node}
*/
_buildTree() {
@@ -989,6 +1059,14 @@ Timeline.BottomUpTimelineTreeView = class extends Timeline.AggregatedTimelineTre
/**
* @override
+ * @return {string}
+ */
+ getToolbarInputAccessiblePlaceHolder() {
+ return ls`Filter bottom-up`;
+ }
+
+ /**
+ * @override
* @return {!TimelineModel.TimelineProfileTree.Node}
*/
_buildTree() {
@@ -1029,8 +1107,9 @@ Timeline.TimelineStackView = class extends UI.VBox {
for (const node of stack) {
const gridNode = new Timeline.TimelineTreeView.GridNode(node, totalTime, totalTime, totalTime, this._treeView);
rootNode.appendChild(gridNode);
- if (node === selectedNode)
+ if (node === selectedNode) {
nodeToReveal = gridNode;
+ }
}
nodeToReveal.revealAndSelect();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
index 82984104ccd..afc8e7480a7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
@@ -37,8 +37,9 @@ Timeline.TimelineUIUtils = class {
* @return {!Object.<string, !Timeline.TimelineRecordStyle>}
*/
static _initEventStyles() {
- if (Timeline.TimelineUIUtils._eventStylesMap)
+ if (Timeline.TimelineUIUtils._eventStylesMap) {
return Timeline.TimelineUIUtils._eventStylesMap;
+ }
const type = TimelineModel.TimelineModel.RecordType;
const categories = Timeline.TimelineUIUtils.categories();
@@ -85,7 +86,8 @@ Timeline.TimelineUIUtils = class {
eventStyles[type.EvaluateScript] = new Timeline.TimelineRecordStyle(ls`Evaluate Script`, scripting);
eventStyles[type.CompileModule] = new Timeline.TimelineRecordStyle(ls`Compile Module`, scripting);
eventStyles[type.EvaluateModule] = new Timeline.TimelineRecordStyle(ls`Evaluate Module`, scripting);
- eventStyles[type.ParseScriptOnBackground] = new Timeline.TimelineRecordStyle(ls`Parse Script`, scripting);
+ eventStyles[type.StreamingCompileScript] =
+ new Timeline.TimelineRecordStyle(ls`Streaming Compile Script`, scripting);
eventStyles[type.WasmStreamFromResponseCallback] =
new Timeline.TimelineRecordStyle(ls`Streaming Wasm Response`, scripting);
eventStyles[type.WasmCompiledModule] = new Timeline.TimelineRecordStyle(ls`Compiled Wasm Module`, scripting);
@@ -104,6 +106,7 @@ Timeline.TimelineUIUtils = class {
eventStyles[type.TimeStamp] = new Timeline.TimelineRecordStyle(ls`Timestamp`, scripting);
eventStyles[type.ConsoleTime] = new Timeline.TimelineRecordStyle(ls`Console Time`, scripting);
eventStyles[type.UserTiming] = new Timeline.TimelineRecordStyle(ls`User Timing`, scripting);
+ eventStyles[type.ResourceWillSendRequest] = new Timeline.TimelineRecordStyle(ls`Will Send Request`, loading);
eventStyles[type.ResourceSendRequest] = new Timeline.TimelineRecordStyle(ls`Send Request`, loading);
eventStyles[type.ResourceReceiveResponse] = new Timeline.TimelineRecordStyle(ls`Receive Response`, loading);
eventStyles[type.ResourceFinish] = new Timeline.TimelineRecordStyle(ls`Finish Loading`, loading);
@@ -151,6 +154,10 @@ Timeline.TimelineUIUtils = class {
return eventStyles;
}
+ static setEventStylesMap(eventStyles) {
+ Timeline.TimelineUIUtils._eventStylesMap = eventStyles;
+ }
+
/**
* @param {!TimelineModel.TimelineIRModel.InputEvents} inputEventType
* @return {?string}
@@ -197,8 +204,9 @@ Timeline.TimelineUIUtils = class {
* @return {string}
*/
static frameDisplayName(frame) {
- if (!TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame))
+ if (!TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame)) {
return UI.beautifyFunctionName(frame.functionName);
+ }
const nativeGroup = TimelineModel.TimelineJSProfileProcessor.nativeGroup(frame.functionName);
const groups = TimelineModel.TimelineJSProfileProcessor.NativeGroups;
switch (nativeGroup) {
@@ -219,8 +227,9 @@ Timeline.TimelineUIUtils = class {
const title = Timeline.TimelineUIUtils.eventStyle(traceEvent).title;
const tokens = [title];
const url = TimelineModel.TimelineData.forEvent(traceEvent).url;
- if (url)
+ if (url) {
tokens.push(url);
+ }
appendObjectProperties(traceEvent.args, 2);
return regExp.test(tokens.join('|'));
@@ -229,17 +238,19 @@ Timeline.TimelineUIUtils = class {
* @param {number} depth
*/
function appendObjectProperties(object, depth) {
- if (!depth)
+ if (!depth) {
return;
+ }
for (const key in object) {
const value = object[key];
const type = typeof value;
- if (type === 'string')
+ if (type === 'string') {
tokens.push(value);
- else if (type === 'number')
+ } else if (type === 'number') {
tokens.push(String(value));
- else if (type === 'object')
+ } else if (type === 'object') {
appendObjectProperties(value, depth - 1);
+ }
}
}
}
@@ -251,8 +262,9 @@ Timeline.TimelineUIUtils = class {
static eventURL(event) {
const data = event.args['data'] || event.args['beginData'];
const url = data && data.url;
- if (url)
+ if (url) {
return url;
+ }
const stackTrace = data && data['stackTrace'];
const frame =
stackTrace && stackTrace.length && stackTrace[0] || TimelineModel.TimelineData.forEvent(event).topFrame();
@@ -261,13 +273,14 @@ Timeline.TimelineUIUtils = class {
/**
* @param {!SDK.TracingModel.Event} event
- * @return {!{title: string, category: !Timeline.TimelineCategory}}
+ * @return {!Timeline.TimelineRecordStyle}
*/
static eventStyle(event) {
const eventStyles = Timeline.TimelineUIUtils._initEventStyles();
if (event.hasCategory(TimelineModel.TimelineModel.Category.Console) ||
- event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
- return {title: event.name, category: Timeline.TimelineUIUtils.categories()['scripting']};
+ event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)) {
+ return new Timeline.TimelineRecordStyle(event.name, Timeline.TimelineUIUtils.categories()['scripting']);
+ }
if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
/** @const */
@@ -275,7 +288,8 @@ Timeline.TimelineUIUtils = class {
const inputEventType = event.name.startsWith(prefix) ? event.name.substr(prefix.length) : event.name;
const displayName = Timeline.TimelineUIUtils.inputEventDisplayName(
/** @type {!TimelineModel.TimelineIRModel.InputEvents} */ (inputEventType));
- return {title: displayName || inputEventType, category: Timeline.TimelineUIUtils.categories()['scripting']};
+ return new Timeline.TimelineRecordStyle(
+ displayName || inputEventType, Timeline.TimelineUIUtils.categories()['scripting']);
}
let result = eventStyles[event.name];
if (!result) {
@@ -292,8 +306,9 @@ Timeline.TimelineUIUtils = class {
static eventColor(event) {
if (event.name === TimelineModel.TimelineModel.RecordType.JSFrame) {
const frame = event.args['data'];
- if (Timeline.TimelineUIUtils.isUserFrame(frame))
+ if (Timeline.TimelineUIUtils.isUserFrame(frame)) {
return Timeline.TimelineUIUtils.colorForId(frame.url);
+ }
}
return Timeline.TimelineUIUtils.eventStyle(event).category.color;
}
@@ -308,21 +323,25 @@ Timeline.TimelineUIUtils = class {
static eventColorByProduct(productRegistry, model, urlToColorCache, event) {
const url = Timeline.TimelineUIUtils.eventURL(event) || '';
let color = urlToColorCache.get(url);
- if (color)
+ if (color) {
return color;
+ }
const defaultColor = '#f2ecdc';
const parsedURL = url.asParsedURL();
- if (!parsedURL)
+ if (!parsedURL) {
return defaultColor;
+ }
let name = productRegistry && productRegistry.nameForUrl(parsedURL);
if (!name) {
name = parsedURL.host;
const rootFrames = model.rootFrames();
- if (rootFrames.some(pageFrame => new Common.ParsedURL(pageFrame.url).host === name))
+ if (rootFrames.some(pageFrame => new Common.ParsedURL(pageFrame.url).host === name)) {
color = defaultColor;
+ }
}
- if (!color)
+ if (!color) {
color = name ? ProductRegistry.BadgePool.colorForEntryName(name) : defaultColor;
+ }
urlToColorCache.set(url, color);
return color;
}
@@ -334,17 +353,22 @@ Timeline.TimelineUIUtils = class {
static eventTitle(event) {
const recordType = TimelineModel.TimelineModel.RecordType;
const eventData = event.args['data'];
- if (event.name === recordType.JSFrame)
+ if (event.name === recordType.JSFrame) {
return Timeline.TimelineUIUtils.frameDisplayName(eventData);
+ }
const title = Timeline.TimelineUIUtils.eventStyle(event).title;
- if (event.hasCategory(TimelineModel.TimelineModel.Category.Console))
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.Console)) {
return title;
- if (event.name === recordType.TimeStamp)
+ }
+ if (event.name === recordType.TimeStamp) {
return ls`${title}: ${eventData['message']}`;
- if (event.name === recordType.Animation && eventData && eventData['name'])
+ }
+ if (event.name === recordType.Animation && eventData && eventData['name']) {
return ls`${title}: ${eventData['name']}`;
- if (event.name === recordType.EventDispatch && eventData && eventData['type'])
+ }
+ if (event.name === recordType.EventDispatch && eventData && eventData['type']) {
return ls`${title}: ${eventData['type']}`;
+ }
return title;
}
@@ -475,18 +499,20 @@ Timeline.TimelineUIUtils = class {
case recordType.Paint: {
const width = Timeline.TimelineUIUtils.quadWidth(eventData.clip);
const height = Timeline.TimelineUIUtils.quadHeight(eventData.clip);
- if (width && height)
+ if (width && height) {
detailsText = Common.UIString('%d\xa0\u00d7\xa0%d', width, height);
+ }
break;
}
case recordType.ParseHTML: {
const startLine = event.args['beginData']['startLine'];
const endLine = event.args['endData'] && event.args['endData']['endLine'];
const url = Bindings.displayNameForURL(event.args['beginData']['url']);
- if (endLine >= 0)
+ if (endLine >= 0) {
detailsText = Common.UIString('%s [%s\u2026%s]', url, startLine + 1, endLine + 1);
- else
+ } else {
detailsText = Common.UIString('%s [%s\u2026]', url, startLine + 1);
+ }
break;
}
case recordType.CompileModule:
@@ -495,24 +521,27 @@ Timeline.TimelineUIUtils = class {
case recordType.CompileScript:
case recordType.EvaluateScript: {
const url = eventData && eventData['url'];
- if (url)
+ if (url) {
detailsText = Bindings.displayNameForURL(url) + ':' + (eventData['lineNumber'] + 1);
+ }
break;
}
case recordType.WasmCompiledModule:
case recordType.WasmModuleCacheHit: {
const url = event.args['url'];
- if (url)
+ if (url) {
detailsText = Bindings.displayNameForURL(url);
+ }
break;
}
- case recordType.ParseScriptOnBackground:
+ case recordType.StreamingCompileScript:
case recordType.XHRReadyStateChange:
case recordType.XHRLoad: {
const url = eventData['url'];
- if (url)
+ if (url) {
detailsText = Bindings.displayNameForURL(url);
+ }
break;
}
case recordType.TimeStamp:
@@ -523,6 +552,7 @@ Timeline.TimelineUIUtils = class {
case recordType.WebSocketSendHandshakeRequest:
case recordType.WebSocketReceiveHandshakeResponse:
case recordType.WebSocketDestroy:
+ case recordType.ResourceWillSendRequest:
case recordType.ResourceSendRequest:
case recordType.ResourceReceivedData:
case recordType.ResourceReceiveResponse:
@@ -532,8 +562,9 @@ Timeline.TimelineUIUtils = class {
case recordType.ResizeImage:
case recordType.DecodeLazyPixelRef: {
const url = TimelineModel.TimelineData.forEvent(event).url;
- if (url)
+ if (url) {
detailsText = Bindings.displayNameForURL(url);
+ }
break;
}
@@ -550,10 +581,11 @@ Timeline.TimelineUIUtils = class {
break;
default:
- if (event.hasCategory(TimelineModel.TimelineModel.Category.Console))
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.Console)) {
detailsText = null;
- else
+ } else {
detailsText = linkifyTopCallFrameAsText();
+ }
break;
}
@@ -567,11 +599,13 @@ Timeline.TimelineUIUtils = class {
*/
function linkifyLocationAsText(scriptId, lineNumber, columnNumber) {
const debuggerModel = target ? target.model(SDK.DebuggerModel) : null;
- if (!target || target.isDisposed() || !scriptId || !debuggerModel)
+ if (!target || target.isDisposed() || !scriptId || !debuggerModel) {
return null;
+ }
const rawLocation = debuggerModel.createRawLocationByScriptId(scriptId, lineNumber, columnNumber);
- if (!rawLocation)
+ if (!rawLocation) {
return null;
+ }
const uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(rawLocation);
return uiLocation ? uiLocation.linkText() : null;
}
@@ -581,13 +615,15 @@ Timeline.TimelineUIUtils = class {
*/
function linkifyTopCallFrameAsText() {
const frame = TimelineModel.TimelineData.forEvent(event).topFrame();
- if (!frame)
+ if (!frame) {
return null;
+ }
let text = linkifyLocationAsText(frame.scriptId, frame.lineNumber, frame.columnNumber);
if (!text) {
text = frame.url;
- if (typeof frame.lineNumber === 'number')
+ if (typeof frame.lineNumber === 'number') {
text += ':' + (frame.lineNumber + 1);
+ }
}
return text;
}
@@ -630,13 +666,15 @@ Timeline.TimelineUIUtils = class {
case recordType.DecodeLazyPixelRef:
case recordType.XHRReadyStateChange:
case recordType.XHRLoad:
+ case recordType.ResourceWillSendRequest:
case recordType.ResourceSendRequest:
case recordType.ResourceReceivedData:
case recordType.ResourceReceiveResponse:
case recordType.ResourceFinish: {
const url = TimelineModel.TimelineData.forEvent(event).url;
- if (url)
+ if (url) {
details = Components.Linkifier.linkifyURL(url);
+ }
break;
}
case recordType.FunctionCall:
@@ -656,26 +694,30 @@ Timeline.TimelineUIUtils = class {
case recordType.CompileScript:
case recordType.EvaluateScript: {
const url = eventData['url'];
- if (url)
+ if (url) {
details = linkifyLocation('', url, eventData['lineNumber'], 0);
+ }
break;
}
- case recordType.ParseScriptOnBackground: {
+ case recordType.StreamingCompileScript: {
const url = eventData['url'];
- if (url)
+ if (url) {
details = linkifyLocation('', url, 0, 0);
+ }
break;
}
default:
- if (event.hasCategory(TimelineModel.TimelineModel.Category.Console))
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.Console)) {
detailsText = null;
- else
+ } else {
details = linkifyTopCallFrame();
+ }
break;
}
- if (!details && detailsText)
+ if (!details && detailsText) {
details = createTextNode(detailsText);
+ }
return details;
/**
@@ -745,25 +787,30 @@ Timeline.TimelineUIUtils = class {
if (typeof event[Timeline.TimelineUIUtils._previewElementSymbol] === 'undefined') {
let previewElement = null;
const url = TimelineModel.TimelineData.forEvent(event).url;
- if (url)
- previewElement = await Components.ImagePreview.build(target, url, false);
- else if (TimelineModel.TimelineData.forEvent(event).picture)
+ if (url) {
+ previewElement = await Components.ImagePreview.build(
+ target, url, false, {imageAltText: Components.ImagePreview.defaultAltTextForImageURL(url)});
+ } else if (TimelineModel.TimelineData.forEvent(event).picture) {
previewElement = await Timeline.TimelineUIUtils.buildPicturePreviewContent(event, target);
+ }
event[Timeline.TimelineUIUtils._previewElementSymbol] = previewElement;
}
/** @type {!Set<number>} */
const nodeIdsToResolve = new Set();
const timelineData = TimelineModel.TimelineData.forEvent(event);
- if (timelineData.backendNodeId)
+ if (timelineData.backendNodeId) {
nodeIdsToResolve.add(timelineData.backendNodeId);
+ }
const invalidationTrackingEvents = TimelineModel.InvalidationTracker.invalidationEventsFor(event);
- if (invalidationTrackingEvents)
+ if (invalidationTrackingEvents) {
Timeline.TimelineUIUtils._collectInvalidationNodeIds(nodeIdsToResolve, invalidationTrackingEvents);
+ }
if (nodeIdsToResolve.size) {
const domModel = target.model(SDK.DOMModel);
- if (domModel)
+ if (domModel) {
relatedNodesMap = await domModel.pushNodesByBackendIdsToFrontend(nodeIdsToResolve);
+ }
}
}
@@ -781,10 +828,12 @@ Timeline.TimelineUIUtils = class {
const initiator = timelineData.initiator();
let url = null;
- if (timelineData.warning)
+ if (timelineData.warning) {
contentHelper.appendWarningRow(event);
- if (event.name === recordTypes.JSFrame && eventData['deoptReason'])
+ }
+ if (event.name === recordTypes.JSFrame && eventData['deoptReason']) {
contentHelper.appendWarningRow(event, TimelineModel.TimelineModel.WarningType.V8Deopt);
+ }
if (detailed && !Number.isNaN(event.duration + 0)) {
contentHelper.appendTextRow(ls`Total Time`, Number.millisToString(event.duration, true));
@@ -813,8 +862,9 @@ Timeline.TimelineUIUtils = class {
case recordTypes.FunctionCall:
const detailsNode =
Timeline.TimelineUIUtils.buildDetailsNodeForTraceEvent(event, model.targetByEvent(event), linkifier);
- if (detailsNode)
+ if (detailsNode) {
contentHelper.appendElementRow(ls`Function`, detailsNode);
+ }
break;
case recordTypes.TimerFire:
case recordTypes.TimerInstall:
@@ -828,39 +878,48 @@ Timeline.TimelineUIUtils = class {
case recordTypes.FireAnimationFrame:
contentHelper.appendTextRow(ls`Callback ID`, eventData['id']);
break;
+ case recordTypes.ResourceWillSendRequest:
case recordTypes.ResourceSendRequest:
case recordTypes.ResourceReceiveResponse:
case recordTypes.ResourceReceivedData:
case recordTypes.ResourceFinish:
url = timelineData.url;
- if (url)
+ if (url) {
contentHelper.appendElementRow(ls`Resource`, Components.Linkifier.linkifyURL(url));
- if (eventData['requestMethod'])
+ }
+ if (eventData['requestMethod']) {
contentHelper.appendTextRow(ls`Request Method`, eventData['requestMethod']);
- if (typeof eventData['statusCode'] === 'number')
+ }
+ if (typeof eventData['statusCode'] === 'number') {
contentHelper.appendTextRow(ls`Status Code`, eventData['statusCode']);
- if (eventData['mimeType'])
+ }
+ if (eventData['mimeType']) {
contentHelper.appendTextRow(ls`MIME Type`, eventData['mimeType']);
+ }
if ('priority' in eventData) {
const priority = PerfUI.uiLabelForNetworkPriority(eventData['priority']);
contentHelper.appendTextRow(ls`Priority`, priority);
}
- if (eventData['encodedDataLength'])
+ if (eventData['encodedDataLength']) {
contentHelper.appendTextRow(ls`Encoded Data`, ls`${eventData['encodedDataLength']} Bytes`);
- if (eventData['decodedBodyLength'])
+ }
+ if (eventData['decodedBodyLength']) {
contentHelper.appendTextRow(ls`Decoded Body`, ls`${eventData['decodedBodyLength']} Bytes`);
+ }
break;
case recordTypes.CompileModule:
contentHelper.appendLocationRow(ls`Module`, event.args['fileName'], 0);
break;
case recordTypes.CompileScript:
url = eventData && eventData['url'];
- if (url)
+ if (url) {
contentHelper.appendLocationRow(ls`Script`, url, eventData['lineNumber'], eventData['columnNumber']);
+ }
contentHelper.appendTextRow(ls`Streamed`, eventData['streamed']);
const producedCacheSize = eventData && eventData['producedCacheSize'];
- if (producedCacheSize)
+ if (producedCacheSize) {
contentHelper.appendTextRow(ls`Produced Cache Size`, producedCacheSize);
+ }
const cacheConsumeOptions = eventData && eventData['cacheConsumeOptions'];
if (cacheConsumeOptions) {
contentHelper.appendTextRow(ls`Cache Consume Options`, cacheConsumeOptions);
@@ -870,8 +929,9 @@ Timeline.TimelineUIUtils = class {
break;
case recordTypes.EvaluateScript:
url = eventData && eventData['url'];
- if (url)
+ if (url) {
contentHelper.appendLocationRow(ls`Script`, url, eventData['lineNumber'], eventData['columnNumber']);
+ }
break;
case recordTypes.WasmStreamFromResponseCallback:
case recordTypes.WasmCompiledModule:
@@ -880,14 +940,17 @@ Timeline.TimelineUIUtils = class {
case recordTypes.WasmModuleCacheInvalid:
if (eventData) {
url = event.args['url'];
- if (url)
+ if (url) {
contentHelper.appendTextRow(ls`Url`, url);
+ }
const producedCachedSize = event.args['producedCachedSize'];
- if (producedCachedSize)
+ if (producedCachedSize) {
contentHelper.appendTextRow(ls`Produced Cache Size`, producedCachedSize);
+ }
const consumedCachedSize = event.args['consumedCachedSize'];
- if (consumedCachedSize)
+ if (consumedCachedSize) {
contentHelper.appendTextRow(ls`Consumed Cache Size`, consumedCachedSize);
+ }
}
break;
case recordTypes.Paint:
@@ -910,13 +973,15 @@ Timeline.TimelineUIUtils = class {
case recordTypes.DrawLazyPixelRef:
relatedNodeLabel = ls`Owner Element`;
url = timelineData.url;
- if (url)
+ if (url) {
contentHelper.appendElementRow(ls`Image URL`, Components.Linkifier.linkifyURL(url));
+ }
break;
case recordTypes.ParseAuthorStyleSheet:
url = eventData['styleSheetUrl'];
- if (url)
+ if (url) {
contentHelper.appendElementRow(ls`Stylesheet URL`, Components.Linkifier.linkifyURL(url));
+ }
break;
case recordTypes.UpdateLayoutTree: // We don't want to see default details.
case recordTypes.RecalculateStyles:
@@ -936,27 +1001,32 @@ Timeline.TimelineUIUtils = class {
case recordTypes.WebSocketReceiveHandshakeResponse:
case recordTypes.WebSocketDestroy:
const initiatorData = initiator ? initiator.args['data'] : eventData;
- if (typeof initiatorData['webSocketURL'] !== 'undefined')
+ if (typeof initiatorData['webSocketURL'] !== 'undefined') {
contentHelper.appendTextRow(ls`URL`, initiatorData['webSocketURL']);
- if (typeof initiatorData['webSocketProtocol'] !== 'undefined')
+ }
+ if (typeof initiatorData['webSocketProtocol'] !== 'undefined') {
contentHelper.appendTextRow(ls`WebSocket Protocol`, initiatorData['webSocketProtocol']);
- if (typeof eventData['message'] !== 'undefined')
+ }
+ if (typeof eventData['message'] !== 'undefined') {
contentHelper.appendTextRow(ls`Message`, eventData['message']);
+ }
break;
case recordTypes.EmbedderCallback:
contentHelper.appendTextRow(ls`Callback Function`, eventData['callbackName']);
break;
case recordTypes.Animation:
- if (event.phase === SDK.TracingModel.Phase.NestableAsyncInstant)
+ if (event.phase === SDK.TracingModel.Phase.NestableAsyncInstant) {
contentHelper.appendTextRow(ls`State`, eventData['state']);
+ }
break;
case recordTypes.ParseHTML: {
const beginData = event.args['beginData'];
const startLine = beginData['startLine'] - 1;
const endLine = event.args['endData'] ? event.args['endData']['endLine'] - 1 : undefined;
url = beginData['url'];
- if (url)
+ if (url) {
contentHelper.appendLocationRange(ls`Range`, url, startLine, endLine);
+ }
break;
}
@@ -991,8 +1061,9 @@ Timeline.TimelineUIUtils = class {
default: {
const detailsNode =
Timeline.TimelineUIUtils.buildDetailsNodeForTraceEvent(event, model.targetByEvent(event), linkifier);
- if (detailsNode)
+ if (detailsNode) {
contentHelper.appendElementRow(ls`Details`, detailsNode);
+ }
break;
}
}
@@ -1017,8 +1088,9 @@ Timeline.TimelineUIUtils = class {
}
if (initiator || timelineData.stackTraceForSelfOrInitiator() ||
- TimelineModel.InvalidationTracker.invalidationEventsFor(event))
+ TimelineModel.InvalidationTracker.invalidationEventsFor(event)) {
Timeline.TimelineUIUtils._generateCauses(event, model.targetByEvent(event), relatedNodesMap, contentHelper);
+ }
const stats = {};
const showPieChart = detailed && Timeline.TimelineUIUtils._aggregatedStatsForTraceEvent(stats, model, event);
@@ -1039,8 +1111,9 @@ Timeline.TimelineUIUtils = class {
*/
static _maybeAppendProductToDetails(contentHelper, badgePool, url) {
const parsedURL = url ? url.asParsedURL() : null;
- if (parsedURL)
+ if (parsedURL) {
contentHelper.appendElementRow('', badgePool.badgeForURL(parsedURL));
+ }
}
/**
@@ -1050,8 +1123,9 @@ Timeline.TimelineUIUtils = class {
* @return {!Object<string, number>}
*/
static statsForTimeRange(events, startTime, endTime) {
- if (!events.length)
+ if (!events.length) {
return {'idle': endTime - startTime};
+ }
buildRangeStatsCacheIfNeeded(events);
const aggregatedStats = subtractStats(aggregatedStatsAtTime(endTime), aggregatedStatsAtTime(startTime));
@@ -1093,8 +1167,9 @@ Timeline.TimelineUIUtils = class {
*/
function subtractStats(a, b) {
const result = Object.assign({}, a);
- for (const key in b)
+ for (const key in b) {
result[key] -= b[key];
+ }
return result;
}
@@ -1102,8 +1177,9 @@ Timeline.TimelineUIUtils = class {
* @param {!Array<!SDK.TracingModel.Event>} events
*/
function buildRangeStatsCacheIfNeeded(events) {
- if (events[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol])
+ if (events[Timeline.TimelineUIUtils._categoryBreakdownCacheSymbol]) {
return;
+ }
// aggeregatedStats is a map by categories. For each category there's an array
// containing sorted time points which records accumulated value of the category.
@@ -1131,8 +1207,9 @@ Timeline.TimelineUIUtils = class {
statsArrays = {time: [], value: []};
aggregatedStats[category] = statsArrays;
}
- if (statsArrays.time.length && statsArrays.time.peekLast() === time)
+ if (statsArrays.time.length && statsArrays.time.peekLast() === time) {
return;
+ }
const lastValue = statsArrays.value.length ? statsArrays.value.peekLast() : 0;
statsArrays.value.push(lastValue + time - lastTime);
statsArrays.time.push(time);
@@ -1144,11 +1221,13 @@ Timeline.TimelineUIUtils = class {
* @param {number} time
*/
function categoryChange(from, to, time) {
- if (from)
+ if (from) {
updateCategory(from, time);
+ }
lastTime = time;
- if (to)
+ if (to) {
updateCategory(to, time);
+ }
}
/**
@@ -1157,8 +1236,9 @@ Timeline.TimelineUIUtils = class {
function onStartEvent(e) {
const category = Timeline.TimelineUIUtils.eventStyle(e).category.name;
const parentCategory = categoryStack.length ? categoryStack.peekLast() : null;
- if (category !== parentCategory)
+ if (category !== parentCategory) {
categoryChange(parentCategory, category, e.startTime);
+ }
categoryStack.push(category);
}
@@ -1168,8 +1248,9 @@ Timeline.TimelineUIUtils = class {
function onEndEvent(e) {
const category = categoryStack.pop();
const parentCategory = categoryStack.length ? categoryStack.peekLast() : null;
- if (category !== parentCategory)
+ if (category !== parentCategory) {
categoryChange(category, parentCategory, e.endTime);
+ }
}
const obj = /** @type {!Object} */ (events);
@@ -1191,58 +1272,86 @@ Timeline.TimelineUIUtils = class {
const color = Timeline.TimelineUIUtils.networkCategoryColor(category);
contentHelper.addSection(ls`Network request`, color);
- const duration = request.endTime - (request.getStartTime() || -Infinity);
- if (request.url)
+ if (request.url) {
contentHelper.appendElementRow(ls`URL`, Components.Linkifier.linkifyURL(request.url));
+ }
Timeline.TimelineUIUtils._maybeAppendProductToDetails(contentHelper, badgePool, request.url);
- if (isFinite(duration))
- contentHelper.appendTextRow(ls`Duration`, Number.millisToString(duration, true));
- if (request.requestMethod)
+
+ // The time from queueing the request until resource processing is finished.
+ const fullDuration = request.endTime - (request.getStartTime() || -Infinity);
+ if (isFinite(fullDuration)) {
+ let textRow = Number.millisToString(fullDuration, true);
+ // The time from queueing the request until the download is finished. This
+ // corresponds to the total time reported for the request in the network tab.
+ const networkDuration = request.finishTime - request.getStartTime();
+ // The time it takes to make the resource available to the renderer process.
+ const processingDuration = request.endTime - request.finishTime;
+ if (isFinite(networkDuration) && isFinite(processingDuration)) {
+ const networkDurationStr = Number.millisToString(networkDuration, true);
+ const processingDurationStr = Number.millisToString(processingDuration, true);
+ const cacheOrNetworkLabel = request.cached() ? ls`load from cache` : ls`network transfer`;
+ textRow += ls` (${networkDurationStr} ${cacheOrNetworkLabel} + ${processingDurationStr} resource loading)`;
+ }
+ contentHelper.appendTextRow(ls`Duration`, textRow);
+ }
+
+ if (request.requestMethod) {
contentHelper.appendTextRow(ls`Request Method`, request.requestMethod);
+ }
if (typeof request.priority === 'string') {
const priority =
PerfUI.uiLabelForNetworkPriority(/** @type {!Protocol.Network.ResourcePriority} */ (request.priority));
contentHelper.appendTextRow(ls`Priority`, priority);
}
- if (request.mimeType)
+ if (request.mimeType) {
contentHelper.appendTextRow(ls`Mime Type`, request.mimeType);
+ }
let lengthText = '';
- if (request.memoryCached())
+ if (request.memoryCached()) {
lengthText += ls` (from memory cache)`;
- else if (request.cached())
+ } else if (request.cached()) {
lengthText += ls` (from cache)`;
- else if (request.timing && request.timing.pushStart)
+ } else if (request.timing && request.timing.pushStart) {
lengthText += ls` (from push)`;
- if (request.fromServiceWorker)
+ }
+ if (request.fromServiceWorker) {
lengthText += ls` (from service worker)`;
- if (request.encodedDataLength || !lengthText)
+ }
+ if (request.encodedDataLength || !lengthText) {
lengthText = `${Number.bytesToString(request.encodedDataLength)}${lengthText}`;
+ }
contentHelper.appendTextRow(ls`Encoded Data`, lengthText);
- if (request.decodedBodyLength)
+ if (request.decodedBodyLength) {
contentHelper.appendTextRow(ls`Decoded Body`, Number.bytesToString(request.decodedBodyLength));
+ }
const title = ls`Initiator`;
const sendRequest = request.children[0];
const topFrame = TimelineModel.TimelineData.forEvent(sendRequest).topFrame();
if (topFrame) {
const link = linkifier.maybeLinkifyConsoleCallFrame(target, topFrame);
- if (link)
+ if (link) {
contentHelper.appendElementRow(title, link);
+ }
} else {
const initiator = TimelineModel.TimelineData.forEvent(sendRequest).initiator();
if (initiator) {
const initiatorURL = TimelineModel.TimelineData.forEvent(initiator).url;
if (initiatorURL) {
const link = linkifier.maybeLinkifyScriptLocation(target, null, initiatorURL, 0);
- if (link)
+ if (link) {
contentHelper.appendElementRow(title, link);
+ }
}
}
}
- if (!request.previewElement && request.url && target)
- request.previewElement = await Components.ImagePreview.build(target, request.url, false);
- if (request.previewElement)
+ if (!request.previewElement && request.url && target) {
+ request.previewElement = await Components.ImagePreview.build(
+ target, request.url, false, {imageAltText: Components.ImagePreview.defaultAltTextForImageURL(request.url)});
+ }
+ if (request.previewElement) {
contentHelper.appendElementRow(ls`Preview`, request.previewElement);
+ }
return contentHelper.fragment;
}
@@ -1331,10 +1440,11 @@ Timeline.TimelineUIUtils = class {
const invalidationTrackingEvents = TimelineModel.InvalidationTracker.invalidationEventsFor(event);
const invalidations = {};
invalidationTrackingEvents.forEach(function(invalidation) {
- if (!invalidations[invalidation.type])
+ if (!invalidations[invalidation.type]) {
invalidations[invalidation.type] = [invalidation];
- else
+ } else {
invalidations[invalidation.type].push(invalidation);
+ }
});
Object.keys(invalidations).forEach(function(type) {
@@ -1386,8 +1496,9 @@ Timeline.TimelineUIUtils = class {
for (let index = 0; index < invalidations.length; index++) {
const invalidation = invalidations[index];
let causeKey = '';
- if (invalidation.cause.reason)
+ if (invalidation.cause.reason) {
causeKey += invalidation.cause.reason + '.';
+ }
if (invalidation.cause.stackTrace) {
invalidation.cause.stackTrace.forEach(function(stackFrame) {
causeKey += stackFrame['functionName'] + '.';
@@ -1398,10 +1509,11 @@ Timeline.TimelineUIUtils = class {
});
}
- if (causeToInvalidationMap.has(causeKey))
+ if (causeToInvalidationMap.has(causeKey)) {
causeToInvalidationMap.get(causeKey).push(invalidation);
- else
+ } else {
causeToInvalidationMap.set(causeKey, [invalidation]);
+ }
}
return causeToInvalidationMap.valuesArray();
}
@@ -1433,21 +1545,26 @@ Timeline.TimelineUIUtils = class {
}
const index = events.binaryIndexOf(event.startTime, eventComparator);
// Not a main thread event?
- if (index < 0)
+ if (index < 0) {
return false;
+ }
let hasChildren = false;
const endTime = event.endTime;
if (endTime) {
for (let i = index; i < events.length; i++) {
const nextEvent = events[i];
- if (nextEvent.startTime >= endTime)
+ if (nextEvent.startTime >= endTime) {
break;
- if (!nextEvent.selfTime)
+ }
+ if (!nextEvent.selfTime) {
continue;
- if (nextEvent.thread !== event.thread)
+ }
+ if (nextEvent.thread !== event.thread) {
continue;
- if (i > index)
+ }
+ if (i > index) {
hasChildren = true;
+ }
const categoryName = Timeline.TimelineUIUtils.eventStyle(nextEvent).category.name;
total[categoryName] = (total[categoryName] || 0) + nextEvent.selfTime;
}
@@ -1455,8 +1572,9 @@ Timeline.TimelineUIUtils = class {
if (SDK.TracingModel.isAsyncPhase(event.phase)) {
if (event.endTime) {
let aggregatedTotal = 0;
- for (const categoryName in total)
+ for (const categoryName in total) {
aggregatedTotal += total[categoryName];
+ }
total['idle'] = Math.max(0, event.endTime - event.startTime - aggregatedTotal);
}
return false;
@@ -1471,18 +1589,21 @@ Timeline.TimelineUIUtils = class {
*/
static async buildPicturePreviewContent(event, target) {
const snapshotWithRect = await new TimelineModel.LayerPaintEvent(event, target).snapshotPromise();
- if (!snapshotWithRect)
+ if (!snapshotWithRect) {
return null;
+ }
const imageURLPromise = snapshotWithRect.snapshot.replay();
snapshotWithRect.snapshot.release();
const imageURL = await imageURLPromise;
- if (!imageURL)
+ if (!imageURL) {
return null;
+ }
const container = createElement('div');
UI.appendStyle(container, 'components/imagePreview.css');
container.classList.add('image-preview-container', 'vbox', 'link');
const img = container.createChild('img');
img.src = imageURL;
+ img.alt = Components.ImagePreview.defaultAltTextForImageURL(imageURL);
const paintProfilerButton = container.createChild('a');
paintProfilerButton.textContent = ls`Paint Profiler`;
container.addEventListener(
@@ -1501,8 +1622,9 @@ Timeline.TimelineUIUtils = class {
const startTime = Number.millisToString(event.startTime - zeroTime);
eventDivider.title = Common.UIString('%s at %s', Timeline.TimelineUIUtils.eventTitle(event), startTime);
const style = Timeline.TimelineUIUtils.markerStyleForEvent(event);
- if (style.tall)
+ if (style.tall) {
eventDivider.style.backgroundColor = style.color;
+ }
return eventDivider;
}
@@ -1513,8 +1635,9 @@ Timeline.TimelineUIUtils = class {
const eventStyles = Timeline.TimelineUIUtils._initEventStyles();
const result = [];
for (const name in eventStyles) {
- if (!eventStyles[name].hidden)
+ if (!eventStyles[name].hidden) {
result.push(name);
+ }
}
return result;
}
@@ -1530,8 +1653,9 @@ Timeline.TimelineUIUtils = class {
* @return {!Object.<string, !Timeline.TimelineCategory>}
*/
static categories() {
- if (Timeline.TimelineUIUtils._categories)
+ if (Timeline.TimelineUIUtils._categories) {
return Timeline.TimelineUIUtils._categories;
+ }
Timeline.TimelineUIUtils._categories = {
loading: new Timeline.TimelineCategory('loading', ls`Loading`, true, 'hsl(214, 67%, 74%)', 'hsl(214, 67%, 66%)'),
scripting:
@@ -1549,6 +1673,31 @@ Timeline.TimelineUIUtils = class {
}
/**
+ * @param {!Object.<string, !Timeline.TimelineCategory>} categories
+ */
+ static setCategories(categories) {
+ Timeline.TimelineUIUtils._categories = categories;
+ }
+
+ /**
+ * @return {!Array}
+ */
+ static getTimelineMainEventCategories() {
+ if (Timeline.TimelineUIUtils._eventCategories) {
+ return Timeline.TimelineUIUtils._eventCategories;
+ }
+ Timeline.TimelineUIUtils._eventCategories = ['idle', 'loading', 'painting', 'rendering', 'scripting', 'other'];
+ return Timeline.TimelineUIUtils._eventCategories;
+ }
+
+ /**
+ * @param {!Array} categories
+ */
+ static setTimelineMainEventCategories(categories) {
+ Timeline.TimelineUIUtils._eventCategories = categories;
+ }
+
+ /**
* @param {!Object} aggregatedStats
* @param {!Timeline.TimelineCategory=} selfCategory
* @param {number=} selfTime
@@ -1556,8 +1705,9 @@ Timeline.TimelineUIUtils = class {
*/
static generatePieChart(aggregatedStats, selfCategory, selfTime) {
let total = 0;
- for (const categoryName in aggregatedStats)
+ for (const categoryName in aggregatedStats) {
total += aggregatedStats[categoryName];
+ }
const element = createElementWithClass('div', 'timeline-details-view-pie-chart-wrapper hbox');
const pieChart = new PerfUI.PieChart({
@@ -1578,8 +1728,9 @@ Timeline.TimelineUIUtils = class {
* @param {string} color
*/
function appendLegendRow(name, title, value, color) {
- if (!value)
+ if (!value) {
return;
+ }
pieChart.addSlice(value, color, title);
}
@@ -1601,8 +1752,9 @@ Timeline.TimelineUIUtils = class {
// Add other categories.
for (const categoryName in Timeline.TimelineUIUtils.categories()) {
const category = Timeline.TimelineUIUtils.categories()[categoryName];
- if (category === selfCategory)
+ if (category === selfCategory) {
continue;
+ }
appendLegendRow(category.name, category.title, aggregatedStats[category.name], category.childColor);
}
return element;
@@ -1631,8 +1783,9 @@ Timeline.TimelineUIUtils = class {
filmStripPreview.addEventListener('click', frameClicked.bind(null, filmStripFrame), false);
}
- if (frame.layerTree)
+ if (frame.layerTree) {
contentHelper.appendElementRow(ls`Layer tree`, Components.Linkifier.linkifyRevealable(frame.layerTree, ls`Show`));
+ }
/**
* @param {!SDK.FilmStripModel.Frame} filmStripFrame
@@ -1652,8 +1805,9 @@ Timeline.TimelineUIUtils = class {
const durationText = Common.UIString(
'%s (at %s)', Number.millisToString(frame.endTime - frame.startTime, true),
Number.millisToString(frame.startTimeOffset, true));
- if (!frame.hasWarnings())
+ if (!frame.hasWarnings()) {
return UI.formatLocalized('%s', [durationText]);
+ }
const link = UI.XLink.create('https://developers.google.com/web/fundamentals/performance/rendering/', ls`jank`);
return UI.formatLocalized('%s. Long frame times are an indication of %s', [durationText, link]);
@@ -1697,8 +1851,9 @@ Timeline.TimelineUIUtils = class {
* @return {!Array.<!Timeline.TimelineUIUtils.EventDispatchTypeDescriptor>}
*/
static eventDispatchDesciptors() {
- if (Timeline.TimelineUIUtils._eventDispatchDesciptors)
+ if (Timeline.TimelineUIUtils._eventDispatchDesciptors) {
return Timeline.TimelineUIUtils._eventDispatchDesciptors;
+ }
const lightOrange = 'hsl(40,100%,80%)';
const orange = 'hsl(40,100%,50%)';
const green = 'hsl(90,100%,40%)';
@@ -1842,8 +1997,9 @@ Timeline.TimelineUIUtils = class {
static eventWarning(event, warningType) {
const timelineData = TimelineModel.TimelineData.forEvent(event);
const warning = warningType || timelineData.warning;
- if (!warning)
+ if (!warning) {
return null;
+ }
const warnings = TimelineModel.TimelineModel.WarningType;
const span = createElement('span');
const eventData = event.args['data'];
@@ -1889,25 +2045,23 @@ Timeline.TimelineUIUtils = class {
*/
static displayNameForFrame(frame, trimAt) {
const url = frame.url;
- if (!trimAt)
+ if (!trimAt) {
trimAt = 30;
+ }
return url.startsWith('about:') ? `"${frame.name.trimMiddle(trimAt)}"` : frame.url.trimEnd(trimAt);
}
};
-/**
- * @unrestricted
- */
Timeline.TimelineRecordStyle = class {
/**
* @param {string} title
* @param {!Timeline.TimelineCategory} category
* @param {boolean=} hidden
*/
- constructor(title, category, hidden) {
+ constructor(title, category, hidden = false) {
this.title = title;
this.category = category;
- this.hidden = !!hidden;
+ this.hidden = hidden;
}
};
@@ -1960,8 +2114,9 @@ Timeline.TimelineUIUtils.InvalidationsGroupElement = class extends UI.TreeElemen
const topFrame = first.cause.stackTrace && first.cause.stackTrace[0];
const truncatedNodesElement = this._getTruncatedNodesElement(this._invalidations);
- if (truncatedNodesElement === null)
+ if (truncatedNodesElement === null) {
return UI.formatLocalized(reason, []);
+ }
const title = UI.formatLocalized('%s for %s', [reason, truncatedNodesElement]);
@@ -2002,8 +2157,9 @@ Timeline.TimelineUIUtils.InvalidationsGroupElement = class extends UI.TreeElemen
const invalidation = this._invalidations[i];
const invalidationNode = this._createInvalidationNode(invalidation, true);
if (invalidationNode) {
- if (!firstNode)
+ if (!firstNode) {
nodeList.createTextChild(ls`, `);
+ }
firstNode = false;
nodeList.appendChild(invalidationNode);
@@ -2189,8 +2345,9 @@ Timeline.TimelinePopupContentHelper = class {
text.createTextChild(String(content));
const cell = createElement('td');
cell.className = 'timeline-details';
- if (styleName)
+ if (styleName) {
cell.className += ' ' + styleName;
+ }
cell.textContent = content;
return cell;
}
@@ -2216,10 +2373,11 @@ Timeline.TimelinePopupContentHelper = class {
row.appendChild(titleCell);
const cell = createElement('td');
cell.className = 'details';
- if (content instanceof Node)
+ if (content instanceof Node) {
cell.appendChild(content);
- else
+ } else {
cell.createTextChild(content || '');
+ }
row.appendChild(cell);
this._contentTable.appendChild(row);
}
@@ -2258,8 +2416,9 @@ Timeline.TimelineDetailsContentHelper = class {
if (title) {
const titleElement = this.element.createChild('div', 'timeline-details-chip-title');
- if (swatchColor)
+ if (swatchColor) {
titleElement.createChild('div').style.backgroundColor = swatchColor;
+ }
titleElement.createTextChild(title);
}
@@ -2292,17 +2451,20 @@ Timeline.TimelineDetailsContentHelper = class {
*/
appendElementRow(title, content, isWarning, isStacked) {
const rowElement = this._tableElement.createChild('div', 'timeline-details-view-row');
- if (isWarning)
+ if (isWarning) {
rowElement.classList.add('timeline-details-warning');
- if (isStacked)
+ }
+ if (isStacked) {
rowElement.classList.add('timeline-details-stack-values');
+ }
const titleElement = rowElement.createChild('div', 'timeline-details-view-row-title');
titleElement.textContent = title;
const valueElement = rowElement.createChild('div', 'timeline-details-view-row-value');
- if (content instanceof Node)
+ if (content instanceof Node) {
valueElement.appendChild(content);
- else
+ } else {
valueElement.createTextChild(content || '');
+ }
}
/**
@@ -2312,11 +2474,13 @@ Timeline.TimelineDetailsContentHelper = class {
* @param {number=} startColumn
*/
appendLocationRow(title, url, startLine, startColumn) {
- if (!this._linkifier || !this._target)
+ if (!this._linkifier || !this._target) {
return;
+ }
const link = this._linkifier.maybeLinkifyScriptLocation(this._target, null, url, startLine, startColumn);
- if (!link)
+ if (!link) {
return;
+ }
this.appendElementRow(title, link);
}
@@ -2327,12 +2491,14 @@ Timeline.TimelineDetailsContentHelper = class {
* @param {number=} endLine
*/
appendLocationRange(title, url, startLine, endLine) {
- if (!this._linkifier || !this._target)
+ if (!this._linkifier || !this._target) {
return;
+ }
const locationContent = createElement('span');
const link = this._linkifier.maybeLinkifyScriptLocation(this._target, null, url, startLine);
- if (!link)
+ if (!link) {
return;
+ }
locationContent.appendChild(link);
locationContent.createTextChild(String.sprintf(' [%s\u2026%s]', startLine + 1, endLine + 1 || ''));
this.appendElementRow(title, locationContent);
@@ -2343,8 +2509,9 @@ Timeline.TimelineDetailsContentHelper = class {
* @param {!Protocol.Runtime.StackTrace} stackTrace
*/
appendStackTrace(title, stackTrace) {
- if (!this._linkifier || !this._target)
+ if (!this._linkifier || !this._target) {
return;
+ }
const rowElement = this._tableElement.createChild('div', 'timeline-details-view-row');
rowElement.createChild('div', 'timeline-details-view-row-title').textContent = title;
@@ -2356,8 +2523,9 @@ Timeline.TimelineDetailsContentHelper = class {
* @param {!Protocol.Runtime.StackTrace} stackTrace
*/
createChildStackTraceElement(parentElement, stackTrace) {
- if (!this._linkifier || !this._target)
+ if (!this._linkifier || !this._target) {
return;
+ }
parentElement.classList.add('timeline-details-stack-values');
const stackTraceElement =
parentElement.createChild('div', 'timeline-details-view-row-value timeline-details-view-row-stack-trace');
@@ -2372,8 +2540,9 @@ Timeline.TimelineDetailsContentHelper = class {
*/
appendWarningRow(event, warningType) {
const warning = Timeline.TimelineUIUtils.eventWarning(event, warningType);
- if (warning)
+ if (warning) {
this.appendElementRow(ls`Warning`, warning, true);
+ }
}
};
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_system_client.h b/chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsController.js
index 7288beb24e0..2fcf0dd4acb 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_system_client.h
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsController.js
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
+ * 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
@@ -28,46 +28,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.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"
-
-namespace blink {
-
-class ExecutionContext;
-class LocalFrame;
-class WorkerClients;
-
-class FileSystemClient {
- USING_FAST_MALLOC(FileSystemClient);
-
- public:
- FileSystemClient() = default;
- virtual ~FileSystemClient() = default;
-
- virtual bool RequestFileSystemAccessSync(ExecutionContext*) = 0;
- virtual void RequestFileSystemAccessAsync(ExecutionContext*,
- base::OnceCallback<void(bool)>) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FileSystemClient);
-};
-
-MODULES_EXPORT void ProvideLocalFileSystemTo(LocalFrame&,
- std::unique_ptr<FileSystemClient>);
-
-MODULES_EXPORT void ProvideLocalFileSystemToWorker(
- WorkerClients*,
- std::unique_ptr<FileSystemClient>);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_
+/**
+ * @extends {Timeline.TimelineController}
+ * @unrestricted
+ */
+Timeline.UIDevtoolsController = class extends Timeline.TimelineController {
+ constructor(target, client) {
+ super(target, client);
+ Timeline.TimelineUIUtils.setEventStylesMap(Timeline.UIDevtoolsUtils.categorizeEvents());
+ Timeline.TimelineUIUtils.setCategories(Timeline.UIDevtoolsUtils.categories());
+ Timeline.TimelineUIUtils.setTimelineMainEventCategories(Timeline.UIDevtoolsUtils.getMainCategoriesList());
+ }
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsUtils.js
new file mode 100644
index 00000000000..f9f72144c80
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/UIDevtoolsUtils.js
@@ -0,0 +1,143 @@
+/*
+ * 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:
+ *
+ * * 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.
+ */
+
+/**
+ * @unrestricted
+ */
+Timeline.UIDevtoolsUtils = class {
+ /**
+ * @return {boolean}
+ */
+ static isUiDevTools() {
+ return Root.Runtime.queryParam('uiDevTools') === 'true';
+ }
+
+ /**
+ * @return {!Object.<string, !Timeline.TimelineRecordStyle>}
+ */
+ static categorizeEvents() {
+ if (Timeline.UIDevtoolsUtils._eventStylesMap) {
+ return Timeline.UIDevtoolsUtils._eventStylesMap;
+ }
+
+ const type = Timeline.UIDevtoolsUtils.RecordType;
+ const categories = Timeline.UIDevtoolsUtils.categories();
+ const drawing = categories['drawing'];
+ const rasterizing = categories['rasterizing'];
+ const layout = categories['layout'];
+ const painting = categories['painting'];
+ const other = categories['other'];
+
+ const eventStyles = {};
+
+ // Paint Categories
+ eventStyles[type.ViewPaint] = new Timeline.TimelineRecordStyle(ls`View::Paint`, painting);
+ eventStyles[type.ViewOnPaint] = new Timeline.TimelineRecordStyle(ls`View::OnPaint`, painting);
+ eventStyles[type.ViewPaintChildren] = new Timeline.TimelineRecordStyle(ls`View::PaintChildren`, painting);
+ eventStyles[type.ViewOnPaintBackground] = new Timeline.TimelineRecordStyle(ls`View::OnPaintBackground`, painting);
+ eventStyles[type.ViewOnPaintBorder] = new Timeline.TimelineRecordStyle(ls`View::OnPaintBorder`, painting);
+ eventStyles[type.LayerPaintContentsToDisplayList] =
+ new Timeline.TimelineRecordStyle(ls`Layer::PaintContentsToDisplayList`, painting);
+
+ // Layout Categories
+ eventStyles[type.ViewLayout] = new Timeline.TimelineRecordStyle(ls`View::Layout`, layout);
+ eventStyles[type.ViewLayoutBoundsChanged] =
+ new Timeline.TimelineRecordStyle(ls`View::Layout(bounds_changed)`, layout);
+
+ // Raster Categories
+ eventStyles[type.RasterTask] = new Timeline.TimelineRecordStyle(ls`RasterTask`, rasterizing);
+ eventStyles[type.RasterizerTaskImplRunOnWorkerThread] =
+ new Timeline.TimelineRecordStyle(ls`RasterizerTaskImpl::RunOnWorkerThread`, rasterizing);
+
+ // Draw Categories
+ eventStyles[type.DirectRendererDrawFrame] =
+ new Timeline.TimelineRecordStyle(ls`DirectRenderer::DrawFrame`, drawing);
+ eventStyles[type.BeginFrame] = new Timeline.TimelineRecordStyle(ls`Frame Start`, drawing, true);
+ eventStyles[type.DrawFrame] = new Timeline.TimelineRecordStyle(ls`Draw Frame`, drawing, true);
+ eventStyles[type.NeedsBeginFrameChanged] =
+ new Timeline.TimelineRecordStyle(ls`NeedsBeginFrameChanged`, drawing, true);
+
+ // Other Categories
+ eventStyles[type.ThreadControllerImplRunTask] =
+ new Timeline.TimelineRecordStyle(ls`ThreadControllerImpl::RunTask`, other);
+
+ Timeline.UIDevtoolsUtils._eventStylesMap = eventStyles;
+ return eventStyles;
+ }
+
+ /**
+ * @return {!Object.<string, !Timeline.TimelineCategory>}
+ */
+ static categories() {
+ if (Timeline.UIDevtoolsUtils._categories) {
+ return Timeline.UIDevtoolsUtils._categories;
+ }
+ Timeline.UIDevtoolsUtils._categories = {
+ layout: new Timeline.TimelineCategory('layout', ls`Layout`, true, 'hsl(214, 67%, 74%)', 'hsl(214, 67%, 66%)'),
+ rasterizing: new Timeline.TimelineCategory(
+ 'rasterizing', ls`Rasterizing`, true, 'hsl(43, 83%, 72%)', 'hsl(43, 83%, 64%) '),
+ drawing: new Timeline.TimelineCategory('drawing', ls`Drawing`, true, 'hsl(256, 67%, 76%)', 'hsl(256, 67%, 70%)'),
+ painting:
+ new Timeline.TimelineCategory('painting', ls`Painting`, true, 'hsl(109, 33%, 64%)', 'hsl(109, 33%, 55%)'),
+ other: new Timeline.TimelineCategory('other', ls`System`, false, 'hsl(0, 0%, 87%)', 'hsl(0, 0%, 79%)'),
+ idle: new Timeline.TimelineCategory('idle', ls`Idle`, false, 'hsl(0, 0%, 98%)', 'hsl(0, 0%, 98%)')
+ };
+ return Timeline.UIDevtoolsUtils._categories;
+ }
+
+ /**
+ * @return {!Array}
+ */
+ static getMainCategoriesList() {
+ return ['idle', 'drawing', 'painting', 'rasterizing', 'layout', 'other'];
+ }
+};
+
+
+/**
+ * @enum {string}
+ */
+Timeline.UIDevtoolsUtils.RecordType = {
+ ViewPaint: 'View::Paint',
+ ViewOnPaint: 'View::OnPaint',
+ ViewPaintChildren: 'View::PaintChildren',
+ ViewOnPaintBackground: 'View::OnPaintBackground',
+ ViewOnPaintBorder: 'View::OnPaintBorder',
+ ViewLayout: 'View::Layout',
+ ViewLayoutBoundsChanged: 'View::Layout(bounds_changed)',
+ LayerPaintContentsToDisplayList: 'Layer::PaintContentsToDisplayList',
+ DirectRendererDrawFrame: 'DirectRenderer::DrawFrame',
+ RasterTask: 'RasterTask',
+ RasterizerTaskImplRunOnWorkerThread: 'RasterizerTaskImpl::RunOnWorkerThread',
+ BeginFrame: 'BeginFrame',
+ DrawFrame: 'DrawFrame',
+ NeedsBeginFrameChanged: 'NeedsBeginFrameChanged',
+ ThreadControllerImplRunTask: 'ThreadControllerImpl::RunTask',
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/module.json b/chromium/third_party/blink/renderer/devtools/front_end/timeline/module.json
index 7a17009b41e..1e682011918 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/module.json
@@ -220,6 +220,7 @@
],
"dependencies": [
"components",
+ "coverage",
"layer_viewer",
"timeline_model",
"perf_ui",
@@ -247,7 +248,9 @@
"TimelineUIUtils.js",
"TimelineLayersView.js",
"TimelinePaintProfilerView.js",
- "TimelinePanel.js"
+ "TimelinePanel.js",
+ "UIDevtoolsUtils.js",
+ "UIDevtoolsController.js"
],
"resources": [
"historyToolbarButton.css",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
index 225c6a9caf4..e4c089ff047 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
@@ -240,6 +240,21 @@
line-height: 18px;
}
+#timeline-overview-coverage {
+ flex-basis: 20px;
+}
+
+.timeline-overview-coverage-label {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ font-size: 9px;
+ color: #888;
+ white-space: nowrap;
+ padding: 0 4px;
+ background-color: hsla(0, 0%, 100%, 0.8);
+}
+
.timeline-details {
vertical-align: top;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
index 73088de110b..3219d7d3c4e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
@@ -69,9 +69,15 @@
<message name="IDS_DEVTOOLS_08db5f30f625a406882862b8a29b1bc6" desc="Text in Timeline UIUtils of the Performance panel">
Major GC
</message>
+ <message name="IDS_DEVTOOLS_099ca81d7a70c42447d89e172198ba5d" desc="Aria-label for filter bar in Event Log view">
+ Filter event log
+ </message>
<message name="IDS_DEVTOOLS_09d66464ad53e6080988ad30824ea023" desc="Text in Timeline Flame Chart Data Provider of the Performance panel">
Frame — <ph name="TRACK_URL">$1s<ex>https://example.com</ex></ph>
</message>
+ <message name="IDS_DEVTOOLS_0a9d131e2c626ead31d9ecb8c54e3372" desc="Text in UIDevtools Utils of the Performance panel">
+ View::OnPaintBackground
+ </message>
<message name="IDS_DEVTOOLS_0d015d96f63a8c12d96b8399482b593f" desc="Text in Timeline UIUtils of the Performance panel">
Uncategorized
</message>
@@ -86,7 +92,7 @@
Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <ph name="RELOADKEY">$4s<ex>Ctrl + R</ex></ph> to record the page load.
</message>
<message name="IDS_DEVTOOLS_0e8dfe937d359c7df31b16ea7e9cca81" desc="Title of a setting under the Performance category in Settings">
- Hide chrome frame in Layers view
+ Hide <ph name="LOCKED_1">chrome</ph> frame in Layers view
</message>
<message name="IDS_DEVTOOLS_10aab9f12eca6bca3a6215914bab2745" desc="Text in Timeline UIUtils of the Performance panel">
Allotted Time
@@ -157,6 +163,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_24aa4117da86c41684ad25742832dfa6" desc="Text in Timeline UIUtils of the Performance panel">
Async
</message>
+ <message name="IDS_DEVTOOLS_24ed51e784c08847f2c1bafe1a6428a4" desc="Text in Timeline UIUtils of the Performance panel">
+ Will Send Request
+ </message>
<message name="IDS_DEVTOOLS_25a5e1f05232eae2d3a9c1ff4cb83869" desc="Text in Timeline UIUtils of the Performance panel">
Function Call
</message>
@@ -169,6 +178,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_2a0e96bf571559add541036a25ca1d36" desc="Text in Timeline UIUtils of the Performance panel">
Call Stacks
</message>
+ <message name="IDS_DEVTOOLS_2a4d793c571c935ed156c25249a45219" desc="Text in UIDevtools Utils of the Performance panel">
+ View::OnPaintBorder
+ </message>
<message name="IDS_DEVTOOLS_2a5021aea912316167342b34cbf358b4" desc="Text in Timeline UIUtils of the Performance panel">
Compile Module
</message>
@@ -202,9 +214,6 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_2fc3f5e968c02091e3ba9863088f0651" desc="Text in Timeline UIUtils of the Performance panel">
Callback Function
</message>
- <message name="IDS_DEVTOOLS_31084046e4a000cc4ac980dc68ea9ce9" desc="Text in Timeline UIUtils of the Performance panel">
- Parse Script
- </message>
<message name="IDS_DEVTOOLS_316853cc3718335f11c048e33b9be98a" desc="Text in Timeline UIUtils of the Performance panel">
Click
</message>
@@ -256,6 +265,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_3df7062234c9e55d49648289c5b2c80f" desc="Text in Timeline UIUtils of the Performance panel">
Time spent in rendering
</message>
+ <message name="IDS_DEVTOOLS_3e8436f8c107f458c78f61101ef33bef" desc="Text in UIDevtools Utils of the Performance panel">
+ DirectRenderer::DrawFrame
+ </message>
<message name="IDS_DEVTOOLS_3e8e23cb13898f3f9760a0f1d9203bd1" desc="Text of a DOM element in Timeline UIUtils of the Performance panel">
Stack trace:
</message>
@@ -277,9 +289,6 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_44ff4e8748811d0661f820aeb28ecaf4" desc="Text in Timeline UIUtils of the Performance panel">
XHR Ready State Change
</message>
- <message name="IDS_DEVTOOLS_46a2a41cc6e552044816a2d04634545d" desc="Text in Timeline UIUtils of the Performance panel">
- State
- </message>
<message name="IDS_DEVTOOLS_46fa564bb1eed5cd3992cac85e8f094b" desc="Title of show screenshots setting in timeline panel of the performance panel">
Screenshots
</message>
@@ -349,6 +358,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_55b4b48b80795ee9b6a3220ca415786d" desc="Text in Timeline UIUtils of the Performance panel">
Schedule Style Recalculation
</message>
+ <message name="IDS_DEVTOOLS_571d0a86e3e15c23eb715c4e8b46b7b8" desc="Text in Timeline UIUtils of the Performance panel">
+ ''' (<ph name="NETWORKDURATIONSTR">$1s<ex>1ms</ex></ph> <ph name="CACHEORNETWORKLABEL">$2s<ex>network transfer</ex></ph> + <ph name="PROCESSINGDURATIONSTR">$3s<ex>1ms</ex></ph> resource loading)
+ </message>
<message name="IDS_DEVTOOLS_57f06e0eceb273507ade79baf8d3a2d4" desc="Text in Timeline UIUtils of the Performance panel">
Tap Begin
</message>
@@ -388,6 +400,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_5fbceaa309bba91ee916d46e06ac0080" desc="Text in Timeline UIUtils of the Performance panel">
Touch Move
</message>
+ <message name="IDS_DEVTOOLS_5fc3cf362fe793dce7e093c63b583f88" desc="Text in UIDevtools Utils of the Performance panel">
+ View::Layout(bounds_changed)
+ </message>
<message name="IDS_DEVTOOLS_5fe7053d3a0e35c2a3242996e690e160" desc="Text in Timeline UIUtils of the Performance panel">
Update Layer
</message>
@@ -418,11 +433,14 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_66f1aed235ade25269a561e81cbbb43a" desc="Text in Timeline UIUtils of the Performance panel">
Scripting
</message>
+ <message name="IDS_DEVTOOLS_6734ebb8322bff404034f6ebbcc0d2fb" desc="Aria-label for filter bar in Call Tree view">
+ Filter call tree
+ </message>
<message name="IDS_DEVTOOLS_67eed98f4bc75c4ab261b79a0e2c52cd" desc="Text in Timeline UIUtils of the Performance panel">
Cache Rejected
</message>
- <message name="IDS_DEVTOOLS_686155af75a60a0f6e9d80c1f7edd3e9" desc="Text in Timeline Tree View of the Performance panel">
- JavaScript
+ <message name="IDS_DEVTOOLS_681d72abce5de4f856e71bfb1856796b" desc="Text in UIDevtools Utils of the Performance panel">
+ Drawing
</message>
<message name="IDS_DEVTOOLS_6978c23868116ca3eccb809bc699742e" desc="Text in Timeline Panel of the Performance panel">
- Significant overhead due to paint instrumentation
@@ -430,9 +448,6 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_6a389f626da11df07508bf251de59c23" desc="Text in Timeline UIUtils of the Performance panel">
Frame Start
</message>
- <message name="IDS_DEVTOOLS_6aafe894685594a908a8996d68e88028" desc="Text in Events Timeline Tree View of the Performance panel">
- Hide records shorter than <ph name="DURATIONMS">$1d<ex>2</ex></ph> ms
- </message>
<message name="IDS_DEVTOOLS_6c906c5f560faeb38f51683bc22fb212" desc="Text in Timeline Tree View of the Performance panel">
Group by Subdomain
</message>
@@ -448,6 +463,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_6d8a59067ffe0498f3f5f2c03025b799" desc="Text in Timeline Tree View of the Performance panel">
Group by URL
</message>
+ <message name="IDS_DEVTOOLS_6ebfbd6a11e852377844c8fd6e1608cc" desc="Text in UIDevtools Utils of the Performance panel">
+ View::OnPaint
+ </message>
<message name="IDS_DEVTOOLS_70582905817c902e7a334c24718cba88" desc="Text in Timeline UIUtils of the Performance panel">
Touch End
</message>
@@ -463,6 +481,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_71613aba6474d2e2dc12d00cc46743f0" desc="Text in Timeline UIUtils of the Performance panel">
Touch Start
</message>
+ <message name="IDS_DEVTOOLS_733bca87dd487283ef74a651c4eea432" desc="Text in UIDevtools Utils of the Performance panel">
+ View::PaintChildren
+ </message>
<message name="IDS_DEVTOOLS_7363d05ecc1497f2f8ae05b334b45651" desc="Title of disable capture jsprofile setting in timeline panel of the performance panel">
Disable JavaScript samples
</message>
@@ -473,7 +494,7 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
Decrypt
</message>
<message name="IDS_DEVTOOLS_76e815d5323a5f3c80a3d186c416e92b" desc="Text in Timeline Tree View of the Performance panel">
- [Chrome extensions overhead]
+ [<ph name="LOCKED_1">Chrome</ph> extensions overhead]
</message>
<message name="IDS_DEVTOOLS_76ecb02d1f339c2dd6f14c41ead368c1" desc="Span text content in Timeline UIUtils of the Performance panel">
Handler took <ph name="NUMBER_MILLISTOSTRING_EVENT_DURATION__TRUE_">$1s<ex>10ms</ex></ph>
@@ -493,11 +514,8 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_7ac6c415cd08c0ba2c0a1f54c0a62a52" desc="Text in Timeline UIUtils of the Performance panel">
''' (from push)
</message>
- <message name="IDS_DEVTOOLS_7b3a6b02f467b95f2b5267aa94708c07" desc="Text in Timeline Flame Chart Data Provider of the Performance panel">
- Thread <ph name="__THREADINDEX">$1s<ex>2</ex></ph>
- </message>
- <message name="IDS_DEVTOOLS_7d341c08fd102f0b86285b5ff2e26ea7" desc="Text in Timeline UIUtils of the Performance panel">
- <ph name="TITLE">$1s<ex>Loading</ex></ph>: <ph name="EVENTDATA__MESSAGE__">$2s<ex>paint</ex></ph>
+ <message name="IDS_DEVTOOLS_80a0135dfd4156f542f097a6351c727f" desc="Text in Timeline UIUtils of the Performance panel">
+ Streaming Compile Script
</message>
<message name="IDS_DEVTOOLS_80a4b8755d836d50c19e6eefb976bc2e" desc="Text in Timeline UIUtils of the Performance panel">
<ph name="SELFCATEGORY_TITLE">$1s<ex>blink.console</ex></ph> (self)
@@ -523,6 +541,9 @@ Click the reload button <ph name="RELOADBUTTON">$3s<ex>reload</ex></ph> or hit <
<message name="IDS_DEVTOOLS_86c8559f4d7d1d74dc3e04baf2b65cc6" desc="Text in Timeline UIUtils of the Performance panel">
Decoded Body
</message>
+ <message name="IDS_DEVTOOLS_86d31b04bab25c0e7f353b8b3a000445" desc="Text in UIDevtools Utils of the Performance panel">
+ Rasterizing
+ </message>
<message name="IDS_DEVTOOLS_871646cb17b6936aa29df33b8d550051" desc="Text in Timeline UIUtils of the Performance panel">
Update Layer Tree
</message>
@@ -606,9 +627,6 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_97c091732895087b8900d81105e54446" desc="Text in Timeline UIUtils of the Performance panel">
Frame Start (main thread)
</message>
- <message name="IDS_DEVTOOLS_997a8c473db4f81c5fb3d5900030d44d" desc="Text in Timeline History Manager of the Performance panel">
- (no recordings)
- </message>
<message name="IDS_DEVTOOLS_9a2837081f4b4cd67f625bd8e7567383" desc="Text in Timeline UIUtils of the Performance panel">
Compile Script
</message>
@@ -630,6 +648,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_a10717d996573373c8f9a01c49bbb6a5" desc="Text in Timeline Panel of the Performance panel">
Loading profile…
</message>
+ <message name="IDS_DEVTOOLS_a34991663b140f981410a06acc058849" desc="Text in UIDevtools Utils of the Performance panel">
+ ThreadControllerImpl::RunTask
+ </message>
<message name="IDS_DEVTOOLS_a3b61900010aa9472919c6c7ac247fed" desc="Text of a DOM element in Timeline UIUtils of the Performance panel">
(changed id to &quot;<ph name="INVALIDATION_CHANGEDID">$1s<ex>id2</ex></ph>&quot;<ph name="EXTRADATA">$2s<ex>a, b</ex></ph>)
</message>
@@ -639,12 +660,18 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_a580a76abe8b0912889d80f5c4cb9559" desc="Text in Timeline Tree View of the Performance panel">
Group by Product
</message>
+ <message name="IDS_DEVTOOLS_a5d91e1697b7c75863fb9c6163a3446e" desc="Text in Timeline Event Overview of the Performance panel">
+ COVERAGE
+ </message>
<message name="IDS_DEVTOOLS_a6f22a2373839a1d417d7a4078f0383a" desc="Text in Timeline Panel of the Performance panel">
- CPU throttling is enabled
</message>
<message name="IDS_DEVTOOLS_a7c815fafe60ae637d38216fa6300395" desc="Text in Timeline UIUtils of the Performance panel">
FCP
</message>
+ <message name="IDS_DEVTOOLS_a9e8acf624d918c753e98cefbd2352c9" desc="Text in UIDevtools Utils of the Performance panel">
+ NeedsBeginFrameChanged
+ </message>
<message name="IDS_DEVTOOLS_aa40d845ecb78d5bd01ff8b0cc9e213e" desc="Text in Timeline UIUtils of the Performance panel">
Receive Data
</message>
@@ -663,6 +690,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_aed0e2bd848c2ac9dddb03d8c21c67b6" desc="Text in Timeline UIUtils of the Performance panel">
Touch Cancel
</message>
+ <message name="IDS_DEVTOOLS_af812f467030e02c8bc8a81b4db8e562" desc="Text in Timeline Panel of the Performance panel">
+ Record coverage with performance trace
+ </message>
<message name="IDS_DEVTOOLS_b030f7d30297555390c6d2d23af55fa1" desc="Text in Timeline History Manager of the Performance panel">
moments
</message>
@@ -685,7 +715,7 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
Layout root
</message>
<message name="IDS_DEVTOOLS_b3bfefedfa27aa11e79f637b22b16d09" desc="Text in Timeline Tree View of the Performance panel">
- [V8 Runtime]
+ [<ph name="LOCKED_1">V8</ph> Runtime]
</message>
<message name="IDS_DEVTOOLS_b49fe3f49a656887d446c2da3851a88a" desc="Text in Timeline UIUtils of the Performance panel">
Network request
@@ -693,6 +723,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_b4c7087912916a68642000d8759baec2" desc="Text in Timeline UIUtils of the Performance panel">
Scroll Begin
</message>
+ <message name="IDS_DEVTOOLS_b4ecf19a9a7427854c0b9bfa03260707" desc="Text in UIDevtools Utils of the Performance panel">
+ View::Layout
+ </message>
<message name="IDS_DEVTOOLS_b53fbbb58656447400f07904e68c0f12" desc="Text in Timeline UIUtils of the Performance panel">
Create WebSocket
</message>
@@ -723,6 +756,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_be85f6b3661854c85ddbde4c1429b2a2" desc="Text in Timeline UIUtils of the Performance panel">
(<ph name="CLIP___">$1s<ex>2</ex></ph>, <ph name="CLIP___">$2s<ex>2</ex></ph>)
</message>
+ <message name="IDS_DEVTOOLS_be87d8c3de2675bbc53f9442af9d8feb" desc="Aria-label for grouping combo box in Timeline Details View">
+ Group by
+ </message>
<message name="IDS_DEVTOOLS_be97c5beb33f5316b2c221bfbb95852b" desc="Text in Timeline UIUtils of the Performance panel">
MIME Type
</message>
@@ -783,6 +819,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_cf56f8ebb3727b1d4d5a17fb18d4df74" desc="Text in Timeline UIUtils of the Performance panel">
Paint Setup
</message>
+ <message name="IDS_DEVTOOLS_cfa720bcf2892b7532563ba7e661fc94" desc="Text in UIDevtools Utils of the Performance panel">
+ View::Paint
+ </message>
<message name="IDS_DEVTOOLS_d0369e883465f2849df8b38966901bbf" desc="Text in Timeline Panel of the Performance panel">
CPU:
</message>
@@ -792,6 +831,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_d0c91aff68287a1a0003af56b91cadde" desc="Range text content in Counters Graph of the Performance panel">
[<ph name="MIN">$1s<ex>2</ex></ph> – <ph name="MAX">$2s<ex>10</ex></ph>]
</message>
+ <message name="IDS_DEVTOOLS_d147f3c372833715f5bcff727b0665aa" desc="Text in UIDevtools Utils of the Performance panel">
+ RasterizerTaskImpl::RunOnWorkerThread
+ </message>
<message name="IDS_DEVTOOLS_d14e91fe7abe33fc8a05c193fc812d68" desc="Text in Timeline UIUtils of the Performance panel">
Mime Type
</message>
@@ -813,6 +855,12 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_d5e3345f0d0b507c8993b1ca0e0ac2c4" desc="Text in Timeline UIUtils of the Performance panel">
First Paint
</message>
+ <message name="IDS_DEVTOOLS_d5f967961bccf06a9eb7989d69d94a15" desc="Text in Timeline UIUtils of the Performance panel">
+ network transfer
+ </message>
+ <message name="IDS_DEVTOOLS_d6ef31f5b235ec815c3b62fc6f236804" desc="Aria-label for the filter bar in Bottom-Up view">
+ Filter bottom-up
+ </message>
<message name="IDS_DEVTOOLS_d84fe3f1d290e4855cc0487b5ea18a4a" desc="Text in Timeline UIUtils of the Performance panel">
Pinch Begin
</message>
@@ -825,6 +873,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_d97477d6d8a838ead9348185bb5b6742" desc="Text in Timeline Flame Chart Data Provider of the Performance panel">
Thread
</message>
+ <message name="IDS_DEVTOOLS_d97db6efa26ba3b28be1f0d597f1d759" desc="Text in Timeline UIUtils of the Performance panel">
+ load from cache
+ </message>
<message name="IDS_DEVTOOLS_da3c710f68f0c891ecad19dcbf2ab349" desc="Text in Timeline UIUtils of the Performance panel">
Console Time
</message>
@@ -840,9 +891,6 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_dc16531c312e4d4c024ffd577d123887" desc="Text in Counters Graph of the Performance panel">
Listeners
</message>
- <message name="IDS_DEVTOOLS_dc63e2b8b0f6f66d3dd2dc5d49483eec" desc="Text in Events Timeline Tree View of the Performance panel">
- Show all records
- </message>
<message name="IDS_DEVTOOLS_dd694dc279a5fbefed6a8323c15f4e67" desc="Text in Timeline UIUtils of the Performance panel">
Cancel Idle Callback
</message>
@@ -864,6 +912,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_dfe67b764ba5e3f6b674f049db64e165" desc="Call site stack label in Timeline UIUtils of the Performance panel">
First Layout Invalidation
</message>
+ <message name="IDS_DEVTOOLS_e0421c199e321b5a5c4379892d6e16e9" desc="Text in UIDevtools Utils of the Performance panel">
+ RasterTask
+ </message>
<message name="IDS_DEVTOOLS_e0c70bcb54d7f58615eb895c232049ce" desc="Text in Timeline UIUtils of the Performance panel">
Composite Layers
</message>
@@ -930,6 +981,9 @@ Then, zoom and pan the timeline with the mousewheel or <ph name="NAVIGATENODE">$
<message name="IDS_DEVTOOLS_f5baffc95ebfe1ede488388589db922b" desc="Title in Timeline UIUtils of the Performance panel">
Other Invalidations
</message>
+ <message name="IDS_DEVTOOLS_f8dd1d7ea0aea500de367999ebba5c47" desc="Text in UIDevtools Utils of the Performance panel">
+ Layer::PaintContentsToDisplayList
+ </message>
<message name="IDS_DEVTOOLS_fa7c73b6eb5f3c3b77e47d8a4557af3e" desc="Title of an action in the timeline tool to load from file">
Load profile…
</message>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineFrameModel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineFrameModel.js
index 5ccc2b0456a..6f245b45c25 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineFrameModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineFrameModel.js
@@ -46,8 +46,9 @@ TimelineModel.TimelineFrameModel = class {
* @return {!Array<!TimelineModel.TimelineFrame>}
*/
frames(startTime, endTime) {
- if (!startTime && !endTime)
+ if (!startTime && !endTime) {
return this._frames;
+ }
const firstFrame = this._frames.lowerBound(startTime || 0, (time, frame) => time - frame.endTime);
const lastFrame = this._frames.lowerBound(endTime || Infinity, (time, frame) => time - frame.startTime);
return this._frames.slice(firstFrame, lastFrame);
@@ -59,12 +60,14 @@ TimelineModel.TimelineFrameModel = class {
*/
hasRasterTile(rasterTask) {
const data = rasterTask.args['tileData'];
- if (!data)
+ if (!data) {
return false;
+ }
const frameId = data['sourceFrameNumber'];
const frame = frameId && this._frameById[frameId];
- if (!frame || !frame.layerTree)
+ if (!frame || !frame.layerTree) {
return false;
+ }
return true;
}
@@ -73,14 +76,16 @@ TimelineModel.TimelineFrameModel = class {
* @return Promise<?{rect: !Protocol.DOM.Rect, snapshot: !SDK.PaintProfilerSnapshot}>}
*/
rasterTilePromise(rasterTask) {
- if (!this._target)
+ if (!this._target) {
return Promise.resolve(null);
+ }
const data = rasterTask.args['tileData'];
const frameId = data['sourceFrameNumber'];
const tileId = data['tileId'] && data['tileId']['id_ref'];
const frame = frameId && this._frameById[frameId];
- if (!frame || !frame.layerTree || !tileId)
+ if (!frame || !frame.layerTree || !tileId) {
return Promise.resolve(null);
+ }
return frame.layerTree.layerTreePromise().then(layerTree => layerTree && layerTree.pictureForRasterTile(tileId));
}
@@ -107,8 +112,9 @@ TimelineModel.TimelineFrameModel = class {
* @param {number} startTime
*/
handleBeginFrame(startTime) {
- if (!this._lastFrame)
+ if (!this._lastFrame) {
this._startFrame(startTime);
+ }
this._lastBeginFrame = startTime;
}
@@ -130,8 +136,9 @@ TimelineModel.TimelineFrameModel = class {
if (idleTimeEnd > this._lastFrame.startTime) {
this._lastFrame.idle = true;
this._startFrame(idleTimeEnd);
- if (this._framePendingActivation)
+ if (this._framePendingActivation) {
this._commitPendingFrame();
+ }
this._lastBeginFrame = null;
}
this._lastNeedsBeginFrame = null;
@@ -142,21 +149,25 @@ TimelineModel.TimelineFrameModel = class {
}
handleActivateLayerTree() {
- if (!this._lastFrame)
+ if (!this._lastFrame) {
return;
- if (this._framePendingActivation && !this._lastNeedsBeginFrame)
+ }
+ if (this._framePendingActivation && !this._lastNeedsBeginFrame) {
this._commitPendingFrame();
+ }
}
handleRequestMainThreadFrame() {
- if (!this._lastFrame)
+ if (!this._lastFrame) {
return;
+ }
this._mainFrameRequested = true;
}
handleCompositeLayers() {
- if (!this._framePendingCommit)
+ if (!this._framePendingCommit) {
return;
+ }
this._framePendingActivation = this._framePendingCommit;
this._framePendingCommit = null;
this._mainFrameRequested = false;
@@ -175,16 +186,18 @@ TimelineModel.TimelineFrameModel = class {
* @param {boolean} needsBeginFrame
*/
handleNeedFrameChanged(startTime, needsBeginFrame) {
- if (needsBeginFrame)
+ if (needsBeginFrame) {
this._lastNeedsBeginFrame = startTime;
+ }
}
/**
* @param {number} startTime
*/
_startFrame(startTime) {
- if (this._lastFrame)
+ if (this._lastFrame) {
this._flushFrame(this._lastFrame, startTime);
+ }
this._lastFrame = new TimelineModel.TimelineFrame(startTime, startTime - this._minimumRecordTime);
}
@@ -195,16 +208,18 @@ TimelineModel.TimelineFrameModel = class {
_flushFrame(frame, endTime) {
frame._setLayerTree(this._lastLayerTree);
frame._setEndTime(endTime);
- if (this._lastLayerTree)
+ if (this._lastLayerTree) {
this._lastLayerTree._setPaints(frame._paints);
+ }
if (this._frames.length &&
(frame.startTime !== this._frames.peekLast().endTime || frame.startTime > frame.endTime)) {
console.assert(
false, `Inconsistent frame time for frame ${this._frames.length} (${frame.startTime} - ${frame.endTime})`);
}
this._frames.push(frame);
- if (typeof frame._mainFrameId === 'number')
+ if (typeof frame._mainFrameId === 'number') {
this._frameById[frame._mainFrameId] = frame;
+ }
}
_commitPendingFrame() {
@@ -224,8 +239,9 @@ TimelineModel.TimelineFrameModel = class {
let j = 0;
this._currentProcessMainThread = threadData.length && threadData[0].thread || null;
for (let i = 0; i < events.length; ++i) {
- while (j + 1 < threadData.length && threadData[j + 1].time <= events[i].startTime)
+ while (j + 1 < threadData.length && threadData[j + 1].time <= events[i].startTime) {
this._currentProcessMainThread = threadData[++j].thread;
+ }
this._addTraceEvent(events[i]);
}
this._currentProcessMainThread = null;
@@ -236,8 +252,9 @@ TimelineModel.TimelineFrameModel = class {
*/
_addTraceEvent(event) {
const eventNames = TimelineModel.TimelineModel.RecordType;
- if (event.startTime && event.startTime < this._minimumRecordTime)
+ if (event.startTime && event.startTime < this._minimumRecordTime) {
this._minimumRecordTime = event.startTime;
+ }
if (event.name === eventNames.SetLayerTreeId) {
this._layerTreeId = event.args['layerTreeId'] || event.args['data']['layerTreeId'];
@@ -248,10 +265,11 @@ TimelineModel.TimelineFrameModel = class {
this.handleLayerTreeSnapshot(new TimelineModel.TracingFrameLayerTree(this._target, snapshot));
} else {
this._processCompositorEvents(event);
- if (event.thread === this._currentProcessMainThread)
+ if (event.thread === this._currentProcessMainThread) {
this._addMainThreadTraceEvent(event);
- else if (this._lastFrame && event.selfTime && !SDK.TracingModel.isTopLevelEvent(event))
+ } else if (this._lastFrame && event.selfTime && !SDK.TracingModel.isTopLevelEvent(event)) {
this._lastFrame._addTimeForCategory(this._categoryMapper(event), event.selfTime);
+ }
}
}
@@ -261,20 +279,22 @@ TimelineModel.TimelineFrameModel = class {
_processCompositorEvents(event) {
const eventNames = TimelineModel.TimelineModel.RecordType;
- if (event.args['layerTreeId'] !== this._layerTreeId)
+ if (event.args['layerTreeId'] !== this._layerTreeId) {
return;
+ }
const timestamp = event.startTime;
- if (event.name === eventNames.BeginFrame)
+ if (event.name === eventNames.BeginFrame) {
this.handleBeginFrame(timestamp);
- else if (event.name === eventNames.DrawFrame)
+ } else if (event.name === eventNames.DrawFrame) {
this.handleDrawFrame(timestamp);
- else if (event.name === eventNames.ActivateLayerTree)
+ } else if (event.name === eventNames.ActivateLayerTree) {
this.handleActivateLayerTree();
- else if (event.name === eventNames.RequestMainThreadFrame)
+ } else if (event.name === eventNames.RequestMainThreadFrame) {
this.handleRequestMainThreadFrame();
- else if (event.name === eventNames.NeedsBeginFrameChanged)
+ } else if (event.name === eventNames.NeedsBeginFrameChanged) {
this.handleNeedFrameChanged(timestamp, event.args['data'] && event.args['data']['needsBeginFrame']);
+ }
}
/**
@@ -297,13 +317,16 @@ TimelineModel.TimelineFrameModel = class {
}
this._addTimeForCategory(this._framePendingCommit.timeByCategory, event);
- if (event.name === eventNames.BeginMainThreadFrame && event.args['data'] && event.args['data']['frameId'])
+ if (event.name === eventNames.BeginMainThreadFrame && event.args['data'] && event.args['data']['frameId']) {
this._framePendingCommit.mainFrameId = event.args['data']['frameId'];
+ }
if (event.name === eventNames.Paint && event.args['data']['layerId'] &&
- TimelineModel.TimelineData.forEvent(event).picture && this._target)
+ TimelineModel.TimelineData.forEvent(event).picture && this._target) {
this._framePendingCommit.paints.push(new TimelineModel.LayerPaintEvent(event, this._target));
- if (event.name === eventNames.CompositeLayers && event.args['layerTreeId'] === this._layerTreeId)
+ }
+ if (event.name === eventNames.CompositeLayers && event.args['layerTreeId'] === this._layerTreeId) {
this.handleCompositeLayers();
+ }
}
/**
@@ -311,8 +334,9 @@ TimelineModel.TimelineFrameModel = class {
* @param {!SDK.TracingModel.Event} event
*/
_addTimeForCategory(timeByCategory, event) {
- if (!event.selfTime)
+ if (!event.selfTime) {
return;
+ }
const categoryName = this._categoryMapper(event);
timeByCategory[categoryName] = (timeByCategory[categoryName] || 0) + event.selfTime;
}
@@ -344,8 +368,9 @@ TimelineModel.TracingFrameLayerTree = class {
*/
async layerTreePromise() {
const result = await this._snapshot.objectPromise();
- if (!result)
+ if (!result) {
return null;
+ }
const viewport = result['device_viewport_size'];
const tiles = result['active_tiles'];
const rootLayer = result['active_tree']['root_layer'];
@@ -423,8 +448,9 @@ TimelineModel.TimelineFrame = class {
* @param {!Object} timeByCategory
*/
_addTimeForCategories(timeByCategory) {
- for (const category in timeByCategory)
+ for (const category in timeByCategory) {
this._addTimeForCategory(category, timeByCategory[category]);
+ }
}
/**
@@ -470,8 +496,9 @@ TimelineModel.LayerPaintEvent = class {
picturePromise() {
const picture = TimelineModel.TimelineData.forEvent(this._event).picture;
return picture.objectPromise().then(result => {
- if (!result)
+ if (!result) {
return null;
+ }
const rect = result['params'] && result['params']['layer_rect'];
const picture = result['skp64'];
return rect && picture ? {rect: rect, serializedPicture: picture} : null;
@@ -484,8 +511,9 @@ TimelineModel.LayerPaintEvent = class {
snapshotPromise() {
const paintProfilerModel = this._target && this._target.model(SDK.PaintProfilerModel);
return this.picturePromise().then(picture => {
- if (!picture || !paintProfilerModel)
+ if (!picture || !paintProfilerModel) {
return null;
+ }
return paintProfilerModel.loadSnapshot(picture.serializedPicture)
.then(snapshot => snapshot ? {rect: picture.rect, snapshot: snapshot} : null);
});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineIRModel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineIRModel.js
index 8abb0ae5f18..7f6871e03f6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineIRModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineIRModel.js
@@ -23,11 +23,13 @@ TimelineModel.TimelineIRModel = class {
*/
populate(inputLatencies, animations) {
this.reset();
- if (!inputLatencies)
+ if (!inputLatencies) {
return;
+ }
this._processInputLatencies(inputLatencies);
- if (animations)
+ if (animations) {
this._processAnimations(animations);
+ }
const range = new Common.SegmentedRange();
range.appendRange(this._drags); // Drags take lower precedence than animation, as we can't detect them reliably.
range.appendRange(this._cssAnimations);
@@ -54,8 +56,9 @@ TimelineModel.TimelineIRModel = class {
for (let i = 0; i < events.length; ++i) {
const event = events[i];
- if (i > 0 && events[i].startTime < events[i - 1].startTime)
+ if (i > 0 && events[i].startTime < events[i - 1].startTime) {
console.assert(false, 'Unordered input events');
+ }
const type = this._inputEventType(event.name);
switch (type) {
case eventTypes.ScrollBegin:
@@ -64,10 +67,11 @@ TimelineModel.TimelineIRModel = class {
break;
case eventTypes.ScrollEnd:
- if (scrollStart)
+ if (scrollStart) {
this._scrolls.append(this._segmentForEventRange(scrollStart, event, phases.Scroll));
- else
+ } else {
this._scrolls.append(this._segmentForEvent(event, phases.Scroll));
+ }
scrollStart = null;
break;
@@ -87,8 +91,9 @@ TimelineModel.TimelineIRModel = class {
case eventTypes.FlingCancel:
// FIXME: also process renderer fling events.
- if (!flingStart)
+ if (!flingStart) {
break;
+ }
this._scrolls.append(this._segmentForEventRange(flingStart, event, phases.Fling));
flingStart = null;
break;
@@ -160,10 +165,11 @@ TimelineModel.TimelineIRModel = class {
case eventTypes.MouseWheel:
// Do not consider first MouseWheel as trace viewer's implementation does -- in case of MouseWheel it's not really special.
- if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event))
+ if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event)) {
this._scrolls.append(this._segmentForEventRange(mouseWheel, event, phases.Scroll));
- else
+ } else {
this._scrolls.append(this._segmentForEvent(event, phases.Scroll));
+ }
mouseWheel = event;
break;
}
@@ -184,8 +190,9 @@ TimelineModel.TimelineIRModel = class {
* @param {!Array<!SDK.TracingModel.AsyncEvent>} events
*/
_processAnimations(events) {
- for (let i = 0; i < events.length; ++i)
+ for (let i = 0; i < events.length; ++i) {
this._cssAnimations.append(this._segmentForEvent(events[i], TimelineModel.TimelineIRModel.Phases.Animation));
+ }
}
/**
@@ -251,8 +258,9 @@ TimelineModel.TimelineIRModel = class {
_inputEventType(eventName) {
const prefix = 'InputLatency::';
if (!eventName.startsWith(prefix)) {
- if (eventName === TimelineModel.TimelineIRModel.InputEvents.ImplSideFling)
+ if (eventName === TimelineModel.TimelineIRModel.InputEvents.ImplSideFling) {
return /** @type {!TimelineModel.TimelineIRModel.InputEvents} */ (eventName);
+ }
console.error('Unrecognized input latency event: ' + eventName);
return null;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineJSProfile.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineJSProfile.js
index df66bb983d8..0d453391f54 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineJSProfile.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineJSProfile.js
@@ -24,14 +24,16 @@ TimelineModel.TimelineJSProfileProcessor = class {
console.error(`Node with unknown id ${samples[i]} at index ${i}`);
continue;
}
- if (node === gcNode || node === idleNode)
+ if (node === gcNode || node === idleNode) {
continue;
+ }
let callFrames = nodeToStackMap.get(node);
if (!callFrames) {
callFrames = /** @type {!Array<!Protocol.Runtime.CallFrame>} */ (new Array(node.depth + 1));
nodeToStackMap.set(node, callFrames);
- for (let j = 0; node.parent; node = node.parent)
+ for (let j = 0; node.parent; node = node.parent) {
callFrames[j++] = /** @type {!Protocol.Runtime.CallFrame} */ (node);
+ }
}
const jsSampleEvent = new SDK.TracingModel.Event(
SDK.TracingModel.DevToolsTimelineEventCategory, TimelineModel.TimelineModel.RecordType.JSSample,
@@ -79,8 +81,8 @@ TimelineModel.TimelineJSProfileProcessor = class {
const jsFramesStack = [];
const lockedJsStackDepth = [];
let ordinal = 0;
- const showAllEvents = Runtime.experiments.isEnabled('timelineShowAllEvents');
- const showRuntimeCallStats = Runtime.experiments.isEnabled('timelineV8RuntimeCallStats');
+ const showAllEvents = Root.Runtime.experiments.isEnabled('timelineShowAllEvents');
+ const showRuntimeCallStats = Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats');
const showNativeFunctions = Common.moduleSetting('showNativeFunctionsInJSProfile').get();
/**
@@ -99,8 +101,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
*/
function onInstantEvent(e, parent) {
e.ordinal = ++ordinal;
- if (parent && isJSInvocationEvent(parent))
+ if (parent && isJSInvocationEvent(parent)) {
extractStackTrace(e);
+ }
}
/**
@@ -126,8 +129,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
console.error(`Trying to truncate higher than the current stack size at ${time}`);
depth = jsFramesStack.length;
}
- for (let k = 0; k < jsFramesStack.length; ++k)
+ for (let k = 0; k < jsFramesStack.length; ++k) {
jsFramesStack[k].setEndTime(time);
+ }
jsFramesStack.length = depth;
}
@@ -143,23 +147,27 @@ TimelineModel.TimelineJSProfileProcessor = class {
* @param {!Array<!Protocol.Runtime.CallFrame>} stack
*/
function filterStackFrames(stack) {
- if (showAllEvents)
+ if (showAllEvents) {
return;
+ }
let previousNativeFrameName = null;
let j = 0;
for (let i = 0; i < stack.length; ++i) {
const frame = stack[i];
const url = frame.url;
const isNativeFrame = url && url.startsWith('native ');
- if (!showNativeFunctions && isNativeFrame)
+ if (!showNativeFunctions && isNativeFrame) {
continue;
+ }
const isNativeRuntimeFrame = TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame);
- if (isNativeRuntimeFrame && !showNativeName(frame.functionName))
+ if (isNativeRuntimeFrame && !showNativeName(frame.functionName)) {
continue;
+ }
const nativeFrameName =
isNativeRuntimeFrame ? TimelineModel.TimelineJSProfileProcessor.nativeGroup(frame.functionName) : null;
- if (previousNativeFrameName && previousNativeFrameName === nativeFrameName)
+ if (previousNativeFrameName && previousNativeFrameName === nativeFrameName) {
continue;
+ }
previousNativeFrameName = nativeFrameName;
stack[j++] = frame;
}
@@ -181,8 +189,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
for (i = lockedJsStackDepth.peekLast() || 0; i < minFrames; ++i) {
const newFrame = callFrames[i];
const oldFrame = jsFramesStack[i].args['data'];
- if (!equalFrames(newFrame, oldFrame))
+ if (!equalFrames(newFrame, oldFrame)) {
break;
+ }
jsFramesStack[i].setEndTime(Math.max(jsFramesStack[i].endTime, endTime));
}
truncateJSStack(i, e.startTime);
@@ -218,10 +227,12 @@ TimelineModel.TimelineJSProfileProcessor = class {
* @return {?TimelineModel.TimelineJSProfileProcessor.NativeGroups}
*/
static nativeGroup(nativeName) {
- if (nativeName.startsWith('Parse'))
+ if (nativeName.startsWith('Parse')) {
return TimelineModel.TimelineJSProfileProcessor.NativeGroups.Parse;
- if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile'))
+ }
+ if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile')) {
return TimelineModel.TimelineJSProfileProcessor.NativeGroups.Compile;
+ }
return null;
}
@@ -234,17 +245,21 @@ TimelineModel.TimelineJSProfileProcessor = class {
*/
static buildTraceProfileFromCpuProfile(profile, tid, injectPageEvent, name) {
const events = [];
- if (injectPageEvent)
+ if (injectPageEvent) {
appendEvent('TracingStartedInPage', {data: {'sessionId': '1'}}, 0, 0, 'M');
- if (!name)
+ }
+ if (!name) {
name = ls`Thread ${tid}`;
+ }
appendEvent(SDK.TracingModel.MetadataEvent.ThreadName, {name}, 0, 0, 'M', '__metadata');
- if (!profile)
+ if (!profile) {
return events;
+ }
const idToNode = new Map();
const nodes = profile['nodes'];
- for (let i = 0; i < nodes.length; ++i)
+ for (let i = 0; i < nodes.length; ++i) {
idToNode.set(nodes[i].id, nodes[i]);
+ }
let programEvent = null;
let functionEvent = null;
let nextTime = profile.startTime;
@@ -260,8 +275,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
closeEvents();
continue;
}
- if (!programEvent)
+ if (!programEvent) {
programEvent = appendEvent('MessageLoop::RunTask', {}, currentTime, 0, 'X', 'toplevel');
+ }
if (name === '(program)') {
if (functionEvent) {
functionEvent.dur = currentTime - functionEvent.ts;
@@ -269,8 +285,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
}
} else {
// A JS function.
- if (!functionEvent)
+ if (!functionEvent) {
functionEvent = appendEvent('FunctionCall', {data: {'sessionId': '1'}}, currentTime);
+ }
}
}
closeEvents();
@@ -278,10 +295,12 @@ TimelineModel.TimelineJSProfileProcessor = class {
return events;
function closeEvents() {
- if (programEvent)
+ if (programEvent) {
programEvent.dur = currentTime - programEvent.ts;
- if (functionEvent)
+ }
+ if (functionEvent) {
functionEvent.dur = currentTime - functionEvent.ts;
+ }
programEvent = null;
functionEvent = null;
}
@@ -298,8 +317,9 @@ TimelineModel.TimelineJSProfileProcessor = class {
function appendEvent(name, args, ts, dur, ph, cat) {
const event = /** @type {!SDK.TracingManager.EventPayload} */ (
{cat: cat || 'disabled-by-default-devtools.timeline', name, ph: ph || 'X', pid: 1, tid, ts, args});
- if (dur)
+ if (dur) {
event.dur = dur;
+ }
events.push(event);
return event;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
index 1916764f0ad..3c51c670720 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -52,16 +52,21 @@ TimelineModel.TimelineModel = class {
const startEvent = TimelineModel.TimelineModel._topLevelEventEndingAfter(events, startTime);
for (let i = startEvent; i < events.length; ++i) {
const e = events[i];
- if ((e.endTime || e.startTime) < startTime)
+ if ((e.endTime || e.startTime) < startTime) {
continue;
- if (e.startTime >= endTime)
+ }
+ if (e.startTime >= endTime) {
break;
- if (SDK.TracingModel.isAsyncPhase(e.phase) || SDK.TracingModel.isFlowPhase(e.phase))
+ }
+ if (SDK.TracingModel.isAsyncPhase(e.phase) || SDK.TracingModel.isFlowPhase(e.phase)) {
continue;
- while (stack.length && stack.peekLast().endTime <= e.startTime)
+ }
+ while (stack.length && stack.peekLast().endTime <= e.startTime) {
onEndEvent(stack.pop());
- if (filter && !filter(e))
+ }
+ if (filter && !filter(e)) {
continue;
+ }
if (e.duration) {
onStartEvent(e);
stack.push(e);
@@ -69,8 +74,9 @@ TimelineModel.TimelineModel = class {
onInstantEvent && onInstantEvent(e, stack.peekLast() || null);
}
}
- while (stack.length)
+ while (stack.length) {
onEndEvent(stack.pop());
+ }
}
/**
@@ -79,8 +85,9 @@ TimelineModel.TimelineModel = class {
*/
static _topLevelEventEndingAfter(events, time) {
let index = events.upperBound(time, (time, event) => time - event.startTime) - 1;
- while (index > 0 && !SDK.TracingModel.isTopLevelEvent(events[index]))
+ while (index > 0 && !SDK.TracingModel.isTopLevelEvent(events[index])) {
index--;
+ }
return Math.max(index, 0);
}
@@ -134,8 +141,9 @@ TimelineModel.TimelineModel = class {
static globalEventId(event, field) {
const data = event.args['data'] || event.args['beginData'];
const id = data && data[field];
- if (!id)
+ if (!id) {
return '';
+ }
return `${event.thread.process().id()}.${id}`;
}
@@ -185,10 +193,11 @@ TimelineModel.TimelineModel = class {
// TODO(alph): Drop the support at some point.
const metadataEvents = this._processMetadataEvents(tracingModel);
this._isGenericTrace = !metadataEvents;
- if (metadataEvents)
+ if (metadataEvents) {
this._processMetadataAndThreads(tracingModel, metadataEvents);
- else
+ } else {
this._processGenericTrace(tracingModel);
+ }
}
this._inspectedTargetEvents.sort(SDK.TracingModel.Event.compareStartTime);
this._processAsyncBrowserEvents(tracingModel);
@@ -201,8 +210,9 @@ TimelineModel.TimelineModel = class {
*/
_processGenericTrace(tracingModel) {
let browserMainThread = SDK.TracingModel.browserMainThread(tracingModel);
- if (!browserMainThread && tracingModel.sortedProcesses().length)
+ if (!browserMainThread && tracingModel.sortedProcesses().length) {
browserMainThread = tracingModel.sortedProcesses()[0].sortedThreads()[0];
+ }
for (const process of tracingModel.sortedProcesses()) {
for (const thread of process.sortedThreads()) {
this._processThreadEvents(
@@ -221,26 +231,31 @@ TimelineModel.TimelineModel = class {
const metaEvent = metadataEvents.page[i];
const process = metaEvent.thread.process();
const endTime = i + 1 < length ? metadataEvents.page[i + 1].startTime : Infinity;
- if (startTime === endTime)
+ if (startTime === endTime) {
continue;
+ }
this._legacyCurrentPage = metaEvent.args['data'] && metaEvent.args['data']['page'];
for (const thread of process.sortedThreads()) {
let workerUrl = null;
if (thread.name() === TimelineModel.TimelineModel.WorkerThreadName ||
thread.name() === TimelineModel.TimelineModel.WorkerThreadNameLegacy) {
const workerMetaEvent = metadataEvents.workers.find(e => {
- if (e.args['data']['workerThreadId'] !== thread.id())
+ if (e.args['data']['workerThreadId'] !== thread.id()) {
return false;
+ }
// This is to support old traces.
- if (e.args['data']['sessionId'] === this._sessionId)
+ if (e.args['data']['sessionId'] === this._sessionId) {
return true;
+ }
return !!this._pageFrames.get(TimelineModel.TimelineModel.eventFrameId(e));
});
- if (!workerMetaEvent)
+ if (!workerMetaEvent) {
continue;
+ }
const workerId = workerMetaEvent.args['data']['workerId'];
- if (workerId)
+ if (workerId) {
this._workerIdByThread.set(thread, workerId);
+ }
workerUrl = workerMetaEvent.args['data']['url'] || '';
}
this._processThreadEvents(
@@ -271,23 +286,27 @@ TimelineModel.TimelineModel = class {
const allMetadataEvents = tracingModel.devToolsMetadataEvents();
for (const process of tracingModel.sortedProcesses()) {
const data = processData.get(process.id());
- if (!data)
+ if (!data) {
continue;
+ }
data.sort((a, b) => a.from - b.from || a.to - b.to);
const ranges = [];
let lastUrl = null;
let lastMainUrl = null;
let hasMain = false;
for (const item of data) {
- if (!ranges.length || item.from > ranges.peekLast().to)
+ if (!ranges.length || item.from > ranges.peekLast().to) {
ranges.push({from: item.from, to: item.to});
- else
+ } else {
ranges.peekLast().to = item.to;
- if (item.main)
+ }
+ if (item.main) {
hasMain = true;
+ }
if (item.url) {
- if (item.main)
+ if (item.main) {
lastMainUrl = item.url;
+ }
lastUrl = item.url;
}
}
@@ -301,16 +320,20 @@ TimelineModel.TimelineModel = class {
thread.name() === TimelineModel.TimelineModel.WorkerThreadName ||
thread.name() === TimelineModel.TimelineModel.WorkerThreadNameLegacy) {
const workerMetaEvent = allMetadataEvents.find(e => {
- if (e.name !== TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingSessionIdForWorker)
+ if (e.name !== TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingSessionIdForWorker) {
return false;
- if (e.thread.process() !== process)
+ }
+ if (e.thread.process() !== process) {
return false;
- if (e.args['data']['workerThreadId'] !== thread.id())
+ }
+ if (e.args['data']['workerThreadId'] !== thread.id()) {
return false;
+ }
return !!this._pageFrames.get(TimelineModel.TimelineModel.eventFrameId(e));
});
- if (!workerMetaEvent)
+ if (!workerMetaEvent) {
continue;
+ }
this._workerIdByThread.set(thread, workerMetaEvent.args['data']['workerId'] || '');
this._processThreadEvents(
tracingModel, ranges, thread, false /* isMainThread */, true /* isWorker */, false /* forMainFrame */,
@@ -336,8 +359,9 @@ TimelineModel.TimelineModel = class {
for (const event of metadataEvents) {
if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage) {
pageDevToolsMetadataEvents.push(event);
- if (event.args['data'] && event.args['data']['persistentIds'])
+ if (event.args['data'] && event.args['data']['persistentIds']) {
this._persistentIds = true;
+ }
const frames = ((event.args['data'] && event.args['data']['frames']) || []);
frames.forEach(payload => this._addPageFrame(event, payload));
this._mainFrame = this.rootFrames()[0];
@@ -348,8 +372,9 @@ TimelineModel.TimelineModel = class {
this._mainFrameNodeId = event.args['frameTreeNodeId'];
}
}
- if (!pageDevToolsMetadataEvents.length)
+ if (!pageDevToolsMetadataEvents.length) {
return null;
+ }
const sessionId =
pageDevToolsMetadataEvents[0].args['sessionId'] || pageDevToolsMetadataEvents[0].args['data']['sessionId'];
@@ -363,11 +388,13 @@ TimelineModel.TimelineModel = class {
function checkSessionId(event) {
let args = event.args;
// FIXME: put sessionId into args["data"] for TracingStartedInPage event.
- if (args['data'])
+ if (args['data']) {
args = args['data'];
+ }
const id = args['sessionId'];
- if (id === sessionId)
+ if (id === sessionId) {
return true;
+ }
mismatchingIds.add(id);
return false;
}
@@ -388,8 +415,9 @@ TimelineModel.TimelineModel = class {
*/
_processSyncBrowserEvents(tracingModel) {
const browserMain = SDK.TracingModel.browserMainThread(tracingModel);
- if (browserMain)
+ if (browserMain) {
browserMain.events().forEach(this._processBrowserEvent, this);
+ }
}
/**
@@ -397,8 +425,9 @@ TimelineModel.TimelineModel = class {
*/
_processAsyncBrowserEvents(tracingModel) {
const browserMain = SDK.TracingModel.browserMainThread(tracingModel);
- if (browserMain)
+ if (browserMain) {
this._processAsyncEvents(browserMain, [{from: 0, to: Infinity}]);
+ }
}
/**
@@ -406,8 +435,9 @@ TimelineModel.TimelineModel = class {
*/
_buildGPUEvents(tracingModel) {
const thread = tracingModel.threadByName('GPU Process', 'CrGpuMain');
- if (!thread)
+ if (!thread) {
return;
+ }
const gpuEventName = TimelineModel.TimelineModel.RecordType.GPUTask;
const track = this._ensureNamedTrack(TimelineModel.TimelineModel.TrackType.GPU);
track.thread = thread;
@@ -451,8 +481,9 @@ TimelineModel.TimelineModel = class {
if (!cpuProfile) {
cpuProfileEvent = events.find(e => e.name === TimelineModel.TimelineModel.RecordType.Profile);
- if (!cpuProfileEvent)
+ if (!cpuProfileEvent) {
return null;
+ }
target = this.targetByEvent(cpuProfileEvent);
const profileGroup = tracingModel.profileGroup(cpuProfileEvent);
if (!profileGroup) {
@@ -469,10 +500,12 @@ TimelineModel.TimelineModel = class {
});
for (const profileEvent of profileGroup.children) {
const eventData = profileEvent.args['data'];
- if ('startTime' in eventData)
+ if ('startTime' in eventData) {
cpuProfile.startTime = eventData['startTime'];
- if ('endTime' in eventData)
+ }
+ if ('endTime' in eventData) {
cpuProfile.endTime = eventData['endTime'];
+ }
const nodesAndSamples = eventData['cpuProfile'] || {};
const samples = nodesAndSamples['samples'] || [];
const lines = eventData['lines'] || Array(samples.length).fill(0);
@@ -485,8 +518,9 @@ TimelineModel.TimelineModel = class {
return null;
}
}
- if (!cpuProfile.endTime)
+ if (!cpuProfile.endTime) {
cpuProfile.endTime = cpuProfile.timeDeltas.reduce((x, y) => x + y, cpuProfile.startTime);
+ }
}
try {
@@ -510,12 +544,14 @@ TimelineModel.TimelineModel = class {
const jsSamples = jsProfileModel ?
TimelineModel.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile(jsProfileModel, thread) :
null;
- if (jsSamples && jsSamples.length)
+ if (jsSamples && jsSamples.length) {
events = events.mergeOrdered(jsSamples, SDK.TracingModel.Event.orderedCompareStartTime);
+ }
if (jsSamples || events.some(e => e.name === TimelineModel.TimelineModel.RecordType.JSSample)) {
const jsFrameEvents = TimelineModel.TimelineJSProfileProcessor.generateJSFrameEvents(events);
- if (jsFrameEvents && jsFrameEvents.length)
+ if (jsFrameEvents && jsFrameEvents.length) {
events = jsFrameEvents.mergeOrdered(events, SDK.TracingModel.Event.orderedCompareStartTime);
+ }
}
return events;
}
@@ -554,26 +590,32 @@ TimelineModel.TimelineModel = class {
let i = events.lowerBound(range.from, (time, event) => time - event.startTime);
for (; i < events.length; i++) {
const event = events[i];
- if (event.startTime >= range.to)
+ if (event.startTime >= range.to) {
break;
- while (eventStack.length && eventStack.peekLast().endTime <= event.startTime)
+ }
+ while (eventStack.length && eventStack.peekLast().endTime <= event.startTime) {
eventStack.pop();
- if (!this._processEvent(event))
+ }
+ if (!this._processEvent(event)) {
continue;
+ }
if (!SDK.TracingModel.isAsyncPhase(event.phase) && event.duration) {
if (eventStack.length) {
const parent = eventStack.peekLast();
parent.selfTime -= event.duration;
- if (parent.selfTime < 0)
+ if (parent.selfTime < 0) {
this._fixNegativeDuration(parent, event);
+ }
}
event.selfTime = event.duration;
- if (!eventStack.length)
+ if (!eventStack.length) {
track.tasks.push(event);
+ }
eventStack.push(event);
}
- if (this.isMarkerEvent(event))
+ if (this.isMarkerEvent(event)) {
this._timeMarkerEvents.push(event);
+ }
track.events.push(event);
this._inspectedTargetEvents.push(event);
@@ -609,8 +651,9 @@ TimelineModel.TimelineModel = class {
* @return {!Array<!SDK.TracingModel.AsyncEvent>}
*/
function group(type) {
- if (!groups.has(type))
+ if (!groups.has(type)) {
groups.set(type, []);
+ }
return groups.get(type);
}
@@ -621,8 +664,9 @@ TimelineModel.TimelineModel = class {
for (; i < asyncEvents.length; ++i) {
const asyncEvent = asyncEvents[i];
- if (asyncEvent.startTime >= range.to)
+ if (asyncEvent.startTime >= range.to) {
break;
+ }
if (asyncEvent.hasCategory(TimelineModel.TimelineModel.Category.Console)) {
group(TimelineModel.TimelineModel.TrackType.Console).push(asyncEvent);
@@ -643,16 +687,19 @@ TimelineModel.TimelineModel = class {
asyncEvent.name === TimelineModel.TimelineModel.RecordType.ImplSideFling) {
const lastStep = asyncEvent.steps.peekLast();
// FIXME: fix event termination on the back-end instead.
- if (lastStep.phase !== SDK.TracingModel.Phase.AsyncEnd)
+ if (lastStep.phase !== SDK.TracingModel.Phase.AsyncEnd) {
continue;
+ }
const data = lastStep.args['data'];
asyncEvent.causedFrame = !!(data && data['INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT']);
if (asyncEvent.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
- if (!this._knownInputEvents.has(lastStep.id))
+ if (!this._knownInputEvents.has(lastStep.id)) {
continue;
+ }
if (asyncEvent.name === TimelineModel.TimelineModel.RecordType.InputLatencyMouseMove &&
- !asyncEvent.causedFrame)
+ !asyncEvent.causedFrame) {
continue;
+ }
const rendererMain = data['INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT'];
if (rendererMain) {
const time = rendererMain['time'] / 1000;
@@ -696,13 +743,15 @@ TimelineModel.TimelineModel = class {
this._currentTaskLayoutAndRecalcEvents = [];
}
- if (this._currentScriptEvent && event.startTime > this._currentScriptEvent.endTime)
+ if (this._currentScriptEvent && event.startTime > this._currentScriptEvent.endTime) {
this._currentScriptEvent = null;
+ }
const eventData = event.args['data'] || event.args['beginData'] || {};
const timelineData = TimelineModel.TimelineData.forEvent(event);
- if (eventData['stackTrace'])
+ if (eventData['stackTrace']) {
timelineData.stackTrace = eventData['stackTrace'];
+ }
if (timelineData.stackTrace && event.name !== recordTypes.JSSample) {
// TraceEvents come with 1-based line & column numbers. The frontend code
// requires 0-based ones. Adjust the values.
@@ -712,13 +761,15 @@ TimelineModel.TimelineModel = class {
}
}
let pageFrameId = TimelineModel.TimelineModel.eventFrameId(event);
- if (!pageFrameId && eventStack.length)
+ if (!pageFrameId && eventStack.length) {
pageFrameId = TimelineModel.TimelineData.forEvent(eventStack.peekLast()).frameId;
+ }
timelineData.frameId = pageFrameId || (this._mainFrame && this._mainFrame.frameId) || '';
this._asyncEventTracker.processEvent(event);
- if (this.isMarkerEvent(event))
+ if (this.isMarkerEvent(event)) {
this._ensureNamedTrack(TimelineModel.TimelineModel.TrackType.Timings);
+ }
switch (event.name) {
case recordTypes.ResourceSendRequest:
@@ -734,11 +785,13 @@ TimelineModel.TimelineModel = class {
case recordTypes.UpdateLayoutTree:
case recordTypes.RecalculateStyles:
this._invalidationTracker.didRecalcStyle(event);
- if (event.args['beginData'])
+ if (event.args['beginData']) {
timelineData.setInitiator(this._lastScheduleStyleRecalculation[event.args['beginData']['frame']]);
+ }
this._lastRecalculateStylesEvent = event;
- if (this._currentScriptEvent)
+ if (this._currentScriptEvent) {
this._currentTaskLayoutAndRecalcEvents.push(event);
+ }
break;
case recordTypes.ScheduleStyleInvalidationTracking:
@@ -754,8 +807,9 @@ TimelineModel.TimelineModel = class {
let layoutInitator = event;
const frameId = eventData['frame'];
if (!this._layoutInvalidate[frameId] && this._lastRecalculateStylesEvent &&
- this._lastRecalculateStylesEvent.endTime > event.startTime)
+ this._lastRecalculateStylesEvent.endTime > event.startTime) {
layoutInitator = TimelineModel.TimelineData.forEvent(this._lastRecalculateStylesEvent).initiator();
+ }
this._layoutInvalidate[frameId] = layoutInitator;
break;
}
@@ -765,53 +819,63 @@ TimelineModel.TimelineModel = class {
const frameId = event.args['beginData']['frame'];
timelineData.setInitiator(this._layoutInvalidate[frameId]);
// In case we have no closing Layout event, endData is not available.
- if (event.args['endData'])
+ if (event.args['endData']) {
timelineData.backendNodeId = event.args['endData']['rootNode'];
+ }
this._layoutInvalidate[frameId] = null;
- if (this._currentScriptEvent)
+ if (this._currentScriptEvent) {
this._currentTaskLayoutAndRecalcEvents.push(event);
+ }
break;
}
case recordTypes.Task:
- if (event.duration > TimelineModel.TimelineModel.Thresholds.LongTask)
+ if (event.duration > TimelineModel.TimelineModel.Thresholds.LongTask) {
timelineData.warning = TimelineModel.TimelineModel.WarningType.LongTask;
+ }
break;
case recordTypes.EventDispatch:
- if (event.duration > TimelineModel.TimelineModel.Thresholds.RecurringHandler)
+ if (event.duration > TimelineModel.TimelineModel.Thresholds.RecurringHandler) {
timelineData.warning = TimelineModel.TimelineModel.WarningType.LongHandler;
+ }
break;
case recordTypes.TimerFire:
case recordTypes.FireAnimationFrame:
- if (event.duration > TimelineModel.TimelineModel.Thresholds.RecurringHandler)
+ if (event.duration > TimelineModel.TimelineModel.Thresholds.RecurringHandler) {
timelineData.warning = TimelineModel.TimelineModel.WarningType.LongRecurringHandler;
+ }
break;
case recordTypes.FunctionCall:
// Compatibility with old format.
- if (typeof eventData['scriptName'] === 'string')
+ if (typeof eventData['scriptName'] === 'string') {
eventData['url'] = eventData['scriptName'];
- if (typeof eventData['scriptLine'] === 'number')
+ }
+ if (typeof eventData['scriptLine'] === 'number') {
eventData['lineNumber'] = eventData['scriptLine'];
+ }
// Fallthrough.
case recordTypes.EvaluateScript:
case recordTypes.CompileScript:
- if (typeof eventData['lineNumber'] === 'number')
+ if (typeof eventData['lineNumber'] === 'number') {
--eventData['lineNumber'];
- if (typeof eventData['columnNumber'] === 'number')
+ }
+ if (typeof eventData['columnNumber'] === 'number') {
--eventData['columnNumber'];
+ }
// Fallthrough intended.
case recordTypes.RunMicrotasks:
// Microtasks technically are not necessarily scripts, but for purpose of
// forced sync style recalc or layout detection they are.
- if (!this._currentScriptEvent)
+ if (!this._currentScriptEvent) {
this._currentScriptEvent = event;
+ }
break;
case recordTypes.SetLayerTreeId:
@@ -824,8 +888,9 @@ TimelineModel.TimelineModel = class {
// We currently only show layer tree for the main frame.
const frameId = TimelineModel.TimelineModel.eventFrameId(event);
const pageFrame = this._pageFrames.get(frameId);
- if (!pageFrame || pageFrame.parent)
+ if (!pageFrame || pageFrame.parent) {
return false;
+ }
this._mainFrameLayerTreeId = eventData['layerTreeId'];
break;
@@ -833,8 +898,9 @@ TimelineModel.TimelineModel = class {
this._invalidationTracker.didPaint(event);
timelineData.backendNodeId = eventData['nodeId'];
// Only keep layer paint events, skip paints for subframes that get painted to the same layer as parent.
- if (!eventData['layerId'])
+ if (!eventData['layerId']) {
break;
+ }
const layerId = eventData['layerId'];
this._lastPaintForLayer[layerId] = event;
break;
@@ -843,8 +909,9 @@ TimelineModel.TimelineModel = class {
case recordTypes.DisplayItemListSnapshot:
case recordTypes.PictureSnapshot: {
const layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLayer);
- if (!layerUpdateEvent || layerUpdateEvent.args['layerTreeId'] !== this._mainFrameLayerTreeId)
+ if (!layerUpdateEvent || layerUpdateEvent.args['layerTreeId'] !== this._mainFrameLayerTreeId) {
break;
+ }
const paintEvent = this._lastPaintForLayer[layerUpdateEvent.args['layerId']];
if (paintEvent) {
TimelineModel.TimelineData.forEvent(paintEvent).picture =
@@ -870,8 +937,9 @@ TimelineModel.TimelineModel = class {
paintImageEvent = decodeLazyPixelRefEvent &&
this._paintImageEventByPixelRefId[decodeLazyPixelRefEvent.args['LazyPixelRef']];
}
- if (!paintImageEvent)
+ if (!paintImageEvent) {
break;
+ }
const paintImageData = TimelineModel.TimelineData.forEvent(paintImageEvent);
timelineData.backendNodeId = paintImageData.backendNodeId;
timelineData.url = paintImageData.url;
@@ -880,8 +948,9 @@ TimelineModel.TimelineModel = class {
case recordTypes.DrawLazyPixelRef: {
const paintImageEvent = this._findAncestorEvent(recordTypes.PaintImage);
- if (!paintImageEvent)
+ if (!paintImageEvent) {
break;
+ }
this._paintImageEventByPixelRefId[event.args['LazyPixelRef']] = paintImageEvent;
const paintImageData = TimelineModel.TimelineData.forEvent(paintImageEvent);
timelineData.backendNodeId = paintImageData.backendNodeId;
@@ -890,8 +959,9 @@ TimelineModel.TimelineModel = class {
}
case recordTypes.FrameStartedLoading:
- if (timelineData.frameId !== event.args['frame'])
+ if (timelineData.frameId !== event.args['frame']) {
return false;
+ }
break;
case recordTypes.MarkLCPCandidate:
@@ -901,14 +971,16 @@ TimelineModel.TimelineModel = class {
case recordTypes.MarkDOMContent:
case recordTypes.MarkLoad: {
const frameId = TimelineModel.TimelineModel.eventFrameId(event);
- if (!this._pageFrames.has(frameId))
+ if (!this._pageFrames.has(frameId)) {
return false;
+ }
break;
}
case recordTypes.CommitLoad: {
- if (this._browserFrameTracking)
+ if (this._browserFrameTracking) {
break;
+ }
const frameId = TimelineModel.TimelineModel.eventFrameId(event);
const isMainFrame = !!eventData['isMainFrame'];
const pageFrame = this._pageFrames.get(frameId);
@@ -918,23 +990,26 @@ TimelineModel.TimelineModel = class {
// We should only have one main frame which has persistent id,
// unless it's an old trace without 'persistentIds' flag.
if (!this._persistentIds) {
- if (eventData['page'] && eventData['page'] !== this._legacyCurrentPage)
+ if (eventData['page'] && eventData['page'] !== this._legacyCurrentPage) {
return false;
+ }
} else if (isMainFrame) {
return false;
} else if (!this._addPageFrame(event, eventData)) {
return false;
}
}
- if (isMainFrame)
+ if (isMainFrame) {
this._mainFrame = this._pageFrames.get(frameId);
+ }
break;
}
case recordTypes.FireIdleCallback:
if (event.duration >
- eventData['allottedMilliseconds'] + TimelineModel.TimelineModel.Thresholds.IdleCallbackAddon)
+ eventData['allottedMilliseconds'] + TimelineModel.TimelineModel.Thresholds.IdleCallbackAddon) {
timelineData.warning = TimelineModel.TimelineModel.WarningType.IdleDeadlineExceeded;
+ }
break;
}
return true;
@@ -946,31 +1021,43 @@ TimelineModel.TimelineModel = class {
_processBrowserEvent(event) {
if (event.name === TimelineModel.TimelineModel.RecordType.LatencyInfoFlow) {
const frameId = event.args['frameTreeNodeId'];
- if (typeof frameId === 'number' && frameId === this._mainFrameNodeId)
+ if (typeof frameId === 'number' && frameId === this._mainFrameNodeId) {
this._knownInputEvents.add(event.bind_id);
+ }
+ return;
+ }
+
+ if (event.name === TimelineModel.TimelineModel.RecordType.ResourceWillSendRequest) {
+ const requestId = event.args['data']['requestId'];
+ if (typeof requestId === 'string') {
+ this._requestsFromBrowser.set(requestId, event);
+ }
return;
}
if (event.hasCategory(SDK.TracingModel.DevToolsMetadataEventCategory) && event.args['data']) {
const data = event.args['data'];
if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingStartedInBrowser) {
- if (!data['persistentIds'])
+ if (!data['persistentIds']) {
return;
+ }
this._browserFrameTracking = true;
this._mainFrameNodeId = data['frameTreeNodeId'];
const frames = data['frames'] || [];
frames.forEach(payload => {
const parent = payload['parent'] && this._pageFrames.get(payload['parent']);
- if (payload['parent'] && !parent)
+ if (payload['parent'] && !parent) {
return;
+ }
let frame = this._pageFrames.get(payload['frame']);
if (!frame) {
frame = new TimelineModel.TimelineModel.PageFrame(payload);
this._pageFrames.set(frame.frameId, frame);
- if (parent)
+ if (parent) {
parent.addChild(frame);
- else
+ } else {
this._mainFrame = frame;
+ }
}
// TODO(dgozman): this should use event.startTime, but due to races between tracing start
// in different processes we cannot do this yet.
@@ -983,8 +1070,9 @@ TimelineModel.TimelineModel = class {
let frame = this._pageFrames.get(data['frame']);
if (!frame) {
const parent = data['parent'] && this._pageFrames.get(data['parent']);
- if (!parent)
+ if (!parent) {
return;
+ }
frame = new TimelineModel.TimelineModel.PageFrame(data);
this._pageFrames.set(frame.frameId, frame);
parent.addChild(frame);
@@ -995,15 +1083,17 @@ TimelineModel.TimelineModel = class {
if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.ProcessReadyInBrowser &&
this._browserFrameTracking) {
const frame = this._pageFrames.get(data['frame']);
- if (frame)
+ if (frame) {
frame.processReady(data['processPseudoId'], data['processId']);
+ }
return;
}
if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.FrameDeletedInBrowser &&
this._browserFrameTracking) {
const frame = this._pageFrames.get(data['frame']);
- if (frame)
+ if (frame) {
frame.deletedTime = event.startTime;
+ }
return;
}
}
@@ -1030,8 +1120,9 @@ TimelineModel.TimelineModel = class {
_findAncestorEvent(name) {
for (let i = this._eventStack.length - 1; i >= 0; --i) {
const event = this._eventStack[i];
- if (event.name === name)
+ if (event.name === name) {
return event;
+ }
}
return null;
}
@@ -1043,13 +1134,15 @@ TimelineModel.TimelineModel = class {
*/
_addPageFrame(event, payload) {
const parent = payload['parent'] && this._pageFrames.get(payload['parent']);
- if (payload['parent'] && !parent)
+ if (payload['parent'] && !parent) {
return false;
+ }
const pageFrame = new TimelineModel.TimelineModel.PageFrame(payload);
this._pageFrames.set(pageFrame.frameId, pageFrame);
pageFrame.update(event.startTime, payload);
- if (parent)
+ if (parent) {
parent.addChild(pageFrame);
+ }
return true;
}
@@ -1074,6 +1167,8 @@ TimelineModel.TimelineModel = class {
/** @type {!Map<string, !TimelineModel.TimelineModel.PageFrame>} */
this._pageFrames = new Map();
this._mainFrame = null;
+ /** @type {!Map<string, !SDK.TracingModel.Event>} */
+ this._requestsFromBrowser = new Map();
this._minimumRecordTime = 0;
this._maximumRecordTime = 0;
@@ -1161,8 +1256,9 @@ TimelineModel.TimelineModel = class {
* @return {!Array<!TimelineModel.TimelineModel.NetworkRequest>}
*/
networkRequests() {
- if (this.isGenericTrace())
+ if (this.isGenericTrace()) {
return [];
+ }
/** @type {!Map<string,!TimelineModel.TimelineModel.NetworkRequest>} */
const requests = new Map();
/** @type {!Array<!TimelineModel.TimelineModel.NetworkRequest>} */
@@ -1171,25 +1267,33 @@ TimelineModel.TimelineModel = class {
const zeroStartRequestsList = [];
const types = TimelineModel.TimelineModel.RecordType;
const resourceTypes = new Set([
- types.ResourceSendRequest, types.ResourceReceiveResponse, types.ResourceReceivedData, types.ResourceFinish,
- types.ResourceMarkAsCached
+ types.ResourceWillSendRequest, types.ResourceSendRequest, types.ResourceReceiveResponse,
+ types.ResourceReceivedData, types.ResourceFinish, types.ResourceMarkAsCached
]);
const events = this.inspectedTargetEvents();
for (let i = 0; i < events.length; ++i) {
const e = events[i];
- if (!resourceTypes.has(e.name))
+ if (!resourceTypes.has(e.name)) {
continue;
+ }
const id = TimelineModel.TimelineModel.globalEventId(e, 'requestId');
+ if (e.name === types.ResourceSendRequest && this._requestsFromBrowser.has(e.args.data.requestId)) {
+ addRequest(this._requestsFromBrowser.get(e.args.data.requestId), id);
+ }
+ addRequest(e, id);
+ }
+ function addRequest(e, id) {
let request = requests.get(id);
if (request) {
request.addEvent(e);
} else {
request = new TimelineModel.TimelineModel.NetworkRequest(e);
requests.set(id, request);
- if (request.startTime)
+ if (request.startTime) {
requestsList.push(request);
- else
+ } else {
zeroStartRequestsList.push(request);
+ }
}
}
return zeroStartRequestsList.concat(requestsList);
@@ -1267,6 +1371,7 @@ TimelineModel.TimelineModel.RecordType = {
ConsoleTime: 'ConsoleTime',
UserTiming: 'UserTiming',
+ ResourceWillSendRequest: 'ResourceWillSendRequest',
ResourceSendRequest: 'ResourceSendRequest',
ResourceReceiveResponse: 'ResourceReceiveResponse',
ResourceReceivedData: 'ResourceReceivedData',
@@ -1286,7 +1391,7 @@ TimelineModel.TimelineModel.RecordType = {
V8Sample: 'V8Sample',
JitCodeAdded: 'JitCodeAdded',
JitCodeMoved: 'JitCodeMoved',
- ParseScriptOnBackground: 'v8.parseOnBackground',
+ StreamingCompileScript: 'v8.parseOnBackground',
V8Execute: 'V8.Execute',
UpdateCounters: 'UpdateCounters',
@@ -1409,19 +1514,22 @@ TimelineModel.TimelineModel.Track = class {
* @return {!Array<!SDK.TracingModel.Event>}
*/
syncEvents() {
- if (this.events.length)
+ if (this.events.length) {
return this.events;
+ }
- if (this._syncEvents)
+ if (this._syncEvents) {
return this._syncEvents;
+ }
const stack = [];
this._syncEvents = [];
for (const event of this.asyncEvents) {
const startTime = event.startTime;
const endTime = event.endTime;
- while (stack.length && startTime >= stack.peekLast().endTime)
+ while (stack.length && startTime >= stack.peekLast().endTime) {
stack.pop();
+ }
if (stack.length && endTime > stack.peekLast().endTime) {
this._syncEvents = [];
break;
@@ -1522,7 +1630,10 @@ TimelineModel.TimelineModel.NetworkRequest = class {
* @param {!SDK.TracingModel.Event} event
*/
constructor(event) {
- this.startTime = event.name === TimelineModel.TimelineModel.RecordType.ResourceSendRequest ? event.startTime : 0;
+ const recordType = TimelineModel.TimelineModel.RecordType;
+ const isInitial =
+ event.name === recordType.ResourceSendRequest || event.name === recordType.ResourceWillSendRequest;
+ this.startTime = isInitial ? event.startTime : 0;
this.endTime = Infinity;
this.encodedDataLength = 0;
this.decodedBodyLength = 0;
@@ -1554,17 +1665,22 @@ TimelineModel.TimelineModel.NetworkRequest = class {
// This Math.min is likely because of BUG(chromium:865066).
this.startTime = Math.min(this.startTime, event.startTime);
const eventData = event.args['data'];
- if (eventData['mimeType'])
+ if (eventData['mimeType']) {
this.mimeType = eventData['mimeType'];
- if ('priority' in eventData)
+ }
+ if ('priority' in eventData) {
this.priority = eventData['priority'];
- if (event.name === recordType.ResourceFinish)
+ }
+ if (event.name === recordType.ResourceFinish) {
this.endTime = event.startTime;
- if (eventData['finishTime'])
+ }
+ if (eventData['finishTime']) {
this.finishTime = eventData['finishTime'] * 1000;
+ }
if (!this.responseTime &&
- (event.name === recordType.ResourceReceiveResponse || event.name === recordType.ResourceReceivedData))
+ (event.name === recordType.ResourceReceiveResponse || event.name === recordType.ResourceReceivedData)) {
this.responseTime = event.startTime;
+ }
const encodedDataLength = eventData['encodedDataLength'] || 0;
if (event.name === recordType.ResourceMarkAsCached) {
// This is a reliable signal for memory caching.
@@ -1575,14 +1691,17 @@ TimelineModel.TimelineModel.NetworkRequest = class {
// See BUG(chromium:998397): back-end over-approximates caching.
this._maybeDiskCached = true;
}
- if (eventData['fromServiceWorker'])
+ if (eventData['fromServiceWorker']) {
this.fromServiceWorker = true;
- if (eventData['hasCachedResource'])
+ }
+ if (eventData['hasCachedResource']) {
this.hasCachedResource = true;
+ }
this.encodedDataLength = encodedDataLength;
}
- if (event.name === recordType.ResourceReceivedData)
+ if (event.name === recordType.ResourceReceivedData) {
this.encodedDataLength += encodedDataLength;
+ }
if (event.name === recordType.ResourceFinish && encodedDataLength) {
this.encodedDataLength = encodedDataLength;
// If a ResourceFinish event with an encoded data length is received,
@@ -1591,16 +1710,21 @@ TimelineModel.TimelineModel.NetworkRequest = class {
this._transferSize = encodedDataLength;
}
const decodedBodyLength = eventData['decodedBodyLength'];
- if (event.name === recordType.ResourceFinish && decodedBodyLength)
+ if (event.name === recordType.ResourceFinish && decodedBodyLength) {
this.decodedBodyLength = decodedBodyLength;
- if (!this.url)
+ }
+ if (!this.url) {
this.url = eventData['url'];
- if (!this.requestMethod)
+ }
+ if (!this.requestMethod) {
this.requestMethod = eventData['requestMethod'];
- if (!this.timing)
+ }
+ if (!this.timing) {
this.timing = eventData['timing'];
- if (eventData['fromServiceWorker'])
+ }
+ if (eventData['fromServiceWorker']) {
this.fromServiceWorker = true;
+ }
}
/**
@@ -1712,8 +1836,9 @@ TimelineModel.InvalidationTrackingEvent = class {
// FIXME: Move this to TimelineUIUtils.js.
if (!this.cause.reason && this.cause.stackTrace &&
- this.type === TimelineModel.TimelineModel.RecordType.LayoutInvalidationTracking)
+ this.type === TimelineModel.TimelineModel.RecordType.LayoutInvalidationTracking) {
this.cause.reason = 'Layout forced';
+ }
}
};
@@ -1756,8 +1881,9 @@ TimelineModel.InvalidationTracker = class {
// will be handled by StyleInvalidatorInvalidationTracking.
// FIXME: Investigate if we can remove StyleInvalidator invalidations entirely.
if (invalidation.type === recordTypes.StyleRecalcInvalidationTracking &&
- invalidation.cause.reason === 'StyleInvalidator')
+ invalidation.cause.reason === 'StyleInvalidator') {
return;
+ }
// Style invalidation events can occur before and during recalc style. didRecalcStyle
// handles style invalidations that occur before the recalc style event but we need to
@@ -1770,20 +1896,23 @@ TimelineModel.InvalidationTracker = class {
const duringRecalcStyle = invalidation.startTime && this._lastRecalcStyle &&
invalidation.startTime >= this._lastRecalcStyle.startTime &&
invalidation.startTime <= this._lastRecalcStyle.endTime;
- if (duringRecalcStyle)
+ if (duringRecalcStyle) {
this._associateWithLastRecalcStyleEvent(invalidation);
+ }
}
// Record the invalidation so later events can look it up.
- if (this._invalidations[invalidation.type])
+ if (this._invalidations[invalidation.type]) {
this._invalidations[invalidation.type].push(invalidation);
- else
+ } else {
this._invalidations[invalidation.type] = [invalidation];
+ }
if (invalidation.nodeId) {
- if (this._invalidationsByNodeId[invalidation.nodeId])
+ if (this._invalidationsByNodeId[invalidation.nodeId]) {
this._invalidationsByNodeId[invalidation.nodeId].push(invalidation);
- else
+ } else {
this._invalidationsByNodeId[invalidation.nodeId] = [invalidation];
+ }
}
}
@@ -1797,16 +1926,18 @@ TimelineModel.InvalidationTracker = class {
TimelineModel.TimelineModel.RecordType.StyleInvalidatorInvalidationTracking,
TimelineModel.TimelineModel.RecordType.StyleRecalcInvalidationTracking
];
- for (const invalidation of this._invalidationsOfTypes(types))
+ for (const invalidation of this._invalidationsOfTypes(types)) {
this._associateWithLastRecalcStyleEvent(invalidation);
+ }
}
/**
* @param {!TimelineModel.InvalidationTrackingEvent} invalidation
*/
_associateWithLastRecalcStyleEvent(invalidation) {
- if (invalidation.linkedRecalcStyleEvent)
+ if (invalidation.linkedRecalcStyleEvent) {
return;
+ }
const recordTypes = TimelineModel.TimelineModel.RecordType;
const recalcStyleFrameId = this._lastRecalcStyle.args['beginData']['frame'];
@@ -1847,8 +1978,9 @@ TimelineModel.InvalidationTracker = class {
for (let j = 0; j < nodeInvalidations.length; j++) {
const invalidation = nodeInvalidations[j];
if (invalidation.frame !== frameId || invalidation.invalidationSet !== setId ||
- invalidation.type !== TimelineModel.TimelineModel.RecordType.ScheduleStyleInvalidationTracking)
+ invalidation.type !== TimelineModel.TimelineModel.RecordType.ScheduleStyleInvalidationTracking) {
continue;
+ }
lastScheduleStyleRecalculation = invalidation;
}
if (!lastScheduleStyleRecalculation) {
@@ -1867,14 +1999,17 @@ TimelineModel.InvalidationTracker = class {
_addSyntheticStyleRecalcInvalidation(baseEvent, styleInvalidatorInvalidation) {
const invalidation = new TimelineModel.InvalidationTrackingEvent(baseEvent);
invalidation.type = TimelineModel.TimelineModel.RecordType.StyleRecalcInvalidationTracking;
- if (styleInvalidatorInvalidation.cause.reason)
+ if (styleInvalidatorInvalidation.cause.reason) {
invalidation.cause.reason = styleInvalidatorInvalidation.cause.reason;
- if (styleInvalidatorInvalidation.selectorPart)
+ }
+ if (styleInvalidatorInvalidation.selectorPart) {
invalidation.selectorPart = styleInvalidatorInvalidation.selectorPart;
+ }
this.addInvalidation(invalidation);
- if (!invalidation.linkedRecalcStyleEvent)
+ if (!invalidation.linkedRecalcStyleEvent) {
this._associateWithLastRecalcStyleEvent(invalidation);
+ }
}
/**
@@ -1884,8 +2019,9 @@ TimelineModel.InvalidationTracker = class {
const layoutFrameId = layoutEvent.args['beginData']['frame'];
for (const invalidation of this._invalidationsOfTypes(
[TimelineModel.TimelineModel.RecordType.LayoutInvalidationTracking])) {
- if (invalidation.linkedLayoutEvent)
+ if (invalidation.linkedLayoutEvent) {
continue;
+ }
this._addInvalidationToEvent(layoutEvent, layoutFrameId, invalidation);
invalidation.linkedLayoutEvent = true;
}
@@ -1904,35 +2040,40 @@ TimelineModel.InvalidationTracker = class {
* @param {!TimelineModel.InvalidationTrackingEvent} invalidation
*/
_addInvalidationToEvent(event, eventFrameId, invalidation) {
- if (eventFrameId !== invalidation.frame)
+ if (eventFrameId !== invalidation.frame) {
return;
- if (!event[TimelineModel.InvalidationTracker._invalidationTrackingEventsSymbol])
+ }
+ if (!event[TimelineModel.InvalidationTracker._invalidationTrackingEventsSymbol]) {
event[TimelineModel.InvalidationTracker._invalidationTrackingEventsSymbol] = [invalidation];
- else
+ } else {
event[TimelineModel.InvalidationTracker._invalidationTrackingEventsSymbol].push(invalidation);
+ }
}
/**
* @param {!Array.<string>=} types
- * @return {!Iterator.<!TimelineModel.InvalidationTrackingEvent>}
+ * @return {!Generator<!TimelineModel.InvalidationTrackingEvent>}
*/
_invalidationsOfTypes(types) {
const invalidations = this._invalidations;
- if (!types)
+ if (!types) {
types = Object.keys(invalidations);
+ }
function* generator() {
for (let i = 0; i < types.length; ++i) {
const invalidationList = invalidations[types[i]] || [];
- for (let j = 0; j < invalidationList.length; ++j)
+ for (let j = 0; j < invalidationList.length; ++j) {
yield invalidationList[j];
+ }
}
}
return generator();
}
_startNewFrameIfNeeded() {
- if (!this._didPaint)
+ if (!this._didPaint) {
return;
+ }
this._initializePerFrameState();
}
@@ -1959,13 +2100,15 @@ TimelineModel.TimelineAsyncEventTracker = class {
TimelineModel.TimelineAsyncEventTracker._initialize();
/** @type {!Map<!TimelineModel.TimelineModel.RecordType, !Map<string, !SDK.TracingModel.Event>>} */
this._initiatorByType = new Map();
- for (const initiator of TimelineModel.TimelineAsyncEventTracker._asyncEvents.keys())
+ for (const initiator of TimelineModel.TimelineAsyncEventTracker._asyncEvents.keys()) {
this._initiatorByType.set(initiator, new Map());
+ }
}
static _initialize() {
- if (TimelineModel.TimelineAsyncEventTracker._asyncEvents)
+ if (TimelineModel.TimelineAsyncEventTracker._asyncEvents) {
return;
+ }
const events = new Map();
let type = TimelineModel.TimelineModel.RecordType;
@@ -1986,8 +2129,9 @@ TimelineModel.TimelineAsyncEventTracker = class {
TimelineModel.TimelineAsyncEventTracker._typeToInitiator = new Map();
for (const entry of events) {
const types = entry[1].causes;
- for (type of types)
+ for (type of types) {
TimelineModel.TimelineAsyncEventTracker._typeToInitiator.set(type, entry[0]);
+ }
}
}
@@ -1998,14 +2142,17 @@ TimelineModel.TimelineAsyncEventTracker = class {
let initiatorType = TimelineModel.TimelineAsyncEventTracker._typeToInitiator.get(
/** @type {!TimelineModel.TimelineModel.RecordType} */ (event.name));
const isInitiator = !initiatorType;
- if (!initiatorType)
+ if (!initiatorType) {
initiatorType = /** @type {!TimelineModel.TimelineModel.RecordType} */ (event.name);
+ }
const initiatorInfo = TimelineModel.TimelineAsyncEventTracker._asyncEvents.get(initiatorType);
- if (!initiatorInfo)
+ if (!initiatorInfo) {
return;
+ }
const id = TimelineModel.TimelineModel.globalEventId(event, initiatorInfo.joinBy);
- if (!id)
+ if (!id) {
return;
+ }
/** @type {!Map<string, !SDK.TracingModel.Event>|undefined} */
const initiatorMap = this._initiatorByType.get(initiatorType);
if (isInitiator) {
@@ -2015,8 +2162,9 @@ TimelineModel.TimelineAsyncEventTracker = class {
const initiator = initiatorMap.get(id) || null;
const timelineData = TimelineModel.TimelineData.forEvent(event);
timelineData.setInitiator(initiator);
- if (!timelineData.frameId && initiator)
+ if (!timelineData.frameId && initiator) {
timelineData.frameId = TimelineModel.TimelineModel.eventFrameId(initiator);
+ }
}
};
@@ -2047,11 +2195,13 @@ TimelineModel.TimelineData = class {
*/
setInitiator(initiator) {
this._initiator = initiator;
- if (!initiator || this.url)
+ if (!initiator || this.url) {
return;
+ }
const initiatorURL = TimelineModel.TimelineData.forEvent(initiator).url;
- if (initiatorURL)
+ if (initiatorURL) {
this.url = initiatorURL;
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModelFilter.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModelFilter.js
index 7e4cea1e4df..02531e8503f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModelFilter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModelFilter.js
@@ -34,12 +34,15 @@ TimelineModel.TimelineVisibleEventsFilter = class extends TimelineModel.Timeline
* @return {!TimelineModel.TimelineModel.RecordType}
*/
static _eventType(event) {
- if (event.hasCategory(TimelineModel.TimelineModel.Category.Console))
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.Console)) {
return TimelineModel.TimelineModel.RecordType.ConsoleTime;
- if (event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming))
+ }
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.UserTiming)) {
return TimelineModel.TimelineModel.RecordType.UserTiming;
- if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo))
+ }
+ if (event.hasCategory(TimelineModel.TimelineModel.Category.LatencyInfo)) {
return TimelineModel.TimelineModel.RecordType.LatencyInfo;
+ }
return /** @type !TimelineModel.TimelineModel.RecordType */ (event.name);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
index 22e1c8840ed..82c2b973435 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
@@ -5,11 +5,16 @@
TimelineModel.TimelineProfileTree = {};
/**
+ * @typedef {Map<string|symbol, !TimelineModel.TimelineProfileTree.Node>}
+ */
+TimelineModel.TimelineProfileTree.ChildrenCache;
+
+/**
* @unrestricted
*/
TimelineModel.TimelineProfileTree.Node = class {
/**
- * @param {string} id
+ * @param {string|symbol} id
* @param {?SDK.TracingModel.Event} event
*/
constructor(id, event) {
@@ -17,7 +22,7 @@ TimelineModel.TimelineProfileTree.Node = class {
this.totalTime = 0;
/** @type {number} */
this.selfTime = 0;
- /** @type {string} */
+ /** @type {string|symbol} */
this.id = id;
/** @type {?SDK.TracingModel.Event} */
this.event = event;
@@ -44,7 +49,7 @@ TimelineModel.TimelineProfileTree.Node = class {
}
/**
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
throw 'Not implemented';
@@ -57,17 +62,19 @@ TimelineModel.TimelineProfileTree.Node = class {
*/
searchTree(matchFunction, results) {
results = results || [];
- if (this.event && matchFunction(this.event))
+ if (this.event && matchFunction(this.event)) {
results.push(this);
- for (const child of this.children().values())
+ }
+ for (const child of this.children().values()) {
child.searchTree(matchFunction, results);
+ }
return results;
}
};
TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.TimelineProfileTree.Node {
/**
- * @param {string} id
+ * @param {string|symbol} id
* @param {?SDK.TracingModel.Event} event
* @param {?TimelineModel.TimelineProfileTree.TopDownNode} parent
*/
@@ -90,22 +97,23 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
/**
* @override
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
return this._children || this._buildChildren();
}
/**
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
_buildChildren() {
/** @type {!Array<!TimelineModel.TimelineProfileTree.TopDownNode>} */
const path = [];
- for (let node = this; node.parent && !node._isGroupNode; node = node.parent)
+ for (let node = this; node.parent && !node._isGroupNode; node = node.parent) {
path.push(/** @type {!TimelineModel.TimelineProfileTree.TopDownNode} */ (node));
+ }
path.reverse();
- /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */
+ /** @type {!TimelineModel.TimelineProfileTree.ChildrenCache} */
const children = new Map();
const self = this;
const root = this._root;
@@ -125,13 +133,16 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
*/
function onStartEvent(e) {
++depth;
- if (depth > path.length + 2)
+ if (depth > path.length + 2) {
return;
- if (!matchPath(e))
+ }
+ if (!matchPath(e)) {
return;
+ }
const duration = Math.min(endTime, e.endTime) - Math.max(startTime, e.startTime);
- if (duration < 0)
+ if (duration < 0) {
console.error('Negative event duration');
+ }
processEvent(e, duration);
}
@@ -140,8 +151,9 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
*/
function onInstantEvent(e) {
++depth;
- if (matchedDepth === path.length && depth <= path.length + 2)
+ if (matchedDepth === path.length && depth <= path.length + 2) {
processEvent(e, 0);
+ }
--depth;
}
@@ -162,8 +174,9 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
} else {
id = eventIdCallback(e);
groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : '';
- if (groupId)
+ if (groupId) {
id += '/' + groupId;
+ }
}
let node = children.get(id);
if (!node) {
@@ -181,23 +194,29 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
* @return {boolean}
*/
function matchPath(e) {
- if (matchedDepth === path.length)
+ if (matchedDepth === path.length) {
return true;
- if (matchedDepth !== depth - 1)
+ }
+ if (matchedDepth !== depth - 1) {
return false;
- if (!e.endTime)
+ }
+ if (!e.endTime) {
return false;
+ }
if (!eventIdCallback) {
- if (e === path[matchedDepth].event)
+ if (e === path[matchedDepth].event) {
++matchedDepth;
+ }
return false;
}
let id = eventIdCallback(e);
const groupId = eventGroupIdCallback ? eventGroupIdCallback(e) : '';
- if (groupId)
+ if (groupId) {
id += '/' + groupId;
- if (id === path[matchedDepth].id)
+ }
+ if (id === path[matchedDepth].id) {
++matchedDepth;
+ }
return false;
}
@@ -206,8 +225,9 @@ TimelineModel.TimelineProfileTree.TopDownNode = class extends TimelineModel.Time
*/
function onEndEvent(e) {
--depth;
- if (matchedDepth > depth)
+ if (matchedDepth > depth) {
matchedDepth = depth;
+ }
}
this._children = children;
@@ -239,21 +259,23 @@ TimelineModel.TimelineProfileTree.TopDownRootNode = class extends TimelineModel.
/**
* @override
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
return this._children || this._grouppedTopNodes();
}
/**
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
_grouppedTopNodes() {
const flatNodes = super.children();
- for (const node of flatNodes.values())
+ for (const node of flatNodes.values()) {
this.selfTime -= node.totalTime;
- if (!this._eventGroupIdCallback)
+ }
+ if (!this._eventGroupIdCallback) {
return flatNodes;
+ }
const groupNodes = new Map();
for (const node of flatNodes.values()) {
const groupId = this._eventGroupIdCallback(/** @type {!SDK.TracingModel.Event} */ (node.event));
@@ -281,7 +303,7 @@ TimelineModel.TimelineProfileTree.BottomUpRootNode = class extends TimelineModel
*/
constructor(events, textFilter, filters, startTime, endTime, eventGroupIdCallback) {
super('', null);
- /** @type {?Map<string, !TimelineModel.TimelineProfileTree.Node>} */
+ /** @type {?TimelineModel.TimelineProfileTree.ChildrenCache} */
this._children = null;
this._events = events;
this._textFilter = textFilter;
@@ -301,35 +323,37 @@ TimelineModel.TimelineProfileTree.BottomUpRootNode = class extends TimelineModel
}
/**
- * @param {!Map<string, !TimelineModel.TimelineProfileTree.Node>} children
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @param {!TimelineModel.TimelineProfileTree.ChildrenCache} children
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
_filterChildren(children) {
for (const [id, child] of children) {
- if (child.event && !this._textFilter.accept(child.event))
- children.delete(/** @type {string} */ (id));
+ if (child.event && !this._textFilter.accept(child.event)) {
+ children.delete(/** @type {string|symbol} */ (id));
+ }
}
return children;
}
/**
* @override
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
- if (!this._children)
+ if (!this._children) {
this._children = this._filterChildren(this._grouppedTopNodes());
+ }
return this._children;
}
/**
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
_ungrouppedTopNodes() {
const root = this;
const startTime = this._startTime;
const endTime = this._endTime;
- /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */
+ /** @type {!TimelineModel.TimelineProfileTree.ChildrenCache} */
const nodeById = new Map();
/** @type {!Array<number>} */
const selfTimeStack = [endTime - startTime];
@@ -349,8 +373,9 @@ TimelineModel.TimelineProfileTree.BottomUpRootNode = class extends TimelineModel
selfTimeStack.push(duration);
const id = TimelineModel.TimelineProfileTree._eventId(e);
const noNodeOnStack = !totalTimeById.has(id);
- if (noNodeOnStack)
+ if (noNodeOnStack) {
totalTimeById.set(id, duration);
+ }
firstNodeStack.push(noNodeOnStack);
}
@@ -369,25 +394,28 @@ TimelineModel.TimelineProfileTree.BottomUpRootNode = class extends TimelineModel
node.totalTime += totalTimeById.get(id);
totalTimeById.delete(id);
}
- if (firstNodeStack.length)
+ if (firstNodeStack.length) {
node.setHasChildren();
+ }
}
this.selfTime = selfTimeStack.pop();
for (const pair of nodeById) {
- if (pair[1].selfTime <= 0)
+ if (pair[1].selfTime <= 0) {
nodeById.delete(/** @type {string} */ (pair[0]));
+ }
}
return nodeById;
}
/**
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
_grouppedTopNodes() {
const flatNodes = this._ungrouppedTopNodes();
- if (!this._eventGroupIdCallback)
+ if (!this._eventGroupIdCallback) {
return flatNodes;
+ }
const groupNodes = new Map();
for (const node of flatNodes.values()) {
const groupId = this._eventGroupIdCallback(/** @type {!SDK.TracingModel.Event} */ (node.event));
@@ -438,7 +466,7 @@ TimelineModel.TimelineProfileTree.GroupNode = class extends TimelineModel.Timeli
/**
* @override
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
return this._children;
@@ -458,7 +486,7 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
this.parent = parent;
this._root = root;
this._depth = (parent._depth || 0) + 1;
- /** @type {?Map<string, !TimelineModel.TimelineProfileTree.Node>} */
+ /** @type {?TimelineModel.TimelineProfileTree.ChildrenCache} */
this._cachedChildren = null;
this._hasChildren = hasChildren;
}
@@ -477,18 +505,19 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
/**
* @override
- * @return {!Map<string, !TimelineModel.TimelineProfileTree.Node>}
+ * @return {!TimelineModel.TimelineProfileTree.ChildrenCache}
*/
children() {
- if (this._cachedChildren)
+ if (this._cachedChildren) {
return this._cachedChildren;
+ }
/** @type {!Array<number>} */
const selfTimeStack = [0];
/** @type {!Array<string>} */
const eventIdStack = [];
/** @type {!Array<!SDK.TracingModel.Event>} */
const eventStack = [];
- /** @type {!Map<string, !TimelineModel.TimelineProfileTree.Node>} */
+ /** @type {!TimelineModel.TimelineProfileTree.ChildrenCache} */
const nodeById = new Map();
const startTime = this._root._startTime;
const endTime = this._root._endTime;
@@ -502,8 +531,9 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
*/
function onStartEvent(e) {
const duration = Math.min(e.endTime, endTime) - Math.max(e.startTime, startTime);
- if (duration < 0)
+ if (duration < 0) {
console.assert(false, 'Negative duration of an event');
+ }
selfTimeStack[selfTimeStack.length - 1] -= duration;
selfTimeStack.push(duration);
const id = TimelineModel.TimelineProfileTree._eventId(e);
@@ -520,11 +550,13 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
eventStack.pop();
let node;
for (node = self; node._depth > 1; node = node.parent) {
- if (node.id !== eventIdStack[eventIdStack.length + 1 - node._depth])
+ if (node.id !== eventIdStack[eventIdStack.length + 1 - node._depth]) {
return;
+ }
}
- if (node.id !== id || eventIdStack.length < self._depth)
+ if (node.id !== id || eventIdStack.length < self._depth) {
return;
+ }
const childId = eventIdStack[eventIdStack.length - self._depth];
node = nodeById.get(childId);
if (!node) {
@@ -551,8 +583,9 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
*/
searchTree(matchFunction, results) {
results = results || [];
- if (this.event && matchFunction(this.event))
+ if (this.event && matchFunction(this.event)) {
results.push(this);
+ }
return results;
}
};
@@ -563,13 +596,15 @@ TimelineModel.TimelineProfileTree.BottomUpNode = class extends TimelineModel.Tim
*/
TimelineModel.TimelineProfileTree.eventURL = function(event) {
const data = event.args['data'] || event.args['beginData'];
- if (data && data['url'])
+ if (data && data['url']) {
return data['url'];
+ }
let frame = TimelineModel.TimelineProfileTree.eventStackFrame(event);
while (frame) {
const url = frame['url'];
- if (url)
+ if (url) {
return url;
+ }
frame = frame.parent;
}
return null;
@@ -580,8 +615,9 @@ TimelineModel.TimelineProfileTree.eventURL = function(event) {
* @return {?Protocol.Runtime.CallFrame}
*/
TimelineModel.TimelineProfileTree.eventStackFrame = function(event) {
- if (event.name === TimelineModel.TimelineModel.RecordType.JSFrame)
+ if (event.name === TimelineModel.TimelineModel.RecordType.JSFrame) {
return /** @type {?Protocol.Runtime.CallFrame} */ (event.args['data'] || null);
+ }
return TimelineModel.TimelineData.forEvent(event).topFrame();
};
@@ -590,10 +626,12 @@ TimelineModel.TimelineProfileTree.eventStackFrame = function(event) {
* @return {string}
*/
TimelineModel.TimelineProfileTree._eventId = function(event) {
- if (event.name === TimelineModel.TimelineModel.RecordType.TimeStamp)
+ if (event.name === TimelineModel.TimelineModel.RecordType.TimeStamp) {
return `${event.name}:${event.args.data.message}`;
- if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame)
+ }
+ if (event.name !== TimelineModel.TimelineModel.RecordType.JSFrame) {
return event.name;
+ }
const frame = event.args['data'];
const location = frame['scriptId'] || frame['url'] || '';
const functionName = frame['functionName'];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TracingLayerTree.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TracingLayerTree.js
index cfaa503d859..7e0c5cc0f82 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TracingLayerTree.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TracingLayerTree.js
@@ -53,8 +53,9 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
// layer tree hierarchy, this code will eventually be removed.
this._extractNodeIdsToResolve(idsToResolve, {}, root);
} else {
- for (let i = 0; i < layers.length; ++i)
+ for (let i = 0; i < layers.length; ++i) {
this._extractNodeIdsToResolve(idsToResolve, {}, layers[i]);
+ }
}
await this.resolveBackendNodeIds(idsToResolve);
@@ -70,8 +71,9 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
const contentRoot = this.contentRoot();
this.setRoot(contentRoot);
for (let i = 0; i < processedLayers.length; ++i) {
- if (processedLayers[i].id() !== contentRoot.id())
+ if (processedLayers[i].id() !== contentRoot.id()) {
contentRoot.addChild(processedLayers[i]);
+ }
}
}
this._setPaints(paints);
@@ -82,8 +84,9 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
*/
setTiles(tiles) {
this._tileById = new Map();
- for (const tile of tiles)
+ for (const tile of tiles) {
this._tileById.set(tile.id, tile);
+ }
}
/**
@@ -96,7 +99,7 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
Common.console.error(`Tile ${tileId} is missing`);
return /** @type {!Promise<?SDK.SnapshotWithRect>} */ (Promise.resolve(null));
}
- const layer = this.layerById(tile.layer_id);
+ const layer = /** @type {?TimelineModel.TracingLayer} */ (this.layerById(tile.layer_id));
if (!layer) {
Common.console.error(`Layer ${tile.layer_id} for tile ${tileId} is not found`);
return /** @type {!Promise<?SDK.SnapshotWithRect>} */ (Promise.resolve(null));
@@ -110,8 +113,9 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
_setPaints(paints) {
for (let i = 0; i < paints.length; ++i) {
const layer = this._layersById[paints[i].layerId()];
- if (layer)
+ if (layer) {
layer._addPaintEvent(paints[i]);
+ }
}
}
@@ -122,17 +126,21 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
*/
_innerSetLayers(oldLayersById, payload) {
let layer = /** @type {?TimelineModel.TracingLayer} */ (oldLayersById[payload.layer_id]);
- if (layer)
+ if (layer) {
layer._reset(payload);
- else
+ } else {
layer = new TimelineModel.TracingLayer(this._paintProfilerModel, payload);
+ }
this._layersById[payload.layer_id] = layer;
- if (payload.owner_node)
+ if (payload.owner_node) {
layer._setNode(this.backendNodeIdToNode().get(payload.owner_node) || null);
- if (!this.contentRoot() && layer.drawsContent())
+ }
+ if (!this.contentRoot() && layer.drawsContent()) {
this.setContentRoot(layer);
- for (let i = 0; payload.children && i < payload.children.length; ++i)
+ }
+ for (let i = 0; payload.children && i < payload.children.length; ++i) {
layer.addChild(this._innerSetLayers(oldLayersById, payload.children[i]));
+ }
return layer;
}
@@ -143,10 +151,12 @@ TimelineModel.TracingLayerTree = class extends SDK.LayerTreeBase {
*/
_extractNodeIdsToResolve(nodeIdsToResolve, seenNodeIds, payload) {
const backendNodeId = payload.owner_node;
- if (backendNodeId && !this.backendNodeIdToNode().has(backendNodeId))
+ if (backendNodeId && !this.backendNodeIdToNode().has(backendNodeId)) {
nodeIdsToResolve.add(backendNodeId);
- for (let i = 0; payload.children && i < payload.children.length; ++i)
+ }
+ for (let i = 0; payload.children && i < payload.children.length; ++i) {
this._extractNodeIdsToResolve(nodeIdsToResolve, seenNodeIds, payload.children[i]);
+ }
}
};
@@ -180,7 +190,12 @@ TimelineModel.TracingLayer = class {
this._parent = null;
this._quad = payload.layer_quad || [];
this._createScrollRects(payload);
- this._compositingReasons = payload.compositing_reasons || [];
+
+ // Keep payload.compositing_reasons as a default
+ // but use the newer payload.debug_info.compositing_reasons
+ // if the first one is not set.
+ this._compositingReasons =
+ payload.compositing_reasons || (payload.debug_info && payload.debug_info.compositing_reasons) || [];
this._drawsContent = !!payload.draws_content;
this._gpuMemoryUsage = payload.gpu_memory_usage;
this._paints = [];
@@ -228,11 +243,13 @@ TimelineModel.TracingLayer = class {
/**
* @override
- * @param {!SDK.Layer} child
+ * @param {!SDK.Layer} childParam
*/
- addChild(child) {
- if (child._parent)
+ addChild(childParam) {
+ const child = /** @type {!TimelineModel.TracingLayer} */ (childParam);
+ if (child._parent) {
console.assert(false, 'Child already has a parent');
+ }
this._children.push(child);
child._parent = this;
child._parentLayerId = this._layerId;
@@ -259,8 +276,9 @@ TimelineModel.TracingLayer = class {
*/
nodeForSelfOrAncestor() {
for (let layer = this; layer; layer = layer._parent) {
- if (layer._node)
+ if (layer._node) {
return layer._node;
+ }
}
return null;
}
@@ -376,8 +394,9 @@ TimelineModel.TracingLayer = class {
*/
snapshots() {
return this._paints.map(paint => paint.snapshotPromise().then(snapshot => {
- if (!snapshot)
+ if (!snapshot) {
return null;
+ }
const rect = {x: snapshot.rect[0], y: snapshot.rect[1], width: snapshot.rect[2], height: snapshot.rect[3]};
return {rect: rect, snapshot: snapshot.snapshot};
}));
@@ -392,8 +411,9 @@ TimelineModel.TracingLayer = class {
const fragments =
pictures.filter(picture => picture && rectsOverlap(picture.rect, targetRect))
.map(picture => ({x: picture.rect[0], y: picture.rect[1], picture: picture.serializedPicture}));
- if (!fragments.length || !this._paintProfilerModel)
+ if (!fragments.length || !this._paintProfilerModel) {
return null;
+ }
const x0 = fragments.reduce((min, item) => Math.min(min, item.x), Infinity);
const y0 = fragments.reduce((min, item) => Math.min(min, item.y), Infinity);
// Rect is in layer content coordinates, make it relative to picture by offsetting to the top left corner.
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
index c48ad36929b..98dbdd366ab 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
@@ -8,8 +8,8 @@
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' ">
- <script src="Runtime.js"></script>
- <script src="toolbox.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="toolbox.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.js b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.js
index fe47ccc7cb7..0a1583c4eae 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.js
@@ -1,4 +1,4 @@
// 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.
-Runtime.startApplication('toolbox');
+Root.Runtime.startApplication('toolbox');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/toolbox_bootstrap/Toolbox.js b/chromium/third_party/blink/renderer/devtools/front_end/toolbox_bootstrap/Toolbox.js
index 731f91b504a..943b43f1730 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/toolbox_bootstrap/Toolbox.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/toolbox_bootstrap/Toolbox.js
@@ -6,8 +6,9 @@
* @suppressGlobalPropertiesCheck
*/
function toolboxLoaded() {
- if (!window.opener)
+ if (!window.opener) {
return;
+ }
const app = window.opener['Emulation']['AdvancedApp']['_instance']();
app['toolboxLoaded'](document);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js
index 29a893d4f22..365f3b93f10 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ARIAUtils.js
@@ -2,305 +2,368 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.ARIAUtils = {};
-UI.ARIAUtils._id = 0;
+let _id = 0;
+
+/**
+ * @param {string} prefix
+ * @return {string}
+ */
+export function nextId(prefix) {
+ return (prefix || '') + ++_id;
+}
/**
* @param {!Element} label
* @param {!Element} control
*/
-UI.ARIAUtils.bindLabelToControl = function(label, control) {
- const controlId = UI.ARIAUtils.nextId('labelledControl');
+export function bindLabelToControl(label, control) {
+ const controlId = nextId('labelledControl');
control.id = controlId;
label.setAttribute('for', controlId);
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsAlert = function(element) {
+export function markAsAlert(element) {
element.setAttribute('role', 'alert');
element.setAttribute('aria-live', 'polite');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsButton = function(element) {
+export function markAsButton(element) {
element.setAttribute('role', 'button');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsCheckbox = function(element) {
+export function markAsCheckbox(element) {
element.setAttribute('role', 'checkbox');
-};
+}
+
+/**
+ * @param {!Element} element
+ */
+export function markAsCombobox(element) {
+ element.setAttribute('role', 'combobox');
+}
/**
* @param {!Element} element
- * @param {boolean=} modal
*/
-UI.ARIAUtils.markAsDialog = function(element, modal) {
+export function markAsModalDialog(element) {
element.setAttribute('role', 'dialog');
- if (modal)
- element.setAttribute('aria-modal', 'true');
-};
+ element.setAttribute('aria-modal', 'true');
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsGroup = function(element) {
+export function markAsGroup(element) {
element.setAttribute('role', 'group');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsLink = function(element) {
+export function markAsLink(element) {
element.setAttribute('role', 'link');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsMenuButton = function(element) {
- UI.ARIAUtils.markAsButton(element);
+export function markAsMenuButton(element) {
+ markAsButton(element);
element.setAttribute('aria-haspopup', true);
-};
+}
/**
* @param {!Element} element
+ * @param {number=} min
+ * @param {number=} max
*/
-UI.ARIAUtils.markAsProgressBar = function(element) {
+export function markAsProgressBar(element, min = 0, max = 100) {
element.setAttribute('role', 'progressbar');
- element.setAttribute('aria-valuemin', 0);
- element.setAttribute('aria-valuemax', 100);
-};
+ element.setAttribute('aria-valuemin', min);
+ element.setAttribute('aria-valuemax', max);
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsTab = function(element) {
+export function markAsTab(element) {
element.setAttribute('role', 'tab');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsTree = function(element) {
+export function markAsTree(element) {
element.setAttribute('role', 'tree');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsTreeitem = function(element) {
+export function markAsTreeitem(element) {
element.setAttribute('role', 'treeitem');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsTextBox = function(element) {
+export function markAsTextBox(element) {
element.setAttribute('role', 'textbox');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsMenu = function(element) {
+export function markAsMenu(element) {
element.setAttribute('role', 'menu');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsMenuItem = function(element) {
+export function markAsMenuItem(element) {
element.setAttribute('role', 'menuitem');
-};
+}
+
+/**
+ * @param {!Element} element
+ */
+export function markAsMenuItemSubMenu(element) {
+ markAsMenuItem(element);
+ element.setAttribute('aria-haspopup', true);
+}
+
+/**
+ * @param {!Element} element
+ */
+export function markAsList(element) {
+ element.setAttribute('role', 'list');
+}
+
+/**
+ * @param {!Element} element
+ */
+export function markAsListitem(element) {
+ element.setAttribute('role', 'listitem');
+}
/**
* Must contain children whose role is option.
* @param {!Element} element
*/
-UI.ARIAUtils.markAsListBox = function(element) {
+export function markAsListBox(element) {
element.setAttribute('role', 'listbox');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsMultiSelectable = function(element) {
+export function markAsMultiSelectable(element) {
element.setAttribute('aria-multiselectable', 'true');
-};
+}
/**
* Must be contained in, or owned by, an element with the role listbox.
* @param {!Element} element
*/
-UI.ARIAUtils.markAsOption = function(element) {
+export function markAsOption(element) {
element.setAttribute('role', 'option');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsRadioGroup = function(element) {
+export function markAsRadioGroup(element) {
element.setAttribute('role', 'radiogroup');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsHidden = function(element) {
+export function markAsHidden(element) {
element.setAttribute('aria-hidden', 'true');
-};
+}
/**
* @param {!Element} element
* @param {number} level
*/
-UI.ARIAUtils.markAsHeading = function(element, level) {
+export function markAsHeading(element, level) {
element.setAttribute('role', 'heading');
element.setAttribute('aria-level', level);
-};
+}
+
+/**
+ * @param {!Element} element
+ */
+export function markAsPoliteLiveRegion(element) {
+ element.setAttribute('aria-live', 'polite');
+}
/**
* @param {!Element} element
* @param {?string} placeholder
*/
-UI.ARIAUtils.setPlaceholder = function(element, placeholder) {
- if (placeholder)
+export function setPlaceholder(element, placeholder) {
+ if (placeholder) {
element.setAttribute('aria-placeholder', placeholder);
- else
+ } else {
element.removeAttribute('aria-placeholder');
-};
+ }
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsPresentation = function(element) {
+export function markAsPresentation(element) {
element.setAttribute('role', 'presentation');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.markAsStatus = function(element) {
+export function markAsStatus(element) {
element.setAttribute('role', 'status');
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.ensureId = function(element) {
- if (!element.id)
- element.id = UI.ARIAUtils.nextId('ariaElement');
-};
-
-/**
- * @param {string} prefix
- * @return {string}
- */
-UI.ARIAUtils.nextId = function(prefix) {
- return (prefix || '') + ++UI.ARIAUtils._id;
-};
+export function ensureId(element) {
+ if (!element.id) {
+ element.id = nextId('ariaElement');
+ }
+}
/**
* @param {!Element} element
* @param {?Element} controlledElement
*/
-UI.ARIAUtils.setControls = function(element, controlledElement) {
+export function setControls(element, controlledElement) {
if (!controlledElement) {
element.removeAttribute('aria-controls');
return;
}
- UI.ARIAUtils.ensureId(controlledElement);
+ ensureId(controlledElement);
element.setAttribute('aria-controls', controlledElement.id);
-};
+}
/**
* @param {!Element} element
* @param {boolean} value
*/
-UI.ARIAUtils.setChecked = function(element, value) {
+export function setChecked(element, value) {
element.setAttribute('aria-checked', !!value);
-};
+}
+
+/**
+ * @param {!Element} element
+ */
+export function setCheckboxAsIndeterminate(element) {
+ element.setAttribute('aria-checked', 'mixed');
+}
/**
* @param {!Element} element
* @param {boolean} value
*/
-UI.ARIAUtils.setExpanded = function(element, value) {
+export function setExpanded(element, value) {
element.setAttribute('aria-expanded', !!value);
-};
+}
/**
* @param {!Element} element
*/
-UI.ARIAUtils.unsetExpandable = function(element) {
+export function unsetExpandable(element) {
element.removeAttribute('aria-expanded');
+}
+
+/**
+ * @enum {string}
+ */
+export const AutocompleteInteractionModel = {
+ inline: 'inline',
+ list: 'list',
+ both: 'both',
+ none: 'none',
};
/**
* @param {!Element} element
+ * @param {!AutocompleteInteractionModel=} interactionModel
+ */
+export function setAutocomplete(element, interactionModel = AutocompleteInteractionModel.none) {
+ element.setAttribute('aria-autocomplete', interactionModel);
+}
+
+/**
+ * @param {!Element} element
* @param {boolean} value
*/
-UI.ARIAUtils.setSelected = function(element, value) {
+export function setSelected(element, value) {
// aria-selected behaves differently for false and undefined.
// Often times undefined values are unintentionally typed as booleans.
// Use !! to make sure this is true or false.
element.setAttribute('aria-selected', !!value);
-};
+}
/**
* @param {!Element} element
* @param {boolean} value
*/
-UI.ARIAUtils.setInvalid = function(element, value) {
- if (value)
+export function setInvalid(element, value) {
+ if (value) {
element.setAttribute('aria-invalid', value);
- else
+ } else {
element.removeAttribute('aria-invalid');
-};
+ }
+}
/**
* @param {!Element} element
* @param {boolean} value
*/
-UI.ARIAUtils.setPressed = function(element, value) {
+export function setPressed(element, value) {
// aria-pressed behaves differently for false and undefined.
// Often times undefined values are unintentionally typed as booleans.
// Use !! to make sure this is true or false.
element.setAttribute('aria-pressed', !!value);
-};
+}
/**
* @param {!Element} element
* @param {number} value
*/
-UI.ARIAUtils.setProgressBarCurrentPercentage = function(element, value) {
+export function setProgressBarCurrentPercentage(element, value) {
element.setAttribute('aria-valuenow', value);
-};
+}
/**
* @param {!Element} element
* @param {string} name
*/
-UI.ARIAUtils.setAccessibleName = function(element, name) {
+export function setAccessibleName(element, name) {
element.setAttribute('aria-label', name);
-};
+}
/** @type {!WeakMap<!Element, !Element>} */
-UI.ARIAUtils._descriptionMap = new WeakMap();
+const _descriptionMap = new WeakMap();
/**
* @param {!Element} element
* @param {string} description
*/
-UI.ARIAUtils.setDescription = function(element, description) {
+export function setDescription(element, description) {
// Nodes in the accesesibility tree are made up of a core
// triplet of "name", "value", "description"
// The "description" field is taken from either
@@ -326,12 +389,13 @@ UI.ARIAUtils.setDescription = function(element, description) {
// The rest of DevTools shouldn't have to worry about this,
// so there is some unfortunate code below.
- if (UI.ARIAUtils._descriptionMap.has(element))
- UI.ARIAUtils._descriptionMap.get(element).remove();
+ if (_descriptionMap.has(element)) {
+ _descriptionMap.get(element).remove();
+ }
element.removeAttribute('data-aria-utils-animation-hack');
if (!description) {
- UI.ARIAUtils._descriptionMap.delete(element);
+ _descriptionMap.delete(element);
element.removeAttribute('aria-describedby');
return;
}
@@ -341,9 +405,9 @@ UI.ARIAUtils.setDescription = function(element, description) {
const descriptionElement = createElement('span');
descriptionElement.textContent = description;
descriptionElement.style.display = 'none';
- UI.ARIAUtils.ensureId(descriptionElement);
+ ensureId(descriptionElement);
element.setAttribute('aria-describedby', descriptionElement.id);
- UI.ARIAUtils._descriptionMap.set(element, descriptionElement);
+ _descriptionMap.set(element, descriptionElement);
// Now we have to actually put this description element
// somewhere in the DOM so that we can point to it.
@@ -367,8 +431,9 @@ UI.ARIAUtils.setDescription = function(element, description) {
// Lets try the next best thing, and just put the description element
// next to it in the DOM.
const inserted = element.insertAdjacentElement('afterend', descriptionElement);
- if (inserted)
+ if (inserted) {
return;
+ }
// Uh oh, the insertion didn't work! That means we aren't currently in the DOM.
// How can we find out when the element enters the DOM?
@@ -376,20 +441,21 @@ UI.ARIAUtils.setDescription = function(element, description) {
element.setAttribute('data-aria-utils-animation-hack', 'sorry');
element.addEventListener('animationend', () => {
// Someone might have made a new description in the meantime.
- if (UI.ARIAUtils._descriptionMap.get(element) !== descriptionElement)
+ if (_descriptionMap.get(element) !== descriptionElement) {
return;
+ }
element.removeAttribute('data-aria-utils-animation-hack');
// Try it again. This time we are in the DOM, so it *should* work.
element.insertAdjacentElement('afterend', descriptionElement);
}, {once: true});
-};
+}
/**
* @param {!Element} element
* @param {?Element} activedescendant
*/
-UI.ARIAUtils.setActiveDescendant = function(element, activedescendant) {
+export function setActiveDescendant(element, activedescendant) {
if (!activedescendant) {
element.removeAttribute('aria-activedescendant');
return;
@@ -397,17 +463,19 @@ UI.ARIAUtils.setActiveDescendant = function(element, activedescendant) {
console.assert(element.hasSameShadowRoot(activedescendant), 'elements are not in the same shadow dom');
- UI.ARIAUtils.ensureId(activedescendant);
+ ensureId(activedescendant);
element.setAttribute('aria-activedescendant', activedescendant.id);
-};
+}
+
+const AlertElementSymbol = Symbol('AlertElementSybmol');
/**
* @param {string} message
* @param {!Element} element
*/
-UI.ARIAUtils.alert = function(message, element) {
+export function alert(message, element) {
const document = element.ownerDocument;
- if (!document[UI.ARIAUtils.AlertElementSymbol]) {
+ if (!document[AlertElementSymbol]) {
const alertElement = document.body.createChild('div');
alertElement.style.position = 'absolute';
alertElement.style.left = '-999em';
@@ -415,9 +483,63 @@ UI.ARIAUtils.alert = function(message, element) {
alertElement.style.overflow = 'hidden';
alertElement.setAttribute('role', 'alert');
alertElement.setAttribute('aria-atomic', 'true');
- document[UI.ARIAUtils.AlertElementSymbol] = alertElement;
+ document[AlertElementSymbol] = alertElement;
}
- document[UI.ARIAUtils.AlertElementSymbol].textContent = message.trimEnd(10000);
-};
-UI.ARIAUtils.AlertElementSymbol = Symbol('AlertElementSybmol');
+ document[AlertElementSymbol].textContent = message.trimEndWithMaxLength(10000);
+}
+
+/** Legacy exported object */
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+self.UI.ARIAUtils = {
+ nextId,
+ bindLabelToControl,
+ markAsAlert,
+ markAsButton,
+ markAsCheckbox,
+ markAsCombobox,
+ markAsModalDialog,
+ markAsGroup,
+ markAsLink,
+ markAsMenuButton,
+ markAsProgressBar,
+ markAsTab,
+ markAsTree,
+ markAsTreeitem,
+ markAsTextBox,
+ markAsMenu,
+ markAsMenuItem,
+ markAsMenuItemSubMenu,
+ markAsList,
+ markAsListitem,
+ markAsListBox,
+ markAsMultiSelectable,
+ markAsOption,
+ markAsRadioGroup,
+ markAsHidden,
+ markAsHeading,
+ markAsPoliteLiveRegion,
+ setPlaceholder,
+ markAsPresentation,
+ markAsStatus,
+ ensureId,
+ setControls,
+ setChecked,
+ setCheckboxAsIndeterminate,
+ setExpanded,
+ unsetExpandable,
+ AutocompleteInteractionModel,
+ setAutocomplete,
+ setSelected,
+ setInvalid,
+ setPressed,
+ setProgressBarCurrentPercentage,
+ setAccessibleName,
+ setDescription,
+ setActiveDescendant,
+ alert,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Action.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Action.js
new file mode 100644
index 00000000000..60d83946079
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Action.js
@@ -0,0 +1,165 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+export default class Action extends Common.Object {
+ /**
+ * @param {!Root.Runtime.Extension} extension
+ */
+ constructor(extension) {
+ super();
+ this._extension = extension;
+ this._enabled = true;
+ this._toggled = false;
+ }
+
+ /**
+ * @return {string}
+ */
+ id() {
+ return this._extension.descriptor()['actionId'];
+ }
+
+ /**
+ * @return {!Runtime.Extension}
+ */
+ extension() {
+ return this._extension;
+ }
+
+ /**
+ * @return {!Promise.<boolean>}
+ */
+ execute() {
+ return this._extension.instance().then(handleAction.bind(this));
+
+ /**
+ * @param {!Object} actionDelegate
+ * @return {boolean}
+ * @this {UI.Action}
+ */
+ function handleAction(actionDelegate) {
+ const actionId = this._extension.descriptor()['actionId'];
+ const delegate = /** @type {!UI.ActionDelegate} */ (actionDelegate);
+ return delegate.handleAction(UI.context, actionId);
+ }
+ }
+
+ /**
+ * @return {string}
+ */
+ icon() {
+ return this._extension.descriptor()['iconClass'] || '';
+ }
+
+ /**
+ * @return {string}
+ */
+ toggledIcon() {
+ return this._extension.descriptor()['toggledIconClass'] || '';
+ }
+
+ /**
+ * @return {boolean}
+ */
+ toggleWithRedColor() {
+ return !!this._extension.descriptor()['toggleWithRedColor'];
+ }
+
+ /**
+ * @param {boolean} enabled
+ */
+ setEnabled(enabled) {
+ if (this._enabled === enabled) {
+ return;
+ }
+
+ this._enabled = enabled;
+ this.dispatchEventToListeners(Events.Enabled, enabled);
+ }
+
+ /**
+ * @return {boolean}
+ */
+ enabled() {
+ return this._enabled;
+ }
+
+ /**
+ * @return {string}
+ */
+ category() {
+ return ls(this._extension.descriptor()['category'] || '');
+ }
+
+ /**
+ * @return {string}
+ */
+ tags() {
+ return this._extension.descriptor()['tags'] || '';
+ }
+
+ /**
+ * @return {boolean}
+ */
+ toggleable() {
+ return !!this._extension.descriptor()['toggleable'];
+ }
+
+ /**
+ * @return {string}
+ */
+ title() {
+ let title = this._extension.title() || '';
+ const options = this._extension.descriptor()['options'];
+ if (options) {
+ for (const pair of options) {
+ if (pair['value'] !== this._toggled) {
+ title = ls(pair['title']);
+ }
+ }
+ }
+ return title;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ toggled() {
+ return this._toggled;
+ }
+
+ /**
+ * @param {boolean} toggled
+ */
+ setToggled(toggled) {
+ console.assert(this.toggleable(), 'Shouldn\'t be toggling an untoggleable action', this.id());
+ if (this._toggled === toggled) {
+ return;
+ }
+
+ this._toggled = toggled;
+ this.dispatchEventToListeners(Events.Toggled, toggled);
+ }
+}
+
+/** @enum {symbol} */
+const Events = {
+ Enabled: Symbol('Enabled'),
+ Toggled: Symbol('Toggled')
+};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Action = Action;
+
+/** @enum {symbol} */
+UI.Action.Events = Events; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionDelegate.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionDelegate.js
new file mode 100644
index 00000000000..ec8341c0b23
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionDelegate.js
@@ -0,0 +1,25 @@
+// 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.
+
+/**
+ * @interface
+ */
+export default class ActionDelegate {
+ /**
+ * @param {!UI.Context} context
+ * @param {string} actionId
+ * @return {boolean}
+ */
+ handleAction(context, actionId) {
+ }
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @interface */
+UI.ActionDelegate = ActionDelegate; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
index aa73fff728a..7f990986679 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.ActionRegistry = class {
+export default class ActionRegistry {
constructor() {
/** @type {!Map.<string, !UI.Action>} */
this._actionsById = new Map();
@@ -15,21 +15,23 @@ UI.ActionRegistry = class {
self.runtime.extensions('action').forEach(registerExtension, this);
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @this {UI.ActionRegistry}
*/
function registerExtension(extension) {
- if (!extension.canInstantiate())
+ if (!extension.canInstantiate()) {
return;
+ }
const actionId = extension.descriptor()['actionId'];
console.assert(actionId);
console.assert(!this._actionsById.get(actionId));
const action = new UI.Action(extension);
- if (!action.category() || action.title())
+ if (!action.category() || action.title()) {
this._actionsById.set(actionId, action);
- else
+ } else {
console.error(`Category actions require a title for command menu: ${actionId}`);
+ }
}
}
@@ -49,13 +51,14 @@ UI.ActionRegistry = class {
const extensions = [];
actionIds.forEach(function(actionId) {
const action = this._actionsById.get(actionId);
- if (action)
- extensions.push(action._extension);
+ if (action) {
+ extensions.push(action.extension());
+ }
}, this);
return context.applicableExtensions(extensions).valuesArray().map(extensionToAction.bind(this));
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
* @return {!UI.Action}
* @this {UI.ActionRegistry}
*/
@@ -71,161 +74,16 @@ UI.ActionRegistry = class {
action(actionId) {
return this._actionsById.get(actionId) || null;
}
-};
-
-/**
- * @unrestricted
- */
-UI.Action = class extends Common.Object {
- /**
- * @param {!Runtime.Extension} extension
- */
- constructor(extension) {
- super();
- this._extension = extension;
- this._enabled = true;
- this._toggled = false;
- }
-
- /**
- * @return {string}
- */
- id() {
- return this._extension.descriptor()['actionId'];
- }
-
- /**
- * @return {!Promise.<boolean>}
- */
- execute() {
- return this._extension.instance().then(handleAction.bind(this));
-
- /**
- * @param {!Object} actionDelegate
- * @return {boolean}
- * @this {UI.Action}
- */
- function handleAction(actionDelegate) {
- const actionId = this._extension.descriptor()['actionId'];
- const delegate = /** @type {!UI.ActionDelegate} */ (actionDelegate);
- return delegate.handleAction(UI.context, actionId);
- }
- }
-
- /**
- * @return {string}
- */
- icon() {
- return this._extension.descriptor()['iconClass'] || '';
- }
-
- /**
- * @return {string}
- */
- toggledIcon() {
- return this._extension.descriptor()['toggledIconClass'] || '';
- }
-
- /**
- * @return {boolean}
- */
- toggleWithRedColor() {
- return !!this._extension.descriptor()['toggleWithRedColor'];
- }
-
- /**
- * @param {boolean} enabled
- */
- setEnabled(enabled) {
- if (this._enabled === enabled)
- return;
-
- this._enabled = enabled;
- this.dispatchEventToListeners(UI.Action.Events.Enabled, enabled);
- }
-
- /**
- * @return {boolean}
- */
- enabled() {
- return this._enabled;
- }
-
- /**
- * @return {string}
- */
- category() {
- return this._extension.descriptor()['category'] || '';
- }
-
- /**
- * @return {string}
- */
- tags() {
- return this._extension.descriptor()['tags'] || '';
- }
-
- /**
- * @return {boolean}
- */
- toggleable() {
- return !!this._extension.descriptor()['toggleable'];
- }
-
- /**
- * @return {string}
- */
- title() {
- let title = this._extension.title();
- const options = this._extension.descriptor()['options'];
- if (options) {
- for (const pair of options) {
- if (pair['value'] !== this._toggled)
- title = pair['title'];
- }
- }
- return title;
- }
+}
- /**
- * @return {boolean}
- */
- toggled() {
- return this._toggled;
- }
+/* Legacy exported object*/
+self.UI = self.UI || {};
- /**
- * @param {boolean} toggled
- */
- setToggled(toggled) {
- console.assert(this.toggleable(), 'Shouldn\'t be toggling an untoggleable action', this.id());
- if (this._toggled === toggled)
- return;
+/* Legacy exported object*/
+UI = UI || {};
- this._toggled = toggled;
- this.dispatchEventToListeners(UI.Action.Events.Toggled, toggled);
- }
-};
-
-/** @enum {symbol} */
-UI.Action.Events = {
- Enabled: Symbol('Enabled'),
- Toggled: Symbol('Toggled')
-};
-
-/**
- * @interface
- */
-UI.ActionDelegate = function() {};
-
-UI.ActionDelegate.prototype = {
- /**
- * @param {!UI.Context} context
- * @param {string} actionId
- * @return {boolean}
- */
- handleAction(context, actionId) {}
-};
+/** @constructor */
+UI.ActionRegistry = ActionRegistry;
/** @type {!UI.ActionRegistry} */
UI.actionRegistry;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Context.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Context.js
index 31b5be91ce9..13e630d2b96 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Context.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Context.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.Context = class {
+export default class Context {
constructor() {
this._flavors = new Map();
this._eventDispatchers = new Map();
@@ -17,12 +17,14 @@ UI.Context = class {
*/
setFlavor(flavorType, flavorValue) {
const value = this._flavors.get(flavorType) || null;
- if (value === flavorValue)
+ if (value === flavorValue) {
return;
- if (flavorValue)
+ }
+ if (flavorValue) {
this._flavors.set(flavorType, flavorValue);
- else
+ } else {
this._flavors.remove(flavorType);
+ }
this._dispatchFlavorChange(flavorType, flavorValue);
}
@@ -40,9 +42,10 @@ UI.Context = class {
}
}
const dispatcher = this._eventDispatchers.get(flavorType);
- if (!dispatcher)
+ if (!dispatcher) {
return;
- dispatcher.dispatchEventToListeners(UI.Context.Events.FlavorChanged, flavorValue);
+ }
+ dispatcher.dispatchEventToListeners(Context.Events.FlavorChanged, flavorValue);
}
/**
@@ -56,7 +59,7 @@ UI.Context = class {
dispatcher = new Common.Object();
this._eventDispatchers.set(flavorType, dispatcher);
}
- dispatcher.addEventListener(UI.Context.Events.FlavorChanged, listener, thisObject);
+ dispatcher.addEventListener(Context.Events.FlavorChanged, listener, thisObject);
}
/**
@@ -66,11 +69,13 @@ UI.Context = class {
*/
removeFlavorChangeListener(flavorType, listener, thisObject) {
const dispatcher = this._eventDispatchers.get(flavorType);
- if (!dispatcher)
+ if (!dispatcher) {
return;
- dispatcher.removeEventListener(UI.Context.Events.FlavorChanged, listener, thisObject);
- if (!dispatcher.hasEventListeners(UI.Context.Events.FlavorChanged))
+ }
+ dispatcher.removeEventListener(Context.Events.FlavorChanged, listener, thisObject);
+ if (!dispatcher.hasEventListeners(Context.Events.FlavorChanged)) {
this._eventDispatchers.remove(flavorType);
+ }
}
/**
@@ -90,37 +95,39 @@ UI.Context = class {
}
/**
- * @param {!Array.<!Runtime.Extension>} extensions
- * @return {!Set.<!Runtime.Extension>}
+ * @param {!Array.<!Root.Runtime.Extension>} extensions
+ * @return {!Set.<!Root.Runtime.Extension>}
*/
applicableExtensions(extensions) {
const targetExtensionSet = new Set();
const availableFlavors = this.flavors();
extensions.forEach(function(extension) {
- if (self.runtime.isExtensionApplicableToContextTypes(extension, availableFlavors))
+ if (self.runtime.isExtensionApplicableToContextTypes(extension, availableFlavors)) {
targetExtensionSet.add(extension);
+ }
});
return targetExtensionSet;
}
-};
+}
/** @enum {symbol} */
-UI.Context.Events = {
+export const Events = {
FlavorChanged: Symbol('FlavorChanged')
};
-/**
- * @interface
- */
-UI.ContextFlavorListener = function() {};
+/* Legacy exported object*/
+self.UI = self.UI || {};
-UI.ContextFlavorListener.prototype = {
- /**
- * @param {?Object} object
- */
- flavorChanged(object) {}
-};
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Context = Context;
+
+/** @enum {symbol} */
+UI.Context.Events = Events;
-UI.context = new UI.Context();
+/** @type {!Context} */
+UI.context = new Context();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextFlavorListener.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextFlavorListener.js
new file mode 100644
index 00000000000..04ceb1836aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextFlavorListener.js
@@ -0,0 +1,22 @@
+// 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.
+/**
+ * @interface
+ */
+export default class ContextFlavorListener {
+ /**
+ * @param {?Object} object
+ */
+ flavorChanged(object) {
+ }
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @interface */
+UI.ContextFlavorListener = ContextFlavorListener; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
index 3aded9679f7..cc6157f6f1c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
@@ -31,9 +31,9 @@
/**
* @unrestricted
*/
-UI.ContextMenuItem = class {
+export class Item {
/**
- * @param {?UI.ContextMenu} contextMenu
+ * @param {?ContextMenu} contextMenu
* @param {string} type
* @param {string=} label
* @param {boolean=} disabled
@@ -45,8 +45,9 @@ UI.ContextMenuItem = class {
this._disabled = disabled;
this._checked = checked;
this._contextMenu = contextMenu;
- if (type === 'item' || type === 'checkbox')
+ if (type === 'item' || type === 'checkbox') {
this._id = contextMenu ? contextMenu._nextId() : 0;
+ }
}
/**
@@ -84,10 +85,12 @@ UI.ContextMenuItem = class {
switch (this._type) {
case 'item':
const result = {type: 'item', id: this._id, label: this._label, enabled: !this._disabled};
- if (this._customElement)
+ if (this._customElement) {
result.element = this._customElement;
- if (this._shortcut)
+ }
+ if (this._shortcut) {
result.shortcut = this._shortcut;
+ }
return result;
case 'separator':
return {type: 'separator'};
@@ -103,18 +106,18 @@ UI.ContextMenuItem = class {
setShortcut(shortcut) {
this._shortcut = shortcut;
}
-};
+}
/**
* @unrestricted
*/
-UI.ContextMenuSection = class {
+export class Section {
/**
- * @param {?UI.ContextMenu} contextMenu
+ * @param {?ContextMenu} contextMenu
*/
constructor(contextMenu) {
this._contextMenu = contextMenu;
- /** @type {!Array<!UI.ContextMenuItem>} */
+ /** @type {!Array<!Item>} */
this._items = [];
}
@@ -122,10 +125,10 @@ UI.ContextMenuSection = class {
* @param {string} label
* @param {function(?)} handler
* @param {boolean=} disabled
- * @return {!UI.ContextMenuItem}
+ * @return {!Item}
*/
appendItem(label, handler, disabled) {
- const item = new UI.ContextMenuItem(this._contextMenu, 'item', label, disabled);
+ const item = new Item(this._contextMenu, 'item', label, disabled);
this._items.push(item);
this._contextMenu._setHandler(item.id(), handler);
return item;
@@ -133,10 +136,10 @@ UI.ContextMenuSection = class {
/**
* @param {!Element} element
- * @return {!UI.ContextMenuItem}
+ * @return {!Item}
*/
appendCustomItem(element) {
- const item = new UI.ContextMenuItem(this._contextMenu, 'item', '<custom>');
+ const item = new Item(this._contextMenu, 'item', '<custom>');
item._customElement = element;
this._items.push(item);
return item;
@@ -150,25 +153,28 @@ UI.ContextMenuSection = class {
appendAction(actionId, label, optional) {
const action = UI.actionRegistry.action(actionId);
if (!action) {
- if (!optional)
+ if (!optional) {
console.error(`Action ${actionId} was not defined`);
+ }
return;
}
- if (!label)
+ if (!label) {
label = action.title();
+ }
const result = this.appendItem(label, action.execute.bind(action));
const shortcut = UI.shortcutRegistry.shortcutTitleForAction(actionId);
- if (shortcut)
+ if (shortcut) {
result.setShortcut(shortcut);
+ }
}
/**
* @param {string} label
* @param {boolean=} disabled
- * @return {!UI.ContextSubMenu}
+ * @return {!SubMenu}
*/
appendSubMenuItem(label, disabled) {
- const item = new UI.ContextSubMenu(this._contextMenu, label, disabled);
+ const item = new SubMenu(this._contextMenu, label, disabled);
item._init();
this._items.push(item);
return item;
@@ -179,120 +185,120 @@ UI.ContextMenuSection = class {
* @param {function()} handler
* @param {boolean=} checked
* @param {boolean=} disabled
- * @return {!UI.ContextMenuItem}
+ * @return {!Item}
*/
appendCheckboxItem(label, handler, checked, disabled) {
- const item = new UI.ContextMenuItem(this._contextMenu, 'checkbox', label, disabled, checked);
+ const item = new Item(this._contextMenu, 'checkbox', label, disabled, checked);
this._items.push(item);
this._contextMenu._setHandler(item.id(), handler);
return item;
}
-};
+}
/**
* @unrestricted
*/
-UI.ContextSubMenu = class extends UI.ContextMenuItem {
+export class SubMenu extends Item {
/**
- * @param {?UI.ContextMenu} contextMenu
+ * @param {?ContextMenu} contextMenu
* @param {string=} label
* @param {boolean=} disabled
*/
constructor(contextMenu, label, disabled) {
super(contextMenu, 'subMenu', label, disabled);
- /** @type {!Map<string, !UI.ContextMenuSection>} */
+ /** @type {!Map<string, !Section>} */
this._sections = new Map();
- /** @type {!Array<!UI.ContextMenuSection>} */
+ /** @type {!Array<!Section>} */
this._sectionList = [];
}
_init() {
- UI.ContextMenu._groupWeights.forEach(name => this.section(name));
+ _groupWeights.forEach(name => this.section(name));
}
/**
* @param {string=} name
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
section(name) {
let section = name ? this._sections.get(name) : null;
if (!section) {
- section = new UI.ContextMenuSection(this._contextMenu);
+ section = new Section(this._contextMenu);
if (name) {
this._sections.set(name, section);
this._sectionList.push(section);
} else {
- this._sectionList.splice(UI.ContextMenu._groupWeights.indexOf('default'), 0, section);
+ this._sectionList.splice(ContextMenu._groupWeights.indexOf('default'), 0, section);
}
}
return section;
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
headerSection() {
return this.section('header');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
newSection() {
return this.section('new');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
revealSection() {
return this.section('reveal');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
clipboardSection() {
return this.section('clipboard');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
editSection() {
return this.section('edit');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
debugSection() {
return this.section('debug');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
viewSection() {
return this.section('view');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
defaultSection() {
return this.section('default');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
saveSection() {
return this.section('save');
}
/**
- * @return {!UI.ContextMenuSection}
+ * @return {!Section}
*/
footerSection() {
return this.section('footer');
@@ -308,10 +314,12 @@ UI.ContextSubMenu = class extends UI.ContextMenuItem {
const nonEmptySections = this._sectionList.filter(section => !!section._items.length);
for (const section of nonEmptySections) {
- for (const item of section._items)
+ for (const item of section._items) {
result.subItems.push(item._buildDescriptor());
- if (section !== nonEmptySections.peekLast())
+ }
+ if (section !== nonEmptySections.peekLast()) {
result.subItems.push({type: 'separator'});
+ }
}
return result;
}
@@ -322,24 +330,26 @@ UI.ContextSubMenu = class extends UI.ContextMenuItem {
appendItemsAtLocation(location) {
for (const extension of self.runtime.extensions('context-menu-item')) {
const itemLocation = extension.descriptor()['location'] || '';
- if (!itemLocation.startsWith(location + '/'))
+ if (!itemLocation.startsWith(location + '/')) {
continue;
+ }
const section = itemLocation.substr(location.length + 1);
- if (!section || section.includes('/'))
+ if (!section || section.includes('/')) {
continue;
+ }
this.section(section).appendAction(extension.descriptor()['actionId']);
}
}
-};
+}
-UI.ContextMenuItem._uniqueSectionName = 0;
+Item._uniqueSectionName = 0;
/**
* @unrestricted
*/
-UI.ContextMenu = class extends UI.ContextSubMenu {
+export default class ContextMenu extends SubMenu {
/**
* @param {!Event} event
* @param {boolean=} useSoftMenu
@@ -351,7 +361,7 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
this._contextMenu = this;
super._init();
this._defaultSection = this.defaultSection();
- /** @type {!Array.<!Promise.<!Array.<!UI.ContextMenu.Provider>>>} */
+ /** @type {!Array.<!Promise.<!Array.<!Provider>>>} */
this._pendingPromises = [];
/** @type {!Array<!Object>} */
this._pendingTargets = [];
@@ -363,17 +373,19 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
this._id = 0;
const target = event.deepElementFromPoint();
- if (target)
+ if (target) {
this.appendApplicableItems(/** @type {!Object} */ (target));
+ }
}
static initialize() {
- InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.SetUseSoftMenu, setUseSoftMenu);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.SetUseSoftMenu, setUseSoftMenu);
/**
* @param {!Common.Event} event
*/
function setUseSoftMenu(event) {
- UI.ContextMenu._useSoftMenu = /** @type {boolean} */ (event.data);
+ ContextMenu._useSoftMenu = /** @type {boolean} */ (event.data);
}
}
@@ -387,7 +399,7 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
* @param {!Event} event
*/
function handler(event) {
- const contextMenu = new UI.ContextMenu(event);
+ const contextMenu = new ContextMenu(event);
contextMenu.show();
}
}
@@ -401,23 +413,24 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
show() {
Promise.all(this._pendingPromises).then(populate.bind(this)).then(this._innerShow.bind(this));
- UI.ContextMenu._pendingMenu = this;
+ ContextMenu._pendingMenu = this;
/**
- * @param {!Array.<!Array.<!UI.ContextMenu.Provider>>} appendCallResults
- * @this {UI.ContextMenu}
+ * @param {!Array.<!Array.<!Provider>>} appendCallResults
+ * @this {ContextMenu}
*/
function populate(appendCallResults) {
- if (UI.ContextMenu._pendingMenu !== this)
+ if (ContextMenu._pendingMenu !== this) {
return;
- delete UI.ContextMenu._pendingMenu;
+ }
+ delete ContextMenu._pendingMenu;
for (let i = 0; i < appendCallResults.length; ++i) {
const providers = appendCallResults[i];
const target = this._pendingTargets[i];
for (let j = 0; j < providers.length; ++j) {
- const provider = /** @type {!UI.ContextMenu.Provider} */ (providers[j]);
+ const provider = /** @type {!Provider} */ (providers[j]);
provider.appendApplicableItems(this._event, this, target);
}
}
@@ -430,26 +443,27 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
}
discard() {
- if (this._softMenu)
+ if (this._softMenu) {
this._softMenu.discard();
+ }
}
_innerShow() {
const menuObject = this._buildMenuDescriptors();
- if (this._useSoftMenu || UI.ContextMenu._useSoftMenu || InspectorFrontendHost.isHostedMode()) {
+ if (this._useSoftMenu || ContextMenu._useSoftMenu || Host.InspectorFrontendHost.isHostedMode()) {
this._softMenu = new UI.SoftContextMenu(menuObject, this._itemSelected.bind(this));
this._softMenu.show(this._event.target.ownerDocument, new AnchorBox(this._x, this._y, 0, 0));
} else {
- InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument);
+ Host.InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument);
/**
- * @this {UI.ContextMenu}
+ * @this {ContextMenu}
*/
function listenToEvents() {
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this);
}
// showContextMenuAtPoint call above synchronously issues a clear event for previous context menu (if any),
@@ -459,12 +473,27 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
}
/**
+ * @param {number} x
+ */
+ setX(x) {
+ this._x = x;
+ }
+
+ /**
+ * @param {number} y
+ */
+ setY(y) {
+ this._y = y;
+ }
+
+ /**
* @param {number} id
* @param {function(?)} handler
*/
_setHandler(id, handler) {
- if (handler)
+ if (handler) {
this._handlers[id] = handler;
+ }
}
/**
@@ -485,40 +514,76 @@ UI.ContextMenu = class extends UI.ContextSubMenu {
* @param {string} id
*/
_itemSelected(id) {
- if (this._handlers[id])
+ if (this._handlers[id]) {
this._handlers[id].call(this);
+ }
this._menuCleared();
}
_menuCleared() {
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this);
- InspectorFrontendHost.events.removeEventListener(
- InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this);
+ Host.InspectorFrontendHost.events.removeEventListener(
+ Host.InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this);
+ }
+
+ /**
+ * @param {!Object} target
+ * @return {boolean}
+ */
+ containsTarget(target) {
+ return this._pendingTargets.indexOf(target) >= 0;
}
/**
* @param {!Object} target
*/
appendApplicableItems(target) {
- this._pendingPromises.push(self.runtime.allInstances(UI.ContextMenu.Provider, target));
+ this._pendingPromises.push(self.runtime.allInstances(Provider, target));
this._pendingTargets.push(target);
}
-};
+}
-UI.ContextMenu._groupWeights =
+export const _groupWeights =
['header', 'new', 'reveal', 'edit', 'clipboard', 'debug', 'view', 'default', 'save', 'footer'];
/**
* @interface
*/
-UI.ContextMenu.Provider = function() {};
-
-UI.ContextMenu.Provider.prototype = {
+export class Provider {
/**
* @param {!Event} event
- * @param {!UI.ContextMenu} contextMenu
+ * @param {!ContextMenu} contextMenu
* @param {!Object} target
*/
appendApplicableItems(event, contextMenu, target) {}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ContextMenu = ContextMenu;
+
+ContextMenu._groupWeights = _groupWeights;
+
+/**
+ * @constructor
+ */
+UI.ContextMenuItem = Item;
+
+/**
+ * @constructor
+ */
+UI.ContextMenuSection = Section;
+
+/** @constructor */
+UI.ContextSubMenu = SubMenu;
+
+/**
+ * @interface
+ */
+UI.ContextMenu.Provider = Provider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Dialog.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Dialog.js
index 7b146fc650b..1d2345c6cea 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Dialog.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Dialog.js
@@ -28,8 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-UI.Dialog = class extends UI.GlassPane {
-
+export default class Dialog extends UI.GlassPane {
constructor() {
super();
this.registerRequiredCSS('ui/dialog.css');
@@ -42,7 +41,7 @@ UI.Dialog = class extends UI.GlassPane {
this.hide();
event.consume(true);
});
- UI.ARIAUtils.markAsDialog(this.contentElement, true);
+ UI.ARIAUtils.markAsModalDialog(this.contentElement);
/** @type {!Map<!HTMLElement, number>} */
this._tabIndexMap = new Map();
/** @type {?UI.WidgetFocusRestorer} */
@@ -64,8 +63,9 @@ UI.Dialog = class extends UI.GlassPane {
show(where) {
const document = /** @type {!Document} */ (
where instanceof Document ? where : (where || UI.inspectorView.element).ownerDocument);
- if (UI.Dialog._instance)
+ if (UI.Dialog._instance) {
UI.Dialog._instance.hide();
+ }
UI.Dialog._instance = this;
this._disableTabIndexOnElements(document);
super.show(document);
@@ -113,8 +113,9 @@ UI.Dialog = class extends UI.GlassPane {
}
_restoreTabIndexOnElements() {
- for (const element of this._tabIndexMap.keys())
+ for (const element of this._tabIndexMap.keys()) {
element.tabIndex = /** @type {number} */ (this._tabIndexMap.get(element));
+ }
this._tabIndexMap.clear();
}
@@ -128,4 +129,13 @@ UI.Dialog = class extends UI.GlassPane {
this.hide();
}
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Dialog = Dialog;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/DropTarget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/DropTarget.js
index cb6c616fe62..5dec7461222 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/DropTarget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/DropTarget.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.DropTarget = class {
+export default class DropTarget {
/**
* @param {!Element} element
* @param {!Array<{kind: string, type: !RegExp}>} transferTypes
@@ -32,8 +32,9 @@ UI.DropTarget = class {
* @param {!Event} event
*/
_onDragEnter(event) {
- if (this._enabled && this._hasMatchingType(event))
+ if (this._enabled && this._hasMatchingType(event)) {
event.consume(true);
+ }
}
/**
@@ -45,8 +46,9 @@ UI.DropTarget = class {
const found = Array.from(event.dataTransfer.items).find(item => {
return transferType.kind === item.kind && !!transferType.type.exec(item.type);
});
- if (found)
+ if (found) {
return true;
+ }
}
return false;
}
@@ -55,12 +57,14 @@ UI.DropTarget = class {
* @param {!Event} event
*/
_onDragOver(event) {
- if (!this._enabled || !this._hasMatchingType(event))
+ if (!this._enabled || !this._hasMatchingType(event)) {
return;
+ }
event.dataTransfer.dropEffect = 'copy';
event.consume(true);
- if (this._dragMaskElement)
+ if (this._dragMaskElement) {
return;
+ }
this._dragMaskElement = this._element.createChild('div', '');
const shadowRoot = UI.createShadowRootWithCoreStyles(this._dragMaskElement, 'ui/dropTarget.css');
shadowRoot.createChild('div', 'drop-target-message').textContent = this._messageText;
@@ -74,8 +78,9 @@ UI.DropTarget = class {
_onDrop(event) {
event.consume(true);
this._removeMask();
- if (this._enabled)
+ if (this._enabled) {
this._handleDrop(event.dataTransfer);
+ }
}
/**
@@ -90,12 +95,23 @@ UI.DropTarget = class {
this._dragMaskElement.remove();
delete this._dragMaskElement;
}
-};
+}
-UI.DropTarget.Type = {
+export const Type = {
URI: {kind: 'string', type: /text\/uri-list/},
Folder: {kind: 'file', type: /$^/},
File: {kind: 'file', type: /.*/},
WebFile: {kind: 'file', type: /[\w]+/},
ImageFile: {kind: 'file', type: /image\/.*/},
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.DropTarget = DropTarget;
+
+UI.DropTarget.Type = Type;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/EmptyWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/EmptyWidget.js
index 4dee0946960..71872f840ce 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/EmptyWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/EmptyWidget.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-UI.EmptyWidget = class extends UI.VBox {
+export default class EmptyWidget extends UI.VBox {
/**
* @param {string} text
*/
@@ -65,4 +65,13 @@ UI.EmptyWidget = class extends UI.VBox {
set text(text) {
this._textElement.textContent = text;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.EmptyWidget = EmptyWidget;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
index 85b416d912b..72c29579ac8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-UI.FilterBar = class extends UI.HBox {
+export default class FilterBar extends UI.HBox {
/**
* @param {string} name
* @param {boolean=} visibleByDefault
@@ -59,12 +59,12 @@ UI.FilterBar = class extends UI.HBox {
}
/**
- * @param {!UI.FilterUI} filter
+ * @param {!FilterUI} filter
*/
addFilter(filter) {
this._filters.push(filter);
this.element.appendChild(filter.element());
- filter.addEventListener(UI.FilterUI.Events.FilterChanged, this._filterChanged, this);
+ filter.addEventListener(FilterUI.Events.FilterChanged, this._filterChanged, this);
this._updateFilterButton();
}
@@ -99,8 +99,9 @@ UI.FilterBar = class extends UI.HBox {
}
_updateFilterBar() {
- if (!this.parentWidget() || this._showingWidget)
+ if (!this.parentWidget() || this._showingWidget) {
return;
+ }
if (this.visible()) {
this._showingWidget = true;
this.showWidget();
@@ -115,8 +116,8 @@ UI.FilterBar = class extends UI.HBox {
*/
focus() {
for (let i = 0; i < this._filters.length; ++i) {
- if (this._filters[i] instanceof UI.TextFilterUI) {
- const textFilterUI = /** @type {!UI.TextFilterUI} */ (this._filters[i]);
+ if (this._filters[i] instanceof TextFilterUI) {
+ const textFilterUI = /** @type {!TextFilterUI} */ (this._filters[i]);
textFilterUI.focus();
break;
}
@@ -125,8 +126,9 @@ UI.FilterBar = class extends UI.HBox {
_updateFilterButton() {
let isActive = false;
- for (const filter of this._filters)
+ for (const filter of this._filters) {
isActive = isActive || filter.isActive();
+ }
this._filterButton.setDefaultWithRedColor(isActive);
this._filterButton.setToggleWithRedColor(isActive);
}
@@ -144,36 +146,34 @@ UI.FilterBar = class extends UI.HBox {
visible() {
return this._alwaysShowFilters || (this._stateSetting.get() && this._enabled);
}
-};
+}
/**
* @interface
- * @extends {Common.EventTarget}
*/
-UI.FilterUI = function() {};
-
-/** @enum {symbol} */
-UI.FilterUI.Events = {
- FilterChanged: Symbol('FilterChanged')
-};
-
-UI.FilterUI.prototype = {
+export class FilterUI extends Common.EventTarget {
/**
* @return {boolean}
*/
- isActive() {},
+ isActive() {
+ }
/**
* @return {!Element}
*/
element() {}
+}
+
+/** @enum {symbol} */
+FilterUI.Events = {
+ FilterChanged: Symbol('FilterChanged')
};
/**
* @implements {UI.FilterUI}
* @unrestricted
*/
-UI.TextFilterUI = class extends Common.Object {
+export class TextFilterUI extends Common.Object {
constructor() {
super();
this._filterElement = createElement('div');
@@ -199,8 +199,9 @@ UI.TextFilterUI = class extends Common.Object {
* @return {!Promise<!UI.SuggestBox.Suggestions>}
*/
_completions(expression, prefix, force) {
- if (this._suggestionProvider)
+ if (this._suggestionProvider) {
return this._suggestionProvider(expression, prefix, force);
+ }
return Promise.resolve([]);
}
/**
@@ -247,15 +248,15 @@ UI.TextFilterUI = class extends Common.Object {
}
_valueChanged() {
- this.dispatchEventToListeners(UI.FilterUI.Events.FilterChanged, null);
+ this.dispatchEventToListeners(FilterUI.Events.FilterChanged, null);
}
-};
+}
/**
- * @implements {UI.FilterUI}
+ * @implements {FilterUI}
* @unrestricted
*/
-UI.NamedBitSetFilterUI = class extends Common.Object {
+export class NamedBitSetFilterUI extends Common.Object {
/**
* @param {!Array.<!UI.NamedBitSetFilterUI.Item>} items
* @param {!Common.Setting=} setting
@@ -272,24 +273,25 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
this._allowedTypes = {};
/** @type {!Array.<!Element>} */
this._typeFilterElements = [];
- this._addBit(UI.NamedBitSetFilterUI.ALL_TYPES, Common.UIString('All'));
+ this._addBit(NamedBitSetFilterUI.ALL_TYPES, Common.UIString('All'));
this._typeFilterElements[0].tabIndex = 0;
this._filtersElement.createChild('div', 'filter-bitset-filter-divider');
- for (let i = 0; i < items.length; ++i)
+ for (let i = 0; i < items.length; ++i) {
this._addBit(items[i].name, items[i].label, items[i].title);
+ }
if (setting) {
this._setting = setting;
setting.addChangeListener(this._settingChanged.bind(this));
this._settingChanged();
} else {
- this._toggleTypeFilter(UI.NamedBitSetFilterUI.ALL_TYPES, false /* allowMultiSelect */);
+ this._toggleTypeFilter(NamedBitSetFilterUI.ALL_TYPES, false /* allowMultiSelect */);
}
}
reset() {
- this._toggleTypeFilter(UI.NamedBitSetFilterUI.ALL_TYPES, false /* allowMultiSelect */);
+ this._toggleTypeFilter(NamedBitSetFilterUI.ALL_TYPES, false /* allowMultiSelect */);
}
/**
@@ -297,7 +299,7 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
* @return {boolean}
*/
isActive() {
- return !this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES];
+ return !this._allowedTypes[NamedBitSetFilterUI.ALL_TYPES];
}
/**
@@ -313,23 +315,24 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
* @return {boolean}
*/
accept(typeName) {
- return !!this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES] || !!this._allowedTypes[typeName];
+ return !!this._allowedTypes[NamedBitSetFilterUI.ALL_TYPES] || !!this._allowedTypes[typeName];
}
_settingChanged() {
const allowedTypes = this._setting.get();
this._allowedTypes = {};
for (const element of this._typeFilterElements) {
- if (allowedTypes[element.typeName])
+ if (allowedTypes[element.typeName]) {
this._allowedTypes[element.typeName] = true;
+ }
}
this._update();
}
_update() {
- if ((Object.keys(this._allowedTypes).length === 0) || this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES]) {
+ if ((Object.keys(this._allowedTypes).length === 0) || this._allowedTypes[NamedBitSetFilterUI.ALL_TYPES]) {
this._allowedTypes = {};
- this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES] = true;
+ this._allowedTypes[NamedBitSetFilterUI.ALL_TYPES] = true;
}
for (const element of this._typeFilterElements) {
const typeName = element.typeName;
@@ -337,7 +340,7 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
element.classList.toggle('selected', active);
UI.ARIAUtils.setSelected(element, active);
}
- this.dispatchEventToListeners(UI.FilterUI.Events.FilterChanged, null);
+ this.dispatchEventToListeners(FilterUI.Events.FilterChanged, null);
}
/**
@@ -351,8 +354,9 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
typeFilterElement.typeName = name;
typeFilterElement.createTextChild(label);
UI.ARIAUtils.markAsOption(typeFilterElement);
- if (title)
+ if (title) {
typeFilterElement.title = title;
+ }
typeFilterElement.addEventListener('click', this._onTypeFilterClicked.bind(this), false);
typeFilterElement.addEventListener('keydown', this._onTypeFilterKeydown.bind(this), false);
this._typeFilterElements.push(typeFilterElement);
@@ -363,10 +367,11 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
*/
_onTypeFilterClicked(e) {
let toggle;
- if (Host.isMac())
+ if (Host.isMac()) {
toggle = e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey;
- else
+ } else {
toggle = e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey;
+ }
this._toggleTypeFilter(e.target.typeName, toggle);
}
@@ -375,23 +380,21 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
*/
_onTypeFilterKeydown(event) {
const element = /** @type {?Element} */ (event.target);
- if (!element)
+ if (!element) {
return;
+ }
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
- if (this._keyFocusNextBit(element, true)) {
+ if (this._keyFocusNextBit(element, true /* selectPrevious */)) {
event.consume(true);
- return;
}
} else if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
- if (this._keyFocusNextBit(element, false)) {
+ if (this._keyFocusNextBit(element, false /* selectPrevious */)) {
event.consume(true);
- return;
}
- } else if (!isEnterOrSpaceKey(event)) {
- return;
+ } else if (isEnterOrSpaceKey(event)) {
+ this._onTypeFilterClicked(event);
}
-
- this._onTypeFilterClicked(event);
}
/**
@@ -401,11 +404,13 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
*/
_keyFocusNextBit(target, selectPrevious) {
const index = this._typeFilterElements.indexOf(target);
- if (index === -1)
+ if (index === -1) {
return false;
+ }
const nextIndex = selectPrevious ? index - 1 : index + 1;
- if (nextIndex < 0 || nextIndex >= this._typeFilterElements.length)
+ if (nextIndex < 0 || nextIndex >= this._typeFilterElements.length) {
return false;
+ }
const nextElement = this._typeFilterElements[nextIndex];
nextElement.tabIndex = 0;
@@ -419,30 +424,29 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
* @param {boolean} allowMultiSelect
*/
_toggleTypeFilter(typeName, allowMultiSelect) {
- if (allowMultiSelect && typeName !== UI.NamedBitSetFilterUI.ALL_TYPES)
- this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES] = false;
- else
+ if (allowMultiSelect && typeName !== NamedBitSetFilterUI.ALL_TYPES) {
+ this._allowedTypes[NamedBitSetFilterUI.ALL_TYPES] = false;
+ } else {
this._allowedTypes = {};
+ }
this._allowedTypes[typeName] = !this._allowedTypes[typeName];
- if (this._setting)
+ if (this._setting) {
this._setting.set(this._allowedTypes);
- else
+ } else {
this._update();
+ }
}
-};
-
-/** @typedef {{name: string, label: string, title: (string|undefined)}} */
-UI.NamedBitSetFilterUI.Item;
+}
-UI.NamedBitSetFilterUI.ALL_TYPES = 'all';
+NamedBitSetFilterUI.ALL_TYPES = 'all';
/**
* @implements {UI.FilterUI}
* @unrestricted
*/
-UI.CheckboxFilterUI = class extends Common.Object {
+export class CheckboxFilterUI extends Common.Object {
/**
* @param {string} className
* @param {string} title
@@ -456,10 +460,11 @@ UI.CheckboxFilterUI = class extends Common.Object {
this._label = UI.CheckboxLabel.create(title);
this._filterElement.appendChild(this._label);
this._checkboxElement = this._label.checkboxElement;
- if (setting)
+ if (setting) {
UI.SettingsUI.bindCheckbox(this._checkboxElement, setting);
- else
+ } else {
this._checkboxElement.checked = true;
+ }
this._checkboxElement.addEventListener('change', this._fireUpdated.bind(this), false);
}
@@ -501,7 +506,7 @@ UI.CheckboxFilterUI = class extends Common.Object {
}
_fireUpdated() {
- this.dispatchEventToListeners(UI.FilterUI.Events.FilterChanged, null);
+ this.dispatchEventToListeners(FilterUI.Events.FilterChanged, null);
}
/**
@@ -512,4 +517,28 @@ UI.CheckboxFilterUI = class extends Common.Object {
this._label.backgroundColor = backgroundColor;
this._label.borderColor = borderColor;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.FilterBar = FilterBar;
+
+/** @interface */
+UI.FilterUI = FilterUI;
+
+/** @constructor */
+UI.TextFilterUI = TextFilterUI;
+
+/** @constructor */
+UI.NamedBitSetFilterUI = NamedBitSetFilterUI;
+
+/** @constructor */
+UI.CheckboxFilterUI = CheckboxFilterUI;
+
+/** @typedef {{name: string, label: string, title: (string|undefined)}} */
+UI.NamedBitSetFilterUI.Item; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterSuggestionBuilder.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterSuggestionBuilder.js
index 9551ba29a9f..ce6261d9631 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterSuggestionBuilder.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterSuggestionBuilder.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.FilterSuggestionBuilder = class {
+export default class FilterSuggestionBuilder {
/**
* @param {!Array<string>} keys
* @param {function(string, !Array<string>)=} valueSorter
@@ -21,12 +21,14 @@ UI.FilterSuggestionBuilder = class {
* @return {!Promise<!UI.SuggestBox.Suggestions>}
*/
completions(expression, prefix, force) {
- if (!prefix && !force)
+ if (!prefix && !force) {
return Promise.resolve([]);
+ }
const negative = prefix.startsWith('-');
- if (negative)
+ if (negative) {
prefix = prefix.substring(1);
+ }
const modifier = negative ? '-' : '';
const valueDelimiterIndex = prefix.indexOf(':');
@@ -34,8 +36,9 @@ UI.FilterSuggestionBuilder = class {
if (valueDelimiterIndex === -1) {
const matcher = new RegExp('^' + prefix.escapeForRegExp(), 'i');
for (const key of this._keys) {
- if (matcher.test(key))
+ if (matcher.test(key)) {
suggestions.push({text: modifier + key + ':'});
+ }
}
} else {
const key = prefix.substring(0, valueDelimiterIndex).toLowerCase();
@@ -44,8 +47,9 @@ UI.FilterSuggestionBuilder = class {
const values = Array.from(this._valuesMap.get(key) || new Set());
this._valueSorter(key, values);
for (const item of values) {
- if (matcher.test(item) && (item !== value))
+ if (matcher.test(item) && (item !== value)) {
suggestions.push({text: modifier + key + ':' + item});
+ }
}
}
return Promise.resolve(suggestions);
@@ -56,15 +60,26 @@ UI.FilterSuggestionBuilder = class {
* @param {?string=} value
*/
addItem(key, value) {
- if (!value)
+ if (!value) {
return;
+ }
- if (!this._valuesMap.get(key))
+ if (!this._valuesMap.get(key)) {
this._valuesMap.set(key, /** @type {!Set<string>} */ (new Set()));
+ }
this._valuesMap.get(key).add(value);
}
clear() {
this._valuesMap.clear();
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.FilterSuggestionBuilder = FilterSuggestionBuilder;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js
index 6baa49a8500..76653b7d1d7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js
@@ -4,10 +4,10 @@
/**
* @unrestricted
*/
-UI.ForwardedInputEventHandler = class {
+export default class ForwardedInputEventHandler {
constructor() {
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.KeyEventUnhandled, this._onKeyEventUnhandled, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, this._onKeyEventUnhandled, this);
}
/**
@@ -20,14 +20,24 @@ UI.ForwardedInputEventHandler = class {
const keyCode = /** @type {number} */ (data.keyCode);
const modifiers = /** @type {number} */ (data.modifiers);
- if (type !== 'keydown')
+ if (type !== 'keydown') {
return;
+ }
UI.context.setFlavor(UI.ShortcutRegistry.ForwardedShortcut, UI.ShortcutRegistry.ForwardedShortcut.instance);
UI.shortcutRegistry.handleKey(UI.KeyboardShortcut.makeKey(keyCode, modifiers), key);
UI.context.setFlavor(UI.ShortcutRegistry.ForwardedShortcut, null);
}
-};
+}
-/** @type {!UI.ForwardedInputEventHandler} */
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ForwardedInputEventHandler = ForwardedInputEventHandler;
+
+/** @type {!ForwardedInputEventHandler} */
UI.forwardedEventHandler = new UI.ForwardedInputEventHandler();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
index 3911e9be852..0f72689ec7d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.Fragment = class {
+export default class Fragment {
/**
* @param {!Element} element
*/
@@ -31,29 +31,29 @@ UI.Fragment = class {
/**
* @param {!Array<string>} strings
* @param {...*} values
- * @return {!UI.Fragment}
+ * @return {!Fragment}
*/
static build(strings, ...values) {
- return UI.Fragment._render(UI.Fragment._template(strings), values);
+ return Fragment._render(Fragment._template(strings), values);
}
/**
* @param {!Array<string>} strings
* @param {...*} values
- * @return {!UI.Fragment}
+ * @return {!Fragment}
*/
static cached(strings, ...values) {
- let template = UI.Fragment._templateCache.get(strings);
+ let template = Fragment._templateCache.get(strings);
if (!template) {
- template = UI.Fragment._template(strings);
- UI.Fragment._templateCache.set(strings, template);
+ template = Fragment._template(strings);
+ Fragment._templateCache.set(strings, template);
}
- return UI.Fragment._render(template, values);
+ return Fragment._render(template, values);
}
/**
* @param {!Array<string>} strings
- * @return {!UI.Fragment._Template}
+ * @return {!Fragment._Template}
* @suppressGlobalPropertiesCheck
*/
static _template(strings) {
@@ -63,11 +63,12 @@ UI.Fragment = class {
html += strings[i];
const close = strings[i].lastIndexOf('>');
const open = strings[i].indexOf('<', close + 1);
- if (close !== -1 && open === -1)
+ if (close !== -1 && open === -1) {
insideText = true;
- else if (open !== -1)
+ } else if (open !== -1) {
insideText = false;
- html += insideText ? UI.Fragment._textMarker : UI.Fragment._attributeMarker(i);
+ }
+ html += insideText ? Fragment._textMarker : Fragment._attributeMarker(i);
}
html += strings[strings.length - 1];
@@ -92,29 +93,32 @@ UI.Fragment = class {
for (let i = 0; i < node.attributes.length; i++) {
const name = node.attributes[i].name;
- if (!UI.Fragment._attributeMarkerRegex.test(name) &&
- !UI.Fragment._attributeMarkerRegex.test(node.attributes[i].value))
+ if (!Fragment._attributeMarkerRegex.test(name) &&
+ !Fragment._attributeMarkerRegex.test(node.attributes[i].value)) {
continue;
+ }
attributesToRemove.push(name);
nodesToMark.push(node);
const bind = {attr: {index: valueIndex}};
- bind.attr.names = name.split(UI.Fragment._attributeMarkerRegex);
+ bind.attr.names = name.split(Fragment._attributeMarkerRegex);
valueIndex += bind.attr.names.length - 1;
- bind.attr.values = node.attributes[i].value.split(UI.Fragment._attributeMarkerRegex);
+ bind.attr.values = node.attributes[i].value.split(Fragment._attributeMarkerRegex);
valueIndex += bind.attr.values.length - 1;
binds.push(bind);
}
- for (let i = 0; i < attributesToRemove.length; i++)
+ for (let i = 0; i < attributesToRemove.length; i++) {
node.removeAttribute(attributesToRemove[i]);
+ }
}
- if (node.nodeType === Node.TEXT_NODE && node.data.indexOf(UI.Fragment._textMarker) !== -1) {
- const texts = node.data.split(UI.Fragment._textMarkerRegex);
+ if (node.nodeType === Node.TEXT_NODE && node.data.indexOf(Fragment._textMarker) !== -1) {
+ const texts = node.data.split(Fragment._textMarkerRegex);
node.data = texts[texts.length - 1];
for (let i = 0; i < texts.length - 1; i++) {
- if (texts[i])
+ if (texts[i]) {
node.parentNode.insertBefore(createTextNode(texts[i]), node);
+ }
const nodeToReplace = createElement('span');
nodesToMark.push(nodeToReplace);
binds.push({replaceNodeIndex: valueIndex++});
@@ -124,32 +128,35 @@ UI.Fragment = class {
if (node.nodeType === Node.TEXT_NODE &&
(!node.previousSibling || node.previousSibling.nodeType === Node.ELEMENT_NODE) &&
- (!node.nextSibling || node.nextSibling.nodeType === Node.ELEMENT_NODE) && /^\s*$/.test(node.data))
+ (!node.nextSibling || node.nextSibling.nodeType === Node.ELEMENT_NODE) && /^\s*$/.test(node.data)) {
emptyTextNodes.push(node);
+ }
}
- for (let i = 0; i < nodesToMark.length; i++)
- nodesToMark[i].classList.add(UI.Fragment._class(i));
+ for (let i = 0; i < nodesToMark.length; i++) {
+ nodesToMark[i].classList.add(Fragment._class(i));
+ }
- for (const emptyTextNode of emptyTextNodes)
+ for (const emptyTextNode of emptyTextNodes) {
emptyTextNode.remove();
+ }
return {template: template, binds: binds};
}
/**
- * @param {!UI.Fragment._Template} template
+ * @param {!Fragment._Template} template
* @param {!Array<*>} values
- * @return {!UI.Fragment}
+ * @return {!Fragment}
*/
static _render(template, values) {
const content = template.template.ownerDocument.importNode(template.template.content, true);
const resultElement =
/** @type {!Element} */ (content.firstChild === content.lastChild ? content.firstChild : content);
- const result = new UI.Fragment(resultElement);
+ const result = new Fragment(resultElement);
const boundElements = [];
for (let i = 0; i < template.binds.length; i++) {
- const className = UI.Fragment._class(i);
+ const className = Fragment._class(i);
const element = /** @type {!Element} */ (content.querySelector('.' + className));
element.classList.remove(className);
boundElements.push(element);
@@ -194,58 +201,76 @@ UI.Fragment = class {
* @return {!Node}
*/
static _nodeForValue(value) {
- if (value instanceof Node)
+ if (value instanceof Node) {
return value;
- if (value instanceof UI.Fragment)
+ }
+ if (value instanceof Fragment) {
return value._element;
+ }
if (Array.isArray(value)) {
const node = createDocumentFragment();
- for (const v of value)
+ for (const v of value) {
node.appendChild(this._nodeForValue(v));
+ }
return node;
}
return createTextNode('' + value);
}
-};
+}
-/**
- * @typedef {!{
- * template: !Element,
- * binds: !Array<!UI.Fragment._Bind>
- * }}
- */
-UI.Fragment._Template;
+export const _textMarker = '{{template-text}}';
+export const _textMarkerRegex = /{{template-text}}/;
+export const _attributeMarker = index => 'template-attribute' + index;
+export const _attributeMarkerRegex = /template-attribute\d+/;
+export const _class = index => 'template-class-' + index;
+export const _templateCache = new Map();
/**
- * @typedef {!{
- * elementId: (string|undefined),
- *
- * attr: (!{
- * index: number,
- * names: !Array<string>,
- * values: !Array<string>
- * }|undefined),
- *
- * replaceNodeIndex: (number|undefined)
- * }}
+ * @param {!Array<string>} strings
+ * @param {...*} vararg
+ * @return {!Element}
*/
-UI.Fragment._Bind;
+export const html = (strings, ...vararg) => {
+ return Fragment.cached(strings, ...vararg).element();
+};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
-UI.Fragment._textMarker = '{{template-text}}';
-UI.Fragment._textMarkerRegex = /{{template-text}}/;
+/* Legacy exported object*/
+UI = UI || {};
-UI.Fragment._attributeMarker = index => 'template-attribute' + index;
-UI.Fragment._attributeMarkerRegex = /template-attribute\d+/;
+/** @constructor */
+UI.Fragment = Fragment;
-UI.Fragment._class = index => 'template-class-' + index;
+UI.Fragment._textMarker = _textMarker;
+UI.Fragment._textMarkerRegex = _textMarkerRegex;
+UI.Fragment._attributeMarker = _attributeMarker;
+UI.Fragment._attributeMarkerRegex = _attributeMarkerRegex;
+UI.Fragment._class = _class;
+UI.Fragment._templateCache = _templateCache;
-UI.Fragment._templateCache = new Map();
+UI.html = html;
/**
- * @param {!Array<string>} strings
- * @param {...*} vararg
- * @return {!Element}
- */
-UI.html = (strings, ...vararg) => {
- return UI.Fragment.cached(strings, ...vararg).element();
-};
+ * @typedef {!{
+ * template: !Element,
+ * binds: !Array<!Fragment._Bind>
+ * }}
+ */
+UI.Fragment._Template;
+
+/**
+ * @typedef {!{
+ * elementId: (string|undefined),
+ *
+ * attr: (!{
+ * index: number,
+ * names: !Array<string>,
+ * values: !Array<string>
+ * }|undefined),
+ *
+ * replaceNodeIndex: (number|undefined)
+ * }}
+ */
+UI.Fragment._Bind; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Geometry.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Geometry.js
index 4f5bf4a3558..632a6ca1753 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Geometry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Geometry.js
@@ -27,17 +27,20 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-UI.Geometry = {};
+
+const Geometry = {};
+
+export default Geometry;
/**
* @type {number}
*/
-UI.Geometry._Eps = 1e-5;
+export const _Eps = 1e-5;
/**
* @unrestricted
*/
-UI.Geometry.Vector = class {
+export class Vector {
/**
* @param {number} x
* @param {number} y
@@ -58,19 +61,20 @@ UI.Geometry.Vector = class {
normalize() {
const length = this.length();
- if (length <= UI.Geometry._Eps)
+ if (length <= UI.Geometry._Eps) {
return;
+ }
this.x /= length;
this.y /= length;
this.z /= length;
}
-};
+}
/**
* @unrestricted
*/
-UI.Geometry.Point = class {
+export class Point {
/**
* @param {number} x
* @param {number} y
@@ -81,7 +85,7 @@ UI.Geometry.Point = class {
}
/**
- * @param {!UI.Geometry.Point} p
+ * @param {!Point} p
* @return {number}
*/
distanceTo(p) {
@@ -89,21 +93,22 @@ UI.Geometry.Point = class {
}
/**
- * @param {!UI.Geometry.Point} line
- * @return {!UI.Geometry.Point}
+ * @param {!Point} line
+ * @return {!Point}
*/
projectOn(line) {
- if (line.x === 0 && line.y === 0)
- return new UI.Geometry.Point(0, 0);
+ if (line.x === 0 && line.y === 0) {
+ return new Point(0, 0);
+ }
return line.scale((this.x * line.x + this.y * line.y) / (Math.pow(line.x, 2) + Math.pow(line.y, 2)));
}
/**
* @param {number} scalar
- * @return {!UI.Geometry.Point}
+ * @return {!Point}
*/
scale(scalar) {
- return new UI.Geometry.Point(this.x * scalar, this.y * scalar);
+ return new Point(this.x * scalar, this.y * scalar);
}
/**
@@ -113,15 +118,15 @@ UI.Geometry.Point = class {
toString() {
return Math.round(this.x * 100) / 100 + ', ' + Math.round(this.y * 100) / 100;
}
-};
+}
/**
* @unrestricted
*/
-UI.Geometry.CubicBezier = class {
+export class CubicBezier {
/**
- * @param {!UI.Geometry.Point} point1
- * @param {!UI.Geometry.Point} point2
+ * @param {!Point} point1
+ * @param {!Point} point2
*/
constructor(point1, point2) {
this.controlPoints = [point1, point2];
@@ -129,26 +134,27 @@ UI.Geometry.CubicBezier = class {
/**
* @param {string} text
- * @return {?UI.Geometry.CubicBezier}
+ * @return {?CubicBezier}
*/
static parse(text) {
- const keywordValues = UI.Geometry.CubicBezier.KeywordValues;
+ const keywordValues = CubicBezier.KeywordValues;
const value = text.toLowerCase().replace(/\s+/g, '');
- if (Object.keys(keywordValues).indexOf(value) !== -1)
- return UI.Geometry.CubicBezier.parse(keywordValues[value]);
+ if (Object.keys(keywordValues).indexOf(value) !== -1) {
+ return CubicBezier.parse(keywordValues[value]);
+ }
const bezierRegex = /^cubic-bezier\(([^,]+),([^,]+),([^,]+),([^,]+)\)$/;
const match = value.match(bezierRegex);
if (match) {
- const control1 = new UI.Geometry.Point(parseFloat(match[1]), parseFloat(match[2]));
- const control2 = new UI.Geometry.Point(parseFloat(match[3]), parseFloat(match[4]));
- return new UI.Geometry.CubicBezier(control1, control2);
+ const control1 = new Point(parseFloat(match[1]), parseFloat(match[2]));
+ const control2 = new Point(parseFloat(match[3]), parseFloat(match[4]));
+ return new CubicBezier(control1, control2);
}
return null;
}
/**
* @param {number} t
- * @return {!UI.Geometry.Point}
+ * @return {!Point}
*/
evaluateAt(t) {
/**
@@ -162,7 +168,7 @@ UI.Geometry.CubicBezier = class {
const x = evaluate(this.controlPoints[0].x, this.controlPoints[1].x, t);
const y = evaluate(this.controlPoints[0].y, this.controlPoints[1].y, t);
- return new UI.Geometry.Point(x, y);
+ return new Point(x, y);
}
/**
@@ -170,19 +176,20 @@ UI.Geometry.CubicBezier = class {
*/
asCSSText() {
const raw = 'cubic-bezier(' + this.controlPoints.join(', ') + ')';
- const keywordValues = UI.Geometry.CubicBezier.KeywordValues;
+ const keywordValues = CubicBezier.KeywordValues;
for (const keyword in keywordValues) {
- if (raw === keywordValues[keyword])
+ if (raw === keywordValues[keyword]) {
return keyword;
+ }
}
return raw;
}
-};
+}
/** @type {!RegExp} */
-UI.Geometry.CubicBezier.Regex = /((cubic-bezier\([^)]+\))|\b(linear|ease-in-out|ease-in|ease-out|ease)\b)/g;
+CubicBezier.Regex = /((cubic-bezier\([^)]+\))|\b(linear|ease-in-out|ease-in|ease-out|ease)\b)/g;
-UI.Geometry.CubicBezier.KeywordValues = {
+CubicBezier.KeywordValues = {
'linear': 'cubic-bezier(0, 0, 1, 1)',
'ease': 'cubic-bezier(0.25, 0.1, 0.25, 1)',
'ease-in': 'cubic-bezier(0.42, 0, 1, 1)',
@@ -190,11 +197,10 @@ UI.Geometry.CubicBezier.KeywordValues = {
'ease-out': 'cubic-bezier(0, 0, 0.58, 1)'
};
-
/**
* @unrestricted
*/
-UI.Geometry.EulerAngles = class {
+export class EulerAngles {
/**
* @param {number} alpha
* @param {number} beta
@@ -208,7 +214,7 @@ UI.Geometry.EulerAngles = class {
/**
* @param {!CSSMatrix} rotationMatrix
- * @return {!UI.Geometry.EulerAngles}
+ * @return {!EulerAngles}
*/
static fromRotationMatrix(rotationMatrix) {
const beta = Math.atan2(rotationMatrix.m23, rotationMatrix.m33);
@@ -216,91 +222,91 @@ UI.Geometry.EulerAngles = class {
-rotationMatrix.m13,
Math.sqrt(rotationMatrix.m11 * rotationMatrix.m11 + rotationMatrix.m12 * rotationMatrix.m12));
const alpha = Math.atan2(rotationMatrix.m12, rotationMatrix.m11);
- return new UI.Geometry.EulerAngles(
- UI.Geometry.radiansToDegrees(alpha), UI.Geometry.radiansToDegrees(beta), UI.Geometry.radiansToDegrees(gamma));
+ return new EulerAngles(radiansToDegrees(alpha), radiansToDegrees(beta), radiansToDegrees(gamma));
}
/**
* @return {string}
*/
toRotate3DString() {
- const gammaAxisY = -Math.sin(UI.Geometry.degreesToRadians(this.beta));
- const gammaAxisZ = Math.cos(UI.Geometry.degreesToRadians(this.beta));
+ const gammaAxisY = -Math.sin(degreesToRadians(this.beta));
+ const gammaAxisZ = Math.cos(degreesToRadians(this.beta));
const axis = {alpha: [0, 1, 0], beta: [-1, 0, 0], gamma: [0, gammaAxisY, gammaAxisZ]};
return 'rotate3d(' + axis.alpha.join(',') + ',' + this.alpha + 'deg) ' +
'rotate3d(' + axis.beta.join(',') + ',' + this.beta + 'deg) ' +
'rotate3d(' + axis.gamma.join(',') + ',' + this.gamma + 'deg)';
}
-};
-
+}
/**
- * @param {!UI.Geometry.Vector} u
- * @param {!UI.Geometry.Vector} v
+ * @param {!Vector} u
+ * @param {!Vector} v
* @return {number}
*/
-UI.Geometry.scalarProduct = function(u, v) {
+export const scalarProduct = function(u, v) {
return u.x * v.x + u.y * v.y + u.z * v.z;
};
/**
- * @param {!UI.Geometry.Vector} u
- * @param {!UI.Geometry.Vector} v
- * @return {!UI.Geometry.Vector}
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {!Vector}
*/
-UI.Geometry.crossProduct = function(u, v) {
+export const crossProduct = function(u, v) {
const x = u.y * v.z - u.z * v.y;
const y = u.z * v.x - u.x * v.z;
const z = u.x * v.y - u.y * v.x;
- return new UI.Geometry.Vector(x, y, z);
+ return new Vector(x, y, z);
};
/**
- * @param {!UI.Geometry.Vector} u
- * @param {!UI.Geometry.Vector} v
- * @return {!UI.Geometry.Vector}
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {!Vector}
*/
-UI.Geometry.subtract = function(u, v) {
+export const subtract = function(u, v) {
const x = u.x - v.x;
const y = u.y - v.y;
const z = u.z - v.z;
- return new UI.Geometry.Vector(x, y, z);
+ return new Vector(x, y, z);
};
/**
- * @param {!UI.Geometry.Vector} v
+ * @param {!Vector} v
* @param {!CSSMatrix} m
- * @return {!UI.Geometry.Vector}
+ * @return {!Vector}
*/
-UI.Geometry.multiplyVectorByMatrixAndNormalize = function(v, m) {
+export const multiplyVectorByMatrixAndNormalize = function(v, m) {
const t = v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + m.m44;
const x = (v.x * m.m11 + v.y * m.m21 + v.z * m.m31 + m.m41) / t;
const y = (v.x * m.m12 + v.y * m.m22 + v.z * m.m32 + m.m42) / t;
const z = (v.x * m.m13 + v.y * m.m23 + v.z * m.m33 + m.m43) / t;
- return new UI.Geometry.Vector(x, y, z);
+ return new Vector(x, y, z);
};
/**
- * @param {!UI.Geometry.Vector} u
- * @param {!UI.Geometry.Vector} v
+ * @param {!Vector} u
+ * @param {!Vector} v
* @return {number}
*/
-UI.Geometry.calculateAngle = function(u, v) {
+export const calculateAngle = function(u, v) {
const uLength = u.length();
const vLength = v.length();
- if (uLength <= UI.Geometry._Eps || vLength <= UI.Geometry._Eps)
+ if (uLength <= _Eps || vLength <= _Eps) {
return 0;
- const cos = UI.Geometry.scalarProduct(u, v) / uLength / vLength;
- if (Math.abs(cos) > 1)
+ }
+ const cos = scalarProduct(u, v) / uLength / vLength;
+ if (Math.abs(cos) > 1) {
return 0;
- return UI.Geometry.radiansToDegrees(Math.acos(cos));
+ }
+ return radiansToDegrees(Math.acos(cos));
};
/**
* @param {number} deg
* @return {number}
*/
-UI.Geometry.degreesToRadians = function(deg) {
+export const degreesToRadians = function(deg) {
return deg * Math.PI / 180;
};
@@ -308,7 +314,7 @@ UI.Geometry.degreesToRadians = function(deg) {
* @param {number} rad
* @return {number}
*/
-UI.Geometry.radiansToDegrees = function(rad) {
+export const radiansToDegrees = function(rad) {
return rad * 180 / Math.PI;
};
@@ -318,13 +324,15 @@ UI.Geometry.radiansToDegrees = function(rad) {
* @param {{minX: number, maxX: number, minY: number, maxY: number}=} aggregateBounds
* @return {!{minX: number, maxX: number, minY: number, maxY: number}}
*/
-UI.Geometry.boundsForTransformedPoints = function(matrix, points, aggregateBounds) {
- if (!aggregateBounds)
+export const boundsForTransformedPoints = function(matrix, points, aggregateBounds) {
+ if (!aggregateBounds) {
aggregateBounds = {minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity};
- if (points.length % 3)
+ }
+ if (points.length % 3) {
console.assert('Invalid size of points array');
+ }
for (let p = 0; p < points.length; p += 3) {
- let vector = new UI.Geometry.Vector(points[p], points[p + 1], points[p + 2]);
+ let vector = new Vector(points[p], points[p + 1], points[p + 2]);
vector = UI.Geometry.multiplyVectorByMatrixAndNormalize(vector, matrix);
aggregateBounds.minX = Math.min(aggregateBounds.minX, vector.x);
aggregateBounds.maxX = Math.max(aggregateBounds.maxX, vector.x);
@@ -337,7 +345,7 @@ UI.Geometry.boundsForTransformedPoints = function(matrix, points, aggregateBound
/**
* @unrestricted
*/
-UI.Size = class {
+export class Size {
/**
* @param {number} width
* @param {number} height
@@ -348,68 +356,69 @@ UI.Size = class {
}
/**
- * @param {?UI.Size} size
- * @return {!UI.Size}
+ * @param {?Size} size
+ * @return {!Size}
*/
clipTo(size) {
- if (!size)
+ if (!size) {
return this;
- return new UI.Size(Math.min(this.width, size.width), Math.min(this.height, size.height));
+ }
+ return new Size(Math.min(this.width, size.width), Math.min(this.height, size.height));
}
/**
* @param {number} scale
- * @return {!UI.Size}
+ * @return {!Size}
*/
scale(scale) {
- return new UI.Size(this.width * scale, this.height * scale);
+ return new Size(this.width * scale, this.height * scale);
}
-};
-/**
- * @param {?UI.Size} size
- * @return {boolean}
- */
-UI.Size.prototype.isEqual = function(size) {
- return !!size && this.width === size.width && this.height === size.height;
-};
+ /**
+ * @param {?Size} size
+ * @return {boolean}
+ */
+ isEqual(size) {
+ return !!size && this.width === size.width && this.height === size.height;
+ }
-/**
- * @param {!UI.Size|number} size
- * @return {!UI.Size}
+ /**
+ * @param {!Size|number} size
+ * @return {!Size}
*/
-UI.Size.prototype.widthToMax = function(size) {
- return new UI.Size(Math.max(this.width, (typeof size === 'number' ? size : size.width)), this.height);
-};
+ widthToMax(size) {
+ return new Size(Math.max(this.width, (typeof size === 'number' ? size : size.width)), this.height);
+ }
-/**
- * @param {!UI.Size|number} size
- * @return {!UI.Size}
+ /**
+ * @param {!Size|number} size
+ * @return {!Size}
*/
-UI.Size.prototype.addWidth = function(size) {
- return new UI.Size(this.width + (typeof size === 'number' ? size : size.width), this.height);
-};
+ addWidth(size) {
+ return new Size(this.width + (typeof size === 'number' ? size : size.width), this.height);
+ }
-/**
- * @param {!UI.Size|number} size
- * @return {!UI.Size}
- */
-UI.Size.prototype.heightToMax = function(size) {
- return new UI.Size(this.width, Math.max(this.height, (typeof size === 'number' ? size : size.height)));
-};
+ /**
+ * @param {!Size|number} size
+ * @return {!Size}
+ */
+ heightToMax(size) {
+ return new Size(this.width, Math.max(this.height, (typeof size === 'number' ? size : size.height)));
+ }
-/**
- * @param {!UI.Size|number} size
- * @return {!UI.Size}
- */
-UI.Size.prototype.addHeight = function(size) {
- return new UI.Size(this.width, this.height + (typeof size === 'number' ? size : size.height));
-};
+ /**
+ * @param {!Size|number} size
+ * @return {!Size}
+ */
+ addHeight(size) {
+ return new Size(this.width, this.height + (typeof size === 'number' ? size : size.height));
+ }
+}
/**
* @unrestricted
*/
-UI.Insets = class {
+export class Insets {
/**
* @param {number} left
* @param {number} top
@@ -424,19 +433,19 @@ UI.Insets = class {
}
/**
- * @param {?UI.Insets} insets
+ * @param {?Insets} insets
* @return {boolean}
*/
isEqual(insets) {
return !!insets && this.left === insets.left && this.top === insets.top && this.right === insets.right &&
this.bottom === insets.bottom;
}
-};
+}
/**
* @unrestricted
*/
-UI.Rect = class {
+export class Rect {
/**
* @param {number} left
* @param {number} top
@@ -451,7 +460,7 @@ UI.Rect = class {
}
/**
- * @param {?UI.Rect} rect
+ * @param {?Rect} rect
* @return {boolean}
*/
isEqual(rect) {
@@ -461,104 +470,209 @@ UI.Rect = class {
/**
* @param {number} scale
- * @return {!UI.Rect}
+ * @return {!Rect}
*/
scale(scale) {
- return new UI.Rect(this.left * scale, this.top * scale, this.width * scale, this.height * scale);
+ return new Rect(this.left * scale, this.top * scale, this.width * scale, this.height * scale);
}
/**
- * @return {!UI.Size}
+ * @return {!Size}
*/
size() {
- return new UI.Size(this.width, this.height);
+ return new Size(this.width, this.height);
}
/**
- * @param {!UI.Rect} origin
- * @return {!UI.Rect}
+ * @param {!Rect} origin
+ * @return {!Rect}
*/
relativeTo(origin) {
- return new UI.Rect(this.left - origin.left, this.top - origin.top, this.width, this.height);
+ return new Rect(this.left - origin.left, this.top - origin.top, this.width, this.height);
}
/**
- * @param {!UI.Rect} origin
- * @return {!UI.Rect}
+ * @param {!Rect} origin
+ * @return {!Rect}
*/
rebaseTo(origin) {
- return new UI.Rect(this.left + origin.left, this.top + origin.top, this.width, this.height);
+ return new Rect(this.left + origin.left, this.top + origin.top, this.width, this.height);
}
-};
+}
/**
* @unrestricted
*/
-UI.Constraints = class {
+export class Constraints {
/**
- * @param {!UI.Size=} minimum
- * @param {?UI.Size=} preferred
+ * @param {!Size=} minimum
+ * @param {?Size=} preferred
*/
constructor(minimum, preferred) {
/**
- * @type {!UI.Size}
+ * @type {!Size}
*/
- this.minimum = minimum || new UI.Size(0, 0);
+ this.minimum = minimum || new Size(0, 0);
/**
- * @type {!UI.Size}
+ * @type {!Size}
*/
this.preferred = preferred || this.minimum;
- if (this.minimum.width > this.preferred.width || this.minimum.height > this.preferred.height)
+ if (this.minimum.width > this.preferred.width || this.minimum.height > this.preferred.height) {
throw new Error('Minimum size is greater than preferred.');
+ }
+ }
+
+ /**
+ * @param {?Constraints} constraints
+ * @return {boolean}
+ */
+ isEqual(constraints) {
+ return !!constraints && this.minimum.isEqual(constraints.minimum) && this.preferred.isEqual(constraints.preferred);
}
-};
+
+ /**
+ * @param {!Constraints|number} value
+ * @return {!Constraints}
+ */
+ widthToMax(value) {
+ if (typeof value === 'number') {
+ return new Constraints(this.minimum.widthToMax(value), this.preferred.widthToMax(value));
+ }
+ return new Constraints(this.minimum.widthToMax(value.minimum), this.preferred.widthToMax(value.preferred));
+ }
+
+ /**
+ * @param {!Constraints|number} value
+ * @return {!Constraints}
+ */
+ addWidth(value) {
+ if (typeof value === 'number') {
+ return new Constraints(this.minimum.addWidth(value), this.preferred.addWidth(value));
+ }
+ return new Constraints(this.minimum.addWidth(value.minimum), this.preferred.addWidth(value.preferred));
+ }
+
+ /**
+ * @param {!Constraints|number} value
+ * @return {!Constraints}
+ */
+ heightToMax(value) {
+ if (typeof value === 'number') {
+ return new Constraints(this.minimum.heightToMax(value), this.preferred.heightToMax(value));
+ }
+ return new Constraints(this.minimum.heightToMax(value.minimum), this.preferred.heightToMax(value.preferred));
+ }
+
+ /**
+ * @param {!Constraints|number} value
+ * @return {!Constraints}
+ */
+ addHeight(value) {
+ if (typeof value === 'number') {
+ return new Constraints(this.minimum.addHeight(value), this.preferred.addHeight(value));
+ }
+ return new Constraints(this.minimum.addHeight(value.minimum), this.preferred.addHeight(value.preferred));
+ }
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+UI.Geometry = Geometry;
/**
- * @param {?UI.Constraints} constraints
- * @return {boolean}
+ * @type {number}
*/
-UI.Constraints.prototype.isEqual = function(constraints) {
- return !!constraints && this.minimum.isEqual(constraints.minimum) && this.preferred.isEqual(constraints.preferred);
-};
+UI.Geometry._Eps = _Eps;
/**
- * @param {!UI.Constraints|number} value
- * @return {!UI.Constraints}
+ * @constructor
*/
-UI.Constraints.prototype.widthToMax = function(value) {
- if (typeof value === 'number')
- return new UI.Constraints(this.minimum.widthToMax(value), this.preferred.widthToMax(value));
- return new UI.Constraints(this.minimum.widthToMax(value.minimum), this.preferred.widthToMax(value.preferred));
-};
+UI.Geometry.Vector = Vector;
/**
- * @param {!UI.Constraints|number} value
- * @return {!UI.Constraints}
+ * @constructor
*/
-UI.Constraints.prototype.addWidth = function(value) {
- if (typeof value === 'number')
- return new UI.Constraints(this.minimum.addWidth(value), this.preferred.addWidth(value));
- return new UI.Constraints(this.minimum.addWidth(value.minimum), this.preferred.addWidth(value.preferred));
-};
+UI.Geometry.Point = Point;
/**
- * @param {!UI.Constraints|number} value
- * @return {!UI.Constraints}
+ * @constructor
*/
-UI.Constraints.prototype.heightToMax = function(value) {
- if (typeof value === 'number')
- return new UI.Constraints(this.minimum.heightToMax(value), this.preferred.heightToMax(value));
- return new UI.Constraints(this.minimum.heightToMax(value.minimum), this.preferred.heightToMax(value.preferred));
-};
+UI.Geometry.CubicBezier = CubicBezier;
/**
- * @param {!UI.Constraints|number} value
- * @return {!UI.Constraints}
+ * @constructor
*/
-UI.Constraints.prototype.addHeight = function(value) {
- if (typeof value === 'number')
- return new UI.Constraints(this.minimum.addHeight(value), this.preferred.addHeight(value));
- return new UI.Constraints(this.minimum.addHeight(value.minimum), this.preferred.addHeight(value.preferred));
-};
+UI.Geometry.EulerAngles = EulerAngles;
+
+/**
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {number}
+ */
+UI.Geometry.scalarProduct = scalarProduct;
+
+/**
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {!Vector}
+ */
+UI.Geometry.crossProduct = crossProduct;
+
+/**
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {!Vector}
+ */
+UI.Geometry.subtract = subtract;
+
+/**
+ * @param {!Vector} v
+ * @param {!CSSMatrix} m
+ * @return {!Vector}
+ */
+UI.Geometry.multiplyVectorByMatrixAndNormalize = multiplyVectorByMatrixAndNormalize;
+
+/**
+ * @param {!Vector} u
+ * @param {!Vector} v
+ * @return {number}
+ */
+UI.Geometry.calculateAngle = calculateAngle;
+
+/**
+ * @param {number} deg
+ * @return {number}
+ */
+UI.Geometry.degreesToRadians = degreesToRadians;
+
+/**
+ * @param {number} rad
+ * @return {number}
+ */
+UI.Geometry.radiansToDegrees = radiansToDegrees;
+
+/** @constructor */
+UI.Size = Size;
+
+/** @constructor */
+UI.Insets = Insets;
+
+/** @constructor */
+UI.Rect = Rect;
+
+/** @constructor */
+UI.Constraints = Constraints;
+
+/**
+ * @param {!CSSMatrix} matrix
+ * @param {!Array.<number>} points
+ * @param {{minX: number, maxX: number, minY: number, maxY: number}=} aggregateBounds
+ * @return {!{minX: number, maxX: number, minY: number, maxY: number}}
+ */
+UI.Geometry.boundsForTransformedPoints = boundsForTransformedPoints;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/GlassPane.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/GlassPane.js
index f6b61dee29f..066b7e26bd8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/GlassPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/GlassPane.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.GlassPane = class {
+export default class GlassPane {
constructor() {
this._widget = new UI.Widget(true);
this._widget.markAsRoot();
@@ -12,7 +12,7 @@ UI.GlassPane = class {
this.element.shadowRoot.appendChild(this._arrowElement);
this.registerRequiredCSS('ui/glassPane.css');
- this.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.PierceGlassPane);
+ this.setPointerEventsBehavior(GlassPane.PointerEventsBehavior.PierceGlassPane);
this._onMouseDownBound = this._onMouseDown.bind(this);
/** @type {?function(!Event)} */
@@ -25,9 +25,9 @@ UI.GlassPane = class {
this._positionY = null;
/** @type {?AnchorBox} */
this._anchorBox = null;
- this._anchorBehavior = UI.GlassPane.AnchorBehavior.PreferTop;
- this._sizeBehavior = UI.GlassPane.SizeBehavior.SetExactSize;
- this._marginBehavior = UI.GlassPane.MarginBehavior.DefaultMargin;
+ this._anchorBehavior = GlassPane.AnchorBehavior.PreferTop;
+ this._sizeBehavior = GlassPane.SizeBehavior.SetExactSize;
+ this._marginBehavior = GlassPane.MarginBehavior.DefaultMargin;
}
/**
@@ -59,13 +59,13 @@ UI.GlassPane = class {
}
/**
- * @param {!UI.GlassPane.PointerEventsBehavior} pointerEventsBehavior
+ * @param {!GlassPane.PointerEventsBehavior} pointerEventsBehavior
*/
setPointerEventsBehavior(pointerEventsBehavior) {
this.element.classList.toggle(
- 'no-pointer-events', pointerEventsBehavior !== UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
+ 'no-pointer-events', pointerEventsBehavior !== GlassPane.PointerEventsBehavior.BlockedByGlassPane);
this.contentElement.classList.toggle(
- 'no-pointer-events', pointerEventsBehavior === UI.GlassPane.PointerEventsBehavior.PierceContents);
+ 'no-pointer-events', pointerEventsBehavior === GlassPane.PointerEventsBehavior.PierceContents);
}
/**
@@ -84,7 +84,7 @@ UI.GlassPane = class {
}
/**
- * @param {!UI.GlassPane.SizeBehavior} sizeBehavior
+ * @param {!GlassPane.SizeBehavior} sizeBehavior
*/
setSizeBehavior(sizeBehavior) {
this._sizeBehavior = sizeBehavior;
@@ -112,38 +112,41 @@ UI.GlassPane = class {
}
/**
- * @param {!UI.GlassPane.AnchorBehavior} behavior
+ * @param {!GlassPane.AnchorBehavior} behavior
*/
setAnchorBehavior(behavior) {
this._anchorBehavior = behavior;
}
/**
- * @param {boolean} behavior
+ * @param {!GlassPane.MarginBehavior} behavior
*/
setMarginBehavior(behavior) {
this._marginBehavior = behavior;
- this._arrowElement.classList.toggle('hidden', behavior !== UI.GlassPane.MarginBehavior.Arrow);
+ this._arrowElement.classList.toggle('hidden', behavior !== GlassPane.MarginBehavior.Arrow);
}
/**
* @param {!Document} document
*/
show(document) {
- if (this.isShowing())
+ if (this.isShowing()) {
return;
+ }
+ // TODO(crbug.com/1006759): Extract the magic number
// Deliberately starts with 3000 to hide other z-indexed elements below.
- this.element.style.zIndex = 3000 + 1000 * UI.GlassPane._panes.size;
+ this.element.style.zIndex = 3000 + 1000 * GlassPane._panes.size;
document.body.addEventListener('mousedown', this._onMouseDownBound, true);
this._widget.show(document.body);
- UI.GlassPane._panes.add(this);
+ GlassPane._panes.add(this);
this._positionContent();
}
hide() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
- UI.GlassPane._panes.delete(this);
+ }
+ GlassPane._panes.delete(this);
this.element.ownerDocument.body.removeEventListener('mousedown', this._onMouseDownBound, true);
this._widget.detach();
}
@@ -152,25 +155,28 @@ UI.GlassPane = class {
* @param {!Event} event
*/
_onMouseDown(event) {
- if (!this._onClickOutsideCallback)
+ if (!this._onClickOutsideCallback) {
return;
+ }
const node = event.deepElementFromPoint();
- if (!node || this.contentElement.isSelfOrAncestor(node))
+ if (!node || this.contentElement.isSelfOrAncestor(node)) {
return;
+ }
this._onClickOutsideCallback.call(null, event);
}
_positionContent() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
- const showArrow = this._marginBehavior === UI.GlassPane.MarginBehavior.Arrow;
- const gutterSize = showArrow ? 8 : (this._marginBehavior === UI.GlassPane.MarginBehavior.NoMargin ? 0 : 3);
+ const showArrow = this._marginBehavior === GlassPane.MarginBehavior.Arrow;
+ const gutterSize = showArrow ? 8 : (this._marginBehavior === GlassPane.MarginBehavior.NoMargin ? 0 : 3);
const scrollbarSize = UI.measuredScrollbarWidth(this.element.ownerDocument);
const arrowSize = 10;
- const container = UI.GlassPane._containers.get(/** @type {!Document} */ (this.element.ownerDocument));
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ const container = GlassPane._containers.get(/** @type {!Document} */ (this.element.ownerDocument));
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
this.contentElement.positionAt(0, 0);
this.contentElement.style.width = '';
this.contentElement.style.maxWidth = '';
@@ -191,7 +197,7 @@ UI.GlassPane = class {
height = Math.min(height, this._maxSize.height);
}
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
const measuredRect = this.contentElement.getBoundingClientRect();
const widthOverflow = height < measuredRect.height ? scrollbarSize : 0;
const heightOverflow = width < measuredRect.width ? scrollbarSize : 0;
@@ -204,20 +210,22 @@ UI.GlassPane = class {
let behavior = this._anchorBehavior;
this._arrowElement.classList.remove('arrow-none', 'arrow-top', 'arrow-bottom', 'arrow-left', 'arrow-right');
- if (behavior === UI.GlassPane.AnchorBehavior.PreferTop || behavior === UI.GlassPane.AnchorBehavior.PreferBottom) {
+ if (behavior === GlassPane.AnchorBehavior.PreferTop || behavior === GlassPane.AnchorBehavior.PreferBottom) {
const top = anchorBox.y - 2 * gutterSize;
const bottom = containerHeight - anchorBox.y - anchorBox.height - 2 * gutterSize;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferTop && top < height && bottom > top)
- behavior = UI.GlassPane.AnchorBehavior.PreferBottom;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferBottom && bottom < height && top > bottom)
- behavior = UI.GlassPane.AnchorBehavior.PreferTop;
+ if (behavior === GlassPane.AnchorBehavior.PreferTop && top < height && bottom > top) {
+ behavior = GlassPane.AnchorBehavior.PreferBottom;
+ }
+ if (behavior === GlassPane.AnchorBehavior.PreferBottom && bottom < height && top > bottom) {
+ behavior = GlassPane.AnchorBehavior.PreferTop;
+ }
let arrowY;
let enoughHeight = true;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferTop) {
+ if (behavior === GlassPane.AnchorBehavior.PreferTop) {
positionY = Math.max(gutterSize, anchorBox.y - height - gutterSize);
const spaceTop = anchorBox.y - positionY - gutterSize;
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
if (height > spaceTop) {
this._arrowElement.classList.add('arrow-none');
enoughHeight = false;
@@ -231,7 +239,7 @@ UI.GlassPane = class {
} else {
positionY = anchorBox.y + anchorBox.height + gutterSize;
const spaceBottom = containerHeight - positionY - gutterSize;
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
if (height > spaceBottom) {
this._arrowElement.classList.add('arrow-none');
positionY = containerHeight - gutterSize - height;
@@ -246,10 +254,11 @@ UI.GlassPane = class {
}
positionX = Math.max(gutterSize, Math.min(anchorBox.x, containerWidth - width - gutterSize));
- if (!enoughHeight)
+ if (!enoughHeight) {
positionX = Math.min(positionX + arrowSize, containerWidth - width - gutterSize);
- else if (showArrow && positionX - arrowSize >= gutterSize)
+ } else if (showArrow && positionX - arrowSize >= gutterSize) {
positionX -= arrowSize;
+ }
width = Math.min(width, containerWidth - positionX - gutterSize);
if (2 * arrowSize >= width) {
this._arrowElement.classList.add('arrow-none');
@@ -261,17 +270,19 @@ UI.GlassPane = class {
} else {
const left = anchorBox.x - 2 * gutterSize;
const right = containerWidth - anchorBox.x - anchorBox.width - 2 * gutterSize;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft && left < width && right > left)
- behavior = UI.GlassPane.AnchorBehavior.PreferRight;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferRight && right < width && left > right)
- behavior = UI.GlassPane.AnchorBehavior.PreferLeft;
+ if (behavior === GlassPane.AnchorBehavior.PreferLeft && left < width && right > left) {
+ behavior = GlassPane.AnchorBehavior.PreferRight;
+ }
+ if (behavior === GlassPane.AnchorBehavior.PreferRight && right < width && left > right) {
+ behavior = GlassPane.AnchorBehavior.PreferLeft;
+ }
let arrowX;
let enoughWidth = true;
- if (behavior === UI.GlassPane.AnchorBehavior.PreferLeft) {
+ if (behavior === GlassPane.AnchorBehavior.PreferLeft) {
positionX = Math.max(gutterSize, anchorBox.x - width - gutterSize);
const spaceLeft = anchorBox.x - positionX - gutterSize;
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
if (width > spaceLeft) {
this._arrowElement.classList.add('arrow-none');
enoughWidth = false;
@@ -285,7 +296,7 @@ UI.GlassPane = class {
} else {
positionX = anchorBox.x + anchorBox.width + gutterSize;
const spaceRight = containerWidth - positionX - gutterSize;
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.MeasureContent) {
+ if (this._sizeBehavior === GlassPane.SizeBehavior.MeasureContent) {
if (width > spaceRight) {
this._arrowElement.classList.add('arrow-none');
positionX = containerWidth - gutterSize - width;
@@ -300,10 +311,11 @@ UI.GlassPane = class {
}
positionY = Math.max(gutterSize, Math.min(anchorBox.y, containerHeight - height - gutterSize));
- if (!enoughWidth)
+ if (!enoughWidth) {
positionY = Math.min(positionY + arrowSize, containerHeight - height - gutterSize);
- else if (showArrow && positionY - arrowSize >= gutterSize)
+ } else if (showArrow && positionY - arrowSize >= gutterSize) {
positionY -= arrowSize;
+ }
height = Math.min(height, containerHeight - positionY - gutterSize);
if (2 * arrowSize >= height) {
this._arrowElement.classList.add('arrow-none');
@@ -322,10 +334,11 @@ UI.GlassPane = class {
}
this.contentElement.style.width = width + 'px';
- if (this._sizeBehavior === UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight)
+ if (this._sizeBehavior === GlassPane.SizeBehavior.SetExactWidthMaxHeight) {
this.contentElement.style.maxHeight = height + 'px';
- else
+ } else {
this.contentElement.style.height = height + 'px';
+ }
this.contentElement.positionAt(positionX, positionY, container);
this._widget.doResize();
@@ -343,8 +356,8 @@ UI.GlassPane = class {
* @param {!Element} element
*/
static setContainer(element) {
- UI.GlassPane._containers.set(/** @type {!Document} */ (element.ownerDocument), element);
- UI.GlassPane.containerMoved(element);
+ GlassPane._containers.set(/** @type {!Document} */ (element.ownerDocument), element);
+ GlassPane.containerMoved(element);
}
/**
@@ -352,29 +365,30 @@ UI.GlassPane = class {
* @return {!Element}
*/
static container(document) {
- return UI.GlassPane._containers.get(document);
+ return GlassPane._containers.get(document);
}
/**
* @param {!Element} element
*/
static containerMoved(element) {
- for (const pane of UI.GlassPane._panes) {
- if (pane.isShowing() && pane.element.ownerDocument === element.ownerDocument)
+ for (const pane of GlassPane._panes) {
+ if (pane.isShowing() && pane.element.ownerDocument === element.ownerDocument) {
pane._positionContent();
+ }
}
}
-};
+}
/** @enum {symbol} */
-UI.GlassPane.PointerEventsBehavior = {
+export const PointerEventsBehavior = {
BlockedByGlassPane: Symbol('BlockedByGlassPane'),
PierceGlassPane: Symbol('PierceGlassPane'),
PierceContents: Symbol('PierceContents')
};
/** @enum {symbol} */
-UI.GlassPane.AnchorBehavior = {
+export const AnchorBehavior = {
PreferTop: Symbol('PreferTop'),
PreferBottom: Symbol('PreferBottom'),
PreferLeft: Symbol('PreferLeft'),
@@ -382,20 +396,48 @@ UI.GlassPane.AnchorBehavior = {
};
/** @enum {symbol} */
-UI.GlassPane.SizeBehavior = {
+export const SizeBehavior = {
SetExactSize: Symbol('SetExactSize'),
SetExactWidthMaxHeight: Symbol('SetExactWidthMaxHeight'),
MeasureContent: Symbol('MeasureContent')
};
/** @enum {symbol} */
-UI.GlassPane.MarginBehavior = {
+export const MarginBehavior = {
Arrow: Symbol('Arrow'),
DefaultMargin: Symbol('DefaultMargin'),
NoMargin: Symbol('NoMargin')
};
/** @type {!Map<!Document, !Element>} */
-UI.GlassPane._containers = new Map();
-/** @type {!Set<!UI.GlassPane>} */
-UI.GlassPane._panes = new Set();
+export const _containers = new Map();
+
+/** @type {!Set<!GlassPane>} */
+export const _panes = new Set();
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.GlassPane = GlassPane;
+
+/** @enum {symbol} */
+UI.GlassPane.PointerEventsBehavior = PointerEventsBehavior;
+
+/** @enum {symbol} */
+UI.GlassPane.AnchorBehavior = AnchorBehavior;
+
+/** @enum {symbol} */
+UI.GlassPane.SizeBehavior = SizeBehavior;
+
+/** @enum {symbol} */
+UI.GlassPane.MarginBehavior = MarginBehavior;
+
+/** @type {!Map<!Document, !Element>} */
+UI.GlassPane._containers = _containers;
+
+/** @type {!Set<!GlassPane>} */
+UI.GlassPane._panes = _panes;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/HistoryInput.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/HistoryInput.js
index 81784fc8db6..e21ff5d7f58 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/HistoryInput.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/HistoryInput.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.HistoryInput = class extends HTMLInputElement {
+export default class HistoryInput extends HTMLInputElement {
constructor() {
super();
this._history = [''];
@@ -13,21 +13,23 @@ UI.HistoryInput = class extends HTMLInputElement {
this.addEventListener('input', this._onInput.bind(this), false);
}
/**
- * @return {!UI.HistoryInput}
+ * @return {!HistoryInput}
*/
static create() {
- if (!UI.HistoryInput._constructor)
- UI.HistoryInput._constructor = UI.registerCustomElement('input', 'history-input', UI.HistoryInput);
+ if (!HistoryInput._constructor) {
+ HistoryInput._constructor = UI.registerCustomElement('input', 'history-input', HistoryInput);
+ }
- return /** @type {!UI.HistoryInput} */ (UI.HistoryInput._constructor());
+ return /** @type {!HistoryInput} */ (HistoryInput._constructor());
}
/**
* @param {!Event} event
*/
_onInput(event) {
- if (this._history.length === this._historyPosition + 1)
+ if (this._history.length === this._historyPosition + 1) {
this._history[this._history.length - 1] = this.value;
+ }
}
/**
@@ -50,10 +52,20 @@ UI.HistoryInput = class extends HTMLInputElement {
}
_saveToHistory() {
- if (this._history.length > 1 && this._history[this._history.length - 2] === this.value)
+ if (this._history.length > 1 && this._history[this._history.length - 2] === this.value) {
return;
+ }
this._history[this._history.length - 1] = this.value;
this._historyPosition = this._history.length - 1;
this._history.push('');
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.HistoryInput = HistoryInput;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Icon.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Icon.js
index 41046de4bac..b1c75a43acf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Icon.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Icon.js
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.Icon = class extends HTMLSpanElement {
+export default class Icon extends HTMLSpanElement {
constructor() {
super();
- /** @type {?UI.Icon.Descriptor} */
+ /** @type {?Icon.Descriptor} */
this._descriptor = null;
- /** @type {?UI.Icon.SpriteSheet} */
+ /** @type {?Icon.SpriteSheet} */
this._spriteSheet = null;
/** @type {string} */
this._iconType = '';
@@ -16,17 +16,20 @@ UI.Icon = class extends HTMLSpanElement {
/**
* @param {string=} iconType
* @param {string=} className
- * @return {!UI.Icon}
+ * @return {!Icon}
*/
static create(iconType, className) {
- if (!UI.Icon._constructor)
- UI.Icon._constructor = UI.registerCustomElement('span', 'ui-icon', UI.Icon);
+ if (!Icon._constructor) {
+ Icon._constructor = UI.registerCustomElement('span', 'ui-icon', Icon);
+ }
- const icon = /** @type {!UI.Icon} */ (UI.Icon._constructor());
- if (className)
+ const icon = /** @type {!Icon} */ (Icon._constructor());
+ if (className) {
icon.className = className;
- if (iconType)
+ }
+ if (iconType) {
icon.setIconType(iconType);
+ }
return icon;
}
@@ -43,11 +46,11 @@ UI.Icon = class extends HTMLSpanElement {
this._descriptor = null;
this._spriteSheet = null;
}
- const descriptor = UI.Icon.Descriptors[iconType] || null;
+ const descriptor = Icon.Descriptors[iconType] || null;
if (descriptor) {
this._iconType = iconType;
this._descriptor = descriptor;
- this._spriteSheet = UI.Icon.SpriteSheets[this._descriptor.spritesheet];
+ this._spriteSheet = Icon.SpriteSheets[this._descriptor.spritesheet];
console.assert(
this._spriteSheet, `ERROR: icon ${this._iconType} has unknown spritesheet: ${this._descriptor.spritesheet}`);
@@ -75,8 +78,9 @@ UI.Icon = class extends HTMLSpanElement {
*/
_propertyValue() {
if (!this._descriptor.coordinates) {
- if (!this._descriptor.position || !UI.Icon._positionRegex.test(this._descriptor.position))
+ if (!this._descriptor.position || !Icon._positionRegex.test(this._descriptor.position)) {
throw new Error(`ERROR: icon '${this._iconType}' has malformed position: '${this._descriptor.position}'`);
+ }
const column = this._descriptor.position[0].toLowerCase().charCodeAt(0) - 97;
const row = parseInt(this._descriptor.position.substring(1), 10) - 1;
this._descriptor.coordinates = {
@@ -86,26 +90,20 @@ UI.Icon = class extends HTMLSpanElement {
}
return `${this._descriptor.coordinates.x}px ${this._descriptor.coordinates.y}px`;
}
-};
+}
-UI.Icon._positionRegex = /^[a-z][1-9][0-9]*$/;
+export const _positionRegex = /^[a-z][1-9][0-9]*$/;
-/** @typedef {{position: string, spritesheet: string, isMask: (boolean|undefined)}} */
-UI.Icon.Descriptor;
-
-/** @typedef {{cellWidth: number, cellHeight: number, padding: number}} */
-UI.Icon.SpriteSheet;
-
-/** @enum {!UI.Icon.SpriteSheet} */
-UI.Icon.SpriteSheets = {
+/** @enum {!Icon.SpriteSheet} */
+export const SpriteSheets = {
'smallicons': {cellWidth: 10, cellHeight: 10, padding: 10},
'mediumicons': {cellWidth: 16, cellHeight: 16, padding: 0},
'largeicons': {cellWidth: 28, cellHeight: 24, padding: 0},
'arrowicons': {cellWidth: 19, cellHeight: 19, padding: 0}
};
-/** @enum {!UI.Icon.Descriptor} */
-UI.Icon.Descriptors = {
+/** @enum {!Icon.Descriptor} */
+export const Descriptors = {
'smallicon-bezier': {position: 'a5', spritesheet: 'smallicons', isMask: true},
'smallicon-checkmark': {position: 'b5', spritesheet: 'smallicons'},
'smallicon-checkmark-square': {position: 'b6', spritesheet: 'smallicons', isMask: true},
@@ -141,6 +139,9 @@ UI.Icon.Descriptors = {
'smallicon-clear-info': {position: 'f2', spritesheet: 'smallicons'},
'smallicon-clear-error': {position: 'f3', spritesheet: 'smallicons'},
'smallicon-account-circle': {position: 'f4', spritesheet: 'smallicons'},
+ 'smallicon-videoplayer-paused': {position: 'f6', spritesheet: 'smallicons', isMask: true},
+ 'smallicon-videoplayer-playing': {position: 'g6', spritesheet: 'smallicons', isMask: true},
+ 'smallicon-videoplayer-destroyed': {position: 'g5', spritesheet: 'smallicons', isMask: true},
'mediumicon-clear-storage': {position: 'a4', spritesheet: 'mediumicons', isMask: true},
'mediumicon-cookie': {position: 'b4', spritesheet: 'mediumicons', isMask: true},
@@ -249,3 +250,26 @@ UI.Icon.Descriptors = {
'mediumicon-arrow-left': {position: 'a2', spritesheet: 'arrowicons'},
'mediumicon-arrow-right': {position: 'a1', spritesheet: 'arrowicons'}
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Icon = Icon;
+
+UI.Icon._positionRegex = _positionRegex;
+
+/** @enum {!Icon.SpriteSheet} */
+UI.Icon.SpriteSheets = SpriteSheets;
+
+/** @enum {!Icon.Descriptor} */
+UI.Icon.Descriptors = Descriptors;
+
+/** @typedef {{position: string, spritesheet: string, isMask: (boolean|undefined), coordinates: ({x: number, y: number}|undefined), invert: (boolean|undefined)}} */
+UI.Icon.Descriptor;
+
+/** @typedef {{cellWidth: number, cellHeight: number, padding: number}} */
+UI.Icon.SpriteSheet; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Infobar.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Infobar.js
index b6523a04127..04eb525e422 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Infobar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Infobar.js
@@ -4,9 +4,9 @@
/**
* @unrestricted
*/
-UI.Infobar = class {
+export default class Infobar {
/**
- * @param {!UI.Infobar.Type} type
+ * @param {!Type} type
* @param {string} text
* @param {!Common.Setting=} disableSetting
*/
@@ -21,42 +21,45 @@ UI.Infobar = class {
this._mainRowText.textContent = text;
this._detailsRows = this._contentElement.createChild('div', 'infobar-details-rows hidden');
- this._toggleElement = this._mainRow.createChild('div', 'infobar-toggle hidden');
- this._toggleElement.addEventListener('click', this._onToggleDetails.bind(this), false);
- this._toggleElement.textContent = Common.UIString('more');
+ this._toggleElement =
+ UI.createTextButton(ls`more`, this._onToggleDetails.bind(this), 'infobar-toggle link-style hidden');
+ this._mainRow.appendChild(this._toggleElement);
/** @type {?Common.Setting} */
this._disableSetting = disableSetting || null;
if (disableSetting) {
- const disableButton = this._mainRow.createChild('div', 'infobar-toggle');
- disableButton.textContent = Common.UIString('never show');
- disableButton.addEventListener('click', this._onDisable.bind(this), false);
+ const disableButton =
+ UI.createTextButton(ls`never show`, this._onDisable.bind(this), 'infobar-toggle link-style');
+ this._mainRow.appendChild(disableButton);
}
this._closeButton = this._contentElement.createChild('div', 'close-button', 'dt-close-button');
- this._closeButton.addEventListener('click', this.dispose.bind(this), false);
+ this._closeButton.setTabbable(true);
+ self.onInvokeElement(this._closeButton, this.dispose.bind(this));
/** @type {?function()} */
this._closeCallback = null;
}
/**
- * @param {!UI.Infobar.Type} type
+ * @param {!Type} type
* @param {string} text
* @param {!Common.Setting=} disableSetting
- * @return {?UI.Infobar}
+ * @return {?Infobar}
*/
static create(type, text, disableSetting) {
- if (disableSetting && disableSetting.get())
+ if (disableSetting && disableSetting.get()) {
return null;
- return new UI.Infobar(type, text, disableSetting);
+ }
+ return new Infobar(type, text, disableSetting);
}
dispose() {
this.element.remove();
this._onResize();
- if (this._closeCallback)
+ if (this._closeCallback) {
this._closeCallback.call(null);
+ }
}
/**
@@ -82,8 +85,9 @@ UI.Infobar = class {
}
_onResize() {
- if (this._parentView)
+ if (this._parentView) {
this._parentView.doResize();
+ }
}
_onDisable() {
@@ -108,11 +112,22 @@ UI.Infobar = class {
detailsRowMessage.textContent = message || '';
return detailsRowMessage;
}
-};
-
+}
/** @enum {string} */
-UI.Infobar.Type = {
+export const Type = {
Warning: 'warning',
Info: 'info'
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Infobar = Infobar;
+
+/** @enum {string} */
+UI.Infobar.Type = Type;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/InplaceEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/InplaceEditor.js
index 31e4f832b50..9734016adeb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/InplaceEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/InplaceEditor.js
@@ -4,16 +4,17 @@
/**
* @unrestricted
*/
-UI.InplaceEditor = class {
+export default class InplaceEditor {
/**
* @param {!Element} element
- * @param {!UI.InplaceEditor.Config=} config
- * @return {?UI.InplaceEditor.Controller}
+ * @param {!InplaceEditor.Config=} config
+ * @return {?InplaceEditor.Controller}
*/
static startEditing(element, config) {
- if (!UI.InplaceEditor._defaultInstance)
- UI.InplaceEditor._defaultInstance = new UI.InplaceEditor();
- return UI.InplaceEditor._defaultInstance.startEditing(element, config);
+ if (!InplaceEditor._defaultInstance) {
+ InplaceEditor._defaultInstance = new InplaceEditor();
+ }
+ return InplaceEditor._defaultInstance.startEditing(element, config);
}
/**
@@ -21,8 +22,9 @@ UI.InplaceEditor = class {
*/
editorContent(editingContext) {
const element = editingContext.element;
- if (element.tagName === 'INPUT' && element.type === 'text')
+ if (element.tagName === 'INPUT' && element.type === 'text') {
return element.value;
+ }
return element.textContent;
}
@@ -37,8 +39,9 @@ UI.InplaceEditor = class {
editingContext.oldRole = oldRole;
const oldTabIndex = element.getAttribute('tabIndex');
- if (typeof oldTabIndex !== 'number' || oldTabIndex < 0)
+ if (typeof oldTabIndex !== 'number' || oldTabIndex < 0) {
element.tabIndex = 0;
+ }
this._focusRestorer = new UI.ElementFocusRestorer(element);
editingContext.oldTabIndex = oldTabIndex;
}
@@ -48,25 +51,28 @@ UI.InplaceEditor = class {
element.classList.remove('editing');
element.removeAttribute('contenteditable');
- if (typeof editingContext.oldRole !== 'string')
+ if (typeof editingContext.oldRole !== 'string') {
element.removeAttribute('role');
- else
+ } else {
element.role = editingContext.oldRole;
+ }
- if (typeof editingContext.oldTabIndex !== 'number')
+ if (typeof editingContext.oldTabIndex !== 'number') {
element.removeAttribute('tabIndex');
- else
+ } else {
element.tabIndex = editingContext.oldTabIndex;
+ }
element.scrollTop = 0;
element.scrollLeft = 0;
}
cancelEditing(editingContext) {
const element = editingContext.element;
- if (element.tagName === 'INPUT' && element.type === 'text')
+ if (element.tagName === 'INPUT' && element.type === 'text') {
element.value = editingContext.oldText;
- else
+ } else {
element.textContent = editingContext.oldText;
+ }
}
augmentEditingHandle(editingContext, handle) {
@@ -74,14 +80,15 @@ UI.InplaceEditor = class {
/**
* @param {!Element} element
- * @param {!UI.InplaceEditor.Config=} config
- * @return {?UI.InplaceEditor.Controller}
+ * @param {!InplaceEditor.Config=} config
+ * @return {?InplaceEditor.Controller}
*/
startEditing(element, config) {
- if (!UI.markBeingEdited(element, true))
+ if (!UI.markBeingEdited(element, true)) {
return null;
+ }
- config = config || new UI.InplaceEditor.Config(function() {}, function() {});
+ config = config || new InplaceEditor.Config(function() {}, function() {});
const editingContext = {element: element, config: config};
const committedCallback = config.commitHandler;
const cancelledCallback = config.cancelHandler;
@@ -98,8 +105,9 @@ UI.InplaceEditor = class {
* @param {!Event=} e
*/
function blurEventListener(e) {
- if (config.blurHandler && !config.blurHandler(element, e))
+ if (config.blurHandler && !config.blurHandler(element, e)) {
return;
+ }
editingCommitted.call(element);
}
@@ -108,11 +116,13 @@ UI.InplaceEditor = class {
element.removeEventListener('blur', blurEventListener, false);
element.removeEventListener('keydown', keyDownEventListener, true);
- if (pasteCallback)
+ if (pasteCallback) {
element.removeEventListener('paste', pasteEventListener, true);
+ }
- if (self._focusRestorer)
+ if (self._focusRestorer) {
self._focusRestorer.restore();
+ }
self.closeEditor(editingContext);
}
@@ -135,12 +145,13 @@ UI.InplaceEditor = class {
* @return {string}
*/
function defaultFinishHandler(event) {
- if (isEnterKey(event))
+ if (isEnterKey(event)) {
return 'commit';
- else if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code || event.key === 'Escape')
+ } else if (event.keyCode === UI.KeyboardShortcut.Keys.Esc.code || event.key === 'Escape') {
return 'cancel';
- else if (event.key === 'Tab')
+ } else if (event.key === 'Tab') {
return 'move-' + (event.shiftKey ? 'backward' : 'forward');
+ }
return '';
}
@@ -153,8 +164,9 @@ UI.InplaceEditor = class {
event.consume(true);
} else if (result && result.startsWith('move-')) {
moveDirection = result.substring(5);
- if (event.key === 'Tab')
+ if (event.key === 'Tab') {
event.consume(true);
+ }
blurEventListener();
}
}
@@ -172,33 +184,30 @@ UI.InplaceEditor = class {
*/
function keyDownEventListener(event) {
let result = defaultFinishHandler(event);
- if (!result && config.postKeydownFinishHandler)
+ if (!result && config.postKeydownFinishHandler) {
result = config.postKeydownFinishHandler(event);
+ }
handleEditingResult(result, event);
}
element.addEventListener('blur', blurEventListener, false);
element.addEventListener('keydown', keyDownEventListener, true);
- if (pasteCallback)
+ if (pasteCallback) {
element.addEventListener('paste', pasteEventListener, true);
+ }
const handle = {cancel: editingCancelled.bind(element), commit: editingCommitted.bind(element)};
this.augmentEditingHandle(editingContext, handle);
return handle;
}
-};
-
-/**
- * @typedef {{cancel: function(), commit: function()}}
- */
-UI.InplaceEditor.Controller;
+}
/**
* @template T
* @unrestricted
*/
-UI.InplaceEditor.Config = class {
+export class Config {
/**
* @param {function(!Element,string,string,T,string)} commitHandler
* @param {function(!Element,T)} cancelHandler
@@ -232,4 +241,23 @@ UI.InplaceEditor.Config = class {
setPostKeydownFinishHandler(postKeydownFinishHandler) {
this.postKeydownFinishHandler = postKeydownFinishHandler;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.InplaceEditor = InplaceEditor;
+
+/**
+ * @constructor
+ */
+UI.InplaceEditor.Config = Config;
+
+/**
+ * @typedef {{cancel: function(), commit: function()}}
+ */
+UI.InplaceEditor.Controller; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js
index c19d28255c8..25e37d5385d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js
@@ -31,7 +31,7 @@
* @implements {UI.ViewLocationResolver}
* @unrestricted
*/
-UI.InspectorView = class extends UI.VBox {
+export default class InspectorView extends UI.VBox {
constructor() {
super();
UI.GlassPane.setContainer(this.element);
@@ -44,7 +44,7 @@ UI.InspectorView = class extends UI.VBox {
this._drawerSplitWidget.enableShowModeSaving();
this._drawerSplitWidget.show(this.element);
- if (Runtime.experiments.isEnabled('splitInDrawer')) {
+ if (Root.Runtime.experiments.isEnabled('splitInDrawer')) {
this._innerDrawerSplitWidget = new UI.SplitWidget(true, true, 'Inspector.drawerSidebarSplitViewState', 200, 200);
this._drawerSplitWidget.setSidebarWidget(this._innerDrawerSplitWidget);
this._drawerSidebarTabbedLocation =
@@ -77,8 +77,8 @@ UI.InspectorView = class extends UI.VBox {
// Create main area tabbed pane.
this._tabbedLocation = UI.viewManager.createTabbedLocation(
- InspectorFrontendHost.bringToFront.bind(InspectorFrontendHost), 'panel', true, true,
- Runtime.queryParam('panel'));
+ Host.InspectorFrontendHost.bringToFront.bind(Host.InspectorFrontendHost), 'panel', true, true,
+ Root.Runtime.queryParam('panel'));
this._tabbedPane = this._tabbedLocation.tabbedPane();
this._tabbedPane.registerRequiredCSS('ui/inspectorViewTabbedPane.css');
@@ -88,15 +88,17 @@ UI.InspectorView = class extends UI.VBox {
// Store the initial selected panel for use in launch histograms
Host.userMetrics.setLaunchPanel(this._tabbedPane.selectedTabId);
- if (Host.isUnderTest())
+ if (Host.isUnderTest()) {
this._tabbedPane.setAutoSelectFirstItemOnShow(false);
+ }
this._drawerSplitWidget.setMainWidget(this._tabbedPane);
this._keyDownBound = this._keyDown.bind(this);
- InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ShowPanel, showPanel.bind(this));
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.ShowPanel, showPanel.bind(this));
/**
- * @this {UI.InspectorView}
+ * @this {InspectorView}
* @param {!Common.Event} event
*/
function showPanel(event) {
@@ -106,10 +108,10 @@ UI.InspectorView = class extends UI.VBox {
}
/**
- * @return {!UI.InspectorView}
+ * @return {!InspectorView}
*/
static instance() {
- return /** @type {!UI.InspectorView} */ (self.runtime.sharedInstance(UI.InspectorView));
+ return /** @type {!InspectorView} */ (self.runtime.sharedInstance(InspectorView));
}
/**
@@ -132,12 +134,15 @@ UI.InspectorView = class extends UI.VBox {
* @return {?UI.ViewLocation}
*/
resolveLocation(locationName) {
- if (locationName === 'drawer-view')
+ if (locationName === 'drawer-view') {
return this._drawerTabbedLocation;
- if (locationName === 'panel')
+ }
+ if (locationName === 'panel') {
return this._tabbedLocation;
- if (locationName === 'drawer-sidebar')
+ }
+ if (locationName === 'drawer-sidebar') {
return this._drawerSidebarTabbedLocation;
+ }
return null;
}
@@ -214,13 +219,15 @@ UI.InspectorView = class extends UI.VBox {
* @param {boolean} focus
*/
_showDrawer(focus) {
- if (this._drawerTabbedPane.isShowing())
+ if (this._drawerTabbedPane.isShowing()) {
return;
+ }
this._drawerSplitWidget.showBoth();
- if (focus)
+ if (focus) {
this._focusRestorer = new UI.WidgetFocusRestorer(this._drawerTabbedPane);
- else
+ } else {
this._focusRestorer = null;
+ }
}
/**
@@ -231,10 +238,12 @@ UI.InspectorView = class extends UI.VBox {
}
_closeDrawer() {
- if (!this._drawerTabbedPane.isShowing())
+ if (!this._drawerTabbedPane.isShowing()) {
return;
- if (this._focusRestorer)
+ }
+ if (this._focusRestorer) {
this._focusRestorer.restore();
+ }
this._drawerSplitWidget.hideSidebar(true);
}
@@ -266,24 +275,27 @@ UI.InspectorView = class extends UI.VBox {
*/
_keyDown(event) {
const keyboardEvent = /** @type {!KeyboardEvent} */ (event);
- if (!UI.KeyboardShortcut.eventHasCtrlOrMeta(keyboardEvent) || event.altKey || event.shiftKey)
+ if (!UI.KeyboardShortcut.eventHasCtrlOrMeta(keyboardEvent) || event.altKey || event.shiftKey) {
return;
+ }
// Ctrl/Cmd + 1-9 should show corresponding panel.
const panelShortcutEnabled = Common.moduleSetting('shortcutPanelSwitch').get();
if (panelShortcutEnabled) {
let panelIndex = -1;
- if (event.keyCode > 0x30 && event.keyCode < 0x3A)
+ if (event.keyCode > 0x30 && event.keyCode < 0x3A) {
panelIndex = event.keyCode - 0x31;
- else if (
+ } else if (
event.keyCode > 0x60 && event.keyCode < 0x6A &&
- keyboardEvent.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD)
+ keyboardEvent.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD) {
panelIndex = event.keyCode - 0x61;
+ }
if (panelIndex !== -1) {
const panelName = this._tabbedPane.tabIds()[panelIndex];
if (panelName) {
- if (!UI.Dialog.hasInstance() && !this._currentPanelLocked)
+ if (!UI.Dialog.hasInstance() && !this._currentPanelLocked) {
this.showPanel(panelName);
+ }
event.consume(true);
}
}
@@ -332,27 +344,23 @@ UI.InspectorView = class extends UI.VBox {
}
minimize() {
- if (this._ownerSplitWidget)
+ if (this._ownerSplitWidget) {
this._ownerSplitWidget.setSidebarMinimized(true);
+ }
}
restore() {
- if (this._ownerSplitWidget)
+ if (this._ownerSplitWidget) {
this._ownerSplitWidget.setSidebarMinimized(false);
+ }
}
-};
-
-
-/**
- * @type {!UI.InspectorView}
- */
-UI.inspectorView;
+}
/**
* @implements {UI.ActionDelegate}
* @unrestricted
*/
-UI.InspectorView.ActionDelegate = class {
+export class ActionDelegate {
/**
* @override
* @param {!UI.Context} context
@@ -362,10 +370,11 @@ UI.InspectorView.ActionDelegate = class {
handleAction(context, actionId) {
switch (actionId) {
case 'main.toggle-drawer':
- if (UI.inspectorView.drawerVisible())
+ if (UI.inspectorView.drawerVisible()) {
UI.inspectorView._closeDrawer();
- else
+ } else {
UI.inspectorView._showDrawer(true);
+ }
return true;
case 'main.next-tab':
UI.inspectorView._tabbedPane.selectNextTab();
@@ -378,4 +387,24 @@ UI.InspectorView.ActionDelegate = class {
}
return false;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.InspectorView = InspectorView;
+
+/**
+ * @implements {UI.ActionDelegate}
+ * @unrestricted
+ */
+UI.InspectorView.ActionDelegate = ActionDelegate;
+
+/**
+ * @type {!InspectorView}
+ */
+UI.inspectorView; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/KeyboardShortcut.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/KeyboardShortcut.js
index baa5271fe44..d0d0511a50a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/KeyboardShortcut.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/KeyboardShortcut.js
@@ -30,7 +30,7 @@
/**
* @unrestricted
*/
-UI.KeyboardShortcut = class {
+export default class KeyboardShortcut {
/**
* Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits.
* It is useful for matching pressed keys.
@@ -40,10 +40,11 @@ UI.KeyboardShortcut = class {
* @return {number}
*/
static makeKey(keyCode, modifiers) {
- if (typeof keyCode === 'string')
+ if (typeof keyCode === 'string') {
keyCode = keyCode.charCodeAt(0) - (/^[a-z]/.test(keyCode) ? 32 : 0);
- modifiers = modifiers || UI.KeyboardShortcut.Modifiers.None;
- return UI.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
+ }
+ modifiers = modifiers || Modifiers.None;
+ return KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
}
/**
@@ -51,19 +52,23 @@ UI.KeyboardShortcut = class {
* @return {number}
*/
static makeKeyFromEvent(keyboardEvent) {
- let modifiers = UI.KeyboardShortcut.Modifiers.None;
- if (keyboardEvent.shiftKey)
- modifiers |= UI.KeyboardShortcut.Modifiers.Shift;
- if (keyboardEvent.ctrlKey)
- modifiers |= UI.KeyboardShortcut.Modifiers.Ctrl;
- if (keyboardEvent.altKey)
- modifiers |= UI.KeyboardShortcut.Modifiers.Alt;
- if (keyboardEvent.metaKey)
- modifiers |= UI.KeyboardShortcut.Modifiers.Meta;
+ let modifiers = Modifiers.None;
+ if (keyboardEvent.shiftKey) {
+ modifiers |= Modifiers.Shift;
+ }
+ if (keyboardEvent.ctrlKey) {
+ modifiers |= Modifiers.Ctrl;
+ }
+ if (keyboardEvent.altKey) {
+ modifiers |= Modifiers.Alt;
+ }
+ if (keyboardEvent.metaKey) {
+ modifiers |= Modifiers.Meta;
+ }
// Use either a real or a synthetic keyCode (for events originating from extensions).
const keyCode = keyboardEvent.keyCode || keyboardEvent['__keyCode'];
- return UI.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
+ return KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
}
/**
@@ -72,7 +77,7 @@ UI.KeyboardShortcut = class {
*/
static makeKeyFromEventIgnoringModifiers(keyboardEvent) {
const keyCode = keyboardEvent.keyCode || keyboardEvent['__keyCode'];
- return UI.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, UI.KeyboardShortcut.Modifiers.None);
+ return KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, Modifiers.None);
}
/**
@@ -94,26 +99,26 @@ UI.KeyboardShortcut = class {
/**
* @param {string|!UI.KeyboardShortcut.Key} key
* @param {number=} modifiers
- * @return {!UI.KeyboardShortcut.Descriptor}
+ * @return {!KeyboardShortcut.Descriptor}
*/
static makeDescriptor(key, modifiers) {
return {
- key: UI.KeyboardShortcut.makeKey(typeof key === 'string' ? key : key.code, modifiers),
- name: UI.KeyboardShortcut.shortcutToString(key, modifiers)
+ key: KeyboardShortcut.makeKey(typeof key === 'string' ? key : key.code, modifiers),
+ name: KeyboardShortcut.shortcutToString(key, modifiers)
};
}
/**
* @param {string} shortcut
- * @return {?UI.KeyboardShortcut.Descriptor}
+ * @return {?KeyboardShortcut.Descriptor}
*/
static makeDescriptorFromBindingShortcut(shortcut) {
const parts = shortcut.split(/\+(?!$)/);
let modifiers = 0;
let keyString;
for (let i = 0; i < parts.length; ++i) {
- if (typeof UI.KeyboardShortcut.Modifiers[parts[i]] !== 'undefined') {
- modifiers |= UI.KeyboardShortcut.Modifiers[parts[i]];
+ if (typeof Modifiers[parts[i]] !== 'undefined') {
+ modifiers |= Modifiers[parts[i]];
continue;
}
console.assert(
@@ -122,13 +127,15 @@ UI.KeyboardShortcut = class {
break;
}
console.assert(keyString, 'Modifiers-only shortcuts are not allowed (encountered <' + shortcut + '>)');
- if (!keyString)
+ if (!keyString) {
return null;
+ }
- const key = UI.KeyboardShortcut.Keys[keyString] || UI.KeyboardShortcut.KeyBindings[keyString];
- if (key && key.shiftKey)
- modifiers |= UI.KeyboardShortcut.Modifiers.Shift;
- return UI.KeyboardShortcut.makeDescriptor(key ? key : keyString, modifiers);
+ const key = KeyboardShortcut.Keys[keyString] || KeyboardShortcut.KeyBindings[keyString];
+ if (key && key.shiftKey) {
+ modifiers |= Modifiers.Shift;
+ }
+ return KeyboardShortcut.makeDescriptor(key ? key : keyString, modifiers);
}
/**
@@ -137,7 +144,7 @@ UI.KeyboardShortcut = class {
* @return {string}
*/
static shortcutToString(key, modifiers) {
- return UI.KeyboardShortcut._modifiersToString(modifiers) + UI.KeyboardShortcut._keyName(key);
+ return KeyboardShortcut._modifiersToString(modifiers) + KeyboardShortcut._keyName(key);
}
/**
@@ -145,10 +152,12 @@ UI.KeyboardShortcut = class {
* @return {string}
*/
static _keyName(key) {
- if (typeof key === 'string')
+ if (typeof key === 'string') {
return key.toUpperCase();
- if (typeof key.name === 'string')
+ }
+ if (typeof key.name === 'string') {
return key.name;
+ }
return key.name[Host.platform()] || key.name.other || '';
}
@@ -175,7 +184,7 @@ UI.KeyboardShortcut = class {
*/
static _modifiersToString(modifiers) {
const isMac = Host.isMac();
- const m = UI.KeyboardShortcut.Modifiers;
+ const m = Modifiers;
const modifierNames = new Map([
[m.Ctrl, isMac ? 'Ctrl\u2004' : 'Ctrl\u200A+\u200A'], [m.Alt, isMac ? '\u2325\u2004' : 'Alt\u200A+\u200A'],
[m.Shift, isMac ? '\u21e7\u2004' : 'Shift\u200A+\u200A'], [m.Meta, isMac ? '\u2318\u2004' : 'Win\u200A+\u200A']
@@ -190,13 +199,13 @@ UI.KeyboardShortcut = class {
return modifiers & m ? /** @type {string} */ (modifierNames.get(m)) : '';
}
}
-};
+}
/**
* Constants for encoding modifier key set as a bit mask.
* @see #_makeKeyFromCodeAndModifiers
*/
-UI.KeyboardShortcut.Modifiers = {
+export const Modifiers = {
None: 0, // Constant for empty modifiers set.
Shift: 1,
Ctrl: 2,
@@ -212,11 +221,8 @@ UI.KeyboardShortcut.Modifiers = {
}
};
-/** @typedef {!{code: number, name: (string|!Object.<string, string>)}} */
-UI.KeyboardShortcut.Key;
-
/** @type {!Object.<string, !UI.KeyboardShortcut.Key>} */
-UI.KeyboardShortcut.Keys = {
+export const Keys = {
Backspace: {code: 8, name: '\u21a4'},
Tab: {code: 9, name: {mac: '\u21e5', other: 'Tab'}},
Enter: {code: 13, name: {mac: '\u21a9', other: 'Enter'}},
@@ -272,18 +278,40 @@ UI.KeyboardShortcut.Keys = {
},
};
-UI.KeyboardShortcut.KeyBindings = {};
+export const KeyBindings = {};
(function() {
-for (const key in UI.KeyboardShortcut.Keys) {
- const descriptor = UI.KeyboardShortcut.Keys[key];
+for (const key in Keys) {
+ const descriptor = Keys[key];
if (typeof descriptor === 'object' && descriptor['code']) {
const name = typeof descriptor['name'] === 'string' ? descriptor['name'] : key;
- UI.KeyboardShortcut.KeyBindings[name] = descriptor;
+ KeyBindings[name] = descriptor;
}
}
})();
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.KeyboardShortcut = KeyboardShortcut;
+
+/**
+ * Constants for encoding modifier key set as a bit mask.
+ * @see #_makeKeyFromCodeAndModifiers
+ */
+UI.KeyboardShortcut.Modifiers = Modifiers;
+
+/** @type {!Object.<string, !UI.KeyboardShortcut.Key>} */
+UI.KeyboardShortcut.Keys = Keys;
+
+UI.KeyboardShortcut.KeyBindings = KeyBindings;
+
+/** @typedef {!{code: number, name: (string|!Object.<string, string>)}} */
+UI.KeyboardShortcut.Key;
/** @typedef {!{key: number, name: string}} */
UI.KeyboardShortcut.Descriptor;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListControl.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListControl.js
index b85f52de4d6..27ea4d47bbc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListControl.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListControl.js
@@ -6,14 +6,13 @@
* @template T
* @interface
*/
-UI.ListDelegate = function() {};
-
-UI.ListDelegate.prototype = {
+export class ListDelegate {
/**
* @param {T} item
* @return {!Element}
*/
- createElementForItem(item) {},
+ createElementForItem(item) {
+ }
/**
* This method is not called in NonViewport mode.
@@ -21,13 +20,15 @@ UI.ListDelegate.prototype = {
* @param {T} item
* @return {number}
*/
- heightForItem(item) {},
+ heightForItem(item) {
+ }
/**
* @param {T} item
* @return {boolean}
*/
- isItemSelectable(item) {},
+ isItemSelectable(item) {
+ }
/**
* @param {?T} from
@@ -35,11 +36,12 @@ UI.ListDelegate.prototype = {
* @param {?Element} fromElement
* @param {?Element} toElement
*/
- selectedItemChanged(from, to, fromElement, toElement) {},
-};
+ selectedItemChanged(from, to, fromElement, toElement) {
+ }
+}
/** @enum {symbol} */
-UI.ListMode = {
+export const ListMode = {
NonViewport: Symbol('UI.ListMode.NonViewport'),
EqualHeightItems: Symbol('UI.ListMode.EqualHeightItems'),
VariousHeightItems: Symbol('UI.ListMode.VariousHeightItems')
@@ -48,11 +50,11 @@ UI.ListMode = {
/**
* @template T
*/
-UI.ListControl = class {
+export default class ListControl {
/**
* @param {!UI.ListModel<T>} model
- * @param {!UI.ListDelegate<T>} delegate
- * @param {!UI.ListMode=} mode
+ * @param {!ListDelegate<T>} delegate
+ * @param {!ListMode=} mode
*/
constructor(model, delegate, mode) {
this.element = createElement('div');
@@ -112,8 +114,9 @@ UI.ListControl = class {
const oldSelectedItem = this._selectedItem;
const oldSelectedElement = oldSelectedItem ? (this._itemToElement.get(oldSelectedItem) || null) : null;
- for (let i = 0; i < data.removed.length; i++)
+ for (let i = 0; i < data.removed.length; i++) {
this._itemToElement.delete(data.removed[i]);
+ }
this._invalidate(from, to, data.inserted);
if (this._selectedIndex >= to) {
@@ -121,8 +124,9 @@ UI.ListControl = class {
this._selectedItem = this._model.at(this._selectedIndex);
} else if (this._selectedIndex >= from) {
let index = this._findFirstSelectable(from + data.inserted, +1, false);
- if (index === -1)
+ if (index === -1) {
index = this._findFirstSelectable(from - 1, -1, false);
+ }
this._select(index, oldSelectedItem, oldSelectedElement);
}
}
@@ -146,8 +150,9 @@ UI.ListControl = class {
const item = this._model.at(index);
this._itemToElement.delete(item);
this.invalidateRange(index, index + 1);
- if (this._selectedIndex !== -1)
+ if (this._selectedIndex !== -1) {
this._select(this._selectedIndex, null, null);
+ }
}
/**
@@ -159,8 +164,9 @@ UI.ListControl = class {
}
viewportResized() {
- if (this._mode === UI.ListMode.NonViewport)
+ if (this._mode === UI.ListMode.NonViewport) {
return;
+ }
// TODO(dgozman): try to keep visible scrollTop the same.
const scrollTop = this.element.scrollTop;
const viewportHeight = this.element.offsetHeight;
@@ -185,10 +191,12 @@ UI.ListControl = class {
* @return {?T}
*/
itemForNode(node) {
- while (node && node.parentNodeOrShadowHost() !== this.element)
+ while (node && node.parentNodeOrShadowHost() !== this.element) {
node = node.parentNodeOrShadowHost();
- if (!node)
+ }
+ if (!node) {
return null;
+ }
const element = /** @type {!Element} */ (node);
const index = this._model.findIndex(item => this._itemToElement.get(item) === element);
return index !== -1 ? this._model.at(index) : null;
@@ -240,10 +248,12 @@ UI.ListControl = class {
}
}
// Scrolling the item before selection ensures it is in the DOM.
- if (index !== -1 && !dontScroll)
+ if (index !== -1 && !dontScroll) {
this._scrollIntoView(index, center);
- if (this._selectedIndex !== index)
+ }
+ if (this._selectedIndex !== index) {
this._select(index);
+ }
}
/**
@@ -252,8 +262,9 @@ UI.ListControl = class {
* @return {boolean}
*/
selectPreviousItem(canWrap, center) {
- if (this._selectedIndex === -1 && !canWrap)
+ if (this._selectedIndex === -1 && !canWrap) {
return false;
+ }
let index = this._selectedIndex === -1 ? this._model.length - 1 : this._selectedIndex - 1;
index = this._findFirstSelectable(index, -1, !!canWrap);
if (index !== -1) {
@@ -270,8 +281,9 @@ UI.ListControl = class {
* @return {boolean}
*/
selectNextItem(canWrap, center) {
- if (this._selectedIndex === -1 && !canWrap)
+ if (this._selectedIndex === -1 && !canWrap) {
return false;
+ }
let index = this._selectedIndex === -1 ? 0 : this._selectedIndex + 1;
index = this._findFirstSelectable(index, +1, !!canWrap);
if (index !== -1) {
@@ -287,8 +299,9 @@ UI.ListControl = class {
* @return {boolean}
*/
selectItemPreviousPage(center) {
- if (this._mode === UI.ListMode.NonViewport)
+ if (this._mode === UI.ListMode.NonViewport) {
return false;
+ }
let index = this._selectedIndex === -1 ? this._model.length - 1 : this._selectedIndex;
index = this._findPageSelectable(index, -1);
if (index !== -1) {
@@ -304,8 +317,9 @@ UI.ListControl = class {
* @return {boolean}
*/
selectItemNextPage(center) {
- if (this._mode === UI.ListMode.NonViewport)
+ if (this._mode === UI.ListMode.NonViewport) {
return false;
+ }
let index = this._selectedIndex === -1 ? 0 : this._selectedIndex;
index = this._findPageSelectable(index, +1);
if (index !== -1) {
@@ -336,10 +350,11 @@ UI.ListControl = class {
}
const scrollTop = this.element.scrollTop;
- if (top < scrollTop)
+ if (top < scrollTop) {
this._updateViewport(top, viewportHeight);
- else if (bottom > scrollTop + viewportHeight)
+ } else if (bottom > scrollTop + viewportHeight) {
this._updateViewport(bottom - viewportHeight, viewportHeight);
+ }
}
/**
@@ -347,8 +362,9 @@ UI.ListControl = class {
*/
_onClick(event) {
const item = this.itemForNode(/** @type {?Node} */ (event.target));
- if (item && this._delegate.isItemSelectable(item))
+ if (item && this._delegate.isItemSelectable(item)) {
this.selectItem(item);
+ }
}
/**
@@ -370,8 +386,9 @@ UI.ListControl = class {
selected = this.selectItemNextPage(false);
break;
}
- if (selected)
+ if (selected) {
event.consume();
+ }
}
/**
@@ -386,16 +403,19 @@ UI.ListControl = class {
* @return {number}
*/
_indexAtOffset(offset) {
- if (this._mode === UI.ListMode.NonViewport)
+ if (this._mode === UI.ListMode.NonViewport) {
throw 'There should be no offset conversions in non-viewport mode';
- if (!this._model.length || offset < 0)
+ }
+ if (!this._model.length || offset < 0) {
return 0;
+ }
if (this._mode === UI.ListMode.VariousHeightItems) {
return Math.min(
this._model.length - 1, this._variableOffsets.lowerBound(offset, undefined, 0, this._model.length));
}
- if (!this._fixedHeight)
+ if (!this._fixedHeight) {
this._measureHeight();
+ }
return Math.min(this._model.length - 1, Math.floor(offset / this._fixedHeight));
}
@@ -418,21 +438,26 @@ UI.ListControl = class {
* @return {number}
*/
_offsetAtIndex(index) {
- if (this._mode === UI.ListMode.NonViewport)
+ if (this._mode === UI.ListMode.NonViewport) {
throw 'There should be no offset conversions in non-viewport mode';
- if (!this._model.length)
+ }
+ if (!this._model.length) {
return 0;
- if (this._mode === UI.ListMode.VariousHeightItems)
+ }
+ if (this._mode === UI.ListMode.VariousHeightItems) {
return this._variableOffsets[index];
- if (!this._fixedHeight)
+ }
+ if (!this._fixedHeight) {
this._measureHeight();
+ }
return index * this._fixedHeight;
}
_measureHeight() {
this._fixedHeight = this._delegate.heightForItem(this._model.at(0));
- if (!this._fixedHeight)
+ if (!this._fixedHeight) {
this._fixedHeight = UI.measurePreferredSize(this._elementAtIndex(0), this.element).height;
+ }
}
/**
@@ -441,18 +466,22 @@ UI.ListControl = class {
* @param {?Element=} oldElement
*/
_select(index, oldItem, oldElement) {
- if (oldItem === undefined)
+ if (oldItem === undefined) {
oldItem = this._selectedItem;
- if (oldElement === undefined)
+ }
+ if (oldElement === undefined) {
oldElement = this._itemToElement.get(oldItem) || null;
+ }
this._selectedIndex = index;
this._selectedItem = index === -1 ? null : this._model.at(index);
const newItem = this._selectedItem;
const newElement = this._selectedIndex !== -1 ? this._elementAtIndex(index) : null;
- if (oldElement)
+ if (oldElement) {
UI.ARIAUtils.setSelected(oldElement, false);
- if (newElement)
+ }
+ if (newElement) {
UI.ARIAUtils.setSelected(newElement, true);
+ }
UI.ARIAUtils.setActiveDescendant(this.element, newElement);
this._delegate.selectedItemChanged(oldItem, newItem, /** @type {?Element} */ (oldElement), newElement);
}
@@ -465,16 +494,19 @@ UI.ListControl = class {
*/
_findFirstSelectable(index, direction, canWrap) {
const length = this._model.length;
- if (!length)
+ if (!length) {
return -1;
+ }
for (let step = 0; step <= length; step++) {
if (index < 0 || index >= length) {
- if (!canWrap)
+ if (!canWrap) {
return -1;
+ }
index = (index + length) % length;
}
- if (this._delegate.isItemSelectable(this._model.at(index)))
+ if (this._delegate.isItemSelectable(this._model.at(index))) {
return index;
+ }
index += direction;
}
return -1;
@@ -492,8 +524,9 @@ UI.ListControl = class {
const viewportHeight = this.element.offsetHeight - 1;
while (index >= 0 && index < this._model.length) {
if (this._delegate.isItemSelectable(this._model.at(index))) {
- if (Math.abs(this._offsetAtIndex(index) - startOffset) >= viewportHeight)
+ if (Math.abs(this._offsetAtIndex(index) - startOffset) >= viewportHeight) {
return index;
+ }
lastSelectable = index;
}
index += direction;
@@ -530,8 +563,9 @@ UI.ListControl = class {
if (this._mode === UI.ListMode.VariousHeightItems) {
this._reallocateVariableOffsets(this._model.length + 1, from + 1);
- for (let i = from + 1; i <= this._model.length; i++)
+ for (let i = from + 1; i <= this._model.length; i++) {
this._variableOffsets[i] = this._variableOffsets[i - 1] + this._delegate.heightForItem(this._model.at(i - 1));
+ }
}
const viewportHeight = this.element.offsetHeight;
@@ -578,12 +612,15 @@ UI.ListControl = class {
*/
_invalidateNonViewportMode(start, remove, add) {
let startElement = this._topElement;
- for (let index = 0; index < start; index++)
+ for (let index = 0; index < start; index++) {
startElement = startElement.nextElementSibling;
- while (remove--)
+ }
+ while (remove--) {
startElement.nextElementSibling.remove();
- while (add--)
+ }
+ while (add--) {
this.element.insertBefore(this._elementAtIndex(start + add), startElement.nextElementSibling);
+ }
}
_clearViewport() {
@@ -662,4 +699,18 @@ UI.ListControl = class {
this._renderedHeight = totalHeight;
this.element.scrollTop = scrollTop;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ListControl = ListControl;
+
+/** @interface */
+UI.ListDelegate = ListDelegate;
+
+UI.ListMode = ListMode; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListModel.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListModel.js
index 468e9489c72..eec8b58531a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListModel.js
@@ -6,7 +6,7 @@
* @implements {Iterable<T>}
* @template T
*/
-UI.ListModel = class extends Common.Object {
+export default class ListModel extends Common.Object {
/**
* @param {!Array<T>=} items
*/
@@ -181,12 +181,23 @@ UI.ListModel = class extends Common.Object {
* @param {number} inserted
*/
_replaced(index, removed, inserted) {
- this.dispatchEventToListeners(
- UI.ListModel.Events.ItemsReplaced, {index: index, removed: removed, inserted: inserted});
+ this.dispatchEventToListeners(Events.ItemsReplaced, {index: index, removed: removed, inserted: inserted});
}
-};
+}
/** @enum {symbol} */
-UI.ListModel.Events = {
+export const Events = {
ItemsReplaced: Symbol('ItemsReplaced'),
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ListModel = ListModel;
+
+/** @enum {symbol} */
+UI.ListModel.Events = Events;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListWidget.js
index c6ee3920103..3b2dd9c72a7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ListWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ListWidget.js
@@ -4,9 +4,9 @@
/**
* @template T
*/
-UI.ListWidget = class extends UI.VBox {
+export default class ListWidget extends UI.VBox {
/**
- * @param {!UI.ListWidget.Delegate<T>} delegate
+ * @param {!Delegate<T>} delegate
*/
constructor(delegate) {
super(true, true /* delegatesFocus */);
@@ -24,7 +24,7 @@ UI.ListWidget = class extends UI.VBox {
this._editable = [];
/** @type {!Array<!Element>} */
this._elements = [];
- /** @type {?UI.ListWidget.Editor<T>} */
+ /** @type {?Editor<T>} */
this._editor = null;
/** @type {?T} */
this._editItem = null;
@@ -52,8 +52,9 @@ UI.ListWidget = class extends UI.VBox {
* @param {boolean} editable
*/
appendItem(item, editable) {
- if (this._lastSeparator && this._items.length)
+ if (this._lastSeparator && this._items.length) {
this._list.appendChild(createElementWithClass('div', 'list-separator'));
+ }
this._lastSeparator = false;
this._items.push(item);
@@ -77,8 +78,9 @@ UI.ListWidget = class extends UI.VBox {
* @param {number} index
*/
removeItem(index) {
- if (this._editItem === this._items[index])
+ if (this._editItem === this._items[index]) {
this._stopEditing();
+ }
const element = this._elements[index];
@@ -88,10 +90,12 @@ UI.ListWidget = class extends UI.VBox {
const next = element.nextElementSibling;
const nextIsSeparator = next && next.classList.contains('list-separator');
- if (previousIsSeparator && (nextIsSeparator || !next))
+ if (previousIsSeparator && (nextIsSeparator || !next)) {
previous.remove();
- if (nextIsSeparator && !previous)
+ }
+ if (nextIsSeparator && !previous) {
next.remove();
+ }
element.remove();
this._elements.splice(index, 1);
@@ -140,7 +144,7 @@ UI.ListWidget = class extends UI.VBox {
return controls;
/**
- * @this {UI.ListWidget}
+ * @this {ListWidget}
*/
function onEditClicked() {
const index = this._elements.indexOf(element);
@@ -149,7 +153,7 @@ UI.ListWidget = class extends UI.VBox {
}
/**
- * @this {UI.ListWidget}
+ * @this {ListWidget}
*/
function onRemoveClicked() {
const index = this._elements.indexOf(element);
@@ -167,13 +171,15 @@ UI.ListWidget = class extends UI.VBox {
}
_updatePlaceholder() {
- if (!this._emptyPlaceholder)
+ if (!this._emptyPlaceholder) {
return;
+ }
- if (!this._elements.length && !this._editor)
+ if (!this._elements.length && !this._editor) {
this._list.appendChild(this._emptyPlaceholder);
- else
+ } else {
this._emptyPlaceholder.remove();
+ }
}
/**
@@ -182,8 +188,9 @@ UI.ListWidget = class extends UI.VBox {
* @param {?Element} insertionPoint
*/
_startEditing(item, element, insertionPoint) {
- if (element && this._editElement === element)
+ if (element && this._editElement === element) {
return;
+ }
this._stopEditing();
this._focusRestorer = new UI.ElementFocusRestorer(this.element);
@@ -191,8 +198,9 @@ UI.ListWidget = class extends UI.VBox {
this._list.classList.add('list-editing');
this._editItem = item;
this._editElement = element;
- if (element)
+ if (element) {
element.classList.add('hidden');
+ }
const index = element ? this._elements.indexOf(element) : -1;
this._editor = this._delegate.beginEdit(item);
@@ -206,65 +214,69 @@ UI.ListWidget = class extends UI.VBox {
_commitEditing() {
const editItem = this._editItem;
const isNew = !this._editElement;
- const editor = /** @type {!UI.ListWidget.Editor<T>} */ (this._editor);
+ const editor = /** @type {!Editor<T>} */ (this._editor);
this._stopEditing();
this._delegate.commitEdit(editItem, editor, isNew);
}
_stopEditing() {
this._list.classList.remove('list-editing');
- if (this._focusRestorer)
+ if (this._focusRestorer) {
this._focusRestorer.restore();
- if (this._editElement)
+ }
+ if (this._editElement) {
this._editElement.classList.remove('hidden');
- if (this._editor && this._editor.element.parentElement)
+ }
+ if (this._editor && this._editor.element.parentElement) {
this._editor.element.remove();
+ }
this._editor = null;
this._editItem = null;
this._editElement = null;
this._updatePlaceholder();
}
-};
+}
/**
* @template T
* @interface
*/
-UI.ListWidget.Delegate = function() {};
-
-UI.ListWidget.Delegate.prototype = {
+export class Delegate {
/**
* @param {!T} item
* @param {boolean} editable
* @return {!Element}
*/
- renderItem(item, editable) {},
+ renderItem(item, editable) {
+ }
/**
* @param {!T} item
* @param {number} index
*/
- removeItemRequested(item, index) {},
+ removeItemRequested(item, index) {
+ }
/**
* @param {!T} item
- * @return {!UI.ListWidget.Editor<T>}
+ * @return {!Editor<T>}
*/
- beginEdit(item) {},
+ beginEdit(item) {
+ }
/**
* @param {!T} item
- * @param {!UI.ListWidget.Editor<T>} editor
+ * @param {!Editor<T>} editor
* @param {boolean} isNew
*/
commitEdit(item, editor, isNew) {}
-};
+}
/**
* @template T
*/
-UI.ListWidget.Editor = class {
+export class Editor {
constructor() {
this.element = createElementWithClass('div', 'editor-container');
this.element.addEventListener('keydown', onKeyDown.bind(null, isEscKey, this._cancelClicked.bind(this)), false);
@@ -272,9 +284,6 @@ UI.ListWidget.Editor = class {
this._contentElement = this.element.createChild('div', 'editor-content');
- this._errorMessageContainer = this.element.createChild('div', 'list-widget-input-validation-error');
- UI.ARIAUtils.markAsAlert(this._errorMessageContainer);
-
const buttonsRow = this.element.createChild('div', 'editor-buttons');
this._commitButton = UI.createTextButton('', this._commitClicked.bind(this), '', true /* primary */);
buttonsRow.appendChild(this._commitButton);
@@ -283,6 +292,9 @@ UI.ListWidget.Editor = class {
'keydown', onKeyDown.bind(null, isEnterKey, this._cancelClicked.bind(this)), false);
buttonsRow.appendChild(this._cancelButton);
+ this._errorMessageContainer = this.element.createChild('div', 'list-widget-input-validation-error');
+ UI.ARIAUtils.markAsAlert(this._errorMessageContainer);
+
/**
* @param {function(!Event):boolean} predicate
* @param {function()} callback
@@ -383,13 +395,15 @@ UI.ListWidget.Editor = class {
const {valid, errorMessage} = this._validators[index].call(null, this._item, this._index, input);
input.classList.toggle('error-input', !valid && !forceValid);
- if (valid || forceValid)
+ if (valid || forceValid) {
UI.ARIAUtils.setInvalid(input, false);
- else
+ } else {
UI.ARIAUtils.setInvalid(input, true);
+ }
- if (!forceValid && errorMessage && !this._errorMessageContainer.textContent)
+ if (!forceValid && errorMessage && !this._errorMessageContainer.textContent) {
this._errorMessageContainer.textContent = errorMessage;
+ }
allValid &= valid;
}
@@ -411,14 +425,16 @@ UI.ListWidget.Editor = class {
this._commitButton.textContent = commitButtonTitle;
this.element.scrollIntoViewIfNeeded(false);
- if (this._controls.length)
+ if (this._controls.length) {
this._controls[0].focus();
+ }
this._validateControls(true);
}
_commitClicked() {
- if (this._commitButton.disabled)
+ if (this._commitButton.disabled) {
return;
+ }
const commit = this._commit;
this._commit = null;
@@ -436,7 +452,27 @@ UI.ListWidget.Editor = class {
this._index = -1;
cancel();
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ListWidget = ListWidget;
+
+/**
+ * @template T
+ * @interface
+ */
+UI.ListWidget.Delegate = Delegate;
+
+/**
+ * @constructor
+ */
+UI.ListWidget.Editor = Editor;
/** @typedef {{valid: boolean, errorMessage: (string|undefined)}} */
UI.ListWidget.ValidatorResult;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
index 30f0ad36fb9..43364b1c4f5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
@@ -25,13 +25,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.
*/
-// For testing.
-UI.panels = {};
/**
* @unrestricted
*/
-UI.Panel = class extends UI.VBox {
+export default class Panel extends UI.VBox {
/**
* @param {string} name
*/
@@ -65,33 +63,12 @@ UI.Panel = class extends UI.VBox {
elementsToRestoreScrollPositionsFor() {
return [];
}
-
- /**
- * @param {!UI.Infobar} infobar
- */
- showInfobar(infobar) {
- infobar.setCloseCallback(this._onInfobarClosed.bind(this, infobar));
- if (this.element.firstChild)
- this.element.insertBefore(infobar.element, this.element.firstChild);
- else
- this.element.appendChild(infobar.element);
- infobar.setParentView(this);
- this.doResize();
- }
-
- /**
- * @param {!UI.Infobar} infobar
- */
- _onInfobarClosed(infobar) {
- infobar.element.remove();
- this.doResize();
- }
-};
+}
/**
* @unrestricted
*/
-UI.PanelWithSidebar = class extends UI.Panel {
+export class PanelWithSidebar extends Panel {
/**
* @param {string} name
* @param {number=} defaultWidth
@@ -133,4 +110,19 @@ UI.PanelWithSidebar = class extends UI.Panel {
splitWidget() {
return this._panelSplitWidget;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Panel = Panel;
+
+/** @constructor */
+UI.PanelWithSidebar = PanelWithSidebar;
+
+// For testing.
+UI.panels = {}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Popover.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/PopoverHelper.js
index b8ba3bd2020..5f8fd7643ef 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Popover.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/PopoverHelper.js
@@ -28,7 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-UI.PopoverHelper = class {
+export default class PopoverHelper {
/**
* @param {!Element} container
* @param {function(!MouseEvent):?UI.PopoverRequest} getRequest
@@ -95,8 +95,9 @@ UI.PopoverHelper = class {
this.hidePopover();
return;
}
- if (this._eventInScheduledContent(event))
+ if (this._eventInScheduledContent(event)) {
return;
+ }
this._startHidePopoverTimer(0);
this._stopShowPopoverTimer();
@@ -108,13 +109,15 @@ UI.PopoverHelper = class {
*/
_mouseMove(event) {
// Pretend that nothing has happened.
- if (this._eventInScheduledContent(event))
+ if (this._eventInScheduledContent(event)) {
return;
+ }
this._startHidePopoverTimer(this._hideTimeout);
this._stopShowPopoverTimer();
- if (event.which && this._disableOnClick)
+ if (event.which && this._disableOnClick) {
return;
+ }
this._startShowPopoverTimer(
/** @type {!MouseEvent} */ (event), this.isPopoverVisible() ? this._showTimeout * 0.6 : this._showTimeout);
}
@@ -131,20 +134,24 @@ UI.PopoverHelper = class {
* @param {!Event} event
*/
_popoverMouseOut(popover, event) {
- if (!popover.isShowing())
+ if (!popover.isShowing()) {
return;
- if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(popover.contentElement))
+ }
+ if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(popover.contentElement)) {
this._startHidePopoverTimer(this._hideTimeout);
+ }
}
/**
* @param {!Event} event
*/
_mouseOut(event) {
- if (!this.isPopoverVisible())
+ if (!this.isPopoverVisible()) {
return;
- if (!this._eventInScheduledContent(event))
+ }
+ if (!this._eventInScheduledContent(event)) {
this._startHidePopoverTimer(this._hideTimeout);
+ }
}
/**
@@ -152,8 +159,9 @@ UI.PopoverHelper = class {
*/
_startHidePopoverTimer(timeout) {
// User has |timeout| ms to reach the popup.
- if (!this._hidePopoverCallback || this._hidePopoverTimer)
+ if (!this._hidePopoverCallback || this._hidePopoverTimer) {
return;
+ }
this._hidePopoverTimer = setTimeout(() => {
this._hidePopover();
@@ -167,8 +175,9 @@ UI.PopoverHelper = class {
*/
_startShowPopoverTimer(event, timeout) {
this._scheduledRequest = this._getRequest.call(null, event);
- if (!this._scheduledRequest)
+ if (!this._scheduledRequest) {
return;
+ }
this._showPopoverTimer = setTimeout(() => {
this._showPopoverTimer = null;
@@ -179,8 +188,9 @@ UI.PopoverHelper = class {
}
_stopShowPopoverTimer() {
- if (!this._showPopoverTimer)
+ if (!this._showPopoverTimer) {
return;
+ }
clearTimeout(this._showPopoverTimer);
this._showPopoverTimer = null;
}
@@ -198,8 +208,9 @@ UI.PopoverHelper = class {
}
_hidePopover() {
- if (!this._hidePopoverCallback)
+ if (!this._hidePopoverCallback) {
return;
+ }
this._hidePopoverCallback.call(null);
this._hidePopoverCallback = null;
}
@@ -214,21 +225,23 @@ UI.PopoverHelper = class {
popover.setMarginBehavior(UI.GlassPane.MarginBehavior.Arrow);
const request = this._scheduledRequest;
request.show.call(null, popover).then(success => {
- if (!success)
+ if (!success) {
return;
+ }
if (this._scheduledRequest !== request) {
- if (request.hide)
+ if (request.hide) {
request.hide.call(null);
+ }
return;
}
// This should not happen, but we hide previous popover to be on the safe side.
- if (UI.PopoverHelper._popoverHelper) {
+ if (PopoverHelper._popoverHelper) {
console.error('One popover is already visible');
- UI.PopoverHelper._popoverHelper.hidePopover();
+ PopoverHelper._popoverHelper.hidePopover();
}
- UI.PopoverHelper._popoverHelper = this;
+ PopoverHelper._popoverHelper = this;
popover.contentElement.classList.toggle('has-padding', this._hasPadding);
popover.contentElement.addEventListener('mousemove', this._popoverMouseMove.bind(this), true);
@@ -237,17 +250,19 @@ UI.PopoverHelper = class {
popover.show(document);
this._hidePopoverCallback = () => {
- if (request.hide)
+ if (request.hide) {
request.hide.call(null);
+ }
popover.hide();
- delete UI.PopoverHelper._popoverHelper;
+ delete PopoverHelper._popoverHelper;
};
});
}
_stopHidePopoverTimer() {
- if (!this._hidePopoverTimer)
+ if (!this._hidePopoverTimer) {
return;
+ }
clearTimeout(this._hidePopoverTimer);
this._hidePopoverTimer = null;
@@ -261,7 +276,16 @@ UI.PopoverHelper = class {
this._container.removeEventListener('mousemove', this._boundMouseMove, false);
this._container.removeEventListener('mouseout', this._boundMouseOut, false);
}
-};
+}
/** @typedef {{box: !AnchorBox, show:(function(!UI.GlassPane):!Promise<boolean>), hide:(function()|undefined)}} */
UI.PopoverRequest;
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.PopoverHelper = PopoverHelper;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ProgressIndicator.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ProgressIndicator.js
index 2c8bb284f12..59ec43912e3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ProgressIndicator.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ProgressIndicator.js
@@ -31,7 +31,7 @@
* @implements {Common.Progress}
* @unrestricted
*/
-UI.ProgressIndicator = class {
+export default class ProgressIndicator {
constructor() {
this.element = createElementWithClass('div', 'progress-indicator');
this._shadowRoot = UI.createShadowRootWithCoreStyles(this.element, 'ui/progressIndicator.css');
@@ -58,8 +58,9 @@ UI.ProgressIndicator = class {
* @override
*/
done() {
- if (this._isDone)
+ if (this._isDone) {
return;
+ }
this._isDone = true;
this.element.remove();
}
@@ -100,8 +101,9 @@ UI.ProgressIndicator = class {
setWorked(worked, title) {
this._worked = worked;
this._progressElement.value = worked;
- if (title)
+ if (title) {
this.setTitle(title);
+ }
}
/**
@@ -111,4 +113,13 @@ UI.ProgressIndicator = class {
worked(worked) {
this.setWorked(this._worked + (worked || 1));
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ProgressIndicator = ProgressIndicator;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js
index 72058974ded..b416a024e4f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/RemoteDebuggingTerminatedScreen.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.RemoteDebuggingTerminatedScreen = class extends UI.VBox {
+export default class RemoteDebuggingTerminatedScreen extends UI.VBox {
/**
* @param {string} reason
*/
@@ -27,7 +27,16 @@ UI.RemoteDebuggingTerminatedScreen = class extends UI.VBox {
dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
dialog.addCloseButton();
dialog.setDimmed(true);
- new UI.RemoteDebuggingTerminatedScreen(reason).show(dialog.contentElement);
+ new RemoteDebuggingTerminatedScreen(reason).show(dialog.contentElement);
dialog.show();
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.RemoteDebuggingTerminatedScreen = RemoteDebuggingTerminatedScreen;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ReportView.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ReportView.js
index ab90dc59a44..be188a11f1f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ReportView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ReportView.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.ReportView = class extends UI.VBox {
+export default class ReportView extends UI.VBox {
/**
* @param {string=} title
*/
@@ -25,8 +25,9 @@ UI.ReportView = class extends UI.VBox {
* @param {string} title
*/
setTitle(title) {
- if (this._titleElement.textContent === title)
+ if (this._titleElement.textContent === title) {
return;
+ }
this._titleElement.textContent = title;
}
@@ -34,10 +35,12 @@ UI.ReportView = class extends UI.VBox {
* @param {string} subtitle
*/
setSubtitle(subtitle) {
- if (this._subtitleElement && this._subtitleElement.textContent === subtitle)
+ if (this._subtitleElement && this._subtitleElement.textContent === subtitle) {
return;
- if (!this._subtitleElement)
+ }
+ if (!this._subtitleElement) {
this._subtitleElement = this._headerElement.createChild('div', 'report-subtitle');
+ }
this._subtitleElement.textContent = subtitle;
}
@@ -45,11 +48,13 @@ UI.ReportView = class extends UI.VBox {
* @param {?Element} link
*/
setURL(link) {
- if (!this._urlElement)
+ if (!this._urlElement) {
this._urlElement = this._headerElement.createChild('div', 'report-url link');
+ }
this._urlElement.removeChildren();
- if (link)
+ if (link) {
this._urlElement.appendChild(link);
+ }
}
/**
@@ -64,27 +69,29 @@ UI.ReportView = class extends UI.VBox {
/**
* @param {string} title
* @param {string=} className
- * @return {!UI.ReportView.Section}
+ * @return {!Section}
*/
appendSection(title, className) {
- const section = new UI.ReportView.Section(title, className);
+ const section = new Section(title, className);
section.show(this._sectionList);
return section;
}
/**
- * @param {function(!UI.ReportView.Section, !UI.ReportView.Section): number} comparator
+ * @param {function(!Section, !Section): number} comparator
*/
sortSections(comparator) {
- const sections = /** @type {!Array<!UI.ReportView.Section>} */ (this.children().slice());
+ const sections = /** @type {!Array<!Section>} */ (this.children().slice());
const sorted = sections.every((e, i, a) => !i || comparator(a[i - 1], a[i]) <= 0);
- if (sorted)
+ if (sorted) {
return;
+ }
this.detachChildWidgets();
sections.sort(comparator);
- for (const section of sections)
+ for (const section of sections) {
section.show(this._sectionList);
+ }
}
/**
@@ -101,12 +108,12 @@ UI.ReportView = class extends UI.VBox {
setBodyScrollable(scrollable) {
this._contentBox.classList.toggle('no-scroll', !scrollable);
}
-};
+}
/**
* @unrestricted
*/
-UI.ReportView.Section = class extends UI.VBox {
+export class Section extends UI.VBox {
/**
* @param {string} title
* @param {string=} className
@@ -114,8 +121,9 @@ UI.ReportView.Section = class extends UI.VBox {
constructor(title, className) {
super();
this.element.classList.add('report-section');
- if (className)
+ if (className) {
this.element.classList.add(className);
+ }
this._headerElement = this.element.createChild('div', 'report-section-header');
this._titleElement = this._headerElement.createChild('div', 'report-section-title');
this.setTitle(title);
@@ -136,12 +144,22 @@ UI.ReportView.Section = class extends UI.VBox {
* @param {string} title
*/
setTitle(title) {
- if (this._titleElement.textContent !== title)
+ if (this._titleElement.textContent !== title) {
this._titleElement.textContent = title;
+ }
this._titleElement.classList.toggle('hidden', !this._titleElement.textContent);
}
/**
+ * Declares the overall container to be a group and assigns a title.
+ * @param {string} groupTitle
+ */
+ setUiGroupTitle(groupTitle) {
+ UI.ARIAUtils.markAsGroup(this.element);
+ UI.ARIAUtils.setAccessibleName(this.element, groupTitle);
+ }
+
+ /**
* @return {!UI.Toolbar}
*/
createToolbar() {
@@ -163,8 +181,9 @@ UI.ReportView.Section = class extends UI.VBox {
this._fieldMap.set(title, row);
row.createChild('div', 'report-field-value');
}
- if (textValue)
+ if (textValue) {
row.lastElementChild.textContent = textValue;
+ }
return /** @type {!Element} */ (row.lastElementChild);
}
@@ -173,8 +192,9 @@ UI.ReportView.Section = class extends UI.VBox {
*/
removeField(title) {
const row = this._fieldMap.get(title);
- if (row)
+ if (row) {
row.remove();
+ }
this._fieldMap.delete(title);
}
@@ -184,8 +204,9 @@ UI.ReportView.Section = class extends UI.VBox {
*/
setFieldVisible(title, visible) {
const row = this._fieldMap.get(title);
- if (row)
+ if (row) {
row.classList.toggle('hidden', !visible);
+ }
}
/**
@@ -220,4 +241,18 @@ UI.ReportView.Section = class extends UI.VBox {
UI.ARIAUtils.markAsGroup(this._fieldList);
UI.ARIAUtils.setAccessibleName(this._fieldList, this.title());
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ReportView = ReportView;
+
+/**
+ * @constructor
+ */
+UI.ReportView.Section = Section;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ResizerWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ResizerWidget.js
index 6e3fbb31e7c..8db3716685d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ResizerWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ResizerWidget.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.ResizerWidget = class extends Common.Object {
+export default class ResizerWidget extends Common.Object {
constructor() {
super();
@@ -40,8 +40,9 @@ UI.ResizerWidget = class extends Common.Object {
* @param {!Element} element
*/
addElement(element) {
- if (this._elements.indexOf(element) !== -1)
+ if (this._elements.indexOf(element) !== -1) {
return;
+ }
this._elements.push(element);
element.addEventListener('mousedown', this._installDragOnMouseDownBound, false);
@@ -52,8 +53,9 @@ UI.ResizerWidget = class extends Common.Object {
* @param {!Element} element
*/
removeElement(element) {
- if (this._elements.indexOf(element) === -1)
+ if (this._elements.indexOf(element) === -1) {
return;
+ }
this._elements.remove(element);
element.removeEventListener('mousedown', this._installDragOnMouseDownBound, false);
@@ -68,10 +70,11 @@ UI.ResizerWidget = class extends Common.Object {
* @param {!Element} element
*/
_updateElementCursor(element) {
- if (this._isEnabled)
+ if (this._isEnabled) {
element.style.setProperty('cursor', this.cursor());
- else
+ } else {
element.style.removeProperty('cursor');
+ }
}
/**
@@ -94,8 +97,9 @@ UI.ResizerWidget = class extends Common.Object {
*/
_installDragOnMouseDown(event) {
// Only handle drags of the nodes specified.
- if (this._elements.indexOf(event.target) === -1)
+ if (this._elements.indexOf(event.target) === -1) {
return false;
+ }
UI.elementDragStart(
/** @type {!Element} */ (event.target), this._dragStart.bind(this), this._drag.bind(this),
this._dragEnd.bind(this), this.cursor(), event);
@@ -106,8 +110,9 @@ UI.ResizerWidget = class extends Common.Object {
* @return {boolean}
*/
_dragStart(event) {
- if (!this._isEnabled)
+ if (!this._isEnabled) {
return false;
+ }
this._startX = event.pageX;
this._startY = event.pageY;
this.sendDragStart(this._startX, this._startY);
@@ -119,8 +124,7 @@ UI.ResizerWidget = class extends Common.Object {
* @param {number} y
*/
sendDragStart(x, y) {
- this.dispatchEventToListeners(
- UI.ResizerWidget.Events.ResizeStart, {startX: x, currentX: x, startY: y, currentY: y});
+ this.dispatchEventToListeners(Events.ResizeStart, {startX: x, currentX: x, startY: y, currentY: y});
}
/**
@@ -147,7 +151,7 @@ UI.ResizerWidget = class extends Common.Object {
*/
sendDragMove(startX, currentX, startY, currentY, shiftKey) {
this.dispatchEventToListeners(
- UI.ResizerWidget.Events.ResizeUpdate,
+ Events.ResizeUpdate,
{startX: startX, currentX: currentX, startY: startY, currentY: currentY, shiftKey: shiftKey});
}
@@ -155,14 +159,14 @@ UI.ResizerWidget = class extends Common.Object {
* @param {!MouseEvent} event
*/
_dragEnd(event) {
- this.dispatchEventToListeners(UI.ResizerWidget.Events.ResizeEnd);
+ this.dispatchEventToListeners(Events.ResizeEnd);
delete this._startX;
delete this._startY;
}
-};
+}
/** @enum {symbol} */
-UI.ResizerWidget.Events = {
+export const Events = {
ResizeStart: Symbol('ResizeStart'),
ResizeUpdate: Symbol('ResizeUpdate'),
ResizeEnd: Symbol('ResizeEnd')
@@ -171,7 +175,7 @@ UI.ResizerWidget.Events = {
/**
* @unrestricted
*/
-UI.SimpleResizerWidget = class extends UI.ResizerWidget {
+export class SimpleResizerWidget extends ResizerWidget {
constructor() {
super();
this._isVertical = true;
@@ -208,8 +212,7 @@ UI.SimpleResizerWidget = class extends UI.ResizerWidget {
*/
sendDragStart(x, y) {
const position = this._isVertical ? y : x;
- this.dispatchEventToListeners(
- UI.ResizerWidget.Events.ResizeStart, {startPosition: position, currentPosition: position});
+ this.dispatchEventToListeners(Events.ResizeStart, {startPosition: position, currentPosition: position});
}
/**
@@ -223,10 +226,25 @@ UI.SimpleResizerWidget = class extends UI.ResizerWidget {
sendDragMove(startX, currentX, startY, currentY, shiftKey) {
if (this._isVertical) {
this.dispatchEventToListeners(
- UI.ResizerWidget.Events.ResizeUpdate, {startPosition: startY, currentPosition: currentY, shiftKey: shiftKey});
+ Events.ResizeUpdate, {startPosition: startY, currentPosition: currentY, shiftKey: shiftKey});
} else {
this.dispatchEventToListeners(
- UI.ResizerWidget.Events.ResizeUpdate, {startPosition: startX, currentPosition: currentX, shiftKey: shiftKey});
+ Events.ResizeUpdate, {startPosition: startX, currentPosition: currentX, shiftKey: shiftKey});
}
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ResizerWidget = ResizerWidget;
+
+/** @enum {symbol} */
+UI.ResizerWidget.Events = Events;
+
+/** @constructor */
+UI.SimpleResizerWidget = SimpleResizerWidget; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/RootView.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/RootView.js
index f6f361b3828..6f599ae5094 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/RootView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/RootView.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.RootView = class extends UI.VBox {
+export default class RootView extends UI.VBox {
constructor() {
super();
this.markAsRoot();
@@ -37,4 +37,13 @@ UI.RootView = class extends UI.VBox {
}
super.doResize();
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.RootView = RootView;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SearchableView.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SearchableView.js
index b03b61fb87b..132375c6ec6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SearchableView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SearchableView.js
@@ -32,15 +32,15 @@
/**
* @unrestricted
*/
-UI.SearchableView = class extends UI.VBox {
+export default class SearchableView extends UI.VBox {
/**
- * @param {!UI.Searchable} searchable
+ * @param {!Searchable} searchable
* @param {string=} settingName
*/
constructor(searchable, settingName) {
super(true);
this.registerRequiredCSS('ui/searchableView.css');
- this.element[UI.SearchableView._symbol] = this;
+ this.element[_symbol] = this;
this._searchProvider = searchable;
this._setting = settingName ? Common.settings.createSetting(settingName, {}) : null;
@@ -129,12 +129,12 @@ UI.SearchableView = class extends UI.VBox {
/**
* @param {?Element} element
- * @return {?UI.SearchableView}
+ * @return {?SearchableView}
*/
static fromElement(element) {
let view = null;
while (element && !view) {
- view = element[UI.SearchableView._symbol];
+ view = element[_symbol];
element = element.parentElementOrShadowHost();
}
return view;
@@ -158,8 +158,9 @@ UI.SearchableView = class extends UI.VBox {
}
_saveSetting() {
- if (!this._setting)
+ if (!this._setting) {
return;
+ }
const settingValue = this._setting.get() || {};
settingValue.caseSensitive = this._caseSensitiveButton.toggled();
settingValue.isRegex = this._regexButton.toggled();
@@ -168,10 +169,12 @@ UI.SearchableView = class extends UI.VBox {
_loadSetting() {
const settingValue = this._setting ? (this._setting.get() || {}) : {};
- if (this._searchProvider.supportsCaseSensitiveSearch())
+ if (this._searchProvider.supportsCaseSensitiveSearch()) {
this._caseSensitiveButton.setToggled(!!settingValue.caseSensitive);
- if (this._searchProvider.supportsRegexSearch())
+ }
+ if (this._searchProvider.supportsRegexSearch()) {
this._regexButton.setToggled(!!settingValue.isRegex);
+ }
}
/**
@@ -197,16 +200,19 @@ UI.SearchableView = class extends UI.VBox {
/**
* @param {number} matches
+ * @suppress {checkTypes}
*/
updateSearchMatchesCount(matches) {
- if (this._searchProvider.currentSearchMatches === matches)
+ if (this._searchProvider.currentSearchMatches === matches) {
return;
+ }
this._searchProvider.currentSearchMatches = matches;
this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentQuery ? matches : 0, -1);
}
/**
* @param {number} currentMatchIndex
+ * @suppress {checkTypes}
*/
updateCurrentMatchIndex(currentMatchIndex) {
this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentSearchMatches, currentMatchIndex);
@@ -221,8 +227,9 @@ UI.SearchableView = class extends UI.VBox {
closeSearch() {
this.cancelSearch();
- if (this._footerElementContainer.hasFocus())
+ if (this._footerElementContainer.hasFocus()) {
this.focus();
+ }
}
_toggleSearchBar(toggled) {
@@ -231,8 +238,9 @@ UI.SearchableView = class extends UI.VBox {
}
cancelSearch() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return;
+ }
this.resetSearch();
delete this._searchIsVisible;
this._toggleSearchBar(false);
@@ -245,8 +253,9 @@ UI.SearchableView = class extends UI.VBox {
}
refreshSearch() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return;
+ }
this.resetSearch();
this._performSearch(false, false);
}
@@ -255,8 +264,9 @@ UI.SearchableView = class extends UI.VBox {
* @return {boolean}
*/
handleFindNextShortcut() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return false;
+ }
this._searchProvider.jumpToNextSearchResult();
return true;
}
@@ -265,8 +275,9 @@ UI.SearchableView = class extends UI.VBox {
* @return {boolean}
*/
handleFindPreviousShortcut() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return false;
+ }
this._searchProvider.jumpToPreviousSearchResult();
return true;
}
@@ -283,8 +294,9 @@ UI.SearchableView = class extends UI.VBox {
* @return {boolean}
*/
handleCancelSearchShortcut() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return false;
+ }
this.closeSearch();
return true;
}
@@ -304,32 +316,36 @@ UI.SearchableView = class extends UI.VBox {
* @param {number} currentMatchIndex
*/
_updateSearchMatchesCountAndCurrentMatchIndex(matches, currentMatchIndex) {
- if (!this._currentQuery)
+ if (!this._currentQuery) {
this._matchesElement.textContent = '';
- else if (matches === 0 || currentMatchIndex >= 0)
+ } else if (matches === 0 || currentMatchIndex >= 0) {
this._matchesElement.textContent = Common.UIString('%d of %d', currentMatchIndex + 1, matches);
- else if (matches === 1)
+ } else if (matches === 1) {
this._matchesElement.textContent = Common.UIString('1 match');
- else
+ } else {
this._matchesElement.textContent = Common.UIString('%d matches', matches);
+ }
this._updateSearchNavigationButtonState(matches > 0);
}
showSearchField() {
- if (this._searchIsVisible)
+ if (this._searchIsVisible) {
this.cancelSearch();
+ }
let queryCandidate;
if (!this._searchInputElement.hasFocus()) {
const selection = UI.inspectorView.element.window().getSelection();
- if (selection.rangeCount)
+ if (selection.rangeCount) {
queryCandidate = selection.toString().replace(/\r?\n.*/, '');
+ }
}
this._toggleSearchBar(true);
this._updateReplaceVisibility();
- if (queryCandidate)
+ if (queryCandidate) {
this._searchInputElement.value = queryCandidate;
+ }
this._performSearch(false, false);
this._searchInputElement.focus();
this._searchInputElement.select();
@@ -353,66 +369,76 @@ UI.SearchableView = class extends UI.VBox {
event.consume(true);
return;
}
- if (!isEnterKey(event))
+ if (!isEnterKey(event)) {
return;
+ }
- if (!this._currentQuery)
+ if (!this._currentQuery) {
this._performSearch(true, true, event.shiftKey);
- else
+ } else {
this._jumpToNextSearchResult(event.shiftKey);
+ }
}
/**
* @param {!Event} event
*/
_onReplaceKeyDown(event) {
- if (isEnterKey(event))
+ if (isEnterKey(event)) {
this._replace();
+ }
}
/**
* @param {boolean=} isBackwardSearch
*/
_jumpToNextSearchResult(isBackwardSearch) {
- if (!this._currentQuery)
+ if (!this._currentQuery) {
return;
+ }
- if (isBackwardSearch)
+ if (isBackwardSearch) {
this._searchProvider.jumpToPreviousSearchResult();
- else
+ } else {
this._searchProvider.jumpToNextSearchResult();
+ }
}
_onNextButtonSearch(event) {
- if (!this._searchNavigationNextElement.classList.contains('enabled'))
+ if (!this._searchNavigationNextElement.classList.contains('enabled')) {
return;
+ }
this._jumpToNextSearchResult();
this._searchInputElement.focus();
}
_onPrevButtonSearch(event) {
- if (!this._searchNavigationPrevElement.classList.contains('enabled'))
+ if (!this._searchNavigationPrevElement.classList.contains('enabled')) {
return;
+ }
this._jumpToNextSearchResult(true);
this._searchInputElement.focus();
}
_onFindClick(event) {
- if (!this._currentQuery)
+ if (!this._currentQuery) {
this._performSearch(true, true);
- else
+ } else {
this._jumpToNextSearchResult();
+ }
this._searchInputElement.focus();
}
_onPreviousClick(event) {
- if (!this._currentQuery)
+ if (!this._currentQuery) {
this._performSearch(true, true, true);
- else
+ } else {
this._jumpToNextSearchResult(true);
+ }
this._searchInputElement.focus();
}
+ /** @suppress {checkTypes} */
_clearSearch() {
delete this._currentQuery;
if (!!this._searchProvider.currentQuery) {
@@ -426,6 +452,7 @@ UI.SearchableView = class extends UI.VBox {
* @param {boolean} forceSearch
* @param {boolean} shouldJump
* @param {boolean=} jumpBackwards
+ * @suppress {checkTypes}
*/
_performSearch(forceSearch, shouldJump, jumpBackwards) {
const query = this._searchInputElement.value;
@@ -442,13 +469,13 @@ UI.SearchableView = class extends UI.VBox {
}
/**
- * @return {!UI.SearchableView.SearchConfig}
+ * @return {!SearchConfig}
*/
_currentSearchConfig() {
const query = this._searchInputElement.value;
const caseSensitive = this._caseSensitiveButton ? this._caseSensitiveButton.toggled() : false;
const isRegex = this._regexButton ? this._regexButton.toggled() : false;
- return new UI.SearchableView.SearchConfig(query, caseSensitive, isRegex);
+ return new SearchConfig(query, caseSensitive, isRegex);
}
_updateSecondRowVisibility() {
@@ -457,10 +484,11 @@ UI.SearchableView = class extends UI.VBox {
this._secondRowButtons.classList.toggle('hidden', !secondRowVisible);
this._replaceInputElement.classList.toggle('hidden', !secondRowVisible);
- if (secondRowVisible)
+ if (secondRowVisible) {
this._replaceInputElement.focus();
- else
+ } else {
this._searchInputElement.focus();
+ }
this.doResize();
}
@@ -481,77 +509,80 @@ UI.SearchableView = class extends UI.VBox {
* @param {!Event} event
*/
_onInput(event) {
- if (this._valueChangedTimeoutId)
+ if (this._valueChangedTimeoutId) {
clearTimeout(this._valueChangedTimeoutId);
+ }
const timeout = this._searchInputElement.value.length < 3 ? 200 : 0;
this._valueChangedTimeoutId = setTimeout(this._onValueChanged.bind(this), timeout);
}
_onValueChanged() {
- if (!this._searchIsVisible)
+ if (!this._searchIsVisible) {
return;
+ }
delete this._valueChangedTimeoutId;
this._performSearch(false, true);
}
-};
-
+}
-UI.SearchableView._symbol = Symbol('searchableView');
+export const _symbol = Symbol('searchableView');
/**
* @interface
*/
-UI.Searchable = function() {};
-
-UI.Searchable.prototype = {
- searchCanceled() {},
+export class Searchable {
+ searchCanceled() {
+ }
/**
- * @param {!UI.SearchableView.SearchConfig} searchConfig
+ * @param {!SearchConfig} searchConfig
* @param {boolean} shouldJump
* @param {boolean=} jumpBackwards
*/
- performSearch(searchConfig, shouldJump, jumpBackwards) {},
+ performSearch(searchConfig, shouldJump, jumpBackwards) {
+ }
- jumpToNextSearchResult() {},
+ jumpToNextSearchResult() {
+ }
- jumpToPreviousSearchResult() {},
+ jumpToPreviousSearchResult() {
+ }
/**
* @return {boolean}
*/
- supportsCaseSensitiveSearch() {},
+ supportsCaseSensitiveSearch() {
+ }
/**
* @return {boolean}
*/
supportsRegexSearch() {}
-};
+}
/**
* @interface
*/
-UI.Replaceable = function() {};
-
-UI.Replaceable.prototype = {
+export class Replaceable {
/**
- * @param {!UI.SearchableView.SearchConfig} searchConfig
+ * @param {!SearchConfig} searchConfig
* @param {string} replacement
*/
- replaceSelectionWith(searchConfig, replacement) {},
+ replaceSelectionWith(searchConfig, replacement) {
+ }
/**
- * @param {!UI.SearchableView.SearchConfig} searchConfig
+ * @param {!SearchConfig} searchConfig
* @param {string} replacement
*/
replaceAllWith(searchConfig, replacement) {}
-};
+}
/**
* @unrestricted
*/
-UI.SearchableView.SearchConfig = class {
+export class SearchConfig {
/**
* @param {string} query
* @param {boolean} caseSensitive
@@ -569,8 +600,9 @@ UI.SearchableView.SearchConfig = class {
*/
toSearchRegex(global) {
let modifiers = this.caseSensitive ? '' : 'i';
- if (global)
+ if (global) {
modifiers += 'g';
+ }
const query = this.isRegex ? '/' + this.query + '/' : this.query;
let regex;
@@ -586,9 +618,30 @@ UI.SearchableView.SearchConfig = class {
}
// Otherwise just do a plain text search.
- if (!regex)
+ if (!regex) {
regex = createPlainTextSearchRegex(query, modifiers);
+ }
return regex;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SearchableView = SearchableView;
+
+/**
+ * @constructor
+ */
+UI.SearchableView.SearchConfig = SearchConfig;
+
+/** @interface */
+UI.Searchable = Searchable;
+
+/** @interface */
+UI.Replaceable = Replaceable; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SegmentedButton.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SegmentedButton.js
index 194ee18fc72..0cd2bec374d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SegmentedButton.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SegmentedButton.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.SegmentedButton = class extends UI.HBox {
+export default class SegmentedButton extends UI.HBox {
constructor() {
super(true);
/** @type {!Map<string, !Element>} */
@@ -31,11 +31,13 @@ UI.SegmentedButton = class extends UI.HBox {
* @param {string} value
*/
select(value) {
- if (this._selected === value)
+ if (this._selected === value) {
return;
+ }
this._selected = value;
- for (const key of this._buttons.keys())
+ for (const key of this._buttons.keys()) {
this._buttons.get(key).classList.toggle('segmented-button-segment-selected', key === this._selected);
+ }
}
/**
@@ -44,4 +46,13 @@ UI.SegmentedButton = class extends UI.HBox {
selected() {
return this._selected;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SegmentedButton = SegmentedButton;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SettingsUI.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SettingsUI.js
index fe24f074139..5bd9117fdaa 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SettingsUI.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SettingsUI.js
@@ -27,7 +27,9 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-UI.SettingsUI = {};
+const SettingsUI = {};
+
+export default SettingsUI;
/**
* @param {string} name
@@ -36,17 +38,19 @@ UI.SettingsUI = {};
* @param {string=} tooltip
* @return {!Element}
*/
-UI.SettingsUI.createSettingCheckbox = function(name, setting, omitParagraphElement, tooltip) {
+export const createSettingCheckbox = function(name, setting, omitParagraphElement, tooltip) {
const label = UI.CheckboxLabel.create(name);
- if (tooltip)
+ if (tooltip) {
label.title = tooltip;
+ }
const input = label.checkboxElement;
input.name = name;
- UI.SettingsUI.bindCheckbox(input, setting);
+ bindCheckbox(input, setting);
- if (omitParagraphElement)
+ if (omitParagraphElement) {
return label;
+ }
const p = createElement('p');
p.appendChild(label);
@@ -57,13 +61,18 @@ UI.SettingsUI.createSettingCheckbox = function(name, setting, omitParagraphEleme
* @param {string} name
* @param {!Array<!{text: string, value: *, raw: (boolean|undefined)}>} options
* @param {!Common.Setting} setting
+ * @param {string=} subtitle
* @return {!Element}
*/
-UI.SettingsUI.createSettingSelect = function(name, options, setting) {
- const p = createElement('p');
- const label = p.createChild('label');
+export const createSettingSelect = function(name, options, setting, subtitle) {
+ const settingSelectElement = createElement('p');
+ const label = settingSelectElement.createChild('label');
+ const select = settingSelectElement.createChild('select', 'chrome-select');
label.textContent = name;
- const select = p.createChild('select', 'chrome-select');
+ if (subtitle) {
+ settingSelectElement.classList.add('chrome-select-label');
+ label.createChild('p').textContent = subtitle;
+ }
UI.ARIAUtils.bindLabelToControl(label, select);
for (let i = 0; i < options.length; ++i) {
@@ -76,13 +85,14 @@ UI.SettingsUI.createSettingSelect = function(name, options, setting) {
setting.addChangeListener(settingChanged);
settingChanged();
select.addEventListener('change', selectChanged, false);
- return p;
+ return settingSelectElement;
function settingChanged() {
const newValue = setting.get();
for (let i = 0; i < options.length; i++) {
- if (options[i].value === newValue)
+ if (options[i].value === newValue) {
select.selectedIndex = i;
+ }
}
}
@@ -96,17 +106,19 @@ UI.SettingsUI.createSettingSelect = function(name, options, setting) {
* @param {!Element} input
* @param {!Common.Setting} setting
*/
-UI.SettingsUI.bindCheckbox = function(input, setting) {
+export const bindCheckbox = function(input, setting) {
function settingChanged() {
- if (input.checked !== setting.get())
+ if (input.checked !== setting.get()) {
input.checked = setting.get();
+ }
}
setting.addChangeListener(settingChanged);
settingChanged();
function inputChanged() {
- if (setting.get() !== input.checked)
+ if (setting.get() !== input.checked) {
setting.set(input.checked);
+ }
}
input.addEventListener('change', inputChanged, false);
};
@@ -116,7 +128,7 @@ UI.SettingsUI.bindCheckbox = function(input, setting) {
* @param {!Element} element
* @return {!Element}
*/
-UI.SettingsUI.createCustomSetting = function(name, element) {
+export const createCustomSetting = function(name, element) {
const p = createElement('p');
const fieldsetElement = p.createChild('fieldset');
const label = fieldsetElement.createChild('label');
@@ -128,19 +140,22 @@ UI.SettingsUI.createCustomSetting = function(name, element) {
/**
* @param {!Common.Setting} setting
+ * @param {string=} subtitle
* @return {?Element}
*/
-UI.SettingsUI.createControlForSetting = function(setting) {
- if (!setting.extension())
+export const createControlForSetting = function(setting, subtitle) {
+ if (!setting.extension()) {
return null;
+ }
const descriptor = setting.extension().descriptor();
const uiTitle = Common.UIString(setting.title() || '');
switch (descriptor['settingType']) {
case 'boolean':
- return UI.SettingsUI.createSettingCheckbox(uiTitle, setting);
+ return createSettingCheckbox(uiTitle, setting);
case 'enum':
- if (Array.isArray(descriptor['options']))
- return UI.SettingsUI.createSettingSelect(uiTitle, descriptor['options'], setting);
+ if (Array.isArray(descriptor['options'])) {
+ return createSettingSelect(uiTitle, descriptor['options'], setting, subtitle);
+ }
console.error('Enum setting defined without options');
return null;
default:
@@ -152,11 +167,60 @@ UI.SettingsUI.createControlForSetting = function(setting) {
/**
* @interface
*/
-UI.SettingUI = function() {};
-
-UI.SettingUI.prototype = {
+export class SettingUI {
/**
* @return {?Element}
*/
settingElement() {}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+UI.SettingsUI = SettingsUI;
+
+/**
+ * @interface
+ */
+UI.SettingUI = SettingUI;
+
+/**
+ * @param {string} name
+ * @param {!Common.Setting} setting
+ * @param {boolean=} omitParagraphElement
+ * @param {string=} tooltip
+ * @return {!Element}
+ */
+UI.SettingsUI.createSettingCheckbox = createSettingCheckbox;
+
+/**
+ * @param {string} name
+ * @param {!Array<!{text: string, value: *, raw: (boolean|undefined)}>} options
+ * @param {!Common.Setting} setting
+ * @param {string=} subtitle
+ * @return {!Element}
+ */
+UI.SettingsUI.createSettingSelect = createSettingSelect;
+
+/**
+ * @param {!Element} input
+ * @param {!Common.Setting} setting
+ */
+UI.SettingsUI.bindCheckbox = bindCheckbox;
+
+/**
+ * @param {string} name
+ * @param {!Element} element
+ * @return {!Element}
+ */
+UI.SettingsUI.createCustomSetting = createCustomSetting;
+
+/**
+ * @param {!Common.Setting} setting
+ * @param {string=} subtitle
+ * @return {?Element}
+ */
+UI.SettingsUI.createControlForSetting = createControlForSetting;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
index 648ca00c381..9ebb8af8f07 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
@@ -4,17 +4,17 @@
/**
* @unrestricted
*/
-UI.ShortcutRegistry = class {
+export default class ShortcutRegistry {
/**
* @param {!UI.ActionRegistry} actionRegistry
* @param {!Document} document
*/
constructor(actionRegistry, document) {
this._actionRegistry = actionRegistry;
- /** @type {!Multimap.<string, string>} */
- this._defaultKeyToActions = new Multimap();
- /** @type {!Multimap.<string, !UI.KeyboardShortcut.Descriptor>} */
- this._defaultActionToShortcut = new Multimap();
+ /** @type {!Platform.Multimap.<string, string>} */
+ this._defaultKeyToActions = new Platform.Multimap();
+ /** @type {!Platform.Multimap.<string, !UI.KeyboardShortcut.Descriptor>} */
+ this._defaultActionToShortcut = new Platform.Multimap();
this._registerBindings(document);
}
@@ -42,8 +42,9 @@ UI.ShortcutRegistry = class {
for (const key of this._defaultKeyToActions.keysArray()) {
const actions = this._defaultKeyToActions.get(key).valuesArray();
const applicableActions = this._actionRegistry.applicableActions(actions, new UI.Context());
- if (applicableActions.length)
+ if (applicableActions.length) {
keys.push(Number(key));
+ }
}
return keys;
}
@@ -64,8 +65,9 @@ UI.ShortcutRegistry = class {
const result = [];
for (let i = 0; i < actionIds.length; ++i) {
const descriptors = this.shortcutDescriptorsForAction(actionIds[i]);
- for (let j = 0; j < descriptors.length; ++j)
+ for (let j = 0; j < descriptors.length; ++j) {
result.push(descriptors[j].key);
+ }
}
return result;
}
@@ -76,8 +78,9 @@ UI.ShortcutRegistry = class {
*/
shortcutTitleForAction(actionId) {
const descriptors = this.shortcutDescriptorsForAction(actionId);
- if (descriptors.length)
+ if (descriptors.length) {
return descriptors[0].name;
+ }
}
/**
@@ -107,8 +110,9 @@ UI.ShortcutRegistry = class {
addShortcutListener(element, actionId, listener, capture) {
console.assert(this._defaultActionToShortcut.has(actionId), 'Unknown action ' + actionId);
element.addEventListener('keydown', event => {
- if (!this.eventMatchesAction(/** @type {!KeyboardEvent} */ (event), actionId) || !listener.call(null))
+ if (!this.eventMatchesAction(/** @type {!KeyboardEvent} */ (event), actionId) || !listener.call(null)) {
return;
+ }
event.consume(true);
}, capture);
}
@@ -121,45 +125,57 @@ UI.ShortcutRegistry = class {
async handleKey(key, domKey, event) {
const keyModifiers = key >> 8;
const actions = this._applicableActions(key);
- if (!actions.length || isPossiblyInputKey())
+ if (!actions.length || isPossiblyInputKey()) {
return;
- if (event)
+ }
+ if (event) {
event.consume(true);
- if (UI.Dialog.hasInstance())
+ }
+ if (UI.Dialog.hasInstance()) {
return;
+ }
for (const action of actions) {
- if (await action.execute())
+ if (await action.execute()) {
return;
+ }
}
/**
* @return {boolean}
*/
function isPossiblyInputKey() {
- if (!event || !UI.isEditing() || /^F\d+|Control|Shift|Alt|Meta|Escape|Win|U\+001B$/.test(domKey))
+ if (!event || !UI.isEditing() || /^F\d+|Control|Shift|Alt|Meta|Escape|Win|U\+001B$/.test(domKey)) {
return false;
+ }
- if (!keyModifiers)
+ if (!keyModifiers) {
return true;
+ }
const modifiers = UI.KeyboardShortcut.Modifiers;
// Undo/Redo will also cause input, so textual undo should take precedence over DevTools undo when editing.
if (Host.isMac()) {
- if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta) === key)
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta) === key) {
return true;
- if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta | modifiers.Shift) === key)
+ }
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta | modifiers.Shift) === key) {
return true;
+ }
} else {
- if (UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl) === key)
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl) === key) {
return true;
- if (UI.KeyboardShortcut.makeKey('y', modifiers.Ctrl) === key)
+ }
+ if (UI.KeyboardShortcut.makeKey('y', modifiers.Ctrl) === key) {
return true;
- if (!Host.isWin() && UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl | modifiers.Shift) === key)
+ }
+ if (!Host.isWin() && UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl | modifiers.Shift) === key) {
return true;
+ }
}
- if ((keyModifiers & (modifiers.Ctrl | modifiers.Alt)) === (modifiers.Ctrl | modifiers.Alt))
+ if ((keyModifiers & (modifiers.Ctrl | modifiers.Alt)) === (modifiers.Ctrl | modifiers.Alt)) {
return Host.isWin();
+ }
return !hasModifier(modifiers.Ctrl) && !hasModifier(modifiers.Alt) && !hasModifier(modifiers.Meta);
}
@@ -179,8 +195,9 @@ UI.ShortcutRegistry = class {
*/
registerShortcut(actionId, shortcut) {
const descriptor = UI.KeyboardShortcut.makeDescriptorFromBindingShortcut(shortcut);
- if (!descriptor)
+ if (!descriptor) {
return;
+ }
this._defaultActionToShortcut.set(actionId, descriptor);
this._defaultKeyToActions.set(String(descriptor.key), actionId);
}
@@ -193,15 +210,16 @@ UI.ShortcutRegistry = class {
extensions.forEach(registerExtension, this);
/**
- * @param {!Runtime.Extension} extension
- * @this {UI.ShortcutRegistry}
+ * @param {!Root.Runtime.Extension} extension
+ * @this {ShortcutRegistry}
*/
function registerExtension(extension) {
const descriptor = extension.descriptor();
const bindings = descriptor['bindings'];
for (let i = 0; bindings && i < bindings.length; ++i) {
- if (!platformMatches(bindings[i].platform))
+ if (!platformMatches(bindings[i].platform)) {
continue;
+ }
const shortcuts = bindings[i]['shortcut'].split(/\s+/);
shortcuts.forEach(this.registerShortcut.bind(this, descriptor['actionId']));
}
@@ -212,24 +230,40 @@ UI.ShortcutRegistry = class {
* @return {boolean}
*/
function platformMatches(platformsString) {
- if (!platformsString)
+ if (!platformsString) {
return true;
+ }
const platforms = platformsString.split(',');
let isMatch = false;
const currentPlatform = Host.platform();
- for (let i = 0; !isMatch && i < platforms.length; ++i)
+ for (let i = 0; !isMatch && i < platforms.length; ++i) {
isMatch = platforms[i] === currentPlatform;
+ }
return isMatch;
}
}
-};
+}
/**
* @unrestricted
*/
-UI.ShortcutRegistry.ForwardedShortcut = class {};
+export class ForwardedShortcut {}
-UI.ShortcutRegistry.ForwardedShortcut.instance = new UI.ShortcutRegistry.ForwardedShortcut();
+ForwardedShortcut.instance = new ForwardedShortcut();
-/** @type {!UI.ShortcutRegistry} */
+/** @type {!ShortcutRegistry} */
UI.shortcutRegistry;
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ShortcutRegistry = ShortcutRegistry;
+
+/**
+ * @unrestricted
+ */
+UI.ShortcutRegistry.ForwardedShortcut = ForwardedShortcut;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
index 82b58fa715b..02bef2240f8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
@@ -31,9 +31,9 @@
/**
* @unrestricted
*/
-UI.ShortcutsScreen = class {
+export default class ShortcutsScreen {
constructor() {
- /** @type {!Object.<string, !UI.ShortcutsSection>} */
+ /** @type {!Object.<string, !ShortcutsSection>} */
this._sections = {};
}
@@ -41,16 +41,13 @@ UI.ShortcutsScreen = class {
// Elements panel
const elementsSection = UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
- const navigate = UI.ShortcutsScreen.ElementsPanelShortcuts.NavigateUp.concat(
- UI.ShortcutsScreen.ElementsPanelShortcuts.NavigateDown);
+ const navigate = ElementsPanelShortcuts.NavigateUp.concat(ElementsPanelShortcuts.NavigateDown);
elementsSection.addRelatedKeys(navigate, Common.UIString('Navigate elements'));
- const expandCollapse =
- UI.ShortcutsScreen.ElementsPanelShortcuts.Expand.concat(UI.ShortcutsScreen.ElementsPanelShortcuts.Collapse);
+ const expandCollapse = ElementsPanelShortcuts.Expand.concat(ElementsPanelShortcuts.Collapse);
elementsSection.addRelatedKeys(expandCollapse, Common.UIString('Expand/collapse'));
- elementsSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.EditAttribute, Common.UIString('Edit attribute'));
+ elementsSection.addAlternateKeys(ElementsPanelShortcuts.EditAttribute, Common.UIString('Edit attribute'));
elementsSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('elements.hide-element'), Common.UIString('Hide element'));
elementsSection.addAlternateKeys(
@@ -60,48 +57,36 @@ UI.ShortcutsScreen = class {
// Styles pane
const stylesPaneSection = UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
- const nextPreviousProperty = UI.ShortcutsScreen.ElementsPanelShortcuts.NextProperty.concat(
- UI.ShortcutsScreen.ElementsPanelShortcuts.PreviousProperty);
+ const nextPreviousProperty = ElementsPanelShortcuts.NextProperty.concat(ElementsPanelShortcuts.PreviousProperty);
stylesPaneSection.addRelatedKeys(nextPreviousProperty, Common.UIString('Next/previous property'));
- stylesPaneSection.addRelatedKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.IncrementValue, Common.UIString('Increment value'));
- stylesPaneSection.addRelatedKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.DecrementValue, Common.UIString('Decrement value'));
+ stylesPaneSection.addRelatedKeys(ElementsPanelShortcuts.IncrementValue, Common.UIString('Increment value'));
+ stylesPaneSection.addRelatedKeys(ElementsPanelShortcuts.DecrementValue, Common.UIString('Decrement value'));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.IncrementBy10, Common.UIString('Increment by %f', 10));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.DecrementBy10, Common.UIString('Decrement by %f', 10));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.IncrementBy10, Common.UIString('Increment by %f', 10));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.DecrementBy10, Common.UIString('Decrement by %f', 10));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.IncrementBy100, Common.UIString('Increment by %f', 100));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.DecrementBy100, Common.UIString('Decrement by %f', 100));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.IncrementBy100, Common.UIString('Increment by %f', 100));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.DecrementBy100, Common.UIString('Decrement by %f', 100));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.IncrementBy01, Common.UIString('Increment by %f', 0.1));
- stylesPaneSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.DecrementBy01, Common.UIString('Decrement by %f', 0.1));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.IncrementBy01, Common.UIString('Increment by %f', 0.1));
+ stylesPaneSection.addAlternateKeys(ElementsPanelShortcuts.DecrementBy01, Common.UIString('Decrement by %f', 0.1));
// Console
const consoleSection = UI.shortcutsScreen.section(Common.UIString('Console'));
consoleSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('console.clear'), Common.UIString('Clear console'));
- consoleSection.addRelatedKeys(
- UI.ShortcutsScreen.ConsolePanelShortcuts.AcceptSuggestion, Common.UIString('Accept suggestion'));
- consoleSection.addAlternateKeys(
- UI.ShortcutsScreen.ConsolePanelShortcuts.ClearConsolePrompt, Common.UIString('Clear console prompt'));
- consoleSection.addRelatedKeys(
- UI.ShortcutsScreen.ConsolePanelShortcuts.NextPreviousLine, Common.UIString('Next/previous line'));
+ consoleSection.addRelatedKeys(ConsolePanelShortcuts.AcceptSuggestion, Common.UIString('Accept suggestion'));
+ consoleSection.addAlternateKeys(ConsolePanelShortcuts.ClearConsolePrompt, Common.UIString('Clear console prompt'));
+ consoleSection.addRelatedKeys(ConsolePanelShortcuts.NextPreviousLine, Common.UIString('Next/previous line'));
if (Host.isMac()) {
consoleSection.addRelatedKeys(
- UI.ShortcutsScreen.ConsolePanelShortcuts.NextPreviousCommand, Common.UIString('Next/previous command'));
+ ConsolePanelShortcuts.NextPreviousCommand, Common.UIString('Next/previous command'));
}
- consoleSection.addKey(UI.ShortcutsScreen.ConsolePanelShortcuts.ExecuteCommand, Common.UIString('Execute command'));
+ consoleSection.addKey(ConsolePanelShortcuts.ExecuteCommand, Common.UIString('Execute command'));
// Debugger
const debuggerSection = UI.shortcutsScreen.section(Common.UIString('Debugger'));
@@ -121,10 +106,9 @@ UI.ShortcutsScreen = class {
debuggerSection.addRelatedKeys(nextAndPrevFrameKeys, Common.UIString('Next/previous call frame'));
debuggerSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.EvaluateSelectionInConsole,
- Common.UIString('Evaluate selection in console'));
+ SourcesPanelShortcuts.EvaluateSelectionInConsole, Common.UIString('Evaluate selection in console'));
debuggerSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.AddSelectionToWatch, Common.UIString('Add selection to watch'));
+ SourcesPanelShortcuts.AddSelectionToWatch, Common.UIString('Add selection to watch'));
debuggerSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('debugger.toggle-breakpoint'),
Common.UIString('Toggle breakpoint'));
@@ -143,8 +127,7 @@ UI.ShortcutsScreen = class {
editingSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('sources.go-to-member'), Common.UIString('Go to member'));
- editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.ToggleAutocompletion, Common.UIString('Autocompletion'));
+ editingSection.addAlternateKeys(SourcesPanelShortcuts.ToggleAutocompletion, Common.UIString('Autocompletion'));
editingSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('sources.go-to-line'), Common.UIString('Go to line'));
editingSection.addAlternateKeys(
@@ -153,21 +136,20 @@ UI.ShortcutsScreen = class {
editingSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('sources.jump-to-next-location'),
Common.UIString('Jump to next editing location'));
+ editingSection.addAlternateKeys(SourcesPanelShortcuts.ToggleComment, Common.UIString('Toggle comment'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.ToggleComment, Common.UIString('Toggle comment'));
- editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.IncreaseCSSUnitByOne, Common.UIString('Increment CSS unit by 1'));
+ SourcesPanelShortcuts.IncreaseCSSUnitByOne, Common.UIString('Increment CSS unit by 1'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.DecreaseCSSUnitByOne, Common.UIString('Decrement CSS unit by 1'));
+ SourcesPanelShortcuts.DecreaseCSSUnitByOne, Common.UIString('Decrement CSS unit by 1'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.IncreaseCSSUnitByTen, Common.UIString('Increment CSS unit by 10'));
+ SourcesPanelShortcuts.IncreaseCSSUnitByTen, Common.UIString('Increment CSS unit by 10'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.DecreaseCSSUnitByTen, Common.UIString('Decrement CSS unit by 10'));
+ SourcesPanelShortcuts.DecreaseCSSUnitByTen, Common.UIString('Decrement CSS unit by 10'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.SelectNextOccurrence, Common.UIString('Select next occurrence'));
- editingSection.addAlternateKeys(UI.ShortcutsScreen.SourcesPanelShortcuts.SoftUndo, Common.UIString('Soft undo'));
+ SourcesPanelShortcuts.SelectNextOccurrence, Common.UIString('Select next occurrence'));
+ editingSection.addAlternateKeys(SourcesPanelShortcuts.SoftUndo, Common.UIString('Soft undo'));
editingSection.addAlternateKeys(
- UI.ShortcutsScreen.SourcesPanelShortcuts.GotoMatchingBracket, Common.UIString('Go to matching bracket'));
+ SourcesPanelShortcuts.GotoMatchingBracket, Common.UIString('Go to matching bracket'));
editingSection.addAlternateKeys(
UI.shortcutRegistry.shortcutDescriptorsForAction('sources.close-editor-tab'),
Common.UIString('Close editor tab'));
@@ -210,32 +192,28 @@ UI.ShortcutsScreen = class {
// Layers panel
const layersSection = UI.shortcutsScreen.section(Common.UIString('Layers Panel'));
- layersSection.addAlternateKeys(UI.ShortcutsScreen.LayersPanelShortcuts.ResetView, Common.UIString('Reset view'));
+ layersSection.addAlternateKeys(LayersPanelShortcuts.ResetView, Common.UIString('Reset view'));
+ layersSection.addAlternateKeys(LayersPanelShortcuts.PanMode, Common.UIString('Switch to pan mode'));
+ layersSection.addAlternateKeys(LayersPanelShortcuts.RotateMode, Common.UIString('Switch to rotate mode'));
layersSection.addAlternateKeys(
- UI.ShortcutsScreen.LayersPanelShortcuts.PanMode, Common.UIString('Switch to pan mode'));
- layersSection.addAlternateKeys(
- UI.ShortcutsScreen.LayersPanelShortcuts.RotateMode, Common.UIString('Switch to rotate mode'));
- layersSection.addAlternateKeys(
- UI.ShortcutsScreen.LayersPanelShortcuts.TogglePanRotate,
- Common.UIString('Temporarily toggle pan/rotate mode while held'));
- layersSection.addAlternateKeys(UI.ShortcutsScreen.LayersPanelShortcuts.ZoomIn, Common.UIString('Zoom in'));
- layersSection.addAlternateKeys(UI.ShortcutsScreen.LayersPanelShortcuts.ZoomOut, Common.UIString('Zoom out'));
+ LayersPanelShortcuts.TogglePanRotate, Common.UIString('Temporarily toggle pan/rotate mode while held'));
+ layersSection.addAlternateKeys(LayersPanelShortcuts.ZoomIn, Common.UIString('Zoom in'));
+ layersSection.addAlternateKeys(LayersPanelShortcuts.ZoomOut, Common.UIString('Zoom out'));
layersSection.addRelatedKeys(
- UI.ShortcutsScreen.LayersPanelShortcuts.Up.concat(UI.ShortcutsScreen.LayersPanelShortcuts.Down),
- Common.UIString('Pan or rotate up/down'));
+ LayersPanelShortcuts.Up.concat(LayersPanelShortcuts.Down), Common.UIString('Pan or rotate up/down'));
layersSection.addRelatedKeys(
- UI.ShortcutsScreen.LayersPanelShortcuts.Left.concat(UI.ShortcutsScreen.LayersPanelShortcuts.Right),
- Common.UIString('Pan or rotate left/right'));
+ LayersPanelShortcuts.Left.concat(LayersPanelShortcuts.Right), Common.UIString('Pan or rotate left/right'));
}
/**
* @param {string} name
- * @return {!UI.ShortcutsSection}
+ * @return {!ShortcutsSection}
*/
section(name) {
let section = this._sections[name];
- if (!section)
- this._sections[name] = section = new UI.ShortcutsSection(name);
+ if (!section) {
+ this._sections[name] = section = new ShortcutsSection(name);
+ }
return section;
}
@@ -244,8 +222,9 @@ UI.ShortcutsScreen = class {
*/
createShortcutsTabView() {
const orderedSections = [];
- for (const section in this._sections)
+ for (const section in this._sections) {
orderedSections.push(this._sections[section]);
+ }
function compareSections(a, b) {
return a.order - b.order;
}
@@ -258,8 +237,9 @@ UI.ShortcutsScreen = class {
const scrollPane = widget.element.createChild('div', 'settings-container-wrapper');
const container = scrollPane.createChild('div');
container.className = 'settings-content settings-container';
- for (let i = 0; i < orderedSections.length; ++i)
+ for (let i = 0; i < orderedSections.length; ++i) {
orderedSections[i].renderSection(container);
+ }
const note = scrollPane.createChild('p', 'settings-footnote');
note.appendChild(UI.createDocumentationLink(
@@ -267,25 +247,25 @@ UI.ShortcutsScreen = class {
return widget;
}
-};
+}
/**
* We cannot initialize it here as localized strings are not loaded yet.
- * @type {!UI.ShortcutsScreen}
+ * @type {!ShortcutsScreen}
*/
UI.shortcutsScreen;
/**
* @unrestricted
*/
-UI.ShortcutsSection = class {
+export class ShortcutsSection {
/**
* @param {string} name
*/
constructor(name) {
this.name = name;
this._lines = /** @type {!Array.<!{key: !Node, text: string}>} */ ([]);
- this.order = ++UI.ShortcutsSection._sequenceNumber;
+ this.order = ++ShortcutsSection._sequenceNumber;
}
/**
@@ -380,18 +360,19 @@ UI.ShortcutsSection = class {
_joinNodes(nodes, delimiter) {
const result = createDocumentFragment();
for (let i = 0; i < nodes.length; ++i) {
- if (i > 0)
+ if (i > 0) {
result.appendChild(delimiter.cloneNode(true));
+ }
result.appendChild(nodes[i]);
}
return result;
}
-};
+}
-UI.ShortcutsSection._sequenceNumber = 0;
+ShortcutsSection._sequenceNumber = 0;
-UI.ShortcutsScreen.ElementsPanelShortcuts = {
+export const ElementsPanelShortcuts = {
NavigateUp: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Up)],
NavigateDown: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Down)],
@@ -432,7 +413,7 @@ UI.ShortcutsScreen.ElementsPanelShortcuts = {
DecrementBy01: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Down, UI.KeyboardShortcut.Modifiers.Alt)]
};
-UI.ShortcutsScreen.ConsolePanelShortcuts = {
+export const ConsolePanelShortcuts = {
AcceptSuggestion: [
UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Tab),
UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Right)
@@ -453,7 +434,7 @@ UI.ShortcutsScreen.ConsolePanelShortcuts = {
],
};
-UI.ShortcutsScreen.SourcesPanelShortcuts = {
+export const SourcesPanelShortcuts = {
SelectNextOccurrence: [UI.KeyboardShortcut.makeDescriptor('d', UI.KeyboardShortcut.Modifiers.CtrlOrMeta)],
SoftUndo: [UI.KeyboardShortcut.makeDescriptor('u', UI.KeyboardShortcut.Modifiers.CtrlOrMeta)],
@@ -484,7 +465,7 @@ UI.ShortcutsScreen.SourcesPanelShortcuts = {
[UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Slash, UI.KeyboardShortcut.Modifiers.CtrlOrMeta)],
};
-UI.ShortcutsScreen.LayersPanelShortcuts = {
+export const LayersPanelShortcuts = {
ResetView: [UI.KeyboardShortcut.makeDescriptor('0')],
PanMode: [UI.KeyboardShortcut.makeDescriptor('x')],
@@ -511,3 +492,20 @@ UI.ShortcutsScreen.LayersPanelShortcuts = {
Right: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Right), UI.KeyboardShortcut.makeDescriptor('d')]
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ShortcutsScreen = ShortcutsScreen;
+
+/** @constructor */
+UI.ShortcutsSection = ShortcutsSection;
+
+UI.ShortcutsScreen.ElementsPanelShortcuts = ElementsPanelShortcuts;
+UI.ShortcutsScreen.ConsolePanelShortcuts = ConsolePanelShortcuts;
+UI.ShortcutsScreen.SourcesPanelShortcuts = SourcesPanelShortcuts;
+UI.ShortcutsScreen.LayersPanelShortcuts = LayersPanelShortcuts;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js
index 0b74e6e7a4a..97ac10947ed 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftContextMenu.js
@@ -26,11 +26,11 @@
/**
* @unrestricted
*/
-UI.SoftContextMenu = class {
+export default class SoftContextMenu {
/**
* @param {!Array.<!InspectorFrontendHostAPI.ContextMenuDescriptor>} items
* @param {function(string)} itemSelectedCallback
- * @param {!UI.SoftContextMenu=} parentMenu
+ * @param {!SoftContextMenu=} parentMenu
*/
constructor(items, itemSelectedCallback, parentMenu) {
this._items = items;
@@ -45,8 +45,9 @@ UI.SoftContextMenu = class {
* @param {!AnchorBox} anchorBox
*/
show(document, anchorBox) {
- if (!this._items.length)
+ if (!this._items.length) {
return;
+ }
this._document = document;
@@ -67,14 +68,24 @@ UI.SoftContextMenu = class {
this._contextMenuElement.addEventListener('mouseup', e => e.consume(), false);
this._contextMenuElement.addEventListener('keydown', this._menuKeyDown.bind(this), false);
- for (let i = 0; i < this._items.length; ++i)
+ for (let i = 0; i < this._items.length; ++i) {
this._contextMenuElement.appendChild(this._createMenuItem(this._items[i]));
+ }
this._glassPane.show(document);
this._focusRestorer = new UI.ElementFocusRestorer(this._contextMenuElement);
if (!this._parentMenu) {
this._hideOnUserGesture = event => {
+ // If a user clicks on any submenu, prevent the menu system from closing.
+ let subMenu = this._subMenu;
+ while (subMenu) {
+ if (subMenu._contextMenuElement === event.path[0]) {
+ return;
+ }
+ subMenu = subMenu._subMenu;
+ }
+
this.discard();
event.consume(true);
};
@@ -84,10 +95,12 @@ UI.SoftContextMenu = class {
}
discard() {
- if (this._subMenu)
+ if (this._subMenu) {
this._subMenu.discard();
- if (this._focusRestorer)
+ }
+ if (this._focusRestorer) {
this._focusRestorer.restore();
+ }
if (this._glassPane) {
this._glassPane.hide();
delete this._glassPane;
@@ -97,24 +110,28 @@ UI.SoftContextMenu = class {
delete this._hideOnUserGesture;
}
}
- if (this._parentMenu)
+ if (this._parentMenu) {
delete this._parentMenu._subMenu;
+ }
}
_createMenuItem(item) {
- if (item.type === 'separator')
+ if (item.type === 'separator') {
return this._createSeparator();
+ }
- if (item.type === 'subMenu')
+ if (item.type === 'subMenu') {
return this._createSubMenu(item);
+ }
const menuItemElement = createElementWithClass('div', 'soft-context-menu-item');
menuItemElement.tabIndex = -1;
UI.ARIAUtils.markAsMenuItem(menuItemElement);
const checkMarkElement = UI.Icon.create('smallicon-checkmark', 'checkmark');
menuItemElement.appendChild(checkMarkElement);
- if (!item.checked)
+ if (!item.checked) {
checkMarkElement.style.opacity = '0';
+ }
if (item.element) {
const wrapper = menuItemElement.createChild('div', 'soft-context-menu-custom-item');
@@ -123,8 +140,9 @@ UI.SoftContextMenu = class {
return menuItemElement;
}
- if (!item.enabled)
+ if (!item.enabled) {
menuItemElement.classList.add('soft-context-menu-disabled');
+ }
menuItemElement.createTextChild(item.label);
menuItemElement.createChild('span', 'soft-context-menu-shortcut').textContent = item.shortcut;
@@ -141,10 +159,11 @@ UI.SoftContextMenu = class {
if (item.type === 'checkbox') {
const checkedState = item.checked ? ls`checked` : ls`unchecked`;
- if (item.shortcut)
+ if (item.shortcut) {
accessibleName = ls`${item.label}, ${item.shortcut}, ${checkedState}`;
- else
+ } else {
accessibleName = ls`${item.label}, ${checkedState}`;
+ }
} else if (item.shortcut) {
accessibleName = ls`${item.label}, ${item.shortcut}`;
}
@@ -157,7 +176,7 @@ UI.SoftContextMenu = class {
const menuItemElement = createElementWithClass('div', 'soft-context-menu-item');
menuItemElement._subItems = item.subItems;
menuItemElement.tabIndex = -1;
- UI.ARIAUtils.markAsMenuItem(menuItemElement);
+ UI.ARIAUtils.markAsMenuItemSubMenu(menuItemElement);
// Occupy the same space on the left in all items.
const checkMarkElement = UI.Icon.create('smallicon-checkmark', 'soft-context-menu-item-checkmark');
@@ -203,12 +222,13 @@ UI.SoftContextMenu = class {
}
/**
- * @return {!UI.SoftContextMenu}
+ * @return {!SoftContextMenu}
*/
_root() {
let root = this;
- while (root._parentMenu)
+ while (root._parentMenu) {
root = root._parentMenu;
+ }
return root;
}
@@ -232,10 +252,11 @@ UI.SoftContextMenu = class {
clearTimeout(menuItemElement._subMenuTimer);
delete menuItemElement._subMenuTimer;
}
- if (this._subMenu)
+ if (this._subMenu) {
return;
+ }
- this._subMenu = new UI.SoftContextMenu(menuItemElement._subItems, this._itemSelectedCallback, this);
+ this._subMenu = new SoftContextMenu(menuItemElement._subItems, this._itemSelectedCallback, this);
const anchorBox = menuItemElement.boxInWindow();
// Adjust for padding.
anchorBox.y -= 5;
@@ -256,8 +277,9 @@ UI.SoftContextMenu = class {
}
const relatedTarget = event.relatedTarget;
- if (relatedTarget === this._contextMenuElement)
+ if (relatedTarget === this._contextMenuElement) {
this._highlightMenuItem(null, true);
+ }
}
/**
@@ -265,11 +287,13 @@ UI.SoftContextMenu = class {
* @param {boolean} scheduleSubMenu
*/
_highlightMenuItem(menuItemElement, scheduleSubMenu) {
- if (this._highlightedMenuItemElement === menuItemElement)
+ if (this._highlightedMenuItemElement === menuItemElement) {
return;
+ }
- if (this._subMenu)
+ if (this._subMenu) {
this._subMenu.discard();
+ }
if (this._highlightedMenuItemElement) {
this._highlightedMenuItemElement.classList.remove('force-white-icons');
this._highlightedMenuItemElement.classList.remove('soft-context-menu-item-mouse-over');
@@ -280,13 +304,15 @@ UI.SoftContextMenu = class {
}
this._highlightedMenuItemElement = menuItemElement;
if (this._highlightedMenuItemElement) {
- if (UI.themeSupport.hasTheme() || Host.isMac())
+ if (UI.themeSupport.hasTheme() || Host.isMac()) {
this._highlightedMenuItemElement.classList.add('force-white-icons');
+ }
this._highlightedMenuItemElement.classList.add('soft-context-menu-item-mouse-over');
- if (this._highlightedMenuItemElement._customElement)
+ if (this._highlightedMenuItemElement._customElement) {
this._highlightedMenuItemElement._customElement.focus();
- else
+ } else {
this._highlightedMenuItemElement.focus();
+ }
if (scheduleSubMenu && this._highlightedMenuItemElement._subItems &&
!this._highlightedMenuItemElement._subMenuTimer) {
this._highlightedMenuItemElement._subMenuTimer =
@@ -299,20 +325,24 @@ UI.SoftContextMenu = class {
let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling :
this._contextMenuElement.lastChild;
while (menuItemElement &&
- (menuItemElement._isSeparator || menuItemElement.classList.contains('soft-context-menu-disabled')))
+ (menuItemElement._isSeparator || menuItemElement.classList.contains('soft-context-menu-disabled'))) {
menuItemElement = menuItemElement.previousSibling;
- if (menuItemElement)
+ }
+ if (menuItemElement) {
this._highlightMenuItem(menuItemElement, false);
+ }
}
_highlightNext() {
let menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling :
this._contextMenuElement.firstChild;
while (menuItemElement &&
- (menuItemElement._isSeparator || menuItemElement.classList.contains('soft-context-menu-disabled')))
+ (menuItemElement._isSeparator || menuItemElement.classList.contains('soft-context-menu-disabled'))) {
menuItemElement = menuItemElement.nextSibling;
- if (menuItemElement)
+ }
+ if (menuItemElement) {
this._highlightMenuItem(menuItemElement, false);
+ }
}
_menuKeyDown(event) {
@@ -330,8 +360,9 @@ UI.SoftContextMenu = class {
}
break;
case 'ArrowRight':
- if (!this._highlightedMenuItemElement)
+ if (!this._highlightedMenuItemElement) {
break;
+ }
if (this._highlightedMenuItemElement._subItems) {
this._showSubMenu(this._highlightedMenuItemElement);
this._subMenu._highlightNext();
@@ -341,17 +372,29 @@ UI.SoftContextMenu = class {
this.discard();
break;
case 'Enter':
- if (!isEnterKey(event))
+ if (!isEnterKey(event)) {
return;
+ }
// Fall through
case ' ': // Space
- if (!this._highlightedMenuItemElement || this._highlightedMenuItemElement._customElement)
+ if (!this._highlightedMenuItemElement || this._highlightedMenuItemElement._customElement) {
return;
+ }
this._triggerAction(this._highlightedMenuItemElement, event);
- if (this._highlightedMenuItemElement._subItems)
+ if (this._highlightedMenuItemElement._subItems) {
this._subMenu._highlightNext();
+ }
break;
}
event.consume(true);
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SoftContextMenu = SoftContextMenu;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js
index b41831f7746..e97c31392b6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SoftDropDown.js
@@ -5,10 +5,10 @@
* @template T
* @implements {UI.ListDelegate<T>}
*/
-UI.SoftDropDown = class {
+export default class SoftDropDown {
/**
* @param {!UI.ListModel<T>} model
- * @param {!UI.SoftDropDown.Delegate<T>} delegate
+ * @param {!Delegate<T>} delegate
*/
constructor(model, delegate) {
this._delegate = delegate;
@@ -40,21 +40,24 @@ UI.SoftDropDown = class {
this._listWasShowing200msAgo = false;
this.element.addEventListener('mousedown', event => {
- if (this._listWasShowing200msAgo)
+ if (this._listWasShowing200msAgo) {
this._hide(event);
- else if (!this.element.disabled)
+ } else if (!this.element.disabled) {
this._show(event);
+ }
}, false);
this.element.addEventListener('keydown', this._onKeyDownButton.bind(this), false);
this._list.element.addEventListener('keydown', this._onKeyDownList.bind(this), false);
this._list.element.addEventListener('focusout', this._hide.bind(this), false);
this._list.element.addEventListener('mousedown', event => event.consume(true), false);
this._list.element.addEventListener('mouseup', event => {
- if (event.target === this._list.element)
+ if (event.target === this._list.element) {
return;
+ }
- if (!this._listWasShowing200msAgo)
+ if (!this._listWasShowing200msAgo) {
return;
+ }
this._selectHighlightedItem();
this._hide(event);
}, false);
@@ -65,15 +68,17 @@ UI.SoftDropDown = class {
* @param {!Event} event
*/
_show(event) {
- if (this._glassPane.isShowing())
+ if (this._glassPane.isShowing()) {
return;
+ }
this._glassPane.setContentAnchorBox(this.element.boxInWindow());
this._glassPane.show(/** @type {!Document} **/ (this.element.ownerDocument));
this._list.element.focus();
UI.ARIAUtils.setExpanded(this.element, true);
this._updateGlasspaneSize();
- if (this._selectedItem)
+ if (this._selectedItem) {
this._list.selectItem(this._selectedItem);
+ }
event.consume(true);
setTimeout(() => this._listWasShowing200msAgo = true, 200);
}
@@ -121,8 +126,9 @@ UI.SoftDropDown = class {
break;
}
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -182,8 +188,9 @@ UI.SoftDropDown = class {
break;
}
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -206,8 +213,9 @@ UI.SoftDropDown = class {
*/
setPlaceholderText(text) {
this._placeholderText = text;
- if (!this._selectedItem)
+ if (!this._selectedItem) {
this._titleElement.textContent = this._placeholderText;
+ }
}
/**
@@ -227,10 +235,11 @@ UI.SoftDropDown = class {
*/
selectItem(item) {
this._selectedItem = item;
- if (this._selectedItem)
+ if (this._selectedItem) {
this._titleElement.textContent = this._delegate.titleFor(this._selectedItem);
- else
+ } else {
this._titleElement.textContent = this._placeholderText;
+ }
this._delegate.itemSelected(this._selectedItem);
}
@@ -242,8 +251,9 @@ UI.SoftDropDown = class {
createElementForItem(item) {
const element = createElementWithClass('div', 'item');
element.addEventListener('mousemove', e => {
- if ((e.movementX || e.movementY) && this._delegate.isItemSelectable(item))
+ if ((e.movementX || e.movementY) && this._delegate.isItemSelectable(item)) {
this._list.selectItem(item, false, /* Don't scroll */ true);
+ }
});
element.classList.toggle('disabled', !this._delegate.isItemSelectable(item));
element.classList.toggle('highlighted', this._list.selectedItem() === item);
@@ -280,10 +290,12 @@ UI.SoftDropDown = class {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('highlighted');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('highlighted');
+ }
UI.ARIAUtils.setActiveDescendant(this._list.element, toElement);
this._delegate.highlightedItemChanged(
@@ -300,13 +312,13 @@ UI.SoftDropDown = class {
refreshItem(item) {
this._list.refreshItem(item);
}
-};
+}
/**
* @interface
* @template T
*/
-UI.SoftDropDown.Delegate = class {
+export class Delegate {
/**
* @param {T} item
* @return {string}
@@ -342,4 +354,19 @@ UI.SoftDropDown.Delegate = class {
*/
highlightedItemChanged(from, to, fromElement, toElement) {
}
-}; \ No newline at end of file
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SoftDropDown = SoftDropDown;
+
+/**
+ * @interface
+ * @template T
+ */
+UI.SoftDropDown.Delegate = Delegate; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
index c5de1150563..69412021e23 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SplitWidget.js
@@ -29,7 +29,7 @@
/**
* @unrestricted
*/
-UI.SplitWidget = class extends UI.Widget {
+export default class SplitWidget extends UI.Widget {
/**
* @param {boolean} isVertical
* @param {boolean} secondIsSidebar
@@ -92,7 +92,7 @@ UI.SplitWidget = class extends UI.Widget {
this.setSecondIsSidebar(secondIsSidebar);
this._innerSetVertical(isVertical);
- this._showMode = UI.SplitWidget.ShowMode.Both;
+ this._showMode = ShowMode.Both;
this._savedShowMode = this._showMode;
// Should be called after isVertical has the right value.
@@ -110,13 +110,15 @@ UI.SplitWidget = class extends UI.Widget {
* @param {boolean} isVertical
*/
setVertical(isVertical) {
- if (this._isVertical === isVertical)
+ if (this._isVertical === isVertical) {
return;
+ }
this._innerSetVertical(isVertical);
- if (this.isShowing())
+ if (this.isShowing()) {
this._updateLayout();
+ }
}
/**
@@ -130,8 +132,9 @@ UI.SplitWidget = class extends UI.Widget {
this._resizerElementSize = null;
this._sidebarSizeDIP = -1;
this._restoreSidebarSizeFromSettings();
- if (this._shouldSaveShowMode)
+ if (this._shouldSaveShowMode) {
this._restoreAndApplyShowModeFromSettings();
+ }
this._updateShowHideSidebarButton();
// FIXME: reverse SplitWidget.isVertical meaning.
this._resizerWidget.setVertical(!isVertical);
@@ -158,16 +161,19 @@ UI.SplitWidget = class extends UI.Widget {
* @param {!UI.Widget} widget
*/
setMainWidget(widget) {
- if (this._mainWidget === widget)
+ if (this._mainWidget === widget) {
return;
+ }
this.suspendInvalidations();
- if (this._mainWidget)
+ if (this._mainWidget) {
this._mainWidget.detach();
+ }
this._mainWidget = widget;
if (widget) {
widget.element.slot = 'insertion-point-main';
- if (this._showMode === UI.SplitWidget.ShowMode.OnlyMain || this._showMode === UI.SplitWidget.ShowMode.Both)
+ if (this._showMode === ShowMode.OnlyMain || this._showMode === ShowMode.Both) {
widget.show(this.element);
+ }
}
this.resumeInvalidations();
}
@@ -176,16 +182,19 @@ UI.SplitWidget = class extends UI.Widget {
* @param {!UI.Widget} widget
*/
setSidebarWidget(widget) {
- if (this._sidebarWidget === widget)
+ if (this._sidebarWidget === widget) {
return;
+ }
this.suspendInvalidations();
- if (this._sidebarWidget)
+ if (this._sidebarWidget) {
this._sidebarWidget.detach();
+ }
this._sidebarWidget = widget;
if (widget) {
widget.element.slot = 'insertion-point-sidebar';
- if (this._showMode === UI.SplitWidget.ShowMode.OnlySidebar || this._showMode === UI.SplitWidget.ShowMode.Both)
+ if (this._showMode === ShowMode.OnlySidebar || this._showMode === ShowMode.Both) {
widget.show(this.element);
+ }
}
this.resumeInvalidations();
}
@@ -209,12 +218,15 @@ UI.SplitWidget = class extends UI.Widget {
* @param {!UI.Widget} widget
*/
childWasDetached(widget) {
- if (this._detaching)
+ if (this._detaching) {
return;
- if (this._mainWidget === widget)
+ }
+ if (this._mainWidget === widget) {
this._mainWidget = null;
- if (this._sidebarWidget === widget)
+ }
+ if (this._sidebarWidget === widget) {
this._sidebarWidget = null;
+ }
this.invalidateConstraints();
}
@@ -241,19 +253,22 @@ UI.SplitWidget = class extends UI.Widget {
* @param {boolean} secondIsSidebar
*/
setSecondIsSidebar(secondIsSidebar) {
- if (secondIsSidebar === this._secondIsSidebar)
+ if (secondIsSidebar === this._secondIsSidebar) {
return;
+ }
this._secondIsSidebar = secondIsSidebar;
if (!this._mainWidget || !this._mainWidget.shouldHideOnDetach()) {
- if (secondIsSidebar)
+ if (secondIsSidebar) {
this.contentElement.insertBefore(this._mainElement, this._sidebarElement);
- else
+ } else {
this.contentElement.insertBefore(this._mainElement, this._resizerElement);
+ }
} else if (!this._sidebarWidget || !this._sidebarWidget.shouldHideOnDetach()) {
- if (secondIsSidebar)
+ if (secondIsSidebar) {
this.contentElement.insertBefore(this._sidebarElement, this._resizerElement);
- else
+ } else {
this.contentElement.insertBefore(this._sidebarElement, this._mainElement);
+ }
} else {
console.error('Could not swap split widget side. Both children widgets contain iframes.');
this._secondIsSidebar = !secondIsSidebar;
@@ -264,8 +279,9 @@ UI.SplitWidget = class extends UI.Widget {
* @return {?string}
*/
sidebarSide() {
- if (this._showMode !== UI.SplitWidget.ShowMode.Both)
+ if (this._showMode !== ShowMode.Both) {
return null;
+ }
return this._isVertical ? (this._secondIsSidebar ? 'right' : 'left') : (this._secondIsSidebar ? 'bottom' : 'top');
}
@@ -281,7 +297,7 @@ UI.SplitWidget = class extends UI.Widget {
*/
hideMain(animate) {
this._showOnly(this._sidebarWidget, this._mainWidget, this._sidebarElement, this._mainElement, animate);
- this._updateShowMode(UI.SplitWidget.ShowMode.OnlySidebar);
+ this._updateShowMode(ShowMode.OnlySidebar);
}
/**
@@ -289,7 +305,7 @@ UI.SplitWidget = class extends UI.Widget {
*/
hideSidebar(animate) {
this._showOnly(this._mainWidget, this._sidebarWidget, this._mainElement, this._sidebarElement, animate);
- this._updateShowMode(UI.SplitWidget.ShowMode.OnlyMain);
+ this._updateShowMode(ShowMode.OnlyMain);
}
/**
@@ -318,15 +334,16 @@ UI.SplitWidget = class extends UI.Widget {
this._cancelAnimation();
/**
- * @this {UI.SplitWidget}
+ * @this {SplitWidget}
*/
function callback() {
if (sideToShow) {
// Make sure main is first in the children list.
- if (sideToShow === this._mainWidget)
+ if (sideToShow === this._mainWidget) {
this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
- else
+ } else {
this._sidebarWidget.show(this.element);
+ }
}
if (sideToHide) {
this._detaching = true;
@@ -344,10 +361,11 @@ UI.SplitWidget = class extends UI.Widget {
this._showFinishedForTest();
}
- if (animate)
+ if (animate) {
this._animate(true, callback.bind(this));
- else
+ } else {
callback.call(this);
+ }
this._sidebarSizeDIP = -1;
this.setResizable(false);
@@ -380,8 +398,9 @@ UI.SplitWidget = class extends UI.Widget {
* @param {boolean=} animate
*/
showBoth(animate) {
- if (this._showMode === UI.SplitWidget.ShowMode.Both)
+ if (this._showMode === ShowMode.Both) {
animate = false;
+ }
this._cancelAnimation();
this._mainElement.classList.remove('maximized', 'hidden');
@@ -391,16 +410,18 @@ UI.SplitWidget = class extends UI.Widget {
// Make sure main is the first in the children list.
this.suspendInvalidations();
- if (this._sidebarWidget)
+ if (this._sidebarWidget) {
this._sidebarWidget.show(this.element);
- if (this._mainWidget)
+ }
+ if (this._mainWidget) {
this._mainWidget.show(this.element, this._sidebarWidget ? this._sidebarWidget.element : null);
+ }
this.resumeInvalidations();
// Order widgets in DOM properly.
this.setSecondIsSidebar(this._secondIsSidebar);
this._sidebarSizeDIP = -1;
- this._updateShowMode(UI.SplitWidget.ShowMode.Both);
+ this._updateShowMode(ShowMode.Both);
this._updateLayout(animate);
}
@@ -456,7 +477,7 @@ UI.SplitWidget = class extends UI.Widget {
this._showMode = showMode;
this._saveShowModeToSettings();
this._updateShowHideSidebarButton();
- this.dispatchEventToListeners(UI.SplitWidget.Events.ShowModeChanged, showMode);
+ this.dispatchEventToListeners(SplitWidget.Events.ShowModeChanged, showMode);
this.invalidateConstraints();
}
@@ -466,12 +487,14 @@ UI.SplitWidget = class extends UI.Widget {
* @param {boolean=} userAction
*/
_innerSetSidebarSizeDIP(sizeDIP, animate, userAction) {
- if (this._showMode !== UI.SplitWidget.ShowMode.Both || !this.isShowing())
+ if (this._showMode !== ShowMode.Both || !this.isShowing()) {
return;
+ }
sizeDIP = this._applyConstraints(sizeDIP, userAction);
- if (this._sidebarSizeDIP === sizeDIP)
+ if (this._sidebarSizeDIP === sizeDIP) {
return;
+ }
if (!this._resizerElementSize) {
this._resizerElementSize =
@@ -529,7 +552,7 @@ UI.SplitWidget = class extends UI.Widget {
} else {
// No need to recalculate this._sidebarSizeDIP and this._totalSizeDIP again.
this.doResize();
- this.dispatchEventToListeners(UI.SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
+ this.dispatchEventToListeners(SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
}
}
@@ -542,10 +565,11 @@ UI.SplitWidget = class extends UI.Widget {
this._animationCallback = callback || null;
let animatedMarginPropertyName;
- if (this._isVertical)
+ if (this._isVertical) {
animatedMarginPropertyName = this._secondIsSidebar ? 'margin-right' : 'margin-left';
- else
+ } else {
animatedMarginPropertyName = this._secondIsSidebar ? 'margin-bottom' : 'margin-top';
+ }
const marginFrom = reverse ? '0' : '-' + UI.zoomManager.dipToCSS(this._sidebarSizeDIP) + 'px';
const marginTo = reverse ? '-' + UI.zoomManager.dipToCSS(this._sidebarSizeDIP) + 'px' : '0';
@@ -559,8 +583,9 @@ UI.SplitWidget = class extends UI.Widget {
}
// 2. Issue onresize to the sidebar element, its size won't change.
- if (!reverse)
+ if (!reverse) {
this._sidebarWidget.doResize();
+ }
// 3. Configure and run animation
this.contentElement.style.setProperty('transition', animatedMarginPropertyName + ' ' + animationTime + 'ms linear');
@@ -568,7 +593,7 @@ UI.SplitWidget = class extends UI.Widget {
const boundAnimationFrame = animationFrame.bind(this);
let startTime;
/**
- * @this {UI.SplitWidget}
+ * @this {SplitWidget}
*/
function animationFrame() {
this._animationFrameHandle = 0;
@@ -579,14 +604,16 @@ UI.SplitWidget = class extends UI.Widget {
startTime = window.performance.now();
} else if (window.performance.now() < startTime + animationTime) {
// Process regular animation frame.
- if (this._mainWidget)
+ if (this._mainWidget) {
this._mainWidget.doResize();
+ }
} else {
// Complete animation.
this._cancelAnimation();
- if (this._mainWidget)
+ if (this._mainWidget) {
this._mainWidget.doResize();
- this.dispatchEventToListeners(UI.SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
+ }
+ this.dispatchEventToListeners(SplitWidget.Events.SidebarSizeChanged, this.sidebarSize());
return;
}
this._animationFrameHandle = this.contentElement.window().requestAnimationFrame(boundAnimationFrame);
@@ -622,41 +649,50 @@ UI.SplitWidget = class extends UI.Widget {
let constraints = this._sidebarWidget ? this._sidebarWidget.constraints() : new UI.Constraints();
let minSidebarSize = this.isVertical() ? constraints.minimum.width : constraints.minimum.height;
- if (!minSidebarSize)
- minSidebarSize = UI.SplitWidget.MinPadding;
+ if (!minSidebarSize) {
+ minSidebarSize = MinPadding;
+ }
minSidebarSize *= zoomFactor;
- if (this._sidebarMinimized)
+ if (this._sidebarMinimized) {
sidebarSize = minSidebarSize;
+ }
let preferredSidebarSize = this.isVertical() ? constraints.preferred.width : constraints.preferred.height;
- if (!preferredSidebarSize)
- preferredSidebarSize = UI.SplitWidget.MinPadding;
+ if (!preferredSidebarSize) {
+ preferredSidebarSize = MinPadding;
+ }
preferredSidebarSize *= zoomFactor;
// Allow sidebar to be less than preferred by explicit user action.
- if (sidebarSize < preferredSidebarSize)
+ if (sidebarSize < preferredSidebarSize) {
preferredSidebarSize = Math.max(sidebarSize, minSidebarSize);
+ }
preferredSidebarSize += zoomFactor; // 1 css pixel for splitter border.
constraints = this._mainWidget ? this._mainWidget.constraints() : new UI.Constraints();
let minMainSize = this.isVertical() ? constraints.minimum.width : constraints.minimum.height;
- if (!minMainSize)
- minMainSize = UI.SplitWidget.MinPadding;
+ if (!minMainSize) {
+ minMainSize = MinPadding;
+ }
minMainSize *= zoomFactor;
let preferredMainSize = this.isVertical() ? constraints.preferred.width : constraints.preferred.height;
- if (!preferredMainSize)
- preferredMainSize = UI.SplitWidget.MinPadding;
+ if (!preferredMainSize) {
+ preferredMainSize = MinPadding;
+ }
preferredMainSize *= zoomFactor;
const savedMainSize = this.isVertical() ? this._savedVerticalMainSize : this._savedHorizontalMainSize;
- if (savedMainSize !== null)
+ if (savedMainSize !== null) {
preferredMainSize = Math.min(preferredMainSize, savedMainSize * zoomFactor);
- if (userAction)
+ }
+ if (userAction) {
preferredMainSize = minMainSize;
+ }
// Enough space for preferred.
const totalPreferred = preferredMainSize + preferredSidebarSize;
- if (totalPreferred <= totalSize)
+ if (totalPreferred <= totalSize) {
return Number.constrain(sidebarSize, preferredSidebarSize, totalSize - preferredMainSize);
+ }
// Enough space for minimum.
if (minMainSize + minSidebarSize <= totalSize) {
@@ -704,14 +740,16 @@ UI.SplitWidget = class extends UI.Widget {
* @return {!UI.Constraints}
*/
calculateConstraints() {
- if (this._showMode === UI.SplitWidget.ShowMode.OnlyMain)
+ if (this._showMode === ShowMode.OnlyMain) {
return this._mainWidget ? this._mainWidget.constraints() : new UI.Constraints();
- if (this._showMode === UI.SplitWidget.ShowMode.OnlySidebar)
+ }
+ if (this._showMode === ShowMode.OnlySidebar) {
return this._sidebarWidget ? this._sidebarWidget.constraints() : new UI.Constraints();
+ }
let mainConstraints = this._mainWidget ? this._mainWidget.constraints() : new UI.Constraints();
let sidebarConstraints = this._sidebarWidget ? this._sidebarWidget.constraints() : new UI.Constraints();
- const min = UI.SplitWidget.MinPadding;
+ const min = MinPadding;
if (this._isVertical) {
mainConstraints = mainConstraints.widthToMax(min).addWidth(1); // 1 for splitter
sidebarConstraints = sidebarConstraints.widthToMax(min);
@@ -742,10 +780,11 @@ UI.SplitWidget = class extends UI.Widget {
this._savedSidebarSizeDIP = constrainedSizeDIP;
this._saveSetting();
this._innerSetSidebarSizeDIP(constrainedSizeDIP, false, true);
- if (this.isVertical())
+ if (this.isVertical()) {
this._savedVerticalMainSize = this._totalSizeDIP() - this._sidebarSizeDIP;
- else
+ } else {
this._savedHorizontalMainSize = this._totalSizeDIP() - this._sidebarSizeDIP;
+ }
}
/**
@@ -790,14 +829,15 @@ UI.SplitWidget = class extends UI.Widget {
* @param {boolean} on
*/
toggleResizer(resizer, on) {
- if (on)
+ if (on) {
this.installResizer(resizer);
- else
+ } else {
this.uninstallResizer(resizer);
+ }
}
/**
- * @return {?UI.SplitWidget.SettingForOrientation}
+ * @return {?SplitWidget.SettingForOrientation}
*/
_settingForOrientation() {
const state = this._setting ? this._setting.get() : {};
@@ -812,8 +852,9 @@ UI.SplitWidget = class extends UI.Widget {
if (!size) {
size = this._isVertical ? this._defaultSidebarWidth : this._defaultSidebarHeight;
// If we have default value in percents, calculate it on first use.
- if (0 < size && size < 1)
+ if (0 < size && size < 1) {
size *= this._totalSizeDIP();
+ }
}
return size;
}
@@ -829,13 +870,13 @@ UI.SplitWidget = class extends UI.Widget {
this._showMode = this._savedShowMode;
switch (this._savedShowMode) {
- case UI.SplitWidget.ShowMode.Both:
+ case ShowMode.Both:
this.showBoth();
break;
- case UI.SplitWidget.ShowMode.OnlyMain:
+ case ShowMode.OnlyMain:
this.hideSidebar();
break;
- case UI.SplitWidget.ShowMode.OnlySidebar:
+ case ShowMode.OnlySidebar:
this.hideMain();
break;
}
@@ -847,19 +888,22 @@ UI.SplitWidget = class extends UI.Widget {
}
_saveSetting() {
- if (!this._setting)
+ if (!this._setting) {
return;
+ }
const state = this._setting.get();
const orientationState = (this._isVertical ? state.vertical : state.horizontal) || {};
orientationState.size = this._savedSidebarSizeDIP;
- if (this._shouldSaveShowMode)
+ if (this._shouldSaveShowMode) {
orientationState.showMode = this._savedShowMode;
+ }
- if (this._isVertical)
+ if (this._isVertical) {
state.vertical = orientationState;
- else
+ } else {
state.horizontal = orientationState;
+ }
this._setting.set(state);
}
@@ -888,22 +932,24 @@ UI.SplitWidget = class extends UI.Widget {
/**
* @param {!Common.Event} event
- * @this {UI.SplitWidget}
+ * @this {SplitWidget}
*/
function buttonClicked(event) {
- if (this._showMode !== UI.SplitWidget.ShowMode.Both)
+ if (this._showMode !== ShowMode.Both) {
this.showBoth(true);
- else
+ } else {
this.hideSidebar(true);
+ }
}
return this._showHideSidebarButton;
}
_updateShowHideSidebarButton() {
- if (!this._showHideSidebarButton)
+ if (!this._showHideSidebarButton) {
return;
- const sidebarHidden = this._showMode === UI.SplitWidget.ShowMode.OnlyMain;
+ }
+ const sidebarHidden = this._showMode === ShowMode.OnlyMain;
let glyph = '';
if (sidebarHidden) {
glyph = this.isVertical() ?
@@ -919,21 +965,36 @@ UI.SplitWidget = class extends UI.Widget {
sidebarHidden ? Common.UIString('Show %s', this._showHideSidebarButtonTitle) :
Common.UIString('Hide %s', this._showHideSidebarButtonTitle));
}
-};
-
-/** @typedef {{showMode: string, size: number}} */
-UI.SplitWidget.SettingForOrientation;
+}
-UI.SplitWidget.ShowMode = {
+export const ShowMode = {
Both: 'Both',
OnlyMain: 'OnlyMain',
OnlySidebar: 'OnlySidebar'
};
/** @enum {symbol} */
-UI.SplitWidget.Events = {
+export const Events = {
SidebarSizeChanged: Symbol('SidebarSizeChanged'),
ShowModeChanged: Symbol('ShowModeChanged')
};
-UI.SplitWidget.MinPadding = 20;
+export const MinPadding = 20;
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SplitWidget = SplitWidget;
+
+UI.SplitWidget.ShowMode = ShowMode;
+UI.SplitWidget.MinPadding = MinPadding;
+
+/** @enum {symbol} */
+UI.SplitWidget.Events = Events;
+
+/** @typedef {{showMode: string, size: number}} */
+UI.SplitWidget.SettingForOrientation; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
index f460d14f58b..07535894c01 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
@@ -30,27 +30,27 @@
/**
* @interface
*/
-UI.SuggestBoxDelegate = function() {};
-
-UI.SuggestBoxDelegate.prototype = {
+export class SuggestBoxDelegate {
/**
* @param {?UI.SuggestBox.Suggestion} suggestion
* @param {boolean=} isIntermediateSuggestion
*/
- applySuggestion(suggestion, isIntermediateSuggestion) {},
+ applySuggestion(suggestion, isIntermediateSuggestion) {
+ }
/**
* acceptSuggestion will be always called after call to applySuggestion with isIntermediateSuggestion being equal to false.
*/
- acceptSuggestion() {},
-};
+ acceptSuggestion() {
+ }
+}
/**
* @implements {UI.ListDelegate}
*/
-UI.SuggestBox = class {
+export default class SuggestBox {
/**
- * @param {!UI.SuggestBoxDelegate} suggestBoxDelegate
+ * @param {!SuggestBoxDelegate} suggestBoxDelegate
* @param {number=} maxItemsHeight
*/
constructor(suggestBoxDelegate, maxItemsHeight) {
@@ -116,8 +116,9 @@ UI.SuggestBox = class {
*/
_maxWidth(items) {
const kMaxWidth = 300;
- if (!items.length)
+ if (!items.length) {
return kMaxWidth;
+ }
let maxItem;
let maxLength = -Infinity;
for (let i = 0; i < items.length; i++) {
@@ -137,8 +138,9 @@ UI.SuggestBox = class {
* @suppressGlobalPropertiesCheck
*/
_show() {
- if (this.visible())
+ if (this.visible()) {
return;
+ }
// TODO(dgozman): take document as a parameter.
this._glassPane.show(document);
this._rowHeight =
@@ -146,8 +148,9 @@ UI.SuggestBox = class {
}
hide() {
- if (!this.visible())
+ if (!this.visible()) {
return;
+ }
this._glassPane.hide();
}
@@ -162,8 +165,9 @@ UI.SuggestBox = class {
return true;
}
const suggestion = this._list.selectedItem();
- if (suggestion && suggestion.text)
+ if (suggestion && suggestion.text) {
UI.ARIAUtils.alert(ls`${suggestion.title || suggestion.text}, suggestion`, this._element);
+ }
this._suggestBoxDelegate.applySuggestion(suggestion, isIntermediateSuggestion);
return this.visible() && !!suggestion;
@@ -175,8 +179,9 @@ UI.SuggestBox = class {
acceptSuggestion() {
const result = this._applySuggestion();
this.hide();
- if (!result)
+ if (!result) {
return false;
+ }
this._suggestBoxDelegate.acceptSuggestion();
@@ -195,18 +200,21 @@ UI.SuggestBox = class {
const icon = UI.Icon.create(item.iconType, 'suggestion-icon');
element.appendChild(icon);
}
- if (item.isSecondary)
+ if (item.isSecondary) {
element.classList.add('secondary');
+ }
element.tabIndex = -1;
const maxTextLength = 50 + query.length;
- const displayText = (item.title || item.text).trim().trimEnd(maxTextLength).replace(/\n/g, '\u21B5');
+ const displayText = (item.title || item.text).trim().trimEndWithMaxLength(maxTextLength).replace(/\n/g, '\u21B5');
const titleElement = element.createChild('span', 'suggestion-title');
const index = displayText.toLowerCase().indexOf(query.toLowerCase());
- if (index > 0)
+ if (index > 0) {
titleElement.createChild('span').textContent = displayText.substring(0, index);
- if (index > -1)
+ }
+ if (index > -1) {
titleElement.createChild('span', 'query').textContent = displayText.substring(index, index + query.length);
+ }
titleElement.createChild('span').textContent = displayText.substring(index > -1 ? index + query.length : 0);
titleElement.createChild('span', 'spacer');
if (item.subtitleRenderer) {
@@ -215,7 +223,7 @@ UI.SuggestBox = class {
element.appendChild(subtitleElement);
} else if (item.subtitle) {
const subtitleElement = element.createChild('span', 'suggestion-subtitle');
- subtitleElement.textContent = item.subtitle.trimEnd(maxTextLength - displayText.length);
+ subtitleElement.textContent = item.subtitle.trimEndWithMaxLength(maxTextLength - displayText.length);
}
return element;
}
@@ -246,8 +254,9 @@ UI.SuggestBox = class {
* @param {?Element} toElement
*/
selectedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('selected', 'force-white-icons');
+ }
if (toElement) {
toElement.classList.add('selected');
toElement.classList.add('force-white-icons');
@@ -260,8 +269,9 @@ UI.SuggestBox = class {
*/
_onClick(event) {
const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
- if (!item)
+ if (!item) {
return;
+ }
this._list.selectItem(item);
this.acceptSuggestion();
@@ -276,15 +286,18 @@ UI.SuggestBox = class {
* @return {boolean}
*/
_canShowBox(completions, highestPriorityItem, canShowForSingleItem, userEnteredText) {
- if (!completions || !completions.length)
+ if (!completions || !completions.length) {
return false;
+ }
- if (completions.length > 1)
+ if (completions.length > 1) {
return true;
+ }
if (!highestPriorityItem || highestPriorityItem.isSecondary ||
- !highestPriorityItem.text.startsWith(userEnteredText))
+ !highestPriorityItem.text.startsWith(userEnteredText)) {
return true;
+ }
// Do not show a single suggestion if it is the same as user-entered query, even if allowed to show single-item suggest boxes.
return canShowForSingleItem && highestPriorityItem.text !== userEnteredText;
@@ -310,10 +323,11 @@ UI.SuggestBox = class {
this._list.invalidateItemHeight();
this._items.replaceAll(completions);
- if (highestPriorityItem && !highestPriorityItem.isSecondary)
+ if (highestPriorityItem && !highestPriorityItem.isSecondary) {
this._list.selectItem(highestPriorityItem, true);
- else
+ } else {
this._list.selectItem(null);
+ }
} else {
if (completions.length === 1) {
this._onlyCompletion = completions[0];
@@ -354,24 +368,36 @@ UI.SuggestBox = class {
// to commit the input or handle it otherwise.
return hasSelectedItem;
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SuggestBox = SuggestBox;
+
+/** @interface */
+UI.SuggestBoxDelegate = SuggestBoxDelegate;
/**
* @typedef {{
- * text: string,
- * title: (string|undefined),
- * subtitle: (string|undefined),
- * iconType: (string|undefined),
- * priority: (number|undefined),
- * isSecondary: (boolean|undefined),
- * subtitleRenderer: (function():!Element|undefined),
- * selectionRange: ({startColumn: number, endColumn: number}|undefined),
- * hideGhostText: (boolean|undefined)
- * }}
- */
+ * text: string,
+ * title: (string|undefined),
+ * subtitle: (string|undefined),
+ * iconType: (string|undefined),
+ * priority: (number|undefined),
+ * isSecondary: (boolean|undefined),
+ * subtitleRenderer: (function():!Element|undefined),
+ * selectionRange: ({startColumn: number, endColumn: number}|undefined),
+ * hideGhostText: (boolean|undefined)
+ * }}
+ */
UI.SuggestBox.Suggestion;
/**
- * @typedef {!Array<!UI.SuggestBox.Suggestion>}
- */
+ * @typedef {!Array<!UI.SuggestBox.Suggestion>}
+ */
UI.SuggestBox.Suggestions;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SyntaxHighlighter.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SyntaxHighlighter.js
index fb2ebbd9b18..5ad445a0d23 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SyntaxHighlighter.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SyntaxHighlighter.js
@@ -31,7 +31,7 @@
/**
* @unrestricted
*/
-UI.SyntaxHighlighter = class {
+export default class SyntaxHighlighter {
/**
* @param {string} mimeType
* @param {boolean} stripExtraWhitespace
@@ -49,8 +49,9 @@ UI.SyntaxHighlighter = class {
createSpan(content, className) {
const span = createElement('span');
span.className = className.replace(/\S+/g, 'cm-$&');
- if (this._stripExtraWhitespace && className !== 'whitespace')
+ if (this._stripExtraWhitespace && className !== 'whitespace') {
content = content.replace(/^[\n\r]*/, '').replace(/\s*$/, '');
+ }
span.createTextChild(content);
return span;
}
@@ -68,7 +69,7 @@ UI.SyntaxHighlighter = class {
/**
* @param {!TextUtils.TokenizerFactory} tokenizerFactory
- * @this {UI.SyntaxHighlighter}
+ * @this {SyntaxHighlighter}
*/
function processTokens(tokenizerFactory) {
node.removeChildren();
@@ -81,8 +82,9 @@ UI.SyntaxHighlighter = class {
const plainText = line.substring(plainTextStart, line.length);
node.createTextChild(plainText);
}
- if (i < lines.length - 1)
+ if (i < lines.length - 1) {
node.createTextChild('\n');
+ }
}
}
@@ -91,11 +93,12 @@ UI.SyntaxHighlighter = class {
* @param {?string} tokenType
* @param {number} column
* @param {number} newColumn
- * @this {UI.SyntaxHighlighter}
+ * @this {SyntaxHighlighter}
*/
function processToken(token, tokenType, column, newColumn) {
- if (!tokenType)
+ if (!tokenType) {
return;
+ }
if (column > plainTextStart) {
const plainText = line.substring(plainTextStart, column);
@@ -105,4 +108,13 @@ UI.SyntaxHighlighter = class {
plainTextStart = newColumn;
}
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.SyntaxHighlighter = SyntaxHighlighter;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js
index 85423436ee6..e0ef4ea547d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js
@@ -31,13 +31,14 @@
/**
* @unrestricted
*/
-UI.TabbedPane = class extends UI.VBox {
+export default class TabbedPane extends UI.VBox {
constructor() {
super(true);
this.registerRequiredCSS('ui/tabbedPane.css');
this.element.classList.add('tabbed-pane');
this.contentElement.classList.add('tabbed-pane-shadow');
this.contentElement.tabIndex = -1;
+ this.setDefaultFocusedElement(this.contentElement);
this._headerElement = this.contentElement.createChild('div', 'tabbed-pane-header');
this._headerContentsElement = this._headerElement.createChild('div', 'tabbed-pane-header-contents');
this._tabSlider = createElementWithClass('div', 'tabbed-pane-tab-slider');
@@ -47,11 +48,11 @@ UI.TabbedPane = class extends UI.VBox {
this._contentElement = this.contentElement.createChild('div', 'tabbed-pane-content');
this._contentElement.setAttribute('role', 'tabpanel');
this._contentElement.createChild('slot');
- /** @type {!Array.<!UI.TabbedPaneTab>} */
+ /** @type {!Array.<!TabbedPaneTab>} */
this._tabs = [];
- /** @type {!Array.<!UI.TabbedPaneTab>} */
+ /** @type {!Array.<!TabbedPaneTab>} */
this._tabsHistory = [];
- /** @type {!Map<string, !UI.TabbedPaneTab>} */
+ /** @type {!Map<string, !TabbedPaneTab>} */
this._tabsById = new Map();
this._currentTabLocked = false;
this._autoSelectFirstItemOnShow = true;
@@ -153,10 +154,11 @@ UI.TabbedPane = class extends UI.VBox {
* @override
*/
focus() {
- if (this.visibleView)
+ if (this.visibleView) {
this.visibleView.focus();
- else
- this.contentElement.focus();
+ } else {
+ this._defaultFocusedElement.focus(); /** _defaultFocusedElement defined in Widget.js */
+ }
}
/**
@@ -176,12 +178,13 @@ UI.TabbedPane = class extends UI.VBox {
}
/**
- * @param {!UI.TabbedPaneTabDelegate} delegate
+ * @param {!TabbedPaneTabDelegate} delegate
*/
setTabDelegate(delegate) {
const tabs = this._tabs.slice();
- for (let i = 0; i < tabs.length; ++i)
+ for (let i = 0; i < tabs.length; ++i) {
tabs[i].setDelegate(delegate);
+ }
this._delegate = delegate;
}
@@ -196,17 +199,19 @@ UI.TabbedPane = class extends UI.VBox {
*/
appendTab(id, tabTitle, view, tabTooltip, userGesture, isCloseable, index) {
isCloseable = typeof isCloseable === 'boolean' ? isCloseable : this._closeableTabs;
- const tab = new UI.TabbedPaneTab(this, id, tabTitle, isCloseable, view, tabTooltip);
+ const tab = new TabbedPaneTab(this, id, tabTitle, isCloseable, view, tabTooltip);
tab.setDelegate(this._delegate);
console.assert(!this._tabsById.has(id), `Tabbed pane already contains a tab with id '${id}'`);
this._tabsById.set(id, tab);
- if (index !== undefined)
+ if (index !== undefined) {
this._tabs.splice(index, 0, tab);
- else
+ } else {
this._tabs.push(tab);
+ }
this._tabsHistory.push(tab);
- if (this._tabsHistory[0] === tab && this.isShowing())
+ if (this._tabsHistory[0] === tab && this.isShowing()) {
this.selectTab(tab.id, userGesture);
+ }
this._updateTabElements();
}
@@ -225,13 +230,16 @@ UI.TabbedPane = class extends UI.VBox {
*/
closeTabs(ids, userGesture) {
const focused = this.hasFocus();
- for (let i = 0; i < ids.length; ++i)
+ for (let i = 0; i < ids.length; ++i) {
this._innerCloseTab(ids[i], userGesture);
+ }
this._updateTabElements();
- if (this._tabsHistory.length)
+ if (this._tabsHistory.length) {
this.selectTab(this._tabsHistory[0].id, false);
- if (focused)
+ }
+ if (focused) {
this.focus();
+ }
}
/**
@@ -239,23 +247,27 @@ UI.TabbedPane = class extends UI.VBox {
* @param {boolean=} userGesture
*/
_innerCloseTab(id, userGesture) {
- if (!this._tabsById.has(id))
+ if (!this._tabsById.has(id)) {
return;
- if (userGesture && !this._tabsById.get(id)._closeable)
+ }
+ if (userGesture && !this._tabsById.get(id)._closeable) {
return;
- if (this._currentTab && this._currentTab.id === id)
+ }
+ if (this._currentTab && this._currentTab.id === id) {
this._hideCurrentTab();
+ }
const tab = this._tabsById.get(id);
this._tabsById.delete(id);
this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1);
this._tabs.splice(this._tabs.indexOf(tab), 1);
- if (tab._shown)
+ if (tab._shown) {
this._hideTabElement(tab);
+ }
const eventData = {tabId: id, view: tab.view, isUserGesture: userGesture};
- this.dispatchEventToListeners(UI.TabbedPane.Events.TabClosed, eventData);
+ this.dispatchEventToListeners(Events.TabClosed, eventData);
return true;
}
@@ -274,8 +286,9 @@ UI.TabbedPane = class extends UI.VBox {
otherTabs(id) {
const result = [];
for (let i = 0; i < this._tabs.length; ++i) {
- if (this._tabs[i].id !== id)
+ if (this._tabs[i].id !== id) {
result.push(this._tabs[i].id);
+ }
}
return result;
}
@@ -292,33 +305,39 @@ UI.TabbedPane = class extends UI.VBox {
break;
}
}
- if (index === -1)
+ if (index === -1) {
return [];
+ }
return this._tabs.slice(index + 1).map(function(tab) {
return tab.id;
});
}
_viewHasFocus() {
- if (this.visibleView && this.visibleView.hasFocus())
+ if (this.visibleView && this.visibleView.hasFocus()) {
return true;
+ }
return this.contentElement === this.contentElement.getComponentRoot().activeElement;
}
/**
* @param {string} id
* @param {boolean=} userGesture
+ * @param {boolean=} forceFocus
* @return {boolean}
*/
- selectTab(id, userGesture) {
- if (this._currentTabLocked)
+ selectTab(id, userGesture, forceFocus) {
+ if (this._currentTabLocked) {
return false;
+ }
const focused = this._viewHasFocus();
const tab = this._tabsById.get(id);
- if (!tab)
+ if (!tab) {
return false;
- if (this._currentTab && this._currentTab.id === id)
+ }
+ if (this._currentTab && this._currentTab.id === id) {
return true;
+ }
this.suspendInvalidations();
this._hideCurrentTab();
@@ -330,11 +349,12 @@ UI.TabbedPane = class extends UI.VBox {
this._tabsHistory.splice(0, 0, tab);
this._updateTabElements();
- if (focused)
+ if (focused || forceFocus) {
this.focus();
+ }
const eventData = {tabId: id, view: tab.view, isUserGesture: userGesture};
- this.dispatchEventToListeners(UI.TabbedPane.Events.TabSelected, eventData);
+ this.dispatchEventToListeners(Events.TabSelected, eventData);
return true;
}
@@ -388,18 +408,21 @@ UI.TabbedPane = class extends UI.VBox {
*/
toggleTabClass(id, className, force) {
const tab = this._tabsById.get(id);
- if (tab._toggleClass(className, force))
+ if (tab._toggleClass(className, force)) {
this._updateTabElements();
+ }
}
/**
* @param {!Common.Event} event
*/
_zoomChanged(event) {
- for (let i = 0; i < this._tabs.length; ++i)
+ for (let i = 0; i < this._tabs.length; ++i) {
delete this._tabs[i]._measuredWidth;
- if (this.isShowing())
+ }
+ if (this.isShowing()) {
this._updateTabElements();
+ }
}
/**
@@ -409,10 +432,12 @@ UI.TabbedPane = class extends UI.VBox {
*/
changeTabTitle(id, tabTitle, tabTooltip) {
const tab = this._tabsById.get(id);
- if (tabTooltip !== undefined)
+ if (tabTooltip !== undefined) {
tab.tooltip = tabTooltip;
+ }
if (tab.title !== tabTitle) {
tab.title = tabTitle;
+ UI.ARIAUtils.setAccessibleName(tab.tabElement, tabTitle);
this._updateTabElements();
}
}
@@ -423,19 +448,23 @@ UI.TabbedPane = class extends UI.VBox {
*/
changeTabView(id, view) {
const tab = this._tabsById.get(id);
- if (tab.view === view)
+ if (tab.view === view) {
return;
+ }
this.suspendInvalidations();
const isSelected = this._currentTab && this._currentTab.id === id;
const shouldFocus = tab.view.hasFocus();
- if (isSelected)
+ if (isSelected) {
this._hideTab(tab);
+ }
tab.view = view;
- if (isSelected)
+ if (isSelected) {
this._showTab(tab);
- if (shouldFocus)
+ }
+ if (shouldFocus) {
tab.view.focus();
+ }
this.resumeInvalidations();
}
@@ -455,13 +484,15 @@ UI.TabbedPane = class extends UI.VBox {
*/
wasShown() {
const effectiveTab = this._currentTab || this._tabsHistory[0];
- if (effectiveTab && this._autoSelectFirstItemOnShow)
+ if (effectiveTab && this._autoSelectFirstItemOnShow) {
this.selectTab(effectiveTab.id);
+ }
}
makeTabSlider() {
- if (this._verticalTabLayout)
+ if (this._verticalTabLayout) {
return;
+ }
this._setTabSlider(true);
}
@@ -481,10 +512,11 @@ UI.TabbedPane = class extends UI.VBox {
let constraints = super.calculateConstraints();
const minContentConstraints = new UI.Constraints(new UI.Size(0, 0), new UI.Size(50, 50));
constraints = constraints.widthToMax(minContentConstraints).heightToMax(minContentConstraints);
- if (this._verticalTabLayout)
+ if (this._verticalTabLayout) {
constraints = constraints.addWidth(new UI.Constraints(new UI.Size(120, 0)));
- else
+ } else {
constraints = constraints.addHeight(new UI.Constraints(new UI.Size(0, 30)));
+ }
return constraints;
}
@@ -494,10 +526,13 @@ UI.TabbedPane = class extends UI.VBox {
/**
* @param {!Element} element
+ * @param {!Element=} focusedElement
*/
- setPlaceholderElement(element) {
+ setPlaceholderElement(element, focusedElement) {
this._placeholderElement = element;
-
+ if (focusedElement) {
+ this._focusedPlaceholderElement = focusedElement;
+ }
if (this._placeholderContainerElement) {
this._placeholderContainerElement.removeChildren();
this._placeholderContainerElement.appendChild(element);
@@ -505,19 +540,25 @@ UI.TabbedPane = class extends UI.VBox {
}
_innerUpdateTabElements() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
if (!this._tabs.length) {
this._contentElement.classList.add('has-no-tabs');
if (this._placeholderElement && !this._placeholderContainerElement) {
this._placeholderContainerElement = this._contentElement.createChild('div', 'tabbed-pane-placeholder fill');
this._placeholderContainerElement.appendChild(this._placeholderElement);
+ if (this._focusedPlaceholderElement) {
+ this.setDefaultFocusedElement(this._focusedPlaceholderElement);
+ this.focus();
+ }
}
} else {
this._contentElement.classList.remove('has-no-tabs');
if (this._placeholderContainerElement) {
this._placeholderContainerElement.remove();
+ this.setDefaultFocusedElement(this.contentElement);
delete this._placeholderContainerElement;
}
}
@@ -530,18 +571,19 @@ UI.TabbedPane = class extends UI.VBox {
/**
* @param {number} index
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!TabbedPaneTab} tab
*/
_showTabElement(index, tab) {
- if (index >= this._tabsElement.children.length)
+ if (index >= this._tabsElement.children.length) {
this._tabsElement.appendChild(tab.tabElement);
- else
+ } else {
this._tabsElement.insertBefore(tab.tabElement, this._tabsElement.children[index]);
+ }
tab._shown = true;
}
/**
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!TabbedPaneTab} tab
*/
_hideTabElement(tab) {
this._tabsElement.removeChild(tab.tabElement);
@@ -551,13 +593,16 @@ UI.TabbedPane = class extends UI.VBox {
_createDropDownButton() {
const dropDownContainer = createElementWithClass('div', 'tabbed-pane-header-tabs-drop-down-container');
const chevronIcon = UI.Icon.create('largeicon-chevron', 'chevron-icon');
- UI.ARIAUtils.markAsButton(dropDownContainer);
+ UI.ARIAUtils.markAsMenuButton(dropDownContainer);
UI.ARIAUtils.setAccessibleName(dropDownContainer, ls`More tabs`);
+ dropDownContainer.tabIndex = 0;
dropDownContainer.appendChild(chevronIcon);
dropDownContainer.addEventListener('click', this._dropDownClicked.bind(this));
+ dropDownContainer.addEventListener('keydown', this._dropDownKeydown.bind(this));
dropDownContainer.addEventListener('mousedown', event => {
- if (event.which !== 1 || this._triggerDropDownTimeout)
+ if (event.which !== 1 || this._triggerDropDownTimeout) {
return;
+ }
this._triggerDropDownTimeout = setTimeout(this._dropDownClicked.bind(this, event), 200);
});
return dropDownContainer;
@@ -567,8 +612,9 @@ UI.TabbedPane = class extends UI.VBox {
* @param {!Event} event
*/
_dropDownClicked(event) {
- if (event.which !== 1)
+ if (event.which !== 1) {
return;
+ }
if (this._triggerDropDownTimeout) {
clearTimeout(this._triggerDropDownTimeout);
this._triggerDropDownTimeout = null;
@@ -577,8 +623,9 @@ UI.TabbedPane = class extends UI.VBox {
const menu = new UI.ContextMenu(event, false, rect.left, rect.bottom);
for (let i = 0; i < this._tabs.length; ++i) {
const tab = this._tabs[i];
- if (tab._shown)
+ if (tab._shown) {
continue;
+ }
menu.defaultSection().appendCheckboxItem(
tab.title, this._dropDownMenuItemSelected.bind(this, tab), this._tabsHistory[0] === tab);
}
@@ -586,11 +633,21 @@ UI.TabbedPane = class extends UI.VBox {
}
/**
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!Event} event
+ */
+ _dropDownKeydown(event) {
+ if (isEnterOrSpaceKey(event)) {
+ this._dropDownButton.click();
+ event.consume(true);
+ }
+ }
+
+ /**
+ * @param {!TabbedPaneTab} tab
*/
_dropDownMenuItemSelected(tab) {
this._lastSelectedOverflowTab = tab;
- this.selectTab(tab.id, true);
+ this.selectTab(tab.id, true, true);
}
_totalWidth() {
@@ -603,8 +660,9 @@ UI.TabbedPane = class extends UI.VBox {
_numberOfTabsShown() {
let numTabsShown = 0;
for (const tab of this._tabs) {
- if (tab._shown)
+ if (tab._shown) {
numTabsShown++;
+ }
}
return numTabsShown;
}
@@ -623,32 +681,37 @@ UI.TabbedPane = class extends UI.VBox {
}
for (let i = 0; i < this._tabs.length; ++i) {
- if (this._tabs[i]._shown && tabsToShowIndexes.indexOf(i) === -1)
+ if (this._tabs[i]._shown && tabsToShowIndexes.indexOf(i) === -1) {
this._hideTabElement(this._tabs[i]);
+ }
}
for (let i = 0; i < tabsToShowIndexes.length; ++i) {
const tab = this._tabs[tabsToShowIndexes[i]];
- if (!tab._shown)
+ if (!tab._shown) {
this._showTabElement(i, tab);
+ }
}
- if (!this._overflowDisabled)
+ if (!this._overflowDisabled) {
this._maybeShowDropDown(tabsToShowIndexes.length !== this._tabs.length);
+ }
}
/**
* @param {boolean} hasMoreTabs
*/
_maybeShowDropDown(hasMoreTabs) {
- if (hasMoreTabs && !this._dropDownButton.parentElement)
+ if (hasMoreTabs && !this._dropDownButton.parentElement) {
this._headerContentsElement.appendChild(this._dropDownButton);
- else if (!hasMoreTabs && this._dropDownButton.parentElement)
+ } else if (!hasMoreTabs && this._dropDownButton.parentElement) {
this._headerContentsElement.removeChild(this._dropDownButton);
+ }
}
_measureDropDownButton() {
- if (this._overflowDisabled || this._measuredDropDownButtonWidth)
+ if (this._overflowDisabled || this._measuredDropDownButtonWidth) {
return;
+ }
this._dropDownButton.classList.add('measuring');
this._headerContentsElement.appendChild(this._dropDownButton);
this._measuredDropDownButtonWidth = this._dropDownButton.getBoundingClientRect().width;
@@ -662,8 +725,9 @@ UI.TabbedPane = class extends UI.VBox {
this._shrinkableTabs ? this._calculateMaxWidth(measuredWidths.slice(), this._totalWidth()) : Number.MAX_VALUE;
let i = 0;
- for (const tab of this._tabs)
+ for (const tab of this._tabs) {
tab.setWidth(this._verticalTabLayout ? -1 : Math.min(maxWidth, measuredWidths[i++]));
+ }
}
_measureWidths() {
@@ -671,8 +735,9 @@ UI.TabbedPane = class extends UI.VBox {
this._tabsElement.style.setProperty('width', '2000px');
const measuringTabElements = [];
for (const tab of this._tabs) {
- if (typeof tab._measuredWidth === 'number')
+ if (typeof tab._measuredWidth === 'number') {
continue;
+ }
const measuringTabElement = tab._createTabElement(true);
measuringTabElement.__tab = tab;
measuringTabElements.push(measuringTabElement);
@@ -686,13 +751,15 @@ UI.TabbedPane = class extends UI.VBox {
}
// Nuke elements from the UI
- for (let i = 0; i < measuringTabElements.length; ++i)
+ for (let i = 0; i < measuringTabElements.length; ++i) {
measuringTabElements[i].remove();
+ }
// Combine the results.
const measuredWidths = [];
- for (const tab of this._tabs)
+ for (const tab of this._tabs) {
measuredWidths.push(tab._measuredWidth);
+ }
this._tabsElement.style.removeProperty('width');
return measuredWidths;
@@ -703,19 +770,22 @@ UI.TabbedPane = class extends UI.VBox {
* @param {number} totalWidth
*/
_calculateMaxWidth(measuredWidths, totalWidth) {
- if (!measuredWidths.length)
+ if (!measuredWidths.length) {
return 0;
+ }
measuredWidths.sort(function(x, y) {
return x - y;
});
let totalMeasuredWidth = 0;
- for (let i = 0; i < measuredWidths.length; ++i)
+ for (let i = 0; i < measuredWidths.length; ++i) {
totalMeasuredWidth += measuredWidths[i];
+ }
- if (totalWidth >= totalMeasuredWidth)
+ if (totalWidth >= totalMeasuredWidth) {
return measuredWidths[measuredWidths.length - 1];
+ }
let totalExtraWidth = 0;
for (let i = measuredWidths.length - 1; i > 0; --i) {
@@ -732,8 +802,8 @@ UI.TabbedPane = class extends UI.VBox {
}
/**
- * @param {!Array.<!UI.TabbedPaneTab>} tabsOrdered
- * @param {!Array.<!UI.TabbedPaneTab>} tabsHistory
+ * @param {!Array.<!TabbedPaneTab>} tabsOrdered
+ * @param {!Array.<!TabbedPaneTab>} tabsHistory
* @param {number} totalWidth
* @param {number} measuredDropDownButtonWidth
* @return {!Array.<number>}
@@ -744,18 +814,22 @@ UI.TabbedPane = class extends UI.VBox {
let totalTabsWidth = 0;
const tabCount = tabsOrdered.length;
const tabsToLookAt = tabsOrdered.slice(0);
- if (this._currentTab !== undefined)
+ if (this._currentTab !== undefined) {
tabsToLookAt.unshift(tabsToLookAt.splice(tabsToLookAt.indexOf(this._currentTab), 1)[0]);
- if (this._lastSelectedOverflowTab !== undefined)
+ }
+ if (this._lastSelectedOverflowTab !== undefined) {
tabsToLookAt.unshift(tabsToLookAt.splice(tabsToLookAt.indexOf(this._lastSelectedOverflowTab), 1)[0]);
+ }
for (let i = 0; i < tabCount; ++i) {
const tab = this._automaticReorder ? tabsHistory[i] : tabsToLookAt[i];
totalTabsWidth += tab.width();
let minimalRequiredWidth = totalTabsWidth;
- if (i !== tabCount - 1)
+ if (i !== tabCount - 1) {
minimalRequiredWidth += measuredDropDownButtonWidth;
- if (!this._verticalTabLayout && minimalRequiredWidth > totalWidth)
+ }
+ if (!this._verticalTabLayout && minimalRequiredWidth > totalWidth) {
break;
+ }
tabsToShowIndexes.push(tabsOrdered.indexOf(tab));
}
@@ -767,15 +841,16 @@ UI.TabbedPane = class extends UI.VBox {
}
_hideCurrentTab() {
- if (!this._currentTab)
+ if (!this._currentTab) {
return;
+ }
this._hideTab(this._currentTab);
delete this._currentTab;
}
/**
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!TabbedPaneTab} tab
*/
_showTab(tab) {
tab.tabElement.tabIndex = 0;
@@ -786,28 +861,31 @@ UI.TabbedPane = class extends UI.VBox {
}
_updateTabSlider() {
- if (!this._sliderEnabled)
+ if (!this._sliderEnabled) {
return;
+ }
if (!this._currentTab) {
this._tabSlider.style.width = 0;
return;
}
let left = 0;
for (let i = 0; i < this._tabs.length && this._currentTab !== this._tabs[i]; i++) {
- if (this._tabs[i]._shown)
+ if (this._tabs[i]._shown) {
left += this._tabs[i]._measuredWidth;
+ }
}
const sliderWidth = this._currentTab._shown ? this._currentTab._measuredWidth : this._dropDownButton.offsetWidth;
const scaleFactor = window.devicePixelRatio >= 1.5 ? ' scaleY(0.75)' : '';
this._tabSlider.style.transform = 'translateX(' + left + 'px)' + scaleFactor;
this._tabSlider.style.width = sliderWidth + 'px';
- if (this._tabSlider.parentElement !== this._headerContentsElement)
+ if (this._tabSlider.parentElement !== this._headerContentsElement) {
this._headerContentsElement.appendChild(this._tabSlider);
+ }
}
/**
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!TabbedPaneTab} tab
*/
_hideTab(tab) {
tab.tabElement.removeAttribute('tabIndex');
@@ -825,17 +903,18 @@ UI.TabbedPane = class extends UI.VBox {
}
/**
- * @param {!UI.TabbedPaneTab} tab
+ * @param {!TabbedPaneTab} tab
* @param {number} index
*/
_insertBefore(tab, index) {
this._tabsElement.insertBefore(tab.tabElement, this._tabsElement.childNodes[index]);
const oldIndex = this._tabs.indexOf(tab);
this._tabs.splice(oldIndex, 1);
- if (oldIndex < index)
+ if (oldIndex < index) {
--index;
+ }
this._tabs.splice(index, 0, tab);
- this.dispatchEventToListeners(UI.TabbedPane.Events.TabOrderChanged, {tabId: tab.id});
+ this.dispatchEventToListeners(Events.TabOrderChanged, {tabId: tab.id});
}
/**
@@ -873,21 +952,24 @@ UI.TabbedPane = class extends UI.VBox {
* @param {!Event} event
*/
_keyDown(event) {
- if (!this._currentTab)
+ if (!this._currentTab) {
return;
+ }
let nextTabElement = null;
switch (event.key) {
case 'ArrowUp':
case 'ArrowLeft':
nextTabElement = this._currentTab.tabElement.previousElementSibling;
- if (!nextTabElement && !this._dropDownButton.parentElement)
+ if (!nextTabElement && !this._dropDownButton.parentElement) {
nextTabElement = this._currentTab.tabElement.parentElement.lastElementChild;
+ }
break;
case 'ArrowDown':
case 'ArrowRight':
nextTabElement = this._currentTab.tabElement.nextElementSibling;
- if (!nextTabElement && !this._dropDownButton.parentElement)
+ if (!nextTabElement && !this._dropDownButton.parentElement) {
nextTabElement = this._currentTab.tabElement.parentElement.firstElementChild;
+ }
break;
case 'Enter':
case ' ':
@@ -904,10 +986,10 @@ UI.TabbedPane = class extends UI.VBox {
this.selectTab(tab.id, true);
nextTabElement.focus();
}
-};
+}
/** @enum {symbol} */
-UI.TabbedPane.Events = {
+export const Events = {
TabSelected: Symbol('TabSelected'),
TabClosed: Symbol('TabClosed'),
TabOrderChanged: Symbol('TabOrderChanged')
@@ -916,7 +998,7 @@ UI.TabbedPane.Events = {
/**
* @unrestricted
*/
-UI.TabbedPaneTab = class {
+export class TabbedPaneTab {
/**
* @param {!UI.TabbedPane} tabbedPane
* @param {string} id
@@ -959,11 +1041,13 @@ UI.TabbedPaneTab = class {
* @param {string} title
*/
set title(title) {
- if (title === this._title)
+ if (title === this._title) {
return;
+ }
this._title = title;
- if (this._titleElement)
+ if (this._titleElement) {
this._titleElement.textContent = title;
+ }
delete this._measuredWidth;
}
@@ -979,8 +1063,9 @@ UI.TabbedPaneTab = class {
*/
_setIcon(icon) {
this._icon = icon;
- if (this._tabElement)
+ if (this._tabElement) {
this._createIconElement(this._tabElement, this._titleElement, false);
+ }
delete this._measuredWidth;
}
@@ -992,8 +1077,9 @@ UI.TabbedPaneTab = class {
_toggleClass(className, force) {
const element = this.tabElement;
const hasClass = element.classList.contains(className);
- if (hasClass === force)
+ if (hasClass === force) {
return false;
+ }
element.classList.toggle(className, force);
delete this._measuredWidth;
return true;
@@ -1025,16 +1111,18 @@ UI.TabbedPaneTab = class {
*/
set tooltip(tooltip) {
this._tooltip = tooltip;
- if (this._titleElement)
+ if (this._titleElement) {
this._titleElement.title = tooltip || '';
+ }
}
/**
* @return {!Element}
*/
get tabElement() {
- if (!this._tabElement)
+ if (!this._tabElement) {
this._tabElement = this._createTabElement(false);
+ }
return this._tabElement;
}
@@ -1055,7 +1143,7 @@ UI.TabbedPaneTab = class {
}
/**
- * @param {!UI.TabbedPaneTabDelegate} delegate
+ * @param {!TabbedPaneTabDelegate} delegate
*/
setDelegate(delegate) {
this._delegate = delegate;
@@ -1071,8 +1159,9 @@ UI.TabbedPaneTab = class {
tabElement.__iconElement.remove();
tabElement.__iconElement = null;
}
- if (!this._icon)
+ if (!this._icon) {
return;
+ }
const iconContainer = createElementWithClass('span', 'tabbed-pane-header-tab-icon');
const iconNode = measuring ? this._icon.cloneNode(true) : this._icon;
@@ -1096,8 +1185,9 @@ UI.TabbedPaneTab = class {
titleElement.textContent = this.title;
titleElement.title = this.tooltip || '';
this._createIconElement(tabElement, titleElement, measuring);
- if (!measuring)
+ if (!measuring) {
this._titleElement = titleElement;
+ }
if (this._closeable) {
const closeButton = tabElement.createChild('div', 'tabbed-pane-close-button', 'dt-close-button');
@@ -1144,8 +1234,9 @@ UI.TabbedPaneTab = class {
* @param {!Event} event
*/
_tabMouseDown(event) {
- if (event.target.classList.contains('tabbed-pane-close-button') || event.button === 1)
+ if (event.target.classList.contains('tabbed-pane-close-button') || event.button === 1) {
return;
+ }
this._tabbedPane.selectTab(this.id, true);
}
@@ -1154,8 +1245,9 @@ UI.TabbedPaneTab = class {
*/
_tabMouseUp(event) {
// This is needed to prevent middle-click pasting on linux when tabs are clicked.
- if (event.button === 1)
+ if (event.button === 1) {
event.consume(true);
+ }
}
/**
@@ -1171,28 +1263,28 @@ UI.TabbedPaneTab = class {
_tabContextMenu(event) {
/**
- * @this {UI.TabbedPaneTab}
+ * @this {TabbedPaneTab}
*/
function close() {
this._closeTabs([this.id]);
}
/**
- * @this {UI.TabbedPaneTab}
+ * @this {TabbedPaneTab}
*/
function closeOthers() {
this._closeTabs(this._tabbedPane.otherTabs(this.id));
}
/**
- * @this {UI.TabbedPaneTab}
+ * @this {TabbedPaneTab}
*/
function closeAll() {
this._closeTabs(this._tabbedPane.tabIds());
}
/**
- * @this {UI.TabbedPaneTab}
+ * @this {TabbedPaneTab}
*/
function closeToTheRight() {
this._closeTabs(this._tabbedPane._tabsToTheRight(this.id));
@@ -1205,8 +1297,9 @@ UI.TabbedPaneTab = class {
contextMenu.defaultSection().appendItem(Common.UIString('Close tabs to the right'), closeToTheRight.bind(this));
contextMenu.defaultSection().appendItem(Common.UIString('Close all'), closeAll.bind(this));
}
- if (this._delegate)
+ if (this._delegate) {
this._delegate.onContextMenu(this.id, contextMenu);
+ }
contextMenu.show();
}
@@ -1215,8 +1308,9 @@ UI.TabbedPaneTab = class {
* @return {boolean}
*/
_startTabDragging(event) {
- if (event.target.classList.contains('tabbed-pane-close-button'))
+ if (event.target.classList.contains('tabbed-pane-close-button')) {
return false;
+ }
this._dragStartX = event.pageX;
this._tabElement.classList.add('dragging');
this._tabbedPane._tabSlider.remove();
@@ -1230,16 +1324,19 @@ UI.TabbedPaneTab = class {
const tabElements = this._tabbedPane._tabsElement.childNodes;
for (let i = 0; i < tabElements.length; ++i) {
let tabElement = tabElements[i];
- if (tabElement === this._tabElement)
+ if (tabElement === this._tabElement) {
continue;
+ }
const intersects = tabElement.offsetLeft + tabElement.clientWidth > this._tabElement.offsetLeft &&
this._tabElement.offsetLeft + this._tabElement.clientWidth > tabElement.offsetLeft;
- if (!intersects)
+ if (!intersects) {
continue;
+ }
- if (Math.abs(event.pageX - this._dragStartX) < tabElement.clientWidth / 2 + 5)
+ if (Math.abs(event.pageX - this._dragStartX) < tabElement.clientWidth / 2 + 5) {
break;
+ }
if (event.pageX - this._dragStartX > 0) {
tabElement = tabElement.nextSibling;
@@ -1273,23 +1370,40 @@ UI.TabbedPaneTab = class {
delete this._dragStartX;
this._tabbedPane._updateTabSlider();
}
-};
+}
/**
* @interface
*/
-UI.TabbedPaneTabDelegate = function() {};
-
-UI.TabbedPaneTabDelegate.prototype = {
+export class TabbedPaneTabDelegate {
/**
* @param {!UI.TabbedPane} tabbedPane
* @param {!Array.<string>} ids
*/
- closeTabs(tabbedPane, ids) {},
+ closeTabs(tabbedPane, ids) {
+ }
/**
* @param {string} tabId
* @param {!UI.ContextMenu} contextMenu
*/
onContextMenu(tabId, contextMenu) {}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.TabbedPane = TabbedPane;
+
+/** @enum {symbol} */
+UI.TabbedPane.Events = Events;
+
+/** @constructor */
+UI.TabbedPaneTab = TabbedPaneTab;
+
+/** @interface */
+UI.TabbedPaneTabDelegate = TabbedPaneTabDelegate; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TargetCrashedScreen.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TargetCrashedScreen.js
index 5d0f2a1fb58..0fe73fd4e97 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TargetCrashedScreen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TargetCrashedScreen.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-UI.TargetCrashedScreen = class extends UI.VBox {
+export default class TargetCrashedScreen extends UI.VBox {
/**
* @param {function()} hideCallback
*/
@@ -22,4 +22,13 @@ UI.TargetCrashedScreen = class extends UI.VBox {
willHide() {
this._hideCallback.call(null);
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.TargetCrashedScreen = TargetCrashedScreen;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
index 34cb20cc139..3234d3559ec 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
@@ -4,129 +4,152 @@
/**
* @interface
*/
-UI.TextEditorFactory = function() {};
-
-UI.TextEditorFactory.prototype = {
+export class TextEditorFactory {
/**
* @param {!UI.TextEditor.Options} options
- * @return {!UI.TextEditor}
+ * @return {!TextEditor}
*/
createEditor(options) {}
-};
+}
/**
* @interface
- * @extends {Common.EventTarget}
*/
-UI.TextEditor = function() {};
-
-UI.TextEditor.prototype = {
-
+export class TextEditor extends Common.EventTarget {
/**
* @return {!UI.Widget}
*/
- widget() {},
+ widget() {
+ }
/**
* @return {!TextUtils.TextRange}
*/
- fullRange() {},
+ fullRange() {
+ }
/**
* @return {!TextUtils.TextRange}
*/
- selection() {},
+ selection() {
+ }
/**
* @param {!TextUtils.TextRange} selection
*/
- setSelection(selection) {},
+ setSelection(selection) {
+ }
/**
* @param {!TextUtils.TextRange=} textRange
* @return {string}
*/
- text(textRange) {},
+ text(textRange) {
+ }
/**
* @return {string}
*/
- textWithCurrentSuggestion() {},
+ textWithCurrentSuggestion() {
+ }
/**
* @param {string} text
*/
- setText(text) {},
+ setText(text) {
+ }
/**
* @param {number} lineNumber
* @return {string}
*/
- line(lineNumber) {},
+ line(lineNumber) {
+ }
- newlineAndIndent() {},
+ newlineAndIndent() {
+ }
/**
* @param {function(!KeyboardEvent)} handler
*/
- addKeyDownHandler(handler) {},
+ addKeyDownHandler(handler) {
+ }
/**
* @param {?UI.AutocompleteConfig} config
*/
- configureAutocomplete(config) {},
+ configureAutocomplete(config) {
+ }
- clearAutocomplete() {},
+ clearAutocomplete() {
+ }
/**
* @param {number} lineNumber
* @param {number} columnNumber
* @return {!{x: number, y: number}}
*/
- visualCoordinates(lineNumber, columnNumber) {},
+ visualCoordinates(lineNumber, columnNumber) {
+ }
/**
* @param {number} lineNumber
* @param {number} columnNumber
* @return {?{startColumn: number, endColumn: number, type: string}}
*/
- tokenAtTextPosition(lineNumber, columnNumber) {},
+ tokenAtTextPosition(lineNumber, columnNumber) {
+ }
/**
* @param {string} placeholder
*/
setPlaceholder(placeholder) {}
-};
+}
/** @enum {symbol} */
-UI.TextEditor.Events = {
+export const Events = {
CursorChanged: Symbol('CursorChanged'),
TextChanged: Symbol('TextChanged'),
SuggestionChanged: Symbol('SuggestionChanged')
};
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @interface */
+UI.TextEditor = TextEditor;
+
+/** @interface */
+UI.TextEditorFactory = TextEditorFactory;
+
+/** @enum {symbol} */
+UI.TextEditor.Events = Events;
+
/**
* @typedef {{
- * bracketMatchingSetting: (!Common.Setting|undefined),
- * devtoolsAccessibleName: (string|undefined),
- * lineNumbers: boolean,
- * lineWrapping: boolean,
- * mimeType: (string|undefined),
- * autoHeight: (boolean|undefined),
- * padBottom: (boolean|undefined),
- * maxHighlightLength: (number|undefined),
- * placeholder: (string|undefined)
- * }}
- */
+ * bracketMatchingSetting: (!Common.Setting|undefined),
+ * devtoolsAccessibleName: (string|undefined),
+ * lineNumbers: boolean,
+ * lineWrapping: boolean,
+ * mimeType: (string|undefined),
+ * autoHeight: (boolean|undefined),
+ * padBottom: (boolean|undefined),
+ * maxHighlightLength: (number|undefined),
+ * placeholder: (string|undefined)
+ * }}
+ */
UI.TextEditor.Options;
/**
- * @typedef {{
- * substituteRangeCallback: ((function(number, number):?TextUtils.TextRange)|undefined),
- * tooltipCallback: ((function(number, number):!Promise<?Element>)|undefined),
- * suggestionsCallback: ((function(!TextUtils.TextRange, !TextUtils.TextRange, boolean=):?Promise.<!UI.SuggestBox.Suggestions>)|undefined),
- * isWordChar: ((function(string):boolean)|undefined),
- * anchorBehavior: (UI.GlassPane.AnchorBehavior|undefined)
- * }}
- */
+ * @typedef {{
+ * substituteRangeCallback: ((function(number, number):?TextUtils.TextRange)|undefined),
+ * tooltipCallback: ((function(number, number):!Promise<?Element>)|undefined),
+ * suggestionsCallback: ((function(!TextUtils.TextRange, !TextUtils.TextRange, boolean=):?Promise.<!UI.SuggestBox.Suggestions>)|undefined),
+ * isWordChar: ((function(string):boolean)|undefined),
+ * anchorBehavior: (UI.GlassPane.AnchorBehavior|undefined)
+ * }}
+ */
UI.AutocompleteConfig;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
index b0e26a1d3d7..ec08d1925b9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
@@ -30,7 +30,7 @@
* @implements {UI.SuggestBoxDelegate}
* @unrestricted
*/
-UI.TextPrompt = class extends Common.Object {
+export default class TextPrompt extends Common.Object {
constructor() {
super();
/**
@@ -38,7 +38,7 @@ UI.TextPrompt = class extends Common.Object {
*/
this._proxyElement;
this._proxyElementDisplay = 'inline-block';
- this._autocompletionTimeout = UI.TextPrompt.DefaultAutocompletionTimeout;
+ this._autocompletionTimeout = DefaultAutocompletionTimeout;
this._title = '';
this._queryRange = null;
this._previousText = '';
@@ -101,8 +101,9 @@ UI.TextPrompt = class extends Common.Object {
* @return {!Element}
*/
_attachInternal(element) {
- if (this._proxyElement)
+ if (this._proxyElement) {
throw 'Cannot attach an attached TextPrompt';
+ }
this._element = element;
this._boundOnKeyDown = this.onKeyDown.bind(this);
@@ -126,8 +127,9 @@ UI.TextPrompt = class extends Common.Object {
this._suggestBox = new UI.SuggestBox(this, 20);
- if (this._title)
+ if (this._title) {
this._proxyElement.title = this._title;
+ }
return this._proxyElement;
}
@@ -148,8 +150,9 @@ UI.TextPrompt = class extends Common.Object {
*/
textWithCurrentSuggestion() {
const text = this.text();
- if (!this._queryRange || !this._currentSuggestion)
+ if (!this._queryRange || !this._currentSuggestion) {
return text;
+ }
const suggestion = this._currentSuggestion.text;
return text.substring(0, this._queryRange.startColumn) + suggestion + text.substring(this._queryRange.endColumn);
}
@@ -195,17 +198,21 @@ UI.TextPrompt = class extends Common.Object {
*/
setTitle(title) {
this._title = title;
- if (this._proxyElement)
+ if (this._proxyElement) {
this._proxyElement.title = title;
+ }
}
/**
* @param {string} placeholder
+ * @param {string=} ariaPlaceholder
*/
- setPlaceholder(placeholder) {
+ setPlaceholder(placeholder, ariaPlaceholder) {
if (placeholder) {
this._element.setAttribute('data-placeholder', placeholder);
- UI.ARIAUtils.setPlaceholder(this._element, placeholder);
+ // TODO(https://github.com/nvaccess/nvda/issues/10164): Remove ariaPlaceholder once the NVDA bug is fixed
+ // ariaPlaceholder and placeholder may differ, like in case the placeholder contains a '?'
+ UI.ARIAUtils.setPlaceholder(this._element, ariaPlaceholder || placeholder);
} else {
this._element.removeAttribute('data-placeholder');
UI.ARIAUtils.setPlaceholder(this._element, null);
@@ -216,10 +223,11 @@ UI.TextPrompt = class extends Common.Object {
* @param {boolean} enabled
*/
setEnabled(enabled) {
- if (enabled)
+ if (enabled) {
this._element.setAttribute('contenteditable', 'plaintext-only');
- else
+ } else {
this._element.removeAttribute('contenteditable');
+ }
this._element.classList.toggle('disabled', !enabled);
}
@@ -229,10 +237,12 @@ UI.TextPrompt = class extends Common.Object {
this._element.removeEventListener('input', this._boundOnInput, false);
this._element.removeEventListener('selectstart', this._boundClearAutocomplete, false);
this._element.removeEventListener('blur', this._boundClearAutocomplete, false);
- if (this._isEditing)
+ if (this._isEditing) {
this._stopEditing();
- if (this._suggestBox)
+ }
+ if (this._suggestBox) {
this._suggestBox.hide();
+ }
}
/**
@@ -246,17 +256,20 @@ UI.TextPrompt = class extends Common.Object {
this._element.addEventListener('blur', this._blurListener, false);
}
this._oldTabIndex = this._element.tabIndex;
- if (this._element.tabIndex < 0)
+ if (this._element.tabIndex < 0) {
this._element.tabIndex = 0;
+ }
this._focusRestorer = new UI.ElementFocusRestorer(this._element);
- if (!this.text())
+ if (!this.text()) {
this.autoCompleteSoon();
+ }
}
_stopEditing() {
this._element.tabIndex = this._oldTabIndex;
- if (this._blurListener)
+ if (this._blurListener) {
this._element.removeEventListener('blur', this._blurListener, false);
+ }
this._contentElement.classList.remove('text-prompt-editing');
delete this._isEditing;
}
@@ -292,10 +305,11 @@ UI.TextPrompt = class extends Common.Object {
case 'ArrowRight':
case 'ArrowDown':
case 'End':
- if (this._isCaretAtEndOfPrompt())
+ if (this._isCaretAtEndOfPrompt()) {
handled = this.acceptAutoComplete();
- else
+ } else {
this.clearAutocomplete();
+ }
break;
case 'Escape':
if (this.isSuggestBoxVisible()) {
@@ -311,11 +325,13 @@ UI.TextPrompt = class extends Common.Object {
break;
}
- if (isEnterKey(event))
+ if (isEnterKey(event)) {
event.preventDefault();
+ }
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
@@ -324,8 +340,9 @@ UI.TextPrompt = class extends Common.Object {
*/
_acceptSuggestionOnStopCharacters(key) {
if (!this._currentSuggestion || !this._queryRange || key.length !== 1 ||
- !this._completionStopCharacters.includes(key))
+ !this._completionStopCharacters.includes(key)) {
return false;
+ }
const query = this.text().substring(this._queryRange.startColumn, this._queryRange.endColumn);
if (query && this._currentSuggestion.text.startsWith(query + key)) {
@@ -342,12 +359,13 @@ UI.TextPrompt = class extends Common.Object {
const text = this.text();
if (event.data && !this._acceptSuggestionOnStopCharacters(event.data)) {
const hasCommonPrefix = text.startsWith(this._previousText) || this._previousText.startsWith(text);
- if (this._queryRange && hasCommonPrefix)
+ if (this._queryRange && hasCommonPrefix) {
this._queryRange.endColumn += text.length - this._previousText.length;
+ }
}
this._refreshGhostText();
this._previousText = text;
- this.dispatchEventToListeners(UI.TextPrompt.Events.TextChanged);
+ this.dispatchEventToListeners(Events.TextChanged);
this.autoCompleteSoon();
}
@@ -357,10 +375,12 @@ UI.TextPrompt = class extends Common.Object {
*/
acceptAutoComplete() {
let result = false;
- if (this.isSuggestBoxVisible())
+ if (this.isSuggestBoxVisible()) {
result = this._suggestBox.acceptSuggestion();
- if (!result)
+ }
+ if (!result) {
result = this._acceptSuggestionInternal();
+ }
return result;
}
@@ -368,14 +388,16 @@ UI.TextPrompt = class extends Common.Object {
clearAutocomplete() {
const beforeText = this.textWithCurrentSuggestion();
- if (this.isSuggestBoxVisible())
+ if (this.isSuggestBoxVisible()) {
this._suggestBox.hide();
+ }
this._clearAutocompleteTimeout();
this._queryRange = null;
this._refreshGhostText();
- if (beforeText !== this.textWithCurrentSuggestion())
- this.dispatchEventToListeners(UI.TextPrompt.Events.TextChanged);
+ if (beforeText !== this.textWithCurrentSuggestion()) {
+ this.dispatchEventToListeners(Events.TextChanged);
+ }
}
_refreshGhostText() {
@@ -419,15 +441,17 @@ UI.TextPrompt = class extends Common.Object {
this._clearAutocompleteTimeout();
const selection = this._element.getComponentSelection();
const selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
- if (!selectionRange)
+ if (!selectionRange) {
return;
+ }
let shouldExit;
- if (!force && !this._isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible())
+ if (!force && !this._isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible()) {
shouldExit = true;
- else if (!selection.isCollapsed)
+ } else if (!selection.isCollapsed) {
shouldExit = true;
+ }
if (shouldExit) {
this.clearAutocomplete();
@@ -489,8 +513,9 @@ UI.TextPrompt = class extends Common.Object {
* @param {!UI.SuggestBox.Suggestions} completions
*/
_completionsReady(completionRequestId, selection, originalWordQueryRange, force, completions) {
- if (this._completionRequestId !== completionRequestId)
+ if (this._completionRequestId !== completionRequestId) {
return;
+ }
const query = originalWordQueryRange.toString();
@@ -499,10 +524,11 @@ UI.TextPrompt = class extends Common.Object {
completions = completions.filter(item => !store.has(item.text) && !!store.add(item.text));
if (query || force) {
- if (query)
+ if (query) {
completions = completions.concat(this.additionalCompletions(query));
- else
+ } else {
completions = this.additionalCompletions(query).concat(completions);
+ }
}
if (!completions.length) {
@@ -516,8 +542,9 @@ UI.TextPrompt = class extends Common.Object {
fullWordRange.setStart(originalWordQueryRange.startContainer, originalWordQueryRange.startOffset);
fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);
- if (query + selectionRange.toString() !== fullWordRange.toString())
+ if (query + selectionRange.toString() !== fullWordRange.toString()) {
return;
+ }
const beforeRange = this._createRange();
beforeRange.setStart(this._element, 0);
@@ -541,8 +568,9 @@ UI.TextPrompt = class extends Common.Object {
applySuggestion(suggestion, isIntermediateSuggestion) {
this._currentSuggestion = suggestion;
this._refreshGhostText();
- if (isIntermediateSuggestion)
- this.dispatchEventToListeners(UI.TextPrompt.Events.TextChanged);
+ if (isIntermediateSuggestion) {
+ this.dispatchEventToListeners(Events.TextChanged);
+ }
}
/**
@@ -556,8 +584,9 @@ UI.TextPrompt = class extends Common.Object {
* @return {boolean}
*/
_acceptSuggestionInternal() {
- if (!this._queryRange)
+ if (!this._queryRange) {
return false;
+ }
const suggestionLength = this._currentSuggestion ? this._currentSuggestion.text.length : 0;
const selectionRange = this._currentSuggestion ? this._currentSuggestion.selectionRange : null;
@@ -567,7 +596,7 @@ UI.TextPrompt = class extends Common.Object {
this.setDOMSelection(this._queryRange.startColumn + startColumn, this._queryRange.startColumn + endColumn);
this.clearAutocomplete();
- this.dispatchEventToListeners(UI.TextPrompt.Events.TextChanged);
+ this.dispatchEventToListeners(Events.TextChanged);
return true;
}
@@ -579,8 +608,9 @@ UI.TextPrompt = class extends Common.Object {
setDOMSelection(startColumn, endColumn) {
this._element.normalize();
const node = this._element.childNodes[0];
- if (!node || node === this._ghostTextElement)
+ if (!node || node === this._ghostTextElement) {
return;
+ }
const range = this._createRange();
range.setStart(node, startColumn);
range.setEnd(node, endColumn);
@@ -604,8 +634,9 @@ UI.TextPrompt = class extends Common.Object {
const selection = this._element.getComponentSelection();
// @see crbug.com/602541
const selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
- if (!selectionRange || !selection.isCollapsed)
+ if (!selectionRange || !selection.isCollapsed) {
return false;
+ }
return selectionRange.startContainer.isSelfOrDescendant(this._element);
}
@@ -615,24 +646,29 @@ UI.TextPrompt = class extends Common.Object {
_isCaretAtEndOfPrompt() {
const selection = this._element.getComponentSelection();
const selectionRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
- if (!selectionRange || !selection.isCollapsed)
+ if (!selectionRange || !selection.isCollapsed) {
return false;
+ }
let node = selectionRange.startContainer;
- if (!node.isSelfOrDescendant(this._element))
+ if (!node.isSelfOrDescendant(this._element)) {
return false;
+ }
- if (this._ghostTextElement.isAncestor(node))
+ if (this._ghostTextElement.isAncestor(node)) {
return true;
+ }
- if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
+ if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length) {
return false;
+ }
let foundNextText = false;
while (node) {
if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
- if (foundNextText && !this._ghostTextElement.isAncestor(node))
+ if (foundNextText && !this._ghostTextElement.isAncestor(node)) {
return false;
+ }
foundNextText = true;
}
@@ -647,8 +683,9 @@ UI.TextPrompt = class extends Common.Object {
const selectionRange = this._createRange();
let container = this._element;
- while (container.childNodes.length)
+ while (container.childNodes.length) {
container = container.lastChild;
+ }
const offset = container.nodeType === Node.TEXT_NODE ? container.textContent.length : 0;
selectionRange.setStart(container, offset);
selectionRange.setEnd(container, offset);
@@ -671,11 +708,25 @@ UI.TextPrompt = class extends Common.Object {
proxyElementForTests() {
return this._proxyElement || null;
}
-};
+}
-UI.TextPrompt.DefaultAutocompletionTimeout = 250;
+export const DefaultAutocompletionTimeout = 250;
/** @enum {symbol} */
-UI.TextPrompt.Events = {
+export const Events = {
TextChanged: Symbol('TextChanged')
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.TextPrompt = TextPrompt;
+
+UI.TextPrompt.DefaultAutocompletionTimeout = DefaultAutocompletionTimeout;
+
+/** @enum {symbol} */
+UI.TextPrompt.Events = Events;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ThrottledWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ThrottledWidget.js
index bbb4f376f81..3903f18e389 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ThrottledWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ThrottledWidget.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.ThrottledWidget = class extends UI.VBox {
+export default class ThrottledWidget extends UI.VBox {
/**
* @param {boolean=} isWebComponent
* @param {number=} timeout
@@ -25,17 +25,19 @@ UI.ThrottledWidget = class extends UI.VBox {
update() {
this._updateWhenVisible = !this.isShowing();
- if (this._updateWhenVisible)
+ if (this._updateWhenVisible) {
return;
+ }
this._updateThrottler.schedule(innerUpdate.bind(this));
/**
- * @this {UI.ThrottledWidget}
+ * @this {ThrottledWidget}
* @return {!Promise<?>}
*/
function innerUpdate() {
- if (this.isShowing())
+ if (this.isShowing()) {
return this.doUpdate();
+ }
this._updateWhenVisible = true;
return Promise.resolve();
}
@@ -46,7 +48,17 @@ UI.ThrottledWidget = class extends UI.VBox {
*/
wasShown() {
super.wasShown();
- if (this._updateWhenVisible)
+ if (this._updateWhenVisible) {
this.update();
+ }
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ThrottledWidget = ThrottledWidget;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
index bc9e0453bce..eb98520fed1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
@@ -31,13 +31,13 @@
/**
* @unrestricted
*/
-UI.Toolbar = class {
+export default class Toolbar {
/**
* @param {string} className
* @param {!Element=} parentElement
*/
constructor(className, parentElement) {
- /** @type {!Array.<!UI.ToolbarItem>} */
+ /** @type {!Array.<!ToolbarItem>} */
this._items = [];
this.element = parentElement ? parentElement.createChild('div') : createElement('div');
this.element.className = className;
@@ -50,9 +50,9 @@ UI.Toolbar = class {
/**
* @param {!UI.Action} action
- * @param {!Array<!UI.ToolbarButton>} toggledOptions
- * @param {!Array<!UI.ToolbarButton>} untoggledOptions
- * @return {!UI.ToolbarButton}
+ * @param {!Array<!ToolbarButton>} toggledOptions
+ * @param {!Array<!ToolbarButton>} untoggledOptions
+ * @return {!ToolbarButton}
*/
static createLongPressActionButton(action, toggledOptions, untoggledOptions) {
const button = UI.Toolbar.createActionButton(action);
@@ -60,7 +60,7 @@ UI.Toolbar = class {
/** @type {?UI.LongClickController} */
let longClickController = null;
- /** @type {?Array<!UI.ToolbarButton>} */
+ /** @type {?Array<!ToolbarButton>} */
let longClickButtons = null;
/** @type {?Element} */
let longClickGlyph = null;
@@ -108,14 +108,16 @@ UI.Toolbar = class {
const topNotBottom = hostButtonPosition.y + buttonHeight * buttons.length < document.documentElement.offsetHeight;
- if (topNotBottom)
+ if (topNotBottom) {
buttons = buttons.reverse();
+ }
optionsBar.element.style.height = (buttonHeight * buttons.length) + 'px';
- if (topNotBottom)
+ if (topNotBottom) {
optionsBar.element.style.top = (hostButtonPosition.y - 5) + 'px';
- else
+ } else {
optionsBar.element.style.top = (hostButtonPosition.y - (buttonHeight * (buttons.length - 1)) - 6) + 'px';
+ }
optionsBar.element.style.left = (hostButtonPosition.x - 5) + 'px';
for (let i = 0; i < buttons.length; ++i) {
@@ -127,22 +129,25 @@ UI.Toolbar = class {
buttons[hostButtonIndex].element.classList.add('emulate-active');
function mouseOver(e) {
- if (e.which !== 1)
+ if (e.which !== 1) {
return;
+ }
const buttonElement = e.target.enclosingNodeOrSelfWithClass('toolbar-item');
buttonElement.classList.add('emulate-active');
}
function mouseOut(e) {
- if (e.which !== 1)
+ if (e.which !== 1) {
return;
+ }
const buttonElement = e.target.enclosingNodeOrSelfWithClass('toolbar-item');
buttonElement.classList.remove('emulate-active');
}
function mouseUp(e) {
- if (e.which !== 1)
+ if (e.which !== 1) {
return;
+ }
optionsGlassPane.hide();
document.documentElement.removeEventListener('mouseup', mouseUp, false);
@@ -160,34 +165,36 @@ UI.Toolbar = class {
/**
* @param {!UI.Action} action
* @param {boolean=} showLabel
- * @return {!UI.ToolbarButton}
+ * @return {!ToolbarButton}
*/
static createActionButton(action, showLabel) {
const button = action.toggleable() ? makeToggle() : makeButton();
- if (showLabel)
+ if (showLabel) {
button.setText(action.title());
- button.addEventListener(UI.ToolbarButton.Events.Click, action.execute, action);
+ }
+ button.addEventListener(ToolbarButton.Events.Click, action.execute, action);
action.addEventListener(UI.Action.Events.Enabled, enabledChanged);
button.setEnabled(action.enabled());
return button;
/**
- * @return {!UI.ToolbarButton}
+ * @return {!ToolbarButton}
*/
function makeButton() {
- const button = new UI.ToolbarButton(action.title(), action.icon());
- if (action.title())
+ const button = new ToolbarButton(action.title(), action.icon());
+ if (action.title()) {
UI.Tooltip.install(button.element, action.title(), action.id());
+ }
return button;
}
/**
- * @return {!UI.ToolbarToggle}
+ * @return {!ToolbarToggle}
*/
function makeToggle() {
- const toggleButton = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
+ const toggleButton = new ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
toggleButton.setToggleWithRedColor(action.toggleWithRedColor());
action.addEventListener(UI.Action.Events.Toggled, toggled);
toggled();
@@ -195,8 +202,9 @@ UI.Toolbar = class {
function toggled() {
toggleButton.setToggled(action.toggled());
- if (action.title())
+ if (action.title()) {
UI.Tooltip.install(toggleButton.element, action.title(), action.id());
+ }
}
}
@@ -211,7 +219,7 @@ UI.Toolbar = class {
/**
* @param {string} actionId
* @param {boolean=} showLabel
- * @return {!UI.ToolbarButton}
+ * @return {!ToolbarButton}
*/
static createActionButtonForId(actionId, showLabel) {
const action = UI.actionRegistry.action(actionId);
@@ -230,8 +238,9 @@ UI.Toolbar = class {
*/
makeWrappable(growVertically) {
this._contentElement.classList.add('wrappable');
- if (growVertically)
+ if (growVertically) {
this._contentElement.classList.add('toolbar-grow-vertical');
+ }
}
makeVertical() {
@@ -262,40 +271,43 @@ UI.Toolbar = class {
*/
setEnabled(enabled) {
this._enabled = enabled;
- for (const item of this._items)
+ for (const item of this._items) {
item._applyEnabledState(this._enabled && item._enabled);
+ }
}
/**
- * @param {!UI.ToolbarItem} item
+ * @param {!ToolbarItem} item
*/
appendToolbarItem(item) {
this._items.push(item);
item._toolbar = this;
- if (!this._enabled)
+ if (!this._enabled) {
item._applyEnabledState(false);
+ }
this._contentElement.insertBefore(item.element, this._insertionPoint);
this._hideSeparatorDupes();
}
appendSeparator() {
- this.appendToolbarItem(new UI.ToolbarSeparator());
+ this.appendToolbarItem(new ToolbarSeparator());
}
appendSpacer() {
- this.appendToolbarItem(new UI.ToolbarSeparator(true));
+ this.appendToolbarItem(new ToolbarSeparator(true));
}
/**
* @param {string} text
*/
appendText(text) {
- this.appendToolbarItem(new UI.ToolbarText(text));
+ this.appendToolbarItem(new ToolbarText(text));
}
removeToolbarItems() {
- for (const item of this._items)
+ for (const item of this._items) {
delete item._toolbar;
+ }
this._items = [];
this._contentElement.removeChildren();
this._insertionPoint = this._contentElement.createChild('slot');
@@ -321,14 +333,15 @@ UI.Toolbar = class {
}
_hideSeparatorDupes() {
- if (!this._items.length)
+ if (!this._items.length) {
return;
+ }
// Don't hide first and last separators if they were added explicitly.
let previousIsSeparator = false;
let lastSeparator;
let nonSeparatorVisible = false;
for (let i = 0; i < this._items.length; ++i) {
- if (this._items[i] instanceof UI.ToolbarSeparator) {
+ if (this._items[i] instanceof ToolbarSeparator) {
this._items[i].setVisible(!previousIsSeparator);
previousIsSeparator = true;
lastSeparator = this._items[i];
@@ -340,8 +353,9 @@ UI.Toolbar = class {
nonSeparatorVisible = true;
}
}
- if (lastSeparator && lastSeparator !== this._items.peekLast())
+ if (lastSeparator && lastSeparator !== this._items.peekLast()) {
lastSeparator.setVisible(false);
+ }
this.element.classList.toggle('hidden', !!lastSeparator && lastSeparator.visible() && !nonSeparatorVisible);
}
@@ -351,24 +365,26 @@ UI.Toolbar = class {
* @return {!Promise}
*/
async appendItemsAtLocation(location) {
- const extensions = self.runtime.extensions(UI.ToolbarItem.Provider);
+ const extensions = self.runtime.extensions(Provider);
const filtered = extensions.filter(e => e.descriptor()['location'] === location);
const items = await Promise.all(filtered.map(extension => {
const descriptor = extension.descriptor();
- if (descriptor['separator'])
- return new UI.ToolbarSeparator();
- if (descriptor['actionId'])
+ if (descriptor['separator']) {
+ return new ToolbarSeparator();
+ }
+ if (descriptor['actionId']) {
return UI.Toolbar.createActionButtonForId(descriptor['actionId'], descriptor['showLabel']);
+ }
return extension.instance().then(p => p.item());
}));
items.filter(item => item).forEach(item => this.appendToolbarItem(item));
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarItem = class extends Common.Object {
+export class ToolbarItem extends Common.Object {
/**
* @param {!Element} element
*/
@@ -384,8 +400,9 @@ UI.ToolbarItem = class extends Common.Object {
* @param {string} title
*/
setTitle(title) {
- if (this._title === title)
+ if (this._title === title) {
return;
+ }
this._title = title;
UI.ARIAUtils.setAccessibleName(this.element, title);
UI.Tooltip.install(this.element, title);
@@ -395,8 +412,9 @@ UI.ToolbarItem = class extends Common.Object {
* @param {boolean} value
*/
setEnabled(value) {
- if (this._enabled === value)
+ if (this._enabled === value) {
return;
+ }
this._enabled = value;
this._applyEnabledState(this._enabled && (!this._toolbar || this._toolbar._enabled));
}
@@ -419,23 +437,25 @@ UI.ToolbarItem = class extends Common.Object {
* @param {boolean} x
*/
setVisible(x) {
- if (this._visible === x)
+ if (this._visible === x) {
return;
+ }
this.element.classList.toggle('hidden', !x);
this._visible = x;
- if (this._toolbar && !(this instanceof UI.ToolbarSeparator))
+ if (this._toolbar && !(this instanceof ToolbarSeparator)) {
this._toolbar._hideSeparatorDupes();
+ }
}
setRightAligned(alignRight) {
this.element.classList.toggle('toolbar-item-right-aligned', alignRight);
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarText = class extends UI.ToolbarItem {
+export class ToolbarText extends ToolbarItem {
/**
* @param {string=} text
*/
@@ -458,12 +478,12 @@ UI.ToolbarText = class extends UI.ToolbarItem {
setText(text) {
this.element.textContent = text;
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarButton = class extends UI.ToolbarItem {
+export class ToolbarButton extends ToolbarItem {
/**
* @param {string} title
* @param {string=} glyph
@@ -479,8 +499,9 @@ UI.ToolbarButton = class extends UI.ToolbarItem {
this._textElement = this.element.createChild('div', 'toolbar-text hidden');
this.setTitle(title);
- if (glyph)
+ if (glyph) {
this.setGlyph(glyph);
+ }
this.setText(text || '');
this._title = '';
}
@@ -489,8 +510,9 @@ UI.ToolbarButton = class extends UI.ToolbarItem {
* @param {string} text
*/
setText(text) {
- if (this._text === text)
+ if (this._text === text) {
return;
+ }
this._textElement.textContent = text;
this._textElement.classList.toggle('hidden', !text);
this._text = text;
@@ -500,8 +522,9 @@ UI.ToolbarButton = class extends UI.ToolbarItem {
* @param {string} glyph
*/
setGlyph(glyph) {
- if (this._glyph === glyph)
+ if (this._glyph === glyph) {
return;
+ }
this._glyphElement.setIconType(glyph);
this._glyphElement.classList.toggle('hidden', !glyph);
this.element.classList.toggle('toolbar-has-glyph', !!glyph);
@@ -526,17 +549,19 @@ UI.ToolbarButton = class extends UI.ToolbarItem {
this.element.classList.add('toolbar-has-dropdown');
const dropdownArrowIcon = UI.Icon.create('smallicon-triangle-down', 'toolbar-dropdown-arrow');
this.element.appendChild(dropdownArrowIcon);
- if (width)
+ if (width) {
this.element.style.width = width + 'px';
+ }
}
/**
* @param {!Event} event
*/
_clicked(event) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
- this.dispatchEventToListeners(UI.ToolbarButton.Events.Click, event);
+ }
+ this.dispatchEventToListeners(ToolbarButton.Events.Click, event);
event.consume();
}
@@ -544,26 +569,28 @@ UI.ToolbarButton = class extends UI.ToolbarItem {
* @param {!Event} event
*/
_mouseDown(event) {
- if (!this._enabled)
+ if (!this._enabled) {
return;
- this.dispatchEventToListeners(UI.ToolbarButton.Events.MouseDown, event);
+ }
+ this.dispatchEventToListeners(ToolbarButton.Events.MouseDown, event);
}
-};
+}
-UI.ToolbarButton.Events = {
+ToolbarButton.Events = {
Click: Symbol('Click'),
MouseDown: Symbol('MouseDown')
};
-UI.ToolbarInput = class extends UI.ToolbarItem {
+export class ToolbarInput extends ToolbarItem {
/**
* @param {string} placeholder
+ * @param {string=} accessiblePlaceholder
* @param {number=} growFactor
* @param {number=} shrinkFactor
* @param {string=} tooltip
* @param {(function(string, string, boolean=):!Promise<!UI.SuggestBox.Suggestions>)=} completions
*/
- constructor(placeholder, growFactor, shrinkFactor, tooltip, completions) {
+ constructor(placeholder, accessiblePlaceholder, growFactor, shrinkFactor, tooltip, completions) {
super(createElementWithClass('div', 'toolbar-input'));
const internalPromptElement = this.element.createChild('div', 'toolbar-input-prompt');
@@ -575,15 +602,18 @@ UI.ToolbarInput = class extends UI.ToolbarItem {
this._proxyElement.classList.add('toolbar-prompt-proxy');
this._proxyElement.addEventListener('keydown', event => this._onKeydownCallback(event));
this._prompt.initialize(completions || (() => Promise.resolve([])), ' ');
- if (tooltip)
+ if (tooltip) {
this._prompt.setTitle(tooltip);
- this._prompt.setPlaceholder(placeholder);
+ }
+ this._prompt.setPlaceholder(placeholder, accessiblePlaceholder);
this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._onChangeCallback.bind(this));
- if (growFactor)
+ if (growFactor) {
this.element.style.flexGrow = growFactor;
- if (shrinkFactor)
+ }
+ if (shrinkFactor) {
this.element.style.flexShrink = shrinkFactor;
+ }
const clearButton = this.element.createChild('div', 'toolbar-input-clear-button');
clearButton.appendChild(UI.Icon.create('mediumicon-gray-cross-hover', 'search-cancel-button'));
@@ -609,8 +639,9 @@ UI.ToolbarInput = class extends UI.ToolbarItem {
*/
setValue(value, notify) {
this._prompt.setText(value);
- if (notify)
+ if (notify) {
this._onChangeCallback();
+ }
this._updateEmptyStyles();
}
@@ -625,30 +656,31 @@ UI.ToolbarInput = class extends UI.ToolbarItem {
* @param {!Event} event
*/
_onKeydownCallback(event) {
- if (!isEscKey(event) || !this._prompt.text())
+ if (!isEscKey(event) || !this._prompt.text()) {
return;
+ }
this.setValue('', true);
event.consume(true);
}
_onChangeCallback() {
this._updateEmptyStyles();
- this.dispatchEventToListeners(UI.ToolbarInput.Event.TextChanged, this._prompt.text());
+ this.dispatchEventToListeners(ToolbarInput.Event.TextChanged, this._prompt.text());
}
_updateEmptyStyles() {
this.element.classList.toggle('toolbar-input-empty', !this._prompt.text());
}
-};
+}
-UI.ToolbarInput.Event = {
+ToolbarInput.Event = {
TextChanged: Symbol('TextChanged')
};
/**
* @unrestricted
*/
-UI.ToolbarToggle = class extends UI.ToolbarButton {
+export class ToolbarToggle extends ToolbarButton {
/**
* @param {string} title
* @param {string=} glyph
@@ -674,14 +706,16 @@ UI.ToolbarToggle = class extends UI.ToolbarButton {
* @param {boolean} toggled
*/
setToggled(toggled) {
- if (this._toggled === toggled)
+ if (this._toggled === toggled) {
return;
+ }
this._toggled = toggled;
this.element.classList.toggle('toolbar-state-on', toggled);
this.element.classList.toggle('toolbar-state-off', !toggled);
UI.ARIAUtils.setPressed(this.element, toggled);
- if (this._toggledGlyph && this._untoggledGlyph)
+ if (this._toggledGlyph && this._untoggledGlyph) {
this.setGlyph(toggled ? this._toggledGlyph : this._untoggledGlyph);
+ }
}
/**
@@ -697,13 +731,13 @@ UI.ToolbarToggle = class extends UI.ToolbarButton {
setToggleWithRedColor(toggleWithRedColor) {
this.element.classList.toggle('toolbar-toggle-with-red-color', toggleWithRedColor);
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarMenuButton = class extends UI.ToolbarButton {
+export class ToolbarMenuButton extends ToolbarButton {
/**
* @param {function(!UI.ContextMenu)} contextMenuHandler
* @param {boolean=} useSoftMenu
@@ -712,6 +746,7 @@ UI.ToolbarMenuButton = class extends UI.ToolbarButton {
super('', 'largeicon-menu');
this._contextMenuHandler = contextMenuHandler;
this._useSoftMenu = !!useSoftMenu;
+ UI.ARIAUtils.markAsMenuButton(this.element);
}
/**
@@ -724,8 +759,9 @@ UI.ToolbarMenuButton = class extends UI.ToolbarButton {
return;
}
- if (!this._triggerTimeout)
+ if (!this._triggerTimeout) {
this._triggerTimeout = setTimeout(this._trigger.bind(this, event), 200);
+ }
}
/**
@@ -736,8 +772,9 @@ UI.ToolbarMenuButton = class extends UI.ToolbarButton {
// Throttling avoids entering a bad state on Macs when rapidly triggering context menus just
// after the window gains focus. See crbug.com/655556
- if (this._lastTriggerTime && Date.now() - this._lastTriggerTime < 300)
+ if (this._lastTriggerTime && Date.now() - this._lastTriggerTime < 300) {
return;
+ }
const contextMenu = new UI.ContextMenu(
event, this._useSoftMenu, this.element.totalOffsetLeft(),
this.element.totalOffsetTop() + this.element.offsetHeight);
@@ -751,26 +788,25 @@ UI.ToolbarMenuButton = class extends UI.ToolbarButton {
* @param {!Event} event
*/
_clicked(event) {
- if (this._triggerTimeout)
+ if (this._triggerTimeout) {
clearTimeout(this._triggerTimeout);
+ }
this._trigger(event);
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarSettingToggle = class extends UI.ToolbarToggle {
+export class ToolbarSettingToggle extends ToolbarToggle {
/**
* @param {!Common.Setting} setting
* @param {string} glyph
* @param {string} title
- * @param {string=} toggledTitle
*/
- constructor(setting, glyph, title, toggledTitle) {
+ constructor(setting, glyph, title) {
super(title, glyph);
this._defaultTitle = title;
- this._toggledTitle = toggledTitle || title;
this._setting = setting;
this._settingChanged();
this._setting.addChangeListener(this._settingChanged, this);
@@ -779,7 +815,7 @@ UI.ToolbarSettingToggle = class extends UI.ToolbarToggle {
_settingChanged() {
const toggled = this._setting.get();
this.setToggled(toggled);
- this.setTitle(toggled ? this._toggledTitle : this._defaultTitle);
+ this.setTitle(this._defaultTitle);
}
/**
@@ -790,71 +826,63 @@ UI.ToolbarSettingToggle = class extends UI.ToolbarToggle {
this._setting.set(!this.toggled());
super._clicked(event);
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarSeparator = class extends UI.ToolbarItem {
+export class ToolbarSeparator extends ToolbarItem {
/**
* @param {boolean=} spacer
*/
constructor(spacer) {
super(createElementWithClass('div', spacer ? 'toolbar-spacer' : 'toolbar-divider'));
}
-};
+}
/**
* @interface
*/
-UI.ToolbarItem.Provider = function() {};
-
-UI.ToolbarItem.Provider.prototype = {
+export class Provider {
/**
- * @return {?UI.ToolbarItem}
+ * @return {?ToolbarItem}
*/
item() {}
-};
+}
/**
* @interface
*/
-UI.ToolbarItem.ItemsProvider = function() {};
-
-UI.ToolbarItem.ItemsProvider.prototype = {
+export class ItemsProvider {
/**
- * @return {!Array<!UI.ToolbarItem>}
+ * @return {!Array<!ToolbarItem>}
*/
toolbarItems() {}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarComboBox = class extends UI.ToolbarItem {
+export class ToolbarComboBox extends ToolbarItem {
/**
* @param {?function(!Event)} changeHandler
+ * @param {string} title
* @param {string=} className
*/
- constructor(changeHandler, className) {
+ constructor(changeHandler, title, className) {
super(createElementWithClass('span', 'toolbar-select-container'));
this._selectElement = this.element.createChild('select', 'toolbar-item');
const dropdownArrowIcon = UI.Icon.create('smallicon-triangle-down', 'toolbar-dropdown-arrow');
this.element.appendChild(dropdownArrowIcon);
- if (changeHandler)
+ if (changeHandler) {
this._selectElement.addEventListener('change', changeHandler, false);
- if (className)
- this._selectElement.classList.add(className);
- }
-
- /**
- * @override
- * @param {string} title
- */
- setTitle(title) {
+ }
UI.ARIAUtils.setAccessibleName(this._selectElement, title);
super.setTitle(title);
+ if (className) {
+ this._selectElement.classList.add(className);
+ }
}
/**
@@ -887,17 +915,15 @@ UI.ToolbarComboBox = class extends UI.ToolbarItem {
/**
* @param {string} label
- * @param {string=} title
* @param {string=} value
* @return {!Element}
*/
- createOption(label, title, value) {
+ createOption(label, value) {
const option = this._selectElement.createChild('option');
option.text = label;
- if (title)
- option.title = title;
- if (typeof value !== 'undefined')
+ if (typeof value !== 'undefined') {
option.value = value;
+ }
return option;
}
@@ -925,8 +951,9 @@ UI.ToolbarComboBox = class extends UI.ToolbarItem {
* @return {?Element}
*/
selectedOption() {
- if (this._selectElement.selectedIndex >= 0)
+ if (this._selectElement.selectedIndex >= 0) {
return this._selectElement[this._selectElement.selectedIndex];
+ }
return null;
}
@@ -964,45 +991,39 @@ UI.ToolbarComboBox = class extends UI.ToolbarItem {
setMinWidth(width) {
this._selectElement.style.minWidth = width + 'px';
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarSettingComboBox = class extends UI.ToolbarComboBox {
+export class ToolbarSettingComboBox extends ToolbarComboBox {
/**
- * @param {!Array<!{value: string, label: string, title: string}>} options
+ * @param {!Array<!{value: string, label: string}>} options
* @param {!Common.Setting} setting
- * @param {string=} optGroup
+ * @param {string} accessibleName
*/
- constructor(options, setting, optGroup) {
- super(null);
- this._setting = setting;
+ constructor(options, setting, accessibleName) {
+ super(null, accessibleName);
this._options = options;
+ this._setting = setting;
this._selectElement.addEventListener('change', this._valueChanged.bind(this), false);
- if (optGroup) {
- const optGroupElement = this._selectElement.createChild('optgroup');
- optGroupElement.label = optGroup;
- this._optionContainer = optGroupElement;
- } else {
- this._optionContainer = this._selectElement;
- }
this.setOptions(options);
setting.addChangeListener(this._settingChanged, this);
}
/**
- * @param {!Array<!{value: string, label: string, title: string}>} options
+ * @param {!Array<!{value: string, label: string}>} options
*/
setOptions(options) {
this._options = options;
- this._optionContainer.removeChildren();
+ this._selectElement.removeChildren();
for (let i = 0; i < options.length; ++i) {
const dataOption = options[i];
- const option = this.createOption(dataOption.label, dataOption.title, dataOption.value);
- this._optionContainer.appendChild(option);
- if (this._setting.get() === dataOption.value)
+ const option = this.createOption(dataOption.label, dataOption.value);
+ this._selectElement.appendChild(option);
+ if (this._setting.get() === dataOption.value) {
this.setSelectedIndex(i);
+ }
}
}
@@ -1014,8 +1035,9 @@ UI.ToolbarSettingComboBox = class extends UI.ToolbarComboBox {
}
_settingChanged() {
- if (this._muteSettingListener)
+ if (this._muteSettingListener) {
return;
+ }
const value = this._setting.get();
for (let i = 0; i < this._options.length; ++i) {
@@ -1035,12 +1057,12 @@ UI.ToolbarSettingComboBox = class extends UI.ToolbarComboBox {
this._setting.set(option.value);
this._muteSettingListener = false;
}
-};
+}
/**
* @unrestricted
*/
-UI.ToolbarCheckbox = class extends UI.ToolbarItem {
+export class ToolbarCheckbox extends ToolbarItem {
/**
* @param {string} text
* @param {string=} tooltip
@@ -1050,10 +1072,12 @@ UI.ToolbarCheckbox = class extends UI.ToolbarItem {
super(UI.CheckboxLabel.create(text));
this.element.classList.add('checkbox');
this.inputElement = this.element.checkboxElement;
- if (tooltip)
+ if (tooltip) {
this.element.title = tooltip;
- if (listener)
+ }
+ if (listener) {
this.inputElement.addEventListener('click', listener, false);
+ }
}
/**
@@ -1078,9 +1102,9 @@ UI.ToolbarCheckbox = class extends UI.ToolbarItem {
super._applyEnabledState(enabled);
this.inputElement.disabled = !enabled;
}
-};
+}
-UI.ToolbarSettingCheckbox = class extends UI.ToolbarCheckbox {
+export class ToolbarSettingCheckbox extends ToolbarCheckbox {
/**
* @param {!Common.Setting} setting
* @param {string=} tooltip
@@ -1090,4 +1114,55 @@ UI.ToolbarSettingCheckbox = class extends UI.ToolbarCheckbox {
super(alternateTitle || setting.title() || '', tooltip);
UI.SettingsUI.bindCheckbox(this.inputElement, setting);
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Toolbar = Toolbar;
+
+/** @constructor */
+UI.ToolbarItem = ToolbarItem;
+
+/** @constructor */
+UI.ToolbarText = ToolbarText;
+
+/** @constructor */
+UI.ToolbarButton = ToolbarButton;
+
+/** @constructor */
+UI.ToolbarInput = ToolbarInput;
+
+/** @constructor */
+UI.ToolbarToggle = ToolbarToggle;
+
+/** @constructor */
+UI.ToolbarMenuButton = ToolbarMenuButton;
+
+/** @constructor */
+UI.ToolbarSettingToggle = ToolbarSettingToggle;
+
+/** @constructor */
+UI.ToolbarSeparator = ToolbarSeparator;
+
+/** @interface */
+UI.ToolbarItem.Provider = Provider;
+
+/** @interface */
+UI.ToolbarItem.ItemsProvider = ItemsProvider;
+
+/** @constructor */
+UI.ToolbarComboBox = ToolbarComboBox;
+
+/** @constructor */
+UI.ToolbarSettingComboBox = ToolbarSettingComboBox;
+
+/** @constructor */
+UI.ToolbarCheckbox = ToolbarCheckbox;
+
+/** @constructor */
+UI.ToolbarSettingCheckbox = ToolbarSettingCheckbox; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
index 765893a4e2b..e7ada8e3884 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.Tooltip = class {
+export default class Tooltip {
/**
* @param {!Document} doc
*/
@@ -25,7 +25,7 @@ UI.Tooltip = class {
* @param {!Document} doc
*/
static installHandler(doc) {
- new UI.Tooltip(doc);
+ new Tooltip(doc);
}
/**
@@ -36,17 +36,17 @@ UI.Tooltip = class {
*/
static install(element, tooltipContent, actionId, options) {
if (!tooltipContent) {
- delete element[UI.Tooltip._symbol];
+ delete element[_symbol];
return;
}
- element[UI.Tooltip._symbol] = {content: tooltipContent, actionId: actionId, options: options || {}};
+ element[_symbol] = {content: tooltipContent, actionId: actionId, options: options || {}};
}
/**
* @param {!Element} element
*/
static addNativeOverrideContainer(element) {
- UI.Tooltip._nativeOverrideContainer.push(element);
+ _nativeOverrideContainer.push(element);
}
/**
@@ -55,19 +55,23 @@ UI.Tooltip = class {
_mouseMove(event) {
const mouseEvent = /** @type {!MouseEvent} */ (event);
const path = mouseEvent.composedPath();
- if (!path || mouseEvent.buttons !== 0 || (mouseEvent.movementX === 0 && mouseEvent.movementY === 0))
+ if (!path || mouseEvent.buttons !== 0 || (mouseEvent.movementX === 0 && mouseEvent.movementY === 0)) {
return;
+ }
- if (this._anchorElement && path.indexOf(this._anchorElement) === -1)
+ if (this._anchorElement && path.indexOf(this._anchorElement) === -1) {
this._hide(false);
+ }
for (const element of path) {
- if (element === this._anchorElement)
+ if (element === this._anchorElement) {
return;
+ }
// The offsetParent is null when the element or an ancestor has 'display: none'.
- if (!(element instanceof Element) || element.offsetParent === null)
+ if (!(element instanceof Element) || element.offsetParent === null) {
continue;
- if (element[UI.Tooltip._symbol]) {
+ }
+ if (element[_symbol]) {
this._show(element, mouseEvent);
return;
}
@@ -79,23 +83,24 @@ UI.Tooltip = class {
* @param {!Event} event
*/
_show(anchorElement, event) {
- const tooltip = anchorElement[UI.Tooltip._symbol];
+ const tooltip = anchorElement[_symbol];
this._anchorElement = anchorElement;
this._tooltipElement.removeChildren();
// Check if native tooltips should be used.
- for (const element of UI.Tooltip._nativeOverrideContainer) {
+ for (const element of _nativeOverrideContainer) {
if (this._anchorElement.isSelfOrDescendant(element)) {
- Object.defineProperty(this._anchorElement, 'title', UI.Tooltip._nativeTitle);
+ Object.defineProperty(this._anchorElement, 'title', /** @type {!Object} */ (_nativeTitle));
this._anchorElement.title = tooltip.content;
return;
}
}
- if (typeof tooltip.content === 'string')
+ if (typeof tooltip.content === 'string') {
this._tooltipElement.setTextContentTruncatedIfNeeded(tooltip.content);
- else
+ } else {
this._tooltipElement.appendChild(tooltip.content);
+ }
if (tooltip.actionId) {
const shortcuts = UI.shortcutRegistry.shortcutDescriptorsForAction(tooltip.actionId);
@@ -111,9 +116,9 @@ UI.Tooltip = class {
// Show tooltip instantly if a tooltip was shown recently.
const now = Date.now();
- const instant = (this._tooltipLastClosed && now - this._tooltipLastClosed < UI.Tooltip.Timing.InstantThreshold);
+ const instant = (this._tooltipLastClosed && now - this._tooltipLastClosed < Timing.InstantThreshold);
this._tooltipElement.classList.toggle('instant', instant);
- this._tooltipLastOpened = instant ? now : now + UI.Tooltip.Timing.OpeningDelay;
+ this._tooltipLastOpened = instant ? now : now + Timing.OpeningDelay;
// Get container element.
const container = UI.GlassPane.container(/** @type {!Document} */ (anchorElement.ownerDocument));
@@ -152,10 +157,12 @@ UI.Tooltip = class {
_hide(removeInstant) {
delete this._anchorElement;
this._tooltipElement.classList.remove('shown');
- if (Date.now() > this._tooltipLastOpened)
+ if (Date.now() > this._tooltipLastOpened) {
this._tooltipLastClosed = Date.now();
- if (removeInstant)
+ }
+ if (removeInstant) {
delete this._tooltipLastClosed;
+ }
}
_reset() {
@@ -164,22 +171,21 @@ UI.Tooltip = class {
this._tooltipElement.style.maxWidth = '0';
this._tooltipElement.style.maxHeight = '0';
}
-};
+}
-UI.Tooltip.Timing = {
+export const Timing = {
// Max time between tooltips showing that no opening delay is required.
'InstantThreshold': 300,
// Wait time before opening a tooltip.
'OpeningDelay': 600
};
-UI.Tooltip._symbol = Symbol('Tooltip');
-
+export const _symbol = Symbol('Tooltip');
/** @type {!Array.<!Element>} */
-UI.Tooltip._nativeOverrideContainer = [];
-UI.Tooltip._nativeTitle =
- /** @type {!ObjectPropertyDescriptor} */ (Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'title'));
+export const _nativeOverrideContainer = [];
+
+export const _nativeTitle = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'title');
Object.defineProperty(HTMLElement.prototype, 'title', {
/**
@@ -187,7 +193,7 @@ Object.defineProperty(HTMLElement.prototype, 'title', {
* @this {!Element}
*/
get: function() {
- const tooltip = this[UI.Tooltip._symbol];
+ const tooltip = this[_symbol];
return tooltip ? tooltip.content : '';
},
@@ -196,6 +202,23 @@ Object.defineProperty(HTMLElement.prototype, 'title', {
* @this {!Element}
*/
set: function(x) {
- UI.Tooltip.install(this, x);
+ Tooltip.install(this, x);
}
});
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Tooltip = Tooltip;
+
+UI.Tooltip.Timing = Timing;
+UI.Tooltip._symbol = _symbol;
+
+/** @type {!Array.<!Element>} */
+UI.Tooltip._nativeOverrideContainer = _nativeOverrideContainer;
+
+UI.Tooltip._nativeTitle = _nativeTitle;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Treeoutline.js
index ea294c50701..32bfecdd234 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Treeoutline.js
@@ -29,15 +29,15 @@
/**
* @unrestricted
*/
-UI.TreeOutline = class extends Common.Object {
+export class TreeOutline extends Common.Object {
constructor() {
super();
this._createRootElement();
- /** @type {?UI.TreeElement} */
+ /** @type {?TreeElement} */
this.selectedTreeElement = null;
this.expandTreeElementsWhenArrowing = false;
- /** @type {?function(!UI.TreeElement, !UI.TreeElement):number} */
+ /** @type {?function(!TreeElement, !TreeElement):number} */
this._comparator = null;
this.contentElement = this._rootElement._childrenListNode;
@@ -47,8 +47,9 @@ UI.TreeOutline = class extends Common.Object {
this._showSelectionOnKeyboardFocus = false;
this._focusable = true;
this.setFocusable(this._focusable);
- if (this._focusable)
+ if (this._focusable) {
this.contentElement.setAttribute('tabIndex', -1);
+ }
this.element = this.contentElement;
UI.ARIAUtils.markAsTree(this.element);
}
@@ -64,7 +65,7 @@ UI.TreeOutline = class extends Common.Object {
}
_createRootElement() {
- this._rootElement = new UI.TreeElement();
+ this._rootElement = new TreeElement();
this._rootElement.treeOutline = this;
this._rootElement.root = true;
this._rootElement.selectable = false;
@@ -73,38 +74,39 @@ UI.TreeOutline = class extends Common.Object {
}
/**
- * @return {!UI.TreeElement}
+ * @return {!TreeElement}
*/
rootElement() {
return this._rootElement;
}
/**
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
firstChild() {
return this._rootElement.firstChild();
}
/**
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
_lastDescendent() {
let last = this._rootElement.lastChild();
- while (last.expanded && last.childCount())
+ while (last.expanded && last.childCount()) {
last = last.lastChild();
+ }
return last;
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
*/
appendChild(child) {
this._rootElement.appendChild(child);
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
* @param {number} index
*/
insertChild(child, index) {
@@ -112,7 +114,7 @@ UI.TreeOutline = class extends Common.Object {
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
*/
removeChild(child) {
this._rootElement.removeChild(child);
@@ -125,29 +127,31 @@ UI.TreeOutline = class extends Common.Object {
/**
* @param {number} x
* @param {number} y
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
treeElementFromPoint(x, y) {
const node = this.contentElement.ownerDocument.deepElementFromPoint(x, y);
- if (!node)
+ if (!node) {
return null;
+ }
const listNode = node.enclosingNodeOrSelfWithNodeNameInArray(['ol', 'li']);
- if (listNode)
+ if (listNode) {
return listNode.parentTreeElement || listNode.treeElement;
+ }
return null;
}
/**
* @param {?Event} event
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
treeElementFromEvent(event) {
return event ? this.treeElementFromPoint(event.pageX, event.pageY) : null;
}
/**
- * @param {?function(!UI.TreeElement, !UI.TreeElement):number} comparator
+ * @param {?function(!TreeElement, !TreeElement):number} comparator
*/
setComparator(comparator) {
this._comparator = comparator;
@@ -160,21 +164,24 @@ UI.TreeOutline = class extends Common.Object {
if (focusable) {
this._focusable = true;
this.contentElement.setAttribute('tabIndex', -1);
- if (this.selectedTreeElement)
+ if (this.selectedTreeElement) {
this.selectedTreeElement._setFocusable(true);
+ }
} else {
this._focusable = false;
this.contentElement.removeAttribute('tabIndex');
- if (this.selectedTreeElement)
+ if (this.selectedTreeElement) {
this.selectedTreeElement._setFocusable(false);
+ }
}
}
focus() {
- if (this.selectedTreeElement)
+ if (this.selectedTreeElement) {
this.selectedTreeElement.listItemElement.focus();
- else
+ } else {
this.contentElement.focus();
+ }
}
useLightSelectionColor() {
@@ -182,21 +189,23 @@ UI.TreeOutline = class extends Common.Object {
}
/**
- * @param {!UI.TreeElement} element
+ * @param {!TreeElement} element
*/
_bindTreeElement(element) {
- if (element.treeOutline)
+ if (element.treeOutline) {
console.error('Binding element for the second time: ' + new Error().stack);
+ }
element.treeOutline = this;
element.onbind();
}
/**
- * @param {!UI.TreeElement} element
+ * @param {!TreeElement} element
*/
_unbindTreeElement(element) {
- if (!element.treeOutline)
+ if (!element.treeOutline) {
console.error('Unbinding element that was not bound: ' + new Error().stack);
+ }
element.deselect();
element.onunbind();
@@ -208,10 +217,12 @@ UI.TreeOutline = class extends Common.Object {
*/
selectPrevious() {
let nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
- while (nextSelectedElement && !nextSelectedElement.selectable)
+ while (nextSelectedElement && !nextSelectedElement.selectable) {
nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
- if (!nextSelectedElement)
+ }
+ if (!nextSelectedElement) {
return false;
+ }
nextSelectedElement.select(false, true);
return true;
}
@@ -221,17 +232,20 @@ UI.TreeOutline = class extends Common.Object {
*/
selectNext() {
let nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
- while (nextSelectedElement && !nextSelectedElement.selectable)
+ while (nextSelectedElement && !nextSelectedElement.selectable) {
nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
- if (!nextSelectedElement)
+ }
+ if (!nextSelectedElement) {
return false;
+ }
nextSelectedElement.select(false, true);
return true;
}
forceSelect() {
- if (this.selectedTreeElement)
+ if (this.selectedTreeElement) {
this.selectedTreeElement.deselect();
+ }
this._selectFirst();
}
@@ -240,10 +254,12 @@ UI.TreeOutline = class extends Common.Object {
*/
_selectFirst() {
let first = this.firstChild();
- while (first && !first.selectable)
+ while (first && !first.selectable) {
first = first.traverseNextTreeElement(true);
- if (!first)
+ }
+ if (!first) {
return false;
+ }
first.select(false, true);
return true;
}
@@ -253,10 +269,12 @@ UI.TreeOutline = class extends Common.Object {
*/
_selectLast() {
let last = this._lastDescendent();
- while (last && !last.selectable)
+ while (last && !last.selectable) {
last = last.traversePreviousTreeElement(true);
- if (!last)
+ }
+ if (!last) {
return false;
+ }
last.select(false, true);
return true;
}
@@ -265,8 +283,9 @@ UI.TreeOutline = class extends Common.Object {
* @param {!Event} event
*/
_treeKeyDown(event) {
- if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey || UI.isEditing())
+ if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey || UI.isEditing()) {
return;
+ }
let handled = false;
if (event.key === 'ArrowUp' && !event.altKey) {
@@ -294,21 +313,23 @@ UI.TreeOutline = class extends Common.Object {
handled = this._selectLast();
}
- if (handled)
+ if (handled) {
event.consume(true);
+ }
}
/**
- * @param {!UI.TreeElement} treeElement
+ * @param {!TreeElement} treeElement
* @param {boolean} center
*/
_deferredScrollIntoView(treeElement, center) {
- if (!this._treeElementToScrollIntoView)
+ if (!this._treeElementToScrollIntoView) {
this.element.window().requestAnimationFrame(deferredScrollIntoView.bind(this));
+ }
this._treeElementToScrollIntoView = treeElement;
this._centerUponScrollIntoView = center;
/**
- * @this {UI.TreeOutline}
+ * @this {TreeOutline}
*/
function deferredScrollIntoView() {
this._treeElementToScrollIntoView.listItemElement.scrollIntoViewIfNeeded(this._centerUponScrollIntoView);
@@ -316,10 +337,10 @@ UI.TreeOutline = class extends Common.Object {
delete this._centerUponScrollIntoView;
}
}
-};
+}
/** @enum {symbol} */
-UI.TreeOutline.Events = {
+const Events = {
ElementAttached: Symbol('ElementAttached'),
ElementsDetached: Symbol('ElementsDetached'),
ElementExpanded: Symbol('ElementExpanded'),
@@ -330,7 +351,7 @@ UI.TreeOutline.Events = {
/**
* @unrestricted
*/
-UI.TreeOutlineInShadow = class extends UI.TreeOutline {
+export class TreeOutlineInShadow extends TreeOutline {
constructor() {
super();
this.contentElement.classList.add('tree-outline');
@@ -357,18 +378,18 @@ UI.TreeOutlineInShadow = class extends UI.TreeOutline {
makeDense() {
this.contentElement.classList.add('tree-outline-dense');
}
-};
+}
/**
* @unrestricted
*/
-UI.TreeElement = class {
+export class TreeElement {
/**
* @param {(string|!Node)=} title
* @param {boolean=} expandable
*/
constructor(title, expandable) {
- /** @type {?UI.TreeOutline} */
+ /** @type {?TreeOutline} */
this.treeOutline = null;
this.parent = null;
this.previousSibling = null;
@@ -377,10 +398,12 @@ UI.TreeElement = class {
this._boundOnBlur = this._onBlur.bind(this);
this._listItemNode = createElement('li');
- this._titleElement = this._listItemNode.createChild('span', 'tree-element-title');
+ /** @protected */
+ this.titleElement = this._listItemNode.createChild('span', 'tree-element-title');
this._listItemNode.treeElement = this;
- if (title)
+ if (title) {
this.title = title;
+ }
this._listItemNode.addEventListener('mousedown', this._handleMouseDown.bind(this), false);
this._listItemNode.addEventListener('click', this._treeElementToggled.bind(this), false);
this._listItemNode.addEventListener('dblclick', this._handleDoubleClick.bind(this), false);
@@ -400,17 +423,19 @@ UI.TreeElement = class {
}
/**
- * @param {?UI.TreeElement} ancestor
+ * @param {?TreeElement} ancestor
* @return {boolean}
*/
hasAncestor(ancestor) {
- if (!ancestor)
+ if (!ancestor) {
return false;
+ }
let currentNode = this.parent;
while (currentNode) {
- if (ancestor === currentNode)
+ if (ancestor === currentNode) {
return true;
+ }
currentNode = currentNode.parent;
}
@@ -418,7 +443,7 @@ UI.TreeElement = class {
}
/**
- * @param {?UI.TreeElement} ancestor
+ * @param {?TreeElement} ancestor
* @return {boolean}
*/
hasAncestorOrSelf(ancestor) {
@@ -426,7 +451,7 @@ UI.TreeElement = class {
}
/**
- * @return {!Array.<!UI.TreeElement>}
+ * @return {!Array.<!TreeElement>}
*/
children() {
return this._children || [];
@@ -440,14 +465,14 @@ UI.TreeElement = class {
}
/**
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
firstChild() {
return this._children ? this._children[0] : null;
}
/**
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
lastChild() {
return this._children ? this._children[this._children.length - 1] : null;
@@ -455,14 +480,14 @@ UI.TreeElement = class {
/**
* @param {number} index
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
childAt(index) {
return this._children ? this._children[index] : null;
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
* @return {number}
*/
indexOfChild(child) {
@@ -470,30 +495,34 @@ UI.TreeElement = class {
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
*/
appendChild(child) {
- if (!this._children)
+ if (!this._children) {
this._children = [];
+ }
let insertionIndex;
- if (this.treeOutline && this.treeOutline._comparator)
+ if (this.treeOutline && this.treeOutline._comparator) {
insertionIndex = this._children.lowerBound(child, this.treeOutline._comparator);
- else
+ } else {
insertionIndex = this._children.length;
+ }
this.insertChild(child, insertionIndex);
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
* @param {number} index
*/
insertChild(child, index) {
- if (!this._children)
+ if (!this._children) {
this._children = [];
+ }
- if (!child)
+ if (!child) {
throw 'child can\'t be undefined or null';
+ }
console.assert(
!child.parent, 'Attempting to insert a child that is already in the tree, reparenting is not supported.');
@@ -519,30 +548,36 @@ UI.TreeElement = class {
this.setExpandable(true);
child.parent = this;
- if (this.treeOutline)
+ if (this.treeOutline) {
this.treeOutline._bindTreeElement(child);
+ }
for (let current = child.firstChild(); this.treeOutline && current;
- current = current.traverseNextTreeElement(false, child, true))
+ current = current.traverseNextTreeElement(false, child, true)) {
this.treeOutline._bindTreeElement(current);
+ }
child.onattach();
child._ensureSelection();
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementAttached, child);
+ if (this.treeOutline) {
+ this.treeOutline.dispatchEventToListeners(Events.ElementAttached, child);
+ }
const nextSibling = child.nextSibling ? child.nextSibling._listItemNode : null;
this._childrenListNode.insertBefore(child._listItemNode, nextSibling);
this._childrenListNode.insertBefore(child._childrenListNode, nextSibling);
- if (child.selected)
+ if (child.selected) {
child.select();
- if (child.expanded)
+ }
+ if (child.expanded) {
child.expand();
+ }
}
/**
* @param {number} childIndex
*/
removeChildAtIndex(childIndex) {
- if (childIndex < 0 || childIndex >= this._children.length)
+ if (childIndex < 0 || childIndex >= this._children.length) {
throw 'childIndex out of range';
+ }
const child = this._children[childIndex];
this._children.splice(childIndex, 1);
@@ -550,51 +585,61 @@ UI.TreeElement = class {
const parent = child.parent;
if (this.treeOutline && this.treeOutline.selectedTreeElement &&
this.treeOutline.selectedTreeElement.hasAncestorOrSelf(child)) {
- if (child.nextSibling)
+ if (child.nextSibling) {
child.nextSibling.select(true);
- else if (child.previousSibling)
+ } else if (child.previousSibling) {
child.previousSibling.select(true);
- else if (parent)
+ } else if (parent) {
parent.select(true);
+ }
}
- if (child.previousSibling)
+ if (child.previousSibling) {
child.previousSibling.nextSibling = child.nextSibling;
- if (child.nextSibling)
+ }
+ if (child.nextSibling) {
child.nextSibling.previousSibling = child.previousSibling;
+ }
child.parent = null;
- if (this.treeOutline)
+ if (this.treeOutline) {
this.treeOutline._unbindTreeElement(child);
+ }
for (let current = child.firstChild(); this.treeOutline && current;
- current = current.traverseNextTreeElement(false, child, true))
+ current = current.traverseNextTreeElement(false, child, true)) {
this.treeOutline._unbindTreeElement(current);
+ }
child._detach();
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementsDetached);
+ if (this.treeOutline) {
+ this.treeOutline.dispatchEventToListeners(Events.ElementsDetached);
+ }
}
/**
- * @param {!UI.TreeElement} child
+ * @param {!TreeElement} child
*/
removeChild(child) {
- if (!child)
+ if (!child) {
throw 'child can\'t be undefined or null';
- if (child.parent !== this)
+ }
+ if (child.parent !== this) {
return;
+ }
const childIndex = this._children.indexOf(child);
- if (childIndex === -1)
+ if (childIndex === -1) {
throw 'child not found in this node\'s children';
+ }
this.removeChildAtIndex(childIndex);
}
removeChildren() {
if (!this.root && this.treeOutline && this.treeOutline.selectedTreeElement &&
- this.treeOutline.selectedTreeElement.hasAncestorOrSelf(this))
+ this.treeOutline.selectedTreeElement.hasAncestorOrSelf(this)) {
this.select(true);
+ }
for (let i = 0; this._children && i < this._children.length; ++i) {
const child = this._children[i];
@@ -602,21 +647,25 @@ UI.TreeElement = class {
child.nextSibling = null;
child.parent = null;
- if (this.treeOutline)
+ if (this.treeOutline) {
this.treeOutline._unbindTreeElement(child);
+ }
for (let current = child.firstChild(); this.treeOutline && current;
- current = current.traverseNextTreeElement(false, child, true))
+ current = current.traverseNextTreeElement(false, child, true)) {
this.treeOutline._unbindTreeElement(current);
+ }
child._detach();
}
this._children = [];
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementsDetached);
+ if (this.treeOutline) {
+ this.treeOutline.dispatchEventToListeners(Events.ElementsDetached);
+ }
}
get selectable() {
- if (this._hidden)
+ if (this._hidden) {
return false;
+ }
return this._selectable;
}
@@ -628,13 +677,6 @@ UI.TreeElement = class {
return this._listItemNode;
}
- /**
- * @return {!Element}
- */
- titleElement() {
- return this._titleElement;
- }
-
get childrenListElement() {
return this._childrenListNode;
}
@@ -650,24 +692,27 @@ UI.TreeElement = class {
* @param {string|!Node} x
*/
set title(x) {
- if (this._title === x)
+ if (this._title === x) {
return;
+ }
this._title = x;
if (typeof x === 'string') {
- this._titleElement.textContent = x;
+ this.titleElement.textContent = x;
this.tooltip = x;
} else {
- this._titleElement = x;
+ this.titleElement = x;
this.tooltip = '';
}
this._listItemNode.removeChildren();
- if (this._leadingIconsElement)
+ if (this._leadingIconsElement) {
this._listItemNode.appendChild(this._leadingIconsElement);
- this._listItemNode.appendChild(this._titleElement);
- if (this._trailingIconsElement)
+ }
+ this._listItemNode.appendChild(this.titleElement);
+ if (this._trailingIconsElement) {
this._listItemNode.appendChild(this._trailingIconsElement);
+ }
this._ensureSelection();
}
@@ -675,10 +720,12 @@ UI.TreeElement = class {
* @return {string}
*/
titleAsText() {
- if (!this._title)
+ if (!this._title) {
return '';
- if (typeof this._title === 'string')
+ }
+ if (typeof this._title === 'string') {
return this._title;
+ }
return this._title.textContent;
}
@@ -686,33 +733,36 @@ UI.TreeElement = class {
* @param {!UI.InplaceEditor.Config} editingConfig
*/
startEditingTitle(editingConfig) {
- UI.InplaceEditor.startEditing(this._titleElement, editingConfig);
- this.treeOutline._shadowRoot.getSelection().selectAllChildren(this._titleElement);
+ UI.InplaceEditor.startEditing(/** @type {!Element} */ (this.titleElement), editingConfig);
+ this.treeOutline._shadowRoot.getSelection().selectAllChildren(this.titleElement);
}
/**
* @param {!Array<!UI.Icon>} icons
*/
setLeadingIcons(icons) {
- if (!this._leadingIconsElement && !icons.length)
+ if (!this._leadingIconsElement && !icons.length) {
return;
+ }
if (!this._leadingIconsElement) {
this._leadingIconsElement = createElementWithClass('div', 'leading-icons');
this._leadingIconsElement.classList.add('icons-container');
- this._listItemNode.insertBefore(this._leadingIconsElement, this._titleElement);
+ this._listItemNode.insertBefore(this._leadingIconsElement, this.titleElement);
this._ensureSelection();
}
this._leadingIconsElement.removeChildren();
- for (const icon of icons)
+ for (const icon of icons) {
this._leadingIconsElement.appendChild(icon);
+ }
}
/**
* @param {!Array<!UI.Icon>} icons
*/
setTrailingIcons(icons) {
- if (!this._trailingIconsElement && !icons.length)
+ if (!this._trailingIconsElement && !icons.length) {
return;
+ }
if (!this._trailingIconsElement) {
this._trailingIconsElement = createElementWithClass('div', 'trailing-icons');
this._trailingIconsElement.classList.add('icons-container');
@@ -720,8 +770,9 @@ UI.TreeElement = class {
this._ensureSelection();
}
this._trailingIconsElement.removeChildren();
- for (const icon of icons)
+ for (const icon of icons) {
this._trailingIconsElement.appendChild(icon);
+ }
}
@@ -736,8 +787,9 @@ UI.TreeElement = class {
* @param {string} x
*/
set tooltip(x) {
- if (this._tooltip === x)
+ if (this._tooltip === x) {
return;
+ }
this._tooltip = x;
this._listItemNode.title = x;
}
@@ -753,8 +805,9 @@ UI.TreeElement = class {
* @param {boolean} expandable
*/
setExpandable(expandable) {
- if (this._expandable === expandable)
+ if (this._expandable === expandable) {
return;
+ }
this._expandable = expandable;
@@ -771,14 +824,16 @@ UI.TreeElement = class {
* @param {boolean} collapsible
*/
setCollapsible(collapsible) {
- if (this._collapsible === collapsible)
+ if (this._collapsible === collapsible) {
return;
+ }
this._collapsible = collapsible;
this._listItemNode.classList.toggle('always-parent', !collapsible);
- if (!collapsible)
+ if (!collapsible) {
this.expand();
+ }
}
get hidden() {
@@ -786,8 +841,9 @@ UI.TreeElement = class {
}
set hidden(x) {
- if (this._hidden === x)
+ if (this._hidden === x) {
return;
+ }
this._hidden = x;
@@ -804,10 +860,12 @@ UI.TreeElement = class {
_ensureSelection() {
- if (!this.treeOutline || !this.treeOutline._renderSelection)
+ if (!this.treeOutline || !this.treeOutline._renderSelection) {
return;
- if (!this._selectionElement)
+ }
+ if (!this._selectionElement) {
this._selectionElement = createElementWithClass('div', 'selection fill');
+ }
this._listItemNode.insertBefore(this._selectionElement, this.listItemElement.firstChild);
}
@@ -816,26 +874,30 @@ UI.TreeElement = class {
*/
_treeElementToggled(event) {
const element = event.currentTarget;
- if (element.treeElement !== this || element.hasSelection())
+ if (element.treeElement !== this || element.hasSelection()) {
return;
+ }
console.assert(!!this.treeOutline);
const showSelectionOnKeyboardFocus = this.treeOutline ? this.treeOutline._showSelectionOnKeyboardFocus : false;
const toggleOnClick = this.toggleOnClick && (showSelectionOnKeyboardFocus || !this.selectable);
const isInTriangle = this.isEventWithinDisclosureTriangle(event);
- if (!toggleOnClick && !isInTriangle)
+ if (!toggleOnClick && !isInTriangle) {
return;
+ }
if (this.expanded) {
- if (event.altKey)
+ if (event.altKey) {
this.collapseRecursively();
- else
+ } else {
this.collapse();
+ }
} else {
- if (event.altKey)
+ if (event.altKey) {
this.expandRecursively();
- else
+ } else {
this.expand();
+ }
}
event.consume();
}
@@ -845,15 +907,19 @@ UI.TreeElement = class {
*/
_handleMouseDown(event) {
const element = event.currentTarget;
- if (!element)
+ if (!element) {
return;
- if (!this.selectable)
+ }
+ if (!this.selectable) {
return;
- if (element.treeElement !== this)
+ }
+ if (element.treeElement !== this) {
return;
+ }
- if (this.isEventWithinDisclosureTriangle(event))
+ if (this.isEventWithinDisclosureTriangle(event)) {
return;
+ }
this.selectOnMouseDown(event);
}
@@ -863,14 +929,17 @@ UI.TreeElement = class {
*/
_handleDoubleClick(event) {
const element = event.currentTarget;
- if (!element || element.treeElement !== this)
+ if (!element || element.treeElement !== this) {
return;
+ }
const handled = this.ondblclick(event);
- if (handled)
+ if (handled) {
return;
- if (this._expandable && !this.expanded)
+ }
+ if (this._expandable && !this.expanded) {
this.expand();
+ }
}
_detach() {
@@ -879,36 +948,42 @@ UI.TreeElement = class {
}
collapse() {
- if (!this.expanded || !this._collapsible)
+ if (!this.expanded || !this._collapsible) {
return;
+ }
this._listItemNode.classList.remove('expanded');
this._childrenListNode.classList.remove('expanded');
UI.ARIAUtils.setExpanded(this._listItemNode, false);
this.expanded = false;
this.oncollapse();
- if (this.treeOutline)
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementCollapsed, this);
+ if (this.treeOutline) {
+ this.treeOutline.dispatchEventToListeners(Events.ElementCollapsed, this);
+ }
}
collapseRecursively() {
let item = this;
while (item) {
- if (item.expanded)
+ if (item.expanded) {
item.collapse();
+ }
item = item.traverseNextTreeElement(false, this, true);
}
}
collapseChildren() {
- if (!this._children)
+ if (!this._children) {
return;
- for (const child of this._children)
+ }
+ for (const child of this._children) {
child.collapseRecursively();
+ }
}
expand() {
- if (!this._expandable || (this.expanded && this._children))
+ if (!this._expandable || (this.expanded && this._children)) {
return;
+ }
// Set this before onpopulate. Since onpopulate can add elements, this makes
// sure the expanded flag is true before calling those functions. This prevents the possibility
@@ -923,7 +998,7 @@ UI.TreeElement = class {
if (this.treeOutline) {
this.onexpand();
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementExpanded, this);
+ this.treeOutline.dispatchEventToListeners(Events.ElementExpanded, this);
}
}
@@ -939,14 +1014,16 @@ UI.TreeElement = class {
// The Inspector uses TreeOutlines to represents object properties, so recursive expansion
// in some case can be infinite, since JavaScript objects can hold circular references.
// So default to a recursion cap of 3 levels, since that gives fairly good results.
- if (isNaN(maxDepth))
+ if (isNaN(maxDepth)) {
maxDepth = 3;
+ }
while (item) {
await item._populateIfNeeded();
- if (depth < maxDepth)
+ if (depth < maxDepth) {
item.expand();
+ }
item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
depth += info.depthChange;
@@ -959,15 +1036,17 @@ UI.TreeElement = class {
*/
collapseOrAscend(altKey) {
if (this.expanded && this._collapsible) {
- if (altKey)
+ if (altKey) {
this.collapseRecursively();
- else
+ } else {
this.collapse();
+ }
return true;
}
- if (!this.parent || this.parent.root)
+ if (!this.parent || this.parent.root) {
return false;
+ }
if (!this.parent.selectable) {
this.parent.collapse();
@@ -975,11 +1054,13 @@ UI.TreeElement = class {
}
let nextSelectedElement = this.parent;
- while (nextSelectedElement && !nextSelectedElement.selectable)
+ while (nextSelectedElement && !nextSelectedElement.selectable) {
nextSelectedElement = nextSelectedElement.parent;
+ }
- if (!nextSelectedElement)
+ if (!nextSelectedElement) {
return false;
+ }
nextSelectedElement.select(false, true);
return true;
}
@@ -989,23 +1070,27 @@ UI.TreeElement = class {
* @return {boolean}
*/
descendOrExpand(altKey) {
- if (!this._expandable)
+ if (!this._expandable) {
return false;
+ }
if (!this.expanded) {
- if (altKey)
+ if (altKey) {
this.expandRecursively();
- else
+ } else {
this.expand();
+ }
return true;
}
let nextSelectedElement = this.firstChild();
- while (nextSelectedElement && !nextSelectedElement.selectable)
+ while (nextSelectedElement && !nextSelectedElement.selectable) {
nextSelectedElement = nextSelectedElement.nextSibling;
+ }
- if (!nextSelectedElement)
+ if (!nextSelectedElement) {
return false;
+ }
nextSelectedElement.select(false, true);
return true;
}
@@ -1016,8 +1101,9 @@ UI.TreeElement = class {
reveal(center) {
let currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded)
+ if (!currentAncestor.expanded) {
currentAncestor.expand();
+ }
currentAncestor = currentAncestor.parent;
}
@@ -1030,8 +1116,9 @@ UI.TreeElement = class {
revealed() {
let currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
- if (!currentAncestor.expanded)
+ if (!currentAncestor.expanded) {
return false;
+ }
currentAncestor = currentAncestor.parent;
}
@@ -1039,8 +1126,9 @@ UI.TreeElement = class {
}
selectOnMouseDown(event) {
- if (this.select(false, true))
+ if (this.select(false, true)) {
event.consume(true);
+ }
if (this._listItemNode.draggable && this._selectionElement) {
const marginLeft =
@@ -1058,8 +1146,9 @@ UI.TreeElement = class {
*/
select(omitFocus, selectedByUser) {
if (!this.treeOutline || !this.selectable || this.selected) {
- if (!omitFocus)
+ if (!omitFocus) {
this.listItemElement.focus();
+ }
return false;
}
// Wait to deselect this element so that focus only changes once
@@ -1067,25 +1156,30 @@ UI.TreeElement = class {
this.treeOutline.selectedTreeElement = null;
if (this.treeOutline._rootElement === this) {
- if (lastSelected)
+ if (lastSelected) {
lastSelected.deselect();
- if (!omitFocus)
+ }
+ if (!omitFocus) {
this.listItemElement.focus();
+ }
return false;
}
this.selected = true;
this.treeOutline.selectedTreeElement = this;
- if (this.treeOutline._focusable)
+ if (this.treeOutline._focusable) {
this._setFocusable(true);
- if (!omitFocus || this.treeOutline.contentElement.hasFocus())
+ }
+ if (!omitFocus || this.treeOutline.contentElement.hasFocus()) {
this.listItemElement.focus();
+ }
this._listItemNode.classList.add('selected');
- this.treeOutline.dispatchEventToListeners(UI.TreeOutline.Events.ElementSelected, this);
- if (lastSelected)
+ this.treeOutline.dispatchEventToListeners(Events.ElementSelected, this);
+ if (lastSelected) {
lastSelected.deselect();
+ }
return this.onselect(selectedByUser);
}
@@ -1105,17 +1199,21 @@ UI.TreeElement = class {
}
_onFocus() {
- if (this.treeOutline._useLightSelectionColor)
+ if (this.treeOutline._useLightSelectionColor) {
return;
- if (!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred'))
+ }
+ if (!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred')) {
this._listItemNode.classList.add('force-white-icons');
+ }
}
_onBlur() {
- if (this.treeOutline._useLightSelectionColor)
+ if (this.treeOutline._useLightSelectionColor) {
return;
- if (!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred'))
+ }
+ if (!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred')) {
this._listItemNode.classList.remove('force-white-icons');
+ }
}
/**
@@ -1134,8 +1232,9 @@ UI.TreeElement = class {
if (this.treeOutline && this.treeOutline.selectedTreeElement === this) {
this.treeOutline.selectedTreeElement = null;
- if (hadFocus)
+ if (hadFocus) {
this.treeOutline.focus();
+ }
}
}
@@ -1210,43 +1309,50 @@ UI.TreeElement = class {
/**
* @param {boolean} skipUnrevealed
- * @param {?UI.TreeElement=} stayWithin
+ * @param {?TreeElement=} stayWithin
* @param {boolean=} dontPopulate
* @param {!Object=} info
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info) {
- if (!dontPopulate)
+ if (!dontPopulate) {
this._populateIfNeeded();
+ }
- if (info)
+ if (info) {
info.depthChange = 0;
+ }
let element = skipUnrevealed ? (this.revealed() ? this.firstChild() : null) : this.firstChild();
if (element && (!skipUnrevealed || (skipUnrevealed && this.expanded))) {
- if (info)
+ if (info) {
info.depthChange = 1;
+ }
return element;
}
- if (this === stayWithin)
+ if (this === stayWithin) {
return null;
+ }
element = skipUnrevealed ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
- if (element)
+ if (element) {
return element;
+ }
element = this;
while (element && !element.root &&
!(skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) &&
element.parent !== stayWithin) {
- if (info)
+ if (info) {
info.depthChange -= 1;
+ }
element = element.parent;
}
- if (!element || element.root)
+ if (!element || element.root) {
return null;
+ }
return (skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
}
@@ -1254,27 +1360,32 @@ UI.TreeElement = class {
/**
* @param {boolean} skipUnrevealed
* @param {boolean=} dontPopulate
- * @return {?UI.TreeElement}
+ * @return {?TreeElement}
*/
traversePreviousTreeElement(skipUnrevealed, dontPopulate) {
let element = skipUnrevealed ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
- if (!dontPopulate && element)
+ if (!dontPopulate && element) {
element._populateIfNeeded();
+ }
- while (element && (skipUnrevealed ? (element.revealed() && element.expanded ? element.lastChild() : null) :
- element.lastChild())) {
- if (!dontPopulate)
+ while (element &&
+ (skipUnrevealed ? (element.revealed() && element.expanded ? element.lastChild() : null) :
+ element.lastChild())) {
+ if (!dontPopulate) {
element._populateIfNeeded();
+ }
element =
(skipUnrevealed ? (element.revealed() && element.expanded ? element.lastChild() : null) :
element.lastChild());
}
- if (element)
+ if (element) {
return element;
+ }
- if (!this.parent || this.parent.root)
+ if (!this.parent || this.parent.root) {
return null;
+ }
return this.parent;
}
@@ -1288,15 +1399,32 @@ UI.TreeElement = class {
console.assert(paddingLeftValue.endsWith('px'));
const computedLeftPadding = parseFloat(paddingLeftValue);
const left = this._listItemNode.totalOffsetLeft() + computedLeftPadding;
- return event.pageX >= left && event.pageX <= left + UI.TreeElement._ArrowToggleWidth && this._expandable;
+ return event.pageX >= left && event.pageX <= left + TreeElement._ArrowToggleWidth && this._expandable;
}
-};
+}
/** @const */
-UI.TreeElement._ArrowToggleWidth = 10;
+TreeElement._ArrowToggleWidth = 10;
(function() {
const img = new Image();
img.src = 'Images/treeoutlineTriangles.svg';
-UI.TreeElement._imagePreload = img;
+TreeElement._imagePreload = img;
})();
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.TreeOutline = TreeOutline;
+
+UI.TreeOutline.Events = Events;
+
+/** @constructor */
+UI.TreeElement = TreeElement;
+
+/** @constructor */
+UI.TreeOutlineInShadow = TreeOutlineInShadow; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
index 6495a8bc168..aa22ef70509 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -28,8 +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.
*/
-UI.highlightedSearchResultClassName = 'highlighted-search-result';
-UI.highlightedCurrentSearchResultClassName = 'current-search-result';
+export const highlightedSearchResultClassName = 'highlighted-search-result';
+export const highlightedCurrentSearchResultClassName = 'current-search-result';
/**
* @param {!Element} element
@@ -40,34 +40,38 @@ UI.highlightedCurrentSearchResultClassName = 'current-search-result';
* @param {?string=} hoverCursor
* @param {number=} startDelay
*/
-UI.installDragHandle = function(
+export function installDragHandle(
element, elementDragStart, elementDrag, elementDragEnd, cursor, hoverCursor, startDelay) {
/**
* @param {!Event} event
*/
function onMouseDown(event) {
- const dragHandler = new UI.DragHandler();
+ const dragHandler = new DragHandler();
const dragStart = dragHandler.elementDragStart.bind(
dragHandler, element, elementDragStart, elementDrag, elementDragEnd, cursor, event);
- if (startDelay)
+ if (startDelay) {
startTimer = setTimeout(dragStart, startDelay);
- else
+ } else {
dragStart();
+ }
}
function onMouseUp() {
- if (startTimer)
+ if (startTimer) {
clearTimeout(startTimer);
+ }
startTimer = null;
}
let startTimer;
element.addEventListener('mousedown', onMouseDown, false);
- if (startDelay)
+ if (startDelay) {
element.addEventListener('mouseup', onMouseUp, false);
- if (hoverCursor !== null)
+ }
+ if (hoverCursor !== null) {
element.style.cursor = hoverCursor || cursor || '';
-};
+ }
+}
/**
* @param {!Element} targetElement
@@ -77,15 +81,15 @@ UI.installDragHandle = function(
* @param {?string} cursor
* @param {!Event} event
*/
-UI.elementDragStart = function(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event) {
- const dragHandler = new UI.DragHandler();
+export function elementDragStart(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event) {
+ const dragHandler = new DragHandler();
dragHandler.elementDragStart(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event);
-};
+}
/**
* @unrestricted
*/
-UI.DragHandler = class {
+export class DragHandler {
constructor() {
this._elementDragMove = this._elementDragMove.bind(this);
this._elementDragEnd = this._elementDragEnd.bind(this);
@@ -94,22 +98,24 @@ UI.DragHandler = class {
_createGlassPane() {
this._glassPaneInUse = true;
- if (!UI.DragHandler._glassPaneUsageCount++) {
- UI.DragHandler._glassPane = new UI.GlassPane();
- UI.DragHandler._glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
- UI.DragHandler._glassPane.show(UI.DragHandler._documentForMouseOut);
+ if (!DragHandler._glassPaneUsageCount++) {
+ DragHandler._glassPane = new UI.GlassPane();
+ DragHandler._glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BlockedByGlassPane);
+ DragHandler._glassPane.show(DragHandler._documentForMouseOut);
}
}
_disposeGlassPane() {
- if (!this._glassPaneInUse)
+ if (!this._glassPaneInUse) {
return;
+ }
this._glassPaneInUse = false;
- if (--UI.DragHandler._glassPaneUsageCount)
+ if (--DragHandler._glassPaneUsageCount) {
return;
- UI.DragHandler._glassPane.hide();
- delete UI.DragHandler._glassPane;
- delete UI.DragHandler._documentForMouseOut;
+ }
+ DragHandler._glassPane.hide();
+ delete DragHandler._glassPane;
+ delete DragHandler._documentForMouseOut;
}
/**
@@ -122,21 +128,24 @@ UI.DragHandler = class {
*/
elementDragStart(targetElement, elementDragStart, elementDrag, elementDragEnd, cursor, event) {
// Only drag upon left button. Right will likely cause a context menu. So will ctrl-click on mac.
- if (event.button || (Host.isMac() && event.ctrlKey))
+ if (event.button || (Host.isMac() && event.ctrlKey)) {
return;
+ }
- if (this._elementDraggingEventListener)
+ if (this._elementDraggingEventListener) {
return;
+ }
- if (elementDragStart && !elementDragStart(/** @type {!MouseEvent} */ (event)))
+ if (elementDragStart && !elementDragStart(/** @type {!MouseEvent} */ (event))) {
return;
+ }
const targetDocument = event.target.ownerDocument;
this._elementDraggingEventListener = elementDrag;
this._elementEndDraggingEventListener = elementDragEnd;
console.assert(
- (UI.DragHandler._documentForMouseOut || targetDocument) === targetDocument, 'Dragging on multiple documents.');
- UI.DragHandler._documentForMouseOut = targetDocument;
+ (DragHandler._documentForMouseOut || targetDocument) === targetDocument, 'Dragging on multiple documents.');
+ DragHandler._documentForMouseOut = targetDocument;
this._dragEventsTargetDocument = targetDocument;
try {
this._dragEventsTargetDocumentTop = targetDocument.defaultView.top.document;
@@ -147,8 +156,9 @@ UI.DragHandler = class {
targetDocument.addEventListener('mousemove', this._elementDragMove, true);
targetDocument.addEventListener('mouseup', this._elementDragEnd, true);
targetDocument.addEventListener('mouseout', this._mouseOutWhileDragging, true);
- if (targetDocument !== this._dragEventsTargetDocumentTop)
+ if (targetDocument !== this._dragEventsTargetDocumentTop) {
this._dragEventsTargetDocumentTop.addEventListener('mouseup', this._elementDragEnd, true);
+ }
if (typeof cursor === 'string') {
this._restoreCursorAfterDrag = restoreCursor.bind(this, targetElement.style.cursor);
@@ -157,7 +167,7 @@ UI.DragHandler = class {
}
/**
* @param {string} oldCursor
- * @this {UI.DragHandler}
+ * @this {DragHandler}
*/
function restoreCursor(oldCursor) {
targetDocument.body.style.removeProperty('cursor');
@@ -173,18 +183,21 @@ UI.DragHandler = class {
}
_unregisterMouseOutWhileDragging() {
- if (!UI.DragHandler._documentForMouseOut)
+ if (!DragHandler._documentForMouseOut) {
return;
- UI.DragHandler._documentForMouseOut.removeEventListener('mouseout', this._mouseOutWhileDragging, true);
+ }
+ DragHandler._documentForMouseOut.removeEventListener('mouseout', this._mouseOutWhileDragging, true);
}
_unregisterDragEvents() {
- if (!this._dragEventsTargetDocument)
+ if (!this._dragEventsTargetDocument) {
return;
+ }
this._dragEventsTargetDocument.removeEventListener('mousemove', this._elementDragMove, true);
this._dragEventsTargetDocument.removeEventListener('mouseup', this._elementDragEnd, true);
- if (this._dragEventsTargetDocument !== this._dragEventsTargetDocumentTop)
+ if (this._dragEventsTargetDocument !== this._dragEventsTargetDocumentTop) {
this._dragEventsTargetDocumentTop.removeEventListener('mouseup', this._elementDragEnd, true);
+ }
delete this._dragEventsTargetDocument;
delete this._dragEventsTargetDocumentTop;
}
@@ -197,8 +210,9 @@ UI.DragHandler = class {
this._elementDragEnd(event);
return;
}
- if (this._elementDraggingEventListener(/** @type {!MouseEvent} */ (event)))
+ if (this._elementDraggingEventListener(/** @type {!MouseEvent} */ (event))) {
this._cancelDragEvents(event);
+ }
}
/**
@@ -208,8 +222,9 @@ UI.DragHandler = class {
this._unregisterDragEvents();
this._unregisterMouseOutWhileDragging();
- if (this._restoreCursorAfterDrag)
+ if (this._restoreCursorAfterDrag) {
this._restoreCursorAfterDrag();
+ }
this._disposeGlassPane();
@@ -224,118 +239,132 @@ UI.DragHandler = class {
const elementDragEnd = this._elementEndDraggingEventListener;
this._cancelDragEvents(/** @type {!MouseEvent} */ (event));
event.preventDefault();
- if (elementDragEnd)
+ if (elementDragEnd) {
elementDragEnd(/** @type {!MouseEvent} */ (event));
+ }
}
-};
+}
-UI.DragHandler._glassPaneUsageCount = 0;
+DragHandler._glassPaneUsageCount = 0;
/**
* @param {?Node=} node
* @return {boolean}
*/
-UI.isBeingEdited = function(node) {
- if (!node || node.nodeType !== Node.ELEMENT_NODE)
+export function isBeingEdited(node) {
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) {
return false;
+ }
let element = /** {!Element} */ (node);
- if (element.classList.contains('text-prompt') || element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')
+ if (element.classList.contains('text-prompt') || element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
return true;
+ }
- if (!UI.__editingCount)
+ if (!UI.__editingCount) {
return false;
+ }
while (element) {
- if (element.__editing)
+ if (element.__editing) {
return true;
+ }
element = element.parentElementOrShadowHost();
}
return false;
-};
+}
/**
* @return {boolean}
* @suppressGlobalPropertiesCheck
*/
-UI.isEditing = function() {
- if (UI.__editingCount)
+export function isEditing() {
+ if (UI.__editingCount) {
return true;
+ }
const focused = document.deepActiveElement();
- if (!focused)
+ if (!focused) {
return false;
+ }
return focused.classList.contains('text-prompt') || focused.nodeName === 'INPUT' || focused.nodeName === 'TEXTAREA';
-};
+}
/**
* @param {!Element} element
* @param {boolean} value
* @return {boolean}
*/
-UI.markBeingEdited = function(element, value) {
+export function markBeingEdited(element, value) {
if (value) {
- if (element.__editing)
+ if (element.__editing) {
return false;
+ }
element.classList.add('being-edited');
element.__editing = true;
UI.__editingCount = (UI.__editingCount || 0) + 1;
} else {
- if (!element.__editing)
+ if (!element.__editing) {
return false;
+ }
element.classList.remove('being-edited');
delete element.__editing;
--UI.__editingCount;
}
return true;
-};
+}
// Avoids Infinity, NaN, and scientific notation (e.g. 1e20), see crbug.com/81165.
-UI._numberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/;
+export const _numberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/;
-UI.StyleValueDelimiters = ' \xA0\t\n"\':;,/()';
+export const StyleValueDelimiters = ' \xA0\t\n"\':;,/()';
/**
* @param {!Event} event
* @return {?string}
*/
-UI._valueModificationDirection = function(event) {
+export function _valueModificationDirection(event) {
let direction = null;
if (event.type === 'mousewheel') {
// When shift is pressed while spinning mousewheel, delta comes as wheelDeltaX.
- if (event.wheelDeltaY > 0 || event.wheelDeltaX > 0)
+ if (event.wheelDeltaY > 0 || event.wheelDeltaX > 0) {
direction = 'Up';
- else if (event.wheelDeltaY < 0 || event.wheelDeltaX < 0)
+ } else if (event.wheelDeltaY < 0 || event.wheelDeltaX < 0) {
direction = 'Down';
+ }
} else {
- if (event.key === 'ArrowUp' || event.key === 'PageUp')
+ if (event.key === 'ArrowUp' || event.key === 'PageUp') {
direction = 'Up';
- else if (event.key === 'ArrowDown' || event.key === 'PageDown')
+ } else if (event.key === 'ArrowDown' || event.key === 'PageDown') {
direction = 'Down';
+ }
}
return direction;
-};
+}
/**
* @param {string} hexString
* @param {!Event} event
* @return {?string}
*/
-UI._modifiedHexValue = function(hexString, event) {
- const direction = UI._valueModificationDirection(event);
- if (!direction)
+export function _modifiedHexValue(hexString, event) {
+ const direction = _valueModificationDirection(event);
+ if (!direction) {
return null;
+ }
const mouseEvent = /** @type {!MouseEvent} */ (event);
const number = parseInt(hexString, 16);
- if (isNaN(number) || !isFinite(number))
+ if (isNaN(number) || !isFinite(number)) {
return null;
+ }
const hexStrLen = hexString.length;
const channelLen = hexStrLen / 3;
// Colors are either rgb or rrggbb.
- if (channelLen !== 1 && channelLen !== 2)
+ if (channelLen !== 1 && channelLen !== 2) {
return null;
+ }
// Precision modifier keys work with both mousewheel and up/down keys.
// When ctrl is pressed, increase R by 1.
@@ -344,16 +373,21 @@ UI._modifiedHexValue = function(hexString, event) {
// If no shortcut keys are pressed then increase hex value by 1.
// Keys can be pressed together to increase RGB channels. e.g trying different shades.
let delta = 0;
- if (UI.KeyboardShortcut.eventHasCtrlOrMeta(mouseEvent))
+ if (UI.KeyboardShortcut.eventHasCtrlOrMeta(mouseEvent)) {
delta += Math.pow(16, channelLen * 2);
- if (mouseEvent.shiftKey)
+ }
+ if (mouseEvent.shiftKey) {
delta += Math.pow(16, channelLen);
- if (mouseEvent.altKey)
+ }
+ if (mouseEvent.altKey) {
delta += 1;
- if (delta === 0)
+ }
+ if (delta === 0) {
delta = 1;
- if (direction === 'Down')
+ }
+ if (direction === 'Down') {
delta *= -1;
+ }
// Increase hex value by 1 and clamp from 0 ... maxValue.
const maxValue = Math.pow(16, hexStrLen) - 1;
@@ -361,10 +395,11 @@ UI._modifiedHexValue = function(hexString, event) {
// Ensure the result length is the same as the original hex value.
let resultString = result.toString(16).toUpperCase();
- for (let i = 0, lengthDelta = hexStrLen - resultString.length; i < lengthDelta; ++i)
+ for (let i = 0, lengthDelta = hexStrLen - resultString.length; i < lengthDelta; ++i) {
resultString = '0' + resultString;
+ }
return resultString;
-};
+}
/**
* @param {number} number
@@ -372,10 +407,11 @@ UI._modifiedHexValue = function(hexString, event) {
* @param {number=} modifierMultiplier
* @return {?number}
*/
-UI._modifiedFloatNumber = function(number, event, modifierMultiplier) {
- const direction = UI._valueModificationDirection(event);
- if (!direction)
+export function _modifiedFloatNumber(number, event, modifierMultiplier) {
+ const direction = _valueModificationDirection(event);
+ if (!direction) {
return null;
+ }
const mouseEvent = /** @type {!MouseEvent} */ (event);
@@ -385,25 +421,29 @@ UI._modifiedFloatNumber = function(number, event, modifierMultiplier) {
// When alt is pressed, increase by 0.1.
// Otherwise increase by 1.
let delta = 1;
- if (UI.KeyboardShortcut.eventHasCtrlOrMeta(mouseEvent))
+ if (UI.KeyboardShortcut.eventHasCtrlOrMeta(mouseEvent)) {
delta = 100;
- else if (mouseEvent.shiftKey)
+ } else if (mouseEvent.shiftKey) {
delta = 10;
- else if (mouseEvent.altKey)
+ } else if (mouseEvent.altKey) {
delta = 0.1;
+ }
- if (direction === 'Down')
+ if (direction === 'Down') {
delta *= -1;
- if (modifierMultiplier)
+ }
+ if (modifierMultiplier) {
delta *= modifierMultiplier;
+ }
// Make the new number and constrain it to a precision of 6, this matches numbers the engine returns.
// Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1.
const result = Number((number + delta).toFixed(6));
- if (!String(result).match(UI._numberRegex))
+ if (!String(result).match(_numberRegex)) {
return null;
+ }
return result;
-};
+}
/**
* @param {string} wordString
@@ -411,7 +451,7 @@ UI._modifiedFloatNumber = function(number, event, modifierMultiplier) {
* @param {function(string, number, string):string=} customNumberHandler
* @return {?string}
*/
-UI.createReplacementString = function(wordString, event, customNumberHandler) {
+export function createReplacementString(wordString, event, customNumberHandler) {
let prefix;
let suffix;
let number;
@@ -420,15 +460,16 @@ UI.createReplacementString = function(wordString, event, customNumberHandler) {
if (matches && matches.length) {
prefix = matches[1];
suffix = matches[3];
- number = UI._modifiedHexValue(matches[2], event);
- if (number !== null)
+ number = _modifiedHexValue(matches[2], event);
+ if (number !== null) {
replacementString = prefix + number + suffix;
+ }
} else {
matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString);
if (matches && matches.length) {
prefix = matches[1];
suffix = matches[3];
- number = UI._modifiedFloatNumber(parseFloat(matches[2]), event);
+ number = _modifiedFloatNumber(parseFloat(matches[2]), event);
if (number !== null) {
replacementString =
customNumberHandler ? customNumberHandler(prefix, number, suffix) : prefix + number + suffix;
@@ -436,7 +477,7 @@ UI.createReplacementString = function(wordString, event, customNumberHandler) {
}
}
return replacementString;
-};
+}
/**
* @param {!Event} event
@@ -446,7 +487,7 @@ UI.createReplacementString = function(wordString, event, customNumberHandler) {
* @param {function(string, number, string):string=} customNumberHandler
* @return {boolean}
*/
-UI.handleElementValueModifications = function(event, element, finishHandler, suggestionHandler, customNumberHandler) {
+export function handleElementValueModifications(event, element, finishHandler, suggestionHandler, customNumberHandler) {
/**
* @return {?Range}
* @suppressGlobalPropertiesCheck
@@ -458,26 +499,30 @@ UI.handleElementValueModifications = function(event, element, finishHandler, sug
const arrowKeyOrMouseWheelEvent =
(event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.type === 'mousewheel');
const pageKeyPressed = (event.key === 'PageUp' || event.key === 'PageDown');
- if (!arrowKeyOrMouseWheelEvent && !pageKeyPressed)
+ if (!arrowKeyOrMouseWheelEvent && !pageKeyPressed) {
return false;
+ }
const selection = element.getComponentSelection();
- if (!selection.rangeCount)
+ if (!selection.rangeCount) {
return false;
+ }
const selectionRange = selection.getRangeAt(0);
- if (!selectionRange.commonAncestorContainer.isSelfOrDescendant(element))
+ if (!selectionRange.commonAncestorContainer.isSelfOrDescendant(element)) {
return false;
+ }
const originalValue = element.textContent;
const wordRange =
- selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, UI.StyleValueDelimiters, element);
+ selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, StyleValueDelimiters, element);
const wordString = wordRange.toString();
- if (suggestionHandler && suggestionHandler(wordString))
+ if (suggestionHandler && suggestionHandler(wordString)) {
return false;
+ }
- const replacementString = UI.createReplacementString(wordString, event, customNumberHandler);
+ const replacementString = createReplacementString(wordString, event, customNumberHandler);
if (replacementString) {
const replacementTextNode = createTextNode(replacementString);
@@ -495,13 +540,14 @@ UI.handleElementValueModifications = function(event, element, finishHandler, sug
event.handled = true;
event.preventDefault();
- if (finishHandler)
+ if (finishHandler) {
finishHandler(originalValue, replacementString);
+ }
return true;
}
return false;
-};
+}
/**
* @param {number} ms
@@ -515,25 +561,25 @@ Number.preciseMillisToString = function(ms, precision) {
};
/** @type {!Common.UIStringFormat} */
-UI._microsFormat = new Common.UIStringFormat('%.0f\xa0\u03bcs');
+export const _microsFormat = new Common.UIStringFormat('%.0f\xa0\u03bcs');
/** @type {!Common.UIStringFormat} */
-UI._subMillisFormat = new Common.UIStringFormat('%.2f\xa0ms');
+export const _subMillisFormat = new Common.UIStringFormat('%.2f\xa0ms');
/** @type {!Common.UIStringFormat} */
-UI._millisFormat = new Common.UIStringFormat('%.0f\xa0ms');
+export const _millisFormat = new Common.UIStringFormat('%.0f\xa0ms');
/** @type {!Common.UIStringFormat} */
-UI._secondsFormat = new Common.UIStringFormat('%.2f\xa0s');
+export const _secondsFormat = new Common.UIStringFormat('%.2f\xa0s');
/** @type {!Common.UIStringFormat} */
-UI._minutesFormat = new Common.UIStringFormat('%.1f\xa0min');
+export const _minutesFormat = new Common.UIStringFormat('%.1f\xa0min');
/** @type {!Common.UIStringFormat} */
-UI._hoursFormat = new Common.UIStringFormat('%.1f\xa0hrs');
+export const _hoursFormat = new Common.UIStringFormat('%.1f\xa0hrs');
/** @type {!Common.UIStringFormat} */
-UI._daysFormat = new Common.UIStringFormat('%.1f\xa0days');
+export const _daysFormat = new Common.UIStringFormat('%.1f\xa0days');
/**
* @param {number} ms
@@ -541,33 +587,41 @@ UI._daysFormat = new Common.UIStringFormat('%.1f\xa0days');
* @return {string}
*/
Number.millisToString = function(ms, higherResolution) {
- if (!isFinite(ms))
+ if (!isFinite(ms)) {
return '-';
+ }
- if (ms === 0)
+ if (ms === 0) {
return '0';
+ }
- if (higherResolution && ms < 0.1)
- return UI._microsFormat.format(ms * 1000);
- if (higherResolution && ms < 1000)
- return UI._subMillisFormat.format(ms);
- if (ms < 1000)
- return UI._millisFormat.format(ms);
+ if (higherResolution && ms < 0.1) {
+ return _microsFormat.format(ms * 1000);
+ }
+ if (higherResolution && ms < 1000) {
+ return _subMillisFormat.format(ms);
+ }
+ if (ms < 1000) {
+ return _millisFormat.format(ms);
+ }
const seconds = ms / 1000;
- if (seconds < 60)
- return UI._secondsFormat.format(seconds);
+ if (seconds < 60) {
+ return _secondsFormat.format(seconds);
+ }
const minutes = seconds / 60;
- if (minutes < 60)
- return UI._minutesFormat.format(minutes);
+ if (minutes < 60) {
+ return _minutesFormat.format(minutes);
+ }
const hours = minutes / 60;
- if (hours < 24)
- return UI._hoursFormat.format(hours);
+ if (hours < 24) {
+ return _hoursFormat.format(hours);
+ }
const days = hours / 24;
- return UI._daysFormat.format(days);
+ return _daysFormat.format(days);
};
/**
@@ -576,8 +630,9 @@ Number.millisToString = function(ms, higherResolution) {
* @return {string}
*/
Number.secondsToString = function(seconds, higherResolution) {
- if (!isFinite(seconds))
+ if (!isFinite(seconds)) {
return '-';
+ }
return Number.millisToString(seconds * 1000, higherResolution);
};
@@ -586,20 +641,24 @@ Number.secondsToString = function(seconds, higherResolution) {
* @return {string}
*/
Number.bytesToString = function(bytes) {
- if (bytes < 1024)
+ if (bytes < 1024) {
return Common.UIString('%.0f\xa0B', bytes);
+ }
const kilobytes = bytes / 1024;
- if (kilobytes < 100)
+ if (kilobytes < 100) {
return Common.UIString('%.1f\xa0KB', kilobytes);
- if (kilobytes < 1024)
+ }
+ if (kilobytes < 1024) {
return Common.UIString('%.0f\xa0KB', kilobytes);
+ }
const megabytes = kilobytes / 1024;
- if (megabytes < 100)
+ if (megabytes < 100) {
return Common.UIString('%.1f\xa0MB', megabytes);
- else
+ } else {
return Common.UIString('%.0f\xa0MB', megabytes);
+ }
};
/**
@@ -609,8 +668,9 @@ Number.bytesToString = function(bytes) {
Number.withThousandsSeparator = function(num) {
let str = num + '';
const re = /(\d+)(\d{3})/;
- while (str.match(re))
- str = str.replace(re, '$1\xa0$2'); // \xa0 is a non-breaking space
+ while (str.match(re)) {
+ str = str.replace(re, '$1\xa0$2');
+ } // \xa0 is a non-breaking space
return str;
};
@@ -619,7 +679,7 @@ Number.withThousandsSeparator = function(num) {
* @param {?ArrayLike} substitutions
* @return {!Element}
*/
-UI.formatLocalized = function(format, substitutions) {
+export function formatLocalized(format, substitutions) {
const formatters = {s: substitution => substitution};
/**
* @param {!Element} a
@@ -632,72 +692,79 @@ UI.formatLocalized = function(format, substitutions) {
}
return String.format(Common.UIString(format), substitutions, formatters, createElement('span'), append)
.formattedResult;
-};
+}
/**
* @return {string}
*/
-UI.openLinkExternallyLabel = function() {
+export function openLinkExternallyLabel() {
return Common.UIString('Open in new tab');
-};
+}
/**
* @return {string}
*/
-UI.copyLinkAddressLabel = function() {
+export function copyLinkAddressLabel() {
return Common.UIString('Copy link address');
-};
+}
/**
* @return {string}
*/
-UI.anotherProfilerActiveLabel = function() {
+export function anotherProfilerActiveLabel() {
return Common.UIString('Another profiler is already active');
-};
+}
/**
* @param {string|undefined} description
* @return {string}
*/
-UI.asyncStackTraceLabel = function(description) {
+export function asyncStackTraceLabel(description) {
if (description) {
- if (description === 'Promise.resolve')
+ if (description === 'Promise.resolve') {
return ls`Promise resolved (async)`;
- else if (description === 'Promise.reject')
+ } else if (description === 'Promise.reject') {
return ls`Promise rejected (async)`;
+ }
return ls`${description} (async)`;
}
return Common.UIString('Async Call');
-};
+}
/**
* @param {!Element} element
*/
-UI.installComponentRootStyles = function(element) {
- UI._injectCoreStyles(element);
+export function installComponentRootStyles(element) {
+ _injectCoreStyles(element);
element.classList.add('platform-' + Host.platform());
// Detect overlay scrollbar enable by checking for nonzero scrollbar width.
- if (!Host.isMac() && UI.measuredScrollbarWidth(element.ownerDocument) === 0)
+ if (!Host.isMac() && measuredScrollbarWidth(element.ownerDocument) === 0) {
element.classList.add('overlay-scrollbar-enabled');
-};
+ }
+}
+
+/** @type {number} */
+let _measuredScrollbarWidth;
/**
* @param {?Document} document
* @return {number}
*/
-UI.measuredScrollbarWidth = function(document) {
- if (typeof UI._measuredScrollbarWidth === 'number')
- return UI._measuredScrollbarWidth;
- if (!document)
+export function measuredScrollbarWidth(document) {
+ if (typeof _measuredScrollbarWidth === 'number') {
+ return _measuredScrollbarWidth;
+ }
+ if (!document) {
return 16;
+ }
const scrollDiv = document.createElement('div');
scrollDiv.setAttribute('style', 'width: 100px; height: 100px; overflow: scroll;');
document.body.appendChild(scrollDiv);
- UI._measuredScrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+ _measuredScrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
document.body.removeChild(scrollDiv);
- return UI._measuredScrollbarWidth;
-};
+ return _measuredScrollbarWidth;
+}
/**
* @param {!Element} element
@@ -705,37 +772,40 @@ UI.measuredScrollbarWidth = function(document) {
* @param {boolean=} delegatesFocus
* @return {!DocumentFragment}
*/
-UI.createShadowRootWithCoreStyles = function(element, cssFile, delegatesFocus) {
+export function createShadowRootWithCoreStyles(element, cssFile, delegatesFocus) {
const shadowRoot = element.attachShadow({mode: 'open', delegatesFocus});
- UI._injectCoreStyles(shadowRoot);
- if (cssFile)
- UI.appendStyle(shadowRoot, cssFile);
- shadowRoot.addEventListener('focus', UI._focusChanged.bind(UI), true);
+ _injectCoreStyles(shadowRoot);
+ if (cssFile) {
+ appendStyle(shadowRoot, cssFile);
+ }
+ shadowRoot.addEventListener('focus', _focusChanged.bind(UI), true);
return shadowRoot;
-};
+}
/**
* @param {!Element|!ShadowRoot} root
*/
-UI._injectCoreStyles = function(root) {
- UI.appendStyle(root, 'ui/inspectorCommon.css');
- UI.appendStyle(root, 'ui/textButton.css');
+export function _injectCoreStyles(root) {
+ appendStyle(root, 'ui/inspectorCommon.css');
+ appendStyle(root, 'ui/textButton.css');
UI.themeSupport.injectHighlightStyleSheets(root);
UI.themeSupport.injectCustomStyleSheets(root);
-};
+}
/**
* @param {!Document} document
* @param {!Event} event
*/
-UI._windowFocused = function(document, event) {
- if (event.target.document.nodeType === Node.DOCUMENT_NODE)
+export function _windowFocused(document, event) {
+ if (event.target.document.nodeType === Node.DOCUMENT_NODE) {
document.body.classList.remove('inactive');
+ }
UI._keyboardFocus = true;
const listener = () => {
const activeElement = document.deepActiveElement();
- if (activeElement)
+ if (activeElement) {
activeElement.removeAttribute('data-keyboard-focus');
+ }
UI._keyboardFocus = false;
};
document.defaultView.requestAnimationFrame(() => {
@@ -743,28 +813,34 @@ UI._windowFocused = function(document, event) {
document.removeEventListener('mousedown', listener, true);
});
document.addEventListener('mousedown', listener, true);
-
-};
+}
/**
* @param {!Document} document
* @param {!Event} event
*/
-UI._windowBlurred = function(document, event) {
- if (event.target.document.nodeType === Node.DOCUMENT_NODE)
+export function _windowBlurred(document, event) {
+ if (event.target.document.nodeType === Node.DOCUMENT_NODE) {
document.body.classList.add('inactive');
-};
+ }
+}
/**
* @param {!Event} event
*/
-UI._focusChanged = function(event) {
+export function _focusChanged(event) {
const document = event.target && event.target.ownerDocument;
const element = document ? document.deepActiveElement() : null;
UI.Widget.focusWidgetForNode(element);
UI.XWidget.focusWidgetForNode(element);
- if (!UI._keyboardFocus)
+ if (!UI._keyboardFocus) {
return;
+ }
+
+ UI.markAsFocusedByKeyboard(element);
+}
+
+UI.markAsFocusedByKeyboard = function(element) {
element.setAttribute('data-keyboard-focus', 'true');
element.addEventListener('blur', () => element.removeAttribute('data-keyboard-focus'), {once: true, capture: true});
};
@@ -772,7 +848,7 @@ UI._focusChanged = function(event) {
/**
* @unrestricted
*/
-UI.ElementFocusRestorer = class {
+export class ElementFocusRestorer {
/**
* @param {!Element} element
*/
@@ -783,14 +859,16 @@ UI.ElementFocusRestorer = class {
}
restore() {
- if (!this._element)
+ if (!this._element) {
return;
- if (this._element.hasFocus() && this._previous)
+ }
+ if (this._element.hasFocus() && this._previous) {
this._previous.focus();
+ }
this._previous = null;
this._element = null;
}
-};
+}
/**
* @param {!Element} element
@@ -799,10 +877,10 @@ UI.ElementFocusRestorer = class {
* @param {!Array.<!Object>=} domChanges
* @return {?Element}
*/
-UI.highlightSearchResult = function(element, offset, length, domChanges) {
- const result = UI.highlightSearchResults(element, [new TextUtils.SourceRange(offset, length)], domChanges);
+export function highlightSearchResult(element, offset, length, domChanges) {
+ const result = highlightSearchResults(element, [new TextUtils.SourceRange(offset, length)], domChanges);
return result.length ? result[0] : null;
-};
+}
/**
* @param {!Element} element
@@ -810,26 +888,27 @@ UI.highlightSearchResult = function(element, offset, length, domChanges) {
* @param {!Array.<!Object>=} changes
* @return {!Array.<!Element>}
*/
-UI.highlightSearchResults = function(element, resultRanges, changes) {
- return UI.highlightRangesWithStyleClass(element, resultRanges, UI.highlightedSearchResultClassName, changes);
-};
+export function highlightSearchResults(element, resultRanges, changes) {
+ return highlightRangesWithStyleClass(element, resultRanges, highlightedSearchResultClassName, changes);
+}
/**
* @param {!Element} element
* @param {string} className
*/
-UI.runCSSAnimationOnce = function(element, className) {
+export function runCSSAnimationOnce(element, className) {
function animationEndCallback() {
element.classList.remove(className);
element.removeEventListener('webkitAnimationEnd', animationEndCallback, false);
}
- if (element.classList.contains(className))
+ if (element.classList.contains(className)) {
element.classList.remove(className);
+ }
element.addEventListener('webkitAnimationEnd', animationEndCallback, false);
element.classList.add(className);
-};
+}
/**
* @param {!Element} element
@@ -838,7 +917,7 @@ UI.runCSSAnimationOnce = function(element, className) {
* @param {!Array.<!Object>=} changes
* @return {!Array.<!Element>}
*/
-UI.highlightRangesWithStyleClass = function(element, resultRanges, styleClass, changes) {
+export function highlightRangesWithStyleClass(element, resultRanges, styleClass, changes) {
changes = changes || [];
const highlightNodes = [];
const textNodes = element.childTextNodes();
@@ -849,8 +928,9 @@ UI.highlightRangesWithStyleClass = function(element, resultRanges, styleClass, c
.join('');
const ownerDocument = element.ownerDocument;
- if (textNodes.length === 0)
+ if (textNodes.length === 0) {
return highlightNodes;
+ }
const nodeRanges = [];
let rangeEndOffset = 0;
@@ -868,13 +948,16 @@ UI.highlightRangesWithStyleClass = function(element, resultRanges, styleClass, c
const endOffset = startOffset + resultRanges[i].length;
while (startIndex < textNodes.length &&
- nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset)
+ nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset) {
startIndex++;
+ }
let endIndex = startIndex;
- while (endIndex < textNodes.length && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset)
+ while (endIndex < textNodes.length && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset) {
endIndex++;
- if (endIndex === textNodes.length)
+ }
+ if (endIndex === textNodes.length) {
break;
+ }
const highlightNode = ownerDocument.createElement('span');
highlightNode.className = styleClass;
@@ -919,9 +1002,9 @@ UI.highlightRangesWithStyleClass = function(element, resultRanges, styleClass, c
nodeRanges[startIndex].length = lastTextNode.textContent.length;
}
return highlightNodes;
-};
+}
-UI.applyDomChanges = function(domChanges) {
+export function applyDomChanges(domChanges) {
for (let i = 0, size = domChanges.length; i < size; ++i) {
const entry = domChanges[i];
switch (entry.type) {
@@ -933,9 +1016,9 @@ UI.applyDomChanges = function(domChanges) {
break;
}
}
-};
+}
-UI.revertDomChanges = function(domChanges) {
+export function revertDomChanges(domChanges) {
for (let i = domChanges.length - 1; i >= 0; --i) {
const entry = domChanges[i];
switch (entry.type) {
@@ -947,14 +1030,14 @@ UI.revertDomChanges = function(domChanges) {
break;
}
}
-};
+}
/**
* @param {!Element} element
* @param {?Element=} containerElement
* @return {!UI.Size}
*/
-UI.measurePreferredSize = function(element, containerElement) {
+export function measurePreferredSize(element, containerElement) {
const oldParent = element.parentElement;
const oldNextSibling = element.nextSibling;
containerElement = containerElement || element.ownerDocument.body;
@@ -963,17 +1046,18 @@ UI.measurePreferredSize = function(element, containerElement) {
const result = element.getBoundingClientRect();
element.positionAt(undefined, undefined);
- if (oldParent)
+ if (oldParent) {
oldParent.insertBefore(element, oldNextSibling);
- else
+ } else {
element.remove();
+ }
return new UI.Size(result.width, result.height);
-};
+}
/**
* @unrestricted
*/
-UI.InvokeOnceHandlers = class {
+export class InvokeOnceHandlers {
/**
* @param {boolean} autoInvoke
*/
@@ -989,8 +1073,9 @@ UI.InvokeOnceHandlers = class {
add(object, method) {
if (!this._handlers) {
this._handlers = new Map();
- if (this._autoInvoke)
+ if (this._autoInvoke) {
this.scheduleInvoke();
+ }
}
let methods = this._handlers.get(object);
if (!methods) {
@@ -1004,8 +1089,9 @@ UI.InvokeOnceHandlers = class {
* @suppressGlobalPropertiesCheck
*/
scheduleInvoke() {
- if (this._handlers)
+ if (this._handlers) {
requestAnimationFrame(this._invoke.bind(this));
+ }
}
_invoke() {
@@ -1015,36 +1101,40 @@ UI.InvokeOnceHandlers = class {
for (let i = 0; i < keys.length; ++i) {
const object = keys[i];
const methods = handlers.get(object).valuesArray();
- for (let j = 0; j < methods.length; ++j)
+ for (let j = 0; j < methods.length; ++j) {
methods[j].call(object);
+ }
}
}
-};
+}
-UI._coalescingLevel = 0;
-UI._postUpdateHandlers = null;
+export let _coalescingLevel = 0;
+export let _postUpdateHandlers = null;
-UI.startBatchUpdate = function() {
- if (!UI._coalescingLevel++)
- UI._postUpdateHandlers = new UI.InvokeOnceHandlers(false);
-};
+export function startBatchUpdate() {
+ if (!_coalescingLevel++) {
+ _postUpdateHandlers = new InvokeOnceHandlers(false);
+ }
+}
-UI.endBatchUpdate = function() {
- if (--UI._coalescingLevel)
+export function endBatchUpdate() {
+ if (--_coalescingLevel) {
return;
- UI._postUpdateHandlers.scheduleInvoke();
- UI._postUpdateHandlers = null;
-};
+ }
+ _postUpdateHandlers.scheduleInvoke();
+ _postUpdateHandlers = null;
+}
/**
* @param {!Object} object
* @param {function()} method
*/
-UI.invokeOnceAfterBatchUpdate = function(object, method) {
- if (!UI._postUpdateHandlers)
- UI._postUpdateHandlers = new UI.InvokeOnceHandlers(true);
- UI._postUpdateHandlers.add(object, method);
-};
+export function invokeOnceAfterBatchUpdate(object, method) {
+ if (!_postUpdateHandlers) {
+ _postUpdateHandlers = new InvokeOnceHandlers(true);
+ }
+ _postUpdateHandlers.add(object, method);
+}
/**
* @param {!Window} window
@@ -1054,26 +1144,27 @@ UI.invokeOnceAfterBatchUpdate = function(object, method) {
* @param {function()=} animationComplete
* @return {function()}
*/
-UI.animateFunction = function(window, func, params, duration, animationComplete) {
+export function animateFunction(window, func, params, duration, animationComplete) {
const start = window.performance.now();
let raf = window.requestAnimationFrame(animationStep);
function animationStep(timestamp) {
const progress = Number.constrain((timestamp - start) / duration, 0, 1);
func(...params.map(p => p.from + (p.to - p.from) * progress));
- if (progress < 1)
+ if (progress < 1) {
raf = window.requestAnimationFrame(animationStep);
- else if (animationComplete)
+ } else if (animationComplete) {
animationComplete();
+ }
}
return () => window.cancelAnimationFrame(raf);
-};
+}
/**
* @unrestricted
*/
-UI.LongClickController = class extends Common.Object {
+export class LongClickController extends Common.Object {
/**
* @param {!Element} element
* @param {function(!Event)} callback
@@ -1093,8 +1184,9 @@ UI.LongClickController = class extends Common.Object {
}
_enable() {
- if (this._longClickData)
+ if (this._longClickData) {
return;
+ }
const boundMouseDown = mouseDown.bind(this);
const boundMouseUp = mouseUp.bind(this);
const boundReset = this.reset.bind(this);
@@ -1108,67 +1200,71 @@ UI.LongClickController = class extends Common.Object {
/**
* @param {!Event} e
- * @this {UI.LongClickController}
+ * @this {LongClickController}
*/
function mouseDown(e) {
- if (e.which !== 1)
+ if (e.which !== 1) {
return;
+ }
const callback = this._callback;
this._longClickInterval = setTimeout(callback.bind(null, e), 200);
}
/**
* @param {!Event} e
- * @this {UI.LongClickController}
+ * @this {LongClickController}
*/
function mouseUp(e) {
- if (e.which !== 1)
+ if (e.which !== 1) {
return;
+ }
this.reset();
}
}
dispose() {
- if (!this._longClickData)
+ if (!this._longClickData) {
return;
+ }
this._element.removeEventListener('mousedown', this._longClickData.mouseDown, false);
this._element.removeEventListener('mouseout', this._longClickData.reset, false);
this._element.removeEventListener('mouseup', this._longClickData.mouseUp, false);
this._element.addEventListener('click', this._longClickData.reset, true);
delete this._longClickData;
}
-};
+}
/**
* @param {!Document} document
* @param {!Common.Setting} themeSetting
*/
-UI.initializeUIUtils = function(document, themeSetting) {
+export function initializeUIUtils(document, themeSetting) {
document.body.classList.toggle('inactive', !document.hasFocus());
- document.defaultView.addEventListener('focus', UI._windowFocused.bind(UI, document), false);
- document.defaultView.addEventListener('blur', UI._windowBlurred.bind(UI, document), false);
- document.addEventListener('focus', UI._focusChanged.bind(UI), true);
+ document.defaultView.addEventListener('focus', _windowFocused.bind(UI, document), false);
+ document.defaultView.addEventListener('blur', _windowBlurred.bind(UI, document), false);
+ document.addEventListener('focus', _focusChanged.bind(UI), true);
document.addEventListener('keydown', event => {
UI._keyboardFocus = true;
document.defaultView.requestAnimationFrame(() => void(UI._keyboardFocus = false));
}, true);
- if (!UI.themeSupport)
- UI.themeSupport = new UI.ThemeSupport(themeSetting);
+ if (!UI.themeSupport) {
+ UI.themeSupport = new ThemeSupport(themeSetting);
+ }
UI.themeSupport.applyTheme(document);
const body = /** @type {!Element} */ (document.body);
- UI.appendStyle(body, 'ui/inspectorStyle.css');
+ appendStyle(body, 'ui/inspectorStyle.css');
UI.GlassPane.setContainer(/** @type {!Element} */ (document.body));
-};
+}
/**
* @param {string} name
* @return {string}
*/
-UI.beautifyFunctionName = function(name) {
+export function beautifyFunctionName(name) {
return name || Common.UIString('(anonymous)');
-};
+}
/**
* @param {string} localName
@@ -1177,7 +1273,7 @@ UI.beautifyFunctionName = function(name) {
* @return {function()}
* @suppressGlobalPropertiesCheck
*/
-UI.registerCustomElement = function(localName, typeExtension, definition) {
+export function registerCustomElement(localName, typeExtension, definition) {
self.customElements.define(typeExtension, class extends definition {
constructor() {
super();
@@ -1186,7 +1282,7 @@ UI.registerCustomElement = function(localName, typeExtension, definition) {
}
}, {extends: localName});
return () => createElement(localName, typeExtension);
-};
+}
/**
* @param {string} text
@@ -1195,31 +1291,34 @@ UI.registerCustomElement = function(localName, typeExtension, definition) {
* @param {boolean=} primary
* @return {!Element}
*/
-UI.createTextButton = function(text, clickHandler, className, primary) {
+export function createTextButton(text, clickHandler, className, primary) {
const element = createElementWithClass('button', className || '');
element.textContent = text;
element.classList.add('text-button');
- if (primary)
+ if (primary) {
element.classList.add('primary-button');
- if (clickHandler)
+ }
+ if (clickHandler) {
element.addEventListener('click', clickHandler, false);
+ }
element.type = 'button';
return element;
-};
+}
/**
* @param {string=} className
* @param {string=} type
* @return {!Element}
*/
-UI.createInput = function(className, type) {
+export function createInput(className, type) {
const element = createElementWithClass('input', className || '');
element.spellcheck = false;
element.classList.add('harmony-input');
- if (type)
+ if (type) {
element.type = type;
+ }
return element;
-};
+}
/**
* @param {string} title
@@ -1227,14 +1326,15 @@ UI.createInput = function(className, type) {
* @param {!Element=} associatedControl
* @return {!Element}
*/
-UI.createLabel = function(title, className, associatedControl) {
+export function createLabel(title, className, associatedControl) {
const element = createElementWithClass('label', className || '');
element.textContent = title;
- if (associatedControl)
+ if (associatedControl) {
UI.ARIAUtils.bindLabelToControl(element, associatedControl);
+ }
return element;
-};
+}
/**
* @param {string} name
@@ -1242,25 +1342,25 @@ UI.createLabel = function(title, className, associatedControl) {
* @param {boolean=} checked
* @return {!Element}
*/
-UI.createRadioLabel = function(name, title, checked) {
+export function createRadioLabel(name, title, checked) {
const element = createElement('span', 'dt-radio');
element.radioElement.name = name;
element.radioElement.checked = !!checked;
element.labelElement.createTextChild(title);
return element;
-};
+}
/**
* @param {string} title
* @param {string} iconClass
* @return {!Element}
*/
-UI.createIconLabel = function(title, iconClass) {
+export function createIconLabel(title, iconClass) {
const element = createElement('span', 'dt-icon-label');
element.createChild('span').textContent = title;
element.type = iconClass;
return element;
-};
+}
/**
* @return {!Element}
@@ -1268,39 +1368,38 @@ UI.createIconLabel = function(title, iconClass) {
* @param {number} max
* @param {number} tabIndex
*/
-UI.createSlider = function(min, max, tabIndex) {
+export function createSlider(min, max, tabIndex) {
const element = createElement('span', 'dt-slider');
element.sliderElement.min = min;
element.sliderElement.max = max;
element.sliderElement.step = 1;
element.sliderElement.tabIndex = tabIndex;
return element;
-};
+}
/**
* @param {!Node} node
* @param {string} cssFile
* @suppressGlobalPropertiesCheck
*/
-UI.appendStyle = function(node, cssFile) {
- const content = Runtime.cachedResources[cssFile] || '';
- if (!content)
+export function appendStyle(node, cssFile) {
+ const content = Root.Runtime.cachedResources[cssFile] || '';
+ if (!content) {
console.error(cssFile + ' not preloaded. Check module.json');
+ }
let styleElement = createElement('style');
- styleElement.type = 'text/css';
styleElement.textContent = content;
node.appendChild(styleElement);
const themeStyleSheet = UI.themeSupport.themeStyleSheet(cssFile, content);
if (themeStyleSheet) {
styleElement = createElement('style');
- styleElement.type = 'text/css';
- styleElement.textContent = themeStyleSheet + '\n' + Runtime.resolveSourceURL(cssFile + '.theme');
+ styleElement.textContent = themeStyleSheet + '\n' + Root.Runtime.resolveSourceURL(cssFile + '.theme');
node.appendChild(styleElement);
}
-};
+}
-UI.CheckboxLabel = class extends HTMLSpanElement {
+export class CheckboxLabel extends HTMLSpanElement {
constructor() {
super();
/** @type {!DocumentFragment} */
@@ -1309,9 +1408,9 @@ UI.CheckboxLabel = class extends HTMLSpanElement {
this.checkboxElement;
/** @type {!Element} */
this.textElement;
- UI.CheckboxLabel._lastId = (UI.CheckboxLabel._lastId || 0) + 1;
- const id = 'ui-checkbox-label' + UI.CheckboxLabel._lastId;
- this._shadowRoot = UI.createShadowRootWithCoreStyles(this, 'ui/checkboxTextLabel.css');
+ CheckboxLabel._lastId = (CheckboxLabel._lastId || 0) + 1;
+ const id = 'ui-checkbox-label' + CheckboxLabel._lastId;
+ this._shadowRoot = createShadowRootWithCoreStyles(this, 'ui/checkboxTextLabel.css');
this.checkboxElement = /** @type {!HTMLInputElement} */ (this._shadowRoot.createChild('input'));
this.checkboxElement.type = 'checkbox';
this.checkboxElement.setAttribute('id', id);
@@ -1324,17 +1423,19 @@ UI.CheckboxLabel = class extends HTMLSpanElement {
* @param {string=} title
* @param {boolean=} checked
* @param {string=} subtitle
- * @return {!UI.CheckboxLabel}
+ * @return {!CheckboxLabel}
*/
static create(title, checked, subtitle) {
- if (!UI.CheckboxLabel._constructor)
- UI.CheckboxLabel._constructor = UI.registerCustomElement('span', 'dt-checkbox', UI.CheckboxLabel);
- const element = /** @type {!UI.CheckboxLabel} */ (UI.CheckboxLabel._constructor());
+ if (!CheckboxLabel._constructor) {
+ CheckboxLabel._constructor = registerCustomElement('span', 'dt-checkbox', CheckboxLabel);
+ }
+ const element = /** @type {!CheckboxLabel} */ (CheckboxLabel._constructor());
element.checkboxElement.checked = !!checked;
if (title !== undefined) {
element.textElement.textContent = title;
- if (subtitle !== undefined)
+ if (subtitle !== undefined) {
element.textElement.createChild('div', 'dt-checkbox-subtitle').textContent = subtitle;
+ }
}
return element;
}
@@ -1367,11 +1468,11 @@ UI.CheckboxLabel = class extends HTMLSpanElement {
this.checkboxElement.classList.add('dt-checkbox-themed');
this.checkboxElement.style.borderColor = color;
}
-};
+}
(function() {
let labelId = 0;
-UI.registerCustomElement('span', 'dt-radio', class extends HTMLSpanElement {
+registerCustomElement('span', 'dt-radio', class extends HTMLSpanElement {
constructor() {
super();
this.radioElement = this.createChild('input', 'dt-radio-button');
@@ -1381,7 +1482,7 @@ UI.registerCustomElement('span', 'dt-radio', class extends HTMLSpanElement {
this.radioElement.id = id;
this.radioElement.type = 'radio';
this.labelElement.htmlFor = id;
- const root = UI.createShadowRootWithCoreStyles(this, 'ui/radioButton.css');
+ const root = createShadowRootWithCoreStyles(this, 'ui/radioButton.css');
root.createChild('slot');
this.addEventListener('click', radioClickHandler, false);
}
@@ -1393,16 +1494,17 @@ UI.registerCustomElement('span', 'dt-radio', class extends HTMLSpanElement {
* @this {Element}
*/
function radioClickHandler(event) {
- if (this.radioElement.checked || this.radioElement.disabled)
+ if (this.radioElement.checked || this.radioElement.disabled) {
return;
+ }
this.radioElement.checked = true;
this.radioElement.dispatchEvent(new Event('change'));
}
-UI.registerCustomElement('span', 'dt-icon-label', class extends HTMLSpanElement {
+registerCustomElement('span', 'dt-icon-label', class extends HTMLSpanElement {
constructor() {
super();
- const root = UI.createShadowRootWithCoreStyles(this);
+ const root = createShadowRootWithCoreStyles(this);
this._iconElement = UI.Icon.create();
this._iconElement.style.setProperty('margin-right', '4px');
root.appendChild(this._iconElement);
@@ -1418,10 +1520,10 @@ UI.registerCustomElement('span', 'dt-icon-label', class extends HTMLSpanElement
}
});
-UI.registerCustomElement('span', 'dt-slider', class extends HTMLSpanElement {
+registerCustomElement('span', 'dt-slider', class extends HTMLSpanElement {
constructor() {
super();
- const root = UI.createShadowRootWithCoreStyles(this, 'ui/slider.css');
+ const root = createShadowRootWithCoreStyles(this, 'ui/slider.css');
this.sliderElement = createElementWithClass('input', 'dt-range-input');
this.sliderElement.type = 'range';
root.appendChild(this.sliderElement);
@@ -1443,10 +1545,10 @@ UI.registerCustomElement('span', 'dt-slider', class extends HTMLSpanElement {
}
});
-UI.registerCustomElement('span', 'dt-small-bubble', class extends HTMLSpanElement {
+registerCustomElement('span', 'dt-small-bubble', class extends HTMLSpanElement {
constructor() {
super();
- const root = UI.createShadowRootWithCoreStyles(this, 'ui/smallBubble.css');
+ const root = createShadowRootWithCoreStyles(this, 'ui/smallBubble.css');
this._textElement = root.createChild('div');
this._textElement.className = 'info';
this._textElement.createChild('slot');
@@ -1461,10 +1563,10 @@ UI.registerCustomElement('span', 'dt-small-bubble', class extends HTMLSpanElemen
}
});
-UI.registerCustomElement('div', 'dt-close-button', class extends HTMLDivElement {
+registerCustomElement('div', 'dt-close-button', class extends HTMLDivElement {
constructor() {
super();
- const root = UI.createShadowRootWithCoreStyles(this, 'ui/closeButton.css');
+ const root = createShadowRootWithCoreStyles(this, 'ui/closeButton.css');
this._buttonElement = root.createChild('div', 'close-button');
UI.ARIAUtils.setAccessibleName(this._buttonElement, ls`Close`);
UI.ARIAUtils.markAsButton(this._buttonElement);
@@ -1497,6 +1599,18 @@ UI.registerCustomElement('div', 'dt-close-button', class extends HTMLDivElement
setAccessibleName(name) {
UI.ARIAUtils.setAccessibleName(this._buttonElement, name);
}
+
+ /**
+ * @param {boolean} tabbable
+ * @this {Element}
+ */
+ setTabbable(tabbable) {
+ if (tabbable) {
+ this._buttonElement.tabIndex = 0;
+ } else {
+ this._buttonElement.tabIndex = -1;
+ }
+ }
});
})();
@@ -1508,7 +1622,7 @@ UI.registerCustomElement('div', 'dt-close-button', class extends HTMLDivElement
* @param {number=} modifierMultiplier
* @return {function(string)}
*/
-UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) {
+export function bindInput(input, apply, validate, numeric, modifierMultiplier) {
input.addEventListener('change', onChange, false);
input.addEventListener('input', onInput, false);
input.addEventListener('keydown', onKeyDown, false);
@@ -1521,8 +1635,9 @@ UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) {
function onChange() {
const {valid} = validate(input.value);
input.classList.toggle('error-input', !valid);
- if (valid)
+ if (valid) {
apply(input.value);
+ }
}
/**
@@ -1531,20 +1646,23 @@ UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) {
function onKeyDown(event) {
if (isEnterKey(event)) {
const {valid} = validate(input.value);
- if (valid)
+ if (valid) {
apply(input.value);
+ }
event.preventDefault();
return;
}
- if (!numeric)
+ if (!numeric) {
return;
+ }
- const value = UI._modifiedFloatNumber(parseFloat(input.value), event, modifierMultiplier);
+ const value = _modifiedFloatNumber(parseFloat(input.value), event, modifierMultiplier);
const stringValue = value ? String(value) : '';
const {valid} = validate(stringValue);
- if (!valid || !value)
+ if (!valid || !value) {
return;
+ }
input.value = stringValue;
apply(input.value);
@@ -1555,15 +1673,16 @@ UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) {
* @param {string} value
*/
function setValue(value) {
- if (value === input.value)
+ if (value === input.value) {
return;
+ }
const {valid} = validate(value);
input.classList.toggle('error-input', !valid);
input.value = value;
}
return setValue;
-};
+}
/**
* @param {!CanvasRenderingContext2D} context
@@ -1572,15 +1691,18 @@ UI.bindInput = function(input, apply, validate, numeric, modifierMultiplier) {
* @param {function(string, number):string} trimFunction
* @return {string}
*/
-UI.trimText = function(context, text, maxWidth, trimFunction) {
+export function trimText(context, text, maxWidth, trimFunction) {
const maxLength = 200;
- if (maxWidth <= 10)
+ if (maxWidth <= 10) {
return '';
- if (text.length > maxLength)
+ }
+ if (text.length > maxLength) {
text = trimFunction(text, maxLength);
- const textWidth = UI.measureTextWidth(context, text);
- if (textWidth <= maxWidth)
+ }
+ const textWidth = measureTextWidth(context, text);
+ if (textWidth <= maxWidth) {
return text;
+ }
let l = 0;
let r = text.length;
@@ -1588,7 +1710,7 @@ UI.trimText = function(context, text, maxWidth, trimFunction) {
let rv = textWidth;
while (l < r && lv !== rv && lv !== maxWidth) {
const m = Math.ceil(l + (r - l) * (maxWidth - lv) / (rv - lv));
- const mv = UI.measureTextWidth(context, trimFunction(text, m));
+ const mv = measureTextWidth(context, trimFunction(text, m));
if (mv <= maxWidth) {
l = m;
lv = mv;
@@ -1599,7 +1721,7 @@ UI.trimText = function(context, text, maxWidth, trimFunction) {
}
text = trimFunction(text, l);
return text !== '\u2026' ? text : '';
-};
+}
/**
* @param {!CanvasRenderingContext2D} context
@@ -1607,9 +1729,9 @@ UI.trimText = function(context, text, maxWidth, trimFunction) {
* @param {number} maxWidth
* @return {string}
*/
-UI.trimTextMiddle = function(context, text, maxWidth) {
- return UI.trimText(context, text, maxWidth, (text, width) => text.trimMiddle(width));
-};
+export function trimTextMiddle(context, text, maxWidth) {
+ return trimText(context, text, maxWidth, (text, width) => text.trimMiddle(width));
+}
/**
* @param {!CanvasRenderingContext2D} context
@@ -1617,24 +1739,25 @@ UI.trimTextMiddle = function(context, text, maxWidth) {
* @param {number} maxWidth
* @return {string}
*/
-UI.trimTextEnd = function(context, text, maxWidth) {
- return UI.trimText(context, text, maxWidth, (text, width) => text.trimEnd(width));
-};
+export function trimTextEnd(context, text, maxWidth) {
+ return trimText(context, text, maxWidth, (text, width) => text.trimEndWithMaxLength(width));
+}
/**
* @param {!CanvasRenderingContext2D} context
* @param {string} text
* @return {number}
*/
-UI.measureTextWidth = function(context, text) {
+export function measureTextWidth(context, text) {
const maxCacheableLength = 200;
- if (text.length > maxCacheableLength)
+ if (text.length > maxCacheableLength) {
return context.measureText(text).width;
+ }
- let widthCache = UI.measureTextWidth._textWidthCache;
+ let widthCache = measureTextWidth._textWidthCache;
if (!widthCache) {
widthCache = new Map();
- UI.measureTextWidth._textWidthCache = widthCache;
+ measureTextWidth._textWidthCache = widthCache;
}
const font = context.font;
let textWidths = widthCache.get(font);
@@ -1648,12 +1771,12 @@ UI.measureTextWidth = function(context, text) {
textWidths.set(text, width);
}
return width;
-};
+}
/**
* @unrestricted
*/
-UI.ThemeSupport = class {
+export class ThemeSupport {
/**
* @param {!Common.Setting} setting
*/
@@ -1690,9 +1813,10 @@ UI.ThemeSupport = class {
*/
injectHighlightStyleSheets(element) {
this._injectingStyleSheet = true;
- UI.appendStyle(element, 'ui/inspectorSyntaxHighlight.css');
- if (this._themeName === 'dark')
- UI.appendStyle(element, 'ui/inspectorSyntaxHighlightDark.css');
+ appendStyle(element, 'ui/inspectorSyntaxHighlight.css');
+ if (this._themeName === 'dark') {
+ appendStyle(element, 'ui/inspectorSyntaxHighlightDark.css');
+ }
this._injectingStyleSheet = false;
}
@@ -1702,7 +1826,6 @@ UI.ThemeSupport = class {
injectCustomStyleSheets(element) {
for (const sheet of this._customSheets){
const styleElement = createElement('style');
- styleElement.type = 'text/css';
styleElement.textContent = sheet;
element.appendChild(styleElement);
}
@@ -1719,20 +1842,22 @@ UI.ThemeSupport = class {
* @param {!Document} document
*/
applyTheme(document) {
- if (!this.hasTheme())
+ if (!this.hasTheme()) {
return;
+ }
- if (this._themeName === 'dark')
+ if (this._themeName === 'dark') {
document.documentElement.classList.add('-theme-with-dark-background');
+ }
const styleSheets = document.styleSheets;
const result = [];
- for (let i = 0; i < styleSheets.length; ++i)
+ for (let i = 0; i < styleSheets.length; ++i) {
result.push(this._patchForTheme(styleSheets[i].href, styleSheets[i]));
+ }
result.push('/*# sourceURL=inspector.css.theme */');
const styleElement = createElement('style');
- styleElement.type = 'text/css';
styleElement.textContent = result.join('\n');
document.head.appendChild(styleElement);
}
@@ -1744,13 +1869,13 @@ UI.ThemeSupport = class {
* @suppressGlobalPropertiesCheck
*/
themeStyleSheet(id, text) {
- if (!this.hasTheme() || this._injectingStyleSheet)
+ if (!this.hasTheme() || this._injectingStyleSheet) {
return '';
+ }
let patch = this._cachedThemePatches.get(id);
if (!patch) {
const styleElement = createElement('style');
- styleElement.type = 'text/css';
styleElement.textContent = text;
document.body.appendChild(styleElement);
patch = this._patchForTheme(id, styleElement.sheet);
@@ -1766,8 +1891,9 @@ UI.ThemeSupport = class {
*/
_patchForTheme(id, styleSheet) {
const cached = this._cachedThemePatches.get(id);
- if (cached)
+ if (cached) {
return cached;
+ }
try {
const rules = styleSheet.cssRules;
@@ -1780,10 +1906,12 @@ UI.ThemeSupport = class {
const output = [];
const style = rules[j].style;
const selectorText = rules[j].selectorText;
- for (let i = 0; style && i < style.length; ++i)
+ for (let i = 0; style && i < style.length; ++i) {
this._patchProperty(selectorText, style, style[i], output);
- if (output.length)
+ }
+ if (output.length) {
result.push(rules[j].selectorText + '{' + output.join('') + '}');
+ }
}
const fullText = result.join('\n');
@@ -1806,53 +1934,63 @@ UI.ThemeSupport = class {
* - One can create specializations for dark themes via body.-theme-with-dark-background selector in host context.
*/
_patchProperty(selectorText, style, name, output) {
- if (!this._themableProperties.has(name))
+ if (!this._themableProperties.has(name)) {
return;
+ }
const value = style.getPropertyValue(name);
- if (!value || value === 'none' || value === 'inherit' || value === 'initial' || value === 'transparent')
+ if (!value || value === 'none' || value === 'inherit' || value === 'initial' || value === 'transparent') {
return;
- if (name === 'background-image' && value.indexOf('gradient') === -1)
+ }
+ if (name === 'background-image' && value.indexOf('gradient') === -1) {
return;
+ }
- if (selectorText.indexOf('-theme-') !== -1)
+ if (selectorText.indexOf('-theme-') !== -1) {
return;
+ }
- let colorUsage = UI.ThemeSupport.ColorUsage.Unknown;
- if (name.indexOf('background') === 0 || name.indexOf('border') === 0)
- colorUsage |= UI.ThemeSupport.ColorUsage.Background;
- if (name.indexOf('background') === -1)
- colorUsage |= UI.ThemeSupport.ColorUsage.Foreground;
+ let colorUsage = ThemeSupport.ColorUsage.Unknown;
+ if (name.indexOf('background') === 0 || name.indexOf('border') === 0) {
+ colorUsage |= ThemeSupport.ColorUsage.Background;
+ }
+ if (name.indexOf('background') === -1) {
+ colorUsage |= ThemeSupport.ColorUsage.Foreground;
+ }
output.push(name);
output.push(':');
const items = value.replace(Common.Color.Regex, '\0$1\0').split('\0');
- for (let i = 0; i < items.length; ++i)
- output.push(this.patchColorText(items[i], colorUsage));
- if (style.getPropertyPriority(name))
+ for (let i = 0; i < items.length; ++i) {
+ output.push(this.patchColorText(items[i], /** @type {!ThemeSupport.ColorUsage} */ (colorUsage)));
+ }
+ if (style.getPropertyPriority(name)) {
output.push(' !important');
+ }
output.push(';');
}
/**
* @param {string} text
- * @param {!UI.ThemeSupport.ColorUsage} colorUsage
+ * @param {!ThemeSupport.ColorUsage} colorUsage
* @return {string}
*/
patchColorText(text, colorUsage) {
const color = Common.Color.parse(text);
- if (!color)
+ if (!color) {
return text;
+ }
const outColor = this.patchColor(color, colorUsage);
let outText = outColor.asString(null);
- if (!outText)
+ if (!outText) {
outText = outColor.asString(outColor.hasAlpha() ? Common.Color.Format.RGBA : Common.Color.Format.RGB);
+ }
return outText || text;
}
/**
* @param {!Common.Color} color
- * @param {!UI.ThemeSupport.ColorUsage} colorUsage
+ * @param {!ThemeSupport.ColorUsage} colorUsage
* @return {!Common.Color}
*/
patchColor(color, colorUsage) {
@@ -1865,7 +2003,7 @@ UI.ThemeSupport = class {
/**
* @param {!Array<number>} hsla
- * @param {!UI.ThemeSupport.ColorUsage} colorUsage
+ * @param {!ThemeSupport.ColorUsage} colorUsage
*/
_patchHSLA(hsla, colorUsage) {
const hue = hsla[0];
@@ -1875,13 +2013,14 @@ UI.ThemeSupport = class {
switch (this._themeName) {
case 'dark':
- const minCap = colorUsage & UI.ThemeSupport.ColorUsage.Background ? 0.14 : 0;
- const maxCap = colorUsage & UI.ThemeSupport.ColorUsage.Foreground ? 0.9 : 1;
+ const minCap = colorUsage & ThemeSupport.ColorUsage.Background ? 0.14 : 0;
+ const maxCap = colorUsage & ThemeSupport.ColorUsage.Foreground ? 0.9 : 1;
lit = 1 - lit;
- if (lit < minCap * 2)
+ if (lit < minCap * 2) {
lit = minCap + lit / 2;
- else if (lit > 2 * maxCap - 1)
+ } else if (lit > 2 * maxCap - 1) {
lit = maxCap - 1 / 2 + lit / 2;
+ }
break;
}
@@ -1890,12 +2029,12 @@ UI.ThemeSupport = class {
hsla[2] = Number.constrain(lit, 0, 1);
hsla[3] = Number.constrain(alpha, 0, 1);
}
-};
+}
/**
* @enum {number}
*/
-UI.ThemeSupport.ColorUsage = {
+ThemeSupport.ColorUsage = {
Unknown: 0,
Foreground: 1 << 0,
Background: 1 << 1,
@@ -1906,39 +2045,36 @@ UI.ThemeSupport.ColorUsage = {
* @param {string} title
* @return {!Element}
*/
-UI.createDocumentationLink = function(article, title) {
+export function createDocumentationLink(article, title) {
return UI.XLink.create('https://developers.google.com/web/tools/chrome-devtools/' + article, title);
-};
+}
/**
* @param {string} url
* @return {!Promise<?Image>}
*/
-UI.loadImage = function(url) {
+export function loadImage(url) {
return new Promise(fulfill => {
const image = new Image();
image.addEventListener('load', () => fulfill(image));
image.addEventListener('error', () => fulfill(null));
image.src = url;
});
-};
+}
/**
* @param {?string} data
* @return {!Promise<?Image>}
*/
-UI.loadImageFromData = function(data) {
- return data ? UI.loadImage('data:image/jpg;base64,' + data) : Promise.resolve(null);
-};
-
-/** @type {!UI.ThemeSupport} */
-UI.themeSupport;
+export function loadImageFromData(data) {
+ return data ? loadImage('data:image/jpg;base64,' + data) : Promise.resolve(null);
+}
/**
* @param {function(!File)} callback
* @return {!Node}
*/
-UI.createFileSelectorElement = function(callback) {
+export function createFileSelectorElement(callback) {
const fileSelectorElement = createElement('input');
fileSelectorElement.type = 'file';
fileSelectorElement.style.display = 'none';
@@ -1948,15 +2084,15 @@ UI.createFileSelectorElement = function(callback) {
callback(fileSelectorElement.files[0]);
}
return fileSelectorElement;
-};
+}
/**
* @const
* @type {number}
*/
-UI.MaxLengthForDisplayedURLs = 150;
+export const MaxLengthForDisplayedURLs = 150;
-UI.MessageDialog = class {
+export class MessageDialog {
/**
* @param {string} message
* @param {!Document|!Element=} where
@@ -1966,10 +2102,10 @@ UI.MessageDialog = class {
const dialog = new UI.Dialog();
dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
dialog.setDimmed(true);
- const shadowRoot = UI.createShadowRootWithCoreStyles(dialog.contentElement, 'ui/confirmDialog.css');
+ const shadowRoot = createShadowRootWithCoreStyles(dialog.contentElement, 'ui/confirmDialog.css');
const content = shadowRoot.createChild('div', 'widget');
await new Promise(resolve => {
- const okButton = UI.createTextButton(Common.UIString('OK'), resolve, '', true);
+ const okButton = createTextButton(Common.UIString('OK'), resolve, '', true);
content.createChild('div', 'message').createChild('span').textContent = message;
content.createChild('div', 'button').appendChild(okButton);
dialog.setOutsideClickCallback(event => {
@@ -1981,9 +2117,9 @@ UI.MessageDialog = class {
});
dialog.hide();
}
-};
+}
-UI.ConfirmDialog = class {
+export class ConfirmDialog {
/**
* @param {string} message
* @param {!Document|!Element=} where
@@ -1993,13 +2129,13 @@ UI.ConfirmDialog = class {
const dialog = new UI.Dialog();
dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MeasureContent);
dialog.setDimmed(true);
- const shadowRoot = UI.createShadowRootWithCoreStyles(dialog.contentElement, 'ui/confirmDialog.css');
+ const shadowRoot = createShadowRootWithCoreStyles(dialog.contentElement, 'ui/confirmDialog.css');
const content = shadowRoot.createChild('div', 'widget');
content.createChild('div', 'message').createChild('span').textContent = message;
const buttonsBar = content.createChild('div', 'button');
const result = await new Promise(resolve => {
- buttonsBar.appendChild(UI.createTextButton(Common.UIString('OK'), () => resolve(true), '', true));
- buttonsBar.appendChild(UI.createTextButton(Common.UIString('Cancel'), () => resolve(false)));
+ buttonsBar.appendChild(createTextButton(Common.UIString('OK'), () => resolve(true), '', true));
+ buttonsBar.appendChild(createTextButton(Common.UIString('Cancel'), () => resolve(false)));
dialog.setOutsideClickCallback(event => {
event.consume();
resolve(false);
@@ -2009,31 +2145,32 @@ UI.ConfirmDialog = class {
dialog.hide();
return result;
}
-};
+}
/**
* @param {!UI.ToolbarButton} toolbarButton
* @return {!Element}
*/
-UI.createInlineButton = function(toolbarButton) {
+export function createInlineButton(toolbarButton) {
const element = createElement('span');
- const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'ui/inlineButton.css');
+ const shadowRoot = createShadowRootWithCoreStyles(element, 'ui/inlineButton.css');
element.classList.add('inline-button');
const toolbar = new UI.Toolbar('');
toolbar.appendToolbarItem(toolbarButton);
shadowRoot.appendChild(toolbar.element);
return element;
-};
+}
/**
* @param {string} text
* @param {number} maxLength
* @return {!DocumentFragment}
*/
-UI.createExpandableText = function(text, maxLength) {
+export function createExpandableText(text, maxLength) {
const clickHandler = () => {
- if (expandElement.parentElement)
+ if (expandElement.parentElement) {
expandElement.parentElement.insertBefore(createTextNode(text.slice(maxLength)), expandElement);
+ }
expandElement.remove();
};
const fragment = createDocumentFragment();
@@ -2045,8 +2182,9 @@ UI.createExpandableText = function(text, maxLength) {
expandElement.classList.add('expandable-inline-button');
expandElement.addEventListener('click', clickHandler);
expandElement.addEventListener('keydown', event => {
- if (event.key === 'Enter' || event.key === ' ')
+ if (event.key === 'Enter' || event.key === ' ') {
clickHandler();
+ }
});
UI.ARIAUtils.markAsButton(expandElement);
@@ -2058,51 +2196,49 @@ UI.createExpandableText = function(text, maxLength) {
const copyButton = fragment.createChild('span', 'expandable-inline-button');
copyButton.setAttribute('data-text', ls`Copy`);
copyButton.addEventListener('click', () => {
- InspectorFrontendHost.copyText(text);
+ Host.InspectorFrontendHost.copyText(text);
});
copyButton.addEventListener('keydown', event => {
- if (event.key === 'Enter' || event.key === ' ')
- InspectorFrontendHost.copyText(text);
+ if (event.key === 'Enter' || event.key === ' ') {
+ Host.InspectorFrontendHost.copyText(text);
+ }
});
UI.ARIAUtils.markAsButton(copyButton);
return fragment;
-};
+}
/**
* @interface
*/
-UI.Renderer = function() {};
-
-UI.Renderer.prototype = {
+export class Renderer {
/**
* @param {!Object} object
* @param {!UI.Renderer.Options=} options
* @return {!Promise<?{node: !Node, tree: ?UI.TreeOutline}>}
*/
- render(object, options) {}
-};
+ render(object, options) {
+ }
+}
/**
- * @param {?Object} object
- * @param {!UI.Renderer.Options=} options
- * @return {!Promise<?{node: !Node, tree: ?UI.TreeOutline}>}
- */
-UI.Renderer.render = async function(object, options) {
- if (!object)
+ * @param {!Object} object
+ * @param {!UI.Renderer.Options=} options
+ * @return {!Promise<?{node: !Node, tree: ?UI.TreeOutline}>}
+ */
+Renderer.render = async function(object, options) {
+ if (!object) {
throw new Error('Can\'t render ' + object);
- const renderer = await self.runtime.extension(UI.Renderer, object).instance();
+ }
+ const renderer = await self.runtime.extension(Renderer, object).instance();
return renderer ? renderer.render(object, options || {}) : null;
};
-/** @typedef {!{title: (string|!Element|undefined), editable: (boolean|undefined) }} */
-UI.Renderer.Options;
-
/**
* @param {number} timestamp
* @param {boolean} full
* @return {string}
*/
-UI.formatTimestamp = function(timestamp, full) {
+export function formatTimestamp(timestamp, full) {
const date = new Date(timestamp);
const yymmdd = date.getFullYear() + '-' + leadZero(date.getMonth() + 1, 2) + '-' + leadZero(date.getDate(), 2);
const hhmmssfff = leadZero(date.getHours(), 2) + ':' + leadZero(date.getMinutes(), 2) + ':' +
@@ -2115,8 +2251,110 @@ UI.formatTimestamp = function(timestamp, full) {
* @return {string}
*/
function leadZero(value, length) {
- const valueString = value.toString();
- const padding = length - valueString.length;
- return padding <= 0 ? valueString : '0'.repeat(padding) + valueString;
+ const valueString = String(value);
+ return valueString.padStart(length, '0');
}
-};
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @type {?ThemeSupport} */
+UI.themeSupport;
+
+UI.highlightedSearchResultClassName = highlightedSearchResultClassName;
+UI.highlightedCurrentSearchResultClassName = highlightedCurrentSearchResultClassName;
+UI._numberRegex = _numberRegex;
+UI.StyleValueDelimiters = StyleValueDelimiters;
+UI._coalescingLevel = _coalescingLevel;
+UI._postUpdateHandlers = _postUpdateHandlers;
+UI.MaxLengthForDisplayedURLs = MaxLengthForDisplayedURLs;
+
+/** @constructor */
+UI.ElementFocusRestorer = ElementFocusRestorer;
+
+/** @constructor */
+UI.DragHandler = DragHandler;
+
+/** @constructor */
+UI.InvokeOnceHandlers = InvokeOnceHandlers;
+
+/** @constructor */
+UI.LongClickController = LongClickController;
+
+/** @constructor */
+UI.ThemeSupport = ThemeSupport;
+
+/** @constructor */
+UI.MessageDialog = MessageDialog;
+
+/** @constructor */
+UI.ConfirmDialog = ConfirmDialog;
+
+/** @constructor */
+UI.CheckboxLabel = CheckboxLabel;
+
+/** @interface */
+UI.Renderer = Renderer;
+
+/** @typedef {!{title: (string|!Element|undefined), editable: (boolean|undefined) }} */
+UI.Renderer.Options;
+
+UI.installDragHandle = installDragHandle;
+UI.elementDragStart = elementDragStart;
+UI.isBeingEdited = isBeingEdited;
+UI.isEditing = isEditing;
+UI.markBeingEdited = markBeingEdited;
+UI._valueModificationDirection = _valueModificationDirection;
+UI._modifiedHexValue = _modifiedHexValue;
+UI._modifiedFloatNumber = _modifiedFloatNumber;
+UI.createReplacementString = createReplacementString;
+UI.handleElementValueModifications = handleElementValueModifications;
+UI.formatLocalized = formatLocalized;
+UI.openLinkExternallyLabel = openLinkExternallyLabel;
+UI.copyLinkAddressLabel = copyLinkAddressLabel;
+UI.anotherProfilerActiveLabel = anotherProfilerActiveLabel;
+UI.asyncStackTraceLabel = asyncStackTraceLabel;
+UI.installComponentRootStyles = installComponentRootStyles;
+UI.measuredScrollbarWidth = measuredScrollbarWidth;
+UI.createShadowRootWithCoreStyles = createShadowRootWithCoreStyles;
+UI._injectCoreStyles = _injectCoreStyles;
+UI._windowFocused = _windowFocused;
+UI._windowBlurred = _windowBlurred;
+UI._focusChanged = _focusChanged;
+UI.highlightSearchResult = highlightSearchResult;
+UI.highlightSearchResults = highlightSearchResults;
+UI.runCSSAnimationOnce = runCSSAnimationOnce;
+UI.highlightRangesWithStyleClass = highlightRangesWithStyleClass;
+UI.applyDomChanges = applyDomChanges;
+UI.revertDomChanges = revertDomChanges;
+UI.measurePreferredSize = measurePreferredSize;
+UI.startBatchUpdate = startBatchUpdate;
+UI.endBatchUpdate = endBatchUpdate;
+UI.invokeOnceAfterBatchUpdate = invokeOnceAfterBatchUpdate;
+UI.animateFunction = animateFunction;
+UI.initializeUIUtils = initializeUIUtils;
+UI.beautifyFunctionName = beautifyFunctionName;
+UI.registerCustomElement = registerCustomElement;
+UI.createTextButton = createTextButton;
+UI.createInput = createInput;
+UI.createLabel = createLabel;
+UI.createRadioLabel = createRadioLabel;
+UI.createIconLabel = createIconLabel;
+UI.createSlider = createSlider;
+UI.appendStyle = appendStyle;
+UI.bindInput = bindInput;
+UI.trimText = trimText;
+UI.trimTextMiddle = trimTextMiddle;
+UI.trimTextEnd = trimTextEnd;
+UI.measureTextWidth = measureTextWidth;
+UI.createDocumentationLink = createDocumentationLink;
+UI.loadImage = loadImage;
+UI.loadImageFromData = loadImageFromData;
+UI.createFileSelectorElement = createFileSelectorElement;
+UI.createInlineButton = createInlineButton;
+UI.createExpandableText = createExpandableText;
+UI.formatTimestamp = formatTimestamp;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
index 4dbf3413642..3fba1c27ca9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
@@ -1,53 +1,61 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
/**
* @interface
*/
-UI.View = function() {};
-
-UI.View.prototype = {
+export default class View {
/**
* @return {string}
*/
- viewId() {},
+ viewId() {
+ }
/**
* @return {string}
*/
- title() {},
+ title() {
+ }
/**
* @return {boolean}
*/
- isCloseable() {},
+ isCloseable() {
+ }
/**
* @return {boolean}
*/
- isTransient() {},
+ isTransient() {
+ }
/**
* @return {!Promise<!Array<!UI.ToolbarItem>>}
*/
- toolbarItems() {},
+ toolbarItems() {
+ }
/**
* @return {!Promise<!UI.Widget>}
*/
- widget() {},
+ widget() {
+ }
+ /**
+ * @return {!Promise|undefined}
+ */
disposeView() {}
-};
+}
-UI.View._symbol = Symbol('view');
-UI.View._widgetSymbol = Symbol('widget');
+export const _symbol = Symbol('view');
+export const _widgetSymbol = Symbol('widget');
/**
- * @implements {UI.View}
+ * @implements {View}
* @unrestricted
*/
-UI.SimpleView = class extends UI.VBox {
+export class SimpleView extends UI.VBox {
/**
* @param {string} title
* @param {boolean=} isWebComponent
@@ -57,7 +65,7 @@ UI.SimpleView = class extends UI.VBox {
this._title = title;
/** @type {!Array<!UI.ToolbarItem>} */
this._toolbarItems = [];
- this[UI.View._symbol] = this;
+ this[_symbol] = this;
}
/**
@@ -134,15 +142,15 @@ UI.SimpleView = class extends UI.VBox {
*/
disposeView() {
}
-};
+}
/**
- * @implements {UI.View}
+ * @implements {View}
* @unrestricted
*/
-UI.ProvidedView = class {
+export class ProvidedView {
/**
- * @param {!Runtime.Extension} extension
+ * @param {!Root.Runtime.Extension} extension
*/
constructor(extension) {
this._extension = extension;
@@ -191,8 +199,9 @@ UI.ProvidedView = class {
return Promise.resolve(result);
}
- if (this._extension.descriptor()['hasToolbar'])
+ if (this._extension.descriptor()['hasToolbar']) {
return this.widget().then(widget => /** @type {!UI.ToolbarItem.ItemsProvider} */ (widget).toolbarItems());
+ }
return Promise.resolve([]);
}
@@ -203,9 +212,10 @@ UI.ProvidedView = class {
async widget() {
this._widgetRequested = true;
const widget = await this._extension.instance();
- if (!(widget instanceof UI.Widget))
+ if (!(widget instanceof UI.Widget)) {
throw new Error('view className should point to a UI.Widget');
- widget[UI.View._symbol] = this;
+ }
+ widget[_symbol] = this;
return /** @type {!UI.Widget} */ (widget);
}
@@ -213,728 +223,105 @@ UI.ProvidedView = class {
* @override
*/
async disposeView() {
- if (!this._widgetRequested)
+ if (!this._widgetRequested) {
return;
+ }
const widget = await this.widget();
widget.ownerViewDisposed();
}
-};
+}
/**
* @interface
*/
-UI.ViewLocation = function() {};
-
-UI.ViewLocation.prototype = {
+export class ViewLocation {
/**
* @param {string} locationName
*/
- appendApplicableItems(locationName) {},
-
- /**
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- */
- appendView(view, insertBefore) {},
-
- /**
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- * @param {boolean=} userGesture
- * @return {!Promise}
- */
- showView(view, insertBefore, userGesture) {},
-
- /**
- * @param {!UI.View} view
- */
- removeView(view) {},
-
- /**
- * @return {!UI.Widget}
- */
- widget() {}
-};
-
-/**
- * @interface
- * @extends {UI.ViewLocation}
- */
-UI.TabbedViewLocation = function() {};
-
-UI.TabbedViewLocation.prototype = {
- /**
- * @return {!UI.TabbedPane}
- */
- tabbedPane() {},
-
- /**
- * @return {!UI.ToolbarMenuButton}
- */
- enableMoreTabsButton() {}
-};
-
-/**
- * @interface
- */
-UI.ViewLocationResolver = function() {};
-
-UI.ViewLocationResolver.prototype = {
- /**
- * @param {string} location
- * @return {?UI.ViewLocation}
- */
- resolveLocation(location) {}
-};
-
-/**
- * @unrestricted
- */
-UI.ViewManager = class {
- constructor() {
- /** @type {!Map<string, !UI.View>} */
- this._views = new Map();
- /** @type {!Map<string, string>} */
- this._locationNameByViewId = new Map();
-
- for (const extension of self.runtime.extensions('view')) {
- const descriptor = extension.descriptor();
- this._views.set(descriptor['id'], new UI.ProvidedView(extension));
- this._locationNameByViewId.set(descriptor['id'], descriptor['location']);
- }
- }
-
- /**
- * @param {!Element} element
- * @param {!Array<!UI.ToolbarItem>} toolbarItems
- */
- static _populateToolbar(element, toolbarItems) {
- if (!toolbarItems.length)
- return;
- const toolbar = new UI.Toolbar('');
- element.insertBefore(toolbar.element, element.firstChild);
- for (const item of toolbarItems)
- toolbar.appendToolbarItem(item);
- }
-
- /**
- * @param {!UI.View} view
- * @return {!Promise}
- */
- revealView(view) {
- const location = /** @type {?UI.ViewManager._Location} */ (view[UI.ViewManager._Location.symbol]);
- if (!location)
- return Promise.resolve();
- location._reveal();
- return location.showView(view);
- }
-
- /**
- * @param {string} viewId
- * @return {?UI.View}
- */
- view(viewId) {
- return this._views.get(viewId);
+ appendApplicableItems(locationName) {
}
/**
- * @param {string} viewId
- * @return {?UI.Widget}
+ * @param {!View} view
+ * @param {?View=} insertBefore
*/
- materializedWidget(viewId) {
- const view = this.view(viewId);
- return view ? view[UI.View._widgetSymbol] : null;
+ appendView(view, insertBefore) {
}
/**
- * @param {string} viewId
+ * @param {!View} view
+ * @param {?View=} insertBefore
* @param {boolean=} userGesture
- * @param {boolean=} omitFocus
* @return {!Promise}
*/
- showView(viewId, userGesture, omitFocus) {
- const view = this._views.get(viewId);
- if (!view) {
- console.error('Could not find view for id: \'' + viewId + '\' ' + new Error().stack);
- return Promise.resolve();
- }
-
- const locationName = this._locationNameByViewId.get(viewId);
-
- const location = view[UI.ViewManager._Location.symbol];
- if (location) {
- location._reveal();
- return location.showView(view, undefined, userGesture, omitFocus);
- }
-
- return this.resolveLocation(locationName).then(location => {
- if (!location)
- throw new Error('Could not resolve location for view: ' + viewId);
- location._reveal();
- return location.showView(view, undefined, userGesture, omitFocus);
- });
- }
-
- /**
- * @param {string=} location
- * @return {!Promise<?UI.ViewManager._Location>}
- */
- resolveLocation(location) {
- if (!location)
- return /** @type {!Promise<?UI.ViewManager._Location>} */ (Promise.resolve(null));
-
- const resolverExtensions = self.runtime.extensions(UI.ViewLocationResolver)
- .filter(extension => extension.descriptor()['name'] === location);
- if (!resolverExtensions.length)
- throw new Error('Unresolved location: ' + location);
- const resolverExtension = resolverExtensions[0];
- return resolverExtension.instance().then(
- resolver => /** @type {?UI.ViewManager._Location} */ (resolver.resolveLocation(location)));
+ showView(view, insertBefore, userGesture) {
}
/**
- * @param {function()=} revealCallback
- * @param {string=} location
- * @param {boolean=} restoreSelection
- * @param {boolean=} allowReorder
- * @param {?string=} defaultTab
- * @return {!UI.TabbedViewLocation}
- */
- createTabbedLocation(revealCallback, location, restoreSelection, allowReorder, defaultTab) {
- return new UI.ViewManager._TabbedLocation(
- this, revealCallback, location, restoreSelection, allowReorder, defaultTab);
- }
-
- /**
- * @param {function()=} revealCallback
- * @param {string=} location
- * @return {!UI.ViewLocation}
- */
- createStackLocation(revealCallback, location) {
- return new UI.ViewManager._StackLocation(this, revealCallback, location);
- }
-
- /**
- * @param {string} location
- * @return {boolean}
- */
- hasViewsForLocation(location) {
- return !!this._viewsForLocation(location).length;
- }
-
- /**
- * @param {string} location
- * @return {!Array<!UI.View>}
+ * @param {!View} view
*/
- _viewsForLocation(location) {
- const result = [];
- for (const id of this._views.keys()) {
- if (this._locationNameByViewId.get(id) === location)
- result.push(this._views.get(id));
- }
- return result;
- }
-};
-
-
-/**
- * @unrestricted
- */
-UI.ViewManager._ContainerWidget = class extends UI.VBox {
- /**
- * @param {!UI.View} view
- */
- constructor(view) {
- super();
- this.element.classList.add('flex-auto', 'view-container', 'overflow-auto');
- this._view = view;
- this.element.tabIndex = -1;
- this.setDefaultFocusedElement(this.element);
- }
-
- /**
- * @return {!Promise}
- */
- _materialize() {
- if (this._materializePromise)
- return this._materializePromise;
- const promises = [];
- promises.push(this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this.element)));
- promises.push(this._view.widget().then(widget => {
- // Move focus from |this| to loaded |widget| if any.
- const shouldFocus = this.element.hasFocus();
- this.setDefaultFocusedElement(null);
- this._view[UI.View._widgetSymbol] = widget;
- widget.show(this.element);
- if (shouldFocus)
- widget.focus();
- }));
- this._materializePromise = Promise.all(promises);
- return this._materializePromise;
- }
-
- /**
- * @override
- */
- wasShown() {
- this._materialize().then(() => {
- this._wasShownForTest();
- });
- }
-
- _wasShownForTest() {
- // This method is sniffed in tests.
- }
-};
-
-/**
- * @unrestricted
- */
-UI.ViewManager._ExpandableContainerWidget = class extends UI.VBox {
- /**
- * @param {!UI.View} view
- */
- constructor(view) {
- super(true);
- this.element.classList.add('flex-none');
- this.registerRequiredCSS('ui/viewContainers.css');
-
- this._titleElement = createElementWithClass('div', 'expandable-view-title');
- UI.ARIAUtils.markAsLink(this._titleElement);
- this._titleExpandIcon = UI.Icon.create('smallicon-triangle-right', 'title-expand-icon');
- this._titleElement.appendChild(this._titleExpandIcon);
- this._titleElement.createTextChild(view.title());
- this._titleElement.tabIndex = 0;
- this._titleElement.addEventListener('click', this._toggleExpanded.bind(this), false);
- this._titleElement.addEventListener('keydown', this._onTitleKeyDown.bind(this), false);
- this.contentElement.insertBefore(this._titleElement, this.contentElement.firstChild);
-
- this.contentElement.createChild('slot');
- this._view = view;
- view[UI.ViewManager._ExpandableContainerWidget._symbol] = this;
- }
-
- /**
- * @return {!Promise}
- */
- _materialize() {
- if (this._materializePromise)
- return this._materializePromise;
- const promises = [];
- promises.push(
- this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this._titleElement)));
- promises.push(this._view.widget().then(widget => {
- this._widget = widget;
- this._view[UI.View._widgetSymbol] = widget;
- widget.show(this.element);
- }));
- this._materializePromise = Promise.all(promises);
- return this._materializePromise;
- }
-
- /**
- * @return {!Promise}
- */
- _expand() {
- if (this._titleElement.classList.contains('expanded'))
- return this._materialize();
- this._titleElement.classList.add('expanded');
- UI.ARIAUtils.setExpanded(this._titleElement, true);
- this._titleExpandIcon.setIconType('smallicon-triangle-down');
- return this._materialize().then(() => this._widget.show(this.element));
- }
-
- _collapse() {
- if (!this._titleElement.classList.contains('expanded'))
- return;
- this._titleElement.classList.remove('expanded');
- UI.ARIAUtils.setExpanded(this._titleElement, false);
- this._titleExpandIcon.setIconType('smallicon-triangle-right');
- this._materialize().then(() => this._widget.detach());
- }
-
- _toggleExpanded() {
- if (this._titleElement.classList.contains('expanded'))
- this._collapse();
- else
- this._expand();
- }
-
- /**
- * @param {!Event} event
- */
- _onTitleKeyDown(event) {
- if (isEnterOrSpaceKey(event)) {
- this._toggleExpanded();
- } else if (event.key === 'ArrowLeft') {
- this._collapse();
- } else if (event.key === 'ArrowRight') {
- if (!this._titleElement.classList.contains('expanded'))
- this._expand();
- else if (this._widget)
- this._widget.focus();
- }
- }
-};
-
-UI.ViewManager._ExpandableContainerWidget._symbol = Symbol('container');
-
-/**
- * @unrestricted
- */
-UI.ViewManager._Location = class {
- /**
- * @param {!UI.ViewManager} manager
- * @param {!UI.Widget} widget
- * @param {function()=} revealCallback
- */
- constructor(manager, widget, revealCallback) {
- this._manager = manager;
- this._revealCallback = revealCallback;
- this._widget = widget;
+ removeView(view) {
}
/**
* @return {!UI.Widget}
*/
widget() {
- return this._widget;
}
-
- _reveal() {
- if (this._revealCallback)
- this._revealCallback();
- }
-};
-
-UI.ViewManager._Location.symbol = Symbol('location');
+}
/**
- * @implements {UI.TabbedViewLocation}
- * @unrestricted
+ * @interface
*/
-UI.ViewManager._TabbedLocation = class extends UI.ViewManager._Location {
+export class TabbedViewLocation extends ViewLocation {
/**
- * @param {!UI.ViewManager} manager
- * @param {function()=} revealCallback
- * @param {string=} location
- * @param {boolean=} restoreSelection
- * @param {boolean=} allowReorder
- * @param {?string=} defaultTab
- */
- constructor(manager, revealCallback, location, restoreSelection, allowReorder, defaultTab) {
- const tabbedPane = new UI.TabbedPane();
- if (allowReorder)
- tabbedPane.setAllowTabReorder(true);
-
- super(manager, tabbedPane, revealCallback);
- this._tabbedPane = tabbedPane;
- this._allowReorder = allowReorder;
-
- this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this._tabSelected, this);
- this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, this._tabClosed, this);
- this._closeableTabSetting = Common.settings.createSetting(location + '-closeableTabs', {});
- this._tabOrderSetting = Common.settings.createSetting(location + '-tabOrder', {});
- this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabOrderChanged, this._persistTabOrder, this);
- if (restoreSelection)
- this._lastSelectedTabSetting = Common.settings.createSetting(location + '-selectedTab', '');
- this._defaultTab = defaultTab;
-
- /** @type {!Map.<string, !UI.View>} */
- this._views = new Map();
-
- if (location)
- this.appendApplicableItems(location);
- }
-
- /**
- * @override
- * @return {!UI.Widget}
- */
- widget() {
- return this._tabbedPane;
- }
-
- /**
- * @override
* @return {!UI.TabbedPane}
*/
tabbedPane() {
- return this._tabbedPane;
}
/**
- * @override
* @return {!UI.ToolbarMenuButton}
*/
enableMoreTabsButton() {
- const moreTabsButton = new UI.ToolbarMenuButton(this._appendTabsToMenu.bind(this));
- this._tabbedPane.leftToolbar().appendToolbarItem(moreTabsButton);
- this._tabbedPane.disableOverflowMenu();
- return moreTabsButton;
- }
-
- /**
- * @override
- * @param {string} locationName
- */
- appendApplicableItems(locationName) {
- const views = this._manager._viewsForLocation(locationName);
- if (this._allowReorder) {
- let i = 0;
- const persistedOrders = this._tabOrderSetting.get();
- const orders = new Map();
- for (const view of views)
- orders.set(view.viewId(), persistedOrders[view.viewId()] || (++i) * UI.ViewManager._TabbedLocation.orderStep);
- views.sort((a, b) => orders.get(a.viewId()) - orders.get(b.viewId()));
- }
-
- for (const view of views) {
- const id = view.viewId();
- this._views.set(id, view);
- view[UI.ViewManager._Location.symbol] = this;
- if (view.isTransient())
- continue;
- if (!view.isCloseable())
- this._appendTab(view);
- else if (this._closeableTabSetting.get()[id])
- this._appendTab(view);
- }
- if (this._defaultTab && this._tabbedPane.hasTab(this._defaultTab))
- this._tabbedPane.selectTab(this._defaultTab);
- else if (this._lastSelectedTabSetting && this._tabbedPane.hasTab(this._lastSelectedTabSetting.get()))
- this._tabbedPane.selectTab(this._lastSelectedTabSetting.get());
- }
-
- /**
- * @param {!UI.ContextMenu} contextMenu
- */
- _appendTabsToMenu(contextMenu) {
- const views = Array.from(this._views.values());
- views.sort((viewa, viewb) => viewa.title().localeCompare(viewb.title()));
- for (const view of views) {
- const title = Common.UIString(view.title());
- contextMenu.defaultSection().appendItem(title, this.showView.bind(this, view, undefined, true));
- }
- }
-
- /**
- * @param {!UI.View} view
- * @param {number=} index
- */
- _appendTab(view, index) {
- this._tabbedPane.appendTab(
- view.viewId(), view.title(), new UI.ViewManager._ContainerWidget(view), undefined, false,
- view.isCloseable() || view.isTransient(), index);
}
-
- /**
- * @override
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- */
- appendView(view, insertBefore) {
- if (this._tabbedPane.hasTab(view.viewId()))
- return;
- const oldLocation = view[UI.ViewManager._Location.symbol];
- if (oldLocation && oldLocation !== this)
- oldLocation.removeView(view);
- view[UI.ViewManager._Location.symbol] = this;
- this._manager._views.set(view.viewId(), view);
- this._views.set(view.viewId(), view);
- let index = undefined;
- const tabIds = this._tabbedPane.tabIds();
- if (this._allowReorder) {
- const orderSetting = this._tabOrderSetting.get();
- const order = orderSetting[view.viewId()];
- for (let i = 0; order && i < tabIds.length; ++i) {
- if (orderSetting[tabIds[i]] && orderSetting[tabIds[i]] > order) {
- index = i;
- break;
- }
- }
- } else if (insertBefore) {
- for (let i = 0; i < tabIds.length; ++i) {
- if (tabIds[i] === insertBefore.viewId()) {
- index = i;
- break;
- }
- }
- }
- this._appendTab(view, index);
-
- if (view.isCloseable()) {
- const tabs = this._closeableTabSetting.get();
- const tabId = view.viewId();
- if (!tabs[tabId]) {
- tabs[tabId] = true;
- this._closeableTabSetting.set(tabs);
- }
- }
- this._persistTabOrder();
- }
-
- /**
- * @override
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- * @param {boolean=} userGesture
- * @param {boolean=} omitFocus
- * @return {!Promise}
- */
- showView(view, insertBefore, userGesture, omitFocus) {
- this.appendView(view, insertBefore);
- this._tabbedPane.selectTab(view.viewId(), userGesture);
- if (!omitFocus)
- this._tabbedPane.focus();
- const widget = /** @type {!UI.ViewManager._ContainerWidget} */ (this._tabbedPane.tabView(view.viewId()));
- return widget._materialize();
- }
-
- /**
- * @param {!UI.View} view
- * @override
- */
- removeView(view) {
- if (!this._tabbedPane.hasTab(view.viewId()))
- return;
-
- delete view[UI.ViewManager._Location.symbol];
- this._manager._views.delete(view.viewId());
- this._tabbedPane.closeTab(view.viewId());
- this._views.delete(view.viewId());
- }
-
- /**
- * @param {!Common.Event} event
- */
- _tabSelected(event) {
- const tabId = /** @type {string} */ (event.data.tabId);
- if (this._lastSelectedTabSetting && event.data['isUserGesture'])
- this._lastSelectedTabSetting.set(tabId);
- }
-
- /**
- * @param {!Common.Event} event
- */
- _tabClosed(event) {
- const id = /** @type {string} */ (event.data['tabId']);
- const tabs = this._closeableTabSetting.get();
- if (tabs[id]) {
- delete tabs[id];
- this._closeableTabSetting.set(tabs);
- }
- this._views.get(id).disposeView();
- }
-
- _persistTabOrder() {
- const tabIds = this._tabbedPane.tabIds();
- const tabOrders = {};
- for (let i = 0; i < tabIds.length; i++)
- tabOrders[tabIds[i]] = (i + 1) * UI.ViewManager._TabbedLocation.orderStep;
-
- const oldTabOrder = this._tabOrderSetting.get();
- const oldTabArray = Object.keys(oldTabOrder);
- oldTabArray.sort((a, b) => oldTabOrder[a] - oldTabOrder[b]);
- let lastOrder = 0;
- for (const key of oldTabArray) {
- if (key in tabOrders) {
- lastOrder = tabOrders[key];
- continue;
- }
- tabOrders[key] = ++lastOrder;
- }
- this._tabOrderSetting.set(tabOrders);
- }
-};
-
-UI.ViewManager._TabbedLocation.orderStep = 10; // Keep in sync with descriptors.
+}
/**
- * @implements {UI.ViewLocation}
- * @unrestricted
+ * @interface
*/
-UI.ViewManager._StackLocation = class extends UI.ViewManager._Location {
+export class ViewLocationResolver {
/**
- * @param {!UI.ViewManager} manager
- * @param {function()=} revealCallback
- * @param {string=} location
+ * @param {string} location
+ * @return {?ViewLocation}
*/
- constructor(manager, revealCallback, location) {
- const vbox = new UI.VBox();
- super(manager, vbox, revealCallback);
- this._vbox = vbox;
+ resolveLocation(location) {
+ }
+}
- /** @type {!Map<string, !UI.ViewManager._ExpandableContainerWidget>} */
- this._expandableContainers = new Map();
+/* Legacy exported object*/
+self.UI = self.UI || {};
- if (location)
- this.appendApplicableItems(location);
- }
+/* Legacy exported object*/
+UI = UI || {};
- /**
- * @override
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- */
- appendView(view, insertBefore) {
- const oldLocation = view[UI.ViewManager._Location.symbol];
- if (oldLocation && oldLocation !== this)
- oldLocation.removeView(view);
-
- let container = this._expandableContainers.get(view.viewId());
- if (!container) {
- view[UI.ViewManager._Location.symbol] = this;
- this._manager._views.set(view.viewId(), view);
- container = new UI.ViewManager._ExpandableContainerWidget(view);
- let beforeElement = null;
- if (insertBefore) {
- const beforeContainer = insertBefore[UI.ViewManager._ExpandableContainerWidget._symbol];
- beforeElement = beforeContainer ? beforeContainer.element : null;
- }
- container.show(this._vbox.contentElement, beforeElement);
- this._expandableContainers.set(view.viewId(), container);
- }
- }
+/** @interface */
+UI.View = View;
- /**
- * @override
- * @param {!UI.View} view
- * @param {?UI.View=} insertBefore
- * @return {!Promise}
- */
- showView(view, insertBefore) {
- this.appendView(view, insertBefore);
- const container = this._expandableContainers.get(view.viewId());
- return container._expand();
- }
+/** @public */
+UI.View.widgetSymbol = _widgetSymbol;
- /**
- * @param {!UI.View} view
- * @override
- */
- removeView(view) {
- const container = this._expandableContainers.get(view.viewId());
- if (!container)
- return;
+/** @constructor */
+UI.SimpleView = SimpleView;
- container.detach();
- this._expandableContainers.delete(view.viewId());
- delete view[UI.ViewManager._Location.symbol];
- this._manager._views.delete(view.viewId());
- }
+/** @constructor */
+UI.ProvidedView = ProvidedView;
- /**
- * @override
- * @param {string} locationName
- */
- appendApplicableItems(locationName) {
- for (const view of this._manager._viewsForLocation(locationName))
- this.appendView(view);
- }
-};
+/** @interface */
+UI.ViewLocation = ViewLocation;
-/**
- * @type {!UI.ViewManager}
- */
-UI.viewManager;
+/** @interface */
+UI.TabbedViewLocation = TabbedViewLocation;
+
+/** @interface */
+UI.ViewLocationResolver = ViewLocationResolver;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ViewManager.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ViewManager.js
new file mode 100644
index 00000000000..be19b5325a2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ViewManager.js
@@ -0,0 +1,713 @@
+// 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.
+
+/**
+ * @unrestricted
+ */
+export default class ViewManager {
+ constructor() {
+ /** @type {!Map<string, !UI.View>} */
+ this._views = new Map();
+ /** @type {!Map<string, string>} */
+ this._locationNameByViewId = new Map();
+
+ for (const extension of self.runtime.extensions('view')) {
+ const descriptor = extension.descriptor();
+ this._views.set(descriptor['id'], new UI.ProvidedView(extension));
+ this._locationNameByViewId.set(descriptor['id'], descriptor['location']);
+ }
+ }
+
+ /**
+ * @param {!Element} element
+ * @param {!Array<!UI.ToolbarItem>} toolbarItems
+ */
+ static _populateToolbar(element, toolbarItems) {
+ if (!toolbarItems.length) {
+ return;
+ }
+ const toolbar = new UI.Toolbar('');
+ element.insertBefore(toolbar.element, element.firstChild);
+ for (const item of toolbarItems) {
+ toolbar.appendToolbarItem(item);
+ }
+ }
+
+ /**
+ * @param {!UI.View} view
+ * @return {!Promise}
+ */
+ revealView(view) {
+ const location = /** @type {?_Location} */ (view[_Location.symbol]);
+ if (!location) {
+ return Promise.resolve();
+ }
+ location._reveal();
+ return location.showView(view);
+ }
+
+ /**
+ * @param {string} viewId
+ * @return {?UI.View}
+ */
+ view(viewId) {
+ return this._views.get(viewId);
+ }
+
+ /**
+ * @param {string} viewId
+ * @return {?UI.Widget}
+ */
+ materializedWidget(viewId) {
+ const view = this.view(viewId);
+ return view ? view[UI.View.widgetSymbol] : null;
+ }
+
+ /**
+ * @param {string} viewId
+ * @param {boolean=} userGesture
+ * @param {boolean=} omitFocus
+ * @return {!Promise}
+ */
+ showView(viewId, userGesture, omitFocus) {
+ const view = this._views.get(viewId);
+ if (!view) {
+ console.error('Could not find view for id: \'' + viewId + '\' ' + new Error().stack);
+ return Promise.resolve();
+ }
+
+ const locationName = this._locationNameByViewId.get(viewId);
+
+ const location = view[_Location.symbol];
+ if (location) {
+ location._reveal();
+ return location.showView(view, undefined, userGesture, omitFocus);
+ }
+
+ return this.resolveLocation(locationName).then(location => {
+ if (!location) {
+ throw new Error('Could not resolve location for view: ' + viewId);
+ }
+ location._reveal();
+ return location.showView(view, undefined, userGesture, omitFocus);
+ });
+ }
+
+ /**
+ * @param {string=} location
+ * @return {!Promise<?_Location>}
+ */
+ resolveLocation(location) {
+ if (!location) {
+ return /** @type {!Promise<?_Location>} */ (Promise.resolve(null));
+ }
+
+ const resolverExtensions = self.runtime.extensions(UI.ViewLocationResolver)
+ .filter(extension => extension.descriptor()['name'] === location);
+ if (!resolverExtensions.length) {
+ throw new Error('Unresolved location: ' + location);
+ }
+ const resolverExtension = resolverExtensions[0];
+ return resolverExtension.instance().then(
+ resolver => /** @type {?_Location} */ (resolver.resolveLocation(location)));
+ }
+
+ /**
+ * @param {function()=} revealCallback
+ * @param {string=} location
+ * @param {boolean=} restoreSelection
+ * @param {boolean=} allowReorder
+ * @param {?string=} defaultTab
+ * @return {!UI.TabbedViewLocation}
+ */
+ createTabbedLocation(revealCallback, location, restoreSelection, allowReorder, defaultTab) {
+ return new UI.ViewManager._TabbedLocation(
+ this, revealCallback, location, restoreSelection, allowReorder, defaultTab);
+ }
+
+ /**
+ * @param {function()=} revealCallback
+ * @param {string=} location
+ * @return {!UI.ViewLocation}
+ */
+ createStackLocation(revealCallback, location) {
+ return new _StackLocation(this, revealCallback, location);
+ }
+
+ /**
+ * @param {string} location
+ * @return {boolean}
+ */
+ hasViewsForLocation(location) {
+ return !!this._viewsForLocation(location).length;
+ }
+
+ /**
+ * @param {string} location
+ * @return {!Array<!UI.View>}
+ */
+ _viewsForLocation(location) {
+ const result = [];
+ for (const id of this._views.keys()) {
+ if (this._locationNameByViewId.get(id) === location) {
+ result.push(this._views.get(id));
+ }
+ }
+ return result;
+ }
+}
+
+
+/**
+ * @unrestricted
+ */
+export class _ContainerWidget extends UI.VBox {
+ /**
+ * @param {!UI.View} view
+ */
+ constructor(view) {
+ super();
+ this.element.classList.add('flex-auto', 'view-container', 'overflow-auto');
+ this._view = view;
+ this.element.tabIndex = -1;
+ this.setDefaultFocusedElement(this.element);
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ _materialize() {
+ if (this._materializePromise) {
+ return this._materializePromise;
+ }
+ const promises = [];
+ // TODO(crbug.com/1006759): Transform to async-await
+ promises.push(this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this.element)));
+ promises.push(this._view.widget().then(widget => {
+ // Move focus from |this| to loaded |widget| if any.
+ const shouldFocus = this.element.hasFocus();
+ this.setDefaultFocusedElement(null);
+ this._view[UI.View.widgetSymbol] = widget;
+ widget.show(this.element);
+ if (shouldFocus) {
+ widget.focus();
+ }
+ }));
+ this._materializePromise = Promise.all(promises);
+ return this._materializePromise;
+ }
+
+ /**
+ * @override
+ */
+ wasShown() {
+ this._materialize().then(() => {
+ this._wasShownForTest();
+ });
+ }
+
+ _wasShownForTest() {
+ // This method is sniffed in tests.
+ }
+}
+
+/**
+ * @unrestricted
+ */
+export class _ExpandableContainerWidget extends UI.VBox {
+ /**
+ * @param {!UI.View} view
+ */
+ constructor(view) {
+ super(true);
+ this.element.classList.add('flex-none');
+ this.registerRequiredCSS('ui/viewContainers.css');
+
+ this._titleElement = createElementWithClass('div', 'expandable-view-title');
+ UI.ARIAUtils.markAsLink(this._titleElement);
+ this._titleExpandIcon = UI.Icon.create('smallicon-triangle-right', 'title-expand-icon');
+ this._titleElement.appendChild(this._titleExpandIcon);
+ this._titleElement.createTextChild(view.title());
+ this._titleElement.tabIndex = 0;
+ this._titleElement.addEventListener('click', this._toggleExpanded.bind(this), false);
+ this._titleElement.addEventListener('keydown', this._onTitleKeyDown.bind(this), false);
+ this.contentElement.insertBefore(this._titleElement, this.contentElement.firstChild);
+
+ this.contentElement.createChild('slot');
+ this._view = view;
+ view[UI.ViewManager._ExpandableContainerWidget._symbol] = this;
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ _materialize() {
+ if (this._materializePromise) {
+ return this._materializePromise;
+ }
+ // TODO(crbug.com/1006759): Transform to async-await
+ const promises = [];
+ promises.push(
+ this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this._titleElement)));
+ promises.push(this._view.widget().then(widget => {
+ this._widget = widget;
+ this._view[UI.View.widgetSymbol] = widget;
+ widget.show(this.element);
+ }));
+ this._materializePromise = Promise.all(promises);
+ return this._materializePromise;
+ }
+
+ /**
+ * @return {!Promise}
+ */
+ _expand() {
+ if (this._titleElement.classList.contains('expanded')) {
+ return this._materialize();
+ }
+ this._titleElement.classList.add('expanded');
+ UI.ARIAUtils.setExpanded(this._titleElement, true);
+ this._titleExpandIcon.setIconType('smallicon-triangle-down');
+ return this._materialize().then(() => this._widget.show(this.element));
+ }
+
+ _collapse() {
+ if (!this._titleElement.classList.contains('expanded')) {
+ return;
+ }
+ this._titleElement.classList.remove('expanded');
+ UI.ARIAUtils.setExpanded(this._titleElement, false);
+ this._titleExpandIcon.setIconType('smallicon-triangle-right');
+ this._materialize().then(() => this._widget.detach());
+ }
+
+ _toggleExpanded() {
+ if (this._titleElement.classList.contains('expanded')) {
+ this._collapse();
+ } else {
+ this._expand();
+ }
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ _onTitleKeyDown(event) {
+ if (isEnterOrSpaceKey(event)) {
+ this._toggleExpanded();
+ } else if (event.key === 'ArrowLeft') {
+ this._collapse();
+ } else if (event.key === 'ArrowRight') {
+ if (!this._titleElement.classList.contains('expanded')) {
+ this._expand();
+ } else if (this._widget) {
+ this._widget.focus();
+ }
+ }
+ }
+}
+
+_ExpandableContainerWidget._symbol = Symbol('container');
+
+/**
+ * @unrestricted
+ */
+export class _Location {
+ /**
+ * @param {!UI.ViewManager} manager
+ * @param {!UI.Widget} widget
+ * @param {function()=} revealCallback
+ */
+ constructor(manager, widget, revealCallback) {
+ this._manager = manager;
+ this._revealCallback = revealCallback;
+ this._widget = widget;
+ }
+
+ /**
+ * @return {!UI.Widget}
+ */
+ widget() {
+ return this._widget;
+ }
+
+ _reveal() {
+ if (this._revealCallback) {
+ this._revealCallback();
+ }
+ }
+}
+
+_Location.symbol = Symbol('location');
+
+/**
+ * @implements {UI.TabbedViewLocation}
+ * @unrestricted
+ */
+export class _TabbedLocation extends _Location {
+ /**
+ * @param {!UI.ViewManager} manager
+ * @param {function()=} revealCallback
+ * @param {string=} location
+ * @param {boolean=} restoreSelection
+ * @param {boolean=} allowReorder
+ * @param {?string=} defaultTab
+ */
+ constructor(manager, revealCallback, location, restoreSelection, allowReorder, defaultTab) {
+ const tabbedPane = new UI.TabbedPane();
+ if (allowReorder) {
+ tabbedPane.setAllowTabReorder(true);
+ }
+
+ super(manager, tabbedPane, revealCallback);
+ this._tabbedPane = tabbedPane;
+ this._allowReorder = allowReorder;
+
+ this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this._tabSelected, this);
+ this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, this._tabClosed, this);
+ this._closeableTabSetting = Common.settings.createSetting(location + '-closeableTabs', {});
+ this._tabOrderSetting = Common.settings.createSetting(location + '-tabOrder', {});
+ this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabOrderChanged, this._persistTabOrder, this);
+ if (restoreSelection) {
+ this._lastSelectedTabSetting = Common.settings.createSetting(location + '-selectedTab', '');
+ }
+ this._defaultTab = defaultTab;
+
+ /** @type {!Map.<string, !UI.View>} */
+ this._views = new Map();
+
+ if (location) {
+ this.appendApplicableItems(location);
+ }
+ }
+
+ /**
+ * @override
+ * @return {!UI.Widget}
+ */
+ widget() {
+ return this._tabbedPane;
+ }
+
+ /**
+ * @override
+ * @return {!UI.TabbedPane}
+ */
+ tabbedPane() {
+ return this._tabbedPane;
+ }
+
+ /**
+ * @override
+ * @return {!UI.ToolbarMenuButton}
+ */
+ enableMoreTabsButton() {
+ const moreTabsButton = new UI.ToolbarMenuButton(this._appendTabsToMenu.bind(this));
+ this._tabbedPane.leftToolbar().appendToolbarItem(moreTabsButton);
+ this._tabbedPane.disableOverflowMenu();
+ return moreTabsButton;
+ }
+
+ /**
+ * @override
+ * @param {string} locationName
+ */
+ appendApplicableItems(locationName) {
+ const views = this._manager._viewsForLocation(locationName);
+ if (this._allowReorder) {
+ let i = 0;
+ const persistedOrders = this._tabOrderSetting.get();
+ const orders = new Map();
+ for (const view of views) {
+ orders.set(view.viewId(), persistedOrders[view.viewId()] || (++i) * UI.ViewManager._TabbedLocation.orderStep);
+ }
+ views.sort((a, b) => orders.get(a.viewId()) - orders.get(b.viewId()));
+ }
+
+ for (const view of views) {
+ const id = view.viewId();
+ this._views.set(id, view);
+ view[_Location.symbol] = this;
+ if (view.isTransient()) {
+ continue;
+ }
+ if (!view.isCloseable()) {
+ this._appendTab(view);
+ } else if (this._closeableTabSetting.get()[id]) {
+ this._appendTab(view);
+ }
+ }
+ if (this._defaultTab && this._tabbedPane.hasTab(this._defaultTab)) {
+ this._tabbedPane.selectTab(this._defaultTab);
+ } else if (this._lastSelectedTabSetting && this._tabbedPane.hasTab(this._lastSelectedTabSetting.get())) {
+ this._tabbedPane.selectTab(this._lastSelectedTabSetting.get());
+ }
+ }
+
+ /**
+ * @param {!UI.ContextMenu} contextMenu
+ */
+ _appendTabsToMenu(contextMenu) {
+ const views = Array.from(this._views.values());
+ views.sort((viewa, viewb) => viewa.title().localeCompare(viewb.title()));
+ for (const view of views) {
+ const title = Common.UIString(view.title());
+ contextMenu.defaultSection().appendItem(title, this.showView.bind(this, view, undefined, true));
+ }
+ }
+
+ /**
+ * @param {!UI.View} view
+ * @param {number=} index
+ */
+ _appendTab(view, index) {
+ this._tabbedPane.appendTab(
+ view.viewId(), view.title(), new UI.ViewManager._ContainerWidget(view), undefined, false,
+ view.isCloseable() || view.isTransient(), index);
+ }
+
+ /**
+ * @override
+ * @param {!UI.View} view
+ * @param {?UI.View=} insertBefore
+ */
+ appendView(view, insertBefore) {
+ if (this._tabbedPane.hasTab(view.viewId())) {
+ return;
+ }
+ const oldLocation = view[_Location.symbol];
+ if (oldLocation && oldLocation !== this) {
+ oldLocation.removeView(view);
+ }
+ view[_Location.symbol] = this;
+ this._manager._views.set(view.viewId(), view);
+ this._views.set(view.viewId(), view);
+ let index = undefined;
+ const tabIds = this._tabbedPane.tabIds();
+ if (this._allowReorder) {
+ const orderSetting = this._tabOrderSetting.get();
+ const order = orderSetting[view.viewId()];
+ for (let i = 0; order && i < tabIds.length; ++i) {
+ if (orderSetting[tabIds[i]] && orderSetting[tabIds[i]] > order) {
+ index = i;
+ break;
+ }
+ }
+ } else if (insertBefore) {
+ for (let i = 0; i < tabIds.length; ++i) {
+ if (tabIds[i] === insertBefore.viewId()) {
+ index = i;
+ break;
+ }
+ }
+ }
+ this._appendTab(view, index);
+
+ if (view.isCloseable()) {
+ const tabs = this._closeableTabSetting.get();
+ const tabId = view.viewId();
+ if (!tabs[tabId]) {
+ tabs[tabId] = true;
+ this._closeableTabSetting.set(tabs);
+ }
+ }
+ this._persistTabOrder();
+ }
+
+ /**
+ * @override
+ * @param {!UI.View} view
+ * @param {?UI.View=} insertBefore
+ * @param {boolean=} userGesture
+ * @param {boolean=} omitFocus
+ * @return {!Promise}
+ */
+ showView(view, insertBefore, userGesture, omitFocus) {
+ this.appendView(view, insertBefore);
+ this._tabbedPane.selectTab(view.viewId(), userGesture);
+ if (!omitFocus) {
+ this._tabbedPane.focus();
+ }
+ const widget = /** @type {!UI.ViewManager._ContainerWidget} */ (this._tabbedPane.tabView(view.viewId()));
+ return widget._materialize();
+ }
+
+ /**
+ * @param {!UI.View} view
+ * @override
+ */
+ removeView(view) {
+ if (!this._tabbedPane.hasTab(view.viewId())) {
+ return;
+ }
+
+ delete view[_Location.symbol];
+ this._manager._views.delete(view.viewId());
+ this._tabbedPane.closeTab(view.viewId());
+ this._views.delete(view.viewId());
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _tabSelected(event) {
+ const tabId = /** @type {string} */ (event.data.tabId);
+ if (this._lastSelectedTabSetting && event.data['isUserGesture']) {
+ this._lastSelectedTabSetting.set(tabId);
+ }
+ }
+
+ /**
+ * @param {!Common.Event} event
+ */
+ _tabClosed(event) {
+ const id = /** @type {string} */ (event.data['tabId']);
+ const tabs = this._closeableTabSetting.get();
+ if (tabs[id]) {
+ delete tabs[id];
+ this._closeableTabSetting.set(tabs);
+ }
+ this._views.get(id).disposeView();
+ }
+
+ _persistTabOrder() {
+ const tabIds = this._tabbedPane.tabIds();
+ const tabOrders = {};
+ for (let i = 0; i < tabIds.length; i++) {
+ tabOrders[tabIds[i]] = (i + 1) * UI.ViewManager._TabbedLocation.orderStep;
+ }
+
+ const oldTabOrder = this._tabOrderSetting.get();
+ const oldTabArray = Object.keys(oldTabOrder);
+ oldTabArray.sort((a, b) => oldTabOrder[a] - oldTabOrder[b]);
+ let lastOrder = 0;
+ for (const key of oldTabArray) {
+ if (key in tabOrders) {
+ lastOrder = tabOrders[key];
+ continue;
+ }
+ tabOrders[key] = ++lastOrder;
+ }
+ this._tabOrderSetting.set(tabOrders);
+ }
+}
+
+_TabbedLocation.orderStep = 10; // Keep in sync with descriptors.
+
+/**
+ * @implements {UI.ViewLocation}
+ * @unrestricted
+ */
+export class _StackLocation extends _Location {
+ /**
+ * @param {!UI.ViewManager} manager
+ * @param {function()=} revealCallback
+ * @param {string=} location
+ */
+ constructor(manager, revealCallback, location) {
+ const vbox = new UI.VBox();
+ super(manager, vbox, revealCallback);
+ this._vbox = vbox;
+
+ /** @type {!Map<string, !UI.ViewManager._ExpandableContainerWidget>} */
+ this._expandableContainers = new Map();
+
+ if (location) {
+ this.appendApplicableItems(location);
+ }
+ }
+
+ /**
+ * @override
+ * @param {!UI.View} view
+ * @param {?UI.View=} insertBefore
+ */
+ appendView(view, insertBefore) {
+ const oldLocation = view[_Location.symbol];
+ if (oldLocation && oldLocation !== this) {
+ oldLocation.removeView(view);
+ }
+
+ let container = this._expandableContainers.get(view.viewId());
+ if (!container) {
+ view[_Location.symbol] = this;
+ this._manager._views.set(view.viewId(), view);
+ container = new UI.ViewManager._ExpandableContainerWidget(view);
+ let beforeElement = null;
+ if (insertBefore) {
+ const beforeContainer = insertBefore[UI.ViewManager._ExpandableContainerWidget._symbol];
+ beforeElement = beforeContainer ? beforeContainer.element : null;
+ }
+ container.show(this._vbox.contentElement, beforeElement);
+ this._expandableContainers.set(view.viewId(), container);
+ }
+ }
+
+ /**
+ * @override
+ * @param {!UI.View} view
+ * @param {?UI.View=} insertBefore
+ * @return {!Promise}
+ */
+ showView(view, insertBefore) {
+ this.appendView(view, insertBefore);
+ const container = this._expandableContainers.get(view.viewId());
+ return container._expand();
+ }
+
+ /**
+ * @param {!UI.View} view
+ * @override
+ */
+ removeView(view) {
+ const container = this._expandableContainers.get(view.viewId());
+ if (!container) {
+ return;
+ }
+
+ container.detach();
+ this._expandableContainers.delete(view.viewId());
+ delete view[_Location.symbol];
+ this._manager._views.delete(view.viewId());
+ }
+
+ /**
+ * @override
+ * @param {string} locationName
+ */
+ appendApplicableItems(locationName) {
+ for (const view of this._manager._viewsForLocation(locationName)) {
+ this.appendView(view);
+ }
+ }
+}
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/**
+ * @type {!UI.ViewManager}
+ */
+UI.viewManager;
+
+/** @constructor */
+UI.ViewManager = ViewManager;
+
+/** @constructor */
+UI.ViewManager._ContainerWidget = _ContainerWidget;
+
+/** @constructor */
+UI.ViewManager._ExpandableContainerWidget = _ExpandableContainerWidget;
+
+/** @constructor */
+UI.ViewManager._Location = _Location;
+
+/** @constructor */
+UI.ViewManager._TabbedLocation = _TabbedLocation;
+
+/** @constructor */
+UI.ViewManager._StackLocation = _StackLocation; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Widget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Widget.js
index 611890d3f81..522e90fb129 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Widget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Widget.js
@@ -27,7 +27,7 @@
/**
* @unrestricted
*/
-UI.Widget = class extends Common.Object {
+export default class Widget extends Common.Object {
/**
* @param {boolean=} isWebComponent
* @param {boolean=} delegatesFocus
@@ -56,8 +56,9 @@ UI.Widget = class extends Common.Object {
static _incrementWidgetCounter(parentElement, childElement) {
const count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0);
- if (!count)
+ if (!count) {
return;
+ }
while (parentElement) {
parentElement.__widgetCounter = (parentElement.__widgetCounter || 0) + count;
@@ -67,8 +68,9 @@ UI.Widget = class extends Common.Object {
static _decrementWidgetCounter(parentElement, childElement) {
const count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0);
- if (!count)
+ if (!count) {
return;
+ }
while (parentElement) {
parentElement.__widgetCounter -= count;
@@ -77,8 +79,9 @@ UI.Widget = class extends Common.Object {
}
static __assert(condition, message) {
- if (!condition)
+ if (!condition) {
throw new Error(message);
+ }
}
/**
@@ -86,12 +89,14 @@ UI.Widget = class extends Common.Object {
*/
static focusWidgetForNode(node) {
while (node) {
- if (node.__widget)
+ if (node.__widget) {
break;
+ }
node = node.parentNodeOrShadowHost();
}
- if (!node)
+ if (!node) {
return;
+ }
let widget = node.__widget;
while (widget._parentWidget) {
@@ -101,26 +106,26 @@ UI.Widget = class extends Common.Object {
}
markAsRoot() {
- UI.Widget.__assert(!this.element.parentElement, 'Attempt to mark as root attached node');
+ Widget.__assert(!this.element.parentElement, 'Attempt to mark as root attached node');
this._isRoot = true;
}
/**
- * @return {?UI.Widget}
+ * @return {?Widget}
*/
parentWidget() {
return this._parentWidget;
}
/**
- * @return {!Array.<!UI.Widget>}
+ * @return {!Array.<!Widget>}
*/
children() {
return this._children;
}
/**
- * @param {!UI.Widget} widget
+ * @param {!Widget} widget
* @protected
*/
childWasDetached(widget) {
@@ -137,13 +142,16 @@ UI.Widget = class extends Common.Object {
* @return {boolean}
*/
shouldHideOnDetach() {
- if (!this.element.parentElement)
+ if (!this.element.parentElement) {
return false;
- if (this._hideOnDetach)
+ }
+ if (this._hideOnDetach) {
return true;
+ }
for (const child of this._children) {
- if (child.shouldHideOnDetach())
+ if (child.shouldHideOnDetach()) {
return true;
+ }
}
return false;
}
@@ -160,19 +168,21 @@ UI.Widget = class extends Common.Object {
}
_parentIsShowing() {
- if (this._isRoot)
+ if (this._isRoot) {
return true;
+ }
return !!this._parentWidget && this._parentWidget.isShowing();
}
/**
- * @param {function(this:UI.Widget)} method
+ * @param {function(this:Widget)} method
*/
_callOnVisibleChildren(method) {
const copy = this._children.slice();
for (let i = 0; i < copy.length; ++i) {
- if (copy[i]._parentWidget === this && copy[i]._visible)
+ if (copy[i]._parentWidget === this && copy[i]._visible) {
method.call(copy[i]);
+ }
}
}
@@ -182,16 +192,18 @@ UI.Widget = class extends Common.Object {
}
_processWasShown() {
- if (this._inNotification())
+ if (this._inNotification()) {
return;
+ }
this.restoreScrollPositions();
this._notify(this.wasShown);
this._callOnVisibleChildren(this._processWasShown);
}
_processWillHide() {
- if (this._inNotification())
+ if (this._inNotification()) {
return;
+ }
this.storeScrollPositions();
this._callOnVisibleChildren(this._processWillHide);
@@ -204,16 +216,18 @@ UI.Widget = class extends Common.Object {
}
_processOnResize() {
- if (this._inNotification())
+ if (this._inNotification()) {
return;
- if (!this.isShowing())
+ }
+ if (!this.isShowing()) {
return;
+ }
this._notify(this.onResize);
this._callOnVisibleChildren(this._processOnResize);
}
/**
- * @param {function(this:UI.Widget)} notification
+ * @param {function(this:Widget)} notification
*/
_notify(notification) {
++this._notificationDepth;
@@ -244,14 +258,15 @@ UI.Widget = class extends Common.Object {
* @param {?Node=} insertBefore
*/
show(parentElement, insertBefore) {
- UI.Widget.__assert(parentElement, 'Attempt to attach widget with no parent element');
+ Widget.__assert(parentElement, 'Attempt to attach widget with no parent element');
if (!this._isRoot) {
// Update widget hierarchy.
let currentParent = parentElement;
- while (currentParent && !currentParent.__widget)
+ while (currentParent && !currentParent.__widget) {
currentParent = currentParent.parentElementOrShadowHost();
- UI.Widget.__assert(currentParent, 'Attempt to attach widget to orphan node');
+ }
+ Widget.__assert(currentParent, 'Attempt to attach widget to orphan node');
this._attach(currentParent.__widget);
}
@@ -259,22 +274,25 @@ UI.Widget = class extends Common.Object {
}
/**
- * @param {!UI.Widget} parentWidget
+ * @param {!Widget} parentWidget
*/
_attach(parentWidget) {
- if (parentWidget === this._parentWidget)
+ if (parentWidget === this._parentWidget) {
return;
- if (this._parentWidget)
+ }
+ if (this._parentWidget) {
this.detach();
+ }
this._parentWidget = parentWidget;
this._parentWidget._children.push(this);
this._isRoot = false;
}
showWidget() {
- if (this._visible)
+ if (this._visible) {
return;
- UI.Widget.__assert(this.element.parentElement, 'Attempt to show widget that is not hidden using hideWidget().');
+ }
+ Widget.__assert(this.element.parentElement, 'Attempt to show widget that is not hidden using hideWidget().');
this._showWidget(/** @type {!Element} */ (this.element.parentElement), this.element.nextSibling);
}
@@ -284,49 +302,58 @@ UI.Widget = class extends Common.Object {
*/
_showWidget(parentElement, insertBefore) {
let currentParent = parentElement;
- while (currentParent && !currentParent.__widget)
+ while (currentParent && !currentParent.__widget) {
currentParent = currentParent.parentElementOrShadowHost();
+ }
if (this._isRoot) {
- UI.Widget.__assert(!currentParent, 'Attempt to show root widget under another widget');
+ Widget.__assert(!currentParent, 'Attempt to show root widget under another widget');
} else {
- UI.Widget.__assert(
+ Widget.__assert(
currentParent && currentParent.__widget === this._parentWidget,
'Attempt to show under node belonging to alien widget');
}
const wasVisible = this._visible;
- if (wasVisible && this.element.parentElement === parentElement)
+ if (wasVisible && this.element.parentElement === parentElement) {
return;
+ }
this._visible = true;
- if (!wasVisible && this._parentIsShowing())
+ if (!wasVisible && this._parentIsShowing()) {
this._processWillShow();
+ }
this.element.classList.remove('hidden');
// Reparent
if (this.element.parentElement !== parentElement) {
- UI.Widget._incrementWidgetCounter(parentElement, this.element);
- if (insertBefore)
- UI.Widget._originalInsertBefore.call(parentElement, this.element, insertBefore);
- else
- UI.Widget._originalAppendChild.call(parentElement, this.element);
+ if (!this._externallyManaged) {
+ Widget._incrementWidgetCounter(parentElement, this.element);
+ }
+ if (insertBefore) {
+ Widget._originalInsertBefore.call(parentElement, this.element, insertBefore);
+ } else {
+ Widget._originalAppendChild.call(parentElement, this.element);
+ }
}
- if (!wasVisible && this._parentIsShowing())
+ if (!wasVisible && this._parentIsShowing()) {
this._processWasShown();
+ }
- if (this._parentWidget && this._hasNonZeroConstraints())
+ if (this._parentWidget && this._hasNonZeroConstraints()) {
this._parentWidget.invalidateConstraints();
- else
+ } else {
this._processOnResize();
+ }
}
hideWidget() {
- if (!this._visible)
+ if (!this._visible) {
return;
+ }
this._hideWidget(false);
}
@@ -337,29 +364,33 @@ UI.Widget = class extends Common.Object {
this._visible = false;
const parentElement = this.element.parentElement;
- if (this._parentIsShowing())
+ if (this._parentIsShowing()) {
this._processWillHide();
+ }
if (removeFromDOM) {
// Force legal removal
- UI.Widget._decrementWidgetCounter(parentElement, this.element);
- UI.Widget._originalRemoveChild.call(parentElement, this.element);
+ Widget._decrementWidgetCounter(parentElement, this.element);
+ Widget._originalRemoveChild.call(parentElement, this.element);
} else {
this.element.classList.add('hidden');
}
- if (this._parentIsShowing())
+ if (this._parentIsShowing()) {
this._processWasHidden();
- if (this._parentWidget && this._hasNonZeroConstraints())
+ }
+ if (this._parentWidget && this._hasNonZeroConstraints()) {
this._parentWidget.invalidateConstraints();
+ }
}
/**
* @param {boolean=} overrideHideOnDetach
*/
detach(overrideHideOnDetach) {
- if (!this._parentWidget && !this._isRoot)
+ if (!this._parentWidget && !this._isRoot) {
return;
+ }
// hideOnDetach means that we should never remove element from dom - content
// has iframes and detaching it will hurt.
@@ -372,28 +403,30 @@ UI.Widget = class extends Common.Object {
} else if (removeFromDOM && this.element.parentElement) {
const parentElement = this.element.parentElement;
// Force kick out from DOM.
- UI.Widget._decrementWidgetCounter(parentElement, this.element);
- UI.Widget._originalRemoveChild.call(parentElement, this.element);
+ Widget._decrementWidgetCounter(parentElement, this.element);
+ Widget._originalRemoveChild.call(parentElement, this.element);
}
// Update widget hierarchy.
if (this._parentWidget) {
const childIndex = this._parentWidget._children.indexOf(this);
- UI.Widget.__assert(childIndex >= 0, 'Attempt to remove non-child widget');
+ Widget.__assert(childIndex >= 0, 'Attempt to remove non-child widget');
this._parentWidget._children.splice(childIndex, 1);
- if (this._parentWidget._defaultFocusedChild === this)
+ if (this._parentWidget._defaultFocusedChild === this) {
this._parentWidget._defaultFocusedChild = null;
+ }
this._parentWidget.childWasDetached(this);
this._parentWidget = null;
} else {
- UI.Widget.__assert(this._isRoot, 'Removing non-root widget from DOM');
+ Widget.__assert(this._isRoot, 'Removing non-root widget from DOM');
}
}
detachChildWidgets() {
const children = this._children.slice();
- for (let i = 0; i < children.length; ++i)
+ for (let i = 0; i < children.length; ++i) {
children[i].detach();
+ }
}
/**
@@ -416,24 +449,29 @@ UI.Widget = class extends Common.Object {
const elements = this.elementsToRestoreScrollPositionsFor();
for (let i = 0; i < elements.length; ++i) {
const container = elements[i];
- if (container._scrollTop)
+ if (container._scrollTop) {
container.scrollTop = container._scrollTop;
- if (container._scrollLeft)
+ }
+ if (container._scrollLeft) {
container.scrollLeft = container._scrollLeft;
+ }
}
}
doResize() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
// No matter what notification we are in, dispatching onResize is not needed.
- if (!this._inNotification())
+ if (!this._inNotification()) {
this._callOnVisibleChildren(this._processOnResize);
+ }
}
doLayout() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
this._notify(this.onLayout);
this.doResize();
}
@@ -454,11 +492,13 @@ UI.Widget = class extends Common.Object {
_collectWidgetHierarchy(prefix, lines) {
lines.push(prefix + '[' + this.element.className + ']' + (this._children.length ? ' {' : ''));
- for (let i = 0; i < this._children.length; ++i)
+ for (let i = 0; i < this._children.length; ++i) {
this._children[i]._collectWidgetHierarchy(prefix + ' ', lines);
+ }
- if (this._children.length)
+ if (this._children.length) {
lines.push(prefix + '}');
+ }
}
/**
@@ -469,21 +509,23 @@ UI.Widget = class extends Common.Object {
}
/**
- * @param {!UI.Widget} child
+ * @param {!Widget} child
*/
setDefaultFocusedChild(child) {
- UI.Widget.__assert(child._parentWidget === this, 'Attempt to set non-child widget as default focused.');
+ Widget.__assert(child._parentWidget === this, 'Attempt to set non-child widget as default focused.');
this._defaultFocusedChild = child;
}
focus() {
- if (!this.isShowing())
+ if (!this.isShowing()) {
return;
+ }
const element = this._defaultFocusedElement;
if (element) {
- if (!element.hasFocus())
+ if (!element.hasFocus()) {
element.focus();
+ }
return;
}
@@ -525,10 +567,12 @@ UI.Widget = class extends Common.Object {
* @return {!UI.Constraints}
*/
constraints() {
- if (typeof this._constraints !== 'undefined')
+ if (typeof this._constraints !== 'undefined') {
return this._constraints;
- if (typeof this._cachedConstraints === 'undefined')
+ }
+ if (typeof this._cachedConstraints === 'undefined') {
this._cachedConstraints = this.calculateConstraints();
+ }
return this._cachedConstraints;
}
@@ -568,8 +612,9 @@ UI.Widget = class extends Common.Object {
resumeInvalidations() {
--this._invalidationsSuspended;
- if (!this._invalidationsSuspended && this._invalidationsRequested)
+ if (!this._invalidationsSuspended && this._invalidationsRequested) {
this.invalidateConstraints();
+ }
}
invalidateConstraints() {
@@ -581,23 +626,37 @@ UI.Widget = class extends Common.Object {
const cached = this._cachedConstraints;
delete this._cachedConstraints;
const actual = this.constraints();
- if (!actual.isEqual(cached) && this._parentWidget)
+ if (!actual.isEqual(cached) && this._parentWidget) {
this._parentWidget.invalidateConstraints();
- else
+ } else {
this.doLayout();
+ }
}
-};
-UI.Widget._originalAppendChild = Element.prototype.appendChild;
-UI.Widget._originalInsertBefore = Element.prototype.insertBefore;
-UI.Widget._originalRemoveChild = Element.prototype.removeChild;
-UI.Widget._originalRemoveChildren = Element.prototype.removeChildren;
+ // Excludes the widget from being tracked by its parents/ancestors via
+ // __widgetCounter because the widget is being handled by external code.
+ // Widgets marked as being externally managed are responsible for
+ // finishing out their own lifecycle (i.e. calling detach() before being
+ // removed from the DOM). This is e.g. used for CodeMirror.
+ //
+ // Also note that this must be called before the widget is shown so that
+ // so that its ancestor's __widgetCounter is not incremented.
+ markAsExternallyManaged() {
+ Widget.__assert(!this._parentWidget, 'Attempt to mark widget as externally managed after insertion to the DOM');
+ this._externallyManaged = true;
+ }
+}
+
+export const _originalAppendChild = Element.prototype.appendChild;
+export const _originalInsertBefore = Element.prototype.insertBefore;
+export const _originalRemoveChild = Element.prototype.removeChild;
+export const _originalRemoveChildren = Element.prototype.removeChildren;
/**
* @unrestricted
*/
-UI.VBox = class extends UI.Widget {
+export class VBox extends Widget {
/**
* @param {boolean=} isWebComponent
* @param {boolean=} delegatesFocus
@@ -615,7 +674,7 @@ UI.VBox = class extends UI.Widget {
let constraints = new UI.Constraints();
/**
- * @this {!UI.Widget}
+ * @this {!Widget}
* @suppressReceiverCheck
*/
function updateForChild() {
@@ -627,12 +686,12 @@ UI.VBox = class extends UI.Widget {
this._callOnVisibleChildren(updateForChild);
return constraints;
}
-};
+}
/**
* @unrestricted
*/
-UI.HBox = class extends UI.Widget {
+export class HBox extends Widget {
/**
* @param {boolean=} isWebComponent
*/
@@ -649,7 +708,7 @@ UI.HBox = class extends UI.Widget {
let constraints = new UI.Constraints();
/**
- * @this {!UI.Widget}
+ * @this {!Widget}
* @suppressReceiverCheck
*/
function updateForChild() {
@@ -661,12 +720,12 @@ UI.HBox = class extends UI.Widget {
this._callOnVisibleChildren(updateForChild);
return constraints;
}
-};
+}
/**
* @unrestricted
*/
-UI.VBoxWithResizeCallback = class extends UI.VBox {
+export class VBoxWithResizeCallback extends VBox {
/**
* @param {function()} resizeCallback
*/
@@ -681,14 +740,14 @@ UI.VBoxWithResizeCallback = class extends UI.VBox {
onResize() {
this._resizeCallback();
}
-};
+}
/**
* @unrestricted
*/
-UI.WidgetFocusRestorer = class {
+export class WidgetFocusRestorer {
/**
- * @param {!UI.Widget} widget
+ * @param {!Widget} widget
*/
constructor(widget) {
this._widget = widget;
@@ -697,14 +756,16 @@ UI.WidgetFocusRestorer = class {
}
restore() {
- if (!this._widget)
+ if (!this._widget) {
return;
- if (this._widget.hasFocus() && this._previous)
+ }
+ if (this._widget.hasFocus() && this._previous) {
this._previous.focus();
+ }
this._previous = null;
this._widget = null;
}
-};
+}
/**
* @override
@@ -713,9 +774,8 @@ UI.WidgetFocusRestorer = class {
* @suppress {duplicate}
*/
Element.prototype.appendChild = function(child) {
- UI.Widget.__assert(
- !child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
- return UI.Widget._originalAppendChild.call(this, child);
+ Widget.__assert(!child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
+ return Widget._originalAppendChild.call(this, child);
};
/**
@@ -726,9 +786,8 @@ Element.prototype.appendChild = function(child) {
* @suppress {duplicate}
*/
Element.prototype.insertBefore = function(child, anchor) {
- UI.Widget.__assert(
- !child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
- return UI.Widget._originalInsertBefore.call(this, child, anchor);
+ Widget.__assert(!child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
+ return Widget._originalInsertBefore.call(this, child, anchor);
};
/**
@@ -738,13 +797,39 @@ Element.prototype.insertBefore = function(child, anchor) {
* @suppress {duplicate}
*/
Element.prototype.removeChild = function(child) {
- UI.Widget.__assert(
+ Widget.__assert(
!child.__widgetCounter && !child.__widget,
'Attempt to remove element containing widget via regular DOM operation');
- return UI.Widget._originalRemoveChild.call(this, child);
+ return Widget._originalRemoveChild.call(this, child);
};
Element.prototype.removeChildren = function() {
- UI.Widget.__assert(!this.__widgetCounter, 'Attempt to remove element containing widget via regular DOM operation');
- UI.Widget._originalRemoveChildren.call(this);
+ Widget.__assert(!this.__widgetCounter, 'Attempt to remove element containing widget via regular DOM operation');
+ Widget._originalRemoveChildren.call(this);
};
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.Widget = Widget;
+
+Widget._originalAppendChild = _originalAppendChild;
+Widget._originalInsertBefore = _originalInsertBefore;
+Widget._originalRemoveChild = _originalRemoveChild;
+Widget._originalRemoveChildren = _originalRemoveChildren;
+
+/** @constructor */
+UI.HBox = HBox;
+
+/** @constructor */
+UI.VBox = VBox;
+
+/** @constructor */
+UI.WidgetFocusRestorer = WidgetFocusRestorer;
+
+/** @constructor */
+UI.VBoxWithResizeCallback = VBoxWithResizeCallback;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/XElement.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/XElement.js
index 09d340a0d26..e94b5e166b3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/XElement.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/XElement.js
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/**
- * @extends {HTMLElement}
- */
-UI.XElement = class extends HTMLElement {
+export default class XElement extends HTMLElement {
+ /**
+ * @override
+ */
static get observedAttributes() {
return [
'flex', 'padding', 'padding-top', 'padding-bottom', 'padding-left',
@@ -24,12 +24,13 @@ UI.XElement = class extends HTMLElement {
*/
attributeChangedCallback(attr, oldValue, newValue) {
if (attr === 'flex') {
- if (newValue === null)
+ if (newValue === null) {
this.style.removeProperty('flex');
- else if (newValue === 'initial' || newValue === 'auto' || newValue === 'none' || newValue.indexOf(' ') !== -1)
+ } else if (newValue === 'initial' || newValue === 'auto' || newValue === 'none' || newValue.indexOf(' ') !== -1) {
this.style.setProperty('flex', newValue);
- else
+ } else {
this.style.setProperty('flex', '0 0 ' + newValue);
+ }
return;
}
if (newValue === null) {
@@ -38,19 +39,20 @@ UI.XElement = class extends HTMLElement {
attr.startsWith('background-') || attr.startsWith('overflow-')) {
const shorthand = attr.substring(0, attr.indexOf('-'));
const shorthandValue = this.getAttribute(shorthand);
- if (shorthandValue !== null)
+ if (shorthandValue !== null) {
this.style.setProperty(shorthand, shorthandValue);
+ }
}
} else {
this.style.setProperty(attr, newValue);
}
}
-};
+}
/**
- * @extends {UI.XElement}
+ * @extends {XElement}
*/
-UI._XBox = class extends UI.XElement {
+export class _XBox extends XElement {
/**
* @param {string} direction
*/
@@ -61,9 +63,11 @@ UI._XBox = class extends UI.XElement {
this.style.setProperty('justify-content', 'flex-start');
}
+ /**
+ * @override
+ */
static get observedAttributes() {
- // TODO(dgozman): should be super.observedAttributes, but does not compile.
- return UI.XElement.observedAttributes.concat(['x-start', 'x-center', 'x-stretch', 'x-baseline', 'justify-content']);
+ return super.observedAttributes.concat(['x-start', 'x-center', 'x-stretch', 'x-baseline', 'justify-content']);
}
/**
@@ -74,38 +78,39 @@ UI._XBox = class extends UI.XElement {
*/
attributeChangedCallback(attr, oldValue, newValue) {
if (attr === 'x-start' || attr === 'x-center' || attr === 'x-stretch' || attr === 'x-baseline') {
- if (newValue === null)
+ if (newValue === null) {
this.style.removeProperty('align-items');
- else
+ } else {
this.style.setProperty('align-items', attr === 'x-start' ? 'flex-start' : attr.substr(2));
+ }
return;
}
super.attributeChangedCallback(attr, oldValue, newValue);
}
-};
+}
/**
- * @extends {UI._XBox}
+ * @extends {_XBox}
*/
-UI.XVBox = class extends UI._XBox {
+export class XVBox extends _XBox {
constructor() {
super('column');
}
-};
+}
/**
- * @extends {UI._XBox}
+ * @extends {_XBox}
*/
-UI.XHBox = class extends UI._XBox {
+export class XHBox extends _XBox {
constructor() {
super('row');
}
-};
+}
/**
- * @extends {UI.XElement}
+ * @extends {XElement}
*/
-UI.XCBox = class extends UI.XElement {
+export class XCBox extends XElement {
constructor() {
super();
this.style.setProperty('display', 'flex');
@@ -113,42 +118,72 @@ UI.XCBox = class extends UI.XElement {
this.style.setProperty('justify-content', 'center');
this.style.setProperty('align-items', 'center');
}
-};
+}
/**
- * @extends {UI.XElement}
+ * @extends {XElement}
*/
-UI.XDiv = class extends UI.XElement {
+export class XDiv extends XElement {
constructor() {
super();
this.style.setProperty('display', 'block');
}
-};
+}
/**
- * @extends {UI.XElement}
+ * @extends {XElement}
*/
-UI.XSpan = class extends UI.XElement {
+export class XSpan extends XElement {
constructor() {
super();
this.style.setProperty('display', 'inline');
}
-};
+}
/**
- * @extends {UI.XElement}
+ * @extends {XElement}
*/
-UI.XText = class extends UI.XElement {
+export class XText extends XElement {
constructor() {
super();
this.style.setProperty('display', 'inline');
this.style.setProperty('white-space', 'pre');
}
-};
-
-self.customElements.define('x-vbox', UI.XVBox);
-self.customElements.define('x-hbox', UI.XHBox);
-self.customElements.define('x-cbox', UI.XCBox);
-self.customElements.define('x-div', UI.XDiv);
-self.customElements.define('x-span', UI.XSpan);
-self.customElements.define('x-text', UI.XText);
+}
+
+self.customElements.define('x-vbox', XVBox);
+self.customElements.define('x-hbox', XHBox);
+self.customElements.define('x-cbox', XCBox);
+self.customElements.define('x-div', XDiv);
+self.customElements.define('x-span', XSpan);
+self.customElements.define('x-text', XText);
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.XElement = XElement;
+
+/** @constructor */
+UI._XBox = _XBox;
+
+/** @constructor */
+UI.XVBox = XVBox;
+
+/** @constructor */
+UI.XHBox = XHBox;
+
+/** @constructor */
+UI.XCBox = XCBox;
+
+/** @constructor */
+UI.XDiv = XDiv;
+
+/** @constructor */
+UI.XSpan = XSpan;
+
+/** @constructor */
+UI.XText = XText; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js
index 6f1aa1ac91e..cbac9aafd63 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/XLink.js
@@ -5,7 +5,7 @@
/**
* @extends {UI.XElement}
*/
-UI.XLink = class extends UI.XElement {
+export default class XLink extends UI.XElement {
/**
* @param {string} url
* @param {string=} linkText
@@ -14,8 +14,9 @@ UI.XLink = class extends UI.XElement {
* @return {!Element}
*/
static create(url, linkText, className, preventClick) {
- if (!linkText)
+ if (!linkText) {
linkText = url;
+ }
className = className || '';
// clang-format off
// TODO(dgozman): migrate css from 'devtools-link' to 'x-link'.
@@ -39,17 +40,18 @@ UI.XLink = class extends UI.XElement {
this._onClick = event => {
event.consume(true);
- InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
+ Host.InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
};
this._onKeyDown = event => {
if (isEnterOrSpaceKey(event)) {
event.consume(true);
- InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
+ Host.InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href));
}
};
}
/**
+ * @override
* @return {!Array<string>}
*/
static get observedAttributes() {
@@ -72,10 +74,12 @@ UI.XLink = class extends UI.XElement {
if (attr === 'href') {
let href = newValue;
- if (newValue.trim().toLowerCase().startsWith('javascript:'))
+ if (newValue.trim().toLowerCase().startsWith('javascript:')) {
href = null;
- if (Common.ParsedURL.isRelativeURL(newValue))
+ }
+ if (Common.ParsedURL.isRelativeURL(newValue)) {
href = null;
+ }
this._href = href;
this.title = newValue;
@@ -97,12 +101,12 @@ UI.XLink = class extends UI.XElement {
this.style.removeProperty('cursor');
}
}
-};
+}
/**
* @implements {UI.ContextMenu.Provider}
*/
-UI.XLink.ContextMenuProvider = class {
+export class ContextMenuProvider {
/**
* @override
* @param {!Event} event
@@ -111,15 +115,31 @@ UI.XLink.ContextMenuProvider = class {
*/
appendApplicableItems(event, contextMenu, target) {
let targetNode = /** @type {!Node} */ (target);
- while (targetNode && !(targetNode instanceof UI.XLink))
+ while (targetNode && !(targetNode instanceof XLink)) {
targetNode = targetNode.parentNodeOrShadowHost();
- if (!targetNode || !targetNode._href)
+ }
+ if (!targetNode || !targetNode._href) {
return;
+ }
contextMenu.revealSection().appendItem(
- UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(targetNode._href));
+ UI.openLinkExternallyLabel(), () => Host.InspectorFrontendHost.openInNewTab(targetNode._href));
contextMenu.revealSection().appendItem(
- UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(targetNode._href));
+ UI.copyLinkAddressLabel(), () => Host.InspectorFrontendHost.copyText(targetNode._href));
}
-};
+}
+
+self.customElements.define('x-link', XLink);
-self.customElements.define('x-link', UI.XLink);
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.XLink = XLink;
+
+/**
+ * @implements {UI.ContextMenu.Provider}
+ */
+UI.XLink.ContextMenuProvider = ContextMenuProvider;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/XWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/XWidget.js
index 6e33f2b8085..b174cd6cc5f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/XWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/XWidget.js
@@ -5,7 +5,7 @@
/**
* @extends {UI.XElement}
*/
-UI.XWidget = class extends UI.XElement {
+export default class XWidget extends UI.XElement {
constructor() {
super();
this.style.setProperty('display', 'flex');
@@ -28,15 +28,16 @@ UI.XWidget = class extends UI.XElement {
/** @type {?function()} */
this._onResizedCallback;
- if (!UI.XWidget._observer) {
- UI.XWidget._observer = new ResizeObserver(entries => {
+ if (!XWidget._observer) {
+ XWidget._observer = new ResizeObserver(entries => {
for (const entry of entries) {
- if (entry.target._visible && entry.target._onResizedCallback)
+ if (entry.target._visible && entry.target._onResizedCallback) {
entry.target._onResizedCallback.call(null);
+ }
}
});
}
- UI.XWidget._observer.observe(this);
+ XWidget._observer.observe(this);
this.setElementsToRestoreScrollPositionsFor([this]);
}
@@ -48,9 +49,10 @@ UI.XWidget = class extends UI.XElement {
node = node && node.parentNodeOrShadowHost();
let widget = null;
while (node) {
- if (node instanceof UI.XWidget) {
- if (widget)
+ if (node instanceof XWidget) {
+ if (widget) {
node._defaultFocusedElement = widget;
+ }
widget = node;
}
node = node.parentNodeOrShadowHost();
@@ -96,19 +98,23 @@ UI.XWidget = class extends UI.XElement {
* @param {!Array<!Element>} elements
*/
setElementsToRestoreScrollPositionsFor(elements) {
- for (const element of this._elementsToRestoreScrollPositionsFor)
- element.removeEventListener('scroll', UI.XWidget._storeScrollPosition, {passive: true, capture: false});
+ for (const element of this._elementsToRestoreScrollPositionsFor) {
+ element.removeEventListener('scroll', XWidget._storeScrollPosition, {passive: true, capture: false});
+ }
this._elementsToRestoreScrollPositionsFor = elements;
- for (const element of this._elementsToRestoreScrollPositionsFor)
- element.addEventListener('scroll', UI.XWidget._storeScrollPosition, {passive: true, capture: false});
+ for (const element of this._elementsToRestoreScrollPositionsFor) {
+ element.addEventListener('scroll', XWidget._storeScrollPosition, {passive: true, capture: false});
+ }
}
restoreScrollPositions() {
for (const element of this._elementsToRestoreScrollPositionsFor) {
- if (element._scrollTop)
+ if (element._scrollTop) {
element.scrollTop = element._scrollTop;
- if (element._scrollLeft)
+ }
+ if (element._scrollLeft) {
element.scrollLeft = element._scrollLeft;
+ }
}
}
@@ -125,8 +131,9 @@ UI.XWidget = class extends UI.XElement {
* @param {?Element} element
*/
setDefaultFocusedElement(element) {
- if (element && !this.isSelfOrAncestor(element))
+ if (element && !this.isSelfOrAncestor(element)) {
throw new Error('Default focus must be descendant');
+ }
this._defaultFocusedElement = element;
}
@@ -134,8 +141,9 @@ UI.XWidget = class extends UI.XElement {
* @override
*/
focus() {
- if (!this._visible)
+ if (!this._visible) {
return;
+ }
let element;
if (this._defaultFocusedElement && this.isSelfOrAncestor(this._defaultFocusedElement)) {
@@ -145,7 +153,7 @@ UI.XWidget = class extends UI.XElement {
} else {
let child = this.traverseNextNode(this);
while (child) {
- if ((child instanceof UI.XWidget) && child._visible) {
+ if ((child instanceof XWidget) && child._visible) {
element = child;
break;
}
@@ -153,12 +161,14 @@ UI.XWidget = class extends UI.XElement {
}
}
- if (!element || element.hasFocus())
+ if (!element || element.hasFocus()) {
return;
- if (element === this)
+ }
+ if (element === this) {
HTMLElement.prototype.focus.call(this);
- else
+ } else {
element.focus();
+ }
}
/**
@@ -167,8 +177,9 @@ UI.XWidget = class extends UI.XElement {
connectedCallback() {
this._visible = true;
this.restoreScrollPositions();
- if (this._onShownCallback)
+ if (this._onShownCallback) {
this._onShownCallback.call(null);
+ }
}
/**
@@ -176,9 +187,19 @@ UI.XWidget = class extends UI.XElement {
*/
disconnectedCallback() {
this._visible = false;
- if (this._onHiddenCallback)
+ if (this._onHiddenCallback) {
this._onHiddenCallback.call(null);
+ }
}
-};
+}
+
+self.customElements.define('x-widget', XWidget);
+
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
-self.customElements.define('x-widget', UI.XWidget);
+/** @constructor */
+UI.XWidget = XWidget;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ZoomManager.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ZoomManager.js
index d0295384cff..f827a8570e0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ZoomManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ZoomManager.js
@@ -4,7 +4,7 @@
/**
* @unrestricted
*/
-UI.ZoomManager = class extends Common.Object {
+export default class ZoomManager extends Common.Object {
/**
* @param {!Window} window
* @param {!InspectorFrontendHostAPI} frontendHost
@@ -42,17 +42,30 @@ UI.ZoomManager = class extends Common.Object {
_onWindowResize() {
const oldZoomFactor = this._zoomFactor;
this._zoomFactor = this._frontendHost.zoomFactor();
- if (oldZoomFactor !== this._zoomFactor)
- this.dispatchEventToListeners(UI.ZoomManager.Events.ZoomChanged, {from: oldZoomFactor, to: this._zoomFactor});
+ if (oldZoomFactor !== this._zoomFactor) {
+ this.dispatchEventToListeners(Events.ZoomChanged, {from: oldZoomFactor, to: this._zoomFactor});
+ }
}
-};
+}
/** @enum {symbol} */
-UI.ZoomManager.Events = {
+export const Events = {
ZoomChanged: Symbol('ZoomChanged')
};
+/* Legacy exported object*/
+self.UI = self.UI || {};
+
+/* Legacy exported object*/
+UI = UI || {};
+
+/** @constructor */
+UI.ZoomManager = ZoomManager;
+
+/** @enum {symbol} */
+UI.ZoomManager.Events = Events;
+
/**
* @type {!UI.ZoomManager}
*/
-UI.zoomManager;
+UI.zoomManager; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/closeButton.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/closeButton.css
index 2d6d99185c6..3080dc8c910 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/closeButton.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/closeButton.css
@@ -25,6 +25,14 @@
display: block;
}
+.close-button[data-keyboard-focus="true"]:focus .default-icon, .close-button:active .default-icon {
+ display: none;
+}
+
+.close-button[data-keyboard-focus="true"]:focus .hover-icon {
+ display: block;
+}
+
.close-button:active .hover-icon {
display: none !important;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/infobar.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/infobar.css
index c18e76bc8a0..c4c5ffbda8d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/infobar.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/infobar.css
@@ -67,6 +67,8 @@
.infobar-toggle {
color: hsl(214, 92%, 50%);
cursor: pointer;
+ margin-top: 5px;
+ margin-bottom: 5px;
}
.infobar-toggle:hover {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
index bd83e0f6a32..1b166b5f0f5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
@@ -166,7 +166,11 @@ input {
color: inherit;
}
-:host-context(.-theme-with-dark-background) input[type="checkbox"]::not(.-theme-preserve) {
+input::placeholder {
+ color: rgba(0, 0, 0, 0.54);
+}
+
+:host-context(.-theme-with-dark-background) input[type="checkbox"]:not(.-theme-preserve) {
-webkit-filter: invert(80%);
}
@@ -269,6 +273,16 @@ input {
opacity: 0.38;
}
+.chrome-select-label {
+ margin: 0px 22px;
+ flex: none;
+}
+
+.chrome-select-label p {
+ margin-top: 0;
+ color: gray;
+}
+
.chrome-select optgroup,
.chrome-select option {
background-color: #EEEEEE;
@@ -457,4 +471,4 @@ button.link[data-keyboard-focus="true"]:focus {
animation: ANIMATION-HACK 0s;
}
@keyframes ANIMATION-HACK {
-} \ No newline at end of file
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
index df31c930788..5f07efef3db 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
@@ -36,6 +36,7 @@
--accent-color: #1a73e8;
--accent-fg-color: #1a73e8;
--accent-color-hover: #3b86e8;
+ --active-control-bg-color: #5a5a5a;
--focus-bg-color: hsl(214, 40%, 92%);
--toolbar-bg-color: #f3f3f3;
--toolbar-hover-bg-color: #eaeaea;
@@ -57,6 +58,7 @@
--accent-color: #0e639c;
--accent-fg-color: #cccccc;
--accent-color-hover: rgb(17, 119, 187);
+ --active-control-bg-color: #cdcdcd;
--focus-bg-color: hsl(214, 19%, 27%);
--toolbar-bg-color: #333333;
--toolbar-hover-bg-color: #202020;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/module.json b/chromium/third_party/blink/renderer/devtools/front_end/ui/module.json
index bd5f5a1e4c9..0c504e5ea3c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/module.json
@@ -6,10 +6,18 @@
"host"
],
"scripts": [
+ ],
+ "modules": [
+ "Action.js",
+ "ActionDelegate.js",
+ "ARIAUtils.js",
+ "ContextFlavorListener.js",
+ "ui.js",
"XElement.js",
"Widget.js",
"View.js",
- "treeoutline.js",
+ "ViewManager.js",
+ "Treeoutline.js",
"InspectorView.js",
"ActionRegistry.js",
"ShortcutRegistry.js",
@@ -34,7 +42,7 @@
"ListModel.js",
"ListWidget.js",
"Panel.js",
- "Popover.js",
+ "PopoverHelper.js",
"ProgressIndicator.js",
"ResizerWidget.js",
"RemoteDebuggingTerminatedScreen.js",
@@ -54,7 +62,6 @@
"SuggestBox.js",
"TabbedPane.js",
"UIUtils.js",
- "ARIAUtils.js",
"ZoomManager.js",
"ShortcutsScreen.js",
"Geometry.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/tabbedPane.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/tabbedPane.css
index 0e94772ad6b..787ea4fd0f1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/tabbedPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/tabbedPane.css
@@ -48,7 +48,8 @@
.tabbed-pane-placeholder {
font-size: 14px;
text-align: center;
- margin-top: 20px;
+ width: fit-content;
+ margin: 20px auto 0px;
text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
line-height: 28px;
overflow: hidden;
@@ -59,6 +60,10 @@
white-space: nowrap;
}
+.tabbed-pane-placeholder-row[data-keyboard-focus="true"]:focus {
+ outline-width: unset;
+}
+
.tabbed-pane-placeholder-key {
flex: 1;
text-align: right;
@@ -67,6 +72,11 @@
text-overflow: ellipsis;
}
+.tabbed-pane-no-shortcut {
+ flex: 1;
+ text-align: center;
+}
+
.tabbed-pane-placeholder-value {
flex: 1;
text-align: left;
@@ -170,18 +180,15 @@
display: block;
}
-.tabbed-pane-header-tabs-drop-down-container:hover {
- background-color: rgb(229, 229, 229);
+.tabbed-pane-header-tabs-drop-down-container:hover,
+.tabbed-pane-header-tabs-drop-down-container[data-keyboard-focus="true"]:focus {
+ background-color: rgba(0, 0, 0, 0.08);
}
.tabbed-pane-header-tabs-drop-down-container.measuring {
visibility: hidden;
}
-.tabbed-pane-header-tabs-drop-down-container:hover {
- opacity: 1.0;
-}
-
.tabbed-pane-header-tabs-drop-down-container:active {
opacity: 0.8;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/textButton.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/textButton.css
index 05fd2cacd72..a918911498a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/textButton.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/textButton.css
@@ -44,6 +44,15 @@
color: #fff;
}
+.text-button.link-style {
+ background: none;
+ border: none;
+ padding: 0!important;
+ font: inherit;
+ cursor: pointer;
+ height: 18px;
+}
+
.text-button.primary-button:not(:disabled):focus,
.text-button.primary-button:not(:disabled):hover,
.text-button.primary-button:not(:disabled):active, -theme-preserve {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ui.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ui.js
new file mode 100644
index 00000000000..644b3ffe993
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ui.js
@@ -0,0 +1,126 @@
+// 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 './Widget.js';
+import './GlassPane.js';
+
+import * as Action from './Action.js';
+import * as ActionDelegate from './ActionDelegate.js';
+import * as ActionRegistry from './ActionRegistry.js';
+import * as ARIAUtils from './ARIAUtils.js';
+import * as Context from './Context.js';
+import * as ContextFlavorListener from './ContextFlavorListener.js';
+import * as ContextMenu from './ContextMenu.js';
+import * as Dialog from './Dialog.js';
+import * as DropTarget from './DropTarget.js';
+import * as EmptyWidget from './EmptyWidget.js';
+import * as FilterBar from './FilterBar.js';
+import * as FilterSuggestionBuilder from './FilterSuggestionBuilder.js';
+import * as ForwardedInputEventHandler from './ForwardedInputEventHandler.js';
+import * as Fragment from './Fragment.js';
+import * as Geometry from './Geometry.js';
+import * as GlassPane from './GlassPane.js';
+import * as HistoryInput from './HistoryInput.js';
+import * as Icon from './Icon.js';
+import * as Infobar from './Infobar.js';
+import * as InplaceEditor from './InplaceEditor.js';
+import * as InspectorView from './InspectorView.js';
+import * as KeyboardShortcut from './KeyboardShortcut.js';
+import * as ListControl from './ListControl.js';
+import * as ListModel from './ListModel.js';
+import * as ListWidget from './ListWidget.js';
+import * as Panel from './Panel.js';
+import * as PopoverHelper from './PopoverHelper.js';
+import * as ProgressIndicator from './ProgressIndicator.js';
+import * as RemoteDebuggingTerminatedScreen from './RemoteDebuggingTerminatedScreen.js';
+import * as ReportView from './ReportView.js';
+import * as ResizerWidget from './ResizerWidget.js';
+import * as RootView from './RootView.js';
+import * as SearchableView from './SearchableView.js';
+import * as SegmentedButton from './SegmentedButton.js';
+import * as SettingsUI from './SettingsUI.js';
+import * as ShortcutRegistry from './ShortcutRegistry.js';
+import * as ShortcutsScreen from './ShortcutsScreen.js';
+import * as SoftContextMenu from './SoftContextMenu.js';
+import * as SoftDropDown from './SoftDropDown.js';
+import * as SplitWidget from './SplitWidget.js';
+import * as SuggestBox from './SuggestBox.js';
+import * as SyntaxHighlighter from './SyntaxHighlighter.js';
+import * as TabbedPane from './TabbedPane.js';
+import * as TargetCrashedScreen from './TargetCrashedScreen.js';
+import * as TextEditor from './TextEditor.js';
+import * as TextPrompt from './TextPrompt.js';
+import * as ThrottledWidget from './ThrottledWidget.js';
+import * as Toolbar from './Toolbar.js';
+import * as Tooltip from './Tooltip.js';
+import * as Treeoutline from './Treeoutline.js';
+import * as UIUtils from './UIUtils.js';
+import * as View from './View.js';
+import * as ViewManager from './ViewManager.js';
+import * as Widget from './Widget.js';
+import * as XElement from './XElement.js';
+import * as XLink from './XLink.js';
+import * as XWidget from './XWidget.js';
+import * as ZoomManager from './ZoomManager.js';
+
+export {
+ Action,
+ ActionDelegate,
+ ActionRegistry,
+ ARIAUtils,
+ Context,
+ ContextFlavorListener,
+ ContextMenu,
+ Dialog,
+ DropTarget,
+ EmptyWidget,
+ FilterBar,
+ FilterSuggestionBuilder,
+ ForwardedInputEventHandler,
+ Fragment,
+ Geometry,
+ GlassPane,
+ HistoryInput,
+ Icon,
+ Infobar,
+ InplaceEditor,
+ InspectorView,
+ KeyboardShortcut,
+ ListControl,
+ ListModel,
+ ListWidget,
+ Panel,
+ PopoverHelper,
+ ProgressIndicator,
+ RemoteDebuggingTerminatedScreen,
+ ReportView,
+ ResizerWidget,
+ RootView,
+ SearchableView,
+ SegmentedButton,
+ SettingsUI,
+ ShortcutRegistry,
+ ShortcutsScreen,
+ SoftContextMenu,
+ SoftDropDown,
+ SplitWidget,
+ SuggestBox,
+ SyntaxHighlighter,
+ TabbedPane,
+ TargetCrashedScreen,
+ TextEditor,
+ TextPrompt,
+ ThrottledWidget,
+ Toolbar,
+ Tooltip,
+ Treeoutline,
+ UIUtils,
+ View,
+ ViewManager,
+ Widget,
+ XElement,
+ XLink,
+ XWidget,
+ ZoomManager,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp
index bfa706ac026..5a861bfe23f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ui_strings.grdp
@@ -85,7 +85,7 @@
Step out
</message>
<message name="IDS_DEVTOOLS_44ac014b674d7d86a04702e6fd1fa858" desc="Text in a dialog box showing how to reconnect to DevTools when remote debugging has been terminated">
- Reconnect when ready by reopening DevTools.
+ Reconnect when ready by reopening <ph name="LOCKED_1">DevTools</ph>.
</message>
<message name="IDS_DEVTOOLS_45b471827af8ba9628e1914afbb13980" desc="Minutes format in UIUtils">
<ph name="PH1">$1.1f<ex>2.2</ex></ph> min
@@ -136,13 +136,13 @@
Save profile
</message>
<message name="IDS_DEVTOOLS_63e29f78b2e7788d9234a5790897fa71" desc="Text in dialog box when the target page crashed">
- DevTools was disconnected from the page.
+ <ph name="LOCKED_1">DevTools</ph> was disconnected from the page.
</message>
<message name="IDS_DEVTOOLS_650654cb12c12b00e68b4384e0aede82" desc="Aria alert to read the suggestion for the suggestion box when typing in text editor">
<ph name="THIS__ONLYCOMPLETION_TEXT">$1s<ex>name</ex></ph>, suggestion
</message>
<message name="IDS_DEVTOOLS_678b7bbae3b9b67cee8bce1fac3067d7" desc="Text for a hyperlink to the shortcut documentation in Shortcuts page">
- Full list of DevTools keyboard shortcuts and gestures
+ Full list of <ph name="LOCKED_1">DevTools</ph> keyboard shortcuts and gestures
</message>
<message name="IDS_DEVTOOLS_6e0e121820384f135321cb766273f4da" desc="Text in the Shortcuts page to explain a keyboard shortcut (soft undo in text editor)">
Soft undo
@@ -178,7 +178,7 @@
Zoom in
</message>
<message name="IDS_DEVTOOLS_7cf206a681131cf4d86fc190f2d9ad27" desc="Text on a button to reconnect Devtools when remote debugging terminated">
- Reconnect DevTools
+ Reconnect <ph name="LOCKED_1">DevTools</ph>
</message>
<message name="IDS_DEVTOOLS_7dce122004969d56ae2e0245cb754d35" desc="Text on a button to start editing text">
Edit
@@ -193,7 +193,7 @@
Layers Panel
</message>
<message name="IDS_DEVTOOLS_86e8f8f8327d28b74e5bd3ab581f77ee" desc="Text that appears when hover over the filter bar in the Network tool">
- e.g. /small[\d]+/ url:a.com/b
+ e.g. <ph name="LOCKED_1">/small[\d]+/ url:a.com/b</ph>
</message>
<message name="IDS_DEVTOOLS_89345110b204ed302eddff2ddbd0f4d9" desc="Text in the Shortcuts page to explain a keyboard shortcut (enable toggle breakpoint shortcut in debugger)">
Toggle breakpoint enabled
@@ -235,7 +235,7 @@
Toggle all breakpoints
</message>
<message name="IDS_DEVTOOLS_a950da8e902568f9a6879abe4313efe7" desc="Text content of content element">
- Once page is reloaded, DevTools will automatically reconnect.
+ Once page is reloaded, <ph name="LOCKED_1">DevTools</ph> will automatically reconnect.
</message>
<message name="IDS_DEVTOOLS_ad91a1da588ce256d30b1af38f78f84e" desc="Accessibility label for unchecked items in the SoftContextMenu">
unchecked
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js
index 9c35e34811d..495214e4fdb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextContentBuilder.js
@@ -21,8 +21,9 @@ WebAudio.ContextDetailBuilder = class {
this._addTitle(title, context.contextId);
this._addEntry(ls`State`, context.contextState);
this._addEntry(ls`Sample Rate`, context.sampleRate, 'Hz');
- if (context.contextType === 'realtime')
+ if (context.contextType === 'realtime') {
this._addEntry(ls`Callback Buffer Size`, context.callbackBufferSize, 'frames');
+ }
this._addEntry(ls`Max Output Channels`, context.maxOutputChannelCount, 'ch');
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
index 7fc659d6391..c71eff469af 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
@@ -6,19 +6,22 @@
* @implements {UI.SoftDropDown.Delegate<!Protocol.WebAudio.BaseAudioContext>}
*/
WebAudio.AudioContextSelector = class extends Common.Object {
- constructor(title) {
+ constructor() {
super();
+ /** @type {string} */
+ this._placeholderText = ls`(no recordings)`;
+
/** @type {!UI.ListModel<!Protocol.WebAudio.BaseAudioContext>} */
this._items = new UI.ListModel();
/** @type {!UI.SoftDropDown<!Protocol.WebAudio.BaseAudioContext>} */
this._dropDown = new UI.SoftDropDown(this._items, this);
- this._dropDown.setPlaceholderText(ls`(no recordings)`);
+ this._dropDown.setPlaceholderText(this._placeholderText);
this._toolbarItem = new UI.ToolbarItem(this._dropDown.element);
this._toolbarItem.setEnabled(false);
- this._toolbarItem.setTitle(title);
+ this._toolbarItem.setTitle(ls`Audio context: ${this._placeholderText}`);
this._items.addEventListener(UI.ListModel.Events.ItemsReplaced, this._onListItemReplaced, this);
this._toolbarItem.element.classList.add('toolbar-has-dropdown');
@@ -27,7 +30,11 @@ WebAudio.AudioContextSelector = class extends Common.Object {
}
_onListItemReplaced() {
- this._toolbarItem.setEnabled(!!this._items.length);
+ const hasItems = !!this._items.length;
+ this._toolbarItem.setEnabled(hasItems);
+ if (!hasItems) {
+ this._toolbarItem.setTitle(ls`Audio context: ${this._placeholderText}`);
+ }
}
/**
@@ -38,8 +45,9 @@ WebAudio.AudioContextSelector = class extends Common.Object {
this._items.insert(this._items.length, context);
// Select if this is the first item.
- if (this._items.length === 1)
+ if (this._items.length === 1) {
this._dropDown.selectItem(context);
+ }
}
/**
@@ -48,8 +56,9 @@ WebAudio.AudioContextSelector = class extends Common.Object {
contextDestroyed(event) {
const contextId = /** @type {!Protocol.WebAudio.GraphObjectId} */ (event.data);
const contextIndex = this._items.findIndex(context => context.contextId === contextId);
- if (contextIndex > -1)
+ if (contextIndex > -1) {
this._items.remove(contextIndex);
+ }
}
/**
@@ -59,13 +68,13 @@ WebAudio.AudioContextSelector = class extends Common.Object {
const changedContext = /** @type {!Protocol.WebAudio.BaseAudioContext} */ (event.data);
const contextIndex = this._items.findIndex(context => context.contextId === changedContext.contextId);
if (contextIndex > -1) {
- this._items.remove(contextIndex);
- this._items.insert(contextIndex, changedContext);
+ this._items.replace(contextIndex, changedContext);
// If the changed context is currently selected by user. Re-select it
// because the actual element is replaced with a new one.
- if (this._selectedContext && this._selectedContext.contextId === changedContext.contextId)
+ if (this._selectedContext && this._selectedContext.contextId === changedContext.contextId) {
this._dropDown.selectItem(changedContext);
+ }
}
}
@@ -78,7 +87,7 @@ WebAudio.AudioContextSelector = class extends Common.Object {
const element = createElementWithClass('div');
const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'web_audio/audioContextSelector.css');
const title = shadowRoot.createChild('div', 'title');
- title.createTextChild(this.titleFor(item).trimEnd(100));
+ title.createTextChild(this.titleFor(item).trimEndWithMaxLength(100));
return element;
}
@@ -86,8 +95,9 @@ WebAudio.AudioContextSelector = class extends Common.Object {
* @return {?Protocol.WebAudio.BaseAudioContext}
*/
selectedContext() {
- if (!this._selectedContext)
+ if (!this._selectedContext) {
return null;
+ }
return this._selectedContext;
}
@@ -100,10 +110,12 @@ WebAudio.AudioContextSelector = class extends Common.Object {
* @param {?Element} toElement
*/
highlightedItemChanged(from, to, fromElement, toElement) {
- if (fromElement)
+ if (fromElement) {
fromElement.classList.remove('highlighted');
- if (toElement)
+ }
+ if (toElement) {
toElement.classList.add('highlighted');
+ }
}
/**
@@ -120,12 +132,15 @@ WebAudio.AudioContextSelector = class extends Common.Object {
* @param {?Protocol.WebAudio.BaseAudioContext} item
*/
itemSelected(item) {
- if (!item)
+ if (!item) {
return;
+ }
// It's possible that no context is selected yet.
- if (!this._selectedContext || this._selectedContext.contextId !== item.contextId)
+ if (!this._selectedContext || this._selectedContext.contextId !== item.contextId) {
this._selectedContext = item;
+ this._toolbarItem.setTitle(ls`Audio context: ${this.titleFor(item)}`);
+ }
this.dispatchEventToListeners(WebAudio.AudioContextSelector.Events.ContextSelected, item);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js
index 19a856b8c25..66e8ca7194e 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioModel.js
@@ -47,14 +47,16 @@ WebAudio.WebAudioModel = class extends SDK.SDKModel {
* @return {!Promise}
*/
resumeModel() {
- if (!this._enabled)
+ if (!this._enabled) {
return Promise.resolve();
+ }
return this._agent.enable();
}
ensureEnabled() {
- if (this._enabled)
+ if (this._enabled) {
return;
+ }
this._agent.enable();
this._enabled = true;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js
index 961659624a9..dba3cd6c1e6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/WebAudioView.js
@@ -14,7 +14,7 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
// Creates the toolbar.
const toolbarContainer = this.contentElement.createChild(
'div', 'web-audio-toolbar-container vbox');
- this._contextSelector = new WebAudio.AudioContextSelector(ls`BaseAudioContexts`);
+ this._contextSelector = new WebAudio.AudioContextSelector();
const toolbar = new UI.Toolbar('web-audio-toolbar', toolbarContainer);
toolbar.appendToolbarItem(UI.Toolbar.createActionButtonForId('components.collect-garbage'));
toolbar.appendSeparator();
@@ -53,16 +53,18 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
*/
wasShown() {
super.wasShown();
- for (const model of SDK.targetManager.models(WebAudio.WebAudioModel))
+ for (const model of SDK.targetManager.models(WebAudio.WebAudioModel)) {
this._addEventListeners(model);
+ }
}
/**
* @override
*/
willHide() {
- for (const model of SDK.targetManager.models(WebAudio.WebAudioModel))
+ for (const model of SDK.targetManager.models(WebAudio.WebAudioModel)) {
this._removeEventListeners(model);
+ }
}
/**
@@ -70,8 +72,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
* @param {!WebAudio.WebAudioModel} webAudioModel
*/
modelAdded(webAudioModel) {
- if (this.isShowing())
+ if (this.isShowing()) {
this._addEventListeners(webAudioModel);
+ }
}
/**
@@ -167,15 +170,17 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
*/
_contextChanged(event) {
const context = /** @type {!Protocol.WebAudio.BaseAudioContext} */ (event.data);
- if (!this._graphManager.hasContext(context.contextId))
+ if (!this._graphManager.hasContext(context.contextId)) {
return;
+ }
this._contextSelector.contextChanged(event);
}
_reset() {
- if (this._landingPage.isShowing())
+ if (this._landingPage.isShowing()) {
this._landingPage.detach();
+ }
this._contextSelector.reset();
this._detailViewContainer.removeChildren();
this._landingPage.show(this._detailViewContainer);
@@ -192,8 +197,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioListenerCreated(event) {
const listener = /** @type {!Protocol.WebAudio.AudioListener} */ (event.data);
const graph = this._graphManager.getGraph(listener.contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.addNode({
nodeId: listener.listenerId,
nodeType: 'Listener',
@@ -208,8 +214,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioListenerWillBeDestroyed(event) {
const {contextId, listenerId} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.removeNode(listenerId);
}
@@ -219,8 +226,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioNodeCreated(event) {
const node = /** @type {!Protocol.WebAudio.AudioNode} */ (event.data);
const graph = this._graphManager.getGraph(node.contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.addNode({
nodeId: node.nodeId,
nodeType: node.nodeType,
@@ -235,8 +243,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioNodeWillBeDestroyed(event) {
const {contextId, nodeId} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.removeNode(nodeId);
}
@@ -246,8 +255,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioParamCreated(event) {
const param = /** @type {!Protocol.WebAudio.AudioParam} */ (event.data);
const graph = this._graphManager.getGraph(param.contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.addParam({
paramId: param.paramId,
paramType: param.paramType,
@@ -261,8 +271,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_audioParamWillBeDestroyed(event) {
const {contextId, paramId} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.removeParam(paramId);
}
@@ -272,8 +283,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_nodesConnected(event) {
const {contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.addNodeToNodeConnection({
sourceId,
destinationId,
@@ -288,8 +300,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_nodesDisconnected(event) {
const {contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
graph.removeNodeToNodeConnection({
sourceId,
destinationId,
@@ -304,13 +317,15 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_nodeParamConnected(event) {
const {contextId, sourceId, destinationId, sourceOutputIndex} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
// Since the destinationId is AudioParamId, we need to find the nodeId as the
// real destinationId.
const nodeId = graph.getNodeIdByParamId(destinationId);
- if (!nodeId)
+ if (!nodeId) {
return;
+ }
graph.addNodeToParamConnection({
sourceId,
destinationId: nodeId,
@@ -325,13 +340,15 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
_nodeParamDisconnected(event) {
const {contextId, sourceId, destinationId, sourceOutputIndex} = event.data;
const graph = this._graphManager.getGraph(contextId);
- if (!graph)
+ if (!graph) {
return;
+ }
// Since the destinationId is AudioParamId, we need to find the nodeId as the
// real destinationId.
const nodeId = graph.getNodeIdByParamId(destinationId);
- if (!nodeId)
+ if (!nodeId) {
return;
+ }
graph.removeNodeToParamConnection({
sourceId,
destinationId: nodeId,
@@ -344,8 +361,9 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
* @param {!Protocol.WebAudio.BaseAudioContext} context
*/
_updateDetailView(context) {
- if (this._landingPage.isShowing())
+ if (this._landingPage.isShowing()) {
this._landingPage.detach();
+ }
const detailBuilder = new WebAudio.ContextDetailBuilder(context);
this._detailViewContainer.removeChildren();
this._detailViewContainer.appendChild(detailBuilder.getFragment());
@@ -376,11 +394,13 @@ WebAudio.WebAudioView = class extends UI.ThrottledWidget {
for (const model of SDK.targetManager.models(WebAudio.WebAudioModel)) {
// Display summary only for real-time context.
if (context.contextType === 'realtime') {
- if (!this._graphManager.hasContext(context.contextId))
+ if (!this._graphManager.hasContext(context.contextId)) {
continue;
+ }
const realtimeData = await model.requestRealtimeData(context.contextId);
- if (realtimeData)
+ if (realtimeData) {
this._updateSummaryBar(context.contextId, realtimeData);
+ }
} else {
this._clearSummaryBar();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphManager.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphManager.js
index b1848975ea8..1ac22bfc8a6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphManager.js
@@ -26,8 +26,9 @@ WebAudio.GraphVisualizer.GraphManager = class extends Common.Object {
* @param {!Protocol.WebAudio.GraphObjectId} contextId
*/
destroyContext(contextId) {
- if (!this._graphMapByContextId.has(contextId))
+ if (!this._graphMapByContextId.has(contextId)) {
return;
+ }
const graph = this._graphMapByContextId.get(contextId);
graph.removeEventListener(WebAudio.GraphVisualizer.GraphView.Events.ShouldRedraw, this._notifyShouldRedraw, this);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphView.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphView.js
index c61d4146aa7..dc2837f6110 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/GraphView.js
@@ -19,15 +19,15 @@ WebAudio.GraphVisualizer.GraphView = class extends Common.Object {
/**
* For each node ID, keep a set of all out-bound edge IDs.
- * @type {!Multimap<!Protocol.WebAudio.GraphObjectId, string>}
+ * @type {!Platform.Multimap<!Protocol.WebAudio.GraphObjectId, string>}
*/
- this._outboundEdgeMap = new Multimap();
+ this._outboundEdgeMap = new Platform.Multimap();
/**
* For each node ID, keep a set of all in-bound edge IDs.
- * @type {!Multimap<!Protocol.WebAudio.GraphObjectId, string>}
+ * @type {!Platform.Multimap<!Protocol.WebAudio.GraphObjectId, string>}
*/
- this._inboundEdgeMap = new Multimap();
+ this._inboundEdgeMap = new Platform.Multimap();
// Use concise node label to replace the long UUID.
// Each graph has its own label generator so that the label starts from 0.
@@ -166,8 +166,9 @@ WebAudio.GraphVisualizer.GraphView = class extends Common.Object {
_addEdge(edge) {
const sourceId = edge.sourceId;
// Do nothing if the edge already exists.
- if (this._outboundEdgeMap.hasValue(sourceId, edge.id))
+ if (this._outboundEdgeMap.hasValue(sourceId, edge.id)) {
return;
+ }
this._edges.set(edge.id, edge);
this._outboundEdgeMap.set(sourceId, edge.id);
@@ -183,8 +184,9 @@ WebAudio.GraphVisualizer.GraphView = class extends Common.Object {
*/
_removeEdge(edgeId) {
const edge = this._edges.get(edgeId);
- if (!edge)
+ if (!edge) {
return;
+ }
this._outboundEdgeMap.delete(edge.sourceId, edgeId);
this._inboundEdgeMap.delete(edge.destinationId, edgeId);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/NodeView.js b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/NodeView.js
index ea10aa8020d..33a0a7881ed 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/NodeView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/graph_visualizer/NodeView.js
@@ -78,8 +78,9 @@ WebAudio.GraphVisualizer.NodeView = class {
getPortsByType(type) {
const result = [];
this.ports.forEach(port => {
- if (port.type === type)
+ if (port.type === type) {
result.push(port);
+ }
});
return result;
}
@@ -235,8 +236,9 @@ WebAudio.GraphVisualizer.NodeLabelGenerator = class {
*/
generateLabel(nodeType) {
// To make the label concise, remove the suffix "Node" from the nodeType.
- if (nodeType.endsWith('Node'))
+ if (nodeType.endsWith('Node')) {
nodeType = nodeType.slice(0, nodeType.length - 4);
+ }
// Also, use an integer to replace the long UUID.
this._totalNumberOfNodes += 1;
@@ -252,8 +254,9 @@ WebAudio.GraphVisualizer.NodeLabelGenerator = class {
* @return {number}
*/
WebAudio.GraphVisualizer.measureTextWidth = (text, fontStyle) => {
- if (!WebAudio.GraphVisualizer._contextForFontTextMeasuring)
+ if (!WebAudio.GraphVisualizer._contextForFontTextMeasuring) {
WebAudio.GraphVisualizer._contextForFontTextMeasuring = createElement('canvas').getContext('2d');
+ }
const context = WebAudio.GraphVisualizer._contextForFontTextMeasuring;
context.save();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp
index 633ec443ebb..190df422631 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp
+++ b/chromium/third_party/blink/renderer/devtools/front_end/web_audio/web_audio_strings.grdp
@@ -21,8 +21,8 @@
<message name="IDS_DEVTOOLS_ab7799fb0ebb5a4167781f756efb820a" desc="Text in Audio Context Content Builder">
Callback Interval
</message>
- <message name="IDS_DEVTOOLS_b78dc7712ef83a078c1c68822d2a1a3f" desc="Text in Web Audio View">
- BaseAudioContexts
+ <message name="IDS_DEVTOOLS_d1adc6d57af38b75e7b7c3bb0b9a44ee" desc="Label prefix for an audio context selection">
+ Audio context: <ph name="THIS__PLACEHOLDERTEXT">$1s<ex>realtime (1e03ec)</ex></ph>
</message>
<message name="IDS_DEVTOOLS_f047f03535a9154caf9a858b5aed17c0" desc="Text in Audio Context Content Builder">
Current Time
@@ -30,4 +30,7 @@
<message name="IDS_DEVTOOLS_f579f693ac9ecb3fb9e822bf32028e13" desc="Text in Audio Context Content Builder">
Sample Rate
</message>
+ <message name="IDS_DEVTOOLS_a5ca0b5894324f8bb54bb9fffad29d1e" desc="A tags of WebAudio tool that can be searched in the command menu">
+ audio
+ </message>
</grit-part> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
index e5827b5e649..09f263de7f4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
@@ -9,8 +9,8 @@
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
<meta name="referrer" content="no-referrer">
- <script src="Runtime.js"></script>
- <script src="worker_app.js"></script>
+ <script type="module" src="root.js"></script>
+ <script defer src="worker_app.js"></script>
</head>
<body class="undocked" id="-blink-dev-tools"></body>
</html>
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.js b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.js
index 4cd27a8bd9b..68642793dea 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.js
@@ -2,4 +2,4 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-Runtime.startApplication('worker_app');
+Root.Runtime.startApplication('worker_app');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js b/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
index 5cca9a549b7..9105900e7c9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
@@ -19,12 +19,15 @@ WorkerMain.WorkerMain = class extends Common.Object {
SDK.ChildTargetManager.install(async ({target, waitingForDebugger}) => {
// Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
- if (target.parentTarget() || target.type() !== SDK.Target.Type.ServiceWorker || !waitingForDebugger)
+ if (target.parentTarget() || target.type() !== SDK.Target.Type.ServiceWorker || !waitingForDebugger) {
return;
+ }
const debuggerModel = target.model(SDK.DebuggerModel);
- if (!debuggerModel)
+ if (!debuggerModel) {
return;
- if (!debuggerModel.isReadyToPause())
+ }
+ if (!debuggerModel.isReadyToPause()) {
await debuggerModel.once(SDK.DebuggerModel.Events.DebuggerIsReadyToPause);
+ }
debuggerModel.pause();
});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_service/ServiceDispatcher.js b/chromium/third_party/blink/renderer/devtools/front_end/worker_service/ServiceDispatcher.js
index 7eb451fc879..ff6d9b505f5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_service/ServiceDispatcher.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_service/ServiceDispatcher.js
@@ -100,8 +100,9 @@ ServiceDispatcher = class {
}
_connectionClosed() {
- for (const object of this._objects.values())
+ for (const object of this._objects.values()) {
object.dispose();
+ }
this._objects.clear();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js b/chromium/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js
index 740a6ecdb4c..d22427c3250 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js
@@ -31,16 +31,17 @@
/**
* @unrestricted
*/
-Workspace.FileManager = class extends Common.Object {
+export default class FileManager extends Common.Object {
constructor() {
super();
/** @type {!Map<string, function(?{fileSystemPath: (string|undefined)})>} */
this._saveCallbacks = new Map();
- InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.SavedURL, this._savedURL, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.CanceledSaveURL, this._canceledSavedURL, this);
- InspectorFrontendHost.events.addEventListener(
- InspectorFrontendHostAPI.Events.AppendedToURL, this._appendedToURL, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.SavedURL, this._savedURL, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.CanceledSaveURL, this._canceledSavedURL, this);
+ Host.InspectorFrontendHost.events.addEventListener(
+ Host.InspectorFrontendHostAPI.Events.AppendedToURL, this._appendedToURL, this);
}
/**
@@ -52,7 +53,7 @@ Workspace.FileManager = class extends Common.Object {
save(url, content, forceSaveAs) {
// Remove this url from the saved URLs while it is being saved.
const result = new Promise(resolve => this._saveCallbacks.set(url, resolve));
- InspectorFrontendHost.save(url, content, forceSaveAs);
+ Host.InspectorFrontendHost.save(url, content, forceSaveAs);
return result;
}
@@ -63,8 +64,9 @@ Workspace.FileManager = class extends Common.Object {
const url = /** @type {string} */ (event.data.url);
const callback = this._saveCallbacks.get(url);
this._saveCallbacks.delete(url);
- if (callback)
+ if (callback) {
callback({fileSystemPath: /** @type {string} */ (event.data.fileSystemPath)});
+ }
}
/**
@@ -74,8 +76,9 @@ Workspace.FileManager = class extends Common.Object {
const url = /** @type {string} */ (event.data);
const callback = this._saveCallbacks.get(url);
this._saveCallbacks.delete(url);
- if (callback)
+ if (callback) {
callback(null);
+ }
}
/**
@@ -83,14 +86,14 @@ Workspace.FileManager = class extends Common.Object {
* @param {string} content
*/
append(url, content) {
- InspectorFrontendHost.append(url, content);
+ Host.InspectorFrontendHost.append(url, content);
}
/**
* @param {string} url
*/
close(url) {
- InspectorFrontendHost.close(url);
+ Host.InspectorFrontendHost.close(url);
}
/**
@@ -98,16 +101,28 @@ Workspace.FileManager = class extends Common.Object {
*/
_appendedToURL(event) {
const url = /** @type {string} */ (event.data);
- this.dispatchEventToListeners(Workspace.FileManager.Events.AppendedToURL, url);
+ this.dispatchEventToListeners(Events.AppendedToURL, url);
}
-};
+}
/** @enum {symbol} */
-Workspace.FileManager.Events = {
+export const Events = {
AppendedToURL: Symbol('AppendedToURL')
};
+/* Legacy exported object */
+self.Workspace = self.Workspace || {};
+
+/* Legacy exported object */
+Workspace = Workspace || {};
+
+/** @constructor */
+Workspace.FileManager = FileManager;
+
+/** @enum {symbol} */
+Workspace.FileManager.Events = Events;
+
/**
- * @type {?Workspace.FileManager}
+ * @type {?FileManager}
*/
-Workspace.fileManager;
+Workspace.fileManager; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace/UISourceCode.js b/chromium/third_party/blink/renderer/devtools/front_end/workspace/UISourceCode.js
index d4724e77b7b..543a003dc6a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/workspace/UISourceCode.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace/UISourceCode.js
@@ -31,7 +31,7 @@
* @implements {Common.ContentProvider}
* @unrestricted
*/
-Workspace.UISourceCode = class extends Common.Object {
+export default class UISourceCode extends Common.Object {
/**
* @param {!Workspace.Project} project
* @param {string} url
@@ -47,8 +47,9 @@ Workspace.UISourceCode = class extends Common.Object {
this._origin = parsedURL.securityOrigin();
this._parentURL = this._origin + parsedURL.folderPathComponents;
this._name = parsedURL.lastPathComponent;
- if (parsedURL.queryParams)
+ if (parsedURL.queryParams) {
this._name += '?' + parsedURL.queryParams;
+ }
} else {
this._origin = '';
this._parentURL = '';
@@ -56,18 +57,16 @@ Workspace.UISourceCode = class extends Common.Object {
}
this._contentType = contentType;
- /** @type {?Promise<?string>} */
+ /** @type {?Promise<!Common.DeferredContent>} */
this._requestContentPromise = null;
- /** @type {?Multimap<string, !Workspace.UISourceCode.LineMarker>} */
+ /** @type {?Platform.Multimap<string, !LineMarker>} */
this._decorations = null;
this._hasCommits = false;
- /** @type {?Set<!Workspace.UISourceCode.Message>} */
+ /** @type {?Set<!Message>} */
this._messages = null;
this._contentLoaded = false;
- /** @type {?string} */
+ /** @type {?Common.DeferredContent} */
this._content = null;
- /** @type {boolean|undefined} */
- this._contentEncoded;
this._forceLoadOnCheckContent = false;
this._checkingContent = false;
/** @type {?string} */
@@ -79,7 +78,7 @@ Workspace.UISourceCode = class extends Common.Object {
}
/**
- * @return {!Promise<?Workspace.UISourceCodeMetadata>}
+ * @return {!Promise<?UISourceCodeMetadata>}
*/
requestMetadata() {
return this._project.requestMetadata(this);
@@ -132,17 +131,19 @@ Workspace.UISourceCode = class extends Common.Object {
* @return {string}
*/
displayName(skipTrim) {
- if (!this._name)
+ if (!this._name) {
return Common.UIString('(index)');
+ }
let name = this._name;
try {
- if (this.project().type() === Workspace.projectTypes.FileSystem)
+ if (this.project().type() === Workspace.projectTypes.FileSystem) {
name = unescape(name);
- else
+ } else {
name = decodeURI(name);
+ }
} catch (e) {
}
- return skipTrim ? name : name.trimEnd(100);
+ return skipTrim ? name : name.trimEndWithMaxLength(100);
}
/**
@@ -167,7 +168,7 @@ Workspace.UISourceCode = class extends Common.Object {
* @param {string=} newName
* @param {string=} newURL
* @param {!Common.ResourceType=} newContentType
- * @this {Workspace.UISourceCode}
+ * @this {UISourceCode}
*/
function innerCallback(success, newName, newURL, newContentType) {
if (success) {
@@ -192,11 +193,13 @@ Workspace.UISourceCode = class extends Common.Object {
const oldURL = this._url;
this._url = this._url.substring(0, this._url.length - this._name.length) + name;
this._name = name;
- if (url)
+ if (url) {
this._url = url;
- if (contentType)
+ }
+ if (contentType) {
this._contentType = contentType;
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.TitleChanged, this);
+ }
+ this.dispatchEventToListeners(Events.TitleChanged, this);
this.project().workspace().dispatchEventToListeners(
Workspace.Workspace.Events.UISourceCodeRenamed, {oldURL: oldURL, uiSourceCode: this});
}
@@ -235,76 +238,83 @@ Workspace.UISourceCode = class extends Common.Object {
/**
* @override
- * @return {!Promise<?string>}
+ * @return {!Promise<!Common.DeferredContent>}
*/
requestContent() {
- if (this._requestContentPromise)
+ if (this._requestContentPromise) {
return this._requestContentPromise;
+ }
if (this._contentLoaded) {
- this._requestContentPromise = Promise.resolve(this._content);
- } else {
- let fulfill;
- this._requestContentPromise = new Promise(x => fulfill = x);
- this._project.requestFileContent(this, (content, encoded) => {
- if (!this._contentLoaded) {
- this._contentLoaded = true;
- this._content = content;
- this._contentEncoded = encoded;
- }
- fulfill(this._content);
- });
+ return Promise.resolve(/** @type {!Common.DeferredContent} */ (this._content));
}
+
+
+ this._requestContentPromise = this._requestContentImpl();
return this._requestContentPromise;
}
- checkContentUpdated() {
- if (!this._contentLoaded && !this._forceLoadOnCheckContent)
+ /**
+ * @returns {!Promise<!Common.DeferredContent>}
+ */
+ async _requestContentImpl() {
+ try {
+ const content = await this._project.requestFileContent(this);
+ if (!this._contentLoaded) {
+ this._contentLoaded = true;
+ this._content = content;
+ this._contentEncoded = content.isEncoded;
+ }
+ } catch (err) {
+ this._contentLoaded = true;
+ this._content = {error: err ? String(err) : '', isEncoded: false};
+ }
+
+ return /** @type {!Common.DeferredContent} */ (this._content);
+ }
+
+ async checkContentUpdated() {
+ if (!this._contentLoaded && !this._forceLoadOnCheckContent) {
return;
+ }
- if (!this._project.canSetFileContent() || this._checkingContent)
+ if (!this._project.canSetFileContent() || this._checkingContent) {
return;
+ }
this._checkingContent = true;
- this._project.requestFileContent(this, contentLoaded.bind(this));
-
- /**
- * @param {?string} updatedContent
- * @param {boolean} encoded
- * @this {Workspace.UISourceCode}
- */
- async function contentLoaded(updatedContent, encoded) {
- this._checkingContent = false;
- if (updatedContent === null) {
- const workingCopy = this.workingCopy();
- this._contentCommitted('', false);
- this.setWorkingCopy(workingCopy);
- return;
- }
- if (this._lastAcceptedContent === updatedContent)
- return;
+ const updatedContent = await this._project.requestFileContent(this);
+ this._checkingContent = false;
+ if (updatedContent.content === null) {
+ const workingCopy = this.workingCopy();
+ this._contentCommitted('', false);
+ this.setWorkingCopy(workingCopy);
+ return;
+ }
+ if (this._lastAcceptedContent === updatedContent.content) {
+ return;
+ }
- if (this._content === updatedContent) {
- this._lastAcceptedContent = null;
- return;
- }
+ if (this._content && this._content.content === updatedContent.content) {
+ this._lastAcceptedContent = null;
+ return;
+ }
- if (!this.isDirty() || this._workingCopy === updatedContent) {
- this._contentCommitted(/** @type {string} */ (updatedContent), false);
- return;
- }
+ if (!this.isDirty() || this._workingCopy === updatedContent.content) {
+ this._contentCommitted(/** @type {string} */ (updatedContent.content), false);
+ return;
+ }
- await Common.Revealer.reveal(this);
+ await Common.Revealer.reveal(this);
- // Make sure we are in the next frame before stopping the world with confirm
- await new Promise(resolve => setTimeout(resolve, 0));
+ // Make sure we are in the next frame before stopping the world with confirm
+ await new Promise(resolve => setTimeout(resolve, 0));
- const shouldUpdate =
- window.confirm(Common.UIString('This file was changed externally. Would you like to reload it?'));
- if (shouldUpdate)
- this._contentCommitted(/** @type {string} */ (updatedContent), false);
- else
- this._lastAcceptedContent = updatedContent;
+ const shouldUpdate = window.confirm(ls`This file was changed externally. Would you like to reload it?`);
+ if (shouldUpdate) {
+ this._contentCommitted(/** @type {string} */ (updatedContent.content), false);
+ } else {
+ this._lastAcceptedContent = updatedContent.content;
}
}
@@ -316,8 +326,9 @@ Workspace.UISourceCode = class extends Common.Object {
* @param {string} content
*/
_commitContent(content) {
- if (this._project.canSetFileContent())
+ if (this._project.canSetFileContent()) {
this._project.setFileContent(this, content, false);
+ }
this._contentCommitted(content, true);
}
@@ -327,7 +338,7 @@ Workspace.UISourceCode = class extends Common.Object {
*/
_contentCommitted(content, committedByUser) {
this._lastAcceptedContent = null;
- this._content = content;
+ this._content = {content, isEncoded: false};
this._contentLoaded = true;
this._requestContentPromise = null;
@@ -335,10 +346,11 @@ Workspace.UISourceCode = class extends Common.Object {
this._innerResetWorkingCopy();
const data = {uiSourceCode: this, content, encoded: this._contentEncoded};
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.WorkingCopyCommitted, data);
+ this.dispatchEventToListeners(Events.WorkingCopyCommitted, data);
this._project.workspace().dispatchEventToListeners(Workspace.Workspace.Events.WorkingCopyCommitted, data);
- if (committedByUser)
+ if (committedByUser) {
this._project.workspace().dispatchEventToListeners(Workspace.Workspace.Events.WorkingCopyCommittedByUser, data);
+ }
}
/**
@@ -363,9 +375,10 @@ Workspace.UISourceCode = class extends Common.Object {
this._workingCopy = this._workingCopyGetter();
this._workingCopyGetter = null;
}
- if (this.isDirty())
+ if (this.isDirty()) {
return /** @type {string} */ (this._workingCopy);
- return this._content || '';
+ }
+ return (this._content && this._content.content) || '';
}
resetWorkingCopy() {
@@ -393,8 +406,9 @@ Workspace.UISourceCode = class extends Common.Object {
*/
setContent(content, isBase64) {
this._contentEncoded = isBase64;
- if (this._project.canSetFileContent())
+ if (this._project.canSetFileContent()) {
this._project.setFileContent(this, content, isBase64);
+ }
this._contentCommitted(content, true);
}
@@ -408,21 +422,23 @@ Workspace.UISourceCode = class extends Common.Object {
_workingCopyChanged() {
this._removeAllMessages();
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.WorkingCopyChanged, this);
+ this.dispatchEventToListeners(Events.WorkingCopyChanged, this);
this._project.workspace().dispatchEventToListeners(
Workspace.Workspace.Events.WorkingCopyChanged, {uiSourceCode: this});
}
removeWorkingCopyGetter() {
- if (!this._workingCopyGetter)
+ if (!this._workingCopyGetter) {
return;
+ }
this._workingCopy = this._workingCopyGetter();
this._workingCopyGetter = null;
}
commitWorkingCopy() {
- if (this.isDirty())
+ if (this.isDirty()) {
this._commitContent(this.workingCopy());
+ }
}
/**
@@ -440,10 +456,17 @@ Workspace.UISourceCode = class extends Common.Object {
}
/**
- * @return {?string}
+ * @return {string}
*/
content() {
- return this._content;
+ return (this._content && this._content.content) || '';
+ }
+
+ /**
+ * @return {?string}
+ */
+ loadError() {
+ return (this._content && this._content.error);
}
/**
@@ -455,8 +478,9 @@ Workspace.UISourceCode = class extends Common.Object {
*/
searchInContent(query, caseSensitive, isRegex) {
const content = this.content();
- if (!content)
+ if (!content) {
return this._project.searchInFileContent(this, query, caseSensitive, isRegex);
+ }
return Promise.resolve(Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex));
}
@@ -470,27 +494,28 @@ Workspace.UISourceCode = class extends Common.Object {
/**
* @param {number} lineNumber
* @param {number=} columnNumber
- * @return {!Workspace.UILocation}
+ * @return {!UILocation}
*/
uiLocation(lineNumber, columnNumber) {
- if (typeof columnNumber === 'undefined')
+ if (typeof columnNumber === 'undefined') {
columnNumber = 0;
- return new Workspace.UILocation(this, lineNumber, columnNumber);
+ }
+ return new UILocation(this, lineNumber, columnNumber);
}
/**
- * @return {!Set<!Workspace.UISourceCode.Message>}
+ * @return {!Set<!Message>}
*/
messages() {
return this._messages ? new Set(this._messages) : new Set();
}
/**
- * @param {!Workspace.UISourceCode.Message.Level} level
+ * @param {!Message.Level} level
* @param {string} text
* @param {number} lineNumber
* @param {number=} columnNumber
- * @return {!Workspace.UISourceCode.Message} message
+ * @return {!Message} message
*/
addLineMessage(level, text, lineNumber, columnNumber) {
return this.addMessage(
@@ -498,33 +523,37 @@ Workspace.UISourceCode = class extends Common.Object {
}
/**
- * @param {!Workspace.UISourceCode.Message.Level} level
+ * @param {!Message.Level} level
* @param {string} text
* @param {!TextUtils.TextRange} range
- * @return {!Workspace.UISourceCode.Message} message
+ * @return {!Message} message
*/
addMessage(level, text, range) {
- const message = new Workspace.UISourceCode.Message(this, level, text, range);
- if (!this._messages)
+ const message = new Message(this, level, text, range);
+ if (!this._messages) {
this._messages = new Set();
+ }
this._messages.add(message);
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.MessageAdded, message);
+ this.dispatchEventToListeners(Events.MessageAdded, message);
return message;
}
/**
- * @param {!Workspace.UISourceCode.Message} message
+ * @param {!Message} message
*/
removeMessage(message) {
- if (this._messages && this._messages.delete(message))
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.MessageRemoved, message);
+ if (this._messages && this._messages.delete(message)) {
+ this.dispatchEventToListeners(Events.MessageRemoved, message);
+ }
}
_removeAllMessages() {
- if (!this._messages)
+ if (!this._messages) {
return;
- for (const message of this._messages)
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.MessageRemoved, message);
+ }
+ for (const message of this._messages) {
+ this.dispatchEventToListeners(Events.MessageRemoved, message);
+ }
this._messages = null;
}
@@ -543,53 +572,55 @@ Workspace.UISourceCode = class extends Common.Object {
* @param {?} data
*/
addDecoration(range, type, data) {
- const marker = new Workspace.UISourceCode.LineMarker(range, type, data);
- if (!this._decorations)
- this._decorations = new Multimap();
+ const marker = new LineMarker(range, type, data);
+ if (!this._decorations) {
+ this._decorations = new Platform.Multimap();
+ }
this._decorations.set(type, marker);
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.LineDecorationAdded, marker);
+ this.dispatchEventToListeners(Events.LineDecorationAdded, marker);
}
/**
* @param {string} type
*/
removeDecorationsForType(type) {
- if (!this._decorations)
+ if (!this._decorations) {
return;
+ }
const markers = this._decorations.get(type);
this._decorations.deleteAll(type);
markers.forEach(marker => {
- this.dispatchEventToListeners(Workspace.UISourceCode.Events.LineDecorationRemoved, marker);
+ this.dispatchEventToListeners(Events.LineDecorationRemoved, marker);
});
}
/**
- * @return {!Array<!Workspace.UISourceCode.LineMarker>}
+ * @return {!Array<!LineMarker>}
*/
allDecorations() {
return this._decorations ? this._decorations.valuesArray() : [];
}
removeAllDecorations() {
- if (!this._decorations)
+ if (!this._decorations) {
return;
+ }
const decorationList = this._decorations.valuesArray();
this._decorations.clear();
- decorationList.forEach(
- marker => this.dispatchEventToListeners(Workspace.UISourceCode.Events.LineDecorationRemoved, marker));
+ decorationList.forEach(marker => this.dispatchEventToListeners(Events.LineDecorationRemoved, marker));
}
/**
* @param {string} type
- * @return {?Set<!Workspace.UISourceCode.LineMarker>}
+ * @return {?Set<!LineMarker>}
*/
decorationsForType(type) {
return this._decorations ? this._decorations.get(type) : null;
}
-};
+}
/** @enum {symbol} */
-Workspace.UISourceCode.Events = {
+export const Events = {
WorkingCopyChanged: Symbol('WorkingCopyChanged'),
WorkingCopyCommitted: Symbol('WorkingCopyCommitted'),
TitleChanged: Symbol('TitleChanged'),
@@ -602,9 +633,9 @@ Workspace.UISourceCode.Events = {
/**
* @unrestricted
*/
-Workspace.UILocation = class {
+export class UILocation {
/**
- * @param {!Workspace.UISourceCode} uiSourceCode
+ * @param {!UISourceCode} uiSourceCode
* @param {number} lineNumber
* @param {number} columnNumber
*/
@@ -620,8 +651,9 @@ Workspace.UILocation = class {
*/
linkText(skipTrim) {
let linkText = this.uiSourceCode.displayName(skipTrim);
- if (typeof this.lineNumber === 'number')
+ if (typeof this.lineNumber === 'number') {
linkText += ':' + (this.lineNumber + 1);
+ }
return linkText;
}
@@ -641,8 +673,8 @@ Workspace.UILocation = class {
}
/**
- * @param {!Workspace.UILocation} location1
- * @param {!Workspace.UILocation} location2
+ * @param {!UILocation} location1
+ * @param {!UILocation} location2
* @return {number}
*/
static comparator(location1, location2) {
@@ -650,25 +682,27 @@ Workspace.UILocation = class {
}
/**
- * @param {!Workspace.UILocation} other
+ * @param {!UILocation} other
* @return {number}
*/
compareTo(other) {
- if (this.uiSourceCode.url() !== other.uiSourceCode.url())
+ if (this.uiSourceCode.url() !== other.uiSourceCode.url()) {
return this.uiSourceCode.url() > other.uiSourceCode.url() ? 1 : -1;
- if (this.lineNumber !== other.lineNumber)
+ }
+ if (this.lineNumber !== other.lineNumber) {
return this.lineNumber - other.lineNumber;
+ }
return this.columnNumber - other.columnNumber;
}
-};
+}
/**
* @unrestricted
*/
-Workspace.UISourceCode.Message = class {
+export class Message {
/**
- * @param {!Workspace.UISourceCode} uiSourceCode
- * @param {!Workspace.UISourceCode.Message.Level} level
+ * @param {!UISourceCode} uiSourceCode
+ * @param {!Message.Level} level
* @param {string} text
* @param {!TextUtils.TextRange} range
*/
@@ -680,14 +714,14 @@ Workspace.UISourceCode.Message = class {
}
/**
- * @return {!Workspace.UISourceCode}
+ * @return {!UISourceCode}
*/
uiSourceCode() {
return this._uiSourceCode;
}
/**
- * @return {!Workspace.UISourceCode.Message.Level}
+ * @return {!Message.Level}
*/
level() {
return this._level;
@@ -722,7 +756,7 @@ Workspace.UISourceCode.Message = class {
}
/**
- * @param {!Workspace.UISourceCode.Message} another
+ * @param {!Message} another
* @return {boolean}
*/
isEqual(another) {
@@ -733,12 +767,12 @@ Workspace.UISourceCode.Message = class {
remove() {
this._uiSourceCode.removeMessage(this);
}
-};
+}
/**
* @enum {string}
*/
-Workspace.UISourceCode.Message.Level = {
+Message.Level = {
Error: 'Error',
Warning: 'Warning'
};
@@ -746,7 +780,7 @@ Workspace.UISourceCode.Message.Level = {
/**
* @unrestricted
*/
-Workspace.UISourceCode.LineMarker = class {
+export class LineMarker {
/**
* @param {!TextUtils.TextRange} range
* @param {string} type
@@ -778,12 +812,12 @@ Workspace.UISourceCode.LineMarker = class {
data() {
return this._data;
}
-};
+}
/**
* @unrestricted
*/
-Workspace.UISourceCodeMetadata = class {
+export class UISourceCodeMetadata {
/**
* @param {?Date} modificationTime
* @param {?number} contentSize
@@ -792,4 +826,28 @@ Workspace.UISourceCodeMetadata = class {
this.modificationTime = modificationTime;
this.contentSize = contentSize;
}
-};
+}
+
+/* Legacy exported object */
+self.Workspace = self.Workspace || {};
+
+/* Legacy exported object */
+Workspace = Workspace || {};
+
+/** @constructor */
+Workspace.UISourceCode = UISourceCode;
+
+/** @enum {symbol} */
+Workspace.UISourceCode.Events = Events;
+
+/** @constructor */
+Workspace.UISourceCode.Message = Message;
+
+/** @constructor */
+Workspace.UISourceCode.LineMarker = LineMarker;
+
+/** @constructor */
+Workspace.UILocation = UILocation;
+
+/** @constructor */
+Workspace.UISourceCodeMetadata = UISourceCodeMetadata; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace/Workspace.js b/chromium/third_party/blink/renderer/devtools/front_end/workspace/WorkspaceImpl.js
index 54a4c98e345..25b056ed7fb 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/workspace/Workspace.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace/WorkspaceImpl.js
@@ -30,83 +30,92 @@
/**
* @interface
*/
-Workspace.ProjectSearchConfig = function() {};
-
-Workspace.ProjectSearchConfig.prototype = {
+export class ProjectSearchConfig {
/**
* @return {string}
*/
- query() {},
+ query() {
+ }
/**
* @return {boolean}
*/
- ignoreCase() {},
+ ignoreCase() {
+ }
/**
* @return {boolean}
*/
- isRegex() {},
+ isRegex() {
+ }
/**
* @return {!Array.<string>}
*/
- queries() {},
+ queries() {
+ }
/**
* @param {string} filePath
* @return {boolean}
*/
- filePathMatchesFileQuery(filePath) {}
-};
+ filePathMatchesFileQuery(filePath) {
+ }
+}
/**
* @interface
*/
-Workspace.Project = function() {};
-
-Workspace.Project.prototype = {
+export class Project {
/**
- * @return {!Workspace.Workspace}
+ * @return {!WorkspaceImpl}
*/
- workspace() {},
+ workspace() {
+ }
/**
* @return {string}
*/
- id() {},
+ id() {
+ }
/**
* @return {string}
*/
- type() {},
+ type() {
+ }
/**
* @return {boolean}
*/
- isServiceProject() {},
+ isServiceProject() {
+ }
/**
* @return {string}
*/
- displayName() {},
+ displayName() {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {!Promise<?Workspace.UISourceCodeMetadata>}
*/
- requestMetadata(uiSourceCode) {},
+ requestMetadata(uiSourceCode) {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
- * @param {function(?string,boolean)} callback
+ * @returns {!Promise<!Common.DeferredContent>}
*/
- requestFileContent(uiSourceCode, callback) {},
+ requestFileContent(uiSourceCode) {
+ }
/**
* @return {boolean}
*/
- canSetFileContent() {},
+ canSetFileContent() {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
@@ -114,42 +123,49 @@ Workspace.Project.prototype = {
* @param {boolean} isBase64
* @return {!Promise}
*/
- setFileContent(uiSourceCode, newContent, isBase64) {},
+ setFileContent(uiSourceCode, newContent, isBase64) {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {string}
*/
- fullDisplayName(uiSourceCode) {},
+ fullDisplayName(uiSourceCode) {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @return {string}
*/
- mimeType(uiSourceCode) {},
+ mimeType(uiSourceCode) {
+ }
/**
* @return {boolean}
*/
- canRename() {},
+ canRename() {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
* @param {string} newName
* @param {function(boolean, string=, string=, !Common.ResourceType=)} callback
*/
- rename(uiSourceCode, newName, callback) {},
+ rename(uiSourceCode, newName, callback) {
+ }
/**
* @param {string} path
*/
- excludeFolder(path) {},
+ excludeFolder(path) {
+ }
/**
* @param {string} path
* @return {boolean}
*/
- canExcludeFolder(path) {},
+ canExcludeFolder(path) {
+ }
/**
* @param {string} path
@@ -158,19 +174,23 @@ Workspace.Project.prototype = {
* @param {boolean=} isBase64
* @return {!Promise<?Workspace.UISourceCode>}
*/
- createFile(path, name, content, isBase64) {},
+ createFile(path, name, content, isBase64) {
+ }
/**
* @return {boolean}
*/
- canCreateFile() {},
+ canCreateFile() {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
*/
- deleteFile(uiSourceCode) {},
+ deleteFile(uiSourceCode) {
+ }
- remove() {},
+ remove() {
+ }
/**
* @param {!Workspace.UISourceCode} uiSourceCode
@@ -179,37 +199,42 @@ Workspace.Project.prototype = {
* @param {boolean} isRegex
* @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
*/
- searchInFileContent(uiSourceCode, query, caseSensitive, isRegex) {},
+ searchInFileContent(uiSourceCode, query, caseSensitive, isRegex) {
+ }
/**
- * @param {!Workspace.ProjectSearchConfig} searchConfig
+ * @param {!ProjectSearchConfig} searchConfig
* @param {!Array.<string>} filesMathingFileQuery
* @param {!Common.Progress} progress
* @return {!Promise<!Array<string>>}
*/
- findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, progress) {},
+ findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, progress) {
+ }
/**
* @param {!Common.Progress} progress
*/
- indexContent(progress) {},
+ indexContent(progress) {
+ }
/**
* @param {string} url
* @return {?Workspace.UISourceCode}
*/
- uiSourceCodeForURL(url) {},
+ uiSourceCodeForURL(url) {
+ }
/**
* @return {!Array.<!Workspace.UISourceCode>}
*/
- uiSourceCodes() {}
-};
+ uiSourceCodes() {
+ }
+}
/**
* @enum {string}
*/
-Workspace.projectTypes = {
+export const projectTypes = {
Debugger: 'debugger',
Formatter: 'formatter',
Network: 'network',
@@ -221,9 +246,9 @@ Workspace.projectTypes = {
/**
* @unrestricted
*/
-Workspace.ProjectStore = class {
+export class ProjectStore {
/**
- * @param {!Workspace.Workspace} workspace
+ * @param {!WorkspaceImpl} workspace
* @param {string} id
* @param {!Workspace.projectTypes} type
* @param {string} displayName
@@ -239,7 +264,7 @@ Workspace.ProjectStore = class {
/** @type {!Array.<!Workspace.UISourceCode>} */
this._uiSourceCodesList = [];
- this._project = /** @type {!Workspace.Project} */ (this);
+ this._project = /** @type {!Project} */ (this);
}
/**
@@ -264,7 +289,7 @@ Workspace.ProjectStore = class {
}
/**
- * @return {!Workspace.Workspace}
+ * @return {!WorkspaceImpl}
*/
workspace() {
return this._workspace;
@@ -285,11 +310,12 @@ Workspace.ProjectStore = class {
*/
addUISourceCode(uiSourceCode) {
const url = uiSourceCode.url();
- if (this.uiSourceCodeForURL(url))
+ if (this.uiSourceCodeForURL(url)) {
return false;
+ }
this._uiSourceCodesMap.set(url, {uiSourceCode: uiSourceCode, index: this._uiSourceCodesList.length});
this._uiSourceCodesList.push(uiSourceCode);
- this._workspace.dispatchEventToListeners(Workspace.Workspace.Events.UISourceCodeAdded, uiSourceCode);
+ this._workspace.dispatchEventToListeners(Events.UISourceCodeAdded, uiSourceCode);
return true;
}
@@ -298,8 +324,9 @@ Workspace.ProjectStore = class {
*/
removeUISourceCode(url) {
const uiSourceCode = this.uiSourceCodeForURL(url);
- if (!uiSourceCode)
+ if (!uiSourceCode) {
return;
+ }
const entry = this._uiSourceCodesMap.get(url);
const movedUISourceCode = this._uiSourceCodesList[this._uiSourceCodesList.length - 1];
@@ -308,7 +335,7 @@ Workspace.ProjectStore = class {
movedEntry.index = entry.index;
this._uiSourceCodesList.splice(this._uiSourceCodesList.length - 1, 1);
this._uiSourceCodesMap.delete(url);
- this._workspace.dispatchEventToListeners(Workspace.Workspace.Events.UISourceCodeRemoved, entry.uiSourceCode);
+ this._workspace.dispatchEventToListeners(Events.UISourceCodeRemoved, entry.uiSourceCode);
}
removeProject() {
@@ -345,15 +372,15 @@ Workspace.ProjectStore = class {
this._uiSourceCodesMap.set(newPath, value);
this._uiSourceCodesMap.delete(oldPath);
}
-};
+}
/**
* @unrestricted
*/
-Workspace.Workspace = class extends Common.Object {
+export default class WorkspaceImpl extends Common.Object {
constructor() {
super();
- /** @type {!Map<string, !Workspace.Project>} */
+ /** @type {!Map<string, !Project>} */
this._projects = new Map();
this._hasResourceContentTrackingExtensions = false;
}
@@ -375,8 +402,9 @@ Workspace.Workspace = class extends Common.Object {
uiSourceCodeForURL(url) {
for (const project of this._projects.values()) {
const uiSourceCode = project.uiSourceCodeForURL(url);
- if (uiSourceCode)
+ if (uiSourceCode) {
return uiSourceCode;
+ }
}
return null;
}
@@ -388,39 +416,40 @@ Workspace.Workspace = class extends Common.Object {
uiSourceCodesForProjectType(type) {
let result = [];
for (const project of this._projects.values()) {
- if (project.type() === type)
+ if (project.type() === type) {
result = result.concat(project.uiSourceCodes());
+ }
}
return result;
}
/**
- * @param {!Workspace.Project} project
+ * @param {!Project} project
*/
addProject(project) {
console.assert(!this._projects.has(project.id()), `A project with id ${project.id()} already exists!`);
this._projects.set(project.id(), project);
- this.dispatchEventToListeners(Workspace.Workspace.Events.ProjectAdded, project);
+ this.dispatchEventToListeners(Events.ProjectAdded, project);
}
/**
- * @param {!Workspace.Project} project
+ * @param {!Project} project
*/
_removeProject(project) {
this._projects.delete(project.id());
- this.dispatchEventToListeners(Workspace.Workspace.Events.ProjectRemoved, project);
+ this.dispatchEventToListeners(Events.ProjectRemoved, project);
}
/**
* @param {string} projectId
- * @return {?Workspace.Project}
+ * @return {?Project}
*/
project(projectId) {
return this._projects.get(projectId) || null;
}
/**
- * @return {!Array.<!Workspace.Project>}
+ * @return {!Array.<!Project>}
*/
projects() {
return this._projects.valuesArray();
@@ -428,7 +457,7 @@ Workspace.Workspace = class extends Common.Object {
/**
* @param {string} type
- * @return {!Array.<!Workspace.Project>}
+ * @return {!Array.<!Project>}
*/
projectsForType(type) {
function filterByType(project) {
@@ -442,8 +471,9 @@ Workspace.Workspace = class extends Common.Object {
*/
uiSourceCodes() {
let result = [];
- for (const project of this._projects.values())
+ for (const project of this._projects.values()) {
result = result.concat(project.uiSourceCodes());
+ }
return result;
}
@@ -460,10 +490,10 @@ Workspace.Workspace = class extends Common.Object {
hasResourceContentTrackingExtensions() {
return this._hasResourceContentTrackingExtensions;
}
-};
+}
/** @enum {symbol} */
-Workspace.Workspace.Events = {
+export const Events = {
UISourceCodeAdded: Symbol('UISourceCodeAdded'),
UISourceCodeRemoved: Symbol('UISourceCodeRemoved'),
UISourceCodeRenamed: Symbol('UISourceCodeRenamed'),
@@ -474,7 +504,31 @@ Workspace.Workspace.Events = {
ProjectRemoved: Symbol('ProjectRemoved')
};
+/* Legacy exported object */
+self.Workspace = self.Workspace || {};
+
+/* Legacy exported object */
+Workspace = Workspace || {};
+
+/** @constructor */
+Workspace.Workspace = WorkspaceImpl;
+
+/** @enum {symbol} */
+Workspace.Workspace.Events = Events;
+
+/** @interface */
+Workspace.ProjectSearchConfig = ProjectSearchConfig;
+
+/** @interface */
+Workspace.Project = Project;
+
+/** @enum {string} */
+Workspace.projectTypes = projectTypes;
+
+/** @constructor */
+Workspace.ProjectStore = ProjectStore;
+
/**
- * @type {!Workspace.Workspace}
+ * @type {!WorkspaceImpl}
*/
Workspace.workspace;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace/module.json b/chromium/third_party/blink/renderer/devtools/front_end/workspace/module.json
index 56005a8a469..0d025c44f92 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/workspace/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace/module.json
@@ -4,9 +4,11 @@
"host",
"platform"
],
- "scripts": [
+ "scripts": [],
+ "modules": [
+ "workspace.js",
"FileManager.js",
"UISourceCode.js",
- "Workspace.js"
+ "WorkspaceImpl.js"
]
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace/workspace.js b/chromium/third_party/blink/renderer/devtools/front_end/workspace/workspace.js
new file mode 100644
index 00000000000..3b2268c4019
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace/workspace.js
@@ -0,0 +1,13 @@
+// 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 * as FileManager from './FileManager.js';
+import * as UISourceCode from './UISourceCode.js';
+import * as Workspace from './WorkspaceImpl.js';
+
+export {
+ FileManager,
+ UISourceCode,
+ Workspace,
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js b/chromium/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js
index 4e05823788b..853fa917191 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/workspace_diff/WorkspaceDiff.js
@@ -71,8 +71,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
* @return {!WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff}
*/
_uiSourceCodeDiff(uiSourceCode) {
- if (!this._uiSourceCodeDiffs.has(uiSourceCode))
+ if (!this._uiSourceCodeDiffs.has(uiSourceCode)) {
this._uiSourceCodeDiffs.set(uiSourceCode, new WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff(uiSourceCode));
+ }
return this._uiSourceCodeDiffs.get(uiSourceCode);
}
@@ -105,8 +106,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
*/
_projectRemoved(event) {
const project = /** @type {!Workspace.Project} */ (event.data);
- for (const uiSourceCode of project.uiSourceCodes())
+ for (const uiSourceCode of project.uiSourceCodes()) {
this._removeUISourceCode(uiSourceCode);
+ }
}
/**
@@ -115,8 +117,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
_removeUISourceCode(uiSourceCode) {
this._loadingUISourceCodes.delete(uiSourceCode);
const uiSourceCodeDiff = this._uiSourceCodeDiffs.get(uiSourceCode);
- if (uiSourceCodeDiff)
+ if (uiSourceCodeDiff) {
uiSourceCodeDiff._dispose = true;
+ }
this._markAsUnmodified(uiSourceCode);
}
@@ -125,8 +128,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
*/
_markAsUnmodified(uiSourceCode) {
this._uiSourceCodeProcessedForTest();
- if (this._modifiedUISourceCodes.delete(uiSourceCode))
+ if (this._modifiedUISourceCodes.delete(uiSourceCode)) {
this.dispatchEventToListeners(WorkspaceDiff.Events.ModifiedStatusChanged, {uiSourceCode, isModified: false});
+ }
}
/**
@@ -134,8 +138,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
*/
_markAsModified(uiSourceCode) {
this._uiSourceCodeProcessedForTest();
- if (this._modifiedUISourceCodes.has(uiSourceCode))
+ if (this._modifiedUISourceCodes.has(uiSourceCode)) {
return;
+ }
this._modifiedUISourceCodes.add(uiSourceCode);
this.dispatchEventToListeners(WorkspaceDiff.Events.ModifiedStatusChanged, {uiSourceCode, isModified: true});
}
@@ -162,18 +167,23 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
return;
}
- const contentsPromise =
- Promise.all([this.requestOriginalContentForUISourceCode(uiSourceCode), uiSourceCode.requestContent()]);
+ const contentsPromise = Promise.all([
+ this.requestOriginalContentForUISourceCode(uiSourceCode),
+ uiSourceCode.requestContent().then(deferredContent => deferredContent.content)
+ ]);
+
this._loadingUISourceCodes.set(uiSourceCode, contentsPromise);
const contents = await contentsPromise;
- if (this._loadingUISourceCodes.get(uiSourceCode) !== contentsPromise)
+ if (this._loadingUISourceCodes.get(uiSourceCode) !== contentsPromise) {
return;
+ }
this._loadingUISourceCodes.delete(uiSourceCode);
- if (contents[0] !== null && contents[1] !== null && contents[0] !== contents[1])
+ if (contents[0] !== null && contents[1] !== null && contents[0] !== contents[1]) {
this._markAsModified(uiSourceCode);
- else
+ } else {
this._markAsUnmodified(uiSourceCode);
+ }
}
/**
@@ -193,8 +203,9 @@ WorkspaceDiff.WorkspaceDiff = class extends Common.Object {
* @param {?string} content
*/
function callback(content) {
- if (typeof content !== 'string')
+ if (typeof content !== 'string') {
return;
+ }
uiSourceCode.addRevision(content);
}
@@ -233,8 +244,9 @@ WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff = class extends Common.Object {
* @this {WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff}
*/
function emitDiffChanged() {
- if (this._dispose)
+ if (this._dispose) {
return;
+ }
this.dispatchEventToListeners(WorkspaceDiff.Events.DiffChanged);
this._pendingChanges = null;
}
@@ -244,52 +256,59 @@ WorkspaceDiff.WorkspaceDiff.UISourceCodeDiff = class extends Common.Object {
* @return {!Promise<?Diff.Diff.DiffArray>}
*/
requestDiff() {
- if (!this._requestDiffPromise)
+ if (!this._requestDiffPromise) {
this._requestDiffPromise = this._innerRequestDiff();
+ }
return this._requestDiffPromise;
}
/**
* @return {!Promise<?string>}
*/
- _originalContent() {
+ async _originalContent() {
const originalNetworkContent =
Persistence.networkPersistenceManager.originalContentForUISourceCode(this._uiSourceCode);
- if (originalNetworkContent)
+ if (originalNetworkContent) {
return originalNetworkContent;
+ }
- let callback;
- const promise = new Promise(fulfill => callback = fulfill);
- this._uiSourceCode.project().requestFileContent(this._uiSourceCode, callback);
- return promise;
+ const content = await this._uiSourceCode.project().requestFileContent(this._uiSourceCode);
+ return content.content || content.error || '';
}
/**
* @return {!Promise<?Diff.Diff.DiffArray>}
*/
async _innerRequestDiff() {
- if (this._dispose)
+ if (this._dispose) {
return null;
+ }
const baseline = await this._originalContent();
- if (baseline.length > 1024 * 1024)
+ if (baseline.length > 1024 * 1024) {
return null;
+ }
// ------------ ASYNC ------------
- if (this._dispose)
+ if (this._dispose) {
return null;
+ }
let current = this._uiSourceCode.workingCopy();
- if (!current && !this._uiSourceCode.contentLoaded())
- current = await this._uiSourceCode.requestContent();
- if (current.length > 1024 * 1024)
+ if (!current && !this._uiSourceCode.contentLoaded()) {
+ current = (await this._uiSourceCode.requestContent()).content;
+ }
+
+ if (current.length > 1024 * 1024) {
return null;
- // ------------ ASYNC ------------
+ }
- if (this._dispose)
+ if (this._dispose) {
return null;
+ }
- if (current === null || baseline === null)
+ if (current === null || baseline === null) {
return null;
+ }
return Diff.Diff.lineDiff(baseline.split(/\r\n|\n|\r/), current.split(/\r\n|\n|\r/));
}
};
@@ -306,8 +325,9 @@ WorkspaceDiff.Events = {
* @return {!WorkspaceDiff.WorkspaceDiff}
*/
WorkspaceDiff.workspaceDiff = function() {
- if (!WorkspaceDiff.WorkspaceDiff._instance)
+ if (!WorkspaceDiff.WorkspaceDiff._instance) {
WorkspaceDiff.WorkspaceDiff._instance = new WorkspaceDiff.WorkspaceDiff(Workspace.workspace);
+ }
return WorkspaceDiff.WorkspaceDiff._instance;
};
diff --git a/chromium/third_party/blink/renderer/devtools/karma.conf.js b/chromium/third_party/blink/renderer/devtools/karma.conf.js
new file mode 100644
index 00000000000..812ec422c80
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/karma.conf.js
@@ -0,0 +1,80 @@
+// 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.
+
+// TODO(1011259): switch to true.
+let external_devtools_frontend = false;
+let node_modules_path = external_devtools_frontend
+ ? ''
+ : '../../../../third_party/devtools-node-modules/third_party/node_modules/';
+
+module.exports = function(config) {
+ const options = {
+ basePath: '',
+
+ files: [{
+ pattern: 'front_end/**/*.js',
+ included: false,
+ served: true
+ },{
+ pattern: 'test/unittests/**/*.ts',
+ type: 'module'
+ }],
+
+ reporters: ['dots', 'coverage-istanbul'],
+
+ preprocessors: {
+ './test/unittests/**/*.ts': ['karma-typescript'],
+ './front_end/common/*.js': ['karma-coverage-istanbul-instrumenter']
+ },
+
+ browsers: ['ChromeHeadless'],
+
+ frameworks: ['mocha', 'chai', 'karma-typescript'],
+
+ karmaTypescriptConfig: {
+ compilerOptions: {
+ target: 'esnext',
+ module: 'esnext',
+ typeRoots: [node_modules_path + '@types']
+ },
+ coverageOptions: {
+ instrumentation: false
+ },
+ bundlerOptions: {
+ resolve: {
+ directories: [node_modules_path]
+ }
+ },
+ exclude: [
+ 'scripts'
+ ]
+ },
+
+ proxies: {
+ '/front_end': '/base/front_end',
+ },
+
+ plugins: [
+ 'karma-chrome-launcher',
+ 'karma-mocha',
+ 'karma-chai',
+ 'karma-typescript',
+ require(node_modules_path + 'karma-coverage-istanbul-instrumenter'),
+ require(node_modules_path + 'karma-coverage-istanbul-reporter')
+ ],
+
+ coverageIstanbulInstrumenter: {
+ esModules: true
+ },
+
+ coverageIstanbulReporter: {
+ reports: ['text', 'html'],
+ dir: 'karma-coverage'
+ },
+
+ singleRun: true
+ };
+
+ config.set(options);
+};
diff --git a/chromium/third_party/blink/renderer/devtools/readme.md b/chromium/third_party/blink/renderer/devtools/readme.md
index 3e49169b90e..7c646595b17 100644
--- a/chromium/third_party/blink/renderer/devtools/readme.md
+++ b/chromium/third_party/blink/renderer/devtools/readme.md
@@ -61,11 +61,11 @@ One-time setup:
npm run setup-dtrun
```
-Now, you can use any of the following commands by simply doing: `dtrun test`.
+Now, you can use any of the following commands by simply doing: `dtrun test`.
In addition, you no longer need to pass double dashes (e.g. `--`) before you pass in the flags. So you can do: `dtrun test -d inspector/test.html`.
-#### `npm run format`
+#### `npm run format`
Formats your code using clang-format
### `npm run format-py`
@@ -85,8 +85,8 @@ npm test -- inspector/sources inspector/console
# debug a specific test. Any one of:
npm run debug-test inspector/cookie-resource-match.html
-npm test -- --debug-devtools inspector/cookie-resource-match.html
-npm test -- -d inspector/cookie-resource-match.html
+npm test -- --debug-devtools inspector/cookie-resource-match.html
+npm test -- -d inspector/cookie-resource-match.html
# pass in additional flags to the test harness
npm test -- -f --child-processes=16
@@ -99,15 +99,15 @@ npm test -- --time-out-ms=6000000 <test_path>
#### `--fetch-content-shell`
```
-# If you're using a full chromium checkout and have a compiled content shell,
-# this will fetch a pre-compiled content shell. This is useful if you
+# If you're using a full chromium checkout and have a compiled content shell,
+# this will fetch a pre-compiled content shell. This is useful if you
# haven't compiled your content shell recently
npm test -- --fetch-content-shell
```
#### `--target=SUB_DIRECTORY_NAME`
```
-# If you're using a build sub-directory that's not out/Release,
+# If you're using a build sub-directory that's not out/Release,
# such as out/Default, then use --target=SUB_DIRECTORY_NAME
npm test -- --target=Default
```
@@ -127,3 +127,17 @@ npm test -- --target=Default
[@ChromeDevTools]: http://twitter.com/ChromeDevTools
[@DevToolsCommits]: http://twitter.com/DevToolsCommits
[all open DevTools tickets]: https://bugs.chromium.org/p/chromium/issues/list?can=2&q=component%3APlatform%3EDevTools&sort=&groupby=&colspec=ID+Stars+Owner+Summary+Modified+Opened
+
+### Tests
+The tests are run through Karma.
+
+```
+python scripts/run_tests.py
+```
+
+You can also specify with which Chrome binary to run tests by setting the
+`chrome-binary` variable.
+
+```
+python scripts/run_tests.py --chrome-binary=/path/to/chromium/build/chromium
+```
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/README.md b/chromium/third_party/blink/renderer/devtools/scripts/README.md
index e7ac952c731..183bcdf62f3 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/README.md
+++ b/chromium/third_party/blink/renderer/devtools/scripts/README.md
@@ -16,7 +16,6 @@ The newer scripts such as for testing and hosted mode are written in Node.js, wh
- gulp - experimental build process written in node.js & gulp to remove the dependency on Chromium-specific build tools (i.e. gn and ninja)
- hosted_mode - run DevTools on a localhost development server
- jsdoc_validator - enforces the use of Closure type annotations
-- local_node - installs a local runtime of node.js
### Python Scripts
- compile_frontend.py - runs closure compiler to do static type analysis
@@ -30,4 +29,4 @@ The easiest way to run the node.js scripts is to use `npm run` which displays al
## Closure
-DevTools manually rolls the closure compiler to ./closure. If you manually roll closure compiler, you will need to re-generate the closure_runner (in ./closure) and jsdoc_validator custom jars using the python scripts in their respective directory. \ No newline at end of file
+DevTools manually rolls the closure compiler to ./closure. If you manually roll closure compiler, you will need to re-generate the closure_runner (in ./closure) and jsdoc_validator custom jars using the python scripts in their respective directory.
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/build_release_applications.py b/chromium/third_party/blink/renderer/devtools/scripts/build/build_release_applications.py
index 74e1c104275..c9f78af60dc 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/build/build_release_applications.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/build_release_applications.py
@@ -133,13 +133,13 @@ class ReleaseBuilder(object):
output = StringIO()
with open(join(self.application_dir, html_name), 'r') as app_input_html:
for line in app_input_html:
- if '<script ' in line or '<link ' in line:
+ if ('<script ' in line and 'type="module"' not in line) or '<link ' in line:
continue
if '</head>' in line:
self._write_include_tags(self.descriptors, output)
js_file = join(self.application_dir, self.app_file('js'))
if path.exists(js_file):
- output.write(' <script>%s</script>\n' % minify_js(read_file(js_file)))
+ output.write(' <script type="module">%s</script>\n' % minify_js(read_file(js_file)))
output.write(line)
write_file(join(self.output_dir, html_name), output.getvalue())
@@ -154,7 +154,7 @@ class ReleaseBuilder(object):
def _generate_include_tag(self, resource_path):
if resource_path.endswith('.js'):
- return ' <script type="text/javascript" src="%s"></script>\n' % resource_path
+ return ' <script defer src="%s"></script>\n' % resource_path
else:
assert resource_path
@@ -183,7 +183,7 @@ class ReleaseBuilder(object):
def _write_module_resources(self, resource_names, output):
for resource_name in resource_names:
resource_name = path.normpath(resource_name).replace('\\', '/')
- output.write('Runtime.cachedResources["%s"] = "' % resource_name)
+ output.write('Root.Runtime.cachedResources["%s"] = "' % resource_name)
resource_content = read_file(path.join(self.application_dir, resource_name))
resource_content += resource_source_url(resource_name).encode('utf-8')
resource_content = resource_content.replace('\\', '\\\\')
@@ -221,15 +221,15 @@ class ReleaseBuilder(object):
runtime_contents = read_file(join(self.application_dir, 'Runtime.js'))
output.write('/* Runtime.js */\n')
output.write(runtime_contents)
- output.write('allDescriptors.push(...%s);' % self._release_module_descriptors())
+ output.write('Root.allDescriptors.push(...%s);' % self._release_module_descriptors())
output.write('/* Application descriptor %s */\n' % self.app_file('json'))
- output.write('applicationDescriptor = ')
+ output.write('Root.applicationDescriptor = ')
output.write(self.descriptors.application_json())
else:
output.write('/* Additional descriptors */\n')
- output.write('allDescriptors.push(...%s);' % self._release_module_descriptors())
+ output.write('Root.allDescriptors.push(...%s);' % self._release_module_descriptors())
output.write('/* Additional descriptors %s */\n' % self.app_file('json'))
- output.write('applicationDescriptor.modules.push(...%s)' % json.dumps(self.descriptors.application.values()))
+ output.write('Root.applicationDescriptor.modules.push(...%s)' % json.dumps(self.descriptors.application.values()))
output.write('\n/* Autostart modules */\n')
self._concatenate_autostart_modules(output)
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/copy_devtools_modules.py b/chromium/third_party/blink/renderer/devtools/scripts/build/copy_devtools_modules.py
new file mode 100755
index 00000000000..a04b9e65252
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/copy_devtools_modules.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+#
+# 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.
+"""
+Copies the modules into the resources folder
+"""
+
+from os.path import join, relpath
+import shutil
+import sys
+
+import rjsmin
+
+from modular_build import read_file, write_file
+
+
+def main(argv):
+ try:
+ input_path_flag_index = argv.index('--input_path')
+ input_path = argv[input_path_flag_index + 1]
+ output_path_flag_index = argv.index('--output_path')
+ output_path = argv[output_path_flag_index + 1]
+ devtools_modules = argv[1:input_path_flag_index]
+ except:
+ print('Usage: %s module_1 module_2 ... module_N --input_path <input_path> --output_path <output_path>' % argv[0])
+ raise
+
+ for file_name in devtools_modules:
+ file_content = read_file(join(input_path, file_name))
+ minified = rjsmin.jsmin(file_content)
+ write_file(join(output_path, relpath(file_name, 'front_end')), minified)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_extension_api.py b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_extension_api.py
index 6d5728bf353..0eb10bc5c64 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_extension_api.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_extension_api.py
@@ -42,7 +42,7 @@ def write_devtools_extension_api(output, input_names):
var tabId;
var extensionInfo = {};
var extensionServer;
- platformExtensionAPI(injectedExtensionAPI("remote-" + window.parent.frames.length));
+ platformExtensionAPI(self.injectedExtensionAPI("remote-" + window.parent.frames.length));
})();""")
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.js b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.js
new file mode 100644
index 00000000000..bbe13f91982
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.js
@@ -0,0 +1,124 @@
+// 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.
+
+/**
+ * This script is called by generate_devtools_ui_strings.py as part of the build process. It
+ * parses DevTools frontend .js and module.json files, collects localizable strings, checks
+ * if frontend strings are in .grd/.grdp files and reports error if present, and generates
+ * {jsonKey, IDS_KEY} mappings if there is no error.
+ *
+ * Usage:
+ * --root_gen_dir The root directory of the output .h and .cc files
+ * --output_header Absolute path of the output .h file for the id mappings
+ * --output_cc Absolute path of the output .cc file for the id mappings
+ */
+
+const checkLocalizedStrings = require('../localization_utils/check_localized_strings');
+const localizationUtils = require('../localization_utils/localization_utils');
+
+const fs = require('fs');
+const path = require('path');
+const {promisify} = require('util');
+const writeFileAsync = promisify(fs.writeFile);
+
+class Arguments {
+ constructor(rootGenDir, outputHeaderFilePath, outputCCFilePath) {
+ this.rootGenDir = rootGenDir;
+ this.outputHeaderFilePath = outputHeaderFilePath;
+ this.outputCCFilePath = outputCCFilePath;
+ }
+}
+
+function parseArguments(args) {
+ const rootGenDirIndex = args.indexOf('--root_gen_dir');
+ const outputHeaderIndex = args.indexOf('--output_header');
+ const outputCCIndex = args.indexOf('--output_cc');
+ return new Arguments(args[rootGenDirIndex + 1], args[outputHeaderIndex + 1], args[outputCCIndex + 1]);
+}
+
+async function main() {
+ const args = parseArguments(process.argv);
+ let frontendStrings;
+ try {
+ [frontendStrings, _] = await checkLocalizedStrings.parseLocalizableResourceMaps();
+ } catch (e) {
+ console.log(e);
+ process.exit(1);
+ }
+
+ const toAddError = checkLocalizedStrings.getAndReportResourcesToAdd();
+ const toModifyError = checkLocalizedStrings.getAndReportIDSKeysToModify();
+ const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove();
+ let error = `${toAddError ? `${toAddError}\n` : ''}${toModifyError ? `${toModifyError}\n` : ''}${
+ toRemoveError ? `${toRemoveError}\n` : ''}`;
+ if (error !== '') {
+ error +=
+ '\nThe errors are potentially fixable with `node third_party/blink/renderer/devtools/scripts/check_localizable_resources.js --autofix`'
+ console.log(error);
+ }
+
+ // Since it's part of the build system, only fail if there are strings to be added to GRD/GRDP files
+ // or if there are wrong IDS_ keys.
+ if (toAddError || toModifyError)
+ process.exit(1);
+
+ try {
+ await generateDevToolsLocalizedStrings(args, frontendStrings);
+ } catch (e) {
+ console.log('Error generating id map files:');
+ console.log(e.stack);
+ process.exit(1);
+ }
+}
+
+// Generates {jsonKey, IDS_KEY} mappings according to frontendStrings
+async function generateDevToolsLocalizedStrings(args, frontendStrings) {
+ const promises = [];
+ const outputAbsoluteHeaderFilePath = path.join(args.rootGenDir, args.outputHeaderFilePath);
+ const outputAbsoluteCCFilePath = path.join(args.rootGenDir, args.outputCCFilePath);
+ const doNotEditStr =
+ `// This file is automatically generated by //third_party/blink/rendered/devtools/build/generate_devtools_ui_strings.js. Do not edit.`;
+ const outputHeaderFileContent = `${doNotEditStr}
+
+#ifndef CHROME_BROWSER_UI_WEBUI_DEVTOOLS_UI_STRINGS_H_
+#define CHROME_BROWSER_UI_WEBUI_DEVTOOLS_UI_STRINGS_H_
+
+#include "chrome/browser/ui/webui/localized_string.h"
+
+namespace devtools {
+
+constexpr unsigned int kLocalizedStringsSize = ${frontendStrings.size};
+extern const LocalizedString kLocalizedStrings[kLocalizedStringsSize];
+
+} // namespace devtools
+
+#endif // CHROME_BROWSER_UI_WEBUI_DEVTOOLS_UI_STRINGS_H_
+`;
+
+ promises.push(writeFileAsync(outputAbsoluteHeaderFilePath, outputHeaderFileContent));
+
+ let mappingsStr = '';
+ frontendStrings.forEach((frontendString, idsKey) => {
+ mappingsStr += ` {"${localizationUtils.sanitizeStringIntoCppFormat(frontendString.string)}", ${idsKey}},\n`;
+ });
+
+ const outputCCFileContent = `${doNotEditStr}
+
+#include "${args.outputHeaderFilePath}"
+
+#include "third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.h"
+
+namespace devtools {
+
+const LocalizedString kLocalizedStrings[] = {
+${mappingsStr}};
+
+} // namespace devtools
+`;
+
+ promises.push(writeFileAsync(outputAbsoluteCCFilePath, outputCCFileContent));
+ return Promise.all(promises);
+}
+
+main();
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.py b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.py
new file mode 100644
index 00000000000..62a9f57b285
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_devtools_ui_strings.py
@@ -0,0 +1,53 @@
+# 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 optparse
+import os
+import subprocess
+import sys
+
+_HERE_PATH = os.path.abspath(os.path.dirname(__file__))
+_JS_SCRIPT_PATH = os.path.join(_HERE_PATH, 'generate_devtools_ui_strings.js')
+_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..', '..', '..', '..'))
+
+sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
+# pylint: disable=wrong-import-position
+import node # pylint: disable=import-error
+_NODE_PATH = node.GetBinaryPath()
+
+
+def main():
+ parser = optparse.OptionParser(description=__doc__)
+ parser.add_option(
+ '--root_gen_dir',
+ action='store',
+ metavar='ROOT_GEN_DIR',
+ help='The root directory where the header and cc will be generated.')
+ parser.add_option('--output_header', action='store', metavar='OUTPUT_HEADER', help='Generated output .h file for pairs of IDs')
+ parser.add_option(
+ '--output_cc',
+ action='store',
+ metavar='OUTPUT_CC',
+ help='Generated output .cc file that contains pairs of {front-end string key, IDS_ key}')
+ options, _ = parser.parse_args()
+
+ if not options.root_gen_dir:
+ parser.error('--root_gen_dir was not specified.')
+ if not options.output_header:
+ parser.error('--output_header was not specified.')
+ if not options.output_header:
+ parser.error('--output_cc was not specified.')
+
+ cmd_parts = [
+ _NODE_PATH, _JS_SCRIPT_PATH, '--root_gen_dir',
+ os.path.abspath(options.root_gen_dir), '--output_header', options.output_header, '--output_cc', options.output_cc
+ ]
+ process = subprocess.Popen(cmd_parts, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, _ = process.communicate()
+ if process.returncode != 0:
+ return out
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/modular_build.py b/chromium/third_party/blink/renderer/devtools/scripts/build/modular_build.py
index 90d66971ff3..c818ad95cad 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/build/modular_build.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/modular_build.py
@@ -76,7 +76,7 @@ class Descriptors:
for name in self.sorted_modules():
module = self.modules[name]
skipped_files = set(module.get('skip_compilation', []))
- for script in module.get('scripts', []):
+ for script in module.get('scripts', []) + module.get('modules', []):
if script not in skipped_files:
files[path.normpath(path.join(self.application_dir, name, script))] = True
return files.keys()
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/check_localizability.js b/chromium/third_party/blink/renderer/devtools/scripts/check_localizability.js
index 000a2947474..a001b194350 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/check_localizability.js
+++ b/chromium/third_party/blink/renderer/devtools/scripts/check_localizability.js
@@ -46,9 +46,10 @@ async function main() {
if (process.argv[2] === '-a')
filePathPromises.push(localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']));
else
- filePaths = process.argv.slice(2);
+ filePaths = process.argv.slice(2).filter(localizationUtils.shouldParseDirectory);
await Promise.all(filePathPromises);
+ filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
const auditFilePromises = filePaths.map(filePath => auditFileForLocalizability(filePath, errors));
await Promise.all(auditFilePromises);
} catch (err) {
@@ -284,7 +285,7 @@ async function auditFileForLocalizability(filePath, errors) {
if (path.extname(filePath) === '.grdp')
return auditGrdpFile(filePath, fileContent, errors);
- const ast = esprima.parse(fileContent, {loc: true});
+ const ast = esprima.parseModule(fileContent, {loc: true});
const relativeFilePath = localizationUtils.getRelativeFilePathFromSrc(filePath);
for (const node of ast.body)
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js b/chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
index 50a2859d96c..706554e63ab 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
+++ b/chromium/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
@@ -13,7 +13,6 @@
*/
const fs = require('fs');
-const path = require('path');
const {promisify} = require('util');
const writeFileAsync = promisify(fs.writeFile);
const appendFileAsync = promisify(fs.appendFile);
@@ -25,25 +24,30 @@ const grdpFileEnd = '</grit-part>';
async function main() {
try {
- await checkLocalizedStrings.parseLocalizableResourceMaps();
+ const shouldAutoFix = process.argv.includes('--autofix');
+ const error = await checkLocalizedStrings.validateGrdAndGrdpFiles(shouldAutoFix);
+ if (error !== '' && !shouldAutoFix)
+ throw new Error(error);
- if (process.argv.includes('--autofix'))
- await autofix();
+ await checkLocalizedStrings.parseLocalizableResourceMaps();
+ if (shouldAutoFix)
+ await autofix(error);
else
- await getErrors();
+ getErrors();
} catch (e) {
- console.log(`Error: ${e.message}`);
+ console.log(e.stack);
process.exit(1);
}
}
main();
-async function getErrors() {
- const toAddError = await checkLocalizedStrings.getAndReportResourcesToAdd();
+function getErrors(existingError) {
+ const toAddError = checkLocalizedStrings.getAndReportResourcesToAdd();
const toModifyError = checkLocalizedStrings.getAndReportIDSKeysToModify();
const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove();
- let error = `${toAddError || ''}${toModifyError || ''}${toRemoveError || ''}`;
+ let error =
+ `${existingError ? `${existingError}\n` : ''}${toAddError || ''}${toModifyError || ''}${toRemoveError || ''}`;
if (error === '') {
console.log('DevTools localizable resources checker passed.');
@@ -55,20 +59,25 @@ async function getErrors() {
throw new Error(error);
}
-async function autofix() {
+async function autofix(existingError) {
const keysToAddToGRD = checkLocalizedStrings.getMessagesToAdd();
const keysToRemoveFromGRD = checkLocalizedStrings.getMessagesToRemove();
const resourceAdded = await addResourcesToGRDP(keysToAddToGRD, keysToRemoveFromGRD);
const resourceModified = await modifyResourcesInGRDP();
const resourceRemoved = await removeResourcesFromGRDP(keysToRemoveFromGRD);
- if (!resourceAdded && !resourceRemoved && !resourceModified) {
+ if (!resourceAdded && !resourceRemoved && !resourceModified && existingError === '') {
console.log('DevTools localizable resources checker passed.');
return;
}
let message =
- 'Found changes to localizable DevTools strings.\nDevTools localizable resources checker has updated the appropriate grdp file(s).';
+ 'Found changes to localizable DevTools resources.\nDevTools localizable resources checker has updated the appropriate grd/grdp file(s).';
+ if (existingError !== '') {
+ message +=
+ `\nGrd/Grdp files have been updated. Please verify the updated grdp files and/or the <part> file references in ${
+ localizationUtils.getRelativeFilePathFromSrc(localizationUtils.GRD_PATH)} are correct.`;
+ }
if (resourceAdded)
message += '\nManually write a description for any new <message> entries.';
if (resourceRemoved && duplicateRemoved(keysToRemoveFromGRD))
@@ -123,8 +132,7 @@ async function addResourcesToGRDP(keysToAddToGRD, keysToRemoveFromGRD) {
// Create a new grdp file and reference it in the parent grd file
promises.push(appendFileAsync(grdpFilePath, `${grdpFileStart}${grdpMessagesToAdd}${grdpFileEnd}`));
- grdpFilePathsToAdd.push(
- path.relative(path.dirname(localizationUtils.GRD_PATH), grdpFilePath).split(path.sep).join('/'));
+ grdpFilePathsToAdd.push(grdpFilePath);
continue;
}
@@ -161,45 +169,11 @@ async function addResourcesToGRDP(keysToAddToGRD, keysToRemoveFromGRD) {
promises.push(writeFileAsync(grdpFilePath, newGrdpFileContent));
}
- promises.push(addChildGRDPFilePathsToGRD(grdpFilePathsToAdd.sort()));
+ promises.push(localizationUtils.addChildGRDPFilePathsToGRD(grdpFilePathsToAdd.sort()));
await Promise.all(promises);
return true;
}
-async function addChildGRDPFilePathsToGRD(relativeGrdpFilePaths) {
- function createPartFileEntry(relativeGrdpFilePath) {
- return ` <part file="${relativeGrdpFilePath}" />\n`;
- }
-
- const grdFileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
- const grdLines = grdFileContent.split('\n');
-
- let newGrdFileContent = '';
- for (let i = 0; i < grdLines.length; i++) {
- const grdLine = grdLines[i];
- // match[0]: full match
- // match[1]: relative grdp file path
- const match = grdLine.match(/<part file="(.*?)"/);
- if (match) {
- const relativeGrdpFilePathsRemaining = [];
- for (const relativeGrdpFilePath of relativeGrdpFilePaths) {
- if (relativeGrdpFilePath < match[1])
- newGrdFileContent += createPartFileEntry(relativeGrdpFilePath);
- else
- relativeGrdpFilePathsRemaining.push(relativeGrdpFilePath);
- }
- relativeGrdpFilePaths = relativeGrdpFilePathsRemaining;
- } else if (grdLine.includes('</messages>')) {
- for (const relativeGrdpFilePath of relativeGrdpFilePaths)
- newGrdFileContent += createPartFileEntry(relativeGrdpFilePath);
- }
- newGrdFileContent += grdLine;
- if (i < grdLines.length - 1)
- newGrdFileContent += '\n';
- }
- return writeFileAsync(localizationUtils.GRD_PATH, newGrdFileContent);
-}
-
// Return true if any resources are updated
async function modifyResourcesInGRDP() {
const messagesToModify = checkLocalizedStrings.getIDSKeysToModify();
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/closure/README.md b/chromium/third_party/blink/renderer/devtools/scripts/closure/README.md
index 83f5621fa72..95935cd87d7 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/closure/README.md
+++ b/chromium/third_party/blink/renderer/devtools/scripts/closure/README.md
@@ -1,53 +1,80 @@
# [Google Closure Compiler](https://developers.google.com/closure/compiler/)
[![Build Status](https://travis-ci.org/google/closure-compiler.svg?branch=master)](https://travis-ci.org/google/closure-compiler)
+[![Open Source Helpers](https://www.codetriage.com/google/closure-compiler/badges/users.svg)](https://www.codetriage.com/google/closure-compiler)
The [Closure Compiler](https://developers.google.com/closure/compiler/) is a tool for making JavaScript download and run faster. It is a true compiler for JavaScript. Instead of compiling from a source language to machine code, it compiles from JavaScript to better JavaScript. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls.
## Getting Started
- * [Download the latest version](http://dl.google.com/closure-compiler/compiler-latest.zip) ([Release details here](https://github.com/google/closure-compiler/wiki/Releases))
- * [Download a specific version](https://github.com/google/closure-compiler/wiki/Binary-Downloads)
+ * [Download the latest version](https://dl.google.com/closure-compiler/compiler-latest.zip) ([Release details here](https://github.com/google/closure-compiler/wiki/Releases))
+ * [Download a specific version](https://github.com/google/closure-compiler/wiki/Binary-Downloads). Also available via:
+ - [Maven](https://github.com/google/closure-compiler/wiki/Maven)
+ - [NPM](https://www.npmjs.com/package/google-closure-compiler) - includes java, native and javascript versions.
* See the [Google Developers Site](https://developers.google.com/closure/compiler/docs/gettingstarted_app) for documentation including instructions for running the compiler from the command line.
## Options for Getting Help
-1. Post in the [Closure Compiler Discuss Group](https://groups.google.com/forum/#!forum/closure-compiler-discuss)
-2. Ask a question on [Stack Overflow](http://stackoverflow.com/questions/tagged/google-closure-compiler)
-3. Consult the [FAQ](https://github.com/google/closure-compiler/wiki/FAQ)
+1. Post in the [Closure Compiler Discuss Group](https://groups.google.com/forum/#!forum/closure-compiler-discuss).
+2. Ask a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/google-closure-compiler).
+3. Consult the [FAQ](https://github.com/google/closure-compiler/wiki/FAQ).
## Building it Yourself
-Note: The Closure Compiler requires [Java 7 or higher](http://www.java.com/).
-
-### Using [Ant](http://ant.apache.org/)
-
-1. Download the [Ant build tool](http://ant.apache.org/bindownload.cgi).
-
-2. At the root of the source tree, there is an Ant file named ```build.xml```.
- To use it, navigate to the same directory and type the command
-
- ```
- ant jar
- ```
-
- This will produce a jar file called ```build/compiler.jar```.
-
-### Using [Eclipse](http://www.eclipse.org/)
-
-1. Download and open the [Eclipse IDE](http://www.eclipse.org/).
-2. Navigate to ```File > New > Project ...``` and create a Java Project. Give
- the project a name.
-3. Select ```Create project from existing source``` and choose the root of the
- checked-out source tree as the existing directory.
-3. Navigate to the ```build.xml``` file. You will see all the build rules in
- the Outline pane. Run the ```jar``` rule to build the compiler in
- ```build/compiler.jar```.
+Note: The Closure Compiler requires [Java 8 or higher](https://www.java.com/).
+
+### Using [Maven](https://maven.apache.org/)
+
+1. Download [Maven](https://maven.apache.org/download.cgi).
+
+2. Add sonatype snapshots repository to `~/.m2/settings.xml`:
+ ```xml
+ <profile>
+ <id>allow-snapshots</id>
+ <activation><activeByDefault>true</activeByDefault></activation>
+ <repositories>
+ <repository>
+ <id>snapshots-repo</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <releases><enabled>false</enabled></releases>
+ <snapshots><enabled>true</enabled></snapshots>
+ </repository>
+ </repositories>
+ </profile>
+ ```
+
+3. On the command line, at the root of this project, run `mvn -DskipTests` (omit the `-DskipTests` if you want to run all the
+unit tests too).
+
+ This will produce a jar file called `target/closure-compiler-1.0-SNAPSHOT.jar`. You can run this jar
+ as per the [Running section](#running) of this Readme. If you want to depend on the compiler via
+ Maven in another Java project, use the `com.google.javascript/closure-compiler-unshaded` artifact.
+
+ Running `mvn -DskipTests -pl externs/pom.xml,pom-main.xml,pom-main-shaded.xml`
+ will skip building the GWT version of the compiler. This can speed up the build process significantly.
+
+### Using [Eclipse](https://www.eclipse.org/)
+
+1. Download and open [Eclipse IDE](https://www.eclipse.org/). Disable `Project > Build automatically` during this process.
+2. On the command line, at the root of this project, run `mvn eclipse:eclipse -DdownloadSources=true` to download JARs and build Eclipse project configuration.
+3. Run `mvn clean` and `mvn -DskipTests` to ensure AutoValues are generated and updated.
+4. In Eclipse, navigate to `File > Import > Maven > Existing Maven Projects` and browse to closure-compiler.
+5. Import both closure-compiler and the nested externs project.
+6. Disregard the warnings about maven-antrun-plugin and build errors.
+7. Configure the project to use the [Google Eclipse style guide](https://github.com/google/styleguide/blob/gh-pages/eclipse-java-google-style.xml)
+8. Edit `.classpath` in closure-compiler-parent. Delete the `<classpathentry ... kind="src" path="src" ... />` line, then add:
+ ```xml
+ <classpathentry excluding="com/google/debugging/sourcemap/super/**|com/google/javascript/jscomp/debugger/gwt/DebuggerGwtMain.java|com/google/javascript/jscomp/gwt/|com/google/javascript/jscomp/resources/super-gwt/**" kind="src" path="src"/>
+ <classpathentry kind="src" path="target/generated-sources/annotations"/>
+ ```
+9. Ensure the Eclipse project settings specify 1.8 compliance level in "Java Compiler".
+10. Build project in Eclipse (right click on the project `closure-compiler-parent` and select `Build Project`).
+11. See *Using Maven* above to build the JAR.
## Running
On the command line, at the root of this project, type
```
-java -jar build/compiler.jar
+java -jar target/closure-compiler-1.0-SNAPSHOT.jar
```
This starts the compiler in interactive mode. Type
@@ -72,7 +99,15 @@ java -jar compiler.jar --help
```
More detailed information about running the Closure Compiler is available in the
-[documentation](http://code.google.com/closure/compiler/docs/gettingstarted_app.html).
+[documentation](https://developers.google.com/closure/compiler/docs/gettingstarted_app).
+
+
+### Run using Eclipse
+
+1. Open the class `src/com/google/javascript/jscomp/CommandLineRunner.java` or create your own extended version of the class.
+2. Run the class in Eclipse.
+3. See the instructions above on how to use the interactive mode - but beware of the [bug](https://stackoverflow.com/questions/4711098/passing-end-of-transmission-ctrl-d-character-in-eclipse-cdt-console) regarding passing "End of Transmission" in the Eclipse console.
+
## Compiling Multiple Scripts
@@ -89,7 +124,7 @@ You can also use minimatch-style globs.
# Recursively include all js files in subdirs
java -jar compiler.jar --js_output_file=out.js 'src/**.js'
-# Recursively include all js files in subdirs, exclusing test files.
+# Recursively include all js files in subdirs, excluding test files.
# Use single-quotes, so that bash doesn't try to expand the '!'
java -jar compiler.jar --js_output_file=out.js 'src/**.js' '!**_test.js'
```
@@ -108,7 +143,8 @@ will re-order the inputs automatically.
1. First make sure that it is really a bug and not simply the way that Closure Compiler works (especially true for ADVANCED_OPTIMIZATIONS).
* Check the [official documentation](https://developers.google.com/closure/compiler/)
* Consult the [FAQ](https://github.com/google/closure-compiler/wiki/FAQ)
- * Search on [Stack Overflow](http://stackoverflow.com/questions/tagged/google-closure-compiler) and in the [Closure Compiler Discuss Group](https://groups.google.com/forum/#!forum/closure-compiler-discuss)
+ * Search on [Stack Overflow](https://stackoverflow.com/questions/tagged/google-closure-compiler) and in the [Closure Compiler Discuss Group](https://groups.google.com/forum/#!forum/closure-compiler-discuss)
+ * Look through the list of [compiler assumptions](https://github.com/google/closure-compiler/wiki/Compiler-Assumptions).
2. If you still think you have found a bug, make sure someone hasn't already reported it. See the list of [known issues](https://github.com/google/closure-compiler/issues).
3. If it hasn't been reported yet, post a new issue. Make sure to add enough detail so that the bug can be recreated. The smaller the reproduction code, the better.
@@ -116,13 +152,26 @@ will re-order the inputs automatically.
1. Consult the [FAQ](https://github.com/google/closure-compiler/wiki/FAQ) to make sure that the behaviour you would like isn't specifically excluded (such as string inlining).
2. Make sure someone hasn't requested the same thing. See the list of [known issues](https://github.com/google/closure-compiler/issues).
3. Read up on [what type of feature requests are accepted](https://github.com/google/closure-compiler/wiki/FAQ#how-do-i-submit-a-feature-request-for-a-new-type-of-optimization).
-4. Submit your reqest as an issue.
+4. Submit your request as an issue.
### Submitting patches
-1. All contributors must sign a contributor license agreement. See the [CONTRIBUTORS](https://raw.githubusercontent.com/google/closure-compiler/master/CONTRIBUTORS) file for details.
+1. All contributors must sign a contributor license agreement (CLA).
+ A CLA basically says that you own the rights to any code you contribute,
+ and that you give us permission to use that code in Closure Compiler.
+ You maintain the copyright on that code.
+ If you own all the rights to your code, you can fill out an
+ [individual CLA](https://code.google.com/legal/individual-cla-v1.0.html).
+ If your employer has any rights to your code, then they also need to fill out
+ a [corporate CLA](https://code.google.com/legal/corporate-cla-v1.0.html).
+ If you don't know if your employer has any rights to your code, you should
+ ask before signing anything.
+ By default, anyone with an @google.com email address already has a CLA
+ signed for them.
2. To make sure your changes are of the type that will be accepted, ask about your patch on the [Closure Compiler Discuss Group](https://groups.google.com/forum/#!forum/closure-compiler-discuss)
3. Fork the repository.
-4. Make your changes.
+4. Make your changes. Check out our
+ [coding conventions](https://github.com/google/closure-compiler/wiki/Contributors#coding-conventions)
+ for details on making sure your code is in correct style.
5. Submit a pull request for your changes. A project developer will review your work and then merge your request into the project.
## Closure Compiler License
@@ -153,7 +202,7 @@ limitations under the License.
<tr>
<td>URL</td>
- <td>http://www.mozilla.org/rhino</td>
+ <td>https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino</td>
</tr>
<tr>
@@ -186,18 +235,13 @@ system have been added.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/args4j.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>https://args4j.dev.java.net/</td>
+ <td>http://args4j.kohsuke.org/</td>
</tr>
<tr>
<td>Version</td>
- <td>2.0.26</td>
+ <td>2.33</td>
</tr>
<tr>
@@ -221,18 +265,13 @@ options/arguments in your CUI application.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/guava.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
<td>https://github.com/google/guava</td>
</tr>
<tr>
<td>Version</td>
- <td>18.0</td>
+ <td>20.0</td>
</tr>
<tr>
@@ -255,18 +294,13 @@ options/arguments in your CUI application.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/jsr305.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>http://code.google.com/p/jsr-305/</td>
+ <td>https://github.com/findbugsproject/findbugs</td>
</tr>
<tr>
<td>Version</td>
- <td>svn revision 47</td>
+ <td>3.0.1</td>
</tr>
<tr>
@@ -289,18 +323,13 @@ options/arguments in your CUI application.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/junit.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>http://sourceforge.net/projects/junit/</td>
+ <td>http://junit.org/junit4/</td>
</tr>
<tr>
<td>Version</td>
- <td>4.11</td>
+ <td>4.12</td>
</tr>
<tr>
@@ -323,18 +352,13 @@ options/arguments in your CUI application.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/protobuf-java.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>http://code.google.com/p/protobuf/</td>
+ <td>https://github.com/google/protobuf</td>
</tr>
<tr>
<td>Version</td>
- <td>2.5.0</td>
+ <td>3.0.2</td>
</tr>
<tr>
@@ -354,22 +378,46 @@ an encoding of structured data.</td>
</tr>
</table>
-### Truth
+### RE2/J
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/truth.jar</code></td>
+ <td>URL</td>
+ <td>https://github.com/google/re2j</td>
+ </tr>
+
+ <tr>
+ <td>Version</td>
+ <td>1.3</td>
</tr>
<tr>
+ <td>License</td>
+ <td>New BSD License</td>
+ </tr>
+
+ <tr>
+ <td>Description</td>
+ <td>Linear time regular expression matching in Java.</td>
+ </tr>
+
+ <tr>
+ <td>Local Modifications</td>
+ <td>None</td>
+ </tr>
+</table>
+
+### Truth
+
+<table>
+ <tr>
<td>URL</td>
<td>https://github.com/google/truth</td>
</tr>
<tr>
<td>Version</td>
- <td>0.24</td>
+ <td>0.32</td>
</tr>
<tr>
@@ -392,20 +440,13 @@ an encoding of structured data.</td>
<table>
<tr>
- <td>Code Path</td>
- <td>
- <code>lib/ant.jar</code>, <code>lib/ant-launcher.jar</code>
- </td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>http://ant.apache.org/bindownload.cgi</td>
+ <td>https://ant.apache.org/bindownload.cgi</td>
</tr>
<tr>
<td>Version</td>
- <td>1.8.1</td>
+ <td>1.9.7</td>
</tr>
<tr>
@@ -429,18 +470,13 @@ without make's wrinkles and with the full portability of pure java code.</td>
<table>
<tr>
- <td>Code Path</td>
- <td><code>lib/gson.jar</code></td>
- </tr>
-
- <tr>
<td>URL</td>
- <td>https://code.google.com/p/google-gson/</td>
+ <td>https://github.com/google/gson</td>
</tr>
<tr>
<td>Version</td>
- <td>2.2.4</td>
+ <td>2.7</td>
</tr>
<tr>
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/build_compiler_runner_jar.py b/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/build_compiler_runner_jar.py
index 7be1449e436..cc1e9e47ec7 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/build_compiler_runner_jar.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/build_compiler_runner_jar.py
@@ -44,7 +44,7 @@ def build_artifacts():
manifest_file.write('Class-Path: %s\n' % closure_jar_relpath)
manifest_file.close()
javac_path = os.path.join(java_bin_path, 'javac')
- javac_command = '%s -target 7 -source 7 -d %s -cp %s %s' % (javac_path, bin_path, rel_to_abs(closure_jar_relpath),
+ javac_command = '%s -target 8 -source 8 -d %s -cp %s %s' % (javac_path, bin_path, rel_to_abs(closure_jar_relpath),
' '.join(java_files))
run_and_communicate(javac_command, 'Error: javac returned %d')
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/closure_runner.jar b/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/closure_runner.jar
index 8559612db20..300f7521635 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/closure_runner.jar
+++ b/chromium/third_party/blink/renderer/devtools/scripts/closure/closure_runner/closure_runner.jar
Binary files differ
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/closure/compiler.jar b/chromium/third_party/blink/renderer/devtools/scripts/closure/compiler.jar
index ca4eec405e4..e5552938da4 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/closure/compiler.jar
+++ b/chromium/third_party/blink/renderer/devtools/scripts/closure/compiler.jar
Binary files differ
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/compile_frontend.py b/chromium/third_party/blink/renderer/devtools/scripts/compile_frontend.py
index 2b80a773081..944ff1543ea 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/compile_frontend.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/compile_frontend.py
@@ -77,6 +77,7 @@ DEVTOOLS_FRONTEND_PATH = path.join(DEVTOOLS_PATH, 'front_end')
GLOBAL_EXTERNS_FILE = to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'externs.js'))
DEFAULT_PROTOCOL_EXTERNS_FILE = path.join(DEVTOOLS_FRONTEND_PATH, 'protocol_externs.js')
RUNTIME_FILE = to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'Runtime.js'))
+ROOT_MODULE_FILE = to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'root.js'))
CLOSURE_COMPILER_JAR = to_platform_path(path.join(SCRIPTS_PATH, 'closure', 'compiler.jar'))
CLOSURE_RUNNER_JAR = to_platform_path(path.join(SCRIPTS_PATH, 'closure', 'closure_runner', 'closure_runner.jar'))
@@ -244,14 +245,18 @@ common_closure_args = [
'SIMPLE_OPTIMIZATIONS',
'--warning_level',
'VERBOSE',
- '--language_in=ECMASCRIPT_2017',
+ '--language_in=ECMASCRIPT_NEXT',
'--language_out=ES5_STRICT',
'--extra_annotation_name',
'suppressReceiverCheck',
'--extra_annotation_name',
'suppressGlobalPropertiesCheck',
'--checks-only',
- '--allow_method_call_decomposing',
+]
+
+GENERATED_SKIP_COMPILATION_FILES = [
+ 'SupportedCSSProperties.js',
+ 'InspectorBackendCommands.js',
]
@@ -280,6 +285,8 @@ def prepare_closure_frontend_compile(temp_devtools_path, descriptors, namespace_
namespace_externs_path,
'--js',
RUNTIME_FILE,
+ '--js',
+ ROOT_MODULE_FILE,
]
all_files = descriptors.all_compiled_files()
@@ -288,6 +295,14 @@ def prepare_closure_frontend_compile(temp_devtools_path, descriptors, namespace_
args.extend(['--js', file])
if "InspectorBackend.js" in file:
args.extend(['--js', protocol_externs_file])
+
+ for file in GENERATED_SKIP_COMPILATION_FILES:
+ # Write a dummy file for skipped compilation files that are autogenerated.
+ # We don't type-check this file, but we import them via ES modules
+ generated_file = path.join(temp_frontend_path, file)
+ modular_build.write_file(generated_file, '')
+ args.extend(['--js', generated_file])
+
command += args
command = [arg.replace(DEVTOOLS_FRONTEND_PATH, temp_frontend_path) for arg in command]
compiler_args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
@@ -315,8 +330,8 @@ def generate_namespace_externs(modules_by_name):
namespaces.sort()
namespace_externs_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)
try:
+ namespace_externs_file.write('var Root = {};\n')
for namespace in namespaces:
- namespace_externs_file.write('/** @const */\n')
namespace_externs_file.write('var %s = {};\n' % namespace)
finally:
namespace_externs_file.close()
@@ -357,9 +372,7 @@ def main():
devtools_js_compile_command = closure_compiler_command + [
'--externs',
- to_platform_path(GLOBAL_EXTERNS_FILE), '--externs',
- to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'host', 'InspectorFrontendHostAPI.js')),
- '--jscomp_off=externsValidation', '--js',
+ to_platform_path(GLOBAL_EXTERNS_FILE), '--jscomp_off=externsValidation', '--js',
to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'devtools_compatibility.js'))
]
devtools_js_compile_proc = popen(devtools_js_compile_command)
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/devtools_paths.py b/chromium/third_party/blink/renderer/devtools/scripts/devtools_paths.py
new file mode 100644
index 00000000000..14d721c7dbb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/devtools_paths.py
@@ -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.
+"""
+Helper to find the path to the correct third_party directory
+"""
+
+from os import path
+import sys
+
+
+# Find the root path of the checkout.
+# In the Chromium repository, this is the src/chromium directory.
+# In the external repository, standalone build, this is the devtools-frontend directory.
+# In the external repository, integrated build, this is the src/chromium directory.
+def root_path():
+ SCRIPTS_PATH = path.dirname(path.abspath(__file__))
+ ABS_DEVTOOLS_PATH = path.dirname(SCRIPTS_PATH)
+ PARENT_PATH = path.dirname(ABS_DEVTOOLS_PATH)
+ # TODO(1011259): remove Chromium repository handling
+ if path.basename(PARENT_PATH) == 'renderer':
+ # Chromium repository
+ return path.dirname(path.dirname(path.dirname(PARENT_PATH)))
+ elif path.basename(PARENT_PATH) == 'third_party':
+ # External repository, integrated build
+ return path.dirname(PARENT_PATH)
+ else:
+ # External repository, standalone build
+ return ABS_DEVTOOLS_PATH
+
+
+# This is the third_party path relative to the root of the checkout.
+def third_party_path():
+ return path.join(root_path(), 'third_party')
+
+
+# This points to the node binary downloaded as part of the checkout.
+def node_path():
+ try:
+ old_sys_path = sys.path[:]
+ sys.path.append(path.join(third_party_path(), 'node'))
+ import node
+ finally:
+ sys.path = old_sys_path
+ return node.GetBinaryPath()
+
+
+DEVTOOLS_ROOT_PATH = path.join(path.dirname(__file__), '..')
+
+
+def node_modules_path():
+ SCRIPTS_PATH = path.dirname(path.abspath(__file__))
+ ABS_DEVTOOLS_PATH = path.dirname(SCRIPTS_PATH)
+ PARENT_PATH = path.dirname(ABS_DEVTOOLS_PATH)
+ # TODO(1011259): remove Chromium repository handling
+ if path.basename(PARENT_PATH) == 'renderer':
+ # While in Chromium repo, node modules are hosted in //third_party/devtools-node-modules.
+ return path.join(root_path(), 'third_party', 'devtools-node-modules', 'third_party', 'node_modules')
+ else:
+ # In the external repo, node modules are hosted in root.
+ return path.join(root_path(), 'node_modules')
+
+
+def eslint_path():
+ return path.join(node_modules_path(), 'eslint', 'bin', 'eslint.js')
+
+
+def karma_path():
+ return path.join(node_modules_path(), 'karma', 'bin', 'karma')
+
+
+def package_json_path():
+ return path.join(DEVTOOLS_ROOT_PATH, 'package.json')
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes
index 3f1964efc53..3b0af4560ca 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes
+++ b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/hashes
@@ -1,2 +1,2 @@
-e9e1827178cd3cbef994fca9d1abdb91157ea3ee3f8c1484bfe6611b106df24d jsdoc_validator.jar
-7dc86cebcd4d0e7251458410fdcfeea8c26ed2f00c0a06ee4484e4dd37f67e89 src
+14e6f313ee99ea6291a268a120e9e0367282a62d03e4fb6fb51f0cb0bf76cc7a jsdoc_validator.jar
+f8235688d050fa2ac061a3c7ff841e145efb38dfe29dbaae103126ec21063770 src
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar
index 676711499d5..7b11d908e5b 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar
+++ b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/jsdoc_validator.jar
Binary files differ
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/FileCheckerCallable.java b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/FileCheckerCallable.java
index 44e4676455b..5c293c61579 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/FileCheckerCallable.java
+++ b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/FileCheckerCallable.java
@@ -41,7 +41,8 @@ public class FileCheckerCallable implements Callable<ValidatorContext> {
ValidatorContext context = new ValidatorContext(readScriptText(), fileName);
ValidationCheckDispatcher dispatcher = new ValidationCheckDispatcher(context);
dispatcher.registerCheck(new ContextTrackingValidationCheck());
- NodeTraversal.traverseEs6ScopeRoots(new Compiler(), parseScript(context), null, dispatcher, true);
+ NodeTraversal.traverseScopeRoots(
+ new Compiler(), parseScript(context), null, dispatcher, true);
return context;
} catch (FileNotFoundException e) {
logError("File not found: " + fileName);
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/MethodAnnotationChecker.java b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/MethodAnnotationChecker.java
index 4d5deea6a00..221faea4a40 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/MethodAnnotationChecker.java
+++ b/chromium/third_party/blink/renderer/devtools/scripts/jsdoc_validator/src/org/chromium/devtools/jsdoc/checks/MethodAnnotationChecker.java
@@ -59,6 +59,13 @@ public final class MethodAnnotationChecker extends ContextTrackingChecker {
Set<String> formalParamNames = new HashSet<>();
for (int i = 0; i < function.parameterNames.size(); ++i) {
String paramName = function.parameterNames.get(i);
+ /**
+ * Varargs can be specified as `...varargs`, but will be named as
+ * `varargs` in the JSDoc
+ */
+ if (paramName.startsWith("...")) {
+ paramName = paramName.substring(3);
+ }
if (!formalParamNames.add(paramName)) {
reportErrorAtNodeStart(function.functionNode,
String.format("Duplicate function argument name: %s", paramName));
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/lint_javascript.py b/chromium/third_party/blink/renderer/devtools/scripts/lint_javascript.py
index 3d43a5c4356..19d31cddee1 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/lint_javascript.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/lint_javascript.py
@@ -9,7 +9,7 @@ import re
import subprocess
import sys
-import local_node
+import devtools_paths
files_to_lint = None
@@ -63,12 +63,13 @@ def js_lint(files_list=None):
eslintconfig_path = path.join(devtools_path, ".eslintrc.js")
eslintignore_path = path.join(devtools_path, ".eslintignore")
exec_command = [
- local_node.node_path(),
- local_node.eslint_path(),
+ devtools_paths.node_path(),
+ devtools_paths.eslint_path(),
"--config",
to_platform_path_exact(eslintconfig_path),
"--ignore-path",
to_platform_path_exact(eslintignore_path),
+ "--fix",
] + files_list
eslint_proc = popen(exec_command, cwd=devtools_path)
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/local_node.py b/chromium/third_party/blink/renderer/devtools/scripts/local_node.py
deleted file mode 100644
index 35ad2c9663c..00000000000
--- a/chromium/third_party/blink/renderer/devtools/scripts/local_node.py
+++ /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.
-"""
-Thin wrapper around the local node.js installed as part of chromium DEPS
-"""
-
-from os import path
-import sys
-
-SCRIPTS_PATH = path.dirname(path.abspath(__file__))
-THIRD_PARTY_PATH = path.join(SCRIPTS_PATH, '..', '..', '..', '..')
-NODE_PATH = path.join(THIRD_PARTY_PATH, 'node')
-ESLINT_PATH = path.join(THIRD_PARTY_PATH, 'devtools-node-modules', 'third_party', 'node_modules', 'eslint', 'bin', 'eslint.js')
-
-try:
- old_sys_path = sys.path[:]
- sys.path.append(NODE_PATH)
- import node
-finally:
- sys.path = old_sys_path
-
-
-def node_path():
- return node.GetBinaryPath()
-
-
-def eslint_path():
- return ESLINT_PATH
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js b/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
index 148740e73ea..90dd6b6af56 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
+++ b/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
@@ -8,7 +8,11 @@
* files and report error if present.
*/
+const fs = require('fs');
const path = require('path');
+const {promisify} = require('util');
+const writeFileAsync = promisify(fs.writeFile);
+const renameFileAsync = promisify(fs.rename);
const localizationUtils = require('./localization_utils');
const escodegen = localizationUtils.escodegen;
const esprimaTypes = localizationUtils.esprimaTypes;
@@ -19,6 +23,7 @@ const extensionStringKeys = ['category', 'destination', 'title', 'title-mac'];
// { IDS_md5-hash => {
// string: string,
// code: string,
+// isShared: boolean,
// filepath: string,
// grdpPath: string,
// location: {
@@ -56,13 +61,144 @@ const IDSkeys = new Map();
const fileToGRDPMap = new Map();
const devtoolsFrontendPath = path.resolve(__dirname, '..', '..', 'front_end');
+let devtoolsFrontendDirs;
+/**
+ * The following functions validate and update grd/grdp files.
+ */
+
+async function validateGrdAndGrdpFiles(shouldAutoFix) {
+ const grdError = await validateGrdFile(shouldAutoFix);
+ const grdpError = await validateGrdpFiles(shouldAutoFix);
+ if (grdError !== '' || grdpError !== '')
+ return `${grdError}\n${grdpError}`;
+ else
+ return '';
+}
+
+function expectedGrdpFilePath(dir) {
+ return path.resolve(dir, `${path.basename(dir)}_strings.grdp`);
+}
+
+async function validateGrdFile(shouldAutoFix) {
+ const fileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
+ const fileLines = fileContent.split('\n');
+ const newLines = [];
+ let errors = '';
+ fileLines.forEach(line => errors += validateGrdLine(line, newLines));
+ if (errors !== '' && shouldAutoFix)
+ await writeFileAsync(localizationUtils.GRD_PATH, newLines.join('\n'));
+ return errors;
+}
+
+function validateGrdLine(line, newLines) {
+ let error = '';
+ const match = line.match(/<part file="([^"]*)" \/>/);
+ if (!match) {
+ newLines.push(line);
+ return error;
+ }
+ // match[0]: full match
+ // match[1]: relative grdp file path
+ const grdpFilePath = localizationUtils.getAbsoluteGrdpPath(match[1]);
+ const expectedGrdpFile = expectedGrdpFilePath(path.dirname(grdpFilePath));
+ if (fs.existsSync(grdpFilePath) &&
+ (grdpFilePath === expectedGrdpFile || grdpFilePath === localizationUtils.SHARED_STRINGS_PATH)) {
+ newLines.push(line);
+ return error;
+ } else if (!fs.existsSync(grdpFilePath)) {
+ error += `${line.trim()} in ${
+ localizationUtils.getRelativeFilePathFromSrc(
+ localizationUtils.GRD_PATH)} refers to a grdp file that doesn't exist. ` +
+ `Please verify the grdp file and update the <part file="..."> entry to reference the correct grdp file. ` +
+ `Make sure the grdp file name is ${path.basename(expectedGrdpFile)}.`
+ } else {
+ error += `${line.trim()} in ${
+ localizationUtils.getRelativeFilePathFromSrc(localizationUtils.GRD_PATH)} should reference "${
+ localizationUtils.getRelativeGrdpPath(expectedGrdpFile)}".`;
+ }
+ return error;
+}
+
+async function validateGrdpFiles(shouldAutoFix) {
+ const frontendDirsToGrdpFiles = await mapFrontendDirsToGrdpFiles();
+ const grdFileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
+ let errors = '';
+ const renameFilePromises = [];
+ const grdpFilesToAddToGrd = [];
+ frontendDirsToGrdpFiles.forEach(
+ (grdpFiles, dir) => errors +=
+ validateGrdpFile(dir, grdpFiles, grdFileContent, shouldAutoFix, renameFilePromises, grdpFilesToAddToGrd));
+ if (grdpFilesToAddToGrd.length > 0)
+ await localizationUtils.addChildGRDPFilePathsToGRD(grdpFilesToAddToGrd.sort());
+ await Promise.all(renameFilePromises);
+ return errors;
+}
+
+async function mapFrontendDirsToGrdpFiles() {
+ devtoolsFrontendDirs =
+ devtoolsFrontendDirs || await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
+ const dirToGrdpFiles = new Map();
+ const getGrdpFilePromises = devtoolsFrontendDirs.map(dir => {
+ const files = [];
+ dirToGrdpFiles.set(dir, files);
+ return localizationUtils.getFilesFromDirectory(dir, files, ['.grdp']);
+ });
+ await Promise.all(getGrdpFilePromises);
+ return dirToGrdpFiles;
+}
+
+function validateGrdpFile(dir, grdpFiles, grdFileContent, shouldAutoFix, renameFilePromises, grdpFilesToAddToGrd) {
+ let error = '';
+ const expectedGrdpFile = expectedGrdpFilePath(dir);
+ if (grdpFiles.length === 0)
+ return error;
+ if (grdpFiles.length > 1) {
+ throw new Error(`${grdpFiles.length} GRDP files found under ${
+ localizationUtils.getRelativeFilePathFromSrc(dir)}. Please make sure there's only one GRDP file named ${
+ path.basename(expectedGrdpFile)} under this directory.`);
+ }
+
+ // Only one grdp file is under the directory
+ if (grdpFiles[0] !== expectedGrdpFile) {
+ // Rename grdp file and the reference in the grd file
+ if (shouldAutoFix) {
+ renameFilePromises.push(renameFileAsync(grdpFiles[0], expectedGrdpFile));
+ grdpFilesToAddToGrd.push(expectedGrdpFile);
+ } else {
+ error += `${localizationUtils.getRelativeFilePathFromSrc(grdpFiles[0])} should be renamed to ${
+ localizationUtils.getRelativeFilePathFromSrc(expectedGrdpFile)}.`;
+ }
+ return error;
+ }
+
+ // Only one grdp file and its name follows the naming convention
+ if (!grdFileContent.includes(localizationUtils.getRelativeGrdpPath(grdpFiles[0]))) {
+ if (shouldAutoFix) {
+ grdpFilesToAddToGrd.push(grdpFiles[0]);
+ } else {
+ error += `Please add ${localizationUtils.createPartFileEntry(grdpFiles[0]).trim()} to ${
+ localizationUtils.getRelativeFilePathFromSrc(grdpFiles[0])}.`;
+ }
+ }
+ return error;
+}
+
+/**
+ * Parse localizable resources.
+ */
async function parseLocalizableResourceMaps() {
+ if (frontendStrings.size === 0 && IDSkeys.size === 0)
+ await parseLocalizableResourceMapsHelper();
+ return [frontendStrings, IDSkeys];
+}
+
+async function parseLocalizableResourceMapsHelper() {
const grdpToFiles = new Map();
- const dirs = await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
+ const dirs = devtoolsFrontendDirs || await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
const grdpToFilesPromises = dirs.map(dir => {
const files = [];
- grdpToFiles.set(path.resolve(dir, `${path.basename(dir)}_strings.grdp`), files);
+ grdpToFiles.set(expectedGrdpFilePath(dir), files);
return localizationUtils.getFilesFromDirectory(dir, files, ['.js', 'module.json']);
});
await Promise.all(grdpToFilesPromises);
@@ -75,7 +211,7 @@ async function parseLocalizableResourceMaps() {
await Promise.all(promises);
// Parse grd(p) files after frontend strings are processed so we know
// what to add or remove based on frontend strings
- await parseIDSKeys(localizationUtils.GRD_PATH);
+ await parseIDSKeys();
}
/**
@@ -93,9 +229,20 @@ async function parseLocalizableStringsFromFile(filePath) {
if (path.basename(filePath) === 'module.json')
return parseLocalizableStringFromModuleJson(fileContent, filePath);
- const ast = esprima.parse(fileContent, {loc: true});
- for (const node of ast.body)
+ let ast;
+ try {
+ ast = esprima.parseModule(fileContent, {loc: true});
+ } catch (e) {
+ throw new Error(
+ `DevTools localization parser failed:\n${localizationUtils.getRelativeFilePathFromSrc(filePath)}: ${
+ e.message}` +
+ `\nThis error is likely due to unsupported JavaScript features.` +
+ ` Such features are not supported by eslint either and will cause presubmit to fail.` +
+ ` Please update the code and use official JavaScript features.`);
+ }
+ for (const node of ast.body) {
parseLocalizableStringFromNode(node, filePath);
+ }
}
function parseLocalizableStringFromModuleJson(fileContent, filePath) {
@@ -115,6 +262,17 @@ function parseLocalizableStringFromModuleJson(fileContent, filePath) {
if (option.text !== undefined)
addString(option.text, option.text, filePath);
}
+ } else if (key === 'defaultValue' && Array.isArray(extension[key])) {
+ for (const defaultVal of extension[key]) {
+ if (defaultVal.title)
+ addString(defaultVal.title, defaultVal.title, filePath);
+ }
+ } else if (key === 'tags' && extension[key]) {
+ const tagsList = extension[key].split(',');
+ for (let tag of tagsList) {
+ tag = tag.trim();
+ addString(tag, tag, filePath);
+ }
}
}
}
@@ -203,18 +361,27 @@ function handleTemplateLiteral(node, code, filePath, argumentNodes) {
}
function addString(str, code, filePath, location, argumentNodes) {
- const currentString = {string: str, code: code, filepath: filePath, grdpPath: fileToGRDPMap.get(filePath)};
+ const ids = localizationUtils.getIDSKey(str);
+
+ // In the case of duplicates, the corresponding grdp message should be added
+ // to the shared strings file only if the duplicate strings span across different
+ // grdp files
+ const existingString = frontendStrings.get(ids);
+ if (existingString) {
+ if (!existingString.isShared && existingString.grdpPath !== fileToGRDPMap.get(filePath)) {
+ existingString.isShared = true;
+ existingString.grdpPath = localizationUtils.SHARED_STRINGS_PATH;
+ }
+ return;
+ }
+
+ const currentString =
+ {string: str, code: code, isShared: false, filepath: filePath, grdpPath: fileToGRDPMap.get(filePath)};
if (location)
currentString.location = location;
if (argumentNodes && argumentNodes.length > 0)
currentString.arguments = argumentNodes.map(argNode => escodegen.generate(argNode));
- // In the case of duplicates, to enforce that entries are added to
- // a consistent GRDP file, we use the file path that sorts lowest as
- // the winning entry into frontendStrings.
- const ids = localizationUtils.getIDSKey(str);
- if (frontendStrings.has(ids) && frontendStrings.get(ids).filepath <= filePath)
- return;
frontendStrings.set(ids, currentString);
}
@@ -223,15 +390,15 @@ function addString(str, code, filePath, location, argumentNodes) {
* devtools frontend grdp files.
*/
-async function parseIDSKeys(grdFilePath) {
+async function parseIDSKeys() {
// NOTE: this function assumes that no <message> tags are present in the parent
- const grdpFilePaths = await parseGRDFile(grdFilePath);
+ const grdpFilePaths = await parseGRDFile();
await parseGRDPFiles(grdpFilePaths);
}
-async function parseGRDFile(grdFilePath) {
- const fileContent = await localizationUtils.parseFileContent(grdFilePath);
- const grdFileDir = path.dirname(grdFilePath);
+async function parseGRDFile() {
+ const fileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
+ const grdFileDir = path.dirname(localizationUtils.GRD_PATH);
const partFileRegex = /<part file="(.*?)"/g;
let match;
@@ -324,7 +491,7 @@ function addMessage(expectedIDSKey, actualIDSKey, grdpPath, line, description) {
* with grdp <message>s and report error of resources to add,
* remove or modify.
*/
-async function getAndReportResourcesToAdd() {
+function getAndReportResourcesToAdd() {
const keysToAddToGRD = getMessagesToAdd();
if (keysToAddToGRD.size === 0)
return;
@@ -464,8 +631,6 @@ function getLongestDescription(messages) {
}
module.exports = {
- frontendStrings,
- IDSkeys,
parseLocalizableResourceMaps,
getAndReportIDSKeysToModify,
getAndReportResourcesToAdd,
@@ -474,4 +639,5 @@ module.exports = {
getLongestDescription,
getMessagesToAdd,
getMessagesToRemove,
+ validateGrdAndGrdpFiles,
};
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js b/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
index 7a2436d0a90..faf1d24b253 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
+++ b/chromium/third_party/blink/renderer/devtools/scripts/localization_utils/localization_utils.js
@@ -9,6 +9,7 @@ const path = require('path');
const readFileAsync = promisify(fs.readFile);
const readDirAsync = promisify(fs.readdir);
const statAsync = promisify(fs.stat);
+const writeFileAsync = promisify(fs.writeFile);
const esprimaTypes = {
BI_EXPR: 'BinaryExpression',
@@ -22,8 +23,8 @@ const esprimaTypes = {
TEMP_LITERAL: 'TemplateLiteral'
};
-const excludeFiles = ['lighthouse-dt-bundle.js', 'Tests.js'];
-const excludeDirs = ['test_runner', 'Images', 'langpacks', 'node_modules'];
+const excludeFiles = ['Tests.js'];
+const excludeDirs = ['test_runner', 'Images', 'langpacks', 'node_modules', 'lighthouse'];
const cppSpecialCharactersMap = {
'"': '\\"',
'\\': '\\\\',
@@ -34,7 +35,8 @@ const IDSPrefix = 'IDS_DEVTOOLS_';
const THIRD_PARTY_PATH = path.resolve(__dirname, '..', '..', '..', '..', '..');
const SRC_PATH = path.resolve(THIRD_PARTY_PATH, '..');
const GRD_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'devtools_ui_strings.grd');
-const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'node', 'node_modules');
+const SHARED_STRINGS_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'shared_strings.grdp');
+const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'devtools-node-modules', 'third_party', 'node_modules');
const escodegen = require(path.resolve(REPO_NODE_MODULES_PATH, 'escodegen'));
const esprima = require(path.resolve(REPO_NODE_MODULES_PATH, 'esprima'));
@@ -252,7 +254,7 @@ function createGrdpMessage(ids, stringObj) {
}
function getIDSKey(str) {
- return `${IDSPrefix}${md5(str)}`
+ return `${IDSPrefix}${md5(str)}`;
}
// Get line number in the file of a character at given index
@@ -261,24 +263,76 @@ function lineNumberOfIndex(str, index) {
return stringToIndex.split('\n').length;
}
+// Relative file path from grdp file with back slash replaced with forward slash
+function getRelativeGrdpPath(grdpPath) {
+ return path.relative(path.dirname(GRD_PATH), grdpPath).split(path.sep).join('/');
+}
+
+function getAbsoluteGrdpPath(relativeGrdpFilePath) {
+ return path.resolve(path.dirname(GRD_PATH), relativeGrdpFilePath);
+}
+
+// Create a <part> entry, given absolute path of a grdp file
+function createPartFileEntry(grdpFilePath) {
+ const relativeGrdpFilePath = getRelativeGrdpPath(grdpFilePath);
+ return ` <part file="${relativeGrdpFilePath}" />\n`;
+}
+
+// grdpFilePaths are sorted and are absolute file paths
+async function addChildGRDPFilePathsToGRD(grdpFilePaths) {
+ const grdFileContent = await parseFileContent(GRD_PATH);
+ const grdLines = grdFileContent.split('\n');
+
+ let newGrdFileContent = '';
+ for (let i = 0; i < grdLines.length; i++) {
+ const grdLine = grdLines[i];
+ // match[0]: full match
+ // match[1]: relative grdp file path
+ const match = grdLine.match(/<part file="(.*?)"/);
+ if (match) {
+ const grdpFilePathsRemaining = [];
+ for (const grdpFilePath of grdpFilePaths) {
+ if (grdpFilePath < getAbsoluteGrdpPath(match[1]))
+ newGrdFileContent += createPartFileEntry(grdpFilePath);
+ else
+ grdpFilePathsRemaining.push(grdpFilePath);
+ }
+ grdpFilePaths = grdpFilePathsRemaining;
+ } else if (grdLine.includes('</messages>')) {
+ for (const grdpFilePath of grdpFilePaths)
+ newGrdFileContent += createPartFileEntry(grdpFilePath);
+ }
+ newGrdFileContent += grdLine;
+ if (i < grdLines.length - 1)
+ newGrdFileContent += '\n';
+ }
+ return writeFileAsync(GRD_PATH, newGrdFileContent);
+}
+
module.exports = {
+ addChildGRDPFilePathsToGRD,
createGrdpMessage,
+ createPartFileEntry,
escodegen,
esprima,
esprimaTypes,
+ getAbsoluteGrdpPath,
getChildDirectoriesFromDirectory,
getFilesFromDirectory,
getIDSKey,
getLocalizationCase,
getLocationMessage,
getRelativeFilePathFromSrc,
+ getRelativeGrdpPath,
GRD_PATH,
IDSPrefix,
isLocalizationCall,
lineNumberOfIndex,
modifyStringIntoGRDFormat,
parseFileContent,
+ SHARED_STRINGS_PATH,
sanitizeStringIntoCppFormat,
sanitizeStringIntoFrontendFormat,
+ shouldParseDirectory,
verifyFunctionCallee
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/migration/package.json b/chromium/third_party/blink/renderer/devtools/scripts/migration/package.json
new file mode 100644
index 00000000000..c160206d851
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/migration/package.json
@@ -0,0 +1,11 @@
+{
+ "devDependencies": {
+ "@types/node": "^12.7.1",
+ "recast": "^0.18.2",
+ "typescript": "^3.6.3"
+ },
+ "scripts": {
+ "build": "tsc",
+ "migrate": "node refactor-to-es-module.js"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-folder-to-es-modules.sh b/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-folder-to-es-modules.sh
new file mode 100755
index 00000000000..562b4363566
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-folder-to-es-modules.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# 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.
+
+if [ -z "$1" ]; then
+ echo "Must supply folder name"
+ exit
+fi
+
+MIGRATION_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+ROOT_PATH="$MIGRATION_SCRIPT_DIR/../.."
+FRONT_END_PATH="$ROOT_PATH/front_end"
+BUILD_GN_PATH="$ROOT_PATH/BUILD.gn"
+
+FOLDER_PATH="$FRONT_END_PATH/$1"
+
+if [ ! -d "$FOLDER_PATH" ]; then
+ echo "Folder on location $FOLDER_PATH does not exist"
+ exit
+fi
+
+FILES=$(find $FOLDER_PATH/*.js | xargs -n 1 basename -s .js)
+
+npm run build
+
+MODULE_FILE="$FRONT_END_PATH/$1/$1.js"
+
+touch "$MODULE_FILE"
+
+echo "// Copyright 2019 The Chromium Authors. All rights reserved." >> $MODULE_FILE
+echo "// Use of this source code is governed by a BSD-style license that can be" >> $MODULE_FILE
+echo "// found in the LICENSE file." >> $MODULE_FILE
+echo "" >> $MODULE_FILE
+
+for FILE in $FILES
+do
+ npm run migrate -- $1 $FILE
+ # Remove old reference in all_devtools_files variable
+ # The start of the substitution reads the whole file, which is necessary to remove the newline characters
+ sed -i -e ":a;N;\$!ba;s/\"front\_end\/$1\/$FILE.js\"\,\n//g" "$BUILD_GN_PATH"
+
+ # Add to all_devtools_modules
+ sed -i -e "s/all\_devtools\_modules = \[/all\_devtools\_modules = \[ \"front\_end\/$1\/$FILE.js\"\,/" "$BUILD_GN_PATH"
+ # Add to copied_devtools_modules
+ sed -i -e "s/copied\_devtools\_modules = \[/copied\_devtools\_modules = \[ \"\$resources\_out\_dir\/$1\/$FILE.js\"\,/" "$BUILD_GN_PATH"
+
+ echo "import * as $FILE from './$FILE.js';" >> $MODULE_FILE
+done
+
+# Add module entrypoint to GN variables
+sed -i -e "s/all\_devtools\_modules = \[/all\_devtools\_modules = \[ \"front\_end\/$1\/$1.js\"\,/" "$BUILD_GN_PATH"
+sed -i -e "s/copied\_devtools\_modules = \[/copied\_devtools\_modules = \[ \"\$resources\_out\_dir\/$1\/$1.js\"\,/" "$BUILD_GN_PATH"
+
+echo "" >> $MODULE_FILE
+echo "export {" >> $MODULE_FILE
+
+for FILE in $FILES
+do
+ echo " $FILE," >> $MODULE_FILE
+done
+
+echo "};" >> $MODULE_FILE
+
+git cl format
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts b/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts
new file mode 100644
index 00000000000..3b1406c07ca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts
@@ -0,0 +1,176 @@
+// 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 { parse, print, types } from 'recast';
+import fs from 'fs';
+import path from 'path';
+import { promisify } from 'util';
+import { IdentifierKind, MemberExpressionKind, ExpressionKind, CommentKind } from 'ast-types/gen/kinds';
+
+const readFile = promisify(fs.readFile);
+const writeFile = promisify(fs.writeFile);
+
+const FRONT_END_FOLDER = path.join(__dirname, '..', '..', 'front_end')
+
+function capitalizeFirstLetter(string: string) {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+}
+
+const b = types.builders;
+
+function createReplacementDeclaration(propertyName: IdentifierKind, declaration: any): any {
+ // UI.ARIAUtils.Foo = class {} -> export class Foo {}
+ if (declaration.type === 'ClassExpression') {
+ return b.exportDeclaration(false, b.classDeclaration(propertyName, declaration.body));
+ }
+ // UI.ARIAUtils.Foo = expression; -> export const Foo = expression;
+ if (declaration.type === 'Literal' || declaration.type.endsWith('Expression')) {
+ return b.exportNamedDeclaration(b.variableDeclaration("const", [b.variableDeclarator(propertyName, declaration)]));
+ }
+ console.error(`Unable to refactor declaration of type "${declaration.type}" named "${propertyName.name}"`);
+}
+
+function getTopLevelMemberExpression(expression: MemberExpressionKind): any {
+ while (expression.object.type === 'MemberExpression') {
+ expression = expression.object;
+ }
+
+ return expression;
+}
+
+function rewriteSource(source: string, refactoringNamespace: string, refactoringFileName: string) {
+ const exportedMembers: {prop: IdentifierKind, comments: CommentKind[]}[] = [];
+ const ast = parse(source);
+
+ ast.program.body = ast.program.body.map((expression: any) => {
+ // UI.ARIAUtils.Foo = 5;
+ if (expression.type === 'ExpressionStatement') {
+ // UI.ARIAUtils.Foo = 5
+ if (expression.expression.type === 'AssignmentExpression') {
+ const assignment = expression.expression;
+
+ // UI.ARIAUtils.Foo
+ if (assignment.left.type === 'MemberExpression') {
+ // UI.ARIAUtils.Foo -> UI.ARIAUtils
+ // UI.ARIAUtils.Nested.Foo -> UI.ARIAUtils
+ const topLevelAssignment = getTopLevelMemberExpression(assignment.left);
+
+ // If there is a nested export, such as `UI.ARIAUtils.Nested.Field`
+ if (topLevelAssignment !== assignment.left.object) {
+ // Exports itself. E.g. `UI.ARIAUtils = <...>`
+ if (assignment.left.object.name === refactoringNamespace && assignment.left.property.name === refactoringFileName) {
+ const {declaration} = createReplacementDeclaration(assignment.left.property, assignment.right);
+ // If it is a variable declaration, we need to use the actual variabledeclator. E.g.:
+ // UI.ARIAUtils = 5; -> export ARIAUtils = 5; instead of "export const ARIAUtils = 5;"
+ const declarationStatement = b.exportDefaultDeclaration(declaration.type === 'VariableDeclaration' ? declaration.declarations[0].init : declaration);
+
+ declarationStatement.comments = expression.comments;
+
+ return declarationStatement;
+ }
+
+ console.error(`Nested field "${assignment.left.property.name}" detected! Requires manual changes.`);
+ expression.comments = expression.comments || [];
+ expression.comments.push(b.commentLine(' TODO(http://crbug.com/1006759): Fix exported symbol'));
+ return expression;
+ }
+
+ const propertyName = assignment.left.property;
+ const {object, property} = topLevelAssignment;
+
+
+ if (object.type === 'Identifier' && property.type === 'Identifier') {
+ // UI
+ const namespace = object.name;
+ // ARIAUtils
+ const fileName = property.name;
+
+ if (namespace === refactoringNamespace && fileName === refactoringFileName) {
+ const declaration = createReplacementDeclaration(propertyName, assignment.right);
+
+ if (declaration) {
+ exportedMembers.push({prop: propertyName, comments: expression.comments || [b.commentLine(' TODO(http://crbug.com/1006759): Add type information if necessary')]});
+ declaration.comments = expression.comments;
+ return declaration;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return expression;
+ });
+
+ // self.UI = self.UI || {};
+ {
+ const legacyNamespaceName = b.memberExpression(b.identifier('self'), b.identifier(refactoringNamespace), false);
+ const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([]));
+ ast.program.body.push(b.expressionStatement.from({
+ expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr),
+ comments: [b.commentBlock(' Legacy exported object ', true, false)]
+ }));
+ }
+
+ // UI = UI || {};
+ const legacyNamespaceName = b.identifier(refactoringNamespace)
+ {
+ const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([]));
+ ast.program.body.push(b.expressionStatement.from({
+ expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr),
+ comments: [b.commentBlock(' Legacy exported object ', true, false)]
+ }));
+ }
+
+ // UI.ARIAUtils = ARIAUtils;
+ const legacyNamespaceExport = b.memberExpression(b.identifier(refactoringNamespace), b.identifier(refactoringFileName), false);
+
+ ast.program.body.push(b.expressionStatement(b.assignmentExpression.from({
+ operator: '=',
+ left: legacyNamespaceExport,
+ right: b.identifier(refactoringFileName),
+ comments: [b.commentLine(' TODO(http://crbug.com/1006759): Add type information if necessary')]
+ })));
+
+ // UI.ARIAUtils.Foo = Foo;
+ exportedMembers.forEach(({prop, comments}) => {
+ const legacyExportedProperty = b.memberExpression(legacyNamespaceExport, b.identifier(prop.name), false);
+
+ ast.program.body.push(b.expressionStatement(b.assignmentExpression.from({
+ operator: '=',
+ left: legacyExportedProperty,
+ right: b.identifier(prop.name),
+ comments,
+ })));
+ });
+
+ return print(ast).code;
+}
+
+const FOLDER_MAPPING: {[name: string]: string} = require(path.join('..', 'special_case_namespaces.json'));
+
+function computeNamespaceName(folderName: string): string {
+ if (folderName in FOLDER_MAPPING) {
+ return FOLDER_MAPPING[folderName];
+ }
+ return capitalizeFirstLetter(folderName);
+}
+
+async function main(refactoringNamespace: string, refactoringFileName: string) {
+ const pathName = path.join(FRONT_END_FOLDER, refactoringNamespace, `${refactoringFileName}.js`);
+ const source = await readFile(pathName, {encoding: 'utf-8'});
+
+ const rewrittenSource = rewriteSource(source, computeNamespaceName(process.argv[2]), refactoringFileName);
+
+ await writeFile(pathName, rewrittenSource);
+
+ // console.log(`Succesfully written source to "${pathName}". Make sure that no other errors are reported before submitting!`);
+}
+
+if (!process.argv[2]) {
+ console.error(`No arguments specified. Run this script with "<folder-name> <filename>". For example: "common Color"`);
+ process.exit(1);
+}
+
+main(process.argv[2], process.argv[3]); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/migration/tsconfig.json b/chromium/third_party/blink/renderer/devtools/scripts/migration/tsconfig.json
new file mode 100644
index 00000000000..33cf4a789a5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/migration/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "module": "commonjs",
+ "strict": true,
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "declaration": false
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/run_tests.py b/chromium/third_party/blink/renderer/devtools/scripts/run_tests.py
new file mode 100755
index 00000000000..da9fcd82bdb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/scripts/run_tests.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+#
+# 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 os
+import re
+import subprocess
+import sys
+
+import devtools_paths
+
+is_cygwin = sys.platform == 'cygwin'
+chrome_binary = None
+
+if len(sys.argv) >= 2:
+ chrome_binary = re.sub(r'^\-\-chrome-binary=(.*)', '\\1', sys.argv[1])
+ is_executable = os.path.exists(chrome_binary) and os.path.isfile(chrome_binary) and os.access(chrome_binary, os.X_OK)
+ if not is_executable:
+ print('Unable to find a Chrome binary at \'%s\'' % chrome_binary)
+ sys.exit(1)
+
+
+def popen(arguments, cwd=None, env=None):
+ return subprocess.Popen(arguments, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
+
+
+def to_platform_path_exact(filepath):
+ if not is_cygwin:
+ return filepath
+ output, _ = popen(['cygpath', '-w', filepath]).communicate()
+ # pylint: disable=E1103
+ return output.strip().replace('\\', '\\\\')
+
+
+scripts_path = os.path.dirname(os.path.abspath(__file__))
+devtools_path = os.path.dirname(scripts_path)
+
+print('Running tests with Karma...')
+if (chrome_binary is not None):
+ print('Using custom Chrome Binary (%s)\n' % chrome_binary)
+else:
+ print('Using system Chrome')
+
+
+def run_tests():
+ karma_errors_found = False
+
+ karmaconfig_path = os.path.join(devtools_path, 'karma.conf.js')
+ exec_command = [devtools_paths.node_path(), devtools_paths.karma_path(), 'start', to_platform_path_exact(karmaconfig_path)]
+
+ env = {'NODE_PATH': devtools_paths.node_modules_path()}
+ if (chrome_binary is not None):
+ env['CHROME_BIN'] = chrome_binary
+
+ karma_proc = popen(exec_command, cwd=devtools_path, env=env)
+
+ (karma_proc_out, _) = karma_proc.communicate()
+ if karma_proc.returncode != 0:
+ karma_errors_found = True
+ else:
+ print('Karma exited successfully')
+
+ print(karma_proc_out)
+ return karma_errors_found
+
+
+errors_found = run_tests()
+
+if errors_found:
+ print('ERRORS DETECTED')
+ sys.exit(1)
diff --git a/chromium/third_party/blink/renderer/devtools/services/devtools.js b/chromium/third_party/blink/renderer/devtools/services/devtools.js
deleted file mode 100644
index 831acea0514..00000000000
--- a/chromium/third_party/blink/renderer/devtools/services/devtools.js
+++ /dev/null
@@ -1,12 +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.
-
-var dispatcher = require("./dispatcher.js");
-var terminal = require("./terminal.js");
-
-var d = new dispatcher.Dispatcher();
-d.registerObject("Terminal", terminal.Terminal);
-d.start(9022);
-
-console.log("Run chrome as `chrome --devtools-flags='service-backend=ws://localhost:9022/endpoint'`");
diff --git a/chromium/third_party/blink/renderer/devtools/services/dispatcher.js b/chromium/third_party/blink/renderer/devtools/services/dispatcher.js
deleted file mode 100644
index 3735931329a..00000000000
--- a/chromium/third_party/blink/renderer/devtools/services/dispatcher.js
+++ /dev/null
@@ -1,130 +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.
-
-var http = require("http");
-var ws = require("ws");
-
-function Dispatcher()
-{
- this._constructors = new Map();
- this._connections = new Set();
-}
-
-Dispatcher.prototype = {
- start: function(port)
- {
- var http_server = http.createServer();
- http_server.listen(port);
-
- var WebSocketServer = ws.Server;
- var options = { server: http_server, path: "/endpoint" };
- var wss = new WebSocketServer(options);
- wss.on("connection", (socket) => {
- var connection = new Connection(this, socket);
- this._connections.add(connection);
- });
- },
-
- registerObject: function(name, constructor)
- {
- this._constructors.set(name, constructor);
- },
-
- _connectionClosed: function(connection)
- {
- this._connections.delete(connection);
- }
-}
-
-exports.Dispatcher = Dispatcher;
-
-function Connection(dispatcher, socket)
-{
- this._dispatcher = dispatcher;
- this._objects = new Map();
- this._lastObjectId = 1;
- this._socket = socket;
- this._socket.on("message", this._dispatchMessageWrapped.bind(this));
- this._socket.on("close", this._connectionClosed.bind(this));
-}
-
-Connection.prototype = {
- _dispatchMessageWrapped: function(data)
- {
- try {
- var message = JSON.parse(data);
- this._dispatchMessage(message);
- } catch(e) {
- this._sendErrorResponse(message.id, e.toString());
- }
- },
-
- _dispatchMessage: function(message)
- {
- var [objectName, method] = message.method.split(".");
- var result = JSON.stringify({id: message.id});
- var constructor = this._dispatcher._constructors.get(objectName);
- if (!constructor) {
- this._sendErrorResponse(message.id, "Could not resolve service '" + objectName + "'");
- return;
- }
- if (method === "create") {
- var id = String(this._lastObjectId++);
- var object = new constructor(this._notify.bind(this, id, objectName));
- this._objects.set(id, object);
- this._sendResponse(message.id, { id: id });
- } else if (method === "dispose") {
- var object = this._objects.get(message.params.id);
- if (!object) {
- console.error("Could not look up object with id for " + JSON.stringify(message));
- return;
- }
- this._objects.delete(message.params.id);
- object.dispose().then(() => this._sendResponse(message.id));
- } else {
- if (!message.params) {
- console.error("No params in the message: " + JSON.stringify(message));
- return;
- }
- var object = this._objects.get(message.params.id);
- if (!object) {
- console.error("Could not look up object with id for " + JSON.stringify(message));
- return;
- }
- var handler = object[method];
- if (!(handler instanceof Function)) {
- console.error("Handler for '" + method + "' is missing.");
- return;
- }
- object[method](message.params).then(result => this._sendResponse(message.id, result));
- }
- },
-
- _connectionClosed: function()
- {
- for (var object of this._objects.values())
- object.dispose();
- this._objects.clear();
- this._dispatcher._connectionClosed(this);
- },
-
- _notify: function(objectId, objectName, method, params)
- {
- params["id"] = objectId;
- var message = { method: objectName + "." + method, params: params };
- this._socket.send(JSON.stringify(message));
- },
-
- _sendResponse: function(messageId, result)
- {
- var message = { id: messageId, result: result };
- this._socket.send(JSON.stringify(message));
- },
-
- _sendErrorResponse: function(messageId, error)
- {
- var message = { id: messageId, error: error };
- this._socket.send(JSON.stringify(message));
- },
-}
diff --git a/chromium/third_party/blink/renderer/devtools/services/package.json b/chromium/third_party/blink/renderer/devtools/services/package.json
deleted file mode 100644
index 824851cef23..00000000000
--- a/chromium/third_party/blink/renderer/devtools/services/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name": "devtools-backend",
- "version": "1.0.0",
- "ignore": [
- ".gitignore"
- ],
- "dependencies": {
- "pty.js": "0.3.1",
- "ws": "^1.1.1"
- }
-}
diff --git a/chromium/third_party/blink/renderer/devtools/services/terminal.js b/chromium/third_party/blink/renderer/devtools/services/terminal.js
deleted file mode 100644
index 742b553f890..00000000000
--- a/chromium/third_party/blink/renderer/devtools/services/terminal.js
+++ /dev/null
@@ -1,52 +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.
-
-var pty = require("pty.js");
-
-function Terminal(notify)
-{
- this._notify = notify;
-}
-
-Terminal.prototype = {
- init: function(params)
- {
- this._term = pty.spawn(process.platform === "win32" ? "cmd.exe" : "bash", [], {
- name: "xterm-color",
- cols: params.cols || 80,
- rows: params.rows || 24,
- cwd: process.env.PWD,
- env: process.env
- });
-
- this._term.on("data", data => {
- if (this._notify)
- this._notify("data", { data: data });
- });
- return Promise.resolve({});
- },
-
- resize: function(params)
- {
- if (this._term)
- this._term.resize(params.cols, params.rows);
- return Promise.resolve({});
- },
-
- write: function(params)
- {
- this._term.write(params.data);
- return Promise.resolve({});
- },
-
- dispose: function(params)
- {
- this._notify = null;
- if (this._term)
- process.kill(this._term.pid);
- return Promise.resolve({});
- },
-}
-
-exports.Terminal = Terminal;
diff --git a/chromium/third_party/blink/renderer/devtools/tsconfig.json b/chromium/third_party/blink/renderer/devtools/tsconfig.json
new file mode 100644
index 00000000000..1d010b66b58
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "compilerOptions": {
+ "module": "esnext",
+ "target": "esnext",
+ "typeRoots": ["../../../devtools-node-modules/third_party/node_modules/@types"]
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/BUILD.gn b/chromium/third_party/blink/renderer/modules/BUILD.gn
index 30dcfb2b62c..e2b05af5f10 100644
--- a/chromium/third_party/blink/renderer/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/BUILD.gn
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
-import("//build/split_static_library.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")
@@ -18,37 +17,19 @@ if (is_android) {
visibility = [ "//third_party/blink/renderer/*" ]
-if (!is_component_build && is_win) {
- # This target as a static library (for non-component builds) is >2GB for
- # official builds and some goma builds on Windows. This causes linking to
- # fail. As a workaround, force using a split static library for these
- # configurations.
- modules_target_type = "split_static_library"
-} else {
- modules_target_type = "component"
-}
-
config("modules_implementation") {
defines = [ "BLINK_MODULES_IMPLEMENTATION=1" ]
}
-config("notouch_config") {
- defines = [ "TOUCHLESS_MEDIA_CONTROLS" ]
-}
-
make_names("module_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).
}
-target("jumbo_" + modules_target_type, "modules") {
+jumbo_component("modules") {
output_name = "blink_modules"
- if (modules_target_type == "split_static_library") {
- split_count = 5
- }
-
visibility = [] # Allow re-assignment of list.
visibility = [ "//third_party/blink/*" ]
@@ -103,6 +84,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/credentialmanager",
"//third_party/blink/renderer/modules/crypto",
"//third_party/blink/renderer/modules/csspaint",
+ "//third_party/blink/renderer/modules/compression",
"//third_party/blink/renderer/modules/device_orientation",
"//third_party/blink/renderer/modules/document_metadata",
"//third_party/blink/renderer/modules/donottrack",
@@ -139,6 +121,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/nfc",
"//third_party/blink/renderer/modules/notifications",
"//third_party/blink/renderer/modules/payments",
+ "//third_party/blink/renderer/modules/p2p",
"//third_party/blink/renderer/modules/peerconnection",
"//third_party/blink/renderer/modules/permissions",
"//third_party/blink/renderer/modules/picture_in_picture",
@@ -175,6 +158,7 @@ target("jumbo_" + modules_target_type, "modules") {
deps = [
":make_modules_generated",
":module_names",
+ "//jingle:webrtc_glue",
"//net:net",
"//third_party/blink/renderer/bindings/modules:generated",
"//third_party/blink/renderer/bindings/modules/v8:bindings_modules_impl",
@@ -182,6 +166,9 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/core",
"//third_party/icu",
"//third_party/webrtc/api/audio:aec3_config_json",
+ "//third_party/webrtc/api/rtc_event_log:rtc_event_log_factory",
+ "//third_party/webrtc/media:rtc_internal_video_codecs",
+ "//third_party/webrtc/modules/video_coding:webrtc_h264",
"//third_party/webrtc/pc:libjingle_peerconnection",
"//third_party/webrtc/rtc_base:rtc_base",
"//third_party/webrtc_overrides:init_webrtc",
@@ -202,10 +189,6 @@ target("jumbo_" + modules_target_type, "modules") {
configs -= [ "//build/config/compiler:default_symbols" ]
configs += blink_symbols_config
-
- if (is_android && notouch_build) {
- configs += [ ":notouch_config" ]
- }
}
jumbo_source_set("modules_testing") {
@@ -383,6 +366,8 @@ jumbo_source_set("unit_tests") {
"peerconnection/adapters/quic_packet_transport_adapter_test.cc",
"peerconnection/byte_buffer_queue_test.cc",
"peerconnection/call_setup_state_tracker_unittest.cc",
+ "peerconnection/media_stream_remote_video_source_test.cc",
+ "peerconnection/media_stream_video_webrtc_sink_test.cc",
"peerconnection/rtc_data_channel_test.cc",
"peerconnection/rtc_ice_transport_test.cc",
"peerconnection/rtc_ice_transport_test.h",
@@ -390,7 +375,13 @@ jumbo_source_set("unit_tests") {
"peerconnection/rtc_quic_stream_test.cc",
"peerconnection/rtc_quic_transport_test.cc",
"peerconnection/rtc_quic_transport_test.h",
+ "peerconnection/rtc_rtp_receiver_impl_test.cc",
+ "peerconnection/rtc_rtp_sender_impl_test.cc",
+ "peerconnection/rtc_rtp_transceiver_impl_test.cc",
"peerconnection/rtc_sctp_transport_test.cc",
+ "peerconnection/transceiver_state_surfacer_test.cc",
+ "peerconnection/webrtc_media_stream_track_adapter_map_test.cc",
+ "peerconnection/webrtc_media_stream_track_adapter_test.cc",
"picture_in_picture/picture_in_picture_controller_test.cc",
"presentation/mock_presentation_service.h",
"presentation/presentation_availability_state_test.cc",
@@ -402,13 +393,17 @@ jumbo_source_set("unit_tests") {
"push_messaging/push_subscription_test.cc",
"remoteplayback/remote_playback_test.cc",
"screen_orientation/screen_orientation_controller_impl_test.cc",
+ "sensor/ambient_light_sensor_test.cc",
+ "sensor/sensor_test_utils.cc",
+ "sensor/sensor_test_utils.h",
"service_worker/service_worker_container_test.cc",
"service_worker/service_worker_installed_scripts_manager_test.cc",
"service_worker/service_worker_timeout_timer_test.cc",
"service_worker/thread_safe_script_container_test.cc",
"service_worker/web_embedded_worker_impl_test.cc",
- "wake_lock/wake_lock_controller_test.cc",
+ "wake_lock/wake_lock_sentinel_test.cc",
"wake_lock/wake_lock_state_record_test.cc",
+ "wake_lock/wake_lock_test.cc",
"wake_lock/wake_lock_test_utils.cc",
"wake_lock/wake_lock_test_utils.h",
"webaudio/audio_basic_processor_handler_test.cc",
@@ -442,14 +437,6 @@ jumbo_source_set("unit_tests") {
sources += [ "payments/skip_to_gpay_utils_test.cc" ]
}
- if (is_android && notouch_build) {
- sources += [
- "media_controls/touchless/media_controls_touchless_impl_test.cc",
- "media_controls/touchless/test_media_controls_menu_host.cc",
- "media_controls/touchless/test_media_controls_menu_host.h",
- ]
- }
-
configs += [
"//third_party/blink/renderer:config",
"//third_party/blink/renderer:inside_blink",
@@ -470,10 +457,12 @@ jumbo_source_set("unit_tests") {
"//third_party/blink/renderer/core",
"//third_party/blink/renderer/modules/gamepad:unit_tests",
"//third_party/blink/renderer/modules/hid:unit_tests",
+ "//third_party/blink/renderer/modules/native_file_system:unit_tests",
"//third_party/blink/renderer/modules/storage:unit_tests",
"//third_party/blink/renderer/platform",
"//third_party/blink/renderer/platform/wtf",
"//third_party/opus",
+ "//third_party/webrtc/api:rtc_error",
"//third_party/webrtc/rtc_base:rtc_base",
"//v8",
]
@@ -496,6 +485,20 @@ group("mediastream_unittests_data") {
]
}
+fuzzer_test("web_app_manifest_fuzzer") {
+ sources = [
+ "manifest/manifest_fuzzer.cc",
+ ]
+
+ dict = "manifest/manifest_fuzzer.dict"
+ seed_corpus = "manifest/fuzzer_seed_corpus"
+
+ deps = [
+ ":modules",
+ "//third_party/blink/renderer/platform:blink_fuzzer_test_support",
+ ]
+}
+
if (use_libfuzzer) {
fuzzer_test("media_capabilities_fuzzer") {
sources = [
diff --git a/chromium/third_party/blink/renderer/modules/DEPS b/chromium/third_party/blink/renderer/modules/DEPS
index 01c7bc15c08..04ac79802bf 100644
--- a/chromium/third_party/blink/renderer/modules/DEPS
+++ b/chromium/third_party/blink/renderer/modules/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+mojo/public/cpp/bindings",
"+services/network/public/cpp/shared_url_loader_factory.h",
"+services/service_manager/public/mojom/interface_provider.mojom-blink.h",
+ "+services/service_manager/public/mojom/interface_provider.mojom-blink-forward.h",
"+services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h",
"+third_party/blink/public/common",
"+third_party/blink/public/web",
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/DEPS b/chromium/third_party/blink/renderer/modules/accessibility/DEPS
index 44011c4a0c6..7f78b77b1af 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/DEPS
+++ b/chromium/third_party/blink/renderer/modules/accessibility/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+mojo/public/cpp/bindings/binding.h",
"+ui/accessibility/ax_enums.mojom-blink.h",
+ "+ui/accessibility/ax_enums.mojom-blink-forward.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/accessibility",
"+third_party/blink/renderer/modules/media_controls",
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 a562d988634..dd4f45e43d0 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
@@ -100,8 +100,6 @@
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-using blink::WebLocalizedString;
-
namespace {
bool IsNeutralWithinTable(blink::AXObject* obj) {
if (!obj)
@@ -115,13 +113,10 @@ bool IsNeutralWithinTable(blink::AXObject* obj) {
namespace blink {
-using namespace html_names;
-
AXLayoutObject::AXLayoutObject(LayoutObject* layout_object,
AXObjectCacheImpl& ax_object_cache)
: AXNodeObject(layout_object->GetNode(), ax_object_cache),
- layout_object_(layout_object),
- is_autofill_available_(false) {
+ layout_object_(layout_object) {
// TODO(aleventhal) Get correct current state of autofill.
#if DCHECK_IS_ON()
layout_object_->SetHasAXObject(true);
@@ -517,7 +512,7 @@ AccessibilityGrabbedState AXLayoutObject::IsGrabbed() const {
if (!SupportsARIADragging())
return kGrabbedStateUndefined;
- const AtomicString& grabbed = GetAttribute(kAriaGrabbedAttr);
+ const AtomicString& grabbed = GetAttribute(html_names::kAriaGrabbedAttr);
return EqualIgnoringASCIICase(grabbed, "true") ? kGrabbedStateTrue
: kGrabbedStateFalse;
}
@@ -763,7 +758,8 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
bool AXLayoutObject::HasAriaCellRole(Element* elem) const {
DCHECK(elem);
- const AtomicString& aria_role_str = elem->FastGetAttribute(kRoleAttr);
+ const AtomicString& aria_role_str =
+ elem->FastGetAttribute(html_names::kRoleAttr);
if (aria_role_str.IsEmpty())
return false;
@@ -877,7 +873,7 @@ const AtomicString& AXLayoutObject::AccessKey() const {
auto* element = DynamicTo<Element>(layout_object_->GetNode());
if (!element)
return g_null_atom;
- return element->getAttribute(kAccesskeyAttr);
+ return element->getAttribute(html_names::kAccesskeyAttr);
}
RGBA32 AXLayoutObject::ComputeBackgroundColor() const {
@@ -934,7 +930,7 @@ RGBA32 AXLayoutObject::GetColor() const {
return color.Rgb();
}
-AtomicString AXLayoutObject::FontFamily() const {
+String AXLayoutObject::FontFamily() const {
if (!GetLayoutObject())
return AXNodeObject::FontFamily();
@@ -942,9 +938,11 @@ AtomicString AXLayoutObject::FontFamily() const {
if (!style)
return AXNodeObject::FontFamily();
- FontDescription& font_description =
- const_cast<FontDescription&>(style->GetFontDescription());
- return font_description.FirstFamily().Family();
+ const SimpleFontData* primary_font = style->GetFont().PrimaryFont();
+ if (!primary_font)
+ return AXNodeObject::FontFamily();
+
+ return primary_font->PlatformData().FontFamilyName();
}
// Font size is in pixels.
@@ -1429,15 +1427,15 @@ String AXLayoutObject::StringValue() const {
// LayoutMenuList will go straight to the text() of its selected item.
// This has to be overridden in the case where the selected item has an ARIA
// label.
- HTMLSelectElement* select_element =
- ToHTMLSelectElement(layout_object_->GetNode());
+ auto* select_element = To<HTMLSelectElement>(layout_object_->GetNode());
int selected_index = select_element->selectedIndex();
const HeapVector<Member<HTMLElement>>& list_items =
select_element->GetListItems();
if (selected_index >= 0 &&
static_cast<size_t>(selected_index) < list_items.size()) {
const AtomicString& overridden_description =
- list_items[selected_index]->FastGetAttribute(kAriaLabelAttr);
+ list_items[selected_index]->FastGetAttribute(
+ html_names::kAriaLabelAttr);
if (!overridden_description.IsNull())
return overridden_description;
}
@@ -1604,18 +1602,18 @@ ax::mojom::HasPopup AXLayoutObject::HasPopup() const {
// a future version of WAI-ARIA. After that we will re-implement them
// following new spec.
bool AXLayoutObject::SupportsARIADragging() const {
- const AtomicString& grabbed = GetAttribute(kAriaGrabbedAttr);
+ const AtomicString& grabbed = GetAttribute(html_names::kAriaGrabbedAttr);
return EqualIgnoringASCIICase(grabbed, "true") ||
EqualIgnoringASCIICase(grabbed, "false");
}
void AXLayoutObject::Dropeffects(
Vector<ax::mojom::Dropeffect>& dropeffects) const {
- if (!HasAttribute(kAriaDropeffectAttr))
+ if (!HasAttribute(html_names::kAriaDropeffectAttr))
return;
Vector<String> str_dropeffects;
- TokenVectorFromAttribute(str_dropeffects, kAriaDropeffectAttr);
+ TokenVectorFromAttribute(str_dropeffects, html_names::kAriaDropeffectAttr);
if (str_dropeffects.IsEmpty()) {
dropeffects.push_back(ax::mojom::Dropeffect::kNone);
@@ -1643,13 +1641,13 @@ ax::mojom::Dropeffect AXLayoutObject::ParseDropeffect(
}
bool AXLayoutObject::SupportsARIAFlowTo() const {
- return !GetAttribute(kAriaFlowtoAttr).IsEmpty();
+ return !GetAttribute(html_names::kAriaFlowtoAttr).IsEmpty();
}
bool AXLayoutObject::SupportsARIAOwns() const {
if (!layout_object_)
return false;
- const AtomicString& aria_owns = GetAttribute(kAriaOwnsAttr);
+ const AtomicString& aria_owns = GetAttribute(html_names::kAriaOwnsAttr);
return !aria_owns.IsEmpty();
}
@@ -1728,7 +1726,7 @@ AXObject* AXLayoutObject::AccessibilityHitTest(const IntPoint& point) const {
if (auto* area = DynamicTo<HTMLAreaElement>(node))
return AccessibilityImageMapHitTest(area, point);
- if (auto* option = ToHTMLOptionElementOrNull(node)) {
+ if (auto* option = DynamicTo<HTMLOptionElement>(node)) {
node = option->OwnerSelectElement();
if (!node)
return nullptr;
@@ -2348,11 +2346,15 @@ void AXLayoutObject::HandleAriaExpandedChanged() {
}
}
-void AXLayoutObject::HandleAutofillStateChanged(bool available) {
- if (is_autofill_available_ != available) {
- is_autofill_available_ = available;
- AXObjectCache().MarkAXObjectDirty(this, false);
- }
+bool AXLayoutObject::IsAutofillAvailable() const {
+ // Autofill state is stored in AXObjectCache.
+ WebAXAutofillState state = AXObjectCache().GetAutofillState(AXObjectID());
+ return state == WebAXAutofillState::kAutofillAvailable;
+}
+
+void AXLayoutObject::HandleAutofillStateChanged(WebAXAutofillState state) {
+ // Autofill state is stored in AXObjectCache.
+ AXObjectCache().SetAutofillState(AXObjectID(), state);
}
void AXLayoutObject::TextChanged() {
@@ -2534,7 +2536,7 @@ bool AXLayoutObject::IsDataTable() const {
valid_cell_count++;
// Any <th> tag -> treat as data table.
- if (cell_node->HasTagName(kThTag))
+ if (cell_node->HasTagName(html_names::kThTag))
return true;
// In this case, the developer explicitly assigned a "data" table
@@ -2543,7 +2545,7 @@ bool AXLayoutObject::IsDataTable() const {
HTMLTableCellElement& cell_element = ToHTMLTableCellElement(*cell_node);
if (!cell_element.Headers().IsEmpty() ||
!cell_element.Abbr().IsEmpty() || !cell_element.Axis().IsEmpty() ||
- !cell_element.FastGetAttribute(kScopeAttr).IsEmpty())
+ !cell_element.FastGetAttribute(html_names::kScopeAttr).IsEmpty())
return true;
}
@@ -2791,7 +2793,7 @@ static bool IsNonEmptyNonHeaderCell(const LayoutNGTableCellInterface* cell) {
return false;
if (Node* node = cell->ToLayoutObject()->GetNode())
- return node->hasChildren() && node->HasTagName(kTdTag);
+ return node->hasChildren() && node->HasTagName(html_names::kTdTag);
return false;
}
@@ -2801,7 +2803,7 @@ static bool IsHeaderCell(const LayoutNGTableCellInterface* cell) {
return false;
if (Node* node = cell->ToLayoutObject()->GetNode())
- return node->HasTagName(kThTag);
+ return node->HasTagName(html_names::kThTag);
return false;
}
@@ -2884,10 +2886,10 @@ ax::mojom::Role AXLayoutObject::DetermineTableCellRole() const {
if (parent->RoleValue() == ax::mojom::Role::kLayoutTableRow)
return ax::mojom::Role::kLayoutTableCell;
- if (!GetNode() || !GetNode()->HasTagName(kThTag))
+ if (!GetNode() || !GetNode()->HasTagName(html_names::kThTag))
return ax::mojom::Role::kCell;
- const AtomicString& scope = GetAttribute(kScopeAttr);
+ const AtomicString& scope = GetAttribute(html_names::kScopeAttr);
if (EqualIgnoringASCIICase(scope, "row") ||
EqualIgnoringASCIICase(scope, "rowgroup"))
return ax::mojom::Role::kRowHeader;
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 8c5c0a99f3f..fef4861c90c 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
@@ -77,7 +77,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
bool IsAXLayoutObject() const override { return true; }
// Check object role or purpose.
- bool IsAutofillAvailable() override { return is_autofill_available_; }
+ bool IsAutofillAvailable() const override;
bool IsDefault() const override;
bool IsEditable() const override;
bool IsRichlyEditable() const override;
@@ -103,7 +103,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
const AtomicString& AccessKey() const override;
RGBA32 ComputeBackgroundColor() const final;
RGBA32 GetColor() const final;
- AtomicString FontFamily() const final;
+ String FontFamily() const final;
// Font size is in pixels.
float FontSize() const final;
float FontWeight() const final;
@@ -186,8 +186,8 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// Notifications that this object may have changed.
void HandleActiveDescendantChanged() override;
void HandleAriaExpandedChanged() override;
- // Called when autofill becomes available/unavailable on a form control.
- void HandleAutofillStateChanged(bool) override;
+ // Called when autofill/autocomplete state changes on a form control.
+ void HandleAutofillStateChanged(WebAXAutofillState state) override;
void TextChanged() override;
// For a table.
@@ -239,8 +239,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
TextDecorationStyleToAXTextDecorationStyle(
const ETextDecorationStyle text_decoration_style);
- bool is_autofill_available_;
-
DISALLOW_COPY_AND_ASSIGN(AXLayoutObject);
};
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_list.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_list.cc
index 5ef457e2da1..576bea195ca 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_list.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_list.cc
@@ -34,8 +34,6 @@
namespace blink {
-using namespace html_names;
-
AXList::AXList(LayoutObject* layout_object, AXObjectCacheImpl& ax_object_cache)
: AXLayoutObject(layout_object, ax_object_cache) {}
@@ -51,7 +49,7 @@ bool AXList::IsDescriptionList() const {
return false;
Node* node = layout_object_->GetNode();
- return node && node->HasTagName(kDlTag);
+ return node && node->HasTagName(html_names::kDlTag);
}
ax::mojom::Role AXList::RoleValue() const {
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box.cc
index fc601746aac..3f9c26a9deb 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box.cc
@@ -51,10 +51,10 @@ ax::mojom::Role AXListBox::DetermineAccessibilityRole() {
}
AXObject* AXListBox::ActiveDescendant() {
- if (!IsHTMLSelectElement(GetNode()))
+ auto* select = DynamicTo<HTMLSelectElement>(GetNode());
+ if (!select)
return nullptr;
- HTMLSelectElement* select = ToHTMLSelectElement(GetNode());
int active_index = select->ActiveSelectionEndListIndex();
if (active_index >= 0 && active_index < static_cast<int>(select->length())) {
HTMLOptionElement* option = select->item(active_index_);
@@ -65,10 +65,10 @@ AXObject* AXListBox::ActiveDescendant() {
}
void AXListBox::ActiveIndexChanged() {
- if (!IsHTMLSelectElement(GetNode()))
+ auto* select = DynamicTo<HTMLSelectElement>(GetNode());
+ if (!select)
return;
- HTMLSelectElement* select = ToHTMLSelectElement(GetNode());
int active_index = select->ActiveSelectionEndListIndex();
if (active_index == active_index_)
return;
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 d9330ea3e5d..7161e3ab512 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
@@ -77,10 +77,9 @@ AccessibilitySelectedState AXListBoxOption::IsSelected() const {
if (!GetNode() || !CanSetSelectedAttribute())
return kSelectedStateUndefined;
- return (IsHTMLOptionElement(GetNode()) &&
- ToHTMLOptionElement(GetNode())->Selected())
- ? kSelectedStateTrue
- : kSelectedStateFalse;
+ auto* option_element = DynamicTo<HTMLOptionElement>(GetNode());
+ return (option_element && option_element->Selected()) ? kSelectedStateTrue
+ : kSelectedStateFalse;
}
bool AXListBoxOption::IsSelectedOptionActive() const {
@@ -124,7 +123,7 @@ String AXListBoxOption::TextAlternative(bool recursive,
return text_alternative;
name_from = ax::mojom::NameFrom::kContents;
- text_alternative = ToHTMLOptionElement(GetNode())->DisplayLabel();
+ text_alternative = To<HTMLOptionElement>(GetNode())->DisplayLabel();
if (name_sources) {
name_sources->push_back(NameSource(found_text_alternative));
name_sources->back().type = name_from;
@@ -151,7 +150,7 @@ bool AXListBoxOption::OnNativeSetSelectedAction(bool selected) {
if ((is_selected && selected) || (!is_selected && !selected))
return false;
- select_element->SelectOptionByAccessKey(ToHTMLOptionElement(GetNode()));
+ select_element->SelectOptionByAccessKey(To<HTMLOptionElement>(GetNode()));
return true;
}
@@ -159,7 +158,7 @@ HTMLSelectElement* AXListBoxOption::ListBoxOptionParentNode() const {
if (!GetNode())
return nullptr;
- if (auto* option = ToHTMLOptionElementOrNull(GetNode()))
+ if (auto* option = DynamicTo<HTMLOptionElement>(GetNode()))
return option->OwnerSelectElement();
return nullptr;
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 93b3356564b..9ce8949afa4 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
@@ -4,14 +4,13 @@
#include "third_party/blink/renderer/modules/accessibility/ax_media_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
-using blink::WebLocalizedString;
-
AXObject* AccessibilityMediaElement::Create(
LayoutObject* layout_object,
AXObjectCacheImpl& ax_object_cache) {
@@ -35,8 +34,7 @@ String AccessibilityMediaElement::TextAlternative(
if (IsUnplayable()) {
HTMLMediaElement* element =
static_cast<HTMLMediaElement*>(layout_object_->GetNode());
- return element->GetLocale().QueryString(
- WebLocalizedString::kAXMediaPlaybackError);
+ return element->GetLocale().QueryString(IDS_MEDIA_PLAYBACK_ERROR);
}
return AXLayoutObject::TextAlternative(
recursive, in_aria_labelled_by_traversal, visited, name_from,
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 3113e675cb3..47d04bfc266 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
@@ -73,7 +73,7 @@ AXObject* AXMenuListOption::ComputeParent() const {
Node* node = GetNode();
if (!node)
return nullptr;
- HTMLSelectElement* select = ToHTMLOptionElement(node)->OwnerSelectElement();
+ auto* select = To<HTMLOptionElement>(node)->OwnerSelectElement();
if (!select)
return nullptr;
AXObject* select_ax_object = AXObjectCache().GetOrCreate(select);
@@ -212,7 +212,7 @@ HTMLSelectElement* AXMenuListOption::ParentSelectNode() const {
if (!GetNode())
return nullptr;
- if (auto* option = ToHTMLOptionElementOrNull(GetNode()))
+ if (auto* option = DynamicTo<HTMLOptionElement>(GetNode()))
return option->OwnerSelectElement();
return nullptr;
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 ce724fe7051..47a28a72ca4 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
@@ -59,7 +59,7 @@ bool AXMenuListPopup::ComputeAccessibilityIsIgnored(
AXMenuListOption* AXMenuListPopup::MenuListOptionAXObject(
HTMLElement* element) const {
DCHECK(element);
- if (!IsHTMLOptionElement(*element))
+ if (!IsA<HTMLOptionElement>(*element))
return nullptr;
AXObject* object = AXObjectCache().GetOrCreate(element);
@@ -73,11 +73,10 @@ int AXMenuListPopup::GetSelectedIndex() const {
if (!parent_)
return -1;
- Node* parent_node = parent_->GetNode();
- if (!IsHTMLSelectElement(parent_node))
+ auto* html_select_element = DynamicTo<HTMLSelectElement>(parent_->GetNode());
+ if (!html_select_element)
return -1;
- HTMLSelectElement* html_select_element = ToHTMLSelectElement(parent_node);
return html_select_element->selectedIndex();
}
@@ -93,11 +92,10 @@ void AXMenuListPopup::AddChildren() {
if (!parent_)
return;
- Node* parent_node = parent_->GetNode();
- if (!IsHTMLSelectElement(parent_node))
+ auto* html_select_element = DynamicTo<HTMLSelectElement>(parent_->GetNode());
+ if (!html_select_element)
return;
- HTMLSelectElement* html_select_element = ToHTMLSelectElement(parent_node);
have_children_ = true;
if (active_index_ == -1)
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 9e3755dcc67..5b2ea42c4c4 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,6 +30,7 @@
#include <math.h>
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -84,7 +85,10 @@
namespace blink {
-using namespace html_names;
+using html_names::kAltAttr;
+using html_names::kTitleAttr;
+using html_names::kTypeAttr;
+using html_names::kValueAttr;
// In ARIA 1.1, default value of aria-level was changed to 2.
const int kDefaultHeadingLevel = 2;
@@ -214,8 +218,8 @@ AXObjectInclusion AXNodeObject::ShouldIncludeBasedOnSemantics(
// Header and footer tags may also be exposed as landmark roles but not
// always.
- if (GetNode() &&
- (GetNode()->HasTagName(kHeaderTag) || GetNode()->HasTagName(kFooterTag)))
+ if (GetNode() && (GetNode()->HasTagName(html_names::kHeaderTag) ||
+ GetNode()->HasTagName(html_names::kFooterTag)))
return kIncludeObject;
// All controls are accessible.
@@ -382,7 +386,7 @@ bool AXNodeObject::ComputeAccessibilityIsIgnored(
}
static bool IsListElement(Node* node) {
- return IsHTMLUListElement(*node) || IsHTMLOListElement(*node) ||
+ return IsHTMLUListElement(*node) || IsA<HTMLOListElement>(*node) ||
IsA<HTMLDListElement>(*node);
}
@@ -456,16 +460,16 @@ const AXObject* AXNodeObject::InheritsPresentationalRoleFrom() const {
static HashSet<QualifiedName>& GetLandmarkRolesNotAllowed() {
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, landmark_roles_not_allowed, ());
if (landmark_roles_not_allowed.IsEmpty()) {
- landmark_roles_not_allowed.insert(kArticleTag);
- landmark_roles_not_allowed.insert(kAsideTag);
- landmark_roles_not_allowed.insert(kNavTag);
- landmark_roles_not_allowed.insert(kSectionTag);
- landmark_roles_not_allowed.insert(kBlockquoteTag);
- landmark_roles_not_allowed.insert(kDetailsTag);
- landmark_roles_not_allowed.insert(kFieldsetTag);
- landmark_roles_not_allowed.insert(kFigureTag);
- landmark_roles_not_allowed.insert(kTdTag);
- landmark_roles_not_allowed.insert(kMainTag);
+ landmark_roles_not_allowed.insert(html_names::kArticleTag);
+ landmark_roles_not_allowed.insert(html_names::kAsideTag);
+ landmark_roles_not_allowed.insert(html_names::kNavTag);
+ landmark_roles_not_allowed.insert(html_names::kSectionTag);
+ landmark_roles_not_allowed.insert(html_names::kBlockquoteTag);
+ landmark_roles_not_allowed.insert(html_names::kDetailsTag);
+ landmark_roles_not_allowed.insert(html_names::kFieldsetTag);
+ landmark_roles_not_allowed.insert(html_names::kFigureTag);
+ landmark_roles_not_allowed.insert(html_names::kTdTag);
+ landmark_roles_not_allowed.insert(html_names::kMainTag);
}
return landmark_roles_not_allowed;
}
@@ -515,7 +519,7 @@ ax::mojom::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsHTMLSummaryElement(*GetNode())) {
ContainerNode* parent = LayoutTreeBuilderTraversal::Parent(*GetNode());
- if (parent && IsHTMLSlotElement(parent))
+ if (IsA<HTMLSlotElement>(parent))
parent = LayoutTreeBuilderTraversal::Parent(*parent);
if (parent && IsA<HTMLDetailsElement>(parent))
return ax::mojom::Role::kDisclosureTriangle;
@@ -577,12 +581,12 @@ ax::mojom::Role AXNodeObject::NativeRoleIgnoringAria() const {
return ax::mojom::Role::kTextField;
}
- if (auto* select_element = ToHTMLSelectElementOrNull(*GetNode())) {
+ if (auto* select_element = DynamicTo<HTMLSelectElement>(*GetNode())) {
return select_element->IsMultiple() ? ax::mojom::Role::kListBox
: ax::mojom::Role::kPopUpButton;
}
- if (auto* option = ToHTMLOptionElementOrNull(*GetNode())) {
+ if (auto* option = DynamicTo<HTMLOptionElement>(*GetNode())) {
HTMLSelectElement* select_element = option->OwnerSelectElement();
return !select_element || select_element->IsMultiple()
? ax::mojom::Role::kListBoxOption
@@ -598,16 +602,16 @@ ax::mojom::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsHTMLDivElement(*GetNode()))
return ax::mojom::Role::kGenericContainer;
- if (IsHTMLMeterElement(*GetNode()))
+ if (IsA<HTMLMeterElement>(*GetNode()))
return ax::mojom::Role::kMeter;
- if (IsHTMLProgressElement(*GetNode()))
+ if (IsA<HTMLProgressElement>(*GetNode()))
return ax::mojom::Role::kProgressIndicator;
- if (IsHTMLOutputElement(*GetNode()))
+ if (IsA<HTMLOutputElement>(*GetNode()))
return ax::mojom::Role::kStatus;
- if (IsHTMLParagraphElement(*GetNode()))
+ if (IsA<HTMLParagraphElement>(*GetNode()))
return ax::mojom::Role::kParagraph;
if (IsA<HTMLLabelElement>(*GetNode()))
@@ -627,52 +631,53 @@ ax::mojom::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsHTMLVideoElement(*GetNode()))
return ax::mojom::Role::kVideo;
- if (GetNode()->HasTagName(kDdTag))
+ if (GetNode()->HasTagName(html_names::kDdTag))
return ax::mojom::Role::kDescriptionListDetail;
- if (GetNode()->HasTagName(kDtTag))
+ if (GetNode()->HasTagName(html_names::kDtTag))
return ax::mojom::Role::kDescriptionListTerm;
if (GetNode()->nodeName() == "math")
return ax::mojom::Role::kMath;
- if (GetNode()->HasTagName(kRpTag) || GetNode()->HasTagName(kRtTag))
- return ax::mojom::Role::kAnnotation;
+ if (GetNode()->HasTagName(html_names::kRpTag) ||
+ GetNode()->HasTagName(html_names::kRtTag))
+ return ax::mojom::Role::kRubyAnnotation;
if (IsHTMLFormElement(*GetNode()))
return ax::mojom::Role::kForm;
- if (GetNode()->HasTagName(kAbbrTag))
+ if (GetNode()->HasTagName(html_names::kAbbrTag))
return ax::mojom::Role::kAbbr;
- if (GetNode()->HasTagName(kArticleTag))
+ if (GetNode()->HasTagName(html_names::kArticleTag))
return ax::mojom::Role::kArticle;
- if (GetNode()->HasTagName(kDelTag))
+ if (GetNode()->HasTagName(html_names::kDelTag))
return ax::mojom::Role::kContentDeletion;
- if (GetNode()->HasTagName(kInsTag))
+ if (GetNode()->HasTagName(html_names::kInsTag))
return ax::mojom::Role::kContentInsertion;
- if (GetNode()->HasTagName(kMainTag))
+ if (GetNode()->HasTagName(html_names::kMainTag))
return ax::mojom::Role::kMain;
- if (GetNode()->HasTagName(kMarkTag))
+ if (GetNode()->HasTagName(html_names::kMarkTag))
return ax::mojom::Role::kMark;
- if (GetNode()->HasTagName(kNavTag))
+ if (GetNode()->HasTagName(html_names::kNavTag))
return ax::mojom::Role::kNavigation;
- if (GetNode()->HasTagName(kAsideTag))
+ if (GetNode()->HasTagName(html_names::kAsideTag))
return ax::mojom::Role::kComplementary;
- if (GetNode()->HasTagName(kPreTag))
+ if (GetNode()->HasTagName(html_names::kPreTag))
return ax::mojom::Role::kPre;
- if (GetNode()->HasTagName(kSectionTag))
- return ax::mojom::Role::kRegion;
+ if (GetNode()->HasTagName(html_names::kSectionTag))
+ return ax::mojom::Role::kSection;
- if (GetNode()->HasTagName(kAddressTag))
+ if (GetNode()->HasTagName(html_names::kAddressTag))
return ax::mojom::Role::kGenericContainer;
if (IsA<HTMLDialogElement>(*GetNode()))
@@ -695,28 +700,28 @@ ax::mojom::Role AXNodeObject::NativeRoleIgnoringAria() const {
// There should only be one banner/contentInfo per page. If header/footer are
// being used within an article or section then it should not be exposed as
// whole page's banner/contentInfo but as a generic container role.
- if (GetNode()->HasTagName(kHeaderTag)) {
+ if (GetNode()->HasTagName(html_names::kHeaderTag)) {
if (IsDescendantOfElementType(GetLandmarkRolesNotAllowed()))
- return ax::mojom::Role::kGenericContainer;
- return ax::mojom::Role::kBanner;
+ return ax::mojom::Role::kHeaderAsNonLandmark;
+ return ax::mojom::Role::kHeader;
}
- if (GetNode()->HasTagName(kFooterTag)) {
+ if (GetNode()->HasTagName(html_names::kFooterTag)) {
if (IsDescendantOfElementType(GetLandmarkRolesNotAllowed()))
- return ax::mojom::Role::kGenericContainer;
+ return ax::mojom::Role::kFooterAsNonLandmark;
return ax::mojom::Role::kFooter;
}
- if (GetNode()->HasTagName(kBlockquoteTag))
+ if (GetNode()->HasTagName(html_names::kBlockquoteTag))
return ax::mojom::Role::kBlockquote;
- if (GetNode()->HasTagName(kCaptionTag))
+ if (GetNode()->HasTagName(html_names::kCaptionTag))
return ax::mojom::Role::kCaption;
- if (GetNode()->HasTagName(kFigcaptionTag))
+ if (GetNode()->HasTagName(html_names::kFigcaptionTag))
return ax::mojom::Role::kFigcaption;
- if (GetNode()->HasTagName(kFigureTag))
+ if (GetNode()->HasTagName(html_names::kFigureTag))
return ax::mojom::Role::kFigure;
if (GetNode()->nodeName() == "TIME")
@@ -806,7 +811,7 @@ bool AXNodeObject::IsMultiline() const {
// also return true if an ancestor is editable.
bool AXNodeObject::HasContentEditableAttributeSet() const {
const AtomicString& content_editable_value =
- GetAttribute(kContenteditableAttr);
+ GetAttribute(html_names::kContenteditableAttr);
if (content_editable_value.IsNull())
return false;
// Both "true" (case-insensitive) and the empty string count as true.
@@ -1057,8 +1062,8 @@ bool AXNodeObject::IsMultiSelectable() const {
break;
}
- return IsHTMLSelectElement(GetNode()) &&
- ToHTMLSelectElement(*GetNode()).IsMultiple();
+ auto* html_select_element = DynamicTo<HTMLSelectElement>(GetNode());
+ return html_select_element && html_select_element->IsMultiple();
}
bool AXNodeObject::IsNativeCheckboxOrRadio() const {
@@ -1189,7 +1194,7 @@ AXRestriction AXNodeObject::Restriction() const {
return kRestrictionNone;
// An <optgroup> is not exposed directly in the AX tree.
- if (IsHTMLOptGroupElement(elem))
+ if (IsA<HTMLOptGroupElement>(elem))
return kRestrictionNone;
// According to ARIA, all elements of the base markup can be disabled.
@@ -1251,7 +1256,8 @@ AccessibilityExpanded AXNodeObject::IsExpanded() const {
if (GetNode() && IsHTMLSummaryElement(*GetNode())) {
if (GetNode()->parentNode() &&
IsA<HTMLDetailsElement>(GetNode()->parentNode()))
- return To<Element>(GetNode()->parentNode())->hasAttribute(kOpenAttr)
+ return To<Element>(GetNode()->parentNode())
+ ->hasAttribute(html_names::kOpenAttr)
? kExpandedExpanded
: kExpandedCollapsed;
}
@@ -1315,22 +1321,22 @@ int AXNodeObject::HeadingLevel() const {
if (!element)
return 0;
- if (element->HasTagName(kH1Tag))
+ if (element->HasTagName(html_names::kH1Tag))
return 1;
- if (element->HasTagName(kH2Tag))
+ if (element->HasTagName(html_names::kH2Tag))
return 2;
- if (element->HasTagName(kH3Tag))
+ if (element->HasTagName(html_names::kH3Tag))
return 3;
- if (element->HasTagName(kH4Tag))
+ if (element->HasTagName(html_names::kH4Tag))
return 4;
- if (element->HasTagName(kH5Tag))
+ if (element->HasTagName(html_names::kH5Tag))
return 5;
- if (element->HasTagName(kH6Tag))
+ if (element->HasTagName(html_names::kH6Tag))
return 6;
if (RoleValue() == ax::mojom::Role::kHeading)
@@ -1369,8 +1375,12 @@ unsigned AXNodeObject::HierarchicalLevel() const {
return level;
}
-// TODO: rename this just AutoComplete, it's not only ARIA.
-String AXNodeObject::AriaAutoComplete() const {
+String AXNodeObject::AutoComplete() const {
+ // Check cache for auto complete state.
+ if (AXObjectCache().GetAutofillState(AXObjectID()) ==
+ WebAXAutofillState::kAutocompleteAvailable)
+ return "list";
+
if (IsNativeTextControl() || IsARIATextControl()) {
const AtomicString& aria_auto_complete =
GetAOMPropertyOrARIAAttribute(AOMStringProperty::kAutocomplete)
@@ -1395,7 +1405,7 @@ bool MarkerTypeIsUsedForAccessibility(DocumentMarker::MarkerType type) {
return DocumentMarker::MarkerTypes(
DocumentMarker::kSpelling | DocumentMarker::kGrammar |
DocumentMarker::kTextMatch | DocumentMarker::kActiveSuggestion |
- DocumentMarker::kSuggestion)
+ DocumentMarker::kSuggestion | DocumentMarker::kTextFragment)
.Contains(type);
}
@@ -1727,7 +1737,7 @@ bool AXNodeObject::ValueForRange(float* out_value) const {
return std::isfinite(*out_value);
}
- if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+ if (auto* meter = DynamicTo<HTMLMeterElement>(GetNode())) {
*out_value = meter->value();
return true;
}
@@ -1773,7 +1783,7 @@ bool AXNodeObject::MaxValueForRange(float* out_value) const {
return std::isfinite(*out_value);
}
- if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+ if (auto* meter = DynamicTo<HTMLMeterElement>(GetNode())) {
*out_value = meter->max();
return true;
}
@@ -1806,7 +1816,7 @@ bool AXNodeObject::MinValueForRange(float* out_value) const {
return std::isfinite(*out_value);
}
- if (auto* meter = ToHTMLMeterElementOrNull(GetNode())) {
+ if (auto* meter = DynamicTo<HTMLMeterElement>(GetNode())) {
*out_value = meter->min();
return true;
}
@@ -1904,14 +1914,15 @@ String AXNodeObject::StringValue() const {
if (!node)
return String();
- if (auto* select_element = ToHTMLSelectElementOrNull(*node)) {
+ if (auto* select_element = DynamicTo<HTMLSelectElement>(*node)) {
int selected_index = select_element->selectedIndex();
const HeapVector<Member<HTMLElement>>& list_items =
select_element->GetListItems();
if (selected_index >= 0 &&
static_cast<wtf_size_t>(selected_index) < list_items.size()) {
const AtomicString& overridden_description =
- list_items[selected_index]->FastGetAttribute(kAriaLabelAttr);
+ list_items[selected_index]->FastGetAttribute(
+ html_names::kAriaLabelAttr);
if (!overridden_description.IsNull())
return overridden_description;
}
@@ -2060,7 +2071,7 @@ String AXNodeObject::TextAlternative(bool recursive,
// Step 2F / 2G from: http://www.w3.org/TR/accname-aam-1.1
if (in_aria_labelled_by_traversal || NameFromContents(recursive)) {
Node* node = GetNode();
- if (!IsHTMLSelectElement(node)) { // Avoid option descendant text
+ if (!IsA<HTMLSelectElement>(node)) { // Avoid option descendant text
name_from = ax::mojom::NameFrom::kContents;
if (name_sources) {
name_sources->push_back(NameSource(found_text_alternative));
@@ -2673,7 +2684,7 @@ bool AXNodeObject::OnNativeFocusAction() {
// using AOM. To be extra safe, exclude objects that are clickable themselves.
// This won't prevent anyone from having a click handler on the object's
// container.
- if (!IsClickable() && element->FastHasAttribute(kIdAttr) &&
+ if (!IsClickable() && element->FastHasAttribute(html_names::kIdAttr) &&
CanBeActiveDescendant()) {
return OnNativeClickAction();
}
@@ -2784,8 +2795,7 @@ void AXNodeObject::UpdateChildrenIfNecessary() {
}
void AXNodeObject::SelectedOptions(AXObjectVector& options) const {
- if (IsHTMLSelectElement(GetNode())) {
- HTMLSelectElement* select = ToHTMLSelectElement(GetNode());
+ if (auto* select = DynamicTo<HTMLSelectElement>(GetNode())) {
for (auto* const option : *select->selectedOptions()) {
AXObject* ax_option = AXObjectCache().GetOrCreate(option);
if (ax_option)
@@ -2877,11 +2887,11 @@ void AXNodeObject::ComputeAriaOwnsChildren(
return;
}
- if (!HasAttribute(kAriaOwnsAttr))
+ if (!HasAttribute(html_names::kAriaOwnsAttr))
return;
// Case 2: aria-owns attribute
- TokenVectorFromAttribute(id_vector, kAriaOwnsAttr);
+ TokenVectorFromAttribute(id_vector, html_names::kAriaOwnsAttr);
AXObjectCache().UpdateAriaOwns(this, id_vector, owned_children);
}
@@ -2926,8 +2936,9 @@ String AXNodeObject::NativeTextAlternative(
++label_index) {
Element* label = labels->item(label_index);
if (name_sources) {
- if (!label->getAttribute(kForAttr).IsEmpty() &&
- label->getAttribute(kForAttr) == html_element->GetIdAttribute()) {
+ if (!label->getAttribute(html_names::kForAttr).IsEmpty() &&
+ label->getAttribute(html_names::kForAttr) ==
+ html_element->GetIdAttribute()) {
name_sources->back().native_source = kAXTextFromNativeHTMLLabelFor;
} else {
name_sources->back().native_source =
@@ -3061,8 +3072,8 @@ String AXNodeObject::NativeTextAlternative(
// localised default value ("Submit")
name_from = ax::mojom::NameFrom::kValue;
- text_alternative = input_element->GetLocale().QueryString(
- WebLocalizedString::kSubmitButtonDefaultLabel);
+ text_alternative =
+ input_element->GetLocale().QueryString(IDS_FORM_SUBMIT_LABEL);
if (name_sources) {
name_sources->push_back(NameSource(*found_text_alternative, kTypeAttr));
NameSource& source = name_sources->back();
@@ -3081,7 +3092,7 @@ String AXNodeObject::NativeTextAlternative(
name_from = ax::mojom::NameFrom::kPlaceholder;
if (name_sources) {
name_sources->push_back(
- NameSource(*found_text_alternative, kPlaceholderAttr));
+ NameSource(*found_text_alternative, html_names::kPlaceholderAttr));
NameSource& source = name_sources->back();
source.type = name_from;
}
@@ -3092,7 +3103,7 @@ String AXNodeObject::NativeTextAlternative(
NameSource& source = name_sources->back();
source.text = text_alternative;
source.attribute_value =
- html_element->FastGetAttribute(kPlaceholderAttr);
+ html_element->FastGetAttribute(html_names::kPlaceholderAttr);
*found_text_alternative = true;
} else {
return text_alternative;
@@ -3104,8 +3115,8 @@ String AXNodeObject::NativeTextAlternative(
if (IsTextControl()) {
name_from = ax::mojom::NameFrom::kPlaceholder;
if (name_sources) {
- name_sources->push_back(
- NameSource(*found_text_alternative, kAriaPlaceholderAttr));
+ name_sources->push_back(NameSource(*found_text_alternative,
+ html_names::kAriaPlaceholderAttr));
NameSource& source = name_sources->back();
source.type = name_from;
}
@@ -3127,7 +3138,7 @@ String AXNodeObject::NativeTextAlternative(
}
// 5.7 figure and figcaption Elements
- if (GetNode()->HasTagName(kFigureTag)) {
+ if (GetNode()->HasTagName(html_names::kFigureTag)) {
// figcaption
name_from = ax::mojom::NameFrom::kRelatedElement;
if (name_sources) {
@@ -3137,7 +3148,7 @@ String AXNodeObject::NativeTextAlternative(
}
Element* figcaption = nullptr;
for (Element& element : ElementTraversal::DescendantsOf(*(GetNode()))) {
- if (element.HasTagName(kFigcaptionTag)) {
+ if (element.HasTagName(html_names::kFigcaptionTag)) {
figcaption = &element;
break;
}
@@ -3233,10 +3244,10 @@ String AXNodeObject::NativeTextAlternative(
name_from = ax::mojom::NameFrom::kAttribute;
if (name_sources) {
name_sources->push_back(
- NameSource(*found_text_alternative, kSummaryAttr));
+ NameSource(*found_text_alternative, html_names::kSummaryAttr));
name_sources->back().type = name_from;
}
- const AtomicString& summary = GetAttribute(kSummaryAttr);
+ const AtomicString& summary = GetAttribute(html_names::kSummaryAttr);
if (!summary.IsNull()) {
text_alternative = summary;
if (name_sources) {
@@ -3332,7 +3343,7 @@ String AXNodeObject::NativeTextAlternative(
name_from = ax::mojom::NameFrom::kAttribute;
if (name_sources) {
name_sources->push_back(
- NameSource(found_text_alternative, kAriaLabelAttr));
+ NameSource(found_text_alternative, html_names::kAriaLabelAttr));
name_sources->back().type = name_from;
}
if (Element* document_element = document->documentElement()) {
@@ -3440,13 +3451,14 @@ String AXNodeObject::Description(ax::mojom::NameFrom name_from,
description_from = ax::mojom::DescriptionFrom::kRelatedElement;
if (description_sources) {
description_sources->push_back(
- DescriptionSource(found_description, kAriaDescribedbyAttr));
+ DescriptionSource(found_description, html_names::kAriaDescribedbyAttr));
description_sources->back().type = description_from;
}
// aria-describedby overrides any other accessible description, from:
// http://rawgit.com/w3c/aria/master/html-aam/html-aam.html
- const AtomicString& aria_describedby = GetAttribute(kAriaDescribedbyAttr);
+ const AtomicString& aria_describedby =
+ GetAttribute(html_names::kAriaDescribedbyAttr);
if (!aria_describedby.IsNull()) {
if (description_sources)
description_sources->back().attribute_value = aria_describedby;
@@ -3582,10 +3594,10 @@ String AXNodeObject::Description(ax::mojom::NameFrom name_from,
description_from = ax::mojom::DescriptionFrom::kAttribute;
if (description_sources) {
description_sources->push_back(
- DescriptionSource(found_description, kAriaHelpAttr));
+ DescriptionSource(found_description, html_names::kAriaHelpAttr));
description_sources->back().type = description_from;
}
- const AtomicString& help = GetAttribute(kAriaHelpAttr);
+ const AtomicString& help = GetAttribute(html_names::kAriaHelpAttr);
if (!help.IsEmpty()) {
description = help;
if (description_sources) {
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 814ede0ef39..2140d86db54 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
@@ -64,7 +64,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
void AlterSliderOrSpinButtonValue(bool increase);
AXObject* ActiveDescendant() override;
String AriaAccessibilityDescription() const;
- String AriaAutoComplete() const override;
+ String AutoComplete() const override;
void AccessibilityChildrenFromAOMProperty(AOMRelationListProperty,
AXObject::AXObjectVector&) const;
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 1bc953837a6..6be853a7529 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
@@ -55,7 +56,9 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/ax_range.h"
#include "third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h"
+#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/language.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -63,12 +66,8 @@
#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
#include "third_party/skia/include/core/SkMatrix44.h"
-using blink::WebLocalizedString;
-
namespace blink {
-using namespace html_names;
-
namespace {
struct RoleHashTraits : HashTraits<ax::mojom::Role> {
@@ -91,6 +90,11 @@ struct RoleEntry {
const RoleEntry kRoles[] = {
{"alert", ax::mojom::Role::kAlert},
{"alertdialog", ax::mojom::Role::kAlertDialog},
+ {"annotation-attribution", ax::mojom::Role::kAnnotationAttribution},
+ {"annotation-commentary", ax::mojom::Role::kAnnotationCommentary},
+ {"annotation-presence", ax::mojom::Role::kAnnotationPresence},
+ {"annotation-revision", ax::mojom::Role::kAnnotationRevision},
+ {"annotation-suggestion", ax::mojom::Role::kAnnotationSuggestion},
{"application", ax::mojom::Role::kApplication},
{"article", ax::mojom::Role::kArticle},
{"banner", ax::mojom::Role::kBanner},
@@ -230,7 +234,11 @@ const InternalRoleEntry kInternalRoles[] = {
{ax::mojom::Role::kAlertDialog, "AlertDialog"},
{ax::mojom::Role::kAlert, "Alert"},
{ax::mojom::Role::kAnchor, "Anchor"},
- {ax::mojom::Role::kAnnotation, "Annotation"},
+ {ax::mojom::Role::kAnnotationAttribution, "kAnnotationAttribution"},
+ {ax::mojom::Role::kAnnotationCommentary, "AnnotationCommentary"},
+ {ax::mojom::Role::kAnnotationPresence, "AnnotationPresence"},
+ {ax::mojom::Role::kAnnotationRevision, "AnnotationRevision"},
+ {ax::mojom::Role::kAnnotationSuggestion, "AnnotationSuggestion"},
{ax::mojom::Role::kApplication, "Application"},
{ax::mojom::Role::kArticle, "Article"},
{ax::mojom::Role::kAudio, "Audio"},
@@ -313,6 +321,7 @@ const InternalRoleEntry kInternalRoles[] = {
{ax::mojom::Role::kFigcaption, "Figcaption"},
{ax::mojom::Role::kFigure, "Figure"},
{ax::mojom::Role::kFooter, "Footer"},
+ {ax::mojom::Role::kFooterAsNonLandmark, "FooterAsNonLandmark"},
{ax::mojom::Role::kForm, "Form"},
{ax::mojom::Role::kGenericContainer, "GenericContainer"},
// --------------------------------------------------------------
@@ -325,6 +334,8 @@ const InternalRoleEntry kInternalRoles[] = {
// --------------------------------------------------------------
{ax::mojom::Role::kGrid, "Grid"},
{ax::mojom::Role::kGroup, "Group"},
+ {ax::mojom::Role::kHeader, "Header"},
+ {ax::mojom::Role::kHeaderAsNonLandmark, "HeaderAsNonLandmark"},
{ax::mojom::Role::kHeading, "Heading"},
{ax::mojom::Role::kIframePresentational, "IframePresentational"},
{ax::mojom::Role::kIframe, "Iframe"},
@@ -377,6 +388,8 @@ const InternalRoleEntry kInternalRoles[] = {
{ax::mojom::Role::kRowHeader, "RowHeader"},
{ax::mojom::Role::kRow, "Row"},
{ax::mojom::Role::kRuby, "Ruby"},
+ {ax::mojom::Role::kRubyAnnotation, "RubyAnnotation"},
+ {ax::mojom::Role::kSection, "Section"},
{ax::mojom::Role::kSvgRoot, "SVGRoot"},
{ax::mojom::Role::kScrollBar, "ScrollBar"},
{ax::mojom::Role::kScrollView, "ScrollView"},
@@ -418,12 +431,14 @@ static_assert(base::size(kInternalRoles) ==
// Roles which we need to map in the other direction
const RoleEntry kReverseRoles[] = {
+ {"banner", ax::mojom::Role::kHeader},
{"button", ax::mojom::Role::kToggleButton},
{"combobox", ax::mojom::Role::kPopUpButton},
{"contentinfo", ax::mojom::Role::kFooter},
{"menuitem", ax::mojom::Role::kMenuButton},
{"menuitem", ax::mojom::Role::kMenuListOption},
{"progressbar", ax::mojom::Role::kMeter},
+ {"region", ax::mojom::Role::kSection},
{"textbox", ax::mojom::Role::kTextField},
{"combobox", ax::mojom::Role::kComboBoxMenuButton},
{"combobox", ax::mojom::Role::kTextFieldWithComboBox}};
@@ -808,10 +823,12 @@ bool AXObject::IsLandmarkRelated() const {
case ax::mojom::Role::kDocToc:
case ax::mojom::Role::kFooter:
case ax::mojom::Role::kForm:
+ case ax::mojom::Role::kHeader:
case ax::mojom::Role::kMain:
case ax::mojom::Role::kNavigation:
case ax::mojom::Role::kRegion:
case ax::mojom::Role::kSearch:
+ case ax::mojom::Role::kSection:
return true;
default:
return false;
@@ -1081,7 +1098,7 @@ const AXObject* AXObject::InertRoot() const {
element = FlatTreeTraversal::ParentElement(*node);
while (element) {
- if (element->hasAttribute(kInertAttr))
+ if (element->hasAttribute(html_names::kInertAttr))
return AXObjectCache().GetOrCreate(element);
element = FlatTreeTraversal::ParentElement(*element);
}
@@ -1195,11 +1212,6 @@ bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const {
if (!GetNode())
return false;
- // Disallow inert nodes from the tree to ensure the dialog is always the
- // first child of the root.
- if (GetNode()->IsInert())
- return false;
-
// If the node is part of the user agent shadow dom, or has the explicit
// internal Role::kIgnored, they aren't interesting for paragraph navigation
// or LabelledBy/DescribedBy relationships.
@@ -1213,16 +1225,29 @@ bool AXObject::ComputeAccessibilityIsIgnoredButIncludedInTree() const {
if (IsLineBreakingObject())
return true;
- // Allow the browser side ax tree to access aria-hidden="true", "visibility:
- // hidden", and "visibility: collapse" nodes. This is useful for APIs that
- // return the node referenced by aria-labeledby and aria-describedby
- if (GetLayoutObject()) {
+ // Allow the browser side ax tree to access "visibility: [hidden|collapse]"
+ // and "display: none" nodes. This is useful for APIs that return the node
+ // referenced by aria-labeledby and aria-describedby.
+ // An element must have an id attribute or it cannot be referenced by
+ // aria-labelledby or aria-describedby.
+ if (RuntimeEnabledFeatures::AccessibilityExposeDisplayNoneEnabled()) {
+ if (Element* element = GetElement()) {
+ if (element->FastHasAttribute(html_names::kIdAttr) &&
+ IsHiddenForTextAlternativeCalculation()) {
+ return true;
+ }
+ }
+ } else if (GetLayoutObject()) {
if (GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible)
return true;
- if (AriaHiddenRoot())
- return true;
}
+ // Allow the browser side ax tree to access "aria-hidden" nodes.
+ // This is useful for APIs that return the node referenced by
+ // aria-labeledby and aria-describedby.
+ if (GetLayoutObject() && AriaHiddenRoot())
+ return true;
+
return false;
}
@@ -1291,7 +1316,7 @@ bool AXObject::CanReceiveAccessibilityFocus() const {
return true;
// aria-activedescendant focus
- return elem->FastHasAttribute(kIdAttr) && CanBeActiveDescendant();
+ return elem->FastHasAttribute(html_names::kIdAttr) && CanBeActiveDescendant();
}
bool AXObject::CanSetValueAttribute() const {
@@ -1536,6 +1561,9 @@ String AXObject::GetName(ax::mojom::NameFrom& name_from,
bool hidden_and_ignored_but_included_in_tree =
IsHiddenForTextAlternativeCalculation() &&
AccessibilityIsIgnoredButIncludedInTree();
+ // Initialize |name_from|, as TextAlternative() might never set it in some
+ // cases.
+ name_from = ax::mojom::NameFrom::kNone;
String text = TextAlternative(false, hidden_and_ignored_but_included_in_tree,
visited, name_from, &related_objects, nullptr);
@@ -1610,8 +1638,7 @@ bool AXObject::IsHiddenForTextAlternativeCalculation() const {
if (Node* node = GetNode()) {
auto* element = DynamicTo<Element>(node);
if (element && node->isConnected()) {
- scoped_refptr<ComputedStyle> style =
- document->EnsureStyleResolver().StyleForElement(element);
+ const ComputedStyle* style = element->EnsureComputedStyle();
return style->Display() == EDisplay::kNone ||
style->Visibility() != EVisibility::kVisible;
}
@@ -1645,9 +1672,10 @@ String AXObject::AriaTextAlternative(bool recursive,
// Check ARIA attributes.
const QualifiedName& attr =
- HasAttribute(kAriaLabeledbyAttr) && !HasAttribute(kAriaLabelledbyAttr)
- ? kAriaLabeledbyAttr
- : kAriaLabelledbyAttr;
+ HasAttribute(html_names::kAriaLabeledbyAttr) &&
+ !HasAttribute(html_names::kAriaLabelledbyAttr)
+ ? html_names::kAriaLabeledbyAttr
+ : html_names::kAriaLabelledbyAttr;
if (name_sources) {
name_sources->push_back(NameSource(*found_text_alternative, attr));
@@ -1690,7 +1718,7 @@ String AXObject::AriaTextAlternative(bool recursive,
name_from = ax::mojom::NameFrom::kAttribute;
if (name_sources) {
name_sources->push_back(
- NameSource(*found_text_alternative, kAriaLabelAttr));
+ NameSource(*found_text_alternative, html_names::kAriaLabelAttr));
name_sources->back().type = name_from;
}
const AtomicString& aria_label =
@@ -1777,9 +1805,9 @@ void AXObject::AriaLabelledbyElementVector(
HeapVector<Member<Element>>& elements,
Vector<String>& ids) const {
// Try both spellings, but prefer aria-labelledby, which is the official spec.
- ElementsFromAttribute(elements, kAriaLabelledbyAttr, ids);
+ ElementsFromAttribute(elements, html_names::kAriaLabelledbyAttr, ids);
if (!ids.size())
- ElementsFromAttribute(elements, kAriaLabeledbyAttr, ids);
+ ElementsFromAttribute(elements, html_names::kAriaLabeledbyAttr, ids);
}
String AXObject::TextFromAriaLabelledby(AXObjectSet& visited,
@@ -1794,7 +1822,7 @@ String AXObject::TextFromAriaDescribedby(AXRelatedObjectVector* related_objects,
Vector<String>& ids) const {
AXObjectSet visited;
HeapVector<Member<Element>> elements;
- ElementsFromAttribute(elements, kAriaDescribedbyAttr, ids);
+ ElementsFromAttribute(elements, html_names::kAriaDescribedbyAttr, ids);
return TextFromElements(true, visited, elements, related_objects);
}
@@ -2043,6 +2071,22 @@ ax::mojom::Role AXObject::DetermineAriaRoleAttribute() const {
ax::mojom::Role role = AriaRoleToWebCoreRole(aria_role);
+ switch (role) {
+ case ax::mojom::Role::kAnnotationAttribution:
+ case ax::mojom::Role::kAnnotationCommentary:
+ case ax::mojom::Role::kAnnotationPresence:
+ case ax::mojom::Role::kAnnotationRevision:
+ case ax::mojom::Role::kAnnotationSuggestion:
+ UseCounter::Count(GetDocument(), WebFeature::kARIAAnnotationRoles);
+ if (!RuntimeEnabledFeatures::
+ AccessibilityExposeARIAAnnotationsEnabled()) {
+ role = ax::mojom::Role::kGenericContainer;
+ }
+ break;
+ default:
+ break;
+ }
+
// ARIA states if an item can get focus, it should not be presentational.
// It also states user agents should ignore the presentational role if
// the element has global ARIA states and properties.
@@ -2516,8 +2560,10 @@ void AXObject::UpdateChildrenIfNecessary() {
void AXObject::ClearChildren() {
// Detach all weak pointers from objects to their parents.
- for (const auto& child : children_)
- child->DetachFromParent();
+ for (const auto& child : children_) {
+ if (child->parent_ == this)
+ child->DetachFromParent();
+ }
children_.clear();
have_children_ = false;
@@ -2568,7 +2614,7 @@ AtomicString AXObject::Language() const {
// 2. The list of languages the browser sends in the [Accept-Language] header.
// 3. The browser's default language.
- const AtomicString& lang = GetAttribute(kLangAttr);
+ const AtomicString& lang = GetAttribute(html_names::kLangAttr);
if (!lang.IsEmpty())
return lang;
@@ -3161,8 +3207,10 @@ bool AXObject::OnNativeScrollToMakeVisibleAction() const {
if (!node)
return false;
if (Element* locked_ancestor =
- DisplayLockUtilities::NearestLockedInclusiveAncestor(*node))
- locked_ancestor->ActivateDisplayLockIfNeeded();
+ DisplayLockUtilities::NearestLockedInclusiveAncestor(*node)) {
+ locked_ancestor->ActivateDisplayLockIfNeeded(
+ DisplayLockActivationReason::kUser);
+ }
LayoutObject* layout_object = node->GetLayoutObject();
if (!layout_object || !node->isConnected())
return false;
@@ -3314,7 +3362,7 @@ bool AXObject::NameFromSelectedOption(bool recursive) const {
// This can be either a button widget with a non-false value of
// aria-haspopup or a select element with size of 1.
case ax::mojom::Role::kPopUpButton:
- return ToHTMLSelectElementOrNull(*GetNode()) ? recursive : false;
+ return DynamicTo<HTMLSelectElement>(*GetNode()) ? recursive : false;
default:
return false;
}
@@ -3365,6 +3413,11 @@ bool AXObject::NameFromContents(bool recursive) const {
// containers for many subobjects. Superset of nameFrom:author ARIA roles.
case ax::mojom::Role::kAlert:
case ax::mojom::Role::kAlertDialog:
+ case ax::mojom::Role::kAnnotationAttribution:
+ case ax::mojom::Role::kAnnotationCommentary:
+ case ax::mojom::Role::kAnnotationPresence:
+ case ax::mojom::Role::kAnnotationRevision:
+ case ax::mojom::Role::kAnnotationSuggestion:
case ax::mojom::Role::kApplication:
case ax::mojom::Role::kAudio:
case ax::mojom::Role::kArticle:
@@ -3428,6 +3481,7 @@ bool AXObject::NameFromContents(bool recursive) const {
case ax::mojom::Role::kGraphicsSymbol:
case ax::mojom::Role::kGrid:
case ax::mojom::Role::kGroup:
+ case ax::mojom::Role::kHeader:
case ax::mojom::Role::kIframePresentational:
case ax::mojom::Role::kIframe:
case ax::mojom::Role::kImage:
@@ -3482,7 +3536,6 @@ bool AXObject::NameFromContents(bool recursive) const {
// Some objects can contribute their contents to ancestor names, but
// only have their own name if they are focusable
case ax::mojom::Role::kAbbr:
- case ax::mojom::Role::kAnnotation:
case ax::mojom::Role::kCanvas:
case ax::mojom::Role::kCaption:
case ax::mojom::Role::kContentDeletion:
@@ -3493,7 +3546,9 @@ bool AXObject::NameFromContents(bool recursive) const {
case ax::mojom::Role::kDetails:
case ax::mojom::Role::kFigcaption:
case ax::mojom::Role::kFooter:
+ case ax::mojom::Role::kFooterAsNonLandmark:
case ax::mojom::Role::kGenericContainer:
+ case ax::mojom::Role::kHeaderAsNonLandmark:
case ax::mojom::Role::kIgnored:
case ax::mojom::Role::kImageMap:
case ax::mojom::Role::kInlineTextBox:
@@ -3516,6 +3571,8 @@ bool AXObject::NameFromContents(bool recursive) const {
// if the row might receive focus
case ax::mojom::Role::kRow:
case ax::mojom::Role::kRuby:
+ case ax::mojom::Role::kRubyAnnotation:
+ case ax::mojom::Role::kSection:
result = recursive || (CanReceiveAccessibilityFocus() && !IsEditable());
break;
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 129600f6d87..fc0cb6b3231 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -35,6 +35,7 @@
#include <ostream>
#include "base/macros.h"
+#include "third_party/blink/public/web/web_ax_enums.h"
#include "third_party/blink/renderer/core/accessibility/axid.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
@@ -101,8 +102,8 @@ class IgnoredReason {
void Trace(blink::Visitor* visitor) { visitor->Trace(related_object); }
};
-class NameSourceRelatedObject
- : public GarbageCollectedFinalized<NameSourceRelatedObject> {
+class NameSourceRelatedObject final
+ : public GarbageCollected<NameSourceRelatedObject> {
public:
WeakMember<AXObject> object;
String text;
@@ -168,14 +169,14 @@ WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::DescriptionSource)
namespace blink {
-class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
+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 ignored objects in the traversal.
class MODULES_EXPORT InOrderTraversalIterator final
- : public GarbageCollectedFinalized<InOrderTraversalIterator> {
+ : public GarbageCollected<InOrderTraversalIterator> {
public:
~InOrderTraversalIterator() = default;
@@ -266,7 +267,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
// Walks through all the unignored parents of the object up to the root.
// Does not include the object itself in the list of ancestors.
class MODULES_EXPORT AncestorsIterator final
- : public GarbageCollectedFinalized<AncestorsIterator> {
+ : public GarbageCollected<AncestorsIterator> {
public:
~AncestorsIterator() = default;
@@ -469,7 +470,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
}
// Check object state.
- virtual bool IsAutofillAvailable() { return false; }
+ virtual bool IsAutofillAvailable() const { return false; }
virtual bool IsClickable() const;
virtual AccessibilityExpanded IsExpanded() const {
return kExpandedUndefined;
@@ -621,7 +622,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
// Used by objects of role ColorWellRole.
virtual RGBA32 ColorValue() const { return Color::kTransparent; }
virtual bool CanvasHasFallbackContent() const { return false; }
- virtual AtomicString FontFamily() const { return g_null_atom; }
+ virtual String FontFamily() const { return String(); }
// Font size is in pixels.
virtual float FontSize() const { return 0.0f; }
virtual float FontWeight() const { return 0.0f; }
@@ -711,7 +712,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
ax::mojom::Role DetermineAriaRoleAttribute() const;
virtual ax::mojom::Role AriaRoleAttribute() const;
virtual AXObject* ActiveDescendant() { return nullptr; }
- virtual String AriaAutoComplete() const { return String(); }
+ virtual String AutoComplete() const { return String(); }
virtual void AriaOwnsElements(AXObjectVector& owns) const {}
virtual void AriaDescribedbyElements(AXObjectVector&) const {}
virtual AXObject* ErrorMessage() const { return nullptr; }
@@ -1000,7 +1001,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
// Notifications that this object may have changed.
virtual void ChildrenChanged() {}
virtual void HandleActiveDescendantChanged() {}
- virtual void HandleAutofillStateChanged(bool) {}
+ virtual void HandleAutofillStateChanged(WebAXAutofillState) {}
virtual void HandleAriaExpandedChanged() {}
virtual void SelectionChanged();
virtual void TextChanged() {}
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 00568b6b8d9..94d449fcf50 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
@@ -88,11 +88,10 @@
#include "third_party/blink/renderer/modules/accessibility/ax_virtual_object.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-using namespace html_names;
-
namespace {
// Return a node for the current layout object or ancestor layout object.
Node* GetClosestNodeForLayoutObject(LayoutObject* layout_object) {
@@ -120,6 +119,7 @@ AXObjectCacheImpl::AXObjectCacheImpl(Document& document)
AddPermissionStatusListener();
documents_.insert(&document);
document.View()->RegisterForLifecycleNotifications(this);
+ relation_cache_->Init();
}
AXObjectCacheImpl::~AXObjectCacheImpl() {
@@ -168,6 +168,45 @@ void AXObjectCacheImpl::DisposePopup(Document* document) {
documents_.erase(document);
}
+Node* AXObjectCacheImpl::FocusedElement() {
+ Node* focused_node = document_->FocusedElement();
+ if (!focused_node)
+ focused_node = document_;
+
+ // If it's an image map, get the focused link within the image map.
+ if (IsA<HTMLAreaElement>(focused_node))
+ return focused_node;
+
+ // See if there's a page popup, for example a calendar picker.
+ Element* adjusted_focused_element = document_->AdjustedFocusedElement();
+ if (auto* input = ToHTMLInputElementOrNull(adjusted_focused_element)) {
+ if (AXObject* ax_popup = input->PopupRootAXObject()) {
+ if (Element* focused_element_in_popup =
+ ax_popup->GetDocument()->FocusedElement())
+ focused_node = focused_element_in_popup;
+ }
+ }
+
+ return focused_node;
+}
+
+AXObject* AXObjectCacheImpl::GetOrCreateFocusedObjectFromNode(Node* node) {
+ // If it's an image map, get the focused link within the image map.
+ if (auto* area = DynamicTo<HTMLAreaElement>(node))
+ return FocusedImageMapUIElement(area);
+
+ AXObject* obj = GetOrCreate(node);
+ if (!obj)
+ return nullptr;
+
+ // the HTML element, for example, is focusable but has an AX object that is
+ // ignored
+ if (!obj->AccessibilityIsIncludedInTree())
+ obj = obj->ParentObjectIncludedInTree();
+
+ return obj;
+}
+
AXObject* AXObjectCacheImpl::FocusedImageMapUIElement(
HTMLAreaElement* area_element) {
// Find the corresponding accessibility object for the HTMLAreaElement. This
@@ -198,34 +237,7 @@ AXObject* AXObjectCacheImpl::FocusedImageMapUIElement(
}
AXObject* AXObjectCacheImpl::FocusedObject() {
- Node* focused_node = document_->FocusedElement();
- if (!focused_node)
- focused_node = document_;
-
- // If it's an image map, get the focused link within the image map.
- if (auto* area = DynamicTo<HTMLAreaElement>(focused_node))
- return FocusedImageMapUIElement(area);
-
- // See if there's a page popup, for example a calendar picker.
- Element* adjusted_focused_element = document_->AdjustedFocusedElement();
- if (auto* input = ToHTMLInputElementOrNull(adjusted_focused_element)) {
- if (AXObject* ax_popup = input->PopupRootAXObject()) {
- if (Element* focused_element_in_popup =
- ax_popup->GetDocument()->FocusedElement())
- focused_node = focused_element_in_popup;
- }
- }
-
- AXObject* obj = GetOrCreate(focused_node);
- if (!obj)
- return nullptr;
-
- // the HTML element, for example, is focusable but has an AX object that is
- // ignored
- if (!obj->AccessibilityIsIncludedInTree())
- obj = obj->ParentObjectUnignored();
-
- return obj;
+ return GetOrCreateFocusedObjectFromNode(this->FocusedElement());
}
AXObject* AXObjectCacheImpl::Get(LayoutObject* layout_object) {
@@ -259,10 +271,10 @@ AXObject* AXObjectCacheImpl::Get(LayoutObject* layout_object) {
// Returns true if |node| is an <option> element and its parent <select>
// is a menu list (not a list box).
static bool IsMenuListOption(const Node* node) {
- if (!IsHTMLOptionElement(node))
+ auto* option_element = DynamicTo<HTMLOptionElement>(node);
+ if (!option_element)
return false;
- const HTMLSelectElement* select =
- ToHTMLOptionElement(node)->OwnerSelectElement();
+ const HTMLSelectElement* select = option_element->OwnerSelectElement();
if (!select)
return false;
const LayoutObject* layout_object = select->GetLayoutObject();
@@ -379,7 +391,8 @@ static bool NodeHasRole(Node* node, const String& role) {
return false;
// TODO(accessibility) support role strings with multiple roles.
- return EqualIgnoringASCIICase(element->getAttribute(kRoleAttr), role);
+ return EqualIgnoringASCIICase(element->getAttribute(html_names::kRoleAttr),
+ role);
}
AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
@@ -390,7 +403,7 @@ AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
// ul/ol/dl type (it shouldn't be a list if aria says otherwise).
if (NodeHasRole(node, "list") || NodeHasRole(node, "directory") ||
(NodeHasRole(node, g_null_atom) &&
- (IsHTMLUListElement(node) || IsHTMLOListElement(node) ||
+ (IsHTMLUListElement(node) || IsA<HTMLOListElement>(node) ||
IsA<HTMLDListElement>(node))))
return MakeGarbageCollected<AXList>(layout_object, *this);
@@ -398,7 +411,7 @@ AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
if (node && node->IsMediaElement())
return AccessibilityMediaElement::Create(layout_object, *this);
- if (IsHTMLOptionElement(node))
+ if (IsA<HTMLOptionElement>(node))
return MakeGarbageCollected<AXListBoxOption>(layout_object, *this);
if (IsHTMLInputElement(node) &&
@@ -431,7 +444,7 @@ AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
AXObject* AXObjectCacheImpl::CreateFromNode(Node* node) {
if (IsMenuListOption(node)) {
- return MakeGarbageCollected<AXMenuListOption>(ToHTMLOptionElement(node),
+ return MakeGarbageCollected<AXMenuListOption>(To<HTMLOptionElement>(node),
*this);
}
@@ -633,7 +646,7 @@ void AXObjectCacheImpl::Remove(AXID ax_id) {
if (!ax_id)
return;
- // first fetch object to operate some cleanup functions on it
+ // First, fetch object to operate some cleanup functions on it.
AXObject* obj = objects_.at(ax_id);
if (!obj)
return;
@@ -641,7 +654,7 @@ void AXObjectCacheImpl::Remove(AXID ax_id) {
obj->Detach();
RemoveAXID(obj);
- // finally remove the object
+ // Finally, remove the object.
if (!objects_.Take(ax_id))
return;
@@ -731,6 +744,7 @@ void AXObjectCacheImpl::RemoveAXID(AXObject* object) {
DCHECK(ids_in_use_.Contains(obj_id));
object->SetAXObjectID(0);
ids_in_use_.erase(obj_id);
+ autofill_state_map_.erase(obj_id);
relation_cache_->RemoveAXID(obj_id);
}
@@ -1171,8 +1185,35 @@ void AXObjectCacheImpl::HandleAriaSelectedChangedWithCleanLayout(Node* node) {
PostNotification(obj, ax::mojom::Event::kCheckedStateChanged);
AXObject* listbox = obj->ParentObjectUnignored();
- if (listbox && listbox->RoleValue() == ax::mojom::Role::kListBox)
+ if (listbox && listbox->RoleValue() == ax::mojom::Role::kListBox) {
+ // Ensure listbox options are in sync as selection status may have changed
+ MarkAXObjectDirty(listbox, true);
PostNotification(listbox, ax::mojom::Event::kSelectedChildrenChanged);
+ }
+}
+
+void AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout(Node* node) {
+ DCHECK(node);
+ DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node));
+ AXObject* obj = Get(node);
+ if (!obj)
+ return;
+
+ PostNotification(obj, ax::mojom::Event::kBlur);
+}
+
+void AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout(Node* node) {
+ DCHECK(node);
+ DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node));
+ // Something about the call chain for this method seems to leave distribution
+ // in a dirty state - update it before we call GetOrCreate so that we don't
+ // crash.
+ node->UpdateDistributionForFlatTreeTraversal();
+ AXObject* obj = GetOrCreateFocusedObjectFromNode(node);
+ if (!obj)
+ return;
+
+ PostNotification(obj, ax::mojom::Event::kFocus);
}
// This might be the new target of a relation. Handle all possible cases.
@@ -1219,12 +1260,8 @@ void AXObjectCacheImpl::HandleRoleChangeWithCleanLayout(Node* node) {
DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node));
- AXObject* obj = Get(node);
- if (!obj && IsHTMLSelectElement(node))
- obj = GetOrCreate(node);
-
// Invalidate the current object and make the parent reconsider its children.
- if (obj) {
+ if (AXObject* obj = GetOrCreate(node)) {
// Save parent for later use.
AXObject* parent = obj->ParentObject();
@@ -1280,12 +1317,14 @@ bool AXObjectCacheImpl::HandleAttributeChanged(const QualifiedName& attr_name,
DeferTreeUpdate(&AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout,
attr_name, element);
- if (attr_name != kRoleAttr && attr_name != kTypeAttr &&
- attr_name != kSizeAttr && attr_name != kAltAttr &&
- attr_name != kTitleAttr &&
- (attr_name != kForAttr && !IsA<HTMLLabelElement>(*element)) &&
- attr_name != kIdAttr && attr_name != kTabindexAttr &&
- attr_name != kDisabledAttr &&
+ if (attr_name != html_names::kRoleAttr &&
+ attr_name != html_names::kTypeAttr &&
+ attr_name != html_names::kSizeAttr && attr_name != html_names::kAltAttr &&
+ attr_name != html_names::kTitleAttr &&
+ (attr_name != html_names::kForAttr && !IsA<HTMLLabelElement>(*element)) &&
+ attr_name != html_names::kIdAttr &&
+ attr_name != html_names::kTabindexAttr &&
+ attr_name != html_names::kDisabledAttr &&
!attr_name.LocalName().StartsWith("aria-")) {
return false;
}
@@ -1314,26 +1353,32 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
Element* element) {
DCHECK(element);
DCHECK(!element->GetDocument().NeedsLayoutTreeUpdateForNode(*element));
- if (attr_name == kRoleAttr || attr_name == kTypeAttr) {
+ if (attr_name == html_names::kRoleAttr ||
+ attr_name == html_names::kTypeAttr) {
HandleRoleChangeWithCleanLayout(element);
- } else if (attr_name == kSizeAttr || attr_name == kAriaHaspopupAttr) {
+ } else if (attr_name == html_names::kSizeAttr ||
+ attr_name == html_names::kAriaHaspopupAttr) {
// Role won't change on edits.
HandleRoleChangeIfNotEditableWithCleanLayout(element);
- } else if (attr_name == kAltAttr || attr_name == kTitleAttr) {
+ } else if (attr_name == html_names::kAltAttr ||
+ attr_name == html_names::kTitleAttr) {
TextChangedWithCleanLayout(element);
- } else if (attr_name == kForAttr && IsA<HTMLLabelElement>(*element)) {
+ } else if (attr_name == html_names::kForAttr &&
+ IsA<HTMLLabelElement>(*element)) {
LabelChangedWithCleanLayout(element);
- } else if (attr_name == kIdAttr) {
+ } else if (attr_name == html_names::kIdAttr) {
MaybeNewRelationTarget(element, Get(element));
- } else if (attr_name == kTabindexAttr) {
+ } else if (attr_name == html_names::kTabindexAttr) {
FocusableChangedWithCleanLayout(element);
- } else if (attr_name == kDisabledAttr || attr_name == kReadonlyAttr) {
+ } else if (attr_name == html_names::kDisabledAttr ||
+ attr_name == html_names::kReadonlyAttr) {
MarkElementDirty(element, false);
- } else if (attr_name == kValueAttr) {
+ } else if (attr_name == html_names::kValueAttr) {
HandleValueChanged(element);
- } else if (attr_name == kMinAttr || attr_name == kMaxAttr) {
+ } else if (attr_name == html_names::kMinAttr ||
+ attr_name == html_names::kMaxAttr) {
MarkElementDirty(element, false);
- } else if (attr_name == kStepAttr) {
+ } else if (attr_name == html_names::kStepAttr) {
MarkElementDirty(element, false);
}
@@ -1341,30 +1386,32 @@ void AXObjectCacheImpl::HandleAttributeChangedWithCleanLayout(
return;
// Perform updates specific to each attribute.
- if (attr_name == kAriaActivedescendantAttr) {
+ if (attr_name == html_names::kAriaActivedescendantAttr) {
HandleActiveDescendantChangedWithCleanLayout(element);
- } else if (attr_name == kAriaValuenowAttr ||
- attr_name == kAriaValuetextAttr) {
+ } else if (attr_name == html_names::kAriaValuenowAttr ||
+ attr_name == html_names::kAriaValuetextAttr) {
HandleValueChanged(element);
- } else if (attr_name == kAriaLabelAttr || attr_name == kAriaLabeledbyAttr ||
- attr_name == kAriaLabelledbyAttr) {
+ } else if (attr_name == html_names::kAriaLabelAttr ||
+ attr_name == html_names::kAriaLabeledbyAttr ||
+ attr_name == html_names::kAriaLabelledbyAttr) {
TextChangedWithCleanLayout(element);
- } else if (attr_name == kAriaDescribedbyAttr) {
+ } else if (attr_name == html_names::kAriaDescribedbyAttr) {
// TODO do we need a DescriptionChanged() ?
TextChangedWithCleanLayout(element);
- } else if (attr_name == kAriaCheckedAttr || attr_name == kAriaPressedAttr) {
+ } else if (attr_name == html_names::kAriaCheckedAttr ||
+ attr_name == html_names::kAriaPressedAttr) {
CheckedStateChanged(element);
- } else if (attr_name == kAriaSelectedAttr) {
+ } else if (attr_name == html_names::kAriaSelectedAttr) {
HandleAriaSelectedChangedWithCleanLayout(element);
- } else if (attr_name == kAriaExpandedAttr) {
+ } else if (attr_name == html_names::kAriaExpandedAttr) {
HandleAriaExpandedChangeWithCleanLayout(element);
- } else if (attr_name == kAriaHiddenAttr) {
+ } else if (attr_name == html_names::kAriaHiddenAttr) {
ChildrenChangedWithCleanLayout(element->parentNode());
- } else if (attr_name == kAriaInvalidAttr) {
+ } else if (attr_name == html_names::kAriaInvalidAttr) {
PostNotification(element, ax::mojom::Event::kInvalidStatusChanged);
- } else if (attr_name == kAriaErrormessageAttr) {
+ } else if (attr_name == html_names::kAriaErrormessageAttr) {
MarkElementDirty(element, false);
- } else if (attr_name == kAriaOwnsAttr) {
+ } else if (attr_name == html_names::kAriaOwnsAttr) {
ChildrenChangedWithCleanLayout(element);
// Ensure aria-owns update fires on original parent as well
if (AXObject* obj = GetOrCreate(element)) {
@@ -1590,13 +1637,23 @@ void AXObjectCacheImpl::HandleFocusedUIElementChanged(
if (!page)
return;
- AXObject* focused_object = this->FocusedObject();
- if (!focused_object)
- return;
+ if (RuntimeEnabledFeatures::AccessibilityExposeDisplayNoneEnabled()) {
+ if (old_focused_element) {
+ DeferTreeUpdate(&AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout,
+ old_focused_element);
+ }
+
+ DeferTreeUpdate(&AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout,
+ this->FocusedElement());
+ } else {
+ AXObject* focused_object = this->FocusedObject();
+ if (!focused_object)
+ return;
- AXObject* old_focused_object = Get(old_focused_element);
- PostNotification(old_focused_object, ax::mojom::Event::kBlur);
- PostNotification(focused_object, ax::mojom::Event::kFocus);
+ AXObject* old_focused_object = Get(old_focused_element);
+ PostNotification(old_focused_object, ax::mojom::Event::kBlur);
+ PostNotification(focused_object, ax::mojom::Event::kFocus);
+ }
}
void AXObjectCacheImpl::HandleInitialFocus() {
@@ -1852,4 +1909,19 @@ ax::mojom::EventFrom AXObjectCacheImpl::ComputeEventFrom() {
return ax::mojom::EventFrom::kPage;
}
+WebAXAutofillState AXObjectCacheImpl::GetAutofillState(AXID id) const {
+ auto iter = autofill_state_map_.find(id);
+ if (iter == autofill_state_map_.end())
+ return WebAXAutofillState::kNoSuggestions;
+ return iter->value;
+}
+
+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);
+ }
+}
+
} // namespace blink
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 0c4ceb5ecdd..dbbf20bc473 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
@@ -36,7 +36,9 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h"
+#include "third_party/blink/public/web/web_ax_enums.h"
#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -45,7 +47,7 @@
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "ui/accessibility/ax_enums.mojom-blink.h"
+#include "ui/accessibility/ax_enums.mojom-blink-forward.h"
namespace blink {
@@ -194,6 +196,8 @@ class MODULES_EXPORT AXObjectCacheImpl
void HandleRoleChangeIfNotEditableWithCleanLayout(Node*);
void HandleAriaExpandedChangeWithCleanLayout(Node*);
void HandleAriaSelectedChangedWithCleanLayout(Node*);
+ void HandleNodeLostFocusWithCleanLayout(Node*);
+ void HandleNodeGainedFocusWithCleanLayout(Node*);
bool InlineTextBoxAccessibilityEnabled();
@@ -256,6 +260,9 @@ class MODULES_EXPORT AXObjectCacheImpl
void set_is_handling_action(bool value) { is_handling_action_ = value; }
+ WebAXAutofillState GetAutofillState(AXID id) const;
+ void SetAutofillState(AXID id, WebAXAutofillState state);
+
protected:
void PostPlatformNotification(
AXObject*,
@@ -268,7 +275,7 @@ class MODULES_EXPORT AXObjectCacheImpl
AXObject* CreateFromInlineTextBox(AbstractInlineTextBox*);
private:
- struct AXEventParams : public GarbageCollectedFinalized<AXEventParams> {
+ struct AXEventParams final : public GarbageCollected<AXEventParams> {
AXEventParams(AXObject* target,
ax::mojom::Event event_type,
ax::mojom::EventFrom event_from)
@@ -280,7 +287,7 @@ class MODULES_EXPORT AXObjectCacheImpl
void Trace(Visitor* visitor) { visitor->Trace(target); }
};
- struct TreeUpdateParams : public GarbageCollectedFinalized<TreeUpdateParams> {
+ struct TreeUpdateParams final : public GarbageCollected<TreeUpdateParams> {
TreeUpdateParams(Node* node, base::OnceClosure callback)
: node(node), callback(std::move(callback)) {}
WeakMember<Node> node;
@@ -322,6 +329,12 @@ class MODULES_EXPORT AXObjectCacheImpl
// ContextLifecycleObserver overrides.
void ContextDestroyed(ExecutionContext*) override;
+ // Get the currently focused Node element.
+ Node* FocusedElement();
+
+ // GetOrCreate the focusable AXObject for a specific Node.
+ AXObject* GetOrCreateFocusedObjectFromNode(Node*);
+
AXObject* FocusedImageMapUIElement(HTMLAreaElement*);
AXID GetOrCreateAXID(AXObject*);
@@ -386,6 +399,9 @@ class MODULES_EXPORT AXObjectCacheImpl
bool is_handling_action_ = false;
+ // Maps ids to their object's autofill state.
+ HashMap<AXID, WebAXAutofillState> autofill_state_map_;
+
DISALLOW_COPY_AND_ASSIGN(AXObjectCacheImpl);
};
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 2bf649ae277..b5426a0d1fa 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
@@ -396,5 +396,55 @@ TEST_F(AccessibilityTest, CheckNoDuplicateChildren) {
ASSERT_EQ(ax_select->FirstChild()->ChildCount(), 1);
}
+TEST_F(AccessibilityTest, InitRelationCache) {
+ // All of the other tests already have accessibility initialized
+ // first, but we don't want to in this test.
+ //
+ // Get rid of the AXContext so the AXObjectCache is destroyed.
+ ax_context_.reset(nullptr);
+
+ SetBodyInnerHTML(R"HTML(
+ <ul id="ul" aria-owns="li"></ul>
+ <label for="a"></label>
+ <input id="a">
+ <input id="b">
+ <div role="section" id="div">
+ <li id="li"></li>
+ </div>
+ )HTML");
+
+ // Now recreate an AXContext, simulating what happens if accessibility
+ // is enabled after the document is loaded.
+ ax_context_.reset(new AXContext(GetDocument()));
+
+ const AXObject* root = GetAXRootObject();
+ ASSERT_NE(nullptr, root);
+ const AXObject* input_a = GetAXObjectByElementId("a");
+ ASSERT_NE(nullptr, input_a);
+ const AXObject* input_b = GetAXObjectByElementId("b");
+ ASSERT_NE(nullptr, input_b);
+
+ EXPECT_TRUE(
+ GetAXObjectCache().MayHaveHTMLLabel(ToHTMLElement(*input_a->GetNode())));
+ EXPECT_FALSE(
+ GetAXObjectCache().MayHaveHTMLLabel(ToHTMLElement(*input_b->GetNode())));
+
+ // Note: retrieve the LI first and check that its parent is not
+ // the paragraph element. If we were to retrieve the UL element,
+ // that would trigger the aria-owns check and wouln't allow us to
+ // test whether the relation cache was initialized.
+ const AXObject* li = GetAXObjectByElementId("li");
+ ASSERT_NE(nullptr, li);
+
+ const AXObject* div = GetAXObjectByElementId("div");
+ ASSERT_NE(nullptr, div);
+ EXPECT_NE(li->ParentObjectUnignored(), div);
+
+ const AXObject* ul = GetAXObjectByElementId("ul");
+ ASSERT_NE(nullptr, ul);
+
+ EXPECT_EQ(li->ParentObjectUnignored(), ul);
+}
+
} // 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 15ebb4bdb28..fd7dd48d0e4 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
@@ -26,7 +26,7 @@ namespace blink {
const AXPosition AXPosition::CreatePositionBeforeObject(
const AXObject& child,
const AXPositionAdjustmentBehavior adjustment_behavior) {
- if (child.IsDetached())
+ if (child.IsDetached() || !child.AccessibilityIsIncludedInTree())
return {};
// If |child| is a text object, but not a text control, make behavior the same
@@ -37,6 +37,10 @@ const AXPosition AXPosition::CreatePositionBeforeObject(
return CreateFirstPositionInObject(child, adjustment_behavior);
const AXObject* parent = child.ParentObjectIncludedInTree();
+
+ if (!parent || parent->IsDetached())
+ return {};
+
DCHECK(parent);
AXPosition position(*parent);
position.text_offset_or_child_index_ = child.IndexInParent();
@@ -51,7 +55,7 @@ const AXPosition AXPosition::CreatePositionBeforeObject(
const AXPosition AXPosition::CreatePositionAfterObject(
const AXObject& child,
const AXPositionAdjustmentBehavior adjustment_behavior) {
- if (child.IsDetached())
+ if (child.IsDetached() || !child.AccessibilityIsIncludedInTree())
return {};
// If |child| is a text object, but not a text control, make behavior the same
@@ -62,6 +66,10 @@ const AXPosition AXPosition::CreatePositionAfterObject(
return CreateLastPositionInObject(child, adjustment_behavior);
const AXObject* parent = child.ParentObjectIncludedInTree();
+
+ if (!parent || parent->IsDetached())
+ return {};
+
DCHECK(parent);
AXPosition position(*parent);
position.text_offset_or_child_index_ = child.IndexInParent() + 1;
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 c571e5eb323..31193add4e2 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
@@ -77,6 +77,12 @@ constexpr char kAOM[] = R"HTML(
</script>
)HTML";
+constexpr char kMap[] = R"HTML(
+ <br id="br">
+ <map id="map">
+ <area shape="rect" coords="0,0,10,10" href="about:blank">
+ </map>
+ )HTML";
} // namespace
//
@@ -734,11 +740,12 @@ TEST_F(AccessibilityTest, PositionInIgnoredObject) {
const AXObject* ax_body = ax_root->FirstChild();
ASSERT_NE(nullptr, ax_body);
ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_body->RoleValue());
- ASSERT_EQ(1, ax_body->ChildCount());
+ ASSERT_EQ(2, ax_body->ChildCount());
const AXObject* ax_hidden = GetAXObjectByElementId("hidden");
ASSERT_NE(nullptr, ax_hidden);
ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_hidden->RoleValue());
+ ASSERT_TRUE(ax_hidden->AccessibilityIsIgnoredButIncludedInTree());
const AXObject* ax_visible = GetAXObjectByElementId("visible");
ASSERT_NE(nullptr, ax_visible);
@@ -762,10 +769,7 @@ TEST_F(AccessibilityTest, PositionInIgnoredObject) {
ax_position_before_visible_from_dom.ChildAfterTreePosition());
// A position at the beginning of the body will appear to be before the hidden
- // element in the DOM, but it should be before the visible object in the
- // accessibility tree since the hidden element is not in the tree. Hence, when
- // converting to the corresponding DOM position, it should be before the
- // visible element in the DOM as well.
+ // element in the DOM.
const auto ax_position_first =
AXPosition::CreateFirstPositionInObject(*ax_root);
const auto position_first = ax_position_first.ToPositionWithAffinity();
@@ -781,13 +785,13 @@ TEST_F(AccessibilityTest, PositionInIgnoredObject) {
EXPECT_EQ(ax_body, ax_position_first_from_dom.ChildAfterTreePosition());
// A DOM position before |hidden| should convert to an accessibility position
- // before |visible|.
+ // before |hidden| because the node is ignored but included in the tree.
const auto position_before = Position::BeforeNode(*hidden);
const auto ax_position_before_from_dom =
AXPosition::FromPosition(position_before);
EXPECT_EQ(ax_body, ax_position_before_from_dom.ContainerObject());
EXPECT_EQ(0, ax_position_before_from_dom.ChildIndex());
- EXPECT_EQ(ax_visible, ax_position_before_from_dom.ChildAfterTreePosition());
+ EXPECT_EQ(ax_hidden, ax_position_before_from_dom.ChildAfterTreePosition());
// A DOM position after |hidden| should convert to an accessibility position
// before |visible|.
@@ -795,7 +799,7 @@ TEST_F(AccessibilityTest, PositionInIgnoredObject) {
const auto ax_position_after_from_dom =
AXPosition::FromPosition(position_after);
EXPECT_EQ(ax_body, ax_position_after_from_dom.ContainerObject());
- EXPECT_EQ(0, ax_position_after_from_dom.ChildIndex());
+ EXPECT_EQ(1, ax_position_after_from_dom.ChildIndex());
EXPECT_EQ(ax_visible, ax_position_after_from_dom.ChildAfterTreePosition());
}
@@ -1622,5 +1626,33 @@ TEST_F(AccessibilityTest, DISABLED_PositionInVirtualAOMNode) {
EXPECT_EQ(ax_after, ax_position_after_from_dom.ChildAfterTreePosition());
}
+TEST_F(AccessibilityTest, PositionInInvalidMapLayout) {
+ SetBodyInnerHTML(kMap);
+
+ Node* br = GetElementById("br");
+ ASSERT_NE(nullptr, br);
+ Node* map = GetElementById("map");
+ ASSERT_NE(nullptr, map);
+
+ // Create an invalid layout by appending a child to the <br>
+ br->appendChild(map);
+ GetDocument().UpdateStyleAndLayoutTree();
+
+ const AXObject* ax_map = GetAXObjectByElementId("map");
+ ASSERT_NE(nullptr, ax_map);
+ ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_map->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreatePositionBeforeObject(*ax_map);
+ const auto position_before = ax_position_before.ToPositionWithAffinity();
+ EXPECT_EQ(nullptr, position_before.AnchorNode());
+ EXPECT_EQ(0, position_before.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_after = AXPosition::CreatePositionAfterObject(*ax_map);
+ const auto position_after = ax_position_after.ToPositionWithAffinity();
+ EXPECT_EQ(nullptr, position_after.AnchorNode());
+ EXPECT_EQ(0, position_after.GetPosition().OffsetInContainerNode());
+}
+
} // namespace test
} // namespace blink
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 02eae002ace..2787cb858cd 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
@@ -5,17 +5,34 @@
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/html/forms/html_label_element.h"
namespace blink {
-using namespace html_names;
-
AXRelationCache::AXRelationCache(AXObjectCacheImpl* object_cache)
: object_cache_(object_cache) {}
AXRelationCache::~AXRelationCache() = default;
+void AXRelationCache::Init() {
+ // Init the relation cache with elements already in the document.
+ Document& document = object_cache_->GetDocument();
+ for (Element& element :
+ ElementTraversal::DescendantsOf(*document.documentElement())) {
+ const auto& id = element.FastGetAttribute(html_names::kForAttr);
+ if (!id.IsEmpty())
+ all_previously_seen_label_target_ids_.insert(id);
+
+ if (element.FastHasAttribute(html_names::kAriaOwnsAttr)) {
+ if (AXObject* obj = object_cache_->GetOrCreate(&element)) {
+ obj->ClearChildren();
+ obj->AddChildren();
+ }
+ }
+ }
+}
+
bool AXRelationCache::IsAriaOwned(const AXObject* child) const {
return aria_owned_child_to_owner_mapping_.Contains(child->AXObjectID());
}
@@ -270,7 +287,8 @@ void AXRelationCache::TextChanged(AXObject* object) {
}
void AXRelationCache::LabelChanged(Node* node) {
- const auto& id = To<HTMLElement>(node)->FastGetAttribute(kForAttr);
+ const auto& id =
+ 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())
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 a96097fd477..2dec5cfb6d0 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
@@ -22,6 +22,9 @@ class AXRelationCache {
explicit AXRelationCache(AXObjectCacheImpl*);
virtual ~AXRelationCache();
+ // Scan the initial document.
+ void Init();
+
// Returns true if the given object's position in the tree was due to
// aria-owns.
bool IsAriaOwned(const AXObject*) const;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
index 7532b8ccc67..02efbea750f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -156,6 +156,9 @@ AXSelection AXSelection::FromCurrentSelection(
*ax_text_control, static_cast<int>(text_control.selectionEnd()),
extent_affinity);
+ if (!ax_base.IsValid() || !ax_extent.IsValid())
+ return {};
+
AXSelection::Builder selection_builder;
selection_builder.SetBase(ax_base).SetExtent(ax_extent);
return selection_builder.Build();
@@ -214,6 +217,9 @@ AXSelection AXSelection::FromSelection(
const auto ax_extent =
AXPosition::FromPosition(dom_extent, extent_affinity, extent_adjustment);
+ if (!ax_base.IsValid() || !ax_extent.IsValid())
+ return {};
+
AXSelection::Builder selection_builder;
selection_builder.SetBase(ax_base).SetExtent(ax_extent);
return selection_builder.Build();
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 e9977f2c479..1091d5b0895 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
@@ -302,7 +302,7 @@ TEST_F(AccessibilitySelectionTest, SetSelectionAcrossLineBreak) {
const Node* paragraph = GetDocument().QuerySelector("p");
ASSERT_NE(nullptr, paragraph);
- ASSERT_TRUE(IsHTMLParagraphElement(paragraph));
+ ASSERT_TRUE(IsA<HTMLParagraphElement>(paragraph));
const Node* br = GetDocument().QuerySelector("br");
ASSERT_NE(nullptr, br);
ASSERT_TRUE(IsA<HTMLBRElement>(br));
@@ -347,7 +347,7 @@ TEST_F(AccessibilitySelectionTest, SetSelectionAcrossLineBreakInEditableText) {
const Node* paragraph = GetDocument().QuerySelector("p");
ASSERT_NE(nullptr, paragraph);
- ASSERT_TRUE(IsHTMLParagraphElement(paragraph));
+ ASSERT_TRUE(IsA<HTMLParagraphElement>(paragraph));
const Node* br = GetDocument().QuerySelector("br");
ASSERT_NE(nullptr, br);
ASSERT_TRUE(IsA<HTMLBRElement>(br));
@@ -420,7 +420,7 @@ TEST_F(AccessibilitySelectionTest, SetSelectionInDisplayNone) {
ASSERT_NE(nullptr, ax_hidden1);
ASSERT_EQ(ax::mojom::Role::kParagraph, ax_hidden1->RoleValue());
ASSERT_TRUE(ax_hidden1->AccessibilityIsIgnored());
- ASSERT_FALSE(ax_hidden1->AccessibilityIsIncludedInTree());
+ ASSERT_TRUE(ax_hidden1->AccessibilityIsIncludedInTree());
const AXObject* ax_between = GetAXObjectByElementId("betweenHidden");
ASSERT_NE(nullptr, ax_between);
ASSERT_EQ(ax::mojom::Role::kParagraph, ax_between->RoleValue());
@@ -428,7 +428,7 @@ TEST_F(AccessibilitySelectionTest, SetSelectionInDisplayNone) {
ASSERT_NE(nullptr, ax_hidden2);
ASSERT_EQ(ax::mojom::Role::kParagraph, ax_hidden2->RoleValue());
ASSERT_TRUE(ax_hidden2->AccessibilityIsIgnored());
- ASSERT_FALSE(ax_hidden2->AccessibilityIsIncludedInTree());
+ ASSERT_TRUE(ax_hidden2->AccessibilityIsIncludedInTree());
const AXObject* ax_after = GetAXObjectByElementId("afterHidden");
ASSERT_NE(nullptr, ax_after);
ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue());
@@ -444,27 +444,27 @@ TEST_F(AccessibilitySelectionTest, SetSelectionInDisplayNone) {
const auto ax_selection_extend = AXSelection::FromSelection(
selection, AXSelectionBehavior::kExtendToValidDOMRange);
- // The shrunk selection should encompass only the |AXObject| between the two
- // aria-hidden elements and nothing else. This means that its anchor should be
- // before and its focus after the |AXObject| in question.
+ // The "display: none" content is included in the AXTree as an ignored node,
+ // so shrunk selection should include those AXObjects. Note that the browser
+ // process will adjust the position to only encompass the |AXObject| between
+ // the two "display: none" elements, since they are ignored nodes.
ASSERT_FALSE(ax_selection_shrink.Base().IsTextPosition());
- EXPECT_EQ(ax_main, ax_selection_shrink.Base().ContainerObject());
- EXPECT_EQ(ax_between->IndexInParent(),
- ax_selection_shrink.Base().ChildIndex());
+ EXPECT_EQ(ax_hidden1, ax_selection_shrink.Base().ContainerObject());
+ EXPECT_EQ(0, ax_selection_shrink.Base().ChildIndex());
ASSERT_FALSE(ax_selection_shrink.Extent().IsTextPosition());
- EXPECT_EQ(ax_between, ax_selection_shrink.Extent().ContainerObject());
- EXPECT_EQ(1, ax_selection_shrink.Extent().ChildIndex());
+ EXPECT_EQ(ax_hidden2, ax_selection_shrink.Extent().ContainerObject());
+ EXPECT_EQ(0, ax_selection_shrink.Extent().ChildIndex());
- // The extended selection should start after the children of the paragraph
- // before the first display:none element and end right before the paragraph
- // after the last display:none element.
+ // The extended selection should start in the "display: none" content because
+ // they are included in the AXTree. The browser process will adjust ignored
+ // positions so that in this case it would only encompass the paragraph
+ // between the "display: none" nodes.
ASSERT_FALSE(ax_selection_extend.Base().IsTextPosition());
- EXPECT_EQ(ax_before, ax_selection_extend.Base().ContainerObject());
- EXPECT_EQ(1, ax_selection_extend.Base().ChildIndex());
+ EXPECT_EQ(ax_hidden1, ax_selection_extend.Base().ContainerObject());
+ EXPECT_EQ(0, ax_selection_extend.Base().ChildIndex());
ASSERT_FALSE(ax_selection_extend.Extent().IsTextPosition());
- EXPECT_EQ(ax_main, ax_selection_extend.Extent().ContainerObject());
- EXPECT_EQ(ax_after->IndexInParent(),
- ax_selection_extend.Extent().ChildIndex());
+ EXPECT_EQ(ax_hidden2, ax_selection_extend.Extent().ContainerObject());
+ EXPECT_EQ(0, ax_selection_extend.Extent().ChildIndex());
// Even though the two AX selections have different anchors and foci, the text
// selected in the accessibility tree should not differ, because any
@@ -476,8 +476,10 @@ TEST_F(AccessibilitySelectionTest, SetSelectionInDisplayNone) {
"++++<Main>\n"
"++++++<Paragraph>\n"
"++++++++<StaticText: Before display:none.>\n"
+ "++++++<Paragraph: Display:none 1.>\n"
"^++++++<Paragraph>\n"
"++++++++<StaticText: In between two display:none elements.>\n"
+ "++++++<Paragraph: Display:none 2.>\n"
"|++++++<Paragraph>\n"
"++++++++<StaticText: After display:none.>\n");
EXPECT_EQ(selection_text, GetSelectionText(ax_selection_shrink));
@@ -1692,6 +1694,33 @@ TEST_F(AccessibilitySelectionTest, SelectionWithEqualBaseAndExtent) {
builder.SetBase(ax_position).SetExtent(ax_position).Build();
}
+TEST_F(AccessibilitySelectionTest, InvalidSelectionOnAShadowRoot) {
+ GetPage().GetSettings().SetScriptEnabled(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id="container">
+ </div>
+ )HTML");
+ Element* const script_element =
+ GetDocument().CreateRawElement(html_names::kScriptTag);
+ script_element->setTextContent(R"SCRIPT(
+ var container = document.getElementById("container");
+ var shadow = container.attachShadow({mode: 'open'});
+ var button = document.createElement("button");
+ button.id = "button";
+ shadow.appendChild(button);
+ )SCRIPT");
+ GetDocument().body()->AppendChild(script_element);
+ UpdateAllLifecyclePhasesForTest();
+
+ Node* shadow_root = GetElementById("container")->GetShadowRoot();
+ const Position base = Position::EditingPositionOf(shadow_root, 0);
+ const Position extent = Position::EditingPositionOf(shadow_root, 1);
+
+ const auto selection =
+ SelectionInDOMTree::Builder().SetBaseAndExtent(base, extent).Build();
+ EXPECT_FALSE(AXSelection::FromSelection(selection).IsValid());
+}
+
//
// Declarative tests.
//
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 c15a9ed776b..a04a922d0c4 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_slider.cc
@@ -113,6 +113,10 @@ bool AXSlider::OnNativeSetValueAction(const String& value) {
// Fire change event manually, as LayoutSlider::setValueForPosition does.
input->DispatchFormControlChangeEvent();
+
+ // Ensure the AX node is updated.
+ AXObjectCache().MarkAXObjectDirty(this, false);
+
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 52071bca0ec..0999dae6fe0 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
@@ -7,8 +7,6 @@
namespace blink {
-using namespace html_names;
-
class BoolAttributeSetter : public AXSparseAttributeSetter {
public:
BoolAttributeSetter(AXBoolAttribute attribute) : attribute_(attribute) {}
@@ -145,45 +143,47 @@ AXSparseAttributeSetterMap& GetSparseAttributeSetterMap() {
ax_sparse_attribute_setter_map, ());
if (ax_sparse_attribute_setter_map.IsEmpty()) {
ax_sparse_attribute_setter_map.Set(
- kAriaActivedescendantAttr,
+ html_names::kAriaActivedescendantAttr,
new ObjectAttributeSetter(AXObjectAttribute::kAriaActiveDescendant));
ax_sparse_attribute_setter_map.Set(
- kAriaControlsAttr, new ObjectVectorAttributeSetter(
- AXObjectVectorAttribute::kAriaControls));
+ html_names::kAriaControlsAttr,
+ new ObjectVectorAttributeSetter(
+ AXObjectVectorAttribute::kAriaControls));
ax_sparse_attribute_setter_map.Set(
- kAriaFlowtoAttr,
+ html_names::kAriaFlowtoAttr,
new ObjectVectorAttributeSetter(AXObjectVectorAttribute::kAriaFlowTo));
ax_sparse_attribute_setter_map.Set(
- kAriaDetailsAttr,
+ html_names::kAriaDetailsAttr,
new ObjectAttributeSetter(AXObjectAttribute::kAriaDetails));
ax_sparse_attribute_setter_map.Set(
- kAriaErrormessageAttr,
+ html_names::kAriaErrormessageAttr,
new ObjectAttributeSetter(AXObjectAttribute::kAriaErrorMessage));
ax_sparse_attribute_setter_map.Set(
- kAriaKeyshortcutsAttr,
+ html_names::kAriaKeyshortcutsAttr,
new StringAttributeSetter(AXStringAttribute::kAriaKeyShortcuts));
ax_sparse_attribute_setter_map.Set(
- kAriaRoledescriptionAttr,
+ html_names::kAriaRoledescriptionAttr,
new StringAttributeSetter(AXStringAttribute::kAriaRoleDescription));
ax_sparse_attribute_setter_map.Set(
- kAriaBusyAttr, new BoolAttributeSetter(AXBoolAttribute::kAriaBusy));
+ html_names::kAriaBusyAttr,
+ new BoolAttributeSetter(AXBoolAttribute::kAriaBusy));
ax_sparse_attribute_setter_map.Set(
- kAriaColcountAttr,
+ html_names::kAriaColcountAttr,
new IntAttributeSetter(AXIntAttribute::kAriaColumnCount));
ax_sparse_attribute_setter_map.Set(
- kAriaColindexAttr,
+ html_names::kAriaColindexAttr,
new UIntAttributeSetter(AXUIntAttribute::kAriaColumnIndex));
ax_sparse_attribute_setter_map.Set(
- kAriaColspanAttr,
+ html_names::kAriaColspanAttr,
new UIntAttributeSetter(AXUIntAttribute::kAriaColumnSpan));
ax_sparse_attribute_setter_map.Set(
- kAriaRowcountAttr,
+ html_names::kAriaRowcountAttr,
new IntAttributeSetter(AXIntAttribute::kAriaRowCount));
ax_sparse_attribute_setter_map.Set(
- kAriaRowindexAttr,
+ html_names::kAriaRowindexAttr,
new UIntAttributeSetter(AXUIntAttribute::kAriaRowIndex));
ax_sparse_attribute_setter_map.Set(
- kAriaRowspanAttr,
+ html_names::kAriaRowspanAttr,
new UIntAttributeSetter(AXUIntAttribute::kAriaRowSpan));
}
return ax_sparse_attribute_setter_map;
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 b825bd2b6e1..eeff1f668b8 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
@@ -11,6 +11,7 @@
#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/node_list.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
@@ -34,8 +35,7 @@ using protocol::Accessibility::AXRelatedNode;
using protocol::Accessibility::AXValue;
using protocol::Maybe;
using protocol::Response;
-
-using namespace html_names;
+namespace AXPropertyNameEnum = protocol::Accessibility::AXPropertyNameEnum;
namespace {
@@ -212,7 +212,7 @@ bool RoleAllowsSort(ax::mojom::Role role) {
void FillWidgetProperties(AXObject& ax_object,
protocol::Array<AXProperty>& properties) {
ax::mojom::Role role = ax_object.RoleValue();
- String autocomplete = ax_object.AriaAutoComplete();
+ String autocomplete = ax_object.AutoComplete();
if (!autocomplete.IsEmpty())
properties.emplace_back(
CreateProperty(AXPropertyNameEnum::Autocomplete,
@@ -450,13 +450,14 @@ class SparseAttributeAXPropertyAdapter
HeapVector<Member<AXObject>>& objects) override {
switch (attribute) {
case AXObjectVectorAttribute::kAriaControls:
- properties_.emplace_back(
- CreateRelatedNodeListProperty(AXPropertyNameEnum::Controls, objects,
- kAriaControlsAttr, *ax_object_));
+ properties_.emplace_back(CreateRelatedNodeListProperty(
+ AXPropertyNameEnum::Controls, objects,
+ html_names::kAriaControlsAttr, *ax_object_));
break;
case AXObjectVectorAttribute::kAriaFlowTo:
properties_.emplace_back(CreateRelatedNodeListProperty(
- AXPropertyNameEnum::Flowto, objects, kAriaFlowtoAttr, *ax_object_));
+ AXPropertyNameEnum::Flowto, objects, html_names::kAriaFlowtoAttr,
+ *ax_object_));
break;
}
}
@@ -467,16 +468,17 @@ void FillRelationships(AXObject& ax_object,
AXObject::AXObjectVector results;
ax_object.AriaDescribedbyElements(results);
if (!results.IsEmpty()) {
- properties.emplace_back(
- CreateRelatedNodeListProperty(AXPropertyNameEnum::Describedby, results,
- kAriaDescribedbyAttr, ax_object));
+ properties.emplace_back(CreateRelatedNodeListProperty(
+ AXPropertyNameEnum::Describedby, results,
+ html_names::kAriaDescribedbyAttr, ax_object));
}
results.clear();
ax_object.AriaOwnsElements(results);
if (!results.IsEmpty()) {
- properties.emplace_back(CreateRelatedNodeListProperty(
- AXPropertyNameEnum::Owns, results, kAriaOwnsAttr, ax_object));
+ properties.emplace_back(
+ CreateRelatedNodeListProperty(AXPropertyNameEnum::Owns, results,
+ html_names::kAriaOwnsAttr, ax_object));
}
results.clear();
}
@@ -566,9 +568,18 @@ void InspectorAccessibilityAgent::AddAncestors(
std::unique_ptr<protocol::Array<AXNode>>& nodes,
AXObjectCacheImpl& cache) const {
AXObject* ancestor = &first_ancestor;
+ AXObject* child = inspected_ax_object;
while (ancestor) {
- nodes->emplace_back(BuildProtocolAXObject(*ancestor, inspected_ax_object,
- true, nodes, cache));
+ std::unique_ptr<AXNode> parent_node_object = BuildProtocolAXObject(
+ *ancestor, inspected_ax_object, true, nodes, cache);
+ auto child_ids = std::make_unique<protocol::Array<AXNodeId>>();
+ if (child)
+ child_ids->emplace_back(String::Number(child->AXObjectID()));
+ else
+ child_ids->emplace_back(String::Number(kIDForInspectedNodeWithNoAXNode));
+ parent_node_object->setChildIds(std::move(child_ids));
+ nodes->emplace_back(std::move(parent_node_object));
+ child = ancestor;
ancestor = ancestor->ParentObjectUnignored();
}
}
@@ -646,16 +657,7 @@ void InspectorAccessibilityAgent::PopulateDOMNodeAncestors(
return;
// Populate parent and ancestors.
- std::unique_ptr<AXNode> parent_node_object =
- BuildProtocolAXObject(*parent_ax_object, nullptr, true, nodes, cache);
- auto child_ids = std::make_unique<protocol::Array<AXNodeId>>();
- child_ids->emplace_back(String::Number(kIDForInspectedNodeWithNoAXNode));
- parent_node_object->setChildIds(std::move(child_ids));
- nodes->emplace_back(std::move(parent_node_object));
-
- AXObject* grandparent_ax_object = parent_ax_object->ParentObjectUnignored();
- if (grandparent_ax_object)
- AddAncestors(*grandparent_ax_object, nullptr, nodes, cache);
+ AddAncestors(*parent_ax_object, nullptr, nodes, cache);
}
std::unique_ptr<AXNode> InspectorAccessibilityAgent::BuildProtocolAXObject(
@@ -717,6 +719,8 @@ Response InspectorAccessibilityAgent::getFullAXTree(
Document* document = inspected_frames_->Root()->GetDocument();
if (!document)
return Response::Error("No document.");
+ if (document->View()->NeedsLayout() || document->NeedsLayoutTreeUpdate())
+ document->UpdateStyleAndLayout();
*nodes = std::make_unique<protocol::Array<protocol::Accessibility::AXNode>>();
AXContext ax_context(*document);
AXObjectCacheImpl& cache = ToAXObjectCacheImpl(ax_context.GetAXObjectCache());
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.cc b/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.cc
index 3852bf325dd..c379a8f00ad 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.cc
@@ -11,8 +11,7 @@
namespace blink {
-using namespace html_names;
-using namespace protocol::Accessibility;
+using protocol::Accessibility::AXRelatedNode;
std::unique_ptr<AXProperty> CreateProperty(const String& name,
std::unique_ptr<AXValue> value) {
@@ -167,43 +166,46 @@ std::unique_ptr<AXValue> CreateRelatedNodeListValue(
}
String ValueSourceType(ax::mojom::NameFrom name_from) {
+ namespace SourceType = protocol::Accessibility::AXValueSourceTypeEnum;
+
switch (name_from) {
case ax::mojom::NameFrom::kAttribute:
case ax::mojom::NameFrom::kAttributeExplicitlyEmpty:
case ax::mojom::NameFrom::kTitle:
case ax::mojom::NameFrom::kValue:
- return AXValueSourceTypeEnum::Attribute;
+ return SourceType::Attribute;
case ax::mojom::NameFrom::kContents:
- return AXValueSourceTypeEnum::Contents;
+ return SourceType::Contents;
case ax::mojom::NameFrom::kPlaceholder:
- return AXValueSourceTypeEnum::Placeholder;
+ return SourceType::Placeholder;
case ax::mojom::NameFrom::kCaption:
case ax::mojom::NameFrom::kRelatedElement:
- return AXValueSourceTypeEnum::RelatedElement;
+ return SourceType::RelatedElement;
default:
- return AXValueSourceTypeEnum::Implicit; // TODO(aboxhall): what to do
- // here?
+ return SourceType::Implicit; // TODO(aboxhall): what to do here?
}
}
String NativeSourceType(AXTextFromNativeHTML native_source) {
+ namespace SourceType = protocol::Accessibility::AXValueNativeSourceTypeEnum;
+
switch (native_source) {
case kAXTextFromNativeHTMLFigcaption:
- return AXValueNativeSourceTypeEnum::Figcaption;
+ return SourceType::Figcaption;
case kAXTextFromNativeHTMLLabel:
- return AXValueNativeSourceTypeEnum::Label;
+ return SourceType::Label;
case kAXTextFromNativeHTMLLabelFor:
- return AXValueNativeSourceTypeEnum::Labelfor;
+ return SourceType::Labelfor;
case kAXTextFromNativeHTMLLabelWrapped:
- return AXValueNativeSourceTypeEnum::Labelwrapped;
+ return SourceType::Labelwrapped;
case kAXTextFromNativeHTMLTableCaption:
- return AXValueNativeSourceTypeEnum::Tablecaption;
+ return SourceType::Tablecaption;
case kAXTextFromNativeHTMLLegend:
- return AXValueNativeSourceTypeEnum::Legend;
+ return SourceType::Legend;
case kAXTextFromNativeHTMLTitleElement:
- return AXValueNativeSourceTypeEnum::Title;
+ return SourceType::Title;
default:
- return AXValueNativeSourceTypeEnum::Other;
+ return SourceType::Other;
}
}
@@ -212,8 +214,8 @@ std::unique_ptr<AXValueSource> CreateValueSource(NameSource& name_source) {
std::unique_ptr<AXValueSource> value_source =
AXValueSource::create().setType(type).build();
if (!name_source.related_objects.IsEmpty()) {
- if (name_source.attribute == kAriaLabelledbyAttr ||
- name_source.attribute == kAriaLabeledbyAttr) {
+ if (name_source.attribute == html_names::kAriaLabelledbyAttr ||
+ name_source.attribute == html_names::kAriaLabeledbyAttr) {
std::unique_ptr<AXValue> attribute_value = CreateRelatedNodeListValue(
name_source.related_objects, AXValueTypeEnum::IdrefList);
if (!name_source.attribute_value.IsNull())
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h b/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h
index 779815e6ae7..d0b5b50d910 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/inspector_type_builder_helper.h
@@ -12,7 +12,10 @@
namespace blink {
-using namespace protocol::Accessibility;
+using protocol::Accessibility::AXProperty;
+using protocol::Accessibility::AXValue;
+using protocol::Accessibility::AXValueSource;
+namespace AXValueTypeEnum = protocol::Accessibility::AXValueTypeEnum;
std::unique_ptr<AXProperty> CreateProperty(const String& name,
std::unique_ptr<AXValue>);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
index 7461c5bd85f..0608c4edd9e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
@@ -44,12 +44,13 @@ class AccessibilityTest : public RenderingTest {
std::string PrintAXTree() const;
+ protected:
+ std::unique_ptr<AXContext> ax_context_;
+
private:
std::ostringstream& PrintAXTreeHelper(std::ostringstream&,
const AXObject* root,
size_t level) const;
-
- std::unique_ptr<AXContext> ax_context_;
};
} // namespace test
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 c6929f56332..f4602a70570 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
@@ -263,8 +263,8 @@ Animator* AnimationWorkletGlobalScope::CreateInstance(
v8::Local<v8::Value> v8_state = serialized_state
? serialized_state->Deserialize(isolate)
: v8::Undefined(isolate).As<v8::Value>();
- ScriptValue options_value(script_state, v8_options);
- ScriptValue state_value(script_state, v8_state);
+ ScriptValue options_value(isolate, v8_options);
+ ScriptValue state_value(isolate, v8_state);
ScriptValue instance;
if (!definition->ConstructorFunction()
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h
index 74770067631..31fe8c68fcb 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h
@@ -26,7 +26,7 @@ class WorkletGlobalScope;
// This is constructed on the main thread but it is used in the worklet backing
// thread.
class MODULES_EXPORT AnimationWorkletProxyClient
- : public GarbageCollectedFinalized<AnimationWorkletProxyClient>,
+ : public GarbageCollected<AnimationWorkletProxyClient>,
public Supplement<WorkerClients>,
public AnimationWorkletMutator {
USING_GARBAGE_COLLECTED_MIXIN(AnimationWorkletProxyClient);
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
index 67e6a0fb903..bfafe9739cb 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
@@ -23,8 +23,7 @@ class AnimatorDefinition;
// Represents an animator instance. It owns the underlying |v8::Object| for the
// instance and knows how to invoke the |animate| function on it.
// See also |AnimationWorkletGlobalScope::CreateInstance|.
-class Animator final : public GarbageCollectedFinalized<Animator>,
- public NameClient {
+class Animator final : public GarbageCollected<Animator>, public NameClient {
public:
Animator(v8::Isolate*,
AnimatorDefinition*,
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 85658f26e11..09bf9c6d352 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
@@ -21,7 +21,7 @@ class V8StateCallback;
// |AnimationWorkletGlobalScope::registerAnimator| to validate the provided
// Javascript class before completing the registration.
class MODULES_EXPORT AnimatorDefinition final
- : public GarbageCollectedFinalized<AnimatorDefinition>,
+ : public GarbageCollected<AnimatorDefinition>,
public NameClient {
public:
explicit AnimatorDefinition(V8AnimatorConstructor* constructor,
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 b0e5de5a844..2e0dd8354a9 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -571,6 +571,13 @@ bool WorkletAnimation::CanStartOnCompositor() {
if (!CheckElementComposited(target))
return false;
+ // If the scroll source is not composited, fall back to main thread.
+ if (timeline_->IsScrollTimeline() &&
+ !CheckElementComposited(
+ *ToScrollTimeline(timeline_)->ResolvedScrollSource())) {
+ return false;
+ }
+
return true;
}
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 fb79cdf8edc..1eeba64de51 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
@@ -31,8 +31,14 @@ ComputedEffectTiming* WorkletAnimationEffect::getComputedTiming() const {
last_update_time_ = local_time;
if (needs_update) {
+ // The playback rate is needed to calculate whether the effect is current or
+ // not (https://drafts.csswg.org/web-animations-1/#current). Since we only
+ // use this information to create a ComputedEffectTiming, which does not
+ // include that information, we do not need to supply one.
+ base::Optional<double> playback_rate = base::nullopt;
calculated_ = specified_timing_.CalculateTimings(
- local_time, Timing::AnimationDirection::kForwards, false);
+ local_time, Timing::AnimationDirection::kForwards, false,
+ playback_rate);
}
return specified_timing_.getComputedTiming(calculated_,
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 1c6f5178629..f4870f4290e 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
@@ -89,7 +89,8 @@ class WorkletAnimationTest : public RenderingTest {
void SetUp() override {
RenderingTest::SetUp();
element_ = GetDocument().CreateElementForBinding("test");
- // Animator has to be registored before constructing WorkletAnimation. For
+ GetDocument().body()->appendChild(element_);
+ // Animator has to be registered before constructing WorkletAnimation. For
// unit test this is faked by adding the animator name to
// WorkletAnimationController.
animator_name_ = "WorkletAnimationTest";
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
index 6fcf88be3db..f974bc49147 100644
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
+++ b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
@@ -18,7 +18,7 @@ class HTMLMediaElement;
class ScriptState;
class MODULES_EXPORT HTMLMediaElementAudioOutputDevice final
- : public GarbageCollectedFinalized<HTMLMediaElementAudioOutputDevice>,
+ : public GarbageCollected<HTMLMediaElementAudioOutputDevice>,
public Supplement<HTMLMediaElement> {
USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElementAudioOutputDevice);
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
index f88536db6be..dd17dd1a725 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
@@ -25,7 +25,7 @@ class BackgroundFetchRegistration;
// connection to the BackgroundFetchService. It's keyed on an active Service
// Worker Registration.
class BackgroundFetchBridge final
- : public GarbageCollectedFinalized<BackgroundFetchBridge>,
+ : public GarbageCollected<BackgroundFetchBridge>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(BackgroundFetchBridge);
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
index 5f50663ec8d..d41ace1757b 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_EVENT_H_
-#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-blink.h"
+#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
index c6ee8d864d4..3b425340c30 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
@@ -14,7 +14,7 @@ namespace blink {
class BackgroundFetchBridge;
class MODULES_EXPORT BackgroundFetchIconLoader final
- : public GarbageCollectedFinalized<BackgroundFetchIconLoader> {
+ : public GarbageCollected<BackgroundFetchIconLoader> {
public:
// The bitmap may be empty if the request failed or the image data could not
// be decoded. The int64_t returned is the scale of the ideal to chosen icon,
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 092f5a3bdb3..7a1464a97b8 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
@@ -8,6 +8,7 @@
#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/modules/v8/request_or_usv_string_or_request_or_usv_string_sequence.h"
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 01592306e7f..49cd93c6a56 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
@@ -184,7 +184,7 @@ TEST_F(BackgroundFetchManagerTest, BlobsExtracted) {
RequestInit* request_init = RequestInit::Create();
request_init->setMethod("POST");
request_init->setBody(blink::ScriptValue(
- scope.GetScriptState(), ToV8(body_text, scope.GetScriptState())));
+ scope.GetIsolate(), ToV8(body_text, scope.GetScriptState())));
Request* image_request =
Request::Create(scope.GetScriptState(), image_url.GetString(),
request_init, scope.GetExceptionState());
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 63e740a0573..08cb59a00ea 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
@@ -71,8 +71,11 @@ void BackgroundFetchRegistration::Initialize(
registration_ = registration;
registration_service_.Bind(std::move(registration_service));
- auto task_runner =
- GetExecutionContext()->GetTaskRunner(TaskType::kBackgroundFetch);
+ ExecutionContext* context = GetExecutionContext();
+ if (!context || context->IsContextDestroyed())
+ return;
+
+ auto task_runner = context->GetTaskRunner(TaskType::kBackgroundFetch);
registration_service_->AddRegistrationObserver(
observer_receiver_.BindNewPipeAndPassRemote(task_runner));
}
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h
index 7e5aba36679..8a491c15e9e 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_event.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_UPDATE_UI_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_UPDATE_UI_EVENT_H_
-#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-blink.h"
+#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h b/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
index 6e6d12f938a..abd4ce489da 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
@@ -16,8 +16,7 @@ namespace blink {
class BackgroundFetchManager;
class ServiceWorkerRegistrationBackgroundFetch final
- : public GarbageCollectedFinalized<
- ServiceWorkerRegistrationBackgroundFetch>,
+ : public GarbageCollected<ServiceWorkerRegistrationBackgroundFetch>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistrationBackgroundFetch);
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
index 6c3c435eecb..ba2920e3d98 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
+++ b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
@@ -17,7 +17,7 @@ class SyncManager;
class ServiceWorkerRegistration;
class ServiceWorkerRegistrationSync final
- : public GarbageCollectedFinalized<ServiceWorkerRegistrationSync>,
+ : public GarbageCollected<ServiceWorkerRegistrationSync>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistrationSync);
diff --git a/chromium/third_party/blink/renderer/modules/badging/BUILD.gn b/chromium/third_party/blink/renderer/modules/badging/BUILD.gn
index 8af60813b49..0e248dc70ea 100644
--- a/chromium/third_party/blink/renderer/modules/badging/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/badging/BUILD.gn
@@ -6,7 +6,7 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("badging") {
sources = [
- "badge.cc",
- "badge.h",
+ "navigator_badge.cc",
+ "navigator_badge.h",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/badging/badge.cc b/chromium/third_party/blink/renderer/modules/badging/badge.cc
deleted file mode 100644
index 8471c032e7c..00000000000
--- a/chromium/third_party/blink/renderer/modules/badging/badge.cc
+++ /dev/null
@@ -1,98 +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/modules/badging/badge.h"
-
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/badging/badge_options.h"
-#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-const char Badge::kSupplementName[] = "Badge";
-
-Badge::~Badge() = default;
-
-// static
-Badge* Badge::From(ExecutionContext* context) {
- Badge* supplement = Supplement<ExecutionContext>::From<Badge>(context);
- if (!supplement) {
- supplement = MakeGarbageCollected<Badge>(context);
- ProvideTo(*context, supplement);
- }
- return supplement;
-}
-
-// static
-void Badge::set(ScriptState* script_state, ExceptionState& exception_state) {
- Badge::set(script_state, BadgeOptions::Create(), exception_state);
-}
-
-// static
-void Badge::set(ScriptState* script_state,
- const BadgeOptions* options,
- ExceptionState& exception_state) {
- BadgeFromState(script_state)
- ->SetBadge(options->scope(), mojom::blink::BadgeValue::NewFlag(0));
-}
-
-// static
-void Badge::set(ScriptState* script_state,
- uint64_t content,
- ExceptionState& exception_state) {
- Badge::set(script_state, content, BadgeOptions::Create(), exception_state);
-}
-
-// static
-void Badge::set(ScriptState* script_state,
- uint64_t content,
- const BadgeOptions* options,
- ExceptionState& exception_state) {
- if (content == 0) {
- Badge::clear(script_state, options);
- } else {
- BadgeFromState(script_state)
- ->SetBadge(options->scope(),
- mojom::blink::BadgeValue::NewNumber(content));
- }
-}
-
-// static
-void Badge::clear(ScriptState* script_state, const BadgeOptions* options) {
- BadgeFromState(script_state)->ClearBadge(options->scope());
-}
-
-void Badge::SetBadge(WTF::String scope, mojom::blink::BadgeValuePtr value) {
- // Resolve |scope| against the URL of the current document/worker.
- KURL scope_url = KURL(execution_context_->Url(), scope);
- badge_service_->SetBadge(scope_url, std::move(value));
-}
-
-void Badge::ClearBadge(WTF::String scope) {
- // Resolve |scope| against the URL of the current document/worker.
- badge_service_->ClearBadge(KURL(execution_context_->Url(), scope));
-}
-
-void Badge::Trace(blink::Visitor* visitor) {
- Supplement<ExecutionContext>::Trace(visitor);
- ScriptWrappable::Trace(visitor);
-
- visitor->Trace(execution_context_);
-}
-
-Badge::Badge(ExecutionContext* context) : execution_context_(context) {
- context->GetInterfaceProvider()->GetInterface(
- badge_service_.BindNewPipeAndPassReceiver());
- DCHECK(badge_service_);
-}
-
-// static
-Badge* Badge::BadgeFromState(ScriptState* script_state) {
- return Badge::From(ExecutionContext::From(script_state));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/badging/badge.h b/chromium/third_party/blink/renderer/modules/badging/badge.h
deleted file mode 100644
index 02658859f20..00000000000
--- a/chromium/third_party/blink/renderer/modules/badging/badge.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
-
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/badging/badging.mojom-blink.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 BadgeOptions;
-class ExceptionState;
-class ExecutionContext;
-class ScriptState;
-
-class Badge final : public ScriptWrappable,
- public Supplement<ExecutionContext> {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(Badge);
-
- public:
- static const char kSupplementName[];
-
- static Badge* From(ExecutionContext*);
-
- explicit Badge(ExecutionContext*);
- ~Badge() override;
-
- // Badge IDL interface.
- static void set(ScriptState*, const BadgeOptions*, ExceptionState&);
- static void set(ScriptState*,
- uint64_t content,
- const BadgeOptions*,
- ExceptionState&);
- static void set(ScriptState*, ExceptionState&);
- static void set(ScriptState*, uint64_t content, ExceptionState&);
- static void clear(ScriptState*, const BadgeOptions*);
-
- void SetBadge(WTF::String scope, mojom::blink::BadgeValuePtr value);
- void ClearBadge(WTF::String scope);
-
- void Trace(blink::Visitor*) override;
-
- private:
- static Badge* BadgeFromState(ScriptState* script_state);
-
- mojo::Remote<blink::mojom::blink::BadgeService> badge_service_;
- Member<ExecutionContext> execution_context_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_BADGE_H_
diff --git a/chromium/third_party/blink/renderer/modules/badging/badge_options.idl b/chromium/third_party/blink/renderer/modules/badging/badge_options.idl
deleted file mode 100644
index 279519c2199..00000000000
--- a/chromium/third_party/blink/renderer/modules/badging/badge_options.idl
+++ /dev/null
@@ -1,12 +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.
-
-// The options used to decide how to apply a badge.
-// See the explainer https://github.com/WICG/badging/blob/master/explainer.md
-dictionary BadgeOptions {
- // The scope of the badge. This is resolved against the URL of the current
- // page.
- // https://github.com/WICG/badging/blob/master/explainer.md#badge-scope
- DOMString scope = "/";
-}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/badging/experimental_badge.idl b/chromium/third_party/blink/renderer/modules/badging/experimental_badge.idl
deleted file mode 100644
index 3e84590f40e..00000000000
--- a/chromium/third_party/blink/renderer/modules/badging/experimental_badge.idl
+++ /dev/null
@@ -1,17 +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.
-
-// TODO(estevenson): Add link to spec once complete.
-// https://github.com/WICG/badging/blob/master/explainer.md
-
-[
- RuntimeEnabled=Badging,
- // TODO(estevenson): Expose the Badge interface to Worker.
- Exposed=Window,
- ImplementedAs=Badge
-] interface ExperimentalBadge {
- [CallWith=ScriptState, RaisesException, MeasureAs=BadgeSet]
- static void set(optional [EnforceRange] unsigned long long contents, optional BadgeOptions options);
- [CallWith=ScriptState, MeasureAs=BadgeClear] static void clear(optional BadgeOptions options);
-};
diff --git a/chromium/third_party/blink/renderer/modules/badging/navigator_badge.cc b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.cc
new file mode 100644
index 00000000000..a6f540dcc9b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file
+
+#include "third_party/blink/renderer/modules/badging/navigator_badge.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/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+
+namespace blink {
+
+const char NavigatorBadge::kSupplementName[] = "NavigatorBadge";
+
+// static
+NavigatorBadge& NavigatorBadge::From(ScriptState* script_state) {
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ NavigatorBadge* supplement =
+ Supplement<ExecutionContext>::From<NavigatorBadge>(context);
+ if (!supplement) {
+ supplement = MakeGarbageCollected<NavigatorBadge>(context);
+ ProvideTo(*context, supplement);
+ }
+ return *supplement;
+}
+
+NavigatorBadge::NavigatorBadge(ExecutionContext* context) {
+ context->GetBrowserInterfaceBroker().GetInterface(
+ badge_service_.BindNewPipeAndPassReceiver());
+ DCHECK(badge_service_);
+}
+
+// static
+ScriptPromise NavigatorBadge::setAppBadge(ScriptState* script_state,
+ Navigator& /*navigator*/) {
+ From(script_state)
+ .badge_service_->SetBadge(mojom::blink::BadgeValue::NewFlag(0));
+ return ScriptPromise::CastUndefined(script_state);
+}
+
+// static
+ScriptPromise NavigatorBadge::setAppBadge(ScriptState* script_state,
+ Navigator& navigator,
+ uint64_t content) {
+ if (content == 0)
+ return NavigatorBadge::clearAppBadge(script_state, navigator);
+
+ From(script_state)
+ .badge_service_->SetBadge(mojom::blink::BadgeValue::NewNumber(content));
+ return ScriptPromise::CastUndefined(script_state);
+}
+
+// static
+ScriptPromise NavigatorBadge::clearAppBadge(ScriptState* script_state,
+ Navigator& /*navigator*/) {
+ From(script_state).badge_service_->ClearBadge();
+ return ScriptPromise::CastUndefined(script_state);
+}
+
+void NavigatorBadge::Trace(blink::Visitor* visitor) {
+ Supplement<ExecutionContext>::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/badging/navigator_badge.h b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.h
new file mode 100644
index 00000000000..e806dce5df3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.h
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_NAVIGATOR_BADGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_NAVIGATOR_BADGE_H_
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/badging/badging.mojom-blink.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+class ScriptPromise;
+
+class NavigatorBadge final : public GarbageCollected<NavigatorBadge>,
+ public Supplement<ExecutionContext> {
+ USING_GARBAGE_COLLECTED_MIXIN(NavigatorBadge);
+
+ public:
+ static const char kSupplementName[];
+
+ static NavigatorBadge& From(ScriptState*);
+ explicit NavigatorBadge(ExecutionContext*);
+
+ // Badge IDL interface.
+ static ScriptPromise setAppBadge(ScriptState*, Navigator&);
+ static ScriptPromise setAppBadge(ScriptState*, Navigator&, uint64_t content);
+ static ScriptPromise clearAppBadge(ScriptState*, Navigator&);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ mojo::Remote<blink::mojom::blink::BadgeService> badge_service_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BADGING_NAVIGATOR_BADGE_H_
diff --git a/chromium/third_party/blink/renderer/modules/badging/navigator_badge.idl b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.idl
new file mode 100644
index 00000000000..a115a8e06a0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/badging/navigator_badge.idl
@@ -0,0 +1,16 @@
+// 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://wicg.github.io/badging/
+[
+ SecureContext,
+ RuntimeEnabled=Badging,
+ ImplementedAs=NavigatorBadge
+] partial interface Navigator {
+ [CallWith=ScriptState, MeasureAs=BadgeSet, ImplementedAs=setAppBadge]
+ Promise<void> setExperimentalAppBadge(optional [EnforceRange] unsigned long long contents);
+
+ [CallWith=ScriptState, MeasureAs=BadgeClear, ImplementedAs=clearAppBadge]
+ Promise<void> clearExperimentalAppBadge();
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
index 9f0dc995b00..83c547016a7 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
@@ -47,8 +47,9 @@ void BatteryDispatcher::UpdateBatteryStatus(
void BatteryDispatcher::StartListening(LocalFrame* frame) {
DCHECK(!monitor_.is_bound());
// See https://bit.ly/2S0zRAS for task types.
- Platform::Current()->GetInterfaceProvider()->GetInterface(mojo::MakeRequest(
- &monitor_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ Platform::Current()->GetInterfaceProvider()->GetInterface(
+ monitor_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
QueryNextStatus();
}
diff --git a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
index 3d6a057f1de..20a75a80ccd 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BATTERY_BATTERY_DISPATCHER_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/battery_monitor.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
#include "third_party/blink/renderer/modules/battery/battery_manager.h"
@@ -15,7 +16,7 @@
namespace blink {
class MODULES_EXPORT BatteryDispatcher final
- : public GarbageCollectedFinalized<BatteryDispatcher>,
+ : public GarbageCollected<BatteryDispatcher>,
public PlatformEventDispatcher {
USING_GARBAGE_COLLECTED_MIXIN(BatteryDispatcher);
@@ -37,7 +38,7 @@ class MODULES_EXPORT BatteryDispatcher final
void StartListening(LocalFrame* frame) override;
void StopListening() override;
- device::mojom::blink::BatteryMonitorPtr monitor_;
+ mojo::Remote<device::mojom::blink::BatteryMonitor> monitor_;
BatteryStatus battery_status_;
bool has_latest_data_;
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 57ba79dcb88..45482512bbd 100644
--- a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h
+++ b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.h
@@ -16,7 +16,7 @@ class ExceptionState;
class KURL;
class ArrayBufferViewOrBlobOrStringOrFormData;
-class NavigatorBeacon final : public GarbageCollectedFinalized<NavigatorBeacon>,
+class NavigatorBeacon final : public GarbageCollected<NavigatorBeacon>,
public Supplement<Navigator> {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorBeacon);
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index 5cdce3a8c4a..44fb0989676 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -6,7 +6,12 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.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/bluetooth/web_bluetooth.mojom-blink.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"
@@ -149,7 +154,7 @@ ScriptPromise Bluetooth::getAvailability(ScriptState* script_state) {
}
CHECK(context->IsSecureContext());
- EnsureServiceConnection();
+ EnsureServiceConnection(context);
// Subsequent steps are handled in the browser process.
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -183,7 +188,12 @@ void Bluetooth::RequestDeviceCallback(
ScriptPromise Bluetooth::requestDevice(ScriptState* script_state,
const RequestDeviceOptions* options,
ExceptionState& exception_state) {
- ExecutionContext* context = ExecutionContext::From(script_state);
+ ExecutionContext* context = GetExecutionContext();
+ if (!context) {
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), kInactiveDocumentError));
+ }
// Remind developers when they are using Web Bluetooth on unsupported platforms.
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \
@@ -216,7 +226,7 @@ ScriptPromise Bluetooth::requestDevice(ScriptState* script_state,
"Must be handling a user gesture to show a permission request."));
}
- EnsureServiceConnection();
+ EnsureServiceConnection(context);
// In order to convert the arguments from service names and aliases to just
// UUIDs, do the following substeps:
@@ -278,7 +288,7 @@ static void ConvertRequestLEScanOptions(
void Bluetooth::RequestScanningCallback(
ScriptPromiseResolver* resolver,
- mojo::BindingId id,
+ mojo::ReceiverId id,
mojom::blink::RequestScanningStartResultPtr result) {
if (!resolver->GetExecutionContext() ||
resolver->GetExecutionContext()->IsContextDestroyed()) {
@@ -300,8 +310,12 @@ void Bluetooth::RequestScanningCallback(
ScriptPromise Bluetooth::requestLEScan(ScriptState* script_state,
const BluetoothLEScanOptions* options,
ExceptionState& exception_state) {
- ExecutionContext* context = ExecutionContext::From(script_state);
- DCHECK(context);
+ ExecutionContext* context = GetExecutionContext();
+ if (!context) {
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), kInactiveDocumentError));
+ }
// Remind developers when they are using Web Bluetooth on unsupported
// platforms.
@@ -332,7 +346,7 @@ ScriptPromise Bluetooth::requestLEScan(ScriptState* script_state,
"Must be handling a user gesture to show a permission request."));
}
- EnsureServiceConnection();
+ EnsureServiceConnection(context);
auto scan_options = mojom::blink::WebBluetoothRequestLEScanOptions::New();
ConvertRequestLEScanOptions(options, scan_options, exception_state);
@@ -347,11 +361,11 @@ ScriptPromise Bluetooth::requestLEScan(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- mojom::blink::WebBluetoothScanClientAssociatedPtrInfo client;
+ mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothScanClient> client;
// See https://bit.ly/2S0zRAS for task types.
- mojo::BindingId id = client_bindings_.AddBinding(
- this, mojo::MakeRequest(&client),
- context->GetTaskRunner(TaskType::kMiscPlatformAPI));
+ mojo::ReceiverId id =
+ client_receivers_.Add(this, client.InitWithNewEndpointAndPassReceiver(),
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI));
service_->RequestScanningStart(
std::move(client), std::move(scan_options),
@@ -399,15 +413,15 @@ void Bluetooth::ScanEvent(mojom::blink::WebBluetoothScanResultPtr result) {
}
void Bluetooth::PageVisibilityChanged() {
- client_bindings_.CloseAllBindings();
+ client_receivers_.Clear();
}
-void Bluetooth::CancelScan(mojo::BindingId id) {
- client_bindings_.RemoveBinding(id);
+void Bluetooth::CancelScan(mojo::ReceiverId id) {
+ client_receivers_.Remove(id);
}
-bool Bluetooth::IsScanActive(mojo::BindingId id) const {
- return client_bindings_.HasBinding(id);
+bool Bluetooth::IsScanActive(mojo::ReceiverId id) const {
+ return client_receivers_.HasReceiver(id);
}
const WTF::AtomicString& Bluetooth::InterfaceName() const {
@@ -419,7 +433,7 @@ ExecutionContext* Bluetooth::GetExecutionContext() const {
}
void Bluetooth::ContextDestroyed(ExecutionContext*) {
- client_bindings_.CloseAllBindings();
+ client_receivers_.Clear();
}
void Bluetooth::Trace(blink::Visitor* visitor) {
@@ -434,7 +448,7 @@ Bluetooth::Bluetooth(ExecutionContext* context)
PageVisibilityObserver(To<Document>(context)->GetPage()) {}
Bluetooth::~Bluetooth() {
- DCHECK(client_bindings_.empty());
+ DCHECK(client_receivers_.empty());
}
BluetoothDevice* Bluetooth::GetBluetoothDeviceRepresentingDevice(
@@ -451,15 +465,12 @@ BluetoothDevice* Bluetooth::GetBluetoothDeviceRepresentingDevice(
return device;
}
-void Bluetooth::EnsureServiceConnection() {
+void Bluetooth::EnsureServiceConnection(ExecutionContext* context) {
if (!service_) {
// See https://bit.ly/2S0zRAS for task types.
- auto* context = GetExecutionContext();
- DCHECK(context);
-
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
- context->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&service_, task_runner));
+ context->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(task_runner));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.h
index ac568359bfb..2162844de66 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.h
@@ -5,8 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_H_
-#include <memory>
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_device.h"
@@ -61,8 +63,8 @@ class Bluetooth final : public EventTargetWithInlineData,
// PageVisibilityObserver
void PageVisibilityChanged() override;
- void CancelScan(mojo::BindingId);
- bool IsScanActive(mojo::BindingId) const;
+ void CancelScan(mojo::ReceiverId);
+ bool IsScanActive(mojo::ReceiverId) const;
private:
BluetoothDevice* GetBluetoothDeviceRepresentingDevice(
@@ -74,20 +76,20 @@ class Bluetooth final : public EventTargetWithInlineData,
mojom::blink::WebBluetoothDevicePtr);
void RequestScanningCallback(ScriptPromiseResolver*,
- mojo::BindingId id,
+ mojo::ReceiverId id,
mojom::blink::RequestScanningStartResultPtr);
- void EnsureServiceConnection();
+ void EnsureServiceConnection(ExecutionContext*);
// Map of device ids to BluetoothDevice objects.
// Ensures only one BluetoothDevice instance represents each
// Bluetooth device inside a single global object.
HeapHashMap<String, Member<BluetoothDevice>> device_instance_map_;
- mojo::AssociatedBindingSet<mojom::blink::WebBluetoothScanClient>
- client_bindings_;
+ mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothScanClient>
+ client_receivers_;
- mojom::blink::WebBluetoothServicePtr service_;
+ mojo::Remote<mojom::blink::WebBluetoothService> service_;
};
} // 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 985e4b43d98..8daeae6fd0e 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_DEVICE_H_
#include <memory>
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/execution_context/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_error.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
index a4027a7eca5..842bc68ed05 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.h
index a88450063b5..2a6ba1e1fdf 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_ERROR_H_
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.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 8f3edbbe322..017c0d3e6ae 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
@@ -4,10 +4,12 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
namespace blink {
BluetoothLEScan::BluetoothLEScan(
- mojo::BindingId id,
+ mojo::ReceiverId id,
Bluetooth* bluetooth,
mojom::blink::WebBluetoothRequestLEScanOptionsPtr options)
: id_(id),
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
index 943627140a7..0fb2bf26b1d 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_LE_SCAN_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_LE_SCAN_H_
+#include "mojo/public/cpp/bindings/receiver_set.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan_filter_init.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -16,7 +17,7 @@ class BluetoothLEScan final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- BluetoothLEScan(mojo::BindingId,
+ BluetoothLEScan(mojo::ReceiverId,
Bluetooth*,
mojom::blink::WebBluetoothRequestLEScanOptionsPtr);
@@ -31,7 +32,7 @@ class BluetoothLEScan final : public ScriptWrappable {
void Trace(blink::Visitor*) override;
private:
- mojo::BindingId id_;
+ mojo::ReceiverId id_;
HeapVector<Member<BluetoothLEScanFilterInit>> filters_;
Member<Bluetooth> bluetooth_;
const bool keep_repeated_devices_;
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 e73dc5f8ad8..0eb9959573c 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
@@ -6,7 +6,9 @@
#include <utility>
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.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/dom/dom_exception.h"
@@ -55,7 +57,7 @@ void BluetoothRemoteGATTCharacteristic::ContextDestroyed(ExecutionContext*) {
}
void BluetoothRemoteGATTCharacteristic::Dispose() {
- client_bindings_.CloseAllBindings();
+ receivers_.Clear();
}
const WTF::AtomicString& BluetoothRemoteGATTCharacteristic::InterfaceName()
@@ -255,15 +257,15 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::startNotifications(
mojom::blink::WebBluetoothService* service =
device_->GetBluetooth()->Service();
- mojom::blink::WebBluetoothCharacteristicClientAssociatedPtrInfo ptr_info;
- auto request = mojo::MakeRequest(&ptr_info);
+ mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothCharacteristicClient>
+ client;
// See https://bit.ly/2S0zRAS for task types.
- client_bindings_.AddBinding(
- this, std::move(request),
+ receivers_.Add(
+ this, client.InitWithNewEndpointAndPassReceiver(),
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI));
service->RemoteCharacteristicStartNotifications(
- characteristic_->instance_id, std::move(ptr_info),
+ characteristic_->instance_id, std::move(client),
WTF::Bind(&BluetoothRemoteGATTCharacteristic::NotificationsCallback,
WrapPersistent(this), WrapPersistent(resolver)));
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 ef53c8cc697..fbe7df6c7ce 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
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#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/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
@@ -133,8 +133,8 @@ class BluetoothRemoteGATTCharacteristic final
Member<BluetoothCharacteristicProperties> properties_;
Member<DOMDataView> value_;
Member<BluetoothDevice> device_;
- mojo::AssociatedBindingSet<mojom::blink::WebBluetoothCharacteristicClient>
- client_bindings_;
+ mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothCharacteristicClient>
+ receivers_;
};
} // 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 dc809116964..a74a57460da 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
@@ -5,7 +5,10 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h"
#include <utility>
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -75,7 +78,7 @@ void BluetoothRemoteGATTServer::Dispose() {
DisconnectIfConnected();
// The pipe to this object must be closed when is marked unreachable to
// prevent messages from being dispatched before lazy sweeping.
- client_bindings_.CloseAllBindings();
+ client_receivers_.Clear();
}
void BluetoothRemoteGATTServer::Trace(blink::Visitor* visitor) {
@@ -106,15 +109,15 @@ ScriptPromise BluetoothRemoteGATTServer::connect(ScriptState* script_state) {
mojom::blink::WebBluetoothService* service =
device_->GetBluetooth()->Service();
- mojom::blink::WebBluetoothServerClientAssociatedPtrInfo ptr_info;
+ mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothServerClient> client;
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- auto request = mojo::MakeRequest(&ptr_info);
- client_bindings_.AddBinding(this, std::move(request), std::move(task_runner));
+ client_receivers_.Add(this, client.InitWithNewEndpointAndPassReceiver(),
+ std::move(task_runner));
service->RemoteServerConnect(
- device_->id(), std::move(ptr_info),
+ device_->id(), std::move(client),
WTF::Bind(&BluetoothRemoteGATTServer::ConnectCallback,
WrapPersistent(this), WrapPersistent(resolver)));
@@ -125,7 +128,7 @@ void BluetoothRemoteGATTServer::disconnect(ScriptState* script_state) {
if (!connected_)
return;
CleanupDisconnectedDeviceAndFireEvent();
- client_bindings_.CloseAllBindings();
+ client_receivers_.Clear();
mojom::blink::WebBluetoothService* service =
device_->GetBluetooth()->Service();
service->RemoteServerDisconnect(device_->id());
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 62d24b336d6..73c60c1f90f 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.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/core/execution_context/context_lifecycle_observer.h"
@@ -108,8 +108,8 @@ class BluetoothRemoteGATTServer
// using this server’s connection.
HeapHashSet<Member<ScriptPromiseResolver>> active_algorithms_;
- mojo::AssociatedBindingSet<mojom::blink::WebBluetoothServerClient>
- client_bindings_;
+ mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothServerClient>
+ client_receivers_;
Member<BluetoothDevice> device_;
bool connected_;
@@ -117,4 +117,4 @@ class BluetoothRemoteGATTServer
} // namespace blink
-#endif // BluetoothDevice_h
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
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 9feec686021..4b351c0cf85 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,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_H_
#include <memory>
-#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.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/modules/bluetooth/bluetooth_device.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc b/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
index e963f704969..683099a37e8 100644
--- a/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
+++ b/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -39,6 +41,15 @@ GetThreadSpecificProvider() {
BroadcastChannel* BroadcastChannel::Create(ExecutionContext* execution_context,
const String& name,
ExceptionState& exception_state) {
+ // Record BroadcastChannel usage in third party context. Don't record if the
+ // frame is same-origin to the top frame, or if we can't tell whether the
+ // frame was ever cross-origin or not.
+ Document* document = DynamicTo<Document>(execution_context);
+ if (document && document->TopFrameOrigin() &&
+ !document->TopFrameOrigin()->CanAccess(document->GetSecurityOrigin())) {
+ UseCounter::Count(document, WebFeature::kThirdPartyBroadcastChannel);
+ }
+
if (execution_context->GetSecurityOrigin()->IsOpaque()) {
// TODO(mek): Decide what to do here depending on
// https://github.com/whatwg/html/issues/1319
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/BUILD.gn b/chromium/third_party/blink/renderer/modules/cache_storage/BUILD.gn
index b221c1559e9..af99e71f534 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/BUILD.gn
@@ -10,10 +10,14 @@ blink_modules_sources("cache_storage") {
"cache.h",
"cache_storage.cc",
"cache_storage.h",
+ "cache_storage_blob_client_list.cc",
+ "cache_storage_blob_client_list.h",
"cache_storage_error.cc",
"cache_storage_error.h",
"cache_storage_trace_utils.cc",
"cache_storage_trace_utils.h",
+ "cache_utils.cc",
+ "cache_utils.h",
"global_cache_storage.cc",
"global_cache_storage.h",
"inspector_cache_storage_agent.cc",
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 35a05fea672..ff092dcb411 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -7,12 +7,9 @@
#include <memory>
#include <utility>
-#include "base/feature_list.h"
#include "base/optional.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/service_worker/service_worker_utils.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
@@ -33,8 +30,10 @@
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage.h"
+#include "third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_error.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h"
+#include "third_party/blink/renderer/modules/cache_storage/cache_utils.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -44,11 +43,11 @@
#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/loader/fetch/cached_metadata.h"
+#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -76,38 +75,22 @@ bool HasJavascriptMimeType(const Response* response) {
return MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type);
}
-enum class CodeCacheGenerateTiming {
- kDontGenerate,
- kGenerateNow,
- kGenerateWhenIdle,
-};
-
-CodeCacheGenerateTiming ShouldGenerateV8CodeCache(ScriptState* script_state,
- const Response* response) {
- EagerCodeCacheStrategy strategy =
- ServiceWorkerUtils::GetEagerCodeCacheStrategy();
- if (strategy == EagerCodeCacheStrategy::kDontGenerate)
- return CodeCacheGenerateTiming::kDontGenerate;
-
+bool ShouldGenerateV8CodeCache(ScriptState* script_state,
+ const Response* response) {
ExecutionContext* context = ExecutionContext::From(script_state);
auto* global_scope = DynamicTo<ServiceWorkerGlobalScope>(context);
if (!global_scope)
- return CodeCacheGenerateTiming::kDontGenerate;
+ return false;
+
+ if (!global_scope->IsInstalling())
+ return false;
if (!HasJavascriptMimeType(response))
- return CodeCacheGenerateTiming::kDontGenerate;
+ return false;
if (!response->InternalBodyBuffer())
- return CodeCacheGenerateTiming::kDontGenerate;
-
- if (global_scope->IsInstalling())
- return CodeCacheGenerateTiming::kGenerateNow;
-
- if (strategy == EagerCodeCacheStrategy::kOnIdleTask) {
- return CodeCacheGenerateTiming::kGenerateWhenIdle;
- }
-
- return CodeCacheGenerateTiming::kDontGenerate;
+ return false;
+ return true;
}
} // namespace
@@ -161,7 +144,7 @@ class Cache::FetchResolvedForAdd final : public ScriptFunction {
if (exception_state.HadException()) {
ScriptPromise rejection =
ScriptPromise::Reject(GetScriptState(), exception_state);
- return ScriptValue(GetScriptState(), rejection.V8Value());
+ return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
}
for (const auto& response : responses) {
@@ -170,21 +153,21 @@ class Cache::FetchResolvedForAdd final : public ScriptFunction {
GetScriptState(),
V8ThrowException::CreateTypeError(GetScriptState()->GetIsolate(),
"Request failed"));
- return ScriptValue(GetScriptState(), rejection.V8Value());
+ return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
}
if (VaryHeaderContainsAsterisk(response)) {
ScriptPromise rejection = ScriptPromise::Reject(
GetScriptState(),
V8ThrowException::CreateTypeError(GetScriptState()->GetIsolate(),
"Vary header contains *"));
- return ScriptValue(GetScriptState(), rejection.V8Value());
+ return ScriptValue(GetScriptState()->GetIsolate(), rejection.V8Value());
}
}
ScriptPromise put_promise =
cache_->PutImpl(GetScriptState(), method_name_, requests_, responses,
exception_state, trace_id_);
- return ScriptValue(GetScriptState(), put_promise.V8Value());
+ return ScriptValue(GetScriptState()->GetIsolate(), put_promise.V8Value());
}
void Trace(blink::Visitor* visitor) override {
@@ -204,7 +187,7 @@ class Cache::FetchResolvedForAdd final : public ScriptFunction {
};
class Cache::BarrierCallbackForPut final
- : public GarbageCollectedFinalized<BarrierCallbackForPut> {
+ : public GarbageCollected<BarrierCallbackForPut> {
public:
BarrierCallbackForPut(wtf_size_t number_of_operations,
Cache* cache,
@@ -236,10 +219,10 @@ class Cache::BarrierCallbackForPut final
MaybeReportInstalledScripts();
int operation_count = batch_operations_.size();
DCHECK_GE(operation_count, 1);
- // Make sure to bind the Cache object to keep the mojo interface pointer
- // alive during the operation. Otherwise GC might prevent the callback
- // from ever being executed.
- cache_->cache_ptr_->Batch(
+ // Make sure to bind the Cache object to keep the mojo remote alive during
+ // the operation. Otherwise GC might prevent the callback from ever being
+ // executed.
+ cache_->cache_remote_->Batch(
std::move(batch_operations_), trace_id_,
WTF::Bind(
[](const String& method_name, ScriptPromiseResolver* resolver,
@@ -336,8 +319,8 @@ class Cache::BarrierCallbackForPut final
continue;
}
uint64_t side_data_blob_size =
- operation->response->side_data_blob
- ? operation->response->side_data_blob->size()
+ operation->response->side_data_blob_for_cache_put
+ ? operation->response->side_data_blob_for_cache_put->size()
: 0;
global_scope->CountCacheStorageInstalledScript(blob_data_handle->size(),
side_data_blob_size);
@@ -354,7 +337,7 @@ class Cache::BarrierCallbackForPut final
};
class Cache::BlobHandleCallbackForPut final
- : public GarbageCollectedFinalized<BlobHandleCallbackForPut>,
+ : public GarbageCollected<BlobHandleCallbackForPut>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(BlobHandleCallbackForPut);
@@ -400,33 +383,25 @@ class Cache::BlobHandleCallbackForPut final
};
class Cache::CodeCacheHandleCallbackForPut final
- : public GarbageCollectedFinalized<CodeCacheHandleCallbackForPut>,
+ : public GarbageCollected<CodeCacheHandleCallbackForPut>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(CodeCacheHandleCallbackForPut);
public:
CodeCacheHandleCallbackForPut(ScriptState* script_state,
- Cache* cache,
wtf_size_t index,
BarrierCallbackForPut* barrier_callback,
Request* request,
Response* response,
- CodeCacheGenerateTiming timing,
int64_t trace_id)
: script_state_(script_state),
- cache_(cache),
index_(index),
barrier_callback_(barrier_callback),
mime_type_(response->InternalMIMEType()),
- timing_(timing),
trace_id_(trace_id) {
fetch_api_request_ = request->CreateFetchAPIRequest();
fetch_api_response_ = response->PopulateFetchAPIResponse();
url_ = fetch_api_request_->url;
- opaque_mode_ = fetch_api_response_->response_type ==
- network::mojom::FetchResponseType::kOpaque
- ? V8CodeCache::OpaqueMode::kOpaque
- : V8CodeCache::OpaqueMode::kNotOpaque;
}
~CodeCacheHandleCallbackForPut() override = default;
@@ -437,7 +412,6 @@ class Cache::CodeCacheHandleCallbackForPut final
TRACE_ID_GLOBAL(trace_id_),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "url",
CacheStorageTracedValue(url_.GetString()));
- base::Time response_time = fetch_api_response_->response_time;
mojom::blink::BatchOperationPtr batch_operation =
mojom::blink::BatchOperation::New();
batch_operation->operation_type = mojom::blink::OperationType::kPut;
@@ -450,33 +424,18 @@ class Cache::CodeCacheHandleCallbackForPut final
batch_operation->response->blob = BlobDataHandle::Create(
std::move(blob_data), array_buffer->ByteLength());
- if (timing_ == CodeCacheGenerateTiming::kGenerateNow) {
- scoped_refptr<CachedMetadata> cached_metadata =
- GenerateFullCodeCache(array_buffer);
- if (cached_metadata) {
- base::span<const uint8_t> serialized_data =
- cached_metadata->SerializedData();
- auto side_data_blob_data = std::make_unique<BlobData>();
- side_data_blob_data->AppendBytes(serialized_data.data(),
- serialized_data.size());
-
- batch_operation->response->side_data_blob = BlobDataHandle::Create(
- std::move(side_data_blob_data), serialized_data.size());
- }
- } else {
- // Schedule an idle task to generate code cache later.
- ServiceWorkerGlobalScope* global_scope = GetServiceWorkerGlobalScope();
- if (global_scope) {
- auto* thread_scheduler =
- global_scope->GetScheduler()->GetWorkerThreadScheduler();
- DCHECK(thread_scheduler);
- int task_id = global_scope->WillStartTask();
- thread_scheduler->IdleTaskRunner()->PostIdleTask(
- FROM_HERE, WTF::Bind(&Cache::CodeCacheHandleCallbackForPut::
- GenerateCodeCacheOnIdleTask,
- WrapPersistent(this), task_id,
- WrapPersistent(array_buffer), response_time));
- }
+ scoped_refptr<CachedMetadata> cached_metadata =
+ GenerateFullCodeCache(array_buffer);
+ if (cached_metadata) {
+ base::span<const uint8_t> serialized_data =
+ cached_metadata->SerializedData();
+ auto side_data_blob_data = std::make_unique<BlobData>();
+ side_data_blob_data->AppendBytes(serialized_data.data(),
+ serialized_data.size());
+
+ batch_operation->response->side_data_blob_for_cache_put =
+ BlobDataHandle::Create(std::move(side_data_blob_data),
+ serialized_data.size());
}
barrier_callback_->OnSuccess(index_, std::move(batch_operation));
@@ -490,7 +449,6 @@ class Cache::CodeCacheHandleCallbackForPut final
void Trace(blink::Visitor* visitor) override {
visitor->Trace(script_state_);
- visitor->Trace(cache_);
visitor->Trace(barrier_callback_);
FetchDataLoader::Client::Trace(visitor);
}
@@ -528,45 +486,12 @@ class Cache::CodeCacheHandleCallbackForPut final
url_, text_decoder->Encoding(), opaque_mode_);
}
- void GenerateCodeCacheOnIdleTask(int task_id,
- DOMArrayBuffer* array_buffer,
- base::Time response_time,
- base::TimeTicks) {
- TRACE_EVENT_WITH_FLOW1(
- "CacheStorage",
- "Cache::CodeCacheHandleCallbackForPut::GenerateCodeCacheOnIdleTask",
- TRACE_ID_GLOBAL(trace_id_),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "url",
- CacheStorageTracedValue(url_.GetString()));
-
- ServiceWorkerGlobalScope* global_scope = GetServiceWorkerGlobalScope();
- if (!global_scope)
- return;
-
- scoped_refptr<CachedMetadata> cached_metadata =
- GenerateFullCodeCache(array_buffer);
- if (!cached_metadata) {
- global_scope->DidEndTask(task_id);
- return;
- }
- cache_->cache_ptr_->SetSideData(
- url_, response_time, cached_metadata->SerializedData(), trace_id_,
- WTF::Bind(
- [](ServiceWorkerGlobalScope* global_scope, int task_id,
- mojom::blink::CacheStorageError error) {
- global_scope->DidEndTask(task_id);
- },
- WrapPersistent(global_scope), task_id));
- }
-
const Member<ScriptState> script_state_;
- const Member<Cache> cache_;
const wtf_size_t index_;
Member<BarrierCallbackForPut> barrier_callback_;
const String mime_type_;
KURL url_;
V8CodeCache::OpaqueMode opaque_mode_;
- CodeCacheGenerateTiming timing_;
const int64_t trace_id_;
mojom::blink::FetchAPIRequestPtr fetch_api_request_;
@@ -697,14 +622,17 @@ ScriptPromise Cache::keys(ScriptState* script_state,
}
Cache::Cache(GlobalFetch::ScopedFetcher* fetcher,
- mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info,
+ mojo::PendingAssociatedRemote<mojom::blink::CacheStorageCache>
+ cache_pending_remote,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : scoped_fetcher_(fetcher) {
- cache_ptr_.Bind(std::move(cache_ptr_info), std::move(task_runner));
+ : scoped_fetcher_(fetcher),
+ blob_client_list_(MakeGarbageCollected<CacheStorageBlobClientList>()) {
+ cache_remote_.Bind(std::move(cache_pending_remote), std::move(task_runner));
}
void Cache::Trace(blink::Visitor* visitor) {
visitor->Trace(scoped_fetcher_);
+ visitor->Trace(blob_client_list_);
ScriptWrappable::Trace(visitor);
}
@@ -729,14 +657,20 @@ ScriptPromise Cache::MatchImpl(ScriptState* script_state,
return promise;
}
- // Make sure to bind the Cache object to keep the mojo interface pointer
- // alive during the operation. Otherwise GC might prevent the callback
- // from ever being executed.
- cache_ptr_->Match(
- std::move(mojo_request), std::move(mojo_options), trace_id,
+ bool in_related_fetch_event = false;
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ if (auto* global_scope = DynamicTo<ServiceWorkerGlobalScope>(context))
+ in_related_fetch_event = global_scope->HasRelatedFetchEvent(request->url());
+
+ // Make sure to bind the Cache object to keep the mojo remote alive during
+ // the operation. Otherwise GC might prevent the callback from ever being
+ // executed.
+ cache_remote_->Match(
+ std::move(mojo_request), std::move(mojo_options), in_related_fetch_event,
+ trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
- const CacheQueryOptions* options, int64_t trace_id, Cache* _,
+ const CacheQueryOptions* options, int64_t trace_id, Cache* self,
mojom::blink::MatchResultPtr result) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
UMA_HISTOGRAM_LONG_TIMES("ServiceWorkerCache.Cache.Renderer.Match",
@@ -766,15 +700,29 @@ ScriptPromise Cache::MatchImpl(ScriptState* script_state,
break;
}
} else {
- TRACE_EVENT_WITH_FLOW1(
- "CacheStorage", "Cache::MatchImpl::Callback",
- TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
- "response", CacheStorageTracedValue(result->get_response()));
UMA_HISTOGRAM_LONG_TIMES(
"ServiceWorkerCache.Cache.Renderer.Match.Hit", elapsed);
ScriptState::Scope scope(resolver->GetScriptState());
- resolver->Resolve(Response::Create(resolver->GetScriptState(),
- *result->get_response()));
+ if (result->is_eager_response()) {
+ TRACE_EVENT_WITH_FLOW1(
+ "CacheStorage", "Cache::MatchImpl::Callback",
+ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
+ "eager_response",
+ CacheStorageTracedValue(
+ result->get_eager_response()->response));
+ resolver->Resolve(
+ CreateEagerResponse(resolver->GetScriptState(),
+ std::move(result->get_eager_response()),
+ self->blob_client_list_));
+ } else {
+ TRACE_EVENT_WITH_FLOW1(
+ "CacheStorage", "Cache::MatchImpl::Callback",
+ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
+ "response",
+ CacheStorageTracedValue(result->get_response()));
+ resolver->Resolve(Response::Create(resolver->GetScriptState(),
+ *result->get_response()));
+ }
}
},
WrapPersistent(resolver), base::TimeTicks::Now(),
@@ -808,10 +756,10 @@ ScriptPromise Cache::MatchAllImpl(ScriptState* script_state,
return promise;
}
- // Make sure to bind the Cache object to keep the mojo interface pointer
- // alive during the operation. Otherwise GC might prevent the callback
- // from ever being executed.
- cache_ptr_->MatchAll(
+ // Make sure to bind the Cache object to keep the mojo remote alive during
+ // the operation. Otherwise GC might prevent the callback from ever being
+ // executed.
+ cache_remote_->MatchAll(
std::move(fetch_api_request), std::move(mojo_options), trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
@@ -864,7 +812,7 @@ ScriptPromise Cache::AddAllImpl(ScriptState* script_state,
HeapVector<RequestInfo> request_infos;
request_infos.resize(requests.size());
- Vector<ScriptPromise> promises;
+ HeapVector<ScriptPromise> promises;
promises.resize(requests.size());
for (wtf_size_t i = 0; i < requests.size(); ++i) {
if (!requests[i]->url().ProtocolIsInHTTPFamily()) {
@@ -917,10 +865,10 @@ ScriptPromise Cache::DeleteImpl(ScriptState* script_state,
return promise;
}
- // Make sure to bind the Cache object to keep the mojo interface pointer
- // alive during the operation. Otherwise GC might prevent the callback
- // from ever being executed.
- cache_ptr_->Batch(
+ // Make sure to bind the Cache object to keep the mojo remote alive during
+ // the operation. Otherwise GC might prevent the callback from ever being
+ // executed.
+ cache_remote_->Batch(
std::move(batch_operations), trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
@@ -1013,16 +961,13 @@ ScriptPromise Cache::PutImpl(ScriptState* script_state,
BodyStreamBuffer* buffer = responses[i]->InternalBodyBuffer();
- CodeCacheGenerateTiming cache_generate_timing =
- ShouldGenerateV8CodeCache(script_state, responses[i]);
- if (cache_generate_timing != CodeCacheGenerateTiming::kDontGenerate) {
+ if (ShouldGenerateV8CodeCache(script_state, responses[i])) {
FetchDataLoader* loader = FetchDataLoader::CreateLoaderAsArrayBuffer();
- buffer->StartLoading(
- loader,
- MakeGarbageCollected<CodeCacheHandleCallbackForPut>(
- script_state, this, i, barrier_callback, requests[i],
- responses[i], cache_generate_timing, trace_id),
- exception_state);
+ buffer->StartLoading(loader,
+ MakeGarbageCollected<CodeCacheHandleCallbackForPut>(
+ script_state, i, barrier_callback, requests[i],
+ responses[i], trace_id),
+ exception_state);
if (exception_state.HadException()) {
barrier_callback->OnError("Could not inspect response body state");
return promise;
@@ -1082,10 +1027,10 @@ ScriptPromise Cache::KeysImpl(ScriptState* script_state,
return promise;
}
- // Make sure to bind the Cache object to keep the mojo interface pointer
- // alive during the operation. Otherwise GC might prevent the callback
- // from ever being executed.
- cache_ptr_->Keys(
+ // Make sure to bind the Cache object to keep the mojo remote alive during
+ // the operation. Otherwise GC might prevent the callback from ever being
+ // executed.
+ cache_remote_->Keys(
std::move(fetch_api_request), std::move(mojo_options), trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
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 d3f75893c99..b386ecdb55a 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
@@ -8,6 +8,8 @@
#include <memory>
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/fetch/global_fetch.h"
@@ -38,6 +40,7 @@ struct TypeConverter<CacheQueryOptionsPtr, const blink::CacheQueryOptions*> {
namespace blink {
+class CacheStorageBlobClientList;
class ExceptionState;
class Response;
class Request;
@@ -50,7 +53,7 @@ class MODULES_EXPORT Cache final : public ScriptWrappable {
public:
Cache(GlobalFetch::ScopedFetcher*,
- mojom::blink::CacheStorageCacheAssociatedPtrInfo,
+ mojo::PendingAssociatedRemote<mojom::blink::CacheStorageCache>,
scoped_refptr<base::SingleThreadTaskRunner>);
// From Cache.idl:
@@ -114,8 +117,9 @@ class MODULES_EXPORT Cache final : public ScriptWrappable {
const CacheQueryOptions*);
Member<GlobalFetch::ScopedFetcher> scoped_fetcher_;
+ Member<CacheStorageBlobClientList> blob_client_list_;
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
+ mojo::AssociatedRemote<mojom::blink::CacheStorageCache> cache_remote_;
DISALLOW_COPY_AND_ASSIGN(Cache);
};
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 60a2e5313a3..2122c8c17b9 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
@@ -20,8 +20,10 @@
#include "third_party/blink/renderer/core/fetch/response.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_error.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_trace_utils.h"
+#include "third_party/blink/renderer/modules/cache_storage/cache_utils.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -100,12 +102,20 @@ ScriptPromise CacheStorage::open(ScriptState* script_state,
return promise;
}
+ // The context may be destroyed and the mojo connection unbound. However the
+ // object may live on, reject any requests after the context is destroyed.
+ if (!cache_storage_remote_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return promise;
+ }
+
ever_used_ = true;
// Make sure to bind the CacheStorage object to keep the mojo interface
// pointer alive during the operation. Otherwise GC might prevent the
// callback from ever being executed.
- cache_storage_ptr_->Open(
+ cache_storage_remote_->Open(
cache_name, trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver,
@@ -166,12 +176,20 @@ ScriptPromise CacheStorage::has(ScriptState* script_state,
return promise;
}
+ // The context may be destroyed and the mojo connection unbound. However the
+ // object may live on, reject any requests after the context is destroyed.
+ if (!cache_storage_remote_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return promise;
+ }
+
ever_used_ = true;
// Make sure to bind the CacheStorage object to keep the mojo interface
// pointer alive during the operation. Otherwise GC might prevent the
// callback from ever being executed.
- cache_storage_ptr_->Has(
+ cache_storage_remote_->Has(
cache_name, trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
@@ -218,12 +236,20 @@ ScriptPromise CacheStorage::Delete(ScriptState* script_state,
return promise;
}
+ // The context may be destroyed and the mojo connection unbound. However the
+ // object may live on, reject any requests after the context is destroyed.
+ if (!cache_storage_remote_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return promise;
+ }
+
ever_used_ = true;
// Make sure to bind the CacheStorage object to keep the mojo interface
// pointer alive during the operation. Otherwise GC might prevent the
// callback from ever being executed.
- cache_storage_ptr_->Delete(
+ cache_storage_remote_->Delete(
cache_name, trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
@@ -270,12 +296,20 @@ ScriptPromise CacheStorage::keys(ScriptState* script_state) {
return promise;
}
+ // The context may be destroyed and the mojo connection unbound. However the
+ // object may live on, reject any requests after the context is destroyed.
+ if (!cache_storage_remote_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return promise;
+ }
+
ever_used_ = true;
// Make sure to bind the CacheStorage object to keep the mojo interface
// pointer alive during the operation. Otherwise GC might prevent the
// callback from ever being executed.
- cache_storage_ptr_->Keys(
+ cache_storage_remote_->Keys(
trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
@@ -319,6 +353,12 @@ ScriptPromise CacheStorage::MatchImpl(ScriptState* script_state,
request->CreateFetchAPIRequest();
mojom::blink::MultiCacheQueryOptionsPtr mojo_options =
mojom::blink::MultiCacheQueryOptions::From(options);
+
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ bool in_related_fetch_event = false;
+ if (auto* global_scope = DynamicTo<ServiceWorkerGlobalScope>(context))
+ in_related_fetch_event = global_scope->HasRelatedFetchEvent(request->url());
+
TRACE_EVENT_WITH_FLOW2("CacheStorage", "CacheStorage::MatchImpl",
TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_OUT,
"request", CacheStorageTracedValue(mojo_request),
@@ -333,6 +373,14 @@ ScriptPromise CacheStorage::MatchImpl(ScriptState* script_state,
return promise;
}
+ // The context may be destroyed and the mojo connection unbound. However the
+ // object may live on, reject any requests after the context is destroyed.
+ if (!cache_storage_remote_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return promise;
+ }
+
if (request->method() != http_names::kGET && !options->ignoreMethod()) {
resolver->Resolve();
return promise;
@@ -343,12 +391,13 @@ ScriptPromise CacheStorage::MatchImpl(ScriptState* script_state,
// Make sure to bind the CacheStorage object to keep the mojo interface
// pointer alive during the operation. Otherwise GC might prevent the
// callback from ever being executed.
- cache_storage_ptr_->Match(
- std::move(mojo_request), std::move(mojo_options), trace_id,
+ cache_storage_remote_->Match(
+ std::move(mojo_request), std::move(mojo_options), in_related_fetch_event,
+ trace_id,
WTF::Bind(
[](ScriptPromiseResolver* resolver, base::TimeTicks start_time,
const MultiCacheQueryOptions* options, int64_t trace_id,
- mojom::blink::MatchResultPtr result) {
+ CacheStorage* self, mojom::blink::MatchResultPtr result) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
if (!options->hasCacheName() || options->cacheName().IsEmpty()) {
UMA_HISTOGRAM_LONG_TIMES(
@@ -379,24 +428,41 @@ ScriptPromise CacheStorage::MatchImpl(ScriptState* script_state,
break;
}
} else {
- TRACE_EVENT_WITH_FLOW1(
- "CacheStorage", "CacheStorage::MatchImpl::Callback",
- TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
- "response", CacheStorageTracedValue(result->get_response()));
ScriptState::Scope scope(resolver->GetScriptState());
- resolver->Resolve(Response::Create(resolver->GetScriptState(),
- *result->get_response()));
+ if (result->is_eager_response()) {
+ TRACE_EVENT_WITH_FLOW1(
+ "CacheStorage", "CacheStorage::MatchImpl::Callback",
+ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
+ "eager_response",
+ CacheStorageTracedValue(
+ result->get_eager_response()->response));
+ resolver->Resolve(
+ CreateEagerResponse(resolver->GetScriptState(),
+ std::move(result->get_eager_response()),
+ self->blob_client_list_));
+ } else {
+ TRACE_EVENT_WITH_FLOW1(
+ "CacheStorage", "CacheStorage::MatchImpl::Callback",
+ TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN,
+ "response",
+ CacheStorageTracedValue(result->get_response()));
+ resolver->Resolve(Response::Create(resolver->GetScriptState(),
+ *result->get_response()));
+ }
}
},
WrapPersistent(resolver), base::TimeTicks::Now(),
- WrapPersistent(options), trace_id));
+ WrapPersistent(options), trace_id, WrapPersistent(this)));
return promise;
}
CacheStorage::CacheStorage(ExecutionContext* context,
GlobalFetch::ScopedFetcher* fetcher)
- : ContextClient(context), scoped_fetcher_(fetcher), ever_used_(false) {
+ : ContextLifecycleObserver(context),
+ scoped_fetcher_(fetcher),
+ blob_client_list_(MakeGarbageCollected<CacheStorageBlobClientList>()),
+ ever_used_(false) {
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
context->GetTaskRunner(blink::TaskType::kMiscPlatformAPI);
@@ -404,16 +470,17 @@ CacheStorage::CacheStorage(ExecutionContext* context,
// Service workers may already have a CacheStoragePtr provided as an
// optimization.
if (auto* service_worker = DynamicTo<ServiceWorkerGlobalScope>(context)) {
- mojom::blink::CacheStoragePtrInfo info = service_worker->TakeCacheStorage();
+ mojo::PendingRemote<mojom::blink::CacheStorage> info =
+ service_worker->TakeCacheStorage();
if (info) {
- cache_storage_ptr_ = RevocableInterfacePtr<mojom::blink::CacheStorage>(
- std::move(info), context->GetInterfaceInvalidator(), task_runner);
+ cache_storage_remote_ = mojo::Remote<mojom::blink::CacheStorage>(
+ std::move(info), task_runner);
return;
}
}
- context->GetInterfaceProvider()->GetInterface(MakeRequest(
- &cache_storage_ptr_, context->GetInterfaceInvalidator(), task_runner));
+ context->GetInterfaceProvider()->GetInterface(
+ cache_storage_remote_.BindNewPipeAndPassReceiver(task_runner));
}
CacheStorage::~CacheStorage() = default;
@@ -431,8 +498,9 @@ bool CacheStorage::HasPendingActivity() const {
void CacheStorage::Trace(blink::Visitor* visitor) {
visitor->Trace(scoped_fetcher_);
+ visitor->Trace(blob_client_list_);
ScriptWrappable::Trace(visitor);
- ContextClient::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
}
bool CacheStorage::IsAllowed(ScriptState* script_state) {
@@ -443,4 +511,8 @@ bool CacheStorage::IsAllowed(ScriptState* script_state) {
return allowed_.value();
}
+void CacheStorage::ContextDestroyed(ExecutionContext*) {
+ cache_storage_remote_.reset();
+}
+
} // namespace blink
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 4e5ae78cd89..b545f83665b 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
@@ -8,7 +8,8 @@
#include <memory>
#include "base/macros.h"
#include "base/optional.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.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/context_lifecycle_observer.h"
@@ -17,15 +18,16 @@
#include "third_party/blink/renderer/modules/cache_storage/multi_cache_query_options.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
+class CacheStorageBlobClientList;
+
class CacheStorage final : public ScriptWrappable,
public ActiveScriptWrappable<CacheStorage>,
- public ContextClient {
+ public ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(CacheStorage);
@@ -44,6 +46,7 @@ class CacheStorage final : public ScriptWrappable,
bool HasPendingActivity() const override;
void Trace(blink::Visitor*) override;
+ void ContextDestroyed(ExecutionContext*) override;
private:
ScriptPromise MatchImpl(ScriptState*,
@@ -53,8 +56,9 @@ class CacheStorage final : public ScriptWrappable,
bool IsAllowed(ScriptState*);
Member<GlobalFetch::ScopedFetcher> scoped_fetcher_;
+ Member<CacheStorageBlobClientList> blob_client_list_;
- RevocableInterfacePtr<mojom::blink::CacheStorage> cache_storage_ptr_;
+ mojo::Remote<mojom::blink::CacheStorage> cache_storage_remote_;
base::Optional<bool> allowed_;
bool ever_used_;
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.cc
new file mode 100644
index 00000000000..b46756aa2fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.cc
@@ -0,0 +1,87 @@
+// 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/cache_storage/cache_storage_blob_client_list.h"
+
+namespace blink {
+
+// Class implementing the BlobReaderClient interface. This is used to
+// propagate the completion of an eager body blob read to the
+// DataPipeBytesConsumer.
+class CacheStorageBlobClientList::Client
+ : public GarbageCollected<CacheStorageBlobClientList::Client>,
+ public mojom::blink::BlobReaderClient {
+ // We must prevent any mojo messages from coming in after this object
+ // starts getting garbage collected.
+ USING_PRE_FINALIZER(CacheStorageBlobClientList::Client, Dispose);
+
+ public:
+ Client(CacheStorageBlobClientList* owner,
+ mojo::PendingReceiver<mojom::blink::BlobReaderClient>
+ client_pending_receiver,
+ DataPipeBytesConsumer::CompletionNotifier* completion_notifier)
+ : owner_(owner),
+ client_receiver_(this, std::move(client_pending_receiver)),
+ completion_notifier_(completion_notifier) {}
+
+ void OnCalculatedSize(uint64_t total_size,
+ uint64_t expected_content_size) override {}
+
+ void OnComplete(int32_t status, uint64_t data_length) override {
+ client_receiver_.reset();
+
+ // 0 is net::OK
+ if (status == 0)
+ completion_notifier_->SignalComplete();
+ else
+ completion_notifier_->SignalError(BytesConsumer::Error());
+
+ if (owner_)
+ owner_->RevokeClient(this);
+ }
+
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(owner_);
+ visitor->Trace(completion_notifier_);
+ }
+
+ private:
+ void Dispose() {
+ // Use the existence of the client_receiver_ binding to see if this
+ // client has already completed.
+ if (!client_receiver_.is_bound())
+ return;
+
+ client_receiver_.reset();
+ completion_notifier_->SignalError(BytesConsumer::Error("aborted"));
+
+ // If we are already being garbage collected its not necessary to
+ // call RevokeClient() on the owner.
+ }
+
+ WeakMember<CacheStorageBlobClientList> owner_;
+ mojo::Receiver<mojom::blink::BlobReaderClient> client_receiver_;
+ Member<DataPipeBytesConsumer::CompletionNotifier> completion_notifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(Client);
+};
+
+void CacheStorageBlobClientList::AddClient(
+ mojo::PendingReceiver<mojom::blink::BlobReaderClient>
+ client_pending_receiver,
+ DataPipeBytesConsumer::CompletionNotifier* completion_notifier) {
+ clients.emplace_back(MakeGarbageCollected<Client>(
+ this, std::move(client_pending_receiver), completion_notifier));
+}
+
+void CacheStorageBlobClientList::Trace(blink::Visitor* visitor) {
+ visitor->Trace(clients);
+}
+
+void CacheStorageBlobClientList::RevokeClient(Client* client) {
+ auto index = clients.Find(client);
+ clients.EraseAt(index);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h
new file mode 100644
index 00000000000..23b0452dadc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h
@@ -0,0 +1,39 @@
+// 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_CACHE_STORAGE_CACHE_STORAGE_BLOB_CLIENT_LIST_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_CACHE_STORAGE_BLOB_CLIENT_LIST_H_
+
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
+
+namespace blink {
+
+// This class holds a list of BlobReaderClient implementations alive until
+// they complete or the entire list is garbage collected.
+class CacheStorageBlobClientList
+ : public GarbageCollected<CacheStorageBlobClientList> {
+ public:
+ CacheStorageBlobClientList() = default;
+ void AddClient(
+ mojo::PendingReceiver<mojom::blink::BlobReaderClient>
+ client_pending_receiver,
+ DataPipeBytesConsumer::CompletionNotifier* completion_notifier);
+
+ void Trace(blink::Visitor* visitor);
+
+ private:
+ class Client;
+
+ void RevokeClient(Client* client);
+
+ HeapVector<Member<Client>> clients;
+ DISALLOW_COPY_AND_ASSIGN(CacheStorageBlobClientList);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_CACHE_STORAGE_BLOB_CLIENT_LIST_H_
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 a9abf23d371..707c7592e49 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
@@ -10,7 +10,8 @@
#include "base/memory/ptr_util.h"
#include "base/optional.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
@@ -21,6 +22,7 @@
#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_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_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_request.h"
@@ -50,7 +52,7 @@ const char kNotImplementedString[] =
"NotSupportedError: Method is not implemented.";
class ScopedFetcherForTests final
- : public GarbageCollectedFinalized<ScopedFetcherForTests>,
+ : public GarbageCollected<ScopedFetcherForTests>,
public GlobalFetch::ScopedFetcher {
USING_GARBAGE_COLLECTED_MIXIN(ScopedFetcherForTests);
@@ -139,6 +141,7 @@ class ErrorCacheForTests : public mojom::blink::CacheStorageCache {
void Match(mojom::blink::FetchAPIRequestPtr fetch_api_request,
mojom::blink::CacheQueryOptionsPtr query_options,
+ bool in_related_fetch_event,
int64_t trace_id,
MatchCallback callback) override {
last_error_web_cache_method_called_ = "dispatchMatch";
@@ -182,14 +185,6 @@ class ErrorCacheForTests : public mojom::blink::CacheStorageCache {
CheckBatchOperationsIfProvided(batch_operations);
std::move(callback).Run(CacheStorageVerboseError::New(error_, String()));
}
- void SetSideData(const KURL& url,
- base::Time response_time,
- base::span<const uint8_t> side_data,
- int64_t trace_id,
- SetSideDataCallback callback) override {
- std::move(callback).Run(
- blink::mojom::CacheStorageError::kErrorNotImplemented);
- }
protected:
void CheckUrlIfProvided(const KURL& url) {
@@ -271,14 +266,14 @@ class CacheStorageTest : public PageTestBase {
Cache* CreateCache(ScopedFetcherForTests* fetcher,
std::unique_ptr<ErrorCacheForTests> cache) {
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr;
- auto request = mojo::MakeRequestAssociatedWithDedicatedPipe(&cache_ptr);
+ mojo::AssociatedRemote<mojom::blink::CacheStorageCache> cache_remote;
cache_ = std::move(cache);
- binding_ = std::make_unique<
- mojo::AssociatedBinding<mojom::blink::CacheStorageCache>>(
- cache_.get(), std::move(request));
+ receiver_ = std::make_unique<
+ mojo::AssociatedReceiver<mojom::blink::CacheStorageCache>>(
+ cache_.get(),
+ cache_remote.BindNewEndpointAndPassDedicatedReceiverForTesting());
return MakeGarbageCollected<Cache>(
- fetcher, cache_ptr.PassInterface(),
+ fetcher, cache_remote.Unbind(),
blink::scheduler::GetSingleThreadTaskRunnerForTesting());
}
@@ -302,12 +297,10 @@ class CacheStorageTest : public PageTestBase {
// Convenience methods for testing the returned promises.
ScriptValue GetRejectValue(ScriptPromise& promise) {
- ScriptValue on_reject;
- promise.Then(UnreachableFunction::Create(GetScriptState()),
- TestFunction::Create(GetScriptState(), &on_reject));
- v8::MicrotasksScope::PerformCheckpoint(GetIsolate());
- test::RunPendingTasks();
- return on_reject;
+ ScriptPromiseTester tester(GetScriptState(), promise);
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsRejected());
+ return tester.Value();
}
std::string GetRejectString(ScriptPromise& promise) {
@@ -319,12 +312,10 @@ class CacheStorageTest : public PageTestBase {
}
ScriptValue GetResolveValue(ScriptPromise& promise) {
- ScriptValue on_resolve;
- promise.Then(TestFunction::Create(GetScriptState(), &on_resolve),
- UnreachableFunction::Create(GetScriptState()));
- v8::MicrotasksScope::PerformCheckpoint(GetIsolate());
- test::RunPendingTasks();
- return on_resolve;
+ ScriptPromiseTester tester(GetScriptState(), promise);
+ tester.WaitUntilSettled();
+ EXPECT_TRUE(tester.IsFulfilled());
+ return tester.Value();
}
std::string GetResolveString(ScriptPromise& promise) {
@@ -336,51 +327,9 @@ class CacheStorageTest : public PageTestBase {
}
private:
- // A ScriptFunction that creates a test failure if it is ever called.
- class UnreachableFunction : public ScriptFunction {
- public:
- static v8::Local<v8::Function> Create(ScriptState* script_state) {
- UnreachableFunction* self =
- MakeGarbageCollected<UnreachableFunction>(script_state);
- return self->BindToV8Function();
- }
-
- UnreachableFunction(ScriptState* script_state)
- : ScriptFunction(script_state) {}
-
- ScriptValue Call(ScriptValue value) override {
- ADD_FAILURE() << "Unexpected call to a null ScriptFunction.";
- return value;
- }
- };
-
- // A ScriptFunction that saves its parameter; used by tests to assert on
- // correct values being passed.
- class TestFunction : public ScriptFunction {
- public:
- static v8::Local<v8::Function> Create(ScriptState* script_state,
- ScriptValue* out_value) {
- TestFunction* self =
- MakeGarbageCollected<TestFunction>(script_state, out_value);
- return self->BindToV8Function();
- }
-
- TestFunction(ScriptState* script_state, ScriptValue* out_value)
- : ScriptFunction(script_state), value_(out_value) {}
-
- ScriptValue Call(ScriptValue value) override {
- DCHECK(!value.IsEmpty());
- *value_ = value;
- return value;
- }
-
- private:
- ScriptValue* value_;
- };
-
std::unique_ptr<ErrorCacheForTests> cache_;
- std::unique_ptr<mojo::AssociatedBinding<mojom::blink::CacheStorageCache>>
- binding_;
+ std::unique_ptr<mojo::AssociatedReceiver<mojom::blink::CacheStorageCache>>
+ receiver_;
};
RequestInfo StringToRequestInfo(const String& value) {
@@ -589,6 +538,7 @@ class MatchTestCache : public NotImplementedErrorCache {
// From WebServiceWorkerCache:
void Match(mojom::blink::FetchAPIRequestPtr fetch_api_request,
mojom::blink::CacheQueryOptionsPtr query_options,
+ bool in_related_fetch_event,
int64_t trace_id,
MatchCallback callback) override {
mojom::blink::MatchResultPtr result = mojom::blink::MatchResult::New();
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.cc
new file mode 100644
index 00000000000..f70202288b4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.cc
@@ -0,0 +1,47 @@
+// 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/cache_storage/cache_utils.h"
+
+#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
+#include "third_party/blink/renderer/core/fetch/response.h"
+#include "third_party/blink/renderer/modules/cache_storage/cache_storage_blob_client_list.h"
+#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h"
+
+namespace blink {
+
+Response* CreateEagerResponse(ScriptState* script_state,
+ mojom::blink::EagerResponsePtr eager_response,
+ CacheStorageBlobClientList* client_list) {
+ auto& response = eager_response->response;
+ DCHECK(!response->blob);
+
+ ExecutionContext* context = ExecutionContext::From(script_state);
+
+ FetchResponseData* fetch_data =
+ Response::CreateUnfilteredFetchResponseDataWithoutBody(script_state,
+ *response);
+
+ DataPipeBytesConsumer::CompletionNotifier* completion_notifier = nullptr;
+ fetch_data->ReplaceBodyStreamBuffer(MakeGarbageCollected<BodyStreamBuffer>(
+ script_state,
+ MakeGarbageCollected<DataPipeBytesConsumer>(
+ context->GetTaskRunner(TaskType::kNetworking),
+ std::move(eager_response->pipe), &completion_notifier),
+ nullptr /* AbortSignal */));
+
+ // Create a BlobReaderClient in the provided list. This will track the
+ // completion of the eagerly read blob and propagate it to the given
+ // DataPipeBytesConsumer::CompletionNotifier. The list will also hold
+ // the client alive.
+ client_list->AddClient(std::move(eager_response->client_receiver),
+ std::move(completion_notifier));
+
+ fetch_data = Response::FilterResponseData(
+ response->response_type, fetch_data, response->cors_exposed_header_names);
+
+ return Response::Create(context, fetch_data);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.h b/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.h
new file mode 100644
index 00000000000..2c80bed0624
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_utils.h
@@ -0,0 +1,26 @@
+// 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_CACHE_STORAGE_CACHE_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_CACHE_UTILS_H_
+
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+
+namespace blink {
+
+class CacheStorageBlobClientList;
+class Response;
+class ScriptState;
+
+// A utility function to deserialize an eagerly read cache_storage response
+// into a web-exposed fetch Response object. The resulting Response will
+// have a DataPipeBytesConsumer body and a side_data_blob which can be used
+// to read any code cache.
+Response* CreateEagerResponse(ScriptState* script_state,
+ mojom::blink::EagerResponsePtr eager_response,
+ CacheStorageBlobClientList* client_list);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_CACHE_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc b/chromium/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
index fd9d7a905e3..483b7a321fc 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
@@ -19,7 +19,7 @@ namespace {
template <typename T>
class GlobalCacheStorageImpl final
- : public GarbageCollectedFinalized<GlobalCacheStorageImpl<T>>,
+ : public GarbageCollected<GlobalCacheStorageImpl<T>>,
public Supplement<T> {
USING_GARBAGE_COLLECTED_MIXIN(GlobalCacheStorageImpl);
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 d67b04c1a71..ccc8ceec252 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
@@ -9,6 +9,8 @@
#include <utility>
#include "base/macros.h"
#include "base/memory/scoped_refptr.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"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
@@ -213,13 +215,15 @@ struct RequestResponse {
class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
public:
- ResponsesAccumulator(wtf_size_t num_responses,
- const DataRequestParams& params,
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr,
- std::unique_ptr<RequestEntriesCallback> callback)
+ ResponsesAccumulator(
+ wtf_size_t num_responses,
+ const DataRequestParams& params,
+ mojo::PendingAssociatedRemote<mojom::blink::CacheStorageCache>
+ cache_pending_remote,
+ std::unique_ptr<RequestEntriesCallback> callback)
: params_(params),
num_responses_left_(num_responses),
- cache_ptr_(std::move(cache_ptr)),
+ cache_remote_(std::move(cache_pending_remote)),
callback_(std::move(callback)) {}
void Dispatch(Vector<mojom::blink::FetchAPIRequestPtr> old_requests) {
@@ -261,21 +265,22 @@ class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
request->redirect_mode, request->integrity, request->priority,
request->fetch_window_id, request->keepalive, request->is_reload,
request->is_history_navigation);
- cache_ptr_->Match(std::move(request),
- mojom::blink::CacheQueryOptions::New(), trace_id,
- WTF::Bind(
- [](scoped_refptr<ResponsesAccumulator> accumulator,
- mojom::blink::FetchAPIRequestPtr request,
- mojom::blink::MatchResultPtr result) {
- if (result->is_status()) {
- accumulator->SendFailure(result->get_status());
- } else {
- accumulator->AddRequestResponsePair(
- request, result->get_response());
- }
- },
- scoped_refptr<ResponsesAccumulator>(this),
- std::move(request_clone_without_body)));
+ cache_remote_->Match(
+ std::move(request), mojom::blink::CacheQueryOptions::New(),
+ false /* in_related_fetch_event */, trace_id,
+ WTF::Bind(
+ [](scoped_refptr<ResponsesAccumulator> accumulator,
+ mojom::blink::FetchAPIRequestPtr request,
+ mojom::blink::MatchResultPtr result) {
+ if (result->is_status()) {
+ accumulator->SendFailure(result->get_status());
+ } else {
+ accumulator->AddRequestResponsePair(request,
+ result->get_response());
+ }
+ },
+ scoped_refptr<ResponsesAccumulator>(this),
+ std::move(request_clone_without_body)));
}
}
@@ -362,7 +367,7 @@ class ResponsesAccumulator : public RefCounted<ResponsesAccumulator> {
DataRequestParams params_;
int num_responses_left_;
Vector<RequestResponse> responses_;
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
+ mojo::AssociatedRemote<mojom::blink::CacheStorageCache> cache_remote_;
std::unique_ptr<RequestEntriesCallback> callback_;
DISALLOW_COPY_AND_ASSIGN(ResponsesAccumulator);
@@ -374,10 +379,11 @@ class GetCacheKeysForRequestData {
public:
GetCacheKeysForRequestData(
const DataRequestParams& params,
- mojom::blink::CacheStorageCacheAssociatedPtrInfo cache_ptr_info,
+ mojo::PendingAssociatedRemote<mojom::blink::CacheStorageCache>
+ cache_pending_remote,
std::unique_ptr<RequestEntriesCallback> callback)
: params_(params), callback_(std::move(callback)) {
- cache_ptr_.Bind(std::move(cache_ptr_info));
+ cache_remote_.Bind(std::move(cache_pending_remote));
}
void Dispatch(std::unique_ptr<GetCacheKeysForRequestData> self) {
@@ -385,7 +391,7 @@ class GetCacheKeysForRequestData {
TRACE_EVENT_WITH_FLOW0(
"CacheStorage", "GetCacheKeysForRequestData::Dispatch",
TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_OUT);
- cache_ptr_->Keys(
+ cache_remote_->Keys(
nullptr /* request */, mojom::blink::CacheQueryOptions::New(), trace_id,
WTF::Bind(
[](DataRequestParams params,
@@ -406,7 +412,7 @@ class GetCacheKeysForRequestData {
scoped_refptr<ResponsesAccumulator> accumulator =
base::AdoptRef(new ResponsesAccumulator(
result->get_keys().size(), params,
- std::move(self->cache_ptr_),
+ self->cache_remote_.Unbind(),
std::move(self->callback_)));
accumulator->Dispatch(std::move(result->get_keys()));
}
@@ -416,7 +422,7 @@ class GetCacheKeysForRequestData {
private:
DataRequestParams params_;
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr_;
+ mojo::AssociatedRemote<mojom::blink::CacheStorageCache> cache_remote_;
std::unique_ptr<RequestEntriesCallback> callback_;
DISALLOW_COPY_AND_ASSIGN(GetCacheKeysForRequestData);
@@ -653,13 +659,15 @@ void InspectorCacheStorageAgent::deleteEntry(
operation->request->url = KURL(request);
operation->request->method = String("GET");
- mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr;
- cache_ptr.Bind(std::move(result->get_cache()));
- auto* cache = cache_ptr.get();
+ mojo::AssociatedRemote<mojom::blink::CacheStorageCache>
+ cache_remote;
+ cache_remote.Bind(std::move(result->get_cache()));
+ auto* cache = cache_remote.get();
cache->Batch(
std::move(batch_operations), trace_id,
WTF::Bind(
- [](mojom::blink::CacheStorageCacheAssociatedPtr cache_ptr,
+ [](mojo::AssociatedRemote<mojom::blink::CacheStorageCache>
+ cache_remote,
std::unique_ptr<DeleteEntryCallback> callback,
mojom::blink::CacheStorageVerboseErrorPtr error) {
if (error->value !=
@@ -673,7 +681,7 @@ void InspectorCacheStorageAgent::deleteEntry(
callback->sendSuccess();
}
},
- std::move(cache_ptr), std::move(callback)));
+ std::move(cache_remote), std::move(callback)));
}
},
cache_name, request, trace_id, std::move(callback)));
@@ -711,7 +719,8 @@ void InspectorCacheStorageAgent::requestCachedResponse(
multi_query_options->cache_name = cache_name;
cache_storage->Match(
- std::move(request), std::move(multi_query_options), trace_id,
+ std::move(request), std::move(multi_query_options),
+ false /* in_related_fetch_event */, trace_id,
WTF::Bind(
[](std::unique_ptr<RequestCachedResponseCallback> callback,
mojom::blink::MatchResultPtr result) {
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h b/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
index b75220c895e..52681c295a8 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
#include "third_party/blink/renderer/core/inspector/protocol/CacheStorage.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/DEPS b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/DEPS
index aaee473139e..11fa35c31af 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/DEPS
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/DEPS
@@ -1,3 +1,10 @@
include_rules = [
"+third_party/skia/include",
-] \ No newline at end of file
+]
+
+specific_include_rules = {
+ # Additional allowed includes for tests.
+ ".*_test(_.*)?\.(cc|h)" : [
+ "+components/viz",
+ ]
+} \ No newline at end of file
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 b54d60ee2d0..fbbd98d2f7d 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
@@ -1597,6 +1597,9 @@ ImageData* BaseRenderingContext2D::getImageData(
WTF::ArrayBufferContents contents;
const CanvasColorParams& color_params = ColorParams();
+ // Deferred offscreen canvases might have recorded commands, make sure
+ // that those get drawn here
+ FinalizeFrame();
scoped_refptr<StaticBitmapImage> snapshot = GetImage(kPreferNoAcceleration);
// GetImagedata is faster in Unaccelerated canvases
@@ -1609,8 +1612,6 @@ ImageData* BaseRenderingContext2D::getImageData(
return nullptr;
}
- NeedsFinalizeFrame();
-
// Convert pixels to proper storage format if needed
if (PixelFormat() != kRGBA8CanvasPixelFormat) {
ImageDataStorageFormat storage_format =
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 112f4aa0c10..5ad18e2ea4e 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
@@ -193,6 +193,8 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
ImageDataColorSettings*,
ExceptionState&) const;
+ // 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&);
void putImageData(ImageData*, int dx, int dy, ExceptionState&);
void putImageData(ImageData*,
@@ -341,7 +343,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
NOTREACHED();
return false;
}
- virtual scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const {
+ virtual scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) {
NOTREACHED();
return nullptr;
}
@@ -361,7 +363,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
mutable UsageCounters usage_counters_;
- virtual void NeedsFinalizeFrame() {}
+ virtual void FinalizeFrame() {}
float GetFontBaseline(const SimpleFontData&) const;
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 5df98e9f9b6..e2c68071542 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
@@ -317,7 +317,7 @@ CanvasPixelFormat CanvasRenderingContext2D::PixelFormat() const {
}
void CanvasRenderingContext2D::Reset() {
- // This is a multiple inherritance bootstrap
+ // This is a multiple inheritance bootstrap
BaseRenderingContext2D::Reset();
}
@@ -665,12 +665,19 @@ bool CanvasRenderingContext2D::CanCreateCanvas2dResourceProvider() const {
}
scoped_refptr<StaticBitmapImage> blink::CanvasRenderingContext2D::GetImage(
- AccelerationHint hint) const {
+ AccelerationHint hint) {
if (!IsPaintable())
return nullptr;
return canvas()->GetCanvas2DLayerBridge()->NewImageSnapshot(hint);
}
+void CanvasRenderingContext2D::FinalizeFrame() {
+ TRACE_EVENT0("blink", "CanvasRenderingContext2D::FinalizeFrame");
+ if (canvas() && canvas()->GetCanvas2DLayerBridge())
+ canvas()->GetCanvas2DLayerBridge()->FinalizeFrame();
+ usage_counters_.num_frames_since_reset++;
+}
+
bool CanvasRenderingContext2D::ParseColorOrCurrentColor(
Color& color,
const String& color_string) const {
@@ -1132,4 +1139,11 @@ bool CanvasRenderingContext2D::IsCanvas2DBufferValid() const {
return false;
}
+bool CanvasRenderingContext2D::IsDeferralEnabled() const {
+ Canvas2DLayerBridge* layer_bridge = canvas()->GetCanvas2DLayerBridge();
+ if (!layer_bridge)
+ return false;
+ return layer_bridge->IsDeferralEnabled();
+}
+
} // namespace blink
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 4f26dd20247..d0e157a83c3 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
@@ -87,7 +87,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
static_cast<HTMLCanvasElement*>(host), attrs);
}
CanvasRenderingContext::ContextType GetContextType() const override {
- return CanvasRenderingContext::kContext2d;
+ return CanvasRenderingContext::kContext2D;
}
private:
@@ -182,7 +182,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
cc::PaintCanvas* ExistingDrawingCanvas() const final;
void DidDraw(const SkIRect& dirty_rect) final;
- scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final;
+ scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) final;
bool StateHasFilter() final;
sk_sp<PaintFilter> StateGetFilter() final;
@@ -190,7 +190,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void ValidateStateStack() const final;
- void FinalizeFrame() override { usage_counters_.num_frames_since_reset++; }
+ void FinalizeFrame() override;
bool IsPaintable() const final { return canvas()->GetCanvas2DLayerBridge(); }
@@ -200,11 +200,9 @@ class MODULES_EXPORT CanvasRenderingContext2D final
CanvasColorParams ColorParamsForTest() const { return ColorParams(); }
- protected:
- void NeedsFinalizeFrame() override {
- CanvasRenderingContext::NeedsFinalizeFrame();
- }
+ bool IsDeferralEnabled() const final;
+ protected:
CanvasColorParams ColorParams() const override;
bool WritePixels(const SkImageInfo& orig_info,
const void* pixels,
@@ -238,7 +236,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void UpdateElementAccessibility(const Path&, Element*);
CanvasRenderingContext::ContextType GetContextType() const override {
- return CanvasRenderingContext::kContext2d;
+ return CanvasRenderingContext::kContext2D;
}
String ColorSpaceAsString() const override;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
index 9e7f31e88be..f7f5fd9ab31 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
@@ -32,7 +32,7 @@ class CanvasRenderingContext2DAPITest : public PageTestBase {
void SetUp() override;
HTMLCanvasElement& CanvasElement() const { return *canvas_element_; }
- CanvasRenderingContext2D* Context2d() const;
+ CanvasRenderingContext2D* Context2D() const;
void CreateContext(OpacityMode);
@@ -42,7 +42,7 @@ class CanvasRenderingContext2DAPITest : public PageTestBase {
CanvasRenderingContext2DAPITest::CanvasRenderingContext2DAPITest() = default;
-CanvasRenderingContext2D* CanvasRenderingContext2DAPITest::Context2d() const {
+CanvasRenderingContext2D* CanvasRenderingContext2DAPITest::Context2D() const {
// If the following check fails, perhaps you forgot to call createContext
// in your test?
EXPECT_NE(nullptr, CanvasElement().RenderingContext());
@@ -56,7 +56,7 @@ void CanvasRenderingContext2DAPITest::CreateContext(OpacityMode opacity_mode) {
CanvasContextCreationAttributesCore attributes;
attributes.alpha = opacity_mode == kNonOpaque;
canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
- Context2d(); // Calling this for the checks
+ Context2D(); // Calling this for the checks
}
void CanvasRenderingContext2DAPITest::SetUp() {
@@ -70,13 +70,13 @@ void CanvasRenderingContext2DAPITest::SetUp() {
TEST_F(CanvasRenderingContext2DAPITest, SetShadowColor_Clamping) {
CreateContext(kNonOpaque);
- Context2d()->setShadowColor("rgba(0,0,0,0)");
- EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2d()->shadowColor());
- Context2d()->setShadowColor("rgb(0,0,0)");
- EXPECT_EQ(String("#000000"), Context2d()->shadowColor());
- Context2d()->setShadowColor("rgb(0,999,0)");
- EXPECT_EQ(String("#00ff00"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ Context2D()->setShadowColor("rgba(0,0,0,0)");
+ EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2D()->shadowColor());
+ Context2D()->setShadowColor("rgb(0,0,0)");
+ EXPECT_EQ(String("#000000"), Context2D()->shadowColor());
+ Context2D()->setShadowColor("rgb(0,999,0)");
+ EXPECT_EQ(String("#00ff00"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgb(0,"
"999999999999999999999999999999999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999999999999999999999999999999999"
@@ -86,23 +86,23 @@ TEST_F(CanvasRenderingContext2DAPITest, SetShadowColor_Clamping) {
"999999999999999999999999999999999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999999999999999999999999999999999"
",0)");
- EXPECT_EQ(String("#00ff00"), Context2d()->shadowColor());
- Context2d()->setShadowColor("rgb(0,0,256)");
- EXPECT_EQ(String("#0000ff"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ EXPECT_EQ(String("#00ff00"), Context2D()->shadowColor());
+ Context2D()->setShadowColor("rgb(0,0,256)");
+ EXPECT_EQ(String("#0000ff"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgb(999999999999999999999999,0,-9999999999999999999999999999)");
- EXPECT_EQ(String("#ff0000"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ EXPECT_EQ(String("#ff0000"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgba("
"999999999999999999999999999999999999999999999999999999999999999999999999"
"9999999999,9,0,1)");
- EXPECT_EQ(String("#ff0900"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ EXPECT_EQ(String("#ff0900"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgba("
"999999999999999999999999999999999999999999999999999999999999999999999999"
"9999999999,9,0,-99999999999999999999999999999999999999)");
- EXPECT_EQ(String("rgba(255, 9, 0, 0)"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ EXPECT_EQ(String("rgba(255, 9, 0, 0)"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgba(7,"
"999999999999999999999999999999999999999999999999999999999999999999999999"
"9999999999,0,"
@@ -114,8 +114,8 @@ TEST_F(CanvasRenderingContext2DAPITest, SetShadowColor_Clamping) {
"999999999999999999999999999999999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999)");
- EXPECT_EQ(String("#07ff00"), Context2d()->shadowColor());
- Context2d()->setShadowColor(
+ EXPECT_EQ(String("#07ff00"), Context2D()->shadowColor());
+ Context2D()->setShadowColor(
"rgba(-7,"
"999999999999999999999999999999999999999999999999999999999999999999999999"
"9999999999,0,"
@@ -127,9 +127,9 @@ TEST_F(CanvasRenderingContext2DAPITest, SetShadowColor_Clamping) {
"999999999999999999999999999999999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999999999999999999999999999999999"
"99999999999999999)");
- EXPECT_EQ(String("#00ff00"), Context2d()->shadowColor());
- Context2d()->setShadowColor("rgba(0%,100%,0%,0.4)");
- EXPECT_EQ(String("rgba(0, 255, 0, 0.4)"), Context2d()->shadowColor());
+ EXPECT_EQ(String("#00ff00"), Context2D()->shadowColor());
+ Context2D()->setShadowColor("rgba(0%,100%,0%,0.4)");
+ EXPECT_EQ(String("rgba(0, 255, 0, 0.4)"), Context2D()->shadowColor());
}
String TrySettingStrokeStyle(CanvasRenderingContext2D* ctx,
@@ -173,15 +173,15 @@ void TrySettingColor(CanvasRenderingContext2D* ctx,
TEST_F(CanvasRenderingContext2DAPITest, ColorSerialization) {
CreateContext(kNonOpaque);
// Check round trips
- TrySettingColor(Context2d(), "transparent", "rgba(0, 0, 0, 0)");
- TrySettingColor(Context2d(), "red", "#ff0000");
- TrySettingColor(Context2d(), "white", "#ffffff");
- TrySettingColor(Context2d(), "", "#666666");
- TrySettingColor(Context2d(), "RGBA(0, 0, 0, 0)", "rgba(0, 0, 0, 0)");
- TrySettingColor(Context2d(), "rgba(0,255,0,1.0)", "#00ff00");
- TrySettingColor(Context2d(), "rgba(1,2,3,0.4)", "rgba(1, 2, 3, 0.4)");
- TrySettingColor(Context2d(), "RgB(1,2,3)", "#010203");
- TrySettingColor(Context2d(), "rGbA(1,2,3,0)", "rgba(1, 2, 3, 0)");
+ TrySettingColor(Context2D(), "transparent", "rgba(0, 0, 0, 0)");
+ TrySettingColor(Context2D(), "red", "#ff0000");
+ TrySettingColor(Context2D(), "white", "#ffffff");
+ TrySettingColor(Context2D(), "", "#666666");
+ TrySettingColor(Context2D(), "RGBA(0, 0, 0, 0)", "rgba(0, 0, 0, 0)");
+ TrySettingColor(Context2D(), "rgba(0,255,0,1.0)", "#00ff00");
+ TrySettingColor(Context2D(), "rgba(1,2,3,0.4)", "rgba(1, 2, 3, 0.4)");
+ TrySettingColor(Context2D(), "RgB(1,2,3)", "#010203");
+ TrySettingColor(Context2D(), "rGbA(1,2,3,0)", "rgba(1, 2, 3, 0)");
}
TEST_F(CanvasRenderingContext2DAPITest, DefaultAttributeValues) {
@@ -189,19 +189,19 @@ TEST_F(CanvasRenderingContext2DAPITest, DefaultAttributeValues) {
{
StringOrCanvasGradientOrCanvasPattern value;
- Context2d()->strokeStyle(value);
+ Context2D()->strokeStyle(value);
EXPECT_TRUE(value.IsString());
EXPECT_EQ(String("#000000"), value.GetAsString());
}
{
StringOrCanvasGradientOrCanvasPattern value;
- Context2d()->fillStyle(value);
+ Context2D()->fillStyle(value);
EXPECT_TRUE(value.IsString());
EXPECT_EQ(String("#000000"), value.GetAsString());
}
- EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2d()->shadowColor());
+ EXPECT_EQ(String("rgba(0, 0, 0, 0)"), Context2D()->shadowColor());
}
TEST_F(CanvasRenderingContext2DAPITest, LineDashStateSave) {
@@ -211,14 +211,14 @@ TEST_F(CanvasRenderingContext2DAPITest, LineDashStateSave) {
simple_dash.push_back(4);
simple_dash.push_back(2);
- Context2d()->setLineDash(simple_dash);
- EXPECT_EQ(simple_dash, Context2d()->getLineDash());
- Context2d()->save();
+ Context2D()->setLineDash(simple_dash);
+ EXPECT_EQ(simple_dash, Context2D()->getLineDash());
+ Context2D()->save();
// Realize the save.
- Context2d()->scale(2, 2);
- EXPECT_EQ(simple_dash, Context2d()->getLineDash());
- Context2d()->restore();
- EXPECT_EQ(simple_dash, Context2d()->getLineDash());
+ Context2D()->scale(2, 2);
+ EXPECT_EQ(simple_dash, Context2D()->getLineDash());
+ Context2D()->restore();
+ EXPECT_EQ(simple_dash, Context2D()->getLineDash());
}
TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
@@ -228,7 +228,7 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
// create a 100x50 imagedata and fill it with white pixels
ImageData* image_data =
- Context2d()->createImageData(100, 50, exception_state);
+ Context2D()->createImageData(100, 50, exception_state);
EXPECT_FALSE(exception_state.HadException());
EXPECT_EQ(100, image_data->width());
EXPECT_EQ(50, image_data->height());
@@ -242,7 +242,7 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
// as 'imageData' but filled with transparent black
ImageData* same_size_image_data =
- Context2d()->createImageData(image_data, exception_state);
+ Context2D()->createImageData(image_data, exception_state);
EXPECT_FALSE(exception_state.HadException());
EXPECT_EQ(100, same_size_image_data->width());
EXPECT_EQ(50, same_size_image_data->height());
@@ -251,13 +251,13 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageData) {
// createImageData(width, height) takes the absolute magnitude of the size
// arguments
- ImageData* imgdata1 = Context2d()->createImageData(10, 20, exception_state);
+ ImageData* imgdata1 = Context2D()->createImageData(10, 20, exception_state);
EXPECT_FALSE(exception_state.HadException());
- ImageData* imgdata2 = Context2d()->createImageData(-10, 20, exception_state);
+ ImageData* imgdata2 = Context2D()->createImageData(-10, 20, exception_state);
EXPECT_FALSE(exception_state.HadException());
- ImageData* imgdata3 = Context2d()->createImageData(10, -20, exception_state);
+ ImageData* imgdata3 = Context2D()->createImageData(10, -20, exception_state);
EXPECT_FALSE(exception_state.HadException());
- ImageData* imgdata4 = Context2d()->createImageData(-10, -20, exception_state);
+ ImageData* imgdata4 = Context2D()->createImageData(-10, -20, exception_state);
EXPECT_FALSE(exception_state.HadException());
EXPECT_EQ((unsigned)800, imgdata1->data()->length());
@@ -270,7 +270,7 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageDataTooBig) {
CreateContext(kNonOpaque);
DummyExceptionStateForTesting exception_state;
ImageData* too_big_image_data =
- Context2d()->createImageData(1000000, 1000000, exception_state);
+ Context2D()->createImageData(1000000, 1000000, exception_state);
EXPECT_EQ(nullptr, too_big_image_data);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
@@ -280,7 +280,7 @@ TEST_F(CanvasRenderingContext2DAPITest, GetImageDataTooBig) {
CreateContext(kNonOpaque);
DummyExceptionStateForTesting exception_state;
ImageData* image_data =
- Context2d()->getImageData(0, 0, 1000000, 1000000, exception_state);
+ Context2D()->getImageData(0, 0, 1000000, 1000000, exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
@@ -290,14 +290,14 @@ TEST_F(CanvasRenderingContext2DAPITest,
GetImageDataIntegerOverflowNegativeParams) {
CreateContext(kNonOpaque);
DummyExceptionStateForTesting exception_state;
- ImageData* image_data = Context2d()->getImageData(
+ ImageData* image_data = Context2D()->getImageData(
1, -2147483647, 1, -2147483647, exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
- image_data = Context2d()->getImageData(-2147483647, 1, -2147483647, 1,
+ image_data = Context2D()->getImageData(-2147483647, 1, -2147483647, 1,
exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
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 8c99835e7e0..b670fe73bca 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
@@ -8,6 +8,7 @@
#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_state.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -334,8 +335,18 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilter(
scoped_refptr<ComputedStyle> filter_style = ComputedStyle::Create();
// Must set font in case the filter uses any font-relative units (em, ex)
- filter_style->SetFont(font_for_filter_);
-
+ // 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());
+ } else {
+ return nullptr;
+ }
+ }
StyleResolverState resolver_state(style_resolution_host->GetDocument(),
*style_resolution_host,
filter_style.get(), filter_style.get());
@@ -617,7 +628,7 @@ bool CanvasRenderingContext2DState::HasPattern() const {
FillStyle()->GetCanvasPattern()->GetPattern();
}
-// Only to be used if the CanvasRenderingContext2dState has Pattern
+// Only to be used if the CanvasRenderingContext2DState has Pattern
bool CanvasRenderingContext2DState::PatternIsAccelerated() const {
DCHECK(HasPattern());
return FillStyle()->GetCanvasPattern()->GetPattern()->IsTextureBacked();
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 0e164085d7b..eaf5b21390c 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
@@ -25,7 +25,7 @@ class CSSValue;
class Element;
class CanvasRenderingContext2DState final
- : public GarbageCollectedFinalized<CanvasRenderingContext2DState>,
+ : public GarbageCollected<CanvasRenderingContext2DState>,
public FontSelectorClient {
USING_GARBAGE_COLLECTED_MIXIN(CanvasRenderingContext2DState);
@@ -119,7 +119,7 @@ class CanvasRenderingContext2DState final
bool HasPattern() const;
- // Only to be used if the CanvasRenderingContext2dState has Pattern
+ // Only to be used if the CanvasRenderingContext2DState has Pattern
bool PatternIsAccelerated() const;
enum Direction { kDirectionInherit, kDirectionRTL, kDirectionLTR };
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 4f9835f30d4..4a33e8cf1a8 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
@@ -6,6 +6,7 @@
#include <memory>
#include "build/build_config.h"
+#include "components/viz/test/test_context_provider.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"
@@ -35,8 +36,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -110,13 +110,15 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
bool IsCanvasResourceHostSet(Canvas2DLayerBridge* bridge) {
return !!bridge->resource_host_;
}
- CanvasRenderingContext2D* Context2d() const {
+ CanvasRenderingContext2D* Context2D() const {
return static_cast<CanvasRenderingContext2D*>(
CanvasElement().RenderingContext());
}
void DrawSomething() {
CanvasElement().DidDraw();
- CanvasElement().FinalizeFrame();
+ CanvasElement().PreFinalizeFrame();
+ Context2D()->FinalizeFrame();
+ CanvasElement().PostFinalizeFrame();
// Grabbing an image forces a flush
CanvasElement().Snapshot(kBackBuffer, kPreferAcceleration);
}
@@ -155,7 +157,7 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
Persistent<MemoryCache> global_memory_cache_;
std::unique_ptr<ScopedAccelerated2dCanvasForTest> allow_accelerated_;
- class WrapGradients final : public GarbageCollectedFinalized<WrapGradients> {
+ class WrapGradients final : public GarbageCollected<WrapGradients> {
public:
void Trace(blink::Visitor* visitor) {
visitor->Trace(opaque_gradient_);
@@ -176,7 +178,7 @@ class CanvasRenderingContext2DTest : public ::testing::Test {
Persistent<ImageData> partial_image_data_;
FakeImageSource opaque_bitmap_;
FakeImageSource alpha_bitmap_;
- FakeGLES2Interface gl_;
+ scoped_refptr<viz::TestContextProvider> test_context_provider_;
StringOrCanvasGradientOrCanvasPattern& OpaqueGradient() {
return wrap_gradients_->opaque_gradient_;
@@ -201,15 +203,8 @@ void CanvasRenderingContext2DTest::CreateContext(OpacityMode opacity_mode,
}
void CanvasRenderingContext2DTest::SetUp() {
- auto factory = [](FakeGLES2Interface* gl, bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- gl->SetIsContextLost(false);
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl);
- };
- SharedGpuContext::SetContextProviderFactoryForTesting(
- WTF::BindRepeating(factory, WTF::Unretained(&gl_)));
-
+ test_context_provider_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(test_context_provider_.get());
allow_accelerated_.reset(
new ScopedAccelerated2dCanvasForTest(AllowsAcceleration()));
web_view_helper_ = std::make_unique<frame_test_helpers::WebViewHelper>();
@@ -350,43 +345,43 @@ class MockImageBufferSurfaceForOverwriteTesting : public Canvas2DLayerBridge {
CanvasElement().SetResourceProviderForTesting( \
nullptr, std::move(mock_surface), size); \
EXPECT_CALL(*surface_ptr, WillOverwriteCanvas()).Times(EXPECTED_OVERDRAWS); \
- Context2d()->save();
+ Context2D()->save();
#define TEST_OVERDRAW_FINALIZE \
- Context2d()->restore(); \
+ Context2D()->restore(); \
Mock::VerifyAndClearExpectations(surface_ptr);
#define TEST_OVERDRAW_1(EXPECTED_OVERDRAWS, CALL1) \
do { \
TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
- Context2d()->CALL1; \
+ Context2D()->CALL1; \
TEST_OVERDRAW_FINALIZE \
} while (0)
#define TEST_OVERDRAW_2(EXPECTED_OVERDRAWS, CALL1, CALL2) \
do { \
TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
- Context2d()->CALL1; \
- Context2d()->CALL2; \
+ Context2D()->CALL1; \
+ Context2D()->CALL2; \
TEST_OVERDRAW_FINALIZE \
} while (0)
#define TEST_OVERDRAW_3(EXPECTED_OVERDRAWS, CALL1, CALL2, CALL3) \
do { \
TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
- Context2d()->CALL1; \
- Context2d()->CALL2; \
- Context2d()->CALL3; \
+ Context2D()->CALL1; \
+ Context2D()->CALL2; \
+ Context2D()->CALL3; \
TEST_OVERDRAW_FINALIZE \
} while (0)
#define TEST_OVERDRAW_4(EXPECTED_OVERDRAWS, CALL1, CALL2, CALL3, CALL4) \
do { \
TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
- Context2d()->CALL1; \
- Context2d()->CALL2; \
- Context2d()->CALL3; \
- Context2d()->CALL4; \
+ Context2D()->CALL1; \
+ Context2D()->CALL2; \
+ Context2D()->CALL3; \
+ Context2D()->CALL4; \
TEST_OVERDRAW_FINALIZE \
} while (0)
@@ -644,14 +639,14 @@ TEST_F(CanvasRenderingContext2DTest, GPUMemoryUpdateForAcceleratedCanvas) {
TEST_F(CanvasRenderingContext2DTest, CanvasDisposedBeforeContext) {
CreateContext(kNonOpaque);
- Context2d()->fillRect(0, 0, 1, 1); // results in task observer registration
+ Context2D()->fillRect(0, 0, 1, 1); // results in task observer registration
- Context2d()->DetachHost();
+ Context2D()->DetachHost();
// This is the only method that is callable after DetachHost
// Test passes by not crashing.
base::PendingTask dummy_pending_task(FROM_HERE, base::Closure());
- Context2d()->DidProcessTask(dummy_pending_task);
+ Context2D()->DidProcessTask(dummy_pending_task);
// Test passes by not crashing during teardown
}
@@ -691,7 +686,7 @@ TEST_F(CanvasRenderingContext2DTest,
size, CanvasColorParams(), kPreferAcceleration);
CanvasElement().SetResourceProviderForTesting(
nullptr, std::move(fake_accelerate_surface), size);
- CanvasRenderingContext2D* context = Context2d();
+ CanvasRenderingContext2D* context = Context2D();
// 800 = 10 * 10 * 4 * 2 where 10*10 is canvas size, 4 is num of bytes per
// pixel per buffer, and 2 is an estimate of num of gpu buffers required
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h
index d581278e224..909768d929b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h
@@ -15,7 +15,7 @@
namespace blink {
-class HitRegion final : public GarbageCollectedFinalized<HitRegion> {
+class HitRegion final : public GarbageCollected<HitRegion> {
public:
HitRegion(const Path&, const HitRegionOptions*);
virtual ~HitRegion() = default;
@@ -37,8 +37,7 @@ class HitRegion final : public GarbageCollectedFinalized<HitRegion> {
WindRule fill_rule_;
};
-class HitRegionManager final
- : public GarbageCollectedFinalized<HitRegionManager> {
+class HitRegionManager final : public GarbageCollected<HitRegionManager> {
public:
HitRegionManager() = default;
~HitRegionManager() {}
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 c064aa71a5d..66271ef4cc5 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
#include "third_party/blink/renderer/modules/canvas/htmlcanvas/canvas_context_creation_attributes_helpers.h"
@@ -36,6 +37,7 @@ void HTMLCanvasElementModule::getContext(
}
OffscreenCanvas* HTMLCanvasElementModule::transferControlToOffscreen(
+ ExecutionContext* execution_context,
HTMLCanvasElement& canvas,
ExceptionState& exception_state) {
OffscreenCanvas* offscreen_canvas = nullptr;
@@ -45,8 +47,8 @@ OffscreenCanvas* HTMLCanvasElementModule::transferControlToOffscreen(
"Cannot transfer control from a canvas for more than one time.");
} else {
canvas.CreateLayer();
- offscreen_canvas =
- TransferControlToOffscreenInternal(canvas, exception_state);
+ offscreen_canvas = TransferControlToOffscreenInternal(
+ execution_context, canvas, exception_state);
}
UMA_HISTOGRAM_BOOLEAN("Blink.OffscreenCanvas.TransferControlToOffscreen",
@@ -55,6 +57,7 @@ OffscreenCanvas* HTMLCanvasElementModule::transferControlToOffscreen(
}
OffscreenCanvas* HTMLCanvasElementModule::TransferControlToOffscreenInternal(
+ ExecutionContext* execution_context,
HTMLCanvasElement& canvas,
ExceptionState& exception_state) {
if (canvas.RenderingContext()) {
@@ -63,10 +66,16 @@ OffscreenCanvas* HTMLCanvasElementModule::TransferControlToOffscreenInternal(
"Cannot transfer control from a canvas that has a rendering context.");
return nullptr;
}
- OffscreenCanvas* offscreen_canvas =
- OffscreenCanvas::Create(canvas.width(), canvas.height());
+ OffscreenCanvas* offscreen_canvas = OffscreenCanvas::Create(
+ execution_context, canvas.width(), canvas.height());
offscreen_canvas->SetFilterQuality(canvas.FilterQuality());
+ // If this canvas is cross-origin, then the associated offscreen canvas
+ // should prefer using the low-power GPU.
+ LocalFrame* frame = canvas.GetDocument().GetFrame();
+ if (!(frame && frame->IsCrossOriginSubframe()))
+ offscreen_canvas->AllowHighPerformancePowerPreference();
+
DOMNodeId canvas_id = DOMNodeIds::IdForNode(&canvas);
offscreen_canvas->SetPlaceholderCanvasId(canvas_id);
canvas.RegisterPlaceholderCanvas(static_cast<int>(canvas_id));
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 2752cff6ec0..85dff7093da 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
@@ -26,11 +26,13 @@ class MODULES_EXPORT HTMLCanvasElementModule {
const CanvasContextCreationAttributesModule*,
ExceptionState&,
RenderingContext&);
- static OffscreenCanvas* transferControlToOffscreen(HTMLCanvasElement&,
+ static OffscreenCanvas* transferControlToOffscreen(ExecutionContext*,
+ HTMLCanvasElement&,
ExceptionState&);
private:
- static OffscreenCanvas* TransferControlToOffscreenInternal(HTMLCanvasElement&,
+ static OffscreenCanvas* TransferControlToOffscreenInternal(ExecutionContext*,
+ HTMLCanvasElement&,
ExceptionState&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl
index c342789f3c5..1c40f9aef68 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.idl
@@ -24,6 +24,6 @@ typedef (CanvasRenderingContext2D or
// Related spec issue: https://github.com/whatwg/html/issues/595
[RaisesException] RenderingContext? getContext(DOMString contextId, [PermissiveDictionaryConversion] optional CanvasContextCreationAttributesModule attributes);
- [RuntimeEnabled=SurfaceEmbeddingFeatures,
+ [CallWith=ExecutionContext, RuntimeEnabled=SurfaceEmbeddingFeatures,
RaisesException, MeasureAs=OffscreenCanvas] OffscreenCanvas transferControlToOffscreen();
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
index 60d6efdc2da..3ca7190541e 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
@@ -24,5 +24,5 @@ typedef (CanvasRenderingContext2D or
// (and is not undefined or null). The binding must ignore this.
// Related spec issue: https://github.com/whatwg/html/issues/595
[RaisesException] RenderingContext? getContext(DOMString contextId, [PermissiveDictionaryConversion] optional CanvasContextCreationAttributesModule attributes);
- [RaisesException, MeasureAs=OffscreenCanvas, RuntimeEnabled=SurfaceEmbeddingFeatures] OffscreenCanvas transferControlToOffscreen();
+ [CallWith=ExecutionContext, RaisesException, MeasureAs=OffscreenCanvas, RuntimeEnabled=SurfaceEmbeddingFeatures] OffscreenCanvas transferControlToOffscreen();
};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_test.cc b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_test.cc
index d2562abcddc..7ba7ea2d500 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_test.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_test.cc
@@ -10,6 +10,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/frame_sinks/embedded_frame_sink.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -67,7 +68,7 @@ class HTMLCanvasElementModuleTest : public ::testing::Test,
HTMLCanvasElement& canvas_element() const { return *canvas_element_; }
OffscreenCanvas* TransferControlToOffscreen(ExceptionState& exception_state) {
return HTMLCanvasElementModule::TransferControlToOffscreenInternal(
- canvas_element(), exception_state);
+ &GetDocument(), canvas_element(), exception_state);
}
frame_test_helpers::WebViewHelper web_view_helper_;
@@ -144,7 +145,9 @@ TEST_P(HTMLCanvasElementModuleTest, LowLatencyCanvasCompositorFrameOpacity) {
EXPECT_NE(shared_quad_state_list.front()->are_contents_opaque,
context_alpha);
})));
- canvas_element().FinalizeFrame();
+ canvas_element().PreFinalizeFrame();
+ context_->FinalizeFrame();
+ canvas_element().PostFinalizeFrame();
platform->RunUntilIdle();
}
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 801b9140d0f..99ba3fc72c2 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
@@ -51,7 +51,7 @@ void ImageBitmapRenderingContextBase::SetImage(ImageBitmap* image_bitmap) {
}
scoped_refptr<StaticBitmapImage> ImageBitmapRenderingContextBase::GetImage(
- AccelerationHint) const {
+ AccelerationHint) {
return image_layer_bridge_->GetImage();
}
@@ -63,7 +63,7 @@ ImageBitmapRenderingContextBase::GetImageAndResetInternal() {
SkBitmap black_bitmap;
black_bitmap.allocN32Pixels(copy_image->width(), copy_image->height());
- black_bitmap.eraseColor(SkColorSetRGB(0, 0, 0));
+ black_bitmap.eraseARGB(0, 0, 0, 0);
image_layer_bridge_->SetImage(
StaticBitmapImage::Create(SkImage::MakeFromBitmap(black_bitmap)));
@@ -99,11 +99,11 @@ bool ImageBitmapRenderingContextBase::CanCreateCanvas2dResourceProvider()
return !!static_cast<OffscreenCanvas*>(Host())->GetOrCreateResourceProvider();
}
-void ImageBitmapRenderingContextBase::PushFrame() {
+bool ImageBitmapRenderingContextBase::PushFrame() {
DCHECK(Host());
DCHECK(Host()->IsOffscreenCanvas());
if (!CanCreateCanvas2dResourceProvider())
- return;
+ return false;
scoped_refptr<StaticBitmapImage> image = image_layer_bridge_->GetImage();
cc::PaintFlags paint_flags;
@@ -116,6 +116,7 @@ void ImageBitmapRenderingContextBase::PushFrame() {
std::move(resource),
SkIRect::MakeWH(image_layer_bridge_->GetImage()->Size().Width(),
image_layer_bridge_->GetImage()->Size().Height()));
+ return true;
}
bool ImageBitmapRenderingContextBase::IsOriginTopLeft() const {
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 7cb61cd9c5e..7f6ce8530d6 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
@@ -43,9 +43,9 @@ class MODULES_EXPORT ImageBitmapRenderingContextBase
void SetIsHidden(bool) override {}
bool isContextLost() const override { return false; }
void SetImage(ImageBitmap*);
- // The acceleration hing here is ignored as GetImage(AccelerationHint) only
+ // The acceleration hint here is ignored as GetImage(AccelerationHint) only
// calls to image_layer_bridge->GetImage(), without giving it a hint
- scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final;
+ scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) final;
// This function resets the internal image resource to a image of the same
// size than the original, with the same properties, but completely black.
// This is used to follow the standard regarding transferToBitmap
@@ -53,7 +53,7 @@ class MODULES_EXPORT ImageBitmapRenderingContextBase
void SetUV(const FloatPoint& left_top, const FloatPoint& right_bottom);
bool IsComposited() const final { return true; }
bool IsAccelerated() const final;
- void PushFrame() override;
+ bool PushFrame() override;
bool IsOriginTopLeft() const override;
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 3c90dfbb7e1..025d75da414 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
@@ -92,7 +92,7 @@ void OffscreenCanvasTest::SetUp() {
DummyExceptionStateForTesting exception_state;
offscreen_canvas_ = HTMLCanvasElementModule::transferControlToOffscreen(
- *canvas_element, exception_state);
+ &GetDocument(), *canvas_element, exception_state);
// |offscreen_canvas_| should inherit the FrameSinkId from |canvas_element|s
// SurfaceLayerBridge, but in tests this id is zero; fill it up by hand.
offscreen_canvas_->SetFrameSinkId(kClientId, kSinkId);
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 8fc6edaec56..bd9d23f974a 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,6 +5,7 @@
#include "third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h"
#include "base/metrics/histogram_functions.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/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
@@ -19,6 +20,7 @@
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.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/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/text/bidi_text_run.h"
@@ -79,8 +81,26 @@ OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D(
OffscreenCanvas* canvas,
const CanvasContextCreationAttributesCore& attrs)
: CanvasRenderingContext(canvas, attrs),
+ is_deferral_enabled_(
+ base::FeatureList::IsEnabled(features::kCanvasAlwaysDeferral)),
random_generator_((uint32_t)base::RandUint64()),
bernoulli_distribution_(kUMASampleProbability) {
+ is_valid_size_ = IsValidImageSize(Host()->Size());
+
+ if (is_deferral_enabled_) {
+ StartRecording();
+
+ // Clear the background transparent or opaque. Similar code at
+ // CanvasResourceProvider::Clear().
+ if (IsCanvas2DBufferValid()) {
+ DCHECK(recorder_);
+ recorder_->getRecordingCanvas()->clear(
+ ColorParams().GetOpacityMode() == kOpaque ? SK_ColorBLACK
+ : SK_ColorTRANSPARENT);
+ DidDraw();
+ }
+ }
+
ExecutionContext* execution_context = canvas->GetTopExecutionContext();
if (auto* document = DynamicTo<Document>(execution_context)) {
Settings* settings = document->GetSettings();
@@ -104,10 +124,50 @@ void OffscreenCanvasRenderingContext2D::commit() {
// TODO(fserb): consolidate this with PushFrame
SkIRect damage_rect(dirty_rect_for_commit_);
dirty_rect_for_commit_.setEmpty();
+ FinalizeFrame();
Host()->Commit(ProduceCanvasResource(), damage_rect);
GetOffscreenFontCache().PruneLocalFontCache(kMaxCachedFonts);
}
+void OffscreenCanvasRenderingContext2D::StartRecording() {
+ DCHECK(is_deferral_enabled_);
+ recorder_ = std::make_unique<PaintRecorder>();
+
+ cc::PaintCanvas* canvas = recorder_->beginRecording(Width(), Height());
+ // Always save an initial frame, to support resetting the top level matrix
+ // and clip.
+ canvas->save();
+
+ RestoreMatrixClipStack(canvas);
+}
+
+void OffscreenCanvasRenderingContext2D::FlushRecording() {
+ if (!have_recorded_draw_commands_)
+ return;
+
+ { // Make a new scope so that PaintRecord gets deleted and that gets timed
+ CanvasResourceProvider* resource_provider = GetCanvasResourceProvider();
+ cc::PaintCanvas* canvas = resource_provider->Canvas();
+ canvas->drawPicture(recorder_->finishRecordingAsPicture());
+ resource_provider->FlushSkia();
+ }
+ GetCanvasResourceProvider()->ReleaseLockedImages();
+
+ if (is_deferral_enabled_)
+ StartRecording();
+ have_recorded_draw_commands_ = false;
+}
+
+void OffscreenCanvasRenderingContext2D::FinalizeFrame() {
+ TRACE_EVENT0("blink", "OffscreenCanvasRenderingContext2D::FinalizeFrame");
+
+ // Make sure surface is ready for painting: fix the rendering mode now
+ // because it will be too late during the paint invalidation phase.
+ if (!GetOrCreateCanvasResourceProvider())
+ return;
+ FlushRecording();
+}
+
// BaseRenderingContext2D implementation
bool OffscreenCanvasRenderingContext2D::OriginClean() const {
return Host()->OriginClean();
@@ -134,7 +194,13 @@ bool OffscreenCanvasRenderingContext2D::CanCreateCanvas2dResourceProvider()
const {
if (!Host() || Host()->Size().IsEmpty())
return false;
- return !!offscreenCanvasForBinding()->GetOrCreateResourceProvider();
+ return !!GetOrCreateCanvasResourceProvider();
+}
+
+CanvasResourceProvider*
+OffscreenCanvasRenderingContext2D::GetOrCreateCanvasResourceProvider() const {
+ // TODO(aaronhk) use Host() instead of offscreenCanvasForBinding() here
+ return offscreenCanvasForBinding()->GetOrCreateResourceProvider();
}
CanvasResourceProvider*
@@ -144,11 +210,15 @@ OffscreenCanvasRenderingContext2D::GetCanvasResourceProvider() const {
void OffscreenCanvasRenderingContext2D::Reset() {
Host()->DiscardResourceProvider();
BaseRenderingContext2D::Reset();
+ if (is_deferral_enabled_)
+ StartRecording();
+ // Because the host may have changed to a zero size
+ is_valid_size_ = IsValidImageSize(Host()->Size());
}
scoped_refptr<CanvasResource>
OffscreenCanvasRenderingContext2D::ProduceCanvasResource() {
- if (!CanCreateCanvas2dResourceProvider())
+ if (!GetOrCreateCanvasResourceProvider())
return nullptr;
scoped_refptr<CanvasResource> frame =
GetCanvasResourceProvider()->ProduceCanvasResource();
@@ -159,14 +229,16 @@ OffscreenCanvasRenderingContext2D::ProduceCanvasResource() {
return frame;
}
-void OffscreenCanvasRenderingContext2D::PushFrame() {
+bool OffscreenCanvasRenderingContext2D::PushFrame() {
if (dirty_rect_for_commit_.isEmpty())
- return;
+ return false;
SkIRect damage_rect(dirty_rect_for_commit_);
- Host()->PushFrame(ProduceCanvasResource(), damage_rect);
+ FinalizeFrame();
+ bool ret = Host()->PushFrame(ProduceCanvasResource(), damage_rect);
dirty_rect_for_commit_.setEmpty();
GetOffscreenFontCache().PruneLocalFontCache(kMaxCachedFonts);
+ return ret;
}
ImageBitmap* OffscreenCanvasRenderingContext2D::TransferToImageBitmap(
@@ -174,25 +246,39 @@ ImageBitmap* OffscreenCanvasRenderingContext2D::TransferToImageBitmap(
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmap2D;
UseCounter::Count(ExecutionContext::From(script_state), feature);
- if (!CanCreateCanvas2dResourceProvider())
+ if (!GetOrCreateCanvasResourceProvider())
return nullptr;
- scoped_refptr<StaticBitmapImage> image =
- GetCanvasResourceProvider()->Snapshot();
+ scoped_refptr<StaticBitmapImage> image = GetImage(kPreferAcceleration);
if (!image)
return nullptr;
image->SetOriginClean(this->OriginClean());
if (image->IsTextureBacked()) {
// Before discarding the image resource, we need to flush pending render ops
// to fully resolve the snapshot.
- image->PaintImageForCurrentFrame().GetSkImage()->getBackendTexture(
- true); // Flush pending ops.
+ // We can only do this if the skImage is not null
+ if (auto skImage = image->PaintImageForCurrentFrame().GetSkImage()) {
+ skImage->getBackendTexture(true); // Flush pending ops.
+ } else {
+ // If the SkImage was null, we better return a null ImageBitmap
+ return nullptr;
+ }
}
- Host()->DiscardResourceProvider(); // "Transfer" means no retained buffer.
+
+ // "Transfer" means no retained buffer. Matrix transformations need to be
+ // preserved though.
+ Host()->DiscardResourceProvider();
+ if (is_deferral_enabled_) {
+ recorder_->getRecordingCanvas()->restore();
+ recorder_->getRecordingCanvas()->save();
+ Host()->SetNeedsMatrixClipRestore();
+ }
+
return ImageBitmap::Create(std::move(image));
}
scoped_refptr<StaticBitmapImage> OffscreenCanvasRenderingContext2D::GetImage(
- AccelerationHint hint) const {
+ AccelerationHint hint) {
+ FinalizeFrame();
if (!IsPaintable())
return nullptr;
scoped_refptr<StaticBitmapImage> image =
@@ -213,6 +299,10 @@ bool OffscreenCanvasRenderingContext2D::ParseColorOrCurrentColor(
}
cc::PaintCanvas* OffscreenCanvasRenderingContext2D::DrawingCanvas() const {
+ if (!is_valid_size_)
+ return nullptr;
+ if (is_deferral_enabled_)
+ return recorder_->getRecordingCanvas();
if (!CanCreateCanvas2dResourceProvider())
return nullptr;
return GetCanvasResourceProvider()->Canvas();
@@ -220,17 +310,25 @@ cc::PaintCanvas* OffscreenCanvasRenderingContext2D::DrawingCanvas() const {
cc::PaintCanvas* OffscreenCanvasRenderingContext2D::ExistingDrawingCanvas()
const {
+ if (!is_valid_size_)
+ return nullptr;
+ if (is_deferral_enabled_)
+ return recorder_->getRecordingCanvas();
if (!IsPaintable())
return nullptr;
return GetCanvasResourceProvider()->Canvas();
}
void OffscreenCanvasRenderingContext2D::DidDraw() {
+ if (is_deferral_enabled_)
+ have_recorded_draw_commands_ = true;
Host()->DidDraw();
dirty_rect_for_commit_.setWH(Width(), Height());
}
void OffscreenCanvasRenderingContext2D::DidDraw(const SkIRect& dirty_rect) {
+ if (is_deferral_enabled_)
+ have_recorded_draw_commands_ = true;
dirty_rect_for_commit_.join(dirty_rect);
Host()->DidDraw(SkRect::Make(dirty_rect_for_commit_));
}
@@ -283,6 +381,17 @@ bool OffscreenCanvasRenderingContext2D::WritePixels(
int x,
int y) {
DCHECK(IsPaintable());
+
+ FinalizeFrame();
+ // WritePixels is not supported by deferral. Since we are directly rendering,
+ // we can't do deferral on top of the canvas. Disable deferral completely.
+ is_deferral_enabled_ = false;
+ have_recorded_draw_commands_ = false;
+ recorder_.reset();
+ // install the current matrix/clip stack onto the immediate canvas
+ if (GetOrCreateCanvasResourceProvider())
+ RestoreMatrixClipStack(GetCanvasResourceProvider()->Canvas());
+
return offscreenCanvasForBinding()->ResourceProvider()->WritePixels(
orig_info, pixels, row_bytes, x, y);
}
@@ -513,8 +622,7 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
Draw(
[&font, &text_run_paint_info, &location](
- cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
- {
+ cc::PaintCanvas* c, const PaintFlags* flags) /* draw lambda */ {
font.DrawBidiText(c, text_run_paint_info, location,
Font::kUseFallbackIfFontNotReady, kCDeviceScaleFactor,
*flags);
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 89270c56caa..eff614da236 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
@@ -12,6 +12,7 @@
#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/modules/canvas/canvas2d/base_rendering_context_2d.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
namespace blink {
@@ -40,7 +41,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
}
CanvasRenderingContext::ContextType GetContextType() const override {
- return CanvasRenderingContext::kContext2d;
+ return CanvasRenderingContext::kContext2D;
}
};
@@ -57,7 +58,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
// CanvasRenderingContext implementation
~OffscreenCanvasRenderingContext2D() override;
- ContextType GetContextType() const override { return kContext2d; }
+ ContextType GetContextType() const override { return kContext2D; }
bool Is2d() const override { return true; }
bool IsComposited() const override { return false; }
bool IsAccelerated() const override;
@@ -68,7 +69,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
void ClearRect(double x, double y, double width, double height) override {
BaseRenderingContext2D::clearRect(x, y, width, height);
}
- scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final;
+ scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) final;
void Reset() override;
void RestoreCanvasMatrixClipStack(cc::PaintCanvas* c) const override {
RestoreMatrixClipStack(c);
@@ -95,6 +96,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
int Height() const final;
bool CanCreateCanvas2dResourceProvider() const final;
+ CanvasResourceProvider* GetOrCreateCanvasResourceProvider() const;
CanvasResourceProvider* GetCanvasResourceProvider() const;
bool ParseColorOrCurrentColor(Color&, const String& color_string) const final;
@@ -118,13 +120,12 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
void Trace(blink::Visitor*) override;
- void PushFrame() override;
+ bool PushFrame() override;
- protected:
- void NeedsFinalizeFrame() override {
- CanvasRenderingContext::NeedsFinalizeFrame();
- }
+ bool HasRecordedDrawCommands() { return have_recorded_draw_commands_; }
+ bool IsDeferralEnabled() const final { return is_deferral_enabled_; }
+ protected:
CanvasColorParams ColorParams() const override;
bool WritePixels(const SkImageInfo& orig_info,
const void* pixels,
@@ -133,6 +134,13 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
int y) override;
private:
+ void StartRecording();
+ bool is_deferral_enabled_;
+ std::unique_ptr<PaintRecorder> recorder_;
+ bool have_recorded_draw_commands_;
+ void FinalizeFrame() final;
+ void FlushRecording();
+
bool IsPaintable() const final;
bool IsCanvas2DBufferValid() const override;
@@ -149,6 +157,8 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
CanvasPixelFormat PixelFormat() const override;
SkIRect dirty_rect_for_commit_;
+ bool is_valid_size_ = false;
+
std::mt19937 random_generator_;
std::bernoulli_distribution bernoulli_distribution_;
};
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 9867510ac72..c4191eb0b65 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -21,9 +21,8 @@ namespace blink {
class ScriptPromiseResolver;
-class ClipboardPromise final
- : public GarbageCollectedFinalized<ClipboardPromise>,
- public ContextLifecycleObserver {
+class ClipboardPromise final : public GarbageCollected<ClipboardPromise>,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(ClipboardPromise);
public:
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 ef4542d3e1e..496ad215663 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_reader.cc
@@ -31,8 +31,12 @@ class ClipboardImageReader final : public ClipboardReader {
SkPixmap pixmap;
bitmap.peekPixels(&pixmap);
- Vector<uint8_t> png_data;
+ // 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;
diff --git a/chromium/third_party/blink/renderer/modules/compression/BUILD.gn b/chromium/third_party/blink/renderer/modules/compression/BUILD.gn
new file mode 100644
index 00000000000..b5a2071fa96
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/BUILD.gn
@@ -0,0 +1,16 @@
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("compression") {
+ sources = [
+ "compression_stream.cc",
+ "compression_stream.h",
+ "decompression_stream.cc",
+ "decompression_stream.h",
+ "deflate_transformer.cc",
+ "deflate_transformer.h",
+ "inflate_transformer.cc",
+ "inflate_transformer.h",
+ "zlib_partition_alloc.cc",
+ "zlib_partition_alloc.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/compression/OWNERS b/chromium/third_party/blink/renderer/modules/compression/OWNERS
new file mode 100644
index 00000000000..b63f88130bc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/OWNERS
@@ -0,0 +1,5 @@
+yhirano@chromium.org
+ricea@chromium.org
+
+# TEAM: blink-network-dev@chromium.org
+# COMPONENT: Blink>Network>StreamsAPI
diff --git a/chromium/third_party/blink/renderer/modules/compression/README.md b/chromium/third_party/blink/renderer/modules/compression/README.md
new file mode 100644
index 00000000000..3a65da92f28
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/README.md
@@ -0,0 +1,8 @@
+# CompressionStreams API
+
+This directory contains the implementation of CompressionStream and
+DecompressionStream.
+
+## Design docs
+
+See [DecompressionStream Design Docs](https://docs.google.com/document/d/1TovyqqeC3HoO0A4UUBKiCyhZlQSl7jM_F7KbWjK2Gcs/edit).
diff --git a/chromium/third_party/blink/renderer/modules/compression/compression_stream.cc b/chromium/third_party/blink/renderer/modules/compression/compression_stream.cc
new file mode 100644
index 00000000000..5959a7bbea2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/compression_stream.cc
@@ -0,0 +1,53 @@
+// 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/compression/compression_stream.h"
+
+#include "third_party/blink/renderer/modules/compression/deflate_transformer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+namespace blink {
+
+CompressionStream* CompressionStream::Create(ScriptState* script_state,
+ const AtomicString& format,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<CompressionStream>(script_state, format,
+ exception_state);
+}
+
+ReadableStream* CompressionStream::readable() const {
+ return transform_->Readable();
+}
+
+WritableStream* CompressionStream::writable() const {
+ return transform_->Writable();
+}
+
+void CompressionStream::Trace(Visitor* visitor) {
+ visitor->Trace(transform_);
+ ScriptWrappable::Trace(visitor);
+}
+
+CompressionStream::CompressionStream(ScriptState* script_state,
+ const AtomicString& format,
+ ExceptionState& exception_state)
+ : transform_(MakeGarbageCollected<TransformStream>()) {
+ DeflateTransformer::Format deflate_format =
+ DeflateTransformer::Format::kDeflate;
+ if (format == "gzip") {
+ deflate_format = DeflateTransformer::Format::kGzip;
+ } else if (format != "deflate") {
+ exception_state.ThrowTypeError("Unsupported format");
+ return;
+ }
+
+ // default level is hardcoded for now.
+ // TODO(arenevier): Make level configurable
+ const int deflate_level = 6;
+ transform_->Init(MakeGarbageCollected<DeflateTransformer>(
+ script_state, deflate_format, deflate_level),
+ script_state, exception_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/compression/compression_stream.h b/chromium/third_party/blink/renderer/modules/compression/compression_stream.h
new file mode 100644
index 00000000000..4a96737539c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/compression_stream.h
@@ -0,0 +1,36 @@
+// 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_COMPRESSION_COMPRESSION_STREAM_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_COMPRESSION_STREAM_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/streams/transform_stream.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class CompressionStream final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static CompressionStream* Create(ScriptState*,
+ const AtomicString&,
+ ExceptionState&);
+ CompressionStream(ScriptState*, const AtomicString&, ExceptionState&);
+
+ ReadableStream* readable() const;
+ WritableStream* writable() const;
+
+ void Trace(Visitor*) override;
+
+ private:
+ const Member<TransformStream> transform_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompressionStream);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_COMPRESSION_STREAM_H_
diff --git a/chromium/third_party/blink/renderer/modules/compression/compression_stream.idl b/chromium/third_party/blink/renderer/modules/compression/compression_stream.idl
new file mode 100644
index 00000000000..475b817bacc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/compression_stream.idl
@@ -0,0 +1,11 @@
+[
+ Exposed=(Window,Worker),
+ Constructor(DOMString format),
+ ConstructorCallWith=ScriptState,
+ RuntimeEnabled=CompressionStreams,
+ RaisesException=Constructor,
+ MeasureAs=CompressionStreamConstructor
+] interface CompressionStream {
+ readonly attribute ReadableStream readable;
+ readonly attribute WritableStream writable;
+};
diff --git a/chromium/third_party/blink/renderer/modules/compression/decompression_stream.cc b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.cc
new file mode 100644
index 00000000000..cb1fbc4bbd6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.cc
@@ -0,0 +1,46 @@
+#include "third_party/blink/renderer/modules/compression/decompression_stream.h"
+#include "third_party/blink/renderer/modules/compression/inflate_transformer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+namespace blink {
+
+DecompressionStream* DecompressionStream::Create(
+ ScriptState* script_state,
+ const AtomicString& format,
+ ExceptionState& exception_state) {
+ return MakeGarbageCollected<DecompressionStream>(script_state, format,
+ exception_state);
+}
+
+ReadableStream* DecompressionStream::readable() const {
+ return transform_->Readable();
+}
+
+WritableStream* DecompressionStream::writable() const {
+ return transform_->Writable();
+}
+
+void DecompressionStream::Trace(Visitor* visitor) {
+ visitor->Trace(transform_);
+ ScriptWrappable::Trace(visitor);
+}
+
+DecompressionStream::DecompressionStream(ScriptState* script_state,
+ const AtomicString& format,
+ ExceptionState& exception_state)
+ : transform_(MakeGarbageCollected<TransformStream>()) {
+ InflateTransformer::Format deflate_format =
+ InflateTransformer::Format::kDeflate;
+ if (format == "gzip") {
+ deflate_format = InflateTransformer::Format::kGzip;
+ } else if (format != "deflate") {
+ exception_state.ThrowTypeError("Unsupported format");
+ return;
+ }
+
+ transform_->Init(
+ MakeGarbageCollected<InflateTransformer>(script_state, deflate_format),
+ script_state, exception_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/compression/decompression_stream.h b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.h
new file mode 100644
index 00000000000..3e2495fb416
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.h
@@ -0,0 +1,32 @@
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DECOMPRESSION_STREAM_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DECOMPRESSION_STREAM_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/core/streams/transform_stream.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class DecompressionStream final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static DecompressionStream* Create(ScriptState*,
+ const AtomicString&,
+ ExceptionState&);
+ DecompressionStream(ScriptState*, const AtomicString&, ExceptionState&);
+
+ ReadableStream* readable() const;
+ WritableStream* writable() const;
+
+ void Trace(Visitor* visitor) override;
+
+ private:
+ const Member<TransformStream> transform_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecompressionStream);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DECOMPRESSION_STREAM_H_
diff --git a/chromium/third_party/blink/renderer/modules/compression/decompression_stream.idl b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.idl
new file mode 100644
index 00000000000..b22d90410f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/decompression_stream.idl
@@ -0,0 +1,11 @@
+[
+ Exposed=(Window,Worker),
+ Constructor(DOMString format),
+ ConstructorCallWith=ScriptState,
+ RaisesException=Constructor,
+ RuntimeEnabled=CompressionStreams,
+ MeasureAs=DecompressionStreamConstructor
+] interface DecompressionStream {
+ readonly attribute ReadableStream readable;
+ readonly attribute WritableStream writable;
+};
diff --git a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc
new file mode 100644
index 00000000000..f8ee728c486
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.cc
@@ -0,0 +1,121 @@
+// 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/compression/deflate_transformer.h"
+
+#include <string.h>
+#include <algorithm>
+#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/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.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/modules/compression/zlib_partition_alloc.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/to_v8.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+DeflateTransformer::DeflateTransformer(ScriptState* script_state,
+ Format format,
+ int level)
+ : script_state_(script_state), out_buffer_(kBufferSize) {
+ DCHECK(level >= 1 && level <= 9);
+ memset(&stream_, 0, sizeof(z_stream));
+ ZlibPartitionAlloc::Configure(&stream_);
+ constexpr int kWindowBits = 15;
+ constexpr int kUseGzip = 16;
+ int err;
+ switch (format) {
+ case Format::kDeflate:
+ err = deflateInit2(&stream_, level, Z_DEFLATED, kWindowBits, 8,
+ Z_DEFAULT_STRATEGY);
+ break;
+ case Format::kGzip:
+ err = deflateInit2(&stream_, level, Z_DEFLATED, kWindowBits + kUseGzip, 8,
+ Z_DEFAULT_STRATEGY);
+ break;
+ }
+ DCHECK_EQ(Z_OK, err);
+}
+
+DeflateTransformer::~DeflateTransformer() {
+ if (!was_flush_called_) {
+ deflateEnd(&stream_);
+ }
+}
+
+void DeflateTransformer::Transform(
+ v8::Local<v8::Value> chunk,
+ TransformStreamDefaultControllerInterface* controller,
+ ExceptionState& exception_state) {
+ ArrayBufferOrArrayBufferView buffer_source;
+ V8ArrayBufferOrArrayBufferView::ToImpl(
+ script_state_->GetIsolate(), chunk, buffer_source,
+ UnionTypeConversionMode::kNotNullable, exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+ if (buffer_source.IsArrayBufferView()) {
+ const auto* view = buffer_source.GetAsArrayBufferView().View();
+ const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
+ wtf_size_t length = view->byteLength();
+ Deflate(start, length, IsFinished(false), controller, exception_state);
+ return;
+ }
+ DCHECK(buffer_source.IsArrayBuffer());
+ const auto* array_buffer = buffer_source.GetAsArrayBuffer();
+ const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
+ wtf_size_t length = array_buffer->ByteLength();
+ Deflate(start, length, IsFinished(false), controller, exception_state);
+}
+
+void DeflateTransformer::Flush(
+ TransformStreamDefaultControllerInterface* controller,
+ ExceptionState& exception_state) {
+ Deflate(nullptr, 0u, IsFinished(true), controller, exception_state);
+ was_flush_called_ = true;
+ deflateEnd(&stream_);
+ out_buffer_.clear();
+}
+
+void DeflateTransformer::Deflate(
+ const uint8_t* start,
+ wtf_size_t length,
+ IsFinished finished,
+ TransformStreamDefaultControllerInterface* controller,
+ ExceptionState& exception_state) {
+ stream_.avail_in = length;
+ // Zlib treats this pointer as const, so this cast is safe.
+ stream_.next_in = const_cast<uint8_t*>(start);
+
+ do {
+ stream_.avail_out = out_buffer_.size();
+ stream_.next_out = out_buffer_.data();
+ int err = deflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
+ DCHECK((finished && err == Z_STREAM_END) || err == Z_OK ||
+ err == Z_BUF_ERROR);
+
+ wtf_size_t bytes = out_buffer_.size() - stream_.avail_out;
+ if (bytes) {
+ controller->Enqueue(
+ ToV8(DOMUint8Array::Create(out_buffer_.data(), bytes), script_state_),
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+ }
+ } while (stream_.avail_out == 0);
+}
+
+void DeflateTransformer::Trace(Visitor* visitor) {
+ visitor->Trace(script_state_);
+ TransformStreamTransformer::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h
new file mode 100644
index 00000000000..c3b93c0c7ca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/deflate_transformer.h
@@ -0,0 +1,60 @@
+// 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_COMPRESSION_DEFLATE_TRANSFORMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_
+
+#include "base/util/type_safety/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"
+#include "third_party/zlib/zlib.h"
+
+namespace blink {
+
+class DeflateTransformer final : public TransformStreamTransformer {
+ public:
+ enum class Format { kGzip, kDeflate };
+
+ DeflateTransformer(ScriptState*, Format, int level);
+ ~DeflateTransformer() override;
+
+ void Transform(v8::Local<v8::Value> chunk,
+ TransformStreamDefaultControllerInterface*,
+ ExceptionState&) override;
+
+ void Flush(TransformStreamDefaultControllerInterface*,
+ ExceptionState&) override;
+
+ ScriptState* GetScriptState() override { return script_state_; }
+
+ void Trace(Visitor*) override;
+
+ private:
+ using IsFinished = util::StrongAlias<class IsFinishedTag, bool>;
+
+ void Deflate(const uint8_t*,
+ wtf_size_t,
+ IsFinished,
+ TransformStreamDefaultControllerInterface*,
+ ExceptionState&);
+
+ Member<ScriptState> script_state_;
+
+ Vector<uint8_t> out_buffer_;
+
+ z_stream stream_;
+
+ bool was_flush_called_ = false;
+
+ // This buffer size has been experimentally verified to be optimal.
+ static constexpr wtf_size_t kBufferSize = 16384;
+
+ DISALLOW_COPY_AND_ASSIGN(DeflateTransformer);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_DEFLATE_TRANSFORMER_H_
diff --git a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc
new file mode 100644
index 00000000000..372a56b410d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.cc
@@ -0,0 +1,116 @@
+#include "third_party/blink/renderer/modules/compression/inflate_transformer.h"
+
+#include <string.h>
+#include <algorithm>
+#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/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
+#include "third_party/blink/renderer/core/streams/transform_stream_default_controller_interface.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/modules/compression/zlib_partition_alloc.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/to_v8.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+InflateTransformer::InflateTransformer(ScriptState* script_state, Format format)
+ : script_state_(script_state), out_buffer_(kBufferSize) {
+ memset(&stream_, 0, sizeof(z_stream));
+ ZlibPartitionAlloc::Configure(&stream_);
+ constexpr int kWindowBits = 15;
+ constexpr int kUseGzip = 16;
+ int err;
+ switch (format) {
+ case Format::kDeflate:
+ err = inflateInit2(&stream_, kWindowBits);
+ break;
+ case Format::kGzip:
+ err = inflateInit2(&stream_, kWindowBits + kUseGzip);
+ break;
+ }
+ DCHECK_EQ(Z_OK, err);
+}
+
+InflateTransformer::~InflateTransformer() {
+ if (!was_flush_called_) {
+ inflateEnd(&stream_);
+ }
+}
+
+void InflateTransformer::Transform(
+ v8::Local<v8::Value> chunk,
+ TransformStreamDefaultControllerInterface* 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()) {
+ return;
+ }
+ if (buffer_source.IsArrayBufferView()) {
+ const auto* view = buffer_source.GetAsArrayBufferView().View();
+ const uint8_t* start = static_cast<const uint8_t*>(view->BaseAddress());
+ wtf_size_t length = view->byteLength();
+ Inflate(start, length, IsFinished(false), controller, exception_state);
+ return;
+ }
+ DCHECK(buffer_source.IsArrayBuffer());
+ const auto* array_buffer = buffer_source.GetAsArrayBuffer();
+ const uint8_t* start = static_cast<const uint8_t*>(array_buffer->Data());
+ wtf_size_t length = array_buffer->ByteLength();
+ Inflate(start, length, IsFinished(false), controller, exception_state);
+}
+
+void InflateTransformer::Flush(
+ TransformStreamDefaultControllerInterface* controller,
+ ExceptionState& exception_state) {
+ DCHECK(!was_flush_called_);
+ Inflate(nullptr, 0u, IsFinished(true), controller, exception_state);
+ inflateEnd(&stream_);
+ was_flush_called_ = true;
+ out_buffer_.clear();
+}
+
+void InflateTransformer::Inflate(
+ const uint8_t* start,
+ wtf_size_t length,
+ IsFinished finished,
+ TransformStreamDefaultControllerInterface* controller,
+ ExceptionState& exception_state) {
+ stream_.avail_in = length;
+ // Zlib treats this pointer as const, so this cast is safe.
+ stream_.next_in = const_cast<uint8_t*>(start);
+
+ do {
+ stream_.avail_out = out_buffer_.size();
+ stream_.next_out = out_buffer_.data();
+ int err = inflate(&stream_, finished ? Z_FINISH : Z_NO_FLUSH);
+ if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
+ exception_state.ThrowTypeError("The compressed data was not valid.");
+ return;
+ }
+
+ wtf_size_t bytes = out_buffer_.size() - stream_.avail_out;
+ if (bytes) {
+ controller->Enqueue(
+ ToV8(DOMUint8Array::Create(out_buffer_.data(), bytes), script_state_),
+ exception_state);
+ if (exception_state.HadException()) {
+ return;
+ }
+ }
+ } while (stream_.avail_out == 0);
+}
+
+void InflateTransformer::Trace(Visitor* visitor) {
+ visitor->Trace(script_state_);
+ TransformStreamTransformer::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h
new file mode 100644
index 00000000000..b76f2c92be2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/inflate_transformer.h
@@ -0,0 +1,56 @@
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_INFLATE_TRANSFORMER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_INFLATE_TRANSFORMER_H_
+
+#include "base/util/type_safety/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"
+#include "third_party/zlib/zlib.h"
+
+namespace blink {
+
+class InflateTransformer final : public TransformStreamTransformer {
+ public:
+ enum class Format { kDeflate, kGzip };
+
+ InflateTransformer(ScriptState*, Format format);
+ ~InflateTransformer() override;
+
+ void Transform(v8::Local<v8::Value> chunk,
+ TransformStreamDefaultControllerInterface*,
+ ExceptionState&) override;
+
+ void Flush(TransformStreamDefaultControllerInterface*,
+ ExceptionState&) override;
+
+ ScriptState* GetScriptState() override { return script_state_; }
+
+ void Trace(Visitor*) override;
+
+ private:
+ using IsFinished = util::StrongAlias<class IsFinishedTag, bool>;
+
+ void Inflate(const uint8_t*,
+ wtf_size_t,
+ IsFinished,
+ TransformStreamDefaultControllerInterface*,
+ ExceptionState&);
+
+ Member<ScriptState> script_state_;
+
+ z_stream stream_;
+
+ Vector<uint8_t> out_buffer_;
+
+ bool was_flush_called_ = false;
+
+ // This buffer size has been experimentally verified to be optimal.
+ static constexpr wtf_size_t kBufferSize = 65536;
+
+ DISALLOW_COPY_AND_ASSIGN(InflateTransformer);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_INFLATE_TRANSFORMER_H_
diff --git a/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.cc b/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.cc
new file mode 100644
index 00000000000..99297631878
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.cc
@@ -0,0 +1,20 @@
+#include "third_party/blink/renderer/modules/compression/zlib_partition_alloc.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
+
+namespace blink {
+
+void ZlibPartitionAlloc::Configure(z_stream* stream) {
+ stream->zalloc = Alloc;
+ stream->zfree = Free;
+}
+
+void* ZlibPartitionAlloc::Alloc(void*, uint32_t items, uint32_t size) {
+ // BufferMalloc is safer than FastMalloc when handling untrusted data.
+ return WTF::Partitions::BufferMalloc(items * size, "zlib");
+}
+
+void ZlibPartitionAlloc::Free(void*, void* address) {
+ WTF::Partitions::BufferFree(address);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.h b/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.h
new file mode 100644
index 00000000000..f013f1a489e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/compression/zlib_partition_alloc.h
@@ -0,0 +1,24 @@
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_ZLIB_PARTITION_ALLOC_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_ZLIB_PARTITION_ALLOC_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/zlib/zlib.h"
+
+namespace blink {
+
+// Use partition alloc for zlib allocations.
+class ZlibPartitionAlloc {
+ STATIC_ONLY(ZlibPartitionAlloc);
+
+ public:
+ static void Configure(z_stream* s);
+
+ private:
+ static void* Alloc(void*, uint32_t items, uint32_t size);
+
+ static void Free(void*, void*);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COMPRESSION_ZLIB_PARTITION_ALLOC_H_
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 9181ed759bb..2240b7eb224 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,8 @@
#include "third_party/blink/renderer/modules/contacts_picker/contacts_manager.h"
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -64,16 +65,31 @@ TypeConverter<blink::ContactInfo*, blink::mojom::blink::ContactInfoPtr>::
} // namespace mojo
namespace blink {
+namespace {
+
+// ContactProperty enum strings.
+constexpr char kAddress[] = "address";
+constexpr char kEmail[] = "email";
+constexpr char kName[] = "name";
+constexpr char kTel[] = "tel";
+
+} // namespace
+
+ContactsManager::ContactsManager() {
+ properties_ = {kEmail, kName, kTel};
+
+ if (RuntimeEnabledFeatures::ContactsManagerAddressesEnabled())
+ properties_.push_back(kAddress);
+}
-ContactsManager::ContactsManager() = default;
ContactsManager::~ContactsManager() = default;
mojo::Remote<mojom::blink::ContactsManager>&
ContactsManager::GetContactsManager(ScriptState* script_state) {
if (!contacts_manager_) {
ExecutionContext::From(script_state)
- ->GetInterfaceProvider()
- ->GetInterface(contacts_manager_.BindNewPipeAndPassReceiver());
+ ->GetBrowserInterfaceBroker()
+ .GetInterface(contacts_manager_.BindNewPipeAndPassReceiver());
}
return contacts_manager_;
}
@@ -113,22 +129,31 @@ ScriptPromise ContactsManager::select(ScriptState* script_state,
"Contacts Picker is already in use."));
}
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- ScriptPromise promise = resolver->Promise();
-
bool include_names = false;
bool include_emails = false;
bool include_tel = false;
for (const String& property : properties) {
- if (property == "name")
+ if (!base::Contains(properties_, property)) {
+ return ScriptPromise::Reject(
+ script_state,
+ V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "The provided value '" + property +
+ "' is not a valid enum value of type ContactProperty"));
+ }
+
+ if (property == kName)
include_names = true;
- else if (property == "email")
+ else if (property == kEmail)
include_emails = true;
- else if (property == "tel")
+ else if (property == kTel)
include_tel = true;
}
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
contact_picker_in_use_ = true;
GetContactsManager(script_state)
->Select(options->multiple(), include_names, include_emails, include_tel,
@@ -166,4 +191,8 @@ void ContactsManager::OnContactsSelected(
resolver->Resolve(contacts_list);
}
+ScriptPromise ContactsManager::getProperties(ScriptState* script_state) {
+ return ScriptPromise::Cast(script_state, ToV8(properties_, script_state));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
index 07ff327049e..b8b622016a9 100644
--- a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
+++ b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.h
@@ -30,6 +30,7 @@ class ContactsManager final : public ScriptWrappable {
ScriptPromise select(ScriptState* script_state,
const Vector<String>& properties,
ContactsSelectOptions* options);
+ ScriptPromise getProperties(ScriptState* script_state);
private:
mojo::Remote<mojom::blink::ContactsManager>& GetContactsManager(
@@ -42,6 +43,7 @@ class ContactsManager final : public ScriptWrappable {
// Created lazily.
mojo::Remote<mojom::blink::ContactsManager> contacts_manager_;
bool contact_picker_in_use_ = false;
+ Vector<String> properties_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.idl b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.idl
index fb3cdd586ed..697fa3a34a1 100644
--- a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.idl
+++ b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_manager.idl
@@ -9,5 +9,6 @@
SecureContext,
RuntimeEnabled=ContactsManager
] interface ContactsManager {
+ [CallWith=ScriptState, MeasureAs=ContactsManagerGetProperties] Promise<sequence<ContactProperty>> getProperties();
[CallWith=ScriptState, MeasureAs=ContactsManagerSelect] Promise<sequence<ContactInfo>> select(sequence<ContactProperty> properties, optional ContactsSelectOptions options);
};
diff --git a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_select_options.idl b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_select_options.idl
index f53294142af..279c5a385f7 100644
--- a/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_select_options.idl
+++ b/chromium/third_party/blink/renderer/modules/contacts_picker/contacts_select_options.idl
@@ -4,7 +4,7 @@
// https://wicg.github.io/contact-api/spec/#contacts-manager
-enum ContactProperty { "email", "name", "tel" };
+enum ContactProperty { "address", "email", "name", "tel" };
dictionary ContactsSelectOptions {
boolean multiple = false;
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_description.idl b/chromium/third_party/blink/renderer/modules/content_index/content_description.idl
index c32a824f00b..93b2652aa1e 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_description.idl
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_description.idl
@@ -5,6 +5,7 @@
// https://github.com/rknoll/content-index
enum ContentCategory {
+ "",
"homepage",
"article",
"video",
@@ -15,7 +16,7 @@ dictionary ContentDescription {
required DOMString id;
required DOMString title;
required DOMString description;
- required ContentCategory category;
+ ContentCategory category = "";
sequence<ContentIconDefinition> icons = [];
required USVString launchUrl;
};
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc b/chromium/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc
index 6a277033a47..889588ec042 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_description_type_converter.cc
@@ -13,6 +13,8 @@ namespace mojo {
namespace {
blink::mojom::ContentCategory GetContentCategory(const WTF::String& category) {
+ if (category == "")
+ return blink::mojom::ContentCategory::NONE;
if (category == "homepage")
return blink::mojom::ContentCategory::HOME_PAGE;
if (category == "article")
@@ -23,11 +25,13 @@ blink::mojom::ContentCategory GetContentCategory(const WTF::String& category) {
return blink::mojom::ContentCategory::AUDIO;
NOTREACHED();
- return blink::mojom::ContentCategory::ARTICLE;
+ return blink::mojom::ContentCategory::NONE;
}
WTF::String GetContentCategory(blink::mojom::ContentCategory category) {
switch (category) {
+ case blink::mojom::ContentCategory::NONE:
+ return "";
case blink::mojom::ContentCategory::HOME_PAGE:
return "homepage";
case blink::mojom::ContentCategory::ARTICLE:
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_index.cc b/chromium/third_party/blink/renderer/modules/content_index/content_index.cc
index a8b4d6f722f..3e0afe7332e 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_index.cc
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_index.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/modules/content_index/content_index.h"
#include "base/optional.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -279,8 +279,10 @@ void ContentIndex::Trace(blink::Visitor* visitor) {
mojom::blink::ContentIndexService* ContentIndex::GetService() {
if (!content_index_service_) {
- registration_->GetExecutionContext()->GetInterfaceProvider()->GetInterface(
- content_index_service_.BindNewPipeAndPassReceiver(task_runner_));
+ registration_->GetExecutionContext()
+ ->GetBrowserInterfaceBroker()
+ .GetInterface(
+ content_index_service_.BindNewPipeAndPassReceiver(task_runner_));
}
return content_index_service_.get();
}
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_index.idl b/chromium/third_party/blink/renderer/modules/content_index/content_index.idl
index fd8f1f8450b..8a116d02860 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_index.idl
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_index.idl
@@ -10,5 +10,5 @@
] interface ContentIndex {
[CallWith=ScriptState, MeasureAs=ContentIndexAdd] Promise<void> add(ContentDescription description);
[CallWith=ScriptState, MeasureAs=ContentIndexDelete, ImplementedAs=deleteDescription] Promise<void> delete(DOMString id);
- [CallWith=ScriptState, MeasureAs=ContentIndexGet] Promise<sequence<ContentDescription>> getDescriptions();
+ [CallWith=ScriptState, MeasureAs=ContentIndexGet, ImplementedAs=getDescriptions] Promise<sequence<ContentDescription>> getAll();
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc b/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
index 0cc3c05e4f7..cd1ea626f1d 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
@@ -8,6 +8,7 @@
#include "base/time/time.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.h b/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.h
index d49fc1db3c8..2643f0666ca 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.h
+++ b/chromium/third_party/blink/renderer/modules/content_index/content_index_icon_loader.h
@@ -17,7 +17,7 @@ namespace blink {
class ExecutionContext;
class MODULES_EXPORT ContentIndexIconLoader final
- : public GarbageCollectedFinalized<ContentIndexIconLoader> {
+ : public GarbageCollected<ContentIndexIconLoader> {
public:
using IconsCallback =
base::OnceCallback<void(mojom::blink::ContentDescriptionPtr description,
diff --git a/chromium/third_party/blink/renderer/modules/content_index/service_worker_registration_content_index.h b/chromium/third_party/blink/renderer/modules/content_index/service_worker_registration_content_index.h
index 5276c310bc0..7852ebacc0f 100644
--- a/chromium/third_party/blink/renderer/modules/content_index/service_worker_registration_content_index.h
+++ b/chromium/third_party/blink/renderer/modules/content_index/service_worker_registration_content_index.h
@@ -16,7 +16,7 @@ namespace blink {
class ContentIndex;
class ServiceWorkerRegistrationContentIndex final
- : public GarbageCollectedFinalized<ServiceWorkerRegistrationContentIndex>,
+ : public GarbageCollected<ServiceWorkerRegistrationContentIndex>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistrationContentIndex);
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 3585a840a94..adb0c2f93f0 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
@@ -424,10 +424,9 @@ void CookieStore::RemoveAllEventListeners() {
}
void CookieStore::OnCookieChange(
- const WebCanonicalCookie& backend_cookie,
- network::mojom::blink::CookieChangeCause change_cause) {
+ network::mojom::blink::CookieChangeInfoPtr change) {
HeapVector<Member<CookieListItem>> changed, deleted;
- CookieChangeEvent::ToEventInfo(backend_cookie, change_cause, changed,
+ CookieChangeEvent::ToEventInfo(change->cookie, change->cause, changed,
deleted);
if (changed.IsEmpty() && deleted.IsEmpty()) {
// The backend only reported OVERWRITE events, which are dropped.
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
index d85631fe163..031eeda80f9 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom-blink.h"
#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -86,8 +86,8 @@ class CookieStore final : public EventTargetWithInlineData,
void RemoveAllEventListeners() override;
// RestrictedCookieChangeListener
- void OnCookieChange(const WebCanonicalCookie&,
- network::mojom::blink::CookieChangeCause) override;
+ void OnCookieChange(
+ network::mojom::blink::CookieChangeInfoPtr change) override;
protected:
// EventTarget overrides.
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h
index ec85f113d2a..6c0e832e30a 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h
@@ -8,6 +8,7 @@
#include <utility>
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_store.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc
index 586f5394b0f..15ba2afcee1 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc
@@ -8,6 +8,7 @@
#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_store.h"
#include "third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h"
@@ -24,8 +25,9 @@ CookieStore* GlobalCookieStoreImpl<WorkerGlobalScope>::BuildCookieStore(
interface_provider->GetInterface(
cookie_manager_remote.BindNewPipeAndPassReceiver(
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+
mojo::Remote<blink::mojom::blink::CookieStore> cookie_store_remote;
- interface_provider->GetInterface(
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
cookie_store_remote.BindNewPipeAndPassReceiver(
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h
index 55e7e723644..31c8c8349b0 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/authenticator_attestation_response.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ATTESTATION_RESPONSE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_AUTHENTICATOR_ATTESTATION_RESPONSE_H_
-#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink-forward.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"
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
index 26a19db1af1..0824e842905 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.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"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -16,10 +15,10 @@ namespace blink {
CredentialManagerProxy::CredentialManagerProxy(Document& document) {
LocalFrame* frame = document.GetFrame();
DCHECK(frame);
- frame->GetDocumentInterfaceBroker().GetCredentialManager(
+ frame->GetBrowserInterfaceBroker().GetInterface(
credential_manager_.BindNewPipeAndPassReceiver(
frame->GetTaskRunner(TaskType::kUserInteraction)));
- frame->GetDocumentInterfaceBroker().GetAuthenticator(
+ frame->GetBrowserInterfaceBroker().GetInterface(
authenticator_.BindNewPipeAndPassReceiver(
frame->GetTaskRunner(TaskType::kUserInteraction)));
}
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
index fd21f867348..25f046d64dc 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
@@ -29,7 +29,7 @@ class ScriptState;
// whose global object owns the CredentialsContainer instance on which the
// method was called.
class MODULES_EXPORT CredentialManagerProxy
- : public GarbageCollectedFinalized<CredentialManagerProxy>,
+ : public GarbageCollected<CredentialManagerProxy>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(CredentialManagerProxy);
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 ab7f9ed6e7d..29f4235f74d 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
@@ -8,6 +8,7 @@
#include <utility>
#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/modules/credentialmanager/authenticator_selection_criteria.h"
#include "third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.h"
@@ -575,13 +576,18 @@ TypeConverter<PublicKeyCredentialRequestOptionsPtr,
if (extensions->hasCableAuthentication()) {
Vector<CableAuthenticationPtr> mojo_data;
for (auto& data : extensions->cableAuthentication()) {
+ if (data->version() != 1) {
+ continue;
+ }
CableAuthenticationPtr mojo_cable =
CableAuthentication::From(data.Get());
if (mojo_cable) {
mojo_data.push_back(std::move(mojo_cable));
}
}
- mojo_options->cable_authentication_data = std::move(mojo_data);
+ if (mojo_data.size() > 0) {
+ mojo_options->cable_authentication_data = std::move(mojo_data);
+ }
}
#if defined(OS_ANDROID)
if (extensions->hasUvm()) {
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 d58dfd537e8..9766db328d8 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
@@ -8,7 +8,7 @@
#include "base/optional.h"
#include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h"
-#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-blink-forward.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/modules/credentialmanager/credentials_container_test.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
index 72be464d9bf..2b52ef0e046 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
@@ -13,6 +13,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/service_manager/public/cpp/interface_provider.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/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"
@@ -21,7 +22,6 @@
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/testing/gc_object_liveness_observer.h"
-#include "third_party/blink/renderer/core/testing/test_document_interface_broker.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/credentialmanager/credential.h"
#include "third_party/blink/renderer/modules/credentialmanager/credential_creation_options.h"
@@ -99,30 +99,6 @@ class MockCredentialManager : public mojom::blink::CredentialManager {
DISALLOW_COPY_AND_ASSIGN(MockCredentialManager);
};
-class MockCredentialManagerDocumentInterfaceBroker
- : public TestDocumentInterfaceBroker {
- public:
- MockCredentialManagerDocumentInterfaceBroker(
- mojom::blink::DocumentInterfaceBroker* document_interface_broker,
- mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker> receiver,
- MockCredentialManager* mock_credential_manager)
- : TestDocumentInterfaceBroker(document_interface_broker,
- std::move(receiver)),
- mock_credential_manager_(mock_credential_manager) {}
-
- void GetCredentialManager(
- mojo::PendingReceiver<::blink::mojom::blink::CredentialManager> receiver)
- override {
- mock_credential_manager_->Bind(std::move(receiver));
- }
-
- void GetAuthenticator(
- mojo::PendingReceiver<mojom::blink::Authenticator> receiver) override {}
-
- private:
- MockCredentialManager* mock_credential_manager_;
-};
-
class CredentialManagerTestingContext {
STACK_ALLOCATED();
@@ -132,12 +108,23 @@ class CredentialManagerTestingContext {
: dummy_context_(KURL("https://example.test")) {
dummy_context_.GetDocument().SetSecureContextStateForTesting(
SecureContextState::kSecure);
- mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker> doc;
- broker_ = std::make_unique<MockCredentialManagerDocumentInterfaceBroker>(
- &dummy_context_.GetFrame().GetDocumentInterfaceBroker(),
- doc.InitWithNewPipeAndPassReceiver(), mock_credential_manager);
- dummy_context_.GetFrame().SetDocumentInterfaceBrokerForTesting(
- doc.PassPipe());
+
+ dummy_context_.GetFrame().GetBrowserInterfaceBroker().SetBinderForTesting(
+ ::blink::mojom::blink::CredentialManager::Name_,
+ WTF::BindRepeating(
+ [](MockCredentialManager* mock_credential_manager,
+ mojo::ScopedMessagePipeHandle handle) {
+ mock_credential_manager->Bind(
+ mojo::PendingReceiver<
+ ::blink::mojom::blink::CredentialManager>(
+ std::move(handle)));
+ },
+ WTF::Unretained(mock_credential_manager)));
+ }
+
+ ~CredentialManagerTestingContext() {
+ dummy_context_.GetFrame().GetBrowserInterfaceBroker().SetBinderForTesting(
+ ::blink::mojom::blink::CredentialManager::Name_, {});
}
Document* GetDocument() { return &dummy_context_.GetDocument(); }
@@ -146,7 +133,6 @@ class CredentialManagerTestingContext {
private:
V8TestingScope dummy_context_;
- std::unique_ptr<MockCredentialManagerDocumentInterfaceBroker> broker_;
};
} // namespace
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 39da74d770c..b6ff20c8b9f 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
@@ -165,7 +165,7 @@ ScriptValue CryptoKey::usages(ScriptState* script_state) {
result.push_back(KeyUsageToString(usage));
}
- return ScriptValue(script_state, ToV8(result, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(result, script_state));
}
bool CryptoKey::CanBeUsedForAlgorithm(const WebCryptoAlgorithm& algorithm,
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 70b49fbe219..d885536893d 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
@@ -30,7 +30,7 @@ class V8PaintCallback;
// the author. It will store the properties for invalidation and input argument
// types as well.
class MODULES_EXPORT CSSPaintDefinition final
- : public GarbageCollectedFinalized<CSSPaintDefinition>,
+ : public GarbageCollected<CSSPaintDefinition>,
public NameClient {
public:
CSSPaintDefinition(
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 0988e3db6cd..f29a220fa01 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc
@@ -31,8 +31,7 @@ PaintRenderingContext2D::PaintRenderingContext2D(
void PaintRenderingContext2D::InitializePaintRecorder() {
paint_recorder_ = std::make_unique<PaintRecorder>();
cc::PaintCanvas* canvas = paint_recorder_->beginRecording(
- container_size_.Width() / effective_zoom_,
- container_size_.Height() / effective_zoom_);
+ container_size_.Width(), container_size_.Height());
// Always save an initial frame, to support resetting the top level matrix
// and clip.
@@ -150,9 +149,8 @@ void PaintRenderingContext2D::setTransform(double m11,
double dx,
double dy) {
BaseRenderingContext2D::setTransform(
- m11 / device_scale_factor_, m12 / device_scale_factor_,
- m21 / device_scale_factor_, m22 / device_scale_factor_,
- dx / device_scale_factor_, dy / device_scale_factor_);
+ m11 * effective_zoom_, m12 * effective_zoom_, m21 * effective_zoom_,
+ m22 * effective_zoom_, dx * effective_zoom_, dy * effective_zoom_);
}
void PaintRenderingContext2D::setTransform(DOMMatrix2DInit* transform,
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 aa4d235ea49..e5d564c0aac 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
@@ -87,13 +87,12 @@ TEST(PaintRenderingContext2DTest, setTransformWithDeviceScaleFactor) {
EXPECT_TRUE(matrix->isIdentity());
ctx->setTransform(2.1, 2.5, 1.4, 2.3, 20, 50);
matrix = ctx->getTransform();
- double epsilon = 0.000001;
- EXPECT_NEAR(matrix->a(), 2.1 / device_scale_factor, epsilon);
- EXPECT_NEAR(matrix->b(), 2.5 / device_scale_factor, epsilon);
- EXPECT_NEAR(matrix->c(), 1.4 / device_scale_factor, epsilon);
- EXPECT_NEAR(matrix->d(), 2.3 / device_scale_factor, epsilon);
- EXPECT_NEAR(matrix->e(), 20 / device_scale_factor, epsilon);
- EXPECT_NEAR(matrix->f(), 50 / device_scale_factor, epsilon);
+ EXPECT_FLOAT_EQ(matrix->a(), 2.1);
+ EXPECT_FLOAT_EQ(matrix->b(), 2.5);
+ EXPECT_FLOAT_EQ(matrix->c(), 1.4);
+ EXPECT_FLOAT_EQ(matrix->d(), 2.3);
+ EXPECT_FLOAT_EQ(matrix->e(), 20);
+ EXPECT_FLOAT_EQ(matrix->f(), 50);
}
TEST(PaintRenderingContext2DTest, setTransformWithDefaultDeviceScaleFactor) {
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
index b7dcf274d10..8182e1f023f 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
@@ -20,7 +20,7 @@ class WorkletModuleResponsesMap;
// A proxy for PaintWorklet to talk to PaintWorkletGlobalScope.
class MODULES_EXPORT PaintWorkletGlobalScopeProxy
- : public GarbageCollectedFinalized<PaintWorkletGlobalScopeProxy>,
+ : public GarbageCollected<PaintWorkletGlobalScopeProxy>,
public WorkletGlobalScopeProxy {
USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletGlobalScopeProxy);
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 8312dc5a7ca..8c5f1bc76f1 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
@@ -30,7 +30,7 @@ class WorkletGlobalScope;
// This class is constructed on the main thread but it is used in the worklet
// backing thread. The entire class is used for off-thread CSS Paint.
class MODULES_EXPORT PaintWorkletProxyClient
- : public GarbageCollectedFinalized<PaintWorkletProxyClient>,
+ : public GarbageCollected<PaintWorkletProxyClient>,
public Supplement<WorkerClients>,
public PaintWorkletPainter {
USING_GARBAGE_COLLECTED_MIXIN(PaintWorkletProxyClient);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/DEPS b/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
index 7c1b789abcd..5538e5bdbd2 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+base/run_loop.h",
"+mojo/public/cpp/bindings/binding.h",
"+services/device/public/mojom/sensor.mojom-blink.h",
+ "+services/device/public/mojom/sensor.mojom-blink-forward.h",
"+services/device/public/mojom/sensor_provider.mojom-blink.h",
"+services/device/public/cpp/test/fake_sensor_and_provider.h",
"+services/device/public/cpp/generic_sensor/sensor_reading.h",
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
index 8360b1bbe5f..ba24867cb9c 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/device_orientation/device_motion_controller.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
index 8bc06547325..9a020ad4632 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
@@ -8,7 +8,7 @@
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/mojom/sensor.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.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/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/platform_event_controller.h"
@@ -81,9 +81,9 @@ void DeviceMotionEventPump::SendStartMessage(LocalFrame* frame) {
if (!sensor_provider_) {
DCHECK(frame);
- frame->GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&sensor_provider_));
- sensor_provider_.set_connection_error_handler(
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ sensor_provider_.BindNewPipeAndPassReceiver());
+ sensor_provider_.set_disconnect_handler(
WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
index 6f36eebb6a1..caec1ea5b21 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
@@ -17,7 +17,7 @@ class DeviceSensorEntry;
class PlatformEventController;
class MODULES_EXPORT DeviceMotionEventPump
- : public GarbageCollectedFinalized<DeviceMotionEventPump>,
+ : public GarbageCollected<DeviceMotionEventPump>,
public DeviceSensorEventPump {
USING_GARBAGE_COLLECTED_MIXIN(DeviceMotionEventPump);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
index bf1c8a756e3..1661da2b6a6 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/run_loop.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/cpp/test/fake_sensor_and_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -24,7 +25,7 @@ namespace blink {
using device::FakeSensorProvider;
class MockDeviceMotionController final
- : public GarbageCollectedFinalized<MockDeviceMotionController>,
+ : public GarbageCollected<MockDeviceMotionController>,
public PlatformEventController {
USING_GARBAGE_COLLECTED_MIXIN(MockDeviceMotionController);
@@ -75,15 +76,14 @@ class DeviceMotionEventPumpTest : public testing::Test {
protected:
void SetUp() override {
- device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
- sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ mojo::PendingRemote<device::mojom::SensorProvider> sensor_provider;
+ sensor_provider_.Bind(sensor_provider.InitWithNewPipeAndPassReceiver());
auto* motion_pump = MakeGarbageCollected<DeviceMotionEventPump>(
base::ThreadTaskRunnerHandle::Get());
motion_pump->SetSensorProviderForTesting(
- device::mojom::blink::SensorProviderPtr(
- device::mojom::blink::SensorProviderPtrInfo(
- sensor_provider_ptr_info.PassHandle(),
- device::mojom::SensorProvider::Version_)));
+ mojo::PendingRemote<device::mojom::blink::SensorProvider>(
+ sensor_provider.PassPipe(),
+ device::mojom::SensorProvider::Version_));
controller_ = MakeGarbageCollected<MockDeviceMotionController>(motion_pump);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
index b7781a525fd..8175847221c 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
index 85f6ed2fc7a..1d253dd5ece 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
@@ -8,7 +8,7 @@
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/mojom/sensor.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.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/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/platform_event_controller.h"
@@ -97,9 +97,9 @@ void DeviceOrientationEventPump::SendStartMessage(LocalFrame* frame) {
if (!sensor_provider_) {
DCHECK(frame);
- frame->GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&sensor_provider_));
- sensor_provider_.set_connection_error_handler(
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ sensor_provider_.BindNewPipeAndPassReceiver());
+ sensor_provider_.set_disconnect_handler(
WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
index 3b2b56499e6..e76252ccc5d 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
@@ -17,7 +17,7 @@ class DeviceSensorEntry;
class PlatformEventController;
class MODULES_EXPORT DeviceOrientationEventPump
- : public GarbageCollectedFinalized<DeviceOrientationEventPump>,
+ : public GarbageCollected<DeviceOrientationEventPump>,
public DeviceSensorEventPump {
USING_GARBAGE_COLLECTED_MIXIN(DeviceOrientationEventPump);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
index db858fc2095..84b409f45a3 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/run_loop.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/cpp/test/fake_sensor_and_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -27,7 +28,7 @@ namespace blink {
using device::FakeSensorProvider;
class MockDeviceOrientationController final
- : public GarbageCollectedFinalized<MockDeviceOrientationController>,
+ : public GarbageCollected<MockDeviceOrientationController>,
public PlatformEventController {
USING_GARBAGE_COLLECTED_MIXIN(MockDeviceOrientationController);
@@ -92,15 +93,14 @@ class DeviceOrientationEventPumpTest : public testing::Test {
protected:
void SetUp() override {
- device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
- sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ mojo::PendingRemote<device::mojom::SensorProvider> sensor_provider;
+ sensor_provider_.Bind(sensor_provider.InitWithNewPipeAndPassReceiver());
auto* orientation_pump = MakeGarbageCollected<DeviceOrientationEventPump>(
base::ThreadTaskRunnerHandle::Get(), false /* absolute */);
orientation_pump->SetSensorProviderForTesting(
- device::mojom::blink::SensorProviderPtr(
- device::mojom::blink::SensorProviderPtrInfo(
- sensor_provider_ptr_info.PassHandle(),
- device::mojom::SensorProvider::Version_)));
+ mojo::PendingRemote<device::mojom::blink::SensorProvider>(
+ sensor_provider.PassPipe(),
+ device::mojom::SensorProvider::Version_));
controller_ =
MakeGarbageCollected<MockDeviceOrientationController>(orientation_pump);
@@ -698,16 +698,15 @@ class DeviceAbsoluteOrientationEventPumpTest : public testing::Test {
protected:
void SetUp() override {
- device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
- sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ mojo::PendingRemote<device::mojom::SensorProvider> sensor_provider;
+ sensor_provider_.Bind(sensor_provider.InitWithNewPipeAndPassReceiver());
auto* absolute_orientation_pump =
MakeGarbageCollected<DeviceOrientationEventPump>(
base::ThreadTaskRunnerHandle::Get(), true /* absolute */);
absolute_orientation_pump->SetSensorProviderForTesting(
- device::mojom::blink::SensorProviderPtr(
- device::mojom::blink::SensorProviderPtrInfo(
- sensor_provider_ptr_info.PassHandle(),
- device::mojom::SensorProvider::Version_)));
+ mojo::PendingRemote<device::mojom::blink::SensorProvider>(
+ sensor_provider.PassPipe(),
+ device::mojom::SensorProvider::Version_));
controller_ = MakeGarbageCollected<MockDeviceOrientationController>(
absolute_orientation_pump);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc
index 412f8f0b145..0a41f8aaf7b 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.cc
@@ -119,7 +119,7 @@ void DeviceSensorEntry::OnSensorCreated(
DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize);
sensor_remote_.Bind(std::move(params->sensor));
- client_receiver_.Bind(std::move(params->client_request));
+ client_receiver_.Bind(std::move(params->client_receiver));
shared_buffer_reader_ = device::SensorReadingSharedBufferReader::Create(
std::move(params->memory), params->buffer_offset);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h
index d11d967a163..0f24fc58705 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_entry.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/device/public/mojom/sensor.mojom-blink-forward.h"
#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -20,7 +20,7 @@ namespace blink {
class DeviceSensorEventPump;
-class DeviceSensorEntry : public GarbageCollectedFinalized<DeviceSensorEntry>,
+class DeviceSensorEntry : public GarbageCollected<DeviceSensorEntry>,
public device::mojom::blink::SensorClient {
USING_PRE_FINALIZER(DeviceSensorEntry, Dispose);
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
index 1bca4b279cb..c2d7c399ae3 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.cc
@@ -41,8 +41,8 @@ void DeviceSensorEventPump::HandleSensorProviderError() {
}
void DeviceSensorEventPump::SetSensorProviderForTesting(
- device::mojom::blink::SensorProviderPtr sensor_provider) {
- sensor_provider_ = std::move(sensor_provider);
+ mojo::PendingRemote<device::mojom::blink::SensorProvider> sensor_provider) {
+ sensor_provider_.Bind(std::move(sensor_provider));
}
DeviceSensorEventPump::PumpState
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
index c5019d5166a..1f41dd4066a 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -34,7 +36,8 @@ class MODULES_EXPORT DeviceSensorEventPump : public GarbageCollectedMixin {
void HandleSensorProviderError();
void SetSensorProviderForTesting(
- device::mojom::blink::SensorProviderPtr sensor_provider);
+ mojo::PendingRemote<device::mojom::blink::SensorProvider>
+ sensor_provider);
PumpState GetPumpStateForTesting();
protected:
@@ -60,7 +63,7 @@ class MODULES_EXPORT DeviceSensorEventPump : public GarbageCollectedMixin {
virtual void DidStartIfPossible();
- device::mojom::blink::SensorProviderPtr sensor_provider_;
+ mojo::Remote<device::mojom::blink::SensorProvider> sensor_provider_;
private:
virtual bool SensorsReadyOrErrored() const = 0;
diff --git a/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.h b/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.h
index 2f6ec201e2a..ccdd46729a9 100644
--- a/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.h
+++ b/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DOCUMENT_METADATA_COPYLESS_PASTE_EXTRACTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DOCUMENT_METADATA_COPYLESS_PASTE_EXTRACTOR_H_
-#include "third_party/blink/public/mojom/document_metadata/copyless_paste.mojom-blink.h"
+#include "third_party/blink/public/mojom/document_metadata/copyless_paste.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
index b32235f2752..c08b7b77f61 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
@@ -27,8 +27,6 @@ ExceptionCode WebCdmExceptionToExceptionCode(
return ToExceptionCode(DOMExceptionCode::kInvalidStateError);
case kWebContentDecryptionModuleExceptionQuotaExceededError:
return ToExceptionCode(DOMExceptionCode::kQuotaExceededError);
- case kWebContentDecryptionModuleExceptionUnknownError:
- return ToExceptionCode(DOMExceptionCode::kUnknownError);
}
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h b/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h
index 6d2a65c48ca..fb687dfde63 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h
@@ -27,7 +27,7 @@ class ScriptState;
class WebContentDecryptionModule;
class MODULES_EXPORT HTMLMediaElementEncryptedMedia final
- : public GarbageCollectedFinalized<HTMLMediaElementEncryptedMedia>,
+ : public GarbageCollected<HTMLMediaElementEncryptedMedia>,
public Supplement<HTMLMediaElement>,
public WebMediaPlayerEncryptedMediaClient {
USING_GARBAGE_COLLECTED_MIXIN(HTMLMediaElementEncryptedMedia);
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 664e74c5af1..c72276e1b28 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
@@ -133,7 +133,7 @@ static ScriptPromise CreateRejectedPromiseAlreadyInitialized(
// A class holding a pending action.
class MediaKeySession::PendingAction final
- : public GarbageCollectedFinalized<MediaKeySession::PendingAction> {
+ : public GarbageCollected<MediaKeySession::PendingAction> {
public:
enum Type { kGenerateRequest, kLoad, kUpdate, kClose, kRemove };
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 11569cdb6bc..a0655337673 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
@@ -18,7 +18,7 @@ namespace blink {
// Represents the key ID and associated status.
class MediaKeyStatusMap::MapEntry final
- : public GarbageCollectedFinalized<MediaKeyStatusMap::MapEntry> {
+ : public GarbageCollected<MediaKeyStatusMap::MapEntry> {
public:
MapEntry(WebData key_id, const String& status)
: key_id_(DOMArrayBuffer::Create(scoped_refptr<SharedBuffer>(key_id))),
@@ -137,8 +137,10 @@ bool MediaKeyStatusMap::has(const ArrayBufferOrArrayBufferView& key_id) {
ScriptValue MediaKeyStatusMap::get(ScriptState* script_state,
const ArrayBufferOrArrayBufferView& key_id) {
uint32_t index = IndexOf(key_id);
- if (index >= entries_.size())
- return ScriptValue(script_state, v8::Undefined(script_state->GetIsolate()));
+ if (index >= entries_.size()) {
+ return ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate()));
+ }
return ScriptValue::From(script_state, at(index).Status());
}
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
index 6fdacf070c0..6197e7c3afd 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
@@ -52,7 +52,7 @@ namespace blink {
// A class holding a pending action.
class MediaKeys::PendingAction final
- : public GarbageCollectedFinalized<MediaKeys::PendingAction> {
+ : public GarbageCollected<MediaKeys::PendingAction> {
public:
enum class Type { kSetServerCertificate, kGetStatusForPolicy };
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 b6ad6e3695d..3445dc8d145 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
@@ -16,6 +16,7 @@
"CookieStore",
"MediaKeySession",
"FileWriter",
+ "GPUDevice",
"HID",
"HIDDevice",
"IdleDetector",
@@ -76,5 +77,6 @@
ImplementedAs: "DOMWebSocket",
},
"USB",
+ "WakeLockSentinel",
],
}
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.h b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.h
index 7596ab2e7fa..e2b79059674 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.h
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.h
@@ -16,7 +16,7 @@
namespace blink {
class MODULES_EXPORT EventSourceParser final
- : public GarbageCollectedFinalized<EventSourceParser> {
+ : public GarbageCollected<EventSourceParser> {
public:
class MODULES_EXPORT Client : public GarbageCollectedMixin {
public:
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 f7ce421bd6f..d36aed3595a 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
@@ -35,7 +35,7 @@ struct EventOrReconnectionTimeSetting {
const uint64_t reconnection_time;
};
-class Client : public GarbageCollectedFinalized<Client>,
+class Client : public GarbageCollected<Client>,
public EventSourceParser::Client {
USING_GARBAGE_COLLECTED_MIXIN(Client);
@@ -57,7 +57,7 @@ class Client : public GarbageCollectedFinalized<Client>,
Vector<EventOrReconnectionTimeSetting> events_;
};
-class StoppingClient : public GarbageCollectedFinalized<StoppingClient>,
+class StoppingClient : public GarbageCollected<StoppingClient>,
public EventSourceParser::Client {
USING_GARBAGE_COLLECTED_MIXIN(StoppingClient);
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 4fb9d34273b..1be76479735 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
@@ -281,11 +281,11 @@ bool WebAXObject::IsAutofillAvailable() const {
return private_->IsAutofillAvailable();
}
-WebString WebAXObject::AriaAutoComplete() const {
+WebString WebAXObject::AutoComplete() const {
if (IsDetached())
return WebString();
- return private_->AriaAutoComplete();
+ return private_->AutoComplete();
}
ax::mojom::AriaCurrentState WebAXObject::AriaCurrentState() const {
@@ -1445,6 +1445,7 @@ static ax::mojom::MarkerType ToAXMarkerType(
return ax::mojom::MarkerType::kSpelling;
case DocumentMarker::kGrammar:
return ax::mojom::MarkerType::kGrammar;
+ case DocumentMarker::kTextFragment:
case DocumentMarker::kTextMatch:
return ax::mojom::MarkerType::kTextMatch;
case DocumentMarker::kActiveSuggestion:
@@ -1630,11 +1631,12 @@ void WebAXObject::Swap(WebAXObject& other) {
other = temp;
}
-void WebAXObject::HandleAutofillStateChanged(bool suggestions_available) const {
+void WebAXObject::HandleAutofillStateChanged(
+ const blink::WebAXAutofillState state) const {
if (IsDetached() || !private_->IsAXLayoutObject())
return;
- private_->HandleAutofillStateChanged(suggestions_available);
+ private_->HandleAutofillStateChanged(state);
}
WebString WebAXObject::ToString() const {
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc b/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
index 380710a7ead..7b274f0f1c9 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/public/web/web_dom_file_system.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_directory_entry.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_entry.h"
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index 8fed6599512..e5297356e3c 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -35,6 +35,9 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
+#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
@@ -70,84 +73,28 @@
namespace blink {
-// static
-std::unique_ptr<WebEmbeddedWorker> WebEmbeddedWorker::Create(
- WebServiceWorkerContextClient* client,
- std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
- installed_scripts_manager_params,
- mojo::ScopedMessagePipeHandle content_settings_handle,
- mojo::ScopedMessagePipeHandle cache_storage,
- mojo::ScopedMessagePipeHandle interface_provider,
- mojo::ScopedMessagePipeHandle browser_interface_broker) {
- return std::make_unique<WebEmbeddedWorkerImpl>(
- std::move(client), std::move(installed_scripts_manager_params),
- std::make_unique<ServiceWorkerContentSettingsProxy>(
- // Chrome doesn't use interface versioning.
- // TODO(falken): Is that comment about versioning correct?
- mojo::PendingRemote<mojom::blink::WorkerContentSettingsProxy>(
- std::move(content_settings_handle), 0u)),
- mojo::PendingRemote<mojom::blink::CacheStorage>(
- std::move(cache_storage), mojom::blink::CacheStorage::Version_),
- service_manager::mojom::blink::InterfaceProviderPtrInfo(
- std::move(interface_provider),
- service_manager::mojom::blink::InterfaceProvider::Version_),
- mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>(
- std::move(browser_interface_broker),
- mojom::blink::BrowserInterfaceBroker::Version_));
+WebServiceWorkerInstalledScriptsManagerParams::
+ WebServiceWorkerInstalledScriptsManagerParams(
+ WebVector<WebURL> installed_scripts_urls,
+ mojo::ScopedMessagePipeHandle manager_receiver,
+ mojo::ScopedMessagePipeHandle manager_host_remote)
+ : installed_scripts_urls(std::move(installed_scripts_urls)),
+ manager_receiver(std::move(manager_receiver)),
+ manager_host_remote(std::move(manager_host_remote)) {
+ DCHECK(!this->installed_scripts_urls.empty());
+ DCHECK(this->manager_receiver);
+ DCHECK(this->manager_host_remote);
}
// static
-std::unique_ptr<WebEmbeddedWorkerImpl> WebEmbeddedWorkerImpl::CreateForTesting(
- WebServiceWorkerContextClient* client,
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>
- installed_scripts_manager) {
- auto worker_impl = std::make_unique<WebEmbeddedWorkerImpl>(
- client, nullptr /* installed_scripts_manager_params */,
- std::make_unique<ServiceWorkerContentSettingsProxy>(
- mojo::NullRemote() /* host_info */),
- mojo::NullRemote() /* cache_storage */,
- nullptr /* interface_provider_info */,
- mojo::NullRemote() /* browser_interface_broker */);
- worker_impl->installed_scripts_manager_ =
- std::move(installed_scripts_manager);
- return worker_impl;
+std::unique_ptr<WebEmbeddedWorker> WebEmbeddedWorker::Create(
+ WebServiceWorkerContextClient* client) {
+ return std::make_unique<WebEmbeddedWorkerImpl>(std::move(client));
}
WebEmbeddedWorkerImpl::WebEmbeddedWorkerImpl(
- WebServiceWorkerContextClient* client,
- std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
- installed_scripts_manager_params,
- std::unique_ptr<ServiceWorkerContentSettingsProxy> content_settings_client,
- mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote,
- service_manager::mojom::blink::InterfaceProviderPtrInfo
- interface_provider_info,
- mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>
- browser_interface_broker)
- : worker_context_client_(client),
- content_settings_client_(std::move(content_settings_client)),
- cache_storage_remote_(std::move(cache_storage_remote)),
- interface_provider_info_(std::move(interface_provider_info)),
- browser_interface_broker_(std::move(browser_interface_broker)) {
- if (installed_scripts_manager_params) {
- DCHECK(installed_scripts_manager_params->manager_receiver.is_valid());
- DCHECK(installed_scripts_manager_params->manager_host_remote.is_valid());
- Vector<KURL> installed_scripts_urls;
- installed_scripts_urls.AppendRange(
- installed_scripts_manager_params->installed_scripts_urls.begin(),
- installed_scripts_manager_params->installed_scripts_urls.end());
- installed_scripts_manager_ = std::make_unique<
- ServiceWorkerInstalledScriptsManager>(
- installed_scripts_urls,
- mojo::PendingReceiver<
- mojom::blink::ServiceWorkerInstalledScriptsManager>(
- std::move(installed_scripts_manager_params->manager_receiver)),
- mojo::PendingRemote<
- mojom::blink::ServiceWorkerInstalledScriptsManagerHost>(
- std::move(installed_scripts_manager_params->manager_host_remote),
- mojom::blink::ServiceWorkerInstalledScriptsManagerHost::Version_),
- Platform::Current()->GetIOTaskRunner());
- }
-}
+ WebServiceWorkerContextClient* client)
+ : worker_context_client_(client) {}
WebEmbeddedWorkerImpl::~WebEmbeddedWorkerImpl() {
// TerminateWorkerContext() must be called before the destructor.
@@ -155,10 +102,24 @@ WebEmbeddedWorkerImpl::~WebEmbeddedWorkerImpl() {
}
void WebEmbeddedWorkerImpl::StartWorkerContext(
- const WebEmbeddedWorkerStartData& data,
+ std::unique_ptr<WebEmbeddedWorkerStartData> worker_start_data,
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
+ installed_scripts_manager_params,
+ mojo::ScopedMessagePipeHandle content_settings_handle,
+ mojo::ScopedMessagePipeHandle cache_storage,
+ mojo::ScopedMessagePipeHandle interface_provider,
+ mojo::ScopedMessagePipeHandle browser_interface_broker,
scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner) {
DCHECK(!asked_to_terminate_);
- worker_start_data_ = data;
+
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager;
+ if (installed_scripts_manager_params) {
+ installed_scripts_manager =
+ std::make_unique<ServiceWorkerInstalledScriptsManager>(
+ std::move(installed_scripts_manager_params),
+ Platform::Current()->GetIOTaskRunner());
+ }
// TODO(mkwst): This really needs to be piped through from the requesting
// document, like we're doing for SharedWorkers. That turns out to be
@@ -168,31 +129,37 @@ void WebEmbeddedWorkerImpl::StartWorkerContext(
// we should fix, but we're taking this shortcut for the prototype.
//
// https://crbug.com/590714
- KURL script_url = worker_start_data_.script_url;
- worker_start_data_.address_space = network::mojom::IPAddressSpace::kPublic;
+ KURL script_url = worker_start_data->script_url;
+ worker_start_data->address_space = network::mojom::IPAddressSpace::kPublic;
if (network_utils::IsReservedIPAddress(script_url.Host()))
- worker_start_data_.address_space = network::mojom::IPAddressSpace::kPrivate;
+ worker_start_data->address_space = network::mojom::IPAddressSpace::kPrivate;
if (SecurityOrigin::Create(script_url)->IsLocalhost())
- worker_start_data_.address_space = network::mojom::IPAddressSpace::kLocal;
+ worker_start_data->address_space = network::mojom::IPAddressSpace::kLocal;
- devtools_worker_token_ = data.devtools_worker_token;
- wait_for_debugger_mode_ = worker_start_data_.wait_for_debugger_mode;
- StartWorkerThread(std::move(initiator_thread_task_runner));
+ StartWorkerThread(
+ std::move(worker_start_data), std::move(installed_scripts_manager),
+ std::make_unique<ServiceWorkerContentSettingsProxy>(
+ // Chrome doesn't use interface versioning.
+ // TODO(falken): Is that comment about versioning correct?
+ mojo::PendingRemote<mojom::blink::WorkerContentSettingsProxy>(
+ std::move(content_settings_handle), 0u)),
+ mojo::PendingRemote<mojom::blink::CacheStorage>(
+ std::move(cache_storage), mojom::blink::CacheStorage::Version_),
+ service_manager::mojom::blink::InterfaceProviderPtrInfo(
+ std::move(interface_provider),
+ service_manager::mojom::blink::InterfaceProvider::Version_),
+ mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>(
+ std::move(browser_interface_broker),
+ mojom::blink::BrowserInterfaceBroker::Version_),
+ std::move(initiator_thread_task_runner));
}
void WebEmbeddedWorkerImpl::TerminateWorkerContext() {
if (asked_to_terminate_)
return;
asked_to_terminate_ = true;
- if (!worker_thread_) {
- // The worker thread has not been created yet if the worker is asked to
- // terminate during waiting for debugger.
- DCHECK_EQ(WebEmbeddedWorkerStartData::kWaitForDebugger,
- worker_start_data_.wait_for_debugger_mode);
- // This deletes 'this'.
- worker_context_client_->WorkerContextFailedToStartOnInitiatorThread();
- return;
- }
+ // StartWorkerThread() must be called before.
+ DCHECK(worker_thread_);
worker_thread_->Terminate();
}
@@ -202,6 +169,15 @@ void WebEmbeddedWorkerImpl::ResumeAfterDownload() {
}
void WebEmbeddedWorkerImpl::StartWorkerThread(
+ std::unique_ptr<WebEmbeddedWorkerStartData> worker_start_data,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager,
+ std::unique_ptr<ServiceWorkerContentSettingsProxy> content_settings_proxy,
+ mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote,
+ service_manager::mojom::blink::InterfaceProviderPtrInfo
+ interface_provider_info,
+ mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>
+ browser_interface_broker,
scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner) {
DCHECK(!asked_to_terminate_);
@@ -212,7 +188,7 @@ void WebEmbeddedWorkerImpl::StartWorkerThread(
// appropriate Document. See comment in CreateFetchClientSettingsObject() for
// details.
scoped_refptr<const SecurityOrigin> starter_origin =
- SecurityOrigin::Create(worker_start_data_.script_url);
+ SecurityOrigin::Create(worker_start_data->script_url);
// This roughly equals to shadow document's IsSecureContext() as a shadow
// document have a frame with no parent.
// See also Document::InitSecureContextState().
@@ -242,43 +218,38 @@ void WebEmbeddedWorkerImpl::StartWorkerThread(
String source_code;
std::unique_ptr<Vector<uint8_t>> cached_meta_data;
- bool is_script_installed = installed_scripts_manager_ &&
- installed_scripts_manager_->IsScriptInstalled(
- worker_start_data_.script_url);
-
// We don't have to set ContentSecurityPolicy and ReferrerPolicy. They're
// served by the worker script loader or the installed scripts manager on the
// worker thread.
global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
- worker_start_data_.script_url, worker_start_data_.script_type,
+ worker_start_data->script_url, worker_start_data->script_type,
OffMainThreadWorkerScriptFetchOption::kEnabled, global_scope_name,
- worker_start_data_.user_agent, std::move(web_worker_fetch_context),
+ worker_start_data->user_agent, std::move(web_worker_fetch_context),
Vector<CSPHeaderAndType>(), network::mojom::ReferrerPolicy::kDefault,
starter_origin.get(), starter_secure_context, starter_https_state,
- nullptr /* worker_clients */, std::move(content_settings_client_),
+ nullptr /* worker_clients */, std::move(content_settings_proxy),
base::nullopt /* response_address_space */,
- nullptr /* OriginTrialTokens */, devtools_worker_token_,
+ nullptr /* OriginTrialTokens */, worker_start_data->devtools_worker_token,
std::move(worker_settings),
- static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options),
+ // Generate the full code cache in the first execution of the script.
+ kV8CacheOptionsFullCodeWithoutHeatCheck,
nullptr /* worklet_module_respones_map */,
- std::move(interface_provider_info_), std::move(browser_interface_broker_),
+ std::move(interface_provider_info), std::move(browser_interface_broker),
BeginFrameProviderParams(), nullptr /* parent_feature_policy */,
base::UnguessableToken() /* agent_cluster_id */);
- // Generate the full code cache in the first execution of the script.
- global_scope_creation_params->v8_cache_options =
- kV8CacheOptionsFullCodeWithoutHeatCheck;
-
worker_thread_ = std::make_unique<ServiceWorkerThread>(
std::make_unique<ServiceWorkerGlobalScopeProxy>(
*this, *worker_context_client_, initiator_thread_task_runner),
- std::move(installed_scripts_manager_), std::move(cache_storage_remote_),
+ std::move(installed_scripts_manager), std::move(cache_storage_remote),
initiator_thread_task_runner);
auto devtools_params = std::make_unique<WorkerDevToolsParams>();
- devtools_params->devtools_worker_token = devtools_worker_token_;
+ devtools_params->devtools_worker_token =
+ worker_start_data->devtools_worker_token;
devtools_params->wait_for_debugger =
- wait_for_debugger_mode_ == WebEmbeddedWorkerStartData::kWaitForDebugger;
+ worker_start_data->wait_for_debugger_mode ==
+ WebEmbeddedWorkerStartData::kWaitForDebugger;
mojo::PendingRemote<mojom::blink::DevToolsAgent> devtools_agent_remote;
devtools_params->agent_receiver =
devtools_agent_remote.InitWithNewPipeAndPassReceiver();
@@ -290,56 +261,39 @@ void WebEmbeddedWorkerImpl::StartWorkerThread(
WorkerBackingThreadStartupData::CreateDefault(),
std::move(devtools_params));
- // If this is an installed service worker, the installed script will be read
- // from the service worker script storage on the worker thread.
- if (is_script_installed) {
- switch (worker_start_data_.script_type) {
- case mojom::ScriptType::kClassic:
- worker_thread_->RunInstalledClassicScript(
- worker_start_data_.script_url, v8_inspector::V8StackTraceId());
- break;
- case mojom::ScriptType::kModule:
- worker_thread_->RunInstalledModuleScript(
- worker_start_data_.script_url,
- CreateFetchClientSettingsObjectData(starter_origin.get(),
- starter_https_state),
- network::mojom::CredentialsMode::kOmit);
- break;
- }
- } else {
- std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- fetch_client_setting_object_data = CreateFetchClientSettingsObjectData(
- starter_origin.get(), starter_https_state);
-
- // If this is a new (not installed) service worker, we are in the Update
- // algorithm here:
- // > Switching on job's worker type, run these substeps with the following
- // > options:
- // https://w3c.github.io/ServiceWorker/#update-algorithm
- switch (worker_start_data_.script_type) {
- // > "classic": Fetch a classic worker script given job's serialized
- // > script url, job's client, "serviceworker", and the to-be-created
- // > environment settings object for this service worker.
- case mojom::ScriptType::kClassic:
- worker_thread_->FetchAndRunClassicScript(
- worker_start_data_.script_url,
- std::move(fetch_client_setting_object_data),
- nullptr /* outside_resource_timing_notifier */,
- v8_inspector::V8StackTraceId());
- break;
-
- // > "module": Fetch a module worker script graph given job’s serialized
- // > script url, job’s client, "serviceworker", "omit", and the
- // > to-be-created environment settings object for this service worker.
- case mojom::ScriptType::kModule:
- worker_thread_->FetchAndRunModuleScript(
- worker_start_data_.script_url,
- std::move(fetch_client_setting_object_data),
- nullptr /* outside_resource_timing_notifier */,
- network::mojom::CredentialsMode::kOmit);
- break;
- }
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
+ fetch_client_setting_object_data = CreateFetchClientSettingsObjectData(
+ worker_start_data->script_url, starter_origin.get(),
+ starter_https_state, worker_start_data->address_space,
+ worker_start_data->outside_fetch_client_settings_object);
+
+ // > Switching on job's worker type, run these substeps with the following
+ // > options:
+ // https://w3c.github.io/ServiceWorker/#update-algorithm
+ switch (worker_start_data->script_type) {
+ // > "classic": Fetch a classic worker script given job's serialized script
+ // > url, job's client, "serviceworker", and the to-be-created environment
+ // > settings object for this service worker.
+ case mojom::ScriptType::kClassic:
+ worker_thread_->FetchAndRunClassicScript(
+ worker_start_data->script_url,
+ std::move(fetch_client_setting_object_data),
+ nullptr /* outside_resource_timing_notifier */,
+ v8_inspector::V8StackTraceId());
+ break;
+
+ // > "module": Fetch a module worker script graph given job’s serialized
+ // > script url, job’s client, "serviceworker", "omit", and the
+ // > to-be-created environment settings object for this service worker.
+ case mojom::ScriptType::kModule:
+ worker_thread_->FetchAndRunModuleScript(
+ worker_start_data->script_url,
+ std::move(fetch_client_setting_object_data),
+ nullptr /* outside_resource_timing_notifier */,
+ network::mojom::CredentialsMode::kOmit);
+ break;
}
+
// We are now ready to inspect worker thread.
worker_context_client_->WorkerReadyForInspectionOnInitiatorThread(
devtools_agent_remote.PassPipe(),
@@ -348,27 +302,33 @@ void WebEmbeddedWorkerImpl::StartWorkerThread(
std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
WebEmbeddedWorkerImpl::CreateFetchClientSettingsObjectData(
+ const KURL& script_url,
const SecurityOrigin* security_origin,
- const HttpsState& https_state) {
- // TODO(crbug.com/967265): Currently we create an incomplete outside settings
- // object from |worker_start_data_| but we should create a proper outside
- // settings objects depending on the situation. For new worker case, this
- // should be the Document that called navigator.serviceWorker.register(). For
- // ServiceWorkerRegistration#update() case, it should be the Document that
- // called update(). For soft update case, it seems to be 'null' document.
- //
- // To get a correct settings, we need to make a way to pass the settings
- // object over mojo IPCs.
+ const HttpsState& https_state,
+ network::mojom::IPAddressSpace address_space,
+ const WebFetchClientSettingsObject& passed_settings_object) {
+ // TODO(crbug.com/967265): Currently |passed_settings_object| doesn't contain
+ // enough parameters to create a complete outside settings object. Pass
+ // all necessary information from the parent execution context.
+ // For new worker case, the parent is the Document that called
+ // navigator.serviceWorker.register(). For ServiceWorkerRegistration#update()
+ // case, it should be the Document that called update(). For soft update case,
+ // it seems to be 'null' document.
+
+ WebInsecureRequestPolicy insecure_requests_policy =
+ passed_settings_object.insecure_requests_policy ==
+ mojom::InsecureRequestsPolicy::kUpgrade
+ ? kUpgradeInsecureRequests
+ : kBlockAllMixedContent;
- const KURL& script_url = worker_start_data_.script_url;
return std::make_unique<CrossThreadFetchClientSettingsObjectData>(
script_url.Copy() /* global_object_url */,
script_url.Copy() /* base_url */, security_origin->IsolatedCopy(),
- network::mojom::ReferrerPolicy::kDefault,
- script_url.GetString().IsolatedCopy() /* outgoing_referrer */,
- https_state, AllowedByNosniff::MimeTypeCheck::kLax,
- worker_start_data_.address_space,
- kBlockAllMixedContent /* insecure_requests_policy */,
+ passed_settings_object.referrer_policy,
+ KURL::CreateIsolated(
+ passed_settings_object.outgoing_referrer.GetString()),
+ https_state, AllowedByNosniff::MimeTypeCheck::kLax, address_space,
+ insecure_requests_policy,
FetchClientSettingsObject::InsecureNavigationsSet(),
false /* mixed_autoupgrade_opt_out */);
}
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
index c4e8c1846d8..bc33444ae2f 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
+++ b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
@@ -36,8 +36,8 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+#include "services/service_manager/public/mojom/interface_provider.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_embedded_worker.h"
#include "third_party/blink/public/web/web_embedded_worker_start_data.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
@@ -61,65 +61,51 @@ struct CrossThreadFetchClientSettingsObjectData;
// worker startup. See https://crbug.com/988335 for details.
class MODULES_EXPORT WebEmbeddedWorkerImpl final : public WebEmbeddedWorker {
public:
- WebEmbeddedWorkerImpl(
- WebServiceWorkerContextClient*,
- std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
- std::unique_ptr<ServiceWorkerContentSettingsProxy>,
- mojo::PendingRemote<mojom::blink::CacheStorage>,
- service_manager::mojom::blink::InterfaceProviderPtrInfo,
- mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>);
+ explicit WebEmbeddedWorkerImpl(WebServiceWorkerContextClient*);
~WebEmbeddedWorkerImpl() override;
// WebEmbeddedWorker overrides.
- void StartWorkerContext(const WebEmbeddedWorkerStartData&,
- scoped_refptr<base::SingleThreadTaskRunner>
- initiator_thread_task_runner) override;
+ void StartWorkerContext(
+ std::unique_ptr<WebEmbeddedWorkerStartData>,
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
+ mojo::ScopedMessagePipeHandle content_settings_handle,
+ mojo::ScopedMessagePipeHandle cache_storage,
+ mojo::ScopedMessagePipeHandle interface_provider,
+ mojo::ScopedMessagePipeHandle browser_interface_broker,
+ scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner)
+ override;
void TerminateWorkerContext() override;
void ResumeAfterDownload() override;
- static std::unique_ptr<WebEmbeddedWorkerImpl> CreateForTesting(
- WebServiceWorkerContextClient*,
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>);
-
void WaitForShutdownForTesting();
private:
- void StartWorkerThread(scoped_refptr<base::SingleThreadTaskRunner>);
+ void StartWorkerThread(
+ std::unique_ptr<WebEmbeddedWorkerStartData> worker_start_data,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>,
+ std::unique_ptr<ServiceWorkerContentSettingsProxy>,
+ mojo::PendingRemote<mojom::blink::CacheStorage>,
+ service_manager::mojom::blink::InterfaceProviderPtrInfo,
+ mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>,
+ scoped_refptr<base::SingleThreadTaskRunner> initiator_thread_task_runner);
// Creates a cross-thread copyable outside settings object for top-level
// worker script fetch.
std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- CreateFetchClientSettingsObjectData(const SecurityOrigin*, const HttpsState&);
-
- WebEmbeddedWorkerStartData worker_start_data_;
+ CreateFetchClientSettingsObjectData(
+ const KURL& script_url,
+ const SecurityOrigin*,
+ const HttpsState&,
+ network::mojom::IPAddressSpace,
+ const WebFetchClientSettingsObject& passed_settings_object);
// Client must remain valid through the entire life time of the worker.
WebServiceWorkerContextClient* const worker_context_client_;
- // These are valid until StartWorkerThread() is called. After the worker
- // thread is created, these are passed to the worker thread.
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>
- installed_scripts_manager_;
- std::unique_ptr<ServiceWorkerContentSettingsProxy> content_settings_client_;
-
std::unique_ptr<ServiceWorkerThread> worker_thread_;
bool asked_to_terminate_ = false;
- // Unique worker token used by DevTools to attribute different instrumentation
- // to the same worker.
- base::UnguessableToken devtools_worker_token_;
- WebEmbeddedWorkerStartData::WaitForDebuggerMode wait_for_debugger_mode_ =
- WebEmbeddedWorkerStartData::kDontWaitForDebugger;
-
- mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote_;
-
- service_manager::mojom::blink::InterfaceProviderPtrInfo
- interface_provider_info_;
-
- mojo::PendingRemote<mojom::blink::BrowserInterfaceBroker>
- browser_interface_broker_;
-
DISALLOW_COPY_AND_ASSIGN(WebEmbeddedWorkerImpl);
};
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/BUILD.gn b/chromium/third_party/blink/renderer/modules/filesystem/BUILD.gn
index 23bd32d4d3a..2e2f3d00a4d 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/filesystem/BUILD.gn
@@ -45,7 +45,6 @@ blink_modules_sources("filesystem") {
"file_entry_sync.h",
"file_system_callbacks.cc",
"file_system_callbacks.h",
- "file_system_client.h",
"file_system_dispatcher.cc",
"file_system_dispatcher.h",
"file_writer.cc",
@@ -58,8 +57,6 @@ blink_modules_sources("filesystem") {
"html_input_element_file_system.h",
"local_file_system.cc",
"local_file_system.h",
- "local_file_system_client.cc",
- "local_file_system_client.h",
"metadata.h",
"sync_callback_helper.h",
"worker_global_scope_file_system.cc",
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.cc b/chromium/third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.cc
index 7259ed52a43..c01ac1ac91a 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/filesystem/dev_tools_host_file_system.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/dev_tools_host.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h
index 2035bcfb3c9..f6be95c7e85 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h
+++ b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_DOM_FILE_SYSTEM_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_DOM_FILE_SYSTEM_BASE_H_
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_flags.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base_test.cc b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base_test.cc
index 4b616ae7085..d8cdbb61ae3 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base_test.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_base_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/filesystem/dom_file_system_base.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h b/chromium/third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h
index e524f907a06..e5f7dbb3a96 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h
+++ b/chromium/third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h
@@ -43,7 +43,7 @@ namespace blink {
class DOMFileSystem;
class DraggedIsolatedFileSystemImpl final
- : public GarbageCollectedFinalized<DraggedIsolatedFileSystemImpl>,
+ : public GarbageCollected<DraggedIsolatedFileSystemImpl>,
public DraggedIsolatedFileSystem,
public Supplement<DataObject> {
USING_GARBAGE_COLLECTED_MIXIN(DraggedIsolatedFileSystemImpl);
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/entry.cc b/chromium/third_party/blink/renderer/modules/filesystem/entry.cc
index b1b371be135..1b3e6eb79f1 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/entry.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/entry.cc
@@ -29,6 +29,7 @@
*/
#include "third_party/blink/renderer/modules/filesystem/entry.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h b/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
index 35f91cab514..f671b4b4ea2 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.h
@@ -33,7 +33,7 @@
#include <memory>
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_void_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_entry_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_error_callback.h"
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 0483ec85bcd..ef829b48015 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
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h"
-#include <memory>
#include <utility>
#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
@@ -284,16 +284,15 @@ void FileSystemDispatcher::ExistsSync(
void FileSystemDispatcher::ReadDirectory(
const KURL& path,
std::unique_ptr<EntriesCallbacks> callbacks) {
- mojom::blink::FileSystemOperationListenerPtr ptr;
- // See https://bit.ly/2S0zRAS for task types
- mojom::blink::FileSystemOperationListenerRequest request = mojo::MakeRequest(
- &ptr,
- GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI));
- op_listeners_.AddBinding(
+ mojo::PendingRemote<mojom::blink::FileSystemOperationListener> listener;
+ mojo::PendingReceiver<mojom::blink::FileSystemOperationListener> receiver =
+ listener.InitWithNewPipeAndPassReceiver();
+ op_listeners_.Add(
std::make_unique<ReadDirectoryListener>(std::move(callbacks)),
- std::move(request),
+ std::move(receiver),
+ // See https://bit.ly/2S0zRAS for task types
GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI));
- GetFileSystemManager().ReadDirectory(path, std::move(ptr));
+ GetFileSystemManager().ReadDirectory(path, std::move(listener));
}
void FileSystemDispatcher::ReadDirectorySync(
@@ -330,18 +329,19 @@ void FileSystemDispatcher::Truncate(const KURL& path,
int64_t offset,
int* request_id_out,
StatusCallback callback) {
- mojom::blink::FileSystemCancellableOperationPtr op_ptr;
+ mojo::Remote<mojom::blink::FileSystemCancellableOperation> op_remote;
// See https://bit.ly/2S0zRAS for task types
- mojom::blink::FileSystemCancellableOperationRequest op_request =
- mojo::MakeRequest(&op_ptr, GetSupplementable()->GetTaskRunner(
- blink::TaskType::kMiscPlatformAPI));
+ mojo::PendingReceiver<mojom::blink::FileSystemCancellableOperation>
+ op_receiver = op_remote.BindNewPipeAndPassReceiver(
+ GetSupplementable()->GetTaskRunner(
+ blink::TaskType::kMiscPlatformAPI));
int operation_id = next_operation_id_++;
- op_ptr.set_connection_error_handler(
- WTF::Bind(&FileSystemDispatcher::RemoveOperationPtr,
+ op_remote.set_disconnect_handler(
+ WTF::Bind(&FileSystemDispatcher::RemoveOperationRemote,
WrapWeakPersistent(this), operation_id));
- cancellable_operations_.insert(operation_id, std::move(op_ptr));
+ cancellable_operations_.insert(operation_id, std::move(op_remote));
GetFileSystemManager().Truncate(
- path, offset, std::move(op_request),
+ path, offset, std::move(op_receiver),
WTF::Bind(&FileSystemDispatcher::DidTruncate, WrapWeakPersistent(this),
operation_id, std::move(callback)));
@@ -363,35 +363,32 @@ void FileSystemDispatcher::Write(const KURL& path,
int* request_id_out,
const WriteCallback& success_callback,
StatusCallback error_callback) {
- mojom::blink::FileSystemCancellableOperationPtr op_ptr;
+ mojo::Remote<mojom::blink::FileSystemCancellableOperation> op_remote;
// See https://bit.ly/2S0zRAS for task types
- mojom::blink::FileSystemCancellableOperationRequest op_request =
- mojo::MakeRequest(&op_ptr, GetSupplementable()->GetTaskRunner(
- blink::TaskType::kMiscPlatformAPI));
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI);
+ mojo::PendingReceiver<mojom::blink::FileSystemCancellableOperation>
+ op_receiver = op_remote.BindNewPipeAndPassReceiver(task_runner);
int operation_id = next_operation_id_++;
- op_ptr.set_connection_error_handler(
- WTF::Bind(&FileSystemDispatcher::RemoveOperationPtr,
+ op_remote.set_disconnect_handler(
+ WTF::Bind(&FileSystemDispatcher::RemoveOperationRemote,
WrapWeakPersistent(this), operation_id));
- cancellable_operations_.insert(operation_id, std::move(op_ptr));
-
- mojom::blink::FileSystemOperationListenerPtr listener_ptr;
- // See https://bit.ly/2S0zRAS for task types
- mojom::blink::FileSystemOperationListenerRequest request = mojo::MakeRequest(
- &listener_ptr,
- GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI));
- op_listeners_.AddBinding(
- std::make_unique<WriteListener>(
- WTF::BindRepeating(&FileSystemDispatcher::DidWrite,
- WrapWeakPersistent(this), success_callback,
- operation_id),
- WTF::Bind(&FileSystemDispatcher::WriteErrorCallback,
- WrapWeakPersistent(this), std::move(error_callback),
- operation_id)),
- std::move(request),
- GetSupplementable()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI));
-
- GetFileSystemManager().Write(path, blob_id, offset, std::move(op_request),
- std::move(listener_ptr));
+ cancellable_operations_.insert(operation_id, std::move(op_remote));
+
+ mojo::PendingRemote<mojom::blink::FileSystemOperationListener> listener;
+ mojo::PendingReceiver<mojom::blink::FileSystemOperationListener> receiver =
+ listener.InitWithNewPipeAndPassReceiver();
+ op_listeners_.Add(std::make_unique<WriteListener>(
+ WTF::BindRepeating(&FileSystemDispatcher::DidWrite,
+ WrapWeakPersistent(this),
+ success_callback, operation_id),
+ WTF::Bind(&FileSystemDispatcher::WriteErrorCallback,
+ WrapWeakPersistent(this),
+ std::move(error_callback), operation_id)),
+ std::move(receiver), task_runner);
+
+ GetFileSystemManager().Write(path, blob_id, offset, std::move(op_receiver),
+ std::move(listener));
if (request_id_out)
*request_id_out = operation_id;
@@ -439,7 +436,7 @@ void FileSystemDispatcher::CreateSnapshotFileSync(
base::File::Info file_info;
base::FilePath platform_path;
base::File::Error error_code = base::File::FILE_ERROR_FAILED;
- mojom::blink::ReceivedSnapshotListenerPtr listener;
+ mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener;
GetFileSystemManager().CreateSnapshotFile(
file_path, &file_info, &platform_path, &error_code, &listener);
DidCreateSnapshotFile(std::move(callbacks), std::move(file_info),
@@ -537,7 +534,7 @@ void FileSystemDispatcher::DidTruncate(int operation_id,
StatusCallback callback,
base::File::Error error_code) {
if (error_code != base::File::FILE_ERROR_ABORT)
- RemoveOperationPtr(operation_id);
+ RemoveOperationRemote(operation_id);
std::move(callback).Run(error_code);
}
@@ -547,7 +544,7 @@ void FileSystemDispatcher::DidWrite(const WriteCallback& callback,
bool complete) {
callback.Run(bytes, complete);
if (complete)
- RemoveOperationPtr(operation_id);
+ RemoveOperationRemote(operation_id);
}
void FileSystemDispatcher::WriteErrorCallback(StatusCallback callback,
@@ -555,14 +552,14 @@ void FileSystemDispatcher::WriteErrorCallback(StatusCallback callback,
base::File::Error error) {
std::move(callback).Run(error);
if (error != base::File::FILE_ERROR_ABORT)
- RemoveOperationPtr(operation_id);
+ RemoveOperationRemote(operation_id);
}
void FileSystemDispatcher::DidCancel(StatusCallback callback,
int cancelled_operation_id,
base::File::Error error_code) {
if (error_code == base::File::FILE_OK)
- RemoveOperationPtr(cancelled_operation_id);
+ RemoveOperationRemote(cancelled_operation_id);
std::move(callback).Run(error_code);
}
@@ -571,7 +568,7 @@ void FileSystemDispatcher::DidCreateSnapshotFile(
const base::File::Info& file_info,
const base::FilePath& platform_path,
base::File::Error error_code,
- mojom::blink::ReceivedSnapshotListenerPtr listener) {
+ mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener) {
if (error_code == base::File::FILE_OK) {
FileMetadata file_metadata = FileMetadata::From(file_info);
file_metadata.platform_path = FilePathToWebString(platform_path);
@@ -584,14 +581,16 @@ void FileSystemDispatcher::DidCreateSnapshotFile(
callbacks->DidCreateSnapshotFile(file_metadata, snapshot_blob);
- if (listener)
- listener->DidReceiveSnapshotFile();
+ if (listener) {
+ mojo::Remote<mojom::blink::ReceivedSnapshotListener>(std::move(listener))
+ ->DidReceiveSnapshotFile();
+ }
} else {
callbacks->DidFail(error_code);
}
}
-void FileSystemDispatcher::RemoveOperationPtr(int operation_id) {
+void FileSystemDispatcher::RemoveOperationRemote(int operation_id) {
auto it = cancellable_operations_.find(operation_id);
if (it == cancellable_operations_.end())
return;
@@ -599,7 +598,7 @@ void FileSystemDispatcher::RemoveOperationPtr(int operation_id) {
}
void FileSystemDispatcher::Prefinalize() {
- op_listeners_.CloseAllBindings();
+ op_listeners_.Clear();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h b/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h
index 4491c0e2826..5344dcf6015 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h
@@ -7,8 +7,9 @@
#include <memory>
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -27,9 +28,8 @@ class SecurityOrigin;
// Sends messages via mojo to the blink::mojom::FileSystemManager service
// running in the browser process. It is owned by ExecutionContext, and
// instances are created lazily by calling FileSystemDispatcher::From().
-class FileSystemDispatcher
- : public GarbageCollectedFinalized<FileSystemDispatcher>,
- public Supplement<ExecutionContext> {
+class FileSystemDispatcher : public GarbageCollected<FileSystemDispatcher>,
+ public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(FileSystemDispatcher);
USING_PRE_FINALIZER(FileSystemDispatcher, Prefinalize);
@@ -191,18 +191,18 @@ class FileSystemDispatcher
const base::File::Info& file_info,
const base::FilePath& platform_path,
base::File::Error error_code,
- mojom::blink::ReceivedSnapshotListenerPtr listener);
+ mojo::PendingRemote<mojom::blink::ReceivedSnapshotListener> listener);
- void RemoveOperationPtr(int operation_id);
+ void RemoveOperationRemote(int operation_id);
void Prefinalize();
mojo::Remote<mojom::blink::FileSystemManager> file_system_manager_;
using OperationsMap =
- HashMap<int, mojom::blink::FileSystemCancellableOperationPtr>;
+ HashMap<int, mojo::Remote<mojom::blink::FileSystemCancellableOperation>>;
OperationsMap cancellable_operations_;
int next_operation_id_;
- mojo::StrongBindingSet<mojom::blink::FileSystemOperationListener>
+ mojo::UniqueReceiverSet<mojom::blink::FileSystemOperationListener>
op_listeners_;
};
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_writer_test.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_writer_test.cc
index 1da44bd046f..9e929f7c99a 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_writer_test.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_writer_test.cc
@@ -30,7 +30,7 @@ KURL mock_path_as_kurl() {
} // namespace
-class TestableFileWriter : public GarbageCollectedFinalized<TestableFileWriter>,
+class TestableFileWriter : public GarbageCollected<TestableFileWriter>,
public FileWriterBase {
USING_GARBAGE_COLLECTED_MIXIN(TestableFileWriter);
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
index b0cd5d9bd29..05f3ba3ab2c 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
@@ -44,10 +44,8 @@
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
-#include "third_party/blink/renderer/modules/filesystem/file_system_client.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -110,15 +108,26 @@ void LocalFileSystem::RequestFileSystemCallback(
void LocalFileSystem::RequestFileSystemAccessInternal(
ExecutionContext* context,
base::OnceCallback<void(bool)> callback) {
- if (!context->IsDocument()) {
- if (!Client().RequestFileSystemAccessSync(context)) {
- std::move(callback).Run(false);
- return;
+ if (context->IsDocument()) {
+ auto* client =
+ To<Document>(context)->GetFrame()->GetContentSettingsClient();
+ if (!client) {
+ std::move(callback).Run(true);
+ } else {
+ client->RequestFileSystemAccessAsync(std::move(callback));
}
- std::move(callback).Run(true);
return;
}
- Client().RequestFileSystemAccessAsync(context, std::move(callback));
+ if (context->IsWorkerGlobalScope()) {
+ auto* client = To<WorkerGlobalScope>(context)->ContentSettingsClient();
+ if (!client) {
+ std::move(callback).Run(true);
+ } else {
+ std::move(callback).Run(client->RequestFileSystemAccessSync());
+ }
+ return;
+ }
+ NOTREACHED();
}
void LocalFileSystem::FileSystemNotAllowedInternal(
@@ -167,21 +176,15 @@ void LocalFileSystem::ResolveURLInternal(
}
}
-LocalFileSystem::LocalFileSystem(LocalFrame& frame,
- std::unique_ptr<FileSystemClient> client)
- : Supplement<LocalFrame>(frame), client_(std::move(client)) {
- DCHECK(client_);
-}
+LocalFileSystem::LocalFileSystem(LocalFrame& frame)
+ : Supplement<LocalFrame>(frame) {}
-LocalFileSystem::LocalFileSystem(WorkerClients& worker_clients,
- std::unique_ptr<FileSystemClient> client)
- : Supplement<WorkerClients>(worker_clients), client_(std::move(client)) {
- DCHECK(client_);
-}
+LocalFileSystem::LocalFileSystem(WorkerGlobalScope& worker_global_scope)
+ : Supplement<WorkerGlobalScope>(worker_global_scope) {}
void LocalFileSystem::Trace(blink::Visitor* visitor) {
Supplement<LocalFrame>::Trace(visitor);
- Supplement<WorkerClients>::Trace(visitor);
+ Supplement<WorkerGlobalScope>::Trace(visitor);
}
const char LocalFileSystem::kSupplementName[] = "LocalFileSystem";
@@ -194,25 +197,21 @@ LocalFileSystem* LocalFileSystem::From(ExecutionContext& context) {
return file_system;
}
- WorkerClients* clients = To<WorkerGlobalScope>(context).Clients();
- DCHECK(clients);
LocalFileSystem* file_system =
- Supplement<WorkerClients>::From<LocalFileSystem>(clients);
+ Supplement<WorkerGlobalScope>::From<LocalFileSystem>(
+ To<WorkerGlobalScope>(context));
DCHECK(file_system);
return file_system;
}
-void ProvideLocalFileSystemTo(LocalFrame& frame,
- std::unique_ptr<FileSystemClient> client) {
- frame.ProvideSupplement(
- MakeGarbageCollected<LocalFileSystem>(frame, std::move(client)));
+void ProvideLocalFileSystemTo(LocalFrame& frame) {
+ frame.ProvideSupplement(MakeGarbageCollected<LocalFileSystem>(frame));
}
-void ProvideLocalFileSystemToWorker(WorkerClients* worker_clients,
- std::unique_ptr<FileSystemClient> client) {
- Supplement<WorkerClients>::ProvideTo(*worker_clients,
- MakeGarbageCollected<LocalFileSystem>(
- *worker_clients, std::move(client)));
+void ProvideLocalFileSystemToWorker(WorkerGlobalScope& worker_global_scope) {
+ Supplement<WorkerGlobalScope>::ProvideTo(
+ worker_global_scope,
+ MakeGarbageCollected<LocalFileSystem>(worker_global_scope));
}
} // namespace blink
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 532745c13d8..48d8734cd72 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
@@ -35,9 +35,9 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h"
+#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -46,15 +46,14 @@
namespace blink {
-class FileSystemClient;
class ExecutionContext;
class FileSystemCallbacks;
class KURL;
class ResolveURICallbacks;
-class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
+class LocalFileSystem final : public GarbageCollected<LocalFileSystem>,
public Supplement<LocalFrame>,
- public Supplement<WorkerClients>,
+ public Supplement<WorkerGlobalScope>,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(LocalFileSystem);
@@ -63,8 +62,8 @@ class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
static const char kSupplementName[];
- LocalFileSystem(LocalFrame&, std::unique_ptr<FileSystemClient>);
- LocalFileSystem(WorkerClients&, std::unique_ptr<FileSystemClient>);
+ explicit LocalFileSystem(LocalFrame&);
+ explicit LocalFileSystem(WorkerGlobalScope&);
~LocalFileSystem();
void ResolveURL(ExecutionContext*,
@@ -77,8 +76,6 @@ class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
std::unique_ptr<FileSystemCallbacks>,
SynchronousType sync_type);
- FileSystemClient& Client() const { return *client_; }
-
static LocalFileSystem* From(ExecutionContext&);
void Trace(blink::Visitor*) override;
@@ -110,11 +107,12 @@ class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
std::unique_ptr<ResolveURICallbacks>,
SynchronousType sync_type);
- const std::unique_ptr<FileSystemClient> client_;
-
DISALLOW_COPY_AND_ASSIGN(LocalFileSystem);
};
+void ProvideLocalFileSystemTo(LocalFrame&);
+void ProvideLocalFileSystemToWorker(WorkerGlobalScope&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_H_
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc
deleted file mode 100644
index 0a0c5ea74da..00000000000
--- a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/filesystem/local_file_system_client.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/web_content_settings_client.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/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-LocalFileSystemClient::~LocalFileSystemClient() = default;
-
-bool LocalFileSystemClient::RequestFileSystemAccessSync(
- ExecutionContext* context) {
- DCHECK(context);
- if (IsA<Document>(context)) {
- // TODO(dcheng): Why is this NOTREACHED and handled?
- NOTREACHED();
- return false;
- }
-
- WebContentSettingsClient* content_settings_client =
- To<WorkerGlobalScope>(context)->ContentSettingsClient();
- if (!content_settings_client)
- return true;
- return content_settings_client->RequestFileSystemAccessSync();
-}
-
-void LocalFileSystemClient::RequestFileSystemAccessAsync(
- ExecutionContext* context,
- base::OnceCallback<void(bool)> callback) {
- DCHECK(context);
- auto* document = DynamicTo<Document>(context);
- if (!document) {
- // TODO(dcheng): Why is this NOTREACHED and handled?
- NOTREACHED();
- return;
- }
-
- if (auto* client = document->GetFrame()->GetContentSettingsClient()) {
- client->RequestFileSystemAccessAsync(std::move(callback));
- } else {
- std::move(callback).Run(true);
- }
-}
-
-LocalFileSystemClient::LocalFileSystemClient() = default;
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/DEPS b/chromium/third_party/blink/renderer/modules/gamepad/DEPS
index 1b7f7f46c93..856ad767222 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/DEPS
+++ b/chromium/third_party/blink/renderer/modules/gamepad/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+device/gamepad/public/cpp/gamepads.h",
"+device/gamepad/public/mojom/gamepad.mojom-blink.h",
+ "+device/gamepad/public/mojom/gamepad.mojom-blink-forward.h",
"+device/gamepad/public/mojom/gamepad_hardware_buffer.h",
"+mojo/public/cpp/bindings/binding.h",
"+mojo/public/cpp/system/buffer.h",
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
index 56505fbd1d4..b8d4afe8b57 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/modules/gamepad/gamepad.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_comparisons.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
index 5dfa9a9c319..afbcdfe984e 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
@@ -22,10 +22,9 @@ namespace blink {
class GamepadSharedMemoryReader;
-class GamepadDispatcher final
- : public GarbageCollectedFinalized<GamepadDispatcher>,
- public PlatformEventDispatcher,
- public WebGamepadListener {
+class GamepadDispatcher final : public GarbageCollected<GamepadDispatcher>,
+ public PlatformEventDispatcher,
+ public WebGamepadListener {
USING_GARBAGE_COLLECTED_MIXIN(GamepadDispatcher);
public:
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
index aaac2409747..0b1c45c2899 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
@@ -6,6 +6,7 @@
#include "base/bind_helpers.h"
#include "device/gamepad/public/cpp/gamepad.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h"
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
index 0a15ef4ecad..a0433c3c44f 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_HAPTIC_ACTUATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_HAPTIC_ACTUATOR_H_
-#include "device/gamepad/public/mojom/gamepad.mojom-blink.h"
+#include "device/gamepad/public/mojom/gamepad.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/member.h"
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 34adaffb087..6387d00e327 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
@@ -5,10 +5,11 @@
#include "third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "device/gamepad/public/cpp/gamepads.h"
#include "device/gamepad/public/mojom/gamepad_hardware_buffer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/web_gamepad_listener.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -16,7 +17,7 @@
namespace blink {
GamepadSharedMemoryReader::GamepadSharedMemoryReader(LocalFrame& frame) {
- frame.GetInterfaceProvider().GetInterface(
+ frame.GetBrowserInterfaceBroker().GetInterface(
gamepad_monitor_remote_.BindNewPipeAndPassReceiver());
// See https://bit.ly/2S0zRAS for task types
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
index ea4946e3957..b59b275dfa0 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -114,6 +114,17 @@ GamepadList* NavigatorGamepad::Gamepads() {
}
is_gamepads_exposed_ = true;
+ ExecutionContext* context =
+ DomWindow() ? DomWindow()->GetExecutionContext() : nullptr;
+
+ if (GetFrame() && GetFrame()->IsCrossOriginSubframe()) {
+ UseCounter::Count(context, WebFeature::kGetGamepadsFromCrossOriginSubframe);
+ }
+
+ if (context && !context->IsSecureContext()) {
+ UseCounter::Count(context, WebFeature::kGetGamepadsFromInsecureContext);
+ }
+
return gamepads_.Get();
}
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
index 8133c7e7c1b..145d0ee0bdc 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
@@ -50,7 +50,7 @@ class GamepadList;
class Navigator;
class MODULES_EXPORT NavigatorGamepad final
- : public GarbageCollectedFinalized<NavigatorGamepad>,
+ : public GarbageCollected<NavigatorGamepad>,
public Supplement<Navigator>,
public DOMWindowClient,
public PlatformEventController,
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/BUILD.gn b/chromium/third_party/blink/renderer/modules/geolocation/BUILD.gn
index 65a4d2126a0..c0a79e2b9f0 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/geolocation/BUILD.gn
@@ -6,18 +6,18 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("geolocation") {
sources = [
- "coordinates.cc",
- "coordinates.h",
"geo_notifier.cc",
"geo_notifier.h",
"geolocation.cc",
"geolocation.h",
+ "geolocation_coordinates.cc",
+ "geolocation_coordinates.h",
"geolocation_error.h",
+ "geolocation_position_error.h",
"geolocation_watchers.cc",
"geolocation_watchers.h",
"geoposition.h",
"navigator_geolocation.cc",
"navigator_geolocation.h",
- "position_error.h",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
index 1f2293b7400..578ab161b9d 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/modules/geolocation/geolocation.h"
-#include "third_party/blink/renderer/modules/geolocation/position_error.h"
+#include "third_party/blink/renderer/modules/geolocation/geolocation_position_error.h"
#include "third_party/blink/renderer/modules/geolocation/position_options.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -45,7 +45,7 @@ void GeoNotifier::Trace(blink::Visitor* visitor) {
visitor->Trace(fatal_error_);
}
-void GeoNotifier::SetFatalError(PositionError* error) {
+void GeoNotifier::SetFatalError(GeolocationPositionError* error) {
// If a fatal error has already been set, stick with it. This makes sure that
// when permission is denied, this is the error reported, as required by the
// spec.
@@ -67,7 +67,7 @@ void GeoNotifier::RunSuccessCallback(Geoposition* position) {
success_callback_->InvokeAndReportException(nullptr, position);
}
-void GeoNotifier::RunErrorCallback(PositionError* error) {
+void GeoNotifier::RunErrorCallback(GeolocationPositionError* error) {
if (error_callback_)
error_callback_->InvokeAndReportException(nullptr, error);
}
@@ -132,8 +132,8 @@ void GeoNotifier::TimerFired(TimerBase*) {
if (error_callback_) {
error_callback_->InvokeAndReportException(
- nullptr, MakeGarbageCollected<PositionError>(PositionError::kTimeout,
- "Timeout expired"));
+ nullptr, MakeGarbageCollected<GeolocationPositionError>(
+ GeolocationPositionError::kTimeout, "Timeout expired"));
}
DEFINE_STATIC_LOCAL(CustomCountHistogram, timeout_expired_histogram,
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 2da6954d85c..887699311e3 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
@@ -16,10 +16,10 @@
namespace blink {
class Geolocation;
+class GeolocationPositionError;
class Geoposition;
-class PositionError;
-class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
+class GeoNotifier final : public GarbageCollected<GeoNotifier>,
public NameClient {
public:
GeoNotifier(Geolocation*,
@@ -34,7 +34,7 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
// Sets the given error as the fatal error if there isn't one yet.
// Starts the timer with an interval of 0.
- void SetFatalError(PositionError*);
+ void SetFatalError(GeolocationPositionError*);
bool UseCachedPosition() const { return use_cached_position_; }
@@ -43,7 +43,7 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
void SetUseCachedPosition();
void RunSuccessCallback(Geoposition*);
- void RunErrorCallback(PositionError*);
+ void RunErrorCallback(GeolocationPositionError*);
void StartTimer();
void StopTimer();
@@ -54,7 +54,7 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
// notifier and the Geolocation. The timer should run only when the notifier
// is owned by the Geolocation. When the Geolocation removes a notifier, the
// timer should be stopped beforehand.
- class Timer final : public GarbageCollectedFinalized<Timer> {
+ class Timer final : public GarbageCollected<Timer> {
public:
explicit Timer(scoped_refptr<base::SingleThreadTaskRunner> web_task_runner,
GeoNotifier* notifier,
@@ -83,7 +83,7 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
Member<V8PositionErrorCallback> error_callback_;
Member<const PositionOptions> options_;
Member<Timer> timer_;
- Member<PositionError> fatal_error_;
+ Member<GeolocationPositionError> fatal_error_;
bool use_cached_position_;
};
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
index d8bc322ea96..65952f5ecba 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -39,7 +39,7 @@
#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/probe/core_probes.h"
-#include "third_party/blink/renderer/modules/geolocation/coordinates.h"
+#include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h"
#include "third_party/blink/renderer/modules/geolocation/geolocation_error.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -55,7 +55,7 @@ const char kFeaturePolicyConsoleWarning[] =
Geoposition* CreateGeoposition(
const device::mojom::blink::Geoposition& position) {
- auto* coordinates = MakeGarbageCollected<Coordinates>(
+ auto* coordinates = MakeGarbageCollected<GeolocationCoordinates>(
position.latitude, position.longitude,
// Lowest point on land is at approximately -400 meters.
position.altitude > -10000., position.altitude, position.accuracy,
@@ -67,23 +67,24 @@ Geoposition* CreateGeoposition(
ConvertSecondsToDOMTimeStamp(position.timestamp.ToDoubleT()));
}
-PositionError* CreatePositionError(
+GeolocationPositionError* CreatePositionError(
device::mojom::blink::Geoposition::ErrorCode mojom_error_code,
const String& error) {
- PositionError::ErrorCode error_code = PositionError::kPositionUnavailable;
+ GeolocationPositionError::ErrorCode error_code =
+ GeolocationPositionError::kPositionUnavailable;
switch (mojom_error_code) {
case device::mojom::blink::Geoposition::ErrorCode::PERMISSION_DENIED:
- error_code = PositionError::kPermissionDenied;
+ error_code = GeolocationPositionError::kPermissionDenied;
break;
case device::mojom::blink::Geoposition::ErrorCode::POSITION_UNAVAILABLE:
- error_code = PositionError::kPositionUnavailable;
+ error_code = GeolocationPositionError::kPositionUnavailable;
break;
case device::mojom::blink::Geoposition::ErrorCode::NONE:
case device::mojom::blink::Geoposition::ErrorCode::TIMEOUT:
NOTREACHED();
break;
}
- return MakeGarbageCollected<PositionError>(error_code, error);
+ return MakeGarbageCollected<GeolocationPositionError>(error_code, error);
}
static void ReportGeolocationViolation(Document* doc) {
@@ -100,8 +101,7 @@ static void ReportGeolocationViolation(Document* doc) {
} // namespace
Geolocation* Geolocation::Create(ExecutionContext* context) {
- Geolocation* geolocation = MakeGarbageCollected<Geolocation>(context);
- return geolocation;
+ return MakeGarbageCollected<Geolocation>(context);
}
Geolocation::Geolocation(ExecutionContext* context)
@@ -138,6 +138,8 @@ void Geolocation::ContextDestroyed(ExecutionContext*) {
StopUpdating();
last_position_ = nullptr;
+ geolocation_.reset();
+ geolocation_service_.reset();
}
void Geolocation::RecordOriginTypeAccess() const {
@@ -221,8 +223,8 @@ void Geolocation::StartRequest(GeoNotifier* notifier) {
String error_message;
if (!GetFrame()->GetSettings()->GetAllowGeolocationOnInsecureOrigins() &&
!GetExecutionContext()->IsSecureContext(error_message)) {
- notifier->SetFatalError(MakeGarbageCollected<PositionError>(
- PositionError::kPermissionDenied, error_message));
+ notifier->SetFatalError(MakeGarbageCollected<GeolocationPositionError>(
+ GeolocationPositionError::kPermissionDenied, error_message));
return;
}
@@ -231,8 +233,9 @@ void Geolocation::StartRequest(GeoNotifier* notifier) {
ReportOptions::kReportOnFailure, kFeaturePolicyConsoleWarning)) {
UseCounter::Count(GetDocument(),
WebFeature::kGeolocationDisabledByFeaturePolicy);
- notifier->SetFatalError(MakeGarbageCollected<PositionError>(
- PositionError::kPermissionDenied, kFeaturePolicyErrorMessage));
+ notifier->SetFatalError(MakeGarbageCollected<GeolocationPositionError>(
+ GeolocationPositionError::kPermissionDenied,
+ kFeaturePolicyErrorMessage));
return;
}
@@ -326,7 +329,7 @@ void Geolocation::StopTimers() {
}
}
-void Geolocation::HandleError(PositionError* error) {
+void Geolocation::HandleError(GeolocationPositionError* error) {
DCHECK(error);
DCHECK(one_shots_being_invoked_.IsEmpty());
@@ -448,6 +451,7 @@ void Geolocation::UpdateGeolocationConnection(GeoNotifier* notifier) {
if (!GetExecutionContext() || !GetPage() || !GetPage()->IsPageVisible() ||
!updating_) {
geolocation_.reset();
+ geolocation_service_.reset();
disconnected_geolocation_ = true;
return;
}
@@ -460,17 +464,15 @@ void Geolocation::UpdateGeolocationConnection(GeoNotifier* notifier) {
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- InterfaceInvalidator* invalidator =
- GetExecutionContext()->GetInterfaceInvalidator();
- GetFrame()->GetInterfaceProvider().GetInterface(&geolocation_service_,
- invalidator, task_runner);
+ GetFrame()->GetInterfaceProvider().GetInterface(
+ geolocation_service_.BindNewPipeAndPassReceiver(task_runner));
geolocation_service_->CreateGeolocation(
- MakeRequest(&geolocation_, invalidator, std::move(task_runner)),
+ geolocation_.BindNewPipeAndPassReceiver(std::move(task_runner)),
LocalFrame::HasTransientUserActivation(GetFrame()),
WTF::Bind(&Geolocation::OnGeolocationPermissionStatusUpdated,
WrapWeakPersistent(this), WrapWeakPersistent(notifier)));
- geolocation_.set_connection_error_handler(WTF::Bind(
+ geolocation_.set_disconnect_handler(WTF::Bind(
&Geolocation::OnGeolocationConnectionError, WrapWeakPersistent(this)));
if (enable_high_accuracy_)
geolocation_->SetHighAccuracy(true);
@@ -509,8 +511,9 @@ void Geolocation::OnGeolocationConnectionError() {
StopUpdating();
// The only reason that we would fail to get a ConnectionError is if we lack
// sufficient permission.
- auto* error = MakeGarbageCollected<PositionError>(
- PositionError::kPermissionDenied, kPermissionDeniedErrorMessage);
+ auto* error = MakeGarbageCollected<GeolocationPositionError>(
+ GeolocationPositionError::kPermissionDenied,
+ kPermissionDeniedErrorMessage);
error->SetIsFatal(true);
HandleError(error);
}
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
index 6ad28ae59bf..65f8b6709ee 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
@@ -27,6 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/geolocation.mojom-blink.h"
#include "third_party/blink/public/mojom/geolocation/geolocation_service.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -35,14 +36,13 @@
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/modules/geolocation/geo_notifier.h"
+#include "third_party/blink/renderer/modules/geolocation/geolocation_position_error.h"
#include "third_party/blink/renderer/modules/geolocation/geolocation_watchers.h"
#include "third_party/blink/renderer/modules/geolocation/geoposition.h"
-#include "third_party/blink/renderer/modules/geolocation/position_error.h"
#include "third_party/blink/renderer/modules/geolocation/position_options.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/mojo/revocable_interface_ptr.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -173,7 +173,7 @@ class MODULES_EXPORT Geolocation final
// Sends the given error to all notifiers, unless the error is not fatal and
// the notifier is due to receive a cached position. Clears the oneshots,
// and also clears the watchers if the error is fatal.
- void HandleError(PositionError*);
+ void HandleError(GeolocationPositionError*);
// Connects to the Geolocation mojo service and starts polling for updates.
void StartUpdating(GeoNotifier*);
@@ -184,15 +184,15 @@ class MODULES_EXPORT Geolocation final
void QueryNextPosition();
// Attempts to obtain a position for the given notifier, either by using
- // the cached position or by requesting one from the Geolocation.
+ // the cached position or by requesting one from the Geolocation service.
// Sets a fatal error if permission is denied or no position can be
// obtained.
void StartRequest(GeoNotifier*);
bool HaveSuitableCachedPosition(const PositionOptions*);
- // Record whether the origin trying to access Geolocation would be allowed
- // to access a feature that can only be accessed by secure origins.
+ // Record whether the origin trying to access Geolocation would be
+ // allowed to access a feature that can only be accessed by secure origins.
// See https://goo.gl/Y0ZkNV
void RecordOriginTypeAccess() const;
@@ -209,10 +209,10 @@ class MODULES_EXPORT Geolocation final
//
// |HandleError(error)| and |MakeSuccessCallbacks| need to clear |one_shots_|
// (and optionally |watchers_|) before invoking the callbacks, in order to
- // avoid clearing notifiers added by calls to Geolocation methods from the
- // callbacks. Thus, something else needs to make the notifiers being invoked
- // alive with wrapper-tracing because V8 GC may run during the callbacks.
- // |one_shots_being_invoked_| and |watchers_being_invoked_| perform
+ // avoid clearing notifiers added by calls to Geolocation methods
+ // from the callbacks. Thus, something else needs to make the notifiers being
+ // invoked alive with wrapper-tracing because V8 GC may run during the
+ // callbacks. |one_shots_being_invoked_| and |watchers_being_invoked_| perform
// wrapper-tracing.
// TODO(https://crbug.com/796145): Remove this hack once on-stack objects
// get supported by either of wrapper-tracing or unified GC.
@@ -220,8 +220,8 @@ class MODULES_EXPORT Geolocation final
HeapVector<Member<GeoNotifier>> watchers_being_invoked_;
Member<Geoposition> last_position_;
- RevocableInterfacePtr<device::mojom::blink::Geolocation> geolocation_;
- RevocableInterfacePtr<mojom::blink::GeolocationService> geolocation_service_;
+ mojo::Remote<device::mojom::blink::Geolocation> geolocation_;
+ mojo::Remote<mojom::blink::GeolocationService> geolocation_service_;
bool enable_high_accuracy_ = false;
// Whether a GeoNotifier is waiting for a position update.
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.idl b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.idl
index 8db3bd87265..93301976d3c 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.idl
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.idl
@@ -26,8 +26,7 @@
// https://www.w3.org/TR/geolocation-API/#geolocation_interface
[
ActiveScriptWrappable,
- Exposed=Window,
- NoInterfaceObject
+ Exposed=Window
] interface Geolocation {
[
LogActivity,
@@ -51,7 +50,8 @@
};
// https://www.w3.org/TR/geolocation-API/#position-callback
-callback PositionCallback = void(Position position);
+callback PositionCallback = void(GeolocationPosition position);
// https://www.w3.org/TR/geolocation-API/#error-callback
-callback PositionErrorCallback = void (PositionError positionError);
+callback PositionErrorCallback =
+ void (GeolocationPositionError positionError);
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.cc b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc
index b30e4e69547..dab1c87a20c 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.cc
@@ -23,11 +23,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/modules/geolocation/coordinates.h"
+#include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h"
namespace blink {
-double Coordinates::altitude(bool& is_null) const {
+double GeolocationCoordinates::altitude(bool& is_null) const {
if (can_provide_altitude_)
return altitude_;
@@ -35,7 +35,7 @@ double Coordinates::altitude(bool& is_null) const {
return 0;
}
-double Coordinates::altitudeAccuracy(bool& is_null) const {
+double GeolocationCoordinates::altitudeAccuracy(bool& is_null) const {
if (can_provide_altitude_accuracy_)
return altitude_accuracy_;
@@ -43,7 +43,7 @@ double Coordinates::altitudeAccuracy(bool& is_null) const {
return 0;
}
-double Coordinates::heading(bool& is_null) const {
+double GeolocationCoordinates::heading(bool& is_null) const {
if (can_provide_heading_)
return heading_;
@@ -51,7 +51,7 @@ double Coordinates::heading(bool& is_null) const {
return 0;
}
-double Coordinates::speed(bool& is_null) const {
+double GeolocationCoordinates::speed(bool& is_null) const {
if (can_provide_speed_)
return speed_;
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h
index 6296150c1fd..beefc9278b7 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_COORDINATES_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_COORDINATES_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_COORDINATES_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_COORDINATES_H_
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -32,21 +32,21 @@
namespace blink {
-class Coordinates : public ScriptWrappable {
+class GeolocationCoordinates : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- Coordinates(double latitude,
- double longitude,
- bool provides_altitude,
- double altitude,
- double accuracy,
- bool provides_altitude_accuracy,
- double altitude_accuracy,
- bool provides_heading,
- double heading,
- bool provides_speed,
- double speed)
+ GeolocationCoordinates(double latitude,
+ double longitude,
+ bool provides_altitude,
+ double altitude,
+ double accuracy,
+ bool provides_altitude_accuracy,
+ double altitude_accuracy,
+ bool provides_heading,
+ double heading,
+ bool provides_speed,
+ double speed)
: latitude_(latitude),
longitude_(longitude),
altitude_(altitude),
@@ -84,4 +84,4 @@ class Coordinates : public ScriptWrappable {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_COORDINATES_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_COORDINATES_H_
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.idl b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.idl
index 93bb79c46ea..f2916d2b3a2 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/coordinates.idl
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_coordinates.idl
@@ -24,9 +24,8 @@
*/
[
- Exposed=Window,
- NoInterfaceObject
-] interface Coordinates {
+ Exposed=Window
+] interface GeolocationCoordinates {
readonly attribute double latitude;
readonly attribute double longitude;
readonly attribute double? altitude;
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_error.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_error.h
index d27b7abf73a..b1a40f07464 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_error.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_error.h
@@ -30,7 +30,7 @@
namespace blink {
-class GeolocationError : public GarbageCollectedFinalized<GeolocationError> {
+class GeolocationError final : public GarbageCollected<GeolocationError> {
public:
enum ErrorCode { kPermissionDenied, kPositionUnavailable };
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/position.idl b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position.idl
index 90d4b17a416..bc3ba9d489a 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/position.idl
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position.idl
@@ -27,9 +27,8 @@
[
Exposed=Window,
- NoInterfaceObject,
ImplementedAs=Geoposition
-] interface Position {
- readonly attribute Coordinates coords;
+] interface GeolocationPosition {
+ readonly attribute GeolocationCoordinates coords;
readonly attribute DOMTimeStamp timestamp;
};
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/position_error.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.h
index 5aea482530b..c57b9024085 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/position_error.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_POSITION_ERROR_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_POSITION_ERROR_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_POSITION_ERROR_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_POSITION_ERROR_H_
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -32,7 +32,7 @@
namespace blink {
-class PositionError final : public ScriptWrappable {
+class GeolocationPositionError final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -42,7 +42,7 @@ class PositionError final : public ScriptWrappable {
kTimeout = 3
};
- PositionError(ErrorCode code, const String& message)
+ GeolocationPositionError(ErrorCode code, const String& message)
: code_(code), message_(message), is_fatal_(false) {}
ErrorCode code() const { return code_; }
@@ -60,4 +60,4 @@ class PositionError final : public ScriptWrappable {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_POSITION_ERROR_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_POSITION_ERROR_H_
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/position_error.idl b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.idl
index 16529fa9ff4..a0f3e3be574 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/position_error.idl
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_position_error.idl
@@ -24,9 +24,8 @@
*/
[
- Exposed=Window,
- NoInterfaceObject
-] interface PositionError {
+ Exposed=Window
+] interface GeolocationPositionError {
readonly attribute unsigned short code;
readonly attribute DOMString message;
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geoposition.h b/chromium/third_party/blink/renderer/modules/geolocation/geoposition.h
index 9b39b62ab1e..0559846b928 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geoposition.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geoposition.h
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/core/dom/dom_time_stamp.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/geolocation/coordinates.h"
+#include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.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/assertions.h"
@@ -39,7 +39,7 @@ class Geoposition final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- Geoposition(Coordinates* coordinates, DOMTimeStamp timestamp)
+ Geoposition(GeolocationCoordinates* coordinates, DOMTimeStamp timestamp)
: coordinates_(coordinates), timestamp_(timestamp) {
DCHECK(coordinates_);
}
@@ -50,10 +50,10 @@ class Geoposition final : public ScriptWrappable {
}
DOMTimeStamp timestamp() const { return timestamp_; }
- Coordinates* coords() const { return coordinates_; }
+ GeolocationCoordinates* coords() const { return coordinates_; }
private:
- Member<Coordinates> coordinates_;
+ Member<GeolocationCoordinates> coordinates_;
DOMTimeStamp timestamp_;
};
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
index 352f21e5946..6804f3a4e39 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
@@ -51,9 +51,10 @@ Geolocation* NavigatorGeolocation::geolocation(Navigator& navigator) {
}
Geolocation* NavigatorGeolocation::geolocation() {
- if (!geolocation_ && GetSupplementable()->GetFrame())
+ if (!geolocation_ && GetSupplementable()->GetFrame()) {
geolocation_ =
Geolocation::Create(GetSupplementable()->GetFrame()->GetDocument());
+ }
return geolocation_;
}
diff --git a/chromium/third_party/blink/renderer/modules/hid/DEPS b/chromium/third_party/blink/renderer/modules/hid/DEPS
index 98e4a1cfa94..003ec941158 100644
--- a/chromium/third_party/blink/renderer/modules/hid/DEPS
+++ b/chromium/third_party/blink/renderer/modules/hid/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+mojo/public/cpp/bindings",
"+services/device/public/mojom/hid.mojom-blink.h",
+ "+services/device/public/mojom/hid.mojom-blink-forward.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid.cc b/chromium/third_party/blink/renderer/modules/hid/hid.cc
index c4a3e1bc21e..dd6d595b1f2 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/hid/hid.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.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"
@@ -22,6 +22,7 @@ namespace blink {
namespace {
+const char kContextGone[] = "Script context has shut down.";
const char kFeaturePolicyBlocked[] =
"Access to the feature \"hid\" is disallowed by feature policy.";
const char kNoDeviceSelected[] = "No device selected.";
@@ -101,20 +102,19 @@ void HID::AddedEventListener(const AtomicString& event_type,
// and disconnect events.
}
-ScriptPromise HID::getDevices(ScriptState* script_state) {
+ScriptPromise HID::getDevices(ScriptState* script_state,
+ ExceptionState& exception_state) {
auto* context = GetExecutionContext();
if (!context) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kContextGone);
+ return ScriptPromise();
}
if (!context->GetSecurityContext().IsFeatureEnabled(
mojom::FeaturePolicyFeature::kHid, ReportOptions::kReportOnFailure)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
- kFeaturePolicyBlocked));
+ exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
+ return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -127,28 +127,25 @@ ScriptPromise HID::getDevices(ScriptState* script_state) {
}
ScriptPromise HID::requestDevice(ScriptState* script_state,
- const HIDDeviceRequestOptions* options) {
+ const HIDDeviceRequestOptions* options,
+ ExceptionState& exception_state) {
auto* frame = GetFrame();
if (!frame || !frame->GetDocument()) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kContextGone);
+ return ScriptPromise();
}
if (!frame->GetDocument()->IsFeatureEnabled(
mojom::FeaturePolicyFeature::kHid, ReportOptions::kReportOnFailure)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
- kFeaturePolicyBlocked));
+ exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
+ return ScriptPromise();
}
if (!LocalFrame::HasTransientUserActivation(frame)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kSecurityError,
- "Must be handling a user gesture to show a permission request."));
+ exception_state.ThrowSecurityError(
+ "Must be handling a user gesture to show a permission request.");
+ return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -230,7 +227,7 @@ void HID::EnsureServiceConnection() {
auto task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- GetExecutionContext()->GetInterfaceProvider()->GetInterface(
+ GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(
WTF::Bind(&HID::OnServiceConnectionError, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid.h b/chromium/third_party/blink/renderer/modules/hid/hid.h
index dbdc82514ab..8bc43fa1baf 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_H_
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/hid.mojom-blink.h"
+#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/script_promise.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
@@ -37,8 +37,10 @@ class HID : public EventTargetWithInlineData, public ContextLifecycleObserver {
// Web-exposed interfaces:
DEFINE_ATTRIBUTE_EVENT_LISTENER(connect, kConnect)
DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect, kDisconnect)
- ScriptPromise getDevices(ScriptState*);
- ScriptPromise requestDevice(ScriptState*, const HIDDeviceRequestOptions*);
+ ScriptPromise getDevices(ScriptState*, ExceptionState&);
+ ScriptPromise requestDevice(ScriptState*,
+ const HIDDeviceRequestOptions*,
+ ExceptionState&);
void Connect(const String& device_guid,
mojo::PendingRemote<device::mojom::blink::HidConnectionClient>
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid.idl b/chromium/third_party/blink/renderer/modules/hid/hid.idl
index b90a32a84f2..ea8de740184 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid.idl
+++ b/chromium/third_party/blink/renderer/modules/hid/hid.idl
@@ -16,12 +16,14 @@
// Retrieves information about all available HID subsystem devices.
[
CallWith=ScriptState,
+ RaisesException,
MeasureAs=HidGetDevices
] Promise<sequence<HIDDevice>> getDevices();
// Requests permission from the user to use a device.
[
CallWith=ScriptState,
+ RaisesException,
MeasureAs=HidRequestDevice
] Promise<sequence<HIDDevice>> requestDevice(
HIDDeviceRequestOptions options);
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.cc b/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.cc
index c95e75307df..e46dd0e4c49 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/hid/hid_collection_info.h"
+#include "services/device/public/mojom/hid.mojom-blink.h"
#include "third_party/blink/renderer/modules/hid/hid_report_info.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.h b/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.h
index 5883758bcd3..aada3a674d0 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_collection_info.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_COLLECTION_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_COLLECTION_INFO_H_
-#include "services/device/public/mojom/hid.mojom-blink.h"
+#include "services/device/public/mojom/hid.mojom-blink-forward.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/hid/hid_device.cc b/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
index 6dd11d79daa..d06e235a79f 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_device.cc
@@ -270,14 +270,15 @@ bool HIDDevice::EnsureNoDeviceChangeInProgress(
return true;
}
-void HIDDevice::FinishOpen(ScriptPromiseResolver* resolver,
- device::mojom::blink::HidConnectionPtr connection) {
+void HIDDevice::FinishOpen(
+ ScriptPromiseResolver* resolver,
+ mojo::PendingRemote<device::mojom::blink::HidConnection> connection) {
MarkRequestComplete(resolver);
device_state_change_in_progress_ = false;
if (connection) {
- connection_ = std::move(connection);
- connection_.set_connection_error_handler(WTF::Bind(
+ connection_.Bind(std::move(connection));
+ connection_.set_disconnect_handler(WTF::Bind(
&HIDDevice::OnServiceConnectionError, WrapWeakPersistent(this)));
resolver->Resolve();
} else {
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 b0aa9adc58f..3c6eaf79ca4 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_device.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_device.h
@@ -5,8 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_DEVICE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_DEVICE_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "services/device/public/mojom/hid.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#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/array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -79,7 +81,7 @@ class MODULES_EXPORT HIDDevice
void OnServiceConnectionError();
void FinishOpen(ScriptPromiseResolver*,
- device::mojom::blink::HidConnectionPtr);
+ mojo::PendingRemote<device::mojom::blink::HidConnection>);
void FinishClose(ScriptPromiseResolver*);
void FinishSendReport(ScriptPromiseResolver*, bool success);
void FinishReceiveReport(ScriptPromiseResolver*,
@@ -95,7 +97,7 @@ class MODULES_EXPORT HIDDevice
Member<HID> parent_;
device::mojom::blink::HidDeviceInfoPtr device_info_;
- device::mojom::blink::HidConnectionPtr connection_;
+ mojo::Remote<device::mojom::blink::HidConnection> connection_;
mojo::Receiver<device::mojom::blink::HidConnectionClient> receiver_{this};
HeapHashSet<Member<ScriptPromiseResolver>> device_requests_;
HeapVector<Member<HIDCollectionInfo>> collections_;
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_report_info.cc b/chromium/third_party/blink/renderer/modules/hid/hid_report_info.cc
index a10eb44c0ff..672a73ca0b7 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_report_info.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_report_info.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/hid/hid_report_info.h"
+#include "services/device/public/mojom/hid.mojom-blink.h"
#include "third_party/blink/renderer/modules/hid/hid_report_item.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_report_info.h b/chromium/third_party/blink/renderer/modules/hid/hid_report_info.h
index e7b0d3ca923..05e8847ee02 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_report_info.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_report_info.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_REPORT_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_REPORT_INFO_H_
-#include "services/device/public/mojom/hid.mojom-blink.h"
+#include "services/device/public/mojom/hid.mojom-blink-forward.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/hid/hid_report_item.cc b/chromium/third_party/blink/renderer/modules/hid/hid_report_item.cc
index a8e98ee354f..514b4c2f0aa 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_report_item.cc
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_report_item.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/hid/hid_report_item.h"
+#include "services/device/public/mojom/hid.mojom-blink.h"
+
namespace blink {
namespace {
diff --git a/chromium/third_party/blink/renderer/modules/hid/hid_report_item.h b/chromium/third_party/blink/renderer/modules/hid/hid_report_item.h
index 63085652d8a..223e351a906 100644
--- a/chromium/third_party/blink/renderer/modules/hid/hid_report_item.h
+++ b/chromium/third_party/blink/renderer/modules/hid/hid_report_item.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_REPORT_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_HID_HID_REPORT_ITEM_H_
-#include "services/device/public/mojom/hid.mojom-blink.h"
+#include "services/device/public/mojom/hid.mojom-blink-forward.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/heap_allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/idle/idle_detector.h b/chromium/third_party/blink/renderer/modules/idle/idle_detector.h
index 95786de9e29..5ad49150618 100644
--- a/chromium/third_party/blink/renderer/modules/idle/idle_detector.h
+++ b/chromium/third_party/blink/renderer/modules/idle/idle_detector.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/idle/idle_manager.mojom-blink.h"
+#include "third_party/blink/public/mojom/idle/idle_manager.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/dom/events/event_target.h"
diff --git a/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc b/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc
index c39a0b20e81..7a29b516de6 100644
--- a/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.cc
@@ -187,7 +187,6 @@ void ImageDownloaderImpl::DidDownloadImage(
}
void ImageDownloaderImpl::Dispose() {
- image_fetchers_.clear();
receiver_.reset();
}
@@ -234,11 +233,11 @@ void ImageDownloaderImpl::Trace(Visitor* visitor) {
}
void ImageDownloaderImpl::ContextDestroyed(ExecutionContext*) {
- for (const auto& fetchers : image_fetchers_) {
+ for (const auto& fetcher : image_fetchers_) {
// Will run callbacks with an empty image vector.
- fetchers->Dispose();
+ fetcher->Dispose();
}
- Dispose();
+ image_fetchers_.clear();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h b/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h
index 90211f4b693..6051b8745e0 100644
--- a/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h
+++ b/chromium/third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h
@@ -16,11 +16,10 @@ class KURL;
class LocalFrame;
class MultiResolutionImageResourceFetcher;
-class ImageDownloaderImpl final
- : public GarbageCollectedFinalized<ImageDownloaderImpl>,
- public Supplement<LocalFrame>,
- public ContextLifecycleObserver,
- public mojom::blink::ImageDownloader {
+class ImageDownloaderImpl final : public GarbageCollected<ImageDownloaderImpl>,
+ public Supplement<LocalFrame>,
+ public ContextLifecycleObserver,
+ public mojom::blink::ImageDownloader {
USING_PRE_FINALIZER(ImageDownloaderImpl, Dispose);
USING_GARBAGE_COLLECTED_MIXIN(ImageDownloaderImpl);
diff --git a/chromium/third_party/blink/renderer/modules/image_downloader/multi_resolution_image_resource_fetcher.h b/chromium/third_party/blink/renderer/modules/image_downloader/multi_resolution_image_resource_fetcher.h
index 1bb332172de..eef1acfd94e 100644
--- a/chromium/third_party/blink/renderer/modules/image_downloader/multi_resolution_image_resource_fetcher.h
+++ b/chromium/third_party/blink/renderer/modules/image_downloader/multi_resolution_image_resource_fetcher.h
@@ -10,7 +10,7 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.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_request.h"
#include "third_party/blink/public/web/web_associated_url_loader_options.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/DEPS b/chromium/third_party/blink/renderer/modules/imagecapture/DEPS
index 8328eae6ced..a07306972ea 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/DEPS
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/DEPS
@@ -1,8 +1,10 @@
include_rules = [
"+media/capture/mojom/image_capture.mojom-blink.h",
+ "+media/capture/mojom/image_capture.mojom-blink-forward.h",
"+media/base",
"+skia/ext/platform_canvas.h",
"+third_party/libyuv",
"+third_party/skia/include/core",
+ "+ui/gfx/gpu_memory_buffer.h",
]
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 7d1c9a12f3f..08eeae358e3 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -7,8 +7,7 @@
#include <memory>
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/interface_provider.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/web_media_stream_track.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
@@ -704,9 +703,10 @@ ImageCapture::ImageCapture(ExecutionContext* context, MediaStreamTrack* track)
if (!GetFrame())
return;
- GetFrame()->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+ GetFrame()->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver());
- service_.set_connection_error_handler(WTF::Bind(
+ service_.set_disconnect_handler(WTF::Bind(
&ImageCapture::OnServiceConnectionError, WrapWeakPersistent(this)));
// Launch a retrieval of the current photo state, which arrive asynchronously
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.h b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.h
index fc3963d8a36..34e4577d81a 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.h
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.h
@@ -7,6 +7,7 @@
#include <memory>
#include "media/capture/mojom/image_capture.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.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/dom/events/event_target.h"
@@ -99,7 +100,7 @@ class MODULES_EXPORT ImageCapture final
Member<MediaStreamTrack> stream_track_;
std::unique_ptr<ImageCaptureFrameGrabber> frame_grabber_;
- media::mojom::blink::ImageCapturePtr service_;
+ mojo::Remote<media::mojom::blink::ImageCapture> service_;
Member<MediaTrackCapabilities> capabilities_;
Member<MediaTrackSettings> settings_;
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.cc b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.cc
index d609544e886..1a250f128bc 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.cc
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.cc
@@ -18,6 +18,7 @@
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/gfx/gpu_memory_buffer.h"
namespace WTF {
// Template specialization of [1], needed to be able to pass callbacks
@@ -79,7 +80,8 @@ void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread(
scoped_refptr<media::VideoFrame> frame,
base::TimeTicks /* current_time */) {
DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_I420A);
+ frame->format() == media::PIXEL_FORMAT_I420A ||
+ frame->format() == media::PIXEL_FORMAT_NV12);
if (first_frame_received_)
return;
@@ -107,25 +109,68 @@ void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread(
const uint32_t destination_pixel_format =
(kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR
: libyuv::FOURCC_ARGB;
-
- libyuv::ConvertFromI420(frame->visible_data(media::VideoFrame::kYPlane),
- frame->stride(media::VideoFrame::kYPlane),
- frame->visible_data(media::VideoFrame::kUPlane),
- frame->stride(media::VideoFrame::kUPlane),
- frame->visible_data(media::VideoFrame::kVPlane),
- frame->stride(media::VideoFrame::kVPlane),
- static_cast<uint8_t*>(pixmap.writable_addr()),
- pixmap.width() * 4, pixmap.width(), pixmap.height(),
- destination_pixel_format);
-
- if (frame->format() == media::PIXEL_FORMAT_I420A) {
- DCHECK(!info.isOpaque());
- // This function copies any plane into the alpha channel of an ARGB image.
- libyuv::ARGBCopyYToAlpha(frame->visible_data(media::VideoFrame::kAPlane),
- frame->stride(media::VideoFrame::kAPlane),
- static_cast<uint8_t*>(pixmap.writable_addr()),
- pixmap.width() * 4, pixmap.width(),
- pixmap.height());
+ uint8_t* destination_plane = static_cast<uint8_t*>(pixmap.writable_addr());
+ int destination_stride = pixmap.width() * 4;
+ int destination_width = pixmap.width();
+ int destination_height = pixmap.height();
+
+ if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ auto* gmb = frame->GetGpuMemoryBuffer();
+ if (!gmb->Map()) {
+ DLOG(ERROR) << "Error mapping GpuMemoryBuffer video frame";
+ std::move(wrapper_callback).Run(sk_sp<SkImage>());
+ return;
+ }
+
+ // NV12 is the only supported pixel format at the moment.
+ DCHECK_EQ(frame->format(), media::PIXEL_FORMAT_NV12);
+ int y_stride = gmb->stride(0);
+ int uv_stride = gmb->stride(1);
+ const uint8_t* y_plane =
+ (static_cast<uint8_t*>(gmb->memory(0)) + frame->visible_rect().x() +
+ (frame->visible_rect().y() * y_stride));
+ // UV plane of NV12 has 2-byte pixel width, with half chroma subsampling
+ // both horizontally and vertically.
+ const uint8_t* uv_plane = (static_cast<uint8_t*>(gmb->memory(1)) +
+ ((frame->visible_rect().x() * 2) / 2) +
+ ((frame->visible_rect().y() / 2) * uv_stride));
+
+ switch (destination_pixel_format) {
+ case libyuv::FOURCC_ABGR:
+ libyuv::NV12ToABGR(y_plane, y_stride, uv_plane, uv_stride,
+ destination_plane, destination_stride,
+ destination_width, destination_height);
+ break;
+ case libyuv::FOURCC_ARGB:
+ libyuv::NV12ToARGB(y_plane, y_stride, uv_plane, uv_stride,
+ destination_plane, destination_stride,
+ destination_width, destination_height);
+ break;
+ default:
+ NOTREACHED();
+ }
+ gmb->Unmap();
+ } else {
+ DCHECK(frame->format() == media::PIXEL_FORMAT_I420 ||
+ frame->format() == media::PIXEL_FORMAT_I420A);
+ libyuv::ConvertFromI420(frame->visible_data(media::VideoFrame::kYPlane),
+ frame->stride(media::VideoFrame::kYPlane),
+ frame->visible_data(media::VideoFrame::kUPlane),
+ frame->stride(media::VideoFrame::kUPlane),
+ frame->visible_data(media::VideoFrame::kVPlane),
+ frame->stride(media::VideoFrame::kVPlane),
+ destination_plane, destination_stride,
+ destination_width, destination_height,
+ destination_pixel_format);
+
+ if (frame->format() == media::PIXEL_FORMAT_I420A) {
+ DCHECK(!info.isOpaque());
+ // This function copies any plane into the alpha channel of an ARGB image.
+ libyuv::ARGBCopyYToAlpha(frame->visible_data(media::VideoFrame::kAPlane),
+ frame->stride(media::VideoFrame::kAPlane),
+ destination_plane, destination_stride,
+ destination_width, destination_height);
+ }
}
std::move(wrapper_callback).Run(surface->makeImageSnapshot());
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.h b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.h
index 85b46e1b854..f050a850607 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.h
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture_frame_grabber.h
@@ -92,10 +92,10 @@ class ScopedWebCallbacks {
std::move(destruction_callback_).Run(std::move(callbacks_));
}
- ScopedWebCallbacks(ScopedWebCallbacks&& other) noexcept = default;
+ ScopedWebCallbacks(ScopedWebCallbacks&& other) = default;
ScopedWebCallbacks(const ScopedWebCallbacks& other) = delete;
- ScopedWebCallbacks& operator=(ScopedWebCallbacks&& other) noexcept = default;
+ ScopedWebCallbacks& operator=(ScopedWebCallbacks&& other) = default;
ScopedWebCallbacks& operator=(const ScopedWebCallbacks& other) = delete;
std::unique_ptr<CallbacksType> PassCallbacks() {
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h b/chromium/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h
index f1c0095df8e..314509c5f9b 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_IMAGECAPTURE_PHOTO_CAPABILITIES_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_IMAGECAPTURE_PHOTO_CAPABILITIES_H_
-#include "media/capture/mojom/image_capture.mojom-blink.h"
+#include "media/capture/mojom/image_capture.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/imagecapture/media_settings_range.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_any.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_any.h
index 38dc88f7921..7d037a0fe23 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_any.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_any.h
@@ -53,7 +53,7 @@ class IDBObjectStore;
// This allows for lazy conversion to script values (via IDBBindingUtilities),
// and avoids the need for many dedicated union types.
-class MODULES_EXPORT IDBAny : public GarbageCollectedFinalized<IDBAny> {
+class MODULES_EXPORT IDBAny final : public GarbageCollected<IDBAny> {
public:
static IDBAny* CreateUndefined();
static IDBAny* CreateNull();
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 7f0794ef304..ba4706eb066 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_observer_callback.h"
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_event_dispatcher.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_index.h"
@@ -353,6 +354,14 @@ void IDBDatabase::deleteObjectStore(const String& name,
IDBTransaction* IDBDatabase::transaction(
ScriptState* script_state,
const StringOrStringSequence& store_names,
+ const String& mode,
+ ExceptionState& exception_state) {
+ return transaction(script_state, store_names, mode, nullptr, exception_state);
+}
+
+IDBTransaction* IDBDatabase::transaction(
+ ScriptState* script_state,
+ const StringOrStringSequence& store_names,
const String& mode_string,
const IDBTransactionOptions* options,
ExceptionState& exception_state) {
@@ -421,17 +430,24 @@ IDBTransaction* IDBDatabase::transaction(
->GetTaskRunner(TaskType::kDatabaseAccess),
transaction_id);
- bool relaxed_durability = false;
- if (RuntimeEnabledFeatures::IDBRelaxedDurabilityEnabled() && options)
- relaxed_durability = options->relaxedDurability();
+ mojom::IDBTransactionDurability durability =
+ mojom::IDBTransactionDurability::Default;
+ if (options) {
+ DCHECK(RuntimeEnabledFeatures::IDBRelaxedDurabilityEnabled());
+ if (options->durability() == indexed_db_names::kRelaxed) {
+ durability = mojom::IDBTransactionDurability::Relaxed;
+ } else if (options->durability() == indexed_db_names::kStrict) {
+ durability = mojom::IDBTransactionDurability::Strict;
+ }
+ }
backend_->CreateTransaction(transaction_backend->CreateReceiver(),
transaction_id, object_store_ids, mode,
- relaxed_durability);
+ durability);
return IDBTransaction::CreateNonVersionChange(
script_state, std::move(transaction_backend), transaction_id, scope, mode,
- this);
+ durability, this);
}
void IDBDatabase::ForceClose() {
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 38cf13db92c..74452627150 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
@@ -105,6 +105,10 @@ class MODULES_EXPORT IDBDatabase final
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&);
void deleteObjectStore(const String& name, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.idl b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.idl
index 5942f0ac58d..938b6b4fae9 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.idl
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.idl
@@ -35,8 +35,12 @@
readonly attribute DOMStringList objectStoreNames;
[NewObject, CallWith=ScriptState, RaisesException] IDBTransaction transaction((DOMString or sequence<DOMString>) storeNames,
+ optional IDBTransactionMode mode = "readonly");
+
+ [NewObject, CallWith=ScriptState, RaisesException, RuntimeEnabled=IDBRelaxedDurability] IDBTransaction transaction((DOMString or sequence<DOMString>) storeNames,
+
optional IDBTransactionMode mode = "readonly",
- optional IDBTransactionOptions options);
+ IDBTransactionOptions options);
void close();
[MeasureAs=IndexedDBWrite, NewObject, RaisesException]
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h
index 965cdc72d37..7591e448bf9 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h
@@ -37,7 +37,7 @@ class IDBDatabase;
class IDBObservation;
class MODULES_EXPORT IDBDatabaseCallbacks
- : public GarbageCollectedFinalized<IDBDatabaseCallbacks> {
+ : public GarbageCollected<IDBDatabaseCallbacks> {
public:
IDBDatabaseCallbacks();
virtual ~IDBDatabaseCallbacks();
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 e08787812b4..e95eb90e828 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -213,15 +213,11 @@ static bool IsContextValid(ExecutionContext* context) {
WebIDBFactory* IDBFactory::GetFactory(ExecutionContext* execution_context) {
if (!web_idb_factory_) {
- mojom::blink::IDBFactoryPtrInfo web_idb_factory_host_info;
- service_manager::InterfaceProvider* interface_provider =
- execution_context->GetInterfaceProvider();
- if (!interface_provider)
- return nullptr;
- interface_provider->GetInterface(
- mojo::MakeRequest(&web_idb_factory_host_info));
+ mojo::PendingRemote<mojom::blink::IDBFactory> web_idb_factory_host_remote;
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
+ web_idb_factory_host_remote.InitWithNewPipeAndPassReceiver());
web_idb_factory_ = std::make_unique<WebIDBFactoryImpl>(
- std::move(web_idb_factory_host_info),
+ std::move(web_idb_factory_host_remote),
execution_context->GetTaskRunner(TaskType::kDatabaseAccess));
}
return web_idb_factory_.get();
@@ -229,9 +225,8 @@ WebIDBFactory* IDBFactory::GetFactory(ExecutionContext* execution_context) {
ScriptPromise IDBFactory::GetDatabaseInfo(ScriptState* script_state,
ExceptionState& exception_state) {
- // The BlinkIDL definition for GetDatabaseInfo already has a [MeasureAs]
- // attribute, so the kIndexedDBRead use counter for kIndexedDBRead must be
- // explicitly updated.
+ // The BlinkIDL definition for GetDatabaseInfo() already has a [Measure]
+ // attribute, so the kIndexedDBRead use counter must be explicitly updated.
UseCounter::Count(ExecutionContext::From(script_state),
WebFeature::kIndexedDBRead);
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.h
index 0c09700a658..0d628fc767c 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.h
@@ -27,7 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_INDEX_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/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.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 6654cf86889..bcc7fb9828a 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
@@ -27,7 +27,7 @@
#include "third_party/blink/public/common/indexeddb/web_idb_types.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#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/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
index 49dbff00b80..d922a27821f 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
@@ -41,5 +41,5 @@
optional boolean lowerOpen = false,
optional boolean upperOpen = false);
- [CallWith=ScriptState, RaisesException] boolean _includes(any key);
+ [CallWith=ScriptState, RaisesException] boolean includes(any key);
};
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.h
index 831fae9df07..bc668d0ea16 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.h
@@ -8,7 +8,7 @@
#include <memory>
#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/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.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/indexeddb/idb_request.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
index f85b8642cc3..48a337ead33 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -34,7 +34,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.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/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
@@ -110,13 +110,13 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
~AsyncTraceState();
// Used to transfer the trace end event state to an IDBRequest.
- AsyncTraceState(AsyncTraceState&& other) noexcept {
+ AsyncTraceState(AsyncTraceState&& other) {
DCHECK(IsEmpty());
this->trace_event_name_ = other.trace_event_name_;
this->id_ = other.id_;
other.trace_event_name_ = nullptr;
}
- AsyncTraceState& operator=(AsyncTraceState&& rhs) noexcept {
+ AsyncTraceState& operator=(AsyncTraceState&& rhs) {
DCHECK(IsEmpty());
this->trace_event_name_ = rhs.trace_event_name_;
this->id_ = rhs.id_;
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 e1a3b49731e..f5cfb941f37 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
@@ -61,7 +61,6 @@
#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"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
@@ -91,7 +90,7 @@ class BackendDatabaseWithMockedClose
int64_t transaction_id,
const WTF::Vector<int64_t>& object_store_ids,
mojom::blink::IDBTransactionMode mode,
- bool relaxed_durability) override {}
+ mojom::blink::IDBTransactionDurability) override {}
MOCK_METHOD0(Close, void());
void VersionChangeIgnored() override {}
void AddObserver(int64_t transaction_id,
@@ -198,7 +197,8 @@ class IDBRequestTest : public testing::Test {
HashSet<String> transaction_scope = {"store"};
transaction_ = IDBTransaction::CreateNonVersionChange(
scope.GetScriptState(), std::move(transaction_backend), kTransactionId,
- transaction_scope, mojom::IDBTransactionMode::ReadOnly, db_.Get());
+ transaction_scope, mojom::IDBTransactionMode::ReadOnly,
+ mojom::IDBTransactionDurability::Relaxed, db_.Get());
IDBKeyPath store_key_path("primaryKey");
scoped_refptr<IDBObjectStoreMetadata> store_metadata = base::AdoptRef(
@@ -435,10 +435,9 @@ TEST_F(IDBRequestTest, ConnectionsAfterStopping) {
class AsyncTraceStateForTesting : public IDBRequest::AsyncTraceState {
public:
AsyncTraceStateForTesting() : IDBRequest::AsyncTraceState() {}
- AsyncTraceStateForTesting(AsyncTraceStateForTesting&& other) noexcept
+ AsyncTraceStateForTesting(AsyncTraceStateForTesting&& other)
: IDBRequest::AsyncTraceState(std::move(other)) {}
- AsyncTraceStateForTesting& operator=(
- AsyncTraceStateForTesting&& rhs) noexcept {
+ AsyncTraceStateForTesting& operator=(AsyncTraceStateForTesting&& rhs) {
AsyncTraceState::operator=(std::move(rhs));
return *this;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
index 7106e79a344..b1b2ec15656 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
@@ -52,12 +52,14 @@ IDBTransaction* IDBTransaction::CreateNonVersionChange(
int64_t id,
const HashSet<String>& scope,
mojom::IDBTransactionMode mode,
+ mojom::IDBTransactionDurability durability,
IDBDatabase* db) {
DCHECK_NE(mode, mojom::IDBTransactionMode::VersionChange);
DCHECK(!scope.IsEmpty()) << "Non-version transactions should operate on a "
"well-defined set of stores";
- return MakeGarbageCollected<IDBTransaction>(
- script_state, std::move(transaction_backend), id, scope, mode, db);
+ return MakeGarbageCollected<IDBTransaction>(script_state,
+ std::move(transaction_backend),
+ id, scope, mode, durability, db);
}
IDBTransaction* IDBTransaction::CreateVersionChange(
@@ -78,12 +80,14 @@ IDBTransaction::IDBTransaction(
int64_t id,
const HashSet<String>& scope,
mojom::IDBTransactionMode mode,
+ mojom::IDBTransactionDurability durability,
IDBDatabase* db)
: ContextLifecycleObserver(ExecutionContext::From(script_state)),
transaction_backend_(std::move(transaction_backend)),
id_(id),
database_(db),
mode_(mode),
+ durability_(durability),
scope_(scope),
event_queue_(
MakeGarbageCollected<EventQueue>(ExecutionContext::From(script_state),
@@ -122,6 +126,7 @@ IDBTransaction::IDBTransaction(
database_(db),
open_db_request_(open_db_request),
mode_(mojom::IDBTransactionMode::VersionChange),
+ durability_(mojom::IDBTransactionDurability::Default),
state_(kInactive),
old_database_metadata_(old_metadata),
event_queue_(
@@ -495,6 +500,21 @@ const String& IDBTransaction::mode() const {
return indexed_db_names::kReadonly;
}
+const String& IDBTransaction::durability() const {
+ switch (durability_) {
+ case mojom::IDBTransactionDurability::Default:
+ return indexed_db_names::kDefault;
+
+ case mojom::IDBTransactionDurability::Strict:
+ return indexed_db_names::kStrict;
+
+ case mojom::IDBTransactionDurability::Relaxed:
+ return indexed_db_names::kRelaxed;
+ }
+
+ NOTREACHED();
+}
+
DOMStringList* IDBTransaction::objectStoreNames() const {
if (IsVersionChange())
return database_->objectStoreNames();
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
index 913cb291937..f73fb13f8b8 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
@@ -29,7 +29,7 @@
#include <memory>
#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/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/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
@@ -75,6 +75,7 @@ class MODULES_EXPORT IDBTransaction final
int64_t transaction_id,
const HashSet<String>& scope,
mojom::IDBTransactionMode,
+ mojom::IDBTransactionDurability,
IDBDatabase* database);
static IDBTransaction* CreateVersionChange(
ExecutionContext*,
@@ -90,6 +91,7 @@ class MODULES_EXPORT IDBTransaction final
int64_t,
const HashSet<String>& scope,
mojom::IDBTransactionMode,
+ mojom::IDBTransactionDurability,
IDBDatabase*);
// For upgrade transactions.
IDBTransaction(ExecutionContext*,
@@ -122,6 +124,7 @@ class MODULES_EXPORT IDBTransaction final
// Implement the IDBTransaction IDL
const String& mode() const;
+ const String& durability() const;
DOMStringList* objectStoreNames() const;
IDBDatabase* db() const { return database_.Get(); }
DOMException* error() const { return error_; }
@@ -213,6 +216,7 @@ class MODULES_EXPORT IDBTransaction final
Member<IDBDatabase> database_;
Member<IDBOpenDBRequest> open_db_request_;
const mojom::IDBTransactionMode mode_;
+ const mojom::IDBTransactionDurability durability_;
// The names of the object stores that make up this transaction's scope.
//
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.idl b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.idl
index 4a09acb0f46..2956e888fb8 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.idl
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.idl
@@ -42,15 +42,13 @@ enum IDBTransactionMode {
// Properties
readonly attribute DOMStringList objectStoreNames;
readonly attribute IDBTransactionMode mode;
+ [RuntimeEnabled=IDBRelaxedDurability] readonly attribute IDBTransactionDurability durability;
[SameObject] readonly attribute IDBDatabase db;
readonly attribute DOMException error;
// Methods
[RaisesException] IDBObjectStore objectStore(DOMString name);
- [
- RaisesException,
- RuntimeEnabled=IDBTransactionCommit
- ] void commit();
+ [RaisesException] void commit();
[RaisesException] void abort();
// Events
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl
index 2a20f7217a1..64109b9655e 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-[inline_doc] dictionary IDBTransactionOptions {
- // If relaxedDurability is true, then the transaction will not be flushed
- // to disk. This is more performant at the cost of durability.
- boolean relaxedDurability = false;
+enum IDBTransactionDurability { "default", "strict", "relaxed" };
+
+dictionary IDBTransactionOptions {
+ // If durability is "relaxed", then the transaction will not be flushed
+ // to disk. This is more performant at the cost of durability. If it is
+ // "strict", then it will always be flushed to disk. "default" leaves the
+ // decision up to the implementation.
+ IDBTransactionDurability durability = "default";
};
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 a599928b6db..f71d72e1c45 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
@@ -98,7 +98,8 @@ class IDBTransactionTest : public testing::Test {
HashSet<String> transaction_scope = {"store"};
transaction_ = IDBTransaction::CreateNonVersionChange(
scope.GetScriptState(), std::move(transaction_backend), kTransactionId,
- transaction_scope, mojom::IDBTransactionMode::ReadOnly, db_.Get());
+ transaction_scope, mojom::IDBTransactionMode::ReadOnly,
+ mojom::IDBTransactionDurability::Relaxed, db_.Get());
IDBKeyPath store_key_path("primaryKey");
scoped_refptr<IDBObjectStoreMetadata> store_metadata = base::AdoptRef(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h
index 850b3fcef01..3f803a71646 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h
@@ -28,7 +28,7 @@
#include "base/optional.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/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
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 81967544713..59866c6b2ff 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,6 +6,7 @@
#include "base/stl_util.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
@@ -207,7 +208,7 @@ StructTraits<blink::mojom::IDBValueDataView, std::unique_ptr<blink::IDBValue>>::
if (mime_type.IsNull())
mime_type = g_empty_string;
blob_info->mime_type = mime_type;
- blob_info->blob = blink::mojom::blink::BlobPtrInfo(
+ blob_info->blob = mojo::PendingRemote<blink::mojom::blink::Blob>(
info.CloneBlobHandle(), blink::mojom::blink::Blob::Version_);
blob_or_file_info.push_back(std::move(blob_info));
}
@@ -244,10 +245,10 @@ bool StructTraits<blink::mojom::IDBValueDataView,
blink::FilePathToWebString(info->file->path),
info->file->name, info->mime_type,
info->file->last_modified.ToDoubleT(),
- info->size, info->blob.PassHandle());
+ info->size, info->blob.PassPipe());
} else {
value_blob_info.emplace_back(info->uuid, info->mime_type, info->size,
- info->blob.PassHandle());
+ info->blob.PassPipe());
}
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_names.json5 b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_names.json5
index edab532e48d..3aa16b76096 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_names.json5
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_names.json5
@@ -32,5 +32,11 @@
"put",
"delete",
"clear",
+
+ // The IDBTransactionDurability enum is still being standardized.
+ // https://chromestatus.com/feature/5730701489995776
+ "default",
+ "relaxed",
+ "strict",
],
}
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 337cbc7f03c..e278a24906d 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
@@ -326,7 +326,7 @@ IDBTransaction* TransactionForDatabase(
StringOrStringSequence scope;
scope.SetString(object_store_name);
IDBTransactionOptions options;
- options.setRelaxedDurability(true);
+ options.setDurability("relaxed");
IDBTransaction* idb_transaction = idb_database->transaction(
script_state, scope, mode, &options, exception_state);
if (exception_state.HadException())
@@ -896,7 +896,8 @@ class GetMetadata final : public ExecutableWithDatabase<GetMetadataCallback> {
ScriptState::Scope scope(script_state);
DummyExceptionStateForTesting exception_state;
IDBRequest* idb_request_get_entries_count = idb_object_store->count(
- script_state, ScriptValue::CreateNull(script_state), exception_state);
+ script_state, ScriptValue::CreateNull(script_state->GetIsolate()),
+ exception_state);
DCHECK(!exception_state.HadException());
if (exception_state.HadException()) {
ExceptionCode ec = exception_state.Code();
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 118199a7dbd..c89042ae206 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
@@ -9,7 +9,7 @@
#include "base/optional.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database_error.h"
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
index 6f91bdee460..9dce5f21f24 100644
--- 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
@@ -29,7 +29,7 @@ class MockWebIDBDatabase : public testing::StrictMock<WebIDBDatabase> {
int64_t id,
const Vector<int64_t>& scope,
mojom::IDBTransactionMode,
- bool relaxed_durability));
+ mojom::IDBTransactionDurability));
MOCK_METHOD0(Close, void());
MOCK_METHOD0(VersionChangeIgnored, void());
MOCK_METHOD1(Abort, void(int64_t transaction_id));
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
index aca1e9a8d9d..a1e3449924c 100644
--- 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
@@ -9,7 +9,7 @@
#include <memory>
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.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"
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 04ec3a37c08..34ed7bc4886 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
@@ -53,7 +53,7 @@ class MODULES_EXPORT WebIDBDatabase {
int64_t id,
const Vector<int64_t>& scope,
mojom::IDBTransactionMode,
- bool relaxed_durability) = 0;
+ mojom::IDBTransactionDurability) = 0;
virtual void Close() = 0;
virtual void VersionChangeIgnored() = 0;
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_impl.cc
index 482b56dec72..ce509c8ed7c 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_impl.cc
@@ -37,9 +37,9 @@ void WebIDBDatabaseImpl::CreateTransaction(
int64_t transaction_id,
const Vector<int64_t>& object_store_ids,
mojom::IDBTransactionMode mode,
- bool relaxed_durability) {
+ mojom::IDBTransactionDurability durability) {
database_->CreateTransaction(std::move(transaction_receiver), transaction_id,
- object_store_ids, mode, relaxed_durability);
+ object_store_ids, mode, durability);
}
void WebIDBDatabaseImpl::Close() {
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
index 63309de97c0..84f75aa5b9b 100644
--- 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
@@ -36,7 +36,7 @@ class MODULES_EXPORT WebIDBDatabaseImpl : public WebIDBDatabase {
int64_t transaction_id,
const Vector<int64_t>& scope,
mojom::IDBTransactionMode mode,
- bool relaxed_durability) override;
+ mojom::IDBTransactionDurability durability) override;
void Close() override;
void VersionChangeIgnored() override;
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
index acb0d9948b4..875fb3037f2 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h"
#include "base/memory/ptr_util.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h"
@@ -13,10 +14,10 @@
namespace blink {
WebIDBFactoryImpl::WebIDBFactoryImpl(
- mojom::blink::IDBFactoryPtrInfo factory_info,
+ mojo::PendingRemote<mojom::blink::IDBFactory> pending_factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(std::move(task_runner)) {
- factory_.Bind(std::move(factory_info), task_runner_);
+ factory_.Bind(std::move(pending_factory), task_runner_);
}
WebIDBFactoryImpl::~WebIDBFactoryImpl() = default;
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
index 49db75aa900..aaec596aa00 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_factory_impl.h
@@ -7,7 +7,9 @@
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
@@ -23,7 +25,7 @@ namespace blink {
class WebIDBFactoryImpl : public WebIDBFactory {
public:
explicit WebIDBFactoryImpl(
- mojom::blink::IDBFactoryPtrInfo factory_info,
+ mojo::PendingRemote<mojom::blink::IDBFactory> pending_factory,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~WebIDBFactoryImpl() override;
@@ -49,7 +51,7 @@ class WebIDBFactoryImpl : public WebIDBFactory {
GetDatabaseCallbacksProxy(
std::unique_ptr<IndexedDBDatabaseCallbacksImpl> callbacks);
- mojom::blink::IDBFactoryPtr factory_;
+ mojo::Remote<mojom::blink::IDBFactory> factory_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
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 a1a0fb65247..9638494a249 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
@@ -30,7 +30,7 @@
#include <memory>
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
-#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.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"
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/BUILD.gn b/chromium/third_party/blink/renderer/modules/installedapp/BUILD.gn
index a72dfcef974..5dd66caec92 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/installedapp/BUILD.gn
@@ -10,6 +10,5 @@ blink_modules_sources("installedapp") {
"installed_app_controller.h",
"navigator_installed_app.cc",
"navigator_installed_app.h",
- "related_application.h",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/OWNERS b/chromium/third_party/blink/renderer/modules/installedapp/OWNERS
index 065b1322ca1..e3383b0300a 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/installedapp/OWNERS
@@ -1,3 +1,4 @@
-mgiuca@chromium.org
+peter@chromium.org
+rayankans@chromium.org
# COMPONENT: Platform>Apps>AppLauncher>Install
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 83a32dd1b91..64d7dba3b61 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
@@ -6,8 +6,10 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.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"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -74,7 +76,7 @@ void InstalledAppController::OnGetManifestForRelatedApps(
if (!provider_) {
// See https://bit.ly/2S0zRAS for task types.
- GetSupplementable()->GetInterfaceProvider().GetInterface(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
provider_.BindNewPipeAndPassReceiver(
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
// TODO(mgiuca): Set a connection error handler. This requires a refactor to
@@ -94,8 +96,11 @@ void InstalledAppController::OnFilterInstalledApps(
Vector<mojom::blink::RelatedApplicationPtr> result) {
HeapVector<Member<RelatedApplication>> applications;
for (const auto& res : result) {
- auto* app = MakeGarbageCollected<RelatedApplication>(res->platform,
- res->url, res->id);
+ auto* app = MakeGarbageCollected<RelatedApplication>();
+ app->setPlatform(res->platform);
+ app->setURL(res->url);
+ app->setId(res->id);
+ app->setVersion(res->version);
applications.push_back(app);
}
callbacks->OnSuccess(applications);
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.h b/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.h
index 13f912a6554..5d1ff418360 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.h
+++ b/chromium/third_party/blink/renderer/modules/installedapp/installed_app_controller.h
@@ -11,8 +11,8 @@
#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom-blink.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/mojom/installedapp/related_application.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -29,7 +29,7 @@ using AppInstalledCallbacks =
CallbackPromiseAdapter<HeapVector<Member<RelatedApplication>>, void>;
class MODULES_EXPORT InstalledAppController final
- : public GarbageCollectedFinalized<InstalledAppController>,
+ : public GarbageCollected<InstalledAppController>,
public Supplement<LocalFrame>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(InstalledAppController);
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/related_application.h b/chromium/third_party/blink/renderer/modules/installedapp/related_application.h
deleted file mode 100644
index 16fb773eccb..00000000000
--- a/chromium/third_party/blink/renderer/modules/installedapp/related_application.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INSTALLEDAPP_RELATED_APPLICATION_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_INSTALLEDAPP_RELATED_APPLICATION_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/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class RelatedApplication final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- RelatedApplication(const String& platform,
- const String& url,
- const String& id)
- : platform_(platform), url_(url), id_(id) {}
- ~RelatedApplication() override = default;
-
- String platform() const { return platform_; }
- String url() const { return url_; }
- String id() const { return id_; }
-
- private:
- const String platform_;
- const String url_;
- const String id_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INSTALLEDAPP_RELATED_APPLICATION_H_
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/related_application.idl b/chromium/third_party/blink/renderer/modules/installedapp/related_application.idl
index c55b7f6f1c7..2e2085bb49a 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/related_application.idl
+++ b/chromium/third_party/blink/renderer/modules/installedapp/related_application.idl
@@ -5,14 +5,9 @@
// TODO(mgiuca): Link to full spec, rather than explainer, upon completion.
// https://github.com/WICG/get-installed-related-apps/blob/master/EXPLAINER.md
-// TODO(mgiuca): This should be a dictionary, not an interface.
-// (NoInterfaceObject is basically a makeshift dictionary.)
-// https://crbug.com/687444.
-[
- NoInterfaceObject,
- RuntimeEnabled=InstalledApp
-] interface RelatedApplication {
- readonly attribute DOMString platform;
- readonly attribute DOMString url;
- readonly attribute DOMString id;
+dictionary RelatedApplication {
+ required USVString platform;
+ USVString url;
+ DOMString id;
+ DOMString version;
};
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
index 0b2456e3f31..f787a3140df 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/keyboard/keyboard_layout.h"
-#include "services/service_manager/public/cpp/interface_provider.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/core/v8/script_promise_resolver.h"
@@ -80,7 +80,8 @@ bool KeyboardLayout::EnsureServiceConnected() {
if (!frame) {
return false;
}
- frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver());
DCHECK(service_);
}
return true;
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
index aa70f5d5302..c607f439b1f 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_LAYOUT_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -16,7 +17,7 @@ namespace blink {
class ScriptPromiseResolver;
-class KeyboardLayout final : public GarbageCollectedFinalized<KeyboardLayout>,
+class KeyboardLayout final : public GarbageCollected<KeyboardLayout>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(KeyboardLayout);
@@ -44,7 +45,7 @@ class KeyboardLayout final : public GarbageCollectedFinalized<KeyboardLayout>,
Member<ScriptPromiseResolver> script_promise_resolver_;
- mojom::blink::KeyboardLockServicePtr service_;
+ mojo::Remote<mojom::blink::KeyboardLockService> service_;
DISALLOW_COPY_AND_ASSIGN(KeyboardLayout);
};
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
index 2a3e41b76b9..575c8b87ecf 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/keyboard/keyboard_lock.h"
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/dom_exception.h"
@@ -100,8 +100,9 @@ bool KeyboardLock::EnsureServiceConnected() {
return false;
}
// See https://bit.ly/2S0zRAS for task types.
- frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(
- &service_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ frame->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(
+ frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
DCHECK(service_);
}
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
index 3a8fe37a58d..ffee4473d70 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_LOCK_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/keyboard_lock/keyboard_lock.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -16,7 +17,7 @@ namespace blink {
class ScriptPromiseResolver;
-class KeyboardLock final : public GarbageCollectedFinalized<KeyboardLock>,
+class KeyboardLock final : public GarbageCollected<KeyboardLock>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(KeyboardLock);
@@ -43,7 +44,7 @@ class KeyboardLock final : public GarbageCollectedFinalized<KeyboardLock>,
void LockRequestFinished(ScriptPromiseResolver*,
mojom::KeyboardLockRequestResult);
- mojom::blink::KeyboardLockServicePtr service_;
+ mojo::Remote<mojom::blink::KeyboardLockService> service_;
Member<ScriptPromiseResolver> request_keylock_resolver_;
DISALLOW_COPY_AND_ASSIGN(KeyboardLock);
diff --git a/chromium/third_party/blink/renderer/modules/launch/dom_window_launch_params.h b/chromium/third_party/blink/renderer/modules/launch/dom_window_launch_params.h
index 881fcb36b9a..d20cfa4e51a 100644
--- a/chromium/third_party/blink/renderer/modules/launch/dom_window_launch_params.h
+++ b/chromium/third_party/blink/renderer/modules/launch/dom_window_launch_params.h
@@ -20,7 +20,7 @@ class LocalDOMWindow;
class Visitor;
class DOMWindowLaunchParams final
- : public GarbageCollectedFinalized<DOMWindowLaunchParams>,
+ : public GarbageCollected<DOMWindowLaunchParams>,
public Supplement<LocalDOMWindow> {
USING_GARBAGE_COLLECTED_MIXIN(DOMWindowLaunchParams);
diff --git a/chromium/third_party/blink/renderer/modules/launch/launch_params.h b/chromium/third_party/blink/renderer/modules/launch/launch_params.h
index ddb62be9808..026f1423611 100644
--- a/chromium/third_party/blink/renderer/modules/launch/launch_params.h
+++ b/chromium/third_party/blink/renderer/modules/launch/launch_params.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_LAUNCH_LAUNCH_PARAMS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_LAUNCH_LAUNCH_PARAMS_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc b/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
index 2f6acc89dad..af48942235c 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "services/service_manager/public/cpp/interface_provider.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/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_lock_granted_callback.h"
@@ -23,6 +23,8 @@
#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/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -54,7 +56,7 @@ HeapVector<Member<LockInfo>> ToLockInfos(
} // namespace
class LockManager::LockRequestImpl final
- : public GarbageCollectedFinalized<LockRequestImpl>,
+ : public GarbageCollected<LockRequestImpl>,
public NameClient,
public mojom::blink::LockRequest {
USING_PRE_FINALIZER(LockManager::LockRequestImpl, Dispose);
@@ -215,6 +217,10 @@ ScriptPromise LockManager::request(ScriptState* script_state,
ExecutionContext* context = ExecutionContext::From(script_state);
DCHECK(context->IsContextThread());
+ context->GetScheduler()->RegisterStickyFeature(
+ blink::SchedulingPolicy::Feature::kWebLocks,
+ {blink::SchedulingPolicy::RecordMetricsForBackForwardCache()});
+
// 5. If origin is an opaque origin, then reject promise with a
// "SecurityError" DOMException.
if (!context->GetSecurityOrigin()->CanAccessLocks()) {
@@ -227,10 +233,10 @@ ScriptPromise LockManager::request(ScriptState* script_state,
}
if (!service_.is_bound()) {
- if (auto* provider = context->GetInterfaceProvider()) {
- provider->GetInterface(service_.BindNewPipeAndPassReceiver(
- context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
- }
+ context->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+
if (!service_.is_bound()) {
exception_state.ThrowTypeError("Service not available.");
return ScriptPromise();
@@ -347,10 +353,10 @@ ScriptPromise LockManager::query(ScriptState* script_state,
}
if (!service_.is_bound()) {
- if (auto* provider = context->GetInterfaceProvider()) {
- provider->GetInterface(service_.BindNewPipeAndPassReceiver(
- context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
- }
+ context->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+
if (!service_.is_bound()) {
exception_state.ThrowTypeError("Service not available.");
return ScriptPromise();
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 cbb606f1e5e..b3bfa941e15 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/locks/lock_manager.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/modules/locks/lock.h"
#include "third_party/blink/renderer/modules/locks/lock_options.h"
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest.json
new file mode 100644
index 00000000000..b0ffff41c0c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest.json
@@ -0,0 +1 @@
+{ "name": "Manifest test app", "start_url": "manifest_test_page.html", "icons": [ { "src": "launcher-icon-1x.png", "sizes": "48x48", "type": "image/png" }, { "src": "image-512px.png", "sizes": "512x512", "type": "image/png" } ], "display": "standalone", "orientation": "landscape" }
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_1.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_1.json
new file mode 100644
index 00000000000..965aa1a8da5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_1.json
@@ -0,0 +1,15 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "action": "/files"
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_2.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_2.json
new file mode 100644
index 00000000000..bc761fbbb48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_2.json
@@ -0,0 +1,16 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "action": "/files",
+ "files": []
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_3.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_3.json
new file mode 100644
index 00000000000..5aa338a5c5e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_3.json
@@ -0,0 +1,19 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "action": "/files",
+ "files": [{
+ "name": "name",
+ "accept": "image/png"
+ }]
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_4.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_4.json
new file mode 100644
index 00000000000..fa58608b26f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_4.json
@@ -0,0 +1,18 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "files": [{
+ "name": "name",
+ "accept": "image/png"
+ }]
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_5.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_5.json
new file mode 100644
index 00000000000..b92df185212
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_5.json
@@ -0,0 +1,18 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "files": [{
+ "name": "name",
+ "accept": ["image/png", "image/jpg"]
+ }]
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_6.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_6.json
new file mode 100644
index 00000000000..b76df252f4b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_file_handler_6.json
@@ -0,0 +1,24 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "file_handler": {
+ "files": [
+ {
+ "name": "name",
+ "accept": ["image/png", "image/jpg"]
+ },
+ {
+ "name": "svgish",
+ "accept": [".svg", "xml/svg"]
+ }
+ ]
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_listing_related_android_app.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_listing_related_android_app.json
new file mode 100644
index 00000000000..3ce01c658c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_listing_related_android_app.json
@@ -0,0 +1,18 @@
+{
+ "name": "Manifest listing related android app",
+ "icons": [
+ {
+ "src": "/banners/image-512px.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "scope": ".",
+ "start_url": ".",
+ "display": "standalone",
+ "prefer_related_applications": false,
+ "related_applications": [{
+ "platform": "play",
+ "id": "com.example.app"
+ }]
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_maskable.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_maskable.json
new file mode 100644
index 00000000000..8c46cfbe63d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_maskable.json
@@ -0,0 +1,20 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "launcher-icon-3x.png",
+ "sizes": "144x144",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ],
+ "scope": "/",
+ "start_url": "manifest_test_page.html",
+ "display": "standalone"
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json
new file mode 100644
index 00000000000..28b8015c84a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json
@@ -0,0 +1,14 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "badge"
+ }
+ ],
+ "start_url": "/",
+ "display": "standalone",
+ "display": "minimal-ui"
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_1.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_1.json
new file mode 100644
index 00000000000..14dcd01faed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_1.json
@@ -0,0 +1,12 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {}
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_2.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_2.json
new file mode 100644
index 00000000000..8c23831a49a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_2.json
@@ -0,0 +1,14 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "action": ""
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_3.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_3.json
new file mode 100644
index 00000000000..a51afa0f690
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_3.json
@@ -0,0 +1,14 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "params": {}
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_4.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_4.json
new file mode 100644
index 00000000000..879eae779f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_4.json
@@ -0,0 +1,15 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "action": "https://example.com/",
+ "params": {}
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_5.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_5.json
new file mode 100644
index 00000000000..de638f366c1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_5.json
@@ -0,0 +1,15 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "action": "share/",
+ "params": {}
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_6.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_6.json
new file mode 100644
index 00000000000..d70f4f9e0bc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_6.json
@@ -0,0 +1,19 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "action": "share/blah/",
+ "params": {
+ "text": "foo",
+ "title": "bar",
+ "url": "baz"
+ }
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_7.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_7.json
new file mode 100644
index 00000000000..339c157f0d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_7.json
@@ -0,0 +1,20 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "url_template": "https://whatever.test/share?title={title}",
+ "action": "share/blah/",
+ "params": {
+ "text": "foo",
+ "title": "bar",
+ "url": "baz"
+ }
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_8.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_8.json
new file mode 100644
index 00000000000..e8f0a83c101
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_share_target_8.json
@@ -0,0 +1,22 @@
+{
+ "name": "Manifest test app",
+ "icons": [
+ {
+ "src": "launcher-icon-4x.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "manifest_test_page.html",
+ "share_target": {
+ "url_template": "https://whatever.test/share?title={title}",
+ "action": "share/blah/",
+ "enctype": "application/x-www-form-urlencoded",
+ "method": "POST",
+ "params": {
+ "text": "foo",
+ "title": "bar",
+ "url": "baz"
+ }
+ }
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_short_name.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_short_name.json
new file mode 100644
index 00000000000..d9c5dfc3d2b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_short_name.json
@@ -0,0 +1 @@
+{ "short_name": "Manifest", "start_url": "https://whatever.test/pwa/manifest_test_page.html", "icons": [ { "src": "launcher-icon-1x.png", "sizes": "48x48", "type": "image/png" }, { "src": "image-512px.png", "sizes": "512x512", "type": "image/png" } ], "display": "browser", "orientation": "portrait", "theme_color": "#000", "scope": "https://whatever.test/pwa/" }
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_wrong_origin.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_wrong_origin.json
new file mode 100644
index 00000000000..43138d91ca7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_wrong_origin.json
@@ -0,0 +1 @@
+{ "short_name": "Manifest", "start_url": "https://example.com/pwa/manifest_test_page.html", "icons": [ { "src": "launcher-icon-1x.png", "sizes": "48x48", "type": "image/png" }, { "src": "image-512px.png", "sizes": "512x512", "type": "image/png" } ], "display": "browser", "orientation": "portrait", "theme_color": "#000", "scope": "https://example.com/pwa/" }
diff --git a/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/play_app_url_manifest.json b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/play_app_url_manifest.json
new file mode 100644
index 00000000000..aa9931264c3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/play_app_url_manifest.json
@@ -0,0 +1,8 @@
+{
+ "prefer_related_applications": true,
+ "related_applications": [{
+ "platform": "play",
+ "id": "com.google.android.apps.chrome",
+ "url": "https://play.google.com/store/apps/details?id=123456&referrer=chrome_inline"
+ }]
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
index ab10edbfb97..9dcb4d6fb6c 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/manifest/image_resource_type_converters.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
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 100eee1bc80..20c7b45cf2f 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
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_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/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.h b/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.h
index b49e7f8b6e5..770cb163f05 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_change_notifier.h
@@ -17,7 +17,7 @@ namespace blink {
class LocalFrame;
class MODULES_EXPORT ManifestChangeNotifier
- : public GarbageCollectedFinalized<ManifestChangeNotifier> {
+ : public GarbageCollected<ManifestChangeNotifier> {
public:
explicit ManifestChangeNotifier(LocalFrame& frame);
virtual ~ManifestChangeNotifier();
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 44b1e8aae79..f38899dd5c0 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/manifest/manifest_fetcher.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
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 5e8af0313d0..bda2edd79e3 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fetcher.h
@@ -24,7 +24,7 @@ class TextResourceDecoder;
// Helper class to download a Web Manifest. When an instance is created, the
// caller need to call Start() and wait for the passed callback to be executed.
// If the fetch fails, the callback will be called with two empty objects.
-class ManifestFetcher final : public GarbageCollectedFinalized<ManifestFetcher>,
+class ManifestFetcher final : public GarbageCollected<ManifestFetcher>,
public ThreadableLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ManifestFetcher);
// This will be called asynchronously after the URL has been fetched,
diff --git a/chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.cc b/chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.cc
new file mode 100644
index 00000000000..274f6620f7c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.cc
@@ -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.
+
+#include "third_party/blink/renderer/modules/manifest/manifest_parser.h"
+#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// Fuzzer for blink::ManifestParser
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport();
+ String string = String::FromUTF8(reinterpret_cast<const char*>(data), size);
+ KURL manifest_url("https://whatever.test/manifest.json");
+ KURL document_url("https://whatever.test/");
+ ManifestParser parser(string, manifest_url, document_url);
+ parser.Parse();
+ 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/manifest/manifest_fuzzer.dict b/chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.dict
new file mode 100644
index 00000000000..01e3f0f95e7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_fuzzer.dict
@@ -0,0 +1,88 @@
+# 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.
+
+"*"
+"{"
+"}"
+"["
+"]"
+"."
+"\".\""
+"/"
+"\"/\""
+"/*"
+"true"
+"\"true\""
+"false"
+"\"false\""
+"name"
+"\"name\""
+"short_name"
+"\"short_name\""
+"icons"
+"\"icons\""
+"src"
+"\"src\""
+"type"
+"\"type\""
+"sizes"
+"\"sizes\""
+"start_url"
+"\"start_url\""
+"display"
+"\"display\""
+"orientation"
+"\"orientation\""
+"standalone"
+"\"standalone\""
+"minimal-ui"
+"\"minimal-ui\""
+"browser"
+"\"browser\""
+"purpose"
+"\"purpose\""
+"any"
+"\"any\""
+"image/png"
+"\"image/png\""
+"url"
+"\"url\""
+"platform"
+"\"platform\""
+"id"
+"\"id\""
+"related_applications"
+"\"related_applications\""
+"prefer_related_applications"
+"\"prefer_related_applications\""
+"theme_color"
+"\"theme_color\""
+"play"
+"\"play\""
+"https://example.com/"
+"\"https://example.com/\""
+"https://example.com/some/path"
+"\"https://example.com/some/path\""
+"GET"
+"\"GET\""
+"POST"
+"\"POST\""
+"action"
+"\"action\""
+"enctype"
+"\"enctype\""
+"share_target"
+"\"share_target\""
+"url_template"
+"\"url_template\""
+"file_handler"
+"\"file_handler\""
+"params"
+"\"params\""
+"application/x-www-form-urlencoded"
+"\"application/x-www-form-urlencoded\""
+"png"
+".png"
+"image/png"
+"\"image/png\""
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 8faab6a7179..2eb33b333d0 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.cc
@@ -255,10 +255,6 @@ void ManifestManager::BindReceiver(
}
void ManifestManager::ContextDestroyed(ExecutionContext*) {
- Dispose();
-}
-
-void ManifestManager::Dispose() {
if (fetcher_)
fetcher_->Cancel();
@@ -270,6 +266,10 @@ void ManifestManager::Dispose() {
receivers_.Clear();
}
+void ManifestManager::Prefinalize() {
+ receivers_.Clear();
+}
+
void ManifestManager::Trace(blink::Visitor* visitor) {
visitor->Trace(fetcher_);
visitor->Trace(manifest_change_notifier_);
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 678c08a8ed9..9f40633d078 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_manager.h
@@ -9,7 +9,7 @@
#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.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"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
@@ -30,12 +30,12 @@ class ResourceResponse;
// the ManifestParser in order to do so.
//
// Consumers should use the mojo ManifestManager interface to use this class.
-class MODULES_EXPORT ManifestManager
- : public GarbageCollectedFinalized<ManifestManager>,
- public Supplement<LocalFrame>,
- public mojom::blink::ManifestManager,
- public ContextLifecycleObserver {
+class MODULES_EXPORT ManifestManager : public GarbageCollected<ManifestManager>,
+ public Supplement<LocalFrame>,
+ public mojom::blink::ManifestManager,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(ManifestManager);
+ USING_PRE_FINALIZER(ManifestManager, Prefinalize);
public:
static const char kSupplementName[];
@@ -85,7 +85,7 @@ class MODULES_EXPORT ManifestManager
void BindReceiver(
mojo::PendingReceiver<mojom::blink::ManifestManager> receiver);
- void Dispose();
+ void Prefinalize();
friend class ManifestManagerTest;
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 45020797187..917b0b63531 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -239,13 +239,15 @@ KURL ManifestParser::ParseScope(const JSONObject* object,
return scope;
}
-WebDisplayMode ManifestParser::ParseDisplay(const JSONObject* object) {
+blink::mojom::DisplayMode ManifestParser::ParseDisplay(
+ const JSONObject* object) {
base::Optional<String> display = ParseString(object, "display", Trim);
if (!display.has_value())
- return kWebDisplayModeUndefined;
+ return blink::mojom::DisplayMode::kUndefined;
- WebDisplayMode display_enum = WebDisplayModeFromString(display->Utf8());
- if (display_enum == kWebDisplayModeUndefined)
+ blink::mojom::DisplayMode display_enum =
+ DisplayModeFromString(display->Utf8());
+ if (display_enum == blink::mojom::DisplayMode::kUndefined)
AddErrorInfo("unknown 'display' value ignored.");
return display_enum;
}
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 db468b331ec..cdf3bcd7352 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_parser.h
@@ -106,9 +106,9 @@ class MODULES_EXPORT ManifestParser {
// Parses the 'display' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-the-display-member
- // Returns the parsed DisplayMode if any, WebDisplayModeUndefined if the
+ // Returns the parsed DisplayMode if any, DisplayMode::kUndefined if the
// parsing failed.
- WebDisplayMode ParseDisplay(const JSONObject* object);
+ blink::mojom::DisplayMode ParseDisplay(const JSONObject* object);
// Parses the 'orientation' field of the manifest, as defined in:
// https://w3c.github.io/manifest/#dfn-steps-for-processing-the-orientation-member
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 1ee1ec177e9..346cfe2a97e 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
@@ -99,7 +99,7 @@ TEST_F(ManifestParserTest, ValidNoContentParses) {
ASSERT_TRUE(manifest->name.IsNull());
ASSERT_TRUE(manifest->short_name.IsNull());
ASSERT_TRUE(manifest->start_url.IsEmpty());
- ASSERT_EQ(manifest->display, kWebDisplayModeUndefined);
+ ASSERT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
ASSERT_EQ(manifest->orientation, kWebScreenOrientationLockDefault);
ASSERT_FALSE(manifest->has_theme_color);
ASSERT_FALSE(manifest->has_background_color);
@@ -452,7 +452,7 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Smoke test.
{
auto& manifest = ParseManifest("{ \"display\": \"browser\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeBrowser);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_FALSE(IsManifestEmpty(manifest));
EXPECT_EQ(0u, GetErrorCount());
}
@@ -460,14 +460,14 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Trim whitespaces.
{
auto& manifest = ParseManifest("{ \"display\": \" browser \" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeBrowser);
+ 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\": {} }");
- EXPECT_EQ(manifest->display, kWebDisplayModeUndefined);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
"property 'display' ignored,"
@@ -478,7 +478,7 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Don't parse if name isn't a string.
{
auto& manifest = ParseManifest("{ \"display\": 42 }");
- EXPECT_EQ(manifest->display, kWebDisplayModeUndefined);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ(
"property 'display' ignored,"
@@ -489,7 +489,7 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Parse fails if string isn't known.
{
auto& manifest = ParseManifest("{ \"display\": \"browser_something\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeUndefined);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined);
EXPECT_EQ(1u, GetErrorCount());
EXPECT_EQ("unknown 'display' value ignored.", errors()[0]);
}
@@ -497,35 +497,35 @@ TEST_F(ManifestParserTest, DisplayParseRules) {
// Accept 'fullscreen'.
{
auto& manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeFullscreen);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kFullscreen);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'fullscreen'.
{
auto& manifest = ParseManifest("{ \"display\": \"standalone\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeStandalone);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kStandalone);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'minimal-ui'.
{
auto& manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeMinimalUi);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kMinimalUi);
EXPECT_EQ(0u, GetErrorCount());
}
// Accept 'browser'.
{
auto& manifest = ParseManifest("{ \"display\": \"browser\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeBrowser);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
// Case insensitive.
{
auto& manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
- EXPECT_EQ(manifest->display, kWebDisplayModeBrowser);
+ EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kBrowser);
EXPECT_EQ(0u, GetErrorCount());
}
}
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
index a07f4771265..38cc1352fb0 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.cc
@@ -8,7 +8,7 @@
#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-forward.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"
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
index 5acd0f64cb8..3642dc58172 100644
--- a/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h
+++ b/chromium/third_party/blink/renderer/modules/manifest/manifest_type_converters.h
@@ -6,7 +6,7 @@
#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.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
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 330ba3c282f..ed75fc1aa1a 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
@@ -42,8 +42,9 @@ void ManifestUmaUtil::ParseSucceeded(
!manifest->short_name.IsEmpty());
UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.start_url",
!manifest->start_url.IsEmpty());
- UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.display",
- manifest->display != kWebDisplayModeUndefined);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Manifest.HasProperty.display",
+ manifest->display != blink::mojom::DisplayMode::kUndefined);
UMA_HISTOGRAM_BOOLEAN(
"Manifest.HasProperty.orientation",
manifest->orientation != kWebScreenOrientationLockDefault);
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 22d4041512b..ec10ba83c5c 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
@@ -12,16 +12,12 @@
#include "media/base/supported_types.h"
#include "media/filters/stream_parser_factory.h"
#include "media/mojo/mojom/media_types.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_decoding_configuration.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_encrypted_media_client.h"
#include "third_party/blink/public/platform/web_encrypted_media_request.h"
-#include "third_party/blink/public/platform/web_transmission_encoding_info_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -48,7 +44,11 @@
#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/instrumentation/use_counter.h"
+#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/media_capabilities/web_media_decoding_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/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -737,8 +737,7 @@ ScriptPromise MediaCapabilities::encodingInfo(
}
if (configuration->type() == "transmission") {
- if (auto* handler =
- Platform::Current()->TransmissionEncodingInfoHandler()) {
+ if (auto* handler = TransmissionEncodingInfoHandler::Instance()) {
handler->EncodingInfo(ToWebMediaConfiguration(configuration),
WTF::Bind(&OnMediaCapabilitiesEncodingInfo,
WrapPersistent(resolver)));
@@ -776,14 +775,14 @@ bool MediaCapabilities::EnsureService(ExecutionContext* execution_context) {
if (decode_history_service_)
return true;
- if (!execution_context || !execution_context->GetInterfaceProvider())
+ if (!execution_context)
return false;
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
execution_context->GetTaskRunner(TaskType::kMediaElementEvent);
- execution_context->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&decode_history_service_, task_runner));
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
+ decode_history_service_.BindNewPipeAndPassReceiver(task_runner));
return true;
}
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 a052fd0eecc..100e5b0367c 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
@@ -7,6 +7,7 @@
#include "media/base/video_codecs.h" // for media::VideoCodecProfile
#include "media/mojo/mojom/video_decode_perf_history.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.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/visitor.h"
@@ -52,7 +53,8 @@ class MODULES_EXPORT MediaCapabilities final : public ScriptWrappable {
bool is_smooth,
bool is_power_efficient);
- media::mojom::blink::VideoDecodePerfHistoryPtr decode_history_service_;
+ mojo::Remote<media::mojom::blink::VideoDecodePerfHistory>
+ decode_history_service_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn b/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
index 0eb064ec84e..cb8247d66c0 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
@@ -101,38 +101,6 @@ blink_modules_sources("media_controls") {
":media_controls_resources",
"//services/service_manager/public/cpp",
]
-
- if (is_android && notouch_build) {
- sources += [
- "touchless/elements/media_controls_touchless_bottom_container_element.cc",
- "touchless/elements/media_controls_touchless_bottom_container_element.h",
- "touchless/elements/media_controls_touchless_element.cc",
- "touchless/elements/media_controls_touchless_element.h",
- "touchless/elements/media_controls_touchless_overlay_element.cc",
- "touchless/elements/media_controls_touchless_overlay_element.h",
- "touchless/elements/media_controls_touchless_play_button_element.cc",
- "touchless/elements/media_controls_touchless_play_button_element.h",
- "touchless/elements/media_controls_touchless_seek_button_element.cc",
- "touchless/elements/media_controls_touchless_seek_button_element.h",
- "touchless/elements/media_controls_touchless_time_display_element.cc",
- "touchless/elements/media_controls_touchless_time_display_element.h",
- "touchless/elements/media_controls_touchless_timeline_element.cc",
- "touchless/elements/media_controls_touchless_timeline_element.h",
- "touchless/elements/media_controls_touchless_volume_button_element.cc",
- "touchless/elements/media_controls_touchless_volume_button_element.h",
- "touchless/elements/media_controls_touchless_volume_container_element.cc",
- "touchless/elements/media_controls_touchless_volume_container_element.h",
- "touchless/media_controls_touchless_impl.cc",
- "touchless/media_controls_touchless_impl.h",
- "touchless/media_controls_touchless_media_event_listener.cc",
- "touchless/media_controls_touchless_media_event_listener.h",
- "touchless/media_controls_touchless_media_event_listener_observer.h",
- "touchless/media_controls_touchless_resource_loader.cc",
- "touchless/media_controls_touchless_resource_loader.h",
- ]
-
- deps += [ ":media_controls_touchless_resources" ]
- }
}
grit("media_controls_resources") {
@@ -144,14 +112,3 @@ grit("media_controls_resources") {
"media_controls_resources_200_percent.pak",
]
}
-
-if (is_android && notouch_build) {
- grit("media_controls_touchless_resources") {
- output_dir = "$blink_modules_output_dir/media_controls/touchless/resources/"
- source = "touchless/resources/media_controls_touchless_resources.grd"
- outputs = [
- "grit/media_controls_touchless_resources.h",
- "media_controls_touchless_resources.pak",
- ]
- }
-}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
index 23e7404c150..03536cd57df 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
@@ -56,12 +57,12 @@ void MediaControlCastButtonElement::TryShowOverlay() {
void MediaControlCastButtonElement::UpdateDisplayType() {
if (IsPlayingRemotely()) {
setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaCastOnButton)));
+ WTF::AtomicString(
+ GetLocale().QueryString(IDS_AX_MEDIA_CAST_ON_BUTTON)));
} else {
setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaCastOffButton)));
+ WTF::AtomicString(
+ GetLocale().QueryString(IDS_AX_MEDIA_CAST_OFF_BUTTON)));
}
UpdateOverflowString();
SetClass("on", IsPlayingRemotely());
@@ -73,9 +74,8 @@ bool MediaControlCastButtonElement::WillRespondToMouseClickEvents() {
return true;
}
-WebLocalizedString::Name MediaControlCastButtonElement::GetOverflowStringName()
- const {
- return WebLocalizedString::kOverflowMenuCast;
+int MediaControlCastButtonElement::GetOverflowStringId() const {
+ return IDS_MEDIA_OVERFLOW_MENU_CAST;
}
bool MediaControlCastButtonElement::HasOverflowButton() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h
index 0b0a774a010..9bc21a99da0 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h
@@ -26,7 +26,7 @@ class MediaControlCastButtonElement final : public MediaControlInputElement {
// MediaControlInputElement overrides.
bool WillRespondToMouseClickEvents() final;
- WebLocalizedString::Name GetOverflowStringName() const final;
+ int GetOverflowStringId() const final;
bool HasOverflowButton() const final;
protected:
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.cc
index 92d077b7c00..42baaa490c9 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.cc
@@ -4,15 +4,15 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_current_time_display_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
namespace blink {
MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(
MediaControlsImpl& media_controls)
- : MediaControlTimeDisplayElement(
- media_controls,
- WebLocalizedString::kAXMediaCurrentTimeDisplay) {
+ : MediaControlTimeDisplayElement(media_controls,
+ IDS_AX_MEDIA_CURRENT_TIME_DISPLAY) {
SetShadowPseudoId(
AtomicString("-webkit-media-controls-current-time-display"));
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.cc
index 80c544b9d42..5ed74878bce 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
@@ -21,7 +22,7 @@ MediaControlDisplayCutoutFullscreenButtonElement::
setType(input_type_names::kButton);
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaDisplayCutoutFullscreenButton)));
+ IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON)));
SetShadowPseudoId(AtomicString(
"-internal-media-controls-display-cutout-fullscreen-button"));
SetIsWanted(false);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
index e7cf7466465..eb065bd0697 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_display_cutout_fullscreen_button_element.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/events/touch_event.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -98,7 +99,7 @@ class MediaControlDisplayCutoutFullscreenButtonElementTest
TEST_F(MediaControlDisplayCutoutFullscreenButtonElementTest,
Fullscreen_ButtonAccessibility) {
EXPECT_EQ(display_cutout_fullscreen_button_->GetLocale().QueryString(
- WebLocalizedString::kAXMediaDisplayCutoutFullscreenButton),
+ IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON),
display_cutout_fullscreen_button_->getAttribute(
html_names::kAriaLabelAttr));
}
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 5f8267cbda9..26e648a0df6 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -22,9 +23,9 @@ MediaControlDownloadButtonElement::MediaControlDownloadButtonElement(
MediaControlsImpl& media_controls)
: MediaControlInputElement(media_controls) {
setType(input_type_names::kButton);
- setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaDownloadButton)));
+ setAttribute(
+ html_names::kAriaLabelAttr,
+ WTF::AtomicString(GetLocale().QueryString(IDS_AX_MEDIA_DOWNLOAD_BUTTON)));
SetShadowPseudoId(AtomicString("-internal-media-controls-download-button"));
SetIsWanted(false);
@@ -46,9 +47,8 @@ bool MediaControlDownloadButtonElement::ShouldDisplayDownloadButton() const {
return true;
}
-WebLocalizedString::Name
-MediaControlDownloadButtonElement::GetOverflowStringName() const {
- return WebLocalizedString::kOverflowMenuDownload;
+int MediaControlDownloadButtonElement::GetOverflowStringId() const {
+ return IDS_MEDIA_OVERFLOW_MENU_DOWNLOAD;
}
bool MediaControlDownloadButtonElement::HasOverflowButton() const {
@@ -68,7 +68,7 @@ const char* MediaControlDownloadButtonElement::GetNameForHistograms() const {
}
void MediaControlDownloadButtonElement::DefaultEventHandler(Event& event) {
- const KURL& url = MediaElement().currentSrc();
+ const KURL& url = MediaElement().downloadURL();
if ((event.type() == event_type_names::kClick ||
event.type() == event_type_names::kGesturetap) &&
!(url.IsNull() || url.IsEmpty())) {
@@ -79,7 +79,7 @@ void MediaControlDownloadButtonElement::DefaultEventHandler(Event& event) {
request.SetRequestContext(mojom::RequestContextType::DOWNLOAD);
request.SetRequestorOrigin(SecurityOrigin::Create(GetDocument().Url()));
GetDocument().GetFrame()->Client()->DownloadURL(
- request, DownloadCrossOriginRedirects::kFollow);
+ request, network::mojom::RedirectMode::kError);
}
MediaControlInputElement::DefaultEventHandler(event);
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h
index a499019b32c..93334801f6e 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.h
@@ -23,7 +23,7 @@ class MediaControlDownloadButtonElement final
// MediaControlInputElement overrides.
// TODO(mlamouri): add WillRespondToMouseClickEvents
- WebLocalizedString::Name GetOverflowStringName() const final;
+ int GetOverflowStringId() const final;
bool HasOverflowButton() const final;
bool IsControlPanelButton() const final;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_base.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_base.h
index 32569074eca..334248fb8df 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_base.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_base.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_ELEMENT_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_ELEMENT_BASE_H_
-#include "third_party/blink/public/platform/web_localized_string.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
index 0ba85ffc249..efcd5928385 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -28,11 +29,11 @@ void MediaControlFullscreenButtonElement::SetIsFullscreen(bool is_fullscreen) {
if (is_fullscreen) {
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaExitFullscreenButton)));
+ IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON)));
} else {
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaEnterFullscreenButton)));
+ IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON)));
}
SetClass("fullscreen", is_fullscreen);
}
@@ -41,11 +42,10 @@ bool MediaControlFullscreenButtonElement::WillRespondToMouseClickEvents() {
return true;
}
-WebLocalizedString::Name
-MediaControlFullscreenButtonElement::GetOverflowStringName() const {
+int MediaControlFullscreenButtonElement::GetOverflowStringId() const {
if (MediaElement().IsFullscreen())
- return WebLocalizedString::kOverflowMenuExitFullscreen;
- return WebLocalizedString::kOverflowMenuEnterFullscreen;
+ return IDS_MEDIA_OVERFLOW_MENU_EXIT_FULLSCREEN;
+ return IDS_MEDIA_OVERFLOW_MENU_ENTER_FULLSCREEN;
}
bool MediaControlFullscreenButtonElement::HasOverflowButton() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h
index 12b50993fe1..d8aa1ae18c0 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h
@@ -22,7 +22,7 @@ class MediaControlFullscreenButtonElement final
// MediaControlInputElement overrides.
bool WillRespondToMouseClickEvents() override;
- WebLocalizedString::Name GetOverflowStringName() const override;
+ int GetOverflowStringId() const override;
bool HasOverflowButton() const override;
bool IsControlPanelButton() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc
index 705b56e59c7..9ed59699962 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h"
#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
@@ -186,10 +187,9 @@ MediaControlInputElement::MediaControlInputElement(
: HTMLInputElement(media_controls.GetDocument(), CreateElementFlags()),
MediaControlElementBase(media_controls, this) {}
-WebLocalizedString::Name MediaControlInputElement::GetOverflowStringName()
- const {
+int MediaControlInputElement::GetOverflowStringId() const {
NOTREACHED();
- return WebLocalizedString::kAXAMPMFieldText;
+ return IDS_AX_AM_PM_FIELD_TEXT;
}
void MediaControlInputElement::UpdateShownState() {
@@ -256,7 +256,7 @@ bool MediaControlInputElement::IsMediaControlElement() const {
}
String MediaControlInputElement::GetOverflowMenuString() const {
- return MediaElement().GetLocale().QueryString(GetOverflowStringName());
+ return MediaElement().GetLocale().QueryString(GetOverflowStringId());
}
String MediaControlInputElement::GetOverflowMenuSubtitleString() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h
index 54970c0f729..8f39a187026 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h
@@ -49,10 +49,10 @@ class MODULES_EXPORT MediaControlInputElement : public HTMLInputElement,
// will be used as a suffix for histograms.
virtual const char* GetNameForHistograms() const = 0;
- // Returns a string representation of the media control element.
- // Subclasses should override this method to return the string representation
+ // Returns a string resource id of the media control element.
+ // Subclasses should override this method to return the string resource id
// of the overflow button.
- virtual WebLocalizedString::Name GetOverflowStringName() const;
+ virtual int GetOverflowStringId() const;
// Implements a default event handler to record interaction on click.
void DefaultEventHandler(Event&) override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
index 20ae4a42321..f6fa3ce832f 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
@@ -44,8 +45,8 @@ class MediaControlInputElementImpl final : public MediaControlInputElement {
: "MediaControlInputElementImpl";
}
- WebLocalizedString::Name GetOverflowStringName() const final {
- return WebLocalizedString::kOverflowMenuDownload;
+ int GetOverflowStringId() const final {
+ return IDS_MEDIA_OVERFLOW_MENU_DOWNLOAD;
}
};
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
index a753f9a2a91..8950bbed67e 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
@@ -38,9 +39,9 @@ MediaControlLoadingPanelElement::MediaControlLoadingPanelElement(
MediaControlsImpl& media_controls)
: MediaControlDivElement(media_controls) {
SetShadowPseudoId(AtomicString("-internal-media-controls-loading-panel"));
- setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaLoadingPanel)));
+ setAttribute(
+ html_names::kAriaLabelAttr,
+ WTF::AtomicString(GetLocale().QueryString(IDS_AX_MEDIA_LOADING_PANEL)));
setAttribute(html_names::kAriaLiveAttr, "polite");
CreateUserAgentShadowRoot();
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.cc
index 39afbe98d6e..2ed62bcb85b 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/input_type_names.h"
@@ -29,21 +30,20 @@ void MediaControlMuteButtonElement::UpdateDisplayType() {
// 'muted' when the volume is 0 even if the element is not muted. This allows
// the painting and the display type to actually match.
bool muted = MediaElement().muted() || MediaElement().volume() == 0;
- setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- muted ? WebLocalizedString::kAXMediaUnMuteButton
- : WebLocalizedString::kAXMediaMuteButton)));
+ setAttribute(
+ html_names::kAriaLabelAttr,
+ WTF::AtomicString(GetLocale().QueryString(
+ muted ? IDS_AX_MEDIA_UNMUTE_BUTTON : IDS_AX_MEDIA_MUTE_BUTTON)));
SetClass("muted", muted);
UpdateOverflowString();
MediaControlInputElement::UpdateDisplayType();
}
-WebLocalizedString::Name MediaControlMuteButtonElement::GetOverflowStringName()
- const {
+int MediaControlMuteButtonElement::GetOverflowStringId() const {
if (MediaElement().muted())
- return WebLocalizedString::kOverflowMenuUnmute;
- return WebLocalizedString::kOverflowMenuMute;
+ return IDS_MEDIA_OVERFLOW_MENU_UNMUTE;
+ return IDS_MEDIA_OVERFLOW_MENU_MUTE;
}
bool MediaControlMuteButtonElement::HasOverflowButton() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h
index f9fbeb82f84..70feb7e2e27 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_mute_button_element.h
@@ -19,7 +19,7 @@ class MediaControlMuteButtonElement final : public MediaControlInputElement {
// MediaControlInputElement overrides.
bool WillRespondToMouseClickEvents() override;
void UpdateDisplayType() override;
- WebLocalizedString::Name GetOverflowStringName() const override;
+ int GetOverflowStringId() const override;
bool HasOverflowButton() const override;
bool IsControlPanelButton() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.cc
index 284eaf03141..3fce3d9e6c4 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
@@ -16,12 +17,12 @@ MediaControlOverflowMenuButtonElement::MediaControlOverflowMenuButtonElement(
MediaControlsImpl& media_controls)
: MediaControlInputElement(media_controls) {
setType(input_type_names::kButton);
- setAttribute(html_names::kAriaLabelAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaOverflowButton)));
+ setAttribute(
+ html_names::kAriaLabelAttr,
+ WTF::AtomicString(GetLocale().QueryString(IDS_AX_MEDIA_OVERFLOW_BUTTON)));
setAttribute(html_names::kTitleAttr,
- WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaOverflowButtonHelp)));
+ WTF::AtomicString(
+ GetLocale().QueryString(IDS_AX_MEDIA_OVERFLOW_BUTTON_HELP)));
SetShadowPseudoId(AtomicString("-internal-media-controls-overflow-button"));
SetIsWanted(false);
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
index e41057b89e1..a06074cf44c 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -47,9 +48,8 @@ MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(
void MediaControlOverlayPlayButtonElement::UpdateDisplayType() {
SetIsWanted(MediaElement().ShouldShowControls());
- WebLocalizedString::Name state =
- MediaElement().paused() ? WebLocalizedString::kAXMediaPlayButton
- : WebLocalizedString::kAXMediaPauseButton;
+ int state = MediaElement().paused() ? IDS_AX_MEDIA_PLAY_BUTTON
+ : IDS_AX_MEDIA_PAUSE_BUTTON;
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(state)));
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
index 77bb081a854..333982bfe05 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_source.h"
@@ -51,16 +52,15 @@ void MediaControlPictureInPictureButtonElement::UpdateDisplayType() {
MediaControlInputElement::UpdateDisplayType();
}
-WebLocalizedString::Name
-MediaControlPictureInPictureButtonElement::GetOverflowStringName() const {
+int MediaControlPictureInPictureButtonElement::GetOverflowStringId() const {
DCHECK(MediaElement().IsHTMLVideoElement());
bool isInPictureInPicture =
PictureInPictureController::IsElementInPictureInPicture(
&ToHTMLVideoElement(MediaElement()));
return isInPictureInPicture
- ? WebLocalizedString::kOverflowMenuExitPictureInPicture
- : WebLocalizedString::kOverflowMenuEnterPictureInPicture;
+ ? IDS_MEDIA_OVERFLOW_MENU_EXIT_PICTURE_IN_PICTURE
+ : IDS_MEDIA_OVERFLOW_MENU_ENTER_PICTURE_IN_PICTURE;
}
bool MediaControlPictureInPictureButtonElement::HasOverflowButton() const {
@@ -102,10 +102,9 @@ void MediaControlPictureInPictureButtonElement::UpdateAriaString(
bool isInPictureInPicture) {
String aria_string =
isInPictureInPicture
- ? GetLocale().QueryString(
- WebLocalizedString::kAXMediaExitPictureInPictureButton)
+ ? GetLocale().QueryString(IDS_AX_MEDIA_EXIT_PICTURE_IN_PICTURE_BUTTON)
: GetLocale().QueryString(
- WebLocalizedString::kAXMediaEnterPictureInPictureButton);
+ IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON);
setAttribute(html_names::kAriaLabelAttr, WTF::AtomicString(aria_string));
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
index 54a30d5adf4..c23a2aac832 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
@@ -20,7 +20,7 @@ class MediaControlPictureInPictureButtonElement final
// MediaControlInputElement:
bool WillRespondToMouseClickEvents() override;
void UpdateDisplayType() override;
- WebLocalizedString::Name GetOverflowStringName() const override;
+ int GetOverflowStringId() const override;
bool HasOverflowButton() const override;
bool IsControlPanelButton() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc
index c91f1de30b5..526d64f7a03 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/input_type_names.h"
@@ -25,9 +26,8 @@ bool MediaControlPlayButtonElement::WillRespondToMouseClickEvents() {
}
void MediaControlPlayButtonElement::UpdateDisplayType() {
- WebLocalizedString::Name state =
- MediaElement().paused() ? WebLocalizedString::kAXMediaPlayButton
- : WebLocalizedString::kAXMediaPauseButton;
+ int state = MediaElement().paused() ? IDS_AX_MEDIA_PLAY_BUTTON
+ : IDS_AX_MEDIA_PAUSE_BUTTON;
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(state)));
SetClass("pause", MediaElement().paused());
@@ -36,11 +36,10 @@ void MediaControlPlayButtonElement::UpdateDisplayType() {
MediaControlInputElement::UpdateDisplayType();
}
-WebLocalizedString::Name MediaControlPlayButtonElement::GetOverflowStringName()
- const {
+int MediaControlPlayButtonElement::GetOverflowStringId() const {
if (MediaElement().paused())
- return WebLocalizedString::kOverflowMenuPlay;
- return WebLocalizedString::kOverflowMenuPause;
+ return IDS_MEDIA_OVERFLOW_MENU_PLAY;
+ return IDS_MEDIA_OVERFLOW_MENU_PAUSE;
}
bool MediaControlPlayButtonElement::HasOverflowButton() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h
index 1248bf8cb68..4fea9d5c53c 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_play_button_element.h
@@ -19,7 +19,7 @@ class MediaControlPlayButtonElement final : public MediaControlInputElement {
// MediaControlInputElement overrides.
bool WillRespondToMouseClickEvents() override;
void UpdateDisplayType() override;
- WebLocalizedString::Name GetOverflowStringName() const override;
+ int GetOverflowStringId() const override;
bool HasOverflowButton() const override;
bool IsControlPanelButton() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc
index 1622c84e74f..d5fa0869c8a 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
namespace {
@@ -18,9 +19,8 @@ namespace blink {
MediaControlRemainingTimeDisplayElement::
MediaControlRemainingTimeDisplayElement(MediaControlsImpl& media_controls)
- : MediaControlTimeDisplayElement(
- media_controls,
- WebLocalizedString::kAXMediaTimeRemainingDisplay) {
+ : MediaControlTimeDisplayElement(media_controls,
+ IDS_AX_MEDIA_TIME_REMAINING_DISPLAY) {
SetShadowPseudoId(
AtomicString("-webkit-media-controls-time-remaining-display"));
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
index 27a1ed54eb7..d9e9c8f2ce5 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -50,9 +51,9 @@ void MediaControlScrubbingMessageElement::PopulateChildren() {
MediaControlsResourceLoader::GetArrowLeftSVGImage());
arrow_left_div2->SetInnerHTMLFromString(
MediaControlsResourceLoader::GetArrowLeftSVGImage());
- message_div->setInnerText(MediaElement().GetLocale().QueryString(
- WebLocalizedString::kMediaScrubbingMessageText),
- ASSERT_NO_EXCEPTION);
+ message_div->setInnerText(
+ MediaElement().GetLocale().QueryString(IDS_MEDIA_SCRUBBING_MESSAGE_TEXT),
+ ASSERT_NO_EXCEPTION);
arrow_right_div1->SetInnerHTMLFromString(
MediaControlsResourceLoader::GetArrowRightSVGImage());
arrow_right_div2->SetInnerHTMLFromString(
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
index 55959a5d40f..0dde7c68f04 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/text.h"
@@ -57,7 +58,7 @@ MediaControlTextTrackListElement::MediaControlTextTrackListElement(
setAttribute(html_names::kRoleAttr, "menu");
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kOverflowMenuCaptionsSubmenuTitle)));
+ IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS_SUBMENU_TITLE)));
SetShadowPseudoId(AtomicString("-internal-media-controls-text-track-list"));
}
@@ -177,12 +178,12 @@ Element* MediaControlTextTrackListElement::CreateTextTrackHeaderItem() {
header_item->ParserAppendChild(
Text::Create(GetDocument(),
GetLocale().QueryString(
- WebLocalizedString::kOverflowMenuCaptionsSubmenuTitle)));
+ IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS_SUBMENU_TITLE)));
header_item->setAttribute(html_names::kRoleAttr, "button");
header_item->setAttribute(
html_names::kAriaLabelAttr,
AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaHideClosedCaptionsMenuButton)));
+ IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_MENU_BUTTON)));
header_item->setTabIndex(0);
return header_item;
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
index e8e525be988..c1e60fcbf40 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
@@ -25,9 +25,9 @@ namespace blink {
MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(
MediaControlsImpl& media_controls,
- blink::WebLocalizedString::Name localized_label)
+ int localized_resource_id)
: MediaControlDivElement(media_controls),
- localized_label_(localized_label) {
+ localized_resource_id_(localized_resource_id) {
SetAriaLabel();
}
@@ -58,7 +58,8 @@ String MediaControlTimeDisplayElement::FormatTime() const {
}
void MediaControlTimeDisplayElement::SetAriaLabel() {
- String aria_label = GetLocale().QueryString(localized_label_, FormatTime());
+ String aria_label =
+ GetLocale().QueryString(localized_resource_id_, FormatTime());
setAttribute(html_names::kAriaLabelAttr, AtomicString(aria_label));
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h
index 2176a8601fe..661fef47960 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h
@@ -21,8 +21,7 @@ class MediaControlTimeDisplayElement : public MediaControlDivElement {
WebSize GetSizeOrDefault() const override;
protected:
- MediaControlTimeDisplayElement(MediaControlsImpl&,
- blink::WebLocalizedString::Name);
+ MediaControlTimeDisplayElement(MediaControlsImpl&, int resource_id);
virtual int EstimateElementWidth() const;
@@ -32,7 +31,7 @@ class MediaControlTimeDisplayElement : public MediaControlDivElement {
void SetAriaLabel();
double current_value_ = 0;
- blink::WebLocalizedString::Name localized_label_;
+ int localized_resource_id_;
};
} // namespace blink
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 946a9fd2ba3..ffb6a069fc8 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
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_screen_info.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
@@ -66,17 +67,16 @@ bool MediaControlTimelineElement::WillRespondToMouseClickEvents() {
void MediaControlTimelineElement::SetPosition(double current_time) {
setValue(String::Number(current_time));
String aria_label =
- GetLocale().QueryString(
- MediaElement().IsHTMLVideoElement()
- ? WebLocalizedString::kAXMediaVideoSliderHelp
- : WebLocalizedString::kAXMediaAudioSliderHelp) +
+ GetLocale().QueryString(MediaElement().IsHTMLVideoElement()
+ ? IDS_AX_MEDIA_VIDEO_SLIDER_HELP
+ : IDS_AX_MEDIA_AUDIO_SLIDER_HELP) +
" " + GetMediaControls().CurrentTimeDisplay().textContent(true) + " " +
GetMediaControls().RemainingTimeDisplay().textContent(true);
setAttribute(html_names::kAriaLabelAttr, AtomicString(aria_label));
setAttribute(html_names::kAriaValuetextAttr,
AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaCurrentTimeDisplay,
+ IDS_AX_MEDIA_CURRENT_TIME_DISPLAY,
GetMediaControls().CurrentTimeDisplay().textContent(true))));
RenderBarSegments();
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
index 8fcd4313b31..53cb32fb7a2 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
@@ -50,7 +51,7 @@ MediaControlToggleClosedCaptionsButtonElement::
: MediaControlInputElement(media_controls) {
setAttribute(html_names::kAriaLabelAttr,
WTF::AtomicString(GetLocale().QueryString(
- WebLocalizedString::kAXMediaShowClosedCaptionsMenuButton)));
+ IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_MENU_BUTTON)));
setType(input_type_names::kButton);
SetShadowPseudoId(
AtomicString("-webkit-media-controls-toggle-closed-captions-button"));
@@ -70,9 +71,8 @@ void MediaControlToggleClosedCaptionsButtonElement::UpdateDisplayType() {
MediaControlInputElement::UpdateDisplayType();
}
-WebLocalizedString::Name
-MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringName() const {
- return WebLocalizedString::kOverflowMenuCaptions;
+int MediaControlToggleClosedCaptionsButtonElement::GetOverflowStringId() const {
+ return IDS_MEDIA_OVERFLOW_MENU_CLOSED_CAPTIONS;
}
bool MediaControlToggleClosedCaptionsButtonElement::HasOverflowButton() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h
index 470b3c2724d..e9dcf0dca96 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h
@@ -21,7 +21,7 @@ class MODULES_EXPORT MediaControlToggleClosedCaptionsButtonElement final
// MediaControlInputElement overrides.
bool WillRespondToMouseClickEvents() override;
void UpdateDisplayType() override;
- WebLocalizedString::Name GetOverflowStringName() const override;
+ int GetOverflowStringId() const override;
bool HasOverflowButton() const override;
String GetOverflowMenuSubtitleString() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc
index f5c1e836784..9c3eaf1275d 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
@@ -21,7 +22,7 @@ const char kEnglishLabel[] = "English";
class LocalePlatformSupport : public TestingPlatformSupport {
public:
WebString QueryLocalizedString(int resource_id) override {
- if (resource_id == WebLocalizedString::kTextTracksOff)
+ if (resource_id == IDS_MEDIA_TRACKS_OFF)
return kTextTracksOffString;
return TestingPlatformSupport::QueryLocalizedString(resource_id);
}
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 66787e645e3..cefff9b5772 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
@@ -1464,7 +1464,7 @@ void MediaControlsImpl::DefaultEventHandler(Event& event) {
ResetHideMediaControlsTimer();
}
- if (event.IsKeyboardEvent() &&
+ if (event.IsKeyboardEvent() && !event.defaultPrevented() &&
!IsSpatialNavigationEnabled(GetDocument().GetFrame())) {
const String& key = ToKeyboardEvent(event).key();
if (key == "Enter" || ToKeyboardEvent(event).keyCode() == ' ') {
@@ -1905,6 +1905,9 @@ void MediaControlsImpl::NotifyElementSizeChanged(DOMRectReadOnly* new_size) {
}
void MediaControlsImpl::ElementSizeChangedTimerFired(TimerBase*) {
+ if (!MediaElement().isConnected())
+ return;
+
ComputeWhichControlsFit();
// Rerender timeline bar segments when size changed.
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 5134c7cfac1..eb976bb28cf 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
@@ -116,7 +116,6 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
// There is no update because only the overlay is expected to change.
RefreshCastButtonVisibilityWithoutUpdate();
}
- void ShowContextMenu() override {}
// Called by the fullscreen buttons to toggle fulllscreen on/off.
void EnterFullscreen();
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 e691c1b3b62..45a2ca0ce22 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
@@ -62,10 +62,10 @@ namespace blink {
namespace {
-class MockChromeClientForImpl : public EmptyChromeClient {
+class FakeChromeClient : public EmptyChromeClient {
public:
- // EmptyChromeClient overrides:
- WebScreenInfo GetScreenInfo() const override {
+ // ChromeClient overrides.
+ WebScreenInfo GetScreenInfo(LocalFrame&) const override {
WebScreenInfo screen_info;
screen_info.orientation_type = kWebScreenOrientationLandscapePrimary;
return screen_info;
@@ -171,7 +171,7 @@ class MediaControlsImplTest : public PageTestBase,
void InitializePage() {
Page::PageClients clients;
FillWithEmptyClients(clients);
- clients.chrome_client = MakeGarbageCollected<MockChromeClientForImpl>();
+ clients.chrome_client = MakeGarbageCollected<FakeChromeClient>();
SetupPageWithClients(&clients,
MakeGarbageCollected<StubLocalFrameClientForImpl>());
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 a3ad5315f4a..f2b7505d7b2 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
@@ -293,11 +293,12 @@ MediaControlsOrientationLockDelegate::ComputeOrientationLock() const {
// consistency. Use WebScreenOrientationLockLandscape as a fallback value.
// TODO(mlamouri): we could improve this by having direct access to
// `window.screen.orientation.type`.
- Frame* frame = GetDocument().GetFrame();
+ LocalFrame* frame = GetDocument().GetFrame();
if (!frame)
return kWebScreenOrientationLockLandscape;
- switch (frame->GetChromeClient().GetScreenInfo().orientation_type) {
+ ChromeClient& chrome_client = frame->GetChromeClient();
+ switch (chrome_client.GetScreenInfo(*frame).orientation_type) {
case kWebScreenOrientationPortraitPrimary:
case kWebScreenOrientationPortraitSecondary:
return kWebScreenOrientationLockPortrait;
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 4e5c0360f2b..42327ab4dcc 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
@@ -131,7 +131,7 @@ class MockChromeClientForOrientationLockDelegate final
WTF::Bind(DidExitFullscreen, WrapPersistent(frame.GetDocument())));
}
- MOCK_CONST_METHOD0(GetScreenInfo, WebScreenInfo());
+ MOCK_CONST_METHOD1(GetScreenInfo, WebScreenInfo(LocalFrame&));
MockScreenOrientation& ScreenOrientationClient() {
return mock_screen_orientation_;
@@ -373,7 +373,7 @@ class MediaControlsOrientationLockAndRotateToFullscreenDelegateTest
screen_info.rect, screen_info.orientation_angle));
testing::Mock::VerifyAndClearExpectations(&ChromeClient());
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(AtLeast(1))
.WillRepeatedly(Return(screen_info));
@@ -589,31 +589,31 @@ TEST_F(MediaControlsOrientationLockDelegateTest, ComputeOrientationLock) {
// 100x100 has more subtilities, it depends on the current screen orientation.
WebScreenInfo screen_info;
screen_info.orientation_type = kWebScreenOrientationUndefined;
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(1)
.WillOnce(Return(screen_info));
EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
screen_info.orientation_type = kWebScreenOrientationPortraitPrimary;
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(1)
.WillOnce(Return(screen_info));
EXPECT_EQ(kWebScreenOrientationLockPortrait, ComputeOrientationLock());
screen_info.orientation_type = kWebScreenOrientationPortraitPrimary;
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(1)
.WillOnce(Return(screen_info));
EXPECT_EQ(kWebScreenOrientationLockPortrait, ComputeOrientationLock());
screen_info.orientation_type = kWebScreenOrientationLandscapePrimary;
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(1)
.WillOnce(Return(screen_info));
EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
screen_info.orientation_type = kWebScreenOrientationLandscapeSecondary;
- EXPECT_CALL(ChromeClient(), GetScreenInfo())
+ EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
.Times(1)
.WillOnce(Return(screen_info));
EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
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 bb12a4a6de6..6188026fdb4 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
@@ -270,11 +270,11 @@ MediaControlsRotateToFullscreenDelegate::ComputeVideoOrientation() const {
MediaControlsRotateToFullscreenDelegate::SimpleOrientation
MediaControlsRotateToFullscreenDelegate::ComputeScreenOrientation() const {
- Frame* frame = video_element_->GetDocument().GetFrame();
+ LocalFrame* frame = video_element_->GetDocument().GetFrame();
if (!frame)
return SimpleOrientation::kUnknown;
- switch (frame->GetChromeClient().GetScreenInfo().orientation_type) {
+ switch (frame->GetChromeClient().GetScreenInfo(*frame).orientation_type) {
case kWebScreenOrientationPortraitPrimary:
case kWebScreenOrientationPortraitSecondary:
return SimpleOrientation::kPortrait;
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 cfe9298a224..260cd09f21c 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
@@ -34,13 +34,12 @@
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+using testing::_;
using testing::AtLeast;
using testing::Return;
namespace blink {
-using namespace html_names;
-
namespace {
class MockVideoWebMediaPlayer : public EmptyWebMediaPlayer {
@@ -72,7 +71,7 @@ class MockChromeClient : public EmptyChromeClient {
Fullscreen::DidExitFullscreen(*frame.GetDocument());
}
- MOCK_CONST_METHOD0(GetScreenInfo, WebScreenInfo());
+ MOCK_CONST_METHOD1(GetScreenInfo, WebScreenInfo(LocalFrame&));
};
class StubLocalFrameClient : public EmptyLocalFrameClient {
@@ -110,7 +109,7 @@ class MediaControlsRotateToFullscreenDelegateTest
SetupPageWithClients(&clients,
MakeGarbageCollected<StubLocalFrameClient>());
video_ = MakeGarbageCollected<HTMLVideoElement>(GetDocument());
- GetVideo().setAttribute(kControlsAttr, g_empty_atom);
+ GetVideo().setAttribute(html_names::kControlsAttr, g_empty_atom);
// Most tests should call GetDocument().body()->AppendChild(&GetVideo());
// This is not done automatically, so that tests control timing of `Attach`.
}
@@ -147,7 +146,7 @@ class MediaControlsRotateToFullscreenDelegateTest
// If scripts are not enabled, controls will always be shown.
GetFrame().GetSettings()->SetScriptEnabled(true);
- GetVideo().removeAttribute(kControlsAttr);
+ GetVideo().removeAttribute(html_names::kControlsAttr);
}
void DispatchEvent(EventTarget& target, const AtomicString& type) {
@@ -191,7 +190,7 @@ void MediaControlsRotateToFullscreenDelegateTest::InitScreenAndVideo(
// Set initial screen orientation (called by `Attach` during `AppendChild`).
WebScreenInfo screen_info;
screen_info.orientation_type = initial_screen_orientation;
- EXPECT_CALL(GetChromeClient(), GetScreenInfo())
+ EXPECT_CALL(GetChromeClient(), GetScreenInfo(_))
.Times(AtLeast(1))
.WillRepeatedly(Return(screen_info));
@@ -232,7 +231,7 @@ void MediaControlsRotateToFullscreenDelegateTest::RotateTo(
WebScreenInfo screen_info;
screen_info.orientation_type = new_screen_orientation;
testing::Mock::VerifyAndClearExpectations(&GetChromeClient());
- EXPECT_CALL(GetChromeClient(), GetScreenInfo())
+ EXPECT_CALL(GetChromeClient(), GetScreenInfo(_))
.Times(AtLeast(1))
.WillRepeatedly(Return(screen_info));
DispatchEvent(GetWindow(), event_type_names::kOrientationchange);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.cc
index 4f986eb3a1c..40978603e6c 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.h"
+#include "third_party/blink/public/strings/grit/blink_strings.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
@@ -18,8 +19,7 @@ MediaControlsTextTrackManager::MediaControlsTextTrackManager(
String MediaControlsTextTrackManager::GetTextTrackLabel(
TextTrack* track) const {
if (!track) {
- return media_element_->GetLocale().QueryString(
- WebLocalizedString::kTextTracksOff);
+ return media_element_->GetLocale().QueryString(IDS_MEDIA_TRACKS_OFF);
}
String track_label = track->label();
@@ -29,8 +29,7 @@ String MediaControlsTextTrackManager::GetTextTrackLabel(
if (track_label.IsEmpty()) {
track_label = String(media_element_->GetLocale().QueryString(
- WebLocalizedString::kTextTracksNoLabel,
- String::Number(track->TrackIndex() + 1)));
+ IDS_MEDIA_TRACKS_NO_LABEL, String::Number(track->TrackIndex() + 1)));
}
return track_label;
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 6cb8ca304cc..fdf46239953 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
@@ -1312,6 +1312,32 @@ video::-internal-media-controls-scrubbing-message {
display: none;
}
+video::-internal-media-controls-text-track-list-kind-captions {
+ -webkit-appearance: none;
+ background-image: -webkit-image-set(
+ url(ic_closed_caption.svg) 1x);
+ background-size: 32px;
+ background-repeat: no-repeat;
+ background-position: center center;
+ height: 20px;
+ width: 20px;
+ margin-left: 10px;
+ vertical-align: middle;
+}
+
+video::-internal-media-controls-text-track-list-kind-subtitles {
+ -webkit-appearance: none;
+ background-image: -webkit-image-set(
+ url(ic_subtitles.svg) 1x);
+ background-size: 32px;
+ background-repeat: no-repeat;
+ background-position: center center;
+ height: 20px;
+ width: 20px;
+ margin-left: 10px;
+ vertical-align: middle;
+}
+
/**
* VR styling.
*/
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.cc
deleted file mode 100644
index 4359bbc3167..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.cc
+++ /dev/null
@@ -1,79 +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/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.h"
-
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
-#include "third_party/blink/renderer/core/css_value_keywords.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-MediaControlsTouchlessBottomContainerElement::
- MediaControlsTouchlessBottomContainerElement(
- MediaControlsTouchlessImpl& media_controls)
- : MediaControlsTouchlessElement(media_controls) {
- SetShadowPseudoId(
- AtomicString("-internal-media-controls-touchless-bottom-container"));
-
- time_display_element_ =
- MakeGarbageCollected<MediaControlsTouchlessTimeDisplayElement>(
- media_controls);
- timeline_element_ =
- MakeGarbageCollected<MediaControlsTouchlessTimelineElement>(
- media_controls);
-
- ParserAppendChild(time_display_element_);
- ParserAppendChild(timeline_element_);
-
- event_listener_ =
- MakeGarbageCollected<MediaControlsSharedHelpers::TransitionEventListener>(
- this,
- WTF::BindRepeating(&MediaControlsTouchlessBottomContainerElement::
- HandleTransitionEndEvent,
- WrapWeakPersistent(this)));
- event_listener_->Attach();
-}
-
-LayoutObject*
-MediaControlsTouchlessBottomContainerElement::TimelineLayoutObject() {
- return timeline_element_->GetLayoutObject();
-}
-
-LayoutObject*
-MediaControlsTouchlessBottomContainerElement::TimeDisplayLayoutObject() {
- return time_display_element_->GetLayoutObject();
-}
-
-void MediaControlsTouchlessBottomContainerElement::MakeOpaque(
- bool should_hide) {
- SetDisplayed(true);
- MediaElement().MediaControlsDidBecomeVisible();
- MediaControlsTouchlessElement::MakeOpaque(should_hide);
-}
-
-void MediaControlsTouchlessBottomContainerElement::HandleTransitionEndEvent() {
- SetDisplayed(false);
-}
-
-void MediaControlsTouchlessBottomContainerElement::SetDisplayed(
- bool displayed) {
- if (displayed)
- RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
- else
- SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kNone);
-}
-
-void MediaControlsTouchlessBottomContainerElement::Trace(
- blink::Visitor* visitor) {
- visitor->Trace(timeline_element_);
- visitor->Trace(time_display_element_);
- visitor->Trace(event_listener_);
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.h
deleted file mode 100644
index e23acc51a24..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.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_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_BOTTOM_CONTAINER_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_BOTTOM_CONTAINER_ELEMENT_H_
-
-#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessImpl;
-class MediaControlsTouchlessTimelineElement;
-class MediaControlsTouchlessTimeDisplayElement;
-class LayoutObject;
-
-class MediaControlsTouchlessBottomContainerElement
- : public MediaControlsTouchlessElement {
- public:
- MediaControlsTouchlessBottomContainerElement(MediaControlsTouchlessImpl&);
- LayoutObject* TimelineLayoutObject();
- LayoutObject* TimeDisplayLayoutObject();
-
- void MakeOpaque(bool);
- void Trace(blink::Visitor*) override;
-
- private:
- void HandleTransitionEndEvent();
- void SetDisplayed(bool);
-
- Member<MediaControlsTouchlessTimelineElement> timeline_element_;
- Member<MediaControlsTouchlessTimeDisplayElement> time_display_element_;
- Member<MediaControlsSharedHelpers::TransitionEventListener> event_listener_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_BOTTOM_CONTAINER_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc
deleted file mode 100644
index 063c3038669..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc
+++ /dev/null
@@ -1,81 +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/media_controls/touchless/elements/media_controls_touchless_element.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/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h"
-
-namespace blink {
-
-namespace {
-
-// Amount of time that media controls are visible.
-constexpr base::TimeDelta kTimeToHideControl =
- base::TimeDelta::FromMilliseconds(3000);
-
-const char kTransparentCSSClass[] = "transparent";
-const char kTransparentImmediateCSSClass[] = "transparent-immediate";
-
-} // namespace
-
-MediaControlsTouchlessElement::MediaControlsTouchlessElement(
- MediaControlsTouchlessImpl& media_controls)
- : HTMLDivElement(media_controls.GetDocument()),
- media_controls_(media_controls) {
- media_controls_->MediaEventListener().AddObserver(this);
-}
-
-HTMLMediaElement& MediaControlsTouchlessElement::MediaElement() const {
- return media_controls_->MediaElement();
-}
-
-void MediaControlsTouchlessElement::MakeOpaque(bool should_hide) {
- EnsureHideControlTimer();
-
- removeAttribute("class");
-
- if (hide_control_timer_->IsActive())
- StopHideControlTimer();
-
- if (should_hide)
- StartHideControlTimer();
-}
-
-void MediaControlsTouchlessElement::MakeTransparent(bool hide_immediate) {
- classList().Add(hide_immediate ? kTransparentImmediateCSSClass
- : kTransparentCSSClass);
-}
-
-void MediaControlsTouchlessElement::EnsureHideControlTimer() {
- if (!hide_control_timer_) {
- hide_control_timer_ =
- std::make_unique<TaskRunnerTimer<MediaControlsTouchlessElement>>(
- MediaElement().GetDocument().GetTaskRunner(
- TaskType::kInternalMedia),
- this, &MediaControlsTouchlessElement::HideControlTimerFired);
- }
-}
-
-void MediaControlsTouchlessElement::HideControlTimerFired(TimerBase*) {
- MakeTransparent();
-}
-
-void MediaControlsTouchlessElement::StartHideControlTimer() {
- hide_control_timer_->StartOneShot(kTimeToHideControl, FROM_HERE);
-}
-
-void MediaControlsTouchlessElement::StopHideControlTimer() {
- hide_control_timer_->Stop();
-}
-
-void MediaControlsTouchlessElement::Trace(blink::Visitor* visitor) {
- HTMLDivElement::Trace(visitor);
- visitor->Trace(media_controls_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h
deleted file mode 100644
index f5463bbf466..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h
+++ /dev/null
@@ -1,67 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_ELEMENT_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h"
-#include "third_party/blink/renderer/platform/heap/member.h"
-#include "third_party/blink/renderer/platform/timer.h"
-
-namespace blink {
-
-class HTMLMediaElement;
-class MediaControlsTouchlessImpl;
-
-class MediaControlsTouchlessElement
- : public HTMLDivElement,
- public MediaControlsTouchlessMediaEventListenerObserver {
- USING_GARBAGE_COLLECTED_MIXIN(MediaControlsTouchlessElement);
-
- public:
- HTMLMediaElement& MediaElement() const;
-
- void Trace(blink::Visitor* visitor) override;
-
- void MakeOpaque(bool /** True if control should hide after timer fired */);
- void MakeTransparent(bool = false /** True if hide immediately */);
-
- // Non-touch media event listener observer implementation.
- void OnFocusIn() override {}
- void OnTimeUpdate() override {}
- void OnDurationChange() override {}
- void OnSeeking() override {}
- void OnLoadingProgress() override {}
- void OnPlay() override {}
- void OnPause() override {}
- void OnEnterFullscreen() override {}
- void OnExitFullscreen() override {}
- void OnError() override {}
- void OnLoadedMetadata() override {}
- void OnKeyPress(KeyboardEvent* event) override {}
- void OnKeyDown(KeyboardEvent* event) override {}
- void OnKeyUp(KeyboardEvent* event) override {}
-
- protected:
- MediaControlsTouchlessElement(MediaControlsTouchlessImpl& media_controls);
-
- private:
- void EnsureHideControlTimer();
- void HideControlTimerFired(TimerBase*);
- void StartHideControlTimer();
- void StopHideControlTimer();
-
- Member<MediaControlsTouchlessImpl> media_controls_;
-
- std::unique_ptr<TaskRunnerTimer<MediaControlsTouchlessElement>>
- hide_control_timer_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaControlsTouchlessElement);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.cc
deleted file mode 100644
index 7ae6f420ca5..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.cc
+++ /dev/null
@@ -1,61 +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/media_controls/touchless/elements/media_controls_touchless_overlay_element.h"
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-#include "third_party/blink/renderer/platform/text/platform_locale.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-MediaControlsTouchlessOverlayElement::MediaControlsTouchlessOverlayElement(
- MediaControlsTouchlessImpl& media_controls)
- : MediaControlsTouchlessElement(media_controls) {
- SetShadowPseudoId(AtomicString("-internal-media-controls-touchless-overlay"));
-
- MediaControlsTouchlessPlayButtonElement* play_button =
- MakeGarbageCollected<MediaControlsTouchlessPlayButtonElement>(
- media_controls);
-
- MediaControlsTouchlessVolumeButtonElement* volume_up_button =
- MakeGarbageCollected<MediaControlsTouchlessVolumeButtonElement>(
- media_controls, true);
- MediaControlsTouchlessVolumeButtonElement* volume_down_button =
- MakeGarbageCollected<MediaControlsTouchlessVolumeButtonElement>(
- media_controls, false);
-
- MediaControlsTouchlessSeekButtonElement* seek_forward_button =
- MakeGarbageCollected<MediaControlsTouchlessSeekButtonElement>(
- media_controls, true);
- MediaControlsTouchlessSeekButtonElement* seek_backward_button =
- MakeGarbageCollected<MediaControlsTouchlessSeekButtonElement>(
- media_controls, false);
-
- ParserAppendChild(volume_up_button);
- ParserAppendChild(seek_backward_button);
- ParserAppendChild(play_button);
- ParserAppendChild(seek_forward_button);
- ParserAppendChild(volume_down_button);
-
- StringBuilder aria_label;
- aria_label.Append(GetLocale().QueryString(
- WebLocalizedString::kAXMediaTouchLessPlayPauseAction));
- aria_label.Append(" ");
- aria_label.Append(
- GetLocale().QueryString(WebLocalizedString::kAXMediaTouchLessSeekAction));
- aria_label.Append(" ");
- aria_label.Append(GetLocale().QueryString(
- WebLocalizedString::kAXMediaTouchLessVolumeAction));
- setAttribute(html_names::kAriaLabelAttr, aria_label.ToAtomicString());
-}
-
-void MediaControlsTouchlessOverlayElement::Trace(blink::Visitor* visitor) {
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h
deleted file mode 100644
index 6c384537362..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h
+++ /dev/null
@@ -1,24 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_OVERLAY_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_OVERLAY_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessImpl;
-
-class MediaControlsTouchlessOverlayElement
- : public MediaControlsTouchlessElement {
- public:
- MediaControlsTouchlessOverlayElement(MediaControlsTouchlessImpl&);
- void Trace(blink::Visitor*) override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_OVERLAY_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.cc
deleted file mode 100644
index ed9724358c7..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h"
-
-#include "third_party/blink/renderer/core/dom/dom_token_list.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-
-namespace blink {
-
-namespace {
-
-const char kPlayingCSSClass[] = "playing";
-const char kPausedCSSClass[] = "paused";
-
-} // namespace
-
-MediaControlsTouchlessPlayButtonElement::
- MediaControlsTouchlessPlayButtonElement(
- MediaControlsTouchlessImpl& controls)
- : MediaControlsTouchlessElement(controls) {
- SetShadowPseudoId(
- AtomicString("-internal-media-controls-touchless-play-button"));
-
- controls.MediaElement().paused() ? OnPause() : OnPlay();
-}
-
-void MediaControlsTouchlessPlayButtonElement::OnPlay() {
- classList().setValue(kPlayingCSSClass);
-}
-
-void MediaControlsTouchlessPlayButtonElement::OnPause() {
- classList().setValue(kPausedCSSClass);
-}
-
-void MediaControlsTouchlessPlayButtonElement::Trace(blink::Visitor* visitor) {
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h
deleted file mode 100644
index 46eb44fdadc..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_play_button_element.h
+++ /dev/null
@@ -1,27 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_PLAY_BUTTON_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_PLAY_BUTTON_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessPlayButtonElement
- : public MediaControlsTouchlessElement {
- public:
- MediaControlsTouchlessPlayButtonElement(MediaControlsTouchlessImpl&);
-
- // MediaControlsTouchlessMediaEventListenerObserver implementation.
- void OnPlay() override;
- void OnPause() override;
-
- void Trace(blink::Visitor*) override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_PLAY_BUTTON_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.cc
deleted file mode 100644
index 4d778ebbee5..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h"
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-
-namespace blink {
-
-MediaControlsTouchlessSeekButtonElement::
- MediaControlsTouchlessSeekButtonElement(
- MediaControlsTouchlessImpl& controls,
- bool forward)
- : MediaControlsTouchlessElement(controls) {
- SetShadowPseudoId(AtomicString(
- forward ? "-internal-media-controls-touchless-seek-forward-button"
- : "-internal-media-controls-touchless-seek-backward-button"));
-}
-
-void MediaControlsTouchlessSeekButtonElement::Trace(blink::Visitor* visitor) {
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h
deleted file mode 100644
index fa0acbf3853..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_seek_button_element.h
+++ /dev/null
@@ -1,24 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_SEEK_BUTTON_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_SEEK_BUTTON_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessSeekButtonElement
- : public MediaControlsTouchlessElement {
- public:
- MediaControlsTouchlessSeekButtonElement(
- MediaControlsTouchlessImpl&,
- bool /** True if it is a seek forward button, false otherwise. */);
- void Trace(blink::Visitor*) override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_SEEK_BUTTON_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.cc
deleted file mode 100644
index 5c6db6bfa01..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h"
-
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-#include "third_party/blink/renderer/platform/text/platform_locale.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-MediaControlsTouchlessTimeDisplayElement::
- MediaControlsTouchlessTimeDisplayElement(
- MediaControlsTouchlessImpl& media_controls)
- : MediaControlsTouchlessElement(media_controls),
- current_time_(0.0),
- duration_(0.0) {
- SetShadowPseudoId(
- AtomicString("-internal-media-controls-touchless-time-display"));
- UpdateTimeDisplay();
-}
-
-void MediaControlsTouchlessTimeDisplayElement::OnTimeUpdate() {
- current_time_ = MediaElement().currentTime();
- UpdateTimeDisplay();
-}
-
-void MediaControlsTouchlessTimeDisplayElement::OnSeeking() {
- current_time_ = MediaElement().currentTime();
- UpdateTimeDisplay();
-}
-
-void MediaControlsTouchlessTimeDisplayElement::OnDurationChange() {
- duration_ = MediaElement().duration();
- UpdateTimeDisplay();
-}
-
-void MediaControlsTouchlessTimeDisplayElement::Trace(blink::Visitor* visitor) {
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-void MediaControlsTouchlessTimeDisplayElement::UpdateTimeDisplay() {
- StringBuilder builder;
- builder.Append(MediaControlsSharedHelpers::FormatTime(current_time_));
- builder.Append(" / ");
- builder.Append(MediaControlsSharedHelpers::FormatTime(duration_));
- setInnerText(builder.ToAtomicString(), ASSERT_NO_EXCEPTION);
-
- StringBuilder aria_label;
- aria_label.Append(GetLocale().QueryString(
- WebLocalizedString::kAXMediaCurrentTimeDisplay,
- MediaControlsSharedHelpers::FormatTime(current_time_)));
- aria_label.Append(" ");
- aria_label.Append(GetLocale().QueryString(
- WebLocalizedString::kAXMediaTimeRemainingDisplay,
- MediaControlsSharedHelpers::FormatTime(duration_)));
- setAttribute(html_names::kAriaLabelAttr, aria_label.ToAtomicString());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h
deleted file mode 100644
index 0134b091c4c..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_time_display_element.h
+++ /dev/null
@@ -1,35 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIME_DISPLAY_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIME_DISPLAY_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessTimeDisplayElement
- : public MediaControlsTouchlessElement {
- public:
- explicit MediaControlsTouchlessTimeDisplayElement(
- MediaControlsTouchlessImpl&);
-
- // MediaControlsTouchlessMediaEventListenerObserver overrides
- void OnTimeUpdate() override;
- void OnSeeking() override;
- void OnDurationChange() override;
-
- void Trace(blink::Visitor* visitor) override;
-
- private:
- void UpdateTimeDisplay();
-
- double current_time_;
- double duration_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIME_DISPLAY_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc
deleted file mode 100644
index 413ae227057..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc
+++ /dev/null
@@ -1,98 +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/media_controls/touchless/elements/media_controls_touchless_timeline_element.h"
-
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/html/time_ranges.h"
-#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-MediaControlsTouchlessTimelineElement::MediaControlsTouchlessTimelineElement(
- MediaControlsTouchlessImpl& media_controls)
- : MediaControlsTouchlessElement(media_controls) {
- SetShadowPseudoId(
- AtomicString("-internal-media-controls-touchless-timeline"));
-
- loaded_bar_ = MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-timeline-loaded", this);
- progress_bar_ = MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-timeline-progress", loaded_bar_);
-}
-
-void MediaControlsTouchlessTimelineElement::OnLoadingProgress() {
- UpdateBarsCSS();
-}
-
-void MediaControlsTouchlessTimelineElement::OnTimeUpdate() {
- current_time_ = MediaElement().currentTime();
- UpdateBars();
-}
-
-void MediaControlsTouchlessTimelineElement::OnSeeking() {
- current_time_ = MediaElement().currentTime();
- UpdateBars();
-}
-
-void MediaControlsTouchlessTimelineElement::OnDurationChange() {
- duration_ = MediaElement().duration();
- UpdateBars();
-}
-
-void MediaControlsTouchlessTimelineElement::UpdateBars() {
- if (std::isnan(duration_) || std::isinf(duration_) || !duration_ ||
- std::isnan(current_time_)) {
- progress_percent_ = 0;
- loaded_percent_ = 0;
- UpdateBarsCSS();
- return;
- }
-
- progress_percent_ = current_time_ / duration_;
- loaded_percent_ = progress_percent_;
-
- base::Optional<unsigned> current_buffered_time_range =
- MediaControlsSharedHelpers::GetCurrentBufferedTimeRange(MediaElement());
- if (current_buffered_time_range) {
- TimeRanges* buffered_time_ranges = MediaElement().buffered();
- float end = buffered_time_ranges->end(current_buffered_time_range.value(),
- ASSERT_NO_EXCEPTION);
- loaded_percent_ = end / duration_;
- }
-
- UpdateBarsCSS();
-}
-
-void MediaControlsTouchlessTimelineElement::UpdateBarsCSS() {
- SetBarWidth(loaded_bar_, loaded_percent_);
-
- // Since progress bar is a child of loaded bar, we need to calculate
- // the percentage accordingly.
- double adjusted_width_percent = 0;
- if (loaded_percent_ != 0)
- adjusted_width_percent = progress_percent_ / loaded_percent_;
-
- SetBarWidth(progress_bar_, adjusted_width_percent);
-}
-
-void MediaControlsTouchlessTimelineElement::SetBarWidth(HTMLDivElement* bar,
- double percent) {
- StringBuilder builder;
- builder.Append("width:");
- builder.AppendNumber(percent * 100);
- builder.Append("%");
- bar->setAttribute("style", builder.ToAtomicString());
-}
-
-void MediaControlsTouchlessTimelineElement::Trace(blink::Visitor* visitor) {
- visitor->Trace(loaded_bar_);
- visitor->Trace(progress_bar_);
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h
deleted file mode 100644
index c8a17e7ac55..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.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_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessTimelineElement
- : public MediaControlsTouchlessElement {
- public:
- explicit MediaControlsTouchlessTimelineElement(MediaControlsTouchlessImpl&);
-
- // MediaControlsTouchlessMediaEventListenerObserver overrides
- void OnTimeUpdate() override;
- void OnSeeking() override;
- void OnDurationChange() override;
- void OnLoadingProgress() override;
-
- void Trace(blink::Visitor*) override;
-
- private:
- void SetBarWidth(HTMLDivElement* bar, double percent);
-
- void UpdateBars();
- void UpdateBarsCSS();
-
- Member<HTMLDivElement> loaded_bar_;
- Member<HTMLDivElement> progress_bar_;
- double current_time_;
- double duration_;
-
- // Used for setting the width of the progress and loaded bars. This is
- // a percentage of the duration of the media.
- double progress_percent_;
- double loaded_percent_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.cc
deleted file mode 100644
index b8c660b8b57..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h"
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
-
-namespace blink {
-
-MediaControlsTouchlessVolumeButtonElement::
- MediaControlsTouchlessVolumeButtonElement(
- MediaControlsTouchlessImpl& controls,
- bool up)
- : MediaControlsTouchlessElement(controls) {
- SetShadowPseudoId(AtomicString(
- up ? "-internal-media-controls-touchless-volume-up-button"
- : "-internal-media-controls-touchless-volume-down-button"));
-}
-
-void MediaControlsTouchlessVolumeButtonElement::Trace(blink::Visitor* visitor) {
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h
deleted file mode 100644
index ad7ae783e4a..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_button_element.h
+++ /dev/null
@@ -1,24 +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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_BUTTON_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_BUTTON_ELEMENT_H_
-
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessVolumeButtonElement
- : public MediaControlsTouchlessElement {
- public:
- MediaControlsTouchlessVolumeButtonElement(
- MediaControlsTouchlessImpl&,
- bool /** True if it is a volume up button, false otherwise. */);
- void Trace(blink::Visitor*) override;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_BUTTON_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.cc
deleted file mode 100644
index 9e38e007d85..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h"
-
-#include "third_party/blink/renderer/core/dom/dom_token_list.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-namespace {
-
-const char kMutedCSSClass[] = "muted";
-
-} // namespace
-
-MediaControlsTouchlessVolumeContainerElement::
- MediaControlsTouchlessVolumeContainerElement(
- MediaControlsTouchlessImpl& media_controls)
- : MediaControlsTouchlessElement(media_controls) {
- SetShadowPseudoId(
- AtomicString("-internal-media-controls-touchless-volume-container"));
-
- Element* volume_bar_background = MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-volume-bar-background", this);
- volume_bar_ = MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-volume-bar", volume_bar_background);
- volume_icon_ = MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-volume-icon", this);
-}
-
-void MediaControlsTouchlessVolumeContainerElement::UpdateVolume() {
- volume_ = MediaElement().volume();
- UpdateCSSClass();
- UpdateVolumeBarCSS();
-}
-
-void MediaControlsTouchlessVolumeContainerElement::UpdateCSSClass() {
- if (volume_ > 0)
- volume_icon_->classList().Remove(kMutedCSSClass);
- else
- volume_icon_->classList().Add(kMutedCSSClass);
-}
-
-void MediaControlsTouchlessVolumeContainerElement::UpdateVolumeBarCSS() {
- StringBuilder builder;
- builder.Append("height:");
- builder.AppendNumber(volume_ * 100);
- builder.Append("%");
- volume_bar_->setAttribute("style", builder.ToAtomicString());
-}
-
-void MediaControlsTouchlessVolumeContainerElement::Trace(
- blink::Visitor* visitor) {
- visitor->Trace(volume_bar_);
- visitor->Trace(volume_icon_);
- MediaControlsTouchlessElement::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h
deleted file mode 100644
index 2b704c0ea76..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h
+++ /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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_CONTAINER_ELEMENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_CONTAINER_ELEMENT_H_
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h"
-
-namespace blink {
-
-class MediaControlsTouchlessVolumeContainerElement
- : public MediaControlsTouchlessElement {
- public:
- explicit MediaControlsTouchlessVolumeContainerElement(
- MediaControlsTouchlessImpl&);
- void UpdateVolume();
-
- void Trace(blink::Visitor*) override;
-
- private:
- void UpdateCSSClass();
- void UpdateVolumeBarCSS();
-
- Member<HTMLDivElement> volume_bar_;
- Member<HTMLDivElement> volume_icon_;
- double volume_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_VOLUME_CONTAINER_ELEMENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc
deleted file mode 100644
index 7adcbc6709e..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc
+++ /dev/null
@@ -1,541 +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/media_controls/touchless/media_controls_touchless_impl.h"
-
-#include <algorithm>
-
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/platform/web_screen_info.h"
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
-#include "third_party/blink/renderer/core/css_value_keywords.h"
-#include "third_party/blink/renderer/core/dom/dom_token_list.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/events/keyboard_event.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/fullscreen/fullscreen.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/html/media/html_video_element.h"
-#include "third_party/blink/renderer/core/html/track/text_track.h"
-#include "third_party/blink/renderer/core/html/track/text_track_list.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
-#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.h"
-#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h"
-#include "third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_bottom_container_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_volume_container_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-namespace {
-
-// When specified as trackIndex, disable text tracks.
-constexpr int kTrackIndexOffValue = -1;
-
-// Number of seconds to jump when press left/right arrow.
-constexpr int kNumberOfSecondsToJumpForTouchless = 10;
-
-// Amount of volume to change when press up/down arrow.
-constexpr double kVolumeToChangeForTouchless = 0.05;
-
-const char kInlineCSSClass[] = "inline";
-
-const char kNoSourceCSSClass[] = "state-no-source";
-
-const char kUseDefaultPosterCSSClass[] = "use-default-poster";
-
-} // namespace
-
-enum class MediaControlsTouchlessImpl::ArrowDirection {
- kUp,
- kDown,
- kLeft,
- kRight,
-};
-
-enum class MediaControlsTouchlessImpl::ControlsState {
- kNoSource,
- kPreReady,
- kReady,
-};
-
-MediaControlsTouchlessImpl::MediaControlsTouchlessImpl(
- HTMLMediaElement& media_element)
- : HTMLDivElement(media_element.GetDocument()),
- MediaControls(media_element),
- overlay_(nullptr),
- bottom_container_(nullptr),
- media_event_listener_(
- MakeGarbageCollected<MediaControlsTouchlessMediaEventListener>(
- media_element)),
- text_track_manager_(
- MakeGarbageCollected<MediaControlsTextTrackManager>(media_element)),
- orientation_lock_delegate_(nullptr) {
- SetShadowPseudoId(AtomicString("-webkit-media-controls-touchless"));
- media_event_listener_->AddObserver(this);
-}
-
-MediaControlsTouchlessImpl* MediaControlsTouchlessImpl::Create(
- HTMLMediaElement& media_element,
- ShadowRoot& shadow_root) {
- MediaControlsTouchlessImpl* controls =
- MakeGarbageCollected<MediaControlsTouchlessImpl>(media_element);
- controls->bottom_container_ =
- MakeGarbageCollected<MediaControlsTouchlessBottomContainerElement>(
- *controls);
- controls->overlay_ =
- MakeGarbageCollected<MediaControlsTouchlessOverlayElement>(*controls);
- controls->volume_container_ =
- MakeGarbageCollected<MediaControlsTouchlessVolumeContainerElement>(
- *controls);
-
- MediaControlElementsHelper::CreateDiv(
- "-internal-media-controls-touchless-info", controls);
-
- controls->ParserAppendChild(controls->bottom_container_);
- controls->ParserAppendChild(controls->overlay_);
- controls->ParserAppendChild(controls->volume_container_);
-
- // Controls start hidden.
- if (!media_element.paused())
- controls->bottom_container_->MakeTransparent();
- controls->overlay_->MakeTransparent();
- controls->volume_container_->MakeTransparent();
-
- if (RuntimeEnabledFeatures::VideoFullscreenOrientationLockEnabled() &&
- media_element.IsHTMLVideoElement()) {
- // Initialize the orientation lock when going fullscreen feature.
- controls->orientation_lock_delegate_ =
- MakeGarbageCollected<MediaControlsOrientationLockDelegate>(
- ToHTMLVideoElement(media_element));
- }
-
- MediaControlsTouchlessResourceLoader::
- InjectMediaControlsTouchlessUAStyleSheet();
-
- if (!media_element.IsFullscreen())
- controls->classList().Add(kInlineCSSClass);
-
- controls->UpdateCSSFromState();
-
- shadow_root.ParserAppendChild(controls);
- return controls;
-}
-
-Node::InsertionNotificationRequest MediaControlsTouchlessImpl::InsertedInto(
- ContainerNode& root) {
- media_event_listener_->Attach();
-
- if (orientation_lock_delegate_)
- orientation_lock_delegate_->Attach();
-
- return HTMLDivElement::InsertedInto(root);
-}
-
-void MediaControlsTouchlessImpl::RemovedFrom(ContainerNode& insertion_point) {
- HTMLDivElement::RemovedFrom(insertion_point);
-
- Hide();
-
- media_event_listener_->Detach();
-
- if (orientation_lock_delegate_)
- orientation_lock_delegate_->Detach();
-}
-
-void MediaControlsTouchlessImpl::MaybeShow() {
- RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
-}
-
-void MediaControlsTouchlessImpl::Hide() {
- SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kNone);
-}
-
-void MediaControlsTouchlessImpl::NetworkStateChanged() {
- UpdateCSSFromState();
-}
-
-LayoutObject* MediaControlsTouchlessImpl::PanelLayoutObject() {
- return nullptr;
-}
-
-LayoutObject* MediaControlsTouchlessImpl::TimelineLayoutObject() {
- return bottom_container_->TimelineLayoutObject();
-}
-
-LayoutObject* MediaControlsTouchlessImpl::ButtonPanelLayoutObject() {
- return bottom_container_->TimeDisplayLayoutObject();
-}
-
-LayoutObject* MediaControlsTouchlessImpl::ContainerLayoutObject() {
- return GetLayoutObject();
-}
-
-MediaControlsTouchlessMediaEventListener&
-MediaControlsTouchlessImpl::MediaEventListener() const {
- return *media_event_listener_;
-}
-
-void MediaControlsTouchlessImpl::OnFocusIn() {
- if (MediaElement().ShouldShowControls()) {
- bottom_container_->MakeOpaque(!MediaElement().paused());
- overlay_->MakeOpaque(true);
- }
-}
-
-void MediaControlsTouchlessImpl::OnPlay() {
- bottom_container_->MakeOpaque(true);
-}
-
-void MediaControlsTouchlessImpl::OnPause() {
- bottom_container_->MakeOpaque(false);
-}
-
-void MediaControlsTouchlessImpl::OnEnterFullscreen() {
- classList().Remove(kInlineCSSClass);
-}
-
-void MediaControlsTouchlessImpl::OnExitFullscreen() {
- classList().Add(kInlineCSSClass);
-}
-
-void MediaControlsTouchlessImpl::OnKeyDown(KeyboardEvent* event) {
- if (!MediaElement().ShouldShowControls())
- return;
-
- bool handled = true;
- switch (event->keyCode()) {
- case VKEY_RETURN:
- volume_container_->MakeTransparent(true);
- overlay_->MakeOpaque(true);
- MediaElement().TogglePlayState();
- break;
- case VKEY_LEFT:
- HandleOrientedArrowPress(OrientArrowPress(ArrowDirection::kLeft));
- break;
- case VKEY_RIGHT:
- HandleOrientedArrowPress(OrientArrowPress(ArrowDirection::kRight));
- break;
- case VKEY_UP:
- HandleOrientedArrowPress(OrientArrowPress(ArrowDirection::kUp));
- break;
- case VKEY_DOWN:
- HandleOrientedArrowPress(OrientArrowPress(ArrowDirection::kDown));
- break;
- default:
- handled = false;
- break;
- }
-
- if (handled)
- event->SetDefaultHandled();
-}
-
-void MediaControlsTouchlessImpl::EnsureMediaControlsMenuHost() {
- if (!media_controls_host_) {
- GetDocument().GetFrame()->GetInterfaceProvider().GetInterface(
- media_controls_host_.BindNewPipeAndPassReceiver(
- GetExecutionContext()->GetTaskRunner(
- blink::TaskType::kMediaElementEvent)));
- media_controls_host_.set_disconnect_handler(WTF::Bind(
- &MediaControlsTouchlessImpl::OnMediaControlsMenuHostConnectionError,
- WrapWeakPersistent(this)));
- }
-}
-
-mojom::blink::VideoStatePtr MediaControlsTouchlessImpl::GetVideoState() {
- mojom::blink::VideoStatePtr video_state = mojom::blink::VideoState::New();
- video_state->is_muted = MediaElement().muted();
- video_state->is_fullscreen = MediaElement().IsFullscreen();
- return video_state;
-}
-
-WTF::Vector<mojom::blink::TextTrackMetadataPtr>
-MediaControlsTouchlessImpl::GetTextTracks() {
- WTF::Vector<mojom::blink::TextTrackMetadataPtr> text_tracks;
- TextTrackList* track_list = MediaElement().textTracks();
- for (unsigned i = 0; i < track_list->length(); i++) {
- TextTrack* track = track_list->AnonymousIndexedGetter(i);
- if (!track->CanBeRendered())
- continue;
-
- mojom::blink::TextTrackMetadataPtr text_track(
- mojom::blink::TextTrackMetadata::New());
- text_track->track_index = track->TrackIndex();
- text_track->label = text_track_manager_->GetTextTrackLabel(track);
- text_tracks.push_back(std::move(text_track));
- }
-
- if (!text_tracks.IsEmpty()) {
- mojom::blink::TextTrackMetadataPtr text_track(
- mojom::blink::TextTrackMetadata::New());
- text_track->track_index = kTrackIndexOffValue;
- text_track->label = text_track_manager_->GetTextTrackLabel(nullptr);
- text_tracks.push_front(std::move(text_track));
- }
-
- return text_tracks;
-}
-
-void MediaControlsTouchlessImpl::ShowContextMenu() {
- EnsureMediaControlsMenuHost();
-
- mojom::blink::VideoStatePtr video_state = GetVideoState();
- WTF::Vector<mojom::blink::TextTrackMetadataPtr> text_tracks = GetTextTracks();
-
- WTF::Vector<mojom::blink::MenuItem> menu_items;
-
- if (MediaControlsSharedHelpers::ShouldShowFullscreenButton(MediaElement()))
- menu_items.push_back(mojom::blink::MenuItem::FULLSCREEN);
-
- if (MediaElement().HasAudio())
- menu_items.push_back(mojom::blink::MenuItem::MUTE);
-
- if (MediaElement().SupportsSave())
- menu_items.push_back(mojom::blink::MenuItem::DOWNLOAD);
-
- if (!text_tracks.IsEmpty())
- menu_items.push_back(mojom::blink::MenuItem::CAPTIONS);
-
- media_controls_host_->ShowMediaMenu(
- std::move(menu_items), std::move(video_state), std::move(text_tracks),
- WTF::Bind(&MediaControlsTouchlessImpl::OnMediaMenuResult,
- WrapWeakPersistent(this)));
-}
-
-void MediaControlsTouchlessImpl::OnMediaMenuResult(
- mojom::blink::MenuResponsePtr response) {
- if (response.is_null())
- return;
-
- switch (response->clicked) {
- case mojom::blink::MenuItem::FULLSCREEN:
- if (MediaElement().IsFullscreen())
- Fullscreen::ExitFullscreen(GetDocument());
- else
- Fullscreen::RequestFullscreen(MediaElement());
- break;
- case mojom::blink::MenuItem::MUTE:
- MediaElement().setMuted(!MediaElement().muted());
- break;
- case mojom::blink::MenuItem::DOWNLOAD:
- Download();
- break;
- case mojom::blink::MenuItem::CAPTIONS:
- text_track_manager_->DisableShowingTextTracks();
- if (response->track_index >= 0)
- text_track_manager_->ShowTextTrackAtIndex(response->track_index);
- break;
- }
-}
-
-void MediaControlsTouchlessImpl::Download() {
- const KURL& url = MediaElement().currentSrc();
- if (url.IsNull() || url.IsEmpty())
- return;
- ResourceRequest request(url);
- request.SetSuggestedFilename(MediaElement().title());
- request.SetRequestContext(mojom::RequestContextType::DOWNLOAD);
- request.SetRequestorOrigin(SecurityOrigin::Create(GetDocument().Url()));
- GetDocument().GetFrame()->Client()->DownloadURL(
- request, DownloadCrossOriginRedirects::kFollow);
-}
-
-void MediaControlsTouchlessImpl::OnMediaControlsMenuHostConnectionError() {
- media_controls_host_.reset();
-}
-
-MediaControlsTouchlessImpl::ArrowDirection
-MediaControlsTouchlessImpl::OrientArrowPress(ArrowDirection direction) {
- switch (GetOrientation()) {
- case kWebScreenOrientationUndefined:
- case kWebScreenOrientationPortraitPrimary:
- return direction;
- case kWebScreenOrientationPortraitSecondary:
- switch (direction) {
- case ArrowDirection::kUp:
- return ArrowDirection::kDown;
- case ArrowDirection::kDown:
- return ArrowDirection::kUp;
- case ArrowDirection::kLeft:
- return ArrowDirection::kRight;
- case ArrowDirection::kRight:
- return ArrowDirection::kLeft;
- }
- case kWebScreenOrientationLandscapePrimary:
- switch (direction) {
- case ArrowDirection::kUp:
- return ArrowDirection::kLeft;
- case ArrowDirection::kDown:
- return ArrowDirection::kRight;
- case ArrowDirection::kLeft:
- return ArrowDirection::kDown;
- case ArrowDirection::kRight:
- return ArrowDirection::kUp;
- }
- case kWebScreenOrientationLandscapeSecondary:
- switch (direction) {
- case ArrowDirection::kUp:
- return ArrowDirection::kRight;
- case ArrowDirection::kDown:
- return ArrowDirection::kLeft;
- case ArrowDirection::kLeft:
- return ArrowDirection::kUp;
- case ArrowDirection::kRight:
- return ArrowDirection::kDown;
- }
- }
-}
-
-void MediaControlsTouchlessImpl::HandleOrientedArrowPress(
- ArrowDirection direction) {
- switch (direction) {
- case ArrowDirection::kUp:
- HandleTopButtonPress();
- break;
- case ArrowDirection::kDown:
- HandleBottomButtonPress();
- break;
- case ArrowDirection::kLeft:
- HandleLeftButtonPress();
- break;
- case ArrowDirection::kRight:
- HandleRightButtonPress();
- break;
- }
-}
-
-WebScreenOrientationType MediaControlsTouchlessImpl::GetOrientation() {
- LocalFrame* frame = GetDocument().GetFrame();
- if (!frame)
- return kWebScreenOrientationUndefined;
-
- return frame->GetChromeClient().GetScreenInfo().orientation_type;
-}
-
-void MediaControlsTouchlessImpl::HandleTopButtonPress() {
- MaybeChangeVolume(kVolumeToChangeForTouchless);
- volume_container_->UpdateVolume();
- overlay_->MakeTransparent(true);
- volume_container_->MakeOpaque(true);
-}
-
-void MediaControlsTouchlessImpl::HandleBottomButtonPress() {
- MaybeChangeVolume(kVolumeToChangeForTouchless * -1);
- volume_container_->UpdateVolume();
- overlay_->MakeTransparent(true);
- volume_container_->MakeOpaque(true);
-}
-
-void MediaControlsTouchlessImpl::HandleLeftButtonPress() {
- if (!MediaElement().paused())
- bottom_container_->MakeOpaque(true);
- MaybeJump(kNumberOfSecondsToJumpForTouchless * -1);
-}
-
-void MediaControlsTouchlessImpl::HandleRightButtonPress() {
- if (!MediaElement().paused())
- bottom_container_->MakeOpaque(true);
- MaybeJump(kNumberOfSecondsToJumpForTouchless);
-}
-
-void MediaControlsTouchlessImpl::MaybeChangeVolume(double volume_to_change) {
- double new_volume = std::max(0.0, MediaElement().volume() + volume_to_change);
- new_volume = std::min(new_volume, 1.0);
- MediaElement().setVolume(new_volume);
-}
-
-void MediaControlsTouchlessImpl::MaybeJump(int seconds) {
- double new_time = std::max(0.0, MediaElement().currentTime() + seconds);
- new_time = std::min(new_time, MediaElement().duration());
- MediaElement().setCurrentTime(new_time);
-}
-
-MediaControlsTouchlessImpl::ControlsState MediaControlsTouchlessImpl::State() {
- HTMLMediaElement::NetworkState network_state =
- MediaElement().getNetworkState();
- HTMLMediaElement::ReadyState ready_state = MediaElement().getReadyState();
-
- switch (network_state) {
- case HTMLMediaElement::kNetworkEmpty:
- case HTMLMediaElement::kNetworkNoSource:
- return ControlsState::kNoSource;
- case HTMLMediaElement::kNetworkLoading:
- if (ready_state == HTMLMediaElement::kHaveNothing)
- return ControlsState::kPreReady;
- else
- return ControlsState::kReady;
- case HTMLMediaElement::kNetworkIdle:
- if (ready_state == HTMLMediaElement::kHaveNothing)
- return ControlsState::kPreReady;
- break;
- }
-
- return ControlsState::kReady;
-}
-
-void MediaControlsTouchlessImpl::UpdateCSSFromState() {
- ControlsState state = State();
-
- if (state == ControlsState::kNoSource)
- classList().Add(kNoSourceCSSClass);
- else
- classList().Remove(kNoSourceCSSClass);
-
- if (!MediaElement().IsHTMLVideoElement())
- return;
-
- if (MediaElement().ShouldShowControls() &&
- !VideoElement().HasAvailableVideoFrame() &&
- VideoElement().PosterImageURL().IsEmpty() &&
- state <= ControlsState::kPreReady) {
- classList().Add(kUseDefaultPosterCSSClass);
- } else {
- classList().Remove(kUseDefaultPosterCSSClass);
- }
-}
-
-HTMLVideoElement& MediaControlsTouchlessImpl::VideoElement() {
- DCHECK(MediaElement().IsHTMLVideoElement());
- return *ToHTMLVideoElement(&MediaElement());
-}
-
-void MediaControlsTouchlessImpl::OnError() {
- UpdateCSSFromState();
-}
-
-void MediaControlsTouchlessImpl::OnLoadedMetadata() {
- UpdateCSSFromState();
-}
-
-void MediaControlsTouchlessImpl::Trace(blink::Visitor* visitor) {
- visitor->Trace(bottom_container_);
- visitor->Trace(overlay_);
- visitor->Trace(media_event_listener_);
- visitor->Trace(text_track_manager_);
- visitor->Trace(orientation_lock_delegate_);
- visitor->Trace(volume_container_);
- MediaControls::Trace(visitor);
- HTMLDivElement::Trace(visitor);
-}
-
-void MediaControlsTouchlessImpl::SetMediaControlsMenuHostForTesting(
- mojo::PendingRemote<mojom::blink::MediaControlsMenuHost> menu_host) {
- media_controls_host_.Bind(std::move(menu_host));
-}
-
-void MediaControlsTouchlessImpl::MenuHostFlushForTesting() {
- media_controls_host_.FlushForTesting();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h
deleted file mode 100644
index 21d32a91007..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h
+++ /dev/null
@@ -1,130 +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_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_IMPL_H_
-
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h"
-#include "third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom-blink.h"
-#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/core/html/media/media_controls.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class MediaControlsOrientationLockDelegate;
-class MediaControlsTouchlessBottomContainerElement;
-class MediaControlsTouchlessOverlayElement;
-class MediaControlsTouchlessMediaEventListener;
-class MediaControlsTouchlessVolumeContainerElement;
-class MediaControlsTextTrackManager;
-
-class MODULES_EXPORT MediaControlsTouchlessImpl final
- : public HTMLDivElement,
- public MediaControls,
- public MediaControlsTouchlessMediaEventListenerObserver {
- USING_GARBAGE_COLLECTED_MIXIN(MediaControlsTouchlessImpl);
-
- public:
- static MediaControlsTouchlessImpl* Create(HTMLMediaElement&, ShadowRoot&);
-
- explicit MediaControlsTouchlessImpl(HTMLMediaElement&);
-
- // Node override.
- Node::InsertionNotificationRequest InsertedInto(ContainerNode&) override;
- void RemovedFrom(ContainerNode&) override;
-
- // MediaControls implementation.
- void MaybeShow() override;
- void Hide() override;
- void Reset() override {}
- void OnControlsListUpdated() override {}
- void OnTrackElementFailedToLoad() override {}
- void NetworkStateChanged() override;
- LayoutObject* PanelLayoutObject() override;
- LayoutObject* TimelineLayoutObject() override;
- LayoutObject* ButtonPanelLayoutObject() override;
- LayoutObject* ContainerLayoutObject() override;
- void ShowContextMenu() override;
- void SetTestMode(bool) override {}
- HTMLDivElement* PanelElement() override { return nullptr; }
- void OnMediaControlsEnabledChange() override {}
-
- // MediaControlsTouchlessMediaEventListenerObserver implementation.
- void OnFocusIn() override;
- void OnTimeUpdate() override {}
- void OnDurationChange() override {}
- void OnSeeking() override {}
- void OnLoadingProgress() override {}
- void OnPlay() override;
- void OnPause() override;
- void OnEnterFullscreen() override;
- void OnExitFullscreen() override;
- void OnError() override;
- void OnLoadedMetadata() override;
- void OnKeyPress(KeyboardEvent* event) override {}
- void OnKeyDown(KeyboardEvent* event) override;
- void OnKeyUp(KeyboardEvent* event) override {}
-
- MediaControlsTouchlessMediaEventListener& MediaEventListener() const;
-
- // Test functions
- void SetMediaControlsMenuHostForTesting(
- mojo::PendingRemote<mojom::blink::MediaControlsMenuHost>);
- void MenuHostFlushForTesting();
-
- void Trace(blink::Visitor*) override;
-
- private:
- friend class MediaControlsTouchlessImplTest;
-
- enum class ArrowDirection;
- enum class ControlsState;
- ArrowDirection OrientArrowPress(ArrowDirection direction);
- void HandleOrientedArrowPress(ArrowDirection direction);
-
- WebScreenOrientationType GetOrientation();
-
- ControlsState State();
- void UpdateCSSFromState();
-
- void HandleTopButtonPress();
- void HandleBottomButtonPress();
- void HandleLeftButtonPress();
- void HandleRightButtonPress();
-
- void MaybeJump(int);
- void MaybeChangeVolume(double);
-
- void Download();
-
- HTMLVideoElement& VideoElement();
-
- // Node
- bool IsMediaControls() const override { return true; }
-
- void EnsureMediaControlsMenuHost();
- mojom::blink::VideoStatePtr GetVideoState();
- WTF::Vector<mojom::blink::TextTrackMetadataPtr> GetTextTracks();
- void OnMediaMenuResult(mojom::blink::MenuResponsePtr);
- void OnMediaControlsMenuHostConnectionError();
-
- Member<MediaControlsTouchlessOverlayElement> overlay_;
- Member<MediaControlsTouchlessBottomContainerElement> bottom_container_;
- Member<MediaControlsTouchlessVolumeContainerElement> volume_container_;
-
- Member<MediaControlsTouchlessMediaEventListener> media_event_listener_;
- Member<MediaControlsTextTrackManager> text_track_manager_;
- Member<MediaControlsOrientationLockDelegate> orientation_lock_delegate_;
-
- mojo::Remote<mojom::blink::MediaControlsMenuHost> media_controls_host_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaControlsTouchlessImpl);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc
deleted file mode 100644
index b18531c663f..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc
+++ /dev/null
@@ -1,637 +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/media_controls/touchless/media_controls_touchless_impl.h"
-
-#include <memory>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom-blink.h"
-#include "third_party/blink/renderer/core/css/css_property_value_set.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/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/events/keyboard_event.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
-#include "third_party/blink/renderer/core/geometry/dom_rect.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element_controls_list.h"
-#include "third_party/blink/renderer/core/html/media/html_media_test_helper.h"
-#include "third_party/blink/renderer/core/html/media/html_video_element.h"
-#include "third_party/blink/renderer/core/html/time_ranges.h"
-#include "third_party/blink/renderer/core/html/track/text_track.h"
-#include "third_party/blink/renderer/core/html/track/text_track_list.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/loader/empty_clients.h"
-#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
-#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-namespace blink {
-
-namespace {
-
-const char kTextTracksOffString[] = "Off";
-
-class LocalePlatformSupport : public TestingPlatformSupport {
- public:
- WebString QueryLocalizedString(int resource_id) override {
- if (resource_id == WebLocalizedString::kTextTracksOff)
- return kTextTracksOffString;
- return TestingPlatformSupport::QueryLocalizedString(resource_id);
- }
-};
-
-class MockWebMediaPlayerForTouchlessImpl : public EmptyWebMediaPlayer {
- public:
- WebTimeRanges Seekable() const override { return seekable_; }
- bool HasVideo() const override { return true; }
- bool HasAudio() const override { return has_audio_; }
- WebTimeRanges Buffered() const override { return buffered_; }
-
- WebTimeRanges buffered_;
- WebTimeRanges seekable_;
- bool has_audio_ = false;
-};
-
-} // namespace
-
-class MockChromeClientForTouchlessImpl : public EmptyChromeClient {
- public:
- explicit MockChromeClientForTouchlessImpl()
- : orientation_(kWebScreenOrientationPortraitPrimary) {}
-
- WebScreenInfo GetScreenInfo() const override {
- WebScreenInfo screen_info;
- screen_info.orientation_type = orientation_;
- return screen_info;
- }
-
- void EnterFullscreen(LocalFrame& frame, const FullscreenOptions*) final {
- Fullscreen::DidEnterFullscreen(*frame.GetDocument());
- }
-
- void ExitFullscreen(LocalFrame& frame) final {
- Fullscreen::DidExitFullscreen(*frame.GetDocument());
- }
-
- void SetOrientation(WebScreenOrientationType orientation_type) {
- orientation_ = orientation_type;
- }
-
- private:
- WebScreenOrientationType orientation_;
-};
-
-class MediaControlsTouchlessImplTest : public PageTestBase {
- protected:
- void SetUp() override { InitializePage(); }
-
- void InitializePage() {
- Page::PageClients clients;
-
- FillWithEmptyClients(clients);
- chrome_client_ = MakeGarbageCollected<MockChromeClientForTouchlessImpl>();
- clients.chrome_client = chrome_client_;
- SetupPageWithClients(
- &clients, MakeGarbageCollected<test::MediaStubLocalFrameClient>(
- std::make_unique<MockWebMediaPlayerForTouchlessImpl>()));
-
- GetDocument().write("<video controls>");
- HTMLMediaElement& video =
- ToHTMLVideoElement(*GetDocument().QuerySelector("video"));
- media_controls_ =
- static_cast<MediaControlsTouchlessImpl*>(video.GetMediaControls());
-
- test_media_controls_host_ = std::make_unique<TestMediaControlsMenuHost>();
-
- media_controls_->SetMediaControlsMenuHostForTesting(
- test_media_controls_host_->CreateMediaControlsMenuHostRemote());
-
- // Scripts are disabled by default which forces controls to be on.
- GetFrame().GetSettings()->SetScriptEnabled(true);
- }
-
- MediaControlsTouchlessImpl& MediaControls() { return *media_controls_; }
- HTMLMediaElement& MediaElement() { return MediaControls().MediaElement(); }
-
- MockWebMediaPlayerForTouchlessImpl* WebMediaPlayer() {
- return static_cast<MockWebMediaPlayerForTouchlessImpl*>(
- MediaElement().GetWebMediaPlayer());
- }
-
- TestMenuHostArgList& GetMenuHostArgList() {
- return test_media_controls_host_->GetMenuHostArgList();
- }
-
- void SetNetworkState(HTMLMediaElement::NetworkState state) {
- MediaElement().SetNetworkState(state);
- }
-
- void SetReadyState(HTMLMediaElement::ReadyState state) {
- MediaElement().SetReadyState(state);
- }
-
- void SimulateKeydownEvent(Element& element, int key_code) {
- KeyboardEventInit* keyboard_event_init = KeyboardEventInit::Create();
- keyboard_event_init->setKeyCode(key_code);
-
- Event* keyboard_event =
- MakeGarbageCollected<KeyboardEvent>("keydown", keyboard_event_init);
- element.DispatchEvent(*keyboard_event);
- }
-
- void LoadMediaWithDuration(double duration) {
- MediaElement().SetSrc("https://example.com/foo.mp4");
- test::RunPendingTasks();
- WebTimeRange time_range(0.0, duration);
- WebMediaPlayer()->seekable_.Assign(&time_range, 1);
- MediaElement().DurationChanged(duration, false /* requestSeek */);
- }
-
- void SetBufferedRange(double end) {
- WebTimeRange time_range(0.0, end);
- WebMediaPlayer()->buffered_.Assign(&time_range, 1);
- }
-
- bool IsControlsVisible(Element* element) {
- return !element->classList().contains("transparent") &&
- !element->classList().contains("transparent-immediate");
- }
-
- bool IsElementDisplayed(Element* element) {
- if (!element->InlineStyle())
- return true;
-
- return element->InlineStyle()->GetPropertyValue(CSSPropertyID::kDisplay) !=
- "none";
- }
-
- void SetHasAudio(bool has_audio) { WebMediaPlayer()->has_audio_ = has_audio; }
-
- Element* GetControlByShadowPseudoId(const char* shadow_pseudo_id) {
- for (Element& element : ElementTraversal::DescendantsOf(MediaControls())) {
- if (element.ShadowPseudoId() == shadow_pseudo_id)
- return &element;
- }
- return nullptr;
- }
-
- void SetScreenOrientation(WebScreenOrientationType orientation_type) {
- chrome_client_->SetOrientation(orientation_type);
- }
-
- void SetMenuResponse(mojom::blink::MenuItem menu_item, int track_index = -1) {
- test_media_controls_host_->SetMenuResponse(menu_item, track_index);
- }
-
- void SetMenuResponseAndShowMenu(mojom::blink::MenuItem menu_item,
- int track_index = -1) {
- SetMenuResponse(menu_item, track_index);
- MediaControls().ShowContextMenu();
- MediaControls().MenuHostFlushForTesting();
- }
-
- void CheckControlKeys(int seek_forward_key,
- int seek_backward_key,
- int volume_up_key,
- int volume_down_key) {
- const int kNumberOfSecondsToJump = 10;
- const double kVolumeToChange = 0.05;
- const int initTime = 10;
- const double initVolume = 0.5;
- MediaElement().setCurrentTime(initTime);
- MediaElement().setVolume(initVolume);
-
- SimulateKeydownEvent(MediaElement(), seek_forward_key);
- ASSERT_EQ(MediaElement().currentTime(), initTime + kNumberOfSecondsToJump);
-
- SimulateKeydownEvent(MediaElement(), seek_backward_key);
- ASSERT_EQ(MediaElement().currentTime(), initTime);
-
- SimulateKeydownEvent(MediaElement(), volume_up_key);
- ASSERT_EQ(MediaElement().volume(), initVolume + kVolumeToChange);
-
- SimulateKeydownEvent(MediaElement(), volume_down_key);
- ASSERT_EQ(MediaElement().volume(), initVolume);
- }
-
- private:
- Persistent<MediaControlsTouchlessImpl> media_controls_;
- Persistent<MockChromeClientForTouchlessImpl> chrome_client_;
- std::unique_ptr<TestMediaControlsMenuHost> test_media_controls_host_;
-};
-
-class MediaControlsTouchlessImplTestWithMockScheduler
- : public MediaControlsTouchlessImplTest {
- public:
- MediaControlsTouchlessImplTestWithMockScheduler() { EnablePlatform(); }
-
- protected:
- void SetUp() override {
- platform()->AdvanceClockSeconds(1);
- MediaControlsTouchlessImplTest::SetUp();
- }
-};
-
-TEST_F(MediaControlsTouchlessImplTest, PlayPause) {
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
- MediaElement().Play();
- ASSERT_FALSE(MediaElement().paused());
-
- // Press center key and video should be paused.
- SimulateKeydownEvent(MediaElement(), VKEY_RETURN);
- ASSERT_TRUE(MediaElement().paused());
-
- // Press center key and video should be played.
- SimulateKeydownEvent(MediaElement(), VKEY_RETURN);
- ASSERT_FALSE(MediaElement().paused());
-}
-
-TEST_F(MediaControlsTouchlessImplTest, HandlesOrientationForArrowInput) {
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
-
- SetScreenOrientation(kWebScreenOrientationPortraitPrimary);
- CheckControlKeys(VKEY_RIGHT, VKEY_LEFT, VKEY_UP, VKEY_DOWN);
-
- SetScreenOrientation(kWebScreenOrientationLandscapePrimary);
- CheckControlKeys(VKEY_DOWN, VKEY_UP, VKEY_RIGHT, VKEY_LEFT);
-
- SetScreenOrientation(kWebScreenOrientationPortraitSecondary);
- CheckControlKeys(VKEY_LEFT, VKEY_RIGHT, VKEY_DOWN, VKEY_UP);
-
- SetScreenOrientation(kWebScreenOrientationLandscapeSecondary);
- CheckControlKeys(VKEY_UP, VKEY_DOWN, VKEY_LEFT, VKEY_RIGHT);
-}
-
-TEST_F(MediaControlsTouchlessImplTest, ArrowInputEdgeCaseHandling) {
- const double duration = 100;
-
- LoadMediaWithDuration(duration);
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
-
- // Seek backward at low current time
- MediaElement().setCurrentTime(1);
- SimulateKeydownEvent(MediaElement(), VKEY_LEFT);
- ASSERT_EQ(MediaElement().currentTime(), 0);
-
- // Seek forward at high current time
- MediaElement().setCurrentTime(duration - 1);
- SimulateKeydownEvent(MediaElement(), VKEY_RIGHT);
- ASSERT_EQ(MediaElement().currentTime(), duration);
-
- // Volume down at low volume
- MediaElement().setVolume(0.01);
- SimulateKeydownEvent(MediaElement(), VKEY_DOWN);
- ASSERT_EQ(MediaElement().volume(), 0);
-
- // Volume up at high volume
- MediaElement().setVolume(0.99);
- SimulateKeydownEvent(MediaElement(), VKEY_UP);
- ASSERT_EQ(MediaElement().volume(), 1);
-}
-
-TEST_F(MediaControlsTouchlessImplTest, PlayPauseIcon) {
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
-
- Element* play_button = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-play-button");
- ASSERT_NE(nullptr, play_button);
-
- MediaElement().pause();
-
- MediaElement().Play();
- test::RunPendingTasks();
- ASSERT_TRUE(play_button->classList().contains("playing"));
- ASSERT_FALSE(play_button->classList().contains("paused"));
-
- MediaElement().pause();
- test::RunPendingTasks();
- ASSERT_TRUE(play_button->classList().contains("paused"));
- ASSERT_FALSE(play_button->classList().contains("playing"));
-}
-
-TEST_F(MediaControlsTouchlessImplTest, ProgressBar) {
- const double duration = 100.0;
- const double buffered = 60.0;
- const double current_time = 15.0;
-
- LoadMediaWithDuration(duration);
- SetBufferedRange(buffered);
- MediaElement().setCurrentTime(current_time);
- test::RunPendingTasks();
-
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kTimeupdate));
-
- Element* timeline =
- GetControlByShadowPseudoId("-internal-media-controls-touchless-timeline");
- Element* progress_bar = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-timeline-progress");
- Element* loaded_bar = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-timeline-loaded");
-
- ASSERT_NE(nullptr, timeline);
- ASSERT_NE(nullptr, progress_bar);
- ASSERT_NE(nullptr, loaded_bar);
-
- double timeline_width = timeline->getBoundingClientRect()->width();
- double progress_bar_width = progress_bar->getBoundingClientRect()->width();
- double loaded_bar_width = loaded_bar->getBoundingClientRect()->width();
- ASSERT_GT(timeline_width, 0);
-
- EXPECT_DOUBLE_EQ(buffered / duration, loaded_bar_width / timeline_width);
- EXPECT_DOUBLE_EQ(current_time / buffered,
- progress_bar_width / loaded_bar_width);
-
- // Seek event should trigger a UI update as well.
- SetBufferedRange(0);
- MediaElement().setCurrentTime(0);
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kSeeking));
-
- EXPECT_DOUBLE_EQ(progress_bar->getBoundingClientRect()->width(), 0);
- EXPECT_DOUBLE_EQ(loaded_bar->getBoundingClientRect()->width(), 0);
-}
-
-TEST_F(MediaControlsTouchlessImplTest, TimeDisplay) {
- const double duration = 4000;
- const double current_time = 3599;
- const char expect_display[] = "59:59 / 1:06:40";
-
- Element* time_display = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-time-display");
-
- EXPECT_EQ(time_display->InnerHTMLAsString(), "0:00 / 0:00");
-
- LoadMediaWithDuration(duration);
- MediaElement().setCurrentTime(current_time);
- test::RunPendingTasks();
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kTimeupdate));
-
- EXPECT_EQ(time_display->InnerHTMLAsString(), expect_display);
-}
-
-TEST_F(MediaControlsTouchlessImplTest, VolumeDisplayTest) {
- Element* volume_bar_background = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-volume-bar-background");
- Element* volume_bar = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-volume-bar");
- ASSERT_NE(nullptr, volume_bar_background);
- ASSERT_NE(nullptr, volume_bar);
-
- const double volume = 0.65; // Initial volume.
- const double volume_delta = 0.05; // Volume change for each press.
- const double error = 0.01; // Allow precision error.
- MediaElement().setVolume(volume);
- SimulateKeydownEvent(MediaElement(), VK_UP);
-
- double volume_bar_background_height =
- volume_bar_background->getBoundingClientRect()->height();
- double volume_bar_height = volume_bar->getBoundingClientRect()->height();
-
- EXPECT_NEAR(volume + volume_delta,
- volume_bar_height / volume_bar_background_height, error);
-}
-
-TEST_F(MediaControlsTouchlessImplTest, ContextMenuMojomTest) {
- ScopedTestingPlatformSupport<LocalePlatformSupport> support;
-
- MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4");
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- LocalFrame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- test::RunPendingTasks();
-
- WebKeyboardEvent web_keyboard_event(
- WebInputEvent::kKeyUp, WebInputEvent::Modifiers::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests());
- // TODO: Cleanup magic numbers once https://crbug.com/949766 lands.
- web_keyboard_event.dom_key = 0x00200310;
- Event* keyboard_event = KeyboardEvent::Create(web_keyboard_event, nullptr);
-
- // Test fullscreen function.
- SetMenuResponse(mojom::blink::MenuItem::FULLSCREEN);
- MediaElement().DispatchEvent(*keyboard_event);
- MediaControls().MenuHostFlushForTesting();
- test::RunPendingTasks();
-
- TestMenuHostArgList& arg_list = GetMenuHostArgList();
- EXPECT_EQ((int)arg_list.menu_items.size(), 2);
- EXPECT_EQ(arg_list.menu_items[0], mojom::blink::MenuItem::FULLSCREEN);
- EXPECT_EQ(arg_list.menu_items[1], mojom::blink::MenuItem::DOWNLOAD);
- EXPECT_FALSE(arg_list.video_state->is_fullscreen);
- EXPECT_TRUE(MediaElement().IsFullscreen());
-
- SetMenuResponseAndShowMenu(mojom::blink::MenuItem::FULLSCREEN);
- test::RunPendingTasks();
-
- EXPECT_TRUE(arg_list.video_state->is_fullscreen);
- EXPECT_FALSE(MediaElement().IsFullscreen());
-
- // Disable download and fullscreen, and show mute option.
- MediaElement().ControlsListInternal()->Add("nofullscreen");
- MediaElement().GetDocument().GetSettings()->SetHideDownloadUI(true);
- SetHasAudio(true);
-
- SetMenuResponseAndShowMenu(mojom::blink::MenuItem::MUTE);
-
- EXPECT_EQ((int)arg_list.menu_items.size(), 1);
- EXPECT_EQ(arg_list.menu_items[0], mojom::blink::MenuItem::MUTE);
- EXPECT_FALSE(arg_list.video_state->is_muted);
- EXPECT_TRUE(MediaElement().muted());
-
- SetMenuResponseAndShowMenu(mojom::blink::MenuItem::MUTE);
-
- EXPECT_TRUE(arg_list.video_state->is_muted);
- EXPECT_FALSE(MediaElement().muted());
-
- // Disable mute option and show text track option.
- SetHasAudio(false);
- TextTrack* track = MediaElement().addTextTrack("subtitles", "english", "en",
- ASSERT_NO_EXCEPTION);
- SetMenuResponseAndShowMenu(mojom::blink::MenuItem::CAPTIONS, 0);
-
- EXPECT_EQ((int)arg_list.menu_items.size(), 1);
- EXPECT_EQ(arg_list.menu_items[0], mojom::blink::MenuItem::CAPTIONS);
- EXPECT_EQ(arg_list.text_tracks[1]->label, "english");
- EXPECT_EQ(track->mode(), TextTrack::ShowingKeyword());
-
- SetMenuResponseAndShowMenu(mojom::blink::MenuItem::CAPTIONS, -1);
- EXPECT_NE(track->mode(), TextTrack::ShowingKeyword());
-}
-
-TEST_F(MediaControlsTouchlessImplTest, NoSourceTest) {
- EXPECT_TRUE(MediaControls().classList().contains("state-no-source"));
-
- LoadMediaWithDuration(10);
- EXPECT_FALSE(MediaControls().classList().contains("state-no-source"));
-}
-
-TEST_F(MediaControlsTouchlessImplTest, DefaultPosterTest) {
- LoadMediaWithDuration(10);
-
- SetNetworkState(HTMLMediaElement::NetworkState::kNetworkLoading);
- test::RunPendingTasks();
- EXPECT_TRUE(MediaControls().classList().contains("use-default-poster"));
-
- SetNetworkState(HTMLMediaElement::NetworkState::kNetworkIdle);
- SetReadyState(HTMLMediaElement::ReadyState::kHaveMetadata);
- test::RunPendingTasks();
- EXPECT_FALSE(MediaControls().classList().contains("use-default-poster"));
-}
-
-TEST_F(MediaControlsTouchlessImplTest, DoesNotHandleKeysWhenDisabled) {
- // Disable the controls.
- MediaElement().SetBooleanAttribute(html_names::kControlsAttr, false);
-
- // Focus the video.
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
- ASSERT_TRUE(MediaElement().paused());
-
- // Enter should not play the video.
- SimulateKeydownEvent(MediaElement(), VKEY_RETURN);
- ASSERT_TRUE(MediaElement().paused());
-
- // The arrow keys should also not be handled.
- const int initTime = 10;
- const double initVolume = 0.5;
- MediaElement().setCurrentTime(initTime);
- MediaElement().setVolume(initVolume);
-
- SimulateKeydownEvent(MediaElement(), VKEY_RIGHT);
- ASSERT_EQ(MediaElement().currentTime(), initTime);
-
- SimulateKeydownEvent(MediaElement(), VKEY_LEFT);
- ASSERT_EQ(MediaElement().currentTime(), initTime);
-
- SimulateKeydownEvent(MediaElement(), VKEY_UP);
- ASSERT_EQ(MediaElement().volume(), initVolume);
-
- SimulateKeydownEvent(MediaElement(), VKEY_DOWN);
- ASSERT_EQ(MediaElement().volume(), initVolume);
-}
-
-TEST_F(MediaControlsTouchlessImplTestWithMockScheduler,
- MidOverlayHideTimerTest) {
- Element* overlay =
- GetControlByShadowPseudoId("-internal-media-controls-touchless-overlay");
- ASSERT_NE(nullptr, overlay);
-
- // Overlay should starts hidden.
- EXPECT_FALSE(IsControlsVisible(overlay));
-
- // Overlay should show when focus in.
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kFocusin));
- EXPECT_TRUE(IsControlsVisible(overlay));
-
- // Overlay should hide after 3 seconds.
- platform()->RunForPeriodSeconds(2.99);
- EXPECT_TRUE(IsControlsVisible(overlay));
- platform()->RunForPeriodSeconds(0.01);
- EXPECT_FALSE(IsControlsVisible(overlay));
-
- // Overlay should show upon pressing return key.
- SimulateKeydownEvent(MediaElement(), VKEY_RETURN);
- EXPECT_TRUE(IsControlsVisible(overlay));
-
- // Overlay should not disappear after 2 seconds.
- platform()->RunForPeriodSeconds(2);
- EXPECT_TRUE(IsControlsVisible(overlay));
-
- // Overlay should hide 3 seconds after last key press.
- platform()->RunForPeriodSeconds(1);
- EXPECT_FALSE(IsControlsVisible(overlay));
-}
-
-TEST_F(MediaControlsTouchlessImplTestWithMockScheduler,
- BottomContainerHideTimerTest) {
- Element* bottom_container = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-bottom-container");
- ASSERT_NE(nullptr, bottom_container);
-
- // Bottom container starts opaque since video is paused.
- EXPECT_TRUE(IsControlsVisible(bottom_container));
- EXPECT_TRUE(IsElementDisplayed(bottom_container));
-
- MediaElement().Play();
- platform()->RunForPeriodSeconds(3);
- EXPECT_FALSE(IsControlsVisible(bottom_container));
-
- MediaElement().pause();
-
- // Pause after play should stop hide timer.
- MediaElement().Play();
- MediaElement().pause();
- platform()->RunForPeriodSeconds(5);
- EXPECT_TRUE(IsControlsVisible(bottom_container));
-
- MediaElement().Play();
- platform()->RunForPeriodSeconds(5);
- EXPECT_FALSE(IsControlsVisible(bottom_container));
-
- // Bottom container should show after focus in.
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kFocusin));
- EXPECT_TRUE(IsControlsVisible(bottom_container));
-
- // Hide after 3 seconds
- platform()->RunForPeriodSeconds(3);
- EXPECT_FALSE(IsControlsVisible(bottom_container));
-
- // Display should be none after hide transition ends.
- bottom_container->DispatchEvent(
- *Event::Create(event_type_names::kTransitionend));
- EXPECT_FALSE(IsElementDisplayed(bottom_container));
-
- // Bottom container should show after pressing right/left arrow.
- SimulateKeydownEvent(MediaElement(), VK_RIGHT);
- EXPECT_TRUE(IsControlsVisible(bottom_container));
-
- platform()->RunForPeriodSeconds(3);
- EXPECT_FALSE(IsControlsVisible(bottom_container));
-
- SimulateKeydownEvent(MediaElement(), VK_LEFT);
- EXPECT_TRUE(IsControlsVisible(bottom_container));
-
- platform()->RunForPeriodSeconds(3);
- EXPECT_FALSE(IsControlsVisible(bottom_container));
-}
-
-TEST_F(MediaControlsTouchlessImplTestWithMockScheduler,
- VolumeDisplayTimerTest) {
- Element* volume_container = GetControlByShadowPseudoId(
- "-internal-media-controls-touchless-volume-container");
- Element* overlay =
- GetControlByShadowPseudoId("-internal-media-controls-touchless-overlay");
- ASSERT_NE(nullptr, volume_container);
- ASSERT_NE(nullptr, overlay);
-
- MediaElement().SetFocused(true, WebFocusType::kWebFocusTypeNone);
- MediaElement().DispatchEvent(*Event::Create(event_type_names::kFocusin));
- EXPECT_TRUE(IsControlsVisible(overlay));
-
- // Press up button should bring up volume display and hide overlay
- // immediately.
- SimulateKeydownEvent(MediaElement(), VK_UP);
- EXPECT_TRUE(IsControlsVisible(volume_container));
- EXPECT_FALSE(IsControlsVisible(overlay));
-
- platform()->RunForPeriodSeconds(3);
- EXPECT_FALSE(IsControlsVisible(volume_container));
-
- SimulateKeydownEvent(MediaElement(), VK_UP);
- EXPECT_TRUE(IsControlsVisible(volume_container));
-
- // Press mid key should bring up mid overlay and hide volume display
- // immediately.
- SimulateKeydownEvent(MediaElement(), VK_RETURN);
- EXPECT_FALSE(IsControlsVisible(volume_container));
- EXPECT_TRUE(IsControlsVisible(overlay));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc
deleted file mode 100644
index 9077df3b625..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc
+++ /dev/null
@@ -1,144 +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/media_controls/touchless/media_controls_touchless_media_event_listener.h"
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/events/keyboard_event.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h"
-
-namespace blink {
-
-MediaControlsTouchlessMediaEventListener::
- MediaControlsTouchlessMediaEventListener(HTMLMediaElement& media_element)
- : media_element_(media_element) {
- if (media_element.isConnected())
- Attach();
-}
-
-void MediaControlsTouchlessMediaEventListener::AddObserver(
- MediaControlsTouchlessMediaEventListenerObserver* observer) {
- observers_.insert(observer);
-}
-
-void MediaControlsTouchlessMediaEventListener::RemoveObserver(
- MediaControlsTouchlessMediaEventListenerObserver* observer) {
- observers_.erase(observer);
-}
-
-void MediaControlsTouchlessMediaEventListener::Attach() {
- DCHECK(media_element_->isConnected());
-
- media_element_->addEventListener(event_type_names::kFocusin, this, false);
- media_element_->addEventListener(event_type_names::kTimeupdate, this, false);
- media_element_->addEventListener(event_type_names::kDurationchange, this,
- false);
- media_element_->addEventListener(event_type_names::kSeeking, this, false);
- media_element_->addEventListener(event_type_names::kProgress, this, false);
-
- media_element_->addEventListener(event_type_names::kPlay, this, false);
- media_element_->addEventListener(event_type_names::kPause, this, false);
-
- media_element_->addEventListener(event_type_names::kError, this, false);
- media_element_->addEventListener(event_type_names::kLoadedmetadata, this,
- false);
-
- media_element_->addEventListener(event_type_names::kKeypress, this, false);
- media_element_->addEventListener(event_type_names::kKeydown, this, false);
- media_element_->addEventListener(event_type_names::kKeyup, this, false);
-
- media_element_->addEventListener(event_type_names::kWebkitfullscreenchange,
- this, false);
- media_element_->GetDocument().addEventListener(
- event_type_names::kFullscreenchange, this, false);
-}
-
-void MediaControlsTouchlessMediaEventListener::Detach() {
- DCHECK(!media_element_->isConnected());
-}
-
-void MediaControlsTouchlessMediaEventListener::Invoke(
- ExecutionContext* execution_context,
- Event* event) {
- if (event->type() == event_type_names::kFocusin) {
- for (auto& observer : observers_)
- observer->OnFocusIn();
- return;
- }
- if (event->type() == event_type_names::kTimeupdate) {
- for (auto& observer : observers_)
- observer->OnTimeUpdate();
- return;
- }
- if (event->type() == event_type_names::kDurationchange) {
- for (auto& observer : observers_)
- observer->OnDurationChange();
- return;
- }
- if (event->type() == event_type_names::kSeeking) {
- for (auto& observer : observers_)
- observer->OnSeeking();
- return;
- }
- if (event->type() == event_type_names::kProgress) {
- for (auto& observer : observers_)
- observer->OnLoadingProgress();
- return;
- }
- if (event->type() == event_type_names::kPlay) {
- for (auto& observer : observers_)
- observer->OnPlay();
- return;
- }
- if (event->type() == event_type_names::kPause) {
- for (auto& observer : observers_)
- observer->OnPause();
- return;
- }
- if (event->type() == event_type_names::kError) {
- for (auto& observer : observers_)
- observer->OnError();
- return;
- }
- if (event->type() == event_type_names::kLoadedmetadata) {
- for (auto& observer : observers_)
- observer->OnLoadedMetadata();
- return;
- }
- if (event->type() == event_type_names::kKeypress) {
- for (auto& observer : observers_)
- observer->OnKeyPress(ToKeyboardEvent(event));
- return;
- }
- if (event->type() == event_type_names::kKeydown) {
- for (auto& observer : observers_)
- observer->OnKeyDown(ToKeyboardEvent(event));
- return;
- }
- if (event->type() == event_type_names::kKeyup) {
- for (auto& observer : observers_)
- observer->OnKeyUp(ToKeyboardEvent(event));
- return;
- }
- if (event->type() == event_type_names::kFullscreenchange ||
- event->type() == event_type_names::kWebkitfullscreenchange) {
- if (media_element_->IsFullscreen()) {
- for (auto& observer : observers_)
- observer->OnEnterFullscreen();
- } else {
- for (auto& observer : observers_)
- observer->OnExitFullscreen();
- }
- }
-}
-
-void MediaControlsTouchlessMediaEventListener::Trace(blink::Visitor* visitor) {
- NativeEventListener::Trace(visitor);
- visitor->Trace(media_element_);
- visitor->Trace(observers_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h
deleted file mode 100644
index a290bd91510..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h
+++ /dev/null
@@ -1,41 +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_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_H_
-
-#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
-
-namespace blink {
-
-class HTMLMediaElement;
-class MediaControlsTouchlessMediaEventListenerObserver;
-
-class MediaControlsTouchlessMediaEventListener final
- : public NativeEventListener {
- public:
- explicit MediaControlsTouchlessMediaEventListener(HTMLMediaElement&);
-
- void AddObserver(MediaControlsTouchlessMediaEventListenerObserver*);
- void RemoveObserver(MediaControlsTouchlessMediaEventListenerObserver*);
-
- void Attach();
- void Detach();
-
- void Trace(blink::Visitor*) override;
- void Invoke(ExecutionContext*, Event*) override;
-
- private:
- HTMLMediaElement& GetMediaElement();
-
- HeapLinkedHashSet<Member<MediaControlsTouchlessMediaEventListenerObserver>>
- observers_;
- Member<HTMLMediaElement> media_element_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaControlsTouchlessMediaEventListener);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h
deleted file mode 100644
index cf07510f775..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h
+++ /dev/null
@@ -1,35 +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_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_OBSERVER_H_
-
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-
-namespace blink {
-
-class KeyboardEvent;
-
-class MediaControlsTouchlessMediaEventListenerObserver
- : public GarbageCollectedMixin {
- public:
- virtual void OnFocusIn() = 0;
- virtual void OnTimeUpdate() = 0;
- virtual void OnDurationChange() = 0;
- virtual void OnSeeking() = 0;
- virtual void OnLoadingProgress() = 0;
- virtual void OnPlay() = 0;
- virtual void OnPause() = 0;
- virtual void OnEnterFullscreen() = 0;
- virtual void OnExitFullscreen() = 0;
- virtual void OnError() = 0;
- virtual void OnLoadedMetadata() = 0;
- virtual void OnKeyPress(KeyboardEvent* event) = 0;
- virtual void OnKeyDown(KeyboardEvent* event) = 0;
- virtual void OnKeyUp(KeyboardEvent* event) = 0;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_MEDIA_EVENT_LISTENER_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.cc
deleted file mode 100644
index 1af1f09c2f8..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.cc
+++ /dev/null
@@ -1,38 +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/media_controls/touchless/media_controls_touchless_resource_loader.h"
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/resources/grit/media_controls_touchless_resources.h"
-#include "third_party/blink/renderer/platform/data_resource_helper.h"
-
-namespace blink {
-
-MediaControlsTouchlessResourceLoader::MediaControlsTouchlessResourceLoader()
- : UAStyleSheetLoader() {}
-
-MediaControlsTouchlessResourceLoader::~MediaControlsTouchlessResourceLoader() =
- default;
-
-String MediaControlsTouchlessResourceLoader::GetMediaControlsTouchlessCSS()
- const {
- return UncompressResourceAsString(IDR_UASTYLE_MEDIA_CONTROLS_TOUCHLESS_CSS);
-}
-
-String MediaControlsTouchlessResourceLoader::GetUAStyleSheet() {
- return GetMediaControlsTouchlessCSS();
-}
-
-void MediaControlsTouchlessResourceLoader::
- InjectMediaControlsTouchlessUAStyleSheet() {
- CSSDefaultStyleSheets& default_style_sheets =
- CSSDefaultStyleSheets::Instance();
- std::unique_ptr<MediaControlsTouchlessResourceLoader> loader =
- std::make_unique<MediaControlsTouchlessResourceLoader>();
-
- if (!default_style_sheets.HasMediaControlsStyleSheetLoader())
- default_style_sheets.SetMediaControlsStyleSheetLoader(std::move(loader));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h
deleted file mode 100644
index 74ed1ac5f1a..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h
+++ /dev/null
@@ -1,28 +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_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_RESOURCE_LOADER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_RESOURCE_LOADER_H_
-
-#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
-
-namespace blink {
-
-// Builds the UA stylesheet for the touchless Media Controls.
-class MediaControlsTouchlessResourceLoader
- : public CSSDefaultStyleSheets::UAStyleSheetLoader {
- public:
- static void InjectMediaControlsTouchlessUAStyleSheet();
-
- String GetUAStyleSheet() override;
- MediaControlsTouchlessResourceLoader();
- ~MediaControlsTouchlessResourceLoader() override;
-
- private:
- String GetMediaControlsTouchlessCSS() const;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_MEDIA_CONTROLS_TOUCHLESS_RESOURCE_LOADER_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/gradient_bg.png b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/gradient_bg.png
deleted file mode 100644
index 25f2a028ae3..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/gradient_bg.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg
deleted file mode 100644
index 09a980598bc..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_forward.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M15 9.86L18.03 12 15 14.14V9.86m-9 0L9.03 12 6 14.14V9.86M13 6v12l8.5-6L13 6zM4 6v12l8.5-6L4 6z"/><path fill="none" d="M0 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg
deleted file mode 100644
index 384fdc49eab..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_fast_rewind.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M18 9.86v4.28L14.97 12 18 9.86m-9 0v4.28L5.97 12 9 9.86M20 6l-8.5 6 8.5 6V6zm-9 0l-8.5 6 8.5 6V6z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg
deleted file mode 100644
index 77cf41fc354..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_mid_background.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<svg width="104" height="104" viewBox="0 0 104 104" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path opacity="0.85" fill-rule="evenodd" clip-rule="evenodd" d="M32 0C14.3269 0 0 14.3269 0 32V72C0 89.6731 14.3269 104 32 104H72C89.6731 104 104 89.6731 104 72V32C104 14.3269 89.6731 0 72 0H32ZM46 30C37.1634 30 30 37.1634 30 46V58C30 66.8366 37.1634 74 46 74H58C66.8366 74 74 66.8366 74 58V46C74 37.1634 66.8366 30 58 30H46Z" fill="#202124"/>
-<rect opacity="0.85" x="32" y="32" width="40" height="40" rx="14" fill="#202124"/>
-</svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_music_note.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_music_note.svg
deleted file mode 100644
index bcabd88d2ee..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_music_note.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 3l.01 10.55c-.59-.34-1.27-.55-2-.55C7.79 13 6 14.79 6 17s1.79 4 4.01 4S14 19.21 14 17V7h4V3h-6z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_no_source.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_no_source.svg
deleted file mode 100644
index 49b7eaf5769..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_no_source.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#000000">
- <path fill="none" d="M0 0h24v24H0zm0 0h24v24H0zm21 19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2"/>
- <path fill="none" d="M0 0h24v24H0z"/>
- <path d="M21 5v6.59l-3-3.01-4 4.01-4-4-4 4-3-3.01V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42l3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l3 2.99 4-4 4 4 4-3.99z"/>
-</svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg
deleted file mode 100644
index bd17d16c452..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_pause.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M19 19h-6V5h6v14zm-4-2h2V7h-2v10zm-4 2H5V5h6v14zm-4-2h2V7H7v10z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg
deleted file mode 100644
index 10c1d08fa74..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_play_arrow.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M10 8.64L15.27 12 10 15.36V8.64M8 5v14l11-7L8 5z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg
deleted file mode 100644
index 67af7988c68..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_down.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M16 7.97v8.05c1.48-.73 2.5-2.25 2.5-4.02 0-1.77-1.02-3.29-2.5-4.03zM5 9v6h4l5 5V4L9 9H5zm7-.17v6.34L9.83 13H7v-2h2.83L12 8.83z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_off.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_off.svg
deleted file mode 100644
index a8636be347d..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_off.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M21.19 21.19L14 14l-2-2-9.2-9.2-1.41 1.42 8.79 8.79c-.06 0-.12-.01-.18-.01-2.21 0-4 1.79-4 4s1.79 4 4.01 4S14 19.21 14 17v-.17l5.78 5.78 1.41-1.42zM14 11.17V7h4V3h-6v6.17z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_on.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_on.svg
deleted file mode 100644
index ba098e8640f..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_on.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg
deleted file mode 100644
index 9c82fbcef37..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/ic_volume_up.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#FFFFFF"><path d="M3 9v6h4l5 5V4L7 9H3zm7-.17v6.34L7.83 13H5v-2h2.83L10 8.83zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77 0-4.28-2.99-7.86-7-8.77z"/><path fill="none" d="M0 0h24v24H0V0z"/></svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css
deleted file mode 100644
index 67a19135220..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css
+++ /dev/null
@@ -1,370 +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. */
-
-audio {
- width: 300px;
- height: 180px;
-}
-
-audio::-webkit-media-controls-touchless,
-video::-webkit-media-controls-touchless {
- width: inherit;
- height: inherit;
-
- position: relative;
- direction: ltr;
- display: flex;
- flex-direction: column;
- opacity: 1;
-
- margin-top: env(safe-area-inset-top);
- margin-left: env(safe-area-inset-left);
- margin-right: env(safe-area-inset-right);
- margin-bottom: env(safe-area-inset-bottom);
-}
-
-audio::-webkit-media-controls-touchless,
-video::-webkit-media-controls-touchless.use-default-poster {
- background: #333;
-}
-
-audio::-internal-media-controls-touchless-info,
-video::-internal-media-controls-touchless-info {
- display: none;
- height: 72px;
- width: 72px;
- border-radius: 50%;
- opacity: 0.3;
- background-color: rgba(255, 255, 255, 0.9);
- background-size: 50%;
- background-position: center;
- background-repeat: no-repeat;
- position: absolute;
- margin: auto;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
-}
-
-audio::-internal-media-controls-touchless-info {
- background-image: -webkit-image-set(url(ic_music_note.svg) 1x);
- display: block;
-}
-
-audio::-webkit-media-controls-touchless.state-no-source [pseudo="-internal-media-controls-touchless-info"],
-video::-webkit-media-controls-touchless.state-no-source [pseudo="-internal-media-controls-touchless-info"] {
- background-image: -webkit-image-set(url(ic_no_source.svg) 1x);
- display: block;
-}
-
-audio::-internal-media-controls-touchless-overlay,
-video::-internal-media-controls-touchless-overlay {
- width: 104px;
- height: 104px;
- background-image: -webkit-image-set(url(ic_mid_background.svg) 1x);
- background-size: 104px;
- background-position: center;
- background-repeat: no-repeat;
- position: absolute;
- opacity: 1;
- z-index: 1;
- margin: auto;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
-}
-
-audio::-webkit-media-controls-touchless.state-no-source [pseudo="-internal-media-controls-touchless-overlay"],
-video::-webkit-media-controls-touchless.state-no-source [pseudo="-internal-media-controls-touchless-overlay"] {
- display: none;
-}
-
-audio::-internal-media-controls-touchless-overlay.transparent,
-video::-internal-media-controls-touchless-overlay.transparent {
- opacity: 0;
- transition: opacity .5s;
-}
-
-audio::-internal-media-controls-touchless-overlay.transparent-immediate,
-video::-internal-media-controls-touchless-overlay.transparent-immediate {
- opacity: 0;
-}
-
-audio::-internal-media-controls-touchless-volume-up-button,
-video::-internal-media-controls-touchless-volume-up-button {
- width: 30px;
- height: 30px;
- margin-left: 37px /* (overlay width -width) / 2 */;
- background-image: -webkit-image-set(url(ic_volume_up.svg) 1x);
- background-size: 20px;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-audio::-internal-media-controls-touchless-seek-backward-button,
-video::-internal-media-controls-touchless-seek-backward-button {
- width: 30px;
- height: 30px;
- margin-top: 7px /* (play button height - height) / 2 */;
- float: left;
- background-image: -webkit-image-set(url(ic_fast_rewind.svg) 1x);
- background-size: 20px;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-audio::-internal-media-controls-touchless-play-button,
-video::-internal-media-controls-touchless-play-button {
- width: 44px;
- height: 44px;
- background-position: center;
- background-size: 24px;
- background-repeat: no-repeat;
- float: left;
-}
-
-audio::-internal-media-controls-touchless-play-button.playing,
-video::-internal-media-controls-touchless-play-button.playing {
- background-image: -webkit-image-set(url(ic_pause.svg) 1x);
-}
-
-audio::-internal-media-controls-touchless-play-button.paused,
-video::-internal-media-controls-touchless-play-button.paused {
- background-image: -webkit-image-set(url(ic_play_arrow.svg) 1x);
-}
-
-audio::-internal-media-controls-touchless-seek-forward-button,
-video::-internal-media-controls-touchless-seek-forward-button {
- width: 30px;
- height: 30px;
- margin-top: 7px /* (play button height - height) / 2 */;
- float: left;
- background-image: -webkit-image-set(url(ic_fast_forward.svg) 1x);
- background-size: 20px;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-audio::-internal-media-controls-touchless-volume-down-button,
-video::-internal-media-controls-touchless-volume-down-button {
- width: 30px;
- height: 30px;
- margin-left: 37px /* (overlay width -width) / 2 */;
- position: absolute;
- bottom: 0;
- background-image: -webkit-image-set(url(ic_volume_down.svg) 1x);
- background-size: 20px;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-audio::-internal-media-controls-touchless-bottom-container,
-video::-internal-media-controls-touchless-bottom-container {
- position: absolute;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
- height: 100%;
- width: 100%;
- z-index: 0;
-
- background:
- -webkit-image-set(url('gradient_bg.png') 1x)
- repeat-x bottom left;
- background-size: auto 48px;
-}
-
-audio::-internal-media-controls-touchless-bottom-container.transparent,
-video::-internal-media-controls-touchless-bottom-container.transparent {
- opacity: 0;
- transition: opacity .5s;
-}
-
-audio::-internal-media-controls-touchless-time-display,
-video::-internal-media-controls-touchless-time-display {
- color: #ffffff;
- font-family: Roboto-Regular, Roboto, sans-serif;
- font-size: 14px;
- width: 100%;
- bottom: auto;
- padding-left: 8px;
- padding-bottom: 8px;
-}
-
-audio::-internal-media-controls-touchless-timeline,
-video::-internal-media-controls-touchless-timeline {
- width: 100%;
- bottom: auto;
- height: 4px;
- background-color: rgba(0, 0, 0, 0.2);
-}
-
-audio::-internal-media-controls-touchless-timeline-loaded,
-video::-internal-media-controls-touchless-timeline-loaded {
- height: 100%;
- width: 0; /* We are using style attribute to override this. */
- border-radius: 0 2px 2px 0;
- background-color: rgba(255, 255, 255, 0.54);
-}
-
-audio::-internal-media-controls-touchless-timeline-progress,
-video::-internal-media-controls-touchless-timeline-progress {
- height: 100%;
- width: 0; /* We are using style attribute to override this. */
- border-radius: 0 2px 2px 0;
- background-color: rgba(255, 255, 255, 1.0);
-}
-
-audio::-internal-media-controls-touchless-volume-container,
-video::-internal-media-controls-touchless-volume-container {
- width: 44px;
- max-height: 152px;
- height: 90%;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- margin: auto;
- background-color: rgba(60,64,67,0.9);
- border-radius: 22px;
-
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
-}
-
-audio::-internal-media-controls-touchless-volume-container.transparent,
-video::-internal-media-controls-touchless-volume-container.transparent {
- opacity: 0;
- transition: opacity .5s;
-}
-
-audio::-internal-media-controls-touchless-volume-container.transparent-immediate,
-video::-internal-media-controls-touchless-volume-container.transparent-immediate {
- opacity: 0;
-}
-
-audio::-internal-media-controls-touchless-volume-bar-background,
-video::-internal-media-controls-touchless-volume-bar-background {
- width: 4px;
- margin-left: 20px;
- margin-top: 12px;
- margin-bottom: 8px;
- background-color: rgba(255,255,255,0.54);
- flex: 1 1 auto;
- border-radius: 2px;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
-}
-
-audio::-webkit-media-controls-touchless.inline [pseudo="-internal-media-controls-touchless-volume-bar-background"],
-video::-webkit-media-controls-touchless.inline [pseudo="-internal-media-controls-touchless-volume-bar-background"] {
- margin-bottom: 12px;
-}
-
-audio::-internal-media-controls-touchless-volume-bar,
-video::-internal-media-controls-touchless-volume-bar {
- background-color: #FFFFFF;
- border-radius: 2px;
-}
-
-audio::-internal-media-controls-touchless-volume-icon,
-video::-internal-media-controls-touchless-volume-icon {
- width: 24px;
- height: 24px;
- margin-left: 10px;
- margin-bottom: 10px;
- flex: 0 1 auto;
- background-image: -webkit-image-set(url(ic_volume_on.svg) 1x);
-}
-
-audio::-internal-media-controls-touchless-volume-icon.muted,
-video::-internal-media-controls-touchless-volume-icon.muted {
- background-image: -webkit-image-set(url(ic_volume_off.svg) 1x);
-}
-
-audio::-webkit-media-controls-touchless.inline div[pseudo="-internal-media-controls-touchless-volume-icon" i],
-video::-webkit-media-controls-touchless.inline div[pseudo="-internal-media-controls-touchless-volume-icon" i] {
- display: none;
-}
-
-/**
- * Text Tracks
- */
-video::-webkit-media-text-track-container {
- position: relative;
- width: inherit;
- height: inherit;
- overflow: hidden;
-
- font: 22px sans-serif;
- text-align: center;
- color: rgba(255, 255, 255, 1);
-
- letter-spacing: normal;
- word-spacing: normal;
- text-transform: none;
- text-indent: 0;
- text-decoration: none;
- pointer-events: none;
- -webkit-user-select: none;
- word-break: break-word;
-}
-
-video::cue {
- display: inline;
-
- background-color: rgba(0, 0, 0, 0.8);
-}
-
-video::-webkit-media-text-track-region {
- position: absolute;
- line-height: 5.33vh;
- writing-mode: horizontal-tb;
- background: rgba(0, 0, 0, 0.8);
- color: rgba(255, 255, 255, 1);
- word-wrap: break-word;
- overflow-wrap: break-word;
- overflow: hidden;
-}
-
-video::-webkit-media-text-track-region-container {
- position: relative;
-
- display: flex;
- flex-flow: column;
- flex-direction: column;
-}
-
-video::-webkit-media-text-track-region-container.scrolling {
- transition: top 433ms linear;
-}
-
-video::-webkit-media-text-track-display {
- position: absolute;
- overflow: hidden;
- white-space: pre-wrap;
- -webkit-box-sizing: border-box;
- flex: 0 0 auto;
-}
-
-video::cue(:future) {
- color: gray;
-}
-
-video::cue(b) {
- font-weight: bold;
-}
-
-video::cue(u) {
- text-decoration: underline;
-}
-
-video::cue(i) {
- font-style: italic;
-}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.grd b/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.grd
deleted file mode 100644
index 5f74e838e60..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/resources/media_controls_touchless_resources.grd
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
- <outputs>
- <output filename="grit/media_controls_touchless_resources.h" type="rc_header">
- <emit emit_type='prepend'></emit>
- </output>
- <output filename="media_controls_touchless_resources.pak" type="data_package" />
- </outputs>
- <release seq="1">
- <structures fallback_to_low_resolution="true">
- <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_CONTROLS_TOUCHLESS_CSS" file="mediaControlsTouchless.css" flattenhtml="true" compress="gzip"/>
- </structures>
- </release>
-</grit>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.cc b/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.cc
deleted file mode 100644
index 25b68b98cb6..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.cc
+++ /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.
-
-#include "third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h"
-
-namespace blink {
-
-mojo::PendingRemote<mojom::blink::MediaControlsMenuHost>
-TestMediaControlsMenuHost::CreateMediaControlsMenuHostRemote() {
- return receiver_.BindNewPipeAndPassRemote();
-}
-
-void TestMediaControlsMenuHost::ShowMediaMenu(
- const WTF::Vector<mojom::MenuItem>& menu_items,
- mojo::PendingRemote<mojom::blink::VideoState> video_state,
- base::Optional<WTF::Vector<mojom::blink::TextTrackMetadataPtr>> text_tracks,
- ShowMediaMenuCallback callback) {
- arg_list_.menu_items = WTF::Vector<mojom::MenuItem>(menu_items);
-
- arg_list_.video_state = mojom::blink::VideoState::New();
- arg_list_.video_state->is_fullscreen = video_state->is_fullscreen;
- arg_list_.video_state->is_muted = video_state->is_muted;
-
- arg_list_.text_tracks = WTF::Vector<mojom::blink::TextTrackMetadataPtr>(
- std::move(text_tracks.value()));
-
- std::move(callback).Run(std::move(response_));
-}
-
-TestMenuHostArgList& TestMediaControlsMenuHost::GetMenuHostArgList() {
- return arg_list_;
-}
-
-void TestMediaControlsMenuHost::SetMenuResponse(
- mojom::blink::MenuItem menu_item,
- int track_index) {
- if (response_.is_null())
- response_ = mojom::blink::MenuResponse::New();
-
- response_->clicked = menu_item;
- response_->track_index = track_index;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h b/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h
deleted file mode 100644
index 018022feaf0..00000000000
--- a/chromium/third_party/blink/renderer/modules/media_controls/touchless/test_media_controls_menu_host.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_TEST_MEDIA_CONTROLS_MENU_HOST_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_TEST_MEDIA_CONTROLS_MENU_HOST_H_
-
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/media_controls/touchless/media_controls.mojom-blink.h"
-
-namespace blink {
-
-struct TestMenuHostArgList {
- WTF::Vector<mojom::MenuItem> menu_items;
- mojom::blink::VideoStatePtr video_state;
- WTF::Vector<mojom::blink::TextTrackMetadataPtr> text_tracks;
-};
-
-class TestMediaControlsMenuHost : public mojom::blink::MediaControlsMenuHost {
- public:
- mojo::PendingRemote<mojom::blink::MediaControlsMenuHost>
- CreateMediaControlsMenuHostRemote();
- void ShowMediaMenu(
- const WTF::Vector<mojom::MenuItem>& menu_items,
- mojo::PendingRemote<mojom::blink::VideoState> video_state,
- base::Optional<WTF::Vector<mojom::blink::TextTrackMetadataPtr>>
- text_tracks,
- ShowMediaMenuCallback callback) override;
-
- TestMenuHostArgList& GetMenuHostArgList();
- void SetMenuResponse(mojom::blink::MenuItem menu_item, int track_index);
-
- private:
- mojo::Receiver<mojom::blink::MediaControlsMenuHost> receiver_{this};
- TestMenuHostArgList arg_list_;
- mojo::Remote<mojom::blink::MenuResponse> response_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_TEST_MEDIA_CONTROLS_MENU_HOST_H_
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/DEPS b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/DEPS
index 1384f5ed1cd..725f02f25ef 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/DEPS
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/DEPS
@@ -8,6 +8,7 @@ include_rules = [
"+cc/paint/paint_canvas.h",
"+cc/paint/skia_paint_canvas.h",
"+components/viz/common",
+ "+gpu/GLES2",
"+media/base",
"+media/capture",
"+skia/ext/platform_canvas.h",
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.cc
index 7bb34cb386e..cc92feb0861 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.cc
@@ -18,8 +18,7 @@ AutoCanvasDrawListener::AutoCanvasDrawListener(
void AutoCanvasDrawListener::SendNewFrame(
sk_sp<SkImage> image,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider) {
- handler_->SendNewFrame(
- image, context_provider ? context_provider->ContextProvider() : nullptr);
+ handler_->SendNewFrame(image, context_provider);
}
bool AutoCanvasDrawListener::NeedsNewFrame() const {
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.h b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.h
index 3523062c394..c3a22e22085 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.h
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/auto_canvas_draw_listener.h
@@ -12,9 +12,8 @@
namespace blink {
-class AutoCanvasDrawListener
- : public GarbageCollectedFinalized<AutoCanvasDrawListener>,
- public CanvasDrawListener {
+class AutoCanvasDrawListener : public GarbageCollected<AutoCanvasDrawListener>,
+ public CanvasDrawListener {
USING_GARBAGE_COLLECTED_MIXIN(AutoCanvasDrawListener);
public:
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 fcab7d34fdf..25f4949f127 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
@@ -21,6 +21,7 @@
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/libyuv/include/libyuv.h"
@@ -171,7 +172,8 @@ CanvasCaptureHandler::CreateCanvasCaptureHandler(
void CanvasCaptureHandler::SendNewFrame(
sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) {
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
TRACE_EVENT0("webrtc", "CanvasCaptureHandler::SendNewFrame");
if (!image)
@@ -209,7 +211,7 @@ void CanvasCaptureHandler::SendNewFrame(
if (image->isOpaque()) {
ReadYUVPixelsAsync(image, context_provider);
} else {
- ReadARGBPixelsAsync(image, context_provider);
+ ReadARGBPixelsAsync(image, context_provider->ContextProvider());
}
}
@@ -289,6 +291,7 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
sk_sp<SkImage> image,
blink::WebGraphicsContext3DProvider* context_provider) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+ DCHECK(context_provider);
const base::TimeTicks timestamp = base::TimeTicks::Now();
const gfx::Size image_size(image->width(), image->height());
@@ -308,7 +311,7 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
DCHECK(result);
DCHECK(context_provider->GetGLHelper());
context_provider->GetGLHelper()->ReadbackTextureAsync(
- texture_info.fID, image_size,
+ texture_info.fID, texture_info.fTarget, image_size,
temp_argb_frame->visible_data(VideoFrame::kARGBPlane), kN32_SkColorType,
WTF::Bind(&CanvasCaptureHandler::OnARGBPixelsReadAsync,
weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame,
@@ -317,8 +320,10 @@ void CanvasCaptureHandler::ReadARGBPixelsAsync(
void CanvasCaptureHandler::ReadYUVPixelsAsync(
sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider) {
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+ DCHECK(context_provider);
const base::TimeTicks timestamp = base::TimeTicks::Now();
const gfx::Size image_size(image->width(), image->height());
@@ -337,12 +342,36 @@ void CanvasCaptureHandler::ReadYUVPixelsAsync(
GrGLTextureInfo texture_info;
const bool result = backend_texture.getGLTextureInfo(&texture_info);
DCHECK(result);
- DCHECK(context_provider->GetGLHelper());
+
+ // The YUV readback path only works for 2D textures.
+ GLuint texture_for_readback = texture_info.fID;
+ GLuint copy_texture = 0;
+ if (texture_info.fTarget != GL_TEXTURE_2D) {
+ auto* gl = context_provider->ContextProvider()->ContextGL();
+ int width = image->imageInfo().width();
+ int height = image->imageInfo().height();
+
+ gl->GenTextures(1, &copy_texture);
+ gl->BindTexture(GL_TEXTURE_2D, copy_texture);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, nullptr);
+ gl->CopyTextureCHROMIUM(texture_info.fID, 0, GL_TEXTURE_2D, copy_texture, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0, 0, 0);
+ image = nullptr;
+ texture_for_readback = copy_texture;
+ }
+
+ DCHECK(context_provider->ContextProvider()->GetGLHelper());
viz::ReadbackYUVInterface* const yuv_reader =
- context_provider->GetGLHelper()->GetReadbackPipelineYUV(
- surface_origin != kTopLeft_GrSurfaceOrigin);
+ context_provider->ContextProvider()
+ ->GetGLHelper()
+ ->GetReadbackPipelineYUV(surface_origin != kTopLeft_GrSurfaceOrigin);
yuv_reader->ReadbackYUV(
- texture_info.fID, image_size, gfx::Rect(image_size),
+ texture_for_readback, image_size, gfx::Rect(image_size),
output_frame->stride(media::VideoFrame::kYPlane),
output_frame->visible_data(media::VideoFrame::kYPlane),
output_frame->stride(media::VideoFrame::kUPlane),
@@ -350,8 +379,8 @@ void CanvasCaptureHandler::ReadYUVPixelsAsync(
output_frame->stride(media::VideoFrame::kVPlane),
output_frame->visible_data(media::VideoFrame::kVPlane), gfx::Point(0, 0),
WTF::Bind(&CanvasCaptureHandler::OnYUVPixelsReadAsync,
- weak_ptr_factory_.GetWeakPtr(), image, output_frame,
- timestamp));
+ weak_ptr_factory_.GetWeakPtr(), image, copy_texture,
+ context_provider, output_frame, timestamp));
}
void CanvasCaptureHandler::OnARGBPixelsReadAsync(
@@ -384,10 +413,17 @@ void CanvasCaptureHandler::OnARGBPixelsReadAsync(
void CanvasCaptureHandler::OnYUVPixelsReadAsync(
sk_sp<SkImage> image,
+ GLuint copy_texture,
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> context_provider,
scoped_refptr<media::VideoFrame> yuv_frame,
base::TimeTicks this_frame_ticks,
bool success) {
DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
+ if (copy_texture && context_provider) {
+ context_provider->ContextProvider()->ContextGL()->DeleteTextures(
+ 1, &copy_texture);
+ }
+
if (!success) {
DLOG(ERROR) << "Couldn't read SkImage using async callback";
return;
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 907dd5dcdf6..e685d093040 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
@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "media/base/video_frame_pool.h"
#include "media/capture/video_capturer_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
@@ -28,6 +29,7 @@ namespace blink {
class LocalFrame;
class WebGraphicsContext3DProvider;
+class WebGraphicsContext3DProviderWrapper;
// CanvasCaptureHandler acts as the link between Blink side HTMLCanvasElement
// and Chrome side VideoCapturerSource. It is responsible for handling
@@ -51,7 +53,8 @@ class MODULES_EXPORT CanvasCaptureHandler {
blink::WebMediaStreamTrack* track);
void SendNewFrame(sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider);
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider);
bool NeedsNewFrame() const;
// Functions called by media::VideoCapturerSource implementation.
@@ -82,16 +85,21 @@ class MODULES_EXPORT CanvasCaptureHandler {
blink::WebGraphicsContext3DProvider* context_provider);
void ReadYUVPixelsAsync(
sk_sp<SkImage> image,
- blink::WebGraphicsContext3DProvider* context_provider);
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider);
void OnARGBPixelsReadAsync(sk_sp<SkImage> image,
scoped_refptr<media::VideoFrame> temp_argb_frame,
base::TimeTicks this_frame_ticks,
bool flip,
bool success);
- void OnYUVPixelsReadAsync(sk_sp<SkImage> image,
- scoped_refptr<media::VideoFrame> yuv_frame,
- base::TimeTicks this_frame_ticks,
- bool success);
+ void OnYUVPixelsReadAsync(
+ sk_sp<SkImage> image,
+ GLuint copy_texture,
+ base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
+ context_provider,
+ scoped_refptr<media::VideoFrame> yuv_frame,
+ base::TimeTicks this_frame_ticks,
+ bool success);
scoped_refptr<media::VideoFrame> ConvertToYUVFrame(
bool is_opaque,
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
index a2129ed72a8..e4b9b8d8741 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
@@ -122,12 +122,15 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
const base::TimeTicks current_time = base::TimeTicks::Now();
if (start_capture_time_.is_null())
start_capture_time_ = current_time;
- const blink::WebSize resolution = web_media_player_->NaturalSize();
if (!canvas_ || is_opaque_ != web_media_player_->IsOpaque()) {
+ // TODO(crbug.com/964494): Avoid the explicit conversion to gfx::Size here.
+ // TODO(sandersd): Implement support for size changes rather than scaling.
+ if (!canvas_)
+ natural_size_ = gfx::Size(web_media_player_->NaturalSize());
is_opaque_ = web_media_player_->IsOpaque();
if (!bitmap_.tryAllocPixels(SkImageInfo::MakeN32(
- resolution.width, resolution.height,
+ natural_size_.width(), natural_size_.height(),
is_opaque_ ? kOpaque_SkAlphaType : kPremul_SkAlphaType))) {
running_callback_.Run(false);
return;
@@ -138,12 +141,11 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
cc::PaintFlags flags;
flags.setBlendMode(SkBlendMode::kSrc);
flags.setFilterQuality(kLow_SkFilterQuality);
- web_media_player_->Paint(
- canvas_.get(), blink::WebRect(0, 0, resolution.width, resolution.height),
- flags);
+ // TODO(crbug.com/964494): Avoid the explicit conversion to blink::WebRect
+ // here.
+ web_media_player_->Paint(canvas_.get(),
+ blink::WebRect(gfx::Rect(natural_size_)), flags);
DCHECK_NE(kUnknown_SkColorType, canvas_->imageInfo().colorType());
- DCHECK_EQ(canvas_->imageInfo().width(), resolution.width);
- DCHECK_EQ(canvas_->imageInfo().height(), resolution.height);
DCHECK_NE(kUnknown_SkColorType, bitmap_.colorType());
DCHECK(!bitmap_.drawsNothing());
@@ -153,11 +155,9 @@ void HtmlVideoElementCapturerSource::sendNewFrame() {
return;
}
- // TODO(crbug.com/964494): Avoid the explicit convertion to gfx::Size here.
- gfx::Size gfx_resolution = gfx::Size(resolution);
scoped_refptr<media::VideoFrame> frame = frame_pool_.CreateFrame(
is_opaque_ ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
- gfx_resolution, gfx::Rect(gfx_resolution), gfx_resolution,
+ natural_size_, gfx::Rect(natural_size_), natural_size_,
current_time - start_capture_time_);
const uint32_t source_pixel_format =
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
index 2ba15320bfa..081ea9dfb25 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h
@@ -64,6 +64,7 @@ class MODULES_EXPORT HtmlVideoElementCapturerSource final
media::VideoFramePool frame_pool_;
SkBitmap bitmap_;
std::unique_ptr<cc::PaintCanvas> canvas_;
+ gfx::Size natural_size_;
const base::WeakPtr<blink::WebMediaPlayer> web_media_player_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
index c2c1bb0611f..c0c0ffe3013 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
@@ -58,8 +58,8 @@ class MockWebMediaPlayer : public WebMediaPlayer {
WebSetSinkIdCompleteCallback) override {}
bool HasVideo() const override { return true; }
bool HasAudio() const override { return false; }
- WebSize NaturalSize() const override { return WebSize(16, 10); }
- WebSize VisibleRect() const override { return WebSize(16, 10); }
+ WebSize NaturalSize() const override { return size_; }
+ WebSize VisibleRect() const override { return size_; }
bool Paused() const override { return false; }
bool Seeking() const override { return false; }
double Duration() const override { return 0.0; }
@@ -98,6 +98,7 @@ class MockWebMediaPlayer : public WebMediaPlayer {
}
bool is_video_opaque_ = true;
+ WebSize size_ = WebSize(16, 10);
base::WeakPtrFactory<MockWebMediaPlayer> weak_factory_{this};
};
@@ -128,6 +129,8 @@ class HTMLVideoElementCapturerSourceTest : public testing::TestWithParam<bool> {
web_media_player_->is_video_opaque_ = opacity;
}
+ void SetVideoPlayerSize(WebSize size) { web_media_player_->size_ = size; }
+
protected:
std::unique_ptr<MockWebMediaPlayer> web_media_player_;
std::unique_ptr<HtmlVideoElementCapturerSource> html_video_capturer_;
@@ -284,4 +287,48 @@ TEST_F(HTMLVideoElementCapturerSourceTest, AlphaAndNot) {
Mock::VerifyAndClearExpectations(this);
}
+// Verify that changes in the natural size of the source WebMediaPlayer do not
+// crash.
+// TODO(crbug.com/1817203): Verify that size changes are fully supported.
+TEST_F(HTMLVideoElementCapturerSourceTest, SizeChange) {
+ InSequence s;
+ media::VideoCaptureFormats formats =
+ html_video_capturer_->GetPreferredFormats();
+ media::VideoCaptureParams params;
+ params.requested_format = formats[0];
+
+ {
+ SetVideoPlayerSize(WebSize(16, 10));
+
+ base::RunLoop run_loop;
+ base::RepeatingClosure quit_closure = run_loop.QuitClosure();
+ scoped_refptr<media::VideoFrame> frame;
+ EXPECT_CALL(*this, DoOnRunning(true)).Times(1);
+ EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
+ .WillOnce(
+ DoAll(SaveArg<0>(&frame), RunClosure2(std::move(quit_closure))));
+ html_video_capturer_->StartCapture(
+ params,
+ WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame,
+ base::Unretained(this)),
+ WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning,
+ base::Unretained(this)));
+ run_loop.Run();
+ }
+ {
+ SetVideoPlayerSize(WebSize(32, 20));
+
+ base::RunLoop run_loop;
+ base::RepeatingClosure quit_closure = run_loop.QuitClosure();
+ scoped_refptr<media::VideoFrame> frame;
+ EXPECT_CALL(*this, DoOnDeliverFrame(_, _))
+ .WillOnce(
+ DoAll(SaveArg<0>(&frame), RunClosure2(std::move(quit_closure))));
+ run_loop.Run();
+ }
+
+ html_video_capturer_->StopCapture();
+ Mock::VerifyAndClearExpectations(this);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/DEPS b/chromium/third_party/blink/renderer/modules/mediarecorder/DEPS
index 2e96f7b831f..d7451d8d225 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/DEPS
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/DEPS
@@ -22,5 +22,6 @@ include_rules = [
specific_include_rules = {
".*_unittest.cc": [
"+base/run_loop.h",
+ "+ui/gfx/gpu_memory_buffer.h",
],
}
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 d8a87a0d3cc..48ff1e9cbd9 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
@@ -32,7 +32,7 @@ class Thread;
// which lives an AudioTrackEncoder with its own threading subtleties, see the
// implementation file.
class MODULES_EXPORT AudioTrackRecorder
- : public GarbageCollectedFinalized<AudioTrackRecorder>,
+ : public GarbageCollected<AudioTrackRecorder>,
public WebMediaStreamAudioSink {
USING_PRE_FINALIZER(AudioTrackRecorder, Prefinalize);
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/blob_event.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/blob_event.cc
index 44aafb7115b..106f651eeb9 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/blob_event.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/blob_event.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/modules/mediarecorder/blob_event.h"
+#include <cmath>
+
#include "third_party/blink/renderer/modules/mediarecorder/blob_event_init.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
namespace blink {
@@ -34,9 +35,7 @@ void BlobEvent::Trace(blink::Visitor* visitor) {
BlobEvent::BlobEvent(const AtomicString& type, const BlobEventInit* initializer)
: Event(type, initializer),
blob_(initializer->data()),
- timecode_(initializer->hasTimecode()
- ? initializer->timecode()
- : WTF::double_conversion::Double::NaN()) {}
+ timecode_(initializer->hasTimecode() ? initializer->timecode() : NAN) {}
BlobEvent::BlobEvent(const AtomicString& type, Blob* blob, double timecode)
: Event(type, Bubbles::kNo, Cancelable::kNo),
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
index 3764fbcf01f..add1b5c9aad 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
@@ -57,6 +57,9 @@ void H264Encoder::EncodeOnEncodingTaskRunner(
TRACE_EVENT0("media", "H264Encoder::EncodeOnEncodingTaskRunner");
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+ if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER)
+ frame = ConvertToI420ForSoftwareEncoder(frame);
+
const gfx::Size frame_size = frame->visible_rect().size();
if (!openh264_encoder_ || configured_size_ != frame_size) {
ConfigureEncoderOnEncodingTaskRunner(frame_size);
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 297295cbab7..9767c19a276 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,13 +16,13 @@
#include "media/base/video_codecs.h"
#include "media/base/video_frame.h"
#include "media/muxers/webm_muxer.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h"
#include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
#include "third_party/blink/renderer/modules/mediarecorder/buildflags.h"
#include "third_party/blink/renderer/modules/mediarecorder/media_recorder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#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/mediastream/media_stream_component.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
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 7c3da873a9c..1ebb7dbd574 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
@@ -42,9 +42,8 @@ struct WebMediaConfiguration;
// All methods are called on the same thread as construction and destruction,
// i.e. the Main Render thread. (Note that a BindToCurrentLoop is used to
// guarantee this, since VideoTrackRecorder sends back frames on IO thread.)
-class MODULES_EXPORT MediaRecorderHandler
- : public GarbageCollectedFinalized<MediaRecorderHandler> {
-
+class MODULES_EXPORT MediaRecorderHandler final
+ : public GarbageCollected<MediaRecorderHandler> {
public:
static MediaRecorderHandler* Create(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
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 8da2d01bc5e..38d5b4248a7 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.cc
@@ -41,6 +41,7 @@ scoped_refptr<VEAEncoder> VEAEncoder::Create(
int32_t bits_per_second,
media::VideoCodecProfile codec,
const gfx::Size& size,
+ bool use_native_input,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
auto encoder = base::AdoptRef(
new VEAEncoder(on_encoded_video_callback, on_error_callback,
@@ -48,7 +49,7 @@ scoped_refptr<VEAEncoder> VEAEncoder::Create(
PostCrossThreadTask(
*encoder->encoding_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner,
- encoder, size));
+ encoder, size, use_native_input));
return encoder;
}
@@ -186,8 +187,12 @@ void VEAEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
if (input_visible_size_ != frame->visible_rect().size() && video_encoder_)
video_encoder_.reset();
- if (!video_encoder_)
- ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size());
+ if (!video_encoder_) {
+ bool use_native_input =
+ frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER;
+ ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size(),
+ use_native_input);
+ }
if (error_notified_) {
DVLOG(3) << "An error occurred in VEA encoder";
@@ -214,13 +219,16 @@ void VEAEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
// Therefore, a copy is necessary to release the current frame.
// Only STORAGE_SHMEM backed frames can be shared with GPU process, therefore
// a copy is required for other storage types.
+ // With STORAGE_GPU_MEMORY_BUFFER we delay the scaling of the frame to the end
+ // of the encoding pipeline.
scoped_refptr<media::VideoFrame> video_frame = frame;
bool can_share_frame =
(video_frame->storage_type() == media::VideoFrame::STORAGE_SHMEM);
- if (!can_share_frame ||
- vea_requested_input_coded_size_ != frame->coded_size() ||
- input_visible_size_.width() < kVEAEncoderMinResolutionWidth ||
- input_visible_size_.height() < kVEAEncoderMinResolutionHeight) {
+ if (frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER &&
+ (!can_share_frame ||
+ vea_requested_input_coded_size_ != frame->coded_size() ||
+ input_visible_size_.width() < kVEAEncoderMinResolutionWidth ||
+ input_visible_size_.height() < kVEAEncoderMinResolutionHeight)) {
// Create SharedMemory backed input buffers as necessary. These SharedMemory
// instances will be shared with GPU process.
const size_t desired_mapped_size = media::VideoFrame::AllocationSize(
@@ -274,7 +282,8 @@ void VEAEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
force_next_frame_to_be_keyframe_ = false;
}
-void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
+void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size,
+ bool use_native_input) {
DVLOG(3) << __func__;
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
DCHECK(gpu_factories_->GetTaskRunner()->BelongsToCurrentThread());
@@ -283,8 +292,20 @@ void VEAEncoder::ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size) {
input_visible_size_ = size;
vea_requested_input_coded_size_ = gfx::Size();
video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
+
+ auto pixel_format = media::VideoPixelFormat::PIXEL_FORMAT_I420;
+ auto storage_type =
+ media::VideoEncodeAccelerator::Config::StorageType::kShmem;
+ if (use_native_input) {
+ // Currently the VAAPI and V4L2 VEA support only native input mode with NV12
+ // DMA-buf buffers.
+ pixel_format = media::PIXEL_FORMAT_NV12;
+ storage_type = media::VideoEncodeAccelerator::Config::StorageType::kDmabuf;
+ }
const media::VideoEncodeAccelerator::Config config(
- media::PIXEL_FORMAT_I420, input_visible_size_, codec_, bits_per_second_);
+ pixel_format, input_visible_size_, codec_, bits_per_second_,
+ base::nullopt, base::nullopt, base::nullopt, 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/mediarecorder/vea_encoder.h b/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.h
index 743ebe05623..e7f63b76f1e 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.h
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/vea_encoder.h
@@ -35,6 +35,7 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder,
int32_t bits_per_second,
media::VideoCodecProfile codec,
const gfx::Size& size,
+ bool use_native_input,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// media::VideoEncodeAccelerator::Client implementation.
@@ -73,7 +74,8 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder,
void EncodeOnEncodingTaskRunner(scoped_refptr<media::VideoFrame> frame,
base::TimeTicks capture_timestamp) override;
- void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size);
+ void ConfigureEncoderOnEncodingTaskRunner(const gfx::Size& size,
+ bool use_native_input);
void DestroyOnEncodingTaskRunner(base::WaitableEvent* async_waiter = nullptr);
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
index c84797f978b..e0b291a0080 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -125,6 +125,8 @@ VideoTrackRecorder::CodecEnumerator::CodecEnumerator(
if (codec >= codec_id_and_profile.min_profile &&
codec <= codec_id_and_profile.max_profile) {
DVLOG(2) << "Accelerated codec found: " << media::GetProfileName(codec)
+ << ", min_resolution: "
+ << supported_profile.min_resolution.ToString()
<< ", max_resolution: "
<< supported_profile.max_resolution.ToString()
<< ", max_framerate: "
@@ -243,7 +245,9 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
return;
}
- if (video_frame->HasTextures()) {
+ if (video_frame->HasTextures() &&
+ video_frame->storage_type() !=
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
PostCrossThreadTask(
*main_task_runner_.get(), FROM_HERE,
CrossThreadBindOnce(&Encoder::RetrieveFrameOnMainThread,
@@ -253,28 +257,27 @@ void VideoTrackRecorder::Encoder::StartFrameEncode(
return;
}
- scoped_refptr<media::VideoFrame> wrapped_frame;
- // Drop alpha channel if the encoder does not support it yet.
- if (!CanEncodeAlphaChannel() &&
- video_frame->format() == media::PIXEL_FORMAT_I420A) {
- wrapped_frame = media::WrapAsI420VideoFrame(video_frame);
- } else {
- wrapped_frame = media::VideoFrame::WrapVideoFrame(
- *video_frame, video_frame->format(), video_frame->visible_rect(),
- video_frame->natural_size());
+ scoped_refptr<media::VideoFrame> frame = video_frame;
+ if (frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ // Drop alpha channel if the encoder does not support it yet.
+ if (!CanEncodeAlphaChannel() &&
+ video_frame->format() == media::PIXEL_FORMAT_I420A) {
+ frame = media::WrapAsI420VideoFrame(video_frame);
+ } else {
+ frame = media::VideoFrame::WrapVideoFrame(
+ video_frame, video_frame->format(), video_frame->visible_rect(),
+ video_frame->natural_size());
+ }
}
- wrapped_frame->AddDestructionObserver(media::BindToCurrentLoop(
+ frame->AddDestructionObserver(media::BindToCurrentLoop(
WTF::Bind(&VideoTrackRecorder::Counter::DecreaseCount,
num_frames_in_encode_->GetWeakPtr())));
- wrapped_frame->AddDestructionObserver(ConvertToBaseOnceCallback(
- CrossThreadBindOnce([](scoped_refptr<VideoFrame> video_frame) {},
- std::move(video_frame))));
num_frames_in_encode_->IncreaseCount();
- PostCrossThreadTask(*encoding_task_runner_.get(), FROM_HERE,
- CrossThreadBindOnce(&Encoder::EncodeOnEncodingTaskRunner,
- WrapRefCounted(this), wrapped_frame,
- capture_timestamp));
+ PostCrossThreadTask(
+ *encoding_task_runner_.get(), FROM_HERE,
+ CrossThreadBindOnce(&Encoder::EncodeOnEncodingTaskRunner,
+ WrapRefCounted(this), frame, capture_timestamp));
}
void VideoTrackRecorder::Encoder::RetrieveFrameOnMainThread(
@@ -393,6 +396,37 @@ bool VideoTrackRecorder::Encoder::CanEncodeAlphaChannel() {
}
// static
+scoped_refptr<media::VideoFrame>
+VideoTrackRecorder::Encoder::ConvertToI420ForSoftwareEncoder(
+ scoped_refptr<media::VideoFrame> frame) {
+ DCHECK_EQ(frame->storage_type(),
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
+ // NV12 is currently the only supported pixel format for GpuMemoryBuffer.
+ DCHECK_EQ(frame->format(), media::VideoPixelFormat::PIXEL_FORMAT_NV12);
+
+ auto* gmb = frame->GetGpuMemoryBuffer();
+ if (!gmb->Map())
+ return frame;
+ scoped_refptr<media::VideoFrame> i420_frame = media::VideoFrame::CreateFrame(
+ media::VideoPixelFormat::PIXEL_FORMAT_I420, frame->coded_size(),
+ frame->visible_rect(), frame->natural_size(), frame->timestamp());
+ auto ret = libyuv::NV12ToI420(
+ static_cast<const uint8_t*>(gmb->memory(0)), gmb->stride(0),
+ static_cast<const uint8_t*>(gmb->memory(1)), gmb->stride(1),
+ i420_frame->data(media::VideoFrame::kYPlane),
+ i420_frame->stride(media::VideoFrame::kYPlane),
+ i420_frame->data(media::VideoFrame::kUPlane),
+ i420_frame->stride(media::VideoFrame::kUPlane),
+ i420_frame->data(media::VideoFrame::kVPlane),
+ i420_frame->stride(media::VideoFrame::kVPlane),
+ frame->coded_size().width(), frame->coded_size().height());
+ gmb->Unmap();
+ if (ret)
+ return frame;
+ return i420_frame;
+}
+
+// static
VideoTrackRecorder::CodecId VideoTrackRecorder::GetPreferredCodecId() {
return GetCodecEnumerator()->GetPreferredCodecId();
}
@@ -413,16 +447,20 @@ bool VideoTrackRecorder::CanUseAcceleratedEncoder(CodecId codec,
if (profile.profile == media::VIDEO_CODEC_PROFILE_UNKNOWN)
return false;
+ const gfx::Size& min_resolution = profile.min_resolution;
+ const size_t min_width = static_cast<size_t>(
+ std::max(kVEAEncoderMinResolutionWidth, min_resolution.width()));
+ const size_t min_height = static_cast<size_t>(
+ std::max(kVEAEncoderMinResolutionHeight, min_resolution.height()));
+
const gfx::Size& max_resolution = profile.max_resolution;
DCHECK_GE(max_resolution.width(), 0);
const size_t max_width = static_cast<size_t>(max_resolution.width());
DCHECK_GE(max_resolution.height(), 0);
const size_t max_height = static_cast<size_t>(max_resolution.height());
- const bool width_within_range =
- max_width >= width && width >= kVEAEncoderMinResolutionWidth;
- const bool height_within_range =
- max_height >= height && height >= kVEAEncoderMinResolutionHeight;
+ const bool width_within_range = max_width >= width && width >= min_width;
+ const bool height_within_range = max_height >= height && height >= min_height;
const bool valid_framerate = framerate * profile.max_framerate_denominator <=
profile.max_framerate_numerator;
return width_within_range && height_within_range && valid_framerate;
@@ -505,11 +543,14 @@ void VideoTrackRecorder::InitializeEncoder(
UMA_HISTOGRAM_BOOLEAN("Media.MediaRecorder.VEAUsed", true);
const auto vea_profile =
GetCodecEnumerator()->GetFirstSupportedVideoCodecProfile(codec);
+ bool use_import_mode =
+ frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER;
encoder_ = VEAEncoder::Create(
on_encoded_video_callback,
media::BindToCurrentLoop(WTF::BindRepeating(
&VideoTrackRecorder::OnError, WrapWeakPersistent(this))),
- bits_per_second, vea_profile, input_size, main_task_runner_);
+ bits_per_second, vea_profile, input_size, use_import_mode,
+ main_task_runner_);
} else {
UMA_HISTOGRAM_BOOLEAN("Media.MediaRecorder.VEAUsed", false);
switch (codec) {
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
index c12dbbf4f01..a55085d7622 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.h
@@ -73,7 +73,7 @@ class Thread;
// thread but that pass frames on Render IO thread. It has an internal Encoder
// with its own threading subtleties, see the implementation file.
class MODULES_EXPORT VideoTrackRecorder
- : public GarbageCollectedFinalized<VideoTrackRecorder>,
+ : public GarbageCollected<VideoTrackRecorder>,
public WebMediaStreamSink {
USING_PRE_FINALIZER(VideoTrackRecorder, Prefinalize);
@@ -184,6 +184,13 @@ class MODULES_EXPORT VideoTrackRecorder
// Called when the frame reference is released after encode.
void FrameReleased(scoped_refptr<media::VideoFrame> frame);
+ // A helper function to convert the given |frame| to an I420 video frame.
+ // Used mainly by the software encoders since I420 is the only supported
+ // pixel format. The function is best-effort. If for any reason the
+ // conversion fails, the original |frame| will be returned.
+ static scoped_refptr<media::VideoFrame> ConvertToI420ForSoftwareEncoder(
+ scoped_refptr<media::VideoFrame> frame);
+
// Used to shutdown properly on the same thread we were created.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
index 68a2f2f42b8..797704c1e44 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
@@ -19,8 +19,10 @@
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/mediarecorder/buildflags.h"
#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "ui/gfx/gpu_memory_buffer.h"
using media::VideoFrame;
using video_track_recorder::kVEAEncoderMinResolutionHeight;
@@ -54,11 +56,16 @@ const gfx::Size kTrackRecorderTestSize[] = {
gfx::Size(kVEAEncoderMinResolutionWidth / 2,
kVEAEncoderMinResolutionHeight / 2),
gfx::Size(kVEAEncoderMinResolutionWidth, kVEAEncoderMinResolutionHeight)};
+const media::VideoFrame::StorageType kStorageTypeToTest[] = {
+ media::VideoFrame::STORAGE_OWNED_MEMORY,
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER};
static const int kTrackRecorderTestSizeDiff = 20;
class VideoTrackRecorderTest
- : public TestWithParam<
- testing::tuple<VideoTrackRecorder::CodecId, gfx::Size, bool>> {
+ : public TestWithParam<testing::tuple<VideoTrackRecorder::CodecId,
+ gfx::Size,
+ bool,
+ media::VideoFrame::StorageType>> {
public:
VideoTrackRecorderTest() : mock_source_(new MockMediaStreamVideoSource()) {
const WebString webkit_track_id(WebString::FromASCII("dummy"));
@@ -162,9 +169,52 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) {
const bool encode_alpha_channel = testing::get<2>(GetParam());
// |frame_size| cannot be arbitrarily small, should be reasonable.
const gfx::Size& frame_size = testing::get<1>(GetParam());
+ const media::VideoFrame::StorageType storage_type =
+ testing::get<3>(GetParam());
+
+ // We don't support alpha channel with GpuMemoryBuffer frames.
+ if (storage_type == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER &&
+ encode_alpha_channel) {
+ return;
+ }
+
+ auto create_test_frame =
+ [](media::VideoFrame::StorageType storage_type,
+ const gfx::Size& frame_size,
+ bool encode_alpha_channel) -> scoped_refptr<VideoFrame> {
+ scoped_refptr<VideoFrame> video_frame;
+ switch (storage_type) {
+ case media::VideoFrame::STORAGE_OWNED_MEMORY:
+ video_frame = encode_alpha_channel
+ ? VideoFrame::CreateTransparentFrame(frame_size)
+ : VideoFrame::CreateBlackFrame(frame_size);
+ break;
+ case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER: {
+ video_frame = CreateTestFrame(frame_size, gfx::Rect(frame_size),
+ frame_size, storage_type);
+ // Create a black NV12 frame.
+ auto* gmb = video_frame->GetGpuMemoryBuffer();
+ gmb->Map();
+ const uint8_t kBlackY = 0x00;
+ const uint8_t kBlackUV = 0x80;
+ memset(static_cast<uint8_t*>(gmb->memory(0)), kBlackY,
+ gmb->stride(0) * frame_size.height());
+ memset(static_cast<uint8_t*>(gmb->memory(1)), kBlackUV,
+ gmb->stride(1) * (frame_size.height() / 2));
+ gmb->Unmap();
+ break;
+ }
+ default:
+ DLOG(ERROR) << "Unexpected storage type";
+ }
+ return video_frame;
+ };
+
const scoped_refptr<VideoFrame> video_frame =
- encode_alpha_channel ? VideoFrame::CreateTransparentFrame(frame_size)
- : VideoFrame::CreateBlackFrame(frame_size);
+ create_test_frame(storage_type, frame_size, encode_alpha_channel);
+ if (!video_frame)
+ ASSERT_TRUE(!!video_frame);
+
const double kFrameRate = 60.0f;
video_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
kFrameRate);
@@ -193,8 +243,7 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) {
const gfx::Size frame_size2(frame_size.width() + kTrackRecorderTestSizeDiff,
frame_size.height());
const scoped_refptr<VideoFrame> video_frame2 =
- encode_alpha_channel ? VideoFrame::CreateTransparentFrame(frame_size2)
- : VideoFrame::CreateBlackFrame(frame_size2);
+ create_test_frame(storage_type, frame_size2, encode_alpha_channel);
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
@@ -215,7 +264,9 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) {
EXPECT_GE(second_frame_encoded_data.size(), kEncodedSizeThreshold);
EXPECT_GE(third_frame_encoded_data.size(), kEncodedSizeThreshold);
- if (encode_alpha_channel && CanEncodeAlphaChannel()) {
+ // We only support NV12 with GpuMemoryBuffer video frame.
+ if (storage_type != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER &&
+ encode_alpha_channel && CanEncodeAlphaChannel()) {
EXPECT_GE(first_frame_encoded_alpha.size(), kEncodedSizeThreshold);
EXPECT_GE(second_frame_encoded_alpha.size(), kEncodedSizeThreshold);
EXPECT_GE(third_frame_encoded_alpha.size(), kEncodedSizeThreshold);
@@ -236,12 +287,24 @@ TEST_P(VideoTrackRecorderTest, EncodeFrameWithPaddedCodedSize) {
const gfx::Size& frame_size = testing::get<1>(GetParam());
const size_t kCodedSizePadding = 16;
- const scoped_refptr<VideoFrame> video_frame =
- VideoFrame::CreateZeroInitializedFrame(
- media::PIXEL_FORMAT_I420,
- gfx::Size(frame_size.width() + kCodedSizePadding,
- frame_size.height()),
- gfx::Rect(frame_size), frame_size, base::TimeDelta());
+ const media::VideoFrame::StorageType storage_type =
+ testing::get<3>(GetParam());
+ const gfx::Size padded_size(frame_size.width() + kCodedSizePadding,
+ frame_size.height());
+ scoped_refptr<VideoFrame> video_frame;
+ switch (storage_type) {
+ case media::VideoFrame::STORAGE_OWNED_MEMORY:
+ video_frame = VideoFrame::CreateZeroInitializedFrame(
+ media::PIXEL_FORMAT_I420, padded_size, gfx::Rect(frame_size),
+ frame_size, base::TimeDelta());
+ break;
+ case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER:
+ video_frame = CreateTestFrame(padded_size, gfx::Rect(frame_size),
+ frame_size, storage_type);
+ break;
+ default:
+ NOTREACHED() << "Unexpected storage type";
+ }
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
@@ -354,7 +417,8 @@ INSTANTIATE_TEST_SUITE_P(,
VideoTrackRecorderTest,
::testing::Combine(ValuesIn(kTrackRecorderTestCodec),
ValuesIn(kTrackRecorderTestSize),
- ::testing::Bool()));
+ ::testing::Bool(),
+ ValuesIn(kStorageTypeToTest)));
class CodecEnumeratorTest : public ::testing::Test {
public:
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
index 5d1afe33d5a..57fca1b3a68 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/vpx_encoder.cc
@@ -72,6 +72,9 @@ void VpxEncoder::EncodeOnEncodingTaskRunner(scoped_refptr<VideoFrame> frame,
TRACE_EVENT0("media", "VpxEncoder::EncodeOnEncodingTaskRunner");
DCHECK(encoding_task_runner_->BelongsToCurrentThread());
+ if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER)
+ frame = ConvertToI420ForSoftwareEncoder(frame);
+
const gfx::Size frame_size = frame->visible_rect().size();
base::TimeDelta duration = EstimateFrameDuration(*frame);
const media::WebmMuxer::VideoParameters video_params(frame);
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
index 44637c4fafa..999d75d511c 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h"
+#include "third_party/blink/public/mojom/mediasession/media_session.mojom-blink.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h
index 28c0d454a6c..ac3300b91bf 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASESSION_MEDIA_METADATA_SANITIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASESSION_MEDIA_METADATA_SANITIZER_H_
-#include "third_party/blink/public/mojom/mediasession/media_session.mojom-blink.h"
+#include "third_party/blink/public/mojom/mediasession/media_session.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
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 f194a6404cd..bd6d83f5184 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -6,7 +6,7 @@
#include <memory>
#include "base/optional.h"
-#include "services/service_manager/public/cpp/interface_provider.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/bindings/modules/v8/v8_media_session_action_handler.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -320,7 +320,7 @@ mojom::blink::MediaSessionService* MediaSession::GetService() {
// See https://bit.ly/2S0zRAS for task types.
auto task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- frame->GetInterfaceProvider().GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver());
if (service_.get()) {
// Record the eTLD+1 of the frame using the API.
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 045b6a0ae29..9e24dab598b 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -533,10 +533,6 @@ WebTimeRanges MediaSource::SeekableInternal() const {
return ranges;
}
-TimeRanges* MediaSource::Seekable() const {
- return MakeGarbageCollected<TimeRanges>(SeekableInternal());
-}
-
void MediaSource::OnTrackChanged(TrackBase* track) {
DCHECK(HTMLMediaElement::MediaTracksEnabledInternally());
SourceBuffer* source_buffer =
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 09e586748cd..de8973e436c 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -102,7 +102,6 @@ class MediaSource final : public EventTargetWithInlineData,
WebTimeRanges BufferedInternal() const override;
WebTimeRanges SeekableInternal() const override;
TimeRanges* Buffered() const override;
- TimeRanges* Seekable() const override;
void OnTrackChanged(TrackBase*) override;
// EventTarget interface
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 c74de365208..e6e82edff11 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -1149,6 +1149,16 @@ void SourceBuffer::NotifyParseWarning(const ParseWarning warning) {
UseCounter::Count(source_->MediaElement()->GetDocument(),
WebFeature::kMediaSourceMuxedSequenceMode);
break;
+ case WebSourceBufferClient::kGroupEndTimestampDecreaseWithinMediaSegment:
+ // Report this problematic Media Segment structure usage to help inform
+ // follow-up work.
+ // TODO(wolenetz): Use the data to scope additional work. See
+ // https://crbug.com/920853 and
+ // https://github.com/w3c/media-source/issues/203.
+ UseCounter::Count(
+ source_->MediaElement()->GetDocument(),
+ WebFeature::kMediaSourceGroupEndTimestampDecreaseWithinMediaSegment);
+ break;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc b/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
index 46283ee2c13..c9373a99ad3 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
@@ -29,7 +29,7 @@ const AtomicString& TrackDefault::TextKeyword() {
}
ScriptValue TrackDefault::kinds(ScriptState* script_state) const {
- return ScriptValue(script_state, ToV8(kinds_, script_state));
+ return ScriptValue(script_state->GetIsolate(), ToV8(kinds_, script_state));
}
TrackDefault* TrackDefault::Create(const AtomicString& type,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn b/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
index f33987b6828..dbc9febb592 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/jumbo.gni")
+import("//media/webrtc/audio_processing.gni")
import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("mediastream") {
@@ -89,6 +90,7 @@ blink_modules_sources("mediastream") {
]
deps = [
"//media/capture/mojom:image_capture_blink",
+ "//media/webrtc",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/DEPS b/chromium/third_party/blink/renderer/modules/mediastream/DEPS
index 5ec9ce3d062..59774da88d5 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/DEPS
+++ b/chromium/third_party/blink/renderer/modules/mediastream/DEPS
@@ -61,5 +61,8 @@ specific_include_rules = {
"+base/files/scoped_temp_dir.h",
"+base/memory/aligned_memory.h",
"+base/path_service.h",
+ "+base/test/bind_test_util.h",
+ "+base/threading/thread.h",
+ "+third_party/blink/renderer/platform/testing/video_frame_utils.h",
],
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
index 1af65160117..e4b9a61ab06 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.cc
@@ -8,6 +8,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
@@ -349,7 +350,7 @@ void ApplyConstraintsProcessor::CleanupRequest(
video_source_ = nullptr;
}
-const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
+blink::mojom::blink::MediaDevicesDispatcherHost*
ApplyConstraintsProcessor::GetMediaDevicesDispatcher() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return media_devices_dispatcher_cb_.Run();
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.h b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.h
index 96933f41210..49c9dd49232 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_processor.h
@@ -10,7 +10,8 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "media/capture/video_capture_types.h"
-#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink-forward.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
#include "third_party/blink/renderer/modules/mediastream/apply_constraints_request.h"
@@ -26,11 +27,11 @@ class MediaStreamVideoTrack;
// requests. Only one applyConstraints() request can be processed at a time.
// ApplyConstraintsProcessor must be created, called and destroyed on the main
// render thread. There should be only one ApplyConstraintsProcessor per frame.
-class MODULES_EXPORT ApplyConstraintsProcessor
- : public GarbageCollectedFinalized<ApplyConstraintsProcessor> {
+class MODULES_EXPORT ApplyConstraintsProcessor final
+ : public GarbageCollected<ApplyConstraintsProcessor> {
public:
using MediaDevicesDispatcherCallback = base::RepeatingCallback<
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&()>;
+ blink::mojom::blink::MediaDevicesDispatcherHost*()>;
ApplyConstraintsProcessor(
MediaDevicesDispatcherCallback media_devices_dispatcher_cb,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
@@ -75,8 +76,7 @@ class MODULES_EXPORT ApplyConstraintsProcessor
void ApplyConstraintsFailed(const char* failed_constraint_name);
void CannotApplyConstraints(const String& message);
void CleanupRequest(base::OnceClosure web_request_callback);
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
- GetMediaDevicesDispatcher();
+ blink::mojom::blink::MediaDevicesDispatcherHost* GetMediaDevicesDispatcher();
// ApplyConstraints requests are processed sequentially. |current_request_|
// contains the request currently being processed, if any.
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_request.h b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_request.h
index ab728233c37..798e4032f04 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_request.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/apply_constraints_request.h
@@ -16,7 +16,7 @@ namespace blink {
class ScriptPromiseResolver;
class MODULES_EXPORT ApplyConstraintsRequest final
- : public GarbageCollectedFinalized<ApplyConstraintsRequest> {
+ : public GarbageCollected<ApplyConstraintsRequest> {
public:
static ApplyConstraintsRequest* CreateForTesting(const WebMediaStreamTrack&,
const WebMediaConstraints&);
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 cf2b6e5dab4..77403396b62 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
@@ -8,6 +8,7 @@
#include "build/build_config.h"
#include "media/base/sample_format.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.cc
index bddcf8cca3f..fa1f3dd489f 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_device_info.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.h b/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.h
index a2f807ee08c..4b47acf6150 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_device_info.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_DEVICE_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_DEVICE_INFO_H_
-#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink-forward.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/heap_allocator.h"
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 4ea5988ca47..faaaf763bb5 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -7,8 +7,8 @@
#include <utility>
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -64,7 +64,7 @@ MediaDevices::MediaDevices(ExecutionContext* context)
MediaDevices::~MediaDevices() = default;
ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
- Platform::Current()->UpdateWebRTCAPICount(WebRTCAPIName::kEnumerateDevices);
+ UpdateWebRTCMethodCount(WebRTCAPIName::kEnumerateDevices);
LocalFrame* frame =
To<Document>(ExecutionContext::From(script_state))->GetFrame();
if (!frame) {
@@ -346,7 +346,7 @@ void MediaDevices::OnDispatcherHostConnectionError() {
const mojo::Remote<mojom::blink::MediaDevicesDispatcherHost>&
MediaDevices::GetDispatcherHost(LocalFrame* frame) {
if (!dispatcher_host_) {
- frame->GetInterfaceProvider().GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
dispatcher_host_.BindNewPipeAndPassReceiver());
dispatcher_host_.set_disconnect_handler(
WTF::Bind(&MediaDevices::OnDispatcherHostConnectionError,
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 0147fb818e3..287276312cb 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
@@ -179,6 +179,7 @@ class PromiseObserver {
bool isFulfilled() { return is_fulfilled_; }
bool isRejected() { return is_rejected_; }
ScriptValue argument() { return saved_arg_; }
+ void Trace(blink::Visitor* visitor) { visitor->Trace(saved_arg_); }
private:
class MyScriptFunction : public ScriptFunction {
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 24499bd1a0c..3bf00e9d36a 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
@@ -134,13 +134,13 @@ VideoCaptureSettings::VideoCaptureSettings(
VideoCaptureSettings::VideoCaptureSettings(const VideoCaptureSettings& other) =
default;
-VideoCaptureSettings::VideoCaptureSettings(
- VideoCaptureSettings&& other) noexcept = default;
+VideoCaptureSettings::VideoCaptureSettings(VideoCaptureSettings&& other) =
+ default;
VideoCaptureSettings::~VideoCaptureSettings() = default;
VideoCaptureSettings& VideoCaptureSettings::operator=(
const VideoCaptureSettings& other) = default;
VideoCaptureSettings& VideoCaptureSettings::operator=(
- VideoCaptureSettings&& other) noexcept = default;
+ VideoCaptureSettings&& other) = default;
AudioCaptureSettings::AudioCaptureSettings() : AudioCaptureSettings("") {}
@@ -166,10 +166,10 @@ AudioCaptureSettings::AudioCaptureSettings(const AudioCaptureSettings& other) =
default;
AudioCaptureSettings& AudioCaptureSettings::operator=(
const AudioCaptureSettings& other) = default;
-AudioCaptureSettings::AudioCaptureSettings(
- AudioCaptureSettings&& other) noexcept = default;
+AudioCaptureSettings::AudioCaptureSettings(AudioCaptureSettings&& other) =
+ default;
AudioCaptureSettings& AudioCaptureSettings::operator=(
- AudioCaptureSettings&& other) noexcept = default;
+ AudioCaptureSettings&& other) = default;
bool GetConstraintValueAsBoolean(
const WebMediaConstraints& constraints,
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 f2884c59e50..1a2a3bdf292 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
@@ -16,6 +16,7 @@
#include "media/audio/audio_features.h"
#include "media/base/audio_parameters.h"
#include "media/base/limits.h"
+#include "media/webrtc/webrtc_switches.h"
#include "third_party/blink/public/common/mediastream/media_stream_controls.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h"
#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
@@ -1011,7 +1012,7 @@ class DeviceContainer {
}
if (is_reconfiguration_allowed || source_info.type() == SourceType::kNone ||
source_info.type() == SourceType::kApmProcessed) {
- if (IsApmInAudioServiceEnabled()) {
+ if (media::IsWebRtcApmInAudioServiceEnabled()) {
processing_based_containers_.push_back(
ProcessingBasedContainer::CreateRemoteApmProcessedContainer(
source_info, is_device_capture, device_parameters_,
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 e5605bb8797..e062b237394 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
@@ -34,22 +34,6 @@ using blink::AudioCaptureSettings;
using blink::AudioProcessingProperties;
using EchoCancellationType = AudioProcessingProperties::EchoCancellationType;
-// Test blink::Platform imlementation that overrides the known methods needed
-// by the tests, including creation of WebRtcAudioDevice instances.
-class WebRtcAudioDeviceTestingPlatformSupport
- : public IOTaskRunnerTestingPlatformSupport {
- public:
- WebRtcAudioDeviceTestingPlatformSupport()
- : webrtc_audio_device_(
- new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()) {}
- blink::WebRtcAudioDeviceImpl* GetWebRtcAudioDevice() override {
- return webrtc_audio_device_.get();
- }
-
- private:
- scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device_;
-};
-
namespace {
using BoolSetFunction = void (blink::BooleanConstraint::*)(bool);
@@ -450,8 +434,7 @@ class MediaStreamConstraintsUtilAudioTestBase {
blink::WebString::FromASCII("system")};
private:
- ScopedTestingPlatformSupport<WebRtcAudioDeviceTestingPlatformSupport>
- platform_;
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
};
class MediaStreamConstraintsUtilAudioTest
@@ -1916,7 +1899,7 @@ TEST_P(MediaStreamConstraintsRemoteAPMTest, Channels) {
constraint_factory_.basic().echo_cancellation.SetExact(true);
result = SelectSettings();
- if (IsApmInAudioServiceEnabled() && GetParam())
+ if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
EXPECT_FALSE(result.HasValue());
else
EXPECT_TRUE(result.HasValue());
@@ -1933,7 +1916,7 @@ TEST_P(MediaStreamConstraintsRemoteAPMTest, SampleRate) {
constraint_factory_.basic().echo_cancellation.SetExact(true);
result = SelectSettings();
- if (IsApmInAudioServiceEnabled() && GetParam())
+ if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
EXPECT_TRUE(result.HasValue());
else
EXPECT_FALSE(result.HasValue());
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
index 96992217b9c..67c8babd6f2 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
@@ -529,9 +529,9 @@ VideoInputDeviceCapabilities::VideoInputDeviceCapabilities(
facing_mode(facing_mode) {}
VideoInputDeviceCapabilities::VideoInputDeviceCapabilities(
- VideoInputDeviceCapabilities&& other) noexcept = default;
+ VideoInputDeviceCapabilities&& other) = default;
VideoInputDeviceCapabilities& VideoInputDeviceCapabilities::operator=(
- VideoInputDeviceCapabilities&& other) noexcept = default;
+ VideoInputDeviceCapabilities&& other) = default;
VideoInputDeviceCapabilities::~VideoInputDeviceCapabilities() = default;
@@ -557,10 +557,10 @@ WebMediaStreamTrack::FacingMode ToWebFacingMode(
VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities() = default;
VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities(
- VideoDeviceCaptureCapabilities&& other) noexcept = default;
+ VideoDeviceCaptureCapabilities&& other) = default;
VideoDeviceCaptureCapabilities::~VideoDeviceCaptureCapabilities() = default;
VideoDeviceCaptureCapabilities& VideoDeviceCaptureCapabilities::operator=(
- VideoDeviceCaptureCapabilities&& other) noexcept = default;
+ VideoDeviceCaptureCapabilities&& other) = default;
VideoCaptureSettings SelectSettingsVideoDeviceCapture(
const VideoDeviceCaptureCapabilities& capabilities,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
index 66ae103f079..94d8ed9616a 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.h
@@ -34,9 +34,8 @@ struct MODULES_EXPORT VideoInputDeviceCapabilities {
Vector<media::VideoCaptureFormat> formats,
media::VideoFacingMode facing_mode);
VideoInputDeviceCapabilities();
- VideoInputDeviceCapabilities(VideoInputDeviceCapabilities&& other) noexcept;
- VideoInputDeviceCapabilities& operator=(
- VideoInputDeviceCapabilities&& other) noexcept;
+ VideoInputDeviceCapabilities(VideoInputDeviceCapabilities&& other);
+ VideoInputDeviceCapabilities& operator=(VideoInputDeviceCapabilities&& other);
~VideoInputDeviceCapabilities();
String device_id;
@@ -47,11 +46,10 @@ struct MODULES_EXPORT VideoInputDeviceCapabilities {
struct MODULES_EXPORT VideoDeviceCaptureCapabilities {
VideoDeviceCaptureCapabilities();
- VideoDeviceCaptureCapabilities(
- VideoDeviceCaptureCapabilities&& other) noexcept;
+ VideoDeviceCaptureCapabilities(VideoDeviceCaptureCapabilities&& other);
~VideoDeviceCaptureCapabilities();
VideoDeviceCaptureCapabilities& operator=(
- VideoDeviceCaptureCapabilities&& other) noexcept;
+ VideoDeviceCaptureCapabilities&& other);
// Each capabilities field is independent of each other.
// TODO(crbug.com/704136): Replace VideoInputDeviceCapabilities in the
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
index 9c372261685..0ff66af2433 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.cc
@@ -49,7 +49,7 @@ MediaStreamDeviceObserver::MediaStreamDeviceObserver(WebLocalFrame* frame) {
static_cast<LocalFrame*>(WebFrame::ToCoreFrame(*frame))
->GetInterfaceRegistry()
->AddInterface(WTF::BindRepeating(
- &MediaStreamDeviceObserver::BindMediaStreamDeviceObserverRequest,
+ &MediaStreamDeviceObserver::BindMediaStreamDeviceObserverReceiver,
WTF::Unretained(this)));
}
@@ -133,7 +133,7 @@ void MediaStreamDeviceObserver::OnDeviceChanged(
}
}
-void MediaStreamDeviceObserver::BindMediaStreamDeviceObserverRequest(
+void MediaStreamDeviceObserver::BindMediaStreamDeviceObserverReceiver(
mojo::PendingReceiver<mojom::blink::MediaStreamDeviceObserver> receiver) {
receiver_.Bind(std::move(receiver));
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
index b79f3e4b306..cf4477650a1 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
@@ -75,7 +76,7 @@ class MODULES_EXPORT MediaStreamDeviceObserver
const MediaStreamDevice& old_device,
const MediaStreamDevice& new_device) override;
- void BindMediaStreamDeviceObserverRequest(
+ void BindMediaStreamDeviceObserverReceiver(
mojo::PendingReceiver<mojom::blink::MediaStreamDeviceObserver> receiver);
mojo::Receiver<mojom::blink::MediaStreamDeviceObserver> receiver_{this};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
index fdab8d44177..5b43153396e 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/public/web/modules/webrtc/webrtc_audio_device_impl.h"
#include "third_party/blink/public/web/modules/webrtc/webrtc_audio_renderer.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -32,7 +33,7 @@ namespace {
// will not be able to pick an appropriate device and return 0.
base::UnguessableToken GetSessionIdForWebRtcAudioRenderer() {
WebRtcAudioDeviceImpl* audio_device =
- Platform::Current()->GetWebRtcAudioDevice();
+ PeerConnectionDependencyFactory::GetInstance()->GetWebRtcAudioDevice();
return audio_device
? audio_device->GetAuthorizedDeviceSessionIdForAudioRenderer()
: base::UnguessableToken();
@@ -117,7 +118,7 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
// This is a remote WebRTC media stream.
WebRtcAudioDeviceImpl* audio_device =
- Platform::Current()->GetWebRtcAudioDevice();
+ PeerConnectionDependencyFactory::GetInstance()->GetWebRtcAudioDevice();
DCHECK(audio_device);
// Share the existing renderer if any, otherwise create a new one.
@@ -128,8 +129,10 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
DVLOG(1) << "Creating WebRtcAudioRenderer for remote WebRTC track.";
renderer = new WebRtcAudioRenderer(
- Platform::Current()->GetWebRtcSignalingTaskRunner(), web_stream,
- web_frame, GetSessionIdForWebRtcAudioRenderer(), device_id.Utf8());
+ PeerConnectionDependencyFactory::GetInstance()
+ ->GetWebRtcSignalingTaskRunner(),
+ web_stream, web_frame, GetSessionIdForWebRtcAudioRenderer(),
+ device_id.Utf8());
if (!audio_device->SetAudioRenderer(renderer.get())) {
WebRtcLogMessage("Error: SetAudioRenderer failed for remote track.");
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 ebc845f2ca6..3305239635b 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
@@ -7,7 +7,7 @@
#include <utility>
#include "media/capture/video_capturer_source.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -210,7 +210,7 @@ mojom::blink::MediaStreamDispatcherHost*
MediaStreamVideoCapturerSource::GetMediaStreamDispatcherHost() {
DCHECK(frame_);
if (!host_) {
- frame_->GetInterfaceProvider().GetInterface(
+ frame_->GetBrowserInterfaceBroker().GetInterface(
host_.BindNewPipeAndPassReceiver());
}
return host_.get();
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 eeef014b9ad..d0e7e2d3908 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
@@ -83,6 +83,9 @@ class MediaStreamVideoRendererSink::FrameDeliverer {
media::VideoFrame::CreateBlackFrame(
state_ == STOPPED ? gfx::Size(kMinFrameSize, kMinFrameSize)
: frame_size_);
+ if (!video_frame)
+ return;
+
video_frame->metadata()->SetBoolean(
media::VideoFrameMetadata::END_OF_STREAM, true);
video_frame->metadata()->SetTimeTicks(
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 7651e4761a6..99759c1041b 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
@@ -461,10 +461,10 @@ MediaStreamVideoSource::PendingTrackInfo::PendingTrackInfo(
callback(callback) {}
MediaStreamVideoSource::PendingTrackInfo::PendingTrackInfo(
- PendingTrackInfo&& other) noexcept = default;
+ PendingTrackInfo&& other) = default;
MediaStreamVideoSource::PendingTrackInfo&
MediaStreamVideoSource::PendingTrackInfo::operator=(
- MediaStreamVideoSource::PendingTrackInfo&& other) noexcept = default;
+ MediaStreamVideoSource::PendingTrackInfo&& other) = default;
MediaStreamVideoSource::PendingTrackInfo::~PendingTrackInfo() {}
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 8508564ede1..676dacd7faf 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
@@ -35,10 +35,6 @@ void ResetCallback(
// |callback| will be deleted when this exits.
}
-// Empty method used for keeping a reference to the original media::VideoFrame.
-// The reference to |frame| is kept in the closure that calls this method.
-void ReleaseOriginalFrame(scoped_refptr<media::VideoFrame> frame) {}
-
} // namespace
// MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering
@@ -230,13 +226,11 @@ MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
// Wrap |black_frame_| so we get a fresh timestamp we can modify. Frames
// returned from this function may still be in use.
scoped_refptr<media::VideoFrame> wrapped_black_frame =
- media::VideoFrame::WrapVideoFrame(*black_frame_, black_frame_->format(),
+ media::VideoFrame::WrapVideoFrame(black_frame_, black_frame_->format(),
black_frame_->visible_rect(),
black_frame_->natural_size());
if (!wrapped_black_frame)
return nullptr;
- wrapped_black_frame->AddDestructionObserver(ConvertToBaseOnceCallback(
- CrossThreadBindOnce(&ReleaseOriginalFrame, black_frame_)));
wrapped_black_frame->set_timestamp(reference_frame.timestamp());
base::TimeTicks reference_time;
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 7dee5233acb..2dfc83085ac 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
@@ -21,6 +21,7 @@
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/public/web/modules/webrtc/webrtc_audio_device_impl.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_local_frame_wrapper.h"
@@ -83,14 +84,6 @@ void LogAudioProcesingProperties(
}
} // namespace
-bool IsApmInAudioServiceEnabled() {
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService);
-#else
- return false;
-#endif
-}
-
ProcessedLocalAudioSource::ProcessedLocalAudioSource(
WebLocalFrame* web_frame,
const blink::MediaStreamDevice& device,
@@ -202,7 +195,7 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
// Create the MediaStreamAudioProcessor, bound to the WebRTC audio device
// module.
WebRtcAudioDeviceImpl* const rtc_audio_device =
- Platform::Current()->GetWebRtcAudioDevice();
+ PeerConnectionDependencyFactory::GetInstance()->GetWebRtcAudioDevice();
if (!rtc_audio_device) {
blink::WebRtcLogMessage(
"ProcessedLocalAudioSource::EnsureSourceIsStarted() fails"
@@ -267,7 +260,7 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() {
DCHECK(params.IsValid());
media::AudioSourceParameters source_params(device().session_id());
const bool use_remote_apm =
- IsApmInAudioServiceEnabled() &&
+ media::IsWebRtcApmInAudioServiceEnabled() &&
MediaStreamAudioProcessor::WouldModifyAudio(audio_processing_properties_);
if (use_remote_apm) {
audio_processor_proxy_ =
@@ -326,7 +319,8 @@ void ProcessedLocalAudioSource::EnsureSourceIsStopped() {
scoped_refptr<media::AudioCapturerSource> source_to_stop(std::move(source_));
if (WebRtcAudioDeviceImpl* rtc_audio_device =
- Platform::Current()->GetWebRtcAudioDevice()) {
+ PeerConnectionDependencyFactory::GetInstance()
+ ->GetWebRtcAudioDevice()) {
rtc_audio_device->RemoveAudioCapturer(this);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
index 3a6d0a9e3d6..9ea18522cc6 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/processed_local_audio_source_test.cc
@@ -69,14 +69,11 @@ MockAudioCapturerSource::MockAudioCapturerSource() {}
MockAudioCapturerSource::~MockAudioCapturerSource() {}
// Test Platform implementation that overrides the known methods needed
-// by the tests, including creation of WebRtcAudioDevice and
-// AudioCapturerSource instances.
-class WebRtcAudioDeviceTestingPlatformSupport : public TestingPlatformSupport {
+// by the tests, including creation of AudioCapturerSource instances.
+class AudioCapturerSourceTestingPlatformSupport
+ : public TestingPlatformSupport {
public:
- WebRtcAudioDeviceTestingPlatformSupport() = default;
- WebRtcAudioDeviceImpl* GetWebRtcAudioDevice() override {
- return audio_device_.get();
- }
+ AudioCapturerSourceTestingPlatformSupport() = default;
scoped_refptr<media::AudioCapturerSource> NewAudioCapturerSource(
WebLocalFrame* web_frame,
@@ -91,8 +88,6 @@ class WebRtcAudioDeviceTestingPlatformSupport : public TestingPlatformSupport {
}
private:
- scoped_refptr<blink::WebRtcAudioDeviceImpl> audio_device_ =
- new rtc::RefCountedObject<blink::WebRtcAudioDeviceImpl>();
scoped_refptr<MockAudioCapturerSource> mock_audio_capturer_source_ =
base::MakeRefCounted<MockAudioCapturerSource>();
};
@@ -188,7 +183,7 @@ class ProcessedLocalAudioSourceTest : public testing::Test {
}
private:
- ScopedTestingPlatformSupport<WebRtcAudioDeviceTestingPlatformSupport>
+ ScopedTestingPlatformSupport<AudioCapturerSourceTestingPlatformSupport>
webrtc_audio_device_platform_support_;
WebMediaStreamSource blink_audio_source_;
WebMediaStreamTrack blink_audio_track_;
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 316c44b9bfe..377ab1191cf 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
@@ -11,7 +11,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/modules/mediastream/webrtc_uma_histograms.h"
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
#include "third_party/blink/public/platform/platform.h"
@@ -88,7 +88,7 @@ UserMediaClient::UserMediaClient(
MakeGarbageCollected<ApplyConstraintsProcessor>(
WTF::BindRepeating(
[](UserMediaClient* client)
- -> const mojom::blink::MediaDevicesDispatcherHostPtr& {
+ -> mojom::blink::MediaDevicesDispatcherHost* {
// |client| is guaranteed to be not null because |client|
// owns this ApplyConstraintsProcessor.
DCHECK(client);
@@ -113,7 +113,7 @@ UserMediaClient::UserMediaClient(
frame,
WTF::BindRepeating(
[](UserMediaClient* client)
- -> const mojom::blink::MediaDevicesDispatcherHostPtr& {
+ -> mojom::blink::MediaDevicesDispatcherHost* {
// |client| is guaranteed to be not null because |client|
// owns this UserMediaProcessor.
DCHECK(client);
@@ -295,19 +295,19 @@ void UserMediaClient::Trace(Visitor* visitor) {
}
void UserMediaClient::SetMediaDevicesDispatcherForTesting(
- blink::mojom::blink::MediaDevicesDispatcherHostPtr
+ mojo::PendingRemote<blink::mojom::blink::MediaDevicesDispatcherHost>
media_devices_dispatcher) {
- media_devices_dispatcher_ = std::move(media_devices_dispatcher);
+ media_devices_dispatcher_.Bind(std::move(media_devices_dispatcher));
}
-const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
+blink::mojom::blink::MediaDevicesDispatcherHost*
UserMediaClient::GetMediaDevicesDispatcher() {
if (!media_devices_dispatcher_) {
- frame_->GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&media_devices_dispatcher_));
+ frame_->GetBrowserInterfaceBroker().GetInterface(
+ media_devices_dispatcher_.BindNewPipeAndPassReceiver());
}
- return media_devices_dispatcher_;
+ return media_devices_dispatcher_.get();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.h b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.h
index a955fd2665b..f6c403a8750 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.h
@@ -10,8 +10,10 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/mediastream/media_devices.h"
-#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
+#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink-forward.h"
#include "third_party/blink/public/web/web_user_media_request.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/mediastream/apply_constraints_request.h"
@@ -32,7 +34,7 @@ class LocalFrame;
// object. This includes getUserMedia and enumerateDevices. It must be created,
// called and destroyed on the render thread.
class MODULES_EXPORT UserMediaClient
- : public GarbageCollectedFinalized<UserMediaClient> {
+ : public GarbageCollected<UserMediaClient> {
public:
// TODO(guidou): Make all constructors private and replace with Create methods
// that return a std::unique_ptr. This class is intended for instantiation on
@@ -56,11 +58,11 @@ class MODULES_EXPORT UserMediaClient
void Trace(Visitor*);
void SetMediaDevicesDispatcherForTesting(
- blink::mojom::blink::MediaDevicesDispatcherHostPtr
+ mojo::PendingRemote<blink::mojom::blink::MediaDevicesDispatcherHost>
media_devices_dispatcher);
private:
- class Request : public GarbageCollectedFinalized<Request> {
+ class Request final : public GarbageCollected<Request> {
public:
explicit Request(std::unique_ptr<UserMediaRequestInfo> request);
explicit Request(blink::ApplyConstraintsRequest* request);
@@ -98,8 +100,7 @@ class MODULES_EXPORT UserMediaClient
void DeleteAllUserMediaRequests();
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
- GetMediaDevicesDispatcher();
+ blink::mojom::blink::MediaDevicesDispatcherHost* GetMediaDevicesDispatcher();
// LocalFrame instance associated with the UserMediaController that
// own this UserMediaClient.
@@ -112,7 +113,8 @@ class MODULES_EXPORT UserMediaClient
// problems in builds that do not include WebRTC.
Member<ApplyConstraintsProcessor> apply_constraints_processor_;
- blink::mojom::blink::MediaDevicesDispatcherHostPtr media_devices_dispatcher_;
+ mojo::Remote<blink::mojom::blink::MediaDevicesDispatcherHost>
+ media_devices_dispatcher_;
// UserMedia requests are processed sequentially. |is_processing_request_|
// is a flag that indicates if a request is being processed at a given time,
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 62b0c3d6700..617e292cd21 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
@@ -15,7 +15,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "media/audio/audio_device_description.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#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/mojom/mediastream/media_devices.mojom-blink.h"
@@ -311,7 +311,7 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
UserMediaProcessorUnderTest(
std::unique_ptr<blink::WebMediaStreamDeviceObserver>
media_stream_device_observer,
- blink::mojom::blink::MediaDevicesDispatcherHostPtr
+ mojo::PendingRemote<blink::mojom::blink::MediaDevicesDispatcherHost>
media_devices_dispatcher,
RequestState* state)
: UserMediaProcessor(
@@ -326,9 +326,9 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
SetMediaStreamDeviceObserverForTesting(media_stream_device_observer_.get());
}
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
- media_devices_dispatcher() const {
- return media_devices_dispatcher_;
+ blink::mojom::blink::MediaDevicesDispatcherHost* media_devices_dispatcher()
+ const {
+ return media_devices_dispatcher_.get();
}
MockMediaStreamVideoCapturerSource* last_created_video_source() const {
@@ -433,7 +433,8 @@ class UserMediaProcessorUnderTest : public UserMediaProcessor {
}
std::unique_ptr<WebMediaStreamDeviceObserver> media_stream_device_observer_;
- blink::mojom::blink::MediaDevicesDispatcherHostPtr media_devices_dispatcher_;
+ mojo::Remote<blink::mojom::blink::MediaDevicesDispatcherHost>
+ media_devices_dispatcher_;
MockMediaStreamVideoCapturerSource* video_source_ = nullptr;
MockLocalMediaStreamAudioSource* local_audio_source_ = nullptr;
bool create_source_that_fails_ = false;
@@ -477,31 +478,24 @@ class UserMediaClientUnderTest : public UserMediaClient {
class UserMediaClientTest : public ::testing::Test {
public:
UserMediaClientTest()
- : binding_user_media_processor_(&media_devices_dispatcher_),
- binding_user_media_client_(&media_devices_dispatcher_) {}
+ : user_media_processor_receiver_(&media_devices_dispatcher_),
+ user_media_client_receiver_(&media_devices_dispatcher_) {}
void SetUp() override {
// Create our test object.
auto* msd_observer = new blink::WebMediaStreamDeviceObserver(nullptr);
- blink::mojom::blink::MediaDevicesDispatcherHostPtr
- user_media_processor_host_proxy;
- binding_user_media_processor_.Bind(
- mojo::MakeRequest(&user_media_processor_host_proxy));
user_media_processor_ = MakeGarbageCollected<UserMediaProcessorUnderTest>(
base::WrapUnique(msd_observer),
- std::move(user_media_processor_host_proxy), &state_);
+ user_media_processor_receiver_.BindNewPipeAndPassRemote(), &state_);
user_media_processor_->set_media_stream_dispatcher_host_for_testing(
mock_dispatcher_host_.CreatePendingRemoteAndBind());
user_media_client_impl_ = MakeGarbageCollected<UserMediaClientUnderTest>(
user_media_processor_, &state_);
- blink::mojom::blink::MediaDevicesDispatcherHostPtr
- user_media_client_host_proxy;
- binding_user_media_client_.Bind(
- mojo::MakeRequest(&user_media_client_host_proxy));
+
user_media_client_impl_->SetMediaDevicesDispatcherForTesting(
- std::move(user_media_client_host_proxy));
+ user_media_client_receiver_.BindNewPipeAndPassRemote());
}
void TearDown() override {
@@ -646,10 +640,10 @@ class UserMediaClientTest : public ::testing::Test {
testing_platform_;
MockMojoMediaStreamDispatcherHost mock_dispatcher_host_;
MockMediaDevicesDispatcherHost media_devices_dispatcher_;
- mojo::Binding<blink::mojom::blink::MediaDevicesDispatcherHost>
- binding_user_media_processor_;
- mojo::Binding<blink::mojom::blink::MediaDevicesDispatcherHost>
- binding_user_media_client_;
+ mojo::Receiver<blink::mojom::blink::MediaDevicesDispatcherHost>
+ user_media_processor_receiver_;
+ mojo::Receiver<blink::mojom::blink::MediaDevicesDispatcherHost>
+ user_media_client_receiver_;
WeakPersistent<UserMediaProcessorUnderTest> user_media_processor_;
Persistent<UserMediaClientUnderTest> user_media_client_impl_;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_controller.h b/chromium/third_party/blink/renderer/modules/mediastream/user_media_controller.h
index a214acfef74..d674cb7271c 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_controller.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_controller.h
@@ -37,10 +37,9 @@ class ApplyConstraintsRequest;
class MediaStreamComponent;
class UserMediaRequest;
-class UserMediaController final
- : public GarbageCollectedFinalized<UserMediaController>,
- public Supplement<LocalFrame>,
- public ContextLifecycleObserver {
+class UserMediaController final : public GarbageCollected<UserMediaController>,
+ public Supplement<LocalFrame>,
+ public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(UserMediaController);
public:
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 a99fd495096..8dda7e5c342 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
@@ -17,7 +17,7 @@
#include "base/strings/stringprintf.h"
#include "media/base/audio_parameters.h"
#include "media/capture/video_capture_types.h"
-#include "services/service_manager/public/cpp/interface_provider.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/platform/modules/mediastream/media_stream_audio_source.h"
@@ -263,8 +263,8 @@ UserMediaRequestInfo::UserMediaRequestInfo(
is_processing_user_gesture(is_processing_user_gesture) {}
// Class for storing state of the the processing of getUserMedia requests.
-class UserMediaProcessor::RequestInfo
- : public GarbageCollectedFinalized<UserMediaProcessor::RequestInfo> {
+class UserMediaProcessor::RequestInfo final
+ : public GarbageCollected<UserMediaProcessor::RequestInfo> {
public:
using ResourcesReady =
base::OnceCallback<void(RequestInfo* request_info,
@@ -516,6 +516,11 @@ void UserMediaProcessor::ProcessRequest(
DCHECK(!current_request_info_);
request_completed_cb_ = std::move(callback);
current_request_info_ = MakeGarbageCollected<RequestInfo>(std::move(request));
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "UMP::ProcessRequest. request_id = %d. Has audio = %d. Has video = %d.",
+ current_request_info_->request_id(),
+ current_request_info_->request()->web_request.Audio(),
+ current_request_info_->request()->web_request.Video()));
// TODO(guidou): Set up audio and video in parallel.
if (current_request_info_->web_request().Audio()) {
SetupAudioInput();
@@ -528,6 +533,14 @@ void UserMediaProcessor::SetupAudioInput() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(current_request_info_);
DCHECK(current_request_info_->web_request().Audio());
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "UMP::SetupAudioInput. request_id = %d, audio constraints = %s",
+ current_request_info_->request_id(),
+ current_request_info_->request()
+ ->web_request.AudioConstraints()
+ .ToString()
+ .Utf8()
+ .c_str()));
auto& audio_controls = current_request_info_->stream_controls()->audio;
InitializeAudioTrackControls(current_request_info_->web_request(),
@@ -540,6 +553,10 @@ void UserMediaProcessor::SetupAudioInput() {
}
if (blink::IsDeviceMediaType(audio_controls.stream_type)) {
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::SetupAudioInput. request_id = %d, "
+ "Requesting device capabilities",
+ current_request_info_->request_id()));
GetMediaDevicesDispatcher()->GetAudioInputCapabilities(WTF::Bind(
&UserMediaProcessor::SelectAudioDeviceSettings,
WrapWeakPersistent(this), current_request_info_->web_request()));
@@ -605,6 +622,9 @@ void UserMediaProcessor::SelectAudioSettings(
return;
DCHECK(current_request_info_->stream_controls()->audio.requested);
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::SelectAudioSettings. request_id = %d.",
+ current_request_info_->request_id()));
auto settings = SelectSettingsAudioCapture(
capabilities, web_request.AudioConstraints(),
web_request.ShouldDisableHardwareNoiseSuppression(),
@@ -681,6 +701,14 @@ void UserMediaProcessor::SetupVideoInput() {
: StreamSelectionStrategy::FORCE_NEW_STREAM);
return;
}
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "UMP::SetupVideoInput. request_id = %d, video constraints = %s",
+ current_request_info_->request_id(),
+ current_request_info_->request()
+ ->web_request.VideoConstraints()
+ .ToString()
+ .Utf8()
+ .c_str()));
auto& video_controls = current_request_info_->stream_controls()->video;
InitializeVideoTrackControls(current_request_info_->web_request(),
@@ -719,6 +747,9 @@ void UserMediaProcessor::SelectVideoDeviceSettings(
DCHECK(current_request_info_->stream_controls()->video.requested);
DCHECK(blink::IsDeviceMediaType(
current_request_info_->stream_controls()->video.stream_type));
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::SelectVideoDeviceSettings. request_id = %d.",
+ current_request_info_->request_id()));
blink::VideoDeviceCaptureCapabilities capabilities;
capabilities.device_capabilities =
@@ -744,12 +775,25 @@ void UserMediaProcessor::SelectVideoDeviceSettings(
settings.device_id();
current_request_info_->SetVideoCaptureSettings(
settings, false /* is_content_capture */);
- GenerateStreamForCurrentRequestInfo();
+
+ if (current_request_info_->web_request().Audio()) {
+ base::Optional<base::UnguessableToken> audio_session_id =
+ DetermineExistingAudioSessionId();
+ GenerateStreamForCurrentRequestInfo(
+ audio_session_id, audio_session_id.has_value()
+ ? StreamSelectionStrategy::SEARCH_BY_SESSION_ID
+ : StreamSelectionStrategy::FORCE_NEW_STREAM);
+ } else {
+ GenerateStreamForCurrentRequestInfo();
+ }
}
void UserMediaProcessor::SelectVideoContentSettings() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(current_request_info_);
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::SelectVideoContentSettings. request_id = %d.",
+ current_request_info_->request_id()));
gfx::Size screen_size = GetScreenSize();
blink::VideoCaptureSettings settings =
blink::SelectSettingsVideoContentCapture(
@@ -781,7 +825,7 @@ void UserMediaProcessor::GenerateStreamForCurrentRequestInfo(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(current_request_info_);
blink::WebRtcLogMessage(base::StringPrintf(
- "UMCI::GenerateStreamForCurrentRequestInfo. request_id=%d, "
+ "UMP::GenerateStreamForCurrentRequestInfo. request_id=%d, "
"audio device id=\"%s\", video device id=\"%s\"",
current_request_info_->request_id(),
current_request_info_->stream_controls()->audio.device_id.c_str(),
@@ -805,9 +849,7 @@ UserMediaProcessor::GetMediaStreamDeviceObserver() {
media_stream_device_observer_for_testing_;
if (frame_) { // Can be null for tests.
auto* web_frame = static_cast<WebLocalFrame*>(WebFrame::FromFrame(frame_));
- DCHECK(web_frame);
-
- if (!web_frame->Client())
+ if (!web_frame || !web_frame->Client())
return nullptr;
// TODO(704136): Move ownership of |WebMediaStreamDeviceObserver| out of
@@ -827,7 +869,6 @@ void UserMediaProcessor::OnStreamGenerated(
const Vector<MediaStreamDevice>& audio_devices,
const Vector<MediaStreamDevice>& video_devices) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
if (result != MediaStreamRequestResult::OK) {
OnStreamGenerationFailed(request_id, result);
return;
@@ -840,13 +881,16 @@ void UserMediaProcessor::OnStreamGenerated(
OnStreamGeneratedForCancelledRequest(audio_devices, video_devices);
return;
}
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::OnStreamGenerated. request_id = %d.",
+ current_request_info_->request_id()));
current_request_info_->set_state(RequestInfo::State::GENERATED);
for (const auto* devices : {&audio_devices, &video_devices}) {
for (const auto& device : *devices) {
blink::WebRtcLogMessage(base::StringPrintf(
- "UMCI::OnStreamGenerated. request_id=%d, device id=\"%s\", "
+ "UMP::OnStreamGenerated. request_id=%d, device id=\"%s\", "
"device name=\"%s\"",
request_id, device.id.c_str(), device.name.c_str()));
}
@@ -905,7 +949,8 @@ gfx::Size UserMediaProcessor::GetScreenSize() {
gfx::Size screen_size(blink::kDefaultScreenCastWidth,
blink::kDefaultScreenCastHeight);
if (frame_) { // Can be null in tests.
- blink::WebScreenInfo info = frame_->GetChromeClient().GetScreenInfo();
+ blink::WebScreenInfo info =
+ frame_->GetChromeClient().GetScreenInfo(*frame_);
screen_size = gfx::Size(info.rect.width, info.rect.height);
}
return screen_size;
@@ -914,6 +959,7 @@ gfx::Size UserMediaProcessor::GetScreenSize() {
void UserMediaProcessor::OnStreamGeneratedForCancelledRequest(
const Vector<MediaStreamDevice>& audio_devices,
const Vector<MediaStreamDevice>& video_devices) {
+ blink::WebRtcLogMessage("UMP::OnStreamGeneratedForCancelledRequest.");
// Only stop the device if the device is not used in another MediaStream.
for (auto* it = audio_devices.begin(); it != audio_devices.end(); ++it) {
if (!FindLocalSource(*it)) {
@@ -986,6 +1032,9 @@ void UserMediaProcessor::OnStreamGenerationFailed(
// MediaStreamDispatcherHost is processing the request.
return;
}
+ blink::WebRtcLogMessage(
+ base::StringPrintf("UMP::OnStreamGenerationFailed. request_id = %d.",
+ current_request_info_->request_id()));
GetUserMediaRequestFailed(result);
DeleteWebRequest(current_request_info_->web_request());
@@ -1341,7 +1390,7 @@ void UserMediaProcessor::GetUserMediaRequestSucceeded(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(IsCurrentRequestInfo(web_request));
blink::WebRtcLogMessage(
- base::StringPrintf("UMCI::GetUserMediaRequestSucceeded. request_id=%d",
+ base::StringPrintf("UMP::GetUserMediaRequestSucceeded. request_id=%d",
current_request_info_->request_id()));
// Completing the getUserMedia request can lead to that the RenderFrame and
@@ -1370,7 +1419,7 @@ void UserMediaProcessor::GetUserMediaRequestFailed(
DCHECK(current_request_info_);
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
blink::WebRtcLogMessage(
- base::StringPrintf("UMCI::GetUserMediaRequestFailed. request_id=%d",
+ base::StringPrintf("UMP::GetUserMediaRequestFailed. request_id=%d",
current_request_info_->request_id()));
// Completing the getUserMedia request can lead to that the RenderFrame and
@@ -1644,13 +1693,13 @@ bool UserMediaProcessor::HasActiveSources() const {
blink::mojom::blink::MediaStreamDispatcherHost*
UserMediaProcessor::GetMediaStreamDispatcherHost() {
if (!dispatcher_host_) {
- frame_->GetInterfaceProvider().GetInterface(
+ frame_->GetBrowserInterfaceBroker().GetInterface(
dispatcher_host_.BindNewPipeAndPassReceiver());
}
return dispatcher_host_.get();
}
-const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
+blink::mojom::blink::MediaDevicesDispatcherHost*
UserMediaProcessor::GetMediaDevicesDispatcher() {
return media_devices_dispatcher_cb_.Run();
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.h b/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.h
index ed09fff493a..c3771147295 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_processor.h
@@ -57,10 +57,10 @@ struct UserMediaRequestInfo {
// UserMediaProcessor must be created, called and destroyed on the main
// render thread. There should be only one UserMediaProcessor per frame.
class MODULES_EXPORT UserMediaProcessor
- : public GarbageCollectedFinalized<UserMediaProcessor> {
+ : public GarbageCollected<UserMediaProcessor> {
public:
using MediaDevicesDispatcherCallback = base::RepeatingCallback<
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&()>;
+ blink::mojom::blink::MediaDevicesDispatcherHost*()>;
// |web_frame| must outlive this instance.
UserMediaProcessor(LocalFrame* frame,
MediaDevicesDispatcherCallback media_devices_dispatcher_cb,
@@ -248,8 +248,7 @@ class MODULES_EXPORT UserMediaProcessor
blink::mojom::blink::MediaStreamDispatcherHost*
GetMediaStreamDispatcherHost();
- const blink::mojom::blink::MediaDevicesDispatcherHostPtr&
- GetMediaDevicesDispatcher();
+ blink::mojom::blink::MediaDevicesDispatcherHost* GetMediaDevicesDispatcher();
void SetupAudioInput();
void SelectAudioDeviceSettings(
@@ -290,13 +289,12 @@ class MODULES_EXPORT UserMediaProcessor
mojo::Remote<blink::mojom::blink::MediaStreamDispatcherHost> dispatcher_host_;
// UserMedia requests are processed sequentially. |current_request_info_|
- // contains the request currently being processed, if any, and
- // |pending_request_infos_| is a list of queued requests.
+ // contains the request currently being processed.
Member<RequestInfo> current_request_info_;
MediaDevicesDispatcherCallback media_devices_dispatcher_cb_;
base::OnceClosure request_completed_cb_;
- WeakMember<LocalFrame> frame_;
+ Member<LocalFrame> frame_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
THREAD_CHECKER(thread_checker_);
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 ad9a97403c3..59f35b6e83f 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
@@ -49,12 +49,12 @@ class MediaStreamDescriptor;
class UserMediaController;
class MODULES_EXPORT UserMediaRequest final
- : public GarbageCollectedFinalized<UserMediaRequest>,
+ : public GarbageCollected<UserMediaRequest>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(UserMediaRequest);
public:
- class Callbacks : public GarbageCollectedFinalized<Callbacks> {
+ class Callbacks : public GarbageCollected<Callbacks> {
public:
virtual ~Callbacks() = default;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
index 5b993e58d95..da67cdfc6a5 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -71,11 +71,6 @@ struct ComputedSettings {
base::TimeTicks last_update_timestamp;
};
-// Empty method used for keeping a reference to the original media::VideoFrame
-// in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed.
-// The reference to |frame| is kept in the closure that calls this method.
-void TrackReleaseOriginalFrame(scoped_refptr<media::VideoFrame> frame) {}
-
int ClampToValidDimension(int dimension) {
return std::min(static_cast<int>(media::limits::kMaxDimension),
std::max(0, dimension));
@@ -317,9 +312,15 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame(
return;
}
- // TODO(perkj): Allow cropping / scaling of textures once
- // https://crbug/362521 is fixed.
- if (frame->HasTextures()) {
+ // If the frame is a texture not backed up by GPU memory we don't apply
+ // cropping/scaling and deliver the frame as-is, leaving it up to the
+ // destination to rescale it. Otherwise, cropping and scaling is soft-applied
+ // before delivery for efficiency.
+ //
+ // TODO(crbug.com/362521): Allow cropping/scaling of non-GPU memory backed
+ // textures.
+ if (frame->HasTextures() &&
+ frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
DoDeliverFrame(std::move(frame), estimated_capture_time);
return;
}
@@ -337,15 +338,13 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame(
media::ComputeLetterboxRegion(frame->visible_rect(), desired_size);
video_frame = media::VideoFrame::WrapVideoFrame(
- *frame, frame->format(), region_in_frame, desired_size);
+ frame, frame->format(), region_in_frame, desired_size);
if (!video_frame) {
PostFrameDroppedToMainTaskRunner(
media::VideoCaptureFrameDropReason::
kResolutionAdapterWrappingFrameForCroppingFailed);
return;
}
- video_frame->AddDestructionObserver(ConvertToBaseOnceCallback(
- CrossThreadBindOnce(&TrackReleaseOriginalFrame, frame)));
DVLOG(3) << "desired size " << desired_size.ToString()
<< " output natural size "
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc b/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
index 4afe674e335..a5fd5db6b48 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc
@@ -6,9 +6,15 @@
#include <limits>
+#include "base/synchronization/waitable_event.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/thread.h"
#include "media/base/limits.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
namespace blink {
@@ -189,4 +195,158 @@ TEST(VideoTrackAdapterTest, NoRescaling) {
EXPECT_EQ(desired_size.height(), kInputHeight);
}
+class VideoTrackAdapterFixtureTest : public ::testing::Test {
+ public:
+ VideoTrackAdapterFixtureTest()
+ : testing_render_thread_("TestingRenderThread"),
+ frame_received_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED) {}
+ ~VideoTrackAdapterFixtureTest() override = default;
+
+ protected:
+ void SetUp() override { testing_render_thread_.Start(); }
+
+ void TearDown() override {
+ if (track_added_) {
+ testing_render_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&VideoTrackAdapter::RemoveTrack, adapter_,
+ null_track_.get()));
+ }
+ testing_render_thread_.Stop();
+ }
+
+ void CreateAdapter(const media::VideoCaptureFormat& capture_format) {
+ mock_source_ =
+ std::make_unique<MockMediaStreamVideoSource>(capture_format, false);
+
+ // Create the VideoTrackAdapter instance on |testing_render_thread_|.
+ base::WaitableEvent adapter_created(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ testing_render_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ adapter_ = base::MakeRefCounted<VideoTrackAdapter>(
+ platform_support_->GetIOTaskRunner(), mock_source_->GetWeakPtr());
+ adapter_created.Signal();
+ }));
+ adapter_created.Wait();
+ }
+
+ // Create or re-configure the dummy |null_track_| with the given
+ // |adapter_settings|.
+ void ConfigureTrack(const VideoTrackAdapterSettings& adapter_settings) {
+ if (!track_added_) {
+ testing_render_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &VideoTrackAdapter::AddTrack, adapter_, null_track_.get(),
+ base::BindRepeating(
+ &VideoTrackAdapterFixtureTest::OnFrameDelivered,
+ base::Unretained(this)),
+ base::DoNothing(), base::DoNothing(), adapter_settings));
+ track_added_ = true;
+ } else {
+ testing_render_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VideoTrackAdapter::ReconfigureTrack, adapter_,
+ null_track_.get(), adapter_settings));
+ }
+ }
+
+ void SetFrameValidationCallback(VideoCaptureDeliverFrameCB callback) {
+ frame_validation_callback_ = std::move(callback);
+ }
+
+ // Deliver |frame| to |adapter_| and wait until OnFrameDelivered signals that
+ // it receives the processed frame.
+ void DeliverAndValidateFrame(scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
+ auto deliver_frame = [&]() {
+ platform_support_->GetIOTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&VideoTrackAdapter::DeliverFrameOnIO,
+ adapter_, frame, estimated_capture_time));
+ };
+
+ frame_received_.Reset();
+ // Bounce the call to DeliverFrameOnIO off |testing_render_thread_| to
+ // synchronize with the AddTrackOnIO / ReconfigureTrackOnIO that would be
+ // invoked through ConfigureTrack.
+ testing_render_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting(deliver_frame));
+ frame_received_.Wait();
+ }
+
+ void OnFrameDelivered(scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
+ if (frame_validation_callback_) {
+ frame_validation_callback_.Run(frame, estimated_capture_time);
+ }
+ frame_received_.Signal();
+ }
+
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport>
+ platform_support_;
+ base::Thread testing_render_thread_;
+ std::unique_ptr<MockMediaStreamVideoSource> mock_source_;
+ scoped_refptr<VideoTrackAdapter> adapter_;
+
+ base::WaitableEvent frame_received_;
+ VideoCaptureDeliverFrameCB frame_validation_callback_;
+
+ // For testing we use a nullptr for MediaStreamVideoTrack.
+ std::unique_ptr<MediaStreamVideoTrack> null_track_ = nullptr;
+ bool track_added_ = false;
+};
+
+TEST_F(VideoTrackAdapterFixtureTest, DeliverFrame_GpuMemoryBuffer) {
+ // Attributes for the original input frame.
+ const gfx::Size kCodedSize(1280, 960);
+ const gfx::Rect kVisibleRect(0, 120, 1280, 720);
+ const gfx::Size kNaturalSize(1280, 720);
+ const double kFrameRate = 30.0;
+ auto gmb_frame =
+ CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
+
+ // Initialize the VideoTrackAdapter to handle GpuMemoryBuffer. NV12 is the
+ // only pixel format supported at the moment.
+ const media::VideoCaptureFormat stream_format(kCodedSize, kFrameRate,
+ media::PIXEL_FORMAT_NV12);
+ CreateAdapter(stream_format);
+
+ // Keep the desired size the same as the natural size of the original frame.
+ VideoTrackAdapterSettings settings_nonscaled(kNaturalSize, kFrameRate);
+ ConfigureTrack(settings_nonscaled);
+ auto check_nonscaled = [&](scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
+ // We should get the original frame as-is here.
+ EXPECT_EQ(frame->storage_type(),
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
+ EXPECT_EQ(frame->GetGpuMemoryBuffer(), gmb_frame->GetGpuMemoryBuffer());
+ EXPECT_EQ(frame->coded_size(), kCodedSize);
+ EXPECT_EQ(frame->visible_rect(), kVisibleRect);
+ EXPECT_EQ(frame->natural_size(), kNaturalSize);
+ };
+ SetFrameValidationCallback(base::BindLambdaForTesting(check_nonscaled));
+ DeliverAndValidateFrame(gmb_frame, base::TimeTicks());
+
+ // Scale the original frame by a factor of 0.5x.
+ const gfx::Size kDesiredSize(640, 360);
+ VideoTrackAdapterSettings settings_scaled(kDesiredSize, kFrameRate);
+ ConfigureTrack(settings_scaled);
+ auto check_scaled = [&](scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
+ // The original frame should be wrapped in a new frame, with |kDesiredSize|
+ // exposed as natural size of the wrapped frame.
+ EXPECT_EQ(frame->storage_type(),
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
+ EXPECT_EQ(frame->GetGpuMemoryBuffer(), gmb_frame->GetGpuMemoryBuffer());
+ EXPECT_EQ(frame->coded_size(), kCodedSize);
+ EXPECT_EQ(frame->visible_rect(), kVisibleRect);
+ EXPECT_EQ(frame->natural_size(), kDesiredSize);
+ };
+ SetFrameValidationCallback(base::BindLambdaForTesting(check_scaled));
+ DeliverAndValidateFrame(gmb_frame, base::TimeTicks());
+}
+
} // namespace blink
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 8e453c820e6..7729f46a6e1 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
@@ -55,7 +55,6 @@ scoped_refptr<media::VideoFrame> CopyFrame(
DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB ||
frame->format() == media::PIXEL_FORMAT_XRGB ||
frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_UYVY ||
frame->format() == media::PIXEL_FORMAT_NV12);
new_frame = media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
@@ -564,8 +563,11 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
is_first_frame = false;
if (!current_frame_->metadata()->GetRotation(
- media::VideoFrameMetadata::ROTATION, &current_video_rotation) ||
- current_video_rotation == *new_rotation) {
+ media::VideoFrameMetadata::ROTATION, &current_video_rotation)) {
+ // Assume VIDEO_ROTATION_0 for current frame without video rotation.
+ current_video_rotation = media::VIDEO_ROTATION_0;
+ }
+ if (current_video_rotation == *new_rotation) {
new_rotation.reset();
}
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 8ad00796a99..4322ed2379d 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
@@ -344,8 +344,12 @@ void MockMediaStreamVideoRenderer::QueueFrames(
frame_size, gfx::Rect(frame_size), frame_size,
base::TimeDelta::FromMilliseconds(token));
- frame->metadata()->SetRotation(media::VideoFrameMetadata::ROTATION,
- rotation);
+ // MediaStreamRemoteVideoSource does not explicitly set the rotation
+ // for unrotated frames, so that is not done here either.
+ if (rotation != media::VIDEO_ROTATION_0) {
+ frame->metadata()->SetRotation(media::VideoFrameMetadata::ROTATION,
+ rotation);
+ }
frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::Key::REFERENCE_TIME,
base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(token));
@@ -582,10 +586,11 @@ class WebMediaPlayerMSTest
void ActivateViewportIntersectionMonitoring(bool activate) override {}
void MediaRemotingStarted(
const WebString& remote_device_friendly_name) override {}
- void MediaRemotingStopped(WebLocalizedString::Name error_msg) override {}
+ void MediaRemotingStopped(int error_code) override {}
void RequestPlay() override {}
void RequestPause() override {}
void RequestMuted(bool muted) override {}
+ Features GetFeatures() override { return Features(); }
// Implementation of cc::VideoFrameProvider::Client
void StopUsingProvider() override;
@@ -1066,6 +1071,24 @@ TEST_P(WebMediaPlayerMSTest, RotationChange) {
EXPECT_EQ(kStandardHeight, natural_size.height);
EXPECT_EQ(kStandardWidth, natural_size.width);
+ // Change rotation again.
+ tokens[0] = 66;
+ timestamps = std::vector<int>(tokens, tokens + base::size(tokens));
+ 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));
+ } else {
+ EXPECT_CALL(*this, DoSetCcLayer(true));
+ EXPECT_CALL(*this, DoStopRendering());
+ EXPECT_CALL(*this, DoStartRendering());
+ }
+ message_loop_controller_.RunAndWaitForStatus(
+ media::PipelineStatus::PIPELINE_OK);
+ base::RunLoop().RunUntilIdle();
+ natural_size = player_->NaturalSize();
+ EXPECT_EQ(kStandardHeight, natural_size.width);
+ EXPECT_EQ(kStandardWidth, natural_size.height);
+
testing::Mock::VerifyAndClearExpectations(this);
EXPECT_CALL(*this, DoSetCcLayer(false));
diff --git a/chromium/third_party/blink/renderer/modules/modules.gni b/chromium/third_party/blink/renderer/modules/modules.gni
index 3d3ee40c96e..30d8be51c8e 100644
--- a/chromium/third_party/blink/renderer/modules/modules.gni
+++ b/chromium/third_party/blink/renderer/modules/modules.gni
@@ -8,9 +8,7 @@
# to the huge and slow lists of sources. If sharing is necessary, make a
# separate .gni.
import("//build/config/jumbo.gni")
-import("//build/split_static_library.gni")
import("//third_party/blink/renderer/config.gni")
-
blink_modules_output_dir = "$root_gen_dir/third_party/blink/renderer/modules"
# Defines a part of blink modules. This is either a source set or a static
@@ -25,11 +23,7 @@ template("blink_modules_sources") {
if (is_component_build) {
target_type = "source_set"
} else {
- if (!defined(invoker.split_count)) {
- target_type = "static_library"
- } else {
- target_type = "split_static_library"
- }
+ target_type = "static_library"
}
target("jumbo_" + target_type, target_name) {
@@ -45,17 +39,9 @@ template("blink_modules_sources") {
if (defined(invoker.deps)) {
deps += invoker.deps
}
- if (target_type == "split_static_library") {
- split_count = invoker.split_count
- }
# Take everything else not handled above from the invoker.
- forward_variables_from(invoker,
- "*",
- [
- "deps",
- "split_count",
- ])
+ forward_variables_from(invoker, "*", [ "deps" ])
}
}
set_defaults("blink_modules_sources") {
diff --git a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni b/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
index 6209ed0706c..fe8647ee296 100644
--- a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -74,7 +74,6 @@ modules_idl_files =
"background_sync/periodic_sync_event.idl",
"background_sync/periodic_sync_manager.idl",
"background_sync/sync_manager.idl",
- "badging/experimental_badge.idl",
"battery/battery_manager.idl",
"bluetooth/bluetooth.idl",
"bluetooth/bluetooth_advertising_event.idl",
@@ -99,6 +98,8 @@ modules_idl_files =
"canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl",
"clipboard/clipboard.idl",
"clipboard/clipboard_item.idl",
+ "compression/compression_stream.idl",
+ "compression/decompression_stream.idl",
"contacts_picker/contacts_manager.idl",
"content_index/content_index.idl",
"content_index/content_index_event.idl",
@@ -163,10 +164,10 @@ modules_idl_files =
"gamepad/gamepad_haptic_actuator.idl",
"gamepad/gamepad_list.idl",
"gamepad/gamepad_pose.idl",
- "geolocation/coordinates.idl",
"geolocation/geolocation.idl",
- "geolocation/position.idl",
- "geolocation/position_error.idl",
+ "geolocation/geolocation_coordinates.idl",
+ "geolocation/geolocation_position.idl",
+ "geolocation/geolocation_position_error.idl",
"hid/hid.idl",
"hid/hid_collection_info.idl",
"hid/hid_connection_event.idl",
@@ -193,7 +194,6 @@ modules_idl_files =
"indexeddb/idb_request.idl",
"indexeddb/idb_transaction.idl",
"indexeddb/idb_version_change_event.idl",
- "installedapp/related_application.idl",
"keyboard/keyboard.idl",
"keyboard/keyboard_layout_map.idl",
"locks/lock.idl",
@@ -354,6 +354,8 @@ modules_idl_files =
"vr/vr_pose.idl",
"vr/vr_stage_parameters.idl",
"wake_lock/wake_lock.idl",
+ "wake_lock/wake_lock_event.idl",
+ "wake_lock/wake_lock_sentinel.idl",
"webaudio/analyser_node.idl",
"webaudio/audio_buffer.idl",
"webaudio/audio_buffer_source_node.idl",
@@ -467,6 +469,7 @@ modules_idl_files =
"webgpu/gpu_compute_pass_encoder.idl",
"webgpu/gpu_compute_pipeline.idl",
"webgpu/gpu_device.idl",
+ "webgpu/gpu_device_lost_info.idl",
"webgpu/gpu_fence.idl",
"webgpu/gpu_out_of_memory_error.idl",
"webgpu/gpu_pipeline_layout.idl",
@@ -573,7 +576,6 @@ modules_dictionary_idl_files =
"background_sync/background_sync_options.idl",
"background_sync/sync_event_init.idl",
"background_sync/periodic_sync_event_init.idl",
- "badging/badge_options.idl",
"bluetooth/bluetooth_advertising_event_init.idl",
"bluetooth/bluetooth_le_scan_filter_init.idl",
"bluetooth/bluetooth_le_scan_options.idl",
@@ -647,6 +649,7 @@ modules_dictionary_idl_files =
"indexeddb/idb_observer_init.idl",
"indexeddb/idb_transaction_options.idl",
"indexeddb/idb_version_change_event_init.idl",
+ "installedapp/related_application.idl",
"locks/lock_info.idl",
"locks/lock_manager_snapshot.idl",
"locks/lock_options.idl",
@@ -707,6 +710,7 @@ modules_dictionary_idl_files =
"payments/image_object.idl",
"payments/merchant_validation_event_init.idl",
"payments/payer_errors.idl",
+ "payments/payment_address_init.idl",
"payments/payment_currency_amount.idl",
"payments/payment_details_base.idl",
"payments/payment_details_init.idl",
@@ -799,7 +803,7 @@ modules_dictionary_idl_files =
"storage/storage_event_init.idl",
"vr/vr_display_event_init.idl",
"vr/vr_layer_init.idl",
- "wake_lock/wake_lock_request_options.idl",
+ "wake_lock/wake_lock_event_init.idl",
"webaudio/analyser_options.idl",
"webaudio/audio_buffer_options.idl",
"webaudio/audio_buffer_source_options.idl",
@@ -836,22 +840,25 @@ modules_dictionary_idl_files =
"webgpu/gpu_bind_group_layout_descriptor.idl",
"webgpu/gpu_blend_descriptor.idl",
"webgpu/gpu_buffer_binding.idl",
+ "webgpu/gpu_command_buffer_descriptor.idl",
"webgpu/gpu_buffer_copy_view.idl",
"webgpu/gpu_buffer_descriptor.idl",
- "webgpu/gpu_color.idl",
+ "webgpu/gpu_color_dict.idl",
"webgpu/gpu_color_state_descriptor.idl",
"webgpu/gpu_command_encoder_descriptor.idl",
"webgpu/gpu_compute_pipeline_descriptor.idl",
+ "webgpu/gpu_compute_pass_descriptor.idl",
"webgpu/gpu_depth_stencil_state_descriptor.idl",
"webgpu/gpu_device_descriptor.idl",
"webgpu/gpu_extensions.idl",
- "webgpu/gpu_extent_3d.idl",
+ "webgpu/gpu_extent_3d_dict.idl",
"webgpu/gpu_fence_descriptor.idl",
"webgpu/gpu_limits.idl",
- "webgpu/gpu_origin_3d.idl",
+ "webgpu/gpu_object_descriptor_base.idl",
+ "webgpu/gpu_origin_3d_dict.idl",
"webgpu/gpu_pipeline_descriptor_base.idl",
"webgpu/gpu_pipeline_layout_descriptor.idl",
- "webgpu/gpu_pipeline_stage_descriptor.idl",
+ "webgpu/gpu_programmable_stage_descriptor.idl",
"webgpu/gpu_rasterization_state_descriptor.idl",
"webgpu/gpu_render_bundle_descriptor.idl",
"webgpu/gpu_render_bundle_encoder_descriptor.idl",
@@ -918,6 +925,7 @@ modules_dependency_idl_files =
"background_fetch/service_worker_registration_background_fetch.idl",
"background_sync/service_worker_global_scope_sync.idl",
"background_sync/service_worker_registration_sync.idl",
+ "badging/navigator_badge.idl",
"battery/navigator_battery.idl",
"beacon/navigator_beacon.idl",
"bluetooth/navigator_bluetooth.idl",
@@ -1005,9 +1013,13 @@ modules_dependency_idl_files =
"storage/window_storage.idl",
"vibration/navigator_vibration.idl",
"vr/navigator_vr.idl",
+ "wake_lock/navigator_wake_lock.idl",
+ "wake_lock/worker_navigator_wake_lock.idl",
"webdatabase/window_web_database.idl",
"webgl/webgl2_rendering_context_base.idl",
"webgl/webgl_rendering_context_base.idl",
+ "webgpu/gpu_programmable_pass_encoder.idl",
+ "webgpu/gpu_render_encoder_base.idl",
"webgpu/navigator_gpu.idl",
"webmidi/navigator_web_midi.idl",
"webshare/navigator_share.idl",
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.cc b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
index 40aca4e435f..30b024c531c 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom-blink.h"
#include "third_party/blink/public/platform/interface_registry.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -28,7 +29,6 @@
#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/page.h"
-#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h"
#include "third_party/blink/renderer/modules/app_banner/app_banner_controller.h"
@@ -50,7 +50,7 @@
#include "third_party/blink/renderer/modules/event_target_modules_names.h"
#include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h"
#include "third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h"
-#include "third_party/blink/renderer/modules/filesystem/local_file_system_client.h"
+#include "third_party/blink/renderer/modules/filesystem/local_file_system.h"
#include "third_party/blink/renderer/modules/gamepad/navigator_gamepad.h"
#include "third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
@@ -83,23 +83,19 @@
#include "third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h"
#include "third_party/blink/renderer/modules/webdatabase/web_database_host.h"
#include "third_party/blink/renderer/modules/webdatabase/web_database_impl.h"
-#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h"
-#include "third_party/blink/renderer/modules/xr/navigator_xr.h"
-#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
-#include "third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h"
-#endif
-#include "third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.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/webgpu/gpu_canvas_context.h"
+#include "third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread.h"
+#include "third_party/blink/renderer/modules/xr/navigator_xr.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#if defined(TOUCHLESS_MEDIA_CONTROLS)
-#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h"
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+#include "third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h"
#endif
namespace blink {
@@ -182,7 +178,7 @@ void ModulesInitializer::InstallSupplements(LocalFrame& frame) const {
ProvidePushMessagingClientTo(
frame, MakeGarbageCollected<PushMessagingClient>(frame));
ProvideUserMediaTo(frame);
- ProvideLocalFileSystemTo(frame, std::make_unique<LocalFileSystemClient>());
+ ProvideLocalFileSystemTo(frame);
ScreenOrientationControllerImpl::ProvideTo(frame);
if (RuntimeEnabledFeatures::PresentationEnabled())
@@ -199,19 +195,14 @@ void ModulesInitializer::InstallSupplements(LocalFrame& frame) const {
}
void ModulesInitializer::ProvideLocalFileSystemToWorker(
- WorkerClients& worker_clients) const {
- ::blink::ProvideLocalFileSystemToWorker(
- &worker_clients, std::make_unique<LocalFileSystemClient>());
+ WorkerGlobalScope& worker_global_scope) const {
+ ::blink::ProvideLocalFileSystemToWorker(worker_global_scope);
}
MediaControls* ModulesInitializer::CreateMediaControls(
HTMLMediaElement& media_element,
ShadowRoot& shadow_root) const {
-#if defined(TOUCHLESS_MEDIA_CONTROLS)
- return MediaControlsTouchlessImpl::Create(media_element, shadow_root);
-#else
return MediaControlsImpl::Create(media_element, shadow_root);
-#endif
}
PictureInPictureController*
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.h b/chromium/third_party/blink/renderer/modules/modules_initializer.h
index 1eec6b30a79..12753f6e0d0 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.h
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.h
@@ -22,7 +22,7 @@ class MODULES_EXPORT ModulesInitializer : public CoreInitializer {
private:
void InstallSupplements(LocalFrame&) const override;
- void ProvideLocalFileSystemToWorker(WorkerClients&) const override;
+ void ProvideLocalFileSystemToWorker(WorkerGlobalScope&) const override;
MediaControls* CreateMediaControls(HTMLMediaElement&,
ShadowRoot&) const override;
PictureInPictureController* CreatePictureInPictureController(
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/BUILD.gn b/chromium/third_party/blink/renderer/modules/native_file_system/BUILD.gn
index 40f58658bd4..6f07c5a9a0e 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/BUILD.gn
@@ -26,3 +26,23 @@ blink_modules_sources("native_file_system") {
"//third_party/blink/renderer/platform",
]
}
+
+jumbo_source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "window_native_file_system_test.cc",
+ ]
+
+ configs += [
+ "//third_party/blink/renderer:config",
+ "//third_party/blink/renderer:inside_blink",
+ "//third_party/blink/renderer/core:blink_core_pch",
+ ]
+
+ deps = [
+ "//testing/gtest",
+ "//third_party/blink/renderer/modules",
+ "//third_party/blink/renderer/platform",
+ "//third_party/blink/renderer/platform/wtf",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
index 8fd7e9c296e..5110bb82089 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.cc
@@ -4,10 +4,12 @@
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.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/dom_exception.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
@@ -28,10 +30,12 @@ constexpr const char kSandboxRootDirectoryName[] = "";
using mojom::blink::NativeFileSystemErrorPtr;
NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle(
+ ExecutionContext* context,
const String& name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemDirectoryHandle>
- mojo_ptr)
- : NativeFileSystemHandle(name), mojo_ptr_(std::move(mojo_ptr)) {
+ mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> mojo_ptr)
+ : NativeFileSystemHandle(context, name),
+ mojo_ptr_(std::move(mojo_ptr),
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
DCHECK(mojo_ptr_);
}
@@ -57,10 +61,7 @@ ScriptPromise NativeFileSystemDirectoryHandle::getFile(
return;
}
resolver->Resolve(MakeGarbageCollected<NativeFileSystemFileHandle>(
- name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle>(
- std::move(handle), context->GetInterfaceInvalidator(),
- context->GetTaskRunner(TaskType::kMiscPlatformAPI))));
+ context, name, std::move(handle)));
},
WrapPersistent(resolver), name));
@@ -74,12 +75,19 @@ ScriptPromise NativeFileSystemDirectoryHandle::getDirectory(
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
+ if (!mojo_ptr_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return result;
+ }
+
mojo_ptr_->GetDirectory(
name, options->create(),
WTF::Bind(
[](ScriptPromiseResolver* resolver, const String& name,
NativeFileSystemErrorPtr result,
- mojom::blink::NativeFileSystemDirectoryHandlePtr handle) {
+ mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>
+ handle) {
ExecutionContext* context = resolver->GetExecutionContext();
if (!context)
return;
@@ -89,12 +97,7 @@ ScriptPromise NativeFileSystemDirectoryHandle::getDirectory(
}
resolver->Resolve(
MakeGarbageCollected<NativeFileSystemDirectoryHandle>(
- name,
- RevocableInterfacePtr<
- mojom::blink::NativeFileSystemDirectoryHandle>(
- handle.PassInterface(),
- context->GetInterfaceInvalidator(),
- context->GetTaskRunner(TaskType::kMiscPlatformAPI))));
+ context, name, std::move(handle)));
},
WrapPersistent(resolver), name));
@@ -124,7 +127,7 @@ ScriptValue NativeFileSystemDirectoryHandle::getEntries(
.ToChecked()) {
return ScriptValue();
}
- return ScriptValue(script_state, result);
+ return ScriptValue(script_state->GetIsolate(), result);
}
ScriptPromise NativeFileSystemDirectoryHandle::removeEntry(
@@ -134,6 +137,12 @@ ScriptPromise NativeFileSystemDirectoryHandle::removeEntry(
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
+ if (!mojo_ptr_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return result;
+ }
+
mojo_ptr_->RemoveEntry(
name, options->recursive(),
WTF::Bind(
@@ -170,7 +179,8 @@ ScriptPromise NativeFileSystemDirectoryHandle::getSystemDirectory(
[](ScriptPromiseResolver* resolver,
mojo::Remote<mojom::blink::NativeFileSystemManager>,
NativeFileSystemErrorPtr result,
- mojom::blink::NativeFileSystemDirectoryHandlePtr handle) {
+ mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>
+ handle) {
ExecutionContext* context = resolver->GetExecutionContext();
if (!context)
return;
@@ -179,27 +189,28 @@ ScriptPromise NativeFileSystemDirectoryHandle::getSystemDirectory(
return;
}
resolver->Resolve(MakeGarbageCollected<NativeFileSystemDirectoryHandle>(
- kSandboxRootDirectoryName,
- RevocableInterfacePtr<
- mojom::blink::NativeFileSystemDirectoryHandle>(
- handle.PassInterface(), context->GetInterfaceInvalidator(),
- context->GetTaskRunner(TaskType::kMiscPlatformAPI))));
+ context, kSandboxRootDirectoryName, std::move(handle)));
},
WrapPersistent(resolver), std::move(manager)));
return result;
}
-mojom::blink::NativeFileSystemTransferTokenPtr
+mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>
NativeFileSystemDirectoryHandle::Transfer() {
- mojom::blink::NativeFileSystemTransferTokenPtr result;
- mojo_ptr_->Transfer(mojo::MakeRequest(&result));
+ mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> result;
+ if (mojo_ptr_)
+ mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver());
return result;
}
void NativeFileSystemDirectoryHandle::QueryPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) {
+ if (!mojo_ptr_) {
+ std::move(callback).Run(mojom::blink::PermissionStatus::DENIED);
+ return;
+ }
mojo_ptr_->GetPermissionStatus(writable, std::move(callback));
}
@@ -207,7 +218,20 @@ void NativeFileSystemDirectoryHandle::RequestPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr,
mojom::blink::PermissionStatus)> callback) {
+ if (!mojo_ptr_) {
+ std::move(callback).Run(
+ mojom::blink::NativeFileSystemError::New(
+ mojom::blink::NativeFileSystemStatus::kInvalidState,
+ base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"),
+ mojom::blink::PermissionStatus::DENIED);
+ return;
+ }
+
mojo_ptr_->RequestPermission(writable, std::move(callback));
}
+void NativeFileSystemDirectoryHandle::ContextDestroyed(ExecutionContext*) {
+ mojo_ptr_.reset();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
index 14e9b3eeb75..8c037ea4114 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h
@@ -5,9 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom-blink.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
namespace blink {
class FileSystemGetDirectoryOptions;
@@ -20,8 +21,9 @@ class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
public:
NativeFileSystemDirectoryHandle(
+ ExecutionContext* context,
const String& name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemDirectoryHandle>);
+ mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>);
bool isDirectory() const override { return true; }
@@ -39,12 +41,15 @@ class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
static ScriptPromise getSystemDirectory(ScriptState*,
const GetSystemDirectoryOptions*);
- mojom::blink::NativeFileSystemTransferTokenPtr Transfer() override;
+ mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> Transfer()
+ override;
mojom::blink::NativeFileSystemDirectoryHandle* MojoHandle() {
return mojo_ptr_.get();
}
+ void ContextDestroyed(ExecutionContext*) override;
+
private:
void QueryPermissionImpl(
bool writable,
@@ -54,8 +59,7 @@ class NativeFileSystemDirectoryHandle final : public NativeFileSystemHandle {
base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr,
mojom::blink::PermissionStatus)>) override;
- RevocableInterfacePtr<mojom::blink::NativeFileSystemDirectoryHandle>
- mojo_ptr_;
+ mojo::Remote<mojom::blink::NativeFileSystemDirectoryHandle> mojo_ptr_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h
index 93d5f13db88..7a7200b71e8 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_DIRECTORY_ITERATOR_H_
#include "base/files/file.h"
-#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom-blink.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -29,9 +29,6 @@ class NativeFileSystemDirectoryIterator final
ExecutionContext* execution_context);
ScriptPromise next(ScriptState*);
- // TODO(mek): This return method should cancel the backend directory iteration
- // operation, to avoid doing useless work.
- void IteratorReturn() {}
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl
index 5be49e4cb44..85924a5e68f 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl
@@ -10,5 +10,4 @@
RuntimeEnabled=NativeFileSystem
] interface NativeFileSystemDirectoryIterator {
[CallWith=ScriptState] Promise<any> next();
- [ImplementedAs=IteratorReturn] void return();
};
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc
index dcbbcc127a9..8abe64a21ff 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h
index ea63282ad17..362018649cd 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_error.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_ERROR_H_
#include "base/files/file.h"
-#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink-forward.h"
namespace blink {
class ScriptPromiseResolver;
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
index 8dd25fcb796..9799925d4a9 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.cc
@@ -21,9 +21,12 @@ namespace blink {
using mojom::blink::NativeFileSystemErrorPtr;
NativeFileSystemFileHandle::NativeFileSystemFileHandle(
+ ExecutionContext* context,
const String& name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle> mojo_ptr)
- : NativeFileSystemHandle(name), mojo_ptr_(std::move(mojo_ptr)) {
+ mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle> mojo_ptr)
+ : NativeFileSystemHandle(context, name),
+ mojo_ptr_(std::move(mojo_ptr),
+ context->GetTaskRunner(TaskType::kMiscPlatformAPI)) {
DCHECK(mojo_ptr_);
}
@@ -33,6 +36,12 @@ ScriptPromise NativeFileSystemFileHandle::createWriter(
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
+ if (!mojo_ptr_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return result;
+ }
+
mojo_ptr_->CreateFileWriter(
options->keepExistingData(),
WTF::Bind(
@@ -48,9 +57,7 @@ ScriptPromise NativeFileSystemFileHandle::createWriter(
return;
}
resolver->Resolve(MakeGarbageCollected<NativeFileSystemWriter>(
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileWriter>(
- std::move(writer), context->GetInterfaceInvalidator(),
- context->GetTaskRunner(TaskType::kMiscPlatformAPI))));
+ context, std::move(writer)));
},
WrapPersistent(resolver)));
@@ -61,6 +68,12 @@ ScriptPromise NativeFileSystemFileHandle::getFile(ScriptState* script_state) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = resolver->Promise();
+ if (!mojo_ptr_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError));
+ return result;
+ }
+
mojo_ptr_->AsBlob(WTF::Bind(
[](ScriptPromiseResolver* resolver, const String& name,
NativeFileSystemErrorPtr result,
@@ -76,16 +89,25 @@ ScriptPromise NativeFileSystemFileHandle::getFile(ScriptState* script_state) {
return result;
}
-mojom::blink::NativeFileSystemTransferTokenPtr
+mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>
NativeFileSystemFileHandle::Transfer() {
- mojom::blink::NativeFileSystemTransferTokenPtr result;
- mojo_ptr_->Transfer(mojo::MakeRequest(&result));
+ mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> result;
+ if (mojo_ptr_)
+ mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver());
return result;
}
+void NativeFileSystemFileHandle::ContextDestroyed(ExecutionContext*) {
+ mojo_ptr_.reset();
+}
+
void NativeFileSystemFileHandle::QueryPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::PermissionStatus)> callback) {
+ if (!mojo_ptr_) {
+ std::move(callback).Run(mojom::blink::PermissionStatus::DENIED);
+ return;
+ }
mojo_ptr_->GetPermissionStatus(writable, std::move(callback));
}
@@ -93,6 +115,15 @@ void NativeFileSystemFileHandle::RequestPermissionImpl(
bool writable,
base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr,
mojom::blink::PermissionStatus)> callback) {
+ if (!mojo_ptr_) {
+ std::move(callback).Run(
+ mojom::blink::NativeFileSystemError::New(
+ mojom::blink::NativeFileSystemStatus::kInvalidState,
+ base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"),
+ mojom::blink::PermissionStatus::DENIED);
+ return;
+ }
+
mojo_ptr_->RequestPermission(writable, std::move(callback));
}
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
index 4f7abf5b9a7..81686cd2490 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h
@@ -5,9 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom-blink.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
namespace blink {
class FileSystemCreateWriterOptions;
@@ -17,8 +18,9 @@ class NativeFileSystemFileHandle final : public NativeFileSystemHandle {
public:
NativeFileSystemFileHandle(
+ ExecutionContext* context,
const String& name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle>);
+ mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle>);
bool isFile() const override { return true; }
@@ -26,7 +28,10 @@ class NativeFileSystemFileHandle final : public NativeFileSystemHandle {
const FileSystemCreateWriterOptions* options);
ScriptPromise getFile(ScriptState*);
- mojom::blink::NativeFileSystemTransferTokenPtr Transfer() override;
+ mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> Transfer()
+ override;
+
+ void ContextDestroyed(ExecutionContext*) override;
mojom::blink::NativeFileSystemFileHandle* MojoHandle() {
return mojo_ptr_.get();
@@ -41,7 +46,7 @@ class NativeFileSystemFileHandle final : public NativeFileSystemHandle {
base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr,
mojom::blink::PermissionStatus)>) override;
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle> mojo_ptr_;
+ mojo::Remote<mojom::blink::NativeFileSystemFileHandle> mojo_ptr_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
index 20222927f8d..634b1ecbe14 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.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/dom_exception.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
@@ -12,15 +13,16 @@
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_error.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_file_handle.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
using mojom::blink::NativeFileSystemEntryPtr;
using mojom::blink::NativeFileSystemErrorPtr;
-NativeFileSystemHandle::NativeFileSystemHandle(const String& name)
- : name_(name) {}
+NativeFileSystemHandle::NativeFileSystemHandle(
+ ExecutionContext* execution_context,
+ const String& name)
+ : ContextLifecycleObserver(execution_context), name_(name) {}
// static
NativeFileSystemHandle* NativeFileSystemHandle::CreateFromMojoEntry(
@@ -28,18 +30,10 @@ NativeFileSystemHandle* NativeFileSystemHandle::CreateFromMojoEntry(
ExecutionContext* execution_context) {
if (e->entry_handle->is_file()) {
return MakeGarbageCollected<NativeFileSystemFileHandle>(
- e->name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileHandle>(
- std::move(e->entry_handle->get_file()),
- execution_context->GetInterfaceInvalidator(),
- execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ execution_context, e->name, std::move(e->entry_handle->get_file()));
}
return MakeGarbageCollected<NativeFileSystemDirectoryHandle>(
- e->name,
- RevocableInterfacePtr<mojom::blink::NativeFileSystemDirectoryHandle>(
- std::move(e->entry_handle->get_directory()),
- execution_context->GetInterfaceInvalidator(),
- execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ execution_context, e->name, std::move(e->entry_handle->get_directory()));
}
namespace {
@@ -97,4 +91,9 @@ ScriptPromise NativeFileSystemHandle::requestPermission(
return result;
}
+void NativeFileSystemHandle::Trace(Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
index b93edad2f7e..1491d217a5a 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_handle.h
@@ -5,11 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_HANDLE_H_
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_transfer_token.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/core/execution_context/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"
@@ -19,11 +21,14 @@ namespace blink {
class ExecutionContext;
class FileSystemHandlePermissionDescriptor;
-class NativeFileSystemHandle : public ScriptWrappable {
+class NativeFileSystemHandle : public ScriptWrappable,
+ public ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(NativeFileSystemHandle);
public:
- explicit NativeFileSystemHandle(const String& name);
+ NativeFileSystemHandle(ExecutionContext* execution_context,
+ const String& name);
static NativeFileSystemHandle* CreateFromMojoEntry(
mojom::blink::NativeFileSystemEntryPtr,
ExecutionContext* execution_context);
@@ -37,7 +42,12 @@ class NativeFileSystemHandle : public ScriptWrappable {
ScriptPromise requestPermission(ScriptState*,
const FileSystemHandlePermissionDescriptor*);
- virtual mojom::blink::NativeFileSystemTransferTokenPtr Transfer() = 0;
+ // Grab a handle to a transfer token. This may return an invalid PendingRemote
+ // if the context is already destroyed.
+ virtual mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>
+ Transfer() = 0;
+
+ void Trace(Visitor*) override;
private:
virtual void QueryPermissionImpl(
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc
index 2d69acc7036..7d9b73fce32 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.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/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
@@ -26,9 +27,12 @@
namespace blink {
NativeFileSystemWriter::NativeFileSystemWriter(
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileWriter> mojo_ptr)
- : mojo_ptr_(std::move(mojo_ptr)) {
- DCHECK(mojo_ptr_);
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter>
+ writer_pending_remote)
+ : ContextLifecycleObserver(context),
+ writer_remote_(std::move(writer_pending_remote)) {
+ DCHECK(writer_remote_);
}
ScriptPromise NativeFileSystemWriter::write(
@@ -66,7 +70,7 @@ ScriptPromise NativeFileSystemWriter::write(
ScriptPromise NativeFileSystemWriter::WriteBlob(ScriptState* script_state,
uint64_t position,
Blob* blob) {
- if (!mojo_ptr_ || pending_operation_) {
+ if (!writer_remote_ || pending_operation_) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError));
@@ -74,14 +78,14 @@ ScriptPromise NativeFileSystemWriter::WriteBlob(ScriptState* script_state,
pending_operation_ =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = pending_operation_->Promise();
- mojo_ptr_->Write(
+ writer_remote_->Write(
position, blob->AsMojoBlob(),
WTF::Bind(&NativeFileSystemWriter::WriteComplete, WrapPersistent(this)));
return result;
}
class NativeFileSystemWriter::StreamWriterClient
- : public GarbageCollectedFinalized<StreamWriterClient>,
+ : public GarbageCollected<StreamWriterClient>,
public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(StreamWriterClient);
@@ -171,7 +175,7 @@ ScriptPromise NativeFileSystemWriter::WriteStream(
uint64_t position,
ReadableStream* stream,
ExceptionState& exception_state) {
- if (!mojo_ptr_ || pending_operation_) {
+ if (!writer_remote_ || pending_operation_) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError));
@@ -191,7 +195,7 @@ ScriptPromise NativeFileSystemWriter::WriteStream(
ScriptPromise result = pending_operation_->Promise();
auto* client = MakeGarbageCollected<StreamWriterClient>(this);
stream_loader_->Start(consumer, client);
- mojo_ptr_->WriteStream(
+ writer_remote_->WriteStream(
position, client->TakeDataPipe(),
WTF::Bind(&StreamWriterClient::WriteComplete, WrapPersistent(client)));
return result;
@@ -199,7 +203,7 @@ ScriptPromise NativeFileSystemWriter::WriteStream(
ScriptPromise NativeFileSystemWriter::truncate(ScriptState* script_state,
uint64_t size) {
- if (!mojo_ptr_ || pending_operation_) {
+ if (!writer_remote_ || pending_operation_) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError));
@@ -207,13 +211,14 @@ ScriptPromise NativeFileSystemWriter::truncate(ScriptState* script_state,
pending_operation_ =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = pending_operation_->Promise();
- mojo_ptr_->Truncate(size, WTF::Bind(&NativeFileSystemWriter::TruncateComplete,
- WrapPersistent(this)));
+ writer_remote_->Truncate(size,
+ WTF::Bind(&NativeFileSystemWriter::TruncateComplete,
+ WrapPersistent(this)));
return result;
}
ScriptPromise NativeFileSystemWriter::close(ScriptState* script_state) {
- if (!mojo_ptr_ || pending_operation_) {
+ if (!writer_remote_ || pending_operation_) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError));
@@ -221,7 +226,7 @@ ScriptPromise NativeFileSystemWriter::close(ScriptState* script_state) {
pending_operation_ =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise result = pending_operation_->Promise();
- mojo_ptr_->Close(
+ writer_remote_->Close(
WTF::Bind(&NativeFileSystemWriter::CloseComplete, WrapPersistent(this)));
return result;
@@ -229,6 +234,7 @@ ScriptPromise NativeFileSystemWriter::close(ScriptState* script_state) {
void NativeFileSystemWriter::Trace(Visitor* visitor) {
ScriptWrappable::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
visitor->Trace(file_);
visitor->Trace(pending_operation_);
visitor->Trace(stream_loader_);
@@ -257,7 +263,11 @@ void NativeFileSystemWriter::CloseComplete(
pending_operation_ = nullptr;
// We close the mojo pipe because we intend this writer to be discarded after
// close. Subsequent operations will fail.
- mojo_ptr_ = nullptr;
+ writer_remote_.reset();
+}
+
+void NativeFileSystemWriter::ContextDestroyed(ExecutionContext*) {
+ writer_remote_.reset();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h
index ba363d2902b..f7de9e038ad 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/native_file_system_writer.h
@@ -5,11 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_WRITER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_WRITER_H_
-#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_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/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
namespace blink {
@@ -22,12 +23,15 @@ class ScriptPromiseResolver;
class ScriptState;
class NativeFileSystemFileHandle;
-class NativeFileSystemWriter final : public ScriptWrappable {
+class NativeFileSystemWriter final : public ScriptWrappable,
+ public ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(NativeFileSystemWriter);
public:
- explicit NativeFileSystemWriter(
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileWriter>);
+ NativeFileSystemWriter(
+ ExecutionContext* context,
+ mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter>);
ScriptPromise write(ScriptState*,
uint64_t position,
@@ -37,6 +41,7 @@ class NativeFileSystemWriter final : public ScriptWrappable {
ScriptPromise close(ScriptState*);
void Trace(Visitor*) override;
+ void ContextDestroyed(ExecutionContext*) override;
private:
class StreamWriterClient;
@@ -52,7 +57,7 @@ class NativeFileSystemWriter final : public ScriptWrappable {
void TruncateComplete(mojom::blink::NativeFileSystemErrorPtr result);
void CloseComplete(mojom::blink::NativeFileSystemErrorPtr result);
- RevocableInterfacePtr<mojom::blink::NativeFileSystemFileWriter> mojo_ptr_;
+ mojo::Remote<mojom::blink::NativeFileSystemFileWriter> writer_remote_;
Member<NativeFileSystemFileHandle> file_;
Member<ScriptPromiseResolver> pending_operation_;
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc b/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc
index c4218a1c9cb..9e587365504 100644
--- a/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system.cc
@@ -12,8 +12,10 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/native_file_system/choose_file_system_entries_options.h"
#include "third_party/blink/renderer/modules/native_file_system/choose_file_system_entries_options_accepts.h"
#include "third_party/blink/renderer/modules/native_file_system/native_file_system_directory_handle.h"
@@ -75,7 +77,8 @@ ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries(
MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
}
- if (!window.GetFrame() || window.GetFrame()->IsCrossOriginSubframe()) {
+ LocalFrame* local_frame = window.GetFrame();
+ if (!local_frame || local_frame->IsCrossOriginSubframe()) {
return ScriptPromise::RejectWithDOMException(
script_state,
MakeGarbageCollected<DOMException>(
@@ -83,7 +86,7 @@ ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries(
"Cross origin sub frames aren't allowed to show a file picker."));
}
- if (!LocalFrame::HasTransientUserActivation(window.GetFrame())) {
+ if (!LocalFrame::HasTransientUserActivation(local_frame)) {
return ScriptPromise::RejectWithDOMException(
script_state,
MakeGarbageCollected<DOMException>(
@@ -119,6 +122,7 @@ ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries(
[](ScriptPromiseResolver* resolver,
mojo::Remote<mojom::blink::NativeFileSystemManager>,
const ChooseFileSystemEntriesOptions* options,
+ LocalFrame* local_frame,
mojom::blink::NativeFileSystemErrorPtr file_operation_result,
Vector<mojom::blink::NativeFileSystemEntryPtr> entries) {
ExecutionContext* context = resolver->GetExecutionContext();
@@ -130,6 +134,17 @@ ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries(
*file_operation_result);
return;
}
+
+ // While it would be better to not trust the renderer process,
+ // we're doing this here to avoid potential mojo message pipe
+ // ordering problems, where the frame activation state
+ // reconciliation messages would compete with concurrent Native File
+ // System messages to the browser.
+ // TODO(https://crbug.com/1017270): Remove this after spec change,
+ // or when activation moves to browser.
+ LocalFrame::NotifyUserActivation(local_frame,
+ UserGestureToken::kNewGesture);
+
if (options->multiple()) {
HeapVector<Member<NativeFileSystemHandle>> results;
results.ReserveInitialCapacity(entries.size());
@@ -144,8 +159,8 @@ ScriptPromise WindowNativeFileSystem::chooseFileSystemEntries(
std::move(entries[0]), context));
}
},
- WrapPersistent(resolver), std::move(manager),
- WrapPersistent(options)));
+ WrapPersistent(resolver), std::move(manager), WrapPersistent(options),
+ WrapPersistent(local_frame)));
return resolver_result;
}
diff --git a/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc b/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc
new file mode 100644
index 00000000000..4fdcf6ca64c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/native_file_system/window_native_file_system_test.cc
@@ -0,0 +1,216 @@
+// 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/native_file_system/window_native_file_system.h"
+
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_directory_handle.mojom-blink.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_error.mojom-blink.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_file_handle.mojom-blink.h"
+#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
+#include "third_party/blink/renderer/core/dom/user_gesture_indicator.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/html/forms/html_button_element.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+class MockNativeFileSystemManager
+ : public mojom::blink::NativeFileSystemManager {
+ public:
+ MockNativeFileSystemManager(service_manager::InterfaceProvider* provider,
+ base::OnceClosure reached_callback)
+ : reached_callback_(std::move(reached_callback)), provider_(provider) {
+ service_manager::InterfaceProvider::TestApi(provider_).SetBinderForName(
+ mojom::blink::NativeFileSystemManager::Name_,
+ WTF::BindRepeating(
+ &MockNativeFileSystemManager::BindNativeFileSystemManager,
+ WTF::Unretained(this)));
+ }
+ MockNativeFileSystemManager(service_manager::InterfaceProvider* provider)
+ : provider_(provider) {
+ service_manager::InterfaceProvider::TestApi(provider_).SetBinderForName(
+ mojom::blink::NativeFileSystemManager::Name_,
+ WTF::BindRepeating(
+ &MockNativeFileSystemManager::BindNativeFileSystemManager,
+ WTF::Unretained(this)));
+ }
+ ~MockNativeFileSystemManager() override {
+ service_manager::InterfaceProvider::TestApi(provider_).SetBinderForName(
+ mojom::blink::NativeFileSystemManager::Name_, {});
+ }
+
+ using ChooseEntriesResponseCallback =
+ base::OnceCallback<void(ChooseEntriesCallback callback)>;
+
+ void SetQuitClosure(base::OnceClosure reached_callback) {
+ reached_callback_ = std::move(reached_callback);
+ }
+
+ // Unused for these tests.
+ void GetSandboxedFileSystem(
+ GetSandboxedFileSystemCallback callback) override {}
+
+ void ChooseEntries(
+ mojom::ChooseFileSystemEntryType type,
+ WTF::Vector<mojom::blink::ChooseFileSystemEntryAcceptsOptionPtr> accepts,
+ bool include_accepts_all,
+ ChooseEntriesCallback callback) override {
+ if (choose_entries_response_callback_) {
+ std::move(choose_entries_response_callback_).Run(std::move(callback));
+ }
+
+ if (reached_callback_)
+ std::move(reached_callback_).Run();
+ }
+
+ void SetChooseEntriesResponse(ChooseEntriesResponseCallback callback) {
+ choose_entries_response_callback_ = std::move(callback);
+ }
+
+ private:
+ void BindNativeFileSystemManager(mojo::ScopedMessagePipeHandle handle) {
+ receivers_.Add(this,
+ mojo::PendingReceiver<mojom::blink::NativeFileSystemManager>(
+ std::move(handle)));
+ }
+
+ base::OnceClosure reached_callback_;
+ ChooseEntriesResponseCallback choose_entries_response_callback_;
+ mojo::ReceiverSet<mojom::blink::NativeFileSystemManager> receivers_;
+ service_manager::InterfaceProvider* provider_;
+};
+
+class WindowNativeFileSystemTest : public PageTestBase {
+ public:
+ void SetUp() override {
+ PageTestBase::SetUp();
+ Navigate("http://localhost");
+ GetDocument().GetSettings()->SetScriptEnabled(true);
+ }
+
+ void Navigate(const String& destinationUrl) {
+ const KURL& url = KURL(NullURL(), destinationUrl);
+ auto navigation_params =
+ WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(), url);
+ GetDocument().GetFrame()->Loader().CommitNavigation(
+ std::move(navigation_params), /*extra_data=*/nullptr);
+ blink::test::RunPendingTasks();
+ ASSERT_EQ(url.GetString(), GetDocument().Url().GetString());
+ }
+};
+
+TEST_F(WindowNativeFileSystemTest, UserActivationRequiredOtherwiseDenied) {
+ LocalFrame* frame = &GetFrame();
+ EXPECT_FALSE(frame->HasBeenActivated());
+
+ MockNativeFileSystemManager manager(&frame->GetInterfaceProvider());
+ manager.SetChooseEntriesResponse(WTF::Bind(
+ [](MockNativeFileSystemManager::ChooseEntriesCallback callback) {
+ FAIL();
+ }));
+ GetFrame().GetScriptController().ExecuteScriptInMainWorld(
+ "window.chooseFileSystemEntries({type: 'openFile'});");
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(frame->HasBeenActivated());
+}
+
+TEST_F(WindowNativeFileSystemTest, UserActivationChooseEntriesSuccessful) {
+ LocalFrame* frame = &GetFrame();
+ EXPECT_FALSE(frame->HasBeenActivated());
+
+ LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+ EXPECT_TRUE(frame->HasBeenActivated());
+
+ base::RunLoop manager_run_loop;
+ MockNativeFileSystemManager manager(&frame->GetInterfaceProvider(),
+ manager_run_loop.QuitClosure());
+ manager.SetChooseEntriesResponse(WTF::Bind(
+ [](MockNativeFileSystemManager::ChooseEntriesCallback callback) {
+ auto error = mojom::blink::NativeFileSystemError::New();
+ error->status = mojom::blink::NativeFileSystemStatus::kOk;
+ error->message = "";
+
+ mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle>
+ pending_remote;
+ ignore_result(pending_remote.InitWithNewPipeAndPassReceiver());
+ auto handle = mojom::blink::NativeFileSystemHandle::NewFile(
+ std::move(pending_remote));
+ auto entry = mojom::blink::NativeFileSystemEntry::New(std::move(handle),
+ "foo.txt");
+ Vector<mojom::blink::NativeFileSystemEntryPtr> entries;
+ entries.push_back(std::move(entry));
+
+ std::move(callback).Run(std::move(error), std::move(entries));
+ }));
+ GetFrame().GetScriptController().ExecuteScriptInMainWorld(
+ "window.chooseFileSystemEntries({type: 'openFile'});");
+ manager_run_loop.Run();
+
+ // Mock Manager finished sending data over the mojo pipe.
+ // Clearing the user activation.
+ frame->ClearActivation();
+ EXPECT_FALSE(frame->HasBeenActivated());
+
+ // Let blink-side receiver process the response and set the user activation
+ // again.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(frame->HasBeenActivated());
+}
+
+TEST_F(WindowNativeFileSystemTest, UserActivationChooseEntriesErrors) {
+ LocalFrame* frame = &GetFrame();
+ EXPECT_FALSE(frame->HasBeenActivated());
+
+ using mojom::blink::NativeFileSystemStatus;
+
+ NativeFileSystemStatus statuses[] = {
+ NativeFileSystemStatus::kPermissionDenied,
+ NativeFileSystemStatus::kInvalidState,
+ NativeFileSystemStatus::kInvalidArgument,
+ NativeFileSystemStatus::kOperationFailed,
+ // kOperationAborted is when the user cancels the file selection.
+ NativeFileSystemStatus::kOperationAborted,
+ };
+ MockNativeFileSystemManager manager(&frame->GetInterfaceProvider());
+
+ for (const NativeFileSystemStatus& status : statuses) {
+ LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture);
+ EXPECT_TRUE(frame->HasBeenActivated());
+
+ base::RunLoop manager_run_loop;
+ manager.SetQuitClosure(manager_run_loop.QuitClosure());
+ manager.SetChooseEntriesResponse(WTF::Bind(
+ [](mojom::blink::NativeFileSystemStatus status,
+ MockNativeFileSystemManager::ChooseEntriesCallback callback) {
+ auto error = mojom::blink::NativeFileSystemError::New();
+ error->status = status;
+ error->message = "";
+ Vector<mojom::blink::NativeFileSystemEntryPtr> entries;
+
+ std::move(callback).Run(std::move(error), std::move(entries));
+ },
+ status));
+ GetFrame().GetScriptController().ExecuteScriptInMainWorld(
+ "window.chooseFileSystemEntries({type: 'openFile'});");
+ manager_run_loop.Run();
+
+ // Mock Manager finished sending data over the mojo pipe.
+ // Clearing the user activation.
+ frame->ClearActivation();
+ EXPECT_FALSE(frame->HasBeenActivated());
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(frame->HasBeenActivated());
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h
index 32a4bc3ef24..0abb5f1a16c 100644
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h
+++ b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h
@@ -41,7 +41,7 @@ class NavigatorContentUtilsClient;
// It is owned by Navigator, and an instance is created lazily by calling
// NavigatorContentUtils::From() via [register/unregister]ProtocolHandler.
class MODULES_EXPORT NavigatorContentUtils final
- : public GarbageCollectedFinalized<NavigatorContentUtils>,
+ : public GarbageCollected<NavigatorContentUtils>,
public Supplement<Navigator> {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorContentUtils);
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h
index 98f1abb3128..0f299809ada 100644
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h
+++ b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h
@@ -15,7 +15,7 @@ class KURL;
class WebLocalFrameImpl;
class MODULES_EXPORT NavigatorContentUtilsClient
- : public GarbageCollectedFinalized<NavigatorContentUtilsClient> {
+ : public GarbageCollected<NavigatorContentUtilsClient> {
public:
explicit NavigatorContentUtilsClient(WebLocalFrameImpl*);
virtual ~NavigatorContentUtilsClient() = default;
diff --git a/chromium/third_party/blink/renderer/modules/netinfo/testing/internals_net_info.cc b/chromium/third_party/blink/renderer/modules/netinfo/testing/internals_net_info.cc
index df7f64fe007..b4a199e6faf 100644
--- a/chromium/third_party/blink/renderer/modules/netinfo/testing/internals_net_info.cc
+++ b/chromium/third_party/blink/renderer/modules/netinfo/testing/internals_net_info.cc
@@ -70,8 +70,6 @@ void InternalsNetInfo::setNetworkConnectionInfoOverride(
}
GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
on_line, webtype, web_effective_type, http_rtt_msec, downlink_max_mbps);
- internals.GetFrame()->Client()->SetEffectiveConnectionTypeForTesting(
- web_effective_type);
}
void InternalsNetInfo::setSaveDataEnabled(Internals&, bool enabled) {
diff --git a/chromium/third_party/blink/renderer/modules/nfc/BUILD.gn b/chromium/third_party/blink/renderer/modules/nfc/BUILD.gn
index bb111904cf8..2ee6df3bd57 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/nfc/BUILD.gn
@@ -10,8 +10,6 @@ blink_modules_sources("nfc") {
"ndef_message.h",
"ndef_record.cc",
"ndef_record.h",
- "nfc_constants.cc",
- "nfc_constants.h",
"nfc_error_event.cc",
"nfc_error_event.h",
"nfc_proxy.cc",
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 3c6f763c421..c30cffd66f3 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_message.cc
@@ -59,7 +59,7 @@ NDEFMessage::NDEFMessage() = default;
NDEFMessage::NDEFMessage(const device::mojom::blink::NDEFMessage& message)
: url_(message.url) {
for (wtf_size_t i = 0; i < message.data.size(); ++i) {
- records_.push_back(MakeGarbageCollected<NDEFRecord>(message.data[i]));
+ records_.push_back(MakeGarbageCollected<NDEFRecord>(*message.data[i]));
}
}
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 1bd4656a7d3..eb8e936ecd0 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.cc
@@ -13,6 +13,8 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
namespace blink {
@@ -26,12 +28,52 @@ WTF::Vector<uint8_t> GetUTF8DataFromString(const String& string) {
return data;
}
+// https://w3c.github.io/web-nfc/#the-ndefrecordtype-string
+// Derives a formatted custom type for the external type record from |input|.
+// Returns a null string for an invalid |input|.
+//
+// TODO(https://crbug.com/520391): Refine the validation algorithm here
+// accordingly once there is a conclusion on some case-sensitive things at
+// https://github.com/w3c/web-nfc/issues/331.
+String ValidateCustomRecordType(const String& input) {
+ static const String kOtherCharsForCustomType("()+,-:=@;$_!*'.");
+
+ if (input.IsEmpty())
+ return String();
+
+ // Finds the separator ':'.
+ wtf_size_t colon_index = input.find(':');
+ if (colon_index == kNotFound)
+ return String();
+
+ // Derives the domain (FQDN) from the part before ':'.
+ String left = input.Left(colon_index);
+ bool success = false;
+ String domain = SecurityOrigin::CanonicalizeHost(left, &success);
+ if (!success || domain.IsEmpty())
+ return String();
+
+ // Validates the part after ':'.
+ String right = input.Substring(colon_index + 1);
+ if (right.length() == 0)
+ return String();
+ for (wtf_size_t i = 0; i < right.length(); i++) {
+ if (!IsASCIIAlphanumeric(right[i]) &&
+ !kOtherCharsForCustomType.Contains(right[i])) {
+ return String();
+ }
+ }
+
+ return domain + ':' + right;
+}
+
static NDEFRecord* CreateTextRecord(const String& media_type,
const ScriptValue& data,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-string-to-ndef
if (data.IsEmpty() || !data.V8Value()->IsString()) {
- exception_state.ThrowTypeError(kNfcTextRecordTypeError);
+ exception_state.ThrowTypeError(
+ "The data for 'text' NDEFRecords must be a String.");
return nullptr;
}
@@ -43,10 +85,10 @@ static NDEFRecord* CreateTextRecord(const String& media_type,
// always uses "lang=en-US;charset=UTF-8" when pushing the record to a NFC
// tag.
if (mime_type.IsEmpty()) {
- mime_type = kNfcPlainTextMimeType;
- } else if (!mime_type.StartsWithIgnoringASCIICase(kNfcPlainTextMimePrefix)) {
+ mime_type = "text/plain";
+ } else if (!mime_type.StartsWithIgnoringASCIICase("text/")) {
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- kNfcTextRecordMediaTypeError);
+ "Invalid media type for 'text' record.");
return nullptr;
}
@@ -60,7 +102,8 @@ static NDEFRecord* CreateUrlRecord(const String& media_type,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-url-to-ndef
if (data.IsEmpty() || !data.V8Value()->IsString()) {
- exception_state.ThrowTypeError(kNfcUrlRecordTypeError);
+ exception_state.ThrowTypeError(
+ "The data for 'url' NDEFRecord must be a String.");
return nullptr;
}
@@ -68,7 +111,7 @@ static NDEFRecord* CreateUrlRecord(const String& media_type,
String url = ToCoreString(data.V8Value().As<v8::String>());
if (!KURL(NullURL(), url).IsValid()) {
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- kNfcUrlRecordParseError);
+ "Cannot parse data for 'url' record.");
return nullptr;
}
return MakeGarbageCollected<NDEFRecord>("url", media_type,
@@ -80,22 +123,22 @@ static NDEFRecord* CreateJsonRecord(const String& media_type,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-json-to-ndef
if (data.IsEmpty()) {
- exception_state.ThrowTypeError(kNfcJsonRecordNoDataError);
+ exception_state.ThrowTypeError(
+ "The data for 'json' NDEFRecord is missing.");
return nullptr;
}
// ExtractMIMETypeFromMediaType() ignores parameters of the MIME type.
String mime_type = ExtractMIMETypeFromMediaType(AtomicString(media_type));
if (mime_type.IsEmpty()) {
- mime_type = kNfcJsonMimeType;
- } else if (mime_type != kNfcJsonMimeType &&
- mime_type != kNfcJsonTextMimeType &&
- !mime_type.EndsWithIgnoringASCIICase(kNfcJsonMimePostfix)) {
+ mime_type = "application/json";
+ } else if (mime_type != "application/json" && mime_type != "text/json" &&
+ !mime_type.EndsWithIgnoringASCIICase("+json")) {
// According to https://mimesniff.spec.whatwg.org/#json-mime-type, a JSON
// MIME type is any MIME type whose subtype ends in "+json" or whose
// essence is "application/json" or "text/json".
exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
- kNfcJsonRecordMediaTypeError);
+ "Invalid media type for 'json' record.");
return nullptr;
}
@@ -120,14 +163,15 @@ static NDEFRecord* CreateOpaqueRecord(const String& media_type,
ExceptionState& exception_state) {
// https://w3c.github.io/web-nfc/#mapping-binary-data-to-ndef
if (data.IsEmpty() || !data.V8Value()->IsArrayBuffer()) {
- exception_state.ThrowTypeError(kNfcOpaqueRecordTypeError);
+ exception_state.ThrowTypeError(
+ "The data for 'opaque' NDEFRecord must be an ArrayBuffer.");
return nullptr;
}
// ExtractMIMETypeFromMediaType() ignores parameters of the MIME type.
String mime_type = ExtractMIMETypeFromMediaType(AtomicString(media_type));
if (mime_type.IsEmpty()) {
- mime_type = kNfcOpaqueMimeType;
+ mime_type = "application/octet-stream";
}
DOMArrayBuffer* array_buffer =
V8ArrayBuffer::ToImpl(data.V8Value().As<v8::Object>());
@@ -138,6 +182,25 @@ static NDEFRecord* CreateOpaqueRecord(const String& media_type,
std::move(bytes));
}
+static NDEFRecord* CreateExternalRecord(const String& custom_type,
+ const ScriptValue& data,
+ ExceptionState& exception_state) {
+ // https://w3c.github.io/web-nfc/#dfn-map-external-data-to-ndef
+ if (data.IsEmpty() || !data.V8Value()->IsArrayBuffer()) {
+ exception_state.ThrowTypeError(
+ "The data for external type NDEFRecord must be an ArrayBuffer.");
+ return nullptr;
+ }
+
+ DOMArrayBuffer* array_buffer =
+ V8ArrayBuffer::ToImpl(data.V8Value().As<v8::Object>());
+ WTF::Vector<uint8_t> bytes;
+ bytes.Append(static_cast<uint8_t*>(array_buffer->Data()),
+ array_buffer->ByteLength());
+ return MakeGarbageCollected<NDEFRecord>(
+ custom_type, "application/octet-stream", std::move(bytes));
+}
+
} // namespace
// static
@@ -175,10 +238,18 @@ NDEFRecord* NDEFRecord::Create(const NDEFRecordInit* init,
return CreateJsonRecord(init->mediaType(), init->data(), exception_state);
} else if (record_type == "opaque") {
return CreateOpaqueRecord(init->mediaType(), init->data(), exception_state);
+ } else if (record_type == "smart-poster") {
+ // TODO(https://crbug.com/520391): Support creating smart-poster records.
+ exception_state.ThrowTypeError("smart-poster type is not supported yet");
+ return nullptr;
+ } else {
+ String formated_type = ValidateCustomRecordType(record_type);
+ if (!formated_type.IsNull())
+ return CreateExternalRecord(formated_type, init->data(), exception_state);
}
- NOTREACHED();
- return nullptr;
+ exception_state.ThrowTypeError("Unknown NDEFRecord type.");
+ return nullptr;
}
NDEFRecord::NDEFRecord(const String& record_type,
@@ -190,19 +261,19 @@ NDEFRecord::NDEFRecord(const String& record_type,
NDEFRecord::NDEFRecord(const String& text)
: record_type_("text"),
- media_type_(StringView(kNfcPlainTextMimeType) + kNfcCharSetUTF8),
+ media_type_("text/plain;charset=UTF-8"),
data_(GetUTF8DataFromString(text)) {}
NDEFRecord::NDEFRecord(DOMArrayBuffer* array_buffer)
- : record_type_("opaque"), media_type_(kNfcOpaqueMimeType) {
+ : record_type_("opaque"), media_type_("application/octet-stream") {
data_.Append(static_cast<uint8_t*>(array_buffer->Data()),
array_buffer->ByteLength());
}
-NDEFRecord::NDEFRecord(const device::mojom::blink::NDEFRecordPtr& record)
- : record_type_(NDEFRecordTypeToString(record->record_type)),
- media_type_(record->media_type),
- data_(record->data) {}
+NDEFRecord::NDEFRecord(const device::mojom::blink::NDEFRecord& record)
+ : record_type_(record.record_type),
+ media_type_(record.media_type),
+ data_(record.data) {}
const String& NDEFRecord::recordType() const {
return record_type_;
@@ -212,10 +283,8 @@ const String& NDEFRecord::mediaType() const {
return media_type_;
}
-String NDEFRecord::toText() const {
- device::mojom::blink::NDEFRecordType type =
- StringToNDEFRecordType(record_type_);
- if (type == device::mojom::blink::NDEFRecordType::EMPTY)
+String NDEFRecord::text() const {
+ if (record_type_ == "empty")
return String();
// TODO(https://crbug.com/520391): Support utf-16 decoding for 'TEXT' record
@@ -224,25 +293,25 @@ String NDEFRecord::toText() const {
return String::FromUTF8WithLatin1Fallback(data_.data(), data_.size());
}
-DOMArrayBuffer* NDEFRecord::toArrayBuffer() const {
- device::mojom::blink::NDEFRecordType type =
- StringToNDEFRecordType(record_type_);
- if (type != device::mojom::blink::NDEFRecordType::JSON &&
- type != device::mojom::blink::NDEFRecordType::OPAQUE_RECORD) {
+DOMArrayBuffer* NDEFRecord::arrayBuffer() const {
+ if (record_type_ == "empty" || record_type_ == "text" ||
+ record_type_ == "url") {
return nullptr;
}
+ DCHECK(record_type_ == "json" || record_type_ == "opaque" ||
+ !ValidateCustomRecordType(record_type_).IsNull());
return DOMArrayBuffer::Create(data_.data(), data_.size());
}
-ScriptValue NDEFRecord::toJSON(ScriptState* script_state,
- ExceptionState& exception_state) const {
- device::mojom::blink::NDEFRecordType type =
- StringToNDEFRecordType(record_type_);
- if (type != device::mojom::blink::NDEFRecordType::JSON &&
- type != device::mojom::blink::NDEFRecordType::OPAQUE_RECORD) {
- return ScriptValue::CreateNull(script_state);
+ScriptValue NDEFRecord::json(ScriptState* script_state,
+ ExceptionState& exception_state) const {
+ if (record_type_ == "empty" || record_type_ == "text" ||
+ record_type_ == "url") {
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
+ DCHECK(record_type_ == "json" || record_type_ == "opaque" ||
+ !ValidateCustomRecordType(record_type_).IsNull());
ScriptState::Scope scope(script_state);
v8::Local<v8::Value> json_object = FromJSONString(
@@ -250,8 +319,8 @@ ScriptValue NDEFRecord::toJSON(ScriptState* script_state,
String::FromUTF8WithLatin1Fallback(data_.data(), data_.size()),
exception_state);
if (exception_state.HadException())
- return ScriptValue::CreateNull(script_state);
- return ScriptValue(script_state, json_object);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
+ return ScriptValue(script_state->GetIsolate(), json_object);
}
const WTF::Vector<uint8_t>& NDEFRecord::data() const {
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 d79185d7462..a77a38276d0 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.h
@@ -33,13 +33,13 @@ class MODULES_EXPORT NDEFRecord final : public ScriptWrappable {
explicit NDEFRecord(DOMArrayBuffer*);
NDEFRecord(const String&, const String&, WTF::Vector<uint8_t>);
- explicit NDEFRecord(const device::mojom::blink::NDEFRecordPtr&);
+ explicit NDEFRecord(const device::mojom::blink::NDEFRecord&);
const String& recordType() const;
const String& mediaType() const;
- String toText() const;
- DOMArrayBuffer* toArrayBuffer() const;
- ScriptValue toJSON(ScriptState*, ExceptionState&) const;
+ String text() const;
+ DOMArrayBuffer* arrayBuffer() const;
+ ScriptValue json(ScriptState*, ExceptionState&) const;
const WTF::Vector<uint8_t>& data() const;
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.idl b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.idl
index 8a7a3336844..e751a681c8c 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record.idl
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record.idl
@@ -13,7 +13,7 @@
] interface NDEFRecord {
readonly attribute NDEFRecordType recordType;
readonly attribute USVString mediaType;
- USVString? toText();
- [NewObject] ArrayBuffer? toArrayBuffer();
- [CallWith=ScriptState, RaisesException] object? toJSON();
+ USVString? text();
+ [NewObject] ArrayBuffer? arrayBuffer();
+ [CallWith=ScriptState, RaisesException] object? json();
};
diff --git a/chromium/third_party/blink/renderer/modules/nfc/ndef_record_init.idl b/chromium/third_party/blink/renderer/modules/nfc/ndef_record_init.idl
index 0bb871c321b..af2d2f1e3a8 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/ndef_record_init.idl
+++ b/chromium/third_party/blink/renderer/modules/nfc/ndef_record_init.idl
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://w3c.github.io/web-nfc/#dom-ndefrecordinit
+// https://w3c.github.io/web-nfc/#the-ndefrecordtype-string
-enum NDEFRecordType { "empty", "text", "url", "json", "opaque" };
+typedef DOMString NDEFRecordType;
typedef any NDEFRecordData;
+// https://w3c.github.io/web-nfc/#dom-ndefrecordinit
+
dictionary NDEFRecordInit {
NDEFRecordType recordType;
USVString mediaType;
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.cc
deleted file mode 100644
index 6961e4ad108..00000000000
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.cc
+++ /dev/null
@@ -1,61 +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/nfc/nfc_constants.h"
-
-namespace blink {
-
-const char kNfcJsonMimePostfix[] = "+json";
-const char kNfcJsonMimePrefix[] = "application/";
-const char kNfcJsonMimeType[] = "application/json";
-const char kNfcJsonTextMimeType[] = "text/json";
-const char kNfcOpaqueMimeType[] = "application/octet-stream";
-const char kNfcPlainTextMimeType[] = "text/plain";
-const char kNfcPlainTextMimePrefix[] = "text/";
-const char kNfcProtocolHttps[] = "https";
-const char kNfcCharSetUTF8[] = ";charset=UTF-8";
-
-// Error messages.
-const char kNfcNotAllowed[] = "NFC operation not allowed.";
-const char kNfcNotSupported[] =
- "No NFC adapter or cannot establish connection.";
-const char kNfcNotReadable[] = "NFC is not enabled.";
-const char kNfcTextRecordTypeError[] =
- "The data for 'text' NDEFRecords must be of String.";
-const char kNfcSetIdError[] = "Cannot set WebNFC Id.";
-const char kNfcTextRecordMediaTypeError[] =
- "Invalid media type for 'text' record.";
-const char kNfcUrlRecordTypeError[] =
- "The data for 'url' NDEFRecord must be of String type.";
-const char kNfcUrlRecordParseError[] = "Cannot parse data for 'url' record.";
-const char kNfcJsonRecordNoDataError[] =
- "The data for 'json' NDEFRecord is missing.";
-const char kNfcJsonRecordStringifyError[] =
- "Cannot stringify data for 'json' record.";
-const char kNfcJsonRecordMediaTypeError[] =
- "Invalid media type for 'json' record.";
-const char kNfcOpaqueRecordTypeError[] =
- "The data for 'opaque' NDEFRecord must be of ArrayBuffer type.";
-const char kNfcRecordTypeError[] = "Unknown NDEFRecord type.";
-const char kNfcRecordDataError[] = "Nonempty NDEFRecord must have data.";
-const char kNfcRecordError[] = "Invalid NDEFRecordType was provided.";
-const char kNfcMsgTypeError[] = "Invalid NDEFMessageSource type was provided.";
-const char kNfcEmptyMsg[] = "Empty NDEFMessage was provided.";
-const char kNfcInvalidMsg[] = "Invalid NFC message was provided.";
-const char kNfcMsgConvertError[] = "Cannot convert NDEFMessage.";
-const char kNfcMsgMaxSizeError[] =
- "NDEFMessage exceeds maximum supported size.";
-const char kNfcUrlPatternError[] = "Invalid URL pattern was provided.";
-const char kNfcInvalidPushTimeout[] =
- "Invalid NFCPushOptions.timeout value was provided.";
-const char kNfcWatchIdNotFound[] = "Provided watch id cannot be found.";
-const char kNfcAccessInNonTopFrame[] =
- "NFC interfaces are only avaliable in a top-level browsing context";
-const char kNfcCancelled[] = "The NFC operation was cancelled.";
-const char kNfcTimeout[] = "NFC operation has timed out.";
-const char kNfcUnknownError[] = "An unknown NFC error has occurred.";
-const char kNfcDataTransferError[] = "NFC data transfer error has occurred.";
-const char kNfcNoModificationAllowed[] = "NFC operation cannot be cancelled.";
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.h b/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.h
deleted file mode 100644
index 8196666b4fd..00000000000
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_constants.h
+++ /dev/null
@@ -1,54 +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_NFC_NFC_CONSTANTS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_NFC_NFC_CONSTANTS_H_
-
-
-namespace blink {
-
-extern const char kNfcJsonMimePostfix[];
-extern const char kNfcJsonMimePrefix[];
-extern const char kNfcJsonMimeType[];
-extern const char kNfcJsonTextMimeType[];
-extern const char kNfcOpaqueMimeType[];
-extern const char kNfcPlainTextMimeType[];
-extern const char kNfcPlainTextMimePrefix[];
-extern const char kNfcProtocolHttps[];
-extern const char kNfcCharSetUTF8[];
-
-// Error messages.
-extern const char kNfcNotAllowed[];
-extern const char kNfcNotSupported[];
-extern const char kNfcNotReadable[];
-extern const char kNfcTextRecordTypeError[];
-extern const char kNfcSetIdError[];
-extern const char kNfcTextRecordMediaTypeError[];
-extern const char kNfcUrlRecordTypeError[];
-extern const char kNfcUrlRecordParseError[];
-extern const char kNfcJsonRecordNoDataError[];
-extern const char kNfcJsonRecordStringifyError[];
-extern const char kNfcJsonRecordMediaTypeError[];
-extern const char kNfcOpaqueRecordTypeError[];
-extern const char kNfcRecordTypeError[];
-extern const char kNfcRecordDataError[];
-extern const char kNfcRecordError[];
-extern const char kNfcMsgTypeError[];
-extern const char kNfcEmptyMsg[];
-extern const char kNfcInvalidMsg[];
-extern const char kNfcMsgConvertError[];
-extern const char kNfcMsgMaxSizeError[];
-extern const char kNfcUrlPatternError[];
-extern const char kNfcInvalidPushTimeout[];
-extern const char kNfcWatchIdNotFound[];
-extern const char kNfcAccessInNonTopFrame[];
-extern const char kNfcCancelled[];
-extern const char kNfcTimeout[];
-extern const char kNfcUnknownError[];
-extern const char kNfcDataTransferError[];
-extern const char kNfcNoModificationAllowed[];
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NFC_NFC_CONSTANTS_H_
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.cc
index df9306051fa..58c193ebb73 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/modules/nfc/nfc_reader.h"
#include "third_party/blink/renderer/modules/nfc/nfc_type_converters.h"
@@ -188,7 +188,7 @@ void NFCProxy::EnsureMojoConnection() {
if (nfc_remote_)
return;
- GetSupplementable()->GetInterfaceProvider()->GetInterface(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
nfc_remote_.BindNewPipeAndPassReceiver());
nfc_remote_.set_disconnect_handler(
WTF::Bind(&NFCProxy::OnMojoConnectionError, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.h b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.h
index 1362c6ec97a..95009090abd 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_proxy.h
@@ -23,12 +23,11 @@ class NFCWriter;
// This is a proxy class used by NFCWriter(s) and NFCReader(s) to connect
// to implementation of device::mojom::blink::NFC interface.
-class MODULES_EXPORT NFCProxy final
- : public GarbageCollectedFinalized<NFCProxy>,
- public PageVisibilityObserver,
- public FocusChangedObserver,
- public Supplement<Document>,
- public device::mojom::blink::NFCClient {
+class MODULES_EXPORT NFCProxy final : public GarbageCollected<NFCProxy>,
+ public PageVisibilityObserver,
+ public FocusChangedObserver,
+ public Supplement<Document>,
+ public device::mojom::blink::NFCClient {
USING_GARBAGE_COLLECTED_MIXIN(NFCProxy);
USING_PRE_FINALIZER(NFCProxy, Dispose);
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 2a2ac6859a5..eac4afaff36 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
@@ -8,9 +8,10 @@
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/modules/nfc/nfc_proxy.h"
@@ -62,7 +63,8 @@ class FakeNfcService : public device::mojom::blink::NFC {
void BindRequest(mojo::ScopedMessagePipeHandle handle) {
DCHECK(!receiver_.is_bound());
- receiver_.Bind(device::mojom::blink::NFCRequest(std::move(handle)));
+ receiver_.Bind(
+ mojo::PendingReceiver<device::mojom::blink::NFC>(std::move(handle)));
receiver_.set_disconnect_handler(
WTF::Bind(&FakeNfcService::OnConnectionError, WTF::Unretained(this)));
}
@@ -152,15 +154,17 @@ class NFCProxyTest : public PageTestBase {
void SetUp() override {
PageTestBase::SetUp(IntSize());
-
- service_manager::InterfaceProvider::TestApi test_api(
- GetDocument().GetInterfaceProvider());
- test_api.SetBinderForName(
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
device::mojom::blink::NFC::Name_,
WTF::BindRepeating(&FakeNfcService::BindRequest,
WTF::Unretained(nfc_service())));
}
+ void TearDown() override {
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
+ device::mojom::blink::NFC::Name_, {});
+ }
+
FakeNfcService* nfc_service() { return nfc_service_.get(); }
void DestroyNfcService() { nfc_service_.reset(); }
@@ -187,7 +191,7 @@ TEST_F(NFCProxyTest, SuccessfulPath) {
auto record = device::mojom::blink::NDEFRecord::New();
WTF::Vector<uint8_t> record_data(
{0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10});
- record->record_type = device::mojom::blink::NDEFRecordType::OPAQUE_RECORD;
+ record->record_type = "opaque";
record->data = WTF::Vector<uint8_t>(record_data);
message->data.push_back(std::move(record));
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_push_options.idl b/chromium/third_party/blink/renderer/modules/nfc/nfc_push_options.idl
index 39da64fce2c..2156206ce72 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_push_options.idl
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_push_options.idl
@@ -11,5 +11,4 @@ dictionary NFCPushOptions {
unrestricted double timeout; // in ms
boolean ignoreRead = true;
AbortSignal? signal;
- NDEFCompatibility compatibility = "nfc-forum";
};
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_reader.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_reader.cc
index 1cc7e8cb5c1..5fbab481088 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_reader.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_reader.cc
@@ -10,7 +10,6 @@
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
-#include "third_party/blink/renderer/modules/nfc/nfc_constants.h"
#include "third_party/blink/renderer/modules/nfc/nfc_error_event.h"
#include "third_party/blink/renderer/modules/nfc/nfc_proxy.h"
#include "third_party/blink/renderer/modules/nfc/nfc_reading_event.h"
@@ -26,7 +25,11 @@ NFCReader* NFCReader::Create(ExecutionContext* context) {
}
NFCReader::NFCReader(ExecutionContext* context)
- : ContextLifecycleObserver(context) {}
+ : ContextLifecycleObserver(context) {
+ // Call GetNFCProxy to create a proxy. This guarantees no allocation will
+ // be needed when calling HasPendingActivity later during gc tracing.
+ GetNfcProxy();
+}
NFCReader::~NFCReader() = default;
@@ -63,11 +66,11 @@ void NFCReader::scan(const NFCScanOptions* options) {
// pattern, fire a NFCErrorEvent with "SyntaxError" DOMException, then return.
if (options->hasURL() && !options->url().IsEmpty()) {
KURL pattern_url(options->url());
- if (!pattern_url.IsValid() || pattern_url.Protocol() != kNfcProtocolHttps) {
+ if (!pattern_url.IsValid() || pattern_url.Protocol() != "https") {
DispatchEvent(*MakeGarbageCollected<NFCErrorEvent>(
- event_type_names::kError,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
- kNfcUrlPatternError)));
+ event_type_names::kError, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kSyntaxError,
+ "Invalid URL pattern was provided.")));
return;
}
}
@@ -112,7 +115,8 @@ bool NFCReader::CheckSecurity() {
DispatchEvent(*MakeGarbageCollected<NFCErrorEvent>(
event_type_names::kError,
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotAllowedError,
- kNfcAccessInNonTopFrame)));
+ "NFC interfaces are only avaliable "
+ "in a top-level browsing context")));
return false;
}
return true;
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_scan_options.idl b/chromium/third_party/blink/renderer/modules/nfc/nfc_scan_options.idl
index 71113658a3c..af62a8eb6e2 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_scan_options.idl
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_scan_options.idl
@@ -2,15 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
-// http://w3c.github.io/web-nfc/#dom-ndefcompatibility
-enum NDEFCompatibility { "nfc-forum", "vendor", "any" };
-
// https://w3c.github.io/web-nfc/#the-nfcscanoptions-dictionary
dictionary NFCScanOptions {
AbortSignal? signal;
USVString url = "";
NDEFRecordType? recordType;
USVString mediaType = "";
- NDEFCompatibility compatibility = "nfc-forum";
};
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
index 37e932d7195..a11da094ed6 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
@@ -30,8 +30,8 @@ namespace mojo {
NDEFRecordPtr TypeConverter<NDEFRecordPtr, ::blink::NDEFRecord*>::Convert(
const ::blink::NDEFRecord* record) {
- return NDEFRecord::New(blink::StringToNDEFRecordType(record->recordType()),
- record->mediaType(), record->data());
+ return NDEFRecord::New(record->recordType(), record->mediaType(),
+ record->data());
}
NDEFMessagePtr TypeConverter<NDEFMessagePtr, ::blink::NDEFMessage*>::Convert(
@@ -52,13 +52,10 @@ TypeConverter<NFCPushOptionsPtr, const blink::NFCPushOptions*>::Convert(
const blink::NFCPushOptions* pushOptions) {
// https://w3c.github.io/web-nfc/#the-nfcpushoptions-dictionary
// Default values for NFCPushOptions dictionary are:
- // target = 'any', timeout = Infinity, ignoreRead = true,
- // compatibility = "nfc-forum"
+ // target = 'any', timeout = Infinity, ignoreRead = true
NFCPushOptionsPtr pushOptionsPtr = NFCPushOptions::New();
pushOptionsPtr->target = blink::StringToNFCPushTarget(pushOptions->target());
pushOptionsPtr->ignore_read = pushOptions->ignoreRead();
- pushOptionsPtr->compatibility =
- blink::StringToNDEFCompatibility(pushOptions->compatibility());
if (pushOptions->hasTimeout())
pushOptionsPtr->timeout = pushOptions->timeout();
@@ -73,17 +70,14 @@ TypeConverter<NFCScanOptionsPtr, const blink::NFCScanOptions*>::Convert(
const blink::NFCScanOptions* scanOptions) {
// https://w3c.github.io/web-nfc/#dom-nfcscanoptions
// Default values for NFCScanOptions dictionary are:
- // url = "", recordType = null, mediaType = "", compatibility = "nfc-forum"
+ // url = "", recordType = null, mediaType = ""
NFCScanOptionsPtr scanOptionsPtr = NFCScanOptions::New();
scanOptionsPtr->url = scanOptions->url();
scanOptionsPtr->media_type = scanOptions->mediaType();
- scanOptionsPtr->compatibility =
- blink::StringToNDEFCompatibility(scanOptions->compatibility());
if (scanOptions->hasRecordType()) {
scanOptionsPtr->record_filter = NDEFRecordTypeFilter::New();
- scanOptionsPtr->record_filter->record_type =
- blink::StringToNDEFRecordType(scanOptions->recordType());
+ scanOptionsPtr->record_filter->record_type = scanOptions->recordType();
}
return scanOptionsPtr;
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.cc
index a8b7b21e14e..32477ef23bd 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.cc
@@ -9,28 +9,25 @@
#include "services/device/public/mojom/nfc.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/nfc/nfc_constants.h"
#include "third_party/blink/renderer/modules/nfc/nfc_type_converters.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-using device::mojom::blink::NDEFCompatibility;
-using device::mojom::blink::NDEFRecordType;
using device::mojom::blink::NFCPushTarget;
namespace blink {
-size_t GetNDEFMessageSize(const device::mojom::blink::NDEFMessagePtr& message) {
- size_t message_size = message->url.CharactersSizeInBytes();
- for (wtf_size_t i = 0; i < message->data.size(); ++i) {
- message_size += message->data[i]->media_type.CharactersSizeInBytes();
- message_size += message->data[i]->data.size();
+size_t GetNDEFMessageSize(const device::mojom::blink::NDEFMessage& message) {
+ size_t message_size = message.url.CharactersSizeInBytes();
+ for (wtf_size_t i = 0; i < message.data.size(); ++i) {
+ message_size += message.data[i]->media_type.CharactersSizeInBytes();
+ message_size += message.data[i]->data.size();
}
return message_size;
}
bool SetNDEFMessageURL(const String& origin,
- device::mojom::blink::NDEFMessagePtr& message) {
+ device::mojom::blink::NDEFMessage* message) {
KURL origin_url(origin);
if (!message->url.IsEmpty() && origin_url.CanSetPathname()) {
@@ -41,58 +38,6 @@ bool SetNDEFMessageURL(const String& origin,
return origin_url.IsValid();
}
-String NDEFRecordTypeToString(const NDEFRecordType& type) {
- switch (type) {
- case NDEFRecordType::TEXT:
- return "text";
- case NDEFRecordType::URL:
- return "url";
- case NDEFRecordType::JSON:
- return "json";
- case NDEFRecordType::OPAQUE_RECORD:
- return "opaque";
- case NDEFRecordType::EMPTY:
- return "empty";
- }
-
- NOTREACHED();
- return String();
-}
-
-NDEFCompatibility StringToNDEFCompatibility(const String& compatibility) {
- if (compatibility == "nfc-forum")
- return NDEFCompatibility::NFC_FORUM;
-
- if (compatibility == "vendor")
- return NDEFCompatibility::VENDOR;
-
- if (compatibility == "any")
- return NDEFCompatibility::ANY;
-
- NOTREACHED();
- return NDEFCompatibility::NFC_FORUM;
-}
-
-NDEFRecordType StringToNDEFRecordType(const String& recordType) {
- if (recordType == "empty")
- return NDEFRecordType::EMPTY;
-
- if (recordType == "text")
- return NDEFRecordType::TEXT;
-
- if (recordType == "url")
- return NDEFRecordType::URL;
-
- if (recordType == "json")
- return NDEFRecordType::JSON;
-
- if (recordType == "opaque")
- return NDEFRecordType::OPAQUE_RECORD;
-
- NOTREACHED();
- return NDEFRecordType::EMPTY;
-}
-
NFCPushTarget StringToNFCPushTarget(const String& target) {
if (target == "tag")
return NFCPushTarget::TAG;
@@ -108,32 +53,35 @@ DOMException* NFCErrorTypeToDOMException(
switch (error_type) {
case device::mojom::blink::NFCErrorType::NOT_ALLOWED:
return MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotAllowedError, kNfcNotAllowed);
+ DOMExceptionCode::kNotAllowedError, "NFC operation not allowed.");
case device::mojom::blink::NFCErrorType::NOT_SUPPORTED:
return MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError, kNfcNotSupported);
+ DOMExceptionCode::kNotSupportedError,
+ "No NFC adapter or cannot establish connection.");
case device::mojom::blink::NFCErrorType::NOT_READABLE:
return MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotReadableError, kNfcNotReadable);
+ DOMExceptionCode::kNotReadableError, "NFC is not enabled.");
case device::mojom::blink::NFCErrorType::NOT_FOUND:
return MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotFoundError, kNfcWatchIdNotFound);
+ DOMExceptionCode::kNotFoundError,
+ "Provided watch id cannot be found.");
case device::mojom::blink::NFCErrorType::INVALID_MESSAGE:
- return MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
- kNfcInvalidMsg);
+ return MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kSyntaxError, "Invalid NFC message was provided.");
case device::mojom::blink::NFCErrorType::OPERATION_CANCELLED:
- return MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
- kNfcCancelled);
+ return MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kAbortError, "The NFC operation was cancelled.");
case device::mojom::blink::NFCErrorType::TIMER_EXPIRED:
return MakeGarbageCollected<DOMException>(DOMExceptionCode::kTimeoutError,
- kNfcTimeout);
+ "NFC operation has timed out.");
case device::mojom::blink::NFCErrorType::CANNOT_CANCEL:
return MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNoModificationAllowedError,
- kNfcNoModificationAllowed);
+ "NFC operation cannot be cancelled.");
case device::mojom::blink::NFCErrorType::IO_ERROR:
- return MakeGarbageCollected<DOMException>(DOMExceptionCode::kNetworkError,
- kNfcDataTransferError);
+ return MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNetworkError,
+ "NFC data transfer error has occurred.");
}
NOTREACHED();
// Don't need to handle the case after a NOTREACHED().
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.h b/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.h
index a8aabb0b421..5c1954eb1dc 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_utils.h
@@ -9,26 +9,16 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/nfc/ndef_message.h"
#include "third_party/blink/renderer/modules/nfc/ndef_record.h"
-#include "third_party/blink/renderer/modules/nfc/nfc_constants.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
class DOMException;
-size_t GetNDEFMessageSize(const device::mojom::blink::NDEFMessagePtr& message);
+size_t GetNDEFMessageSize(const device::mojom::blink::NDEFMessage& message);
bool SetNDEFMessageURL(const String& origin,
- device::mojom::blink::NDEFMessagePtr& message);
-
-WTF::String NDEFRecordTypeToString(
- const device::mojom::blink::NDEFRecordType& type);
-
-device::mojom::blink::NDEFCompatibility StringToNDEFCompatibility(
- const WTF::String& compatibility);
-
-device::mojom::blink::NDEFRecordType StringToNDEFRecordType(
- const WTF::String& recordType);
+ device::mojom::blink::NDEFMessage* message);
device::mojom::blink::NFCPushTarget StringToNFCPushTarget(
const WTF::String& target);
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.cc
index 899a656800f..a69c3e2ae5a 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.cc
@@ -45,15 +45,17 @@ ScriptPromise NFCWriter::push(ScriptState* script_state,
return ScriptPromise::RejectWithDOMException(
script_state,
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotAllowedError,
- kNfcAccessInNonTopFrame));
+ "NFC interfaces are only avaliable "
+ "in a top-level browsing context"));
}
if (options->hasSignal() && options->signal()->aborted()) {
// If signal’s aborted flag is set, then reject p with an "AbortError"
// DOMException and return p.
return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kAbortError, kNfcCancelled));
+ script_state,
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
+ "The NFC operation was cancelled."));
}
// 9. If timeout value is NaN or negative, reject promise with "TypeError"
@@ -61,8 +63,10 @@ ScriptPromise NFCWriter::push(ScriptState* script_state,
if (options->hasTimeout() &&
(std::isnan(options->timeout()) || options->timeout() < 0)) {
return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), kNfcInvalidPushTimeout));
+ script_state,
+ V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "Invalid NFCPushOptions.timeout value was provided."));
}
// Step 10.8: Run "create Web NFC message", if this throws an exception,
@@ -75,27 +79,29 @@ ScriptPromise NFCWriter::push(ScriptState* script_state,
// If NDEFMessage.records is empty, reject promise with TypeError
if (ndef_message->records().size() == 0) {
- return ScriptPromise::Reject(script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), kNfcEmptyMsg));
+ return ScriptPromise::Reject(
+ script_state,
+ V8ThrowException::CreateTypeError(script_state->GetIsolate(),
+ "Empty NDEFMessage was provided."));
}
auto message = device::mojom::blink::NDEFMessage::From(ndef_message);
DCHECK(message);
if (!SetNDEFMessageURL(execution_context->GetSecurityOrigin()->ToString(),
- message)) {
+ message.get())) {
return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kSyntaxError, kNfcSetIdError));
+ script_state,
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
+ "Cannot set WebNFC Id."));
}
- if (GetNDEFMessageSize(message) >
+ if (GetNDEFMessageSize(*message) >
device::mojom::blink::NDEFMessage::kMaxSize) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kNfcMsgMaxSizeError));
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotSupportedError,
+ "NDEFMessage exceeds maximum supported size."));
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.h b/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.h
index 1c80c29a266..9a3ad6687cb 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_writer.h
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/modules/nfc/nfc_constants.h"
#include "third_party/blink/renderer/modules/nfc/nfc_proxy.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification.cc b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
index 88db76541d9..4337c4e4e53 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
@@ -35,7 +35,7 @@
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
+#include "third_party/blink/public/common/notifications/notification_constants.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"
@@ -353,7 +353,7 @@ ScriptValue Notification::data(ScriptState* script_state) {
scoped_refptr<SerializedScriptValue> serialized_value =
SerializedScriptValue::Create(data, length);
- return ScriptValue(script_state,
+ return ScriptValue(script_state->GetIsolate(),
serialized_value->Deserialize(script_state->GetIsolate()));
}
@@ -469,7 +469,7 @@ ScriptPromise Notification::requestPermission(
}
uint32_t Notification::maxActions() {
- return kWebNotificationMaxActions;
+ return kNotificationMaxActions;
}
DispatchEventResult Notification::DispatchEventInternal(Event& event) {
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification.h b/chromium/third_party/blink/renderer/modules/notifications/notification.h
index 11347c60522..b45101ea0ec 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification.h
@@ -33,8 +33,8 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/mojom/notifications/notification_service.mojom-blink.h"
-#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
-#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.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/bindings/core/v8/script_value.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 6a8c94a70d2..2a9d4cb2952 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
@@ -38,7 +38,7 @@ const bool kNotificationRenotify = true;
const bool kNotificationSilent = false;
const bool kNotificationRequireInteraction = true;
-const mojom::blink::NotificationActionType kWebNotificationActionType =
+const mojom::blink::NotificationActionType kBlinkNotificationActionType =
mojom::blink::NotificationActionType::TEXT;
const char kNotificationActionType[] = "text";
const char kNotificationActionAction[] = "my_action";
@@ -157,7 +157,7 @@ TEST_F(NotificationDataTest, ReflectProperties) {
notification_data->require_interaction);
EXPECT_EQ(actions.size(), notification_data->actions->size());
for (const auto& action : notification_data->actions.value()) {
- EXPECT_EQ(kWebNotificationActionType, action->type);
+ EXPECT_EQ(kBlinkNotificationActionType, action->type);
EXPECT_EQ(kNotificationActionAction, action->action);
EXPECT_EQ(kNotificationActionTitle, action->title);
EXPECT_EQ(kNotificationActionPlaceholder, action->placeholder);
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_manager.h b/chromium/third_party/blink/renderer/modules/notifications/notification_manager.h
index f43f45ac2bd..da9fb1f6d75 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_manager.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_manager.h
@@ -25,9 +25,8 @@ class ScriptState;
// connecting and communicating with the Mojo notification service.
//
// TODO(peter): Make the NotificationManager responsible for resource loading.
-class NotificationManager final
- : public GarbageCollectedFinalized<NotificationManager>,
- public Supplement<ExecutionContext> {
+class NotificationManager final : public GarbageCollected<NotificationManager>,
+ public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(NotificationManager);
public:
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.cc
index d29d8a4efc9..be77a72dbd8 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.cc
@@ -8,7 +8,9 @@
#include "base/optional.h"
#include "base/time/time.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
+#include "third_party/blink/public/common/notifications/notification_constants.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/platform/web_size.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -26,15 +28,14 @@ enum class NotificationIconType { kImage, kIcon, kBadge, kActionIcon };
WebSize GetIconDimensions(NotificationIconType type) {
switch (type) {
case NotificationIconType::kImage:
- return {kWebNotificationMaxImageWidthPx,
- kWebNotificationMaxImageHeightPx};
+ return {kNotificationMaxImageWidthPx, kNotificationMaxImageHeightPx};
case NotificationIconType::kIcon:
- return {kWebNotificationMaxIconSizePx, kWebNotificationMaxIconSizePx};
+ return {kNotificationMaxIconSizePx, kNotificationMaxIconSizePx};
case NotificationIconType::kBadge:
- return {kWebNotificationMaxBadgeSizePx, kWebNotificationMaxBadgeSizePx};
+ return {kNotificationMaxBadgeSizePx, kNotificationMaxBadgeSizePx};
case NotificationIconType::kActionIcon:
- return {kWebNotificationMaxActionIconSizePx,
- kWebNotificationMaxActionIconSizePx};
+ return {kNotificationMaxActionIconSizePx,
+ kNotificationMaxActionIconSizePx};
}
}
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.h b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.h
index c9a70fa540d..c772d116ecd 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/loader/threaded_icon_loader.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -26,7 +26,7 @@ struct WebSize;
// Fetches the resources specified in a given NotificationData. Uses a
// callback to notify the caller when all fetches have finished.
class MODULES_EXPORT NotificationResourcesLoader final
- : public GarbageCollectedFinalized<NotificationResourcesLoader> {
+ : public GarbageCollected<NotificationResourcesLoader> {
USING_PRE_FINALIZER(NotificationResourcesLoader, Stop);
public:
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
index 35c641476f9..e46ec6de3de 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_resources_loader_test.cc
@@ -6,7 +6,8 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
+#include "third_party/blink/public/common/notifications/notification_constants.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -148,19 +149,19 @@ TEST_F(NotificationResourcesLoaderTest, LargeIconsAreScaledDown) {
ASSERT_TRUE(Resources());
ASSERT_FALSE(Resources()->icon.drawsNothing());
- ASSERT_EQ(kWebNotificationMaxIconSizePx, Resources()->icon.width());
- ASSERT_EQ(kWebNotificationMaxIconSizePx, Resources()->icon.height());
+ ASSERT_EQ(kNotificationMaxIconSizePx, Resources()->icon.width());
+ ASSERT_EQ(kNotificationMaxIconSizePx, Resources()->icon.height());
ASSERT_FALSE(Resources()->badge.drawsNothing());
- ASSERT_EQ(kWebNotificationMaxBadgeSizePx, Resources()->badge.width());
- ASSERT_EQ(kWebNotificationMaxBadgeSizePx, Resources()->badge.height());
+ ASSERT_EQ(kNotificationMaxBadgeSizePx, Resources()->badge.width());
+ ASSERT_EQ(kNotificationMaxBadgeSizePx, Resources()->badge.height());
ASSERT_TRUE(Resources()->action_icons.has_value());
auto& action_icons = Resources()->action_icons.value();
ASSERT_EQ(1u, action_icons.size());
ASSERT_FALSE(action_icons[0].drawsNothing());
- ASSERT_EQ(kWebNotificationMaxActionIconSizePx, action_icons[0].width());
- ASSERT_EQ(kWebNotificationMaxActionIconSizePx, action_icons[0].height());
+ ASSERT_EQ(kNotificationMaxActionIconSizePx, action_icons[0].width());
+ ASSERT_EQ(kNotificationMaxActionIconSizePx, action_icons[0].height());
}
TEST_F(NotificationResourcesLoaderTest, DownscalingPreserves3_1AspectRatio) {
@@ -173,8 +174,8 @@ TEST_F(NotificationResourcesLoaderTest, DownscalingPreserves3_1AspectRatio) {
ASSERT_TRUE(Resources());
ASSERT_FALSE(Resources()->image.drawsNothing());
- ASSERT_EQ(kWebNotificationMaxImageWidthPx, Resources()->image.width());
- ASSERT_EQ(kWebNotificationMaxImageWidthPx / 3, Resources()->image.height());
+ ASSERT_EQ(kNotificationMaxImageWidthPx, Resources()->image.width());
+ ASSERT_EQ(kNotificationMaxImageWidthPx / 3, Resources()->image.height());
}
TEST_F(NotificationResourcesLoaderTest, DownscalingPreserves3_2AspectRatio) {
@@ -187,9 +188,8 @@ TEST_F(NotificationResourcesLoaderTest, DownscalingPreserves3_2AspectRatio) {
ASSERT_TRUE(Resources());
ASSERT_FALSE(Resources()->image.drawsNothing());
- ASSERT_EQ(kWebNotificationMaxImageHeightPx * 3 / 2,
- Resources()->image.width());
- ASSERT_EQ(kWebNotificationMaxImageHeightPx, Resources()->image.height());
+ ASSERT_EQ(kNotificationMaxImageHeightPx * 3 / 2, Resources()->image.width());
+ ASSERT_EQ(kNotificationMaxImageHeightPx, Resources()->image.height());
}
TEST_F(NotificationResourcesLoaderTest, EmptyDataYieldsEmptyResources) {
diff --git a/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.h b/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.h
index 8b2424e910e..ae6680b15b7 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/mojom/notifications/notification.mojom-blink.h"
+#include "third_party/blink/public/mojom/notifications/notification.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
diff --git a/chromium/third_party/blink/renderer/modules/p2p/BUILD.gn b/chromium/third_party/blink/renderer/modules/p2p/BUILD.gn
new file mode 100644
index 00000000000..4253a358859
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/p2p/BUILD.gn
@@ -0,0 +1,12 @@
+# 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/modules/modules.gni")
+
+blink_modules_sources("p2p") {
+ sources = [
+ "port_allocator.cc",
+ "port_allocator.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/p2p/DEPS b/chromium/third_party/blink/renderer/modules/p2p/DEPS
new file mode 100644
index 00000000000..0e460b98eb3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/p2p/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ # TODO(crbug.com/787254): Remove use of GURL.
+ "+url/gurl.h",
+]
diff --git a/chromium/third_party/blink/renderer/modules/p2p/port_allocator.cc b/chromium/third_party/blink/renderer/modules/p2p/port_allocator.cc
new file mode 100644
index 00000000000..b12fadda106
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/p2p/port_allocator.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/p2p/port_allocator.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <utility>
+
+#include "base/logging.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+
+namespace blink {
+
+P2PPortAllocator::P2PPortAllocator(
+ const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+ std::unique_ptr<rtc::NetworkManager> network_manager,
+ rtc::PacketSocketFactory* socket_factory,
+ const Config& config,
+ const GURL& origin)
+ : cricket::BasicPortAllocator(network_manager.get(), socket_factory),
+ network_manager_(std::move(network_manager)),
+ socket_dispatcher_(socket_dispatcher),
+ config_(config),
+ origin_(origin) {
+ DCHECK(socket_dispatcher);
+ DCHECK(network_manager_);
+ DCHECK(socket_factory);
+ uint32_t flags = 0;
+ if (!config_.enable_multiple_routes) {
+ flags |= cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION;
+ }
+ if (!config_.enable_default_local_candidate) {
+ flags |= cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE;
+ }
+ if (!config_.enable_nonproxied_udp) {
+ flags |= cricket::PORTALLOCATOR_DISABLE_UDP |
+ cricket::PORTALLOCATOR_DISABLE_STUN |
+ cricket::PORTALLOCATOR_DISABLE_UDP_RELAY;
+ }
+ 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() {}
+
+void P2PPortAllocator::Initialize() {
+ BasicPortAllocator::Initialize();
+ network_manager_->Initialize();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/p2p/port_allocator.h b/chromium/third_party/blink/renderer/modules/p2p/port_allocator.h
new file mode 100644
index 00000000000..0358e1672be
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/p2p/port_allocator.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_P2P_PORT_ALLOCATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_P2P_PORT_ALLOCATOR_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/webrtc/p2p/client/basic_port_allocator.h"
+#include "url/gurl.h"
+
+namespace blink {
+
+class P2PSocketDispatcher;
+
+class MODULES_EXPORT P2PPortAllocator : public cricket::BasicPortAllocator {
+ public:
+ struct Config {
+ // Enable non-proxied UDP-based transport when set to true. When set to
+ // false, it effectively disables all UDP traffic until UDP-supporting proxy
+ // RETURN is available in the future.
+ bool enable_nonproxied_udp = true;
+
+ // Request binding to individual NICs. Whether multiple routes is allowed is
+ // subject to the permission check on mic/camera. When specified as false or
+ // the permission request is denied, it still uses the default local address
+ // to generate a single local candidate. TODO(guoweis): Rename this to
+ // |request_multiple_routes|.
+ bool enable_multiple_routes = true;
+
+ // Enable exposing the default local address when set to true. This is
+ // only in effect when the |enable_multiple_routes| is false or the
+ // permission check of mic/camera is denied.
+ bool enable_default_local_candidate = true;
+ };
+
+ P2PPortAllocator(const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
+ std::unique_ptr<rtc::NetworkManager> network_manager,
+ rtc::PacketSocketFactory* socket_factory,
+ const Config& config,
+ const GURL& origin);
+ ~P2PPortAllocator() override;
+
+ // Will also initialize the network manager passed into the constructor.
+ void Initialize() override;
+
+ private:
+ std::unique_ptr<rtc::NetworkManager> network_manager_;
+ scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
+ Config config_;
+ GURL origin_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_P2P_PORT_ALLOCATOR_H_
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 dd2844e5685..112e23f1d28 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_ABORT_PAYMENT_RESPOND_WITH_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_ABORT_PAYMENT_RESPOND_WITH_OBSERVER_H_
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
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 6f3ca2d6c48..96d7c5fd9c5 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
@@ -41,6 +41,7 @@ void BasicCardHelper::ParseBasiccardData(
const ScriptValue& input,
Vector<BasicCardNetwork>& supported_networks_output,
Vector<BasicCardType>& supported_types_output,
+ bool* has_supported_card_types,
ExceptionState& exception_state) {
DCHECK(!input.IsEmpty());
@@ -68,6 +69,10 @@ void BasicCardHelper::ParseBasiccardData(
}
if (basic_card->hasSupportedTypes()) {
+ if (has_supported_card_types) {
+ *has_supported_card_types = true;
+ }
+
if (basic_card->supportedTypes().size() > PaymentRequest::kMaxListSize) {
exception_state.ThrowTypeError(
"basic-card supportedTypes cannot be longer than 1024 elements");
diff --git a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
index f764cbd7214..67b7a83f3da 100644
--- a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
+++ b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_BASIC_CARD_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_BASIC_CARD_HELPER_H_
-#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -20,11 +20,15 @@ class BasicCardHelper {
// Parse 'basic-card' data in |input| and store result in
// |supported_networks_output| and |supported_types_output| or throw
// exception.
+ //
+ // If |has_supported_card_types| is not null, then it is set to true if the
+ // basic-card specific method data has the "supportedTypes" field.
static void ParseBasiccardData(
const ScriptValue& input,
Vector<::payments::mojom::blink::BasicCardNetwork>&
supported_networks_output,
Vector<::payments::mojom::blink::BasicCardType>& supported_types_output,
+ bool* has_supported_card_types,
ExceptionState&);
// Check whether |input| is 'basic-card' network name.
diff --git a/chromium/third_party/blink/renderer/modules/payments/basic_card_request.idl b/chromium/third_party/blink/renderer/modules/payments/basic_card_request.idl
index 8269e80e16b..9bd0aeb9b2b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/basic_card_request.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/basic_card_request.idl
@@ -12,5 +12,5 @@ enum BasicCardType {
dictionary BasicCardRequest {
sequence<DOMString> supportedNetworks;
- [MeasureAs=BasicCardType] sequence<BasicCardType> supportedTypes;
+ sequence<BasicCardType> supportedTypes;
};
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 6df64fdf5d1..4adbd591a0f 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_CAN_MAKE_PAYMENT_RESPOND_WITH_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_CAN_MAKE_PAYMENT_RESPOND_WITH_OBSERVER_H_
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_address_init.idl b/chromium/third_party/blink/renderer/modules/payments/payment_address_init.idl
new file mode 100644
index 00000000000..fb7733fa217
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_address_init.idl
@@ -0,0 +1,18 @@
+// 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://w3c.github.io/payment-request/#dom-addressinit
+
+dictionary PaymentAddressInit {
+ DOMString country;
+ sequence<DOMString> addressLine;
+ DOMString region;
+ DOMString city;
+ DOMString dependentLocality;
+ DOMString postalCode;
+ DOMString sortingCode;
+ DOMString organization;
+ DOMString recipient;
+ DOMString phone;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
index 253ce3d52b0..92733d22ab7 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
@@ -17,7 +17,7 @@ class ScriptState;
class ServiceWorkerRegistration;
class PaymentAppServiceWorkerRegistration final
- : public GarbageCollectedFinalized<PaymentAppServiceWorkerRegistration>,
+ : public GarbageCollected<PaymentAppServiceWorkerRegistration>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(PaymentAppServiceWorkerRegistration);
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 6d652458039..031ee99b7b5 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/payments/payment_event_data_conversion.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/modules/payments/can_make_payment_event_init.h"
#include "third_party/blink/renderer/modules/payments/payment_currency_amount.h"
@@ -62,7 +63,7 @@ ScriptValue StringDataToScriptValue(ScriptState* script_state,
.ToLocal(&v8_value)) {
return ScriptValue();
}
- return ScriptValue(script_state, v8_value);
+ return ScriptValue(script_state->GetIsolate(), v8_value);
}
PaymentMethodData* ToPaymentMethodData(
@@ -76,6 +77,44 @@ PaymentMethodData* ToPaymentMethodData(
return method_data;
}
+PaymentOptions* ToPaymentOptions(
+ payments::mojom::blink::PaymentOptionsPtr options) {
+ DCHECK(options);
+ PaymentOptions* payment_options = PaymentOptions::Create();
+ payment_options->setRequestPayerName(options->request_payer_name);
+ payment_options->setRequestPayerEmail(options->request_payer_email);
+ payment_options->setRequestPayerPhone(options->request_payer_phone);
+ payment_options->setRequestShipping(options->request_shipping);
+
+ String shipping_type = "";
+ switch (options->shipping_type) {
+ case payments::mojom::PaymentShippingType::SHIPPING:
+ shipping_type = "shipping";
+ break;
+ case payments::mojom::PaymentShippingType::DELIVERY:
+ shipping_type = "delivery";
+ break;
+ case payments::mojom::PaymentShippingType::PICKUP:
+ shipping_type = "pickup";
+ break;
+ }
+ payment_options->setShippingType(shipping_type);
+ return payment_options;
+}
+
+PaymentShippingOption* ToShippingOption(
+ payments::mojom::blink::PaymentShippingOptionPtr option) {
+ DCHECK(option);
+ PaymentShippingOption* shipping_option = PaymentShippingOption::Create();
+
+ shipping_option->setAmount(
+ ToPaymentCurrencyAmount(std::move(option->amount)));
+ shipping_option->setLabel(option->label);
+ shipping_option->setId(option->id);
+ shipping_option->setSelected(option->selected);
+ return shipping_option;
+}
+
} // namespace
PaymentRequestEventInit* PaymentEventDataConversion::ToPaymentRequestEventInit(
@@ -107,6 +146,21 @@ PaymentRequestEventInit* PaymentEventDataConversion::ToPaymentRequestEventInit(
}
event_init->setModifiers(modifiers);
event_init->setInstrumentKey(event_data->instrument_key);
+
+ bool request_shipping = false;
+ if (event_data->payment_options) {
+ request_shipping = event_data->payment_options->request_shipping;
+ event_init->setPaymentOptions(
+ ToPaymentOptions(std::move(event_data->payment_options)));
+ }
+ if (event_data->shipping_options.has_value() && request_shipping) {
+ HeapVector<Member<PaymentShippingOption>> shipping_options;
+ for (auto& option : event_data->shipping_options.value()) {
+ shipping_options.push_back(ToShippingOption(std::move(option)));
+ }
+ event_init->setShippingOptions(shipping_options);
+ }
+
return event_init;
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.h b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.h
index 7fd5625ae41..c9d4999e9aa 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_EVENT_DATA_CONVERSION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_EVENT_DATA_CONVERSION_H_
-#include "third_party/blink/public/mojom/payments/payment_app.mojom-blink.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/payments/can_make_payment_event_init.h"
#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
index 150e10dc1ca..dbb6d2ea472 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
@@ -6,6 +6,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/payments/payment_app.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -42,6 +43,27 @@ CreateCanMakePaymentEventDataForTest() {
return event_data;
}
+static payments::mojom::blink::PaymentOptionsPtr CreatePaymentOptionsForTest() {
+ auto payment_options = payments::mojom::blink::PaymentOptions::New();
+ payment_options->request_payer_name = true;
+ payment_options->request_payer_email = true;
+ payment_options->request_payer_phone = true;
+ payment_options->request_shipping = true;
+ payment_options->shipping_type =
+ payments::mojom::PaymentShippingType::DELIVERY;
+ return payment_options;
+}
+
+static payments::mojom::blink::PaymentShippingOptionPtr
+CreateShippingOptionForTest() {
+ auto shipping_option = payments::mojom::blink::PaymentShippingOption::New();
+ shipping_option->amount = CreatePaymentCurrencyAmountForTest();
+ shipping_option->label = String::FromUTF8("shipping-option-label");
+ shipping_option->id = String::FromUTF8("shipping-option-id");
+ shipping_option->selected = true;
+ return shipping_option;
+}
+
static payments::mojom::blink::PaymentRequestEventDataPtr
CreatePaymentRequestEventDataForTest() {
auto event_data = payments::mojom::blink::PaymentRequestEventData::New();
@@ -53,6 +75,10 @@ CreatePaymentRequestEventDataForTest() {
event_data->method_data = std::move(method_data);
event_data->total = CreatePaymentCurrencyAmountForTest();
event_data->instrument_key = String::FromUTF8("payment-instrument-key");
+ event_data->payment_options = CreatePaymentOptionsForTest();
+ Vector<payments::mojom::blink::PaymentShippingOptionPtr> shipping_options;
+ shipping_options.push_back(CreateShippingOptionForTest());
+ event_data->shipping_options = std::move(shipping_options);
return event_data;
}
@@ -124,6 +150,34 @@ TEST(PaymentEventDataConversionTest, ToPaymentRequestEventData) {
ASSERT_TRUE(data->hasInstrumentKey());
EXPECT_EQ("payment-instrument-key", data->instrumentKey());
+
+ // paymentOptions
+ ASSERT_TRUE(data->hasPaymentOptions());
+ ASSERT_TRUE(data->paymentOptions()->hasRequestPayerName());
+ ASSERT_TRUE(data->paymentOptions()->requestPayerName());
+ ASSERT_TRUE(data->paymentOptions()->hasRequestPayerEmail());
+ ASSERT_TRUE(data->paymentOptions()->requestPayerEmail());
+ ASSERT_TRUE(data->paymentOptions()->hasRequestPayerPhone());
+ ASSERT_TRUE(data->paymentOptions()->requestPayerPhone());
+ ASSERT_TRUE(data->paymentOptions()->hasRequestShipping());
+ ASSERT_TRUE(data->paymentOptions()->requestShipping());
+ ASSERT_TRUE(data->paymentOptions()->hasShippingType());
+ EXPECT_EQ("delivery", data->paymentOptions()->shippingType());
+
+ // shippingOptions
+ ASSERT_TRUE(data->hasShippingOptions());
+ EXPECT_EQ(1UL, data->shippingOptions().size());
+ ASSERT_TRUE(data->shippingOptions().front()->hasAmount());
+ ASSERT_TRUE(data->shippingOptions().front()->amount()->hasCurrency());
+ EXPECT_EQ("USD", data->shippingOptions().front()->amount()->currency());
+ ASSERT_TRUE(data->shippingOptions().front()->amount()->hasValue());
+ EXPECT_EQ("9.99", data->shippingOptions().front()->amount()->value());
+ ASSERT_TRUE(data->shippingOptions().front()->hasLabel());
+ EXPECT_EQ("shipping-option-label", data->shippingOptions().front()->label());
+ ASSERT_TRUE(data->shippingOptions().front()->hasId());
+ EXPECT_EQ("shipping-option-id", data->shippingOptions().front()->id());
+ ASSERT_TRUE(data->shippingOptions().front()->hasSelected());
+ ASSERT_TRUE(data->shippingOptions().front()->selected());
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_handler_response.idl b/chromium/third_party/blink/renderer/modules/payments/payment_handler_response.idl
index 0327bd0649d..6f17e0d6e2a 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_handler_response.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_handler_response.idl
@@ -7,4 +7,9 @@
dictionary PaymentHandlerResponse {
DOMString methodName;
object details;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] DOMString? payerName;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] DOMString? payerEmail;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] DOMString? payerPhone;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] PaymentAddressInit shippingAddress;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] DOMString? shippingOption;
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
index 96f625bc201..57ce848c25e 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/payments/payment_handler_utils.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.h b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.h
index 63a4fae2ea4..d1d824ff1a6 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_HANDLER_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_HANDLER_UTILS_H_
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.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/modules/payments/payment_instruments.cc b/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
index 20350d57861..fb39539a370 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
@@ -97,8 +97,8 @@ ScriptPromise RejectNotAllowedToUsePaymentFeatures(ScriptState* script_state) {
// referenced by |PaymentInstrument| will not be traced through the callback and
// can be prematurely destroyed.
// TODO(keishi): Remove this conversion if IDLDictionaryBase situation changes.
-class PaymentInstrumentParameter
- : public GarbageCollectedFinalized<PaymentInstrumentParameter> {
+class PaymentInstrumentParameter final
+ : public GarbageCollected<PaymentInstrumentParameter> {
public:
explicit PaymentInstrumentParameter(const PaymentInstrument* instrument)
: has_icons_(instrument->hasIcons()),
@@ -124,7 +124,10 @@ class PaymentInstrumentParameter
bool has_name() const { return has_name_; }
const String& name() const { return name_; }
- void Trace(blink::Visitor* visitor) { visitor->Trace(icons_); }
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(icons_);
+ visitor->Trace(capabilities_);
+ }
private:
bool has_icons_;
@@ -362,7 +365,8 @@ void PaymentInstruments::OnRequestPermission(
"PaymentInstruments", "set");
BasicCardHelper::ParseBasiccardData(
details->capabilities(), instrument->supported_networks,
- instrument->supported_types, exception_state);
+ instrument->supported_types, /*has_supported_card_types=*/nullptr,
+ exception_state);
if (exception_state.HadException()) {
resolver->Reject(exception_state);
return;
@@ -424,7 +428,7 @@ void PaymentInstruments::onGetPaymentInstrument(
ExceptionState::kGetterContext,
"PaymentInstruments", "get");
instrument->setCapabilities(
- ScriptValue(resolver->GetScriptState(),
+ ScriptValue(resolver->GetScriptState()->GetIsolate(),
FromJSONString(resolver->GetScriptState()->GetIsolate(),
resolver->GetScriptState()->GetContext(),
stored_instrument->stringified_capabilities,
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc b/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
index 0952de3b256..029f5ce7901 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/modules/payments/payment_manager.h"
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/payments/payment_instruments.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
@@ -34,9 +35,55 @@ void PaymentManager::setUserHint(const String& user_hint) {
manager_->SetUserHint(user_hint_);
}
+ScriptPromise PaymentManager::enableDelegations(
+ ScriptState* script_state,
+ const Vector<String>& stringified_delegations) {
+ if (!script_state->ContextIsValid()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "Cannot enable payment delegations"));
+ }
+
+ if (enable_delegations_resolver_) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "Cannot call enableDelegations() again until "
+ "the previous enableDelegations() is finished"));
+ }
+
+ Vector<payments::mojom::blink::PaymentDelegation> delegations;
+ for (auto delegation : stringified_delegations) {
+ if (delegation == "shippingAddress") {
+ delegations.emplace_back(
+ payments::mojom::blink::PaymentDelegation::SHIPPING_ADDRESS);
+ } else if (delegation == "payerName") {
+ delegations.emplace_back(
+ payments::mojom::blink::PaymentDelegation::PAYER_NAME);
+ } else if (delegation == "payerPhone") {
+ delegations.emplace_back(
+ payments::mojom::blink::PaymentDelegation::PAYER_PHONE);
+ } else {
+ DCHECK_EQ("payerEmail", delegation);
+ delegations.emplace_back(
+ payments::mojom::blink::PaymentDelegation::PAYER_EMAIL);
+ }
+ }
+
+ manager_->EnableDelegations(
+ std::move(delegations),
+ WTF::Bind(&PaymentManager::OnEnableDelegationsResponse,
+ WrapPersistent(this)));
+ enable_delegations_resolver_ =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ return enable_delegations_resolver_->Promise();
+}
+
void PaymentManager::Trace(blink::Visitor* visitor) {
visitor->Trace(registration_);
visitor->Trace(instruments_);
+ visitor->Trace(enable_delegations_resolver_);
ScriptWrappable::Trace(visitor);
}
@@ -45,10 +92,9 @@ PaymentManager::PaymentManager(ServiceWorkerRegistration* registration)
DCHECK(registration);
if (ExecutionContext* context = registration->GetExecutionContext()) {
- if (auto* interface_provider = context->GetInterfaceProvider()) {
- interface_provider->GetInterface(manager_.BindNewPipeAndPassReceiver(
- context->GetTaskRunner(TaskType::kUserInteraction)));
- }
+ context->GetBrowserInterfaceBroker().GetInterface(
+ manager_.BindNewPipeAndPassReceiver(
+ context->GetTaskRunner(TaskType::kUserInteraction)));
}
manager_.set_disconnect_handler(WTF::Bind(
@@ -57,7 +103,18 @@ PaymentManager::PaymentManager(ServiceWorkerRegistration* registration)
registration_->scope());
}
+void PaymentManager::OnEnableDelegationsResponse(
+ payments::mojom::blink::PaymentHandlerStatus status) {
+ DCHECK(enable_delegations_resolver_);
+ enable_delegations_resolver_->Resolve(
+ status == payments::mojom::blink::PaymentHandlerStatus::SUCCESS);
+ enable_delegations_resolver_.Clear();
+}
+
void PaymentManager::OnServiceConnectionError() {
+ if (enable_delegations_resolver_)
+ enable_delegations_resolver_.Clear();
+
manager_.reset();
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_manager.h b/chromium/third_party/blink/renderer/modules/payments/payment_manager.h
index edd7cc80a7d..d60f8bcc1c6 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_manager.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_manager.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/payments/payment_app.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"
@@ -16,6 +15,9 @@
namespace blink {
class PaymentInstruments;
+class ScriptPromiseResolver;
+class ScriptPromise;
+class ScriptState;
class ServiceWorkerRegistration;
class MODULES_EXPORT PaymentManager final : public ScriptWrappable {
@@ -33,13 +35,21 @@ class MODULES_EXPORT PaymentManager final : public ScriptWrappable {
void Trace(blink::Visitor*) override;
+ ScriptPromise enableDelegations(
+ ScriptState*,
+ const Vector<String>& stringified_delegations);
+
private:
void OnServiceConnectionError();
+ void OnEnableDelegationsResponse(
+ payments::mojom::blink::PaymentHandlerStatus status);
+
Member<ServiceWorkerRegistration> registration_;
mojo::Remote<payments::mojom::blink::PaymentManager> manager_;
Member<PaymentInstruments> instruments_;
String user_hint_;
+ Member<ScriptPromiseResolver> enable_delegations_resolver_;
DISALLOW_COPY_AND_ASSIGN(PaymentManager);
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_manager.idl b/chromium/third_party/blink/renderer/modules/payments/payment_manager.idl
index e213febce24..10b88279dc2 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_manager.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_manager.idl
@@ -4,10 +4,18 @@
// https://w3c.github.io/webpayments-payment-apps-api/#idl-def-paymentappmanager
+enum PaymentDelegation {
+ "shippingAddress",
+ "payerName",
+ "payerPhone",
+ "payerEmail",
+};
+
[
RuntimeEnabled=PaymentApp,
ConstructorCallWith=ExecutionContext
] interface PaymentManager {
[SameObject] readonly attribute PaymentInstruments instruments;
attribute DOMString userHint;
+ [CallWith=ScriptState, RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] Promise<void> enableDelegations(FrozenArray<PaymentDelegation> delegations);
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_method_change_event.cc b/chromium/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
index 1a3b8e6d0eb..47c8e2dd397 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_method_change_event.cc
@@ -28,8 +28,8 @@ const String& PaymentMethodChangeEvent::methodName() const {
const ScriptValue PaymentMethodChangeEvent::methodDetails(
ScriptState* script_state) const {
if (method_details_.IsEmpty())
- return ScriptValue::CreateNull(script_state);
- return ScriptValue(script_state,
+ return ScriptValue::CreateNull(script_state->GetIsolate());
+ return ScriptValue(script_state->GetIsolate(),
method_details_.GetAcrossWorld(script_state));
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_method_change_response.idl b/chromium/third_party/blink/renderer/modules/payments/payment_method_change_response.idl
index 17f7d2abe8c..46100b01d76 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_method_change_response.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_method_change_response.idl
@@ -3,10 +3,15 @@
// found in the LICENSE file.
// https://w3c.github.io/payment-handler/#dom-paymentmethodchangeresponse
+// Todo(sahel): Change the link to the updated spec. crbug.com/984694
+// Todo(sahel): Rename PaymentMethodChangeResponse to
+// PaymentRequestDetailsUpdate which is a more generic name. crbug.com/984694
dictionary PaymentMethodChangeResponse {
DOMString error;
PaymentCurrencyAmount total;
FrozenArray<PaymentDetailsModifier> modifiers;
+ FrozenArray<PaymentShippingOption> shippingOptions;
object paymentMethodErrors;
+ AddressErrors shippingAddressErrors;
};
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 8bae47431cd..56e4baa064a 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -11,8 +11,7 @@
#include "base/location.h"
#include "base/stl_util.h"
#include "build/build_config.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
@@ -393,19 +392,13 @@ void SetAndroidPayMethodData(v8::Isolate* isolate,
output->api_version = android_pay->apiVersion();
}
-// Parses basic-card data to avoid parsing JSON in the browser.
-void SetBasicCardMethodData(const ScriptValue& input,
- PaymentMethodDataPtr& output,
- ExceptionState& exception_state) {
- BasicCardHelper::ParseBasiccardData(input, output->supported_networks,
- output->supported_types, exception_state);
-}
-
-void StringifyAndParseMethodSpecificData(v8::Isolate* isolate,
- const String& supported_method,
- const ScriptValue& input,
- PaymentMethodDataPtr& output,
- ExceptionState& exception_state) {
+void StringifyAndParseMethodSpecificData(
+ v8::Isolate* isolate,
+ const String& supported_method,
+ const ScriptValue& input,
+ PaymentMethodDataPtr& output,
+ bool* basic_card_has_supported_card_types,
+ ExceptionState& exception_state) {
PaymentsValidators::ValidateAndStringifyObject(
isolate, "Payment method data", input, output->stringified_data,
exception_state);
@@ -423,13 +416,17 @@ void StringifyAndParseMethodSpecificData(v8::Isolate* isolate,
}
if (supported_method == "basic-card") {
- SetBasicCardMethodData(input, output, exception_state);
+ // Parses basic-card data to avoid parsing JSON in the browser.
+ BasicCardHelper::ParseBasiccardData(
+ input, output->supported_networks, output->supported_types,
+ basic_card_has_supported_card_types, exception_state);
}
}
void ValidateAndConvertPaymentDetailsModifiers(
const HeapVector<Member<PaymentDetailsModifier>>& input,
Vector<PaymentDetailsModifierPtr>& output,
+ bool* basic_card_has_supported_card_types,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
if (input.size() > PaymentRequest::kMaxListSize) {
@@ -469,19 +466,22 @@ void ValidateAndConvertPaymentDetailsModifiers(
if (modifier->hasData() && !modifier->data().IsEmpty()) {
StringifyAndParseMethodSpecificData(
execution_context.GetIsolate(), modifier->supportedMethod(),
- modifier->data(), output.back()->method_data, exception_state);
+ modifier->data(), output.back()->method_data,
+ basic_card_has_supported_card_types, exception_state);
} else {
output.back()->method_data->stringified_data = "";
}
}
}
-void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase* input,
- const PaymentOptions* options,
- PaymentDetailsPtr& output,
- String& shipping_option_output,
- ExecutionContext& execution_context,
- ExceptionState& exception_state) {
+void ValidateAndConvertPaymentDetailsBase(
+ const PaymentDetailsBase* input,
+ const PaymentOptions* options,
+ PaymentDetailsPtr& output,
+ String& shipping_option_output,
+ bool* basic_card_has_supported_card_types,
+ ExecutionContext& execution_context,
+ ExceptionState& exception_state) {
if (input->hasDisplayItems()) {
output->display_items = Vector<PaymentItemPtr>();
ValidateAndConvertDisplayItems(input->displayItems(), "display items",
@@ -507,26 +507,29 @@ void ValidateAndConvertPaymentDetailsBase(const PaymentDetailsBase* input,
if (input->hasModifiers()) {
output->modifiers = Vector<PaymentDetailsModifierPtr>();
ValidateAndConvertPaymentDetailsModifiers(
- input->modifiers(), *output->modifiers, execution_context,
+ input->modifiers(), *output->modifiers,
+ basic_card_has_supported_card_types, execution_context,
exception_state);
}
}
-void ValidateAndConvertPaymentDetailsInit(const PaymentDetailsInit* input,
- const PaymentOptions* options,
- PaymentDetailsPtr& output,
- String& shipping_option_output,
- ExecutionContext& execution_context,
- ExceptionState& exception_state) {
+void ValidateAndConvertPaymentDetailsInit(
+ const PaymentDetailsInit* input,
+ const PaymentOptions* options,
+ PaymentDetailsPtr& output,
+ String& shipping_option_output,
+ bool* basic_card_has_supported_card_types,
+ ExecutionContext& execution_context,
+ ExceptionState& exception_state) {
DCHECK(input->hasTotal());
ValidateAndConvertTotal(input->total(), "total", output->total,
execution_context, exception_state);
if (exception_state.HadException())
return;
- ValidateAndConvertPaymentDetailsBase(input, options, output,
- shipping_option_output,
- execution_context, exception_state);
+ ValidateAndConvertPaymentDetailsBase(
+ input, options, output, shipping_option_output,
+ basic_card_has_supported_card_types, execution_context, exception_state);
}
void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate* input,
@@ -535,9 +538,9 @@ void ValidateAndConvertPaymentDetailsUpdate(const PaymentDetailsUpdate* input,
String& shipping_option_output,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
- ValidateAndConvertPaymentDetailsBase(input, options, output,
- shipping_option_output,
- execution_context, exception_state);
+ ValidateAndConvertPaymentDetailsBase(
+ input, options, output, shipping_option_output,
+ /*has_supported_card_types=*/nullptr, execution_context, exception_state);
if (exception_state.HadException())
return;
@@ -585,6 +588,7 @@ void ValidateAndConvertPaymentMethodData(
bool& skip_to_gpay_ready,
Vector<payments::mojom::blink::PaymentMethodDataPtr>& output,
HashSet<String>& method_names,
+ bool* basic_card_has_supported_card_types,
ExecutionContext& execution_context,
ExceptionState& exception_state) {
if (input.IsEmpty()) {
@@ -621,7 +625,7 @@ void ValidateAndConvertPaymentMethodData(
StringifyAndParseMethodSpecificData(
execution_context.GetIsolate(),
payment_method_data->supportedMethod(), payment_method_data->data(),
- output.back(), exception_state);
+ output.back(), basic_card_has_supported_card_types, exception_state);
if (exception_state.HadException())
continue;
@@ -719,6 +723,10 @@ ScriptPromise PaymentRequest::show(ScriptState* script_state,
WebFeature::kPaymentRequestShowWithoutGesture);
}
+ if (basic_card_has_supported_card_types_) {
+ UseCounter::Count(GetExecutionContext(), WebFeature::kBasicCardType);
+ }
+
// TODO(crbug.com/779126): add support for handling payment requests in
// immersive mode.
if (GetFrame()->GetDocument()->GetSettings()->GetImmersiveModeEnabled()) {
@@ -1088,7 +1096,8 @@ PaymentRequest::PaymentRequest(
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI),
this,
&PaymentRequest::OnUpdatePaymentDetailsTimeout),
- is_waiting_for_show_promise_to_resolve_(false) {
+ is_waiting_for_show_promise_to_resolve_(false),
+ basic_card_has_supported_card_types_(false) {
DCHECK(GetExecutionContext()->IsSecureContext());
if (!AllowedToUsePaymentRequest(execution_context)) {
@@ -1118,13 +1127,15 @@ PaymentRequest::PaymentRequest(
Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
ValidateAndConvertPaymentMethodData(method_data, options_, skip_to_gpay_ready,
validated_method_data, method_names_,
+ &basic_card_has_supported_card_types_,
*GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;
ValidateAndConvertPaymentDetailsInit(details, options_, validated_details,
- shipping_option_, *GetExecutionContext(),
- exception_state);
+ shipping_option_,
+ &basic_card_has_supported_card_types_,
+ *GetExecutionContext(), exception_state);
if (exception_state.HadException())
return;
@@ -1151,9 +1162,9 @@ PaymentRequest::PaymentRequest(
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
execution_context->GetTaskRunner(TaskType::kUserInteraction);
- GetFrame()->GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&payment_provider_, task_runner));
- payment_provider_.set_connection_error_handler(
+ GetFrame()->GetBrowserInterfaceBroker().GetInterface(
+ payment_provider_.BindNewPipeAndPassReceiver(task_runner));
+ payment_provider_.set_disconnect_handler(
WTF::Bind(&PaymentRequest::OnConnectionError, WrapWeakPersistent(this)));
UseCounter::Count(execution_context, WebFeature::kPaymentRequestInitialized);
@@ -1211,7 +1222,8 @@ void PaymentRequest::OnPaymentMethodChange(const String& method_name,
ClearResolversAndCloseMojoConnection();
return;
}
- init->setMethodDetails(ScriptValue(script_state, parsed_value));
+ init->setMethodDetails(
+ ScriptValue(script_state->GetIsolate(), parsed_value));
}
PaymentRequestUpdateEvent* event = PaymentMethodChangeEvent::Create(
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request.h b/chromium/third_party/blink/renderer/modules/payments/payment_request.h
index 25442453ba2..2315ff65bfa 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.h
@@ -7,8 +7,9 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "components/payments/mojom/payment_request_data.mojom-blink.h"
+#include "components/payments/mojom/payment_request_data.mojom-blink-forward.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -165,12 +166,13 @@ class MODULES_EXPORT PaymentRequest final
Member<ScriptPromiseResolver> abort_resolver_;
Member<ScriptPromiseResolver> can_make_payment_resolver_;
Member<ScriptPromiseResolver> has_enrolled_instrument_resolver_;
- payments::mojom::blink::PaymentRequestPtr payment_provider_;
+ mojo::Remote<payments::mojom::blink::PaymentRequest> payment_provider_;
mojo::Receiver<payments::mojom::blink::PaymentRequestClient> client_receiver_{
this};
TaskRunnerTimer<PaymentRequest> complete_timer_;
TaskRunnerTimer<PaymentRequest> update_payment_details_timer_;
bool is_waiting_for_show_promise_to_resolve_;
+ bool basic_card_has_supported_card_types_;
DISALLOW_COPY_AND_ASSIGN(PaymentRequest);
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
index df182783f30..163e87e5109 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
#include "third_party/blink/public/platform/interface_provider.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"
@@ -60,6 +61,12 @@ PaymentRequestEvent::PaymentRequestEvent(
? initializer->modifiers()
: HeapVector<Member<PaymentDetailsModifier>>()),
instrument_key_(initializer->instrumentKey()),
+ payment_options_(initializer->hasPaymentOptions()
+ ? initializer->paymentOptions()
+ : PaymentOptions::Create()),
+ shipping_options_(initializer->hasShippingOptions()
+ ? initializer->shippingOptions()
+ : HeapVector<Member<PaymentShippingOption>>()),
observer_(respond_with_observer) {
if (!host.is_valid())
return;
@@ -105,6 +112,19 @@ const String& PaymentRequestEvent::instrumentKey() const {
return instrument_key_;
}
+const ScriptValue PaymentRequestEvent::paymentOptions(
+ ScriptState* script_state) const {
+ if (!payment_options_)
+ return ScriptValue::CreateNull(script_state->GetIsolate());
+ return ScriptValue::From(script_state, payment_options_);
+}
+
+const HeapVector<Member<PaymentShippingOption>>&
+PaymentRequestEvent::shippingOptions(bool& is_null) const {
+ is_null = shipping_options_.IsEmpty();
+ return shipping_options_;
+}
+
ScriptPromise PaymentRequestEvent::openWindow(ScriptState* script_state,
const String& url) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -161,12 +181,12 @@ ScriptPromise PaymentRequestEvent::changePaymentMethod(
const String& method_name,
const ScriptValue& method_details,
ExceptionState& exception_state) {
- if (change_payment_method_resolver_) {
+ if (change_payment_request_details_resolver_) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError,
- "Waiting for response to the previous payment method change"));
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "Waiting for response to the previous payment "
+ "request details change"));
}
if (!payment_handler_host_.is_bound()) {
@@ -188,11 +208,106 @@ ScriptPromise PaymentRequestEvent::changePaymentMethod(
method_data->method_name = method_name;
payment_handler_host_->ChangePaymentMethod(
std::move(method_data),
- WTF::Bind(&PaymentRequestEvent::OnChangePaymentMethodResponse,
+ WTF::Bind(&PaymentRequestEvent::OnChangePaymentRequestDetailsResponse,
+ WrapWeakPersistent(this)));
+ change_payment_request_details_resolver_ =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ return change_payment_request_details_resolver_->Promise();
+}
+
+ScriptPromise PaymentRequestEvent::changeShippingAddress(
+ ScriptState* script_state,
+ PaymentAddressInit* shipping_address) {
+ if (change_payment_request_details_resolver_) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "Waiting for response to the previous payment "
+ "request details change"));
+ }
+
+ if (!payment_handler_host_.is_bound()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "No corresponding PaymentRequest object found"));
+ }
+ if (!shipping_address) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
+ "Shipping address cannot be null"));
+ }
+
+ auto shipping_address_ptr = payments::mojom::blink::PaymentAddress::New();
+ shipping_address_ptr->country = shipping_address->country();
+ shipping_address_ptr->address_line = shipping_address->addressLine();
+ shipping_address_ptr->region = shipping_address->region();
+ shipping_address_ptr->city = shipping_address->city();
+ shipping_address_ptr->dependent_locality =
+ shipping_address->dependentLocality();
+ shipping_address_ptr->postal_code = shipping_address->postalCode();
+ shipping_address_ptr->sorting_code = shipping_address->sortingCode();
+ shipping_address_ptr->organization = shipping_address->organization();
+ shipping_address_ptr->recipient = shipping_address->recipient();
+ shipping_address_ptr->phone = shipping_address->phone();
+ String shipping_address_error;
+ if (!PaymentsValidators::IsValidShippingAddress(shipping_address_ptr,
+ &shipping_address_error)) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
+ shipping_address_error));
+ }
+
+ payment_handler_host_->ChangeShippingAddress(
+ std::move(shipping_address_ptr),
+ WTF::Bind(&PaymentRequestEvent::OnChangePaymentRequestDetailsResponse,
WrapWeakPersistent(this)));
- change_payment_method_resolver_ =
+ change_payment_request_details_resolver_ =
MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- return change_payment_method_resolver_->Promise();
+ return change_payment_request_details_resolver_->Promise();
+}
+
+ScriptPromise PaymentRequestEvent::changeShippingOption(
+ ScriptState* script_state,
+ const String& shipping_option_id) {
+ if (change_payment_request_details_resolver_) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "Waiting for response to the previous payment "
+ "request details change"));
+ }
+
+ if (!payment_handler_host_.is_bound()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError,
+ "No corresponding PaymentRequest object found"));
+ }
+
+ bool shipping_option_id_is_valid = false;
+ for (const auto& option : shipping_options_) {
+ if (option->id() == shipping_option_id) {
+ shipping_option_id_is_valid = true;
+ break;
+ }
+ }
+ if (!shipping_option_id_is_valid) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kSyntaxError,
+ "Shipping option identifier is invalid"));
+ }
+
+ payment_handler_host_->ChangeShippingOption(
+ shipping_option_id,
+ WTF::Bind(&PaymentRequestEvent::OnChangePaymentRequestDetailsResponse,
+ WrapWeakPersistent(this)));
+ change_payment_request_details_resolver_ =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ return change_payment_request_details_resolver_->Promise();
}
void PaymentRequestEvent::respondWith(ScriptState* script_state,
@@ -215,14 +330,16 @@ void PaymentRequestEvent::Trace(blink::Visitor* visitor) {
visitor->Trace(method_data_);
visitor->Trace(total_);
visitor->Trace(modifiers_);
- visitor->Trace(change_payment_method_resolver_);
+ visitor->Trace(payment_options_);
+ visitor->Trace(shipping_options_);
+ visitor->Trace(change_payment_request_details_resolver_);
visitor->Trace(observer_);
ExtendableEvent::Trace(visitor);
}
-void PaymentRequestEvent::OnChangePaymentMethodResponse(
+void PaymentRequestEvent::OnChangePaymentRequestDetailsResponse(
payments::mojom::blink::PaymentMethodChangeResponsePtr response) {
- if (!change_payment_method_resolver_)
+ if (!change_payment_request_details_resolver_)
return;
auto* dictionary = MakeGarbageCollected<PaymentMethodChangeResponse>();
@@ -237,7 +354,8 @@ void PaymentRequestEvent::OnChangePaymentMethodResponse(
dictionary->setTotal(total);
}
- ScriptState* script_state = change_payment_method_resolver_->GetScriptState();
+ ScriptState* script_state =
+ change_payment_request_details_resolver_->GetScriptState();
ScriptState::Scope scope(script_state);
ExceptionState exception_state(script_state->GetIsolate(),
ExceptionState::kConstructionContext,
@@ -268,48 +386,96 @@ void PaymentRequestEvent::OnChangePaymentMethodResponse(
script_state->GetIsolate(), script_state->GetContext(),
response_modifier->method_data->stringified_data, exception_state);
if (exception_state.HadException()) {
- change_payment_method_resolver_->Reject(
+ change_payment_request_details_resolver_->Reject(
MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
exception_state.Message()));
- change_payment_method_resolver_.Clear();
+ change_payment_request_details_resolver_.Clear();
return;
}
- mod->setData(ScriptValue(script_state, parsed_value));
+ mod->setData(ScriptValue(script_state->GetIsolate(), parsed_value));
modifiers->emplace_back(mod);
}
}
dictionary->setModifiers(*modifiers);
}
+ if (response->shipping_options) {
+ auto* shipping_options =
+ MakeGarbageCollected<HeapVector<Member<PaymentShippingOption>>>();
+ for (const auto& response_shipping_option : *response->shipping_options) {
+ if (!response_shipping_option)
+ continue;
+
+ auto* shipping_option = MakeGarbageCollected<PaymentShippingOption>();
+ auto* amount = MakeGarbageCollected<PaymentCurrencyAmount>();
+ amount->setCurrency(response_shipping_option->amount->currency);
+ amount->setValue(response_shipping_option->amount->value);
+ shipping_option->setAmount(amount);
+ shipping_option->setId(response_shipping_option->id);
+ shipping_option->setLabel(response_shipping_option->label);
+ shipping_option->setSelected(response_shipping_option->selected);
+ shipping_options->emplace_back(shipping_option);
+ }
+ dictionary->setShippingOptions(*shipping_options);
+ }
+
if (response->stringified_payment_method_errors &&
!response->stringified_payment_method_errors.IsEmpty()) {
v8::Local<v8::Value> parsed_value = FromJSONString(
script_state->GetIsolate(), script_state->GetContext(),
response->stringified_payment_method_errors, exception_state);
if (exception_state.HadException()) {
- change_payment_method_resolver_->Reject(
+ change_payment_request_details_resolver_->Reject(
MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
exception_state.Message()));
- change_payment_method_resolver_.Clear();
+ change_payment_request_details_resolver_.Clear();
return;
}
- dictionary->setPaymentMethodErrors(ScriptValue(script_state, parsed_value));
+ dictionary->setPaymentMethodErrors(
+ ScriptValue(script_state->GetIsolate(), parsed_value));
+ }
+
+ if (response->shipping_address_errors) {
+ auto* shipping_address_errors = MakeGarbageCollected<AddressErrors>();
+ shipping_address_errors->setAddressLine(
+ response->shipping_address_errors->address_line);
+ shipping_address_errors->setCity(response->shipping_address_errors->city);
+ shipping_address_errors->setCountry(
+ response->shipping_address_errors->country);
+ shipping_address_errors->setDependentLocality(
+ response->shipping_address_errors->dependent_locality);
+ shipping_address_errors->setOrganization(
+ response->shipping_address_errors->organization);
+ shipping_address_errors->setPhone(response->shipping_address_errors->phone);
+ shipping_address_errors->setPostalCode(
+ response->shipping_address_errors->postal_code);
+ shipping_address_errors->setRecipient(
+ response->shipping_address_errors->recipient);
+ shipping_address_errors->setRegion(
+ response->shipping_address_errors->region);
+ shipping_address_errors->setSortingCode(
+ response->shipping_address_errors->sorting_code);
+ dictionary->setShippingAddressErrors(shipping_address_errors);
}
- change_payment_method_resolver_->Resolve(
+ change_payment_request_details_resolver_->Resolve(
dictionary->hasError() || dictionary->hasTotal() ||
- dictionary->hasModifiers() || dictionary->hasPaymentMethodErrors()
+ dictionary->hasModifiers() ||
+ dictionary->hasPaymentMethodErrors() ||
+ dictionary->hasShippingOptions() ||
+ dictionary->hasShippingAddressErrors()
? dictionary
: nullptr);
- change_payment_method_resolver_.Clear();
+ change_payment_request_details_resolver_.Clear();
}
void PaymentRequestEvent::OnHostConnectionError() {
- if (change_payment_method_resolver_) {
- change_payment_method_resolver_->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kAbortError, "Browser process disconnected"));
+ if (change_payment_request_details_resolver_) {
+ change_payment_request_details_resolver_->Reject(
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError,
+ "Browser process disconnected"));
}
- change_payment_method_resolver_.Clear();
+ change_payment_request_details_resolver_.Clear();
payment_handler_host_.reset();
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
index ca798d6e2f9..6d65dbff6d4 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
@@ -11,6 +11,7 @@
#include "third_party/blink/public/mojom/payments/payment_handler_host.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/payments/payment_address_init.h"
#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -56,6 +57,9 @@ class MODULES_EXPORT PaymentRequestEvent final : public ExtendableEvent {
const ScriptValue total(ScriptState*) const;
const HeapVector<Member<PaymentDetailsModifier>>& modifiers() const;
const String& instrumentKey() const;
+ const ScriptValue paymentOptions(ScriptState*) const;
+ const HeapVector<Member<PaymentShippingOption>>& shippingOptions(
+ bool& is_null) const;
ScriptPromise openWindow(ScriptState*, const String& url);
ScriptPromise changePaymentMethod(ScriptState*,
@@ -65,12 +69,16 @@ class MODULES_EXPORT PaymentRequestEvent final : public ExtendableEvent {
const String& method_name,
const ScriptValue& method_details,
ExceptionState& exception_state);
+ ScriptPromise changeShippingAddress(ScriptState*,
+ PaymentAddressInit* shippingAddress);
+ ScriptPromise changeShippingOption(ScriptState*,
+ const String& shipping_option_id);
void respondWith(ScriptState*, ScriptPromise, ExceptionState&);
void Trace(blink::Visitor*) override;
private:
- void OnChangePaymentMethodResponse(
+ void OnChangePaymentRequestDetailsResponse(
payments::mojom::blink::PaymentMethodChangeResponsePtr);
void OnHostConnectionError();
@@ -81,8 +89,10 @@ class MODULES_EXPORT PaymentRequestEvent final : public ExtendableEvent {
Member<PaymentCurrencyAmount> total_;
HeapVector<Member<PaymentDetailsModifier>> modifiers_;
String instrument_key_;
+ Member<PaymentOptions> payment_options_;
+ HeapVector<Member<PaymentShippingOption>> shipping_options_;
- Member<ScriptPromiseResolver> change_payment_method_resolver_;
+ Member<ScriptPromiseResolver> change_payment_request_details_resolver_;
Member<RespondWithObserver> observer_;
mojo::Remote<payments::mojom::blink::PaymentHandlerHost>
payment_handler_host_;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.idl b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.idl
index 51d8824b490..2aac585f76f 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.idl
@@ -16,8 +16,12 @@
[CallWith=ScriptState] readonly attribute object total;
readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
readonly attribute DOMString instrumentKey;
+ [CallWith=ScriptState, RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] readonly attribute object? paymentOptions;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] readonly attribute FrozenArray<PaymentShippingOption>? shippingOptions;
[CallWith=ScriptState] Promise<WindowClient?> openWindow(USVString url);
[CallWith=ScriptState, RaisesException, RuntimeEnabled=PaymentHandlerChangePaymentMethod] Promise<PaymentMethodChangeResponse?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
[CallWith=ScriptState, RaisesException] void respondWith(Promise<PaymentResponse> response);
+ [CallWith=ScriptState, RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] Promise<PaymentMethodChangeResponse?> changeShippingAddress(PaymentAddressInit shippingAddress);
+ [CallWith=ScriptState, RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] Promise<PaymentMethodChangeResponse?> changeShippingOption(DOMString shippingOption);
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event_init.idl b/chromium/third_party/blink/renderer/modules/payments/payment_request_event_init.idl
index ffc0e9e9cca..d15da9f9d6b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event_init.idl
@@ -12,4 +12,6 @@ dictionary PaymentRequestEventInit : ExtendableEventInit {
PaymentCurrencyAmount total;
sequence<PaymentDetailsModifier> modifiers;
DOMString instrumentKey;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] PaymentOptions paymentOptions;
+ [RuntimeEnabled=PaymentHandlerHandlesShippingAndContact] sequence<PaymentShippingOption> shippingOptions;
};
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 966c70a7519..76b75d106ed 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
@@ -6,11 +6,14 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_address.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_payment_handler_response.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/modules/payments/payment_address.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_response.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_utils.h"
+#include "third_party/blink/renderer/modules/payments/payments_validators.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -35,10 +38,10 @@ void PaymentRequestRespondWithObserver::OnResponseRejected(
mojom::ServiceWorkerResponseError error) {
PaymentHandlerUtils::ReportResponseError(GetExecutionContext(),
"PaymentRequestEvent", error);
- Respond("", "",
- error == mojom::ServiceWorkerResponseError::kPromiseRejected
- ? PaymentEventResponseType::PAYMENT_EVENT_REJECT
- : PaymentEventResponseType::PAYMENT_EVENT_INTERNAL_ERROR);
+ BlankResponseWithError(
+ error == mojom::ServiceWorkerResponseError::kPromiseRejected
+ ? PaymentEventResponseType::PAYMENT_EVENT_REJECT
+ : PaymentEventResponseType::PAYMENT_EVENT_INTERNAL_ERROR);
}
void PaymentRequestRespondWithObserver::OnResponseFulfilled(
@@ -72,18 +75,19 @@ void PaymentRequestRespondWithObserver::OnResponseFulfilled(
}
if (!response->hasMethodName() || response->methodName().IsEmpty()) {
- Respond("", "", PaymentEventResponseType::PAYMENT_METHOD_NAME_EMPTY);
+ BlankResponseWithError(PaymentEventResponseType::PAYMENT_METHOD_NAME_EMPTY);
return;
}
if (!response->hasDetails()) {
- Respond("", "", PaymentEventResponseType::PAYMENT_DETAILS_ABSENT);
+ BlankResponseWithError(PaymentEventResponseType::PAYMENT_DETAILS_ABSENT);
return;
}
if (response->details().IsNull() || !response->details().IsObject() ||
response->details().IsEmpty()) {
- Respond("", "", PaymentEventResponseType::PAYMENT_DETAILS_NOT_OBJECT);
+ BlankResponseWithError(
+ PaymentEventResponseType::PAYMENT_DETAILS_NOT_OBJECT);
return;
}
@@ -96,19 +100,76 @@ void PaymentRequestRespondWithObserver::OnResponseFulfilled(
mojom::ConsoleMessageLevel::kError,
"Failed to stringify PaymentHandlerResponse.details in payment "
"response."));
- Respond("", "", PaymentEventResponseType::PAYMENT_DETAILS_STRINGIFY_ERROR);
+ BlankResponseWithError(
+ PaymentEventResponseType::PAYMENT_DETAILS_STRINGIFY_ERROR);
return;
}
String details = ToCoreString(details_value);
DCHECK(!details.IsEmpty());
+ String payer_name = response->hasPayerName() ? response->payerName() : "";
+ if (should_have_payer_name_ && payer_name.IsEmpty()) {
+ BlankResponseWithError(PaymentEventResponseType::PAYER_NAME_EMPTY);
+ return;
+ }
+
+ String payer_email = response->hasPayerEmail() ? response->payerEmail() : "";
+ if (should_have_payer_email_ && payer_email.IsEmpty()) {
+ BlankResponseWithError(PaymentEventResponseType::PAYER_EMAIL_EMPTY);
+ return;
+ }
+
+ String payer_phone = response->hasPayerPhone() ? response->payerPhone() : "";
+ if (should_have_payer_phone_ && payer_phone.IsEmpty()) {
+ BlankResponseWithError(PaymentEventResponseType::PAYER_PHONE_EMPTY);
+ return;
+ }
+
+ if (should_have_shipping_info_ && !response->hasShippingAddress()) {
+ BlankResponseWithError(PaymentEventResponseType::SHIPPING_ADDRESS_INVALID);
+ return;
+ }
+
+ payments::mojom::blink::PaymentAddressPtr shipping_address_ptr =
+ should_have_shipping_info_ ? payments::mojom::blink::PaymentAddress::New()
+ : nullptr;
+ if (should_have_shipping_info_) {
+ auto* shipping_address = response->shippingAddress();
+ shipping_address_ptr->country = shipping_address->country();
+ shipping_address_ptr->address_line = shipping_address->addressLine();
+ shipping_address_ptr->region = shipping_address->region();
+ shipping_address_ptr->city = shipping_address->city();
+ shipping_address_ptr->dependent_locality =
+ shipping_address->dependentLocality();
+ shipping_address_ptr->postal_code = shipping_address->postalCode();
+ shipping_address_ptr->sorting_code = shipping_address->sortingCode();
+ shipping_address_ptr->organization = shipping_address->organization();
+ shipping_address_ptr->recipient = shipping_address->recipient();
+ shipping_address_ptr->phone = shipping_address->phone();
+ if (!PaymentsValidators::IsValidShippingAddress(
+ shipping_address_ptr, nullptr /* = optional_error_message */)) {
+ BlankResponseWithError(
+ PaymentEventResponseType::SHIPPING_ADDRESS_INVALID);
+ return;
+ }
+ }
+
+ String selected_shipping_option_id =
+ response->hasShippingOption() ? response->shippingOption() : "";
+ if (should_have_shipping_info_ && selected_shipping_option_id.IsEmpty()) {
+ BlankResponseWithError(PaymentEventResponseType::SHIPPING_OPTION_EMPTY);
+ return;
+ }
+
Respond(response->methodName(), details,
- PaymentEventResponseType::PAYMENT_EVENT_SUCCESS);
+ PaymentEventResponseType::PAYMENT_EVENT_SUCCESS, payer_name,
+ payer_email, payer_phone, std::move(shipping_address_ptr),
+ selected_shipping_option_id);
}
void PaymentRequestRespondWithObserver::OnNoResponse() {
- Respond("", "", PaymentEventResponseType::PAYMENT_EVENT_NO_RESPONSE);
+ BlankResponseWithError(PaymentEventResponseType::PAYMENT_EVENT_NO_RESPONSE);
}
PaymentRequestRespondWithObserver::PaymentRequestRespondWithObserver(
@@ -124,12 +185,25 @@ void PaymentRequestRespondWithObserver::Trace(blink::Visitor* visitor) {
void PaymentRequestRespondWithObserver::Respond(
const String& method_name,
const String& stringified_details,
- PaymentEventResponseType response_type) {
+ PaymentEventResponseType response_type,
+ const String& payer_name,
+ const String& payer_email,
+ const String& payer_phone,
+ payments::mojom::blink::PaymentAddressPtr shipping_address,
+ const String& selected_shipping_option_id) {
DCHECK(GetExecutionContext());
To<ServiceWorkerGlobalScope>(GetExecutionContext())
->RespondToPaymentRequestEvent(
- event_id_, payments::mojom::blink::PaymentHandlerResponse::New(
- method_name, stringified_details, response_type));
+ event_id_,
+ payments::mojom::blink::PaymentHandlerResponse::New(
+ method_name, stringified_details, response_type, payer_name,
+ payer_email, payer_phone, std::move(shipping_address),
+ selected_shipping_option_id));
+}
+
+void PaymentRequestRespondWithObserver::BlankResponseWithError(
+ PaymentEventResponseType response_type) {
+ Respond("", "", response_type, "", "", "", nullptr, "");
}
} // namespace blink
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 3eaf4d7451b..a9428dc89fc 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
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_REQUEST_RESPOND_WITH_OBSERVER_H_
#include "third_party/blink/public/mojom/payments/payment_app.mojom-blink.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
@@ -41,10 +41,34 @@ class MODULES_EXPORT PaymentRequestRespondWithObserver final
void Trace(blink::Visitor*) override;
+ void set_should_have_payer_name(bool should_have_payer_name) {
+ should_have_payer_name_ = should_have_payer_name;
+ }
+ void set_should_have_payer_email(bool should_have_payer_email) {
+ should_have_payer_email_ = should_have_payer_email;
+ }
+ void set_should_have_payer_phone(bool should_have_payer_phone) {
+ should_have_payer_phone_ = should_have_payer_phone;
+ }
+ void set_should_have_shipping_info(bool should_have_shipping_info) {
+ should_have_shipping_info_ = should_have_shipping_info;
+ }
+
private:
void Respond(const String& method_name,
const String& stringified_details,
- payments::mojom::blink::PaymentEventResponseType response_type);
+ payments::mojom::blink::PaymentEventResponseType response_type,
+ const String& payer_name,
+ const String& payer_email,
+ const String& payer_phone,
+ payments::mojom::blink::PaymentAddressPtr shipping_address,
+ const String& selected_shipping_option_id);
+ void BlankResponseWithError(
+ payments::mojom::blink::PaymentEventResponseType response_type);
+ bool should_have_payer_name_ = false;
+ bool should_have_payer_email_ = false;
+ bool should_have_payer_phone_ = false;
+ bool should_have_shipping_info_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
index e52fcb33c47..930831f133b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
@@ -21,7 +21,7 @@
namespace blink {
namespace {
-class MockPaymentRequest : public GarbageCollectedFinalized<MockPaymentRequest>,
+class MockPaymentRequest : public GarbageCollected<MockPaymentRequest>,
public PaymentRequestDelegate {
USING_GARBAGE_COLLECTED_MIXIN(MockPaymentRequest);
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 0116fdc0351..e95bb6f80d3 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -104,7 +104,8 @@ ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const {
}
ScriptValue PaymentResponse::details(ScriptState* script_state) const {
- return ScriptValue(script_state, details_.GetAcrossWorld(script_state));
+ return ScriptValue(script_state->GetIsolate(),
+ details_.GetAcrossWorld(script_state));
}
ScriptPromise PaymentResponse::complete(ScriptState* script_state,
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 05af654dcbc..c890b371325 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_RESPONSE_H_
#include "base/macros.h"
-#include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/payments/payment_request.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/bindings/core/v8/script_value.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
index 38928418d6f..35d6d02f1c4 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
@@ -25,7 +25,7 @@ namespace blink {
namespace {
class MockPaymentStateResolver final
- : public GarbageCollectedFinalized<MockPaymentStateResolver>,
+ : public GarbageCollected<MockPaymentStateResolver>,
public PaymentStateResolver {
USING_GARBAGE_COLLECTED_MIXIN(MockPaymentStateResolver);
@@ -42,7 +42,9 @@ class MockPaymentStateResolver final
ScriptPromise(ScriptState*,
const PaymentValidationErrors* errorFields));
- void Trace(blink::Visitor* visitor) override {}
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(dummy_promise_);
+ }
private:
ScriptPromise dummy_promise_;
@@ -80,7 +82,7 @@ TEST(PaymentResponseTest, DataCopiedOver) {
ASSERT_TRUE(details.V8Value()->IsObject());
ScriptValue transaction_id(
- scope.GetScriptState(),
+ scope.GetIsolate(),
details.V8Value()
.As<v8::Object>()
->Get(scope.GetContext(),
diff --git a/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils.cc b/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils.cc
index 761da35f933..1a7f1426e13 100644
--- a/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils.cc
@@ -35,9 +35,11 @@ bool PatchGooglePayContactRequestV1(const PaymentOptions& options,
JSONObject* output,
bool* phone_requested,
bool* name_requested) {
- if (options.requestPayerName()) {
+ if (options.requestPayerName() || options.requestPayerPhone()) {
const JSONObject* card_requirements =
output->GetJSONObject("cardRequirements");
+ // Phone number is returned as part of billing address, so
+ // |billingAddressRequired| must be set even if name is not requested.
if (!card_requirements ||
!card_requirements->BooleanProperty("billingAddressRequired", false)) {
GetJSONObjectOrInsert(output, "cardRequirements")
@@ -169,8 +171,10 @@ bool SkipToGPayUtils::PatchPaymentMethodData(
return false;
int api_version;
- if (!object->GetInteger("apiVersion", &api_version))
- return false;
+ if (!object->GetInteger("apiVersion", &api_version)) {
+ // Some API v1 clients don't explicitly specify "apiVersion".
+ api_version = 1;
+ }
bool success = true;
diff --git a/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils_test.cc b/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils_test.cc
index c53660dd0b8..0d56ae8025d 100644
--- a/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/skip_to_gpay_utils_test.cc
@@ -1,3 +1,7 @@
+// 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/payments/skip_to_gpay_utils.h"
#include <memory>
@@ -62,12 +66,13 @@ TEST(SkipToGPayUtilsTest, NothingRequested) {
}
}
-TEST(SkipToGPayUtilsTest, InvalidInputData_MissingApiVersion) {
+TEST(SkipToGPayUtilsTest, MissingApiVersionConsideredV1) {
auto* options = PaymentOptions::Create();
PaymentMethodDataPtr output = MakeTestPaymentMethodData();
+ output->stringified_data = "{}";
- ASSERT_FALSE(SkipToGPayUtils::PatchPaymentMethodData(*options, output));
- EXPECT_TRUE(output->gpay_bridge_data.is_null());
+ ASSERT_TRUE(SkipToGPayUtils::PatchPaymentMethodData(*options, output));
+ EXPECT_EQ("{}", output->gpay_bridge_data->stringified_data);
}
TEST(SkipToGPayUtilsTest, InvalidInputData_NotJSON) {
@@ -132,6 +137,49 @@ TEST(SkipToGPayUtilsTest, RequestEverything) {
}
}
+TEST(SkipToGPayUtilsTest, RequestPhoneOnly) {
+ auto* options = PaymentOptions::Create();
+ options->setRequestPayerPhone(true);
+
+ {
+ PaymentMethodDataPtr output = MakeTestPaymentMethodData();
+ output->stringified_data = kInputDataV1;
+
+ ASSERT_TRUE(SkipToGPayUtils::PatchPaymentMethodData(*options, output));
+
+ EXPECT_EQ(
+ "{\"apiVersion\":1,\"cardRequirements\":{\"billingAddressRequired\":"
+ "true},\"phoneNumberRequired\":true}",
+ output->gpay_bridge_data->stringified_data);
+ EXPECT_TRUE(output->gpay_bridge_data->phone_requested);
+ // Phone number can only be requested as part of billing address, which
+ // implies that name will be requested too.
+ EXPECT_TRUE(output->gpay_bridge_data->name_requested);
+ EXPECT_FALSE(output->gpay_bridge_data->email_requested);
+ EXPECT_FALSE(output->gpay_bridge_data->shipping_requested);
+ EXPECT_EQ(kInputDataV1, output->stringified_data);
+ }
+ {
+ PaymentMethodDataPtr output = MakeTestPaymentMethodData();
+ output->stringified_data = kInputDataV2;
+
+ ASSERT_TRUE(SkipToGPayUtils::PatchPaymentMethodData(*options, output));
+
+ EXPECT_EQ(
+ "{\"apiVersion\":2,\"apiVersionMinor\":0,\"allowedPaymentMethods\":[{"
+ "\"type\":\"CARD\",\"parameters\":{\"billingAddressRequired\":true,"
+ "\"billingAddressParameters\":{\"phoneNumberRequired\":true}}}]}",
+ output->gpay_bridge_data->stringified_data);
+ EXPECT_TRUE(output->gpay_bridge_data->phone_requested);
+ // Phone number can only be requested as part of billing address, which
+ // implies that name will be requested too.
+ EXPECT_TRUE(output->gpay_bridge_data->name_requested);
+ EXPECT_FALSE(output->gpay_bridge_data->email_requested);
+ EXPECT_FALSE(output->gpay_bridge_data->shipping_requested);
+ EXPECT_EQ(kInputDataV2, output->stringified_data);
+ }
+}
+
TEST(SkipToGPayUtilsTest, ShippingAlreadyRequested) {
auto* options = PaymentOptions::Create();
options->setRequestPayerName(true);
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
index 98cef042aaa..32ce674d4be 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -53,8 +53,12 @@ blink_modules_sources("peerconnection") {
"call_setup_state_tracker.cc",
"call_setup_state_tracker.h",
"media_stream_remote_video_source.cc",
+ "media_stream_video_webrtc_sink.cc",
+ "peer_connection_dependency_factory.cc",
"rtc_certificate.cc",
"rtc_certificate.h",
+ "rtc_certificate_generator.cc",
+ "rtc_certificate_generator.h",
"rtc_data_channel.cc",
"rtc_data_channel.h",
"rtc_data_channel_event.cc",
@@ -93,10 +97,13 @@ blink_modules_sources("peerconnection") {
"rtc_quic_transport.h",
"rtc_rtp_receiver.cc",
"rtc_rtp_receiver.h",
+ "rtc_rtp_receiver_impl.cc",
"rtc_rtp_sender.cc",
"rtc_rtp_sender.h",
+ "rtc_rtp_sender_impl.cc",
"rtc_rtp_transceiver.cc",
"rtc_rtp_transceiver.h",
+ "rtc_rtp_transceiver_impl.cc",
"rtc_sctp_transport.cc",
"rtc_sctp_transport.h",
"rtc_session_description.cc",
@@ -120,12 +127,37 @@ blink_modules_sources("peerconnection") {
"rtc_void_request_promise_impl.h",
"rtc_void_request_script_promise_resolver_impl.cc",
"rtc_void_request_script_promise_resolver_impl.h",
+ "transceiver_state_surfacer.cc",
"web_rtc_stats_report_callback_resolver.cc",
"web_rtc_stats_report_callback_resolver.h",
+ "webrtc_media_stream_track_adapter.cc",
+ "webrtc_media_stream_track_adapter_map.cc",
]
public_deps = [
"//third_party/webrtc/api:ice_transport_factory",
+ "//third_party/webrtc/api:rtc_error",
"//third_party/webrtc/api:scoped_refptr",
]
}
+
+jumbo_source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "fake_rtc_rtp_transceiver_impl.cc",
+ "mock_data_channel_impl.cc",
+ "mock_peer_connection_dependency_factory.cc",
+ "mock_peer_connection_impl.cc",
+ "mock_web_rtc_peer_connection_handler_client.cc",
+ "webrtc_stats_report_obtainer.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//third_party/blink/public:test_headers",
+ "//third_party/webrtc_overrides:init_webrtc",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/DEPS b/chromium/third_party/blink/renderer/modules/peerconnection/DEPS
index f84dc56c481..c0f90696a5f 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/DEPS
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+services/metrics/public/cpp/ukm_builders.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/crypto",
"+third_party/blink/renderer/modules/event_modules.h",
@@ -7,15 +6,25 @@ include_rules = [
"+third_party/blink/renderer/modules/mediastream",
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/peerconnection",
+ "+third_party/blink/renderer/modules/p2p",
+
+ "+crypto/openssl_util.h",
+ "+jingle/glue/thread_wrapper.h",
"+media/base",
+ "+media/media_buildflags.h",
+ "+media/video/gpu_video_accelerator_factories.h",
"+net/third_party/quiche/src/quic",
"+net/quic/chromium",
"+net/quic",
"+net/test",
+ "+services/metrics/public/cpp/ukm_builders.h",
]
specific_include_rules = {
- "rtc_data_channel_test\.cc" : [
+ ".*test\.cc" : [
"+base/run_loop.h",
+ "+base/test/bind_test_util.h",
+ "+base/test/test_timeouts.h",
+ "+ui/gfx/color_space.h",
],
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/OWNERS b/chromium/third_party/blink/renderer/modules/peerconnection/OWNERS
index 347366aa979..f2eebf81dfc 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/OWNERS
@@ -1,6 +1,7 @@
guidou@chromium.org
hbos@chromium.org
orphis@chromium.org
+sergeyu@chromium.org
steveanton@chromium.org
tommi@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc b/chromium/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
index eec9ff8f259..ca3088c22ff 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
@@ -174,7 +174,23 @@ TEST_F(P2PQuicStreamTest, StreamClosedAfterReceivingReset) {
quic::QuicRstStreamFrame rst_frame(quic::kInvalidControlFrameId, kStreamId,
quic::QUIC_STREAM_CANCELLED, 0);
+ if (!VersionHasIetfQuicFrames(connection_->version().transport_version)) {
+ // Google RST_STREAM closes the stream in both directions. A RST_STREAM
+ // is then sent to the peer to communicate the final byte offset.
+ EXPECT_CALL(session_,
+ SendRstStream(kStreamId, quic::QUIC_RST_ACKNOWLEDGEMENT, 0));
+ }
stream_->OnStreamReset(rst_frame);
+ if (VersionHasIetfQuicFrames(connection_->version().transport_version)) {
+ // In IETF QUIC, the RST_STREAM only closes the stream in one direction.
+ // A STOP_SENDING frame in require to induce the a RST_STREAM being
+ // send to close the other direction.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_, OnStreamReset(kStreamId, testing::_));
+ quic::QuicStopSendingFrame stop_sending_frame(quic::kInvalidControlFrameId,
+ kStreamId, 0);
+ session_.OnStopSendingFrame(stop_sending_frame);
+ }
EXPECT_TRUE(stream_->IsClosedForTesting());
}
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
new file mode 100644
index 00000000000..c0b8bdf7acc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
@@ -0,0 +1,257 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "third_party/blink/public/web/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h"
+
+namespace blink {
+
+blink::WebMediaStreamTrack CreateWebMediaStreamTrack(
+ const std::string& id,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(blink::WebString::FromUTF8(id),
+ blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("audio_track"), false);
+ std::unique_ptr<blink::MediaStreamAudioSource> audio_source_ptr =
+ std::make_unique<blink::MediaStreamAudioSource>(
+ std::move(task_runner), true /* is_local_source */);
+ blink::MediaStreamAudioSource* audio_source = audio_source_ptr.get();
+ // Takes ownership of |audio_source_ptr|.
+ web_source.SetPlatformSource(std::move(audio_source_ptr));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+}
+
+FakeRTCRtpSenderImpl::FakeRTCRtpSenderImpl(
+ base::Optional<std::string> track_id,
+ std::vector<std::string> stream_ids,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : track_id_(std::move(track_id)),
+ stream_ids_(std::move(stream_ids)),
+ task_runner_(task_runner) {}
+
+FakeRTCRtpSenderImpl::FakeRTCRtpSenderImpl(const FakeRTCRtpSenderImpl&) =
+ default;
+
+FakeRTCRtpSenderImpl::~FakeRTCRtpSenderImpl() {}
+
+FakeRTCRtpSenderImpl& FakeRTCRtpSenderImpl::operator=(
+ const FakeRTCRtpSenderImpl&) = default;
+
+std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpSenderImpl::ShallowCopy()
+ const {
+ return std::make_unique<FakeRTCRtpSenderImpl>(*this);
+}
+
+uintptr_t FakeRTCRtpSenderImpl::Id() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+FakeRTCRtpSenderImpl::DtlsTransport() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+webrtc::DtlsTransportInformation
+FakeRTCRtpSenderImpl::DtlsTransportInformation() {
+ NOTIMPLEMENTED();
+ static webrtc::DtlsTransportInformation dummy(
+ webrtc::DtlsTransportState::kNew);
+ return dummy;
+}
+
+blink::WebMediaStreamTrack FakeRTCRtpSenderImpl::Track() const {
+ return track_id_ ? CreateWebMediaStreamTrack(*track_id_, task_runner_)
+ : blink::WebMediaStreamTrack(); // null
+}
+
+blink::WebVector<blink::WebString> FakeRTCRtpSenderImpl::StreamIds() const {
+ blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size());
+ for (size_t i = 0; i < stream_ids_.size(); ++i) {
+ web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]);
+ }
+ return web_stream_ids;
+}
+
+void FakeRTCRtpSenderImpl::ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ blink::WebRTCVoidRequest request) {
+ NOTIMPLEMENTED();
+}
+
+std::unique_ptr<blink::WebRTCDTMFSenderHandler>
+FakeRTCRtpSenderImpl::GetDtmfSender() const {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+std::unique_ptr<webrtc::RtpParameters> FakeRTCRtpSenderImpl::GetParameters()
+ const {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+void FakeRTCRtpSenderImpl::SetParameters(
+ blink::WebVector<webrtc::RtpEncodingParameters>,
+ webrtc::DegradationPreference,
+ blink::WebRTCVoidRequest) {
+ NOTIMPLEMENTED();
+}
+
+void FakeRTCRtpSenderImpl::GetStats(
+ blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) {
+ NOTIMPLEMENTED();
+}
+
+void FakeRTCRtpSenderImpl::SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) {
+ NOTIMPLEMENTED();
+}
+
+FakeRTCRtpReceiverImpl::FakeRTCRtpReceiverImpl(
+ const std::string& track_id,
+ std::vector<std::string> stream_ids,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : track_(CreateWebMediaStreamTrack(track_id, task_runner)),
+ stream_ids_(std::move(stream_ids)) {}
+
+FakeRTCRtpReceiverImpl::FakeRTCRtpReceiverImpl(const FakeRTCRtpReceiverImpl&) =
+ default;
+
+FakeRTCRtpReceiverImpl::~FakeRTCRtpReceiverImpl() {}
+
+FakeRTCRtpReceiverImpl& FakeRTCRtpReceiverImpl::operator=(
+ const FakeRTCRtpReceiverImpl&) = default;
+
+std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpReceiverImpl::ShallowCopy()
+ const {
+ return std::make_unique<FakeRTCRtpReceiverImpl>(*this);
+}
+
+uintptr_t FakeRTCRtpReceiverImpl::Id() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+FakeRTCRtpReceiverImpl::DtlsTransport() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+webrtc::DtlsTransportInformation
+FakeRTCRtpReceiverImpl::DtlsTransportInformation() {
+ NOTIMPLEMENTED();
+ static webrtc::DtlsTransportInformation dummy(
+ webrtc::DtlsTransportState::kNew);
+ return dummy;
+}
+
+const blink::WebMediaStreamTrack& FakeRTCRtpReceiverImpl::Track() const {
+ return track_;
+}
+
+blink::WebVector<blink::WebString> FakeRTCRtpReceiverImpl::StreamIds() const {
+ blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size());
+ for (size_t i = 0; i < stream_ids_.size(); ++i) {
+ web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]);
+ }
+ return web_stream_ids;
+}
+
+blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>>
+FakeRTCRtpReceiverImpl::GetSources() {
+ NOTIMPLEMENTED();
+ return {};
+}
+
+void FakeRTCRtpReceiverImpl::GetStats(
+ blink::WebRTCStatsReportCallback,
+ const blink::WebVector<webrtc::NonStandardGroupId>&) {
+ NOTIMPLEMENTED();
+}
+
+std::unique_ptr<webrtc::RtpParameters> FakeRTCRtpReceiverImpl::GetParameters()
+ const {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+void FakeRTCRtpReceiverImpl::SetJitterBufferMinimumDelay(
+ base::Optional<double> delay_seconds) {
+ NOTIMPLEMENTED();
+}
+
+FakeRTCRtpTransceiverImpl::FakeRTCRtpTransceiverImpl(
+ base::Optional<std::string> mid,
+ FakeRTCRtpSenderImpl sender,
+ FakeRTCRtpReceiverImpl receiver,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction)
+ : mid_(std::move(mid)),
+ sender_(std::move(sender)),
+ receiver_(std::move(receiver)),
+ stopped_(stopped),
+ direction_(std::move(direction)),
+ current_direction_(std::move(current_direction)) {}
+
+FakeRTCRtpTransceiverImpl::~FakeRTCRtpTransceiverImpl() {}
+
+blink::WebRTCRtpTransceiverImplementationType
+FakeRTCRtpTransceiverImpl::ImplementationType() const {
+ return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver;
+}
+
+uintptr_t FakeRTCRtpTransceiverImpl::Id() const {
+ NOTIMPLEMENTED();
+ return 0u;
+}
+
+blink::WebString FakeRTCRtpTransceiverImpl::Mid() const {
+ return mid_ ? blink::WebString::FromUTF8(*mid_) : blink::WebString();
+}
+
+std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpTransceiverImpl::Sender()
+ const {
+ return sender_.ShallowCopy();
+}
+
+std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpTransceiverImpl::Receiver()
+ const {
+ return receiver_.ShallowCopy();
+}
+
+bool FakeRTCRtpTransceiverImpl::Stopped() const {
+ return stopped_;
+}
+
+webrtc::RtpTransceiverDirection FakeRTCRtpTransceiverImpl::Direction() const {
+ return direction_;
+}
+
+void FakeRTCRtpTransceiverImpl::SetDirection(
+ webrtc::RtpTransceiverDirection direction) {
+ NOTIMPLEMENTED();
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+FakeRTCRtpTransceiverImpl::CurrentDirection() const {
+ return current_direction_;
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+FakeRTCRtpTransceiverImpl::FiredDirection() const {
+ NOTIMPLEMENTED();
+ return base::nullopt;
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..2e9aa9ddfbf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -0,0 +1,234 @@
+// 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/web/modules/peerconnection/media_stream_remote_video_source.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "media/base/video_frame.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/modules/webrtc/track_observer.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_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_sink.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/webrtc/api/video/color_space.h"
+#include "third_party/webrtc/api/video/i420_buffer.h"
+#include "ui/gfx/color_space.h"
+
+namespace blink {
+
+ACTION_P(RunClosure, closure) {
+ closure.Run();
+}
+
+class MediaStreamRemoteVideoSourceUnderTest
+ : public blink::MediaStreamRemoteVideoSource {
+ public:
+ explicit MediaStreamRemoteVideoSourceUnderTest(
+ std::unique_ptr<blink::TrackObserver> observer)
+ : MediaStreamRemoteVideoSource(std::move(observer)) {}
+ using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
+ using MediaStreamRemoteVideoSource::StartSourceImpl;
+};
+
+class MediaStreamRemoteVideoSourceTest : public ::testing::Test {
+ public:
+ MediaStreamRemoteVideoSourceTest()
+ : mock_factory_(new blink::MockPeerConnectionDependencyFactory()),
+ webrtc_video_track_(blink::MockWebRtcVideoTrack::Create("test")),
+ remote_source_(nullptr),
+ number_of_successful_track_starts_(0),
+ number_of_failed_track_starts_(0) {}
+
+ void SetUp() override {
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread =
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+
+ base::WaitableEvent waitable_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ std::unique_ptr<blink::TrackObserver> track_observer;
+ mock_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](scoped_refptr<base::SingleThreadTaskRunner> main_thread,
+ webrtc::MediaStreamTrackInterface* webrtc_track,
+ std::unique_ptr<blink::TrackObserver>* track_observer,
+ base::WaitableEvent* waitable_event) {
+ track_observer->reset(
+ new blink::TrackObserver(main_thread, webrtc_track));
+ waitable_event->Signal();
+ },
+ main_thread, base::Unretained(webrtc_video_track_.get()),
+ base::Unretained(&track_observer),
+ base::Unretained(&waitable_event)));
+ waitable_event.Wait();
+
+ remote_source_ =
+ new MediaStreamRemoteVideoSourceUnderTest(std::move(track_observer));
+ web_source_.Initialize(blink::WebString::FromASCII("dummy_source_id"),
+ blink::WebMediaStreamSource::kTypeVideo,
+ blink::WebString::FromASCII("dummy_source_name"),
+ true /* remote */);
+ web_source_.SetPlatformSource(base::WrapUnique(remote_source_));
+ }
+
+ void TearDown() override {
+ remote_source_->OnSourceTerminated();
+ web_source_.Reset();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ MediaStreamRemoteVideoSourceUnderTest* source() { return remote_source_; }
+
+ blink::MediaStreamVideoTrack* CreateTrack() {
+ bool enabled = true;
+ return new blink::MediaStreamVideoTrack(
+ source(),
+ base::Bind(&MediaStreamRemoteVideoSourceTest::OnTrackStarted,
+ base::Unretained(this)),
+ enabled);
+ }
+
+ int NumberOfSuccessConstraintsCallbacks() const {
+ return number_of_successful_track_starts_;
+ }
+
+ int NumberOfFailedConstraintsCallbacks() const {
+ return number_of_failed_track_starts_;
+ }
+
+ void StopWebRtcTrack() {
+ base::WaitableEvent waitable_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ mock_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](blink::MockWebRtcVideoTrack* video_track,
+ base::WaitableEvent* waitable_event) {
+ video_track->SetEnded();
+ waitable_event->Signal();
+ },
+ base::Unretained(static_cast<blink::MockWebRtcVideoTrack*>(
+ webrtc_video_track_.get())),
+ base::Unretained(&waitable_event)));
+ waitable_event.Wait();
+ }
+
+ const blink::WebMediaStreamSource& webkit_source() const {
+ return web_source_;
+ }
+
+ private:
+ void OnTrackStarted(blink::WebPlatformMediaStreamSource* source,
+ blink::mojom::MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
+ ASSERT_EQ(source, remote_source_);
+ if (result == blink::mojom::MediaStreamRequestResult::OK)
+ ++number_of_successful_track_starts_;
+ else
+ ++number_of_failed_track_starts_;
+ }
+
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory> mock_factory_;
+ scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
+ // |remote_source_| is owned by |web_source_|.
+ MediaStreamRemoteVideoSourceUnderTest* remote_source_;
+ blink::WebMediaStreamSource web_source_;
+ int number_of_successful_track_starts_;
+ int number_of_failed_track_starts_;
+};
+
+TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
+ std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+ EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
+
+ blink::MockMediaStreamVideoSink sink;
+ track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+ base::RunLoop run_loop;
+ base::Closure quit_closure = run_loop.QuitClosure();
+ EXPECT_CALL(sink, OnVideoFrame())
+ .WillOnce(RunClosure(std::move(quit_closure)));
+ rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+ new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+
+ webrtc::I420Buffer::SetBlack(buffer);
+
+ source()->SinkInterfaceForTesting()->OnFrame(
+ webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .set_timestamp_us(1000)
+ .build());
+ run_loop.Run();
+
+ EXPECT_EQ(1, sink.number_of_frames());
+ track->RemoveSink(&sink);
+}
+
+TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
+ std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+
+ blink::MockMediaStreamVideoSink sink;
+ track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+ EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, sink.state());
+ EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive,
+ webkit_source().GetReadyState());
+ StopWebRtcTrack();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded,
+ webkit_source().GetReadyState());
+ EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, sink.state());
+
+ track->RemoveSink(&sink);
+}
+
+TEST_F(MediaStreamRemoteVideoSourceTest, PreservesColorSpace) {
+ std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+ blink::MockMediaStreamVideoSink sink;
+ track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(sink, OnVideoFrame())
+ .WillOnce(RunClosure(run_loop.QuitClosure()));
+ rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+ new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+ webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kSMPTE240M,
+ webrtc::ColorSpace::TransferID::kSMPTE240M,
+ webrtc::ColorSpace::MatrixID::kSMPTE240M,
+ webrtc::ColorSpace::RangeID::kLimited);
+ const webrtc::VideoFrame& input_frame =
+ webrtc::VideoFrame::Builder()
+ .set_video_frame_buffer(buffer)
+ .set_timestamp_ms(0)
+ .set_rotation(webrtc::kVideoRotation_0)
+ .set_color_space(kColorSpace)
+ .build();
+ source()->SinkInterfaceForTesting()->OnFrame(input_frame);
+ run_loop.Run();
+
+ EXPECT_EQ(1, sink.number_of_frames());
+ scoped_refptr<media::VideoFrame> output_frame = sink.last_frame();
+ EXPECT_TRUE(output_frame);
+ EXPECT_TRUE(output_frame->ColorSpace() ==
+ gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE240M,
+ gfx::ColorSpace::TransferID::SMPTE240M,
+ gfx::ColorSpace::MatrixID::SMPTE240M,
+ gfx::ColorSpace::RangeID::LIMITED));
+ track->RemoveSink(&sink);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..729d72c5465
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
@@ -0,0 +1,314 @@
+// 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/web/modules/peerconnection/media_stream_video_webrtc_sink.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "media/base/limits.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_video_track_source.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/web_media_stream_utils.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.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 {
+
+namespace {
+
+absl::optional<bool> ToAbslOptionalBool(const base::Optional<bool>& value) {
+ return value ? absl::optional<bool>(*value) : absl::nullopt;
+}
+
+} // namespace
+
+namespace {
+
+// The default number of microseconds that should elapse since the last video
+// frame was received, before requesting a refresh frame.
+const int64_t kDefaultRefreshIntervalMicros =
+ base::Time::kMicrosecondsPerSecond;
+
+// A lower-bound for the refresh interval.
+const int64_t kLowerBoundRefreshIntervalMicros =
+ base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond;
+
+webrtc::VideoTrackInterface::ContentHint ContentHintTypeToWebRtcContentHint(
+ WebMediaStreamTrack::ContentHintType content_hint) {
+ switch (content_hint) {
+ case WebMediaStreamTrack::ContentHintType::kNone:
+ return webrtc::VideoTrackInterface::ContentHint::kNone;
+ case WebMediaStreamTrack::ContentHintType::kAudioSpeech:
+ case WebMediaStreamTrack::ContentHintType::kAudioMusic:
+ NOTREACHED();
+ break;
+ case WebMediaStreamTrack::ContentHintType::kVideoMotion:
+ return webrtc::VideoTrackInterface::ContentHint::kFluid;
+ case WebMediaStreamTrack::ContentHintType::kVideoDetail:
+ return webrtc::VideoTrackInterface::ContentHint::kDetailed;
+ case WebMediaStreamTrack::ContentHintType::kVideoText:
+ return webrtc::VideoTrackInterface::ContentHint::kText;
+ }
+ NOTREACHED();
+ return webrtc::VideoTrackInterface::ContentHint::kNone;
+}
+
+} // namespace
+
+// Simple help class used for receiving video frames on the IO-thread from a
+// MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter
+// on libjingle's worker thread. WebRtcVideoCapturerAdapter implements a video
+// capturer for libjingle.
+class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
+ : public WTF::ThreadSafeRefCounted<WebRtcVideoSourceAdapter> {
+ public:
+ WebRtcVideoSourceAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ libjingle_worker_thread,
+ const scoped_refptr<WebRtcVideoTrackSource>& source,
+ base::TimeDelta refresh_interval,
+ const base::RepeatingClosure& refresh_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ // MediaStreamVideoWebRtcSink can be destroyed on the main render thread or
+ // libjingles worker thread since it posts video frames on that thread. But
+ // |video_source_| must be released on the main render thread before the
+ // PeerConnectionFactory has been destroyed. The only way to ensure that is to
+ // make sure |video_source_| is released when MediaStreamVideoWebRtcSink() is
+ // destroyed.
+ void ReleaseSourceOnMainThread();
+
+ void OnVideoFrameOnIO(scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time);
+
+ private:
+ friend class WTF::ThreadSafeRefCounted<WebRtcVideoSourceAdapter>;
+
+ void OnVideoFrameOnWorkerThread(scoped_refptr<media::VideoFrame> frame);
+
+ virtual ~WebRtcVideoSourceAdapter();
+
+ // Called whenever a video frame was just delivered on the IO thread. This
+ // restarts the delay period before the |refresh_timer_| will fire the next
+ // time.
+ void ResetRefreshTimerOnMainThread();
+
+ scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_;
+
+ // |render_thread_checker_| is bound to the main render thread.
+ THREAD_CHECKER(render_thread_checker_);
+ // Used to DCHECK that frames are called on the IO-thread.
+ THREAD_CHECKER(io_thread_checker_);
+
+ // Used for posting frames to libjingle's worker thread. Accessed on the
+ // IO-thread.
+ scoped_refptr<base::SingleThreadTaskRunner> libjingle_worker_thread_;
+
+ scoped_refptr<WebRtcVideoTrackSource> video_source_;
+
+ // Used to protect |video_source_|. It is taken by libjingle's worker
+ // thread for each video frame that is delivered but only taken on the
+ // main render thread in ReleaseSourceOnMainThread() when
+ // the owning MediaStreamVideoWebRtcSink is being destroyed.
+ base::Lock video_source_stop_lock_;
+
+ // Requests a refresh frame at regular intervals. The delay on this timer is
+ // reset each time a frame is received so that it will not fire for at least
+ // an additional period. This means refresh frames will only be requested when
+ // the source has halted delivery (e.g., a screen capturer stops sending
+ // frames because the screen is not being updated).
+ //
+ // This mechanism solves a number of problems. First, it will ensure that
+ // remote clients that join a distributed session receive a first video frame
+ // in a timely manner. Second, it will allow WebRTC's internal bandwidth
+ // estimation logic to maintain a more optimal state, since sending a video
+ // frame will "prime it." Third, it allows lossy encoders to clean up
+ // artifacts in a still image. http://crbug.com/486274
+ base::RepeatingTimer refresh_timer_;
+};
+
+MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread,
+ const scoped_refptr<WebRtcVideoTrackSource>& source,
+ base::TimeDelta refresh_interval,
+ const base::RepeatingClosure& refresh_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : render_task_runner_(std::move(task_runner)),
+ libjingle_worker_thread_(libjingle_worker_thread),
+ video_source_(source) {
+ DCHECK(render_task_runner_->RunsTasksInCurrentSequence());
+ DETACH_FROM_THREAD(io_thread_checker_);
+ if (!refresh_interval.is_zero()) {
+ VLOG(1) << "Starting frame refresh timer with interval "
+ << refresh_interval.InMillisecondsF() << " ms.";
+ refresh_timer_.Start(FROM_HERE, refresh_interval, refresh_callback);
+ }
+}
+
+MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+ ~WebRtcVideoSourceAdapter() {
+ DVLOG(3) << "~WebRtcVideoSourceAdapter()";
+ DCHECK(!video_source_);
+ // This object can be destroyed on the main render thread or libjingles worker
+ // thread since it posts video frames on that thread. But |video_source_| must
+ // be released on the main render thread before the PeerConnectionFactory has
+ // been destroyed. The only way to ensure that is to make sure |video_source_|
+ // is released when MediaStreamVideoWebRtcSink() is destroyed.
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+ ResetRefreshTimerOnMainThread() {
+ DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
+ if (refresh_timer_.IsRunning())
+ refresh_timer_.Reset();
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+ ReleaseSourceOnMainThread() {
+ DCHECK_CALLED_ON_VALID_THREAD(render_thread_checker_);
+ // Since frames are posted to the worker thread, this object might be deleted
+ // on that thread. However, since |video_source_| was created on the render
+ // thread, it should be released on the render thread.
+ base::AutoLock auto_lock(video_source_stop_lock_);
+ video_source_ = nullptr;
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
+ scoped_refptr<media::VideoFrame> frame,
+ base::TimeTicks estimated_capture_time) {
+ DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+ render_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoSourceAdapter::ResetRefreshTimerOnMainThread,
+ this));
+ libjingle_worker_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
+ this, std::move(frame)));
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+ OnVideoFrameOnWorkerThread(scoped_refptr<media::VideoFrame> frame) {
+ DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
+ base::AutoLock auto_lock(video_source_stop_lock_);
+ if (video_source_)
+ video_source_->OnFrameCaptured(std::move(frame));
+}
+
+MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
+ const WebMediaStreamTrack& track,
+ PeerConnectionDependencyFactory* factory,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ MediaStreamVideoTrack* video_track =
+ MediaStreamVideoTrack::GetVideoTrack(track);
+ DCHECK(video_track);
+
+ absl::optional<bool> needs_denoising =
+ ToAbslOptionalBool(video_track->noise_reduction());
+
+ bool is_screencast = video_track->is_screencast();
+ base::Optional<double> min_frame_rate = video_track->min_frame_rate();
+ base::Optional<double> max_frame_rate = video_track->max_frame_rate();
+
+ // Enable automatic frame refreshes for the screen capture sources, which will
+ // stop producing frames whenever screen content is not changing. Check the
+ // frameRate constraint to determine the rate of refreshes. If a minimum
+ // frameRate is provided, use that. Otherwise, use the maximum frameRate if it
+ // happens to be less than the default.
+ base::TimeDelta refresh_interval = base::TimeDelta::FromMicroseconds(0);
+ if (is_screencast) {
+ // Start with the default refresh interval, and refine based on constraints.
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(kDefaultRefreshIntervalMicros);
+ if (min_frame_rate.has_value()) {
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
+ base::Time::kMicrosecondsPerSecond / *min_frame_rate));
+ }
+ if (max_frame_rate.has_value()) {
+ const base::TimeDelta alternate_refresh_interval =
+ base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
+ base::Time::kMicrosecondsPerSecond / *max_frame_rate));
+ refresh_interval = std::max(refresh_interval, alternate_refresh_interval);
+ }
+ if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) {
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros);
+ }
+ }
+
+ // TODO(pbos): Consolidate WebRtcVideoCapturerAdapter into WebRtcVideoSource
+ // by removing the need for and dependency on a cricket::VideoCapturer.
+ video_source_ = scoped_refptr<WebRtcVideoTrackSource>(
+ new rtc::RefCountedObject<WebRtcVideoTrackSource>(is_screencast,
+ needs_denoising));
+
+ // TODO(pbos): Consolidate the local video track with the source proxy and
+ // move into PeerConnectionDependencyFactory. This now separately holds on a
+ // reference to the proxy object because
+ // PeerConnectionFactory::CreateVideoTrack doesn't do reference counting.
+ video_source_proxy_ =
+ factory->CreateVideoTrackSourceProxy(video_source_.get());
+ video_track_ = factory->CreateLocalVideoTrack(track.Id().Utf8(),
+ video_source_proxy_.get());
+
+ video_track_->set_content_hint(
+ ContentHintTypeToWebRtcContentHint(track.ContentHint()));
+ video_track_->set_enabled(track.IsEnabled());
+
+ source_adapter_ = base::MakeRefCounted<WebRtcVideoSourceAdapter>(
+ factory->GetWebRtcWorkerThread(), video_source_.get(), refresh_interval,
+ base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame,
+ weak_factory_.GetWeakPtr()),
+ std::move(task_runner));
+
+ MediaStreamVideoSink::ConnectToTrack(
+ track,
+ base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_),
+ false);
+
+ DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast "
+ << is_screencast;
+}
+
+MediaStreamVideoWebRtcSink::~MediaStreamVideoWebRtcSink() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DVLOG(3) << "MediaStreamVideoWebRtcSink dtor().";
+ weak_factory_.InvalidateWeakPtrs();
+ MediaStreamVideoSink::DisconnectFromTrack();
+ source_adapter_->ReleaseSourceOnMainThread();
+}
+
+void MediaStreamVideoWebRtcSink::OnEnabledChanged(bool enabled) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ video_track_->set_enabled(enabled);
+}
+
+void MediaStreamVideoWebRtcSink::OnContentHintChanged(
+ WebMediaStreamTrack::ContentHintType content_hint) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ video_track_->set_content_hint(
+ ContentHintTypeToWebRtcContentHint(content_hint));
+}
+
+void MediaStreamVideoWebRtcSink::RequestRefreshFrame() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ RequestRefreshFrameFromVideoTrack(connected_track());
+}
+
+absl::optional<bool>
+MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() const {
+ return video_source_->needs_denoising();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
new file mode 100644
index 00000000000..9e3d3bdf7f1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
@@ -0,0 +1,59 @@
+// 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/web/modules/peerconnection/media_stream_video_webrtc_sink.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/mock_media_stream_registry.h"
+#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+namespace blink {
+
+class MediaStreamVideoWebRtcSinkTest : public ::testing::Test {
+ public:
+ void SetVideoTrack() {
+ registry_.Init();
+ registry_.AddVideoTrack("test video track");
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
+ registry_.test_stream().VideoTracks();
+ track_ = video_tracks[0];
+ // TODO(hta): Verify that track_ is valid. When constraints produce
+ // no valid format, using the track will cause a crash.
+ }
+
+ void SetVideoTrack(const base::Optional<bool>& noise_reduction) {
+ registry_.Init();
+ registry_.AddVideoTrack("test video track",
+ blink::VideoTrackAdapterSettings(), noise_reduction,
+ false, 0.0);
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
+ registry_.test_stream().VideoTracks();
+ track_ = video_tracks[0];
+ // TODO(hta): Verify that track_ is valid. When constraints produce
+ // no valid format, using the track will cause a crash.
+ }
+
+ protected:
+ blink::WebMediaStreamTrack track_;
+ blink::MockPeerConnectionDependencyFactory dependency_factory_;
+
+ private:
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ blink::MockMediaStreamRegistry registry_;
+};
+
+TEST_F(MediaStreamVideoWebRtcSinkTest, NoiseReductionDefaultsToNotSet) {
+ SetVideoTrack();
+ blink::MediaStreamVideoWebRtcSink my_sink(
+ track_, &dependency_factory_,
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+ EXPECT_TRUE(my_sink.webrtc_video_track());
+ EXPECT_FALSE(my_sink.SourceNeedsDenoisingForTesting());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/mock_data_channel_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/mock_data_channel_impl.cc
new file mode 100644
index 00000000000..45ccb313a70
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/mock_data_channel_impl.cc
@@ -0,0 +1,98 @@
+// 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/web/modules/peerconnection/mock_data_channel_impl.h"
+
+#include "base/logging.h"
+
+namespace blink {
+
+MockDataChannel::MockDataChannel(const std::string& label,
+ const webrtc::DataChannelInit* config)
+ : label_(label),
+ reliable_(config->reliable),
+ state_(webrtc::DataChannelInterface::kConnecting),
+ config_(*config),
+ observer_(nullptr) {}
+
+MockDataChannel::~MockDataChannel() {}
+
+void MockDataChannel::RegisterObserver(webrtc::DataChannelObserver* observer) {
+ observer_ = observer;
+}
+
+void MockDataChannel::UnregisterObserver() {
+ observer_ = nullptr;
+}
+
+std::string MockDataChannel::label() const {
+ return label_;
+}
+
+bool MockDataChannel::reliable() const {
+ return reliable_;
+}
+
+bool MockDataChannel::ordered() const {
+ return config_.ordered;
+}
+
+std::string MockDataChannel::protocol() const {
+ return config_.protocol;
+}
+
+bool MockDataChannel::negotiated() const {
+ return config_.negotiated;
+}
+
+int MockDataChannel::id() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+MockDataChannel::DataState MockDataChannel::state() const {
+ return state_;
+}
+
+uint32_t MockDataChannel::messages_sent() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+uint64_t MockDataChannel::bytes_sent() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+uint32_t MockDataChannel::messages_received() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+uint64_t MockDataChannel::bytes_received() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+// For testing.
+void MockDataChannel::changeState(DataState state) {
+ state_ = state;
+ if (observer_)
+ observer_->OnStateChange();
+}
+
+uint64_t MockDataChannel::buffered_amount() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+void MockDataChannel::Close() {
+ changeState(webrtc::DataChannelInterface::kClosing);
+}
+
+bool MockDataChannel::Send(const webrtc::DataBuffer& buffer) {
+ return state_ == webrtc::DataChannelInterface::kOpen;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc b/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
new file mode 100644
index 00000000000..61cfc6289cd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.cc
@@ -0,0 +1,391 @@
+// 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/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+
+#include <stddef.h>
+
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/webrtc/api/media_stream_interface.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+using webrtc::AudioSourceInterface;
+using webrtc::AudioTrackInterface;
+using webrtc::AudioTrackVector;
+using webrtc::IceCandidateCollection;
+using webrtc::IceCandidateInterface;
+using webrtc::MediaStreamInterface;
+using webrtc::ObserverInterface;
+using webrtc::SessionDescriptionInterface;
+using webrtc::VideoTrackInterface;
+using webrtc::VideoTrackSourceInterface;
+using webrtc::VideoTrackVector;
+
+namespace blink {
+
+template <class V>
+static typename V::iterator FindTrack(V* vector, const std::string& track_id) {
+ auto it = vector->begin();
+ for (; it != vector->end(); ++it) {
+ if ((*it)->id() == track_id) {
+ break;
+ }
+ }
+ return it;
+}
+
+MockWebRtcAudioSource::MockWebRtcAudioSource(bool is_remote)
+ : is_remote_(is_remote) {}
+void MockWebRtcAudioSource::RegisterObserver(ObserverInterface* observer) {}
+void MockWebRtcAudioSource::UnregisterObserver(ObserverInterface* observer) {}
+
+MockWebRtcAudioSource::SourceState MockWebRtcAudioSource::state() const {
+ return SourceState::kLive;
+}
+
+bool MockWebRtcAudioSource::remote() const {
+ return is_remote_;
+}
+
+MockMediaStream::MockMediaStream(const std::string& id) : id_(id) {}
+
+bool MockMediaStream::AddTrack(AudioTrackInterface* track) {
+ audio_track_vector_.push_back(track);
+ NotifyObservers();
+ return true;
+}
+
+bool MockMediaStream::AddTrack(VideoTrackInterface* track) {
+ video_track_vector_.push_back(track);
+ NotifyObservers();
+ return true;
+}
+
+bool MockMediaStream::RemoveTrack(AudioTrackInterface* track) {
+ auto it = FindTrack(&audio_track_vector_, track->id());
+ if (it == audio_track_vector_.end())
+ return false;
+ audio_track_vector_.erase(it);
+ NotifyObservers();
+ return true;
+}
+
+bool MockMediaStream::RemoveTrack(VideoTrackInterface* track) {
+ auto it = FindTrack(&video_track_vector_, track->id());
+ if (it == video_track_vector_.end())
+ return false;
+ video_track_vector_.erase(it);
+ NotifyObservers();
+ return true;
+}
+
+std::string MockMediaStream::id() const {
+ return id_;
+}
+
+AudioTrackVector MockMediaStream::GetAudioTracks() {
+ return audio_track_vector_;
+}
+
+VideoTrackVector MockMediaStream::GetVideoTracks() {
+ return video_track_vector_;
+}
+
+rtc::scoped_refptr<AudioTrackInterface> MockMediaStream::FindAudioTrack(
+ const std::string& track_id) {
+ auto it = FindTrack(&audio_track_vector_, track_id);
+ return it == audio_track_vector_.end() ? nullptr : *it;
+}
+
+rtc::scoped_refptr<VideoTrackInterface> MockMediaStream::FindVideoTrack(
+ const std::string& track_id) {
+ auto it = FindTrack(&video_track_vector_, track_id);
+ return it == video_track_vector_.end() ? nullptr : *it;
+}
+
+void MockMediaStream::RegisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
+}
+
+void MockMediaStream::UnregisterObserver(ObserverInterface* observer) {
+ auto it = observers_.find(observer);
+ DCHECK(it != observers_.end());
+ observers_.erase(it);
+}
+
+void MockMediaStream::NotifyObservers() {
+ for (auto it = observers_.begin(); it != observers_.end(); ++it) {
+ (*it)->OnChanged();
+ }
+}
+
+MockMediaStream::~MockMediaStream() {}
+
+scoped_refptr<MockWebRtcAudioTrack> MockWebRtcAudioTrack::Create(
+ const std::string& id) {
+ return new rtc::RefCountedObject<MockWebRtcAudioTrack>(id);
+}
+
+MockWebRtcAudioTrack::MockWebRtcAudioTrack(const std::string& id)
+ : id_(id),
+ source_(new rtc::RefCountedObject<MockWebRtcAudioSource>(true)),
+ enabled_(true),
+ state_(webrtc::MediaStreamTrackInterface::kLive) {}
+
+MockWebRtcAudioTrack::~MockWebRtcAudioTrack() {}
+
+std::string MockWebRtcAudioTrack::kind() const {
+ return kAudioKind;
+}
+
+webrtc::AudioSourceInterface* MockWebRtcAudioTrack::GetSource() const {
+ return source_.get();
+}
+
+std::string MockWebRtcAudioTrack::id() const {
+ return id_;
+}
+
+bool MockWebRtcAudioTrack::enabled() const {
+ return enabled_;
+}
+
+MockWebRtcVideoTrack::TrackState MockWebRtcAudioTrack::state() const {
+ return state_;
+}
+
+bool MockWebRtcAudioTrack::set_enabled(bool enable) {
+ enabled_ = enable;
+ return true;
+}
+
+void MockWebRtcAudioTrack::RegisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
+}
+
+void MockWebRtcAudioTrack::UnregisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) != observers_.end());
+ observers_.erase(observer);
+}
+
+void MockWebRtcAudioTrack::SetEnded() {
+ DCHECK_EQ(webrtc::MediaStreamTrackInterface::kLive, state_);
+ state_ = webrtc::MediaStreamTrackInterface::kEnded;
+ for (auto* o : observers_)
+ o->OnChanged();
+}
+
+MockWebRtcVideoTrack::MockWebRtcVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source)
+ : id_(id),
+ source_(source),
+ enabled_(true),
+ state_(webrtc::MediaStreamTrackInterface::kLive),
+ sink_(nullptr) {}
+
+MockWebRtcVideoTrack::~MockWebRtcVideoTrack() {}
+
+scoped_refptr<MockWebRtcVideoTrack> MockWebRtcVideoTrack::Create(
+ const std::string& id) {
+ return new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, nullptr);
+}
+
+void MockWebRtcVideoTrack::AddOrUpdateSink(
+ rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ DCHECK(!sink_);
+ sink_ = sink;
+}
+
+void MockWebRtcVideoTrack::RemoveSink(
+ rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) {
+ DCHECK(sink_ == sink);
+ sink_ = nullptr;
+}
+
+VideoTrackSourceInterface* MockWebRtcVideoTrack::GetSource() const {
+ return source_.get();
+}
+
+std::string MockWebRtcVideoTrack::kind() const {
+ return kVideoKind;
+}
+
+std::string MockWebRtcVideoTrack::id() const {
+ return id_;
+}
+
+bool MockWebRtcVideoTrack::enabled() const {
+ return enabled_;
+}
+
+MockWebRtcVideoTrack::TrackState MockWebRtcVideoTrack::state() const {
+ return state_;
+}
+
+bool MockWebRtcVideoTrack::set_enabled(bool enable) {
+ enabled_ = enable;
+ return true;
+}
+
+void MockWebRtcVideoTrack::RegisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
+}
+
+void MockWebRtcVideoTrack::UnregisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) != observers_.end());
+ observers_.erase(observer);
+}
+
+void MockWebRtcVideoTrack::SetEnded() {
+ DCHECK_EQ(webrtc::MediaStreamTrackInterface::kLive, state_);
+ state_ = webrtc::MediaStreamTrackInterface::kEnded;
+ for (auto* o : observers_)
+ o->OnChanged();
+}
+
+class MockSessionDescription : public SessionDescriptionInterface {
+ public:
+ MockSessionDescription(const std::string& type, const std::string& sdp)
+ : type_(type), sdp_(sdp) {}
+ ~MockSessionDescription() override {}
+ cricket::SessionDescription* description() override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ const cricket::SessionDescription* description() const override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ std::string session_id() const override {
+ NOTIMPLEMENTED();
+ return std::string();
+ }
+ std::string session_version() const override {
+ NOTIMPLEMENTED();
+ return std::string();
+ }
+ std::string type() const override { return type_; }
+ bool AddCandidate(const IceCandidateInterface* candidate) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+ size_t number_of_mediasections() const override {
+ NOTIMPLEMENTED();
+ return 0;
+ }
+ const IceCandidateCollection* candidates(
+ size_t mediasection_index) const override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ bool ToString(std::string* out) const override {
+ *out = sdp_;
+ return true;
+ }
+
+ private:
+ std::string type_;
+ std::string sdp_;
+};
+
+class MockIceCandidate : public IceCandidateInterface {
+ public:
+ MockIceCandidate(const std::string& sdp_mid,
+ int sdp_mline_index,
+ const std::string& sdp)
+ : sdp_mid_(sdp_mid), sdp_mline_index_(sdp_mline_index), sdp_(sdp) {
+ // Assign an valid address to |candidate_| to pass assert in code.
+ candidate_.set_address(rtc::SocketAddress("127.0.0.1", 5000));
+ }
+ ~MockIceCandidate() override {}
+ std::string sdp_mid() const override { return sdp_mid_; }
+ int sdp_mline_index() const override { return sdp_mline_index_; }
+ const cricket::Candidate& candidate() const override { return candidate_; }
+ bool ToString(std::string* out) const override {
+ *out = sdp_;
+ return true;
+ }
+
+ private:
+ std::string sdp_mid_;
+ int sdp_mline_index_;
+ std::string sdp_;
+ cricket::Candidate candidate_;
+};
+
+MockPeerConnectionDependencyFactory::MockPeerConnectionDependencyFactory()
+ : blink::PeerConnectionDependencyFactory(
+ /*create_p2p_socket_dispatcher =*/false),
+ signaling_thread_("MockPCFactory WebRtc Signaling Thread") {
+ EnsureWebRtcAudioDeviceImpl();
+ CHECK(signaling_thread_.Start());
+}
+
+MockPeerConnectionDependencyFactory::~MockPeerConnectionDependencyFactory() {}
+
+scoped_refptr<webrtc::PeerConnectionInterface>
+MockPeerConnectionDependencyFactory::CreatePeerConnection(
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
+ blink::WebLocalFrame* frame,
+ webrtc::PeerConnectionObserver* observer) {
+ return new rtc::RefCountedObject<MockPeerConnectionImpl>(this, observer);
+}
+
+scoped_refptr<webrtc::VideoTrackSourceInterface>
+MockPeerConnectionDependencyFactory::CreateVideoTrackSourceProxy(
+ webrtc::VideoTrackSourceInterface* source) {
+ return nullptr;
+}
+scoped_refptr<webrtc::MediaStreamInterface>
+MockPeerConnectionDependencyFactory::CreateLocalMediaStream(
+ const std::string& label) {
+ return new rtc::RefCountedObject<MockMediaStream>(label);
+}
+
+scoped_refptr<webrtc::VideoTrackInterface>
+MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source) {
+ scoped_refptr<webrtc::VideoTrackInterface> track(
+ new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, source));
+ return track;
+}
+
+SessionDescriptionInterface*
+MockPeerConnectionDependencyFactory::CreateSessionDescription(
+ const std::string& type,
+ const std::string& sdp,
+ webrtc::SdpParseError* error) {
+ if (fail_to_create_session_description_)
+ return nullptr;
+ return new MockSessionDescription(type, sdp);
+}
+
+webrtc::IceCandidateInterface*
+MockPeerConnectionDependencyFactory::CreateIceCandidate(
+ const std::string& sdp_mid,
+ int sdp_mline_index,
+ const std::string& sdp) {
+ return new MockIceCandidate(sdp_mid, sdp_mline_index, sdp);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+MockPeerConnectionDependencyFactory::GetWebRtcSignalingTaskRunner() {
+ return signaling_thread_.task_runner();
+}
+
+void MockPeerConnectionDependencyFactory::SetFailToCreateSessionDescription(
+ bool fail) {
+ fail_to_create_session_description_ = fail;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc
new file mode 100644
index 00000000000..ad7a995d010
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc
@@ -0,0 +1,532 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+
+#include <stddef.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_data_channel_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/webrtc/api/rtp_receiver_interface.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+
+using testing::_;
+using webrtc::AudioTrackInterface;
+using webrtc::CreateSessionDescriptionObserver;
+using webrtc::DtmfSenderInterface;
+using webrtc::DtmfSenderObserverInterface;
+using webrtc::IceCandidateInterface;
+using webrtc::MediaStreamInterface;
+using webrtc::PeerConnectionInterface;
+using webrtc::SessionDescriptionInterface;
+using webrtc::SetSessionDescriptionObserver;
+
+namespace blink {
+
+class MockStreamCollection : public webrtc::StreamCollectionInterface {
+ public:
+ size_t count() override { return streams_.size(); }
+ MediaStreamInterface* at(size_t index) override { return streams_[index]; }
+ MediaStreamInterface* find(const std::string& id) override {
+ for (size_t i = 0; i < streams_.size(); ++i) {
+ if (streams_[i]->id() == id)
+ return streams_[i];
+ }
+ return nullptr;
+ }
+ webrtc::MediaStreamTrackInterface* FindAudioTrack(
+ const std::string& id) override {
+ for (size_t i = 0; i < streams_.size(); ++i) {
+ webrtc::MediaStreamTrackInterface* track =
+ streams_.at(i)->FindAudioTrack(id);
+ if (track)
+ return track;
+ }
+ return nullptr;
+ }
+ webrtc::MediaStreamTrackInterface* FindVideoTrack(
+ const std::string& id) override {
+ for (size_t i = 0; i < streams_.size(); ++i) {
+ webrtc::MediaStreamTrackInterface* track =
+ streams_.at(i)->FindVideoTrack(id);
+ if (track)
+ return track;
+ }
+ return nullptr;
+ }
+ void AddStream(MediaStreamInterface* stream) { streams_.push_back(stream); }
+ void RemoveStream(MediaStreamInterface* stream) {
+ auto it = streams_.begin();
+ for (; it != streams_.end(); ++it) {
+ if (it->get() == stream) {
+ streams_.erase(it);
+ break;
+ }
+ }
+ }
+
+ protected:
+ ~MockStreamCollection() override {}
+
+ private:
+ typedef std::vector<rtc::scoped_refptr<MediaStreamInterface>> StreamVector;
+ StreamVector streams_;
+};
+
+class MockDtmfSender : public DtmfSenderInterface {
+ public:
+ void RegisterObserver(DtmfSenderObserverInterface* observer) override {
+ observer_ = observer;
+ }
+ void UnregisterObserver() override { observer_ = nullptr; }
+ bool CanInsertDtmf() override { return true; }
+ bool InsertDtmf(const std::string& tones,
+ int duration,
+ int inter_tone_gap) override {
+ tones_ = tones;
+ duration_ = duration;
+ inter_tone_gap_ = inter_tone_gap;
+ return true;
+ }
+ std::string tones() const override { return tones_; }
+ int duration() const override { return duration_; }
+ int inter_tone_gap() const override { return inter_tone_gap_; }
+
+ private:
+ DtmfSenderObserverInterface* observer_ = nullptr;
+ std::string tones_;
+ int duration_ = 0;
+ int inter_tone_gap_ = 0;
+};
+
+FakeRtpSender::FakeRtpSender(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ std::vector<std::string> stream_ids)
+ : track_(std::move(track)), stream_ids_(std::move(stream_ids)) {}
+
+FakeRtpSender::~FakeRtpSender() {}
+
+bool FakeRtpSender::SetTrack(webrtc::MediaStreamTrackInterface* track) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> FakeRtpSender::track()
+ const {
+ return track_;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+FakeRtpSender::dtls_transport() const {
+ return transport_;
+}
+
+uint32_t FakeRtpSender::ssrc() const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+cricket::MediaType FakeRtpSender::media_type() const {
+ NOTIMPLEMENTED();
+ return cricket::MEDIA_TYPE_AUDIO;
+}
+
+std::string FakeRtpSender::id() const {
+ NOTIMPLEMENTED();
+ return "";
+}
+
+std::vector<std::string> FakeRtpSender::stream_ids() const {
+ return stream_ids_;
+}
+
+std::vector<webrtc::RtpEncodingParameters> FakeRtpSender::init_send_encodings()
+ const {
+ return {};
+}
+
+webrtc::RtpParameters FakeRtpSender::GetParameters() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpParameters();
+}
+
+webrtc::RTCError FakeRtpSender::SetParameters(
+ const webrtc::RtpParameters& parameters) {
+ NOTIMPLEMENTED();
+ return webrtc::RTCError::OK();
+}
+
+rtc::scoped_refptr<webrtc::DtmfSenderInterface> FakeRtpSender::GetDtmfSender()
+ const {
+ return new rtc::RefCountedObject<MockDtmfSender>();
+}
+
+FakeRtpReceiver::FakeRtpReceiver(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams)
+ : track_(std::move(track)), streams_(std::move(streams)) {}
+
+FakeRtpReceiver::~FakeRtpReceiver() {}
+
+rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> FakeRtpReceiver::track()
+ const {
+ return track_;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+FakeRtpReceiver::dtls_transport() const {
+ return transport_;
+}
+
+std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>
+FakeRtpReceiver::streams() const {
+ return streams_;
+}
+
+std::vector<std::string> FakeRtpReceiver::stream_ids() const {
+ std::vector<std::string> stream_ids;
+ for (const auto& stream : streams_)
+ stream_ids.push_back(stream->id());
+ return stream_ids;
+}
+
+cricket::MediaType FakeRtpReceiver::media_type() const {
+ NOTIMPLEMENTED();
+ return cricket::MEDIA_TYPE_AUDIO;
+}
+
+std::string FakeRtpReceiver::id() const {
+ NOTIMPLEMENTED();
+ return "";
+}
+
+webrtc::RtpParameters FakeRtpReceiver::GetParameters() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpParameters();
+}
+
+bool FakeRtpReceiver::SetParameters(const webrtc::RtpParameters& parameters) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void FakeRtpReceiver::SetObserver(
+ webrtc::RtpReceiverObserverInterface* observer) {
+ NOTIMPLEMENTED();
+}
+
+void FakeRtpReceiver::SetJitterBufferMinimumDelay(
+ absl::optional<double> delay_seconds) {
+ NOTIMPLEMENTED();
+}
+
+std::vector<webrtc::RtpSource> FakeRtpReceiver::GetSources() const {
+ NOTIMPLEMENTED();
+ return std::vector<webrtc::RtpSource>();
+}
+
+FakeRtpTransceiver::FakeRtpTransceiver(
+ cricket::MediaType media_type,
+ rtc::scoped_refptr<FakeRtpSender> sender,
+ rtc::scoped_refptr<FakeRtpReceiver> receiver,
+ base::Optional<std::string> mid,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction)
+ : media_type_(media_type),
+ sender_(std::move(sender)),
+ receiver_(std::move(receiver)),
+ mid_(blink::ToAbslOptional(std::move(mid))),
+ stopped_(stopped),
+ direction_(direction),
+ current_direction_(blink::ToAbslOptional(current_direction)) {}
+
+FakeRtpTransceiver::~FakeRtpTransceiver() {}
+
+cricket::MediaType FakeRtpTransceiver::media_type() const {
+ return media_type_;
+}
+
+absl::optional<std::string> FakeRtpTransceiver::mid() const {
+ return mid_;
+}
+
+rtc::scoped_refptr<webrtc::RtpSenderInterface> FakeRtpTransceiver::sender()
+ const {
+ return sender_;
+}
+
+rtc::scoped_refptr<webrtc::RtpReceiverInterface> FakeRtpTransceiver::receiver()
+ const {
+ return receiver_;
+}
+
+bool FakeRtpTransceiver::stopped() const {
+ return stopped_;
+}
+
+webrtc::RtpTransceiverDirection FakeRtpTransceiver::direction() const {
+ return direction_;
+}
+
+void FakeRtpTransceiver::SetDirection(
+ webrtc::RtpTransceiverDirection new_direction) {
+ NOTIMPLEMENTED();
+}
+
+absl::optional<webrtc::RtpTransceiverDirection>
+FakeRtpTransceiver::current_direction() const {
+ return current_direction_;
+}
+
+void FakeRtpTransceiver::Stop() {
+ NOTIMPLEMENTED();
+}
+
+void FakeRtpTransceiver::SetTransport(
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
+ sender_->SetTransport(transport);
+ receiver_->SetTransport(transport);
+}
+
+FakeDtlsTransport::FakeDtlsTransport() {}
+
+rtc::scoped_refptr<webrtc::IceTransportInterface>
+FakeDtlsTransport::ice_transport() {
+ return nullptr;
+}
+
+webrtc::DtlsTransportInformation FakeDtlsTransport::Information() {
+ return webrtc::DtlsTransportInformation(webrtc::DtlsTransportState::kNew);
+}
+
+const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
+const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";
+
+MockPeerConnectionImpl::MockPeerConnectionImpl(
+ MockPeerConnectionDependencyFactory* factory,
+ webrtc::PeerConnectionObserver* observer)
+ : dependency_factory_(factory),
+ remote_streams_(new rtc::RefCountedObject<MockStreamCollection>),
+ hint_audio_(false),
+ hint_video_(false),
+ getstats_result_(true),
+ sdp_mline_index_(-1),
+ observer_(observer) {
+ ON_CALL(*this, SetLocalDescription(_, _))
+ .WillByDefault(testing::Invoke(
+ this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
+ // TODO(hbos): Remove once no longer mandatory to implement.
+ ON_CALL(*this, SetRemoteDescription(_, _))
+ .WillByDefault(testing::Invoke(
+ this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
+ ON_CALL(*this, SetRemoteDescriptionForMock(_, _))
+ .WillByDefault(testing::Invoke(
+ [this](
+ std::unique_ptr<webrtc::SessionDescriptionInterface>* desc,
+ rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>*
+ observer) {
+ SetRemoteDescriptionWorker(nullptr, desc->release());
+ }));
+}
+
+MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
+
+webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>
+MockPeerConnectionImpl::AddTrack(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::vector<std::string>& stream_ids) {
+ DCHECK(track);
+ DCHECK_EQ(1u, stream_ids.size());
+ for (const auto& sender : senders_) {
+ if (sender->track() == track)
+ return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER);
+ }
+ for (const auto& stream_id : stream_ids) {
+ if (!base::Contains(local_stream_ids_, stream_id)) {
+ stream_label_ = stream_id;
+ local_stream_ids_.push_back(stream_id);
+ }
+ }
+ auto* sender = new rtc::RefCountedObject<FakeRtpSender>(track, stream_ids);
+ senders_.push_back(sender);
+ return rtc::scoped_refptr<webrtc::RtpSenderInterface>(sender);
+}
+
+bool MockPeerConnectionImpl::RemoveTrack(webrtc::RtpSenderInterface* s) {
+ rtc::scoped_refptr<FakeRtpSender> sender = static_cast<FakeRtpSender*>(s);
+ auto it = std::find(senders_.begin(), senders_.end(), sender);
+ if (it == senders_.end())
+ return false;
+ senders_.erase(it);
+ auto track = sender->track();
+
+ for (const auto& stream_id : sender->stream_ids()) {
+ auto local_stream_it = std::find(local_stream_ids_.begin(),
+ local_stream_ids_.end(), stream_id);
+ if (local_stream_it != local_stream_ids_.end())
+ local_stream_ids_.erase(local_stream_it);
+ }
+ return true;
+}
+
+std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>>
+MockPeerConnectionImpl::GetSenders() const {
+ std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> senders;
+ for (const auto& sender : senders_)
+ senders.push_back(sender);
+ return senders;
+}
+
+std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>>
+MockPeerConnectionImpl::GetReceivers() const {
+ std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers;
+ for (size_t i = 0; i < remote_streams_->count(); ++i) {
+ for (const auto& audio_track : remote_streams_->at(i)->GetAudioTracks()) {
+ receivers.push_back(
+ new rtc::RefCountedObject<FakeRtpReceiver>(audio_track));
+ }
+ for (const auto& video_track : remote_streams_->at(i)->GetVideoTracks()) {
+ receivers.push_back(
+ new rtc::RefCountedObject<FakeRtpReceiver>(video_track));
+ }
+ }
+ return receivers;
+}
+
+rtc::scoped_refptr<webrtc::DataChannelInterface>
+MockPeerConnectionImpl::CreateDataChannel(
+ const std::string& label,
+ const webrtc::DataChannelInit* config) {
+ return new rtc::RefCountedObject<blink::MockDataChannel>(label, config);
+}
+
+bool MockPeerConnectionImpl::GetStats(webrtc::StatsObserver* observer,
+ webrtc::MediaStreamTrackInterface* track,
+ StatsOutputLevel level) {
+ if (!getstats_result_)
+ return false;
+
+ DCHECK_EQ(kStatsOutputLevelStandard, level);
+ webrtc::StatsReport report1(webrtc::StatsReport::NewTypedId(
+ webrtc::StatsReport::kStatsReportTypeSsrc, "1234"));
+ webrtc::StatsReport report2(webrtc::StatsReport::NewTypedId(
+ webrtc::StatsReport::kStatsReportTypeSession, "nontrack"));
+ report1.set_timestamp(42);
+ report1.AddString(webrtc::StatsReport::kStatsValueNameFingerprint,
+ "trackvalue");
+
+ webrtc::StatsReports reports;
+ reports.push_back(&report1);
+
+ // If selector is given, we pass back one report.
+ // If selector is not given, we pass back two.
+ if (!track) {
+ report2.set_timestamp(44);
+ report2.AddString(webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
+ "somevalue");
+ reports.push_back(&report2);
+ }
+
+ // Note that the callback is synchronous, not asynchronous; it will
+ // happen before the request call completes.
+ observer->OnComplete(reports);
+
+ return true;
+}
+
+void MockPeerConnectionImpl::GetStats(
+ webrtc::RTCStatsCollectorCallback* callback) {
+ DCHECK(callback);
+ DCHECK(stats_report_);
+ callback->OnStatsDelivered(stats_report_);
+}
+
+void MockPeerConnectionImpl::GetStats(
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> selector,
+ rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback> callback) {
+ callback->OnStatsDelivered(stats_report_);
+}
+
+void MockPeerConnectionImpl::GetStats(
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> selector,
+ rtc::scoped_refptr<webrtc::RTCStatsCollectorCallback> callback) {
+ callback->OnStatsDelivered(stats_report_);
+}
+
+void MockPeerConnectionImpl::SetGetStatsReport(webrtc::RTCStatsReport* report) {
+ stats_report_ = report;
+}
+
+const webrtc::SessionDescriptionInterface*
+MockPeerConnectionImpl::local_description() const {
+ return local_desc_.get();
+}
+
+const webrtc::SessionDescriptionInterface*
+MockPeerConnectionImpl::remote_description() const {
+ return remote_desc_.get();
+}
+
+void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
+ remote_streams_->AddStream(stream);
+}
+
+void MockPeerConnectionImpl::CreateOffer(
+ CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) {
+ DCHECK(observer);
+ created_sessiondescription_.reset(
+ dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
+ nullptr));
+}
+
+void MockPeerConnectionImpl::CreateAnswer(
+ CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) {
+ DCHECK(observer);
+ created_sessiondescription_.reset(
+ dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
+ nullptr));
+}
+
+void MockPeerConnectionImpl::SetLocalDescriptionWorker(
+ SetSessionDescriptionObserver* observer,
+ SessionDescriptionInterface* desc) {
+ desc->ToString(&description_sdp_);
+ local_desc_.reset(desc);
+}
+
+void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
+ SetSessionDescriptionObserver* observer,
+ SessionDescriptionInterface* desc) {
+ desc->ToString(&description_sdp_);
+ remote_desc_.reset(desc);
+}
+
+webrtc::RTCError MockPeerConnectionImpl::SetConfiguration(
+ const RTCConfiguration& configuration) {
+ return webrtc::RTCError(setconfiguration_error_type_);
+}
+
+bool MockPeerConnectionImpl::AddIceCandidate(
+ const IceCandidateInterface* candidate) {
+ sdp_mid_ = candidate->sdp_mid();
+ sdp_mline_index_ = candidate->sdp_mline_index();
+ return candidate->ToString(&ice_sdp_);
+}
+
+webrtc::RTCError MockPeerConnectionImpl::SetBitrate(
+ const webrtc::BitrateSettings& bitrate) {
+ NOTIMPLEMENTED();
+ return webrtc::RTCError::OK();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.cc b/chromium/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.cc
new file mode 100644
index 00000000000..81cfc282750
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "third_party/blink/public/web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h"
+
+#include "base/logging.h"
+#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+using testing::_;
+
+namespace blink {
+
+MockWebRTCPeerConnectionHandlerClient::MockWebRTCPeerConnectionHandlerClient() {
+ ON_CALL(*this, DidGenerateICECandidate(_))
+ .WillByDefault(
+ testing::Invoke(this, &MockWebRTCPeerConnectionHandlerClient::
+ didGenerateICECandidateWorker));
+ ON_CALL(*this, DidAddReceiverPlanBForMock(_))
+ .WillByDefault(testing::Invoke(
+ this, &MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker));
+ ON_CALL(*this, DidRemoveReceiverPlanBForMock(_))
+ .WillByDefault(testing::Invoke(
+ this,
+ &MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker));
+}
+
+MockWebRTCPeerConnectionHandlerClient::
+ ~MockWebRTCPeerConnectionHandlerClient() {}
+
+void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker(
+ scoped_refptr<blink::WebRTCICECandidate> candidate) {
+ candidate_sdp_ = candidate->Candidate().Utf8();
+ candidate_mline_index_ = candidate->SdpMLineIndex();
+ candidate_mid_ = candidate->SdpMid().Utf8();
+}
+
+void MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker(
+ std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) {
+ blink::WebVector<blink::WebString> stream_ids =
+ (*web_rtp_receiver)->StreamIds();
+ DCHECK_EQ(1u, stream_ids.size());
+ remote_stream_id_ = stream_ids[0];
+}
+
+void MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker(
+ std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) {
+ remote_stream_id_ = blink::WebString();
+}
+
+} // 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
new file mode 100644
index 00000000000..6629b036989
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -0,0 +1,652 @@
+// 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/web/modules/peerconnection/peer_connection_dependency_factory.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/synchronization/waitable_event.h"
+#include "build/build_config.h"
+#include "crypto/openssl_util.h"
+#include "jingle/glue/thread_wrapper.h"
+#include "media/base/media_permission.h"
+#include "media/media_buildflags.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/peerconnection/webrtc_ip_handling_policy.h"
+#include "third_party/blink/public/platform/modules/peerconnection/audio_codec_factory.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_media_constraints.h"
+#include "third_party/blink/public/platform/web_media_stream.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/webrtc/webrtc_audio_device_impl.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/renderer/modules/p2p/port_allocator.h"
+#include "third_party/blink/renderer/platform/p2p/empty_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/filtering_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/ipc_network_manager.h"
+#include "third_party/blink/renderer/platform/p2p/ipc_socket_factory.h"
+#include "third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h"
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/peerconnection/stun_field_trial.h"
+#include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.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/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"
+#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
+#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
+#include "third_party/webrtc/rtc_base/ref_counted_object.h"
+#include "third_party/webrtc/rtc_base/ssl_adapter.h"
+#include "third_party/webrtc_overrides/task_queue_factory.h"
+
+namespace blink {
+
+namespace {
+
+enum WebRTCIPHandlingPolicy {
+ DEFAULT,
+ DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES,
+ DEFAULT_PUBLIC_INTERFACE_ONLY,
+ DISABLE_NON_PROXIED_UDP,
+};
+
+WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy(
+ const std::string& preference) {
+ if (preference == blink::kWebRTCIPHandlingDefaultPublicAndPrivateInterfaces)
+ return DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES;
+ if (preference == blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly)
+ return DEFAULT_PUBLIC_INTERFACE_ONLY;
+ if (preference == blink::kWebRTCIPHandlingDisableNonProxiedUdp)
+ return DISABLE_NON_PROXIED_UDP;
+ return DEFAULT;
+}
+
+bool IsValidPortRange(uint16_t min_port, uint16_t max_port) {
+ DCHECK(min_port <= max_port);
+ return min_port != 0 && max_port != 0;
+}
+
+// PeerConnectionDependencies wants to own the factory, so we provide a simple
+// object that delegates calls to the IpcPacketSocketFactory.
+// TODO(zstein): Move the creation logic from IpcPacketSocketFactory in to this
+// class.
+class ProxyAsyncResolverFactory final : public webrtc::AsyncResolverFactory {
+ public:
+ ProxyAsyncResolverFactory(IpcPacketSocketFactory* ipc_psf)
+ : ipc_psf_(ipc_psf) {
+ DCHECK(ipc_psf);
+ }
+
+ rtc::AsyncResolverInterface* Create() override {
+ return ipc_psf_->CreateAsyncResolver();
+ }
+
+ private:
+ IpcPacketSocketFactory* ipc_psf_;
+};
+
+} // namespace
+
+PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
+ bool create_p2p_socket_dispatcher)
+ : network_manager_(nullptr),
+ p2p_socket_dispatcher_(
+ create_p2p_socket_dispatcher ? new P2PSocketDispatcher() : nullptr),
+ signaling_thread_(nullptr),
+ worker_thread_(nullptr),
+ chrome_signaling_thread_("Chrome_libJingle_Signaling"),
+ chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
+ TryScheduleStunProbeTrial();
+}
+
+PeerConnectionDependencyFactory::~PeerConnectionDependencyFactory() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DVLOG(1) << "~PeerConnectionDependencyFactory()";
+ DCHECK(!pc_factory_);
+}
+
+PeerConnectionDependencyFactory*
+PeerConnectionDependencyFactory::GetInstance() {
+ DEFINE_STATIC_LOCAL(PeerConnectionDependencyFactory, instance,
+ (/*create_p2p_socket_dispatcher= */ true));
+ return &instance;
+}
+
+std::unique_ptr<blink::WebRTCPeerConnectionHandler>
+PeerConnectionDependencyFactory::CreateRTCPeerConnectionHandler(
+ blink::WebRTCPeerConnectionHandlerClient* client,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ return blink::Platform::Current()->CreateRTCPeerConnectionHandler(
+ client, std::move(task_runner));
+}
+
+const scoped_refptr<webrtc::PeerConnectionFactoryInterface>&
+PeerConnectionDependencyFactory::GetPcFactory() {
+ if (!pc_factory_.get())
+ CreatePeerConnectionFactory();
+ CHECK(pc_factory_.get());
+ return pc_factory_;
+}
+
+void PeerConnectionDependencyFactory::WillDestroyCurrentMessageLoop() {
+ CleanupPeerConnectionFactory();
+}
+
+void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
+ DCHECK(!pc_factory_.get());
+ DCHECK(!signaling_thread_);
+ DCHECK(!worker_thread_);
+ DCHECK(!network_manager_);
+ DCHECK(!socket_factory_);
+ DCHECK(!chrome_signaling_thread_.IsRunning());
+ DCHECK(!chrome_worker_thread_.IsRunning());
+
+ DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
+
+#if BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+ // Building /w |rtc_use_h264|, is the corresponding run-time feature enabled?
+ if (!base::FeatureList::IsEnabled(
+ blink::features::kWebRtcH264WithOpenH264FFmpeg)) {
+ // Feature is to be disabled.
+ webrtc::DisableRtcUseH264();
+ }
+#else
+ webrtc::DisableRtcUseH264();
+#endif // BUILDFLAG(RTC_USE_H264) && BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+ // To allow sending to the signaling/worker threads.
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+
+ EnsureWebRtcAudioDeviceImpl();
+
+ CHECK(chrome_signaling_thread_.Start());
+ CHECK(chrome_worker_thread_.Start());
+
+ base::WaitableEvent start_worker_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ chrome_worker_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&PeerConnectionDependencyFactory::InitializeWorkerThread,
+ base::Unretained(this), &worker_thread_,
+ &start_worker_event));
+
+ base::WaitableEvent create_network_manager_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ std::unique_ptr<MdnsResponderAdapter> mdns_responder;
+#if BUILDFLAG(ENABLE_MDNS)
+ if (base::FeatureList::IsEnabled(
+ blink::features::kWebRtcHideLocalIpsWithMdns)) {
+ // Note that MdnsResponderAdapter is created on the main thread to have
+ // access to the connector to the service manager.
+ mdns_responder = std::make_unique<MdnsResponderAdapter>();
+ }
+#endif // BUILDFLAG(ENABLE_MDNS)
+ chrome_worker_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&PeerConnectionDependencyFactory::
+ CreateIpcNetworkManagerOnWorkerThread,
+ base::Unretained(this), &create_network_manager_event,
+ std::move(mdns_responder)));
+
+ start_worker_event.Wait();
+ create_network_manager_event.Wait();
+
+ CHECK(worker_thread_);
+
+ // Init SSL, which will be needed by PeerConnection.
+ if (!rtc::InitializeSSL()) {
+ LOG(ERROR) << "Failed on InitializeSSL.";
+ NOTREACHED();
+ return;
+ }
+
+ base::WaitableEvent start_signaling_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ chrome_signaling_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &PeerConnectionDependencyFactory::InitializeSignalingThread,
+ base::Unretained(this), blink::Platform::Current()->GetGpuFactories(),
+ &start_signaling_event));
+
+ start_signaling_event.Wait();
+ CHECK(signaling_thread_);
+}
+
+void PeerConnectionDependencyFactory::InitializeSignalingThread(
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ base::WaitableEvent* event) {
+ DCHECK(chrome_signaling_thread_.task_runner()->BelongsToCurrentThread());
+ DCHECK(worker_thread_);
+ DCHECK(p2p_socket_dispatcher_.get());
+
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
+
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("webrtc_peer_connection", R"(
+ semantics {
+ sender: "WebRTC"
+ description:
+ "WebRTC is an API that provides web applications with Real Time "
+ "Communication (RTC) capabilities. It is used to establish a "
+ "secure session with a remote peer, transmitting and receiving "
+ "audio, video and potentially other data."
+ trigger:
+ "Application creates an RTCPeerConnection and connects it to a "
+ "remote peer by exchanging an SDP offer and answer."
+ data:
+ "Media encrypted using DTLS-SRTP, and protocol-level messages for "
+ "the various subprotocols employed by WebRTC (including ICE, DTLS, "
+ "RTCP, etc.). Note that ICE connectivity checks may leak the "
+ "user's IP address(es), subject to the restrictions/guidance in "
+ "https://datatracker.ietf.org/doc/draft-ietf-rtcweb-ip-handling."
+ destination: OTHER
+ destination_other:
+ "A destination determined by the web application that created the "
+ "connection."
+ }
+ policy {
+ cookies_allowed: NO
+ setting:
+ "This feature cannot be disabled in settings, but it won't be used "
+ "unless the application creates an RTCPeerConnection. Media can "
+ "only be captured with user's consent, but data may be sent "
+ "withouth that."
+ policy_exception_justification:
+ "Not implemented. 'WebRtcUdpPortRange' policy can limit the range "
+ "of ports used by WebRTC, but there is no policy to generally "
+ "block it."
+ }
+ )");
+ socket_factory_.reset(new IpcPacketSocketFactory(p2p_socket_dispatcher_.get(),
+ traffic_annotation));
+
+ std::unique_ptr<webrtc::VideoEncoderFactory> webrtc_encoder_factory =
+ blink::CreateWebrtcVideoEncoderFactory(gpu_factories);
+ std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory =
+ blink::CreateWebrtcVideoDecoderFactory(gpu_factories);
+
+ // Enable Multiplex codec in SDP optionally.
+ if (base::FeatureList::IsEnabled(blink::features::kWebRtcMultiplexCodec)) {
+ webrtc_encoder_factory = std::make_unique<webrtc::MultiplexEncoderFactory>(
+ std::move(webrtc_encoder_factory));
+ webrtc_decoder_factory = std::make_unique<webrtc::MultiplexDecoderFactory>(
+ std::move(webrtc_decoder_factory));
+ }
+
+ if (blink::Platform::Current()->UsesFakeCodecForPeerConnection()) {
+ webrtc_encoder_factory =
+ std::make_unique<webrtc::FakeVideoEncoderFactory>();
+ webrtc_decoder_factory =
+ std::make_unique<webrtc::FakeVideoDecoderFactory>();
+ }
+
+ webrtc::PeerConnectionFactoryDependencies pcf_deps;
+ pcf_deps.worker_thread = worker_thread_;
+ pcf_deps.network_thread = worker_thread_;
+ pcf_deps.signaling_thread = signaling_thread_;
+ pcf_deps.task_queue_factory = CreateWebRtcTaskQueueFactory();
+ pcf_deps.call_factory = webrtc::CreateCallFactory();
+ pcf_deps.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>(
+ pcf_deps.task_queue_factory.get());
+ cricket::MediaEngineDependencies media_deps;
+ media_deps.task_queue_factory = pcf_deps.task_queue_factory.get();
+ media_deps.adm = audio_device_.get();
+ media_deps.audio_encoder_factory = blink::CreateWebrtcAudioEncoderFactory();
+ media_deps.audio_decoder_factory = blink::CreateWebrtcAudioDecoderFactory();
+ media_deps.video_encoder_factory = std::move(webrtc_encoder_factory);
+ media_deps.video_decoder_factory = std::move(webrtc_decoder_factory);
+ media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create();
+ pcf_deps.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
+ pc_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(pcf_deps));
+ CHECK(pc_factory_.get());
+
+ webrtc::PeerConnectionFactoryInterface::Options factory_options;
+ factory_options.disable_sctp_data_channels = false;
+ factory_options.disable_encryption =
+ !blink::Platform::Current()->IsWebRtcEncryptionEnabled();
+ pc_factory_->SetOptions(factory_options);
+
+ event->Signal();
+}
+
+bool PeerConnectionDependencyFactory::PeerConnectionFactoryCreated() {
+ return !!pc_factory_;
+}
+
+scoped_refptr<webrtc::PeerConnectionInterface>
+PeerConnectionDependencyFactory::CreatePeerConnection(
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
+ blink::WebLocalFrame* web_frame,
+ webrtc::PeerConnectionObserver* observer) {
+ CHECK(web_frame);
+ CHECK(observer);
+ if (!GetPcFactory().get())
+ return nullptr;
+
+ webrtc::PeerConnectionDependencies dependencies(observer);
+ dependencies.allocator = CreatePortAllocator(web_frame);
+ dependencies.async_resolver_factory = CreateAsyncResolverFactory();
+ return GetPcFactory()
+ ->CreatePeerConnection(config, std::move(dependencies))
+ .get();
+}
+
+std::unique_ptr<cricket::PortAllocator>
+PeerConnectionDependencyFactory::CreatePortAllocator(
+ blink::WebLocalFrame* web_frame) {
+ DCHECK(web_frame);
+
+ // Copy the flag from Preference associated with this WebLocalFrame.
+ P2PPortAllocator::Config port_config;
+ uint16_t min_port = 0;
+ uint16_t max_port = 0;
+ bool allow_mdns_obfuscation = true;
+
+ // |media_permission| will be called to check mic/camera permission. If at
+ // least one of them is granted, P2PPortAllocator is allowed to gather local
+ // host IP addresses as ICE candidates. |media_permission| could be nullptr,
+ // which means the permission will be granted automatically. This could be the
+ // case when either the experiment is not enabled or the preference is not
+ // enforced.
+ //
+ // Note on |media_permission| lifetime: |media_permission| is owned by a frame
+ // (RenderFrameImpl). It is also stored as an indirect member of
+ // RTCPeerConnectionHandler (through PeerConnection/PeerConnectionInterface ->
+ // P2PPortAllocator -> FilteringNetworkManager -> |media_permission|).
+ // The RTCPeerConnectionHandler is owned as RTCPeerConnection::m_peerHandler
+ // in Blink, which will be reset in RTCPeerConnection::stop(). Since
+ // ActiveDOMObject::stop() is guaranteed to be called before a frame is
+ // detached, it is impossible for RTCPeerConnectionHandler to outlive the
+ // frame. Therefore using a raw pointer of |media_permission| is safe here.
+ media::MediaPermission* media_permission = nullptr;
+ if (!blink::Platform::Current()->ShouldEnforceWebRTCRoutingPreferences()) {
+ port_config.enable_multiple_routes = true;
+ port_config.enable_nonproxied_udp = true;
+ VLOG(3) << "WebRTC routing preferences will not be enforced";
+ } else {
+ if (web_frame && web_frame->View()) {
+ blink::WebString webrtc_ip_handling_policy;
+ blink::Platform::Current()->GetWebRTCRendererPreferences(
+ web_frame, &webrtc_ip_handling_policy, &min_port, &max_port,
+ &allow_mdns_obfuscation);
+
+ // TODO(guoweis): |enable_multiple_routes| should be renamed to
+ // |request_multiple_routes|. Whether local IP addresses could be
+ // collected depends on if mic/camera permission is granted for this
+ // origin.
+ WebRTCIPHandlingPolicy policy =
+ GetWebRTCIPHandlingPolicy(webrtc_ip_handling_policy.Utf8());
+ switch (policy) {
+ // TODO(guoweis): specify the flag of disabling local candidate
+ // collection when webrtc is updated.
+ case DEFAULT_PUBLIC_INTERFACE_ONLY:
+ case DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES:
+ port_config.enable_multiple_routes = false;
+ port_config.enable_nonproxied_udp = true;
+ port_config.enable_default_local_candidate =
+ (policy == DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES);
+ break;
+ case DISABLE_NON_PROXIED_UDP:
+ port_config.enable_multiple_routes = false;
+ port_config.enable_nonproxied_udp = false;
+ break;
+ case DEFAULT:
+ port_config.enable_multiple_routes = true;
+ port_config.enable_nonproxied_udp = true;
+ break;
+ }
+
+ VLOG(3) << "WebRTC routing preferences: "
+ << "policy: " << policy
+ << ", multiple_routes: " << port_config.enable_multiple_routes
+ << ", nonproxied_udp: " << port_config.enable_nonproxied_udp
+ << ", min_udp_port: " << min_port
+ << ", max_udp_port: " << max_port
+ << ", allow_mdns_obfuscation: " << allow_mdns_obfuscation;
+ }
+ if (port_config.enable_multiple_routes) {
+ media_permission =
+ blink::Platform::Current()->GetWebRTCMediaPermission(web_frame);
+ }
+ }
+
+ // Now that this file is within Blink, it can not rely on WebURL's
+ // GURL() operator directly. Hence, as per the comment on gurl.h, the
+ // following GURL ctor is used instead.
+ WebURL document_url = web_frame->GetDocument().Url();
+ const GURL& requesting_origin =
+ GURL(document_url.GetString().Utf8(), document_url.GetParsed(),
+ document_url.IsValid())
+ .GetOrigin();
+
+ std::unique_ptr<rtc::NetworkManager> network_manager;
+ if (port_config.enable_multiple_routes) {
+ network_manager = std::make_unique<blink::FilteringNetworkManager>(
+ network_manager_.get(), requesting_origin, media_permission,
+ allow_mdns_obfuscation);
+ } else {
+ network_manager =
+ std::make_unique<blink::EmptyNetworkManager>(network_manager_.get());
+ }
+ auto port_allocator = std::make_unique<P2PPortAllocator>(
+ p2p_socket_dispatcher_, std::move(network_manager), socket_factory_.get(),
+ port_config, requesting_origin);
+ if (IsValidPortRange(min_port, max_port))
+ port_allocator->SetPortRange(min_port, max_port);
+
+ return port_allocator;
+}
+
+std::unique_ptr<webrtc::AsyncResolverFactory>
+PeerConnectionDependencyFactory::CreateAsyncResolverFactory() {
+ return std::make_unique<ProxyAsyncResolverFactory>(socket_factory_.get());
+}
+
+scoped_refptr<webrtc::MediaStreamInterface>
+PeerConnectionDependencyFactory::CreateLocalMediaStream(
+ const std::string& label) {
+ return GetPcFactory()->CreateLocalMediaStream(label).get();
+}
+
+scoped_refptr<webrtc::VideoTrackSourceInterface>
+PeerConnectionDependencyFactory::CreateVideoTrackSourceProxy(
+ webrtc::VideoTrackSourceInterface* source) {
+ // PeerConnectionFactory needs to be instantiated to make sure that
+ // signaling_thread_ and worker_thread_ exist.
+ if (!PeerConnectionFactoryCreated())
+ CreatePeerConnectionFactory();
+
+ return webrtc::VideoTrackSourceProxy::Create(signaling_thread_,
+ worker_thread_, source)
+ .get();
+}
+
+scoped_refptr<webrtc::VideoTrackInterface>
+PeerConnectionDependencyFactory::CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source) {
+ return GetPcFactory()->CreateVideoTrack(id, source).get();
+}
+
+webrtc::SessionDescriptionInterface*
+PeerConnectionDependencyFactory::CreateSessionDescription(
+ const std::string& type,
+ const std::string& sdp,
+ webrtc::SdpParseError* error) {
+ return webrtc::CreateSessionDescription(type, sdp, error);
+}
+
+webrtc::IceCandidateInterface*
+PeerConnectionDependencyFactory::CreateIceCandidate(const std::string& sdp_mid,
+ int sdp_mline_index,
+ const std::string& sdp) {
+ return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp, nullptr);
+}
+
+blink::WebRtcAudioDeviceImpl*
+PeerConnectionDependencyFactory::GetWebRtcAudioDevice() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ EnsureWebRtcAudioDeviceImpl();
+ return audio_device_.get();
+}
+
+void PeerConnectionDependencyFactory::InitializeWorkerThread(
+ rtc::Thread** thread,
+ base::WaitableEvent* event) {
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ *thread = jingle_glue::JingleThreadWrapper::current();
+ event->Signal();
+}
+
+void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
+ base::Optional<std::string> params =
+ blink::Platform::Current()->WebRtcStunProbeTrialParameter();
+ if (!params)
+ return;
+
+ GetPcFactory();
+
+ chrome_worker_thread_.task_runner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(
+ &PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread,
+ base::Unretained(this), *params),
+ base::TimeDelta::FromMilliseconds(blink::kExperimentStartDelayMs));
+}
+
+void PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread(
+ const std::string& params) {
+ DCHECK(network_manager_);
+ DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+ stun_trial_.reset(new blink::StunProberTrial(network_manager_.get(), params,
+ socket_factory_.get()));
+}
+
+void PeerConnectionDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
+ base::WaitableEvent* event,
+ std::unique_ptr<MdnsResponderAdapter> mdns_responder) {
+ DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+ network_manager_ = std::make_unique<blink::IpcNetworkManager>(
+ p2p_socket_dispatcher_.get(), std::move(mdns_responder));
+ event->Signal();
+}
+
+void PeerConnectionDependencyFactory::DeleteIpcNetworkManager() {
+ DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+ network_manager_.reset();
+}
+
+void PeerConnectionDependencyFactory::CleanupPeerConnectionFactory() {
+ DVLOG(1) << "PeerConnectionDependencyFactory::CleanupPeerConnectionFactory()";
+ pc_factory_ = nullptr;
+ if (network_manager_) {
+ // The network manager needs to free its resources on the thread they were
+ // created, which is the worked thread.
+ if (chrome_worker_thread_.IsRunning()) {
+ chrome_worker_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &PeerConnectionDependencyFactory::DeleteIpcNetworkManager,
+ base::Unretained(this)));
+ // Stopping the thread will wait until all tasks have been
+ // processed before returning. We wait for the above task to finish before
+ // letting the the function continue to avoid any potential race issues.
+ chrome_worker_thread_.Stop();
+ } else {
+ NOTREACHED() << "Worker thread not running.";
+ }
+ }
+}
+
+void PeerConnectionDependencyFactory::EnsureInitialized() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ GetPcFactory();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+PeerConnectionDependencyFactory::GetWebRtcWorkerThread() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return chrome_worker_thread_.IsRunning() ? chrome_worker_thread_.task_runner()
+ : nullptr;
+}
+
+rtc::Thread* PeerConnectionDependencyFactory::GetWebRtcWorkerThreadRtcThread() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ EnsureInitialized();
+ return chrome_worker_thread_.IsRunning() ? worker_thread_ : nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+PeerConnectionDependencyFactory::GetWebRtcSignalingTaskRunner() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ EnsureInitialized();
+ return chrome_signaling_thread_.IsRunning()
+ ? chrome_signaling_thread_.task_runner()
+ : nullptr;
+}
+
+void PeerConnectionDependencyFactory::EnsureWebRtcAudioDeviceImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (audio_device_.get())
+ return;
+
+ audio_device_ = new rtc::RefCountedObject<blink::WebRtcAudioDeviceImpl>();
+}
+
+std::unique_ptr<webrtc::RtpCapabilities>
+PeerConnectionDependencyFactory::GetSenderCapabilities(
+ const std::string& kind) {
+ if (kind == "audio") {
+ return std::make_unique<webrtc::RtpCapabilities>(
+ GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO));
+ } else if (kind == "video") {
+ return std::make_unique<webrtc::RtpCapabilities>(
+ GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO));
+ }
+ return nullptr;
+}
+
+std::unique_ptr<webrtc::RtpCapabilities>
+PeerConnectionDependencyFactory::GetReceiverCapabilities(
+ const std::string& kind) {
+ if (kind == "audio") {
+ return std::make_unique<webrtc::RtpCapabilities>(
+ GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO));
+ } else if (kind == "video") {
+ return std::make_unique<webrtc::RtpCapabilities>(
+ GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_VIDEO));
+ }
+ return nullptr;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc
new file mode 100644
index 00000000000..a0db11483f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc
@@ -0,0 +1,152 @@
+// Copyright (c) 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/peerconnection/rtc_certificate_generator.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+#include "third_party/webrtc/rtc_base/rtc_certificate.h"
+#include "third_party/webrtc/rtc_base/rtc_certificate_generator.h"
+
+namespace blink {
+namespace {
+
+rtc::KeyParams WebRTCKeyParamsToKeyParams(
+ const blink::WebRTCKeyParams& key_params) {
+ switch (key_params.KeyType()) {
+ case blink::kWebRTCKeyTypeRSA:
+ return rtc::KeyParams::RSA(key_params.RsaParams().mod_length,
+ key_params.RsaParams().pub_exp);
+ case blink::kWebRTCKeyTypeECDSA:
+ return rtc::KeyParams::ECDSA(
+ static_cast<rtc::ECCurve>(key_params.EcCurve()));
+ default:
+ NOTREACHED();
+ return rtc::KeyParams();
+ }
+}
+
+// A certificate generation request spawned by
+// |GenerateCertificateWithOptionalExpiration|. This
+// is handled by a separate class so that reference counting can keep the
+// request alive independently of the |RTCCertificateGenerator| that spawned it.
+class RTCCertificateGeneratorRequest
+ : public WTF::ThreadSafeRefCounted<RTCCertificateGeneratorRequest> {
+ public:
+ RTCCertificateGeneratorRequest(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ const scoped_refptr<base::SingleThreadTaskRunner>& worker_thread)
+ : main_thread_(main_thread), worker_thread_(worker_thread) {
+ DCHECK(main_thread_);
+ DCHECK(worker_thread_);
+ }
+
+ void GenerateCertificateAsync(
+ const blink::WebRTCKeyParams& key_params,
+ const absl::optional<uint64_t>& expires_ms,
+ blink::RTCCertificateCallback completion_callback) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(completion_callback);
+
+ worker_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCCertificateGeneratorRequest::GenerateCertificateOnWorkerThread,
+ this, key_params, expires_ms, std::move(completion_callback)));
+ }
+
+ private:
+ friend class WTF::ThreadSafeRefCounted<RTCCertificateGeneratorRequest>;
+ ~RTCCertificateGeneratorRequest() {}
+
+ void GenerateCertificateOnWorkerThread(
+ const blink::WebRTCKeyParams key_params,
+ const absl::optional<uint64_t> expires_ms,
+ blink::RTCCertificateCallback completion_callback) {
+ DCHECK(worker_thread_->BelongsToCurrentThread());
+
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+ rtc::RTCCertificateGenerator::GenerateCertificate(
+ WebRTCKeyParamsToKeyParams(key_params), expires_ms);
+
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread,
+ this, std::move(completion_callback), certificate));
+ }
+
+ void DoCallbackOnMainThread(
+ blink::RTCCertificateCallback completion_callback,
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(completion_callback);
+ std::move(completion_callback).Run(std::move(certificate));
+ }
+
+ // The main thread is the renderer thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ // The WebRTC worker thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_;
+};
+
+void GenerateCertificateWithOptionalExpiration(
+ const blink::WebRTCKeyParams& key_params,
+ const absl::optional<uint64_t>& expires_ms,
+ blink::RTCCertificateCallback completion_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(WebRTCKeyParamsToKeyParams(key_params).IsValid());
+ auto* pc_dependency_factory =
+ blink::PeerConnectionDependencyFactory::GetInstance();
+ pc_dependency_factory->EnsureInitialized();
+
+ scoped_refptr<RTCCertificateGeneratorRequest> request =
+ base::MakeRefCounted<RTCCertificateGeneratorRequest>(
+ task_runner, pc_dependency_factory->GetWebRtcWorkerThread());
+ request->GenerateCertificateAsync(key_params, expires_ms,
+ std::move(completion_callback));
+}
+
+} // namespace
+
+void RTCCertificateGenerator::GenerateCertificate(
+ const blink::WebRTCKeyParams& key_params,
+ blink::RTCCertificateCallback completion_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ GenerateCertificateWithOptionalExpiration(
+ key_params, absl::nullopt, std::move(completion_callback), task_runner);
+}
+
+void RTCCertificateGenerator::GenerateCertificateWithExpiration(
+ const blink::WebRTCKeyParams& key_params,
+ uint64_t expires_ms,
+ blink::RTCCertificateCallback completion_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ GenerateCertificateWithOptionalExpiration(
+ key_params, expires_ms, std::move(completion_callback), task_runner);
+}
+
+bool RTCCertificateGenerator::IsSupportedKeyParams(
+ const blink::WebRTCKeyParams& key_params) {
+ return WebRTCKeyParamsToKeyParams(key_params).IsValid();
+}
+
+rtc::scoped_refptr<rtc::RTCCertificate> RTCCertificateGenerator::FromPEM(
+ blink::WebString pem_private_key,
+ blink::WebString pem_certificate) {
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+ rtc::RTCCertificate::FromPEM(rtc::RTCCertificatePEM(
+ pem_private_key.Utf8(), pem_certificate.Utf8()));
+ if (!certificate)
+ return nullptr;
+ return certificate;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h
new file mode 100644
index 00000000000..726b2398449
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h
@@ -0,0 +1,65 @@
+// Copyright (c) 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_PEERCONNECTION_RTC_CERTIFICATE_GENERATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_CERTIFICATE_GENERATOR_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/web_rtc_key_params.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/webrtc/api/peer_connection_interface.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace blink {
+
+using RTCCertificateCallback =
+ base::OnceCallback<void(rtc::scoped_refptr<rtc::RTCCertificate>)>;
+
+// Chromium's WebRTCCertificateGenerator implementation; uses the
+// PeerConnectionIdentityStore/SSLIdentity::Generate to generate the identity,
+// rtc::RTCCertificate and blink::RTCCertificate.
+//
+// TODO(crbug.com/787254): Convert use of WebString to WTF::String.
+class MODULES_EXPORT RTCCertificateGenerator {
+ public:
+ RTCCertificateGenerator() {}
+ ~RTCCertificateGenerator() {}
+
+ // Start generating a certificate asynchronously. |observer| is invoked on the
+ // same thread that called generateCertificate when the operation is
+ // completed.
+ void GenerateCertificate(
+ const blink::WebRTCKeyParams& key_params,
+ blink::RTCCertificateCallback completion_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ void GenerateCertificateWithExpiration(
+ const blink::WebRTCKeyParams& key_params,
+ uint64_t expires_ms,
+ blink::RTCCertificateCallback completion_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ // Determines if the parameters are supported by |GenerateCertificate|.
+ // For example, if the number of bits of some parameter is too small or too
+ // large we may want to reject it for security or performance reasons.
+ bool IsSupportedKeyParams(const blink::WebRTCKeyParams& key_params);
+
+ // Creates a certificate from the PEM strings. See also
+ // |rtc::RTCCertificate::ToPEM|.
+ rtc::scoped_refptr<rtc::RTCCertificate> FromPEM(
+ blink::WebString pem_private_key,
+ blink::WebString pem_certificate);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RTCCertificateGenerator);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_CERTIFICATE_GENERATOR_H_
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
index b0c16615fc6..c7a6438a5b5 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
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 d2a2c691817..12a81819132 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -64,8 +65,8 @@ class DtlsIceTransportAdapterCrossThreadFactory
: ice_transport_(ice_transport) {}
void InitializeOnMainThread(LocalFrame& frame) override {
DCHECK(!worker_thread_rtc_thread_);
- worker_thread_rtc_thread_ =
- Platform::Current()->GetWebRtcWorkerThreadRtcThread();
+ worker_thread_rtc_thread_ = PeerConnectionDependencyFactory::GetInstance()
+ ->GetWebRtcWorkerThreadRtcThread();
}
std::unique_ptr<IceTransportAdapter> ConstructOnWorkerThread(
@@ -88,12 +89,17 @@ class DefaultIceTransportAdapterCrossThreadFactory
DCHECK(!port_allocator_);
DCHECK(!worker_thread_rtc_thread_);
DCHECK(!async_resolver_factory_);
- port_allocator_ = Platform::Current()->CreateWebRtcPortAllocator(
+
+ auto* rtc_dependency_factory =
+ blink::PeerConnectionDependencyFactory::GetInstance();
+ rtc_dependency_factory->EnsureInitialized();
+ port_allocator_ = rtc_dependency_factory->CreatePortAllocator(
frame.Client()->GetWebFrame());
+
async_resolver_factory_ =
Platform::Current()->CreateWebRtcAsyncResolverFactory();
- worker_thread_rtc_thread_ =
- Platform::Current()->GetWebRtcWorkerThreadRtcThread();
+ worker_thread_rtc_thread_ = PeerConnectionDependencyFactory::GetInstance()
+ ->GetWebRtcWorkerThreadRtcThread();
}
std::unique_ptr<IceTransportAdapter> ConstructOnWorkerThread(
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 a40b6f03b4a..26cec8dd675 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
@@ -45,7 +45,6 @@
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_rtc_answer_options.h"
-#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_init.h"
#include "third_party/blink/public/platform/web_rtc_ice_candidate.h"
#include "third_party/blink/public/platform/web_rtc_key_params.h"
@@ -79,6 +78,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream_event.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_answer_options.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_configuration.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel_event.h"
@@ -1670,8 +1670,7 @@ ScriptPromise RTCPeerConnection::generateCertificate(
}
DCHECK(key_params.has_value());
- std::unique_ptr<WebRTCCertificateGenerator> certificate_generator =
- Platform::Current()->CreateRTCCertificateGenerator();
+ auto certificate_generator = std::make_unique<RTCCertificateGenerator>();
// |keyParams| was successfully constructed, but does the certificate
// generator support these parameters?
@@ -1995,20 +1994,21 @@ bool RTCPeerConnection::IsRemoteStream(MediaStream* stream) const {
ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
ExceptionState& exception_state) {
- return getStats(
- script_state,
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return getStats(script_state,
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
ScriptValue callback_or_selector,
ExceptionState& exception_state) {
- return getStats(
- script_state, std::move(callback_or_selector),
- ScriptValue(script_state, v8::Undefined(script_state->GetIsolate())),
- exception_state);
+ return getStats(script_state, std::move(callback_or_selector),
+ ScriptValue(script_state->GetIsolate(),
+ v8::Undefined(script_state->GetIsolate())),
+ exception_state);
}
ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
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 939d2821393..0e205e4259a 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
@@ -372,7 +372,7 @@ class MODULES_EXPORT RTCPeerConnection final
GetTrackRemoveStreamAndGCWithPersistentStream);
typedef base::OnceCallback<bool()> BoolFunction;
- class EventWrapper : public GarbageCollectedFinalized<EventWrapper> {
+ class EventWrapper final : public GarbageCollected<EventWrapper> {
public:
EventWrapper(Event*, BoolFunction);
// Returns true if |m_setupFunction| returns true or it is null.
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 6efc41f5bb5..cd4b886c183 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_rtc_rtp_source.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
@@ -46,25 +47,23 @@ RTCDtlsTransport* RTCRtpReceiver::rtcpTransport() {
return nullptr;
}
-double RTCRtpReceiver::jitterBufferDelayHint(bool& is_null, ExceptionState&) {
- is_null = !jitter_buffer_delay_hint_.has_value();
- return jitter_buffer_delay_hint_.value_or(0.0);
+double RTCRtpReceiver::playoutDelayHint(bool& is_null, ExceptionState&) {
+ is_null = !playout_delay_hint_.has_value();
+ return playout_delay_hint_.value_or(0.0);
}
-void RTCRtpReceiver::setJitterBufferDelayHint(double value,
- bool is_null,
- ExceptionState& exception_state) {
+void RTCRtpReceiver::setPlayoutDelayHint(double value,
+ bool is_null,
+ ExceptionState& exception_state) {
base::Optional<double> hint =
is_null ? base::nullopt : base::Optional<double>(value);
if (hint && *hint < 0.0) {
- exception_state.ThrowDOMException(
- DOMExceptionCode::kInvalidAccessError,
- "jitterBufferDelayHint can't be negative");
+ exception_state.ThrowTypeError("playoutDelayHint can't be negative");
return;
}
- jitter_buffer_delay_hint_ = hint;
- receiver_->SetJitterBufferMinimumDelay(jitter_buffer_delay_hint_);
+ playout_delay_hint_ = hint;
+ receiver_->SetJitterBufferMinimumDelay(playout_delay_hint_);
}
HeapVector<Member<RTCRtpSynchronizationSource>>
@@ -188,7 +187,8 @@ RTCRtpCapabilities* RTCRtpReceiver::getCapabilities(const String& kind) {
HeapVector<Member<RTCRtpHeaderExtensionCapability>>());
std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
- blink::Platform::Current()->GetRtpSenderCapabilities(kind);
+ PeerConnectionDependencyFactory::GetInstance()->GetSenderCapabilities(
+ kind.Utf8());
HeapVector<Member<RTCRtpCodecCapability>> codecs;
codecs.ReserveInitialCapacity(
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 79d311ec4fa..83b396bcea8 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
@@ -43,8 +43,8 @@ class RTCRtpReceiver final : public ScriptWrappable {
MediaStreamTrack* track() const;
RTCDtlsTransport* transport();
RTCDtlsTransport* rtcpTransport();
- double jitterBufferDelayHint(bool&, ExceptionState&);
- void setJitterBufferDelayHint(double, bool, ExceptionState&);
+ double playoutDelayHint(bool&, ExceptionState&);
+ void setPlayoutDelayHint(double, bool, ExceptionState&);
RTCRtpReceiveParameters* getParameters();
HeapVector<Member<RTCRtpSynchronizationSource>> getSynchronizationSources();
HeapVector<Member<RTCRtpContributingSource>> getContributingSources();
@@ -77,7 +77,7 @@ class RTCRtpReceiver final : public ScriptWrappable {
// Hint to the WebRTC Jitter Buffer about desired playout delay. Actual
// observed delay may differ depending on the congestion control. |nullopt|
// means default value must be used.
- base::Optional<double> jitter_buffer_delay_hint_;
+ base::Optional<double> playout_delay_hint_;
};
} // 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 82ea2e89359..0d88ea811ef 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
@@ -8,7 +8,8 @@ interface RTCRtpReceiver {
readonly attribute MediaStreamTrack track;
[RuntimeEnabled=RTCDtlsTransport] readonly attribute RTCDtlsTransport? transport;
[RuntimeEnabled=RTCDtlsTransport] readonly attribute RTCDtlsTransport? rtcpTransport;
- [RaisesException, RuntimeEnabled=RtcJitterBufferDelayHint, Measure] attribute double? jitterBufferDelayHint;
+ // https://henbos.github.io/webrtc-extensions/#dom-rtcrtpreceiver-playoutdelayhint
+ [RaisesException, Measure] attribute double? playoutDelayHint;
static RTCRtpCapabilities? getCapabilities(DOMString kind);
RTCRtpReceiveParameters getParameters();
sequence<RTCRtpSynchronizationSource> getSynchronizationSources();
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc
new file mode 100644
index 00000000000..f3dba4fa581
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc
@@ -0,0 +1,386 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_source.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace blink {
+
+RtpReceiverState::RtpReceiverState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ std::vector<std::string> stream_id)
+ : main_task_runner_(std::move(main_task_runner)),
+ signaling_task_runner_(std::move(signaling_task_runner)),
+ webrtc_receiver_(std::move(webrtc_receiver)),
+ webrtc_dtls_transport_(webrtc_receiver_->dtls_transport()),
+ webrtc_dtls_transport_information_(webrtc::DtlsTransportState::kNew),
+ is_initialized_(false),
+ track_ref_(std::move(track_ref)),
+ stream_ids_(std::move(stream_id)) {
+ DCHECK(main_task_runner_);
+ DCHECK(signaling_task_runner_);
+ DCHECK(webrtc_receiver_);
+ DCHECK(track_ref_);
+ if (webrtc_dtls_transport_) {
+ webrtc_dtls_transport_information_ = webrtc_dtls_transport_->Information();
+ }
+}
+
+RtpReceiverState::RtpReceiverState(RtpReceiverState&& other)
+ : main_task_runner_(other.main_task_runner_),
+ signaling_task_runner_(other.signaling_task_runner_),
+ webrtc_receiver_(std::move(other.webrtc_receiver_)),
+ webrtc_dtls_transport_(std::move(other.webrtc_dtls_transport_)),
+ webrtc_dtls_transport_information_(
+ other.webrtc_dtls_transport_information_),
+ is_initialized_(other.is_initialized_),
+ track_ref_(std::move(other.track_ref_)),
+ stream_ids_(std::move(other.stream_ids_)) {
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+}
+
+RtpReceiverState::~RtpReceiverState() {
+ // It's OK to not be on the main thread if this state has been moved, in which
+ // case |main_task_runner_| is null.
+ DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread());
+}
+
+RtpReceiverState& RtpReceiverState::operator=(RtpReceiverState&& other) {
+ DCHECK_EQ(main_task_runner_, other.main_task_runner_);
+ DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_);
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+ webrtc_receiver_ = std::move(other.webrtc_receiver_);
+ webrtc_dtls_transport_ = std::move(other.webrtc_dtls_transport_);
+ webrtc_dtls_transport_information_ = other.webrtc_dtls_transport_information_;
+ track_ref_ = std::move(other.track_ref_);
+ stream_ids_ = std::move(other.stream_ids_);
+ return *this;
+}
+
+bool RtpReceiverState::is_initialized() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return is_initialized_;
+}
+
+void RtpReceiverState::Initialize() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (is_initialized_)
+ return;
+ track_ref_->InitializeOnMainThread();
+ is_initialized_ = true;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> RtpReceiverState::main_task_runner()
+ const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return main_task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RtpReceiverState::signaling_task_runner() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return signaling_task_runner_;
+}
+
+scoped_refptr<webrtc::RtpReceiverInterface> RtpReceiverState::webrtc_receiver()
+ const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_receiver_;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+RtpReceiverState::webrtc_dtls_transport() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_dtls_transport_;
+}
+
+webrtc::DtlsTransportInformation
+RtpReceiverState::webrtc_dtls_transport_information() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_dtls_transport_information_;
+}
+
+const std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>&
+RtpReceiverState::track_ref() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return track_ref_;
+}
+
+const std::vector<std::string>& RtpReceiverState::stream_ids() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return stream_ids_;
+}
+
+class RTCRtpReceiverImpl::RTCRtpReceiverInternal
+ : public WTF::ThreadSafeRefCounted<
+ RTCRtpReceiverImpl::RTCRtpReceiverInternal,
+ RTCRtpReceiverImpl::RTCRtpReceiverInternalTraits> {
+ public:
+ RTCRtpReceiverInternal(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ RtpReceiverState state)
+ : native_peer_connection_(std::move(native_peer_connection)),
+ main_task_runner_(state.main_task_runner()),
+ signaling_task_runner_(state.signaling_task_runner()),
+ webrtc_receiver_(state.webrtc_receiver()),
+ state_(std::move(state)) {
+ DCHECK(native_peer_connection_);
+ DCHECK(state_.is_initialized());
+ }
+
+ const RtpReceiverState& state() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return state_;
+ }
+
+ void set_state(RtpReceiverState state) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(state.main_task_runner() == main_task_runner_);
+ DCHECK(state.signaling_task_runner() == signaling_task_runner_);
+ DCHECK(state.webrtc_receiver() == webrtc_receiver_);
+ DCHECK(state.is_initialized());
+ state_ = std::move(state);
+ }
+
+ blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> GetSources() {
+ // The webrtc_recever_ is a proxy, so this is a blocking call to the webrtc
+ // signalling thread.
+ auto webrtc_sources = webrtc_receiver_->GetSources();
+ blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>> sources(
+ webrtc_sources.size());
+ for (size_t i = 0; i < webrtc_sources.size(); ++i) {
+ sources[i] = blink::CreateRTCRtpSource(webrtc_sources[i]);
+ }
+ return sources;
+ }
+
+ void GetStats(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ signaling_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCRtpReceiverInternal::GetStatsOnSignalingThread, this,
+ std::move(callback), exposed_group_ids));
+ }
+
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() {
+ return std::make_unique<webrtc::RtpParameters>(
+ webrtc_receiver_->GetParameters());
+ }
+
+ void SetJitterBufferMinimumDelay(base::Optional<double> delay_seconds) {
+ webrtc_receiver_->SetJitterBufferMinimumDelay(
+ blink::ToAbslOptional(delay_seconds));
+ }
+
+ private:
+ friend class WTF::ThreadSafeRefCounted<RTCRtpReceiverInternal,
+ RTCRtpReceiverInternalTraits>;
+ friend struct RTCRtpReceiverImpl::RTCRtpReceiverInternalTraits;
+
+ ~RTCRtpReceiverInternal() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ }
+
+ void GetStatsOnSignalingThread(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ native_peer_connection_->GetStats(
+ webrtc_receiver_.get(),
+ blink::CreateRTCStatsCollectorCallback(
+ main_task_runner_, std::move(callback), exposed_group_ids));
+ }
+
+ const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
+ // Task runners and webrtc receiver: Same information as stored in
+ // |state_| but const and safe to touch on the signaling thread to
+ // avoid race with set_state().
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ const scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_;
+ RtpReceiverState state_;
+};
+
+struct RTCRtpReceiverImpl::RTCRtpReceiverInternalTraits {
+ static void Destruct(const RTCRtpReceiverInternal* receiver) {
+ // RTCRtpReceiverInternal owns AdapterRefs which have to be destroyed on the
+ // main thread, this ensures delete always happens there.
+ if (!receiver->main_task_runner_->BelongsToCurrentThread()) {
+ receiver->main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpReceiverImpl::RTCRtpReceiverInternalTraits::Destruct,
+ base::Unretained(receiver)));
+ return;
+ }
+ delete receiver;
+ }
+};
+
+uintptr_t RTCRtpReceiverImpl::getId(
+ const webrtc::RtpReceiverInterface* webrtc_rtp_receiver) {
+ return reinterpret_cast<uintptr_t>(webrtc_rtp_receiver);
+}
+
+RTCRtpReceiverImpl::RTCRtpReceiverImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ RtpReceiverState state)
+ : internal_(base::MakeRefCounted<RTCRtpReceiverInternal>(
+ std::move(native_peer_connection),
+ std::move(state))) {}
+
+RTCRtpReceiverImpl::RTCRtpReceiverImpl(const RTCRtpReceiverImpl& other)
+ : internal_(other.internal_) {}
+
+RTCRtpReceiverImpl::~RTCRtpReceiverImpl() {}
+
+RTCRtpReceiverImpl& RTCRtpReceiverImpl::operator=(
+ const RTCRtpReceiverImpl& other) {
+ internal_ = other.internal_;
+ return *this;
+}
+
+const RtpReceiverState& RTCRtpReceiverImpl::state() const {
+ return internal_->state();
+}
+
+void RTCRtpReceiverImpl::set_state(RtpReceiverState state) {
+ internal_->set_state(std::move(state));
+}
+
+std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpReceiverImpl::ShallowCopy()
+ const {
+ return std::make_unique<RTCRtpReceiverImpl>(*this);
+}
+
+uintptr_t RTCRtpReceiverImpl::Id() const {
+ return getId(internal_->state().webrtc_receiver().get());
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+RTCRtpReceiverImpl::DtlsTransport() {
+ return internal_->state().webrtc_dtls_transport();
+}
+
+webrtc::DtlsTransportInformation
+RTCRtpReceiverImpl::DtlsTransportInformation() {
+ return internal_->state().webrtc_dtls_transport_information();
+}
+
+const blink::WebMediaStreamTrack& RTCRtpReceiverImpl::Track() const {
+ return internal_->state().track_ref()->web_track();
+}
+
+blink::WebVector<blink::WebString> RTCRtpReceiverImpl::StreamIds() const {
+ const auto& stream_ids = internal_->state().stream_ids();
+ blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size());
+ for (size_t i = 0; i < stream_ids.size(); ++i)
+ web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]);
+ return web_stream_ids;
+}
+
+blink::WebVector<std::unique_ptr<blink::WebRTCRtpSource>>
+RTCRtpReceiverImpl::GetSources() {
+ return internal_->GetSources();
+}
+
+void RTCRtpReceiverImpl::GetStats(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ internal_->GetStats(std::move(callback), exposed_group_ids);
+}
+
+std::unique_ptr<webrtc::RtpParameters> RTCRtpReceiverImpl::GetParameters()
+ const {
+ return internal_->GetParameters();
+}
+
+void RTCRtpReceiverImpl::SetJitterBufferMinimumDelay(
+ base::Optional<double> delay_seconds) {
+ internal_->SetJitterBufferMinimumDelay(delay_seconds);
+}
+
+RTCRtpReceiverOnlyTransceiver::RTCRtpReceiverOnlyTransceiver(
+ std::unique_ptr<blink::WebRTCRtpReceiver> receiver)
+ : receiver_(std::move(receiver)) {
+ DCHECK(receiver_);
+}
+
+RTCRtpReceiverOnlyTransceiver::~RTCRtpReceiverOnlyTransceiver() {}
+
+blink::WebRTCRtpTransceiverImplementationType
+RTCRtpReceiverOnlyTransceiver::ImplementationType() const {
+ return blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly;
+}
+
+uintptr_t RTCRtpReceiverOnlyTransceiver::Id() const {
+ NOTIMPLEMENTED();
+ return 0u;
+}
+
+blink::WebString RTCRtpReceiverOnlyTransceiver::Mid() const {
+ NOTIMPLEMENTED();
+ return blink::WebString();
+}
+
+std::unique_ptr<blink::WebRTCRtpSender> RTCRtpReceiverOnlyTransceiver::Sender()
+ const {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+std::unique_ptr<blink::WebRTCRtpReceiver>
+RTCRtpReceiverOnlyTransceiver::Receiver() const {
+ return receiver_->ShallowCopy();
+}
+
+bool RTCRtpReceiverOnlyTransceiver::Stopped() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+webrtc::RtpTransceiverDirection RTCRtpReceiverOnlyTransceiver::Direction()
+ const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+void RTCRtpReceiverOnlyTransceiver::SetDirection(
+ webrtc::RtpTransceiverDirection direction) {
+ NOTIMPLEMENTED();
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpReceiverOnlyTransceiver::CurrentDirection() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpReceiverOnlyTransceiver::FiredDirection() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+webrtc::RTCError RTCRtpReceiverOnlyTransceiver::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) {
+ NOTIMPLEMENTED();
+ return {};
+}
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc
new file mode 100644
index 00000000000..c0bba3eb514
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_receiver_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/logging.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 "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/webrtc/api/stats/rtc_stats_report.h"
+#include "third_party/webrtc/api/stats/rtcstats_objects.h"
+#include "third_party/webrtc/api/test/mock_rtpreceiver.h"
+
+namespace blink {
+
+class RTCRtpReceiverImplTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ track_map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_thread_);
+ peer_connection_ = new rtc::RefCountedObject<blink::MockPeerConnectionImpl>(
+ dependency_factory_.get(), nullptr);
+ }
+
+ void TearDown() override {
+ receiver_.reset();
+ // Syncing up with the signaling thread ensures any pending operations on
+ // that thread are executed. If they post back to the main thread, such as
+ // the sender's destructor traits, this is allowed to execute before the
+ // test shuts down the threads.
+ SyncWithSignalingThread();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ // Wait for the signaling thread to perform any queued tasks, executing tasks
+ // posted to the current thread in the meantime while waiting.
+ void SyncWithSignalingThread() const {
+ base::RunLoop run_loop;
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ std::unique_ptr<RTCRtpReceiverImpl> CreateReceiver(
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track) {
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref;
+ base::RunLoop run_loop;
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCRtpReceiverImplTest::CreateReceiverOnSignalingThread,
+ base::Unretained(this), std::move(webrtc_track),
+ base::Unretained(&track_ref),
+ base::Unretained(&run_loop)));
+ run_loop.Run();
+ DCHECK(mock_webrtc_receiver_);
+ DCHECK(track_ref);
+ blink::RtpReceiverState state(
+ main_thread_, dependency_factory_->GetWebRtcSignalingTaskRunner(),
+ mock_webrtc_receiver_.get(), std::move(track_ref), {});
+ state.Initialize();
+ return std::make_unique<RTCRtpReceiverImpl>(peer_connection_.get(),
+ std::move(state));
+ }
+
+ scoped_refptr<blink::WebRTCStatsReportObtainer> GetStats() {
+ scoped_refptr<blink::WebRTCStatsReportObtainer> obtainer =
+ new blink::WebRTCStatsReportObtainer();
+ receiver_->GetStats(obtainer->GetStatsCallbackWrapper(), {});
+ return obtainer;
+ }
+
+ protected:
+ void CreateReceiverOnSignalingThread(
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>*
+ track_ref,
+ base::RunLoop* run_loop) {
+ mock_webrtc_receiver_ =
+ new rtc::RefCountedObject<webrtc::MockRtpReceiver>();
+ *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track);
+ run_loop->Quit();
+ }
+
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map_;
+ rtc::scoped_refptr<blink::MockPeerConnectionImpl> peer_connection_;
+ rtc::scoped_refptr<webrtc::MockRtpReceiver> mock_webrtc_receiver_;
+ std::unique_ptr<RTCRtpReceiverImpl> receiver_;
+};
+
+TEST_F(RTCRtpReceiverImplTest, CreateReceiver) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("webrtc_track");
+ receiver_ = CreateReceiver(webrtc_track);
+ EXPECT_FALSE(receiver_->Track().IsNull());
+ EXPECT_EQ(receiver_->Track().Id().Utf8(), webrtc_track->id());
+ EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track);
+}
+
+TEST_F(RTCRtpReceiverImplTest, ShallowCopy) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("webrtc_track");
+ receiver_ = CreateReceiver(webrtc_track);
+ auto copy = std::make_unique<RTCRtpReceiverImpl>(*receiver_);
+ EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track);
+ const auto& webrtc_receiver = receiver_->state().webrtc_receiver();
+ auto web_track_unique_id = receiver_->Track().UniqueId();
+ // Copy is identical to original.
+ EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver);
+ EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track);
+ EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id);
+ // Copy keeps the internal state alive.
+ receiver_.reset();
+ EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver);
+ EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track);
+ EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id);
+}
+
+TEST_F(RTCRtpReceiverImplTest, GetStats) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("webrtc_track");
+ receiver_ = CreateReceiver(webrtc_track);
+
+ // Make the mock return a blink version of the |webtc_report|. The mock does
+ // not perform any stats filtering, we just set it to a dummy value.
+ rtc::scoped_refptr<webrtc::RTCStatsReport> webrtc_report =
+ webrtc::RTCStatsReport::Create(0u);
+ webrtc_report->AddStats(
+ std::make_unique<webrtc::RTCInboundRTPStreamStats>("stats-id", 1234u));
+ peer_connection_->SetGetStatsReport(webrtc_report);
+
+ auto obtainer = GetStats();
+ // Make sure the operation is async.
+ EXPECT_FALSE(obtainer->report());
+ // Wait for the report, this performs the necessary run-loop.
+ auto* report = obtainer->WaitForReport();
+ EXPECT_TRUE(report);
+
+ // Verify dummy value.
+ EXPECT_EQ(report->Size(), 1u);
+ auto stats = report->GetStats(blink::WebString::FromUTF8("stats-id"));
+ EXPECT_TRUE(stats);
+ EXPECT_EQ(stats->Timestamp(), 1.234);
+}
+
+} // namespace blink
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 fcfb8fa98ab..bc07f07be59 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
@@ -9,8 +9,8 @@
#include <tuple>
#include <utility>
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
@@ -574,7 +574,8 @@ RTCRtpCapabilities* RTCRtpSender::getCapabilities(const String& kind) {
HeapVector<Member<RTCRtpHeaderExtensionCapability>>());
std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
- blink::Platform::Current()->GetRtpSenderCapabilities(kind);
+ PeerConnectionDependencyFactory::GetInstance()->GetSenderCapabilities(
+ kind.Utf8());
HeapVector<Member<RTCRtpCodecCapability>> codecs;
codecs.ReserveInitialCapacity(
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
new file mode 100644
index 00000000000..6936819df49
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc
@@ -0,0 +1,569 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+
+namespace blink {
+
+namespace {
+
+// TODO(hbos): Replace WebRTCVoidRequest with something resolving promises based
+// on RTCError, as to surface both exception type and error message.
+// https://crbug.com/790007
+void OnReplaceTrackCompleted(blink::WebRTCVoidRequest request, bool result) {
+ if (result) {
+ request.RequestSucceeded();
+ } else {
+ request.RequestFailed(
+ webrtc::RTCError(webrtc::RTCErrorType::INVALID_MODIFICATION));
+ }
+}
+
+void OnSetParametersCompleted(blink::WebRTCVoidRequest request,
+ webrtc::RTCError result) {
+ if (result.ok())
+ request.RequestSucceeded();
+ else
+ request.RequestFailed(result);
+}
+
+} // namespace
+
+RtpSenderState::RtpSenderState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ std::vector<std::string> stream_ids)
+ : main_task_runner_(std::move(main_task_runner)),
+ signaling_task_runner_(std::move(signaling_task_runner)),
+ webrtc_sender_(std::move(webrtc_sender)),
+ webrtc_dtls_transport_(webrtc_sender_->dtls_transport()),
+ webrtc_dtls_transport_information_(webrtc::DtlsTransportState::kNew),
+ is_initialized_(false),
+ track_ref_(std::move(track_ref)),
+ stream_ids_(std::move(stream_ids)) {
+ DCHECK(main_task_runner_);
+ DCHECK(signaling_task_runner_);
+ DCHECK(webrtc_sender_);
+ if (webrtc_dtls_transport_) {
+ webrtc_dtls_transport_information_ = webrtc_dtls_transport_->Information();
+ }
+}
+
+RtpSenderState::RtpSenderState(RtpSenderState&& other)
+ : main_task_runner_(other.main_task_runner_),
+ signaling_task_runner_(other.signaling_task_runner_),
+ webrtc_sender_(std::move(other.webrtc_sender_)),
+ webrtc_dtls_transport_(std::move(other.webrtc_dtls_transport_)),
+ webrtc_dtls_transport_information_(
+ other.webrtc_dtls_transport_information_),
+ is_initialized_(other.is_initialized_),
+ track_ref_(std::move(other.track_ref_)),
+ stream_ids_(std::move(other.stream_ids_)) {
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+}
+
+RtpSenderState::~RtpSenderState() {
+ // It's OK to not be on the main thread if this state has been moved, in which
+ // case |main_task_runner_| is null.
+ DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread());
+}
+
+RtpSenderState& RtpSenderState::operator=(RtpSenderState&& other) {
+ DCHECK_EQ(main_task_runner_, other.main_task_runner_);
+ DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_);
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+ webrtc_sender_ = std::move(other.webrtc_sender_);
+ webrtc_dtls_transport_ = std::move(other.webrtc_dtls_transport_);
+ webrtc_dtls_transport_information_ = other.webrtc_dtls_transport_information_;
+ is_initialized_ = other.is_initialized_;
+ track_ref_ = std::move(other.track_ref_);
+ stream_ids_ = std::move(other.stream_ids_);
+ return *this;
+}
+
+bool RtpSenderState::is_initialized() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return is_initialized_;
+}
+
+void RtpSenderState::Initialize() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (track_ref_)
+ track_ref_->InitializeOnMainThread();
+ is_initialized_ = true;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> RtpSenderState::main_task_runner()
+ const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return main_task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RtpSenderState::signaling_task_runner() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return signaling_task_runner_;
+}
+
+scoped_refptr<webrtc::RtpSenderInterface> RtpSenderState::webrtc_sender()
+ const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_sender_;
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+RtpSenderState::webrtc_dtls_transport() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_dtls_transport_;
+}
+
+webrtc::DtlsTransportInformation
+RtpSenderState::webrtc_dtls_transport_information() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_dtls_transport_information_;
+}
+
+const std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>&
+RtpSenderState::track_ref() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return track_ref_;
+}
+
+void RtpSenderState::set_track_ref(
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(!is_initialized_ || !track_ref || track_ref->is_initialized());
+ track_ref_ = std::move(track_ref);
+}
+
+std::vector<std::string> RtpSenderState::stream_ids() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return stream_ids_;
+}
+
+class RTCRtpSenderImpl::RTCRtpSenderInternal
+ : public WTF::ThreadSafeRefCounted<
+ RTCRtpSenderImpl::RTCRtpSenderInternal,
+ RTCRtpSenderImpl::RTCRtpSenderInternalTraits> {
+ public:
+ RTCRtpSenderInternal(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpSenderState state)
+ : native_peer_connection_(std::move(native_peer_connection)),
+ track_map_(std::move(track_map)),
+ main_task_runner_(state.main_task_runner()),
+ signaling_task_runner_(state.signaling_task_runner()),
+ webrtc_sender_(state.webrtc_sender()),
+ state_(std::move(state)) {
+ DCHECK(track_map_);
+ DCHECK(state_.is_initialized());
+ }
+
+ const RtpSenderState& state() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return state_;
+ }
+
+ void set_state(RtpSenderState state) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(state.main_task_runner(), main_task_runner_);
+ DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_);
+ DCHECK(state.webrtc_sender() == webrtc_sender_);
+ DCHECK(state.is_initialized());
+ state_ = std::move(state);
+ }
+
+ void ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref;
+ webrtc::MediaStreamTrackInterface* webrtc_track = nullptr;
+ if (!with_track.IsNull()) {
+ track_ref = track_map_->GetOrCreateLocalTrackAdapter(with_track);
+ webrtc_track = track_ref->webrtc_track();
+ }
+ signaling_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCRtpSenderImpl::RTCRtpSenderInternal::
+ ReplaceTrackOnSignalingThread,
+ this, std::move(track_ref),
+ base::Unretained(webrtc_track), std::move(callback)));
+ }
+
+ std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() const {
+ // The webrtc_sender() is a proxy, so this is a blocking call to the
+ // webrtc signalling thread.
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ auto dtmf_sender = webrtc_sender_->GetDtmfSender();
+ return blink::CreateRTCDTMFSenderHandler(main_task_runner_, dtmf_sender);
+ }
+
+ std::unique_ptr<webrtc::RtpParameters> GetParameters() {
+ // The webrtc_sender() is a proxy, so this is a blocking call to the
+ // webrtc signalling thread.
+ parameters_ = webrtc_sender_->GetParameters();
+ return std::make_unique<webrtc::RtpParameters>(parameters_);
+ }
+
+ void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters> encodings,
+ webrtc::DegradationPreference degradation_preference,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+
+ webrtc::RtpParameters new_parameters = parameters_;
+
+ new_parameters.degradation_preference = degradation_preference;
+
+ for (std::size_t i = 0; i < new_parameters.encodings.size(); ++i) {
+ // Encodings have other parameters in the native layer that aren't exposed
+ // to the blink layer. So instead of copying the new struct over the old
+ // one, we copy the members one by one over the old struct, effectively
+ // patching the changes done by the user.
+ const auto& encoding = encodings[i];
+ new_parameters.encodings[i].codec_payload_type =
+ encoding.codec_payload_type;
+ new_parameters.encodings[i].dtx = encoding.dtx;
+ new_parameters.encodings[i].active = encoding.active;
+ new_parameters.encodings[i].bitrate_priority = encoding.bitrate_priority;
+ new_parameters.encodings[i].network_priority = encoding.network_priority;
+ new_parameters.encodings[i].ptime = encoding.ptime;
+ new_parameters.encodings[i].max_bitrate_bps = encoding.max_bitrate_bps;
+ new_parameters.encodings[i].max_framerate = encoding.max_framerate;
+ new_parameters.encodings[i].rid = encoding.rid;
+ new_parameters.encodings[i].scale_resolution_down_by =
+ encoding.scale_resolution_down_by;
+ }
+
+ signaling_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCRtpSenderImpl::RTCRtpSenderInternal::
+ SetParametersOnSignalingThread,
+ this, std::move(new_parameters), std::move(callback)));
+ }
+
+ void GetStats(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ signaling_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSenderImpl::RTCRtpSenderInternal::GetStatsOnSignalingThread,
+ this, std::move(callback), exposed_group_ids));
+ }
+
+ bool RemoveFromPeerConnection(webrtc::PeerConnectionInterface* pc) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (!pc->RemoveTrack(webrtc_sender_.get()))
+ return false;
+ // TODO(hbos): Removing the track should null the sender's track, or we
+ // should do |webrtc_sender_->SetTrack(null)| but that is not allowed on a
+ // stopped sender. In the meantime, there is a discrepancy between layers.
+ // https://crbug.com/webrtc/7945
+ state_.set_track_ref(nullptr);
+ return true;
+ }
+
+ void SetStreams(std::vector<std::string> stream_ids) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ signaling_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&RTCRtpSenderImpl::RTCRtpSenderInternal::
+ SetStreamsOnSignalingThread,
+ this, std::move(stream_ids)));
+ }
+
+ private:
+ friend class WTF::ThreadSafeRefCounted<RTCRtpSenderInternal,
+ RTCRtpSenderInternalTraits>;
+ friend struct RTCRtpSenderImpl::RTCRtpSenderInternalTraits;
+
+ ~RTCRtpSenderInternal() {
+ // Ensured by destructor traits.
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ }
+
+ // |webrtc_track| is passed as an argument because |track_ref->webrtc_track()|
+ // cannot be accessed on the signaling thread. https://crbug.com/756436
+ void ReplaceTrackOnSignalingThread(
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ webrtc::MediaStreamTrackInterface* webrtc_track,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(signaling_task_runner_->BelongsToCurrentThread());
+ bool result = webrtc_sender_->SetTrack(webrtc_track);
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSenderImpl::RTCRtpSenderInternal::ReplaceTrackCallback, this,
+ result, std::move(track_ref), std::move(callback)));
+ }
+
+ void ReplaceTrackCallback(
+ bool result,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref,
+ base::OnceCallback<void(bool)> callback) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (result)
+ state_.set_track_ref(std::move(track_ref));
+ std::move(callback).Run(result);
+ }
+
+ void GetStatsOnSignalingThread(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ native_peer_connection_->GetStats(
+ webrtc_sender_.get(),
+ blink::CreateRTCStatsCollectorCallback(
+ main_task_runner_, std::move(callback), exposed_group_ids));
+ }
+
+ void SetParametersOnSignalingThread(
+ webrtc::RtpParameters parameters,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(signaling_task_runner_->BelongsToCurrentThread());
+ webrtc::RTCError result = webrtc_sender_->SetParameters(parameters);
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSenderImpl::RTCRtpSenderInternal::SetParametersCallback,
+ this, std::move(result), std::move(callback)));
+ }
+
+ void SetParametersCallback(
+ webrtc::RTCError result,
+ base::OnceCallback<void(webrtc::RTCError)> callback) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ std::move(callback).Run(std::move(result));
+ }
+
+ void SetStreamsOnSignalingThread(std::vector<std::string> stream_ids) {
+ DCHECK(signaling_task_runner_->BelongsToCurrentThread());
+ webrtc_sender_->SetStreams(stream_ids);
+ }
+
+ const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
+ const scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map_;
+ // Task runners and webrtc sender: Same information as stored in
+ // |state_| but const and safe to touch on the signaling thread to
+ // avoid race with set_state().
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ const scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_;
+ RtpSenderState state_;
+ webrtc::RtpParameters parameters_;
+};
+
+struct RTCRtpSenderImpl::RTCRtpSenderInternalTraits {
+ static void Destruct(const RTCRtpSenderInternal* sender) {
+ // RTCRtpSenderInternal owns AdapterRefs which have to be destroyed on the
+ // main thread, this ensures delete always happens there.
+ if (!sender->main_task_runner_->BelongsToCurrentThread()) {
+ sender->main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpSenderImpl::RTCRtpSenderInternalTraits::Destruct,
+ base::Unretained(sender)));
+ return;
+ }
+ delete sender;
+ }
+};
+
+uintptr_t RTCRtpSenderImpl::getId(
+ const webrtc::RtpSenderInterface* webrtc_sender) {
+ return reinterpret_cast<uintptr_t>(webrtc_sender);
+}
+
+RTCRtpSenderImpl::RTCRtpSenderImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpSenderState state)
+ : internal_(base::MakeRefCounted<RTCRtpSenderInternal>(
+ std::move(native_peer_connection),
+ std::move(track_map),
+ std::move(state))) {}
+
+RTCRtpSenderImpl::RTCRtpSenderImpl(const RTCRtpSenderImpl& other)
+ : internal_(other.internal_) {}
+
+RTCRtpSenderImpl::~RTCRtpSenderImpl() {}
+
+RTCRtpSenderImpl& RTCRtpSenderImpl::operator=(const RTCRtpSenderImpl& other) {
+ internal_ = other.internal_;
+ return *this;
+}
+
+const RtpSenderState& RTCRtpSenderImpl::state() const {
+ return internal_->state();
+}
+
+void RTCRtpSenderImpl::set_state(RtpSenderState state) {
+ internal_->set_state(std::move(state));
+}
+
+std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSenderImpl::ShallowCopy() const {
+ return std::make_unique<RTCRtpSenderImpl>(*this);
+}
+
+uintptr_t RTCRtpSenderImpl::Id() const {
+ return getId(internal_->state().webrtc_sender().get());
+}
+
+rtc::scoped_refptr<webrtc::DtlsTransportInterface>
+RTCRtpSenderImpl::DtlsTransport() {
+ return internal_->state().webrtc_dtls_transport();
+}
+
+webrtc::DtlsTransportInformation RTCRtpSenderImpl::DtlsTransportInformation() {
+ return internal_->state().webrtc_dtls_transport_information();
+}
+
+blink::WebMediaStreamTrack RTCRtpSenderImpl::Track() const {
+ const auto& track_ref = internal_->state().track_ref();
+ return track_ref ? track_ref->web_track() : blink::WebMediaStreamTrack();
+}
+
+blink::WebVector<blink::WebString> RTCRtpSenderImpl::StreamIds() const {
+ const auto& stream_ids = internal_->state().stream_ids();
+ blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size());
+ for (size_t i = 0; i < stream_ids.size(); ++i)
+ web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]);
+ return web_stream_ids;
+}
+
+void RTCRtpSenderImpl::ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ blink::WebRTCVoidRequest request) {
+ internal_->ReplaceTrack(
+ std::move(with_track),
+ base::BindOnce(&OnReplaceTrackCompleted, std::move(request)));
+}
+
+std::unique_ptr<blink::WebRTCDTMFSenderHandler>
+RTCRtpSenderImpl::GetDtmfSender() const {
+ return internal_->GetDtmfSender();
+}
+
+std::unique_ptr<webrtc::RtpParameters> RTCRtpSenderImpl::GetParameters() const {
+ return internal_->GetParameters();
+}
+
+void RTCRtpSenderImpl::SetParameters(
+ blink::WebVector<webrtc::RtpEncodingParameters> encodings,
+ webrtc::DegradationPreference degradation_preference,
+ blink::WebRTCVoidRequest request) {
+ internal_->SetParameters(
+ std::move(encodings), degradation_preference,
+ base::BindOnce(&OnSetParametersCompleted, std::move(request)));
+}
+
+void RTCRtpSenderImpl::GetStats(
+ blink::WebRTCStatsReportCallback callback,
+ const blink::WebVector<webrtc::NonStandardGroupId>& exposed_group_ids) {
+ internal_->GetStats(std::move(callback), exposed_group_ids);
+}
+
+void RTCRtpSenderImpl::SetStreams(
+ const blink::WebVector<blink::WebString>& stream_ids) {
+ std::vector<std::string> ids;
+ for (auto stream_id : stream_ids)
+ ids.emplace_back(stream_id.Utf8());
+
+ internal_->SetStreams(std::move(ids));
+}
+
+void RTCRtpSenderImpl::ReplaceTrack(blink::WebMediaStreamTrack with_track,
+ base::OnceCallback<void(bool)> callback) {
+ internal_->ReplaceTrack(std::move(with_track), std::move(callback));
+}
+
+bool RTCRtpSenderImpl::RemoveFromPeerConnection(
+ webrtc::PeerConnectionInterface* pc) {
+ return internal_->RemoveFromPeerConnection(pc);
+}
+
+RTCRtpSenderOnlyTransceiver::RTCRtpSenderOnlyTransceiver(
+ std::unique_ptr<blink::WebRTCRtpSender> sender)
+ : sender_(std::move(sender)) {
+ DCHECK(sender_);
+}
+
+RTCRtpSenderOnlyTransceiver::~RTCRtpSenderOnlyTransceiver() {}
+
+blink::WebRTCRtpTransceiverImplementationType
+RTCRtpSenderOnlyTransceiver::ImplementationType() const {
+ return blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly;
+}
+
+uintptr_t RTCRtpSenderOnlyTransceiver::Id() const {
+ NOTIMPLEMENTED();
+ return 0u;
+}
+
+blink::WebString RTCRtpSenderOnlyTransceiver::Mid() const {
+ NOTIMPLEMENTED();
+ return blink::WebString();
+}
+
+std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSenderOnlyTransceiver::Sender()
+ const {
+ return sender_->ShallowCopy();
+}
+
+std::unique_ptr<blink::WebRTCRtpReceiver>
+RTCRtpSenderOnlyTransceiver::Receiver() const {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+bool RTCRtpSenderOnlyTransceiver::Stopped() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+webrtc::RtpTransceiverDirection RTCRtpSenderOnlyTransceiver::Direction() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+void RTCRtpSenderOnlyTransceiver::SetDirection(
+ webrtc::RtpTransceiverDirection direction) {
+ NOTIMPLEMENTED();
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpSenderOnlyTransceiver::CurrentDirection() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpSenderOnlyTransceiver::FiredDirection() const {
+ NOTIMPLEMENTED();
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+webrtc::RTCError RTCRtpSenderOnlyTransceiver::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability>) {
+ NOTIMPLEMENTED();
+ return {};
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
new file mode 100644
index 00000000000..e2f91b39287
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
@@ -0,0 +1,261 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_sender_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_rtc_stats.h"
+#include "third_party/blink/public/platform/web_rtc_void_request.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/webrtc/api/stats/rtc_stats_report.h"
+#include "third_party/webrtc/api/stats/rtcstats_objects.h"
+#include "third_party/webrtc/api/test/mock_rtpsender.h"
+
+using ::testing::_;
+using ::testing::Return;
+
+namespace blink {
+
+class RTCRtpSenderImplTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ track_map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_thread_);
+ peer_connection_ = new rtc::RefCountedObject<blink::MockPeerConnectionImpl>(
+ dependency_factory_.get(), nullptr);
+ mock_webrtc_sender_ = new rtc::RefCountedObject<webrtc::MockRtpSender>();
+ }
+
+ void TearDown() override {
+ sender_.reset();
+ // Syncing up with the signaling thread ensures any pending operations on
+ // that thread are executed. If they post back to the main thread, such as
+ // the sender's destructor traits, this is allowed to execute before the
+ // test shuts down the threads.
+ SyncWithSignalingThread();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ // Wait for the signaling thread to perform any queued tasks, executing tasks
+ // posted to the current thread in the meantime while waiting.
+ void SyncWithSignalingThread() const {
+ base::RunLoop run_loop;
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ blink::WebMediaStreamTrack CreateWebTrack(const std::string& id) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(
+ blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"), false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ std::unique_ptr<RTCRtpSenderImpl> CreateSender(
+ blink::WebMediaStreamTrack web_track) {
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref;
+ if (!web_track.IsNull()) {
+ track_ref = track_map_->GetOrCreateLocalTrackAdapter(web_track);
+ DCHECK(track_ref->is_initialized());
+ }
+ RtpSenderState sender_state(
+ main_thread_, dependency_factory_->GetWebRtcSignalingTaskRunner(),
+ mock_webrtc_sender_.get(), std::move(track_ref),
+ std::vector<std::string>());
+ sender_state.Initialize();
+ return std::make_unique<RTCRtpSenderImpl>(
+ peer_connection_.get(), track_map_, std::move(sender_state));
+ }
+
+ // Calls replaceTrack(), which is asynchronous, returning a callback that when
+ // invoked waits for (run-loops) the operation to complete and returns whether
+ // replaceTrack() was successful.
+ base::OnceCallback<bool()> ReplaceTrack(
+ blink::WebMediaStreamTrack web_track) {
+ std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
+ std::unique_ptr<bool> result_holder(new bool());
+ // On complete, |*result_holder| is set with the result of replaceTrack()
+ // and the |run_loop| quit.
+ sender_->ReplaceTrack(
+ web_track, base::BindOnce(&RTCRtpSenderImplTest::CallbackOnComplete,
+ base::Unretained(this), result_holder.get(),
+ run_loop.get()));
+ // When the resulting callback is invoked, waits for |run_loop| to complete
+ // and returns |*result_holder|.
+ return base::BindOnce(&RTCRtpSenderImplTest::RunLoopAndReturnResult,
+ base::Unretained(this), std::move(result_holder),
+ std::move(run_loop));
+ }
+
+ scoped_refptr<blink::WebRTCStatsReportObtainer> CallGetStats() {
+ scoped_refptr<blink::WebRTCStatsReportObtainer> obtainer =
+ new blink::WebRTCStatsReportObtainer();
+ sender_->GetStats(obtainer->GetStatsCallbackWrapper(), {});
+ return obtainer;
+ }
+
+ protected:
+ void CallbackOnComplete(bool* result_out,
+ base::RunLoop* run_loop,
+ bool result) {
+ *result_out = result;
+ run_loop->Quit();
+ }
+
+ bool RunLoopAndReturnResult(std::unique_ptr<bool> result_holder,
+ std::unique_ptr<base::RunLoop> run_loop) {
+ run_loop->Run();
+ return *result_holder;
+ }
+
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map_;
+ rtc::scoped_refptr<blink::MockPeerConnectionImpl> peer_connection_;
+ rtc::scoped_refptr<webrtc::MockRtpSender> mock_webrtc_sender_;
+ std::unique_ptr<RTCRtpSenderImpl> sender_;
+};
+
+TEST_F(RTCRtpSenderImplTest, CreateSender) {
+ auto web_track = CreateWebTrack("track_id");
+ sender_ = CreateSender(web_track);
+ EXPECT_FALSE(sender_->Track().IsNull());
+ EXPECT_EQ(web_track.UniqueId(), sender_->Track().UniqueId());
+}
+
+TEST_F(RTCRtpSenderImplTest, CreateSenderWithNullTrack) {
+ blink::WebMediaStreamTrack null_track;
+ sender_ = CreateSender(null_track);
+ EXPECT_TRUE(sender_->Track().IsNull());
+}
+
+TEST_F(RTCRtpSenderImplTest, ReplaceTrackSetsTrack) {
+ auto web_track1 = CreateWebTrack("track1");
+ sender_ = CreateSender(web_track1);
+
+ auto web_track2 = CreateWebTrack("track2");
+ EXPECT_CALL(*mock_webrtc_sender_, SetTrack(_)).WillOnce(Return(true));
+ auto replaceTrackRunLoopAndGetResult = ReplaceTrack(web_track2);
+ EXPECT_TRUE(std::move(replaceTrackRunLoopAndGetResult).Run());
+ ASSERT_FALSE(sender_->Track().IsNull());
+ EXPECT_EQ(web_track2.UniqueId(), sender_->Track().UniqueId());
+}
+
+TEST_F(RTCRtpSenderImplTest, ReplaceTrackWithNullTrack) {
+ auto web_track = CreateWebTrack("track_id");
+ sender_ = CreateSender(web_track);
+
+ blink::WebMediaStreamTrack null_track;
+ EXPECT_CALL(*mock_webrtc_sender_, SetTrack(_)).WillOnce(Return(true));
+ auto replaceTrackRunLoopAndGetResult = ReplaceTrack(null_track);
+ EXPECT_TRUE(std::move(replaceTrackRunLoopAndGetResult).Run());
+ EXPECT_TRUE(sender_->Track().IsNull());
+}
+
+TEST_F(RTCRtpSenderImplTest, ReplaceTrackCanFail) {
+ auto web_track = CreateWebTrack("track_id");
+ sender_ = CreateSender(web_track);
+ ASSERT_FALSE(sender_->Track().IsNull());
+ EXPECT_EQ(web_track.UniqueId(), sender_->Track().UniqueId());
+
+ blink::WebMediaStreamTrack null_track;
+ EXPECT_CALL(*mock_webrtc_sender_, SetTrack(_)).WillOnce(Return(false));
+ auto replaceTrackRunLoopAndGetResult = ReplaceTrack(null_track);
+ EXPECT_FALSE(std::move(replaceTrackRunLoopAndGetResult).Run());
+ // The track should not have been set.
+ ASSERT_FALSE(sender_->Track().IsNull());
+ EXPECT_EQ(web_track.UniqueId(), sender_->Track().UniqueId());
+}
+
+TEST_F(RTCRtpSenderImplTest, ReplaceTrackIsNotSetSynchronously) {
+ auto web_track1 = CreateWebTrack("track1");
+ sender_ = CreateSender(web_track1);
+
+ auto web_track2 = CreateWebTrack("track2");
+ EXPECT_CALL(*mock_webrtc_sender_, SetTrack(_)).WillOnce(Return(true));
+ auto replaceTrackRunLoopAndGetResult = ReplaceTrack(web_track2);
+ // The track should not be set until the run loop has executed.
+ ASSERT_FALSE(sender_->Track().IsNull());
+ EXPECT_NE(web_track2.UniqueId(), sender_->Track().UniqueId());
+ // Wait for operation to run to ensure EXPECT_CALL is satisfied.
+ std::move(replaceTrackRunLoopAndGetResult).Run();
+}
+
+TEST_F(RTCRtpSenderImplTest, GetStats) {
+ auto web_track = CreateWebTrack("track_id");
+ sender_ = CreateSender(web_track);
+
+ // Make the mock return a blink version of the |webtc_report|. The mock does
+ // not perform any stats filtering, we just set it to a dummy value.
+ rtc::scoped_refptr<webrtc::RTCStatsReport> webrtc_report =
+ webrtc::RTCStatsReport::Create(0u);
+ webrtc_report->AddStats(
+ std::make_unique<webrtc::RTCOutboundRTPStreamStats>("stats-id", 1234u));
+ peer_connection_->SetGetStatsReport(webrtc_report);
+
+ auto obtainer = CallGetStats();
+ // Make sure the operation is async.
+ EXPECT_FALSE(obtainer->report());
+ // Wait for the report, this performs the necessary run-loop.
+ auto* report = obtainer->WaitForReport();
+ EXPECT_TRUE(report);
+
+ // Verify dummy value.
+ EXPECT_EQ(report->Size(), 1u);
+ auto stats = report->GetStats(blink::WebString::FromUTF8("stats-id"));
+ EXPECT_TRUE(stats);
+ EXPECT_EQ(stats->Timestamp(), 1.234);
+}
+
+TEST_F(RTCRtpSenderImplTest, CopiedSenderSharesInternalStates) {
+ auto web_track = CreateWebTrack("track_id");
+ sender_ = CreateSender(web_track);
+ auto copy = std::make_unique<RTCRtpSenderImpl>(*sender_);
+ // Copy shares original's ID.
+ EXPECT_EQ(sender_->Id(), copy->Id());
+
+ blink::WebMediaStreamTrack null_track;
+ EXPECT_CALL(*mock_webrtc_sender_, SetTrack(_)).WillOnce(Return(true));
+ auto replaceTrackRunLoopAndGetResult = ReplaceTrack(null_track);
+ EXPECT_TRUE(std::move(replaceTrackRunLoopAndGetResult).Run());
+
+ // Both original and copy shows a modified state.
+ EXPECT_TRUE(sender_->Track().IsNull());
+ EXPECT_TRUE(copy->Track().IsNull());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc
new file mode 100644
index 00000000000..0a68985d6e2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc
@@ -0,0 +1,384 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
+#include "third_party/webrtc/api/scoped_refptr.h"
+
+namespace blink {
+
+RtpTransceiverState::RtpTransceiverState(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
+ scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver,
+ base::Optional<blink::RtpSenderState> sender_state,
+ base::Optional<blink::RtpReceiverState> receiver_state,
+ base::Optional<std::string> mid,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction,
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction)
+ : main_task_runner_(std::move(main_task_runner)),
+ signaling_task_runner_(std::move(signaling_task_runner)),
+ webrtc_transceiver_(std::move(webrtc_transceiver)),
+ is_initialized_(false),
+ sender_state_(std::move(sender_state)),
+ receiver_state_(std::move(receiver_state)),
+ mid_(std::move(mid)),
+ stopped_(std::move(stopped)),
+ direction_(std::move(direction)),
+ current_direction_(std::move(current_direction)),
+ fired_direction_(std::move(fired_direction)) {
+ DCHECK(main_task_runner_);
+ DCHECK(signaling_task_runner_);
+ DCHECK(webrtc_transceiver_);
+}
+
+RtpTransceiverState::RtpTransceiverState(RtpTransceiverState&& other)
+ : main_task_runner_(other.main_task_runner_),
+ signaling_task_runner_(other.signaling_task_runner_),
+ webrtc_transceiver_(std::move(other.webrtc_transceiver_)),
+ is_initialized_(other.is_initialized_),
+ sender_state_(std::move(other.sender_state_)),
+ receiver_state_(std::move(other.receiver_state_)),
+ mid_(std::move(other.mid_)),
+ stopped_(std::move(other.stopped_)),
+ direction_(std::move(other.direction_)),
+ current_direction_(std::move(other.current_direction_)),
+ fired_direction_(std::move(other.fired_direction_)) {
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+}
+
+RtpTransceiverState::~RtpTransceiverState() {
+ // It's OK to not be on the main thread if this state has been moved, in which
+ // case |main_task_runner_| is null.
+ DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread());
+}
+
+RtpTransceiverState& RtpTransceiverState::operator=(
+ RtpTransceiverState&& other) {
+ DCHECK_EQ(main_task_runner_, other.main_task_runner_);
+ DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_);
+ // Need to be on main thread for sender/receiver state's destructor that can
+ // be triggered by replacing .
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+ webrtc_transceiver_ = std::move(other.webrtc_transceiver_);
+ is_initialized_ = other.is_initialized_;
+ sender_state_ = std::move(other.sender_state_);
+ receiver_state_ = std::move(other.receiver_state_);
+ mid_ = std::move(other.mid_);
+ stopped_ = std::move(other.stopped_);
+ direction_ = std::move(other.direction_);
+ current_direction_ = std::move(other.current_direction_);
+ fired_direction_ = std::move(other.fired_direction_);
+ return *this;
+}
+
+bool RtpTransceiverState::is_initialized() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return is_initialized_;
+}
+
+void RtpTransceiverState::Initialize() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ if (sender_state_)
+ sender_state_->Initialize();
+ if (receiver_state_)
+ receiver_state_->Initialize();
+ is_initialized_ = true;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RtpTransceiverState::main_task_runner() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return main_task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RtpTransceiverState::signaling_task_runner() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return signaling_task_runner_;
+}
+
+scoped_refptr<webrtc::RtpTransceiverInterface>
+RtpTransceiverState::webrtc_transceiver() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return webrtc_transceiver_;
+}
+
+const base::Optional<blink::RtpSenderState>& RtpTransceiverState::sender_state()
+ const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return sender_state_;
+}
+
+blink::RtpSenderState RtpTransceiverState::MoveSenderState() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ base::Optional<blink::RtpSenderState> temp(base::nullopt);
+ sender_state_.swap(temp);
+ return *std::move(temp);
+}
+
+const base::Optional<blink::RtpReceiverState>&
+RtpTransceiverState::receiver_state() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return receiver_state_;
+}
+
+blink::RtpReceiverState RtpTransceiverState::MoveReceiverState() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ base::Optional<blink::RtpReceiverState> temp(base::nullopt);
+ receiver_state_.swap(temp);
+ return *std::move(temp);
+}
+
+base::Optional<std::string> RtpTransceiverState::mid() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return mid_;
+}
+
+bool RtpTransceiverState::stopped() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return stopped_;
+}
+
+webrtc::RtpTransceiverDirection RtpTransceiverState::direction() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return direction_;
+}
+
+void RtpTransceiverState::set_direction(
+ webrtc::RtpTransceiverDirection direction) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ direction_ = direction;
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RtpTransceiverState::current_direction() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return current_direction_;
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RtpTransceiverState::fired_direction() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return fired_direction_;
+}
+
+class RTCRtpTransceiverImpl::RTCRtpTransceiverInternal
+ : public WTF::ThreadSafeRefCounted<
+ RTCRtpTransceiverImpl::RTCRtpTransceiverInternal,
+ RTCRtpTransceiverImpl::RTCRtpTransceiverInternalTraits> {
+ public:
+ RTCRtpTransceiverInternal(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpTransceiverState state)
+ : main_task_runner_(state.main_task_runner()),
+ signaling_task_runner_(state.signaling_task_runner()),
+ webrtc_transceiver_(state.webrtc_transceiver()),
+ state_(std::move(state)) {
+ sender_ = std::make_unique<blink::RTCRtpSenderImpl>(
+ native_peer_connection, track_map, state_.MoveSenderState());
+ receiver_ = std::make_unique<blink::RTCRtpReceiverImpl>(
+ native_peer_connection, state_.MoveReceiverState());
+ }
+
+ const RtpTransceiverState& state() const {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return state_;
+ }
+
+ void set_state(RtpTransceiverState state,
+ TransceiverStateUpdateMode update_mode) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(state.main_task_runner(), main_task_runner_);
+ DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_);
+ DCHECK(state.webrtc_transceiver() == webrtc_transceiver_);
+ DCHECK(state.is_initialized());
+ auto previous_direction = state_.direction();
+ state_ = std::move(state);
+ auto sender_state = state_.MoveSenderState();
+ if (update_mode == TransceiverStateUpdateMode::kSetDescription) {
+ // setLocalDescription() and setRemoteDescription() cannot modify
+ // "sender.track" or "direction", so this part of the state information is
+ // either identical to the current state or out-dated information.
+ // Surfacing out-dated information has caused crashes and other problems,
+ // see https://crbug.com/950280.
+ sender_state.set_track_ref(sender_->state().track_ref()
+ ? sender_->state().track_ref()->Copy()
+ : nullptr);
+ state_.set_direction(previous_direction);
+ }
+ sender_->set_state(std::move(sender_state));
+ receiver_->set_state(state_.MoveReceiverState());
+ }
+
+ blink::RTCRtpSenderImpl* content_sender() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return sender_.get();
+ }
+
+ blink::RTCRtpReceiverImpl* content_receiver() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return receiver_.get();
+ }
+
+ void SetDirection(webrtc::RtpTransceiverDirection direction) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ // This implicitly performs a blocking invoke on the webrtc signaling thread
+ // due to use of PROXY references for |webrtc_transceiver_|.
+ webrtc_transceiver_->SetDirection(direction);
+ state_.set_direction(webrtc_transceiver_->direction());
+ }
+
+ webrtc::RTCError setCodecPreferences(
+ std::vector<webrtc::RtpCodecCapability> codec_preferences) {
+ return webrtc_transceiver_->SetCodecPreferences(codec_preferences);
+ }
+
+ private:
+ friend class WTF::ThreadSafeRefCounted<RTCRtpTransceiverInternal,
+ RTCRtpTransceiverInternalTraits>;
+ friend struct RTCRtpTransceiverImpl::RTCRtpTransceiverInternalTraits;
+
+ ~RTCRtpTransceiverInternal() {
+ // Ensured by destructor traits.
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ }
+
+ // Task runners and webrtc transceiver: Same information as stored in |state_|
+ // but const and safe to touch on the signaling thread to avoid race with
+ // set_state().
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
+ const scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_;
+ RtpTransceiverState state_;
+ std::unique_ptr<blink::RTCRtpSenderImpl> sender_;
+ std::unique_ptr<blink::RTCRtpReceiverImpl> receiver_;
+};
+
+struct RTCRtpTransceiverImpl::RTCRtpTransceiverInternalTraits {
+ static void Destruct(const RTCRtpTransceiverInternal* transceiver) {
+ // RTCRtpTransceiverInternal owns AdapterRefs which have to be destroyed on
+ // the main thread, this ensures delete always happens there.
+ if (!transceiver->main_task_runner_->BelongsToCurrentThread()) {
+ transceiver->main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &RTCRtpTransceiverImpl::RTCRtpTransceiverInternalTraits::Destruct,
+ base::Unretained(transceiver)));
+ return;
+ }
+ delete transceiver;
+ }
+};
+
+uintptr_t RTCRtpTransceiverImpl::GetId(
+ const webrtc::RtpTransceiverInterface* webrtc_transceiver) {
+ return reinterpret_cast<uintptr_t>(webrtc_transceiver);
+}
+
+RTCRtpTransceiverImpl::RTCRtpTransceiverImpl(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map,
+ RtpTransceiverState transceiver_state)
+ : internal_(base::MakeRefCounted<RTCRtpTransceiverInternal>(
+ std::move(native_peer_connection),
+ std::move(track_map),
+ std::move(transceiver_state))) {}
+
+RTCRtpTransceiverImpl::RTCRtpTransceiverImpl(const RTCRtpTransceiverImpl& other)
+ : internal_(other.internal_) {}
+
+RTCRtpTransceiverImpl::~RTCRtpTransceiverImpl() {}
+
+RTCRtpTransceiverImpl& RTCRtpTransceiverImpl::operator=(
+ const RTCRtpTransceiverImpl& other) {
+ internal_ = other.internal_;
+ return *this;
+}
+
+std::unique_ptr<RTCRtpTransceiverImpl> RTCRtpTransceiverImpl::ShallowCopy()
+ const {
+ return std::make_unique<RTCRtpTransceiverImpl>(*this);
+}
+
+const RtpTransceiverState& RTCRtpTransceiverImpl::state() const {
+ return internal_->state();
+}
+
+blink::RTCRtpSenderImpl* RTCRtpTransceiverImpl::content_sender() {
+ return internal_->content_sender();
+}
+
+blink::RTCRtpReceiverImpl* RTCRtpTransceiverImpl::content_receiver() {
+ return internal_->content_receiver();
+}
+
+void RTCRtpTransceiverImpl::set_state(RtpTransceiverState transceiver_state,
+ TransceiverStateUpdateMode update_mode) {
+ internal_->set_state(std::move(transceiver_state), update_mode);
+}
+
+blink::WebRTCRtpTransceiverImplementationType
+RTCRtpTransceiverImpl::ImplementationType() const {
+ return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver;
+}
+
+uintptr_t RTCRtpTransceiverImpl::Id() const {
+ return GetId(internal_->state().webrtc_transceiver().get());
+}
+
+blink::WebString RTCRtpTransceiverImpl::Mid() const {
+ const auto& mid = internal_->state().mid();
+ return mid ? blink::WebString::FromUTF8(*mid)
+ : blink::WebString(); // IsNull()
+}
+
+std::unique_ptr<blink::WebRTCRtpSender> RTCRtpTransceiverImpl::Sender() const {
+ return internal_->content_sender()->ShallowCopy();
+}
+
+std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpTransceiverImpl::Receiver()
+ const {
+ return internal_->content_receiver()->ShallowCopy();
+}
+
+bool RTCRtpTransceiverImpl::Stopped() const {
+ return internal_->state().stopped();
+}
+
+webrtc::RtpTransceiverDirection RTCRtpTransceiverImpl::Direction() const {
+ return internal_->state().direction();
+}
+
+void RTCRtpTransceiverImpl::SetDirection(
+ webrtc::RtpTransceiverDirection direction) {
+ internal_->SetDirection(direction);
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpTransceiverImpl::CurrentDirection() const {
+ return internal_->state().current_direction();
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpTransceiverImpl::FiredDirection() const {
+ return internal_->state().fired_direction();
+}
+
+webrtc::RTCError RTCRtpTransceiverImpl::SetCodecPreferences(
+ blink::WebVector<webrtc::RtpCodecCapability> codec_preferences) {
+ return internal_->setCodecPreferences(codec_preferences.ReleaseVector());
+}
+} // namespace blink
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
new file mode 100644
index 00000000000..c6210503f09
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl_test.cc
@@ -0,0 +1,426 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/rtc_rtp_transceiver_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/webrtc/api/test/mock_rtpreceiver.h"
+#include "third_party/webrtc/api/test/mock_rtpsender.h"
+
+namespace blink {
+
+class RTCRtpTransceiverImplTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ track_map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_task_runner_);
+ peer_connection_ = new rtc::RefCountedObject<blink::MockPeerConnectionImpl>(
+ dependency_factory_.get(), nullptr);
+ }
+
+ void TearDown() override {
+ // Syncing up with the signaling thread ensures any pending operations on
+ // that thread are executed. If they post back to the main thread, such as
+ // the sender or receiver destructor traits, this is allowed to execute
+ // before the test shuts down the threads.
+ SyncWithSignalingThread();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ // Wait for the signaling thread to perform any queued tasks, executing tasks
+ // posted to the current thread in the meantime while waiting.
+ void SyncWithSignalingThread() const {
+ base::RunLoop run_loop;
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const {
+ return dependency_factory_->GetWebRtcSignalingTaskRunner();
+ }
+
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ CreateLocalTrackAndAdapter(const std::string& id) {
+ return track_map_->GetOrCreateLocalTrackAdapter(CreateBlinkLocalTrack(id));
+ }
+
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ CreateRemoteTrackAndAdapter(const std::string& id) {
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create(id).get();
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ track_ref;
+ base::RunLoop run_loop;
+ signaling_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RTCRtpTransceiverImplTest::
+ CreateRemoteTrackAdapterOnSignalingThread,
+ base::Unretained(this), std::move(webrtc_track),
+ base::Unretained(&track_ref),
+ base::Unretained(&run_loop)));
+ run_loop.Run();
+ DCHECK(track_ref);
+ return track_ref;
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpSender> CreateWebRtcSender(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::string& stream_id) {
+ return new rtc::RefCountedObject<blink::FakeRtpSender>(
+ std::move(track), std::vector<std::string>({stream_id}));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpReceiver> CreateWebRtcReceiver(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::string& stream_id) {
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ new rtc::RefCountedObject<blink::MockMediaStream>(stream_id));
+ return new rtc::RefCountedObject<blink::FakeRtpReceiver>(
+ track.get(),
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
+ {remote_stream}));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpTransceiver> CreateWebRtcTransceiver(
+ rtc::scoped_refptr<blink::FakeRtpSender> sender,
+ rtc::scoped_refptr<blink::FakeRtpReceiver> receiver,
+ base::Optional<std::string> mid,
+ bool stopped,
+ webrtc::RtpTransceiverDirection direction,
+ base::Optional<webrtc::RtpTransceiverDirection> current_direction) {
+ DCHECK(!sender->track() ||
+ sender->track()->kind() == receiver->track()->kind());
+ return new rtc::RefCountedObject<blink::FakeRtpTransceiver>(
+ receiver->track()->kind() ==
+ webrtc::MediaStreamTrackInterface::kAudioKind
+ ? cricket::MEDIA_TYPE_AUDIO
+ : cricket::MEDIA_TYPE_VIDEO,
+ std::move(sender), std::move(receiver), std::move(mid), stopped,
+ direction, std::move(current_direction));
+ }
+
+ RtpTransceiverState CreateTransceiverState(
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ sender_track_ref,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ receiver_track_ref) {
+ std::vector<std::string> receiver_stream_ids;
+ for (const auto& stream : webrtc_transceiver->receiver()->streams()) {
+ receiver_stream_ids.push_back(stream->id());
+ }
+ return RtpTransceiverState(
+ main_task_runner_, signaling_task_runner(), webrtc_transceiver.get(),
+ blink::RtpSenderState(main_task_runner_, signaling_task_runner(),
+ webrtc_transceiver->sender().get(),
+ std::move(sender_track_ref),
+ webrtc_transceiver->sender()->stream_ids()),
+ blink::RtpReceiverState(main_task_runner_, signaling_task_runner(),
+ webrtc_transceiver->receiver().get(),
+ std::move(receiver_track_ref),
+ std::move(receiver_stream_ids)),
+ blink::ToBaseOptional(webrtc_transceiver->mid()),
+ webrtc_transceiver->stopped(), webrtc_transceiver->direction(),
+ blink::ToBaseOptional(webrtc_transceiver->current_direction()),
+ blink::ToBaseOptional(webrtc_transceiver->fired_direction()));
+ }
+
+ protected:
+ blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(
+ blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"), false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ void CreateRemoteTrackAdapterOnSignalingThread(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>*
+ track_ref,
+ base::RunLoop* run_loop) {
+ *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track.get());
+ run_loop->Quit();
+ }
+
+ private:
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ protected:
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_map_;
+ rtc::scoped_refptr<blink::MockPeerConnectionImpl> peer_connection_;
+};
+
+TEST_F(RTCRtpTransceiverImplTest, InitializeTransceiverState) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"),
+ CreateWebRtcReceiver(remote_track_adapter->webrtc_track(),
+ "remote_stream"),
+ base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv,
+ base::nullopt);
+ RtpTransceiverState transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter),
+ std::move(remote_track_adapter));
+ EXPECT_FALSE(transceiver_state.is_initialized());
+ transceiver_state.Initialize();
+
+ EXPECT_TRUE(transceiver_state.is_initialized());
+ // Inspect sender states.
+ const auto& sender_state = transceiver_state.sender_state();
+ EXPECT_TRUE(sender_state);
+ EXPECT_TRUE(sender_state->is_initialized());
+ const auto& webrtc_sender = webrtc_transceiver->sender();
+ EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get());
+ EXPECT_TRUE(sender_state->track_ref()->is_initialized());
+ EXPECT_EQ(sender_state->track_ref()->webrtc_track(),
+ webrtc_sender->track().get());
+ EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids());
+ // Inspect receiver states.
+ const auto& receiver_state = transceiver_state.receiver_state();
+ EXPECT_TRUE(receiver_state);
+ EXPECT_TRUE(receiver_state->is_initialized());
+ const auto& webrtc_receiver = webrtc_transceiver->receiver();
+ EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get());
+ EXPECT_TRUE(receiver_state->track_ref()->is_initialized());
+ EXPECT_EQ(receiver_state->track_ref()->webrtc_track(),
+ webrtc_receiver->track().get());
+ std::vector<std::string> receiver_stream_ids;
+ for (const auto& stream : webrtc_receiver->streams()) {
+ receiver_stream_ids.push_back(stream->id());
+ }
+ EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids);
+ // Inspect transceiver states.
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.mid(),
+ webrtc_transceiver->mid()));
+ EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped());
+ EXPECT_TRUE(transceiver_state.direction() == webrtc_transceiver->direction());
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.current_direction(),
+ webrtc_transceiver->current_direction()));
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.fired_direction(),
+ webrtc_transceiver->fired_direction()));
+}
+
+TEST_F(RTCRtpTransceiverImplTest, CreateTranceiver) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"),
+ CreateWebRtcReceiver(remote_track_adapter->webrtc_track(),
+ "remote_stream"),
+ base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv,
+ base::nullopt);
+ RtpTransceiverState transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter),
+ std::move(remote_track_adapter));
+ EXPECT_FALSE(transceiver_state.is_initialized());
+ transceiver_state.Initialize();
+
+ RTCRtpTransceiverImpl transceiver(peer_connection_.get(), track_map_,
+ std::move(transceiver_state));
+ EXPECT_TRUE(transceiver.Mid().IsNull());
+ EXPECT_TRUE(transceiver.Sender());
+ EXPECT_TRUE(transceiver.Receiver());
+ EXPECT_FALSE(transceiver.Stopped());
+ EXPECT_EQ(transceiver.Direction(),
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ EXPECT_FALSE(transceiver.CurrentDirection());
+ EXPECT_FALSE(transceiver.FiredDirection());
+}
+
+TEST_F(RTCRtpTransceiverImplTest, ModifyTransceiver) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track");
+ auto webrtc_sender =
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream");
+ auto webrtc_receiver = CreateWebRtcReceiver(
+ remote_track_adapter->webrtc_track(), "remote_stream");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ webrtc_sender, webrtc_receiver, base::nullopt, false,
+ webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt);
+
+ // Create initial state.
+ RtpTransceiverState initial_transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(initial_transceiver_state.is_initialized());
+ initial_transceiver_state.Initialize();
+
+ // Modify the webrtc transceiver and create a new state object for the
+ // modified state.
+ *webrtc_transceiver =
+ *CreateWebRtcTransceiver(webrtc_sender, webrtc_receiver, "MidyMacMidface",
+ true, webrtc::RtpTransceiverDirection::kInactive,
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ RtpTransceiverState modified_transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(modified_transceiver_state.is_initialized());
+ modified_transceiver_state.Initialize();
+
+ // Modifying the webrtc transceiver after the initial state was created should
+ // not have affected the transceiver state.
+ RTCRtpTransceiverImpl transceiver(peer_connection_.get(), track_map_,
+ std::move(initial_transceiver_state));
+ EXPECT_TRUE(transceiver.Mid().IsNull());
+ EXPECT_TRUE(transceiver.Sender());
+ EXPECT_TRUE(transceiver.Receiver());
+ EXPECT_FALSE(transceiver.Stopped());
+ EXPECT_EQ(transceiver.Direction(),
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ EXPECT_FALSE(transceiver.CurrentDirection());
+ EXPECT_FALSE(transceiver.FiredDirection());
+
+ // Setting the state should make the transceiver state up-to-date.
+ transceiver.set_state(std::move(modified_transceiver_state),
+ TransceiverStateUpdateMode::kAll);
+ EXPECT_EQ(transceiver.Mid(), "MidyMacMidface");
+ EXPECT_TRUE(transceiver.Sender());
+ EXPECT_TRUE(transceiver.Receiver());
+ EXPECT_TRUE(transceiver.Stopped());
+ EXPECT_EQ(transceiver.Direction(),
+ webrtc::RtpTransceiverDirection::kInactive);
+ EXPECT_TRUE(transceiver.CurrentDirection() ==
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ EXPECT_FALSE(transceiver.FiredDirection());
+}
+
+TEST_F(RTCRtpTransceiverImplTest, ShallowCopy) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track");
+ auto webrtc_sender =
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream");
+ auto webrtc_receiver = CreateWebRtcReceiver(
+ remote_track_adapter->webrtc_track(), "remote_stream");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ webrtc_sender, webrtc_receiver, base::nullopt, false /* stopped */,
+ webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt);
+
+ std::unique_ptr<RTCRtpTransceiverImpl> transceiver;
+ // Create transceiver.
+ {
+ RtpTransceiverState transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(transceiver_state.is_initialized());
+ transceiver_state.Initialize();
+ transceiver.reset(new RTCRtpTransceiverImpl(
+ peer_connection_.get(), track_map_, std::move(transceiver_state)));
+ }
+ DCHECK(transceiver);
+ EXPECT_FALSE(transceiver->Stopped());
+
+ std::unique_ptr<RTCRtpTransceiverImpl> shallow_copy =
+ transceiver->ShallowCopy();
+ // Modifying the shallow copy should modify the original too since they have a
+ // shared internal state.
+ {
+ // Modify webrtc transceiver to be stopped.
+ *webrtc_transceiver = *CreateWebRtcTransceiver(
+ webrtc_sender, webrtc_receiver, base::nullopt, true /* stopped */,
+ webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt);
+ RtpTransceiverState transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(transceiver_state.is_initialized());
+ transceiver_state.Initialize();
+ // Set the state of the shallow copy.
+ shallow_copy->set_state(std::move(transceiver_state),
+ TransceiverStateUpdateMode::kAll);
+ }
+ EXPECT_TRUE(shallow_copy->Stopped());
+ EXPECT_TRUE(transceiver->Stopped());
+}
+
+TEST_F(RTCRtpTransceiverImplTest, TransceiverStateUpdateModeSetDescription) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track");
+ auto webrtc_sender =
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream");
+ auto webrtc_receiver = CreateWebRtcReceiver(
+ remote_track_adapter->webrtc_track(), "remote_stream");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ webrtc_sender, webrtc_receiver, base::nullopt, false,
+ webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt);
+
+ // Create initial state.
+ RtpTransceiverState initial_transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(initial_transceiver_state.is_initialized());
+ initial_transceiver_state.Initialize();
+
+ // Modify the webrtc transceiver and create a new state object for the
+ // modified state.
+ webrtc_sender->SetTrack(nullptr);
+ *webrtc_transceiver =
+ *CreateWebRtcTransceiver(webrtc_sender, webrtc_receiver, "MidyMacMidface",
+ true, webrtc::RtpTransceiverDirection::kInactive,
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ RtpTransceiverState modified_transceiver_state =
+ CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(),
+ remote_track_adapter->Copy());
+ EXPECT_FALSE(modified_transceiver_state.is_initialized());
+ modified_transceiver_state.Initialize();
+
+ // Construct a transceiver from the initial state.
+ RTCRtpTransceiverImpl transceiver(peer_connection_.get(), track_map_,
+ std::move(initial_transceiver_state));
+ // Setting the state with TransceiverStateUpdateMode::kSetDescription should
+ // make the transceiver state up-to-date, except leaving
+ // "transceiver.direction" and "transceiver.sender.track" unmodified.
+ transceiver.set_state(std::move(modified_transceiver_state),
+ TransceiverStateUpdateMode::kSetDescription);
+ EXPECT_EQ(transceiver.Mid(), "MidyMacMidface");
+ EXPECT_TRUE(transceiver.Sender());
+ EXPECT_TRUE(transceiver.Receiver());
+ EXPECT_TRUE(transceiver.Stopped());
+ EXPECT_TRUE(transceiver.CurrentDirection() ==
+ webrtc::RtpTransceiverDirection::kSendRecv);
+ EXPECT_FALSE(transceiver.FiredDirection());
+ // The sender still has a track, even though the modified state doesn't.
+ EXPECT_FALSE(transceiver.Sender()->Track().IsNull());
+ // The direction still "sendrecv", even though the modified state has
+ // "inactive".
+ EXPECT_EQ(transceiver.Direction(),
+ webrtc::RtpTransceiverDirection::kSendRecv);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..3d996d8ae2d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer.cc
@@ -0,0 +1,240 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h"
+
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/webrtc/api/rtp_transceiver_interface.h"
+#include "third_party/webrtc/api/sctp_transport_interface.h"
+
+namespace blink {
+
+TransceiverStateSurfacer::TransceiverStateSurfacer(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner)
+ : main_task_runner_(std::move(main_task_runner)),
+ signaling_task_runner_(std::move(signaling_task_runner)),
+ is_initialized_(false),
+ states_obtained_(false) {
+ DCHECK(main_task_runner_);
+ DCHECK(signaling_task_runner_);
+}
+
+TransceiverStateSurfacer::TransceiverStateSurfacer(
+ TransceiverStateSurfacer&& other)
+ : main_task_runner_(other.main_task_runner_),
+ signaling_task_runner_(other.signaling_task_runner_),
+ is_initialized_(other.is_initialized_),
+ states_obtained_(other.states_obtained_),
+ sctp_transport_snapshot_(other.sctp_transport_snapshot_),
+ transceiver_states_(std::move(other.transceiver_states_)) {
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+}
+
+TransceiverStateSurfacer::~TransceiverStateSurfacer() {
+ // It's OK to not be on the main thread if this object has been moved, in
+ // which case |main_task_runner_| is null.
+ DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread());
+}
+
+TransceiverStateSurfacer& TransceiverStateSurfacer::operator=(
+ TransceiverStateSurfacer&& other) {
+ main_task_runner_ = other.main_task_runner_;
+ signaling_task_runner_ = other.signaling_task_runner_;
+ states_obtained_ = other.states_obtained_;
+ sctp_transport_snapshot_ = other.sctp_transport_snapshot_;
+ transceiver_states_ = std::move(other.transceiver_states_);
+ // Explicitly null |other|'s task runners for use in destructor.
+ other.main_task_runner_ = nullptr;
+ other.signaling_task_runner_ = nullptr;
+ return *this;
+}
+
+void TransceiverStateSurfacer::Initialize(
+ scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ webrtc_transceivers) {
+ DCHECK(signaling_task_runner_->BelongsToCurrentThread());
+ DCHECK(!is_initialized_);
+ DCHECK(native_peer_connection);
+ sctp_transport_snapshot_.transport =
+ native_peer_connection->GetSctpTransport();
+ if (sctp_transport_snapshot_.transport) {
+ sctp_transport_snapshot_.sctp_transport_state =
+ sctp_transport_snapshot_.transport->Information();
+ if (sctp_transport_snapshot_.sctp_transport_state.dtls_transport()) {
+ sctp_transport_snapshot_.dtls_transport_state =
+ sctp_transport_snapshot_.sctp_transport_state.dtls_transport()
+ ->Information();
+ }
+ }
+
+ for (auto& webrtc_transceiver : webrtc_transceivers) {
+ // Create the sender state.
+ base::Optional<blink::RtpSenderState> sender_state;
+ auto webrtc_sender = webrtc_transceiver->sender();
+ if (webrtc_sender) {
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ sender_track_ref;
+ if (webrtc_sender->track()) {
+ // The track adapter for this track must already exist for us to obtain
+ // it, since this cannot be created from the signaling thread.
+ // TODO(hbos): Consider either making it possible to create local track
+ // adapters on the signaling thread for initialization on the main
+ // thread or wait for Onion Souping to simplify this.
+ // https://crbug.com/787254
+ sender_track_ref =
+ track_adapter_map->GetLocalTrackAdapter(webrtc_sender->track());
+ CHECK(sender_track_ref);
+ }
+ sender_state = blink::RtpSenderState(
+ main_task_runner_, signaling_task_runner_, webrtc_sender.get(),
+ std::move(sender_track_ref), webrtc_sender->stream_ids());
+ }
+ // Create the receiver state.
+ base::Optional<blink::RtpReceiverState> receiver_state;
+ auto webrtc_receiver = webrtc_transceiver->receiver();
+ if (webrtc_receiver) {
+ DCHECK(webrtc_receiver->track());
+ auto receiver_track_ref =
+ track_adapter_map->GetOrCreateRemoteTrackAdapter(
+ webrtc_receiver->track().get());
+ DCHECK(receiver_track_ref);
+ std::vector<std::string> receiver_stream_ids;
+ for (auto& stream : webrtc_receiver->streams()) {
+ receiver_stream_ids.push_back(stream->id());
+ }
+ receiver_state = blink::RtpReceiverState(
+ main_task_runner_, signaling_task_runner_, webrtc_receiver.get(),
+ std::move(receiver_track_ref), std::move(receiver_stream_ids));
+ }
+ // Create the transceiver state.
+ transceiver_states_.push_back(blink::RtpTransceiverState(
+ main_task_runner_, signaling_task_runner_, webrtc_transceiver.get(),
+ std::move(sender_state), std::move(receiver_state),
+ blink::ToBaseOptional(webrtc_transceiver->mid()),
+ webrtc_transceiver->stopped(), webrtc_transceiver->direction(),
+ blink::ToBaseOptional(webrtc_transceiver->current_direction()),
+ blink::ToBaseOptional(webrtc_transceiver->fired_direction())));
+ }
+ is_initialized_ = true;
+}
+
+blink::WebRTCSctpTransportSnapshot
+TransceiverStateSurfacer::SctpTransportSnapshot() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(is_initialized_);
+ return sctp_transport_snapshot_;
+}
+
+std::vector<blink::RtpTransceiverState>
+TransceiverStateSurfacer::ObtainStates() {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(is_initialized_);
+ for (auto& transceiver_state : transceiver_states_)
+ transceiver_state.Initialize();
+ states_obtained_ = true;
+ return std::move(transceiver_states_);
+}
+
+SurfaceSenderStateOnly::SurfaceSenderStateOnly(
+ rtc::scoped_refptr<webrtc::RtpSenderInterface> sender)
+ : sender_(std::move(sender)) {
+ DCHECK(sender_);
+}
+
+SurfaceSenderStateOnly::~SurfaceSenderStateOnly() {}
+
+cricket::MediaType SurfaceSenderStateOnly::media_type() const {
+ return sender_->media_type();
+}
+
+absl::optional<std::string> SurfaceSenderStateOnly::mid() const {
+ return absl::nullopt;
+}
+
+rtc::scoped_refptr<webrtc::RtpSenderInterface> SurfaceSenderStateOnly::sender()
+ const {
+ return sender_;
+}
+
+rtc::scoped_refptr<webrtc::RtpReceiverInterface>
+SurfaceSenderStateOnly::receiver() const {
+ return nullptr;
+}
+
+bool SurfaceSenderStateOnly::stopped() const {
+ return false;
+}
+
+webrtc::RtpTransceiverDirection SurfaceSenderStateOnly::direction() const {
+ return webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+void SurfaceSenderStateOnly::SetDirection(
+ webrtc::RtpTransceiverDirection new_direction) {
+ NOTIMPLEMENTED();
+}
+
+absl::optional<webrtc::RtpTransceiverDirection>
+SurfaceSenderStateOnly::current_direction() const {
+ return absl::nullopt;
+}
+
+void SurfaceSenderStateOnly::Stop() {
+ NOTIMPLEMENTED();
+}
+
+SurfaceReceiverStateOnly::SurfaceReceiverStateOnly(
+ rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver)
+ : receiver_(std::move(receiver)) {
+ DCHECK(receiver_);
+}
+
+SurfaceReceiverStateOnly::~SurfaceReceiverStateOnly() {}
+
+cricket::MediaType SurfaceReceiverStateOnly::media_type() const {
+ return receiver_->media_type();
+}
+
+absl::optional<std::string> SurfaceReceiverStateOnly::mid() const {
+ return absl::nullopt;
+}
+
+rtc::scoped_refptr<webrtc::RtpSenderInterface>
+SurfaceReceiverStateOnly::sender() const {
+ return nullptr;
+}
+
+rtc::scoped_refptr<webrtc::RtpReceiverInterface>
+SurfaceReceiverStateOnly::receiver() const {
+ return receiver_;
+}
+
+bool SurfaceReceiverStateOnly::stopped() const {
+ return false;
+}
+
+webrtc::RtpTransceiverDirection SurfaceReceiverStateOnly::direction() const {
+ return webrtc::RtpTransceiverDirection::kRecvOnly;
+}
+
+void SurfaceReceiverStateOnly::SetDirection(
+ webrtc::RtpTransceiverDirection new_direction) {
+ NOTIMPLEMENTED();
+}
+
+absl::optional<webrtc::RtpTransceiverDirection>
+SurfaceReceiverStateOnly::current_direction() const {
+ return absl::nullopt;
+}
+
+void SurfaceReceiverStateOnly::Stop() {
+ NOTIMPLEMENTED();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
new file mode 100644
index 00000000000..9d9ca8ea404
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/transceiver_state_surfacer_test.cc
@@ -0,0 +1,388 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/transceiver_state_surfacer.h"
+
+#include <memory>
+#include <tuple>
+
+#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 "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/modules/peerconnection/webrtc_util.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h"
+#include "third_party/blink/public/web/web_heap.h"
+
+using testing::AnyNumber;
+using testing::Return;
+
+namespace blink {
+
+// To avoid name collision on jumbo builds.
+namespace transceiver_state_surfacer_test {
+
+class MockSctpTransport : public webrtc::SctpTransportInterface {
+ public:
+ MOCK_CONST_METHOD0(dtls_transport,
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface>());
+ MOCK_CONST_METHOD0(Information, webrtc::SctpTransportInformation());
+ MOCK_METHOD1(RegisterObserver, void(webrtc::SctpTransportObserverInterface*));
+ MOCK_METHOD0(UnregisterObserver, void());
+};
+
+class TransceiverStateSurfacerTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ track_adapter_map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_task_runner_);
+ surfacer_.reset(new TransceiverStateSurfacer(main_task_runner_,
+ signaling_task_runner()));
+ peer_connection_ = dependency_factory_->CreatePeerConnection(
+ webrtc::PeerConnectionInterface::RTCConfiguration(), nullptr, nullptr);
+ EXPECT_CALL(
+ *(static_cast<blink::MockPeerConnectionImpl*>(peer_connection_.get())),
+ GetSctpTransport())
+ .Times(AnyNumber());
+ }
+
+ void TearDown() override {
+ // Make sure posted tasks get a chance to execute or else the stuff is
+ // teared down while things are in flight.
+ base::RunLoop().RunUntilIdle();
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const {
+ return dependency_factory_->GetWebRtcSignalingTaskRunner();
+ }
+
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ CreateLocalTrackAndAdapter(const std::string& id) {
+ return track_adapter_map_->GetOrCreateLocalTrackAdapter(
+ CreateBlinkLocalTrack(id));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpTransceiver> CreateWebRtcTransceiver(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> local_track,
+ const std::string& local_stream_id,
+ const std::string& remote_track_id,
+ const std::string& remote_stream_id,
+ rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
+ rtc::scoped_refptr<blink::FakeRtpTransceiver> transceiver =
+ new rtc::RefCountedObject<blink::FakeRtpTransceiver>(
+ local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind
+ ? cricket::MEDIA_TYPE_AUDIO
+ : cricket::MEDIA_TYPE_VIDEO,
+ CreateWebRtcSender(local_track, local_stream_id),
+ CreateWebRtcReceiver(remote_track_id, remote_stream_id),
+ base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv,
+ base::nullopt);
+ if (transport.get()) {
+ transceiver->SetTransport(transport);
+ }
+ return transceiver;
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpSender> CreateWebRtcSender(
+ rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track,
+ const std::string& stream_id) {
+ return new rtc::RefCountedObject<blink::FakeRtpSender>(
+ std::move(track), std::vector<std::string>({stream_id}));
+ }
+
+ rtc::scoped_refptr<blink::FakeRtpReceiver> CreateWebRtcReceiver(
+ const std::string& track_id,
+ const std::string& stream_id) {
+ rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_track =
+ blink::MockWebRtcAudioTrack::Create(track_id).get();
+ rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ new rtc::RefCountedObject<blink::MockMediaStream>(stream_id));
+ return new rtc::RefCountedObject<blink::FakeRtpReceiver>(
+ remote_track.get(),
+ std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
+ {remote_stream}));
+ }
+
+ // Initializes the surfacer on the signaling thread and signals the waitable
+ // event when done. The WaitableEvent's Wait() blocks the main thread until
+ // initialization occurs.
+ std::unique_ptr<base::WaitableEvent> AsyncInitializeSurfacerWithWaitableEvent(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers) {
+ std::unique_ptr<base::WaitableEvent> waitable_event(new base::WaitableEvent(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED));
+ signaling_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithWaitableEventOnSignalingThread,
+ base::Unretained(this), std::move(transceivers),
+ waitable_event.get()));
+ return waitable_event;
+ }
+
+ // Initializes the surfacer on the signaling thread and posts back to the main
+ // thread to execute the callback when done. The RunLoop quits after the
+ // callback is executed. Use the RunLoop's Run() method to allow the posted
+ // task (such as the callback) to be executed while waiting. The caller must
+ // let the loop Run() before destroying it.
+ std::unique_ptr<base::RunLoop> AsyncInitializeSurfacerWithCallback(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::OnceCallback<void()> callback) {
+ std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop());
+ signaling_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithCallbackOnSignalingThread,
+ base::Unretained(this), std::move(transceivers),
+ std::move(callback), run_loop.get()));
+ return run_loop;
+ }
+
+ void ObtainStatesAndExpectInitialized(
+ rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver) {
+ // Inspect SCTP transport
+ auto sctp_snapshot = surfacer_->SctpTransportSnapshot();
+ EXPECT_EQ(peer_connection_->GetSctpTransport(), sctp_snapshot.transport);
+ if (peer_connection_->GetSctpTransport()) {
+ EXPECT_EQ(peer_connection_->GetSctpTransport()->dtls_transport(),
+ sctp_snapshot.sctp_transport_state.dtls_transport());
+ }
+ // Inspect transceivers
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_EQ(transceiver_state.webrtc_transceiver().get(),
+ webrtc_transceiver.get());
+ // Inspect sender states.
+ const auto& sender_state = transceiver_state.sender_state();
+ EXPECT_TRUE(sender_state);
+ EXPECT_TRUE(sender_state->is_initialized());
+ const auto& webrtc_sender = webrtc_transceiver->sender();
+ EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get());
+ EXPECT_TRUE(sender_state->track_ref()->is_initialized());
+ EXPECT_EQ(sender_state->track_ref()->webrtc_track(),
+ webrtc_sender->track().get());
+ EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids());
+ EXPECT_EQ(sender_state->webrtc_dtls_transport(),
+ webrtc_sender->dtls_transport());
+ if (webrtc_sender->dtls_transport()) {
+ EXPECT_EQ(webrtc_sender->dtls_transport()->Information().state(),
+ sender_state->webrtc_dtls_transport_information().state());
+ } else {
+ EXPECT_EQ(webrtc::DtlsTransportState::kNew,
+ sender_state->webrtc_dtls_transport_information().state());
+ }
+ // Inspect receiver states.
+ const auto& receiver_state = transceiver_state.receiver_state();
+ EXPECT_TRUE(receiver_state);
+ EXPECT_TRUE(receiver_state->is_initialized());
+ const auto& webrtc_receiver = webrtc_transceiver->receiver();
+ EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get());
+ EXPECT_TRUE(receiver_state->track_ref()->is_initialized());
+ EXPECT_EQ(receiver_state->track_ref()->webrtc_track(),
+ webrtc_receiver->track().get());
+ std::vector<std::string> receiver_stream_ids;
+ for (const auto& stream : webrtc_receiver->streams()) {
+ receiver_stream_ids.push_back(stream->id());
+ }
+ EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids);
+ EXPECT_EQ(receiver_state->webrtc_dtls_transport(),
+ webrtc_receiver->dtls_transport());
+ if (webrtc_receiver->dtls_transport()) {
+ EXPECT_EQ(webrtc_receiver->dtls_transport()->Information().state(),
+ receiver_state->webrtc_dtls_transport_information().state());
+ } else {
+ EXPECT_EQ(webrtc::DtlsTransportState::kNew,
+ receiver_state->webrtc_dtls_transport_information().state());
+ }
+ // Inspect transceiver states.
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.mid(),
+ webrtc_transceiver->mid()));
+ EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped());
+ EXPECT_TRUE(transceiver_state.direction() ==
+ webrtc_transceiver->direction());
+ EXPECT_TRUE(blink::OptionalEquals(transceiver_state.current_direction(),
+ webrtc_transceiver->current_direction()));
+ }
+
+ private:
+ blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(
+ blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"), false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ void AsyncInitializeSurfacerWithWaitableEventOnSignalingThread(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::WaitableEvent* waitable_event) {
+ DCHECK(signaling_task_runner()->BelongsToCurrentThread());
+ surfacer_->Initialize(peer_connection_, track_adapter_map_,
+ std::move(transceivers));
+ waitable_event->Signal();
+ }
+
+ void AsyncInitializeSurfacerWithCallbackOnSignalingThread(
+ std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
+ transceivers,
+ base::OnceCallback<void()> callback,
+ base::RunLoop* run_loop) {
+ DCHECK(signaling_task_runner()->BelongsToCurrentThread());
+ surfacer_->Initialize(peer_connection_, track_adapter_map_,
+ std::move(transceivers));
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&TransceiverStateSurfacerTest::
+ AsyncInitializeSurfacerWithCallbackOnMainThread,
+ base::Unretained(this), std::move(callback), run_loop));
+ }
+
+ void AsyncInitializeSurfacerWithCallbackOnMainThread(
+ base::OnceCallback<void()> callback,
+ base::RunLoop* run_loop) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DCHECK(surfacer_->is_initialized());
+ std::move(callback).Run();
+ run_loop->Quit();
+ }
+
+ protected:
+ scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map_;
+ std::unique_ptr<TransceiverStateSurfacer> surfacer_;
+};
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverBlockingly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ auto waitable_event =
+ AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver});
+ waitable_event->Wait();
+ ObtainStatesAndExpectInitialized(webrtc_transceiver);
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverInCallback) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ auto run_loop = AsyncInitializeSurfacerWithCallback(
+ {webrtc_transceiver},
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized,
+ base::Unretained(this), webrtc_transceiver));
+ run_loop->Run();
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverWithTransport) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", new rtc::RefCountedObject<blink::FakeDtlsTransport>());
+ auto run_loop = AsyncInitializeSurfacerWithCallback(
+ {webrtc_transceiver},
+ base::BindOnce(
+ &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized,
+ base::Unretained(this), webrtc_transceiver));
+ run_loop->Run();
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceSenderStateOnly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_sender =
+ CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream");
+ auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent(
+ {new SurfaceSenderStateOnly(webrtc_sender)});
+ waitable_event->Wait();
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_TRUE(transceiver_state.sender_state());
+ EXPECT_TRUE(transceiver_state.sender_state()->is_initialized());
+ EXPECT_FALSE(transceiver_state.receiver_state());
+ // Expect transceiver members be be missing for optional members and have
+ // sensible values for non-optional members.
+ EXPECT_FALSE(transceiver_state.mid());
+ EXPECT_FALSE(transceiver_state.stopped());
+ EXPECT_EQ(transceiver_state.direction(),
+ webrtc::RtpTransceiverDirection::kSendOnly);
+ EXPECT_FALSE(transceiver_state.current_direction());
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceReceiverStateOnly) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_receiver = CreateWebRtcReceiver("remote_track", "remote_stream");
+ auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent(
+ {new SurfaceReceiverStateOnly(webrtc_receiver)});
+ waitable_event->Wait();
+ auto transceiver_states = surfacer_->ObtainStates();
+ EXPECT_EQ(1u, transceiver_states.size());
+ auto& transceiver_state = transceiver_states[0];
+ EXPECT_FALSE(transceiver_state.sender_state());
+ EXPECT_TRUE(transceiver_state.receiver_state());
+ EXPECT_TRUE(transceiver_state.receiver_state()->is_initialized());
+ // Expect transceiver members be be missing for optional members and have
+ // sensible values for non-optional members.
+ EXPECT_FALSE(transceiver_state.mid());
+ EXPECT_FALSE(transceiver_state.stopped());
+ EXPECT_EQ(transceiver_state.direction(),
+ webrtc::RtpTransceiverDirection::kRecvOnly);
+ EXPECT_FALSE(transceiver_state.current_direction());
+}
+
+TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverWithSctpTransport) {
+ auto local_track_adapter = CreateLocalTrackAndAdapter("local_track");
+ auto webrtc_transceiver = CreateWebRtcTransceiver(
+ local_track_adapter->webrtc_track(), "local_stream", "remote_track",
+ "remote_stream", nullptr);
+ rtc::scoped_refptr<MockSctpTransport> mock_sctp_transport =
+ new rtc::RefCountedObject<MockSctpTransport>();
+ webrtc::SctpTransportInformation sctp_transport_info(
+ webrtc::SctpTransportState::kNew);
+ EXPECT_CALL(
+ *(static_cast<blink::MockPeerConnectionImpl*>(peer_connection_.get())),
+ GetSctpTransport())
+ .WillRepeatedly(Return(mock_sctp_transport));
+ EXPECT_CALL(*mock_sctp_transport.get(), Information())
+ .WillRepeatedly(Return(sctp_transport_info));
+ EXPECT_CALL(*mock_sctp_transport.get(), dtls_transport()).Times(AnyNumber());
+ auto waitable_event =
+ AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver});
+ waitable_event->Wait();
+ EXPECT_TRUE(surfacer_->SctpTransportSnapshot().transport);
+ ObtainStatesAndExpectInitialized(webrtc_transceiver);
+}
+
+} // namespace transceiver_state_surfacer_test
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter.cc
new file mode 100644
index 00000000000..9165ecccfa7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter.cc
@@ -0,0 +1,338 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h"
+
+#include "base/bind.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_track.h"
+#include "third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h"
+#include "third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
+
+namespace blink {
+
+// static
+scoped_refptr<WebRtcMediaStreamTrackAdapter>
+WebRtcMediaStreamTrackAdapter::CreateLocalTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ const blink::WebMediaStreamTrack& web_track) {
+ DCHECK(factory);
+ DCHECK(main_thread->BelongsToCurrentThread());
+ DCHECK(!web_track.IsNull());
+ scoped_refptr<WebRtcMediaStreamTrackAdapter> local_track_adapter(
+ new WebRtcMediaStreamTrackAdapter(factory, main_thread));
+ if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) {
+ local_track_adapter->InitializeLocalAudioTrack(web_track);
+ } else {
+ DCHECK_EQ(web_track.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ local_track_adapter->InitializeLocalVideoTrack(web_track);
+ }
+ return local_track_adapter;
+}
+
+// static
+scoped_refptr<WebRtcMediaStreamTrackAdapter>
+WebRtcMediaStreamTrackAdapter::CreateRemoteTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ const scoped_refptr<webrtc::MediaStreamTrackInterface>& webrtc_track) {
+ DCHECK(factory);
+ DCHECK(!main_thread->BelongsToCurrentThread());
+ DCHECK(webrtc_track);
+ scoped_refptr<WebRtcMediaStreamTrackAdapter> remote_track_adapter(
+ new WebRtcMediaStreamTrackAdapter(factory, main_thread));
+ if (webrtc_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind) {
+ remote_track_adapter->InitializeRemoteAudioTrack(base::WrapRefCounted(
+ static_cast<webrtc::AudioTrackInterface*>(webrtc_track.get())));
+ } else {
+ DCHECK_EQ(webrtc_track->kind(),
+ webrtc::MediaStreamTrackInterface::kVideoKind);
+ remote_track_adapter->InitializeRemoteVideoTrack(base::WrapRefCounted(
+ static_cast<webrtc::VideoTrackInterface*>(webrtc_track.get())));
+ }
+ return remote_track_adapter;
+}
+
+WebRtcMediaStreamTrackAdapter::WebRtcMediaStreamTrackAdapter(
+ blink::PeerConnectionDependencyFactory* factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread)
+ : factory_(factory),
+ main_thread_(main_thread),
+ remote_track_can_complete_initialization_(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ is_initialized_(false),
+ is_disposed_(false) {
+ DCHECK(factory_);
+ DCHECK(main_thread_);
+}
+
+WebRtcMediaStreamTrackAdapter::~WebRtcMediaStreamTrackAdapter() {
+ DCHECK(!remote_track_can_complete_initialization_.IsSignaled());
+ DCHECK(is_disposed_);
+ // Ensured by destructor traits.
+ DCHECK(main_thread_->BelongsToCurrentThread());
+}
+
+// static
+void WebRtcMediaStreamTrackAdapterTraits::Destruct(
+ const WebRtcMediaStreamTrackAdapter* adapter) {
+ if (!adapter->main_thread_->BelongsToCurrentThread()) {
+ adapter->main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterTraits::Destruct,
+ base::Unretained(adapter)));
+ return;
+ }
+ delete adapter;
+}
+
+void WebRtcMediaStreamTrackAdapter::Dispose() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(is_initialized_);
+ if (is_disposed_)
+ return;
+ remote_track_can_complete_initialization_.Reset();
+ is_disposed_ = true;
+ if (web_track_.Source().GetType() ==
+ blink::WebMediaStreamSource::kTypeAudio) {
+ if (local_track_audio_sink_)
+ DisposeLocalAudioTrack();
+ else
+ DisposeRemoteAudioTrack();
+ } else {
+ DCHECK_EQ(web_track_.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ if (local_track_video_sink_)
+ DisposeLocalVideoTrack();
+ else
+ DisposeRemoteVideoTrack();
+ }
+}
+
+bool WebRtcMediaStreamTrackAdapter::is_initialized() const {
+ return is_initialized_;
+}
+
+void WebRtcMediaStreamTrackAdapter::InitializeOnMainThread() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (is_initialized_)
+ return;
+ // TODO(hbos): Only ever initialize explicitly,
+ // remove EnsureTrackIsInitialized(). https://crbug.com/857458
+ EnsureTrackIsInitialized();
+}
+
+const blink::WebMediaStreamTrack& WebRtcMediaStreamTrackAdapter::web_track() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ EnsureTrackIsInitialized();
+ DCHECK(!web_track_.IsNull());
+ return web_track_;
+}
+
+webrtc::MediaStreamTrackInterface*
+WebRtcMediaStreamTrackAdapter::webrtc_track() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(webrtc_track_);
+ EnsureTrackIsInitialized();
+ return webrtc_track_.get();
+}
+
+bool WebRtcMediaStreamTrackAdapter::IsEqual(
+ const blink::WebMediaStreamTrack& web_track) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ EnsureTrackIsInitialized();
+ return web_track_.GetPlatformTrack() == web_track.GetPlatformTrack();
+}
+
+void WebRtcMediaStreamTrackAdapter::InitializeLocalAudioTrack(
+ const blink::WebMediaStreamTrack& web_track) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!is_initialized_);
+ DCHECK(!web_track.IsNull());
+ DCHECK_EQ(web_track.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ web_track_ = web_track;
+ blink::MediaStreamAudioTrack* native_track =
+ blink::MediaStreamAudioTrack::From(web_track_);
+ DCHECK(native_track);
+
+ // Non-WebRtc remote sources and local sources do not provide an instance of
+ // the webrtc::AudioSourceInterface, and also do not need references to the
+ // audio level calculator or audio processor passed to the sink.
+ webrtc::AudioSourceInterface* source_interface = nullptr;
+ local_track_audio_sink_.reset(new blink::WebRtcAudioSink(
+ web_track_.Id().Utf8(), source_interface,
+ factory_->GetWebRtcSignalingTaskRunner(), main_thread_));
+
+ if (auto* media_stream_source = blink::ProcessedLocalAudioSource::From(
+ blink::MediaStreamAudioSource::From(web_track_.Source()))) {
+ local_track_audio_sink_->SetLevel(media_stream_source->audio_level());
+ // The sink only grabs stats from the audio processor. Stats are only
+ // available if audio processing is turned on. Therefore, only provide the
+ // sink a reference to the processor if audio processing is turned on.
+ if (media_stream_source->HasAudioProcessing()) {
+ local_track_audio_sink_->SetAudioProcessor(
+ media_stream_source->GetAudioProcessor());
+ }
+ }
+ native_track->AddSink(local_track_audio_sink_.get());
+ webrtc_track_ = local_track_audio_sink_->webrtc_audio_track();
+ DCHECK(webrtc_track_);
+ is_initialized_ = true;
+}
+
+void WebRtcMediaStreamTrackAdapter::InitializeLocalVideoTrack(
+ const blink::WebMediaStreamTrack& web_track) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!is_initialized_);
+ DCHECK(!web_track.IsNull());
+ DCHECK_EQ(web_track.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ web_track_ = web_track;
+ local_track_video_sink_.reset(new blink::MediaStreamVideoWebRtcSink(
+ web_track_, factory_, main_thread_));
+ webrtc_track_ = local_track_video_sink_->webrtc_video_track();
+ DCHECK(webrtc_track_);
+ is_initialized_ = true;
+}
+
+void WebRtcMediaStreamTrackAdapter::InitializeRemoteAudioTrack(
+ const scoped_refptr<webrtc::AudioTrackInterface>& webrtc_audio_track) {
+ DCHECK(!main_thread_->BelongsToCurrentThread());
+ DCHECK(!is_initialized_);
+ DCHECK(!remote_track_can_complete_initialization_.IsSignaled());
+ DCHECK(webrtc_audio_track);
+ DCHECK_EQ(webrtc_audio_track->kind(),
+ webrtc::MediaStreamTrackInterface::kAudioKind);
+ remote_audio_track_adapter_ =
+ base::MakeRefCounted<blink::RemoteAudioTrackAdapter>(
+ main_thread_, webrtc_audio_track.get());
+ webrtc_track_ = webrtc_audio_track;
+ // Set the initial volume to zero. When the track is put in an audio tag for
+ // playout, its volume is set to that of the tag. Without this, we could end
+ // up playing out audio that's not attached to any tag, see:
+ // http://crbug.com/810848
+ webrtc_audio_track->GetSource()->SetVolume(0);
+ remote_track_can_complete_initialization_.Signal();
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapter::
+ FinalizeRemoteTrackInitializationOnMainThread,
+ this));
+}
+
+void WebRtcMediaStreamTrackAdapter::InitializeRemoteVideoTrack(
+ const scoped_refptr<webrtc::VideoTrackInterface>& webrtc_video_track) {
+ DCHECK(!main_thread_->BelongsToCurrentThread());
+ DCHECK(webrtc_video_track);
+ DCHECK_EQ(webrtc_video_track->kind(),
+ webrtc::MediaStreamTrackInterface::kVideoKind);
+ remote_video_track_adapter_ =
+ base::MakeRefCounted<blink::RemoteVideoTrackAdapter>(
+ main_thread_, webrtc_video_track.get());
+ webrtc_track_ = webrtc_video_track;
+ remote_track_can_complete_initialization_.Signal();
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapter::
+ FinalizeRemoteTrackInitializationOnMainThread,
+ this));
+}
+
+void WebRtcMediaStreamTrackAdapter::
+ FinalizeRemoteTrackInitializationOnMainThread() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(remote_audio_track_adapter_ || remote_video_track_adapter_);
+ if (is_initialized_)
+ return;
+
+ if (remote_audio_track_adapter_) {
+ remote_audio_track_adapter_->Initialize();
+ web_track_ = *remote_audio_track_adapter_->web_track();
+ } else {
+ remote_video_track_adapter_->Initialize();
+ web_track_ = *remote_video_track_adapter_->web_track();
+ }
+ is_initialized_ = true;
+}
+
+void WebRtcMediaStreamTrackAdapter::EnsureTrackIsInitialized() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (is_initialized_)
+ return;
+
+ // Remote tracks may not be fully initialized yet, since they are partly
+ // initialized on the signaling thread.
+ remote_track_can_complete_initialization_.Wait();
+ FinalizeRemoteTrackInitializationOnMainThread();
+}
+
+void WebRtcMediaStreamTrackAdapter::DisposeLocalAudioTrack() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(local_track_audio_sink_);
+ DCHECK_EQ(web_track_.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ blink::MediaStreamAudioTrack* audio_track =
+ blink::MediaStreamAudioTrack::From(web_track_);
+ DCHECK(audio_track);
+ audio_track->RemoveSink(local_track_audio_sink_.get());
+ local_track_audio_sink_.reset();
+ webrtc_track_ = nullptr;
+ web_track_.Reset();
+}
+
+void WebRtcMediaStreamTrackAdapter::DisposeLocalVideoTrack() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(local_track_video_sink_);
+ DCHECK_EQ(web_track_.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ local_track_video_sink_.reset();
+ webrtc_track_ = nullptr;
+ web_track_.Reset();
+}
+
+void WebRtcMediaStreamTrackAdapter::DisposeRemoteAudioTrack() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(remote_audio_track_adapter_);
+ DCHECK_EQ(web_track_.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapter::
+ UnregisterRemoteAudioTrackAdapterOnSignalingThread,
+ this));
+}
+
+void WebRtcMediaStreamTrackAdapter::DisposeRemoteVideoTrack() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(remote_video_track_adapter_);
+ DCHECK_EQ(web_track_.Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ FinalizeRemoteTrackDisposingOnMainThread();
+}
+
+void WebRtcMediaStreamTrackAdapter::
+ UnregisterRemoteAudioTrackAdapterOnSignalingThread() {
+ DCHECK(!main_thread_->BelongsToCurrentThread());
+ DCHECK(remote_audio_track_adapter_);
+ remote_audio_track_adapter_->Unregister();
+ main_thread_->PostTask(
+ FROM_HERE, base::BindOnce(&WebRtcMediaStreamTrackAdapter::
+ FinalizeRemoteTrackDisposingOnMainThread,
+ this));
+}
+
+void WebRtcMediaStreamTrackAdapter::FinalizeRemoteTrackDisposingOnMainThread() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(is_disposed_);
+ remote_audio_track_adapter_ = nullptr;
+ remote_video_track_adapter_ = nullptr;
+ webrtc_track_ = nullptr;
+ web_track_.Reset();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.cc
new file mode 100644
index 00000000000..d4b697db6c5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.cc
@@ -0,0 +1,215 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/web/modules/peerconnection/peer_connection_dependency_factory.h"
+
+namespace blink {
+
+WebRtcMediaStreamTrackAdapterMap::AdapterRef::AdapterRef(
+ scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map,
+ Type type,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> adapter)
+ : map_(std::move(map)), type_(type), adapter_(std::move(adapter)) {
+ DCHECK(map_);
+ DCHECK(adapter_);
+}
+
+WebRtcMediaStreamTrackAdapterMap::AdapterRef::~AdapterRef() {
+ DCHECK(map_->main_thread_->BelongsToCurrentThread());
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> removed_adapter;
+ {
+ base::AutoLock scoped_lock(map_->lock_);
+ // The adapter is stored in the track adapter map and we have |adapter_|,
+ // so there must be at least two references to the adapter.
+ DCHECK(!adapter_->HasOneRef());
+ // Using a raw pointer instead of |adapter_| allows the reference count to
+ // go down to one if this is the last |AdapterRef|.
+ blink::WebRtcMediaStreamTrackAdapter* adapter = adapter_.get();
+ adapter_ = nullptr;
+ if (adapter->HasOneRef()) {
+ removed_adapter = adapter;
+ // "GetOrCreate..." ensures the adapter is initialized and the secondary
+ // key is set before the last |AdapterRef| is destroyed. We can use either
+ // the primary or secondary key for removal.
+ DCHECK(adapter->is_initialized());
+ if (type_ == Type::kLocal) {
+ map_->local_track_adapters_.EraseByPrimary(
+ adapter->web_track().UniqueId());
+ } else {
+ map_->remote_track_adapters_.EraseByPrimary(adapter->webrtc_track());
+ }
+ }
+ }
+ // Dispose the adapter if it was removed. This is performed after releasing
+ // the lock so that it is safe for any disposal mechanism to do synchronous
+ // invokes to the signaling thread without any risk of deadlock.
+ if (removed_adapter) {
+ removed_adapter->Dispose();
+ }
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::AdapterRef::Copy() const {
+ base::AutoLock scoped_lock(map_->lock_);
+ return base::WrapUnique(new AdapterRef(map_, type_, adapter_));
+}
+
+void WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread() {
+ adapter_->InitializeOnMainThread();
+ if (type_ == WebRtcMediaStreamTrackAdapterMap::AdapterRef::Type::kRemote) {
+ base::AutoLock scoped_lock(map_->lock_);
+ if (!map_->remote_track_adapters_.FindBySecondary(web_track().UniqueId())) {
+ map_->remote_track_adapters_.SetSecondaryKey(webrtc_track(),
+ web_track().UniqueId());
+ }
+ }
+}
+
+WebRtcMediaStreamTrackAdapterMap::WebRtcMediaStreamTrackAdapterMap(
+ blink::PeerConnectionDependencyFactory* const factory,
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread)
+ : factory_(factory), main_thread_(std::move(main_thread)) {
+ DCHECK(factory_);
+ DCHECK(main_thread_);
+}
+
+WebRtcMediaStreamTrackAdapterMap::~WebRtcMediaStreamTrackAdapterMap() {
+ DCHECK(local_track_adapters_.empty());
+ DCHECK(remote_track_adapters_.empty());
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetLocalTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track) {
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ local_track_adapters_.FindByPrimary(web_track.UniqueId());
+ if (!adapter_ptr)
+ return nullptr;
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kLocal, *adapter_ptr));
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetLocalTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track) {
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ local_track_adapters_.FindBySecondary(webrtc_track);
+ if (!adapter_ptr)
+ return nullptr;
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kLocal, *adapter_ptr));
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetOrCreateLocalTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track) {
+ DCHECK(!web_track.IsNull());
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ local_track_adapters_.FindByPrimary(web_track.UniqueId());
+ if (adapter_ptr) {
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kLocal, *adapter_ptr));
+ }
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> new_adapter;
+ {
+ // Do not hold |lock_| while creating the adapter in case that operation
+ // synchronizes with the signaling thread. If we do and the signaling thread
+ // is blocked waiting for |lock_| we end up in a deadlock.
+ base::AutoUnlock scoped_unlock(lock_);
+ new_adapter = blink::WebRtcMediaStreamTrackAdapter::CreateLocalTrackAdapter(
+ factory_, main_thread_, web_track);
+ }
+ DCHECK(new_adapter->is_initialized());
+ local_track_adapters_.Insert(web_track.UniqueId(), new_adapter);
+ local_track_adapters_.SetSecondaryKey(web_track.UniqueId(),
+ new_adapter->webrtc_track());
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kLocal, new_adapter));
+}
+
+size_t WebRtcMediaStreamTrackAdapterMap::GetLocalTrackCount() const {
+ base::AutoLock scoped_lock(lock_);
+ return local_track_adapters_.PrimarySize();
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetRemoteTrackAdapter(
+ const blink::WebMediaStreamTrack& web_track) {
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ remote_track_adapters_.FindBySecondary(web_track.UniqueId());
+ if (!adapter_ptr)
+ return nullptr;
+ DCHECK((*adapter_ptr)->is_initialized());
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kRemote, *adapter_ptr));
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetRemoteTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track) {
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ remote_track_adapters_.FindByPrimary(webrtc_track);
+ if (!adapter_ptr)
+ return nullptr;
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kRemote, *adapter_ptr));
+}
+
+std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+WebRtcMediaStreamTrackAdapterMap::GetOrCreateRemoteTrackAdapter(
+ scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track) {
+ DCHECK(webrtc_track);
+ DCHECK(!main_thread_->BelongsToCurrentThread());
+ base::AutoLock scoped_lock(lock_);
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter>* adapter_ptr =
+ remote_track_adapters_.FindByPrimary(webrtc_track.get());
+ if (adapter_ptr) {
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kRemote, *adapter_ptr));
+ }
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> new_adapter;
+ {
+ // Do not hold |lock_| while creating the adapter in case that operation
+ // synchronizes with the main thread. If we do and the main thread is
+ // blocked waiting for |lock_| we end up in a deadlock.
+ base::AutoUnlock scoped_unlock(lock_);
+ new_adapter =
+ blink::WebRtcMediaStreamTrackAdapter::CreateRemoteTrackAdapter(
+ factory_, main_thread_, webrtc_track);
+ }
+ remote_track_adapters_.Insert(webrtc_track.get(), new_adapter);
+ // The new adapter is initialized in a post to the main thread. As soon as it
+ // is initialized we map its |webrtc_track| to the |remote_track_adapters_|
+ // entry as its secondary key. This ensures that there is at least one
+ // |AdapterRef| alive until after the adapter is initialized and its secondary
+ // key is set.
+ auto adapter_ref = base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter));
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread,
+ std::move(adapter_ref)));
+ return base::WrapUnique(
+ new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter));
+}
+
+size_t WebRtcMediaStreamTrackAdapterMap::GetRemoteTrackCount() const {
+ base::AutoLock scoped_lock(lock_);
+ return remote_track_adapters_.PrimarySize();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc
new file mode 100644
index 00000000000..34a97f0e690
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map_test.cc
@@ -0,0 +1,357 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/test_timeouts.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+namespace blink {
+
+class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ map_ = new blink::WebRtcMediaStreamTrackAdapterMap(
+ dependency_factory_.get(), main_thread_);
+ }
+
+ void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); }
+
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_thread() const {
+ return dependency_factory_->GetWebRtcSignalingTaskRunner();
+ }
+
+ blink::WebMediaStreamTrack CreateLocalTrack(const std::string& id) {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(
+ blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"), false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ GetOrCreateRemoteTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track,
+ bool wait_for_initialization = true) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter;
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterMapTest::
+ GetOrCreateRemoteTrackAdapterOnSignalingThread,
+ base::Unretained(this), base::Unretained(webrtc_track),
+ &adapter));
+ RunMessageLoopsUntilIdle(wait_for_initialization);
+ DCHECK(adapter);
+ if (wait_for_initialization) {
+ DCHECK(adapter->is_initialized());
+ } else {
+ DCHECK(!adapter->is_initialized());
+ }
+ return adapter;
+ }
+
+ void GetOrCreateRemoteTrackAdapterOnSignalingThread(
+ webrtc::MediaStreamTrackInterface* webrtc_track,
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>*
+ adapter) {
+ DCHECK(signaling_thread()->BelongsToCurrentThread());
+ *adapter = map_->GetOrCreateRemoteTrackAdapter(webrtc_track);
+ }
+
+ // Runs message loops on the webrtc signaling thread and the main thread until
+ // idle.
+ void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ base::WaitableEvent waitable_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ signaling_thread()->PostTask(
+ FROM_HERE, base::BindOnce(&WebRtcMediaStreamTrackAdapterMapTest::
+ RunMessageLoopUntilIdleOnSignalingThread,
+ base::Unretained(this), &waitable_event));
+ waitable_event.Wait();
+ if (run_loop_on_main_thread)
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void RunMessageLoopUntilIdleOnSignalingThread(
+ base::WaitableEvent* waitable_event) {
+ DCHECK(signaling_thread()->BelongsToCurrentThread());
+ base::RunLoop().RunUntilIdle();
+ waitable_event->Signal();
+ }
+
+ protected:
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> map_;
+};
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest, AddAndRemoveLocalTrackAdapter) {
+ blink::WebMediaStreamTrack web_track = CreateLocalTrack("local_track");
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter_ref = map_->GetOrCreateLocalTrackAdapter(web_track);
+ EXPECT_TRUE(adapter_ref->is_initialized());
+ EXPECT_EQ(adapter_ref->GetAdapterForTesting(),
+ map_->GetLocalTrackAdapter(web_track)->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetLocalTrackCount());
+
+ // "GetOrCreate" for already existing track.
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter_ref2 = map_->GetOrCreateLocalTrackAdapter(web_track);
+ EXPECT_EQ(adapter_ref->GetAdapterForTesting(),
+ adapter_ref2->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetLocalTrackCount());
+
+ adapter_ref2.reset(); // Not the last reference.
+ EXPECT_TRUE(adapter_ref->GetAdapterForTesting()->is_initialized());
+ EXPECT_EQ(1u, map_->GetLocalTrackCount());
+
+ // Destroying all references to the adapter should remove it from the map and
+ // dispose it.
+ adapter_ref.reset();
+ EXPECT_EQ(0u, map_->GetLocalTrackCount());
+ EXPECT_EQ(nullptr, map_->GetLocalTrackAdapter(web_track));
+ // Allow the disposing of track to occur.
+ RunMessageLoopsUntilIdle();
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest, AddAndRemoveRemoteTrackAdapter) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("remote_track");
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter_ref = GetOrCreateRemoteTrackAdapter(webrtc_track.get());
+ EXPECT_TRUE(adapter_ref->is_initialized());
+ EXPECT_EQ(
+ adapter_ref->GetAdapterForTesting(),
+ map_->GetRemoteTrackAdapter(webrtc_track.get())->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetRemoteTrackCount());
+
+ // "GetOrCreate" for already existing track.
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter_ref2 = GetOrCreateRemoteTrackAdapter(webrtc_track.get());
+ EXPECT_EQ(adapter_ref->GetAdapterForTesting(),
+ adapter_ref2->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetRemoteTrackCount());
+
+ adapter_ref2.reset(); // Not the last reference.
+ EXPECT_TRUE(adapter_ref->GetAdapterForTesting()->is_initialized());
+ EXPECT_EQ(1u, map_->GetRemoteTrackCount());
+
+ // Destroying all references to the adapter should remove it from the map and
+ // dispose it.
+ adapter_ref.reset();
+ EXPECT_EQ(0u, map_->GetRemoteTrackCount());
+ EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get()));
+ // Allow the disposing of track to occur.
+ RunMessageLoopsUntilIdle();
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest,
+ InitializeRemoteTrackAdapterExplicitly) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("remote_track");
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ adapter_ref = GetOrCreateRemoteTrackAdapter(webrtc_track.get(), false);
+ EXPECT_FALSE(adapter_ref->is_initialized());
+ adapter_ref->InitializeOnMainThread();
+ EXPECT_TRUE(adapter_ref->is_initialized());
+
+ EXPECT_EQ(1u, map_->GetRemoteTrackCount());
+ // Ensure the implicit initialization's posted task is run after it is already
+ // initialized.
+ RunMessageLoopsUntilIdle();
+ // Destroying all references to the adapter should remove it from the map and
+ // dispose it.
+ adapter_ref.reset();
+ EXPECT_EQ(0u, map_->GetRemoteTrackCount());
+ EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get()));
+ // Allow the disposing of track to occur.
+ RunMessageLoopsUntilIdle();
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest,
+ LocalAndRemoteTrackAdaptersWithSameID) {
+ // Local and remote tracks should be able to use the same id without conflict.
+ const char* id = "id";
+
+ blink::WebMediaStreamTrack local_web_track = CreateLocalTrack(id);
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ local_adapter = map_->GetOrCreateLocalTrackAdapter(local_web_track);
+ EXPECT_TRUE(local_adapter->is_initialized());
+ EXPECT_EQ(
+ local_adapter->GetAdapterForTesting(),
+ map_->GetLocalTrackAdapter(local_web_track)->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetLocalTrackCount());
+
+ scoped_refptr<blink::MockWebRtcAudioTrack> remote_webrtc_track =
+ blink::MockWebRtcAudioTrack::Create(id);
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>
+ remote_adapter = GetOrCreateRemoteTrackAdapter(remote_webrtc_track.get());
+ EXPECT_TRUE(remote_adapter->is_initialized());
+ EXPECT_EQ(remote_adapter->GetAdapterForTesting(),
+ map_->GetRemoteTrackAdapter(remote_webrtc_track.get())
+ ->GetAdapterForTesting());
+ EXPECT_NE(local_adapter->GetAdapterForTesting(),
+ remote_adapter->GetAdapterForTesting());
+ EXPECT_EQ(1u, map_->GetRemoteTrackCount());
+
+ // Destroying all references to the adapters should remove them from the map.
+ local_adapter.reset();
+ remote_adapter.reset();
+ EXPECT_EQ(0u, map_->GetLocalTrackCount());
+ EXPECT_EQ(0u, map_->GetRemoteTrackCount());
+ EXPECT_EQ(nullptr, map_->GetLocalTrackAdapter(local_web_track));
+ EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(remote_webrtc_track.get()));
+ // Allow the disposing of tracks to occur.
+ RunMessageLoopsUntilIdle();
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest, GetMissingLocalTrackAdapter) {
+ blink::WebMediaStreamTrack local_web_track = CreateLocalTrack("missing");
+ EXPECT_EQ(nullptr, map_->GetLocalTrackAdapter(local_web_track));
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapTest, GetMissingRemoteTrackAdapter) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("missing");
+ EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get()));
+}
+
+// Continuously calls GetOrCreateLocalTrackAdapter() on the main thread and
+// GetOrCreateRemoteTrackAdapter() on the signaling thread hoping to hit
+// deadlocks if the operations were to synchronize with the other thread while
+// holding the lock.
+//
+// Note that this deadlock has been notoriously difficult to reproduce. This
+// test is added as an attempt to guard against this type of regression, but do
+// not trust that if this test passes there is no risk of deadlock.
+class WebRtcMediaStreamTrackAdapterMapStressTest
+ : public WebRtcMediaStreamTrackAdapterMapTest {
+ public:
+ WebRtcMediaStreamTrackAdapterMapStressTest()
+ : WebRtcMediaStreamTrackAdapterMapTest(),
+ increased_run_timeout_(
+ TestTimeouts::action_max_timeout(),
+ base::MakeExpectedNotRunClosure(FROM_HERE,
+ "RunLoop::Run() timed out.")) {}
+
+ void RunStressTest(size_t iterations) {
+ base::RunLoop run_loop;
+ remaining_iterations_ = iterations;
+ PostSignalingThreadLoop();
+ MainThreadLoop(&run_loop);
+ run_loop.Run();
+ // The run loop ensures all operations have began executing, but does not
+ // guarantee that all of them are complete, i.e. that track adapters have
+ // been fully initialized and subequently disposed. For that we need to run
+ // until idle or else we may tear down the test prematurely.
+ RunMessageLoopsUntilIdle();
+ }
+
+ void MainThreadLoop(base::RunLoop* run_loop) {
+ for (size_t i = 0u; i < 5u; ++i) {
+ map_->GetOrCreateLocalTrackAdapter(CreateLocalTrack("local_track_id"));
+ }
+ if (--remaining_iterations_ > 0) {
+ PostSignalingThreadLoop();
+ PostMainThreadLoop(run_loop);
+ } else {
+ // We are now done, but there may still be operations pending to execute
+ // on signaling thread so we perform Quit() in a post to the signaling
+ // thread. This ensures that Quit() is called after all operations have
+ // began executing (but does not guarantee that all operations have
+ // completed).
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterMapStressTest::
+ QuitRunLoopOnSignalingThread,
+ base::Unretained(this), base::Unretained(run_loop)));
+ }
+ }
+
+ void PostMainThreadLoop(base::RunLoop* run_loop) {
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterMapStressTest::MainThreadLoop,
+ base::Unretained(this), base::Unretained(run_loop)));
+ }
+
+ void SignalingThreadLoop() {
+ std::vector<
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>>
+ track_refs;
+ for (size_t i = 0u; i < 5u; ++i) {
+ track_refs.push_back(map_->GetOrCreateRemoteTrackAdapter(
+ blink::MockWebRtcAudioTrack::Create("remote_track_id")));
+ }
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcMediaStreamTrackAdapterMapStressTest::
+ DestroyAdapterRefsOnMainThread,
+ base::Unretained(this), std::move(track_refs)));
+ }
+
+ void PostSignalingThreadLoop() {
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterMapStressTest::SignalingThreadLoop,
+ base::Unretained(this)));
+ }
+
+ void DestroyAdapterRefsOnMainThread(
+ std::vector<
+ std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>>
+ track_refs) {}
+
+ void QuitRunLoopOnSignalingThread(base::RunLoop* run_loop) {
+ run_loop->Quit();
+ }
+
+ private:
+ // TODO(https://crbug.com/1002761): Fix this test to run in < action_timeout()
+ // on slower bots (e.g. Debug, ASAN, etc).
+ const base::RunLoop::ScopedRunTimeoutForTest increased_run_timeout_;
+
+ size_t remaining_iterations_;
+};
+
+TEST_F(WebRtcMediaStreamTrackAdapterMapStressTest, StressTest) {
+ const size_t kNumStressTestIterations = 1000u;
+ RunStressTest(kNumStressTestIterations);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc
new file mode 100644
index 00000000000..54e53ffea49
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_test.cc
@@ -0,0 +1,271 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter.h"
+
+#include <memory>
+
+#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 "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/platform/web_media_stream_source.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_source.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+namespace blink {
+
+class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
+ main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+ }
+
+ void TearDown() override {
+ if (track_adapter_) {
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ track_adapter_->Dispose();
+ track_adapter_ = nullptr;
+ RunMessageLoopsUntilIdle();
+ }
+ blink::WebHeap::CollectAllGarbageForTesting();
+ }
+
+ blink::WebMediaStreamTrack CreateLocalAudioTrack() {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(blink::WebString::FromUTF8("local_audio_id"),
+ blink::WebMediaStreamSource::kTypeAudio,
+ blink::WebString::FromUTF8("local_audio_track"),
+ false);
+ blink::MediaStreamAudioSource* audio_source =
+ new blink::MediaStreamAudioSource(
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
+ // Takes ownership of |audio_source|.
+ web_source.SetPlatformSource(base::WrapUnique(audio_source));
+
+ blink::WebMediaStreamTrack web_track;
+ web_track.Initialize(web_source.Id(), web_source);
+ audio_source->ConnectToTrack(web_track);
+ return web_track;
+ }
+
+ blink::WebMediaStreamTrack CreateLocalVideoTrack() {
+ blink::WebMediaStreamSource web_source;
+ web_source.Initialize(blink::WebString::FromUTF8("local_video_id"),
+ blink::WebMediaStreamSource::kTypeVideo,
+ blink::WebString::FromUTF8("local_video_track"),
+ false);
+ blink::MockMediaStreamVideoSource* video_source =
+ new blink::MockMediaStreamVideoSource();
+ // Takes ownership of |video_source|.
+ web_source.SetPlatformSource(base::WrapUnique(video_source));
+
+ return blink::MediaStreamVideoTrack::CreateVideoTrack(
+ video_source, blink::MediaStreamVideoSource::ConstraintsCallback(),
+ true);
+ }
+
+ void CreateRemoteTrackAdapter(
+ webrtc::MediaStreamTrackInterface* webrtc_track) {
+ track_adapter_ =
+ blink::WebRtcMediaStreamTrackAdapter::CreateRemoteTrackAdapter(
+ dependency_factory_.get(), main_thread_, webrtc_track);
+ }
+
+ void HoldOntoAdapterReference(
+ base::WaitableEvent* waitable_event,
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> adapter) {
+ waitable_event->Wait();
+ }
+
+ // Runs message loops on the webrtc signaling thread and optionally the main
+ // thread until idle.
+ void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) {
+ base::WaitableEvent waitable_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&WebRtcMediaStreamTrackAdapterTest::
+ RunMessageLoopUntilIdleOnSignalingThread,
+ base::Unretained(this), &waitable_event));
+ waitable_event.Wait();
+ if (run_loop_on_main_thread)
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void RunMessageLoopUntilIdleOnSignalingThread(
+ base::WaitableEvent* waitable_event) {
+ DCHECK(dependency_factory_->GetWebRtcSignalingTaskRunner()
+ ->BelongsToCurrentThread());
+ base::RunLoop().RunUntilIdle();
+ waitable_event->Signal();
+ }
+
+ protected:
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+ std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
+ dependency_factory_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<blink::WebRtcMediaStreamTrackAdapter> track_adapter_;
+};
+
+TEST_F(WebRtcMediaStreamTrackAdapterTest, LocalAudioTrack) {
+ track_adapter_ =
+ blink::WebRtcMediaStreamTrackAdapter::CreateLocalTrackAdapter(
+ dependency_factory_.get(), main_thread_, CreateLocalAudioTrack());
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ EXPECT_TRUE(!track_adapter_->web_track().IsNull());
+ EXPECT_EQ(track_adapter_->web_track().Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ EXPECT_TRUE(track_adapter_->webrtc_track());
+ EXPECT_EQ(track_adapter_->webrtc_track()->kind(),
+ webrtc::MediaStreamTrackInterface::kAudioKind);
+ EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(),
+ track_adapter_->web_track().Id());
+ EXPECT_TRUE(track_adapter_->GetLocalTrackAudioSinkForTesting());
+ EXPECT_EQ(
+ track_adapter_->GetLocalTrackAudioSinkForTesting()->webrtc_audio_track(),
+ track_adapter_->webrtc_track());
+}
+
+// Flaky, see https://crbug.com/982200.
+TEST_F(WebRtcMediaStreamTrackAdapterTest, DISABLED_LocalVideoTrack) {
+ track_adapter_ =
+ blink::WebRtcMediaStreamTrackAdapter::CreateLocalTrackAdapter(
+ dependency_factory_.get(), main_thread_, CreateLocalVideoTrack());
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ EXPECT_TRUE(!track_adapter_->web_track().IsNull());
+ EXPECT_EQ(track_adapter_->web_track().Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ EXPECT_TRUE(track_adapter_->webrtc_track());
+ EXPECT_EQ(track_adapter_->webrtc_track()->kind(),
+ webrtc::MediaStreamTrackInterface::kVideoKind);
+ EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(),
+ track_adapter_->web_track().Id());
+ EXPECT_TRUE(track_adapter_->GetLocalTrackVideoSinkForTesting());
+ EXPECT_EQ(
+ track_adapter_->GetLocalTrackVideoSinkForTesting()->webrtc_video_track(),
+ track_adapter_->webrtc_track());
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteAudioTrack) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("remote_audio_track");
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter,
+ base::Unretained(this), base::Unretained(webrtc_track.get())));
+ // The adapter is initialized implicitly in a PostTask, allow it to run.
+ RunMessageLoopsUntilIdle();
+ DCHECK(track_adapter_);
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ EXPECT_TRUE(!track_adapter_->web_track().IsNull());
+ EXPECT_EQ(track_adapter_->web_track().Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ EXPECT_TRUE(track_adapter_->webrtc_track());
+ EXPECT_EQ(track_adapter_->webrtc_track()->kind(),
+ webrtc::MediaStreamTrackInterface::kAudioKind);
+ EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(),
+ track_adapter_->web_track().Id());
+ EXPECT_TRUE(track_adapter_->GetRemoteAudioTrackAdapterForTesting());
+ EXPECT_TRUE(
+ track_adapter_->GetRemoteAudioTrackAdapterForTesting()->initialized());
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteVideoTrack) {
+ scoped_refptr<blink::MockWebRtcVideoTrack> webrtc_track =
+ blink::MockWebRtcVideoTrack::Create("remote_video_track");
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter,
+ base::Unretained(this), base::Unretained(webrtc_track.get())));
+ // The adapter is initialized implicitly in a PostTask, allow it to run.
+ RunMessageLoopsUntilIdle();
+ DCHECK(track_adapter_);
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ EXPECT_TRUE(!track_adapter_->web_track().IsNull());
+ EXPECT_EQ(track_adapter_->web_track().Source().GetType(),
+ blink::WebMediaStreamSource::kTypeVideo);
+ EXPECT_TRUE(track_adapter_->webrtc_track());
+ EXPECT_EQ(track_adapter_->webrtc_track()->kind(),
+ webrtc::MediaStreamTrackInterface::kVideoKind);
+ EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(),
+ track_adapter_->web_track().Id());
+ EXPECT_TRUE(track_adapter_->GetRemoteVideoTrackAdapterForTesting());
+ EXPECT_TRUE(
+ track_adapter_->GetRemoteVideoTrackAdapterForTesting()->initialized());
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteTrackExplicitlyInitialized) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("remote_audio_track");
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter,
+ base::Unretained(this), base::Unretained(webrtc_track.get())));
+ // Wait for the CreateRemoteTrackAdapter() call, but don't run the main thread
+ // loop that would have implicitly initialized the adapter.
+ RunMessageLoopsUntilIdle(false);
+ DCHECK(track_adapter_);
+ EXPECT_FALSE(track_adapter_->is_initialized());
+ // Explicitly initialize before the main thread loop has a chance to run.
+ track_adapter_->InitializeOnMainThread();
+ EXPECT_TRUE(track_adapter_->is_initialized());
+ EXPECT_TRUE(!track_adapter_->web_track().IsNull());
+ EXPECT_EQ(track_adapter_->web_track().Source().GetType(),
+ blink::WebMediaStreamSource::kTypeAudio);
+ EXPECT_TRUE(track_adapter_->webrtc_track());
+ EXPECT_EQ(track_adapter_->webrtc_track()->kind(),
+ webrtc::MediaStreamTrackInterface::kAudioKind);
+ EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(),
+ track_adapter_->web_track().Id());
+ EXPECT_TRUE(track_adapter_->GetRemoteAudioTrackAdapterForTesting());
+ EXPECT_TRUE(
+ track_adapter_->GetRemoteAudioTrackAdapterForTesting()->initialized());
+}
+
+TEST_F(WebRtcMediaStreamTrackAdapterTest, LastReferenceOnSignalingThread) {
+ scoped_refptr<blink::MockWebRtcAudioTrack> webrtc_track =
+ blink::MockWebRtcAudioTrack::Create("remote_audio_track");
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter,
+ base::Unretained(this), base::Unretained(webrtc_track.get())));
+ // The adapter is initialized implicitly in a PostTask, allow it to run.
+ RunMessageLoopsUntilIdle();
+ DCHECK(track_adapter_);
+ EXPECT_TRUE(track_adapter_->is_initialized());
+
+ base::WaitableEvent waitable_event(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ dependency_factory_->GetWebRtcSignalingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &WebRtcMediaStreamTrackAdapterTest::HoldOntoAdapterReference,
+ base::Unretained(this), base::Unretained(&waitable_event),
+ track_adapter_));
+ // Clear last reference on main thread.
+ track_adapter_->Dispose();
+ track_adapter_ = nullptr;
+ waitable_event.Signal();
+ RunMessageLoopsUntilIdle();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc
new file mode 100644
index 00000000000..f27836d2f8d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+
+namespace blink {
+
+WebRTCStatsReportObtainer::WebRTCStatsReportObtainer() {}
+
+WebRTCStatsReportObtainer::~WebRTCStatsReportObtainer() {}
+
+blink::WebRTCStatsReportCallback
+WebRTCStatsReportObtainer::GetStatsCallbackWrapper() {
+ return base::BindOnce(&WebRTCStatsReportObtainer::OnStatsDelivered, this);
+}
+
+blink::WebRTCStatsReport* WebRTCStatsReportObtainer::report() const {
+ return report_.get();
+}
+
+blink::WebRTCStatsReport* WebRTCStatsReportObtainer::WaitForReport() {
+ run_loop_.Run();
+ return report_.get();
+}
+
+void WebRTCStatsReportObtainer::OnStatsDelivered(
+ std::unique_ptr<blink::WebRTCStatsReport> report) {
+ report_ = std::move(report);
+ run_loop_.Quit();
+}
+
+} // namespace blink
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 c61535bbb64..e03c047d0eb 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/permissions/permission_utils.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.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"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -25,8 +25,8 @@ using mojom::blink::PermissionName;
void ConnectToPermissionService(
ExecutionContext* execution_context,
mojo::PendingReceiver<mojom::blink::PermissionService> receiver) {
- if (auto* interface_provider = execution_context->GetInterfaceProvider())
- interface_provider->GetInterface(std::move(receiver));
+ execution_context->GetBrowserInterfaceBroker().GetInterface(
+ std::move(receiver));
}
String PermissionStatusToString(mojom::blink::PermissionStatus status) {
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
index 535c3d8d3be..b4e475b5f96 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -249,7 +249,7 @@ ScriptPromise Permissions::revoke(ScriptState* script_state,
ScriptPromise Permissions::requestAll(
ScriptState* script_state,
- const Vector<ScriptValue>& raw_permissions,
+ const HeapVector<ScriptValue>& raw_permissions,
ExceptionState& exception_state) {
Vector<PermissionDescriptorPtr> internal_permissions;
Vector<int> caller_index_to_internal_index;
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.h b/chromium/third_party/blink/renderer/modules/permissions/permissions.h
index d17ffd938fe..66260d025e7 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.h
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.h
@@ -26,7 +26,7 @@ class Permissions final : public ScriptWrappable {
ScriptPromise request(ScriptState*, const ScriptValue&, ExceptionState&);
ScriptPromise revoke(ScriptState*, const ScriptValue&, ExceptionState&);
ScriptPromise requestAll(ScriptState*,
- const Vector<ScriptValue>&,
+ const HeapVector<ScriptValue>&,
ExceptionState&);
private:
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 b5490ca7819..1c8433f0fc0 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
@@ -9,9 +9,9 @@
#include "base/bind_helpers.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/common/manifest/web_display_mode.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
+#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -320,7 +320,7 @@ bool PictureInPictureControllerImpl::IsEnterAutoPictureInPictureAllowed()
Fullscreen::FullscreenElementFrom(*GetSupplementable()) ||
(GetSupplementable()->View() &&
GetSupplementable()->View()->DisplayMode() !=
- WebDisplayMode::kWebDisplayModeBrowser &&
+ blink::mojom::DisplayMode::kBrowser &&
GetSupplementable()->IsInWebAppScope()))) {
return false;
}
@@ -423,7 +423,7 @@ bool PictureInPictureControllerImpl::EnsureService() {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetSupplementable()->GetFrame()->GetTaskRunner(
TaskType::kMediaElementEvent);
- GetSupplementable()->GetFrame()->GetInterfaceProvider().GetInterface(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
picture_in_picture_service_.BindNewPipeAndPassReceiver(task_runner));
return true;
}
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 169a91021a4..0d44effa064 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
@@ -9,6 +9,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/picture_in_picture/picture_in_picture.mojom-blink.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
@@ -116,16 +117,9 @@ class PictureInPictureControllerFrameClient
explicit PictureInPictureControllerFrameClient(
std::unique_ptr<WebMediaPlayer> player)
- : test::MediaStubLocalFrameClient(std::move(player)),
- interface_provider_(new service_manager::InterfaceProvider()) {}
-
- service_manager::InterfaceProvider* GetInterfaceProvider() override {
- return interface_provider_.get();
- }
+ : test::MediaStubLocalFrameClient(std::move(player)) {}
private:
- std::unique_ptr<service_manager::InterfaceProvider> interface_provider_;
-
DISALLOW_COPY_AND_ASSIGN(PictureInPictureControllerFrameClient);
};
@@ -158,9 +152,7 @@ class PictureInPictureControllerTest : public PageTestBase {
nullptr, PictureInPictureControllerFrameClient::Create(
std::make_unique<PictureInPictureControllerPlayer>()));
- service_manager::InterfaceProvider::TestApi test_api(
- GetFrame().Client()->GetInterfaceProvider());
- test_api.SetBinderForName(
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::PictureInPictureService::Name_,
WTF::BindRepeating(&MockPictureInPictureService::Bind,
WTF::Unretained(&mock_service_)));
@@ -184,6 +176,11 @@ class PictureInPictureControllerTest : public PageTestBase {
test::RunPendingTasks();
}
+ void TearDown() override {
+ GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::PictureInPictureService::Name_, {});
+ }
+
HTMLVideoElement* Video() const { return video_.Get(); }
MockPictureInPictureService& Service() { return mock_service_; }
diff --git a/chromium/third_party/blink/renderer/modules/presentation/mock_presentation_service.h b/chromium/third_party/blink/renderer/modules/presentation/mock_presentation_service.h
index cc570dac530..236a2c22b9b 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/mock_presentation_service.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/mock_presentation_service.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink-forward.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.h
index 64ed0b16312..022e6c45a98 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.h
@@ -20,7 +20,7 @@ namespace blink {
// TODO(crbug.com/749327): Consider removing this class and have
// PresentationAvailabilityState use PresentationAvailabilityProperty directly.
class MODULES_EXPORT PresentationAvailabilityCallbacks
- : public GarbageCollectedFinalized<PresentationAvailabilityCallbacks> {
+ : public GarbageCollected<PresentationAvailabilityCallbacks> {
public:
PresentationAvailabilityCallbacks(PresentationAvailabilityProperty*,
const WTF::Vector<KURL>&);
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_observer.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_observer.h
index efd42039f73..5ac1e43c427 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_observer.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_observer.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_AVAILABILITY_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_AVAILABILITY_OBSERVER_H_
-#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.h
index e1ee2bf50c4..c85f91240f1 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.h
@@ -28,8 +28,8 @@ class PresentationAvailabilityObserver;
// TODO(crbug.com/780109): Improve encapsulation of PresentationAvailability and
// this class by moving the multiple URL tracking logic to the former, and
// consolidating this class's APIs to take repeating callbacks.
-class MODULES_EXPORT PresentationAvailabilityState
- : public GarbageCollectedFinalized<PresentationAvailabilityState> {
+class MODULES_EXPORT PresentationAvailabilityState final
+ : public GarbageCollected<PresentationAvailabilityState> {
public:
explicit PresentationAvailabilityState(mojom::blink::PresentationService*);
~PresentationAvailabilityState();
@@ -60,8 +60,8 @@ class MODULES_EXPORT PresentationAvailabilityState
// Tracks listeners of presentation displays availability for
// |availability_urls|. Shared with PresentationRequest objects with the same
// set of URLs.
- class AvailabilityListener
- : public GarbageCollectedFinalized<AvailabilityListener> {
+ class AvailabilityListener final
+ : public GarbageCollected<AvailabilityListener> {
public:
explicit AvailabilityListener(const Vector<KURL>& availability_urls);
~AvailabilityListener();
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state_test.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state_test.cc
index 719c3026d84..02dbf0b26bb 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state_test.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state_test.cc
@@ -20,7 +20,7 @@ namespace blink {
using mojom::blink::ScreenAvailability;
class MockPresentationAvailabilityObserver
- : public GarbageCollectedFinalized<MockPresentationAvailabilityObserver>,
+ : public GarbageCollected<MockPresentationAvailabilityObserver>,
public PresentationAvailabilityObserver {
USING_GARBAGE_COLLECTED_MIXIN(MockPresentationAvailabilityObserver);
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 3068367244a..fae2d02ddc2 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
@@ -100,7 +100,7 @@ void ThrowPresentationDisconnectedError(ExceptionState& exception_state) {
} // namespace
class PresentationConnection::Message final
- : public GarbageCollectedFinalized<PresentationConnection::Message> {
+ : public GarbageCollected<PresentationConnection::Message> {
public:
Message(const String& text) : type(kMessageTypeText), text(text) {}
@@ -119,7 +119,7 @@ class PresentationConnection::Message final
};
class PresentationConnection::BlobLoader final
- : public GarbageCollectedFinalized<PresentationConnection::BlobLoader>,
+ : public GarbageCollected<PresentationConnection::BlobLoader>,
public FileReaderLoaderClient {
public:
BlobLoader(scoped_refptr<BlobDataHandle> blob_data_handle,
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h
index ef6bb42e5b0..0dac738c3d5 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.cc
index 880e3228800..1c39732e27d 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
#include <memory>
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -153,14 +154,11 @@ PresentationController::FindExistingConnection(
mojo::Remote<mojom::blink::PresentationService>&
PresentationController::GetPresentationService() {
- if (!presentation_service_remote_ && GetFrame() && GetFrame()->Client()) {
- auto* interface_provider = GetFrame()->Client()->GetInterfaceProvider();
-
+ if (!presentation_service_remote_ && GetFrame()) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetFrame()->GetTaskRunner(TaskType::kPresentation);
- interface_provider->GetInterface(
+ GetFrame()->GetBrowserInterfaceBroker().GetInterface(
presentation_service_remote_.BindNewPipeAndPassReceiver(task_runner));
-
presentation_service_remote_->SetController(
presentation_controller_receiver_.BindNewPipeAndPassRemote(
task_runner));
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.h
index 635f6da2711..0518081b27f 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_controller.h
@@ -30,7 +30,7 @@ class PresentationAvailabilityState;
// Implements the PresentationController interface from the Presentation API
// from which websites can implement the controlling side of a presentation.
class MODULES_EXPORT PresentationController
- : public GarbageCollectedFinalized<PresentationController>,
+ : public GarbageCollected<PresentationController>,
public Supplement<LocalFrame>,
public ContextLifecycleObserver,
public mojom::blink::PresentationController {
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
index 7f9db6990b7..72083a57a62 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_error.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.h
index 46cb65f3f74..62f5fcbdbc9 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PRESENTATION_PRESENTATION_ERROR_H_
-#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h"
+#include "third_party/blink/public/mojom/presentation/presentation.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
index 21d97512f07..df661cb69b8 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_receiver.h"
#include "services/service_manager/public/cpp/interface_provider.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/core/dom/document.h"
@@ -27,16 +28,14 @@ PresentationReceiver::PresentationReceiver(LocalFrame* frame)
: ContextLifecycleObserver(frame->GetDocument()),
connection_list_(MakeGarbageCollected<PresentationConnectionList>(
frame->GetDocument())) {
- auto* interface_provider = GetFrame()->Client()->GetInterfaceProvider();
- interface_provider->GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
presentation_service_remote_.BindNewPipeAndPassReceiver());
-
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
frame->GetTaskRunner(TaskType::kPresentation);
// Set the mojo::Remote<T> that remote implementation of PresentationService
- // will use to interact with the associated PresentationReceiver, in order to
- // receive updates on new connections becoming available.
+ // will use to interact with the associated PresentationReceiver, in order
+ // to receive updates on new connections becoming available.
presentation_service_remote_->SetReceiver(
presentation_receiver_receiver_.BindNewPipeAndPassRemote(task_runner));
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
index c2edc0d050e..1ae288c8cf9 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/push_messaging/push_error.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.h
index 045878dc81e..b48a8f41ea2 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PUSH_MESSAGING_PUSH_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PUSH_MESSAGING_PUSH_ERROR_H_
-#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
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 28e48e6a7ef..3ba9a309263 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
@@ -83,7 +83,7 @@ ScriptValue PushMessageData::json(ScriptState* script_state,
if (exception_state.HadException())
return ScriptValue();
- return ScriptValue(script_state, parsed);
+ return ScriptValue(script_state->GetIsolate(), parsed);
}
String PushMessageData::text() const {
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
index af26f9e596f..663392b016b 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
@@ -24,9 +24,8 @@ class ScriptState;
// Registration.
//
// TODO(peter): Use the PushMessaging Mojo service directly from here.
-class PushMessagingBridge final
- : public GarbageCollectedFinalized<PushMessagingBridge>,
- public Supplement<ServiceWorkerRegistration> {
+class PushMessagingBridge final : public GarbageCollected<PushMessagingBridge>,
+ public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(PushMessagingBridge);
public:
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.cc
index a5a32209b7d..692dfc40d73 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.cc
@@ -7,7 +7,8 @@
#include <string>
#include <utility>
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -43,7 +44,7 @@ PushMessagingClient* PushMessagingClient::From(LocalFrame* frame) {
mojom::blink::PushMessaging* PushMessagingClient::GetPushMessagingRemote() {
if (!push_messaging_manager_) {
- GetSupplementable()->GetDocumentInterfaceBroker().GetPushMessaging(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
push_messaging_manager_.BindNewPipeAndPassReceiver(
GetSupplementable()->GetTaskRunner(TaskType::kMiscPlatformAPI)));
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.h
index 606d91ead9c..dab40d00c38 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_client.h
@@ -10,7 +10,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.h"
@@ -26,9 +26,8 @@ class KURL;
class PushSubscriptionOptions;
class ServiceWorkerRegistration;
-class PushMessagingClient final
- : public GarbageCollectedFinalized<PushMessagingClient>,
- public Supplement<LocalFrame> {
+class PushMessagingClient final : public GarbageCollected<PushMessagingClient>,
+ public Supplement<LocalFrame> {
USING_GARBAGE_COLLECTED_MIXIN(PushMessagingClient);
public:
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_provider.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_provider.h
index 64b942b4bb6..4ac49e828fd 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_provider.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_provider.h
@@ -13,7 +13,7 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
-#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-blink.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -28,7 +28,7 @@ enum class PushRegistrationStatus;
class PushSubscriptionOptions;
-class PushProvider final : public GarbageCollectedFinalized<PushProvider>,
+class PushProvider final : public GarbageCollected<PushProvider>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(PushProvider);
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.h
index 3c994990f27..8098e52b8ff 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink.h"
+#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/dom/dom_time_stamp.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
index 5cc313a0ec4..1c72a139be0 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
@@ -16,7 +16,7 @@ class PushManager;
class ServiceWorkerRegistration;
class ServiceWorkerRegistrationPush final
- : public GarbageCollectedFinalized<ServiceWorkerRegistrationPush>,
+ : public GarbageCollected<ServiceWorkerRegistrationPush>,
public Supplement<ServiceWorkerRegistration> {
USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistrationPush);
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 bcbb5c1abbb..1520f7575e2 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
@@ -20,7 +20,7 @@ class V8RemotePlaybackAvailabilityCallback;
// Wraps either a base::OnceClosure or RemotePlaybackAvailabilityCallback object
// to be kept in the RemotePlayback's |availability_callbacks_| map.
class AvailabilityCallbackWrapper final
- : public GarbageCollectedFinalized<AvailabilityCallbackWrapper>,
+ : public GarbageCollected<AvailabilityCallbackWrapper>,
public NameClient {
public:
explicit AvailabilityCallbackWrapper(V8RemotePlaybackAvailabilityCallback*);
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index 10cff33e4c6..85b33dca718 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -369,7 +369,8 @@ void RemotePlayback::StateChanged(
DispatchEvent(*Event::Create(event_type_names::kDisconnect));
if (media_element_->IsHTMLVideoElement()) {
ToHTMLVideoElement(media_element_.Get())
- ->MediaRemotingStopped(WebLocalizedString::kMediaRemotingStopNoText);
+ ->MediaRemotingStopped(
+ WebMediaPlayerClient::kMediaRemotingStopNoText);
}
CleanupConnections();
presentation_id_ = "";
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/BUILD.gn b/chromium/third_party/blink/renderer/modules/scheduler/BUILD.gn
index e7365abba62..8612dd3de36 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/scheduler/BUILD.gn
@@ -6,12 +6,12 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("scheduler") {
sources = [
- "scheduler.cc",
- "scheduler.h",
- "task.cc",
- "task.h",
- "task_queue.cc",
- "task_queue.h",
+ "dom_scheduler.cc",
+ "dom_scheduler.h",
+ "dom_task.cc",
+ "dom_task.h",
+ "dom_task_queue.cc",
+ "dom_task_queue.h",
"window_scheduler.cc",
"window_scheduler.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/README.md b/chromium/third_party/blink/renderer/modules/scheduler/README.md
index bd4ac8cd279..a6f30bc2063 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/README.md
+++ b/chromium/third_party/blink/renderer/modules/scheduler/README.md
@@ -37,23 +37,23 @@ Tasks can be moved between task queues with `taskQueue.task(task)`.
### Code Overview and Blink Scheduler Integration
-#### Scheduler
+#### DOMScheduler
-The `Scheduler` is per-document, and observes document lifecycle changes via
-`ContextLifecycleObserver`. When the context is destroyed, the `Scheduler` stops
+The `DOMScheduler` is per-document, and observes document lifecycle changes via
+`ContextLifecycleObserver`. When the context is destroyed, the `DOMScheduler` stops
running tasks.
-The `Scheduler`'s primary function is to maintain TaskQueues. When the
-`Scheduler` is created (when first accessed via `window.scheduler`), it creates
-a set of *global* `TaskQueues`, one of each priority. Global here means
+The `DOMScheduler`'s primary function is to maintain DOMTaskQueues. When the
+`DOMScheduler` is created (when first accessed via `window.scheduler`), it creates
+a set of *global* `DOMTaskQueues`, one of each priority. Global here means
document-global, meaning all document script can access these via
`window.scheduler`. This is opposed to *custom* task queues, which developers
will be able to create via `new TaskQueue()` (WIP).
-#### TaskQueues
+#### DOMTaskQueues
-Each `TaskQueue` wraps a `WebSchedulingTaskQueue`, which is the interface to the
+Each `DOMTaskQueue` wraps a `WebSchedulingTaskQueue`, which is the interface to the
Blink scheduler.
The `WebSchedulingTaskQueue` is created through the document's `FrameScheduler`,
@@ -61,24 +61,24 @@ and is created with a `WebSchedulingPriority`. The latter is used by the Blink
scheduler to determine the priority of the underlying
[base::sequence_manager::TaskQueue](https://cs.chromium.org/chromium/src/base/task/sequence_manager/task_queue.h).
-The `TaskQueue` owns the `WebSchedulingTaskQueue`, and its lifetime is tied to
-that of the `Document` associated with the `Scheduler`.
+The `DOMTaskQueue` owns the `WebSchedulingTaskQueue`, and its lifetime is tied to
+that of the `Document` associated with the `DOMScheduler`.
-The `WebSchedulingTaskQueue` exposes a `TaskRunner`, which the `TaskQueue` uses
+The `WebSchedulingTaskQueue` exposes a `TaskRunner`, which the `DOMTaskQueue` uses
to post tasks to the Blink scheduler.
-#### Tasks
+#### DOMTasks
-A `Task` is a wrapper for a callback, its arguments, its return value (for
+A `DOMTask` is a wrapper for a callback, its arguments, its return value (for
`task.result`), and a
[`TaskHandle`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h?sq=package:chromium&g=0&l=22),
-which allows the `Task` to be canceled with `task.cancel()`.
+which allows the `DOMTask` to be canceled with `task.cancel()`.
-The Blink scheduler handles the actual task scheduling. A `Task`'s callback is
+The Blink scheduler handles the actual task scheduling. A `DOMTask`'s callback is
scheduled to run by posting it a task to a `TaskRunner`&mdash;just as all tasks
in Blink are. The `TaskRunner` is obtained through the `WebSchedulingTaskQueue`,
-which is owned by the `TaskQueue` that the `Task` is posted to.
+which is owned by the `DOMTaskQueue` that the `DOMTask` is posted to.
TODO(shaseley): Add a diagram for the relation between all the different task
queues.
@@ -104,5 +104,5 @@ priority) of tasks.
The API is modeled after setTimeout and setInterval with regards to detached
documents. When a document is detached, any queued tasks will be prevented from
-running, and future calls to postTask through a cached Scheduler or TaskQueue
+running, and future calls to postTask through a cached DOMScheduler or DOMTaskQueue
will be no-ops and return null.
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
index 5c7398ce025..d324ded33bf 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.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/scheduler/scheduler.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h"
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_task_queue.h"
#include "third_party/blink/renderer/modules/scheduler/scheduler_post_task_options.h"
-#include "third_party/blink/renderer/modules/scheduler/task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
namespace blink {
-const char Scheduler::kSupplementName[] = "Scheduler";
+const char DOMScheduler::kSupplementName[] = "DOMScheduler";
-Scheduler* Scheduler::From(Document& document) {
- Scheduler* scheduler = Supplement<Document>::From<Scheduler>(document);
+DOMScheduler* DOMScheduler::From(Document& document) {
+ DOMScheduler* scheduler = Supplement<Document>::From<DOMScheduler>(document);
if (!scheduler) {
- scheduler = MakeGarbageCollected<Scheduler>(&document);
+ scheduler = MakeGarbageCollected<DOMScheduler>(&document);
Supplement<Document>::ProvideTo(document, scheduler);
}
return scheduler;
}
-Scheduler::Scheduler(Document* document) : ContextLifecycleObserver(document) {
+DOMScheduler::DOMScheduler(Document* document)
+ : ContextLifecycleObserver(document) {
if (document->IsContextDestroyed())
return;
DCHECK(document->GetScheduler());
@@ -32,11 +33,11 @@ Scheduler::Scheduler(Document* document) : ContextLifecycleObserver(document) {
CreateGlobalTaskQueues(document);
}
-void Scheduler::ContextDestroyed(ExecutionContext* context) {
+void DOMScheduler::ContextDestroyed(ExecutionContext* context) {
global_task_queues_.clear();
}
-void Scheduler::Trace(Visitor* visitor) {
+void DOMScheduler::Trace(Visitor* visitor) {
visitor->Trace(global_task_queues_);
visitor->Trace(current_task_queue_);
ScriptWrappable::Trace(visitor);
@@ -44,7 +45,7 @@ void Scheduler::Trace(Visitor* visitor) {
Supplement<Document>::Trace(visitor);
}
-TaskQueue* Scheduler::currentTaskQueue() {
+DOMTaskQueue* DOMScheduler::currentTaskQueue() {
// The |current_task_queue_| will only be set if the task currently running
// was scheduled through window.scheduler. In other cases, e.g. setTimeout,
// |current_task_queue_| will be nullptr, in which case we return the default
@@ -54,41 +55,41 @@ TaskQueue* Scheduler::currentTaskQueue() {
return GetTaskQueue(WebSchedulingPriority::kDefaultPriority);
}
-void Scheduler::OnTaskStarted(TaskQueue* task_queue, Task*) {
+void DOMScheduler::OnTaskStarted(DOMTaskQueue* task_queue, DOMTask*) {
// This is not reentrant; tasks are not nested. This allows us to set
// |current_task_queue_| to nullptr when this task completes.
DCHECK_EQ(current_task_queue_, nullptr);
current_task_queue_ = task_queue;
}
-void Scheduler::OnTaskCompleted(TaskQueue* task_queue, Task*) {
+void DOMScheduler::OnTaskCompleted(DOMTaskQueue* task_queue, DOMTask*) {
DCHECK(current_task_queue_);
DCHECK_EQ(current_task_queue_, task_queue);
current_task_queue_ = nullptr;
}
-TaskQueue* Scheduler::getTaskQueue(AtomicString priority) {
- return GetTaskQueue(TaskQueue::WebSchedulingPriorityFromString(priority));
+DOMTaskQueue* DOMScheduler::getTaskQueue(AtomicString priority) {
+ return GetTaskQueue(WebSchedulingPriorityFromString(priority));
}
-TaskQueue* Scheduler::GetTaskQueue(WebSchedulingPriority priority) {
+DOMTaskQueue* DOMScheduler::GetTaskQueue(WebSchedulingPriority priority) {
if (global_task_queues_.IsEmpty())
return nullptr;
return global_task_queues_[static_cast<int>(priority)];
}
-Task* Scheduler::postTask(V8Function* callback_function,
- SchedulerPostTaskOptions* options,
- const Vector<ScriptValue>& args) {
- TaskQueue* task_queue = getTaskQueue(AtomicString(options->priority()));
+DOMTask* DOMScheduler::postTask(V8Function* callback_function,
+ SchedulerPostTaskOptions* options,
+ const HeapVector<ScriptValue>& args) {
+ DOMTaskQueue* task_queue = getTaskQueue(AtomicString(options->priority()));
if (!task_queue)
return nullptr;
return task_queue->postTask(callback_function, options, args);
}
-void Scheduler::CreateGlobalTaskQueues(Document* document) {
+void DOMScheduler::CreateGlobalTaskQueues(Document* document) {
for (size_t i = 0; i < kWebSchedulingPriorityCount; i++) {
- global_task_queues_.push_back(MakeGarbageCollected<TaskQueue>(
+ global_task_queues_.push_back(MakeGarbageCollected<DOMTaskQueue>(
document, static_cast<WebSchedulingPriority>(i), this));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
new file mode 100644
index 00000000000..88f8d2bdff4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_SCHEDULER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_SCHEDULER_H_
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/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 "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+class DOMTask;
+class DOMTaskQueue;
+class ExecutionContext;
+class SchedulerPostTaskOptions;
+class ScriptValue;
+class V8Function;
+
+class MODULES_EXPORT DOMScheduler : public ScriptWrappable,
+ public ContextLifecycleObserver,
+ public Supplement<Document> {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(DOMScheduler);
+
+ public:
+ static const char kSupplementName[];
+
+ static DOMScheduler* From(Document&);
+
+ explicit DOMScheduler(Document*);
+
+ // Returns the DOMTaskQueue of the currently executing DOMTask. If the current
+ // task was not scheduled through the scheduler, this returns the default
+ // priority global task queue.
+ DOMTaskQueue* currentTaskQueue();
+
+ // Returns the DOMTaskQueue for the given |priority| or nullptr if the
+ // underlying context is destroyed, e.g. for detached documents.
+ DOMTaskQueue* getTaskQueue(AtomicString priority);
+
+ // postTask creates and queues a DOMTask in the |global_task_queues_| entry
+ // corresponding to the priority in the SchedulerPostTaskOptions, and returns
+ // the DOMTask. If the underlying context is destroyed, e.g. for detached
+ // documents, this returns nullptr.
+ DOMTask* postTask(V8Function*,
+ SchedulerPostTaskOptions*,
+ const HeapVector<ScriptValue>& args);
+
+ // Callbacks invoked by DOMTasks when they run.
+ void OnTaskStarted(DOMTaskQueue*, DOMTask*);
+ void OnTaskCompleted(DOMTaskQueue*, DOMTask*);
+
+ void ContextDestroyed(ExecutionContext*) override;
+
+ void Trace(Visitor*) override;
+
+ private:
+ static constexpr size_t kWebSchedulingPriorityCount =
+ static_cast<size_t>(WebSchedulingPriority::kLastPriority) + 1;
+
+ void CreateGlobalTaskQueues(Document*);
+ DOMTaskQueue* GetTaskQueue(WebSchedulingPriority);
+
+ // |global_task_queues_| is initialized with one entry per priority, indexed
+ // by priority. This will be empty when the document is detached.
+ HeapVector<Member<DOMTaskQueue>, kWebSchedulingPriorityCount>
+ global_task_queues_;
+ // The DOMTaskQueue associated with the currently running DOMTask, or nullptr
+ // if the current task was not scheduled through this DOMScheduler.
+ Member<DOMTaskQueue> current_task_queue_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.cc
index f55ed74cbc9..038b65c2944 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.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/scheduler/task.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_task.h"
#include <utility>
@@ -10,18 +10,18 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_function.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/scheduler/scheduler.h"
-#include "third_party/blink/renderer/modules/scheduler/task_queue.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_task_queue.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
-Task::Task(TaskQueue* task_queue,
- ExecutionContext* context,
- V8Function* callback,
- const Vector<ScriptValue>& args,
- base::TimeDelta delay)
+DOMTask::DOMTask(DOMTaskQueue* task_queue,
+ ExecutionContext* context,
+ V8Function* callback,
+ const HeapVector<ScriptValue>& args,
+ base::TimeDelta delay)
: ContextLifecycleObserver(context),
status_(Status::kPending),
task_queue_(task_queue),
@@ -36,9 +36,10 @@ Task::Task(TaskQueue* task_queue,
Schedule(delay_);
}
-void Task::Trace(Visitor* visitor) {
+void DOMTask::Trace(Visitor* visitor) {
visitor->Trace(task_queue_);
visitor->Trace(callback_);
+ visitor->Trace(arguments_);
visitor->Trace(result_value_);
visitor->Trace(result_promise_);
visitor->Trace(exception_);
@@ -46,40 +47,40 @@ void Task::Trace(Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void Task::ContextDestroyed(ExecutionContext* context) {
+void DOMTask::ContextDestroyed(ExecutionContext* context) {
if (status_ != Status::kPending)
return;
CancelPendingTask();
}
-AtomicString Task::priority() const {
+AtomicString DOMTask::priority() const {
DCHECK(task_queue_);
return task_queue_->priority();
}
-AtomicString Task::status() const {
+AtomicString DOMTask::status() const {
return TaskStatusToString(status_);
}
-void Task::cancel(ScriptState* script_state) {
+void DOMTask::cancel(ScriptState* script_state) {
if (status_ != Status::kPending)
return;
CancelPendingTask();
SetTaskStatus(Status::kCanceled);
- ResolveOrRejectPromiseIfNeeded(script_state);
+ LazilyResolveOrRejectPromiseIfReady(script_state);
}
-ScriptPromise Task::result(ScriptState* script_state) {
+ScriptPromise DOMTask::result(ScriptState* script_state) {
if (!result_promise_) {
result_promise_ = MakeGarbageCollected<TaskResultPromise>(
ExecutionContext::From(script_state), this,
TaskResultPromise::kFinished);
- ResolveOrRejectPromiseIfNeeded(script_state);
+ LazilyResolveOrRejectPromiseIfReady(script_state);
}
return result_promise_->Promise(script_state->World());
}
-void Task::MoveTo(TaskQueue* task_queue) {
+void DOMTask::MoveTo(DOMTaskQueue* task_queue) {
if (status_ != Status::kPending || task_queue == task_queue_)
return;
@@ -98,31 +99,31 @@ void Task::MoveTo(TaskQueue* task_queue) {
Schedule(delay);
}
-void Task::Schedule(base::TimeDelta delay) {
+void DOMTask::Schedule(base::TimeDelta delay) {
DCHECK_EQ(status_, Status::kPending);
DCHECK(!task_handle_.IsActive());
DCHECK_GE(delay, base::TimeDelta());
task_handle_ = PostDelayedCancellableTask(
*task_queue_->GetTaskRunner(), FROM_HERE,
- WTF::Bind(&Task::Invoke, WrapPersistent(this)), delay_);
+ WTF::Bind(&DOMTask::Invoke, WrapPersistent(this)), delay_);
}
-void Task::CancelPendingTask() {
+void DOMTask::CancelPendingTask() {
DCHECK_EQ(status_, Status::kPending);
DCHECK(task_handle_.IsActive());
task_handle_.Cancel();
}
-void Task::Invoke() {
+void DOMTask::Invoke() {
DCHECK_EQ(status_, Status::kPending);
DCHECK(callback_);
DCHECK(GetExecutionContext());
DCHECK(!GetExecutionContext()->IsContextDestroyed());
ScriptState* script_state =
- callback_->CallbackRelevantScriptStateOrReportError("Task", "Invoke");
+ callback_->CallbackRelevantScriptStateOrReportError("DOMTask", "Invoke");
if (!script_state || !script_state->ContextIsValid())
return;
@@ -131,11 +132,11 @@ void Task::Invoke() {
InvokeInternal(script_state);
SetTaskStatus(Status::kCompleted);
task_queue_->GetScheduler()->OnTaskCompleted(task_queue_, this);
- ResolveOrRejectPromiseIfNeeded(script_state);
+ LazilyResolveOrRejectPromiseIfReady(script_state);
callback_.Release();
}
-void Task::InvokeInternal(ScriptState* script_state) {
+void DOMTask::InvokeInternal(ScriptState* script_state) {
ScriptState::Scope scope(script_state);
v8::TryCatch try_catch(script_state->GetIsolate());
try_catch.SetVerbose(true);
@@ -150,9 +151,7 @@ void Task::InvokeInternal(ScriptState* script_state) {
result_value_.Set(script_state->GetIsolate(), result.V8Value());
}
-void Task::ResolveOrRejectPromiseIfNeeded(ScriptState* script_state) {
- // Lazily resolove or reject the Promise - we don't do anything unless the
- // result property has been accessed.
+void DOMTask::LazilyResolveOrRejectPromiseIfReady(ScriptState* script_state) {
if (!result_promise_)
return;
@@ -182,15 +181,15 @@ void Task::ResolveOrRejectPromiseIfNeeded(ScriptState* script_state) {
}
}
-void Task::SetTaskStatus(Status status) {
+void DOMTask::SetTaskStatus(Status status) {
DCHECK(IsValidStatusChange(status_, status))
- << "Cannot transition from Task::Status " << TaskStatusToString(status_)
- << " to " << TaskStatusToString(status);
+ << "Cannot transition from DOMTask::Status "
+ << TaskStatusToString(status_) << " to " << TaskStatusToString(status);
status_ = status;
}
// static
-AtomicString Task::TaskStatusToString(Status status) {
+AtomicString DOMTask::TaskStatusToString(Status status) {
DEFINE_STATIC_LOCAL(const AtomicString, pending, ("pending"));
DEFINE_STATIC_LOCAL(const AtomicString, running, ("running"));
DEFINE_STATIC_LOCAL(const AtomicString, canceled, ("canceled"));
@@ -212,7 +211,7 @@ AtomicString Task::TaskStatusToString(Status status) {
}
// static
-bool Task::IsValidStatusChange(Status from, Status to) {
+bool DOMTask::IsValidStatusChange(Status from, Status to) {
// Note: Self transitions are not valid.
switch (from) {
case Status::kPending: {
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.h
index 53e4e1c73f9..0fc2c709c6e 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task.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_SCHEDULER_TASK_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_TASK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_TASK_H_
#include "base/time/time.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
@@ -18,22 +18,23 @@
namespace blink {
+class DOMTaskQueue;
class ScriptState;
class ScriptValue;
-class TaskQueue;
class V8Function;
-class MODULES_EXPORT Task : public ScriptWrappable, ContextLifecycleObserver {
+class MODULES_EXPORT DOMTask : public ScriptWrappable,
+ ContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(Task);
+ USING_GARBAGE_COLLECTED_MIXIN(DOMTask);
public:
- // Creating a task also causes the Task to be scheduled.
- Task(TaskQueue*,
- ExecutionContext*,
- V8Function*,
- const Vector<ScriptValue>& args,
- base::TimeDelta delay);
+ // Creating a task also causes the DOMTask to be scheduled.
+ DOMTask(DOMTaskQueue*,
+ ExecutionContext*,
+ V8Function*,
+ const HeapVector<ScriptValue>& args,
+ base::TimeDelta delay);
// Task IDL Interface.
AtomicString priority() const;
@@ -41,9 +42,9 @@ class MODULES_EXPORT Task : public ScriptWrappable, ContextLifecycleObserver {
void cancel(ScriptState*);
ScriptPromise result(ScriptState*);
- // Move this Task to a different TaskQueue. If the task is already enqueued in
- // the given task queue, this method has no effect.
- void MoveTo(TaskQueue*);
+ // Move this DOMTask to a different DOMTaskQueue. If the task is already
+ // enqueued in the given task queue, this method has no effect.
+ void MoveTo(DOMTaskQueue*);
void ContextDestroyed(ExecutionContext*) override;
@@ -71,20 +72,26 @@ class MODULES_EXPORT Task : public ScriptWrappable, ContextLifecycleObserver {
// otherwise it's queued after |delay|.
void Schedule(base::TimeDelta delay);
- // Callback for running the Task.
+ // Entry point for running this DOMTask's |callback_|.
void Invoke();
+ // Internal step of Invoke that handles invoking the callback, including
+ // catching any errors and retrieving the result.
void InvokeInternal(ScriptState*);
- void ResolveOrRejectPromiseIfNeeded(ScriptState*);
+ // Resolve |result_promise_| if both (a) the task has finished running (with
+ // or without an error) or has been canceled, and (b) task.result has been
+ // accessed and returned to userland. If invoked when either of these
+ // conditions are not met, this is a no-op.
+ void LazilyResolveOrRejectPromiseIfReady(ScriptState*);
static bool IsValidStatusChange(Status from, Status to);
static AtomicString TaskStatusToString(Status);
Status status_;
TaskHandle task_handle_;
- Member<TaskQueue> task_queue_;
+ Member<DOMTaskQueue> task_queue_;
Member<V8Function> callback_;
- Vector<ScriptValue> arguments_;
+ HeapVector<ScriptValue> arguments_;
const base::TimeDelta delay_;
// Only set if |delay_| > 0 since Now() can be somewhat expensive. This
// optimizes the case where there is no delay, which we expect to be the
@@ -92,7 +99,10 @@ class MODULES_EXPORT Task : public ScriptWrappable, ContextLifecycleObserver {
const base::TimeTicks queue_time_;
using TaskResultPromise =
- ScriptPromiseProperty<Member<Task>, ScriptValue, ScriptValue>;
+ ScriptPromiseProperty<Member<DOMTask>, ScriptValue, ScriptValue>;
+ // Lazily initialized when the task.result property is accessed to avoid the
+ // overhead of unnecessarily creating promises for every task if they aren't
+ // going to be used.
Member<TaskResultPromise> result_promise_;
TraceWrapperV8Reference<v8::Value> result_value_;
@@ -101,4 +111,4 @@ class MODULES_EXPORT Task : public ScriptWrappable, ContextLifecycleObserver {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_TASK_H_
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.cc b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.cc
new file mode 100644
index 00000000000..003733ed9ba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.cc
@@ -0,0 +1,80 @@
+// 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/scheduler/dom_task_queue.h"
+
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_function.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_task.h"
+#include "third_party/blink/renderer/modules/scheduler/task_queue_post_task_options.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/persistent.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
+#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+
+namespace blink {
+
+DOMTaskQueue::DOMTaskQueue(Document* document,
+ WebSchedulingPriority priority,
+ DOMScheduler* scheduler)
+ : ContextLifecycleObserver(document),
+ priority_(priority),
+ web_scheduling_task_queue_(document->GetScheduler()
+ ->ToFrameScheduler()
+ ->CreateWebSchedulingTaskQueue(priority)),
+ task_runner_(web_scheduling_task_queue_->GetTaskRunner()),
+ scheduler_(scheduler) {
+ DCHECK(!document->IsContextDestroyed());
+}
+
+void DOMTaskQueue::Trace(Visitor* visitor) {
+ visitor->Trace(scheduler_);
+ ScriptWrappable::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+void DOMTaskQueue::ContextDestroyed(ExecutionContext* context) {
+ web_scheduling_task_queue_.reset(nullptr);
+}
+
+AtomicString DOMTaskQueue::priority() const {
+ return WebSchedulingPriorityToString(priority_);
+}
+
+DOMTask* DOMTaskQueue::postTask(V8Function* function,
+ TaskQueuePostTaskOptions* options,
+ const HeapVector<ScriptValue>& args) {
+ if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
+ return nullptr;
+
+ // 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(
+ options->delay() > 0 ? options->delay() : 0);
+
+ // For global task queues, we don't need to track the task objects separately;
+ // tracking is handled by the |web_scheduling_task_queue_|.
+ return MakeGarbageCollected<DOMTask>(this, GetExecutionContext(), function,
+ args, delay);
+}
+
+void DOMTaskQueue::take(DOMTask* task) {
+ if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
+ return;
+ task->MoveTo(this);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.h b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.h
new file mode 100644
index 00000000000..417fa14f733
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/scheduler/dom_task_queue.h
@@ -0,0 +1,86 @@
+// 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_SCHEDULER_DOM_TASK_QUEUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_TASK_QUEUE_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/execution_context/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 "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace blink {
+
+class DOMScheduler;
+class DOMTask;
+class Document;
+class ExecutionContext;
+class ScriptValue;
+class TaskQueuePostTaskOptions;
+class V8Function;
+class WebSchedulingTaskQueue;
+
+namespace scheduler {
+class WebSchedulingTaskQueue;
+} // namespace scheduler
+
+class MODULES_EXPORT DOMTaskQueue : public ScriptWrappable,
+ ContextLifecycleObserver {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(DOMTaskQueue);
+
+ public:
+ DOMTaskQueue(Document*, WebSchedulingPriority, DOMScheduler*);
+
+ // Returns the priority of the DOMTaskQueue.
+ AtomicString priority() const;
+
+ // postTask creates and queues a DOMTask in this DOMTaskQueue and returns the
+ // DOMTask. If the underlying context is destroyed, e.g. for detached
+ // documents, this returns nullptr.
+ DOMTask* postTask(V8Function*,
+ TaskQueuePostTaskOptions*,
+ const HeapVector<ScriptValue>& args);
+
+ // Move the task from its current DOMTaskQueue to this one. For pending
+ // non-delayed tasks, the task is enqueued at the end of this DOMTaskQueue.
+ // For delayed tasks, the delay is adjusted before reposting it.
+ void take(DOMTask*);
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& GetTaskRunner() {
+ return task_runner_;
+ }
+
+ DOMScheduler* GetScheduler() { return scheduler_.Get(); }
+
+ void ContextDestroyed(ExecutionContext*) override;
+
+ void Trace(Visitor*) override;
+
+ private:
+ void RunTaskCallback(DOMTask*);
+ void ScheduleTask(DOMTask*, base::TimeDelta delay);
+
+ const WebSchedulingPriority priority_;
+ // This is destroyed when the Context is destroyed, and we rely on this
+ // happening before the underlying FrameScheduler is destroyed.
+ std::unique_ptr<WebSchedulingTaskQueue> web_scheduling_task_queue_;
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ Member<DOMScheduler> scheduler_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_DOM_TASK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.h b/chromium/third_party/blink/renderer/modules/scheduler/scheduler.h
deleted file mode 100644
index ad55aef669b..00000000000
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.h
+++ /dev/null
@@ -1,85 +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_SCHEDULER_SCHEDULER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_SCHEDULER_H_
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/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 "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
-namespace blink {
-
-class ExecutionContext;
-class SchedulerPostTaskOptions;
-class ScriptValue;
-class Task;
-class TaskQueue;
-class V8Function;
-
-// TODO(shaseley): Rename this class along with TaskQueue and Task to better
-// differentiate these classes from the various other scheduler, task queue, and
-// task classes in the codebase.
-class MODULES_EXPORT Scheduler : public ScriptWrappable,
- public ContextLifecycleObserver,
- public Supplement<Document> {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(Scheduler);
-
- public:
- static const char kSupplementName[];
-
- static Scheduler* From(Document&);
-
- explicit Scheduler(Document*);
-
- // Returns the TaskQueue of the currently executing Task. If the current task
- // was not scheduled through the scheduler, this returns the default priority
- // global task queue.
- TaskQueue* currentTaskQueue();
-
- // Returns the TaskQueue for the given |priority| or nullptr if the underlying
- // context is destroyed, e.g. for detached documents.
- TaskQueue* getTaskQueue(AtomicString priority);
-
- // postTask creates and queues a Task in the |global_task_queues_| entry
- // corresponding to the priority in the SchedulerPostTaskOptions, and returns
- // the Task. If the underlying context is destroyed, e.g. for detached
- // documents, this returns nullptr.
- Task* postTask(V8Function*,
- SchedulerPostTaskOptions*,
- const Vector<ScriptValue>& args);
-
- // Callbacks invoked by TaskQueues when they run scheduled tasks.
- void OnTaskStarted(TaskQueue*, Task*);
- void OnTaskCompleted(TaskQueue*, Task*);
-
- void ContextDestroyed(ExecutionContext*) override;
-
- void Trace(Visitor*) override;
-
- private:
- static constexpr size_t kWebSchedulingPriorityCount =
- static_cast<size_t>(WebSchedulingPriority::kLastPriority) + 1;
-
- void CreateGlobalTaskQueues(Document*);
- TaskQueue* GetTaskQueue(WebSchedulingPriority);
-
- // |global_task_queues_| is initialized with one entry per priority, indexed
- // by priority. This will be empty when the document is detached.
- HeapVector<Member<TaskQueue>, kWebSchedulingPriorityCount>
- global_task_queues_;
- // The TaskQueue associated with the currently running Task, or nullptr if the
- // current task was not scheduled through this Scheduler.
- Member<TaskQueue> current_task_queue_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl b/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
index 9a4311cf32c..cf184c192ec 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/scheduler.idl
@@ -4,7 +4,10 @@
// Experimental Scheduling API Proposal:
// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
-[RuntimeEnabled=WebScheduler] interface Scheduler {
+[
+ ImplementedAs=DOMScheduler,
+ RuntimeEnabled=WebScheduler
+] interface Scheduler {
readonly attribute TaskQueue currentTaskQueue;
TaskQueue getTaskQueue(TaskQueuePriority priority);
Task postTask(Function callback, optional SchedulerPostTaskOptions options, any... arguments);
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task.idl b/chromium/third_party/blink/renderer/modules/scheduler/task.idl
index 87baeb41d3b..80e1ccf7f32 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task.idl
@@ -6,7 +6,10 @@
// https://docs.google.com/document/d/1xU7HyNsEsbXhTgt0ZnXDbeSXm5-m5FzkLJAT6LTizEI/edit#
enum TaskStatus { "pending", "running", "canceled", "completed" };
-[RuntimeEnabled=WebScheduler] interface Task {
+[
+ ImplementedAs=DOMTask,
+ RuntimeEnabled=WebScheduler
+] interface Task {
readonly attribute TaskStatus status;
readonly attribute TaskQueuePriority priority;
[CallWith=ScriptState] readonly attribute Promise<any> result;
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.cc b/chromium/third_party/blink/renderer/modules/scheduler/task_queue.cc
deleted file mode 100644
index aa2f3d88d48..00000000000
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.cc
+++ /dev/null
@@ -1,150 +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/scheduler/task_queue.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/time/time.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_function.h"
-#include "third_party/blink/renderer/modules/scheduler/scheduler.h"
-#include "third_party/blink/renderer/modules/scheduler/task.h"
-#include "third_party/blink/renderer/modules/scheduler/task_queue_post_task_options.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/persistent.h"
-#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
-#include "third_party/blink/renderer/platform/scheduler/public/web_scheduling_task_queue.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-
-namespace blink {
-
-namespace {
-
-const AtomicString& ImmediatePriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, immediate_priority, ("immediate"));
- return immediate_priority;
-}
-
-const AtomicString& HighPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, high_priority, ("high"));
- return high_priority;
-}
-
-const AtomicString& DefaultPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, default_priority, ("default"));
- return default_priority;
-}
-
-const AtomicString& LowPriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, low_priority, ("low"));
- return low_priority;
-}
-
-const AtomicString& IdlePriorityKeyword() {
- DEFINE_STATIC_LOCAL(const AtomicString, idle_priority, ("idle"));
- return idle_priority;
-}
-
-} // namespace
-
-TaskQueue::TaskQueue(Document* document,
- WebSchedulingPriority priority,
- Scheduler* scheduler)
- : ContextLifecycleObserver(document),
- priority_(priority),
- web_scheduling_task_queue_(document->GetScheduler()
- ->ToFrameScheduler()
- ->CreateWebSchedulingTaskQueue(priority)),
- task_runner_(web_scheduling_task_queue_->GetTaskRunner()),
- scheduler_(scheduler) {
- DCHECK(!document->IsContextDestroyed());
-}
-
-void TaskQueue::Trace(Visitor* visitor) {
- visitor->Trace(scheduler_);
- ScriptWrappable::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
-}
-
-void TaskQueue::ContextDestroyed(ExecutionContext* context) {
- web_scheduling_task_queue_.reset(nullptr);
- task_runner_.reset();
-}
-
-AtomicString TaskQueue::priority() const {
- return WebSchedulingPriorityToString(priority_);
-}
-
-Task* TaskQueue::postTask(V8Function* function,
- TaskQueuePostTaskOptions* options,
- const Vector<ScriptValue>& args) {
- // |task_runner_| will be nullptr when the context is destroyed, which
- // prevents us from scheduling tasks for detached documents.
- if (!task_runner_)
- return nullptr;
-
- // 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(
- options->delay() > 0 ? options->delay() : 0);
-
- // For global task queues, we don't need to track the task objects separately;
- // tracking is handled by the |web_scheduling_task_queue_|.
- return MakeGarbageCollected<Task>(this, GetExecutionContext(), function, args,
- delay);
-}
-
-void TaskQueue::take(Task* task) {
- if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
- return;
- task->MoveTo(this);
-}
-
-// static
-AtomicString TaskQueue::WebSchedulingPriorityToString(
- WebSchedulingPriority priority) {
- switch (priority) {
- case WebSchedulingPriority::kImmediatePriority:
- return ImmediatePriorityKeyword();
- case WebSchedulingPriority::kHighPriority:
- return HighPriorityKeyword();
- case WebSchedulingPriority::kDefaultPriority:
- return DefaultPriorityKeyword();
- case WebSchedulingPriority::kLowPriority:
- return LowPriorityKeyword();
- case WebSchedulingPriority::kIdlePriority:
- return IdlePriorityKeyword();
- }
-
- NOTREACHED();
- return g_empty_atom;
-}
-
-// static
-WebSchedulingPriority TaskQueue::WebSchedulingPriorityFromString(
- AtomicString priority) {
- if (priority == ImmediatePriorityKeyword())
- return WebSchedulingPriority::kImmediatePriority;
- if (priority == HighPriorityKeyword())
- return WebSchedulingPriority::kHighPriority;
- if (priority == DefaultPriorityKeyword())
- return WebSchedulingPriority::kDefaultPriority;
- if (priority == LowPriorityKeyword())
- return WebSchedulingPriority::kLowPriority;
- if (priority == IdlePriorityKeyword())
- return WebSchedulingPriority::kIdlePriority;
-
- NOTREACHED();
- return WebSchedulingPriority::kDefaultPriority;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.h b/chromium/third_party/blink/renderer/modules/scheduler/task_queue.h
deleted file mode 100644
index 7d8ac56e98e..00000000000
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.h
+++ /dev/null
@@ -1,83 +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_SCHEDULER_TASK_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_QUEUE_H_
-
-#include <memory>
-
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/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 "third_party/blink/renderer/platform/scheduler/public/web_scheduling_priority.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-} // namespace base
-
-namespace blink {
-
-class Document;
-class ExecutionContext;
-class Scheduler;
-class ScriptValue;
-class Task;
-class TaskQueuePostTaskOptions;
-class V8Function;
-class WebSchedulingTaskQueue;
-
-namespace scheduler {
-class WebSchedulingTaskQueue;
-} // namespace scheduler
-
-class MODULES_EXPORT TaskQueue : public ScriptWrappable,
- ContextLifecycleObserver {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(TaskQueue);
-
- public:
- TaskQueue(Document*, WebSchedulingPriority, Scheduler*);
-
- // Returns the priority of the TaskQueue.
- AtomicString priority() const;
-
- // postTask creates and queues a Task in this TaskQueue and returns the Task.
- // If the underlying context is destroyed, e.g. for detached documents, this
- // returns nullptr.
- Task* postTask(V8Function*,
- TaskQueuePostTaskOptions*,
- const Vector<ScriptValue>& args);
-
- // Move the task from its current TaskQueue to this one. For pending
- // non-delayed tasks, the task is enqueued at the end of this TaskQueue. For
- // delayed tasks, the delay is adjusted before reposting it.
- void take(Task*);
-
- base::SingleThreadTaskRunner* GetTaskRunner() { return task_runner_.get(); }
- Scheduler* GetScheduler() { return scheduler_.Get(); }
-
- void ContextDestroyed(ExecutionContext*) override;
-
- void Trace(Visitor*) override;
-
- static AtomicString WebSchedulingPriorityToString(WebSchedulingPriority);
- static WebSchedulingPriority WebSchedulingPriorityFromString(AtomicString);
-
- private:
- void RunTaskCallback(Task*);
- void ScheduleTask(Task*, base::TimeDelta delay);
-
- const WebSchedulingPriority priority_;
- std::unique_ptr<WebSchedulingTaskQueue> web_scheduling_task_queue_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- Member<Scheduler> scheduler_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCHEDULER_TASK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.idl b/chromium/third_party/blink/renderer/modules/scheduler/task_queue.idl
index 04e9b8b1cab..8c6e06dc034 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/task_queue.idl
+++ b/chromium/third_party/blink/renderer/modules/scheduler/task_queue.idl
@@ -12,7 +12,10 @@ enum TaskQueuePriority {
"idle"
};
-[RuntimeEnabled=WebScheduler] interface TaskQueue {
+[
+ ImplementedAs=DOMTaskQueue,
+ RuntimeEnabled=WebScheduler
+] interface TaskQueue {
readonly attribute TaskQueuePriority priority;
Task postTask(Function callback, optional TaskQueuePostTaskOptions options, any... arguments);
void take(Task task);
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.cc b/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.cc
index b2c8e5cb7e4..e333a04fb54 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.cc
+++ b/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/modules/scheduler/window_scheduler.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/modules/scheduler/scheduler.h"
+#include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h"
namespace blink {
-Scheduler* WindowScheduler::scheduler(LocalDOMWindow& window) {
+DOMScheduler* WindowScheduler::scheduler(LocalDOMWindow& window) {
if (Document* document = window.document()) {
- return Scheduler::From(*document);
+ return DOMScheduler::From(*document);
}
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.h b/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.h
index bb82156906f..e8739bcfc70 100644
--- a/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.h
+++ b/chromium/third_party/blink/renderer/modules/scheduler/window_scheduler.h
@@ -10,14 +10,14 @@
namespace blink {
+class DOMScheduler;
class LocalDOMWindow;
-class Scheduler;
class MODULES_EXPORT WindowScheduler {
STATIC_ONLY(WindowScheduler);
public:
- static Scheduler* scheduler(LocalDOMWindow&);
+ static DOMScheduler* scheduler(LocalDOMWindow&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc b/chromium/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc
index 273d1edafc3..cdf517b9ff9 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc
@@ -19,7 +19,7 @@ namespace {
template <typename T>
class NavigatorScreenManagerImpl final
- : public GarbageCollectedFinalized<NavigatorScreenManagerImpl<T>>,
+ : public GarbageCollected<NavigatorScreenManagerImpl<T>>,
public Supplement<T> {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorScreenManagerImpl<T>);
diff --git a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc
index bb8085ff685..28e86de680d 100644
--- a/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/screen_enumeration/display.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"
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/DEPS b/chromium/third_party/blink/renderer/modules/screen_orientation/DEPS
index 46ea48e4bcc..a8e4bf80211 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/DEPS
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+mojo/public/cpp/bindings/associated_interface_ptr.h",
"+services/device/public/mojom/screen_orientation.mojom-blink.h",
+ "+services/device/public/mojom/screen_orientation.mojom-blink-forward.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/screen_orientation/lock_orientation_callback.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
index e358e93cb64..314ed4e449d 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.h"
+#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
index eecfa9c21bc..e2a7884ff63 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
@@ -87,13 +87,14 @@ void ScreenOrientationControllerImpl::UpdateOrientation() {
DCHECK(orientation_);
DCHECK(GetPage());
ChromeClient& chrome_client = GetPage()->GetChromeClient();
- WebScreenInfo screen_info = chrome_client.GetScreenInfo();
+ WebScreenInfo screen_info = chrome_client.GetScreenInfo(*GetFrame());
WebScreenOrientationType orientation_type = screen_info.orientation_type;
if (orientation_type == kWebScreenOrientationUndefined) {
// The embedder could not provide us with an orientation, deduce it
// ourselves.
- orientation_type = ComputeOrientation(chrome_client.GetScreenInfo().rect,
- screen_info.orientation_angle);
+ orientation_type =
+ ComputeOrientation(chrome_client.GetScreenInfo(*GetFrame()).rect,
+ screen_info.orientation_angle);
}
DCHECK(orientation_type != kWebScreenOrientationUndefined);
@@ -122,7 +123,7 @@ void ScreenOrientationControllerImpl::PageVisibilityChanged() {
// The orientation type and angle are tied in a way that if the angle has
// changed, the type must have changed.
uint16_t current_angle =
- GetPage()->GetChromeClient().GetScreenInfo().orientation_angle;
+ GetPage()->GetChromeClient().GetScreenInfo(*GetFrame()).orientation_angle;
// FIXME: sendOrientationChangeEvent() currently send an event all the
// children of the frame, so it should only be called on the frame on
diff --git a/chromium/third_party/blink/renderer/modules/sensor/DEPS b/chromium/third_party/blink/renderer/modules/sensor/DEPS
index a91f7e91ce6..ceb8fb25803 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/DEPS
+++ b/chromium/third_party/blink/renderer/modules/sensor/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+mojo/public/cpp/bindings",
"+services/device/public/cpp/generic_sensor",
"+services/device/public/mojom/sensor.mojom-blink.h",
+ "+services/device/public/mojom/sensor.mojom-blink-forward.h",
"+services/device/public/mojom/sensor_provider.mojom-blink.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_modules.h",
@@ -9,3 +10,10 @@ include_rules = [
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/sensor",
]
+
+specific_include_rules = {
+ "sensor_test_utils\.(cc|h)|.+test\.cc": [
+ "+base/run_loop.h",
+ "+services/device/public/cpp/test/fake_sensor_and_provider.h",
+ ],
+}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.cc
index 17b391a5817..d13b52dff27 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/accelerometer.cc b/chromium/third_party/blink/renderer/modules/sensor/accelerometer.cc
index e9f332e53cc..0b1aad22976 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/accelerometer.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/accelerometer.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/accelerometer.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.cc
index 58e3961a5a7..a35c7f3b4a5 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/sensor/ambient_light_sensor.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.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"
@@ -11,6 +12,26 @@ using device::mojom::blink::SensorType;
namespace blink {
+namespace {
+
+// Even though the underlying value has changed, for ALS we provide readouts to
+// JS to the nearest 50 Lux.
+constexpr int kAlsRoundingThreshold = 50;
+
+// Decrease precision of ALS readouts.
+// Round off to the nearest kAlsRoundingThreshold.
+double RoundIlluminance(double value) {
+ return kAlsRoundingThreshold * std::round(value / kAlsRoundingThreshold);
+}
+
+// Value will have to vary by at least half the rounding threshold before it has
+// an effect on the output.
+bool IsSignificantlyDifferent(double als_old, double als_new) {
+ return std::fabs(als_old - als_new) >= kAlsRoundingThreshold / 2;
+}
+
+} // namespace
+
// static
AmbientLightSensor* AmbientLightSensor::Create(
ExecutionContext* execution_context,
@@ -38,11 +59,22 @@ AmbientLightSensor::AmbientLightSensor(ExecutionContext* execution_context,
double AmbientLightSensor::illuminance(bool& is_null) const {
INIT_IS_NULL_AND_RETURN(is_null, 0.0);
- return GetReading().als.value;
+ DCHECK(latest_reading_.has_value());
+ return RoundIlluminance(*latest_reading_);
}
-void AmbientLightSensor::Trace(blink::Visitor* visitor) {
- Sensor::Trace(visitor);
+// When the reading we get does not differ significantly from our current
+// value, we discard this reading and do not emit any events. This is a privacy
+// measure to avoid giving readings that are too specific.
+void AmbientLightSensor::OnSensorReadingChanged() {
+ const double new_reading = GetReading().als.value;
+ if (latest_reading_.has_value() &&
+ !IsSignificantlyDifferent(*latest_reading_, new_reading)) {
+ return;
+ }
+
+ latest_reading_ = new_reading;
+ Sensor::OnSensorReadingChanged();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.h b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.h
index 34b3f1e0ec0..5d69f2fb5c3 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor.h
@@ -5,11 +5,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_AMBIENT_LIGHT_SENSOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_AMBIENT_LIGHT_SENSOR_H_
+#include "base/gtest_prod_util.h"
+#include "base/optional.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/sensor/sensor.h"
namespace blink {
-class AmbientLightSensor final : public Sensor {
+class MODULES_EXPORT AmbientLightSensor final : public Sensor {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -22,7 +25,12 @@ class AmbientLightSensor final : public Sensor {
double illuminance(bool& is_null) const;
- void Trace(blink::Visitor*) override;
+ void OnSensorReadingChanged() override;
+
+ private:
+ base::Optional<double> latest_reading_;
+
+ FRIEND_TEST_ALL_PREFIXES(AmbientLightSensorTest, IlluminanceRounding);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc
new file mode 100644
index 00000000000..dff6922d122
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc
@@ -0,0 +1,152 @@
+// 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/sensor/ambient_light_sensor.h"
+
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
+#include "third_party/blink/renderer/modules/sensor/sensor_test_utils.h"
+
+namespace blink {
+
+namespace {
+
+class MockSensorProxyObserver
+ : public GarbageCollected<MockSensorProxyObserver>,
+ public SensorProxy::Observer {
+ USING_GARBAGE_COLLECTED_MIXIN(MockSensorProxyObserver);
+
+ public:
+ virtual ~MockSensorProxyObserver() = default;
+
+ // Synchronously waits for OnSensorReadingChanged() to be called.
+ void WaitForOnSensorReadingChanged() {
+ run_loop_.emplace();
+ run_loop_->Run();
+ }
+
+ void OnSensorReadingChanged() override {
+ DCHECK(run_loop_.has_value() && run_loop_->running());
+ run_loop_->Quit();
+ }
+
+ private:
+ base::Optional<base::RunLoop> run_loop_;
+};
+
+} // namespace
+
+TEST(AmbientLightSensorTest, IlluminanceInStoppedSensor) {
+ SensorTestContext context;
+ NonThrowableExceptionState exception_state;
+
+ auto* sensor = AmbientLightSensor::Create(context.GetExecutionContext(),
+ exception_state);
+
+ bool illuminance_is_null;
+ sensor->illuminance(illuminance_is_null);
+ EXPECT_TRUE(illuminance_is_null);
+ EXPECT_FALSE(sensor->hasReading());
+}
+
+TEST(AmbientLightSensorTest, IlluminanceInSensorWithoutReading) {
+ SensorTestContext context;
+ NonThrowableExceptionState exception_state;
+
+ auto* sensor = AmbientLightSensor::Create(context.GetExecutionContext(),
+ exception_state);
+ sensor->start();
+ SensorTestUtils::WaitForEvent(sensor, event_type_names::kActivate);
+
+ bool illuminance_is_null;
+ sensor->illuminance(illuminance_is_null);
+ EXPECT_TRUE(illuminance_is_null);
+ EXPECT_FALSE(sensor->hasReading());
+}
+
+TEST(AmbientLightSensorTest, IlluminanceRounding) {
+ SensorTestContext context;
+ NonThrowableExceptionState exception_state;
+
+ auto* sensor = AmbientLightSensor::Create(context.GetExecutionContext(),
+ exception_state);
+ sensor->start();
+ SensorTestUtils::WaitForEvent(sensor, event_type_names::kActivate);
+ EXPECT_FALSE(sensor->hasReading());
+
+ // At this point, we have received an 'activate' event, so the sensor is
+ // initialized and it is connected to a SensorProxy that we can retrieve
+ // here. We then attach a new SensorProxy::Observer that we use to
+ // synchronously wait for OnSensorReadingChanged() to be called. Even though
+ // the order that each observer is notified is arbitrary, we know that by the
+ // time we get to the next call here all observers will have been called.
+ auto* sensor_proxy =
+ SensorProviderProxy::From(To<Document>(context.GetExecutionContext()))
+ ->GetSensorProxy(device::mojom::blink::SensorType::AMBIENT_LIGHT);
+ ASSERT_NE(sensor_proxy, nullptr);
+ auto* mock_observer = MakeGarbageCollected<MockSensorProxyObserver>();
+ sensor_proxy->AddObserver(mock_observer);
+
+ bool illuminance_is_null;
+
+ auto* event_counter = MakeGarbageCollected<SensorTestUtils::EventCounter>();
+ sensor->addEventListener(event_type_names::kReading, event_counter);
+
+ // Go from no reading to 24. This will cause a new "reading" event to be
+ // emitted, and the rounding will cause illuminance() to return 0.
+ context.sensor_provider()->UpdateAmbientLightSensorData(24);
+ mock_observer->WaitForOnSensorReadingChanged();
+ SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading);
+ EXPECT_EQ(24, sensor->latest_reading_);
+ EXPECT_EQ(0, sensor->illuminance(illuminance_is_null));
+ EXPECT_FALSE(illuminance_is_null);
+
+ // Go from 24 to 35. The difference is not significant enough, so we will not
+ // emit any "reading" event or store the new raw reading, as if the new
+ // reading had never existed.
+ context.sensor_provider()->UpdateAmbientLightSensorData(35);
+ mock_observer->WaitForOnSensorReadingChanged();
+ EXPECT_EQ(24, sensor->latest_reading_);
+ EXPECT_EQ(0, sensor->illuminance(illuminance_is_null));
+ EXPECT_FALSE(illuminance_is_null);
+
+ // Go from 24 to 49. The difference is significant enough, so we will emit a
+ // new "reading" event, update our raw reading and return a rounded value of
+ // 50 in illuminance().
+ context.sensor_provider()->UpdateAmbientLightSensorData(49);
+ mock_observer->WaitForOnSensorReadingChanged();
+ SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading);
+ EXPECT_EQ(49, sensor->latest_reading_);
+ EXPECT_EQ(50, sensor->illuminance(illuminance_is_null));
+ EXPECT_FALSE(illuminance_is_null);
+
+ // Go from 49 to 35. The difference is not significant enough, so we will not
+ // emit any "reading" event or store the new raw reading, as if the new
+ // reading had never existed.
+ context.sensor_provider()->UpdateAmbientLightSensorData(35);
+ mock_observer->WaitForOnSensorReadingChanged();
+ EXPECT_EQ(49, sensor->latest_reading_);
+ EXPECT_EQ(50, sensor->illuminance(illuminance_is_null));
+ EXPECT_FALSE(illuminance_is_null);
+
+ // Go from 49 to 24. The difference is significant enough, so we will emit a
+ // new "reading" event, update our raw reading and return a rounded value of
+ // 0 in illuminance().
+ context.sensor_provider()->UpdateAmbientLightSensorData(24);
+ mock_observer->WaitForOnSensorReadingChanged();
+ SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading);
+ EXPECT_EQ(24, sensor->latest_reading_);
+ EXPECT_EQ(0, sensor->illuminance(illuminance_is_null));
+ EXPECT_FALSE(illuminance_is_null);
+
+ // Make sure there were no stray "reading" events besides those we expected
+ // above.
+ EXPECT_EQ(3U, event_counter->event_count());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sensor/gyroscope.cc b/chromium/third_party/blink/renderer/modules/sensor/gyroscope.cc
index b03a5f8ab72..793edcd148e 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/gyroscope.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/gyroscope.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/gyroscope.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.cc
index 26283bb9426..2ce628894ca 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/magnetometer.cc b/chromium/third_party/blink/renderer/modules/sensor/magnetometer.cc
index c1d8838231a..0eb58a59c0a 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/magnetometer.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/magnetometer.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/magnetometer.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.cc
index ef206c04ee3..87d9a9190b4 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/relative_orientation_sensor.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
+
using device::mojom::blink::SensorType;
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
index 57e0e572cc7..a233936449d 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -352,12 +352,13 @@ void Sensor::NotifyActivated() {
state_ = SensorState::kActivated;
if (hasReading()) {
- // If reading has already arrived, send initial 'reading' notification
- // right away.
+ // If reading has already arrived, process the reading values (a subclass
+ // may do some filtering, for example) and then send an initial "reading"
+ // event right away.
DCHECK(!pending_reading_notification_.IsActive());
pending_reading_notification_ = PostCancellableTask(
*GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
- WTF::Bind(&Sensor::NotifyReading, WrapWeakPersistent(this)));
+ WTF::Bind(&Sensor::OnSensorReadingChanged, WrapWeakPersistent(this)));
}
DispatchEvent(*Event::Create(event_type_names::kActivate));
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor.h b/chromium/third_party/blink/renderer/modules/sensor/sensor.h
index bc43314d8ec..14fc0de5560 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor.h
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/platform_event_controller.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/sensor/sensor_options.h"
#include "third_party/blink/renderer/modules/sensor/sensor_proxy.h"
#include "third_party/blink/renderer/modules/sensor/spatial_sensor_options.h"
@@ -26,10 +27,10 @@ class DOMException;
class ExceptionState;
class ExecutionContext;
-class Sensor : public EventTargetWithInlineData,
- public ActiveScriptWrappable<Sensor>,
- public ContextLifecycleObserver,
- public SensorProxy::Observer {
+class MODULES_EXPORT Sensor : public EventTargetWithInlineData,
+ public ActiveScriptWrappable<Sensor>,
+ public ContextLifecycleObserver,
+ public SensorProxy::Observer {
USING_GARBAGE_COLLECTED_MIXIN(Sensor);
DEFINE_WRAPPERTYPEINFO();
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
index 665a1b796ed..aba986057d5 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h"
#include "third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
@@ -19,9 +19,9 @@ void SensorProviderProxy::InitializeIfNeeded() {
if (IsInitialized())
return;
- GetSupplementable()->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&sensor_provider_));
- sensor_provider_.set_connection_error_handler(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
+ sensor_provider_.BindNewPipeAndPassReceiver());
+ sensor_provider_.set_disconnect_handler(
WTF::Bind(&SensorProviderProxy::OnSensorProviderConnectionError,
WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
index 4825cb21356..458e133730d 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
@@ -6,9 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_PROVIDER_PROXY_H_
#include "base/macros.h"
-#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/device/public/mojom/sensor.mojom-blink-forward.h"
#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -18,8 +20,8 @@ class SensorProxy;
// This class wraps 'SensorProvider' mojo interface and it manages
// 'SensorProxy' instances.
-class SensorProviderProxy final
- : public GarbageCollectedFinalized<SensorProviderProxy>,
+class MODULES_EXPORT SensorProviderProxy final
+ : public GarbageCollected<SensorProviderProxy>,
public Supplement<Document> {
USING_GARBAGE_COLLECTED_MIXIN(SensorProviderProxy);
@@ -56,7 +58,7 @@ class SensorProviderProxy final
void OnSensorProviderConnectionError();
SensorsSet sensor_proxies_;
- device::mojom::blink::SensorProviderPtr sensor_provider_;
+ mojo::Remote<device::mojom::blink::SensorProvider> sensor_provider_;
bool inspector_mode_;
DISALLOW_COPY_AND_ASSIGN(SensorProviderProxy);
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 e32c2c7df62..bdf81b05d7f 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
@@ -17,12 +17,10 @@
namespace blink {
-using namespace device::mojom::blink;
-
const char SensorProxy::kDefaultErrorDescription[] =
"Could not connect to a sensor";
-SensorProxy::SensorProxy(SensorType sensor_type,
+SensorProxy::SensorProxy(device::mojom::blink::SensorType sensor_type,
SensorProviderProxy* provider,
Page* page)
: PageVisibilityObserver(page),
@@ -65,14 +63,14 @@ void SensorProxy::ReportError(DOMExceptionCode code, const String& message) {
namespace {
-uint16_t GetScreenOrientationAngleForPage(Page* page) {
+uint16_t GetScreenOrientationAngle(LocalFrame& frame) {
if (WebTestSupport::IsRunningWebTest()) {
// Simulate that the device is turned 90 degrees on the right.
// 'orientation_angle' must be 270 as per
// https://w3c.github.io/screen-orientation/#dfn-update-the-orientation-information.
return 270;
}
- return page->GetChromeClient().GetScreenInfo().orientation_angle;
+ return frame.GetChromeClient().GetScreenInfo(frame).orientation_angle;
}
} // namespace
@@ -83,7 +81,9 @@ const device::SensorReading& SensorProxy::GetReading(bool remapped) const {
if (remapped_reading_.timestamp() != reading_.timestamp()) {
remapped_reading_ = reading_;
SensorReadingRemapper::RemapToScreenCoords(
- type_, GetScreenOrientationAngleForPage(GetPage()),
+ type_,
+ GetScreenOrientationAngle(
+ *provider_->GetSupplementable()->GetFrame()),
&remapped_reading_);
}
return remapped_reading_;
@@ -130,7 +130,7 @@ bool SensorProxy::ShouldSuspendUpdates() const {
return !focused_frame_origin->CanAccess(this_origin);
}
-SensorProvider* SensorProxy::sensor_provider() const {
+device::mojom::blink::SensorProvider* SensorProxy::sensor_provider() const {
return provider_->sensor_provider();
}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
index 7357953a898..f25fc82384b 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
@@ -8,10 +8,11 @@
#include "base/macros.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
-#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/device/public/mojom/sensor.mojom-blink-forward.h"
#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
#include "third_party/blink/renderer/core/page/focus_changed_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -21,9 +22,9 @@ class SensorProviderProxy;
// This class wraps 'Sensor' mojo interface and used by multiple
// JS sensor instances of the same type (within a single frame).
-class SensorProxy : public GarbageCollectedFinalized<SensorProxy>,
- public PageVisibilityObserver,
- public FocusChangedObserver {
+class MODULES_EXPORT SensorProxy : public GarbageCollected<SensorProxy>,
+ public PageVisibilityObserver,
+ public FocusChangedObserver {
USING_GARBAGE_COLLECTED_MIXIN(SensorProxy);
public:
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
index 06d6d591890..9f574c42d57 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
@@ -11,11 +11,11 @@
#include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
-namespace blink {
+using device::mojom::blink::SensorCreationResult;
-using namespace device::mojom::blink;
+namespace blink {
-SensorProxyImpl::SensorProxyImpl(SensorType sensor_type,
+SensorProxyImpl::SensorProxyImpl(device::mojom::blink::SensorType sensor_type,
SensorProviderProxy* provider,
Page* page)
: SensorProxy(sensor_type, provider, page),
@@ -50,7 +50,7 @@ void SensorProxyImpl::Initialize() {
}
void SensorProxyImpl::AddConfiguration(
- SensorConfigurationPtr configuration,
+ device::mojom::blink::SensorConfigurationPtr configuration,
base::OnceCallback<void(bool)> callback) {
DCHECK(IsInitialized());
AddActiveFrequency(configuration->frequency);
@@ -59,7 +59,7 @@ void SensorProxyImpl::AddConfiguration(
}
void SensorProxyImpl::RemoveConfiguration(
- SensorConfigurationPtr configuration) {
+ device::mojom::blink::SensorConfigurationPtr configuration) {
DCHECK(IsInitialized());
RemoveActiveFrequency(configuration->frequency);
sensor_remote_->RemoveConfiguration(std::move(configuration));
@@ -122,7 +122,7 @@ void SensorProxyImpl::RaiseError() {
}
void SensorProxyImpl::SensorReadingChanged() {
- DCHECK_EQ(ReportingMode::ON_CHANGE, mode_);
+ DCHECK_EQ(device::mojom::blink::ReportingMode::ON_CHANGE, mode_);
if (ShouldProcessReadings())
UpdateSensorReading();
}
@@ -154,8 +154,9 @@ void SensorProxyImpl::HandleSensorError(SensorCreationResult error) {
}
}
-void SensorProxyImpl::OnSensorCreated(SensorCreationResult result,
- SensorInitParamsPtr params) {
+void SensorProxyImpl::OnSensorCreated(
+ SensorCreationResult result,
+ device::mojom::blink::SensorInitParamsPtr params) {
DCHECK_EQ(kInitializing, state_);
if (!params) {
DCHECK_NE(SensorCreationResult::SUCCESS, result);
@@ -175,7 +176,7 @@ void SensorProxyImpl::OnSensorCreated(SensorCreationResult result,
DCHECK_GT(default_frequency_, 0.0);
sensor_remote_.Bind(std::move(params->sensor));
- client_receiver_.Bind(std::move(params->client_request));
+ client_receiver_.Bind(std::move(params->client_receiver));
shared_buffer_reader_ = device::SensorReadingSharedBufferReader::Create(
std::move(params->memory), params->buffer_offset);
@@ -216,7 +217,7 @@ bool SensorProxyImpl::ShouldProcessReadings() const {
}
void SensorProxyImpl::UpdatePollingStatus() {
- if (mode_ != ReportingMode::CONTINUOUS)
+ if (mode_ != device::mojom::blink::ReportingMode::CONTINUOUS)
return;
if (ShouldProcessReadings()) {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
index 8a2de5b2290..2eb8cfdf1ab 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
@@ -14,10 +14,8 @@
namespace blink {
-using namespace device::mojom::blink;
-
SensorProxyInspectorImpl::SensorProxyInspectorImpl(
- SensorType sensor_type,
+ device::mojom::blink::SensorType sensor_type,
SensorProviderProxy* provider,
Page* page)
: SensorProxy(sensor_type, provider, page) {}
@@ -41,14 +39,14 @@ void SensorProxyInspectorImpl::Initialize() {
}
void SensorProxyInspectorImpl::AddConfiguration(
- SensorConfigurationPtr configuration,
+ device::mojom::blink::SensorConfigurationPtr configuration,
base::OnceCallback<void(bool)> callback) {
DCHECK(IsInitialized());
std::move(callback).Run(true);
}
void SensorProxyInspectorImpl::RemoveConfiguration(
- SensorConfigurationPtr configuration) {
+ device::mojom::blink::SensorConfigurationPtr configuration) {
DCHECK(IsInitialized());
}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h
index b912c58288a..8bcc8ddf92b 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_READING_REMAPPER_H_
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
-#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/device/public/mojom/sensor.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
new file mode 100644
index 00000000000..76b03b67e6f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
@@ -0,0 +1,83 @@
+// 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 <utility>
+
+#include "base/callback.h"
+#include "base/run_loop.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/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/modules/sensor/sensor_test_utils.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace {
+
+// An event listener that invokes |invocation_callback| when it is called.
+class SyncEventListener final : public NativeEventListener {
+ public:
+ SyncEventListener(base::OnceClosure invocation_callback)
+ : invocation_callback_(std::move(invocation_callback)) {}
+
+ void Invoke(ExecutionContext*, Event*) override {
+ DCHECK(invocation_callback_);
+ std::move(invocation_callback_).Run();
+ }
+
+ private:
+ base::OnceClosure invocation_callback_;
+};
+
+} // namespace
+
+// SensorTestContext
+
+SensorTestContext::SensorTestContext() {
+ // Sensor's constructor has a check for this that could be removed in the
+ // future.
+ testing_scope_.GetDocument().SetSecureContextStateForTesting(
+ SecureContextState::kSecure);
+ // Necessary for SensorProxy::ShouldSuspendUpdates() to work correctly.
+ testing_scope_.GetPage().GetFocusController().SetFocused(true);
+
+ testing_scope_.GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
+ device::mojom::blink::SensorProvider::Name_,
+ WTF::BindRepeating(&SensorTestContext::BindSensorProviderRequest,
+ WTF::Unretained(this)));
+}
+
+SensorTestContext::~SensorTestContext() {
+ testing_scope_.GetDocument().GetBrowserInterfaceBroker().SetBinderForTesting(
+ device::mojom::blink::SensorProvider::Name_, {});
+}
+
+ExecutionContext* SensorTestContext::GetExecutionContext() const {
+ return testing_scope_.GetExecutionContext();
+}
+
+void SensorTestContext::BindSensorProviderRequest(
+ mojo::ScopedMessagePipeHandle handle) {
+ sensor_provider_.Bind(
+ device::mojom::SensorProviderRequest(std::move(handle)));
+}
+
+// SensorTestUtils
+
+// static
+void SensorTestUtils::WaitForEvent(EventTarget* event_target,
+ const WTF::AtomicString& event_type) {
+ base::RunLoop run_loop;
+ auto* event_listener =
+ MakeGarbageCollected<SyncEventListener>(run_loop.QuitClosure());
+ event_target->addEventListener(event_type, event_listener);
+ run_loop.Run();
+ event_target->removeEventListener(event_type, event_listener);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.h
new file mode 100644
index 00000000000..1f43d08a1b6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_test_utils.h
@@ -0,0 +1,67 @@
+// 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_SENSOR_SENSOR_TEST_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_TEST_UTILS_H_
+
+#include "services/device/public/cpp/test/fake_sensor_and_provider.h"
+#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class EventTarget;
+class ExecutionContext;
+
+class SensorTestContext final {
+ STACK_ALLOCATED();
+
+ public:
+ SensorTestContext();
+
+ ~SensorTestContext();
+
+ ExecutionContext* GetExecutionContext() const;
+
+ device::FakeSensorProvider* sensor_provider() { return &sensor_provider_; }
+
+ private:
+ void BindSensorProviderRequest(mojo::ScopedMessagePipeHandle handle);
+
+ device::FakeSensorProvider sensor_provider_;
+ V8TestingScope testing_scope_;
+};
+
+class SensorTestUtils final {
+ public:
+ // An event listener that can be used to count the number of times a
+ // particular event has been fired.
+ //
+ // Usage:
+ // auto* event_counter =
+ // MakeGarbageCollected<SensorTestUtils::EventCounter>();
+ // my_event_target->addEventListener(..., event_counter);
+ // [...]
+ // EXPECT_EQ(42U, event_counter->event_count());
+ class EventCounter : public NativeEventListener {
+ public:
+ void Invoke(ExecutionContext*, Event*) override { event_count_++; }
+
+ size_t event_count() const { return event_count_; }
+
+ private:
+ size_t event_count_ = 0;
+ };
+
+ // Synchronously waits for |event_type| to be delivered to |event_target|.
+ static void WaitForEvent(EventTarget* event_target,
+ const WTF::AtomicString& event_type);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_TEST_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial.cc b/chromium/third_party/blink/renderer/modules/serial/serial.cc
index 6c31da03a82..b9654d2cdae 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial.cc
@@ -8,7 +8,8 @@
#include <utility>
#include "base/unguessable_token.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.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/dom/document.h"
@@ -23,6 +24,7 @@ namespace blink {
namespace {
+const char kContextGone[] = "Script context has shut down.";
const char kFeaturePolicyBlocked[] =
"Access to the feature \"serial\" is disallowed by feature policy.";
const char kNoPortSelected[] = "No port selected by the user.";
@@ -52,21 +54,20 @@ void Serial::ContextDestroyed(ExecutionContext*) {
entry.value->ContextDestroyed();
}
-ScriptPromise Serial::getPorts(ScriptState* script_state) {
+ScriptPromise Serial::getPorts(ScriptState* script_state,
+ ExceptionState& exception_state) {
auto* context = GetExecutionContext();
if (!context) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kContextGone);
+ return ScriptPromise();
}
if (!context->GetSecurityContext().IsFeatureEnabled(
mojom::FeaturePolicyFeature::kSerial,
ReportOptions::kReportOnFailure)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
- kFeaturePolicyBlocked));
+ exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
+ return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -80,29 +81,26 @@ ScriptPromise Serial::getPorts(ScriptState* script_state) {
}
ScriptPromise Serial::requestPort(ScriptState* script_state,
- const SerialPortRequestOptions* options) {
+ const SerialPortRequestOptions* options,
+ ExceptionState& exception_state) {
auto* frame = GetFrame();
if (!frame || !frame->GetDocument()) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotSupportedError));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kContextGone);
+ return ScriptPromise();
}
if (!frame->GetDocument()->IsFeatureEnabled(
mojom::FeaturePolicyFeature::kSerial,
ReportOptions::kReportOnFailure)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
- kFeaturePolicyBlocked));
+ exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
+ return ScriptPromise();
}
if (!LocalFrame::HasTransientUserActivation(frame)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kSecurityError,
- "Must be handling a user gesture to show a permission request."));
+ exception_state.ThrowSecurityError(
+ "Must be handling a user gesture to show a permission request.");
+ return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -139,7 +137,7 @@ void Serial::EnsureServiceConnection() {
auto task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- GetExecutionContext()->GetInterfaceProvider()->GetInterface(
+ GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(
WTF::Bind(&Serial::OnServiceConnectionError, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial.h b/chromium/third_party/blink/renderer/modules/serial/serial.h
index 33290cc0b48..cba9edd27e9 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial.h
+++ b/chromium/third_party/blink/renderer/modules/serial/serial.h
@@ -41,8 +41,10 @@ class Serial final : public EventTargetWithInlineData,
// Web-exposed interfaces
DEFINE_ATTRIBUTE_EVENT_LISTENER(connect, kConnect)
DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect, kDisconnect)
- ScriptPromise getPorts(ScriptState*);
- ScriptPromise requestPort(ScriptState*, const SerialPortRequestOptions*);
+ ScriptPromise getPorts(ScriptState*, ExceptionState&);
+ ScriptPromise requestPort(ScriptState*,
+ const SerialPortRequestOptions*,
+ ExceptionState&);
void GetPort(
const base::UnguessableToken& token,
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial.idl b/chromium/third_party/blink/renderer/modules/serial/serial.idl
index ff9f6568f63..48d7960a578 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial.idl
+++ b/chromium/third_party/blink/renderer/modules/serial/serial.idl
@@ -11,9 +11,9 @@
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
- [CallWith=ScriptState, MeasureAs=SerialGetPorts]
+ [CallWith=ScriptState, RaisesException, MeasureAs=SerialGetPorts]
Promise<sequence<SerialPort>> getPorts();
- [CallWith=ScriptState, MeasureAs=SerialRequestPort, Exposed=Window]
+ [CallWith=ScriptState, RaisesException, MeasureAs=SerialRequestPort, Exposed=Window]
Promise<SerialPort> requestPort(optional SerialPortRequestOptions options);
};
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 a0c6a1543c7..b03503cd8d4 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/serial/serial_port.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
@@ -73,6 +75,57 @@ DOMException* DOMExceptionFromReceiveError(SerialReceiveError error) {
}
}
+// A ScriptFunction that calls ContinueClose() on the provided SerialPort.
+class ContinueCloseFunction : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> Create(ScriptState* script_state,
+ SerialPort* port) {
+ auto* self =
+ MakeGarbageCollected<ContinueCloseFunction>(script_state, port);
+ return self->BindToV8Function();
+ }
+
+ ContinueCloseFunction(ScriptState* script_state, SerialPort* port)
+ : ScriptFunction(script_state), port_(port) {}
+
+ ScriptValue Call(ScriptValue) override {
+ return port_->ContinueClose(GetScriptState()).GetScriptValue();
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(port_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ private:
+ Member<SerialPort> port_;
+};
+
+// A ScriptFunction that calls AbortClose() on the provided SerialPort.
+class AbortCloseFunction : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> Create(ScriptState* script_state,
+ SerialPort* port) {
+ auto* self = MakeGarbageCollected<AbortCloseFunction>(script_state, port);
+ return self->BindToV8Function();
+ }
+
+ AbortCloseFunction(ScriptState* script_state, SerialPort* port)
+ : ScriptFunction(script_state), port_(port) {}
+
+ ScriptValue Call(ScriptValue) override {
+ port_->AbortClose();
+ return ScriptValue();
+ }
+
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(port_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ private:
+ Member<SerialPort> port_;
+};
} // namespace
SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info)
@@ -81,28 +134,27 @@ SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info)
SerialPort::~SerialPort() = default;
ScriptPromise SerialPort::open(ScriptState* script_state,
- const SerialOptions* options) {
+ const SerialOptions* options,
+ ExceptionState& exception_state) {
if (open_resolver_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError,
- "A call to open() is already in progress."));
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "A call to open() is already in progress.");
+ return ScriptPromise();
}
if (port_) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kInvalidStateError,
- "The port is already open."));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The port is already open.");
+ return ScriptPromise();
}
auto mojo_options = device::mojom::blink::SerialConnectionOptions::New();
if (options->baudrate() == 0) {
- return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Requested baud rate must be greater than zero."));
+ exception_state.ThrowTypeError(
+ "Requested baud rate must be greater than zero.");
+ return ScriptPromise();
}
mojo_options->bitrate = options->baudrate();
@@ -114,10 +166,9 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo_options->data_bits = device::mojom::blink::SerialDataBits::EIGHT;
break;
default:
- return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Requested number of data bits must be 7 or 8."));
+ exception_state.ThrowTypeError(
+ "Requested number of data bits must be 7 or 8.");
+ return ScriptPromise();
}
if (options->parity() == "none") {
@@ -138,30 +189,24 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo_options->stop_bits = device::mojom::blink::SerialStopBits::TWO;
break;
default:
- return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Requested number of stop bits must be 1 or 2."));
+ exception_state.ThrowTypeError(
+ "Requested number of stop bits must be 1 or 2.");
+ return ScriptPromise();
}
if (options->buffersize() == 0) {
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- String::Format(
- "Requested buffer size (%d bytes) must be greater than zero.",
- options->buffersize())));
+ exception_state.ThrowTypeError(String::Format(
+ "Requested buffer size (%d bytes) must be greater than zero.",
+ options->buffersize()));
+ return ScriptPromise();
}
if (options->buffersize() > kMaxBufferSize) {
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- String::Format("Requested buffer size (%d bytes) is greater than "
- "the maximum allowed (%d bytes).",
- options->buffersize(), kMaxBufferSize)));
+ exception_state.ThrowTypeError(
+ String::Format("Requested buffer size (%d bytes) is greater than "
+ "the maximum allowed (%d bytes).",
+ options->buffersize(), kMaxBufferSize));
+ return ScriptPromise();
}
buffer_size_ = options->buffersize();
@@ -172,25 +217,21 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo::ScopedDataPipeConsumerHandle readable_pipe;
mojo::ScopedDataPipeProducerHandle readable_pipe_producer;
if (!CreateDataPipe(&readable_pipe_producer, &readable_pipe)) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kQuotaExceededError,
- kResourcesExhaustedReadBuffer));
+ exception_state.ThrowDOMException(DOMExceptionCode::kQuotaExceededError,
+ kResourcesExhaustedReadBuffer);
+ return ScriptPromise();
}
// Pipe handle pair for the WritableStream.
mojo::ScopedDataPipeProducerHandle writable_pipe;
mojo::ScopedDataPipeConsumerHandle writable_pipe_consumer;
if (!CreateDataPipe(&writable_pipe, &writable_pipe_consumer)) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kQuotaExceededError,
- kResourcesExhaustedWriteBuffer));
+ exception_state.ThrowDOMException(DOMExceptionCode::kQuotaExceededError,
+ kResourcesExhaustedWriteBuffer);
+ return ScriptPromise();
}
- device::mojom::blink::SerialPortClientPtr client_ptr;
- auto client_request = mojo::MakeRequest(&client_ptr);
-
+ mojo::PendingRemote<device::mojom::blink::SerialPortClient> client;
parent_->GetPort(info_->token, port_.BindNewPipeAndPassReceiver());
port_.set_disconnect_handler(
WTF::Bind(&SerialPort::OnConnectionError, WrapWeakPersistent(this)));
@@ -198,10 +239,10 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
open_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
auto callback = WTF::Bind(&SerialPort::OnOpen, WrapPersistent(this),
std::move(readable_pipe), std::move(writable_pipe),
- std::move(client_request));
+ client.InitWithNewPipeAndPassReceiver());
port_->Open(std::move(mojo_options), std::move(writable_pipe_consumer),
- std::move(readable_pipe_producer), std::move(client_ptr),
+ std::move(readable_pipe_producer), std::move(client),
std::move(callback));
return open_resolver_->Promise();
}
@@ -211,7 +252,7 @@ ReadableStream* SerialPort::readable(ScriptState* script_state,
if (readable_)
return readable_;
- if (!port_ || open_resolver_)
+ if (!port_ || open_resolver_ || closing_)
return nullptr;
mojo::ScopedDataPipeConsumerHandle readable_pipe;
@@ -232,7 +273,7 @@ WritableStream* SerialPort::writable(ScriptState* script_state,
if (writable_)
return writable_;
- if (!port_ || open_resolver_)
+ if (!port_ || open_resolver_ || closing_)
return nullptr;
mojo::ScopedDataPipeProducerHandle writable_pipe;
@@ -248,11 +289,12 @@ WritableStream* SerialPort::writable(ScriptState* script_state,
return writable_;
}
-ScriptPromise SerialPort::getSignals(ScriptState* script_state) {
+ScriptPromise SerialPort::getSignals(ScriptState* script_state,
+ ExceptionState& exception_state) {
if (!port_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kPortClosed));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kPortClosed);
+ return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -264,11 +306,12 @@ ScriptPromise SerialPort::getSignals(ScriptState* script_state) {
}
ScriptPromise SerialPort::setSignals(ScriptState* script_state,
- const SerialOutputSignals* signals) {
+ const SerialOutputSignals* signals,
+ ExceptionState& exception_state) {
if (!port_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kPortClosed));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kPortClosed);
+ return ScriptPromise();
}
auto mojo_signals = device::mojom::blink::SerialHostControlSignals::New();
@@ -294,24 +337,65 @@ ScriptPromise SerialPort::setSignals(ScriptState* script_state,
return resolver->Promise();
}
-void SerialPort::close() {
- if (underlying_source_) {
- // The ReadableStream will report "done" when the data pipe is closed.
- underlying_source_->ExpectClose();
- underlying_source_ = nullptr;
- readable_ = nullptr;
+ScriptPromise SerialPort::close(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ if (!port_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The port is already closed.");
+ return ScriptPromise();
}
- if (underlying_sink_) {
- // TODO(crbug.com/893334): Rather than triggering an error on the
- // WritableStream this should imply a call to abort() and fail if the stream
- // is locked.
- underlying_sink_->SignalErrorOnClose(DOMExceptionFromSendError(
- device::mojom::SerialSendError::DISCONNECTED));
- underlying_sink_ = nullptr;
- writable_ = nullptr;
+
+ if (closing_) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "A call to close() is already in progress.");
+ return ScriptPromise();
}
- port_.reset();
- client_receiver_.reset();
+
+ closing_ = true;
+
+ HeapVector<ScriptPromise> promises;
+ if (readable_) {
+ promises.push_back(readable_->cancel(script_state, exception_state));
+ if (exception_state.HadException()) {
+ closing_ = false;
+ return ScriptPromise();
+ }
+ }
+ if (writable_) {
+ auto* reason = MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kPortClosed);
+ promises.push_back(writable_->abort(script_state,
+ ScriptValue::From(script_state, reason),
+ exception_state));
+ if (exception_state.HadException()) {
+ closing_ = false;
+ return ScriptPromise();
+ }
+ }
+
+ return ScriptPromise::All(script_state, promises)
+ .Then(ContinueCloseFunction::Create(script_state, this),
+ AbortCloseFunction::Create(script_state, this));
+}
+
+ScriptPromise SerialPort::ContinueClose(ScriptState* script_state) {
+ DCHECK(closing_);
+ DCHECK(!readable_);
+ DCHECK(!writable_);
+ DCHECK(!close_resolver_);
+
+ if (!port_)
+ return ScriptPromise::CastUndefined(script_state);
+
+ close_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ port_->Close(WTF::Bind(&SerialPort::OnClose, WrapPersistent(this)));
+ return close_resolver_->Promise();
+}
+
+void SerialPort::AbortClose() {
+ DCHECK(closing_);
+ closing_ = false;
}
void SerialPort::UnderlyingSourceClosed() {
@@ -337,6 +421,7 @@ void SerialPort::Trace(Visitor* visitor) {
visitor->Trace(underlying_sink_);
visitor->Trace(open_resolver_);
visitor->Trace(signal_resolvers_);
+ visitor->Trace(close_resolver_);
ScriptWrappable::Trace(visitor);
}
@@ -375,6 +460,7 @@ bool SerialPort::CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
}
void SerialPort::OnConnectionError() {
+ closing_ = false;
port_.reset();
client_receiver_.reset();
@@ -387,6 +473,8 @@ void SerialPort::OnConnectionError() {
underlying_source_ = nullptr;
SerialPortUnderlyingSink* underlying_sink = underlying_sink_;
underlying_sink_ = nullptr;
+ ScriptPromiseResolver* close_resolver = close_resolver_;
+ close_resolver_ = nullptr;
if (open_resolver) {
open_resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -404,12 +492,15 @@ void SerialPort::OnConnectionError() {
underlying_sink->SignalErrorOnClose(
DOMExceptionFromSendError(SerialSendError::DISCONNECTED));
}
+ if (close_resolver)
+ close_resolver->Resolve();
}
void SerialPort::OnOpen(
mojo::ScopedDataPipeConsumerHandle readable_pipe,
mojo::ScopedDataPipeProducerHandle writable_pipe,
- device::mojom::blink::SerialPortClientRequest client_request,
+ mojo::PendingReceiver<device::mojom::blink::SerialPortClient>
+ client_receiver,
bool success) {
ScriptState* script_state = open_resolver_->GetScriptState();
if (!script_state->ContextIsValid())
@@ -426,7 +517,7 @@ void SerialPort::OnOpen(
ScriptState::Scope scope(script_state);
InitializeReadableStream(script_state, std::move(readable_pipe));
InitializeWritableStream(script_state, std::move(writable_pipe));
- client_receiver_.Bind(std::move(client_request));
+ client_receiver_.Bind(std::move(client_receiver));
open_resolver_->Resolve();
open_resolver_ = nullptr;
}
@@ -438,8 +529,12 @@ void SerialPort::InitializeReadableStream(
DCHECK(!readable_);
underlying_source_ = MakeGarbageCollected<SerialPortUnderlyingSource>(
script_state, this, std::move(readable_pipe));
+ // Ideally the stream would report the number of bytes that can be read from
+ // the underlying Mojo data pipe. As an approximation the high water mark is
+ // set to 0 so that data remains in the pipe rather than being queued in the
+ // stream and thus adding an extra layer of buffering.
readable_ = ReadableStream::CreateWithCountQueueingStrategy(
- script_state, underlying_source_, 0);
+ script_state, underlying_source_, /*high_water_mark=*/0);
}
void SerialPort::InitializeWritableStream(
@@ -449,8 +544,13 @@ void SerialPort::InitializeWritableStream(
DCHECK(!writable_);
underlying_sink_ = MakeGarbageCollected<SerialPortUnderlyingSink>(
this, std::move(writable_pipe));
+ // Ideally the stream would report the number of bytes that could be written
+ // to the underlying Mojo data pipe. As an approximation the high water mark
+ // is set to 1 so that the stream appears ready but producers observing
+ // backpressure won't queue additional chunks in the stream and thus add an
+ // extra layer of buffering.
writable_ = WritableStream::CreateWithCountQueueingStrategy(
- script_state, underlying_sink_, 0);
+ script_state, underlying_sink_, /*high_water_mark=*/1);
}
void SerialPort::OnGetSignals(
@@ -486,4 +586,15 @@ void SerialPort::OnSetSignals(ScriptPromiseResolver* resolver, bool success) {
resolver->Resolve();
}
+void SerialPort::OnClose() {
+ DCHECK(close_resolver_);
+ closing_ = false;
+ port_.reset();
+ client_receiver_.reset();
+
+ ScriptPromiseResolver* close_resolver = close_resolver_;
+ close_resolver_ = nullptr;
+ close_resolver->Resolve();
+}
+
} // namespace blink
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 f4b84df9600..c2a8626509a 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port.h
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port.h
@@ -5,9 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_PORT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERIAL_SERIAL_PORT_H_
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/serial.mojom-blink.h"
+#include "services/device/public/mojom/serial.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/serial/serial.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -40,17 +41,23 @@ class SerialPort final : public ScriptWrappable,
~SerialPort() override;
// Web-exposed functions
- ScriptPromise open(ScriptState*, const SerialOptions* options);
+ ScriptPromise open(ScriptState*,
+ const SerialOptions* options,
+ ExceptionState&);
ReadableStream* readable(ScriptState*, ExceptionState&);
WritableStream* writable(ScriptState*, ExceptionState&);
- ScriptPromise getSignals(ScriptState*);
- ScriptPromise setSignals(ScriptState*, const SerialOutputSignals*);
- void close();
+ ScriptPromise getSignals(ScriptState*, ExceptionState&);
+ ScriptPromise setSignals(ScriptState*,
+ const SerialOutputSignals*,
+ ExceptionState&);
+ ScriptPromise close(ScriptState*, ExceptionState&);
const base::UnguessableToken& token() const { return info_->token; }
void UnderlyingSourceClosed();
void UnderlyingSinkClosed();
+ ScriptPromise ContinueClose(ScriptState*);
+ void AbortClose();
void ContextDestroyed();
void Trace(Visitor*) override;
@@ -66,7 +73,7 @@ class SerialPort final : public ScriptWrappable,
void OnConnectionError();
void OnOpen(mojo::ScopedDataPipeConsumerHandle,
mojo::ScopedDataPipeProducerHandle,
- device::mojom::blink::SerialPortClientRequest,
+ mojo::PendingReceiver<device::mojom::blink::SerialPortClient>,
bool success);
void InitializeReadableStream(ScriptState*,
mojo::ScopedDataPipeConsumerHandle);
@@ -75,6 +82,7 @@ class SerialPort final : public ScriptWrappable,
void OnGetSignals(ScriptPromiseResolver*,
device::mojom::blink::SerialPortControlSignalsPtr);
void OnSetSignals(ScriptPromiseResolver*, bool success);
+ void OnClose();
mojom::blink::SerialPortInfoPtr info_;
Member<Serial> parent_;
@@ -88,11 +96,17 @@ class SerialPort final : public ScriptWrappable,
Member<WritableStream> writable_;
Member<SerialPortUnderlyingSink> underlying_sink_;
+ // Indicates that the port is being closed and so the streams should not be
+ // reopened on demand.
+ bool closing_ = false;
+
// Resolver for the Promise returned by open().
Member<ScriptPromiseResolver> open_resolver_;
// Resolvers for the Promises returned by getSignals() and setSignals() to
// reject them on Mojo connection failure.
HeapHashSet<Member<ScriptPromiseResolver>> signal_resolvers_;
+ // Resolver for the Promise returned by ClosePort().
+ Member<ScriptPromiseResolver> close_resolver_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port.idl b/chromium/third_party/blink/renderer/modules/serial/serial_port.idl
index fb126830669..24f88bfe635 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port.idl
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port.idl
@@ -13,12 +13,12 @@
[CallWith=ScriptState, RaisesException]
readonly attribute WritableStream writable;
- [CallWith=ScriptState, MeasureAs=SerialPortOpen]
+ [CallWith=ScriptState, RaisesException, MeasureAs=SerialPortOpen]
Promise<void> open(SerialOptions options);
- [CallWith=ScriptState]
+ [CallWith=ScriptState, RaisesException]
Promise<SerialInputSignals> getSignals();
- [CallWith=ScriptState]
+ [CallWith=ScriptState, RaisesException]
Promise<void> setSignals(SerialOutputSignals signals);
- [MeasureAs=SerialPortClose]
- void close();
+ [RaisesException, CallWith=ScriptState, MeasureAs=SerialPortClose]
+ Promise<void> close();
};
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 a2867d7c937..0c10f770169 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
@@ -69,11 +69,11 @@ ScriptPromise SerialPortUnderlyingSink::close(ScriptState* script_state) {
watcher_.Cancel();
data_pipe_.reset();
+ serial_port_->UnderlyingSinkClosed();
if (pending_exception_) {
DOMException* exception = pending_exception_;
pending_exception_ = nullptr;
- serial_port_->UnderlyingSinkClosed();
return ScriptPromise::RejectWithDOMException(script_state, exception);
}
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc
index 8ba9a20a54f..0cf7af14900 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/serial/serial_port_underlying_source.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/streams/readable_stream_default_controller_interface.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
@@ -28,22 +27,25 @@ SerialPortUnderlyingSource::SerialPortUnderlyingSource(
}
ScriptPromise SerialPortUnderlyingSource::pull(ScriptState* script_state) {
- // Only one pending call to pull() is allowed by the spec.
- DCHECK(!pending_pull_);
- // pull() shouldn't be called if an error has been signaled to the controller.
+ // pull() signals that the stream wants more data. By resolving immediately
+ // we allow the stream to be canceled before that data is received. pull()
+ // will not be called again until a chunk is enqueued or if an error has been
+ // signaled to the controller.
DCHECK(data_pipe_);
- if (ReadData())
- return ScriptPromise::CastUndefined(script_state);
+ if (!ReadData())
+ ArmWatcher();
- return ArmWatcher(script_state);
+ return ScriptPromise::CastUndefined(script_state);
}
ScriptPromise SerialPortUnderlyingSource::Cancel(ScriptState* script_state,
ScriptValue reason) {
- // TODO(crbug.com/989653): cancel() should trigger a purge of the serial
- // read buffer.
+ // TODO(crbug.com/989653): Rather than calling Close(), cancel() should
+ // trigger a purge of the serial read buffer and wait for the pipe to close to
+ // indicate the purge has been completed.
Close();
+ ExpectPipeClose();
return ScriptPromise::CastUndefined(script_state);
}
@@ -70,19 +72,7 @@ void SerialPortUnderlyingSource::SignalErrorOnClose(DOMException* exception) {
serial_port_->UnderlyingSourceClosed();
}
-void SerialPortUnderlyingSource::ExpectClose() {
- if (data_pipe_) {
- // Pipe is still open. Wait for PipeClosed() to be called.
- expect_close_ = true;
- return;
- }
-
- Controller()->Close();
- serial_port_->UnderlyingSourceClosed();
-}
-
void SerialPortUnderlyingSource::Trace(Visitor* visitor) {
- visitor->Trace(pending_pull_);
visitor->Trace(pending_exception_);
visitor->Trace(serial_port_);
UnderlyingSourceBase::Trace(visitor);
@@ -113,15 +103,12 @@ bool SerialPortUnderlyingSource::ReadData() {
}
}
-ScriptPromise SerialPortUnderlyingSource::ArmWatcher(
- ScriptState* script_state) {
+void SerialPortUnderlyingSource::ArmWatcher() {
MojoResult ready_result;
mojo::HandleSignalsState ready_state;
MojoResult result = watcher_.Arm(&ready_result, &ready_state);
- if (result == MOJO_RESULT_OK) {
- pending_pull_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- return pending_pull_->Promise();
- }
+ if (result == MOJO_RESULT_OK)
+ return;
DCHECK_EQ(ready_result, MOJO_RESULT_OK);
if (ready_state.readable()) {
@@ -130,24 +117,15 @@ ScriptPromise SerialPortUnderlyingSource::ArmWatcher(
} else if (ready_state.peer_closed()) {
PipeClosed();
}
-
- return ScriptPromise::CastUndefined(script_state);
}
void SerialPortUnderlyingSource::OnHandleReady(
MojoResult result,
const mojo::HandleSignalsState& state) {
- DCHECK(pending_pull_);
-
switch (result) {
case MOJO_RESULT_OK: {
bool read_result = ReadData();
DCHECK(read_result);
- // If the pipe was closed |pending_pull_| will have been resolved.
- if (pending_pull_) {
- pending_pull_->Resolve();
- pending_pull_ = nullptr;
- }
break;
}
case MOJO_RESULT_SHOULD_WAIT:
@@ -159,6 +137,17 @@ void SerialPortUnderlyingSource::OnHandleReady(
}
}
+void SerialPortUnderlyingSource::ExpectPipeClose() {
+ if (data_pipe_) {
+ // The pipe is still open. Wait for PipeClosed() to be called.
+ expect_close_ = true;
+ return;
+ }
+
+ Controller()->Close();
+ serial_port_->UnderlyingSourceClosed();
+}
+
void SerialPortUnderlyingSource::PipeClosed() {
if (pending_exception_) {
Controller()->Error(pending_exception_);
@@ -174,10 +163,6 @@ void SerialPortUnderlyingSource::PipeClosed() {
void SerialPortUnderlyingSource::Close() {
watcher_.Cancel();
data_pipe_.reset();
- if (pending_pull_) {
- pending_pull_->Resolve();
- pending_pull_ = nullptr;
- }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h
index c4a803af0ec..1d6116aa6d0 100644
--- a/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h
+++ b/chromium/third_party/blink/renderer/modules/serial/serial_port_underlying_source.h
@@ -12,7 +12,6 @@
namespace blink {
class DOMException;
-class ScriptPromiseResolver;
class SerialPort;
class SerialPortUnderlyingSource : public UnderlyingSourceBase {
@@ -28,7 +27,6 @@ class SerialPortUnderlyingSource : public UnderlyingSourceBase {
void SignalErrorImmediately(DOMException*);
void SignalErrorOnClose(DOMException*);
- void ExpectClose();
void Trace(Visitor*) override;
@@ -37,15 +35,15 @@ class SerialPortUnderlyingSource : public UnderlyingSourceBase {
// |Controller()| or the pipe was closed, and false otherwise.
bool ReadData();
- ScriptPromise ArmWatcher(ScriptState*);
+ void ArmWatcher();
void OnHandleReady(MojoResult, const mojo::HandleSignalsState&);
+ void ExpectPipeClose();
void PipeClosed();
void Close();
mojo::ScopedDataPipeConsumerHandle data_pipe_;
mojo::SimpleWatcher watcher_;
Member<SerialPort> serial_port_;
- Member<ScriptPromiseResolver> pending_pull_;
Member<DOMException> pending_exception_;
bool expect_close_ = false;
};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/client.idl b/chromium/third_party/blink/renderer/modules/service_worker/client.idl
index f11f4d44fc9..640ef5c6395 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/client.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/client.idl
@@ -22,5 +22,5 @@ enum ClientLifecycleState {
// FIXME: frameType is non-standard, see https://crbug.com/697110
[CallWith=ScriptState] readonly attribute ContextFrameType frameType;
- [RuntimeEnabled=ServiceWorkerFilterFrozen] readonly attribute ClientLifecycleState lifecycleState;
+ [RuntimeEnabled=ServiceWorkerClientLifecycleState] readonly attribute ClientLifecycleState lifecycleState;
};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl b/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl
index c30fdc809bb..f8d2306379f 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl
@@ -20,6 +20,5 @@ enum ClientLifecycleStateQuery {
// https://w3c.github.io/ServiceWorker/#dictdef-clientqueryoptions
dictionary ClientQueryOptions {
boolean includeUncontrolled = false;
- [RuntimeEnabled=ServiceWorkerFilterFrozen] ClientLifecycleStateQuery lifecycleState = "active";
ClientType type = "window";
};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
index 78d1139b5e3..cf4f35ebd16 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
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 6bc45178eff..7de6a92c87b 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
@@ -125,9 +125,8 @@ bool IsClientRequest(network::mojom::RequestContextFrameType frame_type,
// Notifies the result of FetchDataLoader to |callback_|, the other endpoint
// for which is passed to the browser process via
// blink.mojom.ServiceWorkerFetchResponseCallback.OnResponseStream().
-class FetchLoaderClient final
- : public GarbageCollectedFinalized<FetchLoaderClient>,
- public FetchDataLoader::Client {
+class FetchLoaderClient final : public GarbageCollected<FetchLoaderClient>,
+ public FetchDataLoader::Client {
USING_GARBAGE_COLLECTED_MIXIN(FetchLoaderClient);
public:
@@ -217,7 +216,7 @@ void FetchRespondWithObserver::OnResponseRejected(
response->status_text = "";
response->error = error;
To<ServiceWorkerGlobalScope>(GetExecutionContext())
- ->RespondToFetchEvent(event_id_, std::move(response),
+ ->RespondToFetchEvent(event_id_, request_url_, std::move(response),
event_dispatch_time_, base::TimeTicks::Now());
}
@@ -324,8 +323,8 @@ void FetchRespondWithObserver::OnResponseFulfilled(
// Handle the blob response body.
fetch_api_response->blob = blob_data_handle;
service_worker_global_scope->RespondToFetchEvent(
- event_id_, std::move(fetch_api_response), event_dispatch_time_,
- base::TimeTicks::Now());
+ event_id_, request_url_, std::move(fetch_api_response),
+ event_dispatch_time_, base::TimeTicks::Now());
return;
}
@@ -350,19 +349,20 @@ void FetchRespondWithObserver::OnResponseFulfilled(
}
service_worker_global_scope->RespondToFetchEventWithResponseStream(
- event_id_, std::move(fetch_api_response), std::move(stream_handle),
- event_dispatch_time_, base::TimeTicks::Now());
+ event_id_, request_url_, std::move(fetch_api_response),
+ std::move(stream_handle), event_dispatch_time_, base::TimeTicks::Now());
return;
}
service_worker_global_scope->RespondToFetchEvent(
- event_id_, std::move(fetch_api_response), event_dispatch_time_,
- base::TimeTicks::Now());
+ event_id_, request_url_, std::move(fetch_api_response),
+ event_dispatch_time_, base::TimeTicks::Now());
}
void FetchRespondWithObserver::OnNoResponse() {
DCHECK(GetExecutionContext());
To<ServiceWorkerGlobalScope>(GetExecutionContext())
- ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_,
+ ->RespondToFetchEventWithNoResponse(event_id_, request_url_,
+ event_dispatch_time_,
base::TimeTicks::Now());
}
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 abd45b54e55..e18cf9dc8c0 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_RESPOND_WITH_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_RESPOND_WITH_OBSERVER_H_
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
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 6bf52b2494e..9732b7eba96 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
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 3e15f3af490..63e8cee54f1 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_RESPOND_WITH_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_RESPOND_WITH_OBSERVER_H_
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -25,7 +25,7 @@ class WaitUntilObserver;
// each event should implement the procedure of the three behaviors by
// overriding onResponseFulfilled, onResponseRejected and onNoResponse.
class MODULES_EXPORT RespondWithObserver
- : public GarbageCollectedFinalized<RespondWithObserver>,
+ : public GarbageCollected<RespondWithObserver>,
public ContextClient {
USING_GARBAGE_COLLECTED_MIXIN(RespondWithObserver);
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc
index 66703e150f1..0163be1110b 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc
@@ -56,7 +56,7 @@ const AtomicString& ServiceWorker::InterfaceName() const {
void ServiceWorker::postMessage(ScriptState* script_state,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
PostMessageOptions* options = PostMessageOptions::Create();
if (!transfer.IsEmpty())
@@ -116,10 +116,8 @@ String ServiceWorker::scriptURL() const {
String ServiceWorker::state() const {
switch (state_) {
- case mojom::blink::ServiceWorkerState::kUnknown:
- // The web platform should never see this internal state
- NOTREACHED();
- return "unknown";
+ case mojom::blink::ServiceWorkerState::kParsed:
+ return "parsed";
case mojom::blink::ServiceWorkerState::kInstalling:
return "installing";
case mojom::blink::ServiceWorkerState::kInstalled:
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h
index 13e6d1d1649..4d6385ef29c 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h
@@ -55,7 +55,7 @@ class MODULES_EXPORT ServiceWorker final
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(ServiceWorker);
USING_PRE_FINALIZER(ServiceWorker, Dispose);
-
+
public:
static ServiceWorker* From(ExecutionContext*,
mojom::blink::ServiceWorkerObjectInfoPtr);
@@ -80,7 +80,7 @@ class MODULES_EXPORT ServiceWorker final
void postMessage(ScriptState*,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(ScriptState*,
const ScriptValue& message,
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
index 8a8e121d8af..297f47b118b 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
@@ -86,7 +86,7 @@ String ServiceWorkerClient::lifecycleState() const {
void ServiceWorkerClient::postMessage(ScriptState* script_state,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState& exception_state) {
PostMessageOptions* options = PostMessageOptions::Create();
if (!transfer.IsEmpty())
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h
index 0a148390ccf..b44ef1ca091 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h
@@ -36,7 +36,7 @@ class MODULES_EXPORT ServiceWorkerClient : public ScriptWrappable {
String lifecycleState() const;
void postMessage(ScriptState*,
const ScriptValue& message,
- Vector<ScriptValue>& transfer,
+ HeapVector<ScriptValue>& transfer,
ExceptionState&);
void postMessage(ScriptState*,
const ScriptValue& message,
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc
index 406718e2126..9c4ee806a60 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc
@@ -39,18 +39,6 @@ mojom::ServiceWorkerClientType GetClientType(const String& type) {
return mojom::ServiceWorkerClientType::kWindow;
}
-mojom::ServiceWorkerClientLifecycleStateQuery GetLifecycleStateQueryType(
- const String& type) {
- if (type == "active")
- return mojom::ServiceWorkerClientLifecycleStateQuery::kActive;
- if (type == "frozen")
- return mojom::ServiceWorkerClientLifecycleStateQuery::kFrozen;
- if (type == "all")
- return mojom::ServiceWorkerClientLifecycleStateQuery::kAll;
- NOTREACHED();
- return mojom::ServiceWorkerClientLifecycleStateQuery::kActive;
-}
-
void DidGetClient(ScriptPromiseResolver* resolver,
mojom::blink::ServiceWorkerClientInfoPtr info) {
if (!resolver->GetExecutionContext() ||
@@ -149,8 +137,7 @@ ScriptPromise ServiceWorkerClients::matchAll(
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
global_scope->GetServiceWorkerHost()->GetClients(
mojom::blink::ServiceWorkerClientQueryOptions::New(
- options->includeUncontrolled(), GetClientType(options->type()),
- GetLifecycleStateQueryType(options->lifecycleState())),
+ options->includeUncontrolled(), GetClientType(options->type())),
WTF::Bind(&DidGetClients, WrapPersistent(resolver)));
return resolver->Promise();
}
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h
index 168f1ddf22a..f2ff5ac9e15 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h
@@ -33,7 +33,7 @@
#include <memory>
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink-forward.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
index 4fff53a2573..a89c3e20a2f 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -46,6 +46,7 @@ struct StubScriptFunction {
size_t CallCount() { return call_count_; }
ScriptValue Arg() { return arg_; }
+ void Trace(blink::Visitor* visitor) { visitor->Trace(arg_); }
private:
size_t call_count_;
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h
index 27f011d1985..60d2bc1d96f 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_ERROR_H_
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "v8/include/v8.h"
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 d3137079f20..395ec6c1746 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
@@ -61,7 +61,6 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
-#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
#include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
@@ -181,16 +180,18 @@ static std::string MojoEnumToString(T mojo_enum) {
ServiceWorkerGlobalScope* ServiceWorkerGlobalScope::Create(
ServiceWorkerThread* thread,
std::unique_ptr<GlobalScopeCreationParams> creation_params,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager,
mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote,
base::TimeTicks time_origin) {
DCHECK_EQ(creation_params->off_main_thread_fetch_option,
OffMainThreadWorkerScriptFetchOption::kEnabled);
+#if DCHECK_IS_ON()
// If the script is being loaded via script streaming, the script is not yet
// loaded.
- if (thread->GetInstalledScriptsManager() &&
- thread->GetInstalledScriptsManager()->IsScriptInstalled(
- creation_params->script_url)) {
+ if (installed_scripts_manager && installed_scripts_manager->IsScriptInstalled(
+ creation_params->script_url)) {
// CSP headers, referrer policy, and origin trial tokens will be provided by
// the InstalledScriptsManager in EvaluateClassicScript().
DCHECK(creation_params->outside_content_security_policy_headers.IsEmpty());
@@ -198,18 +199,22 @@ ServiceWorkerGlobalScope* ServiceWorkerGlobalScope::Create(
creation_params->referrer_policy);
DCHECK(creation_params->origin_trial_tokens->IsEmpty());
}
+#endif // DCHECK_IS_ON()
return MakeGarbageCollected<ServiceWorkerGlobalScope>(
- std::move(creation_params), thread, std::move(cache_storage_remote),
- time_origin);
+ std::move(creation_params), thread, std::move(installed_scripts_manager),
+ std::move(cache_storage_remote), time_origin);
}
ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
ServiceWorkerThread* thread,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager,
mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote,
base::TimeTicks time_origin)
: WorkerGlobalScope(std::move(creation_params), thread, time_origin),
+ installed_scripts_manager_(std::move(installed_scripts_manager)),
cache_storage_remote_(std::move(cache_storage_remote)) {
// Create the idle timer. At this point the timer is not started. It will be
// started by DidEvaluateScript().
@@ -233,6 +238,12 @@ void ServiceWorkerGlobalScope::FetchAndRunClassicScript(
const v8_inspector::V8StackTraceId& stack_id) {
DCHECK(!IsContextPaused());
+ if (installed_scripts_manager_) {
+ // This service worker is installed. Load and run the installed script.
+ LoadAndRunInstalledClassicScript(script_url, stack_id);
+ return;
+ }
+
// Step 9. "Switching on job's worker type, run these substeps with the
// following options:"
// "classic: Fetch a classic worker script given job's serialized script url,
@@ -279,75 +290,17 @@ void ServiceWorkerGlobalScope::FetchAndRunModuleScript(
WorkerResourceTimingNotifier& outside_resource_timing_notifier,
network::mojom::CredentialsMode credentials_mode) {
DCHECK(IsContextThread());
+
+ // Start fetching scripts regardless of whether this service worker is
+ // installed. For the installed case, the scripts will be read from the
+ // service worker script storage during module script fetch (see
+ // InstalledServiceWorkerModuleScriptFetcher).
FetchModuleScript(module_url_record, outside_settings_object,
outside_resource_timing_notifier,
mojom::RequestContextType::SERVICE_WORKER, credentials_mode,
ModuleScriptCustomFetchType::kWorkerConstructor,
MakeGarbageCollected<ServiceWorkerModuleTreeClient>(
- Modulator::From(ScriptController()->GetScriptState())));
-}
-
-void ServiceWorkerGlobalScope::RunInstalledClassicScript(
- const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id) {
- DCHECK(IsContextThread());
-
- InstalledScriptsManager* installed_scripts_manager =
- GetThread()->GetInstalledScriptsManager();
- DCHECK(installed_scripts_manager);
- DCHECK(installed_scripts_manager->IsScriptInstalled(script_url));
-
- // GetScriptData blocks until the script is received from the browser.
- std::unique_ptr<InstalledScriptsManager::ScriptData> script_data =
- installed_scripts_manager->GetScriptData(script_url);
- if (!script_data) {
- ReportingProxy().DidFailToLoadClassicScript();
- // This will eventually initiate worker thread termination. See
- // ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() for details.
- close();
- return;
- }
- ReportingProxy().DidLoadClassicScript();
-
- auto referrer_policy = network::mojom::ReferrerPolicy::kDefault;
- if (!script_data->GetReferrerPolicy().IsNull()) {
- SecurityPolicy::ReferrerPolicyFromHeaderValue(
- script_data->GetReferrerPolicy(),
- kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
- }
-
- // Construct a ContentSecurityPolicy object to convert
- // ContentSecurityPolicyResponseHeaders to CSPHeaderAndType.
- // TODO(nhiroki): Find an efficient way to do this.
- auto* content_security_policy = MakeGarbageCollected<ContentSecurityPolicy>();
- content_security_policy->DidReceiveHeaders(
- script_data->GetContentSecurityPolicyResponseHeaders());
-
- RunClassicScript(
- script_url, referrer_policy, script_data->GetResponseAddressSpace(),
- content_security_policy->Headers(),
- script_data->CreateOriginTrialTokens().get(),
- script_data->TakeSourceText(), script_data->TakeMetaData(), stack_id);
-}
-
-void ServiceWorkerGlobalScope::RunInstalledModuleScript(
- const KURL& module_url_record,
- const FetchClientSettingsObjectSnapshot& outside_settings_object,
- network::mojom::CredentialsMode credentials_mode) {
- DCHECK(IsContextThread());
- // Currently we don't plumb performance timing for toplevel service worker
- // script fetch. https://crbug.com/954005
- auto* outside_resource_timing_notifier =
- MakeGarbageCollected<NullWorkerResourceTimingNotifier>();
-
- // The installed scripts will be read from the service worker script storage
- // during module script fetch.
- FetchModuleScript(module_url_record, outside_settings_object,
- *outside_resource_timing_notifier,
- mojom::RequestContextType::SERVICE_WORKER, credentials_mode,
- ModuleScriptCustomFetchType::kInstalledServiceWorker,
- MakeGarbageCollected<ServiceWorkerModuleTreeClient>(
- Modulator::From(ScriptController()->GetScriptState())));
+ ScriptController()->GetScriptState()));
}
void ServiceWorkerGlobalScope::Dispose() {
@@ -359,6 +312,11 @@ void ServiceWorkerGlobalScope::Dispose() {
WorkerGlobalScope::Dispose();
}
+InstalledScriptsManager*
+ServiceWorkerGlobalScope::GetInstalledScriptsManager() {
+ return installed_scripts_manager_.get();
+}
+
void ServiceWorkerGlobalScope::CountWorkerScript(size_t script_size,
size_t cached_metadata_size) {
DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic);
@@ -536,6 +494,47 @@ void ServiceWorkerGlobalScope::Initialize(
DCHECK_EQ(appcache_id, mojom::blink::kAppCacheNoCacheId);
}
+void ServiceWorkerGlobalScope::LoadAndRunInstalledClassicScript(
+ const KURL& script_url,
+ const v8_inspector::V8StackTraceId& stack_id) {
+ DCHECK(IsContextThread());
+
+ DCHECK(installed_scripts_manager_);
+ DCHECK(installed_scripts_manager_->IsScriptInstalled(script_url));
+
+ // GetScriptData blocks until the script is received from the browser.
+ std::unique_ptr<InstalledScriptsManager::ScriptData> script_data =
+ installed_scripts_manager_->GetScriptData(script_url);
+ if (!script_data) {
+ ReportingProxy().DidFailToFetchClassicScript();
+ // This will eventually initiate worker thread termination. See
+ // ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() for details.
+ close();
+ return;
+ }
+ ReportingProxy().DidLoadClassicScript();
+
+ auto referrer_policy = network::mojom::ReferrerPolicy::kDefault;
+ if (!script_data->GetReferrerPolicy().IsNull()) {
+ SecurityPolicy::ReferrerPolicyFromHeaderValue(
+ script_data->GetReferrerPolicy(),
+ kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
+ }
+
+ // Construct a ContentSecurityPolicy object to convert
+ // ContentSecurityPolicyResponseHeaders to CSPHeaderAndType.
+ // TODO(nhiroki): Find an efficient way to do this.
+ auto* content_security_policy = MakeGarbageCollected<ContentSecurityPolicy>();
+ content_security_policy->DidReceiveHeaders(
+ script_data->GetContentSecurityPolicyResponseHeaders());
+
+ RunClassicScript(
+ script_url, referrer_policy, script_data->GetResponseAddressSpace(),
+ content_security_policy->Headers(),
+ script_data->CreateOriginTrialTokens().get(),
+ script_data->TakeSourceText(), script_data->TakeMetaData(), stack_id);
+}
+
// https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm
void ServiceWorkerGlobalScope::RunClassicScript(
const KURL& response_url,
@@ -576,6 +575,10 @@ ServiceWorkerRegistration* ServiceWorkerGlobalScope::registration() {
return registration_;
}
+::blink::ServiceWorker* ServiceWorkerGlobalScope::serviceWorker() {
+ return service_worker_;
+}
+
ScriptPromise ServiceWorkerGlobalScope::skipWaiting(ScriptState* script_state) {
ExecutionContext* execution_context = ExecutionContext::From(script_state);
// FIXME: short-term fix, see details at:
@@ -695,6 +698,33 @@ bool ServiceWorkerGlobalScope::AddEventListenerInternal(
options);
}
+bool ServiceWorkerGlobalScope::FetchClassicImportedScript(
+ const KURL& script_url,
+ KURL* out_response_url,
+ String* out_source_code,
+ std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data) {
+ // InstalledScriptsManager is used only for starting installed service
+ // workers.
+ if (installed_scripts_manager_) {
+ // All imported scripts must be installed. This is already checked in
+ // ServiceWorkerGlobalScope::importScripts().
+ DCHECK(installed_scripts_manager_->IsScriptInstalled(script_url));
+ std::unique_ptr<InstalledScriptsManager::ScriptData> script_data =
+ installed_scripts_manager_->GetScriptData(script_url);
+ if (!script_data)
+ return false;
+ *out_response_url = script_url;
+ *out_source_code = script_data->TakeSourceText();
+ *out_cached_meta_data = script_data->TakeMetaData();
+ // TODO(shimazu): Add appropriate probes for inspector.
+ return true;
+ }
+ // This is a new service worker. Proceed with importing scripts and installing
+ // them.
+ return WorkerGlobalScope::FetchClassicImportedScript(
+ script_url, out_response_url, out_source_code, out_cached_meta_data);
+}
+
const AtomicString& ServiceWorkerGlobalScope::InterfaceName() const {
return event_target_names::kServiceWorkerGlobalScope;
}
@@ -726,25 +756,30 @@ void ServiceWorkerGlobalScope::DispatchExtendableEventWithRespondWith(
void ServiceWorkerGlobalScope::Trace(blink::Visitor* visitor) {
visitor->Trace(clients_);
visitor->Trace(registration_);
+ visitor->Trace(service_worker_);
visitor->Trace(service_worker_objects_);
visitor->Trace(pending_preload_fetch_events_);
WorkerGlobalScope::Trace(visitor);
}
+bool ServiceWorkerGlobalScope::HasRelatedFetchEvent(
+ const KURL& request_url) const {
+ auto it = unresponded_fetch_event_counts_.find(request_url);
+ return it != unresponded_fetch_event_counts_.end();
+}
+
void ServiceWorkerGlobalScope::importScripts(
const HeapVector<StringOrTrustedScriptURL>& urls,
ExceptionState& exception_state) {
- InstalledScriptsManager* installed_scripts_manager =
- GetThread()->GetInstalledScriptsManager();
for (const StringOrTrustedScriptURL& stringOrUrl : urls) {
String string_url = stringOrUrl.IsString()
? stringOrUrl.GetAsString()
: stringOrUrl.GetAsTrustedScriptURL()->toString();
KURL completed_url = CompleteURL(string_url);
- if (installed_scripts_manager &&
- !installed_scripts_manager->IsScriptInstalled(completed_url)) {
- DCHECK(installed_scripts_manager->IsScriptInstalled(Url()));
+ if (installed_scripts_manager_ &&
+ !installed_scripts_manager_->IsScriptInstalled(completed_url)) {
+ DCHECK(installed_scripts_manager_->IsScriptInstalled(Url()));
exception_state.ThrowDOMException(
DOMExceptionCode::kNetworkError,
"Failed to import '" + completed_url.ElidedString() +
@@ -903,6 +938,7 @@ void ServiceWorkerGlobalScope::DidHandleExtendableMessageEvent(
void ServiceWorkerGlobalScope::RespondToFetchEventWithNoResponse(
int fetch_event_id,
+ const KURL& request_url,
base::TimeTicks event_dispatch_time,
base::TimeTicks respond_with_settled_time) {
DCHECK(IsContextThread());
@@ -920,11 +956,14 @@ void ServiceWorkerGlobalScope::RespondToFetchEventWithNoResponse(
timing->dispatch_event_time = event_dispatch_time;
timing->respond_with_settled_time = respond_with_settled_time;
+ NoteRespondedToFetchEvent(request_url);
+
response_callback->OnFallback(std::move(timing));
}
void ServiceWorkerGlobalScope::RespondToFetchEvent(
int fetch_event_id,
+ const KURL& request_url,
mojom::blink::FetchAPIResponsePtr response,
base::TimeTicks event_dispatch_time,
base::TimeTicks respond_with_settled_time) {
@@ -943,11 +982,14 @@ void ServiceWorkerGlobalScope::RespondToFetchEvent(
timing->dispatch_event_time = event_dispatch_time;
timing->respond_with_settled_time = respond_with_settled_time;
+ NoteRespondedToFetchEvent(request_url);
+
response_callback->OnResponse(std::move(response), std::move(timing));
}
void ServiceWorkerGlobalScope::RespondToFetchEventWithResponseStream(
int fetch_event_id,
+ const KURL& request_url,
mojom::blink::FetchAPIResponsePtr response,
mojom::blink::ServiceWorkerStreamHandlePtr body_as_stream,
base::TimeTicks event_dispatch_time,
@@ -967,6 +1009,8 @@ void ServiceWorkerGlobalScope::RespondToFetchEventWithResponseStream(
timing->dispatch_event_time = event_dispatch_time;
timing->respond_with_settled_time = respond_with_settled_time;
+ NoteRespondedToFetchEvent(request_url);
+
response_callback->OnResponseStream(
std::move(response), std::move(body_as_stream), std::move(timing));
}
@@ -1235,23 +1279,6 @@ ServiceWorkerGlobalScope::GetServiceWorkerHost() {
return service_worker_host_.get();
}
-int ServiceWorkerGlobalScope::WillStartTask() {
- DCHECK(IsContextThread());
- DCHECK(timeout_timer_);
- return timeout_timer_->StartEvent(base::DoNothing());
-}
-
-void ServiceWorkerGlobalScope::DidEndTask(int task_id) {
- DCHECK(IsContextThread());
- DCHECK(timeout_timer_);
- // Check if the task is still alive, since the timeout timer might have
- // already timed it out (which calls the abort callback passed to StartEvent()
- // but that does nothing, since we just check HasEvent() here instead of
- // maintaining our own set of started events).
- if (timeout_timer_->HasEvent(task_id))
- timeout_timer_->EndEvent(task_id);
-}
-
void ServiceWorkerGlobalScope::OnIdleTimeout() {
DCHECK(IsContextThread());
// RequestedTermination() returns true if ServiceWorkerTimeoutTimer agrees
@@ -1379,6 +1406,8 @@ void ServiceWorkerGlobalScope::DispatchFetchEventInternal(
pending_preload_fetch_events_.insert(event_id, fetch_event);
}
+ NoteNewFetchEvent(request->url());
+
DispatchExtendableEventWithRespondWith(fetch_event, wait_until_observer,
respond_with_observer);
}
@@ -1386,11 +1415,8 @@ void ServiceWorkerGlobalScope::DispatchFetchEventInternal(
void ServiceWorkerGlobalScope::SetFetchHandlerExistence(
FetchHandlerExistence fetch_handler_existence) {
DCHECK(IsContextThread());
- if (fetch_handler_existence == FetchHandlerExistence::EXISTS &&
- base::FeatureList::IsEnabled(
- features::kServiceWorkerIsolateInForeground)) {
+ if (fetch_handler_existence == FetchHandlerExistence::EXISTS)
GetThread()->GetIsolate()->IsolateInForegroundNotification();
- }
}
void ServiceWorkerGlobalScope::DispatchFetchEventForSubresource(
@@ -1426,8 +1452,10 @@ void ServiceWorkerGlobalScope::InitializeGlobalScope(
mojo::PendingAssociatedRemote<mojom::blink::ServiceWorkerHost>
service_worker_host,
mojom::blink::ServiceWorkerRegistrationObjectInfoPtr registration_info,
+ mojom::blink::ServiceWorkerObjectInfoPtr service_worker_info,
mojom::blink::FetchHandlerExistence fetch_hander_existence) {
DCHECK(IsContextThread());
+ DCHECK(!global_scope_initialized_);
DCHECK(service_worker_host.is_valid());
DCHECK(!service_worker_host_);
@@ -1442,9 +1470,34 @@ void ServiceWorkerGlobalScope::InitializeGlobalScope(
registration_ = MakeGarbageCollected<ServiceWorkerRegistration>(
GetExecutionContext(), std::move(registration_info));
+ // Set ServiceWorkerGlobalScope#serviceWorker.
+ DCHECK_NE(service_worker_info->version_id,
+ mojom::blink::kInvalidServiceWorkerVersionId);
+ DCHECK(service_worker_info->host_remote.is_valid());
+ DCHECK(service_worker_info->receiver.is_valid());
+ service_worker_ = ::blink::ServiceWorker::From(
+ GetExecutionContext(), std::move(service_worker_info));
+
SetFetchHandlerExistence(fetch_hander_existence);
- ReadyToRunWorkerScript();
+ global_scope_initialized_ = true;
+ if (!pause_evaluation_)
+ ReadyToRunWorkerScript();
+}
+
+void ServiceWorkerGlobalScope::PauseEvaluation() {
+ DCHECK(IsContextThread());
+ DCHECK(!global_scope_initialized_);
+ DCHECK(!pause_evaluation_);
+ pause_evaluation_ = true;
+}
+
+void ServiceWorkerGlobalScope::ResumeEvaluation() {
+ DCHECK(IsContextThread());
+ DCHECK(pause_evaluation_);
+ pause_evaluation_ = false;
+ if (global_scope_initialized_)
+ ReadyToRunWorkerScript();
}
void ServiceWorkerGlobalScope::DispatchInstallEvent(
@@ -1628,24 +1681,6 @@ void ServiceWorkerGlobalScope::DispatchExtendableMessageEvent(
DispatchExtendableMessageEventInternal(event_id, std::move(event));
}
-void ServiceWorkerGlobalScope::DispatchExtendableMessageEventWithCustomTimeout(
- mojom::blink::ExtendableMessageEventPtr event,
- base::TimeDelta timeout,
- DispatchExtendableMessageEventCallback callback) {
- DCHECK(IsContextThread());
- int event_id = timeout_timer_->StartEventWithCustomTimeout(
- CreateAbortCallback(&message_event_callbacks_), timeout);
- message_event_callbacks_.Set(event_id, std::move(callback));
- TRACE_EVENT_WITH_FLOW0(
- "ServiceWorker",
- "ServiceWorkerGlobalScope::"
- "DispatchExtendableMessageEventWithCustomTimeout",
- TRACE_ID_WITH_SCOPE(kServiceWorkerGlobalScopeTraceScope,
- TRACE_ID_LOCAL(event_id)),
- TRACE_EVENT_FLAG_FLOW_OUT);
- DispatchExtendableMessageEventInternal(event_id, std::move(event));
-}
-
void ServiceWorkerGlobalScope::DispatchFetchEventForMainResource(
mojom::blink::DispatchFetchEventParamsPtr params,
mojo::PendingRemote<mojom::blink::ServiceWorkerFetchResponseCallback>
@@ -1893,6 +1928,20 @@ void ServiceWorkerGlobalScope::DispatchPaymentRequestEvent(
PaymentRequestRespondWithObserver* respond_with_observer =
PaymentRequestRespondWithObserver::Create(this, event_id,
wait_until_observer);
+
+ // Update respond_with_observer to check for required information specified in
+ // the event_data during response validation.
+ if (event_data->payment_options) {
+ respond_with_observer->set_should_have_payer_name(
+ event_data->payment_options->request_payer_name);
+ respond_with_observer->set_should_have_payer_email(
+ event_data->payment_options->request_payer_email);
+ respond_with_observer->set_should_have_payer_phone(
+ event_data->payment_options->request_payer_phone);
+ respond_with_observer->set_should_have_shipping_info(
+ event_data->payment_options->request_shipping);
+ }
+
mojo::PendingRemote<payments::mojom::blink::PaymentHandlerHost>
payment_handler_host = std::move(event_data->payment_handler_host);
Event* event = PaymentRequestEvent::Create(
@@ -1907,8 +1956,7 @@ void ServiceWorkerGlobalScope::DispatchPaymentRequestEvent(
}
void ServiceWorkerGlobalScope::DispatchCookieChangeEvent(
- const WebCanonicalCookie& cookie,
- ::network::mojom::CookieChangeCause change_cause,
+ network::mojom::blink::CookieChangeInfoPtr change,
DispatchCookieChangeEventCallback callback) {
DCHECK(IsContextThread());
int event_id = timeout_timer_->StartEvent(
@@ -1925,7 +1973,8 @@ void ServiceWorkerGlobalScope::DispatchCookieChangeEvent(
HeapVector<Member<CookieListItem>> changed;
HeapVector<Member<CookieListItem>> deleted;
- CookieChangeEvent::ToEventInfo(cookie, change_cause, changed, deleted);
+ CookieChangeEvent::ToEventInfo(change->cookie, change->cause, changed,
+ deleted);
Event* event = ExtendableCookieChangeEvent::Create(
event_type_names::kCookiechange, std::move(changed), std::move(deleted),
observer);
@@ -1982,4 +2031,22 @@ void ServiceWorkerGlobalScope::AddMessageToConsole(
/* column_number= */ 0)));
}
+void ServiceWorkerGlobalScope::NoteNewFetchEvent(const KURL& request_url) {
+ auto it = unresponded_fetch_event_counts_.find(request_url);
+ if (it == unresponded_fetch_event_counts_.end()) {
+ unresponded_fetch_event_counts_.insert(request_url, 1);
+ } else {
+ it->value += 1;
+ }
+}
+
+void ServiceWorkerGlobalScope::NoteRespondedToFetchEvent(
+ const KURL& request_url) {
+ auto it = unresponded_fetch_event_counts_.find(request_url);
+ DCHECK_GE(it->value, 1);
+ it->value -= 1;
+ if (it->value == 0)
+ unresponded_fetch_event_counts_.erase(it);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
index daeae831872..a31bb47b710 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
@@ -38,16 +38,18 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h"
#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/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/service_worker_installed_scripts_manager.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.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/forward.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
@@ -59,6 +61,7 @@ class ScriptPromise;
class ScriptState;
class ServiceWorker;
class ServiceWorkerClients;
+class ServiceWorkerInstalledScriptsManager;
class ServiceWorkerRegistration;
class ServiceWorkerThread;
class StringOrTrustedScriptURL;
@@ -83,13 +86,16 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
static ServiceWorkerGlobalScope* Create(
ServiceWorkerThread*,
std::unique_ptr<GlobalScopeCreationParams>,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>,
mojo::PendingRemote<mojom::blink::CacheStorage>,
base::TimeTicks time_origin);
- ServiceWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
- ServiceWorkerThread*,
- mojo::PendingRemote<mojom::blink::CacheStorage>,
- base::TimeTicks time_origin);
+ ServiceWorkerGlobalScope(
+ std::unique_ptr<GlobalScopeCreationParams>,
+ ServiceWorkerThread*,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>,
+ mojo::PendingRemote<mojom::blink::CacheStorage>,
+ base::TimeTicks time_origin);
~ServiceWorkerGlobalScope() override;
// ExecutionContext overrides:
@@ -103,33 +109,20 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
const Vector<CSPHeaderAndType>& response_csp_headers,
const Vector<String>* response_origin_trial_tokens,
int64_t appcache_id) override;
- // Fetches and runs the top-level classic worker script for the 'new' or
- // 'update' service worker cases.
+ // Fetches and runs the top-level classic worker script.
void FetchAndRunClassicScript(
const KURL& script_url,
const FetchClientSettingsObjectSnapshot& outside_settings_object,
WorkerResourceTimingNotifier& outside_resource_timing_notifier,
const v8_inspector::V8StackTraceId& stack_id) override;
- // Fetches and runs the top-level module worker script for the 'new' or
- // 'update' service worker cases.
+ // Fetches and runs the top-level module worker script.
void FetchAndRunModuleScript(
const KURL& module_url_record,
const FetchClientSettingsObjectSnapshot& outside_settings_object,
WorkerResourceTimingNotifier& outside_resource_timing_notifier,
network::mojom::CredentialsMode) override;
void Dispose() override;
-
- // Runs the installed top-level classic worker script for the 'installed'
- // service worker case.
- void RunInstalledClassicScript(const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id);
-
- // Runs the installed top-level module worker script for the 'installed'
- // service worker case.
- void RunInstalledModuleScript(
- const KURL& module_url_record,
- const FetchClientSettingsObjectSnapshot& outside_settings_object,
- network::mojom::CredentialsMode);
+ InstalledScriptsManager* GetInstalledScriptsManager() override;
// Counts an evaluated script and its size. Called for the main worker script.
void CountWorkerScript(size_t script_size, size_t cached_metadata_size);
@@ -144,6 +137,7 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
// ServiceWorkerGlobalScope.idl
ServiceWorkerClients* clients();
ServiceWorkerRegistration* registration();
+ ::blink::ServiceWorker* serviceWorker();
ScriptPromise fetch(ScriptState*,
const RequestInfo&,
@@ -166,6 +160,12 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length);
+ // Pauses the toplevel script evaluation until ResumeEvaluation is called.
+ // Must be called before InitializeGlobalScope().
+ void PauseEvaluation();
+ // Resumes the toplevel script evaluation. Must be called only after
+ // PauseEvaluation() is called.
+ void ResumeEvaluation();
// Creates a ServiceWorkerTimeoutTimer::StayAwakeToken to ensure that the idle
// timer won't be triggered while any of these are alive.
@@ -215,10 +215,12 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
// native fetch.
void RespondToFetchEventWithNoResponse(
int fetch_event_id,
+ const KURL& request_url,
base::TimeTicks event_dispatch_time,
base::TimeTicks respond_with_settled_time);
// Responds to the fetch event with |response|.
void RespondToFetchEvent(int fetch_event_id,
+ const KURL& request_url,
mojom::blink::FetchAPIResponsePtr,
base::TimeTicks event_dispatch_time,
base::TimeTicks respond_with_settled_time);
@@ -226,6 +228,7 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
// |body_as_stream|.
void RespondToFetchEventWithResponseStream(
int fetch_event_id,
+ const KURL& request_url,
mojom::blink::FetchAPIResponsePtr,
mojom::blink::ServiceWorkerStreamHandlePtr,
base::TimeTicks event_dispatch_time,
@@ -277,15 +280,6 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
mojom::blink::ServiceWorkerHost* GetServiceWorkerHost();
- // Called when a task is going to be scheduled on the service worker.
- // The service worker shouldn't request to be terminated until the task is
- // finished. Returns an id for the task. The caller must call DidEndTask()
- // with the returned id to notify that the task is finished.
- int WillStartTask();
- // Called when a task is finished. |task_id| must be a return value of
- // WillStartTask().
- void DidEndTask(int task_id);
-
DEFINE_ATTRIBUTE_EVENT_LISTENER(install, kInstall)
DEFINE_ATTRIBUTE_EVENT_LISTENER(activate, kActivate)
DEFINE_ATTRIBUTE_EVENT_LISTENER(fetch, kFetch)
@@ -293,6 +287,10 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
void Trace(blink::Visitor*) override;
+ // Returns true if a FetchEvent exists with the given request URL and
+ // is still waiting for a Response.
+ bool HasRelatedFetchEvent(const KURL& request_url) const;
+
protected:
// EventTarget
bool AddEventListenerInternal(
@@ -300,6 +298,13 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
EventListener*,
const AddEventListenerOptionsResolved*) override;
+ // WorkerGlobalScope
+ bool FetchClassicImportedScript(
+ const KURL& script_url,
+ KURL* out_response_url,
+ String* out_source_code,
+ std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data) override;
+
private:
void importScripts(const HeapVector<StringOrTrustedScriptURL>& urls,
ExceptionState&) override;
@@ -313,6 +318,11 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
void DidFetchClassicScript(WorkerClassicScriptLoader* classic_script_loader,
const v8_inspector::V8StackTraceId& stack_id);
+ // Loads and runs the installed top-level classic worker script.
+ void LoadAndRunInstalledClassicScript(
+ const KURL& script_url,
+ const v8_inspector::V8StackTraceId& stack_id);
+
// https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm
void RunClassicScript(const KURL& response_url,
network::mojom::ReferrerPolicy response_referrer_policy,
@@ -371,6 +381,7 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
mojo::PendingAssociatedRemote<mojom::blink::ServiceWorkerHost>
service_worker_host,
mojom::blink::ServiceWorkerRegistrationObjectInfoPtr registration_info,
+ mojom::blink::ServiceWorkerObjectInfoPtr service_worker_info,
mojom::blink::FetchHandlerExistence fetch_hander_existence) override;
void DispatchInstallEvent(DispatchInstallEventCallback callback) override;
void DispatchActivateEvent(DispatchActivateEventCallback callback) override;
@@ -389,10 +400,6 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
void DispatchExtendableMessageEvent(
mojom::blink::ExtendableMessageEventPtr event,
DispatchExtendableMessageEventCallback callback) override;
- void DispatchExtendableMessageEventWithCustomTimeout(
- mojom::blink::ExtendableMessageEventPtr event,
- base::TimeDelta timeout,
- DispatchExtendableMessageEventCallback callback) override;
void DispatchFetchEventForMainResource(
mojom::blink::DispatchFetchEventParamsPtr params,
mojo::PendingRemote<mojom::blink::ServiceWorkerFetchResponseCallback>
@@ -440,8 +447,7 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
response_callback,
DispatchPaymentRequestEventCallback callback) override;
void DispatchCookieChangeEvent(
- const WebCanonicalCookie& cookie,
- ::network::mojom::blink::CookieChangeCause cause,
+ network::mojom::blink::CookieChangeInfoPtr change,
DispatchCookieChangeEventCallback callback) override;
void DispatchContentDeleteEvent(
const String& id,
@@ -451,8 +457,13 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
void AddMessageToConsole(mojom::blink::ConsoleMessageLevel,
const String& message) override;
+ void NoteNewFetchEvent(const KURL& request_url);
+ void NoteRespondedToFetchEvent(const KURL& request_url);
+
Member<ServiceWorkerClients> clients_;
Member<ServiceWorkerRegistration> registration_;
+ Member<::blink::ServiceWorker> service_worker_;
+
// Map from service worker version id to JavaScript ServiceWorker object in
// current execution context.
HeapHashMap<int64_t,
@@ -469,6 +480,10 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
uint64_t cache_storage_installed_script_total_size_ = 0;
uint64_t cache_storage_installed_script_metadata_total_size_ = 0;
+ // Non-null only when this service worker is already installed.
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager_;
+
// May be provided in the constructor as an optimization so InterfaceProvider
// doesn't need to be used. Taken at the initial call to
// ServiceWorkerGlobalScope#caches.
@@ -532,10 +547,23 @@ class MODULES_EXPORT ServiceWorkerGlobalScope final
HeapHashMap<int, Member<FetchEvent>> pending_preload_fetch_events_;
+ // Track outstanding FetchEvent objects still waiting for a response by
+ // request URL. This information can be used as a hint that cache_storage
+ // or fetch requests to the same URL is likely to be used to satisfy a
+ // FetchEvent. This in turn can allow us to use more aggressive
+ // optimizations in these cases.
+ HashMap<KURL, int> unresponded_fetch_event_counts_;
+
// Timer triggered when the service worker considers it should be stopped or
// an event should be aborted.
std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer_;
+ // InitializeGlobalScope() pauses the top level script evaluation when this
+ // flag is true.
+ bool pause_evaluation_ = false;
+ // ResumeEvaluation() evaluates the top level script when this flag is true.
+ bool global_scope_initialized_ = false;
+
// Connected by the ServiceWorkerProviderHost in the browser process and by
// the controllees. |controller_bindings_| should be destroyed before
// |timeout_timer_| since the pipe needs to be disconnected before callbacks
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl
index 88ad7c0cb5d..e76abe6f525 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl
@@ -37,6 +37,7 @@
readonly attribute Clients clients;
readonly attribute ServiceWorkerRegistration registration;
+ readonly attribute ServiceWorker serviceWorker;
[CallWith=ScriptState] Promise<void> skipWaiting();
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
index 5e14386cff6..5ead861c27b 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
@@ -165,14 +165,6 @@ void ServiceWorkerGlobalScopeProxy::DidLoadClassicScript() {
Client().WorkerScriptLoadedOnWorkerThread();
}
-void ServiceWorkerGlobalScopeProxy::DidFailToLoadClassicScript() {
- DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
- // Tell ServiceWorkerContextClient about the failure. The generic
- // WorkerContextFailedToStart() wouldn't make sense because
- // WorkerContextStarted() was already called.
- Client().FailedToLoadClassicScript();
-}
-
void ServiceWorkerGlobalScopeProxy::DidFetchScript() {
DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
Client().WorkerScriptLoadedOnWorkerThread();
@@ -180,7 +172,7 @@ void ServiceWorkerGlobalScopeProxy::DidFetchScript() {
void ServiceWorkerGlobalScopeProxy::DidFailToFetchClassicScript() {
DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
- Client().FailedToLoadClassicScript();
+ Client().FailedToFetchClassicScript();
}
void ServiceWorkerGlobalScopeProxy::DidFailToFetchModuleScript() {
@@ -324,6 +316,14 @@ bool ServiceWorkerGlobalScopeProxy::IsWindowInteractionAllowed() {
return WorkerGlobalScope()->IsWindowInteractionAllowed();
}
+void ServiceWorkerGlobalScopeProxy::PauseEvaluation() {
+ WorkerGlobalScope()->PauseEvaluation();
+}
+
+void ServiceWorkerGlobalScopeProxy::ResumeEvaluation() {
+ WorkerGlobalScope()->ResumeEvaluation();
+}
+
WebServiceWorkerContextClient& ServiceWorkerGlobalScopeProxy::Client() const {
DCHECK(client_);
return *client_;
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
index e39df8ad6c1..981994b3fa3 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
@@ -91,6 +91,8 @@ class ServiceWorkerGlobalScopeProxy final : public WebServiceWorkerContextProxy,
int64_t encoded_body_length,
int64_t decoded_body_length) override;
bool IsWindowInteractionAllowed() override;
+ void PauseEvaluation() override;
+ void ResumeEvaluation() override;
// WorkerReportingProxy overrides:
void CountFeature(WebFeature) override;
@@ -105,7 +107,6 @@ class ServiceWorkerGlobalScopeProxy final : public WebServiceWorkerContextProxy,
void WillInitializeWorkerContext() override;
void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
void DidLoadClassicScript() override;
- void DidFailToLoadClassicScript() override;
void DidFetchScript() override;
void DidFailToFetchClassicScript() override;
void DidFailToFetchModuleScript() override;
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
index c265bf8da3e..e4c2615fb09 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
@@ -9,7 +9,10 @@
#include "base/barrier_closure.h"
#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "third_party/blink/public/web/web_embedded_worker.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_thread.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
@@ -245,18 +248,33 @@ std::unique_ptr<TracedValue> UrlToTracedValue(const KURL& url) {
} // namespace
ServiceWorkerInstalledScriptsManager::ServiceWorkerInstalledScriptsManager(
- const Vector<KURL>& installed_urls,
- mojo::PendingReceiver<mojom::blink::ServiceWorkerInstalledScriptsManager>
- manager_receiver,
- mojo::PendingRemote<mojom::blink::ServiceWorkerInstalledScriptsManagerHost>
- manager_host,
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>
+ installed_scripts_manager_params,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
- : script_container_(base::MakeRefCounted<ThreadSafeScriptContainer>()),
- manager_host_(std::move(manager_host)) {
- // We're on the main thread now, but |installed_urls_| will be accessed on the
- // worker thread later, so make a deep copy of |url| as key.
- for (const KURL& url : installed_urls)
- installed_urls_.insert(url.Copy());
+ : script_container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {
+ DCHECK(installed_scripts_manager_params);
+
+ DCHECK(installed_scripts_manager_params->manager_receiver);
+ auto manager_receiver =
+ mojo::PendingReceiver<mojom::blink::ServiceWorkerInstalledScriptsManager>(
+ std::move(installed_scripts_manager_params->manager_receiver));
+
+ DCHECK(installed_scripts_manager_params->manager_host_remote);
+ manager_host_ = mojo::SharedRemote<
+ mojom::blink::ServiceWorkerInstalledScriptsManagerHost>(
+ mojo::PendingRemote<
+ mojom::blink::ServiceWorkerInstalledScriptsManagerHost>(
+ std::move(installed_scripts_manager_params->manager_host_remote),
+ mojom::blink::ServiceWorkerInstalledScriptsManagerHost::Version_));
+
+ // Don't touch |installed_urls_| after this point. We're on the initiator
+ // thread now, but |installed_urls_| will be accessed on the
+ // worker thread later, so they should keep isolated from the current thread.
+ for (const WebURL& url :
+ installed_scripts_manager_params->installed_scripts_urls) {
+ installed_urls_.insert(KURL(url).Copy());
+ }
+
PostCrossThreadTask(
*io_task_runner, FROM_HERE,
CrossThreadBindOnce(&Internal::Create, script_container_,
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h
index 91f9aeac710..3c7f8803746 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h
@@ -5,8 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
@@ -19,17 +17,16 @@
namespace blink {
+struct WebServiceWorkerInstalledScriptsManagerParams;
+
// ServiceWorkerInstalledScriptsManager provides the main script and imported
// scripts of an installed service worker. The scripts are streamed from the
// browser process in parallel with worker thread initialization.
-class MODULES_EXPORT ServiceWorkerInstalledScriptsManager
+class MODULES_EXPORT ServiceWorkerInstalledScriptsManager final
: public InstalledScriptsManager {
public:
ServiceWorkerInstalledScriptsManager(
- const Vector<KURL>& installed_urls,
- mojo::PendingReceiver<mojom::blink::ServiceWorkerInstalledScriptsManager>,
- mojo::PendingRemote<
- mojom::blink::ServiceWorkerInstalledScriptsManagerHost>,
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
virtual ~ServiceWorkerInstalledScriptsManager() = default;
@@ -43,7 +40,10 @@ class MODULES_EXPORT ServiceWorkerInstalledScriptsManager
std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> GetRawScriptData(
const KURL& script_url);
+ // Constructed on the initiator thread, and accessed only on the worker
+ // thread.
HashSet<KURL> installed_urls_;
+
scoped_refptr<ThreadSafeScriptContainer> script_container_;
mojo::SharedRemote<mojom::blink::ServiceWorkerInstalledScriptsManagerHost>
manager_host_;
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 8f78882ba54..2e6ef8e49ee 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
@@ -11,6 +11,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/web/web_embedded_worker.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"
@@ -140,11 +141,14 @@ class ServiceWorkerInstalledScriptsManagerTest : public testing::Test {
void CreateInstalledScriptsManager(
mojom::blink::ServiceWorkerInstalledScriptsInfoPtr
installed_scripts_info) {
+ auto installed_scripts_manager_params =
+ std::make_unique<WebServiceWorkerInstalledScriptsManagerParams>(
+ std::move(installed_scripts_info->installed_urls),
+ installed_scripts_info->manager_receiver.PassPipe(),
+ installed_scripts_info->manager_host_remote.PassPipe());
installed_scripts_manager_ =
std::make_unique<ServiceWorkerInstalledScriptsManager>(
- std::move(installed_scripts_info->installed_urls),
- std::move(installed_scripts_info->manager_receiver),
- std::move(installed_scripts_info->manager_host_remote),
+ std::move(installed_scripts_manager_params),
io_thread_->GetTaskRunner());
}
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 04d76da1954..6136ce36971 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
@@ -12,8 +12,8 @@
namespace blink {
ServiceWorkerModuleTreeClient::ServiceWorkerModuleTreeClient(
- Modulator* modulator)
- : modulator_(modulator) {}
+ ScriptState* script_state)
+ : script_state_(script_state) {}
// This client is used for both new and installed scripts. In the new scripts
// case, this is a partial implementation of the custom "perform the fetch" hook
@@ -23,9 +23,8 @@ ServiceWorkerModuleTreeClient::ServiceWorkerModuleTreeClient(
// script resource.
void ServiceWorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
ModuleScript* module_script) {
- auto* execution_context =
- ExecutionContext::From(modulator_->GetScriptState());
- auto* worker_global_scope = To<WorkerGlobalScope>(execution_context);
+ auto* worker_global_scope =
+ To<WorkerGlobalScope>(ExecutionContext::From(script_state_));
blink::WorkerReportingProxy& worker_reporting_proxy =
worker_global_scope->ReportingProxy();
@@ -48,7 +47,7 @@ void ServiceWorkerModuleTreeClient::NotifyModuleTreeLoadFinished(
}
void ServiceWorkerModuleTreeClient::Trace(blink::Visitor* visitor) {
- visitor->Trace(modulator_);
+ visitor->Trace(script_state_);
ModuleTreeClient::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.h
index e6cae49b147..94e2ec67e37 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_module_tree_client.h
@@ -12,12 +12,13 @@
namespace blink {
class ModuleScript;
+class ScriptState;
// This is an implementation of ModuleTreeClient for service workers that lives
// on the worker context's thread.
class ServiceWorkerModuleTreeClient final : public ModuleTreeClient {
public:
- explicit ServiceWorkerModuleTreeClient(Modulator*);
+ explicit ServiceWorkerModuleTreeClient(ScriptState*);
// Implements ModuleTreeClient.
void NotifyModuleTreeLoadFinished(ModuleScript*) final;
@@ -25,7 +26,7 @@ class ServiceWorkerModuleTreeClient final : public ModuleTreeClient {
void Trace(blink::Visitor*) override;
private:
- Member<Modulator> modulator_;
+ Member<ScriptState> script_state_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc
index c33064b4337..c8f8a946500 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc
@@ -32,16 +32,12 @@
#include <memory>
-#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.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 "v8/include/v8-inspector.h"
namespace blink {
@@ -68,68 +64,16 @@ void ServiceWorkerThread::ClearWorkerBackingThread() {
worker_backing_thread_ = nullptr;
}
-InstalledScriptsManager* ServiceWorkerThread::GetInstalledScriptsManager() {
- return installed_scripts_manager_.get();
-}
-
void ServiceWorkerThread::TerminateForTesting() {
global_scope_proxy_->TerminateWorkerContext();
WorkerThread::TerminateForTesting();
}
-void ServiceWorkerThread::RunInstalledClassicScript(
- const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id) {
- // Use TaskType::kDOMManipulation for consistency with
- // WorkerThread::EvaluateClassicScript().
- PostCrossThreadTask(
- *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
- CrossThreadBindOnce(
- &ServiceWorkerThread::RunInstalledClassicScriptOnWorkerThread,
- CrossThreadUnretained(this), script_url, stack_id));
-}
-
-void ServiceWorkerThread::RunInstalledModuleScript(
- const KURL& module_url_record,
- std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- outside_settings_object_data,
- network::mojom::CredentialsMode credentials_mode) {
- PostCrossThreadTask(
- *GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
- CrossThreadBindOnce(
- &ServiceWorkerThread::RunInstalledModuleScriptOnWorkerThread,
- CrossThreadUnretained(this), module_url_record,
- WTF::Passed(std::move(outside_settings_object_data)),
- credentials_mode));
-}
-
-void ServiceWorkerThread::RunInstalledClassicScriptOnWorkerThread(
- const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id) {
- DCHECK(IsCurrentThread());
- To<ServiceWorkerGlobalScope>(GlobalScope())
- ->RunInstalledClassicScript(script_url, stack_id);
-}
-
-void ServiceWorkerThread::RunInstalledModuleScriptOnWorkerThread(
- const KURL& module_url_record,
- std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- outside_settings_object,
- network::mojom::CredentialsMode credentials_mode) {
- DCHECK(IsCurrentThread());
- To<ServiceWorkerGlobalScope>(GlobalScope())
- ->RunInstalledModuleScript(
- module_url_record,
- *MakeGarbageCollected<FetchClientSettingsObjectSnapshot>(
- std::move(outside_settings_object)),
- credentials_mode);
-}
-
WorkerOrWorkletGlobalScope* ServiceWorkerThread::CreateWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params) {
- return ServiceWorkerGlobalScope::Create(this, std::move(creation_params),
- std::move(cache_storage_remote_),
- time_origin_);
+ return ServiceWorkerGlobalScope::Create(
+ this, std::move(creation_params), std::move(installed_scripts_manager_),
+ std::move(cache_storage_remote_), time_origin_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h
index 528e594a45b..9c5919c632e 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h
@@ -32,7 +32,7 @@
#include <memory>
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink.h"
+#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -60,17 +60,8 @@ class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread {
return *worker_backing_thread_;
}
void ClearWorkerBackingThread() override;
- InstalledScriptsManager* GetInstalledScriptsManager() override;
void TerminateForTesting() override;
- void RunInstalledClassicScript(const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id);
- void RunInstalledModuleScript(
- const KURL& module_url_record,
- std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- outside_settings_object_data,
- network::mojom::CredentialsMode);
-
private:
WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams>) override;
@@ -79,17 +70,10 @@ class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread {
return WebThreadType::kServiceWorkerThread;
}
- void RunInstalledClassicScriptOnWorkerThread(
- const KURL& script_url,
- const v8_inspector::V8StackTraceId& stack_id);
- void RunInstalledModuleScriptOnWorkerThread(
- const KURL& module_url_record,
- std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
- outside_settings_object,
- network::mojom::CredentialsMode);
-
std::unique_ptr<ServiceWorkerGlobalScopeProxy> global_scope_proxy_;
std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
+
+ // Ownership of these members is moved out in CreateWorkerGlobalScope().
std::unique_ptr<ServiceWorkerInstalledScriptsManager>
installed_scripts_manager_;
mojo::PendingRemote<mojom::blink::CacheStorage> cache_storage_remote_;
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.cc
index cd504d0d3ce..fb160277bc8 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.cc
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.h
index 257a1df5e48..3cad5e70a8a 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_timeout_timer.h
@@ -11,7 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.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"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h
index 162abc3de8b..13a009afcd4 100644
--- a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h
+++ b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h
@@ -20,7 +20,7 @@ class ScriptValue;
// Created for each ExtendableEvent instance.
class MODULES_EXPORT WaitUntilObserver final
- : public GarbageCollectedFinalized<WaitUntilObserver>,
+ : public GarbageCollected<WaitUntilObserver>,
public ContextClient {
USING_GARBAGE_COLLECTED_MIXIN(WaitUntilObserver);
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 5841f33ba20..0b8b5fc56a4 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
@@ -18,7 +18,6 @@
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#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_installed_scripts_manager.mojom-blink.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
@@ -28,12 +27,11 @@
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
#include "third_party/blink/public/web/web_embedded_worker_start_data.h"
-#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
-#include "third_party/blink/renderer/modules/service_worker/thread_safe_script_container.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.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"
@@ -127,7 +125,6 @@ class MockServiceWorkerContextClient final
MOCK_METHOD2(WorkerReadyForInspectionOnInitiatorThread,
void(mojo::ScopedMessagePipeHandle,
mojo::ScopedMessagePipeHandle));
- MOCK_METHOD0(WorkerContextFailedToStartOnInitiatorThread, void());
void WorkerContextStarted(WebServiceWorkerContextProxy* proxy,
scoped_refptr<base::SequencedTaskRunner>) override {
@@ -142,6 +139,13 @@ class MockServiceWorkerContextClient final
mojo::PendingAssociatedRemote<mojom::blink::ServiceWorkerRegistrationObject>
registration_object;
+ mojo::PendingAssociatedRemote<mojom::blink::ServiceWorkerObjectHost>
+ service_worker_object_host;
+ auto service_worker_object_host_receiver =
+ service_worker_object_host.InitWithNewEndpointAndPassReceiver();
+ mojo::PendingAssociatedRemote<mojom::blink::ServiceWorkerObject>
+ service_worker_object;
+
// Simulates calling blink.mojom.ServiceWorker.InitializeGlobalScope() to
// unblock the service worker script evaluation.
mojo::Remote<mojom::blink::ServiceWorker> service_worker;
@@ -155,18 +159,22 @@ class MockServiceWorkerContextClient final
std::move(registration_object_host),
registration_object.InitWithNewEndpointAndPassReceiver(), nullptr,
nullptr, nullptr),
+ mojom::blink::ServiceWorkerObjectInfo::New(
+ 1 /* service_worker_version_id */,
+ mojom::blink::ServiceWorkerState::kParsed,
+ KURL("https://example.com"), std::move(service_worker_object_host),
+ service_worker_object.InitWithNewEndpointAndPassReceiver()),
mojom::blink::FetchHandlerExistence::EXISTS);
// To make the other side callable.
mojo::AssociateWithDisconnectedPipe(host_receiver.PassHandle());
mojo::AssociateWithDisconnectedPipe(
registration_object_host_receiver.PassHandle());
+ mojo::AssociateWithDisconnectedPipe(
+ service_worker_object_host_receiver.PassHandle());
}
- void FailedToLoadClassicScript() override {
- // off-main-script fetch:
- // In production code, calling FailedToLoadClassicScript results in
- // terminating the worker.
+ void FailedToFetchClassicScript() override {
classic_script_load_failure_event_.Signal();
}
@@ -194,130 +202,108 @@ class MockServiceWorkerContextClient final
base::WaitableEvent classic_script_load_failure_event_;
};
-class MockServiceWorkerInstalledScriptsManager
- : public ServiceWorkerInstalledScriptsManager {
- public:
- MockServiceWorkerInstalledScriptsManager()
- : ServiceWorkerInstalledScriptsManager(
- Vector<KURL>() /* installed_urls */,
- mojo::PendingReceiver<
- mojom::blink::ServiceWorkerInstalledScriptsManager>(
- mojo::MessagePipe().handle1),
- mojo::PendingRemote<
- mojom::blink::ServiceWorkerInstalledScriptsManagerHost>(
- mojo::MessagePipe().handle0,
- mojom::blink::ServiceWorkerInstalledScriptsManagerHost::
- Version_),
- // Pass a temporary task runner to ensure
- // ServiceWorkerInstalledScriptsManager construction succeeds.
- Platform::Current()
- ->CreateThread(ThreadCreationParams(WebThreadType::kTestThread)
- .SetThreadNameForTest("io thread"))
- ->GetTaskRunner()) {}
- MOCK_CONST_METHOD1(IsScriptInstalled, bool(const KURL& script_url));
- MOCK_METHOD1(GetRawScriptData,
- std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>(
- const KURL& script_url));
-};
-
class WebEmbeddedWorkerImplTest : public testing::Test {
protected:
void SetUp() override {
- auto installed_scripts_manager =
- std::make_unique<MockServiceWorkerInstalledScriptsManager>();
- mock_installed_scripts_manager_ = installed_scripts_manager.get();
mock_client_ = std::make_unique<MockServiceWorkerContextClient>();
- worker_ = WebEmbeddedWorkerImpl::CreateForTesting(
- mock_client_.get(), std::move(installed_scripts_manager));
+ worker_ = std::make_unique<WebEmbeddedWorkerImpl>(mock_client_.get());
- WebURL script_url =
- url_test_helpers::ToKURL("https://www.example.com/sw.js");
- WebURLResponse response(script_url);
+ script_url_ = url_test_helpers::ToKURL("https://www.example.com/sw.js");
+ WebURLResponse response(script_url_);
response.SetMimeType("text/javascript");
response.SetHttpStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(script_url,
- response, "");
+ url_test_helpers::RegisterMockedURLLoadWithCustomResponse(script_url_, "",
+ response);
+ }
- start_data_.script_url = script_url;
- start_data_.user_agent = WebString("dummy user agent");
- start_data_.script_type = mojom::ScriptType::kClassic;
- start_data_.wait_for_debugger_mode =
+ std::unique_ptr<WebEmbeddedWorkerStartData> CreateStartData() {
+ WebFetchClientSettingsObject outside_settings_object(
+ network::mojom::ReferrerPolicy::kDefault,
+ /*outgoing_referrer=*/WebURL(script_url_),
+ blink::mojom::InsecureRequestsPolicy::kDoNotUpgrade);
+ auto start_data = std::make_unique<WebEmbeddedWorkerStartData>(
+ std::move(outside_settings_object));
+ start_data->script_url = script_url_;
+ start_data->user_agent = WebString("dummy user agent");
+ start_data->script_type = mojom::ScriptType::kClassic;
+ start_data->wait_for_debugger_mode =
WebEmbeddedWorkerStartData::kDontWaitForDebugger;
- start_data_.v8_cache_options = WebSettings::V8CacheOptions::kDefault;
+ return start_data;
}
void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
+ // Drain queued tasks posted from the worker thread in order to avoid tasks
+ // bound with unretained objects from running after tear down. Worker
+ // termination may post such tasks (see https://crbug,com/1007616).
+ // TODO(nhiroki): Stop using synchronous WaitableEvent, and instead use
+ // QuitClosure to wait until all the tasks run before test completion.
+ test::RunPendingTasks();
+
+ url_test_helpers::UnregisterAllURLsAndClearMemoryCache();
}
- WebEmbeddedWorkerStartData start_data_;
+ WebURL script_url_;
std::unique_ptr<MockServiceWorkerContextClient> mock_client_;
- MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_;
std::unique_ptr<WebEmbeddedWorkerImpl> worker_;
};
} // namespace
TEST_F(WebEmbeddedWorkerImplTest, TerminateSoonAfterStart) {
- worker_->StartWorkerContext(start_data_, Thread::Current()->GetTaskRunner());
+ worker_->StartWorkerContext(
+ CreateStartData(),
+ /*installed_scripts_manager_params=*/nullptr,
+ /*content_settings_proxy=*/mojo::ScopedMessagePipeHandle(),
+ /*cache_storage_remote=*/mojo::ScopedMessagePipeHandle(),
+ /*interface_provider_info=*/mojo::ScopedMessagePipeHandle(),
+ /*browser_interface_broker=*/mojo::ScopedMessagePipeHandle(),
+ Thread::Current()->GetTaskRunner());
testing::Mock::VerifyAndClearExpectations(mock_client_.get());
+ // Terminate the worker immediately after start.
worker_->TerminateWorkerContext();
- // The worker thread was started. Wait for shutdown tasks to finish.
worker_->WaitForShutdownForTesting();
}
TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileWaitingForDebugger) {
- start_data_.wait_for_debugger_mode =
+ std::unique_ptr<WebEmbeddedWorkerStartData> start_data = CreateStartData();
+ start_data->wait_for_debugger_mode =
WebEmbeddedWorkerStartData::kWaitForDebugger;
- worker_->StartWorkerContext(start_data_, Thread::Current()->GetTaskRunner());
+ worker_->StartWorkerContext(
+ std::move(start_data),
+ /*installed_scripts_manager_params=*/nullptr,
+ /*content_settings_proxy=*/mojo::ScopedMessagePipeHandle(),
+ /*cache_storage_remote=*/mojo::ScopedMessagePipeHandle(),
+ /*interface_provider_info=*/mojo::ScopedMessagePipeHandle(),
+ /*browser_interface_broker=*/mojo::ScopedMessagePipeHandle(),
+ Thread::Current()->GetTaskRunner());
testing::Mock::VerifyAndClearExpectations(mock_client_.get());
+ // Terminate the worker while waiting for the debugger.
worker_->TerminateWorkerContext();
worker_->WaitForShutdownForTesting();
}
-TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) {
- // Load the shadow page.
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(KURL(start_data_.script_url)))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- worker_->StartWorkerContext(start_data_, Thread::Current()->GetTaskRunner());
- testing::Mock::VerifyAndClearExpectations(mock_client_.get());
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Terminate before finishing the script load.
- worker_->TerminateWorkerContext();
- // The worker thread was started. Wait for shutdown tasks to finish.
- worker_->WaitForShutdownForTesting();
-}
-
TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) {
- // Load the shadow page.
WebURL script_url = url_test_helpers::ToKURL(kNotFoundScriptURL);
- WebURLResponse response;
- response.SetMimeType("text/javascript");
- response.SetHttpStatusCode(404);
- ResourceError error = ResourceError::Failure(script_url);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
- script_url, response, error);
- start_data_.script_url = script_url;
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(KURL(start_data_.script_url)))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
+ url_test_helpers::RegisterMockedErrorURLLoad(script_url);
+ std::unique_ptr<WebEmbeddedWorkerStartData> start_data = CreateStartData();
+ start_data->script_url = script_url;
+
// Start worker and load the script.
- worker_->StartWorkerContext(start_data_, Thread::Current()->GetTaskRunner());
+ worker_->StartWorkerContext(
+ std::move(start_data),
+ /*installed_scripts_manager_params=*/nullptr,
+ /*content_settings_proxy=*/mojo::ScopedMessagePipeHandle(),
+ /*cache_storage_remote=*/mojo::ScopedMessagePipeHandle(),
+ /*interface_provider_info=*/mojo::ScopedMessagePipeHandle(),
+ /*browser_interface_broker=*/mojo::ScopedMessagePipeHandle(),
+ Thread::Current()->GetTaskRunner());
testing::Mock::VerifyAndClearExpectations(mock_client_.get());
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
mock_client_->WaitUntilFailedToLoadClassicScript();
- // The worker thread was started. Ask to shutdown and wait for shutdown
- // tasks to finish.
+ // Terminate the worker for cleanup.
worker_->TerminateWorkerContext();
worker_->WaitForShutdownForTesting();
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/DEPS b/chromium/third_party/blink/renderer/modules/shapedetection/DEPS
index c1b5ad37a4f..7b205447533 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/DEPS
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+services/shape_detection/public/mojom",
"+services/service_manager/public/cpp",
"+skia/public/mojom/bitmap.mojom-blink.h",
+ "+skia/public/mojom/bitmap.mojom-blink-forward.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/canvas/canvas2d",
"+third_party/blink/renderer/modules/imagecapture/point_2d.h",
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
index 27c599799ad..46ad05e8bad 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
@@ -87,9 +87,9 @@ BarcodeDetector::BarcodeDetector(ExecutionContext* context,
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
BarcodeDetectorStatics::From(context)->CreateBarcodeDetection(
- mojo::MakeRequest(&service_, task_runner),
+ service_.BindNewPipeAndPassReceiver(task_runner),
std::move(barcode_detector_options));
- service_.set_connection_error_handler(
+ service_.set_disconnect_handler(
WTF::Bind(&BarcodeDetector::OnConnectionError, WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.h b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.h
index 775a513cf22..98a324a2e88 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/shape_detection/public/mojom/barcodedetection.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"
@@ -44,7 +45,7 @@ class MODULES_EXPORT BarcodeDetector final : public ShapeDetector {
void OnConnectionError();
- shape_detection::mojom::blink::BarcodeDetectionPtr service_;
+ mojo::Remote<shape_detection::mojom::blink::BarcodeDetection> service_;
HeapHashSet<Member<ScriptPromiseResolver>> detect_requests_;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.cc b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.cc
index a2f366142c5..4ec76fed03b 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h"
-#include "services/service_manager/public/cpp/interface_provider.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/script_promise_resolver.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -34,10 +34,11 @@ BarcodeDetectorStatics::BarcodeDetectorStatics(ExecutionContext& document)
BarcodeDetectorStatics::~BarcodeDetectorStatics() = default;
void BarcodeDetectorStatics::CreateBarcodeDetection(
- shape_detection::mojom::blink::BarcodeDetectionRequest request,
+ mojo::PendingReceiver<shape_detection::mojom::blink::BarcodeDetection>
+ receiver,
shape_detection::mojom::blink::BarcodeDetectorOptionsPtr options) {
EnsureServiceConnection();
- service_->CreateBarcodeDetection(std::move(request), std::move(options));
+ service_->CreateBarcodeDetection(std::move(receiver), std::move(options));
}
ScriptPromise BarcodeDetectorStatics::EnumerateSupportedFormats(
@@ -65,9 +66,9 @@ void BarcodeDetectorStatics::EnsureServiceConnection() {
// See https://bit.ly/2S0zRAS for task types.
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
- auto request = mojo::MakeRequest(&service_, task_runner);
- context->GetInterfaceProvider()->GetInterface(std::move(request));
- service_.set_connection_error_handler(WTF::Bind(
+ context->GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(task_runner));
+ service_.set_disconnect_handler(WTF::Bind(
&BarcodeDetectorStatics::OnConnectionError, WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h
index 0689a11fcb8..fc94f081c17 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector_statics.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_STATICS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_BARCODE_DETECTOR_STATICS_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -20,7 +21,7 @@ class ScriptPromiseResolver;
// This class owns the BarcodeDetectionProvider connection used to create the
// BarcodeDetector instances for this ExecutionContext.
class BarcodeDetectorStatics final
- : public GarbageCollectedFinalized<BarcodeDetectorStatics>,
+ : public GarbageCollected<BarcodeDetectorStatics>,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(BarcodeDetectorStatics);
@@ -33,7 +34,7 @@ class BarcodeDetectorStatics final
~BarcodeDetectorStatics();
void CreateBarcodeDetection(
- shape_detection::mojom::blink::BarcodeDetectionRequest,
+ mojo::PendingReceiver<shape_detection::mojom::blink::BarcodeDetection>,
shape_detection::mojom::blink::BarcodeDetectorOptionsPtr);
ScriptPromise EnumerateSupportedFormats(ScriptState*);
@@ -46,7 +47,8 @@ class BarcodeDetectorStatics final
const Vector<shape_detection::mojom::blink::BarcodeFormat>&);
void OnConnectionError();
- shape_detection::mojom::blink::BarcodeDetectionProviderPtr service_;
+ mojo::Remote<shape_detection::mojom::blink::BarcodeDetectionProvider>
+ service_;
// Holds Promises returned by EnumerateSupportedFormats() so that they can be
// resolve in the case of a Mojo connection error.
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
index a0a130d890c..6577edc0000 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
@@ -6,8 +6,8 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.h"
#include "services/shape_detection/public/mojom/facedetection_provider.mojom-blink.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/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -37,17 +37,17 @@ FaceDetector::FaceDetector(ExecutionContext* context,
face_detector_options->max_detected_faces = options->maxDetectedFaces();
face_detector_options->fast_mode = options->fastMode();
- shape_detection::mojom::blink::FaceDetectionProviderPtr provider;
+ mojo::Remote<shape_detection::mojom::blink::FaceDetectionProvider> provider;
// See https://bit.ly/2S0zRAS for task types.
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
- auto request = mojo::MakeRequest(&provider, task_runner);
- if (auto* interface_provider = context->GetInterfaceProvider()) {
- interface_provider->GetInterface(std::move(request));
- }
- provider->CreateFaceDetection(mojo::MakeRequest(&face_service_, task_runner),
- std::move(face_detector_options));
+ context->GetBrowserInterfaceBroker().GetInterface(
+ provider.BindNewPipeAndPassReceiver(task_runner));
+
+ provider->CreateFaceDetection(
+ face_service_.BindNewPipeAndPassReceiver(task_runner),
+ std::move(face_detector_options));
- face_service_.set_connection_error_handler(WTF::Bind(
+ face_service_.set_disconnect_handler(WTF::Bind(
&FaceDetector::OnFaceServiceConnectionError, WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.h b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.h
index 86537084d01..7c5bb6b07f3 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_FACE_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_FACE_DETECTOR_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/shape_detection/public/mojom/facedetection.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"
@@ -36,7 +37,7 @@ class MODULES_EXPORT FaceDetector final : public ShapeDetector {
Vector<shape_detection::mojom::blink::FaceDetectionResultPtr>);
void OnFaceServiceConnectionError();
- shape_detection::mojom::blink::FaceDetectionPtr face_service_;
+ mojo::Remote<shape_detection::mojom::blink::FaceDetection> face_service_;
HeapHashSet<Member<ScriptPromiseResolver>> face_service_requests_;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detection_type_converter.h b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detection_type_converter.h
index 9fa35082f54..91fc95f6c6d 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detection_type_converter.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detection_type_converter.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_SHAPE_DETECTION_TYPE_CONVERTER_H_
#include "mojo/public/cpp/bindings/type_converter.h"
-#include "services/shape_detection/public/mojom/facedetection.mojom-blink.h"
+#include "services/shape_detection/public/mojom/facedetection.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace mojo {
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 bb7e075111b..f1ed766b476 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_SHAPE_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_SHAPE_DETECTOR_H_
-#include "skia/public/mojom/bitmap.mojom-blink.h"
+#include "skia/public/mojom/bitmap.mojom-blink-forward.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/window_or_worker_global_scope.h"
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
index 0db9dc33c66..8c01af260ce 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
@@ -25,12 +25,10 @@ TextDetector* TextDetector::Create(ExecutionContext* context) {
TextDetector::TextDetector(ExecutionContext* context) : ShapeDetector() {
// See https://bit.ly/2S0zRAS for task types.
auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
- auto request = mojo::MakeRequest(&text_service_, task_runner);
- if (auto* interface_provider = context->GetInterfaceProvider()) {
- interface_provider->GetInterface(std::move(request));
- }
+ context->GetBrowserInterfaceBroker().GetInterface(
+ text_service_.BindNewPipeAndPassReceiver(task_runner));
- text_service_.set_connection_error_handler(WTF::Bind(
+ text_service_.set_disconnect_handler(WTF::Bind(
&TextDetector::OnTextServiceConnectionError, WrapWeakPersistent(this)));
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.h b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.h
index 89136af5626..48e06aff0f3 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_TEXT_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_TEXT_DETECTOR_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/shape_detection/public/mojom/textdetection.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"
@@ -35,7 +36,7 @@ class MODULES_EXPORT TextDetector final : public ShapeDetector {
Vector<shape_detection::mojom::blink::TextDetectionResultPtr>);
void OnTextServiceConnectionError();
- shape_detection::mojom::blink::TextDetectionPtr text_service_;
+ mojo::Remote<shape_detection::mojom::blink::TextDetection> text_service_;
HeapHashSet<Member<ScriptPromiseResolver>> text_service_requests_;
};
diff --git a/chromium/third_party/blink/renderer/modules/sms/sms_receiver.cc b/chromium/third_party/blink/renderer/modules/sms/sms_receiver.cc
index be89fae5847..127220a175a 100644
--- a/chromium/third_party/blink/renderer/modules/sms/sms_receiver.cc
+++ b/chromium/third_party/blink/renderer/modules/sms/sms_receiver.cc
@@ -6,7 +6,7 @@
#include "third_party/blink/renderer/modules/sms/sms_receiver.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/sms/sms_receiver.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"
@@ -46,7 +46,7 @@ ScriptPromise SMSReceiver::receive(ScriptState* script_state,
GetExecutionContext()->GetTaskRunner(TaskType::kInternalIPC);
if (!service_) {
- GetExecutionContext()->GetInterfaceProvider()->GetInterface(
+ GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(WTF::Bind(
&SMSReceiver::OnSMSReceiverConnectionError, WrapWeakPersistent(this)));
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 9b6db1d2104..ea507a2a1a4 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
@@ -27,6 +27,8 @@
#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/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_controller.h"
@@ -56,18 +58,15 @@ void SpeechRecognition::start(ExceptionState& exception_state) {
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetExecutionContext()->GetTaskRunner(blink::TaskType::kMiscPlatformAPI);
- mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client;
- binding_.Bind(mojo::MakeRequest(&session_client),
- GetExecutionContext()->GetInterfaceInvalidator(), task_runner);
- binding_.set_connection_error_handler(WTF::Bind(
+ mojo::PendingRemote<mojom::blink::SpeechRecognitionSessionClient>
+ session_client;
+ receiver_.Bind(session_client.InitWithNewPipeAndPassReceiver(), task_runner);
+ receiver_.set_disconnect_handler(WTF::Bind(
&SpeechRecognition::OnConnectionError, WrapWeakPersistent(this)));
- mojom::blink::SpeechRecognitionSessionRequest session_request =
- MakeRequest(&session_, GetExecutionContext()->GetInterfaceInvalidator());
-
- controller_->Start(std::move(session_request), std::move(session_client),
- *grammars_, lang_, continuous_, interim_results_,
- max_alternatives_);
+ controller_->Start(session_.BindNewPipeAndPassReceiver(),
+ std::move(session_client), *grammars_, lang_, continuous_,
+ interim_results_, max_alternatives_);
started_ = true;
}
@@ -171,7 +170,7 @@ void SpeechRecognition::Ended() {
started_ = false;
stopping_ = false;
session_.reset();
- binding_.Close();
+ receiver_.reset();
DispatchEvent(*Event::Create(event_type_names::kEnd));
}
@@ -185,6 +184,8 @@ ExecutionContext* SpeechRecognition::GetExecutionContext() const {
void SpeechRecognition::ContextDestroyed(ExecutionContext*) {
controller_ = nullptr;
+ receiver_.reset();
+ session_.reset();
}
bool SpeechRecognition::HasPendingActivity() const {
@@ -218,7 +219,7 @@ SpeechRecognition::SpeechRecognition(LocalFrame* frame,
controller_(SpeechRecognitionController::From(frame)),
started_(false),
stopping_(false),
- binding_(this) {}
+ receiver_(this) {}
SpeechRecognition::~SpeechRecognition() = default;
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
index fb936e1ec48..a849c046819 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
@@ -26,6 +26,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_H_
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom-blink.h"
#include "third_party/blink/public/platform/web_private_ptr.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -36,8 +38,6 @@
#include "third_party/blink/renderer/modules/speech/speech_grammar_list.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_result.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_binding.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -135,8 +135,8 @@ class MODULES_EXPORT SpeechRecognition final
bool started_;
bool stopping_;
HeapVector<Member<SpeechRecognitionResult>> final_results_;
- RevocableBinding<mojom::blink::SpeechRecognitionSessionClient> binding_;
- RevocableInterfacePtr<mojom::blink::SpeechRecognitionSession> session_;
+ mojo::Receiver<mojom::blink::SpeechRecognitionSessionClient> receiver_;
+ mojo::Remote<mojom::blink::SpeechRecognitionSession> session_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
index bdeacd02c7d..e228072ef86 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
@@ -27,7 +27,7 @@
#include <memory>
-#include "services/service_manager/public/cpp/interface_provider.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/modules/speech/speech_grammar_list.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
@@ -50,8 +50,10 @@ SpeechRecognitionController* SpeechRecognitionController::Create(
}
void SpeechRecognitionController::Start(
- mojom::blink::SpeechRecognitionSessionRequest session_request,
- mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client,
+ mojo::PendingReceiver<mojom::blink::SpeechRecognitionSession>
+ session_receiver,
+ mojo::PendingRemote<mojom::blink::SpeechRecognitionSessionClient>
+ session_client,
const SpeechGrammarList& grammars,
const String& lang,
bool continuous,
@@ -70,7 +72,7 @@ void SpeechRecognitionController::Start(
msg_params->interim_results = interim_results;
msg_params->origin = GetSupplementable()->GetDocument()->GetSecurityOrigin();
msg_params->client = std::move(session_client);
- msg_params->session_request = std::move(session_request);
+ msg_params->session_receiver = std::move(session_receiver);
GetSpeechRecognizer()->Start(std::move(msg_params));
}
@@ -83,7 +85,7 @@ void ProvideSpeechRecognitionTo(LocalFrame& frame) {
mojo::Remote<mojom::blink::SpeechRecognizer>&
SpeechRecognitionController::GetSpeechRecognizer() {
if (!speech_recognizer_) {
- GetSupplementable()->GetInterfaceProvider().GetInterface(
+ GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
speech_recognizer_.BindNewPipeAndPassReceiver());
}
return speech_recognizer_;
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
index 0e8cd808298..1c3c658e95d 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
@@ -28,6 +28,8 @@
#include <memory>
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -38,7 +40,7 @@ namespace blink {
class SpeechGrammarList;
class SpeechRecognitionController final
- : public GarbageCollectedFinalized<SpeechRecognitionController>,
+ : public GarbageCollected<SpeechRecognitionController>,
public Supplement<LocalFrame> {
USING_GARBAGE_COLLECTED_MIXIN(SpeechRecognitionController);
@@ -48,8 +50,10 @@ class SpeechRecognitionController final
explicit SpeechRecognitionController(LocalFrame& frame);
virtual ~SpeechRecognitionController();
- void Start(mojom::blink::SpeechRecognitionSessionRequest session_request,
- mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client,
+ void Start(mojo::PendingReceiver<mojom::blink::SpeechRecognitionSession>
+ session_receiver,
+ mojo::PendingRemote<mojom::blink::SpeechRecognitionSessionClient>
+ session_client,
const SpeechGrammarList& grammars,
const String& lang,
bool continuous,
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.cc
index b6af5b34492..923f679cb9a 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/modules/speech/speech_recognition_error_event.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error_code.mojom-blink.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.h
index b2a4bfc59b4..a8f68f994f7 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error_event.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_ERROR_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_ERROR_EVENT_H_
-#include "third_party/blink/public/mojom/speech/speech_recognition_error_code.mojom-blink.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error_code.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_error_event_init.h"
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
index 881c00103a0..576818ba299 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -28,7 +28,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom-blink.h"
+#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h
index 095a437502a..763545898bf 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis_utterance.h
@@ -27,7 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_SYNTHESIS_UTTERANCE_H_
#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom-blink.h"
+#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/speech/speech_synthesis_voice.h"
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 d8091d631e0..3e04a018e3e 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
@@ -31,7 +31,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom-blink.h"
-#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom-blink.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/storage/cached_storage_area.h"
@@ -65,7 +65,7 @@ class WebViewClient;
// The StorageNamespace for SessioStorage supplement the Page. |GetCachedArea|
// is used to get the storage area for an origin.
class MODULES_EXPORT StorageNamespace final
- : public GarbageCollectedFinalized<StorageNamespace>,
+ : public GarbageCollected<StorageNamespace>,
public Supplement<Page>,
public CachedStorageArea::InspectorEventListener {
USING_GARBAGE_COLLECTED_MIXIN(StorageNamespace);
diff --git a/chromium/third_party/blink/renderer/modules/storage/testing/fake_area_source.h b/chromium/third_party/blink/renderer/modules/storage/testing/fake_area_source.h
index 3dd94dd97d5..9d57e679df2 100644
--- a/chromium/third_party/blink/renderer/modules/storage/testing/fake_area_source.h
+++ b/chromium/third_party/blink/renderer/modules/storage/testing/fake_area_source.h
@@ -11,7 +11,7 @@
namespace blink {
-class FakeAreaSource : public GarbageCollectedFinalized<FakeAreaSource>,
+class FakeAreaSource : public GarbageCollected<FakeAreaSource>,
public CachedStorageArea::Source {
USING_GARBAGE_COLLECTED_MIXIN(FakeAreaSource);
diff --git a/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.h b/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.h
index 4c2fad06174..c478a282200 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.h
+++ b/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.h
@@ -46,7 +46,7 @@ enum NavigatorVibrationType {
};
class MODULES_EXPORT NavigatorVibration final
- : public GarbageCollectedFinalized<NavigatorVibration>,
+ : public GarbageCollected<NavigatorVibration>,
public Supplement<Navigator>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorVibration);
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 ca05aba2bd1..c42f2033249 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
@@ -19,7 +19,7 @@
#include "third_party/blink/renderer/modules/vibration/vibration_controller.h"
-#include "services/service_manager/public/cpp/interface_provider.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"
@@ -85,8 +85,8 @@ VibrationController::VibrationController(LocalFrame& frame)
is_running_(false),
is_calling_cancel_(false),
is_calling_vibrate_(false) {
- frame.GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&vibration_manager_));
+ frame.GetBrowserInterfaceBroker().GetInterface(
+ vibration_manager_.BindNewPipeAndPassReceiver());
}
VibrationController::~VibrationController() = default;
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 613f45e4a80..3e4153725b0 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h
+++ b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.h
@@ -21,6 +21,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_VIBRATION_VIBRATION_CONTROLLER_H_
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/vibration_manager.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
@@ -36,7 +37,7 @@ class LocalFrame;
class UnsignedLongOrUnsignedLongSequence;
class MODULES_EXPORT VibrationController final
- : public GarbageCollectedFinalized<VibrationController>,
+ : public GarbageCollected<VibrationController>,
public ContextLifecycleObserver,
public PageVisibilityObserver {
USING_GARBAGE_COLLECTED_MIXIN(VibrationController);
@@ -73,9 +74,9 @@ class MODULES_EXPORT VibrationController final
// Inherited from PageVisibilityObserver.
void PageVisibilityChanged() override;
- // Ptr to VibrationManager mojo interface. This is reset in |contextDestroyed|
- // and must not be called or recreated after it is reset.
- device::mojom::blink::VibrationManagerPtr vibration_manager_;
+ // Remote to VibrationManager mojo interface. This is reset in
+ // |contextDestroyed| and must not be called or recreated after it is reset.
+ mojo::Remote<device::mojom::blink::VibrationManager> vibration_manager_;
// Timer for calling |doVibrate| after a delay. It is safe to call
// |startOneshot| when the timer is already running: it may affect the time
diff --git a/chromium/third_party/blink/renderer/modules/vr/DEPS b/chromium/third_party/blink/renderer/modules/vr/DEPS
index fb7ece351e6..4ba629d6702 100644
--- a/chromium/third_party/blink/renderer/modules/vr/DEPS
+++ b/chromium/third_party/blink/renderer/modules/vr/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+mojo/public/cpp/bindings/binding.h",
"+device/vr/public/mojom/vr_service.mojom-blink.h",
+ "+device/vr/public/mojom/vr_service.mojom-blink-forward.h",
"+gpu/command_buffer/client/gles2_interface.h",
"+ui/gfx/geometry",
"+services/metrics/public/cpp/ukm_builders.h"
diff --git a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.h b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.h
index 7f7922274f5..29f360281f7 100644
--- a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.h
+++ b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.h
@@ -21,7 +21,7 @@ class Document;
class VRController;
class MODULES_EXPORT NavigatorVR final
- : public GarbageCollectedFinalized<NavigatorVR>,
+ : public GarbageCollected<NavigatorVR>,
public Supplement<Navigator>,
public LocalDOMWindow::EventListenerObserver,
public FocusChangedObserver {
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc b/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
index 139896ffc8f..fb555e7d41f 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
@@ -7,7 +7,7 @@
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -27,7 +27,7 @@ VRController::VRController(NavigatorVR* navigator_vr)
// See https://bit.ly/2S0zRAS for task types.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
navigator_vr->GetDocument()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- navigator_vr->GetDocument()->GetFrame()->GetInterfaceProvider().GetInterface(
+ navigator_vr->GetDocument()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(
WTF::Bind(&VRController::Dispose, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_controller.h b/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
index 68888f53684..11403461fe3 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -22,7 +22,7 @@ namespace blink {
class NavigatorVR;
-class VRController final : public GarbageCollectedFinalized<VRController>,
+class VRController final : public GarbageCollected<VRController>,
public device::mojom::blink::VRServiceClient,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(VRController);
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display.cc b/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
index c6bc369fc5e..81b28bd5488 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -124,11 +124,19 @@ void SessionClientBinding::OnChanged(
void SessionClientBinding::OnExitPresent() {
display_->OnExitPresent(is_immersive_);
}
-void SessionClientBinding::OnBlur() {
- display_->OnBlur(is_immersive_);
-}
-void SessionClientBinding::OnFocus() {
- display_->OnFocus(is_immersive_);
+void SessionClientBinding::OnVisibilityStateChanged(
+ device::mojom::blink::XRVisibilityState visibility_state) {
+ switch (visibility_state) {
+ case device::mojom::blink::XRVisibilityState::VISIBLE:
+ display_->OnFocus(is_immersive_);
+ break;
+ case device::mojom::blink::XRVisibilityState::VISIBLE_BLURRED:
+ display_->OnBlur(is_immersive_);
+ break;
+ case device::mojom::blink::XRVisibilityState::HIDDEN:
+ display_->OnBlur(is_immersive_);
+ break;
+ }
}
void SessionClientBinding::Trace(blink::Visitor* visitor) {
visitor->Trace(display_);
@@ -557,18 +565,18 @@ void VRDisplay::OnRequestImmersiveSessionReturned(
// The presentation provider error handler can trigger if a device is
// disconnected from the system. This can happen if, for example, an HMD is
// unplugged.
- vr_presentation_data_provider_.set_connection_error_handler(
+ vr_presentation_data_provider_.set_disconnect_handler(
WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
WrapWeakPersistent(this)));
vr_presentation_provider_.Bind(
std::move(session->submit_frame_sink->provider));
- vr_presentation_provider_.set_connection_error_handler(
+ vr_presentation_provider_.set_disconnect_handler(
WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
WrapWeakPersistent(this)));
frame_transport_ = MakeGarbageCollected<XRFrameTransport>();
frame_transport_->BindSubmitFrameClient(
- std::move(session->submit_frame_sink->client_request));
+ std::move(session->submit_frame_sink->client_receiver));
frame_transport_->SetTransportOptions(
std::move(session->submit_frame_sink->transport_options));
@@ -576,7 +584,7 @@ void VRDisplay::OnRequestImmersiveSessionReturned(
immersive_client_binding_->Close();
immersive_client_binding_ = MakeGarbageCollected<SessionClientBinding>(
this, SessionClientBinding::SessionBindingType::kImmersive,
- std::move(session->client_request));
+ std::move(session->client_receiver));
Update(std::move(session->display_info));
@@ -605,7 +613,7 @@ void VRDisplay::SetNonImmersiveSession(
non_immersive_provider_.Bind(std::move(session->data_provider));
non_immersive_client_binding_ = MakeGarbageCollected<SessionClientBinding>(
this, SessionClientBinding::SessionBindingType::kNonImmersive,
- std::move(session->client_request));
+ std::move(session->client_receiver));
}
// Now that we're initialized, we need to ensure that the data is flowing
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display.h b/chromium/third_party/blink/renderer/modules/vr/vr_display.h
index b03e6b39360..c438fc4cb91 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display.h
@@ -8,8 +8,9 @@
#include <memory>
#include <utility>
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_frame_request_callback.h"
@@ -45,9 +46,8 @@ class WebGLRenderingContextBase;
// Wrapper class to allow the VRDisplay to distinguish between immersive and
// non-immersive XRSession events.
-class SessionClientBinding
- : public GarbageCollectedFinalized<SessionClientBinding>,
- public device::mojom::blink::XRSessionClient {
+class SessionClientBinding : public GarbageCollected<SessionClientBinding>,
+ public device::mojom::blink::XRSessionClient {
public:
enum class SessionBindingType {
kImmersive = 0,
@@ -66,8 +66,8 @@ class SessionClientBinding
private:
void OnChanged(device::mojom::blink::VRDisplayInfoPtr) override;
void OnExitPresent() override;
- void OnBlur() override;
- void OnFocus() override;
+ void OnVisibilityStateChanged(
+ device::mojom::blink::XRVisibilityState) override;
// VRDisplay keeps all references to SessionClientBinding, so as soon as
// VRDisplay is destroyed, so is the SessionClientBinding.
@@ -262,7 +262,8 @@ class VRDisplay final : public EventTargetWithInlineData,
bool did_log_requestPresent_ = false;
bool non_immersive_session_initialized_ = false;
- device::mojom::blink::XRFrameDataProviderPtr non_immersive_provider_;
+ mojo::Remote<device::mojom::blink::XRFrameDataProvider>
+ non_immersive_provider_;
bool present_image_needs_copy_ = false;
@@ -270,8 +271,10 @@ class VRDisplay final : public EventTargetWithInlineData,
Member<SessionClientBinding> immersive_client_binding_;
mojo::Receiver<device::mojom::blink::VRDisplayClient>
display_client_receiver_{this};
- device::mojom::blink::XRFrameDataProviderPtr vr_presentation_data_provider_;
- device::mojom::blink::XRPresentationProviderPtr vr_presentation_provider_;
+ mojo::Remote<device::mojom::blink::XRFrameDataProvider>
+ vr_presentation_data_provider_;
+ mojo::Remote<device::mojom::blink::XRPresentationProvider>
+ vr_presentation_provider_;
HeapDeque<Member<ScriptPromiseResolver>> pending_present_resolvers_;
};
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.cc b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.cc
index 729055bb210..e0de2507520 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/vr/vr_eye_parameters.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.h b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.h
index cde8e8b97ca..11068fa643c 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_EYE_PARAMETERS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_EYE_PARAMETERS_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/modules/vr/vr_field_of_view.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.cc b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.cc
index d3e07747c32..b135694f997 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/vr/vr_frame_data.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/modules/vr/vr_eye_parameters.h"
#include "third_party/blink/renderer/modules/vr/vr_pose.h"
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.h b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.h
index b028cbd8d45..b25514aa7b3 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_FRAME_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_FRAME_DATA_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.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/vr/vr_pose.cc b/chromium/third_party/blink/renderer/modules/vr/vr_pose.cc
index d5bc8c4740f..50d3abaceca 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_pose.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_pose.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/vr/vr_pose.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+
namespace blink {
namespace {
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_pose.h b/chromium/third_party/blink/renderer/modules/vr/vr_pose.h
index 626bf3305c2..0e94034c163 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_pose.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_pose.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_POSE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_POSE_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.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/vr/vr_stage_parameters.cc b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.cc
index 3b2169b7c5f..3f298212143 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/vr/vr_stage_parameters.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.h b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.h
index 24e6432d01f..f2aca2a27f1 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_STAGE_PARAMETERS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_VR_VR_STAGE_PARAMETERS_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.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/wake_lock/BUILD.gn b/chromium/third_party/blink/renderer/modules/wake_lock/BUILD.gn
index 5ac56b29436..d9feea597d9 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/BUILD.gn
@@ -6,14 +6,20 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("wake_lock") {
sources = [
+ "navigator_wake_lock.cc",
+ "navigator_wake_lock.h",
"wake_lock.cc",
"wake_lock.h",
- "wake_lock_controller.cc",
- "wake_lock_controller.h",
+ "wake_lock_event.cc",
+ "wake_lock_event.h",
+ "wake_lock_sentinel.cc",
+ "wake_lock_sentinel.h",
"wake_lock_state_record.cc",
"wake_lock_state_record.h",
"wake_lock_type.cc",
"wake_lock_type.h",
+ "worker_navigator_wake_lock.cc",
+ "worker_navigator_wake_lock.h",
]
deps = [
"//mojo/public/cpp/bindings",
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/DEPS b/chromium/third_party/blink/renderer/modules/wake_lock/DEPS
index 12b0536e1e6..271ccdbd562 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/DEPS
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/DEPS
@@ -6,7 +6,7 @@ include_rules = [
]
specific_include_rules = {
- "wake_lock_test_utils\.cc": [
+ "wake_lock_test_utils\.cc|.+_test\.cc": [
"+base/run_loop.h",
],
}
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 f30e0a386f3..8c6e964062b 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/README.md
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/README.md
@@ -101,9 +101,9 @@ This is an implementation detail, but the code handling wake locks in `VideoWake
```c++
mojo::Remote<mojom::blink::WakeLockService> wake_lock_service;
-device::mojom::blink::WakeLockPtr wake_lock;
+mojo::Remote<device::mojom::blink::WakeLock> wake_lock;
execution_context->GetInterface(wake_lock_service.BindNewPipeAndPassReceiver());
-wake_lock_service->GetWakeLock(..., mojo::MakeRequest(&wake_lock));
+wake_lock_service->GetWakeLock(..., wake_lock.BindNewPipeAndPassReceiver());
wake_lock_->RequestWakeLock();
```
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc
new file mode 100644
index 00000000000..e6f900b1bd3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.cc
@@ -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.
+
+#include "third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+
+namespace blink {
+
+NavigatorWakeLock::NavigatorWakeLock(Navigator& navigator)
+ : Supplement<Navigator>(navigator) {}
+
+WakeLock* NavigatorWakeLock::GetWakeLock() {
+ if (!wake_lock_) {
+ auto* frame = GetSupplementable()->GetFrame();
+ if (frame) {
+ DCHECK(frame->GetDocument());
+ wake_lock_ = MakeGarbageCollected<WakeLock>(*frame->GetDocument());
+ }
+ }
+ return wake_lock_;
+}
+
+// static
+const char NavigatorWakeLock::kSupplementName[] = "NavigatorWakeLock";
+
+// static
+NavigatorWakeLock& NavigatorWakeLock::From(Navigator& navigator) {
+ NavigatorWakeLock* supplement =
+ Supplement<Navigator>::From<NavigatorWakeLock>(navigator);
+ if (!supplement) {
+ supplement = MakeGarbageCollected<NavigatorWakeLock>(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ return *supplement;
+}
+
+// static
+WakeLock* NavigatorWakeLock::wakeLock(Navigator& navigator) {
+ return NavigatorWakeLock::From(navigator).GetWakeLock();
+}
+
+void NavigatorWakeLock::Trace(blink::Visitor* visitor) {
+ visitor->Trace(wake_lock_);
+ Supplement<Navigator>::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h
new file mode 100644
index 00000000000..bdfd505cad1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.h
@@ -0,0 +1,39 @@
+// 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_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Navigator;
+class WakeLock;
+
+class NavigatorWakeLock final : public GarbageCollected<NavigatorWakeLock>,
+ public Supplement<Navigator> {
+ USING_GARBAGE_COLLECTED_MIXIN(NavigatorWakeLock);
+
+ public:
+ static const char kSupplementName[];
+
+ static NavigatorWakeLock& From(Navigator&);
+
+ static WakeLock* wakeLock(Navigator&);
+
+ explicit NavigatorWakeLock(Navigator&);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ WakeLock* GetWakeLock();
+
+ Member<WakeLock> wake_lock_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_NAVIGATOR_WAKE_LOCK_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl
new file mode 100644
index 00000000000..36fc458d69d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ ImplementedAs=NavigatorWakeLock,
+ RuntimeEnabled=WakeLock,
+ SecureContext
+] partial interface Navigator {
+ [SameObject] readonly attribute WakeLock wakeLock;
+};
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 b74d76454e1..4d6da59d01b 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
@@ -4,14 +4,15 @@
#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_request_options.h"
+#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -19,28 +20,28 @@
namespace blink {
-// static
-ScriptPromise WakeLock::requestPermission(ScriptState* script_state,
- const String& type) {
- // https://w3c.github.io/wake-lock/#requestpermission-static-method
- // 1. Let promise be a new promise.
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- ScriptPromise promise = resolver->Promise();
+using mojom::blink::PermissionService;
+using mojom::blink::PermissionStatus;
- // 2. Return promise and run the following steps in parallel:
- // 2.1. Let state be the result of running and waiting for the obtain
- // permission steps with type.
- // 2.2. Resolve promise with state.
- auto* document = To<Document>(ExecutionContext::From(script_state));
- WakeLockController::From(document).RequestPermission(ToWakeLockType(type),
- resolver);
- return promise;
-}
+WakeLock::WakeLock(Document& document)
+ : ContextLifecycleObserver(&document),
+ PageVisibilityObserver(document.GetPage()),
+ state_records_{
+ MakeGarbageCollected<WakeLockStateRecord>(&document,
+ WakeLockType::kScreen),
+ MakeGarbageCollected<WakeLockStateRecord>(&document,
+ WakeLockType::kSystem)} {}
-// static
-ScriptPromise WakeLock::request(ScriptState* script_state,
- const String& type,
- WakeLockRequestOptions* options) {
+WakeLock::WakeLock(DedicatedWorkerGlobalScope& worker_scope)
+ : ContextLifecycleObserver(&worker_scope),
+ PageVisibilityObserver(nullptr),
+ state_records_{
+ MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
+ WakeLockType::kScreen),
+ MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
+ WakeLockType::kSystem)} {}
+
+ScriptPromise WakeLock::request(ScriptState* script_state, const String& type) {
// https://w3c.github.io/wake-lock/#request-static-method
auto* context = ExecutionContext::From(script_state);
DCHECK(context->IsDocument() || context->IsDedicatedWorkerGlobalScope());
@@ -111,21 +112,10 @@ ScriptPromise WakeLock::request(ScriptState* script_state,
}
}
- // 5. If options' signal member is present, then run the following steps:
- // 5.1. Let signal be options's signal member.
- // 5.2. If signal’s aborted flag is set, then reject promise with an
- // "AbortError" DOMException and return promise.
- if (options->hasSignal() && options->signal()->aborted()) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
- }
-
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
WakeLockType wake_lock_type = ToWakeLockType(type);
- WakeLockController& controller = WakeLockController::From(context);
switch (wake_lock_type) {
case WakeLockType::kScreen:
@@ -139,20 +129,140 @@ ScriptPromise WakeLock::request(ScriptState* script_state,
break;
}
- // 5.3. Otherwise, add to signal:
- // 5.3.1. Run release a wake lock with promise and type.
- if (options->hasSignal()) {
- options->signal()->AddAlgorithm(WTF::Bind(
- &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
- wake_lock_type, WrapPersistent(resolver)));
- }
-
// 6. Run the following steps in parallel, but abort when options' signal
// member is present and its aborted flag is set:
- controller.RequestWakeLock(wake_lock_type, resolver, options->signal());
+ // 6.1. Let state be the result of awaiting obtain permission steps with
+ // type:
+ DoRequest(wake_lock_type, resolver);
// 7. Return promise.
return promise;
}
+void WakeLock::DoRequest(WakeLockType type, ScriptPromiseResolver* resolver) {
+ ObtainPermission(
+ type, WTF::Bind(&WakeLock::DidReceivePermissionResponse,
+ WrapPersistent(this), type, WrapPersistent(resolver)));
+}
+
+void WakeLock::DidReceivePermissionResponse(WakeLockType type,
+ ScriptPromiseResolver* resolver,
+ PermissionStatus status) {
+ // https://w3c.github.io/wake-lock/#request-static-method
+ DCHECK(status == PermissionStatus::GRANTED ||
+ status == PermissionStatus::DENIED);
+ DCHECK(resolver);
+ // 6.1.1. If state is "denied", then reject promise with a "NotAllowedError"
+ // DOMException, and abort these steps.
+ if (status != PermissionStatus::GRANTED) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotAllowedError,
+ "Wake Lock permission request denied"));
+ return;
+ }
+ // https://github.com/w3c/wake-lock/issues/222: the page can become hidden
+ // between request() and WakeLockStateRecord::AcquireWakeLock(), in which case
+ // we need to abort early.
+ if (type == WakeLockType::kScreen &&
+ !(GetPage() && GetPage()->IsPageVisible())) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kNotAllowedError,
+ "The requesting page is not visible"));
+ return;
+ }
+ // 6.2. Let success be the result of awaiting acquire a wake lock with promise
+ // and type:
+ // 6.2.1. If success is false then reject promise with a "NotAllowedError"
+ // DOMException, and abort these steps.
+ WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
+ DCHECK(state_record);
+ state_record->AcquireWakeLock(resolver);
+}
+
+void WakeLock::ContextDestroyed(ExecutionContext*) {
+ // https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
+ // 1. Let document be the responsible document of the current settings object.
+ // 2. Let screenRecord be the platform wake lock's state record associated
+ // with document and wake lock type "screen".
+ // 3. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
+ // 3.1. Run release a wake lock with lockPromise and "screen".
+ // 4. Let systemRecord be the platform wake lock's state record associated
+ // with document and wake lock type "system".
+ // 5. For each lockPromise in systemRecord.[[WakeLockStateRecord]]:
+ // 5.1. Run release a wake lock with lockPromise and "system".
+ for (WakeLockStateRecord* state_record : state_records_) {
+ if (state_record)
+ state_record->ClearWakeLocks();
+ }
+}
+
+void WakeLock::PageVisibilityChanged() {
+ // https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+ // 1. Let document be the Document of the top-level browsing context.
+ // 2. If document's visibility state is "visible", abort these steps.
+ if (GetPage() && GetPage()->IsPageVisible())
+ return;
+ // 3. Let screenRecord be the platform wake lock's state record associated
+ // with wake lock type "screen".
+ // 4. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
+ // 4.1. Run release a wake lock with lockPromise and "screen".
+ WakeLockStateRecord* state_record =
+ state_records_[static_cast<size_t>(WakeLockType::kScreen)];
+ if (state_record)
+ state_record->ClearWakeLocks();
+}
+
+void WakeLock::ObtainPermission(
+ WakeLockType type,
+ base::OnceCallback<void(PermissionStatus)> callback) {
+ // https://w3c.github.io/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 bypass all the steps covering
+ // calling the "query a permission" algorithm and handling its result).
+ // * 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.
+ // * Even if WakeLockPermissionContext changes in the future, this Blink
+ // implementation is unlikely to change because
+ // WakeLockPermissionContext::RequestPermission() will take its
+ // |user_gesture| argument into account to actually implement a slightly
+ // altered version of "request permission to use", the behavior of which
+ // will match the definition of "obtain permission" in the Wake Lock spec.
+ DCHECK(type == WakeLockType::kScreen || type == WakeLockType::kSystem);
+ static_assert(
+ static_cast<mojom::blink::WakeLockType>(WakeLockType::kScreen) ==
+ mojom::blink::WakeLockType::kScreen,
+ "WakeLockType and mojom::blink::WakeLockType must have identical values");
+ static_assert(
+ static_cast<mojom::blink::WakeLockType>(WakeLockType::kSystem) ==
+ mojom::blink::WakeLockType::kSystem,
+ "WakeLockType and mojom::blink::WakeLockType must have identical values");
+
+ auto* local_frame = GetExecutionContext()->IsDocument()
+ ? To<Document>(GetExecutionContext())->GetFrame()
+ : nullptr;
+ GetPermissionService()->RequestPermission(
+ CreateWakeLockPermissionDescriptor(
+ static_cast<mojom::blink::WakeLockType>(type)),
+ LocalFrame::HasTransientUserActivation(local_frame), std::move(callback));
+}
+
+PermissionService* WakeLock::GetPermissionService() {
+ if (!permission_service_) {
+ ConnectToPermissionService(
+ GetExecutionContext(),
+ permission_service_.BindNewPipeAndPassReceiver());
+ }
+ return permission_service_.get();
+}
+
+void WakeLock::Trace(Visitor* visitor) {
+ for (WakeLockStateRecord* state_record : state_records_)
+ visitor->Trace(state_record);
+ PageVisibilityObserver::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+ ScriptWrappable::Trace(visitor);
+}
+
} // namespace blink
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 4042b2bccbe..4484785512f 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
@@ -5,8 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_H_
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
#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/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
+#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
namespace WTF {
@@ -16,17 +26,60 @@ class String;
namespace blink {
+class ExecutionContext;
class ScriptState;
-class WakeLockRequestOptions;
+class WakeLockStateRecord;
-class WakeLock final : public ScriptWrappable {
+class MODULES_EXPORT WakeLock final : public ScriptWrappable,
+ public ContextLifecycleObserver,
+ public PageVisibilityObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(WakeLock);
DEFINE_WRAPPERTYPEINFO();
public:
- static ScriptPromise requestPermission(ScriptState*, const WTF::String& type);
- static ScriptPromise request(ScriptState*,
- const WTF::String& type,
- WakeLockRequestOptions*);
+ explicit WakeLock(Document&);
+ explicit WakeLock(DedicatedWorkerGlobalScope&);
+
+ ScriptPromise request(ScriptState*, const WTF::String& type);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ // While this could be part of request() itself, having it as a separate
+ // function makes testing (which uses a custom ScriptPromiseResolver) a lot
+ // easier.
+ void DoRequest(WakeLockType, ScriptPromiseResolver*);
+
+ void DidReceivePermissionResponse(WakeLockType,
+ ScriptPromiseResolver*,
+ mojom::blink::PermissionStatus);
+
+ // ContextLifecycleObserver implementation
+ void ContextDestroyed(ExecutionContext*) override;
+
+ // PageVisibilityObserver implementation
+ void PageVisibilityChanged() override;
+
+ // Permission handling
+ void ObtainPermission(
+ WakeLockType,
+ base::OnceCallback<void(mojom::blink::PermissionStatus)> callback);
+ mojom::blink::PermissionService* GetPermissionService();
+
+ mojo::Remote<mojom::blink::PermissionService> permission_service_;
+
+ // https://w3c.github.io/wake-lock/#concepts-and-state-record
+ // Each platform wake lock (one per wake lock type) has an associated state
+ // record per responsible document [...] internal slots.
+ Member<WakeLockStateRecord> state_records_[kWakeLockTypeCount];
+
+ FRIEND_TEST_ALL_PREFIXES(WakeLockSentinelTest, ContextDestruction);
+ FRIEND_TEST_ALL_PREFIXES(WakeLockTest, RequestWakeLockGranted);
+ FRIEND_TEST_ALL_PREFIXES(WakeLockTest, RequestWakeLockDenied);
+ FRIEND_TEST_ALL_PREFIXES(WakeLockTest, LossOfDocumentActivity);
+ FRIEND_TEST_ALL_PREFIXES(WakeLockTest, PageVisibilityHidden);
+ FRIEND_TEST_ALL_PREFIXES(WakeLockTest,
+ PageVisibilityHiddenBeforeLockAcquisition);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.idl b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
index 6fd074ad4cd..806981c25f9 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock.idl
@@ -13,6 +13,5 @@ enum WakeLockType {
Exposed=(DedicatedWorker,Window),
RuntimeEnabled=WakeLock
] interface WakeLock {
- [CallWith=ScriptState, Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type);
- [CallWith=ScriptState] static Promise<void> request(WakeLockType type, optional WakeLockRequestOptions options);
+ [CallWith=ScriptState] Promise<WakeLockSentinel> request(WakeLockType type);
};
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
deleted file mode 100644
index 6c87877bd04..00000000000
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
+++ /dev/null
@@ -1,234 +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/wake_lock/wake_lock_controller.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-using mojom::blink::PermissionService;
-using mojom::blink::PermissionStatus;
-
-WakeLockController::WakeLockController(Document& document)
- : Supplement<ExecutionContext>(document),
- ContextLifecycleObserver(&document),
- PageVisibilityObserver(document.GetPage()),
- state_records_{
- MakeGarbageCollected<WakeLockStateRecord>(&document,
- WakeLockType::kScreen),
- MakeGarbageCollected<WakeLockStateRecord>(&document,
- WakeLockType::kSystem)} {}
-
-WakeLockController::WakeLockController(DedicatedWorkerGlobalScope& worker_scope)
- : Supplement<ExecutionContext>(worker_scope),
- ContextLifecycleObserver(&worker_scope),
- PageVisibilityObserver(nullptr),
- state_records_{
- MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
- WakeLockType::kScreen),
- MakeGarbageCollected<WakeLockStateRecord>(&worker_scope,
- WakeLockType::kSystem)} {}
-
-const char WakeLockController::kSupplementName[] = "WakeLockController";
-
-// static
-WakeLockController& WakeLockController::From(
- ExecutionContext* execution_context) {
- DCHECK(execution_context->IsDocument() ||
- execution_context->IsDedicatedWorkerGlobalScope());
- auto* controller =
- Supplement<ExecutionContext>::From<WakeLockController>(execution_context);
- if (!controller) {
- if (execution_context->IsDocument()) {
- controller = MakeGarbageCollected<WakeLockController>(
- *To<Document>(execution_context));
- } else {
- controller = MakeGarbageCollected<WakeLockController>(
- *To<DedicatedWorkerGlobalScope>(execution_context));
- }
- Supplement<ExecutionContext>::ProvideTo(*execution_context, controller);
- }
- return *controller;
-}
-
-void WakeLockController::Trace(Visitor* visitor) {
- for (WakeLockStateRecord* state_record : state_records_)
- visitor->Trace(state_record);
- PageVisibilityObserver::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
- Supplement<ExecutionContext>::Trace(visitor);
-}
-
-void WakeLockController::RequestWakeLock(WakeLockType type,
- ScriptPromiseResolver* resolver,
- AbortSignal* signal) {
- // https://w3c.github.io/wake-lock/#request-static-method
- // 6. [...] abort when options' signal member is present and its aborted flag
- // is set:
- DCHECK(resolver);
- // We were called via WakeLock::request(), which should have handled the
- // signal->aborted() case.
- DCHECK(!signal || !signal->aborted());
- // 6.1. Let state be the result of awaiting obtain permission steps with
- // type:
- ObtainPermission(
- type, WTF::Bind(&WakeLockController::DidReceivePermissionResponse,
- WrapPersistent(this), type, WrapPersistent(resolver),
- WrapPersistent(signal)));
-}
-
-void WakeLockController::DidReceivePermissionResponse(
- WakeLockType type,
- ScriptPromiseResolver* resolver,
- AbortSignal* signal,
- PermissionStatus status) {
- // https://w3c.github.io/wake-lock/#request-static-method
- DCHECK(status == PermissionStatus::GRANTED ||
- status == PermissionStatus::DENIED);
- DCHECK(resolver);
- if (signal && signal->aborted())
- return;
- // 6.1.1. If state is "denied", then reject promise with a "NotAllowedError"
- // DOMException, and abort these steps.
- if (status != PermissionStatus::GRANTED) {
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotAllowedError,
- "Wake Lock permission request denied"));
- return;
- }
- // https://github.com/w3c/wake-lock/issues/222: the page can become hidden
- // between RequestWakeLock() and AcquireWakeLock(), in which case we need to
- // abort early.
- if (type == WakeLockType::kScreen &&
- !(GetPage() && GetPage()->IsPageVisible())) {
- ReleaseWakeLock(type, resolver);
- return;
- }
- // 6.2. Let success be the result of awaiting acquire a wake lock with promise
- // and type:
- // 6.2.1. If success is false then reject promise with a "NotAllowedError"
- // DOMException, and abort these steps.
- AcquireWakeLock(type, resolver);
-}
-
-void WakeLockController::ReleaseWakeLock(WakeLockType type,
- ScriptPromiseResolver* resolver) {
- DCHECK_LE(type, WakeLockType::kMaxValue);
- WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
- DCHECK(state_record);
- state_record->ReleaseWakeLock(resolver);
-}
-
-void WakeLockController::RequestPermission(WakeLockType type,
- ScriptPromiseResolver* resolver) {
- // https://w3c.github.io/wake-lock/#requestpermission-static-method
- // 2.1. Let state be the result of running and waiting for the obtain
- // permission steps with type.
- // 2.2. Resolve promise with state.
- auto permission_callback = WTF::Bind(
- [](ScriptPromiseResolver* resolver, PermissionStatus status) {
- DCHECK(status == PermissionStatus::GRANTED ||
- status == PermissionStatus::DENIED);
- DCHECK(resolver);
- resolver->Resolve(PermissionStatusToString(status));
- },
- WrapPersistent(resolver));
- ObtainPermission(type, std::move(permission_callback));
-}
-
-void WakeLockController::ContextDestroyed(ExecutionContext*) {
- // https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
- // 1. Let document be the responsible document of the current settings object.
- // 2. Let screenRecord be the platform wake lock's state record associated
- // with document and wake lock type "screen".
- // 3. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
- // 3.1. Run release a wake lock with lockPromise and "screen".
- // 4. Let systemRecord be the platform wake lock's state record associated
- // with document and wake lock type "system".
- // 5. For each lockPromise in systemRecord.[[WakeLockStateRecord]]:
- // 5.1. Run release a wake lock with lockPromise and "system".
- for (WakeLockStateRecord* state_record : state_records_) {
- if (state_record)
- state_record->ClearWakeLocks();
- }
-}
-
-void WakeLockController::PageVisibilityChanged() {
- // https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
- // 1. Let document be the Document of the top-level browsing context.
- // 2. If document's visibility state is "visible", abort these steps.
- if (GetPage() && GetPage()->IsPageVisible())
- return;
- // 3. Let screenRecord be the platform wake lock's state record associated
- // with wake lock type "screen".
- // 4. For each lockPromise in screenRecord.[[WakeLockStateRecord]]:
- // 4.1. Run release a wake lock with lockPromise and "screen".
- WakeLockStateRecord* state_record =
- state_records_[static_cast<size_t>(WakeLockType::kScreen)];
- if (state_record)
- state_record->ClearWakeLocks();
-}
-
-void WakeLockController::AcquireWakeLock(WakeLockType type,
- ScriptPromiseResolver* resolver) {
- DCHECK_LE(type, WakeLockType::kMaxValue);
- WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
- DCHECK(state_record);
- state_record->AcquireWakeLock(resolver);
-}
-
-void WakeLockController::ObtainPermission(
- WakeLockType type,
- base::OnceCallback<void(PermissionStatus)> callback) {
- // https:w3c.github.io/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 bypass all the steps covering
- // calling the "query a permission" algorithm and handling its result).
- // * 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.
- // * Even if WakeLockPermissionContext changes in the future, this Blink
- // implementation is unlikely to change because
- // WakeLockPermissionContext::RequestPermission() will take its
- // |user_gesture| argument into account to actually implement a slightly
- // altered version of "request permission to use", the behavior of which
- // will match the definition of "obtain permission" in the Wake Lock spec.
- DCHECK(type == WakeLockType::kScreen || type == WakeLockType::kSystem);
- static_assert(
- static_cast<mojom::blink::WakeLockType>(WakeLockType::kScreen) ==
- mojom::blink::WakeLockType::kScreen,
- "WakeLockType and mojom::blink::WakeLockType must have identical values");
- static_assert(
- static_cast<mojom::blink::WakeLockType>(WakeLockType::kSystem) ==
- mojom::blink::WakeLockType::kSystem,
- "WakeLockType and mojom::blink::WakeLockType must have identical values");
-
- auto* local_frame = GetExecutionContext()->IsDocument()
- ? To<Document>(GetExecutionContext())->GetFrame()
- : nullptr;
-
- GetPermissionService()->RequestPermission(
- CreateWakeLockPermissionDescriptor(
- static_cast<mojom::blink::WakeLockType>(type)),
- LocalFrame::HasTransientUserActivation(local_frame), std::move(callback));
-}
-
-PermissionService* WakeLockController::GetPermissionService() {
- if (!permission_service_) {
- ConnectToPermissionService(
- GetExecutionContext(),
- permission_service_.BindNewPipeAndPassReceiver());
- }
- return permission_service_.get();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h
deleted file mode 100644
index 4688fdd5a97..00000000000
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.h
+++ /dev/null
@@ -1,88 +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_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
-
-#include "base/callback.h"
-#include "base/gtest_prod_util.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
-#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class AbortSignal;
-class ExecutionContext;
-class ScriptPromiseResolver;
-class WakeLockStateRecord;
-
-// WakeLockController is used to track per-Document wake lock state and react to
-// Document changes appropriately.
-class MODULES_EXPORT WakeLockController final
- : public GarbageCollectedFinalized<WakeLockController>,
- public Supplement<ExecutionContext>,
- public ContextLifecycleObserver,
- public PageVisibilityObserver {
- USING_GARBAGE_COLLECTED_MIXIN(WakeLockController);
-
- public:
- static const char kSupplementName[];
-
- explicit WakeLockController(Document&);
- explicit WakeLockController(DedicatedWorkerGlobalScope&);
-
- static WakeLockController& From(ExecutionContext*);
-
- void Trace(blink::Visitor*) override;
-
- void RequestWakeLock(WakeLockType type,
- ScriptPromiseResolver* resolver,
- AbortSignal* signal);
-
- void ReleaseWakeLock(WakeLockType type, ScriptPromiseResolver*);
-
- void RequestPermission(WakeLockType type, ScriptPromiseResolver*);
-
- private:
- // ContextLifecycleObserver implementation
- void ContextDestroyed(ExecutionContext*) override;
-
- // PageVisibilityObserver implementation
- void PageVisibilityChanged() override;
-
- void AcquireWakeLock(WakeLockType type, ScriptPromiseResolver*);
-
- void DidReceivePermissionResponse(WakeLockType type,
- ScriptPromiseResolver*,
- AbortSignal*,
- mojom::blink::PermissionStatus);
-
- // Permission handling
- void ObtainPermission(
- WakeLockType type,
- base::OnceCallback<void(mojom::blink::PermissionStatus)> callback);
- mojom::blink::PermissionService* GetPermissionService();
-
- mojo::Remote<mojom::blink::PermissionService> permission_service_;
-
- // https://w3c.github.io/wake-lock/#concepts-and-state-record
- // Each platform wake lock (one per wake lock type) has an associated state
- // record per responsible document [...] internal slots.
- Member<WakeLockStateRecord> state_records_[kWakeLockTypeCount];
-
- FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireScreenWakeLock);
- FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireSystemWakeLock);
- FRIEND_TEST_ALL_PREFIXES(WakeLockControllerTest, AcquireMultipleLocks);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_CONTROLLER_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
deleted file mode 100644
index 32d40ff0145..00000000000
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
+++ /dev/null
@@ -1,488 +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/wake_lock/wake_lock_controller.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-TEST(WakeLockControllerTest, RequestWakeLockGranted) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver, nullptr);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- MockPermissionService& permission_service = context.GetPermissionService();
-
- permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
- screen_lock.WaitForRequest();
-
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, RequestWakeLockDenied) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
-
- auto* system_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise = system_resolver->Promise();
-
- controller.RequestWakeLock(WakeLockType::kSystem, system_resolver, nullptr);
-
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- MockPermissionService& permission_service = context.GetPermissionService();
-
- permission_service.WaitForPermissionRequest(WakeLockType::kSystem);
- context.WaitForPromiseRejection(system_promise);
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(system_promise));
- EXPECT_FALSE(system_lock.is_acquired());
-
- // System locks are not allowed by default, so the promise should have been
- // rejected with a NotAllowedError DOMException.
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(system_promise);
- ASSERT_NE(dom_exception, nullptr);
- EXPECT_EQ("NotAllowedError", dom_exception->name());
-}
-
-// Abort early in DidReceivePermissionResponse().
-TEST(WakeLockControllerTest, RequestWakeLockAbortEarly) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
- abort_signal->AddAlgorithm(WTF::Bind(
- &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
- WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
- controller.RequestWakeLock(
- WakeLockType::kScreen,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()),
- abort_signal);
-
- MockPermissionService& permission_service = context.GetPermissionService();
-
- permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
- abort_signal->SignalAbort();
-
- context.WaitForPromiseRejection(screen_promise);
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- EXPECT_FALSE(screen_lock.is_acquired());
-
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
- ASSERT_NE(dom_exception, nullptr);
- EXPECT_EQ("AbortError", dom_exception->name());
-}
-
-TEST(WakeLockControllerTest, AcquireScreenWakeLock) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- controller.AcquireWakeLock(
- WakeLockType::kScreen,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- screen_lock.WaitForRequest();
-
- EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, AcquireSystemWakeLock) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- controller.AcquireWakeLock(
- WakeLockType::kSystem,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- system_lock.WaitForRequest();
-
- EXPECT_TRUE(system_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, AcquireMultipleLocks) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- controller.AcquireWakeLock(
- WakeLockType::kScreen,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
- controller.AcquireWakeLock(
- WakeLockType::kSystem,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
- controller.AcquireWakeLock(
- WakeLockType::kSystem,
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()));
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- screen_lock.WaitForRequest();
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- system_lock.WaitForRequest();
-
- EXPECT_TRUE(screen_lock.is_acquired());
- EXPECT_TRUE(system_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, ReleaseUnaquiredWakeLockRejectsPromise) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
- auto* resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise promise = resolver->Promise();
-
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise));
- controller.ReleaseWakeLock(WakeLockType::kScreen, resolver);
- context.WaitForPromiseRejection(promise);
-
- // The promise is always rejected, even if it is not in [[ActiveLocks]].
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, ReleaseWakeLock) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
- auto* resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise promise = resolver->Promise();
-
- controller.RequestWakeLock(WakeLockType::kScreen, resolver,
- /*signal=*/nullptr);
- screen_lock.WaitForRequest();
- controller.ReleaseWakeLock(WakeLockType::kScreen, resolver);
- context.WaitForPromiseRejection(promise);
- screen_lock.WaitForCancelation();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// This is actually part of WakeLock::request(), but it is easier to just test
-// it here.
-TEST(WakeLockControllerTest, AbortSignal) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
- abort_signal->AddAlgorithm(WTF::Bind(
- &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
- WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
- /*signal=*/nullptr);
- screen_lock.WaitForRequest();
-
- abort_signal->SignalAbort();
- context.WaitForPromiseRejection(screen_promise);
- screen_lock.WaitForCancelation();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
-TEST(WakeLockControllerTest, LossOfDocumentActivity) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
- // First, acquire a handful of locks of different types.
- auto* screen_resolver1 =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise1 = screen_resolver1->Promise();
- auto* screen_resolver2 =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise2 = screen_resolver2->Promise();
- auto* system_resolver1 =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise1 = system_resolver1->Promise();
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver1,
- /*signal=*/nullptr);
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver2,
- /*signal=*/nullptr);
- screen_lock.WaitForRequest();
- controller.RequestWakeLock(WakeLockType::kSystem, system_resolver1,
- /*signal=*/nullptr);
- system_lock.WaitForRequest();
-
- // Now shut down our Document and make sure all [[ActiveLocks]] slots have
- // been cleared. We cannot check that the promises have been rejected because
- // ScriptPromiseResolver::Reject() will bail out if we no longer have a valid
- // execution context.
- context.GetDocument()->Shutdown();
- screen_lock.WaitForCancelation();
- system_lock.WaitForCancelation();
-
- EXPECT_FALSE(screen_lock.is_acquired());
- EXPECT_FALSE(system_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
-TEST(WakeLockControllerTest, PageVisibilityHidden) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- auto* system_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise = system_resolver->Promise();
-
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
- /*signal=*/nullptr);
- controller.RequestWakeLock(WakeLockType::kSystem, system_resolver,
- /*signal=*/nullptr);
-
- screen_lock.WaitForRequest();
- system_lock.WaitForRequest();
-
- context.GetDocument()->GetPage()->SetIsHidden(true, false);
-
- context.WaitForPromiseRejection(screen_promise);
- screen_lock.WaitForCancelation();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
- ASSERT_NE(dom_exception, nullptr);
- EXPECT_EQ("AbortError", dom_exception->name());
- EXPECT_FALSE(screen_lock.is_acquired());
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(system_promise));
- EXPECT_TRUE(system_lock.is_acquired());
-
- context.GetDocument()->GetPage()->SetIsHidden(false, false);
-
- auto* other_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise other_promise = system_resolver->Promise();
- controller.RequestWakeLock(WakeLockType::kScreen, other_resolver,
- /*signal=*/nullptr);
- screen_lock.WaitForRequest();
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(other_promise));
- EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
-TEST(WakeLockControllerTest, PageVisibilityHiddenBeforeLockAcquisition) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- MockWakeLock& system_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kSystem);
- auto* system_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise = system_resolver->Promise();
-
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
- /*signal=*/nullptr);
- controller.RequestWakeLock(WakeLockType::kSystem, system_resolver,
- /*signal=*/nullptr);
- context.GetDocument()->GetPage()->SetIsHidden(true, false);
-
- context.WaitForPromiseRejection(screen_promise);
- system_lock.WaitForRequest();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- EXPECT_FALSE(screen_lock.is_acquired());
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(system_promise));
- EXPECT_TRUE(system_lock.is_acquired());
-}
-
-// Check that hiding a page and signaling abort does not try to delete a
-// screen lock twice.
-TEST(WakeLockControllerTest, PageVisibilityAndAbortSignal) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
- auto* screen_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise screen_promise = screen_resolver->Promise();
-
- auto* abort_signal = MakeGarbageCollected<AbortSignal>(context.GetDocument());
- abort_signal->AddAlgorithm(WTF::Bind(
- &WakeLockController::ReleaseWakeLock, WrapWeakPersistent(&controller),
- WakeLockType::kScreen, WrapPersistent(screen_resolver)));
-
- controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver,
- /*signal=*/nullptr);
- screen_lock.WaitForRequest();
-
- context.GetDocument()->GetPage()->SetIsHidden(true, false);
- context.WaitForPromiseRejection(screen_promise);
- screen_lock.WaitForCancelation();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(screen_promise));
- EXPECT_FALSE(screen_lock.is_acquired());
-
- abort_signal->SignalAbort();
- test::RunPendingTasks();
-
- EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockControllerTest, RequestPermissionGranted) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
-
- auto* system_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise = system_resolver->Promise();
-
- controller.RequestPermission(WakeLockType::kSystem, system_resolver);
- context.WaitForPromiseFulfillment(system_promise);
-
- EXPECT_EQ(v8::Promise::kFulfilled,
- ScriptPromiseUtils::GetPromiseState(system_promise));
- EXPECT_EQ("granted",
- ScriptPromiseUtils::GetPromiseResolutionAsString(system_promise));
-}
-
-TEST(WakeLockControllerTest, RequestPermissionDenied) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto& controller = WakeLockController::From(context.GetDocument());
-
- context.GetPermissionService().SetPermissionResponse(
- WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
-
- auto* system_resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise system_promise = system_resolver->Promise();
-
- controller.RequestPermission(WakeLockType::kSystem, system_resolver);
- context.WaitForPromiseFulfillment(system_promise);
-
- EXPECT_EQ(v8::Promise::kFulfilled,
- ScriptPromiseUtils::GetPromiseState(system_promise));
- EXPECT_EQ("denied",
- ScriptPromiseUtils::GetPromiseResolutionAsString(system_promise));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc
new file mode 100644
index 00000000000..866fbaeb109
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.cc
@@ -0,0 +1,46 @@
+// 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/wake_lock/wake_lock_event.h"
+
+#include "base/logging.h"
+#include "third_party/blink/renderer/modules/event_interface_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+// static
+WakeLockEvent* WakeLockEvent::Create(const AtomicString& type,
+ const WakeLockEventInit* initializer) {
+ DCHECK(initializer->hasLock());
+ return MakeGarbageCollected<WakeLockEvent>(type, initializer);
+}
+
+WakeLockEvent::WakeLockEvent(const AtomicString& type,
+ const WakeLockEventInit* initializer)
+ : Event(type, initializer), lock_(initializer->lock()) {
+ DCHECK_NE(nullptr, lock_);
+}
+
+WakeLockEvent::WakeLockEvent(const AtomicString& type, WakeLockSentinel* lock)
+ : Event(type, Bubbles::kNo, Cancelable::kNo), lock_(lock) {}
+
+WakeLockEvent::~WakeLockEvent() = default;
+
+WakeLockSentinel* WakeLockEvent::lock() const {
+ return lock_;
+}
+
+const AtomicString& WakeLockEvent::InterfaceName() const {
+ return event_interface_names::kWakeLockEvent;
+}
+
+void WakeLockEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(lock_);
+ Event::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h
new file mode 100644
index 00000000000..228a4b13597
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.h
@@ -0,0 +1,41 @@
+// 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_WAKE_LOCK_WAKE_LOCK_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_EVENT_H_
+
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class WakeLockEventInit;
+class WakeLockSentinel;
+
+class WakeLockEvent final : public Event {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static WakeLockEvent* Create(const AtomicString& type,
+ const WakeLockEventInit* initializer);
+
+ WakeLockEvent(const AtomicString& type, const WakeLockEventInit* initializer);
+ WakeLockEvent(const AtomicString& type, WakeLockSentinel* lock);
+ ~WakeLockEvent() override;
+
+ // Web-exposed APIs.
+ WakeLockSentinel* lock() const;
+
+ // Event overrides.
+ const AtomicString& InterfaceName() const override;
+ void Trace(blink::Visitor* visitor) override;
+
+ private:
+ const Member<WakeLockSentinel> lock_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl
new file mode 100644
index 00000000000..9ad1cfb5b7e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event.idl
@@ -0,0 +1,12 @@
+// 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.
+
+[
+ SecureContext,
+ Exposed=(DedicatedWorker,Window),
+ Constructor(DOMString type, WakeLockEventInit init),
+ RuntimeEnabled=WakeLock
+] interface WakeLockEvent : Event {
+ readonly attribute WakeLockSentinel lock;
+};
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl
new file mode 100644
index 00000000000..40d203e5e49
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.idl
@@ -0,0 +1,7 @@
+// 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.
+
+dictionary WakeLockEventInit : EventInit {
+ required WakeLockSentinel lock;
+};
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.cc
new file mode 100644
index 00000000000..2738eb99a9e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.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/modules/wake_lock/wake_lock_sentinel.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/event_target_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_event_init.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+WakeLockSentinel::WakeLockSentinel(ScriptState* script_state,
+ WakeLockType type,
+ WakeLockStateRecord* manager)
+ : ContextLifecycleObserver(ExecutionContext::From(script_state)),
+ manager_(manager),
+ type_(type) {}
+
+WakeLockSentinel::~WakeLockSentinel() = default;
+
+ScriptPromise WakeLockSentinel::release(ScriptState* script_state) {
+ DoRelease();
+ return ScriptPromise::CastUndefined(script_state);
+}
+
+String WakeLockSentinel::type() const {
+ switch (type_) {
+ case WakeLockType::kScreen:
+ return "screen";
+ case WakeLockType::kSystem:
+ return "system";
+ }
+}
+
+ExecutionContext* WakeLockSentinel::GetExecutionContext() const {
+ return ContextLifecycleObserver::GetExecutionContext();
+}
+
+const AtomicString& WakeLockSentinel::InterfaceName() const {
+ return event_target_names::kWakeLockSentinel;
+}
+
+void WakeLockSentinel::Trace(blink::Visitor* visitor) {
+ visitor->Trace(manager_);
+ EventTargetWithInlineData::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+bool WakeLockSentinel::HasPendingActivity() const {
+ return HasEventListeners();
+}
+
+void WakeLockSentinel::ContextDestroyed(ExecutionContext*) {
+ // Release all event listeners so that HasPendingActivity() does not return
+ // true forever once a listener has been added to the object.
+ RemoveAllEventListeners();
+ DCHECK(!HasEventListeners());
+}
+
+void WakeLockSentinel::DoRelease() {
+ if (!manager_)
+ return;
+
+ manager_->UnregisterSentinel(this);
+ manager_.Clear();
+
+ // This function may be called on ExecutionContext destruction. Events should
+ // not be dispatched in this case.
+ if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
+ return;
+
+ DispatchEvent(
+ *MakeGarbageCollected<WakeLockEvent>(event_type_names::kRelease, this));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h
new file mode 100644
index 00000000000..30d954a1f50
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.h
@@ -0,0 +1,72 @@
+// 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_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
+
+#include "base/gtest_prod_util.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/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ExecutionContext;
+class ScriptState;
+class WakeLockStateRecord;
+
+class MODULES_EXPORT WakeLockSentinel final
+ : public EventTargetWithInlineData,
+ public ActiveScriptWrappable<WakeLockSentinel>,
+ public ContextLifecycleObserver {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(WakeLockSentinel);
+
+ public:
+ WakeLockSentinel(ScriptState* script_state,
+ WakeLockType type,
+ WakeLockStateRecord* manager);
+ ~WakeLockSentinel() override;
+
+ // Web-exposed interfaces
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(release, kRelease)
+ ScriptPromise release(ScriptState*);
+ String type() const;
+
+ // EventTarget overrides.
+ ExecutionContext* GetExecutionContext() const override;
+ const AtomicString& InterfaceName() const override;
+ void Trace(blink::Visitor*) override;
+
+ // ActiveScriptWrappable overrides.
+ bool HasPendingActivity() const override;
+
+ // ContextLifecycleObserver overrides.
+ void ContextDestroyed(ExecutionContext*) override;
+
+ private:
+ friend class WakeLockStateRecord;
+
+ // This function, which only has any effect once, detaches this sentinel from
+ // its |manager_|, and fires a "release" event.
+ // It is implemented separately from release() itself so that |manager_| can
+ // call it without triggering the creation of a new ScriptPromise, as it is
+ // not relevant to |manager_| and this function may be called from a context
+ // where |script_state_|'s context is no longer valid.
+ void DoRelease();
+
+ Member<WakeLockStateRecord> manager_;
+ const WakeLockType type_;
+
+ FRIEND_TEST_ALL_PREFIXES(WakeLockSentinelTest, MultipleReleaseCalls);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_SENTINEL_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl
new file mode 100644
index 00000000000..f747650f99a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel.idl
@@ -0,0 +1,16 @@
+// 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.
+
+[
+ ActiveScriptWrappable,
+ Exposed=(DedicatedWorker,Window),
+ RuntimeEnabled=WakeLock,
+ SecureContext
+] interface WakeLockSentinel : EventTarget {
+ attribute EventHandler onrelease;
+
+ readonly attribute WakeLockType type;
+
+ [CallWith=ScriptState] Promise<void> release();
+};
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc
new file mode 100644
index 00000000000..e086827f145
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_sentinel_test.cc
@@ -0,0 +1,121 @@
+// 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/wake_lock/wake_lock_sentinel.h"
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
+#include "third_party/blink/renderer/modules/event_target_modules_names.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+namespace {
+
+class SyncEventListener final : public NativeEventListener {
+ public:
+ SyncEventListener(base::OnceClosure invocation_callback)
+ : invocation_callback_(std::move(invocation_callback)) {}
+ void Invoke(ExecutionContext*, Event*) override {
+ DCHECK(invocation_callback_);
+ std::move(invocation_callback_).Run();
+ }
+
+ private:
+ base::OnceClosure invocation_callback_;
+};
+
+} // namespace
+
+TEST(WakeLockSentinelTest, SentinelType) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ auto* sentinel = MakeGarbageCollected<WakeLockSentinel>(
+ context.GetScriptState(), WakeLockType::kScreen, /*manager=*/nullptr);
+ EXPECT_EQ("screen", sentinel->type());
+
+ sentinel = MakeGarbageCollected<WakeLockSentinel>(
+ context.GetScriptState(), WakeLockType::kSystem, /*manager=*/nullptr);
+ EXPECT_EQ("system", sentinel->type());
+}
+
+TEST(WakeLockSentinelTest, MultipleReleaseCalls) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ auto* state_record = MakeGarbageCollected<WakeLockStateRecord>(
+ context.GetDocument(), WakeLockType::kScreen);
+ auto* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise promise = resolver->Promise();
+ state_record->AcquireWakeLock(resolver);
+ context.WaitForPromiseFulfillment(promise);
+ auto* sentinel =
+ ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise);
+ ASSERT_NE(nullptr, sentinel);
+
+ base::RunLoop run_loop;
+ auto* event_listener =
+ MakeGarbageCollected<SyncEventListener>(run_loop.QuitClosure());
+ sentinel->addEventListener(event_type_names::kRelease, event_listener);
+ sentinel->release(context.GetScriptState());
+ run_loop.Run();
+ sentinel->removeEventListener(event_type_names::kRelease, event_listener);
+
+ EXPECT_EQ(nullptr, sentinel->manager_);
+
+ event_listener = MakeGarbageCollected<SyncEventListener>(WTF::Bind([]() {
+ EXPECT_TRUE(false) << "This event handler should not be reached.";
+ }));
+ sentinel->addEventListener(event_type_names::kRelease, event_listener);
+ sentinel->release(context.GetScriptState());
+}
+
+TEST(WakeLockSentinelTest, ContextDestruction) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+
+ auto* screen_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise screen_promise = screen_resolver->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+
+ WakeLockStateRecord* state_record =
+ wake_lock->state_records_[static_cast<size_t>(WakeLockType::kScreen)];
+ ASSERT_TRUE(state_record);
+
+ context.WaitForPromiseFulfillment(screen_promise);
+ auto* sentinel = ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
+ screen_promise);
+ ASSERT_TRUE(sentinel);
+
+ auto* event_listener =
+ MakeGarbageCollected<SyncEventListener>(WTF::Bind([]() {
+ EXPECT_TRUE(false) << "This event handler should not be reached.";
+ }));
+ sentinel->addEventListener(event_type_names::kRelease, event_listener);
+ EXPECT_TRUE(sentinel->HasPendingActivity());
+
+ context.GetDocument()->Shutdown();
+
+ // If the method returns false the object can be GC'ed.
+ EXPECT_FALSE(sentinel->HasPendingActivity());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
index 37d8ba05609..c5194fb2dea 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
@@ -5,19 +5,19 @@
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h"
#include "base/logging.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/wake_lock/wake_lock.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/modules/wake_lock/wake_lock_sentinel.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
WakeLockStateRecord::WakeLockStateRecord(ExecutionContext* execution_context,
WakeLockType type)
- : wake_lock_type_(ToMojomWakeLockType(type)),
- execution_context_(execution_context) {
+ : wake_lock_type_(type), execution_context_(execution_context) {
DCHECK_NE(execution_context, nullptr);
}
@@ -37,60 +37,39 @@ void WakeLockStateRecord::AcquireWakeLock(ScriptPromiseResolver* resolver) {
// 4.3. Add lockPromise to record.[[WakeLockStateRecord]].
// 5. Return active.
if (!wake_lock_) {
- auto* interface_provider = execution_context_->GetInterfaceProvider();
- DCHECK(interface_provider);
mojo::Remote<mojom::blink::WakeLockService> wake_lock_service;
- interface_provider->GetInterface(
+ execution_context_->GetBrowserInterfaceBroker().GetInterface(
wake_lock_service.BindNewPipeAndPassReceiver());
- wake_lock_service->GetWakeLock(
- wake_lock_type_, device::mojom::blink::WakeLockReason::kOther,
- "Blink Wake Lock", wake_lock_.BindNewPipeAndPassReceiver());
+ wake_lock_service->GetWakeLock(ToMojomWakeLockType(wake_lock_type_),
+ device::mojom::blink::WakeLockReason::kOther,
+ "Blink Wake Lock",
+ wake_lock_.BindNewPipeAndPassReceiver());
wake_lock_.set_disconnect_handler(
WTF::Bind(&WakeLockStateRecord::OnWakeLockConnectionError,
WrapWeakPersistent(this)));
wake_lock_->RequestWakeLock();
}
- DCHECK(!active_locks_.Contains(resolver));
- active_locks_.insert(resolver);
+ auto* sentinel = MakeGarbageCollected<WakeLockSentinel>(
+ resolver->GetScriptState(), wake_lock_type_, this);
+ wake_lock_sentinels_.insert(sentinel);
+ resolver->Resolve(sentinel);
}
-void WakeLockStateRecord::ReleaseWakeLock(ScriptPromiseResolver* resolver) {
- // https://w3c.github.io/wake-lock/#release-wake-lock-algorithm
- // 1. Reject lockPromise with an "AbortError" DOMException.
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kAbortError, "Wake Lock released"));
+void WakeLockStateRecord::UnregisterSentinel(WakeLockSentinel* sentinel) {
+ auto iterator = wake_lock_sentinels_.find(sentinel);
+ DCHECK(iterator != wake_lock_sentinels_.end());
+ wake_lock_sentinels_.erase(iterator);
- // 2. Let document be the responsible document of the current settings object.
- // 3. Let record be the platform wake lock's state record associated with
- // document and type.
- // 4. If record.[[ActiveLocks]] does not contain lockPromise, abort these
- // steps.
- auto iterator = active_locks_.find(resolver);
- if (iterator == active_locks_.end())
- return;
-
- // 5. Remove lockPromise from record.[[ActiveLocks]].
- active_locks_.erase(iterator);
-
- // 6. If the internal slot [[ActiveLocks]] of all the platform wake lock's
- // state records are all empty, then run the following steps in parallel:
- // 6.1. Ask the underlying operation system to release the wake lock of type
- // type and let success be true if the operation succeeded, or else
- // false.
- if (active_locks_.IsEmpty() && wake_lock_.is_bound()) {
+ if (wake_lock_sentinels_.IsEmpty() && wake_lock_.is_bound()) {
wake_lock_->CancelWakeLock();
wake_lock_.reset();
-
- // 6.2. If success is true and type is "screen" run the following:
- // 6.2.1. Reset the platform-specific inactivity timer after which the
- // screen is actually turned off.
}
}
void WakeLockStateRecord::ClearWakeLocks() {
- while (!active_locks_.IsEmpty())
- ReleaseWakeLock(*active_locks_.begin());
+ while (!wake_lock_sentinels_.IsEmpty())
+ (*wake_lock_sentinels_.begin())->DoRelease();
}
void WakeLockStateRecord::OnWakeLockConnectionError() {
@@ -100,7 +79,7 @@ void WakeLockStateRecord::OnWakeLockConnectionError() {
void WakeLockStateRecord::Trace(blink::Visitor* visitor) {
visitor->Trace(execution_context_);
- visitor->Trace(active_locks_);
+ visitor->Trace(wake_lock_sentinels_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
index 5a8a9af7841..c40a504771c 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
@@ -7,7 +7,7 @@
#include "base/gtest_prod_util.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/wake_lock.mojom-blink.h"
+#include "services/device/public/mojom/wake_lock.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -16,45 +16,41 @@ namespace blink {
class ExecutionContext;
class ScriptPromiseResolver;
+class WakeLockSentinel;
// https://w3c.github.io/wake-lock/#concepts-and-state-record
// Per-document and per-wake lock type internal data.
-class MODULES_EXPORT WakeLockStateRecord
- : public GarbageCollectedFinalized<WakeLockStateRecord> {
+class MODULES_EXPORT WakeLockStateRecord final
+ : public GarbageCollected<WakeLockStateRecord> {
public:
WakeLockStateRecord(ExecutionContext*, WakeLockType);
void AcquireWakeLock(ScriptPromiseResolver*);
- void ReleaseWakeLock(ScriptPromiseResolver*);
void ClearWakeLocks();
+ void UnregisterSentinel(WakeLockSentinel*);
+
void Trace(blink::Visitor* visitor);
private:
- using ActiveLocksType = HeapHashSet<Member<ScriptPromiseResolver>>;
-
- friend class WakeLockControllerTest;
-
// Handle connection errors from |wake_lock_|.
void OnWakeLockConnectionError();
- // A list of Promises representing active wake locks associated with the
- // responsible document.
- ActiveLocksType active_locks_;
+ // A set with all WakeLockSentinel instances belonging to this
+ // Navigator/WorkerNavigator.
+ HeapHashSet<Member<WakeLockSentinel>> wake_lock_sentinels_;
// An actual platform WakeLock. If bound, it means there is an active wake
// lock for a given type.
mojo::Remote<device::mojom::blink::WakeLock> wake_lock_;
- device::mojom::blink::WakeLockType wake_lock_type_;
+ WakeLockType wake_lock_type_;
// ExecutionContext from which we will connect to |wake_lock_service_|.
Member<ExecutionContext> execution_context_;
FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, AcquireWakeLock);
FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseAllWakeLocks);
- FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseNonExistentWakeLock);
FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseOneWakeLock);
- FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseRejectsPromise);
FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ClearWakeLocks);
FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, WakeLockConnectionError);
};
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
index 3fea7bcfc3a..ed2828c27eb 100644
--- a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
@@ -33,6 +33,7 @@ TEST(WakeLockStateRecordTest, AcquireWakeLock) {
MockWakeLock& screen_lock =
wake_lock_service.get_wake_lock(WakeLockType::kScreen);
EXPECT_FALSE(screen_lock.is_acquired());
+ EXPECT_FALSE(state_record->wake_lock_.is_bound());
auto* resolver1 =
MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
@@ -45,12 +46,19 @@ TEST(WakeLockStateRecordTest, AcquireWakeLock) {
state_record->AcquireWakeLock(resolver2);
screen_lock.WaitForRequest();
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise1));
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise2));
+ context.WaitForPromiseFulfillment(promise1);
+ context.WaitForPromiseFulfillment(promise2);
+
+ auto* sentinel1 =
+ ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise1);
+ auto* sentinel2 =
+ ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise2);
+
+ EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel1));
+ EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel2));
+ EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
EXPECT_TRUE(screen_lock.is_acquired());
- EXPECT_EQ(2U, state_record->active_locks_.size());
+ EXPECT_TRUE(state_record->wake_lock_.is_bound());
}
TEST(WakeLockStateRecordTest, ReleaseAllWakeLocks) {
@@ -67,61 +75,20 @@ TEST(WakeLockStateRecordTest, ReleaseAllWakeLocks) {
state_record->AcquireWakeLock(resolver);
screen_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(promise);
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_EQ(1U, state_record->active_locks_.size());
+ EXPECT_EQ(1U, state_record->wake_lock_sentinels_.size());
EXPECT_TRUE(screen_lock.is_acquired());
- state_record->ReleaseWakeLock(resolver);
- context.WaitForPromiseRejection(promise);
- screen_lock.WaitForCancelation();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
-
- EXPECT_EQ(0U, state_record->active_locks_.size());
- EXPECT_FALSE(screen_lock.is_acquired());
-}
-
-// Test that trying to remove an entry that does not exist is a no-op. This can
-// happen, for example, when a page visibility change releases a screen lock
-// and a call to AbortController.abort() causes an attempt to release the same
-// lock again.
-TEST(WakeLockStateRecordTest, ReleaseNonExistentWakeLock) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto* state_record = MakeStateRecord(context, WakeLockType::kScreen);
+ auto* sentinel =
+ ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise);
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
- auto* resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise promise = resolver->Promise();
-
- state_record->AcquireWakeLock(resolver);
- screen_lock.WaitForRequest();
- state_record->ReleaseWakeLock(resolver);
- context.WaitForPromiseRejection(promise);
+ state_record->UnregisterSentinel(sentinel);
screen_lock.WaitForCancelation();
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_EQ(0U, state_record->active_locks_.size());
- EXPECT_FALSE(screen_lock.is_acquired());
-
- state_record->ReleaseWakeLock(resolver);
- test::RunPendingTasks();
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_EQ(0U, state_record->active_locks_.size());
+ EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
EXPECT_FALSE(screen_lock.is_acquired());
+ EXPECT_FALSE(state_record->wake_lock_.is_bound());
}
TEST(WakeLockStateRecordTest, ReleaseOneWakeLock) {
@@ -143,54 +110,24 @@ TEST(WakeLockStateRecordTest, ReleaseOneWakeLock) {
state_record->AcquireWakeLock(resolver2);
screen_lock.WaitForRequest();
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise1));
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise2));
- EXPECT_EQ(2U, state_record->active_locks_.size());
- EXPECT_TRUE(screen_lock.is_acquired());
-
- state_record->ReleaseWakeLock(resolver1);
- context.WaitForPromiseRejection(promise1);
+ context.WaitForPromiseFulfillment(promise1);
+ context.WaitForPromiseFulfillment(promise2);
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise1));
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise2));
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
-
- EXPECT_EQ(1U, state_record->active_locks_.size());
EXPECT_TRUE(screen_lock.is_acquired());
-}
-
-TEST(WakeLockStateRecordTest, ReleaseRejectsPromise) {
- MockWakeLockService wake_lock_service;
- WakeLockTestingContext context(&wake_lock_service);
- auto* state_record = MakeStateRecord(context, WakeLockType::kScreen);
-
- MockWakeLock& screen_lock =
- wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-
- auto* resolver =
- MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
- ScriptPromise promise = resolver->Promise();
-
- EXPECT_EQ(v8::Promise::kPending,
- ScriptPromiseUtils::GetPromiseState(promise));
+ EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
- state_record->ReleaseWakeLock(resolver);
- context.WaitForPromiseRejection(promise);
+ auto* sentinel1 =
+ ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(promise1);
+ EXPECT_TRUE(state_record->wake_lock_sentinels_.Contains(sentinel1));
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise));
- EXPECT_EQ(0U, state_record->active_locks_.size());
- EXPECT_FALSE(screen_lock.is_acquired());
+ state_record->UnregisterSentinel(sentinel1);
+ EXPECT_FALSE(state_record->wake_lock_sentinels_.Contains(sentinel1));
+ EXPECT_TRUE(state_record->wake_lock_.is_bound());
+ EXPECT_EQ(1U, state_record->wake_lock_sentinels_.size());
+ EXPECT_TRUE(screen_lock.is_acquired());
}
-TEST(WakeLockStateRecordTest, ClearEmptyActiveLocksList) {
+TEST(WakeLockStateRecordTest, ClearEmptyWakeLockSentinelList) {
MockWakeLockService wake_lock_service;
WakeLockTestingContext context(&wake_lock_service);
auto* state_record = MakeStateRecord(context, WakeLockType::kSystem);
@@ -223,26 +160,15 @@ TEST(WakeLockStateRecordTest, ClearWakeLocks) {
state_record->AcquireWakeLock(resolver1);
state_record->AcquireWakeLock(resolver2);
system_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(promise1);
+ context.WaitForPromiseFulfillment(promise2);
+
+ EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
state_record->ClearWakeLocks();
- context.WaitForPromiseRejection(promise1);
- context.WaitForPromiseRejection(promise2);
system_lock.WaitForCancelation();
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise1));
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise2));
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
- dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise2);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
-
- EXPECT_EQ(0U, state_record->active_locks_.size());
+ EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
EXPECT_FALSE(system_lock.is_acquired());
}
@@ -264,25 +190,17 @@ TEST(WakeLockStateRecordTest, WakeLockConnectionError) {
state_record->AcquireWakeLock(resolver1);
state_record->AcquireWakeLock(resolver2);
system_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(promise1);
+ context.WaitForPromiseFulfillment(promise2);
+ EXPECT_EQ(2U, state_record->wake_lock_sentinels_.size());
+
+ // Unbind and wait for the disconnection to reach |wake_lock_|'s
+ // disconnection handler.
system_lock.Unbind();
- context.WaitForPromiseRejection(promise1);
- context.WaitForPromiseRejection(promise2);
-
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise1));
- EXPECT_EQ(v8::Promise::kRejected,
- ScriptPromiseUtils::GetPromiseState(promise2));
- DOMException* dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise1);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
- dom_exception =
- ScriptPromiseUtils::GetPromiseResolutionAsDOMException(promise2);
- ASSERT_NE(nullptr, dom_exception);
- EXPECT_EQ("AbortError", dom_exception->name());
-
- EXPECT_EQ(0U, state_record->active_locks_.size());
+ state_record->wake_lock_.FlushForTesting();
+
+ EXPECT_EQ(0U, state_record->wake_lock_sentinels_.size());
EXPECT_FALSE(state_record->wake_lock_);
EXPECT_FALSE(system_lock.is_acquired());
}
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc
new file mode 100644
index 00000000000..049f2e99b89
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/wake_lock_test.cc
@@ -0,0 +1,212 @@
+// 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/wake_lock/wake_lock.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+TEST(WakeLockTest, RequestWakeLockGranted) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+
+ auto* screen_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise screen_promise = screen_resolver->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+
+ MockWakeLock& screen_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+ MockPermissionService& permission_service = context.GetPermissionService();
+
+ permission_service.WaitForPermissionRequest(WakeLockType::kScreen);
+ screen_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(screen_promise);
+
+ EXPECT_NE(nullptr, ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
+ screen_promise));
+ EXPECT_TRUE(screen_lock.is_acquired());
+}
+
+TEST(WakeLockTest, RequestWakeLockDenied) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kSystem, mojom::blink::PermissionStatus::DENIED);
+
+ auto* system_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise system_promise = system_resolver->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+
+ MockWakeLock& system_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+ MockPermissionService& permission_service = context.GetPermissionService();
+
+ permission_service.WaitForPermissionRequest(WakeLockType::kSystem);
+ context.WaitForPromiseRejection(system_promise);
+
+ EXPECT_EQ(v8::Promise::kRejected,
+ ScriptPromiseUtils::GetPromiseState(system_promise));
+ EXPECT_FALSE(system_lock.is_acquired());
+
+ // System locks are not allowed by default, so the promise should have been
+ // rejected with a NotAllowedError DOMException.
+ DOMException* dom_exception =
+ ScriptPromiseUtils::GetPromiseResolutionAsDOMException(system_promise);
+ ASSERT_NE(dom_exception, nullptr);
+ EXPECT_EQ("NotAllowedError", dom_exception->name());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-full-activity
+TEST(WakeLockTest, LossOfDocumentActivity) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ MockWakeLock& screen_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+ MockWakeLock& system_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+ // First, acquire a handful of locks of different types.
+ auto* screen_resolver1 =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ screen_resolver1->Promise();
+ auto* screen_resolver2 =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ screen_resolver2->Promise();
+ auto* system_resolver1 =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ system_resolver1->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver1);
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver2);
+ screen_lock.WaitForRequest();
+ wake_lock->DoRequest(WakeLockType::kSystem, system_resolver1);
+ system_lock.WaitForRequest();
+
+ // Now shut down our Document and make sure all [[ActiveLocks]] slots have
+ // been cleared. We cannot check that the promises have been rejected because
+ // ScriptPromiseResolver::Reject() will bail out if we no longer have a valid
+ // execution context.
+ context.GetDocument()->Shutdown();
+ screen_lock.WaitForCancelation();
+ system_lock.WaitForCancelation();
+
+ EXPECT_FALSE(screen_lock.is_acquired());
+ EXPECT_FALSE(system_lock.is_acquired());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+TEST(WakeLockTest, PageVisibilityHidden) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+ MockWakeLock& screen_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+ auto* screen_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise screen_promise = screen_resolver->Promise();
+
+ MockWakeLock& system_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+ auto* system_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise system_promise = system_resolver->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+ screen_lock.WaitForRequest();
+ wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+ system_lock.WaitForRequest();
+
+ context.WaitForPromiseFulfillment(screen_promise);
+ context.WaitForPromiseFulfillment(system_promise);
+
+ context.GetDocument()->GetPage()->SetIsHidden(true, false);
+
+ screen_lock.WaitForCancelation();
+
+ EXPECT_FALSE(screen_lock.is_acquired());
+ EXPECT_TRUE(system_lock.is_acquired());
+
+ context.GetDocument()->GetPage()->SetIsHidden(false, false);
+
+ auto* other_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise other_promise = other_resolver->Promise();
+ wake_lock->DoRequest(WakeLockType::kScreen, other_resolver);
+ screen_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(other_promise);
+ EXPECT_TRUE(screen_lock.is_acquired());
+}
+
+// https://w3c.github.io/wake-lock/#handling-document-loss-of-visibility
+TEST(WakeLockTest, PageVisibilityHiddenBeforeLockAcquisition) {
+ MockWakeLockService wake_lock_service;
+ WakeLockTestingContext context(&wake_lock_service);
+
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kScreen, mojom::blink::PermissionStatus::GRANTED);
+ context.GetPermissionService().SetPermissionResponse(
+ WakeLockType::kSystem, mojom::blink::PermissionStatus::GRANTED);
+
+ MockWakeLock& screen_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+ auto* screen_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise screen_promise = screen_resolver->Promise();
+
+ MockWakeLock& system_lock =
+ wake_lock_service.get_wake_lock(WakeLockType::kSystem);
+ auto* system_resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+ ScriptPromise system_promise = system_resolver->Promise();
+
+ auto* wake_lock = MakeGarbageCollected<WakeLock>(*context.GetDocument());
+ wake_lock->DoRequest(WakeLockType::kScreen, screen_resolver);
+ wake_lock->DoRequest(WakeLockType::kSystem, system_resolver);
+ context.GetDocument()->GetPage()->SetIsHidden(true, false);
+
+ context.WaitForPromiseRejection(screen_promise);
+ system_lock.WaitForRequest();
+ context.WaitForPromiseFulfillment(system_promise);
+
+ EXPECT_EQ(v8::Promise::kRejected,
+ ScriptPromiseUtils::GetPromiseState(screen_promise));
+ DOMException* dom_exception =
+ ScriptPromiseUtils::GetPromiseResolutionAsDOMException(screen_promise);
+ ASSERT_NE(dom_exception, nullptr);
+ EXPECT_EQ("NotAllowedError", dom_exception->name());
+
+ EXPECT_FALSE(screen_lock.is_acquired());
+ EXPECT_TRUE(system_lock.is_acquired());
+}
+
+} // namespace blink
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 35274834c92..804169849a8 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
@@ -10,9 +10,10 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_sentinel.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -247,18 +248,26 @@ void MockPermissionService::AddPermissionObserver(
WakeLockTestingContext::WakeLockTestingContext(
MockWakeLockService* mock_wake_lock_service) {
- service_manager::InterfaceProvider::TestApi test_api(
- GetDocument()->GetInterfaceProvider());
- test_api.SetBinderForName(
+ GetDocument()->GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::WakeLockService::Name_,
WTF::BindRepeating(&MockWakeLockService::BindRequest,
WTF::Unretained(mock_wake_lock_service)));
- test_api.SetBinderForName(
+ GetDocument()->GetBrowserInterfaceBroker().SetBinderForTesting(
mojom::blink::PermissionService::Name_,
WTF::BindRepeating(&MockPermissionService::BindRequest,
WTF::Unretained(&permission_service_)));
}
+WakeLockTestingContext::~WakeLockTestingContext() {
+ // Remove the testing binder to avoid crashes between tests caused by
+ // our mocks rebinding an already-bound Binding.
+ // See https://crbug.com/1010116 for more information.
+ GetDocument()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::WakeLockService::Name_, {});
+ GetDocument()->GetBrowserInterfaceBroker().SetBinderForTesting(
+ mojom::blink::PermissionService::Name_, {});
+}
+
Document* WakeLockTestingContext::GetDocument() {
return &testing_scope_.GetDocument();
}
@@ -309,25 +318,16 @@ v8::Promise::PromiseState ScriptPromiseUtils::GetPromiseState(
}
// static
-String ScriptPromiseUtils::GetPromiseResolutionAsString(
+DOMException* ScriptPromiseUtils::GetPromiseResolutionAsDOMException(
const ScriptPromise& promise) {
- auto v8_promise = promise.V8Value().As<v8::Promise>();
- if (v8_promise->State() == v8::Promise::kPending) {
- return g_empty_string;
- }
- ScriptValue promise_result(promise.GetScriptValue().GetScriptState(),
- v8_promise->Result());
- String value;
- if (!promise_result.ToString(value)) {
- return g_empty_string;
- }
- return value;
+ return V8DOMException::ToImplWithTypeCheck(
+ promise.GetIsolate(), promise.V8Value().As<v8::Promise>()->Result());
}
// static
-DOMException* ScriptPromiseUtils::GetPromiseResolutionAsDOMException(
+WakeLockSentinel* ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
const ScriptPromise& promise) {
- return V8DOMException::ToImplWithTypeCheck(
+ return V8WakeLockSentinel::ToImplWithTypeCheck(
promise.GetIsolate(), promise.V8Value().As<v8::Promise>()->Result());
}
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 03a76b5eea2..a2630eb8955 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
@@ -11,7 +11,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/device/public/mojom/wake_lock.mojom-blink.h"
+#include "services/device/public/mojom/wake_lock.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
@@ -22,7 +22,9 @@
namespace blink {
+class DOMException;
class Document;
+class WakeLockSentinel;
// Mock WakeLock implementation that tracks whether it's bound or acquired, and
// provides a few helper methods to synchronously wait for RequestWakeLock()
@@ -141,7 +143,7 @@ class MockPermissionService final : public mojom::blink::PermissionService {
// MockWakeLockService mock_service;
// WakeLockTestingContext context(&mock_service);
// mojo::Remote<mojom::blink::WakeLockService> service;
-// context.GetDocument()->GetInterfaceProvider()->GetInterface(
+// context.GetDocument()->GetBrowserInterfaceBroker().GetInterface(
// service.BindNewPipeAndPassReceiver());
// service->GetWakeLock(...); // Will call mock_service.GetWakeLock().
// }
@@ -150,6 +152,7 @@ class WakeLockTestingContext final {
public:
WakeLockTestingContext(MockWakeLockService* mock_wake_lock_service);
+ ~WakeLockTestingContext();
Document* GetDocument();
LocalFrame* Frame();
@@ -174,15 +177,16 @@ class ScriptPromiseUtils final {
static v8::Promise::PromiseState GetPromiseState(
const ScriptPromise& promise);
- // Shorthand for getting a String out of a ScriptPromise. This assumes the
- // promise has been resolved with a string. If anything wrong happens during
- // the conversion, an empty string is returned.
- static String GetPromiseResolutionAsString(const ScriptPromise&);
-
// Shorthand for getting a DOMException* out of a ScriptPromise. This assumes
// the promise has been resolved with a DOMException. If the conversion fails,
// nullptr is returned.
static DOMException* GetPromiseResolutionAsDOMException(const ScriptPromise&);
+
+ // Shorthand for getting a WakeLockSentinel* out of a ScriptPromise. This
+ // assumes the promise has been resolved with a WakeLockSentinel. If the
+ // conversion fails, nullptr is returned.
+ static WakeLockSentinel* GetPromiseResolutionAsWakeLockSentinel(
+ const ScriptPromise&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc
new file mode 100644
index 00000000000..094a3baedb1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.cc
@@ -0,0 +1,57 @@
+// 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/wake_lock/worker_navigator_wake_lock.h"
+
+#include "third_party/blink/renderer/core/workers/worker_navigator.h"
+#include "third_party/blink/renderer/modules/wake_lock/wake_lock.h"
+
+namespace blink {
+
+WorkerNavigatorWakeLock::WorkerNavigatorWakeLock(WorkerNavigator& navigator)
+ : Supplement<WorkerNavigator>(navigator) {}
+
+// static
+const char WorkerNavigatorWakeLock::kSupplementName[] =
+ "WorkerNavigatorWakeLock";
+
+// static
+WorkerNavigatorWakeLock& WorkerNavigatorWakeLock::From(
+ WorkerNavigator& navigator) {
+ WorkerNavigatorWakeLock* supplement =
+ Supplement<WorkerNavigator>::From<WorkerNavigatorWakeLock>(navigator);
+ if (!supplement) {
+ supplement = MakeGarbageCollected<WorkerNavigatorWakeLock>(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ return *supplement;
+}
+
+// static
+WakeLock* WorkerNavigatorWakeLock::wakeLock(ScriptState* script_state,
+ WorkerNavigator& navigator) {
+ return WorkerNavigatorWakeLock::From(navigator).GetWakeLock(script_state);
+}
+
+WakeLock* WorkerNavigatorWakeLock::GetWakeLock(ScriptState* script_state) {
+ if (!wake_lock_) {
+ auto* execution_context = ExecutionContext::From(script_state);
+ DCHECK(execution_context);
+
+ // TODO(https://crbug.com/839117): Remove this check once the Exposed
+ // attribute is fixed to only expose this property in dedicated workers.
+ if (execution_context->IsDedicatedWorkerGlobalScope()) {
+ wake_lock_ = MakeGarbageCollected<WakeLock>(
+ *To<DedicatedWorkerGlobalScope>(execution_context));
+ }
+ }
+ return wake_lock_;
+}
+
+void WorkerNavigatorWakeLock::Trace(blink::Visitor* visitor) {
+ visitor->Trace(wake_lock_);
+ Supplement<WorkerNavigator>::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h
new file mode 100644
index 00000000000..bc01e30e4a5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.h
@@ -0,0 +1,41 @@
+// 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_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class ScriptState;
+class WakeLock;
+class WorkerNavigator;
+
+class WorkerNavigatorWakeLock final
+ : public GarbageCollected<WorkerNavigatorWakeLock>,
+ public Supplement<WorkerNavigator> {
+ USING_GARBAGE_COLLECTED_MIXIN(WorkerNavigatorWakeLock);
+
+ public:
+ static const char kSupplementName[];
+
+ static WorkerNavigatorWakeLock& From(WorkerNavigator&);
+
+ static WakeLock* wakeLock(ScriptState*, WorkerNavigator&);
+
+ explicit WorkerNavigatorWakeLock(WorkerNavigator&);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ WakeLock* GetWakeLock(ScriptState*);
+
+ Member<WakeLock> wake_lock_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WORKER_NAVIGATOR_WAKE_LOCK_H_
diff --git a/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl
new file mode 100644
index 00000000000..ddcc2c2d006
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/wake_lock/worker_navigator_wake_lock.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ ImplementedAs=WorkerNavigatorWakeLock,
+ RuntimeEnabled=WakeLock,
+ SecureContext
+] partial interface WorkerNavigator {
+ [CallWith=ScriptState, SameObject] readonly attribute WakeLock wakeLock;
+};
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 839d8c83973..bd76a6a7dec 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -155,6 +155,20 @@ AudioContext::AudioContext(Document& document,
}
Initialize();
+
+ // Compute the base latency now and cache the value since it doesn't change
+ // once the context is constructed. We need the destination to be initialized
+ // so we have to compute it here.
+ //
+ // TODO(hongchan): Due to the incompatible constructor between
+ // AudioDestinationNode and RealtimeAudioDestinationNode, casting directly
+ // from |destination()| is impossible. This is a temporary workaround until
+ // the refactoring is completed.
+ RealtimeAudioDestinationHandler& destination_handler =
+ static_cast<RealtimeAudioDestinationHandler&>(
+ destination()->GetAudioDestinationHandler());
+ base_latency_ = destination_handler.GetFramesPerBuffer() /
+ static_cast<double>(sampleRate());
}
void AudioContext::Uninitialize() {
@@ -359,15 +373,7 @@ double AudioContext::baseLatency() const {
DCHECK(IsMainThread());
DCHECK(destination());
- // TODO(hongchan): Due to the incompatible constructor between
- // AudioDestinationNode and RealtimeAudioDestinationNode, casting directly
- // from |destination()| is impossible. This is a temporary workaround until
- // the refactoring is completed.
- RealtimeAudioDestinationHandler& destination_handler =
- static_cast<RealtimeAudioDestinationHandler&>(
- destination()->GetAudioDestinationHandler());
- return destination_handler.GetFramesPerBuffer() /
- static_cast<double>(sampleRate());
+ return base_latency_;
}
MediaElementAudioSourceNode* AudioContext::createMediaElementSource(
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
index e0d4cf1aef2..013eee56725 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -176,6 +176,9 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext {
// Represents whether a context is suspended by explicit |context.suspend()|.
bool suspended_by_user_ = false;
+ // baseLatency for this context
+ double base_latency_ = 0;
+
// AudioContextManager for reporting audibility.
mojo::Remote<mojom::blink::AudioContextManager> audio_context_manager_;
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 168593bce8c..15496ffdc8b 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -45,13 +45,13 @@ namespace blink {
AudioHandler::AudioHandler(NodeType node_type,
AudioNode& node,
float sample_rate)
- : is_initialized_(false),
+ : last_processing_time_(-1),
+ last_non_silent_time_(0),
+ is_initialized_(false),
node_type_(kNodeTypeUnknown),
node_(&node),
context_(node.context()),
deferred_task_handler_(&context_->GetDeferredTaskHandler()),
- last_processing_time_(-1),
- last_non_silent_time_(0),
connection_ref_count_(0),
is_disabled_(false),
channel_count_(2) {
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 f9c9b0688f4..5f716c83d44 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
@@ -180,7 +180,7 @@ class MODULES_EXPORT AudioHandler : public ThreadSafeRefCounted<AudioHandler> {
// will only process once per rendering time quantum even if it's called
// repeatedly. This handles the case of "fanout" where an output is connected
// to multiple AudioNode inputs. Called from context's audio thread.
- void ProcessIfNecessary(uint32_t frames_to_process);
+ virtual void ProcessIfNecessary(uint32_t frames_to_process);
// Called when a new connection has been made to one of our inputs or the
// connection number of channels has changed. This potentially gives us
@@ -267,6 +267,14 @@ class MODULES_EXPORT AudioHandler : public ThreadSafeRefCounted<AudioHandler> {
// Force all inputs to take any channel interpretation changes into account.
void UpdateChannelsForInputs();
+ // The last time (context time) that his handler ran its Process() method.
+ // For each render quantum, we only want to process just once to handle fanout
+ // of this handler.
+ double last_processing_time_;
+
+ // The last time (context time) when this node did not have silent inputs.
+ double last_non_silent_time_;
+
private:
void SetNodeType(NodeType);
@@ -289,9 +297,6 @@ class MODULES_EXPORT AudioHandler : public ThreadSafeRefCounted<AudioHandler> {
Vector<std::unique_ptr<AudioNodeInput>> inputs_;
Vector<std::unique_ptr<AudioNodeOutput>> outputs_;
- double last_processing_time_;
- double last_non_silent_time_;
-
int connection_ref_count_;
bool is_disabled_;
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 ae1686cc677..72e7eb137d9 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
@@ -153,7 +153,7 @@ AudioWorkletProcessor* AudioWorkletGlobalScope::CreateProcessor(
std::make_unique<ProcessorCreationParams>(
name, std::move(message_port_channel)));
- ScriptValue options(script_state,
+ ScriptValue options(isolate,
ToV8(node_options->Deserialize(isolate), script_state));
ScriptValue instance;
@@ -310,9 +310,9 @@ bool AudioWorkletGlobalScope::Process(
// wrapper of v8::Object instance.
ScriptValue result;
if (!definition->ProcessFunction()
- ->Invoke(processor, ScriptValue(script_state, inputs),
- ScriptValue(script_state, outputs),
- ScriptValue(script_state, param_values))
+ ->Invoke(processor, ScriptValue(isolate, inputs),
+ ScriptValue(isolate, outputs),
+ ScriptValue(isolate, param_values))
.To(&result)) {
// process() method call failed for some reason or an exception was thrown
// by the user supplied code. Disable the processor to exclude it from the
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 d720ccf90ec..2607d5b4ec7 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
@@ -41,8 +41,12 @@ void AudioWorkletObjectProxy::DidEvaluateModuleScript(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::kInternalMedia),
+ *GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalLoading),
FROM_HERE,
CrossThreadBindOnce(
&AudioWorkletMessagingProxy::SynchronizeWorkletProcessorInfoList,
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 c5fa9ee8346..4ff7ca44d3a 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
@@ -25,7 +25,7 @@ class V8BlinkAudioWorkletProcessorConstructor;
// This is constructed and destroyed on a worker thread, and all methods also
// must be called on the worker thread.
class MODULES_EXPORT AudioWorkletProcessorDefinition final
- : public GarbageCollectedFinalized<AudioWorkletProcessorDefinition>,
+ : public GarbageCollected<AudioWorkletProcessorDefinition>,
public NameClient {
public:
static AudioWorkletProcessorDefinition* Create(
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 34adef56ced..a9ecf56688a 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
@@ -151,6 +151,8 @@ void BaseAudioContext::Clear() {
void BaseAudioContext::Uninitialize() {
DCHECK(IsMainThread());
+ MutexLocker locker(GetTearDownMutex());
+
if (!IsDestinationInitialized())
return;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
index d5aadf7e58e..d6e4fe5e25f 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -328,6 +328,8 @@ class MODULES_EXPORT BaseAudioContext
void ReportDidCreate() final;
void ReportWillBeDestroyed() final;
+ Mutex& GetTearDownMutex() const { return tear_down_mutex_; }
+
protected:
enum ContextType { kRealtimeContext, kOfflineContext };
@@ -429,6 +431,12 @@ class MODULES_EXPORT BaseAudioContext
// This cannot be nullptr once it is assigned from AudioWorkletThread until
// the BaseAudioContext goes away.
WorkerThread* audio_worklet_thread_ = nullptr;
+
+ // Due to the multi-threading architecture of WebAudio, it is possible that
+ // object allocated by the main thread still can be accessed by the audio
+ // rendering thread while this context is torn down (GCed) by
+ // |Uninitialize()|.
+ mutable Mutex tear_down_mutex_;
};
} // namespace blink
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 2dc8395143d..ce19fe6675c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/modules/webaudio/convolver_options.h"
#include "third_party/blink/renderer/platform/audio/reverb.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
// Note about empirical tuning:
// The maximum FFT size affects reverb performance and accuracy.
@@ -136,6 +137,12 @@ void ConvolverHandler::SetBuffer(AudioBuffer* buffer,
return;
}
+ {
+ // Get some statistics on the size of the impulse response.
+ UMA_HISTOGRAM_LONG_TIMES("WebAudio.ConvolverNode.ImpulseResponseLength",
+ base::TimeDelta::FromSecondsD(buffer->duration()));
+ }
+
// Wrap the AudioBuffer by an AudioBus. It's an efficient pointer set and not
// a memcpy(). This memory is simply used in the Reverb constructor and no
// reference to it is kept for later use in that class.
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
index 69a58ba8816..b0cc2b94ef4 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -293,24 +293,32 @@ bool OfflineAudioDestinationHandler::RenderIfNotSuspended(
return true;
}
- DCHECK_GE(NumberOfInputs(), 1u);
-
- // This will cause the node(s) connected to us to process, which in turn will
- // pull on their input(s), all the way backwards through the rendering graph.
- AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
+ {
+ MutexTryLocker try_locker(Context()->GetTearDownMutex());
+ if (try_locker.Locked()) {
+ DCHECK_GE(NumberOfInputs(), 1u);
+
+ // This will cause the node(s) connected to us to process, which in turn
+ // will pull on their input(s), all the way backwards through the
+ // rendering graph.
+ AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
+
+ if (!rendered_bus) {
+ destination_bus->Zero();
+ } else if (rendered_bus != destination_bus) {
+ // in-place processing was not possible - so copy
+ destination_bus->CopyFrom(*rendered_bus);
+ }
+ } else {
+ destination_bus->Zero();
+ }
- if (!rendered_bus) {
- destination_bus->Zero();
- } else if (rendered_bus != destination_bus) {
- // in-place processing was not possible - so copy
- destination_bus->CopyFrom(*rendered_bus);
+ // Process nodes which need a little extra help because they are not
+ // connected to anything, but still need to process.
+ Context()->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
+ number_of_frames);
}
- // Process nodes which need a little extra help because they are not connected
- // to anything, but still need to process.
- Context()->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
- number_of_frames);
-
// Let the context take care of any business at the end of each render
// quantum.
Context()->HandlePostRenderTasks();
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 c0ac6bd2294..da282b553eb 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
@@ -37,8 +37,6 @@
namespace blink {
-using namespace vector_math;
-
OscillatorHandler::OscillatorHandler(AudioNode& node,
float sample_rate,
const String& oscillator_type,
@@ -218,15 +216,16 @@ bool OscillatorHandler::CalculateSampleAccuratePhaseIncrements(
// Convert from cents to rate scalar.
float k = 1.0 / 1200;
- Vsmul(detune_values, 1, &k, detune_values, 1, frames_to_process);
+ vector_math::Vsmul(detune_values, 1, &k, detune_values, 1,
+ frames_to_process);
for (unsigned i = 0; i < frames_to_process; ++i) {
detune_values[i] = std::exp2(detune_values[i]);
}
if (has_frequency_changes) {
// Multiply frequencies by detune scalings.
- Vmul(detune_values, 1, phase_increments, 1, phase_increments, 1,
- frames_to_process);
+ vector_math::Vmul(detune_values, 1, phase_increments, 1, phase_increments,
+ 1, frames_to_process);
}
} else {
// Handle ordinary parameter changes if there are no scheduled
@@ -240,8 +239,8 @@ bool OscillatorHandler::CalculateSampleAccuratePhaseIncrements(
ClampFrequency(phase_increments, frames_to_process,
Context()->sampleRate() / 2);
// Convert from frequency to wavetable increment.
- Vsmul(phase_increments, 1, &final_scale, phase_increments, 1,
- frames_to_process);
+ vector_math::Vsmul(phase_increments, 1, &final_scale, phase_increments, 1,
+ frames_to_process);
}
return has_sample_accurate_values;
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 eeb96c0e0c1..5eb9ad6251c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
@@ -99,6 +99,69 @@ PannerHandler::~PannerHandler() {
Uninitialize();
}
+// PannerNode needs a custom ProcessIfNecessary to get the process lock when
+// computing PropagatesSilence() to protect processing from changes happening to
+// the panning model. This is very similar to AudioNode::ProcessIfNecessary.
+void PannerHandler::ProcessIfNecessary(uint32_t frames_to_process) {
+ DCHECK(Context()->IsAudioThread());
+
+ if (!IsInitialized())
+ return;
+
+ // Ensure that we only process once per rendering quantum.
+ // This handles the "fanout" problem where an output is connected to multiple
+ // inputs. The first time we're called during this time slice we process, but
+ // after that we don't want to re-process, instead our output(s) will already
+ // have the results cached in their bus;
+ double current_time = Context()->currentTime();
+ if (last_processing_time_ != current_time) {
+ // important to first update this time because of feedback loops in the
+ // rendering graph.
+ last_processing_time_ = current_time;
+
+ PullInputs(frames_to_process);
+
+ bool silent_inputs = InputsAreSilent();
+
+ {
+ // Need to protect calls to PropagetesSilence (and Process) because the
+ // main threda may be changing the panning model that modifies the
+ // TailTime and LatencyTime methods called by PropagatesSilence.
+ MutexTryLocker try_locker(process_lock_);
+ if (try_locker.Locked()) {
+ if (silent_inputs && PropagatesSilence()) {
+ SilenceOutputs();
+ // AudioParams still need to be processed so that the value can be
+ // updated if there are automations or so that the upstream nodes get
+ // pulled if any are connected to the AudioParam.
+ ProcessOnlyAudioParams(frames_to_process);
+ } else {
+ // Unsilence the outputs first because the processing of the node may
+ // cause the outputs to go silent and we want to propagate that hint
+ // to the downstream nodes. (For example, a Gain node with a gain of
+ // 0 will want to silence its output.)
+ UnsilenceOutputs();
+ Process(frames_to_process);
+ }
+ } else {
+ // We must be in the middle of changing the properties of the panner.
+ // Just output silence.
+ AudioBus* destination = Output(0).Bus();
+ destination->Zero();
+ }
+ }
+
+ if (!silent_inputs) {
+ // Update |last_non_silent_time| AFTER processing this block.
+ // Doing it before causes |PropagateSilence()| to be one render
+ // quantum longer than necessary.
+ last_non_silent_time_ =
+ (Context()->CurrentSampleFrame() + frames_to_process) /
+ static_cast<double>(Context()->sampleRate());
+ }
+ }
+}
+
void PannerHandler::Process(uint32_t frames_to_process) {
AudioBus* destination = Output(0).Bus();
@@ -114,10 +177,9 @@ void PannerHandler::Process(uint32_t frames_to_process) {
}
// The audio thread can't block on this lock, so we call tryLock() instead.
- MutexTryLocker try_locker(process_lock_);
MutexTryLocker try_listener_locker(Listener()->ListenerLock());
- if (try_locker.Locked() && try_listener_locker.Locked()) {
+ if (try_listener_locker.Locked()) {
if (!Context()->HasRealtimeConstraint() &&
panning_model_ == Panner::kPanningModelHRTF) {
// For an OfflineAudioContext, we need to make sure the HRTFDatabase
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.h b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.h
index 1b9cbbc32cb..8fe0ec50822 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.h
@@ -71,6 +71,7 @@ class PannerHandler final : public AudioHandler {
~PannerHandler() override;
// AudioHandler
+ void ProcessIfNecessary(uint32_t frames_to_process) override;
void Process(uint32_t frames_to_process) override;
void ProcessSampleAccurateValues(AudioBus* destination,
const AudioBus* source,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc b/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
index 78dafb2d847..b8a64742a0a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
@@ -49,8 +49,6 @@ const unsigned kMaxPeriodicWaveSize = 16384;
const float kCentsPerRange = 1200 / kNumberOfOctaveBands;
-using namespace vector_math;
-
PeriodicWave* PeriodicWave::Create(BaseAudioContext& context,
const Vector<float>& real,
const Vector<float>& imag,
@@ -251,9 +249,9 @@ void PeriodicWave::CreateBandLimitedTables(const float* real_data,
// arrays. Need to scale the data by fftSize to remove the scaling that the
// inverse IFFT would do.
float scale = fft_size;
- Vsmul(real_data, 1, &scale, real_p, 1, number_of_components);
+ vector_math::Vsmul(real_data, 1, &scale, real_p, 1, number_of_components);
scale = -scale;
- Vsmul(imag_data, 1, &scale, imag_p, 1, number_of_components);
+ vector_math::Vsmul(imag_data, 1, &scale, imag_p, 1, number_of_components);
// Find the starting bin where we should start culling. We need to clear
// out the highest frequencies to band-limit the waveform.
@@ -288,7 +286,7 @@ void PeriodicWave::CreateBandLimitedTables(const float* real_data,
if (!disable_normalization) {
if (!range_index) {
float max_value;
- Vmaxmgv(data, 1, &max_value, fft_size);
+ vector_math::Vmaxmgv(data, 1, &max_value, fft_size);
if (max_value)
normalization_scale = 1.0f / max_value;
@@ -296,7 +294,7 @@ void PeriodicWave::CreateBandLimitedTables(const float* real_data,
}
// Apply normalization scale.
- Vsmul(data, 1, &normalization_scale, data, 1, fft_size);
+ vector_math::Vsmul(data, 1, &normalization_scale, data, 1, fft_size);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
index 9f7119bb6cd..58caf2b93a0 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.cc
@@ -198,28 +198,33 @@ void RealtimeAudioDestinationHandler::Render(
// Only pull on the audio graph if we have not stopped the destination. It
// takes time for the destination to stop, but we want to stop pulling before
// the destination has actually stopped.
- if (IsPullingAudioGraphAllowed()) {
- // Renders the graph by pulling all the input(s) to this node. This will in
- // turn pull on their input(s), all the way backwards through the graph.
- AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
-
- DCHECK(rendered_bus);
- if (!rendered_bus) {
- // AudioNodeInput might be in the middle of destruction. Then the internal
- // summing bus will return as nullptr. Then zero out the output.
+ {
+ MutexTryLocker try_locker(context->GetTearDownMutex());
+ if (try_locker.Locked() && IsPullingAudioGraphAllowed()) {
+ // Renders the graph by pulling all the inputs to this node. This will
+ // in turn pull on their inputs, all the way backwards through the graph.
+ AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
+
+ DCHECK(rendered_bus);
+ if (!rendered_bus) {
+ // AudioNodeInput might be in the middle of destruction. Then the
+ // internal summing bus will return as nullptr. Then zero out the
+ // output.
+ destination_bus->Zero();
+ } else if (rendered_bus != destination_bus) {
+ // In-place processing was not possible. Copy the rendererd result to
+ // the given |destination_bus| buffer.
+ destination_bus->CopyFrom(*rendered_bus);
+ }
+ } else {
destination_bus->Zero();
- } else if (rendered_bus != destination_bus) {
- // In-place processing was not possible. Copy the rendererd result to the
- // given |destination_bus| buffer.
- destination_bus->CopyFrom(*rendered_bus);
}
- } else {
- destination_bus->Zero();
- }
- // Processes "automatic" nodes that are not connected to anything. This can
- // be done after copying because it does not affect the rendered result.
- context->GetDeferredTaskHandler().ProcessAutomaticPullNodes(number_of_frames);
+ // Processes "automatic" nodes that are not connected to anything. This can
+ // be done after copying because it does not affect the rendered result.
+ context->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
+ number_of_frames);
+ }
context->HandlePostRenderTasks();
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 f81fa99e6a3..540b62de4ab 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
@@ -125,12 +125,11 @@ NotShared<DOMFloat32Array> WaveShaperNode::curve() {
return NotShared<DOMFloat32Array>(nullptr);
unsigned size = curve->size();
- scoped_refptr<WTF::Float32Array> new_curve = WTF::Float32Array::Create(size);
- memcpy(new_curve->Data(), curve->data(), sizeof(float) * size);
+ NotShared<DOMFloat32Array> result(DOMFloat32Array::Create(size));
+ memcpy(result.View()->Data(), curve->data(), sizeof(float) * size);
- return NotShared<DOMFloat32Array>(
- DOMFloat32Array::Create(std::move(new_curve)));
+ return result;
}
void WaveShaperNode::setOversample(const String& type) {
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database_context.h b/chromium/third_party/blink/renderer/modules/webdatabase/database_context.h
index c561e1cfd54..cb56a462f5d 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_context.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_context.h
@@ -38,7 +38,7 @@ class DatabaseThread;
class ExecutionContext;
class SecurityOrigin;
-class DatabaseContext final : public GarbageCollectedFinalized<DatabaseContext>,
+class DatabaseContext final : public GarbageCollected<DatabaseContext>,
public ContextLifecycleObserver {
USING_GARBAGE_COLLECTED_MIXIN(DatabaseContext);
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database_thread.h b/chromium/third_party/blink/renderer/modules/webdatabase/database_thread.h
index 9eeae61fa89..3f5faf80f52 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_thread.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_thread.h
@@ -43,7 +43,7 @@ class DatabaseTask;
class SQLTransactionClient;
class SQLTransactionCoordinator;
-class DatabaseThread : public GarbageCollectedFinalized<DatabaseThread> {
+class DatabaseThread final : public GarbageCollected<DatabaseThread> {
public:
DatabaseThread();
~DatabaseThread();
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h b/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h
index dadec74db1c..19490afaa05 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_resource.h
@@ -39,8 +39,8 @@
namespace blink {
class Database;
-class InspectorDatabaseResource
- : public GarbageCollectedFinalized<InspectorDatabaseResource> {
+class InspectorDatabaseResource final
+ : public GarbageCollected<InspectorDatabaseResource> {
public:
InspectorDatabaseResource(Database*,
const String& domain,
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement.h
index e6d736ad69c..dfe45739142 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement.h
@@ -45,8 +45,7 @@ class SQLTransaction;
class SQLStatement final : public GarbageCollected<SQLStatement> {
public:
- class OnSuccessCallback
- : public GarbageCollectedFinalized<OnSuccessCallback> {
+ class OnSuccessCallback : public GarbageCollected<OnSuccessCallback> {
public:
virtual ~OnSuccessCallback() = default;
virtual void Trace(blink::Visitor*) {}
@@ -73,7 +72,7 @@ class SQLStatement final : public GarbageCollected<SQLStatement> {
Member<V8SQLStatementCallback> callback_;
};
- class OnErrorCallback : public GarbageCollectedFinalized<OnErrorCallback> {
+ class OnErrorCallback : public GarbageCollected<OnErrorCallback> {
public:
virtual ~OnErrorCallback() = default;
virtual void Trace(blink::Visitor*) {}
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h
index cc1756d369e..788633e4a14 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_statement_backend.h
@@ -42,8 +42,7 @@ class SQLErrorData;
class SQLResultSet;
class SQLStatement;
-class SQLStatementBackend final
- : public GarbageCollectedFinalized<SQLStatementBackend> {
+class SQLStatementBackend final : public GarbageCollected<SQLStatementBackend> {
public:
SQLStatementBackend(SQLStatement*,
const String& statement,
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 d8d85d19cb6..776d50e2724 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -347,7 +347,7 @@ void SQLTransaction::executeSql(ScriptState* script_state,
void SQLTransaction::executeSql(
ScriptState* script_state,
const String& sql_statement,
- const base::Optional<Vector<ScriptValue>>& arguments,
+ const base::Optional<HeapVector<ScriptValue>>& arguments,
V8SQLStatementCallback* callback,
V8SQLStatementErrorCallback* callback_error,
ExceptionState& exception_state) {
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
index 916d3f16d22..74d99c733fe 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
@@ -56,8 +56,7 @@ class SQLTransaction final : public ScriptWrappable,
DEFINE_WRAPPERTYPEINFO();
public:
- class OnProcessCallback
- : public GarbageCollectedFinalized<OnProcessCallback> {
+ class OnProcessCallback : public GarbageCollected<OnProcessCallback> {
public:
virtual ~OnProcessCallback() = default;
virtual void Trace(blink::Visitor*) {}
@@ -84,8 +83,7 @@ class SQLTransaction final : public ScriptWrappable,
Member<V8SQLTransactionCallback> callback_;
};
- class OnSuccessCallback
- : public GarbageCollectedFinalized<OnSuccessCallback> {
+ class OnSuccessCallback : public GarbageCollected<OnSuccessCallback> {
public:
virtual ~OnSuccessCallback() = default;
virtual void Trace(blink::Visitor*) {}
@@ -111,7 +109,7 @@ class SQLTransaction final : public ScriptWrappable,
Member<V8VoidCallback> callback_;
};
- class OnErrorCallback : public GarbageCollectedFinalized<OnErrorCallback> {
+ class OnErrorCallback : public GarbageCollected<OnErrorCallback> {
public:
virtual ~OnErrorCallback() = default;
virtual void Trace(blink::Visitor*) {}
@@ -161,7 +159,7 @@ class SQLTransaction final : public ScriptWrappable,
void executeSql(ScriptState*, const String& sql_statement, ExceptionState&);
void executeSql(ScriptState*,
const String& sql_statement,
- const base::Optional<Vector<ScriptValue>>& arguments,
+ const base::Optional<HeapVector<ScriptValue>>& arguments,
V8SQLStatementCallback*,
V8SQLStatementErrorCallback*,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
index 3525a917caf..8c82b2eeb08 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
@@ -47,8 +47,7 @@ class SQLTransaction;
class SQLTransactionBackend;
class SQLValue;
-class SQLTransactionWrapper
- : public GarbageCollectedFinalized<SQLTransactionWrapper> {
+class SQLTransactionWrapper : public GarbageCollected<SQLTransactionWrapper> {
public:
virtual ~SQLTransactionWrapper() = default;
virtual void Trace(blink::Visitor* visitor) {}
@@ -59,7 +58,7 @@ class SQLTransactionWrapper
};
class SQLTransactionBackend final
- : public GarbageCollectedFinalized<SQLTransactionBackend>,
+ : public GarbageCollected<SQLTransactionBackend>,
public SQLTransactionStateMachine<SQLTransactionBackend> {
public:
SQLTransactionBackend(Database*,
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h
index 35e5be3d4f7..593bc5b3293 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_coordinator.h
@@ -44,8 +44,8 @@ namespace blink {
class SQLTransactionBackend;
-class SQLTransactionCoordinator
- : public GarbageCollectedFinalized<SQLTransactionCoordinator> {
+class SQLTransactionCoordinator final
+ : public GarbageCollected<SQLTransactionCoordinator> {
public:
SQLTransactionCoordinator();
void Trace(blink::Visitor*);
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.cc b/chromium/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.cc
index 2762ed835db..afc4438a382 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sqlite/sandboxed_vfs_file.cc
@@ -146,6 +146,7 @@ SandboxedVfsFile* SandboxedVfsFile::FromSqliteFile(sqlite3_file* sqlite_file) {
int SandboxedVfsFile::Close() {
file_.Close();
+ delete this;
return SQLITE_OK;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.cc b/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.cc
index c671a2a7776..aa45e44a2ad 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query.cc
@@ -143,7 +143,7 @@ ScriptValue EXTDisjointTimerQuery::getQueryEXT(ScriptState* script_state,
GLenum pname) {
WebGLExtensionScopedContext scoped(this);
if (scoped.IsLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (pname == GL_QUERY_COUNTER_BITS_EXT) {
if (target == GL_TIMESTAMP_EXT || target == GL_TIME_ELAPSED_EXT) {
@@ -153,22 +153,22 @@ ScriptValue EXTDisjointTimerQuery::getQueryEXT(ScriptState* script_state,
}
scoped.Context()->SynthesizeGLError(GL_INVALID_ENUM, "getQuery",
"invalid target/pname combination");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (target == GL_TIME_ELAPSED_EXT && pname == GL_CURRENT_QUERY) {
return current_elapsed_query_
? WebGLAny(script_state, current_elapsed_query_)
- : ScriptValue::CreateNull(script_state);
+ : ScriptValue::CreateNull(script_state->GetIsolate());
}
if (target == GL_TIMESTAMP_EXT && pname == GL_CURRENT_QUERY) {
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
scoped.Context()->SynthesizeGLError(GL_INVALID_ENUM, "getQuery",
"invalid target/pname combination");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
ScriptValue EXTDisjointTimerQuery::getQueryObjectEXT(ScriptState* script_state,
@@ -176,15 +176,15 @@ ScriptValue EXTDisjointTimerQuery::getQueryObjectEXT(ScriptState* script_state,
GLenum pname) {
WebGLExtensionScopedContext scoped(this);
if (scoped.IsLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (!scoped.Context()->ValidateWebGLObject("getQueryObjectEXT", query))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (current_elapsed_query_ == query) {
scoped.Context()->SynthesizeGLError(
GL_INVALID_OPERATION, "getQueryObjectEXT", "query is currently active");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (pname) {
@@ -202,7 +202,7 @@ ScriptValue EXTDisjointTimerQuery::getQueryObjectEXT(ScriptState* script_state,
break;
}
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
void EXTDisjointTimerQuery::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
index 00e91fcb9b1..b196c45c175 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/webgl_any.h"
#include "third_party/blink/renderer/modules/webgl/webgl_program.h"
#include "third_party/blink/renderer/modules/webgl/webgl_uniform_location.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -69,21 +70,71 @@ void WebGL2ComputeRenderingContextBase::dispatchComputeIndirect(
ContextGL()->DispatchComputeIndirect(static_cast<GLintptr>(offset));
}
+void WebGL2ComputeRenderingContextBase::drawArraysIndirect(
+ GLenum mode,
+ int64_t offset) {
+ if (!ValidateValueFitNonNegInt32("drawArraysIndirect", "offset", offset))
+ return;
+
+ if (!ValidateDrawArrays("drawArraysIndirect"))
+ return;
+
+ if (!bound_vertex_array_object_->IsAllEnabledAttribBufferBound()) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "drawArraysIndirect",
+ "no buffer is bound to enabled attribute");
+ return;
+ }
+
+ ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
+ drawing_buffer_.get());
+ OnBeforeDrawCall();
+ ContextGL()->DrawArraysIndirect(
+ mode, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void WebGL2ComputeRenderingContextBase::drawElementsIndirect(
+ GLenum mode,
+ GLenum type,
+ int64_t offset) {
+ if (!ValidateValueFitNonNegInt32("drawElementsIndirect", "offset", offset))
+ return;
+
+ // The buffer currently bound to the (GL_)DRAW_INDIRECT_BUFFER binding might
+ // be unpopulated at this point, so the validation of element array buffer
+ // offset in it needs to be deferred. By feeding a dummy in-range offset value
+ // here, other validation logic for indexed drawing can be reused.
+ int64_t dummy_offset = 0;
+ if (!ValidateDrawElements("drawElementsIndirect", type, dummy_offset))
+ return;
+
+ if (!bound_vertex_array_object_->IsAllEnabledAttribBufferBound()) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "drawElementsIndirect",
+ "no buffer is bound to enabled attribute");
+ return;
+ }
+
+ ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
+ drawing_buffer_.get());
+ OnBeforeDrawCall();
+ ContextGL()->DrawElementsIndirect(
+ mode, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
ScriptValue WebGL2ComputeRenderingContextBase::getProgramInterfaceParameter(
ScriptState* script_state,
WebGLProgram* program,
GLenum program_interface,
GLenum pname) {
if (!ValidateWebGLProgramOrShader("getProgramInterfaceParameter", program))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (!ValidateProgramInterface(
"getProgramInterfaceParameter", program_interface))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (program_interface == GL_ATOMIC_COUNTER_BUFFER &&
pname == GL_MAX_NAME_LENGTH) {
SynthesizeGLError(GL_INVALID_OPERATION, "getProgramInterfaceParameter",
"atomic counter resources are not assigned name strings");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (program_interface != GL_ATOMIC_COUNTER_BUFFER &&
program_interface != GL_SHADER_STORAGE_BLOCK &&
@@ -92,7 +143,7 @@ ScriptValue WebGL2ComputeRenderingContextBase::getProgramInterfaceParameter(
SynthesizeGLError(
GL_INVALID_OPERATION, "getProgramInterfaceParameter",
"invalid parameter name for the specified program interface");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (pname) {
@@ -107,7 +158,7 @@ ScriptValue WebGL2ComputeRenderingContextBase::getProgramInterfaceParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getProgramInterfaceParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -164,7 +215,7 @@ String WebGL2ComputeRenderingContextBase::getProgramResourceName(
return String(name.get(), static_cast<uint32_t>(length));
}
-base::Optional<Vector<ScriptValue>>
+base::Optional<HeapVector<ScriptValue>>
WebGL2ComputeRenderingContextBase::getProgramResource(
ScriptState* script_state,
WebGLProgram* program,
@@ -229,7 +280,7 @@ WebGL2ComputeRenderingContextBase::getProgramResource(
// Interpret the returned values and construct the result array. The type of
// each array element is the natural type for the requested property.
- Vector<ScriptValue> result;
+ HeapVector<ScriptValue> result;
wtf_size_t auxiliary_param_index = 0;
wtf_size_t extended_param_index = auxiliary_params.size();
for (GLenum prop : props) {
@@ -346,7 +397,7 @@ ScriptValue WebGL2ComputeRenderingContextBase::getParameter(
ScriptState* script_state,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_SHADING_LANGUAGE_VERSION: {
return WebGLAny(
@@ -397,14 +448,14 @@ ScriptValue WebGL2ComputeRenderingContextBase::getIndexedParameter(
GLenum target,
GLuint index) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (target) {
case GL_ATOMIC_COUNTER_BUFFER_BINDING:
if (index >= bound_indexed_atomic_counter_buffers_.size()) {
SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter",
"index out of range");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
return WebGLAny(script_state,
bound_indexed_atomic_counter_buffers_[index].Get());
@@ -412,7 +463,7 @@ ScriptValue WebGL2ComputeRenderingContextBase::getIndexedParameter(
if (index >= bound_indexed_shader_storage_buffers_.size()) {
SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter",
"index out of range");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
return WebGLAny(script_state,
bound_indexed_shader_storage_buffers_[index].Get());
@@ -620,11 +671,12 @@ ScriptValue WebGL2ComputeRenderingContextBase::WrapLocation(
}
case GL_UNIFORM: {
if (location == -1)
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
DCHECK_GE(location, 0);
WebGLUniformLocation* uniform_location =
WebGLUniformLocation::Create(program, location);
- return ScriptValue(script_state, ToV8(uniform_location, script_state));
+ return ScriptValue(script_state->GetIsolate(),
+ ToV8(uniform_location, script_state));
}
default: {
return WebGLAny(script_state, location);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
index c120a67e5a6..0953f26e985 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -21,6 +21,10 @@ class WebGL2ComputeRenderingContextBase : public WebGL2RenderingContextBase {
void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
void dispatchComputeIndirect(int64_t offset);
+ /* Draw indirect */
+ void drawArraysIndirect(GLenum mode, int64_t offset);
+ void drawElementsIndirect(GLenum mode, GLenum type, int64_t offset);
+
/* Program interface query */
ScriptValue getProgramInterfaceParameter(ScriptState*,
WebGLProgram*,
@@ -32,7 +36,7 @@ class WebGL2ComputeRenderingContextBase : public WebGL2RenderingContextBase {
String getProgramResourceName(WebGLProgram*,
GLenum program_interface,
GLuint index);
- base::Optional<Vector<ScriptValue>> getProgramResource(
+ base::Optional<HeapVector<ScriptValue>> getProgramResource(
ScriptState*,
WebGLProgram*,
GLenum program_interface,
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
index f63b65181ac..2dd697ff573 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
@@ -94,6 +94,10 @@ interface mixin WebGL2ComputeRenderingContextBase {
void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
void dispatchComputeIndirect(GLintptr offset);
+ /* Draw indirect */
+ void drawArraysIndirect(GLenum mode, GLintptr offset);
+ void drawElementsIndirect(GLenum mode, GLenum type, GLintptr offset);
+
/* Program interface query */
[CallWith=ScriptState] any getProgramInterfaceParameter(WebGLProgram program, GLenum programInterface, GLenum pname);
GLuint getProgramResourceIndex(WebGLProgram program, GLenum programInterface, DOMString name);
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 82dcc844fde..23713f10315 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
@@ -146,7 +146,7 @@ void WebGL2RenderingContext::RegisterContextExtensions() {
RegisterExtension<WebGLMultiDrawInstanced>(webgl_multi_draw_instanced_,
kDraftExtension);
RegisterExtension<WebGLVideoTexture>(webgl_video_texture_, kDraftExtension);
- RegisterExtension<OVRMultiview2>(ovr_multiview2_, kDraftExtension);
+ RegisterExtension<OVRMultiview2>(ovr_multiview2_);
}
void WebGL2RenderingContext::Trace(blink::Visitor* visitor) {
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 133cfbeeb9e..04915cb1372 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
@@ -487,12 +487,12 @@ ScriptValue WebGL2RenderingContextBase::getInternalformatParameter(
GLenum internalformat,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (target != GL_RENDERBUFFER) {
SynthesizeGLError(GL_INVALID_ENUM, "getInternalformatParameter",
"invalid target");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (internalformat) {
@@ -549,13 +549,13 @@ ScriptValue WebGL2RenderingContextBase::getInternalformatParameter(
SynthesizeGLError(GL_INVALID_ENUM, "getInternalformatParameter",
"invalid internalformat when EXT_color_buffer_float "
"is not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
break;
default:
SynthesizeGLError(GL_INVALID_ENUM, "getInternalformatParameter",
"invalid internalformat");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (pname) {
@@ -577,7 +577,7 @@ ScriptValue WebGL2RenderingContextBase::getInternalformatParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getInternalformatParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3935,7 +3935,7 @@ ScriptValue WebGL2RenderingContextBase::getQuery(ScriptState* script_state,
GLenum target,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (ExtensionEnabled(kEXTDisjointTimerQueryWebGL2Name)) {
if (pname == GL_QUERY_COUNTER_BITS_EXT) {
@@ -3946,23 +3946,23 @@ ScriptValue WebGL2RenderingContextBase::getQuery(ScriptState* script_state,
}
SynthesizeGLError(GL_INVALID_ENUM, "getQuery",
"invalid target/pname combination");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (target == GL_TIME_ELAPSED_EXT && pname == GL_CURRENT_QUERY) {
return current_elapsed_query_
? WebGLAny(script_state, current_elapsed_query_)
- : ScriptValue::CreateNull(script_state);
+ : ScriptValue::CreateNull(script_state->GetIsolate());
}
if (target == GL_TIMESTAMP_EXT && pname == GL_CURRENT_QUERY) {
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
if (pname != GL_CURRENT_QUERY) {
SynthesizeGLError(GL_INVALID_ENUM, "getQuery", "invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (target) {
@@ -3977,9 +3977,9 @@ ScriptValue WebGL2RenderingContextBase::getQuery(ScriptState* script_state,
current_transform_feedback_primitives_written_query_);
default:
SynthesizeGLError(GL_INVALID_ENUM, "getQuery", "invalid target");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
ScriptValue WebGL2RenderingContextBase::getQueryParameter(
@@ -3987,21 +3987,21 @@ ScriptValue WebGL2RenderingContextBase::getQueryParameter(
WebGLQuery* query,
GLenum pname) {
if (!ValidateWebGLObject("getQueryParameter", query))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
// Query is non-null at this point.
if (!query->GetTarget()) {
SynthesizeGLError(GL_INVALID_OPERATION, "getQueryParameter",
"'query' is not a query object yet, since it has't been "
"used by beginQuery");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (query == current_boolean_occlusion_query_ ||
query == current_transform_feedback_primitives_written_query_ ||
query == current_elapsed_query_) {
SynthesizeGLError(GL_INVALID_OPERATION, "getQueryParameter",
"query is currently active");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
switch (pname) {
@@ -4016,7 +4016,7 @@ ScriptValue WebGL2RenderingContextBase::getQueryParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getQueryParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4152,6 +4152,13 @@ void WebGL2RenderingContextBase::SamplerParameter(WebGLSampler* sampler,
return;
}
break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!ExtensionEnabled(kEXTTextureFilterAnisotropicName)) {
+ SynthesizeGLError(GL_INVALID_ENUM, "samplerParameter",
+ "EXT_texture_filter_anisotropic not enabled");
+ return;
+ }
+ break;
default:
SynthesizeGLError(GL_INVALID_ENUM, "samplerParameter",
"invalid parameter name");
@@ -4182,7 +4189,7 @@ ScriptValue WebGL2RenderingContextBase::getSamplerParameter(
WebGLSampler* sampler,
GLenum pname) {
if (!ValidateWebGLObject("getSamplerParameter", sampler))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_TEXTURE_COMPARE_FUNC:
@@ -4202,10 +4209,20 @@ ScriptValue WebGL2RenderingContextBase::getSamplerParameter(
ContextGL()->GetSamplerParameterfv(ObjectOrZero(sampler), pname, &value);
return WebGLAny(script_state, value);
}
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT: {
+ if (!ExtensionEnabled(kEXTTextureFilterAnisotropicName)) {
+ SynthesizeGLError(GL_INVALID_ENUM, "samplerParameter",
+ "EXT_texture_filter_anisotropic not enabled");
+ return ScriptValue::CreateNull(script_state->GetIsolate());
+ }
+ GLfloat value = 0.f;
+ ContextGL()->GetSamplerParameterfv(ObjectOrZero(sampler), pname, &value);
+ return WebGLAny(script_state, value);
+ }
default:
SynthesizeGLError(GL_INVALID_ENUM, "getSamplerParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4297,7 +4314,7 @@ ScriptValue WebGL2RenderingContextBase::getSyncParameter(
WebGLSync* sync,
GLenum pname) {
if (!ValidateWebGLObject("getSyncParameter", sync))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_OBJECT_TYPE:
@@ -4310,7 +4327,7 @@ ScriptValue WebGL2RenderingContextBase::getSyncParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getSyncParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4644,7 +4661,7 @@ ScriptValue WebGL2RenderingContextBase::getIndexedParameter(
GLenum target,
GLuint index) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (target) {
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: {
@@ -4653,7 +4670,7 @@ ScriptValue WebGL2RenderingContextBase::getIndexedParameter(
index, &buffer)) {
SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter",
"index out of range");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
return WebGLAny(script_state, buffer);
}
@@ -4661,7 +4678,7 @@ ScriptValue WebGL2RenderingContextBase::getIndexedParameter(
if (index >= bound_indexed_uniform_buffers_.size()) {
SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter",
"index out of range");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
return WebGLAny(script_state,
bound_indexed_uniform_buffers_[index].Get());
@@ -4676,7 +4693,7 @@ ScriptValue WebGL2RenderingContextBase::getIndexedParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4701,7 +4718,7 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniforms(
const Vector<GLuint>& uniform_indices,
GLenum pname) {
if (!ValidateWebGLProgramOrShader("getActiveUniforms", program))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
enum ReturnType { kEnumType, kUnsignedIntType, kIntType, kBoolType };
@@ -4725,7 +4742,7 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniforms(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getActiveUniforms",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint active_uniforms = -1;
@@ -4738,7 +4755,7 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniforms(
if (index >= active_uniforms_unsigned) {
SynthesizeGLError(GL_INVALID_VALUE, "getActiveUniforms",
"uniform index greater than ACTIVE_UNIFORMS");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4770,7 +4787,7 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniforms(
}
default:
NOTREACHED();
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -4813,11 +4830,11 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniformBlockParameter(
GLuint uniform_block_index,
GLenum pname) {
if (!ValidateWebGLProgramOrShader("getActiveUniformBlockParameter", program))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (!ValidateUniformBlockIndex("getActiveUniformBlockParameter", program,
uniform_block_index))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_UNIFORM_BLOCK_BINDING:
@@ -4852,7 +4869,7 @@ ScriptValue WebGL2RenderingContextBase::getActiveUniformBlockParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getActiveUniformBlockParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -5016,7 +5033,7 @@ void WebGL2RenderingContextBase::deleteFramebuffer(
ScriptValue WebGL2RenderingContextBase::getParameter(ScriptState* script_state,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_SHADING_LANGUAGE_VERSION: {
return WebGLAny(
@@ -5138,7 +5155,7 @@ ScriptValue WebGL2RenderingContextBase::getParameter(ScriptState* script_state,
if (!transform_feedback_binding_->IsDefaultObject()) {
return WebGLAny(script_state, transform_feedback_binding_.Get());
}
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_TRANSFORM_FEEDBACK_PAUSED:
return GetBooleanParameter(script_state, pname);
case GL_UNIFORM_BUFFER_BINDING:
@@ -5162,7 +5179,7 @@ ScriptValue WebGL2RenderingContextBase::getParameter(ScriptState* script_state,
SynthesizeGLError(GL_INVALID_ENUM, "getParameter",
"invalid parameter name, "
"EXT_disjoint_timer_query_webgl2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_GPU_DISJOINT_EXT:
if (ExtensionEnabled(kEXTDisjointTimerQueryWebGL2Name)) {
return GetBooleanParameter(script_state, GL_GPU_DISJOINT_EXT);
@@ -5170,7 +5187,7 @@ ScriptValue WebGL2RenderingContextBase::getParameter(ScriptState* script_state,
SynthesizeGLError(GL_INVALID_ENUM, "getParameter",
"invalid parameter name, "
"EXT_disjoint_timer_query_webgl2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
return WebGLRenderingContextBase::getParameter(script_state, pname);
@@ -5557,7 +5574,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
const char kFunctionName[] = "getFramebufferAttachmentParameter";
if (isContextLost() || !ValidateGetFramebufferAttachmentParameterFunc(
kFunctionName, target, attachment))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
WebGLFramebuffer* framebuffer_binding = GetFramebufferBinding(target);
DCHECK(!framebuffer_binding || framebuffer_binding->Object());
@@ -5578,7 +5595,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
default:
SynthesizeGLError(GL_INVALID_OPERATION, kFunctionName,
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
switch (pname) {
@@ -5612,17 +5629,17 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
return WebGLAny(script_state, 0);
SynthesizeGLError(GL_INVALID_ENUM, kFunctionName,
"invalid parameter name, OVR_multiview2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
if (ExtensionEnabled(kOVRMultiview2Name))
return WebGLAny(script_state, 0);
SynthesizeGLError(GL_INVALID_ENUM, kFunctionName,
"invalid parameter name, OVR_multiview2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
SynthesizeGLError(GL_INVALID_ENUM, kFunctionName,
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -5636,7 +5653,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
SynthesizeGLError(
GL_INVALID_OPERATION, kFunctionName,
"different objects bound to DEPTH_ATTACHMENT and STENCIL_ATTACHMENT");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
attachment_object = depth_attachment;
} else {
@@ -5648,11 +5665,11 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
return WebGLAny(script_state, GL_NONE);
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
SynthesizeGLError(GL_INVALID_OPERATION, kFunctionName,
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
DCHECK(attachment_object->IsTexture() || attachment_object->IsRenderbuffer());
@@ -5686,7 +5703,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
SynthesizeGLError(
GL_INVALID_OPERATION, kFunctionName,
"COMPONENT_TYPE can't be queried for DEPTH_STENCIL_ATTACHMENT");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
FALLTHROUGH;
case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: {
@@ -5700,7 +5717,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
if (!ExtensionEnabled(kOVRMultiview2Name)) {
SynthesizeGLError(GL_INVALID_ENUM, kFunctionName,
"invalid parameter name, OVR_multiview2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint value = 0;
ContextGL()->GetFramebufferAttachmentParameteriv(target, attachment,
@@ -5711,7 +5728,7 @@ ScriptValue WebGL2RenderingContextBase::getFramebufferAttachmentParameter(
break;
}
SynthesizeGLError(GL_INVALID_ENUM, kFunctionName, "invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
void WebGL2RenderingContextBase::Trace(blink::Visitor* visitor) {
@@ -5769,7 +5786,7 @@ ScriptValue WebGL2RenderingContextBase::getTexParameter(
GLenum target,
GLenum pname) {
if (isContextLost() || !ValidateTextureBinding("getTexParameter", target))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_TEXTURE_WRAP_R:
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.cc
index 444834b91c6..5f30971ef34 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.cc
@@ -12,7 +12,7 @@ WebGLCompressedTextureETC::WebGLCompressedTextureETC(
WebGLRenderingContextBase* context)
: WebGLExtension(context) {
context->ExtensionsUtil()->EnsureExtensionEnabled(
- "GL_CHROMIUM_compressed_texture_etc");
+ "GL_ANGLE_compressed_texture_etc");
context->AddCompressedTextureFormat(GL_COMPRESSED_R11_EAC);
context->AddCompressedTextureFormat(GL_COMPRESSED_SIGNED_R11_EAC);
context->AddCompressedTextureFormat(GL_COMPRESSED_RGB8_ETC2);
@@ -38,8 +38,7 @@ WebGLCompressedTextureETC* WebGLCompressedTextureETC::Create(
bool WebGLCompressedTextureETC::Supported(WebGLRenderingContextBase* context) {
Extensions3DUtil* extensions_util = context->ExtensionsUtil();
- return extensions_util->SupportsExtension(
- "GL_CHROMIUM_compressed_texture_etc");
+ return extensions_util->SupportsExtension("GL_ANGLE_compressed_texture_etc");
}
const char* WebGLCompressedTextureETC::ExtensionName() {
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 1a094f9a03b..03338285aa6 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,6 +28,7 @@
#include <memory>
#include <utility>
+#include "base/feature_list.h"
#include "base/numerics/checked_math.h"
#include "base/stl_util.h"
#include "build/build_config.h"
@@ -115,6 +116,10 @@
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
namespace blink {
+namespace {
+const base::Feature kLowLatencyWebGLSwapChain{
+ "LowLatencyWebGLSwapChain", base::FEATURE_DISABLED_BY_DEFAULT};
+} // namespace
bool WebGLRenderingContextBase::webgl_context_limits_initialized_ = false;
unsigned WebGLRenderingContextBase::max_active_webgl_contexts_ = 0;
@@ -440,6 +445,7 @@ void StripComments::Process(UChar c) {
break;
case kMiddleOfLine:
+ case kInPreprocessorDirective:
if (c == '/' && Peek(temp)) {
if (temp == '/') {
parse_state_ = kInSingleLineComment;
@@ -463,14 +469,6 @@ void StripComments::Process(UChar c) {
Emit(c);
break;
- case kInPreprocessorDirective:
- // No matter what the character is, just pass it
- // through. Do not parse comments in this state. This
- // might not be the right thing to do long term, but it
- // should handle the #error preprocessor directive.
- Emit(c);
- break;
-
case kInSingleLineComment:
// Line-continuation characters are processed before comment processing.
// Advance string if a new line character is immediately behind
@@ -772,9 +770,11 @@ WebGLRenderingContextBase::GetStaticBitmapImage(
}
scoped_refptr<StaticBitmapImage> WebGLRenderingContextBase::GetImage(
- AccelerationHint hint) const {
+ AccelerationHint hint) {
if (!GetDrawingBuffer())
return nullptr;
+
+ ScopedFramebufferRestorer fbo_restorer(this);
GetDrawingBuffer()->ResolveAndBindForReadAndDraw();
// Use the drawing buffer size here instead of the canvas size to ensure that
// sizing is consistent for the GetStaticBitmapImage() result. The forced
@@ -1097,7 +1097,7 @@ scoped_refptr<DrawingBuffer> WebGLRenderingContextBase::CreateDrawingBuffer(
: DrawingBuffer::kAllowChromiumImage;
bool using_swap_chain =
- RuntimeEnabledFeatures::WebGLSwapChainEnabled() &&
+ base::FeatureList::IsEnabled(kLowLatencyWebGLSwapChain) &&
context_provider->GetCapabilities().shared_image_swap_chain &&
CreationAttributes().desynchronized;
@@ -1391,22 +1391,31 @@ void WebGLRenderingContextBase::DidDraw() {
CanvasRenderingContext::DidDraw();
}
-void WebGLRenderingContextBase::PushFrame() {
+bool WebGLRenderingContextBase::PushFrame() {
int width = GetDrawingBuffer()->Size().Width();
int height = GetDrawingBuffer()->Size().Height();
+ int submitted_frame = false;
if (PaintRenderingResultsToCanvas(kBackBuffer)) {
if (Host()->GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
- Host()->PushFrame(Host()->ResourceProvider()->ProduceCanvasResource(),
- SkIRect::MakeWH(width, height));
+ submitted_frame =
+ Host()->PushFrame(Host()->ResourceProvider()->ProduceCanvasResource(),
+ SkIRect::MakeWH(width, height));
}
}
MarkLayerComposited();
+ return submitted_frame;
}
void WebGLRenderingContextBase::FinalizeFrame() {
if (GetDrawingBuffer() && GetDrawingBuffer()->UsingSwapChain())
GetDrawingBuffer()->PresentSwapChain();
marked_canvas_dirty_ = false;
+
+ // For low-latency canvases
+ const bool webgl_overlay_enabled =
+ RuntimeEnabledFeatures::WebGLImageChromiumEnabled() || UsingSwapChain();
+ if (canvas() && canvas()->LowLatencyEnabled() && !webgl_overlay_enabled)
+ PaintRenderingResultsToCanvas(kBackBuffer);
}
void WebGLRenderingContextBase::OnErrorMessage(const char* message,
@@ -1611,7 +1620,7 @@ bool WebGLRenderingContextBase::ContextCreatedOnXRCompatibleAdapter() {
bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer(
CanvasResourceProvider* resource_provider,
- SourceDrawingBuffer source_buffer) const {
+ SourceDrawingBuffer source_buffer) {
if (!drawing_buffer_)
return false;
if (resource_provider->IsAccelerated()) {
@@ -1657,8 +1666,7 @@ IntSize WebGLRenderingContextBase::DrawingBufferSize() const {
return GetDrawingBuffer()->Size();
}
-scoped_refptr<Uint8Array>
-WebGLRenderingContextBase::PaintRenderingResultsToDataArray(
+sk_sp<SkData> WebGLRenderingContextBase::PaintRenderingResultsToDataArray(
SourceDrawingBuffer source_buffer) {
if (isContextLost())
return nullptr;
@@ -2911,7 +2919,7 @@ ScriptValue WebGLRenderingContextBase::getBufferParameter(
GLenum target,
GLenum pname) {
if (isContextLost() || !ValidateBufferTarget("getBufferParameter", target))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_BUFFER_USAGE: {
@@ -2929,7 +2937,7 @@ ScriptValue WebGLRenderingContextBase::getBufferParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getBufferParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3033,7 +3041,7 @@ ScriptValue WebGLRenderingContextBase::getExtension(ScriptState* script_state,
ToV8(extension, script_state->GetContext()->Global(),
script_state->GetIsolate());
- return ScriptValue(script_state, wrapped_extension);
+ return ScriptValue(script_state->GetIsolate(), wrapped_extension);
}
ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
@@ -3044,18 +3052,18 @@ ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
if (isContextLost() ||
!ValidateFramebufferFuncParameters("getFramebufferAttachmentParameter",
target, attachment))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (!framebuffer_binding_ || !framebuffer_binding_->Object()) {
SynthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter",
"no framebuffer bound");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (framebuffer_binding_ && framebuffer_binding_->Opaque()) {
SynthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter",
"cannot query parameters of an opaque framebuffer");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
WebGLSharedObject* attachment_object =
@@ -3067,7 +3075,7 @@ ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
// specifies INVALID_OPERATION.
SynthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
DCHECK(attachment_object->IsTexture() || attachment_object->IsRenderbuffer());
@@ -3093,11 +3101,11 @@ ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
}
SynthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter",
"invalid parameter name for renderbuffer attachment");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
SynthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter",
"invalid parameter name for texture attachment");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
} else {
switch (pname) {
@@ -3114,11 +3122,11 @@ ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
}
SynthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter",
"invalid parameter name for renderbuffer attachment");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
SynthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter",
"invalid parameter name for renderbuffer attachment");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
}
@@ -3126,7 +3134,7 @@ ScriptValue WebGLRenderingContextBase::getFramebufferAttachmentParameter(
ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
const int kIntZero = 0;
switch (pname) {
case GL_ACTIVE_TEXTURE:
@@ -3336,7 +3344,7 @@ ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state,
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, OES_standard_derivatives not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case WebGLDebugRendererInfo::kUnmaskedRendererWebgl:
if (ExtensionEnabled(kWebGLDebugRendererInfoName))
return WebGLAny(script_state,
@@ -3344,7 +3352,7 @@ ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state,
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, WEBGL_debug_renderer_info not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case WebGLDebugRendererInfo::kUnmaskedVendorWebgl:
if (ExtensionEnabled(kWebGLDebugRendererInfoName))
return WebGLAny(script_state,
@@ -3352,59 +3360,60 @@ ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state,
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, WEBGL_debug_renderer_info not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
if (ExtensionEnabled(kOESVertexArrayObjectName) || IsWebGL2OrHigher()) {
if (!bound_vertex_array_object_->IsDefaultObject())
return WebGLAny(script_state, bound_vertex_array_object_.Get());
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, OES_vertex_array_object not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
- if (ExtensionEnabled(kEXTTextureFilterAnisotropicName))
- return GetUnsignedIntParameter(script_state,
- GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+ if (ExtensionEnabled(kEXTTextureFilterAnisotropicName)) {
+ return GetFloatParameter(script_state,
+ GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+ }
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, EXT_texture_filter_anisotropic not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
if (ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2OrHigher())
return WebGLAny(script_state, MaxColorAttachments());
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, WEBGL_draw_buffers not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_MAX_DRAW_BUFFERS_EXT:
if (ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2OrHigher())
return WebGLAny(script_state, MaxDrawBuffers());
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, WEBGL_draw_buffers not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_TIMESTAMP_EXT:
if (ExtensionEnabled(kEXTDisjointTimerQueryName))
return WebGLAny(script_state, 0);
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, EXT_disjoint_timer_query not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_GPU_DISJOINT_EXT:
if (ExtensionEnabled(kEXTDisjointTimerQueryName))
return GetBooleanParameter(script_state, GL_GPU_DISJOINT_EXT);
SynthesizeGLError(
GL_INVALID_ENUM, "getParameter",
"invalid parameter name, EXT_disjoint_timer_query not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
case GL_MAX_VIEWS_OVR:
if (ExtensionEnabled(kOVRMultiview2Name))
return GetIntParameter(script_state, pname);
SynthesizeGLError(GL_INVALID_ENUM, "getParameter",
"invalid parameter name, OVR_multiview2 not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
if ((ExtensionEnabled(kWebGLDrawBuffersName) || IsWebGL2OrHigher()) &&
pname >= GL_DRAW_BUFFER0_EXT &&
@@ -3418,7 +3427,7 @@ ScriptValue WebGLRenderingContextBase::getParameter(ScriptState* script_state,
}
SynthesizeGLError(GL_INVALID_ENUM, "getParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3427,7 +3436,7 @@ ScriptValue WebGLRenderingContextBase::getProgramParameter(
WebGLProgram* program,
GLenum pname) {
if (!ValidateWebGLProgramOrShader("getProgramParamter", program)) {
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint value = 0;
@@ -3443,7 +3452,7 @@ ScriptValue WebGLRenderingContextBase::getProgramParameter(
if (!ExtensionEnabled(kKHRParallelShaderCompileName)) {
SynthesizeGLError(GL_INVALID_ENUM, "getProgramParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
bool completed;
if (checkProgramCompletionQueryAvailable(program, &completed)) {
@@ -3455,7 +3464,7 @@ ScriptValue WebGLRenderingContextBase::getProgramParameter(
if (!IsWebGL2OrHigher()) {
SynthesizeGLError(GL_INVALID_ENUM, "getProgramParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
FALLTHROUGH;
case GL_ATTACHED_SHADERS:
@@ -3467,7 +3476,7 @@ ScriptValue WebGLRenderingContextBase::getProgramParameter(
if (!IsWebGL2OrHigher()) {
SynthesizeGLError(GL_INVALID_ENUM, "getProgramParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
ContextGL()->GetProgramiv(ObjectOrZero(program), pname, &value);
return WebGLAny(script_state, static_cast<unsigned>(value));
@@ -3480,7 +3489,7 @@ ScriptValue WebGLRenderingContextBase::getProgramParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getProgramParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3496,16 +3505,16 @@ ScriptValue WebGLRenderingContextBase::getRenderbufferParameter(
GLenum target,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (target != GL_RENDERBUFFER) {
SynthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter",
"invalid target");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if (!renderbuffer_binding_ || !renderbuffer_binding_->Object()) {
SynthesizeGLError(GL_INVALID_OPERATION, "getRenderbufferParameter",
"no renderbuffer bound");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint value = 0;
@@ -3514,7 +3523,7 @@ ScriptValue WebGLRenderingContextBase::getRenderbufferParameter(
if (!IsWebGL2OrHigher()) {
SynthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
FALLTHROUGH;
case GL_RENDERBUFFER_WIDTH:
@@ -3534,7 +3543,7 @@ ScriptValue WebGLRenderingContextBase::getRenderbufferParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3543,7 +3552,7 @@ ScriptValue WebGLRenderingContextBase::getShaderParameter(
WebGLShader* shader,
GLenum pname) {
if (!ValidateWebGLProgramOrShader("getShaderParameter", shader)) {
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint value = 0;
switch (pname) {
@@ -3556,7 +3565,7 @@ ScriptValue WebGLRenderingContextBase::getShaderParameter(
if (!ExtensionEnabled(kKHRParallelShaderCompileName)) {
SynthesizeGLError(GL_INVALID_ENUM, "getShaderParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
ContextGL()->GetShaderiv(ObjectOrZero(shader), pname, &value);
return WebGLAny(script_state, static_cast<bool>(value));
@@ -3566,7 +3575,7 @@ ScriptValue WebGLRenderingContextBase::getShaderParameter(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getShaderParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3637,9 +3646,9 @@ ScriptValue WebGLRenderingContextBase::getTexParameter(
GLenum target,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (!ValidateTextureBinding("getTexParameter", target))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
case GL_TEXTURE_MAG_FILTER:
case GL_TEXTURE_MIN_FILTER:
@@ -3658,11 +3667,11 @@ ScriptValue WebGLRenderingContextBase::getTexParameter(
SynthesizeGLError(
GL_INVALID_ENUM, "getTexParameter",
"invalid parameter name, EXT_texture_filter_anisotropic not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
default:
SynthesizeGLError(GL_INVALID_ENUM, "getTexParameter",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -3671,12 +3680,12 @@ ScriptValue WebGLRenderingContextBase::getUniform(
WebGLProgram* program,
const WebGLUniformLocation* uniform_location) {
if (!ValidateWebGLProgramOrShader("getUniform", program))
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
DCHECK(uniform_location);
if (uniform_location->Program() != program) {
SynthesizeGLError(GL_INVALID_OPERATION, "getUniform",
"no uniformlocation or not valid for this program");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
GLint location = uniform_location->Location();
@@ -3685,11 +3694,11 @@ ScriptValue WebGLRenderingContextBase::getUniform(
ContextGL()->GetProgramiv(program_id, GL_ACTIVE_UNIFORM_MAX_LENGTH,
&max_name_length);
if (max_name_length < 0)
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (max_name_length == 0) {
SynthesizeGLError(GL_INVALID_VALUE, "getUniform",
"no active uniforms exist");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
// FIXME: make this more efficient using WebGLUniformLocation and caching
@@ -3707,7 +3716,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
&size, &type,
reinterpret_cast<GLchar*>(name_ptr));
if (size < 0)
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
String name(name_impl->Substring(0, name_length));
StringBuilder name_builder;
// Strip "[0]" from the name if it's an array.
@@ -3802,7 +3811,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
SynthesizeGLError(
GL_INVALID_VALUE, "getUniform",
"unhandled type, WEBGL_video_texture extension not enabled");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
base_type = GL_INT;
length = 1;
@@ -3812,7 +3821,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
// Can't handle this type
SynthesizeGLError(GL_INVALID_VALUE, "getUniform",
"unhandled type");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
// handle GLenums for WebGL 2.0 or higher
switch (type) {
@@ -3887,7 +3896,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
if (context_type_ != Platform::kWebGL2ComputeContextType) {
SynthesizeGLError(GL_INVALID_VALUE, "getUniform",
"unhandled type");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
base_type = GL_INT;
length = 1;
@@ -3897,7 +3906,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
// Can't handle this type
SynthesizeGLError(GL_INVALID_VALUE, "getUniform",
"unhandled type");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
switch (base_type) {
@@ -3944,7 +3953,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
// If we get here, something went wrong in our unfortunately complex logic
// above
SynthesizeGLError(GL_INVALID_VALUE, "getUniform", "unknown error");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
WebGLUniformLocation* WebGLRenderingContextBase::getUniformLocation(
@@ -3975,11 +3984,11 @@ ScriptValue WebGLRenderingContextBase::getVertexAttrib(
GLuint index,
GLenum pname) {
if (isContextLost())
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
if (index >= max_vertex_attribs_) {
SynthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib",
"index out of range");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
if ((ExtensionEnabled(kANGLEInstancedArraysName) || IsWebGL2OrHigher()) &&
@@ -4033,7 +4042,7 @@ ScriptValue WebGLRenderingContextBase::getVertexAttrib(
NOTREACHED();
break;
}
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
if (IsWebGL2OrHigher()) {
@@ -4045,7 +4054,7 @@ ScriptValue WebGLRenderingContextBase::getVertexAttrib(
default:
SynthesizeGLError(GL_INVALID_ENUM, "getVertexAttrib",
"invalid parameter name");
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
}
@@ -5455,9 +5464,13 @@ void WebGLRenderingContextBase::TexImageHelperCanvasRenderingContextHost(
// TODO(crbug.com/612542): Implement GPU-to-GPU copy path for more
// cases, like copying to layers of 3D textures, and elements of
// 2D texture arrays.
+ bool flip_y = unpack_flip_y_;
+ if (is_origin_top_left_ && is_webgl_canvas)
+ flip_y = !flip_y;
+
TexImageImpl(function_id, target, level, internalformat, xoffset, yoffset,
zoffset, format, type, image.get(),
- WebGLImageConversion::kHtmlDomCanvas, unpack_flip_y_,
+ WebGLImageConversion::kHtmlDomCanvas, flip_y,
unpack_premultiply_alpha_, source_sub_rectangle, depth,
unpack_image_height);
}
@@ -5722,7 +5735,7 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
SkPixmap pixmap;
uint8_t* pixel_data_ptr = nullptr;
- scoped_refptr<Uint8Array> pixel_data;
+ Vector<uint8_t> pixel_data;
// In the case where an ImageBitmap is not texture backed, peekPixels() always
// succeed. However, when it is texture backed and !canUseTexImageByGPU, we
// do a GPU read back.
@@ -5732,7 +5745,7 @@ void WebGLRenderingContextBase::TexImageHelperImageBitmap(
} else {
pixel_data = bitmap->CopyBitmapData(
bitmap->IsPremultiplied() ? kPremultiplyAlpha : kUnpremultiplyAlpha);
- pixel_data_ptr = pixel_data->Data();
+ pixel_data_ptr = pixel_data.data();
}
Vector<uint8_t> data;
bool need_conversion = true;
@@ -6803,7 +6816,7 @@ ScriptValue WebGLRenderingContextBase::GetIntParameter(
if (value == 0) {
// This indicates read framebuffer is incomplete and an
// INVALID_OPERATION has been generated.
- return ScriptValue::CreateNull(script_state);
+ return ScriptValue::CreateNull(script_state->GetIsolate());
}
break;
default:
@@ -7502,9 +7515,12 @@ void WebGLRenderingContextBase::PrintGLErrorToConsole(const String& message) {
}
void WebGLRenderingContextBase::PrintWarningToConsole(const String& message) {
- Host()->GetTopExecutionContext()->AddConsoleMessage(
- ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering,
- mojom::ConsoleMessageLevel::kWarning, message));
+ blink::ExecutionContext* context = Host()->GetTopExecutionContext();
+ if (context) {
+ context->AddConsoleMessage(
+ ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering,
+ mojom::ConsoleMessageLevel::kWarning, message));
+ }
}
bool WebGLRenderingContextBase::ValidateFramebufferFuncParameters(
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 c2fc04ae55e..8368b2766c2 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
@@ -56,6 +56,7 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES3/gl31.h"
+#include "third_party/skia/include/core/SkData.h"
namespace cc {
class Layer;
@@ -566,8 +567,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void MarkLayerComposited() override;
- scoped_refptr<Uint8Array> PaintRenderingResultsToDataArray(
- SourceDrawingBuffer) override;
+ sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer) override;
void ProvideBackBufferToResourceProvider() const override;
unsigned MaxVertexAttribs() const { return max_vertex_attribs_; }
@@ -596,7 +596,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
};
scoped_refptr<StaticBitmapImage> GetImage(
- AccelerationHint = kPreferAcceleration) const override;
+ AccelerationHint = kPreferAcceleration) override;
void SetFilterQuality(SkFilterQuality) override;
bool IsWebGL2OrHigher() {
return context_type_ == Platform::kWebGL2ContextType ||
@@ -669,7 +669,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void DidDraw(const SkIRect&) override;
void DidDraw() override;
void FinalizeFrame() override;
- void PushFrame() override;
+ bool PushFrame() override;
// DrawingBuffer::Client implementation.
bool DrawingBufferClientIsBoundForDraw() override;
@@ -1740,7 +1740,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
bool ContextCreatedOnXRCompatibleAdapter();
bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
- SourceDrawingBuffer) const;
+ SourceDrawingBuffer);
void HoldReferenceToDrawingBuffer(DrawingBuffer*);
static void InitializeWebGLContextLimits(
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
index 0837d1e3b19..ef46d408147 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -35,6 +35,8 @@ blink_modules_sources("webgpu") {
"gpu_compute_pipeline.h",
"gpu_device.cc",
"gpu_device.h",
+ "gpu_device_lost_info.cc",
+ "gpu_device_lost_info.h",
"gpu_fence.cc",
"gpu_fence.h",
"gpu_out_of_memory_error.cc",
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 8689267ffbd..af1fb2af52e 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
@@ -6,10 +6,10 @@
#include <dawn/dawn.h>
-#include "third_party/blink/renderer/modules/webgpu/gpu_color.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_extent_3d.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_origin_3d.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.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_sequence_or_gpu_extent_3d_dict.h"
+#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_sequence_or_gpu_origin_3d_dict.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_shader_module.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -32,6 +32,9 @@ DawnBindingType AsDawnEnum<DawnBindingType>(const WTF::String& webgpu_enum) {
if (webgpu_enum == "sampled-texture") {
return DAWN_BINDING_TYPE_SAMPLED_TEXTURE;
}
+ if (webgpu_enum == "storage-texture") {
+ return DAWN_BINDING_TYPE_STORAGE_TEXTURE;
+ }
NOTREACHED();
return DAWN_BINDING_TYPE_FORCE32;
}
@@ -291,6 +294,9 @@ DawnStoreOp AsDawnEnum<DawnStoreOp>(const WTF::String& webgpu_enum) {
if (webgpu_enum == "store") {
return DAWN_STORE_OP_STORE;
}
+ if (webgpu_enum == "clear") {
+ return DAWN_STORE_OP_CLEAR;
+ }
NOTREACHED();
return DAWN_STORE_OP_FORCE32;
}
@@ -420,154 +426,57 @@ DawnInputStepMode AsDawnEnum<DawnInputStepMode>(
template <>
DawnVertexFormat AsDawnEnum<DawnVertexFormat>(const WTF::String& webgpu_enum) {
- if (webgpu_enum == "uchar") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "uchar2") {
return DAWN_VERTEX_FORMAT_UCHAR2;
}
- if (webgpu_enum == "uchar3") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "uchar4") {
return DAWN_VERTEX_FORMAT_UCHAR4;
}
- if (webgpu_enum == "char") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "char2") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
- if (webgpu_enum == "char3") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
+ return DAWN_VERTEX_FORMAT_CHAR2;
}
if (webgpu_enum == "char4") {
return DAWN_VERTEX_FORMAT_CHAR4;
}
- if (webgpu_enum == "ucharnorm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "uchar2norm") {
return DAWN_VERTEX_FORMAT_UCHAR2_NORM;
}
- if (webgpu_enum == "uchar3norm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "uchar4norm") {
return DAWN_VERTEX_FORMAT_UCHAR4_NORM;
}
- if (webgpu_enum == "uchar4norm-bgra") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
- if (webgpu_enum == "charnorm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "char2norm") {
return DAWN_VERTEX_FORMAT_CHAR2_NORM;
}
- if (webgpu_enum == "char3norm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "char4norm") {
return DAWN_VERTEX_FORMAT_CHAR4_NORM;
}
- if (webgpu_enum == "ushort") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "ushort2") {
return DAWN_VERTEX_FORMAT_USHORT2;
}
- if (webgpu_enum == "ushort3") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "ushort4") {
return DAWN_VERTEX_FORMAT_USHORT4;
}
- if (webgpu_enum == "short") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "short2") {
return DAWN_VERTEX_FORMAT_SHORT2;
}
- if (webgpu_enum == "short3") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "short4") {
return DAWN_VERTEX_FORMAT_SHORT4;
}
- if (webgpu_enum == "ushortnorm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "ushort2norm") {
return DAWN_VERTEX_FORMAT_USHORT2_NORM;
}
- if (webgpu_enum == "ushort3norm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "ushort4norm") {
return DAWN_VERTEX_FORMAT_USHORT4_NORM;
}
- if (webgpu_enum == "shortnorm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "short2norm") {
return DAWN_VERTEX_FORMAT_SHORT2_NORM;
}
- if (webgpu_enum == "short3norm") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "short4norm") {
return DAWN_VERTEX_FORMAT_SHORT4_NORM;
}
- if (webgpu_enum == "half") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "half2") {
return DAWN_VERTEX_FORMAT_HALF2;
}
- if (webgpu_enum == "half3") {
- // TODO(crbug.com/dawn/41): Implement remaining vertex formats
- NOTREACHED();
- return DAWN_VERTEX_FORMAT_FORCE32;
- }
if (webgpu_enum == "half4") {
return DAWN_VERTEX_FORMAT_HALF4;
}
@@ -665,7 +574,50 @@ DawnFrontFace AsDawnEnum<DawnFrontFace>(const WTF::String& webgpu_enum) {
return DAWN_FRONT_FACE_FORCE32;
}
-DawnColor AsDawnType(const GPUColor* webgpu_color) {
+template <>
+DawnTextureAspect AsDawnEnum<DawnTextureAspect>(
+ const WTF::String& webgpu_enum) {
+ if (webgpu_enum == "all") {
+ return DAWN_TEXTURE_ASPECT_ALL;
+ }
+ if (webgpu_enum == "stencil-only") {
+ return DAWN_TEXTURE_ASPECT_STENCIL_ONLY;
+ }
+ if (webgpu_enum == "depth-only") {
+ return DAWN_TEXTURE_ASPECT_DEPTH_ONLY;
+ }
+ NOTREACHED();
+ return DAWN_TEXTURE_ASPECT_FORCE32;
+}
+
+template <>
+DawnErrorFilter AsDawnEnum<DawnErrorFilter>(const WTF::String& webgpu_enum) {
+ if (webgpu_enum == "none") {
+ return DAWN_ERROR_FILTER_NONE;
+ }
+ if (webgpu_enum == "out-of-memory") {
+ return DAWN_ERROR_FILTER_OUT_OF_MEMORY;
+ }
+ if (webgpu_enum == "validation") {
+ return DAWN_ERROR_FILTER_VALIDATION;
+ }
+ NOTREACHED();
+ return DAWN_ERROR_FILTER_FORCE32;
+}
+
+DawnColor AsDawnColor(const Vector<double>& webgpu_color) {
+ DCHECK_EQ(webgpu_color.size(), 4UL);
+
+ DawnColor dawn_color = {};
+ dawn_color.r = webgpu_color[0];
+ dawn_color.g = webgpu_color[1];
+ dawn_color.b = webgpu_color[2];
+ dawn_color.a = webgpu_color[3];
+
+ return dawn_color;
+}
+
+DawnColor AsDawnType(const GPUColorDict* webgpu_color) {
DCHECK(webgpu_color);
DawnColor dawn_color = {};
@@ -677,30 +629,77 @@ DawnColor AsDawnType(const GPUColor* webgpu_color) {
return dawn_color;
}
-DawnExtent3D AsDawnType(const GPUExtent3D* webgpu_extent) {
+DawnColor 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();
+ DawnColor dawn_color = {};
+ return dawn_color;
+}
+
+DawnExtent3D AsDawnType(
+ const UnsignedLongSequenceOrGPUExtent3DDict* webgpu_extent) {
DCHECK(webgpu_extent);
DawnExtent3D dawn_extent = {};
- dawn_extent.width = webgpu_extent->width();
- dawn_extent.height = webgpu_extent->height();
- dawn_extent.depth = webgpu_extent->depth();
+
+ if (webgpu_extent->IsUnsignedLongSequence()) {
+ const Vector<uint32_t>& webgpu_extent_sequence =
+ webgpu_extent->GetAsUnsignedLongSequence();
+ DCHECK_EQ(webgpu_extent_sequence.size(), 3UL);
+ dawn_extent.width = webgpu_extent_sequence[0];
+ dawn_extent.height = webgpu_extent_sequence[1];
+ dawn_extent.depth = webgpu_extent_sequence[2];
+
+ } 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.depth = webgpu_extent_3d_dict->depth();
+
+ } else {
+ NOTREACHED();
+ }
return dawn_extent;
}
-DawnOrigin3D AsDawnType(const GPUOrigin3D* webgpu_origin) {
+DawnOrigin3D AsDawnType(
+ const UnsignedLongSequenceOrGPUOrigin3DDict* webgpu_origin) {
DCHECK(webgpu_origin);
DawnOrigin3D dawn_origin = {};
- dawn_origin.x = webgpu_origin->x();
- dawn_origin.y = webgpu_origin->y();
- dawn_origin.z = webgpu_origin->z();
+
+ if (webgpu_origin->IsUnsignedLongSequence()) {
+ const Vector<uint32_t>& webgpu_origin_sequence =
+ webgpu_origin->GetAsUnsignedLongSequence();
+ DCHECK_EQ(webgpu_origin_sequence.size(), 3UL);
+ dawn_origin.x = webgpu_origin_sequence[0];
+ dawn_origin.y = webgpu_origin_sequence[1];
+ dawn_origin.z = webgpu_origin_sequence[2];
+
+ } 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();
+ }
return dawn_origin;
}
-OwnedPipelineStageDescriptor AsDawnType(
- const GPUPipelineStageDescriptor* webgpu_stage) {
+OwnedProgrammableStageDescriptor AsDawnType(
+ const GPUProgrammableStageDescriptor* webgpu_stage) {
DCHECK(webgpu_stage);
std::string entry_point = webgpu_stage->entryPoint().Ascii();
@@ -712,7 +711,7 @@ OwnedPipelineStageDescriptor AsDawnType(
char* entry_point_ptr = entry_point_keepalive.get();
memcpy(entry_point_ptr, entry_point.c_str(), byte_size);
- DawnPipelineStageDescriptor dawn_stage = {};
+ DawnProgrammableStageDescriptor dawn_stage = {};
dawn_stage.module = webgpu_stage->module()->GetHandle();
dawn_stage.entryPoint = entry_point_ptr;
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 b86fa804de7..7411163de4b 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
@@ -19,10 +19,11 @@
namespace blink {
-class GPUColor;
-class GPUExtent3D;
-class GPUOrigin3D;
-class GPUPipelineStageDescriptor;
+class DoubleSequenceOrGPUColorDict;
+class GPUColorDict;
+class GPUProgrammableStageDescriptor;
+class UnsignedLongSequenceOrGPUExtent3DDict;
+class UnsignedLongSequenceOrGPUOrigin3DDict;
// Convert WebGPU bitfield values to Dawn enums. These have the same value.
template <typename DawnEnum>
@@ -37,13 +38,16 @@ DawnEnum AsDawnEnum(const WTF::String& webgpu_enum);
// These conversions are used multiple times and are declared here. Conversions
// used only once, for example for object construction, are defined
// individually.
-DawnColor AsDawnType(const GPUColor*);
-DawnExtent3D AsDawnType(const GPUExtent3D*);
-DawnOrigin3D AsDawnType(const GPUOrigin3D*);
-
-using OwnedPipelineStageDescriptor =
- std::tuple<DawnPipelineStageDescriptor, std::unique_ptr<char[]>>;
-OwnedPipelineStageDescriptor AsDawnType(const GPUPipelineStageDescriptor*);
+DawnColor AsDawnColor(const Vector<double>&);
+DawnColor AsDawnType(const GPUColorDict*);
+DawnColor AsDawnType(const DoubleSequenceOrGPUColorDict*);
+DawnExtent3D AsDawnType(const UnsignedLongSequenceOrGPUExtent3DDict*);
+DawnOrigin3D AsDawnType(const UnsignedLongSequenceOrGPUOrigin3DDict*);
+
+using OwnedProgrammableStageDescriptor =
+ std::tuple<DawnProgrammableStageDescriptor, std::unique_ptr<char[]>>;
+OwnedProgrammableStageDescriptor AsDawnType(
+ const GPUProgrammableStageDescriptor*);
// WebGPU objects are converted to Dawn objects by getting the opaque handle
// which can be passed to Dawn.
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 0521f0d56e1..8ce13313c75 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.cc
@@ -12,8 +12,6 @@ DawnObjectBase::DawnObjectBase(
scoped_refptr<DawnControlClientHolder> dawn_control_client)
: dawn_control_client_(std::move(dawn_control_client)) {}
-DawnObjectBase::~DawnObjectBase() = default;
-
const scoped_refptr<DawnControlClientHolder>&
DawnObjectBase::GetDawnControlClient() const {
return dawn_control_client_;
@@ -34,6 +32,8 @@ const DawnProcTable& DawnObjectBase::GetProcs() const {
DawnObjectImpl::DawnObjectImpl(GPUDevice* device)
: DawnObjectBase(device->GetDawnControlClient()), device_(device) {}
+DawnObjectImpl::~DawnObjectImpl() = default;
+
void DawnObjectImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(device_);
ScriptWrappable::Trace(visitor);
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 06c66ace749..7b47862450a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/dawn_object.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_DAWN_OBJECT_H_
#include <dawn/dawn.h>
+#include <dawn/dawn_proc_table.h>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -28,10 +29,9 @@ class Visitor;
// The DawnControlClientHolder is used to hold the WebGPUInterface and keep
// track of whether or not the client has been destroyed. If the client is
// destroyed, we should not call any Dawn functions.
-class DawnObjectBase : public ScriptWrappable {
+class DawnObjectBase {
public:
DawnObjectBase(scoped_refptr<DawnControlClientHolder> dawn_control_client);
- ~DawnObjectBase() override;
const scoped_refptr<DawnControlClientHolder>& GetDawnControlClient() const;
bool IsDawnControlClientDestroyed() const;
@@ -42,9 +42,10 @@ class DawnObjectBase : public ScriptWrappable {
scoped_refptr<DawnControlClientHolder> dawn_control_client_;
};
-class DawnObjectImpl : public DawnObjectBase {
+class DawnObjectImpl : public ScriptWrappable, public DawnObjectBase {
public:
DawnObjectImpl(GPUDevice* device);
+ ~DawnObjectImpl() override;
void Trace(blink::Visitor* visitor) override;
@@ -57,6 +58,7 @@ class DawnObject : public DawnObjectImpl {
public:
DawnObject(GPUDevice* device, Handle handle)
: DawnObjectImpl(device), handle_(handle) {}
+ ~DawnObject() override = default;
Handle GetHandle() const { return handle_; }
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
index d4829e40c57..75c64330192 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -57,7 +57,7 @@ void GPU::Trace(blink::Visitor* visitor) {
}
void GPU::ContextDestroyed(ExecutionContext* execution_context) {
- dawn_control_client_->MarkDestroyed();
+ dawn_control_client_->Destroy();
}
ScriptPromise GPU::requestAdapter(ScriptState* script_state,
@@ -65,16 +65,14 @@ ScriptPromise GPU::requestAdapter(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- if (options->powerPreference()) {
- ExecutionContext::From(script_state)
- ->AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning,
- "The powerPreference option is not implemented yet."));
+ // For now we choose kHighPerformance by default.
+ gpu::webgpu::PowerPreference power_preference =
+ gpu::webgpu::PowerPreference::kHighPerformance;
+ if (options->powerPreference() == "low-power") {
+ power_preference = gpu::webgpu::PowerPreference::kLowPower;
}
-
- // TODO(enga): Request the adapter from the WebGPUInterface.
- GPUAdapter* adapter = GPUAdapter::Create("Default", dawn_control_client_);
+ GPUAdapter* adapter =
+ GPUAdapter::Create("Default", power_preference, dawn_control_client_);
resolver->Resolve(adapter);
return promise;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu.idl
index 2e5f6ebf708..393ae11f7f8 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.idl
@@ -4,11 +4,16 @@
// https://gpuweb.github.io/gpuweb/
+typedef unsigned long long GPUBufferSize;
+typedef (sequence<double> or GPUColorDict) GPUColor;
+typedef (sequence<unsigned long> or GPUExtent3DDict) GPUExtent3D;
+typedef (sequence<unsigned long> or GPUOrigin3DDict) GPUOrigin3D;
+
[
RuntimeEnabled=WebGPU
] interface GPU {
[
RuntimeEnabled=WebGPU,
CallWith=ScriptState
- ] Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options);
+ ] Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {});
};
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 4e89c557d38..4c262c61aa5 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -6,20 +6,26 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_request_adapter_options.h"
namespace blink {
// static
GPUAdapter* GPUAdapter::Create(
const String& name,
+ gpu::webgpu::PowerPreference power_preference,
scoped_refptr<DawnControlClientHolder> dawn_control_client) {
- return MakeGarbageCollected<GPUAdapter>(name, std::move(dawn_control_client));
+ return MakeGarbageCollected<GPUAdapter>(name, power_preference,
+ std::move(dawn_control_client));
}
GPUAdapter::GPUAdapter(
const String& name,
+ gpu::webgpu::PowerPreference power_preference,
scoped_refptr<DawnControlClientHolder> dawn_control_client)
- : DawnObjectBase(std::move(dawn_control_client)), name_(name) {}
+ : DawnObjectBase(dawn_control_client), name_(name) {
+ dawn_control_client->GetInterface()->RequestAdapter(power_preference);
+}
const String& GPUAdapter::name() const {
return name_;
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 abc9594273d..afbed689c85 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_ADAPTER_H_
#include "base/memory/scoped_refptr.h"
+#include "gpu/command_buffer/client/webgpu_interface.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
@@ -16,14 +17,16 @@ namespace blink {
class GPUDeviceDescriptor;
-class GPUAdapter final : public DawnObjectBase {
+class GPUAdapter final : public ScriptWrappable, public DawnObjectBase {
DEFINE_WRAPPERTYPEINFO();
public:
static GPUAdapter* Create(
const String& name,
+ gpu::webgpu::PowerPreference power_preference,
scoped_refptr<DawnControlClientHolder> dawn_control_client);
GPUAdapter(const String& name,
+ gpu::webgpu::PowerPreference power_preference,
scoped_refptr<DawnControlClientHolder> dawn_control_client);
const String& name() const;
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 4edcf4170ee..0c14346816e 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -9,5 +9,5 @@
] interface GPUAdapter {
readonly attribute DOMString name;
- [CallWith=ScriptState] Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor);
+ [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 63333d41e73..0aee4c2b18d 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
@@ -59,6 +59,9 @@ GPUBindGroup* GPUBindGroup::Create(GPUDevice* device,
dawn_desc.layout = AsDawnType(webgpu_desc->layout());
dawn_desc.bindingCount = binding_count;
dawn_desc.bindings = bindings.get();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return MakeGarbageCollected<GPUBindGroup>(
device, device->GetProcs().deviceCreateBindGroup(device->GetHandle(),
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl
index ab56efc0743..c347eed9402 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUBindGroupDescriptor {
+dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
required GPUBindGroupLayout layout;
required sequence<GPUBindGroupBinding> bindings;
};
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 859082ccf42..3bc7266415c 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
@@ -18,10 +18,12 @@ DawnBindGroupLayoutBinding AsDawnType(
dawn_binding.type = AsDawnEnum<DawnBindingType>(webgpu_binding->type());
dawn_binding.visibility =
AsDawnEnum<DawnShaderStage>(webgpu_binding->visibility());
+ dawn_binding.textureDimension =
+ AsDawnEnum<DawnTextureViewDimension>(webgpu_binding->textureDimension());
dawn_binding.textureComponentType = AsDawnEnum<DawnTextureComponentType>(
webgpu_binding->textureComponentType());
dawn_binding.multisampled = webgpu_binding->multisampled();
- dawn_binding.dynamic = webgpu_binding->dynamic();
+ dawn_binding.hasDynamicOffset = webgpu_binding->hasDynamicOffset();
return dawn_binding;
}
@@ -43,6 +45,9 @@ GPUBindGroupLayout* GPUBindGroupLayout::Create(
dawn_desc.nextInChain = nullptr;
dawn_desc.bindingCount = binding_count;
dawn_desc.bindings = bindings.get();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return MakeGarbageCollected<GPUBindGroupLayout>(
device, device->GetProcs().deviceCreateBindGroupLayout(
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl
index 372f4086b14..141823e5bf2 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_binding.idl
@@ -8,9 +8,10 @@ dictionary GPUBindGroupLayoutBinding {
required unsigned long binding;
required GPUShaderStageFlags visibility;
required GPUBindingType type;
+ GPUTextureViewDimension textureDimension = "2d";
GPUTextureComponentType textureComponentType = "float";
boolean multisampled = false;
- boolean dynamic = false;
+ boolean hasDynamicOffset = false;
};
enum GPUBindingType {
@@ -19,6 +20,7 @@ enum GPUBindingType {
"readonly-storage-buffer",
"sampler",
"sampled-texture",
+ "storage-texture",
};
enum GPUTextureComponentType {
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl
index 74663eabc35..96f07ac5e21 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout_descriptor.idl
@@ -4,6 +4,6 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUBindGroupLayoutDescriptor {
+dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupLayoutBinding> bindings;
};
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 a17386b6426..81e8cfbd89d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -51,6 +51,9 @@ DawnBufferDescriptor AsDawnType(const GPUBufferDescriptor* webgpu_desc) {
dawn_desc.nextInChain = nullptr;
dawn_desc.usage = AsDawnEnum<DawnBufferUsage>(webgpu_desc->usage());
dawn_desc.size = webgpu_desc->size();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl
index e3ee3c6fb99..af62cf63455 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_binding.idl
@@ -6,7 +6,7 @@
dictionary GPUBufferBinding {
required GPUBuffer buffer;
- unsigned long long offset = 0;
+ GPUBufferSize offset = 0;
// If size is undefined, use the whole size of the buffer.
- unsigned long long size;
+ GPUBufferSize size;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl
index 0ba2fb0edbb..2b18ef078bf 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.idl
@@ -6,7 +6,7 @@
dictionary GPUBufferCopyView {
required GPUBuffer buffer;
- unsigned long long offset = 0;
+ GPUBufferSize offset = 0;
required unsigned long rowPitch;
required unsigned long imageHeight;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl
index f36194db5ca..27216d32484 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUBufferDescriptor {
- required unsigned long long size;
+dictionary GPUBufferDescriptor : GPUObjectDescriptorBase {
+ required GPUBufferSize size;
required GPUBufferUsageFlags usage;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.h
index 01924b0043e..5c922e7e413 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.h
@@ -14,7 +14,6 @@ class GPUBufferUsage : public ScriptWrappable {
public:
// gpu_buffer_usage.idl
- static constexpr uint32_t kNone = 0;
static constexpr uint32_t kMapRead = 1;
static constexpr uint32_t kMapWrite = 2;
static constexpr uint32_t kCopySrc = 4;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl
index 981d67faaa0..b49cc104204 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_buffer_usage.idl
@@ -8,14 +8,13 @@ typedef unsigned long GPUBufferUsageFlags;
[
RuntimeEnabled=WebGPU
] interface GPUBufferUsage {
- const unsigned long NONE = 0;
- const unsigned long MAP_READ = 1;
- const unsigned long MAP_WRITE = 2;
- const unsigned long COPY_SRC = 4;
- const unsigned long COPY_DST = 8;
- const unsigned long INDEX = 16;
- const unsigned long VERTEX = 32;
- const unsigned long UNIFORM = 64;
- const unsigned long STORAGE = 128;
- const unsigned long INDIRECT = 256;
+ const GPUBufferUsageFlags MAP_READ = 1;
+ const GPUBufferUsageFlags MAP_WRITE = 2;
+ const GPUBufferUsageFlags COPY_SRC = 4;
+ const GPUBufferUsageFlags COPY_DST = 8;
+ const GPUBufferUsageFlags INDEX = 16;
+ const GPUBufferUsageFlags VERTEX = 32;
+ const GPUBufferUsageFlags UNIFORM = 64;
+ const GPUBufferUsageFlags STORAGE = 128;
+ const GPUBufferUsageFlags INDIRECT = 256;
};
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 5c5f063093e..773faf3070d 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
@@ -80,4 +80,17 @@ GPUSwapChain* GPUCanvasContext::configureSwapChain(
return swapchain_;
}
+ScriptPromise GPUCanvasContext::getSwapChainPreferredFormat(
+ ScriptState* script_state,
+ const GPUDevice* device) {
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO(crbug.com/1007166): Return actual preferred format for the swap chain.
+ resolver->Resolve("bgra8unorm");
+
+ return promise;
+}
+
} // 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 03602229816..e5d4c54ef62 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
@@ -45,7 +45,7 @@ class GPUCanvasContext : public CanvasRenderingContext {
// CanvasRenderingContext implementation
ContextType GetContextType() const override;
void SetCanvasGetContextResult(RenderingContext&) final;
- scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final {
+ scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) final {
return nullptr;
}
void SetIsHidden(bool) override {}
@@ -62,6 +62,8 @@ class GPUCanvasContext : public CanvasRenderingContext {
// gpu_canvas_context.idl
GPUSwapChain* configureSwapChain(const GPUSwapChainDescriptor* descriptor);
+ ScriptPromise getSwapChainPreferredFormat(ScriptState* script_state,
+ const GPUDevice* device);
private:
DISALLOW_COPY_AND_ASSIGN(GPUCanvasContext);
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 5e4ac97377a..feb476c9ab5 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
@@ -8,4 +8,6 @@
RuntimeEnabled=WebGPU
] interface GPUCanvasContext {
GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor);
+
+ [CallWith=ScriptState] Promise<GPUTextureFormat> getSwapChainPreferredFormat(GPUDevice device);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl
new file mode 100644
index 00000000000..1759ca47004
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl
@@ -0,0 +1,12 @@
+// 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/
+
+dictionary GPUColorDict {
+ required double r;
+ required double g;
+ required double b;
+ required double a;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
index 165f7594fa2..07e114c7cda 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
@@ -7,7 +7,7 @@
dictionary GPUColorStateDescriptor {
required GPUTextureFormat format;
- GPUBlendDescriptor alphaBlend;
- GPUBlendDescriptor colorBlend;
+ GPUBlendDescriptor alphaBlend = {};
+ GPUBlendDescriptor colorBlend = {};
GPUColorWriteFlags writeMask = 15; // GPUColorWrite.ALL
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.h
index 429220b4d5e..4df070ed6b8 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.h
@@ -14,7 +14,6 @@ class GPUColorWrite : public ScriptWrappable {
public:
// gpu_color_write.idl
- static constexpr uint32_t kNone = 0;
static constexpr uint32_t kRed = 1;
static constexpr uint32_t kGreen = 2;
static constexpr uint32_t kBlue = 4;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl
index a28647f7112..a71fbafd0f2 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_color_write.idl
@@ -8,10 +8,9 @@ typedef unsigned long GPUColorWriteFlags;
[
RuntimeEnabled=WebGPU
] interface GPUColorWrite {
- const unsigned long NONE = 0;
- const unsigned long RED = 1;
- const unsigned long GREEN = 2;
- const unsigned long BLUE = 4;
- const unsigned long ALPHA = 8;
- const unsigned long ALL = 15;
+ const GPUColorWriteFlags RED = 1;
+ const GPUColorWriteFlags GREEN = 2;
+ const GPUColorWriteFlags BLUE = 4;
+ const GPUColorWriteFlags ALPHA = 8;
+ const GPUColorWriteFlags ALL = 15;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_buffer_descriptor.idl
index 3055ed714c4..700ed995e07 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_color.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_buffer_descriptor.idl
@@ -4,9 +4,5 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUColor {
- required float r;
- required float g;
- required float b;
- required float a;
+dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
};
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 438330e58cc..3afc4108da6 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,15 +4,18 @@
#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_sequence_or_gpu_extent_3d_dict.h"
+#include "third_party/blink/renderer/bindings/modules/v8/unsigned_long_sequence_or_gpu_origin_3d_dict.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_buffer_copy_view.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_compute_pass_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_extent_3d.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_origin_3d.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_color_attachment_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_descriptor.h"
@@ -23,6 +26,31 @@
namespace blink {
+bool ValidateCopySize(UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state) {
+ if (copy_size.IsUnsignedLongSequence() &&
+ copy_size.GetAsUnsignedLongSequence().size() != 3) {
+ exception_state.ThrowRangeError("copySize length must be 3");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateTextureCopyView(GPUTextureCopyView* texture_copy_view,
+ ExceptionState& exception_state) {
+ DCHECK(texture_copy_view);
+
+ const UnsignedLongSequenceOrGPUOrigin3DDict origin =
+ texture_copy_view->origin();
+ if (origin.IsUnsignedLongSequence() &&
+ origin.GetAsUnsignedLongSequence().size() != 3) {
+ exception_state.ThrowRangeError(
+ "texture copy view origin length must be 3");
+ return false;
+ }
+ return true;
+}
+
DawnRenderPassColorAttachmentDescriptor AsDawnType(
const GPURenderPassColorAttachmentDescriptor* webgpu_desc) {
DCHECK(webgpu_desc);
@@ -37,8 +65,14 @@ DawnRenderPassColorAttachmentDescriptor AsDawnType(
const WTF::String& gpuLoadOp = webgpu_desc->loadValue().GetAsGPULoadOp();
dawn_desc.loadOp = AsDawnEnum<DawnLoadOp>(gpuLoadOp);
- } else if (webgpu_desc->loadValue().IsGPUColor()) {
- GPUColor* gpuColor = webgpu_desc->loadValue().GetAsGPUColor();
+ } else if (webgpu_desc->loadValue().IsDoubleSequence()) {
+ const Vector<double>& gpuColor =
+ webgpu_desc->loadValue().GetAsDoubleSequence();
+ dawn_desc.loadOp = DAWN_LOAD_OP_CLEAR;
+ dawn_desc.clearColor = AsDawnColor(gpuColor);
+
+ } else if (webgpu_desc->loadValue().IsGPUColorDict()) {
+ const GPUColorDict* gpuColor = webgpu_desc->loadValue().GetAsGPUColorDict();
dawn_desc.loadOp = DAWN_LOAD_OP_CLEAR;
dawn_desc.clearColor = AsDawnType(gpuColor);
@@ -82,9 +116,10 @@ DawnRenderPassDepthStencilAttachmentDescriptor AsDawnType(
dawn_desc.stencilLoadOp = AsDawnEnum<DawnLoadOp>(gpuLoadOp);
dawn_desc.clearStencil = 0;
- } else if (webgpu_desc->stencilLoadValue().IsLong()) {
+ } else if (webgpu_desc->stencilLoadValue().IsUnsignedLong()) {
dawn_desc.stencilLoadOp = DAWN_LOAD_OP_CLEAR;
- dawn_desc.clearStencil = webgpu_desc->stencilLoadValue().GetAsLong();
+ dawn_desc.clearStencil =
+ webgpu_desc->stencilLoadValue().GetAsUnsignedLong();
} else {
NOTREACHED();
@@ -119,7 +154,7 @@ DawnTextureCopyView AsDawnType(const GPUTextureCopyView* webgpu_view) {
dawn_view.texture = webgpu_view->texture()->GetHandle();
dawn_view.mipLevel = webgpu_view->mipLevel();
dawn_view.arrayLayer = webgpu_view->arrayLayer();
- dawn_view.origin = AsDawnType(webgpu_view->origin());
+ dawn_view.origin = AsDawnType(&webgpu_view->origin());
return dawn_view;
}
@@ -130,6 +165,9 @@ DawnCommandEncoderDescriptor AsDawnType(
DawnCommandEncoderDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
@@ -168,33 +206,39 @@ GPUCommandEncoder::~GPUCommandEncoder() {
}
GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass(
- const GPURenderPassDescriptor* descriptor) {
+ const GPURenderPassDescriptor* descriptor,
+ ExceptionState& exception_state) {
DCHECK(descriptor);
uint32_t color_attachment_count =
static_cast<uint32_t>(descriptor->colorAttachments().size());
+ // Check loadValue color is correctly formatted before further processing.
+ for (wtf_size_t i = 0; i < color_attachment_count; ++i) {
+ const GPURenderPassColorAttachmentDescriptor* color_attachment =
+ descriptor->colorAttachments()[i];
+ const GPULoadOpOrDoubleSequenceOrGPUColorDict load_value =
+ color_attachment->loadValue();
+
+ if (load_value.IsDoubleSequence() &&
+ load_value.GetAsDoubleSequence().size() != 4) {
+ exception_state.ThrowRangeError("loadValue color size must be 4");
+ return nullptr;
+ }
+ }
+
DawnRenderPassDescriptor dawn_desc = {};
dawn_desc.colorAttachmentCount = color_attachment_count;
dawn_desc.colorAttachments = nullptr;
+ if (descriptor->hasLabel()) {
+ dawn_desc.label = descriptor->label().Utf8().data();
+ }
- using DescriptorPtr = DawnRenderPassColorAttachmentDescriptor*;
- using DescriptorArray = DawnRenderPassColorAttachmentDescriptor[];
- using DescriptorPtrArray = DescriptorPtr[];
-
- std::unique_ptr<DescriptorArray> color_attachments;
- std::unique_ptr<DescriptorPtrArray> color_attachment_ptrs;
+ std::unique_ptr<DawnRenderPassColorAttachmentDescriptor[]> color_attachments;
if (color_attachment_count > 0) {
color_attachments = AsDawnType(descriptor->colorAttachments());
-
- color_attachment_ptrs = std::unique_ptr<DescriptorPtrArray>(
- new DescriptorPtr[color_attachment_count]);
-
- for (uint32_t i = 0; i < color_attachment_count; ++i) {
- color_attachment_ptrs[i] = color_attachments.get() + i;
- }
- dawn_desc.colorAttachments = color_attachment_ptrs.get();
+ dawn_desc.colorAttachments = color_attachments.get();
}
DawnRenderPassDepthStencilAttachmentDescriptor depthStencilAttachment = {};
@@ -210,9 +254,16 @@ GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass(
GetProcs().commandEncoderBeginRenderPass(GetHandle(), &dawn_desc));
}
-GPUComputePassEncoder* GPUCommandEncoder::beginComputePass() {
+GPUComputePassEncoder* GPUCommandEncoder::beginComputePass(
+ const GPUComputePassDescriptor* descriptor) {
+ DawnComputePassDescriptor dawn_desc = {};
+ if (descriptor->hasLabel()) {
+ dawn_desc.label = descriptor->label().Utf8().data();
+ }
+
return GPUComputePassEncoder::Create(
- device_, GetProcs().commandEncoderBeginComputePass(GetHandle(), nullptr));
+ device_,
+ GetProcs().commandEncoderBeginComputePass(GetHandle(), &dawn_desc));
}
void GPUCommandEncoder::copyBufferToBuffer(GPUBuffer* src,
@@ -227,42 +278,84 @@ void GPUCommandEncoder::copyBufferToBuffer(GPUBuffer* src,
dst_offset, size);
}
-void GPUCommandEncoder::copyBufferToTexture(GPUBufferCopyView* source,
- GPUTextureCopyView* destination,
- GPUExtent3D* copy_size) {
+void GPUCommandEncoder::copyBufferToTexture(
+ GPUBufferCopyView* source,
+ GPUTextureCopyView* destination,
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state) {
+ if (!ValidateCopySize(copy_size, exception_state) ||
+ !ValidateTextureCopyView(destination, exception_state)) {
+ return;
+ }
+
DawnBufferCopyView dawn_source = AsDawnType(source);
DawnTextureCopyView dawn_destination = AsDawnType(destination);
- DawnExtent3D dawn_copy_size = AsDawnType(copy_size);
+ DawnExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyBufferToTexture(
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
}
-void GPUCommandEncoder::copyTextureToBuffer(GPUTextureCopyView* source,
- GPUBufferCopyView* destination,
- GPUExtent3D* copy_size) {
+void GPUCommandEncoder::copyTextureToBuffer(
+ GPUTextureCopyView* source,
+ GPUBufferCopyView* destination,
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state) {
+ if (!ValidateCopySize(copy_size, exception_state) ||
+ !ValidateTextureCopyView(source, exception_state)) {
+ return;
+ }
+
DawnTextureCopyView dawn_source = AsDawnType(source);
DawnBufferCopyView dawn_destination = AsDawnType(destination);
- DawnExtent3D dawn_copy_size = AsDawnType(copy_size);
+ DawnExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyTextureToBuffer(
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
}
-void GPUCommandEncoder::copyTextureToTexture(GPUTextureCopyView* source,
- GPUTextureCopyView* destination,
- GPUExtent3D* copy_size) {
+void GPUCommandEncoder::copyTextureToTexture(
+ GPUTextureCopyView* source,
+ GPUTextureCopyView* destination,
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state) {
+ if (!ValidateCopySize(copy_size, exception_state) ||
+ !ValidateTextureCopyView(source, exception_state) ||
+ !ValidateTextureCopyView(destination, exception_state)) {
+ return;
+ }
+
DawnTextureCopyView dawn_source = AsDawnType(source);
DawnTextureCopyView dawn_destination = AsDawnType(destination);
- DawnExtent3D dawn_copy_size = AsDawnType(copy_size);
+ DawnExtent3D dawn_copy_size = AsDawnType(&copy_size);
GetProcs().commandEncoderCopyTextureToTexture(
GetHandle(), &dawn_source, &dawn_destination, &dawn_copy_size);
}
-GPUCommandBuffer* GPUCommandEncoder::finish() {
+void GPUCommandEncoder::pushDebugGroup(String groupLabel) {
+ GetProcs().commandEncoderPushDebugGroup(GetHandle(),
+ groupLabel.Utf8().data());
+}
+
+void GPUCommandEncoder::popDebugGroup() {
+ GetProcs().commandEncoderPopDebugGroup(GetHandle());
+}
+
+void GPUCommandEncoder::insertDebugMarker(String markerLabel) {
+ GetProcs().commandEncoderInsertDebugMarker(GetHandle(),
+ markerLabel.Utf8().data());
+}
+
+GPUCommandBuffer* GPUCommandEncoder::finish(
+ const GPUCommandBufferDescriptor* descriptor) {
+ DawnCommandBufferDescriptor dawn_desc = {};
+ if (descriptor->hasLabel()) {
+ dawn_desc.label = descriptor->label().Utf8().data();
+ }
+
return GPUCommandBuffer::Create(
- device_, GetProcs().commandEncoderFinish(GetHandle(), nullptr));
+ device_, GetProcs().commandEncoderFinish(GetHandle(), &dawn_desc));
}
} // namespace blink
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 adb50dc5bec..d00bb828491 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
@@ -6,18 +6,22 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_COMMAND_ENCODER_H_
#include "third_party/blink/renderer/modules/webgpu/dawn_object.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
+class ExceptionState;
class GPUBuffer;
class GPUBufferCopyView;
class GPUCommandBuffer;
+class GPUCommandBufferDescriptor;
class GPUCommandEncoderDescriptor;
+class GPUComputePassDescriptor;
class GPUComputePassEncoder;
-class GPUExtent3D;
class GPURenderPassDescriptor;
class GPURenderPassEncoder;
class GPUTextureCopyView;
+class UnsignedLongSequenceOrGPUExtent3DDict;
class GPUCommandEncoder : public DawnObject<DawnCommandEncoder> {
DEFINE_WRAPPERTYPEINFO();
@@ -32,8 +36,10 @@ class GPUCommandEncoder : public DawnObject<DawnCommandEncoder> {
// gpu_command_encoder.idl
GPURenderPassEncoder* beginRenderPass(
- const GPURenderPassDescriptor* descriptor);
- GPUComputePassEncoder* beginComputePass();
+ const GPURenderPassDescriptor* descriptor,
+ ExceptionState& exception_state);
+ GPUComputePassEncoder* beginComputePass(
+ const GPUComputePassDescriptor* descriptor);
void copyBufferToBuffer(GPUBuffer* src,
uint64_t src_offset,
GPUBuffer* dst,
@@ -41,14 +47,20 @@ class GPUCommandEncoder : public DawnObject<DawnCommandEncoder> {
uint64_t size);
void copyBufferToTexture(GPUBufferCopyView* source,
GPUTextureCopyView* destination,
- GPUExtent3D* copy_size);
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state);
void copyTextureToBuffer(GPUTextureCopyView* source,
GPUBufferCopyView* destination,
- GPUExtent3D* copy_size);
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state);
void copyTextureToTexture(GPUTextureCopyView* source,
GPUTextureCopyView* destination,
- GPUExtent3D* copy_size);
- GPUCommandBuffer* finish();
+ UnsignedLongSequenceOrGPUExtent3DDict& copy_size,
+ ExceptionState& exception_state);
+ void pushDebugGroup(String groupLabel);
+ void popDebugGroup();
+ void insertDebugMarker(String markerLabel);
+ GPUCommandBuffer* finish(const GPUCommandBufferDescriptor* descriptor);
private:
DISALLOW_COPY_AND_ASSIGN(GPUCommandEncoder);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
index 1a76aca161f..574ec01e66b 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
@@ -7,28 +7,34 @@
[
RuntimeEnabled=WebGPU
] interface GPUCommandEncoder {
- GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
- GPUComputePassEncoder beginComputePass();
+ [RaisesException] GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
+ GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});
void copyBufferToBuffer(
- GPUBuffer src, unsigned long long srcOffset,
- GPUBuffer dst, unsigned long long dstOffset,
- unsigned long long size);
+ GPUBuffer src,
+ GPUBufferSize srcOffset,
+ GPUBuffer dst,
+ GPUBufferSize dstOffset,
+ GPUBufferSize size);
- void copyBufferToTexture(
+ [RaisesException] void copyBufferToTexture(
GPUBufferCopyView source,
GPUTextureCopyView destination,
GPUExtent3D copySize);
- void copyTextureToBuffer(
+ [RaisesException] void copyTextureToBuffer(
GPUTextureCopyView source,
GPUBufferCopyView destination,
GPUExtent3D copySize);
- void copyTextureToTexture(
+ [RaisesException] void copyTextureToTexture(
GPUTextureCopyView source,
GPUTextureCopyView destination,
GPUExtent3D copySize);
- GPUCommandBuffer finish();
+ void pushDebugGroup(DOMString groupLabel);
+ void popDebugGroup();
+ void insertDebugMarker(DOMString markerLabel);
+
+ GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl
index 0cef584d579..e28ac16410c 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_command_encoder_descriptor.idl
@@ -4,5 +4,5 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUCommandEncoderDescriptor {
+dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_descriptor.idl
index d1359bac418..5dcd9e84457 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_descriptor.idl
@@ -4,8 +4,5 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUOrigin3D {
- required unsigned long x;
- required unsigned long y;
- required unsigned long z;
+dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
index 75149c6848e..dd75cea414b 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
@@ -7,21 +7,13 @@
[
RuntimeEnabled=WebGPU
] interface GPUComputePassEncoder {
- // GPUProgrammablePassEncoder methods
- void setBindGroup(unsigned long index,
- GPUBindGroup bindGroup,
- optional sequence<unsigned long long> dynamicOffsets = []);
- void pushDebugGroup(DOMString groupLabel);
- void popDebugGroup();
- void insertDebugMarker(DOMString markerLabel);
-
void setPipeline(GPUComputePipeline pipeline);
-
void dispatch(unsigned long x,
optional unsigned long y = 1,
optional unsigned long z = 1);
void dispatchIndirect(GPUBuffer indirectBuffer,
- unsigned long long indirectOffset);
+ GPUBufferSize indirectOffset);
void endPass();
};
+GPUComputePassEncoder includes GPUProgrammablePassEncoder;
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 f3ab8365659..4da7c3c5a23 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
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_shader_module.h"
namespace blink {
@@ -23,6 +23,9 @@ GPUComputePipeline* GPUComputePipeline::Create(
DawnComputePipelineDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
dawn_desc.layout = AsDawnType(webgpu_desc->layout());
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
auto compute_stage = AsDawnType(webgpu_desc->computeStage());
dawn_desc.computeStage = std::get<0>(compute_stage);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl
index aefb71c1512..6d6d8fd23ea 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline_descriptor.idl
@@ -5,5 +5,5 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
- required GPUPipelineStageDescriptor computeStage;
+ required GPUProgrammableStageDescriptor computeStage;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl
index 03f2efe2066..9bf8f07ac93 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_depth_stencil_state_descriptor.idl
@@ -10,8 +10,8 @@ dictionary GPUDepthStencilStateDescriptor {
boolean depthWriteEnabled = false;
GPUCompareFunction depthCompare = "always";
- required GPUStencilStateFaceDescriptor stencilFront;
- required GPUStencilStateFaceDescriptor stencilBack;
+ GPUStencilStateFaceDescriptor stencilFront = {};
+ GPUStencilStateFaceDescriptor stencilBack = {};
unsigned long stencilReadMask = 0xFFFFFFFF;
unsigned long stencilWriteMask = 0xFFFFFFFF;
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 cee563d23e6..1604383f6c8 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -7,8 +7,10 @@
#include "gpu/command_buffer/client/webgpu_interface.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.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"
+#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_bind_group.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.h"
@@ -16,6 +18,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_descriptor.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_queue.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h"
@@ -23,6 +26,8 @@
#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_texture.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event_init.h"
namespace blink {
@@ -41,10 +46,14 @@ GPUDevice::GPUDevice(ExecutionContext* execution_context,
scoped_refptr<DawnControlClientHolder> dawn_control_client,
GPUAdapter* adapter,
const GPUDeviceDescriptor* descriptor)
- : DawnObject(dawn_control_client,
+ : ContextClient(execution_context),
+ DawnObject(dawn_control_client,
dawn_control_client->GetInterface()->GetDefaultDevice()),
adapter_(adapter),
queue_(GPUQueue::Create(this, GetProcs().deviceCreateQueue(GetHandle()))),
+ lost_property_(MakeGarbageCollected<LostProperty>(execution_context,
+ this,
+ LostProperty::kLost)),
error_callback_(
BindRepeatingDawnCallback(&GPUDevice::OnUncapturedError,
WrapWeakPersistent(this),
@@ -72,17 +81,44 @@ void GPUDevice::OnUncapturedError(ExecutionContext* execution_context,
mojom::ConsoleMessageLevel::kWarning, message);
execution_context->AddConsoleMessage(console_message);
}
+
+ // TODO: Use device lost callback instead of uncaptured error callback.
+ if (errorType == DAWN_ERROR_TYPE_DEVICE_LOST &&
+ lost_property_->GetState() == ScriptPromisePropertyBase::kPending) {
+ GPUDeviceLostInfo* device_lost_info = GPUDeviceLostInfo::Create(message);
+ lost_property_->Resolve(device_lost_info);
+ }
+
+ GPUUncapturedErrorEventInit* init = GPUUncapturedErrorEventInit::Create();
+ if (errorType == DAWN_ERROR_TYPE_VALIDATION) {
+ GPUValidationError* error = GPUValidationError::Create(message);
+ init->setError(
+ GPUOutOfMemoryErrorOrGPUValidationError::FromGPUValidationError(error));
+ } else if (errorType == DAWN_ERROR_TYPE_OUT_OF_MEMORY) {
+ GPUOutOfMemoryError* error = GPUOutOfMemoryError::Create();
+ init->setError(
+ GPUOutOfMemoryErrorOrGPUValidationError::FromGPUOutOfMemoryError(
+ error));
+ } else {
+ return;
+ }
+ this->DispatchEvent(*GPUUncapturedErrorEvent::Create(
+ event_type_names::kUncapturederror, init));
}
GPUAdapter* GPUDevice::adapter() const {
return adapter_;
}
+ScriptPromise GPUDevice::lost(ScriptState* script_state) {
+ return lost_property_->Promise(script_state->World());
+}
+
GPUBuffer* GPUDevice::createBuffer(const GPUBufferDescriptor* descriptor) {
return GPUBuffer::Create(this, descriptor);
}
-WTF::Vector<ScriptValue> GPUDevice::createBufferMapped(
+HeapVector<ScriptValue> GPUDevice::createBufferMapped(
ScriptState* script_state,
const GPUBufferDescriptor* descriptor,
ExceptionState& exception_state) {
@@ -94,9 +130,9 @@ WTF::Vector<ScriptValue> GPUDevice::createBufferMapped(
v8::Isolate* isolate = script_state->GetIsolate();
v8::Local<v8::Object> creation_context = script_state->GetContext()->Global();
- return WTF::Vector<ScriptValue>({
- ScriptValue(script_state, ToV8(gpu_buffer, creation_context, isolate)),
- ScriptValue(script_state, ToV8(array_buffer, creation_context, isolate)),
+ return HeapVector<ScriptValue>({
+ ScriptValue(isolate, ToV8(gpu_buffer, creation_context, isolate)),
+ ScriptValue(isolate, ToV8(array_buffer, creation_context, isolate)),
});
}
@@ -117,7 +153,7 @@ ScriptPromise GPUDevice::createBufferMappedAsync(
ToV8(array_buffer, creation_context, isolate),
};
- ScriptValue result(script_state, v8::Array::New(isolate, elements, 2));
+ ScriptValue result(isolate, v8::Array::New(isolate, elements, 2));
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
@@ -137,8 +173,9 @@ ScriptPromise GPUDevice::createBufferMappedAsync(
return promise;
}
-GPUTexture* GPUDevice::createTexture(const GPUTextureDescriptor* descriptor) {
- return GPUTexture::Create(this, descriptor);
+GPUTexture* GPUDevice::createTexture(const GPUTextureDescriptor* descriptor,
+ ExceptionState& exception_state) {
+ return GPUTexture::Create(this, descriptor, exception_state);
}
GPUSampler* GPUDevice::createSampler(const GPUSamplerDescriptor* descriptor) {
@@ -190,10 +227,74 @@ GPUQueue* GPUDevice::getQueue() {
return queue_;
}
+void GPUDevice::pushErrorScope(const WTF::String& filter) {
+ GetProcs().devicePushErrorScope(GetHandle(),
+ AsDawnEnum<DawnErrorFilter>(filter));
+}
+
+ScriptPromise GPUDevice::popErrorScope(ScriptState* script_state) {
+ ScriptPromiseResolver* resolver =
+ MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ auto* callback =
+ BindDawnCallback(&GPUDevice::OnPopErrorScopeCallback,
+ WrapPersistent(this), WrapPersistent(resolver));
+
+ if (!GetProcs().devicePopErrorScope(GetHandle(), callback->UnboundCallback(),
+ callback->AsUserdata())) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError, "No error scopes to pop."));
+ delete callback;
+ return promise;
+ }
+
+ // WebGPU guarantees callbacks complete in finite time. Flush now so that
+ // commands reach the GPU process. TODO(enga): This should happen at the end
+ // of the task.
+ GetInterface()->FlushCommands();
+
+ return promise;
+}
+
+void GPUDevice::OnPopErrorScopeCallback(ScriptPromiseResolver* resolver,
+ DawnErrorType type,
+ const char* message) {
+ v8::Isolate* isolate = resolver->GetScriptState()->GetIsolate();
+ switch (type) {
+ case DAWN_ERROR_TYPE_NO_ERROR:
+ resolver->Resolve(v8::Null(isolate));
+ break;
+ case DAWN_ERROR_TYPE_OUT_OF_MEMORY:
+ resolver->Resolve(GPUOutOfMemoryError::Create());
+ break;
+ case DAWN_ERROR_TYPE_VALIDATION:
+ resolver->Resolve(GPUValidationError::Create(message));
+ break;
+ case DAWN_ERROR_TYPE_UNKNOWN:
+ case DAWN_ERROR_TYPE_DEVICE_LOST:
+ resolver->Reject(
+ MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+ExecutionContext* GPUDevice::GetExecutionContext() const {
+ return ContextClient::GetExecutionContext();
+}
+
+const AtomicString& GPUDevice::InterfaceName() const {
+ return event_target_names::kGPUDevice;
+}
+
void GPUDevice::Trace(blink::Visitor* visitor) {
visitor->Trace(adapter_);
visitor->Trace(queue_);
- DawnObject<DawnDevice>::Trace(visitor);
+ visitor->Trace(lost_property_);
+ ContextClient::Trace(visitor);
+ EventTargetWithInlineData::Trace(visitor);
}
} // 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 e2b11122e7d..1f172691fae 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -7,6 +7,9 @@
#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/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"
@@ -26,6 +29,7 @@ class GPUBindGroupLayoutDescriptor;
class GPUComputePipeline;
class GPUComputePipelineDescriptor;
class GPUDeviceDescriptor;
+class GPUDeviceLostInfo;
class GPUPipelineLayout;
class GPUPipelineLayoutDescriptor;
class GPUQueue;
@@ -39,9 +43,13 @@ class GPUShaderModule;
class GPUShaderModuleDescriptor;
class GPUTexture;
class GPUTextureDescriptor;
+class ScriptPromiseResolver;
class ScriptState;
-class GPUDevice final : public DawnObject<DawnDevice> {
+class GPUDevice final : public EventTargetWithInlineData,
+ public ContextClient,
+ public DawnObject<DawnDevice> {
+ USING_GARBAGE_COLLECTED_MIXIN(GPUDevice);
DEFINE_WRAPPERTYPEINFO();
public:
@@ -60,16 +68,18 @@ class GPUDevice final : public DawnObject<DawnDevice> {
// gpu_device.idl
GPUAdapter* adapter() const;
+ ScriptPromise lost(ScriptState* script_state);
GPUBuffer* createBuffer(const GPUBufferDescriptor* descriptor);
- WTF::Vector<ScriptValue> createBufferMapped(
+ HeapVector<ScriptValue> createBufferMapped(
ScriptState* script_state,
const GPUBufferDescriptor* descriptor,
ExceptionState& exception_state);
ScriptPromise createBufferMappedAsync(ScriptState* script_state,
const GPUBufferDescriptor* descriptor,
ExceptionState& exception_state);
- GPUTexture* createTexture(const GPUTextureDescriptor* descriptor);
+ GPUTexture* createTexture(const GPUTextureDescriptor* descriptor,
+ ExceptionState& exception_state);
GPUSampler* createSampler(const GPUSamplerDescriptor* descriptor);
GPUBindGroup* createBindGroup(const GPUBindGroupDescriptor* descriptor);
@@ -93,13 +103,31 @@ class GPUDevice final : public DawnObject<DawnDevice> {
GPUQueue* getQueue();
+ void pushErrorScope(const WTF::String& filter);
+ ScriptPromise popErrorScope(ScriptState* script_state);
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(uncapturederror, kUncapturederror)
+
+ // EventTarget overrides.
+ const AtomicString& InterfaceName() const override;
+ ExecutionContext* GetExecutionContext() const override;
+
private:
+ using LostProperty = ScriptPromiseProperty<Member<GPUDevice>,
+ Member<GPUDeviceLostInfo>,
+ ToV8UndefinedGenerator>;
+
void OnUncapturedError(ExecutionContext* execution_context,
DawnErrorType errorType,
const char* message);
+ void OnPopErrorScopeCallback(ScriptPromiseResolver* resolver,
+ DawnErrorType type,
+ const char* message);
+
Member<GPUAdapter> adapter_;
Member<GPUQueue> queue_;
+ Member<LostProperty> lost_property_;
std::unique_ptr<
DawnCallback<base::RepeatingCallback<void(DawnErrorType, const char*)>>>
error_callback_;
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 cc32b405661..56e9b385828 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -6,14 +6,15 @@
[
RuntimeEnabled=WebGPU
-] interface GPUDevice {
+] interface GPUDevice : EventTarget {
readonly attribute GPUAdapter adapter;
+ [CallWith=ScriptState] readonly attribute Promise<GPUDeviceLostInfo> lost;
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
[CallWith=ScriptState, RaisesException] GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
[CallWith=ScriptState, RaisesException] Promise<GPUMappedBuffer> createBufferMappedAsync(GPUBufferDescriptor descriptor);
- GPUTexture createTexture(GPUTextureDescriptor descriptor);
- GPUSampler createSampler(GPUSamplerDescriptor descriptor);
+ [RaisesException] GPUTexture createTexture(GPUTextureDescriptor descriptor);
+ GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
@@ -23,9 +24,20 @@
[CallWith=ScriptState] GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
- GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor);
+ GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
GPUQueue getQueue();
+
+ void pushErrorScope(GPUErrorFilter filter);
+ [CallWith=ScriptState] Promise<GPUError?> popErrorScope();
+
+ attribute EventHandler onuncapturederror;
+};
+
+enum GPUErrorFilter {
+ "none",
+ "out-of-memory",
+ "validation"
};
typedef sequence<any> GPUMappedBuffer; // [GPUBuffer, ArrayBuffer]
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 a5983c8dde5..83468228edd 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
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUDeviceDescriptor {
- GPUExtensions extensions;
- GPULimits limits;
+dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
+ GPUExtensions extensions = {};
+ GPULimits limits = {};
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc
new file mode 100644
index 00000000000..3a6f1022868
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc
@@ -0,0 +1,22 @@
+// 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/webgpu/gpu_device_lost_info.h"
+
+namespace blink {
+
+// static
+GPUDeviceLostInfo* GPUDeviceLostInfo::Create(const String& message) {
+ return MakeGarbageCollected<GPUDeviceLostInfo>(message);
+}
+
+GPUDeviceLostInfo::GPUDeviceLostInfo(const String& message) {
+ message_ = message;
+}
+
+const String& GPUDeviceLostInfo::message() const {
+ return message_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h
new file mode 100644
index 00000000000..db6b2142a98
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h
@@ -0,0 +1,31 @@
+// 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_WEBGPU_GPU_DEVICE_LOST_INFO_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_LOST_INFO_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class GPUDeviceLostInfo : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static GPUDeviceLostInfo* Create(const String& message);
+ GPUDeviceLostInfo(const String& message);
+
+ // gpu_device_lost_info.idl
+ const String& message() const;
+
+ private:
+ String message_;
+
+ DISALLOW_COPY_AND_ASSIGN(GPUDeviceLostInfo);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_LOST_INFO_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl
new file mode 100644
index 00000000000..44fd3a1d16f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl
@@ -0,0 +1,12 @@
+// 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/
+
+[
+ RuntimeEnabled=WebGPU
+] interface GPUDeviceLostInfo {
+ readonly attribute DOMString message;
+};
+
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d_dict.idl
index 19b45af4747..ef2da9fd7e0 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_extent_3d_dict.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUExtent3D {
+dictionary GPUExtent3DDict {
required unsigned long width;
required unsigned long height;
required unsigned long depth;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl
index 4a94de1c80f..e5ce2679eb3 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_fence_descriptor.idl
@@ -4,6 +4,6 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUFenceDescriptor {
+dictionary GPUFenceDescriptor : GPUObjectDescriptorBase {
unsigned long long initialValue = 0;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl
new file mode 100644
index 00000000000..020c0e21584
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_object_descriptor_base.idl
@@ -0,0 +1,9 @@
+// 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/
+
+dictionary GPUObjectDescriptorBase {
+ DOMString? label;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d_dict.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d_dict.idl
new file mode 100644
index 00000000000..741be633dc0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_origin_3d_dict.idl
@@ -0,0 +1,11 @@
+// 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/
+
+dictionary GPUOrigin3DDict {
+ unsigned long x = 0;
+ unsigned long y = 0;
+ unsigned long z = 0;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl
index 417592f8b5f..d2cadf779a9 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_descriptor_base.idl
@@ -4,7 +4,6 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUPipelineDescriptorBase {
- DOMString label;
+dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
required GPUPipelineLayout layout;
};
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 1f62227b7f2..97a617285e4 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
@@ -29,6 +29,9 @@ GPUPipelineLayout* GPUPipelineLayout::Create(
dawn_desc.nextInChain = nullptr;
dawn_desc.bindGroupLayoutCount = bind_group_layout_count;
dawn_desc.bindGroupLayouts = bind_group_layouts.get();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return MakeGarbageCollected<GPUPipelineLayout>(
device, device->GetProcs().deviceCreatePipelineLayout(device->GetHandle(),
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl
index e6fbc7b06ee..7d78d369ac9 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl
@@ -4,6 +4,6 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUPipelineLayoutDescriptor {
+dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase {
required sequence<GPUBindGroupLayout> bindGroupLayouts;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_pass_encoder.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_pass_encoder.idl
new file mode 100644
index 00000000000..4d57cefafdd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_pass_encoder.idl
@@ -0,0 +1,16 @@
+// 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/
+
+[
+ RuntimeEnabled=WebGPU
+] interface mixin GPUProgrammablePassEncoder {
+ void setBindGroup(unsigned long index, GPUBindGroup bindGroup,
+ optional sequence<GPUBufferSize> dynamicOffsets = []);
+
+ void pushDebugGroup(DOMString groupLabel);
+ void popDebugGroup();
+ void insertDebugMarker(DOMString markerLabel);
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.idl
index dc75910a740..a2cdfd81029 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUPipelineStageDescriptor {
+dictionary GPUProgrammableStageDescriptor {
required GPUShaderModule module;
required DOMString entryPoint;
};
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 f1cd037f6d0..a4a5a0dd2ac 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -51,6 +51,9 @@ GPUFence* GPUQueue::createFence(const GPUFenceDescriptor* descriptor) {
DawnFenceDescriptor desc = {};
desc.nextInChain = nullptr;
desc.initialValue = descriptor->initialValue();
+ if (descriptor->hasLabel()) {
+ desc.label = descriptor->label().Utf8().data();
+ }
return GPUFence::Create(device_,
GetProcs().queueCreateFence(GetHandle(), &desc));
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 cafda6861d9..2cb3f9cab9b 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_queue.idl
@@ -9,6 +9,6 @@
] interface GPUQueue {
void submit(sequence<GPUCommandBuffer> buffers);
- GPUFence createFence(optional GPUFenceDescriptor descriptor);
+ GPUFence createFence(optional GPUFenceDescriptor descriptor = {});
void signal(GPUFence fence, unsigned long long signalValue);
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.idl
index 662df784dc8..257e326dc68 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.idl
@@ -4,5 +4,5 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPURenderBundleDescriptor {
+dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase {
};
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 4dfd4989b09..78def74489b 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
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_bind_group.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_color.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.h"
@@ -38,6 +37,9 @@ GPURenderBundleEncoder* GPURenderBundleEncoder::Create(
dawn_desc.colorFormats = color_formats.get();
dawn_desc.depthStencilFormat = depth_stencil_format;
dawn_desc.sampleCount = webgpu_desc->sampleCount();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return MakeGarbageCollected<GPURenderBundleEncoder>(
device, device->GetProcs().deviceCreateRenderBundleEncoder(
@@ -89,22 +91,11 @@ void GPURenderBundleEncoder::setIndexBuffer(GPUBuffer* buffer,
offset);
}
-void GPURenderBundleEncoder::setVertexBuffers(
- uint32_t startSlot,
- const HeapVector<Member<GPUBuffer>>& buffers,
- const Vector<uint64_t>& offsets,
- ExceptionState& exception_state) {
- if (buffers.size() != offsets.size()) {
- exception_state.ThrowRangeError(
- "buffers array and offsets array must be the same length");
- return;
- }
-
- std::unique_ptr<DawnBuffer[]> dawn_buffers = AsDawnType(buffers);
-
- GetProcs().renderBundleEncoderSetVertexBuffers(
- GetHandle(), startSlot, buffers.size(), dawn_buffers.get(),
- offsets.data());
+void GPURenderBundleEncoder::setVertexBuffer(uint32_t slot,
+ const GPUBuffer* buffer,
+ uint64_t offset) {
+ GetProcs().renderBundleEncoderSetVertexBuffer(GetHandle(), slot,
+ buffer->GetHandle(), offset);
}
void GPURenderBundleEncoder::draw(uint32_t vertexCount,
@@ -141,6 +132,9 @@ GPURenderBundle* GPURenderBundleEncoder::finish(
const GPURenderBundleDescriptor* webgpu_desc) {
DawnRenderBundleDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
DawnRenderBundle render_bundle =
GetProcs().renderBundleEncoderFinish(GetHandle(), &dawn_desc);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h
index 39f8b79953a..a8015a71d73 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h
@@ -39,10 +39,7 @@ class GPURenderBundleEncoder : public DawnObject<DawnRenderBundleEncoder> {
void setPipeline(GPURenderPipeline* pipeline);
void setIndexBuffer(GPUBuffer* buffer, uint64_t offset);
- void setVertexBuffers(uint32_t startSlot,
- const HeapVector<Member<GPUBuffer>>& buffers,
- const Vector<uint64_t>& offsets,
- ExceptionState& exception_state);
+ void setVertexBuffer(uint32_t slot, const GPUBuffer* buffer, uint64_t offset);
void draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl
index 6d3a898be0d..1ee0037875f 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl
@@ -7,32 +7,7 @@
[
RuntimeEnabled=WebGPU
] interface GPURenderBundleEncoder {
- // GPUProgrammablePassEncoder methods
- void setBindGroup(unsigned long index,
- GPUBindGroup bindGroup,
- optional sequence<unsigned long long> dynamicOffsets = []);
- void pushDebugGroup(DOMString groupLabel);
- void popDebugGroup();
- void insertDebugMarker(DOMString markerLabel);
-
- // GPURenderEncoderBase methods
- void setPipeline(GPURenderPipeline pipeline);
- void setIndexBuffer(GPUBuffer buffer, unsigned long long offset);
- [RaisesException] void setVertexBuffers(unsigned long startSlot,
- sequence<GPUBuffer> buffers,
- sequence<unsigned long long> offsets);
- void draw(unsigned long vertexCount, unsigned long instanceCount,
- unsigned long firstVertex,
- unsigned long firstInstance);
- void drawIndexed(unsigned long indexCount, unsigned long instanceCount,
- unsigned long firstIndex,
- long baseVertex,
- unsigned long firstInstance);
- void drawIndirect(GPUBuffer indirectBuffer,
- unsigned long long indirectOffset);
- void drawIndexedIndirect(GPUBuffer indirectBuffer,
- unsigned long long indirectOffset);
-
- // GPURenderBundleEncoder methods
- GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor);
+ GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
};
+GPURenderBundleEncoder includes GPUProgrammablePassEncoder;
+GPURenderBundleEncoder includes GPURenderEncoderBase;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder_descriptor.idl
index 222ef60356d..14c8bd4eecb 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPURenderBundleEncoderDescriptor {
+dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase {
required sequence<GPUTextureFormat> colorFormats;
GPUTextureFormat depthStencilFormat;
unsigned long sampleCount = 1;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl
new file mode 100644
index 00000000000..ea5c4c6e9d3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_encoder_base.idl
@@ -0,0 +1,29 @@
+// 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/
+
+[
+ RuntimeEnabled=WebGPU
+] interface mixin GPURenderEncoderBase {
+ void setPipeline(GPURenderPipeline pipeline);
+
+ void setIndexBuffer(GPUBuffer buffer, optional GPUBufferSize offset = 0);
+ void setVertexBuffer(unsigned long slot,
+ GPUBuffer buffer,
+ optional GPUBufferSize offset = 0);
+
+ void draw(unsigned long vertexCount, unsigned long instanceCount,
+ unsigned long firstVertex,
+ unsigned long firstInstance);
+ void drawIndexed(unsigned long indexCount, unsigned long instanceCount,
+ unsigned long firstIndex,
+ long baseVertex,
+ unsigned long firstInstance);
+
+ void drawIndirect(GPUBuffer indirectBuffer,
+ GPUBufferSize indirectOffset);
+ void drawIndexedIndirect(GPUBuffer indirectBuffer,
+ GPUBufferSize indirectOffset);
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl
index 63c9b326ff1..3d325417185 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment_descriptor.idl
@@ -10,6 +10,6 @@ dictionary GPURenderPassDepthStencilAttachmentDescriptor {
required (GPULoadOp or float) depthLoadValue;
required GPUStoreOp depthStoreOp;
- required (GPULoadOp or long) stencilLoadValue;
+ required (GPULoadOp or unsigned long) stencilLoadValue;
required GPUStoreOp stencilStoreOp;
};
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 cb0bcdbb106..9589242ac4f 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
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPURenderPassDescriptor {
+dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
required sequence<GPURenderPassColorAttachmentDescriptor> colorAttachments;
GPURenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
};
@@ -14,5 +14,6 @@ enum GPULoadOp {
};
enum GPUStoreOp {
- "store"
+ "store",
+ "clear"
};
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 4378f95b533..6214d6742ed 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,10 +4,10 @@
#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/modules/webgpu/dawn_conversions.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_bind_group.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
-#include "third_party/blink/renderer/modules/webgpu/gpu_color.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle.h"
#include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h"
@@ -61,8 +61,14 @@ void GPURenderPassEncoder::setPipeline(GPURenderPipeline* pipeline) {
GetProcs().renderPassEncoderSetPipeline(GetHandle(), pipeline->GetHandle());
}
-void GPURenderPassEncoder::setBlendColor(GPUColor* color) {
- DawnColor dawn_color = AsDawnType(color);
+void GPURenderPassEncoder::setBlendColor(DoubleSequenceOrGPUColorDict& color,
+ ExceptionState& exception_state) {
+ if (color.IsDoubleSequence() && color.GetAsDoubleSequence().size() != 4) {
+ exception_state.ThrowRangeError("color size must be 4");
+ return;
+ }
+
+ DawnColor dawn_color = AsDawnType(&color);
GetProcs().renderPassEncoderSetBlendColor(GetHandle(), &dawn_color);
}
@@ -92,22 +98,11 @@ void GPURenderPassEncoder::setIndexBuffer(GPUBuffer* buffer, uint64_t offset) {
offset);
}
-void GPURenderPassEncoder::setVertexBuffers(
- uint32_t startSlot,
- const HeapVector<Member<GPUBuffer>>& buffers,
- const Vector<uint64_t>& offsets,
- ExceptionState& exception_state) {
- if (buffers.size() != offsets.size()) {
- exception_state.ThrowRangeError(
- "buffers array and offsets array must be the same length");
- return;
- }
-
- std::unique_ptr<DawnBuffer[]> dawn_buffers = AsDawnType(buffers);
-
- GetProcs().renderPassEncoderSetVertexBuffers(
- GetHandle(), startSlot, buffers.size(), dawn_buffers.get(),
- offsets.data());
+void GPURenderPassEncoder::setVertexBuffer(uint32_t slot,
+ const GPUBuffer* buffer,
+ const uint64_t offset) {
+ GetProcs().renderPassEncoderSetVertexBuffer(GetHandle(), slot,
+ buffer->GetHandle(), offset);
}
void GPURenderPassEncoder::draw(uint32_t vertexCount,
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 f270ea8d822..03622039cd3 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
@@ -12,7 +12,7 @@ namespace blink {
class GPUBindGroup;
class GPUBuffer;
-class GPUColor;
+class DoubleSequenceOrGPUColorDict;
class GPURenderBundle;
class GPURenderPipeline;
@@ -36,7 +36,8 @@ class GPURenderPassEncoder : public DawnObject<DawnRenderPassEncoder> {
void insertDebugMarker(String markerLabel);
void setPipeline(GPURenderPipeline* pipeline);
- void setBlendColor(GPUColor* color);
+ void setBlendColor(DoubleSequenceOrGPUColorDict& color,
+ ExceptionState& exception_state);
void setStencilReference(uint32_t reference);
void setViewport(float x,
float y,
@@ -46,10 +47,9 @@ class GPURenderPassEncoder : public DawnObject<DawnRenderPassEncoder> {
float maxDepth);
void setScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
void setIndexBuffer(GPUBuffer* buffer, uint64_t offset);
- void setVertexBuffers(uint32_t startSlot,
- const HeapVector<Member<GPUBuffer>>& buffers,
- const Vector<uint64_t>& offsets,
- ExceptionState& exception_state);
+ void setVertexBuffer(uint32_t slot,
+ const GPUBuffer* buffer,
+ const uint64_t offset);
void draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
index b3db8006310..524f750a6db 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
@@ -7,39 +7,18 @@
[
RuntimeEnabled=WebGPU
] interface GPURenderPassEncoder {
- // GPUProgrammablePassEncoder methods
- void setBindGroup(unsigned long index,
- GPUBindGroup bindGroup,
- optional sequence<unsigned long long> dynamicOffsets = []);
- void pushDebugGroup(DOMString groupLabel);
- void popDebugGroup();
- void insertDebugMarker(DOMString markerLabel);
-
- void setPipeline(GPURenderPipeline pipeline);
-
- void setBlendColor(GPUColor color);
- void setStencilReference(unsigned long reference);
void setViewport(float x, float y,
float width, float height,
float minDepth, float maxDepth);
+
void setScissorRect(unsigned long x, unsigned long y,
unsigned long width, unsigned long height);
- void setIndexBuffer(GPUBuffer buffer, unsigned long long offset);
- [RaisesException] void setVertexBuffers(unsigned long startSlot,
- sequence<GPUBuffer> buffers,
- sequence<unsigned long long> offsets);
- void draw(unsigned long vertexCount, unsigned long instanceCount,
- unsigned long firstVertex,
- unsigned long firstInstance);
- void drawIndexed(unsigned long indexCount, unsigned long instanceCount,
- unsigned long firstIndex,
- long baseVertex,
- unsigned long firstInstance);
- void drawIndirect(GPUBuffer indirectBuffer,
- unsigned long long indirectOffset);
- void drawIndexedIndirect(GPUBuffer indirectBuffer,
- unsigned long long indirectOffset);
+
+ [RaisesException] void setBlendColor(GPUColor color);
+ void setStencilReference(unsigned long reference);
void executeBundles(sequence<GPURenderBundle> bundles);
void endPass();
};
+GPURenderPassEncoder includes GPUProgrammablePassEncoder;
+GPURenderPassEncoder includes GPURenderEncoderBase;
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 1af046f0103..658342cec45 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
@@ -41,17 +41,8 @@ DawnColorStateDescriptor AsDawnType(
DawnColorStateDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
-
- GPUBlendDescriptor* gpu_alpha_blend = webgpu_desc->hasAlphaBlend()
- ? webgpu_desc->alphaBlend()
- : GPUBlendDescriptor::Create();
- dawn_desc.alphaBlend = AsDawnType(gpu_alpha_blend);
-
- GPUBlendDescriptor* gpu_color_blend = webgpu_desc->hasColorBlend()
- ? webgpu_desc->colorBlend()
- : GPUBlendDescriptor::Create();
- dawn_desc.colorBlend = AsDawnType(gpu_color_blend);
-
+ dawn_desc.alphaBlend = AsDawnType(webgpu_desc->alphaBlend());
+ dawn_desc.colorBlend = AsDawnType(webgpu_desc->colorBlend());
dawn_desc.writeMask =
AsDawnEnum<DawnColorWriteMask>(webgpu_desc->writeMask());
dawn_desc.format = AsDawnEnum<DawnTextureFormat>(webgpu_desc->format());
@@ -177,6 +168,9 @@ DawnVertexInputInfo GPUVertexInputAsDawnInputState(
// stopped appending to the vector so the pointers aren't invalidated.
uint32_t attributeIndex = 0;
for (DawnVertexBufferDescriptor& buffer : dawn_vertex_buffers) {
+ if (buffer.attributeCount == 0) {
+ continue;
+ }
buffer.attributes = &dawn_vertex_attributes[attributeIndex];
attributeIndex += buffer.attributeCount;
}
@@ -217,11 +211,14 @@ GPURenderPipeline* GPURenderPipeline::Create(
DawnRenderPipelineDescriptor dawn_desc = {};
dawn_desc.nextInChain = nullptr;
dawn_desc.layout = AsDawnType(webgpu_desc->layout());
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
- OwnedPipelineStageDescriptor vertex_stage_info =
+ OwnedProgrammableStageDescriptor vertex_stage_info =
AsDawnType(webgpu_desc->vertexStage());
dawn_desc.vertexStage = std::get<0>(vertex_stage_info);
- OwnedPipelineStageDescriptor fragment_stage_info;
+ OwnedProgrammableStageDescriptor fragment_stage_info;
if (webgpu_desc->hasFragmentStage()) {
fragment_stage_info = AsDawnType(webgpu_desc->fragmentStage());
dawn_desc.fragmentStage = &std::get<0>(fragment_stage_info);
@@ -229,34 +226,24 @@ GPURenderPipeline* GPURenderPipeline::Create(
dawn_desc.fragmentStage = nullptr;
}
- DawnVertexInputInfo vertex_input_info;
- if (webgpu_desc->hasVertexInput()) {
- // TODO(crbug.com/dawn/131): Update Dawn to match WebGPU vertex input
- v8::Isolate* isolate = script_state->GetIsolate();
- ExceptionState exception_state(isolate,
- ExceptionState::kConstructionContext,
- "GPUVertexInputDescriptor");
- vertex_input_info = GPUVertexInputAsDawnInputState(
- isolate, webgpu_desc->vertexInput(), exception_state);
- dawn_desc.vertexInput = &std::get<0>(vertex_input_info);
-
- if (exception_state.HadException()) {
- return nullptr;
- }
- } else {
- dawn_desc.vertexInput = nullptr;
+ // TODO(crbug.com/dawn/131): Update Dawn to match WebGPU vertex input
+ v8::Isolate* isolate = script_state->GetIsolate();
+ ExceptionState exception_state(isolate, ExceptionState::kConstructionContext,
+ "GPUVertexInputDescriptor");
+ DawnVertexInputInfo vertex_input_info = GPUVertexInputAsDawnInputState(
+ isolate, webgpu_desc->vertexInput(), exception_state);
+ dawn_desc.vertexInput = &std::get<0>(vertex_input_info);
+
+ if (exception_state.HadException()) {
+ return nullptr;
}
dawn_desc.primitiveTopology =
AsDawnEnum<DawnPrimitiveTopology>(webgpu_desc->primitiveTopology());
DawnRasterizationStateDescriptor rasterization_state;
- if (webgpu_desc->hasRasterizationState()) {
- rasterization_state = AsDawnType(webgpu_desc->rasterizationState());
- dawn_desc.rasterizationState = &rasterization_state;
- } else {
- dawn_desc.rasterizationState = nullptr;
- }
+ rasterization_state = AsDawnType(webgpu_desc->rasterizationState());
+ dawn_desc.rasterizationState = &rasterization_state;
dawn_desc.sampleCount = webgpu_desc->sampleCount();
@@ -273,8 +260,7 @@ GPURenderPipeline* GPURenderPipeline::Create(
dawn_desc.colorStateCount =
static_cast<uint32_t>(webgpu_desc->colorStates().size());
- DawnColorStateDescriptor* color_state_descriptors = color_states.get();
- dawn_desc.colorStates = &color_state_descriptors;
+ dawn_desc.colorStates = color_states.get();
dawn_desc.sampleMask = webgpu_desc->sampleMask();
dawn_desc.alphaToCoverageEnabled = webgpu_desc->alphaToCoverageEnabled();
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl
index 4fe019c6062..0017094c86b 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline_descriptor.idl
@@ -5,14 +5,14 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
- required GPUPipelineStageDescriptor vertexStage;
- GPUPipelineStageDescriptor fragmentStage;
+ required GPUProgrammableStageDescriptor vertexStage;
+ GPUProgrammableStageDescriptor fragmentStage;
required GPUPrimitiveTopology primitiveTopology;
- GPURasterizationStateDescriptor rasterizationState;
+ GPURasterizationStateDescriptor rasterizationState = {};
required sequence<GPUColorStateDescriptor> colorStates;
GPUDepthStencilStateDescriptor depthStencilState;
- GPUVertexInputDescriptor vertexInput;
+ GPUVertexInputDescriptor vertexInput = {};
unsigned long sampleCount = 1;
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 0b21805d3f6..37aa1f668ac 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler.cc
@@ -29,8 +29,10 @@ DawnSamplerDescriptor AsDawnType(const GPUSamplerDescriptor* webgpu_desc) {
AsDawnEnum<DawnFilterMode>(webgpu_desc->mipmapFilter());
dawn_desc.lodMinClamp = webgpu_desc->lodMinClamp();
dawn_desc.lodMaxClamp = webgpu_desc->lodMaxClamp();
- dawn_desc.compare =
- AsDawnEnum<DawnCompareFunction>(webgpu_desc->compareFunction());
+ dawn_desc.compare = AsDawnEnum<DawnCompareFunction>(webgpu_desc->compare());
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl
index 4eb8b2be28f..22e45466911 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_sampler_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUSamplerDescriptor {
+dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
GPUAddressMode addressModeU = "clamp-to-edge";
GPUAddressMode addressModeV = "clamp-to-edge";
GPUAddressMode addressModeW = "clamp-to-edge";
@@ -13,7 +13,7 @@ dictionary GPUSamplerDescriptor {
GPUFilterMode mipmapFilter = "nearest";
float lodMinClamp = 0;
float lodMaxClamp = 0xffffffff;
- GPUCompareFunction compareFunction = "never";
+ GPUCompareFunction compare = "never";
};
enum GPUAddressMode {
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 16c65e4a074..edd4004cfb1 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
@@ -18,6 +18,9 @@ DawnShaderModuleDescriptor AsDawnType(
dawn_desc.nextInChain = nullptr;
dawn_desc.code = webgpu_desc->code().View()->Data();
dawn_desc.codeSize = webgpu_desc->code().View()->length();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl
index 640d87576de..976f406838a 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_module_descriptor.idl
@@ -4,8 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUShaderModuleDescriptor {
- DOMString label;
+dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
// TODO(kainino): should be:
// [AllowShared, FlexibleArrayBufferView] required ArrayBufferView code;
// (or BufferSource?)
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.h
index 6ab71b94a14..07b664900f5 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.h
@@ -14,7 +14,6 @@ class GPUShaderStage : public ScriptWrappable {
public:
// gpu_shader_stage.idl
- static constexpr uint32_t kNone = 0;
static constexpr uint32_t kVertex = 1;
static constexpr uint32_t kFragment = 2;
static constexpr uint32_t kCompute = 4;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl
index 54f85887df4..546221e2a07 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_shader_stage.idl
@@ -8,8 +8,7 @@ typedef unsigned long GPUShaderStageFlags;
[
RuntimeEnabled=WebGPU
] interface GPUShaderStage {
- const unsigned long NONE = 0;
- const unsigned long VERTEX = 1;
- const unsigned long FRAGMENT = 2;
- const unsigned long COMPUTE = 4;
+ const GPUShaderStageFlags VERTEX = 1;
+ const GPUShaderStageFlags FRAGMENT = 2;
+ const GPUShaderStageFlags COMPUTE = 4;
};
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 a400bf0e62b..9521cc2d7fd 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
@@ -24,6 +24,7 @@ GPUSwapChain::GPUSwapChain(GPUCanvasContext* context,
device_(descriptor->device()),
context_(context),
usage_(AsDawnEnum<DawnTextureUsage>(descriptor->usage())) {
+ // TODO: Use label from GPUObjectDescriptorBase.
swap_buffers_ = base::AdoptRef(new WebGPUSwapBufferProvider(
this, GetDawnControlClient(), usage_,
AsDawnEnum<DawnTextureFormat>(descriptor->format())));
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 b644bba9dd7..edaedbfd219 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
@@ -19,7 +19,8 @@ class GPUDevice;
class GPUSwapChainDescriptor;
class GPUTexture;
-class GPUSwapChain : public DawnObjectBase,
+class GPUSwapChain : public ScriptWrappable,
+ public DawnObjectBase,
public WebGPUSwapBufferProvider::Client {
DEFINE_WRAPPERTYPEINFO();
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
index 073b8e0c697..48bdb46c8ee 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_swap_chain_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUSwapChainDescriptor {
+dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
required GPUDevice device;
required GPUTextureFormat format;
GPUTextureUsageFlags usage = 16; // GPUTextureUsage.OUTPUT_ATTACHMENT
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 6006899d80d..9a4ec197e86 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.cc
@@ -22,11 +22,14 @@ DawnTextureDescriptor AsDawnType(const GPUTextureDescriptor* webgpu_desc) {
dawn_desc.usage = static_cast<DawnTextureUsage>(webgpu_desc->usage());
dawn_desc.dimension =
AsDawnEnum<DawnTextureDimension>(webgpu_desc->dimension());
- dawn_desc.size = AsDawnType(webgpu_desc->size());
+ dawn_desc.size = AsDawnType(&webgpu_desc->size());
dawn_desc.arrayLayerCount = webgpu_desc->arrayLayerCount();
dawn_desc.format = AsDawnEnum<DawnTextureFormat>(webgpu_desc->format());
dawn_desc.mipLevelCount = webgpu_desc->mipLevelCount();
dawn_desc.sampleCount = webgpu_desc->sampleCount();
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
@@ -44,6 +47,10 @@ DawnTextureViewDescriptor AsDawnType(
dawn_desc.mipLevelCount = webgpu_desc->mipLevelCount();
dawn_desc.baseArrayLayer = webgpu_desc->baseArrayLayer();
dawn_desc.arrayLayerCount = webgpu_desc->arrayLayerCount();
+ dawn_desc.aspect = AsDawnEnum<DawnTextureAspect>(webgpu_desc->aspect());
+ if (webgpu_desc->hasLabel()) {
+ dawn_desc.label = webgpu_desc->label().Utf8().data();
+ }
return dawn_desc;
}
@@ -52,9 +59,19 @@ DawnTextureViewDescriptor AsDawnType(
// static
GPUTexture* GPUTexture::Create(GPUDevice* device,
- const GPUTextureDescriptor* webgpu_desc) {
+ const GPUTextureDescriptor* webgpu_desc,
+ ExceptionState& exception_state) {
DCHECK(device);
DCHECK(webgpu_desc);
+
+ // Check size is correctly formatted before further processing.
+ const UnsignedLongSequenceOrGPUExtent3DDict& size = webgpu_desc->size();
+ if (size.IsUnsignedLongSequence() &&
+ size.GetAsUnsignedLongSequence().size() != 3) {
+ exception_state.ThrowRangeError("size length must be 3");
+ return nullptr;
+ }
+
DawnTextureDescriptor dawn_desc = AsDawnType(webgpu_desc);
return MakeGarbageCollected<GPUTexture>(
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 2063c416819..a137fdc8771 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.h
@@ -9,6 +9,7 @@
namespace blink {
+class ExceptionState;
class GPUTextureDescriptor;
class GPUTextureView;
class GPUTextureViewDescriptor;
@@ -18,7 +19,8 @@ class GPUTexture : public DawnObject<DawnTexture> {
public:
static GPUTexture* Create(GPUDevice* device,
- const GPUTextureDescriptor* webgpu_desc);
+ const GPUTextureDescriptor* webgpu_desc,
+ ExceptionState& exception_state);
explicit GPUTexture(GPUDevice* device, DawnTexture texture);
~GPUTexture() override;
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
index cdbcb367fe0..67904ef9d39 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture.idl
@@ -7,6 +7,6 @@
[
RuntimeEnabled=WebGPU
] interface GPUTexture {
- GPUTextureView createView(optional GPUTextureViewDescriptor desc);
+ GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
void destroy();
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl
index c0630b90bf3..0f9f85c1920 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_copy_view.idl
@@ -8,5 +8,5 @@ dictionary GPUTextureCopyView {
required GPUTexture texture;
unsigned long mipLevel = 0;
unsigned long arrayLayer = 0;
- required GPUOrigin3D origin;
+ GPUOrigin3D origin = {};
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
index b838a4cb0d9..e7b7b96b274 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUTextureDescriptor {
+dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
required GPUExtent3D size;
unsigned long arrayLayerCount = 1;
unsigned long mipLevelCount = 1;
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 30ec2618ac3..4455467dafc 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
@@ -14,7 +14,6 @@ class GPUTextureUsage : public ScriptWrappable {
public:
// gpu_texture_usage.idl
- static constexpr uint32_t kNone = 0;
static constexpr uint32_t kCopySrc = 1;
static constexpr uint32_t kCopyDst = 2;
static constexpr uint32_t kSampled = 4;
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 8a5c208a29b..d8139ba2073 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
@@ -8,10 +8,9 @@ typedef unsigned long GPUTextureUsageFlags;
[
RuntimeEnabled=WebGPU
] interface GPUTextureUsage {
- const unsigned long NONE = 0;
- 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 OUTPUT_ATTACHMENT = 16;
+ const GPUTextureUsageFlags COPY_SRC = 1;
+ const GPUTextureUsageFlags COPY_DST = 2;
+ const GPUTextureUsageFlags SAMPLED = 4;
+ const GPUTextureUsageFlags STORAGE = 8;
+ const GPUTextureUsageFlags OUTPUT_ATTACHMENT = 16;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl
index 551d2923ce8..ec3b27af8cb 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_texture_view_descriptor.idl
@@ -4,7 +4,7 @@
// https://gpuweb.github.io/gpuweb/
-dictionary GPUTextureViewDescriptor {
+dictionary GPUTextureViewDescriptor : GPUObjectDescriptorBase {
GPUTextureFormat format;
GPUTextureViewDimension dimension;
GPUTextureAspect aspect = "all";
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl
index 515407bcef1..80bed55a9d4 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_uncaptured_error_event.idl
@@ -8,4 +8,5 @@
Constructor(DOMString type, GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict),
RuntimeEnabled=WebGPU
] interface GPUUncapturedErrorEvent : Event {
+ readonly attribute GPUError error;
};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl
index 297b7f9e64f..3e92bd06e85 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_attribute_descriptor.idl
@@ -4,12 +4,10 @@
// https://gpuweb.github.io/gpuweb/
-typedef unsigned long GPUShaderAttributeIndex;
-
dictionary GPUVertexAttributeDescriptor {
- unsigned long long offset = 0;
+ GPUBufferSize offset = 0;
required GPUVertexFormat format;
- required GPUShaderAttributeIndex shaderLocation;
+ required unsigned long shaderLocation;
};
enum GPUVertexFormat {
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl
index b6ab1912f63..a6967902644 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_vertex_buffer_descriptor.idl
@@ -5,7 +5,7 @@
// https://gpuweb.github.io/gpuweb/
dictionary GPUVertexBufferDescriptor {
- required unsigned long long stride;
+ required GPUBufferSize stride;
GPUInputStepMode stepMode = "vertex";
required sequence<GPUVertexAttributeDescriptor> attributeSet;
};
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/DEPS b/chromium/third_party/blink/renderer/modules/webmidi/DEPS
index 9e5294b9d10..35e7842acbb 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webmidi/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+media/midi/midi_service.mojom-blink.h",
+ "+media/midi/midi_service.mojom-blink-forward.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_modules.h",
"+third_party/blink/renderer/modules/event_target_modules.h",
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_access.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_access.h
index 0d81d1909ac..73a42977dfa 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_access.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_access.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_ACCESS_H_
#include <memory>
-#include "media/midi/midi_service.mojom-blink.h"
+#include "media/midi/midi_service.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/context_lifecycle_observer.h"
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h
index e347e495e10..b3271887604 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.h
@@ -6,10 +6,10 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_ACCESS_INITIALIZER_H_
#include <memory>
-#include "media/midi/midi_service.mojom-blink.h"
+#include "media/midi/midi_service.mojom-blink-forward.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
-#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_input.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_input.h
index f09b3b0aa4b..23d2067d9f2 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_input.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_input.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_INPUT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_INPUT_H_
-#include "media/midi/midi_service.mojom-blink.h"
+#include "media/midi/midi_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/webmidi/midi_port.h"
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
index 0f62c6e6f62..f7c92147e0c 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_PORT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_PORT_H_
-#include "media/midi/midi_service.mojom-blink.h"
+#include "media/midi/midi_service.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/bindings/core/v8/script_promise_resolver.h"
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 21433d18aff..ac930802c90 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -7,7 +7,7 @@
#include <stdint.h>
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -198,7 +198,7 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
}
// See https://bit.ly/2S0zRAS for task types.
- frame->GetInterfaceProvider().GetInterface(
+ frame->GetBrowserInterfaceBroker().GetInterface(
service_remote_.BindNewPipeAndPassReceiver(
frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
service_remote_.set_disconnect_handler(WTF::Bind(
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 af3c18e45e1..23ff0e6bc91 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.h
@@ -24,7 +24,7 @@ class Navigator;
class ShareData;
class MODULES_EXPORT NavigatorShare final
- : public GarbageCollectedFinalized<NavigatorShare>,
+ : public GarbageCollected<NavigatorShare>,
public Supplement<Navigator> {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorShare);
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 a0c8268afa4..1f615675b3a 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
@@ -6,8 +6,8 @@
#include <memory>
#include <utility>
-#include "services/service_manager/public/cpp/interface_provider.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/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
@@ -112,14 +112,20 @@ class NavigatorShareTest : public testing::Test {
nullptr /* extra_data */);
test::RunPendingTasks();
- service_manager::InterfaceProvider::TestApi test_api(
- &GetFrame().GetInterfaceProvider());
- test_api.SetBinderForName(
+ GetFrame().GetBrowserInterfaceBroker().SetBinderForTesting(
ShareService::Name_,
WTF::BindRepeating(&MockShareService::Bind,
WTF::Unretained(&mock_share_service_)));
}
+ void TearDown() override {
+ // Remove the testing binder to avoid crashes between tests caused by
+ // MockShareService rebinding an already-bound Binding.
+ // See https://crbug.com/1010116 for more information.
+ GetFrame().GetBrowserInterfaceBroker().SetBinderForTesting(
+ ShareService::Name_, {});
+ }
+
public:
MockShareService mock_share_service_;
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 1736f885d2b..6fd0d7871cb 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -152,7 +152,7 @@ class MODULES_EXPORT DOMWebSocket : public EventTargetWithInlineData,
private:
// FIXME: This should inherit blink::EventQueue.
- class EventQueue final : public GarbageCollectedFinalized<EventQueue> {
+ class EventQueue final : public GarbageCollected<EventQueue> {
public:
static EventQueue* Create(EventTarget* target) {
return MakeGarbageCollected<EventQueue>(target);
diff --git a/chromium/third_party/blink/renderer/modules/websockets/mock_websocket_channel.h b/chromium/third_party/blink/renderer/modules/websockets/mock_websocket_channel.h
index 3c9e0aa78ed..8e8574b589a 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/mock_websocket_channel.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/mock_websocket_channel.h
@@ -9,7 +9,7 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h"
+#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/websockets/websocket_channel.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -52,6 +52,7 @@ class MockWebSocketChannel : public WebSocketChannel {
FailMock(reason, level, location.get());
}
MOCK_METHOD0(Disconnect, void());
+ MOCK_METHOD0(CancelHandshake, void());
MOCK_METHOD0(ApplyBackpressure, void());
MOCK_METHOD0(RemoveBackpressure, void());
};
diff --git a/chromium/third_party/blink/renderer/modules/websockets/web_pepper_socket_channel_client_proxy.h b/chromium/third_party/blink/renderer/modules/websockets/web_pepper_socket_channel_client_proxy.h
index 80159e0405f..bf525db6a34 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/web_pepper_socket_channel_client_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/web_pepper_socket_channel_client_proxy.h
@@ -21,7 +21,7 @@ namespace blink {
// WebPepperSocketImpl cannot be on Oilpan's heap. Thus we need to introduce a
// proxy class to decouple WebPepperSocketImpl from WebSocketChannelClient.
class WebPepperSocketChannelClientProxy final
- : public GarbageCollectedFinalized<WebPepperSocketChannelClientProxy>,
+ : public GarbageCollected<WebPepperSocketChannelClientProxy>,
public WebSocketChannelClient {
USING_GARBAGE_COLLECTED_MIXIN(WebPepperSocketChannelClientProxy);
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel.h
index 5c90167724d..5b315322efc 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel.h
@@ -47,7 +47,7 @@ class DOMArrayBuffer;
class KURL;
class MODULES_EXPORT WebSocketChannel
- : public GarbageCollectedFinalized<WebSocketChannel> {
+ : public GarbageCollected<WebSocketChannel> {
public:
enum class SendResult { SENT_SYNCHRONOUSLY, CALLBACK_WILL_BE_CALLED };
@@ -102,6 +102,10 @@ class MODULES_EXPORT WebSocketChannel
// Do not call any methods after calling this method.
virtual void Disconnect() = 0; // Will suppress didClose().
+ // Cancel the WebSocket handshake. Does nothing if the connection is already
+ // established. Do not call any other methods after this one.
+ virtual void CancelHandshake() = 0;
+
// Clients can call ApplyBackpressure() to indicate that they want to stop
// receiving new messages. WebSocketChannelClient::DidReceive*Message() may
// still be called after this, until existing flow control quota is used up.
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 d0a92c7b31b..3a3cac1ad1c 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
@@ -66,6 +66,8 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
namespace blink {
@@ -79,7 +81,7 @@ enum WebSocketOpCode {
} // namespace
class WebSocketChannelImpl::BlobLoader final
- : public GarbageCollectedFinalized<WebSocketChannelImpl::BlobLoader>,
+ : public GarbageCollected<WebSocketChannelImpl::BlobLoader>,
public FileReaderLoaderClient {
public:
BlobLoader(scoped_refptr<BlobDataHandle>,
@@ -102,8 +104,8 @@ class WebSocketChannelImpl::BlobLoader final
std::unique_ptr<FileReaderLoader> loader_;
};
-class WebSocketChannelImpl::Message
- : public GarbageCollectedFinalized<WebSocketChannelImpl::Message> {
+class WebSocketChannelImpl::Message final
+ : public GarbageCollected<WebSocketChannelImpl::Message> {
public:
Message(const std::string&, base::OnceClosure completion_callback);
explicit Message(scoped_refptr<BlobDataHandle>);
@@ -415,6 +417,18 @@ void WebSocketChannelImpl::Disconnect() {
Dispose();
}
+void WebSocketChannelImpl::CancelHandshake() {
+ NETWORK_DVLOG(1) << this << " CancelHandshake()";
+ if (GetState() != State::kConnecting)
+ return;
+
+ // This may still disconnect even if the handshake is complete if we haven't
+ // got the message yet.
+ // TODO(ricea): Plumb it through to the network stack to fix the race
+ // condition.
+ Disconnect();
+}
+
void WebSocketChannelImpl::ApplyBackpressure() {
backpressure_ = true;
}
@@ -439,31 +453,26 @@ void WebSocketChannelImpl::OnOpeningHandshakeStarted(
handshake_request_ = std::move(request);
}
-void WebSocketChannelImpl::OnResponseReceived(
- network::mojom::blink::WebSocketHandshakeResponsePtr response) {
- DCHECK_EQ(GetState(), State::kConnecting);
- NETWORK_DVLOG(1) << this << " OnResponseReceived("
- << response->url.GetString() << ")";
- TRACE_EVENT_INSTANT1(
- "devtools.timeline", "WebSocketReceiveHandshakeResponse",
- TRACE_EVENT_SCOPE_THREAD, "data",
- InspectorWebSocketEvent::Data(execution_context_, identifier_));
- probe::DidReceiveWebSocketHandshakeResponse(execution_context_, identifier_,
- handshake_request_.get(),
- response.get());
- handshake_request_ = nullptr;
-}
-
void WebSocketChannelImpl::OnConnectionEstablished(
mojo::PendingRemote<network::mojom::blink::WebSocket> websocket,
mojo::PendingReceiver<network::mojom::blink::WebSocketClient>
client_receiver,
const String& protocol,
const String& extensions,
+ network::mojom::blink::WebSocketHandshakeResponsePtr response,
mojo::ScopedDataPipeConsumerHandle readable) {
DCHECK_EQ(GetState(), State::kConnecting);
NETWORK_DVLOG(1) << this << " OnConnectionEstablished(" << protocol << ", "
<< extensions << ")";
+ TRACE_EVENT_INSTANT1(
+ "devtools.timeline", "WebSocketReceiveHandshakeResponse",
+ TRACE_EVENT_SCOPE_THREAD, "data",
+ InspectorWebSocketEvent::Data(execution_context_, identifier_));
+ probe::DidReceiveWebSocketHandshakeResponse(execution_context_, identifier_,
+ handshake_request_.get(),
+ response.get());
+ handshake_request_ = nullptr;
+
// From now on, we will detect mojo errors via |client_receiver_|.
handshake_client_receiver_.reset();
client_receiver_.Bind(
@@ -625,15 +634,8 @@ void WebSocketChannelImpl::SendAndAdjustQuota(
network::mojom::blink::WebSocketMessageType type,
base::span<const char> data,
uint64_t* consumed_buffered_amount) {
- // TODO(darin): Avoid this copy.
- Vector<uint8_t> data_to_pass;
- // This cast is always valid because the data size is limited by
- // sending_quota_, which is controlled by the browser process and in practice
- // is always much smaller than 4GB.
- // TODO(ricea): Change the type of sending_quota_ to wtf_size_t.
- data_to_pass.ReserveInitialCapacity(static_cast<wtf_size_t>(data.size()));
- data_to_pass.Append(data.data(), static_cast<wtf_size_t>(data.size()));
-
+ base::span<const uint8_t> data_to_pass(
+ reinterpret_cast<const uint8_t*>(data.data()), data.size());
websocket_->SendFrame(fin, type, data_to_pass);
sending_quota_ -= data.size();
@@ -887,12 +889,22 @@ void WebSocketChannelImpl::ConsumeDataFrame(
return;
}
+ // TODO(yoichio): Do this after EndReadData by reading |message_chunks_|
+ // instead.
+ if (receiving_message_type_is_text_ && received_text_is_all_ascii_) {
+ for (size_t i = 0; i < size; i++) {
+ if (!IsASCII(data[i])) {
+ received_text_is_all_ascii_ = false;
+ break;
+ }
+ }
+ }
+
if (!fin) {
message_chunks_.Append(base::make_span(data, size));
return;
}
- const wtf_size_t message_size = static_cast<wtf_size_t>(message_size_so_far);
Vector<base::span<const char>> chunks = message_chunks_.GetView();
if (size > 0) {
chunks.push_back(base::make_span(data, size));
@@ -904,20 +916,8 @@ void WebSocketChannelImpl::ConsumeDataFrame(
false, chunks);
if (receiving_message_type_is_text_) {
- Vector<char> flatten;
- base::span<const char> span;
- if (chunks.size() > 1) {
- flatten.ReserveCapacity(message_size);
- for (const auto& chunk : chunks) {
- flatten.Append(chunk.data(), static_cast<wtf_size_t>(chunk.size()));
- }
- span = base::make_span(flatten.data(), flatten.size());
- } else if (chunks.size() == 1) {
- span = chunks[0];
- }
- String message = span.size() > 0
- ? String::FromUTF8(span.data(), span.size())
- : g_empty_string;
+ String message = GetTextMessage(
+ chunks, static_cast<wtf_size_t>(message_size_so_far + size));
if (message.IsNull()) {
FailAsError("Could not decode a text frame as UTF-8.");
} else {
@@ -927,6 +927,47 @@ void WebSocketChannelImpl::ConsumeDataFrame(
client_->DidReceiveBinaryMessage(chunks);
}
message_chunks_.Clear();
+ received_text_is_all_ascii_ = true;
+}
+
+String WebSocketChannelImpl::GetTextMessage(
+ const Vector<base::span<const char>>& chunks,
+ wtf_size_t size) {
+ DCHECK(receiving_message_type_is_text_);
+
+ if (size == 0) {
+ return g_empty_string;
+ }
+
+ // We can skip UTF8 encoding if received text contains only ASCII.
+ // We do this in order to avoid constructing a temporary buffer.
+ if (received_text_is_all_ascii_) {
+ LChar* buffer;
+ scoped_refptr<StringImpl> string_impl =
+ StringImpl::CreateUninitialized(size, buffer);
+ size_t index = 0;
+ for (const auto& chunk : chunks) {
+ DCHECK_LE(index + chunk.size(), size);
+ memcpy(buffer + index, chunk.data(), chunk.size());
+ index += chunk.size();
+ }
+ DCHECK_EQ(index, size);
+ return String(std::move(string_impl));
+ }
+
+ Vector<char> flatten;
+ base::span<const char> span;
+ if (chunks.size() > 1) {
+ flatten.ReserveCapacity(size);
+ for (const auto& chunk : chunks) {
+ flatten.Append(chunk.data(), static_cast<wtf_size_t>(chunk.size()));
+ }
+ span = base::make_span(flatten.data(), flatten.size());
+ } else if (chunks.size() == 1) {
+ span = chunks[0];
+ }
+ DCHECK_EQ(span.size(), size);
+ return String::FromUTF8(span.data(), span.size());
}
void WebSocketChannelImpl::OnConnectionError(const base::Location& set_from,
@@ -949,6 +990,7 @@ void WebSocketChannelImpl::OnConnectionError(const base::Location& set_from,
}
void WebSocketChannelImpl::Dispose() {
+ message_chunks_.Reset();
has_initiated_opening_handshake_ = true;
feature_handle_for_scheduler_.reset();
handshake_throttle_.reset();
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
index c5f5b5b4372..318b7d7a213 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
@@ -42,7 +42,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "services/network/public/mojom/websocket.mojom-blink.h"
-#include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-blink.h"
+#include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -107,20 +107,20 @@ class MODULES_EXPORT WebSocketChannelImpl final
mojom::ConsoleMessageLevel,
std::unique_ptr<SourceLocation>) override;
void Disconnect() override;
+ void CancelHandshake() override;
void ApplyBackpressure() override;
void RemoveBackpressure() override;
// network::mojom::blink::WebSocketHandshakeClient methods:
void OnOpeningHandshakeStarted(
network::mojom::blink::WebSocketHandshakeRequestPtr) override;
- void OnResponseReceived(
- network::mojom::blink::WebSocketHandshakeResponsePtr) override;
void OnConnectionEstablished(
mojo::PendingRemote<network::mojom::blink::WebSocket> websocket,
mojo::PendingReceiver<network::mojom::blink::WebSocketClient>
client_receiver,
const String& selected_protocol,
const String& extensions,
+ network::mojom::blink::WebSocketHandshakeResponsePtr,
mojo::ScopedDataPipeConsumerHandle readable) override;
// network::mojom::blink::WebSocketClient methods:
@@ -228,6 +228,8 @@ class MODULES_EXPORT WebSocketChannelImpl final
network::mojom::blink::WebSocketMessageType type,
const char* data,
size_t data_size);
+ String GetTextMessage(const Vector<base::span<const char>>& chunks,
+ wtf_size_t size);
void OnConnectionError(const base::Location& set_from,
uint32_t custom_reason,
const std::string& description);
@@ -243,6 +245,7 @@ class MODULES_EXPORT WebSocketChannelImpl final
bool backpressure_ = false;
bool receiving_message_type_is_text_ = false;
+ bool received_text_is_all_ascii_ = true;
bool throttle_passed_ = false;
bool has_initiated_opening_handshake_ = false;
uint64_t sending_quota_ = 0;
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 84ec7583387..4231f311c15 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
@@ -14,6 +14,7 @@
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/websockets/websocket_connector.mojom-blink.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -41,7 +42,7 @@ namespace blink {
typedef testing::StrictMock<testing::MockFunction<void(int)>> Checkpoint;
class MockWebSocketChannelClient
- : public GarbageCollectedFinalized<MockWebSocketChannelClient>,
+ : public GarbageCollected<MockWebSocketChannelClient>,
public WebSocketChannelClient {
USING_GARBAGE_COLLECTED_MIXIN(MockWebSocketChannelClient);
@@ -112,8 +113,10 @@ class WebSocketChannelImplTest : public PageTestBase {
void SendFrame(bool fin,
WebSocketMessageType type,
- const Vector<uint8_t>& data) override {
- frames_.push_back(Frame{fin, type, data});
+ base::span<const uint8_t> data) override {
+ Vector<uint8_t> data_to_pass;
+ data_to_pass.AppendRange(data.begin(), data.end());
+ frames_.push_back(Frame{fin, type, std::move(data_to_pass)});
}
void StartReceiving() override {
DCHECK(!is_start_receiving_called_);
@@ -235,10 +238,14 @@ class WebSocketChannelImplTest : public PageTestBase {
auto websocket = std::make_unique<TestWebSocket>(
websocket_to_pass.InitWithNewPipeAndPassReceiver());
+ auto response = network::mojom::blink::WebSocketHandshakeResponse::New();
+ response->http_version = network::mojom::blink::HttpVersion::New();
+ response->status_text = "";
+ response->headers_text = "";
handshake_client->OnConnectionEstablished(
std::move(websocket_to_pass),
client_remote.InitWithNewPipeAndPassReceiver(), selected_protocol,
- extensions, std::move(readable));
+ extensions, std::move(response), std::move(readable));
client->Bind(std::move(client_remote));
return websocket;
}
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.cc
index 0080e5bbe81..21affd2886c 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.cc
@@ -81,6 +81,14 @@ void WebSocketMessageChunkAccumulator::Clear() {
}
}
+void WebSocketMessageChunkAccumulator::Reset() {
+ segments_.clear();
+ pool_.clear();
+ size_ = 0;
+ num_pooled_segments_to_be_removed_ = 0;
+ timer_.Stop();
+}
+
void WebSocketMessageChunkAccumulator::OnTimerFired(TimerBase*) {
DCHECK(!timer_.IsActive());
const auto to_be_removed =
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.h
index 2558fd545bd..c3c7ee16ac8 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_message_chunk_accumulator.h
@@ -43,6 +43,9 @@ class MODULES_EXPORT WebSocketMessageChunkAccumulator final {
// uses for certain amount of time.
void Clear();
+ // Clear all stored data and cancel timers.
+ void Reset();
+
// The regions will be available until Clear() is called.
Vector<base::span<const char>> GetView() const;
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 49252d33cb8..c33cdbc2653 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.cc
@@ -14,6 +14,7 @@
#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"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/streams/readable_stream.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_interface.h"
@@ -467,8 +468,6 @@ void WebSocketStream::DidConnect(const String& subprotocol,
return;
common_.SetState(WebSocketCommon::kOpen);
was_ever_connected_ = true;
- // Don't read all of a huge initial message before read() has been called.
- channel_->ApplyBackpressure();
auto* connection = MakeGarbageCollected<WebSocketConnection>();
connection->setProtocol(subprotocol);
connection->setExtensions(extensions);
@@ -598,7 +597,24 @@ void WebSocketStream::Connect(ScriptState* script_state,
DVLOG(1) << "WebSocketStream " << this << " Connect() url=" << url
<< " options=" << options;
- // TODO(ricea): Support AbortSignal.
+ // Don't read all of a huge initial message before read() has been called.
+ channel_->ApplyBackpressure();
+
+ auto* signal = options->signal();
+ if (signal && signal->aborted()) {
+ auto exception = V8ThrowDOMException::CreateOrEmpty(
+ script_state->GetIsolate(), DOMExceptionCode::kAbortError,
+ "WebSocket handshake was aborted");
+ connection_resolver_->Reject(exception);
+ closed_resolver_->Reject(exception);
+ return;
+ }
+
+ if (signal) {
+ signal->AddAlgorithm(
+ WTF::Bind(&WebSocketStream::OnAbort, WrapWeakPersistent(this)));
+ }
+
auto result = common_.Connect(
ExecutionContext::From(script_state), url,
options->hasProtocols() ? options->protocols() : Vector<String>(),
@@ -680,6 +696,22 @@ v8::Local<v8::Value> WebSocketStream::CreateNetworkErrorDOMException() {
"A network error occurred");
}
+void WebSocketStream::OnAbort() {
+ DVLOG(1) << "WebSocketStream " << this << " OnAbort()";
+
+ if (was_ever_connected_ || !channel_)
+ return;
+
+ channel_->CancelHandshake();
+ channel_ = nullptr;
+
+ auto exception = V8ThrowDOMException::CreateOrEmpty(
+ script_state_->GetIsolate(), DOMExceptionCode::kAbortError,
+ "WebSocket handshake was aborted");
+ connection_resolver_->Reject(exception);
+ closed_resolver_->Reject(exception);
+}
+
WebSocketCloseInfo* WebSocketStream::MakeCloseInfo(uint16_t code,
const String& reason) {
DVLOG(1) << "WebSocketStream MakeCloseInfo() code=" << code
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.h
index 1438614eb5f..df0ecc29756 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream.h
@@ -108,6 +108,7 @@ class MODULES_EXPORT WebSocketStream final
void CloseInternal(int code,
const String& reason,
ExceptionState& exception_state);
+ void OnAbort();
v8::Local<v8::Value> CreateNetworkErrorDOMException();
static WebSocketCloseInfo* MakeCloseInfo(uint16_t code, const String& reason);
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream_test.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream_test.cc
index 554ed5942fc..d33f4504c64 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_stream_test.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_stream_test.cc
@@ -10,13 +10,19 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.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/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_dom_exception.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/websockets/mock_websocket_channel.h"
#include "third_party/blink/renderer/modules/websockets/websocket_channel.h"
#include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
#include "third_party/blink/renderer/modules/websockets/websocket_close_info.h"
#include "third_party/blink/renderer/modules/websockets/websocket_stream_options.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
namespace blink {
@@ -56,6 +62,39 @@ class WebSocketStreamTest : public ::testing::Test {
channel_, exception_state);
}
+ 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);
+ }
+
+ // Returns the value of the property |key| on object |object|, stringified as
+ // a UTF-8 encoded std::string so that it can be compared and printed by
+ // EXPECT_EQ. |object| must have been verified to be a v8::Object. |key| must
+ // be encoded as latin1. undefined and null values are stringified as
+ // "undefined" and "null" respectively. "undefined" is also used to mean "not
+ // found".
+ std::string PropertyAsString(ScriptState* script_state,
+ v8::Local<v8::Value> object,
+ String key) {
+ v8::Local<v8::Value> value;
+ auto* isolate = script_state->GetIsolate();
+ if (!object.As<v8::Object>()
+ ->GetRealNamedProperty(script_state->GetContext(),
+ V8String(isolate, key))
+ .ToLocal(&value)) {
+ value = v8::Undefined(isolate);
+ }
+
+ v8::String::Utf8Value utf8value(isolate, value);
+ return std::string(*utf8value, utf8value.length());
+ }
+
private:
Persistent<MockWebSocketChannel> channel_;
};
@@ -63,6 +102,9 @@ class WebSocketStreamTest : public ::testing::Test {
TEST_F(WebSocketStreamTest, ConstructWithBadURL) {
V8TestingScope scope;
auto& exception_state = scope.GetExceptionState();
+
+ EXPECT_CALL(Channel(), ApplyBackpressure());
+
auto* stream = Create(scope.GetScriptState(), "bad-scheme:", exception_state);
EXPECT_FALSE(stream);
@@ -72,7 +114,7 @@ TEST_F(WebSocketStreamTest, ConstructWithBadURL) {
EXPECT_EQ(
"The URL's scheme must be either 'ws' or 'wss'. 'bad-scheme' is not "
"allowed.",
- scope.GetExceptionState().Message());
+ exception_state.Message());
}
// Most coverage for bad constructor arguments is provided by
@@ -84,6 +126,7 @@ TEST_F(WebSocketStreamTest, Connect) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(), Connect(KURL("ws://example.com/hoge"), String()))
.WillOnce(Return(true));
}
@@ -100,6 +143,7 @@ TEST_F(WebSocketStreamTest, ConnectWithProtocols) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(),
Connect(KURL("ws://example.com/chat"), String("chat0, chat1")))
.WillOnce(Return(true));
@@ -119,22 +163,36 @@ TEST_F(WebSocketStreamTest, ConnectWithFailedHandshake) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(), Connect(KURL("ws://example.com/chat"), String()))
.WillOnce(Return(true));
EXPECT_CALL(Channel(), Disconnect());
}
- auto* stream = Create(scope.GetScriptState(), "ws://example.com/chat",
- ASSERT_NO_EXCEPTION);
+ auto* script_state = scope.GetScriptState();
+ auto* stream =
+ Create(script_state, "ws://example.com/chat", ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream);
EXPECT_EQ(KURL("ws://example.com/chat"), stream->url());
+ ScriptPromiseTester connection_tester(script_state,
+ stream->connection(script_state));
+ ScriptPromiseTester closed_tester(script_state, stream->closed(script_state));
+
stream->DidError();
stream->DidClose(WebSocketChannelClient::kClosingHandshakeIncomplete,
WebSocketChannel::kCloseEventCodeAbnormalClosure, String());
- // TODO(ricea): Verify the promises are rejected correctly.
+ connection_tester.WaitUntilSettled();
+ closed_tester.WaitUntilSettled();
+
+ EXPECT_TRUE(connection_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, connection_tester.Value(),
+ DOMExceptionCode::kNetworkError));
+ EXPECT_TRUE(closed_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, closed_tester.Value(),
+ DOMExceptionCode::kNetworkError));
}
TEST_F(WebSocketStreamTest, ConnectWithSuccessfulHandshake) {
@@ -143,25 +201,41 @@ TEST_F(WebSocketStreamTest, ConnectWithSuccessfulHandshake) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(),
Connect(KURL("ws://example.com/chat"), String("chat")))
.WillOnce(Return(true));
- EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(Channel(), Close(1001, String()));
}
auto* options = WebSocketStreamOptions::Create();
options->setProtocols({"chat"});
- auto* stream = Create(scope.GetScriptState(), "ws://example.com/chat",
- options, ASSERT_NO_EXCEPTION);
+ auto* script_state = scope.GetScriptState();
+ auto* stream = Create(script_state, "ws://example.com/chat", options,
+ ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream);
EXPECT_EQ(KURL("ws://example.com/chat"), stream->url());
+ ScriptPromiseTester connection_tester(script_state,
+ stream->connection(script_state));
+
stream->DidConnect("chat", "permessage-deflate");
- // TODO(ricea): Verify the connection promise is resolved correctly.
+ connection_tester.WaitUntilSettled();
+
+ EXPECT_TRUE(connection_tester.IsFulfilled());
+ v8::Local<v8::Value> value = connection_tester.Value().V8Value();
+ ASSERT_FALSE(value.IsEmpty());
+ ASSERT_TRUE(value->IsObject());
+ EXPECT_EQ(PropertyAsString(script_state, value, "readable"),
+ "[object ReadableStream]");
+ EXPECT_EQ(PropertyAsString(script_state, value, "writable"),
+ "[object WritableStream]");
+ EXPECT_EQ(PropertyAsString(script_state, value, "protocol"), "chat");
+ EXPECT_EQ(PropertyAsString(script_state, value, "extensions"),
+ "permessage-deflate");
// Destruction of V8TestingScope causes Close() to be called.
checkpoint.Call(1);
@@ -172,22 +246,36 @@ TEST_F(WebSocketStreamTest, ConnectThenCloseCleanly) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(), Connect(KURL("ws://example.com/echo"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(), Close(-1, String("")));
EXPECT_CALL(Channel(), Disconnect());
}
- auto* stream = Create(scope.GetScriptState(), "ws://example.com/echo",
- ASSERT_NO_EXCEPTION);
+ auto* script_state = scope.GetScriptState();
+ auto* stream =
+ Create(script_state, "ws://example.com/echo", ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream);
stream->DidConnect("", "");
+
+ ScriptPromiseTester closed_tester(script_state, stream->closed(script_state));
+
stream->close(MakeGarbageCollected<WebSocketCloseInfo>(),
scope.GetExceptionState());
stream->DidClose(WebSocketChannelClient::kClosingHandshakeComplete, 1005, "");
+
+ closed_tester.WaitUntilSettled();
+ EXPECT_TRUE(closed_tester.IsFulfilled());
+ ASSERT_TRUE(closed_tester.Value().IsObject());
+ EXPECT_EQ(
+ PropertyAsString(script_state, closed_tester.Value().V8Value(), "code"),
+ "1005");
+ EXPECT_EQ(
+ PropertyAsString(script_state, closed_tester.Value().V8Value(), "reason"),
+ "");
}
TEST_F(WebSocketStreamTest, CloseDuringHandshake) {
@@ -195,6 +283,7 @@ TEST_F(WebSocketStreamTest, CloseDuringHandshake) {
{
InSequence s;
+ EXPECT_CALL(Channel(), ApplyBackpressure());
EXPECT_CALL(Channel(), Connect(KURL("ws://example.com/echo"), String()))
.WillOnce(Return(true));
EXPECT_CALL(
@@ -205,15 +294,30 @@ TEST_F(WebSocketStreamTest, CloseDuringHandshake) {
EXPECT_CALL(Channel(), Disconnect());
}
+ auto* script_state = scope.GetScriptState();
auto* stream = Create(scope.GetScriptState(), "ws://example.com/echo",
ASSERT_NO_EXCEPTION);
EXPECT_TRUE(stream);
+ ScriptPromiseTester connection_tester(script_state,
+ stream->connection(script_state));
+ ScriptPromiseTester closed_tester(script_state, stream->closed(script_state));
+
stream->close(MakeGarbageCollected<WebSocketCloseInfo>(),
scope.GetExceptionState());
stream->DidClose(WebSocketChannelClient::kClosingHandshakeIncomplete, 1006,
"");
+
+ connection_tester.WaitUntilSettled();
+ closed_tester.WaitUntilSettled();
+
+ EXPECT_TRUE(connection_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, connection_tester.Value(),
+ DOMExceptionCode::kNetworkError));
+ EXPECT_TRUE(closed_tester.IsRejected());
+ EXPECT_TRUE(IsDOMException(script_state, closed_tester.Value(),
+ DOMExceptionCode::kNetworkError));
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb.cc b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
index 2585c1b6cd2..cbe336ae699 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
@@ -9,7 +9,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/device/public/mojom/usb_device.mojom-blink.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.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"
@@ -299,7 +299,7 @@ void USB::EnsureServiceConnection() {
// See https://bit.ly/2S0zRAS for task types.
auto task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
- GetExecutionContext()->GetInterfaceProvider()->GetInterface(
+ GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
service_.BindNewPipeAndPassReceiver(task_runner));
service_.set_disconnect_handler(
WTF::Bind(&USB::OnServiceConnectionError, WrapWeakPersistent(this)));
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb.h b/chromium/third_party/blink/renderer/modules/webusb/usb.h
index 39dbd680878..5a8d54156fa 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb.h
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb.h
@@ -7,7 +7,7 @@
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/usb_manager.mojom-blink.h"
+#include "services/device/public/mojom/usb_manager.mojom-blink-forward.h"
#include "services/device/public/mojom/usb_manager_client.mojom-blink.h"
#include "third_party/blink/public/mojom/usb/web_usb_service.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
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 35f15124faf..5985cec332c 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -349,16 +349,24 @@ ScriptPromise USBDevice::controlTransferIn(
unsigned length) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- if (EnsureDeviceConfigured(resolver)) {
- auto parameters = ConvertControlTransferParameters(setup, resolver);
- if (parameters) {
- device_requests_.insert(resolver);
- device_->ControlTransferIn(
- std::move(parameters), length, 0,
- WTF::Bind(&USBDevice::AsyncControlTransferIn, WrapPersistent(this),
- WrapPersistent(resolver)));
- }
+ if (!EnsureNoDeviceOrInterfaceChangeInProgress(resolver))
+ return promise;
+
+ if (!opened_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kOpenRequired));
+ return promise;
}
+
+ auto parameters = ConvertControlTransferParameters(setup, resolver);
+ if (!parameters)
+ return promise;
+
+ device_requests_.insert(resolver);
+ device_->ControlTransferIn(
+ std::move(parameters), length, 0,
+ WTF::Bind(&USBDevice::AsyncControlTransferIn, WrapPersistent(this),
+ WrapPersistent(resolver)));
return promise;
}
@@ -367,16 +375,24 @@ ScriptPromise USBDevice::controlTransferOut(
const USBControlTransferParameters* setup) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- if (EnsureDeviceConfigured(resolver)) {
- auto parameters = ConvertControlTransferParameters(setup, resolver);
- if (parameters) {
- device_requests_.insert(resolver);
- device_->ControlTransferOut(
- std::move(parameters), Vector<uint8_t>(), 0,
- WTF::Bind(&USBDevice::AsyncControlTransferOut, WrapPersistent(this),
- 0, WrapPersistent(resolver)));
- }
+ if (!EnsureNoDeviceOrInterfaceChangeInProgress(resolver))
+ return promise;
+
+ if (!opened_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kOpenRequired));
+ return promise;
}
+
+ auto parameters = ConvertControlTransferParameters(setup, resolver);
+ if (!parameters)
+ return promise;
+
+ device_requests_.insert(resolver);
+ device_->ControlTransferOut(
+ std::move(parameters), Vector<uint8_t>(), 0,
+ WTF::Bind(&USBDevice::AsyncControlTransferOut, WrapPersistent(this), 0,
+ WrapPersistent(resolver)));
return promise;
}
@@ -386,9 +402,15 @@ ScriptPromise USBDevice::controlTransferOut(
const ArrayBufferOrArrayBufferView& data) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- if (!EnsureDeviceConfigured(resolver))
+ if (!EnsureNoDeviceOrInterfaceChangeInProgress(resolver))
return promise;
+ if (!opened_) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kOpenRequired));
+ return promise;
+ }
+
auto parameters = ConvertControlTransferParameters(setup, resolver);
if (!parameters)
return promise;
@@ -589,62 +611,83 @@ bool USBDevice::IsProtectedInterfaceClass(wtf_size_t interface_index) const {
return false;
}
-bool USBDevice::EnsureNoDeviceOrInterfaceChangeInProgress(
+bool USBDevice::EnsureNoDeviceChangeInProgress(
ScriptPromiseResolver* resolver) const {
if (!device_) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotFoundError, kDeviceDisconnected));
- } else if (device_state_change_in_progress_) {
+ return false;
+ }
+
+ if (device_state_change_in_progress_) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError, kDeviceStateChangeInProgress));
- } else if (AnyInterfaceChangeInProgress()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool USBDevice::EnsureNoDeviceOrInterfaceChangeInProgress(
+ ScriptPromiseResolver* resolver) const {
+ if (!EnsureNoDeviceChangeInProgress(resolver))
+ return false;
+
+ if (AnyInterfaceChangeInProgress()) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError, kInterfaceStateChangeInProgress));
- } else {
- return true;
+ return false;
}
- return false;
+
+ return true;
}
bool USBDevice::EnsureDeviceConfigured(ScriptPromiseResolver* resolver) const {
- if (!device_) {
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kNotFoundError, kDeviceDisconnected));
- } else if (device_state_change_in_progress_) {
- resolver->Reject(MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kDeviceStateChangeInProgress));
- } else if (!opened_) {
+ if (!EnsureNoDeviceChangeInProgress(resolver))
+ return false;
+
+ if (!opened_) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError, kOpenRequired));
- } else if (configuration_index_ == kNotFound) {
+ return false;
+ }
+
+ if (configuration_index_ == kNotFound) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError,
"The device must have a configuration selected."));
- } else {
- return true;
+ return false;
}
- return false;
+
+ return true;
}
bool USBDevice::EnsureInterfaceClaimed(uint8_t interface_number,
ScriptPromiseResolver* resolver) const {
if (!EnsureDeviceConfigured(resolver))
return false;
+
wtf_size_t interface_index = FindInterfaceIndex(interface_number);
if (interface_index == kNotFound) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotFoundError, kInterfaceNotFound));
- } else if (interface_state_change_in_progress_[interface_index]) {
+ return false;
+ }
+
+ if (interface_state_change_in_progress_[interface_index]) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError, kInterfaceStateChangeInProgress));
- } else if (!claimed_interfaces_[interface_index]) {
+ return false;
+ }
+
+ if (!claimed_interfaces_[interface_index]) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError,
"The specified interface has not been claimed."));
- } else {
- return true;
+ return false;
}
- return false;
+
+ return true;
}
bool USBDevice::EnsureEndpointAvailable(bool in_transfer,
@@ -652,12 +695,14 @@ bool USBDevice::EnsureEndpointAvailable(bool in_transfer,
ScriptPromiseResolver* resolver) const {
if (!EnsureDeviceConfigured(resolver))
return false;
+
if (endpoint_number == 0 || endpoint_number >= kEndpointsBitsNumber) {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kIndexSizeError,
"The specified endpoint number is out of range."));
return false;
}
+
auto& bit_vector = in_transfer ? in_endpoints_ : out_endpoints_;
if (!bit_vector[endpoint_number - 1]) {
resolver->Reject(MakeGarbageCollected<DOMException>(
@@ -667,6 +712,7 @@ bool USBDevice::EnsureEndpointAvailable(bool in_transfer,
"interface."));
return false;
}
+
return true;
}
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 d6319b55d1f..774a66bd3ce 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.h
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.h
@@ -116,6 +116,7 @@ class USBDevice : public ScriptWrappable, public ContextLifecycleObserver {
wtf_size_t FindAlternateIndex(wtf_size_t interface_index,
uint8_t alternate_setting) const;
bool IsProtectedInterfaceClass(wtf_size_t interface_index) const;
+ bool EnsureNoDeviceChangeInProgress(ScriptPromiseResolver*) const;
bool EnsureNoDeviceOrInterfaceChangeInProgress(ScriptPromiseResolver*) const;
bool EnsureDeviceConfigured(ScriptPromiseResolver*) const;
bool EnsureInterfaceClaimed(uint8_t interface_number,
diff --git a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
index d6dfe7219d7..ac6f487986f 100644
--- a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -44,6 +44,8 @@ blink_modules_sources("xr") {
"xr_input_source_event.h",
"xr_input_sources_change_event.cc",
"xr_input_sources_change_event.h",
+ "xr_native_origin_information.cc",
+ "xr_native_origin_information.h",
"xr_object_space.h",
"xr_plane.cc",
"xr_plane.h",
diff --git a/chromium/third_party/blink/renderer/modules/xr/DEPS b/chromium/third_party/blink/renderer/modules/xr/DEPS
index a66627d651d..ab8648248ac 100644
--- a/chromium/third_party/blink/renderer/modules/xr/DEPS
+++ b/chromium/third_party/blink/renderer/modules/xr/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+mojo/public/cpp/bindings/binding.h",
"+mojo/public/cpp/system/platform_handle.h",
"+device/vr/public/mojom/vr_service.mojom-blink.h",
+ "+device/vr/public/mojom/vr_service.mojom-blink-forward.h",
"+gpu/command_buffer/client/gles2_interface.h",
"+gpu/command_buffer/common/mailbox_holder.h",
"+services/metrics/public/cpp/ukm_builders.h",
diff --git a/chromium/third_party/blink/renderer/modules/xr/navigator_xr.h b/chromium/third_party/blink/renderer/modules/xr/navigator_xr.h
index 988e4025266..5ed2491e47d 100644
--- a/chromium/third_party/blink/renderer/modules/xr/navigator_xr.h
+++ b/chromium/third_party/blink/renderer/modules/xr/navigator_xr.h
@@ -15,9 +15,8 @@ namespace blink {
class Document;
class XR;
-class MODULES_EXPORT NavigatorXR final
- : public GarbageCollectedFinalized<NavigatorXR>,
- public Supplement<Navigator> {
+class MODULES_EXPORT NavigatorXR final : public GarbageCollected<NavigatorXR>,
+ public Supplement<Navigator> {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorXR);
public:
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr.cc b/chromium/third_party/blink/renderer/modules/xr/xr.cc
index 7a66e509c20..72a09f5e834 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr.cc
@@ -7,14 +7,18 @@
#include <utility>
#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/local_frame.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/inspector/console_message.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/modules/event_modules.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
@@ -25,6 +29,7 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
namespace blink {
namespace {
@@ -52,6 +57,20 @@ const char kImmersiveArModeNotValid[] =
"Failed to execute '%s' on 'XR': The provided value 'immersive-ar' is not "
"a valid enum value of type XRSessionMode.";
+constexpr device::mojom::XRSessionFeature kDefaultImmersiveVrFeatures[] = {
+ device::mojom::XRSessionFeature::REF_SPACE_VIEWER,
+ device::mojom::XRSessionFeature::REF_SPACE_LOCAL,
+};
+
+constexpr device::mojom::XRSessionFeature kDefaultImmersiveArFeatures[] = {
+ device::mojom::XRSessionFeature::REF_SPACE_VIEWER,
+ device::mojom::XRSessionFeature::REF_SPACE_LOCAL,
+};
+
+constexpr device::mojom::XRSessionFeature kDefaultInlineFeatures[] = {
+ device::mojom::XRSessionFeature::REF_SPACE_VIEWER,
+};
+
// Helper method to convert session mode into Mojo options.
device::mojom::blink::XRSessionOptionsPtr convertModeToMojo(
XRSession::SessionMode mode) {
@@ -79,7 +98,7 @@ XRSession::SessionMode stringToSessionMode(const String& mode_string) {
return XRSession::kModeInline;
}
-const char* SessionModeToString(XRSession::SessionMode session_mode) {
+const char* SessionModeToString(const XRSession::SessionMode& session_mode) {
switch (session_mode) {
case XRSession::SessionMode::kModeInline:
return "inline";
@@ -97,6 +116,7 @@ const char* SessionModeToString(XRSession::SessionMode session_mode) {
// unrecognized, returns nullopt. Based on the spec:
// https://immersive-web.github.io/webxr/#feature-name
base::Optional<device::mojom::XRSessionFeature> StringToXRSessionFeature(
+ const Document* doc,
const String& feature_string) {
if (feature_string == "viewer") {
return device::mojom::XRSessionFeature::REF_SPACE_VIEWER;
@@ -108,6 +128,9 @@ base::Optional<device::mojom::XRSessionFeature> StringToXRSessionFeature(
return device::mojom::XRSessionFeature::REF_SPACE_BOUNDED_FLOOR;
} else if (feature_string == "unbounded") {
return device::mojom::XRSessionFeature::REF_SPACE_UNBOUNDED;
+ } else if (RuntimeEnabledFeatures::WebXRARDOMOverlayEnabled(doc) &&
+ feature_string == "dom-overlay-for-handheld-ar") {
+ return device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR;
}
return base::nullopt;
@@ -124,41 +147,27 @@ bool IsFeatureValidForMode(device::mojom::XRSessionFeature feature,
case device::mojom::XRSessionFeature::REF_SPACE_UNBOUNDED:
return mode == XRSession::kModeImmersiveVR ||
mode == XRSession::kModeImmersiveAR;
+ case device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR:
+ return mode == XRSession::kModeImmersiveAR;
}
}
-template <typename Fn>
-XRSessionFeatureSet ParseRequestedFeatures(
- const WTF::Vector<ScriptValue>& features,
- XRSession::SessionMode session_mode,
- Fn&& error_fn) {
- XRSessionFeatureSet result;
-
- // Iterate over all requested features, even if intermediate
- // elements are found to be invalid.
- for (const auto& feature : features) {
- String feature_string;
- if (feature.ToString(feature_string)) {
- auto feature_enum = StringToXRSessionFeature(feature_string);
+bool HasRequiredFeaturePolicy(const Document* doc,
+ device::mojom::XRSessionFeature feature) {
+ if (!doc)
+ return false;
- if (!feature_enum) {
- String error_message =
- "Unrecognized feature requested: " + feature_string;
- error_fn(std::move(error_message));
- } else if (!IsFeatureValidForMode(feature_enum.value(), session_mode)) {
- String error_message =
- "Feature '" + feature_string +
- "' is not supported for mode: " + SessionModeToString(session_mode);
- error_fn(std::move(error_message));
- } else {
- result.insert(feature_enum.value());
- }
- } else {
- error_fn("Unrecognized feature value");
- }
+ switch (feature) {
+ case device::mojom::XRSessionFeature::REF_SPACE_VIEWER:
+ return true;
+ case device::mojom::XRSessionFeature::REF_SPACE_LOCAL:
+ case device::mojom::XRSessionFeature::REF_SPACE_LOCAL_FLOOR:
+ case device::mojom::XRSessionFeature::REF_SPACE_BOUNDED_FLOOR:
+ case device::mojom::XRSessionFeature::REF_SPACE_UNBOUNDED:
+ case device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR:
+ return doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebXr,
+ ReportOptions::kReportOnFailure);
}
-
- return result;
}
// Ensure that the immersive session request is allowed, if not
@@ -177,11 +186,6 @@ const char* CheckImmersiveSessionRequestAllowed(LocalFrame* frame,
return kPageNotVisible;
}
- if (!doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebXr,
- ReportOptions::kReportOnFailure)) {
- return kFeaturePolicyBlocked;
- }
-
// Consent occurs in the Browser process.
return nullptr;
@@ -194,7 +198,6 @@ const char* CheckImmersiveSessionRequestAllowed(LocalFrame* frame,
// https://immersive-web.github.io/webxr/#inline-session-request-is-allowed
const char* XR::CheckInlineSessionRequestAllowed(
LocalFrame* frame,
- Document* doc,
const PendingRequestSessionQuery& query) {
// Without user activation, we must reject the session if *any* features
// (optional or required) were present, whether or not they were recognized.
@@ -219,26 +222,33 @@ const char* XR::CheckInlineSessionRequestAllowed(
}
}
- // Make sure the WebXR feature policy is enabled
- if (!doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebXr,
- ReportOptions::kReportOnFailure)) {
- return kFeaturePolicyBlocked;
- }
-
return nullptr;
}
XR::PendingSupportsSessionQuery::PendingSupportsSessionQuery(
ScriptPromiseResolver* resolver,
- XRSession::SessionMode session_mode)
- : resolver_(resolver), mode_(session_mode) {}
+ XRSession::SessionMode session_mode,
+ bool throw_on_unsupported)
+ : resolver_(resolver),
+ mode_(session_mode),
+ throw_on_unsupported_(throw_on_unsupported) {}
void XR::PendingSupportsSessionQuery::Trace(blink::Visitor* visitor) {
visitor->Trace(resolver_);
}
-void XR::PendingSupportsSessionQuery::Resolve() {
- resolver_->Resolve();
+void XR::PendingSupportsSessionQuery::Resolve(bool supported,
+ ExceptionState* exception_state) {
+ if (throw_on_unsupported_) {
+ if (supported) {
+ resolver_->Resolve();
+ } else {
+ RejectWithDOMException(DOMExceptionCode::kNotSupportedError,
+ kSessionNotSupported, exception_state);
+ }
+ } else {
+ resolver_->Resolve(supported);
+ }
}
void XR::PendingSupportsSessionQuery::RejectWithDOMException(
@@ -248,7 +258,11 @@ void XR::PendingSupportsSessionQuery::RejectWithDOMException(
DCHECK_NE(exception_code, DOMExceptionCode::kSecurityError);
if (exception_state) {
+ // The generated bindings will reject the returned promise for us.
+ // Detaching the resolver prevents it from thinking we abandoned
+ // the promise.
exception_state->ThrowDOMException(exception_code, message);
+ resolver_->Detach();
} else {
resolver_->Reject(
MakeGarbageCollected<DOMException>(exception_code, message));
@@ -259,7 +273,11 @@ void XR::PendingSupportsSessionQuery::RejectWithSecurityError(
const String& sanitized_message,
ExceptionState* exception_state) {
if (exception_state) {
+ // The generated V8 bindings will reject the returned promise for us.
+ // Detaching the resolver prevents it from thinking we abandoned
+ // the promise.
exception_state->ThrowSecurityError(sanitized_message);
+ resolver_->Detach();
} else {
resolver_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, sanitized_message));
@@ -270,7 +288,11 @@ void XR::PendingSupportsSessionQuery::RejectWithTypeError(
const String& message,
ExceptionState* exception_state) {
if (exception_state) {
+ // The generated bindings will reject the returned promise for us.
+ // Detaching the resolver prevents it from thinking we abandoned
+ // the promise.
exception_state->ThrowTypeError(message);
+ resolver_->Detach();
} else {
resolver_->Reject(V8ThrowException::CreateTypeError(
resolver_->GetScriptState()->GetIsolate(), message));
@@ -306,6 +328,7 @@ void XR::PendingRequestSessionQuery::RejectWithDOMException(
if (exception_state) {
exception_state->ThrowDOMException(exception_code, message);
+ resolver_->Detach();
} else {
resolver_->Reject(
MakeGarbageCollected<DOMException>(exception_code, message));
@@ -319,6 +342,7 @@ void XR::PendingRequestSessionQuery::RejectWithSecurityError(
ExceptionState* exception_state) {
if (exception_state) {
exception_state->ThrowSecurityError(sanitized_message);
+ resolver_->Detach();
} else {
resolver_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kSecurityError, sanitized_message));
@@ -332,6 +356,7 @@ void XR::PendingRequestSessionQuery::RejectWithTypeError(
ExceptionState* exception_state) {
if (exception_state) {
exception_state->ThrowTypeError(message);
+ resolver_->Detach();
} else {
resolver_->Reject(V8ThrowException::CreateTypeError(
GetScriptState()->GetIsolate(), message));
@@ -405,9 +430,10 @@ XR::XR(LocalFrame& frame, int64_t ukm_source_id)
{SchedulingPolicy::RecordMetricsForBackForwardCache()})) {
// See https://bit.ly/2S0zRAS for task types.
DCHECK(frame.IsAttached());
- frame.GetInterfaceProvider().GetInterface(mojo::MakeRequest(
- &service_, frame.GetTaskRunner(TaskType::kMiscPlatformAPI)));
- service_.set_connection_error_handler(
+ frame.GetBrowserInterfaceBroker().GetInterface(
+ service_.BindNewPipeAndPassReceiver(
+ frame.GetTaskRunner(TaskType::kMiscPlatformAPI)));
+ service_.set_disconnect_handler(
WTF::Bind(&XR::Dispose, WrapWeakPersistent(this)));
}
@@ -441,19 +467,9 @@ XRFrameProvider* XR::frameProvider() {
return frame_provider_;
}
-bool XR::CanRequestNonImmersiveFrameData() const {
- return !!magic_window_provider_;
-}
-
-void XR::GetNonImmersiveFrameData(
- device::mojom::blink::XRFrameDataRequestOptionsPtr options,
- device::mojom::blink::XRFrameDataProvider::GetFrameDataCallback callback) {
- DCHECK(CanRequestNonImmersiveFrameData());
- magic_window_provider_->GetFrameData(std::move(options), std::move(callback));
-}
-
-const device::mojom::blink::XREnvironmentIntegrationProviderAssociatedPtr&
-XR::xrEnvironmentProviderPtr() {
+const mojo::AssociatedRemote<
+ device::mojom::blink::XREnvironmentIntegrationProvider>&
+XR::xrEnvironmentProviderRemote() {
return environment_provider_;
}
@@ -465,26 +481,87 @@ void XR::AddEnvironmentProviderErrorHandler(
void XR::ExitPresent() {
DCHECK(service_);
service_->ExitPresent();
+
+ // If the document was potentially being shown in a DOM overlay via
+ // fullscreened elements, make sure to clear any fullscreen states on exiting
+ // the session. This avoids a race condition:
+ // - browser side ends session and exits fullscreen (i.e. back button)
+ // - renderer processes WebViewImpl::ExitFullscreen via ChromeClient
+ // - JS application sets a new element to fullscreen, this is allowed
+ // because doc->IsImmersiveArOverlay() is still true at this point
+ // - renderer processes XR session shutdown (this method)
+ // - browser re-enters fullscreen unexpectedly
+ LocalFrame* frame = GetFrame();
+ if (!frame)
+ return;
+
+ Document* doc = frame->GetDocument();
+ DCHECK(doc);
+ if (doc->IsImmersiveArOverlay()) {
+ doc->SetIsImmersiveArOverlay(false);
+ Element* fullscreen_element = Fullscreen::FullscreenElementFrom(*doc);
+ if (fullscreen_element) {
+ // "ua_originated" means that the browser process already exited
+ // fullscreen. Set it to false because we need the browser process
+ // to get notified that it needs to exit fullscreen. Use
+ // FullyExitFullscreen to ensure that we return to non-fullscreen mode.
+ // ExitFullscreen only unfullscreens a single element, potentially
+ // leaving others in fullscreen mode.
+ constexpr bool kUaOriginated = false;
+ Fullscreen::FullyExitFullscreen(*doc, kUaOriginated);
+ }
+ // Restore the FrameView background color that was changed in
+ // OnRequestSessionReturned.
+ auto* frame_view = doc->GetLayoutView()->GetFrameView();
+ // SetBaseBackgroundColor updates composited layer mappings.
+ // That DCHECKs IsAllowedToQueryCompositingState which requires
+ // DocumentLifecycle >= kInCompositingUpdate.
+ frame_view->UpdateLifecycleToCompositingInputsClean();
+ frame_view->SetBaseBackgroundColor(original_base_background_color_);
+ }
+}
+
+void XR::SetFramesThrottled(const XRSession* session, bool throttled) {
+ // The service only cares if the immersive session is throttling frames.
+ if (session->immersive()) {
+ // If we have an immersive session, we should have a service.
+ DCHECK(service_);
+ service_->SetFramesThrottled(throttled);
+ }
}
ScriptPromise XR::supportsSession(ScriptState* script_state,
const String& mode,
ExceptionState& exception_state) {
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- ScriptPromise promise = resolver->Promise();
+ return InternalIsSessionSupported(script_state, mode, exception_state, true);
+}
+
+ScriptPromise XR::isSessionSupported(ScriptState* script_state,
+ const String& mode,
+ ExceptionState& exception_state) {
+ return InternalIsSessionSupported(script_state, mode, exception_state, false);
+}
+ScriptPromise XR::InternalIsSessionSupported(ScriptState* script_state,
+ const String& mode,
+ ExceptionState& exception_state,
+ bool throw_on_unsupported) {
LocalFrame* frame = GetFrame();
Document* doc = frame ? frame->GetDocument() : nullptr;
if (!doc) {
// Reject if the frame or document is inaccessible.
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kNavigatorDetachedError);
- return promise;
+ return ScriptPromise(); // Will be rejected by generated bindings
}
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
XRSession::SessionMode session_mode = stringToSessionMode(mode);
PendingSupportsSessionQuery* query =
- MakeGarbageCollected<PendingSupportsSessionQuery>(resolver, session_mode);
+ MakeGarbageCollected<PendingSupportsSessionQuery>(resolver, session_mode,
+ throw_on_unsupported);
if (session_mode == XRSession::kModeImmersiveAR &&
!RuntimeEnabledFeatures::WebXRARModuleEnabled(doc)) {
@@ -494,6 +571,12 @@ ScriptPromise XR::supportsSession(ScriptState* script_state,
return promise;
}
+ if (session_mode == XRSession::kModeInline) {
+ // inline sessions are always supported.
+ query->Resolve(true);
+ return promise;
+ }
+
if (!doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebXr,
ReportOptions::kReportOnFailure)) {
// Only allow the call to be made if the appropriate feature policy is in
@@ -502,27 +585,21 @@ ScriptPromise XR::supportsSession(ScriptState* script_state,
return promise;
}
- if (session_mode == XRSession::kModeInline) {
- // `inline` sessions are always supported if not blocked by feature policy.
- query->Resolve();
- } else {
- if (!service_) {
- // If we don't have a service at the time we reach this call it indicates
- // that there's no WebXR hardware. Reject as not supported.
- query->RejectWithDOMException(DOMExceptionCode::kNotSupportedError,
- kSessionNotSupported, &exception_state);
- return promise;
- }
+ if (!service_) {
+ // If we don't have a service at the time we reach this call it indicates
+ // that there's no WebXR hardware. Reject as not supported.
+ query->Resolve(false, &exception_state);
+ return promise;
+ }
- device::mojom::blink::XRSessionOptionsPtr session_options =
- convertModeToMojo(query->mode());
+ device::mojom::blink::XRSessionOptionsPtr session_options =
+ convertModeToMojo(query->mode());
- outstanding_support_queries_.insert(query);
- service_->SupportsSession(
- std::move(session_options),
- WTF::Bind(&XR::OnSupportsSessionReturned, WrapPersistent(this),
- WrapPersistent(query)));
- }
+ outstanding_support_queries_.insert(query);
+ service_->SupportsSession(
+ std::move(session_options),
+ WTF::Bind(&XR::OnSupportsSessionReturned, WrapPersistent(this),
+ WrapPersistent(query)));
return promise;
}
@@ -539,15 +616,6 @@ void XR::RequestImmersiveSession(LocalFrame* frame,
did_log_request_immersive_session_ = true;
}
- // If its an immersive AR session, make sure that feature is enabled
- if (query->mode() == XRSession::kModeImmersiveAR &&
- !RuntimeEnabledFeatures::WebXRARModuleEnabled(doc)) {
- query->RejectWithTypeError(
- String::Format(kImmersiveArModeNotValid, "requestSession"),
- exception_state);
- return;
- }
-
// Make sure the request is allowed
auto* immersive_session_request_error =
CheckImmersiveSessionRequestAllowed(frame, doc);
@@ -593,12 +661,11 @@ void XR::RequestImmersiveSession(LocalFrame* frame,
}
void XR::RequestInlineSession(LocalFrame* frame,
- Document* doc,
PendingRequestSessionQuery* query,
ExceptionState* exception_state) {
// Make sure the inline session request was allowed
auto* inline_session_request_error =
- CheckInlineSessionRequestAllowed(frame, doc, *query);
+ CheckInlineSessionRequestAllowed(frame, *query);
if (inline_session_request_error) {
query->RejectWithSecurityError(inline_session_request_error,
exception_state);
@@ -634,15 +701,57 @@ void XR::RequestInlineSession(LocalFrame* frame,
WrapPersistent(query)));
}
+XR::RequestedXRSessionFeatureSet XR::ParseRequestedFeatures(
+ Document* doc,
+ const HeapVector<ScriptValue>& features,
+ const XRSession::SessionMode& session_mode,
+ mojom::ConsoleMessageLevel error_level) {
+ RequestedXRSessionFeatureSet result;
+
+ // Iterate over all requested features, even if intermediate
+ // elements are found to be invalid.
+ for (const auto& feature : features) {
+ String feature_string;
+ if (feature.ToString(feature_string)) {
+ auto feature_enum = StringToXRSessionFeature(doc, feature_string);
+
+ if (!feature_enum) {
+ GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kJavaScript, error_level,
+ "Unrecognized feature requested: " + feature_string));
+ result.invalid_features = true;
+ } else if (!IsFeatureValidForMode(feature_enum.value(), session_mode)) {
+ GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kJavaScript, error_level,
+ "Feature '" + feature_string + "' is not supported for mode: " +
+ SessionModeToString(session_mode)));
+ result.invalid_features = true;
+ } else if (!HasRequiredFeaturePolicy(doc, feature_enum.value())) {
+ GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
+ mojom::ConsoleMessageSource::kJavaScript, error_level,
+ "Feature '" + feature_string +
+ "' is not permitted by feature policy"));
+ result.invalid_features = true;
+ } else {
+ result.valid_features.insert(feature_enum.value());
+ }
+ } else {
+ GetExecutionContext()->AddConsoleMessage(
+ ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript,
+ error_level, "Unrecognized feature value"));
+ result.invalid_features = true;
+ }
+ }
+
+ return result;
+}
+
ScriptPromise XR::requestSession(ScriptState* script_state,
const String& mode,
XRSessionInit* session_init,
ExceptionState& exception_state) {
// TODO(https://crbug.com/968622): Make sure we don't forget to call
// metrics-related methods when the promise gets resolved/rejected.
- auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
- ScriptPromise promise = resolver->Promise();
-
LocalFrame* frame = GetFrame();
Document* doc = frame ? frame->GetDocument() : nullptr;
if (!doc) {
@@ -652,51 +761,69 @@ ScriptPromise XR::requestSession(ScriptState* script_state,
// Document to get UkmRecorder anyway).
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kNavigatorDetachedError);
- return promise;
+ return ScriptPromise(); // Will be rejected by generated bindings
}
XRSession::SessionMode session_mode = stringToSessionMode(mode);
+ // If the request is for immersive-ar, ensure that feature is enabled.
+ if (session_mode == XRSession::kModeImmersiveAR &&
+ !RuntimeEnabledFeatures::WebXRARModuleEnabled(doc)) {
+ exception_state.ThrowTypeError(
+ String::Format(kImmersiveArModeNotValid, "requestSession"));
+
+ // We haven't created the query yet, so we can't use it to implicitly log
+ // our metrics for us, so explicitly log it here, as the query requires the
+ // features to be parsed before it can be built.
+ ukm::builders::XR_WebXR_SessionRequest(GetSourceId())
+ .SetMode(static_cast<int64_t>(session_mode))
+ .SetStatus(static_cast<int64_t>(SessionRequestStatus::kOtherError))
+ .Record(doc->UkmRecorder());
+ return ScriptPromise();
+ }
+
// Parse required feature strings
RequestedXRSessionFeatureSet required_features;
if (session_init && session_init->hasRequiredFeatures()) {
- required_features.valid_features = ParseRequestedFeatures(
- session_init->requiredFeatures(), session_mode,
- [&](const String& error) {
- GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kError, error));
- required_features.invalid_features = true;
- });
+ required_features = ParseRequestedFeatures(
+ doc, session_init->requiredFeatures(), session_mode,
+ mojom::ConsoleMessageLevel::kError);
}
// Parse optional feature strings
RequestedXRSessionFeatureSet optional_features;
if (session_init && session_init->hasOptionalFeatures()) {
- optional_features.valid_features = ParseRequestedFeatures(
- session_init->optionalFeatures(), session_mode,
- [&](const String& error) {
- GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
- mojom::ConsoleMessageSource::kJavaScript,
- mojom::ConsoleMessageLevel::kWarning, error));
- optional_features.invalid_features = true;
- });
+ optional_features = ParseRequestedFeatures(
+ doc, session_init->optionalFeatures(), session_mode,
+ mojom::ConsoleMessageLevel::kWarning);
}
// Certain session modes imply default features.
- // Add those default features as optional features now.
+ // Add those default features as required features now.
+ base::span<const device::mojom::XRSessionFeature> default_features;
switch (session_mode) {
case XRSession::kModeImmersiveVR:
+ default_features = kDefaultImmersiveVrFeatures;
+ break;
case XRSession::kModeImmersiveAR:
- optional_features.valid_features.insert(
- device::mojom::XRSessionFeature::REF_SPACE_LOCAL);
- FALLTHROUGH;
+ default_features = kDefaultImmersiveArFeatures;
+ break;
case XRSession::kModeInline:
- optional_features.valid_features.insert(
- device::mojom::XRSessionFeature::REF_SPACE_VIEWER);
+ default_features = kDefaultInlineFeatures;
break;
}
+ for (const auto& feature : default_features) {
+ if (HasRequiredFeaturePolicy(doc, feature)) {
+ required_features.valid_features.insert(feature);
+ } else {
+ required_features.invalid_features = true;
+ }
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
PendingRequestSessionQuery* query =
MakeGarbageCollected<PendingRequestSessionQuery>(
GetSourceId(), resolver, session_mode, std::move(required_features),
@@ -708,7 +835,7 @@ ScriptPromise XR::requestSession(ScriptState* script_state,
RequestImmersiveSession(frame, doc, query, &exception_state);
break;
case XRSession::kModeInline:
- RequestInlineSession(frame, doc, query, &exception_state);
+ RequestInlineSession(frame, query, &exception_state);
break;
}
@@ -719,7 +846,11 @@ ScriptPromise XR::requestSession(ScriptState* script_state,
// changed. For example, if a new physical device was connected to the system,
// it might be able to support immersive sessions, where it couldn't before.
void XR::OnDeviceChanged() {
- DispatchEvent(*blink::Event::Create(event_type_names::kDevicechange));
+ LocalFrame* frame = GetFrame();
+ Document* doc = frame ? frame->GetDocument() : nullptr;
+ if (doc && doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebXr)) {
+ DispatchEvent(*blink::Event::Create(event_type_names::kDevicechange));
+ }
}
void XR::OnSupportsSessionReturned(PendingSupportsSessionQuery* query,
@@ -728,13 +859,7 @@ void XR::OnSupportsSessionReturned(PendingSupportsSessionQuery* query,
// promise, so remove it from our outstanding list.
DCHECK(outstanding_support_queries_.Contains(query));
outstanding_support_queries_.erase(query);
-
- if (supports_session) {
- query->Resolve();
- } else {
- query->RejectWithDOMException(DOMExceptionCode::kNotSupportedError,
- kSessionNotSupported, nullptr);
- }
+ query->Resolve(supports_session);
}
void XR::OnRequestSessionReturned(
@@ -798,33 +923,74 @@ void XR::OnRequestSessionReturned(
}
XRSession* session = CreateSession(
- query->mode(), blend_mode, std::move(session_ptr->client_request),
+ query->mode(), blend_mode, std::move(session_ptr->client_receiver),
std::move(session_ptr->display_info), session_ptr->uses_input_eventing,
enabled_features);
+ frameProvider()->OnSessionStarted(session, std::move(session_ptr));
+
if (query->mode() == XRSession::kModeImmersiveVR ||
query->mode() == XRSession::kModeImmersiveAR) {
- frameProvider()->BeginImmersiveSession(session, std::move(session_ptr));
if (environment_integration) {
// See Task Sources spreadsheet for more information:
// https://docs.google.com/spreadsheets/d/1b-dus1Ug3A8y0lX0blkmOjJILisUASdj8x9YN_XMwYc/view
- frameProvider()->GetDataProvider()->GetEnvironmentIntegrationProvider(
- mojo::MakeRequest(&environment_provider_,
- GetExecutionContext()->GetTaskRunner(
- TaskType::kMiscPlatformAPI)));
- environment_provider_.set_connection_error_handler(WTF::Bind(
+ frameProvider()
+ ->GetImmersiveDataProvider()
+ ->GetEnvironmentIntegrationProvider(
+ environment_provider_.BindNewEndpointAndPassReceiver(
+ GetExecutionContext()->GetTaskRunner(
+ TaskType::kMiscPlatformAPI)));
+ environment_provider_.set_disconnect_handler(WTF::Bind(
&XR::OnEnvironmentProviderDisconnect, WrapWeakPersistent(this)));
+
+ session->OnEnvironmentProviderCreated();
+
+ LocalFrame* frame = GetFrame();
+ DCHECK(frame);
+
+ if (enabled_features.Contains(
+ device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR)) {
+ // The session is using DOM overlay mode.
+ Document* doc = frame->GetDocument();
+ DCHECK(doc);
+ doc->SetIsImmersiveArOverlay(true);
+
+ // Save the current base background color (restored in ExitPresent),
+ // and set a transparent background for the FrameView.
+ auto* frame_view = doc->GetLayoutView()->GetFrameView();
+ // SetBaseBackgroundColor updates composited layer mappings.
+ // That DCHECKs IsAllowedToQueryCompositingState which requires
+ // DocumentLifecycle >= kInCompositingUpdate.
+ frame_view->UpdateLifecycleToCompositingInputsClean();
+ original_base_background_color_ = frame_view->BaseBackgroundColor();
+ frame_view->SetBaseBackgroundColor(Color::kTransparent);
+
+ // In DOM overlay mode, entering fullscreen mode needs to be triggered
+ // from the Renderer by actually fullscreening an element. If there
+ // is no current fullscreen element, fullscreen the <body> element
+ // for now. The JS application can use enterFullscreen to change this.
+ //
+ // A TabObserver on the browser side exits the session if there's
+ // no longer a fullscreen element, for example if the JS app manually
+ // unfullscreens the "body" element. That ensures we don't end up in a
+ // hybrid non-fullscreen AR state.
+ Element* fullscreen_element = Fullscreen::FullscreenElementFrom(*doc);
+ if (!fullscreen_element) {
+ Element* body = doc->body();
+ DCHECK(body);
+ // FIXME: this is the "prefixed" version that doesn't generate a
+ // fullscreenchange event and auto-hides navigation bars. Should the
+ // event be generated?
+ Fullscreen::RequestFullscreen(*body);
+ }
+ }
}
if (query->mode() == XRSession::kModeImmersiveVR &&
session->UsesInputEventing()) {
- frameProvider()->GetDataProvider()->SetInputSourceButtonListener(
+ frameProvider()->GetImmersiveDataProvider()->SetInputSourceButtonListener(
session->GetInputClickListener());
}
- } else {
- magic_window_provider_.Bind(std::move(session_ptr->data_provider));
- magic_window_provider_.set_connection_error_handler(WTF::Bind(
- &XR::OnMagicWindowProviderDisconnect, WrapWeakPersistent(this)));
}
UseCounter::Count(ExecutionContext::From(query->GetScriptState()),
@@ -870,15 +1036,15 @@ void XR::ContextDestroyed(ExecutionContext*) {
XRSession* XR::CreateSession(
XRSession::SessionMode mode,
XRSession::EnvironmentBlendMode blend_mode,
- device::mojom::blink::XRSessionClientRequest client_request,
+ mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
+ client_receiver,
device::mojom::blink::VRDisplayInfoPtr display_info,
bool uses_input_eventing,
XRSessionFeatureSet enabled_features,
bool sensorless_session) {
XRSession* session = MakeGarbageCollected<XRSession>(
- this, client_request ? std::move(client_request) : nullptr, mode,
- blend_mode, uses_input_eventing, sensorless_session,
- std::move(enabled_features));
+ this, std::move(client_receiver), mode, blend_mode, uses_input_eventing,
+ sensorless_session, std::move(enabled_features));
if (display_info)
session->SetXRDisplayInfo(std::move(display_info));
sessions_.insert(session);
@@ -906,7 +1072,8 @@ XRSession* XR::CreateSensorlessInlineSession() {
// TODO(https://crbug.com/944936): The blend mode could be "additive".
XRSession::EnvironmentBlendMode blend_mode = XRSession::kBlendModeOpaque;
return CreateSession(XRSession::kModeInline, blend_mode,
- nullptr /* client request */, nullptr /* display_info */,
+ mojo::NullReceiver() /* client receiver */,
+ nullptr /* display_info */,
false /* uses_input_eventing */,
{device::mojom::XRSessionFeature::REF_SPACE_VIEWER},
true /* sensorless_session */);
@@ -950,17 +1117,6 @@ void XR::OnEnvironmentProviderDisconnect() {
environment_provider_.reset();
}
-// Ends all non-immersive sessions when the magic window provider got
-// disconnected.
-void XR::OnMagicWindowProviderDisconnect() {
- for (auto& session : sessions_) {
- if (!session->immersive() && !session->ended()) {
- session->ForceEnd();
- }
- }
- magic_window_provider_.reset();
-}
-
void XR::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_provider_);
visitor->Trace(sessions_);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr.h b/chromium/third_party/blink/renderer/modules/xr/xr.h
index b5ca34a5c4d..654c7199eb4 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr.h
@@ -6,7 +6,10 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
@@ -14,6 +17,7 @@
#include "third_party/blink/renderer/core/page/focus_changed_observer.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
#include "third_party/blink/renderer/modules/xr/xr_session_init.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/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -46,6 +50,9 @@ class XR final : public EventTargetWithInlineData,
ScriptPromise supportsSession(ScriptState*,
const String&,
ExceptionState& exception_state);
+ ScriptPromise isSessionSupported(ScriptState*,
+ const String&,
+ ExceptionState& exception_state);
ScriptPromise requestSession(ScriptState*,
const String&,
XRSessionInit*,
@@ -53,13 +60,9 @@ class XR final : public EventTargetWithInlineData,
XRFrameProvider* frameProvider();
- bool CanRequestNonImmersiveFrameData() const;
- void GetNonImmersiveFrameData(
- device::mojom::blink::XRFrameDataRequestOptionsPtr,
- device::mojom::blink::XRFrameDataProvider::GetFrameDataCallback);
-
- const device::mojom::blink::XREnvironmentIntegrationProviderAssociatedPtr&
- xrEnvironmentProviderPtr();
+ const mojo::AssociatedRemote<
+ device::mojom::blink::XREnvironmentIntegrationProvider>&
+ xrEnvironmentProviderRemote();
// VRServiceClient overrides.
void OnDeviceChanged() override;
@@ -79,11 +82,15 @@ class XR final : public EventTargetWithInlineData,
int64_t GetSourceId() const { return ukm_source_id_; }
using EnvironmentProviderErrorCallback = base::OnceCallback<void()>;
+ // Registers a callback that'll be invoked when mojo invokes a disconnect
+ // handler on the underlying XREnvironmentIntegrationProvider remote.
void AddEnvironmentProviderErrorHandler(
EnvironmentProviderErrorCallback callback);
void ExitPresent();
+ void SetFramesThrottled(const XRSession* session, bool throttled);
+
base::TimeTicks NavigationStart() const { return navigation_start_; }
private:
@@ -109,7 +116,7 @@ class XR final : public EventTargetWithInlineData,
// ScriptPromiseResolver that allows us to add additional logic as certain
// things related to promise's life cycle happen.
class PendingRequestSessionQuery final
- : public GarbageCollectedFinalized<PendingRequestSessionQuery> {
+ : public GarbageCollected<PendingRequestSessionQuery> {
public:
PendingRequestSessionQuery(int64_t ukm_source_id,
ScriptPromiseResolver* resolver,
@@ -175,11 +182,13 @@ class XR final : public EventTargetWithInlineData,
class PendingSupportsSessionQuery final
: public GarbageCollected<PendingSupportsSessionQuery> {
public:
- PendingSupportsSessionQuery(ScriptPromiseResolver*, XRSession::SessionMode);
+ PendingSupportsSessionQuery(ScriptPromiseResolver*,
+ XRSession::SessionMode,
+ bool throw_on_unsupported);
virtual ~PendingSupportsSessionQuery() = default;
// Resolves underlying promise.
- void Resolve();
+ void Resolve(bool supported, ExceptionState* exception_state = nullptr);
// Rejects underlying promise with a DOMException.
// Do not call this with |DOMExceptionCode::kSecurityError|, use
@@ -202,6 +211,8 @@ class XR final : public EventTargetWithInlineData,
void RejectWithTypeError(const String& message,
ExceptionState* exception_state);
+ bool ThrowOnUnsupported() const { return throw_on_unsupported_; }
+
XRSession::SessionMode mode() const;
virtual void Trace(blink::Visitor*);
@@ -210,21 +221,33 @@ class XR final : public EventTargetWithInlineData,
Member<ScriptPromiseResolver> resolver_;
const XRSession::SessionMode mode_;
+ // Only set when calling the deprecated supportsSession method.
+ const bool throw_on_unsupported_ = false;
+
DISALLOW_COPY_AND_ASSIGN(PendingSupportsSessionQuery);
};
+ ScriptPromise InternalIsSessionSupported(ScriptState*,
+ const String&,
+ ExceptionState& exception_state,
+ bool throw_on_unsupported);
+
const char* CheckInlineSessionRequestAllowed(
LocalFrame* frame,
- Document* doc,
const PendingRequestSessionQuery& query);
+ RequestedXRSessionFeatureSet ParseRequestedFeatures(
+ Document* doc,
+ const HeapVector<ScriptValue>& features,
+ const XRSession::SessionMode& session_mode,
+ mojom::ConsoleMessageLevel error_level);
+
void RequestImmersiveSession(LocalFrame* frame,
Document* doc,
PendingRequestSessionQuery* query,
ExceptionState* exception_state);
void RequestInlineSession(LocalFrame* frame,
- Document* doc,
PendingRequestSessionQuery* query,
ExceptionState* exception_state);
@@ -243,7 +266,8 @@ class XR final : public EventTargetWithInlineData,
XRSession* CreateSession(
XRSession::SessionMode mode,
XRSession::EnvironmentBlendMode blend_mode,
- device::mojom::blink::XRSessionClientRequest client_request,
+ mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
+ client_receiver,
device::mojom::blink::VRDisplayInfoPtr display_info,
bool uses_input_eventing,
XRSessionFeatureSet enabled_features,
@@ -256,7 +280,6 @@ class XR final : public EventTargetWithInlineData,
void Dispose();
void OnEnvironmentProviderDisconnect();
- void OnMagicWindowProviderDisconnect();
// Indicates whether use of requestDevice has already been logged.
bool did_log_supports_immersive_ = false;
@@ -275,9 +298,8 @@ class XR final : public EventTargetWithInlineData,
Member<XRFrameProvider> frame_provider_;
HeapHashSet<WeakMember<XRSession>> sessions_;
- device::mojom::blink::VRServicePtr service_;
- device::mojom::blink::XRFrameDataProviderPtr magic_window_provider_;
- device::mojom::blink::XREnvironmentIntegrationProviderAssociatedPtr
+ mojo::Remote<device::mojom::blink::VRService> service_;
+ mojo::AssociatedRemote<device::mojom::blink::XREnvironmentIntegrationProvider>
environment_provider_;
mojo::Receiver<device::mojom::blink::VRServiceClient> receiver_{this};
@@ -287,6 +309,9 @@ class XR final : public EventTargetWithInlineData,
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
feature_handle_for_scheduler_;
+
+ // In DOM overlay mode, save and restore the FrameView background color.
+ Color original_base_background_color_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr.idl b/chromium/third_party/blink/renderer/modules/xr/xr.idl
index a1dab899bba..93aba883d87 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr.idl
@@ -9,6 +9,7 @@
RuntimeEnabled=WebXR
] interface XR : EventTarget {
attribute EventHandler ondevicechange;
- [CallWith=ScriptState, MeasureAs=XRSupportsSession, RaisesException] Promise<void> supportsSession(XRSessionMode mode);
+ [CallWith=ScriptState, DeprecateAs=XRSupportsSession, RaisesException] Promise<void> supportsSession(XRSessionMode mode);
+ [CallWith=ScriptState, MeasureAs=XRIsSessionSupported, RaisesException] Promise<boolean> isSessionSupported(XRSessionMode mode);
[CallWith=ScriptState, MeasureAs=XRRequestSession, RaisesException] Promise<XRSession> requestSession(XRSessionMode mode, optional XRSessionInit options);
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_anchor.cc b/chromium/third_party/blink/renderer/modules/xr/xr_anchor.cc
index 2d04e94018a..322a48a67b2 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_anchor.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_anchor.cc
@@ -10,10 +10,10 @@
namespace blink {
-XRAnchor::XRAnchor(int32_t id, XRSession* session)
+XRAnchor::XRAnchor(uint32_t id, XRSession* session)
: id_(id), session_(session), anchor_data_(base::nullopt) {}
-XRAnchor::XRAnchor(int32_t id,
+XRAnchor::XRAnchor(uint32_t id,
XRSession* session,
const device::mojom::blink::XRAnchorDataPtr& anchor_data,
double timestamp)
@@ -32,6 +32,10 @@ void XRAnchor::Update(const device::mojom::blink::XRAnchorDataPtr& anchor_data,
}
}
+uint32_t XRAnchor::id() const {
+ return id_;
+}
+
XRSpace* XRAnchor::anchorSpace() const {
if (!anchor_data_) {
return nullptr;
@@ -68,8 +72,7 @@ double XRAnchor::lastChangedTime(bool& is_null) const {
}
void XRAnchor::detach() {
- // TODO(992033): Actually detach anchor once anchor creation is implemented.
- DVLOG(2) << "Detaching anchor, id_=" << id_;
+ session_->xr()->xrEnvironmentProviderRemote()->DetachAnchor(id_);
}
void XRAnchor::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_anchor.h b/chromium/third_party/blink/renderer/modules/xr/xr_anchor.h
index fdec8bbb45b..2cc7d985129 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_anchor.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_anchor.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/optional.h"
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -21,13 +21,15 @@ class XRAnchor : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- XRAnchor(int32_t id, XRSession* session);
+ XRAnchor(uint32_t id, XRSession* session);
- XRAnchor(int32_t id,
+ XRAnchor(uint32_t id,
XRSession* session,
const device::mojom::blink::XRAnchorDataPtr& anchor_data,
double timestamp);
+ uint32_t id() const;
+
XRSpace* anchorSpace() const;
TransformationMatrix poseMatrix() const;
@@ -54,7 +56,7 @@ class XRAnchor : public ScriptWrappable {
double timestamp);
};
- const int32_t id_;
+ const uint32_t id_;
Member<XRSession> session_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc
index 03f07672b15..e5a389abe64 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc
@@ -23,7 +23,8 @@ XRBoundedReferenceSpace::XRBoundedReferenceSpace(
XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default;
// No default pose for bounded reference spaces.
-std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::DefaultPose() {
+std::unique_ptr<TransformationMatrix>
+XRBoundedReferenceSpace::DefaultViewerPose() {
return nullptr;
}
@@ -40,12 +41,14 @@ void XRBoundedReferenceSpace::EnsureUpdated() {
if (display_info && display_info->stage_parameters) {
// Use the transform given by xrDisplayInfo's stage_parameters if available.
- floor_level_transform_ = std::make_unique<TransformationMatrix>(
+ bounded_space_from_mojo_ = std::make_unique<TransformationMatrix>(
display_info->stage_parameters->standing_transform.matrix());
// In order to ensure that the bounds continue to line up with the user's
// physical environment we need to transform by the inverse of the
- // originOffset.
+ // originOffset. TODO(https://crbug.com/1008466): move originOffset to
+ // separate class? If yes, that class would need to apply a transform
+ // in the boundsGeometry accessor.
TransformationMatrix bounds_transform = InverseOriginOffsetMatrix();
if (display_info->stage_parameters->bounds) {
@@ -78,31 +81,28 @@ void XRBoundedReferenceSpace::EnsureUpdated() {
} else {
// If stage parameters aren't available set the transform to null, which
// will subsequently cause this reference space to return null poses.
- floor_level_transform_.reset();
+ bounded_space_from_mojo_.reset();
bounds_geometry_.clear();
}
DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this));
}
-// Transforms a given pose from a "base" reference space used by the XR
-// service to the bounded (floor level) reference space. Ideally in the future
-// this reference space can be used without additional transforms, with
-// the various XR backends returning poses already in the right space.
-std::unique_ptr<TransformationMatrix>
-XRBoundedReferenceSpace::TransformBasePose(
- const TransformationMatrix& base_pose) {
+// Gets the pose of the mojo origin in this reference space, corresponding to a
+// transform from mojo coordinates to reference space coordinates. Ideally in
+// the future this reference space can be used without additional transforms,
+// with the various XR backends returning poses already in the right space.
+std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer) {
EnsureUpdated();
// If the reference space has a transform apply it to the base pose and return
// that, otherwise return null.
- if (floor_level_transform_) {
- std::unique_ptr<TransformationMatrix> pose(
- std::make_unique<TransformationMatrix>(*floor_level_transform_));
- pose->Multiply(base_pose);
- return pose;
+ if (bounded_space_from_mojo_) {
+ std::unique_ptr<TransformationMatrix> space_from_mojo(
+ std::make_unique<TransformationMatrix>(*bounded_space_from_mojo_));
+ return space_from_mojo;
}
-
return nullptr;
}
@@ -111,6 +111,11 @@ HeapVector<Member<DOMPointReadOnly>> XRBoundedReferenceSpace::boundsGeometry() {
return bounds_geometry_;
}
+base::Optional<XRNativeOriginInformation>
+XRBoundedReferenceSpace::NativeOrigin() const {
+ return XRNativeOriginInformation::Create(this);
+}
+
void XRBoundedReferenceSpace::Trace(blink::Visitor* visitor) {
visitor->Trace(bounds_geometry_);
XRReferenceSpace::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h
index 61b1170bb0b..8f871b2a961 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h
@@ -19,12 +19,14 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace {
XRBoundedReferenceSpace(XRSession*, XRRigidTransform*);
~XRBoundedReferenceSpace() override;
- std::unique_ptr<TransformationMatrix> DefaultPose() override;
- std::unique_ptr<TransformationMatrix> TransformBasePose(
- const TransformationMatrix& base_pose) override;
+ std::unique_ptr<TransformationMatrix> DefaultViewerPose() override;
+ std::unique_ptr<TransformationMatrix> SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer) override;
HeapVector<Member<DOMPointReadOnly>> boundsGeometry();
+ base::Optional<XRNativeOriginInformation> NativeOrigin() const override;
+
void Trace(blink::Visitor*) override;
void OnReset() override;
@@ -36,7 +38,7 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace {
void EnsureUpdated();
HeapVector<Member<DOMPointReadOnly>> bounds_geometry_;
- std::unique_ptr<TransformationMatrix> floor_level_transform_;
+ std::unique_ptr<TransformationMatrix> bounded_space_from_mojo_;
unsigned int stage_parameters_id_ = 0;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
index bc88ea5d0bb..e40a41feac4 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
@@ -55,8 +55,7 @@ XRCanvasInputProvider::XRCanvasInputProvider(XRSession* session,
canvas->addEventListener(event_type_names::kPointercancel, listener_);
}
-XRCanvasInputProvider::~XRCanvasInputProvider() {
-}
+XRCanvasInputProvider::~XRCanvasInputProvider() {}
void XRCanvasInputProvider::Stop() {
if (!listener_) {
@@ -111,11 +110,12 @@ void XRCanvasInputProvider::UpdateInputSource(PointerEvent* event) {
// projection matrix to get a 3D point in space, which is then returned in
// matrix form so we can use it as an XRInputSource's pointerMatrix.
XRViewData& view = session_->views()[0];
- TransformationMatrix pointer_transform_matrix = view.UnprojectPointer(
+ TransformationMatrix viewer_from_pointer = view.UnprojectPointer(
element_x, element_y, canvas_->OffsetWidth(), canvas_->OffsetHeight());
- // Update the input source's pointer matrix.
- input_source_->SetPointerTransformMatrix(&pointer_transform_matrix);
+ // Update the pointer pose in input space. For screen tapping, input
+ // space is equivalent to viewer space.
+ input_source_->SetInputFromPointer(&viewer_from_pointer);
}
void XRCanvasInputProvider::ClearInputSource() {
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 4f0d67b1ade..3662b8d72ad 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
@@ -19,9 +19,8 @@ class PointerEvent;
class XRInputSource;
class XRSession;
-class XRCanvasInputProvider
- : public GarbageCollectedFinalized<XRCanvasInputProvider>,
- public NameClient {
+class XRCanvasInputProvider : public GarbageCollected<XRCanvasInputProvider>,
+ public NameClient {
public:
XRCanvasInputProvider(XRSession*, HTMLCanvasElement*);
virtual ~XRCanvasInputProvider();
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 5df159ab468..c8a138d86e2 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_source.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "third_party/blink/renderer/modules/xr/xr_reference_space.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
@@ -26,6 +27,9 @@ const char kNonAnimationFrame[] =
const char kSessionMismatch[] = "XRSpace and XRFrame sessions do not match.";
+const char kCannotReportPoses[] =
+ "Poses cannot be given out for the current state.";
+
} // namespace
XRFrame::XRFrame(XRSession* session, XRWorldInformation* world_information)
@@ -56,10 +60,16 @@ XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space,
return nullptr;
}
+ if (!session_->CanReportPoses()) {
+ exception_state.ThrowSecurityError(kCannotReportPoses);
+ return nullptr;
+ }
+
session_->LogGetPose();
std::unique_ptr<TransformationMatrix> pose =
- reference_space->GetViewerPoseMatrix(base_pose_matrix_.get());
+ reference_space->SpaceFromViewerWithDefaultAndOffset(
+ mojo_from_viewer_.get());
if (!pose) {
return nullptr;
}
@@ -84,6 +94,9 @@ XRPose* XRFrame::getPose(XRSpace* space_A,
}
if (!space_A || !space_B) {
+ DVLOG(2) << __func__
+ << " : space_A or space_B is null, space_A =" << space_A
+ << ", space_B = " << space_B;
return nullptr;
}
@@ -99,11 +112,18 @@ XRPose* XRFrame::getPose(XRSpace* space_A,
return nullptr;
}
- return space_A->getPose(space_B, base_pose_matrix_.get());
+ if (!session_->CanReportPoses()) {
+ exception_state.ThrowSecurityError(kCannotReportPoses);
+ return nullptr;
+ }
+
+ return space_A->getPose(space_B, mojo_from_viewer_.get());
}
-void XRFrame::SetBasePoseMatrix(const TransformationMatrix& base_pose_matrix) {
- base_pose_matrix_ = std::make_unique<TransformationMatrix>(base_pose_matrix);
+void XRFrame::SetMojoFromViewer(const TransformationMatrix& mojo_from_viewer,
+ bool emulated_position) {
+ mojo_from_viewer_ = std::make_unique<TransformationMatrix>(mojo_from_viewer);
+ emulated_position_ = emulated_position;
}
void XRFrame::Deactivate() {
@@ -112,9 +132,10 @@ void XRFrame::Deactivate() {
}
HeapVector<Member<XRHitTestResult>> XRFrame::getHitTestResults(
- XRHitTestSource* hitTestSource,
- XRSpace* relativeTo) {
- return {};
+ XRHitTestSource* hit_test_source) {
+ if (!session_->ValidateHitTestSourceExists(hit_test_source))
+ return {};
+ return hit_test_source->Results();
}
void XRFrame::Trace(blink::Visitor* visitor) {
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 7b2e808bc49..8cbd0fba270 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -41,7 +41,7 @@ class XRFrame final : public ScriptWrappable {
XRWorldInformation* worldInformation() const { return world_information_; }
XRAnchorSet* trackedAnchors() const;
- void SetBasePoseMatrix(const TransformationMatrix&);
+ void SetMojoFromViewer(const TransformationMatrix&, bool emulated_position);
void Trace(blink::Visitor*) override;
@@ -52,8 +52,9 @@ class XRFrame final : public ScriptWrappable {
}
HeapVector<Member<XRHitTestResult>> getHitTestResults(
- XRHitTestSource* hitTestSource,
- XRSpace* relativeTo);
+ XRHitTestSource* hit_test_source);
+
+ bool EmulatedPosition() const { return emulated_position_; }
private:
std::unique_ptr<TransformationMatrix> GetAdjustedPoseMatrix(XRSpace*) const;
@@ -64,8 +65,9 @@ class XRFrame final : public ScriptWrappable {
const Member<XRSession> session_;
- // Maps from mojo space to headset space.
- std::unique_ptr<TransformationMatrix> base_pose_matrix_;
+ // Viewer pose in mojo space, the matrix maps from viewer (headset) space to
+ // mojo space.
+ std::unique_ptr<TransformationMatrix> mojo_from_viewer_;
// Frames are only active during callbacks. getPose and getViewerPose should
// only be called from JS on active frames.
@@ -75,6 +77,8 @@ class XRFrame final : public ScriptWrappable {
// animation frames. getViewerPose should only be called from JS on active
// animation frames.
bool is_animation_frame_ = false;
+
+ bool emulated_position_ = false;
};
} // namespace blink
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 53851b1a99b..90ed5d2adba 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -19,5 +19,5 @@
[RaisesException] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace);
[RaisesException] XRPose? getPose(XRSpace space, XRSpace relativeTo);
- [RuntimeEnabled=WebXRHitTest] FrozenArray<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource, [DefaultValue=Undefined] optional XRSpace relativeTo);
+ [RuntimeEnabled=WebXRHitTest] FrozenArray<XRHitTestResult> getHitTestResults(XRHitTestSource hitTestSource);
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
index b50db17d5e3..6ef38e31eae 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -66,33 +66,50 @@ XRFrameProvider::XRFrameProvider(XR* xr)
frame_transport_ = MakeGarbageCollected<XRFrameTransport>();
}
-void XRFrameProvider::BeginImmersiveSession(
+void XRFrameProvider::OnSessionStarted(
XRSession* session,
device::mojom::blink::XRSessionPtr session_ptr) {
- // Make sure the session is indeed an immersive one.
- DCHECK(session && session->immersive());
-
- // Ensure we can only have one immersive session at a time.
- DCHECK(!immersive_session_);
- DCHECK(session_ptr->data_provider);
- DCHECK(session_ptr->submit_frame_sink);
-
- immersive_session_ = session;
+ DCHECK(session);
- immersive_data_provider_.Bind(std::move(session_ptr->data_provider));
- immersive_data_provider_.set_connection_error_handler(WTF::Bind(
- &XRFrameProvider::OnProviderConnectionError, WrapWeakPersistent(this)));
+ if (session->immersive()) {
+ // Ensure we can only have one immersive session at a time.
+ DCHECK(!immersive_session_);
+ DCHECK(session_ptr->data_provider);
+ DCHECK(session_ptr->submit_frame_sink);
+
+ immersive_session_ = session;
+
+ immersive_data_provider_.Bind(std::move(session_ptr->data_provider));
+ immersive_data_provider_.set_disconnect_handler(
+ WTF::Bind(&XRFrameProvider::OnProviderConnectionError,
+ WrapWeakPersistent(this), WrapWeakPersistent(session)));
+
+ immersive_presentation_provider_.Bind(
+ std::move(session_ptr->submit_frame_sink->provider));
+ immersive_presentation_provider_.set_disconnect_handler(
+ WTF::Bind(&XRFrameProvider::OnProviderConnectionError,
+ WrapWeakPersistent(this), WrapWeakPersistent(session)));
+
+ frame_transport_->BindSubmitFrameClient(
+ std::move(session_ptr->submit_frame_sink->client_receiver));
+ frame_transport_->SetTransportOptions(
+ std::move(session_ptr->submit_frame_sink->transport_options));
+ frame_transport_->PresentChange();
+ } else {
+ // If a non-immersive session doesn't have a data provider, we don't
+ // need to store a reference to it.
+ if (!session_ptr->data_provider) {
+ return;
+ }
- presentation_provider_.Bind(
- std::move(session_ptr->submit_frame_sink->provider));
- presentation_provider_.set_connection_error_handler(WTF::Bind(
- &XRFrameProvider::OnProviderConnectionError, WrapWeakPersistent(this)));
+ mojo::Remote<device::mojom::blink::XRFrameDataProvider> data_provider;
+ data_provider.Bind(std::move(session_ptr->data_provider));
+ data_provider.set_disconnect_handler(
+ WTF::Bind(&XRFrameProvider::OnProviderConnectionError,
+ WrapWeakPersistent(this), WrapWeakPersistent(session)));
- frame_transport_->BindSubmitFrameClient(
- std::move(session_ptr->submit_frame_sink->client_request));
- frame_transport_->SetTransportOptions(
- std::move(session_ptr->submit_frame_sink->transport_options));
- frame_transport_->PresentChange();
+ non_immersive_data_providers_.insert(session, std::move(data_provider));
+ }
}
void XRFrameProvider::OnFocusChanged() {
@@ -112,35 +129,41 @@ void XRFrameProvider::OnFocusChanged() {
// Ends the immersive session when the presentation or immersive data provider
// got disconnected.
-void XRFrameProvider::OnProviderConnectionError() {
- presentation_provider_.reset();
- immersive_data_provider_.reset();
- if (vsync_connection_failed_)
- return;
- immersive_session_->ForceEnd();
- vsync_connection_failed_ = true;
+void XRFrameProvider::OnProviderConnectionError(XRSession* session) {
+ // This will call into |OnSessionEnded|, unless it has already ended.
+ session->ForceEnd();
}
-// Called by the immersive session when it is ended.
-void XRFrameProvider::OnImmersiveSessionEnded() {
- if (!immersive_session_)
- return;
-
- xr_->ExitPresent();
-
- immersive_session_ = nullptr;
- pending_immersive_vsync_ = false;
- frame_id_ = -1;
- presentation_provider_.reset();
- immersive_data_provider_.reset();
-
- frame_transport_ = MakeGarbageCollected<XRFrameTransport>();
+void XRFrameProvider::OnSessionEnded(XRSession* session) {
+ if (session->immersive()) {
+ DCHECK(session == immersive_session_);
+
+ xr_->ExitPresent();
+
+ immersive_session_ = nullptr;
+ pending_immersive_vsync_ = false;
+ frame_id_ = -1;
+ immersive_presentation_provider_.reset();
+ immersive_data_provider_.reset();
+ immersive_frame_pose_ = nullptr;
+ is_immersive_frame_position_emulated_ = false;
+
+ frame_transport_ = MakeGarbageCollected<XRFrameTransport>();
+
+ // When we no longer have an active immersive session schedule all the
+ // outstanding frames that were requested while the immersive session was
+ // active.
+ if (requesting_sessions_.size() > 0) {
+ for (auto& session : requesting_sessions_) {
+ RequestNonImmersiveFrameData(session.key.Get());
+ }
- // When we no longer have an active immersive session schedule all the
- // outstanding frames that were requested while the immersive session was
- // active.
- if (requesting_sessions_.size() > 0)
- ScheduleNonImmersiveFrame(nullptr);
+ ScheduleNonImmersiveFrame(nullptr);
+ }
+ } else {
+ non_immersive_data_providers_.erase(session);
+ requesting_sessions_.erase(session);
+ }
}
// Schedule a session to be notified when the next XR frame is available.
@@ -159,13 +182,19 @@ void XRFrameProvider::RequestFrame(XRSession* session) {
// Non-immersive frame logic.
- requesting_sessions_.push_back(session);
+ // Duplicate frame requests are treated as a no-op.
+ if (requesting_sessions_.Contains(session)) {
+ return;
+ }
+ requesting_sessions_.insert(session, nullptr);
// If there's an active immersive session save the request but suppress
// processing it until the immersive session is no longer active.
- if (immersive_session_)
+ if (immersive_session_) {
return;
+ }
+ RequestNonImmersiveFrameData(session);
ScheduleNonImmersiveFrame(std::move(options));
}
@@ -201,23 +230,9 @@ void XRFrameProvider::ScheduleNonImmersiveFrame(
if (!doc)
return;
- // This is cleared by either OnNonImmersiveFrameData (GetFrameData callback,
- // used if we have a magic window provider), or by OnNonImmersiveVSync
- // (XRFrameProviderRequestCallback's invoke, used if there's no magic window
- // provider).
pending_non_immersive_vsync_ = true;
- // If we have a Magic Window provider, request frame data and flag that
- // we're waiting for it. If not, clear any pose data, so that
- // ProcessScheduledFrame handles it appropriately.
- if (xr_->CanRequestNonImmersiveFrameData()) {
- xr_->GetNonImmersiveFrameData(
- std::move(options), WTF::Bind(&XRFrameProvider::OnNonImmersiveFrameData,
- WrapWeakPersistent(this)));
- } else {
- frame_pose_ = nullptr;
- }
-
+ // Calls |OnNonImmersiveVSync|
doc->RequestAnimationFrame(
MakeGarbageCollected<XRFrameProviderRequestCallback>(this));
}
@@ -226,7 +241,6 @@ void XRFrameProvider::OnImmersiveFrameData(
device::mojom::blink::XRFrameDataPtr data) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
- vsync_connection_failed_ = false;
if (!data) {
return;
}
@@ -250,7 +264,14 @@ void XRFrameProvider::OnImmersiveFrameData(
.MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now)
.InMillisecondsF();
- frame_pose_ = std::move(data->pose);
+ immersive_frame_pose_ = std::move(data->pose);
+ if (immersive_frame_pose_) {
+ is_immersive_frame_position_emulated_ =
+ immersive_frame_pose_->emulated_position;
+ } else {
+ is_immersive_frame_position_emulated_ = true;
+ }
+
frame_id_ = data->frame_id;
buffer_mailbox_holder_ = data->buffer_holder;
@@ -291,13 +312,13 @@ void XRFrameProvider::OnNonImmersiveVSync(double high_res_now_ms) {
}
void XRFrameProvider::OnNonImmersiveFrameData(
+ XRSession* session,
device::mojom::blink::XRFrameDataPtr frame_data) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
// TODO(https://crbug.com/837834): add unit tests for this code path.
- pending_non_immersive_vsync_ = false;
LocalFrame* frame = xr_->GetFrame();
if (!frame)
return;
@@ -305,17 +326,48 @@ void XRFrameProvider::OnNonImmersiveFrameData(
if (!doc)
return;
- if (!frame_data) {
+ // Look up the request for this session. The session may have ended between
+ // when the request was sent and this callback, so skip it in that case.
+ auto request = requesting_sessions_.find(session);
+ if (request == requesting_sessions_.end()) {
+ return;
+ }
+
+ if (frame_data) {
+ request->value = std::move(frame_data->pose);
+ } else {
// Unexpectedly didn't get frame data, and we don't have a timestamp.
// Try to request a regular animation frame to avoid getting stuck.
DVLOG(1) << __FUNCTION__ << ": NO FRAME DATA!";
- frame_pose_ = nullptr;
+ request->value = nullptr;
doc->RequestAnimationFrame(
MakeGarbageCollected<XRFrameProviderRequestCallback>(this));
- return;
}
+}
- frame_pose_ = std::move(frame_data->pose);
+void XRFrameProvider::RequestNonImmersiveFrameData(XRSession* session) {
+ DCHECK(session);
+ DCHECK(!session->immersive());
+ DCHECK(!immersive_session_);
+
+ // The requesting_sessions_ entry for this session must have already
+ // been created in |RequestFrame|.
+ auto request = requesting_sessions_.find(session);
+ DCHECK(request != requesting_sessions_.end());
+
+ auto provider = non_immersive_data_providers_.find(session);
+ if (provider == non_immersive_data_providers_.end()) {
+ request->value = nullptr;
+ } else {
+ auto& data_provider = provider->value;
+ auto options = device::mojom::blink::XRFrameDataRequestOptions::New(
+ session->worldTrackingState()->planeDetectionState()->enabled());
+
+ data_provider->GetFrameData(
+ std::move(options),
+ WTF::Bind(&XRFrameProvider::OnNonImmersiveFrameData,
+ WrapWeakPersistent(this), WrapWeakPersistent(session)));
+ }
}
void XRFrameProvider::ProcessScheduledFrame(
@@ -332,11 +384,24 @@ void XRFrameProvider::ProcessScheduledFrame(
}
if (immersive_session_) {
- if (frame_pose_) {
+ // We need to ensure that pose data is valid for the duration of the frame,
+ // because input events may call into |session.end()| which will destroy
+ // this data otherwise. Move the data into local scope here so that it can't
+ // be destroyed.
+ auto frame_pose = std::move(immersive_frame_pose_);
+
+ // Prior to updating input source state, update the state needed to create
+ // presentation frame as newly created presentation frame will get passed to
+ // the input source select[/start/end] events.
+ immersive_session_->UpdatePresentationFrameState(
+ high_res_now_ms, getPoseMatrix(frame_pose), frame_data,
+ is_immersive_frame_position_emulated_);
+
+ if (frame_pose) {
base::span<const device::mojom::blink::XRInputSourceStatePtr>
input_states;
- if (frame_pose_->input_state.has_value())
- input_states = frame_pose_->input_state.value();
+ if (frame_pose->input_state.has_value())
+ input_states = frame_pose->input_state.value();
immersive_session_->OnInputStateChange(frame_id_, input_states);
}
@@ -346,18 +411,17 @@ void XRFrameProvider::ProcessScheduledFrame(
if (!immersive_session_)
return;
- if (frame_pose_ && frame_pose_->pose_reset) {
+ if (frame_pose && frame_pose->pose_reset) {
immersive_session_->OnPoseReset();
}
// Check if immersive session is still set as OnPoseReset may have allowed a
// ForceEndSession to be triggered.
- if (!immersive_session_)
+ if (!immersive_session_) {
return;
+ }
// If there's an immersive session active only process its frame.
- std::unique_ptr<TransformationMatrix> pose_matrix =
- getPoseMatrix(frame_pose_);
#if DCHECK_IS_ON()
// Sanity check: if drawing into a shared buffer, the optional mailbox
// holder must be present. Exception is the first immersive frame after a
@@ -375,35 +439,38 @@ void XRFrameProvider::ProcessScheduledFrame(
if (frame_data && frame_data->stage_parameters_updated) {
immersive_session_->UpdateStageParameters(frame_data->stage_parameters);
}
- if (frame_data) {
- immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix),
- buffer_mailbox_holder_,
- frame_data->detected_planes_data);
- } else {
- immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix),
- buffer_mailbox_holder_, nullptr);
- }
+
+ immersive_session_->OnFrame(high_res_now_ms, buffer_mailbox_holder_);
} else {
// In the process of fulfilling the frame requests for each session they are
// extremely likely to request another frame. Work off of a separate list
// from the requests to prevent infinite loops.
- DCHECK(processing_sessions_.IsEmpty());
- swap(requesting_sessions_, processing_sessions_);
+ decltype(requesting_sessions_) processing_sessions;
+ swap(requesting_sessions_, processing_sessions);
// Inform sessions with a pending request of the new frame
- for (unsigned i = 0; i < processing_sessions_.size(); ++i) {
- XRSession* session = processing_sessions_.at(i).Get();
+ for (auto& request : processing_sessions) {
+ XRSession* session = request.key.Get();
// If the session was terminated between requesting and now, we shouldn't
// process anything further.
if (session->ended())
continue;
- if (frame_pose_) {
+ const auto& frame_pose = request.value;
+
+ // Prior to updating input source state, update the state needed to create
+ // presentation frame as newly created presentation frame will get passed
+ // to the input source select[/start/end] events.
+ session->UpdatePresentationFrameState(
+ high_res_now_ms, getPoseMatrix(frame_pose), frame_data,
+ true /* Non-immersive positions are always emulated */);
+
+ if (frame_pose) {
base::span<const device::mojom::blink::XRInputSourceStatePtr>
input_states;
- if (frame_pose_->input_state.has_value())
- input_states = frame_pose_->input_state.value();
+ if (frame_pose->input_state.has_value())
+ input_states = frame_pose->input_state.value();
session->OnInputStateChange(frame_id_, input_states);
}
@@ -413,7 +480,7 @@ void XRFrameProvider::ProcessScheduledFrame(
if (session->ended())
continue;
- if (frame_pose_ && frame_pose_->pose_reset) {
+ if (frame_pose && frame_pose->pose_reset) {
session->OnPoseReset();
}
@@ -421,18 +488,8 @@ void XRFrameProvider::ProcessScheduledFrame(
if (session->ended())
continue;
- std::unique_ptr<TransformationMatrix> pose_matrix =
- getPoseMatrix(frame_pose_);
- if (frame_data) {
- session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
- frame_data->detected_planes_data);
- } else {
- session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
- nullptr);
- }
+ session->OnFrame(high_res_now_ms, base::nullopt);
}
-
- processing_sessions_.clear();
}
}
@@ -440,7 +497,7 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
DCHECK(layer);
DCHECK(immersive_session_);
DCHECK(layer->session() == immersive_session_);
- if (!presentation_provider_.is_bound())
+ if (!immersive_presentation_provider_.is_bound())
return;
TRACE_EVENT1("gpu", "XRFrameProvider::SubmitWebGLLayer", "frame", frame_id_);
@@ -459,7 +516,7 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
if (!was_changed) {
// Just tell the device side that there was no submitted frame instead of
// executing the implicit end-of-frame submit.
- frame_transport_->FrameSubmitMissing(presentation_provider_.get(),
+ frame_transport_->FrameSubmitMissing(immersive_presentation_provider_.get(),
webgl_context->ContextGL(), frame_id_);
return;
}
@@ -475,9 +532,9 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
bool needs_copy = false;
DVLOG(3) << __FUNCTION__ << ": FrameSubmit for SharedBuffer mode";
frame_transport_->FrameSubmit(
- presentation_provider_.get(), webgl_context->ContextGL(), webgl_context,
- std::move(image_ref), std::move(image_release_callback), frame_id_,
- needs_copy);
+ immersive_presentation_provider_.get(), webgl_context->ContextGL(),
+ webgl_context, std::move(image_ref), std::move(image_release_callback),
+ frame_id_, needs_copy);
return;
}
@@ -499,9 +556,9 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
bool needs_copy = immersive_session_->External();
frame_transport_->FrameSubmit(
- presentation_provider_.get(), webgl_context->ContextGL(), webgl_context,
- std::move(image_ref), std::move(image_release_callback), frame_id_,
- needs_copy);
+ immersive_presentation_provider_.get(), webgl_context->ContextGL(),
+ webgl_context, std::move(image_ref), std::move(image_release_callback),
+ frame_id_, needs_copy);
// Reset our frame id, since anything we'd want to do (resizing/etc) can
// no-longer happen to this frame.
@@ -512,7 +569,7 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
// the moment. Will need an overhaul when we get more robust layering support.
void XRFrameProvider::UpdateWebGLLayerViewports(XRWebGLLayer* layer) {
DCHECK(layer->session() == immersive_session_);
- DCHECK(presentation_provider_);
+ DCHECK(immersive_presentation_provider_);
XRViewport* left = layer->GetViewportForEye(XRView::kEyeLeft);
XRViewport* right = layer->GetViewportForEye(XRView::kEyeRight);
@@ -538,12 +595,12 @@ void XRFrameProvider::UpdateWebGLLayerViewports(XRWebGLLayer* layer) {
static_cast<float>(right->height()) / height)
: WebFloatRect();
- presentation_provider_->UpdateLayerBounds(
+ immersive_presentation_provider_->UpdateLayerBounds(
frame_id_, left_coords, right_coords, WebSize(width, height));
}
void XRFrameProvider::Dispose() {
- presentation_provider_.reset();
+ immersive_presentation_provider_.reset();
immersive_data_provider_.reset();
// TODO(bajones): Do something for outstanding frame requests?
}
@@ -552,8 +609,8 @@ void XRFrameProvider::Trace(blink::Visitor* visitor) {
visitor->Trace(xr_);
visitor->Trace(frame_transport_);
visitor->Trace(immersive_session_);
+ visitor->Trace(non_immersive_data_providers_);
visitor->Trace(requesting_sessions_);
- visitor->Trace(processing_sessions_);
}
} // namespace blink
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 41f7a064114..8fd58cc40a5 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,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_PROVIDER_H_
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.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/handle.h"
@@ -21,17 +21,15 @@ class XRWebGLLayer;
// This class manages requesting and dispatching frame updates, which includes
// pose information for a given XRDevice.
-class XRFrameProvider final
- : public GarbageCollectedFinalized<XRFrameProvider> {
+class XRFrameProvider final : public GarbageCollected<XRFrameProvider> {
public:
explicit XRFrameProvider(XR*);
XRSession* immersive_session() const { return immersive_session_; }
- device::mojom::blink::XRPresentationClientPtr GetSubmitFrameClient();
- void BeginImmersiveSession(XRSession* session,
- device::mojom::blink::XRSessionPtr session_ptr);
- void OnImmersiveSessionEnded();
+ void OnSessionStarted(XRSession* session,
+ device::mojom::blink::XRSessionPtr session_ptr);
+ void OnSessionEnded(XRSession* session);
void RequestFrame(XRSession*);
@@ -43,7 +41,7 @@ class XRFrameProvider final
void Dispose();
void OnFocusChanged();
- device::mojom::blink::XRFrameDataProvider* GetDataProvider() {
+ device::mojom::blink::XRFrameDataProvider* GetImmersiveDataProvider() {
return immersive_data_provider_.get();
}
@@ -51,30 +49,47 @@ class XRFrameProvider final
private:
void OnImmersiveFrameData(device::mojom::blink::XRFrameDataPtr data);
- void OnNonImmersiveFrameData(device::mojom::blink::XRFrameDataPtr data);
+ void OnNonImmersiveFrameData(XRSession* session,
+ device::mojom::blink::XRFrameDataPtr data);
+
+ // Posts a request to the |XRFrameDataProvider| for the given session for
+ // frame data. If the given session has no provider, it will be given null
+ // frame data.
+ void RequestNonImmersiveFrameData(XRSession* session);
// TODO(https://crbug.com/955819): options should be removed from those
// methods as they'll no longer be passed on a per-frame basis.
void ScheduleImmersiveFrame(
device::mojom::blink::XRFrameDataRequestOptionsPtr options);
+
+ // Schedules an animation frame to service all non-immersive requesting
+ // sessions. This will be postponed if there is a currently running immmersive
+ // session.
void ScheduleNonImmersiveFrame(
device::mojom::blink::XRFrameDataRequestOptionsPtr options);
- void OnProviderConnectionError();
+ void OnProviderConnectionError(XRSession* session);
void ProcessScheduledFrame(device::mojom::blink::XRFrameDataPtr frame_data,
double high_res_now_ms);
const Member<XR> xr_;
+
+ // Immersive session state
Member<XRSession> immersive_session_;
Member<XRFrameTransport> frame_transport_;
-
- // Non-immersive Sessions which have requested a frame update.
- HeapVector<Member<XRSession>> requesting_sessions_;
- HeapVector<Member<XRSession>> processing_sessions_;
-
- device::mojom::blink::XRPresentationProviderPtr presentation_provider_;
- device::mojom::blink::XRFrameDataProviderPtr immersive_data_provider_;
- device::mojom::blink::VRPosePtr frame_pose_;
+ mojo::Remote<device::mojom::blink::XRFrameDataProvider>
+ immersive_data_provider_;
+ mojo::Remote<device::mojom::blink::XRPresentationProvider>
+ immersive_presentation_provider_;
+ device::mojom::blink::VRPosePtr immersive_frame_pose_;
+ bool is_immersive_frame_position_emulated_ = false;
+
+ // Non-immersive session state
+ HeapHashMap<Member<XRSession>,
+ mojo::Remote<device::mojom::blink::XRFrameDataProvider>>
+ non_immersive_data_providers_;
+ HeapHashMap<Member<XRSession>, device::mojom::blink::VRPosePtr>
+ requesting_sessions_;
// This frame ID is XR-specific and is used to track when frames arrive at the
// XR compositor so that it knows which poses to use, when to apply bounds
@@ -82,7 +97,6 @@ class XRFrameProvider final
int16_t frame_id_ = -1;
bool pending_immersive_vsync_ = false;
bool pending_non_immersive_vsync_ = false;
- bool vsync_connection_failed_ = false;
base::Optional<gpu::MailboxHolder> buffer_mailbox_holder_;
bool last_has_focus_ = false;
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 5698febc27f..d5258abdb28 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
@@ -17,7 +17,7 @@ class XRFrame;
class XRSession;
class XRFrameRequestCallbackCollection final
- : public GarbageCollectedFinalized<XRFrameRequestCallbackCollection>,
+ : public GarbageCollected<XRFrameRequestCallbackCollection>,
public NameClient {
public:
explicit XRFrameRequestCallbackCollection(ExecutionContext*);
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 7c5fd7987b0..0eb6ff3e93b 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
@@ -15,7 +15,7 @@ XRGripSpace::XRGripSpace(XRSession* session, XRInputSource* source)
: XRSpace(session), input_source_(source) {}
XRPose* XRGripSpace::getPose(XRSpace* other_space,
- const TransformationMatrix* base_pose_matrix) {
+ const TransformationMatrix* mojo_from_viewer) {
// Grip is only available when using tracked pointer for input.
if (input_source_->TargetRayMode() !=
device::mojom::XRTargetRayMode::POINTING) {
@@ -23,26 +23,34 @@ XRPose* XRGripSpace::getPose(XRSpace* other_space,
}
// Make sure the required pose matrices are available.
- if (!base_pose_matrix || !input_source_->BasePose()) {
+ if (!mojo_from_viewer || !input_source_->MojoFromInput()) {
return nullptr;
}
- std::unique_ptr<TransformationMatrix> grip_pose =
- other_space->TransformBaseInputPose(*(input_source_->BasePose()),
- *base_pose_matrix);
-
- if (!grip_pose) {
+ // Calculate grip pose in other_space, aka other_from_grip
+ std::unique_ptr<TransformationMatrix> other_from_grip =
+ other_space->SpaceFromInputForViewer(*(input_source_->MojoFromInput()),
+ *mojo_from_viewer);
+ if (!other_from_grip) {
return nullptr;
}
// Account for any changes made to the reference space's origin offset so
// that things like teleportation works.
- TransformationMatrix adjusted_pose =
- other_space->InverseOriginOffsetMatrix().Multiply(*grip_pose);
- return MakeGarbageCollected<XRPose>(adjusted_pose,
+ //
+ // This is offset_from_grip = offset_from_other * other_from_grip,
+ // where offset_from_other = inverse(other_from_offset).
+ // TODO(https://crbug.com/1008466): move originOffset to separate class?
+ TransformationMatrix offset_from_grip =
+ other_space->InverseOriginOffsetMatrix().Multiply(*other_from_grip);
+ return MakeGarbageCollected<XRPose>(offset_from_grip,
input_source_->emulatedPosition());
}
+base::Optional<XRNativeOriginInformation> XRGripSpace::NativeOrigin() const {
+ return input_source_->nativeOrigin();
+}
+
void XRGripSpace::Trace(blink::Visitor* visitor) {
visitor->Trace(input_source_);
XRSpace::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.h
index f24ad46fbf0..0ffa42e6525 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_grip_space.h
@@ -13,10 +13,12 @@ namespace blink {
class XRGripSpace : public XRSpace {
public:
- XRGripSpace(XRSession*, XRInputSource*);
+ XRGripSpace(XRSession* session, XRInputSource* input_source);
XRPose* getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) override;
+ base::Optional<XRNativeOriginInformation> NativeOrigin() const override;
+
void Trace(blink::Visitor*) override;
private:
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.cc b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.cc
index 90e870addef..73d366ffd7a 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.cc
@@ -2,16 +2,38 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xr_hit_test_options.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_options.h"
+
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_options_init.h"
+#include "third_party/blink/renderer/modules/xr/xr_ray.h"
+#include "third_party/blink/renderer/modules/xr/xr_space.h"
namespace blink {
+XRHitTestOptions::XRHitTestOptions(XRHitTestOptionsInit* options_init) {
+ DCHECK(options_init);
+
+ space_ = options_init->space();
+
+ if (options_init->hasOffsetRay()) {
+ ray_ = options_init->offsetRay();
+ } else {
+ ray_ = MakeGarbageCollected<XRRay>();
+ }
+}
+
+void XRHitTestOptions::Trace(blink::Visitor* visitor) {
+ visitor->Trace(space_);
+ visitor->Trace(ray_);
+ ScriptWrappable::Trace(visitor);
+}
+
XRSpace* XRHitTestOptions::space() const {
- return nullptr;
+ return space_;
}
XRRay* XRHitTestOptions::offsetRay() const {
- return nullptr;
+ return ray_;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.h b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.h
index 1c83d5eca17..0c671b1378c 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_options.h
@@ -11,13 +11,22 @@ namespace blink {
class XRRay;
class XRSpace;
+class XRHitTestOptionsInit;
class XRHitTestOptions : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
+ explicit XRHitTestOptions(XRHitTestOptionsInit* options_init);
+
XRSpace* space() const;
XRRay* offsetRay() const;
+
+ void Trace(blink::Visitor* visitor) override;
+
+ private:
+ Member<XRSpace> space_;
+ Member<XRRay> ray_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.cc b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.cc
index da4a2a0d22e..dd3bc4c2eef 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.cc
@@ -2,16 +2,41 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xr_hit_test_result.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_result.h"
+
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_source.h"
+#include "third_party/blink/renderer/modules/xr/xr_pose.h"
+#include "third_party/blink/renderer/modules/xr/xr_space.h"
namespace blink {
+XRHitTestResult::XRHitTestResult(XRHitTestSource* hit_test_source,
+ const TransformationMatrix& pose)
+ : hit_test_source_(hit_test_source),
+ pose_(std::make_unique<TransformationMatrix>(pose)) {}
+
XRHitTestOptions* XRHitTestResult::hitTestOptions() const {
- return nullptr;
+ return hit_test_source_->hitTestOptions();
+}
+
+XRPose* XRHitTestResult::getPose(XRSpace* relative_to) {
+ DCHECK(relative_to->MojoFromSpace());
+
+ auto mojo_from_this = *pose_;
+
+ auto mojo_from_other = *relative_to->MojoFromSpace();
+ DCHECK(mojo_from_other.IsInvertible());
+
+ auto other_from_mojo = mojo_from_other.Inverse();
+
+ auto other_from_this = other_from_mojo * mojo_from_this;
+
+ return MakeGarbageCollected<XRPose>(other_from_this, false);
}
-XRRigidTransform* XRHitTestResult::transform() const {
- return nullptr;
+void XRHitTestResult::Trace(blink::Visitor* visitor) {
+ visitor->Trace(hit_test_source_);
+ ScriptWrappable::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.h b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.h
index f1c96dcf46a..37526c06384 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.h
@@ -9,15 +9,28 @@
namespace blink {
+class TransformationMatrix;
class XRHitTestOptions;
-class XRRigidTransform;
+class XRHitTestSource;
+class XRPose;
+class XRSpace;
class XRHitTestResult : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
+ XRHitTestResult(XRHitTestSource* hit_test_source,
+ const TransformationMatrix& pose);
+
XRHitTestOptions* hitTestOptions() const;
- XRRigidTransform* transform() const;
+
+ XRPose* getPose(XRSpace* relative_to);
+
+ void Trace(blink::Visitor* visitor) override;
+
+ private:
+ Member<XRHitTestSource> hit_test_source_;
+ std::unique_ptr<TransformationMatrix> pose_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.idl b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.idl
index f286d65cd40..7c3cd75e8d9 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_result.idl
@@ -5,5 +5,6 @@
[SecureContext, Exposed=Window, RuntimeEnabled=WebXRHitTest]
interface XRHitTestResult {
readonly attribute XRHitTestOptions hitTestOptions;
- readonly attribute XRRigidTransform transform;
+
+ XRPose? getPose(XRSpace relative_to);
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.cc b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.cc
index 1fe50a99f91..f1435ee342c 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.cc
@@ -2,12 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "xr_hit_test_source.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_source.h"
+
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_options.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_result.h"
namespace blink {
+XRHitTestSource::XRHitTestSource(uint32_t id, XRHitTestOptions* options)
+ : id_(id), options_(options) {}
+
+uint32_t XRHitTestSource::id() const {
+ return id_;
+}
+
XRHitTestOptions* XRHitTestSource::hitTestOptions() const {
- return nullptr;
+ return options_;
+}
+
+HeapVector<Member<XRHitTestResult>> XRHitTestSource::Results() {
+ HeapVector<Member<XRHitTestResult>> results;
+
+ for (const auto& result : last_frame_results_) {
+ results.emplace_back(MakeGarbageCollected<XRHitTestResult>(this, *result));
+ }
+
+ return results;
+}
+
+void XRHitTestSource::Update(
+ const WTF::Vector<device::mojom::blink::XRHitResultPtr>& hit_test_results) {
+ last_frame_results_.clear();
+
+ for (auto& result : hit_test_results) {
+ last_frame_results_.push_back(
+ std::make_unique<TransformationMatrix>(result->hit_matrix.matrix()));
+ }
+}
+
+void XRHitTestSource::Trace(blink::Visitor* visitor) {
+ visitor->Trace(options_);
+ ScriptWrappable::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.h b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
index 2c7f2da57af..78c6c0b0576 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_test_source.h
@@ -5,17 +5,43 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_HIT_TEST_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_HIT_TEST_SOURCE_H_
+#include <memory>
+
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
+
namespace blink {
class XRHitTestOptions;
+class XRHitTestResult;
class XRHitTestSource : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
+ XRHitTestSource(uint32_t id, XRHitTestOptions* options);
+
+ uint32_t id() const;
+
XRHitTestOptions* hitTestOptions() const;
+
+ // Returns a vector of XRHitTestResults that were obtained during last frame
+ // update. This method is not exposed to JavaScript.
+ HeapVector<Member<XRHitTestResult>> Results();
+
+ void Update(const WTF::Vector<device::mojom::blink::XRHitResultPtr>&
+ hit_test_results);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ const uint32_t id_;
+
+ Member<XRHitTestOptions> options_;
+
+ Vector<std::unique_ptr<TransformationMatrix>> last_frame_results_;
};
} // namespace blink
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 47d2d2fdd6f..66154cdf7a8 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
@@ -79,9 +79,8 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
updated_source->state_.target_ray_mode = desc->target_ray_mode;
updated_source->state_.handedness = desc->handedness;
- updated_source->state_.emulated_position = desc->emulated_position;
- updated_source->pointer_transform_matrix_ =
+ updated_source->input_from_pointer_ =
TryGetTransformationMatrix(desc->pointer_offset);
updated_source->state_.profiles.clear();
@@ -90,7 +89,9 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
}
}
- updated_source->base_pose_matrix_ = TryGetTransformationMatrix(state->grip);
+ updated_source->mojo_from_input_ = TryGetTransformationMatrix(state->grip);
+
+ updated_source->state_.emulated_position = state->emulated_position;
return updated_source;
}
@@ -114,10 +115,10 @@ XRInputSource::XRInputSource(const XRInputSource& other)
MakeGarbageCollected<XRTargetRaySpace>(other.session_, this)),
grip_space_(MakeGarbageCollected<XRGripSpace>(other.session_, this)),
gamepad_(other.gamepad_),
- base_pose_matrix_(
- TryGetTransformationMatrix(other.base_pose_matrix_.get())),
- pointer_transform_matrix_(
- TryGetTransformationMatrix(other.pointer_transform_matrix_.get())) {}
+ mojo_from_input_(
+ TryGetTransformationMatrix(other.mojo_from_input_.get())),
+ input_from_pointer_(
+ TryGetTransformationMatrix(other.input_from_pointer_.get())) {}
const String XRInputSource::handedness() const {
switch (state_.handedness) {
@@ -186,10 +187,9 @@ bool XRInputSource::InvalidatesSameObject(
return false;
}
-void XRInputSource::SetPointerTransformMatrix(
- const TransformationMatrix* pointer_transform_matrix) {
- pointer_transform_matrix_ =
- TryGetTransformationMatrix(pointer_transform_matrix);
+void XRInputSource::SetInputFromPointer(
+ const TransformationMatrix* input_from_pointer) {
+ input_from_pointer_ = TryGetTransformationMatrix(input_from_pointer);
}
void XRInputSource::SetGamepadConnected(bool state) {
@@ -211,6 +211,10 @@ void XRInputSource::UpdateGamepad(
}
}
+base::Optional<XRNativeOriginInformation> XRInputSource::nativeOrigin() const {
+ return XRNativeOriginInformation::Create(this);
+}
+
void XRInputSource::OnSelectStart() {
// Discard duplicate events and ones after the session has ended.
if (state_.primary_input_pressed || session_->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 34a6cb76bf0..492043dcd6d 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
@@ -5,8 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad.h"
+#include "third_party/blink/renderer/modules/xr/xr_native_origin_information.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -59,7 +60,7 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
uint32_t source_id() const { return state_.source_id; }
- void SetPointerTransformMatrix(const TransformationMatrix*);
+ void SetInputFromPointer(const TransformationMatrix*);
void SetGamepadConnected(bool state);
// Gamepad::Client
@@ -74,13 +75,15 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
device::mojom::XRTargetRayMode TargetRayMode() const {
return state_.target_ray_mode;
}
- const TransformationMatrix* BasePose() const {
- return base_pose_matrix_.get();
+ const TransformationMatrix* MojoFromInput() const {
+ return mojo_from_input_.get();
}
- const TransformationMatrix* PointerTransform() const {
- return pointer_transform_matrix_.get();
+ const TransformationMatrix* InputFromPointer() const {
+ return input_from_pointer_.get();
}
+ base::Optional<XRNativeOriginInformation> nativeOrigin() const;
+
void OnSelectStart();
void OnSelectEnd(UserActivation user_activation);
void OnSelect();
@@ -132,11 +135,14 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
Member<XRGripSpace> grip_space_;
Member<Gamepad> gamepad_;
- std::unique_ptr<TransformationMatrix> base_pose_matrix_;
+ // Input device pose in mojo space. This is the grip pose for
+ // tracked controllers, and the viewer pose for screen input.
+ std::unique_ptr<TransformationMatrix> mojo_from_input_;
- // This is the transform to apply to the base_pose_matrix_ to get the pointer
- // matrix. In most cases it should be static.
- std::unique_ptr<TransformationMatrix> pointer_transform_matrix_;
+ // Pointer pose in input device space, this is the transform to apply to
+ // mojo_from_input_ to get the pointer matrix. In most cases it should be
+ // static.
+ std::unique_ptr<TransformationMatrix> input_from_pointer_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
index d1869d2fe85..78ee80c2c2c 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
@@ -23,6 +23,6 @@ enum XRTargetRayMode {
readonly attribute XRTargetRayMode targetRayMode;
[SameObject] readonly attribute XRSpace targetRaySpace;
[SameObject] readonly attribute XRSpace? gripSpace;
- [SameObject, Measure] readonly attribute Gamepad? gamepad;
+ [SameObject, Measure, RuntimeEnabled=WebXrGamepadModule] readonly attribute Gamepad? gamepad;
[SameObject, SaveSameObject] readonly attribute FrozenArray<DOMString> profiles;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.cc b/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.cc
new file mode 100644
index 00000000000..f25edd1b6d1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.cc
@@ -0,0 +1,87 @@
+// 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/xr/xr_native_origin_information.h"
+
+#include "third_party/blink/renderer/modules/xr/type_converters.h"
+#include "third_party/blink/renderer/modules/xr/xr_anchor.h"
+#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
+#include "third_party/blink/renderer/modules/xr/xr_plane.h"
+#include "third_party/blink/renderer/modules/xr/xr_reference_space.h"
+
+namespace blink {
+
+base::Optional<XRNativeOriginInformation> XRNativeOriginInformation::Create(
+ const XRAnchor* anchor) {
+ DCHECK(anchor);
+ return XRNativeOriginInformation(Type::Anchor, anchor->id());
+}
+
+base::Optional<XRNativeOriginInformation> XRNativeOriginInformation::Create(
+ const XRInputSource* input_source) {
+ DCHECK(input_source);
+ return XRNativeOriginInformation(Type::InputSource,
+ input_source->source_id());
+}
+
+base::Optional<XRNativeOriginInformation> XRNativeOriginInformation::Create(
+ const XRPlane* plane) {
+ DCHECK(plane);
+ return XRNativeOriginInformation(Type::Plane, plane->id());
+}
+
+base::Optional<XRNativeOriginInformation> XRNativeOriginInformation::Create(
+ const XRReferenceSpace* reference_space) {
+ DCHECK(reference_space);
+ switch (reference_space->GetType()) {
+ case XRReferenceSpace::Type::kTypeBoundedFloor:
+ return XRNativeOriginInformation(
+ Type::ReferenceSpace,
+ device::mojom::XRReferenceSpaceCategory::BOUNDED_FLOOR);
+ case XRReferenceSpace::Type::kTypeUnbounded:
+ return XRNativeOriginInformation(
+ Type::ReferenceSpace,
+ device::mojom::XRReferenceSpaceCategory::UNBOUNDED);
+ case XRReferenceSpace::Type::kTypeLocalFloor:
+ return XRNativeOriginInformation(
+ Type::ReferenceSpace,
+ device::mojom::XRReferenceSpaceCategory::LOCAL_FLOOR);
+ case XRReferenceSpace::Type::kTypeLocal:
+ return XRNativeOriginInformation(
+ Type::ReferenceSpace, device::mojom::XRReferenceSpaceCategory::LOCAL);
+ case XRReferenceSpace::Type::kTypeViewer:
+ return XRNativeOriginInformation(
+ Type::ReferenceSpace,
+ device::mojom::XRReferenceSpaceCategory::VIEWER);
+ }
+}
+
+XRNativeOriginInformation::XRNativeOriginInformation(Type type, uint32_t id)
+ : type_(type), id_(id) {}
+
+XRNativeOriginInformation::XRNativeOriginInformation(
+ Type type,
+ device::mojom::XRReferenceSpaceCategory reference_space_category)
+ : type_(type), reference_space_category_(reference_space_category) {}
+
+device::mojom::blink::XRNativeOriginInformationPtr
+XRNativeOriginInformation::ToMojo() const {
+ switch (type_) {
+ case XRNativeOriginInformation::Type::Anchor:
+ return device::mojom::blink::XRNativeOriginInformation::NewAnchorId(id_);
+
+ case XRNativeOriginInformation::Type::InputSource:
+ return device::mojom::blink::XRNativeOriginInformation::NewInputSourceId(
+ id_);
+
+ case XRNativeOriginInformation::Type::Plane:
+ return device::mojom::blink::XRNativeOriginInformation::NewPlaneId(id_);
+
+ case XRNativeOriginInformation::Type::ReferenceSpace:
+ return device::mojom::blink::XRNativeOriginInformation::
+ NewReferenceSpaceCategory(reference_space_category_);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.h b/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.h
new file mode 100644
index 00000000000..e517126a5d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_native_origin_information.h
@@ -0,0 +1,59 @@
+// 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_XR_XR_NATIVE_ORIGIN_INFORMATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_NATIVE_ORIGIN_INFORMATION_H_
+
+#include <cstdint>
+
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+
+namespace blink {
+
+class XRAnchor;
+class XRInputSource;
+class XRPlane;
+class XRReferenceSpace;
+
+// XRNativeOriginInformation carries all the information that is required to
+// uniquely identify a native origin on the device side. Native origin roughly
+// represents anything that is known and tracked by the device, for example
+// anchors, planes, input sources, reference spaces.
+class XRNativeOriginInformation {
+ public:
+ XRNativeOriginInformation(XRNativeOriginInformation&& other) = default;
+
+ device::mojom::blink::XRNativeOriginInformationPtr ToMojo() const;
+
+ static base::Optional<XRNativeOriginInformation> Create(
+ const XRAnchor* anchor);
+ static base::Optional<XRNativeOriginInformation> Create(
+ const XRInputSource* input_source);
+ static base::Optional<XRNativeOriginInformation> Create(const XRPlane* plane);
+ static base::Optional<XRNativeOriginInformation> Create(
+ const XRReferenceSpace* reference_space);
+
+ private:
+ enum class Type : int32_t { ReferenceSpace, InputSource, Anchor, Plane };
+
+ XRNativeOriginInformation() = delete;
+ XRNativeOriginInformation(const XRNativeOriginInformation& other) = delete;
+ void operator=(const XRNativeOriginInformation& other) = delete;
+
+ XRNativeOriginInformation(Type type, uint32_t id);
+ XRNativeOriginInformation(
+ Type type,
+ device::mojom::XRReferenceSpaceCategory reference_space_type);
+
+ const Type type_;
+
+ const union {
+ uint32_t id_;
+ device::mojom::XRReferenceSpaceCategory reference_space_category_;
+ };
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_NATIVE_ORIGIN_INFORMATION_H_
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_object_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_object_space.h
index 82992113d9b..a35b6894c01 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_object_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_object_space.h
@@ -21,14 +21,18 @@ class XRObjectSpace : public XRSpace {
explicit XRObjectSpace(XRSession* session, const T* object)
: XRSpace(session), object_(object) {}
- std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace() override {
- auto mojo_to_object = object_->poseMatrix();
+ std::unique_ptr<TransformationMatrix> MojoFromSpace() override {
+ auto object_from_mojo = object_->poseMatrix();
- if (!mojo_to_object.IsInvertible()) {
+ if (!object_from_mojo.IsInvertible()) {
return nullptr;
}
- return std::make_unique<TransformationMatrix>(mojo_to_object.Inverse());
+ return std::make_unique<TransformationMatrix>(object_from_mojo.Inverse());
+ }
+
+ base::Optional<XRNativeOriginInformation> NativeOrigin() const override {
+ return XRNativeOriginInformation::Create(object_);
}
void Trace(blink::Visitor* visitor) override {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_plane.cc b/chromium/third_party/blink/renderer/modules/xr/xr_plane.cc
index ce7c5cb5398..e7cb010e658 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_plane.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_plane.cc
@@ -13,7 +13,7 @@
namespace blink {
-XRPlane::XRPlane(int32_t id,
+XRPlane::XRPlane(uint32_t id,
XRSession* session,
const device::mojom::blink::XRPlaneDataPtr& plane_data,
double timestamp)
@@ -26,7 +26,7 @@ XRPlane::XRPlane(int32_t id,
plane_data->polygon),
timestamp) {}
-XRPlane::XRPlane(int32_t id,
+XRPlane::XRPlane(uint32_t id,
XRSession* session,
const base::Optional<Orientation>& orientation,
const TransformationMatrix& pose_matrix,
@@ -41,7 +41,7 @@ XRPlane::XRPlane(int32_t id,
DVLOG(3) << __func__;
}
-int32_t XRPlane::id() const {
+uint32_t XRPlane::id() const {
return id_;
}
@@ -83,14 +83,10 @@ HeapVector<Member<DOMPointReadOnly>> XRPlane::polygon() const {
ScriptPromise XRPlane::createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose,
- XRSpace* space) {
- // TODO(https://crbug.com/992033): Implement anchor creation from a plane
- // instead of rejecting the promise. This'll cause the string literal used
- // below to be removed.
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- "Device does not support anchors!"));
+ XRSpace* space,
+ ExceptionState& exception_state) {
+ return session_->CreateAnchor(script_state, initial_pose, space, this,
+ exception_state);
}
void XRPlane::Update(const device::mojom::blink::XRPlaneDataPtr& plane_data,
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_plane.h b/chromium/third_party/blink/renderer/modules/xr/xr_plane.h
index 1bde0499cd1..6d8c219b9d0 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_plane.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_plane.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/optional.h"
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -16,6 +16,7 @@
namespace blink {
+class ExceptionState;
class XRRigidTransform;
class XRSession;
class XRSpace;
@@ -26,18 +27,18 @@ class XRPlane : public ScriptWrappable {
public:
enum Orientation { kHorizontal, kVertical };
- XRPlane(int32_t id,
+ XRPlane(uint32_t id,
XRSession* session,
const device::mojom::blink::XRPlaneDataPtr& plane_data,
double timestamp);
- XRPlane(int32_t id,
+ XRPlane(uint32_t id,
XRSession* session,
const base::Optional<Orientation>& orientation,
const TransformationMatrix& pose_matrix,
const HeapVector<Member<DOMPointReadOnly>>& polygon,
double timestamp);
- int32_t id() const;
+ uint32_t id() const;
XRSpace* planeSpace() const;
@@ -49,7 +50,8 @@ class XRPlane : public ScriptWrappable {
ScriptPromise createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose,
- XRSpace* space);
+ XRSpace* space,
+ ExceptionState& exception_state);
// Updates plane data from passed in |plane_data|. The resulting instance
// should be equivalent to the instance that would be create by calling
@@ -60,7 +62,7 @@ class XRPlane : public ScriptWrappable {
void Trace(blink::Visitor* visitor) override;
private:
- const int32_t id_;
+ const uint32_t id_;
HeapVector<Member<DOMPointReadOnly>> polygon_;
base::Optional<Orientation> orientation_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_plane.idl b/chromium/third_party/blink/renderer/modules/xr/xr_plane.idl
index 9528f82d4ac..2c2f6820fa4 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_plane.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_plane.idl
@@ -20,5 +20,5 @@ interface XRPlane {
readonly attribute XRPlaneOrientation? orientation;
readonly attribute DOMHighResTimeStamp lastChangedTime;
- [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space);
+ [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space);
};
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 9e695382345..17139f4e613 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
@@ -13,13 +13,17 @@
#include "third_party/blink/renderer/modules/xr/xr_rigid_transform.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "ui/gfx/geometry/quaternion.h"
#include "ui/gfx/geometry/vector3d_f.h"
namespace blink {
+XRRay::XRRay() {
+ origin_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
+ direction_ = DOMPointReadOnly::Create(0.0, 0.0, -1.0, 0.0);
+}
+
XRRay::XRRay(const TransformationMatrix& matrix,
ExceptionState& exception_state) {
Set(matrix, exception_state);
@@ -60,7 +64,8 @@ void XRRay::Set(const TransformationMatrix& matrix,
}
// Sets member variables from passed in |origin| and |direction|.
-// All constructors eventually invoke this method.
+// All constructors with the exception of default constructor eventually invoke
+// this method.
// If the |direction|'s length is 0, this method will initialize direction to
// default vector (0, 0, -1).
void XRRay::Set(FloatPoint3D origin,
@@ -184,12 +189,25 @@ DOMFloat32Array* XRRay::matrix() {
// onto translation (i.e. translation * rotation) in column-vector notation.
// Step 8: Set ray’s internal matrix to matrix
matrix_ = transformationMatrixToDOMFloat32Array(matrix);
+ if (!raw_matrix_) {
+ raw_matrix_ = std::make_unique<TransformationMatrix>(matrix);
+ } else {
+ *raw_matrix_ = matrix;
+ }
}
// Step 9: Return matrix
return matrix_;
}
+TransformationMatrix XRRay::RawMatrix() {
+ matrix();
+
+ DCHECK(raw_matrix_);
+
+ return *raw_matrix_;
+}
+
void XRRay::Trace(blink::Visitor* visitor) {
visitor->Trace(origin_);
visitor->Trace(direction_);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_ray.h b/chromium/third_party/blink/renderer/modules/xr/xr_ray.h
index 369fefe0b82..f76b7ac2566 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_ray.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.h
@@ -11,19 +11,20 @@
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
namespace blink {
class DOMPointInit;
class DOMPointReadOnly;
class ExceptionState;
-class TransformationMatrix;
class XRRigidTransform;
class XRRay final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
+ XRRay();
explicit XRRay(const TransformationMatrix& matrix,
ExceptionState& exception_state);
explicit XRRay(XRRigidTransform* transform, ExceptionState& exception_state);
@@ -36,6 +37,10 @@ class XRRay final : public ScriptWrappable {
DOMPointReadOnly* direction() const { return direction_; }
DOMFloat32Array* matrix();
+ // Calling |RawMatrix()| is equivalent to calling |matrix()| w.r.t. the data
+ // that will be returned, the only difference is the returned type.
+ TransformationMatrix RawMatrix();
+
static XRRay* Create(ExceptionState& exception_state);
static XRRay* Create(DOMPointInit* origin, ExceptionState& exception_state);
static XRRay* Create(DOMPointInit* origin,
@@ -55,6 +60,7 @@ class XRRay final : public ScriptWrappable {
Member<DOMPointReadOnly> origin_;
Member<DOMPointReadOnly> direction_;
Member<DOMFloat32Array> matrix_;
+ std::unique_ptr<TransformationMatrix> raw_matrix_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.cc b/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.cc
index d79de50e223..a4b669e7b13 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.cc
@@ -48,54 +48,57 @@ XRReferenceSpace::~XRReferenceSpace() = default;
XRPose* XRReferenceSpace::getPose(
XRSpace* other_space,
- const TransformationMatrix* base_pose_matrix) {
+ const TransformationMatrix* mojo_from_viewer) {
if (type_ == Type::kTypeViewer) {
- std::unique_ptr<TransformationMatrix> viewer_pose_matrix =
- other_space->GetViewerPoseMatrix(base_pose_matrix);
- if (!viewer_pose_matrix) {
+ std::unique_ptr<TransformationMatrix> other_offsetspace_from_viewer =
+ other_space->SpaceFromViewerWithDefaultAndOffset(mojo_from_viewer);
+ if (!other_offsetspace_from_viewer) {
return nullptr;
}
- return MakeGarbageCollected<XRPose>(*viewer_pose_matrix,
+
+ auto viewer_from_offset = OriginOffsetMatrix();
+
+ auto other_offsetspace_from_offset =
+ *other_offsetspace_from_viewer * viewer_from_offset;
+
+ return MakeGarbageCollected<XRPose>(other_offsetspace_from_offset,
session()->EmulatedPosition());
} else {
- return XRSpace::getPose(other_space, base_pose_matrix);
+ return XRSpace::getPose(other_space, mojo_from_viewer);
}
}
-void XRReferenceSpace::UpdateFloorLevelTransform() {
+void XRReferenceSpace::SetFloorFromMojo() {
const device::mojom::blink::VRDisplayInfoPtr& display_info =
session()->GetVRDisplayInfo();
if (display_info && display_info->stage_parameters) {
// Use the transform given by xrDisplayInfo's stage_parameters if available.
- floor_level_transform_ = std::make_unique<TransformationMatrix>(
+ floor_from_mojo_ = std::make_unique<TransformationMatrix>(
display_info->stage_parameters->standing_transform.matrix());
} else {
// Otherwise, create a transform based on the default emulated height.
- floor_level_transform_ = std::make_unique<TransformationMatrix>();
- floor_level_transform_->Translate3d(0, kDefaultEmulationHeightMeters, 0);
+ floor_from_mojo_ = std::make_unique<TransformationMatrix>();
+ floor_from_mojo_->Translate3d(0, kDefaultEmulationHeightMeters, 0);
}
display_info_id_ = session()->DisplayInfoPtrId();
}
-// Returns a default pose if no base pose is available. Only applicable to
-// viewer reference spaces.
-std::unique_ptr<TransformationMatrix> XRReferenceSpace::DefaultPose() {
+// Returns a default viewer pose if no actual viewer pose is available. Only
+// applicable to viewer reference spaces.
+std::unique_ptr<TransformationMatrix> XRReferenceSpace::DefaultViewerPose() {
// A viewer reference space always returns an identity matrix.
return type_ == Type::kTypeViewer ? std::make_unique<TransformationMatrix>()
: nullptr;
}
-// Transforms a given pose from a "base" reference space used by the XR
-// service to the space represenced by this reference space.
-std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBasePose(
- const TransformationMatrix& base_pose) {
+std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer) {
switch (type_) {
case Type::kTypeLocal:
- // Currently all base poses are 'local' poses, so return directly.
- return std::make_unique<TransformationMatrix>(base_pose);
- break;
+ // Currently 'local' space is equivalent to mojo space.
+ return std::make_unique<TransformationMatrix>();
case Type::kTypeLocalFloor:
// Currently all base poses are 'local' space, so use of 'local-floor'
// reference spaces requires adjustment. Ideally the service will
@@ -105,57 +108,77 @@ std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBasePose(
// Check first to see if the xrDisplayInfo has updated since the last
// call. If so, update the floor-level transform.
if (display_info_id_ != session()->DisplayInfoPtrId())
- UpdateFloorLevelTransform();
-
- // Apply the floor-level transform to the base pose.
- if (floor_level_transform_) {
- auto pose =
- std::make_unique<TransformationMatrix>(*floor_level_transform_);
- pose->Multiply(base_pose);
- return pose;
- }
- break;
+ SetFloorFromMojo();
+ return std::make_unique<TransformationMatrix>(*floor_from_mojo_);
case Type::kTypeViewer:
- // Always return the default pose because we will only get here for an
- // "viewer" reference space.
- return DefaultPose();
+ // Return viewer_from_mojo which is the inverse of mojo_from_viewer.
+ return std::make_unique<TransformationMatrix>(mojo_from_viewer.Inverse());
case Type::kTypeUnbounded:
// For now we assume that poses returned by systems that support unbounded
- // reference spaces are already in the correct space.
- return std::make_unique<TransformationMatrix>(base_pose);
+ // reference spaces are already in the correct space. Return an identity.
+ return std::make_unique<TransformationMatrix>();
case Type::kTypeBoundedFloor:
+ NOTREACHED() << "kTypeBoundedFloor should be handled by subclass";
break;
}
return nullptr;
}
-// Serves the same purpose as TransformBasePose, but for input poses. Needs to
-// know the head pose so that cases like the viewer frame of reference can
-// properly adjust the input's relative position.
-std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBaseInputPose(
- const TransformationMatrix& base_input_pose,
- const TransformationMatrix& base_pose) {
- return TransformBasePose(base_input_pose);
+// Returns the refspace-from-viewerspace transform, corresponding to the pose of
+// the viewer in this space. This takes the mojo_from_viewer transform (viewer
+// pose in mojo space) as input, and left-multiplies space_from_mojo onto that.
+std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromViewer(
+ const TransformationMatrix& mojo_from_viewer) {
+ if (type_ == Type::kTypeViewer) {
+ // Special case for viewer space, always return an identity matrix
+ // explicitly. In theory the default behavior of multiplying SpaceFromMojo *
+ // MojoFromViewer would be equivalent, but that would likely return an
+ // almost-identity due to rounding errors.
+ return std::make_unique<TransformationMatrix>();
+ }
+
+ // Return space_from_viewer = space_from_mojo * mojo_from_viewer
+ auto space_from_viewer = SpaceFromMojo(mojo_from_viewer);
+ if (!space_from_viewer)
+ return nullptr;
+ space_from_viewer->Multiply(mojo_from_viewer);
+ return space_from_viewer;
}
-std::unique_ptr<TransformationMatrix>
-XRReferenceSpace::GetTransformToMojoSpace() {
+std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromInputForViewer(
+ const TransformationMatrix& mojo_from_input,
+ const TransformationMatrix& mojo_from_viewer) {
+ // Return space_from_input = space_from_mojo * mojo_from_input
+ auto space_from_input = SpaceFromMojo(mojo_from_viewer);
+ if (!space_from_input)
+ return nullptr;
+ space_from_input->Multiply(mojo_from_input);
+ return space_from_input;
+}
+
+std::unique_ptr<TransformationMatrix> XRReferenceSpace::MojoFromSpace() {
// XRReferenceSpace doesn't do anything special with the base pose, but
// derived reference spaces (bounded, unbounded, stationary, etc.) have their
// own custom behavior.
+
+ // Calculate the offset space's pose (including originOffset) in mojo
+ // space.
TransformationMatrix identity;
- std::unique_ptr<TransformationMatrix> transform_matrix =
- TransformBasePose(identity);
+ std::unique_ptr<TransformationMatrix> mojo_from_offsetspace =
+ SpaceFromViewer(identity);
- if (!transform_matrix) {
+ if (!mojo_from_offsetspace) {
// Transform wasn't possible.
return nullptr;
}
// Must account for position and orientation defined by origin offset.
- transform_matrix->Multiply(origin_offset_->TransformMatrix());
- return transform_matrix;
+ // Result is mojo_from_offset = mojo_from_ref * ref_from_offset,
+ // where ref_from_offset is originOffset's transform matrix.
+ // TODO(https://crbug.com/1008466): move originOffset to separate class?
+ mojo_from_offsetspace->Multiply(origin_offset_->TransformMatrix());
+ return mojo_from_offsetspace;
}
TransformationMatrix XRReferenceSpace::OriginOffsetMatrix() {
@@ -166,6 +189,10 @@ TransformationMatrix XRReferenceSpace::InverseOriginOffsetMatrix() {
return origin_offset_->InverseTransformMatrix();
}
+XRReferenceSpace::Type XRReferenceSpace::GetType() const {
+ return type_;
+}
+
XRReferenceSpace* XRReferenceSpace::getOffsetReferenceSpace(
XRRigidTransform* additional_offset) {
auto matrix =
@@ -181,6 +208,11 @@ XRReferenceSpace* XRReferenceSpace::cloneWithOriginOffset(
type_);
}
+base::Optional<XRNativeOriginInformation> XRReferenceSpace::NativeOrigin()
+ const {
+ return XRNativeOriginInformation::Create(this);
+}
+
void XRReferenceSpace::Trace(blink::Visitor* visitor) {
visitor->Trace(origin_offset_);
XRSpace::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.h
index c4e012b34b8..dd112382514 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_reference_space.h
@@ -30,28 +30,36 @@ class XRReferenceSpace : public XRSpace {
static Type StringToReferenceSpaceType(const String& reference_space_type);
- XRReferenceSpace(XRSession*, Type);
- XRReferenceSpace(XRSession*, XRRigidTransform*, Type);
+ XRReferenceSpace(XRSession* session, Type type);
+ XRReferenceSpace(XRSession* session,
+ XRRigidTransform* origin_offset,
+ Type type);
~XRReferenceSpace() override;
XRPose* getPose(XRSpace* other_space,
- const TransformationMatrix* base_pose_matrix) override;
- std::unique_ptr<TransformationMatrix> DefaultPose() override;
- std::unique_ptr<TransformationMatrix> TransformBasePose(
- const TransformationMatrix& base_pose) override;
- std::unique_ptr<TransformationMatrix> TransformBaseInputPose(
- const TransformationMatrix& base_input_pose,
- const TransformationMatrix& base_pose) override;
-
- std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace() override;
+ const TransformationMatrix* mojo_from_viewer) override;
+ std::unique_ptr<TransformationMatrix> DefaultViewerPose() override;
+ std::unique_ptr<TransformationMatrix> SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer) override;
+ std::unique_ptr<TransformationMatrix> SpaceFromViewer(
+ const TransformationMatrix& mojo_from_viewer) override;
+ std::unique_ptr<TransformationMatrix> SpaceFromInputForViewer(
+ const TransformationMatrix& mojo_from_input,
+ const TransformationMatrix& mojo_from_viewer) override;
+
+ std::unique_ptr<TransformationMatrix> MojoFromSpace() override;
TransformationMatrix OriginOffsetMatrix() override;
TransformationMatrix InverseOriginOffsetMatrix() override;
+ Type GetType() const;
+
XRReferenceSpace* getOffsetReferenceSpace(XRRigidTransform* transform);
DEFINE_ATTRIBUTE_EVENT_LISTENER(reset, kReset)
+ base::Optional<XRNativeOriginInformation> NativeOrigin() const override;
+
void Trace(blink::Visitor*) override;
virtual void OnReset();
@@ -60,11 +68,11 @@ class XRReferenceSpace : public XRSpace {
virtual XRReferenceSpace* cloneWithOriginOffset(
XRRigidTransform* origin_offset);
- void UpdateFloorLevelTransform();
+ void SetFloorFromMojo();
unsigned int display_info_id_ = 0;
- std::unique_ptr<TransformationMatrix> floor_level_transform_;
+ std::unique_ptr<TransformationMatrix> floor_from_mojo_;
Member<XRRigidTransform> origin_offset_;
Type type_;
};
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 54c599d12e9..514986217e2 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -7,6 +7,8 @@
#include <memory>
#include <utility>
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+
#include "base/auto_reset.h"
#include "base/metrics/histogram_macros.h"
#include "services/metrics/public/cpp/ukm_builders.h"
@@ -21,13 +23,17 @@
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h"
#include "third_party/blink/renderer/modules/xr/xr.h"
+#include "third_party/blink/renderer/modules/xr/xr_anchor_set.h"
#include "third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h"
#include "third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h"
#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_frame_provider.h"
#include "third_party/blink/renderer/modules/xr/xr_hit_result.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_options.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_test_source.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source_event.h"
#include "third_party/blink/renderer/modules/xr/xr_input_sources_change_event.h"
+#include "third_party/blink/renderer/modules/xr/xr_plane.h"
#include "third_party/blink/renderer/modules/xr/xr_ray.h"
#include "third_party/blink/renderer/modules/xr/xr_reference_space.h"
#include "third_party/blink/renderer/modules/xr/xr_render_state.h"
@@ -59,12 +65,28 @@ const char kInlineVerticalFOVNotSupported[] =
const char kNoSpaceSpecified[] = "No XRSpace specified.";
+const char kNoRigidTransformSpecified[] = "No XRRigidTransform specified.";
+
const char kHitTestNotSupported[] = "Device does not support hit-test!";
const char kAnchorsNotSupported[] = "Device does not support anchors!";
const char kDeviceDisconnected[] = "The XR device has been disconnected.";
+const char kNonInvertibleMatrix[] =
+ "The operation encountered non-invertible matrix and could not be "
+ "completed.";
+
+const char kUnableToDecomposeMatrix[] =
+ "The operation was unable to decompose a matrix and could not be "
+ "completed.";
+
+const char kUnableToRetrieveNativeOrigin[] =
+ "The operation was unable to retrieve the native origin from XRSpace and "
+ "could not be completed.";
+
+const char kHitTestSubscriptionFailed[] = "Hit test subscription failed.";
+
const double kDegToRad = M_PI / 180.0;
// Indices into the views array.
@@ -135,7 +157,8 @@ class XRSession::XRSessionResizeObserverDelegate final
XRSession::XRSession(
XR* xr,
- device::mojom::blink::XRSessionClientRequest client_request,
+ mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
+ client_receiver,
XRSession::SessionMode mode,
EnvironmentBlendMode environment_blend_mode,
bool uses_input_eventing,
@@ -148,16 +171,15 @@ XRSession::XRSession(
world_information_(MakeGarbageCollected<XRWorldInformation>(this)),
enabled_features_(std::move(enabled_features)),
input_sources_(MakeGarbageCollected<XRInputSourceArray>()),
- client_binding_(this, std::move(client_request)),
- input_binding_(this),
+ client_receiver_(this, std::move(client_receiver)),
callback_collection_(
MakeGarbageCollected<XRFrameRequestCallbackCollection>(
xr_->GetExecutionContext())),
uses_input_eventing_(uses_input_eventing),
sensorless_session_(sensorless_session) {
render_state_ = MakeGarbageCollected<XRRenderState>(immersive());
- blurred_ = !HasAppropriateFocus();
- visibility_state_string_ = HasAppropriateFocus() ? "visible" : "hidden";
+ // Ensure that frame focus is considered in the initial visibilityState.
+ UpdateVisibilityState();
switch (environment_blend_mode) {
case kBlendModeOpaque:
@@ -175,6 +197,32 @@ XRSession::XRSession(
}
}
+const String XRSession::visibilityState() const {
+ switch (visibility_state_) {
+ case XRVisibilityState::VISIBLE:
+ return "visible";
+ case XRVisibilityState::VISIBLE_BLURRED:
+ return "visible-blurred";
+ case XRVisibilityState::HIDDEN:
+ return "hidden";
+ }
+}
+
+XRAnchorSet* XRSession::trackedAnchors() const {
+ DVLOG(3) << __func__;
+
+ HeapHashSet<Member<XRAnchor>> result;
+
+ if (is_tracked_anchors_null_)
+ return nullptr;
+
+ for (auto& anchor_id_and_anchor : anchor_ids_to_anchors_) {
+ result.insert(anchor_id_and_anchor.value);
+ }
+
+ return MakeGarbageCollected<XRAnchorSet>(result);
+}
+
bool XRSession::immersive() const {
return mode_ == kModeImmersiveVR || mode_ == kModeImmersiveAR;
}
@@ -187,13 +235,10 @@ const AtomicString& XRSession::InterfaceName() const {
return event_target_names::kXRSession;
}
-device::mojom::blink::XRInputSourceButtonListenerAssociatedPtrInfo
+mojo::PendingAssociatedRemote<device::mojom::blink::XRInputSourceButtonListener>
XRSession::GetInputClickListener() {
- DCHECK(!input_binding_);
- device::mojom::blink::XRInputSourceButtonListenerAssociatedPtrInfo
- input_listener;
- input_binding_.Bind(MakeRequest(&input_listener));
- return input_listener;
+ DCHECK(!input_receiver_.is_bound());
+ return input_receiver_.BindNewEndpointAndPassRemote();
}
void XRSession::updateRenderState(XRRenderStateInit* init,
@@ -210,36 +255,20 @@ void XRSession::updateRenderState(XRRenderStateInit* init,
return;
}
- if (init->hasBaseLayer() && init->baseLayer()) {
- // Validate that any baseLayer provided was created with this session.
- if (init->baseLayer()->session() != this) {
- exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
- kIncompatibleLayer);
- return;
- }
-
- // If the baseLayer was previously null and there are outstanding rAF
- // callbacks, kick off a new frame request to flush them out.
- if (!render_state_->baseLayer() && !pending_frame_ &&
- !callback_collection_->IsEmpty()) {
- // Kick off a request for a new XR frame.
- xr_->frameProvider()->RequestFrame(this);
- pending_frame_ = true;
- }
-
- if (!immersive() && init->baseLayer()->output_canvas()) {
- // If the output canvas was previously null and there are outstanding rAF
- // callbacks, kick off a new frame request to flush them out.
- if (!render_state_->output_canvas() && !pending_frame_ &&
- !callback_collection_->IsEmpty()) {
- // Kick off a request for a new XR frame.
- xr_->frameProvider()->RequestFrame(this);
- pending_frame_ = true;
- }
- }
+ // Validate that any baseLayer provided was created with this session.
+ if (init->hasBaseLayer() && init->baseLayer() &&
+ init->baseLayer()->session() != this) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kIncompatibleLayer);
+ return;
}
pending_render_state_.push_back(init);
+
+ // Updating our render state may have caused us to be in a state where we
+ // should be requesting frames again. Kick off a new frame request in case
+ // there are any pending callbacks to flush them out.
+ MaybeRequestFrame();
}
void XRSession::updateWorldTrackingState(
@@ -273,12 +302,14 @@ void XRSession::UpdateStageParameters(
SetXRDisplayInfo(std::move(display_info));
}
-ScriptPromise XRSession::requestReferenceSpace(ScriptState* script_state,
- const String& type) {
+ScriptPromise XRSession::requestReferenceSpace(
+ ScriptState* script_state,
+ const String& type,
+ ExceptionState& exception_state) {
if (ended_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kSessionEnded));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded);
+ return ScriptPromise();
}
XRReferenceSpace::Type requested_type =
@@ -289,10 +320,9 @@ ScriptPromise XRSession::requestReferenceSpace(ScriptState* script_state,
if (sensorless_session_ &&
requested_type != XRReferenceSpace::Type::kTypeViewer) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kReferenceSpaceNotSupported));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kReferenceSpaceNotSupported);
+ return ScriptPromise();
}
// If the session feature required by this reference space type is not
@@ -300,10 +330,9 @@ ScriptPromise XRSession::requestReferenceSpace(ScriptState* script_state,
auto type_as_feature = MapReferenceSpaceTypeToFeature(requested_type);
if (!type_as_feature ||
!enabled_features_.Contains(type_as_feature.value())) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kReferenceSpaceNotSupported));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kReferenceSpaceNotSupported);
+ return ScriptPromise();
}
XRReferenceSpace* reference_space = nullptr;
@@ -341,10 +370,9 @@ ScriptPromise XRSession::requestReferenceSpace(ScriptState* script_state,
// If the above switch statement failed to assign to reference_space,
// it's because the reference space wasn't supported by the device.
if (!reference_space) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kReferenceSpaceNotSupported));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kReferenceSpaceNotSupported);
+ return ScriptPromise();
}
DCHECK(reference_space);
@@ -360,29 +388,122 @@ ScriptPromise XRSession::requestReferenceSpace(ScriptState* script_state,
return promise;
}
+ScriptPromise XRSession::CreateAnchor(ScriptState* script_state,
+ XRRigidTransform* initial_pose,
+ XRSpace* space,
+ XRPlane* plane,
+ ExceptionState& exception_state) {
+ if (ended_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded);
+ return ScriptPromise();
+ }
+
+ if (!initial_pose) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kNoRigidTransformSpecified);
+ return ScriptPromise();
+ }
+
+ if (!space) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kNoSpaceSpecified);
+ return ScriptPromise();
+ }
+
+ // Reject the promise if device doesn't support the anchors API.
+ if (!xr_->xrEnvironmentProviderRemote()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kAnchorsNotSupported);
+ return ScriptPromise();
+ }
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // Transformation from passed in |space| to mojo space.
+ std::unique_ptr<TransformationMatrix> mojo_from_space =
+ space->MojoFromSpace();
+
+ DVLOG(3) << __func__
+ << ": mojo_from_space = " << mojo_from_space->ToString(true);
+
+ // Matrix will be null if transformation from object space to mojo space is
+ // not invertible, log & bail out in that case.
+ if (!mojo_from_space || !mojo_from_space->IsInvertible()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kNonInvertibleMatrix);
+ return ScriptPromise();
+ }
+
+ auto space_from_mojo = mojo_from_space->Inverse();
+
+ DVLOG(3) << __func__
+ << ": space_from_mojo = " << space_from_mojo.ToString(true);
+
+ // Transformation from passed in pose to |space|.
+ auto mojo_from_initial_pose = initial_pose->TransformMatrix();
+ auto space_from_initial_pose = space_from_mojo * mojo_from_initial_pose;
+
+ DVLOG(3) << __func__ << ": mojo_from_initial_pose = "
+ << mojo_from_initial_pose.ToString(true);
+
+ DVLOG(3) << __func__ << ": space_from_initial_pose = "
+ << space_from_initial_pose.ToString(true);
+
+ TransformationMatrix::DecomposedType decomposed;
+ if (!space_from_initial_pose.Decompose(decomposed)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kUnableToDecomposeMatrix);
+ return ScriptPromise();
+ }
+
+ device::mojom::blink::VRPosePtr pose_ptr =
+ device::mojom::blink::VRPose::New();
+
+ pose_ptr->orientation =
+ gfx::Quaternion(-decomposed.quaternion_x, -decomposed.quaternion_y,
+ -decomposed.quaternion_z, decomposed.quaternion_w);
+ pose_ptr->position = blink::WebFloatPoint3D(
+ decomposed.translate_x, decomposed.translate_y, decomposed.translate_z);
+
+ DVLOG(3) << __func__
+ << ": pose_ptr->orientation = " << pose_ptr->orientation->ToString()
+ << ", pose_ptr->position = [" << pose_ptr->position->x << ", "
+ << pose_ptr->position->y << ", " << pose_ptr->position->z << "]";
+
+ if (plane) {
+ xr_->xrEnvironmentProviderRemote()->CreatePlaneAnchor(
+ std::move(pose_ptr), plane->id(),
+ WTF::Bind(&XRSession::OnCreateAnchorResult, WrapPersistent(this),
+ WrapPersistent(resolver)));
+ } else {
+ xr_->xrEnvironmentProviderRemote()->CreateAnchor(
+ std::move(pose_ptr),
+ WTF::Bind(&XRSession::OnCreateAnchorResult, WrapPersistent(this),
+ WrapPersistent(resolver)));
+ }
+ create_anchor_promises_.insert(resolver);
+
+ return promise;
+}
+
ScriptPromise XRSession::createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose,
- XRSpace* space) {
- // TODO(https://crbug.com/992033): Implement anchor creation from a session
- // instead of rejecting the promise.
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kAnchorsNotSupported));
+ XRSpace* space,
+ ExceptionState& exception_state) {
+ return CreateAnchor(script_state, initial_pose, space, nullptr,
+ exception_state);
}
int XRSession::requestAnimationFrame(V8XRFrameRequestCallback* callback) {
- TRACE_EVENT0("gpu", __FUNCTION__);
+ TRACE_EVENT0("gpu", __func__);
// Don't allow any new frame requests once the session is ended.
if (ended_)
return 0;
int id = callback_collection_->RegisterCallback(callback);
- if (!pending_frame_) {
- // Kick off a request for a new XR frame.
- xr_->frameProvider()->RequestFrame(this);
- pending_frame_ = true;
- }
+ MaybeRequestFrame();
return id;
}
@@ -404,25 +525,26 @@ XRInputSourceArray* XRSession::inputSources() const {
ScriptPromise XRSession::requestHitTest(ScriptState* script_state,
XRRay* ray,
- XRSpace* space) {
+ XRSpace* space,
+ ExceptionState& exception_state) {
+ DVLOG(2) << __func__;
+
if (ended_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kSessionEnded));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded);
+ return ScriptPromise();
}
if (!space) {
- return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), kNoSpaceSpecified));
+ exception_state.ThrowTypeError(kNoSpaceSpecified);
+ return ScriptPromise();
}
// Reject the promise if device doesn't support the hit-test API.
- if (!xr_->xrEnvironmentProviderPtr()) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
- kHitTestNotSupported));
+ if (!xr_->xrEnvironmentProviderRemote()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ kHitTestNotSupported);
+ return ScriptPromise();
}
device::mojom::blink::XRRayPtr ray_mojo = device::mojom::blink::XRRay::New();
@@ -436,8 +558,7 @@ ScriptPromise XRSession::requestHitTest(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
- EnsureEnvironmentErrorHandler();
- xr_->xrEnvironmentProviderPtr()->RequestHitTest(
+ xr_->xrEnvironmentProviderRemote()->RequestHitTest(
std::move(ray_mojo),
WTF::Bind(&XRSession::OnHitTestResults, WrapPersistent(this),
WrapPersistent(resolver)));
@@ -446,11 +567,68 @@ ScriptPromise XRSession::requestHitTest(ScriptState* script_state,
return promise;
}
-ScriptPromise XRSession::requestHitTestSource(ScriptState* script_state,
- XRHitTestOptionsInit* options) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- MakeGarbageCollected<DOMException>(DOMExceptionCode::kInvalidStateError));
+ScriptPromise XRSession::requestHitTestSource(
+ ScriptState* script_state,
+ XRHitTestOptionsInit* options_init,
+ ExceptionState& exception_state) {
+ DVLOG(2) << __func__;
+
+ DCHECK(options_init); // is this enforced by generated bindings?
+
+ XRHitTestOptions* options =
+ MakeGarbageCollected<XRHitTestOptions>(options_init);
+
+ // 1. Grab the native origin from the passed in XRSpace.
+ base::Optional<XRNativeOriginInformation> maybe_native_origin =
+ options->space()->NativeOrigin();
+
+ if (!maybe_native_origin) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kUnableToRetrieveNativeOrigin);
+ return {};
+ }
+
+ // 2. Convert the XRRay to be expressed in terms of passed in XRSpace. This
+ // should only matter for spaces whose transforms are not fully known on the
+ // device (for example any space containing origin-offset).
+ TransformationMatrix origin_from_space =
+ options->space()->OriginOffsetMatrix();
+
+ DVLOG(3) << __func__
+ << ": origin_from_space = " << origin_from_space.ToString(true);
+
+ // Transformation from passed in pose to |space|.
+ auto space_from_ray = options->offsetRay()->RawMatrix();
+ auto origin_from_ray = origin_from_space * space_from_ray;
+
+ DVLOG(3) << __func__
+ << ": space_from_ray = " << space_from_ray.ToString(true);
+
+ DVLOG(3) << __func__
+ << ": origin_from_ray = " << origin_from_ray.ToString(true);
+
+ device::mojom::blink::XRRayPtr ray_mojo = device::mojom::blink::XRRay::New();
+
+ ray_mojo->origin = WebFloatPoint3D(origin_from_ray.MapPoint({0, 0, 0}));
+
+ // Zero out the translation of origin_from_ray matrix to correctly map a 3D
+ // vector.
+ origin_from_ray.Translate3d(-origin_from_ray.M41(), -origin_from_ray.M42(),
+ -origin_from_ray.M43());
+
+ auto direction = origin_from_ray.MapPoint({0, 0, -1});
+ ray_mojo->direction = {direction.X(), direction.Y(), direction.Z()};
+
+ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ xr_->xrEnvironmentProviderRemote()->SubscribeToHitTest(
+ maybe_native_origin->ToMojo(), std::move(ray_mojo),
+ WTF::Bind(&XRSession::OnSubscribeToHitTestResult, WrapPersistent(this),
+ WrapPersistent(resolver), WrapPersistent(options)));
+ request_hit_test_source_promises_.insert(resolver);
+
+ return promise;
}
void XRSession::OnHitTestResults(
@@ -473,9 +651,54 @@ void XRSession::OnHitTestResults(
resolver->Resolve(hit_results);
}
+void XRSession::OnSubscribeToHitTestResult(
+ ScriptPromiseResolver* resolver,
+ XRHitTestOptions* options,
+ device::mojom::SubscribeToHitTestResult result,
+ uint32_t subscription_id) {
+ DVLOG(2) << __func__ << ": result=" << result
+ << ", subscription_id=" << subscription_id;
+
+ DCHECK(request_hit_test_source_promises_.Contains(resolver));
+ request_hit_test_source_promises_.erase(resolver);
+
+ if (result != device::mojom::SubscribeToHitTestResult::SUCCESS) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kOperationError, kHitTestSubscriptionFailed));
+ return;
+ }
+
+ XRHitTestSource* hit_test_source =
+ MakeGarbageCollected<XRHitTestSource>(subscription_id, options);
+
+ hit_test_source_ids_to_hit_test_sources_.insert(subscription_id,
+ hit_test_source);
+
+ resolver->Resolve(hit_test_source);
+}
+
+void XRSession::OnCreateAnchorResult(ScriptPromiseResolver* resolver,
+ device::mojom::CreateAnchorResult result,
+ uint32_t id) {
+ DCHECK(create_anchor_promises_.Contains(resolver));
+ create_anchor_promises_.erase(resolver);
+
+ XRAnchor* anchor = MakeGarbageCollected<XRAnchor>(id, this);
+
+ anchor_ids_to_anchors_.insert(id, anchor);
+
+ resolver->Resolve(anchor);
+}
+
+void XRSession::OnEnvironmentProviderCreated() {
+ EnsureEnvironmentErrorHandler();
+}
+
void XRSession::EnsureEnvironmentErrorHandler() {
+ // Install error handler on environment provider to ensure that we get
+ // notified so that we can clean up all relevant pending promises.
if (!environment_error_handler_subscribed_ &&
- xr_->xrEnvironmentProviderPtr()) {
+ xr_->xrEnvironmentProviderRemote()) {
environment_error_handler_subscribed_ = true;
xr_->AddEnvironmentProviderErrorHandler(WTF::Bind(
&XRSession::OnEnvironmentProviderError, WrapWeakPersistent(this)));
@@ -489,14 +712,137 @@ void XRSession::OnEnvironmentProviderError() {
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError, kDeviceDisconnected));
}
+
+ HeapHashSet<Member<ScriptPromiseResolver>> create_anchor_promises;
+ create_anchor_promises_.swap(create_anchor_promises);
+ for (ScriptPromiseResolver* resolver : create_anchor_promises) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kDeviceDisconnected));
+ }
+
+ HeapHashSet<Member<ScriptPromiseResolver>> request_hit_test_source_promises;
+ request_hit_test_source_promises_.swap(request_hit_test_source_promises);
+ for (ScriptPromiseResolver* resolver : request_hit_test_source_promises) {
+ resolver->Reject(MakeGarbageCollected<DOMException>(
+ DOMExceptionCode::kInvalidStateError, kDeviceDisconnected));
+ }
+}
+
+void XRSession::ProcessAnchorsData(
+ const device::mojom::blink::XRAnchorsDataPtr& tracked_anchors_data,
+ double timestamp) {
+ TRACE_EVENT0("xr", __func__);
+
+ 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;
+ anchor_ids_to_anchors_.clear();
+ return;
+ }
+
+ TRACE_COUNTER2("xr", "Anchor statistics", "All anchors",
+ tracked_anchors_data->all_anchors_ids.size(),
+ "Updated anchors",
+ tracked_anchors_data->updated_anchors_data.size());
+
+ DVLOG(3) << __func__ << ": updated anchors size="
+ << tracked_anchors_data->updated_anchors_data.size()
+ << ", all anchors size="
+ << tracked_anchors_data->all_anchors_ids.size();
+
+ is_tracked_anchors_null_ = false;
+
+ HeapHashMap<uint32_t, Member<XRAnchor>> updated_anchors;
+
+ // First, process all planes that had their information updated (new planes
+ // are also processed here).
+ for (const auto& anchor : tracked_anchors_data->updated_anchors_data) {
+ auto it = anchor_ids_to_anchors_.find(anchor->id);
+ if (it != anchor_ids_to_anchors_.end()) {
+ updated_anchors.insert(anchor->id, it->value);
+ it->value->Update(anchor, timestamp);
+ } else {
+ updated_anchors.insert(
+ anchor->id,
+ MakeGarbageCollected<XRAnchor>(anchor->id, this, anchor, timestamp));
+ }
+ }
+
+ // Then, copy over the planes that were not updated but are still present.
+ for (const auto& anchor_id : tracked_anchors_data->all_anchors_ids) {
+ auto it_updated = updated_anchors.find(anchor_id);
+
+ // If the plane was already updated, there is nothing to do as it was
+ // already moved to |updated_anchors|. Otherwise just copy it over as-is.
+ if (it_updated == updated_anchors.end()) {
+ auto it = anchor_ids_to_anchors_.find(anchor_id);
+ DCHECK(it != anchor_ids_to_anchors_.end());
+ updated_anchors.insert(anchor_id, it->value);
+ }
+ }
+
+ anchor_ids_to_anchors_.swap(updated_anchors);
+}
+
+void XRSession::CleanUpUnusedHitTestSources() {
+ // Gather all IDs of unused hit test sources.
+ HashSet<uint32_t> unused_hit_test_source_ids;
+ for (auto& subscription_id_and_hit_test_source :
+ hit_test_source_ids_to_hit_test_sources_) {
+ if (!subscription_id_and_hit_test_source.value) {
+ unused_hit_test_source_ids.insert(
+ subscription_id_and_hit_test_source.key);
+ }
+ }
+
+ // Remove all of the unused hit test sources.
+ hit_test_source_ids_to_hit_test_sources_.RemoveAll(
+ unused_hit_test_source_ids);
+
+ DVLOG(3) << __func__ << ": removed unused hit test sources, amount: "
+ << unused_hit_test_source_ids.size();
+}
+
+void XRSession::ProcessHitTestData(
+ const device::mojom::blink::XRHitTestSubscriptionResultsDataPtr&
+ hit_test_subscriptions_data) {
+ DVLOG(2) << __func__;
+
+ CleanUpUnusedHitTestSources();
+
+ if (hit_test_subscriptions_data) {
+ // We have received hit test results for hit test subscriptions - process
+ // each result and notify its corresponding hit test source about new
+ // results for the current frame.
+ for (auto& hit_test_subscription_data :
+ hit_test_subscriptions_data->results) {
+ auto it = hit_test_source_ids_to_hit_test_sources_.find(
+ hit_test_subscription_data->subscription_id);
+ if (it != hit_test_source_ids_to_hit_test_sources_.end()) {
+ it->value->Update(hit_test_subscription_data->hit_test_results);
+ }
+ }
+ } else {
+ // We have not received hit test results for any of the hit test
+ // subscriptions in the current frame - clean up the results on all hit test
+ // source objects.
+ for (auto& subscription_id_and_hit_test_source :
+ hit_test_source_ids_to_hit_test_sources_) {
+ subscription_id_and_hit_test_source.value->Update({});
+ }
+ }
}
-ScriptPromise XRSession::end(ScriptState* script_state) {
+ScriptPromise XRSession::end(ScriptState* script_state,
+ ExceptionState& exception_state) {
// Don't allow a session to end twice.
if (ended_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, MakeGarbageCollected<DOMException>(
- DOMExceptionCode::kInvalidStateError, kSessionEnded));
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded);
+ return ScriptPromise();
}
ForceEnd();
@@ -534,11 +880,8 @@ void XRSession::ForceEnd() {
canvas_input_provider_ = nullptr;
}
- // If this session is the active immersive session, notify the frameProvider
- // that it's ended.
- if (xr_->frameProvider()->immersive_session() == this) {
- xr_->frameProvider()->OnImmersiveSessionEnded();
- }
+ // Notify the frame provider that we've ended
+ xr_->frameProvider()->OnSessionEnded(this);
DispatchEvent(*XRSessionEvent::Create(event_type_names::kEnd, this));
}
@@ -581,38 +924,101 @@ DoubleSize XRSession::OutputCanvasSize() const {
return DoubleSize(output_width_, output_height_);
}
-void XRSession::OnFocus() {
- if (!blurred_)
- return;
+void XRSession::OnFocusChanged() {
+ UpdateVisibilityState();
+}
+
+void XRSession::OnVisibilityStateChanged(XRVisibilityState visibility_state) {
+ // TODO(crbug.com/1002742): Until some ambiguities in the spec are cleared up,
+ // force "visible-blurred" states from the device to report as "hidden"
+ if (visibility_state == XRVisibilityState::VISIBLE_BLURRED) {
+ visibility_state = XRVisibilityState::HIDDEN;
+ }
- blurred_ = false;
- visibility_state_string_ = "visible";
- DispatchEvent(
- *XRSessionEvent::Create(event_type_names::kVisibilitychange, this));
+ if (device_visibility_state_ != visibility_state) {
+ device_visibility_state_ = visibility_state;
+ UpdateVisibilityState();
+ }
}
-void XRSession::OnBlur() {
- if (blurred_)
+// The ultimate visibility state of the session is a combination of the devices
+// reported visibility state and, for inline sessions, the frame focus, which
+// will override the device visibility to "hidden" if the frame is not currently
+// focused.
+void XRSession::UpdateVisibilityState() {
+ // Don't need to track the visibility state if the session has ended.
+ if (ended_) {
return;
+ }
- blurred_ = true;
- visibility_state_string_ = "hidden";
- DispatchEvent(
- *XRSessionEvent::Create(event_type_names::kVisibilitychange, this));
-}
+ XRVisibilityState state = device_visibility_state_;
+
+ // The WebXR spec requires that if our document is not focused, that we don't
+ // hand out real poses. For immersive sessions, we have to rely on the device
+ // to tell us it's visibility state, as some runtimes (WMR) put focus in the
+ // headset, and thus we cannot rely on Document Focus state. This is fine
+ // because while the runtime reports us as focused the content owned by the
+ // session should be focued, which is owned by the document. For inline, we
+ // can and must rely on frame focus.
+ if (!immersive() && !xr_->IsFrameFocused()) {
+ state = XRVisibilityState::HIDDEN;
+ }
+
+ if (visibility_state_ != state) {
+ visibility_state_ = state;
+
+ // If the visibility state was changed to something other than hidden, we
+ // may be able to restart the frame loop.
+ MaybeRequestFrame();
-// Immersive sessions may still not be blurred in headset even if the page isn't
-// focused. This prevents the in-headset experience from freezing on an
-// external display headset when the user clicks on another tab.
-bool XRSession::HasAppropriateFocus() {
- return immersive() ? has_xr_focus_ : has_xr_focus_ && xr_->IsFrameFocused();
+ DispatchEvent(
+ *XRSessionEvent::Create(event_type_names::kVisibilitychange, this));
+ }
}
-void XRSession::OnFocusChanged() {
- if (HasAppropriateFocus()) {
- OnFocus();
- } else {
- OnBlur();
+void XRSession::MaybeRequestFrame() {
+ bool will_have_base_layer = !!render_state_->baseLayer();
+ for (const auto& init : pending_render_state_) {
+ if (init->hasBaseLayer()) {
+ will_have_base_layer = !!init->baseLayer();
+ }
+ }
+
+ // A page will not be allowed to get frames if its visibility state is hidden.
+ bool page_allowed_frames = visibility_state_ != XRVisibilityState::HIDDEN;
+
+ // A page is configured properly if it will have a base layer when the frame
+ // callback gets resolved.
+ bool page_configured_properly = will_have_base_layer;
+
+ // If we have an outstanding callback registered, then we know that the page
+ // actually wants frames.
+ bool page_wants_frame = !callback_collection_->IsEmpty();
+
+ // A page can process frames if it has its appropriate base layer set and has
+ // indicated that it actually wants frames.
+ bool page_can_process_frames = page_configured_properly && page_wants_frame;
+
+ // We consider frames to be throttled if the page is not allowed frames, but
+ // otherwise would be able to receive them. Therefore, if the page isn't in a
+ // state to process frames, it doesn't matter if we are throttling it, any
+ // "stalls" should be attributed to the page being poorly behaved.
+ bool frames_throttled = page_can_process_frames && !page_allowed_frames;
+
+ // If our throttled state has changed, notify anyone who may care
+ if (frames_throttled_ != frames_throttled) {
+ frames_throttled_ = frames_throttled;
+ xr_->SetFramesThrottled(this, frames_throttled_);
+ }
+
+ // We can request a frame if we don't have one already pending, the page is
+ // allowed to request frames, and the page is set up to properly handle frames
+ // and wants one.
+ bool request_frame =
+ !pending_frame_ && page_allowed_frames && page_can_process_frames;
+ if (request_frame) {
+ xr_->frameProvider()->RequestFrame(this);
+ pending_frame_ = true;
}
}
@@ -632,8 +1038,9 @@ void XRSession::DetachOutputCanvas(HTMLCanvasElement* canvas) {
}
void XRSession::ApplyPendingRenderState() {
+ DCHECK(!prev_base_layer_);
if (pending_render_state_.size() > 0) {
- XRWebGLLayer* prev_base_layer = render_state_->baseLayer();
+ prev_base_layer_ = render_state_->baseLayer();
HTMLCanvasElement* prev_ouput_canvas = render_state_->output_canvas();
update_views_next_frame_ = true;
@@ -646,7 +1053,7 @@ void XRSession::ApplyPendingRenderState() {
// If this is an inline session and the base layer has changed, give it an
// opportunity to update it's drawing buffer size.
if (!immersive() && render_state_->baseLayer() &&
- render_state_->baseLayer() != prev_base_layer) {
+ render_state_->baseLayer() != prev_base_layer_) {
render_state_->baseLayer()->OnResize();
}
@@ -681,38 +1088,84 @@ void XRSession::ApplyPendingRenderState() {
}
}
-void XRSession::OnFrame(
+void XRSession::UpdatePresentationFrameState(
double timestamp,
- std::unique_ptr<TransformationMatrix> base_pose_matrix,
- const base::Optional<gpu::MailboxHolder>& output_mailbox_holder,
- const device::mojom::blink::XRPlaneDetectionDataPtr& detected_planes_data) {
- TRACE_EVENT0("gpu", __FUNCTION__);
- DVLOG(2) << __FUNCTION__;
+ std::unique_ptr<TransformationMatrix> mojo_from_viewer,
+ const device::mojom::blink::XRFrameDataPtr& frame_data,
+ bool emulated_position) {
+ TRACE_EVENT0("gpu", __func__);
+ DVLOG(2) << __func__ << " : frame_data valid? "
+ << (frame_data ? true : false);
// Don't process any outstanding frames once the session is ended.
if (ended_)
return;
- base_pose_matrix_ = std::move(base_pose_matrix);
+ mojo_from_viewer_ = std::move(mojo_from_viewer);
+ DVLOG(2) << __func__ << " : mojo_from_viewer_ valid? "
+ << (mojo_from_viewer_ ? true : false);
+
+ emulated_position_ = emulated_position;
+
+ // Update objects that might change on per-frame basis.
+ if (frame_data) {
+ world_information_->ProcessPlaneInformation(
+ frame_data->detected_planes_data, timestamp);
+ ProcessAnchorsData(frame_data->anchors_data, timestamp);
+ ProcessHitTestData(frame_data->hit_test_subscription_results);
+ } else {
+ world_information_->ProcessPlaneInformation(nullptr, timestamp);
+ ProcessAnchorsData(nullptr, timestamp);
+ ProcessHitTestData(nullptr);
+ }
+}
+
+void XRSession::OnFrame(
+ double timestamp,
+ const base::Optional<gpu::MailboxHolder>& output_mailbox_holder) {
+ TRACE_EVENT0("gpu", __func__);
+ DVLOG(2) << __func__;
+ // Don't process any outstanding frames once the session is ended.
+ if (ended_)
+ return;
// If there are pending render state changes, apply them now.
+ prev_base_layer_ = nullptr;
ApplyPendingRenderState();
- world_information_->ProcessPlaneInformation(detected_planes_data, timestamp);
-
if (pending_frame_) {
pending_frame_ = false;
// Don't allow frames to be processed if there's no layers attached to the
// session. That would allow tracking with no associated visuals.
XRWebGLLayer* frame_base_layer = render_state_->baseLayer();
- if (!frame_base_layer)
+ if (!frame_base_layer) {
+ // If we previously had a frame base layer, we need to still attempt to
+ // submit a frame back to the runtime, as all "GetFrameData" calls need a
+ // matching submit.
+ if (prev_base_layer_) {
+ prev_base_layer_->OnFrameStart(output_mailbox_holder);
+ prev_base_layer_->OnFrameEnd();
+ prev_base_layer_ = nullptr;
+ }
return;
+ }
// Don't allow frames to be processed if an inline session doesn't have an
// output canvas.
if (!immersive() && !render_state_->output_canvas())
return;
+ frame_base_layer->OnFrameStart(output_mailbox_holder);
+
+ // Don't allow frames to be processed if the session's visibility state is
+ // "hidden".
+ if (visibility_state_ == XRVisibilityState::HIDDEN) {
+ // If the frame is skipped because of the visibility state, make sure we
+ // end the frame anyway.
+ frame_base_layer->OnFrameEnd();
+ return;
+ }
+
XRFrame* presentation_frame = CreatePresentationFrame();
presentation_frame->SetAnimationFrame(true);
@@ -722,8 +1175,6 @@ void XRSession::OnFrame(
update_views_next_frame_ = false;
}
- frame_base_layer->OnFrameStart(output_mailbox_holder);
-
// Resolve the queued requestAnimationFrame callbacks. All XR rendering will
// happen within these calls. resolving_frame_ will be true for the duration
// of the callbacks.
@@ -751,11 +1202,28 @@ void XRSession::LogGetPose() const {
}
}
+bool XRSession::CanReportPoses() {
+ // The spec has a few requirements for if poses can be reported.
+ // If we have a session, then user intent is understood. Therefore, (due to
+ // the way visibility state is updatd), the rest of the steps really just
+ // boil down to whether or not the XRVisibilityState is Visible.
+ return visibility_state_ == XRVisibilityState::VISIBLE;
+}
+
XRFrame* XRSession::CreatePresentationFrame() {
+ DVLOG(2) << __func__;
+
XRFrame* presentation_frame =
MakeGarbageCollected<XRFrame>(this, world_information_);
- if (base_pose_matrix_) {
- presentation_frame->SetBasePoseMatrix(*base_pose_matrix_);
+
+ // TODO(https://crbug.com/1004201): Determine if world_information_ should be
+ // treated similarly to mojo_from_viewer_.
+ if (mojo_from_viewer_ && visibility_state_ != XRVisibilityState::HIDDEN) {
+ DVLOG(2) << __func__ << " : mojo_from_viewer_ is set and not hidden,"
+ << " updating presentation frame";
+
+ presentation_frame->SetMojoFromViewer(*mojo_from_viewer_,
+ EmulatedPosition());
}
return presentation_frame;
}
@@ -781,7 +1249,7 @@ void XRSession::UpdateCanvasDimensions(Element* element) {
if (orientation) {
output_angle = orientation->angle();
- DVLOG(2) << __FUNCTION__ << ": got angle=" << output_angle;
+ DVLOG(2) << __func__ << ": got angle=" << output_angle;
}
if (render_state_->baseLayer()) {
@@ -807,6 +1275,11 @@ void XRSession::OnInputStateChangeInternal(
int16_t frame_id,
base::span<const device::mojom::blink::XRInputSourceStatePtr> input_states,
bool from_eventing) {
+ // If we're in any state other than visible, input should not be processed
+ if (visibility_state_ != XRVisibilityState::VISIBLE) {
+ return;
+ }
+
HeapVector<Member<XRInputSource>> added;
HeapVector<Member<XRInputSource>> removed;
last_frame_id_ = frame_id;
@@ -921,6 +1394,21 @@ void XRSession::OnExitPresent() {
}
}
+bool XRSession::ValidateHitTestSourceExists(XRHitTestSource* hit_test_source) {
+ auto it =
+ hit_test_source_ids_to_hit_test_sources_.find(hit_test_source->id());
+ if (it == hit_test_source_ids_to_hit_test_sources_.end()) {
+ return false;
+ }
+
+ if (!it->value) {
+ hit_test_source_ids_to_hit_test_sources_.erase(it);
+ return false;
+ }
+
+ return true;
+}
+
void XRSession::SetXRDisplayInfo(
device::mojom::blink::VRDisplayInfoPtr display_info) {
// We don't necessarily trust the backend to only send us display info changes
@@ -1024,7 +1512,12 @@ void XRSession::Trace(blink::Visitor* visitor) {
visitor->Trace(canvas_input_provider_);
visitor->Trace(callback_collection_);
visitor->Trace(hit_test_promises_);
+ visitor->Trace(create_anchor_promises_);
+ visitor->Trace(request_hit_test_source_promises_);
visitor->Trace(reference_spaces_);
+ visitor->Trace(anchor_ids_to_anchors_);
+ visitor->Trace(prev_base_layer_);
+ visitor->Trace(hit_test_source_ids_to_hit_test_sources_);
EventTargetWithInlineData::Trace(visitor);
}
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 f7f1c9cfb69..30c9ca5b139 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.h
@@ -7,8 +7,9 @@
#include "base/containers/span.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
@@ -33,9 +34,13 @@ class ResizeObserver;
class ScriptPromiseResolver;
class V8XRFrameRequestCallback;
class XR;
+class XRAnchor;
class XRAnchorSet;
class XRCanvasInputProvider;
+class XRHitTestOptions;
class XRHitTestOptionsInit;
+class XRHitTestSource;
+class XRPlane;
class XRRay;
class XRReferenceSpace;
class XRRenderState;
@@ -43,6 +48,7 @@ class XRRenderStateInit;
class XRRigidTransform;
class XRSpace;
class XRViewData;
+class XRWebGLLayer;
class XRWorldInformation;
class XRWorldTrackingState;
class XRWorldTrackingStateInit;
@@ -67,7 +73,8 @@ class XRSession final
};
XRSession(XR* xr,
- device::mojom::blink::XRSessionClientRequest client_request,
+ mojo::PendingReceiver<device::mojom::blink::XRSessionClient>
+ client_receiver,
SessionMode mode,
EnvironmentBlendMode environment_blend_mode,
bool uses_input_eventing,
@@ -77,11 +84,11 @@ class XRSession final
XR* xr() const { return xr_; }
const String& environmentBlendMode() const { return blend_mode_string_; }
- const String& visibilityState() const { return visibility_state_string_; }
+ const String visibilityState() const;
XRRenderState* renderState() const { return render_state_; }
XRWorldTrackingState* worldTrackingState() { return world_tracking_state_; }
XRSpace* viewerSpace() const;
- XRAnchorSet* trackedAnchors() const { return nullptr; }
+ XRAnchorSet* trackedAnchors() const;
bool immersive() const;
@@ -98,11 +105,21 @@ class XRSession final
XRWorldTrackingStateInit* world_tracking_state_init,
ExceptionState& exception_state);
ScriptPromise requestReferenceSpace(ScriptState* script_state,
- const String& type);
+ const String& type,
+ ExceptionState&);
+ // IDL-exposed
ScriptPromise createAnchor(ScriptState* script_state,
XRRigidTransform* initial_pose,
- XRSpace* space);
+ XRSpace* space,
+ ExceptionState& exception_state);
+
+ // helper, not IDL-exposed
+ ScriptPromise CreateAnchor(ScriptState* script_state,
+ XRRigidTransform* pose,
+ XRSpace* space,
+ XRPlane* plane,
+ ExceptionState& exception_state);
int requestAnimationFrame(V8XRFrameRequestCallback* callback);
void cancelAnimationFrame(int id);
@@ -110,14 +127,16 @@ class XRSession final
XRInputSourceArray* inputSources() const;
ScriptPromise requestHitTestSource(ScriptState* script_state,
- XRHitTestOptionsInit* options);
+ XRHitTestOptionsInit* options,
+ ExceptionState& exception_state);
ScriptPromise requestHitTest(ScriptState* script_state,
XRRay* ray,
- XRSpace* space);
+ XRSpace* space,
+ ExceptionState&);
// Called by JavaScript to manually end the session.
- ScriptPromise end(ScriptState* script_state);
+ ScriptPromise end(ScriptState* script_state, ExceptionState&);
bool ended() const { return ended_; }
@@ -146,10 +165,7 @@ class XRSession final
void OnFocusChanged();
void OnFrame(double timestamp,
- std::unique_ptr<TransformationMatrix> base_pose_matrix,
- const base::Optional<gpu::MailboxHolder>& output_mailbox_holder,
- const device::mojom::blink::XRPlaneDetectionDataPtr&
- detected_planes_data);
+ const base::Optional<gpu::MailboxHolder>& output_mailbox_holder);
void OnInputStateChange(
int16_t frame_id,
@@ -171,18 +187,18 @@ class XRSession final
return display_info_;
}
- device::mojom::blink::XRInputSourceButtonListenerAssociatedPtrInfo
+ mojo::PendingAssociatedRemote<
+ device::mojom::blink::XRInputSourceButtonListener>
GetInputClickListener();
- // TODO(crbug.com/969131): Update the mojom to deliver this per-frame.
bool EmulatedPosition() const {
- if (display_info_) {
- return !display_info_->capabilities->has_position;
- }
-
// If we don't have display info then we should be using the identity
// reference space, which by definition will be emulating the position.
- return true;
+ if (!display_info_) {
+ return true;
+ }
+
+ return emulated_position_;
}
// Immersive sessions currently use two views for VR, and only a single view
@@ -201,6 +217,10 @@ class XRSession final
unsigned int DisplayInfoPtrId() const { return display_info_id_; }
unsigned int StageParametersId() const { return stage_parameters_id_; }
+ // Returns true if the session recognizes passed in hit_test_source as still
+ // existing.
+ bool ValidateHitTestSourceExists(XRHitTestSource* hit_test_source);
+
void SetXRDisplayInfo(device::mojom::blink::VRDisplayInfoPtr display_info);
bool UsesInputEventing() { return uses_input_eventing_; }
@@ -210,14 +230,38 @@ class XRSession final
// ScriptWrappable
bool HasPendingActivity() const override;
+ bool CanReportPoses();
+
+ // Creates presentation frame based on current state of the session.
+ // State currently used in XRFrame creation is mojo_from_viewer_ and
+ // world_information_. The created XRFrame also stores a reference to this
+ // XRSession.
XRFrame* CreatePresentationFrame();
+ // Updates the internal XRSession state that is relevant to creating
+ // presentation frames.
+ void UpdatePresentationFrameState(
+ double timestamp,
+ std::unique_ptr<TransformationMatrix> mojo_from_viewer,
+ const device::mojom::blink::XRFrameDataPtr& frame_data,
+ bool emulated_position);
+
+ // Notifies immersive session that the environment integration provider has
+ // been created by the session's XR instance, |xr_|. Gives a session an
+ // opportunity to register its own error handlers on environment integration
+ // provider endpoint.
+ void OnEnvironmentProviderCreated();
+
private:
class XRSessionResizeObserverDelegate;
+ using XRVisibilityState = device::mojom::blink::XRVisibilityState;
+
void UpdateCanvasDimensions(Element*);
void ApplyPendingRenderState();
+ void MaybeRequestFrame();
+
void OnInputStateChangeInternal(
int16_t frame_id,
base::span<const device::mojom::blink::XRInputSourceStatePtr>
@@ -227,23 +271,45 @@ class XRSession final
// XRSessionClient
void OnChanged(device::mojom::blink::VRDisplayInfoPtr display_info) override;
void OnExitPresent() override;
- void OnFocus() override;
- void OnBlur() override;
+ void OnVisibilityStateChanged(
+ device::mojom::blink::XRVisibilityState visibility_state) override;
- bool HasAppropriateFocus();
+ void UpdateVisibilityState();
void OnHitTestResults(
ScriptPromiseResolver* resolver,
base::Optional<WTF::Vector<device::mojom::blink::XRHitResultPtr>>
results);
+ void OnSubscribeToHitTestResult(
+ ScriptPromiseResolver* resolver,
+ XRHitTestOptions* options,
+ device::mojom::SubscribeToHitTestResult result,
+ uint32_t subscription_id);
+
+ void OnCreateAnchorResult(ScriptPromiseResolver* resolver,
+ device::mojom::CreateAnchorResult result,
+ uint32_t id);
+
void EnsureEnvironmentErrorHandler();
void OnEnvironmentProviderError();
+ void ProcessAnchorsData(
+ const device::mojom::blink::XRAnchorsDataPtr& tracked_anchors_data,
+ double timestamp);
+
+ void CleanUpUnusedHitTestSources();
+
+ void ProcessHitTestData(
+ const device::mojom::blink::XRHitTestSubscriptionResultsDataPtr&
+ hit_test_data);
+
const Member<XR> xr_;
const SessionMode mode_;
const bool environment_integration_;
String blend_mode_string_;
+ XRVisibilityState device_visibility_state_ = XRVisibilityState::VISIBLE;
+ XRVisibilityState visibility_state_ = XRVisibilityState::VISIBLE;
String visibility_state_string_;
Member<XRRenderState> render_state_;
Member<XRWorldTrackingState> world_tracking_state_;
@@ -251,34 +317,52 @@ class XRSession final
HeapVector<Member<XRRenderStateInit>> pending_render_state_;
XRSessionFeatureSet enabled_features_;
+
+ bool is_tracked_anchors_null_ = true;
+ HeapHashMap<uint32_t, Member<XRAnchor>> anchor_ids_to_anchors_;
+
+ // Mapping of hit test source ids (aka hit test subscription ids) to hit test
+ // sources. Hit test source has to be stored via weak member - JavaScript side
+ // will communicate that it's no longer interested in the subscription by
+ // dropping all its references to the hit test source & we need to make sure
+ // that we don't keep the XRHitTestSources alive.
+ HeapHashMap<uint32_t, WeakMember<XRHitTestSource>>
+ hit_test_source_ids_to_hit_test_sources_;
+
WTF::Vector<XRViewData> views_;
Member<XRInputSourceArray> input_sources_;
+ Member<XRWebGLLayer> prev_base_layer_;
Member<ResizeObserver> resize_observer_;
Member<XRCanvasInputProvider> canvas_input_provider_;
bool environment_error_handler_subscribed_ = false;
HeapHashSet<Member<ScriptPromiseResolver>> hit_test_promises_;
+ // Set of promises returned from CreateAnchor that are still in-flight.
+ HeapHashSet<Member<ScriptPromiseResolver>> create_anchor_promises_;
+ // Set of promises returned from requestHitTestSource that are still
+ // in-flight.
+ HeapHashSet<Member<ScriptPromiseResolver>> request_hit_test_source_promises_;
HeapVector<Member<XRReferenceSpace>> reference_spaces_;
- bool has_xr_focus_ = true;
bool is_external_ = false;
unsigned int display_info_id_ = 0;
unsigned int stage_parameters_id_ = 0;
device::mojom::blink::VRDisplayInfoPtr display_info_;
- mojo::Binding<device::mojom::blink::XRSessionClient> client_binding_;
- mojo::AssociatedBinding<device::mojom::blink::XRInputSourceButtonListener>
- input_binding_;
+ mojo::Receiver<device::mojom::blink::XRSessionClient> client_receiver_;
+ mojo::AssociatedReceiver<device::mojom::blink::XRInputSourceButtonListener>
+ input_receiver_{this};
Member<XRFrameRequestCallbackCollection> callback_collection_;
- std::unique_ptr<TransformationMatrix> base_pose_matrix_;
+ // Viewer pose in mojo space.
+ std::unique_ptr<TransformationMatrix> mojo_from_viewer_;
- bool blurred_;
bool ended_ = false;
bool pending_frame_ = false;
bool resolving_frame_ = false;
bool update_views_next_frame_ = false;
bool views_dirty_ = true;
+ bool frames_throttled_ = false;
// Indicates that we've already logged a metric, so don't need to log it
// again.
@@ -296,6 +380,8 @@ class XRSession final
bool sensorless_session_ = false;
int16_t last_frame_id_ = -1;
+
+ bool emulated_position_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session.idl b/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
index 0266a596185..1afffcb72d3 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -42,21 +42,21 @@ enum XRVisibilityState {
[RaisesException] void updateRenderState(optional XRRenderStateInit init);
- [CallWith=ScriptState] Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type);
+ [CallWith=ScriptState, RaisesException] Promise<XRReferenceSpace> requestReferenceSpace(XRReferenceSpaceType type);
long requestAnimationFrame(XRFrameRequestCallback callback);
void cancelAnimationFrame(long handle);
- [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState] Promise<FrozenArray<XRHitResult>> requestHitTest(XRRay ray, XRSpace space);
+ [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, RaisesException] Promise<FrozenArray<XRHitResult>> requestHitTest(XRRay ray, XRSpace space);
// https://github.com/immersive-web/real-world-geometry/blob/master/plane-detection-explainer.md
[RuntimeEnabled=WebXRPlaneDetection] readonly attribute XRWorldTrackingState worldTrackingState;
[RuntimeEnabled=WebXRPlaneDetection, RaisesException] void updateWorldTrackingState(optional XRWorldTrackingStateInit state);
[RuntimeEnabled=WebXRAnchors] readonly attribute XRAnchorSet trackedAnchors;
- [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space);
+ [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space);
- [CallWith=ScriptState, Measure] Promise<void> end();
+ [CallWith=ScriptState, Measure, RaisesException] Promise<void> end();
- [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState] Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
+ [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, RaisesException] Promise<XRHitTestSource> requestHitTestSource(XRHitTestOptionsInit options);
};
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 252b8a09e9a..3908681c92d 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_space.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_space.cc
@@ -16,24 +16,29 @@ XRSpace::XRSpace(XRSession* session) : session_(session) {}
XRSpace::~XRSpace() = default;
-std::unique_ptr<TransformationMatrix> XRSpace::GetTransformToMojoSpace() {
+std::unique_ptr<TransformationMatrix> XRSpace::MojoFromSpace() {
// The base XRSpace does not have any relevant information, so can't determine
// a transform here.
return nullptr;
}
-std::unique_ptr<TransformationMatrix> XRSpace::DefaultPose() {
+std::unique_ptr<TransformationMatrix> XRSpace::DefaultViewerPose() {
return nullptr;
}
-std::unique_ptr<TransformationMatrix> XRSpace::TransformBasePose(
- const TransformationMatrix& base_pose) {
+std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer) {
return nullptr;
}
-std::unique_ptr<TransformationMatrix> XRSpace::TransformBaseInputPose(
- const TransformationMatrix& base_input_pose,
- const TransformationMatrix& base_pose) {
+std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromViewer(
+ const TransformationMatrix& mojo_from_viewer) {
+ return nullptr;
+}
+
+std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromInputForViewer(
+ const TransformationMatrix& mojo_from_input,
+ const TransformationMatrix& mojo_from_viewer) {
return nullptr;
}
@@ -49,18 +54,17 @@ TransformationMatrix XRSpace::InverseOriginOffsetMatrix() {
XRPose* XRSpace::getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) {
- std::unique_ptr<TransformationMatrix> mojo_from_this =
- GetTransformToMojoSpace();
- if (!mojo_from_this) {
+ std::unique_ptr<TransformationMatrix> mojo_from_space = MojoFromSpace();
+ if (!mojo_from_space) {
return nullptr;
}
// Rigid transforms should always be invertible.
- DCHECK(mojo_from_this->IsInvertible());
- TransformationMatrix this_from_mojo = mojo_from_this->Inverse();
+ DCHECK(mojo_from_space->IsInvertible());
+ TransformationMatrix space_from_mojo = mojo_from_space->Inverse();
std::unique_ptr<TransformationMatrix> mojo_from_other =
- other_space->GetTransformToMojoSpace();
+ other_space->MojoFromSpace();
if (!mojo_from_other) {
return nullptr;
}
@@ -68,33 +72,38 @@ XRPose* XRSpace::getPose(XRSpace* other_space,
// TODO(crbug.com/969133): Update how EmulatedPosition is determined here once
// spec issue https://github.com/immersive-web/webxr/issues/534 has been
// resolved.
- TransformationMatrix this_from_other =
- this_from_mojo.Multiply(*mojo_from_other);
- return MakeGarbageCollected<XRPose>(this_from_other,
+ TransformationMatrix space_from_other =
+ space_from_mojo.Multiply(*mojo_from_other);
+ return MakeGarbageCollected<XRPose>(space_from_other,
session()->EmulatedPosition());
}
-std::unique_ptr<TransformationMatrix> XRSpace::GetViewerPoseMatrix(
- const TransformationMatrix* base_pose_matrix) {
- std::unique_ptr<TransformationMatrix> pose;
+std::unique_ptr<TransformationMatrix>
+XRSpace::SpaceFromViewerWithDefaultAndOffset(
+ const TransformationMatrix* mojo_from_viewer) {
+ std::unique_ptr<TransformationMatrix> space_from_viewer;
// If we don't have a valid base pose, request the reference space's default
- // pose. Most common when tracking is lost.
- if (base_pose_matrix) {
- pose = TransformBasePose(*base_pose_matrix);
+ // viewer pose. Most common when tracking is lost.
+ if (mojo_from_viewer) {
+ space_from_viewer = SpaceFromViewer(*mojo_from_viewer);
} else {
- pose = DefaultPose();
+ space_from_viewer = DefaultViewerPose();
}
// Can only update an XRViewerPose's views with an invertible matrix.
- if (!pose || !pose->IsInvertible()) {
+ if (!space_from_viewer || !space_from_viewer->IsInvertible()) {
return nullptr;
}
// Account for any changes made to the reference space's origin offset so that
// things like teleportation works.
+ //
+ // This is offset_from_viewer = offset_from_space * space_from_viewer,
+ // where offset_from_viewer = inverse(viewer_from_offset).
+ // TODO(https://crbug.com/1008466): move originOffset to separate class?
return std::make_unique<TransformationMatrix>(
- InverseOriginOffsetMatrix().Multiply(*pose));
+ InverseOriginOffsetMatrix().Multiply(*space_from_viewer));
}
ExecutionContext* XRSpace::GetExecutionContext() const {
@@ -105,6 +114,10 @@ const AtomicString& XRSpace::InterfaceName() const {
return event_target_names::kXRSpace;
}
+base::Optional<XRNativeOriginInformation> XRSpace::NativeOrigin() const {
+ return base::nullopt;
+}
+
void XRSpace::Trace(blink::Visitor* visitor) {
visitor->Trace(session_);
ScriptWrappable::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_space.h
index c2c832df04e..1ea887c709e 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_space.h
@@ -9,6 +9,7 @@
#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/modules/xr/xr_native_origin_information.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -24,26 +25,51 @@ class XRSession;
class XRSpace : public EventTargetWithInlineData {
DEFINE_WRAPPERTYPEINFO();
+ protected:
+ explicit XRSpace(XRSession* session);
+
public:
- explicit XRSpace(XRSession*);
~XRSpace() override;
- // Get a transform that maps from this space to mojo space.
- // Returns nullptr if computing a transform is not possible.
- virtual std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace();
-
- virtual std::unique_ptr<TransformationMatrix> DefaultPose();
- virtual std::unique_ptr<TransformationMatrix> TransformBasePose(
- const TransformationMatrix& base_pose);
- virtual std::unique_ptr<TransformationMatrix> TransformBaseInputPose(
- const TransformationMatrix& base_input_pose,
- const TransformationMatrix& base_pose);
+ // Gets a default viewer pose appropriate for this space. This is an identity
+ // for viewer space, null for everything else.
+ virtual std::unique_ptr<TransformationMatrix> DefaultViewerPose();
+
+ // Gets the pose of this space's origin in mojo space. This is a transform
+ // that maps from this space to mojo space (aka device space). Unless noted
+ // otherwise, all data returned over vr_service.mojom interfaces is expressed
+ // in mojo space coordinates. Returns nullptr if computing a transform is not
+ // possible.
+ virtual std::unique_ptr<TransformationMatrix> MojoFromSpace();
+
+ // Gets the pose of the mojo origin in this reference space, corresponding
+ // to a transform from mojo coordinates to reference space coordinates.
+ virtual std::unique_ptr<TransformationMatrix> SpaceFromMojo(
+ const TransformationMatrix& mojo_from_viewer);
+
+ // Gets the viewer pose in this space, corresponding to a transform from
+ // viewer coordinates to this space's coordinates. (The position elements of
+ // the transformation matrix are the viewer's location in this space's
+ // coordinates.)
+ virtual std::unique_ptr<TransformationMatrix> SpaceFromViewer(
+ const TransformationMatrix& mojo_from_viewer);
+
+ // Gets an input pose in this space. This requires the viewer pose as
+ // an additional input since a "viewer" space needs to transform the
+ // input pose to headset-relative coordinates.
+ virtual std::unique_ptr<TransformationMatrix> SpaceFromInputForViewer(
+ const TransformationMatrix& mojo_from_input,
+ const TransformationMatrix& mojo_from_viewer);
virtual XRPose* getPose(XRSpace* other_space,
- const TransformationMatrix* base_pose_matrix);
+ const TransformationMatrix* mojo_from_viewer);
- std::unique_ptr<TransformationMatrix> GetViewerPoseMatrix(
- const TransformationMatrix* base_pose_matrix);
+ // Gets the viewer pose in this space, including using an appropriate
+ // default pose (i.e. if tracking is lost), and applying originOffset
+ // as applicable. TODO(https://crbug.com/1008466): consider moving
+ // the originOffset handling to a separate class?
+ std::unique_ptr<TransformationMatrix> SpaceFromViewerWithDefaultAndOffset(
+ const TransformationMatrix* mojo_from_viewer);
XRSession* session() const { return session_; }
@@ -51,10 +77,13 @@ class XRSpace : public EventTargetWithInlineData {
ExecutionContext* GetExecutionContext() const override;
const AtomicString& InterfaceName() const override;
+ // Return origin offset matrix, aka native_origin_from_offset_space.
virtual TransformationMatrix OriginOffsetMatrix();
virtual TransformationMatrix InverseOriginOffsetMatrix();
- void Trace(blink::Visitor*) override;
+ virtual base::Optional<XRNativeOriginInformation> NativeOrigin() const = 0;
+
+ void Trace(blink::Visitor* visitor) override;
private:
const Member<XRSession> session_;
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 c023be67e18..90eedcfd54b 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
@@ -14,92 +14,104 @@ namespace blink {
XRTargetRaySpace::XRTargetRaySpace(XRSession* session, XRInputSource* source)
: XRSpace(session), input_source_(source) {}
-std::unique_ptr<TransformationMatrix> XRTargetRaySpace::GetPointerPoseForScreen(
+std::unique_ptr<TransformationMatrix> XRTargetRaySpace::OtherSpaceFromScreenTap(
XRSpace* other_space,
- const TransformationMatrix& base_pose_matrix) {
- // If the pointer origin is the screen we need the head's base pose and
- // the pointer transform matrix to continue. The pointer transform will
- // represent the point the canvas was clicked as an offset from the view.
- if (!input_source_->PointerTransform()) {
+ const TransformationMatrix& mojo_from_viewer) {
+ // If the pointer origin is the screen, the input space is viewer space, and
+ // we need the head's viewer pose and the pointer pose in continue. The
+ // pointer transform will represent the point the canvas was clicked as an
+ // offset from the view.
+ if (!input_source_->InputFromPointer()) {
return nullptr;
}
- // Multiply the head pose and pointer transform to get the final pointer.
- std::unique_ptr<TransformationMatrix> pointer_pose =
- other_space->TransformBasePose(base_pose_matrix);
- if (!pointer_pose) {
+ // other_from_pointer = other_from_input * input_from_pointer,
+ // where input space is equivalent to viewer space for screen taps.
+ std::unique_ptr<TransformationMatrix> other_from_pointer =
+ other_space->SpaceFromViewer(mojo_from_viewer);
+ if (!other_from_pointer) {
return nullptr;
}
-
- pointer_pose->Multiply(*(input_source_->PointerTransform()));
- return pointer_pose;
+ other_from_pointer->Multiply(*(input_source_->InputFromPointer()));
+ return other_from_pointer;
}
-std::unique_ptr<TransformationMatrix> XRTargetRaySpace::GetTrackedPointerPose(
+std::unique_ptr<TransformationMatrix>
+XRTargetRaySpace::OtherSpaceFromTrackedPointer(
XRSpace* other_space,
- const TransformationMatrix& base_pose_matrix) {
- if (!input_source_->BasePose()) {
+ const TransformationMatrix& mojo_from_viewer) {
+ if (!input_source_->MojoFromInput()) {
return nullptr;
}
- std::unique_ptr<TransformationMatrix> grip_pose =
- other_space->TransformBaseInputPose(*(input_source_->BasePose()),
- base_pose_matrix);
+ // Calculate other_from_pointer = other_from_input * input_from_pointer
+ std::unique_ptr<TransformationMatrix> other_from_pointer =
+ other_space->SpaceFromInputForViewer(*(input_source_->MojoFromInput()),
+ mojo_from_viewer);
- if (!grip_pose) {
+ if (!other_from_pointer) {
return nullptr;
}
-
- if (input_source_->PointerTransform()) {
- grip_pose->Multiply(*(input_source_->PointerTransform()));
+ if (input_source_->InputFromPointer()) {
+ other_from_pointer->Multiply(*(input_source_->InputFromPointer()));
}
-
- return grip_pose;
+ return other_from_pointer;
}
XRPose* XRTargetRaySpace::getPose(
XRSpace* other_space,
- const TransformationMatrix* base_pose_matrix) {
+ const TransformationMatrix* mojo_from_viewer) {
// If we don't have a valid base pose (most common when tracking is lost),
// we can't get a target ray pose regardless of the mode.
- if (!base_pose_matrix) {
+ if (!mojo_from_viewer) {
+ DVLOG(2) << __func__ << " : mojo_from_viewer is null, returning nullptr";
return nullptr;
}
- std::unique_ptr<TransformationMatrix> pointer_pose = nullptr;
+ std::unique_ptr<TransformationMatrix> other_from_ray = nullptr;
switch (input_source_->TargetRayMode()) {
case device::mojom::XRTargetRayMode::TAPPING: {
- pointer_pose = GetPointerPoseForScreen(other_space, *base_pose_matrix);
+ other_from_ray = OtherSpaceFromScreenTap(other_space, *mojo_from_viewer);
break;
}
case device::mojom::XRTargetRayMode::GAZING: {
// If the pointer origin is the users head, this is a gaze cursor and the
// returned pointer is based on the device pose. Just return the head pose
// as the pointer pose.
- pointer_pose = other_space->TransformBasePose(*base_pose_matrix);
+ other_from_ray = other_space->SpaceFromViewer(*mojo_from_viewer);
break;
}
case device::mojom::XRTargetRayMode::POINTING: {
- pointer_pose = GetTrackedPointerPose(other_space, *base_pose_matrix);
+ other_from_ray =
+ OtherSpaceFromTrackedPointer(other_space, *mojo_from_viewer);
break;
}
- default: {
- return nullptr;
- }
}
- if (!pointer_pose) {
+ if (!other_from_ray) {
+ DVLOG(2) << __func__ << " : "
+ << "other_from_ray is null, input_source_->TargetRayMode() = "
+ << input_source_->TargetRayMode();
return nullptr;
}
// Account for any changes made to the reference space's origin offset so that
// things like teleportation works.
- TransformationMatrix adjusted_pose =
- other_space->InverseOriginOffsetMatrix().Multiply(*pointer_pose);
- return MakeGarbageCollected<XRPose>(adjusted_pose,
+ //
+ // otheroffset_from_ray = otheroffset_from_other * other_from_ray
+ // where otheroffset_from_other = inverse(other_from_otheroffset)
+ // TODO(https://crbug.com/1008466): move originOffset to separate class?
+ TransformationMatrix otheroffset_from_ray =
+ other_space->InverseOriginOffsetMatrix().Multiply(*other_from_ray);
+ return MakeGarbageCollected<XRPose>(otheroffset_from_ray,
input_source_->emulatedPosition());
}
+base::Optional<XRNativeOriginInformation> XRTargetRaySpace::NativeOrigin()
+ const {
+ return input_source_->nativeOrigin();
+}
+
void XRTargetRaySpace::Trace(blink::Visitor* visitor) {
visitor->Trace(input_source_);
XRSpace::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.h b/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.h
index bf7c704ddf9..8df09c58c8a 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_target_ray_space.h
@@ -13,19 +13,21 @@ namespace blink {
class XRTargetRaySpace : public XRSpace {
public:
- XRTargetRaySpace(XRSession*, XRInputSource*);
+ XRTargetRaySpace(XRSession* session, XRInputSource* input_space);
XRPose* getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) override;
+ base::Optional<XRNativeOriginInformation> NativeOrigin() const override;
+
void Trace(blink::Visitor*) override;
private:
- std::unique_ptr<TransformationMatrix> GetPointerPoseForScreen(
+ std::unique_ptr<TransformationMatrix> OtherSpaceFromScreenTap(
XRSpace* other_space,
- const TransformationMatrix& base_pose_matrix);
- std::unique_ptr<TransformationMatrix> GetTrackedPointerPose(
+ const TransformationMatrix& mojo_from_viewer);
+ std::unique_ptr<TransformationMatrix> OtherSpaceFromTrackedPointer(
XRSpace* other_space,
- const TransformationMatrix& base_pose_matrix);
+ const TransformationMatrix& mojo_from_viewer);
Member<XRInputSource> input_source_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_world_information.cc b/chromium/third_party/blink/renderer/modules/xr/xr_world_information.cc
index 0feed185dab..6af75714927 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_world_information.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_world_information.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/xr/xr_world_information.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
namespace blink {
@@ -58,7 +59,7 @@ void XRWorldInformation::ProcessPlaneInformation(
is_detected_planes_null_ = false;
- HeapHashMap<int32_t, Member<XRPlane>> updated_planes;
+ HeapHashMap<uint32_t, Member<XRPlane>> updated_planes;
// First, process all planes that had their information updated (new planes
// are also processed here).
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_world_information.h b/chromium/third_party/blink/renderer/modules/xr/xr_world_information.h
index 6f6e8167355..bd03a3a3f72 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_world_information.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_world_information.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_WORLD_INFORMATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_WORLD_INFORMATION_H_
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "device/vr/public/mojom/vr_service.mojom-blink-forward.h"
#include "third_party/blink/renderer/modules/xr/xr_plane.h"
#include "third_party/blink/renderer/modules/xr/xr_plane_set.h"
@@ -37,7 +37,7 @@ class XRWorldInformation : public ScriptWrappable {
// This is the case if we have a freshly constructed instance, or if our
// last `ProcessPlaneInformation()` was called with base::nullopt.
bool is_detected_planes_null_ = true;
- HeapHashMap<int32_t, Member<XRPlane>> plane_ids_to_planes_;
+ HeapHashMap<uint32_t, Member<XRPlane>> plane_ids_to_planes_;
Member<XRSession> session_;
};
diff --git a/chromium/third_party/blink/renderer/platform/BUILD.gn b/chromium/third_party/blink/renderer/platform/BUILD.gn
index 0e85ec3df1b..a3f1ea12b1e 100644
--- a/chromium/third_party/blink/renderer/platform/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/BUILD.gn
@@ -16,7 +16,10 @@ import("//third_party/blink/renderer/platform/platform_generated.gni")
import("//v8/gni/v8.gni")
# Most targets in this file are private actions so use that as the default.
-visibility = [ ":*" ]
+visibility = [
+ ":*",
+ "//third_party/blink/renderer/platform/heap:test_support",
+]
blink_platform_avx_files = [
"audio/cpu/x86/vector_math_avx.cc",
@@ -398,6 +401,7 @@ jumbo_component("platform") {
"bindings/callback_method_retriever.cc",
"bindings/callback_method_retriever.h",
"bindings/custom_wrappable.h",
+ "bindings/dom_data_store.cc",
"bindings/dom_data_store.h",
"bindings/dom_wrapper_world.cc",
"bindings/dom_wrapper_world.h",
@@ -425,7 +429,6 @@ jumbo_component("platform") {
"bindings/script_state.h",
"bindings/script_wrappable.cc",
"bindings/script_wrappable.h",
- "bindings/shared_persistent.h",
"bindings/string_resource.cc",
"bindings/string_resource.h",
"bindings/to_v8.h",
@@ -607,6 +610,8 @@ jumbo_component("platform") {
"fonts/font_global_context.h",
"fonts/font_metrics.cc",
"fonts/font_metrics.h",
+ "fonts/font_optical_sizing.cc",
+ "fonts/font_optical_sizing.h",
"fonts/font_orientation.cc",
"fonts/font_orientation.h",
"fonts/font_platform_data.cc",
@@ -724,6 +729,10 @@ jumbo_component("platform") {
"fonts/web_font_typeface_factory.h",
"fonts/win/dwrite_font_format_support.cc",
"fonts/win/dwrite_font_format_support.h",
+ "fonts/win/fallback_family_style_cache_win.cc",
+ "fonts/win/fallback_family_style_cache_win.h",
+ "fonts/win/fallback_lru_cache_win.cc",
+ "fonts/win/fallback_lru_cache_win.h",
"fonts/win/font_cache_skia_win.cc",
"fonts/win/font_fallback_win.cc",
"fonts/win/font_fallback_win.h",
@@ -999,7 +1008,6 @@ jumbo_component("platform") {
"graphics/interpolation_space.cc",
"graphics/interpolation_space.h",
"graphics/lab_color_space.h",
- "graphics/link_highlight.h",
"graphics/logging_canvas.cc",
"graphics/logging_canvas.h",
"graphics/mailbox_texture_holder.cc",
@@ -1184,6 +1192,12 @@ jumbo_component("platform") {
"mac/web_core_ns_cell_extras.h",
"mac/web_core_ns_cell_extras.mm",
"media/webaudiosourceprovider_impl.cc",
+ "media_capabilities/web_audio_configuration.h",
+ "media_capabilities/web_media_capabilities_info.h",
+ "media_capabilities/web_media_capabilities_key_system_configuration.h",
+ "media_capabilities/web_media_configuration.h",
+ "media_capabilities/web_media_decoding_configuration.h",
+ "media_capabilities/web_video_configuration.h",
"mediastream/aec_dump_agent_impl.cc",
"mediastream/aec_dump_agent_impl.h",
"mediastream/audio_service_audio_processor_proxy.cc",
@@ -1213,14 +1227,31 @@ jumbo_component("platform") {
"mojo/canonical_cookie_mojom_traits.cc",
"mojo/canonical_cookie_mojom_traits.h",
"mojo/fetch_api_request_headers_mojom_traits.h",
- "mojo/interface_invalidator.cc",
- "mojo/interface_invalidator.h",
"mojo/mojo_helper.h",
- "mojo/revocable_binding.h",
- "mojo/revocable_interface_ptr.h",
- "mojo/revocable_strong_binding.h",
"mojo/string16_mojom_traits.cc",
"mojo/string16_mojom_traits.h",
+ "p2p/empty_network_manager.cc",
+ "p2p/empty_network_manager.h",
+ "p2p/filtering_network_manager.cc",
+ "p2p/filtering_network_manager.h",
+ "p2p/host_address_request.cc",
+ "p2p/host_address_request.h",
+ "p2p/ipc_network_manager.cc",
+ "p2p/ipc_network_manager.h",
+ "p2p/ipc_socket_factory.cc",
+ "p2p/ipc_socket_factory.h",
+ "p2p/mdns_responder_adapter.cc",
+ "p2p/mdns_responder_adapter.h",
+ "p2p/network_list_manager.h",
+ "p2p/network_list_observer.h",
+ "p2p/network_manager_uma.cc",
+ "p2p/network_manager_uma.h",
+ "p2p/socket_client.h",
+ "p2p/socket_client_delegate.h",
+ "p2p/socket_client_impl.cc",
+ "p2p/socket_client_impl.h",
+ "p2p/socket_dispatcher.cc",
+ "p2p/socket_dispatcher.h",
"peerconnection/audio_codec_factory.cc",
"peerconnection/rtc_answer_options_platform.h",
"peerconnection/rtc_dtmf_sender_handler.cc",
@@ -1244,6 +1275,12 @@ jumbo_component("platform") {
"peerconnection/rtc_video_encoder_factory.cc",
"peerconnection/rtc_video_encoder_factory.h",
"peerconnection/rtc_void_request.h",
+ "peerconnection/stun_field_trial.cc",
+ "peerconnection/stun_field_trial.h",
+ "peerconnection/transmission_encoding_info_handler.cc",
+ "peerconnection/transmission_encoding_info_handler.h",
+ "peerconnection/video_codec_factory.cc",
+ "peerconnection/video_codec_factory.h",
"peerconnection/webrtc_audio_sink.cc",
"peerconnection/webrtc_video_track_source.cc",
"prerender.cc",
@@ -1431,11 +1468,13 @@ jumbo_component("platform") {
deps = [
":platform_export",
"//base/allocator:buildflags",
+ "//components/paint_preview/common",
"//components/viz/client",
"//components/viz/common",
"//crypto",
"//device/vr/public/mojom:mojom_blink",
"//gin",
+ "//jingle:webrtc_glue",
"//media",
"//media/capture/mojom:video_capture",
"//mojo/public/cpp/base",
@@ -1450,7 +1489,9 @@ jumbo_component("platform") {
"//third_party/ced",
"//third_party/emoji-segmenter",
"//third_party/icu",
+ "//third_party/libyuv",
"//third_party/webrtc/api:libjingle_logging_api",
+ "//third_party/webrtc/api:packet_socket_factory",
"//third_party/webrtc/api/audio_codecs/L16:audio_decoder_L16",
"//third_party/webrtc/api/audio_codecs/L16:audio_encoder_L16",
"//third_party/webrtc/api/audio_codecs/g711:audio_decoder_g711",
@@ -1463,6 +1504,7 @@ jumbo_component("platform") {
"//third_party/webrtc/api/audio_codecs/opus:audio_decoder_opus",
"//third_party/webrtc/api/audio_codecs/opus:audio_encoder_multiopus",
"//third_party/webrtc/api/audio_codecs/opus:audio_encoder_opus",
+ "//third_party/webrtc/media:rtc_internal_video_codecs",
"//third_party/webrtc/modules/video_coding:webrtc_h264",
"//third_party/webrtc/p2p:rtc_p2p",
"//third_party/webrtc_overrides:init_webrtc",
@@ -1470,6 +1512,7 @@ jumbo_component("platform") {
"//ui/base:base",
"//ui/gfx",
"//ui/gfx/geometry",
+ "//ui/gfx/mojom",
]
if (is_mac) {
@@ -1553,6 +1596,8 @@ jumbo_static_library("test_support") {
sources = [
"graphics/gpu/drawing_buffer_test_helpers.h",
+ "graphics/test/gpu_test_utils.cc",
+ "graphics/test/gpu_test_utils.h",
"testing/code_cache_loader_mock.cc",
"testing/code_cache_loader_mock.h",
"testing/compositor_test.cc",
@@ -1594,6 +1639,8 @@ jumbo_static_library("test_support") {
"testing/unit_test_helpers.h",
"testing/url_test_helpers.cc",
"testing/url_test_helpers.h",
+ "testing/video_frame_utils.cc",
+ "testing/video_frame_utils.h",
"testing/viewport_layers_setup.cc",
"testing/viewport_layers_setup.h",
"testing/weburl_loader_mock.cc",
@@ -1629,11 +1676,13 @@ jumbo_static_library("test_support") {
deps = [
"//base/test:test_support",
+ "//media:test_support",
"//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//services/service_manager/public/cpp",
"//skia",
"//third_party/blink/renderer/platform/blob:test_support",
+ "//third_party/blink/renderer/platform/heap:test_support",
"//third_party/blink/renderer/platform/loader:test_support",
"//third_party/blink/renderer/platform/network:test_support",
"//third_party/blink/renderer/platform/scheduler:test_support",
@@ -1673,6 +1722,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"exported/mediastream/media_stream_audio_processor_options_test.cc",
"exported/mediastream/media_stream_audio_test.cc",
"exported/mediastream/webrtc_uma_histograms_test.cc",
+ "exported/page_zoom_test.cc",
"exported/video_capture/web_video_capture_impl_manager_test.cc",
"exported/web_canonical_cookie_test.cc",
"exported/web_icon_sizes_parser_test.cc",
@@ -1792,12 +1842,15 @@ jumbo_source_set("blink_platform_unittests_sources") {
"mhtml/mhtml_parser_test.cc",
"mojo/big_string_mojom_traits_test.cc",
"mojo/geometry_mojom_traits_test.cc",
- "mojo/interface_invalidator_test.cc",
"mojo/kurl_security_origin_test.cc",
"mojo/string16_mojom_traits_test.cc",
+ "p2p/filtering_network_manager_test.cc",
+ "p2p/ipc_network_manager_test.cc",
"peerconnection/rtc_stats_test.cc",
"peerconnection/rtc_video_decoder_adapter_test.cc",
"peerconnection/rtc_video_encoder_test.cc",
+ "peerconnection/stun_field_trial_test.cc",
+ "peerconnection/transmission_encoding_info_handler_test.cc",
"peerconnection/two_keys_adapter_map_unittest.cc",
"peerconnection/webrtc_video_track_source_test.cc",
"text/bidi_resolver_test.cc",
@@ -1822,16 +1875,20 @@ jumbo_source_set("blink_platform_unittests_sources") {
"transforms/rotation_test.cc",
"transforms/transform_operations_test.cc",
"transforms/transformation_matrix_test.cc",
+ "video_capture/gpu_memory_buffer_test_support.cc",
+ "video_capture/gpu_memory_buffer_test_support.h",
"video_capture/video_capture_impl_test.cc",
"weborigin/known_ports_test.cc",
"weborigin/kurl_test.cc",
"weborigin/scheme_registry_test.cc",
"weborigin/security_origin_test.cc",
"weborigin/security_policy_test.cc",
+ "webrtc/webrtc_video_frame_adapter_test.cc",
]
if (is_win) {
sources += [ "text/locale_win_test.cc" ]
+ sources += [ "fonts/win/fallback_lru_cache_win_test.cc" ]
} else if (is_mac) {
sources += [
"fonts/opentype/open_type_caps_support_test.mm",
diff --git a/chromium/third_party/blink/renderer/platform/DEPS b/chromium/third_party/blink/renderer/platform/DEPS
index cbc4b785e3a..9a37cb552a9 100644
--- a/chromium/third_party/blink/renderer/platform/DEPS
+++ b/chromium/third_party/blink/renderer/platform/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+base/bind.h",
"+base/bind_helpers.h",
"+base/bit_cast.h",
+ "+base/command_line.h",
"+base/compiler_specific.h",
"+base/cpu.h",
"+base/feature_list.h",
diff --git a/chromium/third_party/blink/renderer/platform/OWNERS b/chromium/third_party/blink/renderer/platform/OWNERS
index ff5335a8461..8b254a80be2 100644
--- a/chromium/third_party/blink/renderer/platform/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/OWNERS
@@ -10,6 +10,7 @@ jbroman@chromium.org
jochen@chromium.org
kbr@chromium.org
kinuko@chromium.org
+kojii@chromium.org
mkwst@chromium.org
noel@chromium.org
pdr@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/animation/animated_layers_test.cc b/chromium/third_party/blink/renderer/platform/animation/animated_layers_test.cc
index 4ed2a366583..10a1866b599 100644
--- a/chromium/third_party/blink/renderer/platform/animation/animated_layers_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/animated_layers_test.cc
@@ -46,68 +46,4 @@ class AnimationForTesting : public CompositorAnimationClient {
std::unique_ptr<CompositorAnimation> compositor_animation_;
};
-// TODO(bokan): This test doesn't yet work because cc::Layers can't set an
-// element id in that mode. We fail at AttachElement since the element id is
-// invalid. https://crbug.com/993386.
-TEST_F(AnimatedLayersTest,
- DISABLED_updateLayerShouldFlattenTransformWithAnimations) {
- cc::Layer* cc_layer = layers_.graphics_layer().CcLayer();
- cc::MutatorHost* mutator = layers_.layer_tree_host()->mutator_host();
- EXPECT_FALSE(
- mutator->HasTickingKeyframeModelForTesting(cc_layer->element_id()));
-
- auto curve = std::make_unique<CompositorFloatAnimationCurve>();
- curve->AddKeyframe(
- CompositorFloatKeyframe(0.0, 0.0,
- *CubicBezierTimingFunction::Preset(
- CubicBezierTimingFunction::EaseType::EASE)));
- auto float_keyframe_model(std::make_unique<CompositorKeyframeModel>(
- *curve, compositor_target_property::OPACITY, 0, 0));
- int keyframe_model_id = float_keyframe_model->Id();
-
- auto compositor_timeline = std::make_unique<CompositorAnimationTimeline>();
- AnimationForTesting animation;
-
- cc::AnimationHost* host = layers_.animation_host();
-
- host->AddAnimationTimeline(compositor_timeline->GetAnimationTimeline());
- compositor_timeline->AnimationAttached(animation);
-
- cc_layer->SetElementId(CompositorElementId(cc_layer->id()));
-
- animation.GetCompositorAnimation()->AttachElement(cc_layer->element_id());
- ASSERT_TRUE(animation.GetCompositorAnimation()->IsElementAttached());
-
- animation.GetCompositorAnimation()->AddKeyframeModel(
- std::move(float_keyframe_model));
-
- EXPECT_TRUE(
- mutator->HasTickingKeyframeModelForTesting(cc_layer->element_id()));
-
- layers_.graphics_layer().SetShouldFlattenTransform(false);
-
- cc_layer = layers_.graphics_layer().CcLayer();
- ASSERT_TRUE(cc_layer);
-
- EXPECT_TRUE(
- mutator->HasTickingKeyframeModelForTesting(cc_layer->element_id()));
- animation.GetCompositorAnimation()->RemoveKeyframeModel(keyframe_model_id);
- EXPECT_FALSE(
- mutator->HasTickingKeyframeModelForTesting(cc_layer->element_id()));
-
- layers_.graphics_layer().SetShouldFlattenTransform(true);
-
- cc_layer = layers_.graphics_layer().CcLayer();
- ASSERT_TRUE(cc_layer);
-
- EXPECT_FALSE(
- mutator->HasTickingKeyframeModelForTesting(cc_layer->element_id()));
-
- animation.GetCompositorAnimation()->DetachElement();
- ASSERT_FALSE(animation.GetCompositorAnimation()->IsElementAttached());
-
- compositor_timeline->AnimationDestroyed(animation);
- host->RemoveAnimationTimeline(compositor_timeline->GetAnimationTimeline());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_bus.cc b/chromium/third_party/blink/renderer/platform/audio/audio_bus.cc
index 93a91994bf7..e2162d04478 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_bus.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_bus.cc
@@ -45,7 +45,8 @@
namespace blink {
-using namespace vector_math;
+using vector_math::Vadd;
+using vector_math::Vsma;
const unsigned kMaxBusChannels = 32;
@@ -527,8 +528,8 @@ void AudioBus::CopyWithGainFrom(const AudioBus& source_bus, float gain) {
} else {
for (unsigned channel_index = 0; channel_index < number_of_channels;
++channel_index) {
- Vsmul(sources[channel_index], 1, &gain, destinations[channel_index], 1,
- frames_to_process);
+ vector_math::Vsmul(sources[channel_index], 1, &gain,
+ destinations[channel_index], 1, frames_to_process);
}
}
}
@@ -562,7 +563,8 @@ void AudioBus::CopyWithSampleAccurateGainValuesFrom(
if (source_bus.NumberOfChannels() == NumberOfChannels())
source = source_bus.Channel(channel_index)->Data();
float* destination = Channel(channel_index)->MutableData();
- Vmul(source, 1, gain_values, 1, destination, 1, number_of_gain_values);
+ vector_math::Vmul(source, 1, gain_values, 1, destination, 1,
+ number_of_gain_values);
}
}
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 e4b6950925a..c32867ed9c7 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_channel.cc
@@ -35,8 +35,6 @@
namespace blink {
-using namespace vector_math;
-
void AudioChannel::ResizeSmaller(size_t new_length) {
DCHECK_LE(new_length, length_);
length_ = new_length;
@@ -46,7 +44,7 @@ void AudioChannel::Scale(float scale) {
if (IsSilent())
return;
- Vsmul(Data(), 1, &scale, MutableData(), 1, length());
+ vector_math::Vsmul(Data(), 1, &scale, MutableData(), 1, length());
}
void AudioChannel::CopyFrom(const AudioChannel* source_channel) {
@@ -98,10 +96,12 @@ void AudioChannel::SumFrom(const AudioChannel* source_channel) {
if (source_channel->IsSilent())
return;
- if (IsSilent())
+ if (IsSilent()) {
CopyFrom(source_channel);
- else
- Vadd(Data(), 1, source_channel->Data(), 1, MutableData(), 1, length());
+ } else {
+ vector_math::Vadd(Data(), 1, source_channel->Data(), 1, MutableData(), 1,
+ length());
+ }
}
float AudioChannel::MaxAbsValue() const {
@@ -110,7 +110,7 @@ float AudioChannel::MaxAbsValue() const {
float max = 0;
- Vmaxmgv(Data(), 1, &max, length());
+ vector_math::Vmaxmgv(Data(), 1, &max, length());
return max;
}
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 d0c04723a2b..4a47aa8aaa8 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
@@ -83,52 +83,95 @@ void AudioDelayDSPKernel::Process(const float* source,
DCHECK(destination);
float sample_rate = this->SampleRate();
- double delay_time = 0;
- float* delay_times = delay_times_.Data();
double max_time = MaxDelayTime();
- bool sample_accurate = HasSampleAccurateValues();
-
- if (sample_accurate) {
+ if (HasSampleAccurateValues()) {
+ float* delay_times = delay_times_.Data();
CalculateSampleAccurateValues(delay_times, frames_to_process);
- } else {
- delay_time = this->DelayTime(sample_rate);
-
- // Make sure the delay time is in a valid range.
- delay_time = clampTo(delay_time, 0.0, max_time);
- }
- for (unsigned i = 0; i < frames_to_process; ++i) {
- if (sample_accurate) {
- delay_time = delay_times[i];
+ for (unsigned i = 0; i < frames_to_process; ++i) {
+ double delay_time = delay_times[i];
if (std::isnan(delay_time))
delay_time = max_time;
else
delay_time = clampTo(delay_time, 0.0, max_time);
- }
- double desired_delay_frames = delay_time * sample_rate;
+ double desired_delay_frames = delay_time * sample_rate;
+
+ double read_position =
+ write_index_ + buffer_length - desired_delay_frames;
+ if (read_position >= buffer_length)
+ read_position -= buffer_length;
+
+ // Linearly interpolate in-between delay times.
+ int read_index1 = static_cast<int>(read_position);
+ int read_index2 = (read_index1 + 1) % buffer_length;
+ double interpolation_factor = read_position - read_index1;
+
+ double input = static_cast<float>(*source++);
+ buffer[write_index_] = static_cast<float>(input);
+ write_index_ = (write_index_ + 1) % buffer_length;
+ double sample1 = buffer[read_index1];
+ double sample2 = buffer[read_index2];
+
+ double output = (1.0 - interpolation_factor) * sample1 +
+ interpolation_factor * sample2;
+
+ *destination++ = static_cast<float>(output);
+ }
+ } else {
+ // This is basically the same as above, but optimized for the case where the
+ // delay time is constant for the current render.
+ //
+ // TODO(crbug.com/1012198): There are still some further optimizations that
+ // could be done. interp_factor could be a float to eliminate several
+ // conversions between floats and doubles. It might be possible to get rid
+ // of the wrapping if the buffer were longer. This may aslo allow
+ // |write_index_| to be different from |read_index1| or |read_index2| which
+ // simplifies the loop a bit.
+
+ double delay_time = this->DelayTime(sample_rate);
+ // Make sure the delay time is in a valid range.
+ delay_time = clampTo(delay_time, 0.0, max_time);
+ double desired_delay_frames = delay_time * sample_rate;
double read_position = write_index_ + buffer_length - desired_delay_frames;
if (read_position >= buffer_length)
read_position -= buffer_length;
- // Linearly interpolate in-between delay times.
+ // Linearly interpolate in-between delay times. |read_index1| and
+ // |read_index2| are the indices of the frames to be used for
+ // interpolation.
int read_index1 = static_cast<int>(read_position);
int read_index2 = (read_index1 + 1) % buffer_length;
- double interpolation_factor = read_position - read_index1;
-
- double input = static_cast<float>(*source++);
- buffer[write_index_] = static_cast<float>(input);
- write_index_ = (write_index_ + 1) % buffer_length;
-
- double sample1 = buffer[read_index1];
- double sample2 = buffer[read_index2];
-
- double output =
- (1.0 - interpolation_factor) * sample1 + interpolation_factor * sample2;
+ double interp_factor = read_position - read_index1;
+
+ int w_index = write_index_;
+
+ for (unsigned i = 0; i < frames_to_process; ++i) {
+ // Copy the latest sample into the buffer. Needed because
+ // w_index could be the same as read_index1 or read_index2.
+ buffer[w_index] = *source++;
+ float sample1 = buffer[read_index1];
+ float sample2 = buffer[read_index2];
+
+ // Update the indices and wrap them to the beginning of the buffer if
+ // needed.
+ ++w_index;
+ ++read_index1;
+ ++read_index2;
+ if (w_index >= static_cast<int>(buffer_length))
+ w_index -= buffer_length;
+ if (read_index1 >= static_cast<int>(buffer_length))
+ read_index1 -= buffer_length;
+ if (read_index2 >= static_cast<int>(buffer_length))
+ read_index2 -= buffer_length;
+
+ // Linearly interpolate between samples.
+ *destination++ = (1 - interp_factor) * sample1 + interp_factor * sample2;
+ }
- *destination++ = static_cast<float>(output);
+ write_index_ = w_index;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.cc b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
index 2768fcbd57b..ac01b96c9bc 100644
--- a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor.cc
@@ -33,8 +33,6 @@
namespace blink {
-using namespace audio_utilities;
-
DynamicsCompressor::DynamicsCompressor(float sample_rate,
unsigned number_of_channels)
: number_of_channels_(number_of_channels),
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 b57bf9c409c..daec0eceb54 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
@@ -36,8 +36,6 @@
namespace blink {
-using namespace audio_utilities;
-
// Metering hits peaks instantly, but releases this fast (in seconds).
const float kMeteringReleaseTimeConstant = 0.325f;
@@ -63,8 +61,9 @@ DynamicsCompressorKernel::DynamicsCompressorKernel(float sample_rate,
// Initializes most member variables
Reset();
- metering_release_k_ = static_cast<float>(DiscreteTimeConstantForSampleRate(
- kMeteringReleaseTimeConstant, sample_rate));
+ metering_release_k_ =
+ float{audio_utilities::DiscreteTimeConstantForSampleRate(
+ kMeteringReleaseTimeConstant, sample_rate)};
}
void DynamicsCompressorKernel::SetNumberOfChannels(
@@ -114,10 +113,10 @@ float DynamicsCompressorKernel::Saturate(float x, float k) {
y = KneeCurve(x, k);
else {
// Constant ratio after knee.
- float x_db = LinearToDecibels(x);
+ float x_db = audio_utilities::LinearToDecibels(x);
float y_db = yknee_threshold_db_ + slope_ * (x_db - knee_threshold_db_);
- y = DecibelsToLinear(y_db);
+ y = audio_utilities::DecibelsToLinear(y_db);
}
return y;
@@ -132,11 +131,11 @@ float DynamicsCompressorKernel::SlopeAt(float x, float k) {
float x2 = x * 1.001;
- float x_db = LinearToDecibels(x);
- float x2_db = LinearToDecibels(x2);
+ float x_db = audio_utilities::LinearToDecibels(x);
+ float x2_db = audio_utilities::LinearToDecibels(x2);
- float y_db = LinearToDecibels(KneeCurve(x, k));
- float y2_db = LinearToDecibels(KneeCurve(x2, k));
+ float y_db = audio_utilities::LinearToDecibels(KneeCurve(x, k));
+ float y2_db = audio_utilities::LinearToDecibels(KneeCurve(x2, k));
float m = (y2_db - y_db) / (x2_db - x_db);
@@ -145,7 +144,7 @@ float DynamicsCompressorKernel::SlopeAt(float x, float k) {
float DynamicsCompressorKernel::KAtSlope(float desired_slope) {
float x_db = db_threshold_ + db_knee_;
- float x = DecibelsToLinear(x_db);
+ float x = audio_utilities::DecibelsToLinear(x_db);
// Approximate k given initial values.
float min_k = 0.1;
@@ -178,7 +177,7 @@ float DynamicsCompressorKernel::UpdateStaticCurveParameters(float db_threshold,
if (db_threshold != db_threshold_ || db_knee != db_knee_ || ratio != ratio_) {
// Threshold and knee.
db_threshold_ = db_threshold;
- linear_threshold_ = DecibelsToLinear(db_threshold);
+ linear_threshold_ = audio_utilities::DecibelsToLinear(db_threshold);
db_knee_ = db_knee;
// Compute knee parameters.
@@ -188,9 +187,10 @@ float DynamicsCompressorKernel::UpdateStaticCurveParameters(float db_threshold,
float k = KAtSlope(1 / ratio_);
knee_threshold_db_ = db_threshold + db_knee;
- knee_threshold_ = DecibelsToLinear(knee_threshold_db_);
+ knee_threshold_ = audio_utilities::DecibelsToLinear(knee_threshold_db_);
- yknee_threshold_db_ = LinearToDecibels(KneeCurve(knee_threshold_, k));
+ yknee_threshold_db_ =
+ audio_utilities::LinearToDecibels(KneeCurve(knee_threshold_, k));
knee_ = k;
}
@@ -233,7 +233,7 @@ void DynamicsCompressorKernel::Process(
full_range_makeup_gain = powf(full_range_makeup_gain, 0.6f);
float master_linear_gain =
- DecibelsToLinear(db_post_gain) * full_range_makeup_gain;
+ audio_utilities::DecibelsToLinear(db_post_gain) * full_range_makeup_gain;
// Attack parameters.
attack_time = std::max(0.001f, attack_time);
@@ -317,8 +317,8 @@ void DynamicsCompressorKernel::Process(
if (scaled_desired_gain == 0) {
compression_diff_db = is_releasing ? -1 : 1;
} else {
- compression_diff_db =
- LinearToDecibels(compressor_gain_ / scaled_desired_gain);
+ compression_diff_db = audio_utilities::LinearToDecibels(
+ compressor_gain_ / scaled_desired_gain);
}
if (is_releasing) {
@@ -352,7 +352,7 @@ void DynamicsCompressorKernel::Process(
#define kSpacingDb 5
float db_per_frame = kSpacingDb / calc_release_frames;
- envelope_rate = DecibelsToLinear(db_per_frame);
+ envelope_rate = audio_utilities::DecibelsToLinear(db_per_frame);
} else {
// Attack mode - compressionDiffDb should be positive dB
@@ -417,12 +417,13 @@ void DynamicsCompressorKernel::Process(
float attenuation = abs_input <= 0.0001f ? 1 : shaped_input / abs_input;
- float attenuation_db = -LinearToDecibels(attenuation);
+ float attenuation_db = -audio_utilities::LinearToDecibels(attenuation);
attenuation_db = std::max(2.0f, attenuation_db);
float db_per_frame = attenuation_db / sat_release_frames;
- float sat_release_rate = DecibelsToLinear(db_per_frame) - 1;
+ float sat_release_rate =
+ audio_utilities::DecibelsToLinear(db_per_frame) - 1;
bool is_release = (attenuation > detector_average);
float rate = is_release ? sat_release_rate : 1;
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 6531386b903..a01b3fec556 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_convolver.cc
@@ -31,8 +31,6 @@
namespace blink {
-using namespace vector_math;
-
FFTConvolver::FFTConvolver(size_t fft_size)
: frame_(fft_size),
read_write_index_(0),
@@ -88,8 +86,8 @@ void FFTConvolver::Process(const FFTFrame* fft_kernel,
frame_.DoInverseFFT(output_buffer_.Data());
// Overlap-add 1st half from previous time
- Vadd(output_buffer_.Data(), 1, last_overlap_buffer_.Data(), 1,
- output_buffer_.Data(), 1, half_size);
+ vector_math::Vadd(output_buffer_.Data(), 1, last_overlap_buffer_.Data(),
+ 1, output_buffer_.Data(), 1, half_size);
// Finally, save 2nd half of result
DCHECK_EQ(output_buffer_.size(), 2 * half_size);
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 2c4517f6d6e..81e8266794c 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
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/audio/push_pull_fifo.h"
+#include <algorithm>
#include <memory>
+
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -207,7 +209,8 @@ size_t PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) {
: 0;
}
-const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const {
+const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() {
+ MutexLocker locker(lock_);
return {length(), NumberOfChannels(), frames_available_, index_read_,
index_write_, overflow_count_, underflow_count_};
}
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 a86ad7e715f..cf7b2c399f1 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
@@ -67,15 +67,21 @@ class PLATFORM_EXPORT PushPullFIFO {
size_t Pull(AudioBus* output_bus, size_t frames_requested);
size_t length() const { return fifo_length_; }
- unsigned NumberOfChannels() const { return fifo_bus_->NumberOfChannels(); }
+ unsigned NumberOfChannels() const {
+ lock_.AssertAcquired();
+ return fifo_bus_->NumberOfChannels();
+ }
// TODO(hongchan): For single thread unit test only. Consider refactoring.
- AudioBus* GetFIFOBusForTest() const { return fifo_bus_.get(); }
+ AudioBus* GetFIFOBusForTest() {
+ MutexLocker locker(lock_);
+ return fifo_bus_.get();
+ }
// For single thread unit test only. Get the current configuration that
// consists of FIFO length, number of channels, read/write index position and
// under/overflow count.
- const PushPullFIFOStateForTest GetStateForTest() const;
+ const PushPullFIFOStateForTest GetStateForTest();
private:
// The size of the FIFO.
@@ -86,13 +92,12 @@ class PLATFORM_EXPORT PushPullFIFO {
unsigned overflow_count_ = 0;
unsigned underflow_count_ = 0;
- // This lock protects variables below.
Mutex lock_;
// The number of frames in the FIFO actually available for pulling.
- size_t frames_available_ = 0;
- size_t index_read_ = 0;
- size_t index_write_ = 0;
- scoped_refptr<AudioBus> fifo_bus_;
+ size_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);
};
diff --git a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc
index abdc15b8b7c..1e5db219d62 100644
--- a/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/push_pull_fifo_multithread_test.cc
@@ -30,7 +30,8 @@ class FIFOClient {
public:
FIFOClient(PushPullFIFO* fifo, size_t bus_length, size_t jitter_range_ms)
: fifo_(fifo),
- bus_(AudioBus::Create(fifo->NumberOfChannels(), bus_length)),
+ bus_(AudioBus::Create(fifo->GetStateForTest().number_of_channels,
+ bus_length)),
client_thread_(Platform::Current()->CreateThread(
ThreadCreationParams(WebThreadType::kTestThread)
.SetThreadNameForTest("FIFOClientThread"))),
diff --git a/chromium/third_party/blink/renderer/platform/audio/reverb.cc b/chromium/third_party/blink/renderer/platform/audio/reverb.cc
index 392e709effe..e7eca7d2093 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb.cc
@@ -41,8 +41,6 @@
namespace blink {
-using namespace vector_math;
-
// Empirical gain calibration tested across many impulse responses to ensure
// perceived volume is same as dry (unprocessed) signal
const float kGainCalibration = -58;
@@ -61,7 +59,8 @@ static float CalculateNormalizationScale(AudioBus* response) {
for (size_t i = 0; i < number_of_channels; ++i) {
float channel_power = 0;
- Vsvesq(response->Channel(i)->Data(), 1, &channel_power, length);
+ vector_math::Vsvesq(response->Channel(i)->Data(), 1, &channel_power,
+ length);
power += channel_power;
}
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 fe801b8c65c..b92806e3fec 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,8 +32,6 @@
namespace blink {
-using namespace vector_math;
-
ReverbAccumulationBuffer::ReverbAccumulationBuffer(size_t length)
: buffer_(length), read_index_(0), read_time_frame_(0) {}
@@ -90,13 +88,14 @@ int ReverbAccumulationBuffer::Accumulate(float* source,
DCHECK_LE(number_of_frames1 + write_index, buffer_length);
DCHECK_LE(number_of_frames2, buffer_length);
- Vadd(source, 1, destination + write_index, 1, destination + write_index, 1,
- number_of_frames1);
+ vector_math::Vadd(source, 1, destination + write_index, 1,
+ destination + write_index, 1, number_of_frames1);
// Handle wrap-around if necessary
- if (number_of_frames2 > 0)
- Vadd(source + number_of_frames1, 1, destination, 1, destination, 1,
- number_of_frames2);
+ if (number_of_frames2 > 0) {
+ vector_math::Vadd(source + number_of_frames1, 1, destination, 1,
+ destination, 1, number_of_frames2);
+ }
return write_index;
}
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 5bd54e4c908..68b923ba2bb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/reverb_convolver.cc
@@ -41,8 +41,6 @@
namespace blink {
-using namespace vector_math;
-
const int kInputBufferSize = 8 * 16384;
// We only process the leading portion of the impulse response in the real-time
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 19054adc3b3..65fe7e63b89 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
@@ -23,7 +23,7 @@ namespace blink {
// |Invoke| member function that performs "invoke" steps. Subclasses will
// implement it.
class PLATFORM_EXPORT CallbackFunctionBase
- : public GarbageCollectedFinalized<CallbackFunctionBase>,
+ : public GarbageCollected<CallbackFunctionBase>,
public NameClient {
public:
virtual ~CallbackFunctionBase() = default;
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 896a9faf982..6176390dcec 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
@@ -21,7 +21,7 @@ namespace blink {
// As the signatures of callback interface's operations vary, this class does
// not implement any operation. Subclasses will implement it.
class PLATFORM_EXPORT CallbackInterfaceBase
- : public GarbageCollectedFinalized<CallbackInterfaceBase>,
+ : public GarbageCollected<CallbackInterfaceBase>,
public NameClient {
public:
// Whether the callback interface is a "single operation callback interface"
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 65a381fb91f..f7a543b205b 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/custom_wrappable.h
@@ -13,7 +13,7 @@ namespace blink {
// See the comment on CustomWrappableAdaptor.
class PLATFORM_EXPORT CustomWrappable
- : public GarbageCollectedFinalized<CustomWrappable>,
+ : public GarbageCollected<CustomWrappable>,
public NameClient {
public:
virtual ~CustomWrappable() = default;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc
new file mode 100644
index 00000000000..5e10e7024b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.cc
@@ -0,0 +1,31 @@
+// 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/bindings/dom_data_store.h"
+
+namespace blink {
+
+DOMDataStore::DOMDataStore(v8::Isolate* isolate, bool is_main_world)
+ : is_main_world_(is_main_world) {}
+
+void DOMDataStore::Dispose() {
+ for (const auto& it : wrapper_map_) {
+ // Explicitly reset references so that a following V8 GC will not find them
+ // and treat them as roots. There's optimizations (see
+ // EmbedderHeapTracer::IsRootForNonTracingGC) that would not treat them as
+ // roots and then Blink would not be able to find and remove them from a DOM
+ // world. Explicitly resetting on disposal avoids that problem
+ it.value->ref.Clear();
+ }
+}
+
+void DOMDataStore::WrappedReference::Trace(Visitor* visitor) {
+ visitor->Trace(ref);
+}
+
+void DOMDataStore::Trace(Visitor* visitor) {
+ visitor->Trace(wrapper_map_);
+}
+
+} // namespace blink
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 d660b674b01..e582ad68741 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
@@ -48,9 +48,7 @@ namespace blink {
// wrappers and provides an API to perform common operations with this map and
// manage wrappers in a single world. Each world (DOMWrapperWorld) holds a
// single map instance to hold wrappers only for that world.
-class DOMDataStore {
- USING_FAST_MALLOC(DOMDataStore);
-
+class DOMDataStore final : public GarbageCollected<DOMDataStore> {
public:
static DOMDataStore& Current(v8::Isolate* isolate) {
return DOMWrapperWorld::Current(isolate).DomDataStore();
@@ -110,20 +108,17 @@ class DOMDataStore {
return Current(isolate).ContainsWrapper(object);
}
- DOMDataStore(v8::Isolate* isolate, bool is_main_world)
- : is_main_world_(is_main_world) {
- // We never use |wrapper_map_| when it's the main world.
- if (!is_main_world) {
- wrapper_map_.emplace();
- }
- }
+ DOMDataStore(v8::Isolate* isolate, bool is_main_world);
+
+ // Clears all references.
+ void Dispose();
v8::Local<v8::Object> Get(ScriptWrappable* object, v8::Isolate* isolate) {
if (is_main_world_)
return object->MainWorldWrapper(isolate);
- auto it = wrapper_map_->find(object);
- if (it != wrapper_map_->end())
- return it->value.NewLocal(isolate);
+ auto it = wrapper_map_.find(object);
+ if (it != wrapper_map_.end())
+ return it->value->ref.NewLocal(isolate);
return v8::Local<v8::Object>();
}
@@ -136,41 +131,40 @@ class DOMDataStore {
if (is_main_world_)
return object->SetWrapper(isolate, wrapper_type_info, wrapper);
- auto result = wrapper_map_->insert(object, Value(isolate, wrapper));
+ auto result = wrapper_map_.insert(
+ object, MakeGarbageCollected<WrappedReference>(isolate, wrapper));
if (LIKELY(result.is_new_entry)) {
- wrapper_type_info->ConfigureWrapper(&result.stored_value->value.Get());
- result.stored_value->value.Get().SetFinalizationCallback(
- this, RemoveEntryFromMap);
+ wrapper_type_info->ConfigureWrapper(
+ &result.stored_value->value->ref.Get());
} else {
- DCHECK(!result.stored_value->value.IsEmpty());
- wrapper = result.stored_value->value.NewLocal(isolate);
+ DCHECK(!result.stored_value->value->ref.IsEmpty());
+ wrapper = result.stored_value->value->ref.NewLocal(isolate);
}
return result.is_new_entry;
}
- void Trace(const ScriptWrappable* script_wrappable, Visitor* visitor) {
- DCHECK(wrapper_map_);
- auto it =
- wrapper_map_->find(const_cast<ScriptWrappable*>(script_wrappable));
- if (it != wrapper_map_->end()) {
- visitor->Trace(
- static_cast<TraceWrapperV8Reference<v8::Object>&>(it->value));
- }
- }
-
- // Dissociates a wrapper, if any, from |script_wrappable|.
- void UnsetWrapperIfAny(ScriptWrappable* script_wrappable) {
+ bool UnsetSpecificWrapperIfSet(
+ ScriptWrappable* object,
+ const v8::TracedReference<v8::Object>& handle) {
DCHECK(!is_main_world_);
- wrapper_map_->erase(script_wrappable);
+ const auto& it = wrapper_map_.find(object);
+ if (it != wrapper_map_.end()) {
+ if (it->value->ref.Get() == handle) {
+ it->value->ref.Clear();
+ wrapper_map_.erase(it);
+ return true;
+ }
+ }
+ return false;
}
bool SetReturnValueFrom(v8::ReturnValue<v8::Value> return_value,
ScriptWrappable* object) {
if (is_main_world_)
return object->SetReturnValue(return_value);
- auto it = wrapper_map_->find(object);
- if (it != wrapper_map_->end()) {
- return_value.Set(it->value.Get());
+ auto it = wrapper_map_.find(object);
+ if (it != wrapper_map_.end()) {
+ return_value.Set(it->value->ref.Get());
return true;
}
return false;
@@ -179,10 +173,12 @@ class DOMDataStore {
bool ContainsWrapper(const ScriptWrappable* object) {
if (is_main_world_)
return object->ContainsWrapper();
- return wrapper_map_->find(const_cast<ScriptWrappable*>(object)) !=
- wrapper_map_->end();
+ return wrapper_map_.find(const_cast<ScriptWrappable*>(object)) !=
+ wrapper_map_.end();
}
+ virtual void Trace(Visitor*);
+
private:
// We can use a wrapper stored in a ScriptWrappable when we're in the main
// world. This method does the fast check if we're in the main world. If this
@@ -203,54 +199,25 @@ class DOMDataStore {
return wrappable->IsEqualTo(holder);
}
- static void RemoveEntryFromMap(const v8::WeakCallbackInfo<void>& data) {
- DOMDataStore* store = reinterpret_cast<DOMDataStore*>(data.GetParameter());
- ScriptWrappable* key = reinterpret_cast<ScriptWrappable*>(
- data.GetInternalField(kV8DOMWrapperObjectIndex));
- const auto& it = store->wrapper_map_->find(key);
- DCHECK_NE(store->wrapper_map_->end(), it);
- store->wrapper_map_->erase(it);
- WrapperTypeInfo::WrapperDestroyed();
- }
-
- // Specialization of TraceWrapperV8Reference to avoid write barriers on move
- // operations. This is correct as entries are never moved out of the storage
- // but only moved for rehashing purposes.
- //
- // We need to avoid write barriers to allow resizing of the hashmap backing
- // during V8 garbage collections. The resize is triggered when entries are
- // removed which happens in a phase where V8 prohibits any API calls. To work
- // around that we just don't emit write barriers for moving.
- class DOMWorldWrapperReference : public TraceWrapperV8Reference<v8::Object> {
+ // Wrapper around TraceWrapperV8Reference to allow use in ephemeron hash map
+ // below.
+ class PLATFORM_EXPORT WrappedReference final
+ : public GarbageCollected<WrappedReference> {
public:
- DOMWorldWrapperReference() = default;
- // Regular write barrier for constructor is emitted by
- // TraceWrapperV8Reference.
- DOMWorldWrapperReference(v8::Isolate* isolate, v8::Local<v8::Object> handle)
- : TraceWrapperV8Reference(isolate, handle) {}
+ WrappedReference() = default;
+ WrappedReference(v8::Isolate* isolate, v8::Local<v8::Object> handle)
+ : ref(isolate, handle) {}
- // Move support without write barrier.
- DOMWorldWrapperReference(DOMWorldWrapperReference&& other) noexcept
- : TraceWrapperV8Reference() {
- handle_ = std::move(other.handle_);
- }
- DOMWorldWrapperReference& operator=(
- DOMWorldWrapperReference&& rhs) noexcept {
- handle_ = std::move(rhs.handle_);
- return *this;
- }
- };
+ virtual void Trace(Visitor*);
- // UntracedMember is safe here as the map is not keeping ScriptWrappable alive
- // but merely adding additional edges from Blink to V8.
- using Key = UntracedMember<ScriptWrappable>;
- using Value = DOMWorldWrapperReference;
- using MapType = WTF::HashMap<Key, Value>;
+ TraceWrapperV8Reference<v8::Object> ref;
+ };
bool is_main_world_;
- GC_PLUGIN_IGNORE(
- "Avoid dispatch on Visitor by looking up value in DOMDataStore::Trace.")
- base::Optional<MapType> wrapper_map_;
+ // Ephemeron map: WrappedReference will be kept alive as long as
+ // ScriptWrappable is alive.
+ HeapHashMap<WeakMember<ScriptWrappable>, Member<WrappedReference>>
+ wrapper_map_;
DISALLOW_COPY_AND_ASSIGN(DOMDataStore);
};
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 23bb6ef9bd4..a48be9f22f4 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
@@ -73,7 +73,8 @@ DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate,
int32_t world_id)
: world_type_(world_type),
world_id_(world_id),
- dom_data_store_(std::make_unique<DOMDataStore>(isolate, IsMainWorld())) {
+ dom_data_store_(
+ MakeGarbageCollected<DOMDataStore>(isolate, IsMainWorld())) {
switch (world_type_) {
case WorldType::kMain:
// The main world is managed separately from worldMap(). See worldMap().
@@ -109,16 +110,6 @@ void DOMWrapperWorld::AllWorldsInCurrentThread(
worlds.push_back(world);
}
-void DOMWrapperWorld::Trace(const ScriptWrappable* script_wrappable,
- Visitor* visitor) {
- // Marking for worlds other than the main world.
- for (DOMWrapperWorld* world : GetWorldMap().Values()) {
- DOMDataStore& data_store = world->DomDataStore();
- if (data_store.ContainsWrapper(script_wrappable))
- data_store.Trace(script_wrappable, visitor);
- }
-}
-
DOMWrapperWorld::~DOMWrapperWorld() {
DCHECK(!IsMainWorld());
if (IsMainThread())
@@ -131,7 +122,8 @@ DOMWrapperWorld::~DOMWrapperWorld() {
}
void DOMWrapperWorld::Dispose() {
- dom_data_store_.reset();
+ dom_data_store_->Dispose();
+ dom_data_store_.Clear();
DCHECK(GetWorldMap().Contains(world_id_));
GetWorldMap().erase(world_id_);
}
@@ -238,17 +230,6 @@ int DOMWrapperWorld::GenerateWorldIdForType(WorldType world_type) {
return kInvalidWorldId;
}
-void DOMWrapperWorld::DissociateDOMWindowWrappersInAllWorlds(
- ScriptWrappable* script_wrappable) {
- DCHECK(script_wrappable);
- DCHECK(IsMainThread());
-
- script_wrappable->UnsetWrapperIfAny();
-
- for (auto*& world : GetWorldMap().Values())
- world->DomDataStore().UnsetWrapperIfAny(script_wrappable);
-}
-
bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread(
ScriptWrappable* script_wrappable) {
DCHECK(IsMainThread());
@@ -263,4 +244,16 @@ bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread(
return false;
}
+// static
+bool DOMWrapperWorld::UnsetNonMainWorldWrapperIfSet(
+ ScriptWrappable* object,
+ const v8::TracedReference<v8::Object>& handle) {
+ for (DOMWrapperWorld* world : GetWorldMap().Values()) {
+ DOMDataStore& data_store = world->DomDataStore();
+ if (data_store.UnsetSpecificWrapperIfSet(object, handle))
+ return true;
+ }
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index 5b6ffba7554..75dde53c356 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -37,6 +37,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_isolated_world_ids.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.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"
@@ -104,9 +105,6 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
static void AllWorldsInCurrentThread(
Vector<scoped_refptr<DOMWrapperWorld>>& worlds);
- // Traces wrappers corresponding to the ScriptWrappable in DOM data stores.
- static void Trace(const ScriptWrappable*, Visitor*);
-
static DOMWrapperWorld& World(v8::Local<v8::Context> context) {
return ScriptState::From(context)->World();
}
@@ -142,7 +140,16 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
int GetWorldId() const { return world_id_; }
DOMDataStore& DomDataStore() const { return *dom_data_store_; }
+ // Clear the reference pointing from |object| to |handle| in any world.
+ static bool UnsetSpecificWrapperIfSet(
+ ScriptWrappable* object,
+ const v8::TracedReference<v8::Object>& handle);
+
private:
+ static bool UnsetNonMainWorldWrapperIfSet(
+ ScriptWrappable* object,
+ const v8::TracedReference<v8::Object>& handle);
+
DOMWrapperWorld(v8::Isolate*, WorldType, int32_t world_id);
static unsigned number_of_non_main_worlds_in_main_thread_;
@@ -152,35 +159,23 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
// out of DOMWrapperWorld.
static int GenerateWorldIdForType(WorldType);
- // Dissociates all wrappers in all worlds associated with |script_wrappable|.
- //
- // Do not use this function except for DOMWindow. Only DOMWindow needs to
- // dissociate wrappers from the ScriptWrappable because of the following two
- // reasons.
- //
- // Reason 1) Case of the main world
- // A DOMWindow may be collected by Blink GC *before* V8 GC collects the
- // wrapper because the wrapper object associated with a DOMWindow is a global
- // proxy, which remains after navigations. We don't want V8 GC to reset the
- // weak persistent handle to a wrapper within the DOMWindow
- // (ScriptWrappable::main_world_wrapper_) *after* Blink GC collects the
- // DOMWindow because it's use-after-free. Thus, we need to dissociate the
- // wrapper in advance.
- //
- // Reason 2) Case of isolated worlds
- // As same, a DOMWindow may be collected before the wrapper gets collected.
- // A DOMWrapperMap supports mapping from ScriptWrappable* to v8::Global<T>,
- // and we don't want to leave an entry of an already-dead DOMWindow* to the
- // persistent handle for the global proxy object, especially considering that
- // the address to the already-dead DOMWindow* may be re-used.
- friend class DOMWindow;
- static void DissociateDOMWindowWrappersInAllWorlds(ScriptWrappable*);
-
const WorldType world_type_;
const int32_t world_id_;
- std::unique_ptr<DOMDataStore> dom_data_store_;
+ Persistent<DOMDataStore> dom_data_store_;
};
+// static
+inline bool DOMWrapperWorld::UnsetSpecificWrapperIfSet(
+ ScriptWrappable* object,
+ const v8::TracedReference<v8::Object>& handle) {
+ // Fast path for main world.
+ if (object->UnsetMainWorldWrapperIfSet(handle))
+ return true;
+
+ // Slow path: |object| may point to |handle| in any non-main DOM world.
+ return DOMWrapperWorld::UnsetNonMainWorldWrapperIfSet(object, handle);
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_DOM_WRAPPER_WORLD_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 20d03c1a9d2..310c57cea15 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -209,12 +209,7 @@ ParkableStringImpl::~ParkableStringImpl() {
if (!may_be_parked())
return;
-#if DCHECK_IS_ON()
- {
- MutexLocker locker(mutex_);
- DCHECK_EQ(0, lock_depth_);
- }
-#endif
+ DCHECK_EQ(0, lock_depth_for_testing());
AsanUnpoisonString(string_);
DCHECK(state_ == State::kParked || state_ == State::kUnparked);
@@ -362,7 +357,7 @@ ParkableStringImpl::AgeOrParkResult ParkableStringImpl::MaybeAgeOrParkString() {
DCHECK(!is_parked());
Status status = CurrentStatus();
- if (is_young()) {
+ if (is_young_) {
if (status == Status::kUnreferencedExternally)
is_young_ = false;
} else {
@@ -403,7 +398,7 @@ bool ParkableStringImpl::Park(ParkingMode mode) {
void ParkableStringImpl::ParkInternal(ParkingMode mode) {
mutex_.AssertAcquired();
DCHECK_EQ(State::kUnparked, state_);
- DCHECK(!is_young());
+ DCHECK(!is_young_);
DCHECK(CanParkNow());
// Parking can proceed synchronously.
@@ -449,7 +444,7 @@ ParkableStringImpl::Status ParkableStringImpl::CurrentStatus() const {
}
bool ParkableStringImpl::CanParkNow() const {
- return CurrentStatus() == Status::kUnreferencedExternally && !is_young();
+ return CurrentStatus() == Status::kUnreferencedExternally && !is_young_;
}
void ParkableStringImpl::Unpark() {
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 abc5d42e1c8..96fa7f71b94 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
@@ -11,6 +11,7 @@
#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/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -105,12 +106,10 @@ class PLATFORM_EXPORT ParkableStringImpl final
return compressed_->size();
}
- // A string can either be "young" or "old". It starts young, and transitions
- // are:
- // Young -> Old: By calling |MaybeAgeOrParkString()|.
- // Old -> Young: When the string is accessed, either by |Lock()|-ing it or
- // calling |ToString()|.
- bool is_young() const { return is_young_; }
+ bool is_young_for_testing() {
+ MutexLocker locker(mutex_);
+ return is_young_;
+ }
private:
enum class State : uint8_t;
@@ -128,12 +127,12 @@ class PLATFORM_EXPORT ParkableStringImpl final
// May be called from any thread.
void LockWithoutMakingYoung();
#endif // defined(ADDRESS_SANITIZER)
- // May be called from any thread. Must acquire |mutex_| first.
- void MakeYoung();
- // Whether the string is referenced or locked. Must be called with |mutex_|
- // held, and the return value is valid as long as |mutex_| is held.
- Status CurrentStatus() const;
- bool CanParkNow() const;
+ // May be called from any thread.
+ void MakeYoung() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ // Whether the string is referenced or locked. The return value is valid as
+ // long as |mutex_| is held.
+ Status CurrentStatus() const EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ bool CanParkNow() const EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void ParkInternal(ParkingMode mode);
void Unpark();
String UnparkInternal() const;
@@ -151,14 +150,29 @@ class PLATFORM_EXPORT ParkableStringImpl final
// Background thread.
static void CompressInBackground(std::unique_ptr<CompressionTaskParams>);
- Mutex mutex_; // protects lock_depth_.
- int lock_depth_;
+ int lock_depth_for_testing() {
+ MutexLocker locker_(mutex_);
+ return lock_depth_;
+ }
+
+ Mutex mutex_;
+ int lock_depth_ GUARDED_BY(mutex_);
// Main thread only.
State state_;
String string_;
std::unique_ptr<Vector<uint8_t>> compressed_;
- bool is_young_ : 1;
+
+ // A string can either be "young" or "old". It starts young, and transitions
+ // are:
+ // Young -> Old: By calling |MaybeAgeOrParkString()|.
+ // Old -> Young: When the string is accessed, either by |Lock()|-ing it or
+ // calling |ToString()|.
+ //
+ // Thread safety: it is typically not safe to guard only one part of a
+ // bitfield with a mutex, but this is correct here, as the other members are
+ // const (and never change).
+ bool is_young_ : 1 GUARDED_BY(mutex_);
const bool may_be_parked_ : 1;
const bool is_8bit_ : 1;
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 8421304b09a..f3c6a8a3683 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
@@ -25,6 +25,12 @@
namespace blink {
+// Disabling this will cause parkable strings to never be compressed.
+// This is useful for headless mode + virtual time. Since virtual time advances
+// quickly, strings may be parked too eagerly in that mode.
+const base::Feature kCompressParkableStrings{"CompressParkableStrings",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
struct ParkableStringManager::Statistics {
size_t original_size;
size_t uncompressed_size;
@@ -38,11 +44,18 @@ struct ParkableStringManager::Statistics {
namespace {
+bool CompressionEnabled() {
+ return base::FeatureList::IsEnabled(kCompressParkableStrings);
+}
+
class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
public MemoryPressureListener {
USING_GARBAGE_COLLECTED_MIXIN(OnPurgeMemoryListener);
void OnPurgeMemory() override {
+ if (!CompressionEnabled()) {
+ return;
+ }
ParkableStringManager::Instance().PurgeMemory();
}
};
@@ -147,7 +160,8 @@ bool ParkableStringManager::ShouldPark(const StringImpl& string) {
// Don't attempt to park strings smaller than this size.
static constexpr unsigned int kSizeThreshold = 10000;
// TODO(lizeb): Consider parking non-main thread strings.
- return string.length() > kSizeThreshold && IsMainThread();
+ return string.length() > kSizeThreshold && IsMainThread() &&
+ CompressionEnabled();
}
scoped_refptr<ParkableStringImpl> ParkableStringManager::Add(
@@ -254,6 +268,7 @@ void ParkableStringManager::RecordUnparkingTime(
void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
DCHECK(IsMainThread());
+ DCHECK(CompressionEnabled());
size_t total_size = 0;
for (ParkableStringImpl* str : parked_strings_)
@@ -305,6 +320,8 @@ void ParkableStringManager::RecordStatisticsAfter5Minutes() const {
}
void ParkableStringManager::AgeStringsAndPark() {
+ DCHECK(CompressionEnabled());
+
TRACE_EVENT0("blink", "ParkableStringManager::AgeStringsAndPark");
has_pending_aging_task_ = false;
@@ -331,6 +348,9 @@ void ParkableStringManager::AgeStringsAndPark() {
}
void ParkableStringManager::ScheduleAgingTaskIfNeeded() {
+ if (!CompressionEnabled())
+ return;
+
if (has_pending_aging_task_)
return;
@@ -346,6 +366,7 @@ void ParkableStringManager::ScheduleAgingTaskIfNeeded() {
void ParkableStringManager::PurgeMemory() {
DCHECK(IsMainThread());
+ DCHECK(CompressionEnabled());
ParkAll(ParkableStringImpl::ParkingMode::kAlways);
// Critical memory pressure: drop compressed data for strings that we cannot
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 1333ed75f9a..5aefb0984ac 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_PARKABLE_STRING_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_PARKABLE_STRING_MANAGER_H_
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
@@ -21,6 +22,8 @@ namespace blink {
class ParkableString;
+PLATFORM_EXPORT extern const base::Feature kCompressParkableStrings;
+
class PLATFORM_EXPORT ParkableStringManagerDumpProvider
: public base::trace_event::MemoryDumpProvider {
USING_FAST_MALLOC(ParkableStringManagerDumpProvider);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index 920ae68c433..970245a9599 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -8,6 +8,7 @@
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/elapsed_timer.h"
@@ -59,7 +60,9 @@ class ParkableStringTest : public ::testing::Test {
}
void WaitForAging() {
- EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
+ if (base::FeatureList::IsEnabled(kCompressParkableStrings)) {
+ EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
+ }
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(
ParkableStringManager::kAgingIntervalInSeconds));
}
@@ -362,15 +365,15 @@ TEST_F(ParkableStringTest, Unpark) {
TEST_F(ParkableStringTest, LockUnlock) {
ParkableString parkable(MakeLargeString().Impl());
ParkableStringImpl* impl = parkable.Impl();
- EXPECT_EQ(0, impl->lock_depth_);
+ EXPECT_EQ(0, impl->lock_depth_for_testing());
parkable.Lock();
- EXPECT_EQ(1, impl->lock_depth_);
+ EXPECT_EQ(1, impl->lock_depth_for_testing());
parkable.Lock();
parkable.Unlock();
- EXPECT_EQ(1, impl->lock_depth_);
+ EXPECT_EQ(1, impl->lock_depth_for_testing());
parkable.Unlock();
- EXPECT_EQ(0, impl->lock_depth_);
+ EXPECT_EQ(0, impl->lock_depth_for_testing());
parkable.Lock();
EXPECT_FALSE(ParkAndWait(parkable));
@@ -393,12 +396,12 @@ TEST_F(ParkableStringTest, LockParkedString) {
EXPECT_TRUE(impl->is_parked());
parkable.ToString();
EXPECT_FALSE(impl->is_parked());
- EXPECT_EQ(1, impl->lock_depth_);
+ EXPECT_EQ(1, impl->lock_depth_for_testing());
EXPECT_FALSE(ParkAndWait(parkable));
parkable.Unlock();
- EXPECT_EQ(0, impl->lock_depth_);
+ EXPECT_EQ(0, impl->lock_depth_for_testing());
EXPECT_TRUE(ParkAndWait(parkable));
EXPECT_TRUE(impl->is_parked());
}
@@ -673,39 +676,51 @@ TEST_F(ParkableStringTest, ReportMemoryDump) {
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(savings))));
}
+TEST_F(ParkableStringTest, CompressionDisabled) {
+ base::test::ScopedFeatureList features;
+ features.InitAndDisableFeature(kCompressParkableStrings);
+
+ ParkableString parkable(MakeLargeString().ReleaseImpl());
+ WaitForDelayedParking();
+ EXPECT_FALSE(parkable.Impl()->is_parked());
+
+ MemoryPressureListenerRegistry::Instance().OnPurgeMemory();
+ EXPECT_FALSE(parkable.Impl()->is_parked());
+}
+
TEST_F(ParkableStringTest, Aging) {
ParkableString parkable(MakeLargeString().ReleaseImpl());
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
WaitForAging();
- EXPECT_FALSE(parkable.Impl()->is_young());
+ EXPECT_FALSE(parkable.Impl()->is_young_for_testing());
parkable.Lock();
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
// Locked strings don't age.
WaitForAging();
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
parkable.Unlock();
WaitForAging();
- EXPECT_FALSE(parkable.Impl()->is_young());
+ EXPECT_FALSE(parkable.Impl()->is_young_for_testing());
parkable.ToString();
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
// No external reference, can age again.
WaitForAging();
- EXPECT_FALSE(parkable.Impl()->is_young());
+ EXPECT_FALSE(parkable.Impl()->is_young_for_testing());
// External references prevent a string from aging.
String retained = parkable.ToString();
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
WaitForAging();
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
}
TEST_F(ParkableStringTest, OldStringsAreParked) {
ParkableString parkable(MakeLargeString().ReleaseImpl());
- EXPECT_TRUE(parkable.Impl()->is_young());
+ EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
WaitForAging();
- EXPECT_FALSE(parkable.Impl()->is_young());
+ EXPECT_FALSE(parkable.Impl()->is_young_for_testing());
WaitForAging();
EXPECT_TRUE(parkable.Impl()->is_parked());
diff --git a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
index acfa9640e6f..7899cd79360 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
@@ -177,7 +177,7 @@ Vector<RuntimeCallCounter*> RuntimeCallStats::CounterMapToSortedArray() const {
void RuntimeCallStats::AddCounterMapStatsToBuilder(
StringBuilder& builder) const {
builder.AppendFormat("\nNumber of counters in map: %u\n\n",
- counter_map_.size()));
+ counter_map_.size());
for (RuntimeCallCounter* counter : CounterMapToSortedArray()) {
builder.AppendFormat(row_format, counter->GetName(), counter->GetCount(),
counter->GetTime().InMillisecondsF());
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h b/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h
index ef9e174ec04..e6224751292 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_promise_properties.h
@@ -11,6 +11,7 @@
P(ScriptPromise, kClosed##__VA_ARGS__) \
P(ScriptPromise, kFinished##__VA_ARGS__) \
P(ScriptPromise, kLoaded##__VA_ARGS__) \
+ P(ScriptPromise, kLost##__VA_ARGS__) \
P(ScriptPromise, kReleased##__VA_ARGS__) \
P(ScriptPromise, kResponseReady##__VA_ARGS__) \
P(ScriptPromise, kUserChoice##__VA_ARGS__) \
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 b7deb68b9cd..f4ba8ef7edc 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
@@ -73,8 +73,7 @@ class V8PerContextData;
// ScriptState is created when v8::Context is created.
// ScriptState is destroyed when v8::Context is garbage-collected and
// all V8 proxy objects that have references to the ScriptState are destructed.
-class PLATFORM_EXPORT ScriptState final
- : public GarbageCollectedFinalized<ScriptState> {
+class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
public:
class Scope {
STACK_ALLOCATED();
@@ -204,8 +203,8 @@ class PLATFORM_EXPORT ScriptState final
// ScriptStateProtectingContext keeps the context associated with the
// ScriptState alive. You need to call Clear() once you no longer need the
// context. Otherwise, the context will leak.
-class ScriptStateProtectingContext
- : public GarbageCollectedFinalized<ScriptStateProtectingContext> {
+class ScriptStateProtectingContext final
+ : public GarbageCollected<ScriptStateProtectingContext> {
public:
explicit ScriptStateProtectingContext(ScriptState* script_state)
: script_state_(script_state) {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
index 5d4d7bd9349..3f344d0ccf0 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
@@ -40,7 +40,6 @@ v8::Local<v8::Object> ScriptWrappable::AssociateWithWrapper(
void ScriptWrappable::Trace(Visitor* visitor) {
visitor->Trace(main_world_wrapper_);
- DOMWrapperWorld::Trace(this, visitor);
}
const char* ScriptWrappable::NameInHeapSnapshot() const {
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 2a9c4ccf7e9..25475561588 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -50,7 +50,7 @@ namespace blink {
// The wrapper object for the main world is stored in ScriptWrappable. Wrapper
// objects for other worlds are stored in DOMWrapperMap.
class PLATFORM_EXPORT ScriptWrappable
- : public GarbageCollectedFinalized<ScriptWrappable>,
+ : public GarbageCollected<ScriptWrappable>,
public NameClient {
public:
virtual ~ScriptWrappable() = default;
@@ -128,14 +128,6 @@ class PLATFORM_EXPORT ScriptWrappable
return true;
}
- // Dissociates the wrapper, if any, from this instance.
- void UnsetWrapperIfAny() {
- if (ContainsWrapper()) {
- main_world_wrapper_.Get().Reset();
- WrapperTypeInfo::WrapperDestroyed();
- }
- }
-
bool IsEqualTo(const v8::Local<v8::Object>& other) const {
return main_world_wrapper_.Get() == other;
}
@@ -151,21 +143,41 @@ class PLATFORM_EXPORT ScriptWrappable
ScriptWrappable() = default;
private:
- // These classes are exceptionally allowed to use MainWorldWrapper().
- friend class DOMDataStore;
- friend class HeapSnaphotWrapperVisitor;
- friend class V8HiddenValue;
- friend class V8PrivateProperty;
-
v8::Local<v8::Object> MainWorldWrapper(v8::Isolate* isolate) const {
return main_world_wrapper_.NewLocal(isolate);
}
+ // Clear the main world wrapper if it is set to |handle|.
+ bool UnsetMainWorldWrapperIfSet(
+ const v8::TracedReference<v8::Object>& handle);
+
+ static_assert(
+ std::is_trivially_destructible<
+ TraceWrapperV8Reference<v8::Object>>::value,
+ "TraceWrapperV8Reference<v8::Object> should be trivially destructible.");
+
TraceWrapperV8Reference<v8::Object> main_world_wrapper_;
+ // These classes are exceptionally allowed to directly interact with the main
+ // world wrapper.
+ friend class DOMDataStore;
+ friend class DOMWrapperWorld;
+ friend class HeapSnaphotWrapperVisitor;
+ friend class V8HiddenValue;
+ friend class V8PrivateProperty;
+
DISALLOW_COPY_AND_ASSIGN(ScriptWrappable);
};
+inline bool ScriptWrappable::UnsetMainWorldWrapperIfSet(
+ const v8::TracedReference<v8::Object>& handle) {
+ if (main_world_wrapper_.Get() == handle) {
+ main_world_wrapper_.Clear();
+ return true;
+ }
+ return false;
+}
+
// Defines |GetWrapperTypeInfo| virtual method which returns the WrapperTypeInfo
// of the instance. Also declares a static member of type WrapperTypeInfo, of
// which the definition is given by the IDL code generator.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h b/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h
deleted file mode 100644
index 35a9036297a..00000000000
--- a/chromium/third_party/blink/renderer/platform/bindings/shared_persistent.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-// A ref counted version of ScopedPersistent. This class is intended for use by
-// ScriptValue and not for normal use. Consider using ScopedPersistent directly
-// instead.
-template <typename T>
-class SharedPersistent : public RefCounted<SharedPersistent<T>> {
- USING_FAST_MALLOC(SharedPersistent);
-
- public:
- static scoped_refptr<SharedPersistent<T>> Create(v8::Local<T> value,
- v8::Isolate* isolate) {
- return base::AdoptRef(new SharedPersistent<T>(value, isolate));
- }
-
- v8::Local<T> NewLocal(v8::Isolate* isolate) const {
- return value_.NewLocal(isolate);
- }
-
- bool IsEmpty() { return value_.IsEmpty(); }
-
- bool operator==(const SharedPersistent<T>& other) {
- return value_ == other.value_;
- }
-
- private:
- explicit SharedPersistent(v8::Local<T> value, v8::Isolate* isolate)
- : value_(isolate, value) {}
- ScopedPersistent<T> value_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedPersistent);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SHARED_PERSISTENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
index 53cfd74a90a..d11fd0c3acc 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
@@ -11,15 +11,6 @@
#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
#include "v8/include/v8.h"
-namespace v8 {
-
-template <typename T>
-struct TracedGlobalTrait<v8::TracedGlobal<T>> {
- static constexpr bool kRequiresExplicitDestruction = false;
-};
-
-} // namespace v8
-
namespace blink {
/**
@@ -50,8 +41,8 @@ class TraceWrapperV8Reference {
bool IsEmpty() const { return handle_.IsEmpty(); }
void Clear() { handle_.Reset(); }
- ALWAYS_INLINE const v8::TracedGlobal<T>& Get() const { return handle_; }
- ALWAYS_INLINE v8::TracedGlobal<T>& Get() { return handle_; }
+ ALWAYS_INLINE const v8::TracedReference<T>& Get() const { return handle_; }
+ ALWAYS_INLINE v8::TracedReference<T>& Get() { return handle_; }
template <typename S>
const TraceWrapperV8Reference<S>& Cast() const {
@@ -124,7 +115,7 @@ class TraceWrapperV8Reference {
UnifiedHeapMarkingVisitor::WriteBarrier(UnsafeCast<v8::Value>());
}
- v8::TracedGlobal<T> handle_;
+ v8::TracedReference<T> handle_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.cc
index 798b4d236c9..83ebb3cabab 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.cc
@@ -73,7 +73,10 @@ v8::Local<v8::Object> V8DOMWrapper::CreateWrapper(
bool V8DOMWrapper::IsWrapper(v8::Isolate* isolate, v8::Local<v8::Value> value) {
if (value.IsEmpty() || !value->IsObject())
return false;
+
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ if (!object->IsApiWrapper())
+ return false;
if (object->InternalFieldCount() < kV8DefaultWrapperInternalFieldCount)
return false;
@@ -89,7 +92,10 @@ bool V8DOMWrapper::IsWrapper(v8::Isolate* isolate, v8::Local<v8::Value> value) {
bool V8DOMWrapper::HasInternalFieldsSet(v8::Local<v8::Value> value) {
if (value.IsEmpty() || !value->IsObject())
return false;
+
v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ if (!object->IsApiWrapper())
+ return false;
if (object->InternalFieldCount() < kV8DefaultWrapperInternalFieldCount)
return false;
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 eb5e19b9ece..ac7c7a22708 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
@@ -98,17 +98,16 @@ class V8GlobalValueMapTraits {
* A map for safely storing persistent V8 values, based on
* v8::GlobalValueMap.
*/
-template <typename KeyType,
- typename ValueType,
- v8::PersistentContainerCallbackType type>
-class V8GlobalValueMap : public v8::GlobalValueMap<
- KeyType,
- ValueType,
- V8GlobalValueMapTraits<KeyType, ValueType, type>> {
+template <typename KeyType, typename ValueType>
+class V8GlobalValueMap
+ : public v8::GlobalValueMap<
+ KeyType,
+ ValueType,
+ V8GlobalValueMapTraits<KeyType, ValueType, v8::kNotWeak>> {
DISALLOW_NEW();
public:
- typedef V8GlobalValueMapTraits<KeyType, ValueType, type> Traits;
+ typedef V8GlobalValueMapTraits<KeyType, ValueType, v8::kNotWeak> Traits;
explicit V8GlobalValueMap(v8::Isolate* isolate)
: v8::GlobalValueMap<KeyType, ValueType, Traits>(isolate) {}
V8GlobalValueMap(v8::Isolate* isolate, const char* label)
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 146dbe6b481..203cb7cf540 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
@@ -132,13 +132,9 @@ class PLATFORM_EXPORT V8PerContextData final {
// For each possible type of wrapper, we keep a boilerplate object.
// The boilerplate is used to create additional wrappers of the same type.
- typedef V8GlobalValueMap<const WrapperTypeInfo*, v8::Object, v8::kNotWeak>
- WrapperBoilerplateMap;
- WrapperBoilerplateMap wrapper_boilerplates_;
+ V8GlobalValueMap<const WrapperTypeInfo*, v8::Object> wrapper_boilerplates_;
- typedef V8GlobalValueMap<const WrapperTypeInfo*, v8::Function, v8::kNotWeak>
- ConstructorMap;
- ConstructorMap constructor_map_;
+ V8GlobalValueMap<const WrapperTypeInfo*, v8::Function> constructor_map_;
std::unique_ptr<gin::ContextHolder> context_holder_;
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 9b4f14f811c..6b5c64a59f3 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/macros.h"
-#include "base/single_thread_task_runner.h"
#include "gin/public/gin_embedders.h"
#include "gin/public/isolate_holder.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
@@ -103,7 +102,7 @@ class PLATFORM_EXPORT V8PerIsolateData {
// Pointers to core/ objects that are garbage collected. Receives callback
// when V8PerIsolateData will be destroyed.
class PLATFORM_EXPORT GarbageCollectedData
- : public GarbageCollectedFinalized<GarbageCollectedData> {
+ : public GarbageCollected<GarbageCollectedData> {
public:
virtual ~GarbageCollectedData() = default;
virtual void WillBeDestroyed() {}
@@ -263,7 +262,7 @@ class PLATFORM_EXPORT V8PerIsolateData {
// When taking a V8 context snapshot, we can't keep V8 objects with eternal
// handles. So we use a special interface map that doesn't use eternal handles
// instead of the default V8FunctionTemplateMap.
- V8GlobalValueMap<const WrapperTypeInfo*, v8::FunctionTemplate, v8::kNotWeak>
+ V8GlobalValueMap<const WrapperTypeInfo*, v8::FunctionTemplate>
interface_template_map_for_v8_context_snapshot_;
std::unique_ptr<StringCache> string_cache_;
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 fdd9694dc65..6d41991be21 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
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.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_map.h"
#include "v8/include/v8.h"
namespace blink {
@@ -61,10 +62,6 @@ class ScriptWrappable;
#define V8_PRIVATE_PROPERTY_GETTER_NAME(InterfaceName, PrivateKeyName) \
Get##InterfaceName##PrivateKeyName
-// The member variable's name for a private property.
-#define V8_PRIVATE_PROPERTY_MEMBER_NAME(InterfaceName, PrivateKeyName) \
- m_symbol##InterfaceName##PrivateKeyName
-
// The string used to create a private symbol. Must be unique per V8 instance.
#define V8_PRIVATE_PROPERTY_SYMBOL_STRING(InterfaceName, PrivateKeyName) \
#InterfaceName "#" #PrivateKeyName // NOLINT(whitespace/indent)
@@ -148,20 +145,15 @@ class PLATFORM_EXPORT V8PrivateProperty {
v8::Isolate* isolate_;
};
-#define V8_PRIVATE_PROPERTY_DEFINE_GETTER(InterfaceName, KeyName) \
- static Symbol V8_PRIVATE_PROPERTY_GETTER_NAME(/* // NOLINT */ \
- InterfaceName, KeyName)( \
- v8::Isolate * isolate) { \
- V8PrivateProperty* private_prop = \
- V8PerIsolateData::From(isolate)->PrivateProperty(); \
- v8::Eternal<v8::Private>& property_handle = \
- private_prop->V8_PRIVATE_PROPERTY_MEMBER_NAME(InterfaceName, KeyName); \
- if (UNLIKELY(property_handle.IsEmpty())) { \
- property_handle.Set( \
- isolate, CreateV8Private(isolate, V8_PRIVATE_PROPERTY_SYMBOL_STRING( \
- InterfaceName, KeyName))); \
- } \
- return Symbol(isolate, property_handle.Get(isolate)); \
+#define V8_PRIVATE_PROPERTY_DEFINE_GETTER(InterfaceName, KeyName) \
+ static Symbol V8_PRIVATE_PROPERTY_GETTER_NAME(/* // NOLINT */ \
+ InterfaceName, KeyName)( \
+ v8::Isolate * isolate) { \
+ /* This key is used for uniquely identifying v8::Private. */ \
+ static int private_property_key; \
+ return GetSymbol( \
+ isolate, &private_property_key, \
+ V8_PRIVATE_PROPERTY_SYMBOL_STRING(InterfaceName, KeyName)); \
}
V8_PRIVATE_PROPERTY_FOR_EACH(V8_PRIVATE_PROPERTY_DEFINE_GETTER)
@@ -196,10 +188,36 @@ class PLATFORM_EXPORT V8PrivateProperty {
return GetSymbol(isolate, "unexpected cached accessor");
}
+ // This is a hack for PopStateEvent to get the same private property of
+ // History, named State.
+ static Symbol GetHistoryStateSymbol(v8::Isolate* isolate) {
+ // This key is used for uniquely identifying v8::Private.
+ static int private_property_key;
+ return GetSymbol(isolate, &private_property_key, "History#State");
+ }
+
static Symbol GetSymbol(v8::Isolate* isolate, const char* symbol) {
return Symbol(isolate, CreateCachedV8Private(isolate, symbol));
}
+ // Returns a Symbol to access a private property. Symbol instances from same
+ // |key|s are guaranteed to access the same property. |desc| is a description
+ // of the property.
+ static Symbol GetSymbol(v8::Isolate* isolate, void* key, const char* desc) {
+ V8PrivateProperty* private_prop =
+ V8PerIsolateData::From(isolate)->PrivateProperty();
+ auto& symbol_map = private_prop->symbol_map_;
+ auto iter = symbol_map.find(key);
+ v8::Local<v8::Private> v8_private;
+ if (UNLIKELY(iter == symbol_map.end())) {
+ v8_private = CreateV8Private(isolate, desc);
+ symbol_map.insert(key, v8::Eternal<v8::Private>(isolate, v8_private));
+ } else {
+ v8_private = iter->value.Get(isolate);
+ }
+ return Symbol(isolate, v8_private);
+ }
+
private:
static v8::Local<v8::Private> CreateV8Private(v8::Isolate*,
const char* symbol);
@@ -207,18 +225,14 @@ class PLATFORM_EXPORT V8PrivateProperty {
static v8::Local<v8::Private> CreateCachedV8Private(v8::Isolate*,
const char* symbol);
-#define V8_PRIVATE_PROPERTY_DECLARE_MEMBER(InterfaceName, KeyName) \
- v8::Eternal<v8::Private> V8_PRIVATE_PROPERTY_MEMBER_NAME( \
- InterfaceName, KeyName); // NOLINT(readability/naming/underscores)
- V8_PRIVATE_PROPERTY_FOR_EACH(V8_PRIVATE_PROPERTY_DECLARE_MEMBER)
-#undef V8_PRIVATE_PROPERTY_DECLARE_MEMBER
-
// TODO(peria): Do not use this specialized hack for
// Window#DocumentCachedAccessor. This is required to put v8::Private key in
// a snapshot, and it cannot be a v8::Eternal<> due to V8 serializer's
// requirement.
ScopedPersistent<v8::Private> symbol_window_document_cached_accessor_;
+ WTF::HashMap<void*, v8::Eternal<v8::Private>> symbol_map_;
+
DISALLOW_COPY_AND_ASSIGN(V8PrivateProperty);
};
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 4b873d32059..4782a9e4557 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
@@ -122,7 +122,7 @@ struct WrapperTypeInfo {
wrapper->SetWrapperClassId(wrapper_class_id);
}
- void ConfigureWrapper(v8::TracedGlobal<v8::Object>* wrapper) const {
+ void ConfigureWrapper(v8::TracedReference<v8::Object>* wrapper) const {
wrapper->SetWrapperClassId(wrapper_class_id);
}
@@ -177,7 +177,7 @@ inline T* GetInternalField(const v8::PersistentBase<v8::Object>& persistent) {
}
template <typename T, int offset>
-inline T* GetInternalField(const v8::TracedGlobal<v8::Object>& global) {
+inline T* GetInternalField(const v8::TracedReference<v8::Object>& global) {
DCHECK_LT(offset, v8::Object::InternalFieldCount(global));
return reinterpret_cast<T*>(
v8::Object::GetAlignedPointerFromInternalField(global, offset));
@@ -198,7 +198,7 @@ inline ScriptWrappable* ToScriptWrappable(
}
inline ScriptWrappable* ToScriptWrappable(
- const v8::TracedGlobal<v8::Object>& wrapper) {
+ const v8::TracedReference<v8::Object>& wrapper) {
return GetInternalField<ScriptWrappable, kV8DOMWrapperObjectIndex>(wrapper);
}
@@ -219,7 +219,8 @@ inline void* ToUntypedWrappable(const v8::PersistentBase<v8::Object>& wrapper) {
return GetInternalField<void, kV8DOMWrapperObjectIndex>(wrapper);
}
-inline void* ToUntypedWrappable(const v8::TracedGlobal<v8::Object>& wrapper) {
+inline void* ToUntypedWrappable(
+ const v8::TracedReference<v8::Object>& wrapper) {
return GetInternalField<void, kV8DOMWrapperObjectIndex>(wrapper);
}
@@ -233,7 +234,7 @@ inline const WrapperTypeInfo* ToWrapperTypeInfo(
}
inline const WrapperTypeInfo* ToWrapperTypeInfo(
- const v8::TracedGlobal<v8::Object>& wrapper) {
+ const v8::TracedReference<v8::Object>& wrapper) {
return GetInternalField<WrapperTypeInfo, kV8DOMWrapperTypeIndex>(wrapper);
}
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.h b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
index 5a65699c9a3..59b019a6ce9 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_BLOB_BYTES_PROVIDER_H_
#include "base/sequenced_task_runner.h"
-#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
+#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/blob/data_element.mojom-blink.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
index 3047792edfb..f88c3d4b5dd 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -374,13 +374,24 @@ mojo::PendingRemote<mojom::blink::Blob> BlobDataHandle::CloneBlobRemote() {
return blob_clone;
}
-network::mojom::blink::DataPipeGetterPtr BlobDataHandle::AsDataPipeGetter() {
+void BlobDataHandle::CloneBlobRemote(
+ mojo::PendingReceiver<mojom::blink::Blob> receiver) {
MutexLocker locker(blob_remote_mutex_);
if (!blob_remote_.is_valid())
- return nullptr;
- network::mojom::blink::DataPipeGetterPtr result;
+ return;
+ mojo::Remote<mojom::blink::Blob> blob(std::move(blob_remote_));
+ blob->Clone(std::move(receiver));
+ blob_remote_ = blob.Unbind();
+}
+
+mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+BlobDataHandle::AsDataPipeGetter() {
+ MutexLocker locker(blob_remote_mutex_);
+ if (!blob_remote_.is_valid())
+ return mojo::NullRemote();
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter> result;
mojo::Remote<mojom::blink::Blob> blob(std::move(blob_remote_));
- blob->AsDataPipeGetter(MakeRequest(&result));
+ blob->AsDataPipeGetter(result.InitWithNewPipeAndPassReceiver());
blob_remote_ = blob.Unbind();
return result;
}
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 212126e4348..9ae3614125a 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
@@ -55,7 +55,6 @@ namespace network {
namespace mojom {
namespace blink {
class DataPipeGetter;
-using DataPipeGetterPtr = mojo::InterfacePtr<DataPipeGetter>;
} // namespace blink
} // namespace mojom
} // namespace network
@@ -209,7 +208,8 @@ class PLATFORM_EXPORT BlobDataHandle
~BlobDataHandle();
mojo::PendingRemote<mojom::blink::Blob> CloneBlobRemote();
- network::mojom::blink::DataPipeGetterPtr AsDataPipeGetter();
+ void CloneBlobRemote(mojo::PendingReceiver<mojom::blink::Blob>);
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter> AsDataPipeGetter();
void ReadAll(mojo::ScopedDataPipeProducerHandle,
mojo::PendingRemote<mojom::blink::BlobReaderClient>);
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 508b485c1dd..ee7a6b4d2f9 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
@@ -24,7 +24,6 @@
namespace blink {
using mojom::blink::Blob;
-using mojom::blink::BlobPtr;
using mojom::blink::BlobRegistry;
using mojom::blink::DataElement;
using mojom::blink::DataElementBlob;
@@ -72,9 +71,9 @@ struct ExpectedElement {
static ExpectedElement Blob(const String& uuid,
uint64_t offset,
uint64_t length) {
- return ExpectedElement{
- DataElement::NewBlob(DataElementBlob::New(nullptr, offset, length)),
- uuid};
+ return ExpectedElement{DataElement::NewBlob(DataElementBlob::New(
+ mojo::NullRemote(), offset, length)),
+ uuid};
}
};
@@ -203,7 +202,8 @@ class BlobDataHandleTest : public testing::Test {
base::RunLoop loop;
String received_uuid;
- mojom::blink::BlobPtr blob(std::move(actual->get_blob()->blob));
+ mojo::Remote<mojom::blink::Blob> blob(
+ std::move(actual->get_blob()->blob));
blob->GetInternalUUID(base::BindOnce(
[](base::Closure quit_closure, String* uuid_out,
const String& uuid) {
diff --git a/chromium/third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.cc
index c58bb4cacf2..043ce32a06e 100644
--- a/chromium/third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/serialized_blob_mojom_traits.cc
@@ -16,7 +16,7 @@ bool StructTraits<blink::mojom::blink::SerializedBlob::DataView,
return false;
*out = blink::BlobDataHandle::Create(
uuid, type, data.size(),
- data.TakeBlob<blink::mojom::blink::BlobPtrInfo>());
+ data.TakeBlob<mojo::PendingRemote<blink::mojom::blink::Blob>>());
return true;
}
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 c5efe79a37e..733798e9c77 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
@@ -25,9 +25,10 @@ class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
DCHECK(result);
}
- void Clone(network::mojom::blink::DataPipeGetterRequest request) override {
- mojo::MakeStrongBinding(std::make_unique<SimpleDataPipeGetter>(str_),
- std::move(request));
+ void Clone(mojo::PendingReceiver<network::mojom::blink::DataPipeGetter>
+ receiver) override {
+ mojo::MakeSelfOwnedReceiver(std::make_unique<SimpleDataPipeGetter>(str_),
+ std::move(receiver));
}
private:
@@ -47,11 +48,11 @@ void FakeBlob::Clone(mojo::PendingReceiver<mojom::blink::Blob> receiver) {
}
void FakeBlob::AsDataPipeGetter(
- network::mojom::blink::DataPipeGetterRequest request) {
+ mojo::PendingReceiver<network::mojom::blink::DataPipeGetter> receiver) {
if (state_)
state_->did_initiate_read_operation = true;
- mojo::MakeStrongBinding(std::make_unique<SimpleDataPipeGetter>(body_),
- std::move(request));
+ mojo::MakeSelfOwnedReceiver(std::make_unique<SimpleDataPipeGetter>(body_),
+ std::move(receiver));
}
void FakeBlob::ReadRange(uint64_t offset,
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
index dbaa5b52974..8ec5c7654c1 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_TESTING_FAKE_BLOB_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_TESTING_FAKE_BLOB_H_
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
namespace blink {
@@ -22,7 +23,8 @@ class FakeBlob : public mojom::blink::Blob {
State* state = nullptr);
void Clone(mojo::PendingReceiver<mojom::blink::Blob>) override;
- void AsDataPipeGetter(network::mojom::blink::DataPipeGetterRequest) override;
+ void AsDataPipeGetter(
+ mojo::PendingReceiver<network::mojom::blink::DataPipeGetter>) override;
void ReadRange(uint64_t offset,
uint64_t length,
mojo::ScopedDataPipeProducerHandle,
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 12e2eb64766..d70a550fff1 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
@@ -23,17 +23,17 @@ 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(nullptr);
+ std::move(callback).Run(mojo::NullRemote());
return;
}
- mojom::blink::BlobPtr blob;
- it->value->Clone(MakeRequest(&blob));
+ mojo::PendingRemote<mojom::blink::Blob> blob;
+ it->value->Clone(blob.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(blob));
}
void FakeBlobURLStore::ResolveAsURLLoaderFactory(
const KURL&,
- network::mojom::blink::URLLoaderFactoryRequest) {
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>) {
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 f26a0a5c184..79e62acb098 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 "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
@@ -25,7 +26,7 @@ class FakeBlobURLStore : public mojom::blink::BlobURLStore {
void Resolve(const KURL&, ResolveCallback) override;
void ResolveAsURLLoaderFactory(
const KURL&,
- network::mojom::blink::URLLoaderFactoryRequest) override;
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderFactory>) override;
void ResolveForNavigation(
const KURL&,
mojo::PendingReceiver<mojom::blink::BlobURLToken>) override;
diff --git a/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h b/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
index 620f8393474..d9d00569546 100644
--- a/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
+++ b/chromium/third_party/blink/renderer/platform/content_decryption_module_result.h
@@ -17,7 +17,7 @@ class WebString;
// Used to notify completion of a CDM operation.
class ContentDecryptionModuleResult
- : public GarbageCollectedFinalized<ContentDecryptionModuleResult> {
+ : public GarbageCollected<ContentDecryptionModuleResult> {
public:
virtual ~ContentDecryptionModuleResult() = default;
diff --git a/chromium/third_party/blink/renderer/platform/crypto_result.h b/chromium/third_party/blink/renderer/platform/crypto_result.h
index bd3860815c7..2fc6b5aa1ee 100644
--- a/chromium/third_party/blink/renderer/platform/crypto_result.h
+++ b/chromium/third_party/blink/renderer/platform/crypto_result.h
@@ -49,8 +49,7 @@ class CryptoResultCancel : public ThreadSafeRefCounted<CryptoResultCancel> {
};
// Receives notification of completion of the crypto operation.
-class PLATFORM_EXPORT CryptoResult
- : public GarbageCollectedFinalized<CryptoResult> {
+class PLATFORM_EXPORT CryptoResult : public GarbageCollected<CryptoResult> {
public:
virtual ~CryptoResult() = default;
diff --git a/chromium/third_party/blink/renderer/platform/encrypted_media_request.h b/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
index 143f47c6767..25770c1e020 100644
--- a/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
+++ b/chromium/third_party/blink/renderer/platform/encrypted_media_request.h
@@ -18,8 +18,7 @@ class WebString;
template <typename T>
class WebVector;
-class EncryptedMediaRequest
- : public GarbageCollectedFinalized<EncryptedMediaRequest> {
+class EncryptedMediaRequest : public GarbageCollected<EncryptedMediaRequest> {
public:
virtual ~EncryptedMediaRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/exported/page_zoom_test.cc b/chromium/third_party/blink/renderer/platform/exported/page_zoom_test.cc
new file mode 100644
index 00000000000..f65c533139e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/page_zoom_test.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/page/page_zoom.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(PageZoomTest, ZoomValuesEqual) {
+ // Test two identical values.
+ EXPECT_TRUE(blink::PageZoomValuesEqual(1.5, 1.5));
+
+ // Test two values that are close enough to be considered equal.
+ EXPECT_TRUE(blink::PageZoomValuesEqual(1.5, 1.49999999));
+
+ // Test two values that are close, but should not be considered equal.
+ EXPECT_FALSE(blink::PageZoomValuesEqual(1.5, 1.4));
+}
diff --git a/chromium/third_party/blink/renderer/platform/exported/platform.cc b/chromium/third_party/blink/renderer/platform/exported/platform.cc
index 06e65023d0b..ff12a36a135 100644
--- a/chromium/third_party/blink/renderer/platform/exported/platform.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/platform.cc
@@ -44,7 +44,6 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/public/platform/web_prerendering_support.h"
-#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
@@ -223,11 +222,11 @@ void Platform::InitializeCommon(Platform* platform,
Thread::SetMainThread(std::move(main_thread));
ProcessHeap::Init();
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- BlinkGCMemoryDumpProvider::Instance(), "BlinkGC",
- base::ThreadTaskRunnerHandle::Get());
- ThreadState::AttachMainThread();
+ ThreadState* thread_state = ThreadState::AttachMainThread();
+ new BlinkGCMemoryDumpProvider(
+ thread_state, base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkMainThread);
MemoryPressureListenerRegistry::Initialize();
@@ -353,19 +352,4 @@ Platform::CreateWebRtcAsyncResolverFactory() {
return nullptr;
}
-std::unique_ptr<WebRTCCertificateGenerator>
-Platform::CreateRTCCertificateGenerator() {
- return nullptr;
-}
-
-std::unique_ptr<webrtc::RtpCapabilities> Platform::GetRtpSenderCapabilities(
- const WebString& kind) {
- return nullptr;
-}
-
-std::unique_ptr<webrtc::RtpCapabilities> Platform::GetRtpReceiverCapabilities(
- const WebString& kind) {
- return nullptr;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/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 c1cfe77562d..ebf7dcdbc61 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
@@ -16,7 +16,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/video_capture/web_video_capture_impl_manager.h"
-#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h"
#include "third_party/blink/renderer/platform/video_capture/video_capture_impl.h"
using media::BindToCurrentLoop;
@@ -61,7 +61,8 @@ class MockVideoCaptureImpl : public VideoCaptureImpl,
void Start(const base::UnguessableToken& device_id,
const base::UnguessableToken& session_id,
const media::VideoCaptureParams& params,
- media::mojom::blink::VideoCaptureObserverPtr observer) override {
+ mojo::PendingRemote<media::mojom::blink::VideoCaptureObserver>
+ observer) override {
// For every Start(), expect a corresponding Stop() call.
EXPECT_CALL(*this, Stop(_));
// Simulate device started.
@@ -222,7 +223,8 @@ class VideoCaptureImplManagerTest : public ::testing::Test,
}
base::test::TaskEnvironment task_environment_;
- ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+ ScopedTestingPlatformSupport<TestingPlatformSupportForGpuMemoryBuffer>
+ platform_;
base::RunLoop cleanup_run_loop_;
std::unique_ptr<MockVideoCaptureImplManager> manager_;
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
index 79fee2d6201..9496a7da67d 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_blob_info.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/public/platform/web_blob_info.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -13,12 +14,13 @@ WebBlobInfo::WebBlobInfo(const WebString& uuid,
const WebString& type,
uint64_t size,
mojo::ScopedMessagePipeHandle handle)
- : WebBlobInfo(BlobDataHandle::Create(
- uuid,
- type,
- size,
- mojom::blink::BlobPtrInfo(std::move(handle),
- mojom::blink::Blob::Version_))) {}
+ : WebBlobInfo(
+ BlobDataHandle::Create(uuid,
+ type,
+ size,
+ mojo::PendingRemote<mojom::blink::Blob>(
+ std::move(handle),
+ mojom::blink::Blob::Version_))) {}
WebBlobInfo::WebBlobInfo(const WebString& uuid,
const WebString& file_path,
@@ -27,15 +29,16 @@ WebBlobInfo::WebBlobInfo(const WebString& uuid,
double last_modified,
uint64_t size,
mojo::ScopedMessagePipeHandle handle)
- : WebBlobInfo(BlobDataHandle::Create(
- uuid,
- type,
- size,
- mojom::blink::BlobPtrInfo(std::move(handle),
- mojom::blink::Blob::Version_)),
- file_path,
- file_name,
- last_modified) {}
+ : WebBlobInfo(
+ BlobDataHandle::Create(uuid,
+ type,
+ size,
+ mojo::PendingRemote<mojom::blink::Blob>(
+ std::move(handle),
+ mojom::blink::Blob::Version_)),
+ file_path,
+ file_name,
+ last_modified) {}
// static
WebBlobInfo WebBlobInfo::BlobForTesting(const WebString& uuid,
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_cache.cc b/chromium/third_party/blink/renderer/platform/exported/web_cache.cc
index 6cf1ea0f1d5..035f3e21ffd 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_cache.cc
@@ -35,9 +35,9 @@
namespace blink {
// A helper method for coverting a MemoryCache::TypeStatistic to a
-// WebCache::ResourceTypeStat.
+// WebCacheResourceTypeStat.
static void ToResourceTypeStat(const MemoryCache::TypeStatistic& from,
- WebCache::ResourceTypeStat& to) {
+ WebCacheResourceTypeStat& to) {
to.count = from.count;
to.size = from.size;
to.decoded_size = from.decoded_size;
@@ -67,7 +67,7 @@ void WebCache::GetUsageStats(UsageStats* result) {
}
}
-void WebCache::GetResourceTypeStats(ResourceTypeStats* result) {
+void WebCache::GetResourceTypeStats(WebCacheResourceTypeStats* result) {
MemoryCache* cache = GetMemoryCache();
if (cache) {
MemoryCache::Statistics stats = cache->GetStatistics();
@@ -78,7 +78,7 @@ void WebCache::GetResourceTypeStats(ResourceTypeStats* result) {
ToResourceTypeStat(stats.fonts, result->fonts);
ToResourceTypeStat(stats.other, result->other);
} else {
- memset(result, 0, sizeof(WebCache::ResourceTypeStats));
+ memset(result, 0, sizeof(WebCacheResourceTypeStats));
}
}
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 a0a12cfd2d1..f56eb5dac95 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
@@ -30,9 +30,11 @@
#include "third_party/blink/public/platform/web_http_body.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/form_data_encoder.h"
@@ -97,10 +99,11 @@ bool WebHTTPBody::ElementAt(size_t index, Element& result) const {
break;
case FormDataElement::kDataPipe:
result.type = Element::kTypeDataPipe;
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- (*element.data_pipe_getter_->GetPtr())
- ->Clone(mojo::MakeRequest(&data_pipe_getter));
- result.data_pipe_getter = data_pipe_getter.PassInterface().PassHandle();
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter;
+ element.data_pipe_getter_->GetDataPipeGetter()->Clone(
+ data_pipe_getter.InitWithNewPipeAndPassReceiver());
+ result.data_pipe_getter = data_pipe_getter.PassPipe();
break;
}
@@ -141,20 +144,20 @@ void WebHTTPBody::AppendBlob(const WebString& uuid,
uint64_t length,
mojo::ScopedMessagePipeHandle blob_handle) {
EnsureMutable();
- mojom::blink::BlobPtrInfo blob_ptr_info(std::move(blob_handle),
- mojom::blink::Blob::Version_);
+ mojo::PendingRemote<mojom::blink::Blob> blob_remote(
+ std::move(blob_handle), mojom::blink::Blob::Version_);
private_->AppendBlob(
uuid, BlobDataHandle::Create(uuid, "" /* type is not necessary */, length,
- std::move(blob_ptr_info)));
+ std::move(blob_remote)));
}
void WebHTTPBody::AppendDataPipe(mojo::ScopedMessagePipeHandle message_pipe) {
EnsureMutable();
- // Convert the raw message pipe to network::mojom::blink::DataPipeGetter.
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- data_pipe_getter.Bind(network::mojom::blink::DataPipeGetterPtrInfo(
- std::move(message_pipe), 0u));
+ // Convert the raw message pipe to
+ // mojo::Remote<network::mojom::blink::DataPipeGetter>.
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter> data_pipe_getter(
+ std::move(message_pipe), 0u);
auto wrapped =
base::MakeRefCounted<WrappedDataPipeGetter>(std::move(data_pipe_getter));
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
index 308b2cfe057..9d1960e18cf 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_icon_sizes_parser.cc
@@ -65,7 +65,7 @@ WebVector<WebSize> WebIconSizesParser::ParseIconSizes(
break;
// See if the current size is "any".
- if (sizes_string.FindIgnoringCase("any", i) == i &&
+ if (sizes_string.Substring(i, 3).StartsWithIgnoringCase("any") &&
(i + 3 == length || IsWhitespace(sizes_string[i + 3]))) {
icon_sizes.push_back(WebSize(0, 0));
i = i + 3;
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_mixed_content.cc b/chromium/third_party/blink/renderer/platform/exported/web_mixed_content.cc
index 858cad7d029..6b8f43b7f69 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_mixed_content.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_mixed_content.cc
@@ -30,6 +30,8 @@
#include "third_party/blink/public/platform/web_mixed_content.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+
namespace blink {
// static
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 fc2aecbe27e..bbeca4e606c 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
@@ -64,6 +64,14 @@ void WebRuntimeFeatures::EnableFeatureFromString(const std::string& name,
RuntimeEnabledFeatures::SetFeatureEnabledFromString(name, enable);
}
+void WebRuntimeFeatures::EnableForcedColors(bool enable) {
+ RuntimeEnabledFeatures::SetForcedColorsEnabled(enable);
+}
+
+bool WebRuntimeFeatures::IsForcedColorsEnabled() {
+ return RuntimeEnabledFeatures::ForcedColorsEnabled();
+}
+
void WebRuntimeFeatures::EnableFractionalScrollOffsets(bool enable) {
RuntimeEnabledFeatures::SetFractionalScrollOffsetsEnabled(enable);
}
@@ -88,6 +96,14 @@ void WebRuntimeFeatures::EnableAccelerated2dCanvas(bool enable) {
RuntimeEnabledFeatures::SetAccelerated2dCanvasEnabled(enable);
}
+void WebRuntimeFeatures::EnableAccessibilityExposeARIAAnnotations(bool enable) {
+ RuntimeEnabledFeatures::SetAccessibilityExposeARIAAnnotationsEnabled(enable);
+}
+
+void WebRuntimeFeatures::EnableAccessibilityExposeDisplayNone(bool enable) {
+ RuntimeEnabledFeatures::SetAccessibilityExposeDisplayNoneEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableAccessibilityObjectModel(bool enable) {
RuntimeEnabledFeatures::SetAccessibilityObjectModelEnabled(enable);
}
@@ -132,10 +148,6 @@ void WebRuntimeFeatures::EnableCanvas2dImageChromium(bool enable) {
RuntimeEnabledFeatures::SetCanvas2dImageChromiumEnabled(enable);
}
-void WebRuntimeFeatures::EnableCanvas2dSwapChain(bool enable) {
- RuntimeEnabledFeatures::SetCanvas2dSwapChainEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableCompositedSelectionUpdate(bool enable) {
RuntimeEnabledFeatures::SetCompositedSelectionUpdateEnabled(enable);
}
@@ -192,10 +204,6 @@ void WebRuntimeFeatures::EnableFileSystem(bool enable) {
RuntimeEnabledFeatures::SetFileSystemEnabled(enable);
}
-void WebRuntimeFeatures::EnableFirstContentfulPaintPlusPlus(bool enable) {
- RuntimeEnabledFeatures::SetFirstContentfulPaintPlusPlusEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableForceSynchronousHTMLParsing(bool enable) {
RuntimeEnabledFeatures::SetForceSynchronousHTMLParsingEnabled(enable);
}
@@ -216,12 +224,12 @@ void WebRuntimeFeatures::EnableImplicitRootScroller(bool enable) {
RuntimeEnabledFeatures::SetImplicitRootScrollerEnabled(enable);
}
-void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) {
- RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable);
+void WebRuntimeFeatures::EnableCSSOMViewScrollCoordinates(bool enable) {
+ RuntimeEnabledFeatures::SetCSSOMViewScrollCoordinatesEnabled(enable);
}
-void WebRuntimeFeatures::EnableJankTrackingSweepLine(bool enable) {
- RuntimeEnabledFeatures::SetJankTrackingSweepLineEnabled(enable);
+void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) {
+ RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable);
}
void WebRuntimeFeatures::EnableBuiltInModuleAll(bool enable) {
@@ -361,10 +369,6 @@ void WebRuntimeFeatures::EnablePortals(bool enable) {
RuntimeEnabledFeatures::SetPortalsEnabled(enable);
}
-void WebRuntimeFeatures::EnableRasterInducingScroll(bool enable) {
- RuntimeEnabledFeatures::SetRasterInducingScrollEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableScriptedSpeechRecognition(bool enable) {
RuntimeEnabledFeatures::SetScriptedSpeechRecognitionEnabled(enable);
}
@@ -405,10 +409,6 @@ void WebRuntimeFeatures::EnableWebGLImageChromium(bool enable) {
RuntimeEnabledFeatures::SetWebGLImageChromiumEnabled(enable);
}
-void WebRuntimeFeatures::EnableWebGLSwapChain(bool enable) {
- RuntimeEnabledFeatures::SetWebGLSwapChainEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableXSLT(bool enable) {
RuntimeEnabledFeatures::SetXSLTEnabled(enable);
}
@@ -477,10 +477,18 @@ void WebRuntimeFeatures::EnableWebXRARModule(bool enable) {
RuntimeEnabledFeatures::SetWebXRARModuleEnabled(enable);
}
+void WebRuntimeFeatures::EnableWebXRARDOMOverlay(bool enable) {
+ RuntimeEnabledFeatures::SetWebXRARDOMOverlayEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableWebXRAnchors(bool enable) {
RuntimeEnabledFeatures::SetWebXRAnchorsEnabled(enable);
}
+void WebRuntimeFeatures::EnableWebXrGamepadModule(bool enable) {
+ RuntimeEnabledFeatures::SetWebXrGamepadModuleEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableWebXRHitTest(bool enable) {
RuntimeEnabledFeatures::SetWebXRHitTestEnabled(enable);
}
@@ -493,10 +501,6 @@ void WebRuntimeFeatures::EnablePresentationAPI(bool enable) {
RuntimeEnabledFeatures::SetPresentationEnabled(enable);
}
-void WebRuntimeFeatures::EnableResourceLoadScheduler(bool enable) {
- RuntimeEnabledFeatures::SetResourceLoadSchedulerEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableRestrictAutomaticLazyFrameLoadingToDataSaver(
bool enable) {
RuntimeEnabledFeatures::
@@ -521,10 +525,6 @@ void WebRuntimeFeatures::EnableExpensiveBackgroundTimerThrottling(bool enable) {
RuntimeEnabledFeatures::SetExpensiveBackgroundTimerThrottlingEnabled(enable);
}
-void WebRuntimeFeatures::EnableScrollAnchorSerialization(bool enable) {
- RuntimeEnabledFeatures::SetScrollAnchorSerializationEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableFetchMetadata(bool enable) {
RuntimeEnabledFeatures::SetFetchMetadataEnabled(enable);
}
@@ -583,10 +583,6 @@ void WebRuntimeFeatures::EnableWebAuth(bool enable) {
RuntimeEnabledFeatures::SetWebAuthEnabled(enable);
}
-void WebRuntimeFeatures::EnableClientPlaceholdersForServerLoFi(bool enable) {
- RuntimeEnabledFeatures::SetClientPlaceholdersForServerLoFiEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableLazyInitializeMediaControls(bool enable) {
RuntimeEnabledFeatures::SetLazyInitializeMediaControlsEnabled(enable);
}
@@ -676,10 +672,6 @@ void WebRuntimeFeatures::EnableSkipTouchEventFilter(bool enable) {
RuntimeEnabledFeatures::SetSkipTouchEventFilterEnabled(enable);
}
-void WebRuntimeFeatures::EnableStaleWhileRevalidate(bool enable) {
- RuntimeEnabledFeatures::SetStaleWhileRevalidateEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableSmsReceiver(bool enable) {
RuntimeEnabledFeatures::SetSmsReceiverEnabled(enable);
}
@@ -688,12 +680,6 @@ void WebRuntimeFeatures::EnableDisplayLocking(bool enable) {
RuntimeEnabledFeatures::SetDisplayLockingEnabled(enable);
}
-void WebRuntimeFeatures::EnablePauseExecutionContextOnBackgroundFreeze(
- bool enable) {
- RuntimeEnabledFeatures::SetPauseExecutionContextOnBackgroundFreezeEnabled(
- enable);
-}
-
void WebRuntimeFeatures::EnableConsolidatedMovementXY(bool enable) {
RuntimeEnabledFeatures::SetConsolidatedMovementXYEnabled(enable);
}
@@ -702,10 +688,6 @@ void WebRuntimeFeatures::EnableCooperativeScheduling(bool enable) {
RuntimeEnabledFeatures::SetCooperativeSchedulingEnabled(enable);
}
-void WebRuntimeFeatures::EnableStreamsNative(bool enable) {
- RuntimeEnabledFeatures::SetStreamsNativeEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableMouseSubframeNoImplicitCapture(bool enable) {
RuntimeEnabledFeatures::SetMouseSubframeNoImplicitCaptureEnabled(enable);
}
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 71d4c079f7a..fbe4828fcca 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_string.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_string.cc
@@ -51,9 +51,9 @@ namespace blink {
WebString::~WebString() = default;
WebString::WebString() = default;
WebString::WebString(const WebString&) = default;
-WebString::WebString(WebString&&) noexcept = default;
+WebString::WebString(WebString&&) = default;
WebString& WebString::operator=(const WebString&) = default;
-WebString& WebString::operator=(WebString&&) noexcept = default;
+WebString& WebString::operator=(WebString&&) = default;
WebString::WebString(const WebUChar* data, size_t len)
: impl_(StringImpl::Create8BitIfPossible(data, len)) {}
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 cb48f88fca6..7caaaf10b1b 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
@@ -42,6 +42,7 @@
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -49,6 +50,8 @@ using blink::mojom::FetchCacheMode;
namespace blink {
+WebURLRequest::ExtraData::ExtraData() : render_frame_id_(MSG_ROUTING_NONE) {}
+
// The purpose of this struct is to permit allocating a ResourceRequest on the
// heap, which is otherwise disallowed by DISALLOW_NEW annotation on
// ResourceRequest.
@@ -120,6 +123,10 @@ WebSecurityOrigin WebURLRequest::RequestorOrigin() const {
return resource_request_->RequestorOrigin();
}
+WebSecurityOrigin WebURLRequest::IsolatedWorldOrigin() const {
+ return resource_request_->IsolatedWorldOrigin();
+}
+
void WebURLRequest::SetRequestorOrigin(
const WebSecurityOrigin& requestor_origin) {
resource_request_->SetRequestorOrigin(requestor_origin);
@@ -391,10 +398,6 @@ bool WebURLRequest::IsRevalidating() const {
return resource_request_->IsRevalidating();
}
-bool WebURLRequest::ShouldAlsoUseFactoryBoundOriginForCors() const {
- return resource_request_->ShouldAlsoUseFactoryBoundOriginForCors();
-}
-
const base::Optional<base::UnguessableToken>& WebURLRequest::GetDevToolsToken()
const {
return resource_request_->GetDevToolsToken();
@@ -496,6 +499,11 @@ bool WebURLRequest::IsSignedExchangePrefetchCacheEnabled() const {
return resource_request_->IsSignedExchangePrefetchCacheEnabled();
}
+base::Optional<base::UnguessableToken> WebURLRequest::RecursivePrefetchToken()
+ const {
+ return resource_request_->RecursivePrefetchToken();
+}
+
WebURLRequest::WebURLRequest(ResourceRequest& r) : resource_request_(&r) {}
} // namespace blink
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 9157f3948e9..e8eca6afa73 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
@@ -41,6 +41,7 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_load_timing.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -243,7 +244,7 @@ void WebURLResponse::SetIsLegacyTLSVersion(bool value) {
resource_response_->SetIsLegacyTLSVersion(value);
}
-void WebURLResponse::SetSecurityStyle(WebSecurityStyle security_style) {
+void WebURLResponse::SetSecurityStyle(SecurityStyle security_style) {
resource_response_->SetSecurityStyle(security_style);
}
@@ -302,6 +303,10 @@ void WebURLResponse::SetWasCached(bool value) {
resource_response_->SetWasCached(value);
}
+bool WebURLResponse::WasFetchedViaSPDY() const {
+ return resource_response_->WasFetchedViaSPDY();
+}
+
void WebURLResponse::SetWasFetchedViaSPDY(bool value) {
resource_response_->SetWasFetchedViaSPDY(value);
}
@@ -399,6 +404,19 @@ void WebURLResponse::SetWasInPrefetchCache(bool was_in_prefetch_cache) {
resource_response_->SetWasInPrefetchCache(was_in_prefetch_cache);
}
+void WebURLResponse::SetRecursivePrefetchToken(
+ const base::Optional<base::UnguessableToken>& token) {
+ resource_response_->SetRecursivePrefetchToken(token);
+}
+
+bool WebURLResponse::WasAlpnNegotiated() const {
+ return resource_response_->WasAlpnNegotiated();
+}
+
+void WebURLResponse::SetWasAlpnNegotiated(bool was_alpn_negotiated) {
+ resource_response_->SetWasAlpnNegotiated(was_alpn_negotiated);
+}
+
WebString WebURLResponse::AlpnNegotiatedProtocol() const {
return resource_response_->AlpnNegotiatedProtocol();
}
@@ -408,6 +426,16 @@ void WebURLResponse::SetAlpnNegotiatedProtocol(
resource_response_->SetAlpnNegotiatedProtocol(alpn_negotiated_protocol);
}
+bool WebURLResponse::WasAlternateProtocolAvailable() const {
+ return resource_response_->WasAlternateProtocolAvailable();
+}
+
+void WebURLResponse::SetWasAlternateProtocolAvailable(
+ bool was_alternate_protocol_available) {
+ resource_response_->SetWasAlternateProtocolAvailable(
+ was_alternate_protocol_available);
+}
+
net::HttpResponseInfo::ConnectionInfo WebURLResponse::ConnectionInfo() const {
return resource_response_->ConnectionInfo();
}
diff --git a/chromium/third_party/blink/renderer/platform/file_metadata.cc b/chromium/third_party/blink/renderer/platform/file_metadata.cc
index 1bf6c960867..e3c075c047b 100644
--- a/chromium/third_party/blink/renderer/platform/file_metadata.cc
+++ b/chromium/third_party/blink/renderer/platform/file_metadata.cc
@@ -30,7 +30,11 @@
#include "third_party/blink/renderer/platform/file_metadata.h"
+#include <limits>
+#include <string>
+
#include "base/optional.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/filename_util.h"
#include "third_party/blink/public/mojom/file/file_utilities.mojom-blink.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
@@ -75,12 +79,12 @@ bool GetFileModificationTime(const String& path, double& result) {
bool GetFileMetadata(const String& path, FileMetadata& metadata) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
- ThreadSpecific<mojom::blink::FileUtilitiesHostPtr>, thread_specific_host,
- ());
+ ThreadSpecific<mojo::Remote<mojom::blink::FileUtilitiesHost>>,
+ thread_specific_host, ());
auto& host = *thread_specific_host;
if (!host) {
Platform::Current()->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&host));
+ host.BindNewPipeAndPassReceiver());
}
base::Optional<base::File::Info> file_info;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.cc b/chromium/third_party/blink/renderer/platform/fonts/font.cc
index cf30e88b6ac..4fc2c843e14 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.cc
@@ -550,6 +550,24 @@ void Font::ExpandRangeToIncludePartialGlyphs(const TextRun& text_run,
buffer.ExpandRangeToIncludePartialGlyphs(from, to);
}
+float Font::TabWidth(const SimpleFontData* font_data,
+ const TabSize& tab_size,
+ float position) const {
+ float base_tab_width = TabWidth(font_data, tab_size);
+ if (!base_tab_width)
+ return GetFontDescription().LetterSpacing();
+
+ float distance_to_tab_stop = base_tab_width - fmodf(position, base_tab_width);
+
+ // Let the minimum width be the half of the space width so that it's always
+ // recognizable. if the distance to the next tab stop is less than that,
+ // advance an additional tab stop.
+ if (distance_to_tab_stop < font_data->SpaceWidth() / 2)
+ distance_to_tab_stop += base_tab_width;
+
+ return distance_to_tab_stop;
+}
+
LayoutUnit Font::TabWidth(const TabSize& tab_size, LayoutUnit position) const {
const SimpleFontData* font_data = PrimaryFont();
if (!font_data)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.h b/chromium/third_party/blink/renderer/platform/fonts/font.h
index 504e9267416..d13cb218a04 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.h
@@ -276,21 +276,6 @@ inline float Font::TabWidth(const SimpleFontData* font_data,
return base_tab_width ? base_tab_width : GetFontDescription().LetterSpacing();
}
-inline float Font::TabWidth(const SimpleFontData* font_data,
- const TabSize& tab_size,
- float position) const {
- float base_tab_width = TabWidth(font_data, tab_size);
- float distance_to_tab_stop = base_tab_width - fmodf(position, base_tab_width);
-
- // Let the minimum width be the half of the space width so that it's always
- // recognizable. if the distance to the next tab stop is less than that,
- // advance an additional tab stop.
- if (distance_to_tab_stop < font_data->SpaceWidth() / 2)
- distance_to_tab_stop += base_tab_width;
-
- return distance_to_tab_stop;
-}
-
} // namespace blink
#endif
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 acba677e52c..4025c77b42a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -31,10 +31,13 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
#include <limits.h>
+
#include <memory>
+#include <string>
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/renderer/platform/fonts/fallback_list_composite_key.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_client.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
@@ -57,6 +60,7 @@
#if defined(OS_WIN)
#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
+#include "third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h"
#endif
class SkString;
@@ -352,7 +356,8 @@ class PLATFORM_EXPORT FontCache {
// Windows creates an SkFontMgr for unit testing automatically. This flag is
// to ensure it's not happening in the production from the crash log.
bool is_test_font_mgr_ = false;
- mojom::blink::DWriteFontProxyPtr service_;
+ mojo::Remote<mojom::blink::DWriteFontProxy> service_;
+ std::unique_ptr<FallbackFamilyStyleCache> fallback_params_cache_;
#endif // defined(OS_WIN)
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
@@ -399,4 +404,4 @@ AtomicString ToAtomicString(const SkString&);
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
index d56df8c0c03..2160fcb2c3b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_client.h
@@ -37,7 +37,7 @@
namespace blink {
class PLATFORM_EXPORT FontCacheClient
- : public GarbageCollectedFinalized<FontCacheClient> {
+ : public GarbageCollected<FontCacheClient> {
public:
virtual ~FontCacheClient() = default;
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 790da169577..ecc8454ff02 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
@@ -67,6 +67,7 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData(
bool italic,
const FontSelectionRequest& selection_request,
const FontSelectionCapabilities& selection_capabilities,
+ const OpticalSizing& optical_sizing,
FontOrientation orientation,
const FontVariationSettings* variation_settings) {
DCHECK(base_typeface_);
@@ -105,15 +106,24 @@ FontPlatformData FontCustomPlatformData::GetFontPlatformData(
axes.push_back(width_axis);
axes.push_back(slant_axis);
+ bool explicit_opsz_configured = false;
if (variation_settings && variation_settings->size() < UINT16_MAX) {
axes.ReserveCapacity(variation_settings->size() + axes.size());
for (const auto& setting : *variation_settings) {
+ if (setting.Tag() == AtomicString("opsz"))
+ explicit_opsz_configured = true;
SkFontArguments::Axis axis = {AtomicStringToFourByteTag(setting.Tag()),
SkFloatToScalar(setting.Value())};
axes.push_back(axis);
}
}
+ if (optical_sizing == kAutoOpticalSizing && !explicit_opsz_configured) {
+ SkFontArguments::Axis opsz_axis = {SkSetFourByteTag('o', 'p', 's', 'z'),
+ SkFloatToScalar(size)};
+ axes.push_back(opsz_axis);
+ }
+
int index;
std::unique_ptr<SkStreamAsset> stream(base_typeface_->openStream(&index));
sk_sp<SkTypeface> sk_variation_font(FontManagerForSubType(font_sub_type)
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 bf02f747494..7b129c1acfc 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
@@ -33,6 +33,7 @@
#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"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -64,6 +65,7 @@ class PLATFORM_EXPORT FontCustomPlatformData
bool italic,
const FontSelectionRequest&,
const FontSelectionCapabilities&,
+ const OpticalSizing& optical_sizing,
FontOrientation = FontOrientation::kHorizontal,
const FontVariationSettings* = nullptr);
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 24e8e83d474..6f20525f341 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -93,6 +93,7 @@ FontDescription::FontDescription()
fields_.typesetting_features_ = default_typesetting_features_;
fields_.variant_numeric_ = FontVariantNumeric().fields_as_unsigned_;
fields_.subpixel_ascent_descent_ = false;
+ fields_.font_optical_sizing_ = OpticalSizing::kAutoOpticalSizing;
}
FontDescription::FontDescription(const FontDescription&) = default;
@@ -217,11 +218,12 @@ FontCacheKey FontDescription::CacheKey(
bool is_unique_match,
const FontSelectionRequest& font_selection_request) const {
unsigned options =
- static_cast<unsigned>(fields_.synthetic_italic_) << 6 | // bit 7
- static_cast<unsigned>(fields_.synthetic_bold_) << 5 | // bit 6
- static_cast<unsigned>(fields_.text_rendering_) << 3 | // bits 4-5
- static_cast<unsigned>(fields_.orientation_) << 1 | // bit 2-3
- static_cast<unsigned>(fields_.subpixel_text_position_); // bit 1
+ static_cast<unsigned>(fields_.font_optical_sizing_) << 7 | // bit 8
+ static_cast<unsigned>(fields_.synthetic_italic_) << 6 | // bit 7
+ static_cast<unsigned>(fields_.synthetic_bold_) << 5 | // bit 6
+ static_cast<unsigned>(fields_.text_rendering_) << 3 | // bits 4-5
+ static_cast<unsigned>(fields_.orientation_) << 1 | // bit 2-3
+ static_cast<unsigned>(fields_.subpixel_text_position_); // bit 1
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
float device_scale_factor_for_key = FontCache::DeviceScaleFactor();
@@ -229,7 +231,7 @@ FontCacheKey FontDescription::CacheKey(
float device_scale_factor_for_key = 1.0f;
#endif
FontCacheKey cache_key(creation_params, EffectiveFontSize(),
- options | font_selection_request_.GetHash() << 8,
+ options | font_selection_request_.GetHash() << 9,
device_scale_factor_for_key, variation_settings_,
is_unique_match);
return cache_key;
@@ -371,6 +373,42 @@ SkFontStyle FontDescription::SkiaFontStyle() const {
return SkFontStyle(skia_weight, skia_width, slant);
}
+void FontDescription::UpdateFromSkiaFontStyle(const SkFontStyle& font_style) {
+ SetWeight(FontSelectionValue(font_style.weight()));
+
+ switch (font_style.width()) {
+ case (SkFontStyle::kUltraCondensed_Width):
+ SetStretch(UltraCondensedWidthValue());
+ break;
+ case (SkFontStyle::kExtraCondensed_Width):
+ SetStretch(ExtraCondensedWidthValue());
+ break;
+ case (SkFontStyle::kCondensed_Width):
+ SetStretch(CondensedWidthValue());
+ break;
+ case (SkFontStyle::kSemiCondensed_Width):
+ SetStretch(SemiCondensedWidthValue());
+ break;
+ case (SkFontStyle::kSemiExpanded_Width):
+ SetStretch(SemiExpandedWidthValue());
+ break;
+ case (SkFontStyle::kExpanded_Width):
+ SetStretch(ExpandedWidthValue());
+ break;
+ case (SkFontStyle::kExtraExpanded_Width):
+ SetStretch(ExtraExpandedWidthValue());
+ break;
+ case (SkFontStyle::kUltraExpanded_Width):
+ SetStretch(UltraExpandedWidthValue());
+ break;
+ }
+
+ if (font_style.slant() == SkFontStyle::kOblique_Slant)
+ SetStyle(ItalicSlopeValue());
+ else
+ SetStyle(NormalSlopeValue());
+}
+
int FontDescription::MinimumPrefixWidthToHyphenate() const {
// If the maximum width available for the prefix before the hyphen is small,
// then it is very unlikely that an hyphenation opportunity exists, so do not
@@ -496,7 +534,7 @@ String FontDescription::ToString() const {
"keyword_size=%u, font_smoothing=%s, text_rendering=%s, "
"synthetic_bold=%s, synthetic_italic=%s, subpixel_positioning=%s, "
"subpixel_ascent_descent=%s, variant_numeric=[%s], "
- "variant_east_asian=[%s]",
+ "variant_east_asian=[%s], font_optical_sizing=%s",
family_list_.ToString().Ascii().c_str(),
(feature_settings_ ? feature_settings_->ToString().Ascii().c_str() : ""),
(variation_settings_ ? variation_settings_->ToString().Ascii().c_str()
@@ -524,7 +562,8 @@ String FontDescription::ToString() const {
ToBooleanString(UseSubpixelPositioning()),
ToBooleanString(SubpixelAscentDescent()),
VariantNumeric().ToString().Ascii().c_str(),
- VariantEastAsian().ToString().Ascii().c_str());
+ VariantEastAsian().ToString().Ascii().c_str(),
+ blink::ToString(FontOpticalSizing()).Ascii().c_str());
}
} // namespace blink
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 5306455422f..8d19bd6873c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
#include "third_party/blink/renderer/platform/fonts/font_family.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"
#include "third_party/blink/renderer/platform/fonts/font_smoothing_mode.h"
@@ -206,6 +207,9 @@ class PLATFORM_EXPORT FontDescription {
FontSmoothingMode FontSmoothing() const {
return static_cast<FontSmoothingMode>(fields_.font_smoothing_);
}
+ OpticalSizing FontOpticalSizing() const {
+ return static_cast<OpticalSizing>(fields_.font_optical_sizing_);
+ }
TextRenderingMode TextRendering() const {
return static_cast<TextRenderingMode>(fields_.text_rendering_);
}
@@ -282,6 +286,9 @@ class PLATFORM_EXPORT FontDescription {
void SetFontSmoothing(FontSmoothingMode smoothing) {
fields_.font_smoothing_ = smoothing;
}
+ void SetFontOpticalSizing(OpticalSizing font_optical_sizing) {
+ fields_.font_optical_sizing_ = font_optical_sizing;
+ }
void SetTextRendering(TextRenderingMode rendering) {
fields_.text_rendering_ = rendering;
UpdateTypesettingFeatures();
@@ -343,6 +350,8 @@ class PLATFORM_EXPORT FontDescription {
SkFontStyle SkiaFontStyle() const;
+ void UpdateFromSkiaFontStyle(const SkFontStyle& font_style);
+
int MinimumPrefixWidthToHyphenate() const;
String ToString() const;
@@ -413,6 +422,7 @@ class PLATFORM_EXPORT FontDescription {
unsigned variant_numeric_ : 8;
unsigned variant_east_asian_ : 6;
mutable unsigned subpixel_ascent_descent_ : 1;
+ unsigned font_optical_sizing_ : 1;
};
static_assert(sizeof(BitFields) == sizeof(FieldsAsUnsignedType),
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 c5935c6bfb4..737580ef6bf 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
@@ -116,7 +116,7 @@ TEST(FontDescriptionTest, ToString) {
"variant_numeric=[numeric_figure=NormalFigure, "
"numeric_spacing=NormalSpacing, numeric_fraction=Normal, ordinal=Off, "
"slashed_zero=Off], variant_east_asian=[form=Normal, width=Normal, "
- "ruby=false]",
+ "ruby=false], font_optical_sizing=Auto",
description.ToString());
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.cc b/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.cc
new file mode 100644
index 00000000000..b912bfa2617
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.cc
@@ -0,0 +1,19 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/font_optical_sizing.h"
+
+namespace blink {
+
+String ToString(OpticalSizing font_optical_sizing) {
+ switch (font_optical_sizing) {
+ case OpticalSizing::kAutoOpticalSizing:
+ return "Auto";
+ case OpticalSizing::kNoneOpticalSizing:
+ return "None";
+ }
+ return "Unknown";
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.h b/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.h
new file mode 100644
index 00000000000..bd18e89ff8d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_optical_sizing.h
@@ -0,0 +1,17 @@
+// 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_FONTS_FONT_OPTICAL_SIZING_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_OPTICAL_SIZING_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+enum OpticalSizing { kAutoOpticalSizing, kNoneOpticalSizing };
+
+PLATFORM_EXPORT String ToString(OpticalSizing);
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_OPTICAL_SIZING_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
index 3aad1f7cd16..302923ee596 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/fonts/text_run_paint_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/text/tab_size.h"
#include "third_party/blink/renderer/platform/text/text_run.h"
using blink::test::CreateTestFont;
@@ -86,4 +87,12 @@ TEST_F(FontTest, ExpandRange) {
EXPECT_EQ(GetExpandedRange("tneiciffe", false, 0, 9), Vector<int>({0, 9}));
}
+TEST_F(FontTest, TabWidthZero) {
+ Font font =
+ CreateTestFont("Ahem", test::PlatformTestDataPath("Ahem.woff"), 0);
+ TabSize tab_size(8);
+ EXPECT_EQ(font.TabWidth(tab_size, .0f), .0f);
+ EXPECT_EQ(font.TabWidth(tab_size, LayoutUnit()), LayoutUnit());
+}
+
} // 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 7bcef5fbea7..189e5a62a66 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
@@ -9,7 +9,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/deque.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include <unicode/uchar.h>
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 8007d48e989..89fea7e10c3 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
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
#include <memory>
+
+#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
@@ -235,13 +237,13 @@ TEST_F(CachingWordShaperTest, SegmentEmojiPilotJudgeSequence) {
// the latter including a variation selector.
const UChar kStr[] = {0xD83D, 0xDC68, 0xD83C, 0xDFFB, 0x200D, 0x2696, 0xFE0F,
0xD83D, 0xDC68, 0xD83C, 0xDFFB, 0x200D, 0x2708, 0xFE0F};
- TextRun text_run(kStr, ARRAY_SIZE(kStr));
+ TextRun text_run(kStr, base::size(kStr));
scoped_refptr<const ShapeResult> word_result;
CachingWordShapeIterator iterator(cache.get(), text_run, &font);
ASSERT_TRUE(iterator.Next(&word_result));
- EXPECT_EQ(ARRAY_SIZE(kStr), word_result->NumCharacters());
+ EXPECT_EQ(base::size(kStr), word_result->NumCharacters());
ASSERT_FALSE(iterator.Next(&word_result));
}
@@ -303,7 +305,7 @@ TEST_F(CachingWordShaperTest, SegmentEmojiSubdivisionFlags) {
0xDC73, 0xDB40, 0xDC63, 0xDB40, 0xDC74, 0xDB40, 0xDC7F,
0xD83C, 0xDFF4, 0xDB40, 0xDC67, 0xDB40, 0xDC62, 0xDB40,
0xDC65, 0xDB40, 0xDC6E, 0xDB40, 0xDC67, 0xDB40, 0xDC7F};
- TextRun text_run(kStr, ARRAY_SIZE(kStr));
+ TextRun text_run(kStr, base::size(kStr));
scoped_refptr<const ShapeResult> word_result;
CachingWordShapeIterator iterator(cache.get(), text_run, &font);
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 5fa78fbbb1e..eeb7e99b05f 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
@@ -263,8 +263,9 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
void CopyRange(unsigned start, unsigned end, ShapeResult*) const;
struct ShapeRange {
- // ShapeRange(unsigned start, unsigned end, ShapeResult* target)
- // : start(start), end(end), target(target){};
+ ShapeRange(unsigned start, unsigned end, ShapeResult* target)
+ : start(start), end(end), target(target) {}
+
unsigned start;
unsigned end;
ShapeResult* target;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
index ee3eba136b1..859395b6559 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
@@ -32,20 +32,12 @@ namespace {
// ShapingLineBreaker computes using visual positions. This function flips
// logical advance to visual, or vice versa.
-LayoutUnit FlipRtl(LayoutUnit value, TextDirection direction) {
+inline LayoutUnit FlipRtl(LayoutUnit value, TextDirection direction) {
return IsLtr(direction) ? value : -value;
}
-// Snaps a visual position to the line start direction.
-LayoutUnit SnapStart(float value, TextDirection direction) {
- return IsLtr(direction) ? LayoutUnit::FromFloatFloor(value)
- : LayoutUnit::FromFloatCeil(value);
-}
-
-// Snaps a visual position to the line end direction.
-LayoutUnit SnapEnd(float value, TextDirection direction) {
- return IsLtr(direction) ? LayoutUnit::FromFloatCeil(value)
- : LayoutUnit::FromFloatFloor(value);
+inline float FlipRtl(float value, TextDirection direction) {
+ return IsLtr(direction) ? value : -value;
}
inline bool IsBreakableSpace(UChar ch) {
@@ -221,17 +213,16 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine(
const String& text = GetText();
// The start position in the original shape results.
- float start_position_float =
- result_->CachedPositionForOffset(start - range_start);
- TextDirection direction = result_->Direction();
- LayoutUnit start_position = SnapStart(start_position_float, direction);
+ float start_position = result_->CachedPositionForOffset(start - range_start);
// Find a candidate break opportunity by identifying the last offset before
// exceeding the available space and the determine the closest valid break
// preceding the candidate.
- LayoutUnit end_position = SnapEnd(start_position_float, direction) +
- FlipRtl(available_space, direction);
- DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0));
+ TextDirection direction = result_->Direction();
+ float end_position = start_position + FlipRtl(available_space, direction);
+ DCHECK_GE(FlipRtl(LayoutUnit::FromFloatCeil(end_position - start_position),
+ direction),
+ LayoutUnit(0));
unsigned candidate_break =
result_->CachedOffsetForPosition(end_position) + range_start;
@@ -283,11 +274,10 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine(
return ShapeResultView::Create(
Shape(start, break_opportunity.offset).get());
}
- LayoutUnit original_width = FlipRtl(
- SnapEnd(result_->CachedPositionForOffset(first_safe - range_start),
- direction) -
- start_position,
- direction);
+ float first_safe_position =
+ result_->CachedPositionForOffset(first_safe - range_start);
+ LayoutUnit original_width = LayoutUnit::FromFloatCeil(
+ FlipRtl(first_safe_position - start_position, direction));
line_start_result = Shape(start, first_safe);
available_space += line_start_result->SnappedWidth() - original_width;
}
@@ -334,10 +324,10 @@ scoped_refptr<const ShapeResultView> ShapingLineBreaker::ShapeLine(
}
// Check if this opportunity can fit after reshaping the line end.
- LayoutUnit safe_position = SnapStart(
- result_->CachedPositionForOffset(last_safe - range_start), direction);
+ float safe_position =
+ result_->CachedPositionForOffset(last_safe - range_start);
line_end_result = Shape(last_safe, break_opportunity.offset);
- if (line_end_result->SnappedWidth() <=
+ if (line_end_result->Width() <=
FlipRtl(end_position - safe_position, direction))
break;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc
new file mode 100644
index 00000000000..a563a80074d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.cc
@@ -0,0 +1,91 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h"
+
+#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
+
+namespace blink {
+
+namespace {
+
+const wtf_size_t kMaxCacheSlots = 16;
+
+String makeCacheKey(FontDescription::GenericFamilyType generic_family,
+ String bcp47_language_tag,
+ FontFallbackPriority fallback_priority) {
+ StringBuilder cache_key;
+ cache_key.Append(bcp47_language_tag);
+ cache_key.AppendNumber(
+ static_cast<
+ std::underlying_type<FontDescription::GenericFamilyType>::type>(
+ generic_family));
+ cache_key.AppendNumber(
+ static_cast<std::underlying_type<FontFallbackPriority>::type>(
+ fallback_priority));
+ return cache_key.ToString();
+}
+
+void getFallbackFamilyAndStyle(SkTypeface* typeface,
+ String* fallback_family,
+ SkFontStyle* fallback_style) {
+ SkString family;
+ typeface->getFamilyName(&family);
+ *fallback_family = family.c_str();
+
+ *fallback_style = typeface->fontStyle();
+}
+} // namespace
+
+FallbackFamilyStyleCache::FallbackFamilyStyleCache()
+ : recent_fallback_fonts_(kMaxCacheSlots) {}
+
+void FallbackFamilyStyleCache::Put(
+ FontDescription::GenericFamilyType generic_family,
+ String bcp47_language_tag,
+ FontFallbackPriority fallback_priority,
+ SkTypeface* typeface) {
+ String cache_key =
+ makeCacheKey(generic_family, bcp47_language_tag, fallback_priority);
+
+ FallbackLruCache::TypefaceVector* existing_typefaces =
+ recent_fallback_fonts_.Get(cache_key);
+ if (existing_typefaces) {
+ existing_typefaces->insert(0, sk_ref_sp(typeface));
+ } else {
+ FallbackLruCache::TypefaceVector typefaces;
+ typefaces.push_back(sk_ref_sp(typeface));
+ recent_fallback_fonts_.Put(std::move(cache_key), std::move(typefaces));
+ }
+}
+
+void FallbackFamilyStyleCache::Get(
+ FontDescription::GenericFamilyType generic_family,
+ String bcp47_language_tag,
+ FontFallbackPriority fallback_priority,
+ UChar32 character,
+ String* fallback_family,
+ SkFontStyle* fallback_style) {
+ FallbackLruCache::TypefaceVector* typefaces = recent_fallback_fonts_.Get(
+ makeCacheKey(generic_family, bcp47_language_tag, fallback_priority));
+ if (!typefaces)
+ return;
+
+ for (wtf_size_t i = 0; i < typefaces->size(); ++i) {
+ sk_sp<SkTypeface>& typeface = typefaces->at(i);
+ if (typeface->unicharToGlyph(character)) {
+ getFallbackFamilyAndStyle(typeface.get(), fallback_family,
+ fallback_style);
+ sk_sp<SkTypeface> tmp_typeface(typeface);
+ // For the vector of typefaces for this specific language tag, since this
+ // SkTypeface had a glyph, move it to the beginning to accelerate
+ // subsequent lookups.
+ typefaces->EraseAt(i);
+ typefaces->insert(0, std::move(tmp_typeface));
+ return;
+ }
+ }
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..5e8f86ebcf9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h
@@ -0,0 +1,56 @@
+// 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_FONTS_WIN_FALLBACK_FAMILY_STYLE_CACHE_WIN_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_FAMILY_STYLE_CACHE_WIN_H_
+
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
+#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+
+namespace blink {
+
+class FallbackFamilyStyleCache {
+ USING_FAST_MALLOC(FallbackFamilyStyleCache);
+
+ public:
+ FallbackFamilyStyleCache();
+
+ // Places a SkTypeface object in the cache for specified language tag and
+ // fallback priority, taking a reference on SkTypeface. Adds the |SkTypeface|
+ // to the beginning of a list of typefaces if previous |SkTypefaces| objects
+ // where added for this set of parameters. Note, the internal list of
+ // typefaces for a language tag and fallback priority is not checked for
+ // duplicates when adding a |typeface| object.
+ void Put(FontDescription::GenericFamilyType generic_family,
+ String bcp47_language_tag,
+ FontFallbackPriority fallback_priority,
+ SkTypeface* typeface);
+
+ // Fetches a |fallback_family| and |fallback_style| for a given language tag,
+ // fallback priority and codepoint. Checks the internal cache for whether a
+ // fallback font with glyph coverage for |character| is available for the
+ // given parameters, then returns its family name and style.
+ void Get(FontDescription::GenericFamilyType generic_family,
+ String bcp47_language_tag,
+ FontFallbackPriority fallback_priority,
+ UChar32 character,
+ String* fallback_family,
+ SkFontStyle* fallback_style);
+
+ // Empties the internal cache, deleting keys and unrefing the typefaces that
+ // were placed in the cache.
+ void Clear();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FallbackFamilyStyleCache);
+
+ FallbackLruCache recent_fallback_fonts_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_FAMILY_STYLE_CACHE_WIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc
new file mode 100644
index 00000000000..37b6a152785
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.cc
@@ -0,0 +1,57 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
+
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+FallbackLruCache::FallbackLruCache(size_t max_size) : max_size_(max_size) {
+ DCHECK_GT(max_size_, 0u);
+}
+
+FallbackLruCache::TypefaceVector* FallbackLruCache::Get(const String& key) {
+ HashMapType::iterator find_result = map_.find(key);
+ if (find_result == map_.end())
+ return nullptr;
+
+ // Move result to beginning of list.
+ KeyListNode* node = find_result->value.ListNode();
+ ordering_.Remove(node);
+ ordering_.Push(node);
+ return find_result->value.value();
+}
+
+void FallbackLruCache::Put(String&& key, TypefaceVector&& arg) {
+ HashMapType::iterator find_result = map_.find(key);
+ if (find_result != map_.end()) {
+ ordering_.Remove(find_result->value.ListNode());
+ map_.erase(find_result);
+ }
+
+ if (map_.size() >= max_size_) {
+ RemoveLeastRecentlyUsed();
+ }
+
+ std::unique_ptr<KeyListNode> list_node = std::make_unique<KeyListNode>(key);
+ HashMapType::AddResult add_result = map_.insert(
+ std::move(key), MappedWithListNode(std::move(arg), std::move(list_node)));
+ DCHECK(add_result.is_new_entry);
+ ordering_.Push(add_result.stored_value->value.ListNode());
+}
+
+void FallbackLruCache::Clear() {
+ map_.clear();
+ ordering_.Clear();
+}
+
+void FallbackLruCache::RemoveLeastRecentlyUsed() {
+ KeyListNode* tail = ordering_.Tail();
+ ordering_.Remove(tail);
+ map_.erase(tail->key());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h
new file mode 100644
index 00000000000..90048e3319a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h
@@ -0,0 +1,91 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/doubly_linked_list.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
+
+namespace blink {
+
+/* A LRU cache for storing a a vector of typefaces for a particular key string,
+ * which would usually be a locale plus potential additional parameters. Uses a
+ * HashMap for storage and access and a DoublyLinkedList for managing age of
+ * entries. TODO(https://crbug.com/1010925): Potentially move this to a generic
+ * LRU Cache implementation once we have such in WTF. */
+class PLATFORM_EXPORT FallbackLruCache {
+ USING_FAST_MALLOC(FallbackLruCache);
+
+ public:
+ FallbackLruCache(size_t max_size);
+
+ using TypefaceVector = Vector<sk_sp<SkTypeface>>;
+
+ TypefaceVector* Get(const String& key);
+ void Put(String&& key, TypefaceVector&& arg);
+
+ void Clear();
+
+ size_t size() const { return map_.size(); }
+
+ private:
+ class KeyListNode final : public DoublyLinkedListNode<KeyListNode> {
+ USING_FAST_MALLOC(KeyListNode);
+
+ public:
+ friend class DoublyLinkedListNode<KeyListNode>;
+ KeyListNode(const String& key) : key_(key) {}
+
+ const String& key() const { return key_; }
+
+ private:
+ String key_;
+ KeyListNode* prev_{nullptr};
+ KeyListNode* next_{nullptr};
+ };
+
+ class MappedWithListNode {
+ USING_FAST_MALLOC(MappedWithListNode);
+
+ public:
+ MappedWithListNode(TypefaceVector&& mapped_arg,
+ std::unique_ptr<KeyListNode>&& list_node)
+ : mapped_value_(std::move(mapped_arg)),
+ list_node_(std::move(list_node)) {}
+
+ MappedWithListNode(WTF::HashTableDeletedValueType) {
+ list_node_.reset(reinterpret_cast<KeyListNode*>(-1));
+ }
+
+ TypefaceVector* value() { return &mapped_value_; }
+ KeyListNode* ListNode() { return list_node_.get(); }
+
+ private:
+ TypefaceVector mapped_value_;
+ std::unique_ptr<KeyListNode> list_node_;
+ };
+
+ void RemoveLeastRecentlyUsed();
+
+ using HashMapType = HashMap<String,
+ MappedWithListNode,
+ DefaultHash<String>::Hash,
+ HashTraits<String>,
+ SimpleClassHashTraits<MappedWithListNode>>;
+
+ HashMapType map_;
+ DoublyLinkedList<KeyListNode> ordering_;
+ size_t max_size_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FALLBACK_LRU_CACHE_WIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc
new file mode 100644
index 00000000000..92f78aa9e38
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win_test.cc
@@ -0,0 +1,97 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/win/fallback_lru_cache_win.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+
+namespace {
+
+const char kHanSimplifiedLocale[] = "zh-Hans";
+const size_t kLruCacheTestSize = 5;
+const char kFontFamilyNameArial[] = "Arial";
+const UChar32 kFirstCJKIdeograph = 0x4E00;
+const UChar32 kSecondCJKIdeograph = kFirstCJKIdeograph + 1;
+
+sk_sp<SkTypeface> fallbackForLocale(String locale, UChar32 codepoint) {
+ sk_sp<SkFontMgr> font_mgr = SkFontMgr::RefDefault();
+ std::string locale_string(locale.Ascii());
+ const char* locale_char = locale_string.c_str();
+ return sk_sp<SkTypeface>(font_mgr->matchFamilyStyleCharacter(
+ kFontFamilyNameArial, SkFontStyle(), &locale_char, 1, codepoint));
+}
+
+void fillCacheWithDummies(blink::FallbackLruCache& lru_cache,
+ const char* format_string,
+ size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ blink::FallbackLruCache::TypefaceVector dummy_typefaces;
+ dummy_typefaces.push_back(
+ SkTypeface::MakeFromName(kFontFamilyNameArial, SkFontStyle()));
+ lru_cache.Put(String::Format(format_string, i), std::move(dummy_typefaces));
+ }
+}
+
+} // namespace
+
+namespace blink {
+
+TEST(FallbackLruCacheTest, KeepChineseWhenFetched) {
+ // Put a Chinese font in the cache, add size - 1 more dummy fallback fonts so
+ // that the cache is full. Get() and verify typeface for Chinese to move them
+ // up to the top of the cache. Then fill again with size - 1 items and verify
+ // that Chinese is still in the cache. Then fill with # size items to evict
+ // the Chinese font and ensure it's gone.
+ FallbackLruCache lru_cache(kLruCacheTestSize);
+ EXPECT_EQ(lru_cache.size(), 0u);
+ FallbackLruCache::TypefaceVector fallback_typefaces_zh;
+ fallback_typefaces_zh.push_back(
+ fallbackForLocale(kHanSimplifiedLocale, kFirstCJKIdeograph));
+ lru_cache.Put(kHanSimplifiedLocale, std::move(fallback_typefaces_zh));
+
+ EXPECT_EQ(lru_cache.size(), 1u);
+
+ fillCacheWithDummies(lru_cache, "dummy_locale_%zu", kLruCacheTestSize - 1);
+ FallbackLruCache::TypefaceVector* chinese_typefaces =
+ lru_cache.Get(kHanSimplifiedLocale);
+ EXPECT_TRUE(chinese_typefaces);
+ EXPECT_TRUE(chinese_typefaces->at(0)->unicharToGlyph(0x4E01));
+ EXPECT_EQ(lru_cache.size(), kLruCacheTestSize);
+
+ fillCacheWithDummies(lru_cache, "dummy_locale_2nd_%zu",
+ kLruCacheTestSize - 1);
+ chinese_typefaces = nullptr;
+ chinese_typefaces = lru_cache.Get(kHanSimplifiedLocale);
+ EXPECT_TRUE(chinese_typefaces);
+ EXPECT_EQ(chinese_typefaces->size(), 1u);
+ EXPECT_TRUE(chinese_typefaces->at(0)->unicharToGlyph(kSecondCJKIdeograph));
+ EXPECT_EQ(lru_cache.size(), kLruCacheTestSize);
+
+ fillCacheWithDummies(lru_cache, "dummy_locale_3rd_%zu", kLruCacheTestSize);
+ chinese_typefaces = nullptr;
+ chinese_typefaces = lru_cache.Get(kHanSimplifiedLocale);
+ EXPECT_FALSE(chinese_typefaces);
+ EXPECT_EQ(lru_cache.size(), kLruCacheTestSize);
+}
+
+TEST(FallbackLruCacheTest, LargeFillAndClear) {
+ FallbackLruCache lru_cache(kLruCacheTestSize);
+ EXPECT_EQ(lru_cache.size(), 0u);
+ fillCacheWithDummies(lru_cache, "dummy_locale_%zu", 1000);
+ EXPECT_EQ(lru_cache.size(), kLruCacheTestSize);
+ lru_cache.Clear();
+ EXPECT_EQ(lru_cache.size(), 0u);
+}
+
+TEST(FallbackLruCacheTest, KeyOverride) {
+ FallbackLruCache lru_cache(kLruCacheTestSize);
+ EXPECT_EQ(lru_cache.size(), 0u);
+ fillCacheWithDummies(lru_cache, "same_locale", 10);
+ EXPECT_EQ(lru_cache.size(), 1u);
+}
+
+} // namespace blink
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 cabb176c7b0..821a6a7afc3 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
@@ -36,6 +36,7 @@
#include <unicode/uscript.h>
#include <memory>
+#include <string>
#include <utility>
#include "base/debug/alias.h"
@@ -229,7 +230,7 @@ void FontCache::EnsureServiceConnected() {
if (service_)
return;
Platform::Current()->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&service_));
+ service_.BindNewPipeAndPassReceiver());
}
// TODO(https://crbug.com/976737): This function is deprecated and only intended
@@ -328,25 +329,50 @@ scoped_refptr<SimpleFontData> FontCache::GetDWriteFallbackFamily(
// character + language tag and call matchFamilyStyleCharacter on the browser
// side, where we can do that.
if (!use_skia_font_fallback_) {
- EnsureServiceConnected();
-
- // After Mojo IPC, on the browser side, this ultimately reaches
- // Skia's matchFamilyStyleCharacter for Windows, which does not implement
- // traversing the language tag stack but only processes the most important
- // one, so we use FallbackLocaleForCharacter() to determine what locale to
- // choose to achieve the best possible result.
- AtomicString family(GetOutOfProcessFallbackFamily(
- codepoint, font_description.GenericFamily(),
- fallback_locale->LocaleForSkFontMgr(), fallback_priority, service_));
-
- if (family.IsEmpty())
- return nullptr;
+ String fallback_family;
+ SkFontStyle fallback_style;
- FontFaceCreationParams create_by_family(family);
- FontPlatformData* data =
- GetFontPlatformData(font_description, create_by_family);
+ if (UNLIKELY(!fallback_params_cache_)) {
+ fallback_params_cache_ = std::make_unique<FallbackFamilyStyleCache>();
+ }
+
+ fallback_params_cache_->Get(
+ font_description.GenericFamily(), fallback_locale->LocaleForSkFontMgr(),
+ fallback_priority, codepoint, &fallback_family, &fallback_style);
+ bool result_from_cache = !fallback_family.IsNull();
+
+ if (!result_from_cache) {
+ EnsureServiceConnected();
+
+ // After Mojo IPC, on the browser side, this ultimately reaches
+ // Skia's matchFamilyStyleCharacter for Windows, which does not implement
+ // traversing the language tag stack but only processes the most important
+ // one, so we use FallbackLocaleForCharacter() to determine what locale to
+ // choose to achieve the best possible result.
+
+ if (!GetOutOfProcessFallbackFamily(
+ codepoint, font_description.GenericFamily(),
+ fallback_locale->LocaleForSkFontMgr(), fallback_priority,
+ service_, &fallback_family, &fallback_style))
+ return nullptr;
+
+ if (fallback_family.IsEmpty())
+ return nullptr;
+ }
+
+ FontFaceCreationParams create_by_family((AtomicString(fallback_family)));
+ FontDescription fallback_updated_font_description(font_description);
+ fallback_updated_font_description.UpdateFromSkiaFontStyle(fallback_style);
+ FontPlatformData* data = GetFontPlatformData(
+ fallback_updated_font_description, create_by_family);
if (!data || !data->FontContainsCharacter(codepoint))
return nullptr;
+
+ if (!result_from_cache) {
+ fallback_params_cache_->Put(font_description.GenericFamily(),
+ fallback_locale->LocaleForSkFontMgr(),
+ fallback_priority, data->Typeface());
+ }
return FontDataFromFontPlatformData(data, kDoNotRetain);
} else {
std::string family_name = font_description.Family().Family().Utf8();
@@ -362,9 +388,12 @@ scoped_refptr<SimpleFontData> FontCache::GetDWriteFallbackFamily(
SkString skia_family;
typeface->getFamilyName(&skia_family);
+ FontDescription fallback_updated_font_description(font_description);
+ fallback_updated_font_description.UpdateFromSkiaFontStyle(
+ typeface->fontStyle());
FontFaceCreationParams create_by_family(ToAtomicString(skia_family));
- FontPlatformData* data =
- GetFontPlatformData(font_description, create_by_family);
+ FontPlatformData* data = GetFontPlatformData(
+ fallback_updated_font_description, create_by_family);
if (!data || !data->FontContainsCharacter(codepoint))
return nullptr;
return FontDataFromFontPlatformData(data, kDoNotRetain);
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 79b0ae068e1..591c693d2e0 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
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/platform/fonts/win/font_fallback_win.h"
#include <unicode/uchar.h>
+
#include <limits>
#include "base/stl_util.h"
@@ -547,12 +548,14 @@ const UChar* GetFallbackFamily(UChar32 character,
return family;
}
-const String GetOutOfProcessFallbackFamily(
+bool GetOutOfProcessFallbackFamily(
UChar32 character,
FontDescription::GenericFamilyType generic_family,
String bcp47_language_tag,
FontFallbackPriority,
- const mojom::blink::DWriteFontProxyPtr& service) {
+ const mojo::Remote<mojom::blink::DWriteFontProxy>& service,
+ String* fallback_family,
+ SkFontStyle* fallback_style) {
String base_family_name_approximation;
switch (generic_family) {
case FontDescription::kMonospaceFamily:
@@ -564,11 +567,19 @@ const String GetOutOfProcessFallbackFamily(
default:
base_family_name_approximation = kTimesNewRoman;
}
- String fallback_family_name;
- service->FallbackFamilyNameForCodepoint(base_family_name_approximation,
- bcp47_language_tag, character,
- &fallback_family_name);
- return fallback_family_name;
+
+ mojom::blink::FallbackFamilyAndStylePtr fallback_family_and_style;
+ bool mojo_result = service->FallbackFamilyAndStyleForCodepoint(
+ base_family_name_approximation, bcp47_language_tag, character,
+ &fallback_family_and_style);
+
+ SECURITY_DCHECK(fallback_family);
+ SECURITY_DCHECK(fallback_style);
+ *fallback_family = fallback_family_and_style->fallback_family_name;
+ *fallback_style = SkFontStyle(
+ fallback_family_and_style->weight, fallback_family_and_style->width,
+ static_cast<SkFontStyle::Slant>(fallback_family_and_style->slant));
+ return mojo_result;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h
index c3e93c2e7a6..254eba78a36 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h
@@ -33,13 +33,14 @@
#include <unicode/locid.h>
#include <unicode/uscript.h>
-#include <usp10.h>
-#include <wchar.h>
-#include <windows.h>
-#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/skia/include/core/SkFontStyle.h"
class SkFontMgr;
@@ -61,12 +62,14 @@ PLATFORM_EXPORT const UChar* GetFallbackFamily(
// that characters belong to by performing an out of process lookup and using
// system fallback API based on IDWriteTextLayout. This method is only to be
// used on pre Windows 8.1, as otherwise IDWriteFontFallback API is available.
-PLATFORM_EXPORT const String GetOutOfProcessFallbackFamily(
+PLATFORM_EXPORT bool GetOutOfProcessFallbackFamily(
UChar32 character,
FontDescription::GenericFamilyType,
String bcp47_language_tag,
FontFallbackPriority,
- const mojom::blink::DWriteFontProxyPtr& font_proxy);
+ const mojo::Remote<mojom::blink::DWriteFontProxy>& font_proxy,
+ String* fallback_family,
+ SkFontStyle* fallback_style);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
index beef91f8d92..52555021f7b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.cc
@@ -4,6 +4,9 @@
#include "third_party/blink/renderer/platform/fonts/win/font_unique_name_lookup_win.h"
+#include <memory>
+#include <utility>
+
#include "base/files/file_path.h"
#include "mojo/public/mojom/base/shared_memory.mojom-blink.h"
#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
@@ -163,7 +166,7 @@ void FontUniqueNameLookupWin::EnsureServiceConnected() {
if (service_)
return;
Platform::Current()->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&service_));
+ service_.BindNewPipeAndPassReceiver());
}
void FontUniqueNameLookupWin::PrepareFontUniqueNameLookup(
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 6570b26be87..eb7c881a05d 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
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/font_unique_name_lookup/font_table_matcher.h"
#include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
#include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h"
@@ -42,7 +43,7 @@ class FontUniqueNameLookupWin : public FontUniqueNameLookup {
base::FilePath font_file_path,
uint32_t ttc_index);
- mojom::blink::DWriteFontProxyPtr service_;
+ mojo::Remote<mojom::blink::DWriteFontProxy> service_;
WTF::Deque<NotifyFontUniqueNameLookupReady> pending_callbacks_;
base::Optional<blink::mojom::UniqueFontLookupMode> lookup_mode_;
base::Optional<bool> sync_available_;
@@ -54,4 +55,4 @@ class FontUniqueNameLookupWin : public FontUniqueNameLookup {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WIN_FONT_UNIQUE_NAME_LOOKUP_WIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/DEPS b/chromium/third_party/blink/renderer/platform/graphics/DEPS
index 56477699a71..37eff60e8f0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/DEPS
@@ -11,6 +11,7 @@ include_rules = [
"+base/barrier_closure.h",
"+base/callback_helpers.h",
"+cc",
+ "+components/paint_preview/common",
"+components/viz/client",
"+components/viz/common",
"+gpu/config",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/OWNERS b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
index 28d1c1091e5..73a65352c7d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
@@ -17,6 +17,9 @@ samans@chromium.org
# lowLatency canvas
mcasas@chromium.org
+# canvas resources and images
+khushalsagar@chromium.org
+
# TEAM: paint-dev@chromium.org
# COMPONENT: Blink>Paint
diff --git a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
index 26e5544b7b4..a93063f7715 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
@@ -43,7 +44,7 @@ std::unique_ptr<Thread> CreateThread(const char* name) {
}
class MockAnimationWorkletMutator
- : public GarbageCollectedFinalized<MockAnimationWorkletMutator>,
+ : public GarbageCollected<MockAnimationWorkletMutator>,
public AnimationWorkletMutator {
USING_GARBAGE_COLLECTED_MIXIN(MockAnimationWorkletMutator);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
index 0d7ea36cb3c..9524ea33884 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -59,6 +59,10 @@ void BeginFrameProvider::CreateCompositorFrameSinkIfNeeded() {
if (compositor_frame_sink_.is_bound())
return;
+ // Once we are using RAF, this thread is driving Display updates. Update
+ // priority accordingly.
+ base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
+
mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
Platform::Current()->GetInterfaceProvider()->GetInterface(
provider.BindNewPipeAndPassReceiver());
@@ -91,17 +95,28 @@ void BeginFrameProvider::RequestBeginFrame() {
void BeginFrameProvider::OnBeginFrame(
const viz::BeginFrameArgs& args,
WTF::HashMap<uint32_t, ::viz::mojom::blink::FrameTimingDetailsPtr>) {
+ TRACE_EVENT_WITH_FLOW0("blink", "BeginFrameProvider::OnBeginFrame",
+ TRACE_ID_GLOBAL(args.trace_id),
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
+ if (args.deadline < base::TimeTicks::Now()) {
+ compositor_frame_sink_->DidNotProduceFrame(viz::BeginFrameAck(args, false));
+ return;
+ }
+
// If there was no need for a BeginFrame, just skip it.
if (needs_begin_frame_ && requested_needs_begin_frame_) {
requested_needs_begin_frame_ = false;
- begin_frame_client_->BeginFrame();
+ begin_frame_client_->BeginFrame(args);
} else {
if (!requested_needs_begin_frame_) {
needs_begin_frame_ = false;
compositor_frame_sink_->SetNeedsBeginFrame(false);
}
}
+}
+void BeginFrameProvider::FinishBeginFrame(const viz::BeginFrameArgs& args) {
compositor_frame_sink_->DidNotProduceFrame(viz::BeginFrameAck(args, false));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
index af52da0a241..85dd881a260 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
@@ -24,7 +24,7 @@ struct PLATFORM_EXPORT BeginFrameProviderParams final {
class PLATFORM_EXPORT BeginFrameProviderClient {
public:
- virtual void BeginFrame() = 0;
+ virtual void BeginFrame(const viz::BeginFrameArgs&) = 0;
virtual ~BeginFrameProviderClient() = default;
};
@@ -39,6 +39,7 @@ class PLATFORM_EXPORT BeginFrameProvider
void CreateCompositorFrameSinkIfNeeded();
void RequestBeginFrame();
+ void FinishBeginFrame(const viz::BeginFrameArgs&);
// viz::mojom::blink::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
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 b52d106c1f5..effb974b2a2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -451,14 +451,14 @@ void BitmapImage::SetAnimationPolicy(ImageAnimationPolicy policy) {
}
DarkModeClassification BitmapImage::CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) {
- if (src_rect.Width() < kMinImageSizeForClassification1D ||
- src_rect.Height() < kMinImageSizeForClassification1D)
+ if (dest_rect.Width() < kMinImageSizeForClassification1D ||
+ dest_rect.Height() < kMinImageSizeForClassification1D)
return DarkModeClassification::kApplyFilter;
- if (src_rect.Width() > kMaxImageSizeForClassification1D ||
- src_rect.Height() > kMaxImageSizeForClassification1D) {
+ if (dest_rect.Width() > kMaxImageSizeForClassification1D ||
+ dest_rect.Height() > kMaxImageSizeForClassification1D) {
return DarkModeClassification::kDoNotApplyFilter;
}
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 06e3461de26..b73b4caf454 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
@@ -102,7 +102,7 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
}
DarkModeClassification CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) override;
protected:
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 baece0b7253..b535b55898c 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
@@ -116,7 +116,7 @@ class TestingPlatformSupportWithMaxDecodedBytes
class BitmapImageTest : public testing::Test {
public:
- class FakeImageObserver : public GarbageCollectedFinalized<FakeImageObserver>,
+ class FakeImageObserver : public GarbageCollected<FakeImageObserver>,
public ImageObserver {
USING_GARBAGE_COLLECTED_MIXIN(FakeImageObserver);
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 d8831e7eb75..ab76937e4b6 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
@@ -124,8 +124,6 @@ void Canvas2DLayerBridge::StartRecording() {
if (resource_host_)
resource_host_->RestoreCanvasMatrixClipStack(canvas);
-
- recording_pixel_count_ = 0;
}
void Canvas2DLayerBridge::ResetResourceProvider() {
@@ -342,6 +340,8 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
hibernation_image_.reset();
if (resource_host_) {
+ // If deferral is enabled the recorder will play back the transform, so we
+ // should not do it here or else it will be applied twice
if (!is_deferral_enabled_)
resource_host_->RestoreCanvasMatrixClipStack(resource_provider->Canvas());
@@ -443,15 +443,19 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
return false;
}
- // WritePixels is not supported by deferral. Since we are directly rendering,
- // we can't do deferral on top of the canvas. Disable deferral completely.
- last_recording_ = nullptr;
- is_deferral_enabled_ = false;
- have_recorded_draw_commands_ = false;
- recorder_.reset();
- // install the current matrix/clip stack onto the immediate canvas
- if (GetOrCreateResourceProvider()) {
- resource_host_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
+ if (is_deferral_enabled_) {
+ // WritePixels is not supported by deferral. Since we are directly
+ // rendering, we can't do deferral on top of the canvas. Disable deferral
+ // completely.
+ last_recording_ = nullptr;
+ is_deferral_enabled_ = false;
+ have_recorded_draw_commands_ = false;
+ recorder_.reset();
+ // install the current matrix/clip stack onto the immediate canvas
+ if (GetOrCreateResourceProvider()) {
+ resource_host_->RestoreCanvasMatrixClipStack(
+ ResourceProvider()->Canvas());
+ }
}
ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y);
@@ -730,9 +734,9 @@ void Canvas2DLayerBridge::FinalizeFrame() {
if (!GetOrCreateResourceProvider(kPreferAcceleration))
return;
+ FlushRecording();
++frames_since_last_commit_;
if (frames_since_last_commit_ >= 2) {
- ResourceProvider()->FlushSkia();
if (IsAccelerated() && !rate_limiter_) {
// Make sure the GPU is never more than two animation frames behind.
constexpr unsigned kMaxCanvasAnimationBacklog = 2;
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 ce27be9c5b3..06c069f13a3 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
@@ -170,12 +170,12 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
CanvasResourceProvider* ResourceProvider() const;
void FlushRecording();
- PaintRecorder* getRecorder() { return recorder_.get(); }
sk_sp<cc::PaintRecord> getLastRecord() { return last_recording_; }
// This is called when the Canvas element has cleared the frame, so the 2D
// bridge knows that there's no previous content on the resource.
void ClearFrame() { clear_frame_ = true; }
+ bool IsDeferralEnabled() const { return is_deferral_enabled_; }
private:
friend class Canvas2DLayerBridgeTest;
@@ -199,7 +199,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
int frames_since_last_commit_ = 0;
bool have_recorded_draw_commands_;
bool is_hidden_;
- // See the implementation of DisableDeferral() for more information.
bool is_deferral_enabled_;
bool software_rendering_while_hidden_;
bool hibernation_scheduled_ = false;
@@ -210,7 +209,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
const AccelerationMode acceleration_mode_;
const CanvasColorParams color_params_;
const IntSize size_;
- base::CheckedNumeric<int> recording_pixel_count_;
enum SnapshotState {
kInitialSnapshotState,
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 1d34f5b1d3f..aa146496726 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -37,6 +37,8 @@
#include "cc/test/stub_decode_cache.h"
#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_gles2_interface.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -51,9 +53,8 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/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/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -77,23 +78,6 @@ namespace blink {
namespace {
-class MockGLES2InterfaceWithImageSupport : public FakeGLES2Interface {
- public:
- MOCK_METHOD0(Flush, void());
- MOCK_METHOD4(CreateImageCHROMIUM,
- GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
- MOCK_METHOD1(DestroyImageCHROMIUM, void(GLuint));
- MOCK_METHOD2(GenTextures, void(GLsizei, GLuint*));
- MOCK_METHOD2(DeleteTextures, void(GLsizei, const GLuint*));
- // Fake
- void ProduceTextureDirectCHROMIUM(GLuint texture, GLbyte* mailbox) override {
- mailbox[0] = mailbox_count_++; // Make non-zero mailbox names
- }
-
- private:
- int mailbox_count_ = 1;
-};
-
class ImageTrackingDecodeCache : public cc::StubDecodeCache {
public:
ImageTrackingDecodeCache() = default;
@@ -163,29 +147,12 @@ class Canvas2DLayerBridgeTest : public Test {
}
void SetUp() override {
- auto factory = [](gpu::gles2::GLES2Interface* gl,
- ImageTrackingDecodeCache* cache, GrContext* context,
- bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl, cache,
- context);
- };
-
- gpu::gles2::GLES2Interface* gl = &gl_;
- GrContext* context = nullptr;
- if (!NeedsMockGL()) {
- test_context_provider_ = viz::TestContextProvider::Create();
- test_context_provider_->BindToCurrentThread();
- gl = test_context_provider_->ContextGL();
- context = test_context_provider_->GrContext();
- }
- SharedGpuContext::SetContextProviderFactoryForTesting(WTF::BindRepeating(
- factory, WTF::Unretained(gl), WTF::Unretained(&image_decode_cache_),
- WTF::Unretained(context)));
+ test_context_provider_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(test_context_provider_.get(),
+ &image_decode_cache_);
}
- virtual bool NeedsMockGL() { return true; }
+ virtual bool NeedsMockGL() { return false; }
void TearDown() override {
SharedGpuContext::ResetForTesting();
@@ -199,7 +166,6 @@ class Canvas2DLayerBridgeTest : public Test {
protected:
scoped_refptr<viz::TestContextProvider> test_context_provider_;
- MockGLES2InterfaceWithImageSupport gl_;
ImageTrackingDecodeCache image_decode_cache_;
std::unique_ptr<MockCanvasResourceHost> host_;
};
@@ -227,7 +193,7 @@ TEST_F(Canvas2DLayerBridgeTest, NoDrawOnContextLost) {
uint32_t gen_id = bridge->GetOrCreateResourceProvider()->ContentUniqueID();
bridge->DrawingCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
EXPECT_EQ(nullptr, bridge->GetOrCreateResourceProvider());
// The following passes by not crashing
bridge->NewImageSnapshot(kPreferAcceleration);
@@ -242,7 +208,7 @@ TEST_F(Canvas2DLayerBridgeTest, PrepareMailboxWhenContextIsLost) {
bridge->FinalizeFrame(); // Trigger the creation of a backing store
// When the context is lost we are not sure if we should still be producing
// GL frames for the compositor or not, so fail to generate frames.
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
viz::TransferableResource resource;
std::unique_ptr<viz::SingleReleaseCallback> release_callback;
@@ -260,7 +226,7 @@ TEST_F(Canvas2DLayerBridgeTest,
EXPECT_TRUE(bridge->IsValid());
// When the context is lost we are not sure if we should still be producing
// GL frames for the compositor or not, so fail to generate frames.
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
EXPECT_FALSE(bridge->IsValid());
// Restoration will fail because
@@ -331,7 +297,7 @@ TEST_F(Canvas2DLayerBridgeTest, ReleaseCallbackWithNullContextProviderWrapper) {
}
bool lost_resource = true;
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
// Get a new context provider so that the WeakPtr to the old one is null.
// This is the test to make sure that ReleaseMailboxImageResource() handles
// null context_provider_wrapper properly.
@@ -390,7 +356,7 @@ TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
}
TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) {
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
CanvasColorParams());
@@ -876,7 +842,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_HibernationAbortedDueToLostContext)
MockLogger* mock_logger_ptr = mock_logger.get();
bridge->SetLoggerForTesting(std::move(mock_logger));
- gl_.SetIsContextLost(true);
+ test_context_provider_->TestContextGL()->set_context_lost(true);
// Test entering hibernation
EXPECT_CALL(
@@ -983,168 +949,79 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_PrepareMailboxWhileBackgroundRendering)
EXPECT_TRUE(bridge->IsValid());
}
-TEST_F(Canvas2DLayerBridgeTest, GpuMemoryBufferRecycling) {
- InSequence s;
+TEST_F(Canvas2DLayerBridgeTest, ResourceRecycling) {
ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true);
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper()
->ContextProvider()
->GetCapabilities())
.gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRA_8888);
- viz::TransferableResource resource1;
- viz::TransferableResource resource2;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
- constexpr GLuint texture_id1 = 1;
- constexpr GLuint texture_id2 = 2;
- constexpr GLuint image_id1 = 3;
- constexpr GLuint image_id2 = 4;
- const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
+ viz::TransferableResource resources[3];
+ std::unique_ptr<viz::SingleReleaseCallback> callbacks[3];
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1));
- EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id1));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id1));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id_for_copy = 17;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id_for_copy));
- EXPECT_CALL(gl_, GenTextures(1, _));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
- }
DrawSomething(bridge.get());
- ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource1,
- &release_callback1));
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2));
- EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id2));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id2));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id_for_copy = 19;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id_for_copy));
- EXPECT_CALL(gl_, GenTextures(1, _));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
- }
+ ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[0],
+ &callbacks[0]));
DrawSomething(bridge.get());
- ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource2,
- &release_callback2));
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Check that release resources does not result in destruction due
- // to recycling.
- EXPECT_CALL(gl_, DeleteTextures(_, _)).Times(0);
- bool lost_resource = false;
- release_callback1->Run(gpu::SyncToken(), lost_resource);
- release_callback1 = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, DeleteTextures(_, _)).Times(0);
- release_callback2->Run(gpu::SyncToken(), lost_resource);
- release_callback2 = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Destroying the bridge results in destruction of cached resources.
- EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id1)));
- EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id2)));
- bridge.reset();
+ ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[1],
+ &callbacks[1]));
+ EXPECT_NE(resources[0].mailbox_holder.mailbox,
+ resources[1].mailbox_holder.mailbox);
+
+ // Now release the first resource and draw again. It should be reused due to
+ // recycling.
+ callbacks[0]->Run(gpu::SyncToken(), false);
+ DrawSomething(bridge.get());
+ ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[2],
+ &callbacks[2]));
+ EXPECT_EQ(resources[0].mailbox_holder.mailbox,
+ resources[2].mailbox_holder.mailbox);
- testing::Mock::VerifyAndClearExpectations(&gl_);
+ callbacks[1]->Run(gpu::SyncToken(), false);
+ callbacks[2]->Run(gpu::SyncToken(), false);
}
-TEST_F(Canvas2DLayerBridgeTest, NoGpuMemoryBufferRecyclingWhenPageHidden) {
- InSequence s;
+TEST_F(Canvas2DLayerBridgeTest, NoResourceRecyclingWhenPageHidden) {
ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true);
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper()
->ContextProvider()
->GetCapabilities())
.gpu_memory_buffer_formats.Add(gfx::BufferFormat::BGRA_8888);
- viz::TransferableResource resource1;
- viz::TransferableResource resource2;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback1;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback2;
- constexpr GLuint texture_id1 = 1;
- constexpr GLuint texture_id2 = 2;
- constexpr GLuint image_id1 = 3;
- constexpr GLuint image_id2 = 4;
- const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
+ viz::TransferableResource resources[2];
+ std::unique_ptr<viz::SingleReleaseCallback> callbacks[2];
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1));
- EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id1));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id1));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id_for_copy = 17;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id_for_copy));
- EXPECT_CALL(gl_, GenTextures(1, _));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
- }
DrawSomething(bridge.get());
- bridge->PrepareTransferableResource(nullptr, &resource1, &release_callback1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2));
- EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id2));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id2));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id_for_copy = 19;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id_for_copy));
- EXPECT_CALL(gl_, GenTextures(1, _));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
- }
+ ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[0],
+ &callbacks[0]));
DrawSomething(bridge.get());
- bridge->PrepareTransferableResource(nullptr, &resource2, &release_callback2);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Release first frame to cache
- EXPECT_CALL(gl_, DeleteTextures(_, _)).Times(0);
- bool lost_resource = false;
- release_callback1->Run(gpu::SyncToken(), lost_resource);
- release_callback1 = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Switching to Hidden frees cached resources immediately
- EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id1)));
+ ASSERT_TRUE(bridge->PrepareTransferableResource(nullptr, &resources[1],
+ &callbacks[1]));
+ EXPECT_NE(resources[0].mailbox_holder.mailbox,
+ resources[1].mailbox_holder.mailbox);
+
+ // Now release the first resource and mark the page hidden. The recycled
+ // resource should be dropped.
+ callbacks[0]->Run(gpu::SyncToken(), false);
+ EXPECT_EQ(test_context_provider_->TestContextGL()->NumTextures(), 2u);
bridge->SetIsHidden(true);
+ EXPECT_EQ(test_context_provider_->TestContextGL()->NumTextures(), 1u);
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Release second frame and verify that its resource is destroyed immediately
- // due to the layer bridge being hidden
- EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id2)));
- release_callback2->Run(gpu::SyncToken(), lost_resource);
- release_callback2 = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
+ // Release second frame, this resource is not released because its the current
+ // render target for the canvas. It should only be released if the canvas is
+ // hibernated.
+ callbacks[1]->Run(gpu::SyncToken(), false);
+ EXPECT_EQ(test_context_provider_->TestContextGL()->NumTextures(), 1u);
}
-TEST_F(Canvas2DLayerBridgeTest, ReleaseGpuMemoryBufferAfterBridgeDestroyed) {
- InSequence s;
+TEST_F(Canvas2DLayerBridgeTest, ReleaseResourcesAfterBridgeDestroyed) {
ScopedCanvas2dImageChromiumForTest canvas_2d_image_chromium(true);
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
const_cast<gpu::Capabilities&>(SharedGpuContext::ContextProviderWrapper()
->ContextProvider()
->GetCapabilities())
@@ -1152,43 +1029,20 @@ TEST_F(Canvas2DLayerBridgeTest, ReleaseGpuMemoryBufferAfterBridgeDestroyed) {
viz::TransferableResource resource;
std::unique_ptr<viz::SingleReleaseCallback> release_callback;
- constexpr GLuint texture_id = 1;
- constexpr GLuint image_id = 2;
- const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id_for_copy = 17;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id_for_copy));
- EXPECT_CALL(gl_, GenTextures(1, _));
- EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
- }
DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource, &release_callback);
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
// Tearing down the bridge does not destroy unreleased resources.
- EXPECT_CALL(gl_, DeleteTextures(_, _)).Times(0);
bridge.reset();
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id)));
+ EXPECT_EQ(test_context_provider_->TestContextGL()->NumTextures(), 1u);
constexpr bool lost_resource = false;
release_callback->Run(gpu::SyncToken(), lost_resource);
+ EXPECT_EQ(test_context_provider_->TestContextGL()->NumTextures(), 0u);
release_callback = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
}
TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
@@ -1315,16 +1169,11 @@ TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
bridge->DrawingCanvas()->drawImage(images[1].paint_image(), 0u, 0u, &flags);
}
-class Canvas2DLayerBridgeTestNoMockGL : public Canvas2DLayerBridgeTest {
- bool NeedsMockGL() override { return false; }
-};
-
-TEST_F(Canvas2DLayerBridgeTestNoMockGL,
+TEST_F(Canvas2DLayerBridgeTest,
PrepareTransferableResourceTracksCanvasChanges) {
IntSize size = IntSize(300, 300);
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
size, Canvas2DLayerBridge::kEnableAcceleration, CanvasColorParams());
- host_->set_provider_type(CanvasResourceProvider::kSharedImage);
bridge->DrawingCanvas()->clear(SK_ColorRED);
DrawSomething(bridge.get());
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 8689b73154a..f6b8014c19c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -181,397 +181,6 @@ GLenum CanvasResource::GLFilter() const {
return filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
}
-// CanvasResourceBitmap
-//==============================================================================
-
-CanvasResourceBitmap::CanvasResourceBitmap(
- scoped_refptr<StaticBitmapImage> image,
- base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params)
- : CanvasResource(std::move(provider), filter_quality, color_params),
- image_(std::move(image)) {}
-
-CanvasResourceBitmap::~CanvasResourceBitmap() {
- OnDestroy();
-}
-
-scoped_refptr<CanvasResourceBitmap> CanvasResourceBitmap::Create(
- scoped_refptr<StaticBitmapImage> image,
- base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params) {
- auto resource = AdoptRef(new CanvasResourceBitmap(
- std::move(image), std::move(provider), filter_quality, color_params));
- return resource->IsValid() ? resource : nullptr;
-}
-
-bool CanvasResourceBitmap::IsValid() const {
- return image_ ? image_->IsValid() : false;
-}
-
-bool CanvasResourceBitmap::IsAccelerated() const {
- return image_->IsTextureBacked();
-}
-
-scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper) {
- if (IsAccelerated())
- return base::WrapRefCounted(this);
-
- TRACE_EVENT0("blink", "CanvasResourceBitmap::MakeAccelerated");
-
- if (!context_provider_wrapper)
- return nullptr;
- scoped_refptr<StaticBitmapImage> accelerated_image =
- image_->MakeAccelerated(context_provider_wrapper);
- // passing nullptr for the resource provider argument creates an orphan
- // CanvasResource, which implies that it internal resources will not be
- // recycled.
- scoped_refptr<CanvasResource> accelerated_resource =
- Create(accelerated_image, nullptr, FilterQuality(), ColorParams());
- if (!accelerated_resource)
- return nullptr;
- return accelerated_resource;
-}
-
-scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeUnaccelerated() {
- if (!IsAccelerated())
- return base::WrapRefCounted(this);
-
- TRACE_EVENT0("blink", "CanvasResourceBitmap::MakeUnaccelerated");
-
- scoped_refptr<StaticBitmapImage> unaccelerated_image =
- image_->MakeUnaccelerated();
- // passing nullptr for the resource provider argument creates an orphan
- // CanvasResource, which implies that it internal resources will not be
- // recycled.
- scoped_refptr<CanvasResource> unaccelerated_resource =
- Create(unaccelerated_image, nullptr, FilterQuality(), ColorParams());
- return unaccelerated_resource;
-}
-
-void CanvasResourceBitmap::TearDown() {
- image_ = nullptr;
-}
-
-IntSize CanvasResourceBitmap::Size() const {
- if (!image_)
- return IntSize(0, 0);
- return IntSize(image_->width(), image_->height());
-}
-
-GLenum CanvasResourceBitmap::TextureTarget() const {
- return GL_TEXTURE_2D;
-}
-
-scoped_refptr<StaticBitmapImage> CanvasResourceBitmap::Bitmap() {
- return image_;
-}
-
-const gpu::Mailbox& CanvasResourceBitmap::GetOrCreateGpuMailbox(
- MailboxSyncMode sync_mode) {
- DCHECK(image_); // Calling code should check IsValid() before calling this.
- image_->EnsureMailbox(sync_mode, GLFilter());
- return image_->GetMailbox();
-}
-
-bool CanvasResourceBitmap::HasGpuMailbox() const {
- return image_ && image_->HasMailbox();
-}
-
-const gpu::SyncToken CanvasResourceBitmap::GetSyncToken() {
- DCHECK(image_); // Calling code should check IsValid() before calling this.
- return image_->GetSyncToken();
-}
-
-void CanvasResourceBitmap::Transfer() {
- DCHECK(image_); // Calling code should check IsValid() before calling this.
- return image_->Transfer();
-}
-
-bool CanvasResourceBitmap::OriginClean() const {
- DCHECK(image_);
- return image_->OriginClean();
-}
-
-void CanvasResourceBitmap::SetOriginClean(bool value) {
- DCHECK(image_);
- image_->SetOriginClean(value);
-}
-
-base::WeakPtr<WebGraphicsContext3DProviderWrapper>
-CanvasResourceBitmap::ContextProviderWrapper() const {
- if (!image_)
- return nullptr;
- return image_->ContextProviderWrapper();
-}
-
-void CanvasResourceBitmap::TakeSkImage(sk_sp<SkImage> image) {
- DCHECK(IsAccelerated() == image->isTextureBacked());
- image_ =
- StaticBitmapImage::Create(std::move(image), ContextProviderWrapper());
-}
-
-// CanvasResourceGpuMemoryBuffer
-//==============================================================================
-
-CanvasResourceGpuMemoryBuffer::CanvasResourceGpuMemoryBuffer(
- const IntSize& size,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
- bool is_accelerated)
- : CanvasResource(std::move(provider), filter_quality, color_params),
- context_provider_wrapper_(std::move(context_provider_wrapper)),
- is_accelerated_(is_accelerated) {
- if (!context_provider_wrapper_)
- return;
- auto* gl = context_provider_wrapper_->ContextProvider()->ContextGL();
- auto* gr = context_provider_wrapper_->ContextProvider()->GetGrContext();
- if (!gl || !gr)
- return;
-
- const gfx::BufferUsage buffer_usage =
- is_accelerated ? gfx::BufferUsage::SCANOUT
- : gfx::BufferUsage::SCANOUT_CPU_READ_WRITE;
-
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
- Platform::Current()->GetGpuMemoryBufferManager();
- if (!gpu_memory_buffer_manager)
- return;
- gpu_memory_buffer_ = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
- gfx::Size(size.Width(), size.Height()), ColorParams().GetBufferFormat(),
- buffer_usage, gpu::kNullSurfaceHandle);
- if (!gpu_memory_buffer_)
- return;
-
- gpu_memory_buffer_->SetColorSpace(color_params.GetStorageGfxColorSpace());
-
- const GLuint image_id = gl->CreateImageCHROMIUM(
- gpu_memory_buffer_->AsClientBuffer(), size.Width(), size.Height(),
- ColorParams().GLUnsizedInternalFormat());
- if (!image_id) {
- gpu_memory_buffer_ = nullptr;
- return;
- }
- gl->GenTextures(1, &texture_id_);
- const GLenum target = TextureTarget();
- gl->BindTexture(target, texture_id_);
- gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GLFilter());
- gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GLFilter());
- gl->BindTexImage2DCHROMIUM(target, image_id);
- gl->DestroyImageCHROMIUM(image_id);
-
- if (is_accelerated_ && target == GL_TEXTURE_EXTERNAL_OES) {
- // We can't CopyTextureCHROMIUM() into a GL_TEXTURE_EXTERNAL_OES; create
- // another image and bind a GL_TEXTURE_2D texture to it.
- const GLuint image_2d_id_for_copy = gl->CreateImageCHROMIUM(
- gpu_memory_buffer_->AsClientBuffer(), size.Width(), size.Height(),
- ColorParams().GLUnsizedInternalFormat());
-
- gl->GenTextures(1, &texture_2d_id_for_copy_);
- gl->BindTexture(GL_TEXTURE_2D, texture_2d_id_for_copy_);
- gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_2d_id_for_copy);
-
- gl->DestroyImageCHROMIUM(image_2d_id_for_copy);
- }
-}
-
-CanvasResourceGpuMemoryBuffer::~CanvasResourceGpuMemoryBuffer() {
- OnDestroy();
-}
-
-bool CanvasResourceGpuMemoryBuffer::IsValid() const {
- return !!context_provider_wrapper_ && gpu_memory_buffer_;
-}
-
-GLenum CanvasResourceGpuMemoryBuffer::TextureTarget() const {
- return gpu::GetPlatformSpecificTextureTarget();
-}
-
-IntSize CanvasResourceGpuMemoryBuffer::Size() const {
- return IntSize(gpu_memory_buffer_->GetSize());
-}
-
-scoped_refptr<CanvasResourceGpuMemoryBuffer>
-CanvasResourceGpuMemoryBuffer::Create(
- const IntSize& size,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality,
- bool is_accelerated) {
- TRACE_EVENT0("blink", "CanvasResourceGpuMemoryBuffer::Create");
- auto resource = AdoptRef(new CanvasResourceGpuMemoryBuffer(
- size, color_params, std::move(context_provider_wrapper),
- std::move(provider), filter_quality, is_accelerated));
- return resource->IsValid() ? resource : nullptr;
-}
-
-void CanvasResourceGpuMemoryBuffer::TearDown() {
- // Unref should result in destruction.
- DCHECK(!surface_ || surface_->unique());
-
- surface_ = nullptr;
- if (context_provider_wrapper_) {
- auto* gl = ContextGL();
- if (gl && texture_id_)
- gl->DeleteTextures(1, &texture_id_);
- if (gl && texture_2d_id_for_copy_)
- gl->DeleteTextures(1, &texture_2d_id_for_copy_);
- }
- texture_id_ = 0;
- texture_2d_id_for_copy_ = 0;
- gpu_memory_buffer_ = nullptr;
-}
-
-void CanvasResourceGpuMemoryBuffer::Abandon() {
- surface_ = nullptr;
- texture_id_ = 0;
- texture_2d_id_for_copy_ = 0;
- gpu_memory_buffer_ = nullptr;
-}
-
-const gpu::Mailbox& CanvasResourceGpuMemoryBuffer::GetOrCreateGpuMailbox(
- MailboxSyncMode sync_mode) {
- auto* gl = ContextGL();
- if (gpu_mailbox_.IsZero() && gl) {
- gl->ProduceTextureDirectCHROMIUM(texture_id_, gpu_mailbox_.name);
- mailbox_needs_new_sync_token_ = true;
- mailbox_sync_mode_ = sync_mode;
- }
- return gpu_mailbox_;
-}
-
-bool CanvasResourceGpuMemoryBuffer::HasGpuMailbox() const {
- return !gpu_mailbox_.IsZero();
-}
-
-GLuint CanvasResourceGpuMemoryBuffer::GetBackingTextureHandleForOverwrite() {
- return texture_2d_id_for_copy_ ? texture_2d_id_for_copy_ : texture_id_;
-}
-
-const gpu::SyncToken CanvasResourceGpuMemoryBuffer::GetSyncToken() {
- if (!mailbox_needs_new_sync_token_)
- return sync_token_;
- auto* gl = ContextGL();
- if (!gl)
- return sync_token_;
- mailbox_needs_new_sync_token_ = false;
- if (mailbox_sync_mode_ == kVerifiedSyncToken)
- gl->GenSyncTokenCHROMIUM(sync_token_.GetData());
- else
- gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
-
- return sync_token_;
-}
-
-void CanvasResourceGpuMemoryBuffer::CopyFromTexture(GLuint source_texture,
- GLenum format,
- GLenum type) {
- DCHECK(is_accelerated_);
- if (!IsValid())
- return;
-
- TRACE_EVENT0("blink", "CanvasResourceGpuMemoryBuffer::CopyFromTexture");
- GLenum target = TextureTarget();
- GLuint texture_id = texture_id_;
-
- if (texture_2d_id_for_copy_) {
- // We can't CopyTextureCHROMIUM() into a GL_TEXTURE_EXTERNAL_OES; use
- // instead GL_TEXTURE_2D for the CopyTextureChromium().
- target = GL_TEXTURE_2D;
- texture_id = texture_2d_id_for_copy_;
- }
-
- ContextGL()->CopyTextureCHROMIUM(
- source_texture, 0 /*sourceLevel*/, target, texture_id, 0 /*destLevel*/,
- format, type, false /*unpackFlipY*/, false /*unpackPremultiplyAlpha*/,
- false /*unpackUnmultiplyAlpha*/);
-
- mailbox_needs_new_sync_token_ = true;
-}
-
-void CanvasResourceGpuMemoryBuffer::TakeSkImage(sk_sp<SkImage> image) {
- WillPaint();
- if (!surface_)
- return;
- surface_->getCanvas()->drawImage(image, 0, 0);
- DidPaint();
-}
-
-void CanvasResourceGpuMemoryBuffer::WillPaint() {
- if (!IsValid()) {
- surface_ = nullptr;
- return;
- }
-
- TRACE_EVENT1("blink", "CanvasResourceGpuMemoryBuffer::WillPaint",
- "accelerated", is_accelerated_);
-
- if (is_accelerated_) {
- if (!surface_) { // When accelerated it is okay to re-use previous
- // SkSurface
- GrGLTextureInfo texture_info;
- texture_info.fTarget = TextureTarget();
- texture_info.fID = texture_id_;
- texture_info.fFormat =
- ColorParams().GLSizedInternalFormat(); // unsized format
- GrBackendTexture backend_texture(Size().Width(), Size().Height(),
- GrMipMapped::kNo, texture_info);
- constexpr int sample_count = 0;
- surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
- GetGrContext(), backend_texture, kTopLeft_GrSurfaceOrigin,
- sample_count, ColorParams().GetSkColorType(),
- ColorParams().GetSkColorSpace(), nullptr /*surface props*/);
- }
- } else {
- gpu_memory_buffer_->Map();
- void* buffer_base_address = gpu_memory_buffer_->memory(0);
- if (!surface_ || buffer_base_address != buffer_base_address_) {
- buffer_base_address_ = buffer_base_address;
- SkImageInfo image_info = SkImageInfo::Make(
- Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
- ColorParams().GetSkAlphaType(), ColorParams().GetSkColorSpace());
- surface_ = SkSurface::MakeRasterDirect(image_info, buffer_base_address_,
- gpu_memory_buffer_->stride(0));
- }
- }
-
- DCHECK(surface_);
-}
-
-void CanvasResourceGpuMemoryBuffer::DidPaint() {
- TRACE_EVENT1("blink", "CanvasResourceGpuMemoryBuffer::DidPaint",
- "accelerated", is_accelerated_);
-
- if (is_accelerated_) {
- auto* gr = context_provider_wrapper_->ContextProvider()->GetGrContext();
- if (gr)
- gr->flush();
- mailbox_needs_new_sync_token_ = true;
- } else {
- gpu_memory_buffer_->Unmap();
- }
-}
-
-base::WeakPtr<WebGraphicsContext3DProviderWrapper>
-CanvasResourceGpuMemoryBuffer::ContextProviderWrapper() const {
- return context_provider_wrapper_;
-}
-
-scoped_refptr<StaticBitmapImage> CanvasResourceGpuMemoryBuffer::Bitmap() {
- WillPaint();
- scoped_refptr<StaticBitmapImage> bitmap = StaticBitmapImage::Create(
- surface_->makeImageSnapshot(), ContextProviderWrapper());
- DidPaint();
- bitmap->SetOriginClean(is_origin_clean_);
- return bitmap;
-}
-
// CanvasResourceSharedBitmap
//==============================================================================
@@ -955,13 +564,10 @@ scoped_refptr<StaticBitmapImage> CanvasResourceSharedImage::Bitmap() {
scoped_refptr<StaticBitmapImage> image;
// If its cross thread, then the sync token was already verified. If not, then
- // it doesn't need to be verified.
- if (!is_cross_thread())
- owning_thread_data().mailbox_sync_mode = kUnverifiedSyncToken;
-
+ // we don't need one. The image lazily generates a token if needed.
+ gpu::SyncToken token = is_cross_thread() ? sync_token() : gpu::SyncToken();
image = AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
- mailbox(), is_cross_thread() ? sync_token() : GetSyncToken(),
- texture_id_for_image, image_info, texture_target_,
+ mailbox(), token, texture_id_for_image, image_info, texture_target_,
context_provider_wrapper_, owning_thread_id_, is_origin_top_left_,
std::move(release_callback));
@@ -1010,10 +616,12 @@ void CanvasResourceSharedImage::SetGLFilterIfNeeded() {
!WeakProvider())
return;
- ContextGL()->BindTexture(TextureTarget(), GetTextureIdForReadAccess());
- ContextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GLFilter());
- ContextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GLFilter());
- ContextGL()->BindTexture(TextureTarget(), 0u);
+ ContextGL()->BindTexture(texture_target_, GetTextureIdForReadAccess());
+ ContextGL()->TexParameteri(texture_target_, GL_TEXTURE_MIN_FILTER,
+ GLFilter());
+ ContextGL()->TexParameteri(texture_target_, GL_TEXTURE_MAG_FILTER,
+ GLFilter());
+ ContextGL()->BindTexture(texture_target_, 0u);
owning_thread_data().mailbox_needs_new_sync_token = true;
owning_thread_data().needs_gl_filter_reset = false;
Provider()->NotifyTexParamsModified(this);
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 fdf292e01f1..2442ab2425c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -52,42 +52,87 @@ class PLATFORM_EXPORT CanvasResource
: public WTF::ThreadSafeRefCounted<CanvasResource> {
public:
virtual ~CanvasResource();
+
+ // We perform a lazy copy on write if the canvas content needs to be updated
+ // while its current resource is in use. In order to avoid re-allocating
+ // resources, its preferable to reuse a resource if its no longer in use.
+ // This API indicates whether a resource can be recycled.
virtual bool IsRecycleable() const = 0;
+
+ // Returns true if rendering to the resource is accelerated.
virtual bool IsAccelerated() const = 0;
+
+ // Returns true if the resource can be used with accelerated compositing. This
+ // is different from IsAccelerated since a resource may be rendered to on the
+ // CPU but can be used with GPU compositing (using GMBs).
virtual bool SupportsAcceleratedCompositing() const = 0;
+
+ // Returns true if the resource is still usable. It maybe not be valid in the
+ // case of a context loss or if we fail to initialize the memory backing for
+ // the resource.
virtual bool IsValid() const = 0;
+
+ // When a resource is returned by the display compositor, a sync token is
+ // provided to indicate when the compositor's commands using the resource are
+ // executed on the GPU thread.
+ // However in some cases we need to ensure that the commands using the
+ // resource have finished executing on the GPU itself. This API indicates
+ // whether this is required. The primary use-case for this is GMBs rendered to
+ // on the CPU but composited on the GPU. Its important for the GPU reads to be
+ // finished before updating the resource on the CPU.
virtual bool NeedsReadLockFences() const { return false; }
+
+ // The bounds for this resource.
virtual IntSize Size() const = 0;
+
+ // The mailbox which can be used to reference this resource in GPU commands.
+ // The sync mode indicates how the sync token for the resource should be
+ // prepared.
virtual const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) = 0;
+
+ // A CanvasResource is not thread-safe and does not allow concurrent usage
+ // from multiple threads. But it maybe used from any thread. It remains bound
+ // to the current thread until Transfer is called. Note that while the
+ // resource maybe used for reads on any thread, it can be written to only on
+ // the thread where it was created.
virtual void Transfer() {}
+
+ // Returns the sync token to indicate when all writes to the current resource
+ // are finished on the GPU thread.
virtual const gpu::SyncToken GetSyncToken() {
NOTREACHED();
return gpu::SyncToken();
}
+
+ // Provides a TransferableResource representation of this resource to share it
+ // with the compositor.
bool PrepareTransferableResource(viz::TransferableResource*,
std::unique_ptr<viz::SingleReleaseCallback>*,
MailboxSyncMode);
+
+ // Issues a wait for this sync token on the context used by this resource for
+ // rendering.
void WaitSyncToken(const gpu::SyncToken&);
- virtual scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) = 0;
- virtual scoped_refptr<CanvasResource> MakeUnaccelerated() = 0;
+
virtual bool OriginClean() const = 0;
virtual void SetOriginClean(bool) = 0;
+
+ // Provides a StaticBitmapImage wrapping this resource. Commonly used for
+ // snapshots not used in compositing (for instance to draw to another canvas).
virtual scoped_refptr<StaticBitmapImage> Bitmap() = 0;
- virtual void CopyFromTexture(GLuint source_texture,
- GLenum format,
- GLenum type) {
- NOTREACHED();
- }
- // Only CanvasResourceProvider and derivatives should call this.
+ // Copies the contents of |image| to the resource's backing memory. Only
+ // CanvasResourceProvider and derivatives should call this.
virtual void TakeSkImage(sk_sp<SkImage> image) = 0;
+ // Provides the texture ID that can be used to write to this resource.
+ // TODO(khushalsagar): Won't work with OOPR.
virtual GLuint GetBackingTextureHandleForOverwrite() {
NOTREACHED();
return 0;
}
+ // Returns the texture target for the ID provided above.
virtual GLenum TextureTarget() const {
NOTREACHED();
return 0;
@@ -107,7 +152,9 @@ class PLATFORM_EXPORT CanvasResource
Abandon();
}
+ // The filter quality to use when the resource is drawn by the compositor.
SkFilterQuality FilterQuality() const { return filter_quality_; }
+
SkImageInfo CreateSkImageInfo() const;
protected:
@@ -123,9 +170,19 @@ class PLATFORM_EXPORT CanvasResource
// before this resource could be deleted.
virtual void Abandon() { TearDown(); }
+ // Returns true if the resource is backed by memory such that it can be used
+ // for direct scanout by the display.
virtual bool IsOverlayCandidate() const { return false; }
+
+ // Returns true if the resource is backed by memory that can be referenced
+ // using a mailbox.
virtual bool HasGpuMailbox() const = 0;
+
+ // Destroys the backing memory and any other references to it kept alive by
+ // this object. This must be called from the same thread where the resource
+ // was created.
virtual void TearDown() = 0;
+
gpu::gles2::GLES2Interface* ContextGL() const;
GLenum GLFilter() const;
GrContext* GetGrContext() const;
@@ -157,125 +214,6 @@ class PLATFORM_EXPORT CanvasResource
#endif
};
-// Resource type for skia Bitmaps (RAM and texture backed)
-class PLATFORM_EXPORT CanvasResourceBitmap final : public CanvasResource {
- public:
- static scoped_refptr<CanvasResourceBitmap> Create(
- scoped_refptr<StaticBitmapImage>,
- base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
- const CanvasColorParams&);
- ~CanvasResourceBitmap() override;
-
- // Not recyclable: Skia handles texture recycling internally and bitmaps are
- // cheap to allocate.
- bool IsRecycleable() const final { return false; }
- bool IsAccelerated() const final;
- bool SupportsAcceleratedCompositing() const override {
- return IsAccelerated();
- }
- bool IsValid() const final;
- IntSize Size() const final;
- void Transfer() final;
- scoped_refptr<StaticBitmapImage> Bitmap() final;
- bool OriginClean() const final;
- void SetOriginClean(bool value) final;
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final;
- scoped_refptr<CanvasResource> MakeUnaccelerated() final;
- void TakeSkImage(sk_sp<SkImage> image) final;
-
- private:
- void TearDown() override;
- GLenum TextureTarget() const final;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
- const override;
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
- bool HasGpuMailbox() const override;
- const gpu::SyncToken GetSyncToken() override;
-
- CanvasResourceBitmap(scoped_refptr<StaticBitmapImage>,
- base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
- const CanvasColorParams&);
-
- scoped_refptr<StaticBitmapImage> image_;
-};
-
-// Resource type for GpuMemoryBuffers
-class PLATFORM_EXPORT CanvasResourceGpuMemoryBuffer final
- : public CanvasResource {
- public:
- static scoped_refptr<CanvasResourceGpuMemoryBuffer> Create(
- const IntSize&,
- const CanvasColorParams&,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
- base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
- bool is_accelerated);
- ~CanvasResourceGpuMemoryBuffer() override;
- bool IsRecycleable() const final { return IsValid(); }
- bool IsAccelerated() const final { return is_accelerated_; }
- bool IsValid() const override;
- bool SupportsAcceleratedCompositing() const override { return true; }
- bool NeedsReadLockFences() const final { return true; }
- bool OriginClean() const final { return is_origin_clean_; }
- void SetOriginClean(bool value) final { is_origin_clean_ = value; }
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- NOTREACHED();
- return nullptr;
- }
- scoped_refptr<CanvasResource> MakeUnaccelerated() final {
- NOTREACHED();
- return nullptr;
- }
- void Abandon() final;
- IntSize Size() const final;
- void TakeSkImage(sk_sp<SkImage> image) final;
- void CopyFromTexture(GLuint source_texture,
- GLenum format,
- GLenum type) override;
- scoped_refptr<StaticBitmapImage> Bitmap() override;
- GLuint GetBackingTextureHandleForOverwrite() final;
-
- private:
- void TearDown() override;
- GLenum TextureTarget() const final;
- bool IsOverlayCandidate() const final { return true; }
- const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
- bool HasGpuMailbox() const override;
- const gpu::SyncToken GetSyncToken() override;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
- const override;
- void WillPaint();
- void DidPaint();
-
- CanvasResourceGpuMemoryBuffer(
- const IntSize&,
- const CanvasColorParams&,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
- base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality,
- bool is_accelerated);
-
- gpu::Mailbox gpu_mailbox_;
- gpu::SyncToken sync_token_;
- bool mailbox_needs_new_sync_token_ = false;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
- std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
- void* buffer_base_address_ = nullptr;
- sk_sp<SkSurface> surface_;
- GLuint texture_id_ = 0;
- MailboxSyncMode mailbox_sync_mode_ = kVerifiedSyncToken;
- bool is_accelerated_;
- bool is_origin_clean_ = true;
-
- // GL_TEXTURE_2D view of |gpu_memory_buffer_| for CopyFromTexture(); only used
- // if TextureTarget() is GL_TEXTURE_EXTERNAL_OES.
- GLuint texture_2d_id_for_copy_ = 0;
-};
-
// Resource type for SharedBitmaps
class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
public:
@@ -290,23 +228,9 @@ class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
bool IsValid() const final;
bool SupportsAcceleratedCompositing() const final { return false; }
bool NeedsReadLockFences() const final { return false; }
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- NOTREACHED();
- return nullptr;
- }
- scoped_refptr<CanvasResource> MakeUnaccelerated() final {
- NOTREACHED();
- return nullptr;
- }
void Abandon() final;
IntSize Size() const final;
void TakeSkImage(sk_sp<SkImage> image) final;
- void CopyFromTexture(GLuint source_texture,
- GLenum format,
- GLenum type) override {
- NOTREACHED();
- }
scoped_refptr<StaticBitmapImage> Bitmap() final;
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool flag) final { is_origin_clean_ = flag; }
@@ -352,15 +276,6 @@ class PLATFORM_EXPORT CanvasResourceSharedImage final : public CanvasResource {
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool value) final { is_origin_clean_ = value; }
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- NOTREACHED();
- return nullptr;
- }
- scoped_refptr<CanvasResource> MakeUnaccelerated() final {
- NOTREACHED();
- return nullptr;
- }
void TakeSkImage(sk_sp<SkImage> image) final { NOTREACHED(); }
void NotifyResourceLost() final;
bool NeedsReadLockFences() const final {
@@ -500,15 +415,6 @@ class PLATFORM_EXPORT ExternalCanvasResource final : public CanvasResource {
bool NeedsReadLockFences() const final { return false; }
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool value) final { is_origin_clean_ = value; }
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- NOTREACHED();
- return nullptr;
- }
- scoped_refptr<CanvasResource> MakeUnaccelerated() final {
- NOTREACHED();
- return nullptr;
- }
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
@@ -559,15 +465,6 @@ class PLATFORM_EXPORT CanvasResourceSwapChain final : public CanvasResource {
bool NeedsReadLockFences() const final { return false; }
bool OriginClean() const final { return is_origin_clean_; }
void SetOriginClean(bool value) final { is_origin_clean_ = value; }
- scoped_refptr<CanvasResource> MakeAccelerated(
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- NOTREACHED();
- return nullptr;
- }
- scoped_refptr<CanvasResource> MakeUnaccelerated() final {
- NOTREACHED();
- return nullptr;
- }
void Abandon() final;
IntSize Size() const final { return size_; }
void TakeSkImage(sk_sp<SkImage> image) final;
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 d4b089d2e13..e1ee697308a 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
@@ -321,20 +321,31 @@ void CanvasResourceDispatcher::SetNeedsBeginFrameInternal() {
sink_->SetNeedsBeginFrame(needs_begin_frame_ && !suspend_animation_);
}
+bool CanvasResourceDispatcher::HasTooManyPendingFrames() const {
+ return pending_compositor_frames_ >= kMaxPendingCompositorFrames;
+}
+
void CanvasResourceDispatcher::OnBeginFrame(
const viz::BeginFrameArgs& begin_frame_args,
WTF::HashMap<uint32_t, ::viz::mojom::blink::FrameTimingDetailsPtr>) {
current_begin_frame_ack_ = viz::BeginFrameAck(begin_frame_args, false);
- if (pending_compositor_frames_ >= kMaxPendingCompositorFrames ||
+ if (HasTooManyPendingFrames() ||
(begin_frame_args.type == viz::BeginFrameArgs::MISSED &&
base::TimeTicks::Now() > begin_frame_args.deadline)) {
sink_->DidNotProduceFrame(current_begin_frame_ack_);
return;
}
- if (Client())
- Client()->BeginFrame();
- // TODO(eseckler): Tell |sink_| if we did not draw during the BeginFrame.
+ // TODO(fserb): should EnqueueMicrotask BeginFrame().
+ // We usually never get to BeginFrame if we are on RAF mode. But it could
+ // still happen that begin frame gets requested and we don't have a frame
+ // anymore, so we shouldn't let the compositor wait.
+ bool submitted_frame = Client() && Client()->BeginFrame();
+ if (!submitted_frame) {
+ sink_->DidNotProduceFrame(current_begin_frame_ack_);
+ }
+
+ // TODO(fserb): Update this with the correct value if we are on RAF submit.
current_begin_frame_ack_.sequence_number =
viz::BeginFrameArgs::kInvalidFrameNumber;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
index fef3d719289..30710a8e31b 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
@@ -22,7 +22,7 @@ class CanvasResource;
class CanvasResourceDispatcherClient {
public:
- virtual void BeginFrame() = 0;
+ virtual bool BeginFrame() = 0;
};
class PLATFORM_EXPORT CanvasResourceDispatcher
@@ -60,6 +60,10 @@ class PLATFORM_EXPORT CanvasResourceDispatcher
const SkIRect& damage_rect,
bool needs_vertical_flip,
bool is_opaque);
+ void ReplaceBeginFrameAck(const viz::BeginFrameArgs& args) {
+ current_begin_frame_ack_ = viz::BeginFrameAck(args, true);
+ }
+ bool HasTooManyPendingFrames() const;
void Reshape(const IntSize&);
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 52f6f6eda2b..749a1f77dfa 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
@@ -23,188 +23,6 @@
namespace blink {
-// * Renders to a texture managed by Skia. Mailboxes are backed by vanilla GL
-// textures.
-// * Layers are not overlay candidates.
-class CanvasResourceProviderTexture : public CanvasResourceProvider {
- public:
- CanvasResourceProviderTexture(
- const IntSize& size,
- unsigned msaa_sample_count,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
- bool is_origin_top_left)
- : CanvasResourceProvider(kTexture,
- size,
- msaa_sample_count,
- filter_quality,
- color_params,
- is_origin_top_left,
- std::move(context_provider_wrapper),
- std::move(resource_dispatcher)) {}
-
- ~CanvasResourceProviderTexture() override = default;
-
- bool IsValid() const final { return GetSkSurface() && !IsGpuContextLost(); }
- bool IsAccelerated() const final { return true; }
- bool SupportsDirectCompositing() const override { return true; }
-
- GLuint GetBackingTextureHandleForOverwrite() override {
- GrBackendTexture backend_texture = GetSkSurface()->getBackendTexture(
- SkSurface::kDiscardWrite_TextureHandleAccess);
- if (!backend_texture.isValid())
- return 0;
- GrGLTextureInfo info;
- if (!backend_texture.getGLTextureInfo(&info))
- return 0;
- return info.fID;
- }
-
- protected:
- scoped_refptr<CanvasResource> ProduceCanvasResource() override {
- TRACE_EVENT0("blink",
- "CanvasResourceProviderTexture::ProduceCanvasResource");
- DCHECK(GetSkSurface());
-
- if (IsGpuContextLost())
- return nullptr;
-
- auto* gl = ContextGL();
- DCHECK(gl);
-
- if (ContextProviderWrapper()
- ->ContextProvider()
- ->GetCapabilities()
- .disable_2d_canvas_copy_on_write) {
- // A readback operation may alter the texture parameters, which may affect
- // the compositor's behavior. Therefore, we must trigger copy-on-write
- // even though we are not technically writing to the texture, only to its
- // parameters. This issue is Android-WebView specific: crbug.com/585250.
- // If this issue with readback affecting state is ever fixed, then we'll
- // have to do this instead of triggering a copy-on-write:
- // static_cast<AcceleratedStaticBitmapImage*>(image.get())
- // ->RetainOriginalSkImageForCopyOnWrite();
- GetSkSurface()->notifyContentWillChange(
- SkSurface::kRetain_ContentChangeMode);
- }
-
- auto paint_image = MakeImageSnapshot();
- if (!paint_image)
- return nullptr;
- DCHECK(paint_image.GetSkImage()->isTextureBacked());
-
- scoped_refptr<StaticBitmapImage> image = StaticBitmapImage::Create(
- paint_image.GetSkImage(), ContextProviderWrapper());
-
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- image, CreateWeakPtr(), FilterQuality(), ColorParams());
- if (!resource)
- return nullptr;
-
- return resource;
- }
-
- scoped_refptr<StaticBitmapImage> Snapshot() override {
- TRACE_EVENT0("blink", "CanvasResourceProviderTexture::Snapshot");
- return SnapshotInternal();
- }
-
- sk_sp<SkSurface> CreateSkSurface() const override {
- TRACE_EVENT0("blink", "CanvasResourceProviderTexture::CreateSkSurface");
- if (IsGpuContextLost())
- return nullptr;
- auto* gr = GetGrContext();
- DCHECK(gr);
-
- const SkImageInfo info = SkImageInfo::Make(
- Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
- kPremul_SkAlphaType, ColorParams().GetSkColorSpaceForSkSurfaces());
-
- return SkSurface::MakeRenderTarget(
- gr, SkBudgeted::kNo, info, GetMSAASampleCount(), GetGrSurfaceOrigin(),
- ColorParams().GetSkSurfaceProps());
- }
-};
-
-// * Renders to a texture managed by Skia. Mailboxes are GPU-accelerated
-// platform native surfaces.
-// * Layers are overlay candidates.
-class CanvasResourceProviderTextureGpuMemoryBuffer final
- : public CanvasResourceProviderTexture {
- public:
- CanvasResourceProviderTextureGpuMemoryBuffer(
- const IntSize& size,
- unsigned msaa_sample_count,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
- bool is_origin_top_left)
- : CanvasResourceProviderTexture(size,
- msaa_sample_count,
- filter_quality,
- color_params,
- std::move(context_provider_wrapper),
- std::move(resource_dispatcher),
- is_origin_top_left) {
- type_ = kTextureGpuMemoryBuffer;
- }
-
- ~CanvasResourceProviderTextureGpuMemoryBuffer() override = default;
- bool SupportsDirectCompositing() const override { return true; }
- bool SupportsSingleBuffering() const override { return true; }
-
- private:
- scoped_refptr<CanvasResource> CreateResource() final {
- TRACE_EVENT0(
- "blink",
- "CanvasResourceProviderTextureGpuMemoreBuffer::CreateResource");
- constexpr bool is_accelerated = true;
- return CanvasResourceGpuMemoryBuffer::Create(
- Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(),
- FilterQuality(), is_accelerated);
- }
-
- scoped_refptr<CanvasResource> ProduceCanvasResource() final {
- TRACE_EVENT0(
- "blink",
- "CanvasResourceProviderTextureGpuMemoreBuffer::ProduceCanvasResource");
- DCHECK(GetSkSurface());
-
- if (IsGpuContextLost())
- return nullptr;
-
- scoped_refptr<CanvasResource> output_resource = NewOrRecycledResource();
- if (!output_resource) {
- // GpuMemoryBuffer creation failed, fallback to Texture resource
- return CanvasResourceProviderTexture::ProduceCanvasResource();
- }
-
- auto paint_image = MakeImageSnapshot();
- if (!paint_image)
- return nullptr;
- DCHECK(paint_image.GetSkImage()->isTextureBacked());
-
- GrBackendTexture backend_texture =
- paint_image.GetSkImage()->getBackendTexture(true);
- DCHECK(backend_texture.isValid());
-
- GrGLTextureInfo info;
- if (!backend_texture.getGLTextureInfo(&info))
- return nullptr;
-
- GLuint skia_texture_id = info.fID;
- output_resource->CopyFromTexture(skia_texture_id,
- ColorParams().GLUnsizedInternalFormat(),
- ColorParams().GLType());
- return output_resource;
- }
-};
-
// * Renders to a Skia RAM-backed bitmap.
// * Mailboxing is not supported : cannot be directly composited.
class CanvasResourceProviderBitmap : public CanvasResourceProvider {
@@ -251,66 +69,6 @@ class CanvasResourceProviderBitmap : public CanvasResourceProvider {
}
};
-// * Renders to a ram memory buffer managed by Skia
-// * Uses GpuMemoryBuffer to pass frames to the compositor
-// * Layers are overlay candidates
-class CanvasResourceProviderBitmapGpuMemoryBuffer final
- : public CanvasResourceProviderBitmap {
- public:
- CanvasResourceProviderBitmapGpuMemoryBuffer(
- const IntSize& size,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
- : CanvasResourceProviderBitmap(size,
- filter_quality,
- color_params,
- std::move(context_provider_wrapper),
- std::move(resource_dispatcher)) {
- type_ = kBitmapGpuMemoryBuffer;
- }
-
- ~CanvasResourceProviderBitmapGpuMemoryBuffer() override = default;
- bool SupportsDirectCompositing() const override { return true; }
- bool SupportsSingleBuffering() const override { return true; }
-
- private:
- scoped_refptr<CanvasResource> CreateResource() final {
- TRACE_EVENT0("blink",
- "CanvasResourceProviderBitmapGpuMemoryBuffer::CreateResource");
-
- constexpr bool is_accelerated = false;
- return CanvasResourceGpuMemoryBuffer::Create(
- Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(),
- FilterQuality(), is_accelerated);
- }
-
- scoped_refptr<CanvasResource> ProduceCanvasResource() final {
- TRACE_EVENT0(
- "blink",
- "CanvasResourceProviderBitmapGpuMemoryBuffer::ProduceCanvasResource");
-
- DCHECK(GetSkSurface());
-
- scoped_refptr<CanvasResource> output_resource = NewOrRecycledResource();
- if (!output_resource) {
- // Not compositable without a GpuMemoryBuffer
- return nullptr;
- }
-
- auto paint_image = MakeImageSnapshot();
- if (!paint_image)
- return nullptr;
- DCHECK(!paint_image.GetSkImage()->isTextureBacked());
-
- output_resource->TakeSkImage(paint_image.GetSkImage());
-
- return output_resource;
- }
-};
-
// * Renders to a shared memory bitmap.
// * Uses SharedBitmaps to pass frames directly to the compositor.
class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
@@ -362,99 +120,6 @@ class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
}
};
-// * Renders to a GpuMemoryBuffer-backed texture used to create a SkSurface.
-// * Layers are overlay candidates
-class CanvasResourceProviderDirectGpuMemoryBuffer final
- : public CanvasResourceProvider {
- public:
- CanvasResourceProviderDirectGpuMemoryBuffer(
- const IntSize& size,
- unsigned msaa_sample_count,
- SkFilterQuality filter_quality,
- const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
- bool is_origin_top_left)
- : CanvasResourceProvider(kDirectGpuMemoryBuffer,
- size,
- msaa_sample_count,
- filter_quality,
- color_params,
- is_origin_top_left,
- std::move(context_provider_wrapper),
- std::move(resource_dispatcher)) {
- constexpr bool is_accelerated = true;
- resource_ = CanvasResourceGpuMemoryBuffer::Create(
- Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(),
- FilterQuality(), is_accelerated);
- }
-
- ~CanvasResourceProviderDirectGpuMemoryBuffer() override = default;
- bool IsValid() const final { return GetSkSurface() && !IsGpuContextLost(); }
- bool IsAccelerated() const final { return true; }
- bool SupportsDirectCompositing() const override { return true; }
- bool SupportsSingleBuffering() const override { return true; }
-
- private:
- GLuint GetBackingTextureHandleForOverwrite() override {
- return resource_->GetBackingTextureHandleForOverwrite();
- }
-
- scoped_refptr<CanvasResource> CreateResource() final {
- TRACE_EVENT0("blink",
- "CanvasResourceProviderDirectGpuMemoryBuffer::CreateResource");
- DCHECK(resource_);
- return resource_;
- }
-
- scoped_refptr<CanvasResource> ProduceCanvasResource() final {
- TRACE_EVENT0(
- "blink",
- "CanvasResourceProviderDirectGpuMemoryBuffer::ProduceCanvasResource");
- if (IsGpuContextLost())
- return nullptr;
- FlushSkia();
-
- auto* gl = ContextGL();
- DCHECK(gl);
- gl->Flush();
-
- return NewOrRecycledResource();
- }
-
- scoped_refptr<StaticBitmapImage> Snapshot() override {
- TRACE_EVENT0("blink",
- "CanvasResourceProviderDirectGpuMemoryBuffer::Snapshot");
- return SnapshotInternal();
- }
-
- sk_sp<SkSurface> CreateSkSurface() const override {
- if (IsGpuContextLost() || !resource_)
- return nullptr;
- auto* gr = GetGrContext();
- DCHECK(gr);
-
- GrGLTextureInfo texture_info = {};
- texture_info.fID = resource_->GetBackingTextureHandleForOverwrite();
- texture_info.fTarget = GL_TEXTURE_2D;
- // Skia requires a sized internal format.
- texture_info.fFormat = ColorParams().GLSizedInternalFormat();
-
- const GrBackendTexture backend_texture(Size().Width(), Size().Height(),
- GrMipMapped::kNo, texture_info);
-
- auto surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
- gr, backend_texture, GetGrSurfaceOrigin(), GetMSAASampleCount(),
- ColorParams().GetSkColorType(),
- ColorParams().GetSkColorSpaceForSkSurfaces(),
- ColorParams().GetSkSurfaceProps());
- return surface;
- }
-
- scoped_refptr<CanvasResource> resource_;
-};
-
// * Renders to a SharedImage, which manages memory internally.
// * Layers are overlay candidates.
class CanvasResourceProviderSharedImage : public CanvasResourceProvider {
@@ -913,13 +578,7 @@ enum class CanvasResourceType {
kDirect3DSwapChain,
kDirect2DSwapChain,
kDirect3DGpuMemoryBuffer,
- // TODO(khushalsagar): Delete Direct2D and TextureGpuMemoryBuffer types once
- // shared image for single buffered canvas sticks.
- kDirect2DGpuMemoryBuffer,
- kTextureGpuMemoryBuffer,
- kBitmapGpuMemoryBuffer,
kSharedBitmap,
- kTexture,
kBitmap,
kSharedImage,
};
@@ -932,54 +591,29 @@ const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
static const Vector<CanvasResourceType> kAcceleratedFallbackList({
CanvasResourceType::kSharedImage,
- CanvasResourceType::kTexture,
// Fallback to software
CanvasResourceType::kBitmap,
});
- static const Vector<CanvasResourceType> kSoftwareCompositedFallbackList({
- CanvasResourceType::kSharedImage,
- CanvasResourceType::kBitmapGpuMemoryBuffer,
- CanvasResourceType::kSharedBitmap,
- // Fallback to no direct compositing support
- CanvasResourceType::kBitmap,
- });
-
- static const Vector<CanvasResourceType> kAcceleratedCompositedFallbackList({
+ static const Vector<CanvasResourceType> kCompositedFallbackList({
CanvasResourceType::kSharedImage,
- CanvasResourceType::kTextureGpuMemoryBuffer,
- CanvasResourceType::kTexture,
- // Fallback to software composited
- // (|kSoftwareCompositedFallbackList|).
- CanvasResourceType::kBitmapGpuMemoryBuffer,
CanvasResourceType::kSharedBitmap,
// Fallback to no direct compositing support
CanvasResourceType::kBitmap,
});
- DCHECK(std::equal(kAcceleratedCompositedFallbackList.begin() + 3,
- kAcceleratedCompositedFallbackList.end(),
- kSoftwareCompositedFallbackList.begin() + 1,
- kSoftwareCompositedFallbackList.end()));
static const Vector<CanvasResourceType> kAcceleratedDirect2DFallbackList({
+ // Needed for low latency canvas on Windows.
CanvasResourceType::kDirect2DSwapChain,
+ // The rest is equal to |kCompositedFallbackList|.
CanvasResourceType::kSharedImage,
- CanvasResourceType::kDirect2DGpuMemoryBuffer,
- // The rest is equal to |kAcceleratedCompositedFallbackList|.
- CanvasResourceType::kTextureGpuMemoryBuffer,
- CanvasResourceType::kTexture,
- // Fallback to software composited
- CanvasResourceType::kBitmapGpuMemoryBuffer,
CanvasResourceType::kSharedBitmap,
- // Fallback to no direct compositing support
CanvasResourceType::kBitmap,
});
- // TODO(khushalsagar): Change this DCHECK after kDirect2DGpuMemoryBuffer and
- // kTextureGpuMemoryBuffer are removed.
- DCHECK(std::equal(kAcceleratedDirect2DFallbackList.begin() + 3,
+ DCHECK(std::equal(kAcceleratedDirect2DFallbackList.begin() + 1,
kAcceleratedDirect2DFallbackList.end(),
- kAcceleratedCompositedFallbackList.begin() + 1,
- kAcceleratedCompositedFallbackList.end()));
+ kCompositedFallbackList.begin(),
+ kCompositedFallbackList.end()));
static const Vector<CanvasResourceType> kAcceleratedDirect3DFallbackList({
// This is used with single-buffered WebGL where the resource comes
@@ -988,35 +622,27 @@ const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
// compositor.
CanvasResourceType::kDirect3DSwapChain,
CanvasResourceType::kDirect3DGpuMemoryBuffer,
- // The rest is equal to |kAcceleratedDirect2DFallbackList|.
+ // The rest is equal to |kCompositedFallbackList|.
CanvasResourceType::kSharedImage,
- CanvasResourceType::kDirect2DGpuMemoryBuffer,
- CanvasResourceType::kTextureGpuMemoryBuffer,
- CanvasResourceType::kTexture,
- // Fallback to software composited
- CanvasResourceType::kBitmapGpuMemoryBuffer,
CanvasResourceType::kSharedBitmap,
- // Fallback to no direct compositing support
CanvasResourceType::kBitmap,
});
- // TODO(khushalsagar): Change this DCHECK after kDirect2DGpuMemoryBuffer and
- // kTextureGpuMemoryBuffer are removed.
DCHECK(std::equal(kAcceleratedDirect3DFallbackList.begin() + 2,
kAcceleratedDirect3DFallbackList.end(),
- kAcceleratedDirect2DFallbackList.begin() + 1,
- kAcceleratedDirect2DFallbackList.end()));
+ kCompositedFallbackList.begin(),
+ kCompositedFallbackList.end()));
switch (usage) {
case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
return kSoftwareFallbackList;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedResourceUsage:
- return kSoftwareCompositedFallbackList;
+ return kCompositedFallbackList;
case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
return kAcceleratedFallbackList;
case CanvasResourceProvider::ResourceUsage::
kAcceleratedCompositedResourceUsage:
- return kAcceleratedCompositedFallbackList;
+ return kCompositedFallbackList;
case CanvasResourceProvider::ResourceUsage::
kAcceleratedDirect2DResourceUsage:
return kAcceleratedDirect2DFallbackList;
@@ -1025,10 +651,11 @@ const Vector<CanvasResourceType>& GetResourceTypeFallbackList(
return kAcceleratedDirect3DFallbackList;
case CanvasResourceProvider::ResourceUsage::
kSoftwareCompositedDirect2DResourceUsage:
- return kSoftwareCompositedFallbackList;
+ return kCompositedFallbackList;
}
NOTREACHED();
}
+
} // unnamed namespace
std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::CreateForCanvas(
@@ -1122,63 +749,19 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
size, filter_quality, color_params, context_provider_wrapper,
resource_dispatcher);
break;
- case CanvasResourceType::kTextureGpuMemoryBuffer:
- if (!is_gpu_memory_buffer_image_allowed)
- continue;
- DCHECK_EQ(color_params.GLUnsizedInternalFormat(),
- gpu::InternalFormatForGpuMemoryBufferFormat(
- color_params.GetBufferFormat()));
- provider =
- std::make_unique<CanvasResourceProviderTextureGpuMemoryBuffer>(
- size, msaa_sample_count, filter_quality, color_params,
- context_provider_wrapper, resource_dispatcher,
- is_origin_top_left);
- break;
- case CanvasResourceType::kDirect2DGpuMemoryBuffer:
- if (!is_gpu_memory_buffer_image_allowed)
- continue;
- DCHECK_EQ(color_params.GLUnsizedInternalFormat(),
- gpu::InternalFormatForGpuMemoryBufferFormat(
- color_params.GetBufferFormat()));
- provider =
- std::make_unique<CanvasResourceProviderDirectGpuMemoryBuffer>(
- size, msaa_sample_count, filter_quality, color_params,
- context_provider_wrapper, resource_dispatcher,
- is_origin_top_left);
- break;
case CanvasResourceType::kDirect3DGpuMemoryBuffer:
if (!is_gpu_memory_buffer_image_allowed)
continue;
- DCHECK_EQ(color_params.GLUnsizedInternalFormat(),
- gpu::InternalFormatForGpuMemoryBufferFormat(
- color_params.GetBufferFormat()));
provider = std::make_unique<CanvasResourceProviderPassThrough>(
size, filter_quality, color_params, context_provider_wrapper,
resource_dispatcher);
break;
- case CanvasResourceType::kBitmapGpuMemoryBuffer:
- if (!is_gpu_memory_buffer_image_allowed ||
- !Platform::Current()->GetGpuMemoryBufferManager()) {
- continue;
- }
- provider =
- std::make_unique<CanvasResourceProviderBitmapGpuMemoryBuffer>(
- size, filter_quality, color_params, context_provider_wrapper,
- resource_dispatcher);
- break;
case CanvasResourceType::kSharedBitmap:
if (!resource_dispatcher)
continue;
provider = std::make_unique<CanvasResourceProviderSharedBitmap>(
size, filter_quality, color_params, resource_dispatcher);
break;
- case CanvasResourceType::kTexture:
- if (!context_provider_wrapper)
- continue;
- provider = std::make_unique<CanvasResourceProviderTexture>(
- size, msaa_sample_count, filter_quality, color_params,
- context_provider_wrapper, resource_dispatcher, is_origin_top_left);
- break;
case CanvasResourceType::kBitmap:
provider = std::make_unique<CanvasResourceProviderBitmap>(
size, filter_quality, color_params, context_provider_wrapper,
@@ -1216,7 +799,8 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
const bool is_accelerated =
usage == ResourceUsage::kAcceleratedResourceUsage ||
usage == ResourceUsage::kAcceleratedCompositedResourceUsage ||
- usage == ResourceUsage::kAcceleratedDirect2DResourceUsage;
+ usage == ResourceUsage::kAcceleratedDirect2DResourceUsage ||
+ usage == ResourceUsage::kAcceleratedDirect3DResourceUsage;
// If the rendering will be in software and we don't have GMB support,
// fallback to bitmap provider type.
@@ -1244,49 +828,6 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
return nullptr;
}
-std::unique_ptr<CanvasResourceProvider>
-CanvasResourceProvider::CreateForTesting(
- const IntSize& size,
- ResourceProviderType type,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
- unsigned msaa_sample_count,
- const CanvasColorParams& color_params,
- uint8_t presentation_mode,
- base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher,
- bool is_origin_top_left) {
- switch (type) {
- case CanvasResourceProvider::kSharedBitmap:
- DCHECK(resource_dispatcher);
- return std::make_unique<CanvasResourceProviderSharedBitmap>(
- size, kLow_SkFilterQuality, color_params, resource_dispatcher);
- case CanvasResourceProvider::kTexture:
- DCHECK(context_provider_wrapper);
- return std::make_unique<CanvasResourceProviderTexture>(
- size, msaa_sample_count, kLow_SkFilterQuality, color_params,
- context_provider_wrapper, resource_dispatcher, is_origin_top_left);
- case CanvasResourceProvider::kBitmap:
- return std::make_unique<CanvasResourceProviderBitmap>(
- size, kLow_SkFilterQuality, color_params, context_provider_wrapper,
- resource_dispatcher);
- case CanvasResourceProvider::kSharedImage:
- return std::make_unique<CanvasResourceProviderSharedImage>(
- size, msaa_sample_count, kLow_SkFilterQuality, color_params,
- context_provider_wrapper, resource_dispatcher, is_origin_top_left,
- false, false, true);
- case CanvasResourceProvider::kTextureGpuMemoryBuffer:
- return std::make_unique<CanvasResourceProviderTextureGpuMemoryBuffer>(
- size, msaa_sample_count, kLow_SkFilterQuality, color_params,
- context_provider_wrapper, resource_dispatcher, is_origin_top_left);
- case CanvasResourceProvider::kBitmapGpuMemoryBuffer:
- return std::make_unique<CanvasResourceProviderBitmapGpuMemoryBuffer>(
- size, kLow_SkFilterQuality, color_params, context_provider_wrapper,
- resource_dispatcher);
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider {
public:
CanvasImageProvider(cc::ImageDecodeCache* cache_n32,
@@ -1609,8 +1150,9 @@ void CanvasResourceProvider::RecycleResource(
// Need to check HasOneRef() because if there are outstanding references to
// the resource, it cannot be safely recycled.
if (resource->HasOneRef() && resource_recycling_enabled_ &&
- !is_single_buffered_)
+ !is_single_buffered_) {
canvas_resources_.push_back(std::move(resource));
+ }
}
void CanvasResourceProvider::SetResourceRecyclingEnabled(bool value) {
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 e504b48e882..c4b6c912330 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
@@ -110,16 +110,6 @@ class PLATFORM_EXPORT CanvasResourceProvider
base::WeakPtr<CanvasResourceDispatcher>,
bool is_origin_top_left = true);
- static std::unique_ptr<CanvasResourceProvider> CreateForTesting(
- const IntSize&,
- ResourceProviderType,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
- unsigned msaa_sample_count,
- const CanvasColorParams&,
- uint8_t presentation_mode,
- base::WeakPtr<CanvasResourceDispatcher>,
- bool is_origin_top_left = true);
-
// Use Snapshot() for capturing a frame that is intended to be displayed via
// the compositor. Cases that are destined to be transferred via a
// TransferableResource should call ProduceCanvasResource() instead.
@@ -196,6 +186,10 @@ class PLATFORM_EXPORT CanvasResourceProvider
// are modified externally from the provider's SkSurface.
virtual void NotifyTexParamsModified(const CanvasResource* resource) {}
+ size_t cached_resources_count_for_testing() const {
+ return canvas_resources_.size();
+ }
+
protected:
gpu::gles2::GLES2Interface* ContextGL() const;
GrContext* GetGrContext() const;
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 5a353402d29..1f0eb8f969d 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
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/test/gpu_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"
using testing::_;
@@ -32,80 +33,7 @@ class MockCanvasResourceDispatcherClient
public:
MockCanvasResourceDispatcherClient() = default;
- MOCK_METHOD0(BeginFrame, void());
-};
-
-class MockWebGraphisContext3DProviderWrapper
- : public WebGraphicsContext3DProvider {
- public:
- MockWebGraphisContext3DProviderWrapper(cc::ImageDecodeCache* cache = nullptr)
- : image_decode_cache_(cache ? cache : &stub_image_decode_cache_) {
- // enable all gpu features.
- for (unsigned feature = 0; feature < gpu::NUMBER_OF_GPU_FEATURE_TYPES;
- ++feature) {
- gpu_feature_info_.status_values[feature] = gpu::kGpuFeatureStatusEnabled;
- }
- }
- ~MockWebGraphisContext3DProviderWrapper() override = default;
-
- GrContext* GetGrContext() override {
- return GetTestContextProvider()->GrContext();
- }
-
- const gpu::Capabilities& GetCapabilities() const override {
- return capabilities_;
- }
- void SetCapabilities(const gpu::Capabilities& c) { capabilities_ = c; }
-
- const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override {
- return gpu_feature_info_;
- }
-
- const WebglPreferences& GetWebglPreferences() const override {
- return webgl_preferences_;
- }
-
- viz::GLHelper* GetGLHelper() override { return nullptr; }
-
- gpu::gles2::GLES2Interface* ContextGL() override {
- return GetTestContextProvider()->ContextGL();
- }
-
- gpu::webgpu::WebGPUInterface* WebGPUInterface() override { return nullptr; }
-
- scoped_refptr<viz::TestContextProvider> GetTestContextProvider() {
- if (!test_context_provider_) {
- test_context_provider_ = viz::TestContextProvider::Create();
- // Needed for CanvasResourceProviderDirect2DGpuMemoryBuffer.
- test_context_provider_->UnboundTestContextGL()
- ->set_support_texture_format_bgra8888(true);
- test_context_provider_->BindToCurrentThread();
- }
- return test_context_provider_;
- }
-
- bool BindToCurrentThread() override { return false; }
- void SetLostContextCallback(base::RepeatingClosure) override {}
- void SetErrorMessageCallback(
- base::RepeatingCallback<void(const char*, int32_t id)>) override {}
- cc::ImageDecodeCache* ImageDecodeCache(SkColorType color_type) override {
- return image_decode_cache_;
- }
- viz::TestSharedImageInterface* SharedImageInterface() override {
- return GetTestContextProvider()->SharedImageInterface();
- }
- void CopyVideoFrame(media::PaintCanvasVideoRenderer* video_render,
- media::VideoFrame* video_frame,
- cc::PaintCanvas* canvas) override {}
-
- private:
- cc::StubDecodeCache stub_image_decode_cache_;
-
- scoped_refptr<viz::TestContextProvider> test_context_provider_;
- gpu::Capabilities capabilities_;
- gpu::GpuFeatureInfo gpu_feature_info_;
- WebglPreferences webgl_preferences_;
- cc::ImageDecodeCache* image_decode_cache_;
+ MOCK_METHOD0(BeginFrame, bool());
};
} // anonymous namespace
@@ -113,15 +41,9 @@ class MockWebGraphisContext3DProviderWrapper
class CanvasResourceProviderTest : public Test {
public:
void SetUp() override {
- // Install our mock GL context so that it gets served by SharedGpuContext.
- auto factory = [](bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- // Unretained is safe since TearDown() cleans up the SharedGpuContext.
- return std::make_unique<MockWebGraphisContext3DProviderWrapper>();
- };
- SharedGpuContext::SetContextProviderFactoryForTesting(
- WTF::BindRepeating(factory));
+ test_context_provider_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(test_context_provider_.get(),
+ &image_decode_cache_);
context_provider_wrapper_ = SharedGpuContext::ContextProviderWrapper();
}
@@ -138,7 +60,7 @@ class CanvasResourceProviderTest : public Test {
auto capabilities = context_provider->GetCapabilities();
capabilities.gpu_memory_buffer_formats.Add(buffer_format);
- static_cast<MockWebGraphisContext3DProviderWrapper*>(context_provider)
+ static_cast<FakeWebGraphicsContext3DProvider*>(context_provider)
->SetCapabilities(capabilities);
}
@@ -147,7 +69,7 @@ class CanvasResourceProviderTest : public Test {
auto capabilities = context_provider->GetCapabilities();
capabilities.texture_storage_image = true;
capabilities.max_texture_size = 1024;
- static_cast<MockWebGraphisContext3DProviderWrapper*>(context_provider)
+ static_cast<FakeWebGraphicsContext3DProvider*>(context_provider)
->SetCapabilities(capabilities);
}
@@ -159,20 +81,24 @@ class CanvasResourceProviderTest : public Test {
}
protected:
+ cc::StubDecodeCache image_decode_cache_;
+ scoped_refptr<viz::TestContextProvider> test_context_provider_;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform_;
};
-TEST_F(CanvasResourceProviderTest,
- CanvasResourceProviderTextureGpuMemoryBuffer) {
+TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
const IntSize kSize(10, 10);
const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
kRGBA8CanvasPixelFormat, kNonOpaque);
EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
+ EnsureOverlaysSupported();
- auto provider = CanvasResourceProvider::CreateForTesting(
- kSize, CanvasResourceProvider::kTextureGpuMemoryBuffer,
- context_provider_wrapper_, 0 /* msaa_sample_count */, kColorParams,
+ auto provider = CanvasResourceProvider::Create(
+ kSize,
+ CanvasResourceProvider::ResourceUsage::kAcceleratedDirect2DResourceUsage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kMedium_SkFilterQuality, kColorParams,
CanvasResourceProvider::kAllowImageChromiumPresentationMode,
nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
@@ -216,12 +142,12 @@ TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
EXPECT_FALSE(provider->IsSingleBuffered());
}
-TEST_F(CanvasResourceProviderTest,
- CanvasResourceProviderBitmapGpuMemoryBuffer) {
+TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
const IntSize kSize(10, 10);
const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
kRGBA8CanvasPixelFormat, kNonOpaque);
EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
+ EnsureOverlaysSupported();
auto provider = CanvasResourceProvider::Create(
kSize,
@@ -245,15 +171,19 @@ TEST_F(CanvasResourceProviderTest,
EXPECT_FALSE(provider->IsSingleBuffered());
}
-TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedImage) {
+TEST_F(CanvasResourceProviderTest,
+ CanvasResourceProviderSharedImageResourceRecycling) {
const IntSize kSize(10, 10);
const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
kRGBA8CanvasPixelFormat, kNonOpaque);
EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
- auto provider = CanvasResourceProvider::CreateForTesting(
- kSize, CanvasResourceProvider::kSharedImage, context_provider_wrapper_,
- 0 /* msaa_sample_count */, kColorParams,
+ auto provider = CanvasResourceProvider::Create(
+ kSize,
+ CanvasResourceProvider::ResourceUsage::
+ kAcceleratedCompositedResourceUsage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kMedium_SkFilterQuality, kColorParams,
CanvasResourceProvider::kAllowImageChromiumPresentationMode,
nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
@@ -302,9 +232,12 @@ TEST_F(CanvasResourceProviderTest,
kRGBA8CanvasPixelFormat, kNonOpaque);
EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
- auto provider = CanvasResourceProvider::CreateForTesting(
- kSize, CanvasResourceProvider::kSharedImage, context_provider_wrapper_,
- 0 /* msaa_sample_count */, kColorParams,
+ auto provider = CanvasResourceProvider::Create(
+ kSize,
+ CanvasResourceProvider::ResourceUsage::
+ kAcceleratedCompositedResourceUsage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kMedium_SkFilterQuality, kColorParams,
CanvasResourceProvider::kAllowImageChromiumPresentationMode,
nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
ASSERT_TRUE(provider->IsValid());
@@ -332,20 +265,23 @@ TEST_F(CanvasResourceProviderTest,
TEST_F(CanvasResourceProviderTest,
CanvasResourceProviderSharedImageCopyOnWriteDisabled) {
- auto* mock_context = static_cast<MockWebGraphisContext3DProviderWrapper*>(
+ auto* fake_context = static_cast<FakeWebGraphicsContext3DProvider*>(
context_provider_wrapper_->ContextProvider());
- auto caps = mock_context->GetCapabilities();
+ auto caps = fake_context->GetCapabilities();
caps.disable_2d_canvas_copy_on_write = true;
- mock_context->SetCapabilities(caps);
+ fake_context->SetCapabilities(caps);
const IntSize kSize(10, 10);
const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
kRGBA8CanvasPixelFormat, kNonOpaque);
EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
- auto provider = CanvasResourceProvider::CreateForTesting(
- kSize, CanvasResourceProvider::kSharedImage, context_provider_wrapper_,
- 0 /* msaa_sample_count */, kColorParams,
+ auto provider = CanvasResourceProvider::Create(
+ kSize,
+ CanvasResourceProvider::ResourceUsage::
+ kAcceleratedCompositedResourceUsage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kMedium_SkFilterQuality, kColorParams,
CanvasResourceProvider::kAllowImageChromiumPresentationMode,
nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
ASSERT_TRUE(provider->IsValid());
@@ -482,7 +418,7 @@ TEST_F(CanvasResourceProviderTest,
ExternalCanvasResource::Create(
mailbox, kSize, GL_TEXTURE_2D, kColorParams,
SharedGpuContext::ContextProviderWrapper(), provider->CreateWeakPtr(),
- kNone_SkFilterQuality);
+ kMedium_SkFilterQuality);
// NewOrRecycledResource() would return nullptr before an ImportResource().
EXPECT_TRUE(provider->ImportResource(resource));
@@ -491,4 +427,111 @@ TEST_F(CanvasResourceProviderTest,
EXPECT_EQ(provider->NewOrRecycledResource(), resource);
}
+// Verifies that Accelerated Direct 3D resources are backed by SharedImages.
+// https://crbug.com/985366
+TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3D) {
+ const IntSize kSize(10, 10);
+ const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
+ kRGBA8CanvasPixelFormat, kNonOpaque);
+
+ auto provider = CanvasResourceProvider::Create(
+ kSize,
+ CanvasResourceProvider::ResourceUsage::kAcceleratedDirect3DResourceUsage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+
+ EXPECT_EQ(provider->Size(), kSize);
+ EXPECT_TRUE(provider->IsValid());
+ EXPECT_TRUE(provider->IsAccelerated());
+ EXPECT_TRUE(provider->SupportsDirectCompositing());
+ EXPECT_FALSE(provider->SupportsSingleBuffering());
+ EXPECT_EQ(provider->ColorParams().ColorSpace(), kColorParams.ColorSpace());
+ EXPECT_EQ(provider->ColorParams().PixelFormat(), kColorParams.PixelFormat());
+ EXPECT_EQ(provider->ColorParams().GetOpacityMode(),
+ kColorParams.GetOpacityMode());
+
+ EXPECT_FALSE(provider->IsSingleBuffered());
+ provider->TryEnableSingleBuffering();
+ EXPECT_FALSE(provider->IsSingleBuffered());
+
+ auto resource = provider->ProduceCanvasResource();
+ viz::TransferableResource transferable_resource;
+ std::unique_ptr<viz::SingleReleaseCallback> callback;
+ resource->PrepareTransferableResource(&transferable_resource, &callback,
+ kOrderingBarrier);
+ EXPECT_TRUE(transferable_resource.mailbox_holder.mailbox.IsSharedImage());
+ EXPECT_FALSE(transferable_resource.is_overlay_candidate);
+ callback->Run(gpu::SyncToken(), true /* is_lost */);
+}
+
+TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
+ const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
+ kRGBA8CanvasPixelFormat, kNonOpaque);
+ const int max_texture_size = context_provider_wrapper_->ContextProvider()
+ ->GetCapabilities()
+ .max_texture_size;
+ EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
+ EnsureOverlaysSupported();
+
+ for (int i = 0;
+ i < static_cast<int>(CanvasResourceProvider::ResourceUsage::kMaxValue);
+ ++i) {
+ SCOPED_TRACE(i);
+ auto usage = static_cast<CanvasResourceProvider::ResourceUsage>(i);
+ bool should_support_compositing = false;
+ switch (usage) {
+ case CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage:
+ should_support_compositing = false;
+ break;
+ case CanvasResourceProvider::ResourceUsage::
+ kSoftwareCompositedResourceUsage:
+ FALLTHROUGH;
+ case CanvasResourceProvider::ResourceUsage::
+ kSoftwareCompositedDirect2DResourceUsage:
+ should_support_compositing = PlatformSupportsGMBs();
+ break;
+ case CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage:
+ FALLTHROUGH;
+ case CanvasResourceProvider::ResourceUsage::
+ kAcceleratedCompositedResourceUsage:
+ FALLTHROUGH;
+ case CanvasResourceProvider::ResourceUsage::
+ kAcceleratedDirect2DResourceUsage:
+ FALLTHROUGH;
+ case CanvasResourceProvider::ResourceUsage::
+ kAcceleratedDirect3DResourceUsage:
+ should_support_compositing = true;
+ break;
+ }
+
+ auto provider = CanvasResourceProvider::Create(
+ IntSize(max_texture_size - 1, max_texture_size), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ EXPECT_EQ(provider->SupportsDirectCompositing(),
+ should_support_compositing);
+
+ provider = CanvasResourceProvider::Create(
+ IntSize(max_texture_size, max_texture_size), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ EXPECT_EQ(provider->SupportsDirectCompositing(),
+ should_support_compositing);
+
+ provider = CanvasResourceProvider::Create(
+ IntSize(max_texture_size + 1, max_texture_size), usage,
+ context_provider_wrapper_, 0 /* msaa_sample_count */,
+ kLow_SkFilterQuality, kColorParams,
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode,
+ nullptr /* resource_dispatcher */, true /* is_origin_top_left */);
+ EXPECT_FALSE(provider->SupportsDirectCompositing());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
index 3dc0a13fc4a..03156bbb3cb 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
@@ -20,382 +20,9 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkSurface.h"
-using testing::_;
-using testing::AtLeast;
-using testing::Pointee;
-using testing::Return;
-using testing::SetArrayArgument;
-using testing::Test;
-
namespace blink {
-class MockGLES2InterfaceWithMailboxSupport : public FakeGLES2Interface {
- public:
- MOCK_METHOD2(ProduceTextureDirectCHROMIUM, void(GLuint, GLbyte*));
- MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
- MOCK_METHOD1(GenSyncTokenCHROMIUM, void(GLbyte*));
- MOCK_METHOD4(CreateImageCHROMIUM,
- GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
- MOCK_METHOD2(BindTexture, void(GLenum, GLuint));
-};
-
-class CanvasResourceTest : public Test {
- public:
- void SetUp() override {
- // Install our mock GL context so that it gets served by SharedGpuContext.
- auto factory = [](FakeGLES2Interface* gl, bool* gpu_compositing_disabled)
- -> std::unique_ptr<WebGraphicsContext3DProvider> {
- *gpu_compositing_disabled = false;
- return std::make_unique<FakeWebGraphicsContext3DProvider>(gl);
- };
- SharedGpuContext::SetContextProviderFactoryForTesting(
- WTF::BindRepeating(factory, WTF::Unretained(&gl_)));
- context_provider_wrapper_ = SharedGpuContext::ContextProviderWrapper();
- }
-
- void TearDown() override { SharedGpuContext::ResetForTesting(); }
-
- GrContext* GetGrContext() {
- return context_provider_wrapper_->ContextProvider()->GetGrContext();
- }
-
- protected:
- MockGLES2InterfaceWithMailboxSupport gl_;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
-};
-
-gpu::SyncToken GenTestSyncToken(int id) {
- gpu::SyncToken token;
- token.Set(gpu::CommandBufferNamespace::GPU_IO,
- gpu::CommandBufferId::FromUnsafeValue(id), 1);
- return token;
-}
-
-TEST_F(CanvasResourceTest, SkiaResourceNoMailboxLeak) {
- testing::InSequence s;
- SkImageInfo image_info =
- SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> surface =
- SkSurface::MakeRenderTarget(GetGrContext(), SkBudgeted::kYes, image_info);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_TRUE(!!context_provider_wrapper_);
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- StaticBitmapImage::Create(surface->makeImageSnapshot(),
- context_provider_wrapper_),
- nullptr, kLow_SkFilterQuality, CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- gpu::Mailbox test_mailbox;
- test_mailbox.name[0] = 1;
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
- .WillOnce(SetArrayArgument<1>(
- test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
- EXPECT_CALL(gl_, BindTexture(GL_TEXTURE_2D, _)).Times(2);
- EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_));
- resource->GetOrCreateGpuMailbox(kUnverifiedSyncToken);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // No expected call to DeleteTextures becaus skia recycles
- // No expected call to ProduceTextureDirectCHROMIUM(0, *) because
- // mailbox is cached by GraphicsContext3DUtils and therefore does not need to
- // be orphaned.
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(0, _)).Times(0);
- resource = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Purging skia's resource cache will finally delete the GrTexture, resulting
- // in the mailbox being orphaned via ProduceTextureDirectCHROMIUM.
- EXPECT_CALL(gl_,
- ProduceTextureDirectCHROMIUM(0, Pointee(test_mailbox.name[0])))
- .Times(0);
- GetGrContext()->performDeferredCleanup(std::chrono::milliseconds(0));
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-}
-
-TEST_F(CanvasResourceTest, GpuMemoryBufferSyncTokenRefresh) {
- testing::InSequence s;
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- constexpr GLuint image_id = 1;
- const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, BindTexture(texture_target, _));
- if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint image_2d_id = 2;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(image_2d_id));
- EXPECT_CALL(gl_, BindTexture(GL_TEXTURE_2D, _));
- }
- scoped_refptr<CanvasResource> resource =
- CanvasResourceGpuMemoryBuffer::Create(
- IntSize(10, 10), CanvasColorParams(),
- SharedGpuContext::ContextProviderWrapper(),
- nullptr, // Resource provider
- kLow_SkFilterQuality, true /*is_accelerated*/);
-
- EXPECT_TRUE(bool(resource));
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- gpu::Mailbox test_mailbox;
- test_mailbox.name[0] = 1;
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
- .WillOnce(SetArrayArgument<1>(
- test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
- resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- const gpu::SyncToken reference_token1 = GenTestSyncToken(1);
- EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_))
- .WillOnce(SetArrayArgument<0>(
- reinterpret_cast<const GLbyte*>(&reference_token1),
- reinterpret_cast<const GLbyte*>(&reference_token1 + 1)));
- gpu::SyncToken actual_token = resource->GetSyncToken();
- EXPECT_EQ(actual_token, reference_token1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Grabbing the mailbox again without making any changes must not result in
- // a sync token refresh
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _)).Times(0);
- EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_)).Times(0);
- resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
- actual_token = resource->GetSyncToken();
- EXPECT_EQ(actual_token, reference_token1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Grabbing the mailbox again after a content change must result in
- // a sync token refresh, but the mailbox gets re-used.
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _)).Times(0);
- const gpu::SyncToken reference_token2 = GenTestSyncToken(2);
- EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_))
- .WillOnce(SetArrayArgument<0>(
- reinterpret_cast<const GLbyte*>(&reference_token2),
- reinterpret_cast<const GLbyte*>(&reference_token2 + 1)));
- resource->CopyFromTexture(1, // source texture id
- GL_RGBA, GL_UNSIGNED_BYTE);
- resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
- actual_token = resource->GetSyncToken();
- EXPECT_EQ(actual_token, reference_token2);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-}
-
-TEST_F(CanvasResourceTest, MakeAcceleratedFromAcceleratedResourceIsNoOp) {
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- SkImageInfo image_info =
- SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> surface =
- SkSurface::MakeRenderTarget(GetGrContext(), SkBudgeted::kYes, image_info);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_TRUE(!!context_provider_wrapper_);
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- StaticBitmapImage::Create(surface->makeImageSnapshot(),
- context_provider_wrapper_),
- nullptr, kLow_SkFilterQuality, CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_TRUE(resource->IsAccelerated());
- scoped_refptr<CanvasResource> new_resource =
- resource->MakeAccelerated(context_provider_wrapper_);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_EQ(new_resource.get(), resource.get());
- EXPECT_TRUE(new_resource->IsAccelerated());
-}
-
-TEST_F(CanvasResourceTest, MakeAcceleratedFromRasterResource) {
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- SkImageInfo image_info =
- SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
-
- EXPECT_TRUE(!!context_provider_wrapper_);
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- StaticBitmapImage::Create(surface->makeImageSnapshot(),
- context_provider_wrapper_),
- nullptr, kLow_SkFilterQuality, CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_FALSE(resource->IsAccelerated());
- scoped_refptr<CanvasResource> new_resource =
- resource->MakeAccelerated(context_provider_wrapper_);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_NE(new_resource.get(), resource.get());
- EXPECT_FALSE(resource->IsAccelerated());
- EXPECT_TRUE(new_resource->IsAccelerated());
-}
-
-TEST_F(CanvasResourceTest, MakeUnacceleratedFromUnacceleratedResourceIsNoOp) {
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- SkImageInfo image_info =
- SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
-
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- StaticBitmapImage::Create(surface->makeImageSnapshot(),
- context_provider_wrapper_),
- nullptr, kLow_SkFilterQuality, CanvasColorParams());
-
- EXPECT_FALSE(resource->IsAccelerated());
- scoped_refptr<CanvasResource> new_resource = resource->MakeUnaccelerated();
-
- EXPECT_EQ(new_resource.get(), resource.get());
- EXPECT_FALSE(new_resource->IsAccelerated());
-}
-
-TEST_F(CanvasResourceTest, MakeUnacceleratedFromAcceleratedResource) {
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- SkImageInfo image_info =
- SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType, nullptr);
- sk_sp<SkSurface> surface =
- SkSurface::MakeRenderTarget(GetGrContext(), SkBudgeted::kYes, image_info);
-
- EXPECT_TRUE(!!context_provider_wrapper_);
- scoped_refptr<CanvasResource> resource = CanvasResourceBitmap::Create(
- StaticBitmapImage::Create(surface->makeImageSnapshot(),
- context_provider_wrapper_),
- nullptr, kLow_SkFilterQuality, CanvasColorParams());
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_TRUE(resource->IsAccelerated());
- scoped_refptr<CanvasResource> new_resource = resource->MakeUnaccelerated();
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_NE(new_resource.get(), resource.get());
- EXPECT_TRUE(resource->IsAccelerated());
- EXPECT_FALSE(new_resource->IsAccelerated());
-}
-
-void PaintToCanvasResource(CanvasResource* canvas_resource) {
- SkImageInfo image_info = SkImageInfo::MakeN32(
- canvas_resource->Size().Width(), canvas_resource->Size().Height(),
- kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
- sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
- SkPaint paint;
- paint.setColor(SK_ColorYELLOW);
- surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 10, 10), paint);
- canvas_resource->TakeSkImage(surface->makeImageSnapshot());
-}
-
-TEST_F(CanvasResourceTest, RamGpuMemoryBuffer_ResourcePreparation) {
- testing::InSequence s;
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
-
- EXPECT_TRUE(!!context_provider_wrapper_);
- constexpr GLuint image_id = 1;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, BindTexture(gpu::GetPlatformSpecificTextureTarget(), _));
-
- constexpr bool is_accelerated = false;
- scoped_refptr<CanvasResource> canvas_resource =
- CanvasResourceGpuMemoryBuffer::Create(
- IntSize(10, 10), CanvasColorParams(), context_provider_wrapper_,
- nullptr /*CanvasResourceProvider*/, kLow_SkFilterQuality,
- is_accelerated);
-
- EXPECT_TRUE(!!canvas_resource);
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- if (canvas_resource) {
- gpu::Mailbox test_mailbox;
- test_mailbox.name[0] = 1;
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
- .WillOnce(SetArrayArgument<1>(
- test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
-
- PaintToCanvasResource(canvas_resource.get());
-
- viz::TransferableResource transferable_resource;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback;
-
- bool success = canvas_resource->PrepareTransferableResource(
- &transferable_resource, &release_callback, kUnverifiedSyncToken);
-
- EXPECT_TRUE(success);
-
- release_callback->Run(gpu::SyncToken(), false);
- }
-}
-
-TEST_F(CanvasResourceTest, GpuMemoryBuffer_accelerated_8bit) {
- testing::InSequence s;
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
- EXPECT_TRUE(!!context_provider_wrapper_);
-
- constexpr GLuint image_id = 1;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, BindTexture(_, _));
-
- if (gpu::GetPlatformSpecificTextureTarget() == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint second_image_id = 2;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(second_image_id));
- EXPECT_CALL(gl_, BindTexture(_, _));
- }
-
- constexpr bool is_accelerated = true;
- scoped_refptr<CanvasResource> canvas_resource =
- CanvasResourceGpuMemoryBuffer::Create(
- IntSize(10, 10), CanvasColorParams(), context_provider_wrapper_,
- nullptr /*CanvasResourceProvider*/, kLow_SkFilterQuality,
- is_accelerated);
-
- EXPECT_TRUE(!!canvas_resource);
-}
-
-TEST_F(CanvasResourceTest, GpuMemoryBuffer_accelerated_float16) {
- testing::InSequence s;
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
- EXPECT_TRUE(!!context_provider_wrapper_);
-
- constexpr GLuint image_id = 1;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, BindTexture(_, _));
-
- if (gpu::GetPlatformSpecificTextureTarget() == GL_TEXTURE_EXTERNAL_OES) {
- constexpr GLuint second_image_id = 2;
- EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
- .WillOnce(Return(second_image_id));
- EXPECT_CALL(gl_, BindTexture(_, _));
- }
-
- constexpr bool is_accelerated = true;
- scoped_refptr<CanvasResource> canvas_resource =
- CanvasResourceGpuMemoryBuffer::Create(
- IntSize(10, 10),
- CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat,
- kNonOpaque),
- context_provider_wrapper_, nullptr /*CanvasResourceProvider*/,
- kLow_SkFilterQuality, is_accelerated);
-
- EXPECT_TRUE(!!canvas_resource);
-}
-
-TEST_F(CanvasResourceTest, PrepareTransferableResource_SharedBitmap) {
- testing::InSequence s;
- ScopedTestingPlatformSupport<GpuMemoryBufferTestPlatform> platform;
+TEST(CanvasResourceTest, PrepareTransferableResource_SharedBitmap) {
scoped_refptr<CanvasResource> canvas_resource =
CanvasResourceSharedBitmap::Create(IntSize(10, 10), CanvasColorParams(),
nullptr, // CanvasResourceProvider
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color.cc b/chromium/third_party/blink/renderer/platform/graphics/color.cc
index 9a9aac14a64..a9d5eb859e5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color.cc
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/decimal.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.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/string_view.h"
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 5f3a71d90df..9889add4240 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
@@ -19,7 +19,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
namespace blink {
@@ -149,8 +148,7 @@ std::unique_ptr<base::trace_event::TracedValue>
ContentLayerClientImpl::TakeDebugInfo(const cc::Layer* layer) {
DCHECK_EQ(layer, cc_picture_layer_.get());
auto traced_value = std::make_unique<base::trace_event::TracedValue>();
- traced_value->SetString("layer_name",
- WTF::StringUTF8Adaptor(debug_name_).AsStringPiece());
+ traced_value->SetString("layer_name", LayerDebugName(layer));
if (auto* tracking = raster_invalidator_.GetTracking()) {
tracking->AddToTracedValue(*traced_value);
tracking->ClearInvalidations();
@@ -160,6 +158,12 @@ ContentLayerClientImpl::TakeDebugInfo(const cc::Layer* layer) {
return traced_value;
}
+std::string ContentLayerClientImpl::LayerDebugName(
+ const cc::Layer* layer) const {
+ DCHECK_EQ(layer, cc_picture_layer_.get());
+ return debug_name_.Utf8();
+}
+
scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
scoped_refptr<const PaintArtifact> paint_artifact,
const PaintChunkSubset& paint_chunks,
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 a75ad728b88..03d76178613 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
@@ -47,6 +47,7 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
// cc::LayerClient
std::unique_ptr<base::trace_event::TracedValue> TakeDebugInfo(
const cc::Layer*) override;
+ std::string LayerDebugName(const cc::Layer*) const override;
void DidChangeScrollbarsHiddenIfOverlay(bool) override {}
bool Matches(const PaintChunk& paint_chunk) const {
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 1a5796c8f77..ec618961a3a 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
@@ -396,14 +396,15 @@ void PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
static bool CanUpcastTo(const PropertyTreeState& guest,
const PropertyTreeState& home);
bool PaintArtifactCompositor::PendingLayer::CanMerge(
- const PendingLayer& guest) const {
+ const PendingLayer& guest,
+ const PropertyTreeState& guest_state) const {
if (requires_own_layer || guest.requires_own_layer)
return false;
if (&property_tree_state.Effect().Unalias() !=
- &guest.property_tree_state.Effect().Unalias()) {
+ &guest_state.Effect().Unalias()) {
return false;
}
- return CanUpcastTo(guest.property_tree_state, property_tree_state);
+ return CanUpcastTo(guest_state, property_tree_state);
}
void PaintArtifactCompositor::PendingLayer::Upcast(
@@ -507,29 +508,48 @@ bool PaintArtifactCompositor::MightOverlap(const PendingLayer& layer_a,
return bounds_a.Rect().Intersects(bounds_b.Rect());
}
-bool PaintArtifactCompositor::CanDecompositeEffect(
+bool PaintArtifactCompositor::DecompositeEffect(
+ const EffectPaintPropertyNode& unaliased_parent_effect,
+ size_t first_layer_in_parent_group_index,
const EffectPaintPropertyNode& unaliased_effect,
- const PendingLayer& layer) {
+ size_t layer_index) {
+ // The layer must be the last layer in pending_layers_.
+ DCHECK_EQ(layer_index, pending_layers_.size() - 1);
+
// If the effect associated with the layer is deeper than than the effect
// 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().Unalias() != &unaliased_effect)
return false;
if (layer.requires_own_layer)
return false;
- // TODO(trchen): Exotic blending layer may be decomposited only if it could
- // be merged into the first layer of the current group.
- if (unaliased_effect.BlendMode() != SkBlendMode::kSrcOver)
- return false;
if (unaliased_effect.HasDirectCompositingReasons())
return false;
- if (!CanUpcastTo(layer.property_tree_state,
- PropertyTreeState(unaliased_effect.LocalTransformSpace(),
- unaliased_effect.OutputClip()
- ? *unaliased_effect.OutputClip()
- : layer.property_tree_state.Clip(),
- unaliased_effect)))
+
+ PropertyTreeState group_state(unaliased_effect.LocalTransformSpace(),
+ unaliased_effect.OutputClip()
+ ? *unaliased_effect.OutputClip()
+ : layer.property_tree_state.Clip(),
+ unaliased_effect);
+ if (!CanUpcastTo(layer.property_tree_state, group_state))
return false;
+
+ PropertyTreeState upcast_state = group_state;
+ upcast_state.SetEffect(unaliased_parent_effect);
+
+ // Exotic blending layer can be decomposited only if its parent group
+ // (which defines the scope of the blending) has only one layer before it,
+ // and it can be merged into that layer.
+ if (unaliased_effect.BlendMode() != SkBlendMode::kSrcOver) {
+ if (layer_index - 1 != first_layer_in_parent_group_index)
+ return false;
+ if (!pending_layers_[first_layer_in_parent_group_index].CanMerge(
+ layer, upcast_state))
+ return false;
+ }
+
+ layer.Upcast(upcast_state);
return true;
}
@@ -641,25 +661,16 @@ void PaintArtifactCompositor::LayerizeGroup(
// a recursion call.
wtf_size_t first_layer_in_subgroup = pending_layers_.size();
LayerizeGroup(paint_artifact, settings, *unaliased_subgroup, chunk_it);
- // Now the chunk iterator stepped over the subgroup we just saw.
- // If the subgroup generated 2 or more layers then the subgroup must be
- // composited to satisfy grouping requirement.
- // i.e. Grouping effects generally must be applied atomically,
- // for example, Opacity(A+B) != Opacity(A) + Opacity(B), thus an effect
- // either applied 100% within a layer, or not at all applied within layer
- // (i.e. applied by compositor render surface instead).
- if (pending_layers_.size() != first_layer_in_subgroup + 1)
+ // The above LayerizeGroup generated new layers in pending_layers_
+ // [first_layer_in_subgroup .. pending_layers.size() - 1]. If it generated
+ // 2 or more layer that we already know can't be merged together, we
+ // should not decomposite and try to merge any of them into the previous
+ // layers.
+ if (first_layer_in_subgroup != pending_layers_.size() - 1)
continue;
- // Now attempt to "decomposite" subgroup.
- PendingLayer& subgroup_layer = pending_layers_[first_layer_in_subgroup];
- if (!CanDecompositeEffect(*unaliased_subgroup, subgroup_layer))
+ if (!DecompositeEffect(unaliased_group, first_layer_in_current_group,
+ *unaliased_subgroup, first_layer_in_subgroup))
continue;
- subgroup_layer.Upcast(
- PropertyTreeState(unaliased_subgroup->LocalTransformSpace(),
- unaliased_subgroup->OutputClip()
- ? *unaliased_subgroup->OutputClip()
- : subgroup_layer.property_tree_state.Clip(),
- unaliased_group));
}
// At this point pending_layers_.back() is the either a layer from a
// "decomposited" subgroup or a layer created from a chunk we just
@@ -673,7 +684,7 @@ void PaintArtifactCompositor::LayerizeGroup(
for (wtf_size_t candidate_index = pending_layers_.size() - 1;
candidate_index-- > first_layer_in_current_group;) {
PendingLayer& candidate_layer = pending_layers_[candidate_index];
- if (candidate_layer.CanMerge(new_layer)) {
+ if (candidate_layer.CanMerge(new_layer, new_layer.property_tree_state)) {
candidate_layer.Merge(new_layer);
pending_layers_.pop_back();
break;
@@ -749,7 +760,7 @@ scoped_refptr<cc::DisplayItemList> SynthesizedClip::PaintContentsToDisplayList(
cc_list->push<cc::DrawRRectOp>(local_rrect_, flags);
} else {
cc_list->push<cc::SaveOp>();
- cc_list->push<cc::TranslateOp>(-layer_origin_.x(), -layer_origin_.x());
+ cc_list->push<cc::TranslateOp>(-layer_origin_.x(), -layer_origin_.y());
cc_list->push<cc::ClipPathOp>(path_->GetSkPath(), SkClipOp::kIntersect,
true);
SkRRect rrect = local_rrect_;
@@ -795,20 +806,33 @@ static void UpdateCompositorViewportProperties(
PropertyTreeManager& property_tree_manager,
cc::LayerTreeHost* layer_tree_host) {
cc::LayerTreeHost::ViewportPropertyIds ids;
- // This is also needed by pre-CompositeAfterPaint, so is not guarded by
- // CompositeAfterPaintEnabled().
+ if (properties.overscroll_elasticity_transform) {
+ ids.overscroll_elasticity_transform =
+ property_tree_manager.EnsureCompositorTransformNode(
+ *properties.overscroll_elasticity_transform);
+ }
if (properties.page_scale) {
ids.page_scale_transform =
property_tree_manager.EnsureCompositorPageScaleTransformNode(
*properties.page_scale);
}
- if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
- if (properties.inner_scroll_translation) {
- ids.inner_scroll = property_tree_manager.EnsureCompositorScrollNode(
- *properties.inner_scroll_translation);
+ if (properties.inner_scroll_translation) {
+ ids.inner_scroll = property_tree_manager.EnsureCompositorScrollNode(
+ *properties.inner_scroll_translation);
+ if (properties.outer_clip) {
+ ids.outer_clip = property_tree_manager.EnsureCompositorClipNode(
+ *properties.outer_clip);
+ }
+ if (properties.outer_scroll_translation) {
+ ids.outer_scroll = property_tree_manager.EnsureCompositorScrollNode(
+ *properties.outer_scroll_translation);
}
- layer_tree_host->RegisterViewportPropertyIds(ids);
+ } else {
+ // Outer viewport properties exist only if inner viewport property exists.
+ DCHECK(!properties.outer_clip);
+ DCHECK(!properties.outer_scroll_translation);
}
+ layer_tree_host->RegisterViewportPropertyIds(ids);
}
// Walk the pending layer list and build up a table of transform nodes that
@@ -1103,36 +1127,51 @@ cc::PropertyTrees* PaintArtifactCompositor::GetPropertyTreesForDirectUpdate() {
bool PaintArtifactCompositor::DirectlyUpdateCompositedOpacityValue(
const EffectPaintPropertyNode& effect) {
+ // We can only directly-update compositor values if all content associated
+ // with the node is known to be composited.
+ DCHECK(effect.HasDirectCompositingReasons());
if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
return PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
- property_trees, effect);
+ property_trees, *root_layer_->layer_tree_host(), effect);
}
return false;
}
bool PaintArtifactCompositor::DirectlyUpdateScrollOffsetTransform(
const TransformPaintPropertyNode& transform) {
+ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+ // We can only directly-update compositor values if all content associated
+ // with the node is known to be composited. We cannot DCHECK this pre-
+ // CompositeAfterPaint because we cannot query CompositedLayerMapping here.
+ DCHECK(transform.HasDirectCompositingReasons());
+ }
if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
return PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
- property_trees, transform);
+ property_trees, *root_layer_->layer_tree_host(), transform);
}
return false;
}
bool PaintArtifactCompositor::DirectlyUpdateTransform(
const TransformPaintPropertyNode& transform) {
+ // We can only directly-update compositor values if all content associated
+ // with the node is known to be composited.
+ DCHECK(transform.HasDirectCompositingReasons());
if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
- return PropertyTreeManager::DirectlyUpdateTransform(property_trees,
- transform);
+ return PropertyTreeManager::DirectlyUpdateTransform(
+ property_trees, *root_layer_->layer_tree_host(), transform);
}
return false;
}
bool PaintArtifactCompositor::DirectlyUpdatePageScaleTransform(
const TransformPaintPropertyNode& transform) {
+ // We can only directly-update compositor values if all content associated
+ // with the node is known to be composited.
+ DCHECK(transform.HasDirectCompositingReasons());
if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
- return PropertyTreeManager::DirectlyUpdatePageScaleTransform(property_trees,
- transform);
+ return PropertyTreeManager::DirectlyUpdatePageScaleTransform(
+ property_trees, *root_layer_->layer_tree_host(), transform);
}
return false;
}
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 135615b4613..8d2beeb08e5 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
@@ -119,10 +119,11 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
~PaintArtifactCompositor();
struct ViewportProperties {
+ const TransformPaintPropertyNode* overscroll_elasticity_transform = nullptr;
const TransformPaintPropertyNode* page_scale = nullptr;
const TransformPaintPropertyNode* inner_scroll_translation = nullptr;
- // TODO(crbug.com/909750): Add other viewport properties, e.g.
- // outer_scroll_translation.
+ const ClipPaintPropertyNode* outer_clip = nullptr;
+ const TransformPaintPropertyNode* outer_scroll_translation = nullptr;
};
struct Settings {
@@ -213,7 +214,10 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// applied. The merged layer must have a property tree state that's deeper
// than this layer, i.e. can "upcast" to this layer's state.
void Merge(const PendingLayer& guest);
- bool CanMerge(const PendingLayer& guest) const;
+ // |guest_state| is for cases that we want to check if we can merge |guest|
+ // if it has |guest_state| (which may be different from its current state).
+ bool CanMerge(const PendingLayer& guest,
+ const PropertyTreeState& guest_state) 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
@@ -260,8 +264,10 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
const EffectPaintPropertyNode&,
Vector<PaintChunk>::const_iterator& chunk_cursor);
static bool MightOverlap(const PendingLayer&, const PendingLayer&);
- static bool CanDecompositeEffect(const EffectPaintPropertyNode&,
- const PendingLayer&);
+ bool DecompositeEffect(const EffectPaintPropertyNode& unaliased_parent_effect,
+ size_t first_layer_in_parent_group_index,
+ const EffectPaintPropertyNode& unaliased_effect,
+ size_t layer_index);
// Builds a leaf layer that represents a single paint chunk.
scoped_refptr<cc::Layer> CompositedLayerForPendingLayer(
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 e4cf4525821..c98d8f2ec88 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
@@ -619,7 +619,6 @@ TEST_P(PaintArtifactCompositorTest, SortingContextID) {
Pointee(DrawsRectangle(FloatRect(0, 0, 300, 200), Color::kWhite)));
int white_sorting_context_id =
GetTransformNode(white_layer).sorting_context_id;
- EXPECT_EQ(white_layer->sorting_context_id(), white_sorting_context_id);
EXPECT_EQ(0, white_sorting_context_id);
// The light gray layer is 3D sorted.
@@ -977,7 +976,7 @@ TEST_P(PaintArtifactCompositorTest, EffectTreeConversionWithAlias) {
const cc::EffectNode& converted_effect1 = *effect_tree.Node(2);
EXPECT_EQ(converted_root_effect.id, converted_effect1.parent_id);
EXPECT_FLOAT_EQ(0.5, converted_effect1.opacity);
- EXPECT_EQ(real_effect1->GetCompositorElementId().GetInternalValue(),
+ EXPECT_EQ(real_effect1->GetCompositorElementId().GetStableId(),
converted_effect1.stable_id);
const cc::EffectNode& converted_effect2 = *effect_tree.Node(3);
@@ -2008,7 +2007,7 @@ TEST_P(PaintArtifactCompositorTest, EffectWithElementIdWithAlias) {
ElementIdToEffectNodeIndex(real_effect->GetCompositorElementId()));
}
-TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMask) {
+TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleLuminanceMask) {
auto masked = CreateOpacityEffect(
e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
EffectPaintPropertyNode::State masking_state;
@@ -2016,8 +2015,6 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMask) {
masking_state.output_clip = &c0();
masking_state.color_filter = kColorFilterLuminanceToAlpha;
masking_state.blend_mode = SkBlendMode::kDstIn;
- masking_state.direct_compositing_reasons =
- CompositingReason::kSquashingDisallowed;
auto masking =
EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
@@ -2027,30 +2024,18 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMask) {
artifact.Chunk(t0(), c0(), *masking)
.RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
- ASSERT_EQ(2u, ContentLayerCount());
+ ASSERT_EQ(1u, ContentLayerCount());
- const cc::Layer* masked_layer = ContentLayerAt(0);
- EXPECT_THAT(masked_layer->GetPicture(),
- Pointee(DrawsRectangle(FloatRect(0, 0, 200, 200), Color::kGray)));
- EXPECT_EQ(Translation(100, 100), masked_layer->ScreenSpaceTransform());
- EXPECT_EQ(gfx::Size(200, 200), masked_layer->bounds());
+ const cc::Layer* layer = ContentLayerAt(0);
+ EXPECT_THAT(*layer->GetPicture(),
+ DrawsRectangles(Vector<RectWithColor>{
+ RectWithColor(FloatRect(0, 0, 200, 200), Color::kGray),
+ RectWithColor(FloatRect(50, 50, 100, 100), Color::kWhite)}));
+ EXPECT_EQ(Translation(100, 100), layer->ScreenSpaceTransform());
+ EXPECT_EQ(gfx::Size(200, 200), layer->bounds());
const cc::EffectNode* masked_group =
- GetPropertyTrees().effect_tree.Node(masked_layer->effect_tree_index());
- EXPECT_TRUE(masked_group->HasRenderSurface());
-
- const cc::Layer* masking_layer = ContentLayerAt(1);
- EXPECT_THAT(
- masking_layer->GetPicture(),
- Pointee(DrawsRectangle(FloatRect(0, 0, 100, 100), Color::kWhite)));
- EXPECT_EQ(Translation(150, 150), masking_layer->ScreenSpaceTransform());
- EXPECT_EQ(gfx::Size(100, 100), masking_layer->bounds());
- const cc::EffectNode* masking_group =
- GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
- EXPECT_FALSE(masking_group->HasRenderSurface());
- EXPECT_EQ(masked_group->id, masking_group->parent_id);
- ASSERT_EQ(1u, masking_group->filters.size());
- EXPECT_EQ(cc::FilterOperation::REFERENCE,
- masking_group->filters.at(0).type());
+ GetPropertyTrees().effect_tree.Node(layer->effect_tree_index());
+ EXPECT_FALSE(masked_group->HasRenderSurface());
}
TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
@@ -2061,8 +2046,6 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
masking_state.output_clip = &c0();
masking_state.color_filter = kColorFilterLuminanceToAlpha;
masking_state.blend_mode = SkBlendMode::kDstIn;
- masking_state.direct_compositing_reasons =
- CompositingReason::kSquashingDisallowed;
auto masking =
EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
@@ -2090,7 +2073,31 @@ TEST_P(PaintArtifactCompositorTest, CompositedLuminanceMaskTwoChildren) {
masking_group->filters.at(0).type());
}
-TEST_P(PaintArtifactCompositorTest, CompositedExoticBlendMode) {
+TEST_P(PaintArtifactCompositorTest, NonCompositedSimpleExoticBlendMode) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.blend_mode = SkBlendMode::kXor;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *masked)
+ .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(1u, ContentLayerCount());
+
+ const cc::Layer* layer = ContentLayerAt(0);
+ const cc::EffectNode* group =
+ GetPropertyTrees().effect_tree.Node(layer->effect_tree_index());
+ EXPECT_FALSE(group->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest, ForcedCompositedExoticBlendMode) {
auto masked = CreateOpacityEffect(
e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
EffectPaintPropertyNode::State masking_state;
@@ -2113,6 +2120,77 @@ TEST_P(PaintArtifactCompositorTest, CompositedExoticBlendMode) {
const cc::Layer* masking_layer = ContentLayerAt(1);
const cc::EffectNode* masking_group =
GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+ EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
+
+ /// This requires a render surface.
+ EXPECT_TRUE(masking_group->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest,
+ CompositedExoticBlendModeOnTwoOpacityAnimationLayers) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ auto masked_child1 = CreateOpacityEffect(
+ *masked, 1.0, CompositingReason::kActiveOpacityAnimation);
+ auto masked_child2 = CreateOpacityEffect(
+ *masked, 1.0, CompositingReason::kActiveOpacityAnimation);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.blend_mode = SkBlendMode::kXor;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(t0(), c0(), *masked_child1)
+ .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(t0(), c0(), *masked_child2)
+ .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(3u, ContentLayerCount());
+
+ const cc::Layer* masking_layer = ContentLayerAt(2);
+ const cc::EffectNode* masking_group =
+ GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+ EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
+
+ /// This requires a render surface.
+ EXPECT_TRUE(masking_group->HasRenderSurface());
+}
+
+TEST_P(PaintArtifactCompositorTest,
+ CompositedExoticBlendModeOnTwo3DTransformLayers) {
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
+ auto transform1 =
+ CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+ CompositingReason::k3DTransform);
+ auto transform2 =
+ CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
+ CompositingReason::k3DTransform);
+ EffectPaintPropertyNode::State masking_state;
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
+ masking_state.blend_mode = SkBlendMode::kXor;
+ auto masking =
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
+
+ TestPaintArtifact artifact;
+ artifact.Chunk(*transform1, c0(), *masked)
+ .RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
+ artifact.Chunk(*transform2, c0(), *masked)
+ .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ artifact.Chunk(t0(), c0(), *masking)
+ .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
+ Update(artifact.Build());
+ ASSERT_EQ(3u, ContentLayerCount());
+
+ const cc::Layer* masking_layer = ContentLayerAt(2);
+ const cc::EffectNode* masking_group =
+ GetPropertyTrees().effect_tree.Node(masking_layer->effect_tree_index());
+ EXPECT_EQ(SkBlendMode::kXor, masking_group->blend_mode);
/// This requires a render surface.
EXPECT_TRUE(masking_group->HasRenderSurface());
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 8ad94b1dbd5..ce4a6bf8c06 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
@@ -229,9 +229,9 @@ class ConversionContext {
const TransformPaintPropertyNode* previous_transform_ = nullptr;
// This structure accumulates bounds of all chunks under an effect. When an
- // effect starts, we emit a SaveLayer[Alpha]Op with null bounds starts, and
- // push a new |EffectBoundsInfo| onto |effect_bounds_stack_|. When the effect
- // ends, we update the bounds of the op.
+ // effect starts, we emit a SaveLayer[Alpha]Op with null bounds, and push a
+ // new |EffectBoundsInfo| onto |effect_bounds_stack_|. When the effect ends,
+ // we update the bounds of the op.
struct EffectBoundsInfo {
// The id of the SaveLayer[Alpha]Op for this effect. It's recorded when we
// push the op for this effect, and used when this effect ends in
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 41a73f43ecd..757e737fa3b 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
@@ -114,6 +114,7 @@ static void SetTransformTreePageScaleFactor(
bool PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
cc::PropertyTrees* property_trees,
+ cc::LayerTreeHost& host,
const EffectPaintPropertyNode& effect) {
auto* cc_effect = property_trees->effect_tree.Node(
effect.CcNodeId(property_trees->sequence_number));
@@ -128,11 +129,13 @@ bool PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
cc_effect->opacity = effect.Opacity();
cc_effect->effect_changed = true;
property_trees->effect_tree.set_needs_update(true);
+ host.SetNeedsCommit();
return true;
}
bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
cc::PropertyTrees* property_trees,
+ cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
auto* scroll_node = transform.ScrollNode();
// Only handle scroll adjustments.
@@ -158,11 +161,13 @@ bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
cc_transform->transform_changed = true;
property_trees->transform_tree.set_needs_update(true);
property_trees->scroll_tree.set_needs_update(true);
+ host.SetNeedsCommit();
return true;
}
bool PropertyTreeManager::DirectlyUpdateTransform(
cc::PropertyTrees* property_trees,
+ cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
// If we have a ScrollNode, we should be using
// DirectlyUpdateScrollOffsetTransform().
@@ -182,11 +187,13 @@ bool PropertyTreeManager::DirectlyUpdateTransform(
cc_transform->transform_changed = true;
property_trees->transform_tree.set_needs_update(true);
+ host.SetNeedsCommit();
return true;
}
bool PropertyTreeManager::DirectlyUpdatePageScaleTransform(
cc::PropertyTrees* property_trees,
+ cc::LayerTreeHost& host,
const TransformPaintPropertyNode& transform) {
DCHECK(!transform.ScrollNode());
@@ -200,6 +207,7 @@ bool PropertyTreeManager::DirectlyUpdatePageScaleTransform(
cc_transform);
cc_transform->transform_changed = true;
property_trees->transform_tree.set_needs_update(true);
+ host.SetNeedsCommit();
return true;
}
@@ -282,7 +290,7 @@ void PropertyTreeManager::SetupRootEffectNode() {
static UniqueObjectId unique_id = NewUniqueObjectId();
effect_node.stable_id =
- CompositorElementIdFromUniqueObjectId(unique_id).GetInternalValue();
+ CompositorElementIdFromUniqueObjectId(unique_id).GetStableId();
effect_node.transform_id = kRealRootNodeId;
effect_node.clip_id = kSecondaryRootNodeId;
effect_node.render_surface_reason = cc::RenderSurfaceReason::kRoot;
@@ -590,14 +598,14 @@ void PropertyTreeManager::EmitClipMaskLayer() {
DCHECK_EQ(static_cast<uint64_t>(cc::EffectNode::INVALID_STABLE_ID),
mask_isolation.stable_id);
- mask_isolation.stable_id = mask_isolation_id.GetInternalValue();
+ mask_isolation.stable_id = mask_isolation_id.GetStableId();
if (!needs_layer)
return;
cc::EffectNode& mask_effect = *GetEffectTree().Node(
GetEffectTree().Insert(cc::EffectNode(), current_.effect_id));
- mask_effect.stable_id = mask_effect_id.GetInternalValue();
+ mask_effect.stable_id = mask_effect_id.GetStableId();
mask_effect.clip_id = clip_id;
mask_effect.blend_mode = SkBlendMode::kDstIn;
@@ -898,7 +906,7 @@ SkBlendMode PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded(
} else {
synthetic_effect.stable_id =
CompositorElementIdFromUniqueObjectId(NewUniqueObjectId())
- .GetInternalValue();
+ .GetStableId();
// The clip of the synthetic effect is the parent of the clip, so that
// the clip itself will be applied in the render surface.
DCHECK(pending_clip.clip->Parent());
@@ -1040,7 +1048,7 @@ void PropertyTreeManager::PopulateCcEffectNode(
const EffectPaintPropertyNode& effect,
int output_clip_id,
SkBlendMode blend_mode) {
- effect_node.stable_id = effect.GetCompositorElementId().GetInternalValue();
+ effect_node.stable_id = effect.GetCompositorElementId().GetStableId();
effect_node.clip_id = output_clip_id;
// An effect with filters or backdrop filters needs a render surface.
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 0031fa21f18..09b99c7d1f2 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
@@ -17,6 +17,7 @@ namespace cc {
class ClipTree;
class EffectTree;
class Layer;
+class LayerTreeHost;
class PropertyTrees;
class ScrollTree;
class TransformTree;
@@ -119,14 +120,18 @@ class PropertyTreeManager {
static bool DirectlyUpdateCompositedOpacityValue(
cc::PropertyTrees*,
+ cc::LayerTreeHost&,
const EffectPaintPropertyNode&);
static bool DirectlyUpdateScrollOffsetTransform(
cc::PropertyTrees*,
+ cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
static bool DirectlyUpdateTransform(cc::PropertyTrees*,
+ cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
static bool DirectlyUpdatePageScaleTransform(
cc::PropertyTrees*,
+ cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
private:
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 1245f2dcef1..4770acc056c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -36,6 +36,8 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
{CompositingReason::kActiveBackdropFilterAnimation,
"activeBackdropFilterAnimation",
"Has an active accelerated backdrop filter animation or transition"},
+ {CompositingReason::kImmersiveArOverlay, "immersiveArOverlay",
+ "Is DOM overlay for WebXR immersive-ar mode"},
{CompositingReason::kScrollDependentPosition, "scrollDependentPosition",
"Is fixed or sticky position"},
{CompositingReason::kOverflowScrollingTouch, "overflowScrollingTouch",
@@ -110,8 +112,6 @@ constexpr CompositingReasonStringMap kCompositingReasonsStringMap[] = {
"tree"},
{CompositingReason::kLayerForDescendantClip, "layerForDescendantClip",
"Secondary layer, to clip descendants of the owning layer"},
- {CompositingReason::kLayerForPerspective, "layerForPerspective",
- "Secondary layer, to house the perspective transform for all descendants"},
{CompositingReason::kLayerForHorizontalScrollbar,
"layerForHorizontalScrollbar",
"Secondary layer, the horizontal scrollbar layer"},
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 0ba9f3bb806..8d6d9c4cb2d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -27,6 +27,7 @@ using CompositingReasons = uint64_t;
V(ActiveOpacityAnimation) \
V(ActiveFilterAnimation) \
V(ActiveBackdropFilterAnimation) \
+ V(ImmersiveArOverlay) \
V(ScrollDependentPosition) \
V(OverflowScrollingTouch) \
V(OverflowScrollingParent) \
@@ -39,7 +40,6 @@ using CompositingReasons = uint64_t;
V(WillChangeOther) \
V(BackdropFilter) \
V(RootScroller) \
- V(ScrollTimelineTarget) \
\
/* Overlap reasons that require knowing what's behind you in paint-order \
before knowing the answer. */ \
@@ -70,7 +70,6 @@ using CompositingReasons = uint64_t;
/* CompositedLayerMapping internal hierarchy reasons. */ \
V(LayerForAncestorClip) \
V(LayerForDescendantClip) \
- V(LayerForPerspective) \
V(LayerForHorizontalScrollbar) \
V(LayerForVerticalScrollbar) \
V(LayerForOverflowControlsHost) \
@@ -129,8 +128,8 @@ class PLATFORM_EXPORT CompositingReason {
kComboAllDirectNonStyleDeterminedReasons =
kVideo | kCanvas | kPlugin | kIFrame | kOverflowScrollingParent |
- kOutOfFlowClipping | kVideoOverlay | kRoot | kRootScroller |
- kScrollDependentPosition | kScrollTimelineTarget,
+ kOutOfFlowClipping | kVideoOverlay | kImmersiveArOverlay | kRoot |
+ kRootScroller | kScrollDependentPosition,
kComboAllDirectReasons = kComboAllDirectStyleDeterminedReasons |
kComboAllDirectNonStyleDeterminedReasons,
@@ -159,7 +158,7 @@ class PLATFORM_EXPORT CompositingReason {
kPerspectiveWith3DDescendants | kPreserve3DWith3DDescendants |
kActiveTransformAnimation,
kDirectReasonsForEffectProperty = kActiveOpacityAnimation |
- kWillChangeOpacity |
+ kWillChangeOpacity | kBackdropFilter |
kActiveBackdropFilterAnimation,
kDirectReasonsForFilterProperty = kActiveFilterAnimation,
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
index b80cf9e1c5b..86486ca89a7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
@@ -14,12 +14,10 @@ UniqueObjectId NewUniqueObjectId() {
static CompositorElementId CreateCompositorElementId(
uint64_t blink_id,
CompositorElementIdNamespace namespace_id) {
- DCHECK(
- blink_id > 0 &&
- blink_id <
- std::numeric_limits<uint64_t>::max() /
- static_cast<unsigned>(
- CompositorElementIdNamespace::kMaxRepresentableNamespaceId));
+ DCHECK(blink_id > 0 &&
+ blink_id < std::numeric_limits<uint64_t>::max() /
+ static_cast<unsigned>(
+ CompositorElementIdNamespace::kMaxRepresentable));
// Shift to make room for namespace_id enum bits.
cc::ElementIdType id = blink_id << kCompositorNamespaceBitCount;
id += static_cast<uint64_t>(namespace_id);
@@ -29,17 +27,7 @@ static CompositorElementId CreateCompositorElementId(
CompositorElementId PLATFORM_EXPORT CompositorElementIdFromUniqueObjectId(
UniqueObjectId id,
CompositorElementIdNamespace namespace_id) {
- DCHECK(namespace_id == CompositorElementIdNamespace::kPrimary ||
- namespace_id == CompositorElementIdNamespace::kScroll ||
- namespace_id == CompositorElementIdNamespace::kStickyTranslation ||
- namespace_id == CompositorElementIdNamespace::kPrimaryEffect ||
- namespace_id == CompositorElementIdNamespace::kPrimaryTransform ||
- namespace_id == CompositorElementIdNamespace::kEffectFilter ||
- namespace_id == CompositorElementIdNamespace::kEffectMask ||
- namespace_id == CompositorElementIdNamespace::kEffectClipPath ||
- namespace_id == CompositorElementIdNamespace::kVerticalScrollbar ||
- namespace_id == CompositorElementIdNamespace::kHorizontalScrollbar ||
- namespace_id == CompositorElementIdNamespace::kOverscrollElasticity);
+ DCHECK_LE(namespace_id, CompositorElementIdNamespace::kMax);
return CreateCompositorElementId(id, namespace_id);
}
@@ -59,9 +47,8 @@ CompositorElementIdFromUniqueObjectId(UniqueObjectId id) {
CompositorElementIdNamespace NamespaceFromCompositorElementId(
CompositorElementId element_id) {
return static_cast<CompositorElementIdNamespace>(
- element_id.GetInternalValue() %
- static_cast<uint64_t>(
- CompositorElementIdNamespace::kMaxRepresentableNamespaceId));
+ element_id.GetStableId() %
+ static_cast<uint64_t>(CompositorElementIdNamespace::kMaxRepresentable));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
index 585bb6e11c4..957fbf2b7fe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
@@ -25,12 +25,17 @@ enum class CompositorElementIdNamespace {
kEffectClipPath,
kVerticalScrollbar,
kHorizontalScrollbar,
- kOverscrollElasticity,
+ // The following values are for internal usage only.
+ kMax = kHorizontalScrollbar,
// A sentinel to indicate the maximum representable namespace id
// (the maximum is one less than this value).
- kMaxRepresentableNamespaceId = 1 << kCompositorNamespaceBitCount
+ kMaxRepresentable = 1 << kCompositorNamespaceBitCount
};
+static_assert(CompositorElementIdNamespace::kMax <=
+ CompositorElementIdNamespace::kMaxRepresentable,
+ "");
+
using CompositorElementId = cc::ElementId;
using ScrollbarId = uint64_t;
using UniqueObjectId = uint64_t;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
index 225187d29d8..7247c1820a0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
@@ -11,7 +11,7 @@ namespace blink {
class CompositorElementIdTest : public testing::Test {};
uint64_t IdFromCompositorElementId(CompositorElementId element_id) {
- return element_id.GetInternalValue() >> kCompositorNamespaceBitCount;
+ return element_id.GetStableId() >> kCompositorNamespaceBitCount;
}
TEST_F(CompositorElementIdTest, EncodeDecode) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
index fd01c00f64c..19cb6f21032 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
@@ -69,7 +69,7 @@ ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size)
: end_index_(0), max_object_size_(max_object_size) {}
ContiguousContainerBase::ContiguousContainerBase(
- ContiguousContainerBase&& source) noexcept
+ ContiguousContainerBase&& source)
: ContiguousContainerBase(source.max_object_size_) {
Swap(source);
}
@@ -77,7 +77,7 @@ ContiguousContainerBase::ContiguousContainerBase(
ContiguousContainerBase::~ContiguousContainerBase() = default;
ContiguousContainerBase& ContiguousContainerBase::operator=(
- ContiguousContainerBase&& source) noexcept {
+ ContiguousContainerBase&& source) {
Swap(source);
return *this;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
index 867e59c8626..3eee5589124 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -42,10 +42,10 @@ class PLATFORM_EXPORT ContiguousContainerBase {
protected:
explicit ContiguousContainerBase(size_t max_object_size);
- ContiguousContainerBase(ContiguousContainerBase&&) noexcept;
+ ContiguousContainerBase(ContiguousContainerBase&&);
~ContiguousContainerBase();
- ContiguousContainerBase& operator=(ContiguousContainerBase&&) noexcept;
+ ContiguousContainerBase& operator=(ContiguousContainerBase&&);
size_t size() const { return elements_.size(); }
bool IsEmpty() const { return !size(); }
@@ -147,7 +147,7 @@ class ContiguousContainer : public ContiguousContainerBase {
WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType));
}
- ContiguousContainer(ContiguousContainer&& source) noexcept
+ ContiguousContainer(ContiguousContainer&& source)
: ContiguousContainerBase(std::move(source)) {}
~ContiguousContainer() {
@@ -157,7 +157,7 @@ class ContiguousContainer : public ContiguousContainerBase {
}
}
- ContiguousContainer& operator=(ContiguousContainer&& source) noexcept {
+ ContiguousContainer& operator=(ContiguousContainer&& source) {
// Must clear in the derived class to ensure that element destructors
// care called.
Clear();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier_test.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier_test.cc
index 5242caf1d42..c2251c51b8a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_classifier_test.cc
@@ -22,7 +22,7 @@ Color GetColorWithBrightness(int target_brightness) {
TEST(DarkModeColorClassifierTest, ApplyFilterToDarkTextOnly) {
DarkModeSettings settings;
- settings.mode = DarkMode::kSimpleInvertForTesting;
+ settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting;
settings.text_brightness_threshold = 200;
auto classifier = DarkModeColorClassifier::MakeTextColorClassifier(settings);
@@ -51,7 +51,7 @@ TEST(DarkModeColorClassifierTest, ApplyFilterToDarkTextOnly) {
TEST(DarkModeColorClassifierTest, ApplyFilterToLightBackgroundElementsOnly) {
DarkModeSettings settings;
- settings.mode = DarkMode::kSimpleInvertForTesting;
+ settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting;
settings.background_brightness_threshold = 200;
auto classifier =
DarkModeColorClassifier::MakeBackgroundColorClassifier(settings);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc
index 571db462712..0fe6ee1c29b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_color_filter.cc
@@ -94,10 +94,10 @@ class LabColorFilter : public DarkModeColorFilter {
std::unique_ptr<DarkModeColorFilter> DarkModeColorFilter::FromSettings(
const DarkModeSettings& settings) {
switch (settings.mode) {
- case DarkMode::kOff:
+ case DarkModeInversionAlgorithm::kOff:
return nullptr;
- case DarkMode::kSimpleInvertForTesting:
+ case DarkModeInversionAlgorithm::kSimpleInvertForTesting:
uint8_t identity[256], invert[256];
for (int i = 0; i < 256; ++i) {
identity[i] = i;
@@ -106,15 +106,15 @@ std::unique_ptr<DarkModeColorFilter> DarkModeColorFilter::FromSettings(
return std::make_unique<SkColorFilterWrapper>(
SkTableColorFilter::MakeARGB(identity, invert, invert, invert));
- case DarkMode::kInvertBrightness:
+ case DarkModeInversionAlgorithm::kInvertBrightness:
return std::make_unique<SkColorFilterWrapper>(SkColorFilterFromSettings(
SkHighContrastConfig::InvertStyle::kInvertBrightness, settings));
- case DarkMode::kInvertLightness:
+ case DarkModeInversionAlgorithm::kInvertLightness:
return std::make_unique<SkColorFilterWrapper>(SkColorFilterFromSettings(
SkHighContrastConfig::InvertStyle::kInvertLightness, settings));
- case DarkMode::kInvertLightnessLAB:
+ case DarkModeInversionAlgorithm::kInvertLightnessLAB:
return std::make_unique<LabColorFilter>();
}
NOTREACHED();
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 94cd199a889..0a10700da9f 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
@@ -31,7 +31,7 @@ bool AreFloatsEqual(float a, float b) {
void VerifySettingsAreUnchanged(const DarkModeSettings& a,
const DarkModeSettings& b) {
- if (a.mode == DarkMode::kOff)
+ if (a.mode == DarkModeInversionAlgorithm::kOff)
return;
DCHECK_EQ(a.image_policy, b.image_policy);
@@ -45,6 +45,7 @@ void VerifySettingsAreUnchanged(const DarkModeSettings& a,
bool ShouldApplyToImage(const DarkModeSettings& settings,
const FloatRect& src_rect,
+ const FloatRect& dest_rect,
Image* image) {
switch (settings.image_policy) {
case DarkModeImagePolicy::kFilterSmart: {
@@ -61,7 +62,8 @@ bool ShouldApplyToImage(const DarkModeSettings& settings,
break;
}
}
- DarkModeClassification result = classifier->Classify(image, src_rect);
+ DarkModeClassification result =
+ classifier->Classify(image, src_rect, dest_rect);
return result == DarkModeClassification::kApplyFilter;
}
case DarkModeImagePolicy::kFilterNone:
@@ -89,7 +91,7 @@ DarkModeFilter::DarkModeFilter()
color_filter_(nullptr),
image_filter_(nullptr) {
DarkModeSettings default_settings;
- default_settings.mode = DarkMode::kOff;
+ default_settings.mode = DarkModeInversionAlgorithm::kOff;
UpdateSettings(default_settings);
}
@@ -133,9 +135,11 @@ Color DarkModeFilter::InvertColorIfNeeded(const Color& color,
}
void DarkModeFilter::ApplyToImageFlagsIfNeeded(const FloatRect& src_rect,
+ const FloatRect& dest_rect,
Image* image,
cc::PaintFlags* flags) {
- if (!image_filter_ || !ShouldApplyToImage(settings(), src_rect, image))
+ if (!image_filter_ ||
+ !ShouldApplyToImage(settings(), src_rect, dest_rect, image))
return;
flags->setColorFilter(image_filter_);
}
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 81ccf42831c..6c96642010e 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
@@ -45,6 +45,7 @@ class PLATFORM_EXPORT DarkModeFilter {
// |image| and |flags| must not be null.
void ApplyToImageFlagsIfNeeded(const FloatRect& src_rect,
+ const FloatRect& dest_rect,
Image* image,
cc::PaintFlags* flags);
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 743c9e015e7..34e414d6175 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
@@ -19,7 +19,7 @@ TEST(DarkModeFilterTest, DoNotApplyFilterWhenDarkModeIsOff) {
DarkModeFilter filter;
DarkModeSettings settings;
- settings.mode = DarkMode::kOff;
+ settings.mode = DarkModeInversionAlgorithm::kOff;
filter.UpdateSettings(settings);
EXPECT_EQ(Color::kWhite,
@@ -38,7 +38,7 @@ TEST(DarkModeFilterTest, ApplyDarkModeToColorsAndFlags) {
DarkModeFilter filter;
DarkModeSettings settings;
- settings.mode = DarkMode::kSimpleInvertForTesting;
+ settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting;
filter.UpdateSettings(settings);
EXPECT_EQ(Color::kBlack,
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 2059816cfa3..906b4e781a0 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
@@ -33,25 +33,19 @@ const float kMinOpaquePixelPercentageForForeground = 0.2;
} // namespace
DarkModeImageClassifier::DarkModeImageClassifier()
- : pixels_to_sample_(kPixelsToSample) {}
+ : pixels_to_sample_(kPixelsToSample),
+ blocks_count_horizontal_(kBlocksCount1D),
+ blocks_count_vertical_(kBlocksCount1D) {}
DarkModeClassification DarkModeImageClassifier::Classify(
Image* image,
- const FloatRect& src_rect) {
+ const FloatRect& src_rect,
+ const FloatRect& dest_rect) {
DarkModeClassification result = image->GetDarkModeClassification(src_rect);
if (result != DarkModeClassification::kNotClassified)
return result;
- // TODO(v.paturi): This is a limitation that arises because of the way
- // GetSamples() is implemented. Try to get rid of this limitation.
- if (src_rect.Width() <= kBlocksCount1D ||
- src_rect.Height() <= kBlocksCount1D) {
- result = DarkModeClassification::kDoNotApplyFilter;
- image->AddDarkModeClassification(src_rect, result);
- return result;
- }
-
- result = image->CheckTypeSpecificConditionsForDarkMode(src_rect, this);
+ result = image->CheckTypeSpecificConditionsForDarkMode(dest_rect, this);
if (result != DarkModeClassification::kNotClassified) {
image->AddDarkModeClassification(src_rect, result);
return result;
@@ -77,6 +71,12 @@ DarkModeImageClassifier::GetFeatures(Image* image, const FloatRect& src_rect) {
if (pixels_to_sample_ > src_rect.Width() * src_rect.Height())
pixels_to_sample_ = src_rect.Width() * src_rect.Height();
+ if (blocks_count_horizontal_ > src_rect.Width())
+ blocks_count_horizontal_ = floor(src_rect.Width());
+
+ if (blocks_count_vertical_ > src_rect.Height())
+ blocks_count_vertical_ = floor(src_rect.Height());
+
float transparency_ratio;
float background_ratio;
Vector<SkColor> sampled_pixels;
@@ -97,26 +97,30 @@ void DarkModeImageClassifier::GetSamples(const SkBitmap& bitmap,
Vector<SkColor>* sampled_pixels,
float* transparency_ratio,
float* background_ratio) {
- int pixels_per_block = pixels_to_sample_ / (kBlocksCount1D * kBlocksCount1D);
+ int pixels_per_block =
+ pixels_to_sample_ / (blocks_count_horizontal_ * blocks_count_vertical_);
int transparent_pixels = 0;
int opaque_pixels = 0;
int blocks_count = 0;
- Vector<int> horizontal_grid(kBlocksCount1D + 1);
- Vector<int> vertical_grid(kBlocksCount1D + 1);
- for (int block = 0; block <= kBlocksCount1D; block++) {
- horizontal_grid[block] = static_cast<int>(
- round(block * bitmap.width() / static_cast<float>(kBlocksCount1D)));
- vertical_grid[block] = static_cast<int>(
- round(block * bitmap.height() / static_cast<float>(kBlocksCount1D)));
+ Vector<int> horizontal_grid(blocks_count_horizontal_ + 1);
+ Vector<int> vertical_grid(blocks_count_vertical_ + 1);
+
+ for (int block = 0; block <= blocks_count_horizontal_; block++) {
+ horizontal_grid[block] = static_cast<int>(round(
+ block * bitmap.width() / static_cast<float>(blocks_count_horizontal_)));
+ }
+ for (int block = 0; block <= blocks_count_vertical_; block++) {
+ vertical_grid[block] = static_cast<int>(round(
+ block * bitmap.height() / static_cast<float>(blocks_count_vertical_)));
}
sampled_pixels->clear();
Vector<IntRect> foreground_blocks;
- for (int y = 0; y < kBlocksCount1D; y++) {
- for (int x = 0; x < kBlocksCount1D; x++) {
+ for (int y = 0; y < blocks_count_vertical_; y++) {
+ for (int x = 0; x < blocks_count_horizontal_; x++) {
IntRect block(horizontal_grid[x], vertical_grid[y],
horizontal_grid[x + 1] - horizontal_grid[x],
vertical_grid[y + 1] - vertical_grid[y]);
@@ -239,4 +243,10 @@ float DarkModeImageClassifier::ComputeColorBucketsRatio(
max_buckets[color_mode == ColorMode::kColor];
}
+void DarkModeImageClassifier::ResetDataMembersToDefaults() {
+ pixels_to_sample_ = kPixelsToSample;
+ blocks_count_horizontal_ = kBlocksCount1D;
+ blocks_count_vertical_ = kBlocksCount1D;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h
index 259a1df7e37..a54f25937c3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h
@@ -22,7 +22,9 @@ class PLATFORM_EXPORT DarkModeImageClassifier {
DarkModeImageClassifier();
~DarkModeImageClassifier() = default;
- DarkModeClassification Classify(Image* image, const FloatRect& src_rect);
+ DarkModeClassification Classify(Image* image,
+ const FloatRect& src_rect,
+ const FloatRect& dest_rect);
struct Features {
// True if the image is in color, false if it is grayscale.
@@ -54,6 +56,24 @@ class PLATFORM_EXPORT DarkModeImageClassifier {
void SetImageType(ImageType image_type) { image_type_ = image_type; }
+ // Functions for testing.
+
+ void SetHorizontalBlocksCount(int horizontal_blocks) {
+ blocks_count_horizontal_ = horizontal_blocks;
+ }
+
+ void SetVerticalBlocksCount(int vertical_blocks) {
+ blocks_count_vertical_ = vertical_blocks;
+ }
+
+ int HorizontalBlocksCount() { return blocks_count_horizontal_; }
+
+ int VerticalBlocksCount() { return blocks_count_vertical_; }
+
+ void ResetDataMembersToDefaults();
+
+ // End of Functions for testing.
+
private:
enum class ColorMode { kColor = 0, kGrayscale = 1 };
@@ -86,6 +106,12 @@ class PLATFORM_EXPORT DarkModeImageClassifier {
const ColorMode color_mode);
int pixels_to_sample_;
+ // Holds the number of blocks in the horizontal direction when the image is
+ // divided into a grid of blocks.
+ int blocks_count_horizontal_;
+ // Holds the number of blocks in the vertical direction when the image is
+ // divided into a grid of blocks.
+ int blocks_count_vertical_;
ImageType image_type_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc
index 8d30e9c8b28..9a38e0dd1ad 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc
@@ -54,43 +54,49 @@ class FakeImageForCacheTest : public Image {
class DarkModeImageClassifierTest : public testing::Test {
public:
- // Loads the image from |file_name|, computes features into |features|,
- // and returns the classification result.
- bool GetFeaturesAndClassification(
- const String& file_name,
- DarkModeImageClassifier::Features* features) {
- CHECK(features);
+ // Loads the image from |file_name|.
+ scoped_refptr<BitmapImage> GetImage(const String& file_name) {
SCOPED_TRACE(file_name);
- scoped_refptr<BitmapImage> image = LoadImage(file_name);
- DarkModeImageClassifier dark_mode_image_classifier;
- dark_mode_image_classifier.SetImageType(
+ String file_path = test::BlinkWebTestsDir() + file_name;
+ scoped_refptr<SharedBuffer> image_data = test::ReadFromFile(file_path);
+ EXPECT_TRUE(image_data.get() && image_data.get()->size());
+
+ scoped_refptr<BitmapImage> image = BitmapImage::Create();
+ image->SetData(image_data, true);
+ return image;
+ }
+
+ // Computes features into |features|.
+ void GetFeatures(scoped_refptr<BitmapImage> image,
+ DarkModeImageClassifier::Features* features) {
+ CHECK(features);
+ dark_mode_image_classifier_.SetImageType(
DarkModeImageClassifier::ImageType::kBitmap);
- auto features_or_null = dark_mode_image_classifier.GetFeatures(
+ auto features_or_null = dark_mode_image_classifier_.GetFeatures(
image.get(), FloatRect(0, 0, image->width(), image->height()));
CHECK(features_or_null.has_value());
(*features) = features_or_null.value();
+ }
+
+ // Returns the classification result.
+ bool GetClassification(const DarkModeImageClassifier::Features features) {
DarkModeClassification result =
- dark_mode_generic_classifier_.ClassifyWithFeatures(*features);
+ dark_mode_generic_classifier_.ClassifyWithFeatures(features);
return result == DarkModeClassification::kApplyFilter;
}
- DarkModeGenericClassifier* classifier() {
- return &dark_mode_generic_classifier_;
+ DarkModeImageClassifier* image_classifier() {
+ return &dark_mode_image_classifier_;
}
- protected:
- scoped_refptr<BitmapImage> LoadImage(const String& file_name) {
- String file_path = test::BlinkWebTestsDir() + file_name;
- scoped_refptr<SharedBuffer> image_data = test::ReadFromFile(file_path);
- EXPECT_TRUE(image_data.get() && image_data.get()->size());
-
- scoped_refptr<BitmapImage> image = BitmapImage::Create();
- image->SetData(image_data, true);
- return image;
+ DarkModeGenericClassifier* generic_classifier() {
+ return &dark_mode_generic_classifier_;
}
+ protected:
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
+ DarkModeImageClassifier dark_mode_image_classifier_;
DarkModeGenericClassifier dark_mode_generic_classifier_;
};
@@ -102,9 +108,13 @@ TEST_F(DarkModeImageClassifierTest, FeaturesAndClassification) {
// Color Buckets Ratio: Low
// Decision Tree: Apply
// Neural Network: NA
- EXPECT_TRUE(GetFeaturesAndClassification("/images/resources/grid-large.png",
- &features));
- EXPECT_EQ(classifier()->ClassifyUsingDecisionTreeForTesting(features),
+
+ // The data members of DarkModeImageClassifier have to be reset for every
+ // image as the same classifier object is used for all the tests.
+ image_classifier()->ResetDataMembersToDefaults();
+ GetFeatures(GetImage("/images/resources/grid-large.png"), &features);
+ EXPECT_TRUE(GetClassification(features));
+ EXPECT_EQ(generic_classifier()->ClassifyUsingDecisionTreeForTesting(features),
DarkModeClassification::kApplyFilter);
EXPECT_FALSE(features.is_colorful);
EXPECT_FALSE(features.is_svg);
@@ -117,9 +127,10 @@ TEST_F(DarkModeImageClassifierTest, FeaturesAndClassification) {
// Color Buckets Ratio: Medium
// Decision Tree: Can't Decide
// Neural Network: Apply
- EXPECT_FALSE(GetFeaturesAndClassification("/images/resources/apng08-ref.png",
- &features));
- EXPECT_EQ(classifier()->ClassifyUsingDecisionTreeForTesting(features),
+ image_classifier()->ResetDataMembersToDefaults();
+ GetFeatures(GetImage("/images/resources/apng08-ref.png"), &features);
+ EXPECT_FALSE(GetClassification(features));
+ EXPECT_EQ(generic_classifier()->ClassifyUsingDecisionTreeForTesting(features),
DarkModeClassification::kNotClassified);
EXPECT_FALSE(features.is_colorful);
EXPECT_FALSE(features.is_svg);
@@ -132,9 +143,10 @@ TEST_F(DarkModeImageClassifierTest, FeaturesAndClassification) {
// Color Buckets Ratio: Low
// Decision Tree: Apply
// Neural Network: NA.
- EXPECT_TRUE(GetFeaturesAndClassification(
- "/images/resources/twitter_favicon.ico", &features));
- EXPECT_EQ(classifier()->ClassifyUsingDecisionTreeForTesting(features),
+ image_classifier()->ResetDataMembersToDefaults();
+ GetFeatures(GetImage("/images/resources/twitter_favicon.ico"), &features);
+ EXPECT_TRUE(GetClassification(features));
+ EXPECT_EQ(generic_classifier()->ClassifyUsingDecisionTreeForTesting(features),
DarkModeClassification::kApplyFilter);
EXPECT_TRUE(features.is_colorful);
EXPECT_FALSE(features.is_svg);
@@ -147,9 +159,11 @@ TEST_F(DarkModeImageClassifierTest, FeaturesAndClassification) {
// Color Buckets Ratio: High
// Decision Tree: Do Not Apply
// Neural Network: NA.
- EXPECT_FALSE(GetFeaturesAndClassification(
- "/images/resources/blue-wheel-srgb-color-profile.png", &features));
- EXPECT_EQ(classifier()->ClassifyUsingDecisionTreeForTesting(features),
+ image_classifier()->ResetDataMembersToDefaults();
+ GetFeatures(GetImage("/images/resources/blue-wheel-srgb-color-profile.png"),
+ &features);
+ EXPECT_FALSE(GetClassification(features));
+ EXPECT_EQ(generic_classifier()->ClassifyUsingDecisionTreeForTesting(features),
DarkModeClassification::kDoNotApplyFilter);
EXPECT_TRUE(features.is_colorful);
EXPECT_FALSE(features.is_svg);
@@ -162,9 +176,10 @@ TEST_F(DarkModeImageClassifierTest, FeaturesAndClassification) {
// Color Buckets Ratio: Medium
// Decision Tree: Apply
// Neural Network: NA.
- EXPECT_TRUE(GetFeaturesAndClassification(
- "/images/resources/ycbcr-444-float.jpg", &features));
- EXPECT_EQ(classifier()->ClassifyUsingDecisionTreeForTesting(features),
+ image_classifier()->ResetDataMembersToDefaults();
+ GetFeatures(GetImage("/images/resources/ycbcr-444-float.jpg"), &features);
+ EXPECT_TRUE(GetClassification(features));
+ EXPECT_EQ(generic_classifier()->ClassifyUsingDecisionTreeForTesting(features),
DarkModeClassification::kApplyFilter);
EXPECT_TRUE(features.is_colorful);
EXPECT_FALSE(features.is_svg);
@@ -201,4 +216,41 @@ TEST_F(DarkModeImageClassifierTest, Caching) {
EXPECT_EQ(image->GetMapSize(), 3);
}
+TEST_F(DarkModeImageClassifierTest, BlocksCount) {
+ scoped_refptr<BitmapImage> image =
+ GetImage("/images/resources/grid-large.png");
+ DarkModeImageClassifier::Features features;
+ image_classifier()->ResetDataMembersToDefaults();
+
+ // When the horizontal and vertical blocks counts are lesser than the
+ // image dimensions, they should remain unaltered.
+ image_classifier()->SetHorizontalBlocksCount((int)(image->width() - 1));
+ image_classifier()->SetVerticalBlocksCount((int)(image->height() - 1));
+ GetFeatures(image, &features);
+ EXPECT_EQ(image_classifier()->HorizontalBlocksCount(),
+ (int)(image->width() - 1));
+ EXPECT_EQ(image_classifier()->VerticalBlocksCount(),
+ (int)(image->height() - 1));
+
+ // When the horizontal and vertical blocks counts are lesser than the
+ // image dimensions, they should remain unaltered.
+ image_classifier()->SetHorizontalBlocksCount((int)(image->width()));
+ image_classifier()->SetVerticalBlocksCount((int)(image->height()));
+ GetFeatures(image, &features);
+ EXPECT_EQ(image_classifier()->HorizontalBlocksCount(),
+ (int)(image->width()));
+ EXPECT_EQ(image_classifier()->VerticalBlocksCount(),
+ (int)(image->height()));
+
+ // When the horizontal and vertical blocks counts are greater than the
+ // image dimensions, they should be reduced.
+ image_classifier()->SetHorizontalBlocksCount((int)(image->width() + 1));
+ image_classifier()->SetVerticalBlocksCount((int)(image->height() + 1));
+ GetFeatures(image, &features);
+ EXPECT_EQ(image_classifier()->HorizontalBlocksCount(),
+ floor(image->width()));
+ EXPECT_EQ(image_classifier()->VerticalBlocksCount(),
+ floor(image->height()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings.h b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
index 4d3cd756b83..babdfb632bf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/dark_mode_settings.h
@@ -7,8 +7,10 @@
namespace blink {
-enum class DarkMode {
+enum class DarkModeInversionAlgorithm {
// Default, drawing is unfiltered.
+ // TODO(https://crbug.com/1002664): This value is deprecated and in the
+ // process of being removed.
kOff,
// For testing only, does a simple 8-bit invert of every RGB pixel component.
kSimpleInvertForTesting,
@@ -42,7 +44,7 @@ enum class DarkModeClassifierType {
// BuildDarkModeSettings() in
// //src/third_party/blink/renderer/core/accessibility/apply_dark_mode.h
struct DarkModeSettings {
- DarkMode mode = DarkMode::kOff;
+ DarkModeInversionAlgorithm mode = DarkModeInversionAlgorithm::kOff;
bool grayscale = false;
float image_grayscale_percent = 0.0; // Valid range from 0.0 to 1.0
float contrast = 0.0; // Valid range from -1.0 to 1.0
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 ddde5f68126..40567fed4d5 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
@@ -25,8 +25,8 @@
#include "third_party/blink/renderer/platform/graphics/decoding_image_generator.h"
-#include <utility>
#include <memory>
+#include <utility>
#include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
@@ -39,27 +39,6 @@
namespace blink {
-namespace {
-
-// These filename extension strings come from ImageDecoder::FilenameExtension.
-PaintImage::ImageType FileExtensionToImageType(String image_extension) {
- if (image_extension == "png")
- return PaintImage::ImageType::kPNG;
- if (image_extension == "jpg")
- return PaintImage::ImageType::kJPEG;
- if (image_extension == "webp")
- return PaintImage::ImageType::kWEBP;
- if (image_extension == "gif")
- return PaintImage::ImageType::kGIF;
- if (image_extension == "ico")
- return PaintImage::ImageType::kICO;
- if (image_extension == "bmp")
- return PaintImage::ImageType::kBMP;
- return PaintImage::ImageType::kInvalid;
-}
-
-} // namespace
-
// static
std::unique_ptr<SkImageGenerator>
DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
@@ -88,11 +67,13 @@ DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
WebVector<FrameMetadata> frames;
frames.emplace_back(FrameMetadata());
+ cc::ImageHeaderMetadata image_metadata =
+ decoder->MakeMetadataForDecodeAcceleration();
+ image_metadata.all_data_received_prior_to_decode = true;
sk_sp<DecodingImageGenerator> generator = DecodingImageGenerator::Create(
std::move(frame), info, std::move(segment_reader), std::move(frames),
PaintImage::GetNextContentId(), true /* all_data_received */,
- true /* is_eligible_for_accelerated_decoding */,
- false /* can_yuv_decode */, decoder->FilenameExtension());
+ false /* can_yuv_decode */, image_metadata);
return std::make_unique<SkiaPaintImageGenerator>(
std::move(generator), PaintImage::kDefaultFrameIndex,
PaintImage::kDefaultGeneratorClientId);
@@ -106,14 +87,11 @@ sk_sp<DecodingImageGenerator> DecodingImageGenerator::Create(
WebVector<FrameMetadata> frames,
PaintImage::ContentId content_id,
bool all_data_received,
- bool is_eligible_for_accelerated_decoding,
bool can_yuv_decode,
- String image_type) {
- PaintImage::ImageType paint_image_type = FileExtensionToImageType(image_type);
+ const cc::ImageHeaderMetadata& image_metadata) {
return sk_sp<DecodingImageGenerator>(new DecodingImageGenerator(
std::move(frame_generator), info, std::move(data), std::move(frames),
- content_id, all_data_received, is_eligible_for_accelerated_decoding,
- can_yuv_decode, paint_image_type));
+ content_id, all_data_received, can_yuv_decode, image_metadata));
}
DecodingImageGenerator::DecodingImageGenerator(
@@ -123,25 +101,18 @@ DecodingImageGenerator::DecodingImageGenerator(
WebVector<FrameMetadata> frames,
PaintImage::ContentId complete_frame_content_id,
bool all_data_received,
- bool is_eligible_for_accelerated_decoding,
bool can_yuv_decode,
- PaintImage::ImageType image_type)
+ const cc::ImageHeaderMetadata& image_metadata)
: PaintImageGenerator(info, frames.ReleaseVector()),
frame_generator_(std::move(frame_generator)),
data_(std::move(data)),
all_data_received_(all_data_received),
- is_eligible_for_accelerated_decoding_(
- is_eligible_for_accelerated_decoding),
can_yuv_decode_(can_yuv_decode),
complete_frame_content_id_(complete_frame_content_id),
- image_type_(image_type) {}
+ image_metadata_(image_metadata) {}
DecodingImageGenerator::~DecodingImageGenerator() = default;
-bool DecodingImageGenerator::IsEligibleForAcceleratedDecoding() const {
- return is_eligible_for_accelerated_decoding_;
-}
-
sk_sp<SkData> DecodingImageGenerator::GetEncodedData() const {
TRACE_EVENT0("blink", "DecodingImageGenerator::refEncodedData");
@@ -317,4 +288,9 @@ PaintImage::ContentId DecodingImageGenerator::GetContentIdForFrame(
return PaintImageGenerator::GetContentIdForFrame(frame_index);
}
+const cc::ImageHeaderMetadata*
+DecodingImageGenerator::GetMetadataForDecodeAcceleration() const {
+ return &image_metadata_;
+}
+
} // namespace blink
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 aeb18534224..b72f3bddc85 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
@@ -63,14 +63,12 @@ class PLATFORM_EXPORT DecodingImageGenerator final
WebVector<FrameMetadata>,
PaintImage::ContentId,
bool all_data_received,
- bool is_eligible_for_accelerated_decoding,
bool can_yuv_decode,
- String image_type);
+ const cc::ImageHeaderMetadata& image_metadata);
~DecodingImageGenerator() override;
// PaintImageGenerator implementation.
- bool IsEligibleForAcceleratedDecoding() const override;
sk_sp<SkData> GetEncodedData() const override;
bool GetPixels(const SkImageInfo&,
void* pixels,
@@ -88,7 +86,8 @@ class PLATFORM_EXPORT DecodingImageGenerator final
uint32_t lazy_pixel_ref) override;
SkISize GetSupportedDecodeSize(const SkISize& requested_size) const override;
PaintImage::ContentId GetContentIdForFrame(size_t frame_index) const override;
- PaintImage::ImageType GetImageType() const override { return image_type_; }
+ const cc::ImageHeaderMetadata* GetMetadataForDecodeAcceleration()
+ const override;
private:
DecodingImageGenerator(scoped_refptr<ImageFrameGenerator>,
@@ -97,19 +96,20 @@ class PLATFORM_EXPORT DecodingImageGenerator final
WebVector<FrameMetadata>,
PaintImage::ContentId,
bool all_data_received,
- bool is_eligible_for_accelerated_decoding,
bool can_yuv_decode,
- PaintImage::ImageType image_type);
+ const cc::ImageHeaderMetadata& image_metadata);
scoped_refptr<ImageFrameGenerator> frame_generator_;
const scoped_refptr<SegmentReader> data_; // Data source.
const bool all_data_received_;
- const bool is_eligible_for_accelerated_decoding_;
const bool can_yuv_decode_;
const PaintImage::ContentId complete_frame_content_id_;
- // The image file kind as returned by the underlying decoder and
- // translated into PaintImage::ImageType.
- const PaintImage::ImageType image_type_;
+
+ // Image metadata, such as format (e.g. Jpeg or WebP), YUV subsampling factor
+ // (e.g. 444, 422, 420, etc.), size, and format-specific information that is
+ // 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);
};
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 22add864e28..6141df1b539 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
@@ -36,7 +36,6 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/skia/include/core/SkImage.h"
@@ -234,11 +233,14 @@ sk_sp<PaintImageGenerator> DeferredImageDecoder::CreateGenerator(size_t index) {
// common, so we avoid worrying about this with the line below.
can_yuv_decode_ &= !incremental_decode_needed_.value();
+ DCHECK(image_metadata_);
+ image_metadata_->all_data_received_prior_to_decode =
+ !incremental_decode_needed_.value();
+
auto generator = DecodingImageGenerator::Create(
frame_generator_, info, std::move(segment_reader), std::move(frames),
- complete_frame_content_id_, all_data_received_,
- !incremental_decode_needed_.value() /* able to do accelerated decoding */,
- can_yuv_decode_, image_type);
+ complete_frame_content_id_, all_data_received_, can_yuv_decode_,
+ *image_metadata_);
first_decoding_generator_created_ = true;
size_t image_byte_size = ByteSize();
@@ -418,10 +420,12 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
}
can_yuv_decode_ =
- RuntimeEnabledFeatures::DecodeLossyWebPImagesToYUVEnabled() &&
metadata_decoder_->CanDecodeToYUV() && all_data_received_ &&
!frame_generator_->IsMultiFrame();
+ if (!image_metadata_)
+ image_metadata_ = metadata_decoder_->MakeMetadataForDecodeAcceleration();
+
// If we've received all of the data, then we can reset the metadata decoder,
// since everything we care about should now be stored in |frame_data_|.
if (all_data_received_) {
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 8f590958e61..d7a069b0590 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
@@ -120,6 +120,10 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
const PaintImage::ContentId complete_frame_content_id_;
base::Optional<bool> incremental_decode_needed_;
+ // Caches an image's metadata so it can outlive |metadata_decoder_| after all
+ // data is received in cases where multiple generators are created.
+ base::Optional<cc::ImageHeaderMetadata> image_metadata_;
+
// Caches frame state information.
Vector<DeferredFrameData> frame_data_;
scoped_refptr<ImageFrameGenerator> frame_generator_;
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 eb53eebe75e..da3ee02e80b 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
@@ -199,47 +199,50 @@ TEST_F(DeferredImageDecoderTest, drawIntoPaintRecordProgressive) {
EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
}
-TEST_F(DeferredImageDecoderTest, isEligibleForHardwareDecodingNonIncremental) {
- // The image is received completely. This is okay for hardware decoding since
- // it's assumed that the software decoder hasn't done any work.
+TEST_F(DeferredImageDecoderTest, allDataReceivedPriorToDecodeNonIncrementally) {
+ // The image is received completely at once.
lazy_decoder_->SetData(data_, true /* all_data_received */);
PaintImage image = CreatePaintImage();
ASSERT_TRUE(image);
- EXPECT_TRUE(image.IsEligibleForAcceleratedDecoding());
+ ASSERT_TRUE(image.GetImageHeaderMetadata());
+ EXPECT_TRUE(
+ image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
}
-TEST_F(DeferredImageDecoderTest, isEligibleForHardwareDecodingIncremental) {
+TEST_F(DeferredImageDecoderTest, allDataReceivedPriorToDecodeIncrementally) {
// The image is received in two parts, but a PaintImageGenerator is created
- // only after all the data is received. This is okay for hardware decoding
- // since it's assumed that the software decoder hasn't done any work before
- // the PaintImageGenerator is created.
+ // only after all the data is received.
scoped_refptr<SharedBuffer> partial_data =
SharedBuffer::Create(data_->Data(), data_->size() - 10);
lazy_decoder_->SetData(partial_data, false /* all_data_received */);
lazy_decoder_->SetData(data_, true /* all_data_received */);
PaintImage image = CreatePaintImage();
ASSERT_TRUE(image);
- EXPECT_TRUE(image.IsEligibleForAcceleratedDecoding());
+ ASSERT_TRUE(image.GetImageHeaderMetadata());
+ EXPECT_TRUE(
+ image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
}
-TEST_F(DeferredImageDecoderTest, isNotEligibleForHardwareDecoding) {
+TEST_F(DeferredImageDecoderTest, notAllDataReceivedPriorToDecode) {
// The image is received in two parts, and a PaintImageGenerator is created
// for each one. In real usage, it's likely that the software image decoder
- // will start working with partial data, so there's no point in using the
- // hardware accelerator (because if we did, we'd be doing double work: in
- // software and in hardware).
+ // will start working with partial data.
scoped_refptr<SharedBuffer> partial_data =
SharedBuffer::Create(data_->Data(), data_->size() - 10);
lazy_decoder_->SetData(partial_data, false /* all_data_received */);
PaintImage image =
CreatePaintImage(PaintImage::CompletionState::PARTIALLY_DONE);
ASSERT_TRUE(image);
- EXPECT_FALSE(image.IsEligibleForAcceleratedDecoding());
+ ASSERT_TRUE(image.GetImageHeaderMetadata());
+ EXPECT_FALSE(
+ image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
lazy_decoder_->SetData(data_, true /* all_data_received */);
image = CreatePaintImage();
ASSERT_TRUE(image);
- EXPECT_FALSE(image.IsEligibleForAcceleratedDecoding());
+ ASSERT_TRUE(image.GetImageHeaderMetadata());
+ EXPECT_FALSE(
+ image.GetImageHeaderMetadata()->all_data_received_prior_to_decode);
}
static void RasterizeMain(cc::PaintCanvas* canvas, sk_sp<PaintRecord> record) {
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 688ad342ef4..cec2f5c1208 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
@@ -48,9 +48,7 @@ enum FilterEffectType {
kFilterEffectTypeSourceInput
};
-class PLATFORM_EXPORT FilterEffect
- : public GarbageCollectedFinalized<FilterEffect> {
-
+class PLATFORM_EXPORT FilterEffect : public GarbageCollected<FilterEffect> {
public:
virtual ~FilterEffect();
virtual void Trace(blink::Visitor*);
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 594e4408c43..0007fdc67c5 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
@@ -12,15 +12,15 @@ namespace blink {
DawnControlClientHolder::DawnControlClientHolder(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider)
: context_provider_(std::move(context_provider)),
- interface_(context_provider_->WebGPUInterface()),
- destroyed_(false) {}
+ interface_(context_provider_->WebGPUInterface()) {}
-void DawnControlClientHolder::MarkDestroyed() {
- destroyed_ = true;
+void DawnControlClientHolder::Destroy() {
+ interface_ = nullptr;
+ context_provider_.reset();
}
bool DawnControlClientHolder::IsDestroyed() const {
- return destroyed_;
+ return !interface_;
}
WebGraphicsContext3DProvider* DawnControlClientHolder::GetContextProvider()
@@ -29,12 +29,11 @@ WebGraphicsContext3DProvider* DawnControlClientHolder::GetContextProvider()
}
gpu::webgpu::WebGPUInterface* DawnControlClientHolder::GetInterface() const {
- DCHECK(!destroyed_);
+ DCHECK(interface_);
return interface_;
}
const DawnProcTable& DawnControlClientHolder::GetProcs() const {
- DCHECK(!destroyed_);
DCHECK(interface_);
return interface_->GetProcs();
}
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 20e93d3e591..af143834c51 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
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_DAWN_CONTROL_CLIENT_HOLDER_H_
#include <dawn/dawn.h>
+#include <dawn/dawn_proc_table.h>
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -22,15 +23,15 @@ class WebGPUInterface;
namespace blink {
// This class holds the WebGPUInterface and a |destroyed_| flag.
-// DawnControlClientHolder::MarkDestroyed() should be called if the
-// backing WebGPUInterface has been destroyed.
+// DawnControlClientHolder::Destroy() should be called to destroy the backing
+// WebGPUInterface.
class PLATFORM_EXPORT DawnControlClientHolder
: public RefCounted<DawnControlClientHolder> {
public:
DawnControlClientHolder(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider);
- void MarkDestroyed();
+ void Destroy();
bool IsDestroyed() const;
WebGraphicsContext3DProvider* GetContextProvider() const;
@@ -43,7 +44,6 @@ class PLATFORM_EXPORT DawnControlClientHolder
std::unique_ptr<WebGraphicsContext3DProvider> context_provider_;
gpu::webgpu::WebGPUInterface* interface_;
- bool destroyed_;
};
} // namespace blink
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 d54fa99d5cb..65b672a3573 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
@@ -253,6 +253,8 @@ void DrawingBuffer::SetIsHidden(bool hidden) {
is_hidden_ = hidden;
if (is_hidden_)
recycled_color_buffer_queue_.clear();
+ gl_->ContextVisibilityHintCHROMIUM(is_hidden_ ? GL_FALSE : GL_TRUE);
+ gl_->Flush();
}
void DrawingBuffer::SetFilterQuality(SkFilterQuality filter_quality) {
@@ -557,9 +559,10 @@ scoped_refptr<StaticBitmapImage> DrawingBuffer::TransferToStaticBitmapImage(
// to transferToImageBitmap are made back-to-back, or when the context gets
// lost. We intentionally leave the transparent black image in legacy color
// space.
- sk_sp<SkSurface> surface =
- SkSurface::MakeRasterN32Premul(size_.Width(), size_.Height());
- return StaticBitmapImage::Create(surface->makeImageSnapshot());
+ SkBitmap black_bitmap;
+ black_bitmap.allocN32Pixels(size_.Width(), size_.Height());
+ black_bitmap.eraseARGB(0, 0, 0, 0);
+ return StaticBitmapImage::Create(SkImage::MakeFromBitmap(black_bitmap));
}
DCHECK_EQ(size_.Width(), transferable_resource.size.width());
@@ -670,12 +673,11 @@ DrawingBuffer::ColorBuffer::~ColorBuffer() {
sii->DestroySharedImage(receive_sync_token, mailbox);
gpu_memory_buffer.reset();
- gl->DeleteTextures(1, &texture_id);
- if (rgb_workaround_texture_id) {
- sii->DestroySharedImage(receive_sync_token, rgb_workaround_mailbox);
- // Avoid deleting this texture if it was unused.
- gl->DeleteTextures(1, &rgb_workaround_texture_id);
- }
+ gl->DeleteTextures(1u, &texture_id);
+
+ // Avoid deleting this texture if it was unused.
+ if (rgb_workaround_texture_id)
+ gl->DeleteTextures(1u, &rgb_workaround_texture_id);
}
bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
@@ -810,16 +812,6 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
allocate_alpha_channel_ = false;
have_alpha_channel_ = true;
}
- if (UsingSwapChain()) {
- // Swap chains always have an alpha channel, and multisample resolve
- // doesn't work if we pretend we don't have one.
- // This configuration will
- // - allow invalid CopyTexImage to RGBA targets
- // - fail valid FramebufferBlit from RGB targets
- // TODO(sunnyps): Copy into intermediate texture for blitFramebuffer.
- allocate_alpha_channel_ = true;
- have_alpha_channel_ = true;
- }
}
state_restorer_->SetFramebufferBindingDirty();
@@ -1071,33 +1063,9 @@ bool DrawingBuffer::ResizeDefaultFramebuffer(const IntSize& size) {
AttachColorBufferToReadFramebuffer();
if (WantExplicitResolve()) {
- state_restorer_->SetFramebufferBindingDirty();
- state_restorer_->SetRenderbufferBindingDirty();
- gl_->BindFramebuffer(GL_FRAMEBUFFER, multisample_fbo_);
- gl_->BindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffer_);
- // Note that the multisample rendertarget will allocate an alpha channel
- // based on |have_alpha_channel_|, not |allocate_alpha_channel_|, since it
- // will resolve into the ColorBuffer.
- GLenum internal_format = have_alpha_channel_ ? GL_RGBA8_OES : GL_RGB8_OES;
- if (use_half_float_storage_) {
- DCHECK(want_alpha_channel_);
- internal_format = GL_RGBA16F_EXT;
- }
- if (has_eqaa_support) {
- gl_->RenderbufferStorageMultisampleAdvancedAMD(
- GL_RENDERBUFFER, sample_count_, eqaa_storage_sample_count_,
- internal_format, size.Width(), size.Height());
- } else {
- gl_->RenderbufferStorageMultisampleCHROMIUM(
- GL_RENDERBUFFER, sample_count_, internal_format, size.Width(),
- size.Height());
- }
-
- if (gl_->GetError() == GL_OUT_OF_MEMORY)
+ if (!ReallocateMultisampleRenderbuffer(size)) {
return false;
-
- gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, multisample_renderbuffer_);
+ }
}
if (WantDepthOrStencil()) {
@@ -1276,6 +1244,47 @@ void DrawingBuffer::ResolveIfNeeded() {
!contents_change_resolved_)
ResolveMultisampleFramebufferInternal();
contents_change_resolved_ = true;
+
+ auto* gl = ContextProvider()->ContextGL();
+ if (gl->DidGpuSwitch() == GL_TRUE) {
+ // TODO(crbug.com/681341): handle preserveDrawingBuffer:true, and
+ // user-allocated multisampled renderbuffers, by dispatching a context lost
+ // event.
+ if (WantExplicitResolve()) {
+ ReallocateMultisampleRenderbuffer(size_);
+ }
+ }
+}
+
+bool DrawingBuffer::ReallocateMultisampleRenderbuffer(const IntSize& size) {
+ state_restorer_->SetFramebufferBindingDirty();
+ state_restorer_->SetRenderbufferBindingDirty();
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, multisample_fbo_);
+ gl_->BindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffer_);
+ // Note that the multisample rendertarget will allocate an alpha channel
+ // based on |have_alpha_channel_|, not |allocate_alpha_channel_|, since it
+ // will resolve into the ColorBuffer.
+ GLenum internal_format = have_alpha_channel_ ? GL_RGBA8_OES : GL_RGB8_OES;
+ if (use_half_float_storage_) {
+ DCHECK(want_alpha_channel_);
+ internal_format = GL_RGBA16F_EXT;
+ }
+ if (has_eqaa_support) {
+ gl_->RenderbufferStorageMultisampleAdvancedAMD(
+ GL_RENDERBUFFER, sample_count_, eqaa_storage_sample_count_,
+ internal_format, size.Width(), size.Height());
+ } else {
+ gl_->RenderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, sample_count_,
+ internal_format, size.Width(),
+ size.Height());
+ }
+
+ if (gl_->GetError() == GL_OUT_OF_MEMORY)
+ return false;
+
+ gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, multisample_renderbuffer_);
+ return true;
}
void DrawingBuffer::RestoreFramebufferBindings() {
@@ -1301,7 +1310,7 @@ void DrawingBuffer::Bind(GLenum target) {
gl_->BindFramebuffer(target, WantExplicitResolve() ? multisample_fbo_ : fbo_);
}
-scoped_refptr<Uint8Array> DrawingBuffer::PaintRenderingResultsToDataArray(
+sk_sp<SkData> DrawingBuffer::PaintRenderingResultsToDataArray(
SourceDrawingBuffer source_buffer) {
ScopedStateRestorer scoped_state_restorer(this);
@@ -1318,19 +1327,10 @@ scoped_refptr<Uint8Array> DrawingBuffer::PaintRenderingResultsToDataArray(
if (!data_size.IsValid())
return nullptr;
- unsigned byte_length = width * height * 4;
- if (RuntimeEnabledFeatures::CanvasColorManagementEnabled() &&
- use_half_float_storage_) {
- byte_length *= 2;
- }
- scoped_refptr<ArrayBuffer> dst_buffer =
- ArrayBuffer::CreateOrNull(byte_length, 1);
+ unsigned byte_length = data_size.ValueOrDie<unsigned>();
+ sk_sp<SkData> dst_buffer = TryAllocateSkData(byte_length);
if (!dst_buffer)
return nullptr;
- scoped_refptr<Uint8Array> data_array =
- Uint8Array::Create(std::move(dst_buffer), 0, byte_length);
- if (!data_array)
- return nullptr;
GLuint fbo = 0;
state_restorer_->SetFramebufferBindingDirty();
@@ -1344,10 +1344,10 @@ scoped_refptr<Uint8Array> DrawingBuffer::PaintRenderingResultsToDataArray(
gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
}
- ReadBackFramebuffer(static_cast<unsigned char*>(data_array->Data()), width,
- height, kReadbackRGBA,
+ auto* writable_data = static_cast<uint8_t*>(dst_buffer->writable_data());
+ ReadBackFramebuffer(writable_data, width, height, kReadbackRGBA,
WebGLImageConversion::kAlphaDoNothing);
- FlipVertically(static_cast<uint8_t*>(data_array->Data()), width, height);
+ FlipVertically(writable_data, width, height);
if (fbo) {
gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
@@ -1355,7 +1355,7 @@ scoped_refptr<Uint8Array> DrawingBuffer::PaintRenderingResultsToDataArray(
gl_->DeleteFramebuffers(1, &fbo);
}
- return data_array;
+ return dst_buffer;
}
void DrawingBuffer::ReadBackFramebuffer(unsigned char* pixels,
@@ -1502,7 +1502,6 @@ scoped_refptr<DrawingBuffer::ColorBuffer> DrawingBuffer::CreateColorBuffer(
format = use_half_float_storage_ ? viz::RGBA_F16 : viz::RGBA_8888;
} else {
DCHECK(!use_half_float_storage_);
- DCHECK(!UsingSwapChain());
format = viz::RGBX_8888;
}
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 2cd5b3a58d1..2aa58412c39 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
@@ -235,8 +235,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
const IntRect& src_sub_rectangle,
SourceDrawingBuffer);
- scoped_refptr<Uint8Array> PaintRenderingResultsToDataArray(
- SourceDrawingBuffer);
+ sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer);
int SampleCount() const { return sample_count_; }
bool ExplicitResolveOfMultisampleData() const {
@@ -367,9 +366,6 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// situation (the alpha channel is zeroed), requiring more fixups.
GLuint rgb_workaround_texture_id = 0;
- // The mailbox for |rgb_workaround_texture_id|.
- gpu::Mailbox rgb_workaround_mailbox;
-
// The mailbox used to send this buffer to the compositor.
gpu::Mailbox mailbox;
@@ -478,6 +474,10 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
bool SetupRGBEmulationForBlitFramebuffer(bool is_user_draw_framebuffer_bound);
void CleanupRGBEmulationForBlitFramebuffer();
+ // Reallocate Multisampled renderbuffer, used by explicit resolve when resize
+ // and GPU switch
+ bool ReallocateMultisampleRenderbuffer(const IntSize&);
+
// Weak, reset by beginDestruction.
Client* client_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
index e4a3331a283..68c1c5063ca 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
@@ -36,7 +36,7 @@ void GrTextureMailboxReleaseProc(void* data) {
namespace blink {
-void GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
+bool GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
GLenum& out_texture_target,
const sk_sp<SkImage>& image,
GLenum filter) {
@@ -51,6 +51,9 @@ void GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
DCHECK(gr);
DCHECK(gl);
GrTexture* gr_texture = image->getTexture();
+ if (!gr_texture)
+ return false;
+
DCHECK(gr == gr_texture->getContext());
GrBackendTexture backend_texture = image->getBackendTexture(true);
@@ -84,6 +87,7 @@ void GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
gl->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl->BindTexture(texture_target, 0);
gr_texture->textureParamsModified();
+ return true;
}
void GraphicsContext3DUtils::RegisterMailbox(GrTexture* gr_texture,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
index f103ac3c74d..403becdd9f4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
@@ -34,7 +34,7 @@ class PLATFORM_EXPORT GraphicsContext3DUtils {
// mailbox for a given texture. The caching of pre-existing mailboxes survives
// when the texture gets recycled by skia for creating a new SkSurface or
// SkImage with a pre-existing GrTexture backing.
- void GetMailboxForSkImage(gpu::Mailbox&,
+ bool GetMailboxForSkImage(gpu::Mailbox&,
GLenum&,
const sk_sp<SkImage>&,
GLenum filter);
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 9f23d5d2e10..ecad1895ee6 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
@@ -46,6 +46,11 @@ ImageLayerBridge::~ImageLayerBridge() {
void ImageLayerBridge::SetImage(scoped_refptr<StaticBitmapImage> image) {
if (disposed_)
return;
+ // There could be the case that the current SkImage (encapsulated in the image
+ // parameter of the function) is null, that means that something went wrong
+ // during the creation of the image and we should not try and setImage with it
+ if (image && !image->PaintImageForCurrentFrame().GetSkImage())
+ return;
image_ = std::move(image);
if (image_) {
@@ -58,16 +63,15 @@ void ImageLayerBridge::SetImage(scoped_refptr<StaticBitmapImage> image) {
// ensure its opacity is not used.
layer_->SetForceTextureToOpaque(!image_->CurrentFrameKnownToBeOpaque());
}
- }
- if (!has_presented_since_last_set_image_ && image_ &&
- image_->IsTextureBacked()) {
- // If the layer bridge is not presenting, the GrContext may not be getting
- // flushed regularly. The flush is normally triggered inside the
- // m_image->EnsureMailbox() call of
- // ImageLayerBridge::PrepareTransferableResource. To prevent a potential
- // memory leak we must flush the GrContext here.
- image_->PaintImageForCurrentFrame().GetSkImage()->getBackendTexture(
- true); // GrContext flush.
+ if (!has_presented_since_last_set_image_ && image_->IsTextureBacked()) {
+ // If the layer bridge is not presenting, the GrContext may not be getting
+ // flushed regularly. The flush is normally triggered inside the
+ // m_image->EnsureMailbox() call of
+ // ImageLayerBridge::PrepareTransferableResource. To prevent a potential
+ // memory leak we must flush the GrContext here.
+ image_->PaintImageForCurrentFrame().GetSkImage()->getBackendTexture(
+ true); // GrContext flush.
+ }
}
has_presented_since_last_set_image_ = false;
}
@@ -242,9 +246,9 @@ cc::Layer* ImageLayerBridge::CcLayer() const {
}
ImageLayerBridge::RegisteredBitmap::RegisteredBitmap() = default;
-ImageLayerBridge::RegisteredBitmap::RegisteredBitmap(
- RegisteredBitmap&& other) noexcept = default;
+ImageLayerBridge::RegisteredBitmap::RegisteredBitmap(RegisteredBitmap&& other) =
+ default;
ImageLayerBridge::RegisteredBitmap& ImageLayerBridge::RegisteredBitmap::
-operator=(RegisteredBitmap&& other) noexcept = default;
+operator=(RegisteredBitmap&& other) = default;
} // namespace blink
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 bea81dfbdd4..d550eb47af5 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
@@ -30,9 +30,8 @@ class Size;
namespace blink {
class PLATFORM_EXPORT ImageLayerBridge
- : public GarbageCollectedFinalized<ImageLayerBridge>,
+ : public GarbageCollected<ImageLayerBridge>,
public cc::TextureLayerClient {
-
public:
ImageLayerBridge(OpacityMode);
~ImageLayerBridge() override;
@@ -65,8 +64,8 @@ class PLATFORM_EXPORT ImageLayerBridge
// only with software compositing.
struct RegisteredBitmap {
RegisteredBitmap();
- RegisteredBitmap(RegisteredBitmap&& other) noexcept;
- RegisteredBitmap& operator=(RegisteredBitmap&& other) noexcept;
+ RegisteredBitmap(RegisteredBitmap&& other);
+ RegisteredBitmap& operator=(RegisteredBitmap&& other);
scoped_refptr<cc::CrossThreadSharedBitmap> bitmap;
cc::SharedBitmapIdRegistration registration;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
index 7de8d47211e..f3bfe43141c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
@@ -58,6 +58,10 @@ static void CreateContextProviderOnMainThread(
context_attributes.enable_raster_interface = true;
context_attributes.support_grcontext = true;
+ // The shared GPU context should not trigger a switch to the high-performance
+ // GPU.
+ context_attributes.prefer_low_power_gpu = true;
+
*gpu_compositing_disabled = Platform::Current()->IsGpuCompositingDisabled();
if (*gpu_compositing_disabled && only_if_gpu_compositing) {
waitable_event->Signal();
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 832820921f4..1592804d496 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
@@ -7,6 +7,7 @@
#include <memory>
#include "base/test/null_task_runner.h"
+#include "components/viz/test/test_gles2_interface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,6 +16,7 @@
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -71,9 +73,6 @@ class MailboxMockGLES2Interface : public TestGLES2Interface {
MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
};
-class MailboxSharedGpuContextTest
- : public SharedGpuContextTestBase<MailboxMockGLES2Interface> {};
-
// Test fixure that simulate a graphics context creation failure, when using gpu
// compositing.
class BadSharedGpuContextTest : public Test {
@@ -210,13 +209,18 @@ TEST_F(SoftwareCompositingTest, CompositingMode) {
EXPECT_FALSE(SharedGpuContext::IsGpuCompositingEnabled());
}
-class FakeMailboxGenerator {
- STACK_ALLOCATED();
-
+class MailboxSharedGpuContextTest : public Test {
public:
- void ProduceTexture(GLuint texture, GLbyte* name) { *name = counter_++; }
+ void SetUp() override {
+ task_runner_ = base::MakeRefCounted<base::NullTaskRunner>();
+ handle_ = std::make_unique<base::ThreadTaskRunnerHandle>(task_runner_);
+ context_ = viz::TestContextProvider::Create();
+ InitializeSharedGpuContext(context_.get());
+ }
- GLbyte counter_ = 1;
+ scoped_refptr<viz::TestContextProvider> context_;
+ scoped_refptr<base::NullTaskRunner> task_runner_;
+ std::unique_ptr<base::ThreadTaskRunnerHandle> handle_;
};
TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
@@ -231,104 +235,25 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
CanvasResourceProvider::kDefaultPresentationMode,
nullptr // canvas_resource_dispatcher
);
+ ASSERT_TRUE(resource_provider->IsAccelerated());
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- FakeMailboxGenerator mailboxGenerator;
- gpu::Mailbox mailbox;
- GLenum texture_target;
- mailbox.name[0] = 0;
-
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
- .Times(1)
- .WillOnce(testing::Invoke(&mailboxGenerator,
- &FakeMailboxGenerator::ProduceTexture));
-
- SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox, texture_target, image->PaintImageForCurrentFrame().GetSkImage(),
- GL_NEAREST);
-
- EXPECT_EQ(mailbox.name[0], 1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
- .Times(0); // ProduceTextureDirectCHROMIUM must not be called!
-
- mailbox.name[0] = 0;
- SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox, texture_target, image->PaintImageForCurrentFrame().GetSkImage(),
- GL_NEAREST);
- EXPECT_EQ(mailbox.name[0], 1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-}
-
-TEST_F(MailboxSharedGpuContextTest, MailboxCacheSurvivesSkiaRecycling) {
- IntSize size(10, 10);
- std::unique_ptr<CanvasResourceProvider> resource_provider =
- CanvasResourceProvider::Create(
- size,
- CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(),
- 0, // msaa_sample_count
- kLow_SkFilterQuality, CanvasColorParams(),
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr // canvas_resource_dispatcher
- );
- EXPECT_TRUE(resource_provider && resource_provider->IsValid());
- scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- FakeMailboxGenerator mailboxGenerator;
- gpu::Mailbox mailbox;
- GLenum texture_target;
- mailbox.name[0] = 0;
-
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
- .Times(1)
- .WillOnce(testing::Invoke(&mailboxGenerator,
- &FakeMailboxGenerator::ProduceTexture));
+ GLenum texture_target = GL_TEXTURE_2D;
+ gpu::Mailbox mailbox[3];
+ // Creating the SkImage representation from the shared image mailbox registers
+ // the same mailbox mapping to this SkImage with the cache. This ensures we
+ // don't recreate a non-shared image mailbox if going from SkImage to mailbox.
+ mailbox[0] = image->GetMailbox();
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox, texture_target, image->PaintImageForCurrentFrame().GetSkImage(),
- GL_NEAREST);
-
- EXPECT_EQ(mailbox.name[0], 1);
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Destroy image and surface to return texture to recleable resource pool
- image = nullptr;
- resource_provider = nullptr;
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- // Re-creating surface should recycle the old GrTexture inside skia
- resource_provider = CanvasResourceProvider::Create(
- size, CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(),
- 0, // msaa_sample_count
- kLow_SkFilterQuality, CanvasColorParams(),
- CanvasResourceProvider::kDefaultPresentationMode,
- nullptr // canvas_resource_dispatcher
- );
+ mailbox[1], texture_target,
+ image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
+ EXPECT_EQ(mailbox[0], mailbox[1]);
- EXPECT_TRUE(resource_provider && resource_provider->IsValid());
- image = resource_provider->Snapshot();
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
-
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
- .Times(0); // ProduceTextureDirectCHROMIUM must not be called!
-
- mailbox.name[0] = 0;
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox, texture_target, image->PaintImageForCurrentFrame().GetSkImage(),
- GL_NEAREST);
- EXPECT_EQ(mailbox.name[0], 1);
-
- testing::Mock::VerifyAndClearExpectations(&gl_);
+ mailbox[2], texture_target,
+ image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
+ EXPECT_EQ(mailbox[1], mailbox[2]);
}
} // unnamed namespace
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 7681d87d34c..928096a88d0 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
@@ -72,7 +72,7 @@ void WebGPUSwapBufferProvider::Neuter() {
layer_ = nullptr;
}
- if (current_swap_buffer_) {
+ if (current_swap_buffer_ && !dawn_control_client_->IsDestroyed()) {
// Ensure we wait for previous WebGPU commands before destroying the shared
// image.
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
@@ -87,7 +87,7 @@ void WebGPUSwapBufferProvider::Neuter() {
DawnTexture WebGPUSwapBufferProvider::GetNewTexture(DawnDevice device,
const IntSize& size) {
- DCHECK(!current_swap_buffer_);
+ DCHECK(!current_swap_buffer_ && !dawn_control_client_->IsDestroyed());
gpu::webgpu::WebGPUInterface* webgpu = dawn_control_client_->GetInterface();
gpu::SharedImageInterface* sii =
@@ -132,7 +132,7 @@ bool WebGPUSwapBufferProvider::PrepareTransferableResource(
cc::SharedBitmapIdRegistrar* bitmap_registrar,
viz::TransferableResource* out_resource,
std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) {
- DCHECK(!neutered_);
+ DCHECK(!neutered_ && !dawn_control_client_->IsDestroyed());
if (!current_swap_buffer_ || neutered_) {
return false;
@@ -206,6 +206,9 @@ WebGPUSwapBufferProvider::SwapBuffer::SwapBuffer(
access_finished_token(creation_token) {}
WebGPUSwapBufferProvider::SwapBuffer::~SwapBuffer() {
+ if (swap_buffers->dawn_control_client_->IsDestroyed()) {
+ return;
+ }
gpu::SharedImageInterface* sii =
swap_buffers->dawn_control_client_->GetContextProvider()
->SharedImageInterface();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index bb3177ba6fd..e599e2eda72 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "gpu/command_buffer/client/gles2_interface.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
index 1ffe2ab566c..4bd102781f0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
@@ -28,7 +28,7 @@ class GpuMemoryBufferImageCopy;
class Image;
class PLATFORM_EXPORT XRFrameTransport final
- : public GarbageCollectedFinalized<XRFrameTransport>,
+ : public GarbageCollected<XRFrameTransport>,
public device::mojom::blink::XRPresentationClient {
public:
explicit XRFrameTransport();
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 94b047d69f0..66641fb359c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
@@ -46,7 +46,7 @@ class PLATFORM_EXPORT GradientGeneratedImage final : public GeneratedImage {
bool ApplyShader(PaintFlags&, const SkMatrix&) override;
DarkModeClassification CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) override {
return DarkModeClassification::kApplyFilter;
}
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 77eaebd7809..ee1ce96db8d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -30,6 +30,7 @@
#include "base/optional.h"
#include "build/build_config.h"
+#include "components/paint_preview/common/paint_preview_tracker.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
@@ -89,12 +90,14 @@ class GraphicsContext::DarkModeFlags final {
GraphicsContext::GraphicsContext(PaintController& paint_controller,
DisabledMode disable_context_or_painting,
- printing::MetafileSkia* metafile)
+ printing::MetafileSkia* metafile,
+ paint_preview::PaintPreviewTracker* tracker)
: canvas_(nullptr),
paint_controller_(paint_controller),
paint_state_stack_(),
paint_state_index_(0),
metafile_(metafile),
+ tracker_(tracker),
#if DCHECK_IS_ON()
layer_count_(0),
disable_destruction_checks_(false),
@@ -102,6 +105,7 @@ GraphicsContext::GraphicsContext(PaintController& paint_controller,
disabled_state_(disable_context_or_painting),
device_scale_factor_(1.0f),
printing_(false),
+ is_painting_preview_(false),
in_drawing_recorder_(false) {
// FIXME: Do some tests to determine how many states are typically used, and
// allocate several here.
@@ -916,6 +920,7 @@ void GraphicsContext::DrawImage(
Image::ImageDecodingMode decode_mode,
const FloatRect& dest,
const FloatRect* src_ptr,
+ bool has_filter_property,
SkBlendMode op,
RespectImageOrientationEnum should_respect_image_orientation) {
if (ContextDisabled() || !image)
@@ -928,7 +933,9 @@ void GraphicsContext::DrawImage(
image_flags.setColor(SK_ColorBLACK);
image_flags.setFilterQuality(ComputeFilterQuality(image, dest, src));
- dark_mode_filter_.ApplyToImageFlagsIfNeeded(src, image, &image_flags);
+ // Do not classify the image if the element has any CSS filters.
+ if (!has_filter_property)
+ dark_mode_filter_.ApplyToImageFlagsIfNeeded(src, dest, image, &image_flags);
image->Draw(canvas_, image_flags, dest, src, should_respect_image_orientation,
Image::kClampImageToSourceRect, decode_mode);
@@ -940,14 +947,15 @@ void GraphicsContext::DrawImageRRect(
Image::ImageDecodingMode decode_mode,
const FloatRoundedRect& dest,
const FloatRect& src_rect,
+ bool has_filter_property,
SkBlendMode op,
RespectImageOrientationEnum respect_orientation) {
if (ContextDisabled() || !image)
return;
if (!dest.IsRounded()) {
- DrawImage(image, decode_mode, dest.Rect(), &src_rect, op,
- respect_orientation);
+ DrawImage(image, decode_mode, dest.Rect(), &src_rect, has_filter_property,
+ op, respect_orientation);
return;
}
@@ -964,7 +972,8 @@ void GraphicsContext::DrawImageRRect(
image_flags.setFilterQuality(
ComputeFilterQuality(image, dest.Rect(), src_rect));
- dark_mode_filter_.ApplyToImageFlagsIfNeeded(src_rect, image, &image_flags);
+ dark_mode_filter_.ApplyToImageFlagsIfNeeded(src_rect, dest.Rect(), image,
+ &image_flags);
bool use_shader = (visible_src == src_rect) &&
(respect_orientation == kDoNotRespectImageOrientation);
@@ -1363,6 +1372,12 @@ void GraphicsContext::SetURLForRect(const KURL& link,
return;
DCHECK(canvas_);
+ // Intercept URL rects when painting previews.
+ if (IsPaintingPreview() && tracker_) {
+ tracker_->AnnotateLink(link.GetString().Utf8(), dest_rect);
+ return;
+ }
+
sk_sp<SkData> url(SkData::MakeWithCString(link.GetString().Utf8().c_str()));
canvas_->Annotate(cc::PaintCanvas::AnnotationType::URL, dest_rect,
std::move(url));
@@ -1374,6 +1389,12 @@ void GraphicsContext::SetURLFragmentForRect(const String& dest_name,
return;
DCHECK(canvas_);
+ // Intercept URL rects when painting previews.
+ if (IsPaintingPreview() && tracker_) {
+ tracker_->AnnotateLink(dest_name.Utf8(), rect);
+ return;
+ }
+
sk_sp<SkData> sk_dest_name(SkData::MakeWithCString(dest_name.Utf8().c_str()));
canvas_->Annotate(cc::PaintCanvas::AnnotationType::LINK_TO_DESTINATION, rect,
std::move(sk_dest_name));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
index 76c9346d9da..5a42e8103ab 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -53,6 +53,10 @@ class SkPath;
class SkRRect;
struct SkRect;
+namespace paint_preview {
+class PaintPreviewTracker;
+} // namespace paint_preview
+
namespace blink {
class FloatRect;
@@ -74,7 +78,8 @@ class PLATFORM_EXPORT GraphicsContext {
explicit GraphicsContext(PaintController&,
DisabledMode = kNothingDisabled,
- printing::MetafileSkia* = nullptr);
+ printing::MetafileSkia* = nullptr,
+ paint_preview::PaintPreviewTracker* = nullptr);
~GraphicsContext();
@@ -161,6 +166,19 @@ class PLATFORM_EXPORT GraphicsContext {
bool Printing() const { return printing_; }
void SetPrinting(bool printing) { printing_ = printing; }
+ // Returns if the context is saving a paint preview instead of displaying.
+ // In such cases, clipping should not occur.
+ bool IsPaintingPreview() const { return is_painting_preview_; }
+ void SetIsPaintingPreview(bool is_painting_preview) {
+ is_painting_preview_ = is_painting_preview;
+ }
+
+ // Returns if the context is printing or painting a preview. Many of the
+ // behaviors required for printing and paint previews are shared.
+ bool IsPrintingOrPaintingPreview() const {
+ return Printing() || IsPaintingPreview();
+ }
+
SkColorFilter* GetColorFilter() const;
void SetColorFilter(ColorFilter);
// ---------- End state management methods -----------------
@@ -222,6 +240,7 @@ class PLATFORM_EXPORT GraphicsContext {
Image::ImageDecodingMode,
const FloatRect& dest_rect,
const FloatRect* src_rect = nullptr,
+ bool has_filter_property = false,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kDoNotRespectImageOrientation);
void DrawImageRRect(
@@ -229,6 +248,7 @@ class PLATFORM_EXPORT GraphicsContext {
Image::ImageDecodingMode,
const FloatRoundedRect& dest,
const FloatRect& src_rect,
+ bool has_filter_property = false,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kDoNotRespectImageOrientation);
void DrawImageTiled(Image* image,
@@ -496,6 +516,7 @@ class PLATFORM_EXPORT GraphicsContext {
PaintRecorder paint_recorder_;
printing::MetafileSkia* metafile_;
+ paint_preview::PaintPreviewTracker* tracker_;
#if DCHECK_IS_ON()
int layer_count_;
@@ -510,6 +531,7 @@ class PLATFORM_EXPORT GraphicsContext {
DarkModeFilter dark_mode_filter_;
unsigned printing_ : 1;
+ unsigned is_painting_preview_ : 1;
unsigned in_drawing_recorder_ : 1;
DISALLOW_COPY_AND_ASSIGN(GraphicsContext);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
index 5b8d37d248a..5c364638b53 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
@@ -184,7 +184,7 @@ TEST_F(GraphicsContextDarkModeTest, NoDarkMode) {
TEST_F(GraphicsContextDarkModeTest, DarkModeOff) {
DarkModeSettings settings;
- settings.mode = DarkMode::kOff;
+ settings.mode = DarkModeInversionAlgorithm::kOff;
settings.grayscale = false;
settings.contrast = 0;
context_->SetDarkMode(settings);
@@ -201,7 +201,7 @@ TEST_F(GraphicsContextDarkModeTest, DarkModeOff) {
// is replaced with |255 - c| for easy testing.
TEST_F(GraphicsContextDarkModeTest, SimpleInvertForTesting) {
DarkModeSettings settings;
- settings.mode = DarkMode::kSimpleInvertForTesting;
+ settings.mode = DarkModeInversionAlgorithm::kSimpleInvertForTesting;
settings.grayscale = false;
settings.contrast = 0;
context_->SetDarkMode(settings);
@@ -217,7 +217,7 @@ TEST_F(GraphicsContextDarkModeTest, SimpleInvertForTesting) {
// Invert brightness (with gamma correction).
TEST_F(GraphicsContextDarkModeTest, InvertBrightness) {
DarkModeSettings settings;
- settings.mode = DarkMode::kInvertBrightness;
+ settings.mode = DarkModeInversionAlgorithm::kInvertBrightness;
settings.grayscale = false;
settings.contrast = 0;
context_->SetDarkMode(settings);
@@ -233,7 +233,7 @@ TEST_F(GraphicsContextDarkModeTest, InvertBrightness) {
// Invert lightness (in HSL space).
TEST_F(GraphicsContextDarkModeTest, InvertLightness) {
DarkModeSettings settings;
- settings.mode = DarkMode::kInvertLightness;
+ settings.mode = DarkModeInversionAlgorithm::kInvertLightness;
settings.grayscale = false;
settings.contrast = 0;
context_->SetDarkMode(settings);
@@ -249,7 +249,7 @@ TEST_F(GraphicsContextDarkModeTest, InvertLightness) {
// Invert lightness plus grayscale.
TEST_F(GraphicsContextDarkModeTest, InvertLightnessPlusGrayscale) {
DarkModeSettings settings;
- settings.mode = DarkMode::kInvertLightness;
+ settings.mode = DarkModeInversionAlgorithm::kInvertLightness;
settings.grayscale = true;
settings.contrast = 0;
context_->SetDarkMode(settings);
@@ -264,7 +264,7 @@ TEST_F(GraphicsContextDarkModeTest, InvertLightnessPlusGrayscale) {
TEST_F(GraphicsContextDarkModeTest, InvertLightnessPlusContrast) {
DarkModeSettings settings;
- settings.mode = DarkMode::kInvertLightness;
+ settings.mode = DarkModeInversionAlgorithm::kInvertLightness;
settings.grayscale = false;
settings.contrast = 0.2;
context_->SetDarkMode(settings);
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 259929e2cd1..211e3db2d05 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -49,7 +49,6 @@
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/graphics/link_highlight.h"
#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -61,7 +60,6 @@
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -82,8 +80,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
parent_(nullptr),
mask_layer_(nullptr),
contents_layer_(nullptr),
- contents_layer_id_(0),
- rendering_context3d_(0) {
+ contents_layer_id_(0) {
#if DCHECK_IS_ON()
DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
client.VerifyNotPainting();
@@ -100,9 +97,6 @@ GraphicsLayer::~GraphicsLayer() {
CcLayer()->ClearClient();
CcLayer()->SetLayerClient(nullptr);
SetContentsLayer(nullptr);
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->ClearCurrentGraphicsLayer();
- link_highlights_.clear();
#if DCHECK_IS_ON()
client_.VerifyNotPainting();
@@ -230,7 +224,7 @@ IntRect GraphicsLayer::InterestRect() {
return previous_interest_rect_;
}
-void GraphicsLayer::PaintRecursively() {
+bool GraphicsLayer::PaintRecursively() {
Vector<GraphicsLayer*> repainted_layers;
PaintRecursivelyInternal(repainted_layers);
@@ -243,6 +237,7 @@ void GraphicsLayer::PaintRecursively() {
#endif
layer->GetPaintController().FinishCycle();
}
+ return !repainted_layers.IsEmpty();
}
void GraphicsLayer::PaintRecursivelyInternal(
@@ -375,11 +370,8 @@ void GraphicsLayer::UpdateLayerIsDrawable() {
if (cc::Layer* contents_layer = ContentsLayerIfRegistered())
contents_layer->SetIsDrawable(contents_visible_);
- if (draws_content_) {
+ if (draws_content_)
CcLayer()->SetNeedsDisplay();
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->Invalidate();
- }
}
void GraphicsLayer::UpdateContentsRect() {
@@ -466,8 +458,6 @@ void GraphicsLayer::SetupContentsLayer(cc::Layer* contents_layer) {
// SetDrawsContent() and SetContentsVisible().
contents_layer_->SetIsDrawable(contents_visible_);
contents_layer_->SetHitTestable(contents_visible_);
- contents_layer_->SetMaskLayer(nullptr);
- contents_layer_->Set3dSortingContextId(rendering_context3d_);
}
void GraphicsLayer::ClearContentsLayerIfUnregistered() {
@@ -550,13 +540,6 @@ String GraphicsLayer::DebugName(const cc::Layer* layer) const {
if (layer->id() == contents_layer_id_)
return "ContentsLayer for " + client_.DebugName(this);
- for (size_t i = 0; i < link_highlights_.size(); ++i) {
- if (layer == link_highlights_[i]->Layer()) {
- return "LinkHighlight[" + String::Number(i) + "] for " +
- client_.DebugName(this);
- }
- }
-
if (layer == layer_.get())
return client_.DebugName(this);
@@ -588,37 +571,6 @@ void GraphicsLayer::SetSize(const gfx::Size& size) {
// Note that we don't resize m_contentsLayer. It's up the caller to do that.
}
-void GraphicsLayer::SetTransform(const TransformationMatrix& transform) {
- transform_ = transform;
- CcLayer()->SetTransform(TransformationMatrix::ToTransform(transform));
-}
-
-void GraphicsLayer::SetTransformOrigin(const gfx::Point3F& transform_origin) {
- CcLayer()->SetTransformOrigin(transform_origin);
-}
-
-const gfx::Point3F& GraphicsLayer::TransformOrigin() const {
- return CcLayer()->transform_origin();
-}
-
-bool GraphicsLayer::ShouldFlattenTransform() const {
- return CcLayer()->should_flatten_transform();
-}
-
-void GraphicsLayer::SetShouldFlattenTransform(bool should_flatten) {
- CcLayer()->SetShouldFlattenTransform(should_flatten);
-}
-
-void GraphicsLayer::SetRenderingContext(int context) {
- if (rendering_context3d_ == context)
- return;
-
- rendering_context3d_ = context;
- CcLayer()->Set3dSortingContextId(context);
-
- if (contents_layer_)
- contents_layer_->Set3dSortingContextId(rendering_context3d_);
-}
bool GraphicsLayer::MasksToBounds() const {
return CcLayer()->masks_to_bounds();
@@ -685,30 +637,6 @@ bool GraphicsLayer::BackfaceVisibility() const {
return CcLayer()->double_sided();
}
-void GraphicsLayer::SetOpacity(float opacity) {
- CcLayer()->SetOpacity(opacity);
-}
-
-float GraphicsLayer::Opacity() const {
- return CcLayer()->opacity();
-}
-
-void GraphicsLayer::SetBlendMode(BlendMode blend_mode) {
- CcLayer()->SetBlendMode(WebCoreBlendModeToSkBlendMode(blend_mode));
-}
-
-BlendMode GraphicsLayer::GetBlendMode() const {
- return BlendModeFromSkBlendMode(CcLayer()->blend_mode());
-}
-
-bool GraphicsLayer::IsRootForIsolatedGroup() const {
- return CcLayer()->is_root_for_isolated_group();
-}
-
-void GraphicsLayer::SetIsRootForIsolatedGroup(bool isolated) {
- CcLayer()->SetIsRootForIsolatedGroup(isolated);
-}
-
void GraphicsLayer::SetHitTestable(bool should_hit_test) {
if (hit_testable_ == should_hit_test)
return;
@@ -729,10 +657,11 @@ void GraphicsLayer::SetNeedsDisplay() {
return;
CcLayer()->SetNeedsDisplay();
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->Invalidate();
- GetPaintController().InvalidateAll();
+ // Invalidate the paint controller if it exists, but don't bother creating one
+ // if not.
+ if (paint_controller_)
+ paint_controller_->InvalidateAll();
if (raster_invalidator_)
raster_invalidator_->ClearOldStates();
@@ -741,12 +670,16 @@ void GraphicsLayer::SetNeedsDisplay() {
PaintInvalidationReason::kFullLayer);
}
+void GraphicsLayer::SetNeedsDisplayRecursively() {
+ for (auto* child : children_) {
+ child->SetNeedsDisplayRecursively();
+ }
+ SetNeedsDisplay();
+}
+
void GraphicsLayer::SetNeedsDisplayInRect(const IntRect& rect) {
DCHECK(PaintsContentOrHitTest());
-
CcLayer()->SetNeedsDisplayRect(rect);
- for (auto* link_highlight : link_highlights_)
- link_highlight->Invalidate();
}
void GraphicsLayer::SetContentsRect(const IntRect& rect) {
@@ -826,24 +759,11 @@ void GraphicsLayer::SetPaintingPhase(GraphicsLayerPaintingPhase phase) {
SetNeedsDisplay();
}
-void GraphicsLayer::AddLinkHighlight(LinkHighlight* link_highlight) {
- DCHECK(link_highlight && !link_highlights_.Contains(link_highlight));
- link_highlights_.push_back(link_highlight);
- link_highlight->Layer()->SetLayerClient(weak_ptr_factory_.GetWeakPtr());
- UpdateChildList();
-}
-
-void GraphicsLayer::RemoveLinkHighlight(LinkHighlight* link_highlight) {
- link_highlights_.EraseAt(link_highlights_.Find(link_highlight));
- UpdateChildList();
-}
-
std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
const cc::Layer* layer) {
auto traced_value = std::make_unique<base::trace_event::TracedValue>();
- traced_value->SetString(
- "layer_name", WTF::StringUTF8Adaptor(DebugName(layer)).AsStringPiece());
+ traced_value->SetString("layer_name", LayerDebugName(layer));
traced_value->BeginArray("compositing_reasons");
for (const char* description :
@@ -868,6 +788,10 @@ std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
return traced_value;
}
+std::string GraphicsLayer::LayerDebugName(const cc::Layer* layer) const {
+ return DebugName(layer).Utf8();
+}
+
void GraphicsLayer::DidChangeScrollbarsHiddenIfOverlay(bool hidden) {
client_.SetOverlayScrollbarsHidden(hidden);
}
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 4e0baa259f4..c4868211288 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -65,7 +65,6 @@ class PictureLayer;
namespace blink {
class Image;
-class LinkHighlight;
class PaintController;
class RasterInvalidationTracking;
class RasterInvalidator;
@@ -124,18 +123,10 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
const gfx::PointF& GetPosition() const;
void SetPosition(const gfx::PointF&);
- const gfx::Point3F& TransformOrigin() const;
- void SetTransformOrigin(const gfx::Point3F&);
-
// The size of the layer.
const gfx::Size& Size() const;
void SetSize(const gfx::Size&);
- const TransformationMatrix& Transform() const { return transform_; }
- void SetTransform(const TransformationMatrix&);
-
- bool ShouldFlattenTransform() const;
- void SetShouldFlattenTransform(bool);
void SetRenderingContext(int id);
bool MasksToBounds() const;
@@ -169,14 +160,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool BackfaceVisibility() const;
- float Opacity() const;
- void SetOpacity(float);
-
- BlendMode GetBlendMode() const;
- void SetBlendMode(BlendMode);
- bool IsRootForIsolatedGroup() const;
- void SetIsRootForIsolatedGroup(bool);
-
void SetHitTestable(bool);
bool GetHitTestable() const { return hit_testable_; }
@@ -187,6 +170,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
void SetPaintingPhase(GraphicsLayerPaintingPhase);
void SetNeedsDisplay();
+ void SetNeedsDisplayRecursively();
void SetContentsNeedsDisplay();
// Set that the position/size of the contents (image or video).
@@ -228,25 +212,18 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
const IntRect&,
PaintInvalidationReason);
- void AddLinkHighlight(LinkHighlight*);
- void RemoveLinkHighlight(LinkHighlight*);
- const Vector<LinkHighlight*>& GetLinkHighlights() const {
- return link_highlights_;
- }
-
- int GetRenderingContext3D() const { return rendering_context3d_; }
-
static void RegisterContentsLayer(cc::Layer*);
static void UnregisterContentsLayer(cc::Layer*);
IntRect InterestRect();
- void PaintRecursively();
+ bool PaintRecursively();
// Returns true if this layer is repainted.
bool Paint(GraphicsContext::DisabledMode = GraphicsContext::kNothingDisabled);
// cc::LayerClient implementation.
std::unique_ptr<base::trace_event::TracedValue> TakeDebugInfo(
const cc::Layer*) override;
+ std::string LayerDebugName(const cc::Layer*) const override;
void DidChangeScrollbarsHiddenIfOverlay(bool) override;
PaintController& GetPaintController() const;
@@ -371,10 +348,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
// point on.
int contents_layer_id_;
- Vector<LinkHighlight*> link_highlights_;
-
- int rendering_context3d_;
-
SquashingDisallowedReasons squashing_disallowed_reasons_ =
SquashingDisallowedReason::kNone;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.h b/chromium/third_party/blink/renderer/platform/graphics/image.h
index eb1a444e429..445dbd8f71f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.h
@@ -241,7 +241,7 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
// need to be checked before the classification algorithms are applied
// on the image.
virtual DarkModeClassification CheckTypeSpecificConditionsForDarkMode(
- const FloatRect& src_rect,
+ const FloatRect& dest_rect,
DarkModeImageClassifier* classifier) {
return DarkModeClassification::kDoNotApplyFilter;
}
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 30ec2bad2f3..080f1e7a1ef 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
@@ -240,6 +240,7 @@ template <class T, class U, class V>
void ImageDecodingStore::InsertCacheInternal(std::unique_ptr<T> cache_entry,
U* cache_map,
V* identifier_map) {
+ mutex_.AssertAcquired();
const size_t cache_entry_bytes = cache_entry->MemoryUsageInBytes();
heap_memory_usage_in_bytes_ += cache_entry_bytes;
@@ -266,6 +267,7 @@ void ImageDecodingStore::RemoveFromCacheInternal(
U* cache_map,
V* identifier_map,
Vector<std::unique_ptr<CacheEntry>>* deletion_list) {
+ mutex_.AssertAcquired();
DCHECK_EQ(cache_entry->UseCount(), 0);
const size_t cache_entry_bytes = cache_entry->MemoryUsageInBytes();
@@ -307,6 +309,7 @@ void ImageDecodingStore::RemoveCacheIndexedByGeneratorInternal(
V* identifier_map,
const ImageFrameGenerator* generator,
Vector<std::unique_ptr<CacheEntry>>* deletion_list) {
+ mutex_.AssertAcquired();
typename V::iterator iter = identifier_map->find(generator);
if (iter == identifier_map->end())
return;
@@ -327,6 +330,7 @@ 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());
}
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 8ef570c510e..99d17c19138 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
@@ -322,35 +322,31 @@ class PLATFORM_EXPORT ImageDecodingStore final {
// This is used for eviction of old entries.
// Head of this list is the least recently used cache entry.
// Tail of this list is the most recently used cache entry.
- DoublyLinkedList<CacheEntry> ordered_cache_list_;
+ DoublyLinkedList<CacheEntry> ordered_cache_list_ GUARDED_BY(mutex_);
// A lookup table for all decoder cache objects. Owns all decoder cache
// objects.
typedef HashMap<DecoderCacheKey, std::unique_ptr<DecoderCacheEntry>>
DecoderCacheMap;
- DecoderCacheMap decoder_cache_map_;
+ DecoderCacheMap decoder_cache_map_ GUARDED_BY(mutex_);
// A lookup table to map ImageFrameGenerator to all associated
// decoder cache keys.
typedef HashSet<DecoderCacheKey> DecoderCacheKeySet;
typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet>
DecoderCacheKeyMap;
- DecoderCacheKeyMap decoder_cache_key_map_;
+ DecoderCacheKeyMap decoder_cache_key_map_ GUARDED_BY(mutex_);
- size_t heap_limit_in_bytes_;
- size_t heap_memory_usage_in_bytes_;
+ size_t heap_limit_in_bytes_ GUARDED_BY(mutex_);
+ size_t heap_memory_usage_in_bytes_ GUARDED_BY(mutex_);
// A listener to global memory pressure events.
base::MemoryPressureListener memory_pressure_listener_;
- // Protect concurrent access to these members:
- // m_orderedCacheList
- // m_decoderCacheMap and all CacheEntrys stored in it
- // m_decoderCacheKeyMap
- // m_heapLimitInBytes
- // m_heapMemoryUsageInBytes
- // This mutex also protects calls to underlying skBitmap's
- // lockPixels()/unlockPixels() as they are not threadsafe.
+ // Also protects:
+ // - the CacheEntry in |decoder_cache_map_|.
+ // - calls to underlying skBitmap's LockPixels()/UnlockPixels() as they are
+ // not threadsafe.
Mutex mutex_;
DISALLOW_COPY_AND_ASSIGN(ImageDecodingStore);
@@ -358,4 +354,4 @@ class PLATFORM_EXPORT ImageDecodingStore final {
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_DECODING_STORE_H_
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 bd064bbc1ff..65787e1ea0a 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
@@ -27,6 +27,7 @@
#include <memory>
#include "base/memory/memory_pressure_listener.h"
+#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
#include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h"
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 036bca13398..59dfaac45b3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_FRAME_GENERATOR_H_
#include <memory>
+#include <utility>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
@@ -150,13 +151,11 @@ class PLATFORM_EXPORT ImageFrameGenerator final
const bool is_multi_frame_;
const Vector<SkISize> supported_sizes_;
- // Prevents concurrent access to all variables below.
mutable Mutex generator_mutex_;
-
- bool decode_failed_ = false;
- bool yuv_decoding_failed_ = false;
- size_t frame_count_ = 0u;
- Vector<bool> has_alpha_;
+ 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;
+ Vector<bool> has_alpha_ GUARDED_BY(generator_mutex_);
struct ClientMutex {
int ref_count = 0;
@@ -170,7 +169,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
std::unique_ptr<ClientMutex>,
WTF::IntHash<cc::PaintImage::GeneratorClientId>,
WTF::UnsignedWithZeroKeyHashTraits<cc::PaintImage::GeneratorClientId>>
- mutex_map_;
+ mutex_map_ GUARDED_BY(generator_mutex_);
std::unique_ptr<ImageDecoderFactory> image_decoder_factory_;
@@ -179,4 +178,4 @@ class PLATFORM_EXPORT ImageFrameGenerator final
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_FRAME_GENERATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h b/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h
deleted file mode 100644
index 74d4ac15023..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/link_highlight.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_LINK_HIGHLIGHT_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_LINK_HIGHLIGHT_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace cc {
-class Layer;
-}
-
-namespace blink {
-
-class EffectPaintPropertyNode;
-class FloatPoint;
-
-class PLATFORM_EXPORT LinkHighlight : public DisplayItemClient {
- public:
- ~LinkHighlight() override {}
-
- virtual void Invalidate() = 0;
- virtual void ClearCurrentGraphicsLayer() = 0;
- virtual cc::Layer* Layer() = 0;
-
- virtual const EffectPaintPropertyNode& Effect() const = 0;
-
- // This returns the link highlight offset from its parent transform node,
- // including both the link location and the layer location.
- virtual FloatPoint GetOffsetFromTransformNode() const = 0;
-
- // DisplayItemClient methods
- // TODO(wangxianzhu): This class doesn't need to be a DisplayItemClient in
- // CompositeAfterPaint.
- String DebugName() const final { return "LinkHighlight"; }
- IntRect VisualRect() const final { return IntRect(); }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_LINK_HIGHLIGHT_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
index 1693f32aaac..d0ac4be0f10 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
@@ -94,8 +94,9 @@ MailboxTextureHolder::MailboxTextureHolder(
if (!ContextProviderWrapper())
return;
- ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
- mailbox_, texture_target_, image, filter);
+ if (!ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
+ mailbox_, texture_target_, image, filter))
+ return;
InitCommon();
}
@@ -153,9 +154,8 @@ void MailboxTextureHolder::Sync(MailboxSyncMode mode) {
void MailboxTextureHolder::InitCommon() {
DCHECK(!thread_id_);
- Thread* thread = Thread::Current();
- thread_id_ = thread->ThreadId();
- texture_thread_task_runner_ = thread->GetTaskRunner();
+ thread_id_ = base::PlatformThread::CurrentId();
+ texture_thread_task_runner_ = Thread::Current()->GetTaskRunner();
}
bool MailboxTextureHolder::IsValid() const {
@@ -168,7 +168,7 @@ bool MailboxTextureHolder::IsValid() const {
}
bool MailboxTextureHolder::IsCrossThread() const {
- return thread_id_ != Thread::Current()->ThreadId();
+ return thread_id_ != base::PlatformThread::CurrentId();
}
MailboxTextureHolder::~MailboxTextureHolder() {
@@ -176,8 +176,7 @@ MailboxTextureHolder::~MailboxTextureHolder() {
new gpu::SyncToken(mailbox_ref()->sync_token()));
std::unique_ptr<gpu::Mailbox> passed_mailbox(new gpu::Mailbox(mailbox_));
- if (texture_thread_task_runner_ &&
- thread_id_ != Thread::Current()->ThreadId()) {
+ if (texture_thread_task_runner_ && IsCrossThread()) {
PostCrossThreadTask(
*texture_thread_task_runner_, FROM_HERE,
CrossThreadBindOnce(&ReleaseTexture, is_converted_from_skia_texture_,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
index 930f022d5d3..da4d6800f99 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
@@ -72,7 +72,7 @@ class PLATFORM_EXPORT MailboxTextureHolder final : public TextureHolder {
unsigned texture_id_;
bool is_converted_from_skia_texture_;
scoped_refptr<base::SingleThreadTaskRunner> texture_thread_task_runner_;
- PlatformThreadId thread_id_;
+ base::PlatformThreadId thread_id_;
bool did_issue_ordering_barrier_ = false;
SkImageInfo sk_image_info_;
GLenum texture_target_;
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 428e10aabc4..6aa649cca79 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
@@ -98,18 +98,10 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(SVGClip);
DEBUG_STRING_CASE(SVGFilter);
DEBUG_STRING_CASE(SVGMask);
- DEBUG_STRING_CASE(ScrollbarBackButtonEnd);
- DEBUG_STRING_CASE(ScrollbarBackButtonStart);
- DEBUG_STRING_CASE(ScrollbarBackground);
- DEBUG_STRING_CASE(ScrollbarBackTrack);
- DEBUG_STRING_CASE(ScrollbarCorner);
- DEBUG_STRING_CASE(ScrollbarForwardButtonEnd);
- DEBUG_STRING_CASE(ScrollbarForwardButtonStart);
- DEBUG_STRING_CASE(ScrollbarForwardTrack);
DEBUG_STRING_CASE(ScrollbarThumb);
DEBUG_STRING_CASE(ScrollbarTickmarks);
- DEBUG_STRING_CASE(ScrollbarTrackBackground);
- DEBUG_STRING_CASE(ScrollbarCompositedScrollbar);
+ DEBUG_STRING_CASE(ScrollbarTrackAndButtons);
+ DEBUG_STRING_CASE(ScrollCorner);
DEBUG_STRING_CASE(SelectionTint);
DEBUG_STRING_CASE(TableCollapsedBorders);
DEBUG_STRING_CASE(VideoBitmap);
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 9d71d046108..79dbb3805e5 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
@@ -81,18 +81,10 @@ class PLATFORM_EXPORT DisplayItem {
kSVGClip,
kSVGFilter,
kSVGMask,
- kScrollbarBackButtonEnd,
- kScrollbarBackButtonStart,
- kScrollbarBackground,
- kScrollbarBackTrack,
- kScrollbarCorner,
- kScrollbarForwardButtonEnd,
- kScrollbarForwardButtonStart,
- kScrollbarForwardTrack,
+ kScrollCorner,
+ kScrollbarTrackAndButtons,
kScrollbarThumb,
kScrollbarTickmarks,
- kScrollbarTrackBackground,
- kScrollbarCompositedScrollbar,
kSelectionTint,
kTableCollapsedBorders,
kVideoBitmap,
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 cd3ed2f2988..9ee2571f0ae 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
@@ -28,10 +28,10 @@ class PLATFORM_EXPORT DisplayItemList
public:
DisplayItemList(size_t initial_size_bytes)
: ContiguousContainer(kMaximumDisplayItemSize, initial_size_bytes) {}
- DisplayItemList(DisplayItemList&& source) noexcept
+ DisplayItemList(DisplayItemList&& source)
: ContiguousContainer(std::move(source)) {}
- DisplayItemList& operator=(DisplayItemList&& source) noexcept {
+ DisplayItemList& operator=(DisplayItemList&& source) {
ContiguousContainer::operator=(std::move(source));
return *this;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
index 87b547968b6..c11b72e0597 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h
@@ -44,6 +44,9 @@ class PLATFORM_EXPORT FloatClipRect {
}
void Intersect(const FloatClipRect& other) {
+ if (other.is_infinite_)
+ return;
+
if (is_infinite_) {
is_infinite_ = other.is_infinite_;
rect_ = other.rect_;
@@ -56,7 +59,12 @@ class PLATFORM_EXPORT FloatClipRect {
ClearIsTight();
}
+ // See FloatRect::InclusiveIntersect for description of the return value.
+ // TL;DR, this returns true if rects actually intersect.
bool InclusiveIntersect(const FloatClipRect& other) {
+ if (other.is_infinite_)
+ return true;
+
bool retval = true;
if (is_infinite_) {
is_infinite_ = other.is_infinite_;
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 352678752ff..6ab4f4aedfd 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
@@ -13,7 +13,7 @@ class FloatClipRectTest : public testing::Test {
public:
};
-TEST_F(FloatClipRectTest, InfinitRect) {
+TEST_F(FloatClipRectTest, InfiniteRect) {
FloatClipRect rect;
EXPECT_TRUE(rect.IsInfinite());
EXPECT_FALSE(rect.HasRadius());
@@ -60,6 +60,28 @@ TEST_F(FloatClipRectTest, Intersect) {
EXPECT_FALSE(rect.IsTight());
}
+TEST_F(FloatClipRectTest, IntersectWithInfinite) {
+ FloatClipRect infinite;
+ FloatRect large(0, 0, std::numeric_limits<int>::max(),
+ std::numeric_limits<int>::max());
+ FloatClipRect unclipped(large);
+
+ unclipped.Intersect(infinite);
+ EXPECT_FALSE(unclipped.IsInfinite());
+ EXPECT_EQ(large, unclipped.Rect());
+}
+
+TEST_F(FloatClipRectTest, InclusiveIntersectWithInfinite) {
+ FloatClipRect infinite;
+ FloatRect large(0, 0, std::numeric_limits<int>::max(),
+ std::numeric_limits<int>::max());
+ FloatClipRect unclipped(large);
+
+ ASSERT_TRUE(unclipped.InclusiveIntersect(infinite));
+ EXPECT_FALSE(unclipped.IsInfinite());
+ EXPECT_EQ(large, unclipped.Rect());
+}
+
TEST_F(FloatClipRectTest, SetHasRadius) {
FloatClipRect rect;
rect.SetHasRadius();
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 e3661a7e6cd..fea4d4d387c 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
@@ -799,6 +799,8 @@ TEST_P(GeometryMapperTest, InvertedClip) {
PropertyTreeState dest(t0(), *clip, e0());
FloatClipRect visual_rect(FloatRect(0, 0, 10, 200));
+ EXPECT_TRUE(visual_rect.IsTight());
+
GeometryMapper::LocalToAncestorVisualRect(PropertyTreeState::Root(), dest,
visual_rect);
@@ -806,7 +808,7 @@ TEST_P(GeometryMapperTest, InvertedClip) {
// LocalToAncestorVisualRect must fall back to the original rect, mapped
// into the root space.
EXPECT_EQ(FloatRect(0, 0, 10, 200), visual_rect.Rect());
- EXPECT_FALSE(visual_rect.IsTight());
+ EXPECT_TRUE(visual_rect.IsTight());
}
TEST_P(GeometryMapperTest, Precision) {
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 cc2aad3f03f..58a1eaa2b76 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
@@ -71,29 +71,23 @@ void ComputeChunkDerivedData(const DisplayItemList& display_items,
chunk.hit_test_data->AppendTouchActionRect(hit_test.GetHitTestRect());
}
-#if DCHECK_IS_ON()
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
- // Because ScrollHitTestDisplayItems force new paint chunks (see:
- // PaintChunker::IncrementDisplayItemIndex), they should only be the first
- // item in a paint chunk.
- DCHECK(!item.IsScrollHitTest() || item.Equals(*items.begin()));
- }
-#endif
- }
-
- if (RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled()) {
// Because ScrollHitTestDisplayItems force new paint chunks (see:
// PaintChunker::IncrementDisplayItemIndex), they should only be the first
// item in a paint chunk.
- if (items.begin()->IsScrollHitTest()) {
- const auto& scroll_hit_test_item =
- static_cast<const ScrollHitTestDisplayItem&>(*items.begin());
- if (!chunk.hit_test_data)
- chunk.hit_test_data = std::make_unique<HitTestData>();
- chunk.hit_test_data->SetScrollHitTest(
- scroll_hit_test_item.scroll_offset_node(),
- scroll_hit_test_item.scroll_container_bounds());
- }
+ DCHECK(!item.IsScrollHitTest() || item.Equals(*items.begin()));
+ }
+
+ // Because ScrollHitTestDisplayItems force new paint chunks (see:
+ // PaintChunker::IncrementDisplayItemIndex), they should only be the first
+ // item in a paint chunk.
+ if (items.begin()->IsScrollHitTest()) {
+ const auto& scroll_hit_test_item =
+ static_cast<const ScrollHitTestDisplayItem&>(*items.begin());
+ if (!chunk.hit_test_data)
+ chunk.hit_test_data = std::make_unique<HitTestData>();
+ chunk.hit_test_data->SetScrollHitTest(
+ scroll_hit_test_item.scroll_offset_node(),
+ scroll_hit_test_item.scroll_container_bounds());
}
if (known_to_be_opaque_region.contains(chunk.bounds))
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 6b690463544..b7b3241f107 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
@@ -10,9 +10,11 @@
namespace blink {
-PaintRecordBuilder::PaintRecordBuilder(printing::MetafileSkia* metafile,
- GraphicsContext* containing_context,
- PaintController* paint_controller)
+PaintRecordBuilder::PaintRecordBuilder(
+ printing::MetafileSkia* metafile,
+ GraphicsContext* containing_context,
+ PaintController* paint_controller,
+ paint_preview::PaintPreviewTracker* tracker)
: paint_controller_(nullptr) {
GraphicsContext::DisabledMode disabled_mode =
GraphicsContext::kNothingDisabled;
@@ -30,12 +32,13 @@ PaintRecordBuilder::PaintRecordBuilder(printing::MetafileSkia* metafile,
paint_controller_->UpdateCurrentPaintChunkProperties(
base::nullopt, PropertyTreeState::Root());
- context_ = std::make_unique<GraphicsContext>(*paint_controller_,
- disabled_mode, metafile);
+ context_ = std::make_unique<GraphicsContext>(
+ *paint_controller_, disabled_mode, metafile, tracker);
if (containing_context) {
context_->SetDarkMode(containing_context->dark_mode_settings());
context_->SetDeviceScaleFactor(containing_context->DeviceScaleFactor());
context_->SetPrinting(containing_context->Printing());
+ context_->SetIsPaintingPreview(containing_context->IsPaintingPreview());
}
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
index 521dd79c362..42631cf4740 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
@@ -19,12 +19,15 @@ namespace cc {
class PaintCanvas;
}
+namespace paint_preview {
+class PaintPreviewTracker;
+}
+
namespace blink {
class GraphicsContext;
class PaintController;
class PLATFORM_EXPORT PaintRecordBuilder final : public DisplayItemClient {
-
public:
// Constructs a new builder for the resulting paint record. If |metadata|
// is specified, that metadata is propagated to the builder's internal canvas.
@@ -39,7 +42,8 @@ class PLATFORM_EXPORT PaintRecordBuilder final : public DisplayItemClient {
// CompositeAfterPaint.
PaintRecordBuilder(printing::MetafileSkia* metafile = nullptr,
GraphicsContext* containing_context = nullptr,
- PaintController* = nullptr);
+ PaintController* = nullptr,
+ paint_preview::PaintPreviewTracker* tracker = nullptr);
~PaintRecordBuilder() override;
GraphicsContext& Context() { return *context_; }
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
index 6e1f2445ae5..3c8cd82d14a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
@@ -18,7 +18,6 @@ ScrollHitTestDisplayItem::ScrollHitTestDisplayItem(
: DisplayItem(client, type, sizeof(*this)),
scroll_offset_node_(scroll_offset_node),
scroll_container_bounds_(scroll_container_bounds) {
- DCHECK(RuntimeEnabledFeatures::PaintNonFastScrollableRegionsEnabled());
#if DCHECK_IS_ON()
if (type == DisplayItem::Type::kResizerScrollHitTest ||
type == DisplayItem::Type::kPluginScrollHitTest) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
index cd115e2106f..b2bfbe00b4d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
@@ -20,7 +20,6 @@ class GraphicsContext;
//
// This serves three purposes:
// 1. Creating non-fast scrollable regions for non-composited scrollers.
-// (When PaintNonFastScrollableRegions is enabled).
// Scrollable areas create a non-fast scrollable region in the
// non-scrolling paint property tree state. Pre-CompositeAfterPaint, we skip
// painting these for composited scrollers. With CompositeAfterPaint, we
@@ -28,7 +27,6 @@ class GraphicsContext;
// (see: PaintArtifactCompositor::UpdateNonFastScrollableRegions).
//
// 2. Creating non-fast scrollable regions for plugins and resize handles.
-// (When PaintNonFastScrollableRegions is enabled).
// Plugins that have blocking event handlers and resize handles both need to
// prevent composited scrolling. A different display item type is used
// (kPluginScrollHitTest and kResizerScrollHitTest) to disambiguate multiple
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 7a97f6bb504..b764379856e 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
@@ -49,7 +49,7 @@ class PaintWorkletPaintDispatcherAsyncTest : public ::testing::Test {
};
class MockPaintWorkletPainter
- : public GarbageCollectedFinalized<MockPaintWorkletPainter>,
+ : public GarbageCollected<MockPaintWorkletPainter>,
public PaintWorkletPainter {
USING_GARBAGE_COLLECTED_MIXIN(MockPaintWorkletPainter);
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 75b7b9be95a..43a015c670f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -8,6 +8,7 @@
#include "base/stl_util.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"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_family.h"
@@ -115,20 +116,19 @@ FontDescription CreatePlaceholderFontDescription(float scale_factor) {
String FormatOriginalResourceSizeBytes(int64_t bytes) {
DCHECK_LT(0, bytes);
- static constexpr WebLocalizedString::Name kUnitsNames[] = {
- WebLocalizedString::kUnitsKibibytes, WebLocalizedString::kUnitsMebibytes,
- WebLocalizedString::kUnitsGibibytes, WebLocalizedString::kUnitsTebibytes,
- WebLocalizedString::kUnitsPebibytes};
+ static constexpr int kUnitsResourceIds[] = {
+ IDS_UNITS_KIBIBYTES, IDS_UNITS_MEBIBYTES, IDS_UNITS_GIBIBYTES,
+ IDS_UNITS_TEBIBYTES, IDS_UNITS_PEBIBYTES};
// Start with KB. The formatted text will be at least "1 KB", with any smaller
// amounts being rounded up to "1 KB".
- const WebLocalizedString::Name* units = kUnitsNames;
+ const int* units = kUnitsResourceIds;
int64_t denomenator = 1024;
// Find the smallest unit that can represent |bytes| in 3 digits or less.
// Round up to the next higher unit if possible when it would take 4 digits to
// display the amount, e.g. 1000 KB will be rounded up to 1 MB.
- for (; units < kUnitsNames + (base::size(kUnitsNames) - 1) &&
+ for (; units < kUnitsResourceIds + (base::size(kUnitsResourceIds) - 1) &&
bytes >= denomenator * 1000;
++units, denomenator *= 1024) {
}
@@ -137,7 +137,7 @@ String FormatOriginalResourceSizeBytes(int64_t bytes) {
if (bytes < denomenator) {
// Round up to 1.
numeric_string = String::Number(1);
- } else if (units != kUnitsNames && bytes < denomenator * 10) {
+ } else if (units != kUnitsResourceIds && bytes < denomenator * 10) {
// For amounts between 1 and 10 units and larger than 1 MB, allow up to one
// fractional digit.
numeric_string = String::Number(
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 0a62b5e9f93..81fb9df438a 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
@@ -9,8 +9,8 @@
#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/web_localized_string.h"
#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/strings/grit/blink_strings.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/geometry/float_rect.h"
@@ -213,15 +213,15 @@ class TestingUnitsPlatform : public TestingPlatformSupport {
const WebString& parameter) override {
String p = parameter;
switch (resource_id) {
- case WebLocalizedString::kUnitsKibibytes:
+ case IDS_UNITS_KIBIBYTES:
return String(p + " KB");
- case WebLocalizedString::kUnitsMebibytes:
+ case IDS_UNITS_MEBIBYTES:
return String(p + " MB");
- case WebLocalizedString::kUnitsGibibytes:
+ case IDS_UNITS_GIBIBYTES:
return String(p + " GB");
- case WebLocalizedString::kUnitsTebibytes:
+ case IDS_UNITS_TEBIBYTES:
return String(p + " TB");
- case WebLocalizedString::kUnitsPebibytes:
+ case IDS_UNITS_PEBIBYTES:
return String(p + " PB");
default:
return WebString();
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 9fdbf892032..1e8ae93ee66 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
@@ -30,10 +30,12 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+#include "base/allocator/partition_allocator/partition_alloc.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"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"
#include "third_party/skia/include/third_party/skcms/skcms.h"
@@ -405,4 +407,18 @@ template void PLATFORM_EXPORT DrawPlatformFocusRing<SkPath>(const SkPath&,
SkColor,
float width);
+sk_sp<SkData> TryAllocateSkData(size_t size) {
+ void* buffer = WTF::Partitions::BufferPartition()->AllocFlags(
+ base::PartitionAllocReturnNull | base::PartitionAllocZeroFill, size,
+ "SkData");
+ if (!buffer)
+ return nullptr;
+ return SkData::MakeWithProc(
+ buffer, size,
+ [](const void* buffer, void* context) {
+ WTF::Partitions::BufferPartition()->Free(const_cast<void*>(buffer));
+ },
+ /*context=*/nullptr);
+}
+
} // namespace blink
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 8155a31cf84..f6edaa4ada5 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
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkScalar.h"
@@ -153,6 +154,11 @@ WebCoreClampingModeToSkiaRectConstraint(Image::ImageClampingMode clamp_mode) {
: cc::PaintCanvas::kFast_SrcRectConstraint;
}
+// Attempts to allocate an SkData on the PartitionAlloc buffer partition.
+// If this fails (e.g. due to low memory), returns a null sk_sp<SkData> instead.
+// Otherwise, the returned buffer is guaranteed to be zero-filled.
+PLATFORM_EXPORT sk_sp<SkData> TryAllocateSkData(size_t size);
+
// Skia's smart pointer APIs are preferable over their legacy raw pointer
// counterparts.
//
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
index dd769db7189..f59034399e6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
@@ -142,7 +142,8 @@ SkiaTextureHolder::~SkiaTextureHolder() {
}
bool SkiaTextureHolder::IsValid() const {
- return !!image_ && !!ContextProviderWrapper();
+ return !!image_ && !!ContextProviderWrapper() &&
+ image_->isValid(ContextProvider()->GetGrContext());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
index 6aa6dd075ef..6605e4258a3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.cc
@@ -75,7 +75,9 @@ constexpr SquashingDisallowedReasonStringMap
{SquashingDisallowedReason::kMaskMismatch,
"SquashingDisallowedReasonMaskMismatch",
"Cannot squash layers across mask boundaries."},
-};
+ {SquashingDisallowedReason::kCrossesLayoutContainmentBoundary,
+ "SquashingDisallowedReasonCrossesLayoutContainmentBoundary",
+ "Cannot squash layer across layout containment boundary."}};
} // anonymous namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
index 99102b24f49..21357fae5cf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/squashing_disallowed_reasons.h
@@ -29,7 +29,8 @@ using SquashingDisallowedReasons = unsigned;
V(RenderingContextMismatch) \
V(FragmentedContent) \
V(ClipPathMismatch) \
- V(MaskMismatch)
+ V(MaskMismatch) \
+ V(CrossesLayoutContainmentBoundary)
class PLATFORM_EXPORT SquashingDisallowedReason {
DISALLOW_NEW();
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 7c142e6f16e..2dd398f4b50 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
@@ -41,27 +41,10 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(PaintImage image) {
}
scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
- scoped_refptr<Uint8Array>&& image_pixels,
+ sk_sp<SkData> data,
const SkImageInfo& info) {
- SkPixmap pixmap(info, image_pixels->Data(), info.minRowBytes());
-
- Uint8Array* pixels = image_pixels.get();
- if (pixels) {
- pixels->AddRef();
- image_pixels = nullptr;
- }
-
- return Create(SkImage::MakeFromRaster(
- pixmap,
- [](const void*, void* p) { static_cast<Uint8Array*>(p)->Release(); },
- pixels));
-}
-
-scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
- WTF::ArrayBufferContents& contents,
- const SkImageInfo& info) {
- SkPixmap pixmap(info, contents.Data(), info.minRowBytes());
- return Create(SkImage::MakeFromRaster(pixmap, nullptr, nullptr));
+ return Create(
+ SkImage::MakeRasterData(info, std::move(data), info.minRowBytes()));
}
void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
@@ -114,12 +97,14 @@ bool StaticBitmapImage::ConvertToArrayBufferContents(
int alloc_size_in_bytes = data_size.ValueOrDie();
if (!src_image) {
- auto data = WTF::ArrayBufferContents::CreateDataHandle(
- alloc_size_in_bytes, WTF::ArrayBufferContents::kZeroInitialize);
- if (!data)
+ WTF::ArrayBufferContents result(alloc_size_in_bytes, 1,
+ WTF::ArrayBufferContents::kNotShared,
+ WTF::ArrayBufferContents::kZeroInitialize);
+
+ // Check if the ArrayBuffer backing store was allocated correctly.
+ if (result.DataLength() != static_cast<size_t>(alloc_size_in_bytes)) {
return false;
- WTF::ArrayBufferContents result(std::move(data),
- WTF::ArrayBufferContents::kNotShared);
+ }
result.Transfer(dest_contents);
return true;
}
@@ -132,12 +117,14 @@ bool StaticBitmapImage::ConvertToArrayBufferContents(
WTF::ArrayBufferContents::InitializationPolicy initialization_policy =
may_have_stray_area ? WTF::ArrayBufferContents::kZeroInitialize
: WTF::ArrayBufferContents::kDontInitialize;
- auto data = WTF::ArrayBufferContents::CreateDataHandle(alloc_size_in_bytes,
- initialization_policy);
- if (!data)
+
+ WTF::ArrayBufferContents result(alloc_size_in_bytes, 1,
+ WTF::ArrayBufferContents::kNotShared,
+ initialization_policy);
+ // Check if the ArrayBuffer backing store was allocated correctly.
+ if (result.DataLength() != static_cast<size_t>(alloc_size_in_bytes)) {
return false;
- WTF::ArrayBufferContents result(std::move(data),
- WTF::ArrayBufferContents::kNotShared);
+ }
SkColorType color_type =
(color_params.GetSkColorType() == kRGBA_F16_SkColorType)
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 399fe355552..85a393afe8e 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
@@ -41,9 +41,7 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
sk_sp<SkImage>,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> = nullptr);
static scoped_refptr<StaticBitmapImage> Create(PaintImage);
- static scoped_refptr<StaticBitmapImage> Create(scoped_refptr<Uint8Array>&&,
- const SkImageInfo&);
- static scoped_refptr<StaticBitmapImage> Create(WTF::ArrayBufferContents&,
+ static scoped_refptr<StaticBitmapImage> Create(sk_sp<SkData> data,
const SkImageInfo&);
bool IsStaticBitmapImage() const override { return true; }
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 b9cb2068a82..986247a64de 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -10,7 +10,6 @@
#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 "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
#include "media/base/video_frame.h"
@@ -32,7 +31,8 @@ VideoFrameSubmitter::VideoFrameSubmitter(
std::unique_ptr<VideoFrameResourceProvider> resource_provider)
: context_provider_callback_(context_provider_callback),
resource_provider_(std::move(resource_provider)),
- rotation_(media::VIDEO_ROTATION_0) {
+ rotation_(media::VIDEO_ROTATION_0),
+ frame_trackers_(false, nullptr) {
DETACH_FROM_THREAD(thread_checker_);
}
@@ -176,7 +176,6 @@ void VideoFrameSubmitter::OnBeginFrame(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame");
- frame_trackers_.NotifyBeginImplFrame(args);
last_begin_frame_args_ = args;
for (const auto& pair : timing_details) {
@@ -186,22 +185,28 @@ void VideoFrameSubmitter::OnBeginFrame(
if (base::Contains(frame_token_to_timestamp_map_, pair.key) &&
!(pair.value->presentation_feedback->flags &
gfx::PresentationFeedback::kFailure)) {
- frame_trackers_.NotifyFramePresented(
- pair.key, gfx::PresentationFeedback(
- pair.value->presentation_feedback->timestamp,
- pair.value->presentation_feedback->interval,
- pair.value->presentation_feedback->flags));
+ if (!ignorable_submitted_frames_.contains(pair.key)) {
+ frame_trackers_.NotifyFramePresented(
+ pair.key, gfx::PresentationFeedback(
+ pair.value->presentation_feedback->timestamp,
+ pair.value->presentation_feedback->interval,
+ pair.value->presentation_feedback->flags));
+ }
UMA_HISTOGRAM_TIMES("Media.VideoFrameSubmitter",
pair.value->presentation_feedback->timestamp -
frame_token_to_timestamp_map_[pair.key]);
frame_token_to_timestamp_map_.erase(pair.key);
}
+ ignorable_submitted_frames_.erase(pair.key);
+
TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(
"media", "VideoFrameSubmitter", pair.key,
pair.value->presentation_feedback->timestamp);
}
+ frame_trackers_.NotifyBeginImplFrame(args);
+
// Don't call UpdateCurrentFrame() for MISSED BeginFrames. Also don't call it
// after StopRendering() has been called (forbidden by API contract).
viz::BeginFrameAck current_begin_frame_ack(args, false);
@@ -317,15 +322,15 @@ void VideoFrameSubmitter::StartSubmitting() {
provider->CreateCompositorFrameSink(
frame_sink_id_, receiver_.BindNewPipeAndPassRemote(),
- mojo::MakeRequest(&compositor_frame_sink_));
+ compositor_frame_sink_.BindNewPipeAndPassReceiver());
if (!surface_embedder_.is_bound()) {
provider->ConnectToEmbedder(frame_sink_id_,
- mojo::MakeRequest(&surface_embedder_));
+ surface_embedder_.BindNewPipeAndPassReceiver());
} else {
GenerateNewSurfaceId();
}
- compositor_frame_sink_.set_connection_error_handler(base::BindOnce(
+ compositor_frame_sink_.set_disconnect_handler(base::BindOnce(
&VideoFrameSubmitter::OnContextLost, base::Unretained(this)));
UpdateSubmissionState();
@@ -407,15 +412,8 @@ bool VideoFrameSubmitter::SubmitFrame(
// not building up unused remote side resources. See https://crbug.com/830828.
//
// Similarly we don't submit the same frame multiple times.
-#if defined(OS_ANDROID)
- // Android MediaPlayer sometimes sends the same frame ID multiple times. So
- // don't elide these frames on M78 where this isn't fixed.
- if (waiting_for_compositor_ack_)
- return false;
-#else
if (waiting_for_compositor_ack_ || last_frame_id_ == video_frame->unique_id())
return false;
-#endif
last_frame_id_ = video_frame->unique_id();
@@ -424,6 +422,15 @@ bool VideoFrameSubmitter::SubmitFrame(
rotation_ == media::VIDEO_ROTATION_270) {
frame_size = gfx::Size(frame_size.height(), frame_size.width());
}
+
+ if (frame_size.IsEmpty()) {
+ // We're not supposed to get 0x0 frames. For now, just ignore it until we
+ // track down where they're coming from. Creating a CompositorFrame with an
+ // empty output rectangle isn't allowed.
+ // crbug.com/979564
+ return false;
+ }
+
if (frame_size_ != frame_size) {
if (!frame_size_.IsEmpty())
GenerateNewSurfaceId();
@@ -446,13 +453,13 @@ bool VideoFrameSubmitter::SubmitFrame(
// We can pass nullptr for the HitTestData as the CompositorFram will not
// contain any SurfaceDrawQuads.
- frame_trackers_.NotifySubmitFrame(compositor_frame.metadata.frame_token,
- false, begin_frame_ack,
- last_begin_frame_args_);
+ auto frame_token = compositor_frame.metadata.frame_token;
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
std::move(compositor_frame), nullptr, 0);
+ frame_trackers_.NotifySubmitFrame(frame_token, false, begin_frame_ack,
+ last_begin_frame_args_);
resource_provider_->ReleaseFrameResources();
waiting_for_compositor_ack_ = true;
@@ -473,13 +480,14 @@ void VideoFrameSubmitter::SubmitEmptyFrame() {
last_frame_id_.reset();
auto begin_frame_ack = viz::BeginFrameAck::CreateManualAckWithDamage();
auto compositor_frame = CreateCompositorFrame(begin_frame_ack, nullptr);
- frame_trackers_.NotifySubmitFrame(compositor_frame.metadata.frame_token,
- false, begin_frame_ack,
- last_begin_frame_args_);
+
+ auto frame_token = compositor_frame.metadata.frame_token;
compositor_frame_sink_->SubmitCompositorFrame(
child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
.local_surface_id(),
std::move(compositor_frame), nullptr, 0);
+ frame_trackers_.NotifySubmitFrame(frame_token, false, begin_frame_ack,
+ last_begin_frame_args_);
// We don't set |waiting_for_compositor_ack_| here since we want to allow a
// subsequent real frame to replace it at any time if needed.
@@ -533,6 +541,10 @@ viz::CompositorFrame VideoFrameSubmitter::CreateCompositorFrame(
*next_frame_token_, "Pre-submit buffering");
frame_token_to_timestamp_map_[*next_frame_token_] = value;
+
+ if (begin_frame_ack.source_id == viz::BeginFrameArgs::kManualSourceId)
+ ignorable_submitted_frames_.insert(*next_frame_token_);
+
UMA_HISTOGRAM_TIMES("Media.VideoFrameSubmitter.PreSubmitBuffering",
base::TimeTicks::Now() - value);
} else {
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 886b6330cf2..0953c624df4 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
@@ -19,6 +19,7 @@
#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/buffer.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom-blink.h"
#include "services/viz/public/mojom/compositing/frame_timing_details.mojom-blink.h"
@@ -131,8 +132,8 @@ class PLATFORM_EXPORT VideoFrameSubmitter
cc::VideoFrameProvider* video_frame_provider_ = nullptr;
scoped_refptr<viz::RasterContextProvider> context_provider_;
- viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_;
- mojom::blink::SurfaceEmbedderPtr surface_embedder_;
+ mojo::Remote<viz::mojom::blink::CompositorFrameSink> compositor_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_;
@@ -185,6 +186,11 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// Required for FrameSequenceTrackerCollection::NotifySubmitFrame
viz::BeginFrameArgs last_begin_frame_args_;
+ // The token of the frames that are submitted outside OnBeginFrame(). These
+ // frames should be ignored by the video tracker even if they are reported as
+ // presented.
+ base::flat_set<uint32_t> ignorable_submitted_frames_;
+
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<VideoFrameSubmitter> weak_ptr_factory_{this};
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 4b0dce2af6c..742b9d0cc98 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
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/test/simple_test_tick_clock.h"
@@ -24,6 +25,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.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.h"
#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -182,10 +184,9 @@ 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_ =
- viz::mojom::blink::CompositorFrameSinkPtr(std::move(submitter_sink));
- mojom::blink::SurfaceEmbedderPtr embedder;
- mojo::MakeRequest(&embedder);
+ submitter_->compositor_frame_sink_.Bind(std::move(submitter_sink));
+ mojo::Remote<mojom::blink::SurfaceEmbedder> embedder;
+ ignore_result(embedder.BindNewPipeAndPassReceiver());
submitter_->surface_embedder_ = std::move(embedder);
auto surface_id = viz::SurfaceId(
viz::FrameSinkId(1, 1),
@@ -917,4 +918,14 @@ TEST_F(VideoFrameSubmitterTest, NoDuplicateFramesDidReceiveFrame) {
task_environment_.RunUntilIdle();
}
+TEST_F(VideoFrameSubmitterTest, ZeroSizedFramesAreNotSubmitted) {
+ auto vf = media::VideoFrame::CreateEOSFrame();
+ ASSERT_TRUE(vf->natural_size().IsEmpty());
+
+ EXPECT_CALL(*video_frame_provider_, GetCurrentFrame()).WillOnce(Return(vf));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(0);
+ submitter_->DidReceiveFrame();
+ task_environment_.RunUntilIdle();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
index 3088edaae03..43fabbc3f3a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -30,6 +30,7 @@ blink_platform_sources("heap") {
"blink_gc_memory_dump_provider.h",
"cancelable_task_scheduler.cc",
"cancelable_task_scheduler.h",
+ "disallow_new_wrapper.h",
"finalizer_traits.h",
"garbage_collected.h",
"gc_info.cc",
@@ -67,6 +68,8 @@ blink_platform_sources("heap") {
"thread_state.cc",
"thread_state.h",
"thread_state_scopes.h",
+ "thread_state_statistics.cc",
+ "thread_state_statistics.h",
"threading_traits.h",
"trace_traits.h",
"unified_heap_controller.cc",
@@ -87,6 +90,21 @@ blink_platform_sources("heap") {
]
}
+jumbo_source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "heap_test_utilities.cc",
+ "heap_test_utilities.h",
+ ]
+
+ deps = [
+ "//testing/gtest",
+ "//third_party/blink/public/mojom:mojom_platform_blink_headers",
+ "//third_party/blink/renderer/platform:bindings_buildflags",
+ ]
+}
+
test("blink_heap_unittests") {
deps = [
":blink_heap_unittests_sources",
@@ -112,8 +130,6 @@ jumbo_source_set("blink_heap_unittests_sources") {
"heap_compact_test.cc",
"heap_stats_collector_test.cc",
"heap_test.cc",
- "heap_test_utilities.cc",
- "heap_test_utilities.h",
"heap_thread_test.cc",
"heap_traits_test.cc",
"incremental_marking_test.cc",
@@ -123,6 +139,7 @@ jumbo_source_set("blink_heap_unittests_sources") {
"persistent_test.cc",
"thread_state_scheduling_test.cc",
"worklist_test.cc",
+ "write_barrier_perftest.cc",
]
configs += [
diff --git a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
index 34a5c254803..ac60de45424 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
+++ b/chromium/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
@@ -40,8 +40,13 @@ You may not allocate an on-heap object on stack.
Your class may need to have a tracing method. See [Tracing](#Tracing) for details.
-If your class needs finalization (i.e. some work needs to be done on destruction), use
-[GarbageCollectedFinalized](#GarbageCollectedFinalized) instead.
+Your class will be automatically finalized as long as it is non-trivially destructible. Non-final classes are
+required to have a virtual destructor.
+
+Note that finalization is done at an arbitrary time after the object becomes unreachable.
+
+Any destructor executed within the finalization period must not touch any other on-heap object, because destructors
+can be executed in any order.
`GarbageCollected<T>` or any class deriving from `GarbageCollected<T>`, directly or indirectly, must be the first
element in its base class list (called "leftmost derivation rule"). This rule is needed to assure each on-heap object
@@ -75,40 +80,11 @@ public:
};
```
-### GarbageCollectedFinalized
-
-If you want to make your class garbage-collected and the class needs finalization, your class needs to inherit from
-`GarbageCollectedFinalized<YourClass>` instead of `GarbageCollected<YourClass>`.
-
-A class is said to *need finalization* when it meets either of the following criteria:
-
-* It has non-empty destructor; or
-* It has a member that needs finalization.
-
-```c++
-class YourClass : public GarbageCollectedFinalized<YourClass> {
-public:
- ~YourClass() { ... } // Non-empty destructor means finalization is needed.
-
-private:
- scoped_refptr<Something> something_; // scoped_refptr<> has non-empty destructor, so finalization is needed.
-};
-```
-
-Note that finalization is done at an arbitrary time after the object becomes unreachable.
-
-Any destructor executed within the finalization period must not touch any other on-heap object, because destructors
-can be executed in any order.
-
-Because `GarbageCollectedFinalized<T>` is a special case of `GarbageCollected<T>`, all the restrictions that apply
-to `GarbageCollected<T>` classes also apply to `GarbageCollectedFinalized<T>`.
-
### GarbageCollectedMixin
A non-leftmost base class of a garbage-collected class may derive from `GarbageCollectedMixin`. If a direct child
-class of `GarbageCollected<T>` or `GarbageCollectedFinalized<T>` has a non-leftmost base class deriving from
-`GarbageCollectedMixin`, the garbage-collected class must declare the `USING_GARBAGE_COLLECTED_MIXIN(ClassName)` macro
-in its class declaration.
+class of `GarbageCollected<T>` has a non-leftmost base class deriving from `GarbageCollectedMixin`, the
+garbage-collected class must declare the `USING_GARBAGE_COLLECTED_MIXIN(ClassName)` macro in its class declaration.
A class deriving from `GarbageCollectedMixin` can be treated similarly as garbage-collected classes. Specifically, it
can have `Member<T>`s and `WeakMember<T>`s, and a tracing method. A pointer to such a class must be retained in the
@@ -179,7 +155,7 @@ It is invoked before the sweeping phase starts to allow a pre-finalizer to touch
It is useful for doing cleanups that cannot be done with a destructor.
```c++
-class YourClass : public GarbageCollectedFinalized<YourClass> {
+class YourClass : public GarbageCollected<YourClass> {
USING_PRE_FINALIZER(YourClass, Dispose);
public:
void Dispose() {
@@ -200,7 +176,7 @@ Sometimes it is necessary to further delegate pre-finalizers up the class hierar
It is possible to construct such delegations using virtual methods.
```c++
-class Parent : public GarbageCollectedFinalized<Parent> {
+class Parent : public GarbageCollected<Parent> {
USING_PRE_FINALIZER(Parent, Dispose);
public:
void Dispose() { DisposeImpl(); }
diff --git a/chromium/third_party/blink/renderer/platform/heap/DEPS b/chromium/third_party/blink/renderer/platform/heap/DEPS
index 43c7d4fba14..eda4c2ea500 100644
--- a/chromium/third_party/blink/renderer/platform/heap/DEPS
+++ b/chromium/third_party/blink/renderer/platform/heap/DEPS
@@ -9,8 +9,11 @@ include_rules = [
"+base/atomicops.h",
"+base/bits.h",
"+base/sampling_heap_profiler/poisson_allocation_sampler.h",
+ "+base/strings/string_number_conversions.h",
"+base/synchronization/lock.h",
"+base/task_runner.h",
+ "+base/template_util.h",
+ "+testing/perf/perf_test.h",
"+third_party/blink/renderer/platform/bindings",
"+third_party/blink/renderer/platform/instrumentation/histogram.h",
diff --git a/chromium/third_party/blink/renderer/platform/heap/OWNERS b/chromium/third_party/blink/renderer/platform/heap/OWNERS
index cf641acea1f..bca3233e2e4 100644
--- a/chromium/third_party/blink/renderer/platform/heap/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/heap/OWNERS
@@ -1,4 +1,4 @@
-erik.corry@gmail.com
+bikineev@chromium.org
haraken@chromium.org
kouhei@chromium.org
mlippautz@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc.cc b/chromium/third_party/blink/renderer/platform/heap/blink_gc.cc
index 6e58baa0dab..cdf0a47e63b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc.cc
@@ -34,10 +34,8 @@ const char* BlinkGC::ToString(BlinkGC::MarkingType type) {
switch (type) {
case BlinkGC::MarkingType::kAtomicMarking:
return "AtomicMarking";
- case BlinkGC::MarkingType::kIncrementalMarking:
- return "IncrementalMarking";
- case BlinkGC::MarkingType::kTakeSnapshot:
- return "TakeSnapshot";
+ case BlinkGC::MarkingType::kIncrementalAndConcurrentMarking:
+ return "IncrementalAndConcurrentMarking";
}
IMMEDIATE_CRASH();
}
@@ -62,4 +60,20 @@ const char* BlinkGC::ToString(BlinkGC::StackState stack_state) {
IMMEDIATE_CRASH();
}
+const char* BlinkGC::ToString(BlinkGC::ArenaIndices arena_index) {
+#define ArenaCase(name) \
+ case k##name##ArenaIndex: \
+ return "" #name "Arena";
+
+ switch (arena_index) {
+ FOR_EACH_ARENA(ArenaCase)
+
+ case BlinkGC::ArenaIndices::kNumberOfArenas:
+ IMMEDIATE_CRASH();
+ }
+ IMMEDIATE_CRASH();
+
+#undef ArenaCase
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
index 3ce4e9d5821..3eebe011100 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -41,20 +41,26 @@ using MovingObjectCallback = void (*)(MovableReference from,
MovableReference to,
size_t);
-// List of typed arenas. The list is used to generate the implementation
-// of typed arena related methods.
-//
-// To create a new typed arena add a H(<ClassName>) to the
-// FOR_EACH_TYPED_ARENA macro below.
-#define FOR_EACH_TYPED_ARENA(H) \
- H(Node) \
- H(CSSValue)
-
-#define TypedArenaEnumName(Type) k##Type##ArenaIndex,
+// List of all arenas. Includes typed arenas as well.
+#define FOR_EACH_ARENA(H) \
+ H(NormalPage1) \
+ H(NormalPage2) \
+ H(NormalPage3) \
+ H(NormalPage4) \
+ H(Vector1) \
+ H(Vector2) \
+ H(Vector3) \
+ H(Vector4) \
+ H(InlineVector) \
+ H(HashTable) \
+ H(Node) \
+ H(CSSValue) \
+ H(LargeObject)
class PLATFORM_EXPORT WorklistTaskId {
public:
- static constexpr int MainThread = 0;
+ static constexpr int MutatorThread = 0;
+ static constexpr int ConcurrentThreadBase = 1;
};
class PLATFORM_EXPORT BlinkGC final {
@@ -70,11 +76,9 @@ class PLATFORM_EXPORT BlinkGC final {
enum MarkingType {
// The marking completes synchronously.
kAtomicMarking,
- // The marking task is split and executed in chunks.
- kIncrementalMarking,
- // We run marking to take a heap snapshot. Sweeping should do nothing and
- // just clear the mark flags.
- kTakeSnapshot,
+ // The marking task is split and executed in chunks (either on the mutator
+ // thread or concurrently).
+ kIncrementalAndConcurrentMarking
};
enum SweepingType {
@@ -104,21 +108,13 @@ class PLATFORM_EXPORT BlinkGC final {
kMaxValue = kUnifiedHeapForMemoryReductionGC,
};
+#define DeclareArenaIndex(name) k##name##ArenaIndex,
enum ArenaIndices {
- kNormalPage1ArenaIndex = 0,
- kNormalPage2ArenaIndex,
- kNormalPage3ArenaIndex,
- kNormalPage4ArenaIndex,
- kVector1ArenaIndex,
- kVector2ArenaIndex,
- kVector3ArenaIndex,
- kVector4ArenaIndex,
- kInlineVectorArenaIndex,
- kHashTableArenaIndex,
- FOR_EACH_TYPED_ARENA(TypedArenaEnumName) kLargeObjectArenaIndex,
+ FOR_EACH_ARENA(DeclareArenaIndex)
// Values used for iteration of heap segments.
kNumberOfArenas,
};
+#undef DeclareArenaIndex
enum V8GCType {
kV8MinorGC,
@@ -132,6 +128,7 @@ class PLATFORM_EXPORT BlinkGC final {
static const char* ToString(MarkingType);
static const char* ToString(StackState);
static const char* ToString(SweepingType);
+ static const char* ToString(ArenaIndices);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
index ba7a8ac9f47..d4105605814 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
@@ -4,10 +4,15 @@
#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
+#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 "base/trace_event/process_memory_dump.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/heap/thread_state_statistics.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
@@ -15,64 +20,125 @@
namespace blink {
namespace {
-void DumpMemoryTotals(base::trace_event::ProcessMemoryDump* memory_dump) {
- base::trace_event::MemoryAllocatorDump* allocator_dump =
- memory_dump->CreateAllocatorDump("blink_gc");
- allocator_dump->AddScalar("size", "bytes",
- ProcessHeap::TotalAllocatedSpace());
-
- base::trace_event::MemoryAllocatorDump* objects_dump =
- memory_dump->CreateAllocatorDump("blink_gc/allocated_objects");
-
- // ThreadHeap::markedObjectSize() can be underestimated if we're still in the
- // process of lazy sweeping.
- objects_dump->AddScalar("size", "bytes",
- ProcessHeap::TotalAllocatedObjectSize());
+constexpr const char* HeapTypeString(
+ BlinkGCMemoryDumpProvider::HeapType heap_type) {
+ switch (heap_type) {
+ case BlinkGCMemoryDumpProvider::HeapType::kBlinkMainThread:
+ return "main";
+ case BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread:
+ return "workers";
+ }
}
} // namespace
-BlinkGCMemoryDumpProvider* BlinkGCMemoryDumpProvider::Instance() {
- DEFINE_STATIC_LOCAL(BlinkGCMemoryDumpProvider, instance, ());
- return &instance;
+BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider(
+ ThreadState* thread_state,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ BlinkGCMemoryDumpProvider::HeapType heap_type)
+ : thread_state_(thread_state),
+ heap_type_(heap_type),
+ dump_base_name_(
+ "blink_gc/" + std::string(HeapTypeString(heap_type_)) + "/heap" +
+ (heap_type_ == HeapType::kBlinkWorkerThread
+ ? "/" + base::StringPrintf(
+ "worker_0x%" PRIXPTR,
+ reinterpret_cast<uintptr_t>(thread_state_))
+ : "")) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, "BlinkGC", task_runner);
}
-BlinkGCMemoryDumpProvider::~BlinkGCMemoryDumpProvider() = default;
+BlinkGCMemoryDumpProvider::~BlinkGCMemoryDumpProvider() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+}
bool BlinkGCMemoryDumpProvider::OnMemoryDump(
const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* memory_dump) {
- using base::trace_event::MemoryDumpLevelOfDetail;
- MemoryDumpLevelOfDetail level_of_detail = args.level_of_detail;
- // In the case of a detailed dump perform a mark-only GC pass to collect
- // more detailed stats.
- if (level_of_detail == MemoryDumpLevelOfDetail::DETAILED) {
- ThreadState::Current()->CollectGarbage(
- BlinkGC::kNoHeapPointersOnStack, BlinkGC::kTakeSnapshot,
- BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting);
+ base::trace_event::ProcessMemoryDump* process_memory_dump) {
+ ThreadState::Statistics::DetailLevel detail_level =
+ args.level_of_detail ==
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED
+ ? ThreadState::Statistics::kDetailed
+ : ThreadState::Statistics::kBrief;
+
+ ThreadState::Statistics stats =
+ ThreadState::StatisticsCollector(thread_state_)
+ .CollectStatistics(detail_level);
+
+ auto* heap_dump = process_memory_dump->CreateAllocatorDump(dump_base_name_);
+ heap_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ stats.committed_size_bytes);
+ heap_dump->AddScalar("allocated_objects_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ stats.used_size_bytes);
+
+ if (detail_level == ThreadState::Statistics::kBrief) {
+ return true;
}
- DumpMemoryTotals(memory_dump);
- // Merge all dumps collected by ThreadHeap::collectGarbage.
- if (level_of_detail == MemoryDumpLevelOfDetail::DETAILED)
- memory_dump->TakeAllDumpsFrom(current_process_memory_dump_.get());
- return true;
-}
+ // Detailed statistics.
+ for (const ThreadState::Statistics::ArenaStatistics& arena_stats :
+ stats.arena_stats) {
+ std::string arena_dump_name = dump_base_name_ + "/" + arena_stats.name;
+ auto* arena_dump =
+ process_memory_dump->CreateAllocatorDump(arena_dump_name);
+ arena_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ arena_stats.committed_size_bytes);
+ arena_dump->AddScalar("allocated_objects_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ arena_stats.used_size_bytes);
-base::trace_event::MemoryAllocatorDump*
-BlinkGCMemoryDumpProvider::CreateMemoryAllocatorDumpForCurrentGC(
- const String& absolute_name) {
- // TODO(bashi): Change type name of |absoluteName|.
- return current_process_memory_dump_->CreateAllocatorDump(
- absolute_name.Utf8());
-}
+ size_t page_count = 0;
+ for (const ThreadState::Statistics::PageStatistics& page_stats :
+ arena_stats.page_stats) {
+ auto* page_dump = process_memory_dump->CreateAllocatorDump(
+ arena_dump_name + "/pages/page_" +
+ base::NumberToString(page_count++));
+ page_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ page_stats.committed_size_bytes);
+ page_dump->AddScalar("allocated_objects_size",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ page_stats.used_size_bytes);
+ }
-void BlinkGCMemoryDumpProvider::ClearProcessDumpForCurrentGC() {
- current_process_memory_dump_->Clear();
-}
+ const ThreadState::Statistics::FreeListStatistics& free_list_stats =
+ arena_stats.free_list_stats;
+ for (wtf_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]);
+ std::string padded_bucket_size =
+ 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);
+ free_list_bucket_dump->AddScalar(
+ "free_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ free_list_stats.free_size[i]);
+ }
+
+ const ThreadState::Statistics::ObjectStatistics& object_stats =
+ arena_stats.object_stats;
+ for (wtf_size_t i = 1; i < object_stats.num_types; i++) {
+ if (object_stats.type_name[i].empty())
+ continue;
-BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider()
- : current_process_memory_dump_(new base::trace_event::ProcessMemoryDump(
- {base::trace_event::MemoryDumpLevelOfDetail::DETAILED})) {}
+ 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]);
+ }
+ }
+ return true;
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h
index 278e83a11f1..42be7084019 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h
@@ -12,49 +12,36 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace base {
-namespace trace_event {
-
-class MemoryAllocatorDump;
-
-} // namespace trace_event
+class SingleThreadTaskRunner;
} // namespace base
namespace blink {
-class WebMemoryAllocatorDump;
+
+class ThreadState;
class PLATFORM_EXPORT BlinkGCMemoryDumpProvider final
: public base::trace_event::MemoryDumpProvider {
USING_FAST_MALLOC(BlinkGCMemoryDumpProvider);
public:
- static BlinkGCMemoryDumpProvider* Instance();
- ~BlinkGCMemoryDumpProvider() override;
+ enum class HeapType { kBlinkMainThread, kBlinkWorkerThread };
+
+ ~BlinkGCMemoryDumpProvider() final;
+ BlinkGCMemoryDumpProvider(
+ ThreadState* thread_state,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ HeapType heap_type);
// MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs&,
- base::trace_event::ProcessMemoryDump*) override;
-
- // The returned WebMemoryAllocatorDump is owned by
- // BlinkGCMemoryDumpProvider, and should not be retained (just used to
- // dump in the current call stack).
- base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDumpForCurrentGC(
- const String& absolute_name);
-
- // This must be called before taking a new process-wide GC snapshot, to
- // clear the previous dumps.
- void ClearProcessDumpForCurrentGC();
-
- base::trace_event::ProcessMemoryDump* CurrentProcessMemoryDump() {
- return current_process_memory_dump_.get();
- }
+ base::trace_event::ProcessMemoryDump*) final;
private:
- BlinkGCMemoryDumpProvider();
-
- std::unique_ptr<base::trace_event::ProcessMemoryDump>
- current_process_memory_dump_;
+ ThreadState* const thread_state_;
+ const HeapType heap_type_;
+ const std::string dump_base_name_;
};
} // namespace blink
-#endif
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_BLINK_GC_MEMORY_DUMP_PROVIDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
index bd590dd3bd5..7ad0cee1cea 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
@@ -7,18 +7,125 @@
#include "base/trace_event/process_memory_dump.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/heap/blink_gc.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
namespace blink {
-TEST(BlinkGCDumpProviderTest, MemoryDump) {
+namespace {
+class BlinkGCMemoryDumpProviderTest : public TestSupportingGC {};
+
+void CheckBasicHeapDumpStructure(base::trace_event::MemoryAllocatorDump* dump) {
+ ASSERT_NE(nullptr, dump);
+
+ bool found_allocated_object_size = false;
+ bool found_size = false;
+ for (const auto& entry : dump->entries()) {
+ if (entry.name == "allocated_objects_size")
+ found_allocated_object_size = true;
+ if (entry.name == "size")
+ found_size = true;
+ }
+ EXPECT_TRUE(found_allocated_object_size);
+ EXPECT_TRUE(found_size);
+}
+
+} // namespace
+
+TEST_F(BlinkGCMemoryDumpProviderTest, MainThreadLightDump) {
+ base::trace_event::MemoryDumpArgs args = {
+ base::trace_event::MemoryDumpLevelOfDetail::LIGHT};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> dump(
+ new base::trace_event::ProcessMemoryDump(args));
+ std::unique_ptr<BlinkGCMemoryDumpProvider> dump_provider(
+ new BlinkGCMemoryDumpProvider(
+ ThreadState::Current(), base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkMainThread));
+ dump_provider->OnMemoryDump(args, dump.get());
+
+ auto* main_heap = dump->GetAllocatorDump("blink_gc/main/heap");
+ CheckBasicHeapDumpStructure(main_heap);
+}
+
+TEST_F(BlinkGCMemoryDumpProviderTest, MainThreadDetailedDump) {
+ base::trace_event::MemoryDumpArgs args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> dump(
+ new base::trace_event::ProcessMemoryDump(args));
+ std::unique_ptr<BlinkGCMemoryDumpProvider> dump_provider(
+ new BlinkGCMemoryDumpProvider(
+ ThreadState::Current(), base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkMainThread));
+ dump_provider->OnMemoryDump(args, dump.get());
+
+ // All arenas should be present in the dump.
+#define CheckArena(name) \
+ CheckBasicHeapDumpStructure( \
+ dump->GetAllocatorDump("blink_gc/main/heap/" #name "Arena"));
+
+ FOR_EACH_ARENA(CheckArena)
+#undef CheckArena
+}
+
+TEST_F(BlinkGCMemoryDumpProviderTest, WorkerLightDump) {
+ base::trace_event::MemoryDumpArgs args = {
+ base::trace_event::MemoryDumpLevelOfDetail::LIGHT};
+ std::unique_ptr<base::trace_event::ProcessMemoryDump> dump(
+ new base::trace_event::ProcessMemoryDump(args));
+ std::unique_ptr<BlinkGCMemoryDumpProvider> dump_provider(
+ new BlinkGCMemoryDumpProvider(
+ ThreadState::Current(), base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread));
+ dump_provider->OnMemoryDump(args, dump.get());
+
+ // There should be no main thread heap dump available.
+ ASSERT_EQ(nullptr, dump->GetAllocatorDump("blink_gc/main/heap"));
+
+ size_t workers_found = 0;
+ for (const auto& kvp : dump->allocator_dumps()) {
+ if (kvp.first.find("blink_gc/workers/heap") != std::string::npos) {
+ workers_found++;
+ CheckBasicHeapDumpStructure(dump->GetAllocatorDump(kvp.first));
+ }
+ }
+ EXPECT_EQ(1u, workers_found);
+}
+
+TEST_F(BlinkGCMemoryDumpProviderTest, WorkerDetailedDump) {
base::trace_event::MemoryDumpArgs args = {
base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
std::unique_ptr<base::trace_event::ProcessMemoryDump> dump(
new base::trace_event::ProcessMemoryDump(args));
- BlinkGCMemoryDumpProvider::Instance()->OnMemoryDump(args, dump.get());
- DCHECK(dump->GetAllocatorDump("blink_gc"));
- DCHECK(dump->GetAllocatorDump("blink_gc/allocated_objects"));
+ std::unique_ptr<BlinkGCMemoryDumpProvider> dump_provider(
+ new BlinkGCMemoryDumpProvider(
+ ThreadState::Current(), base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread));
+ dump_provider->OnMemoryDump(args, dump.get());
+
+ // There should be no main thread heap dump available.
+ ASSERT_EQ(nullptr, dump->GetAllocatorDump("blink_gc/main/heap"));
+
+ // Find worker suffix.
+ std::string worker_suffix;
+ for (const auto& kvp : dump->allocator_dumps()) {
+ if (kvp.first.find("blink_gc/workers/heap/worker_0x") !=
+ std::string::npos) {
+ auto start_pos = kvp.first.find("_0x");
+ auto end_pos = kvp.first.find("/", start_pos);
+ worker_suffix = kvp.first.substr(start_pos + 1, end_pos - start_pos - 1);
+ }
+ }
+ std::string worker_base_path =
+ "blink_gc/workers/heap/worker_" + worker_suffix;
+ CheckBasicHeapDumpStructure(dump->GetAllocatorDump(worker_base_path));
+
+#define CheckArena(name) \
+ CheckBasicHeapDumpStructure( \
+ dump->GetAllocatorDump(worker_base_path + "/" #name "Arena"));
+
+ FOR_EACH_ARENA(CheckArena)
+#undef CheckArena
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h b/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h
index dacd97da487..914ab57871b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h
@@ -11,6 +11,7 @@
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.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/functional.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -24,6 +25,8 @@ namespace blink {
// before they are invoked. User is responsible for synchronizing completion of
// tasks and destruction of CancelableTaskScheduler.
class PLATFORM_EXPORT CancelableTaskScheduler final {
+ USING_FAST_MALLOC(CancelableTaskScheduler);
+
public:
using Task = WTF::CrossThreadOnceFunction<void()>;
diff --git a/chromium/third_party/blink/renderer/platform/heap/disallow_new_wrapper.h b/chromium/third_party/blink/renderer/platform/heap/disallow_new_wrapper.h
new file mode 100644
index 00000000000..118cadb044e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/disallow_new_wrapper.h
@@ -0,0 +1,39 @@
+// 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_HEAP_DISALLOW_NEW_WRAPPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_DISALLOW_NEW_WRAPPER_H_
+
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+
+namespace blink {
+
+// DisallowNewWrapper wraps a disallow new type in a GarbageCollected class.
+template <typename T>
+class DisallowNewWrapper : public GarbageCollected<DisallowNewWrapper<T>> {
+ public:
+ explicit DisallowNewWrapper(const T& value) : value_(value) {
+ static_assert(WTF::IsDisallowNew<T>::value,
+ "T needs to be a disallow new type");
+ static_assert(WTF::IsTraceable<T>::value, "T needs to be traceable");
+ }
+
+ const T& Value() const { return value_; }
+
+ void Trace(Visitor* visitor) { visitor->Trace(value_); }
+
+ private:
+ T value_;
+};
+
+// Wraps a disallow new type in a GarbageCollected class, making it possible to
+// be referenced off heap from a Persistent.
+template <typename T>
+DisallowNewWrapper<T>* WrapDisallowNew(const T& value) {
+ return MakeGarbageCollected<DisallowNewWrapper<T>>(value);
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_DISALLOW_NEW_WRAPPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h b/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
index 3a2a9a69b4b..d96e35642b4 100644
--- a/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/finalizer_traits.h
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FINALIZER_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_FINALIZER_TRAITS_H_
+#include <type_traits>
+
+#include "base/template_util.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
namespace WTF {
@@ -16,18 +19,42 @@ class ListHashSetNode;
namespace blink {
-// The FinalizerTraitImpl specifies how to finalize objects. Objects that
-// inherit from GarbageCollectedFinalized are finalized by calling their
-// |Finalize| method which by default will call the destructor on the object.
-template <typename T, bool isGarbageCollectedFinalized>
+namespace internal {
+
+template <typename T, typename = void>
+struct HasFinalizeGarbageCollectedObject : std::false_type {};
+
+template <typename T>
+struct HasFinalizeGarbageCollectedObject<
+ T,
+ base::void_t<decltype(std::declval<T>().FinalizeGarbageCollectedObject())>>
+ : std::true_type {};
+
+// The FinalizerTraitImpl specifies how to finalize objects.
+template <typename T, bool isFinalized>
struct FinalizerTraitImpl;
template <typename T>
struct FinalizerTraitImpl<T, true> {
+ private:
STATIC_ONLY(FinalizerTraitImpl);
+ struct CustomDispatch {
+ static void Call(void* obj) {
+ static_cast<T*>(obj)->FinalizeGarbageCollectedObject();
+ }
+ };
+ struct DestructorDispatch {
+ static void Call(void* obj) { static_cast<T*>(obj)->~T(); }
+ };
+ using FinalizeImpl =
+ std::conditional_t<HasFinalizeGarbageCollectedObject<T>::value,
+ CustomDispatch,
+ DestructorDispatch>;
+
+ public:
static void Finalize(void* obj) {
static_assert(sizeof(T), "T must be fully defined");
- static_cast<T*>(obj)->FinalizeGarbageCollectedObject();
+ FinalizeImpl::Call(obj);
}
};
@@ -39,21 +66,18 @@ struct FinalizerTraitImpl<T, false> {
}
};
+} // namespace internal
+
// The FinalizerTrait is used to determine if a type requires finalization and
// what finalization means.
-//
-// By default classes that inherit from GarbageCollectedFinalized need
-// finalization and finalization means calling the |Finalize| method of the
-// object. The FinalizerTrait can be specialized if the default behavior is not
-// desired.
template <typename T>
struct FinalizerTrait {
STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer =
- WTF::IsSubclassOfTemplate<typename std::remove_const<T>::type,
- GarbageCollectedFinalized>::value;
+ static constexpr bool kNonTrivialFinalizer =
+ internal::HasFinalizeGarbageCollectedObject<T>::value ||
+ !std::is_trivially_destructible<typename std::remove_cv<T>::type>::value;
static void Finalize(void* obj) {
- FinalizerTraitImpl<T, kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<T, kNonTrivialFinalizer>::Finalize(obj);
}
};
@@ -66,32 +90,32 @@ class HeapHashTableBacking;
template <typename T, typename U, typename V>
struct FinalizerTrait<LinkedHashSet<T, U, V, HeapAllocator>> {
STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer = true;
+ static constexpr bool kNonTrivialFinalizer = true;
static void Finalize(void* obj) {
- FinalizerTraitImpl<LinkedHashSet<T, U, V, HeapAllocator>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<LinkedHashSet<T, U, V, HeapAllocator>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
template <typename T, typename Allocator>
struct FinalizerTrait<WTF::ListHashSetNode<T, Allocator>> {
STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer =
+ static constexpr bool kNonTrivialFinalizer =
!std::is_trivially_destructible<T>::value;
static void Finalize(void* obj) {
- FinalizerTraitImpl<WTF::ListHashSetNode<T, Allocator>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<WTF::ListHashSetNode<T, Allocator>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
template <typename T, size_t inlineCapacity>
struct FinalizerTrait<Vector<T, inlineCapacity, HeapAllocator>> {
STATIC_ONLY(FinalizerTrait);
- static const bool kNonTrivialFinalizer =
+ static constexpr bool kNonTrivialFinalizer =
inlineCapacity && VectorTraits<T>::kNeedsDestruction;
static void Finalize(void* obj) {
- FinalizerTraitImpl<Vector<T, inlineCapacity, HeapAllocator>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<Vector<T, inlineCapacity, HeapAllocator>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
@@ -101,8 +125,8 @@ struct FinalizerTrait<Deque<T, inlineCapacity, HeapAllocator>> {
static const bool kNonTrivialFinalizer =
inlineCapacity && VectorTraits<T>::kNeedsDestruction;
static void Finalize(void* obj) {
- FinalizerTraitImpl<Deque<T, inlineCapacity, HeapAllocator>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<Deque<T, inlineCapacity, HeapAllocator>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
@@ -112,8 +136,8 @@ struct FinalizerTrait<HeapHashTableBacking<Table>> {
static const bool kNonTrivialFinalizer =
!std::is_trivially_destructible<typename Table::ValueType>::value;
static void Finalize(void* obj) {
- FinalizerTraitImpl<HeapHashTableBacking<Table>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<HeapHashTableBacking<Table>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
@@ -122,8 +146,8 @@ struct FinalizerTrait<HeapVectorBacking<T, Traits>> {
STATIC_ONLY(FinalizerTrait);
static const bool kNonTrivialFinalizer = Traits::kNeedsDestruction;
static void Finalize(void* obj) {
- FinalizerTraitImpl<HeapVectorBacking<T, Traits>,
- kNonTrivialFinalizer>::Finalize(obj);
+ internal::FinalizerTraitImpl<HeapVectorBacking<T, Traits>,
+ kNonTrivialFinalizer>::Finalize(obj);
}
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
index f83943bf552..d0f4d272e94 100644
--- a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
+++ b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
@@ -179,48 +179,11 @@ class PLATFORM_EXPORT GarbageCollectedMixin {
// Base class for objects allocated in the Blink garbage-collected heap.
//
-// Defines a 'new' operator that allocates the memory in the heap. 'delete'
-// should not be called on objects that inherit from GarbageCollected.
-//
-// Instances of GarbageCollected will *NOT* get finalized. Their destructor
-// will not be called. Therefore, only classes that have trivial destructors
-// with no semantic meaning (including all their subclasses) should inherit from
-// GarbageCollected. If there are non-trival destructors in a given class or
-// any of its subclasses, GarbageCollectedFinalized should be used which
-// guarantees that the destructor is called on an instance when the garbage
-// collector determines that it is no longer reachable.
+// Instances of GarbageCollected will be finalized if they are non-trivially
+// destructible.
template <typename T>
class GarbageCollected;
-// Base class for objects allocated in the Blink garbage-collected heap.
-//
-// Defines a 'new' operator that allocates the memory in the heap. 'delete'
-// should not be called on objects that inherit from GarbageCollected.
-//
-// Instances of GarbageCollectedFinalized will have their destructor called when
-// the garbage collector determines that the object is no longer reachable.
-template <typename T>
-class GarbageCollectedFinalized : public GarbageCollected<T> {
- protected:
- // finalizeGarbageCollectedObject is called when the object is freed from
- // the heap. By default finalization means calling the destructor on the
- // object. finalizeGarbageCollectedObject can be overridden to support
- // calling the destructor of a subclass. This is useful for objects without
- // vtables that require explicit dispatching. The name is intentionally a
- // bit long to make name conflicts less likely.
- void FinalizeGarbageCollectedObject() { static_cast<T*>(this)->~T(); }
-
- GarbageCollectedFinalized() = default;
- ~GarbageCollectedFinalized() = default;
-
- template <typename U>
- friend struct HasFinalizer;
- template <typename U, bool>
- friend struct FinalizerTraitImpl;
-
- DISALLOW_COPY_AND_ASSIGN(GarbageCollectedFinalized);
-};
-
template <typename T,
bool = WTF::IsSubclassOfTemplate<typename std::remove_const<T>::type,
GarbageCollected>::value>
diff --git a/chromium/third_party/blink/renderer/platform/heap/gc_info.h b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
index 9466d29e3c8..fa960e46af7 100644
--- a/chromium/third_party/blink/renderer/platform/heap/gc_info.h
+++ b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
@@ -25,7 +25,7 @@
namespace blink {
// GCInfo contains metadata for objects that are instantiated from classes that
-// inherit for GarbageCollected or GarbageCollectedFinalized.
+// inherit from GarbageCollected.
struct GCInfo {
const TraceCallback trace;
const FinalizationCallback finalize;
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.cc b/chromium/third_party/blink/renderer/platform/heap/heap.cc
index 6a8ee14d839..af6f4b3903f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.cc
@@ -35,6 +35,7 @@
#include <memory>
#include "base/trace_event/process_memory_dump.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
@@ -190,7 +191,7 @@ void ThreadHeap::DestroyMarkingWorklists(BlinkGC::StackState stack_state) {
const bool conservative_gc =
BlinkGC::StackState::kHeapPointersOnStack == stack_state;
NotFullyConstructedItem item;
- while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MainThread,
+ while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MutatorThread,
&item)) {
HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress(
reinterpret_cast<Address>(const_cast<void*>(item)));
@@ -222,7 +223,8 @@ bool ThreadHeap::ShouldRegisterMovingAddress(Address address) {
void ThreadHeap::FlushNotFullyConstructedObjects() {
if (!not_fully_constructed_worklist_->IsGlobalEmpty()) {
- not_fully_constructed_worklist_->FlushToGlobal(WorklistTaskId::MainThread);
+ not_fully_constructed_worklist_->FlushToGlobal(
+ WorklistTaskId::MutatorThread);
previously_not_fully_constructed_worklist_->MergeGlobalPool(
not_fully_constructed_worklist_.get());
}
@@ -235,10 +237,10 @@ void ThreadHeap::MarkNotFullyConstructedObjects(MarkingVisitor* visitor) {
stats_collector(),
ThreadHeapStatsCollector::kMarkNotFullyConstructedObjects);
- DCHECK_EQ(WorklistTaskId::MainThread, visitor->task_id());
+ DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
NotFullyConstructedItem item;
- while (
- not_fully_constructed_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
+ while (not_fully_constructed_worklist_->Pop(WorklistTaskId::MutatorThread,
+ &item)) {
BasePage* const page = PageFromObject(item);
visitor->ConservativelyMarkAddress(page, reinterpret_cast<Address>(item));
}
@@ -250,25 +252,19 @@ void ThreadHeap::InvokeEphemeronCallbacks(MarkingVisitor* visitor) {
stats_collector(),
ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
- // MarkingVisitor records callbacks for weak tables in a worklist.
- // ThreadHeap reads from the worklist before invoking ephemeron callbacks.
- // We need to flush the callback worklist so ThreadHeap can access it.
- //
- // TODO(omerkatz): In concurrent marking, this should flush all visitors.
- if (thread_state_->in_atomic_pause())
- visitor->FlushWeakTableCallbacks();
-
// We first reiterate over known callbacks from previous iterations.
for (auto& tuple : ephemeron_callbacks_)
tuple.value(visitor, tuple.key);
- DCHECK_EQ(WorklistTaskId::MainThread, visitor->task_id());
+ DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
// Then we iterate over the new callbacks found by the marking visitor.
+ // Callbacks found by the concurrent marking will be flushed eventually
+ // and then invoked by the mutator thread (in the atomic pause at latest).
while (!weak_table_worklist_->IsGlobalEmpty()) {
// Read ephemeron callbacks from worklist to ephemeron_callbacks_ hashmap.
WeakTableWorklist::View ephemerons_worklist(weak_table_worklist_.get(),
- WorklistTaskId::MainThread);
+ WorklistTaskId::MutatorThread);
WeakTableItem item;
while (ephemerons_worklist.Pop(&item)) {
auto result = ephemeron_callbacks_.insert(item.object, item.callback);
@@ -288,13 +284,12 @@ bool DrainWorklistWithDeadline(base::TimeTicks deadline,
Worklist* worklist,
Callback callback,
int task_id) {
- const size_t kDeadlineCheckInterval = 2500;
+ const size_t kDeadlineCheckInterval = 1250;
size_t processed_callback_count = 0;
typename Worklist::EntryType item;
while (worklist->Pop(task_id, &item)) {
callback(item);
- processed_callback_count++;
if (++processed_callback_count == kDeadlineCheckInterval) {
if (deadline <= base::TimeTicks::Now()) {
return false;
@@ -309,9 +304,7 @@ bool DrainWorklistWithDeadline(base::TimeTicks deadline,
bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
base::TimeTicks deadline) {
- DCHECK_EQ(WorklistTaskId::MainThread, visitor->task_id());
-
- FlushV8References(visitor);
+ DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
bool finished;
// Ephemeron fixed point loop.
@@ -329,9 +322,9 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
->IsInConstruction());
item.callback(visitor, item.object);
},
- WorklistTaskId::MainThread);
+ WorklistTaskId::MutatorThread);
if (!finished)
- return false;
+ break;
// Iteratively mark all objects that were previously discovered while
// being in construction. The objects can be processed incrementally once
@@ -341,9 +334,9 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
[visitor](const NotFullyConstructedItem& item) {
visitor->DynamicallyMarkAddress(reinterpret_cast<Address>(item));
},
- WorklistTaskId::MainThread);
+ WorklistTaskId::MutatorThread);
if (!finished)
- return false;
+ break;
}
InvokeEphemeronCallbacks(visitor);
@@ -351,12 +344,24 @@ bool ThreadHeap::AdvanceMarking(MarkingVisitor* visitor,
// Rerun loop if ephemeron processing queued more objects for tracing.
} while (!marking_worklist_->IsGlobalEmpty());
- // In case we reached here, we might not enter these method again for a
- // while. Flush all V8 references before returning so we don't get left with
- /// unflushed references.
- FlushV8References(visitor);
+ FlushV8References();
- return true;
+ return finished;
+}
+
+bool ThreadHeap::AdvanceConcurrentMarking(ConcurrentMarkingVisitor* visitor,
+ base::TimeTicks deadline) {
+ // Iteratively mark all objects that are reachable from the objects
+ // currently pushed onto the marking worklist.
+ return DrainWorklistWithDeadline(
+ deadline, marking_worklist_.get(),
+ [visitor](const MarkingItem& item) {
+ DCHECK(
+ !HeapObjectHeader::FromPayload(item.object)
+ ->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>());
+ item.callback(visitor, item.object);
+ },
+ visitor->task_id());
}
void ThreadHeap::WeakProcessing(MarkingVisitor* visitor) {
@@ -367,11 +372,11 @@ void ThreadHeap::WeakProcessing(MarkingVisitor* visitor) {
// resurrecting them or allocating new ones.
ThreadState::NoAllocationScope allocation_forbidden(ThreadState::Current());
- DCHECK_EQ(WorklistTaskId::MainThread, visitor->task_id());
+ DCHECK_EQ(WorklistTaskId::MutatorThread, visitor->task_id());
// Call weak callbacks on objects that may now be pointing to dead objects.
CustomCallbackItem item;
- while (weak_callback_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
+ while (weak_callback_worklist_->Pop(WorklistTaskId::MutatorThread, &item)) {
item.callback(visitor, item.object);
}
// Weak callbacks should not add any new objects for marking.
@@ -535,128 +540,46 @@ BasePage* ThreadHeap::FindPageFromAddress(Address address) {
}
#endif
-void ThreadHeap::TakeSnapshot(SnapshotType type) {
- DCHECK(thread_state_->InAtomicMarkingPause());
-
- // 0 is used as index for freelist entries. Objects are indexed 1 to
- // gcInfoIndex.
- ThreadState::GCSnapshotInfo info(GCInfoTable::Get().GcInfoIndex() + 1);
- String thread_dump_name =
- String("blink_gc/thread_") + String::Number(thread_state_->ThreadId());
- const String heaps_dump_name = thread_dump_name + "/heaps";
- const String classes_dump_name = thread_dump_name + "/classes";
-
- int number_of_heaps_reported = 0;
-#define SNAPSHOT_HEAP(ArenaType) \
- { \
- number_of_heaps_reported++; \
- switch (type) { \
- case SnapshotType::kHeapSnapshot: \
- arenas_[BlinkGC::k##ArenaType##ArenaIndex]->TakeSnapshot( \
- heaps_dump_name + "/" #ArenaType, info); \
- break; \
- case SnapshotType::kFreelistSnapshot: \
- arenas_[BlinkGC::k##ArenaType##ArenaIndex]->TakeFreelistSnapshot( \
- heaps_dump_name + "/" #ArenaType); \
- break; \
- default: \
- NOTREACHED(); \
- } \
- }
-
- SNAPSHOT_HEAP(NormalPage1);
- SNAPSHOT_HEAP(NormalPage2);
- SNAPSHOT_HEAP(NormalPage3);
- SNAPSHOT_HEAP(NormalPage4);
- SNAPSHOT_HEAP(Vector1);
- SNAPSHOT_HEAP(Vector2);
- SNAPSHOT_HEAP(Vector3);
- SNAPSHOT_HEAP(Vector4);
- SNAPSHOT_HEAP(InlineVector);
- SNAPSHOT_HEAP(HashTable);
- SNAPSHOT_HEAP(LargeObject);
- FOR_EACH_TYPED_ARENA(SNAPSHOT_HEAP);
+void ThreadHeap::CollectStatistics(ThreadState::Statistics* stats) {
+#define SNAPSHOT_ARENA(name) \
+ arenas_[BlinkGC::k##name##ArenaIndex]->CollectStatistics( \
+ BlinkGC::ToString(BlinkGC::k##name##ArenaIndex), stats);
- DCHECK_EQ(number_of_heaps_reported, BlinkGC::kNumberOfArenas);
-
-#undef SNAPSHOT_HEAP
-
- if (type == SnapshotType::kFreelistSnapshot)
- return;
-
- size_t total_live_count = 0;
- size_t total_dead_count = 0;
- size_t total_live_size = 0;
- size_t total_dead_size = 0;
- for (uint32_t gc_info_index = 1;
- gc_info_index <= GCInfoTable::Get().GcInfoIndex(); ++gc_info_index) {
- total_live_count += info.live_count[gc_info_index];
- total_dead_count += info.dead_count[gc_info_index];
- total_live_size += info.live_size[gc_info_index];
- total_dead_size += info.dead_size[gc_info_index];
- }
+ FOR_EACH_ARENA(SNAPSHOT_ARENA)
+#undef SNAPSHOT_ARENA
+}
- base::trace_event::MemoryAllocatorDump* thread_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(thread_dump_name);
- thread_dump->AddScalar("live_count", "objects", total_live_count);
- thread_dump->AddScalar("dead_count", "objects", total_dead_count);
- thread_dump->AddScalar("live_size", "bytes", total_live_size);
- thread_dump->AddScalar("dead_size", "bytes", total_dead_size);
-
- base::trace_event::MemoryAllocatorDump* heaps_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(heaps_dump_name);
- base::trace_event::MemoryAllocatorDump* classes_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(classes_dump_name);
- BlinkGCMemoryDumpProvider::Instance()
- ->CurrentProcessMemoryDump()
- ->AddOwnershipEdge(classes_dump->guid(), heaps_dump->guid());
-}
-
-bool ThreadHeap::AdvanceLazySweep(base::TimeTicks deadline) {
- static const base::TimeDelta slack = base::TimeDelta::FromSecondsD(0.001);
- for (int i = 0; i < BlinkGC::kNumberOfArenas; i++) {
+bool ThreadHeap::AdvanceSweep(SweepingType sweeping_type,
+ base::TimeTicks deadline) {
+ static constexpr base::TimeDelta slack = base::TimeDelta::FromSecondsD(0.001);
+ auto sweeping_function = sweeping_type == SweepingType::kMutator
+ ? &BaseArena::LazySweepWithDeadline
+ : &BaseArena::ConcurrentSweepWithDeadline;
+ for (size_t i = 0; i < BlinkGC::kNumberOfArenas; i++) {
// lazySweepWithDeadline() won't check the deadline until it sweeps
// 10 pages. So we give a small slack for safety.
const base::TimeDelta remaining_budget =
deadline - slack - base::TimeTicks::Now();
if (remaining_budget <= base::TimeDelta() ||
- !arenas_[i]->LazySweepWithDeadline(deadline)) {
+ !(arenas_[i]->*sweeping_function)(deadline)) {
return false;
}
}
return true;
}
-void ThreadHeap::ConcurrentSweep() {
- // Concurrent sweep simply sweeps pages not calling finalizers.
- for (size_t i = BlinkGC::kNormalPage1ArenaIndex;
- i < BlinkGC::kNumberOfArenas; i++) {
- arenas_[i]->SweepOnConcurrentThread();
- }
-}
-
// TODO(omerkatz): Temporary solution until concurrent marking is ready. see
// https://crrev.com/c/1730054 for details. Eventually this will be removed.
-void ThreadHeap::FlushV8References(MarkingVisitor* visitor) {
+void ThreadHeap::FlushV8References() {
if (!thread_state_->IsUnifiedGCMarkingInProgress())
return;
- UnifiedHeapMarkingVisitor* unified_visitor =
- reinterpret_cast<UnifiedHeapMarkingVisitor*>(visitor);
-
- DCHECK((unified_visitor->task_id() != WorklistTaskId::MainThread) ||
- v8_references_worklist_->IsGlobalEmpty());
-
- // TODO(omerkatz): In concurrent marking, this should flush all visitors
- unified_visitor->FlushV8References();
-
- DCHECK_EQ(WorklistTaskId::MainThread, visitor->task_id());
+ DCHECK(v8_references_worklist_->IsGlobalEmpty() ||
+ base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking));
V8ReferencesWorklist::View v8_references(v8_references_worklist_.get(),
- WorklistTaskId::MainThread);
+ WorklistTaskId::MutatorThread);
V8Reference reference;
v8::EmbedderHeapTracer* controller =
reinterpret_cast<v8::EmbedderHeapTracer*>(
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.h b/chromium/third_party/blink/renderer/platform/heap/heap.h
index e4993326b10..e5a7316a7d0 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.h
@@ -36,10 +36,12 @@
#include "base/macros.h"
#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/heap/finalizer_traits.h"
#include "third_party/blink/renderer/platform/heap/gc_info.h"
#include "third_party/blink/renderer/platform/heap/heap_page.h"
#include "third_party/blink/renderer/platform/heap/process_heap.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/heap/thread_state_statistics.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/heap/worklist.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -55,6 +57,7 @@ class IncrementalMarkingScopeBase;
} // namespace incremental_marking_test
class AddressCache;
+class ConcurrentMarkingVisitor;
class ThreadHeapStatsCollector;
class PagePool;
class ProcessHeapReporter;
@@ -172,6 +175,14 @@ class ObjectAliveTrait<T, true> {
}
};
+template <typename T, typename = int>
+struct IsGarbageCollectedContainer : std::false_type {};
+
+template <typename T>
+struct IsGarbageCollectedContainer<
+ T,
+ typename T::IsGarbageCollectedCollectionTypeMarker> : std::true_type {};
+
} // namespace internal
class PLATFORM_EXPORT ThreadHeap {
@@ -282,6 +293,9 @@ class PLATFORM_EXPORT ThreadHeap {
bool AdvanceMarking(MarkingVisitor*, base::TimeTicks deadline);
void VerifyMarking();
+ // Returns true if marker is done
+ bool AdvanceConcurrentMarking(ConcurrentMarkingVisitor*, base::TimeTicks);
+
// Conservatively checks whether an address is a pointer in any of the
// thread heaps. If so marks the object pointed to as live.
Address CheckAndMarkPointer(MarkingVisitor*, Address);
@@ -372,17 +386,15 @@ class PLATFORM_EXPORT ThreadHeap {
void Compact();
- bool AdvanceLazySweep(base::TimeTicks deadline);
-
- void ConcurrentSweep();
+ enum class SweepingType : uint8_t { kMutator, kConcurrent };
+ bool AdvanceSweep(SweepingType sweeping_type, base::TimeTicks deadline);
void PrepareForSweep();
void RemoveAllPages();
void InvokeFinalizersOnSweptPages();
void CompleteSweep();
- enum SnapshotType { kHeapSnapshot, kFreelistSnapshot };
- void TakeSnapshot(SnapshotType);
+ void CollectStatistics(ThreadState::Statistics* statistics);
ThreadHeapStatsCollector* stats_collector() const {
return heap_stats_collector_.get();
@@ -412,7 +424,7 @@ class PLATFORM_EXPORT ThreadHeap {
void InvokeEphemeronCallbacks(MarkingVisitor*);
- void FlushV8References(MarkingVisitor*);
+ void FlushV8References();
ThreadState* thread_state_;
std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_;
@@ -533,6 +545,13 @@ template <typename T, typename... Args>
T* MakeGarbageCollected(Args&&... args) {
static_assert(WTF::IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
+ static_assert(std::is_trivially_destructible<T>::value ||
+ std::has_virtual_destructor<T>::value ||
+ std::is_final<T>::value ||
+ internal::IsGarbageCollectedContainer<T>::value ||
+ internal::HasFinalizeGarbageCollectedObject<T>::value,
+ "Finalized GarbageCollected class should either have a virtual "
+ "destructor or be marked as final.");
void* memory = T::AllocateObject(sizeof(T));
HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
// Placement new as regular operator new() is deleted.
@@ -553,6 +572,13 @@ template <typename T, typename... Args>
T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) {
static_assert(WTF::IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
+ static_assert(std::is_trivially_destructible<T>::value ||
+ std::has_virtual_destructor<T>::value ||
+ std::is_final<T>::value ||
+ internal::IsGarbageCollectedContainer<T>::value ||
+ internal::HasFinalizeGarbageCollectedObject<T>::value,
+ "Finalized GarbageCollected class should either have a virtual "
+ "destructor or be marked as final.");
void* memory = T::AllocateObject(sizeof(T) + additional_bytes.value);
HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
// Placement new as regular operator new() is deleted.
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.cc b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.cc
index 74bdb074eae..034f753ddc2 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.cc
@@ -97,7 +97,8 @@ bool HeapAllocator::BackingExpand(void* address, size_t new_size) {
bool succeed = arena->ExpandObject(header, new_size);
if (succeed) {
state->Heap().AllocationPointAdjusted(arena->ArenaIndex());
- if (header->IsMarked() && state->IsMarkingInProgress()) {
+ if (header->IsMarked<HeapObjectHeader::AccessMode::kAtomic>() &&
+ state->IsMarkingInProgress()) {
state->CurrentVisitor()->AdjustMarkedBytes(header, old_size);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
index d9461ff361f..351f61fe604 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -491,10 +491,12 @@ class HeapHashMap : public HashMap<KeyArg,
KeyTraitsArg,
MappedTraitsArg,
HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
+ static_assert(std::is_trivially_destructible<HeapHashMap>::value,
+ "HeapHashMap must be trivially destructible.");
static_assert(
IsAllowedInContainer<KeyArg>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
@@ -504,7 +506,7 @@ class HeapHashMap : public HashMap<KeyArg,
static_assert(
WTF::IsTraceable<KeyArg>::value || WTF::IsTraceable<MappedArg>::value,
"For hash maps without traceable elements, use HashMap<> "
- "instead of HeapHashMap<>");
+ "instead of HeapHashMap<>.");
}
public:
@@ -522,16 +524,18 @@ template <typename ValueArg,
typename TraitsArg = HashTraits<ValueArg>>
class HeapHashSet
: public HashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
+ static_assert(std::is_trivially_destructible<HeapHashSet>::value,
+ "HeapHashSet must be trivially destructible.");
static_assert(
IsAllowedInContainer<ValueArg>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<ValueArg>::value,
"For hash sets without traceable elements, use HashSet<> "
- "instead of HeapHashSet<>");
+ "instead of HeapHashSet<>.");
}
public:
@@ -548,7 +552,7 @@ template <typename ValueArg,
typename TraitsArg = HashTraits<ValueArg>>
class HeapLinkedHashSet
: public LinkedHashSet<ValueArg, HashArg, TraitsArg, HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
// HeapLinkedHashSet is using custom callbacks for compaction that rely on the
// fact that the container itself does not move.
@@ -560,7 +564,7 @@ class HeapLinkedHashSet
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<ValueArg>::value,
"For sets without traceable elements, use LinkedHashSet<> "
- "instead of HeapLinkedHashSet<>");
+ "instead of HeapLinkedHashSet<>.");
}
public:
@@ -582,16 +586,18 @@ class HeapListHashSet
inlineCapacity,
HashArg,
HeapListHashSetAllocator<ValueArg, inlineCapacity>> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
+ static_assert(std::is_trivially_destructible<HeapListHashSet>::value,
+ "HeapListHashSet must be trivially destructible.");
static_assert(
IsAllowedInContainer<ValueArg>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<ValueArg>::value,
"For sets without traceable elements, use ListHashSet<> "
- "instead of HeapListHashSet<>");
+ "instead of HeapListHashSet<>.");
}
public:
@@ -608,16 +614,18 @@ template <typename Value,
typename Traits = HashTraits<Value>>
class HeapHashCountedSet
: public HashCountedSet<Value, HashFunctions, Traits, HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
+ static_assert(std::is_trivially_destructible<HeapHashCountedSet>::value,
+ "HeapHashCountedSet must be trivially destructible.");
static_assert(
IsAllowedInContainer<Value>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<Value>::value,
"For counted sets without traceable elements, use "
- "HashCountedSet<> instead of HeapHashCountedSet<>");
+ "HashCountedSet<> instead of HeapHashCountedSet<>.");
}
public:
@@ -631,16 +639,19 @@ class HeapHashCountedSet
template <typename T, wtf_size_t inlineCapacity = 0>
class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
static_assert(
+ std::is_trivially_destructible<HeapVector>::value || inlineCapacity,
+ "HeapVector must be trivially destructible.");
+ static_assert(
IsAllowedInContainer<T>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<T>::value,
"For vectors without traceable elements, use Vector<> "
- "instead of HeapVector<>");
+ "instead of HeapVector<>.");
}
public:
@@ -679,11 +690,14 @@ class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
template <typename T, wtf_size_t inlineCapacity = 0>
class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
- IS_GARBAGE_COLLECTED_TYPE();
+ IS_GARBAGE_COLLECTED_CONTAINER_TYPE();
DISALLOW_NEW();
static void CheckType() {
static_assert(
+ std::is_trivially_destructible<HeapDeque>::value || inlineCapacity,
+ "HeapDeque must be trivially destructible.");
+ static_assert(
IsAllowedInContainer<T>::value,
"Not allowed to directly nest type. Use Member<> indirection instead.");
static_assert(WTF::IsTraceable<T>::value,
@@ -698,7 +712,7 @@ class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
// VectorTraits<T>::kNeedsDestruction case for now.
static_assert(inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
"on-heap HeapDeque<> should not have an inline capacity");
- return ThreadHeap::Allocate<HeapVector<T, inlineCapacity>>(size);
+ return ThreadHeap::Allocate<HeapDeque<T, inlineCapacity>>(size);
}
HeapDeque() { CheckType(); }
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
index 6b2cbfc2e99..2b210308f4d 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -282,7 +282,7 @@ void HeapCompact::MovableObjectFixups::RelocateInteriorFixups(Address from,
void HeapCompact::MovableObjectFixups::UpdateCallbacks() {
BackingStoreCallbackWorklist::View backing_store_callbacks(
- heap_->GetBackingStoreCallbackWorklist(), WorklistTaskId::MainThread);
+ heap_->GetBackingStoreCallbackWorklist(), WorklistTaskId::MutatorThread);
BackingStoreCallbackItem item;
while (backing_store_callbacks.Pop(&item)) {
fixup_callbacks_.insert(item.backing, item.callback);
@@ -341,7 +341,6 @@ HeapCompact::MovableObjectFixups& HeapCompact::Fixups() {
bool HeapCompact::ShouldCompact(BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::GCReason reason) {
- DCHECK_NE(BlinkGC::MarkingType::kTakeSnapshot, marking_type);
if (marking_type == BlinkGC::MarkingType::kAtomicMarking &&
stack_state == BlinkGC::StackState::kHeapPointersOnStack) {
// The following check ensures that tests that want to test compaction are
@@ -448,7 +447,7 @@ void HeapCompact::FilterNonLiveSlots() {
last_fixup_count_for_testing_ = 0;
MovableReferenceWorklist::View traced_slots(
- heap_->GetMovableReferenceWorklist(), WorklistTaskId::MainThread);
+ heap_->GetMovableReferenceWorklist(), WorklistTaskId::MutatorThread);
MovableReference* slot;
while (traced_slots.Pop(&slot)) {
if (*slot) {
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
index 0d2ab962fce..e2eef4b7e05 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact_test.cc
@@ -23,7 +23,7 @@ enum VerifyArenaCompaction {
HashTablesAreCompacted,
};
-class IntWrapper : public blink::GarbageCollectedFinalized<IntWrapper> {
+class IntWrapper : public blink::GarbageCollected<IntWrapper> {
public:
static bool did_verify_at_least_once;
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
index c2c1430e692..48fa884bee4 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -133,31 +133,34 @@ void BaseArena::RemoveAllPages() {
}
}
-void BaseArena::TakeSnapshot(const String& dump_base_name,
- ThreadState::GCSnapshotInfo& info) {
- // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName"
- base::trace_event::MemoryAllocatorDump* allocator_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(dump_base_name);
- size_t page_count = 0;
- BasePage::HeapSnapshotInfo heap_info;
- for (BasePage* page : unswept_pages_) {
- String dump_name =
- dump_base_name + String::Format("/pages/page_%zu", page_count++);
- base::trace_event::MemoryAllocatorDump* page_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(dump_name);
+void BaseArena::CollectStatistics(std::string name,
+ ThreadState::Statistics* stats) {
+ ThreadState::Statistics::ArenaStatistics arena_stats;
+
+ ResetAllocationPoint();
- page->TakeSnapshot(page_dump, info, heap_info);
+ if (!NameClient::HideInternalName()) {
+ size_t num_types = GCInfoTable::Get().GcInfoIndex() + 1;
+ arena_stats.object_stats.num_types = num_types;
+ arena_stats.object_stats.type_name.resize(num_types);
+ arena_stats.object_stats.type_count.resize(num_types);
+ arena_stats.object_stats.type_bytes.resize(num_types);
}
- allocator_dump->AddScalar("blink_page_count", "objects", page_count);
- // When taking a full dump (w/ freelist), both the /buckets and /pages
- // report their free size but they are not meant to be added together.
- // Therefore, here we override the free_size of the parent heap to be
- // equal to the free_size of the sum of its heap pages.
- allocator_dump->AddScalar("free_size", "bytes", heap_info.free_size);
- allocator_dump->AddScalar("free_count", "objects", heap_info.free_count);
+ arena_stats.name = std::move(name);
+ DCHECK(unswept_pages_.IsEmpty());
+ for (BasePage* page : swept_pages_) {
+ page->CollectStatistics(&arena_stats);
+ }
+ CollectFreeListStatistics(&arena_stats.free_list_stats);
+ stats->used_size_bytes += arena_stats.used_size_bytes;
+ stats->committed_size_bytes += arena_stats.committed_size_bytes;
+ stats->arena_stats.emplace_back(std::move(arena_stats));
+}
+
+void NormalPageArena::CollectFreeListStatistics(
+ ThreadState::Statistics::FreeListStatistics* stats) {
+ free_list_.CollectStatistics(stats);
}
#if DCHECK_IS_ON()
@@ -309,13 +312,13 @@ bool BaseArena::LazySweepWithDeadline(base::TimeTicks deadline) {
// Platform::current()->monotonicallyIncreasingTimeSeconds() per page (i.e.,
// 128 KB sweep or one LargeObject sweep), so we check the deadline per 10
// pages.
- static const int kDeadlineCheckInterval = 10;
+ static constexpr size_t kDeadlineCheckInterval = 10;
CHECK(GetThreadState()->IsSweepingInProgress());
DCHECK(GetThreadState()->SweepForbidden());
DCHECK(ScriptForbiddenScope::IsScriptForbidden());
- int page_count = 1;
+ size_t page_count = 1;
// TODO(bikineev): We should probably process pages in the reverse order. This
// will leave more work for concurrent sweeper and reduce memory footprint
// faster.
@@ -367,10 +370,18 @@ void BaseArena::InvokeFinalizersOnSweptPages() {
}
}
-void BaseArena::SweepOnConcurrentThread() {
+bool BaseArena::ConcurrentSweepWithDeadline(base::TimeTicks deadline) {
+ static constexpr size_t kDeadlineCheckInterval = 10;
+ size_t page_count = 1;
while (BasePage* page = unswept_pages_.PopLocked()) {
SweepUnsweptPageOnConcurrentThread(page);
+ if (page_count % kDeadlineCheckInterval == 0 &&
+ deadline <= base::TimeTicks::Now()) {
+ return SweepingCompleted();
+ }
+ ++page_count;
}
+ return true;
}
void BaseArena::CompleteSweep() {
@@ -627,20 +638,6 @@ bool NormalPageArena::PagesToBeSweptContains(Address address) {
}
#endif
-void NormalPageArena::TakeFreelistSnapshot(const String& dump_name) {
- if (free_list_.TakeSnapshot(dump_name)) {
- base::trace_event::MemoryAllocatorDump* buckets_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(dump_name + "/buckets");
- base::trace_event::MemoryAllocatorDump* pages_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(dump_name + "/pages");
- BlinkGCMemoryDumpProvider::Instance()
- ->CurrentProcessMemoryDump()
- ->AddOwnershipEdge(pages_dump->guid(), buckets_dump->guid());
- }
-}
-
void NormalPageArena::AllocatePage() {
GetThreadState()->Heap().address_cache()->MarkDirty();
PageMemory* page_memory =
@@ -735,10 +732,7 @@ void NormalPageArena::PromptlyFreeObject(HeapObjectHeader* header) {
->ClearBit(address);
return;
}
- // The object may be on a page that has not been swept yet and requires
- // manual unmarking.
- if (header->IsMarked())
- header->Unmark();
+ DCHECK(!header->IsMarked());
PromptlyFreeObjectInFreeList(header, size);
}
}
@@ -1130,7 +1124,9 @@ void FreeList::Add(Address address, size_t size) {
}
void FreeList::MoveFrom(FreeList* other) {
+#if DCHECK_IS_ON()
const size_t expected_size = FreeListSize() + other->FreeListSize();
+#endif
// Newly created entries get added to the head.
for (size_t index = 0; index < kBlinkPageSizeLog2; ++index) {
@@ -1151,7 +1147,9 @@ void FreeList::MoveFrom(FreeList* other) {
std::max(biggest_free_list_index_, other->biggest_free_list_index_);
other->biggest_free_list_index_ = 0;
+#if DCHECK_IS_ON()
DCHECK_EQ(expected_size, FreeListSize());
+#endif
DCHECK(other->IsEmpty());
}
@@ -1284,41 +1282,41 @@ int FreeList::BucketIndexForSize(size_t size) {
return index;
}
-bool FreeList::TakeSnapshot(const String& dump_base_name) {
- bool did_dump_bucket_stats = false;
+void FreeList::CollectStatistics(
+ ThreadState::Statistics::FreeListStatistics* stats) {
+ Vector<size_t> bucket_size;
+ Vector<size_t> free_count;
+ Vector<size_t> free_size;
for (size_t i = 0; i < kBlinkPageSizeLog2; ++i) {
size_t entry_count = 0;
- size_t free_size = 0;
+ size_t entry_size = 0;
for (FreeListEntry* entry = free_list_heads_[i]; entry;
entry = entry->Next()) {
++entry_count;
- free_size += entry->size();
+ entry_size += entry->size();
}
-
- String dump_name =
- dump_base_name + "/buckets/bucket_" + String::Number(1 << i);
- base::trace_event::MemoryAllocatorDump* bucket_dump =
- BlinkGCMemoryDumpProvider::Instance()
- ->CreateMemoryAllocatorDumpForCurrentGC(dump_name);
- bucket_dump->AddScalar("free_count", "objects", entry_count);
- bucket_dump->AddScalar("free_size", "bytes", free_size);
- did_dump_bucket_stats = true;
+ bucket_size.push_back(1 << i);
+ free_count.push_back(entry_count);
+ free_size.push_back(entry_size);
}
- return did_dump_bucket_stats;
+ *stats = {std::move(bucket_size), std::move(free_count),
+ std::move(free_size)};
}
-BasePage::BasePage(PageMemory* storage, BaseArena* arena)
+BasePage::BasePage(PageMemory* storage, BaseArena* arena, PageType page_type)
: magic_(GetMagic()),
storage_(storage),
arena_(arena),
- swept_(true) {
+ thread_state_(arena->GetThreadState()),
+ page_type_(page_type) {
#if DCHECK_IS_ON()
DCHECK(IsPageHeaderAddress(reinterpret_cast<Address>(this)));
#endif
}
NormalPage::NormalPage(PageMemory* storage, BaseArena* arena)
- : BasePage(storage, arena), object_start_bit_map_(Payload()) {
+ : BasePage(storage, arena, PageType::kNormalPage),
+ object_start_bit_map_(Payload()) {
#if DCHECK_IS_ON()
DCHECK(IsPageHeaderAddress(reinterpret_cast<Address>(this)));
#endif // DCHECK_IS_ON()
@@ -1718,7 +1716,8 @@ Address ObjectStartBitmap::FindHeader(
return object_offset + offset_;
}
-HeapObjectHeader* NormalPage::FindHeaderFromAddress(Address address) {
+HeapObjectHeader* NormalPage::ConservativelyFindHeaderFromAddress(
+ Address address) {
if (!ContainedInObjectPayload(address))
return nullptr;
if (ArenaForNormalPage()->IsInCurrentAllocationPointRegion(address))
@@ -1733,47 +1732,43 @@ HeapObjectHeader* NormalPage::FindHeaderFromAddress(Address address) {
return header;
}
-void NormalPage::TakeSnapshot(base::trace_event::MemoryAllocatorDump* page_dump,
- ThreadState::GCSnapshotInfo& info,
- HeapSnapshotInfo& heap_info) {
+HeapObjectHeader* NormalPage::FindHeaderFromAddress(Address address) {
+ DCHECK(ContainedInObjectPayload(address));
+ DCHECK(!ArenaForNormalPage()->IsInCurrentAllocationPointRegion(address));
+ HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(
+ object_start_bit_map()->FindHeader(address));
+ DCHECK(header->IsValid());
+ DCHECK_LT(0u, header->GcInfoIndex());
+ DCHECK_GT(header->PayloadEnd(), address);
+ return header;
+}
+
+void NormalPage::CollectStatistics(
+ ThreadState::Statistics::ArenaStatistics* arena_stats) {
HeapObjectHeader* header = nullptr;
- size_t live_count = 0;
- size_t dead_count = 0;
- size_t free_count = 0;
size_t live_size = 0;
- size_t dead_size = 0;
- size_t free_size = 0;
for (Address header_address = Payload(); header_address < PayloadEnd();
header_address += header->size()) {
header = reinterpret_cast<HeapObjectHeader*>(header_address);
- if (header->IsFree()) {
- free_count++;
- free_size += header->size();
- } else if (header->IsMarked()) {
- live_count++;
+ if (!header->IsFree()) {
+ // All non-free objects, dead or alive, are considered as live for the
+ // purpose of taking a snapshot.
live_size += header->size();
-
- uint32_t gc_info_index = header->GcInfoIndex();
- info.live_count[gc_info_index]++;
- info.live_size[gc_info_index] += header->size();
- } else {
- dead_count++;
- dead_size += header->size();
-
- uint32_t gc_info_index = header->GcInfoIndex();
- info.dead_count[gc_info_index]++;
- info.dead_size[gc_info_index] += header->size();
+ if (!NameClient::HideInternalName()) {
+ // Detailed names available.
+ uint32_t gc_info_index = header->GcInfoIndex();
+ arena_stats->object_stats.type_count[gc_info_index]++;
+ arena_stats->object_stats.type_bytes[gc_info_index] += header->size();
+ if (arena_stats->object_stats.type_name[gc_info_index].empty()) {
+ arena_stats->object_stats.type_name[gc_info_index] = header->Name();
+ }
+ }
}
}
-
- page_dump->AddScalar("live_count", "objects", live_count);
- page_dump->AddScalar("dead_count", "objects", dead_count);
- page_dump->AddScalar("free_count", "objects", free_count);
- page_dump->AddScalar("live_size", "bytes", live_size);
- page_dump->AddScalar("dead_size", "bytes", dead_size);
- page_dump->AddScalar("free_size", "bytes", free_size);
- heap_info.free_size += free_size;
- heap_info.free_count += free_count;
+ arena_stats->committed_size_bytes += kBlinkPageSize;
+ arena_stats->used_size_bytes += live_size;
+ arena_stats->page_stats.emplace_back(
+ ThreadState::Statistics::PageStatistics{kBlinkPageSize, live_size});
}
#if DCHECK_IS_ON()
@@ -1788,7 +1783,7 @@ bool NormalPage::Contains(Address addr) {
LargeObjectPage::LargeObjectPage(PageMemory* storage,
BaseArena* arena,
size_t object_size)
- : BasePage(storage, arena),
+ : BasePage(storage, arena, PageType::kLargeObjectPage),
object_size_(object_size)
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
,
@@ -1837,33 +1832,24 @@ void LargeObjectPage::PoisonUnmarkedObjects() {
}
#endif
-void LargeObjectPage::TakeSnapshot(
- base::trace_event::MemoryAllocatorDump* page_dump,
- ThreadState::GCSnapshotInfo& info,
- HeapSnapshotInfo&) {
- size_t live_size = 0;
- size_t dead_size = 0;
- size_t live_count = 0;
- size_t dead_count = 0;
+void LargeObjectPage::CollectStatistics(
+ ThreadState::Statistics::ArenaStatistics* arena_stats) {
HeapObjectHeader* header = ObjectHeader();
- uint32_t gc_info_index = header->GcInfoIndex();
- size_t payload_size = header->PayloadSize();
- if (header->IsMarked()) {
- live_count = 1;
- live_size += payload_size;
- info.live_count[gc_info_index]++;
- info.live_size[gc_info_index] += payload_size;
- } else {
- dead_count = 1;
- dead_size += payload_size;
- info.dead_count[gc_info_index]++;
- info.dead_size[gc_info_index] += payload_size;
- }
-
- page_dump->AddScalar("live_count", "objects", live_count);
- page_dump->AddScalar("dead_count", "objects", dead_count);
- page_dump->AddScalar("live_size", "bytes", live_size);
- page_dump->AddScalar("dead_size", "bytes", dead_size);
+ size_t live_size = 0;
+ // All non-free objects, dead or alive, are considered as live for the
+ // purpose of taking a snapshot.
+ live_size += ObjectSize();
+ if (!NameClient::HideInternalName()) {
+ // Detailed names available.
+ uint32_t gc_info_index = header->GcInfoIndex();
+ arena_stats->object_stats.type_count[gc_info_index]++;
+ arena_stats->object_stats.type_bytes[gc_info_index] += ObjectSize();
+ }
+
+ arena_stats->committed_size_bytes += size();
+ arena_stats->used_size_bytes += live_size;
+ arena_stats->page_stats.emplace_back(
+ ThreadState::Statistics::PageStatistics{size(), live_size});
}
#if DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.h b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
index d5e9da49a80..733b97bd7ef 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/heap/gc_info.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/heap/thread_state_statistics.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -50,12 +51,6 @@
#include "third_party/blink/renderer/platform/wtf/sanitizers.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
-namespace base {
-namespace trace_event {
-class MemoryAllocatorDump;
-} // namespace trace_event
-} // namespace base
-
namespace blink {
// TODO(palmer): Document the reason for 17.
@@ -400,8 +395,7 @@ class FreeList {
bool IsEmpty() const;
size_t FreeListSize() const;
- // Returns true if the freelist snapshot is captured.
- bool TakeSnapshot(const String& dump_base_name);
+ void CollectStatistics(ThreadState::Statistics::FreeListStatistics*);
template <typename Predicate>
FreeListEntry* FindEntry(Predicate pred) {
@@ -477,6 +471,10 @@ enum class FinalizeType : uint8_t { kInlined, kDeferred };
// |SweepResult| indicates if page turned out to be empty after sweeping.
enum class SweepResult : uint8_t { kPageEmpty, kPageNotEmpty };
+// |PageType| indicates whether a page is used for normal objects or whether it
+// holds a large object.
+enum class PageType : uint8_t { kNormalPage, kLargeObjectPage };
+
// |BasePage| is a base class for |NormalPage| and |LargeObjectPage|.
//
// - |NormalPage| is a page whose size is |kBlinkPageSize|. A |NormalPage| can
@@ -493,7 +491,7 @@ class BasePage {
DISALLOW_NEW();
public:
- BasePage(PageMemory*, BaseArena*);
+ BasePage(PageMemory*, BaseArena*, PageType);
virtual ~BasePage() = default;
// Virtual methods are slow. So performance-sensitive methods should be
@@ -513,28 +511,21 @@ class BasePage {
virtual void PoisonUnmarkedObjects() = 0;
#endif
- class HeapSnapshotInfo {
- STACK_ALLOCATED();
-
- public:
- size_t free_count = 0;
- size_t free_size = 0;
- };
+ virtual void CollectStatistics(
+ ThreadState::Statistics::ArenaStatistics* arena_stats) = 0;
- virtual void TakeSnapshot(base::trace_event::MemoryAllocatorDump*,
- ThreadState::GCSnapshotInfo&,
- HeapSnapshotInfo&) = 0;
#if DCHECK_IS_ON()
virtual bool Contains(Address) = 0;
#endif
virtual size_t size() = 0;
- virtual bool IsLargeObjectPage() { return false; }
Address GetAddress() { return reinterpret_cast<Address>(this); }
PageMemory* Storage() const { return storage_; }
BaseArena* Arena() const { return arena_; }
+ ThreadState* thread_state() const { return thread_state_; }
- // Returns true if this page has been swept by the ongoing lazy sweep.
+ // Returns true if this page has been swept by the ongoing sweep; false
+ // otherwise.
bool HasBeenSwept() const { return swept_; }
void MarkAsSwept() {
@@ -547,6 +538,11 @@ class BasePage {
swept_ = false;
}
+ // Returns true if this page is a large object page; false otherwise.
+ bool IsLargeObjectPage() const {
+ return page_type_ == PageType::kLargeObjectPage;
+ }
+
// Returns true if magic number is valid.
bool IsValid() const;
@@ -559,10 +555,13 @@ class BasePage {
uint32_t const magic_;
PageMemory* const storage_;
BaseArena* const arena_;
+ ThreadState* const thread_state_;
// Track the sweeping state of a page. Set to false at the start of a sweep,
- // true upon completion of lazy sweeping.
- bool swept_;
+ // true upon completion of sweeping that page.
+ bool swept_ = true;
+
+ PageType page_type_;
friend class BaseArena;
};
@@ -700,9 +699,9 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
void PoisonUnmarkedObjects() override;
#endif
- void TakeSnapshot(base::trace_event::MemoryAllocatorDump*,
- ThreadState::GCSnapshotInfo&,
- HeapSnapshotInfo&) override;
+ void CollectStatistics(
+ ThreadState::Statistics::ArenaStatistics* arena_stats) override;
+
#if DCHECK_IS_ON()
// Returns true for the whole |kBlinkPageSize| page that the page is on, even
// for the header, and the unmapped guard page at the start. That ensures the
@@ -752,6 +751,11 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
// Uses the object_start_bit_map_ to find an object for a given address. The
// returned header is either nullptr, indicating that no object could be
// found, or it is pointing to valid object or free list entry.
+ HeapObjectHeader* ConservativelyFindHeaderFromAddress(Address);
+
+ // Uses the object_start_bit_map_ to find an object for a given address. It is
+ // assumed that the address points into a valid heap object. Use the
+ // conservative version if that assumption does not hold.
HeapObjectHeader* FindHeaderFromAddress(Address);
void VerifyMarking() override;
@@ -841,11 +845,8 @@ class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
void MakeConsistentForMutator() override;
void FinalizeSweep(SweepResult) override;
- void TakeSnapshot(base::trace_event::MemoryAllocatorDump*,
- ThreadState::GCSnapshotInfo&,
- HeapSnapshotInfo&) override;
-
- bool IsLargeObjectPage() override { return true; }
+ void CollectStatistics(
+ ThreadState::Statistics::ArenaStatistics* arena_stats) override;
void VerifyMarking() override;
@@ -889,11 +890,13 @@ class PLATFORM_EXPORT BaseArena {
virtual ~BaseArena();
void RemoveAllPages();
- void TakeSnapshot(const String& dump_base_name, ThreadState::GCSnapshotInfo&);
+ void CollectStatistics(std::string, ThreadState::Statistics*);
+ virtual void CollectFreeListStatistics(
+ ThreadState::Statistics::FreeListStatistics*) {}
+
#if DCHECK_IS_ON()
BasePage* FindPageFromAddress(Address);
#endif
- virtual void TakeFreelistSnapshot(const String& dump_base_name) {}
virtual void ClearFreeLists() {}
virtual void MakeIterable() {}
virtual void MakeConsistentForGC();
@@ -912,8 +915,8 @@ class PLATFORM_EXPORT BaseArena {
// Returns true if we have swept all pages within the deadline. Returns false
// otherwise.
bool LazySweepWithDeadline(base::TimeTicks deadline);
+ bool ConcurrentSweepWithDeadline(base::TimeTicks deadline);
void CompleteSweep();
- void SweepOnConcurrentThread();
void InvokeFinalizersOnSweptPages();
ThreadState* GetThreadState() { return thread_state_; }
@@ -970,13 +973,14 @@ class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
}
void AddToFreeList(FreeList* other) { free_list_.MoveFrom(other); }
void ClearFreeLists() override;
+ void CollectFreeListStatistics(
+ ThreadState::Statistics::FreeListStatistics*) override;
void MakeIterable() override;
#if DCHECK_IS_ON()
bool IsConsistentForGC() override;
bool PagesToBeSweptContains(Address);
#endif
- void TakeFreelistSnapshot(const String& dump_base_name) override;
Address AllocateObject(size_t allocation_size, size_t gc_info_index);
@@ -1073,7 +1077,7 @@ PLATFORM_EXPORT ALWAYS_INLINE BasePage* PageFromObject(const void* object) {
BasePage* page = reinterpret_cast<BasePage*>(BlinkPageAddress(address) +
kBlinkGuardPageSize);
// Page must have a valid magic.
- DCHECK(page->IsValid());
+ CHECK(page->IsValid());
#if DCHECK_IS_ON()
DCHECK(page->Contains(address));
#endif
@@ -1129,7 +1133,7 @@ NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsInConstruction() const {
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline void HeapObjectHeader::MarkFullyConstructed() {
- DCHECK(IsInConstruction());
+ DCHECK(IsInConstruction<mode>());
StoreEncoded<mode, EncodedHalf::kHigh>(kHeaderIsInConstructionMask,
kHeaderIsInConstructionMask);
}
@@ -1195,7 +1199,7 @@ NO_SANITIZE_ADDRESS inline void HeapObjectHeader::Mark() {
template <HeapObjectHeader::AccessMode mode>
NO_SANITIZE_ADDRESS inline void HeapObjectHeader::Unmark() {
CheckHeader();
- DCHECK(IsMarked());
+ DCHECK(IsMarked<mode>());
StoreEncoded<mode, EncodedHalf::kLow>(0u, kHeaderMarkBitMask);
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
index 7b79d56eeda..54b950c1874 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -70,7 +70,7 @@ namespace {
class HeapTest : public TestSupportingGC {};
-class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
+class IntWrapper : public GarbageCollected<IntWrapper> {
public:
virtual ~IntWrapper() {
destructor_calls_.fetch_add(1, std::memory_order_relaxed);
@@ -145,7 +145,7 @@ class KeyWithCopyingMoveConstructor final {
}
KeyWithCopyingMoveConstructor(const KeyWithCopyingMoveConstructor&) = default;
// The move constructor delegates to the copy constructor intentionally.
- KeyWithCopyingMoveConstructor(KeyWithCopyingMoveConstructor&& x) noexcept
+ KeyWithCopyingMoveConstructor(KeyWithCopyingMoveConstructor&& x)
: KeyWithCopyingMoveConstructor(x) {}
KeyWithCopyingMoveConstructor& operator=(
const KeyWithCopyingMoveConstructor&) = default;
@@ -415,8 +415,7 @@ class SimpleObject : public GarbageCollected<SimpleObject> {
char payload[64];
};
-class HeapTestSuperClass
- : public GarbageCollectedFinalized<HeapTestSuperClass> {
+class HeapTestSuperClass : public GarbageCollected<HeapTestSuperClass> {
public:
HeapTestSuperClass() = default;
virtual ~HeapTestSuperClass() { ++destructor_calls_; }
@@ -605,11 +604,6 @@ class ThreadedHeapTester : public ThreadedTesterBase {
gc_count_.fetch_add(1, std::memory_order_release);
}
- // Taking snapshot shouldn't have any bad side effect.
- // TODO(haraken): This snapshot GC causes crashes, so disable
- // it at the moment. Fix the crash and enable it.
- // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack,
- // BlinkGC::TakeSnapshot, BlinkGC::ForcedGC);
TestSupportingGC::PreciselyCollectGarbage();
EXPECT_EQ(wrapper->Value(), 0x0bbac0de);
EXPECT_EQ((*global_persistent)->Value(), 0x0ed0cabb);
@@ -644,11 +638,6 @@ class ThreadedWeaknessTester : public ThreadedTesterBase {
gc_count_.fetch_add(1, std::memory_order_release);
}
- // Taking snapshot shouldn't have any bad side effect.
- // TODO(haraken): This snapshot GC causes crashes, so disable
- // it at the moment. Fix the crash and enable it.
- // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack,
- // BlinkGC::TakeSnapshot, BlinkGC::ForcedGC);
TestSupportingGC::PreciselyCollectGarbage();
EXPECT_TRUE(weak_map->IsEmpty());
}
@@ -690,7 +679,7 @@ class ThreadPersistentHeapTester : public ThreadedTesterBase {
Persistent<PersistentChain> persistent_chain_;
};
- class PersistentChain : public GarbageCollectedFinalized<PersistentChain> {
+ class PersistentChain final : public GarbageCollected<PersistentChain> {
public:
explicit PersistentChain(int count) {
ref_counted_chain_ = base::AdoptRef(RefCountedChain::Create(count));
@@ -721,7 +710,7 @@ void CheckWithSlack(T expected, T actual, int slack) {
EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
}
-class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
+class TraceCounter final : public GarbageCollected<TraceCounter> {
public:
TraceCounter() : trace_count_(0) {}
@@ -755,8 +744,8 @@ class ClassWithMember : public GarbageCollected<ClassWithMember> {
Member<TraceCounter> trace_counter_;
};
-class SimpleFinalizedObject
- : public GarbageCollectedFinalized<SimpleFinalizedObject> {
+class SimpleFinalizedObject final
+ : public GarbageCollected<SimpleFinalizedObject> {
public:
SimpleFinalizedObject() = default;
~SimpleFinalizedObject() { ++destructor_calls_; }
@@ -798,7 +787,7 @@ class IntNode : public GarbageCollected<IntNode> {
int value_;
};
-class Bar : public GarbageCollectedFinalized<Bar> {
+class Bar : public GarbageCollected<Bar> {
public:
Bar() : magic_(kMagic) { live_++; }
@@ -887,7 +876,7 @@ class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
Member<IntWrapper> int_wrapper_;
};
-class LargeHeapObject : public GarbageCollectedFinalized<LargeHeapObject> {
+class LargeHeapObject final : public GarbageCollected<LargeHeapObject> {
public:
LargeHeapObject() { int_wrapper_ = MakeGarbageCollected<IntWrapper>(23); }
~LargeHeapObject() { destructor_calls_++; }
@@ -917,8 +906,8 @@ int LargeHeapObject::destructor_calls_ = 0;
// "keep alive" persistent reference that is set & cleared across
// ref-counting operations.
//
-class RefCountedAndGarbageCollected
- : public GarbageCollectedFinalized<RefCountedAndGarbageCollected> {
+class RefCountedAndGarbageCollected final
+ : public GarbageCollected<RefCountedAndGarbageCollected> {
public:
RefCountedAndGarbageCollected() : keep_alive_(PERSISTENT_FROM_HERE) {}
~RefCountedAndGarbageCollected() { ++destructor_calls_; }
@@ -951,9 +940,9 @@ class RefCountedAndGarbageCollected
int RefCountedAndGarbageCollected::destructor_calls_ = 0;
-class RefCountedAndGarbageCollected2
+class RefCountedAndGarbageCollected2 final
: public HeapTestOtherSuperClass,
- public GarbageCollectedFinalized<RefCountedAndGarbageCollected2> {
+ public GarbageCollected<RefCountedAndGarbageCollected2> {
public:
RefCountedAndGarbageCollected2() : keep_alive_(PERSISTENT_FROM_HERE) {}
~RefCountedAndGarbageCollected2() { ++destructor_calls_; }
@@ -1027,7 +1016,7 @@ class WithWeakMember : public Bar {
WeakMember<Bar> weak_bar_;
};
-class Observable : public GarbageCollectedFinalized<Observable> {
+class Observable final : public GarbageCollected<Observable> {
USING_PRE_FINALIZER(Observable, WillFinalize);
public:
@@ -1051,8 +1040,8 @@ class Observable : public GarbageCollectedFinalized<Observable> {
bool Observable::will_finalize_was_called_ = false;
-class ObservableWithPreFinalizer
- : public GarbageCollectedFinalized<ObservableWithPreFinalizer> {
+class ObservableWithPreFinalizer final
+ : public GarbageCollected<ObservableWithPreFinalizer> {
USING_PRE_FINALIZER(ObservableWithPreFinalizer, Dispose);
public:
@@ -1075,7 +1064,7 @@ bool g_dispose_was_called_for_pre_finalizer_base = false;
bool g_dispose_was_called_for_pre_finalizer_mixin = false;
bool g_dispose_was_called_for_pre_finalizer_sub_class = false;
-class PreFinalizerBase : public GarbageCollectedFinalized<PreFinalizerBase> {
+class PreFinalizerBase : public GarbageCollected<PreFinalizerBase> {
USING_PRE_FINALIZER(PreFinalizerBase, Dispose);
public:
@@ -1210,7 +1199,7 @@ Persistent<FinalizationObserverWithHashMap::ObserverMap>*
class SuperClass;
-class PointsBack : public GarbageCollectedFinalized<PointsBack> {
+class PointsBack final : public GarbageCollected<PointsBack> {
public:
PointsBack() : back_pointer_(nullptr) { ++alive_count_; }
~PointsBack() { --alive_count_; }
@@ -1231,7 +1220,7 @@ class PointsBack : public GarbageCollectedFinalized<PointsBack> {
int PointsBack::alive_count_ = 0;
-class SuperClass : public GarbageCollectedFinalized<SuperClass> {
+class SuperClass : public GarbageCollected<SuperClass> {
public:
explicit SuperClass(PointsBack* points_back) : points_back_(points_back) {
points_back_->SetBackPointer(this);
@@ -1258,7 +1247,7 @@ class SuperClass : public GarbageCollectedFinalized<SuperClass> {
};
int SuperClass::alive_count_ = 0;
-class SubData : public GarbageCollectedFinalized<SubData> {
+class SubData final : public GarbageCollected<SubData> {
public:
SubData() { ++alive_count_; }
~SubData() { --alive_count_; }
@@ -1377,7 +1366,7 @@ WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace)
namespace blink {
-class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
+class OneKiloByteObject final : public GarbageCollected<OneKiloByteObject> {
public:
~OneKiloByteObject() { destructor_calls_++; }
char* Data() { return data_; }
@@ -1408,8 +1397,8 @@ class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
DynamicallySizedObject() = default;
};
-class FinalizationAllocator
- : public GarbageCollectedFinalized<FinalizationAllocator> {
+class FinalizationAllocator final
+ : public GarbageCollected<FinalizationAllocator> {
public:
FinalizationAllocator(Persistent<IntWrapper>* wrapper) : wrapper_(wrapper) {}
@@ -1428,8 +1417,8 @@ class FinalizationAllocator
Persistent<IntWrapper>* wrapper_;
};
-class PreFinalizerBackingShrinkForbidden
- : public GarbageCollectedFinalized<PreFinalizerBackingShrinkForbidden> {
+class PreFinalizerBackingShrinkForbidden final
+ : public GarbageCollected<PreFinalizerBackingShrinkForbidden> {
USING_PRE_FINALIZER(PreFinalizerBackingShrinkForbidden, Dispose);
public:
@@ -1485,9 +1474,8 @@ TEST_F(HeapTest, PreFinalizerBackingShrinkForbidden) {
PreciselyCollectGarbage();
}
-class PreFinalizerVectorBackingExpandForbidden
- : public GarbageCollectedFinalized<
- PreFinalizerVectorBackingExpandForbidden> {
+class PreFinalizerVectorBackingExpandForbidden final
+ : public GarbageCollected<PreFinalizerVectorBackingExpandForbidden> {
USING_PRE_FINALIZER(PreFinalizerVectorBackingExpandForbidden, Dispose);
public:
@@ -1515,9 +1503,8 @@ TEST(HeapDeathTest, PreFinalizerVectorBackingExpandForbidden) {
TestSupportingGC::PreciselyCollectGarbage();
}
-class PreFinalizerHashTableBackingExpandForbidden
- : public GarbageCollectedFinalized<
- PreFinalizerHashTableBackingExpandForbidden> {
+class PreFinalizerHashTableBackingExpandForbidden final
+ : public GarbageCollected<PreFinalizerHashTableBackingExpandForbidden> {
USING_PRE_FINALIZER(PreFinalizerHashTableBackingExpandForbidden, Dispose);
public:
@@ -1547,7 +1534,7 @@ TEST(HeapDeathTest, PreFinalizerHashTableBackingExpandForbidden) {
#endif // DCHECK_IS_ON()
class PreFinalizerAllocationForbidden
- : public GarbageCollectedFinalized<PreFinalizerAllocationForbidden> {
+ : public GarbageCollected<PreFinalizerAllocationForbidden> {
USING_PRE_FINALIZER(PreFinalizerAllocationForbidden, Dispose);
public:
@@ -2369,7 +2356,7 @@ typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak;
typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
typedef std::pair<int, WeakMember<IntWrapper>> PairUnwrappedWeak;
-class Container : public GarbageCollected<Container> {
+class Container final : public GarbageCollected<Container> {
public:
HeapHashMap<Member<IntWrapper>, Member<IntWrapper>> map;
HeapHashSet<Member<IntWrapper>> set;
@@ -4282,7 +4269,7 @@ WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::InlinedVectorObject)
namespace blink {
class InlinedVectorObjectWrapper final
- : public GarbageCollectedFinalized<InlinedVectorObjectWrapper> {
+ : public GarbageCollected<InlinedVectorObjectWrapper> {
public:
InlinedVectorObjectWrapper() {
InlinedVectorObject i1, i2;
@@ -4307,7 +4294,7 @@ class InlinedVectorObjectWrapper final
};
class InlinedVectorObjectWithVtableWrapper final
- : public GarbageCollectedFinalized<InlinedVectorObjectWithVtableWrapper> {
+ : public GarbageCollected<InlinedVectorObjectWithVtableWrapper> {
public:
InlinedVectorObjectWithVtableWrapper() {
InlinedVectorObjectWithVtable i1, i2;
@@ -5318,8 +5305,8 @@ static bool AllocateAndReturnBool() {
}
template <typename T>
-class TraceIfNeededTester
- : public GarbageCollectedFinalized<TraceIfNeededTester<T>> {
+class TraceIfNeededTester final
+ : public GarbageCollected<TraceIfNeededTester<T>> {
public:
TraceIfNeededTester() = default;
explicit TraceIfNeededTester(const T& obj) : obj_(obj) {}
@@ -5465,7 +5452,7 @@ TEST_F(HeapTest, PartObjectWithVirtualMethod) {
}
class AllocInSuperConstructorArgumentSuper
- : public GarbageCollectedFinalized<AllocInSuperConstructorArgumentSuper> {
+ : public GarbageCollected<AllocInSuperConstructorArgumentSuper> {
public:
AllocInSuperConstructorArgumentSuper(bool value) : value_(value) {}
virtual ~AllocInSuperConstructorArgumentSuper() = default;
@@ -5492,8 +5479,8 @@ TEST_F(HeapTest, AllocationInSuperConstructorArgument) {
ThreadState::Current()->CollectAllGarbageForTesting();
}
-class NonNodeAllocatingNodeInDestructor
- : public GarbageCollectedFinalized<NonNodeAllocatingNodeInDestructor> {
+class NonNodeAllocatingNodeInDestructor final
+ : public GarbageCollected<NonNodeAllocatingNodeInDestructor> {
public:
~NonNodeAllocatingNodeInDestructor() {
node_ = new Persistent<IntNode>(IntNode::Create(10));
@@ -5853,8 +5840,7 @@ class ThreadedClearOnShutdownTester : public ThreadedTesterBase {
};
class ThreadedClearOnShutdownTester::HeapObject final
- : public GarbageCollectedFinalized<
- ThreadedClearOnShutdownTester::HeapObject> {
+ : public GarbageCollected<ThreadedClearOnShutdownTester::HeapObject> {
public:
explicit HeapObject(bool test_destructor)
: test_destructor_(test_destructor) {}
@@ -5957,7 +5943,7 @@ TEST_F(HeapTest, IsGarbageCollected) {
static_assert(WTF::IsGarbageCollectedType<const SimpleObject>::value,
"const GarbageCollected<>");
static_assert(WTF::IsGarbageCollectedType<IntWrapper>::value,
- "GarbageCollectedFinalized<>");
+ "GarbageCollected<>");
static_assert(WTF::IsGarbageCollectedType<GarbageCollectedMixin>::value,
"GarbageCollectedMixin");
static_assert(WTF::IsGarbageCollectedType<const GarbageCollectedMixin>::value,
@@ -6014,86 +6000,6 @@ TEST_F(HeapTest, HeapHashMapCallsDestructor) {
EXPECT_TRUE(string.Impl()->HasOneRef());
}
-TEST_F(HeapTest, PromptlyFreeStackAllocatedHeapVector) {
- NormalPageArena* normal_arena;
- Address before;
- {
- HeapVector<Member<IntWrapper>> vector;
- vector.push_back(MakeGarbageCollected<IntWrapper>(0));
- NormalPage* normal_page =
- static_cast<NormalPage*>(PageFromObject(vector.data()));
- normal_arena = normal_page->ArenaForNormalPage();
- CHECK(normal_arena);
- before = normal_arena->CurrentAllocationPoint();
- }
- Address after = normal_arena->CurrentAllocationPoint();
- // We check the allocation point to see if promptly freed
- EXPECT_NE(after, before);
-}
-
-TEST_F(HeapTest, PromptlyFreeStackAllocatedHeapDeque) {
- NormalPageArena* normal_arena;
- Address before;
- {
- HeapDeque<Member<IntWrapper>> deque;
- deque.push_back(MakeGarbageCollected<IntWrapper>(0));
- NormalPage* normal_page =
- static_cast<NormalPage*>(PageFromObject(&deque.front()));
- normal_arena = normal_page->ArenaForNormalPage();
- CHECK(normal_arena);
- before = normal_arena->CurrentAllocationPoint();
- }
- Address after = normal_arena->CurrentAllocationPoint();
- // We check the allocation point to see if promptly freed
- EXPECT_NE(after, before);
-}
-
-TEST_F(HeapTest, PromptlyFreeStackAllocatedHeapHashSet) {
- NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
- ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
- CHECK(normal_arena);
- Address before;
- {
- HeapHashSet<Member<IntWrapper>> hash_set;
- hash_set.insert(MakeGarbageCollected<IntWrapper>(0));
- before = normal_arena->CurrentAllocationPoint();
- }
- Address after = normal_arena->CurrentAllocationPoint();
- // We check the allocation point to see if promptly freed
- EXPECT_NE(after, before);
-}
-
-TEST_F(HeapTest, PromptlyFreeStackAllocatedHeapListHashSet) {
- ClearOutOldGarbage();
- NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
- ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
- CHECK(normal_arena);
- Address before;
- {
- HeapListHashSet<Member<IntWrapper>> list_hash_set;
- list_hash_set.insert(MakeGarbageCollected<IntWrapper>(0));
- before = normal_arena->CurrentAllocationPoint();
- }
- Address after = normal_arena->CurrentAllocationPoint();
- // We check the allocation point to see if promptly freed
- EXPECT_NE(after, before);
-}
-
-TEST_F(HeapTest, PromptlyFreeStackAllocatedHeapLinkedHashSet) {
- NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
- ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
- CHECK(normal_arena);
- Address before;
- {
- HeapLinkedHashSet<Member<IntWrapper>> linked_hash_set;
- linked_hash_set.insert(MakeGarbageCollected<IntWrapper>(0));
- before = normal_arena->CurrentAllocationPoint();
- }
- Address after = normal_arena->CurrentAllocationPoint();
- // We check the allocation point to see if promptly freed
- EXPECT_NE(after, before);
-}
-
TEST_F(HeapTest, ShrinkVector) {
// Regression test: https://crbug.com/823289
@@ -6145,7 +6051,7 @@ TEST_F(HeapTest, PersistentAssignsDeletedValue) {
PreciselyCollectGarbage();
}
-struct HeapHashMapWrapper : GarbageCollectedFinalized<HeapHashMapWrapper> {
+struct HeapHashMapWrapper final : GarbageCollected<HeapHashMapWrapper> {
HeapHashMapWrapper() {
for (int i = 0; i < 100; ++i) {
map_.insert(MakeGarbageCollected<IntWrapper>(i),
@@ -6187,7 +6093,7 @@ TEST_F(HeapTest, AccessDeletedBackingStore) {
}
BaseArena* map_arena = PageFromObject(map)->Arena();
// Sweep normal arena, but don't call finalizers.
- map_arena->SweepOnConcurrentThread();
+ map_arena->ConcurrentSweepWithDeadline(base::TimeTicks::Max());
// Now complete sweeping with PerformIdleLazySweep and call finalizers.
while (thread_state->IsSweepingInProgress()) {
thread_state->PerformIdleLazySweep(base::TimeTicks::Max());
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
index acb2cd9a407..528bd25aa8e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_compact.h"
namespace blink {
@@ -42,4 +43,48 @@ void TestSupportingGC::CompleteSweepingIfNeeded() {
ThreadState::Current()->CompleteSweep();
}
+IncrementalMarkingTestDriver::~IncrementalMarkingTestDriver() {
+ if (thread_state_->IsIncrementalMarking())
+ FinishGC();
+}
+
+void IncrementalMarkingTestDriver::Start() {
+ thread_state_->IncrementalMarkingStart(
+ BlinkGC::GCReason::kForcedGCForTesting);
+}
+
+bool IncrementalMarkingTestDriver::SingleStep(BlinkGC::StackState stack_state) {
+ CHECK(thread_state_->IsIncrementalMarking());
+ if (thread_state_->GetGCState() ==
+ ThreadState::kIncrementalMarkingStepScheduled) {
+ thread_state_->IncrementalMarkingStep(stack_state);
+ return true;
+ }
+ return false;
+}
+
+void IncrementalMarkingTestDriver::FinishSteps(
+ BlinkGC::StackState stack_state) {
+ CHECK(thread_state_->IsIncrementalMarking());
+ while (SingleStep(stack_state)) {
+ }
+}
+
+void IncrementalMarkingTestDriver::FinishGC(bool complete_sweep) {
+ CHECK(thread_state_->IsIncrementalMarking());
+ FinishSteps(BlinkGC::StackState::kNoHeapPointersOnStack);
+ CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled,
+ thread_state_->GetGCState());
+ thread_state_->RunScheduledGC(BlinkGC::StackState::kNoHeapPointersOnStack);
+ CHECK(!thread_state_->IsIncrementalMarking());
+ if (complete_sweep) {
+ thread_state_->CompleteSweep();
+ }
+}
+
+size_t IncrementalMarkingTestDriver::GetHeapCompactLastFixupCount() const {
+ HeapCompact* compaction = ThreadState::Current()->Heap().Compaction();
+ return compaction->LastFixupCountForTesting();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
index 0c7b669a16a..0d80e38b360 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.h
@@ -141,6 +141,27 @@ class LinkedObject : public GarbageCollected<LinkedObject> {
Member<LinkedObject> next_;
};
+// Test driver for incremental marking. Assumes that no stack handling is
+// required.
+class IncrementalMarkingTestDriver {
+ public:
+ explicit IncrementalMarkingTestDriver(ThreadState* thread_state)
+ : thread_state_(thread_state) {}
+ ~IncrementalMarkingTestDriver();
+
+ void Start();
+ bool SingleStep(BlinkGC::StackState stack_state =
+ BlinkGC::StackState::kNoHeapPointersOnStack);
+ void FinishSteps(BlinkGC::StackState stack_state =
+ BlinkGC::StackState::kNoHeapPointersOnStack);
+ void FinishGC(bool complete_sweep = true);
+
+ size_t GetHeapCompactLastFixupCount() const;
+
+ private:
+ ThreadState* const thread_state_;
+};
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_TEST_UTILITIES_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
index 0eeb71c64a9..b278208dd5b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -69,7 +69,6 @@ static void ParkWorkerThread() {
class Object : public GarbageCollected<Object> {
public:
Object() {}
- ~Object() {}
void Trace(blink::Visitor* visitor) {}
};
@@ -171,7 +170,7 @@ TEST_F(HeapThreadDeathTest, PersistentSameThreadCheck) {
class MarkingSameThreadCheckTester : public AlternatingThreadTester {
private:
- class MainThreadObject : public GarbageCollectedFinalized<MainThreadObject> {
+ class MainThreadObject final : public GarbageCollected<MainThreadObject> {
public:
void Trace(blink::Visitor* visitor) { visitor->Trace(set_); }
void AddToSet(Object* object) { set_.insert(42, object); }
@@ -212,7 +211,7 @@ TEST_F(HeapThreadDeathTest, MarkingSameThreadCheck) {
#endif
class DestructorLockingObject
- : public GarbageCollectedFinalized<DestructorLockingObject> {
+ : public GarbageCollected<DestructorLockingObject> {
public:
DestructorLockingObject() = default;
virtual ~DestructorLockingObject() { ++destructor_calls_; }
diff --git a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index 0e682e5a3dd..e30bbba1f4a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -171,7 +171,7 @@ class ExpectWriteBarrierFires : public IncrementalMarkingScope {
EXPECT_FALSE(marking_worklist_->IsGlobalEmpty());
MarkingItem item;
// All objects watched should be on the marking stack.
- while (marking_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
+ while (marking_worklist_->Pop(WorklistTaskId::MutatorThread, &item)) {
// Inspect backing stores to allow specifying objects that are only
// reachable through a backing store.
if (!ThreadHeap::IsNormalArenaIndex(
@@ -1444,7 +1444,7 @@ TEST_F(IncrementalMarkingTest, WriteBarrierDuringMixinConstruction) {
// the process of calling the constructor.
EXPECT_FALSE(scope.marking_worklist()->IsGlobalEmpty());
MarkingItem marking_item;
- while (scope.marking_worklist()->Pop(WorklistTaskId::MainThread,
+ while (scope.marking_worklist()->Pop(WorklistTaskId::MutatorThread,
&marking_item)) {
HeapObjectHeader* header =
HeapObjectHeader::FromPayload(marking_item.object);
@@ -1458,8 +1458,8 @@ TEST_F(IncrementalMarkingTest, WriteBarrierDuringMixinConstruction) {
bool found_mixin_object = false;
// The same object may be on the marking work list because of expanding
// and rehashing of the backing store in the registry.
- while (scope.not_fully_constructed_worklist()->Pop(WorklistTaskId::MainThread,
- &partial_item)) {
+ while (scope.not_fully_constructed_worklist()->Pop(
+ WorklistTaskId::MutatorThread, &partial_item)) {
if (object == partial_item)
found_mixin_object = true;
HeapObjectHeader* header = HeapObjectHeader::FromPayload(partial_item);
@@ -1482,60 +1482,6 @@ TEST_F(IncrementalMarkingTest, OverrideAfterMixinConstruction) {
// Tests that execute complete incremental garbage collections. ================
// =============================================================================
-// Test driver for incremental marking. Assumes that no stack handling is
-// required.
-class IncrementalMarkingTestDriver {
- public:
- explicit IncrementalMarkingTestDriver(ThreadState* thread_state)
- : thread_state_(thread_state) {}
- ~IncrementalMarkingTestDriver() {
- if (thread_state_->IsIncrementalMarking())
- FinishGC();
- }
-
- void Start() {
- thread_state_->IncrementalMarkingStart(
- BlinkGC::GCReason::kForcedGCForTesting);
- }
-
- bool SingleStep(BlinkGC::StackState stack_state =
- BlinkGC::StackState::kNoHeapPointersOnStack) {
- CHECK(thread_state_->IsIncrementalMarking());
- if (thread_state_->GetGCState() ==
- ThreadState::kIncrementalMarkingStepScheduled) {
- thread_state_->IncrementalMarkingStep(stack_state);
- return true;
- }
- return false;
- }
-
- void FinishSteps(BlinkGC::StackState stack_state =
- BlinkGC::StackState::kNoHeapPointersOnStack) {
- CHECK(thread_state_->IsIncrementalMarking());
- while (SingleStep(stack_state)) {
- }
- }
-
- void FinishGC(bool complete_sweep = true) {
- CHECK(thread_state_->IsIncrementalMarking());
- FinishSteps(BlinkGC::StackState::kNoHeapPointersOnStack);
- CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled,
- thread_state_->GetGCState());
- thread_state_->RunScheduledGC(BlinkGC::StackState::kNoHeapPointersOnStack);
- CHECK(!thread_state_->IsIncrementalMarking());
- if (complete_sweep)
- thread_state_->CompleteSweep();
- }
-
- size_t GetHeapCompactLastFixupCount() {
- HeapCompact* compaction = ThreadState::Current()->Heap().Compaction();
- return compaction->LastFixupCountForTesting();
- }
-
- private:
- ThreadState* const thread_state_;
-};
-
TEST_F(IncrementalMarkingTest, TestDriver) {
IncrementalMarkingTestDriver driver(ThreadState::Current());
driver.Start();
@@ -1860,7 +1806,8 @@ TEST_F(IncrementalMarkingTest,
driver.FinishSteps();
// GCs here are without stack. This is just to show that we don't want this
// object marked.
- CHECK(!HeapObjectHeader::FromPayload(nested)->IsMarked());
+ CHECK(!HeapObjectHeader::FromPayload(nested)
+ ->IsMarked<HeapObjectHeader::AccessMode::kAtomic>());
nested = nullptr;
driver.FinishGC();
}
@@ -1892,7 +1839,8 @@ TEST_F(IncrementalMarkingTest, AdjustMarkedBytesOnMarkedBackingStore) {
driver.Start();
driver.FinishSteps();
// The object is marked at this point.
- CHECK(HeapObjectHeader::FromPayload(holder.Get())->IsMarked());
+ CHECK(HeapObjectHeader::FromPayload(holder.Get())
+ ->IsMarked<HeapObjectHeader::AccessMode::kAtomic>());
driver.FinishGC(false);
// The object is still marked as sweeping did not make any progress.
CHECK(HeapObjectHeader::FromPayload(holder.Get())->IsMarked());
@@ -1930,7 +1878,7 @@ TEST_F(IncrementalMarkingTest, HeapCompactWithStaleSlotInNestedContainer) {
driver.FinishGC();
}
-class Destructed : public GarbageCollectedFinalized<Destructed> {
+class Destructed final : public GarbageCollected<Destructed> {
public:
~Destructed() { n_destructed++; }
@@ -1941,7 +1889,7 @@ class Destructed : public GarbageCollectedFinalized<Destructed> {
size_t Destructed::n_destructed = 0;
-class Wrapper : public GarbageCollectedFinalized<Wrapper> {
+class Wrapper final : public GarbageCollected<Wrapper> {
public:
using HashType = HeapLinkedHashSet<Member<Destructed>>;
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
index e998881935d..f789e3a9b36 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -32,12 +32,7 @@ MarkingVisitorBase::MarkingVisitorBase(ThreadState* state,
backing_store_callback_worklist_(Heap().GetBackingStoreCallbackWorklist(),
task_id),
marking_mode_(marking_mode),
- task_id_(task_id) {
- DCHECK(state->InAtomicMarkingPause());
-#if DCHECK_IS_ON()
- DCHECK(state->CheckThread());
-#endif // DCHECK_IS_ON
-}
+ task_id_(task_id) {}
void MarkingVisitorBase::FlushCompactionWorklists() {
movable_reference_worklist_.FlushToGlobal();
@@ -46,9 +41,6 @@ void MarkingVisitorBase::FlushCompactionWorklists() {
void MarkingVisitorBase::RegisterWeakCallback(void* object,
WeakCallback callback) {
- // We don't want to run weak processings when taking a snapshot.
- if (marking_mode_ == kSnapshotMarking)
- return;
weak_callback_worklist_.Push({object, callback});
}
@@ -80,40 +72,50 @@ bool MarkingVisitorBase::RegisterWeakTable(
return true;
}
-void MarkingVisitorBase::FlushWeakTableCallbacks() {
- weak_table_worklist_.FlushToGlobal();
-}
-
void MarkingVisitorBase::AdjustMarkedBytes(HeapObjectHeader* header,
size_t old_size) {
- DCHECK(header->IsMarked());
+ DCHECK(header->IsMarked<HeapObjectHeader::AccessMode::kAtomic>());
// Currently, only expansion of an object is supported during marking.
DCHECK_GE(header->size(), old_size);
marked_bytes_ += header->size() - old_size;
}
+// static
bool MarkingVisitor::WriteBarrierSlow(void* value) {
if (!value || IsHashTableDeleteValue(value))
return false;
- ThreadState* const thread_state = ThreadState::Current();
+ // It is guaranteed that managed references point to either GarbageCollected
+ // or GarbageCollectedMixin. Mixins are restricted to regular objects sizes.
+ // It is thus possible to get to the page header by aligning properly.
+ BasePage* base_page = PageFromObject(value);
+
+ ThreadState* const thread_state = base_page->thread_state();
if (!thread_state->IsIncrementalMarking())
return false;
- HeapObjectHeader* const header = HeapObjectHeader::FromInnerAddress(
- reinterpret_cast<Address>(const_cast<void*>(value)));
- if (header->IsMarked())
+ HeapObjectHeader* header;
+ if (LIKELY(!base_page->IsLargeObjectPage())) {
+ header = reinterpret_cast<HeapObjectHeader*>(
+ static_cast<NormalPage*>(base_page)->FindHeaderFromAddress(
+ reinterpret_cast<Address>(value)));
+ } else {
+ header = static_cast<LargeObjectPage*>(base_page)->ObjectHeader();
+ }
+ DCHECK(header->IsValid());
+
+ if (!header->TryMark<HeapObjectHeader::AccessMode::kAtomic>())
return false;
- if (header->IsInConstruction()) {
+ if (UNLIKELY(header->IsInConstruction())) {
+ // It is assumed that objects on not_fully_constructed_worklist_ are not
+ // marked.
+ header->Unmark();
thread_state->CurrentVisitor()->not_fully_constructed_worklist_.Push(
header->Payload());
return true;
}
- // Mark and push trace callback.
- if (!header->TryMark<HeapObjectHeader::AccessMode::kAtomic>())
- return false;
MarkingVisitor* visitor = thread_state->CurrentVisitor();
visitor->AccountMarkedBytes(header);
visitor->marking_worklist_.Push(
@@ -142,7 +144,7 @@ void MarkingVisitor::TraceMarkedBackingStoreSlow(void* value) {
}
MarkingVisitor::MarkingVisitor(ThreadState* state, MarkingMode marking_mode)
- : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MainThread) {
+ : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread) {
DCHECK(state->InAtomicMarkingPause());
DCHECK(state->CheckThread());
}
@@ -164,7 +166,8 @@ void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
HeapObjectHeader* const header =
page->IsLargeObjectPage()
? static_cast<LargeObjectPage*>(page)->ObjectHeader()
- : static_cast<NormalPage*>(page)->FindHeaderFromAddress(address);
+ : static_cast<NormalPage*>(page)->ConservativelyFindHeaderFromAddress(
+ address);
if (!header || header->IsMarked())
return;
@@ -205,13 +208,27 @@ void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
}
}
+void MarkingVisitor::FlushMarkingWorklist() {
+ marking_worklist_.FlushToGlobal();
+}
+
ConcurrentMarkingVisitor::ConcurrentMarkingVisitor(ThreadState* state,
MarkingMode marking_mode,
int task_id)
: MarkingVisitorBase(state, marking_mode, task_id) {
- DCHECK(state->InAtomicMarkingPause());
- DCHECK(state->CheckThread());
- DCHECK_NE(WorklistTaskId::MainThread, task_id);
+ DCHECK(!state->CheckThread());
+ DCHECK_NE(WorklistTaskId::MutatorThread, task_id);
+}
+
+void ConcurrentMarkingVisitor::FlushWorklists() {
+ // Flush marking worklists for further marking on the mutator thread.
+ marking_worklist_.FlushToGlobal();
+ not_fully_constructed_worklist_.FlushToGlobal();
+ weak_callback_worklist_.FlushToGlobal();
+ weak_table_worklist_.FlushToGlobal();
+ // Flush compaction worklists.
+ movable_reference_worklist_.FlushToGlobal();
+ backing_store_callback_worklist_.FlushToGlobal();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
index 80dee1024a0..a75facecbf9 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -21,9 +21,6 @@ class PLATFORM_EXPORT MarkingVisitorBase : public Visitor {
// This is a default visitor. This is used for MarkingType=kAtomicMarking
// and MarkingType=kIncrementalMarking.
kGlobalMarking,
- // This visitor just marks objects and ignores weak processing.
- // This is used for MarkingType=kTakeSnapshot.
- kSnapshotMarking,
// Perform global marking along with preparing for additional sweep
// compaction of heap arenas afterwards. Compared to the GlobalMarking
// visitor, this visitor will also register references to objects
@@ -57,7 +54,8 @@ class PLATFORM_EXPORT MarkingVisitorBase : public Visitor {
// ensures that any newly set value after this point is kept alive and does
// not require the callback.
if (desc.base_object_payload != BlinkGC::kNotFullyConstructedObject &&
- HeapObjectHeader::FromPayload(desc.base_object_payload)->IsMarked())
+ HeapObjectHeader::FromPayload(desc.base_object_payload)
+ ->IsMarked<HeapObjectHeader::AccessMode::kAtomic>())
return;
RegisterWeakCallback(object_weak_ref, callback);
}
@@ -110,8 +108,6 @@ class PLATFORM_EXPORT MarkingVisitorBase : public Visitor {
// Flush private segments remaining in visitor's worklists to global pools.
void FlushCompactionWorklists();
- void FlushWeakTableCallbacks();
-
size_t marked_bytes() const { return marked_bytes_; }
int task_id() const { return task_id_; }
@@ -164,7 +160,7 @@ inline bool MarkingVisitorBase::MarkHeaderNoTracing(HeapObjectHeader* header) {
// freed backing store.
DCHECK(!header->IsFree());
- if (header->TryMark()) {
+ if (header->TryMark<HeapObjectHeader::AccessMode::kAtomic>()) {
AccountMarkedBytes(header);
return true;
}
@@ -176,7 +172,7 @@ inline void MarkingVisitorBase::MarkHeader(HeapObjectHeader* header,
DCHECK(header);
DCHECK(callback);
- if (header->IsInConstruction()) {
+ if (header->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()) {
not_fully_constructed_worklist_.Push(header->Payload());
} else if (MarkHeaderNoTracing(header)) {
marking_worklist_.Push(
@@ -214,6 +210,8 @@ class PLATFORM_EXPORT MarkingVisitor : public MarkingVisitorBase {
// to be in construction.
void DynamicallyMarkAddress(Address);
+ void FlushMarkingWorklist();
+
private:
// Exact version of the marking write barriers.
static bool WriteBarrierSlow(void*);
@@ -243,6 +241,8 @@ class PLATFORM_EXPORT ConcurrentMarkingVisitor : public MarkingVisitorBase {
public:
ConcurrentMarkingVisitor(ThreadState*, MarkingMode, int);
~ConcurrentMarkingVisitor() override = default;
+
+ virtual void FlushWorklists();
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent.h b/chromium/third_party/blink/renderer/platform/heap/persistent.h
index 7a0e96365ae..a2e9ed6e644 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent.h
@@ -64,7 +64,10 @@ class PersistentBase {
return result;
}
- void Clear() { AssignSafe(nullptr); }
+ void Clear() {
+ // Note that this also frees up related data in the backend.
+ AssignSafe(nullptr);
+ }
T* Get() const {
CheckPointer();
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
index 5edbdc75d2d..a0a6bb8c996 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
@@ -19,59 +19,44 @@ class DummyGCBase final : public GarbageCollected<DummyGCBase> {
};
}
-PersistentRegion::~PersistentRegion() {
+PersistentRegionBase::~PersistentRegionBase() {
PersistentNodeSlots* slots = slots_;
while (slots) {
PersistentNodeSlots* dead_slots = slots;
- slots = slots->next_;
+ slots = slots->next;
delete dead_slots;
}
}
-int PersistentRegion::NumberOfPersistents() {
+int PersistentRegionBase::NodesInUse() const {
size_t persistent_count = 0;
- for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next_) {
+ for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- if (!slots->slot_[i].IsUnused())
+ if (!slots->slot[i].IsUnused())
++persistent_count;
}
}
#if DCHECK_IS_ON()
- DCHECK_EQ(persistent_count, persistent_count_);
+ DCHECK_EQ(persistent_count, used_node_count_);
#endif
return persistent_count;
}
-void PersistentRegion::EnsurePersistentNodeSlots(void* self,
- TraceCallback trace) {
+void PersistentRegionBase::EnsureNodeSlots() {
DCHECK(!free_list_head_);
PersistentNodeSlots* slots = new PersistentNodeSlots;
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- PersistentNode* node = &slots->slot_[i];
+ PersistentNode* node = &slots->slot[i];
node->SetFreeListNext(free_list_head_);
free_list_head_ = node;
DCHECK(node->IsUnused());
}
- slots->next_ = slots_;
+ slots->next = slots_;
slots_ = slots;
}
-void PersistentRegion::ReleasePersistentNode(PersistentNode* persistent_node) {
- DCHECK(!persistent_node->IsUnused());
- // 'self' is in use, containing the persistent wrapper object.
- void* self = persistent_node->Self();
- Persistent<DummyGCBase>* persistent =
- reinterpret_cast<Persistent<DummyGCBase>*>(self);
- persistent->Clear();
- DCHECK(persistent_node->IsUnused());
-}
-
-// This function traces all PersistentNodes. If we encounter
-// a PersistentNodeSlot that contains only freed PersistentNodes,
-// we delete the PersistentNodeSlot. This function rebuilds the free
-// list of PersistentNodes.
-void PersistentRegion::TracePersistentNodes(Visitor* visitor,
- ShouldTraceCallback should_trace) {
+void PersistentRegionBase::TraceNodesImpl(Visitor* visitor,
+ ShouldTraceCallback should_trace) {
free_list_head_ = nullptr;
size_t persistent_count = 0;
PersistentNodeSlots** prev_next = &slots_;
@@ -81,7 +66,7 @@ void PersistentRegion::TracePersistentNodes(Visitor* visitor,
PersistentNode* free_list_last = nullptr;
int free_count = 0;
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- PersistentNode* node = &slots->slot_[i];
+ PersistentNode* node = &slots->slot[i];
if (node->IsUnused()) {
if (!free_list_next)
free_list_last = node;
@@ -97,8 +82,8 @@ void PersistentRegion::TracePersistentNodes(Visitor* visitor,
}
if (free_count == PersistentNodeSlots::kSlotCount) {
PersistentNodeSlots* dead_slots = slots;
- *prev_next = slots->next_;
- slots = slots->next_;
+ *prev_next = slots->next;
+ slots = slots->next;
delete dead_slots;
} else {
if (free_list_last) {
@@ -107,21 +92,32 @@ void PersistentRegion::TracePersistentNodes(Visitor* visitor,
free_list_last->SetFreeListNext(free_list_head_);
free_list_head_ = free_list_next;
}
- prev_next = &slots->next_;
- slots = slots->next_;
+ prev_next = &slots->next;
+ slots = slots->next;
}
}
#if DCHECK_IS_ON()
- DCHECK_EQ(persistent_count, persistent_count_);
+ DCHECK_EQ(persistent_count, used_node_count_);
#endif
}
-void PersistentRegion::PrepareForThreadStateTermination() {
+void PersistentRegion::ReleaseNode(PersistentNode* persistent_node) {
+ DCHECK(!persistent_node->IsUnused());
+ // 'self' is in use, containing the persistent wrapper object.
+ void* self = persistent_node->Self();
+ Persistent<DummyGCBase>* persistent =
+ reinterpret_cast<Persistent<DummyGCBase>*>(self);
+ persistent->Clear();
+ DCHECK(persistent_node->IsUnused());
+}
+
+void PersistentRegion::PrepareForThreadStateTermination(ThreadState* state) {
+ DCHECK_EQ(state, ThreadState::Current());
DCHECK(!IsMainThread());
PersistentNodeSlots* slots = slots_;
while (slots) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- PersistentNode* node = &slots->slot_[i];
+ PersistentNode* node = &slots->slot[i];
if (node->IsUnused())
continue;
// It is safe to cast to Persistent<DummyGCBase> because persistent heap
@@ -132,10 +128,10 @@ void PersistentRegion::PrepareForThreadStateTermination() {
persistent->Clear();
DCHECK(node->IsUnused());
}
- slots = slots->next_;
+ slots = slots->next;
}
#if DCHECK_IS_ON()
- DCHECK_EQ(persistent_count_, 0u);
+ DCHECK_EQ(used_node_count_, 0u);
#endif
}
@@ -159,17 +155,17 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
// out the underlying heap reference.
MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
- PersistentNodeSlots* slots = persistent_region_.slots_;
+ PersistentNodeSlots* slots = slots_;
while (slots) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- if (slots->slot_[i].IsUnused())
+ if (slots->slot[i].IsUnused())
continue;
// 'self' is in use, containing the cross-thread persistent wrapper
// object.
CrossThreadPersistent<DummyGCBase>* persistent =
reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>(
- slots->slot_[i].Self());
+ slots->slot[i].Self());
DCHECK(persistent);
void* raw_object = persistent->Get();
if (!raw_object)
@@ -178,10 +174,10 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
DCHECK(page);
if (page->Arena()->GetThreadState() == thread_state) {
persistent->ClearWithLockHeld();
- DCHECK(slots->slot_[i].IsUnused());
+ DCHECK(slots->slot[i].IsUnused());
}
}
- slots = slots->next_;
+ slots = slots->next;
}
}
@@ -191,10 +187,9 @@ void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
ProcessHeap::CrossThreadPersistentMutex().AssertAcquired();
#endif
size_t persistent_count = 0;
- for (PersistentNodeSlots* slots = persistent_region_.slots_; slots;
- slots = slots->next_) {
+ for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
- const PersistentNode& node = slots->slot_[i];
+ const PersistentNode& node = slots->slot[i];
if (!node.IsUnused()) {
ASAN_UNPOISON_MEMORY_REGION(node.Self(),
sizeof(CrossThreadPersistent<void*>));
@@ -203,7 +198,7 @@ void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
}
}
#if DCHECK_IS_ON()
- DCHECK_EQ(persistent_count, persistent_region_.persistent_count_);
+ DCHECK_EQ(persistent_count, used_node_count_);
#endif
}
#endif
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
index fcd71423629..bc76a0174b1 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -123,12 +123,11 @@ class PersistentNode final {
struct PersistentNodeSlots final {
USING_FAST_MALLOC(PersistentNodeSlots);
- private:
- static const int kSlotCount = 256;
- PersistentNodeSlots* next_;
- PersistentNode slot_[kSlotCount];
- friend class PersistentRegion;
- friend class CrossThreadPersistentRegion;
+ public:
+ static constexpr int kSlotCount = 256;
+
+ PersistentNodeSlots* next;
+ PersistentNode slot[kSlotCount];
};
// Used by PersistentBase to manage a pointer to a thread heap persistent node.
@@ -196,118 +195,119 @@ class CrossThreadPersistentNodePtr {
std::atomic<PersistentNode*> ptr_{nullptr};
};
-// PersistentRegion provides a region of PersistentNodes. PersistentRegion
-// holds a linked list of PersistentNodeSlots, each of which stores
-// a predefined number of PersistentNodes. You can call allocatePersistentNode/
-// freePersistentNode to allocate/free a PersistentNode on the region.
-class PLATFORM_EXPORT PersistentRegion final {
- USING_FAST_MALLOC(PersistentRegion);
-
+class PLATFORM_EXPORT PersistentRegionBase {
public:
- PersistentRegion() = default;
- ~PersistentRegion();
+ ~PersistentRegionBase();
+
+ inline PersistentNode* AllocateNode(void* self, TraceCallback trace);
+ inline void FreeNode(PersistentNode* persistent_node);
+ int NodesInUse() const;
+
+ protected:
+ using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*);
- PersistentNode* AllocatePersistentNode(void* self, TraceCallback trace) {
+ void TraceNodesImpl(Visitor*, ShouldTraceCallback);
+
+ void EnsureNodeSlots();
+
+ PersistentNode* free_list_head_ = nullptr;
+ PersistentNodeSlots* slots_ = nullptr;
#if DCHECK_IS_ON()
- ++persistent_count_;
+ size_t used_node_count_ = 0;
#endif
- if (UNLIKELY(!free_list_head_))
- EnsurePersistentNodeSlots(self, trace);
- DCHECK(free_list_head_);
- PersistentNode* node = free_list_head_;
- free_list_head_ = free_list_head_->FreeListNext();
- node->Initialize(self, trace);
- DCHECK(!node->IsUnused());
- return node;
- }
+};
- void FreePersistentNode(PersistentNode* persistent_node) {
+inline PersistentNode* PersistentRegionBase::AllocateNode(void* self,
+ TraceCallback trace) {
#if DCHECK_IS_ON()
- DCHECK_GT(persistent_count_, 0u);
+ ++used_node_count_;
#endif
- persistent_node->SetFreeListNext(free_list_head_);
- free_list_head_ = persistent_node;
+ if (UNLIKELY(!free_list_head_))
+ EnsureNodeSlots();
+ DCHECK(free_list_head_);
+ PersistentNode* node = free_list_head_;
+ free_list_head_ = free_list_head_->FreeListNext();
+ node->Initialize(self, trace);
+ DCHECK(!node->IsUnused());
+ return node;
+}
+
+void PersistentRegionBase::FreeNode(PersistentNode* persistent_node) {
#if DCHECK_IS_ON()
- --persistent_count_;
+ DCHECK_GT(used_node_count_, 0u);
#endif
- }
+ persistent_node->SetFreeListNext(free_list_head_);
+ free_list_head_ = persistent_node;
+#if DCHECK_IS_ON()
+ --used_node_count_;
+#endif
+}
- static bool ShouldTracePersistentNode(Visitor*, PersistentNode*) {
- return true;
- }
+class PLATFORM_EXPORT PersistentRegion final : public PersistentRegionBase {
+ USING_FAST_MALLOC(PersistentRegion);
- void ReleasePersistentNode(PersistentNode*);
- using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*);
- void TracePersistentNodes(
- Visitor*,
- ShouldTraceCallback = PersistentRegion::ShouldTracePersistentNode);
- int NumberOfPersistents();
- void PrepareForThreadStateTermination();
+ public:
+ inline void TraceNodes(Visitor*);
- private:
- friend CrossThreadPersistentRegion;
+ // Clears the Persistent and then frees the node.
+ void ReleaseNode(PersistentNode*);
- void EnsurePersistentNodeSlots(void*, TraceCallback);
+ void PrepareForThreadStateTermination(ThreadState*);
- PersistentNode* free_list_head_ = nullptr;
- PersistentNodeSlots* slots_ = nullptr;
-#if DCHECK_IS_ON()
- size_t persistent_count_ = 0;
-#endif
+ private:
+ static constexpr bool ShouldTracePersistentNode(Visitor*, PersistentNode*) {
+ return true;
+ }
};
-// Protected by ProcessHeap::CrossThreadPersistentMutex.
-class PLATFORM_EXPORT CrossThreadPersistentRegion final {
+inline void PersistentRegion::TraceNodes(Visitor* visitor) {
+ PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode);
+}
+
+class PLATFORM_EXPORT CrossThreadPersistentRegion final
+ : public PersistentRegionBase {
USING_FAST_MALLOC(CrossThreadPersistentRegion);
public:
- PersistentNode* AllocatePersistentNode(void* self, TraceCallback trace) {
- PersistentMutexTraits<
- kCrossThreadPersistentConfiguration>::AssertAcquired();
- return persistent_region_.AllocatePersistentNode(self, trace);
- }
-
- void FreePersistentNode(PersistentNode* node) {
- PersistentMutexTraits<
- kCrossThreadPersistentConfiguration>::AssertAcquired();
- // When the thread that holds the heap object that the cross-thread
- // persistent shuts down, prepareForThreadStateTermination() will clear out
- // the associated CrossThreadPersistent<> and PersistentNode so as to avoid
- // unsafe access. This can overlap with a holder of the
- // CrossThreadPersistent<> also clearing the persistent and freeing the
- // PersistentNode.
- //
- // The lock ensures the updating is ordered, but by the time lock has been
- // acquired the PersistentNode reference may have been cleared out already;
- // check for this.
- if (!node)
- return;
- persistent_region_.FreePersistentNode(node);
- }
-
- void TracePersistentNodes(Visitor* visitor) {
- PersistentMutexTraits<
- kCrossThreadPersistentConfiguration>::AssertAcquired();
- persistent_region_.TracePersistentNodes(
- visitor, CrossThreadPersistentRegion::ShouldTracePersistentNode);
- }
+ inline PersistentNode* AllocateNode(void* self, TraceCallback trace);
+ inline void FreeNode(PersistentNode*);
+ inline void TraceNodes(Visitor*);
void PrepareForThreadStateTermination(ThreadState*);
- NO_SANITIZE_ADDRESS
- static bool ShouldTracePersistentNode(Visitor*, PersistentNode*);
-
#if defined(ADDRESS_SANITIZER)
void UnpoisonCrossThreadPersistents();
#endif
private:
- // We don't make CrossThreadPersistentRegion inherit from PersistentRegion
- // because we don't want to virtualize performance-sensitive methods
- // such as PersistentRegion::allocate/freePersistentNode.
- PersistentRegion persistent_region_;
+ NO_SANITIZE_ADDRESS
+ static bool ShouldTracePersistentNode(Visitor*, PersistentNode*);
};
+inline PersistentNode* CrossThreadPersistentRegion::AllocateNode(
+ void* self,
+ TraceCallback trace) {
+ PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired();
+ return PersistentRegionBase::AllocateNode(self, trace);
+}
+
+inline void CrossThreadPersistentRegion::FreeNode(PersistentNode* node) {
+ PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired();
+ // PersistentBase::UninitializeSafe opportunistically checks for uninitialized
+ // nodes to allow a fast path destruction of unused nodes. This check is
+ // performed without taking the lock that is required for processing a
+ // cross-thread node. After taking the lock the condition needs to checked
+ // again to avoid double-freeing a node because the node may have been
+ // concurrently freed by the garbage collector on another thread.
+ if (!node)
+ return;
+ PersistentRegionBase::FreeNode(node);
+}
+
+inline void CrossThreadPersistentRegion::TraceNodes(Visitor* visitor) {
+ PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode);
+}
+
template <ThreadAffinity affinity,
WeaknessPersistentConfiguration weakness_configuration>
void PersistentNodePtr<affinity, weakness_configuration>::Initialize(
@@ -319,7 +319,7 @@ void PersistentNodePtr<affinity, weakness_configuration>::Initialize(
weakness_configuration == kWeakPersistentConfiguration
? state->GetWeakPersistentRegion()
: state->GetPersistentRegion();
- ptr_ = region->AllocatePersistentNode(owner, trace_callback);
+ ptr_ = region->AllocateNode(owner, trace_callback);
#if DCHECK_IS_ON()
state_ = state;
#endif
@@ -354,7 +354,7 @@ void CrossThreadPersistentNodePtr<weakness_configuration>::Initialize(
weakness_configuration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
- PersistentNode* node = region.AllocatePersistentNode(owner, trace_callback);
+ PersistentNode* node = region.AllocateNode(owner, trace_callback);
ptr_.store(node, std::memory_order_release);
}
@@ -365,7 +365,7 @@ void CrossThreadPersistentNodePtr<weakness_configuration>::Uninitialize() {
weakness_configuration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
- region.FreePersistentNode(ptr_.load(std::memory_order_relaxed));
+ region.FreeNode(ptr_.load(std::memory_order_relaxed));
ptr_.store(nullptr, std::memory_order_release);
}
@@ -376,7 +376,7 @@ void CrossThreadPersistentNodePtr<weakness_configuration>::ClearWithLockHeld() {
weakness_configuration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
- region.FreePersistentNode(ptr_.load(std::memory_order_relaxed));
+ region.FreeNode(ptr_.load(std::memory_order_relaxed));
ptr_.store(nullptr, std::memory_order_release);
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/process_heap.cc b/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
index 604eb8d3471..df929e8dfd2 100644
--- a/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/heap/process_heap.h"
#include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/heap/gc_info.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/persistent_node.h"
@@ -27,6 +28,11 @@ void BlinkGCFreeHook(uint8_t* address) {
} // namespace
void ProcessHeap::Init() {
+ DCHECK(!base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking) ||
+ base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapIncrementalMarking));
+
total_allocated_space_ = 0;
total_allocated_object_size_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
index 662d65a94df..9e803dccfad 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/address_cache.h"
#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
+#include "third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_buildflags.h"
@@ -97,13 +98,19 @@ uint8_t ThreadState::main_thread_state_storage_[sizeof(ThreadState)];
namespace {
-const size_t kDefaultAllocatedObjectSizeThreshold = 100 * 1024;
-
// Duration of one incremental marking step. Should be short enough that it
// doesn't cause jank even though it is scheduled as a normal task.
constexpr base::TimeDelta kDefaultIncrementalMarkingStepDuration =
base::TimeDelta::FromMilliseconds(2);
+// Concurrent marking should stop every once in a while to flush private
+// segments to v8 marking worklist. It should also stop to avoid priority
+// inversion.
+//
+// TODO(omerkatz): What is a good value to set here?
+constexpr base::TimeDelta kConcurrentMarkingStepDuration =
+ base::TimeDelta::FromMilliseconds(2);
+
constexpr size_t kMaxTerminationGCLoops = 20;
// Helper function to convert a byte count to a KB count, capping at
@@ -134,28 +141,16 @@ ThreadState::ThreadState()
#if defined(ADDRESS_SANITIZER)
asan_fake_stack_(__asan_get_current_fake_stack()),
#endif
- sweeper_scheduler_(base::MakeRefCounted<WorkerPoolTaskRunner>()) {
+ marker_scheduler_(std::make_unique<CancelableTaskScheduler>(
+ base::MakeRefCounted<WorkerPoolTaskRunner>())),
+ sweeper_scheduler_(std::make_unique<CancelableTaskScheduler>(
+ base::MakeRefCounted<WorkerPoolTaskRunner>())) {
DCHECK(CheckThread());
DCHECK(!**thread_specific_);
**thread_specific_ = this;
heap_ = std::make_unique<ThreadHeap>(this);
}
-// Implementation for RAILModeObserver
-void ThreadState::OnRAILModeChanged(RAILMode new_mode) {
- should_optimize_for_load_time_ = new_mode == RAILMode::kLoad;
- // When switching RAIL mode to load we try to avoid incremental marking as
- // the write barrier cost is noticeable on throughput and garbage
- // accumulated during loading is likely to be alive during that phase. The
- // same argument holds for unified heap garbage collections with the
- // difference that these collections are triggered by V8 and should thus be
- // avoided on that end.
- if (should_optimize_for_load_time_ && IsIncrementalMarking() &&
- !IsUnifiedGCMarkingInProgress() &&
- GetGCState() == GCState::kIncrementalMarkingStepScheduled)
- ScheduleIncrementalMarkingFinalize();
-}
-
ThreadState::~ThreadState() {
DCHECK(CheckThread());
if (IsMainThread())
@@ -165,15 +160,13 @@ ThreadState::~ThreadState() {
**thread_specific_ = nullptr;
}
-void ThreadState::AttachMainThread() {
+ThreadState* ThreadState::AttachMainThread() {
thread_specific_ = new WTF::ThreadSpecific<ThreadState*>();
- new (main_thread_state_storage_) ThreadState();
-
- ThreadScheduler::Current()->AddRAILModeObserver(MainThreadState());
+ return new (main_thread_state_storage_) ThreadState();
}
-void ThreadState::AttachCurrentThread() {
- new ThreadState();
+ThreadState* ThreadState::AttachCurrentThread() {
+ return new ThreadState();
}
void ThreadState::DetachCurrentThread() {
@@ -217,7 +210,7 @@ void ThreadState::RunTerminationGC() {
DCHECK(CheckThread());
FinishIncrementalMarkingIfRunning(BlinkGC::kNoHeapPointersOnStack,
- BlinkGC::kIncrementalMarking,
+ BlinkGC::kIncrementalAndConcurrentMarking,
BlinkGC::kConcurrentAndLazySweeping,
BlinkGC::GCReason::kThreadTerminationGC);
@@ -234,7 +227,7 @@ void ThreadState::RunTerminationGC() {
// Do thread local GC's as long as the count of thread local Persistents
// changes and is above zero.
int old_count = -1;
- int current_count = GetPersistentRegion()->NumberOfPersistents();
+ int current_count = GetPersistentRegion()->NodesInUse();
DCHECK_GE(current_count, 0);
while (current_count != old_count) {
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
@@ -244,7 +237,7 @@ void ThreadState::RunTerminationGC() {
// instantiated while running the termination GC.
ReleaseStaticPersistentNodes();
old_count = current_count;
- current_count = GetPersistentRegion()->NumberOfPersistents();
+ current_count = GetPersistentRegion()->NodesInUse();
}
// We should not have any persistents left when getting to this point,
@@ -252,17 +245,17 @@ void ThreadState::RunTerminationGC() {
// RegisterAsStaticReference. Clearing out all the Persistents will avoid
// stale pointers and gets them reported as nullptr dereferences.
if (current_count) {
- for (size_t i = 0; i < kMaxTerminationGCLoops &&
- GetPersistentRegion()->NumberOfPersistents();
+ for (size_t i = 0;
+ i < kMaxTerminationGCLoops && GetPersistentRegion()->NodesInUse();
i++) {
- GetPersistentRegion()->PrepareForThreadStateTermination();
+ GetPersistentRegion()->PrepareForThreadStateTermination(this);
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
BlinkGC::kEagerSweeping,
BlinkGC::GCReason::kThreadTerminationGC);
}
}
- CHECK(!GetPersistentRegion()->NumberOfPersistents());
+ CHECK(!GetPersistentRegion()->NodesInUse());
// All of pre-finalizers should be consumed.
DCHECK(ordered_pre_finalizers_.empty());
@@ -343,173 +336,18 @@ void ThreadState::VisitPersistents(Visitor* visitor) {
Heap().stats_collector(),
ThreadHeapStatsCollector::kVisitCrossThreadPersistents);
ProcessHeap::CrossThreadPersistentMutex().AssertAcquired();
- ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor);
+ ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(visitor);
}
{
ThreadHeapStatsCollector::Scope inner_stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kVisitPersistents);
- persistent_region_->TracePersistentNodes(visitor);
+ persistent_region_->TraceNodes(visitor);
}
}
void ThreadState::VisitWeakPersistents(Visitor* visitor) {
- ProcessHeap::GetCrossThreadWeakPersistentRegion().TracePersistentNodes(
- visitor);
- weak_persistent_region_->TracePersistentNodes(visitor);
-}
-
-ThreadState::GCSnapshotInfo::GCSnapshotInfo(wtf_size_t num_object_types)
- : live_count(Vector<int>(num_object_types)),
- dead_count(Vector<int>(num_object_types)),
- live_size(Vector<size_t>(num_object_types)),
- dead_size(Vector<size_t>(num_object_types)) {}
-
-size_t ThreadState::TotalMemorySize() {
- return heap_->stats_collector()->object_size_in_bytes() +
- WTF::Partitions::TotalSizeOfCommittedPages();
-}
-
-size_t ThreadState::EstimatedLiveSize(size_t estimation_base_size,
- size_t size_at_last_gc) {
- const ThreadHeapStatsCollector& stats_collector = *heap_->stats_collector();
- const ThreadHeapStatsCollector::Event& prev = stats_collector.previous();
-
- if (prev.wrapper_count_before_sweeping == 0)
- return estimation_base_size;
-
- // (estimated size) = (estimation base size) - (heap size at the last GC) /
- // (# of persistent handles at the last GC) *
- // (# of persistent handles collected since the last GC)
- size_t size_retained_by_collected_persistents = static_cast<size_t>(
- 1.0 * size_at_last_gc / prev.wrapper_count_before_sweeping *
- stats_collector.collected_wrapper_count());
- if (estimation_base_size < size_retained_by_collected_persistents)
- return 0;
- return estimation_base_size - size_retained_by_collected_persistents;
-}
-
-double ThreadState::HeapGrowingRate() {
- const size_t current_size = heap_->stats_collector()->object_size_in_bytes();
- // TODO(mlippautz): Clarify those two parameters below.
- const size_t estimated_size =
- EstimatedLiveSize(heap_->stats_collector()->previous().marked_bytes,
- heap_->stats_collector()->previous().marked_bytes);
-
- // If the estimatedSize is 0, we set a high growing rate to trigger a GC.
- double growing_rate =
- estimated_size > 0 ? 1.0 * current_size / estimated_size : 100;
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadState::heapEstimatedSizeKB",
- CappedSizeInKB(estimated_size));
- TRACE_COUNTER1(
- TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::heapGrowingRate",
- base::saturated_cast<base::Histogram::Sample>(100 * growing_rate));
- return growing_rate;
-}
-
-double ThreadState::PartitionAllocGrowingRate() {
- size_t current_size = WTF::Partitions::TotalSizeOfCommittedPages();
- size_t estimated_size = EstimatedLiveSize(
- current_size, heap_->stats_collector()
- ->previous()
- .partition_alloc_bytes_before_sweeping);
-
- // If the estimatedSize is 0, we set a high growing rate to trigger a GC.
- double growing_rate =
- estimated_size > 0 ? 1.0 * current_size / estimated_size : 100;
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadState::partitionAllocEstimatedSizeKB",
- CappedSizeInKB(estimated_size));
- TRACE_COUNTER1(
- TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadState::partitionAllocGrowingRate",
- base::saturated_cast<base::Histogram::Sample>(100 * growing_rate));
- return growing_rate;
-}
-
-// TODO(haraken): We should improve the GC heuristics. The heuristics affect
-// performance significantly.
-bool ThreadState::JudgeGCThreshold(size_t allocated_object_size_threshold,
- size_t total_memory_size_threshold,
- double heap_growing_rate_threshold) {
- // If the allocated object size or the total memory size is small, don't
- // trigger a GC.
- if (heap_->stats_collector()->allocated_bytes_since_prev_gc() <
- static_cast<int64_t>(allocated_object_size_threshold) ||
- TotalMemorySize() < total_memory_size_threshold)
- return false;
-
- VLOG(2) << "[state:" << this << "] JudgeGCThreshold:"
- << " heapGrowingRate=" << std::setprecision(1) << HeapGrowingRate()
- << " partitionAllocGrowingRate=" << std::setprecision(1)
- << PartitionAllocGrowingRate();
- // If the growing rate of Oilpan's heap or PartitionAlloc is high enough,
- // trigger a GC.
- return HeapGrowingRate() >= heap_growing_rate_threshold ||
- PartitionAllocGrowingRate() >= heap_growing_rate_threshold;
-}
-
-bool ThreadState::ShouldScheduleV8FollowupGC() {
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- return false;
-
- return JudgeGCThreshold(kDefaultAllocatedObjectSizeThreshold,
- 32 * 1024 * 1024, 1.5);
-}
-
-bool ThreadState::ShouldForceConservativeGC() {
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- return false;
-
- // TODO(haraken): 400% is too large. Lower the heap growing factor.
- return JudgeGCThreshold(kDefaultAllocatedObjectSizeThreshold,
- 32 * 1024 * 1024, 5.0);
-}
-
-// If we're consuming too much memory, trigger a conservative GC
-// aggressively. This is a safe guard to avoid OOM.
-bool ThreadState::ShouldForceMemoryPressureGC() {
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- return false;
-
- if (TotalMemorySize() < 300 * 1024 * 1024)
- return false;
- return JudgeGCThreshold(0, 0, 1.5);
-}
-
-void ThreadState::ScheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gc_type) {
- VLOG(2) << "[state:" << this << "] ScheduleV8FollowupGCIfNeeded: v8_gc_type="
- << ((gc_type == BlinkGC::kV8MajorGC) ? "MajorGC" : "MinorGC");
- DCHECK(CheckThread());
-
- if (IsGCForbidden())
- return;
-
- if (gc_type == BlinkGC::kV8MajorGC) {
- // In case of unified heap garbage collections a V8 major GC also collects
- // the Blink heap.
- return;
- }
-
- if (ShouldScheduleV8FollowupGC()) {
- // When we want to optimize for load time, we should prioritize throughput
- // over latency and not do incremental marking.
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapIncrementalMarking) &&
- !should_optimize_for_load_time_) {
- VLOG(2) << "[state:" << this << "] "
- << "ScheduleV8FollowupGCIfNeeded: Scheduled incremental v8 "
- "followup GC";
- ScheduleIncrementalGC(BlinkGC::GCReason::kIncrementalV8FollowupGC);
- } else {
- VLOG(2) << "[state:" << this << "] "
- << "ScheduleV8FollowupGCIfNeeded: Scheduled precise GC";
- SchedulePreciseGC();
- }
- }
+ ProcessHeap::GetCrossThreadWeakPersistentRegion().TraceNodes(visitor);
+ weak_persistent_region_->TraceNodes(visitor);
}
void ThreadState::WillStartV8GC(BlinkGC::V8GCType gc_type) {
@@ -546,32 +384,6 @@ void ThreadState::ScheduleGCIfNeeded() {
if (IsUnifiedGCMarkingInProgress())
return;
- ReportMemoryToV8();
-
- if (ShouldForceMemoryPressureGC()) {
- CompleteSweep();
- if (ShouldForceMemoryPressureGC()) {
- VLOG(2) << "[state:" << this << "] "
- << "ScheduleGCIfNeeded: Scheduled memory pressure GC";
- CollectGarbage(BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
- BlinkGC::GCReason::kMemoryPressureGC);
- return;
- }
- }
-
- if (ShouldForceConservativeGC()) {
- CompleteSweep();
- if (ShouldForceConservativeGC()) {
- VLOG(2) << "[state:" << this << "] "
- << "ScheduleGCIfNeeded: Scheduled conservative GC";
- CollectGarbage(BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kConcurrentAndLazySweeping,
- BlinkGC::GCReason::kConservativeGC);
- return;
- }
- }
-
if (GetGCState() == kNoGCScheduled &&
base::FeatureList::IsEnabled(
blink::features::kBlinkHeapIncrementalMarkingStress)) {
@@ -614,7 +426,8 @@ void ThreadState::PerformIdleLazySweep(base::TimeTicks deadline) {
ThreadHeapStatsCollector::EnabledScope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kLazySweepInIdle,
"idleDeltaInSeconds", (deadline - base::TimeTicks::Now()).InSecondsF());
- sweep_completed = Heap().AdvanceLazySweep(deadline);
+ sweep_completed =
+ Heap().AdvanceSweep(ThreadHeap::SweepingType::kMutator, deadline);
// We couldn't finish the sweeping within the deadline.
// We request another idle task for the remaining sweeping.
if (sweep_completed) {
@@ -632,11 +445,25 @@ void ThreadState::PerformIdleLazySweep(base::TimeTicks deadline) {
void ThreadState::PerformConcurrentSweep() {
VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] "
<< "ConcurrentSweep";
+ // As opposed to PerformIdleLazySweep, this function doesn't receive deadline
+ // from the scheduler, but defines it itself.
+ static constexpr base::TimeDelta kConcurrentSweepStepDuration =
+ base::TimeDelta::FromMilliseconds(2);
// Concurrent sweeper doesn't call finalizers - this guarantees that sweeping
// is not called recursively.
ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentSweep);
- Heap().ConcurrentSweep();
+ const bool finished = Heap().AdvanceSweep(
+ ThreadHeap::SweepingType::kConcurrent,
+ base::TimeTicks::Now() + kConcurrentSweepStepDuration);
+ if (!finished) {
+ // Reschedule itself. It is safe even if the task timeouts and reposts
+ // itself while the mutator thread is waiting on CancelAndWait(). The
+ // mutator thread will simply wake up and cancel the newly post task itself.
+ sweeper_scheduler_->ScheduleTask(
+ WTF::CrossThreadBindOnce(&ThreadState::PerformConcurrentSweep,
+ WTF::CrossThreadUnretained(this)));
+ }
}
void ThreadState::ScheduleIncrementalMarkingStep() {
@@ -666,7 +493,7 @@ void ThreadState::ScheduleConcurrentAndLazySweep() {
static constexpr size_t kNumberOfSweepingTasks = 1u;
for (size_t i = 0; i < kNumberOfSweepingTasks; ++i) {
- sweeper_scheduler_.ScheduleTask(
+ sweeper_scheduler_->ScheduleTask(
WTF::CrossThreadBindOnce(&ThreadState::PerformConcurrentSweep,
WTF::CrossThreadUnretained(this)));
}
@@ -822,14 +649,6 @@ void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) {
}
}
-void ThreadState::FinishSnapshot() {
- // Force setting NoGCScheduled to circumvent checkThread()
- // in setGCState().
- gc_state_ = kNoGCScheduled;
- SetGCPhase(GCPhase::kSweeping);
- SetGCPhase(GCPhase::kNone);
-}
-
void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::GCReason reason) {
@@ -847,18 +666,21 @@ void ThreadState::AtomicPauseMarkPrologue(BlinkGC::StackState stack_state,
if (IsMarkingInProgress()) {
// Incremental marking is already in progress. Only update the state
// that is necessary to update.
+ SetGCState(kNoGCScheduled);
+ if (base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking)) {
+ // Stop concurrent markers
+ marker_scheduler_->CancelAndWait();
+ active_markers_ = 0;
+ }
+ DisableIncrementalMarkingBarrier();
current_gc_data_.reason = reason;
current_gc_data_.stack_state = stack_state;
Heap().stats_collector()->UpdateReason(reason);
- SetGCState(kNoGCScheduled);
- DisableIncrementalMarkingBarrier();
} else {
MarkPhasePrologue(stack_state, marking_type, reason);
}
- if (marking_type == BlinkGC::kTakeSnapshot)
- BlinkGCMemoryDumpProvider::Instance()->ClearProcessDumpForCurrentGC();
-
if (stack_state == BlinkGC::kNoHeapPointersOnStack) {
Heap().FlushNotFullyConstructedObjects();
}
@@ -919,7 +741,7 @@ void ThreadState::SynchronizeAndFinishConcurrentSweeping() {
DCHECK(SweepForbidden());
// Wait for concurrent sweepers.
- sweeper_scheduler_.CancelAndWait();
+ sweeper_scheduler_->CancelAndWait();
// Concurrent sweepers may perform some work at the last stage (e.g.
// sweeping the last page and preparing finalizers).
@@ -1149,19 +971,6 @@ void ThreadState::RemoveObserver(BlinkGCObserver* observer) {
observers_.erase(observer);
}
-void ThreadState::ReportMemoryToV8() {
- if (!isolate_ || base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- return;
-
- const size_t current_heap_size =
- heap_->stats_collector()->object_size_in_bytes();
- int64_t diff = static_cast<int64_t>(current_heap_size) -
- static_cast<int64_t>(reported_memory_to_v8_);
- isolate_->AdjustAmountOfExternalAllocatedMemory(diff);
- reported_memory_to_v8_ = current_heap_size;
-}
-
void ThreadState::EnterStaticReferenceRegistrationDisabledScope() {
static_persistent_registration_disabled_count_++;
}
@@ -1185,12 +994,12 @@ void ThreadState::ReleaseStaticPersistentNodes() {
PersistentRegion* persistent_region = GetPersistentRegion();
for (PersistentNode* it : static_persistents)
- persistent_region->ReleasePersistentNode(it);
+ persistent_region->ReleaseNode(it);
}
void ThreadState::FreePersistentNode(PersistentRegion* persistent_region,
PersistentNode* persistent_node) {
- persistent_region->FreePersistentNode(persistent_node);
+ persistent_region->FreeNode(persistent_node);
// Do not allow static persistents to be freed before
// they're all released in releaseStaticPersistentNodes().
//
@@ -1262,12 +1071,21 @@ void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) {
kDefaultIncrementalMarkingStepDuration;
previous_incremental_marking_time_left_ = base::TimeDelta::Max();
MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack,
- BlinkGC::kIncrementalMarking, reason);
+ BlinkGC::kIncrementalAndConcurrentMarking, reason);
{
MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
MarkPhaseVisitRoots();
}
+ DCHECK(Heap().GetV8ReferencesWorklist()->IsGlobalEmpty());
EnableIncrementalMarkingBarrier();
+ if (base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking)) {
+ // No active concurrent markers yet, so it is safe to write to
+ // concurrently_marked_bytes_ without a lock.
+ concurrently_marked_bytes_ = 0;
+ current_gc_data_.visitor->FlushMarkingWorklist();
+ ScheduleConcurrentMarking();
+ }
ScheduleIncrementalMarkingStep();
DCHECK(IsMarkingInProgress());
}
@@ -1287,8 +1105,15 @@ void ThreadState::IncrementalMarkingStep(BlinkGC::StackState stack_state) {
if (stack_state == BlinkGC::kNoHeapPointersOnStack) {
Heap().FlushNotFullyConstructedObjects();
}
- const bool complete = MarkPhaseAdvanceMarking(
+
+ bool complete = MarkPhaseAdvanceMarking(
base::TimeTicks::Now() + next_incremental_marking_step_duration_);
+
+ if (base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking)) {
+ complete = complete && ConcurrentMarkingStep();
+ }
+
if (complete) {
if (IsUnifiedGCMarkingInProgress()) {
// If there are no more objects to mark for unified garbage collections
@@ -1306,6 +1131,16 @@ void ThreadState::IncrementalMarkingStep(BlinkGC::StackState stack_state) {
DCHECK(IsMarkingInProgress());
}
+bool ThreadState::ConcurrentMarkingStep() {
+ current_gc_data_.visitor->FlushMarkingWorklist();
+ if (!Heap().GetMarkingWorklist()->IsGlobalPoolEmpty()) {
+ ScheduleConcurrentMarking();
+ return false;
+ }
+ base::AutoLock lock(active_concurrent_markers_lock_);
+ return active_markers_ == 0;
+}
+
void ThreadState::IncrementalMarkingFinalize() {
DCHECK(IsMarkingInProgress());
DCHECK(!IsUnifiedGCMarkingInProgress());
@@ -1318,7 +1153,9 @@ void ThreadState::IncrementalMarkingFinalize() {
<< "Reason: " << BlinkGC::ToString(current_gc_data_.reason);
// Call into the regular bottleneck instead of the internal version to get
// UMA accounting and allow follow up GCs if necessary.
- CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kIncrementalMarking,
+ DCHECK_EQ(BlinkGC::kIncrementalAndConcurrentMarking,
+ current_gc_data_.marking_type);
+ CollectGarbage(BlinkGC::kNoHeapPointersOnStack, current_gc_data_.marking_type,
BlinkGC::kConcurrentAndLazySweeping, current_gc_data_.reason);
}
@@ -1451,11 +1288,15 @@ class ClearReferencesInDeadObjectsVisitor final
value->Reset();
}
- void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>& value) final {
+ void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) final {
+ CHECK(false) << "Blink does not use v8::TracedGlobal.";
+ }
+
+ void VisitTracedReference(const v8::TracedReference<v8::Value>& value) final {
// TODO(mlippautz): Avoid const_cast after changing the API to allow
- // modificaton of the TracedGlobal handle.
- if (InDeadObject(&const_cast<v8::TracedGlobal<v8::Value>&>(value)))
- const_cast<v8::TracedGlobal<v8::Value>&>(value).Reset();
+ // modificaton of the handle.
+ if (InDeadObject(&const_cast<v8::TracedReference<v8::Value>&>(value)))
+ const_cast<v8::TracedReference<v8::Value>&>(value).Reset();
}
private:
@@ -1486,23 +1327,6 @@ void ThreadState::AtomicPauseSweepAndCompact(
DCHECK(CheckThread());
Heap().PrepareForSweep();
- if (marking_type == BlinkGC::kTakeSnapshot) {
- // Doing lazy sweeping for kTakeSnapshot doesn't make any sense so the
- // sweeping type should always be kEagerSweeping.
- DCHECK_EQ(sweeping_type, BlinkGC::kEagerSweeping);
- Heap().TakeSnapshot(ThreadHeap::SnapshotType::kHeapSnapshot);
-
- // This unmarks all marked objects and marks all unmarked objects dead.
- Heap().MakeConsistentForMutator();
-
- Heap().TakeSnapshot(ThreadHeap::SnapshotType::kFreelistSnapshot);
-
- FinishSnapshot();
- CHECK(!IsSweepingInProgress());
- CHECK_EQ(GetGCState(), kNoGCScheduled);
- return;
- }
-
// We have to set the GCPhase to Sweeping before calling pre-finalizers
// to disallow a GC during the pre-finalizers.
SetGCPhase(GCPhase::kSweeping);
@@ -1584,11 +1408,15 @@ class UnpoisonHandlesVisitor final
VisitSlot(value, sizeof(v8::Persistent<v8::Value>));
}
- void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>& value) final {
+ void VisitTracedGlobalHandle(const v8::TracedGlobal<v8::Value>&) final {
+ CHECK(false) << "Blink does not use v8::TracedGlobal.";
+ }
+
+ void VisitTracedReference(const v8::TracedReference<v8::Value>& value) final {
// TODO(mlippautz): Avoid const_cast after changing the API to allow
- // modificaton of the TracedGlobal handle.
- VisitSlot(&const_cast<v8::TracedGlobal<v8::Value>&>(value),
- sizeof(v8::TracedGlobal<v8::Value>));
+ // modificaton of the handle.
+ VisitSlot(&const_cast<v8::TracedReference<v8::Value>&>(value),
+ sizeof(v8::TracedReference<v8::Value>));
}
private:
@@ -1655,13 +1483,9 @@ void ThreadState::RunAtomicPause(BlinkGC::StackState stack_state,
namespace {
-MarkingVisitor::MarkingMode GetMarkingMode(bool should_compact,
- bool create_snapshot) {
- CHECK(!should_compact || !create_snapshot);
- return (create_snapshot)
- ? MarkingVisitor::kSnapshotMarking
- : (should_compact) ? MarkingVisitor::kGlobalMarkingWithCompaction
- : MarkingVisitor::kGlobalMarking;
+MarkingVisitor::MarkingMode GetMarkingMode(bool should_compact) {
+ return (should_compact) ? MarkingVisitor::kGlobalMarkingWithCompaction
+ : MarkingVisitor::kGlobalMarking;
}
} // namespace
@@ -1672,11 +1496,7 @@ void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
SetGCPhase(GCPhase::kMarking);
Heap().SetupWorklists();
- const bool take_snapshot = marking_type == BlinkGC::kTakeSnapshot;
-
- // Enable compaction if supported and feasible.
const bool compaction_enabled =
- !take_snapshot &&
Heap().Compaction()->ShouldCompact(stack_state, marking_type, reason);
if (compaction_enabled) {
Heap().Compaction()->Initialize(this);
@@ -1686,10 +1506,9 @@ void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
current_gc_data_.visitor =
IsUnifiedGCMarkingInProgress()
? std::make_unique<UnifiedHeapMarkingVisitor>(
- this, GetMarkingMode(compaction_enabled, take_snapshot),
- GetIsolate())
+ this, GetMarkingMode(compaction_enabled), GetIsolate())
: std::make_unique<MarkingVisitor>(
- this, GetMarkingMode(compaction_enabled, take_snapshot));
+ this, GetMarkingMode(compaction_enabled));
current_gc_data_.stack_state = stack_state;
current_gc_data_.marking_type = marking_type;
}
@@ -1752,10 +1571,10 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) {
}
Heap().DestroyMarkingWorklists(current_gc_data_.stack_state);
- // TODO(omerkatz): When migrating to concurrent marking, the following 3
- // lines will need to be wrapped with a loop iterating over all visitors.
+ size_t marked_bytes = concurrently_marked_bytes_;
+
current_gc_data_.visitor->FlushCompactionWorklists();
- const size_t marked_bytes = current_gc_data_.visitor->marked_bytes();
+ marked_bytes += current_gc_data_.visitor->marked_bytes();
current_gc_data_.visitor.reset();
Heap().stats_collector()->NotifyMarkingCompleted(marked_bytes);
@@ -1773,8 +1592,6 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) {
}
void ThreadState::VerifyMarking(BlinkGC::MarkingType marking_type) {
- DCHECK_NE(BlinkGC::kTakeSnapshot, marking_type);
-
if (IsVerifyMarkingEnabled())
Heap().VerifyMarking();
}
@@ -1812,4 +1629,72 @@ void ThreadState::UpdateIncrementalMarkingStepDuration() {
previous_incremental_marking_time_left_ = time_left;
}
+void ThreadState::ScheduleConcurrentMarking() {
+ base::AutoLock lock(active_concurrent_markers_lock_);
+
+ if (active_markers_ > 0) {
+ // Concurrent markers are already running, should not run them again
+ return;
+ }
+
+ DCHECK(base::FeatureList::IsEnabled(
+ blink::features::kBlinkHeapConcurrentMarking));
+
+ // Number of concurrent marking tasks to start. The check below verifies
+ // that the marking worklist has enough private segments for all tasks.
+ //
+ // TODO(omerkatz): kNumberOfMarkingTasks should be set heuristically instead
+ // of a constant.
+ static constexpr int kNumberOfConcurrentMarkingTasks = 1u;
+ DCHECK_LT(kNumberOfConcurrentMarkingTasks,
+ Heap().GetMarkingWorklist()->num_tasks());
+
+ active_markers_ = kNumberOfConcurrentMarkingTasks;
+
+ for (int i = 0; i < kNumberOfConcurrentMarkingTasks; ++i) {
+ marker_scheduler_->ScheduleTask(
+ WTF::CrossThreadBindOnce(&ThreadState::PerformConcurrentMark,
+ WTF::CrossThreadUnretained(this), i));
+ }
+}
+
+void ThreadState::PerformConcurrentMark(int concurrent_marker_id) {
+ VLOG(2) << "[state:" << this << "] [threadid:" << CurrentThread() << "] "
+ << "ConcurrentMark";
+ ThreadHeapStatsCollector::EnabledConcurrentScope stats_scope(
+ Heap().stats_collector(), ThreadHeapStatsCollector::kConcurrentMark);
+
+ const int task_id =
+ WorklistTaskId::ConcurrentThreadBase + concurrent_marker_id;
+ std::unique_ptr<ConcurrentMarkingVisitor> concurrent_visitor =
+ IsUnifiedGCMarkingInProgress()
+ ? std::make_unique<ConcurrentUnifiedHeapMarkingVisitor>(
+ this, GetMarkingMode(Heap().Compaction()->IsCompacting()),
+ GetIsolate(), task_id)
+ : std::make_unique<ConcurrentMarkingVisitor>(
+ this, GetMarkingMode(Heap().Compaction()->IsCompacting()),
+ task_id);
+
+ const bool finished = Heap().AdvanceConcurrentMarking(
+ concurrent_visitor.get(),
+ base::TimeTicks::Now() + kConcurrentMarkingStepDuration);
+
+ concurrent_visitor->FlushWorklists();
+ {
+ base::AutoLock lock(active_concurrent_markers_lock_);
+ // When marking is done, flush visitor worklists and decrement number of
+ // active markers so we know how many markers are left
+ concurrently_marked_bytes_ += concurrent_visitor->marked_bytes();
+ if (finished) {
+ --active_markers_;
+ return;
+ }
+ }
+
+ // Reschedule this marker
+ marker_scheduler_->ScheduleTask(WTF::CrossThreadBindOnce(
+ &ThreadState::PerformConcurrentMark, WTF::CrossThreadUnretained(this),
+ concurrent_marker_id));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.h b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
index 2a12bf573be..7fbff6794bc 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.h
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
@@ -34,12 +34,11 @@
#include <memory>
#include "base/macros.h"
+#include "base/synchronization/lock.h"
#include "third_party/blink/renderer/platform/heap/atomic_entry_flag.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
-#include "third_party/blink/renderer/platform/heap/cancelable_task_scheduler.h"
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/public/rail_mode_observer.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -59,9 +58,9 @@ namespace blink {
namespace incremental_marking_test {
class IncrementalMarkingScope;
-class IncrementalMarkingTestDriver;
} // namespace incremental_marking_test
+class CancelableTaskScheduler;
class MarkingVisitor;
class PersistentNode;
class PersistentRegion;
@@ -126,7 +125,7 @@ class PLATFORM_EXPORT BlinkGCObserver {
ThreadState* thread_state_;
};
-class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
+class PLATFORM_EXPORT ThreadState final {
USING_FAST_MALLOC(ThreadState);
public:
@@ -182,6 +181,8 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
class LsanDisabledScope;
class MainThreadGCForbiddenScope;
class NoAllocationScope;
+ class StatisticsCollector;
+ struct Statistics;
class SweepForbiddenScope;
using V8TraceRootsCallback = void (*)(v8::Isolate*, Visitor*);
@@ -199,12 +200,12 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
return incremental_marking_flag_.MightBeEntered();
}
- static void AttachMainThread();
+ static ThreadState* AttachMainThread();
// Associate ThreadState object with the current thread. After this
// call thread can start using the garbage collected heap infrastructure.
// It also has to periodically check for safepoints.
- static void AttachCurrentThread();
+ static ThreadState* AttachCurrentThread();
// Disassociate attached ThreadState from the current thread. The thread
// can no longer use the garbage collected heap after this call.
@@ -253,7 +254,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
void SchedulePreciseGC();
void ScheduleIncrementalGC(BlinkGC::GCReason);
- void ScheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType);
void ScheduleForcedGCForTesting();
void ScheduleGCIfNeeded();
void WillStartV8GC(BlinkGC::V8GCType);
@@ -297,8 +297,13 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
void EnableIncrementalMarkingBarrier();
void DisableIncrementalMarkingBarrier();
+ // Returns true if concurrent marking is finished (i.e. all current threads
+ // terminated and the worklist is empty)
+ bool ConcurrentMarkingStep();
+ void ScheduleConcurrentMarking();
+ void PerformConcurrentMark(int);
+
void CompleteSweep();
- void FinishSnapshot();
void NotifySweepDone();
void PostSweep();
@@ -341,19 +346,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
return weak_persistent_region_.get();
}
- struct GCSnapshotInfo {
- STACK_ALLOCATED();
-
- public:
- GCSnapshotInfo(wtf_size_t num_object_types);
-
- // Map from gcInfoIndex (vector-index) to count/size.
- Vector<int> live_count;
- Vector<int> dead_count;
- Vector<size_t> live_size;
- Vector<size_t> dead_size;
- };
-
void RegisterStaticPersistentNode(PersistentNode*);
void ReleaseStaticPersistentNodes();
void FreePersistentNode(PersistentRegion*, PersistentNode*);
@@ -386,9 +378,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
return current_gc_data_.visitor.get();
}
- // Implementation for RAILModeObserver
- void OnRAILModeChanged(RAILMode new_mode) override;
-
// Returns true if the marking verifier is enabled, false otherwise.
bool IsVerifyMarkingEnabled() const;
@@ -413,7 +402,7 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
intptr_t* end_of_stack);
ThreadState();
- ~ThreadState() override;
+ ~ThreadState();
void EnterNoAllocationScope() { no_allocation_count_++; }
void LeaveNoAllocationScope() { no_allocation_count_--; }
@@ -502,33 +491,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
// See |DetachCurrentThread|.
void RunTerminationGC();
- // ShouldForceConservativeGC
- // implements the heuristics that are used to determine when to collect
- // garbage.
- // If shouldForceConservativeGC returns true, we force the garbage
- // collection immediately. Otherwise, if should*GC returns true, we
- // record that we should garbage collect the next time we return
- // to the event loop. If both return false, we don't need to
- // collect garbage at this point.
- bool ShouldForceConservativeGC();
- // V8 minor or major GC is likely to drop a lot of references to objects
- // on Oilpan's heap. We give a chance to schedule a GC.
- bool ShouldScheduleV8FollowupGC();
-
- // Internal helpers to handle memory pressure conditions.
-
- // Returns true if memory use is in a near-OOM state
- // (aka being under "memory pressure".)
- bool ShouldForceMemoryPressureGC();
-
- size_t EstimatedLiveSize(size_t current_size, size_t size_at_last_gc);
- size_t TotalMemorySize();
- double HeapGrowingRate();
- double PartitionAllocGrowingRate();
- bool JudgeGCThreshold(size_t allocated_object_size_threshold,
- size_t total_memory_size_threshold,
- double heap_growing_rate_threshold);
-
void RunScheduledGC(BlinkGC::StackState);
void UpdateIncrementalMarkingStepDuration();
@@ -537,8 +499,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
void InvokePreFinalizers();
- void ReportMemoryToV8();
-
// Adds the given observer to the ThreadState's observer list. This doesn't
// take ownership of the argument. The argument must not be null. The argument
// must not be registered before calling this.
@@ -613,7 +573,6 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
// have to clear before initiating LSan's leak detection.
HashSet<PersistentNode*> static_persistents_;
- size_t reported_memory_to_v8_ = 0;
int gc_age_ = 0;
struct GCData {
@@ -624,11 +583,16 @@ class PLATFORM_EXPORT ThreadState final : private RAILModeObserver {
};
GCData current_gc_data_;
- CancelableTaskScheduler sweeper_scheduler_;
+ std::unique_ptr<CancelableTaskScheduler> marker_scheduler_;
+ uint8_t active_markers_ = 0;
+ base::Lock active_concurrent_markers_lock_;
+ size_t concurrently_marked_bytes_ = 0;
+
+ std::unique_ptr<CancelableTaskScheduler> sweeper_scheduler_;
friend class BlinkGCObserver;
friend class incremental_marking_test::IncrementalMarkingScope;
- friend class incremental_marking_test::IncrementalMarkingTestDriver;
+ friend class IncrementalMarkingTestDriver;
friend class HeapAllocator;
template <typename T>
friend class PrefinalizerRegistration;
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.cc b/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.cc
new file mode 100644
index 00000000000..90a684cb1c7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.cc
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/heap/thread_state_statistics.h"
+
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
+
+namespace blink {
+
+ThreadState::Statistics ThreadState::StatisticsCollector::CollectStatistics(
+ Statistics::DetailLevel detail_level) const {
+ Statistics stats;
+ stats.detail_level = detail_level;
+ if (detail_level == Statistics::kBrief) {
+ ThreadHeapStatsCollector* stats_collector =
+ thread_state_->Heap().stats_collector();
+ stats.committed_size_bytes = stats_collector->allocated_space_bytes();
+ stats.used_size_bytes = stats_collector->object_size_in_bytes();
+ return stats;
+ }
+
+ thread_state_->CompleteSweep();
+
+ // Detailed statistics.
+ thread_state_->Heap().CollectStatistics(&stats);
+ stats.detail_level = Statistics::kDetailed;
+ return stats;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.h b/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.h
new file mode 100644
index 00000000000..c2a3a6ff7b4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state_statistics.h
@@ -0,0 +1,67 @@
+// 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_HEAP_THREAD_STATE_STATISTICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_STATISTICS_H_
+
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+
+namespace blink {
+
+struct PLATFORM_EXPORT ThreadState::Statistics final {
+ enum DetailLevel : uint32_t {
+ kBrief,
+ kDetailed,
+ };
+
+ struct ObjectStatistics {
+ size_t num_types = 0;
+ Vector<std::string> type_name;
+ Vector<size_t> type_count;
+ Vector<size_t> type_bytes;
+ };
+
+ struct PageStatistics {
+ size_t committed_size_bytes = 0;
+ size_t used_size_bytes = 0;
+ };
+
+ struct FreeListStatistics {
+ Vector<size_t> bucket_size;
+ Vector<size_t> free_count;
+ Vector<size_t> free_size;
+ };
+
+ struct ArenaStatistics {
+ std::string name;
+ size_t committed_size_bytes = 0;
+ size_t used_size_bytes = 0;
+ Vector<PageStatistics> page_stats;
+ FreeListStatistics free_list_stats;
+ // Only filled when NameClient::HideInternalName() is false.
+ ObjectStatistics object_stats;
+ };
+
+ size_t committed_size_bytes = 0;
+ size_t used_size_bytes = 0;
+ DetailLevel detail_level;
+
+ // Only filled when detail_level is kDetailed.
+ Vector<ArenaStatistics> arena_stats;
+};
+
+class PLATFORM_EXPORT ThreadState::StatisticsCollector {
+ public:
+ explicit StatisticsCollector(ThreadState* thread_state)
+ : thread_state_(thread_state) {}
+
+ ThreadState::Statistics CollectStatistics(Statistics::DetailLevel) const;
+
+ private:
+ ThreadState* const thread_state_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_STATISTICS_H_
diff --git a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
index ac051c106a1..cfbd628a60c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
@@ -580,19 +580,18 @@ struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
// Nodes used by LinkedHashSet. Again we need two versions to disambiguate the
// template.
-template <typename Value, typename Allocator, typename Traits>
+template <typename Value, typename Traits>
struct TraceInCollectionTrait<kNoWeakHandling,
- LinkedHashSetNode<Value, Allocator>,
+ LinkedHashSetNode<Value>,
Traits> {
- static bool IsAlive(LinkedHashSetNode<Value, Allocator>& self) {
+ static bool IsAlive(LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kNoWeakHandling, Value,
typename Traits::ValueTraits>::IsAlive(self.value_);
}
template <typename VisitorDispatcher>
- static bool Trace(VisitorDispatcher visitor,
- LinkedHashSetNode<Value, Allocator>& self) {
+ static bool Trace(VisitorDispatcher visitor, LinkedHashSetNode<Value>& self) {
static_assert(IsTraceableInCollectionTrait<Traits>::value ||
Traits::kWeakHandlingFlag == WTF::kWeakHandling,
"T should not be traced");
@@ -602,19 +601,16 @@ struct TraceInCollectionTrait<kNoWeakHandling,
}
};
-template <typename Value, typename Allocator, typename Traits>
-struct TraceInCollectionTrait<kWeakHandling,
- LinkedHashSetNode<Value, Allocator>,
- Traits> {
- static bool IsAlive(LinkedHashSetNode<Value, Allocator>& self) {
+template <typename Value, typename Traits>
+struct TraceInCollectionTrait<kWeakHandling, LinkedHashSetNode<Value>, Traits> {
+ static bool IsAlive(LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kWeakHandling, Value,
typename Traits::ValueTraits>::IsAlive(self.value_);
}
template <typename VisitorDispatcher>
- static bool Trace(VisitorDispatcher visitor,
- LinkedHashSetNode<Value, Allocator>& self) {
+ static bool Trace(VisitorDispatcher visitor, LinkedHashSetNode<Value>& self) {
return TraceInCollectionTrait<
kWeakHandling, Value, typename Traits::ValueTraits>::Trace(visitor,
self.value_);
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
index f9bc2267c3e..9df99b39c66 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/heap/unified_heap_controller.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"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
@@ -29,15 +31,11 @@ constexpr BlinkGC::StackState ToBlinkGCStackState(
UnifiedHeapController::UnifiedHeapController(ThreadState* thread_state)
: thread_state_(thread_state) {
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- thread_state->Heap().stats_collector()->RegisterObserver(this);
+ thread_state->Heap().stats_collector()->RegisterObserver(this);
}
UnifiedHeapController::~UnifiedHeapController() {
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling))
- thread_state_->Heap().stats_collector()->UnregisterObserver(this);
+ thread_state_->Heap().stats_collector()->UnregisterObserver(this);
}
void UnifiedHeapController::TracePrologue(
@@ -48,7 +46,7 @@ void UnifiedHeapController::TracePrologue(
// Be conservative here as a new garbage collection gets started right away.
thread_state_->FinishIncrementalMarkingIfRunning(
- BlinkGC::kHeapPointersOnStack, BlinkGC::kIncrementalMarking,
+ BlinkGC::kHeapPointersOnStack, BlinkGC::kIncrementalAndConcurrentMarking,
BlinkGC::kConcurrentAndLazySweeping,
thread_state_->current_gc_data_.reason);
@@ -68,10 +66,11 @@ void UnifiedHeapController::EnterFinalPause(EmbedderStackState stack_state) {
ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope(
thread_state_->Heap().stats_collector());
thread_state_->AtomicPauseMarkPrologue(
- ToBlinkGCStackState(stack_state), BlinkGC::kIncrementalMarking,
+ ToBlinkGCStackState(stack_state),
+ BlinkGC::kIncrementalAndConcurrentMarking,
thread_state_->current_gc_data_.reason);
thread_state_->AtomicPauseMarkRoots(ToBlinkGCStackState(stack_state),
- BlinkGC::kIncrementalMarking,
+ BlinkGC::kIncrementalAndConcurrentMarking,
thread_state_->current_gc_data_.reason);
}
@@ -81,18 +80,17 @@ void UnifiedHeapController::TraceEpilogue(
{
ThreadHeapStatsCollector::BlinkGCInV8Scope nested_scope(
thread_state_->Heap().stats_collector());
- thread_state_->AtomicPauseMarkEpilogue(BlinkGC::kIncrementalMarking);
+ thread_state_->AtomicPauseMarkEpilogue(
+ BlinkGC::kIncrementalAndConcurrentMarking);
thread_state_->AtomicPauseSweepAndCompact(
- BlinkGC::kIncrementalMarking, BlinkGC::kConcurrentAndLazySweeping);
-
- if (base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling)) {
- ThreadHeapStatsCollector* const stats_collector =
- thread_state_->Heap().stats_collector();
- summary->allocated_size =
- static_cast<size_t>(stats_collector->marked_bytes());
- summary->time = stats_collector->marking_time_so_far().InMillisecondsF();
- }
+ BlinkGC::kIncrementalAndConcurrentMarking,
+ BlinkGC::kConcurrentAndLazySweeping);
+
+ ThreadHeapStatsCollector* const stats_collector =
+ thread_state_->Heap().stats_collector();
+ summary->allocated_size =
+ static_cast<size_t>(stats_collector->marked_bytes());
+ summary->time = stats_collector->marking_time_so_far().InMillisecondsF();
buffered_allocated_size_ = 0;
}
thread_state_->AtomicPauseEpilogue();
@@ -147,16 +145,17 @@ bool UnifiedHeapController::IsTracingDone() {
return is_tracing_done_;
}
-bool UnifiedHeapController::IsRootForNonTracingGCInternal(
- const v8::TracedGlobal<v8::Value>& handle) {
+bool UnifiedHeapController::IsRootForNonTracingGC(
+ const v8::TracedReference<v8::Value>& handle) {
const uint16_t class_id = handle.WrapperClassId();
- // Stand-alone TracedGlobal reference or kCustomWrappableId. Keep as root as
+ // Stand-alone reference or kCustomWrappableId. Keep as root as
// we don't know better.
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
return true;
- const v8::TracedGlobal<v8::Object>& traced = handle.As<v8::Object>();
+ const v8::TracedReference<v8::Object>& traced =
+ handle.template As<v8::Object>();
if (ToWrapperTypeInfo(traced)->IsActiveScriptWrappable() &&
ToScriptWrappable(traced)->HasPendingActivity()) {
return true;
@@ -170,7 +169,7 @@ bool UnifiedHeapController::IsRootForNonTracingGCInternal(
}
void UnifiedHeapController::ResetHandleInNonTracingGC(
- const v8::TracedGlobal<v8::Value>& handle) {
+ const v8::TracedReference<v8::Value>& handle) {
const uint16_t class_id = handle.WrapperClassId();
// Only consider handles that have not been treated as roots, see
// IsRootForNonTracingGCInternal.
@@ -178,21 +177,32 @@ void UnifiedHeapController::ResetHandleInNonTracingGC(
class_id != WrapperTypeInfo::kObjectClassId)
return;
- const v8::TracedGlobal<v8::Object>& traced = handle.As<v8::Object>();
- ToScriptWrappable(traced)->UnsetWrapperIfAny();
+ // Clearing the wrapper below adjusts the DOM wrapper store which may
+ // re-allocate its backing. We have to avoid report memory to V8 as that may
+ // trigger GC during GC.
+ ThreadState::GCForbiddenScope gc_forbidden(thread_state());
+ const v8::TracedReference<v8::Object>& traced = handle.As<v8::Object>();
+ bool success = DOMWrapperWorld::UnsetSpecificWrapperIfSet(
+ ToScriptWrappable(traced), traced);
+ // Since V8 found a handle, Blink needs to find it as well when trying to
+ // remove it.
+ CHECK(success);
}
bool UnifiedHeapController::IsRootForNonTracingGC(
const v8::TracedGlobal<v8::Value>& handle) {
- return IsRootForNonTracingGCInternal(handle);
+ CHECK(false) << "Blink does not use v8::TracedGlobal.";
+ return false;
}
void UnifiedHeapController::ReportBufferedAllocatedSizeIfPossible() {
- DCHECK(base::FeatureList::IsEnabled(
- blink::features::kBlinkHeapUnifiedGCScheduling));
- // Reported from a recursive sweeping call.
- if (thread_state()->IsSweepingInProgress() &&
- thread_state()->SweepForbidden()) {
+ // Avoid reporting to V8 in the following conditions as that may trigger GC
+ // finalizations where not allowed.
+ // - Recursive sweeping.
+ // - GC forbidden scope.
+ if ((thread_state()->IsSweepingInProgress() &&
+ thread_state()->SweepForbidden()) ||
+ thread_state()->IsGCForbidden()) {
return;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.h b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.h
index f8ca95c0020..5ec55f91db5 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.h
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_controller.h
@@ -45,8 +45,9 @@ class PLATFORM_EXPORT UnifiedHeapController final
void RegisterV8References(const std::vector<std::pair<void*, void*>>&) final;
bool AdvanceTracing(double) final;
bool IsTracingDone() final;
+ bool IsRootForNonTracingGC(const v8::TracedReference<v8::Value>&) final;
bool IsRootForNonTracingGC(const v8::TracedGlobal<v8::Value>&) final;
- void ResetHandleInNonTracingGC(const v8::TracedGlobal<v8::Value>&) final;
+ void ResetHandleInNonTracingGC(const v8::TracedReference<v8::Value>&) final;
ThreadState* thread_state() const { return thread_state_; }
@@ -59,9 +60,6 @@ class PLATFORM_EXPORT UnifiedHeapController final
void DecreaseAllocatedSpace(size_t) final {}
private:
- static bool IsRootForNonTracingGCInternal(
- const v8::TracedGlobal<v8::Value>& handle);
-
void ReportBufferedAllocatedSizeIfPossible();
ThreadState* const thread_state_;
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
index 13dc902049a..69523852e26 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.cc
@@ -20,9 +20,9 @@ UnifiedHeapMarkingVisitorBase::UnifiedHeapMarkingVisitorBase(
int task_id)
: isolate_(isolate),
controller_(thread_state->unified_heap_controller()),
- task_id_(task_id),
v8_references_worklist_(thread_state->Heap().GetV8ReferencesWorklist(),
- task_id) {
+ task_id),
+ task_id_(task_id) {
DCHECK(controller_);
}
@@ -31,7 +31,7 @@ void UnifiedHeapMarkingVisitorBase::VisitImpl(
if (v8_reference.Get().IsEmpty())
return;
DCHECK(isolate_);
- if (task_id_ != WorklistTaskId::MainThread) {
+ if (task_id_ != WorklistTaskId::MutatorThread) {
// This is a temporary solution. Pushing directly from concurrent threads
// to V8 marking worklist will currently result in data races. This
// solution guarantees correctness until we implement a long-term solution
@@ -43,18 +43,13 @@ void UnifiedHeapMarkingVisitorBase::VisitImpl(
controller_->RegisterEmbedderReference(v8_reference.Get());
}
-void UnifiedHeapMarkingVisitorBase::FlushV8References() {
- if (task_id_ != WorklistTaskId::MainThread)
- v8_references_worklist_.FlushToGlobal();
-}
-
UnifiedHeapMarkingVisitor::UnifiedHeapMarkingVisitor(ThreadState* thread_state,
MarkingMode mode,
v8::Isolate* isolate)
: MarkingVisitor(thread_state, mode),
UnifiedHeapMarkingVisitorBase(thread_state,
isolate,
- WorklistTaskId::MainThread) {}
+ WorklistTaskId::MutatorThread) {}
void UnifiedHeapMarkingVisitor::WriteBarrier(
const TraceWrapperV8Reference<v8::Value>& object) {
@@ -92,4 +87,9 @@ ConcurrentUnifiedHeapMarkingVisitor::ConcurrentUnifiedHeapMarkingVisitor(
: ConcurrentMarkingVisitor(thread_state, mode, task_id),
UnifiedHeapMarkingVisitorBase(thread_state, isolate, task_id) {}
+void ConcurrentUnifiedHeapMarkingVisitor::FlushWorklists() {
+ ConcurrentMarkingVisitor::FlushWorklists();
+ v8_references_worklist_.FlushToGlobal();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
index 77cab26c16f..d0bb85ce74c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h
@@ -27,18 +27,15 @@ class PLATFORM_EXPORT UnifiedHeapMarkingVisitorBase {
// Visitation methods that announce reachable wrappers to V8.
void VisitImpl(const TraceWrapperV8Reference<v8::Value>&);
- // Flush all V8 references in the private segments to the global pool.
- void FlushV8References();
-
protected:
UnifiedHeapMarkingVisitorBase(ThreadState*, v8::Isolate*, int);
v8::Isolate* const isolate_;
v8::EmbedderHeapTracer* const controller_;
+ V8ReferencesWorklist::View v8_references_worklist_;
private:
int task_id_;
- V8ReferencesWorklist::View v8_references_worklist_;
DISALLOW_COPY_AND_ASSIGN(UnifiedHeapMarkingVisitorBase);
};
@@ -81,6 +78,8 @@ class PLATFORM_EXPORT ConcurrentUnifiedHeapMarkingVisitor
VisitImpl(v);
}
+ void FlushWorklists() override;
+
private:
DISALLOW_COPY_AND_ASSIGN(ConcurrentUnifiedHeapMarkingVisitor);
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/worklist.h b/chromium/third_party/blink/renderer/platform/heap/worklist.h
index 724b91fa1de..1e516113262 100644
--- a/chromium/third_party/blink/renderer/platform/heap/worklist.h
+++ b/chromium/third_party/blink/renderer/platform/heap/worklist.h
@@ -30,7 +30,7 @@ namespace blink {
//
// Work stealing is best effort, i.e., there is no way to inform other tasks
// of the need of items.
-template <typename _EntryType, int segment_size, int max_tasks = 1>
+template <typename _EntryType, int segment_size, int max_tasks = 2>
class Worklist {
USING_FAST_MALLOC(Worklist);
using WorklistType = Worklist<_EntryType, segment_size, max_tasks>;
@@ -190,6 +190,8 @@ class Worklist {
global_pool_.MergeList(pair.first, pair.second);
}
+ int num_tasks() const { return num_tasks_; }
+
private:
FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentCreate);
FRIEND_TEST_ALL_PREFIXES(WorklistTest, SegmentPush);
diff --git a/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc b/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc
new file mode 100644
index 00000000000..2cc9848ddbd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/write_barrier_perftest.cc
@@ -0,0 +1,79 @@
+// 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.
+
+#include "base/callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_test.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+
+namespace blink {
+
+class WriteBarrierPerfTest : public TestSupportingGC {};
+
+namespace {
+
+class PerfDummyObject : public GarbageCollected<PerfDummyObject> {
+ public:
+ PerfDummyObject() = default;
+ virtual void Trace(Visitor*) {}
+};
+
+base::TimeDelta TimedRun(base::RepeatingCallback<void()> callback) {
+ const base::TimeTicks start = base::TimeTicks::Now();
+ callback.Run();
+ return base::TimeTicks::Now() - start;
+}
+
+} // namespace
+
+TEST_F(WriteBarrierPerfTest, MemberWritePerformance) {
+ // Setup.
+ constexpr wtf_size_t kNumElements = 100000;
+ Persistent<HeapVector<Member<PerfDummyObject>>> holder(
+ MakeGarbageCollected<HeapVector<Member<PerfDummyObject>>>());
+ for (wtf_size_t i = 0; i < kNumElements; ++i) {
+ holder->push_back(MakeGarbageCollected<PerfDummyObject>());
+ }
+ PreciselyCollectGarbage();
+ // Benchmark.
+ base::RepeatingCallback<void()> benchmark = base::BindRepeating(
+ [](const Persistent<HeapVector<Member<PerfDummyObject>>>& holder) {
+ for (wtf_size_t i = 0; i < kNumElements / 2; ++i) {
+ (*holder)[i].Swap((*holder)[kNumElements / 2 + i]);
+ }
+ },
+ holder);
+
+ // During GC.
+ IncrementalMarkingTestDriver driver(ThreadState::Current());
+ driver.Start();
+ base::TimeDelta during_gc_duration = TimedRun(benchmark);
+ driver.FinishSteps();
+ PreciselyCollectGarbage();
+
+ // Outside GC.
+ base::TimeDelta outside_gc_duration = TimedRun(benchmark);
+
+ // Cleanup.
+ holder.Clear();
+ PreciselyCollectGarbage();
+
+ // Reporting.
+ perf_test::PrintResult(
+ "WriteBarrierPerfTest", " writes during GC", "",
+ static_cast<double>(kNumElements) / during_gc_duration.InMillisecondsF(),
+ "writes/ms", true);
+ perf_test::PrintResult(
+ "WriteBarrierPerfTest", " writes outside GC", "",
+ static_cast<double>(kNumElements) / outside_gc_duration.InMillisecondsF(),
+ "writes/ms", true);
+ perf_test::PrintResult("WriteBarrierPerfTest", " relative speed difference",
+ "",
+ during_gc_duration.InMillisecondsF() /
+ outside_gc_duration.InMillisecondsF(),
+ "times", true);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/DEPS b/chromium/third_party/blink/renderer/platform/image-decoders/DEPS
index c40be9e6748..8bcb95131bd 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/DEPS
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+third_party/blink/renderer/platform/image-decoders",
# Dependencies.
+ "+base/bits.h",
"+cc/paint/image_animation_count.h",
"+third_party/blink/renderer/platform/geometry",
"+third_party/blink/renderer/platform/graphics",
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 be5912724a5..0571d11a1c5 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
@@ -32,9 +32,30 @@
#include "third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "ui/gfx/geometry/size.h"
namespace blink {
+namespace {
+
+cc::ImageType FileExtensionToImageType(String image_extension) {
+ if (image_extension == "png")
+ return cc::ImageType::kPNG;
+ if (image_extension == "jpg")
+ return cc::ImageType::kJPEG;
+ if (image_extension == "webp")
+ return cc::ImageType::kWEBP;
+ if (image_extension == "gif")
+ return cc::ImageType::kGIF;
+ if (image_extension == "ico")
+ return cc::ImageType::kICO;
+ if (image_extension == "bmp")
+ return cc::ImageType::kBMP;
+ return cc::ImageType::kInvalid;
+}
+
+} // namespace
+
const size_t ImageDecoder::kNoDecodedImageByteLimit;
inline bool MatchesJPEGSignature(const char* contents) {
@@ -232,6 +253,17 @@ ImageDecoder::CompressionFormat ImageDecoder::GetCompressionFormat(
return kUndefinedFormat;
}
+cc::ImageHeaderMetadata ImageDecoder::MakeMetadataForDecodeAcceleration()
+ const {
+ DCHECK(IsDecodedSizeAvailable());
+ cc::ImageHeaderMetadata image_metadata{};
+ image_metadata.image_type = FileExtensionToImageType(FilenameExtension());
+ image_metadata.yuv_subsampling = GetYUVSubsampling();
+ image_metadata.image_size = static_cast<gfx::Size>(size_);
+ image_metadata.has_embedded_color_profile = HasEmbeddedColorProfile();
+ return image_metadata;
+}
+
size_t ImageDecoder::FrameCount() {
const size_t old_size = frame_buffer_cache_.size();
const size_t new_size = DecodeFrameCount();
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 2b993033116..274c73c966c 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
@@ -33,6 +33,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
#include "third_party/blink/renderer/platform/image-decoders/image_animation.h"
#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
@@ -243,6 +244,12 @@ class PLATFORM_EXPORT ImageDecoder {
return SkYUVColorSpace::kIdentity_SkYUVColorSpace;
}
+ // Returns the information required to decide whether or not hardware
+ // acceleration can be used to decode this image. Callers of this function
+ // must ensure the header was successfully parsed prior to calling this
+ // method, i.e., IsDecodedSizeAvailable() must return true.
+ virtual cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const;
+
// This will only differ from size() for ICO (where each frame is a
// different icon) or other formats where different frames are different
// sizes. This does NOT differ from size() for GIF or WebP, since
@@ -357,11 +364,13 @@ class PLATFORM_EXPORT ImageDecoder {
frame_buffer_cache_[0].SetMemoryAllocator(allocator);
}
- virtual bool CanDecodeToYUV() { return false; }
+ virtual bool CanDecodeToYUV() { return allow_decode_to_yuv_; }
// Should only be called if CanDecodeToYuv() returns true, in which case
// the subclass of ImageDecoder must override this method.
virtual void DecodeToYUV() { NOTREACHED(); }
- virtual void SetImagePlanes(std::unique_ptr<ImagePlanes>) {}
+ void SetImagePlanes(std::unique_ptr<ImagePlanes> image_planes) {
+ image_planes_ = std::move(image_planes);
+ }
protected:
ImageDecoder(AlphaOption alpha_option,
@@ -372,6 +381,7 @@ class PLATFORM_EXPORT ImageDecoder {
high_bit_depth_decoding_option_(high_bit_depth_decoding_option),
color_behavior_(color_behavior),
max_decoded_bytes_(max_decoded_bytes),
+ allow_decode_to_yuv_(false),
purge_aggressively_(false) {}
// Calculates the most recent frame whose image data may be needed in
@@ -488,7 +498,19 @@ class PLATFORM_EXPORT ImageDecoder {
frame_status == ImageFrame::kFrameComplete;
}
+ // Note that |allow_decode_to_yuv_| being true merely means that the
+ // ImageDecoder supports decoding to YUV. Other layers higher in the
+ // stack (the PaintImageGenerator, ImageFrameGenerator, or cache) may
+ // decline to go down the YUV path.
+ bool allow_decode_to_yuv_;
+ std::unique_ptr<ImagePlanes> image_planes_;
+
private:
+ // The YUV subsampling of the image.
+ virtual cc::YUVSubsampling GetYUVSubsampling() const {
+ return cc::YUVSubsampling::kUnknown;
+ }
+
// Some code paths compute the size of the image as "width * height * 4 or 8"
// and return it as a (signed) int. Avoid overflow.
inline bool SizeCalculationMayOverflow(unsigned width,
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 99b5cd14ee3..600c03c6218 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
@@ -122,6 +122,10 @@ bool ImageFrame::AllocatePixelData(int new_width,
sk_sp<SkColorSpace> color_space) {
// AllocatePixelData() should only be called once.
DCHECK(!Width() && !Height());
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ if (new_width > 1000 || new_height > 1000)
+ return false;
+#endif
SkImageInfo info = SkImageInfo::MakeN32(
new_width, new_height,
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 9290eccbc5b..142bc4d5eac 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
@@ -39,6 +39,8 @@
#include <memory>
+#include "base/bits.h"
+#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -81,6 +83,39 @@ const int exifMarker = JPEG_APP0 + 1;
// JPEG only supports a denominator of 8.
const unsigned g_scale_denominator = 8;
+// Extracts the YUV subsampling format of an image given |info| which is assumed
+// to have gone through a jpeg_read_header() call.
+cc::YUVSubsampling YuvSubsampling(const jpeg_decompress_struct& info) {
+ if (info.jpeg_color_space == JCS_YCbCr && info.num_components == 3 &&
+ info.comp_info && info.comp_info[1].h_samp_factor == 1 &&
+ info.comp_info[1].v_samp_factor == 1 &&
+ info.comp_info[2].h_samp_factor == 1 &&
+ info.comp_info[2].v_samp_factor == 1) {
+ const int h = info.comp_info[0].h_samp_factor;
+ const int v = info.comp_info[0].v_samp_factor;
+ if (v == 1) {
+ switch (h) {
+ case 1:
+ return cc::YUVSubsampling::k444;
+ case 2:
+ return cc::YUVSubsampling::k422;
+ case 4:
+ return cc::YUVSubsampling::k411;
+ }
+ } else if (v == 2) {
+ switch (h) {
+ case 1:
+ return cc::YUVSubsampling::k440;
+ case 2:
+ return cc::YUVSubsampling::k420;
+ case 4:
+ return cc::YUVSubsampling::k410;
+ }
+ }
+ }
+ return cc::YUVSubsampling::kUnknown;
+}
+
// Extracts the JPEG color space of an image for UMA purposes given |info| which
// is assumed to have gone through a jpeg_read_header(). When the color space is
// YCbCr, we also extract the chroma subsampling. The caveat is that the
@@ -101,39 +136,23 @@ blink::BitmapImageMetrics::JpegColorSpace ExtractUMAJpegColorSpace(
case JCS_YCCK:
return blink::BitmapImageMetrics::JpegColorSpace::kYCCK;
case JCS_YCbCr:
- // The following logic is mostly reused from YuvSubsampling(). However,
- // here we use |info.comp_info| instead of |info.cur_comp_info| to read
- // the components from the SOF instead of the first scan. We also don't
- // care about |info.scale_denom|.
- // TODO: can we use this same logic in YuvSubsampling()?
- if (info.num_components == 3 && info.comp_info &&
- info.comp_info[1].h_samp_factor == 1 &&
- info.comp_info[1].v_samp_factor == 1 &&
- info.comp_info[2].h_samp_factor == 1 &&
- info.comp_info[2].v_samp_factor == 1) {
- const int h = info.comp_info[0].h_samp_factor;
- const int v = info.comp_info[0].v_samp_factor;
- if (v == 1) {
- switch (h) {
- case 1:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr444;
- case 2:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr422;
- case 4:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr411;
- }
- } else if (v == 2) {
- switch (h) {
- case 1:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr440;
- case 2:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr420;
- case 4:
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr410;
- }
- }
+ switch (YuvSubsampling(info)) {
+ case cc::YUVSubsampling::k444:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr444;
+ case cc::YUVSubsampling::k422:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr422;
+ case cc::YUVSubsampling::k411:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr411;
+ case cc::YUVSubsampling::k440:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr440;
+ case cc::YUVSubsampling::k420:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr420;
+ case cc::YUVSubsampling::k410:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCr410;
+ case cc::YUVSubsampling::kUnknown:
+ return blink::BitmapImageMetrics::JpegColorSpace::kYCbCrOther;
}
- return blink::BitmapImageMetrics::JpegColorSpace::kYCbCrOther;
+ NOTREACHED();
default:
return blink::BitmapImageMetrics::JpegColorSpace::kUnknown;
}
@@ -164,16 +183,6 @@ enum jstate {
JPEG_DONE
};
-enum yuv_subsampling {
- YUV_UNKNOWN,
- YUV_410,
- YUV_411,
- YUV_420,
- YUV_422,
- YUV_440,
- YUV_444
-};
-
void init_source(j_decompress_ptr jd);
boolean fill_input_buffer(j_decompress_ptr jd);
void skip_input_data(j_decompress_ptr jd, long num_bytes);
@@ -273,56 +282,13 @@ static ImageOrientation ReadImageOrientation(jpeg_decompress_struct* info) {
static IntSize ComputeYUVSize(const jpeg_decompress_struct* info,
int component) {
- return IntSize(info->cur_comp_info[component]->downsampled_width,
- info->cur_comp_info[component]->downsampled_height);
+ return IntSize(info->comp_info[component].downsampled_width,
+ info->comp_info[component].downsampled_height);
}
static size_t ComputeYUVWidthBytes(const jpeg_decompress_struct* info,
int component) {
- return info->cur_comp_info[component]->width_in_blocks * DCTSIZE;
-}
-
-static yuv_subsampling YuvSubsampling(const jpeg_decompress_struct& info) {
- if ((DCTSIZE == 8) && (info.num_components == 3) && (info.scale_denom <= 8) &&
- (info.cur_comp_info[0]) && (info.cur_comp_info[1]) &&
- (info.cur_comp_info[2]) && (info.cur_comp_info[1]->h_samp_factor == 1) &&
- (info.cur_comp_info[1]->v_samp_factor == 1) &&
- (info.cur_comp_info[2]->h_samp_factor == 1) &&
- (info.cur_comp_info[2]->v_samp_factor == 1)) {
- int h = info.cur_comp_info[0]->h_samp_factor;
- int v = info.cur_comp_info[0]->v_samp_factor;
- // 4:4:4 : (h == 1) && (v == 1)
- // 4:4:0 : (h == 1) && (v == 2)
- // 4:2:2 : (h == 2) && (v == 1)
- // 4:2:0 : (h == 2) && (v == 2)
- // 4:1:1 : (h == 4) && (v == 1)
- // 4:1:0 : (h == 4) && (v == 2)
- if (v == 1) {
- switch (h) {
- case 1:
- return YUV_444;
- case 2:
- return YUV_422;
- case 4:
- return YUV_411;
- default:
- break;
- }
- } else if (v == 2) {
- switch (h) {
- case 1:
- return YUV_440;
- case 2:
- return YUV_420;
- case 4:
- return YUV_410;
- default:
- break;
- }
- }
- }
-
- return YUV_UNKNOWN;
+ return info->comp_info[component].width_in_blocks * DCTSIZE;
}
static void ProgressMonitor(j_common_ptr info) {
@@ -483,9 +449,11 @@ class JPEGImageReader final {
switch (info_.jpeg_color_space) {
case JCS_YCbCr:
// libjpeg can convert YCbCr image pixels to RGB.
+ // TODO(crbug.com/919627): is the info_.scale_denom <= 8 actually
+ // needed?
info_.out_color_space = rgbOutputColorSpace();
- if (decoder_->HasImagePlanes() &&
- (YuvSubsampling(info_) != YUV_UNKNOWN))
+ if (decoder_->HasImagePlanes() && info_.scale_denom <= 8 &&
+ (YuvSubsampling(info_) != cc::YUVSubsampling::kUnknown))
override_color_space = JCS_YCbCr;
break;
case JCS_GRAYSCALE:
@@ -924,19 +892,17 @@ bool JPEGImageDecoder::ShouldGenerateAllSizes() const {
}
bool JPEGImageDecoder::CanDecodeToYUV() {
- // TODO(crbug.com/919627): Right now |decode_to_yuv_for_testing_| is false by
- // default and is only set true for unit tests. Remove it once
- // JPEG YUV decoding is finished and YUV decoding doesn't need to be disabled
- // outside of tests.
+ // TODO(crbug.com/919627): Right now |allow_decode_to_yuv_| is false by
+ // default and is only set true for unit tests.
//
- // Returning false here is a bit deceptive because the JPEG decoder does
- // support YUV. But the rest of the infrastructure at levels above the decoder
- // is not quite there yet to handle the resulting JPEG YUV data,
- // so for now we disable that path.
+ // Returning false here is a bit deceptive because the
+ // JPEG decoder does support YUV. But the rest of the infrastructure at levels
+ // above the decoder is not quite there yet to handle the resulting JPEG YUV
+ // data, so for now we disable that path.
//
// Calling IsSizeAvailable() ensures the reader is created and the output
// color space is set.
- return decode_to_yuv_for_testing_ && IsSizeAvailable() &&
+ return allow_decode_to_yuv_ && IsSizeAvailable() &&
reader_->Info()->out_color_space == JCS_YCbCr;
}
@@ -956,11 +922,6 @@ SkYUVColorSpace JPEGImageDecoder::GetYUVColorSpace() const {
return SkYUVColorSpace::kJPEG_SkYUVColorSpace;
}
-void JPEGImageDecoder::SetImagePlanes(
- std::unique_ptr<ImagePlanes> image_planes) {
- image_planes_ = std::move(image_planes);
-}
-
void JPEGImageDecoder::SetSupportedDecodeSizes(Vector<SkISize> sizes) {
supported_decode_sizes_ = std::move(sizes);
}
@@ -972,6 +933,27 @@ Vector<SkISize> JPEGImageDecoder::GetSupportedDecodeSizes() const {
return supported_decode_sizes_;
}
+cc::ImageHeaderMetadata JPEGImageDecoder::MakeMetadataForDecodeAcceleration()
+ const {
+ cc::ImageHeaderMetadata image_metadata =
+ ImageDecoder::MakeMetadataForDecodeAcceleration();
+ image_metadata.jpeg_is_progressive = reader_->Info()->buffered_image;
+
+ // Calculate the coded size of the image.
+ const size_t mcu_width =
+ base::checked_cast<size_t>(reader_->Info()->comp_info->h_samp_factor * 8);
+ const size_t mcu_height =
+ base::checked_cast<size_t>(reader_->Info()->comp_info->v_samp_factor * 8);
+ const int coded_width = base::checked_cast<int>(base::bits::Align(
+ base::checked_cast<size_t>(image_metadata.image_size.width()),
+ mcu_width));
+ const int coded_height = base::checked_cast<int>(base::bits::Align(
+ base::checked_cast<size_t>(image_metadata.image_size.height()),
+ mcu_height));
+ image_metadata.coded_size = gfx::Size(coded_width, coded_height);
+ return image_metadata;
+}
+
// At the moment we support only JCS_RGB and JCS_CMYK values of the
// J_COLOR_SPACE enum.
// If you need a specific implementation for other J_COLOR_SPACE values,
@@ -1181,6 +1163,13 @@ inline bool IsComplete(const JPEGImageDecoder* decoder, bool only_size) {
return decoder->FrameIsDecodedAtIndex(0);
}
+cc::YUVSubsampling JPEGImageDecoder::GetYUVSubsampling() const {
+ DCHECK(reader_->Info());
+ // reader_->Info() should have gone through a jpeg_read_header() call.
+ DCHECK(IsDecodedSizeAvailable());
+ return YuvSubsampling(*reader_->Info());
+}
+
void JPEGImageDecoder::Decode(bool only_size) {
if (Failed())
return;
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 450f065796d..68010342150 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
@@ -52,7 +52,6 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
bool CanDecodeToYUV() override;
void DecodeToYUV() override;
SkYUVColorSpace GetYUVColorSpace() const override;
- void SetImagePlanes(std::unique_ptr<ImagePlanes>) override;
Vector<SkISize> GetSupportedDecodeSizes() const override;
bool HasImagePlanes() const { return image_planes_.get(); }
@@ -67,14 +66,20 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
void SetDecodedSize(unsigned width, unsigned height);
void SetSupportedDecodeSizes(Vector<SkISize> sizes);
+
+ // TODO(crbug.com/919627): |allow_decode_to_yuv_| is false by
+ // default and is only set true for unit tests. Remove it once
+ // JPEG YUV decoding is finished and YUV decoding is enabled by default.
void SetDecodeToYuvForTesting(bool decode_to_yuv) {
- decode_to_yuv_for_testing_ = decode_to_yuv;
+ allow_decode_to_yuv_ = decode_to_yuv;
}
private:
// ImageDecoder:
void DecodeSize() override { Decode(true); }
void Decode(size_t) override { Decode(false); }
+ cc::YUVSubsampling GetYUVSubsampling() const override;
+ cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const override;
// Decodes the image. If |only_size| is true, stops decoding after
// calculating the image size. If decoding fails but there is no more
@@ -83,10 +88,8 @@ class PLATFORM_EXPORT JPEGImageDecoder final : public ImageDecoder {
std::unique_ptr<JPEGImageReader> reader_;
const size_t offset_;
- std::unique_ptr<ImagePlanes> image_planes_;
IntSize decoded_size_;
Vector<SkISize> supported_decode_sizes_;
- bool decode_to_yuv_for_testing_ = false;
DISALLOW_COPY_AND_ASSIGN(JPEGImageDecoder);
};
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 d7087225c2a..8d9c85f4c06 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
@@ -42,7 +42,6 @@
#include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h"
namespace blink {
@@ -122,12 +121,13 @@ void ReadYUV(size_t max_decoded_bytes,
row_bytes[1] = decoder->DecodedYUVWidthBytes(1);
row_bytes[2] = decoder->DecodedYUVWidthBytes(2);
- scoped_refptr<ArrayBuffer> buffer(ArrayBuffer::Create(
- row_bytes[0] * y_size.Height() + row_bytes[1] * u_size.Height() +
- row_bytes[2] * v_size.Height(),
- 1));
+ size_t planes_data_size = row_bytes[0] * y_size.Height() +
+ row_bytes[1] * u_size.Height() +
+ row_bytes[2] * v_size.Height();
+ std::unique_ptr<char[]> planes_data(new char[planes_data_size]);
+
void* planes[3];
- planes[0] = buffer->Data();
+ planes[0] = reinterpret_cast<void*>(planes_data.get());
planes[1] = ((char*)planes[0]) + row_bytes[0] * y_size.Height();
planes[2] = ((char*)planes[1]) + row_bytes[1] * u_size.Height();
@@ -250,6 +250,16 @@ TEST(JPEGImageDecoderTest, yuv) {
EXPECT_EQ(128u, output_uv_width);
EXPECT_EQ(128u, output_uv_height);
+ // Each plane is in its own scan.
+ const char* jpeg_file_non_interleaved =
+ "/images/resources/cs-uma-ycbcr-420-non-interleaved.jpg"; // 64x64
+ ReadYUV(kLargeEnoughSize, &output_y_width, &output_y_height, &output_uv_width,
+ &output_uv_height, jpeg_file_non_interleaved);
+ EXPECT_EQ(64u, output_y_width);
+ EXPECT_EQ(64u, output_y_height);
+ EXPECT_EQ(32u, output_uv_width);
+ EXPECT_EQ(32u, output_uv_height);
+
const char* jpeg_file_image_size_not_multiple_of8 =
"/images/resources/cropped_mandrill.jpg"; // 439x154
ReadYUV(kLargeEnoughSize, &output_y_width, &output_y_height, &output_uv_width,
@@ -493,7 +503,7 @@ const ColorSpaceUMATest::ParamType kColorSpaceUMATestParams[] = {
{"cs-uma-grayscale.jpg", true,
BitmapImageMetrics::JpegColorSpace::kGrayscale},
{"cs-uma-rgb.jpg", true, BitmapImageMetrics::JpegColorSpace::kRGB},
- // Each component is in a separate plane. Should not make a difference.
+ // Each component is in a separate scan. Should not make a difference.
{"cs-uma-rgb-non-interleaved.jpg", true,
BitmapImageMetrics::JpegColorSpace::kRGB},
{"cs-uma-cmyk.jpg", true, BitmapImageMetrics::JpegColorSpace::kCMYK},
@@ -515,7 +525,7 @@ const ColorSpaceUMATest::ParamType kColorSpaceUMATestParams[] = {
BitmapImageMetrics::JpegColorSpace::kYCbCr411},
{"cs-uma-ycbcr-420.jpg", true,
BitmapImageMetrics::JpegColorSpace::kYCbCr420},
- // Each component is in a separate plane. Should not make a difference.
+ // Each component is in a separate scan. Should not make a difference.
{"cs-uma-ycbcr-420-non-interleaved.jpg", true,
BitmapImageMetrics::JpegColorSpace::kYCbCr420},
// 3 components/both JFIF and Adobe markers, so we expect libjpeg_turbo to
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 5b457f0fd99..3d22cf6fb57 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
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
+#include <utility>
+
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
@@ -20,7 +22,7 @@ namespace blink {
// Interface for ImageDecoder to read a SharedBuffer.
class SharedBufferSegmentReader final : public SegmentReader {
public:
- SharedBufferSegmentReader(scoped_refptr<SharedBuffer>);
+ explicit SharedBufferSegmentReader(scoped_refptr<SharedBuffer>);
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
sk_sp<SkData> GetAsSkData() const override;
@@ -66,7 +68,7 @@ sk_sp<SkData> SharedBufferSegmentReader::GetAsSkData() const {
// Interface for ImageDecoder to read an SkData.
class DataSegmentReader final : public SegmentReader {
public:
- DataSegmentReader(sk_sp<SkData>);
+ explicit DataSegmentReader(sk_sp<SkData>);
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
sk_sp<SkData> GetAsSkData() const override;
@@ -101,7 +103,7 @@ sk_sp<SkData> DataSegmentReader::GetAsSkData() const {
class ROBufferSegmentReader final : public SegmentReader {
public:
- ROBufferSegmentReader(sk_sp<SkROBuffer>);
+ explicit ROBufferSegmentReader(sk_sp<SkROBuffer>);
size_t size() const override;
size_t GetSomeData(const char*& data, size_t position) const override;
@@ -109,11 +111,10 @@ class ROBufferSegmentReader final : public SegmentReader {
private:
sk_sp<SkROBuffer> ro_buffer_;
- // Protects access to mutable fields.
mutable Mutex read_mutex_;
// Position of the first char in the current block of iter_.
- mutable size_t position_of_block_;
- mutable SkROBuffer::Iter iter_;
+ mutable size_t position_of_block_ GUARDED_BY(read_mutex_);
+ mutable SkROBuffer::Iter iter_ GUARDED_BY(read_mutex_);
DISALLOW_COPY_AND_ASSIGN(ROBufferSegmentReader);
};
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.cc b/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.cc
index 4024f9cc449..5a9870125d2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.cc
@@ -10,10 +10,10 @@ namespace blink {
SegmentStream::SegmentStream() = default;
-SegmentStream::SegmentStream(SegmentStream&& rhs) noexcept
+SegmentStream::SegmentStream(SegmentStream&& rhs)
: reader_(std::move(rhs.reader_)), position_(rhs.position_) {}
-SegmentStream& SegmentStream::operator=(SegmentStream&& rhs) noexcept {
+SegmentStream& SegmentStream::operator=(SegmentStream&& rhs) {
reader_ = std::move(rhs.reader_);
position_ = rhs.position_;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.h b/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.h
index f49f551e20f..fa1ccf27571 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/segment_stream.h
@@ -19,8 +19,8 @@ class PLATFORM_EXPORT SegmentStream : public SkStream {
SegmentStream();
SegmentStream(const SegmentStream&) = delete;
SegmentStream& operator=(const SegmentStream&) = delete;
- SegmentStream(SegmentStream&&) noexcept;
- SegmentStream& operator=(SegmentStream&&) noexcept;
+ SegmentStream(SegmentStream&&);
+ SegmentStream& operator=(SegmentStream&&);
~SegmentStream() override;
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 a7be357470a..a75f37382a0 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
@@ -28,6 +28,8 @@
#include "third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h"
+#include <string.h>
+
#include "base/feature_list.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/instrumentation/histogram.h"
@@ -121,6 +123,20 @@ enum WebPFileFormat {
kCountWebPFileFormats
};
+// Validates that |blob| is a simple lossy WebP image. Note that this explicitly
+// checks "WEBPVP8 " to exclude extended lossy WebPs that don't actually use any
+// extended features.
+//
+// TODO(crbug.com/1009237): consider combining this with the logic to detect
+// WebPs that can be decoded to YUV.
+bool IsSimpleLossyWebPImage(const sk_sp<SkData>& blob) {
+ if (blob->size() < 20UL)
+ return false;
+ DCHECK(blob->bytes());
+ return !memcmp(blob->bytes(), "RIFF", 4) &&
+ !memcmp(blob->bytes() + 8UL, "WEBPVP8 ", 8);
+}
+
// This method parses |blob|'s header and emits a UMA with the file format, as
// defined by WebP, see WebPFileFormat.
void UpdateWebPFileFormatUMA(const sk_sp<SkData>& blob) {
@@ -168,7 +184,6 @@ WEBPImageDecoder::WEBPImageDecoder(AlphaOption alpha_option,
decoder_(nullptr),
format_flags_(0),
frame_background_has_alpha_(false),
- can_decode_to_yuv_(false),
demux_(nullptr),
demux_state_(WEBP_DEMUX_PARSING_HEADER),
have_already_parsed_this_data_(false),
@@ -249,7 +264,9 @@ void WEBPImageDecoder::OnSetData(SegmentReader* data) {
// we don't require IsAllDataReceived() to be true before decoding).
if (IsAllDataReceived()) {
UpdateDemuxer();
- can_decode_to_yuv_ = CanAllowYUVDecodingForWebP();
+ allow_decode_to_yuv_ =
+ RuntimeEnabledFeatures::DecodeLossyWebPImagesToYUVEnabled() &&
+ CanAllowYUVDecodingForWebP();
}
}
@@ -383,15 +400,6 @@ void WEBPImageDecoder::OnInitFrameBuffer(size_t frame_index) {
buffer.SetHasAlpha(true);
}
-void WEBPImageDecoder::SetImagePlanes(
- std::unique_ptr<ImagePlanes> image_planes) {
- image_planes_ = std::move(image_planes);
-}
-
-bool WEBPImageDecoder::CanDecodeToYUV() {
- return can_decode_to_yuv_;
-}
-
void WEBPImageDecoder::DecodeToYUV() {
DCHECK(IsDoingYuvDecode());
@@ -449,6 +457,17 @@ SkYUVColorSpace WEBPImageDecoder::GetYUVColorSpace() const {
return SkYUVColorSpace::kRec601_SkYUVColorSpace;
}
+cc::YUVSubsampling WEBPImageDecoder::GetYUVSubsampling() const {
+ DCHECK(consolidated_data_);
+ if (IsSimpleLossyWebPImage(consolidated_data_))
+ return cc::YUVSubsampling::k420;
+ // It is possible for a non-simple lossy WebP to also be YUV 4:2:0. However,
+ // we're being conservative here because this is currently only used for
+ // hardware decode acceleration, and WebPs other than simple lossy are not
+ // supported in that path anyway.
+ return cc::YUVSubsampling::kUnknown;
+}
+
bool WEBPImageDecoder::CanReusePreviousFrameBuffer(size_t frame_index) const {
DCHECK(frame_index < frame_buffer_cache_.size());
return frame_buffer_cache_[frame_index].GetAlphaBlendSource() !=
@@ -775,4 +794,15 @@ bool WEBPImageDecoder::DecodeSingleFrame(const uint8_t* data_bytes,
}
}
+cc::ImageHeaderMetadata WEBPImageDecoder::MakeMetadataForDecodeAcceleration()
+ const {
+ cc::ImageHeaderMetadata image_metadata =
+ ImageDecoder::MakeMetadataForDecodeAcceleration();
+
+ DCHECK(consolidated_data_);
+ image_metadata.webp_is_non_extended_lossy =
+ IsSimpleLossyWebPImage(consolidated_data_);
+ return image_metadata;
+}
+
} // namespace blink
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 fa748070a10..1c40d370d9e 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
@@ -59,10 +59,10 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
size_t DecodeFrameCount() override;
void InitializeNewFrame(size_t) override;
void Decode(size_t) override;
- void SetImagePlanes(std::unique_ptr<ImagePlanes>) override;
- bool CanDecodeToYUV() override;
void DecodeToYUV() override;
SkYUVColorSpace GetYUVColorSpace() const override;
+ cc::YUVSubsampling GetYUVSubsampling() const override;
+ cc::ImageHeaderMetadata MakeMetadataForDecodeAcceleration() const override;
WEBP_CSP_MODE RGBOutputMode();
// Returns true if the image data received so far (as stored in
@@ -88,7 +88,7 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
bool IsDoingYuvDecode() const {
if (image_planes_) {
- DCHECK(can_decode_to_yuv_);
+ DCHECK(allow_decode_to_yuv_);
return true;
}
return false;
@@ -98,12 +98,6 @@ class PLATFORM_EXPORT WEBPImageDecoder final : public ImageDecoder {
WebPDecBuffer decoder_buffer_;
int format_flags_;
bool frame_background_has_alpha_;
- // Note that |can_decode_to_yuv_| being true merely means that the
- // WEBPImageDecoder is allowed to decode to YUV. Other layers higher in the
- // stack (the PaintImageGenerator, ImageFrameGenerator, or cache) may
- // decline to go down the YUV path.
- bool can_decode_to_yuv_;
- std::unique_ptr<ImagePlanes> image_planes_;
// Provides the size of each component.
IntSize DecodedYUVSize(int component) const override;
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 4c8bcd196de..50d4bd81a40 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
@@ -37,7 +37,6 @@
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn b/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
index 4431cce8942..a53a2e66cac 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/BUILD.gn
@@ -6,6 +6,12 @@ import("//build/config/jumbo.gni")
import("//third_party/blink/renderer/platform/platform.gni")
blink_platform_sources("instrumentation") {
+ visibility = []
+ visibility = [
+ "//third_party/blink/renderer/platform",
+ "//third_party/blink/renderer/platform/scheduler",
+ ]
+
sources = [
"histogram.cc",
"histogram.h",
@@ -35,6 +41,7 @@ blink_platform_sources("instrumentation") {
]
deps = [
+ "//components/performance_manager/public/mojom:mojom_blink",
"//services/service_manager/public/cpp",
]
}
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/DEPS b/chromium/third_party/blink/renderer/platform/instrumentation/DEPS
index 056ae2a312e..1b9aae2b542 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/DEPS
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/DEPS
@@ -12,6 +12,7 @@ include_rules = [
"+base/strings",
"+base/trace_event",
"+base/values.h",
+ "+components/performance_manager/public/mojom",
"+skia/ext/skia_trace_memory_dump_impl.h",
"+third_party/blink/renderer/platform/fonts/font_global_context.h",
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
index 23867b966ce..6a3443121a5 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/instance_counters.h
@@ -48,7 +48,6 @@ namespace blink {
V(MediaKeys) \
V(Node) \
V(Resource) \
- V(ScriptPromise) \
V(ContextLifecycleStateObserver) \
V(V8PerContextData) \
V(WorkerGlobalScope) \
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 9ed96d2fcc7..9bab204ceeb 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
@@ -9,11 +9,12 @@
#include "third_party/blink/public/platform/web_memory_pressure_level.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
namespace blink {
+class Thread;
+
class PLATFORM_EXPORT MemoryPressureListener : public GarbageCollectedMixin {
public:
virtual ~MemoryPressureListener() = default;
@@ -26,7 +27,7 @@ class PLATFORM_EXPORT MemoryPressureListener : public GarbageCollectedMixin {
// MemoryPressureListenerRegistry listens to some events which could be
// opportunities for reducing memory consumption and notifies its clients.
class PLATFORM_EXPORT MemoryPressureListenerRegistry final
- : public GarbageCollectedFinalized<MemoryPressureListenerRegistry> {
+ : public GarbageCollected<MemoryPressureListenerRegistry> {
public:
static MemoryPressureListenerRegistry& Instance();
@@ -68,7 +69,7 @@ class PLATFORM_EXPORT MemoryPressureListenerRegistry final
static bool is_low_end_device_;
HeapHashSet<WeakMember<MemoryPressureListener>> clients_;
- HashSet<Thread*> threads_;
+ HashSet<Thread*> threads_ GUARDED_BY(threads_mutex_);
Mutex threads_mutex_;
DISALLOW_COPY_AND_ASSIGN(MemoryPressureListenerRegistry);
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
index fd6a37d0999..29c7ca3b990 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
@@ -14,7 +14,7 @@ namespace blink {
namespace {
-using resource_coordinator::mojom::InterventionPolicy;
+using performance_manager::mojom::InterventionPolicy;
} // namespace
@@ -30,7 +30,7 @@ DocumentResourceCoordinator::MaybeCreate(
DocumentResourceCoordinator::DocumentResourceCoordinator(
service_manager::InterfaceProvider* interface_provider) {
- interface_provider->GetInterface(mojo::MakeRequest(&service_));
+ interface_provider->GetInterface(service_.BindNewPipeAndPassReceiver());
DCHECK(service_);
}
@@ -41,7 +41,7 @@ void DocumentResourceCoordinator::SetNetworkAlmostIdle() {
}
void DocumentResourceCoordinator::SetLifecycleState(
- resource_coordinator::mojom::LifecycleState state) {
+ performance_manager::mojom::LifecycleState state) {
service_->SetLifecycleState(state);
}
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 144bc289e2f..59217530e37 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
@@ -8,7 +8,8 @@
#include <memory>
#include "base/macros.h"
-#include "services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.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"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -28,10 +29,10 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
~DocumentResourceCoordinator();
void SetNetworkAlmostIdle();
- void SetLifecycleState(resource_coordinator::mojom::LifecycleState);
+ void SetLifecycleState(performance_manager::mojom::LifecycleState);
void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload);
void SetOriginTrialFreezePolicy(
- resource_coordinator::mojom::InterventionPolicy policy);
+ performance_manager::mojom::InterventionPolicy policy);
// A one way switch that marks a frame as being an adframe.
void SetIsAdFrame();
void OnNonPersistentNotificationCreated();
@@ -39,7 +40,8 @@ class PLATFORM_EXPORT DocumentResourceCoordinator final {
private:
explicit DocumentResourceCoordinator(service_manager::InterfaceProvider*);
- resource_coordinator::mojom::blink::DocumentCoordinationUnitPtr service_;
+ mojo::Remote<performance_manager::mojom::blink::DocumentCoordinationUnit>
+ service_;
DISALLOW_COPY_AND_ASSIGN(DocumentResourceCoordinator);
};
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
index decffea5062..42437f60fba 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
@@ -27,7 +27,7 @@ void RendererResourceCoordinator::MaybeInitialize() {
DCHECK(platform);
mojo::PendingRemote<
- resource_coordinator::mojom::blink::ProcessCoordinationUnit>
+ performance_manager::mojom::blink::ProcessCoordinationUnit>
remote;
platform->GetBrowserInterfaceBrokerProxy()->GetInterface(
remote.InitWithNewPipeAndPassReceiver());
@@ -49,7 +49,7 @@ RendererResourceCoordinator* RendererResourceCoordinator::Get() {
RendererResourceCoordinator::RendererResourceCoordinator(
mojo::PendingRemote<
- resource_coordinator::mojom::blink::ProcessCoordinationUnit> remote) {
+ performance_manager::mojom::blink::ProcessCoordinationUnit> remote) {
service_.Bind(std::move(remote));
}
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
index 35fe1bb8adf..43795cc3f35 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
@@ -6,7 +6,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTRUMENTATION_RESOURCE_COORDINATOR_RENDERER_RESOURCE_COORDINATOR_H_
#include "base/macros.h"
-#include "services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.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"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -35,9 +36,10 @@ class PLATFORM_EXPORT RendererResourceCoordinator {
private:
explicit RendererResourceCoordinator(
mojo::PendingRemote<
- resource_coordinator::mojom::blink::ProcessCoordinationUnit> remote);
+ performance_manager::mojom::blink::ProcessCoordinationUnit> remote);
- resource_coordinator::mojom::blink::ProcessCoordinationUnitPtr service_;
+ mojo::Remote<performance_manager::mojom::blink::ProcessCoordinationUnit>
+ service_;
DISALLOW_COPY_AND_ASSIGN(RendererResourceCoordinator);
};
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc b/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
index a0ee46c42a9..3f45f763351 100644
--- a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
@@ -39,7 +39,7 @@ namespace blink {
class TestingObserver;
class DummyContext final
- : public GarbageCollectedFinalized<DummyContext>,
+ : public GarbageCollected<DummyContext>,
public LifecycleNotifier<DummyContext, TestingObserver> {
USING_GARBAGE_COLLECTED_MIXIN(DummyContext);
@@ -143,10 +143,12 @@ TEST(LifecycleContextTest, ObserverRemovedDuringNotifyDestroyed) {
// This is a regression test for http://crbug.com/854639.
TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) {
base::test::ScopedFeatureList scoped_feature_list;
- // Disable concurrent sweeping as worker_pool task environment is not set.
+ // Disable concurrent marking and concurrent sweeping as worker_pool task
+ // environment is not set.
scoped_feature_list.InitWithFeatures(
{blink::features::kBlinkHeapIncrementalMarking},
- {blink::features::kBlinkHeapConcurrentSweeping});
+ {blink::features::kBlinkHeapConcurrentMarking,
+ blink::features::kBlinkHeapConcurrentSweeping});
ThreadState* thread_state = ThreadState::Current();
thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting);
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h b/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
index 05e99583d79..d105761b4b8 100644
--- a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
+++ b/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
@@ -161,6 +161,9 @@ inline void LifecycleNotifier<T, Observer>::NotifyContextDestroyed() {
ContextDestroyedNotifier<Observer, T>::Call(observer, Context());
observer->ClearContext();
}
+ // Explicitly free the backing store to avoid memory regressions.
+ // TODO(bikineev): Revisit after young generation is done.
+ observers.clear();
}
template <typename T, typename Observer>
diff --git a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
index dedf6288459..731514c2914 100644
--- a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -77,6 +77,7 @@ blink_platform_sources("loader") {
"fetch/resource_load_timing.h",
"fetch/resource_loader.cc",
"fetch/resource_loader.h",
+ "fetch/resource_loader_options.cc",
"fetch/resource_loader_options.h",
"fetch/resource_loading_log.h",
"fetch/resource_priority.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
index 7c53cfefe18..927f24b470a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/allowed_by_nosniff.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
+#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/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
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 1f7940ca1f4..a676308244c 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
@@ -22,7 +22,7 @@ using MimeTypeCheck = AllowedByNosniff::MimeTypeCheck;
using WebFeature = mojom::WebFeature;
using ::testing::_;
-class MockUseCounter : public GarbageCollectedFinalized<MockUseCounter>,
+class MockUseCounter : public GarbageCollected<MockUseCounter>,
public UseCounter {
USING_GARBAGE_COLLECTED_MIXIN(MockUseCounter);
@@ -35,7 +35,7 @@ class MockUseCounter : public GarbageCollectedFinalized<MockUseCounter>,
MOCK_METHOD1(CountDeprecation, void(mojom::WebFeature));
};
-class MockConsoleLogger : public GarbageCollectedFinalized<MockConsoleLogger>,
+class MockConsoleLogger : public GarbageCollected<MockConsoleLogger>,
public ConsoleLogger {
USING_GARBAGE_COLLECTED_MIXIN(MockConsoleLogger);
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 1b15903c379..42c442fb1d9 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -12,6 +12,7 @@
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/cors/preflight_cache.h"
#include "services/network/public/cpp/request_mode.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
@@ -287,6 +288,7 @@ network::mojom::FetchResponseType CalculateResponseTainting(
const KURL& url,
network::mojom::RequestMode request_mode,
const SecurityOrigin* origin,
+ const SecurityOrigin* isolated_world_origin,
CorsFlag cors_flag) {
if (url.ProtocolIsData())
return network::mojom::FetchResponseType::kBasic;
@@ -302,9 +304,12 @@ network::mojom::FetchResponseType CalculateResponseTainting(
return network::mojom::FetchResponseType::kBasic;
}
- if (request_mode == network::mojom::RequestMode::kNoCors &&
- !origin->CanRequest(url)) {
- return network::mojom::FetchResponseType::kOpaque;
+ if (request_mode == network::mojom::RequestMode::kNoCors) {
+ bool can_request = origin->CanRequest(url);
+ if (!can_request && isolated_world_origin)
+ can_request = isolated_world_origin->CanRequest(url);
+ if (!can_request)
+ return network::mojom::FetchResponseType::kOpaque;
}
return network::mojom::FetchResponseType::kBasic;
}
@@ -355,7 +360,7 @@ Vector<String> CorsUnsafeRequestHeaderNames(const HTTPHeaderMap& headers) {
}
bool IsForbiddenHeaderName(const String& name) {
- return network::cors::IsForbiddenHeader(name.Latin1());
+ return !net::HttpUtil::IsSafeHeader(name.Latin1());
}
bool ContainsOnlyCorsSafelistedHeaders(const HTTPHeaderMap& header_map) {
@@ -384,16 +389,25 @@ bool IsOkStatus(int status) {
}
bool CalculateCorsFlag(const KURL& url,
- const SecurityOrigin* origin,
+ const SecurityOrigin* initiator_origin,
+ const SecurityOrigin* isolated_world_origin,
network::mojom::RequestMode request_mode) {
if (network::IsNavigationRequestMode(request_mode) ||
request_mode == network::mojom::RequestMode::kNoCors) {
return false;
}
+
// CORS needs a proper origin (including a unique opaque origin). If the
- // request doesn't have one, CORS should not work.
- DCHECK(origin);
- return !origin->CanReadContent(url);
+ // request doesn't have one, CORS will not work.
+ DCHECK(initiator_origin);
+
+ if (initiator_origin->CanReadContent(url))
+ return false;
+
+ if (isolated_world_origin && isolated_world_origin->CanReadContent(url))
+ return false;
+
+ return true;
}
WebHTTPHeaderSet ExtractCorsExposedHeaderNamesList(
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 6544bf125f7..84998f9c4b2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
@@ -7,9 +7,9 @@
#include "base/optional.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
-#include "services/network/public/mojom/cors.mojom-blink.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.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/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_http_header_set.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -85,6 +85,7 @@ PLATFORM_EXPORT network::mojom::FetchResponseType CalculateResponseTainting(
const KURL& url,
network::mojom::RequestMode request_mode,
const SecurityOrigin* origin,
+ const SecurityOrigin* isolated_world_origin,
CorsFlag cors_flag);
PLATFORM_EXPORT bool CalculateCredentialsFlag(
@@ -119,7 +120,8 @@ PLATFORM_EXPORT bool IsOkStatus(int status);
// This function will be removed when out-of-renderer CORS is enabled.
PLATFORM_EXPORT bool CalculateCorsFlag(
const KURL& url,
- const SecurityOrigin* origin,
+ const SecurityOrigin* initiator_origin,
+ const SecurityOrigin* isolated_world_origin,
network::mojom::RequestMode request_mode);
PLATFORM_EXPORT WebHTTPHeaderSet
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
index 8d40c9577bf..d428a2f5a64 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
@@ -6,6 +6,7 @@
#include <initializer_list>
+#include "services/network/public/mojom/cors.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.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 fa806507b9c..73dfab95277 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
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
-#include "services/network/public/mojom/cors.mojom-blink.h"
+#include "services/network/public/mojom/cors.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_url_request.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/cors/cors_test.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
index 60a7ba4b09b..e68e93c56b7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.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/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -118,68 +119,68 @@ TEST(CorsTest, CalculateResponseTainting) {
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kSameOrigin,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(FetchResponseType::kBasic,
cors::CalculateResponseTainting(
same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- CorsFlag::Unset));
+ nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
// CORS flag is false, cross-origin request
EXPECT_EQ(
FetchResponseType::kOpaque,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
- origin, CorsFlag::Unset));
+ origin, nullptr, CorsFlag::Unset));
// CORS flag is true, same-origin request
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kCors,
- origin, CorsFlag::Set));
+ origin, nullptr, CorsFlag::Set));
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(
same_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- CorsFlag::Set));
+ nullptr, CorsFlag::Set));
// CORS flag is true, cross-origin request
- EXPECT_EQ(FetchResponseType::kCors,
- cors::CalculateResponseTainting(
- cross_origin_url, RequestMode::kCors, origin, CorsFlag::Set));
+ EXPECT_EQ(FetchResponseType::kCors, cors::CalculateResponseTainting(
+ cross_origin_url, RequestMode::kCors,
+ origin, nullptr, CorsFlag::Set));
EXPECT_EQ(FetchResponseType::kCors,
cors::CalculateResponseTainting(
cross_origin_url, RequestMode::kCorsWithForcedPreflight, origin,
- CorsFlag::Set));
+ nullptr, CorsFlag::Set));
// Origin is not provided.
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNoCors,
- no_origin, CorsFlag::Unset));
+ no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(same_origin_url, RequestMode::kNavigate,
- no_origin, CorsFlag::Unset));
+ no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNoCors,
- no_origin, CorsFlag::Unset));
+ no_origin, nullptr, CorsFlag::Unset));
EXPECT_EQ(
FetchResponseType::kBasic,
cors::CalculateResponseTainting(cross_origin_url, RequestMode::kNavigate,
- no_origin, CorsFlag::Unset));
+ no_origin, nullptr, CorsFlag::Unset));
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h b/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
index 61ac0cdd914..c557ed1495d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h
@@ -23,8 +23,7 @@ class ExecutionContext;
// BytesConsumer has four states: waiting, readable, closed and errored. Once
// the state becomes closed or errored, it will never change. |readable| means
// that the BytesConsumer is ready to read non-empty bytes synchronously.
-class PLATFORM_EXPORT BytesConsumer
- : public GarbageCollectedFinalized<BytesConsumer> {
+class PLATFORM_EXPORT BytesConsumer : public GarbageCollected<BytesConsumer> {
public:
enum class Result {
kOk,
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
index 8320f8b8389..3aea5dc8784 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h
@@ -7,7 +7,7 @@
#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.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-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"
@@ -44,8 +44,7 @@ PLATFORM_EXPORT bool ShouldUseIsolatedCodeCache(mojom::RequestContextType,
const ResourceResponse&);
// Handler class for caching operations.
-class CachedMetadataHandler
- : public GarbageCollectedFinalized<CachedMetadataHandler> {
+class CachedMetadataHandler : public GarbageCollected<CachedMetadataHandler> {
public:
enum CacheType {
kSendToPlatform, // send cache data to blink::Platform::cacheMetadata
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 6c7765251ee..8772922ab81 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,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_CLIENT_SETTINGS_OBJECT_H_
#include "base/optional.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -31,7 +31,7 @@ namespace blink {
// used together with them.
// https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
class PLATFORM_EXPORT FetchClientSettingsObject
- : public GarbageCollectedFinalized<FetchClientSettingsObject> {
+ : public GarbageCollected<FetchClientSettingsObject> {
public:
virtual ~FetchClientSettingsObject() = default;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
index fdb78e09b99..9565501195c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
namespace blink {
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 ee03ed33520..aa2b09db435 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
@@ -36,8 +36,8 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink-forward.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
@@ -64,8 +64,7 @@ class WebScopedVirtualTimePauser;
// Any processing that depends on components outside platform/loader/fetch/
// should be implemented on a subclass of this interface, and then exposed to
// the ResourceFetcher via this interface.
-class PLATFORM_EXPORT FetchContext
- : public GarbageCollectedFinalized<FetchContext> {
+class PLATFORM_EXPORT FetchContext : public GarbageCollected<FetchContext> {
public:
FetchContext() = default;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
index b376754473d..0cb6e496324 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -109,12 +109,6 @@ void FetchParameters::MakeSynchronous() {
options_.synchronous_policy = kRequestSynchronously;
}
-void FetchParameters::SetClientLoFiPlaceholder() {
- resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() |
- WebURLRequest::kClientLoFiOn);
- SetAllowImagePlaceholder();
-}
-
void FetchParameters::SetLazyImagePlaceholder() {
resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() |
WebURLRequest::kLazyImageLoadDeferred);
@@ -141,10 +135,8 @@ void FetchParameters::SetAllowImagePlaceholder() {
// Make sure that the request isn't marked as using an image preview type,
// since without loading an image placeholder, Client Lo-Fi isn't really
// in use.
- resource_request_.SetPreviewsState(
- resource_request_.GetPreviewsState() &
- ~(WebURLRequest::kClientLoFiOn |
- WebURLRequest::kLazyImageLoadDeferred));
+ resource_request_.SetPreviewsState(resource_request_.GetPreviewsState() &
+ ~WebURLRequest::kLazyImageLoadDeferred);
return;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 7eee031f6f3..8cc76c6216d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -176,10 +176,6 @@ class PLATFORM_EXPORT FetchParameters {
return image_request_optimization_;
}
- // Configures the request to load an image as a placeholder and sets the
- // Client LoFi preview bit.
- void SetClientLoFiPlaceholder();
-
// Configures the request to load an image as a placeholder or defers the
// image and sets the lazy image load bit.
void SetLazyImagePlaceholder();
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 c7560a95178..b3000a9c3c3 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
@@ -62,10 +62,9 @@ class MemoryCacheEntry final : public GarbageCollected<MemoryCacheEntry> {
// This cache holds subresources used by Web pages: images, scripts,
// stylesheets, etc.
-class PLATFORM_EXPORT MemoryCache final
- : public GarbageCollectedFinalized<MemoryCache>,
- public MemoryCacheDumpClient,
- public MemoryPressureListener {
+class PLATFORM_EXPORT MemoryCache final : public GarbageCollected<MemoryCache>,
+ public MemoryCacheDumpClient,
+ public MemoryPressureListener {
USING_GARBAGE_COLLECTED_MIXIN(MemoryCache);
public:
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
index 541caf3ea7d..cc258880713 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
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 4c0cec98e23..13b03795a99 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
@@ -111,7 +111,7 @@ void RawResource::AppendData(const char* data, size_t length) {
}
class RawResource::PreloadBytesConsumerClient final
- : public GarbageCollectedFinalized<PreloadBytesConsumerClient>,
+ : public GarbageCollected<PreloadBytesConsumerClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(PreloadBytesConsumerClient);
@@ -236,6 +236,10 @@ SingleCachedMetadataHandler* RawResource::ScriptCacheHandler() {
return static_cast<SingleCachedMetadataHandler*>(Resource::CacheHandler());
}
+scoped_refptr<BlobDataHandle> RawResource::DownloadedBlob() const {
+ return downloaded_blob_;
+}
+
void RawResource::Trace(Visitor* visitor) {
visitor->Trace(bytes_consumer_for_preload_);
Resource::Trace(visitor);
@@ -403,6 +407,9 @@ Resource::MatchStatus RawResource::CanReuse(
return Resource::CanReuse(new_fetch_parameters);
}
+void RawResourceClient::DidDownloadToBlob(Resource*,
+ scoped_refptr<BlobDataHandle>) {}
+
RawResourceClientStateChecker::RawResourceClientStateChecker()
: state_(kNotAddedAsClient) {}
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 28f9c7056b2..8dcb65ccdb9 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
@@ -33,11 +33,13 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
+
class BytesConsumer;
class BufferingBytesConsumer;
class FetchParameters;
class RawResourceClient;
class ResourceFetcher;
+class SingleCachedMetadataHandler;
class PLATFORM_EXPORT RawResource final : public Resource {
public:
@@ -90,9 +92,7 @@ class PLATFORM_EXPORT RawResource final : public Resource {
// type is kRaw.
SingleCachedMetadataHandler* ScriptCacheHandler();
- scoped_refptr<BlobDataHandle> DownloadedBlob() const {
- return downloaded_blob_;
- }
+ scoped_refptr<BlobDataHandle> DownloadedBlob() const;
void Trace(Visitor* visitor) override;
@@ -199,7 +199,7 @@ class PLATFORM_EXPORT RawResourceClient : public ResourceClient {
// null if creating the blob failed for some reason (but the download itself
// otherwise succeeded). Could also not be called at all if the downloaded
// resource ended up being zero bytes.
- virtual void DidDownloadToBlob(Resource*, scoped_refptr<BlobDataHandle>) {}
+ virtual void DidDownloadToBlob(Resource*, scoped_refptr<BlobDataHandle>);
};
// Checks the sequence of callbacks of RawResourceClient. This can be used only
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 6c161c69930..4a1276b11b0 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
@@ -59,7 +59,7 @@ class RawResourceTest : public testing::Test {
protected:
class NoopResponseBodyLoaderClient
- : public GarbageCollectedFinalized<NoopResponseBodyLoaderClient>,
+ : public GarbageCollected<NoopResponseBodyLoaderClient>,
public ResponseBodyLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(NoopResponseBodyLoaderClient);
@@ -96,7 +96,7 @@ TEST_F(RawResourceTest, DontIgnoreAcceptForCacheReuse) {
Resource::MatchStatus::kOk);
}
-class DummyClient final : public GarbageCollectedFinalized<DummyClient>,
+class DummyClient final : public GarbageCollected<DummyClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(DummyClient);
@@ -135,7 +135,7 @@ class DummyClient final : public GarbageCollectedFinalized<DummyClient>,
};
// This client adds another client when notified.
-class AddingClient final : public GarbageCollectedFinalized<AddingClient>,
+class AddingClient final : public GarbageCollected<AddingClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(AddingClient);
@@ -192,7 +192,7 @@ TEST_F(RawResourceTest, AddClientDuringCallback) {
}
// This client removes another client when notified.
-class RemovingClient : public GarbageCollectedFinalized<RemovingClient>,
+class RemovingClient : public GarbageCollected<RemovingClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(RemovingClient);
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 0f9af93834c..d1e114bdc64 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.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_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
@@ -49,6 +50,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client_walker.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
@@ -392,6 +394,8 @@ const scoped_refptr<const SecurityOrigin>& Resource::GetOrigin() const {
return LastResourceRequest().RequestorOrigin();
}
+void Resource::DidDownloadToBlob(scoped_refptr<BlobDataHandle>) {}
+
static base::TimeDelta CurrentAge(const ResourceResponse& response,
base::Time response_timestamp) {
// RFC2616 13.2.3
@@ -1258,4 +1262,13 @@ void Resource::SetClockForTesting(const base::Clock* clock) {
g_clock_for_testing = clock;
}
+size_t Resource::CodeCacheSize() const {
+ return cache_handler_ ? cache_handler_->GetCodeCacheSize() : 0;
+}
+
+CachedMetadataHandler* Resource::CreateCachedMetadataHandler(
+ std::unique_ptr<CachedMetadataSender> send_callback) {
+ return nullptr;
+}
+
} // namespace blink
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 d9038a50641..ea72b2936c8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -31,11 +31,10 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "mojo/public/cpp/base/big_buffer.h"
-#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/code_cache.mojom-blink-forward.h"
#include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
@@ -63,6 +62,8 @@ class Clock;
namespace blink {
+class CachedMetadataHandler;
+class CachedMetadataSender;
class FetchParameters;
class ResourceClient;
class ResourceFetcher;
@@ -97,7 +98,7 @@ enum class ResourceType : uint8_t {
// should derive from ResourceClient, to get the function calls in case the
// requested data has arrived. This class also does the actual communication
// with the loader to obtain the resource from the network.
-class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
+class PLATFORM_EXPORT Resource : public GarbageCollected<Resource>,
public MemoryPressureListener {
USING_GARBAGE_COLLECTED_MIXIN(Resource);
@@ -237,9 +238,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
size_t DecodedSize() const { return decoded_size_; }
size_t OverheadSize() const { return overhead_size_; }
- size_t CodeCacheSize() const {
- return (cache_handler_) ? cache_handler_->GetCodeCacheSize() : 0;
- }
+ size_t CodeCacheSize() const;
bool IsLoaded() const { return status_ > ResourceStatus::kPending; }
@@ -350,7 +349,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
virtual void DidSendData(uint64_t /* bytesSent */,
uint64_t /* totalBytesToBeSent */) {}
virtual void DidDownloadData(uint64_t) {}
- virtual void DidDownloadToBlob(scoped_refptr<BlobDataHandle>) {}
+ virtual void DidDownloadToBlob(scoped_refptr<BlobDataHandle>);
base::TimeTicks LoadResponseEnd() const { return load_response_end_; }
@@ -510,9 +509,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
// override SetSerializedCachedMetadata with an implementation that fills the
// cache handler.
virtual CachedMetadataHandler* CreateCachedMetadataHandler(
- std::unique_ptr<CachedMetadataSender> send_callback) {
- return nullptr;
- }
+ std::unique_ptr<CachedMetadataSender> send_callback);
CachedMetadataHandler* CacheHandler() { return cache_handler_.Get(); }
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
index 61cbc358996..592174eae92 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -30,7 +30,6 @@
#include <iosfwd>
#include "base/optional.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
-#include "third_party/blink/public/platform/web_url_error.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"
@@ -38,6 +37,7 @@
namespace blink {
+struct WebURLError;
enum class ResourceRequestBlockedReason;
// ResourceError represents an error for loading a resource. There is no
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 e68da5fb2da..50929eb28a7 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
@@ -32,6 +32,7 @@
#include <utility>
#include "base/auto_reset.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/time/time.h"
#include "services/network/public/cpp/request_mode.h"
@@ -63,6 +64,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -351,7 +353,9 @@ void SetSecFetchHeaders(
destination_value = "empty";
// We'll handle adding these headers to navigations outside of Blink.
- if (strncmp(destination_value, "document", 8) != 0 &&
+ if ((strncmp(destination_value, "document", 8) != 0 ||
+ strncmp(destination_value, "iframe", 6) != 0 ||
+ strncmp(destination_value, "frame", 5) != 0) &&
request.GetRequestContext() != mojom::RequestContextType::INTERNAL) {
if (blink::RuntimeEnabledFeatures::FetchMetadataDestinationEnabled()) {
request.SetHttpHeaderField("Sec-Fetch-Dest", destination_value);
@@ -505,7 +509,11 @@ ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
mojom::RequestContextType::PING ||
resource_request.GetRequestContext() ==
mojom::RequestContextType::CSP_REPORT) {
- priority = ResourceLoadPriority::kVeryLow;
+ if (base::FeatureList::IsEnabled(features::kSetLowPriorityForBeacon)) {
+ priority = ResourceLoadPriority::kLow;
+ } else {
+ priority = ResourceLoadPriority::kVeryLow;
+ }
}
priority = AdjustPriorityWithPriorityHint(priority, type, resource_request,
@@ -572,8 +580,6 @@ ResourceFetcher::ResourceFetcher(const ResourceFetcherInit& init)
allow_stale_resources_(false),
image_fetched_(false),
should_log_request_as_invalid_in_imported_document_(false) {
- stale_while_revalidate_enabled_ =
- RuntimeEnabledFeatures::StaleWhileRevalidateEnabledByRuntimeFlag();
InstanceCounters::IncrementCounter(InstanceCounters::kResourceFetcherCounter);
if (IsMainThread())
MainThreadFetchersSet().insert(this);
@@ -870,8 +876,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
// stale resource is returned a StaleRevalidation request will be scheduled.
// Explicitly disallow stale responses for fetchers that don't have SWR
// enabled (via origin trial), and non-GET requests.
- resource_request.SetAllowStaleResponse(stale_while_revalidate_enabled_ &&
- resource_request.HttpMethod() ==
+ resource_request.SetAllowStaleResponse(resource_request.HttpMethod() ==
http_names::kGET &&
!params.IsStaleRevalidation());
@@ -916,14 +921,17 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
const scoped_refptr<const SecurityOrigin> origin =
resource_request.RequestorOrigin();
DCHECK(!options.cors_flag);
- params.MutableOptions().cors_flag = cors::CalculateCorsFlag(
- params.Url(), origin.get(), resource_request.GetMode());
+ params.MutableOptions().cors_flag =
+ cors::CalculateCorsFlag(params.Url(), origin.get(),
+ resource_request.IsolatedWorldOrigin().get(),
+ resource_request.GetMode());
// TODO(yhirano): Reject requests for non CORS-enabled schemes.
// See https://crrev.com/c/1298828.
resource_request.SetAllowStoredCredentials(cors::CalculateCredentialsFlag(
resource_request.GetCredentialsMode(),
cors::CalculateResponseTainting(
params.Url(), resource_request.GetMode(), origin.get(),
+ resource_request.IsolatedWorldOrigin().get(),
params.Options().cors_flag ? CorsFlag::Set : CorsFlag::Unset)));
}
@@ -947,6 +955,8 @@ Resource* ResourceFetcher::RequestResource(FetchParameters& params,
// We don't expect the fetcher to be used, so count such unexpected use.
UMA_HISTOGRAM_ENUMERATION("HTMLImport.UnexpectedRequest",
factory.GetType());
+
+ base::debug::DumpWithoutCrashing();
}
// If detached, we do very early return here to skip all processing below.
@@ -2023,18 +2033,9 @@ void ResourceFetcher::UpdateAllImageResourcePriorities() {
}
not_loaded_image_resources_.RemoveAll(to_be_removed);
-}
-
-void ResourceFetcher::ReloadLoFiImages() {
- for (Resource* resource : image_resources_) {
- resource->ReloadIfLoFiOrPlaceholderImage(this, Resource::kReloadAlways);
- }
-
- // |Resource::ReloadIfLoFiOrPlaceholderImage| can make images pending again,
- // so we set |not_loaded_image_resources_| to be all the images
- // conservatively. This isn't expected to cause performance problems as
- // |ReloadLoFiImages| is relatively rare.
- not_loaded_image_resources_ = image_resources_;
+ // Explicitly free the backing store to not regress memory.
+ // TODO(bikineev): Revisit when young generation is done.
+ to_be_removed.clear();
}
String ResourceFetcher::GetCacheIdentifier() const {
@@ -2080,10 +2081,6 @@ void ResourceFetcher::PrepareForLeakDetection() {
StopFetchingIncludingKeepaliveLoaders();
}
-void ResourceFetcher::SetStaleWhileRevalidateEnabled(bool enabled) {
- stale_while_revalidate_enabled_ = enabled;
-}
-
void ResourceFetcher::StopFetchingInternal(StopFetchingTarget target) {
// TODO(toyoshim): May want to suspend scheduler while canceling loaders so
// that the cancellations below do not awake unnecessary scheduling.
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 dfbd91bf482..9c3ad282fc6 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
@@ -33,7 +33,7 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
-#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink-forward.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/preload_key.h"
@@ -77,12 +77,12 @@ struct ResourceLoaderOptions;
// keep a ResourceFetcher alive past detach if scripts still reference the
// Document.
class PLATFORM_EXPORT ResourceFetcher
- : public GarbageCollectedFinalized<ResourceFetcher> {
+ : public GarbageCollected<ResourceFetcher> {
USING_PRE_FINALIZER(ResourceFetcher, ClearPreloads);
public:
// An abstract interface for creating loaders.
- class LoaderFactory : public GarbageCollectedFinalized<LoaderFactory> {
+ class LoaderFactory : public GarbageCollected<LoaderFactory> {
public:
virtual ~LoaderFactory() = default;
@@ -225,8 +225,6 @@ class PLATFORM_EXPORT ResourceFetcher
void UpdateAllImageResourcePriorities();
- void ReloadLoFiImages();
-
// Returns whether the given resource is contained as a preloaded resource.
bool ContainsAsPreload(Resource*) const;
@@ -246,8 +244,6 @@ class PLATFORM_EXPORT ResourceFetcher
// counting.
void PrepareForLeakDetection();
- void SetStaleWhileRevalidateEnabled(bool enabled);
-
using ResourceFetcherSet = HeapHashSet<WeakMember<ResourceFetcher>>;
static const ResourceFetcherSet& MainThreadFetchers();
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 dc5ab3d585b..297508b42ea 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
@@ -33,7 +33,7 @@ class FetchClientSettingsObject;
// FetchClientSettingsObject when the property is clearly defined in the spec.
// Otherwise, put it to this class.
class PLATFORM_EXPORT ResourceFetcherProperties
- : public GarbageCollectedFinalized<ResourceFetcherProperties> {
+ : public GarbageCollected<ResourceFetcherProperties> {
public:
using ControllerServiceWorkerMode = mojom::ControllerServiceWorkerMode;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
index dfa57880c7b..b3ae16d95f2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties_test.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
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 b2c4abbb313..0d5bf38942d 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
@@ -33,6 +33,7 @@
#include <memory>
#include "base/optional.h"
#include "build/build_config.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.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/public/mojom/loader/request_context_frame_type.mojom-blink.h"
@@ -81,11 +82,11 @@ constexpr char kTestResourceFilename[] = "white-1x1.png";
constexpr char kTestResourceMimeType[] = "image/png";
constexpr uint32_t kTestResourceSize = 103; // size of white-1x1.png
-void RegisterMockedURLLoadWithCustomResponse(const KURL& url,
- const ResourceResponse& response) {
- url_test_helpers::RegisterMockedURLLoadWithCustomResponse(
- url, test::PlatformTestDataPath(kTestResourceFilename),
- WrappedResourceResponse(response));
+void RegisterMockedURLLoadWithCustomResponse(const WebURL& full_url,
+ const WebString& file_path,
+ WebURLResponse response) {
+ url_test_helpers::RegisterMockedURLLoadWithCustomResponse(full_url, file_path,
+ response);
}
void RegisterMockedURLLoad(const KURL& url) {
@@ -214,7 +215,9 @@ TEST_F(ResourceFetcherTest, UseExistingResource) {
ResourceResponse response(url);
response.SetHttpStatusCode(200);
response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
FetchParameters fetch_params{ResourceRequest(url)};
Resource* resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
@@ -338,7 +341,9 @@ TEST_F(ResourceFetcherTest, VaryResource) {
response.SetHttpStatusCode(200);
response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
response.SetHttpHeaderField(http_names::kVary, "*");
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
FetchParameters fetch_params_original{ResourceRequest(url)};
Resource* resource =
@@ -353,7 +358,7 @@ TEST_F(ResourceFetcherTest, VaryResource) {
}
class RequestSameResourceOnComplete
- : public GarbageCollectedFinalized<RequestSameResourceOnComplete>,
+ : public GarbageCollected<RequestSameResourceOnComplete>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(RequestSameResourceOnComplete);
@@ -406,7 +411,9 @@ TEST_F(ResourceFetcherTest, RevalidateWhileFinishingLoading) {
response.SetHttpStatusCode(200);
response.SetHttpHeaderField(http_names::kCacheControl, "max-age=3600");
response.SetHttpHeaderField(http_names::kETag, "1234567890");
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
ResourceFetcher* fetcher1 = CreateFetcher(
*MakeGarbageCollected<TestResourceFetcherProperties>(source_origin));
@@ -440,13 +447,13 @@ TEST_F(ResourceFetcherTest, MAYBE_DontReuseMediaDataUrl) {
}
class ServeRequestsOnCompleteClient final
- : public GarbageCollectedFinalized<ServeRequestsOnCompleteClient>,
+ : public GarbageCollected<ServeRequestsOnCompleteClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(ServeRequestsOnCompleteClient);
public:
void NotifyFinished(Resource*) override {
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ url_test_helpers::ServeAsynchronousRequests();
ClearResource();
}
@@ -515,8 +522,9 @@ class ScopedMockRedirectRequester {
redirect_response.SetHttpStatusCode(301);
redirect_response.SetHttpHeaderField(http_names::kLocation, to_url);
redirect_response.SetEncodedDataLength(kRedirectResponseOverheadBytes);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(
- redirect_url, redirect_response, "");
+
+ RegisterMockedURLLoadWithCustomResponse(redirect_url, "",
+ redirect_response);
}
void RegisterFinalResource(const WebString& url) {
@@ -533,7 +541,7 @@ class ScopedMockRedirectRequester {
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
FetchParameters fetch_params(resource_request);
RawResource::Fetch(fetch_params, fetcher, nullptr);
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ url_test_helpers::ServeAsynchronousRequests();
}
private:
@@ -903,7 +911,9 @@ TEST_F(ResourceFetcherTest, ContentIdURL) {
KURL url("cid:0123456789@example.com");
ResourceResponse response(url);
response.SetHttpStatusCode(200);
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
auto* fetcher = CreateFetcher();
@@ -937,7 +947,9 @@ TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
response.SetHttpHeaderField(http_names::kCacheControl,
"max-age=0, stale-while-revalidate=40");
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
Resource* resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
ASSERT_TRUE(resource);
@@ -945,7 +957,6 @@ TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
EXPECT_TRUE(resource->IsLoaded());
EXPECT_TRUE(GetMemoryCache()->Contains(resource));
- fetcher->SetStaleWhileRevalidateEnabled(true);
ResourceRequest resource_request(url);
resource_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
fetch_params = FetchParameters(resource_request);
@@ -960,7 +971,9 @@ TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
ResourceResponse revalidate_response(url);
revalidate_response.SetHttpStatusCode(200);
platform_->GetURLLoaderMockFactory()->UnregisterURL(url);
- RegisterMockedURLLoadWithCustomResponse(url, revalidate_response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(revalidate_response));
new_resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
EXPECT_EQ(resource, new_resource);
EXPECT_TRUE(GetMemoryCache()->Contains(resource));
@@ -981,7 +994,9 @@ TEST_F(ResourceFetcherTest, CachedResourceShouldNotCrashByNullURL) {
KURL url("http://127.0.0.1:8000/foo.html");
ResourceResponse response(url);
response.SetHttpStatusCode(200);
- RegisterMockedURLLoadWithCustomResponse(url, response);
+ RegisterMockedURLLoadWithCustomResponse(
+ url, test::PlatformTestDataPath(kTestResourceFilename),
+ WrappedResourceResponse(response));
FetchParameters fetch_params{ResourceRequest(url)};
MockResource::Fetch(fetch_params, fetcher, nullptr);
ASSERT_NE(fetcher->CachedResource(url), nullptr);
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 e2999eaa1c1..16104ff9310 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
@@ -38,7 +38,7 @@ struct FetchInitiatorInfo;
// All functions except for the destructor and the trace method must be pure
// virtual, and must not be called when the associated fetcher is detached.
class PLATFORM_EXPORT ResourceLoadObserver
- : public GarbageCollectedFinalized<ResourceLoadObserver> {
+ : public GarbageCollected<ResourceLoadObserver> {
public:
virtual ~ResourceLoadObserver() = default;
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 c981ff87742..6496f9fe7e8 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
@@ -89,9 +89,6 @@ uint32_t GetFieldTrialUint32Param(const char* trial_name,
size_t GetOutstandingThrottledLimit(
const DetachableResourceFetcherProperties& properties) {
- if (!RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled())
- return ResourceLoadScheduler::kOutstandingUnlimited;
-
static const size_t main_frame_limit = GetFieldTrialUint32Param(
kResourceLoadThrottlingTrial, kOutstandingLimitForBackgroundMainFrameName,
kOutstandingLimitForBackgroundMainFrameDefault);
@@ -108,10 +105,6 @@ int TakeWholeKilobytes(int64_t& bytes) {
return kilobytes;
}
-bool IsResourceLoadThrottlingEnabled() {
- return RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled();
-}
-
} // namespace
// A class to gather throttling and traffic information to report histograms.
@@ -377,9 +370,7 @@ bool ResourceLoadScheduler::IsClientDelayable(const ClientIdWithPriority& info,
return throttleable;
case scheduler::SchedulingLifecycleState::kHidden:
case scheduler::SchedulingLifecycleState::kThrottled:
- if (IsResourceLoadThrottlingEnabled())
- return option == ThrottleOption::kThrottleable;
- return throttleable;
+ return option == ThrottleOption::kThrottleable;
case scheduler::SchedulingLifecycleState::kStopped:
return stoppable;
}
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 20e7d3d8d2f..b951ecfd303 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
@@ -82,7 +82,7 @@ class PLATFORM_EXPORT ResourceLoadSchedulerClient
// minutes, all throttleable resource loading requests are throttled
// indefinitely (i.e., threshold is zero in such a circumstance).
class PLATFORM_EXPORT ResourceLoadScheduler final
- : public GarbageCollectedFinalized<ResourceLoadScheduler>,
+ : public GarbageCollected<ResourceLoadScheduler>,
public FrameScheduler::Observer {
public:
// An option to use in calling Request(). If kCanNotBeStoppedOrThrottled is
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 91cfcfaf206..a5056c1becf 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
@@ -18,7 +18,7 @@
namespace blink {
namespace {
-class MockClient final : public GarbageCollectedFinalized<MockClient>,
+class MockClient final : public GarbageCollected<MockClient>,
public ResourceLoadSchedulerClient {
USING_GARBAGE_COLLECTED_MIXIN(MockClient);
@@ -70,9 +70,8 @@ class MockClient final : public GarbageCollectedFinalized<MockClient>,
class ResourceLoadSchedulerTest : public testing::Test {
public:
- class MockConsoleLogger final
- : public GarbageCollectedFinalized<MockConsoleLogger>,
- public ConsoleLogger {
+ class MockConsoleLogger final : public GarbageCollected<MockConsoleLogger>,
+ public ConsoleLogger {
USING_GARBAGE_COLLECTED_MIXIN(MockConsoleLogger);
public:
@@ -90,7 +89,6 @@ class ResourceLoadSchedulerTest : public testing::Test {
using ThrottleOption = ResourceLoadScheduler::ThrottleOption;
void SetUp() override {
- DCHECK(RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled());
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
properties->SetShouldBlockLoadingSubResource(true);
auto frame_scheduler = std::make_unique<scheduler::FakeFrameScheduler>();
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 fa68bec431a..3d6537e645e 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
@@ -57,6 +57,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
#include "third_party/blink/renderer/platform/loader/fetch/console_logger.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -474,6 +475,7 @@ void ResourceLoader::Start() {
const auto origin = resource_->GetOrigin();
response_tainting_ = cors::CalculateResponseTainting(
request.Url(), request.GetMode(), origin.get(),
+ request.IsolatedWorldOrigin().get(),
GetCorsFlag() ? CorsFlag::Set : CorsFlag::Unset);
}
@@ -684,7 +686,6 @@ static bool IsManualRedirectFetchRequest(const ResourceRequest& request) {
bool ResourceLoader::WillFollowRedirect(
const WebURL& new_url,
const WebURL& new_site_for_cookies,
- const base::Optional<WebSecurityOrigin>& new_top_frame_origin,
const WebString& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
@@ -699,14 +700,10 @@ bool ResourceLoader::WillFollowRedirect(
return false;
}
- scoped_refptr<const SecurityOrigin> top_frame_origin =
- new_top_frame_origin
- ? base::WrapRefCounted(new_top_frame_origin.value().Get())
- : scoped_refptr<SecurityOrigin>();
std::unique_ptr<ResourceRequest> new_request =
resource_->LastResourceRequest().CreateRedirectRequest(
- new_url, new_method, new_site_for_cookies, top_frame_origin,
- new_referrer, new_referrer_policy,
+ new_url, new_method, new_site_for_cookies, new_referrer,
+ new_referrer_policy,
!passed_redirect_response.WasFetchedViaServiceWorker());
@@ -855,8 +852,9 @@ bool ResourceLoader::WillFollowRedirect(
if (ShouldCheckCorsInResourceLoader()) {
bool new_cors_flag =
GetCorsFlag() ||
- cors::CalculateCorsFlag(new_request->Url(),
- resource_->GetOrigin().get(), request_mode);
+ cors::CalculateCorsFlag(
+ new_request->Url(), resource_->GetOrigin().get(),
+ new_request->IsolatedWorldOrigin().get(), request_mode);
resource_->MutableOptions().cors_flag = new_cors_flag;
// Cross-origin requests are only allowed certain registered schemes.
if (GetCorsFlag() && !SchemeRegistry::ShouldTreatURLSchemeAsCorsEnabled(
@@ -869,6 +867,7 @@ bool ResourceLoader::WillFollowRedirect(
}
response_tainting_ = cors::CalculateResponseTainting(
new_request->Url(), request_mode, resource_->GetOrigin().get(),
+ new_request->IsolatedWorldOrigin().get(),
GetCorsFlag() ? CorsFlag::Set : CorsFlag::Unset);
}
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 4ffb63c02c2..0046f323f2e 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
@@ -35,7 +35,7 @@
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
@@ -62,7 +62,7 @@ class ResponseBodyLoader;
// WebURLLoader and loads the resource using it. Any per-load logic should be
// implemented in this class basically.
class PLATFORM_EXPORT ResourceLoader final
- : public GarbageCollectedFinalized<ResourceLoader>,
+ : public GarbageCollected<ResourceLoader>,
public ResourceLoadSchedulerClient,
protected WebURLLoaderClient,
protected mojom::blink::ProgressClient,
@@ -116,7 +116,6 @@ class PLATFORM_EXPORT ResourceLoader final
bool WillFollowRedirect(
const WebURL& new_url,
const WebURL& new_site_for_cookies,
- const base::Optional<WebSecurityOrigin>& new_top_frame_origin,
const WebString& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
const WebString& new_method,
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 a4ac914dcc1..16769297a2d 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
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "mojo/public/cpp/base/big_buffer.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/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
index a601dc072a8..df25cab69b1 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
+ * 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
@@ -28,27 +28,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_
+#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
-#include <memory>
-#include "base/callback.h"
-#include "third_party/blink/renderer/modules/filesystem/file_system_client.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
namespace blink {
-class LocalFileSystemClient final : public FileSystemClient {
- public:
- LocalFileSystemClient();
- ~LocalFileSystemClient() override;
+ResourceLoaderOptions::ResourceLoaderOptions()
+ : data_buffering_policy(kBufferData),
+ content_security_policy_option(kCheckContentSecurityPolicy),
+ request_initiator_context(kDocumentContext),
+ synchronous_policy(kRequestAsynchronously),
+ cors_handling_by_resource_fetcher(kEnableCorsHandlingByResourceFetcher),
+ cors_flag(false),
+ parser_disposition(kParserInserted),
+ cache_aware_loading_enabled(kNotCacheAwareLoadingEnabled) {}
- bool RequestFileSystemAccessSync(ExecutionContext*) override;
- void RequestFileSystemAccessAsync(ExecutionContext*,
- base::OnceCallback<void(bool)>) override;
-};
+ResourceLoaderOptions::ResourceLoaderOptions(
+ const ResourceLoaderOptions& other) = default;
-} // namespace blink
+ResourceLoaderOptions& ResourceLoaderOptions::operator=(
+ const ResourceLoaderOptions& other) = default;
+
+ResourceLoaderOptions::~ResourceLoaderOptions() = default;
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
index 05bc75081c1..b233ca5deed 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
@@ -32,9 +32,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOADER_OPTIONS_H_
#include "base/memory/scoped_refptr.h"
-#include "services/network/public/mojom/url_loader_factory.mojom-blink.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/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.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"
@@ -74,19 +76,18 @@ enum CacheAwareLoadingEnabled : uint8_t {
};
// This class is thread-bound. Do not copy/pass an instance across threads.
-struct ResourceLoaderOptions {
+struct PLATFORM_EXPORT ResourceLoaderOptions {
USING_FAST_MALLOC(ResourceLoaderOptions);
public:
- ResourceLoaderOptions()
- : data_buffering_policy(kBufferData),
- content_security_policy_option(kCheckContentSecurityPolicy),
- request_initiator_context(kDocumentContext),
- synchronous_policy(kRequestAsynchronously),
- cors_handling_by_resource_fetcher(kEnableCorsHandlingByResourceFetcher),
- cors_flag(false),
- parser_disposition(kParserInserted),
- cache_aware_loading_enabled(kNotCacheAwareLoadingEnabled) {}
+ // We define constructors, destructor, and assignment operator in
+ // resource_loader_options.cc because they require the full definition of
+ // URLLoaderFactory for |url_loader_factory| data member, and we'd like
+ // to avoid to include huge url_loader_factory.mojom-blink.h.
+ ResourceLoaderOptions();
+ ResourceLoaderOptions(const ResourceLoaderOptions& other);
+ ResourceLoaderOptions& operator=(const ResourceLoaderOptions& other);
+ ~ResourceLoaderOptions();
FetchInitiatorInfo initiator_info;
@@ -112,8 +113,8 @@ struct ResourceLoaderOptions {
// If not null, this URLLoaderFactory should be used to load this resource
// rather than whatever factory the system might otherwise use.
// Used for example for loading blob: URLs and for prefetch loading.
- scoped_refptr<
- base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>
+ scoped_refptr<base::RefCountedData<
+ mojo::PendingRemote<network::mojom::blink::URLLoaderFactory>>>
url_loader_factory;
};
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 b0e56e37072..9a88c03ab81 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
@@ -10,7 +10,7 @@
#include "mojo/public/c/system/data_pipe.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_runtime_features.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_loader_factory.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
@@ -117,9 +117,6 @@ std::ostream& operator<<(std::ostream& o, const ResourceLoaderTest::From& f) {
}
TEST_F(ResourceLoaderTest, ResponseType) {
- // This test will be trivial if EnableOutOfBlinkCors is enabled.
- WebRuntimeFeatures::EnableOutOfBlinkCors(false);
-
const scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::Create(foo_url_);
const scoped_refptr<const SecurityOrigin> no_origin = nullptr;
@@ -302,7 +299,7 @@ TEST_F(ResourceLoaderTest, LoadDataURL_AsyncAndNonStream) {
// Helper class which stores a BytesConsumer passed by RawResource and reads the
// bytes when ReadThroughBytesConsumer is called.
class TestRawResourceClient final
- : public GarbageCollectedFinalized<TestRawResourceClient>,
+ : public GarbageCollected<TestRawResourceClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(TestRawResourceClient);
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 26d4d3d5a64..fa5cd0ad990 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
@@ -29,11 +29,14 @@
#include <memory>
#include "base/unguessable_token.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer.h"
namespace blink {
@@ -88,7 +91,6 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
const KURL& new_url,
const AtomicString& new_method,
const KURL& new_site_for_cookies,
- scoped_refptr<const SecurityOrigin> new_top_frame_origin,
const String& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
bool skip_service_worker) const {
@@ -97,7 +99,6 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
request->SetRequestorOrigin(RequestorOrigin());
request->SetHttpMethod(new_method);
request->SetSiteForCookies(new_site_for_cookies);
- request->SetTopFrameOrigin(std::move(new_top_frame_origin));
String referrer =
new_referrer.IsEmpty() ? Referrer::NoReferrer() : String(new_referrer);
// TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a
@@ -131,6 +132,7 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
request->SetFromOriginDirtyStyleSheet(IsFromOriginDirtyStyleSheet());
request->SetSignedExchangePrefetchCacheEnabled(
IsSignedExchangePrefetchCacheEnabled());
+ request->SetRecursivePrefetchToken(RecursivePrefetchToken());
return request;
}
@@ -353,6 +355,16 @@ void ResourceRequest::SetHasUserGesture(bool has_user_gesture) {
has_user_gesture_ |= has_user_gesture;
}
+bool ResourceRequest::CanDisplay(const KURL& url) const {
+ if (RequestorOrigin()->CanDisplay(url))
+ return true;
+
+ if (IsolatedWorldOrigin() && IsolatedWorldOrigin()->CanDisplay(url))
+ return true;
+
+ return false;
+}
+
const CacheControlHeader& ResourceRequest::GetCacheControlHeader() const {
if (!cache_control_header_cache_.parsed) {
cache_control_header_cache_ = ParseCacheControlDirectives(
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 00d75a4acbe..ba96c04e50c 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
@@ -35,10 +35,10 @@
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "services/network/public/mojom/cors.mojom-blink.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "services/network/public/mojom/cors.mojom-blink-forward.h"
+#include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
@@ -46,13 +46,13 @@
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
class EncodedFormData;
+struct Referrer;
// A ResourceRequest is a "request" object for ResourceLoader. Conceptually
// it is https://fetch.spec.whatwg.org/#concept-request, but it contains
@@ -82,7 +82,6 @@ class PLATFORM_EXPORT ResourceRequest final {
const KURL& new_url,
const AtomicString& new_method,
const KURL& new_site_for_cookies,
- scoped_refptr<const SecurityOrigin> new_top_frame_origin,
const String& new_referrer,
network::mojom::ReferrerPolicy new_referrer_policy,
bool skip_service_worker) const;
@@ -126,6 +125,15 @@ class PLATFORM_EXPORT ResourceRequest final {
requestor_origin_ = std::move(origin);
}
+ // The origin of the isolated world - set if this is a fetch/XHR initiated by
+ // an isolated world.
+ const scoped_refptr<const SecurityOrigin>& IsolatedWorldOrigin() const {
+ return isolated_world_origin_;
+ }
+ void SetIsolatedWorldOrigin(scoped_refptr<const SecurityOrigin> origin) {
+ isolated_world_origin_ = std::move(origin);
+ }
+
const AtomicString& HttpMethod() const;
void SetHttpMethod(const AtomicString&);
@@ -358,13 +366,6 @@ class PLATFORM_EXPORT ResourceRequest final {
}
bool IsAutomaticUpgrade() const { return is_automatic_upgrade_; }
- bool ShouldAlsoUseFactoryBoundOriginForCors() const {
- return should_also_use_factory_bound_origin_for_cors_;
- }
- void SetShouldAlsoUseFactoryBoundOriginForCors(bool value) {
- should_also_use_factory_bound_origin_for_cors_ = value;
- }
-
void SetAllowStaleResponse(bool value) { allow_stale_response_ = value; }
bool AllowsStaleResponse() const { return allow_stale_response_; }
@@ -408,6 +409,14 @@ class PLATFORM_EXPORT ResourceRequest final {
return fetch_window_id_;
}
+ void SetRecursivePrefetchToken(
+ const base::Optional<base::UnguessableToken>& token) {
+ recursive_prefetch_token_ = token;
+ }
+ const base::Optional<base::UnguessableToken>& RecursivePrefetchToken() const {
+ return recursive_prefetch_token_;
+ }
+
void SetInspectorId(uint64_t inspector_id) { inspector_id_ = inspector_id; }
uint64_t InspectorId() const { return inspector_id_; }
@@ -439,6 +448,10 @@ class PLATFORM_EXPORT ResourceRequest final {
prefetch_maybe_for_top_level_navigation;
}
+ // Whether either RequestorOrigin or IsolatedWorldOrigin can display the
+ // |url|,
+ bool CanDisplay(const KURL&) const;
+
private:
using SharableExtraData =
base::RefCountedData<std::unique_ptr<WebURLRequest::ExtraData>>;
@@ -458,6 +471,7 @@ class PLATFORM_EXPORT ResourceRequest final {
scoped_refptr<const SecurityOrigin> top_frame_origin_;
scoped_refptr<const SecurityOrigin> requestor_origin_;
+ scoped_refptr<const SecurityOrigin> isolated_world_origin_;
AtomicString http_method_;
HTTPHeaderMap http_header_fields_;
@@ -507,7 +521,6 @@ class PLATFORM_EXPORT ResourceRequest final {
bool is_revalidating_ = false;
bool is_automatic_upgrade_ = false;
- bool should_also_use_factory_bound_origin_for_cors_ = false;
base::Optional<base::UnguessableToken> devtools_token_;
base::Optional<String> devtools_id_;
@@ -530,6 +543,11 @@ class PLATFORM_EXPORT ResourceRequest final {
// the request under the cross-origin's partition. Furthermore, its reuse from
// the prefetch cache will be restricted to top-level-navigations.
bool prefetch_maybe_for_top_level_navigation_ = false;
+
+ // This is used when fetching preload header requests from cross-origin
+ // prefetch responses. The browser process uses this token to ensure the
+ // request is cached correctly.
+ base::Optional<base::UnguessableToken> recursive_prefetch_token_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
index 188cbd4ecc1..ffb5fbcea4d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
@@ -33,28 +33,11 @@ TEST(ResourceRequestTest, SetIsAdResource) {
std::unique_ptr<ResourceRequest> redirect_request =
original.CreateRedirectRequest(
KURL("https://example.test/redirect"), original.HttpMethod(),
- original.SiteForCookies(), original.TopFrameOrigin(),
- original.HttpReferrer(), original.GetReferrerPolicy(),
- original.GetSkipServiceWorker());
+ original.SiteForCookies(), original.HttpReferrer(),
+ original.GetReferrerPolicy(), original.GetSkipServiceWorker());
EXPECT_TRUE(redirect_request->IsAdResource());
}
-TEST(ResourceRequestTest, SetTopFrameURL) {
- KURL url("http://example.com");
- scoped_refptr<SecurityOrigin> origin = SecurityOrigin::Create(url);
- ResourceRequest original;
- original.SetTopFrameOrigin(origin);
-
- // Should persist across redirects.
- std::unique_ptr<ResourceRequest> redirect_request =
- original.CreateRedirectRequest(
- KURL("https://example.test/redirect"), original.HttpMethod(),
- original.SiteForCookies(), original.TopFrameOrigin(),
- original.HttpReferrer(), original.GetReferrerPolicy(),
- original.GetSkipServiceWorker());
- EXPECT_EQ(origin, redirect_request->TopFrameOrigin());
-}
-
TEST(ResourceRequestTest, UpgradeIfInsecureAcrossRedirects) {
ResourceRequest original;
EXPECT_FALSE(original.UpgradeIfInsecure());
@@ -65,9 +48,8 @@ TEST(ResourceRequestTest, UpgradeIfInsecureAcrossRedirects) {
std::unique_ptr<ResourceRequest> redirect_request =
original.CreateRedirectRequest(
KURL("https://example.test/redirect"), original.HttpMethod(),
- original.SiteForCookies(), original.TopFrameOrigin(),
- original.HttpReferrer(), original.GetReferrerPolicy(),
- original.GetSkipServiceWorker());
+ original.SiteForCookies(), original.HttpReferrer(),
+ original.GetReferrerPolicy(), original.GetSkipServiceWorker());
EXPECT_TRUE(redirect_request->UpgradeIfInsecure());
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index 2a6ebc6289b..9db2d03be02 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -31,7 +31,11 @@
#include <memory>
#include <string>
+#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"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -76,15 +80,21 @@ ResourceResponse::SignedCertificateTimestamp::IsolatedCopy() const {
signature_data_.IsolatedCopy());
}
-ResourceResponse::ResourceResponse() : is_null_(true) {}
+ResourceResponse::ResourceResponse()
+ : is_null_(true),
+ response_type_(network::mojom::FetchResponseType::kDefault) {}
ResourceResponse::ResourceResponse(const KURL& current_request_url)
- : current_request_url_(current_request_url), is_null_(false) {}
+ : current_request_url_(current_request_url),
+ is_null_(false),
+ response_type_(network::mojom::FetchResponseType::kDefault) {}
ResourceResponse::ResourceResponse(const ResourceResponse&) = default;
ResourceResponse& ResourceResponse::operator=(const ResourceResponse&) =
default;
+ResourceResponse::~ResourceResponse() = default;
+
bool ResourceResponse::IsHTTP() const {
return current_request_url_.ProtocolIsInHTTPFamily();
}
@@ -222,13 +232,21 @@ void ResourceResponse::SetSecurityDetails(
time_t valid_to,
const Vector<AtomicString>& certificate,
const SignedCertificateTimestampList& sct_list) {
- DCHECK_NE(security_style_, kWebSecurityStyleUnknown);
- DCHECK_NE(security_style_, kWebSecurityStyleNeutral);
+ DCHECK_NE(security_style_, SecurityStyle::kUnknown);
+ DCHECK_NE(security_style_, SecurityStyle::kNeutral);
security_details_ = SecurityDetails(
protocol, key_exchange, key_exchange_group, cipher, mac, subject_name,
san_list, issuer, valid_from, valid_to, certificate, sct_list);
}
+bool ResourceResponse::IsCorsSameOrigin() const {
+ return network::cors::IsCorsSameOriginResponseType(response_type_);
+}
+
+bool ResourceResponse::IsCorsCrossOrigin() const {
+ return network::cors::IsCorsCrossOriginResponseType(response_type_);
+}
+
void ResourceResponse::SetHttpHeaderField(const AtomicString& name,
const AtomicString& value) {
UpdateHeaderParsedState(name);
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 4dd70ee0c5a..6f2445073ad 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -33,12 +33,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/time/time.h"
-#include "services/network/public/cpp/cors/cors.h"
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/renderer/platform/blob/blob_data.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_header_map.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -50,6 +45,9 @@
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
// a lot of blink specific fields. WebURLResponse is the "public version"
@@ -163,6 +161,7 @@ class PLATFORM_EXPORT ResourceResponse final {
explicit ResourceResponse(const KURL& current_request_url);
ResourceResponse(const ResourceResponse&);
ResourceResponse& operator=(const ResourceResponse&);
+ ~ResourceResponse();
bool IsNull() const { return is_null_; }
bool IsHTTP() const;
@@ -281,8 +280,8 @@ class PLATFORM_EXPORT ResourceResponse final {
bool IsLegacyTLSVersion() const { return is_legacy_tls_version_; }
void SetIsLegacyTLSVersion(bool value) { is_legacy_tls_version_ = value; }
- WebSecurityStyle GetSecurityStyle() const { return security_style_; }
- void SetSecurityStyle(WebSecurityStyle security_style) {
+ SecurityStyle GetSecurityStyle() const { return security_style_; }
+ void SetSecurityStyle(SecurityStyle security_style) {
security_style_ = security_style;
}
@@ -334,13 +333,9 @@ class PLATFORM_EXPORT ResourceResponse final {
response_type_ = value;
}
// https://html.spec.whatwg.org/C/#cors-same-origin
- bool IsCorsSameOrigin() const {
- return network::cors::IsCorsSameOriginResponseType(response_type_);
- }
+ bool IsCorsSameOrigin() const;
// https://html.spec.whatwg.org/C/#cors-cross-origin
- bool IsCorsCrossOrigin() const {
- return network::cors::IsCorsCrossOriginResponseType(response_type_);
- }
+ bool IsCorsCrossOrigin() const;
// See network::ResourceResponseInfo::url_list_via_service_worker.
const Vector<KURL>& UrlListViaServiceWorker() const {
@@ -384,6 +379,11 @@ class PLATFORM_EXPORT ResourceResponse final {
uint16_t RemotePort() const { return remote_port_; }
void SetRemotePort(uint16_t value) { remote_port_ = value; }
+ bool WasAlpnNegotiated() const { return was_alpn_negotiated_; }
+ void SetWasAlpnNegotiated(bool was_alpn_negotiated) {
+ was_alpn_negotiated_ = was_alpn_negotiated;
+ }
+
const AtomicString& AlpnNegotiatedProtocol() const {
return alpn_negotiated_protocol_;
}
@@ -409,6 +409,14 @@ class PLATFORM_EXPORT ResourceResponse final {
int64_t DecodedBodyLength() const { return decoded_body_length_; }
void SetDecodedBodyLength(int64_t value);
+ const base::Optional<base::UnguessableToken>& RecursivePrefetchToken() const {
+ return recursive_prefetch_token_;
+ }
+ void SetRecursivePrefetchToken(
+ const base::Optional<base::UnguessableToken>& token) {
+ recursive_prefetch_token_ = token;
+ }
+
unsigned MemoryUsage() const {
// average size, mostly due to URL and Header Map strings
return 1280;
@@ -432,6 +440,14 @@ class PLATFORM_EXPORT ResourceResponse final {
void SetFromArchive(bool from_archive) { from_archive_ = from_archive; }
+ bool WasAlternateProtocolAvailable() const {
+ return was_alternate_protocol_available_;
+ }
+
+ void SetWasAlternateProtocolAvailable(bool was_alternate_protocol_available) {
+ was_alternate_protocol_available_ = was_alternate_protocol_available;
+ }
+
bool IsSignedExchangeInnerResponse() const {
return is_signed_exchange_inner_response_;
}
@@ -520,9 +536,14 @@ class PLATFORM_EXPORT ResourceResponse final {
// True if this resource was loaded from a MHTML archive.
bool from_archive_ = false;
+ // True if response could use alternate protocol.
+ bool was_alternate_protocol_available_ = false;
+
+ // True if the response was delivered after ALPN is negotiated.
+ bool was_alpn_negotiated_ = false;
+
// https://fetch.spec.whatwg.org/#concept-response-type
- network::mojom::FetchResponseType response_type_ =
- network::mojom::FetchResponseType::kDefault;
+ network::mojom::FetchResponseType response_type_;
// HTTP version used in the response, if known.
HTTPVersion http_version_ = kHTTPVersionUnknown;
@@ -533,7 +554,7 @@ class PLATFORM_EXPORT ResourceResponse final {
// The security style of the resource.
// This only contains a valid value when the DevTools Network domain is
// enabled. (Otherwise, it contains a default value of Unknown.)
- WebSecurityStyle security_style_ = kWebSecurityStyleUnknown;
+ SecurityStyle security_style_ = SecurityStyle::kUnknown;
// Security details of this request's connection.
base::Optional<SecurityDetails> security_details_;
@@ -588,6 +609,11 @@ class PLATFORM_EXPORT ResourceResponse final {
// Sizes of the response body in bytes after any content-encoding is
// removed.
int64_t decoded_body_length_ = 0;
+
+ // This is propagated from the browser process's PrefetchURLLoader on
+ // cross-origin prefetch responses. It is used to pass the token along to
+ // preload header requests from these responses.
+ base::Optional<base::UnguessableToken> recursive_prefetch_token_;
};
} // namespace blink
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 ce64c55af15..e6d51e04693 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
@@ -26,7 +26,7 @@ class ResponseBodyLoader;
// See ResponseBodyLoader for details. This is a virtual interface to expose
// only Drain functions.
class PLATFORM_EXPORT ResponseBodyLoaderDrainableInterface
- : public GarbageCollectedFinalized<ResponseBodyLoaderDrainableInterface> {
+ : public GarbageCollected<ResponseBodyLoaderDrainableInterface> {
public:
virtual ~ResponseBodyLoaderDrainableInterface() = default;
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 e7cc1ea2661..15b6cb9322b 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
@@ -24,7 +24,7 @@ class ResponseBodyLoaderTest : public testing::Test {
using Command = ReplayingBytesConsumer::Command;
using PublicState = BytesConsumer::PublicState;
using Result = BytesConsumer::Result;
- class TestClient final : public GarbageCollectedFinalized<TestClient>,
+ class TestClient final : public GarbageCollected<TestClient>,
public ResponseBodyLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(TestClient);
@@ -87,7 +87,7 @@ class ResponseBodyLoaderTest : public testing::Test {
bool cancelled_ = false;
};
- class ReadingClient final : public GarbageCollectedFinalized<ReadingClient>,
+ class ReadingClient final : public GarbageCollected<ReadingClient>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(ReadingClient);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
index 1dbb4570d09..24e2efe2f92 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_SCRIPT_FETCH_OPTIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_SCRIPT_FETCH_OPTIONS_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/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/web_url_request.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"
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
index 6a7b729faa6..6ef734efb47 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
@@ -14,7 +14,7 @@ namespace blink {
// to revalidate the resource. When the request has been completed the original
// resource will be removed from the memory cache.
class StaleRevalidationResourceClient
- : public GarbageCollectedFinalized<StaleRevalidationResourceClient>,
+ : public GarbageCollected<StaleRevalidationResourceClient>,
public RawResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(StaleRevalidationResourceClient);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h b/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
index 8907914c3a7..c7fdb961cd7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/worker_resource_timing_notifier.h
@@ -16,7 +16,7 @@ struct WebResourceTimingInfo;
// appropriate Performance Timeline.
// https://w3c.github.io/performance-timeline/#performance-timeline
class WorkerResourceTimingNotifier
- : public GarbageCollectedFinalized<WorkerResourceTimingNotifier> {
+ : public GarbageCollected<WorkerResourceTimingNotifier> {
public:
WorkerResourceTimingNotifier() = default;
virtual ~WorkerResourceTimingNotifier() = default;
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 ff660e46df8..e3333add828 100644
--- a/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/subresource_integrity.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
#include "base/stl_util.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"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.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 8bfa8ff7fe3..5b3753c2fdb 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
@@ -21,7 +21,6 @@
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.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/loader/testing/bytes_consumer_test_reader.h b/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
index 6fb4430be35..6a321b75317 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h
@@ -16,7 +16,7 @@ class FakeTaskRunner;
} // namespace scheduler
class BytesConsumerTestReader final
- : public GarbageCollectedFinalized<BytesConsumerTestReader>,
+ : public GarbageCollected<BytesConsumerTestReader>,
public BytesConsumer::Client {
USING_GARBAGE_COLLECTED_MIXIN(BytesConsumerTestReader);
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
index 173f2407671..5c1e0690529 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_TESTING_MOCK_RESOURCE_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/resource.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource_client.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource_client.h
index a9fe34287e3..2b2f071a462 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_resource_client.h
@@ -36,7 +36,7 @@
namespace blink {
-class MockResourceClient : public GarbageCollectedFinalized<MockResourceClient>,
+class MockResourceClient : public GarbageCollected<MockResourceClient>,
public ResourceClient {
USING_GARBAGE_COLLECTED_MIXIN(MockResourceClient);
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
index 62a3c3a96b9..3bef4165682 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/loader/testing/test_resource_fetcher_properties.h"
+#include "services/network/public/mojom/ip_address_space.mojom-blink.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
diff --git a/chromium/third_party/blink/renderer/platform/media_capabilities/DEPS b/chromium/third_party/blink/renderer/platform/media_capabilities/DEPS
new file mode 100644
index 00000000000..3bb5207e2fc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ # Don't depend on platform/.
+ "-third_party/blink/renderer/platform",
+
+ # Module.
+ "+third_party/blink/renderer/platform/media_capabilities",
+
+ # Dependencies.
+ "+media/base/eme_constants.h",
+]
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/OWNERS b/chromium/third_party/blink/renderer/platform/media_capabilities/OWNERS
index d7c53c9f4ca..d7c53c9f4ca 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/OWNERS
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_audio_configuration.h
index 060b9a8c4de..0ffec904a2d 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_audio_configuration.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_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
#include "base/optional.h"
#include "third_party/blink/public/platform/web_string.h"
@@ -25,4 +25,4 @@ struct WebAudioConfiguration {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_AUDIO_CONFIGURATION_H_
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.h
index 7a15df2a933..792fc53769c 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_info.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.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_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
namespace blink {
@@ -17,4 +17,4 @@ struct WebMediaCapabilitiesInfo {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_INFO_H_
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_key_system_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_key_system_configuration.h
index 90f7ae20825..7e1c5b0bdde 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_key_system_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_key_system_configuration.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_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
#include "media/base/eme_constants.h"
#include "third_party/blink/public/platform/web_encrypted_media_types.h"
@@ -46,4 +46,4 @@ struct WebMediaCapabilitiesKeySystemConfiguration {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CAPABILITIES_KEY_SYSTEM_CONFIGURATION_H_
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h
index 0f0e91b117a..68657673336 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h
@@ -2,12 +2,12 @@
// 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_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
#include "base/optional.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_audio_configuration.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_video_configuration.h"
+#include "third_party/blink/renderer/platform/media_capabilities/web_audio_configuration.h"
+#include "third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h"
namespace blink {
@@ -43,4 +43,4 @@ struct WebMediaConfiguration {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_CONFIGURATION_H_
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_decoding_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_decoding_configuration.h
index 568fa4152f6..5495149cca7 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_media_decoding_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_media_decoding_configuration.h
@@ -2,12 +2,12 @@
// 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_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
#include "base/optional.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_capabilities_key_system_configuration.h"
-#include "third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h"
+#include "third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_key_system_configuration.h"
+#include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
namespace blink {
@@ -32,4 +32,4 @@ struct WebMediaDecodingConfiguration : public WebMediaConfiguration {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_MEDIA_DECODING_CONFIGURATION_H_
diff --git a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_video_configuration.h b/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.h
index 9189ba35707..2dbd73c2c54 100644
--- a/chromium/third_party/blink/public/platform/modules/media_capabilities/web_video_configuration.h
+++ b/chromium/third_party/blink/renderer/platform/media_capabilities/web_video_configuration.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_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
+#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/blink/public/platform/web_string.h"
@@ -23,4 +23,4 @@ struct WebVideoConfiguration {
} // namespace blink
-#endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_MODULES_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MEDIA_CAPABILITIES_WEB_VIDEO_CONFIGURATION_H_
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 ade35b4143d..b4643ea7cb6 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
@@ -52,7 +52,7 @@ class WebAudioSourceProvider;
// TODO(hta): Consider merging the two classes.
class PLATFORM_EXPORT MediaStreamComponent final
- : public GarbageCollectedFinalized<MediaStreamComponent> {
+ : public GarbageCollected<MediaStreamComponent> {
USING_PRE_FINALIZER(MediaStreamComponent, Dispose);
private:
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
index 3622f7f631e..ea3e04c6d18 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
@@ -55,7 +55,7 @@ class PLATFORM_EXPORT MediaStreamDescriptorClient
};
class PLATFORM_EXPORT MediaStreamDescriptor final
- : public GarbageCollectedFinalized<MediaStreamDescriptor> {
+ : public GarbageCollected<MediaStreamDescriptor> {
private:
static int GenerateUniqueId();
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 354e0e0a8e8..9e18929b075 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
@@ -189,7 +189,10 @@ void MediaStreamSource::Trace(blink::Visitor* visitor) {
}
void MediaStreamSource::Dispose() {
- audio_consumers_.clear();
+ {
+ MutexLocker locker(audio_consumers_lock_);
+ audio_consumers_.clear();
+ }
platform_source_.reset();
constraints_.Reset();
}
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 fecbcc2d38f..2e4edff6f0b 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
@@ -50,7 +50,7 @@
namespace blink {
class PLATFORM_EXPORT MediaStreamSource final
- : public GarbageCollectedFinalized<MediaStreamSource> {
+ : public GarbageCollected<MediaStreamSource> {
USING_PRE_FINALIZER(MediaStreamSource, Dispose);
public:
@@ -135,7 +135,8 @@ class PLATFORM_EXPORT MediaStreamSource final
bool requires_consumer_;
HeapHashSet<WeakMember<Observer>> observers_;
Mutex audio_consumers_lock_;
- HashSet<AudioDestinationConsumer*> audio_consumers_;
+ HashSet<AudioDestinationConsumer*> audio_consumers_
+ GUARDED_BY(audio_consumers_lock_);
std::unique_ptr<WebPlatformMediaStreamSource> platform_source_;
WebMediaConstraints constraints_;
WebMediaStreamSource::Capabilities capabilities_;
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h b/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
index 19396708c83..10b339edd88 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
+++ b/chromium/third_party/blink/renderer/platform/mhtml/archive_resource.h
@@ -38,7 +38,7 @@
namespace blink {
class PLATFORM_EXPORT ArchiveResource final
- : public GarbageCollectedFinalized<ArchiveResource> {
+ : public GarbageCollected<ArchiveResource> {
public:
ArchiveResource(scoped_refptr<SharedBuffer>,
const KURL&,
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 d45cce0e56e..94d98b13a53 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
@@ -33,6 +33,7 @@
#include <stddef.h>
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
+#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink.h"
#include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_parser.h"
#include "third_party/blink/renderer/platform/mhtml/serialized_resource.h"
@@ -45,7 +46,6 @@
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
index 0f19fd944b8..985d346276c 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.h
@@ -31,7 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MHTML_MHTML_ARCHIVE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MHTML_MHTML_ARCHIVE_H_
-#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/mhtml_load_result.mojom-blink-forward.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/string_hash.h"
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
index 2e6332178bc..f08d30dab9c 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_parser.cc
@@ -91,7 +91,7 @@ void QuotedPrintableDecode(const char* data,
// This class is a limited MIME parser used to parse the MIME headers of MHTML
// files.
-class MIMEHeader : public GarbageCollectedFinalized<MIMEHeader> {
+class MIMEHeader final : public GarbageCollected<MIMEHeader> {
public:
MIMEHeader();
diff --git a/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
index d157f8ee94d..dda183cb6c9 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_BIG_STRING_MOJOM_TRAITS_H_
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "mojo/public/mojom/base/big_string.mojom-blink.h"
+#include "mojo/public/mojom/base/big_string.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index 0c0fb6cb0df..410098fd757 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -7,6 +7,11 @@ typemaps = [
"//media/mojo/mojom/audio_parameters.typemap",
"//mojo/public/cpp/base/values.typemap",
"//services/network/public/cpp/http_request_headers.typemap",
+ "//services/network/public/cpp/ip_address_for_blink.typemap",
+ "//services/network/public/cpp/ip_endpoint_for_blink.typemap",
+ "//services/network/public/cpp/network_interface_for_blink.typemap",
+ "//services/network/public/cpp/mutable_network_traffic_annotation_tag.typemap",
+ "//services/network/public/cpp/p2p.typemap",
"//third_party/blink/renderer/core/messaging/blink_cloneable_message.typemap",
"//third_party/blink/renderer/core/messaging/blink_transferable_message.typemap",
"//third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap",
@@ -21,10 +26,10 @@ typemaps = [
"//third_party/blink/renderer/platform/mojo/time.typemap",
"//third_party/blink/renderer/platform/network/encoded_form_data_element.typemap",
"//third_party/blink/renderer/platform/network/encoded_form_data.typemap",
- "//third_party/blink/public/common/manifest/display_mode.typemap",
"//third_party/blink/public/common/mediastream/media_stream.typemap",
"//third_party/blink/public/common/screen_orientation/screen_orientation_lock_types.typemap",
"//third_party/blink/public/mojom/bluetooth/bluetooth.typemap",
+ "//ui/gfx/mojom/buffer_types_for_blink.typemap",
"//ui/gfx/mojom/color_space_for_blink.typemap",
"//ui/gfx/mojom/transform.typemap",
]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/bluetooth_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/bluetooth_mojom_traits.h
index 10e78a19e7d..cde9a60e6d8 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/bluetooth_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/bluetooth_mojom_traits.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_BLUETOOTH_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_BLUETOOTH_MOJOM_TRAITS_H_
-#include "device/bluetooth/public/mojom/uuid.mojom-blink.h"
+#include "device/bluetooth/public/mojom/uuid.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h
index cbb61baa785..c6d6ec8d0a4 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h
@@ -7,7 +7,7 @@
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink-forward.h"
#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/public/platform/web_string.h"
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 24e4e456824..62f146420c9 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
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_FETCH_API_REQUEST_HEADERS_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_FETCH_API_REQUEST_HEADERS_MOJOM_TRAITS_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc b/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
index e33ef649813..7ae4b572773 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/geometry_mojom_traits_test.cc
@@ -5,7 +5,8 @@
#include <utility>
#include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/mojom/geometry.mojom-blink.h"
#include "ui/gfx/geometry/mojom/geometry_traits_test_service.mojom-blink.h"
@@ -21,9 +22,10 @@ class GeometryStructTraitsTest
GeometryStructTraitsTest() {}
protected:
- gfx::mojom::blink::GeometryTraitsTestServicePtr GetTraitsTestProxy() {
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy;
- traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService>
+ GetTraitsTestProxy() {
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy;
+ traits_test_receivers_.Add(this, proxy.BindNewPipeAndPassReceiver());
return proxy;
}
@@ -93,8 +95,8 @@ class GeometryStructTraitsTest
std::move(callback).Run(q);
}
- mojo::BindingSet<gfx::mojom::blink::GeometryTraitsTestService>
- traits_test_bindings_;
+ mojo::ReceiverSet<gfx::mojom::blink::GeometryTraitsTestService>
+ traits_test_receivers_;
base::test::TaskEnvironment task_environment_;
@@ -107,7 +109,8 @@ TEST_F(GeometryStructTraitsTest, Size) {
const int32_t kWidth = 1234;
const int32_t kHeight = 5678;
WebSize input(kWidth, kHeight);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebSize output;
proxy->EchoSize(input, &output);
EXPECT_EQ(input, output);
@@ -117,7 +120,8 @@ TEST_F(GeometryStructTraitsTest, Point) {
const float kX = 1234;
const float kY = 5678;
WebPoint input(kX, kY);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebPoint output;
proxy->EchoPoint(input, &output);
EXPECT_EQ(input, output);
@@ -127,7 +131,8 @@ TEST_F(GeometryStructTraitsTest, PointF) {
const float kX = 1.234;
const float kY = 5.678;
WebFloatPoint input(kX, kY);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebFloatPoint output;
proxy->EchoPointF(input, &output);
EXPECT_EQ(input, output);
@@ -138,7 +143,8 @@ TEST_F(GeometryStructTraitsTest, Point3D) {
const float kY = 5.678;
const float kZ = 9.098;
WebFloatPoint3D input(kX, kY, kZ);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebFloatPoint3D output;
proxy->EchoPoint3F(input, &output);
EXPECT_EQ(input, output);
@@ -150,7 +156,8 @@ TEST_F(GeometryStructTraitsTest, Rect) {
const float kWidth = 3;
const float kHeight = 4;
WebRect input(kX, kY, kWidth, kHeight);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebRect output;
proxy->EchoRect(input, &output);
EXPECT_EQ(input, output);
@@ -162,7 +169,8 @@ TEST_F(GeometryStructTraitsTest, RectF) {
const float kWidth = 3.456;
const float kHeight = 4.567;
WebFloatRect input(kX, kY, kWidth, kHeight);
- gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ mojo::Remote<gfx::mojom::blink::GeometryTraitsTestService> proxy =
+ GetTraitsTestProxy();
WebFloatRect output;
proxy->EchoRectF(input, &output);
EXPECT_EQ(input, output);
diff --git a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.cc b/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.cc
deleted file mode 100644
index a0bde42cff2..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.cc
+++ /dev/null
@@ -1,35 +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/mojo/interface_invalidator.h"
-
-namespace blink {
-
-InterfaceInvalidator::InterfaceInvalidator() {}
-
-InterfaceInvalidator::~InterfaceInvalidator() {
- weak_factory_.InvalidateWeakPtrs();
- NotifyInvalidate();
-}
-
-void InterfaceInvalidator::AddObserver(Observer* observer) {
- DCHECK(observer);
- observers_.AddObserver(observer);
-}
-
-void InterfaceInvalidator::RemoveObserver(const Observer* observer) {
- DCHECK(observer);
- observers_.RemoveObserver(observer);
-}
-
-base::WeakPtr<InterfaceInvalidator> InterfaceInvalidator::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-void InterfaceInvalidator::NotifyInvalidate() {
- for (auto& observer : observers_)
- observer.OnInvalidate();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.h b/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.h
deleted file mode 100644
index e6e815b06f1..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator.h
+++ /dev/null
@@ -1,46 +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_MOJO_INTERFACE_INVALIDATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_INTERFACE_INVALIDATOR_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-// Notifies weak interface bindings to be invalidated when this object is
-// destroyed.
-class PLATFORM_EXPORT InterfaceInvalidator {
- USING_FAST_MALLOC(InterfaceInvalidator);
-
- public:
- InterfaceInvalidator();
- ~InterfaceInvalidator();
-
- class Observer {
- public:
- virtual void OnInvalidate() = 0;
- };
-
- void AddObserver(Observer*);
- void RemoveObserver(const Observer*);
-
- base::WeakPtr<InterfaceInvalidator> GetWeakPtr();
-
- private:
- void NotifyInvalidate();
-
- base::ObserverList<Observer>::Unchecked observers_;
- base::WeakPtrFactory<InterfaceInvalidator> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(InterfaceInvalidator);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_INTERFACE_INVALIDATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc
deleted file mode 100644
index 901b04af765..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/interface_invalidator_test.cc
+++ /dev/null
@@ -1,619 +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 <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/interfaces/bindings/tests/ping_service.mojom-blink.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_binding.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_strong_binding.h"
-
-namespace blink {
-
-namespace {
-
-void DoSetFlag(bool* flag) {
- *flag = true;
-}
-
-class PingServiceImplBase : public mojo::test::blink::PingService {
- public:
- PingServiceImplBase(bool send_response = true)
- : send_response_(send_response) {}
- ~PingServiceImplBase() override {}
-
- // mojo::test::blink::PingService:
- void Ping(PingCallback callback) override {
- if (ping_handler_)
- ping_handler_.Run();
-
- if (send_response_) {
- std::move(callback).Run();
- } else {
- saved_callback_ = std::move(callback);
- }
-
- if (post_ping_handler_)
- post_ping_handler_.Run();
- }
-
- void set_ping_handler(const base::RepeatingClosure& handler) {
- ping_handler_ = handler;
- }
-
- void set_post_ping_handler(const base::RepeatingClosure& handler) {
- post_ping_handler_ = handler;
- }
-
- private:
- bool send_response_;
- PingCallback saved_callback_;
- base::RepeatingClosure ping_handler_;
- base::RepeatingClosure post_ping_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(PingServiceImplBase);
-};
-
-class PingServiceImpl : public PingServiceImplBase {
- public:
- PingServiceImpl(
- mojo::PendingReceiver<mojo::test::blink::PingService> receiver,
- bool send_response = true)
- : PingServiceImplBase(send_response),
- error_handler_called_(false),
- receiver_(this, std::move(receiver)) {
- receiver_.set_disconnect_handler(
- base::BindOnce(DoSetFlag, &error_handler_called_));
- }
-
- ~PingServiceImpl() override {}
-
- bool error_handler_called() { return error_handler_called_; }
-
- mojo::Receiver<mojo::test::blink::PingService>* receiver() {
- return &receiver_;
- }
-
- private:
- bool error_handler_called_;
- mojo::Receiver<mojo::test::blink::PingService> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
-};
-
-class InterfaceInvalidatorTest : public testing::Test {
- public:
- InterfaceInvalidatorTest() {}
- ~InterfaceInvalidatorTest() override {}
-
- private:
- base::test::TaskEnvironment task_environment_;
-
- DISALLOW_COPY_AND_ASSIGN(InterfaceInvalidatorTest);
-};
-
-class InterfaceInvalidatorObserver : public InterfaceInvalidator::Observer {
- public:
- InterfaceInvalidatorObserver(const base::RepeatingClosure& handler) {
- invalidate_handler_ = handler;
- }
- ~InterfaceInvalidatorObserver() {}
-
- void OnInvalidate() override { invalidate_handler_.Run(); }
-
- private:
- base::RepeatingClosure invalidate_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(InterfaceInvalidatorObserver);
-};
-
-TEST_F(InterfaceInvalidatorTest, DestroyNotifiesObservers) {
- int called = 0;
- auto inc_called_cb = base::BindLambdaForTesting([&] { ++called; });
- InterfaceInvalidatorObserver observer1(inc_called_cb);
- InterfaceInvalidatorObserver observer2(inc_called_cb);
- {
- InterfaceInvalidator invalidator;
- invalidator.AddObserver(&observer1);
- invalidator.AddObserver(&observer2);
- EXPECT_EQ(called, 0);
- }
- EXPECT_EQ(called, 2);
-}
-
-TEST_F(InterfaceInvalidatorTest, DestroyInvalidatesRevocableInterfacePtr) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- bool ping_called = false;
- wptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(ping_called);
-
- bool error_handler_called = false;
- wptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &error_handler_called));
-
- invalidator.reset();
- impl.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- wptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(error_handler_called);
- EXPECT_TRUE(impl.error_handler_called());
- EXPECT_TRUE(wptr.encountered_error());
- EXPECT_TRUE(wptr);
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateAfterMessageSent) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- bool called = false;
- impl.set_ping_handler(base::BindRepeating(DoSetFlag, &called));
- // The passed in callback will not be called as the interface is invalidated
- // before a response can come back.
- wptr->Ping(base::BindRepeating([] { FAIL(); }));
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(called);
- EXPECT_TRUE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, PassInterfaceThenInvalidate) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- bool impl_called = false;
- impl.set_ping_handler(base::BindRepeating(DoSetFlag, &impl_called));
- wptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- mojo::test::blink::PingServicePtr ptr(wptr.PassInterface());
- invalidator.reset();
- bool ping_called = false;
- ptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(ping_called);
- EXPECT_TRUE(impl_called);
- EXPECT_FALSE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, PassInterfaceOfInvalidatedPtr) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- impl.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- bool error_handler_called = false;
- wptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &error_handler_called));
-
- // This also destroys the original invalidator.
- invalidator = std::make_unique<InterfaceInvalidator>();
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(error_handler_called);
- ASSERT_TRUE(impl.error_handler_called());
-
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr2(
- wptr.PassInterface(), invalidator.get(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- wptr2->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterfaceInvalidatorTest,
- PassInterfaceBeforeConnectionErrorNotification) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- impl.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- wptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- // This also destroys the original invalidator.
- invalidator = std::make_unique<InterfaceInvalidator>();
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr2(
- wptr.PassInterface(), invalidator.get(),
- blink::scheduler::GetSingleThreadTaskRunnerForTesting());
- wptr2->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateAfterReset) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
- wptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- wptr.reset();
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(wptr);
-}
-
-TEST_F(InterfaceInvalidatorTest, ResetInvalidatedRevocableInterfacePtr) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
- wptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- invalidator.reset();
- wptr.reset();
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateErroredPtr) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- int called = 0;
- wptr.set_connection_error_handler(
- base::BindLambdaForTesting([&] { called++; }));
-
- impl.receiver()->reset();
- base::RunLoop().RunUntilIdle();
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(called, 1);
- EXPECT_FALSE(impl.error_handler_called());
-}
-
-// InterfacePtrs do not set up a proxy until they are used for the first
-// time.
-TEST_F(InterfaceInvalidatorTest, InvalidateBeforeProxyConfigured) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- invalidator.reset();
- wptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, MoveChangesInvalidatorObserver) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- auto wptr2(std::move(wptr));
- bool called = false;
- wptr2.set_connection_error_handler(base::BindOnce(DoSetFlag, &called));
-
- invalidator.reset();
- wptr2->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(called);
- EXPECT_TRUE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, MoveInvalidatedPointer) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- invalidator.reset();
- auto wptr2(std::move(wptr));
- wptr2->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateRevocableInterfacePtrDuringSyncIPC) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()));
-
- impl.set_ping_handler(
- base::BindLambdaForTesting([&]() { invalidator.reset(); }));
- bool result = wptr->Ping();
- EXPECT_FALSE(result);
-}
-
-TEST_F(InterfaceInvalidatorTest,
- InvalidateRevocableInterfacePtrDuringSyncIPCWithoutResponse) {
- RevocableInterfacePtr<mojo::test::blink::PingService> wptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- PingServiceImpl impl(MakeRequest(&wptr, invalidator.get()),
- false /* send_response */);
-
- impl.set_ping_handler(
- base::BindLambdaForTesting([&]() { invalidator.reset(); }));
- bool result = wptr->Ping();
- EXPECT_FALSE(result);
-}
-
-class RevocablePingServiceImpl : public PingServiceImplBase {
- public:
- RevocablePingServiceImpl(
- mojo::InterfaceRequest<mojo::test::blink::PingService> request,
- InterfaceInvalidator* invalidator,
- bool send_response = true)
- : PingServiceImplBase(send_response),
- error_handler_called_(false),
- binding_(this, std::move(request), invalidator) {
- binding_.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &error_handler_called_));
- }
-
- ~RevocablePingServiceImpl() override {}
-
- bool error_handler_called() { return error_handler_called_; }
-
- RevocableBinding<mojo::test::blink::PingService>* binding() {
- return &binding_;
- }
-
- private:
- bool error_handler_called_;
- RevocableBinding<mojo::test::blink::PingService> binding_;
-
- DISALLOW_COPY_AND_ASSIGN(RevocablePingServiceImpl);
-};
-
-TEST_F(InterfaceInvalidatorTest, DestroyInvalidatesRevocableBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- bool ping_called = false;
- ptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(ping_called);
-
- bool error_handler_called = false;
- ptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &error_handler_called));
-
- invalidator.reset();
- impl.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(error_handler_called);
- EXPECT_TRUE(impl.error_handler_called());
- EXPECT_TRUE(ptr.encountered_error());
- EXPECT_TRUE(ptr);
- EXPECT_TRUE(*impl.binding());
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateBindingBeforeResponse) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
- impl.set_ping_handler(
- base::BindLambdaForTesting([&] { invalidator.reset(); }));
-
- bool ptr_error_handler_called = false;
- ptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &ptr_error_handler_called));
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(ptr_error_handler_called);
- EXPECT_TRUE(impl.error_handler_called());
- EXPECT_TRUE(*impl.binding());
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateBindingAfterResponse) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
- impl.set_post_ping_handler(base::BindLambdaForTesting([&] {
- invalidator.reset();
- impl.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- }));
-
- bool ptr_error_handler_called = false;
- ptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &ptr_error_handler_called));
- bool ping_called = false;
- ptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(ping_called);
- EXPECT_TRUE(ptr_error_handler_called);
- EXPECT_TRUE(impl.error_handler_called());
- EXPECT_TRUE(*impl.binding());
-}
-
-TEST_F(InterfaceInvalidatorTest, UnbindThenInvalidate) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
- ptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- PingServiceImpl impl2(impl.binding()->Unbind());
- invalidator.reset();
- bool ping_called = false;
- ptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(ping_called);
- EXPECT_FALSE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, UnbindInvalidatedRevocableBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- bool ptr_error_handler_called = false;
- ptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &ptr_error_handler_called));
-
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(ptr_error_handler_called);
- ASSERT_TRUE(impl.error_handler_called());
-
- PingServiceImpl impl2(impl.binding()->Unbind());
- impl2.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(impl2.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, UnbindBeforeConnectionErrorNotification) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- bool ptr_error_handler_called = false;
- ptr.set_connection_error_handler(
- base::BindOnce(DoSetFlag, &ptr_error_handler_called));
-
- invalidator.reset();
- PingServiceImpl impl2(impl.binding()->Unbind());
- impl2.set_ping_handler(base::BindRepeating([] { FAIL(); }));
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(impl.error_handler_called());
- EXPECT_TRUE(impl2.error_handler_called());
- EXPECT_TRUE(ptr_error_handler_called);
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateClosedRevocableBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- impl.binding()->Close();
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(impl.error_handler_called());
- EXPECT_FALSE(*impl.binding());
-}
-
-TEST_F(InterfaceInvalidatorTest, CloseInvalidatedRevocableBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- invalidator.reset();
- impl.binding()->Close();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(impl.error_handler_called());
- EXPECT_FALSE(*impl.binding());
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateErroredRevocableBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- int called = 0;
- impl.binding()->set_connection_error_handler(
- base::BindLambdaForTesting([&] { called++; }));
-
- ptr.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, called);
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, called);
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateWhileRevocableBindingPaused) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- impl.binding()->PauseIncomingMethodCallProcessing();
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(impl.error_handler_called());
- impl.binding()->ResumeIncomingMethodCallProcessing();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(impl.error_handler_called());
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateRevocableBindingDuringSyncIPC) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get());
-
- impl.set_ping_handler(
- base::BindLambdaForTesting([&] { invalidator.reset(); }));
- bool result = ptr->Ping();
- EXPECT_FALSE(result);
-}
-
-TEST_F(InterfaceInvalidatorTest,
- InvalidateRevocableBindingDuringSyncIPCWithoutResponse) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- RevocablePingServiceImpl impl(MakeRequest(&ptr), invalidator.get(),
- false /* send_response */);
-
- impl.set_ping_handler(
- base::BindLambdaForTesting([&] { invalidator.reset(); }));
- bool result = ptr->Ping();
- EXPECT_FALSE(result);
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateStrongBinding) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- auto impl_ptr =
- MakeRevocableStrongBinding(std::make_unique<PingServiceImplBase>(),
- MakeRequest(&ptr), invalidator.get());
- auto* impl = reinterpret_cast<PingServiceImplBase*>(impl_ptr->impl());
-
- bool impl_called = false;
- impl->set_ping_handler(base::BindRepeating(DoSetFlag, &impl_called));
- bool ping_called = false;
- ptr->Ping(base::BindRepeating(DoSetFlag, &ping_called));
- base::RunLoop().RunUntilIdle();
- ASSERT_TRUE(impl_called);
- ASSERT_TRUE(ping_called);
-
- impl->set_ping_handler(base::BindRepeating([] { FAIL(); }));
- invalidator.reset();
- ptr->Ping(base::BindRepeating([] { FAIL(); }));
- base::RunLoop().RunUntilIdle();
-
- ASSERT_FALSE(impl_ptr);
-}
-
-TEST_F(InterfaceInvalidatorTest, InvalidateStrongBindingAfterError) {
- mojo::test::blink::PingServicePtr ptr;
- auto invalidator = std::make_unique<InterfaceInvalidator>();
- auto impl_ptr =
- MakeRevocableStrongBinding(std::make_unique<PingServiceImplBase>(),
- MakeRequest(&ptr), invalidator.get());
- ptr.set_connection_error_handler(base::BindOnce([] { FAIL(); }));
-
- ptr.reset();
- base::RunLoop().RunUntilIdle();
- invalidator.reset();
- base::RunLoop().RunUntilIdle();
-
- ASSERT_FALSE(impl_ptr);
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
index 9d065c52067..bcd6a69e8df 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "url/mojom/url.mojom-blink.h"
+#include "url/mojom/url.mojom-blink-forward.h"
#include "url/url_constants.h"
namespace mojo {
diff --git a/chromium/third_party/blink/renderer/platform/mojo/revocable_binding.h b/chromium/third_party/blink/renderer/platform/mojo/revocable_binding.h
deleted file mode 100644
index a4677276a1e..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/revocable_binding.h
+++ /dev/null
@@ -1,182 +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_MOJO_REVOCABLE_BINDING_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_BINDING_H_
-
-#include <utility>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/connection_error_callback.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/lib/binding_state.h"
-#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
-#include "mojo/public/cpp/system/core.h"
-#include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
-
-namespace blink {
-
-class MessageReceiver;
-
-// RevocableBinding is a wrapper around a Binding that has to be tied to an
-// InterfaceInvalidator when bound to a message pipe. The underlying connection
-// is automatically closed once the InterfaceInvalidator is destroyed, and the
-// binding will behave as if its peer had closed the connection. This is useful
-// for tying the lifetime of mojo interfaces to another object.
-//
-// TODO(austinct): Add set_connection_error_with_reason_handler(),
-// CloseWithReason(), ReportBadMessage() and GetBadMessageCallback() methods if
-// needed. Undesirable for now because of the std::string parameter.
-template <typename Interface,
- typename ImplRefTraits = mojo::RawPtrImplRefTraits<Interface>>
-class RevocableBinding : public InterfaceInvalidator::Observer {
- public:
- using ImplPointerType = typename ImplRefTraits::PointerType;
-
- // Constructs an incomplete binding that will use the implementation |impl|.
- // The binding may be completed with a subsequent call to the |Bind| method.
- // Does not take ownership of |impl|, which must outlive the binding.
- explicit RevocableBinding(ImplPointerType impl) : binding_(std::move(impl)) {}
-
- // Constructs a completed binding of |impl| to the message pipe endpoint in
- // |request|, taking ownership of the endpoint. Does not take ownership of
- // |impl|, which must outlive the binding. Ties the lifetime of the binding to
- // |invalidator|.
- RevocableBinding(ImplPointerType impl,
- mojo::InterfaceRequest<Interface> request,
- InterfaceInvalidator* invalidator,
- scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr)
- : RevocableBinding(std::move(impl)) {
- Bind(std::move(request), invalidator, std::move(runner));
- }
-
- // Tears down the binding, closing the message pipe and leaving the interface
- // implementation unbound.
- ~RevocableBinding() { SetInvalidator(nullptr); }
-
- // Completes a binding that was constructed with only an interface
- // implementation by removing the message pipe endpoint from |request| and
- // binding it to the previously specified implementation. Ties the lifetime of
- // the binding to |invalidator|.
- void Bind(mojo::InterfaceRequest<Interface> request,
- InterfaceInvalidator* invalidator,
- scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr) {
- DCHECK(invalidator);
- binding_.Bind(std::move(request), std::move(runner));
- SetInvalidator(invalidator);
- }
-
- // Adds a message filter to be notified of each incoming message before
- // dispatch. If a filter returns |false| from Accept(), the message is not
- // dispatched and the pipe is closed. Filters cannot be removed.
- void AddFilter(std::unique_ptr<MessageReceiver> filter) {
- binding_.AddFilter(std::move(filter));
- }
-
- // Whether there are any associated interfaces running on the pipe currently.
- bool HasAssociatedInterfaces() const {
- return binding_.HasAssociatedInterfaces();
- }
-
- // Stops processing incoming messages until
- // ResumeIncomingMethodCallProcessing().
- // Outgoing messages are still sent.
- //
- // No errors are detected on the message pipe while paused.
- //
- // This method may only be called if the object has been bound to a message
- // pipe and there are no associated interfaces running.
- void PauseIncomingMethodCallProcessing() {
- binding_.PauseIncomingMethodCallProcessing();
- }
- void ResumeIncomingMethodCallProcessing() {
- binding_.ResumeIncomingMethodCallProcessing();
- }
-
- // Closes the message pipe that was previously bound. Put this object into a
- // state where it can be rebound to a new pipe.
- void Close() {
- SetInvalidator(nullptr);
- binding_.Close();
- }
-
- // Unbinds the underlying pipe from this binding and returns it so it can be
- // used in another context, such as on another sequence or with a different
- // implementation. Put this object into a state where it can be rebound to a
- // new pipe.
- //
- // This method may only be called if the object has been bound to a message
- // pipe and there are no associated interfaces running.
- //
- // TODO(yzshen): For now, users need to make sure there is no one holding
- // on to associated interface endpoint handles at both sides of the
- // message pipe in order to call this method. We need a way to forcefully
- // invalidate associated interface endpoint handles.
- mojo::InterfaceRequest<Interface> Unbind() {
- SetInvalidator(nullptr);
- return binding_.Unbind();
- }
-
- // Sets an error handler that will be called if a connection error occurs on
- // the bound message pipe.
- //
- // This method may only be called after this RevocableBinding has been bound
- // to a message pipe. The error handler will be reset when this
- // RevocableBinding is unbound, closed or invalidated.
- void set_connection_error_handler(base::OnceClosure error_handler) {
- binding_.set_connection_error_handler(std::move(error_handler));
- }
-
- // Returns the interface implementation that was previously specified. Caller
- // does not take ownership.
- Interface* impl() { return binding_.impl(); }
-
- // Indicates whether the binding has been completed (i.e., whether a message
- // pipe has been bound to the implementation).
- explicit operator bool() const { return static_cast<bool>(binding_); }
-
- // Sends a no-op message on the underlying message pipe and runs the current
- // message loop until its response is received. This can be used in tests to
- // verify that no message was sent on a message pipe in response to some
- // stimulus.
- void FlushForTesting() { binding_.FlushForTesting(); }
-
- private:
- // InterfaceInvalidator::Observer
- void OnInvalidate() override {
- if (binding_) {
- binding_.internal_state()->RaiseError();
- }
- if (invalidator_) {
- invalidator_->RemoveObserver(this);
- }
- invalidator_.reset();
- }
-
- // Replaces the existing invalidator with a new invalidator and changes the
- // invalidator being observed.
- void SetInvalidator(InterfaceInvalidator* invalidator) {
- if (invalidator_)
- invalidator_->RemoveObserver(this);
-
- invalidator_.reset();
- if (invalidator) {
- invalidator_ = invalidator->GetWeakPtr();
- invalidator_->AddObserver(this);
- }
- }
-
- mojo::Binding<Interface, ImplRefTraits> binding_;
- base::WeakPtr<InterfaceInvalidator> invalidator_;
-
- DISALLOW_COPY_AND_ASSIGN(RevocableBinding);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_BINDING_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h b/chromium/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h
deleted file mode 100644
index 555be28de28..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/revocable_interface_ptr.h
+++ /dev/null
@@ -1,241 +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_MOJO_REVOCABLE_INTERFACE_PTR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_INTERFACE_PTR_H_
-
-#include <stdint.h>
-
-#include <cstddef>
-#include <string>
-#include <utility>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/connection_error_callback.h"
-#include "mojo/public/cpp/bindings/interface_ptr_info.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
-#include "third_party/blink/renderer/platform/mojo/interface_invalidator.h"
-
-namespace blink {
-
-// RevocableInterfacePtr is a wrapper around an InterfacePtr that has to be tied
-// to an InterfaceInvalidator when bound to a message pipe. The underlying
-// connection is closed once the InterfaceInvalidator is destroyed and the
-// interface will behave as if its peer had closed the connection. This is
-// useful for tying the lifetime of interface pointers to another object.
-template <typename Interface>
-class RevocableInterfacePtr : public InterfaceInvalidator::Observer {
- public:
- using PtrType = mojo::InterfacePtr<Interface>;
- using PtrInfoType = mojo::InterfacePtrInfo<Interface>;
- using Proxy = typename Interface::Proxy_;
-
- // Constructs an unbound RevocableInterfacePtr.
- RevocableInterfacePtr() {}
- RevocableInterfacePtr(std::nullptr_t) {}
-
- // Takes over the binding of another RevocableInterfacePtr.
- RevocableInterfacePtr(RevocableInterfacePtr&& other) noexcept {
- interface_ptr_ = std::move(other.interface_ptr_);
- SetInvalidator(other.invalidator_.get());
- // Reset the other interface ptr to remove it as an observer of the
- // invalidator.
- other.reset();
- }
-
- RevocableInterfacePtr(
- PtrInfoType info,
- InterfaceInvalidator* invalidator,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- Bind(std::move(info), invalidator, task_runner);
- }
-
- // Takes over the binding of another RevocableInterfacePtr, and closes any
- // message pipe already bound to this pointer.
- RevocableInterfacePtr& operator=(RevocableInterfacePtr&& other) noexcept {
- reset();
- interface_ptr_ = std::move(other.interface_ptr_);
- SetInvalidator(other.invalidator_.get());
- // Reset the other interface ptr to remove it as an observer of the
- // invalidator.
- other.reset();
- return *this;
- }
-
- // Assigning nullptr to this class causes it to close the currently bound
- // message pipe (if any) and returns the pointer to the unbound state.
- RevocableInterfacePtr& operator=(std::nullptr_t) {
- reset();
- return *this;
- }
-
- // Closes the bound message pipe (if any) on destruction.
- ~RevocableInterfacePtr() {
- if (invalidator_) {
- invalidator_->RemoveObserver(this);
- }
- }
-
- // Binds the RevocableInterfacePtr to a remote implementation of Interface.
- //
- // Calling with an invalid |info| (containing an invalid message pipe handle)
- // has the same effect as reset(). In this case, the InterfacePtr is not
- // considered as bound.
- //
- // |runner| must belong to the same thread. It will be used to dispatch all
- // callbacks and connection error notification. It is useful when you attach
- // multiple task runners to a single thread for the purposes of task
- // scheduling.
- void Bind(PtrInfoType info,
- InterfaceInvalidator* invalidator,
- scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr) {
- DCHECK(invalidator);
- reset();
- if (info.is_valid()) {
- interface_ptr_.Bind(std::move(info), std::move(runner));
- invalidator_ = invalidator->GetWeakPtr();
- invalidator_->AddObserver(this);
- }
- }
-
- // Returns a raw pointer to the local proxy. Caller does not take ownership.
- // Note that the local proxy is thread hostile, as stated above.
- Proxy* get() const { return interface_ptr_.get(); }
-
- // Functions like a pointer to Interface. Must already be bound.
- Proxy* operator->() const { return get(); }
- Proxy& operator*() const { return *get(); }
-
- // Returns the version number of the interface that the remote side supports.
- uint32_t version() const { return interface_ptr_.version(); }
-
- // Queries the max version that the remote side supports. On completion, the
- // result will be returned as the input of |callback|. The version number of
- // this interface pointer will also be updated.
- void QueryVersion(const base::RepeatingCallback<void(uint32_t)>& callback) {
- interface_ptr_.QueryVersion(callback);
- }
-
- // If the remote side doesn't support the specified version, it will close its
- // end of the message pipe asynchronously. This does nothing if it's already
- // known that the remote side supports the specified version, i.e., if
- // |version <= this->version()|.
- //
- // After calling RequireVersion() with a version not supported by the remote
- // side, all subsequent calls to interface methods will be ignored.
- void RequireVersion(uint32_t version) {
- interface_ptr_.RequireVersion(version);
- }
-
- // Sends a no-op message on the underlying message pipe and runs the current
- // message loop until its response is received. This can be used in tests to
- // verify that no message was sent on a message pipe in response to some
- // stimulus.
- void FlushForTesting() { interface_ptr_.FlushForTesting(); }
-
- // Closes the bound message pipe, if any.
- void reset() {
- interface_ptr_.reset();
- SetInvalidator(nullptr);
- }
-
- // Similar to the method above, but also specifies a disconnect reason.
- void ResetWithReason(uint32_t custom_reason, const std::string& description) {
- interface_ptr_.ResetWithReason(custom_reason, description);
- SetInvalidator(nullptr);
- }
-
- // Whether there are any associated interfaces running on the pipe currently.
- bool HasAssociatedInterfaces() const {
- return interface_ptr_.HasAssociatedInterfaces();
- }
-
- // Indicates whether the message pipe has encountered an error. If true,
- // method calls made on this interface will be dropped (and may already have
- // been dropped).
- bool encountered_error() const { return interface_ptr_.encountered_error(); }
-
- // Registers a handler to receive error notifications. The handler will be
- // called from the sequence that owns this RevocableInterfacePtr.
- //
- // This method may only be called after the RevocableInterfacePtr has been
- // bound to a message pipe.
- void set_connection_error_handler(base::OnceClosure error_handler) {
- interface_ptr_.set_connection_error_handler(std::move(error_handler));
- }
-
- void set_connection_error_with_reason_handler(
- mojo::ConnectionErrorWithReasonCallback error_handler) {
- interface_ptr_.set_connection_error_with_reason_handler(
- std::move(error_handler));
- }
-
- // Unbinds the RevocableInterfacePtr and returns the information which could
- // be used to setup a RevocableInterfacePtr again. See comments on
- // InterfacePtr::PassInterface for details.
- PtrInfoType PassInterface() {
- SetInvalidator(nullptr);
- return interface_ptr_.PassInterface();
- }
-
- bool operator==(const RevocableInterfacePtr& other) const {
- if (this == &other)
- return true;
-
- // Now that the two refer to different objects, they are equivalent if
- // and only if they are both null.
- return !(*this) && !other;
- }
-
- // Allow RevocableInterfacePtr<> to be used in boolean expressions.
- explicit operator bool() const { return static_cast<bool>(interface_ptr_); }
-
- private:
- // InterfaceInvalidator::Observer
- void OnInvalidate() override {
- interface_ptr_.internal_state()->RaiseError();
- if (invalidator_) {
- invalidator_->RemoveObserver(this);
- }
- invalidator_.reset();
- }
-
- // Replaces the existing invalidator with a new invalidator and changes the
- // invalidator being observed.
- void SetInvalidator(InterfaceInvalidator* invalidator) {
- if (invalidator_)
- invalidator_->RemoveObserver(this);
-
- invalidator_.reset();
- if (invalidator) {
- invalidator_ = invalidator->GetWeakPtr();
- invalidator_->AddObserver(this);
- }
- }
-
- PtrType interface_ptr_;
- base::WeakPtr<InterfaceInvalidator> invalidator_;
-
- DISALLOW_COPY_AND_ASSIGN(RevocableInterfacePtr);
-};
-
-template <typename Interface>
-mojo::InterfaceRequest<Interface> MakeRequest(
- RevocableInterfacePtr<Interface>* ptr,
- InterfaceInvalidator* invalidator,
- scoped_refptr<base::SingleThreadTaskRunner> runner = nullptr) {
- mojo::MessagePipe pipe;
- ptr->Bind(mojo::InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u),
- invalidator, std::move(runner));
- return mojo::InterfaceRequest<Interface>(std::move(pipe.handle1));
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_INTERFACE_PTR_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/revocable_strong_binding.h b/chromium/third_party/blink/renderer/platform/mojo/revocable_strong_binding.h
deleted file mode 100644
index 802868736ba..00000000000
--- a/chromium/third_party/blink/renderer/platform/mojo/revocable_strong_binding.h
+++ /dev/null
@@ -1,134 +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_MOJO_REVOCABLE_STRONG_BINDING_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_STRONG_BINDING_H_
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "mojo/public/cpp/bindings/connection_error_callback.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/cpp/bindings/message_header_validator.h"
-#include "mojo/public/cpp/system/core.h"
-#include "third_party/blink/renderer/platform/mojo/revocable_binding.h"
-
-namespace blink {
-
-class InterfaceInvalidator;
-
-template <typename Interface>
-class RevocableStrongBinding;
-
-template <typename Interface>
-using RevocableStrongBindingPtr =
- base::WeakPtr<RevocableStrongBinding<Interface>>;
-
-// This is a wrapper around a StrongBinding that binds it to an interface
-// invalidator. When the invalidator is destroyed or a connection error is
-// detected, the interface implementation is deleted. If the task runner that a
-// RevocableStrongBinding is bound on is stopped, the connection error handler
-// will not be invoked and the implementation will not be deleted.
-//
-// To use, call RevocableStrongBinding<T>::Create() (see below) or the helper
-// MakeRevocableStrongBinding function:
-//
-// MakeRevocableStrongBinding(std::make_unique<FooImpl>(),
-// std::move(foo_request));
-//
-template <typename Interface>
-class RevocableStrongBinding {
- public:
- // Create a new RevocableStrongBinding instance. The instance owns itself,
- // cleaning up only in the event of a pipe connection error or invalidation.
- // Returns a WeakPtr to the new RevocableStrongBinding instance.
- static RevocableStrongBindingPtr<Interface> Create(
- std::unique_ptr<Interface> impl,
- mojo::InterfaceRequest<Interface> request,
- InterfaceInvalidator* invalidator) {
- RevocableStrongBinding* binding = new RevocableStrongBinding(
- std::move(impl), std::move(request), invalidator);
- return binding->weak_factory_.GetWeakPtr();
- }
-
- // Note: The error handler must not delete the interface implementation.
- //
- // This method may only be called after this RevocableStrongBinding has been
- // bound to a message pipe.
- void set_connection_error_handler(base::OnceClosure error_handler) {
- DCHECK(binding_.is_bound());
- connection_error_handler_ = std::move(error_handler);
- }
-
- // Stops processing incoming messages until
- // ResumeIncomingMethodCallProcessing().
- // Outgoing messages are still sent.
- //
- // No errors are detected on the message pipe while paused.
- //
- // This method may only be called if the object has been bound to a message
- // pipe and there are no associated interfaces running.
- void PauseIncomingMethodCallProcessing() {
- binding_.PauseIncomingMethodCallProcessing();
- }
- void ResumeIncomingMethodCallProcessing() {
- binding_.ResumeIncomingMethodCallProcessing();
- }
-
- // Forces the binding to close. This destroys the RevocableStrongBinding
- // instance.
- void Close() { delete this; }
-
- Interface* impl() { return impl_.get(); }
-
- // Sends a message on the underlying message pipe and runs the current
- // message loop until its response is received. This can be used in tests to
- // verify that no message was sent on a message pipe in response to some
- // stimulus.
- void FlushForTesting() { binding_.FlushForTesting(); }
-
- private:
- RevocableStrongBinding(std::unique_ptr<Interface> impl,
- mojo::InterfaceRequest<Interface> request,
- InterfaceInvalidator* invalidator)
- : impl_(std::move(impl)),
- binding_(impl_.get(), std::move(request), invalidator) {
- binding_.set_connection_error_handler(base::BindOnce(
- &RevocableStrongBinding::OnConnectionError, base::Unretained(this)));
- }
-
- ~RevocableStrongBinding() = default;
-
- void OnConnectionError() {
- if (connection_error_handler_) {
- std::move(connection_error_handler_).Run();
- }
- Close();
- }
-
- std::unique_ptr<Interface> impl_;
- base::OnceClosure connection_error_handler_;
- RevocableBinding<Interface> binding_;
- base::WeakPtrFactory<RevocableStrongBinding> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(RevocableStrongBinding);
-};
-
-template <typename Interface, typename Impl>
-RevocableStrongBindingPtr<Interface> MakeRevocableStrongBinding(
- std::unique_ptr<Impl> impl,
- mojo::InterfaceRequest<Interface> request,
- InterfaceInvalidator* invalidator) {
- return RevocableStrongBinding<Interface>::Create(
- std::move(impl), std::move(request), invalidator);
-}
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_REVOCABLE_STRONG_BINDING_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 d483e3f331d..762af709982 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,7 +7,7 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "url/mojom/origin.mojom-blink.h"
+#include "url/mojom/origin.mojom-blink-forward.h"
#include "url/scheme_host_port.h"
namespace mojo {
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 cf91f10861c..1b660e6ffc9 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
@@ -21,6 +21,8 @@
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/network/form_data_encoder.h"
#include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h"
@@ -59,11 +61,10 @@ FormDataElement::FormDataElement(
: type_(kDataPipe), data_pipe_getter_(std::move(data_pipe_getter)) {}
FormDataElement::FormDataElement(const FormDataElement&) = default;
-FormDataElement::FormDataElement(FormDataElement&&) noexcept = default;
+FormDataElement::FormDataElement(FormDataElement&&) = default;
FormDataElement::~FormDataElement() = default;
FormDataElement& FormDataElement::operator=(const FormDataElement&) = default;
-FormDataElement& FormDataElement::operator=(FormDataElement&&) noexcept =
- default;
+FormDataElement& FormDataElement::operator=(FormDataElement&&) = default;
bool operator==(const FormDataElement& a, const FormDataElement& b) {
if (&a == &b)
@@ -150,9 +151,10 @@ scoped_refptr<EncodedFormData> EncodedFormData::DeepCopy() const {
e.blob_uuid_.IsolatedCopy(), e.optional_blob_data_handle_));
break;
case FormDataElement::kDataPipe:
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- (*e.data_pipe_getter_->GetPtr())
- ->Clone(mojo::MakeRequest(&data_pipe_getter));
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter;
+ e.data_pipe_getter_->GetDataPipeGetter()->Clone(
+ data_pipe_getter.InitWithNewPipeAndPassReceiver());
auto wrapped = base::MakeRefCounted<WrappedDataPipeGetter>(
std::move(data_pipe_getter));
form_data->elements_.UncheckedAppend(
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
index c950519f254..865f664dd07 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data.h
@@ -30,7 +30,6 @@
#include <utility>
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "third_party/blink/renderer/platform/blob/blob_data.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"
@@ -62,12 +61,12 @@ class PLATFORM_EXPORT FormDataElement final {
explicit FormDataElement(scoped_refptr<WrappedDataPipeGetter>);
FormDataElement(const FormDataElement&);
- FormDataElement(FormDataElement&&) noexcept;
+ FormDataElement(FormDataElement&&);
~FormDataElement();
FormDataElement& operator=(const FormDataElement&);
- FormDataElement& operator=(FormDataElement&&) noexcept;
+ FormDataElement& operator=(FormDataElement&&);
bool IsSafeToSendToAnotherThread() const;
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
index 4e64779717c..0df4fbecb5a 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.cc
@@ -11,6 +11,7 @@
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
@@ -66,29 +67,32 @@ StructTraits<blink::mojom::FetchAPIDataElementDataView,
}
// static
-network::mojom::blink::DataPipeGetterPtrInfo StructTraits<
+mojo::PendingRemote<network::mojom::blink::DataPipeGetter> StructTraits<
blink::mojom::FetchAPIDataElementDataView,
blink::FormDataElement>::data_pipe_getter(const blink::FormDataElement&
data) {
if (data.type_ == blink::FormDataElement::kDataPipe) {
if (!data.data_pipe_getter_)
- return nullptr;
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- (*data.data_pipe_getter_->GetPtr())
- ->Clone(mojo::MakeRequest(&data_pipe_getter));
- return data_pipe_getter.PassInterface();
+ return mojo::NullRemote();
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter> data_pipe_getter;
+ data.data_pipe_getter_->GetDataPipeGetter()->Clone(
+ data_pipe_getter.InitWithNewPipeAndPassReceiver());
+ return data_pipe_getter;
}
if (data.type_ == blink::FormDataElement::kEncodedBlob) {
if (data.optional_blob_data_handle_) {
- blink::mojom::blink::BlobPtr blob_ptr(blink::mojom::blink::BlobPtrInfo(
- data.optional_blob_data_handle_->CloneBlobRemote().PassPipe(),
- blink::mojom::blink::Blob::Version_));
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter_ptr;
- blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr));
- return data_pipe_getter_ptr.PassInterface();
+ mojo::Remote<blink::mojom::blink::Blob> blob_remote(
+ mojo::PendingRemote<blink::mojom::blink::Blob>(
+ data.optional_blob_data_handle_->CloneBlobRemote().PassPipe(),
+ blink::mojom::blink::Blob::Version_));
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter_remote;
+ blob_remote->AsDataPipeGetter(
+ data_pipe_getter_remote.InitWithNewPipeAndPassReceiver());
+ return data_pipe_getter_remote;
}
}
- return nullptr;
+ return mojo::NullRemote();
}
// static
@@ -139,15 +143,13 @@ bool StructTraits<blink::mojom::FetchAPIDataElementDataView,
}
case network::mojom::DataElementType::kDataPipe: {
out->type_ = blink::FormDataElement::kDataPipe;
- auto data_pipe_ptr_info = data.TakeDataPipeGetter<
- network::mojom::blink::DataPipeGetterPtrInfo>();
- DCHECK(data_pipe_ptr_info.is_valid());
+ auto data_pipe_ptr_remote = data.TakeDataPipeGetter<
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>>();
+ DCHECK(data_pipe_ptr_remote.is_valid());
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- data_pipe_getter.Bind(std::move(data_pipe_ptr_info));
out->data_pipe_getter_ =
base::MakeRefCounted<blink::WrappedDataPipeGetter>(
- std::move(data_pipe_getter));
+ std::move(data_pipe_ptr_remote));
break;
}
case network::mojom::DataElementType::kBlob:
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
index 74c00ea5c7e..c81eef75fe8 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_ELEMENT_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_ELEMENT_MOJOM_TRAITS_H_
-#include "services/network/public/mojom/url_loader.mojom-blink.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "services/network/public/mojom/url_loader.mojom-blink-forward.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
@@ -27,12 +28,12 @@ struct PLATFORM_EXPORT StructTraits<blink::mojom::FetchAPIDataElementDataView,
return data.blob_uuid_;
}
- static network::mojom::blink::DataPipeGetterPtrInfo data_pipe_getter(
- const blink::FormDataElement& data);
+ static mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter(const blink::FormDataElement& data);
- static network::mojom::blink::ChunkedDataPipeGetterPtrInfo
+ static mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
chunked_data_pipe_getter(const blink::FormDataElement& data) {
- return nullptr;
+ return mojo::NullRemote();
}
static uint64_t offset(const blink::FormDataElement& data) {
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
index 0a403da6821..07b98ae23b7 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_mojom_traits.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_ENCODED_FORM_DATA_MOJOM_TRAITS_H_
-#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink-forward.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
namespace mojo {
diff --git a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_test.cc b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
index b333ac5410b..461380f721c 100644
--- a/chromium/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
+++ b/chromium/third_party/blink/renderer/platform/network/encoded_form_data_test.cc
@@ -10,6 +10,7 @@
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/string_traits_wtf.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/network/public/mojom/url_loader.mojom-blink.h"
@@ -147,7 +148,7 @@ TEST_F(EncodedFormDataMojomTraitsTest, Roundtrips_FormDataElement) {
mojo::MessagePipe pipe;
original3.optional_blob_data_handle_ = BlobDataHandle::Create(
original3.blob_uuid_, "type-test", 100,
- mojom::blink::BlobPtrInfo(std::move(pipe.handle0), 0));
+ mojo::PendingRemote<mojom::blink::Blob>(std::move(pipe.handle0), 0));
FormDataElement copied3;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<
blink::mojom::blink::FetchAPIDataElement>(&original3, &copied3));
@@ -155,8 +156,8 @@ TEST_F(EncodedFormDataMojomTraitsTest, Roundtrips_FormDataElement) {
FormDataElement original4;
original4.type_ = blink::FormDataElement::kDataPipe;
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter;
- auto request = mojo::MakeRequest(&data_pipe_getter);
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter> data_pipe_getter;
+ ignore_result(data_pipe_getter.InitWithNewPipeAndPassReceiver());
original4.data_pipe_getter_ =
base::MakeRefCounted<blink::WrappedDataPipeGetter>(
std::move(data_pipe_getter));
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 f6e9b52b6be..feee0ce34f6 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
@@ -8,7 +8,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
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 3067328559b..4b686e1e360 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
@@ -362,9 +362,9 @@ class PLATFORM_EXPORT NetworkStateNotifier {
double GetRandomMultiplier(const String& host) const;
mutable Mutex mutex_;
- NetworkState state_;
- bool has_override_;
- NetworkState override_;
+ NetworkState state_ GUARDED_BY(mutex_);
+ bool has_override_ GUARDED_BY(mutex_);
+ NetworkState override_ GUARDED_BY(mutex_);
ObserverListMap connection_observers_;
ObserverListMap on_line_state_observers_;
diff --git a/chromium/third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h b/chromium/third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h
index f50bf1467a1..96ee5dd39bd 100644
--- a/chromium/third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h
+++ b/chromium/third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h
@@ -7,6 +7,8 @@
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/data_pipe_getter.mojom-blink.h"
namespace blink {
@@ -18,16 +20,17 @@ class PLATFORM_EXPORT WrappedDataPipeGetter final
: public RefCounted<WrappedDataPipeGetter> {
public:
explicit WrappedDataPipeGetter(
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter)
+ mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
+ data_pipe_getter)
: data_pipe_getter_(std::move(data_pipe_getter)) {}
~WrappedDataPipeGetter() = default;
- network::mojom::blink::DataPipeGetterPtr* GetPtr() {
- return &data_pipe_getter_;
+ network::mojom::blink::DataPipeGetter* GetDataPipeGetter() {
+ return data_pipe_getter_.get();
}
private:
- network::mojom::blink::DataPipeGetterPtr data_pipe_getter_;
+ mojo::Remote<network::mojom::blink::DataPipeGetter> data_pipe_getter_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/DEPS b/chromium/third_party/blink/renderer/platform/p2p/DEPS
new file mode 100644
index 00000000000..4dca1d572eb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/DEPS
@@ -0,0 +1,13 @@
+include_rules = [
+ "+base/observer_list_threadsafe.h",
+ "+crypto/random.h",
+ "+jingle/glue/utils.h",
+ "+media/base/media_permission.h",
+ "+net/base/ip_address.h",
+ "+net/base/ip_endpoint.h",
+ "+net/base/network_change_notifier.h",
+ "+net/base/network_interfaces.h",
+ "+net/traffic_annotation/network_traffic_annotation.h",
+ "+services/network/public/cpp/p2p_param_traits.h",
+ "+services/network/public/cpp/p2p_socket_type.h",
+]
diff --git a/chromium/third_party/blink/renderer/platform/p2p/OWNERS b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
new file mode 100644
index 00000000000..70573c449d9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/OWNERS
@@ -0,0 +1,4 @@
+sergeyu@chromium.org
+juberti@chromium.org
+
+# COMPONENT: Blink>WebRTC
diff --git a/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.cc b/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.cc
new file mode 100644
index 00000000000..4895e42047e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.cc
@@ -0,0 +1,65 @@
+// 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/p2p/empty_network_manager.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "third_party/blink/renderer/platform/p2p/network_manager_uma.h"
+
+namespace blink {
+
+EmptyNetworkManager::EmptyNetworkManager(rtc::NetworkManager* network_manager)
+ : network_manager_(network_manager) {
+ DCHECK(network_manager);
+ DETACH_FROM_THREAD(thread_checker_);
+ set_enumeration_permission(ENUMERATION_BLOCKED);
+ network_manager_->SignalNetworksChanged.connect(
+ this, &EmptyNetworkManager::OnNetworksChanged);
+}
+
+EmptyNetworkManager::~EmptyNetworkManager() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+void EmptyNetworkManager::StartUpdating() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ ++start_count_;
+ network_manager_->StartUpdating();
+}
+
+void EmptyNetworkManager::StopUpdating() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ network_manager_->StopUpdating();
+ --start_count_;
+ DCHECK_GE(start_count_, 0);
+}
+
+void EmptyNetworkManager::GetNetworks(NetworkList* networks) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ networks->clear();
+}
+
+bool EmptyNetworkManager::GetDefaultLocalAddress(
+ int family,
+ rtc::IPAddress* ipaddress) const {
+ return network_manager_->GetDefaultLocalAddress(family, ipaddress);
+}
+
+void EmptyNetworkManager::OnNetworksChanged() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (!start_count_)
+ return;
+
+ if (!sent_first_update_)
+ blink::ReportIPPermissionStatus(blink::PERMISSION_NOT_REQUESTED);
+
+ sent_first_update_ = true;
+ SignalNetworksChanged();
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..77d4363464a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/empty_network_manager.h
@@ -0,0 +1,69 @@
+// 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_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"
+#include "third_party/webrtc/rtc_base/network.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
+
+namespace rtc {
+class IPAddress;
+} // namespace rtc
+
+namespace blink {
+
+// A NetworkManager implementation which handles the case where local address
+// enumeration is not requested and just returns empty network lists. This class
+// is not thread safe and should only be used by WebRTC's network thread.
+class EmptyNetworkManager : public rtc::NetworkManagerBase,
+ public sigslot::has_slots<> {
+ public:
+ // This class is created by WebRTC's signaling thread but used by WebRTC's
+ // worker thread |task_runner|.
+ PLATFORM_EXPORT explicit EmptyNetworkManager(
+ rtc::NetworkManager* network_manager);
+ PLATFORM_EXPORT ~EmptyNetworkManager() override;
+
+ // rtc::NetworkManager:
+ void StartUpdating() override;
+ void StopUpdating() override;
+ void GetNetworks(NetworkList* networks) const override;
+ bool GetDefaultLocalAddress(int family,
+ rtc::IPAddress* ipaddress) const override;
+
+ private:
+ // Receive callback from the wrapped NetworkManager when the underneath
+ // network list is changed.
+ //
+ // We wait for this so that we don't signal networks changed before we have
+ // default IP addresses.
+ void OnNetworksChanged();
+
+ THREAD_CHECKER(thread_checker_);
+
+ // Whether we have fired the first SignalNetworksChanged.
+ // Used to ensure we only report metrics once.
+ bool sent_first_update_ = false;
+
+ // SignalNetworksChanged will only be fired if there is any outstanding
+ // StartUpdating.
+ int start_count_ = 0;
+
+ // |network_manager_| is just a reference, owned by
+ // PeerConnectionDependencyFactory.
+ rtc::NetworkManager* network_manager_;
+
+ base::WeakPtrFactory<EmptyNetworkManager> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(EmptyNetworkManager);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_EMPTY_NETWORK_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc
new file mode 100644
index 00000000000..c5131f81207
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.cc
@@ -0,0 +1,224 @@
+// 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/p2p/filtering_network_manager.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "media/base/media_permission.h"
+
+namespace blink {
+
+FilteringNetworkManager::FilteringNetworkManager(
+ rtc::NetworkManager* network_manager,
+ const GURL& requesting_origin,
+ media::MediaPermission* media_permission,
+ bool allow_mdns_obfuscation)
+ : network_manager_(network_manager),
+ media_permission_(media_permission),
+ requesting_origin_(requesting_origin),
+ allow_mdns_obfuscation_(allow_mdns_obfuscation) {
+ DETACH_FROM_THREAD(thread_checker_);
+ set_enumeration_permission(ENUMERATION_BLOCKED);
+
+ // If the feature is not enabled, just return ALLOWED as it's requested.
+ if (!media_permission_) {
+ started_permission_check_ = true;
+ set_enumeration_permission(ENUMERATION_ALLOWED);
+ VLOG(3) << "media_permission is not passed, granting permission";
+ return;
+ }
+}
+
+FilteringNetworkManager::~FilteringNetworkManager() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // This helps to catch the case if permission never comes back.
+ if (!start_updating_time_.is_null())
+ ReportMetrics(false);
+}
+
+base::WeakPtr<FilteringNetworkManager> FilteringNetworkManager::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+void FilteringNetworkManager::Initialize() {
+ rtc::NetworkManagerBase::Initialize();
+ if (media_permission_)
+ CheckPermission();
+}
+
+void FilteringNetworkManager::StartUpdating() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(started_permission_check_);
+
+ if (start_updating_time_.is_null()) {
+ start_updating_time_ = base::TimeTicks::Now();
+ network_manager_->SignalNetworksChanged.connect(
+ this, &FilteringNetworkManager::OnNetworksChanged);
+ }
+
+ // Update |pending_network_update_| and |start_count_| before calling
+ // StartUpdating, in case the update signal is fired synchronously.
+ pending_network_update_ = true;
+ ++start_count_;
+ network_manager_->StartUpdating();
+ // If we have not sent the first update, which implies we have not received
+ // the first network update from the base network manager, we wait until the
+ // base network manager signals a network change for us to populate the
+ // network information in |OnNetworksChanged| and fire the event there.
+ if (sent_first_update_) {
+ FireEventIfStarted();
+ }
+}
+
+void FilteringNetworkManager::StopUpdating() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ network_manager_->StopUpdating();
+ DCHECK_GT(start_count_, 0);
+ --start_count_;
+}
+
+void FilteringNetworkManager::GetNetworks(NetworkList* networks) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ networks->clear();
+
+ if (enumeration_permission() == ENUMERATION_ALLOWED)
+ NetworkManagerBase::GetNetworks(networks);
+
+ VLOG(3) << "GetNetworks() returns " << networks->size() << " networks.";
+}
+
+webrtc::MdnsResponderInterface* FilteringNetworkManager::GetMdnsResponder()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // mDNS responder is set to null if we have the enumeration permission or the
+ // mDNS obfuscation of IPs is disallowed.
+ if (enumeration_permission() == ENUMERATION_ALLOWED ||
+ !allow_mdns_obfuscation_)
+ return nullptr;
+
+ return network_manager_->GetMdnsResponder();
+}
+
+void FilteringNetworkManager::CheckPermission() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!started_permission_check_);
+
+ started_permission_check_ = true;
+ pending_permission_checks_ = 2;
+
+ VLOG(1) << "FilteringNetworkManager checking permission status.";
+ // Request for media permission asynchronously.
+ media_permission_->HasPermission(
+ media::MediaPermission::AUDIO_CAPTURE,
+ base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
+ GetWeakPtr()));
+ media_permission_->HasPermission(
+ media::MediaPermission::VIDEO_CAPTURE,
+ base::BindOnce(&FilteringNetworkManager::OnPermissionStatus,
+ GetWeakPtr()));
+}
+
+void FilteringNetworkManager::OnPermissionStatus(bool granted) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_GT(pending_permission_checks_, 0);
+ VLOG(1) << "FilteringNetworkManager received permission status: "
+ << (granted ? "granted" : "denied");
+ blink::IPPermissionStatus old_status = GetIPPermissionStatus();
+
+ --pending_permission_checks_;
+
+ if (granted)
+ set_enumeration_permission(ENUMERATION_ALLOWED);
+
+ // If the IP permission status changed *and* we have an up-to-date network
+ // list, fire a network change event.
+ if (GetIPPermissionStatus() != old_status && !pending_network_update_)
+ FireEventIfStarted();
+}
+
+void FilteringNetworkManager::OnNetworksChanged() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ pending_network_update_ = false;
+
+ // Update the default local addresses.
+ rtc::IPAddress ipv4_default;
+ rtc::IPAddress ipv6_default;
+ network_manager_->GetDefaultLocalAddress(AF_INET, &ipv4_default);
+ network_manager_->GetDefaultLocalAddress(AF_INET6, &ipv6_default);
+ set_default_local_addresses(ipv4_default, ipv6_default);
+
+ // Copy and merge the networks. Fire a signal if the permission status is
+ // known.
+ NetworkList networks;
+ network_manager_->GetNetworks(&networks);
+ NetworkList copied_networks;
+ copied_networks.reserve(networks.size());
+ for (rtc::Network* network : networks) {
+ auto copied_network = std::make_unique<rtc::Network>(*network);
+ copied_network->set_default_local_address_provider(this);
+ copied_network->set_mdns_responder_provider(this);
+ copied_networks.push_back(copied_network.release());
+ }
+ bool changed;
+ MergeNetworkList(copied_networks, &changed);
+ // We wait until our permission status is known before firing a network
+ // change signal, so that the listener(s) don't miss out on receiving a
+ // full network list.
+ if (changed && GetIPPermissionStatus() != blink::PERMISSION_UNKNOWN)
+ FireEventIfStarted();
+}
+
+void FilteringNetworkManager::ReportMetrics(bool report_start_latency) {
+ if (report_start_latency) {
+ blink::ReportTimeToUpdateNetworkList(base::TimeTicks::Now() -
+ start_updating_time_);
+ }
+
+ ReportIPPermissionStatus(GetIPPermissionStatus());
+}
+
+blink::IPPermissionStatus FilteringNetworkManager::GetIPPermissionStatus()
+ const {
+ if (enumeration_permission() == ENUMERATION_ALLOWED) {
+ return media_permission_ ? blink::PERMISSION_GRANTED_WITH_CHECKING
+ : blink::PERMISSION_GRANTED_WITHOUT_CHECKING;
+ }
+
+ if (!pending_permission_checks_ &&
+ enumeration_permission() == ENUMERATION_BLOCKED) {
+ return blink::PERMISSION_DENIED;
+ }
+
+ return blink::PERMISSION_UNKNOWN;
+}
+
+void FilteringNetworkManager::FireEventIfStarted() {
+ if (!start_count_)
+ return;
+
+ if (!sent_first_update_)
+ ReportMetrics(true);
+
+ // Post a task to avoid reentrancy.
+ //
+ // TODO(crbug.com/787254): Use Frame-based TaskRunner here.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&FilteringNetworkManager::SendNetworksChangedSignal,
+ GetWeakPtr()));
+
+ sent_first_update_ = true;
+}
+
+void FilteringNetworkManager::SendNetworksChangedSignal() {
+ SignalNetworksChanged();
+}
+
+} // 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
new file mode 100644
index 00000000000..f9dc5f61c8a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager.h
@@ -0,0 +1,133 @@
+// 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_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"
+#include "third_party/blink/public/platform/web_common.h"
+#include "third_party/blink/renderer/platform/p2p/network_manager_uma.h"
+#include "third_party/webrtc/rtc_base/network.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
+#include "url/gurl.h"
+
+namespace media {
+class MediaPermission;
+} // namespace media
+
+namespace blink {
+
+// FilteringNetworkManager exposes rtc::NetworkManager to
+// PeerConnectionDependencyFactory and wraps the IpcNetworkManager. It only
+// handles the case where multiple_routes is requested. It checks at least one
+// of mic/camera permissions is granted before allowing WebRTC to use the local
+// IP addresses as ICE candidates. The class handles asynchronous signals like
+// SignalNetworksChanged from IpcNetworkManager and permission status from
+// MediaPermission before it signals WebRTC that the network information is
+// ready. It is designed to fire the network change event at the earliest time
+// to reduce any extra call setup delay. This class is not thread safe and
+// should only be used by WebRTC's network thread. It inherits from
+// rtc::NetworkManagerBase to have the same implementation of
+// GetAnyAddressNetworks(). We can't mark the whole class BLINK_PLATFORM_EXPORT
+// as it requires all super classes to be BLINK_PLATFORM_EXPORT as well.
+//
+// TODO(crbug.com/787254): Move this class out of the Blink exposed API when
+// all users of it have been Onion souped. Also, move it away from url/gurl.h.
+class FilteringNetworkManager : public rtc::NetworkManagerBase,
+ public sigslot::has_slots<> {
+ public:
+ // This class is created by WebRTC's signaling thread but used by WebRTC's
+ // worker thread |task_runner|.
+ BLINK_PLATFORM_EXPORT FilteringNetworkManager(
+ rtc::NetworkManager* network_manager,
+ const GURL& requesting_origin,
+ media::MediaPermission* media_permission,
+ bool allow_mdns_obfuscation);
+
+ BLINK_PLATFORM_EXPORT ~FilteringNetworkManager() override;
+
+ // rtc::NetworkManager:
+ void Initialize() override;
+ void StartUpdating() override;
+ void StopUpdating() override;
+ void GetNetworks(NetworkList* networks) const override;
+
+ webrtc::MdnsResponderInterface* GetMdnsResponder() const override;
+
+ private:
+ // Check mic/camera permission.
+ void CheckPermission();
+
+ // Receive callback from MediaPermission when the permission status is
+ // available.
+ void OnPermissionStatus(bool granted);
+
+ base::WeakPtr<FilteringNetworkManager> GetWeakPtr();
+
+ // Receive callback from the wrapped NetworkManager when the underneath
+ // network list is changed.
+ void OnNetworksChanged();
+
+ // Reporting the IPPermissionStatus and how long it takes to send
+ // SignalNetworksChanged. |report_start_latency| is false when called by the
+ // destructor to report no networks changed signal is ever fired and could
+ // potentially be a bug.
+ void ReportMetrics(bool report_start_latency);
+
+ // A tri-state permission checking status. It starts with UNKNOWN and will
+ // change to GRANTED if one of permissions is granted. Otherwise, DENIED will
+ // be returned.
+ blink::IPPermissionStatus GetIPPermissionStatus() const;
+
+ void FireEventIfStarted();
+
+ void SendNetworksChangedSignal();
+
+ // |network_manager_| is just a reference, owned by
+ // PeerConnectionDependencyFactory.
+ rtc::NetworkManager* network_manager_;
+
+ // The class is created by the signaling thread but used by the worker thread.
+ THREAD_CHECKER(thread_checker_);
+
+ media::MediaPermission* media_permission_;
+
+ int pending_permission_checks_ = 0;
+
+ // Whether we're waiting for a network change signal from |network_manager_|.
+ bool pending_network_update_ = false;
+
+ // Whether we have fired the first SignalNetworksChanged.
+ // Used to ensure we only report metrics once.
+ bool sent_first_update_ = false;
+
+ // SignalNetworksChanged will only be fired if there is any outstanding
+ // StartUpdating.
+ int start_count_ = 0;
+
+ // Track whether CheckPermission has been called before StartUpdating.
+ bool started_permission_check_ = false;
+
+ // Track how long it takes for client to receive SignalNetworksChanged. This
+ // helps to identify if the signal is delayed by permission check and increase
+ // the setup time.
+ base::TimeTicks start_updating_time_;
+
+ GURL requesting_origin_;
+
+ // When the mDNS obfuscation is allowed, access to the mDNS responder provided
+ // by the base network manager is provided to conceal IPs with mDNS hostnames.
+ bool allow_mdns_obfuscation_ = true;
+
+ base::WeakPtrFactory<FilteringNetworkManager> weak_ptr_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(FilteringNetworkManager);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_FILTERING_NETWORK_MANAGER_H_
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
new file mode 100644
index 00000000000..6b2da1ad524
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
@@ -0,0 +1,517 @@
+// 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/p2p/filtering_network_manager.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.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"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/p2p/empty_network_manager.h"
+#include "third_party/webrtc/rtc_base/ip_address.h"
+
+using NetworkList = rtc::NetworkManager::NetworkList;
+using ::testing::SizeIs;
+
+namespace {
+
+enum EventType {
+ MIC_DENIED, // Receive mic permission denied.
+ MIC_GRANTED, // Receive mic permission granted.
+ CAMERA_DENIED, // Receive camera permission denied.
+ CAMERA_GRANTED, // Receive camera permission granted.
+ START_UPDATING, // Client calls StartUpdating() on FilteringNetworkManager.
+ STOP_UPDATING, // Client calls StopUpdating() on FilteringNetworkManager.
+ MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, // MockNetworkManager has signaled
+ // networks changed event and the
+ // underlying network is replaced by
+ // a new one.
+ MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, // MockNetworkManager has signaled
+ // networks changed event but the
+ // underlying network stays the
+ // same.
+};
+
+enum ResultType {
+ NO_SIGNAL, // Do not expect SignalNetworksChanged fired.
+ SIGNAL_ENUMERATION_BLOCKED, // Expect SignalNetworksChanged and
+ // ENUMERATION_BLOCKED.
+ SIGNAL_ENUMERATION_ALLOWED, // Expect SignalNetworksChanged and
+ // ENUMERATION_ALLOWED.
+};
+
+struct TestEntry {
+ EventType event;
+ ResultType expected_result;
+};
+
+class EmptyMdnsResponder : public webrtc::MdnsResponderInterface {
+ public:
+ void CreateNameForAddress(const rtc::IPAddress& addr,
+ NameCreatedCallback callback) override {
+ NOTREACHED();
+ }
+ void RemoveNameForAddress(const rtc::IPAddress& addr,
+ NameRemovedCallback callback) override {
+ NOTREACHED();
+ }
+};
+
+class MockNetworkManager : public rtc::NetworkManagerBase {
+ public:
+ MockNetworkManager() : mdns_responder_(new EmptyMdnsResponder()) {}
+ // Mimic the current behavior that once the first signal is sent, any future
+ // StartUpdating() will trigger another one.
+ void StartUpdating() override {
+ if (sent_first_update_)
+ SignalNetworksChanged();
+ }
+ void StopUpdating() override {}
+ void GetNetworks(NetworkList* networks) const override {
+ networks->push_back(network_.get());
+ }
+
+ void SendNetworksChanged() {
+ sent_first_update_ = true;
+ SignalNetworksChanged();
+ }
+
+ webrtc::MdnsResponderInterface* GetMdnsResponder() const override {
+ return mdns_responder_.get();
+ }
+
+ void CopyAndSetNetwork(const rtc::Network& network) {
+ network_ = std::make_unique<rtc::Network>(network);
+ network_->AddIP(network_->GetBestIP());
+ }
+
+ private:
+ bool sent_first_update_ = false;
+ std::unique_ptr<rtc::Network> network_;
+ std::unique_ptr<EmptyMdnsResponder> mdns_responder_;
+};
+
+class MockMediaPermission : public media::MediaPermission {
+ public:
+ MockMediaPermission() {}
+ ~MockMediaPermission() override {}
+
+ void RequestPermission(Type type,
+ PermissionStatusCB permission_status_cb) override {
+ NOTIMPLEMENTED();
+ }
+
+ void HasPermission(Type type,
+ PermissionStatusCB permission_status_cb) override {
+ if (type == MediaPermission::AUDIO_CAPTURE) {
+ DCHECK(mic_callback_.is_null());
+ mic_callback_ = std::move(permission_status_cb);
+ } else {
+ DCHECK(type == MediaPermission::VIDEO_CAPTURE);
+ DCHECK(camera_callback_.is_null());
+ camera_callback_ = std::move(permission_status_cb);
+ }
+ }
+
+ bool IsEncryptedMediaEnabled() override { return true; }
+
+ void SetMicPermission(bool granted) {
+ if (!mic_callback_)
+ return;
+
+ std::move(mic_callback_).Run(granted);
+ }
+
+ void SetCameraPermission(bool granted) {
+ if (!camera_callback_)
+ return;
+
+ std::move(camera_callback_).Run(granted);
+ }
+
+ private:
+ PermissionStatusCB mic_callback_;
+ PermissionStatusCB camera_callback_;
+};
+
+} // namespace
+
+namespace blink {
+
+class FilteringNetworkManagerTest : public testing::Test,
+ public sigslot::has_slots<> {
+ public:
+ FilteringNetworkManagerTest()
+ : media_permission_(new MockMediaPermission()),
+ task_runner_(new base::TestSimpleTaskRunner()),
+ task_runner_handle_(task_runner_) {
+ networks_.emplace_back("test_eth0", "Test Network Adapter 1",
+ rtc::IPAddress(0x12345600U), 24,
+ rtc::ADAPTER_TYPE_ETHERNET),
+ networks_.back().AddIP(rtc::IPAddress(0x12345678));
+ networks_.emplace_back("test_eth1", "Test Network Adapter 2",
+ rtc::IPAddress(0x87654300U), 24,
+ rtc::ADAPTER_TYPE_ETHERNET),
+ networks_.back().AddIP(rtc::IPAddress(0x87654321));
+ }
+
+ void SetupNetworkManager(bool multiple_routes_requested) {
+ base_network_manager_ = std::make_unique<MockNetworkManager>();
+ SetNewNetworkForBaseNetworkManager();
+ if (multiple_routes_requested) {
+ network_manager_ = std::make_unique<FilteringNetworkManager>(
+ base_network_manager_.get(), GURL(), media_permission_.get(),
+ allow_mdns_obfuscation_);
+ network_manager_->Initialize();
+ } else {
+ network_manager_ = std::make_unique<blink::EmptyNetworkManager>(
+ base_network_manager_.get());
+ }
+ network_manager_->SignalNetworksChanged.connect(
+ this, &FilteringNetworkManagerTest::OnNetworksChanged);
+ }
+
+ void RunTests(TestEntry* tests, size_t size) {
+ for (size_t i = 0; i < size; ++i) {
+ EXPECT_EQ(tests[i].expected_result, ProcessEvent(tests[i].event))
+ << " in step: " << i;
+ }
+ }
+
+ void SetNewNetworkForBaseNetworkManager() {
+ base_network_manager_->CopyAndSetNetwork(networks_[next_new_network_id_]);
+ next_new_network_id_ = (next_new_network_id_ + 1) % networks_.size();
+ }
+
+ ResultType ProcessEvent(EventType event) {
+ clear_callback_called();
+ switch (event) {
+ case MIC_DENIED:
+ case MIC_GRANTED:
+ media_permission_->SetMicPermission(event == MIC_GRANTED);
+ break;
+ case CAMERA_DENIED:
+ case CAMERA_GRANTED:
+ media_permission_->SetCameraPermission(event == CAMERA_GRANTED);
+ break;
+ case START_UPDATING:
+ network_manager_->StartUpdating();
+ break;
+ case STOP_UPDATING:
+ network_manager_->StopUpdating();
+ break;
+ case MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK:
+ SetNewNetworkForBaseNetworkManager();
+ base_network_manager_->SendNetworksChanged();
+ break;
+ case MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK:
+ base_network_manager_->SendNetworksChanged();
+ break;
+ }
+
+ task_runner_->RunUntilIdle();
+
+ if (!callback_called_)
+ return NO_SIGNAL;
+
+ if (network_manager_->enumeration_permission() ==
+ rtc::NetworkManager::ENUMERATION_BLOCKED) {
+ EXPECT_EQ(0u, GetP2PNetworkList().size());
+ return SIGNAL_ENUMERATION_BLOCKED;
+ }
+ EXPECT_EQ(1u, GetP2PNetworkList().size());
+ return SIGNAL_ENUMERATION_ALLOWED;
+ }
+
+ protected:
+ const NetworkList& GetP2PNetworkList() {
+ network_list_.clear();
+ network_manager_->GetNetworks(&network_list_);
+ return network_list_;
+ }
+
+ void OnNetworksChanged() { callback_called_ = true; }
+ void clear_callback_called() { callback_called_ = false; }
+ void set_allow_mdns_obfuscation(bool val) { allow_mdns_obfuscation_ = val; }
+
+ bool callback_called_ = false;
+ std::unique_ptr<rtc::NetworkManager> network_manager_;
+ std::unique_ptr<MockNetworkManager> base_network_manager_;
+
+ std::unique_ptr<MockMediaPermission> media_permission_;
+ bool allow_mdns_obfuscation_ = true;
+
+ std::vector<rtc::Network> networks_;
+ int next_new_network_id_ = 0;
+
+ NetworkList network_list_;
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ base::ThreadTaskRunnerHandle task_runner_handle_;
+};
+
+// Test that when multiple routes is not requested, SignalNetworksChanged is
+// fired right after the StartUpdating().
+TEST_F(FilteringNetworkManagerTest, MultipleRoutesNotRequested) {
+ SetupNetworkManager(false);
+ TestEntry tests[] = {
+ // Underneath network manager signals, no callback as StartUpdating() is
+ // not called.
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ // StartUpdating() is called, should receive callback as the multiple
+ // routes is not requested.
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ // Further network signal should trigger callback, since the
+ // EmptyNetworkManager always forwards the signal from the base network
+ // manager if there is any outstanding StartUpdate();
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, SIGNAL_ENUMERATION_BLOCKED},
+ // StartUpdating() always triggers callback after we have sent the first
+ // network update.
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {STOP_UPDATING, NO_SIGNAL},
+ // No outstanding StartUpdating(), no more signal.
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that multiple routes request is blocked and signaled right after
+// StartUpdating() since mic/camera permissions are denied.
+TEST_F(FilteringNetworkManagerTest, BlockMultipleRoutesByStartUpdating) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ // Both mic and camera are denied.
+ {MIC_DENIED, NO_SIGNAL},
+ {CAMERA_DENIED, NO_SIGNAL},
+ // Once StartUpdating() is called, signal network changed event with
+ // ENUMERATION_BLOCKED.
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ // Further network signal should not trigger callback, since the set of
+ // networks does not change after merging.
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ // Signal when observing a change after merging while there is any
+ // outstanding StartUpdate();
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, SIGNAL_ENUMERATION_BLOCKED},
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {STOP_UPDATING, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that multiple routes request is blocked and signaled right after
+// last pending permission check is denied since StartUpdating() has been called
+// previously.
+TEST_F(FilteringNetworkManagerTest, BlockMultipleRoutesByPermissionsDenied) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ // StartUpdating() should not fire the event before we send the first
+ // update.
+ {START_UPDATING, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ {MIC_DENIED, NO_SIGNAL},
+ // The last permission check being denied should immediately trigger the
+ // networks changed signal, since we already have an updated network list.
+ {CAMERA_DENIED, SIGNAL_ENUMERATION_BLOCKED},
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {STOP_UPDATING, NO_SIGNAL},
+ // No outstanding StartUpdating(), no more signal.
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that after permissions have been denied, a network change signal from
+// the internal NetworkManager is still needed before signaling a network
+// change outwards. This is because even if network enumeration is blocked,
+// we still want to give time to obtain the default IP addresses.
+TEST_F(FilteringNetworkManagerTest, BlockMultipleRoutesByNetworksChanged) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ {START_UPDATING, NO_SIGNAL},
+ {MIC_DENIED, NO_SIGNAL},
+ {CAMERA_DENIED, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, SIGNAL_ENUMERATION_BLOCKED},
+ {START_UPDATING, SIGNAL_ENUMERATION_BLOCKED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {STOP_UPDATING, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// a pending permission check is granted since StartUpdating() has been called
+// previously.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByPermissionsGranted) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ {START_UPDATING, NO_SIGNAL},
+ {MIC_DENIED, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ // Once one media type is granted, signal networks changed with
+ // ENUMERATION_ALLOWED.
+ {CAMERA_GRANTED, SIGNAL_ENUMERATION_ALLOWED},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ // If there is any outstanding StartUpdating(), new event from underneath
+ // network manger should trigger SignalNetworksChanged.
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ // No outstanding StartUpdating(), no more signal.
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// StartUpdating() since there is at least one media permission granted.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByStartUpdating) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ {MIC_DENIED, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ {CAMERA_GRANTED, NO_SIGNAL},
+ // StartUpdating() should signal the event with the status of permissions
+ // granted.
+ {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ // Signal when observing a change after merging while there is any
+ // outstanding StartUpdate();
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ // No outstanding StartUpdating(), no more signal.
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that multiple routes request is granted and signaled right after
+// underneath NetworkManager's SignalNetworksChanged() as at least one
+// permission is granted and StartUpdating() has been called.
+TEST_F(FilteringNetworkManagerTest, AllowMultipleRoutesByNetworksChanged) {
+ SetupNetworkManager(true);
+
+ TestEntry tests[] = {
+ {START_UPDATING, NO_SIGNAL},
+ {CAMERA_GRANTED, NO_SIGNAL},
+ // Underneath network manager's signal networks changed should trigger
+ // SignalNetworksChanged with ENUMERATION_ALLOWED.
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, SIGNAL_ENUMERATION_ALLOWED},
+ {MIC_DENIED, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, SIGNAL_ENUMERATION_ALLOWED},
+ {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, SIGNAL_ENUMERATION_ALLOWED},
+ {STOP_UPDATING, NO_SIGNAL},
+ {MOCK_NETWORKS_CHANGED_WITH_NEW_NETWORK, NO_SIGNAL},
+ };
+
+ RunTests(tests, base::size(tests));
+}
+
+// Test that the networks provided by the GetNetworks() and
+// GetAnyAddressNetworks() are not associated with an mDNS responder if the
+// enumeration permission is granted, even if the mDNS obfuscation of local IPs
+// is allowed (which is by default).
+TEST_F(FilteringNetworkManagerTest, NullMdnsResponderAfterPermissionGranted) {
+ SetupNetworkManager(true);
+
+ TestEntry setup_steps[] = {
+ {MOCK_NETWORKS_CHANGED_WITH_SAME_NETWORK, NO_SIGNAL},
+ // Both mic and camera are granted.
+ {MIC_GRANTED, NO_SIGNAL},
+ {CAMERA_GRANTED, NO_SIGNAL},
+ // Once StartUpdating() is called, signal network changed event with
+ // ENUMERATION_ALLOWED.
+ {START_UPDATING, SIGNAL_ENUMERATION_ALLOWED},
+ };
+ RunTests(setup_steps, base::size(setup_steps));
+
+ NetworkList networks;
+ network_manager_->GetNetworks(&networks);
+ EXPECT_THAT(networks, SizeIs(1u));
+ for (const rtc::Network* network : networks) {
+ EXPECT_EQ(nullptr, network->GetMdnsResponder());
+ }
+
+ networks.clear();
+ network_manager_->GetAnyAddressNetworks(&networks);
+ EXPECT_THAT(networks, SizeIs(2u));
+ for (const rtc::Network* network : networks) {
+ EXPECT_EQ(nullptr, network->GetMdnsResponder());
+ }
+}
+
+// Test the networks on the default routes given by GetAnyAddressNetworks() are
+// associated with an mDNS responder if the enumeration is blocked and the mDNS
+// obfuscation of local IPs is allowed (which is by default).
+TEST_F(FilteringNetworkManagerTest,
+ ProvideMdnsResponderForDefaultRouteAfterPermissionDenied) {
+ SetupNetworkManager(true);
+ // By default, the enumeration is blocked if we provide |media_permission_|;
+ EXPECT_EQ(rtc::NetworkManager::ENUMERATION_BLOCKED,
+ network_manager_->enumeration_permission());
+
+ NetworkList networks;
+ network_manager_->GetNetworks(&networks);
+ EXPECT_TRUE(networks.empty());
+
+ network_manager_->GetAnyAddressNetworks(&networks);
+ EXPECT_THAT(networks, SizeIs(2u));
+ EXPECT_NE(nullptr, network_manager_->GetMdnsResponder());
+ for (const rtc::Network* network : networks) {
+ EXPECT_EQ(network_manager_->GetMdnsResponder(),
+ network->GetMdnsResponder());
+ }
+}
+
+// This is a similar test to the previous one but tests that the networks
+// provided by the GetNetworks() and GetAnyAddressNetworks() are not associated
+// with an mDNS responder if the mDNS obfuscation of local IPs is not allowed.
+TEST_F(FilteringNetworkManagerTest,
+ NullMdnsResponderWhenMdnsObfuscationDisallowedAfterPermissionDenied) {
+ set_allow_mdns_obfuscation(false);
+ SetupNetworkManager(true);
+ // By default, the enumeration is blocked if we provide |media_permission_|;
+ EXPECT_EQ(rtc::NetworkManager::ENUMERATION_BLOCKED,
+ network_manager_->enumeration_permission());
+
+ NetworkList networks;
+ network_manager_->GetNetworks(&networks);
+ EXPECT_TRUE(networks.empty());
+
+ network_manager_->GetAnyAddressNetworks(&networks);
+ EXPECT_THAT(networks, SizeIs(2u));
+ for (const rtc::Network* network : networks) {
+ EXPECT_EQ(nullptr, network->GetMdnsResponder());
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc
new file mode 100644
index 00000000000..c2ecba2cd67
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/p2p/host_address_request.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/location.h"
+#include "jingle/glue/utils.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+P2PAsyncAddressResolver::P2PAsyncAddressResolver(
+ P2PSocketDispatcher* dispatcher)
+ : dispatcher_(dispatcher), state_(STATE_CREATED) {
+ AddRef(); // Balanced in Destroy().
+}
+
+P2PAsyncAddressResolver::~P2PAsyncAddressResolver() {
+ DCHECK(state_ == STATE_CREATED || state_ == STATE_FINISHED);
+}
+
+void P2PAsyncAddressResolver::Start(const rtc::SocketAddress& host_name,
+ DoneCallback done_callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(STATE_CREATED, state_);
+
+ state_ = STATE_SENT;
+ done_callback_ = std::move(done_callback);
+ bool enable_mdns = base::FeatureList::IsEnabled(
+ blink::features::kWebRtcHideLocalIpsWithMdns);
+ dispatcher_->GetP2PSocketManager()->get()->GetHostAddress(
+ String(host_name.hostname().data()), enable_mdns,
+ base::BindOnce(&P2PAsyncAddressResolver::OnResponse,
+ base::Unretained(this)));
+}
+
+void P2PAsyncAddressResolver::Cancel() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (state_ != STATE_FINISHED)
+ state_ = STATE_FINISHED;
+
+ done_callback_.Reset();
+}
+
+void P2PAsyncAddressResolver::OnResponse(
+ const Vector<net::IPAddress>& addresses) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (state_ == STATE_SENT) {
+ state_ = STATE_FINISHED;
+ std::move(done_callback_).Run(addresses);
+ }
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..9bb5ccf10b4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/host_address_request.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_HOST_ADDRESS_REQUEST_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_HOST_ADDRESS_REQUEST_H_
+
+#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"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/webrtc/rtc_base/async_resolver_interface.h"
+
+namespace blink {
+
+class P2PSocketDispatcher;
+
+// P2PAsyncAddressResolver performs DNS hostname resolution. It's used
+// to resolve addresses of STUN and relay servers.
+class P2PAsyncAddressResolver
+ : public base::RefCountedThreadSafe<P2PAsyncAddressResolver> {
+ public:
+ using DoneCallback = base::OnceCallback<void(const Vector<net::IPAddress>&)>;
+
+ P2PAsyncAddressResolver(P2PSocketDispatcher* dispatcher);
+ // Start address resolve process.
+ void Start(const rtc::SocketAddress& addr, DoneCallback done_callback);
+ // Clients must unregister before exiting for cleanup.
+ void Cancel();
+
+ private:
+ enum State {
+ STATE_CREATED,
+ STATE_SENT,
+ STATE_FINISHED,
+ };
+
+ friend class P2PSocketDispatcher;
+
+ friend class base::RefCountedThreadSafe<P2PAsyncAddressResolver>;
+
+ virtual ~P2PAsyncAddressResolver();
+
+ void OnResponse(const Vector<net::IPAddress>& address);
+
+ P2PSocketDispatcher* dispatcher_;
+ THREAD_CHECKER(thread_checker_);
+
+ // State must be accessed from delegate thread only.
+ State state_;
+ DoneCallback done_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PAsyncAddressResolver);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_HOST_ADDRESS_REQUEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
new file mode 100644
index 00000000000..1ac806df97a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/p2p/ipc_network_manager.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/sys_byteorder.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "jingle/glue/utils.h"
+#include "net/base/ip_address.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/webrtc/rtc_base/socket_address.h"
+
+namespace blink {
+
+namespace {
+
+rtc::AdapterType ConvertConnectionTypeToAdapterType(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ switch (type) {
+ case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
+ return rtc::ADAPTER_TYPE_UNKNOWN;
+ case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
+ return rtc::ADAPTER_TYPE_ETHERNET;
+ case net::NetworkChangeNotifier::CONNECTION_WIFI:
+ return rtc::ADAPTER_TYPE_WIFI;
+ case net::NetworkChangeNotifier::CONNECTION_2G:
+ case net::NetworkChangeNotifier::CONNECTION_3G:
+ case net::NetworkChangeNotifier::CONNECTION_4G:
+ return rtc::ADAPTER_TYPE_CELLULAR;
+ default:
+ return rtc::ADAPTER_TYPE_UNKNOWN;
+ }
+}
+
+} // namespace
+
+IpcNetworkManager::IpcNetworkManager(
+ blink::NetworkListManager* network_list_manager,
+ std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder)
+ : network_list_manager_(network_list_manager),
+ mdns_responder_(std::move(mdns_responder)) {
+ network_list_manager_->AddNetworkListObserver(this);
+}
+
+IpcNetworkManager::~IpcNetworkManager() {
+ DCHECK(!start_count_);
+ network_list_manager_->RemoveNetworkListObserver(this);
+}
+
+void IpcNetworkManager::StartUpdating() {
+ if (network_list_received_) {
+ // Post a task to avoid reentrancy.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&IpcNetworkManager::SendNetworksChangedSignal,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ VLOG(1) << "IpcNetworkManager::StartUpdating called; still waiting for "
+ "network list from browser process.";
+ }
+ ++start_count_;
+}
+
+void IpcNetworkManager::StopUpdating() {
+ DCHECK_GT(start_count_, 0);
+ --start_count_;
+}
+
+void IpcNetworkManager::OnNetworkListChanged(
+ const net::NetworkInterfaceList& list,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) {
+ // Update flag if network list received for the first time.
+ if (!network_list_received_) {
+ VLOG(1) << "IpcNetworkManager received network list from browser process "
+ "for the first time.";
+ network_list_received_ = true;
+ }
+
+ // Default addresses should be set only when they are in the filtered list of
+ // network addresses.
+ bool use_default_ipv4_address = false;
+ bool use_default_ipv6_address = false;
+
+ // rtc::Network uses these prefix_length to compare network
+ // interfaces discovered.
+ std::vector<rtc::Network*> networks;
+ for (auto it = list.begin(); it != list.end(); it++) {
+ rtc::IPAddress ip_address =
+ jingle_glue::NetIPAddressToRtcIPAddress(it->address);
+ DCHECK(!ip_address.IsNil());
+
+ rtc::IPAddress prefix = rtc::TruncateIP(ip_address, it->prefix_length);
+ rtc::AdapterType adapter_type =
+ ConvertConnectionTypeToAdapterType(it->type);
+ // If the adapter type is unknown, try to guess it using WebRTC's string
+ // matching rules.
+ if (adapter_type == rtc::ADAPTER_TYPE_UNKNOWN) {
+ adapter_type = rtc::GetAdapterTypeFromName(it->name.c_str());
+ }
+ std::unique_ptr<rtc::Network> network(new rtc::Network(
+ it->name, it->name, prefix, it->prefix_length, adapter_type));
+ network->set_default_local_address_provider(this);
+ network->set_mdns_responder_provider(this);
+
+ rtc::InterfaceAddress iface_addr;
+ if (it->address.IsIPv4()) {
+ use_default_ipv4_address |= (default_ipv4_local_address == it->address);
+ iface_addr = rtc::InterfaceAddress(ip_address);
+ } else {
+ DCHECK(it->address.IsIPv6());
+ iface_addr = rtc::InterfaceAddress(ip_address, it->ip_address_attributes);
+
+ // Only allow non-private, non-deprecated IPv6 addresses which don't
+ // contain MAC.
+ if (rtc::IPIsMacBased(iface_addr) ||
+ (it->ip_address_attributes & net::IP_ADDRESS_ATTRIBUTE_DEPRECATED) ||
+ rtc::IPIsPrivate(iface_addr)) {
+ continue;
+ }
+
+ use_default_ipv6_address |= (default_ipv6_local_address == it->address);
+ }
+ network->AddIP(iface_addr);
+ networks.push_back(network.release());
+ }
+
+ // Update the default local addresses.
+ rtc::IPAddress ipv4_default;
+ rtc::IPAddress ipv6_default;
+ if (use_default_ipv4_address) {
+ ipv4_default =
+ jingle_glue::NetIPAddressToRtcIPAddress(default_ipv4_local_address);
+ }
+ if (use_default_ipv6_address) {
+ ipv6_default =
+ jingle_glue::NetIPAddressToRtcIPAddress(default_ipv6_local_address);
+ }
+ set_default_local_addresses(ipv4_default, ipv6_default);
+
+ if (Platform::Current()->AllowsLoopbackInPeerConnection()) {
+ std::string name_v4("loopback_ipv4");
+ rtc::IPAddress ip_address_v4(INADDR_LOOPBACK);
+ rtc::Network* network_v4 = new rtc::Network(name_v4, name_v4, ip_address_v4,
+ 32, rtc::ADAPTER_TYPE_UNKNOWN);
+ network_v4->set_default_local_address_provider(this);
+ network_v4->set_mdns_responder_provider(this);
+ network_v4->AddIP(ip_address_v4);
+ networks.push_back(network_v4);
+
+ rtc::IPAddress ipv6_default_address;
+ // Only add IPv6 loopback if we can get default local address for IPv6. If
+ // we can't, it means that we don't have IPv6 enabled on this machine and
+ // bind() to the IPv6 loopback address will fail.
+ if (GetDefaultLocalAddress(AF_INET6, &ipv6_default_address)) {
+ DCHECK(!ipv6_default_address.IsNil());
+ std::string name_v6("loopback_ipv6");
+ rtc::IPAddress ip_address_v6(in6addr_loopback);
+ rtc::Network* network_v6 = new rtc::Network(
+ name_v6, name_v6, ip_address_v6, 64, rtc::ADAPTER_TYPE_UNKNOWN);
+ network_v6->set_default_local_address_provider(this);
+ network_v6->set_mdns_responder_provider(this);
+ network_v6->AddIP(ip_address_v6);
+ networks.push_back(network_v6);
+ }
+ }
+
+ bool changed = false;
+ NetworkManager::Stats stats;
+ MergeNetworkList(networks, &changed, &stats);
+ if (changed)
+ SignalNetworksChanged();
+
+ // Send interface counts to UMA.
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
+ stats.ipv4_network_count);
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
+ stats.ipv6_network_count);
+}
+
+webrtc::MdnsResponderInterface* IpcNetworkManager::GetMdnsResponder() const {
+ return mdns_responder_.get();
+}
+
+void IpcNetworkManager::SendNetworksChangedSignal() {
+ SignalNetworksChanged();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.h b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.h
new file mode 100644
index 00000000000..8db04200cd1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/rtc_base/mdns_responder_interface.h"
+#include "third_party/webrtc/rtc_base/network.h"
+
+namespace net {
+class IPAddress;
+} // namespace net
+
+namespace blink {
+
+// IpcNetworkManager is a NetworkManager for libjingle that gets a
+// list of network interfaces from the browser.
+class IpcNetworkManager : public rtc::NetworkManagerBase,
+ public blink::NetworkListObserver {
+ public:
+ // Constructor doesn't take ownership of the |network_list_manager|.
+ PLATFORM_EXPORT IpcNetworkManager(
+ blink::NetworkListManager* network_list_manager,
+ std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder);
+ ~IpcNetworkManager() override;
+
+ // rtc:::NetworkManager:
+ void StartUpdating() override;
+ void StopUpdating() override;
+ webrtc::MdnsResponderInterface* GetMdnsResponder() const override;
+
+ // blink::NetworkListObserver interface.
+ void OnNetworkListChanged(
+ const net::NetworkInterfaceList& list,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) override;
+
+ private:
+ void SendNetworksChangedSignal();
+
+ // TODO(crbug.com/787254): Consider moving NetworkListManager to Oilpan and
+ // avoid using a raw pointer.
+ blink::NetworkListManager* network_list_manager_;
+ std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder_;
+ int start_count_ = 0;
+ bool network_list_received_ = false;
+
+ base::WeakPtrFactory<IpcNetworkManager> weak_factory_{this};
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_NETWORK_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc
new file mode 100644
index 00000000000..b00dc6fb852
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_network_manager_test.cc
@@ -0,0 +1,201 @@
+// 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/p2p/ipc_network_manager.h"
+
+#include <algorithm>
+#include <memory>
+
+#include "net/base/ip_address.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_interfaces.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/webrtc/rtc_base/mdns_responder_interface.h"
+
+namespace blink {
+
+namespace {
+
+class MockP2PSocketDispatcher : public blink::NetworkListManager {
+ public:
+ void AddNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) override {}
+
+ void RemoveNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) override {}
+
+ ~MockP2PSocketDispatcher() override {}
+};
+
+class EmptyMdnsResponder : public webrtc::MdnsResponderInterface {
+ public:
+ void CreateNameForAddress(const rtc::IPAddress& addr,
+ NameCreatedCallback callback) override {}
+ void RemoveNameForAddress(const rtc::IPAddress& addr,
+ NameRemovedCallback callback) override {}
+};
+
+} // namespace
+
+// 2 IPv6 addresses with only last digit different.
+static const char kIPv6PublicAddrString1[] =
+ "2401:fa00:4:1000:be30:5b30:50e5:c3";
+static const char kIPv6PublicAddrString2[] =
+ "2401:fa00:4:1000:be30:5b30:50e5:c4";
+static const char kIPv4MappedAddrString[] = "::ffff:38.32.0.0";
+
+class IpcNetworkManagerTest : public testing::Test {
+ public:
+ IpcNetworkManagerTest()
+ : network_list_manager_(new MockP2PSocketDispatcher()),
+ network_manager_(std::make_unique<IpcNetworkManager>(
+ network_list_manager_.get(),
+ std::make_unique<EmptyMdnsResponder>())) {}
+
+ protected:
+ std::unique_ptr<MockP2PSocketDispatcher> network_list_manager_;
+ std::unique_ptr<IpcNetworkManager> network_manager_;
+};
+
+// Test overall logic of IpcNetworkManager on OnNetworkListChanged
+// that it should group addresses with the same network key under
+// single Network class. This also tests the logic inside
+// IpcNetworkManager in addition to MergeNetworkList.
+// TODO(guoweis): disable this test case for now until fix for webrtc
+// issue 19249005 integrated into chromium
+TEST_F(IpcNetworkManagerTest, TestMergeNetworkList) {
+ net::NetworkInterfaceList list;
+ net::IPAddress ip;
+ std::vector<rtc::Network*> networks;
+ rtc::IPAddress ip_address;
+
+ // Add 2 networks with the same prefix and prefix length.
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString1));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString2));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(),
+ net::IPAddress());
+ network_manager_->GetNetworks(&networks);
+ EXPECT_EQ(1uL, networks.size());
+ EXPECT_EQ(2uL, networks[0]->GetIPs().size());
+
+ // Add another network with different prefix length, should result in
+ // a different network.
+ networks.clear();
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 48,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ // Push an unknown address as the default address.
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv4MappedAddrString));
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(), ip);
+
+ // The unknown default address should be ignored.
+ EXPECT_FALSE(network_manager_->GetDefaultLocalAddress(AF_INET6, &ip_address));
+
+ network_manager_->GetNetworks(&networks);
+
+ // Verify we have 2 networks now.
+ EXPECT_EQ(2uL, networks.size());
+ // Verify the network with prefix length of 64 has 2 IP addresses.
+ auto network_with_two_ips = std::find_if(
+ networks.begin(), networks.end(),
+ [](rtc::Network* network) { return network->prefix_length() == 64; });
+ ASSERT_NE(networks.end(), network_with_two_ips);
+ EXPECT_EQ(2uL, (*network_with_two_ips)->GetIPs().size());
+ // IPs should be in the same order as the list passed into
+ // OnNetworkListChanged.
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString1, &ip_address));
+ EXPECT_EQ((*network_with_two_ips)->GetIPs()[0],
+ rtc::InterfaceAddress(ip_address));
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
+ EXPECT_EQ((*network_with_two_ips)->GetIPs()[1],
+ rtc::InterfaceAddress(ip_address));
+ // Verify the network with prefix length of 48 has 1 IP address.
+ auto network_with_one_ip = std::find_if(
+ networks.begin(), networks.end(),
+ [](rtc::Network* network) { return network->prefix_length() == 48; });
+ ASSERT_NE(networks.end(), network_with_one_ip);
+ EXPECT_EQ(1uL, (*network_with_one_ip)->GetIPs().size());
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
+ EXPECT_EQ((*network_with_one_ip)->GetIPs()[0],
+ rtc::InterfaceAddress(ip_address));
+}
+
+// Test that IpcNetworkManager will guess a network type from the interface
+// name when not otherwise available.
+TEST_F(IpcNetworkManagerTest, DeterminesNetworkTypeFromNameIfUnknown) {
+ net::NetworkInterfaceList list;
+ net::IPAddress ip;
+ std::vector<rtc::Network*> networks;
+ rtc::IPAddress ip_address;
+
+ // Add a "tun1" entry of type "unknown" and "tun2" entry of type Wi-Fi. The
+ // "tun1" entry (and only it) should have its type determined from its name,
+ // since its type is unknown.
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString1));
+ list.push_back(net::NetworkInterface(
+ "tun1", "tun1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString2));
+ list.push_back(net::NetworkInterface(
+ "tun2", "tun2", 0, net::NetworkChangeNotifier::CONNECTION_WIFI, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(),
+ net::IPAddress());
+ network_manager_->GetNetworks(&networks);
+ EXPECT_EQ(2uL, networks.size());
+
+ auto tun1 = std::find_if(
+ networks.begin(), networks.end(),
+ [](rtc::Network* network) { return network->name() == "tun1"; });
+ ASSERT_NE(networks.end(), tun1);
+ auto tun2 = std::find_if(
+ networks.begin(), networks.end(),
+ [](rtc::Network* network) { return network->name() == "tun2"; });
+ ASSERT_NE(networks.end(), tun1);
+
+ EXPECT_EQ(rtc::ADAPTER_TYPE_VPN, (*tun1)->type());
+ EXPECT_EQ(rtc::ADAPTER_TYPE_WIFI, (*tun2)->type());
+}
+
+// Test that IpcNetworkManager will act as the mDNS responder provider for
+// all networks that it returns.
+TEST_F(IpcNetworkManagerTest,
+ ServeAsMdnsResponderProviderForNetworksEnumerated) {
+ net::NetworkInterfaceList list;
+ // Add networks.
+ net::IPAddress ip;
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString1));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(),
+ net::IPAddress());
+ std::vector<rtc::Network*> networks;
+ network_manager_->GetNetworks(&networks);
+
+ ASSERT_EQ(1u, networks.size());
+ webrtc::MdnsResponderInterface* const mdns_responder =
+ network_manager_->GetMdnsResponder();
+ EXPECT_EQ(mdns_responder, networks[0]->GetMdnsResponder());
+ networks.clear();
+ network_manager_->GetAnyAddressNetworks(&networks);
+ ASSERT_EQ(2u, networks.size());
+ EXPECT_EQ(mdns_responder, networks[0]->GetMdnsResponder());
+ EXPECT_EQ(mdns_responder, networks[1]->GetMdnsResponder());
+}
+
+} // 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
new file mode 100644
index 00000000000..a28777e90c0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.cc
@@ -0,0 +1,797 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/p2p/ipc_socket_factory.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <list>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/sequence_checker.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_checker.h"
+#include "base/trace_event/trace_event.h"
+#include "jingle/glue/utils.h"
+#include "net/base/ip_address.h"
+#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
+#include "third_party/blink/renderer/platform/p2p/host_address_request.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client_delegate.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "third_party/webrtc/rtc_base/async_packet_socket.h"
+
+namespace blink {
+
+namespace {
+
+const int kDefaultNonSetOptionValue = -1;
+
+bool IsTcpClientSocket(network::P2PSocketType type) {
+ return (type == network::P2P_SOCKET_STUN_TCP_CLIENT) ||
+ (type == network::P2P_SOCKET_TCP_CLIENT) ||
+ (type == network::P2P_SOCKET_STUN_SSLTCP_CLIENT) ||
+ (type == network::P2P_SOCKET_SSLTCP_CLIENT) ||
+ (type == network::P2P_SOCKET_TLS_CLIENT) ||
+ (type == network::P2P_SOCKET_STUN_TLS_CLIENT);
+}
+
+bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,
+ network::P2PSocketOption* ipc_option) {
+ switch (option) {
+ case rtc::Socket::OPT_RCVBUF:
+ *ipc_option = network::P2P_SOCKET_OPT_RCVBUF;
+ break;
+ case rtc::Socket::OPT_SNDBUF:
+ *ipc_option = network::P2P_SOCKET_OPT_SNDBUF;
+ break;
+ case rtc::Socket::OPT_DSCP:
+ *ipc_option = network::P2P_SOCKET_OPT_DSCP;
+ break;
+ case rtc::Socket::OPT_DONTFRAGMENT:
+ case rtc::Socket::OPT_NODELAY:
+ case rtc::Socket::OPT_IPV6_V6ONLY:
+ case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID:
+ return false; // Not supported by the chrome sockets.
+ default:
+ NOTREACHED();
+ return false;
+ }
+ return true;
+}
+
+const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB
+
+// IpcPacketSocket implements rtc::AsyncPacketSocket interface
+// using P2PSocketClient that works over IPC-channel. It must be used
+// on the thread it was created.
+class IpcPacketSocket : public rtc::AsyncPacketSocket,
+ public blink::P2PSocketClientDelegate {
+ public:
+ IpcPacketSocket();
+ ~IpcPacketSocket() override;
+
+ // Struct to track information when a packet is received by this socket for
+ // send. The information tracked here will be used to match with the
+ // P2PSendPacketMetrics from the underneath system socket.
+ struct InFlightPacketRecord {
+ InFlightPacketRecord(uint64_t packet_id, size_t packet_size)
+ : packet_id(packet_id), packet_size(packet_size) {}
+
+ uint64_t packet_id;
+ size_t packet_size;
+ };
+
+ typedef std::list<InFlightPacketRecord> InFlightPacketList;
+
+ // Always takes ownership of client even if initialization fails.
+ bool Init(network::P2PSocketType type,
+ std::unique_ptr<P2PSocketClientImpl> client,
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const rtc::SocketAddress& remote_address);
+
+ // rtc::AsyncPacketSocket interface.
+ rtc::SocketAddress GetLocalAddress() const override;
+ rtc::SocketAddress GetRemoteAddress() const override;
+ int Send(const void* pv,
+ size_t cb,
+ const rtc::PacketOptions& options) override;
+ int SendTo(const void* pv,
+ size_t cb,
+ const rtc::SocketAddress& addr,
+ const rtc::PacketOptions& options) override;
+ int Close() override;
+ State GetState() const override;
+ int GetOption(rtc::Socket::Option option, int* value) override;
+ int SetOption(rtc::Socket::Option option, int value) override;
+ int GetError() const override;
+ void SetError(int error) override;
+
+ // P2PSocketClientDelegate implementation.
+ void OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) override;
+ void OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ std::unique_ptr<blink::P2PSocketClient> client) override;
+ void OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) override;
+ void OnError() override;
+ void OnDataReceived(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const base::TimeTicks& timestamp) override;
+
+ private:
+ enum InternalState {
+ IS_UNINITIALIZED,
+ IS_OPENING,
+ IS_OPEN,
+ IS_CLOSED,
+ IS_ERROR,
+ };
+
+ // Increment the counter for consecutive bytes discarded as socket is running
+ // out of buffer.
+ void IncrementDiscardCounters(size_t bytes_discarded);
+
+ // Update trace of send throttling internal state. This should be called
+ // immediately after any changes to |send_bytes_available_| and/or
+ // |in_flight_packet_records_|.
+ void TraceSendThrottlingState() const;
+
+ void InitAcceptedTcp(std::unique_ptr<blink::P2PSocketClient> client,
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address);
+
+ int DoSetOption(network::P2PSocketOption option, int value);
+
+ network::P2PSocketType type_;
+
+ // Used to verify that a method runs on the thread that created this socket.
+ THREAD_CHECKER(thread_checker_);
+
+ // Corresponding P2P socket client.
+ std::unique_ptr<blink::P2PSocketClient> client_;
+
+ // Local address is allocated by the browser process, and the
+ // renderer side doesn't know the address until it receives OnOpen()
+ // event from the browser.
+ rtc::SocketAddress local_address_;
+
+ // Remote address for client TCP connections.
+ rtc::SocketAddress remote_address_;
+
+ // Current state of the object.
+ InternalState state_;
+
+ // Track the number of bytes allowed to be sent non-blocking. This is used to
+ // throttle the sending of packets to the browser process. For each packet
+ // sent, the value is decreased. As callbacks to OnSendComplete() (as IPCs
+ // from the browser process) are made, the value is increased back. This
+ // allows short bursts of high-rate sending without dropping packets, but
+ // quickly restricts the client to a sustainable steady-state rate.
+ size_t send_bytes_available_;
+
+ // Used to detect when browser doesn't send SendComplete message for some
+ // packets. In normal case, the first packet should be the one that we're
+ // going to receive the next completion signal.
+ InFlightPacketList in_flight_packet_records_;
+
+ // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
+ // caller expects SignalWritable notification.
+ bool writable_signal_expected_;
+
+ // Current error code. Valid when state_ == IS_ERROR.
+ int error_;
+ int options_[network::P2P_SOCKET_OPT_MAX];
+
+ // Track the maximum and current consecutive bytes discarded due to not enough
+ // send_bytes_available_.
+ size_t max_discard_bytes_sequence_;
+ 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);
+};
+
+// Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
+// class is to send SignalDone, after OnDone callback from
+// P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
+// of MT sig slots clients must call disconnect. This class is to make sure
+// we destruct from the same thread on which is created.
+class AsyncAddressResolverImpl : public rtc::AsyncResolverInterface {
+ public:
+ AsyncAddressResolverImpl(P2PSocketDispatcher* dispatcher);
+ ~AsyncAddressResolverImpl() override;
+
+ // rtc::AsyncResolverInterface interface.
+ void Start(const rtc::SocketAddress& addr) override;
+ bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override;
+ int GetError() const override;
+ void Destroy(bool wait) override;
+
+ private:
+ virtual void OnAddressResolved(const Vector<net::IPAddress>& addresses);
+
+ scoped_refptr<P2PAsyncAddressResolver> resolver_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ rtc::SocketAddress addr_; // Address to resolve.
+ std::vector<rtc::IPAddress> addresses_; // Resolved addresses.
+};
+
+IpcPacketSocket::IpcPacketSocket()
+ : type_(network::P2P_SOCKET_UDP),
+ state_(IS_UNINITIALIZED),
+ send_bytes_available_(kMaximumInFlightBytes),
+ writable_signal_expected_(false),
+ error_(0),
+ max_discard_bytes_sequence_(0),
+ current_discard_bytes_sequence_(0),
+ packets_discarded_(0),
+ total_packets_(0) {
+ static_assert(kMaximumInFlightBytes > 0, "would send at zero rate");
+ std::fill_n(options_, static_cast<int>(network::P2P_SOCKET_OPT_MAX),
+ kDefaultNonSetOptionValue);
+}
+
+IpcPacketSocket::~IpcPacketSocket() {
+ if (state_ == IS_OPENING || state_ == IS_OPEN || state_ == IS_ERROR) {
+ Close();
+ }
+
+ UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ApplicationMaxConsecutiveBytesDiscard.v2",
+ max_discard_bytes_sequence_, 1, 1000000, 200);
+ if (total_packets_ > 0) {
+ UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
+ (packets_discarded_ * 100) / total_packets_);
+ }
+}
+
+void IpcPacketSocket::TraceSendThrottlingState() const {
+ TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
+ send_bytes_available_);
+ TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
+ in_flight_packet_records_.size());
+}
+
+void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
+ current_discard_bytes_sequence_ += bytes_discarded;
+ packets_discarded_++;
+
+ if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
+ max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
+ }
+}
+
+bool IpcPacketSocket::Init(network::P2PSocketType type,
+ std::unique_ptr<P2PSocketClientImpl> client,
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const rtc::SocketAddress& remote_address) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, IS_UNINITIALIZED);
+
+ type_ = type;
+ auto* client_ptr = client.get();
+ client_ = std::move(client);
+ local_address_ = local_address;
+ remote_address_ = remote_address;
+ state_ = IS_OPENING;
+
+ net::IPEndPoint local_endpoint;
+ if (!jingle_glue::SocketAddressToIPEndPoint(local_address, &local_endpoint)) {
+ return false;
+ }
+
+ net::IPEndPoint remote_endpoint;
+ if (!remote_address.IsNil()) {
+ DCHECK(IsTcpClientSocket(type_));
+
+ if (remote_address.IsUnresolvedIP()) {
+ remote_endpoint =
+ net::IPEndPoint(net::IPAddress(), remote_address.port());
+ } else {
+ if (!jingle_glue::SocketAddressToIPEndPoint(remote_address,
+ &remote_endpoint)) {
+ return false;
+ }
+ }
+ }
+
+ // We need to send both resolved and unresolved address in Init. Unresolved
+ // address will be used in case of TLS for certificate hostname matching.
+ // Certificate will be tied to domain name not to IP address.
+ network::P2PHostAndIPEndPoint remote_info(remote_address.hostname(),
+ remote_endpoint);
+
+ client_ptr->Init(type, local_endpoint, min_port, max_port, remote_info, this);
+
+ return true;
+}
+
+void IpcPacketSocket::InitAcceptedTcp(
+ std::unique_ptr<blink::P2PSocketClient> client,
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, IS_UNINITIALIZED);
+
+ client_ = std::move(client);
+ local_address_ = local_address;
+ remote_address_ = remote_address;
+ state_ = IS_OPEN;
+ TraceSendThrottlingState();
+ client_->SetDelegate(this);
+}
+
+// rtc::AsyncPacketSocket interface.
+rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return local_address_;
+}
+
+rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return remote_address_;
+}
+
+int IpcPacketSocket::Send(const void* data,
+ size_t data_size,
+ const rtc::PacketOptions& options) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return SendTo(data, data_size, remote_address_, options);
+}
+
+int IpcPacketSocket::SendTo(const void* data,
+ size_t data_size,
+ const rtc::SocketAddress& address,
+ const rtc::PacketOptions& options) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ switch (state_) {
+ case IS_UNINITIALIZED:
+ NOTREACHED();
+ error_ = EWOULDBLOCK;
+ return -1;
+ case IS_OPENING:
+ error_ = EWOULDBLOCK;
+ return -1;
+ case IS_CLOSED:
+ error_ = ENOTCONN;
+ return -1;
+ case IS_ERROR:
+ return -1;
+ case IS_OPEN:
+ // Continue sending the packet.
+ break;
+ }
+
+ if (data_size == 0) {
+ NOTREACHED();
+ return 0;
+ }
+
+ total_packets_++;
+
+ if (data_size > send_bytes_available_) {
+ TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
+ TRACE_EVENT_SCOPE_THREAD, "id",
+ client_->GetSocketID());
+ if (!writable_signal_expected_) {
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
+ static_cast<int>(in_flight_packet_records_.size())));
+
+ writable_signal_expected_ = true;
+ }
+
+ error_ = EWOULDBLOCK;
+ IncrementDiscardCounters(data_size);
+ return -1;
+ } else {
+ current_discard_bytes_sequence_ = 0;
+ }
+
+ net::IPEndPoint address_chrome;
+ if (address.IsUnresolvedIP()) {
+ address_chrome = net::IPEndPoint(net::IPAddress(), address.port());
+ } else {
+ if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
+ LOG(WARNING) << "Failed to convert remote address to IPEndPoint: address="
+ << address.ipaddr().ToSensitiveString()
+ << ", remote_address_="
+ << remote_address_.ipaddr().ToSensitiveString();
+ NOTREACHED();
+ error_ = EINVAL;
+ return -1;
+ }
+ }
+
+ send_bytes_available_ -= data_size;
+
+ const int8_t* data_char = reinterpret_cast<const int8_t*>(data);
+ Vector<int8_t> data_vector;
+ data_vector.AppendRange(data_char, data_char + data_size);
+ 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
+ // P2PSocketClientImpl::Send().
+ DCHECK_NE(packet_id, 0uL);
+
+ in_flight_packet_records_.push_back(
+ InFlightPacketRecord(packet_id, data_size));
+ TraceSendThrottlingState();
+
+ // Fake successful send. The caller ignores result anyway.
+ return data_size;
+}
+
+int IpcPacketSocket::Close() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ client_->Close();
+ state_ = IS_CLOSED;
+
+ return 0;
+}
+
+rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ switch (state_) {
+ case IS_UNINITIALIZED:
+ NOTREACHED();
+ return STATE_CLOSED;
+
+ case IS_OPENING:
+ return STATE_BINDING;
+
+ case IS_OPEN:
+ if (IsTcpClientSocket(type_)) {
+ return STATE_CONNECTED;
+ } else {
+ return STATE_BOUND;
+ }
+
+ case IS_CLOSED:
+ case IS_ERROR:
+ return STATE_CLOSED;
+ }
+
+ NOTREACHED();
+ return STATE_CLOSED;
+}
+
+int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
+ network::P2PSocketOption p2p_socket_option = network::P2P_SOCKET_OPT_MAX;
+ if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
+ // unsupported option.
+ return -1;
+ }
+
+ *value = options_[p2p_socket_option];
+ return 0;
+}
+
+int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ network::P2PSocketOption p2p_socket_option = network::P2P_SOCKET_OPT_MAX;
+ if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
+ // Option is not supported.
+ return -1;
+ }
+
+ options_[p2p_socket_option] = value;
+
+ if (state_ == IS_OPEN) {
+ // Options will be applied when state becomes IS_OPEN in OnOpen.
+ return DoSetOption(p2p_socket_option, value);
+ }
+ return 0;
+}
+
+int IpcPacketSocket::DoSetOption(network::P2PSocketOption option, int value) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK_EQ(state_, IS_OPEN);
+
+ client_->SetOption(option, value);
+ return 0;
+}
+
+int IpcPacketSocket::GetError() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return error_;
+}
+
+void IpcPacketSocket::SetError(int error) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ error_ = error;
+}
+
+void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) {
+ // Always expect correct IPv4 address to be allocated.
+ NOTREACHED();
+ OnError();
+ return;
+ }
+
+ state_ = IS_OPEN;
+ TraceSendThrottlingState();
+
+ // Set all pending options if any.
+ for (int i = 0; i < network::P2P_SOCKET_OPT_MAX; ++i) {
+ if (options_[i] != kDefaultNonSetOptionValue)
+ DoSetOption(static_cast<network::P2PSocketOption>(i), options_[i]);
+ }
+
+ SignalAddressReady(this, local_address_);
+ if (IsTcpClientSocket(type_)) {
+ // If remote address is unresolved, set resolved remote IP address received
+ // in the callback. This address will be used while sending the packets
+ // over the network.
+ if (remote_address_.IsUnresolvedIP()) {
+ rtc::SocketAddress jingle_socket_address;
+ // |remote_address| could be unresolved if the connection is behind a
+ // proxy.
+ if (!remote_address.address().empty() &&
+ jingle_glue::IPEndPointToSocketAddress(remote_address,
+ &jingle_socket_address)) {
+ // Set only the IP address.
+ remote_address_.SetResolvedIP(jingle_socket_address.ipaddr());
+ }
+ }
+
+ // SignalConnect after updating the |remote_address_| so that the listener
+ // can get the resolved remote address.
+ SignalConnect(this);
+ }
+}
+
+void IpcPacketSocket::OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ std::unique_ptr<blink::P2PSocketClient> client) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
+
+ rtc::SocketAddress remote_address;
+ if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
+ // Always expect correct IPv4 address to be allocated.
+ NOTREACHED();
+ }
+ socket->InitAcceptedTcp(std::move(client), local_address_, remote_address);
+ SignalNewConnection(this, socket.release());
+}
+
+void IpcPacketSocket::OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ CHECK(!in_flight_packet_records_.empty());
+
+ const InFlightPacketRecord& record = in_flight_packet_records_.front();
+
+ // Tracking is not turned on for TCP so it's always 0. For UDP, this will
+ // cause a crash when the packet ids don't match.
+ CHECK(send_metrics.packet_id == 0 ||
+ record.packet_id == send_metrics.packet_id);
+
+ send_bytes_available_ += record.packet_size;
+
+ DCHECK_LE(send_bytes_available_, kMaximumInFlightBytes);
+
+ in_flight_packet_records_.pop_front();
+ TraceSendThrottlingState();
+
+ SignalSentPacket(this, rtc::SentPacket(send_metrics.rtc_packet_id,
+ send_metrics.send_time_ms));
+
+ if (writable_signal_expected_ && send_bytes_available_ > 0) {
+ blink::WebRtcLogMessage(base::StringPrintf(
+ "IpcPacketSocket: sending is unblocked. %d packets in flight.",
+ static_cast<int>(in_flight_packet_records_.size())));
+
+ writable_signal_expected_ = false;
+ SignalReadyToSend(this);
+ }
+}
+
+void IpcPacketSocket::OnError() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ bool was_closed = (state_ == IS_ERROR || state_ == IS_CLOSED);
+ state_ = IS_ERROR;
+ error_ = ECONNABORTED;
+ if (!was_closed) {
+ SignalClose(this, 0);
+ }
+}
+
+void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const base::TimeTicks& timestamp) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ rtc::SocketAddress address_lj;
+
+ if (address.address().empty()) {
+ DCHECK(IsTcpClientSocket(type_));
+ // |address| could be empty for TCP connections behind a proxy.
+ address_lj = remote_address_;
+ } else {
+ if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) {
+ // We should always be able to convert address here because we
+ // don't expect IPv6 address on IPv4 connections.
+ NOTREACHED();
+ return;
+ }
+ }
+
+ SignalReadPacket(this, reinterpret_cast<const char*>(&data[0]), data.size(),
+ address_lj, timestamp.since_origin().InMicroseconds());
+}
+
+AsyncAddressResolverImpl::AsyncAddressResolverImpl(
+ P2PSocketDispatcher* dispatcher)
+ : resolver_(new P2PAsyncAddressResolver(dispatcher)) {}
+
+AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Port and hostname must be copied to the resolved address returned from
+ // GetResolvedAddress.
+ addr_ = addr;
+
+ resolver_->Start(addr,
+ base::BindOnce(&AsyncAddressResolverImpl::OnAddressResolved,
+ base::Unretained(this)));
+}
+
+bool AsyncAddressResolverImpl::GetResolvedAddress(
+ int family,
+ rtc::SocketAddress* addr) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (addresses_.empty())
+ return false;
+
+ for (size_t i = 0; i < addresses_.size(); ++i) {
+ if (family == addresses_[i].family()) {
+ *addr = addr_;
+ addr->SetResolvedIP(addresses_[i]);
+ return true;
+ }
+ }
+ return false;
+}
+
+int AsyncAddressResolverImpl::GetError() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return addresses_.empty() ? -1 : 0;
+}
+
+void AsyncAddressResolverImpl::Destroy(bool wait) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ resolver_->Cancel();
+ // Libjingle doesn't need this object any more and it's not going to delete
+ // it explicitly.
+ delete this;
+}
+
+void AsyncAddressResolverImpl::OnAddressResolved(
+ const Vector<net::IPAddress>& addresses) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (size_t i = 0; i < addresses.size(); ++i) {
+ rtc::SocketAddress socket_address;
+ if (!jingle_glue::IPEndPointToSocketAddress(
+ net::IPEndPoint(addresses[i], 0), &socket_address)) {
+ NOTREACHED();
+ }
+ addresses_.push_back(socket_address.ipaddr());
+ }
+ SignalDone(this);
+}
+
+} // namespace
+
+IpcPacketSocketFactory::IpcPacketSocketFactory(
+ P2PSocketDispatcher* socket_dispatcher,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation)
+ : socket_dispatcher_(socket_dispatcher),
+ traffic_annotation_(traffic_annotation) {}
+
+IpcPacketSocketFactory::~IpcPacketSocketFactory() {}
+
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port) {
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
+ std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
+ if (!socket->Init(network::P2P_SOCKET_UDP, std::move(socket_client),
+ local_address, min_port, max_port, rtc::SocketAddress())) {
+ return nullptr;
+ }
+ return socket.release();
+}
+
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ int opts) {
+ // TODO(sergeyu): Implement SSL support.
+ if (opts & rtc::PacketSocketFactory::OPT_SSLTCP)
+ return nullptr;
+
+ network::P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TCP_SERVER
+ : network::P2P_SOCKET_TCP_SERVER;
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
+ std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
+ if (!socket->Init(type, std::move(socket_client), local_address, min_port,
+ max_port, rtc::SocketAddress())) {
+ return nullptr;
+ }
+ return socket.release();
+}
+
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address,
+ const rtc::ProxyInfo& proxy_info,
+ const std::string& user_agent,
+ const rtc::PacketSocketTcpOptions& opts) {
+ network::P2PSocketType type;
+ if (opts.opts & rtc::PacketSocketFactory::OPT_SSLTCP) {
+ type = (opts.opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_SSLTCP_CLIENT
+ : network::P2P_SOCKET_SSLTCP_CLIENT;
+ } else if (opts.opts & rtc::PacketSocketFactory::OPT_TLS) {
+ type = (opts.opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TLS_CLIENT
+ : network::P2P_SOCKET_TLS_CLIENT;
+ } else {
+ type = (opts.opts & rtc::PacketSocketFactory::OPT_STUN)
+ ? network::P2P_SOCKET_STUN_TCP_CLIENT
+ : network::P2P_SOCKET_TCP_CLIENT;
+ }
+ auto socket_client = std::make_unique<P2PSocketClientImpl>(
+ socket_dispatcher_, traffic_annotation_);
+ std::unique_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
+ if (!socket->Init(type, std::move(socket_client), local_address, 0, 0,
+ remote_address))
+ return nullptr;
+ return socket.release();
+}
+
+rtc::AsyncResolverInterface* IpcPacketSocketFactory::CreateAsyncResolver() {
+ std::unique_ptr<AsyncAddressResolverImpl> resolver(
+ new AsyncAddressResolverImpl(socket_dispatcher_));
+ return resolver.release();
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..21a0a25dc80
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/ipc_socket_factory.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_SOCKET_FACTORY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_SOCKET_FACTORY_H_
+
+#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/platform_export.h"
+#include "third_party/webrtc/api/packet_socket_factory.h"
+
+namespace blink {
+
+class P2PSocketDispatcher;
+
+// IpcPacketSocketFactory implements rtc::PacketSocketFactory
+// interface for libjingle using IPC-based P2P sockets. The class must
+// be used on a thread that is a libjingle thread (implements
+// rtc::Thread) and also has associated base::MessageLoop. Each
+// socket created by the factory must be used on the thread it was
+// created on.
+class IpcPacketSocketFactory : public rtc::PacketSocketFactory {
+ public:
+ PLATFORM_EXPORT explicit IpcPacketSocketFactory(
+ P2PSocketDispatcher* socket_dispatcher,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation);
+ ~IpcPacketSocketFactory() override;
+
+ rtc::AsyncPacketSocket* CreateUdpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port) override;
+ rtc::AsyncPacketSocket* CreateServerTcpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ int opts) override;
+ rtc::AsyncPacketSocket* CreateClientTcpSocket(
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address,
+ const rtc::ProxyInfo& proxy_info,
+ const std::string& user_agent,
+ const rtc::PacketSocketTcpOptions& opts) override;
+ rtc::AsyncResolverInterface* CreateAsyncResolver() override;
+
+ private:
+ P2PSocketDispatcher* socket_dispatcher_;
+ const net::NetworkTrafficAnnotationTag traffic_annotation_;
+
+ DISALLOW_COPY_AND_ASSIGN(IpcPacketSocketFactory);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_IPC_SOCKET_FACTORY_H_
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
new file mode 100644
index 00000000000..ae1a35be488
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.cc
@@ -0,0 +1,69 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use 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/p2p/mdns_responder_adapter.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "jingle/glue/utils.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/ip_address.h"
+#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/platform/platform.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/rtc_base/ip_address.h"
+
+namespace blink {
+
+namespace {
+
+void OnNameCreatedForAddress(
+ webrtc::MdnsResponderInterface::NameCreatedCallback callback,
+ const rtc::IPAddress& addr,
+ const String& name,
+ bool announcement_scheduled) {
+ // We currently ignore whether there is an announcement sent for the name.
+ callback(addr, name.Utf8());
+}
+
+void OnNameRemovedForAddress(
+ webrtc::MdnsResponderInterface::NameRemovedCallback callback,
+ bool removed,
+ bool goodbye_scheduled) {
+ // We currently ignore whether there is a goodbye sent for the name.
+ callback(removed);
+}
+
+} // namespace
+
+MdnsResponderAdapter::MdnsResponderAdapter() {
+ 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()->GetBrowserInterfaceBrokerProxy()->GetInterface(
+ std::move(receiver));
+}
+
+MdnsResponderAdapter::~MdnsResponderAdapter() = default;
+
+void MdnsResponderAdapter::CreateNameForAddress(const rtc::IPAddress& addr,
+ NameCreatedCallback callback) {
+ shared_remote_client_->CreateNameForAddress(
+ jingle_glue::RtcIPAddressToNetIPAddress(addr),
+ base::BindOnce(&OnNameCreatedForAddress, callback, addr));
+}
+
+void MdnsResponderAdapter::RemoveNameForAddress(const rtc::IPAddress& addr,
+ NameRemovedCallback callback) {
+ shared_remote_client_->RemoveNameForAddress(
+ jingle_glue::RtcIPAddressToNetIPAddress(addr),
+ base::BindOnce(&OnNameRemovedForAddress, callback));
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..79a70b7c4b6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/mdns_responder_adapter.h
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_MDNS_RESPONDER_ADAPTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_MDNS_RESPONDER_ADAPTER_H_
+
+#include "mojo/public/cpp/bindings/shared_remote.h"
+#include "services/network/public/mojom/mdns_responder.mojom-blink-forward.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/rtc_base/mdns_responder_interface.h"
+
+namespace rtc {
+class IPAddress;
+} // namespace rtc
+
+namespace blink {
+
+// 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
+// and resolve mDNS hostnames to conceal local IP addresses.
+class PLATFORM_EXPORT MdnsResponderAdapter
+ : public webrtc::MdnsResponderInterface {
+ public:
+ // The adapter should be created on the main thread to have access to the
+ // connector to the service manager.
+ MdnsResponderAdapter();
+ ~MdnsResponderAdapter() override;
+
+ // webrtc::MdnsResponderInterface implementation.
+ void CreateNameForAddress(const rtc::IPAddress& addr,
+ NameCreatedCallback callback) override;
+ void RemoveNameForAddress(const rtc::IPAddress& addr,
+ NameRemovedCallback callback) override;
+
+ private:
+ mojo::SharedRemote<network::mojom::blink::MdnsResponder>
+ shared_remote_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(MdnsResponderAdapter);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_MDNS_RESPONDER_ADAPTER_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/network_list_manager.h b/chromium/third_party/blink/renderer/platform/p2p/network_list_manager.h
new file mode 100644
index 00000000000..0be11c05b1a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/network_list_manager.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// NetworkListManager interface is introduced to enable unit test on
+// IpcNetworkManager such that it doesn't depend on implementation of
+// P2PSocketDispatcher.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+
+class NetworkListObserver;
+
+// TODO(crbug.com/787254): Verify whether this abstract class is still
+// needed now that its Clients have all switched to Blink.
+class PLATFORM_EXPORT NetworkListManager {
+ public:
+ // Add a new network list observer. Each observer is called
+ // immidiately after it is registered and then later whenever
+ // network configuration changes. Can be called on any thread. The
+ // observer is always called on the thread it was added.
+ virtual void AddNetworkListObserver(
+ NetworkListObserver* network_list_observer) = 0;
+
+ // Removes network list observer. Must be called on the thread on
+ // which the observer was added.
+ virtual void RemoveNetworkListObserver(
+ NetworkListObserver* network_list_observer) = 0;
+
+ protected:
+ // Marked as protected to prevent explicit deletion, as
+ // P2PSocketDispatcher is not owned by IpcNetworkManager.
+ virtual ~NetworkListManager() {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/network_list_observer.h b/chromium/third_party/blink/renderer/platform/p2p/network_list_observer.h
new file mode 100644
index 00000000000..714c9a79db5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/network_list_observer.h
@@ -0,0 +1,37 @@
+// 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_P2P_NETWORK_LIST_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_OBSERVER_H_
+
+#include <vector>
+
+namespace net {
+class IPAddress;
+struct NetworkInterface;
+typedef std::vector<NetworkInterface> NetworkInterfaceList;
+} // namespace net
+
+namespace blink {
+
+// TODO(crbug.com/787254): Verify whether this abstract class is still
+// needed now that its Clients have all switched to Blink.
+//
+// TODO(crbug.com/787254): Move this class away from std::vector.
+class NetworkListObserver {
+ public:
+ virtual ~NetworkListObserver() {}
+
+ virtual void OnNetworkListChanged(
+ const net::NetworkInterfaceList& list,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) = 0;
+
+ protected:
+ NetworkListObserver() {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_LIST_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.cc b/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.cc
new file mode 100644
index 00000000000..b21e0a4e178
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.cc
@@ -0,0 +1,21 @@
+// 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/p2p/network_manager_uma.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
+
+namespace blink {
+
+void ReportTimeToUpdateNetworkList(const base::TimeDelta& ticks) {
+ UMA_HISTOGRAM_TIMES("WebRTC.PeerConnection.TimeToNetworkUpdated", ticks);
+}
+
+void ReportIPPermissionStatus(IPPermissionStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPPermissionStatus", status,
+ PERMISSION_MAX);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.h b/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.h
new file mode 100644
index 00000000000..618e3d9f8e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/network_manager_uma.h
@@ -0,0 +1,37 @@
+// 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_P2P_NETWORK_MANAGER_UMA_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_MANAGER_UMA_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace base {
+class TimeDelta;
+} // namespace base
+
+namespace blink {
+
+// TODO(crbug.com/787254): Move the enum and helper methods here
+// out of the Blink exposed API when all users of it have been Onion souped.
+
+// Need to be kept the same order as in histograms.xml
+enum IPPermissionStatus {
+ PERMISSION_UNKNOWN, // Requested but have never fired SignalNetworksChanged.
+ PERMISSION_NOT_REQUESTED, // Multiple routes is not requested.
+ PERMISSION_DENIED, // Requested but denied.
+ PERMISSION_GRANTED_WITH_CHECKING, // Requested and granted after checking
+ // mic/camera permission.
+ PERMISSION_GRANTED_WITHOUT_CHECKING, // Requested and granted without
+ // checking mic/camera permission.
+ PERMISSION_MAX,
+};
+
+PLATFORM_EXPORT void ReportIPPermissionStatus(IPPermissionStatus status);
+PLATFORM_EXPORT void ReportTimeToUpdateNetworkList(
+ const base::TimeDelta& ticks);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_NETWORK_MANAGER_UMA_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_client.h b/chromium/third_party/blink/renderer/platform/p2p/socket_client.h
new file mode 100644
index 00000000000..4b0ef9b81df
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client.h
@@ -0,0 +1,51 @@
+// 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_P2P_SOCKET_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_H_
+
+#include <stdint.h>
+
+#include "net/base/ip_endpoint.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace rtc {
+struct PacketOptions;
+}
+
+namespace blink {
+
+class P2PSocketClientDelegate;
+
+// P2P socket that routes all calls over IPC.
+//
+// TODO(crbug.com/787254): Verify whether this class is still needed
+// now that all its clients are in Blink.
+//
+// Also, move it away from std::vector.
+class P2PSocketClient {
+ public:
+ virtual ~P2PSocketClient() {}
+
+ // Send the |data| to the |address| using Differentiated Services Code Point
+ // |dscp|. Return value is the unique packet_id for this packet.
+ virtual uint64_t Send(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const rtc::PacketOptions& options) = 0;
+
+ virtual void SetOption(network::P2PSocketOption option, int value) = 0;
+
+ // Must be called before the socket is destroyed.
+ virtual void Close() = 0;
+
+ virtual int GetSocketID() const = 0;
+ virtual void SetDelegate(P2PSocketClientDelegate* delegate) = 0;
+
+ protected:
+ P2PSocketClient() {}
+};
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_client_delegate.h b/chromium/third_party/blink/renderer/platform/p2p/socket_client_delegate.h
new file mode 100644
index 00000000000..282784fb526
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client_delegate.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_DELEGATE_H_
+
+#include "net/base/ip_endpoint.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+
+namespace blink {
+
+class P2PSocketClient;
+
+// TODO(crbug.com/787254): Consider eliminating this pure virtual class now
+// that it has moved to blink/renderer.
+class P2PSocketClientDelegate {
+ public:
+ virtual ~P2PSocketClientDelegate() {}
+
+ // Called after the socket has been opened with the local endpoint address
+ // as argument. Please note that in the precence of multiple interfaces,
+ // you should not rely on the local endpoint address if possible.
+ virtual void OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) = 0;
+
+ // For a socket that is listening on incoming TCP connectsion, this
+ // function is called when a new client connects.
+ virtual void OnIncomingTcpConnection(
+ const net::IPEndPoint& address,
+ std::unique_ptr<P2PSocketClient> client) = 0;
+
+ // Called once for each Send() call after the send is complete.
+ virtual void OnSendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) = 0;
+
+ // Called if an non-retryable error occurs.
+ virtual void OnError() = 0;
+
+ // Called when data is received on the socket.
+ virtual void OnDataReceived(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const base::TimeTicks& timestamp) = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
new file mode 100644
index 00000000000..65a89454e60
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.cc
@@ -0,0 +1,175 @@
+// 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/p2p/socket_client_impl.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/time/time.h"
+#include "crypto/random.h"
+#include "services/network/public/cpp/p2p_param_traits.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client_delegate.h"
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+
+namespace {
+
+uint64_t GetUniqueId(uint32_t random_socket_id, uint32_t packet_id) {
+ uint64_t uid = random_socket_id;
+ uid <<= 32;
+ uid |= packet_id;
+ return uid;
+}
+
+} // namespace
+
+namespace blink {
+
+P2PSocketClientImpl::P2PSocketClientImpl(
+ P2PSocketDispatcher* dispatcher,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation)
+ : dispatcher_(dispatcher),
+ socket_id_(0),
+ delegate_(nullptr),
+ state_(STATE_UNINITIALIZED),
+ traffic_annotation_(traffic_annotation),
+ random_socket_id_(0),
+ next_packet_id_(0),
+ binding_(this) {
+ crypto::RandBytes(&random_socket_id_, sizeof(random_socket_id_));
+}
+
+P2PSocketClientImpl::~P2PSocketClientImpl() {
+ CHECK(state_ == STATE_CLOSED || state_ == STATE_UNINITIALIZED);
+}
+
+void P2PSocketClientImpl::Init(
+ network::P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const network::P2PHostAndIPEndPoint& remote_address,
+ blink::P2PSocketClientDelegate* delegate) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(delegate);
+ // |delegate_| is only accessesed on |delegate_message_loop_|.
+ delegate_ = delegate;
+
+ DCHECK_EQ(state_, STATE_UNINITIALIZED);
+ state_ = STATE_OPENING;
+ network::mojom::blink::P2PSocketClientPtr socket_client;
+ binding_.Bind(mojo::MakeRequest(&socket_client));
+ binding_.set_connection_error_handler(base::BindOnce(
+ &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
+ dispatcher_->GetP2PSocketManager()->get()->CreateSocket(
+ type, local_address, network::P2PPortRange(min_port, max_port),
+ remote_address, std::move(socket_client), mojo::MakeRequest(&socket_));
+}
+
+uint64_t P2PSocketClientImpl::Send(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const rtc::PacketOptions& options) {
+ uint64_t unique_id = GetUniqueId(random_socket_id_, ++next_packet_id_);
+
+ // Can send data only when the socket is open.
+ DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
+ if (state_ == STATE_OPEN) {
+ SendWithPacketId(address, data, options, unique_id);
+ }
+
+ return unique_id;
+}
+
+void P2PSocketClientImpl::SendWithPacketId(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const rtc::PacketOptions& options,
+ uint64_t packet_id) {
+ TRACE_EVENT_ASYNC_BEGIN0("p2p", "Send", packet_id);
+
+ socket_->Send(data, network::P2PPacketInfo(address, options, packet_id),
+ net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
+}
+
+void P2PSocketClientImpl::SetOption(network::P2PSocketOption option,
+ int value) {
+ DCHECK(state_ == STATE_OPEN || state_ == STATE_ERROR);
+ if (state_ == STATE_OPEN)
+ socket_->SetOption(option, value);
+}
+
+void P2PSocketClientImpl::Close() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ delegate_ = nullptr;
+ if (socket_)
+ socket_.reset();
+
+ state_ = STATE_CLOSED;
+}
+
+int P2PSocketClientImpl::GetSocketID() const {
+ return socket_id_;
+}
+
+void P2PSocketClientImpl::SetDelegate(
+ blink::P2PSocketClientDelegate* delegate) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ delegate_ = delegate;
+}
+
+void P2PSocketClientImpl::SocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
+ state_ = STATE_OPEN;
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (delegate_)
+ delegate_->OnOpen(local_address, remote_address);
+}
+
+void P2PSocketClientImpl::SendComplete(
+ const network::P2PSendPacketMetrics& send_metrics) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (delegate_)
+ delegate_->OnSendComplete(send_metrics);
+}
+
+void P2PSocketClientImpl::IncomingTcpConnection(
+ const net::IPEndPoint& socket_address,
+ network::mojom::blink::P2PSocketPtr socket,
+ network::mojom::blink::P2PSocketClientRequest client_request) {
+ DCHECK_EQ(state_, STATE_OPEN);
+
+ auto new_client =
+ std::make_unique<P2PSocketClientImpl>(dispatcher_, traffic_annotation_);
+ new_client->state_ = STATE_OPEN;
+
+ network::mojom::blink::P2PSocketClientPtr socket_client;
+ new_client->socket_ = std::move(socket);
+ new_client->binding_.Bind(std::move(client_request));
+ new_client->binding_.set_connection_error_handler(base::BindOnce(
+ &P2PSocketClientImpl::OnConnectionError, base::Unretained(this)));
+
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (delegate_) {
+ delegate_->OnIncomingTcpConnection(socket_address, std::move(new_client));
+ } else {
+ // Just close the socket if there is no delegate to accept it.
+ new_client->Close();
+ }
+}
+
+void P2PSocketClientImpl::DataReceived(const net::IPEndPoint& socket_address,
+ const Vector<int8_t>& data,
+ base::TimeTicks timestamp) {
+ DCHECK_EQ(STATE_OPEN, state_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (delegate_)
+ delegate_->OnDataReceived(socket_address, data, timestamp);
+}
+
+void P2PSocketClientImpl::OnConnectionError() {
+ state_ = STATE_ERROR;
+ if (delegate_)
+ delegate_->OnError();
+}
+
+} // 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
new file mode 100644
index 00000000000..080c3fa5c8e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_client_impl.h
@@ -0,0 +1,118 @@
+// 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_P2P_SOCKET_CLIENT_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_IMPL_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/base/ip_endpoint.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+#include "services/network/public/mojom/p2p.mojom-blink.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace base {
+class TimeTicks;
+} // namespace base
+
+namespace blink {
+
+class P2PSocketDispatcher;
+
+// P2P socket that routes all calls over Mojo.
+//
+// The object runs on the WebRTC worker thread.
+class P2PSocketClientImpl : public blink::P2PSocketClient,
+ public network::mojom::blink::P2PSocketClient {
+ public:
+ P2PSocketClientImpl(
+ P2PSocketDispatcher* dispatcher,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation);
+ ~P2PSocketClientImpl() override;
+
+ // Initialize socket of the specified |type| and connected to the
+ // specified |address|. |address| matters only when |type| is set to
+ // P2P_SOCKET_TCP_CLIENT.
+ virtual void Init(network::P2PSocketType type,
+ const net::IPEndPoint& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const network::P2PHostAndIPEndPoint& remote_address,
+ blink::P2PSocketClientDelegate* delegate);
+
+ // Send the |data| to the |address| using Differentiated Services Code Point
+ // |dscp|. Return value is the unique packet_id for this packet.
+ uint64_t Send(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const rtc::PacketOptions& options) override;
+
+ // Setting socket options.
+ void SetOption(network::P2PSocketOption option, int value) override;
+
+ // Must be called before the socket is destroyed. The delegate may
+ // not be called after |closed_task| is executed.
+ void Close() override;
+
+ int GetSocketID() const override;
+
+ void SetDelegate(blink::P2PSocketClientDelegate* delegate) override;
+
+ private:
+ enum State {
+ STATE_UNINITIALIZED,
+ STATE_OPENING,
+ STATE_OPEN,
+ STATE_CLOSED,
+ STATE_ERROR,
+ };
+
+ friend class P2PSocketDispatcher;
+
+ // Helper function to be called by Send to handle different threading
+ // condition.
+ void SendWithPacketId(const net::IPEndPoint& address,
+ const Vector<int8_t>& data,
+ const rtc::PacketOptions& options,
+ uint64_t packet_id);
+
+ // network::mojom::blink::P2PSocketClient interface.
+ void SocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) override;
+ void SendComplete(const network::P2PSendPacketMetrics& send_metrics) override;
+ void IncomingTcpConnection(
+ const net::IPEndPoint& socket_address,
+ network::mojom::blink::P2PSocketPtr socket,
+ network::mojom::blink::P2PSocketClientRequest client_request) override;
+ void DataReceived(const net::IPEndPoint& socket_address,
+ const Vector<int8_t>& data,
+ base::TimeTicks timestamp) override;
+
+ void OnConnectionError();
+
+ P2PSocketDispatcher* dispatcher_;
+ THREAD_CHECKER(thread_checker_);
+ int socket_id_;
+ blink::P2PSocketClientDelegate* delegate_;
+ State state_;
+ const net::NetworkTrafficAnnotationTag traffic_annotation_;
+
+ // These two fields are used to identify packets for tracing.
+ uint32_t random_socket_id_;
+ uint32_t next_packet_id_;
+
+ network::mojom::blink::P2PSocketPtr socket_;
+ mojo::Binding<network::mojom::blink::P2PSocketClient> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(P2PSocketClientImpl);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_CLIENT_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
new file mode 100644
index 00000000000..c82473ef536
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/p2p/socket_dispatcher.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "services/network/public/cpp/p2p_param_traits.h"
+#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
+#include "third_party/blink/renderer/platform/p2p/socket_client_impl.h"
+
+namespace blink {
+
+P2PSocketDispatcher::P2PSocketDispatcher()
+ : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ network_list_observers_(
+ new base::ObserverListThreadSafe<blink::NetworkListObserver>()) {}
+
+P2PSocketDispatcher::~P2PSocketDispatcher() {}
+
+void P2PSocketDispatcher::AddNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) {
+ network_list_observers_->AddObserver(network_list_observer);
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&P2PSocketDispatcher::RequestNetworkEventsIfNecessary,
+ this));
+}
+
+void P2PSocketDispatcher::RemoveNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) {
+ network_list_observers_->RemoveObserver(network_list_observer);
+}
+
+scoped_refptr<network::mojom::blink::ThreadSafeP2PSocketManagerPtr>
+P2PSocketDispatcher::GetP2PSocketManager() {
+ base::AutoLock lock(p2p_socket_manager_lock_);
+ if (!thread_safe_p2p_socket_manager_) {
+ network::mojom::blink::P2PSocketManagerPtr p2p_socket_manager;
+ p2p_socket_manager_request_ = mojo::MakeRequest(&p2p_socket_manager);
+ p2p_socket_manager.set_connection_error_handler(base::BindOnce(
+ &P2PSocketDispatcher::OnConnectionError, base::Unretained(this)));
+ thread_safe_p2p_socket_manager_ =
+ network::mojom::blink::ThreadSafeP2PSocketManagerPtr::Create(
+ std::move(p2p_socket_manager));
+ }
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&P2PSocketDispatcher::RequestInterfaceIfNecessary, this));
+ return thread_safe_p2p_socket_manager_;
+}
+
+void P2PSocketDispatcher::NetworkListChanged(
+ const Vector<net::NetworkInterface>& networks,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ networks_ = networks;
+ default_ipv4_local_address_ = default_ipv4_local_address;
+ default_ipv6_local_address_ = default_ipv6_local_address;
+
+ // TODO(crbug.com/787254): Remove this helper when network_list_observer.h
+ // 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++)
+ copy[i] = networks[i];
+
+ network_list_observers_->Notify(
+ FROM_HERE, &blink::NetworkListObserver::OnNetworkListChanged,
+ std::move(copy), default_ipv4_local_address, default_ipv6_local_address);
+}
+
+void P2PSocketDispatcher::RequestInterfaceIfNecessary() {
+ if (!p2p_socket_manager_request_.is_pending())
+ return;
+
+ blink::Platform::Current()->GetBrowserInterfaceBrokerProxy()->GetInterface(
+ std::move(p2p_socket_manager_request_));
+}
+
+void P2PSocketDispatcher::RequestNetworkEventsIfNecessary() {
+ if (network_notification_client_receiver_.is_bound()) {
+ // TODO(crbug.com/787254): Remove this helper when network_list_observer.h
+ // 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++)
+ copy[i] = networks_[i];
+
+ network_list_observers_->Notify(
+ FROM_HERE, &blink::NetworkListObserver::OnNetworkListChanged,
+ std::move(copy), default_ipv4_local_address_,
+ default_ipv6_local_address_);
+ } else {
+ GetP2PSocketManager()->get()->StartNetworkNotifications(
+ network_notification_client_receiver_.BindNewPipeAndPassRemote());
+ }
+}
+
+void P2PSocketDispatcher::OnConnectionError() {
+ base::AutoLock lock(p2p_socket_manager_lock_);
+ thread_safe_p2p_socket_manager_.reset();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
new file mode 100644
index 00000000000..53423773df6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/p2p/socket_dispatcher.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// P2PSocketDispatcher is a per-renderer object that dispatchers all
+// P2P messages received from the browser and relays all P2P messages
+// sent to the browser. P2PSocketClient instances register themselves
+// with the dispatcher using RegisterClient() and UnregisterClient().
+//
+// Relationship of classes.
+//
+// P2PSocketHost P2PSocketClient
+// ^ ^
+// | |
+// v IPC v
+// P2PSocketDispatcherHost <---------> P2PSocketDispatcher
+//
+// P2PSocketDispatcher receives and dispatches messages on the
+// IO thread.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_DISPATCHER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_DISPATCHER_H_
+
+#include <stdint.h>
+
+#include "base/callback_forward.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"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
+#include "net/base/ip_address.h"
+#include "net/base/network_interfaces.h"
+#include "services/network/public/cpp/p2p_socket_type.h"
+#include "services/network/public/mojom/p2p.mojom-blink.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace blink {
+class NetworkListObserver;
+}
+
+namespace blink {
+
+// This class is created on the main thread, but is used primarily on the
+// WebRTC worker threads.
+class PLATFORM_EXPORT P2PSocketDispatcher
+ : public base::RefCountedThreadSafe<P2PSocketDispatcher>,
+ public blink::NetworkListManager,
+ public network::mojom::blink::P2PNetworkNotificationClient {
+ public:
+ P2PSocketDispatcher();
+
+ // blink::NetworkListManager interface:
+ void AddNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) override;
+ void RemoveNetworkListObserver(
+ blink::NetworkListObserver* network_list_observer) override;
+
+ scoped_refptr<network::mojom::blink::ThreadSafeP2PSocketManagerPtr>
+ GetP2PSocketManager();
+
+ private:
+ friend class base::RefCountedThreadSafe<P2PSocketDispatcher>;
+
+ ~P2PSocketDispatcher() override;
+
+ // network::mojom::blink::P2PNetworkNotificationClient interface.
+ void NetworkListChanged(
+ const Vector<net::NetworkInterface>& networks,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) override;
+
+ void RequestInterfaceIfNecessary();
+ void RequestNetworkEventsIfNecessary();
+
+ void OnConnectionError();
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ // TODO(crbug.com/787254): When moving NetworkListObserver to Oilpan,
+ // thread-safety needs to be taken into account.
+ scoped_refptr<base::ObserverListThreadSafe<blink::NetworkListObserver>>
+ network_list_observers_;
+
+ network::mojom::blink::P2PSocketManagerRequest p2p_socket_manager_request_;
+ scoped_refptr<network::mojom::blink::ThreadSafeP2PSocketManagerPtr>
+ thread_safe_p2p_socket_manager_;
+ base::Lock p2p_socket_manager_lock_;
+
+ // Cached from last |NetworkListChanged| call.
+ Vector<net::NetworkInterface> networks_;
+ net::IPAddress default_ipv4_local_address_;
+ net::IPAddress default_ipv6_local_address_;
+
+ mojo::Receiver<network::mojom::blink::P2PNetworkNotificationClient>
+ network_notification_client_receiver_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcher);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_P2P_SOCKET_DISPATCHER_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/DEPS b/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
index 909e5b662ef..27851784cbb 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/DEPS
@@ -3,10 +3,14 @@ include_rules = [
"-third_party/blink/renderer/platform",
# Module.
+ "+third_party/blink/renderer/platform/p2p",
"+third_party/blink/renderer/platform/peerconnection",
+ "+third_party/blink/renderer/platform/media_capabilities",
"+third_party/blink/renderer/platform/webrtc",
# Dependencies.
+ "+base/strings/string_number_conversions.h",
+ "+base/strings/string_split.h",
"+base/threading/thread_restrictions.h",
"+media/base",
"+media/media_buildflags.h",
@@ -27,5 +31,6 @@ specific_include_rules = {
"+gpu/command_buffer/common/mailbox.h",
"+media/video/mock_gpu_video_accelerator_factories.h",
"+media/video/mock_video_encode_accelerator.h",
+ "+third_party/blink/renderer/platform/testing/video_frame_utils.h",
],
}
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/OWNERS b/chromium/third_party/blink/renderer/platform/peerconnection/OWNERS
index b3a7338c70a..b30d5fd6d29 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/OWNERS
@@ -1,3 +1,5 @@
file://third_party/blink/renderer/modules/peerconnection/OWNERS
+per-file rtc_video_*=file://media/gpu/OWNERS
+
# COMPONENT: Blink>WebRTC
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
index 0b7258484f4..f13f8e955f6 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_session_description_request.h
@@ -42,7 +42,7 @@ namespace blink {
class WebRTCSessionDescription;
class RTCSessionDescriptionRequest
- : public GarbageCollectedFinalized<RTCSessionDescriptionRequest> {
+ : public GarbageCollected<RTCSessionDescriptionRequest> {
public:
virtual ~RTCSessionDescriptionRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
index 0651cb89114..8510fb9635c 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_stats_request.h
@@ -40,7 +40,7 @@ namespace blink {
class MediaStreamComponent;
class RTCStatsResponseBase;
-class RTCStatsRequest : public GarbageCollectedFinalized<RTCStatsRequest> {
+class RTCStatsRequest : public GarbageCollected<RTCStatsRequest> {
public:
virtual ~RTCStatsRequest() = default;
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 ba2a0ab105f..2ab30075132 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
@@ -10,7 +10,6 @@
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "media/video/gpu_video_accelerator_factories.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_decoder_factory_util.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_adapter.h"
namespace blink {
@@ -59,11 +58,6 @@ class ScopedVideoDecoder : public webrtc::VideoDecoder {
} // namespace
-std::unique_ptr<webrtc::VideoDecoderFactory> CreateRTCVideoDecoderFactory(
- media::GpuVideoAcceleratorFactories* gpu_factories) {
- return std::make_unique<RTCVideoDecoderFactory>(gpu_factories);
-}
-
RTCVideoDecoderFactory::RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) {
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 0e5c1612b1e..bf83cf5c630 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
@@ -8,6 +8,9 @@
#include <memory>
#include <vector>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/unsafe_shared_memory_region.h"
@@ -22,6 +25,7 @@
#include "base/time/time.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
+#include "media/base/media_switches.h"
#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
@@ -211,6 +215,14 @@ class RTCVideoEncoder::Impl
// Perform encoding on an input frame from the input queue.
void EncodeOneFrame();
+ // Perform encoding on an input frame from the input queue using VEA native
+ // input mode. The input frame must be backed with GpuMemoryBuffer buffers.
+ void EncodeOneFrameWithNativeInput();
+
+ // Creates a GpuMemoryBuffer frame filled with black pixels. Returns true if
+ // the frame is successfully created; false otherwise.
+ bool CreateBlackGpuMemoryBufferFrame(const gfx::Size& natural_size);
+
// Notify that an input frame is finished for encoding. |index| is the index
// of the completed frame in |input_buffers_|.
void EncodeFrameFinished(int index);
@@ -289,6 +301,13 @@ class RTCVideoEncoder::Impl
// encoder.
int output_buffers_free_count_;
+ // Whether to send the frames to VEA as native buffer. Native buffer allows
+ // VEA to pass the buffer to the encoder directly without further processing.
+ bool use_native_input_;
+
+ // A black GpuMemoryBuffer frame used when the video track is disabled.
+ scoped_refptr<media::VideoFrame> black_gmb_frame_;
+
// webrtc::VideoEncoder encode complete callback.
webrtc::EncodedImageCallback* encoded_image_callback_;
@@ -321,6 +340,7 @@ RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
input_next_frame_(nullptr),
input_next_frame_keyframe_(false),
output_buffers_free_count_(0),
+ use_native_input_(false),
encoded_image_callback_(nullptr),
video_codec_type_(video_codec_type),
video_content_type_(video_content_type),
@@ -351,9 +371,21 @@ void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
return;
}
input_visible_size_ = input_visible_size;
+ media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_I420;
+ auto storage_type =
+ media::VideoEncodeAccelerator::Config::StorageType::kShmem;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kVideoCaptureUseGpuMemoryBuffer) &&
+ video_content_type_ != webrtc::VideoContentType::SCREENSHARE) {
+ // Use import mode for camera when GpuMemoryBuffer-based video capture is
+ // enabled.
+ pixel_format = media::PIXEL_FORMAT_NV12;
+ storage_type = media::VideoEncodeAccelerator::Config::StorageType::kDmabuf;
+ use_native_input_ = true;
+ }
const media::VideoEncodeAccelerator::Config config(
- media::PIXEL_FORMAT_I420, input_visible_size_, profile, bitrate * 1000,
- base::nullopt, base::nullopt, base::nullopt, base::nullopt,
+ pixel_format, input_visible_size_, profile, bitrate * 1000, base::nullopt,
+ base::nullopt, base::nullopt, storage_type,
video_content_type_ == webrtc::VideoContentType::SCREENSHARE
? media::VideoEncodeAccelerator::Config::ContentType::kDisplay
: media::VideoEncodeAccelerator::Config::ContentType::kCamera);
@@ -382,10 +414,10 @@ void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
}
// If there are no free input and output buffers, drop the frame to avoid a
- // deadlock. If there is a free input buffer, EncodeOneFrame will run and
- // unblock Encode(). If there are no free input buffers but there is a free
- // output buffer, EncodeFrameFinished will be called later to unblock
- // Encode().
+ // deadlock. If there is a free input buffer and |use_native_input_| is false,
+ // EncodeOneFrame will run and unblock Encode(). If there are no free input
+ // buffers but there is a free output buffer, EncodeFrameFinished will be
+ // called later to unblock Encode().
//
// The caller of Encode() holds a webrtc lock. The deadlock happens when:
// (1) Encode() is waiting for the frame to be encoded in EncodeOneFrame().
@@ -399,7 +431,8 @@ void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
// buffers. Returning an error in Encode() is not fatal and WebRTC will just
// continue. If this is a key frame, WebRTC will request a key frame again.
// Besides, webrtc will drop a frame if Encode() blocks too long.
- if (input_buffers_free_.IsEmpty() && output_buffers_free_count_ == 0) {
+ if (!use_native_input_ && input_buffers_free_.IsEmpty() &&
+ output_buffers_free_count_ == 0) {
DVLOG(2) << "Run out of input and output buffers. Drop the frame.";
SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
return;
@@ -407,6 +440,13 @@ void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
input_next_frame_ = input_frame;
input_next_frame_keyframe_ = force_keyframe;
+ // If |use_native_input_| is true, then we always queue the frame to the
+ // encoder since no intermediate buffer is needed in RTCVideoEncoder.
+ if (use_native_input_) {
+ EncodeOneFrameWithNativeInput();
+ return;
+ }
+
if (!input_buffers_free_.IsEmpty())
EncodeOneFrame();
}
@@ -449,8 +489,8 @@ void RTCVideoEncoder::Impl::RequestEncodingParametersChange(
// TODO(sprang): Clean this up if/when webrtc struct moves to int.
uint32_t layer_bitrate =
parameters.bitrate.GetBitrate(spatial_id, temporal_id);
- RTC_CHECK_LE(layer_bitrate,
- static_cast<uint32_t>(std::numeric_limits<int>::max()));
+ CHECK_LE(layer_bitrate,
+ static_cast<uint32_t>(std::numeric_limits<int>::max()));
if (!allocation.SetBitrate(spatial_id, temporal_id, layer_bitrate)) {
LOG(WARNING) << "Overflow in bitrate allocation: "
<< parameters.bitrate.ToString();
@@ -605,9 +645,9 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(
}
webrtc::EncodedImage image;
- image.Allocate(metadata.payload_size_bytes);
- image.set_size(metadata.payload_size_bytes);
- memcpy(image.data(), output_mapping_memory, metadata.payload_size_bytes);
+ image.SetEncodedData(webrtc::EncodedImageBuffer::Create(
+ static_cast<const uint8_t*>(output_mapping_memory),
+ metadata.payload_size_bytes));
image._encodedWidth = input_visible_size_.width();
image._encodedHeight = input_visible_size_.height();
image.SetTimestamp(rtp_timestamp.value());
@@ -757,9 +797,109 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
}
+void RTCVideoEncoder::Impl::EncodeOneFrameWithNativeInput() {
+ DVLOG(3) << "Impl::EncodeOneFrameWithNativeInput()";
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(input_next_frame_);
+
+ // EncodeOneFrameWithNativeInput() may re-enter EncodeFrameFinished() if
+ // VEA::Encode() fails, we receive a VEA::NotifyError(), and the
+ // media::VideoFrame we pass to Encode() gets destroyed early. Handle this by
+ // resetting our input_next_frame_* state before we hand off the VideoFrame to
+ // the VEA.
+ const webrtc::VideoFrame* next_frame = input_next_frame_;
+ const bool next_frame_keyframe = input_next_frame_keyframe_;
+ input_next_frame_ = nullptr;
+ input_next_frame_keyframe_ = false;
+
+ if (!video_encoder_) {
+ SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
+ return;
+ }
+
+ scoped_refptr<media::VideoFrame> frame;
+ if (next_frame->video_frame_buffer()->type() !=
+ webrtc::VideoFrameBuffer::Type::kNative) {
+ // If we get a non-native frame it's because the video track is disabled and
+ // WebRTC VideoBroadcaster replaces the camera frame with a black YUV frame.
+ if (!black_gmb_frame_) {
+ gfx::Size natural_size(next_frame->width(), next_frame->height());
+ if (!CreateBlackGpuMemoryBufferFrame(natural_size)) {
+ DVLOG(2) << "Failed to allocate native buffer for black frame";
+ SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_ERROR);
+ return;
+ }
+ }
+ frame = media::VideoFrame::WrapVideoFrame(
+ black_gmb_frame_, black_gmb_frame_->format(),
+ black_gmb_frame_->visible_rect(), black_gmb_frame_->natural_size());
+ frame->set_timestamp(
+ base::TimeDelta::FromMilliseconds(next_frame->ntp_time_ms()));
+ } else {
+ frame = static_cast<blink::WebRtcVideoFrameAdapter*>(
+ next_frame->video_frame_buffer().get())
+ ->getMediaVideoFrame();
+ }
+
+ if (frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ LogAndNotifyError(FROM_HERE, "frame isn't GpuMemoryBuffer based VideoFrame",
+ media::VideoEncodeAccelerator::kPlatformFailureError);
+ return;
+ }
+
+ constexpr int kDummyIndex = -1;
+ frame->AddDestructionObserver(media::BindToCurrentLoop(base::BindOnce(
+ &RTCVideoEncoder::Impl::EncodeFrameFinished, this, kDummyIndex)));
+ if (!failed_timestamp_match_) {
+ DCHECK(std::find_if(pending_timestamps_.begin(), pending_timestamps_.end(),
+ [&frame](const RTCTimestamps& entry) {
+ return entry.media_timestamp_ == frame->timestamp();
+ }) == pending_timestamps_.end());
+ pending_timestamps_.emplace_back(frame->timestamp(),
+ next_frame->timestamp(),
+ next_frame->render_time_ms());
+ }
+ video_encoder_->Encode(frame, next_frame_keyframe);
+ SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
+}
+
+bool RTCVideoEncoder::Impl::CreateBlackGpuMemoryBufferFrame(
+ const gfx::Size& natural_size) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ auto gmb = gpu_factories_->CreateGpuMemoryBuffer(
+ natural_size, gfx::BufferFormat::YUV_420_BIPLANAR,
+ gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE);
+
+ if (!gmb || !gmb->Map()) {
+ black_gmb_frame_ = nullptr;
+ return false;
+ }
+ // Fills the NV12 frame with YUV black (0x00, 0x80, 0x80).
+ const auto gmb_size = gmb->GetSize();
+ memset(static_cast<uint8_t*>(gmb->memory(0)), 0x0,
+ gmb->stride(0) * gmb_size.height());
+ memset(static_cast<uint8_t*>(gmb->memory(1)), 0x80,
+ gmb->stride(1) * gmb_size.height() / 2);
+ gmb->Unmap();
+
+ gpu::MailboxHolder empty_mailboxes[media::VideoFrame::kMaxPlanes];
+ black_gmb_frame_ = media::VideoFrame::WrapExternalGpuMemoryBuffer(
+ gfx::Rect(gmb_size), natural_size, std::move(gmb), empty_mailboxes,
+ base::NullCallback(), base::TimeDelta());
+ return true;
+}
+
void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) {
DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (use_native_input_) {
+ if (input_next_frame_)
+ EncodeOneFrameWithNativeInput();
+ return;
+ }
+
DCHECK_GE(index, 0);
DCHECK_LT(index, static_cast<int>(input_buffers_.size()));
input_buffers_free_.push_back(index);
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 a0943b829af..fc5bcb11250 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
@@ -11,7 +11,6 @@
#include "media/media_buildflags.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/platform/modules/peerconnection/rtc_video_encoder_factory_util.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
#include "third_party/webrtc/api/video_codecs/video_encoder.h"
@@ -104,11 +103,6 @@ bool IsSameFormat(const webrtc::SdpVideoFormat& format1,
} // anonymous namespace
-std::unique_ptr<webrtc::VideoEncoderFactory> CreateRTCVideoEncoderFactory(
- media::GpuVideoAcceleratorFactories* gpu_factories) {
- return std::make_unique<RTCVideoEncoderFactory>(gpu_factories);
-}
-
RTCVideoEncoderFactory::RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) {
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
index 590402cb7b0..173a1bddab5 100644
--- a/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/rtc_void_request.h
@@ -37,7 +37,7 @@
namespace blink {
-class RTCVoidRequest : public GarbageCollectedFinalized<RTCVoidRequest> {
+class RTCVoidRequest : public GarbageCollected<RTCVoidRequest> {
public:
virtual ~RTCVoidRequest() = default;
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.cc b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.cc
new file mode 100644
index 00000000000..bd64f2e09d0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.cc
@@ -0,0 +1,312 @@
+// 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/peerconnection/stun_field_trial.h"
+
+#include <math.h>
+
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "third_party/webrtc/api/packet_socket_factory.h"
+#include "third_party/webrtc/rtc_base/async_packet_socket.h"
+#include "third_party/webrtc/rtc_base/async_resolver_interface.h"
+#include "third_party/webrtc/rtc_base/ip_address.h"
+#include "third_party/webrtc/rtc_base/network.h"
+#include "third_party/webrtc/rtc_base/socket_address.h"
+#include "third_party/webrtc/rtc_base/thread.h"
+
+using stunprober::StunProber;
+
+namespace blink {
+
+namespace {
+
+// This needs to be the same as NatTypeCounters in histograms.xml.
+enum NatType {
+ NAT_TYPE_NONE,
+ NAT_TYPE_UNKNOWN,
+ NAT_TYPE_SYMMETRIC,
+ NAT_TYPE_NON_SYMMETRIC,
+ NAT_TYPE_MAX
+};
+
+// This needs to match "NatType" in histograms.xml.
+const char* const NatTypeNames[] = {"NoNAT", "UnknownNAT", "SymNAT",
+ "NonSymNAT"};
+static_assert(base::size(NatTypeNames) == NAT_TYPE_MAX,
+ "NatType enums must match names");
+
+NatType GetNatType(stunprober::NatType nat_type) {
+ switch (nat_type) {
+ case stunprober::NATTYPE_NONE:
+ return NAT_TYPE_NONE;
+ case stunprober::NATTYPE_UNKNOWN:
+ return NAT_TYPE_UNKNOWN;
+ case stunprober::NATTYPE_SYMMETRIC:
+ return NAT_TYPE_SYMMETRIC;
+ case stunprober::NATTYPE_NON_SYMMETRIC:
+ return NAT_TYPE_NON_SYMMETRIC;
+ default:
+ return NAT_TYPE_MAX;
+ }
+}
+
+std::string HistogramName(const std::string& prefix,
+ NatType nat_type,
+ int interval_ms,
+ int batch_index) {
+ return base::StringPrintf("WebRTC.Stun.%s.%s.%dms.%d", prefix.c_str(),
+ NatTypeNames[nat_type], interval_ms, batch_index);
+}
+
+} // namespace
+
+StunProberTrial::Param::Param() {}
+
+StunProberTrial::Param::~Param() {}
+
+StunProberTrial::StunProberTrial(rtc::NetworkManager* network_manager,
+ const std::string& params,
+ rtc::PacketSocketFactory* factory)
+ : network_manager_(network_manager),
+ param_line_(params),
+ factory_(factory) {
+ // We have to connect to the signal to avoid a race condition if network
+ // manager hasn't received the network update when we start, the StunProber
+ // will just fail.
+ network_manager_->SignalNetworksChanged.connect(
+ this, &StunProberTrial::OnNetworksChanged);
+ network_manager_->StartUpdating();
+}
+
+StunProberTrial::~StunProberTrial() {}
+
+void StunProberTrial::SaveHistogramData() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NatType nat_type = NAT_TYPE_UNKNOWN;
+ int interval_ms = 0;
+ int count = 0;
+ int total_requests_sent = 0;
+ int total_responses_received = 0;
+ for (auto* prober : probers_) {
+ ++count;
+
+ // Get the stats.
+ StunProber::Stats stats;
+ if (!prober->GetStats(&stats))
+ return;
+
+ // Check if the NAT type is consistent.
+ if (nat_type == NAT_TYPE_UNKNOWN) {
+ nat_type = GetNatType(stats.nat_type);
+ } else {
+ NatType type = GetNatType(stats.nat_type);
+ // For subsequent probers, we might get unknown as nattype if all the
+ // bindings fail, but it's ok.
+ if (nat_type != type && type != NAT_TYPE_UNKNOWN)
+ return;
+ }
+
+ // Check that the interval is consistent. Use the real probe interval for
+ // reporting, converting from nanosecond to millisecond.
+ int new_interval_ms =
+ round(static_cast<float>(stats.actual_request_interval_ns) / 1000);
+ if (interval_ms == 0) {
+ interval_ms = new_interval_ms;
+ } else if (abs(interval_ms - new_interval_ms) > 3) {
+ DVLOG(1) << "current interval: " << new_interval_ms
+ << " is too far off from previous one: " << interval_ms;
+ continue;
+ }
+
+ // Sum up the total sent and recv packets.
+ total_requests_sent += stats.raw_num_request_sent;
+ total_responses_received += stats.num_response_received;
+
+ if (count % batch_size_ > 0)
+ continue;
+
+ // If 50% of probers are not counted, ignore this batch.
+ // |raw_num_request_sent| should be the same for each prober.
+ if (total_requests_sent < (stats.raw_num_request_sent * batch_size_ / 2)) {
+ total_responses_received = 0;
+ total_requests_sent = 0;
+ continue;
+ }
+
+ int success_rate = total_responses_received * 100 / total_requests_sent;
+ // Use target_request_interval_ns for naming of UMA to avoid inconsistency.
+ std::string histogram_name = HistogramName(
+ "BatchSuccessPercent", nat_type,
+ stats.target_request_interval_ns / 1000, count / batch_size_);
+
+ // Mimic the same behavior as UMA_HISTOGRAM_PERCENTAGE. We can't use
+ // that macro as the histogram name is determined dynamically.
+ base::HistogramBase* histogram =
+ base::Histogram::FactoryGet(histogram_name, 1, 101, 102,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ histogram->Add(success_rate);
+
+ DVLOG(1) << "Histogram '" << histogram_name.c_str()
+ << "' = " << success_rate;
+
+ DVLOG(1) << "Shared Socket Mode: " << stats.shared_socket_mode;
+ DVLOG(1) << "Requests sent: " << total_requests_sent;
+ DVLOG(1) << "Responses received: " << total_responses_received;
+ DVLOG(1) << "Target interval (ns): " << stats.target_request_interval_ns;
+ DVLOG(1) << "Actual interval (ns): " << stats.actual_request_interval_ns;
+ DVLOG(1) << "NAT Type: " << NatTypeNames[nat_type];
+ DVLOG(1) << "Host IP: " << stats.host_ip;
+
+ total_requests_sent = 0;
+ total_responses_received = 0;
+ }
+}
+
+bool StunProberTrial::ParseParameters(const std::string& param_line,
+ StunProberTrial::Param* params) {
+ std::vector<std::string> stun_params = base::SplitString(
+ param_line, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+ if (stun_params.size() < 5) {
+ DLOG(ERROR) << "Not enough parameters specified in StartStunProbeTrial";
+ return false;
+ }
+ auto param = stun_params.begin();
+
+ if (param->empty()) {
+ params->requests_per_ip = 10;
+ } else if (!base::StringToInt(*param, &params->requests_per_ip)) {
+ DLOG(ERROR) << "Failed to parse request_per_ip in StartStunProbeTrial";
+ return false;
+ }
+ param++;
+
+ // Set inter-probe interval randomly from 0, 5, 10, ... 50, 100 ms.
+ if ((*param).empty()) {
+ params->interval_ms = base::RandInt(0, 11) * 5;
+ } else if (!base::StringToInt(*param, &params->interval_ms)) {
+ DLOG(ERROR) << "Failed to parse interval in StartStunProbeTrial";
+ return false;
+ }
+ param++;
+
+ if ((*param).empty()) {
+ params->shared_socket_mode = base::RandInt(0, 1);
+ } else if (!base::StringToInt(*param, &params->shared_socket_mode)) {
+ DLOG(ERROR) << "Failed to parse shared_socket_mode in StartStunProbeTrial";
+ return false;
+ }
+ param++;
+
+ if (param->empty()) {
+ params->batch_size = 5;
+ } else if (!base::StringToInt(*param, &params->batch_size)) {
+ DLOG(ERROR) << "Failed to parse batch_size in StartStunProbeTrial";
+ return false;
+ }
+ param++;
+
+ if (param->empty()) {
+ params->total_batches = 5;
+ } else if (!base::StringToInt(*param, &params->total_batches)) {
+ DLOG(ERROR) << "Failed to parse total_batches in StartStunProbeTrial";
+ return false;
+ }
+ param++;
+
+ while (param != stun_params.end() && !param->empty()) {
+ rtc::SocketAddress server;
+ if (!server.FromString(*param)) {
+ DLOG(ERROR) << "Failed to parse address in StartStunProbeTrial";
+ return false;
+ }
+ params->servers.push_back(server);
+ param++;
+ }
+
+ return !params->servers.empty();
+}
+
+void StunProberTrial::OnNetworksChanged() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DVLOG(1) << "Starting stun trial with params: " << param_line_;
+ rtc::NetworkManager::NetworkList networks;
+ network_manager_->GetNetworks(&networks);
+
+ // If we don't have local addresses, we won't be able to determine whether
+ // we're behind NAT or not.
+ if (networks.empty()) {
+ DLOG(ERROR) << "No networks specified in StartStunProbeTrial";
+ return;
+ }
+
+ network_manager_->StopUpdating();
+ network_manager_->SignalNetworksChanged.disconnect(this);
+
+ StunProberTrial::Param params;
+ if (!ParseParameters(param_line_, &params)) {
+ return;
+ }
+
+ batch_size_ = params.batch_size;
+ total_probers_ = params.total_batches * batch_size_;
+
+ for (int i = 0; i < total_probers_; i++) {
+ std::unique_ptr<StunProber> prober(
+ new StunProber(factory_, rtc::Thread::Current(), networks));
+ if (!prober->Prepare(params.servers, (params.shared_socket_mode != 0),
+ params.interval_ms, params.requests_per_ip, 1000,
+ this)) {
+ DLOG(ERROR) << "Failed to Prepare in StartStunProbeTrial";
+ return;
+ }
+
+ probers_.push_back(prober.release());
+ }
+}
+
+void StunProberTrial::OnFinished(StunProber* prober,
+ StunProber::Status result) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (result == StunProber::SUCCESS)
+ ++finished_probers_;
+
+ if (finished_probers_ == total_probers_)
+ SaveHistogramData();
+}
+
+void StunProberTrial::OnPrepared(StunProber* prober,
+ StunProber::Status result) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (result == StunProber::SUCCESS)
+ ++ready_probers_;
+
+ if (ready_probers_ == total_probers_) {
+ // TODO(guoweis) estimated_execution_time() is the same for all probers. It
+ // could be moved up to the StunProberTrial class once the DNS resolution
+ // part is moved up too.
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(
+ probers_.front()->estimated_execution_time()),
+ this, &StunProberTrial::OnTimer);
+ }
+}
+
+void StunProberTrial::OnTimer() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ probers_[started_probers_]->Start(this);
+ started_probers_++;
+
+ if (started_probers_ == total_probers_)
+ timer_.Stop();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h
new file mode 100644
index 00000000000..223e0145f2c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial.h
@@ -0,0 +1,103 @@
+// 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_PEERCONNECTION_STUN_FIELD_TRIAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_STUN_FIELD_TRIAL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_manager.h"
+#include "third_party/blink/renderer/platform/p2p/network_list_observer.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/p2p/stunprober/stun_prober.h"
+#include "third_party/webrtc/rtc_base/network.h"
+#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"
+
+namespace rtc {
+class PacketSocketFactory;
+class SocketAddress;
+} // namespace rtc
+
+namespace blink {
+
+// Wait for 30 seconds to avoid high CPU usage during browser start-up which
+// might affect the accuracy of the trial. The trial wakes up the browser every
+// 1 ms for no more than 3 seconds to see if time has passed for sending next
+// stun probe.
+static const int kExperimentStartDelayMs = 30000;
+
+// TODO(crbug.com/787254): Migrate away from std::vector and std::string.
+class StunProberTrial : public stunprober::StunProber::Observer,
+ public sigslot::has_slots<> {
+ public:
+ struct PLATFORM_EXPORT Param {
+ Param();
+ ~Param();
+ int requests_per_ip = 0;
+ int interval_ms = 0;
+ int shared_socket_mode = 0;
+ int batch_size = 0;
+ int total_batches = 0;
+ std::vector<rtc::SocketAddress> servers;
+ };
+
+ PLATFORM_EXPORT StunProberTrial(rtc::NetworkManager* network_manager,
+ const std::string& params,
+ rtc::PacketSocketFactory* factory);
+ ~StunProberTrial() override;
+
+ private:
+ // This will use |factory_| to create sockets, send stun binding requests with
+ // various intervals as determined by |params|, observed the success rate and
+ // latency of the stun responses and report through UMA.
+ void OnNetworksChanged();
+
+ // Parsing function to decode the '/' separated parameter string |params|.
+ static PLATFORM_EXPORT bool ParseParameters(const std::string& param_line,
+ Param* params);
+
+ // stunprober::StunProber::Observer:
+ void OnPrepared(stunprober::StunProber* prober,
+ stunprober::StunProber::Status status) override;
+ // OnFinished is invoked when the StunProber receives all the responses or
+ // times out.
+ void OnFinished(stunprober::StunProber* prober,
+ stunprober::StunProber::Status status) override;
+
+ // This will be invoked repeatedly for |total_probers_| times with the
+ // interval equal to the estimated run time of a prober.
+ void OnTimer();
+
+ void SaveHistogramData();
+
+ rtc::NetworkManager* network_manager_;
+ std::string param_line_;
+ rtc::PacketSocketFactory* factory_ = nullptr;
+ int total_probers_ = 0;
+ int batch_size_ = 0;
+ int ready_probers_ = 0;
+ int started_probers_ = 0;
+ int finished_probers_ = 0;
+ std::vector<stunprober::StunProber*> probers_;
+ THREAD_CHECKER(thread_checker_);
+
+ // The reason we use a timer instead of depending on the OnFinished callback
+ // of each prober is that the OnFinished is not fired at the last of STUN
+ // request of each prober, instead, it includes a timeout period which waits
+ // the server response to come back. Having a timer guarantees the
+ // inter-prober intervals is the same as the STUN interval inside a prober.
+ base::RepeatingTimer timer_;
+
+ FRIEND_TEST_ALL_PREFIXES(StunProbeTrial, VerifyParameterParsing);
+ DISALLOW_COPY_AND_ASSIGN(StunProberTrial);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_STUN_FIELD_TRIAL_H_
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial_test.cc b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial_test.cc
new file mode 100644
index 00000000000..e48d6c04fec
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/stun_field_trial_test.cc
@@ -0,0 +1,41 @@
+// 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/peerconnection/stun_field_trial.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/rtc_base/socket_address.h"
+
+namespace blink {
+
+TEST(StunProbeTrial, VerifyParameterParsing) {
+ StunProberTrial::Param params;
+ std::string param_line;
+
+ param_line = "20/100/1/3/3/server:3478/server2:3478";
+ EXPECT_TRUE(StunProberTrial::ParseParameters(param_line, &params));
+ EXPECT_EQ(params.requests_per_ip, 20);
+ EXPECT_EQ(params.interval_ms, 100);
+ EXPECT_EQ(params.shared_socket_mode, 1);
+ EXPECT_EQ(params.batch_size, 3);
+ EXPECT_EQ(params.total_batches, 3);
+ EXPECT_EQ(params.servers.size(), 2u);
+ EXPECT_EQ(params.servers[0], rtc::SocketAddress("server", 3478));
+ EXPECT_EQ(params.servers[1], rtc::SocketAddress("server2", 3478));
+ params.servers.clear();
+
+ param_line = "/////server:3478";
+ EXPECT_TRUE(StunProberTrial::ParseParameters(param_line, &params));
+ EXPECT_EQ(params.requests_per_ip, 10);
+ EXPECT_EQ(params.servers.size(), 1u);
+ EXPECT_EQ(params.servers[0], rtc::SocketAddress("server", 3478));
+ params.servers.clear();
+
+ // Make sure there is no crash. Parsing will fail as there is no server
+ // specified.
+ param_line = "/////";
+ EXPECT_FALSE(StunProberTrial::ParseParameters(param_line, &params));
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..9ce0d60d4e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.cc
@@ -0,0 +1,191 @@
+// 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/cpu.h"
+#include "base/logging.h"
+#include "base/system/sys_info.h"
+#include "third_party/blink/public/platform/modules/peerconnection/audio_codec_factory.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/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::CreateWebrtcVideoEncoderFactory(GetGpuFactories()),
+ CanCpuEncodeHdSmoothly()) {}
+
+TransmissionEncodingInfoHandler::TransmissionEncodingInfoHandler(
+ std::unique_ptr<webrtc::VideoEncoderFactory> video_encoder_factory,
+ bool cpu_hd_smooth)
+ : cpu_hd_smooth_(cpu_hd_smooth) {
+ 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();
+ supported_video_codecs_.insert(codec_name);
+ const auto codec_info =
+ video_encoder_factory->QueryVideoEncoder(video_format);
+ if (codec_info.is_hardware_accelerated)
+ 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(
+ "supported_video_codecs_:[%s] hardware_accelerated_video_codecs_:[%s] "
+ "supported_audio_codecs_:[%s]",
+ StringHashSetToString(supported_video_codecs_).Utf8().c_str(),
+ 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
new file mode 100644
index 00000000000..dbb9ececd2b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h
@@ -0,0 +1,75 @@
+// 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 supported video codecs.
+ HashSet<String> supported_video_codecs_;
+ // 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
new file mode 100644
index 00000000000..6454d942a83
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler_test.cc
@@ -0,0 +1,323 @@
+// 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,
+ bool is_hardware_accelerated = false,
+ bool has_internal_source = false) {
+ supported_video_formats_.push_back(video_format);
+ codec_info_.push_back({.is_hardware_accelerated = is_hardware_accelerated,
+ .has_internal_source = has_internal_source});
+ }
+
+ std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
+ return supported_video_formats_;
+ }
+
+ CodecInfo QueryVideoEncoder(
+ const webrtc::SdpVideoFormat& format) const override {
+ DCHECK_EQ(supported_video_formats_.size(), codec_info_.size());
+ for (size_t i = 0; i < supported_video_formats_.size(); ++i) {
+ if (supported_video_formats_[i] == format)
+ return codec_info_[i];
+ }
+ NOTREACHED() << "QueryVideoEncoder() assumes |format| is supported.";
+ return CodecInfo();
+ }
+
+ 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_;
+ std::vector<CodecInfo> codec_info_;
+};
+
+} // 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(), base::nullopt,
+ base::nullopt};
+ }
+
+ blink::WebMediaConfiguration ComposeWebMediaConfigurationForVideo(
+ const std::string& mime_type,
+ const std::string& codec) {
+ return blink::WebMediaConfiguration(
+ blink::MediaConfigurationType::kTransmission, base::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), base::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) {
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ 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"),
+ true);
+ 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.
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ // Assume powerful CPU.
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ true);
+ VerifyEncodingInfo(handler,
+ ComposeWebMediaConfigurationForVideo("video/vp8", ""),
+ true, true, false);
+}
+
+TEST_F(TransmissionEncodingInfoHandlerTest, SmoothVideoCodecVgaResolution) {
+ // Assume no HW vp8 encoder.
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ // Assume no powerful CPU.
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ false);
+
+ // VP8 encoding for 640x480 video.
+ blink::WebMediaConfiguration config(
+ blink::MediaConfigurationType::kTransmission, base::nullopt,
+ ComposeVideoConfiguration("video/vp8", "", 640, 480));
+
+ VerifyEncodingInfo(handler, config, true, true, false);
+}
+
+TEST_F(TransmissionEncodingInfoHandlerTest, SmoothVideoCodecBelowHdResolution) {
+ // Assume no HW vp8 encoder.
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ // Assume no powerful CPU.
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ false);
+
+ // VP8 encoding for 1024x768 video. Note its area size is below 1280x720).
+ blink::WebMediaConfiguration config(
+ blink::MediaConfigurationType::kTransmission, base::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", ""));
+
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ 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"),
+ true);
+ 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.
+ auto video_encoder_factory = std::make_unique<FakeVideoEncoderFactory>();
+ video_encoder_factory->AddSupportedFormat(webrtc::SdpVideoFormat("vp8"),
+ false);
+ // Assume powerful CPU.
+ TransmissionEncodingInfoHandler handler(std::move(video_encoder_factory),
+ true);
+ VerifyEncodingInfo(handler, config, true, true, false);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..85ae4df4e58
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.cc
@@ -0,0 +1,204 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use 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/video_codec_factory.h"
+
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h"
+#include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h"
+#include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h"
+#include "third_party/webrtc/media/base/codec.h"
+#include "third_party/webrtc/media/engine/encoder_simulcast_proxy.h"
+#include "third_party/webrtc/media/engine/internal_decoder_factory.h"
+#include "third_party/webrtc/media/engine/internal_encoder_factory.h"
+#include "third_party/webrtc/media/engine/simulcast_encoder_adapter.h"
+
+#if defined(OS_ANDROID)
+#include "media/base/android/media_codec_util.h"
+#endif
+
+namespace blink {
+
+namespace {
+
+bool IsFormatSupported(
+ const std::vector<webrtc::SdpVideoFormat>& supported_formats,
+ const webrtc::SdpVideoFormat& format) {
+ for (const webrtc::SdpVideoFormat& supported_format : supported_formats) {
+ if (cricket::IsSameCodec(format.name, format.parameters,
+ supported_format.name,
+ supported_format.parameters)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename Factory>
+bool IsFormatSupported(const Factory* factory,
+ const webrtc::SdpVideoFormat& format) {
+ return factory && IsFormatSupported(factory->GetSupportedFormats(), format);
+}
+
+// Merge |formats1| and |formats2|, but avoid adding duplicate formats.
+std::vector<webrtc::SdpVideoFormat> MergeFormats(
+ std::vector<webrtc::SdpVideoFormat> formats1,
+ const std::vector<webrtc::SdpVideoFormat>& formats2) {
+ for (const webrtc::SdpVideoFormat& format : formats2) {
+ // Don't add same format twice.
+ if (!IsFormatSupported(formats1, format))
+ formats1.push_back(format);
+ }
+ return formats1;
+}
+
+std::unique_ptr<webrtc::VideoDecoder> CreateDecoder(
+ webrtc::VideoDecoderFactory* factory,
+ const webrtc::SdpVideoFormat& format) {
+ return factory ? factory->CreateVideoDecoder(format) : nullptr;
+}
+
+std::unique_ptr<webrtc::VideoDecoder> Wrap(
+ std::unique_ptr<webrtc::VideoDecoder> software_decoder,
+ std::unique_ptr<webrtc::VideoDecoder> hardware_decoder) {
+ if (software_decoder && hardware_decoder) {
+ return webrtc::CreateVideoDecoderSoftwareFallbackWrapper(
+ std::move(software_decoder), std::move(hardware_decoder));
+ }
+ return hardware_decoder ? std::move(hardware_decoder)
+ : std::move(software_decoder);
+}
+
+std::unique_ptr<webrtc::VideoEncoder> Wrap(
+ std::unique_ptr<webrtc::VideoEncoder> software_encoder,
+ std::unique_ptr<webrtc::VideoEncoder> hardware_encoder) {
+ if (software_encoder && hardware_encoder) {
+ return webrtc::CreateVideoEncoderSoftwareFallbackWrapper(
+ std::move(software_encoder), std::move(hardware_encoder));
+ }
+ return hardware_encoder ? std::move(hardware_encoder)
+ : std::move(software_encoder);
+}
+
+// This class combines a hardware factory with the internal factory and adds
+// internal SW codecs, simulcast, and SW fallback wrappers.
+class EncoderAdapter : public webrtc::VideoEncoderFactory {
+ public:
+ explicit EncoderAdapter(
+ std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory)
+ : hardware_encoder_factory_(std::move(hardware_encoder_factory)) {}
+
+ webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
+ const webrtc::SdpVideoFormat& format) const override {
+ const webrtc::VideoEncoderFactory* factory =
+ IsFormatSupported(hardware_encoder_factory_.get(), format)
+ ? hardware_encoder_factory_.get()
+ : &software_encoder_factory_;
+ return factory->QueryVideoEncoder(format);
+ }
+
+ std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
+ const webrtc::SdpVideoFormat& format) override {
+ std::unique_ptr<webrtc::VideoEncoder> software_encoder;
+ if (IsFormatSupported(&software_encoder_factory_, format)) {
+ software_encoder = std::make_unique<webrtc::EncoderSimulcastProxy>(
+ &software_encoder_factory_, format);
+ }
+
+ std::unique_ptr<webrtc::VideoEncoder> hardware_encoder;
+ if (IsFormatSupported(hardware_encoder_factory_.get(), format)) {
+ hardware_encoder =
+ base::EqualsCaseInsensitiveASCII(format.name.c_str(),
+ cricket::kVp9CodecName)
+ ? hardware_encoder_factory_->CreateVideoEncoder(format)
+ : std::make_unique<webrtc::SimulcastEncoderAdapter>(
+ hardware_encoder_factory_.get(), format);
+ }
+
+ return Wrap(std::move(software_encoder), std::move(hardware_encoder));
+ }
+
+ std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
+ std::vector<webrtc::SdpVideoFormat> software_formats =
+ software_encoder_factory_.GetSupportedFormats();
+ return hardware_encoder_factory_
+ ? MergeFormats(software_formats,
+ hardware_encoder_factory_->GetSupportedFormats())
+ : software_formats;
+ }
+
+ private:
+ webrtc::InternalEncoderFactory software_encoder_factory_;
+ const std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory_;
+};
+
+// This class combines a hardware codec factory with the internal factory and
+// adds internal SW codecs and SW fallback wrappers.
+class DecoderAdapter : public webrtc::VideoDecoderFactory {
+ public:
+ explicit DecoderAdapter(
+ std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory)
+ : hardware_decoder_factory_(std::move(hardware_decoder_factory)) {}
+
+ std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
+ const webrtc::SdpVideoFormat& format) override {
+ std::unique_ptr<webrtc::VideoDecoder> software_decoder =
+ CreateDecoder(&software_decoder_factory_, format);
+
+ std::unique_ptr<webrtc::VideoDecoder> hardware_decoder =
+ CreateDecoder(hardware_decoder_factory_.get(), format);
+
+ return Wrap(std::move(software_decoder), std::move(hardware_decoder));
+ }
+
+ std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
+ std::vector<webrtc::SdpVideoFormat> software_formats =
+ software_decoder_factory_.GetSupportedFormats();
+ return hardware_decoder_factory_
+ ? MergeFormats(software_formats,
+ hardware_decoder_factory_->GetSupportedFormats())
+ : software_formats;
+ }
+
+ private:
+ webrtc::InternalDecoderFactory software_decoder_factory_;
+ const std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory_;
+};
+
+} // namespace
+
+std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory(
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory;
+
+ if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
+ Platform::Current()->IsWebRtcHWEncodingEnabled()) {
+ encoder_factory = std::make_unique<RTCVideoEncoderFactory>(gpu_factories);
+ }
+
+#if defined(OS_ANDROID)
+ if (!media::MediaCodecUtil::SupportsSetParameters())
+ encoder_factory.reset();
+#endif
+
+ return std::make_unique<EncoderAdapter>(std::move(encoder_factory));
+}
+
+std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory(
+ media::GpuVideoAcceleratorFactories* gpu_factories) {
+ std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory;
+
+ if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
+ Platform::Current()->IsWebRtcHWDecodingEnabled()) {
+ decoder_factory = std::make_unique<RTCVideoDecoderFactory>(gpu_factories);
+ }
+
+ return std::make_unique<DecoderAdapter>(std::move(decoder_factory));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h b/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h
new file mode 100644
index 00000000000..522d9aefb5e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/peerconnection/video_codec_factory.h
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
+#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
+
+namespace media {
+class GpuVideoAcceleratorFactories;
+}
+
+namespace blink {
+
+PLATFORM_EXPORT std::unique_ptr<webrtc::VideoEncoderFactory>
+CreateWebrtcVideoEncoderFactory(
+ media::GpuVideoAcceleratorFactories* gpu_factories);
+PLATFORM_EXPORT std::unique_ptr<webrtc::VideoDecoderFactory>
+CreateWebrtcVideoDecoderFactory(
+ media::GpuVideoAcceleratorFactories* gpu_factories);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PEERCONNECTION_VIDEO_CODEC_FACTORY_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 95788affd9f..1698102ad64 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
@@ -69,6 +69,8 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
if (!(frame->IsMappable() &&
(frame->format() == media::PIXEL_FORMAT_I420 ||
frame->format() == media::PIXEL_FORMAT_I420A)) &&
+ !(frame->storage_type() ==
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) &&
!frame->HasTextures()) {
// Since connecting sources and sinks do not check the format, we need to
// just ignore formats that we can not handle.
@@ -123,9 +125,11 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
timestamp_aligner_.TranslateTimestamp(frame->timestamp().InMicroseconds(),
now_us);
- // Return |frame| directly if it is texture backed, because there is no
- // cropping support for texture yet. See http://crbug/503653.
- if (frame->HasTextures()) {
+ // Return |frame| directly if it is texture not backed up by GPU memory,
+ // because there is no cropping support for texture yet. See
+ // http://crbug/503653.
+ if (frame->HasTextures() &&
+ frame->storage_type() != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
// The webrtc::VideoFrame::UpdateRect expected by WebRTC must
// be relative to the |visible_rect()|. We need to translate.
const auto cropped_rect =
@@ -159,17 +163,11 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
frame_adaptation_params.scale_to_height);
// Soft-apply the new (combined) cropping and scaling.
scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::WrapVideoFrame(*frame, frame->format(),
+ media::VideoFrame::WrapVideoFrame(frame, frame->format(),
cropped_visible_rect, adapted_size);
if (!video_frame)
return;
- // Attach shared ownership of the wrapped |frame| to the wrapping
- // |video_frame|.
- video_frame->AddDestructionObserver(
- base::BindOnce(base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(),
- std::move(frame)));
-
// If no scaling is needed, return a wrapped version of |frame| directly.
// The soft-applied cropping will be taken into account by the remainder
// of the pipeline.
@@ -183,6 +181,20 @@ void WebRtcVideoTrackSource::OnFrameCaptured(
return;
}
+ // Delay scaling if |video_frame| is backed by GpuMemoryBuffer.
+ if (video_frame->storage_type() ==
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ // When scaling is applied and any part of the frame has changed, we mark
+ // the whole frame as changed.
+ const auto update_rect_on_scaled =
+ accumulated_update_rect_.IsEmpty()
+ ? gfx::Rect()
+ : gfx::Rect(video_frame->natural_size());
+ DeliverFrame(std::move(video_frame), update_rect_on_scaled,
+ translated_camera_time_us);
+ return;
+ }
+
// Since scaling is required, hard-apply both the cropping and scaling before
// we hand the frame over to WebRTC.
const bool has_alpha = video_frame->format() == media::PIXEL_FORMAT_I420A;
@@ -251,10 +263,17 @@ void WebRtcVideoTrackSource::DeliverFrame(
// If the cropping or the size have changed since the previous
// frame, even if nothing in the incoming coded frame content has changed, we
// have to assume that every pixel in the outgoing frame has changed.
- if (frame->visible_rect() != cropping_rect_of_previous_delivered_frame_) {
+ if (frame->visible_rect() != cropping_rect_of_previous_delivered_frame_ ||
+ frame->natural_size() != natural_size_of_previous_delivered_frame_) {
cropping_rect_of_previous_delivered_frame_ = frame->visible_rect();
- update_rect = gfx::Rect(0, 0, frame->visible_rect().width(),
- frame->visible_rect().height());
+ natural_size_of_previous_delivered_frame_ = frame->natural_size();
+ if (frame->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ // Use the frame natural size since we delay the scaling.
+ update_rect = gfx::Rect(frame->natural_size());
+ } else {
+ update_rect = gfx::Rect(0, 0, frame->visible_rect().width(),
+ frame->visible_rect().height());
+ }
}
// Clear accumulated_update_rect_.
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 b3853e932fa..5d339e4e602 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
@@ -4,12 +4,14 @@
#include <algorithm>
+#include "base/bind_helpers.h"
#include "base/single_thread_task_runner.h"
#include "base/test/task_environment.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/modules/peerconnection/webrtc_video_track_source.h"
+#include "third_party/blink/renderer/platform/testing/video_frame_utils.h"
#include "third_party/webrtc/api/video/video_frame.h"
#include "third_party/webrtc/rtc_base/ref_counted_object.h"
@@ -32,7 +34,8 @@ class MockVideoSink : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
MOCK_METHOD1(OnFrame, void(const webrtc::VideoFrame&));
};
-class WebRtcVideoTrackSourceTest : public ::testing::Test {
+class WebRtcVideoTrackSourceTest
+ : public ::testing::TestWithParam<media::VideoFrame::StorageType> {
public:
WebRtcVideoTrackSourceTest()
: track_source_(new rtc::RefCountedObject<WebRtcVideoTrackSource>(
@@ -46,21 +49,22 @@ class WebRtcVideoTrackSourceTest : public ::testing::Test {
void SendTestFrame(const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
- const gfx::Size& natural_size) {
- scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_I420, coded_size, visible_rect, natural_size,
- base::TimeDelta());
+ const gfx::Size& natural_size,
+ media::VideoFrame::StorageType storage_type) {
+ scoped_refptr<media::VideoFrame> frame =
+ CreateTestFrame(coded_size, visible_rect, natural_size, storage_type);
track_source_->OnFrameCaptured(frame);
}
- void SendTestFrameWithUpdateRect(const gfx::Size& coded_size,
- const gfx::Rect& visible_rect,
- const gfx::Size& natural_size,
- int capture_counter,
- const gfx::Rect& update_rect) {
- scoped_refptr<media::VideoFrame> frame = media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_I420, coded_size, visible_rect, natural_size,
- base::TimeDelta());
+ void SendTestFrameWithUpdateRect(
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
+ const gfx::Size& natural_size,
+ int capture_counter,
+ const gfx::Rect& update_rect,
+ media::VideoFrame::StorageType storage_type) {
+ scoped_refptr<media::VideoFrame> frame =
+ CreateTestFrame(coded_size, visible_rect, natural_size, storage_type);
frame->metadata()->SetInteger(media::VideoFrameMetadata::CAPTURE_COUNTER,
capture_counter);
frame->metadata()->SetRect(media::VideoFrameMetadata::CAPTURE_UPDATE_RECT,
@@ -112,10 +116,11 @@ class WebRtcVideoTrackSourceTest : public ::testing::Test {
scoped_refptr<WebRtcVideoTrackSource> track_source_;
};
-TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo640360) {
+TEST_P(WebRtcVideoTrackSourceTest, CropFrameTo640360) {
const gfx::Size kCodedSize(640, 480);
const gfx::Rect kVisibleRect(0, 60, 640, 360);
const gfx::Size kNaturalSize(640, 360);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_KeepAsIs(kNaturalSize));
@@ -124,13 +129,14 @@ TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo640360) {
EXPECT_EQ(kNaturalSize.width(), frame.width());
EXPECT_EQ(kNaturalSize.height(), frame.height());
}));
- SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize);
+ SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize, storage_type);
}
-TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo320320) {
+TEST_P(WebRtcVideoTrackSourceTest, CropFrameTo320320) {
const gfx::Size kCodedSize(640, 480);
const gfx::Rect kVisibleRect(80, 0, 480, 480);
const gfx::Size kNaturalSize(320, 320);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_KeepAsIs(kNaturalSize));
@@ -139,13 +145,14 @@ TEST_F(WebRtcVideoTrackSourceTest, CropFrameTo320320) {
EXPECT_EQ(kNaturalSize.width(), frame.width());
EXPECT_EQ(kNaturalSize.height(), frame.height());
}));
- SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize);
+ SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize, storage_type);
}
-TEST_F(WebRtcVideoTrackSourceTest, Scale720To640360) {
+TEST_P(WebRtcVideoTrackSourceTest, Scale720To640360) {
const gfx::Size kCodedSize(1280, 720);
const gfx::Rect kVisibleRect(0, 0, 1280, 720);
const gfx::Size kNaturalSize(640, 360);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_KeepAsIs(kNaturalSize));
@@ -154,13 +161,14 @@ TEST_F(WebRtcVideoTrackSourceTest, Scale720To640360) {
EXPECT_EQ(kNaturalSize.width(), frame.width());
EXPECT_EQ(kNaturalSize.height(), frame.height());
}));
- SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize);
+ SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize, storage_type);
}
-TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
+TEST_P(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
const gfx::Size kCodedSize(640, 480);
const gfx::Rect kVisibleRect(0, 0, 640, 480);
const gfx::Size kNaturalSize(640, 480);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_KeepAsIs(kNaturalSize));
@@ -174,7 +182,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
}));
int capture_counter = 101; // arbitrary absolute value
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- capture_counter, kUpdateRect1);
+ capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Update rect for second frame should get passed along.
@@ -183,7 +191,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
ExpectUpdateRectEquals(kUpdateRect1, frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect1);
+ ++capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Simulate the next frame getting dropped
@@ -192,7 +200,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
const gfx::Rect kUpdateRect2(2, 3, 4, 5);
EXPECT_CALL(mock_sink_, OnFrame(_)).Times(0);
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect2);
+ ++capture_counter, kUpdateRect2, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// The |update_rect| for the next frame is expected to contain the union
@@ -208,7 +216,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
ExpectUpdateRectEquals(expected_update_rect, frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect3);
+ ++capture_counter, kUpdateRect3, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Simulate a gap in |capture_counter|. This is expected to cause the whole
@@ -220,7 +228,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
ExpectUpdateRectEquals(kVisibleRect, frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect4);
+ ++capture_counter, kUpdateRect4, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Important edge case (expected to be fairly common): An empty update rect
@@ -231,7 +239,8 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
EXPECT_TRUE(frame.update_rect().IsEmpty());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kEmptyRectWithZeroOrigin);
+ ++capture_counter, kEmptyRectWithZeroOrigin,
+ storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
const gfx::Rect kEmptyRectWithNonZeroOrigin(10, 20, 0, 0);
@@ -240,7 +249,8 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
EXPECT_TRUE(frame.update_rect().IsEmpty());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kEmptyRectWithNonZeroOrigin);
+ ++capture_counter, kEmptyRectWithNonZeroOrigin,
+ storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// A frame without a CAPTURE_COUNTER and CAPTURE_UPDATE_RECT is treated as the
@@ -249,14 +259,15 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithNoTransform) {
.WillOnce(Invoke([kVisibleRect](const webrtc::VideoFrame& frame) {
ExpectUpdateRectEquals(kVisibleRect, frame.update_rect());
}));
- SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize);
+ SendTestFrame(kCodedSize, kVisibleRect, kNaturalSize, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
}
-TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
+TEST_P(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
const gfx::Size kCodedSize(640, 480);
const gfx::Rect kVisibleRect(100, 50, 200, 80);
const gfx::Size kNaturalSize = gfx::Size(200, 80);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_KeepAsIs(kNaturalSize));
@@ -270,7 +281,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
}));
int capture_counter = 101; // arbitrary absolute value
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- capture_counter, kUpdateRect1);
+ capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Update rect for second frame should get passed along.
@@ -283,7 +294,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
ExpectUpdateRectEquals(expected_update_rect, frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect1);
+ ++capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Update rect outside crop region.
@@ -293,7 +304,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
EXPECT_TRUE(frame.update_rect().IsEmpty());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect2);
+ ++capture_counter, kUpdateRect2, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// Update rect partly overlapping crop region.
@@ -306,7 +317,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect3);
+ ++capture_counter, kUpdateRect3, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// When crop origin changes, the whole frame is expected to be marked as
@@ -319,7 +330,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect2, kNaturalSize,
- ++capture_counter, kUpdateRect1);
+ ++capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// When crop size changes, the whole frame is expected to be marked as
@@ -333,15 +344,16 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithCropFromUpstream) {
frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect3, kNaturalSize,
- ++capture_counter, kUpdateRect1);
+ ++capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
}
-TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
+TEST_P(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
const gfx::Size kCodedSize(640, 480);
const gfx::Rect kVisibleRect(100, 50, 200, 80);
const gfx::Size kNaturalSize = gfx::Size(200, 80);
const gfx::Size kScaleToSize = gfx::Size(120, 50);
+ const media::VideoFrame::StorageType storage_type = GetParam();
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_Scale(kNaturalSize, kScaleToSize));
@@ -355,7 +367,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
}));
int capture_counter = 101; // arbitrary absolute value
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- capture_counter, kUpdateRect1);
+ capture_counter, kUpdateRect1, storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
// When scaling is applied and UPDATE_RECT is not empty, we always expect a
@@ -366,7 +378,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
frame.update_rect());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, kUpdateRect1);
+ ++capture_counter, kUpdateRect1, storage_type);
// When UPDATE_RECT is empty, we expect to deliver an empty UpdateRect even if
// scaling is applied.
@@ -375,7 +387,7 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
EXPECT_TRUE(frame.update_rect().IsEmpty());
}));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, gfx::Rect());
+ ++capture_counter, gfx::Rect(), storage_type);
// When UPDATE_RECT is empty, but the scaling has changed, we expect to
// deliver an full UpdateRect.
@@ -388,9 +400,15 @@ TEST_F(WebRtcVideoTrackSourceTest, UpdateRectWithScaling) {
track_source_->SetCustomFrameAdaptationParamsForTesting(
FrameAdaptation_Scale(kNaturalSize, kScaleToSize2));
SendTestFrameWithUpdateRect(kCodedSize, kVisibleRect, kNaturalSize,
- ++capture_counter, gfx::Rect());
+ ++capture_counter, gfx::Rect(), storage_type);
Mock::VerifyAndClearExpectations(&mock_sink_);
}
+INSTANTIATE_TEST_SUITE_P(
+ WebRtcVideoTrackSourceTest,
+ WebRtcVideoTrackSourceTest,
+ testing::Values(media::VideoFrame::STORAGE_OWNED_MEMORY,
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER));
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/prerender.h b/chromium/third_party/blink/renderer/platform/prerender.h
index 753ee9ac0ba..06b32a45f55 100644
--- a/chromium/third_party/blink/renderer/platform/prerender.h
+++ b/chromium/third_party/blink/renderer/platform/prerender.h
@@ -47,8 +47,7 @@ namespace blink {
class PrerenderClient;
-class PLATFORM_EXPORT Prerender final
- : public GarbageCollectedFinalized<Prerender> {
+class PLATFORM_EXPORT Prerender final : public GarbageCollected<Prerender> {
DISALLOW_COPY_AND_ASSIGN(Prerender);
public:
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 0a7b6e1902c..1cdb197f045 100644
--- a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -99,6 +99,14 @@
status: "stable",
},
{
+ name: "AccessibilityExposeARIAAnnotations",
+ status: "experimental",
+ },
+ {
+ name: "AccessibilityExposeDisplayNone",
+ status: "test",
+ },
+ {
name: "AccessibilityObjectModel",
status: "experimental",
},
@@ -134,6 +142,13 @@
status: "experimental",
},
{
+ // Use an aspect ratio from the HTML attributes even when we use sizing
+ // from CSS.
+ // https://github.com/WICG/intrinsicsize-attribute/issues/16
+ name: "AspectRatioFromWidthAndHeight",
+ status: "stable",
+ },
+ {
name: "AsyncClipboard",
status: "stable",
},
@@ -157,12 +172,12 @@
{
name: "AutomaticLazyFrameLoading",
depends_on: ["LazyFrameLoading"],
- status: "experimental",
+ status: "stable",
},
{
name: "AutomaticLazyImageLoading",
depends_on: ["LazyImageLoading"],
- status: "experimental",
+ status: "stable",
},
{
name: "AutomationControlled",
@@ -192,7 +207,7 @@
},
{
name: "Badging",
- origin_trial_feature_name: "Badging",
+ origin_trial_feature_name: "BadgingV2",
status: "experimental",
},
{
@@ -262,9 +277,6 @@
status: "experimental",
},
{
- name: "Canvas2dSwapChain",
- },
- {
name: "CanvasColorManagement",
status: "experimental",
},
@@ -277,17 +289,14 @@
status: "experimental",
},
{
- name: "ClickRetargetting",
+ name: "ClickPointerEvent",
status: "experimental",
},
{
- name: "ClientHintsFeaturePolicy",
+ name: "ClickRetargetting",
status: "experimental",
},
{
- name: "ClientPlaceholdersForServerLoFi",
- },
- {
name: "CompositeAfterPaint",
},
{
@@ -299,6 +308,10 @@
status: "test",
},
{
+ name: "CompressionStreams",
+ status: "experimental",
+ },
+ {
name: "ComputedAccessibilityInfo",
status: "experimental",
},
@@ -312,6 +325,10 @@
status: {"Android": "experimental", "default": "test"},
},
{
+ name: "ContactsManagerAddresses",
+ status: {"Android": "experimental", "default": "test"},
+ },
+ {
name: "ContentIndex",
status: "experimental",
},
@@ -353,10 +370,6 @@
status: "experimental",
},
{
- name: "CSSAltText",
- status: "stable",
- },
- {
name: "CSSBackdropFilter",
status: "stable",
},
@@ -376,12 +389,13 @@
// CSS min(), max() and clamp()
// https://drafts.csswg.org/css-values-4/#comp-func
name: "CSSComparisonFunctions",
- status: "test",
+ status: "stable",
},
{
// Support for CSS content-size property.
// http://tabatkins.github.io/specs/css-content-size/
name: "CSSContentSize",
+ implied_by: ["DisplayLocking"],
status: "experimental",
},
{
@@ -389,9 +403,6 @@
status: "experimental",
},
{
- name: "CSSFontFeatureValues"
- },
- {
name: "CSSFontSizeAdjust",
status: "experimental",
},
@@ -436,6 +447,10 @@
status: "experimental",
},
{
+ name: "CSSOMViewScrollCoordinates",
+ status: "experimental",
+ },
+ {
name: "CSSPaintAPIArguments",
status: "experimental",
depends_on: ["CSSVariables2"],
@@ -495,8 +510,8 @@
status: "stable",
},
{
- name: "CustomUserTiming",
- status: "stable",
+ name: "CustomStatePseudoClass",
+ status: "experimental",
},
{
name: "Database",
@@ -529,6 +544,7 @@
},
{
name: "DisplayLocking",
+ origin_trial_feature_name: "DisplayLocking",
status: "experimental",
},
{
@@ -554,10 +570,8 @@
implied_by: ["FormAssociatedCustomElements"],
},
{
- // https://crbug.com/879270
- name: "ElementTiming",
- origin_trial_feature_name: "ElementTimingImages",
- status: "stable",
+ name: "EmbeddedVTTStylesheets",
+ status: "experimental",
},
{
name: "EncryptedMediaEncryptionSchemeQuery",
@@ -598,8 +612,10 @@
name: "ExperimentalContentSecurityPolicyFeatures",
status: "experimental",
},
- // Enables navigator.scheduling.isInputPending, allowing long-running JS to
- // be able to yield itself when user input is queued (crbug.com/910421).
+ // Enables navigator.scheduling.isInputPending and
+ // navigator.scheduling.isFramePending, allowing long-running JS to
+ // be able to yield itself when user input is queued (crbug.com/910421) or a
+ // display update is scheduled.
{
name: "ExperimentalIsInputPending",
origin_trial_feature_name: "ExperimentalIsInputPending",
@@ -677,13 +693,6 @@
name: "FileSystem",
status: "stable",
},
- // FirstContentfulPaintPlusPlus enables the Largest Text Paint metric, Last
- // Text Paint metric, Largest Image Paint metric and Last Image Paint
- // metric. See also: http://bit.ly/fcp_plus_plus
- {
- name: "FirstContentfulPaintPlusPlus",
- status: "stable",
- },
// Perform style recalc traversal in the flat tree order, including marking
// flat-tree instead of shadow-including ancestors for child dirtiness.
{
@@ -701,6 +710,7 @@
// For simulating Android's overlay fullscreen video in web tests on Linux.
{
name: "ForcedColors",
+ status: "experimental",
},
{
name: "ForceDeferScriptIntervention",
@@ -781,10 +791,6 @@
status: "experimental",
},
{
- name: "IDBTransactionCommit",
- status: "stable",
- },
- {
name: "IdleDetection",
status: "experimental",
},
@@ -802,6 +808,10 @@
settable_from_internals: true,
},
{
+ name: "ImportMaps",
+ implied_by: ["ExperimentalProductivityFeatures", "BuiltInModuleInfra"],
+ },
+ {
name: "InertAttribute",
status: "experimental",
},
@@ -816,6 +826,10 @@
status: "experimental",
},
{
+ name: "IntersectionObserverDocumentScrollingElementRoot",
+ status: "experimental",
+ },
+ {
name: "IntersectionObserverV2",
status: "stable",
},
@@ -835,12 +849,6 @@
name: "IsolatedWorldCSP"
},
{
- // Modifies LayoutShiftTracker to use O(n log n) sweep line algorithm for
- // computing the area of the layout shift region.
- name: "JankTrackingSweepLine",
- status: "stable",
- },
- {
name: "JSONModules",
},
{
@@ -855,19 +863,8 @@
status: "experimental",
},
{
- name: "LargestContentfulPaint",
- status: "stable",
- },
- {
- // Exposes layout shift scores to Javascript. See explainer:
- // http://bit.ly/lsm-explainer.
- name: "LayoutInstabilityAPI",
- origin_trial_feature_name: "LayoutJankAPI",
- status: "stable",
- },
- {
name: "LayoutNG",
- implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFlexBox", "LayoutNGFragmentItem", "LayoutNGLineCache", "EditingNG", "BidiCaretAffinity", "LayoutNGTable"],
+ implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFlexBox", "LayoutNGFragmentItem", "LayoutNGFragmentPaint", "LayoutNGLineCache", "EditingNG", "BidiCaretAffinity", "LayoutNGTable"],
status: "stable",
},
{
@@ -887,6 +884,9 @@
name: "LayoutNGFragmentItem",
},
{
+ name: "LayoutNGFragmentPaint",
+ },
+ {
name: "LayoutNGLineCache",
},
{
@@ -919,13 +919,15 @@
// Enabled by features::kLegacyWindowsDWriteFontFallback;
},
{
- name: "LinkSystemColors"
+ name: "LinkSystemColors",
+ status: "stable",
},
{
- name: "LongTaskV2",
+ name:"ManualSlotting",
+ status:"experimental",
},
{
- name:"ManualSlotting",
+ name:"MeasureMemory",
status:"experimental",
},
{
@@ -972,6 +974,9 @@
name: "MediaEngagementBypassAutoplayPolicies",
},
{
+ name: "MediaQueryNavigationControls",
+ },
+ {
name: "MediaQueryPrefersColorScheme",
status: "stable",
},
@@ -1174,17 +1179,17 @@
settable_from_internals: true,
status: "experimental",
},
- // The following are developer opt-outs and opt-ins for PageLifecycle state
- // transitions. If neither is specified then heuristics will be applied to
- // determine whether the page is eligible.
+ // The following are developer opt-outs and opt-ins for page freezing. If
+ // neither is specified then heuristics will be applied to determine whether
+ // the page is eligible.
{
- name: "PageLifecycleTransitionsOptIn",
- origin_trial_feature_name: "PageLifecycleTransitionsOptIn",
+ name: "PageFreezeOptIn",
+ origin_trial_feature_name: "PageFreezeOptIn",
status: "experimental",
},
{
- name: "PageLifecycleTransitionsOptOut",
- origin_trial_feature_name: "PageLifecycleTransitionsOptOut",
+ name: "PageFreezeOptOut",
+ origin_trial_feature_name: "PageFreezeOptOut",
status: "experimental",
},
{
@@ -1192,11 +1197,6 @@
// Android does not have support for PagePopup
status: {"Android": "", "default": "stable"},
},
- // See: https://docs.google.com/document/d/1IyYJ6bVF7KZq96b_s5NrAzGtVoBXn_LQnya9y4yT3iw/view
- {
- name: "PaintNonFastScrollableRegions",
- status: "stable",
- },
{
name: "PaintUnderInvalidationChecking",
settable_from_internals: true,
@@ -1213,10 +1213,6 @@
name: "PassPaintVisualRectToCompositor",
},
{
- name: "PauseExecutionContextOnBackgroundFreeze",
- status: "stable",
- },
- {
name: "PaymentApp",
status: "experimental",
},
@@ -1225,6 +1221,10 @@
status: "stable",
},
{
+ name: "PaymentHandlerHandlesShippingAndContact",
+ status: "experimental",
+ },
+ {
name: "PaymentMethodChangeEvent",
status: "stable",
},
@@ -1344,10 +1344,6 @@
status: "experimental",
},
{
- name: "RasterInducingScroll",
- status: "experimental",
- },
- {
name: "ReducedReferrerGranularity",
},
{
@@ -1361,26 +1357,22 @@
status: {"Android": "stable", "default": ""},
},
{
- name: "ResourceLoadScheduler",
- status: "experimental",
- },
- {
name: "RestrictAppCacheToSecureContexts",
status: "stable",
},
{
name: "RestrictAutomaticLazyFrameLoadingToDataSaver",
depends_on: ["AutomaticLazyFrameLoading"],
- status: "experimental",
+ status: "stable",
},
{
name: "RestrictAutomaticLazyImageLoadingToDataSaver",
depends_on: ["AutomaticLazyImageLoading"],
- status: "experimental",
+ status: "stable",
},
{
name: "RestrictedWebkitAppearance",
- status: "experimental",
+ status: "stable",
},
{
name: "RtcAudioJitterBufferMaxPackets",
@@ -1403,11 +1395,6 @@
origin_trial_feature_name: "RTCQuicTransport",
status: "experimental",
},
- {
- name: "RtcJitterBufferDelayHint",
- origin_trial_feature_name: "RtcJitterBufferDelayHint",
- status: "experimental",
- },
// Enables the use of the RTCQuicTransport object.
{
name: "RTCQuicTransport",
@@ -1463,11 +1450,6 @@
{
name: "ScriptStreamingOnPreload",
},
- // Serialize and restore scroll anchors.
- {
- name: "ScrollAnchorSerialization",
- status: "test",
- },
{
name: "ScrollCustomization",
},
@@ -1500,7 +1482,7 @@
status: {"Android": "", "default": "experimental"},
},
{
- name: "ServiceWorkerFilterFrozen",
+ name: "ServiceWorkerClientLifecycleState",
status: "experimental",
},
{
@@ -1572,11 +1554,6 @@
status: "experimental",
},
{
- name: "StaleWhileRevalidate",
- origin_trial_feature_name: "StaleWhileRevalidate",
- status: "stable",
- },
- {
// Enabled when blink::features::kStorageAccessAPI is enabled.
name: "StorageAccessAPI",
status: "test",
@@ -1586,10 +1563,6 @@
status: "stable"
},
{
- name: "StreamsNative",
- status: "stable",
- },
- {
name: "SurfaceEmbeddingFeatures",
status: "stable",
},
@@ -1631,7 +1604,6 @@
},
{
name: "TrustedDOMTypes",
- origin_trial_feature_name: "TrustedDOMTypes",
status: "experimental",
},
{
@@ -1682,6 +1654,7 @@
},
{
name: "UseWindowsSystemColors",
+ status: "stable",
},
{
name: "V8IdleTasks",
@@ -1744,7 +1717,7 @@
},
{
name: "WebBluetoothScanning",
- status: "test",
+ status: "experimental",
},
{
name: "WebGL2ComputeContext",
@@ -1757,9 +1730,6 @@
{
name: "WebGLImageChromium",
},
- {
- name: "WebGLSwapChain",
- },
// WebGPU adds a large attack surface area to the GPU process and allows
// running arbitrary programs on the GPU (compute shaders), which may
// perform arbitrary read/writes of GPU memory if not properly sandboxed.
@@ -1774,6 +1744,7 @@
},
{
name: "WebkitBoxLayoutUsesFlexLayout",
+ status: "stable",
},
{
name: "WebNFC",
@@ -1818,19 +1789,28 @@
},
{
name: "WebXR",
- origin_trial_feature_name: "WebXRDeviceM76",
- status: "experimental",
+ status: "stable",
},
{
name: "WebXRAnchors",
// depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
},
{
+ name: "WebXRARDOMOverlay",
+ // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ status: "experimental",
+ },
+ {
name: "WebXRARModule",
- // depends_on: ["WebXR"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ depends_on: ["WebXR"],
status: "experimental",
},
{
+ name: "WebXrGamepadModule",
+ // depends_on: ["WebXR"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
+ status: "stable",
+ },
+ {
name: "WebXRHitTest",
// depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed
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 7c6e34e4179..6812a3a5f3d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -109,6 +109,7 @@ 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",
@@ -165,6 +166,7 @@ blink_platform_sources("scheduler") {
"//services/metrics/public/cpp:ukm_builders",
"//services/metrics/public/mojom",
"//third_party/blink/renderer/platform:make_platform_generated",
+ "//third_party/blink/renderer/platform/instrumentation",
"//third_party/blink/renderer/platform/wtf",
"//v8",
]
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
index 9d66acca505..a42789826bd 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
@@ -40,6 +40,8 @@ include_rules = [
"+base/task/sequence_manager/sequence_manager.h",
"+base/task/sequence_manager/task_queue.h",
"+base/task/sequence_manager/time_domain.h",
+ "+base/task/simple_task_executor.h",
+ "+base/task/task_executor.h",
"+base/task/task_traits.h",
"+base/threading/platform_thread.h",
"+base/threading/sequenced_task_runner_handle.h",
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 74cd66d3634..0413fe7b99a 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h"
#include "base/auto_reset.h"
+#include "base/run_loop.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
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 62f42192fb5..ce590849c50 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
@@ -31,7 +31,7 @@ class DummyFrameScheduler : public FrameScheduler {
PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
- void SetPausedForCooperativeScheduling(Paused) override {}
+ void SetPreemptedForCooperativeScheduling(Preempted) override {}
void SetFrameVisible(bool) override {}
bool IsFrameVisible() const override { return true; }
bool IsPageVisible() const override { return true; }
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/event_loop.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
index abed7cb40f0..77bbf2e3868 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/event_loop.cc
@@ -51,8 +51,8 @@ void EventLoop::Disable() {
loop_enabled_ = false;
for (auto* scheduler : schedulers_) {
- scheduler->SetPausedForCooperativeScheduling(
- FrameOrWorkerScheduler::Paused(true));
+ scheduler->SetPreemptedForCooperativeScheduling(
+ FrameOrWorkerScheduler::Preempted(true));
}
// TODO(keishi): Disable microtaskqueue too.
}
@@ -61,8 +61,8 @@ void EventLoop::Enable() {
loop_enabled_ = true;
for (auto* scheduler : schedulers_) {
- scheduler->SetPausedForCooperativeScheduling(
- FrameOrWorkerScheduler::Paused(false));
+ scheduler->SetPreemptedForCooperativeScheduling(
+ FrameOrWorkerScheduler::Preempted(false));
}
// TODO(keishi): Enable microtaskqueue too.
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
index ebe99ffd349..e971856d539 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
@@ -28,15 +28,14 @@ FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle::
}
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle::
- SchedulingAffectingFeatureHandle(
- SchedulingAffectingFeatureHandle&& other) noexcept
+ SchedulingAffectingFeatureHandle(SchedulingAffectingFeatureHandle&& other)
: feature_(other.feature_), scheduler_(std::move(other.scheduler_)) {
other.scheduler_ = nullptr;
}
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle&
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle::operator=(
- SchedulingAffectingFeatureHandle&& other) noexcept {
+ SchedulingAffectingFeatureHandle&& other) {
feature_ = other.feature_;
policy_ = std::move(other.policy_);
scheduler_ = std::move(other.scheduler_);
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 2c84d706944..fad56ee1a94 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
@@ -103,9 +103,9 @@ TaskHandle::~TaskHandle() {
Cancel();
}
-TaskHandle::TaskHandle(TaskHandle&&) noexcept = default;
+TaskHandle::TaskHandle(TaskHandle&&) = default;
-TaskHandle& TaskHandle::operator=(TaskHandle&& other) noexcept {
+TaskHandle& TaskHandle::operator=(TaskHandle&& other) {
TaskHandle tmp(std::move(other));
runner_.swap(tmp.runner_);
return *this;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
index 78dbcab8ee6..c751d9ccc24 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -40,6 +40,8 @@ void SchedulerHelper::InitDefaultQueues(
DCHECK(sequence_manager_);
sequence_manager_->SetDefaultTaskRunner(default_task_runner_);
+
+ simple_task_executor_.emplace(default_task_runner_);
}
SchedulerHelper::~SchedulerHelper() {
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 c28535f2fc8..3f2267ef8ec 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/simple_task_executor.h"
#include "base/time/tick_clock.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -134,6 +135,7 @@ class PLATFORM_EXPORT SchedulerHelper
Observer* observer_; // NOT OWNED
UkmTaskSampler ukm_task_sampler_;
+ base::Optional<base::SimpleTaskExecutor> simple_task_executor_;
DISALLOW_COPY_AND_ASSIGN(SchedulerHelper);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
index 0a06b0c2740..ceabb45254b 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
@@ -21,6 +21,7 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) {
case Feature::kWebGL:
case Feature::kWebVR:
case Feature::kWebXR:
+ case Feature::kSharedWorker:
return false;
case Feature::kMainResourceHasCacheControlNoStore:
case Feature::kMainResourceHasCacheControlNoCache:
@@ -42,6 +43,7 @@ bool SchedulingPolicy::IsFeatureSticky(SchedulingPolicy::Feature feature) {
case Feature::kRequestedVideoCapturePermission:
case Feature::kRequestedSensorsPermission:
case Feature::kRequestedBackgroundWorkPermission:
+ case Feature::kWebLocks:
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
index 8247a784472..74e6c82b9af 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
@@ -150,6 +150,14 @@ void WebThreadScheduler::DidAnimateForInputOnCompositorThread() {
NOTREACHED();
}
+void WebThreadScheduler::DidScheduleBeginMainFrame() {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::DidRunBeginMainFrame() {
+ NOTREACHED();
+}
+
void WebThreadScheduler::SetRendererHidden(bool hidden) {
NOTREACHED();
}
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 2b9e0ac8e64..fa9a882b29b 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
@@ -55,7 +55,7 @@ QueuePriority CompositorPriorityExperiments::GetCompositorPriority() const {
case Experiment::kVeryHighPriorityForCompositingAlways:
return QueuePriority::kVeryHighPriority;
case Experiment::kVeryHighPriorityForCompositingWhenFast:
- if (compositing_is_fast_) {
+ if (scheduler_->main_thread_compositing_is_fast()) {
return QueuePriority::kVeryHighPriority;
}
return QueuePriority::kNormalPriority;
@@ -71,11 +71,6 @@ QueuePriority CompositorPriorityExperiments::GetCompositorPriority() const {
}
}
-void CompositorPriorityExperiments::SetCompositingIsFast(
- bool compositing_is_fast) {
- compositing_is_fast_ = compositing_is_fast;
-}
-
void CompositorPriorityExperiments::DoPrioritizeCompositingAfterDelay() {
delay_compositor_priority_ = QueuePriority::kVeryHighPriority;
scheduler_->OnCompositorPriorityExperimentUpdateCompositorPriority();
@@ -114,11 +109,6 @@ void CompositorPriorityExperiments::OnTaskCompleted(
if (!queue)
return;
- // Don't change priorities if compositor priority is already set to highest
- // or higher.
- if (current_compositor_priority <= QueuePriority::kHighestPriority)
- return;
-
switch (experiment_) {
case Experiment::kVeryHighPriorityForCompositingAlways:
return;
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 6275859c944..1cb8789fcdf 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
@@ -44,8 +44,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
QueuePriority GetCompositorPriority() const;
- void SetCompositingIsFast(bool compositing_is_fast);
-
void OnTaskCompleted(MainThreadTaskQueue* queue,
QueuePriority current_priority,
MainThreadTaskQueue::TaskTiming* task_timing);
@@ -109,8 +107,6 @@ class PLATFORM_EXPORT CompositorPriorityExperiments {
QueuePriority alternating_compositor_priority_ =
QueuePriority::kVeryHighPriority;
- bool compositing_is_fast_ = false;
-
QueuePriority delay_compositor_priority_ = QueuePriority::kNormalPriority;
CancelableClosureHolder do_prioritize_compositing_after_delay_callback_;
base::TimeDelta prioritize_compositing_after_delay_length_;
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 6be08311154..be332f683dd 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
@@ -185,6 +185,12 @@ FrameSchedulerImpl::FrameSchedulerImpl(
this,
&tracing_controller_,
YesNoStateToString),
+ preempted_for_cooperative_scheduling_(
+ false,
+ "FrameScheduler.PreemptedForCooperativeScheduling",
+ this,
+ &tracing_controller_,
+ YesNoStateToString),
aggressive_throttling_opt_out_count(0),
opted_out_from_aggressive_throttling_(
false,
@@ -829,6 +835,7 @@ void FrameSchedulerImpl::UpdateQueuePolicy(
DCHECK(parent_page_scheduler_);
bool queue_disabled = false;
queue_disabled |= frame_paused_ && queue->CanBePaused();
+ queue_disabled |= preempted_for_cooperative_scheduling_;
// Per-frame freezable task queues will be frozen after 5 mins in background
// on Android, and if the browser freezes the page in the background. They
// will be resumed when the page is visible.
@@ -1147,7 +1154,7 @@ FrameSchedulerImpl::ThrottleableTaskQueueTraits() {
.SetCanBeFrozen(true)
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true);
+ .SetCanRunWhenVirtualTimePaused(true);
}
// static
@@ -1158,7 +1165,7 @@ FrameSchedulerImpl::DeferrableTaskQueueTraits() {
.SetCanBeFrozen(base::FeatureList::IsEnabled(
blink::features::kStopNonTimersInBackground))
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true);
+ .SetCanRunWhenVirtualTimePaused(true);
}
// static
@@ -1168,7 +1175,7 @@ FrameSchedulerImpl::PausableTaskQueueTraits() {
.SetCanBeFrozen(base::FeatureList::IsEnabled(
blink::features::kStopNonTimersInBackground))
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true);
+ .SetCanRunWhenVirtualTimePaused(true);
}
// static
@@ -1182,23 +1189,26 @@ FrameSchedulerImpl::FreezableTaskQueueTraits() {
// static
MainThreadTaskQueue::QueueTraits
FrameSchedulerImpl::UnpausableTaskQueueTraits() {
- return QueueTraits().SetShouldUseVirtualTime(true);
+ return QueueTraits().SetCanRunWhenVirtualTimePaused(true);
}
MainThreadTaskQueue::QueueTraits
FrameSchedulerImpl::ForegroundOnlyTaskQueueTraits() {
return ThrottleableTaskQueueTraits()
.SetCanRunInBackground(false)
- .SetShouldUseVirtualTime(true);
+ .SetCanRunWhenVirtualTimePaused(true);
}
MainThreadTaskQueue::QueueTraits
FrameSchedulerImpl::DoesNotUseVirtualTimeTaskQueueTraits() {
- return QueueTraits().SetShouldUseVirtualTime(false);
+ return QueueTraits().SetCanRunWhenVirtualTimePaused(false);
}
-void FrameSchedulerImpl::SetPausedForCooperativeScheduling(Paused paused) {
- // TODO(keishi): Stop all task queues
+void FrameSchedulerImpl::SetPreemptedForCooperativeScheduling(
+ Preempted preempted) {
+ DCHECK_NE(preempted.value(), preempted_for_cooperative_scheduling_);
+ preempted_for_cooperative_scheduling_ = preempted.value();
+ UpdatePolicy();
}
MainThreadTaskQueue::QueueTraits
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 6d27ae3506a..9f9eef3782e 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
@@ -81,7 +81,7 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
~FrameSchedulerImpl() override;
// FrameOrWorkerScheduler implementation:
- void SetPausedForCooperativeScheduling(Paused) override;
+ void SetPreemptedForCooperativeScheduling(Preempted) override;
// FrameScheduler implementation:
void SetFrameVisible(bool frame_visible) override;
@@ -323,6 +323,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler,
TraceableState<bool, TracingCategoryName::kInfo> subresource_loading_paused_;
StateTracer<TracingCategoryName::kInfo> url_tracer_;
TraceableState<bool, TracingCategoryName::kInfo> task_queues_throttled_;
+ TraceableState<bool, TracingCategoryName::kInfo>
+ preempted_for_cooperative_scheduling_;
// TODO(kraynov): https://crbug.com/827113
// Trace the count of aggressive throttling opt outs.
int aggressive_throttling_opt_out_count;
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 1ffe34a84b9..891ed7a9c6e 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
@@ -466,6 +466,30 @@ TEST_F(FrameSchedulerImplTest, PauseAndResume) {
EXPECT_EQ(5, counter);
}
+TEST_F(FrameSchedulerImplTest, PauseAndResumeForCooperativeScheduling) {
+ EXPECT_TRUE(LoadingTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(ThrottleableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(DeferrableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(PausableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(UnpausableTaskQueue()->IsQueueEnabled());
+
+ frame_scheduler_->SetPreemptedForCooperativeScheduling(
+ FrameOrWorkerScheduler::Preempted(true));
+ EXPECT_FALSE(LoadingTaskQueue()->IsQueueEnabled());
+ EXPECT_FALSE(ThrottleableTaskQueue()->IsQueueEnabled());
+ EXPECT_FALSE(DeferrableTaskQueue()->IsQueueEnabled());
+ EXPECT_FALSE(PausableTaskQueue()->IsQueueEnabled());
+ EXPECT_FALSE(UnpausableTaskQueue()->IsQueueEnabled());
+
+ frame_scheduler_->SetPreemptedForCooperativeScheduling(
+ FrameOrWorkerScheduler::Preempted(false));
+ EXPECT_TRUE(LoadingTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(ThrottleableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(DeferrableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(PausableTaskQueue()->IsQueueEnabled());
+ EXPECT_TRUE(UnpausableTaskQueue()->IsQueueEnabled());
+}
+
TEST_F(FrameSchedulerImplTest, FreezeForegroundOnlyTasks) {
int counter = 0;
ForegroundOnlyTaskQueue()->task_runner()->PostTask(
@@ -1792,37 +1816,37 @@ TEST_F(ThrottleableAndFreezableTaskTypesTest, QueueTraitsFromFieldTrialParams) {
.SetCanBeThrottled(true)
.SetCanBeFrozen(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kDOMManipulation);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeFrozen(true)
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
// Test some task types that were not configured through field trial
// parameters.
task_queue = GetTaskQueue(TaskType::kInternalIPC);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
}
@@ -1900,35 +1924,35 @@ TEST_F(ThrottleableOnlyTaskTypesTest, QueueTraitsFromFieldTrialParams) {
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeThrottled(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kMediaElementEvent);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kDatabaseAccess);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kDOMManipulation);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
// Test some task types that were not configured through field trial
// parameters.
task_queue = GetTaskQueue(TaskType::kInternalIPC);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
task_queue = GetTaskQueue(TaskType::kMiscPlatformAPI);
EXPECT_EQ(task_queue->GetQueueTraits(), MainThreadTaskQueue::QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
}
class FrameSchedulerImplDatabaseAccessWithoutHighPriority
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 15b978b7ee7..710f3d595b9 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
@@ -129,10 +129,8 @@ void FrameTaskQueueController::TaskQueueCreated(
const scoped_refptr<MainThreadTaskQueue>& task_queue) {
DCHECK(task_queue);
- std::unique_ptr<QueueEnabledVoter> voter;
- // Only create a voter for queues that can be disabled.
- if (task_queue->CanBePaused() || task_queue->CanBeFrozen())
- voter = task_queue->CreateQueueEnabledVoter();
+ std::unique_ptr<QueueEnabledVoter> voter =
+ task_queue->CreateQueueEnabledVoter();
delegate_->OnTaskQueueCreated(task_queue.get(), voter.get());
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 67dbe5b4038..c1542650192 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
@@ -95,7 +95,7 @@ class FrameTaskQueueControllerTest : public testing::Test,
.SetCanBeFrozen(true)
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
}
scoped_refptr<MainThreadTaskQueue> GetTaskQueue(
@@ -144,7 +144,7 @@ TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) {
.SetCanBeDeferred(true)
.SetCanBeFrozen(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
EXPECT_FALSE(all_task_queues.Contains(task_queue));
all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
@@ -152,20 +152,20 @@ TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) {
task_queue = GetTaskQueue(QueueTraits()
.SetCanBeDeferred(true)
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
EXPECT_FALSE(all_task_queues.Contains(task_queue));
all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
task_queue = GetTaskQueue(QueueTraits()
.SetCanBePaused(true)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
EXPECT_FALSE(all_task_queues.Contains(task_queue));
all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
task_queue = GetTaskQueue(QueueTraits()
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
EXPECT_FALSE(all_task_queues.Contains(task_queue));
all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
@@ -197,16 +197,7 @@ TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) {
EXPECT_FALSE(it == all_task_queues.end());
EXPECT_EQ(it->value, QueueCheckResult::kDidNotSeeQueue);
all_task_queues.Set(task_queue_ptr, QueueCheckResult::kDidSeeQueue);
- if (task_queue_ptr->queue_type() ==
- MainThreadTaskQueue::QueueType::kFrameLoading ||
- task_queue_ptr->queue_type() ==
- MainThreadTaskQueue::QueueType::kFrameLoadingControl) {
- EXPECT_NE(voter, nullptr);
- } else if (task_queue_ptr->GetQueueTraits().can_be_paused) {
- EXPECT_NE(voter, nullptr);
- } else {
- EXPECT_EQ(voter, nullptr);
- }
+ EXPECT_NE(voter, nullptr);
}
}
@@ -368,7 +359,7 @@ TEST_P(TaskQueueCreationFromQueueTraitsTest,
.SetCanBeFrozen(!!(i & 1 << 2))
.SetCanBePaused(!!(i & 1 << 3))
.SetCanRunInBackground(!!(i & 1 << 4))
- .SetShouldUseVirtualTime(!!(i & 1 << 5))
+ .SetCanRunWhenVirtualTimePaused(!!(i & 1 << 5))
.SetPrioritisationType(prioritisation_type);
scoped_refptr<MainThreadTaskQueue> task_queue =
frame_task_queue_controller_->GetTaskQueue(queue_traits);
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 76d1fbbd966..2dc7430c95a 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
@@ -485,7 +485,8 @@ MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
nested_runloop(false),
compositing_experiment(main_thread_scheduler_impl),
should_prioritize_compositing(false),
- compositor_priority_experiments(main_thread_scheduler_impl) {}
+ compositor_priority_experiments(main_thread_scheduler_impl),
+ main_thread_compositing_is_fast(false) {}
MainThreadSchedulerImpl::MainThreadOnly::~MainThreadOnly() = default;
@@ -543,7 +544,12 @@ MainThreadSchedulerImpl::AnyThread::AnyThread(
"Scheduler.HaveSeenInputSinceNavigation",
main_thread_scheduler_impl,
&main_thread_scheduler_impl->tracing_controller_,
- YesNoStateToString) {}
+ YesNoStateToString),
+ begin_main_frame_scheduled_count(
+ 0,
+ "Scheduler.BeginMainFrameScheduledCount",
+ main_thread_scheduler_impl,
+ &main_thread_scheduler_impl->tracing_controller_) {}
MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
high_priority_input =
@@ -786,7 +792,7 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTimerTaskQueue(
.SetCanBeDeferred(true)
.SetCanBeThrottled(true)
.SetFrameScheduler(frame_scheduler)
- .SetShouldUseVirtualTime(true));
+ .SetCanRunWhenVirtualTimePaused(true));
}
std::unique_ptr<WebRenderWidgetSchedulingState>
@@ -1132,6 +1138,16 @@ void MainThreadSchedulerImpl::DidAnimateForInputOnCompositorThread() {
base::TimeDelta::FromMilliseconds(kFlingEscalationLimitMillis);
}
+void MainThreadSchedulerImpl::DidScheduleBeginMainFrame() {
+ base::AutoLock lock(any_thread_lock_);
+ any_thread().begin_main_frame_scheduled_count += 1;
+}
+
+void MainThreadSchedulerImpl::DidRunBeginMainFrame() {
+ base::AutoLock lock(any_thread_lock_);
+ any_thread().begin_main_frame_scheduled_count -= 1;
+}
+
void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
const blink::WebInputEvent& web_input_event,
InputEventState input_event_state) {
@@ -1431,7 +1447,7 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
// Avoid prioritizing main thread compositing (e.g., rAF) if it is extremely
// slow, because that can cause starvation in other task sources.
- bool main_thread_compositing_is_fast =
+ main_thread_only().main_thread_compositing_is_fast =
main_thread_only().idle_time_estimator.GetExpectedIdleDuration(
main_thread_only().compositor_frame_interval) >
main_thread_only().compositor_frame_interval *
@@ -1443,53 +1459,24 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
switch (new_policy.use_case()) {
case UseCase::kCompositorGesture:
- if (main_thread_only().blocking_input_expected_soon) {
+ if (main_thread_only().blocking_input_expected_soon)
new_policy.rail_mode() = RAILMode::kResponse;
- new_policy.compositor_priority() =
- TaskQueue::QueuePriority::kHighestPriority;
- } else {
- // What we really want to do is priorize loading tasks, but that doesn't
- // seem to be safe. Instead we do that by proxy by deprioritizing
- // compositor tasks. This should be safe since we've already gone to the
- // pain of fixing ordering issues with them.
- new_policy.compositor_priority() =
- TaskQueue::QueuePriority::kLowPriority;
- }
break;
case UseCase::kSynchronizedGesture:
- new_policy.compositor_priority() = main_thread_compositing_is_fast
- ? TaskQueue::kHighestPriority
- : TaskQueue::kNormalPriority;
if (main_thread_only().blocking_input_expected_soon)
new_policy.rail_mode() = RAILMode::kResponse;
break;
case UseCase::kMainThreadCustomInputHandling:
- // In main thread input handling scenarios we don't have perfect knowledge
- // about which things we should be prioritizing, so we don't attempt to
- // block expensive tasks because we don't know whether they were integral
- // to the page's functionality or not.
- new_policy.compositor_priority() =
- main_thread_compositing_is_fast
- ? TaskQueue::QueuePriority::kHighestPriority
- : TaskQueue::QueuePriority::kNormalPriority;
break;
case UseCase::kMainThreadGesture:
- // A main thread gesture is for example a scroll gesture which is handled
- // by the main thread. Since we know the established gesture type, we can
- // be a little more aggressive about prioritizing compositing and input
- // handling over other tasks.
- new_policy.compositor_priority() =
- TaskQueue::QueuePriority::kHighestPriority;
if (main_thread_only().blocking_input_expected_soon)
new_policy.rail_mode() = RAILMode::kResponse;
break;
case UseCase::kTouchstart:
- new_policy.compositor_priority() =
- TaskQueue::QueuePriority::kHighestPriority;
new_policy.rail_mode() = RAILMode::kResponse;
new_policy.loading_queue_policy().is_deferred = true;
new_policy.timer_queue_policy().is_deferred = true;
@@ -1506,12 +1493,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
case UseCase::kEarlyLoading:
new_policy.rail_mode() = RAILMode::kLoad;
- if (scheduling_settings_
- .prioritize_compositing_and_loading_during_early_loading) {
- new_policy.compositor_priority() =
- base::sequence_manager::TaskQueue::QueuePriority::kHighPriority;
- new_policy.should_prioritize_loading_with_compositing() = true;
- }
break;
case UseCase::kLoading:
@@ -1523,15 +1504,27 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
NOTREACHED();
}
- // Do not reset compositor priority if set to highest or higher.
- if (new_policy.compositor_priority() >
- TaskQueue::QueuePriority::kHighestPriority &&
- main_thread_only().compositor_priority_experiments.IsExperimentActive()) {
- main_thread_only().compositor_priority_experiments.SetCompositingIsFast(
- main_thread_compositing_is_fast);
+ if (main_thread_only().should_prioritize_compositing) {
new_policy.compositor_priority() =
main_thread_only()
- .compositor_priority_experiments.GetCompositorPriority();
+ .compositing_experiment.GetIncreasedCompositingPriority();
+ } else if (scheduling_settings_
+ .prioritize_compositing_and_loading_during_early_loading &&
+ current_use_case() == UseCase::kEarlyLoading) {
+ new_policy.compositor_priority() =
+ base::sequence_manager::TaskQueue::QueuePriority::kHighPriority;
+ new_policy.should_prioritize_loading_with_compositing() = true;
+ } else {
+ base::Optional<TaskQueue::QueuePriority> computed_compositor_priority =
+ ComputeCompositorPriorityFromUseCase();
+ if (computed_compositor_priority) {
+ new_policy.compositor_priority() = computed_compositor_priority.value();
+ } else if (main_thread_only()
+ .compositor_priority_experiments.IsExperimentActive()) {
+ new_policy.compositor_priority() =
+ main_thread_only()
+ .compositor_priority_experiments.GetCompositorPriority();
+ }
}
// TODO(skyostil): Add an idle state for foreground tabs too.
@@ -1555,12 +1548,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
new_policy.should_disable_throttling() = main_thread_only().use_virtual_time;
- if (main_thread_only().should_prioritize_compositing) {
- new_policy.compositor_priority() =
- main_thread_only()
- .compositing_experiment.GetIncreasedCompositingPriority();
- }
-
// Tracing is done before the early out check, because it's quite possible we
// will otherwise miss this information in traces.
CreateTraceEventObjectSnapshotLocked();
@@ -2312,6 +2299,11 @@ PendingUserInputInfo MainThreadSchedulerImpl::GetPendingUserInputInfo() const {
return any_thread().pending_input_monitor.Info();
}
+bool MainThreadSchedulerImpl::IsBeginMainFrameScheduled() const {
+ base::AutoLock lock(any_thread_lock_);
+ return any_thread().begin_main_frame_scheduled_count.value() > 0;
+}
+
void MainThreadSchedulerImpl::RunIdleTask(Thread::IdleTask task,
base::TimeTicks deadline) {
std::move(task).Run(deadline);
@@ -2775,7 +2767,49 @@ void MainThreadSchedulerImpl::SetShouldPrioritizeCompositing(
void MainThreadSchedulerImpl::
OnCompositorPriorityExperimentUpdateCompositorPriority() {
- UpdatePolicy();
+ if (!ComputeCompositorPriorityFromUseCase())
+ UpdatePolicy();
+}
+
+base::Optional<TaskQueue::QueuePriority>
+MainThreadSchedulerImpl::ComputeCompositorPriorityFromUseCase() const {
+ switch (current_use_case()) {
+ case UseCase::kCompositorGesture:
+ if (main_thread_only().blocking_input_expected_soon)
+ return TaskQueue::QueuePriority::kHighestPriority;
+ // What we really want to do is priorize loading tasks, but that doesn't
+ // seem to be safe. Instead we do that by proxy by deprioritizing
+ // compositor tasks. This should be safe since we've already gone to the
+ // pain of fixing ordering issues with them.
+ return TaskQueue::QueuePriority::kLowPriority;
+
+ case UseCase::kSynchronizedGesture:
+ case UseCase::kMainThreadCustomInputHandling:
+ // In main thread input handling use case we don't have perfect knowledge
+ // about which things we should be prioritizing, so we don't attempt to
+ // block expensive tasks because we don't know whether they were integral
+ // to the page's functionality or not.
+ if (main_thread_only().main_thread_compositing_is_fast)
+ return TaskQueue::QueuePriority::kHighestPriority;
+ return base::nullopt;
+
+ case UseCase::kMainThreadGesture:
+ case UseCase::kTouchstart:
+ // A main thread gesture is for example a scroll gesture which is handled
+ // by the main thread. Since we know the established gesture type, we can
+ // be a little more aggressive about prioritizing compositing and input
+ // handling over other tasks.
+ return TaskQueue::QueuePriority::kHighestPriority;
+
+ case UseCase::kNone:
+ case UseCase::kEarlyLoading:
+ case UseCase::kLoading:
+ return base::nullopt;
+
+ default:
+ NOTREACHED();
+ return base::nullopt;
+ }
}
void MainThreadSchedulerImpl::OnSafepointEntered() {
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 6b2b35e5f25..968935ee12b 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
@@ -191,6 +191,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void DidHandleInputEventOnMainThread(const WebInputEvent& web_input_event,
WebInputEventResult result) override;
void DidAnimateForInputOnCompositorThread() override;
+ void DidScheduleBeginMainFrame() override;
+ void DidRunBeginMainFrame() override;
void SetRendererHidden(bool hidden) override;
void SetRendererBackgrounded(bool backgrounded) override;
void SetSchedulerKeepActive(bool keep_active) override;
@@ -217,6 +219,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
const char* name,
WebScopedVirtualTimePauser::VirtualTaskDuration duration) override;
PendingUserInputInfo GetPendingUserInputInfo() const override;
+ bool IsBeginMainFrameScheduled() const override;
// ThreadScheduler implementation:
void PostIdleTask(const base::Location&, Thread::IdleTask) override;
@@ -424,6 +427,10 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
.current_policy.should_prioritize_loading_with_compositing();
}
+ bool main_thread_compositing_is_fast() const {
+ return main_thread_only().main_thread_compositing_is_fast;
+ }
+
protected:
scoped_refptr<MainThreadTaskQueue> ControlTaskQueue();
scoped_refptr<MainThreadTaskQueue> DefaultTaskQueue();
@@ -739,6 +746,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// trigger a priority update.
bool ShouldUpdateTaskQueuePriorities(Policy new_policy) const;
+ // Computes the priority for compositing based on the current use case.
+ // Returns nullopt if the use case does not need to set the priority.
+ base::Optional<TaskQueue::QueuePriority>
+ ComputeCompositorPriorityFromUseCase() const;
+
static void RunIdleTask(Thread::IdleTask, base::TimeTicks deadline);
// Probabilistically record all task metadata for the current task.
@@ -932,6 +944,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// Compositing priority experiments (crbug.com/966177).
CompositorPriorityExperiments compositor_priority_experiments;
+
+ bool main_thread_compositing_is_fast;
};
struct AnyThread {
@@ -958,6 +972,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
waiting_for_meaningful_paint;
TraceableState<bool, TracingCategoryName::kInfo>
have_seen_input_since_navigation;
+ TraceableCounter<uint32_t, TracingCategoryName::kInfo>
+ begin_main_frame_scheduled_count;
};
struct CompositorThreadOnly {
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 6d71f8b0b1a..ae4606816ef 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
@@ -14,8 +14,10 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/task/sequence_manager/test/fake_task.h"
#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/task_executor.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -45,6 +47,7 @@ namespace scheduler {
namespace main_thread_scheduler_impl_unittest {
using testing::Mock;
+using testing::NotNull;
using InputEventState = WebThreadScheduler::InputEventState;
using base::sequence_manager::FakeTask;
using base::sequence_manager::FakeTaskTiming;
@@ -2106,6 +2109,32 @@ TEST_P(MainThreadSchedulerImplTest,
EXPECT_FALSE(BlockingInputExpectedSoon());
}
+TEST_P(MainThreadSchedulerImplTest,
+ GetTaskExecutorForCurrentThreadInPostedTask) {
+ base::TaskExecutor* task_executor = base::GetTaskExecutorForCurrentThread();
+ EXPECT_THAT(task_executor, NotNull());
+
+ base::RunLoop run_loop;
+
+ default_task_runner_->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ EXPECT_EQ(base::GetTaskExecutorForCurrentThread(), task_executor);
+ run_loop.Quit();
+ }));
+
+ run_loop.Run();
+}
+
+TEST_P(MainThreadSchedulerImplTest, CurrentThread) {
+ EXPECT_EQ(scheduler_->DeprecatedDefaultTaskRunner(),
+ base::CreateSingleThreadTaskRunner({base::CurrentThread()}));
+
+ // base::TaskPriority is currently ignored in blink.
+ EXPECT_EQ(scheduler_->DeprecatedDefaultTaskRunner(),
+ base::CreateSingleThreadTaskRunner(
+ {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}));
+}
+
class MainThreadSchedulerImplWithMessageLoopTest
: public MainThreadSchedulerImplTest {
public:
@@ -3239,7 +3268,7 @@ TEST_P(MainThreadSchedulerImplTest, VirtualTimeWithOneQueueWithoutVirtualTime) {
task_queues.push_back(scheduler_->NewTaskQueue(
MainThreadTaskQueue::QueueCreationParams(
MainThreadTaskQueue::QueueType::kFrameThrottleable)
- .SetShouldUseVirtualTime(i != 42)));
+ .SetCanRunWhenVirtualTimePaused(i != 42)));
}
// This should install a fence on all queues with virtual time.
@@ -3653,6 +3682,21 @@ TEST_P(MainThreadSchedulerImplTest, MicrotaskCheckpointTiming) {
observer.result().front().second);
}
+TEST_P(MainThreadSchedulerImplTest, IsBeginMainFrameScheduled) {
+ EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled());
+ scheduler_->DidScheduleBeginMainFrame();
+ EXPECT_TRUE(scheduler_->IsBeginMainFrameScheduled());
+ scheduler_->DidRunBeginMainFrame();
+ EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled());
+ scheduler_->DidScheduleBeginMainFrame();
+ scheduler_->DidScheduleBeginMainFrame();
+ EXPECT_TRUE(scheduler_->IsBeginMainFrameScheduled());
+ scheduler_->DidRunBeginMainFrame();
+ EXPECT_TRUE(scheduler_->IsBeginMainFrameScheduled());
+ scheduler_->DidRunBeginMainFrame();
+ EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled());
+}
+
class VeryHighPriorityForCompositingAlwaysExperimentTest
: public MainThreadSchedulerImplTest {
public:
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 06c4cf14b5f..4348ecfccf9 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
@@ -118,7 +118,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
can_be_paused(false),
can_be_frozen(false),
can_run_in_background(true),
- should_use_virtual_time(false) {}
+ can_run_when_virtual_time_paused(false) {}
// Separate enum class for handling prioritisation decisions in task queues.
enum class PrioritisationType {
@@ -170,8 +170,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue
return *this;
}
- QueueTraits SetShouldUseVirtualTime(bool value) {
- should_use_virtual_time = value;
+ QueueTraits SetCanRunWhenVirtualTimePaused(bool value) {
+ can_run_when_virtual_time_paused = value;
return *this;
}
@@ -186,7 +186,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
can_be_paused == other.can_be_paused &&
can_be_frozen == other.can_be_frozen &&
can_run_in_background == other.can_run_in_background &&
- should_use_virtual_time == other.should_use_virtual_time &&
+ can_run_when_virtual_time_paused == other.can_run_when_virtual_time_paused &&
prioritisation_type == other.prioritisation_type;
}
@@ -201,7 +201,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
key |= can_be_paused << (offset++);
key |= can_be_frozen << (offset++);
key |= can_run_in_background << (offset++);
- key |= should_use_virtual_time << (offset++);
+ key |= can_run_when_virtual_time_paused << (offset++);
key |= static_cast<int>(prioritisation_type) << offset;
offset += kPrioritisationTypeWidthBits;
return key;
@@ -212,7 +212,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
bool can_be_paused : 1;
bool can_be_frozen : 1;
bool can_run_in_background : 1;
- bool should_use_virtual_time : 1;
+ bool can_run_when_virtual_time_paused : 1;
PrioritisationType prioritisation_type = PrioritisationType::kRegular;
};
@@ -273,8 +273,8 @@ class PLATFORM_EXPORT MainThreadTaskQueue
return *this;
}
- QueueCreationParams SetShouldUseVirtualTime(bool value) {
- queue_traits = queue_traits.SetShouldUseVirtualTime(value);
+ QueueCreationParams SetCanRunWhenVirtualTimePaused(bool value) {
+ queue_traits = queue_traits.SetCanRunWhenVirtualTimePaused(value);
ApplyQueueTraitsToSpec();
return *this;
}
@@ -346,7 +346,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
}
bool ShouldUseVirtualTime() const {
- return queue_traits_.should_use_virtual_time;
+ return queue_traits_.can_run_when_virtual_time_paused;
}
bool FreezeWhenKeepActive() const { return freeze_when_keep_active_; }
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.cc
new file mode 100644
index 00000000000..c3c98447ec4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scheduling_priority.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/scheduler/public/web_scheduling_priority.h"
+
+namespace blink {
+
+namespace {
+
+const AtomicString& ImmediatePriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, immediate_priority, ("immediate"));
+ return immediate_priority;
+}
+
+const AtomicString& HighPriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, high_priority, ("high"));
+ return high_priority;
+}
+
+const AtomicString& DefaultPriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, default_priority, ("default"));
+ return default_priority;
+}
+
+const AtomicString& LowPriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, low_priority, ("low"));
+ return low_priority;
+}
+
+const AtomicString& IdlePriorityKeyword() {
+ DEFINE_STATIC_LOCAL(const AtomicString, idle_priority, ("idle"));
+ return idle_priority;
+}
+
+} // namespace
+
+AtomicString WebSchedulingPriorityToString(WebSchedulingPriority priority) {
+ switch (priority) {
+ case WebSchedulingPriority::kImmediatePriority:
+ return ImmediatePriorityKeyword();
+ case WebSchedulingPriority::kHighPriority:
+ return HighPriorityKeyword();
+ case WebSchedulingPriority::kDefaultPriority:
+ return DefaultPriorityKeyword();
+ case WebSchedulingPriority::kLowPriority:
+ return LowPriorityKeyword();
+ case WebSchedulingPriority::kIdlePriority:
+ return IdlePriorityKeyword();
+ }
+
+ NOTREACHED();
+ return g_empty_atom;
+}
+
+WebSchedulingPriority WebSchedulingPriorityFromString(
+ const AtomicString& priority) {
+ if (priority == ImmediatePriorityKeyword())
+ return WebSchedulingPriority::kImmediatePriority;
+ if (priority == HighPriorityKeyword())
+ return WebSchedulingPriority::kHighPriority;
+ if (priority == DefaultPriorityKeyword())
+ return WebSchedulingPriority::kDefaultPriority;
+ if (priority == LowPriorityKeyword())
+ return WebSchedulingPriority::kLowPriority;
+ if (priority == IdlePriorityKeyword())
+ return WebSchedulingPriority::kIdlePriority;
+
+ NOTREACHED();
+ return WebSchedulingPriority::kDefaultPriority;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scoped_virtual_time_pauser.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scoped_virtual_time_pauser.cc
index f55730a8604..b64ec9d8aa6 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scoped_virtual_time_pauser.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_scoped_virtual_time_pauser.cc
@@ -28,7 +28,7 @@ WebScopedVirtualTimePauser::~WebScopedVirtualTimePauser() {
}
WebScopedVirtualTimePauser::WebScopedVirtualTimePauser(
- WebScopedVirtualTimePauser&& other) noexcept {
+ WebScopedVirtualTimePauser&& other) {
virtual_time_when_paused_ = other.virtual_time_when_paused_;
paused_ = other.paused_;
duration_ = other.duration_;
@@ -39,7 +39,7 @@ WebScopedVirtualTimePauser::WebScopedVirtualTimePauser(
}
WebScopedVirtualTimePauser& WebScopedVirtualTimePauser::operator=(
- WebScopedVirtualTimePauser&& other) noexcept {
+ WebScopedVirtualTimePauser&& other) {
if (scheduler_ && paused_)
DecrementVirtualTimePauseCount();
virtual_time_when_paused_ = other.virtual_time_when_paused_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/public/DEPS
new file mode 100644
index 00000000000..1361ae437f2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/DEPS
@@ -0,0 +1,5 @@
+specific_include_rules = {
+ "thread.h": [
+ "+base/task/task_observer.h",
+ ]
+} \ No newline at end of file
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 56915ee4c0d..3ded554b191 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
@@ -57,12 +57,11 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
public:
SchedulingAffectingFeatureHandle() = default;
- SchedulingAffectingFeatureHandle(
- SchedulingAffectingFeatureHandle&&) noexcept;
+ SchedulingAffectingFeatureHandle(SchedulingAffectingFeatureHandle&&);
inline ~SchedulingAffectingFeatureHandle() { reset(); }
SchedulingAffectingFeatureHandle& operator=(
- SchedulingAffectingFeatureHandle&&) noexcept;
+ SchedulingAffectingFeatureHandle&&);
inline void reset() {
if (scheduler_)
@@ -86,9 +85,9 @@ class PLATFORM_EXPORT FrameOrWorkerScheduler {
virtual ~FrameOrWorkerScheduler();
- using Paused = util::StrongAlias<class PausedTag, bool>;
+ using Preempted = util::StrongAlias<class PreemptedTag, bool>;
// Stops any tasks from running while we yield and run a nested loop.
- virtual void SetPausedForCooperativeScheduling(Paused) = 0;
+ virtual void SetPreemptedForCooperativeScheduling(Preempted) = 0;
// Notifies scheduler that this execution context has started using a feature
// which impacts scheduling decisions.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h
index 38cbf63ac87..ae66c73c336 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h
@@ -28,8 +28,8 @@ class PLATFORM_EXPORT TaskHandle {
TaskHandle();
~TaskHandle();
- TaskHandle(TaskHandle&&) noexcept;
- TaskHandle& operator=(TaskHandle&&) noexcept;
+ TaskHandle(TaskHandle&&);
+ TaskHandle& operator=(TaskHandle&&);
// Returns true if the task will run later. Returns false if the task is
// cancelled or the task is run already.
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 9926c72207c..d02598fed23 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread.h
@@ -29,6 +29,7 @@
#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"
#include "third_party/blink/public/platform/web_thread_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
index 182fe536e24..9eb6426a100 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
@@ -131,6 +131,11 @@ class PLATFORM_EXPORT ThreadScheduler {
return scheduler::PendingUserInputInfo();
}
+ // Indicates that a BeginMainFrame task has been scheduled to run on the main
+ // thread. Note that this is inherently racy, as it will be affected by code
+ // running on the compositor thread.
+ virtual bool IsBeginMainFrameScheduled() const { return false; }
+
// Associates |isolate| to the scheduler.
virtual void SetV8Isolate(v8::Isolate* isolate) = 0;
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 1244640d80c..fde66f54035 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
@@ -5,6 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WEB_SCHEDULING_PRIORITY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WEB_SCHEDULING_PRIORITY_H_
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
namespace blink {
// Priorities for the experimental scheduling API (see
@@ -19,6 +22,11 @@ enum class WebSchedulingPriority {
kLastPriority = kIdlePriority
};
+PLATFORM_EXPORT AtomicString
+ WebSchedulingPriorityToString(WebSchedulingPriority);
+PLATFORM_EXPORT WebSchedulingPriority
+WebSchedulingPriorityFromString(const AtomicString&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WEB_SCHEDULING_PRIORITY_H_
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 39922c6af2b..c4221032c66 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
@@ -68,7 +68,7 @@ class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
const SchedulingPolicy& policy) override;
// FrameOrWorkerScheduler implementation:
- void SetPausedForCooperativeScheduling(Paused) override {}
+ void SetPreemptedForCooperativeScheduling(Preempted) override {}
protected:
scoped_refptr<NonMainThreadTaskQueue> ThrottleableTaskQueue();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
index 2c322949f74..f20f940d56e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
@@ -9,6 +9,7 @@ specific_include_rules = {
"worker_thread.cc": [
"+base/message_loop/message_pump_type.h",
"+third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h",
+ "+third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h",
"+third_party/blink/renderer/platform/heap/gc_task_runner.h",
],
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
index f55ef03fc71..ec5bb5a5c27 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.cc
@@ -18,6 +18,7 @@
#include "base/task/sequence_manager/task_queue.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.h"
#include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.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"
@@ -124,8 +125,11 @@ void WorkerThread::SimpleThreadImpl::WaitForInit() {
}
WorkerThread::GCSupport::GCSupport(WorkerThread* thread) {
- ThreadState::AttachCurrentThread();
+ ThreadState* thread_state = ThreadState::AttachCurrentThread();
gc_task_runner_ = std::make_unique<GCTaskRunner>(thread);
+ blink_gc_memory_dump_provider_ = std::make_unique<BlinkGCMemoryDumpProvider>(
+ thread_state, base::ThreadTaskRunnerHandle::Get(),
+ BlinkGCMemoryDumpProvider::HeapType::kBlinkWorkerThread);
}
WorkerThread::GCSupport::~GCSupport() {
@@ -134,6 +138,7 @@ WorkerThread::GCSupport::~GCSupport() {
#endif
// Ensure no posted tasks will run from this point on.
gc_task_runner_.reset();
+ blink_gc_memory_dump_provider_.reset();
ThreadState::DetachCurrentThread();
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
index 53b5364590f..108f1becf32 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread.h
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
namespace blink {
+class BlinkGCMemoryDumpProvider;
class ThreadScheduler;
}
@@ -136,6 +137,7 @@ class PLATFORM_EXPORT WorkerThread : public Thread {
private:
std::unique_ptr<GCTaskRunner> gc_task_runner_;
+ std::unique_ptr<BlinkGCMemoryDumpProvider> blink_gc_memory_dump_provider_;
};
std::unique_ptr<SimpleThreadImpl> thread_;
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 755a07c9d56..c394f642660 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
@@ -8,6 +8,7 @@
#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"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
@@ -161,6 +162,13 @@ TEST_F(WorkerThreadTest, TestShutdown) {
thread_.reset();
}
+TEST_F(WorkerThreadTest, GetTaskExecutorForCurrentThreadInPostedTask) {
+ RunOnWorkerThread(FROM_HERE, base::BindOnce([]() {
+ EXPECT_THAT(base::GetTaskExecutorForCurrentThread(),
+ testing::NotNull());
+ }));
+}
+
} // namespace worker_thread_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/DEPS b/chromium/third_party/blink/renderer/platform/testing/DEPS
index 3d295859227..ad1509f9392 100644
--- a/chromium/third_party/blink/renderer/platform/testing/DEPS
+++ b/chromium/third_party/blink/renderer/platform/testing/DEPS
@@ -50,4 +50,10 @@ specific_include_rules = {
'testing_platform_support_with_mock_scheduler\.cc': [
"+base/task/sequence_manager/test/sequence_manager_for_test.h",
],
+ "video_frame_utils\.cc": [
+ "+media/video/fake_gpu_memory_buffer.h",
+ ],
+ "video_frame_utils\.h": [
+ "+media/base/video_frame.h",
+ ],
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
index ef7d0b5eeb9..1e40f8af786 100644
--- a/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -43,7 +43,7 @@ class TestFontSelector : public FontSelector {
font_description.IsSyntheticBold(),
font_description.IsSyntheticItalic(),
font_description.GetFontSelectionRequest(), normal_capabilities,
- font_description.Orientation());
+ font_description.FontOpticalSizing(), font_description.Orientation());
return SimpleFontData::Create(platform_data, CustomFontData::Create());
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
index fb5b973bdc5..d125cb3038b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
+++ b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -15,27 +15,19 @@ enum {
kCompositeAfterPaint = 1 << 0,
kUnderInvalidationChecking = 1 << 1,
kFastBorderRadius = 1 << 2,
- kPaintNonFastScrollableRegions = 1 << 3,
};
class PaintTestConfigurations
: public testing::WithParamInterface<unsigned>,
private ScopedCompositeAfterPaintForTest,
private ScopedPaintUnderInvalidationCheckingForTest,
- private ScopedFastBorderRadiusForTest,
- private ScopedPaintNonFastScrollableRegionsForTest {
+ private ScopedFastBorderRadiusForTest {
public:
PaintTestConfigurations()
: ScopedCompositeAfterPaintForTest(GetParam() & kCompositeAfterPaint),
ScopedPaintUnderInvalidationCheckingForTest(GetParam() &
kUnderInvalidationChecking),
- ScopedFastBorderRadiusForTest(GetParam() & kFastBorderRadius),
- // Because PaintNonFastScrollableRegions is implied by
- // CompositeAfterPaint (see: runtime_eanbled_features.json5), we must
- // enable the scoped flag for (PNFSR || CAP).
- ScopedPaintNonFastScrollableRegionsForTest(
- GetParam() & kPaintNonFastScrollableRegions ||
- GetParam() & kCompositeAfterPaint) {}
+ ScopedFastBorderRadiusForTest(GetParam() & kFastBorderRadius) {}
~PaintTestConfigurations() {
// Must destruct all objects before toggling back feature flags.
WebHeap::CollectAllGarbageForTesting();
@@ -56,9 +48,8 @@ class PaintTestConfigurations
::testing::Values(0, kCompositeAfterPaint, kFastBorderRadius))
#define INSTANTIATE_SCROLL_HIT_TEST_SUITE_P(test_class) \
- INSTANTIATE_TEST_SUITE_P( \
- All, test_class, \
- ::testing::Values(kPaintNonFastScrollableRegions, kCompositeAfterPaint))
+ INSTANTIATE_TEST_SUITE_P(All, test_class, \
+ ::testing::Values(0, kCompositeAfterPaint))
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/scoped_mocked_url.cc b/chromium/third_party/blink/renderer/platform/testing/scoped_mocked_url.cc
index 701b0b59508..62964edc894 100644
--- a/chromium/third_party/blink/renderer/platform/testing/scoped_mocked_url.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/scoped_mocked_url.cc
@@ -14,7 +14,7 @@ namespace test {
ScopedMockedURL::ScopedMockedURL(const WebURL& url) : url_(url) {}
ScopedMockedURL::~ScopedMockedURL() {
- Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(url_);
+ url_test_helpers::RegisterMockedURLUnregister(url_);
}
ScopedMockedURLLoad::ScopedMockedURLLoad(const WebURL& full_url,
diff --git a/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.cc b/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.cc
new file mode 100644
index 00000000000..59bfc456a06
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.cc
@@ -0,0 +1,41 @@
+// 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/testing/video_frame_utils.h"
+
+#include "base/bind_helpers.h"
+#include "media/video/fake_gpu_memory_buffer.h"
+
+namespace blink {
+
+scoped_refptr<media::VideoFrame> CreateTestFrame(
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
+ const gfx::Size& natural_size,
+ media::VideoFrame::StorageType storage_type) {
+ scoped_refptr<media::VideoFrame> frame;
+ switch (storage_type) {
+ case media::VideoFrame::STORAGE_OWNED_MEMORY:
+ frame = media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_I420,
+ coded_size, visible_rect,
+ natural_size, base::TimeDelta());
+ break;
+
+ case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER: {
+ auto gmb = std::make_unique<media::FakeGpuMemoryBuffer>(
+ coded_size, gfx::BufferFormat::YUV_420_BIPLANAR);
+ const gpu::MailboxHolder empty_mailboxes[media::VideoFrame::kMaxPlanes];
+ frame = media::VideoFrame::WrapExternalGpuMemoryBuffer(
+ visible_rect, natural_size, std::move(gmb), empty_mailboxes,
+ base::NullCallback(), base::TimeDelta());
+ break;
+ }
+
+ default:
+ NOTREACHED() << "Unexpected storage type";
+ }
+ return frame;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.h b/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.h
new file mode 100644
index 00000000000..9052e73e48f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/video_frame_utils.h
@@ -0,0 +1,20 @@
+// 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_TESTING_VIDEO_FRAME_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_VIDEO_FRAME_UTILS_H_
+
+#include "media/base/video_frame.h"
+
+namespace blink {
+
+scoped_refptr<media::VideoFrame> CreateTestFrame(
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
+ const gfx::Size& natural_size,
+ media::VideoFrame::StorageType storage_type);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_VIDEO_FRAME_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc b/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc
index 24d95500f55..09f8a12caec 100644
--- a/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc
@@ -17,29 +17,16 @@
namespace blink {
ViewportLayersSetup::ViewportLayersSetup() {
- clip_layer_ = std::make_unique<FakeGraphicsLayer>(client_);
- scroll_elasticity_layer_ = std::make_unique<FakeGraphicsLayer>(client_);
- page_scale_layer_ = std::make_unique<FakeGraphicsLayer>(client_);
+ // TODO(wangxianzhu): Don't create unnecessary layers.
+ root_layer_ = std::make_unique<FakeGraphicsLayer>(client_);
graphics_layer_ = std::make_unique<FakeGraphicsLayer>(client_);
graphics_layer_->SetDrawsContent(true);
graphics_layer_->SetHitTestable(true);
- clip_layer_->AddChild(scroll_elasticity_layer_.get());
- scroll_elasticity_layer_->AddChild(page_scale_layer_.get());
- page_scale_layer_->AddChild(graphics_layer_.get());
- graphics_layer_->CcLayer()->SetScrollable(clip_layer_->CcLayer()->bounds());
+ root_layer_->AddChild(graphics_layer_.get());
+ graphics_layer_->CcLayer()->SetScrollable(root_layer_->CcLayer()->bounds());
layer_tree_ = std::make_unique<LayerTreeHostEmbedder>();
- layer_tree_->layer_tree_host()->SetRootLayer(clip_layer_->CcLayer());
-
- scroll_elasticity_layer_->SetElementId(cc::LayerIdToElementIdForTesting(
- scroll_elasticity_layer_->CcLayer()->id()));
-
- cc::ViewportLayers viewport_layers;
- viewport_layers.overscroll_elasticity_element_id =
- scroll_elasticity_layer_->CcLayer()->element_id();
- viewport_layers.page_scale = page_scale_layer_->CcLayer();
- viewport_layers.inner_viewport_container = clip_layer_->CcLayer();
- viewport_layers.inner_viewport_scroll = graphics_layer_->CcLayer();
- layer_tree_->layer_tree_host()->RegisterViewportLayers(viewport_layers);
+ layer_tree_->layer_tree_host()->SetRootLayer(root_layer_->CcLayer());
+
layer_tree_->layer_tree_host()->SetViewportRectAndScale(
gfx::Rect(1, 1), /*device_scale_factor=*/1.f,
viz::LocalSurfaceIdAllocation());
diff --git a/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.h b/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.h
index 20e947b875d..356a06f7164 100644
--- a/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.h
+++ b/chromium/third_party/blink/renderer/platform/testing/viewport_layers_setup.h
@@ -34,10 +34,8 @@ class ViewportLayersSetup {
cc::AnimationHost* animation_host();
private:
+ std::unique_ptr<FakeGraphicsLayer> root_layer_;
std::unique_ptr<FakeGraphicsLayer> graphics_layer_;
- std::unique_ptr<FakeGraphicsLayer> page_scale_layer_;
- std::unique_ptr<FakeGraphicsLayer> scroll_elasticity_layer_;
- std::unique_ptr<FakeGraphicsLayer> clip_layer_;
FakeGraphicsLayerClient client_;
std::unique_ptr<LayerTreeHostEmbedder> layer_tree_;
};
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 49f71b9bab1..b389c9cde40 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
@@ -78,8 +78,7 @@ WebURL WebURLLoaderMock::ServeRedirect(
bool report_raw_headers = false;
bool follow = client_->WillFollowRedirect(
- redirect_url, redirect_url,
- WebSecurityOrigin::Create(WebURL(redirect_url)), WebString(),
+ redirect_url, redirect_url, WebString(),
network::mojom::ReferrerPolicy::kDefault, request.HttpMethod(),
redirect_response, report_raw_headers);
// |this| might be deleted in willFollowRedirect().
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 5ff99058fc6..191d623c5be 100644
--- a/chromium/third_party/blink/renderer/platform/text/platform_locale.cc
+++ b/chromium/third_party/blink/renderer/platform/text/platform_locale.cc
@@ -34,6 +34,7 @@
#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"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -218,7 +219,7 @@ String Locale::QueryString(int resource_id,
String Locale::ValidationMessageTooLongText(unsigned value_length,
int max_length) {
- return QueryString(WebLocalizedString::kValidationTooLong,
+ return QueryString(IDS_FORM_VALIDATION_TOO_LONG,
ConvertToLocalizedNumber(String::Number(value_length)),
ConvertToLocalizedNumber(String::Number(max_length)));
}
@@ -226,18 +227,18 @@ String Locale::ValidationMessageTooLongText(unsigned value_length,
String Locale::ValidationMessageTooShortText(unsigned value_length,
int min_length) {
if (value_length == 1) {
- return QueryString(WebLocalizedString::kValidationTooShort,
+ return QueryString(IDS_FORM_VALIDATION_TOO_SHORT,
ConvertToLocalizedNumber(String::Number(value_length)),
ConvertToLocalizedNumber(String::Number(min_length)));
}
- return QueryString(WebLocalizedString::kValidationTooShortPlural,
+ return QueryString(IDS_FORM_VALIDATION_TOO_SHORT_PLURAL,
ConvertToLocalizedNumber(String::Number(value_length)),
ConvertToLocalizedNumber(String::Number(min_length)));
}
String Locale::WeekFormatInLDML() {
- String templ = QueryString(WebLocalizedString::kWeekFormatTemplate);
+ String templ = QueryString(IDS_FORM_INPUT_WEEK_TEMPLATE);
// Converts a string like "Week $2, $1" to an LDML date format pattern like
// "'Week 'ww', 'yyyy".
StringBuilder builder;
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 4735101c28e..3a246033211 100644
--- a/chromium/third_party/blink/renderer/platform/text/platform_locale.h
+++ b/chromium/third_party/blink/renderer/platform/text/platform_locale.h
@@ -29,7 +29,6 @@
#include <memory>
#include "base/macros.h"
-#include "third_party/blink/public/platform/web_localized_string.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"
diff --git a/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc b/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
index 41d9798eff3..28a477f54d1 100644
--- a/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
@@ -9,8 +9,6 @@
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
-using namespace blink;
-
// TODO(jsbell): This fuzzes code in wtf/ but has dependencies on platform/,
// so it must live in the latter directory. Once wtf/ moves into platform/wtf
// this should move there as well.
@@ -27,7 +25,7 @@ class TextCodecFuzzHarness {};
// Fuzzer for WTF::TextCodec.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport();
+ static blink::BlinkFuzzerTestSupport test_support;
// The fuzzer picks 3 bytes off the end of the data to initialize metadata, so
// abort if the input is smaller than that.
if (size < 3)
diff --git a/chromium/third_party/blink/renderer/platform/timer_test.cc b/chromium/third_party/blink/renderer/platform/timer_test.cc
index bb4adf3181e..32c6792ec09 100644
--- a/chromium/third_party/blink/renderer/platform/timer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/timer_test.cc
@@ -87,8 +87,7 @@ class TimerTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
};
-class OnHeapTimerOwner final
- : public GarbageCollectedFinalized<OnHeapTimerOwner> {
+class OnHeapTimerOwner final : public GarbageCollected<OnHeapTimerOwner> {
public:
class Record final : public RefCounted<Record> {
public:
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transform_operations.h b/chromium/third_party/blink/renderer/platform/transforms/transform_operations.h
index c7ef91f07b0..51d25367425 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transform_operations.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/transform_operations.h
@@ -72,6 +72,17 @@ class PLATFORM_EXPORT TransformOperations {
return false;
}
+ // Return true if any of the operation types are non-perspective 3D operation
+ // types (even if the values describe affine transforms)
+ bool HasNonPerspective3DOperation() const {
+ for (auto& operation : operations_) {
+ if (operation->Is3DOperation() &&
+ operation->GetType() != TransformOperation::kPerspective)
+ return true;
+ }
+ return false;
+ }
+
bool PreservesAxisAlignment() const {
for (auto& operation : operations_) {
if (!operation->PreservesAxisAlignment())
@@ -90,6 +101,15 @@ class PLATFORM_EXPORT TransformOperations {
return false;
}
+ // Returns true if any operation is perspective.
+ bool HasPerspective() const {
+ for (auto& operation : operations_) {
+ if (operation->GetType() == TransformOperation::kPerspective)
+ return true;
+ }
+ return false;
+ }
+
bool DependsOnBoxSize() const {
for (auto& operation : operations_) {
if (operation->DependsOnBoxSize())
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 45ac39afaa7..2a9c9c3fe6b 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
@@ -546,4 +546,24 @@ TEST(TransformOperationsTest, ZoomTest) {
EXPECT_EQ(result1, result2);
}
+TEST(TransformOperationsTest, PerspectiveOpsTest) {
+ TransformOperations ops;
+ EXPECT_FALSE(ops.HasPerspective());
+ EXPECT_FALSE(ops.HasNonPerspective3DOperation());
+
+ ops.Operations().push_back(TranslateTransformOperation::Create(
+ Length::Fixed(1), Length::Fixed(2), TransformOperation::kTranslate));
+ EXPECT_FALSE(ops.HasPerspective());
+ EXPECT_FALSE(ops.HasNonPerspective3DOperation());
+
+ ops.Operations().push_back(PerspectiveTransformOperation::Create(1234));
+ EXPECT_TRUE(ops.HasPerspective());
+ EXPECT_FALSE(ops.HasNonPerspective3DOperation());
+
+ ops.Operations().push_back(TranslateTransformOperation::Create(
+ Length::Fixed(1), Length::Fixed(2), 3, TransformOperation::kTranslate3D));
+ EXPECT_TRUE(ops.HasPerspective());
+ EXPECT_TRUE(ops.HasNonPerspective3DOperation());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/DEPS b/chromium/third_party/blink/renderer/platform/video_capture/DEPS
index cc06b7a8c2a..ab4b0ea49e6 100644
--- a/chromium/third_party/blink/renderer/platform/video_capture/DEPS
+++ b/chromium/third_party/blink/renderer/platform/video_capture/DEPS
@@ -10,10 +10,25 @@ include_rules = [
"+media/capture",
"+third_party/blink/renderer/platform/wtf",
"+third_party/blink/renderer/platform/platform_export.h",
+
+ # Dependencies for GpuMemoryBuffer.
+ "+gpu/command_buffer/client/shared_image_interface.h",
+ "+gpu/command_buffer/common/shared_image_usage.h",
+ "+gpu/ipc/common/gpu_memory_buffer_support.h",
+ "+media/video/gpu_video_accelerator_factories.h",
]
specific_include_rules = {
"video_capture_impl_test.cc": [
+ "+third_party/blink/renderer/platform/testing/gpu_memory_buffer_test_support.h",
+ ],
+ "gpu_memory_buffer_test_support.cc": [
+ "+components/viz/test/test_context_provider.h",
+ "+media/video/fake_gpu_memory_buffer.h",
+ "+media/video/mock_gpu_video_accelerator_factories.h",
+ ],
+ "gpu_memory_buffer_test_support.h": [
+ "+gpu/ipc/common/gpu_memory_buffer_support.h",
"+third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h",
],
}
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.cc b/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.cc
new file mode 100644
index 00000000000..084d2601abc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.cc
@@ -0,0 +1,79 @@
+// 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/video_capture/gpu_memory_buffer_test_support.h"
+
+#include "components/viz/test/test_context_provider.h"
+#include "media/video/fake_gpu_memory_buffer.h"
+#include "media/video/mock_gpu_video_accelerator_factories.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Return;
+
+namespace blink {
+
+namespace {
+
+class FakeGpuMemoryBufferImpl : public gpu::GpuMemoryBufferImpl {
+ public:
+ FakeGpuMemoryBufferImpl(const gfx::Size& size, gfx::BufferFormat format)
+ : gpu::GpuMemoryBufferImpl(
+ gfx::GpuMemoryBufferId(),
+ size,
+ format,
+ gpu::GpuMemoryBufferImpl::DestructionCallback()),
+ fake_gmb_(std::make_unique<media::FakeGpuMemoryBuffer>(size, format)) {}
+
+ // gfx::GpuMemoryBuffer implementation
+ bool Map() override { return fake_gmb_->Map(); }
+ void* memory(size_t plane) override { return fake_gmb_->memory(plane); }
+ void Unmap() override { fake_gmb_->Unmap(); }
+ int stride(size_t plane) const override { return fake_gmb_->stride(plane); }
+ gfx::GpuMemoryBufferType GetType() const override {
+ return fake_gmb_->GetType();
+ }
+ gfx::GpuMemoryBufferHandle CloneHandle() const override {
+ return fake_gmb_->CloneHandle();
+ }
+
+ private:
+ std::unique_ptr<media::FakeGpuMemoryBuffer> fake_gmb_;
+};
+
+} // namespace
+
+std::unique_ptr<gpu::GpuMemoryBufferImpl>
+FakeGpuMemoryBufferSupport::CreateGpuMemoryBufferImplFromHandle(
+ gfx::GpuMemoryBufferHandle handle,
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage,
+ gpu::GpuMemoryBufferImpl::DestructionCallback callback) {
+ return std::make_unique<FakeGpuMemoryBufferImpl>(size, format);
+}
+
+TestingPlatformSupportForGpuMemoryBuffer::
+ TestingPlatformSupportForGpuMemoryBuffer()
+ : sii_(new viz::TestSharedImageInterface),
+ gpu_factories_(new media::MockGpuVideoAcceleratorFactories(sii_.get())),
+ media_thread_("TestingMediaThread") {
+ gpu_factories_->SetVideoFrameOutputFormat(
+ media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB);
+ media_thread_.Start();
+ ON_CALL(*gpu_factories_, GetTaskRunner())
+ .WillByDefault(Return(media_thread_.task_runner()));
+}
+
+TestingPlatformSupportForGpuMemoryBuffer::
+ ~TestingPlatformSupportForGpuMemoryBuffer() {
+ media_thread_.Stop();
+}
+
+media::GpuVideoAcceleratorFactories*
+TestingPlatformSupportForGpuMemoryBuffer::GetGpuFactories() {
+ return gpu_factories_.get();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h b/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h
new file mode 100644
index 00000000000..b1294f07cf1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h
@@ -0,0 +1,48 @@
+// 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_VIDEO_CAPTURE_GPU_MEMORY_BUFFER_TEST_SUPPORT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_VIDEO_CAPTURE_GPU_MEMORY_BUFFER_TEST_SUPPORT_H_
+
+#include <memory>
+
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+namespace media {
+class MockGpuVideoAcceleratorFactories;
+} // namespace media
+
+namespace viz {
+class TestSharedImageInterface;
+} // namespace viz
+
+namespace blink {
+
+class FakeGpuMemoryBufferSupport : public gpu::GpuMemoryBufferSupport {
+ public:
+ std::unique_ptr<gpu::GpuMemoryBufferImpl> CreateGpuMemoryBufferImplFromHandle(
+ gfx::GpuMemoryBufferHandle handle,
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage,
+ gpu::GpuMemoryBufferImpl::DestructionCallback callback) override;
+};
+
+class TestingPlatformSupportForGpuMemoryBuffer
+ : public IOTaskRunnerTestingPlatformSupport {
+ public:
+ TestingPlatformSupportForGpuMemoryBuffer();
+ ~TestingPlatformSupportForGpuMemoryBuffer() override;
+ media::GpuVideoAcceleratorFactories* GetGpuFactories() override;
+
+ private:
+ std::unique_ptr<viz::TestSharedImageInterface> sii_;
+ std::unique_ptr<media::MockGpuVideoAcceleratorFactories> gpu_factories_;
+ base::Thread media_thread_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_VIDEO_CAPTURE_GPU_MEMORY_BUFFER_TEST_SUPPORT_H_
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 36b3567aac9..eacd0c7d4ff 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
@@ -20,10 +20,14 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
+#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/video_frame.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"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
@@ -34,12 +38,32 @@ namespace blink {
using VideoFrameBufferHandleType = media::mojom::blink::VideoBufferHandle::Tag;
+// A collection of all types of handles that we use to reference a camera buffer
+// backed with GpuMemoryBuffer.
+struct GpuMemoryBufferResources {
+ explicit GpuMemoryBufferResources(gfx::GpuMemoryBufferHandle handle)
+ : gpu_memory_buffer_handle(std::move(handle)) {}
+ // Stores the GpuMemoryBufferHandle when a new buffer is first registered.
+ // |gpu_memory_buffer_handle| is converted to |gpu_memory_buffer| below when
+ // the camera frame is ready for the first time.
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
+ // The GpuMemoryBuffer backing the camera frame.
+ std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer;
+ // The SharedImage created from |gpu_memory_buffer|.
+ gpu::Mailbox mailbox;
+ // The release sync token for |mailbox|.
+ gpu::SyncToken release_sync_token;
+};
+
struct VideoCaptureImpl::BufferContext
: public base::RefCountedThreadSafe<BufferContext> {
public:
- explicit BufferContext(
- media::mojom::blink::VideoBufferHandlePtr buffer_handle)
- : buffer_type_(buffer_handle->which()) {
+ BufferContext(media::mojom::blink::VideoBufferHandlePtr buffer_handle,
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner)
+ : buffer_type_(buffer_handle->which()),
+ gpu_factories_(gpu_factories),
+ media_task_runner_(std::move(media_task_runner)) {
switch (buffer_type_) {
case VideoFrameBufferHandleType::SHARED_BUFFER_HANDLE:
InitializeFromSharedMemory(
@@ -56,8 +80,10 @@ struct VideoCaptureImpl::BufferContext
InitializeFromMailbox(std::move(buffer_handle->get_mailbox_handles()));
break;
case VideoFrameBufferHandleType::GPU_MEMORY_BUFFER_HANDLE:
- // TODO(jcliang): Implement this.
- NOTREACHED();
+ CHECK(gpu_factories_);
+ CHECK(media_task_runner_);
+ InitializeFromGpuMemoryBufferHandle(
+ std::move(buffer_handle->get_gpu_memory_buffer_handle()));
break;
}
}
@@ -69,6 +95,104 @@ struct VideoCaptureImpl::BufferContext
return mailbox_holders_;
}
+ gfx::GpuMemoryBufferHandle TakeGpuMemoryBufferHandle() {
+ return std::move(gmb_resources_->gpu_memory_buffer_handle);
+ }
+ void SetGpuMemoryBuffer(
+ std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer) {
+ gmb_resources_->gpu_memory_buffer = std::move(gpu_memory_buffer);
+ }
+ gfx::GpuMemoryBuffer* GetGpuMemoryBuffer() {
+ return gmb_resources_->gpu_memory_buffer.get();
+ }
+
+ // Creates SharedImage mailboxes for |gpu_memory_buffer_handle_| and wraps the
+ // mailboxes with the buffer handles in a DMA-buf VideoFrame. The consumer of
+ // the VideoFrame can access the data either through mailboxes (e.g. display)
+ // or through the DMA-buf FDs (e.g. video encoder).
+ static void BindBufferToTextureOnMediaThread(
+ scoped_refptr<BufferContext> buffer_context,
+ media::mojom::blink::VideoFrameInfoPtr info,
+ std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer,
+ scoped_refptr<media::VideoFrame> frame,
+ base::OnceCallback<void(media::mojom::blink::VideoFrameInfoPtr,
+ scoped_refptr<media::VideoFrame>,
+ scoped_refptr<BufferContext>)> on_texture_bound) {
+ DCHECK(buffer_context->media_task_runner_->BelongsToCurrentThread());
+ DCHECK(buffer_context->gpu_factories_);
+ DCHECK_EQ(info->pixel_format, media::PIXEL_FORMAT_NV12);
+ DCHECK_EQ(
+ buffer_context->gpu_factories_->VideoFrameOutputFormat(
+ info->pixel_format),
+ media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB);
+
+ // Create GPU texture and bind GpuMemoryBuffer to the texture.
+ auto* sii = buffer_context->gpu_factories_->SharedImageInterface();
+ if (!sii) {
+ std::move(on_texture_bound)
+ .Run(std::move(info), std::move(frame), std::move(buffer_context));
+ return;
+ }
+ unsigned texture_target =
+ buffer_context->gpu_factories_->ImageTextureTarget(
+ gpu_memory_buffer->GetFormat());
+ if (buffer_context->gmb_resources_->mailbox.IsZero()) {
+ uint32_t usage =
+ gpu::SHARED_IMAGE_USAGE_GLES2 | gpu::SHARED_IMAGE_USAGE_RASTER |
+ gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT;
+ buffer_context->gmb_resources_->mailbox = sii->CreateSharedImage(
+ gpu_memory_buffer.get(),
+ buffer_context->gpu_factories_->GpuMemoryBufferManager(),
+ *(info->color_space), usage);
+ } else {
+ sii->UpdateSharedImage(buffer_context->gmb_resources_->release_sync_token,
+ buffer_context->gmb_resources_->mailbox);
+ }
+ gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
+ CHECK(!buffer_context->gmb_resources_->mailbox.IsZero());
+ gpu::MailboxHolder mailbox_holder_array[media::VideoFrame::kMaxPlanes];
+ mailbox_holder_array[0] = gpu::MailboxHolder(
+ buffer_context->gmb_resources_->mailbox, sync_token, texture_target);
+
+ const auto gmb_size = gpu_memory_buffer->GetSize();
+ frame = media::VideoFrame::WrapExternalGpuMemoryBuffer(
+ gfx::Rect(info->visible_rect), gmb_size, std::move(gpu_memory_buffer),
+ mailbox_holder_array,
+ base::BindOnce(&BufferContext::MailboxHolderReleased, buffer_context),
+ info->timestamp);
+ frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY,
+ true);
+ frame->metadata()->SetBoolean(
+ media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED, true);
+
+ std::move(on_texture_bound)
+ .Run(std::move(info), std::move(frame), std::move(buffer_context));
+ }
+
+ static void MailboxHolderReleased(scoped_refptr<BufferContext> buffer_context,
+ const gpu::SyncToken& release_sync_token) {
+ if (!buffer_context->media_task_runner_->BelongsToCurrentThread()) {
+ buffer_context->media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BufferContext::MailboxHolderReleased,
+ std::move(buffer_context), release_sync_token));
+ return;
+ }
+ buffer_context->gmb_resources_->release_sync_token = release_sync_token;
+ }
+
+ static void DestroyTextureOnMediaThread(
+ media::GpuVideoAcceleratorFactories* gpu_factories,
+ gpu::Mailbox mailbox,
+ gpu::SyncToken release_sync_token) {
+ if (!mailbox.IsZero()) {
+ auto* sii = gpu_factories->SharedImageInterface();
+ if (!sii)
+ return;
+ sii->DestroySharedImage(release_sync_token, mailbox);
+ }
+ }
+
private:
void InitializeFromSharedMemory(mojo::ScopedSharedBufferHandle handle) {
DCHECK(handle.is_valid());
@@ -103,8 +227,21 @@ struct VideoCaptureImpl::BufferContext
mailbox_holders_ = std::move(mailbox_handles->mailbox_holder);
}
+ void InitializeFromGpuMemoryBufferHandle(
+ gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
+ gmb_resources_ = std::make_unique<GpuMemoryBufferResources>(
+ std::move(gpu_memory_buffer_handle));
+ }
+
friend class base::RefCountedThreadSafe<BufferContext>;
- virtual ~BufferContext() {}
+ virtual ~BufferContext() {
+ if (buffer_type_ == VideoFrameBufferHandleType::GPU_MEMORY_BUFFER_HANDLE) {
+ media_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&BufferContext::DestroyTextureOnMediaThread,
+ gpu_factories_, gmb_resources_->mailbox,
+ gmb_resources_->release_sync_token));
+ }
+ }
VideoFrameBufferHandleType buffer_type_;
@@ -122,6 +259,15 @@ struct VideoCaptureImpl::BufferContext
// Only valid for |buffer_type_ == MAILBOX_HANDLES|.
Vector<gpu::MailboxHolder> mailbox_holders_;
+ // The following is for |buffer_type == GPU_MEMORY_BUFFER_HANDLE|.
+
+ // Uses to create SharedImage from |gpu_memory_buffer_|.
+ media::GpuVideoAcceleratorFactories* gpu_factories_;
+ // The task runner that |gpu_factories_| runs on.
+ const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+
+ std::unique_ptr<GpuMemoryBufferResources> gmb_resources_;
+
DISALLOW_COPY_AND_ASSIGN(BufferContext);
};
@@ -144,15 +290,18 @@ VideoCaptureImpl::VideoCaptureImpl(media::VideoCaptureSessionId session_id)
: device_id_(session_id),
session_id_(session_id),
video_capture_host_for_testing_(nullptr),
- observer_binding_(this),
- state_(blink::VIDEO_CAPTURE_STATE_STOPPED) {
+ state_(blink::VIDEO_CAPTURE_STATE_STOPPED),
+ gpu_memory_buffer_support_(new gpu::GpuMemoryBufferSupport()) {
CHECK(!session_id.is_empty());
DETACH_FROM_THREAD(io_thread_checker_);
- media::mojom::blink::VideoCaptureHostPtr temp_video_capture_host;
Platform::Current()->GetBrowserInterfaceBrokerProxy()->GetInterface(
- mojo::MakeRequest(&temp_video_capture_host));
- video_capture_host_info_ = temp_video_capture_host.PassInterface();
+ pending_video_capture_host_.InitWithNewPipeAndPassReceiver());
+
+ gpu_factories_ = Platform::Current()->GetGpuFactories();
+ if (gpu_factories_) {
+ media_task_runner_ = gpu_factories_->GetTaskRunner();
+ }
}
VideoCaptureImpl::~VideoCaptureImpl() {
@@ -275,6 +424,11 @@ void VideoCaptureImpl::OnLog(const String& message) {
GetVideoCaptureHost()->OnLog(device_id_, message);
}
+void VideoCaptureImpl::SetGpuMemoryBufferSupportForTesting(
+ std::unique_ptr<gpu::GpuMemoryBufferSupport> gpu_memory_buffer_support) {
+ gpu_memory_buffer_support_ = std::move(gpu_memory_buffer_support);
+}
+
void VideoCaptureImpl::OnStateChanged(media::mojom::VideoCaptureState state) {
DVLOG(1) << __func__ << " state: " << state;
DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
@@ -334,7 +488,9 @@ void VideoCaptureImpl::OnNewBuffer(
const bool inserted =
client_buffers_
- .emplace(buffer_id, new BufferContext(std::move(buffer_handle)))
+ .emplace(buffer_id,
+ new BufferContext(std::move(buffer_handle), gpu_factories_,
+ media_task_runner_))
.second;
DCHECK(inserted);
}
@@ -449,11 +605,62 @@ void VideoCaptureImpl::OnBufferReady(
info->timestamp);
break;
}
- case VideoFrameBufferHandleType::GPU_MEMORY_BUFFER_HANDLE:
- // TODO(jcliang): Implement this.
- NOTREACHED();
- break;
+ case VideoFrameBufferHandleType::GPU_MEMORY_BUFFER_HANDLE: {
+ // Create GpuMemoryBuffer from handle.
+ if (!buffer_context->GetGpuMemoryBuffer()) {
+ gfx::BufferFormat gfx_format;
+ switch (info->pixel_format) {
+ case media::VideoPixelFormat::PIXEL_FORMAT_NV12:
+ gfx_format = gfx::BufferFormat::YUV_420_BIPLANAR;
+ break;
+ default:
+ LOG(FATAL) << "Unsupported pixel format";
+ return;
+ }
+ // The GpuMemoryBuffer is allocated and owned by the video capture
+ // buffer pool from the video capture service process, so we don't need
+ // to destroy the GpuMemoryBuffer here.
+ auto gmb =
+ gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
+ buffer_context->TakeGpuMemoryBufferHandle(),
+ gfx::Size(info->coded_size), gfx_format,
+ gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE, base::DoNothing());
+ buffer_context->SetGpuMemoryBuffer(std::move(gmb));
+ }
+ CHECK(buffer_context->GetGpuMemoryBuffer());
+
+ // Clone the GpuMemoryBuffer and wrap it in a VideoFrame.
+ std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
+ gpu_memory_buffer_support_->CreateGpuMemoryBufferImplFromHandle(
+ buffer_context->GetGpuMemoryBuffer()->CloneHandle(),
+ buffer_context->GetGpuMemoryBuffer()->GetSize(),
+ buffer_context->GetGpuMemoryBuffer()->GetFormat(),
+ gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE, base::DoNothing());
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &BufferContext::BindBufferToTextureOnMediaThread,
+ std::move(buffer_context), base::Passed(&info),
+ base::Passed(&gmb), frame,
+ media::BindToCurrentLoop(base::BindOnce(
+ &VideoCaptureImpl::OnVideoFrameReady,
+ weak_factory_.GetWeakPtr(), buffer_id, reference_time))));
+ return;
+ }
}
+ OnVideoFrameReady(buffer_id, reference_time, std::move(info),
+ std::move(frame), std::move(buffer_context));
+}
+
+void VideoCaptureImpl::OnVideoFrameReady(
+ int32_t buffer_id,
+ base::TimeTicks reference_time,
+ media::mojom::blink::VideoFrameInfoPtr info,
+ scoped_refptr<media::VideoFrame> frame,
+ scoped_refptr<BufferContext> buffer_context) {
+ DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
+
if (!frame) {
OnFrameDropped(media::VideoCaptureFrameDropReason::
kVideoCaptureImplFailedToWrapDataAsMediaVideoFrame);
@@ -554,10 +761,8 @@ void VideoCaptureImpl::StartCaptureInternal() {
state_ = VIDEO_CAPTURE_STATE_STARTING;
OnLog("VideoCaptureImpl changing state to VIDEO_CAPTURE_STATE_STARTING");
- media::mojom::blink::VideoCaptureObserverPtr observer;
- observer_binding_.Bind(mojo::MakeRequest(&observer));
GetVideoCaptureHost()->Start(device_id_, session_id_, params_,
- std::move(observer));
+ observer_receiver_.BindNewPipeAndPassRemote());
}
void VideoCaptureImpl::OnDeviceSupportedFormats(
@@ -591,8 +796,8 @@ media::mojom::blink::VideoCaptureHost* VideoCaptureImpl::GetVideoCaptureHost() {
if (video_capture_host_for_testing_)
return video_capture_host_for_testing_;
- if (!video_capture_host_.get())
- video_capture_host_.Bind(std::move(video_capture_host_info_));
+ if (!video_capture_host_.is_bound())
+ video_capture_host_.Bind(std::move(pending_video_capture_host_));
return video_capture_host_.get();
}
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 671250af55e..7bca6dbb199 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
@@ -14,10 +14,20 @@
#include "media/base/video_frame.h"
#include "media/capture/mojom/video_capture.mojom-blink.h"
#include "media/capture/video_capture_types.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/media/video_capture.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+namespace gpu {
+class GpuMemoryBufferSupport;
+} // namespace gpu
+
+namespace media {
+class GpuVideoAcceleratorFactories;
+} // namespace media
+
namespace blink {
// VideoCaptureImpl represents a capture device in renderer process. It provides
@@ -71,6 +81,8 @@ class PLATFORM_EXPORT VideoCaptureImpl
media::mojom::blink::VideoCaptureHost* service) {
video_capture_host_for_testing_ = service;
}
+ void SetGpuMemoryBufferSupportForTesting(
+ std::unique_ptr<gpu::GpuMemoryBufferSupport> gpu_memory_buffer_support);
// media::mojom::VideoCaptureObserver implementation.
void OnStateChanged(media::mojom::VideoCaptureState state) override;
@@ -95,6 +107,12 @@ class PLATFORM_EXPORT VideoCaptureImpl
using BufferFinishedCallback =
base::OnceCallback<void(double consumer_resource_utilization)>;
+ void OnVideoFrameReady(int32_t buffer_id,
+ base::TimeTicks reference_time,
+ media::mojom::blink::VideoFrameInfoPtr info,
+ scoped_refptr<media::VideoFrame> frame,
+ scoped_refptr<BufferContext> buffer_context);
+
void OnAllClientsFinishedConsumingFrame(
int buffer_id,
scoped_refptr<BufferContext> buffer_context,
@@ -130,14 +148,16 @@ class PLATFORM_EXPORT VideoCaptureImpl
const base::UnguessableToken device_id_;
const base::UnguessableToken session_id_;
- // |video_capture_host_| is an IO-thread InterfacePtr to a remote service
- // implementation and is created by binding |video_capture_host_info_|,
+ // |video_capture_host_| is an IO-thread mojo::Remote to a remote service
+ // implementation and is created by binding |pending_video_capture_host_|,
// unless a |video_capture_host_for_testing_| has been injected.
- media::mojom::blink::VideoCaptureHostPtrInfo video_capture_host_info_;
- media::mojom::blink::VideoCaptureHostPtr video_capture_host_;
+ mojo::PendingRemote<media::mojom::blink::VideoCaptureHost>
+ pending_video_capture_host_;
+ mojo::Remote<media::mojom::blink::VideoCaptureHost> video_capture_host_;
media::mojom::blink::VideoCaptureHost* video_capture_host_for_testing_;
- mojo::Binding<media::mojom::blink::VideoCaptureObserver> observer_binding_;
+ mojo::Receiver<media::mojom::blink::VideoCaptureObserver> observer_receiver_{
+ this};
// Buffers available for sending to the client.
using ClientBufferMap = std::map<int32_t, scoped_refptr<BufferContext>>;
@@ -154,6 +174,12 @@ class PLATFORM_EXPORT VideoCaptureImpl
VideoCaptureState state_;
+ // Methods of |gpu_factories_| need to run on |media_task_runner_|.
+ media::GpuVideoAcceleratorFactories* gpu_factories_;
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+
+ std::unique_ptr<gpu::GpuMemoryBufferSupport> gpu_memory_buffer_support_;
+
THREAD_CHECKER(io_thread_checker_);
// WeakPtrFactory pointing back to |this| object, for use with
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 7a99f544a53..2a1682941ce 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
@@ -10,13 +10,15 @@
#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_test_util.h"
#include "base/test/task_environment.h"
#include "media/capture/mojom/video_capture.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"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/video_capture/gpu_memory_buffer_test_support.h"
#include "third_party/blink/renderer/platform/video_capture/video_capture_impl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -24,6 +26,7 @@ using ::testing::_;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::InvokeWithoutArgs;
+using ::testing::Mock;
using ::testing::SaveArg;
using ::testing::WithArgs;
@@ -55,7 +58,8 @@ class MockMojoVideoCaptureHost : public media::mojom::blink::VideoCaptureHost {
void Start(const base::UnguessableToken& device_id,
const base::UnguessableToken& session_id,
const media::VideoCaptureParams& params,
- media::mojom::blink::VideoCaptureObserverPtr observer) override {
+ mojo::PendingRemote<media::mojom::blink::VideoCaptureObserver>
+ observer) override {
DoStart(device_id, session_id, params);
}
MOCK_METHOD3(DoStart,
@@ -128,6 +132,9 @@ class VideoCaptureImplTest : public ::testing::Test {
video_capture_impl_->OnStateChanged(
media::mojom::VideoCaptureState::STARTED);
}));
+
+ video_capture_impl_->SetGpuMemoryBufferSupportForTesting(
+ std::make_unique<FakeGpuMemoryBufferSupport>());
}
protected:
@@ -170,7 +177,18 @@ class VideoCaptureImplTest : public ::testing::Test {
std::move(region)));
}
- void SimulateBufferReceived(int buffer_id, const gfx::Size& size) {
+ void SimulateGpuMemoryBufferCreated(int buffer_id,
+ gfx::GpuMemoryBufferHandle gmb_handle) {
+ video_capture_impl_->OnNewBuffer(
+ buffer_id,
+ media::mojom::blink::VideoBufferHandle::NewGpuMemoryBufferHandle(
+ std::move(gmb_handle)));
+ }
+
+ void SimulateBufferReceived(
+ int buffer_id,
+ const gfx::Size& size,
+ media::VideoPixelFormat pixel_format = media::PIXEL_FORMAT_I420) {
media::mojom::blink::VideoFrameInfoPtr info =
media::mojom::blink::VideoFrameInfo::New();
@@ -180,9 +198,10 @@ class VideoCaptureImplTest : public ::testing::Test {
info->metadata = frame_metadata.GetInternalValues().Clone();
info->timestamp = now - base::TimeTicks();
- info->pixel_format = media::PIXEL_FORMAT_I420;
+ info->pixel_format = pixel_format;
info->coded_size = WebSize(size);
info->visible_rect = WebRect(gfx::Rect(size));
+ info->color_space = gfx::ColorSpace();
video_capture_impl_->OnBufferReady(buffer_id, std::move(info));
}
@@ -211,8 +230,9 @@ class VideoCaptureImplTest : public ::testing::Test {
const base::UnguessableToken session_id_ = base::UnguessableToken::Create();
base::test::TaskEnvironment task_environment_;
- ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
- const std::unique_ptr<VideoCaptureImpl> video_capture_impl_;
+ ScopedTestingPlatformSupport<TestingPlatformSupportForGpuMemoryBuffer>
+ platform_;
+ std::unique_ptr<VideoCaptureImpl> video_capture_impl_;
MockMojoVideoCaptureHost mock_video_capture_host_;
media::VideoCaptureParams params_small_;
media::VideoCaptureParams params_large_;
@@ -356,6 +376,74 @@ TEST_F(VideoCaptureImplTest, BufferReceived_ReadOnlyShmemRegion) {
EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
}
+TEST_F(VideoCaptureImplTest, BufferReceived_GpuMemoryBufferHandle) {
+ const int kArbitraryBufferId = 11;
+
+ // With GpuMemoryBufferHandle, the buffer handle is received on the IO thread
+ // and passed to a media thread to create a SharedImage. After the SharedImage
+ // is created and wrapped in a video frame, we pass the video frame back to
+ // the IO thread to pass to the clients by calling their frame-ready
+ // callbacks.
+ base::Thread testing_io_thread("TestingIOThread");
+ base::WaitableEvent frame_ready_event;
+ scoped_refptr<media::VideoFrame> frame;
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _))
+ .WillOnce(
+ Invoke([&](scoped_refptr<media::VideoFrame> f, base::TimeTicks t) {
+ // Hold on a reference to the video frame to emulate that we're
+ // actively using the buffer.
+ frame = f;
+ frame_ready_event.Signal();
+ }));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kArbitraryBufferId, _))
+ .Times(0);
+
+ // The first half of the test: Create and queue the GpuMemoryBufferHandle.
+ // VideoCaptureImpl would:
+ // 1. create a GpuMemoryBuffer out of the handle on |testing_io_thread|
+ // 2. create a SharedImage from the GpuMemoryBuffer on |media_thread_|
+ // 3. invoke OnFrameReady callback on |testing_io_thread|
+ auto create_and_queue_buffer = [&]() {
+ gfx::GpuMemoryBufferHandle gmb_handle;
+ gmb_handle.type = gfx::NATIVE_PIXMAP;
+ gmb_handle.id = gfx::GpuMemoryBufferId(kArbitraryBufferId);
+
+ StartCapture(0, params_small_);
+ SimulateGpuMemoryBufferCreated(kArbitraryBufferId, std::move(gmb_handle));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size,
+ media::PIXEL_FORMAT_NV12);
+ };
+
+ // The second half of the test: Stop capture and destroy the buffer.
+ // Everything should happen on |testing_io_thread| here.
+ auto stop_capture_and_destroy_buffer = [&]() {
+ StopCapture(0);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+ // Explicitly destroy |video_capture_impl_| to make sure it's destroyed on
+ // the right thread.
+ video_capture_impl_.reset();
+ };
+
+ testing_io_thread.Start();
+ testing_io_thread.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting(create_and_queue_buffer));
+
+ // Wait until OnFrameReady is called on |testing_io_thread|.
+ EXPECT_TRUE(frame_ready_event.TimedWait(base::TimeDelta::FromSeconds(3)));
+
+ testing_io_thread.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting(stop_capture_and_destroy_buffer));
+ testing_io_thread.Stop();
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
+}
+
TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop) {
const int kArbitraryBufferId = 12;
@@ -412,6 +500,33 @@ TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop_ReadOnlyShmemRegion) {
EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
}
+TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop_GpuMemoryBufferHandle) {
+ const int kArbitraryBufferId = 12;
+
+ gfx::GpuMemoryBufferHandle gmb_handle;
+ gmb_handle.type = gfx::NATIVE_PIXMAP;
+ gmb_handle.id = gfx::GpuMemoryBufferId(kArbitraryBufferId);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_large_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+
+ StartCapture(0, params_large_);
+ SimulateGpuMemoryBufferCreated(kArbitraryBufferId, std::move(gmb_handle));
+ StopCapture(0);
+ // A buffer received after StopCapture() triggers an instant ReleaseBuffer().
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size,
+ media::PIXEL_FORMAT_NV12);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
+}
+
TEST_F(VideoCaptureImplTest, AlreadyStarted) {
media::VideoCaptureParams params = {};
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
@@ -478,11 +593,15 @@ TEST_F(VideoCaptureImplTest, BufferReceivedBeforeOnStarted) {
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
// Additional STARTED will cause RequestRefreshFrame a second time.
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
EXPECT_CALL(mock_video_capture_host_, Stop(_));
@@ -512,11 +631,52 @@ TEST_F(VideoCaptureImplTest,
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
+
+ // Additional STARTED will cause RequestRefreshFrame a second time.
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest,
+ BufferReceivedBeforeOnStarted_GpuMemoryBufferHandle) {
+ const int kArbitraryBufferId = 16;
+
+ gfx::GpuMemoryBufferHandle gmb_handle;
+ gmb_handle.type = gfx::NATIVE_PIXMAP;
+ gmb_handle.id = gfx::GpuMemoryBufferId(kArbitraryBufferId);
+
+ InSequence s;
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_))
+ .WillOnce(DoNothing());
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+ StartCapture(0, params_small_);
+ SimulateGpuMemoryBufferCreated(kArbitraryBufferId, std::move(gmb_handle));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size,
+ media::PIXEL_FORMAT_NV12);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
// Additional STARTED will cause RequestRefreshFrame a second time.
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+ Mock::VerifyAndClearExpectations(this);
+ Mock::VerifyAndClearExpectations(&mock_video_capture_host_);
EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
EXPECT_CALL(mock_video_capture_host_, Stop(_));
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
index 2e9a9d1a7d2..c9d777e7160 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
@@ -59,8 +59,7 @@ OriginAccessEntry::OriginAccessEntry(
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort,
priority) {}
-OriginAccessEntry::OriginAccessEntry(OriginAccessEntry&& from) noexcept =
- default;
+OriginAccessEntry::OriginAccessEntry(OriginAccessEntry&& from) = default;
network::cors::OriginAccessEntry::MatchResult OriginAccessEntry::MatchesOrigin(
const SecurityOrigin& origin) const {
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 b3e567474f6..5113a406bd3 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,7 @@ class PLATFORM_EXPORT OriginAccessEntry {
network::mojom::CorsDomainMatchMode,
network::mojom::CorsOriginAccessMatchPriority priority =
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
- OriginAccessEntry(OriginAccessEntry&& from) noexcept;
+ OriginAccessEntry(OriginAccessEntry&& from);
network::cors::OriginAccessEntry::MatchResult MatchesOrigin(
const SecurityOrigin&) const;
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
index 52be887a34e..922fbdee70a 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -63,11 +63,12 @@ const String& EnsureNonNull(const String& string) {
} // namespace
-static URLSecurityOriginMap* g_url_origin_map = nullptr;
+static URLSecurityOriginMap* g_blob_url_null_origin_map = nullptr;
-static SecurityOrigin* GetOriginFromMap(const KURL& url) {
- if (g_url_origin_map)
- return g_url_origin_map->GetOrigin(url);
+static SecurityOrigin* GetNullOriginFromBlobURL(const KURL& blob_url) {
+ DCHECK(blob_url.ProtocolIs("blob"));
+ if (g_blob_url_null_origin_map)
+ return g_blob_url_null_origin_map->GetOrigin(blob_url);
return nullptr;
}
@@ -93,8 +94,10 @@ KURL SecurityOrigin::ExtractInnerURL(const KURL& url) {
return KURL(url.GetPath());
}
-void SecurityOrigin::SetMap(URLSecurityOriginMap* map) {
- g_url_origin_map = map;
+void SecurityOrigin::SetBlobURLNullOriginMap(
+ URLSecurityOriginMap* blob_url_null_origin_map) {
+ DCHECK(!g_blob_url_null_origin_map);
+ g_blob_url_null_origin_map = blob_url_null_origin_map;
}
static bool ShouldTreatAsOpaqueOrigin(const KURL& url) {
@@ -202,8 +205,10 @@ SecurityOrigin::SecurityOrigin(const SecurityOrigin* other,
scoped_refptr<SecurityOrigin> SecurityOrigin::CreateWithReferenceOrigin(
const KURL& url,
const SecurityOrigin* reference_origin) {
- if (scoped_refptr<SecurityOrigin> origin = GetOriginFromMap(url))
- return origin;
+ if (url.ProtocolIs("blob")) {
+ if (scoped_refptr<SecurityOrigin> origin = GetNullOriginFromBlobURL(url))
+ return origin;
+ }
if (ShouldTreatAsOpaqueOrigin(url)) {
if (!reference_origin)
@@ -318,16 +323,6 @@ bool SecurityOrigin::IsSecure(const KURL& url) {
return false;
}
-bool SecurityOrigin::SerializesAsNull() const {
- if (IsOpaque())
- return true;
-
- if (IsLocal() && block_local_access_from_local_origin_)
- return true;
-
- return false;
-}
-
base::Optional<base::UnguessableToken>
SecurityOrigin::GetNonceForSerialization() const {
// The call to token() forces initialization of the |nonce_if_opaque_| if
@@ -421,11 +416,15 @@ bool SecurityOrigin::CanRequest(const KURL& url) const {
if (universal_access_)
return true;
- if (GetOriginFromMap(url) == this)
- return true;
-
- if (IsOpaque())
+ if (SerializesAsNull()) {
+ // Allow the request if the URL is blob and it has the same "null" origin
+ // with |this|.
+ // TODO(nhiroki): Probably we should check the equality by
+ // SecurityOrigin::IsSameSchemeHostPort().
+ if (url.ProtocolIs("blob") && GetNullOriginFromBlobURL(url) == this)
+ return true;
return false;
+ }
scoped_refptr<const SecurityOrigin> target_origin =
SecurityOrigin::Create(url);
@@ -707,4 +706,14 @@ scoped_refptr<SecurityOrigin> SecurityOrigin::GetOriginForAgentCluster(
return result;
}
+bool SecurityOrigin::SerializesAsNull() const {
+ if (IsOpaque())
+ return true;
+
+ if (IsLocal() && block_local_access_from_local_origin_)
+ return true;
+
+ return false;
+}
+
} // 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 abceb071ce4..19595353110 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -95,7 +95,9 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
static scoped_refptr<SecurityOrigin> CreateFromUrlOrigin(const url::Origin&);
url::Origin ToUrlOrigin() const;
- static void SetMap(URLSecurityOriginMap*);
+ // Sets the map to look up a SecurityOrigin instance serialized to "null" from
+ // a blob URL.
+ static void SetBlobURLNullOriginMap(URLSecurityOriginMap*);
// Some URL schemes use nested URLs for their security context. For example,
// filesystem URLs look like the following:
@@ -334,6 +336,9 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
return agent_cluster_id_;
}
+ // Returns true if this security origin is serialized to "null".
+ bool SerializesAsNull() const;
+
private:
constexpr static const uint16_t kInvalidPort = 0;
@@ -365,8 +370,6 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
bool PassesFileCheck(const SecurityOrigin*) const;
void BuildRawString(StringBuilder&) const;
- bool SerializesAsNull() const;
-
// Get the nonce associated with this origin, if it is unique. This should be
// used only when trying to send an Origin across an IPC pipe.
base::Optional<base::UnguessableToken> GetNonceForSerialization() const;
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 a47b8b7c907..d58dedd4d21 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
@@ -35,6 +35,7 @@
#include "base/stl_util.h"
#include "net/base/url_util.h"
#include "services/network/public/mojom/cors.mojom-blink.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/blob/blob_url.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
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 cb4e4bded94..20cd6eb8d4c 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
@@ -29,7 +29,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_SECURITY_POLICY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_SECURITY_POLICY_H_
-#include "services/network/public/mojom/cors_origin_pattern.mojom-blink.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom-blink-forward.h"
#include "services/network/public/mojom/referrer_policy.mojom-blink.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
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 32414fa50a6..2c6e996fef8 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "services/network/public/mojom/cors.mojom-blink.h"
+#include "services/network/public/mojom/cors_origin_pattern.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/url_security_origin_map.h b/chromium/third_party/blink/renderer/platform/weborigin/url_security_origin_map.h
index cd927d9d85a..0cfe303ef9c 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/url_security_origin_map.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/url_security_origin_map.h
@@ -45,6 +45,9 @@ class URLSecurityOriginMap {
public:
URLSecurityOriginMap() = default;
virtual ~URLSecurityOriginMap() = default;
+
+ // Returns a SecurityOrigin instance that represents the origin of the given
+ // URL. May return nullptr.
virtual SecurityOrigin* GetOrigin(const KURL&) = 0;
private:
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 f7708a9e1a9..bda303b71c9 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
@@ -4,9 +4,12 @@
#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
+#include "base/bind_helpers.h"
#include "base/logging.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 {
@@ -78,6 +81,50 @@ void IsValidFrame(const media::VideoFrame& frame) {
CHECK(frame.stride(media::VideoFrame::kVPlane));
}
+scoped_refptr<media::VideoFrame> ConstructI420VideoFrame(
+ const media::VideoFrame& 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);
+ gfx::GpuMemoryBuffer* gmb = source_frame.GetGpuMemoryBuffer();
+ if (!gmb || !gmb->Map()) {
+ return nullptr;
+ }
+
+ // Crop to the visible rectangle specified in |source_frame|.
+ const uint8_t* src_y = (reinterpret_cast<const uint8_t*>(gmb->memory(0)) +
+ source_frame.visible_rect().x() +
+ (source_frame.visible_rect().y() * gmb->stride(0)));
+ const uint8_t* src_uv =
+ (reinterpret_cast<const uint8_t*>(gmb->memory(1)) +
+ ((source_frame.visible_rect().x() / 2) * 2) +
+ ((source_frame.visible_rect().y() / 2) * gmb->stride(1)));
+
+ // Convert to I420 and scale to the natural size specified in |source_frame|.
+ scoped_refptr<media::VideoFrame> i420_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_I420, source_frame.natural_size(),
+ gfx::Rect(source_frame.natural_size()), source_frame.natural_size(),
+ source_frame.timestamp());
+ i420_frame->metadata()->MergeMetadataFrom(source_frame.metadata());
+ const auto& i420_planes = i420_frame->layout().planes();
+ webrtc::NV12ToI420Scaler scaler;
+ scaler.NV12ToI420Scale(
+ src_y, gmb->stride(0), src_uv, gmb->stride(1),
+ source_frame.visible_rect().width(), source_frame.visible_rect().height(),
+ i420_frame->data(media::VideoFrame::kYPlane),
+ i420_planes[media::VideoFrame::kYPlane].stride,
+ i420_frame->data(media::VideoFrame::kUPlane),
+ i420_planes[media::VideoFrame::kUPlane].stride,
+ i420_frame->data(media::VideoFrame::kVPlane),
+ i420_planes[media::VideoFrame::kVPlane].stride,
+ i420_frame->coded_size().width(), i420_frame->coded_size().height());
+
+ gmb->Unmap();
+
+ return i420_frame;
+}
+
} // anonymous namespace
namespace blink {
@@ -93,15 +140,40 @@ webrtc::VideoFrameBuffer::Type WebRtcVideoFrameAdapter::type() const {
}
int WebRtcVideoFrameAdapter::width() const {
+ if (frame_->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ return frame_->natural_size().width();
+ }
return frame_->visible_rect().width();
}
int WebRtcVideoFrameAdapter::height() const {
+ if (frame_->storage_type() == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER) {
+ return frame_->natural_size().height();
+ }
return frame_->visible_rect().height();
}
rtc::scoped_refptr<webrtc::I420BufferInterface>
WebRtcVideoFrameAdapter::CreateFrameAdapter() const {
+ if (frame_->storage_type() ==
+ media::VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER) {
+ auto i420_frame = ConstructI420VideoFrame(*frame_);
+ if (!i420_frame) {
+ return new rtc::RefCountedObject<
+ FrameAdapter<webrtc::I420BufferInterface>>(
+ media::VideoFrame::CreateColorFrame(frame_->natural_size(), 0u, 0x80,
+ 0x80, frame_->timestamp()));
+ }
+
+ // Keep |frame_| alive until |i420_frame| is destroyed.
+ i420_frame->AddDestructionObserver(base::BindOnce(
+ base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(), frame_));
+
+ IsValidFrame(*i420_frame);
+ return new rtc::RefCountedObject<FrameAdapter<webrtc::I420BufferInterface>>(
+ i420_frame);
+ }
+
// We cant convert texture synchronously due to threading issues, see
// https://crbug.com/663452. Instead, return a black frame (yuv = {0, 0x80,
// 0x80}).
diff --git a/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc
new file mode 100644
index 00000000000..d65df0e8adb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter_test.cc
@@ -0,0 +1,65 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.h"
+
+#include "media/base/video_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/video_frame_utils.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"
+
+namespace blink {
+
+TEST(WebRtcVideoFrameAdapterTest, WidthAndHeight) {
+ 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 visible rectangle for
+ // VideoFrame backed by owned memory.
+ auto owned_memory_frame =
+ CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
+ media::VideoFrame::STORAGE_OWNED_MEMORY);
+ rtc::scoped_refptr<webrtc::VideoFrameBuffer> owned_memory_frame_adapter(
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(
+ std::move(owned_memory_frame)));
+ EXPECT_EQ(owned_memory_frame_adapter->width(), kVisibleRect.width());
+ EXPECT_EQ(owned_memory_frame_adapter->height(), kVisibleRect.height());
+
+ // The adapter should report width and height from the natural size for
+ // VideoFrame backed by GpuMemoryBuffer.
+ auto gmb_frame =
+ CreateTestFrame(kCodedSize, kVisibleRect, kNaturalSize,
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER);
+ rtc::scoped_refptr<webrtc::VideoFrameBuffer> gmb_frame_adapter(
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(std::move(gmb_frame)));
+ EXPECT_EQ(gmb_frame_adapter->width(), kNaturalSize.width());
+ EXPECT_EQ(gmb_frame_adapter->height(), kNaturalSize.height());
+}
+
+TEST(WebRtcVideoFrameAdapterTest, ToI420DownScale) {
+ const gfx::Size kCodedSize(1280, 960);
+ const gfx::Rect kVisibleRect(0, 120, 1280, 720);
+ const gfx::Size kNaturalSize(640, 360);
+
+ 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<WebRtcVideoFrameAdapter>(std::move(gmb_frame)));
+ 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();
+ EXPECT_EQ(i420_frame->width(), kNaturalSize.width());
+ EXPECT_EQ(i420_frame->height(), kNaturalSize.height());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/wtf/Allocator.md b/chromium/third_party/blink/renderer/platform/wtf/Allocator.md
index b8c7ab10a2c..2d7471c824b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/Allocator.md
+++ b/chromium/third_party/blink/renderer/platform/wtf/Allocator.md
@@ -14,7 +14,7 @@ Oilpan is a garbage collection system in Blink.
The lifetime of objects allocated by Oilpan is automatically managed.
The following objects are allocated by Oilpan:
-* Objects that inherit from GarbageCollected<T> or GarbageCollectedFinalized<T>.
+* Objects that inherit from GarbageCollected<T>.
* HeapVector<T>, HeapHashSet<T>, HeapHashMap<T, U> etc
@@ -72,8 +72,7 @@ The following is a basic rule to determine which of Oilpan or PartitionAlloc
you should use when allocating a new object:
* Use Oilpan if you want a GC to manage the lifetime of the object.
-You need to make the object inherit from GarbageCollected<T> or
-GarbageCollectedFinalized<T>. See
+You need to make the object inherit from GarbageCollected<T>. See
[BlinkGCAPIReference.md](../heap/BlinkGCAPIReference.md) to learn
programming with Oilpan.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
index dd87934c741..ae3e47514a1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -55,26 +55,8 @@ jumbo_component("wtf") {
"decimal.h",
"deque.h",
"doubly_linked_list.h",
- "dtoa/bignum-dtoa.cc",
- "dtoa/bignum-dtoa.h",
- "dtoa/bignum.cc",
- "dtoa/bignum.h",
- "dtoa/cached-powers.cc",
- "dtoa/cached-powers.h",
- "dtoa/diy-fp.cc",
- "dtoa/diy-fp.h",
- "dtoa/double-conversion.cc",
- "dtoa/double-conversion.h",
- "dtoa/double.h",
- "dtoa/dtoa.cc",
- "dtoa/dtoa.h",
- "dtoa/fast-dtoa.cc",
- "dtoa/fast-dtoa.h",
- "dtoa/fixed-dtoa.cc",
- "dtoa/fixed-dtoa.h",
- "dtoa/strtod.cc",
- "dtoa/strtod.h",
- "dtoa/utils.h",
+ "dtoa.cc",
+ "dtoa.h",
"dynamic_annotations.cc",
"dynamic_annotations.h",
"forward.h",
@@ -238,6 +220,7 @@ jumbo_component("wtf") {
public_deps = [
"//base",
+ "//base/third_party/double_conversion",
"//third_party/icu",
]
diff --git a/chromium/third_party/blink/renderer/platform/wtf/DEPS b/chromium/third_party/blink/renderer/platform/wtf/DEPS
index 7ef4a105394..43cd2e6f12f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/DEPS
+++ b/chromium/third_party/blink/renderer/platform/wtf/DEPS
@@ -20,6 +20,7 @@ include_rules = [
"+base/rand_util.h",
"+base/stl_util.h",
"+base/strings",
+ "+base/third_party/double_conversion",
"+base/template_util.h",
"+base/test/metrics/histogram_tester.h",
"+base/threading",
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 bb5e450b6d4..709c28baa11 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/allocator.h
@@ -60,6 +60,15 @@ class __thisIsHereToForceASemicolonAfterThisMacro;
private: \
friend class ::WTF::internal::__thisIsHereToForceASemicolonAfterThisMacro
+#define IS_GARBAGE_COLLECTED_CONTAINER_TYPE() \
+ IS_GARBAGE_COLLECTED_TYPE(); \
+ \
+ public: \
+ using IsGarbageCollectedCollectionTypeMarker = int; \
+ \
+ private: \
+ friend class ::WTF::internal::__thisIsHereToForceASemicolonAfterThisMacro
+
#if defined(__clang__)
#define ANNOTATE_STACK_ALLOCATED \
__attribute__((annotate("blink_stack_allocated")))
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 6f24a91d1f7..94209ae764b 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
@@ -265,25 +265,6 @@ struct CrossThreadCopier<String> {
WTF_EXPORT static Type Copy(const String&);
};
-// mojo::InterfacePtrInfo is a cross-thread safe mojo::InterfacePtr.
-template <typename Interface>
-struct CrossThreadCopier<mojo::InterfacePtrInfo<Interface>> {
- STATIC_ONLY(CrossThreadCopier);
- using Type = mojo::InterfacePtrInfo<Interface>;
- static Type Copy(Type ptr_info) {
- return ptr_info; // This is in fact a move.
- }
-};
-
-template <typename Interface>
-struct CrossThreadCopier<mojo::InterfaceRequest<Interface>> {
- STATIC_ONLY(CrossThreadCopier);
- using Type = mojo::InterfaceRequest<Interface>;
- static Type Copy(Type request) {
- return request; // This is in fact a move.
- }
-};
-
template <typename Interface>
struct CrossThreadCopier<mojo::PendingReceiver<Interface>> {
STATIC_ONLY(CrossThreadCopier);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/decimal.cc b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
index c6d881dae34..58720c931f3 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
@@ -40,13 +40,13 @@
namespace blink {
-namespace decimal_private {
+namespace {
-static int const kExponentMax = 1023;
-static int const kExponentMin = -1023;
-static int const kPrecision = 18;
+constexpr int kExponentMax = 1023;
+constexpr int kExponentMin = -1023;
+constexpr int kPrecision = 18;
-static const uint64_t kMaxCoefficient =
+constexpr uint64_t kMaxCoefficient =
UINT64_C(0xDE0B6B3A763FFFF); // 999999999999999999 == 18 9's
// This class handles Decimal special values.
@@ -75,54 +75,38 @@ class SpecialValueHandler {
const Decimal& lhs_;
const Decimal& rhs_;
- Result result_;
+ Result result_ = kResultIsUnknown;
DISALLOW_COPY_AND_ASSIGN(SpecialValueHandler);
};
SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
- : lhs_(lhs), rhs_(rhs), result_(kResultIsUnknown) {}
+ : lhs_(lhs), rhs_(rhs) {}
SpecialValueHandler::HandleResult SpecialValueHandler::Handle() {
if (lhs_.IsFinite() && rhs_.IsFinite())
return kBothFinite;
- const Decimal::EncodedData::FormatClass lhs_class =
- lhs_.Value().GetFormatClass();
- const Decimal::EncodedData::FormatClass rhs_class =
- rhs_.Value().GetFormatClass();
- if (lhs_class == Decimal::EncodedData::kClassNaN) {
+ if (lhs_.IsNaN()) {
result_ = kResultIsLHS;
return kEitherNaN;
}
- if (rhs_class == Decimal::EncodedData::kClassNaN) {
+ if (rhs_.IsNaN()) {
result_ = kResultIsRHS;
return kEitherNaN;
}
- if (lhs_class == Decimal::EncodedData::kClassInfinity)
- return rhs_class == Decimal::EncodedData::kClassInfinity ? kBothInfinity
- : kLHSIsInfinity;
+ if (lhs_.IsInfinity())
+ return rhs_.IsInfinity() ? kBothInfinity : kLHSIsInfinity;
- if (rhs_class == Decimal::EncodedData::kClassInfinity)
- return kRHSIsInfinity;
-
- NOTREACHED();
- return kBothFinite;
+ DCHECK(rhs_.IsInfinity());
+ return kRHSIsInfinity;
}
Decimal SpecialValueHandler::Value() const {
- switch (result_) {
- case kResultIsLHS:
- return lhs_;
- case kResultIsRHS:
- return rhs_;
- case kResultIsUnknown:
- default:
- NOTREACHED();
- return lhs_;
- }
+ DCHECK(result_ == kResultIsLHS || result_ == kResultIsRHS);
+ return (result_ == kResultIsLHS) ? lhs_ : rhs_;
}
// This class is used for 128 bit unsigned integer arithmetic.
@@ -232,9 +216,7 @@ static uint64_t ScaleUp(uint64_t x, int n) {
}
}
-} // namespace decimal_private
-
-using namespace decimal_private;
+} // namespace
Decimal::EncodedData::EncodedData(Sign sign, FormatClass format_class)
: coefficient_(0), exponent_(0), format_class_(format_class), sign_(sign) {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/decimal.h b/chromium/third_party/blink/renderer/platform/wtf/decimal.h
index 1ba7091a9ca..98e5a4ab794 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/decimal.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal.h
@@ -39,10 +39,6 @@
namespace blink {
-namespace decimal_private {
-class SpecialValueHandler;
-}
-
// This class represents decimal base floating point number.
//
// FIXME: Once all C++ compiler support decimal type, we should replace this
@@ -63,7 +59,6 @@ class WTF_EXPORT Decimal {
DISALLOW_NEW();
// For accessing FormatClass.
friend class Decimal;
- friend class decimal_private::SpecialValueHandler;
public:
EncodedData(Sign, int exponent, uint64_t coefficient);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/deque.h b/chromium/third_party/blink/renderer/platform/wtf/deque.h
index 2fd35823b88..4a98ffbe84e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/deque.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/deque.h
@@ -52,7 +52,9 @@ class DequeConstIterator;
template <typename T,
wtf_size_t inlineCapacity = 0,
typename Allocator = PartitionAllocator>
-class Deque {
+class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
+ (INLINE_CAPACITY == 0) &&
+ Allocator::kIsGarbageCollected> {
USE_ALLOCATOR(Deque, Allocator);
public:
@@ -64,11 +66,10 @@ class Deque {
Deque();
Deque(const Deque&);
Deque& operator=(const Deque&);
- Deque(Deque&&) noexcept;
- Deque& operator=(Deque&&) noexcept;
- ~Deque();
+ Deque(Deque&&);
+ Deque& operator=(Deque&&);
- void FinalizeGarbageCollectedObject() { NOTREACHED(); }
+ void Finalize();
void Swap(Deque&);
@@ -342,14 +343,14 @@ Deque<T, inlineCapacity, Allocator>::operator=(const Deque& other) {
}
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
-inline Deque<T, inlineCapacity, Allocator>::Deque(Deque&& other) noexcept
+inline Deque<T, inlineCapacity, Allocator>::Deque(Deque&& other)
: start_(0), end_(0) {
Swap(other);
}
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
inline Deque<T, inlineCapacity, Allocator>&
-Deque<T, inlineCapacity, Allocator>::operator=(Deque&& other) noexcept {
+Deque<T, inlineCapacity, Allocator>::operator=(Deque&& other) {
Swap(other);
return *this;
}
@@ -374,16 +375,18 @@ inline void Deque<T, inlineCapacity, Allocator>::DestroyAll() {
// For design of the destructor, please refer to
// [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
-inline Deque<T, inlineCapacity, Allocator>::~Deque() {
+inline void Deque<T, inlineCapacity, Allocator>::Finalize() {
+ static_assert(!Allocator::kIsGarbageCollected || INLINE_CAPACITY,
+ "GarbageCollected collections without inline capacity cannot "
+ "be finalized.");
if ((!INLINE_CAPACITY && !buffer_.Buffer()))
return;
if (!IsEmpty() &&
!(Allocator::kIsGarbageCollected && buffer_.HasOutOfLineBuffer()))
DestroyAll();
- // If this is called during sweeping, it must not touch the OutOfLineBuffer.
- if (Allocator::IsSweepForbidden())
- return;
+ // For garbage collected deque HeapAllocator::BackingFree() will bail out
+ // during sweeping.
buffer_.Destruct();
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc
index 0e47ce59450..8ac63b5acc2 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc
@@ -33,9 +33,10 @@
* file.
*/
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include <string.h>
+
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -52,7 +53,7 @@ const char* NumberToString(double d, NumberToStringBuffer buffer) {
static inline const char* FormatStringTruncatingTrailingZerosIfNeeded(
NumberToStringBuffer buffer,
double_conversion::StringBuilder& builder) {
- int length = builder.GetPosition();
+ int length = builder.position();
// If there is an exponent, stripping trailing zeros would be incorrect.
// FIXME: Zeros should be stripped before the 'e'.
@@ -85,8 +86,9 @@ static inline const char* FormatStringTruncatingTrailingZerosIfNeeded(
}
// Truncate the StringBuilder, and return the final result.
- builder.SetPosition(truncated_length + 1);
- return builder.Finalize();
+ char* result = builder.Finalize();
+ result[truncated_length + 1] = '\0';
+ return result;
}
const char* NumberToFixedPrecisionString(double d,
@@ -143,6 +145,14 @@ double ParseDoubleFromLongString(const UChar* string,
return ParseDouble(conversion_buffer.data(), length, parsed_length);
}
+const double_conversion::StringToDoubleConverter& GetDoubleConverter() {
+ static double_conversion::StringToDoubleConverter converter(
+ double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES |
+ double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK,
+ 0.0, 0, nullptr, nullptr);
+ return converter;
+}
+
} // namespace internal
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa.h
index 0af307d00b2..34a99ec603d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/dtoa.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa.h
@@ -18,10 +18,11 @@
*
*/
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DTOA_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DTOA_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_H_
-#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
+#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/wtf_export.h"
@@ -53,13 +54,18 @@ namespace internal {
double ParseDoubleFromLongString(const UChar* string,
size_t length,
size_t& parsed_length);
-}
+const double_conversion::StringToDoubleConverter& GetDoubleConverter();
+} // namespace internal
inline double ParseDouble(const LChar* string,
size_t length,
size_t& parsed_length) {
- return double_conversion::StringToDoubleConverter::StringToDouble(
- reinterpret_cast<const char*>(string), length, &parsed_length);
+ int int_parsed_length = 0;
+ double d = internal::GetDoubleConverter().StringToDouble(
+ reinterpret_cast<const char*>(string), base::saturated_cast<int>(length),
+ &int_parsed_length);
+ parsed_length = int_parsed_length;
+ return d;
}
inline double ParseDouble(const UChar* string,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/COPYING b/chromium/third_party/blink/renderer/platform/wtf/dtoa/COPYING
deleted file mode 100644
index 933718a9ef9..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/COPYING
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2006-2011, the V8 project authors. 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.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/LICENSE b/chromium/third_party/blink/renderer/platform/wtf/dtoa/LICENSE
deleted file mode 100644
index 933718a9ef9..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2006-2011, the V8 project authors. 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.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/README b/chromium/third_party/blink/renderer/platform/wtf/dtoa/README
deleted file mode 100644
index f186b420f42..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/README
+++ /dev/null
@@ -1,11 +0,0 @@
-http://code.google.com/p/double-conversion
-
-This project (double-conversion) provides binary-decimal and decimal-binary
-routines for IEEE doubles.
-
-The library consists of efficient conversion routines that have been extracted
-from the V8 JavaScript engine. The code has been refactored and improved so that
-it can be used more easily in other projects.
-
-There is extensive documentation in src/double-conversion.h. Other examples can
-be found in test/cctest/test-conversions.cc.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc
deleted file mode 100644
index 00f8870d2b8..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc
+++ /dev/null
@@ -1,680 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h"
-
-#include <math.h>
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/bignum.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-static int NormalizedExponent(uint64_t significand, int exponent) {
- DCHECK_NE(significand, 0u);
- while ((significand & Double::kHiddenBit) == 0) {
- significand = significand << 1;
- exponent = exponent - 1;
- }
- return exponent;
-}
-
-// Forward declarations:
-// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
-static int EstimatePower(int exponent);
-// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
-// and denominator.
-static void InitialScaledStartValues(double v,
- int estimated_power,
- bool need_boundary_deltas,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus);
-// Multiplies numerator/denominator so that its values lies in the range 1-10.
-// Returns decimal_point s.t.
-// v = numerator'/denominator' * 10^(decimal_point-1)
-// where numerator' and denominator' are the values of numerator and
-// denominator after the call to this function.
-static void FixupMultiply10(int estimated_power,
- bool is_even,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus);
-// Generates digits from the left to the right and stops when the generated
-// digits yield the shortest decimal representation of v.
-static void GenerateShortestDigits(Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus,
- bool is_even,
- Vector<char> buffer,
- int* length);
-// Generates 'requested_digits' after the decimal point.
-static void BignumToFixed(int requested_digits,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Vector<char>(buffer),
- int* length);
-// Generates 'count' digits of numerator/denominator.
-// Once 'count' digits have been produced rounds the result depending on the
-// remainder (remainders of exactly .5 round upwards). Might update the
-// decimal_point when rounding up (for example for 0.9999).
-static void GenerateCountedDigits(int count,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Vector<char>(buffer),
- int* length);
-
-void BignumDtoa(double v,
- BignumDtoaMode mode,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* decimal_point) {
- DCHECK_GT(v, 0);
- DCHECK(!Double(v).IsSpecial());
- uint64_t significand = Double(v).Significand();
- bool is_even = (significand & 1) == 0;
- int exponent = Double(v).Exponent();
- int normalized_exponent = NormalizedExponent(significand, exponent);
- // estimated_power might be too low by 1.
- int estimated_power = EstimatePower(normalized_exponent);
-
- // Shortcut for Fixed.
- // The requested digits correspond to the digits after the point. If the
- // number is much too small, then there is no need in trying to get any
- // digits.
- if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
- buffer[0] = '\0';
- *length = 0;
- // Set decimal-point to -requested_digits. This is what Gay does.
- // Note that it should not have any effect anyways since the string is
- // empty.
- *decimal_point = -requested_digits;
- return;
- }
-
- Bignum numerator;
- Bignum denominator;
- Bignum delta_minus;
- Bignum delta_plus;
- // Make sure the bignum can grow large enough. The smallest double equals
- // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
- // The maximum double is 1.7976931348623157e308 which needs fewer than
- // 308*4 binary digits.
- DCHECK_GE(Bignum::kMaxSignificantBits, 324 * 4);
- bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST);
- InitialScaledStartValues(v, estimated_power, need_boundary_deltas, &numerator,
- &denominator, &delta_minus, &delta_plus);
- // We now have v = (numerator / denominator) * 10^estimated_power.
- FixupMultiply10(estimated_power, is_even, decimal_point, &numerator,
- &denominator, &delta_minus, &delta_plus);
- // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
- // 1 <= (numerator + delta_plus) / denominator < 10
- switch (mode) {
- case BIGNUM_DTOA_SHORTEST:
- GenerateShortestDigits(&numerator, &denominator, &delta_minus,
- &delta_plus, is_even, buffer, length);
- break;
- case BIGNUM_DTOA_FIXED:
- BignumToFixed(requested_digits, decimal_point, &numerator, &denominator,
- buffer, length);
- break;
- case BIGNUM_DTOA_PRECISION:
- GenerateCountedDigits(requested_digits, decimal_point, &numerator,
- &denominator, buffer, length);
- break;
- default:
- UNREACHABLE();
- }
- buffer[*length] = '\0';
-}
-
-// The procedure starts generating digits from the left to the right and stops
-// when the generated digits yield the shortest decimal representation of v. A
-// decimal representation of v is a number lying closer to v than to any other
-// double, so it converts to v when read.
-//
-// This is true if d, the decimal representation, is between m- and m+, the
-// upper and lower boundaries. d must be strictly between them if !is_even.
-// m- := (numerator - delta_minus) / denominator
-// m+ := (numerator + delta_plus) / denominator
-//
-// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
-// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
-// will be produced. This should be the standard precondition.
-static void GenerateShortestDigits(Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus,
- bool is_even,
- Vector<char> buffer,
- int* length) {
- // Small optimization: if delta_minus and delta_plus are the same just reuse
- // one of the two bignums.
- if (Bignum::Equal(*delta_minus, *delta_plus)) {
- delta_plus = delta_minus;
- }
- *length = 0;
- while (true) {
- uint16_t digit;
- digit = numerator->DivideModuloIntBignum(*denominator);
- DCHECK_LE(digit, 9u); // digit is a uint16_t and therefore always positive.
- // digit = numerator / denominator (integer division).
- // numerator = numerator % denominator.
- buffer[(*length)++] = static_cast<char>(digit + '0');
-
- // Can we stop already?
- // If the remainder of the division is less than the distance to the lower
- // boundary we can stop. In this case we simply round down (discarding the
- // remainder).
- // Similarly we test if we can round up (using the upper boundary).
- bool in_delta_room_minus;
- bool in_delta_room_plus;
- if (is_even) {
- in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
- } else {
- in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
- }
- if (is_even) {
- in_delta_room_plus =
- Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
- } else {
- in_delta_room_plus =
- Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
- }
- if (!in_delta_room_minus && !in_delta_room_plus) {
- // Prepare for next iteration.
- numerator->Times10();
- delta_minus->Times10();
- // We optimized delta_plus to be equal to delta_minus (if they share the
- // same value). So don't multiply delta_plus if they point to the same
- // object.
- if (delta_minus != delta_plus) {
- delta_plus->Times10();
- }
- } else if (in_delta_room_minus && in_delta_room_plus) {
- // Let's see if 2*numerator < denominator.
- // If yes, then the next digit would be < 5 and we can round down.
- int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
- if (compare < 0) {
- // Remaining digits are less than .5. -> Round down (== do nothing).
- } else if (compare > 0) {
- // Remaining digits are more than .5 of denominator. -> Round up.
- // Note that the last digit could not be a '9' as otherwise the whole
- // loop would have stopped earlier.
- // We still have an assert here in case the preconditions were not
- // satisfied.
- DCHECK_NE(buffer[(*length) - 1], '9');
- buffer[(*length) - 1]++;
- } else {
- // Halfway case.
- // TODO(floitsch): need a way to solve half-way cases.
- // For now let's round towards even (since this is what Gay seems to
- // do).
-
- if ((buffer[(*length) - 1] - '0') % 2 == 0) {
- // Round down => Do nothing.
- } else {
- DCHECK_NE(buffer[(*length) - 1], '9');
- buffer[(*length) - 1]++;
- }
- }
- return;
- } else if (in_delta_room_minus) {
- // Round down (== do nothing).
- return;
- } else { // in_delta_room_plus
- // Round up.
- // Note again that the last digit could not be '9' since this would have
- // stopped the loop earlier.
- // We still have an ASSERT here, in case the preconditions were not
- // satisfied.
- DCHECK_NE(buffer[(*length) - 1], '9');
- buffer[(*length) - 1]++;
- return;
- }
- }
-}
-
-// Let v = numerator / denominator < 10.
-// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
-// from left to right. Once 'count' digits have been produced we decide wether
-// to round up or down. Remainders of exactly .5 round upwards. Numbers such
-// as 9.999999 propagate a carry all the way, and change the
-// exponent (decimal_point), when rounding upwards.
-static void GenerateCountedDigits(int count,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Vector<char>(buffer),
- int* length) {
- DCHECK_GE(count, 0);
- for (int i = 0; i < count - 1; ++i) {
- uint16_t digit;
- digit = numerator->DivideModuloIntBignum(*denominator);
- DCHECK_LE(digit, 9u); // digit is a uint16_t and therefore always positive.
- // digit = numerator / denominator (integer division).
- // numerator = numerator % denominator.
- buffer[i] = static_cast<char>(digit + '0');
- // Prepare for next iteration.
- numerator->Times10();
- }
- // Generate the last digit.
- uint16_t digit;
- digit = numerator->DivideModuloIntBignum(*denominator);
- if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
- digit++;
- }
- buffer[count - 1] = static_cast<char>(digit + '0');
- // Correct bad digits (in case we had a sequence of '9's). Propagate the
- // carry until we hat a non-'9' or til we reach the first digit.
- for (int i = count - 1; i > 0; --i) {
- if (buffer[i] != '0' + 10)
- break;
- buffer[i] = '0';
- buffer[i - 1]++;
- }
- if (buffer[0] == '0' + 10) {
- // Propagate a carry past the top place.
- buffer[0] = '1';
- (*decimal_point)++;
- }
- *length = count;
-}
-
-// Generates 'requested_digits' after the decimal point. It might omit
-// trailing '0's. If the input number is too small then no digits at all are
-// generated (ex.: 2 fixed digits for 0.00001).
-//
-// Input verifies: 1 <= (numerator + delta) / denominator < 10.
-static void BignumToFixed(int requested_digits,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Vector<char>(buffer),
- int* length) {
- // Note that we have to look at more than just the requested_digits, since
- // a number could be rounded up. Example: v=0.5 with requested_digits=0.
- // Even though the power of v equals 0 we can't just stop here.
- if (-(*decimal_point) > requested_digits) {
- // The number is definitively too small.
- // Ex: 0.001 with requested_digits == 1.
- // Set decimal-point to -requested_digits. This is what Gay does.
- // Note that it should not have any effect anyways since the string is
- // empty.
- *decimal_point = -requested_digits;
- *length = 0;
- return;
- } else if (-(*decimal_point) == requested_digits) {
- // We only need to verify if the number rounds down or up.
- // Ex: 0.04 and 0.06 with requested_digits == 1.
- DCHECK_EQ(*decimal_point, -requested_digits);
- // Initially the fraction lies in range (1, 10]. Multiply the denominator
- // by 10 so that we can compare more easily.
- denominator->Times10();
- if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
- // If the fraction is >= 0.5 then we have to include the rounded
- // digit.
- buffer[0] = '1';
- *length = 1;
- (*decimal_point)++;
- } else {
- // Note that we caught most of similar cases earlier.
- *length = 0;
- }
- return;
- } else {
- // The requested digits correspond to the digits after the point.
- // The variable 'needed_digits' includes the digits before the point.
- int needed_digits = (*decimal_point) + requested_digits;
- GenerateCountedDigits(needed_digits, decimal_point, numerator, denominator,
- buffer, length);
- }
-}
-
-// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
-// v = f * 2^exponent and 2^52 <= f < 2^53.
-// v is hence a normalized double with the given exponent. The output is an
-// approximation for the exponent of the decimal approimation .digits * 10^k.
-//
-// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
-// Note: this property holds for v's upper boundary m+ too.
-// 10^k <= m+ < 10^k+1.
-// (see explanation below).
-//
-// Examples:
-// EstimatePower(0) => 16
-// EstimatePower(-52) => 0
-//
-// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
-static int EstimatePower(int exponent) {
- // This function estimates log10 of v where v = f*2^e (with e == exponent).
- // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
- // Note that f is bounded by its container size. Let p = 53 (the double's
- // significand size). Then 2^(p-1) <= f < 2^p.
- //
- // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
- // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
- // The computed number undershoots by less than 0.631 (when we compute log3
- // and not log10).
- //
- // Optimization: since we only need an approximated result this computation
- // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
- // not really measurable, though.
- //
- // Since we want to avoid overshooting we decrement by 1e10 so that
- // floating-point imprecisions don't affect us.
- //
- // Explanation for v's boundary m+: the computation takes advantage of
- // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
- // (even for denormals where the delta can be much more important).
-
- const double kK1Log10 = 0.30102999566398114; // 1/lg(10)
-
- // For doubles len(f) == 53 (don't forget the hidden bit).
- const int kSignificandSize = 53;
- double estimate = ceil((exponent + kSignificandSize - 1) * kK1Log10 - 1e-10);
- return static_cast<int>(estimate);
-}
-
-// See comments for InitialScaledStartValues.
-static void InitialScaledStartValuesPositiveExponent(double v,
- int estimated_power,
- bool need_boundary_deltas,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus) {
- // A positive exponent implies a positive power.
- DCHECK_GE(estimated_power, 0);
- // Since the estimated_power is positive we simply multiply the denominator
- // by 10^estimated_power.
-
- // numerator = v.
- numerator->AssignUInt64(Double(v).Significand());
- numerator->ShiftLeft(Double(v).Exponent());
- // denominator = 10^estimated_power.
- denominator->AssignPowerUInt16(10, estimated_power);
-
- if (need_boundary_deltas) {
- // Introduce a common denominator so that the deltas to the boundaries are
- // integers.
- denominator->ShiftLeft(1);
- numerator->ShiftLeft(1);
- // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
- // denominator (of 2) delta_plus equals 2^e.
- delta_plus->AssignUInt16(1);
- delta_plus->ShiftLeft(Double(v).Exponent());
- // Same for delta_minus (with adjustments below if f == 2^p-1).
- delta_minus->AssignUInt16(1);
- delta_minus->ShiftLeft(Double(v).Exponent());
-
- // If the significand (without the hidden bit) is 0, then the lower
- // boundary is closer than just half a ulp (unit in the last place).
- // There is only one exception: if the next lower number is a denormal then
- // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we
- // have to test it in the other function where exponent < 0).
- uint64_t v_bits = Double(v).AsUint64();
- if ((v_bits & Double::kSignificandMask) == 0) {
- // The lower boundary is closer at half the distance of "normal" numbers.
- // Increase the common denominator and adapt all but the delta_minus.
- denominator->ShiftLeft(1); // *2
- numerator->ShiftLeft(1); // *2
- delta_plus->ShiftLeft(1); // *2
- }
- }
-}
-
-// See comments for InitialScaledStartValues
-static void InitialScaledStartValuesNegativeExponentPositivePower(
- double v,
- int estimated_power,
- bool need_boundary_deltas,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus) {
- uint64_t significand = Double(v).Significand();
- int exponent = Double(v).Exponent();
- // v = f * 2^e with e < 0, and with estimated_power >= 0.
- // This means that e is close to 0 (have a look at how estimated_power is
- // computed).
-
- // numerator = significand
- // since v = significand * 2^exponent this is equivalent to
- // numerator = v * / 2^-exponent
- numerator->AssignUInt64(significand);
- // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
- denominator->AssignPowerUInt16(10, estimated_power);
- denominator->ShiftLeft(-exponent);
-
- if (need_boundary_deltas) {
- // Introduce a common denominator so that the deltas to the boundaries are
- // integers.
- denominator->ShiftLeft(1);
- numerator->ShiftLeft(1);
- // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
- // denominator (of 2) delta_plus equals 2^e.
- // Given that the denominator already includes v's exponent the distance
- // to the boundaries is simply 1.
- delta_plus->AssignUInt16(1);
- // Same for delta_minus (with adjustments below if f == 2^p-1).
- delta_minus->AssignUInt16(1);
-
- // If the significand (without the hidden bit) is 0, then the lower
- // boundary is closer than just one ulp (unit in the last place).
- // There is only one exception: if the next lower number is a denormal
- // then the distance is 1 ulp. Since the exponent is close to zero
- // (otherwise estimated_power would have been negative) this cannot happen
- // here either.
- uint64_t v_bits = Double(v).AsUint64();
- if ((v_bits & Double::kSignificandMask) == 0) {
- // The lower boundary is closer at half the distance of "normal" numbers.
- // Increase the denominator and adapt all but the delta_minus.
- denominator->ShiftLeft(1); // *2
- numerator->ShiftLeft(1); // *2
- delta_plus->ShiftLeft(1); // *2
- }
- }
-}
-
-// See comments for InitialScaledStartValues
-static void InitialScaledStartValuesNegativeExponentNegativePower(
- double v,
- int estimated_power,
- bool need_boundary_deltas,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus) {
- const uint64_t kMinimalNormalizedExponent =
- UINT64_2PART_C(0x00100000, 00000000);
- uint64_t significand = Double(v).Significand();
- int exponent = Double(v).Exponent();
- // Instead of multiplying the denominator with 10^estimated_power we
- // multiply all values (numerator and deltas) by 10^-estimated_power.
-
- // Use numerator as temporary container for power_ten.
- Bignum* power_ten = numerator;
- power_ten->AssignPowerUInt16(10, -estimated_power);
-
- if (need_boundary_deltas) {
- // Since power_ten == numerator we must make a copy of 10^estimated_power
- // before we complete the computation of the numerator.
- // delta_plus = delta_minus = 10^estimated_power
- delta_plus->AssignBignum(*power_ten);
- delta_minus->AssignBignum(*power_ten);
- }
-
- // numerator = significand * 2 * 10^-estimated_power
- // since v = significand * 2^exponent this is equivalent to
- // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
- // Remember: numerator has been abused as power_ten. So no need to assign it
- // to itself.
- DCHECK_EQ(numerator, power_ten);
- numerator->MultiplyByUInt64(significand);
-
- // denominator = 2 * 2^-exponent with exponent < 0.
- denominator->AssignUInt16(1);
- denominator->ShiftLeft(-exponent);
-
- if (need_boundary_deltas) {
- // Introduce a common denominator so that the deltas to the boundaries are
- // integers.
- numerator->ShiftLeft(1);
- denominator->ShiftLeft(1);
- // With this shift the boundaries have their correct value, since
- // delta_plus = 10^-estimated_power, and
- // delta_minus = 10^-estimated_power.
- // These assignments have been done earlier.
-
- // The special case where the lower boundary is twice as close.
- // This time we have to look out for the exception too.
- uint64_t v_bits = Double(v).AsUint64();
- if ((v_bits & Double::kSignificandMask) == 0 &&
- // The only exception where a significand == 0 has its boundaries at
- // "normal" distances:
- (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) {
- numerator->ShiftLeft(1); // *2
- denominator->ShiftLeft(1); // *2
- delta_plus->ShiftLeft(1); // *2
- }
- }
-}
-
-// Let v = significand * 2^exponent.
-// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
-// and denominator. The functions GenerateShortestDigits and
-// GenerateCountedDigits will then convert this ratio to its decimal
-// representation d, with the required accuracy.
-// Then d * 10^estimated_power is the representation of v.
-// (Note: the fraction and the estimated_power might get adjusted before
-// generating the decimal representation.)
-//
-// The initial start values consist of:
-// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
-// - a scaled (common) denominator.
-// optionally (used by GenerateShortestDigits to decide if it has the shortest
-// decimal converting back to v):
-// - v - m-: the distance to the lower boundary.
-// - m+ - v: the distance to the upper boundary.
-//
-// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
-//
-// Let ep == estimated_power, then the returned values will satisfy:
-// v / 10^ep = numerator / denominator.
-// v's boundaries m- and m+:
-// m- / 10^ep == v / 10^ep - delta_minus / denominator
-// m+ / 10^ep == v / 10^ep + delta_plus / denominator
-// Or in other words:
-// m- == v - delta_minus * 10^ep / denominator;
-// m+ == v + delta_plus * 10^ep / denominator;
-//
-// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
-// or 10^k <= v < 10^(k+1)
-// we then have 0.1 <= numerator/denominator < 1
-// or 1 <= numerator/denominator < 10
-//
-// It is then easy to kickstart the digit-generation routine.
-//
-// The boundary-deltas are only filled if need_boundary_deltas is set.
-static void InitialScaledStartValues(double v,
- int estimated_power,
- bool need_boundary_deltas,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus) {
- if (Double(v).Exponent() >= 0) {
- InitialScaledStartValuesPositiveExponent(
- v, estimated_power, need_boundary_deltas, numerator, denominator,
- delta_minus, delta_plus);
- } else if (estimated_power >= 0) {
- InitialScaledStartValuesNegativeExponentPositivePower(
- v, estimated_power, need_boundary_deltas, numerator, denominator,
- delta_minus, delta_plus);
- } else {
- InitialScaledStartValuesNegativeExponentNegativePower(
- v, estimated_power, need_boundary_deltas, numerator, denominator,
- delta_minus, delta_plus);
- }
-}
-
-// This routine multiplies numerator/denominator so that its values lies in the
-// range 1-10. That is after a call to this function we have:
-// 1 <= (numerator + delta_plus) /denominator < 10.
-// Let numerator the input before modification and numerator' the argument
-// after modification, then the output-parameter decimal_point is such that
-// numerator / denominator * 10^estimated_power ==
-// numerator' / denominator' * 10^(decimal_point - 1)
-// In some cases estimated_power was too low, and this is already the case. We
-// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
-// estimated_power) but do not touch the numerator or denominator.
-// Otherwise the routine multiplies the numerator and the deltas by 10.
-static void FixupMultiply10(int estimated_power,
- bool is_even,
- int* decimal_point,
- Bignum* numerator,
- Bignum* denominator,
- Bignum* delta_minus,
- Bignum* delta_plus) {
- bool in_range;
- if (is_even) {
- // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
- // are rounded to the closest floating-point number with even significand.
- in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
- } else {
- in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
- }
- if (in_range) {
- // Since numerator + delta_plus >= denominator we already have
- // 1 <= numerator/denominator < 10. Simply update the estimated_power.
- *decimal_point = estimated_power + 1;
- } else {
- *decimal_point = estimated_power;
- numerator->Times10();
- if (Bignum::Equal(*delta_minus, *delta_plus)) {
- delta_minus->Times10();
- delta_plus->AssignBignum(*delta_minus);
- } else {
- delta_minus->Times10();
- delta_plus->Times10();
- }
- }
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h
deleted file mode 100644
index 3878c7ce379..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_BIGNUM_DTOA_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_BIGNUM_DTOA_H_
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-enum BignumDtoaMode {
- // Return the shortest correct representation.
- // For example the output of 0.299999999999999988897 is (the less accurate but
- // correct) 0.3.
- BIGNUM_DTOA_SHORTEST,
- // Return a fixed number of digits after the decimal point.
- // For instance fixed(0.1, 4) becomes 0.1000
- // If the input number is big, the output will be big.
- BIGNUM_DTOA_FIXED,
- // Return a fixed number of digits, no matter what the exponent is.
- BIGNUM_DTOA_PRECISION
-};
-
-// Converts the given double 'v' to ascii.
-// The result should be interpreted as buffer * 10^(point-length).
-// The buffer will be null-terminated.
-//
-// The input v must be > 0 and different from NaN, and Infinity.
-//
-// The output depends on the given mode:
-// - SHORTEST: produce the least amount of digits for which the internal
-// identity requirement is still satisfied. If the digits are printed
-// (together with the correct exponent) then reading this number will give
-// 'v' again. The buffer will choose the representation that is closest to
-// 'v'. If there are two at the same distance, than the number is round up.
-// In this mode the 'requested_digits' parameter is ignored.
-// - FIXED: produces digits necessary to print a given number with
-// 'requested_digits' digits after the decimal point. The produced digits
-// might be too short in which case the caller has to fill the gaps with '0's.
-// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
-// Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
-// buffer="2", point=0.
-// Note: the length of the returned buffer has no meaning wrt the significance
-// of its digits. That is, just because it contains '0's does not mean that
-// any other digit would not satisfy the internal identity requirement.
-// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
-// Even though the length of produced digits usually equals
-// 'requested_digits', the function is allowed to return fewer digits, in
-// which case the caller has to fill the missing digits with '0's.
-// Halfway cases are again rounded up.
-// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
-// and a terminating null-character.
-void BignumDtoa(double v,
- BignumDtoaMode mode,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* point);
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_BIGNUM_DTOA_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.cc
deleted file mode 100644
index 07a743c4b2d..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.cc
+++ /dev/null
@@ -1,770 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/bignum.h"
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-Bignum::Bignum()
- : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
- for (int i = 0; i < kBigitCapacity; ++i) {
- bigits_[i] = 0;
- }
-}
-
-template <typename S>
-static int BitSize(S value) {
- return 8 * sizeof(value);
-}
-
-// Guaranteed to lie in one Bigit.
-void Bignum::AssignUInt16(uint16_t value) {
- DCHECK_GE(kBigitSize, BitSize(value));
- Zero();
- if (value == 0)
- return;
-
- EnsureCapacity(1);
- bigits_[0] = value;
- used_digits_ = 1;
-}
-
-void Bignum::AssignUInt64(uint64_t value) {
- const int kUInt64Size = 64;
-
- Zero();
- if (value == 0)
- return;
-
- int needed_bigits = kUInt64Size / kBigitSize + 1;
- EnsureCapacity(needed_bigits);
- for (int i = 0; i < needed_bigits; ++i) {
- bigits_[i] = (uint32_t)value & kBigitMask;
- value = value >> kBigitSize;
- }
- used_digits_ = needed_bigits;
- Clamp();
-}
-
-void Bignum::AssignBignum(const Bignum& other) {
- exponent_ = other.exponent_;
- for (int i = 0; i < other.used_digits_; ++i) {
- bigits_[i] = other.bigits_[i];
- }
- // Clear the excess digits (if there were any).
- for (int i = other.used_digits_; i < used_digits_; ++i) {
- bigits_[i] = 0;
- }
- used_digits_ = other.used_digits_;
-}
-
-static uint64_t ReadUInt64(Vector<const char> buffer,
- int from,
- int digits_to_read) {
- uint64_t result = 0;
- for (int i = from; i < from + digits_to_read; ++i) {
- int digit = buffer[i] - '0';
- DCHECK_LE(0, digit);
- DCHECK_LE(digit, 9);
- result = result * 10 + digit;
- }
- return result;
-}
-
-void Bignum::AssignDecimalString(Vector<const char> value) {
- // 2^64 = 18446744073709551616 > 10^19
- const int kMaxUint64DecimalDigits = 19;
- Zero();
- int length = value.length();
- int pos = 0;
- // Let's just say that each digit needs 4 bits.
- while (length >= kMaxUint64DecimalDigits) {
- uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
- pos += kMaxUint64DecimalDigits;
- length -= kMaxUint64DecimalDigits;
- MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
- AddUInt64(digits);
- }
- uint64_t digits = ReadUInt64(value, pos, length);
- MultiplyByPowerOfTen(length);
- AddUInt64(digits);
- Clamp();
-}
-
-static int HexCharValue(char c) {
- if ('0' <= c && c <= '9')
- return c - '0';
- if ('a' <= c && c <= 'f')
- return 10 + c - 'a';
- if ('A' <= c && c <= 'F')
- return 10 + c - 'A';
- UNREACHABLE();
- return 0; // To make compiler happy.
-}
-
-void Bignum::AssignHexString(Vector<const char> value) {
- Zero();
- int length = value.length();
-
- int needed_bigits = length * 4 / kBigitSize + 1;
- EnsureCapacity(needed_bigits);
- int string_index = length - 1;
- for (int i = 0; i < needed_bigits - 1; ++i) {
- // These bigits are guaranteed to be "full".
- Chunk current_bigit = 0;
- for (int j = 0; j < kBigitSize / 4; j++) {
- current_bigit += HexCharValue(value[string_index--]) << (j * 4);
- }
- bigits_[i] = current_bigit;
- }
- used_digits_ = needed_bigits - 1;
-
- Chunk most_significant_bigit = 0; // Could be = 0;
- for (int j = 0; j <= string_index; ++j) {
- most_significant_bigit <<= 4;
- most_significant_bigit += HexCharValue(value[j]);
- }
- if (most_significant_bigit != 0) {
- bigits_[used_digits_] = most_significant_bigit;
- used_digits_++;
- }
- Clamp();
-}
-
-void Bignum::AddUInt64(uint64_t operand) {
- if (operand == 0)
- return;
- Bignum other;
- other.AssignUInt64(operand);
- AddBignum(other);
-}
-
-void Bignum::AddBignum(const Bignum& other) {
- DCHECK(IsClamped());
- DCHECK(other.IsClamped());
-
- // If this has a greater exponent than other append zero-bigits to this.
- // After this call exponent_ <= other.exponent_.
- Align(other);
-
- // There are two possibilities:
- // aaaaaaaaaaa 0000 (where the 0s represent a's exponent)
- // bbbbb 00000000
- // ----------------
- // ccccccccccc 0000
- // or
- // aaaaaaaaaa 0000
- // bbbbbbbbb 0000000
- // -----------------
- // cccccccccccc 0000
- // In both cases we might need a carry bigit.
-
- EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
- Chunk carry = 0;
- int bigit_pos = other.exponent_ - exponent_;
- DCHECK_GE(bigit_pos, 0);
- for (int i = 0; i < other.used_digits_; ++i) {
- Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
- bigits_[bigit_pos] = sum & kBigitMask;
- carry = sum >> kBigitSize;
- bigit_pos++;
- }
-
- while (carry != 0) {
- Chunk sum = bigits_[bigit_pos] + carry;
- bigits_[bigit_pos] = sum & kBigitMask;
- carry = sum >> kBigitSize;
- bigit_pos++;
- }
- used_digits_ = Max(bigit_pos, used_digits_);
- DCHECK(IsClamped());
-}
-
-void Bignum::SubtractBignum(const Bignum& other) {
- DCHECK(IsClamped());
- DCHECK(other.IsClamped());
- // We require this to be bigger than other.
- DCHECK(LessEqual(other, *this));
-
- Align(other);
-
- int offset = other.exponent_ - exponent_;
- Chunk borrow = 0;
- int i;
- for (i = 0; i < other.used_digits_; ++i) {
- DCHECK((borrow == 0) || (borrow == 1));
- Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
- bigits_[i + offset] = difference & kBigitMask;
- borrow = difference >> (kChunkSize - 1);
- }
- while (borrow != 0) {
- Chunk difference = bigits_[i + offset] - borrow;
- bigits_[i + offset] = difference & kBigitMask;
- borrow = difference >> (kChunkSize - 1);
- ++i;
- }
- Clamp();
-}
-
-void Bignum::ShiftLeft(int shift_amount) {
- if (used_digits_ == 0)
- return;
- exponent_ += shift_amount / kBigitSize;
- int local_shift = shift_amount % kBigitSize;
- EnsureCapacity(used_digits_ + 1);
- BigitsShiftLeft(local_shift);
-}
-
-void Bignum::MultiplyByUInt32(uint32_t factor) {
- if (factor == 1)
- return;
- if (factor == 0) {
- Zero();
- return;
- }
- if (used_digits_ == 0)
- return;
-
- // The product of a bigit with the factor is of size kBigitSize + 32.
- // Assert that this number + 1 (for the carry) fits into double chunk.
- DCHECK_GE(kDoubleChunkSize, kBigitSize + 32 + 1);
- DoubleChunk carry = 0;
- for (int i = 0; i < used_digits_; ++i) {
- DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;
- bigits_[i] = static_cast<Chunk>(product & kBigitMask);
- carry = (product >> kBigitSize);
- }
- while (carry != 0) {
- EnsureCapacity(used_digits_ + 1);
- bigits_[used_digits_] = (uint32_t)carry & kBigitMask;
- used_digits_++;
- carry >>= kBigitSize;
- }
-}
-
-void Bignum::MultiplyByUInt64(uint64_t factor) {
- if (factor == 1)
- return;
- if (factor == 0) {
- Zero();
- return;
- }
- DCHECK_LT(kBigitSize, 32);
- uint64_t carry = 0;
- uint64_t low = factor & 0xFFFFFFFF;
- uint64_t high = factor >> 32;
- for (int i = 0; i < used_digits_; ++i) {
- uint64_t product_low = low * bigits_[i];
- uint64_t product_high = high * bigits_[i];
- uint64_t tmp = (carry & kBigitMask) + product_low;
- bigits_[i] = (uint32_t)tmp & kBigitMask;
- carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
- (product_high << (32 - kBigitSize));
- }
- while (carry != 0) {
- EnsureCapacity(used_digits_ + 1);
- bigits_[used_digits_] = (uint32_t)carry & kBigitMask;
- used_digits_++;
- carry >>= kBigitSize;
- }
-}
-
-void Bignum::MultiplyByPowerOfTen(int exponent) {
- const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
- const uint16_t kFive1 = 5;
- const uint16_t kFive2 = kFive1 * 5;
- const uint16_t kFive3 = kFive2 * 5;
- const uint16_t kFive4 = kFive3 * 5;
- const uint16_t kFive5 = kFive4 * 5;
- const uint16_t kFive6 = kFive5 * 5;
- const uint32_t kFive7 = kFive6 * 5;
- const uint32_t kFive8 = kFive7 * 5;
- const uint32_t kFive9 = kFive8 * 5;
- const uint32_t kFive10 = kFive9 * 5;
- const uint32_t kFive11 = kFive10 * 5;
- const uint32_t kFive12 = kFive11 * 5;
- const uint32_t kFive13 = kFive12 * 5;
- const uint32_t kFive1_to_12[] = {kFive1, kFive2, kFive3, kFive4,
- kFive5, kFive6, kFive7, kFive8,
- kFive9, kFive10, kFive11, kFive12};
-
- DCHECK_GE(exponent, 0);
- if (exponent == 0)
- return;
- if (used_digits_ == 0)
- return;
-
- // We shift by exponent at the end just before returning.
- int remaining_exponent = exponent;
- while (remaining_exponent >= 27) {
- MultiplyByUInt64(kFive27);
- remaining_exponent -= 27;
- }
- while (remaining_exponent >= 13) {
- MultiplyByUInt32(kFive13);
- remaining_exponent -= 13;
- }
- if (remaining_exponent > 0) {
- MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
- }
- ShiftLeft(exponent);
-}
-
-void Bignum::Square() {
- DCHECK(IsClamped());
- int product_length = 2 * used_digits_;
- EnsureCapacity(product_length);
-
- // Comba multiplication: compute each column separately.
- // Example: r = a2a1a0 * b2b1b0.
- // r = 1 * a0b0 +
- // 10 * (a1b0 + a0b1) +
- // 100 * (a2b0 + a1b1 + a0b2) +
- // 1000 * (a2b1 + a1b2) +
- // 10000 * a2b2
- //
- // In the worst case we have to accumulate nb-digits products of
- // digit*digit.
- //
- // Assert that the additional number of bits in a DoubleChunk are enough
- // to sum up used_digits of Bigit*Bigit.
- if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
- UNIMPLEMENTED();
- }
- DoubleChunk accumulator = 0;
- // First shift the digits so we don't overwrite them.
- int copy_offset = used_digits_;
- for (int i = 0; i < used_digits_; ++i) {
- bigits_[copy_offset + i] = bigits_[i];
- }
- // We have two loops to avoid some 'if's in the loop.
- for (int i = 0; i < used_digits_; ++i) {
- // Process temporary digit i with power i.
- // The sum of the two indices must be equal to i.
- int bigit_index1 = i;
- int bigit_index2 = 0;
- // Sum all of the sub-products.
- while (bigit_index1 >= 0) {
- Chunk chunk1 = bigits_[copy_offset + bigit_index1];
- Chunk chunk2 = bigits_[copy_offset + bigit_index2];
- accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
- bigit_index1--;
- bigit_index2++;
- }
- bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
- accumulator >>= kBigitSize;
- }
- for (int i = used_digits_; i < product_length; ++i) {
- int bigit_index1 = used_digits_ - 1;
- int bigit_index2 = i - bigit_index1;
- // Invariant: sum of both indices is again equal to i.
- // Inner loop runs 0 times on last iteration, emptying accumulator.
- while (bigit_index2 < used_digits_) {
- Chunk chunk1 = bigits_[copy_offset + bigit_index1];
- Chunk chunk2 = bigits_[copy_offset + bigit_index2];
- accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
- bigit_index1--;
- bigit_index2++;
- }
- // The overwritten bigits_[i] will never be read in further loop iterations,
- // because bigit_index1 and bigit_index2 are always greater
- // than i - used_digits_.
- bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
- accumulator >>= kBigitSize;
- }
- // Since the result was guaranteed to lie inside the number the
- // accumulator must be 0 now.
- DCHECK_EQ(accumulator, 0u);
-
- // Don't forget to update the used_digits and the exponent.
- used_digits_ = product_length;
- exponent_ *= 2;
- Clamp();
-}
-
-void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
- DCHECK_NE(base, 0);
- DCHECK_GE(power_exponent, 0);
- if (power_exponent == 0) {
- AssignUInt16(1);
- return;
- }
- Zero();
- int shifts = 0;
- // We expect base to be in range 2-32, and most often to be 10.
- // It does not make much sense to implement different algorithms for counting
- // the bits.
- while ((base & 1) == 0) {
- base >>= 1;
- shifts++;
- }
- int bit_size = 0;
- int tmp_base = base;
- while (tmp_base != 0) {
- tmp_base >>= 1;
- bit_size++;
- }
- int final_size = bit_size * power_exponent;
- // 1 extra bigit for the shifting, and one for rounded final_size.
- EnsureCapacity(final_size / kBigitSize + 2);
-
- // Left to Right exponentiation.
- int mask = 1;
- while (power_exponent >= mask)
- mask <<= 1;
-
- // The mask is now pointing to the bit above the most significant 1-bit of
- // power_exponent.
- // Get rid of first 1-bit;
- mask >>= 2;
- uint64_t this_value = base;
-
- bool delayed_multipliciation = false;
- const uint64_t max_32bits = 0xFFFFFFFF;
- while (mask != 0 && this_value <= max_32bits) {
- this_value = this_value * this_value;
- // Verify that there is enough space in this_value to perform the
- // multiplication. The first bit_size bits must be 0.
- if ((power_exponent & mask) != 0) {
- uint64_t base_bits_mask =
- ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
- bool high_bits_zero = (this_value & base_bits_mask) == 0;
- if (high_bits_zero) {
- this_value *= base;
- } else {
- delayed_multipliciation = true;
- }
- }
- mask >>= 1;
- }
- AssignUInt64(this_value);
- if (delayed_multipliciation) {
- MultiplyByUInt32(base);
- }
-
- // Now do the same thing as a bignum.
- while (mask != 0) {
- Square();
- if ((power_exponent & mask) != 0) {
- MultiplyByUInt32(base);
- }
- mask >>= 1;
- }
-
- // And finally add the saved shifts.
- ShiftLeft(shifts * power_exponent);
-}
-
-// Precondition: this/other < 16bit.
-uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
- DCHECK(IsClamped());
- DCHECK(other.IsClamped());
- DCHECK_GT(other.used_digits_, 0);
-
- // Easy case: if we have less digits than the divisor than the result is
- // 0. Note: this handles the case where this == 0, too.
- if (BigitLength() < other.BigitLength()) {
- return 0;
- }
-
- Align(other);
-
- uint16_t result = 0;
-
- // Start by removing multiples of 'other' until both numbers have the same
- // number of digits.
- while (BigitLength() > other.BigitLength()) {
- // This naive approach is extremely inefficient if the this divided other
- // might be big. This function is implemented for doubleToString where
- // the result should be small (less than 10).
- DCHECK_GE(other.bigits_[other.used_digits_ - 1], ((1u << kBigitSize) / 16));
- // Remove the multiples of the first digit.
- // Example this = 23 and other equals 9. -> Remove 2 multiples.
- result += static_cast<uint16_t>(bigits_[used_digits_ - 1]);
- SubtractTimes(other, bigits_[used_digits_ - 1]);
- }
-
- DCHECK_EQ(BigitLength(), other.BigitLength());
-
- // Both bignums are at the same length now.
- // Since other has more than 0 digits we know that the access to
- // bigits_[used_digits_ - 1] is safe.
- Chunk this_bigit = bigits_[used_digits_ - 1];
- Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
-
- if (other.used_digits_ == 1) {
- // Shortcut for easy (and common) case.
- uint16_t quotient = static_cast<uint16_t>(this_bigit / other_bigit);
- bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
- result += quotient;
- Clamp();
- return result;
- }
-
- uint16_t division_estimate =
- static_cast<uint16_t>(this_bigit / (other_bigit + 1));
- result += division_estimate;
- SubtractTimes(other, division_estimate);
-
- if (other_bigit * (division_estimate + 1) > this_bigit) {
- // No need to even try to subtract. Even if other's remaining digits were 0
- // another subtraction would be too much.
- return result;
- }
-
- while (LessEqual(other, *this)) {
- SubtractBignum(other);
- result++;
- }
- return result;
-}
-
-template <typename S>
-static int SizeInHexChars(S number) {
- DCHECK_GT(number, 0u);
- int result = 0;
- while (number != 0) {
- number >>= 4;
- result++;
- }
- return result;
-}
-
-static char HexCharOfValue(uint8_t value) {
- DCHECK_LE(0, value);
- DCHECK_LE(value, 16);
- if (value < 10)
- return value + '0';
- return value - 10 + 'A';
-}
-
-bool Bignum::ToHexString(char* buffer, int buffer_size) const {
- DCHECK(IsClamped());
- // Each bigit must be printable as separate hex-character.
- DCHECK_EQ(kBigitSize % 4, 0);
- const int kHexCharsPerBigit = kBigitSize / 4;
-
- if (used_digits_ == 0) {
- if (buffer_size < 2)
- return false;
- buffer[0] = '0';
- buffer[1] = '\0';
- return true;
- }
- // We add 1 for the terminating '\0' character.
- int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
- SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
- if (needed_chars > buffer_size)
- return false;
- int string_index = needed_chars - 1;
- buffer[string_index--] = '\0';
- for (int i = 0; i < exponent_; ++i) {
- for (int j = 0; j < kHexCharsPerBigit; ++j) {
- buffer[string_index--] = '0';
- }
- }
- for (int i = 0; i < used_digits_ - 1; ++i) {
- Chunk current_bigit = bigits_[i];
- for (int j = 0; j < kHexCharsPerBigit; ++j) {
- buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
- current_bigit >>= 4;
- }
- }
- // And finally the last bigit.
- Chunk most_significant_bigit = bigits_[used_digits_ - 1];
- while (most_significant_bigit != 0) {
- buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
- most_significant_bigit >>= 4;
- }
- return true;
-}
-
-Bignum::Chunk Bignum::BigitAt(int index) const {
- if (index >= BigitLength())
- return 0;
- if (index < exponent_)
- return 0;
- return bigits_[index - exponent_];
-}
-
-int Bignum::Compare(const Bignum& a, const Bignum& b) {
- DCHECK(a.IsClamped());
- DCHECK(b.IsClamped());
- int bigit_length_a = a.BigitLength();
- int bigit_length_b = b.BigitLength();
- if (bigit_length_a < bigit_length_b)
- return -1;
- if (bigit_length_a > bigit_length_b)
- return +1;
- for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {
- Chunk bigit_a = a.BigitAt(i);
- Chunk bigit_b = b.BigitAt(i);
- if (bigit_a < bigit_b)
- return -1;
- if (bigit_a > bigit_b)
- return +1;
- // Otherwise they are equal up to this digit. Try the next digit.
- }
- return 0;
-}
-
-int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
- DCHECK(a.IsClamped());
- DCHECK(b.IsClamped());
- DCHECK(c.IsClamped());
- if (a.BigitLength() < b.BigitLength()) {
- return PlusCompare(b, a, c);
- }
- if (a.BigitLength() + 1 < c.BigitLength())
- return -1;
- if (a.BigitLength() > c.BigitLength())
- return +1;
- // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
- // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
- // of 'a'.
- if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
- return -1;
- }
-
- Chunk borrow = 0;
- // Starting at min_exponent all digits are == 0. So no need to compare them.
- int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);
- for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
- Chunk chunk_a = a.BigitAt(i);
- Chunk chunk_b = b.BigitAt(i);
- Chunk chunk_c = c.BigitAt(i);
- Chunk sum = chunk_a + chunk_b;
- if (sum > chunk_c + borrow) {
- return +1;
- } else {
- borrow = chunk_c + borrow - sum;
- if (borrow > 1)
- return -1;
- borrow <<= kBigitSize;
- }
- }
- if (borrow == 0)
- return 0;
- return -1;
-}
-
-void Bignum::Clamp() {
- while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
- used_digits_--;
- }
- if (used_digits_ == 0) {
- // Zero.
- exponent_ = 0;
- }
-}
-
-bool Bignum::IsClamped() const {
- return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
-}
-
-void Bignum::Zero() {
- for (int i = 0; i < used_digits_; ++i) {
- bigits_[i] = 0;
- }
- used_digits_ = 0;
- exponent_ = 0;
-}
-
-void Bignum::Align(const Bignum& other) {
- if (exponent_ > other.exponent_) {
- // If "X" represents a "hidden" digit (by the exponent) then we are in the
- // following case (a == this, b == other):
- // a: aaaaaaXXXX or a: aaaaaXXX
- // b: bbbbbbX b: bbbbbbbbXX
- // We replace some of the hidden digits (X) of a with 0 digits.
- // a: aaaaaa000X or a: aaaaa0XX
- int zero_digits = exponent_ - other.exponent_;
- EnsureCapacity(used_digits_ + zero_digits);
- for (int i = used_digits_ - 1; i >= 0; --i) {
- bigits_[i + zero_digits] = bigits_[i];
- }
- for (int i = 0; i < zero_digits; ++i) {
- bigits_[i] = 0;
- }
- used_digits_ += zero_digits;
- exponent_ -= zero_digits;
- DCHECK_GE(used_digits_, 0);
- DCHECK_GE(exponent_, 0);
- }
-}
-
-void Bignum::BigitsShiftLeft(int shift_amount) {
- DCHECK_LT(shift_amount, kBigitSize);
- DCHECK_GE(shift_amount, 0);
- Chunk carry = 0;
- for (int i = 0; i < used_digits_; ++i) {
- Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
- bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
- carry = new_carry;
- }
- if (carry != 0) {
- bigits_[used_digits_] = carry;
- used_digits_++;
- }
-}
-
-void Bignum::SubtractTimes(const Bignum& other, int factor) {
- DCHECK_LE(exponent_, other.exponent_);
- if (factor < 3) {
- for (int i = 0; i < factor; ++i) {
- SubtractBignum(other);
- }
- return;
- }
- Chunk borrow = 0;
- int exponent_diff = other.exponent_ - exponent_;
- for (int i = 0; i < other.used_digits_; ++i) {
- DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];
- DoubleChunk remove = borrow + product;
- Chunk difference =
- bigits_[i + exponent_diff] - ((uint32_t)remove & kBigitMask);
- bigits_[i + exponent_diff] = difference & kBigitMask;
- borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
- (remove >> kBigitSize));
- }
- for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
- if (borrow == 0)
- return;
- Chunk difference = bigits_[i] - borrow;
- bigits_[i] = difference & kBigitMask;
- borrow = difference >> (kChunkSize - 1);
- }
- Clamp();
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.h
deleted file mode 100644
index 20caeeb1e5b..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_BIGNUM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_BIGNUM_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-class Bignum {
- DISALLOW_NEW();
-
- public:
- // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
- // This bignum can encode much bigger numbers, since it contains an
- // exponent.
- static const int kMaxSignificantBits = 3584;
-
- Bignum();
- void AssignUInt16(uint16_t value);
- void AssignUInt64(uint64_t value);
- void AssignBignum(const Bignum& other);
-
- void AssignDecimalString(Vector<const char> value);
- void AssignHexString(Vector<const char> value);
-
- void AssignPowerUInt16(uint16_t base, int exponent);
-
- void AddUInt16(uint16_t operand);
- void AddUInt64(uint64_t operand);
- void AddBignum(const Bignum& other);
- // Precondition: this >= other.
- void SubtractBignum(const Bignum& other);
-
- void Square();
- void ShiftLeft(int shift_amount);
- void MultiplyByUInt32(uint32_t factor);
- void MultiplyByUInt64(uint64_t factor);
- void MultiplyByPowerOfTen(int exponent);
- void Times10() { return MultiplyByUInt32(10); }
- // Pseudocode:
- // int result = this / other;
- // this = this % other;
- // In the worst case this function is in O(this/other).
- uint16_t DivideModuloIntBignum(const Bignum& other);
-
- bool ToHexString(char* buffer, int buffer_size) const;
-
- static int Compare(const Bignum& a, const Bignum& b);
- static bool Equal(const Bignum& a, const Bignum& b) {
- return Compare(a, b) == 0;
- }
- static bool LessEqual(const Bignum& a, const Bignum& b) {
- return Compare(a, b) <= 0;
- }
- static bool Less(const Bignum& a, const Bignum& b) {
- return Compare(a, b) < 0;
- }
- // Returns Compare(a + b, c);
- static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);
- // Returns a + b == c
- static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
- return PlusCompare(a, b, c) == 0;
- }
- // Returns a + b <= c
- static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
- return PlusCompare(a, b, c) <= 0;
- }
- // Returns a + b < c
- static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {
- return PlusCompare(a, b, c) < 0;
- }
-
- private:
- typedef uint32_t Chunk;
- typedef uint64_t DoubleChunk;
-
- static const int kChunkSize = sizeof(Chunk) * 8;
- static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
- // With bigit size of 28 we loose some bits, but a double still fits easily
- // into two chunks, and more importantly we can use the Comba multiplication.
- static const int kBigitSize = 28;
- static const Chunk kBigitMask = (1 << kBigitSize) - 1;
- // Every instance allocates kBigitLength chunks on the stack. Bignums cannot
- // grow. There are no checks if the stack-allocated space is sufficient.
- static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
-
- void EnsureCapacity(int size) {
- if (size > kBigitCapacity) {
- UNREACHABLE();
- }
- }
- void Align(const Bignum& other);
- void Clamp();
- bool IsClamped() const;
- void Zero();
- // Requires this to have enough capacity (no tests done).
- // Updates used_digits_ if necessary.
- // shift_amount must be < kBigitSize.
- void BigitsShiftLeft(int shift_amount);
- // BigitLength includes the "hidden" digits encoded in the exponent.
- int BigitLength() const { return used_digits_ + exponent_; }
- Chunk BigitAt(int index) const;
- void SubtractTimes(const Bignum& other, int factor);
-
- Chunk bigits_buffer_[kBigitCapacity];
- // A vector backed by bigits_buffer_. This way accesses to the array are
- // checked for out-of-bounds errors.
- Vector<Chunk> bigits_;
- int used_digits_;
- // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
- int exponent_;
-
- DISALLOW_COPY_AND_ASSIGN(Bignum);
-};
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_BIGNUM_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.cc
deleted file mode 100644
index 653b996f340..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h"
-
-#include <limits.h>
-#include <math.h>
-#include <stdarg.h>
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-struct CachedPower {
- uint64_t significand;
- int16_t binary_exponent;
- int16_t decimal_exponent;
-};
-
-static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
-static const CachedPower kCachedPowers[] = {
- {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
- {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
- {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
- {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
- {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
- {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
- {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
- {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
- {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
- {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
- {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
- {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
- {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
- {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
- {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
- {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
- {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
- {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
- {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
- {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
- {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
- {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
- {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
- {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
- {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
- {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
- {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
- {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
- {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
- {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
- {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
- {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
- {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
- {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
- {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
- {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
- {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
- {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
- {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
- {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
- {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
- {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
- {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
- {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
- {UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
- {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
- {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
- {UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
- {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
- {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
- {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
- {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
- {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
- {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
- {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
- {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
- {UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
- {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
- {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
- {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
- {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
- {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
- {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
- {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
- {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
- {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
- {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
- {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
- {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
- {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
- {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
- {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
- {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
- {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
- {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
- {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
- {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
- {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
- {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
- {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
- {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
- {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
- {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
- {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
- {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
- {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
- {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
-};
-static const int kCachedPowersOffset =
- 348; // -kCachedPowers[0].decimal_exponent
-
-const int PowersOfTenCache::kDecimalExponentDistance =
- 8; // kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent
-const int PowersOfTenCache::kMinDecimalExponent =
- -348; // kCachedPowers[0].decimal_exponent
-const int PowersOfTenCache::kMaxDecimalExponent =
- 340; // kCachedPowers[kCachedPowersLength - 1].decimal_exponent
-
-#if DCHECK_IS_ON()
-static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
-
-// Check that the static constants match the values in kCachedPowers.
-static void ValidateStaticConstants() {
- DCHECK_EQ(kCachedPowersOffset, -kCachedPowers[0].decimal_exponent);
- DCHECK_EQ(
- PowersOfTenCache::kDecimalExponentDistance,
- (kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent));
- DCHECK_EQ(PowersOfTenCache::kMinDecimalExponent,
- kCachedPowers[0].decimal_exponent);
- DCHECK_EQ(PowersOfTenCache::kMaxDecimalExponent,
- kCachedPowers[kCachedPowersLength - 1].decimal_exponent);
-}
-#endif
-
-void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
- int min_exponent,
- int max_exponent,
- DiyFp* power,
- int* decimal_exponent) {
-#if DCHECK_IS_ON()
- ValidateStaticConstants();
-#endif
- const int kQ = DiyFp::kSignificandSize;
- double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
- int foo = kCachedPowersOffset;
- int index = (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
- DCHECK_LE(0, index);
-#if DCHECK_IS_ON()
- DCHECK_LT(index, kCachedPowersLength);
-#endif
- CachedPower cached_power = kCachedPowers[index];
- DCHECK_LE(min_exponent, cached_power.binary_exponent);
- DCHECK_LE(cached_power.binary_exponent, max_exponent);
- *decimal_exponent = cached_power.decimal_exponent;
- *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
-}
-
-void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
- DiyFp* power,
- int* found_exponent) {
- DCHECK_LE(kMinDecimalExponent, requested_exponent);
- DCHECK_LT(requested_exponent, kMaxDecimalExponent + kDecimalExponentDistance);
-#if DCHECK_IS_ON()
- ValidateStaticConstants();
-#endif
- int index =
- (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
- CachedPower cached_power = kCachedPowers[index];
- *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
- *found_exponent = cached_power.decimal_exponent;
- DCHECK_LE(*found_exponent, requested_exponent);
- DCHECK_LT(requested_exponent, *found_exponent + kDecimalExponentDistance);
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h
deleted file mode 100644
index d346aea60da..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_CACHED_POWERS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_CACHED_POWERS_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-class PowersOfTenCache {
- STATIC_ONLY(PowersOfTenCache);
-
- public:
- // Not all powers of ten are cached. The decimal exponent of two neighboring
- // cached numbers will differ by kDecimalExponentDistance.
- static const int kDecimalExponentDistance;
-
- static const int kMinDecimalExponent;
- static const int kMaxDecimalExponent;
-
- // Returns a cached power-of-ten with a binary exponent in the range
- // [min_exponent; max_exponent] (boundaries included).
- static void GetCachedPowerForBinaryExponentRange(int min_exponent,
- int max_exponent,
- DiyFp* power,
- int* decimal_exponent);
-
- // Returns a cached power of ten x ~= 10^k such that
- // k <= decimal_exponent < k + kCachedPowersDecimalDistance.
- // The given decimal_exponent must satisfy
- // kMinDecimalExponent <= requested_exponent, and
- // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
- static void GetCachedPowerForDecimalExponent(int requested_exponent,
- DiyFp* power,
- int* found_exponent);
-};
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_CACHED_POWERS_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.cc
deleted file mode 100644
index 0b28f3105eb..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h"
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-void DiyFp::Multiply(const DiyFp& other) {
- // Simply "emulates" a 128 bit multiplication.
- // However: the resulting number only contains 64 bits. The least
- // significant 64 bits are only used for rounding the most significant 64
- // bits.
- const uint64_t kM32 = 0xFFFFFFFFU;
- uint64_t a = f_ >> 32;
- uint64_t b = f_ & kM32;
- uint64_t c = other.f_ >> 32;
- uint64_t d = other.f_ & kM32;
- uint64_t ac = a * c;
- uint64_t bc = b * c;
- uint64_t ad = a * d;
- uint64_t bd = b * d;
- uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
- // By adding 1U << 31 to tmp we round the final result.
- // Halfway cases will be round up.
- tmp += 1U << 31;
- uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
- e_ += other.e_ + 64;
- f_ = result_f;
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h
deleted file mode 100644
index ce5a189cc86..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_DIY_FP_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DIY_FP_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// This "Do It Yourself Floating Point" class implements a floating-point number
-// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
-// have the most significant bit of the significand set.
-// Multiplication and Subtraction do not normalize their results.
-// DiyFp are not designed to contain special doubles (NaN and Infinity).
-class DiyFp {
- STACK_ALLOCATED();
-
- public:
- static const int kSignificandSize = 64;
-
- DiyFp() : f_(0), e_(0) {}
- DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
-
- // this = this - other.
- // The exponents of both numbers must be the same and the significand of this
- // must be bigger than the significand of other.
- // The result will not be normalized.
- void Subtract(const DiyFp& other) {
- DCHECK_EQ(e_, other.e_);
- DCHECK_GE(f_, other.f_);
- f_ -= other.f_;
- }
-
- // Returns a - b.
- // The exponents of both numbers must be the same and this must be bigger
- // than other. The result will not be normalized.
- static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
- DiyFp result = a;
- result.Subtract(b);
- return result;
- }
-
- // this = this * other.
- void Multiply(const DiyFp& other);
-
- // returns a * b;
- static DiyFp Times(const DiyFp& a, const DiyFp& b) {
- DiyFp result = a;
- result.Multiply(b);
- return result;
- }
-
- void Normalize() {
- DCHECK_NE(f_, 0u);
- uint64_t f = f_;
- int e = e_;
-
- // This method is mainly called for normalizing boundaries. In general
- // boundaries need to be shifted by 10 bits. We thus optimize for this case.
- const uint64_t kK10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
- while ((f & kK10MSBits) == 0) {
- f <<= 10;
- e -= 10;
- }
- while ((f & kUint64MSB) == 0) {
- f <<= 1;
- e--;
- }
- f_ = f;
- e_ = e;
- }
-
- static DiyFp Normalize(const DiyFp& a) {
- DiyFp result = a;
- result.Normalize();
- return result;
- }
-
- uint64_t F() const { return f_; }
- int E() const { return e_; }
-
- void set_f(uint64_t new_value) { f_ = new_value; }
- void set_e(int new_value) { e_ = new_value; }
-
- private:
- static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);
-
- uint64_t f_;
- int e_;
-};
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DIY_FP_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.cc
deleted file mode 100644
index ac604227e16..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.cc
+++ /dev/null
@@ -1,596 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
-
-#include <limits.h>
-#include <math.h>
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/strtod.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
- int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
- static const DoubleToStringConverter converter(flags, "Infinity", "NaN", 'e',
- -6, 21, 6, 0);
- return converter;
-}
-
-bool DoubleToStringConverter::HandleSpecialValues(
- double value,
- StringBuilder* result_builder) const {
- Double double_inspect(value);
- if (double_inspect.IsInfinite()) {
- if (infinity_symbol_ == nullptr)
- return false;
- if (value < 0) {
- result_builder->AddCharacter('-');
- }
- result_builder->AddString(infinity_symbol_);
- return true;
- }
- if (double_inspect.IsNan()) {
- if (nan_symbol_ == nullptr)
- return false;
- result_builder->AddString(nan_symbol_);
- return true;
- }
- return false;
-}
-
-void DoubleToStringConverter::CreateExponentialRepresentation(
- const char* decimal_digits,
- int length,
- int exponent,
- StringBuilder* result_builder) const {
- DCHECK_NE(length, 0);
- result_builder->AddCharacter(decimal_digits[0]);
- if (length != 1) {
- result_builder->AddCharacter('.');
- result_builder->AddSubstring(&decimal_digits[1], length - 1);
- }
- result_builder->AddCharacter(exponent_character_);
- if (exponent < 0) {
- result_builder->AddCharacter('-');
- exponent = -exponent;
- } else {
- if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
- result_builder->AddCharacter('+');
- }
- }
- if (exponent == 0) {
- result_builder->AddCharacter('0');
- return;
- }
- DCHECK_LT(exponent, 1e4);
- const int kMaxExponentLength = 5;
- char buffer[kMaxExponentLength + 1];
- int first_char_pos = kMaxExponentLength;
- buffer[first_char_pos] = '\0';
- while (exponent > 0) {
- buffer[--first_char_pos] = '0' + (exponent % 10);
- exponent /= 10;
- }
- result_builder->AddSubstring(&buffer[first_char_pos],
- kMaxExponentLength - first_char_pos);
-}
-
-void DoubleToStringConverter::CreateDecimalRepresentation(
- const char* decimal_digits,
- int length,
- int decimal_point,
- int digits_after_point,
- StringBuilder* result_builder) const {
- // Create a representation that is padded with zeros if needed.
- if (decimal_point <= 0) {
- // "0.00000decimal_rep".
- result_builder->AddCharacter('0');
- if (digits_after_point > 0) {
- result_builder->AddCharacter('.');
- result_builder->AddPadding('0', -decimal_point);
- DCHECK_LE(length, digits_after_point - (-decimal_point));
- result_builder->AddSubstring(decimal_digits, length);
- int remaining_digits = digits_after_point - (-decimal_point) - length;
- result_builder->AddPadding('0', remaining_digits);
- }
- } else if (decimal_point >= length) {
- // "decimal_rep0000.00000" or "decimal_rep.0000"
- result_builder->AddSubstring(decimal_digits, length);
- result_builder->AddPadding('0', decimal_point - length);
- if (digits_after_point > 0) {
- result_builder->AddCharacter('.');
- result_builder->AddPadding('0', digits_after_point);
- }
- } else {
- // "decima.l_rep000"
- DCHECK_GT(digits_after_point, 0);
- result_builder->AddSubstring(decimal_digits, decimal_point);
- result_builder->AddCharacter('.');
- DCHECK_LE(length - decimal_point, digits_after_point);
- result_builder->AddSubstring(&decimal_digits[decimal_point],
- length - decimal_point);
- int remaining_digits = digits_after_point - (length - decimal_point);
- result_builder->AddPadding('0', remaining_digits);
- }
- if (digits_after_point == 0) {
- if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
- result_builder->AddCharacter('.');
- }
- if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
- result_builder->AddCharacter('0');
- }
- }
-}
-
-bool DoubleToStringConverter::ToShortest(double value,
- StringBuilder* result_builder) const {
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- int decimal_point;
- bool sign;
- const int kDecimalRepCapacity = kBase10MaximalLength + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, &sign,
- &decimal_rep_length, &decimal_point);
-
- bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- int exponent = decimal_point - 1;
- if ((decimal_in_shortest_low_ <= exponent) &&
- (exponent < decimal_in_shortest_high_)) {
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
- Max(0, decimal_rep_length - decimal_point),
- result_builder);
- } else {
- CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
- result_builder);
- }
- return true;
-}
-
-bool DoubleToStringConverter::ToFixed(double value,
- int requested_digits,
- StringBuilder* result_builder) const {
- DCHECK_EQ(kMaxFixedDigitsBeforePoint, 60);
- const double kFirstNonFixed = 1e60;
-
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (requested_digits > kMaxFixedDigitsAfterPoint)
- return false;
- if (value >= kFirstNonFixed || value <= -kFirstNonFixed)
- return false;
-
- // Find a sufficiently precise decimal representation of n.
- int decimal_point;
- bool sign;
- // Add space for the '\0' byte.
- const int kDecimalRepCapacity =
- kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
- DoubleToAscii(value, FIXED, requested_digits, decimal_rep,
- kDecimalRepCapacity, &sign, &decimal_rep_length,
- &decimal_point);
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
- requested_digits, result_builder);
- return true;
-}
-
-bool DoubleToStringConverter::ToExponential(
- double value,
- int requested_digits,
- StringBuilder* result_builder) const {
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (requested_digits < -1)
- return false;
- if (requested_digits > kMaxExponentialDigits)
- return false;
-
- int decimal_point;
- bool sign;
- // Add space for digit before the decimal point and the '\0' character.
- const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
- DCHECK_GT(kDecimalRepCapacity, kBase10MaximalLength);
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- if (requested_digits == -1) {
- DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, &sign,
- &decimal_rep_length, &decimal_point);
- } else {
- DoubleToAscii(value, PRECISION, requested_digits + 1, decimal_rep,
- kDecimalRepCapacity, &sign, &decimal_rep_length,
- &decimal_point);
- DCHECK_LE(decimal_rep_length, requested_digits + 1);
-
- for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
- decimal_rep[i] = '0';
- }
- decimal_rep_length = requested_digits + 1;
- }
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- int exponent = decimal_point - 1;
- CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
- result_builder);
- return true;
-}
-
-bool DoubleToStringConverter::ToPrecision(double value,
- int precision,
- StringBuilder* result_builder) const {
- if (Double(value).IsSpecial()) {
- return HandleSpecialValues(value, result_builder);
- }
-
- if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
- return false;
- }
-
- // Find a sufficiently precise decimal representation of n.
- int decimal_point;
- bool sign;
- // Add one for the terminating null character.
- const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
- char decimal_rep[kDecimalRepCapacity];
- int decimal_rep_length;
-
- DoubleToAscii(value, PRECISION, precision, decimal_rep, kDecimalRepCapacity,
- &sign, &decimal_rep_length, &decimal_point);
- DCHECK_LE(decimal_rep_length, precision);
-
- bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
- if (sign && (value != 0.0 || !unique_zero)) {
- result_builder->AddCharacter('-');
- }
-
- // The exponent if we print the number as x.xxeyyy. That is with the
- // decimal point after the first digit.
- int exponent = decimal_point - 1;
-
- int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
- if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
- (decimal_point - precision + extra_zero >
- max_trailing_padding_zeroes_in_precision_mode_)) {
- // Fill buffer to contain 'precision' digits.
- // Usually the buffer is already at the correct length, but 'DoubleToAscii'
- // is allowed to return less characters.
- for (int i = decimal_rep_length; i < precision; ++i) {
- decimal_rep[i] = '0';
- }
-
- CreateExponentialRepresentation(decimal_rep, precision, exponent,
- result_builder);
- } else {
- CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
- Max(0, precision - decimal_point),
- result_builder);
- }
- return true;
-}
-
-static BignumDtoaMode DtoaToBignumDtoaMode(
- DoubleToStringConverter::DtoaMode dtoa_mode) {
- switch (dtoa_mode) {
- case DoubleToStringConverter::SHORTEST:
- return BIGNUM_DTOA_SHORTEST;
- case DoubleToStringConverter::FIXED:
- return BIGNUM_DTOA_FIXED;
- case DoubleToStringConverter::PRECISION:
- return BIGNUM_DTOA_PRECISION;
- default:
- UNREACHABLE();
- return BIGNUM_DTOA_SHORTEST; // To silence compiler.
- }
-}
-
-void DoubleToStringConverter::DoubleToAscii(double v,
- DtoaMode mode,
- int requested_digits,
- char* buffer,
- int buffer_length,
- bool* sign,
- int* length,
- int* point) {
- Vector<char> vector(buffer, buffer_length);
- DCHECK(!Double(v).IsSpecial());
- DCHECK(mode == SHORTEST || requested_digits >= 0);
-
- if (Double(v).Sign() < 0) {
- *sign = true;
- v = -v;
- } else {
- *sign = false;
- }
-
- if (mode == PRECISION && requested_digits == 0) {
- vector[0] = '\0';
- *length = 0;
- return;
- }
-
- if (v == 0) {
- vector[0] = '0';
- vector[1] = '\0';
- *length = 1;
- *point = 1;
- return;
- }
-
- bool fast_worked;
- switch (mode) {
- case SHORTEST:
- fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
- break;
- case FIXED:
- fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
- break;
- case PRECISION:
- fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, vector,
- length, point);
- break;
- default:
- UNREACHABLE();
- fast_worked = false;
- }
- if (fast_worked)
- return;
-
- // If the fast dtoa didn't succeed use the slower bignum version.
- BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
- BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
- vector[*length] = '\0';
-}
-
-// Maximum number of significant digits in decimal representation.
-// The longest possible double in decimal representation is
-// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
-// (768 digits). If we parse a number whose first digits are equal to a
-// mean of 2 adjacent doubles (that could have up to 769 digits) the result
-// must be rounded to the bigger one unless the tail consists of zeros, so
-// we don't need to preserve all the digits.
-const int kMaxSignificantDigits = 772;
-
-static double SignedZero(bool sign) {
- return sign ? -0.0 : 0.0;
-}
-
-double StringToDoubleConverter::StringToDouble(
- const char* input,
- size_t length,
- size_t* processed_characters_count) {
- const char* current = input;
- const char* end = input + length;
-
- *processed_characters_count = 0;
-
- // To make sure that iterator dereferencing is valid the following
- // convention is used:
- // 1. Each '++current' statement is followed by check for equality to 'end'.
- // 3. If 'current' becomes equal to 'end' the function returns or goes to
- // 'parsing_done'.
- // 4. 'current' is not dereferenced after the 'parsing_done' label.
- // 5. Code before 'parsing_done' may rely on 'current != end'.
- if (current == end)
- return 0.0;
-
- // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
- const int kBufferSize = kMaxSignificantDigits + 10;
- char buffer[kBufferSize]; // NOLINT: size is known at compile time.
- int buffer_pos = 0;
-
- // Exponent will be adjusted if insignificant digits of the integer part
- // or insignificant leading zeros of the fractional part are dropped.
- int exponent = 0;
- int significant_digits = 0;
- int insignificant_digits = 0;
- bool nonzero_digit_dropped = false;
- bool sign = false;
-
- if (*current == '+' || *current == '-') {
- sign = (*current == '-');
- ++current;
- if (current == end)
- return 0.0;
- }
-
- bool leading_zero = false;
- if (*current == '0') {
- ++current;
- if (current == end) {
- *processed_characters_count = current - input;
- return SignedZero(sign);
- }
-
- leading_zero = true;
-
- // Ignore leading zeros in the integer part.
- while (*current == '0') {
- ++current;
- if (current == end) {
- *processed_characters_count = current - input;
- return SignedZero(sign);
- }
- }
- }
-
- // Copy significant digits of the integer part (if any) to the buffer.
- while (*current >= '0' && *current <= '9') {
- if (significant_digits < kMaxSignificantDigits) {
- DCHECK_LT(buffer_pos, kBufferSize);
- buffer[buffer_pos++] = static_cast<char>(*current);
- significant_digits++;
- } else {
- insignificant_digits++; // Move the digit into the exponential part.
- nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
- }
- ++current;
- if (current == end)
- goto parsing_done;
- }
-
- if (*current == '.') {
- ++current;
- if (current == end) {
- if (significant_digits == 0 && !leading_zero) {
- return 0.0;
- } else {
- goto parsing_done;
- }
- }
-
- if (significant_digits == 0) {
- // Integer part consists of 0 or is absent. Significant digits start after
- // leading zeros (if any).
- while (*current == '0') {
- ++current;
- if (current == end) {
- *processed_characters_count = current - input;
- return SignedZero(sign);
- }
- exponent--; // Move this 0 into the exponent.
- }
- }
-
- // There is a fractional part.
- while (*current >= '0' && *current <= '9') {
- if (significant_digits < kMaxSignificantDigits) {
- DCHECK_LT(buffer_pos, kBufferSize);
- buffer[buffer_pos++] = static_cast<char>(*current);
- significant_digits++;
- exponent--;
- } else {
- // Ignore insignificant digits in the fractional part.
- nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
- }
- ++current;
- if (current == end)
- goto parsing_done;
- }
- }
-
- if (!leading_zero && exponent == 0 && significant_digits == 0) {
- // If leading_zeros is true then the string contains zeros.
- // If exponent < 0 then string was [+-]\.0*...
- // If significant_digits != 0 the string is not equal to 0.
- // Otherwise there are no digits in the string.
- return 0.0;
- }
-
- // Parse exponential part.
- if (*current == 'e' || *current == 'E') {
- ++current;
- if (current == end) {
- --current;
- goto parsing_done;
- }
- char sign = 0;
- if (*current == '+' || *current == '-') {
- sign = static_cast<char>(*current);
- ++current;
- if (current == end) {
- current -= 2;
- goto parsing_done;
- }
- }
-
- if (*current < '0' || *current > '9') {
- if (sign)
- --current;
- --current;
- goto parsing_done;
- }
-
- const int max_exponent = INT_MAX / 2;
- DCHECK_LE(-max_exponent / 2, exponent);
- DCHECK_LE(exponent, max_exponent / 2);
- int num = 0;
- do {
- // Check overflow.
- int digit = *current - '0';
- if (num >= max_exponent / 10 &&
- !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
- num = max_exponent;
- } else {
- num = num * 10 + digit;
- }
- ++current;
- } while (current != end && *current >= '0' && *current <= '9');
-
- exponent += (sign == '-' ? -num : num);
- }
-
-parsing_done:
- exponent += insignificant_digits;
-
- if (nonzero_digit_dropped) {
- buffer[buffer_pos++] = '1';
- exponent--;
- }
-
- DCHECK_LT(buffer_pos, kBufferSize);
- buffer[buffer_pos] = '\0';
-
- double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
- *processed_characters_count = current - input;
- return sign ? -converted : converted;
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h
deleted file mode 100644
index fe935ceff97..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_DOUBLE_CONVERSION_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DOUBLE_CONVERSION_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-class DoubleToStringConverter {
- STACK_ALLOCATED();
-
- public:
- // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
- // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
- // function returns false.
- static const int kMaxFixedDigitsBeforePoint = 60;
- static const int kMaxFixedDigitsAfterPoint = 60;
-
- // When calling ToExponential with a requested_digits
- // parameter > kMaxExponentialDigits then the function returns false.
- static const int kMaxExponentialDigits = 120;
-
- // When calling ToPrecision with a requested_digits
- // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
- // then the function returns false.
- static const int kMinPrecisionDigits = 1;
- static const int kMaxPrecisionDigits = 120;
-
- enum Flags {
- NO_FLAGS = 0,
- EMIT_POSITIVE_EXPONENT_SIGN = 1,
- EMIT_TRAILING_DECIMAL_POINT = 2,
- EMIT_TRAILING_ZERO_AFTER_POINT = 4,
- UNIQUE_ZERO = 8
- };
-
- // Flags should be a bit-or combination of the possible Flags-enum.
- // - NO_FLAGS: no special flags.
- // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
- // form, emits a '+' for positive exponents. Example: 1.2e+2.
- // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
- // converted into decimal format then a trailing decimal point is appended.
- // Example: 2345.0 is converted to "2345.".
- // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
- // emits a trailing '0'-character. This flag requires the
- // EXMIT_TRAILING_DECIMAL_POINT flag.
- // Example: 2345.0 is converted to "2345.0".
- // - UNIQUE_ZERO: "-0.0" is converted to "0.0".
- //
- // Infinity symbol and nan_symbol provide the string representation for these
- // special values. If the string is NULL and the special value is encountered
- // then the conversion functions return false.
- //
- // The exponent_character is used in exponential representations. It is
- // usually 'e' or 'E'.
- //
- // When converting to the shortest representation the converter will
- // represent input numbers in decimal format if they are in the interval
- // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
- // (lower boundary included, greater boundary excluded).
- // Example: with decimal_in_shortest_low = -6 and
- // decimal_in_shortest_high = 21:
- // ToShortest(0.000001) -> "0.000001"
- // ToShortest(0.0000001) -> "1e-7"
- // ToShortest(111111111111111111111.0) -> "111111111111111110000"
- // ToShortest(100000000000000000000.0) -> "100000000000000000000"
- // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
- //
- // When converting to precision mode the converter may add
- // max_leading_padding_zeroes before returning the number in exponential
- // format.
- // Example with max_leading_padding_zeroes_in_precision_mode = 6.
- // ToPrecision(0.0000012345, 2) -> "0.0000012"
- // ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarly the converter may add up to
- // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
- // returning an exponential representation. A zero added by the
- // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
- // ToPrecision(230.0, 2) -> "230"
- // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
- // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
- DoubleToStringConverter(int flags,
- const char* infinity_symbol,
- const char* nan_symbol,
- char exponent_character,
- int decimal_in_shortest_low,
- int decimal_in_shortest_high,
- int max_leading_padding_zeroes_in_precision_mode,
- int max_trailing_padding_zeroes_in_precision_mode)
- : flags_(flags),
- infinity_symbol_(infinity_symbol),
- nan_symbol_(nan_symbol),
- exponent_character_(exponent_character),
- decimal_in_shortest_low_(decimal_in_shortest_low),
- decimal_in_shortest_high_(decimal_in_shortest_high),
- max_leading_padding_zeroes_in_precision_mode_(
- max_leading_padding_zeroes_in_precision_mode),
- max_trailing_padding_zeroes_in_precision_mode_(
- max_trailing_padding_zeroes_in_precision_mode) {
- // When 'trailing zero after the point' is set, then 'trailing point'
- // must be set too.
- DCHECK(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
- !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
- }
-
- // Returns a converter following the EcmaScript specification.
- static const DoubleToStringConverter& EcmaScriptConverter();
-
- // Computes the shortest string of digits that correctly represent the input
- // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
- // (see constructor) it then either returns a decimal representation, or an
- // exponential representation.
- // Example with decimal_in_shortest_low = -6,
- // decimal_in_shortest_high = 21,
- // EMIT_POSITIVE_EXPONENT_SIGN activated, and
- // EMIT_TRAILING_DECIMAL_POINT deactivated:
- // ToShortest(0.000001) -> "0.000001"
- // ToShortest(0.0000001) -> "1e-7"
- // ToShortest(111111111111111111111.0) -> "111111111111111110000"
- // ToShortest(100000000000000000000.0) -> "100000000000000000000"
- // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
- //
- // Note: the conversion may round the output if the returned string
- // is accurate enough to uniquely identify the input-number.
- // For example the most precise representation of the double 9e59 equals
- // "899999999999999918767229449717619953810131273674690656206848", but
- // the converter will return the shorter (but still correct) "9e59".
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except when the input value is special and no infinity_symbol or
- // nan_symbol has been given to the constructor.
- bool ToShortest(double value, StringBuilder* result_builder) const;
-
- // Computes a decimal representation with a fixed number of digits after the
- // decimal point. The last emitted digit is rounded.
- //
- // Examples:
- // ToFixed(3.12, 1) -> "3.1"
- // ToFixed(3.1415, 3) -> "3.142"
- // ToFixed(1234.56789, 4) -> "1234.5679"
- // ToFixed(1.23, 5) -> "1.23000"
- // ToFixed(0.1, 4) -> "0.1000"
- // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
- // ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
- // ToFixed(0.1, 17) -> "0.10000000000000001"
- //
- // If requested_digits equals 0, then the tail of the result depends on
- // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
- // Examples, for requested_digits == 0,
- // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
- // - false and false: then 123.45 -> 123
- // 0.678 -> 1
- // - true and false: then 123.45 -> 123.
- // 0.678 -> 1.
- // - true and true: then 123.45 -> 123.0
- // 0.678 -> 1.0
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - 'value' > 10^kMaxFixedDigitsBeforePoint, or
- // - 'requested_digits' > kMaxFixedDigitsAfterPoint.
- // The last two conditions imply that the result will never contain more than
- // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
- // (one additional character for the sign, and one for the decimal point).
- bool ToFixed(double value,
- int requested_digits,
- StringBuilder* result_builder) const;
-
- // Computes a representation in exponential format with requested_digits
- // after the decimal point. The last emitted digit is rounded.
- // If requested_digits equals -1, then the shortest exponential representation
- // is computed.
- //
- // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
- // exponent_character set to 'e'.
- // ToExponential(3.12, 1) -> "3.1e0"
- // ToExponential(5.0, 3) -> "5.000e0"
- // ToExponential(0.001, 2) -> "1.00e-3"
- // ToExponential(3.1415, -1) -> "3.1415e0"
- // ToExponential(3.1415, 4) -> "3.1415e0"
- // ToExponential(3.1415, 3) -> "3.142e0"
- // ToExponential(123456789000000, 3) -> "1.235e14"
- // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
- // ToExponential(1000000000000000019884624838656.0, 32) ->
- // "1.00000000000000001988462483865600e30"
- // ToExponential(1234, 0) -> "1e3"
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - 'requested_digits' > kMaxExponentialDigits.
- // The last condition implies that the result will never contain more than
- // kMaxExponentialDigits + 8 characters (the sign, the digit before the
- // decimal point, the decimal point, the exponent character, the
- // exponent's sign, and at most 3 exponent digits).
- bool ToExponential(double value,
- int requested_digits,
- StringBuilder* result_builder) const;
-
- // Computes 'precision' leading digits of the given 'value' and returns them
- // either in exponential or decimal format, depending on
- // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
- // constructor).
- // The last computed digit is rounded.
- //
- // Example with max_leading_padding_zeroes_in_precision_mode = 6.
- // ToPrecision(0.0000012345, 2) -> "0.0000012"
- // ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarly the converter may add up to
- // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
- // returning an exponential representation. A zero added by the
- // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
- // ToPrecision(230.0, 2) -> "230"
- // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
- // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
- // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
- // EMIT_TRAILING_ZERO_AFTER_POINT:
- // ToPrecision(123450.0, 6) -> "123450"
- // ToPrecision(123450.0, 5) -> "123450"
- // ToPrecision(123450.0, 4) -> "123500"
- // ToPrecision(123450.0, 3) -> "123000"
- // ToPrecision(123450.0, 2) -> "1.2e5"
- //
- // Returns true if the conversion succeeds. The conversion always succeeds
- // except for the following cases:
- // - the input value is special and no infinity_symbol or nan_symbol has
- // been provided to the constructor,
- // - precision < kMinPericisionDigits
- // - precision > kMaxPrecisionDigits
- // The last condition implies that the result will never contain more than
- // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
- // exponent character, the exponent's sign, and at most 3 exponent digits).
- bool ToPrecision(double value,
- int precision,
- StringBuilder* result_builder) const;
-
- enum DtoaMode {
- // Produce the shortest correct representation.
- // For example the output of 0.299999999999999988897 is (the less accurate
- // but correct) 0.3.
- SHORTEST,
- // Produce a fixed number of digits after the decimal point.
- // For instance fixed(0.1, 4) becomes 0.1000
- // If the input number is big, the output will be big.
- FIXED,
- // Fixed number of digits (independent of the decimal point).
- PRECISION
- };
-
- // The maximal number of digits that are needed to emit a double in base 10.
- // A higher precision can be achieved by using more digits, but the shortest
- // accurate representation of any double will never use more digits than
- // kBase10MaximalLength.
- // Note that DoubleToAscii null-terminates its input. So the given buffer
- // should be at least kBase10MaximalLength + 1 characters long.
- static const int kBase10MaximalLength = 17;
-
- // Converts the given double 'v' to ascii.
- // The result should be interpreted as buffer * 10^(point-length).
- //
- // The output depends on the given mode:
- // - SHORTEST: produce the least amount of digits for which the internal
- // identity requirement is still satisfied. If the digits are printed
- // (together with the correct exponent) then reading this number will give
- // 'v' again. The buffer will choose the representation that is closest to
- // 'v'. If there are two at the same distance, than the one farther away
- // from 0 is chosen (halfway cases - ending with 5 - are rounded up).
- // In this mode the 'requested_digits' parameter is ignored.
- // - FIXED: produces digits necessary to print a given number with
- // 'requested_digits' digits after the decimal point. The produced digits
- // might be too short in which case the caller has to fill the remainder
- // with '0's.
- // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
- // Halfway cases are rounded towards +/-Infinity (away from 0). The call
- // toFixed(0.15, 2) thus returns buffer="2", point=0.
- // The returned buffer may contain digits that would be truncated from the
- // shortest representation of the input.
- // - PRECISION: produces 'requested_digits' where the first digit is not '0'.
- // Even though the length of produced digits usually equals
- // 'requested_digits', the function is allowed to return fewer digits, in
- // which case the caller has to fill the missing digits with '0's.
- // Halfway cases are again rounded away from 0.
- // DoubleToAscii expects the given buffer to be big enough to hold all
- // digits and a terminating null-character. In SHORTEST-mode it expects a
- // buffer of at least kBase10MaximalLength + 1. In all other modes the
- // requested_digits parameter (+ 1 for the null-character) limits the size of
- // the output. The given length is only used in debug mode to ensure the
- // buffer is big enough.
- static void DoubleToAscii(double v,
- DtoaMode mode,
- int requested_digits,
- char* buffer,
- int buffer_length,
- bool* sign,
- int* length,
- int* point);
-
- private:
- // If the value is a special value (NaN or Infinity) constructs the
- // corresponding string using the configured infinity/nan-symbol.
- // If either of them is NULL or the value is not special then the
- // function returns false.
- bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
- // Constructs an exponential representation (i.e. 1.234e56).
- // The given exponent assumes a decimal point after the first decimal digit.
- void CreateExponentialRepresentation(const char* decimal_digits,
- int length,
- int exponent,
- StringBuilder* result_builder) const;
- // Creates a decimal representation (i.e 1234.5678).
- void CreateDecimalRepresentation(const char* decimal_digits,
- int length,
- int decimal_point,
- int digits_after_point,
- StringBuilder* result_builder) const;
-
- const int flags_;
- const char* const infinity_symbol_;
- const char* const nan_symbol_;
- const char exponent_character_;
- const int decimal_in_shortest_low_;
- const int decimal_in_shortest_high_;
- const int max_leading_padding_zeroes_in_precision_mode_;
- const int max_trailing_padding_zeroes_in_precision_mode_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
-};
-
-class StringToDoubleConverter {
- STACK_ALLOCATED();
-
- public:
- // Performs the conversion.
- // The output parameter 'processed_characters_count' is set to the number
- // of characters that have been processed to read the number.
- static double StringToDouble(const char* buffer,
- size_t length,
- size_t* processed_characters_count);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
-};
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DOUBLE_CONVERSION_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/double.h
deleted file mode 100644
index 386fc3eb62b..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double.h
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_DOUBLE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DOUBLE_H_
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// We assume that doubles and uint64_t have the same endianness.
-static uint64_t double_to_uint64(double d) {
- return BitCast<uint64_t>(d);
-}
-static double uint64_to_double(uint64_t d64) {
- return BitCast<double>(d64);
-}
-
-// Helper functions for doubles.
-class Double {
- STACK_ALLOCATED();
-
- public:
- static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
- static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
- static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
- static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
- static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
- static const int kSignificandSize = 53;
-
- Double() : d64_(0) {}
- explicit Double(double d) : d64_(double_to_uint64(d)) {}
- explicit Double(uint64_t d64) : d64_(d64) {}
- explicit Double(DiyFp diy_fp) : d64_(DiyFpToUint64(diy_fp)) {}
-
- // The value encoded by this Double must be greater or equal to +0.0.
- // It must not be special (infinity, or NaN).
- DiyFp AsDiyFp() const {
- DCHECK_GT(Sign(), 0);
- DCHECK(!IsSpecial());
- return DiyFp(Significand(), Exponent());
- }
-
- // The value encoded by this Double must be strictly greater than 0.
- DiyFp AsNormalizedDiyFp() const {
- DCHECK_GT(Value(), 0.0);
- uint64_t f = Significand();
- int e = Exponent();
-
- // The current double could be a denormal.
- while ((f & kHiddenBit) == 0) {
- f <<= 1;
- e--;
- }
- // Do the final shifts in one go.
- f <<= DiyFp::kSignificandSize - kSignificandSize;
- e -= DiyFp::kSignificandSize - kSignificandSize;
- return DiyFp(f, e);
- }
-
- // Returns the double's bit as uint64.
- uint64_t AsUint64() const { return d64_; }
-
- // Returns the next greater double. Returns +infinity on input +infinity.
- double NextDouble() const {
- if (d64_ == kInfinity)
- return Double(kInfinity).Value();
- if (Sign() < 0 && Significand() == 0) {
- // -0.0
- return 0.0;
- }
- if (Sign() < 0) {
- return Double(d64_ - 1).Value();
- } else {
- return Double(d64_ + 1).Value();
- }
- }
-
- int Exponent() const {
- if (IsDenormal())
- return kDenormalExponent;
-
- uint64_t d64 = AsUint64();
- int biased_e =
- static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
- return biased_e - kExponentBias;
- }
-
- uint64_t Significand() const {
- uint64_t d64 = AsUint64();
- uint64_t significand = d64 & kSignificandMask;
- if (!IsDenormal()) {
- return significand + kHiddenBit;
- } else {
- return significand;
- }
- }
-
- // Returns true if the double is a denormal.
- bool IsDenormal() const {
- uint64_t d64 = AsUint64();
- return (d64 & kExponentMask) == 0;
- }
-
- // We consider denormals not to be special.
- // Hence only Infinity and NaN are special.
- bool IsSpecial() const {
- uint64_t d64 = AsUint64();
- return (d64 & kExponentMask) == kExponentMask;
- }
-
- bool IsNan() const {
- uint64_t d64 = AsUint64();
- return ((d64 & kExponentMask) == kExponentMask) &&
- ((d64 & kSignificandMask) != 0);
- }
-
- bool IsInfinite() const {
- uint64_t d64 = AsUint64();
- return ((d64 & kExponentMask) == kExponentMask) &&
- ((d64 & kSignificandMask) == 0);
- }
-
- int Sign() const {
- uint64_t d64 = AsUint64();
- return (d64 & kSignMask) == 0 ? 1 : -1;
- }
-
- // Precondition: the value encoded by this Double must be greater or equal
- // than +0.0.
- DiyFp UpperBoundary() const {
- DCHECK_GT(Sign(), 0);
- return DiyFp(Significand() * 2 + 1, Exponent() - 1);
- }
-
- // Computes the two boundaries of this.
- // The bigger boundary (m_plus) is normalized. The lower boundary has the same
- // exponent as m_plus.
- // Precondition: the value encoded by this Double must be greater than 0.
- void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
- DCHECK_GT(Value(), 0.0);
- DiyFp v = this->AsDiyFp();
- bool significand_is_zero = (v.F() == kHiddenBit);
- DiyFp plus = DiyFp::Normalize(DiyFp((v.F() << 1) + 1, v.E() - 1));
- DiyFp minus;
- if (significand_is_zero && v.E() != kDenormalExponent) {
- // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
- // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
- // at a distance of 1e8.
- // The only exception is for the smallest normal: the largest denormal is
- // at the same distance as its successor.
- // Note: denormals have the same exponent as the smallest normals.
- minus = DiyFp((v.F() << 2) - 1, v.E() - 2);
- } else {
- minus = DiyFp((v.F() << 1) - 1, v.E() - 1);
- }
- minus.set_f(minus.F() << (minus.E() - plus.E()));
- minus.set_e(plus.E());
- *out_m_plus = plus;
- *out_m_minus = minus;
- }
-
- double Value() const { return uint64_to_double(d64_); }
-
- // Returns the significand size for a given order of magnitude.
- // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
- // This function returns the number of significant binary digits v will have
- // once it's encoded into a double. In almost all cases this is equal to
- // kSignificandSize. The only exceptions are denormals. They start with
- // leading zeroes and their effective significand-size is hence smaller.
- static int SignificandSizeForOrderOfMagnitude(int order) {
- if (order >= (kDenormalExponent + kSignificandSize)) {
- return kSignificandSize;
- }
- if (order <= kDenormalExponent)
- return 0;
- return order - kDenormalExponent;
- }
-
- static double Infinity() { return Double(kInfinity).Value(); }
-
- static double NaN() { return Double(kNaN).Value(); }
-
- private:
- static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
- static const int kDenormalExponent = -kExponentBias + 1;
- static const int kMaxExponent = 0x7FF - kExponentBias;
- static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
- static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
-
- const uint64_t d64_;
-
- static uint64_t DiyFpToUint64(DiyFp diy_fp) {
- uint64_t significand = diy_fp.F();
- int exponent = diy_fp.E();
- while (significand > kHiddenBit + kSignificandMask) {
- significand >>= 1;
- exponent++;
- }
- if (exponent >= kMaxExponent) {
- return kInfinity;
- }
- if (exponent < kDenormalExponent) {
- return 0;
- }
- while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
- significand <<= 1;
- exponent--;
- }
- uint64_t biased_exponent;
- if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
- biased_exponent = 0;
- } else {
- biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
- }
- return (significand & kSignificandMask) |
- (biased_exponent << kPhysicalSignificandSize);
- }
-};
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_DOUBLE_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.cc
deleted file mode 100644
index 9e703653d3d..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.cc
+++ /dev/null
@@ -1,743 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h"
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/diy-fp.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// The minimal and maximal target exponent define the range of w's binary
-// exponent, where 'w' is the result of multiplying the input by a cached power
-// of ten.
-//
-// A different range might be chosen on a different platform, to optimize digit
-// generation, but a smaller range requires more powers of ten to be cached.
-static const int kMinimalTargetExponent = -60;
-static const int kMaximalTargetExponent = -32;
-
-// Adjusts the last digit of the generated number, and screens out generated
-// solutions that may be inaccurate. A solution may be inaccurate if it is
-// outside the safe interval, or if we cannot prove that it is closer to the
-// input than a neighboring representation of the same length.
-//
-// Input: * buffer containing the digits of too_high / 10^kappa
-// * the buffer's length
-// * distance_too_high_w == (too_high - w).f() * unit
-// * unsafe_interval == (too_high - too_low).f() * unit
-// * rest = (too_high - buffer * 10^kappa).f() * unit
-// * ten_kappa = 10^kappa * unit
-// * unit = the common multiplier
-// Output: returns true if the buffer is guaranteed to contain the closest
-// representable number to the input.
-// Modifies the generated digits in the buffer to approach (round towards) w.
-static bool RoundWeed(Vector<char> buffer,
- int length,
- uint64_t distance_too_high_w,
- uint64_t unsafe_interval,
- uint64_t rest,
- uint64_t ten_kappa,
- uint64_t unit) {
- uint64_t small_distance = distance_too_high_w - unit;
- uint64_t big_distance = distance_too_high_w + unit;
- // Let w_low = too_high - big_distance, and
- // w_high = too_high - small_distance.
- // Note: w_low < w < w_high
- //
- // The real w (* unit) must lie somewhere inside the interval
- // ]w_low; w_high[ (often written as "(w_low; w_high)")
-
- // Basically the buffer currently contains a number in the unsafe interval
- // ]too_low; too_high[ with too_low < w < too_high
- //
- // too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- // ^v 1 unit ^ ^ ^ ^
- // boundary_high --------------------- . . . .
- // ^v 1 unit . . . .
- // - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . .
- // . . ^ . .
- // . big_distance . . .
- // . . . . rest
- // small_distance . . . .
- // v . . . .
- // w_high - - - - - - - - - - - - - - - - - - . . . .
- // ^v 1 unit . . . .
- // w ---------------------------------------- . . . .
- // ^v 1 unit v . . .
- // w_low - - - - - - - - - - - - - - - - - - - - - . . .
- // . . v
- // buffer --------------------------------------------------+-------+--------
- // . .
- // safe_interval .
- // v .
- // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .
- // ^v 1 unit .
- // boundary_low ------------------------- unsafe_interval
- // ^v 1 unit v
- // too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- //
- //
- // Note that the value of buffer could lie anywhere inside the range too_low
- // to too_high.
- //
- // boundary_low, boundary_high and w are approximations of the real boundaries
- // and v (the input number). They are guaranteed to be precise up to one unit.
- // In fact the error is guaranteed to be strictly less than one unit.
- //
- // Anything that lies outside the unsafe interval is guaranteed not to round
- // to v when read again.
- // Anything that lies inside the safe interval is guaranteed to round to v
- // when read again.
- // If the number inside the buffer lies inside the unsafe interval but not
- // inside the safe interval then we simply do not know and bail out (returning
- // false).
- //
- // Similarly we have to take into account the imprecision of 'w' when finding
- // the closest representation of 'w'. If we have two potential
- // representations, and one is closer to both w_low and w_high, then we know
- // it is closer to the actual value v.
- //
- // By generating the digits of too_high we got the largest (closest to
- // too_high) buffer that is still in the unsafe interval. In the case where
- // w_high < buffer < too_high we try to decrement the buffer.
- // This way the buffer approaches (rounds towards) w.
- // There are 3 conditions that stop the decrementation process:
- // 1) the buffer is already below w_high
- // 2) decrementing the buffer would make it leave the unsafe interval
- // 3) decrementing the buffer would yield a number below w_high and farther
- // away than the current number. In other words:
- // (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
- // Instead of using the buffer directly we use its distance to too_high.
- // Conceptually rest ~= too_high - buffer
- // We need to do the following tests in this order to avoid over- and
- // underflows.
- DCHECK_LE(rest, unsafe_interval);
- while (rest < small_distance && // Negated condition 1
- unsafe_interval - rest >= ten_kappa && // Negated condition 2
- (rest + ten_kappa < small_distance || // buffer{-1} > w_high
- small_distance - rest >= rest + ten_kappa - small_distance)) {
- buffer[length - 1]--;
- rest += ten_kappa;
- }
-
- // We have approached w+ as much as possible. We now test if approaching w-
- // would require changing the buffer. If yes, then we have two possible
- // representations close to w, but we cannot decide which one is closer.
- if (rest < big_distance && unsafe_interval - rest >= ten_kappa &&
- (rest + ten_kappa < big_distance ||
- big_distance - rest > rest + ten_kappa - big_distance)) {
- return false;
- }
-
- // Weeding test.
- // The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
- // Since too_low = too_high - unsafe_interval this is equivalent to
- // [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
- // Conceptually we have: rest ~= too_high - buffer
- return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
-}
-
-// Rounds the buffer upwards if the result is closer to v by possibly adding
-// 1 to the buffer. If the precision of the calculation is not sufficient to
-// round correctly, return false.
-// The rounding might shift the whole buffer in which case the kappa is
-// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.
-//
-// If 2*rest > ten_kappa then the buffer needs to be round up.
-// rest can have an error of +/- 1 unit. This function accounts for the
-// imprecision and returns false, if the rounding direction cannot be
-// unambiguously determined.
-//
-// Precondition: rest < ten_kappa.
-static bool RoundWeedCounted(Vector<char> buffer,
- int length,
- uint64_t rest,
- uint64_t ten_kappa,
- uint64_t unit,
- int* kappa) {
- DCHECK_LT(rest, ten_kappa);
- // The following tests are done in a specific order to avoid overflows. They
- // will work correctly with any uint64 values of rest < ten_kappa and unit.
- //
- // If the unit is too big, then we don't know which way to round. For example
- // a unit of 50 means that the real number lies within rest +/- 50. If
- // 10^kappa == 40 then there is no way to tell which way to round.
- if (unit >= ten_kappa)
- return false;
- // Even if unit is just half the size of 10^kappa we are already completely
- // lost. (And after the previous test we know that the expression will not
- // over/underflow.)
- if (ten_kappa - unit <= unit)
- return false;
- // If 2 * (rest + unit) <= 10^kappa we can safely round down.
- if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {
- return true;
- }
- // If 2 * (rest - unit) >= 10^kappa, then we can safely round up.
- if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {
- // Increment the last digit recursively until we find a non '9' digit.
- buffer[length - 1]++;
- for (int i = length - 1; i > 0; --i) {
- if (buffer[i] != '0' + 10)
- break;
- buffer[i] = '0';
- buffer[i - 1]++;
- }
- // If the first digit is now '0'+ 10 we had a buffer with all '9's. With the
- // exception of the first digit all digits are now '0'. Simply switch the
- // first digit to '1' and adjust the kappa. Example: "99" becomes "10" and
- // the power (the kappa) is increased.
- if (buffer[0] == '0' + 10) {
- buffer[0] = '1';
- (*kappa) += 1;
- }
- return true;
- }
- return false;
-}
-
-static const uint32_t kTen4 = 10000;
-static const uint32_t kTen5 = 100000;
-static const uint32_t kTen6 = 1000000;
-static const uint32_t kTen7 = 10000000;
-static const uint32_t kTen8 = 100000000;
-static const uint32_t kTen9 = 1000000000;
-
-// Returns the biggest power of ten that is less than or equal to the given
-// number. We furthermore receive the maximum number of bits 'number' has.
-// If number_bits == 0 then 0^-1 is returned
-// The number of bits must be <= 32.
-// Precondition: number < (1 << (number_bits + 1)).
-static void BiggestPowerTen(uint32_t number,
- int number_bits,
- uint32_t* power,
- int* exponent) {
- DCHECK_LT(number, (uint32_t)(1 << (number_bits + 1)));
-
- switch (number_bits) {
- case 32:
- case 31:
- case 30:
- if (kTen9 <= number) {
- *power = kTen9;
- *exponent = 9;
- break;
- }
- FALLTHROUGH;
- case 29:
- case 28:
- case 27:
- if (kTen8 <= number) {
- *power = kTen8;
- *exponent = 8;
- break;
- }
- FALLTHROUGH;
- case 26:
- case 25:
- case 24:
- if (kTen7 <= number) {
- *power = kTen7;
- *exponent = 7;
- break;
- }
- FALLTHROUGH;
- case 23:
- case 22:
- case 21:
- case 20:
- if (kTen6 <= number) {
- *power = kTen6;
- *exponent = 6;
- break;
- }
- FALLTHROUGH;
- case 19:
- case 18:
- case 17:
- if (kTen5 <= number) {
- *power = kTen5;
- *exponent = 5;
- break;
- }
- FALLTHROUGH;
- case 16:
- case 15:
- case 14:
- if (kTen4 <= number) {
- *power = kTen4;
- *exponent = 4;
- break;
- }
- FALLTHROUGH;
- case 13:
- case 12:
- case 11:
- case 10:
- if (1000 <= number) {
- *power = 1000;
- *exponent = 3;
- break;
- }
- FALLTHROUGH;
- case 9:
- case 8:
- case 7:
- if (100 <= number) {
- *power = 100;
- *exponent = 2;
- break;
- }
- FALLTHROUGH;
- case 6:
- case 5:
- case 4:
- if (10 <= number) {
- *power = 10;
- *exponent = 1;
- break;
- }
- FALLTHROUGH;
- case 3:
- case 2:
- case 1:
- if (1 <= number) {
- *power = 1;
- *exponent = 0;
- break;
- }
- FALLTHROUGH;
- case 0:
- *power = 0;
- *exponent = -1;
- break;
- default:
- // Following assignments are here to silence compiler warnings.
- *power = 0;
- *exponent = 0;
- UNREACHABLE();
- }
-}
-
-// Generates the digits of input number w.
-// w is a floating-point number (DiyFp), consisting of a significand and an
-// exponent. Its exponent is bounded by kMinimalTargetExponent and
-// kMaximalTargetExponent.
-// Hence -60 <= w.e() <= -32.
-//
-// Returns false if it fails, in which case the generated digits in the buffer
-// should not be used.
-// Preconditions:
-// * low, w and high are correct up to 1 ulp (unit in the last place). That
-// is, their error must be less than a unit of their last digits.
-// * low.e() == w.e() == high.e()
-// * low < w < high, and taking into account their error: low~ <= high~
-// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
-// Postconditions: returns false if procedure fails.
-// otherwise:
-// * buffer is not null-terminated, but len contains the number of digits.
-// * buffer contains the shortest possible decimal digit-sequence
-// such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
-// correct values of low and high (without their error).
-// * if more than one decimal representation gives the minimal number of
-// decimal digits then the one closest to W (where W is the correct value
-// of w) is chosen.
-// Remark: this procedure takes into account the imprecision of its input
-// numbers. If the precision is not enough to guarantee all the postconditions
-// then false is returned. This usually happens rarely (~0.5%).
-//
-// Say, for the sake of example, that
-// w.e() == -48, and w.f() == 0x1234567890abcdef
-// w's value can be computed by w.f() * 2^w.e()
-// We can obtain w's integral digits by simply shifting w.f() by -w.e().
-// -> w's integral part is 0x1234
-// w's fractional part is therefore 0x567890abcdef.
-// Printing w's integral part is easy (simply print 0x1234 in decimal).
-// In order to print its fraction we repeatedly multiply the fraction by 10 and
-// get each digit. Example the first digit after the point would be computed by
-// (0x567890abcdef * 10) >> 48. -> 3
-// The whole thing becomes slightly more complicated because we want to stop
-// once we have enough digits. That is, once the digits inside the buffer
-// represent 'w' we can stop. Everything inside the interval low - high
-// represents w. However we have to pay attention to low, high and w's
-// imprecision.
-static bool DigitGen(DiyFp low,
- DiyFp w,
- DiyFp high,
- Vector<char> buffer,
- int* length,
- int* kappa) {
- DCHECK_EQ(low.E(), w.E());
- DCHECK_EQ(w.E(), high.E());
- DCHECK_LE(low.F() + 1, high.F() - 1);
- DCHECK_LE(kMinimalTargetExponent, w.E());
- DCHECK_LE(w.E(), kMaximalTargetExponent);
- // low, w and high are imprecise, but by less than one ulp (unit in the
- // last place). If we remove (resp. add) 1 ulp from low (resp. high) we
- // are certain that the new numbers are outside of the interval we want
- // the final representation to lie in. Inversely adding (resp. removing) 1
- // ulp from low (resp. high) would yield numbers that are certain to lie
- // in the interval. We will use this fact later on. We will now start by
- // generating the digits within the uncertain interval. Later we will weed
- // out representations that lie outside the safe interval and thus _might_
- // lie outside the correct interval.
- uint64_t unit = 1;
- DiyFp too_low = DiyFp(low.F() - unit, low.E());
- DiyFp too_high = DiyFp(high.F() + unit, high.E());
- // too_low and too_high are guaranteed to lie outside the interval we want
- // the generated number in.
- DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
- // We now cut the input number into two parts: the integral digits and the
- // fractionals. We will not write any decimal separator though, but adapt
- // kappa instead.
- // Reminder: we are currently computing the digits (stored inside the
- // buffer) such that: too_low < buffer * 10^kappa < too_high We use
- // too_high for the digit_generation and stop as soon as possible. If we
- // stop early we effectively round down.
- DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.E(), w.E());
- // Division by one is a shift.
- uint32_t integrals = static_cast<uint32_t>(too_high.F() >> -one.E());
- // Modulo by one is an and.
- uint64_t fractionals = too_high.F() & (one.F() - 1);
- uint32_t divisor;
- int divisor_exponent;
- BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.E()), &divisor,
- &divisor_exponent);
- *kappa = divisor_exponent + 1;
- *length = 0;
- // Loop invariant: buffer = too_high / 10^kappa (integer division)
- // The invariant holds for the first iteration: kappa has been initialized
- // with the divisor exponent + 1. And the divisor is the biggest power of
- // ten that is smaller than integrals.
- while (*kappa > 0) {
- char digit = static_cast<char>(integrals / divisor);
- buffer[*length] = '0' + digit;
- (*length)++;
- integrals %= divisor;
- (*kappa)--;
- // Note that kappa now equals the exponent of the divisor and that the
- // invariant thus holds again.
- uint64_t rest =
- (static_cast<uint64_t>(integrals) << -one.E()) + fractionals;
- // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
- // Reminder: unsafe_interval.e() == one.e()
- if (rest < unsafe_interval.F()) {
- // Rounding down (by not emitting the remaining digits) yields a
- // number that lies within the unsafe interval.
- return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).F(),
- unsafe_interval.F(), rest,
- static_cast<uint64_t>(divisor) << -one.E(), unit);
- }
- divisor /= 10;
- }
-
- // The integrals have been generated. We are at the point of the decimal
- // separator. In the following loop we simply multiply the remaining digits by
- // 10 and divide by one. We just need to pay attention to multiply associated
- // data (like the interval or 'unit'), too.
- // Note that the multiplication by 10 does not overflow, because w.e >= -60
- // and thus one.e >= -60.
- DCHECK_GE(one.E(), -60);
- DCHECK_LT(fractionals, one.F());
- DCHECK_GE(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10, one.F());
- while (true) {
- fractionals *= 10;
- unit *= 10;
- unsafe_interval.set_f(unsafe_interval.F() * 10);
- // Integer division by one.
- char digit = static_cast<char>(fractionals >> -one.E());
- buffer[*length] = '0' + digit;
- (*length)++;
- fractionals &= one.F() - 1; // Modulo by one.
- (*kappa)--;
- if (fractionals < unsafe_interval.F()) {
- return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).F() * unit,
- unsafe_interval.F(), fractionals, one.F(), unit);
- }
- }
-}
-
-// Generates (at most) requested_digits digits of input number w.
-// w is a floating-point number (DiyFp), consisting of a significand and an
-// exponent. Its exponent is bounded by kMinimalTargetExponent and
-// kMaximalTargetExponent.
-// Hence -60 <= w.e() <= -32.
-//
-// Returns false if it fails, in which case the generated digits in the buffer
-// should not be used.
-// Preconditions:
-// * w is correct up to 1 ulp (unit in the last place). That
-// is, its error must be strictly less than a unit of its last digit.
-// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
-//
-// Postconditions: returns false if procedure fails.
-// otherwise:
-// * buffer is not null-terminated, but length contains the number of
-// digits.
-// * the representation in buffer is the most precise representation of
-// requested_digits digits.
-// * buffer contains at most requested_digits digits of w. If there are less
-// than requested_digits digits then some trailing '0's have been removed.
-// * kappa is such that
-// w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.
-//
-// Remark: This procedure takes into account the imprecision of its input
-// numbers. If the precision is not enough to guarantee all the postconditions
-// then false is returned. This usually happens rarely, but the failure-rate
-// increases with higher requested_digits.
-static bool DigitGenCounted(DiyFp w,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* kappa) {
- DCHECK_LE(kMinimalTargetExponent, w.E());
- DCHECK_LE(w.E(), kMaximalTargetExponent);
- DCHECK_GE(kMinimalTargetExponent, -60);
- DCHECK_LE(kMaximalTargetExponent, -32);
- // w is assumed to have an error less than 1 unit. Whenever w is scaled we
- // also scale its error.
- uint64_t w_error = 1;
- // We cut the input number into two parts: the integral digits and the
- // fractional digits. We don't emit any decimal separator, but adapt kappa
- // instead. Example: instead of writing "1.2" we put "12" into the buffer
- // and increase kappa by 1.
- DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.E(), w.E());
- // Division by one is a shift.
- uint32_t integrals = static_cast<uint32_t>(w.F() >> -one.E());
- // Modulo by one is an and.
- uint64_t fractionals = w.F() & (one.F() - 1);
- uint32_t divisor;
- int divisor_exponent;
- BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.E()), &divisor,
- &divisor_exponent);
- *kappa = divisor_exponent + 1;
- *length = 0;
-
- // Loop invariant: buffer = w / 10^kappa (integer division)
- // The invariant holds for the first iteration: kappa has been initialized
- // with the divisor exponent + 1. And the divisor is the biggest power of
- // ten that is smaller than 'integrals'.
- while (*kappa > 0) {
- char digit = static_cast<char>(integrals / divisor);
- buffer[*length] = '0' + digit;
- (*length)++;
- requested_digits--;
- integrals %= divisor;
- (*kappa)--;
- // Note that kappa now equals the exponent of the divisor and that the
- // invariant thus holds again.
- if (requested_digits == 0)
- break;
- divisor /= 10;
- }
-
- if (requested_digits == 0) {
- uint64_t rest =
- (static_cast<uint64_t>(integrals) << -one.E()) + fractionals;
- return RoundWeedCounted(buffer, *length, rest,
- static_cast<uint64_t>(divisor) << -one.E(), w_error,
- kappa);
- }
-
- // The integrals have been generated. We are at the point of the decimal
- // separator. In the following loop we simply multiply the remaining digits by
- // 10 and divide by one. We just need to pay attention to multiply associated
- // data (the 'unit'), too.
- // Note that the multiplication by 10 does not overflow, because w.e >= -60
- // and thus one.e >= -60.
- DCHECK_GE(one.E(), -60);
- DCHECK_LT(fractionals, one.F());
- DCHECK_GE(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10, one.F());
- while (requested_digits > 0 && fractionals > w_error) {
- fractionals *= 10;
- w_error *= 10;
- // Integer division by one.
- char digit = static_cast<char>(fractionals >> -one.E());
- buffer[*length] = '0' + digit;
- (*length)++;
- requested_digits--;
- fractionals &= one.F() - 1; // Modulo by one.
- (*kappa)--;
- }
- if (requested_digits != 0)
- return false;
- return RoundWeedCounted(buffer, *length, fractionals, one.F(), w_error,
- kappa);
-}
-
-// Provides a decimal representation of v.
-// Returns true if it succeeds, otherwise the result cannot be trusted.
-// There will be *length digits inside the buffer (not null-terminated).
-// If the function returns true then
-// v == (double) (buffer * 10^decimal_exponent).
-// The digits in the buffer are the shortest representation possible: no
-// 0.09999999999999999 instead of 0.1. The shorter representation will even be
-// chosen even if the longer one would be closer to v.
-// The last digit will be closest to the actual v. That is, even if several
-// digits might correctly yield 'v' when read again, the closest will be
-// computed.
-static bool Grisu3(double v,
- Vector<char> buffer,
- int* length,
- int* decimal_exponent) {
- DiyFp w = Double(v).AsNormalizedDiyFp();
- // boundary_minus and boundary_plus are the boundaries between v and its
- // closest floating-point neighbors. Any number strictly between
- // boundary_minus and boundary_plus will round to v when convert to a double.
- // Grisu3 will never output representations that lie exactly on a boundary.
- DiyFp boundary_minus, boundary_plus;
- Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
- DCHECK_EQ(boundary_plus.E(), w.E());
- DiyFp ten_mk; // Cached power of ten: 10^-k
- int mk; // -k
- int ten_mk_minimal_binary_exponent =
- kMinimalTargetExponent - (w.E() + DiyFp::kSignificandSize);
- int ten_mk_maximal_binary_exponent =
- kMaximalTargetExponent - (w.E() + DiyFp::kSignificandSize);
- PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
- ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent, &ten_mk,
- &mk);
- DCHECK_LE(kMinimalTargetExponent,
- w.E() + ten_mk.E() + DiyFp::kSignificandSize);
- DCHECK_GE(kMaximalTargetExponent,
- w.E() + ten_mk.E() + DiyFp::kSignificandSize);
- // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
- // 64 bit significand and ten_mk is thus only precise up to 64 bits.
-
- // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
- // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
- // off by a small amount.
- // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
- // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
- // (f-1) * 2^e < w*10^k < (f+1) * 2^e
- DiyFp scaled_w = DiyFp::Times(w, ten_mk);
- DCHECK_EQ(scaled_w.E(),
- boundary_plus.E() + ten_mk.E() + DiyFp::kSignificandSize);
- // In theory it would be possible to avoid some recomputations by computing
- // the difference between w and boundary_minus/plus (a power of 2) and to
- // compute scaled_boundary_minus/plus by subtracting/adding from
- // scaled_w. However the code becomes much less readable and the speed
- // enhancements are not terriffic.
- DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
- DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
-
- // DigitGen will generate the digits of scaled_w. Therefore we have
- // v == (double) (scaled_w * 10^-mk).
- // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
- // integer than it will be updated. For instance if scaled_w == 1.23 then
- // the buffer will be filled with "123" und the decimal_exponent will be
- // decreased by 2.
- int kappa;
- bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
- buffer, length, &kappa);
- *decimal_exponent = -mk + kappa;
- return result;
-}
-
-// The "counted" version of grisu3 (see above) only generates requested_digits
-// number of digits. This version does not generate the shortest representation,
-// and with enough requested digits 0.1 will at some point print as 0.9999999...
-// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
-// therefore the rounding strategy for halfway cases is irrelevant.
-static bool Grisu3Counted(double v,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* decimal_exponent) {
- DiyFp w = Double(v).AsNormalizedDiyFp();
- DiyFp ten_mk; // Cached power of ten: 10^-k
- int mk; // -k
- int ten_mk_minimal_binary_exponent =
- kMinimalTargetExponent - (w.E() + DiyFp::kSignificandSize);
- int ten_mk_maximal_binary_exponent =
- kMaximalTargetExponent - (w.E() + DiyFp::kSignificandSize);
- PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
- ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent, &ten_mk,
- &mk);
- DCHECK_LE(kMinimalTargetExponent,
- w.E() + ten_mk.E() + DiyFp::kSignificandSize);
- DCHECK_GE(kMaximalTargetExponent,
- w.E() + ten_mk.E() + DiyFp::kSignificandSize);
- // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
- // 64 bit significand and ten_mk is thus only precise up to 64 bits.
-
- // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
- // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
- // off by a small amount.
- // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
- // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
- // (f-1) * 2^e < w*10^k < (f+1) * 2^e
- DiyFp scaled_w = DiyFp::Times(w, ten_mk);
-
- // We now have (double) (scaled_w * 10^-mk).
- // DigitGen will generate the first requested_digits digits of scaled_w and
- // return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It
- // will not always be exactly the same since DigitGenCounted only produces a
- // limited number of digits.)
- int kappa;
- bool result =
- DigitGenCounted(scaled_w, requested_digits, buffer, length, &kappa);
- *decimal_exponent = -mk + kappa;
- return result;
-}
-
-bool FastDtoa(double v,
- FastDtoaMode mode,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* decimal_point) {
- DCHECK_GT(v, 0);
- DCHECK(!Double(v).IsSpecial());
-
- bool result = false;
- int decimal_exponent = 0;
- switch (mode) {
- case FAST_DTOA_SHORTEST:
- result = Grisu3(v, buffer, length, &decimal_exponent);
- break;
- case FAST_DTOA_PRECISION:
- result =
- Grisu3Counted(v, requested_digits, buffer, length, &decimal_exponent);
- break;
- default:
- UNREACHABLE();
- }
- if (result) {
- *decimal_point = *length + decimal_exponent;
- buffer[*length] = '\0';
- }
- return result;
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h
deleted file mode 100644
index e1c7305c5f5..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fast-dtoa.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_FAST_DTOA_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_FAST_DTOA_H_
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-enum FastDtoaMode {
- // Computes the shortest representation of the given input. The returned
- // result will be the most accurate number of this length. Longer
- // representations might be more accurate.
- FAST_DTOA_SHORTEST,
- // Computes a representation where the precision (number of digits) is
- // given as input. The precision is independent of the decimal point.
- FAST_DTOA_PRECISION
-};
-
-// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not
-// include the terminating '\0' character.
-static const int kFastDtoaMaximalLength = 17;
-
-// Provides a decimal representation of v.
-// The result should be interpreted as buffer * 10^(point - length).
-//
-// Precondition:
-// * v must be a strictly positive finite double.
-//
-// Returns true if it succeeds, otherwise the result can not be trusted.
-// There will be *length digits inside the buffer followed by a null terminator.
-// If the function returns true and mode equals
-// - FAST_DTOA_SHORTEST, then
-// the parameter requested_digits is ignored.
-// The result satisfies
-// v == (double) (buffer * 10^(point - length)).
-// The digits in the buffer are the shortest representation possible. E.g.
-// if 0.099999999999 and 0.1 represent the same double then "1" is returned
-// with point = 0.
-// The last digit will be closest to the actual v. That is, even if several
-// digits might correctly yield 'v' when read again, the buffer will contain
-// the one closest to v.
-// - FAST_DTOA_PRECISION, then
-// the buffer contains requested_digits digits.
-// the difference v - (buffer * 10^(point-length)) is closest to zero for
-// all possible representations of requested_digits digits.
-// If there are two values that are equally close, then FastDtoa returns
-// false.
-// For both modes the buffer must be large enough to hold the result.
-bool FastDtoa(double d,
- FastDtoaMode mode,
- int requested_digits,
- Vector<char> buffer,
- int* length,
- int* decimal_point);
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_FAST_DTOA_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc
deleted file mode 100644
index 57616a9cd77..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h"
-
-#include <math.h>
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// Represents a 128bit type. This class should be replaced by a native type on
-// platforms that support 128bit integers.
-class UInt128 {
- STACK_ALLOCATED();
-
- public:
- UInt128() : high_bits_(0), low_bits_(0) {}
- UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) {}
-
- void Multiply(uint32_t multiplicand) {
- uint64_t accumulator;
-
- accumulator = (low_bits_ & kMask32) * multiplicand;
- uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
- accumulator >>= 32;
- accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
- low_bits_ = (accumulator << 32) + part;
- accumulator >>= 32;
- accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
- part = static_cast<uint32_t>(accumulator & kMask32);
- accumulator >>= 32;
- accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
- high_bits_ = (accumulator << 32) + part;
- DCHECK_EQ((accumulator >> 32), 0u);
- }
-
- void Shift(int shift_amount) {
- DCHECK_LE(-64, shift_amount);
- DCHECK_LE(shift_amount, 64);
- if (shift_amount == 0) {
- return;
- } else if (shift_amount == -64) {
- high_bits_ = low_bits_;
- low_bits_ = 0;
- } else if (shift_amount == 64) {
- low_bits_ = high_bits_;
- high_bits_ = 0;
- } else if (shift_amount <= 0) {
- high_bits_ <<= -shift_amount;
- high_bits_ += low_bits_ >> (64 + shift_amount);
- low_bits_ <<= -shift_amount;
- } else {
- low_bits_ >>= shift_amount;
- low_bits_ += high_bits_ << (64 - shift_amount);
- high_bits_ >>= shift_amount;
- }
- }
-
- // Modifies *this to *this MOD (2^power).
- // Returns *this DIV (2^power).
- int DivModPowerOf2(int power) {
- if (power >= 64) {
- int result = static_cast<int>(high_bits_ >> (power - 64));
- high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
- return result;
- } else {
- uint64_t part_low = low_bits_ >> power;
- uint64_t part_high = high_bits_ << (64 - power);
- int result = static_cast<int>(part_low + part_high);
- high_bits_ = 0;
- low_bits_ -= part_low << power;
- return result;
- }
- }
-
- bool IsZero() const { return high_bits_ == 0 && low_bits_ == 0; }
-
- int BitAt(int position) {
- if (position >= 64) {
- return static_cast<int>(high_bits_ >> (position - 64)) & 1;
- } else {
- return static_cast<int>(low_bits_ >> position) & 1;
- }
- }
-
- private:
- static const uint64_t kMask32 = 0xFFFFFFFF;
- // Value == (high_bits_ << 64) + low_bits_
- uint64_t high_bits_;
- uint64_t low_bits_;
-};
-
-static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
-
-static void FillDigits32FixedLength(uint32_t number,
- int requested_length,
- Vector<char> buffer,
- int* length) {
- for (int i = requested_length - 1; i >= 0; --i) {
- buffer[(*length) + i] = '0' + number % 10;
- number /= 10;
- }
- *length += requested_length;
-}
-
-static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
- int number_length = 0;
- // We fill the digits in reverse order and exchange them afterwards.
- while (number != 0) {
- char digit = number % 10;
- number /= 10;
- buffer[(*length) + number_length] = '0' + digit;
- number_length++;
- }
- // Exchange the digits.
- int i = *length;
- int j = *length + number_length - 1;
- while (i < j) {
- char tmp = buffer[i];
- buffer[i] = buffer[j];
- buffer[j] = tmp;
- i++;
- j--;
- }
- *length += number_length;
-}
-
-static void FillDigits64FixedLength(uint64_t number,
- int,
- Vector<char> buffer,
- int* length) {
- const uint32_t kTen7 = 10000000;
- // For efficiency cut the number into 3 uint32_t parts, and print those.
- uint32_t part2 = static_cast<uint32_t>(number % kTen7);
- number /= kTen7;
- uint32_t part1 = static_cast<uint32_t>(number % kTen7);
- uint32_t part0 = static_cast<uint32_t>(number / kTen7);
-
- FillDigits32FixedLength(part0, 3, buffer, length);
- FillDigits32FixedLength(part1, 7, buffer, length);
- FillDigits32FixedLength(part2, 7, buffer, length);
-}
-
-static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
- const uint32_t kTen7 = 10000000;
- // For efficiency cut the number into 3 uint32_t parts, and print those.
- uint32_t part2 = static_cast<uint32_t>(number % kTen7);
- number /= kTen7;
- uint32_t part1 = static_cast<uint32_t>(number % kTen7);
- uint32_t part0 = static_cast<uint32_t>(number / kTen7);
-
- if (part0 != 0) {
- FillDigits32(part0, buffer, length);
- FillDigits32FixedLength(part1, 7, buffer, length);
- FillDigits32FixedLength(part2, 7, buffer, length);
- } else if (part1 != 0) {
- FillDigits32(part1, buffer, length);
- FillDigits32FixedLength(part2, 7, buffer, length);
- } else {
- FillDigits32(part2, buffer, length);
- }
-}
-
-static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
- // An empty buffer represents 0.
- if (*length == 0) {
- buffer[0] = '1';
- *decimal_point = 1;
- *length = 1;
- return;
- }
- // Round the last digit until we either have a digit that was not '9' or until
- // we reached the first digit.
- buffer[(*length) - 1]++;
- for (int i = (*length) - 1; i > 0; --i) {
- if (buffer[i] != '0' + 10) {
- return;
- }
- buffer[i] = '0';
- buffer[i - 1]++;
- }
- // If the first digit is now '0' + 10, we would need to set it to '0' and add
- // a '1' in front. However we reach the first digit only if all following
- // digits had been '9' before rounding up. Now all trailing digits are '0' and
- // we simply switch the first digit to '1' and update the decimal-point
- // (indicating that the point is now one digit to the right).
- if (buffer[0] == '0' + 10) {
- buffer[0] = '1';
- (*decimal_point)++;
- }
-}
-
-// The given fractionals number represents a fixed-point number with binary
-// point at bit (-exponent).
-// Preconditions:
-// -128 <= exponent <= 0.
-// 0 <= fractionals * 2^exponent < 1
-// The buffer holds the result.
-// The function will round its result. During the rounding-process digits not
-// generated by this function might be updated, and the decimal-point variable
-// might be updated. If this function generates the digits 99 and the buffer
-// already contained "199" (thus yielding a buffer of "19999") then a
-// rounding-up will change the contents of the buffer to "20000".
-static void FillFractionals(uint64_t fractionals,
- int exponent,
- int fractional_count,
- Vector<char> buffer,
- int* length,
- int* decimal_point) {
- DCHECK_LE(-128, exponent);
- DCHECK_LE(exponent, 0);
- // 'fractionals' is a fixed-point number, with binary point at bit
- // (-exponent). Inside the function the non-converted remainder of fractionals
- // is a fixed-point number, with binary point at bit 'point'.
- if (-exponent <= 64) {
- // One 64 bit number is sufficient.
- DCHECK(fractionals >> 56 == 0);
- int point = -exponent;
- for (int i = 0; i < fractional_count; ++i) {
- if (fractionals == 0)
- break;
- // Instead of multiplying by 10 we multiply by 5 and adjust the point
- // location. This way the fractionals variable will not overflow.
- // Invariant at the beginning of the loop: fractionals < 2^point.
- // Initially we have: point <= 64 and fractionals < 2^56
- // After each iteration the point is decremented by one.
- // Note that 5^3 = 125 < 128 = 2^7.
- // Therefore three iterations of this loop will not overflow fractionals
- // (even without the subtraction at the end of the loop body). At this
- // time point will satisfy point <= 61 and therefore fractionals < 2^point
- // and any further multiplication of fractionals by 5 will not overflow.
- fractionals *= 5;
- point--;
- char digit = static_cast<char>(fractionals >> point);
- buffer[*length] = '0' + digit;
- (*length)++;
- fractionals -= static_cast<uint64_t>(digit) << point;
- }
- // If the first bit after the point is set we have to round up.
- if (((fractionals >> (point - 1)) & 1) == 1) {
- RoundUp(buffer, length, decimal_point);
- }
- } else { // We need 128 bits.
- DCHECK_LT(64, -exponent);
- DCHECK_LE(-exponent, 128);
- UInt128 fractionals128 = UInt128(fractionals, 0);
- fractionals128.Shift(-exponent - 64);
- int point = 128;
- for (int i = 0; i < fractional_count; ++i) {
- if (fractionals128.IsZero())
- break;
- // As before: instead of multiplying by 10 we multiply by 5 and adjust the
- // point location.
- // This multiplication will not overflow for the same reasons as before.
- fractionals128.Multiply(5);
- point--;
- char digit = static_cast<char>(fractionals128.DivModPowerOf2(point));
- buffer[*length] = '0' + digit;
- (*length)++;
- }
- if (fractionals128.BitAt(point - 1) == 1) {
- RoundUp(buffer, length, decimal_point);
- }
- }
-}
-
-// Removes leading and trailing zeros.
-// If leading zeros are removed then the decimal point position is adjusted.
-static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
- while (*length > 0 && buffer[(*length) - 1] == '0') {
- (*length)--;
- }
- int first_non_zero = 0;
- while (first_non_zero < *length && buffer[first_non_zero] == '0') {
- first_non_zero++;
- }
- if (first_non_zero != 0) {
- for (int i = first_non_zero; i < *length; ++i) {
- buffer[i - first_non_zero] = buffer[i];
- }
- *length -= first_non_zero;
- *decimal_point -= first_non_zero;
- }
-}
-
-bool FastFixedDtoa(double v,
- int fractional_count,
- Vector<char> buffer,
- int* length,
- int* decimal_point) {
- const uint32_t kMaxUInt32 = 0xFFFFFFFF;
- uint64_t significand = Double(v).Significand();
- int exponent = Double(v).Exponent();
- // v = significand * 2^exponent (with significand a 53bit integer).
- // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
- // don't know how to compute the representation. 2^73 ~= 9.5*10^21.
- // If necessary this limit could probably be increased, but we don't need
- // more.
- if (exponent > 20)
- return false;
- if (fractional_count > 20)
- return false;
- *length = 0;
- // At most kDoubleSignificandSize bits of the significand are non-zero.
- // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
- // bits: 0..11*..0xxx..53*..xx
- if (exponent + kDoubleSignificandSize > 64) {
- // The exponent must be > 11.
- //
- // We know that v = significand * 2^exponent.
- // And the exponent > 11.
- // We simplify the task by dividing v by 10^17.
- // The quotient delivers the first digits, and the remainder fits into a 64
- // bit number.
- // Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
- const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
- uint64_t divisor = kFive17;
- int divisor_power = 17;
- uint64_t dividend = significand;
- uint32_t quotient;
- uint64_t remainder;
- // Let v = f * 2^e with f == significand and e == exponent.
- // Then need q (quotient) and r (remainder) as follows:
- // v = q * 10^17 + r
- // f * 2^e = q * 10^17 + r
- // f * 2^e = q * 5^17 * 2^17 + r
- // If e > 17 then
- // f * 2^(e-17) = q * 5^17 + r/2^17
- // else
- // f = q * 5^17 * 2^(17-e) + r/2^e
- if (exponent > divisor_power) {
- // We only allow exponents of up to 20 and therefore (17 - e) <= 3
- dividend <<= exponent - divisor_power;
- quotient = static_cast<uint32_t>(dividend / divisor);
- remainder = (dividend % divisor) << divisor_power;
- } else {
- divisor <<= divisor_power - exponent;
- quotient = static_cast<uint32_t>(dividend / divisor);
- remainder = (dividend % divisor) << exponent;
- }
- FillDigits32(quotient, buffer, length);
- FillDigits64FixedLength(remainder, divisor_power, buffer, length);
- *decimal_point = *length;
- } else if (exponent >= 0) {
- // 0 <= exponent <= 11
- significand <<= exponent;
- FillDigits64(significand, buffer, length);
- *decimal_point = *length;
- } else if (exponent > -kDoubleSignificandSize) {
- // We have to cut the number.
- uint64_t integrals = significand >> -exponent;
- uint64_t fractionals = significand - (integrals << -exponent);
- if (integrals > kMaxUInt32) {
- FillDigits64(integrals, buffer, length);
- } else {
- FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
- }
- *decimal_point = *length;
- FillFractionals(fractionals, exponent, fractional_count, buffer, length,
- decimal_point);
- } else if (exponent < -128) {
- // This configuration (with at most 20 digits) means that all digits must be
- // 0.
- DCHECK_LE(fractional_count, 20);
- buffer[0] = '\0';
- *length = 0;
- *decimal_point = -fractional_count;
- } else {
- *decimal_point = 0;
- FillFractionals(significand, exponent, fractional_count, buffer, length,
- decimal_point);
- }
- TrimZeros(buffer, length, decimal_point);
- buffer[*length] = '\0';
- if ((*length) == 0) {
- // The string is empty and the decimal_point thus has no importance. Mimic
- // Gay's dtoa and and set it to -fractional_count.
- *decimal_point = -fractional_count;
- }
- return true;
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h
deleted file mode 100644
index e206ad67438..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_FIXED_DTOA_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_FIXED_DTOA_H_
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// Produces digits necessary to print a given number with
-// 'fractional_count' digits after the decimal point.
-// The buffer must be big enough to hold the result plus one terminating null
-// character.
-//
-// The produced digits might be too short in which case the caller has to fill
-// the gaps with '0's.
-// Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and
-// decimal_point = -2.
-// Halfway cases are rounded towards +/-Infinity (away from 0). The call
-// FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0.
-// The returned buffer may contain digits that would be truncated from the
-// shortest representation of the input.
-//
-// This method only works for some parameters. If it can't handle the input it
-// returns false. The output is null-terminated when the function succeeds.
-bool FastFixedDtoa(double v,
- int fractional_count,
- Vector<char> buffer,
- int* length,
- int* decimal_point);
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_FIXED_DTOA_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.cc
deleted file mode 100644
index 867356101f2..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.cc
+++ /dev/null
@@ -1,447 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/strtod.h"
-
-#include <limits.h>
-#include <stdarg.h>
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/bignum.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/cached-powers.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// 2^53 = 9007199254740992.
-// Any integer with at most 15 decimal digits will hence fit into a double
-// (which has a 53bit significand) without loss of precision.
-static const int kMaxExactDoubleIntegerDecimalDigits = 15;
-// 2^64 = 18446744073709551616 > 10^19
-static const int kMaxUint64DecimalDigits = 19;
-
-// Max double: 1.7976931348623157 x 10^308
-// Min non-zero double: 4.9406564584124654 x 10^-324
-// Any x >= 10^309 is interpreted as +infinity.
-// Any x <= 10^-324 is interpreted as 0.
-// Note that 2.5e-324 (despite being smaller than the min double) will be read
-// as non-zero (equal to the min non-zero double).
-static const int kMaxDecimalPower = 309;
-static const int kMinDecimalPower = -324;
-
-// 2^64 = 18446744073709551616
-static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
-
-// clang-format off
-static const double exact_powers_of_ten[] = {
- 1.0, // 10^0
- 10.0,
- 100.0,
- 1000.0,
- 10000.0,
- 100000.0,
- 1000000.0,
- 10000000.0,
- 100000000.0,
- 1000000000.0,
- 10000000000.0, // 10^10
- 100000000000.0,
- 1000000000000.0,
- 10000000000000.0,
- 100000000000000.0,
- 1000000000000000.0,
- 10000000000000000.0,
- 100000000000000000.0,
- 1000000000000000000.0,
- 10000000000000000000.0,
- 100000000000000000000.0, // 10^20
- 1000000000000000000000.0,
- // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
- 10000000000000000000000.0};
-// clang-format on
-
-static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
-
-// Maximum number of significant digits in the decimal representation.
-// In fact the value is 772 (see conversions.cc), but to give us some margin
-// we round up to 780.
-static const int kMaxSignificantDecimalDigits = 780;
-
-static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
- for (int i = 0; i < buffer.length(); i++) {
- if (buffer[i] != '0') {
- return buffer.SubVector(i, buffer.length());
- }
- }
- return Vector<const char>(buffer.Start(), 0);
-}
-
-static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
- for (int i = buffer.length() - 1; i >= 0; --i) {
- if (buffer[i] != '0') {
- return buffer.SubVector(0, i + 1);
- }
- }
- return Vector<const char>(buffer.Start(), 0);
-}
-
-static void TrimToMaxSignificantDigits(Vector<const char> buffer,
- int exponent,
- char* significant_buffer,
- int* significant_exponent) {
- for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
- significant_buffer[i] = buffer[i];
- }
- // The input buffer has been trimmed. Therefore the last digit must be
- // different from '0'.
- DCHECK_NE(buffer[buffer.length() - 1], '0');
- // Set the last digit to be non-zero. This is sufficient to guarantee
- // correct rounding.
- significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
- *significant_exponent =
- exponent + (buffer.length() - kMaxSignificantDecimalDigits);
-}
-
-// Reads digits from the buffer and converts them to a uint64.
-// Reads in as many digits as fit into a uint64.
-// When the string starts with "1844674407370955161" no further digit is read.
-// Since 2^64 = 18446744073709551616 it would still be possible read another
-// digit if it was less or equal than 6, but this would complicate the code.
-static uint64_t ReadUint64(Vector<const char> buffer,
- int* number_of_read_digits) {
- uint64_t result = 0;
- int i = 0;
- while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
- int digit = buffer[i++] - '0';
- DCHECK_LE(0, digit);
- DCHECK_LE(digit, 9);
- result = 10 * result + digit;
- }
- *number_of_read_digits = i;
- return result;
-}
-
-// Reads a DiyFp from the buffer.
-// The returned DiyFp is not necessarily normalized.
-// If remaining_decimals is zero then the returned DiyFp is accurate.
-// Otherwise it has been rounded and has error of at most 1/2 ulp.
-static void ReadDiyFp(Vector<const char> buffer,
- DiyFp* result,
- int* remaining_decimals) {
- int read_digits;
- uint64_t significand = ReadUint64(buffer, &read_digits);
- if (buffer.length() == read_digits) {
- *result = DiyFp(significand, 0);
- *remaining_decimals = 0;
- } else {
- // Round the significand.
- if (buffer[read_digits] >= '5') {
- significand++;
- }
- // Compute the binary exponent.
- int exponent = 0;
- *result = DiyFp(significand, exponent);
- *remaining_decimals = buffer.length() - read_digits;
- }
-}
-
-static bool DoubleStrtod(Vector<const char> trimmed,
- int exponent,
- double* result) {
-#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
- // On x86 the floating-point stack can be 64 or 80 bits wide. If it is
- // 80 bits wide (as is the case on Linux) then double-rounding occurs and the
- // result is not accurate.
- // We know that Windows32 uses 64 bits and is therefore accurate.
- // Note that the ARM simulator is compiled for 32bits. It therefore exhibits
- // the same problem.
- return false;
-#endif
- if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
- int read_digits;
- // The trimmed input fits into a double.
- // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
- // can compute the result-double simply by multiplying (resp. dividing) the
- // two numbers.
- // This is possible because IEEE guarantees that floating-point operations
- // return the best possible approximation.
- if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
- // 10^-exponent fits into a double.
- *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
- DCHECK_EQ(read_digits, trimmed.length());
- *result /= exact_powers_of_ten[-exponent];
- return true;
- }
- if (0 <= exponent && exponent < kExactPowersOfTenSize) {
- // 10^exponent fits into a double.
- *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
- DCHECK_EQ(read_digits, trimmed.length());
- *result *= exact_powers_of_ten[exponent];
- return true;
- }
- int remaining_digits =
- kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
- if ((0 <= exponent) &&
- (exponent - remaining_digits < kExactPowersOfTenSize)) {
- // The trimmed string was short and we can multiply it with
- // 10^remaining_digits. As a result the remaining exponent now fits
- // into a double too.
- *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
- DCHECK_EQ(read_digits, trimmed.length());
- *result *= exact_powers_of_ten[remaining_digits];
- *result *= exact_powers_of_ten[exponent - remaining_digits];
- return true;
- }
- }
- return false;
-}
-
-// Returns 10^exponent as an exact DiyFp.
-// The given exponent must be in the range [1; kDecimalExponentDistance[.
-static DiyFp AdjustmentPowerOfTen(int exponent) {
- DCHECK_LT(0, exponent);
- DCHECK_LT(exponent, PowersOfTenCache::kDecimalExponentDistance);
- // Simply hardcode the remaining powers for the given decimal exponent
- // distance.
- DCHECK_EQ(PowersOfTenCache::kDecimalExponentDistance, 8);
- switch (exponent) {
- case 1:
- return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);
- case 2:
- return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);
- case 3:
- return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);
- case 4:
- return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);
- case 5:
- return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);
- case 6:
- return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);
- case 7:
- return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
- default:
- UNREACHABLE();
- return DiyFp(0, 0);
- }
-}
-
-// If the function returns true then the result is the correct double.
-// Otherwise it is either the correct double or the double that is just below
-// the correct double.
-static bool DiyFpStrtod(Vector<const char> buffer,
- int exponent,
- double* result) {
- DiyFp input;
- int remaining_decimals;
- ReadDiyFp(buffer, &input, &remaining_decimals);
- // Since we may have dropped some digits the input is not accurate.
- // If remaining_decimals is different than 0 than the error is at most
- // .5 ulp (unit in the last place).
- // We don't want to deal with fractions and therefore keep a common
- // denominator.
- const int kDenominatorLog = 3;
- const int kDenominator = 1 << kDenominatorLog;
- // Move the remaining decimals into the exponent.
- exponent += remaining_decimals;
- int64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
-
- int old_e = input.E();
- input.Normalize();
- error <<= old_e - input.E();
-
- DCHECK_LE(exponent, PowersOfTenCache::kMaxDecimalExponent);
- if (exponent < PowersOfTenCache::kMinDecimalExponent) {
- *result = 0.0;
- return true;
- }
- DiyFp cached_power;
- int cached_decimal_exponent;
- PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, &cached_power,
- &cached_decimal_exponent);
-
- if (cached_decimal_exponent != exponent) {
- int adjustment_exponent = exponent - cached_decimal_exponent;
- DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
- input.Multiply(adjustment_power);
- if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
- // The product of input with the adjustment power fits into a 64 bit
- // integer.
- DCHECK_EQ(DiyFp::kSignificandSize, 64);
- } else {
- // The adjustment power is exact. There is hence only an error of 0.5.
- error += kDenominator / 2;
- }
- }
-
- input.Multiply(cached_power);
- // The error introduced by a multiplication of a*b equals
- // error_a + error_b + error_a*error_b/2^64 + 0.5
- // Substituting a with 'input' and b with 'cached_power' we have
- // error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
- // error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
- int error_b = kDenominator / 2;
- int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
- int fixed_error = kDenominator / 2;
- error += error_b + error_ab + fixed_error;
-
- old_e = input.E();
- input.Normalize();
- error <<= old_e - input.E();
-
- // See if the double's significand changes if we add/subtract the error.
- int order_of_magnitude = DiyFp::kSignificandSize + input.E();
- int effective_significand_size =
- Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
- int precision_digits_count =
- DiyFp::kSignificandSize - effective_significand_size;
- if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
- // This can only happen for very small denormals. In this case the
- // half-way multiplied by the denominator exceeds the range of an uint64.
- // Simply shift everything to the right.
- int shift_amount = (precision_digits_count + kDenominatorLog) -
- DiyFp::kSignificandSize + 1;
- input.set_f(input.F() >> shift_amount);
- input.set_e(input.E() + shift_amount);
- // We add 1 for the lost precision of error, and kDenominator for
- // the lost precision of input.f().
- error = (error >> shift_amount) + 1 + kDenominator;
- precision_digits_count -= shift_amount;
- }
- // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
- DCHECK_EQ(DiyFp::kSignificandSize, 64);
- DCHECK_LT(precision_digits_count, 64);
- uint64_t one64 = 1;
- uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
- uint64_t precision_bits = input.F() & precision_bits_mask;
- uint64_t half_way = one64 << (precision_digits_count - 1);
- precision_bits *= kDenominator;
- half_way *= kDenominator;
- DiyFp rounded_input(input.F() >> precision_digits_count,
- input.E() + precision_digits_count);
- if (precision_bits >= half_way + error) {
- rounded_input.set_f(rounded_input.F() + 1);
- }
- // If the last_bits are too close to the half-way case than we are too
- // inaccurate and round down. In this case we return false so that we can
- // fall back to a more precise algorithm.
-
- *result = Double(rounded_input).Value();
- if (half_way - error < precision_bits && precision_bits < half_way + error) {
- // Too imprecise. The caller will have to fall back to a slower version.
- // However the returned number is guaranteed to be either the correct
- // double, or the next-lower double.
- return false;
- } else {
- return true;
- }
-}
-
-// Returns the correct double for the buffer*10^exponent.
-// The variable guess should be a close guess that is either the correct double
-// or its lower neighbor (the nearest double less than the correct one).
-// Preconditions:
-// buffer.length() + exponent <= kMaxDecimalPower + 1
-// buffer.length() + exponent > kMinDecimalPower
-// buffer.length() <= kMaxDecimalSignificantDigits
-static double BignumStrtod(Vector<const char> buffer,
- int exponent,
- double guess) {
- if (guess == Double::Infinity()) {
- return guess;
- }
-
- DiyFp upper_boundary = Double(guess).UpperBoundary();
-
- DCHECK_LE(buffer.length() + exponent, kMaxDecimalPower + 1);
- DCHECK_GT(buffer.length() + exponent, kMinDecimalPower);
- DCHECK_LE(buffer.length(), kMaxSignificantDecimalDigits);
- // Make sure that the Bignum will be able to hold all our numbers.
- // Our Bignum implementation has a separate field for exponents. Shifts will
- // consume at most one bigit (< 64 bits).
- // ln(10) == 3.3219...
- DCHECK_LT(((kMaxDecimalPower + 1) * 333 / 100), Bignum::kMaxSignificantBits);
- Bignum input;
- Bignum boundary;
- input.AssignDecimalString(buffer);
- boundary.AssignUInt64(upper_boundary.F());
- if (exponent >= 0) {
- input.MultiplyByPowerOfTen(exponent);
- } else {
- boundary.MultiplyByPowerOfTen(-exponent);
- }
- if (upper_boundary.E() > 0) {
- boundary.ShiftLeft(upper_boundary.E());
- } else {
- input.ShiftLeft(-upper_boundary.E());
- }
- int comparison = Bignum::Compare(input, boundary);
- if (comparison < 0) {
- return guess;
- } else if (comparison > 0) {
- return Double(guess).NextDouble();
- } else if ((Double(guess).Significand() & 1) == 0) {
- // Round towards even.
- return guess;
- } else {
- return Double(guess).NextDouble();
- }
-}
-
-double Strtod(Vector<const char> buffer, int exponent) {
- Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
- Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
- exponent += left_trimmed.length() - trimmed.length();
- if (trimmed.length() == 0)
- return 0.0;
- if (trimmed.length() > kMaxSignificantDecimalDigits) {
- char significant_buffer[kMaxSignificantDecimalDigits];
- int significant_exponent;
- TrimToMaxSignificantDigits(trimmed, exponent, significant_buffer,
- &significant_exponent);
- return Strtod(
- Vector<const char>(significant_buffer, kMaxSignificantDecimalDigits),
- significant_exponent);
- }
- if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
- return Double::Infinity();
- }
- if (exponent + trimmed.length() <= kMinDecimalPower) {
- return 0.0;
- }
-
- double guess;
- if (DoubleStrtod(trimmed, exponent, &guess) ||
- DiyFpStrtod(trimmed, exponent, &guess)) {
- return guess;
- }
- return BignumStrtod(trimmed, exponent, guess);
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.h
deleted file mode 100644
index 827c52a62d4..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/strtod.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_STRTOD_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_STRTOD_H_
-
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace WTF {
-
-namespace double_conversion {
-
-// The buffer must only contain digits in the range [0-9]. It must not
-// contain a dot or a sign. It must not start with '0', and must not be empty.
-double Strtod(Vector<const char> buffer, int exponent);
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_STRTOD_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/utils.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/utils.h
deleted file mode 100644
index e0e16ffff2a..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/utils.h
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2010 the V8 project authors. 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_DTOA_UTILS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_UTILS_H_
-
-#include <string.h>
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-#define UNIMPLEMENTED NOTREACHED
-#define UNREACHABLE NOTREACHED
-
-// Double operations detection based on target architecture.
-// Linux uses a 80bit wide floating point stack on x86. This induces double
-// rounding, which in turn leads to wrong results.
-// An easy way to test if the floating-point operations are correct is to
-// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
-// the result is equal to 89255e-22.
-// The best way to test this, is to create a division-function and to compare
-// the output of the division with the expected result. (Inlining must be
-// disabled.)
-// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
-#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) || \
- defined(__aarch64__) || defined(__MIPSEL__) || defined(__powerpc64__)
-#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#elif defined(_M_IX86) || defined(__i386__)
-#if defined(_WIN32)
-// Windows uses a 64bit wide floating point stack.
-#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#else
-#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
-#endif // _WIN32
-#else
-#error Target architecture was not detected as supported by Double-Conversion.
-#endif
-
-#if defined(_WIN32) && !defined(__MINGW32__)
-
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef short int16_t; // NOLINT
-typedef unsigned short uint16_t; // NOLINT
-typedef int int32_t;
-typedef unsigned int uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-// intptr_t and friends are defined in crtdefs.h through stdio.h.
-
-#else
-
-#include <stdint.h>
-
-#endif
-
-// The following macro works on both 32 and 64-bit platforms.
-// Usage: instead of writing 0x1234567890123456
-// write UINT64_2PART_C(0x12345678,90123456);
-#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
-
-// The expression ARRAY_SIZE(a) is a compile-time constant of type
-// size_t which represents the number of elements of the given
-// array. You should only use ARRAY_SIZE on statically allocated
-// arrays.
-#define ARRAY_SIZE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
-// A macro to disallow the evil copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#ifndef DISALLOW_COPY_AND_ASSIGN
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-#endif // DISALLOW_COPY_AND_ASSIGN
-
-// A macro to disallow all the implicit constructors, namely the
-// default constructor, copy constructor and operator= functions.
-//
-// This should be used in the private: declarations for a class
-// that wants to prevent anyone from instantiating it. This is
-// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName() = delete; \
- DISALLOW_COPY_AND_ASSIGN(TypeName)
-
-namespace WTF {
-
-namespace double_conversion {
-
-static const int kCharSize = sizeof(char);
-
-// Returns the maximum of the two parameters.
-template <typename T>
-static T Max(T a, T b) {
- return a < b ? b : a;
-}
-
-// Returns the minimum of the two parameters.
-template <typename T>
-static T Min(T a, T b) {
- return a < b ? a : b;
-}
-
-inline int StrLength(const char* string) {
- size_t length = strlen(string);
- DCHECK_EQ(length, static_cast<size_t>(static_cast<int>(length)));
- return static_cast<int>(length);
-}
-
-// This is a simplified version of V8's Vector class.
-template <typename T>
-class Vector {
- public:
- Vector() : start_(NULL), length_(0) {}
- Vector(T* data, int length) : start_(data), length_(length) {
- DCHECK(length == 0 || (length > 0 && data != nullptr));
- }
-
- // Returns a vector using the same backing storage as this one,
- // spanning from and including 'from', to but not including 'to'.
- Vector<T> SubVector(int from, int to) {
- DCHECK_LE(to, length_);
- DCHECK_LT(from, to);
- DCHECK_LE(0, from);
- return Vector<T>(Start() + from, to - from);
- }
-
- // Returns the length of the vector.
- int length() const { return length_; }
-
- // Returns whether or not the vector is empty.
- bool is_empty() const { return length_ == 0; }
-
- // Returns the pointer to the start of the data in the vector.
- T* Start() const { return start_; }
-
- // Access individual vector elements.
- T& operator[](int index) const {
- CHECK_LE(0, index);
- CHECK_LT(index, length_);
- return start_[index];
- }
-
- T& First() { return start_[0]; }
-
- T& Last() { return start_[length_ - 1]; }
-
- private:
- T* start_;
- int length_;
-};
-
-// Helper class for building result strings in a character buffer. The
-// purpose of the class is to use safe operations that checks the
-// buffer bounds on all operations in debug mode.
-class StringBuilder {
- DISALLOW_NEW();
-
- public:
- StringBuilder(char* buffer, int size) : buffer_(buffer, size), position_(0) {}
-
- ~StringBuilder() {
- if (!is_finalized())
- Finalize();
- }
-
- int size() const { return buffer_.length(); }
-
- // Get the current position in the builder.
- int GetPosition() const {
- DCHECK(!is_finalized());
- return position_;
- }
-
- // Set the current position in the builder.
- void SetPosition(int position) {
- DCHECK(!is_finalized());
- SECURITY_DCHECK(position < size());
- position_ = position;
- }
-
- // Reset the position.
- void Reset() { position_ = 0; }
-
- // Add a single character to the builder. It is not allowed to add
- // 0-characters; use the Finalize() method to terminate the string
- // instead.
- void AddCharacter(char c) {
- DCHECK_NE(c, '\0');
- DCHECK(!is_finalized());
- DCHECK_LT(position_, buffer_.length());
- buffer_[position_++] = c;
- }
-
- // Add an entire string to the builder. Uses strlen() internally to
- // compute the length of the input string.
- void AddString(const char* s) { AddSubstring(s, StrLength(s)); }
-
- // Add the first 'n' characters of the given string 's' to the
- // builder. The input string must have enough characters.
- void AddSubstring(const char* s, int n) {
- DCHECK(!is_finalized());
- DCHECK_LT(position_ + n, buffer_.length());
- SECURITY_DCHECK(static_cast<size_t>(n) <= strlen(s));
- memcpy(&buffer_[position_], s, n * kCharSize);
- position_ += n;
- }
-
- // Add character padding to the builder. If count is non-positive,
- // nothing is added to the builder.
- void AddPadding(char c, int count) {
- for (int i = 0; i < count; i++) {
- AddCharacter(c);
- }
- }
-
- // Finalize the string by 0-terminating it and returning the buffer.
- char* Finalize() {
- DCHECK(!is_finalized());
- DCHECK_LT(position_, buffer_.length());
- buffer_[position_] = '\0';
- // Make sure nobody managed to add a 0-character to the
- // buffer while building the string.
- DCHECK_EQ(strlen(buffer_.Start()), static_cast<size_t>(position_));
- position_ = -1;
- DCHECK(is_finalized());
- return buffer_.Start();
- }
-
- private:
- Vector<char> buffer_;
- int position_;
-
- bool is_finalized() const { return position_ < 0; }
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
-};
-
-// The type-based aliasing rule allows the compiler to assume that pointers of
-// different types (for some definition of different) never alias each other.
-// Thus the following code does not work:
-//
-// float f = foo();
-// int fbits = *(int*)(&f);
-//
-// The compiler 'knows' that the int pointer can't refer to f since the types
-// don't match, so the compiler may cache f in a register, leaving random data
-// in fbits. Using C++ style casts makes no difference, however a pointer to
-// char data is assumed to alias any other pointer. This is the 'memcpy
-// exception'.
-//
-// Bit_cast uses the memcpy exception to move the bits from a variable of one
-// type of a variable of another type. Of course the end result is likely to
-// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
-// will completely optimize BitCast away.
-//
-// There is an additional use for BitCast.
-// Recent gccs will warn when they see casts that may result in breakage due to
-// the type-based aliasing rule. If you have checked that there is no breakage
-// you can use BitCast to cast one pointer type to another. This confuses gcc
-// enough that it can no longer see that you have cast one pointer type to
-// another thus avoiding the warning.
-template <class Dest, class Source>
-inline Dest BitCast(const Source& source) {
- // Compile time assertion: sizeof(Dest) == sizeof(Source)
- // A compile error here means your Dest and Source have different sizes.
- static_assert(sizeof(Dest) == sizeof(Source), "sizes should be equal");
-
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
-
-template <class Dest, class Source>
-inline Dest BitCast(Source* source) {
- return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
-}
-
-} // namespace double_conversion
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DTOA_UTILS_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa_test.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa_test.cc
index eb60c54756a..f00c28852b8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa_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/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/functional.h b/chromium/third_party/blink/renderer/platform/wtf/functional.h
index 2c5aeea5f0f..51a04791af2 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/functional.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/functional.h
@@ -117,8 +117,7 @@ template <typename T>
class PassedWrapper final {
public:
explicit PassedWrapper(T&& scoper) : scoper_(std::move(scoper)) {}
- PassedWrapper(PassedWrapper&& other) noexcept
- : scoper_(std::move(other.scoper_)) {}
+ PassedWrapper(PassedWrapper&& other) : scoper_(std::move(other.scoper_)) {}
T MoveOut() const { return std::move(scoper_); }
private:
@@ -210,6 +209,9 @@ struct CheckGCedTypeRestriction {
"GCed types are forbidden as bound parameters.");
static_assert(!WTF::IsStackAllocatedType<T>::value,
"Stack allocated types are forbidden as bound parameters.");
+ static_assert(
+ !(WTF::IsDisallowNew<T>::value && WTF::IsTraceable<T>::value),
+ "Traceable disallow new types are forbidden as bound parameters.");
};
template <typename Index, typename... Args>
@@ -319,9 +321,8 @@ class CrossThreadFunction<R(Args...)> {
CrossThreadFunction(const CrossThreadFunction&) = delete;
CrossThreadFunction& operator=(const CrossThreadFunction&) = delete;
- CrossThreadFunction(CrossThreadFunction&& other) noexcept = default;
- CrossThreadFunction& operator=(CrossThreadFunction&& other) noexcept =
- default;
+ CrossThreadFunction(CrossThreadFunction&& other) = default;
+ CrossThreadFunction& operator=(CrossThreadFunction&& other) = default;
R Run(Args... args) const & {
return callback_.Run(std::forward<Args>(args)...);
@@ -356,9 +357,8 @@ class CrossThreadOnceFunction<R(Args...)> {
CrossThreadOnceFunction(const CrossThreadOnceFunction&) = delete;
CrossThreadOnceFunction& operator=(const CrossThreadOnceFunction&) = delete;
- CrossThreadOnceFunction(CrossThreadOnceFunction&& other) noexcept = default;
- CrossThreadOnceFunction& operator=(CrossThreadOnceFunction&& other) noexcept =
- default;
+ CrossThreadOnceFunction(CrossThreadOnceFunction&& other) = default;
+ CrossThreadOnceFunction& operator=(CrossThreadOnceFunction&& other) = default;
R Run(Args... args) && {
return std::move(callback_).Run(std::forward<Args>(args)...);
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 8a002a8be1d..46b39e0697f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -106,8 +106,8 @@ class HashMap {
#endif
HashMap(const HashMap&) = default;
HashMap& operator=(const HashMap&) = default;
- HashMap(HashMap&&) noexcept = default;
- HashMap& operator=(HashMap&&) noexcept = default;
+ HashMap(HashMap&&) = default;
+ HashMap& operator=(HashMap&&) = default;
// For example, HashMap<int, int>({{1, 11}, {2, 22}, {3, 33}}) will give you
// a HashMap containing a mapping {1 -> 11, 2 -> 22, 3 -> 33}.
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 c79e45f177e..d7cdeeddf1c 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -74,8 +74,8 @@ class HashSet {
}
HashSet(const HashSet&) = default;
HashSet& operator=(const HashSet&) = default;
- HashSet(HashSet&&) noexcept = default;
- HashSet& operator=(HashSet&&) noexcept = default;
+ HashSet(HashSet&&) = default;
+ HashSet& operator=(HashSet&&) = default;
HashSet(std::initializer_list<ValueType> elements);
HashSet& operator=(std::initializer_list<ValueType> elements);
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 c667fdf4372..52483ec5926 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
@@ -694,7 +695,15 @@ template <typename Key,
typename Traits,
typename KeyTraits,
typename Allocator>
-class HashTable final {
+class HashTable final
+ : public ConditionalDestructor<HashTable<Key,
+ Value,
+ Extractor,
+ HashFunctions,
+ Traits,
+ KeyTraits,
+ Allocator>,
+ Allocator::kIsGarbageCollected> {
DISALLOW_NEW();
public:
@@ -726,15 +735,11 @@ class HashTable final {
HashTable();
- // For design of the destructor, please refer to
- // [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
- ~HashTable() {
+ void Finalize() {
+ static_assert(!Allocator::kIsGarbageCollected,
+ "GCed collections can't be finalized.");
if (LIKELY(!table_))
return;
- // If this is called during sweeping, it must not touch other heap objects
- // such as the backing.
- if (Allocator::IsSweepForbidden())
- return;
EnterAccessForbiddenScope();
DeleteAllBucketsAndDeallocate(table_, table_size_);
LeaveAccessForbiddenScope();
@@ -742,10 +747,10 @@ class HashTable final {
}
HashTable(const HashTable&);
- HashTable(HashTable&&) noexcept;
+ HashTable(HashTable&&);
void swap(HashTable&);
HashTable& operator=(const HashTable&);
- HashTable& operator=(HashTable&&) noexcept;
+ HashTable& operator=(HashTable&&);
// When the hash table is empty, just return the same iterator for end as
// for begin. This is more efficient because we don't have to skip all the
@@ -1924,7 +1929,7 @@ template <typename Key,
typename KeyTraits,
typename Allocator>
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
- HashTable(HashTable&& other) noexcept
+ HashTable(HashTable&& other)
: table_(nullptr),
table_size_(0),
key_count_(0),
@@ -2003,7 +2008,7 @@ template <typename Key,
typename Allocator>
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>&
HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits, Allocator>::
-operator=(HashTable&& other) noexcept {
+operator=(HashTable&& other) {
swap(other);
return *this;
}
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 79c3d76d61d..1f0e0105d05 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
@@ -121,7 +121,7 @@ class LinkedHashSetNodeBase {
LinkedHashSetNodeBase(const LinkedHashSetNodeBase& other)
: prev_(nullptr), next_(nullptr) {}
- LinkedHashSetNodeBase(LinkedHashSetNodeBase&& other) noexcept
+ LinkedHashSetNodeBase(LinkedHashSetNodeBase&& other)
: prev_(other.prev_), next_(other.next_) {
other.prev_ = nullptr;
other.next_ = nullptr;
@@ -136,7 +136,7 @@ class LinkedHashSetNodeBase {
LinkedHashSetNodeBase& operator=(const LinkedHashSetNodeBase& other) = delete;
};
-template <typename ValueArg, typename Allocator>
+template <typename ValueArg>
class LinkedHashSetNode : public LinkedHashSetNodeBase {
DISALLOW_NEW();
@@ -151,7 +151,7 @@ class LinkedHashSetNode : public LinkedHashSetNodeBase {
LinkedHashSetNodeBase* next)
: LinkedHashSetNodeBase(prev, next), value_(std::move(value)) {}
- LinkedHashSetNode(LinkedHashSetNode&& other) noexcept
+ LinkedHashSetNode(LinkedHashSetNode&& other)
: LinkedHashSetNodeBase(std::move(other)),
value_(std::move(other.value_)) {}
@@ -171,7 +171,7 @@ class LinkedHashSet {
private:
typedef ValueArg Value;
typedef TraitsArg Traits;
- typedef LinkedHashSetNode<Value, Allocator> Node;
+ typedef LinkedHashSetNode<Value> Node;
typedef LinkedHashSetNodeBase NodeBase;
typedef LinkedHashSetTranslator<Value, HashFunctions, Allocator>
NodeHashFunctions;
@@ -214,9 +214,9 @@ class LinkedHashSet {
LinkedHashSet();
LinkedHashSet(const LinkedHashSet&);
- LinkedHashSet(LinkedHashSet&&) noexcept;
+ LinkedHashSet(LinkedHashSet&&);
LinkedHashSet& operator=(const LinkedHashSet&);
- LinkedHashSet& operator=(LinkedHashSet&&) noexcept;
+ LinkedHashSet& operator=(LinkedHashSet&&);
// Needs finalization. The anchor needs to unlink itself from the chain.
~LinkedHashSet();
@@ -361,7 +361,7 @@ class LinkedHashSet {
template <typename Value, typename HashFunctions, typename Allocator>
struct LinkedHashSetTranslator {
STATIC_ONLY(LinkedHashSetTranslator);
- typedef LinkedHashSetNode<Value, Allocator> Node;
+ typedef LinkedHashSetNode<Value> Node;
typedef LinkedHashSetNodeBase NodeBase;
typedef typename HashTraits<Value>::PeekInType ValuePeekInType;
static unsigned GetHash(const Node& node) {
@@ -394,16 +394,16 @@ struct LinkedHashSetTranslator {
template <typename Value, typename Allocator>
struct LinkedHashSetExtractor {
STATIC_ONLY(LinkedHashSetExtractor);
- static const Value& Extract(const LinkedHashSetNode<Value, Allocator>& node) {
+ static const Value& Extract(const LinkedHashSetNode<Value>& node) {
return node.value_;
}
};
template <typename Value, typename ValueTraitsArg, typename Allocator>
struct LinkedHashSetTraits
- : public SimpleClassHashTraits<LinkedHashSetNode<Value, Allocator>> {
+ : public SimpleClassHashTraits<LinkedHashSetNode<Value>> {
STATIC_ONLY(LinkedHashSetTraits);
- using Node = LinkedHashSetNode<Value, Allocator>;
+ using Node = LinkedHashSetNode<Value>;
using NodeBase = LinkedHashSetNodeBase;
typedef ValueTraitsArg ValueTraits;
@@ -748,7 +748,7 @@ inline LinkedHashSet<T, U, V, W>::LinkedHashSet(const LinkedHashSet& other)
}
template <typename T, typename U, typename V, typename W>
-inline LinkedHashSet<T, U, V, W>::LinkedHashSet(LinkedHashSet&& other) noexcept
+inline LinkedHashSet<T, U, V, W>::LinkedHashSet(LinkedHashSet&& other)
: anchor_() {
Swap(other);
}
@@ -763,7 +763,7 @@ inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(
template <typename T, typename U, typename V, typename W>
inline LinkedHashSet<T, U, V, W>& LinkedHashSet<T, U, V, W>::operator=(
- LinkedHashSet&& other) noexcept {
+ LinkedHashSet&& other) {
Swap(other);
return *this;
}
@@ -961,8 +961,7 @@ inline void LinkedHashSet<T, U, V, W>::erase(ValuePeekInType value) {
}
template <typename T, typename Allocator>
-inline void swap(LinkedHashSetNode<T, Allocator>& a,
- LinkedHashSetNode<T, Allocator>& b) {
+inline void swap(LinkedHashSetNode<T>& a, LinkedHashSetNode<T>& b) {
typedef LinkedHashSetNodeBase Base;
// The key and value cannot be swapped atomically, and it would be
// wrong to have a GC when only one was swapped and the other still
diff --git a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
index 70776de903d..78bd279a7cb 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
@@ -25,6 +25,7 @@
#include <memory>
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
+#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace WTF {
@@ -76,7 +77,10 @@ template <typename ValueArg,
typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename AllocatorArg =
ListHashSetAllocator<ValueArg, inlineCapacity>>
-class ListHashSet {
+class ListHashSet
+ : public ConditionalDestructor<
+ ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>,
+ AllocatorArg::kIsGarbageCollected> {
typedef AllocatorArg Allocator;
USE_ALLOCATOR(ListHashSet, Allocator);
@@ -145,10 +149,10 @@ class ListHashSet {
ListHashSet();
ListHashSet(const ListHashSet&);
- ListHashSet(ListHashSet&&) noexcept;
+ ListHashSet(ListHashSet&&);
ListHashSet& operator=(const ListHashSet&);
- ListHashSet& operator=(ListHashSet&&) noexcept;
- ~ListHashSet();
+ ListHashSet& operator=(ListHashSet&&);
+ void Finalize();
void Swap(ListHashSet&);
@@ -776,8 +780,7 @@ inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(
}
template <typename T, size_t inlineCapacity, typename U, typename V>
-inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(
- ListHashSet&& other) noexcept
+inline ListHashSet<T, inlineCapacity, U, V>::ListHashSet(ListHashSet&& other)
: head_(nullptr), tail_(nullptr) {
Swap(other);
}
@@ -792,7 +795,7 @@ ListHashSet<T, inlineCapacity, U, V>::operator=(const ListHashSet& other) {
template <typename T, size_t inlineCapacity, typename U, typename V>
inline ListHashSet<T, inlineCapacity, U, V>&
-ListHashSet<T, inlineCapacity, U, V>::operator=(ListHashSet&& other) noexcept {
+ListHashSet<T, inlineCapacity, U, V>::operator=(ListHashSet&& other) {
Swap(other);
return *this;
}
@@ -805,14 +808,10 @@ inline void ListHashSet<T, inlineCapacity, U, V>::Swap(ListHashSet& other) {
allocator_provider_.Swap(other.allocator_provider_);
}
-// For design of the destructor, please refer to
-// [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
template <typename T, size_t inlineCapacity, typename U, typename V>
-inline ListHashSet<T, inlineCapacity, U, V>::~ListHashSet() {
- // If this is called during GC sweeping, it must not touch other heap objects
- // such as the ListHashSetNodes that is touching in DeleteAllNodes().
- if (Allocator::IsSweepForbidden())
- return;
+inline void ListHashSet<T, inlineCapacity, U, V>::Finalize() {
+ static_assert(!Allocator::kIsGarbageCollected,
+ "GCed collections can't be finalized");
DeleteAllNodes();
allocator_provider_.ReleaseAllocator();
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
index 206c640b3e6..4974591078f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
@@ -23,7 +23,7 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_table.h"
#include "third_party/blink/renderer/platform/wtf/text/case_map.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
index d76441ab204..37a3de36b68 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
@@ -29,7 +29,7 @@
#include <algorithm>
#include "base/optional.h"
#include "base/strings/string_util.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 6a2198fa50a..d00bd2605f6 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
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
#include <type_traits>
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#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"
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 b0bcef364d3..5d7213c8503 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
@@ -27,7 +27,7 @@
#include <algorithm>
#include "base/strings/string_util.h"
#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/dtoa.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/case_map.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading_pthreads.cc b/chromium/third_party/blink/renderer/platform/wtf/threading_pthreads.cc
index a8187873533..c772694ea42 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_pthreads.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_pthreads.cc
@@ -40,7 +40,6 @@
#include <sys/time.h>
#include "base/threading/scoped_blocking_call.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.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/thread_specific.h"
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 0930b733cbb..1b45d55a4fa 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
@@ -158,7 +158,7 @@ class CopyAssignmentDeleted final {
STACK_ALLOCATED();
public:
- CopyAssignmentDeleted& operator=(CopyAssignmentDeleted&&) noexcept;
+ CopyAssignmentDeleted& operator=(CopyAssignmentDeleted&&);
private:
CopyAssignmentDeleted& operator=(const CopyAssignmentDeleted&) = delete;
@@ -173,7 +173,7 @@ class CopyAssignmentPrivate final {
STACK_ALLOCATED();
public:
- CopyAssignmentPrivate& operator=(CopyAssignmentPrivate&&) noexcept;
+ CopyAssignmentPrivate& operator=(CopyAssignmentPrivate&&);
private:
CopyAssignmentPrivate& operator=(const CopyAssignmentPrivate&);
@@ -188,7 +188,7 @@ class CopyAssignmentUndeclared final {
STACK_ALLOCATED();
public:
- CopyAssignmentUndeclared& operator=(CopyAssignmentUndeclared&&) noexcept;
+ CopyAssignmentUndeclared& operator=(CopyAssignmentUndeclared&&);
};
static_assert(!std::is_copy_assignable<CopyAssignmentUndeclared>::value,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h b/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h
index 4bb5e23349b..4b398f937d1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h
@@ -64,11 +64,11 @@ class WTF_EXPORT ArrayBufferContents {
DataDeleter deleter,
void* deleter_info)
: data_(data),
- data_length_(length),
+ data_length_(data ? length : 0),
deleter_(deleter),
deleter_info_(deleter_info) {}
// Move constructor
- DataHandle(DataHandle&& other) noexcept { *this = std::move(other); }
+ DataHandle(DataHandle&& other) { *this = std::move(other); }
~DataHandle() {
if (!data_)
return;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector.h b/chromium/third_party/blink/renderer/platform/wtf/vector.h
index 207645a9193..43a27f72f79 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector.h
@@ -31,6 +31,7 @@
#include "base/template_util.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
+#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/container_annotations.h"
#include "third_party/blink/renderer/platform/wtf/forward.h" // For default Vector template parameters.
@@ -973,7 +974,11 @@ class VectorBuffer : protected VectorBufferBase<T, true, Allocator> {
// store iterators in another heap object.
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
-class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator> {
+class Vector
+ : private VectorBuffer<T, INLINE_CAPACITY, Allocator>,
+ public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>,
+ (INLINE_CAPACITY == 0) &&
+ Allocator::kIsGarbageCollected> {
USE_ALLOCATOR(Vector, Allocator);
using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>;
using TypeOperations = VectorTypeOperations<T, Allocator>;
@@ -1013,8 +1018,8 @@ class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator> {
Vector& operator=(const Vector<T, otherCapacity, Allocator>&);
// Moving.
- Vector(Vector&&) noexcept;
- Vector& operator=(Vector&&) noexcept;
+ Vector(Vector&&);
+ Vector& operator=(Vector&&);
// Construct with an initializer list. You can do e.g.
// Vector<int> v({1, 2, 3});
@@ -1257,12 +1262,12 @@ class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator> {
return Allocator::template MaxElementCountInBackingStore<T>();
}
- // For design of the destructor, please refer to
- // [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
- ~Vector() {
- if (!INLINE_CAPACITY) {
- if (LIKELY(!Base::Buffer()))
- return;
+ void Finalize() {
+ static_assert(!Allocator::kIsGarbageCollected || INLINE_CAPACITY,
+ "GarbageCollected collections without inline capacity cannot "
+ "be finalized.");
+ if (!INLINE_CAPACITY && LIKELY(!Base::Buffer())) {
+ return;
}
ANNOTATE_DELETE_BUFFER(begin(), capacity(), size_);
if (LIKELY(size_) &&
@@ -1271,21 +1276,11 @@ class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator> {
size_ = 0; // Partial protection against use-after-free.
}
- // If this is called during sweeping, the backing should not be touched.
- // Other collections have an early return here if IsSweepForbidden(), but
- // adding that resulted in performance regression for shadow dom benchmarks
- // (crbug.com/866084) because of the additional access to TLS. The check has
- // been removed but the same check exists in HeapAllocator::BackingFree() so
- // things should be fine as long as VectorBase does not touch the backing.
-
+ // For garbage collected vector HeapAllocator::BackingFree() will bail out
+ // during sweeping.
Base::Destruct();
}
- // This method will be referenced when creating an on-heap HeapVector with
- // inline capacity and elements requiring destruction. However usage of such a
- // type is banned with a static assert.
- void FinalizeGarbageCollectedObject() { NOTREACHED(); }
-
template <typename VisitorDispatcher, typename A = Allocator>
std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher);
@@ -1464,7 +1459,7 @@ operator=(const Vector<T, otherCapacity, Allocator>& other) {
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
Vector<T, inlineCapacity, Allocator>::Vector(
- Vector<T, inlineCapacity, Allocator>&& other) noexcept {
+ Vector<T, inlineCapacity, Allocator>&& other) {
size_ = 0;
// It's a little weird to implement a move constructor using swap but this
// way we don't have to add a move constructor to VectorBuffer.
@@ -1473,7 +1468,7 @@ Vector<T, inlineCapacity, Allocator>::Vector(
template <typename T, wtf_size_t inlineCapacity, typename Allocator>
Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::
-operator=(Vector<T, inlineCapacity, Allocator>&& other) noexcept {
+operator=(Vector<T, inlineCapacity, Allocator>&& other) {
swap(other);
return *this;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc b/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
index aa8a138ca51..788cc2bb12d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector_test.cc
@@ -420,8 +420,8 @@ TEST(VectorTest, AppendFirst) {
class MojoMoveOnlyType final {
public:
MojoMoveOnlyType();
- MojoMoveOnlyType(MojoMoveOnlyType&&) noexcept;
- MojoMoveOnlyType& operator=(MojoMoveOnlyType&&) noexcept;
+ MojoMoveOnlyType(MojoMoveOnlyType&&);
+ MojoMoveOnlyType& operator=(MojoMoveOnlyType&&);
~MojoMoveOnlyType();
private:
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf.cc b/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
index c0d64e88c43..50809fbd5a6 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf.cc
@@ -30,10 +30,11 @@
#include "third_party/blink/renderer/platform/wtf/wtf.h"
+#include "base/third_party/double_conversion/double-conversion/double-conversion.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
+#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/stack_util.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -73,6 +74,7 @@ void Initialize(void (*call_on_main_thread_function)(MainThreadFunction,
// Force initialization of static DoubleToStringConverter converter variable
// inside EcmaScriptConverter function while we are in single thread mode.
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
+ internal::GetDoubleConverter();
g_call_on_main_thread_function = call_on_main_thread_function;
internal::InitializeMainThreadStackEstimate();
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 e797445abe1..8f31365dcd0 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
@@ -36,9 +36,9 @@ class MoveOnly {
public:
explicit MoveOnly(int i = 0) : i_(i) {}
- MoveOnly(MoveOnly&& other) noexcept : i_(other.i_) { other.i_ = 0; }
+ MoveOnly(MoveOnly&& other) : i_(other.i_) { other.i_ = 0; }
- MoveOnly& operator=(MoveOnly&& other) noexcept {
+ MoveOnly& operator=(MoveOnly&& other) {
if (this != &other) {
i_ = other.i_;
other.i_ = 0;
@@ -62,12 +62,12 @@ class MoveOnlyHashValue {
explicit MoveOnlyHashValue(int value = kEmpty, int id = 0)
: value_(value), id_(id) {}
- MoveOnlyHashValue(MoveOnlyHashValue&& other) noexcept
+ MoveOnlyHashValue(MoveOnlyHashValue&& other)
: value_(other.value_), id_(other.id_) {
other.value_ = kMovedOut;
other.id_ = 0;
}
- MoveOnlyHashValue& operator=(MoveOnlyHashValue&& other) noexcept {
+ MoveOnlyHashValue& operator=(MoveOnlyHashValue&& other) {
value_ = other.value_;
id_ = other.id_;
other.value_ = kMovedOut;
diff --git a/chromium/third_party/blink/tools/BUILD.gn b/chromium/third_party/blink/tools/BUILD.gn
index f02b590fe04..e59f75ef491 100644
--- a/chromium/third_party/blink/tools/BUILD.gn
+++ b/chromium/third_party/blink/tools/BUILD.gn
@@ -2,51 +2,16 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# This action generates WPT metadata files for skipping web tests
-action("build_wpt_metadata") {
- testonly = true
- script = "//third_party/blink/tools/build_wpt_metadata.py"
- args = [
- "--metadata-output-dir",
- rebase_path("$root_out_dir/wpt_expectations_metadata"),
- "--additional-expectations",
- "../../third_party/blink/web_tests/WPTOverrideExpectations",
- ]
- outputs = [
- "$root_out_dir/wpt_expectations_metadata.stamp",
- ]
- data = [
- # Include the blinkpy tools to access expectations data
- "//third_party/blink/tools/blinkpy/",
- ]
- inputs = [
- # Include the various Test Expectations files
- "//third_party/blink/web_tests/ASANExpectations",
- "//third_party/blink/web_tests/LeakExpectations",
- "//third_party/blink/web_tests/MSANExpectations",
- "//third_party/blink/web_tests/NeverFixTests",
- "//third_party/blink/web_tests/SlowTests",
- "//third_party/blink/web_tests/StaleTestExpectations",
- "//third_party/blink/web_tests/TestExpectations",
- "//third_party/blink/web_tests/VirtualTestSuites",
- "//third_party/blink/web_tests/WPTOverrideExpectations",
- ]
-}
-
# WPT codebase for running webplatform tests
group("wpt_tests_isolate") {
testonly = true
- data_deps = [
- ":build_wpt_metadata",
- # Note that we also depend on Chrome and Chromedriver here but specify those
- # via the //wpt_tests_isolate target in //src/BUILD.gn
- ]
data = [
"//testing/scripts/common.py",
"//testing/scripts/run_wpt_tests.py",
"//testing/xvfb.py",
- # Include blinkpy tools for post-processing WPT output.
+ # Include blinkpy tools for setting up expectations.
+ "//third_party/blink/tools/build_wpt_metadata.py",
"//third_party/blink/tools/update_wpt_output.py",
"//third_party/blink/tools/blinkpy/",
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/file_uploader.py b/chromium/third_party/blink/tools/blinkpy/common/net/file_uploader.py
index b2d20bcd898..664db1112c3 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/file_uploader.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/file_uploader.py
@@ -48,7 +48,7 @@ def _encode_multipart_form_data(fields, files):
(content_type, body) ready for httplib.HTTP instance.
Source:
- http://code.google.com/p/rietveld/source/browse/trunk/upload.py
+ https://github.com/rietveld-codereview/rietveld/blob/1be266f92fbd6e01732e1bde10589bc408d65633/upload.py#L964
"""
BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
CRLF = '\r\n'
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
index 2da0a917feb..2caf360958d 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl.py
@@ -4,8 +4,8 @@
"""An interface to git-cl.
-The git-cl tool is responsible for communicating with Rietveld, Gerrit,
-and Buildbucket to manage changelists and try jobs associated with them.
+The git-cl tool is responsible for communicating with Gerrit and Buildbucket to
+manage changelists and try jobs associated with them.
"""
import collections
@@ -13,8 +13,10 @@ import json
import logging
import re
-from blinkpy.common.net.buildbot import Build, filter_latest_builds
from blinkpy.common.checkout.git import Git
+from blinkpy.common.net.buildbot import Build, filter_latest_builds
+from blinkpy.common.net.luci_auth import LuciAuth
+
_log = logging.getLogger(__name__)
@@ -22,6 +24,10 @@ _log = logging.getLogger(__name__)
# in order to authenticate with buildbucket.
_COMMANDS_THAT_TAKE_REFRESH_TOKEN = ('try',)
+# These characters always appear at the beginning of the SearchBuilds response
+# from BuildBucket.
+SEARCHBUILDS_RESPONSE_PREFIX = ")]}'"
+
class CLStatus(collections.namedtuple('CLStatus', ('status', 'try_job_results'))):
"""Represents the current status of a particular CL.
@@ -43,6 +49,18 @@ class TryJobStatus(collections.namedtuple('TryJobStatus', ('status', 'result')))
assert result in (None, 'FAILURE', 'SUCCESS', 'CANCELED')
return super(TryJobStatus, cls).__new__(cls, status, result)
+ @staticmethod
+ def from_bb_status(bb_status):
+ """Converts a buildbucket status into a TryJobStatus object."""
+ assert bb_status in ('SCHEDULED', 'STARTED', 'SUCCESS', 'FAILURE', 'INFRA_FAILURE', 'CANCELLED')
+ if bb_status in ('SCHEDULED', 'STARTED'):
+ return TryJobStatus(bb_status, None)
+ else:
+ # Map result INFRA_FAILURE to FAILURE to avoid introducing a new
+ # result, and it amounts to the same thing anyway.
+ return TryJobStatus('COMPLETED',
+ 'FAILURE' if bb_status == 'INFRA_FAILURE' else bb_status)
+
class GitCL(object):
@@ -112,6 +130,9 @@ class GitCL(object):
def _get_cl_status(self):
return self.run(['status', '--field=status']).strip()
+ def _get_latest_patchset(self):
+ return self.run(['status', '--field=patch']).strip()
+
def wait_for_try_jobs(
self, poll_delay_seconds=10 * 60, timeout_seconds=120 * 60,
cq_only=False):
@@ -127,7 +148,8 @@ class GitCL(object):
def finished_try_job_results_or_none():
cl_status = self._get_cl_status()
_log.debug('Fetched CL status: %s', cl_status)
- try_job_results = self.latest_try_jobs(cq_only=cq_only)
+ issue_number = self.get_issue_number()
+ try_job_results = self.latest_try_jobs(issue_number, cq_only=cq_only)
_log.debug('Fetched try results: %s', try_job_results)
if (cl_status == 'closed' or
(try_job_results and self.all_finished(try_job_results))):
@@ -184,14 +206,18 @@ class GitCL(object):
self._host.print_('Timed out waiting%s.' % message)
return None
- def latest_try_jobs(self, builder_names=None, cq_only=False, patchset=None):
+ def latest_try_jobs(
+ self, issue_number=None, builder_names=None, cq_only=False, patchset=None):
"""Fetches a dict of Build to TryJobStatus for the latest try jobs.
+ This variant fetches try job data from buildbucket directly.
+
This includes jobs that are not yet finished and builds with infra
failures, so if a build is in this list, that doesn't guarantee that
there are results.
Args:
+ issue_number: The git cl/issue number we're working with.
builder_names: Optional list of builders used to filter results.
cq_only: If True, only include CQ jobs.
patchset: If given, use this patchset instead of the latest.
@@ -200,11 +226,11 @@ class GitCL(object):
A dict mapping Build objects to TryJobStatus objects, with
only the latest jobs included.
"""
- # TODO(crbug.com/771438): Update filter_latest to handle Swarming tasks.
+ if not issue_number:
+ issue_number = self.get_issue_number()
return self.filter_latest(
self.try_job_results(
- builder_names, include_swarming_tasks=False, cq_only=cq_only,
- patchset=patchset))
+ issue_number, builder_names, cq_only=cq_only, patchset=patchset))
@staticmethod
def filter_latest(try_results):
@@ -215,41 +241,91 @@ class GitCL(object):
return {b: s for b, s in try_results.items() if b in latest_builds}
def try_job_results(
- self, builder_names=None, include_swarming_tasks=True,
- cq_only=False, patchset=None):
+ self, issue_number=None, builder_names=None, cq_only=False, patchset=None):
"""Returns a dict mapping Build objects to TryJobStatus objects."""
- raw_results = self.fetch_raw_try_job_results(patchset=patchset)
+ if not issue_number:
+ issue_number = self.get_issue_number()
+ raw_results_json = self.fetch_raw_try_job_results(issue_number, patchset)
build_to_status = {}
- for result in raw_results:
- if builder_names and result['builder_name'] not in builder_names:
+ if 'builds' not in raw_results_json:
+ return build_to_status
+ for build in raw_results_json['builds']:
+ builder_name = build['builder']['builder']
+ if builder_names and builder_name not in builder_names:
continue
- is_swarming_task = result['url'] and '/task/' in result['url']
- if is_swarming_task and not include_swarming_tasks:
- continue
- is_cq = 'user_agent:cq' in result.get('tags', [])
- is_experimental = 'cq_experimental:true' in result.get('tags', [])
+ is_cq = 'tags' in build and {'key': 'user_agent', 'value': 'cq'} in build['tags']
+ is_experimental = 'tags' in build and {'key': 'cq_experimental', 'value': 'true'} in build['tags']
if cq_only and not (is_cq and not is_experimental):
continue
- build_to_status[self._build(result)] = self._try_job_status(result)
+ build_number = build.get('number')
+ status = build['status']
+ build_to_status[Build(builder_name, build_number)] = TryJobStatus.from_bb_status(status)
return build_to_status
- def fetch_raw_try_job_results(self, patchset=None):
- """Requests results of try jobs for the current CL and the parsed JSON.
-
- The return value is expected to be a list of dicts, which each are
- expected to have the fields "builder_name", "status", "result", and
- "url". The format is determined by the output of "git cl try-results".
+ def fetch_raw_try_job_results(self, issue_number, patchset=None):
+ """Gets try job results for the specified CL from buildbucket.
+
+ This uses the SearchBuilds rpc format specified in
+ https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/buildbucket/proto/rpc.proto
+
+ The response is a list of dicts of the following form:
+ {
+ "builds": [
+ {
+ "status": <status>
+ "builder": {
+ "builder": <builder_name>
+ },
+ "number": <build_number>,
+ "tags": [
+ {
+ "key": <tag key>
+ "value": <tag value>
+ },
+ ... more tags
+ ]
+ },
+ ... more builds
+ }
+
+ This method returns the JSON representation of the above response.
"""
- with self._host.filesystem.mkdtemp() as temp_directory:
- results_path = self._host.filesystem.join(temp_directory, 'try-results.json')
- command = ['try-results', '--json', results_path]
- if patchset:
- command.extend(['--patchset', str(patchset)])
- self.run(command)
- contents = self._host.filesystem.read_text_file(results_path)
- _log.debug('Fetched try results to file "%s".', results_path)
- self._host.filesystem.remove(results_path)
- return json.loads(contents)
+ if not patchset:
+ patchset = self._get_latest_patchset()
+
+ luci_token = LuciAuth(self._host).get_access_token()
+ hed = {
+ 'Authorization': 'Bearer ' + luci_token,
+ 'Accept': 'application/json',
+ 'Content-Type': 'application/json',
+ }
+ data = {
+ 'predicate': {
+ 'gerritChanges': [
+ {
+ 'host': 'chromium-review.googlesource.com',
+ 'project': 'chromium/src',
+ 'change': issue_number,
+ 'patchset': patchset
+ }
+ ]
+ },
+ 'fields': 'builds.*.builder.builder,builds.*.status,builds.*.tags,builds.*.number'
+ }
+ url = 'https://cr-buildbucket.appspot.com/prpc/buildbucket.v2.Builds/SearchBuilds'
+ req_body = json.dumps(data)
+ _log.debug("Sending SearchBuilds request. Url: %s with Body: %s" % (url, req_body))
+ response = self._host.web.request('POST', url, data=req_body, headers=hed)
+ if response.getcode() == 200:
+ response_body = response.read()
+ if response_body.startswith(SEARCHBUILDS_RESPONSE_PREFIX):
+ response_body = response_body[len(SEARCHBUILDS_RESPONSE_PREFIX):]
+ return json.loads(response_body)
+
+ _log.error("Failed to fetch tryjob results from buildbucket (status=%s)" % response.status)
+ _log.debug("Full SearchBuilds response: %s" % str(response))
+ return None
+
@staticmethod
def _build(result_dict):
diff --git a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
index 489a6c469e6..06f76d22a57 100644
--- a/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/common/net/git_cl_unittest.py
@@ -8,7 +8,9 @@ from blinkpy.common.host_mock import MockHost
from blinkpy.common.net.buildbot import Build
from blinkpy.common.net.git_cl import CLStatus
from blinkpy.common.net.git_cl import GitCL
+from blinkpy.common.net.git_cl import SEARCHBUILDS_RESPONSE_PREFIX
from blinkpy.common.net.git_cl import TryJobStatus
+from blinkpy.common.net.web_mock import MockWeb
from blinkpy.common.system.executive_mock import MockExecutive
@@ -88,30 +90,6 @@ class GitCLTest(unittest.TestCase):
],
])
- def test_fetch_raw_try_job_results(self):
- # Fetching raw try job results has a side effect of writing to and
- # reading from a temporary JSON file. This test method verifies the
- # command line used to fetch try job results.
- host = MockHost()
- host.filesystem.write_text_file(
- '/__im_tmp/tmp_0_/try-results.json', '{}')
- host.filesystem.write_text_file(
- '/__im_tmp/tmp_1_/try-results.json', '{}')
- git_cl = GitCL(host)
- git_cl.fetch_raw_try_job_results()
- git_cl.fetch_raw_try_job_results(patchset=7)
- self.assertEqual(host.executive.calls, [
- [
- 'git', 'cl', 'try-results',
- '--json', '/__im_tmp/tmp_0_/try-results.json',
- ],
- [
- 'git', 'cl', 'try-results',
- '--json', '/__im_tmp/tmp_1_/try-results.json',
- '--patchset', '7'
- ]
- ])
-
def test_get_issue_number(self):
host = MockHost()
host.executive = MockExecutive(output='Foo\nIssue number: 12345 (http://crrev.com/12345)')
@@ -133,14 +111,23 @@ class GitCLTest(unittest.TestCase):
def test_wait_for_try_jobs_timeout(self):
host = MockHost()
git_cl = GitCL(host)
- git_cl.fetch_raw_try_job_results = lambda **_: [
- {
- 'builder_name': 'some-builder',
- 'status': 'STARTED',
- 'result': None,
- 'url': None,
- },
- ]
+ response = {
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "STARTED",
+ "builder": {
+ "builder": "some-builder"
+ },
+ "number": 100
+ }
+ ]
+ }"""
+ }
+ # Specify the same response 10 times to ensure each poll gets ones.
+ git_cl._host.web = MockWeb(responses=[response] * 10)
self.assertIsNone(git_cl.wait_for_try_jobs())
self.assertEqual(
host.stdout.getvalue(),
@@ -156,7 +143,13 @@ class GitCLTest(unittest.TestCase):
def test_wait_for_try_jobs_no_results_not_considered_finished(self):
host = MockHost()
git_cl = GitCL(host)
- git_cl.fetch_raw_try_job_results = lambda **_: []
+ # git_cl.fetch_raw_try_job_results = lambda **_: []
+ response = {
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX + "{}"
+ }
+ # Specify the same response 10 times to ensure each poll gets ones.
+ git_cl._host.web = MockWeb(responses=[response] * 10)
self.assertIsNone(git_cl.wait_for_try_jobs())
self.assertEqual(
host.stdout.getvalue(),
@@ -173,14 +166,22 @@ class GitCLTest(unittest.TestCase):
host = MockHost()
host.executive = MockExecutive(output='closed')
git_cl = GitCL(host)
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'some-builder',
- 'status': 'STARTED',
- 'result': None,
- 'url': None,
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "STARTED",
+ "builder": {
+ "builder": "some-builder"
+ }
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
git_cl.wait_for_try_jobs(),
CLStatus(
@@ -198,17 +199,23 @@ class GitCLTest(unittest.TestCase):
host = MockHost()
host.executive = MockExecutive(output='lgtm')
git_cl = GitCL(host)
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'some-builder',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/100',
- ],
- 'url': 'http://ci.chromium.org/b/8931586523737389552',
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "FAILURE",
+ "builder": {
+ "builder": "some-builder"
+ },
+ "number": 100
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
git_cl.wait_for_try_jobs(),
CLStatus(
@@ -280,64 +287,84 @@ class GitCLTest(unittest.TestCase):
def test_latest_try_jobs_cq_only(self):
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'cq-a',
- 'experimental': False,
- 'result': None,
- 'status': 'SCHEDULED',
- 'tags': ['user_agent:cq'],
- 'url': None,
- },
- {
- 'builder_name': 'cq-b',
- 'experimental': False,
- 'result': None,
- 'status': 'SCHEDULED',
- 'tags': ['cq_experimental:false', 'user_agent:cq'],
- 'url': None,
- },
- {
- 'builder_name': 'cq-c',
- 'experimental': True,
- 'result': None,
- 'status': 'SCHEDULED',
- 'tags': ['cq_experimental:false', 'user_agent:cq'],
- 'url': None,
- },
- {
- 'builder_name': 'cq-a-experimental',
- 'experimental': True,
- 'result': None,
- 'status': 'SCHEDULED',
- 'tags': ['cq_experimental:true', 'user_agent:cq'],
- 'url': None,
- },
- {
- 'builder_name': 'cq-b-experimental',
- 'experimental': False,
- 'result': None,
- 'status': 'SCHEDULED',
- 'tags': ['cq_experimental:true', 'user_agent:cq'],
- 'url': None,
- },
- {
- 'builder_name': 'other-a',
- 'experimental': False,
- 'status': 'SCHEDULED',
- 'result': None,
- 'tags': ['user_agent:git_cl_try'],
- 'url': None,
- },
- {
- 'builder_name': 'other-b',
- 'experimental': False,
- 'status': 'SCHEDULED',
- 'result': None,
- 'tags': ['is_experimental:false', 'user_agent:git_cl_try'],
- 'url': None,
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "cq-a"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "cq"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "cq-b"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "cq"},
+ {"key": "cq_experimental", "value": "false"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "cq-c"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "cq"},
+ {"key": "cq_experimental", "value": "false"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "cq-a-experimental"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "cq"},
+ {"key": "cq_experimental", "value": "true"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "cq-b-experimental"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "cq"},
+ {"key": "cq_experimental", "value": "true"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "other-a"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "git_cl_try"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "other-b"
+ },
+ "tags": [
+ {"key": "user_agent", "value": "git_cl_try"},
+ {"key": "cq_experimental", "value": "false"}
+ ]
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
git_cl.latest_try_jobs(cq_only=True),
{
@@ -347,123 +374,109 @@ class GitCLTest(unittest.TestCase):
})
def test_latest_try_jobs(self):
+ # Here we have multiple builds with the same name, but we only take the
+ # latest one (based on build number).
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/100',
- ],
- 'url': 'http://build.chromium.org/b/123123123132123123',
- },
- {
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/90',
- ],
- 'url': 'http://build.chromium.org/p/master/builders/builder-b/builds/90',
- },
- {
- 'builder_name': 'builder-a',
- 'status': 'SCHEDULED',
- 'result': None,
- 'url': None,
- },
- {
- 'builder_name': 'builder-c',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/123',
- ],
- 'url': 'http://ci.chromium.org/b/123123123123123123',
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-b"
+ },
+ "number": 100
+ },
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-b"
+ },
+ "number": 90
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "builder-a"
+ }
+ },
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-c"
+ },
+ "number": 123
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
- git_cl.latest_try_jobs(['builder-a', 'builder-b']),
+ git_cl.latest_try_jobs(builder_names=['builder-a', 'builder-b']),
{
Build('builder-a'): TryJobStatus('SCHEDULED'),
Build('builder-b', 100): TryJobStatus('COMPLETED', 'SUCCESS'),
})
- def test_latest_try_jobs_started_build_luci_url(self):
+ def test_latest_try_jobs_started(self):
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-a',
- 'status': 'STARTED',
- 'result': None,
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/100',
- ],
- 'url': 'http://ci.chromium.org/b/123123123123123',
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "STARTED",
+ "builder": {
+ "builder": "builder-a"
+ },
+ "number": 100
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
- git_cl.latest_try_jobs(['builder-a']),
+ git_cl.latest_try_jobs(builder_names=['builder-a']),
{Build('builder-a', 100): TryJobStatus('STARTED')})
def test_latest_try_jobs_failures(self):
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-a',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'failure_reason': 'BUILD_FAILURE',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/100',
- ],
- 'url': 'http://ci.chromium.org/b/123123123123123123',
- },
- {
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'failure_reason': 'INFRA_FAILURE',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/200',
- ],
- 'url': 'http://ci.chromium.org/b/1293871928371923719',
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "FAILURE",
+ "builder": {
+ "builder": "builder-a"
+ },
+ "number": 100
+ },
+ {
+ "status": "INFRA_FAILURE",
+ "builder": {
+ "builder": "builder-b"
+ },
+ "number": 200
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
- git_cl.latest_try_jobs(['builder-a', 'builder-b']),
+ git_cl.latest_try_jobs(builder_names=['builder-a', 'builder-b']),
{
Build('builder-a', 100): TryJobStatus('COMPLETED', 'FAILURE'),
Build('builder-b', 200): TryJobStatus('COMPLETED', 'FAILURE'),
})
- def test_latest_try_jobs_ignores_swarming_task(self):
- git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
- {
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/10',
- ],
- 'url': 'https://ci.chromium.org/b/123918239182739',
- },
- {
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'url': ('https://ci.chromium.org/swarming/task/'
- '1234abcd1234abcd?server=chromium-swarm.appspot.com'),
- }
- ]
- self.assertEqual(
- git_cl.latest_try_jobs(['builder-b']),
- {
- Build('builder-b', 10): TryJobStatus('COMPLETED', 'SUCCESS'),
- })
-
def test_filter_latest(self):
try_job_results = {
Build('builder-a', 100): TryJobStatus('COMPLETED', 'FAILURE'),
@@ -480,71 +493,115 @@ class GitCLTest(unittest.TestCase):
def test_filter_latest_none(self):
self.assertIsNone(GitCL.filter_latest(None))
- def test_try_job_results_url_format_fallback(self):
+ def test_try_job_results_with_other_builder(self):
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
- {
- 'builder_name': 'builder-a',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'tags': [
- 'build_address:luci.chromium.try/chromium_presubmit/100',
- ],
- 'url': 'http://ci.chromium.org/p/master/builders/builder-b/builds/10',
- },
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'url': 'http://ci.chromium.org/p/master/builders/builder-b/builds/20',
- },
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "FAILURE",
+ "builder": {
+ "builder": "builder-a"
+ },
+ "number": 100,
+ "tags": [
+ {"key": "user_agent", "value": "cq"}
+ ]
+ }
+ ]
+ }"""
+ }
+ ])
+ # We ignore builders that we explicitly don't care about;
+ # so if we only care about other-builder, not builder-a,
+ # then no exception is raised.
+ self.assertEqual(git_cl.try_job_results(builder_names=['other-builder']), {})
+
+ def test_try_job_results(self):
+ git_cl = GitCL(MockHost())
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-c',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'url': 'https://ci.chromium.org/swarming/task/36a767f405d9ee10',
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-a"
+ },
+ "number": 111,
+ "tags": [
+ {"key": "user_agent", "value": "cq"}
+ ]
+ },
+ {
+ "status": "SCHEDULED",
+ "builder": {
+ "builder": "builder-b"
+ },
+ "number": 222
+ },
+ {
+ "status": "INFRA_FAILURE",
+ "builder": {
+ "builder": "builder-c"
+ },
+ "number": 333
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
- git_cl.try_job_results(),
+ git_cl.try_job_results(issue_number=None),
{
- Build('builder-a', 100): TryJobStatus('COMPLETED', 'FAILURE'),
- Build('builder-b', 20): TryJobStatus('COMPLETED', 'FAILURE'),
- Build('builder-c', '36a767f405d9ee10'): TryJobStatus('COMPLETED', 'FAILURE'),
+ Build('builder-a', 111): TryJobStatus('COMPLETED', 'SUCCESS'),
+ Build('builder-b', 222): TryJobStatus('SCHEDULED', None),
+ # INFRA_FAILURE is mapped to FAILURE for this build.
+ Build('builder-c', 333): TryJobStatus('COMPLETED', 'FAILURE'),
})
- def test_try_job_results_with_swarming_url_with_query(self):
+ def test_try_job_results_skip_experimental_cq(self):
git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
+ git_cl._host.web = MockWeb(responses=[
{
- 'builder_name': 'builder-b',
- 'status': 'COMPLETED',
- 'result': 'SUCCESS',
- 'url': ('https://ci.chromium.org/swarming/task/'
- '38740befcd9c0010?server=chromium-swarm.appspot.com'),
- },
- ]
+ 'status_code': 200,
+ 'body': SEARCHBUILDS_RESPONSE_PREFIX +
+ """{
+ "builds": [
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-a"
+ },
+ "number": 111,
+ "tags": [
+ {"key": "user_agent", "value": "cq"}
+ ]
+ },
+ {
+ "status": "SUCCESS",
+ "builder": {
+ "builder": "builder-b"
+ },
+ "number": 222,
+ "tags": [
+ {"key": "user_agent", "value": "cq"},
+ {"key": "cq_experimental", "value": "true"}
+ ]
+ }
+ ]
+ }"""
+ }
+ ])
self.assertEqual(
- git_cl.try_job_results(),
+ # Only one build appears - builder-b is ignored because it is
+ # experimental.
+ git_cl.try_job_results(issue_number=None, cq_only=True),
{
- Build('builder-b', '38740befcd9c0010'): TryJobStatus('COMPLETED', 'SUCCESS'),
+ Build('builder-a', 111): TryJobStatus('COMPLETED', 'SUCCESS'),
})
-
- def test_try_job_results_with_unexpected_url_format(self):
- git_cl = GitCL(MockHost())
- git_cl.fetch_raw_try_job_results = lambda **_: [
- {
- 'builder_name': 'builder-a',
- 'status': 'COMPLETED',
- 'result': 'FAILURE',
- 'failure_reason': 'BUILD_FAILURE',
- 'url': 'https://example.com/',
- },
- ]
- # We try to parse a build number or task ID from the URL.
- with self.assertRaisesRegexp(AssertionError, 'https://example.com/ did not match expected format'):
- git_cl.try_job_results()
- # We ignore builders that we explicitly don't care about;
- # so if we only care about other-builder, not builder-a,
- # then no exception is raised.
- self.assertEqual(git_cl.try_job_results(['other-builder']), {})
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 0f9e351ffd8..6561ccceaa0 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
@@ -250,13 +250,14 @@ _CONFIG = [
# cc::Layers.
'cc::Layer',
'cc::PictureLayer',
+ 'cc::SurfaceLayer',
# cc::Layer helper data structs.
'cc::ElementId',
'cc::LayerPositionConstraint',
'cc::OverscrollBehavior',
'cc::Scrollbar',
- 'cc::ScrollbarLayerInterface',
+ 'cc::ScrollbarLayerBase',
'cc::ScrollbarOrientation',
'cc::ScrollbarPart',
'cc::StickyPositionConstraint',
@@ -267,6 +268,7 @@ _CONFIG = [
'cc::HORIZONTAL',
'cc::VERTICAL',
'cc::THUMB',
+ 'cc::TRACK',
'cc::TICKMARKS',
'cc::BrowserControlsState',
'cc::EventListenerClass',
@@ -376,7 +378,7 @@ _CONFIG = [
# namespace.
'frame_test_helpers::.+',
- # Blink uses Mojo, so it needs mojo::Binding, mojo::InterfacePtr, et
+ # Blink uses Mojo, so it needs mojo::Receiver, mojo::Remote, et
# cetera, as well as generated Mojo bindings.
# Note that the Mojo callback helpers are explicitly forbidden:
# Blink already has a signal for contexts being destroyed, and
@@ -459,8 +461,16 @@ _CONFIG = [
],
},
{
+ 'paths': ['third_party/blink/renderer/core/animation_frame',
+ 'third_party/blink/renderer/core/offscreencanvas',
+ 'third_party/blink/renderer/core/html/canvas'],
+ 'allowed': [
+ 'viz::BeginFrameArgs',
+ ],
+ },
+ {
'paths': ['third_party/blink/renderer/core/clipboard'],
- 'allowed': ['gfx::PNGCodec', 'net::EscapeForHTML'],
+ 'allowed': ['net::EscapeForHTML'],
},
{
'paths': ['third_party/blink/renderer/core/css'],
@@ -602,6 +612,16 @@ _CONFIG = [
},
{
'paths': [
+ 'third_party/blink/renderer/core/html/media/',
+ ],
+ # This module needs access to the following for media's base::Feature
+ # list.
+ 'allowed': [
+ 'media::.+',
+ ]
+ },
+ {
+ 'paths': [
'third_party/blink/renderer/modules/encryptedmedia/',
],
'allowed': [
@@ -726,6 +746,7 @@ _CONFIG = [
# The WebGPU Blink module needs access to the WebGPU control
# command buffer interface.
'allowed': [
+ 'gpu::webgpu::PowerPreference',
'gpu::webgpu::WebGPUInterface',
],
},
@@ -823,14 +844,43 @@ _CONFIG = [
],
'allowed': ['crypto::.+'],
},
+
{
'paths': [
- 'third_party/blink/renderer/modules/peerconnection',
- 'third_party/blink/renderer/bindings/modules/v8/serialization',
+ 'third_party/blink/renderer/modules/p2p',
],
'allowed': [
+ # TODO(crbug.com/787254): Remove GURL usage.
+ 'GURL',
'cricket::.*',
+ 'rtc::.+',
+ ]
+ },
+ {
+ 'paths': [
+ # TODO(crbug.com/787254): Separate the two paths below and their own
+ # whitelist.
+ 'third_party/blink/renderer/modules/peerconnection/',
+ 'third_party/blink/renderer/bindings/modules/v8/serialization/',
+ ],
+ 'allowed': [
+ 'absl::.+',
+ 'base::AutoLock',
+ 'base::AutoUnlock',
+ 'base::Lock',
+ # TODO(crbug.com/787254): Remove base::BindOnce, base::Unretained,
+ # base::MessageLoopCurrent.
+ 'base::Bind.*',
+ "base::MessageLoopCurrent",
+ 'base::Unretained',
+ 'base::WrapRefCounted',
+ 'cricket::.*',
+ 'jingle_glue::JingleThreadWrapper',
+ # TODO(crbug.com/787254): Remove GURL usage.
+ 'GURL',
'media::.+',
+ 'net::NetworkTrafficAnnotationTag',
+ 'net::DefineNetworkTrafficAnnotation',
'rtc::.+',
'webrtc::.+',
'quic::.+',
@@ -846,7 +896,6 @@ _CONFIG = [
# AtomicString or HeapVector) are used cross thread. These Blink types
# are converted to the STL/WebRTC counterparts in the parent directory.
'allowed': [
- 'absl::.+',
'base::OnTaskRunnerDeleter',
'sigslot::.+',
],
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 32eb85ffeb7..73f15e94ade 100644
--- a/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
+++ b/chromium/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -36,7 +36,7 @@ from blinkpy.common.path_finder import WEB_TESTS_LAST_COMPONENT
from blinkpy.common.memoized import memoized
from blinkpy.common.net.buildbot import Build
from blinkpy.tool.commands.command import Command
-from blinkpy.web_tests.controllers.test_result_writer import TestResultWriter
+from blinkpy.web_tests.models import test_failures
from blinkpy.web_tests.models.test_expectations import TestExpectations
from blinkpy.web_tests.port import base, factory
@@ -101,12 +101,12 @@ class AbstractRebaseliningCommand(Command):
def _file_name_for_actual_result(self, test_name, suffix):
# output_filename takes extensions starting with '.'.
return self._host_port.output_filename(
- test_name, TestResultWriter.FILENAME_SUFFIX_ACTUAL, '.' + suffix)
+ test_name, test_failures.FILENAME_SUFFIX_ACTUAL, '.' + suffix)
def _file_name_for_expected_result(self, test_name, suffix):
# output_filename takes extensions starting with '.'.
return self._host_port.output_filename(
- test_name, TestResultWriter.FILENAME_SUFFIX_EXPECTED, '.' + suffix)
+ test_name, test_failures.FILENAME_SUFFIX_EXPECTED, '.' + suffix)
class ChangeSet(object):
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 c8e0153e390..eb35930ebf2 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
@@ -87,7 +87,7 @@ class RebaselineCL(AbstractParallelRebaselineCommand):
self._selected_try_bots = frozenset(try_builders)
jobs = self.git_cl.latest_try_jobs(
- self.selected_try_bots, patchset=options.patchset)
+ builder_names=self.selected_try_bots, patchset=options.patchset)
self._log_jobs(jobs)
builders_with_no_jobs = self.selected_try_bots - {b.builder_name for b in jobs}
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 58897842452..ca008080a00 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
@@ -105,7 +105,7 @@ class WPTExpectationsUpdater(object):
def get_latest_try_jobs(self):
"""Returns the latest finished try jobs as Build objects."""
- return self.git_cl.latest_try_jobs(self._get_try_bots(), patchset=self.patchset)
+ return self.git_cl.latest_try_jobs(builder_names=self._get_try_bots(), patchset=self.patchset)
def get_failing_results_dict(self, build):
"""Returns a nested dict of failing test results.
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 dd71479f453..ebeaea74b4e 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github.py
@@ -348,16 +348,9 @@ class WPTGitHub(object):
def pr_for_chromium_commit(self, chromium_commit):
"""Returns a PR corresponding to the given ChromiumCommit, or None."""
- pull_request = self.pr_with_change_id(chromium_commit.change_id())
- if pull_request:
- return pull_request
- # The Change ID can't be used for commits made via Rietveld,
- # so we fall back to trying to use commit position here.
- # Note that Gerrit returns ToT+1 as the commit positions for in-flight
- # CLs, but they are scrubbed from the PR description and hence would
- # not be mismatched to random Chromium commits in the fallback.
- # TODO(robertma): Remove this fallback after Rietveld becomes read-only.
- return self.pr_with_position(chromium_commit.position)
+ # We rely on Change-Id because Gerrit returns ToT+1 as the commit
+ # positions for in-flight CLs, whereas Change-Id is permanent.
+ return self.pr_with_change_id(chromium_commit.change_id())
def pr_with_change_id(self, target_change_id):
for pull_request in self.all_pull_requests():
@@ -368,14 +361,6 @@ class WPTGitHub(object):
return pull_request
return None
- def pr_with_position(self, position):
- for pull_request in self.all_pull_requests():
- # Same as above, search all 'Cr-Commit-Position's.
- pr_commit_positions = self.extract_metadata('Cr-Commit-Position: ', pull_request.body, all_matches=True)
- if position in pr_commit_positions:
- return pull_request
- return None
-
@staticmethod
def extract_metadata(tag, commit_body, all_matches=False):
values = []
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py
index 621ef346ad3..8278637f494 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py
@@ -86,13 +86,6 @@ class MockWPTGitHub(object):
return pr
return None
- def pr_with_position(self, position):
- self.calls.append('pr_with_position')
- for pr in self.pull_requests:
- if position in pr.body:
- return pr
- return None
-
def pr_with_change_id(self, change_id):
self.calls.append('pr_with_change_id')
for pr in self.pull_requests:
diff --git a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py
index 2532bbb8aae..470346fb326 100644
--- a/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py
@@ -199,16 +199,6 @@ class WPTGitHubTest(unittest.TestCase):
pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
self.assertEqual(pull_request.number, 2)
- def test_pr_for_chromium_commit_falls_back_to_commit_position(self):
- self.wpt_github.all_pull_requests = lambda: [
- PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nCr-Commit-Position: refs/heads/master@{#10}', 'open', []),
- PullRequest('PR2', 2, 'body\nChange-Id: I00decade\nCr-Commit-Position: refs/heads/master@{#33}', 'open', []),
- ]
- chromium_commit = MockChromiumCommit(
- MockHost(), position='refs/heads/master@{#10}')
- pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
- self.assertEqual(pull_request.number, 1)
-
def test_pr_for_chromium_commit_multiple_change_ids(self):
self.wpt_github.all_pull_requests = lambda: [
PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nChange-Id: I00decade', 'open', []),
@@ -223,19 +213,3 @@ class WPTGitHubTest(unittest.TestCase):
MockHost(), change_id='I00decade', position='refs/heads/master@{#33}')
pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
self.assertEqual(pull_request.number, 1)
-
- def test_pr_for_chromium_commit_multiple_commit_positions(self):
- self.wpt_github.all_pull_requests = lambda: [
- PullRequest('PR1', 1, 'body\nCr-Commit-Position: refs/heads/master@{#10}\n'
- 'Cr-Commit-Position: refs/heads/master@{#33}', 'open', []),
- ]
-
- chromium_commit = MockChromiumCommit(
- MockHost(), position='refs/heads/master@{#10}')
- pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
- self.assertEqual(pull_request.number, 1)
-
- chromium_commit = MockChromiumCommit(
- MockHost(), position='refs/heads/master@{#33}')
- pull_request = self.wpt_github.pr_for_chromium_commit(chromium_commit)
- self.assertEqual(pull_request.number, 1)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
index fb2dc364295..0a840ca603e 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
@@ -47,7 +47,6 @@ from blinkpy.common import exit_codes
from blinkpy.common.net.file_uploader import FileUploader
from blinkpy.common.path_finder import PathFinder
from blinkpy.tool import grammar
-from blinkpy.web_tests.controllers.test_result_writer import TestResultWriter
from blinkpy.web_tests.controllers.web_test_finder import WebTestFinder
from blinkpy.web_tests.controllers.web_test_runner import WebTestRunner
from blinkpy.web_tests.layout_package import json_results_generator
@@ -260,7 +259,8 @@ class Manager(object):
def _collect_tests(self, args):
return self._finder.find_tests(args, test_list=self._options.test_list,
- fastest_percentile=self._options.fastest)
+ fastest_percentile=self._options.fastest,
+ filters=self._options.isolated_script_test_filter)
def _is_http_test(self, test):
return (
@@ -287,10 +287,11 @@ class Manager(object):
return tests_to_run, tests_to_skip
- def _test_input_for_file(self, test_file):
+ def _test_input_for_file(self, test_file, retry_attempt):
return TestInput(test_file,
self._options.slow_time_out_ms if self._test_is_slow(test_file) else self._options.time_out_ms,
- self._test_requires_lock(test_file))
+ self._test_requires_lock(test_file),
+ retry_attempt=retry_attempt)
def _test_requires_lock(self, test_file):
"""Returns True if the test needs to be locked when running multiple
@@ -381,7 +382,8 @@ class Manager(object):
for _ in xrange(iterations):
for test in tests_to_run:
for _ in xrange(repeat_each):
- test_inputs.append(self._test_input_for_file(test))
+ test_inputs.append(
+ self._test_input_for_file(test, retry_attempt))
return self._runner.run_tests(self._expectations, test_inputs,
tests_to_skip, num_workers, retry_attempt)
@@ -435,28 +437,50 @@ class Manager(object):
logs after that time.
"""
crashed_processes = []
+ test_to_crash_failure = {}
+
+ # reset static variables for Failure type classes
+ test_failures.TestFailure.port = self._port
+ test_failures.TestFailure.result_directory = self._results_directory
+ test_failures.TestFailure.filesystem = self._filesystem
+
for test, result in run_results.unexpected_results_by_name.iteritems():
if result.type != test_expectations.CRASH:
continue
for failure in result.failures:
- if not isinstance(failure, test_failures.FailureCrash):
- continue
- if failure.has_log:
+ if (not isinstance(failure, test_failures.FailureCrash) or
+ failure.has_log):
continue
crashed_processes.append([test, failure.process_name, failure.pid])
-
- sample_files = self._port.look_for_new_samples(crashed_processes, start_time)
- if sample_files:
- for test, sample_file in sample_files.iteritems():
- writer = TestResultWriter(self._filesystem, self._port, self._port.results_directory(), test)
- writer.copy_sample_file(sample_file)
-
- crash_logs = self._port.look_for_new_crash_logs(crashed_processes, start_time)
- if crash_logs:
- for test, (crash_log, crash_site) in crash_logs.iteritems():
- writer = TestResultWriter(self._filesystem, self._port, self._port.results_directory(), test)
- writer.write_crash_log(crash_log)
- run_results.unexpected_results_by_name[test].crash_site = crash_site
+ test_to_crash_failure[test] = failure
+
+ sample_files = self._port.look_for_new_samples(
+ crashed_processes, start_time) or {}
+ for test, sample_file in sample_files.iteritems():
+ test_failures.TestFailure.test_name = test
+ test_result = run_results.unexpected_results_by_name[test]
+ artifact_relative_path = self._port.output_filename(
+ test, test_failures.FILENAME_SUFFIX_SAMPLE, '.txt')
+ artifacts_sub_dir = test_result.artifacts.ArtifactsSubDirectory()
+ artifact_abspath = self._filesystem.join(
+ self._results_directory, artifacts_sub_dir, artifact_relative_path)
+ self._filesystem.maybe_make_directory(
+ self._filesystem.dirname(artifact_abspath))
+ self._filesystem.copyfile(sample_file, artifact_abspath)
+ test_result.artifacts.AddArtifact('sample_file',
+ self._filesystem.join(artifacts_sub_dir, artifact_relative_path))
+
+ new_crash_logs = self._port.look_for_new_crash_logs(
+ crashed_processes, start_time) or {}
+ for test, (crash_log, crash_site) in new_crash_logs.iteritems():
+ test_failures.TestFailure.test_name = test
+ failure.crash_log = crash_log
+ failure.has_log = self._port.output_contains_sanitizer_messages(
+ failure.crash_log)
+ test_result = run_results.unexpected_results_by_name[test]
+ test_result.crash_site = crash_site
+ test_to_crash_failure[test].create_artifacts(
+ test_result.artifacts, force_overwrite=True)
def _clobber_old_results(self):
dir_above_results_path = self._filesystem.dirname(self._results_directory)
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 76e5ff6065c..50660692d07 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
@@ -31,12 +31,10 @@ import hashlib
import logging
import re
-from blinkpy.web_tests.controllers import repaint_overlay
-from blinkpy.web_tests.controllers import test_result_writer
from blinkpy.web_tests.port.driver import DeviceFailure, DriverInput, DriverOutput
from blinkpy.web_tests.models import test_expectations
from blinkpy.web_tests.models import test_failures
-from blinkpy.web_tests.models.test_results import TestResult
+from blinkpy.web_tests.models.test_results import TestResult, build_test_result
from blinkpy.web_tests.models import testharness_results
@@ -50,7 +48,9 @@ def run_single_test(
port, options, results_directory, worker_name, primary_driver,
secondary_driver, test_input)
try:
- return runner.run()
+ test_result = runner.run()
+ test_result.create_artifacts()
+ return test_result
except DeviceFailure as error:
_log.error('device failed: %s', error)
return TestResult(test_input.test_name, device_failed=True)
@@ -69,6 +69,16 @@ class SingleTestRunner(object):
self._worker_name = worker_name
self._test_name = test_input.test_name
self._reference_files = test_input.reference_files
+ self._retry_attempt = test_input.retry_attempt
+
+ test_failures.TestFailure.port = port
+ test_failures.TestFailure.test_name = test_input.test_name
+ test_failures.TestFailure.result_directory = results_directory
+ test_failures.TestFailure.filesystem = self._filesystem
+ TestResult.repeat_tests = (
+ self._options.watch or self._options.repeat_each > 1 or self._options.iterations > 1)
+ TestResult.results_directory = self._results_directory
+ TestResult.filesystem = port.host.filesystem
# If this is a virtual test that uses the default flags instead of the
# virtual flags for it's references, run it on the secondary driver so
@@ -117,40 +127,55 @@ class SingleTestRunner(object):
driver_output = self._driver.run_test(self._driver_input())
expected_driver_output = self._expected_driver_output()
failures = self._handle_error(driver_output)
- test_result = TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr(),
- pid=driver_output.pid, crash_site=driver_output.crash_site)
- test_result_writer.write_test_result(self._filesystem, self._port, self._results_directory,
- self._test_name, driver_output, expected_driver_output, test_result.failures)
+
+ test_result = build_test_result(
+ driver_output, self._test_name, retry_attempt=self._retry_attempt,
+ failures=failures, test_run_time=driver_output.test_time,
+ pid=driver_output.pid, crash_site=driver_output.crash_site)
return test_result
def _run_compare_test(self):
"""Runs the signle 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)
- test_result = self._compare_output(expected_driver_output, driver_output)
- test_result_writer.write_test_result(self._filesystem, self._port, self._results_directory,
- self._test_name, driver_output, expected_driver_output, test_result.failures)
- return test_result
+ return build_test_result(
+ driver_output, self._test_name, retry_attempt=self._retry_attempt,
+ failures=failures, test_run_time=driver_output.test_time,
+ pid=driver_output.pid, crash_site=driver_output.crash_site)
def _run_rebaseline(self):
- """Similar to _run_compare_test(), but has the side effect of updating or adding baselines.
- This is called when --reset-results and/or --copy-baselines are specified in the command line.
- If --reset-results, in the returned result we treat baseline mismatch as success."""
+ """Similar to _run_compare_test(), but has the side effect of updating
+ or adding baselines. This is called when --reset-results and/or
+ --copy-baselines are specified in the command line. If --reset-results,
+ in the returned result we treat baseline mismatch as success."""
driver_output = self._driver.run_test(self._driver_input())
expected_driver_output = self._expected_driver_output()
- actual_failures = self._compare_output(expected_driver_output, driver_output).failures
- failures = self._handle_error(driver_output) if self._options.reset_results else actual_failures
- test_result_writer.write_test_result(self._filesystem, self._port, self._results_directory,
- self._test_name, driver_output, expected_driver_output, failures)
- self._update_or_add_new_baselines(driver_output, actual_failures)
- return TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr(),
- pid=driver_output.pid, crash_site=driver_output.crash_site)
+
+ all_failures = self._compare_output(
+ expected_driver_output, driver_output)
+
+ if self._options.reset_results:
+ # Only report leaks, timeouts and crashes and treat all other
+ # failures as successes
+ reported_failures = self._handle_error(driver_output)
+ else:
+ # Return comparison failures between the baseline and the actual
+ # output as well as leaks, timeouts and crashes
+ reported_failures = all_failures
+
+ self._update_or_add_new_baselines(driver_output, all_failures)
+
+ return build_test_result(
+ driver_output, self._test_name, retry_attempt=self._retry_attempt,
+ failures=reported_failures, test_run_time=driver_output.test_time,
+ pid=driver_output.pid, crash_site=driver_output.crash_site)
def _update_or_add_new_baselines(self, driver_output, failures):
"""Updates or adds new baselines for the test if necessary."""
if (test_failures.has_failure_type(test_failures.FailureTimeout, failures) or
- test_failures.has_failure_type(test_failures.FailureCrash, failures)):
+ test_failures.has_failure_type(test_failures.FailureCrash, failures)):
return
# We usually don't want to create a new baseline if there isn't one
# existing (which usually means this baseline isn't necessary, e.g.
@@ -164,19 +189,22 @@ class SingleTestRunner(object):
# optimize them later with optimize-baselines.
if self._is_all_pass_testharness_text_not_needing_baseline(driver_output.text):
driver_output.text = None
- self._save_baseline_data(driver_output.text, '.txt',
- test_failures.has_failure_type(test_failures.FailureMissingResult, failures) or
- test_failures.has_failure_type(test_failures.FailureTestHarnessAssertion, failures))
- self._save_baseline_data(driver_output.audio, '.wav',
- test_failures.has_failure_type(test_failures.FailureMissingAudio, failures))
+ self._save_baseline_data(
+ driver_output.text, '.txt',
+ test_failures.has_failure_type(test_failures.FailureMissingResult, failures) or
+ test_failures.has_failure_type(test_failures.FailureTestHarnessAssertion, failures))
+ self._save_baseline_data(
+ driver_output.audio, '.wav',
+ test_failures.has_failure_type(test_failures.FailureMissingAudio, failures))
expected_png = driver_output.image
if self._reference_files:
_log.warning('Can not rebaseline the image baseline of reftest %s', self._test_name)
# Let _save_baseline_data remove the '-expected.png' if it exists.
expected_png = None
- self._save_baseline_data(expected_png, '.png',
- test_failures.has_failure_type(test_failures.FailureMissingImage, failures))
+ self._save_baseline_data(
+ expected_png, '.png',
+ test_failures.has_failure_type(test_failures.FailureMissingImage, failures))
def _save_baseline_data(self, data, extension, force_create_new_baseline):
port = self._port
@@ -193,7 +221,8 @@ class SingleTestRunner(object):
elif self._options.copy_baselines:
output_dir = fs.join(port.baseline_version_dir(), fs.dirname(self._test_name))
else:
- output_dir = fs.dirname(port.expected_filename(self._test_name, extension, fallback_base_for_virtual=False))
+ output_dir = fs.dirname(
+ port.expected_filename(self._test_name, extension, fallback_base_for_virtual=False))
fs.maybe_make_directory(output_dir)
output_basename = fs.basename(fs.splitext(self._test_name)[0] + '-expected' + extension)
@@ -201,8 +230,9 @@ class SingleTestRunner(object):
# Remove |output_path| if it exists and is not the generic expectation to
# avoid extra baseline if the new baseline is the same as the fallback baseline.
- generic_dir = fs.join(port.web_tests_dir(),
- fs.dirname(port.lookup_virtual_test_base(self._test_name) or self._test_name))
+ generic_dir = fs.join(
+ port.web_tests_dir(), fs.dirname(
+ port.lookup_virtual_test_base(self._test_name) or self._test_name))
if (not data or output_dir != generic_dir) and fs.exists(output_path):
_log.info('Removing the current baseline "%s"', port.relative_test_filename(output_path))
fs.remove(output_path)
@@ -213,11 +243,13 @@ class SingleTestRunner(object):
if (current_expected_path and
fs.sha1(current_expected_path) == hashlib.sha1(data).hexdigest()):
if self._options.reset_results:
- _log.info('Not writing new baseline "%s" because it is the same as the current baseline',
- port.relative_test_filename(output_path))
+ _log.info(
+ 'Not writing new baseline "%s" because it is the same as the current baseline',
+ port.relative_test_filename(output_path))
else:
- _log.info('Not copying baseline to "%s" because the actual result is the same as the current baseline',
- port.relative_test_filename(output_path))
+ _log.info(
+ 'Not copying baseline to "%s" because the actual result is the same as the current baseline',
+ port.relative_test_filename(output_path))
return
if not data and not current_expected_path:
@@ -234,21 +266,24 @@ class SingleTestRunner(object):
if fs.exists(current_expected_path):
fs.copyfile(current_expected_path, output_path)
else:
- _log.error('Could not copy baseline to "%s" from "%s" because the source file does not exist',
- port.relative_test_filename(output_path), current_expected_path)
+ _log.error(
+ 'Could not copy baseline to "%s" from "%s" because the source file does not exist',
+ port.relative_test_filename(output_path), current_expected_path)
def _handle_error(self, driver_output, reference_filename=None):
"""Returns test failures if some unusual errors happen in driver's run.
Args:
driver_output: The output from the driver.
- reference_filename: The full path to the reference file which produced the driver_output.
- This arg is optional and should be used only in reftests until we have a better way to know
- which html file is used for producing the driver_output.
+ reference_filename: The full path to the reference file which produced
+ the driver_output. This arg is optional and should be used only in
+ reftests until we have a better way to know which html file
+ is used for producing the driver_output.
"""
failures = []
if driver_output.timeout:
- failures.append(test_failures.FailureTimeout(bool(reference_filename)))
+ failures.append(test_failures.FailureTimeout(
+ driver_output, bool(reference_filename)))
if reference_filename:
testname = self._port.relative_test_filename(reference_filename)
@@ -256,17 +291,18 @@ class SingleTestRunner(object):
testname = self._test_name
if driver_output.crash:
- failures.append(test_failures.FailureCrash(bool(reference_filename),
- driver_output.crashed_process_name,
- driver_output.crashed_pid,
- self._port.output_contains_sanitizer_messages(driver_output.crash_log)))
+ failures.append(test_failures.FailureCrash(
+ driver_output, is_reftest=bool(reference_filename),
+ process_name=driver_output.crashed_process_name,
+ pid=driver_output.crashed_pid,
+ has_log=self._port.output_contains_sanitizer_messages(driver_output.crash_log)))
if driver_output.error:
_log.debug('%s %s crashed, (stderr lines):', self._worker_name, testname)
else:
_log.debug('%s %s crashed, (no stderr)', self._worker_name, testname)
elif driver_output.leak:
- failures.append(test_failures.FailureLeak(bool(reference_filename),
- driver_output.leak_log))
+ failures.append(test_failures.FailureLeak(
+ driver_output, bool(reference_filename)))
_log.debug('%s %s leaked', self._worker_name, testname)
elif driver_output.error:
_log.debug('%s %s output stderr lines:', self._worker_name, testname)
@@ -280,25 +316,22 @@ class SingleTestRunner(object):
if driver_output.crash:
# Don't continue any more if we already have a crash.
- # In case of timeouts, we continue since we still want to see the text and image output.
- return TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr(),
- pid=driver_output.pid, crash_site=driver_output.crash_site)
+ # In case of timeouts, we continue since we still want
+ # to see the text and image output.
+ return failures
- failures.extend(self._check_extra_and_missing_baselines(expected_driver_output, driver_output))
+ failures.extend(
+ self._check_extra_and_missing_baselines(expected_driver_output, driver_output))
- testharness_completed, testharness_failures = self._compare_testharness_test(expected_driver_output,
- driver_output)
+ testharness_completed, testharness_failures = self._compare_testharness_test(
+ expected_driver_output, driver_output)
if testharness_completed:
failures.extend(testharness_failures)
else:
failures.extend(self._compare_text(expected_driver_output, driver_output))
failures.extend(self._compare_image(expected_driver_output, driver_output))
failures.extend(self._compare_audio(expected_driver_output, driver_output))
-
- has_repaint_overlay = (repaint_overlay.result_contains_repaint_rects(expected_driver_output.text) or
- repaint_overlay.result_contains_repaint_rects(driver_output.text))
- return TestResult(self._test_name, failures, driver_output.test_time, driver_output.has_stderr(),
- pid=driver_output.pid, has_repaint_overlay=has_repaint_overlay)
+ return failures
def _report_extra_baseline(self, driver_output, extension, message):
"""If the baseline file exists, logs an error and returns True."""
@@ -337,9 +370,11 @@ class SingleTestRunner(object):
# -expected.txt for testharness tests.
pass
elif not expected_driver_output.text:
- failures.append(test_failures.FailureMissingResult())
+ failures.append(test_failures.FailureMissingResult(
+ driver_output, expected_driver_output))
elif self._report_extra_baseline(driver_output, '.txt', 'does not produce text result'):
- failures.append(test_failures.FailureTextMismatch())
+ failures.append(test_failures.FailureTextNotGenerated(
+ driver_output, expected_driver_output))
if driver_output.image_hash:
if self._reference_files:
@@ -348,17 +383,22 @@ class SingleTestRunner(object):
pass
else:
if not expected_driver_output.image:
- failures.append(test_failures.FailureMissingImage())
- if not expected_driver_output.image_hash:
- failures.append(test_failures.FailureMissingImageHash())
+ failures.append(test_failures.FailureMissingImage(
+ driver_output, expected_driver_output))
+ elif not expected_driver_output.image_hash:
+ failures.append(test_failures.FailureMissingImageHash(
+ driver_output, expected_driver_output))
elif self._report_extra_baseline(driver_output, '.png', 'does not produce image result'):
- failures.append(test_failures.FailureImageHashMismatch())
+ failures.append(test_failures.FailureImageHashNotGenerated(
+ driver_output, expected_driver_output))
if driver_output.audio:
if not expected_driver_output.audio:
- failures.append(test_failures.FailureMissingAudio())
+ failures.append(test_failures.FailureMissingAudio(
+ driver_output, expected_driver_output))
elif self._report_extra_baseline(driver_output, '.wav', 'does not produce audio result'):
- failures.append(test_failures.FailureAudioMismatch())
+ failures.append(test_failures.FailureAudioNotGenerated(
+ driver_output, expected_driver_output))
return failures
@@ -372,7 +412,8 @@ class SingleTestRunner(object):
if not testharness_results.is_testharness_output(driver_output.text):
return False, []
if not testharness_results.is_testharness_output_passing(driver_output.text):
- return True, [test_failures.FailureTestHarnessAssertion()]
+ return True, [test_failures.FailureTestHarnessAssertion(
+ driver_output, expected_driver_output)]
return True, []
def _is_render_tree(self, text):
@@ -400,7 +441,8 @@ class SingleTestRunner(object):
return text
def remove_ng_text(results):
- processed = re.sub(r'LayoutNG(BlockFlow|ListItem|TableCell)', r'Layout\1', results)
+ processed = re.sub(
+ r'LayoutNG(BlockFlow|ListItem|TableCell)', r'Layout\1', results)
# LayoutTableCaption doesn't override LayoutBlockFlow::GetName, so
# render tree dumps have "LayoutBlockFlow" for captions.
processed = re.sub('LayoutNGTableCaption', 'LayoutBlockFlow', processed)
@@ -413,7 +455,8 @@ class SingleTestRunner(object):
return False
# There's a mix of NG and legacy names in both expected and actual,
# so just remove NG from both.
- return not self._port.do_text_results_differ(remove_ng_text(expected), remove_ng_text(actual))
+ return not self._port.do_text_results_differ(
+ remove_ng_text(expected), remove_ng_text(actual))
# LayoutNG name mismatch (e.g., LayoutBlockFlow vs. LayoutNGBlockFlow)
# is treated as pass
@@ -424,28 +467,34 @@ class SingleTestRunner(object):
if self._port.do_text_results_differ(
remove_chars(expected_text, ' \t\n'),
remove_chars(normalized_actual_text, ' \t\n')):
- return [test_failures.FailureTextMismatch()]
+ return [test_failures.FailureTextMismatch(
+ driver_output, expected_driver_output)]
# Space-only mismatch
if not self._port.do_text_results_differ(
remove_chars(expected_text, ' \t'),
remove_chars(normalized_actual_text, ' \t')):
- return [test_failures.FailureSpacesAndTabsTextMismatch()]
+ return [test_failures.FailureSpacesAndTabsTextMismatch(
+ driver_output, expected_driver_output)]
# Newline-only mismatch
if not self._port.do_text_results_differ(
remove_chars(expected_text, '\n'),
remove_chars(normalized_actual_text, '\n')):
- return [test_failures.FailureLineBreaksTextMismatch()]
+ return [test_failures.FailureLineBreaksTextMismatch(
+ driver_output, expected_driver_output)]
# Spaces and newlines
- return [test_failures.FailureSpaceTabLineBreakTextMismatch()]
+ return [test_failures.FailureSpaceTabLineBreakTextMismatch(
+ driver_output, expected_driver_output)]
def _compare_audio(self, expected_driver_output, driver_output):
if not expected_driver_output.audio or not driver_output.audio:
return []
- if self._port.do_audio_results_differ(expected_driver_output.audio, driver_output.audio):
- return [test_failures.FailureAudioMismatch()]
+ if self._port.do_audio_results_differ(
+ expected_driver_output.audio, driver_output.audio):
+ return [test_failures.FailureAudioMismatch(
+ driver_output, expected_driver_output)]
return []
def _get_normalized_output_text(self, output):
@@ -469,17 +518,25 @@ class SingleTestRunner(object):
return []
if driver_output.image_hash != expected_driver_output.image_hash:
- diff, err_str = self._port.diff_image(expected_driver_output.image, driver_output.image)
+ diff, err_str = self._port.diff_image(
+ expected_driver_output.image, driver_output.image)
+
+ if diff:
+ driver_output.image_diff = diff
+
if err_str:
- _log.warning(' %s : %s', self._test_name, err_str)
+ _log.error(' %s : %s', self._test_name, err_str)
driver_output.error = (driver_output.error or '') + err_str
- return [test_failures.FailureImageHashMismatch()]
- driver_output.image_diff = diff
- if driver_output.image_diff:
- return [test_failures.FailureImageHashMismatch()]
- # See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this isn't a full failure.
- _log.warning(' %s -> pixel hash failed (but diff passed)', self._test_name)
+ if diff or err_str:
+ return [
+ test_failures.FailureImageHashMismatch(
+ driver_output, expected_driver_output)]
+ else:
+ # See https://bugs.webkit.org/show_bug.cgi?id=69444 for why this
+ # isn't a full failure.
+ _log.warning(
+ ' %s -> pixel hash failed (but diff passed)', self._test_name)
return []
@@ -488,92 +545,113 @@ class SingleTestRunner(object):
total_test_time = test_output.test_time
expected_text = self._port.expected_text(self._test_name)
- expected_text_output = DriverOutput(text=expected_text, image=None, image_hash=None, audio=None)
+ expected_text_output = DriverOutput(
+ text=expected_text, image=None, image_hash=None, audio=None)
# This _compare_output compares text if expected text exists, ignores
# image, checks for extra baselines, and generates crash or timeout
# failures if needed.
- compare_text_result = self._compare_output(expected_text_output, test_output)
+ compare_text_failures = self._compare_output(
+ expected_text_output, test_output)
# If the test crashed, or timed out, there's no point in running the reference at all.
# This can save a lot of execution time if we have a lot of crashes or timeouts.
if test_output.crash or test_output.timeout:
- if test_output.crash:
- test_result_writer.write_test_result(
- self._filesystem, self._port, self._results_directory, self._test_name,
- test_output, expected_text_output, compare_text_result.failures)
- return compare_text_result
+ return build_test_result(
+ test_output, self._test_name, retry_attempt=self._retry_attempt,
+ failures=compare_text_failures, test_run_time=test_output.test_time,
+ pid=test_output.pid, crash_site=test_output.crash_site)
# A reftest can have multiple match references and multiple mismatch references;
# the test fails if any mismatch matches and all of the matches don't match.
- # To minimize the number of references we have to check, we run all of the mismatches first,
- # then the matches, and short-circuit out as soon as we can.
- # Note that sorting by the expectation sorts "!=" before "==" so this is easy to do.
+ # To minimize the number of references we have to check, we run all of the
+ # mismatches first, then the matches, and short-circuit out as soon as we can.
+ # Note that sorting by the expectation sorts "!=" before "==" so this is easy
+ # to do.
expected_output = None
- test_result = None
- putAllMismatchBeforeMatch = sorted
reference_test_names = []
- for expectation, reference_filename in putAllMismatchBeforeMatch(self._reference_files):
- if self._port.lookup_virtual_test_base(self._test_name):
- args = self._port.lookup_virtual_reference_args(self._test_name)
- else:
- args = self._port.lookup_physical_reference_args(self._test_name)
+ reftest_failures = []
+ if self._port.lookup_virtual_test_base(self._test_name):
+ args = self._port.lookup_virtual_reference_args(self._test_name)
+ else:
+ args = self._port.lookup_physical_reference_args(self._test_name)
+
+ # sort self._reference_files to put mismatch tests first
+ for expectation, reference_filename in sorted(self._reference_files):
reference_test_name = self._port.relative_test_filename(reference_filename)
reference_test_names.append(reference_test_name)
driver_input = DriverInput(reference_test_name, self._timeout_ms,
image_hash=test_output.image_hash, args=args)
expected_output = self._reference_driver.run_test(driver_input)
total_test_time += expected_output.test_time
- test_result = self._compare_output_with_reference(
+ reftest_failures = self._compare_output_with_reference(
expected_output, test_output, reference_filename, expectation == '!=')
- if (expectation == '!=' and test_result.failures) or (expectation == '==' and not test_result.failures):
+ if ((expectation == '!=' and reftest_failures) or
+ (expectation == '==' and not reftest_failures)):
break
assert expected_output
- assert test_result
# Combine compare_text_result and test_result
- test_result.failures.extend(compare_text_result.failures)
- test_result.has_repaint_overlay = compare_text_result.has_repaint_overlay
expected_output.text = expected_text_output.text
+ failures = reftest_failures + compare_text_failures
- test_result_writer.write_test_result(self._filesystem, self._port, self._results_directory,
- self._test_name, test_output, expected_output, test_result.failures)
-
- # FIXME: We don't really deal with a mix of reftest types properly. We pass in a set() to reftest_type
- # and only really handle the first of the references in the result.
+ # FIXME: We don't really deal with a mix of reftest types properly. We
+ # pass in a set() to reftest_type and only really handle the first of
+ # the references in the result.
reftest_type = list(set([reference_file[0] for reference_file in self._reference_files]))
- return TestResult(self._test_name, test_result.failures, total_test_time,
- test_result.has_stderr, reftest_type=reftest_type, pid=test_result.pid, crash_site=test_result.crash_site,
- references=reference_test_names, has_repaint_overlay=test_result.has_repaint_overlay)
- # The returned TestResult always has 0 test_run_time. _run_reftest() calculates total_run_time from test outputs.
- def _compare_output_with_reference(self, reference_driver_output, actual_driver_output, reference_filename, mismatch):
- has_stderr = reference_driver_output.has_stderr() or actual_driver_output.has_stderr()
+ return build_test_result(
+ test_output, self._test_name, retry_attempt=self._retry_attempt,
+ failures=failures, test_run_time=total_test_time, reftest_type=reftest_type,
+ pid=test_output.pid, crash_site=test_output.crash_site,
+ references=reference_test_names)
+
+ def _compare_output_with_reference(
+ self, reference_driver_output, actual_driver_output, reference_filename, mismatch):
failures = []
+
+ # Don't continue any more if we already have crash
failures.extend(self._handle_error(actual_driver_output))
if failures:
- # Don't continue any more if we already have crash or timeout.
- return TestResult(self._test_name, failures, 0, has_stderr, crash_site=actual_driver_output.crash_site)
- failures.extend(self._handle_error(reference_driver_output, reference_filename=reference_filename))
+ return failures
+ failures.extend(
+ self._handle_error(reference_driver_output,
+ reference_filename=reference_filename))
if failures:
- return TestResult(self._test_name, failures, 0, has_stderr, pid=actual_driver_output.pid,
- crash_site=reference_driver_output.crash_site)
+ return failures
if not actual_driver_output.image_hash:
- failures.append(test_failures.FailureReftestNoImageGenerated(reference_filename))
+ failures.append(test_failures.FailureReftestNoImageGenerated(
+ actual_driver_output, reference_driver_output, reference_filename))
elif not reference_driver_output.image_hash:
- failures.append(test_failures.FailureReftestNoReferenceImageGenerated(reference_filename))
+ failures.append(test_failures.FailureReftestNoReferenceImageGenerated(
+ actual_driver_output, reference_driver_output, reference_filename))
elif mismatch:
if reference_driver_output.image_hash == actual_driver_output.image_hash:
- failures.append(test_failures.FailureReftestMismatchDidNotOccur(reference_filename))
+ failures.append(test_failures.FailureReftestMismatchDidNotOccur(
+ actual_driver_output, reference_driver_output, reference_filename))
elif reference_driver_output.image_hash != actual_driver_output.image_hash:
- diff, err_str = self._port.diff_image(reference_driver_output.image, actual_driver_output.image)
+ diff, err_str = self._port.diff_image(
+ reference_driver_output.image, actual_driver_output.image)
if diff:
- failures.append(test_failures.FailureReftestMismatch(reference_filename))
- elif err_str:
+ actual_driver_output.image_diff = diff
+
+ if err_str:
_log.error(err_str)
+ actual_driver_output.error = (actual_driver_output.error or '') + err_str
+
+ if diff or err_str:
+ failures.append(
+ test_failures.FailureReftestMismatch(
+ actual_driver_output, reference_driver_output,
+ reference_filename))
+ elif err_str:
+ # TODO(rmhasan) Should we include this error message in the artifacts ?
+ _log.error(' %s : %s', self._test_name, err_str)
else:
- _log.warning(" %s -> ref test hashes didn't match but diff passed", self._test_name)
+ _log.warning(
+ " %s -> ref test hashes didn't match but diff passed",
+ self._test_name)
- return TestResult(self._test_name, failures, 0, has_stderr, pid=actual_driver_output.pid)
+ return failures
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py
deleted file mode 100644
index 308162aba45..00000000000
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer.py
+++ /dev/null
@@ -1,275 +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:
-#
-# * 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.
-
-
-import logging
-
-from blinkpy.common.html_diff import html_diff
-from blinkpy.common.unified_diff import unified_diff
-from blinkpy.web_tests.controllers import repaint_overlay
-from blinkpy.web_tests.models import test_failures
-
-
-_log = logging.getLogger(__name__)
-
-
-def write_test_result(filesystem, port, results_directory, test_name, driver_output,
- expected_driver_output, failures):
- """Write the test result to the result output directory."""
- root_output_dir = results_directory
- writer = TestResultWriter(filesystem, port, root_output_dir, test_name)
-
- if driver_output.error:
- writer.write_stderr(driver_output.error)
-
- for failure in failures:
- # FIXME: Instead of this long 'if' block, each failure class might
- # have a responsibility for writing a test result.
- if isinstance(failure, (test_failures.FailureMissingResult,
- test_failures.FailureTextMismatch,
- test_failures.FailureTestHarnessAssertion)):
- writer.write_text_files(driver_output.text, expected_driver_output.text)
- writer.create_text_diff_and_write_result(driver_output.text, expected_driver_output.text)
- elif isinstance(failure, test_failures.FailureMissingImage):
- writer.write_image_files(driver_output.image, expected_image=None)
- elif isinstance(failure, test_failures.FailureMissingImageHash):
- writer.write_image_files(driver_output.image, expected_driver_output.image)
- elif isinstance(failure, test_failures.FailureImageHashMismatch):
- writer.write_image_files(driver_output.image, expected_driver_output.image)
- writer.write_image_diff_files(driver_output.image_diff)
- elif isinstance(failure, (test_failures.FailureAudioMismatch,
- test_failures.FailureMissingAudio)):
- writer.write_audio_files(driver_output.audio, expected_driver_output.audio)
- elif isinstance(failure, test_failures.FailureCrash):
- crashed_driver_output = expected_driver_output if failure.is_reftest else driver_output
- writer.write_crash_log(crashed_driver_output.crash_log)
- elif isinstance(failure, test_failures.FailureLeak):
- writer.write_leak_log(driver_output.leak_log)
- elif isinstance(failure, (
- test_failures.FailureReftestMismatch,
- test_failures.FailureReftestNoImageGenerated,
- test_failures.FailureReftestNoReferenceImageGenerated)):
- writer.write_image_files(driver_output.image, expected_driver_output.image)
- if driver_output.image and expected_driver_output.image:
- diff_image, _ = port.diff_image(expected_driver_output.image, driver_output.image)
- if diff_image:
- writer.write_image_diff_files(diff_image)
- else:
- _log.warning('ref test mismatch did not produce an image diff.')
- if filesystem.exists(failure.reference_filename):
- writer.write_reftest(failure.reference_filename)
- else:
- _log.warning("reference %s was not found", failure.reference_filename)
- elif isinstance(failure, test_failures.FailureReftestMismatchDidNotOccur):
- writer.write_image_files(driver_output.image, expected_image=None)
- if filesystem.exists(failure.reference_filename):
- writer.write_reftest(failure.reference_filename)
- else:
- _log.warning("reference %s was not found", failure.reference_filename)
- else:
- assert isinstance(failure, test_failures.FailureTimeout)
-
- if expected_driver_output is not None:
- writer.create_repaint_overlay_result(driver_output.text, expected_driver_output.text)
-
-
-class TestResultWriter(object):
- """A class which handles all writing operations to the result directory."""
-
- # Filename pieces when writing failures to the test results directory.
- FILENAME_SUFFIX_ACTUAL = "-actual"
- FILENAME_SUFFIX_EXPECTED = "-expected"
- FILENAME_SUFFIX_DIFF = "-diff"
- FILENAME_SUFFIX_DIFFS = "-diffs"
- FILENAME_SUFFIX_STDERR = "-stderr"
- FILENAME_SUFFIX_CRASH_LOG = "-crash-log"
- FILENAME_SUFFIX_SAMPLE = "-sample"
- FILENAME_SUFFIX_LEAK_LOG = "-leak-log"
- FILENAME_SUFFIX_HTML_DIFF = "-pretty-diff"
- FILENAME_SUFFIX_OVERLAY = "-overlay"
-
- def __init__(self, filesystem, port, root_output_dir, test_name):
- self._filesystem = filesystem
- self._port = port
- self._root_output_dir = root_output_dir
- self._test_name = test_name
-
- def _write_file(self, path, contents):
- if contents is not None:
- fs = self._filesystem
- fs.maybe_make_directory(fs.dirname(path))
- fs.write_binary_file(path, contents)
-
- def _output_filename(self, suffix, extension):
- """Returns a filename based on the given suffix and extension.
-
- For example, if test name is "fast/dom/foo.html", the suffix is
- "-expected", and the extension is "-expected.txt", the return value is
- "fast/dom/foo-expected.txt".
- """
- return self._port.output_filename(self._test_name, suffix, extension)
-
- def _output_abspath(self, suffix, extension):
- """Similar to _output_filename, but returns an absolute path in output dir."""
- filename = self._output_filename(suffix, extension)
- return self._filesystem.join(self._root_output_dir, filename)
-
- def write_output_files(self, file_type, output, expected):
- """Writes the test output, the expected output in the results directory.
-
- The full output filename of the actual, for example, will be
- <filename>-actual<file_type>
- For instance,
- my_test-actual.txt
-
- Args:
- file_type: A string describing the test output file type, e.g. ".txt"
- output: A string containing the test output
- expected: A string containing the expected test output
- """
- actual_filename = self._output_abspath(self.FILENAME_SUFFIX_ACTUAL, file_type)
- expected_filename = self._output_abspath(self.FILENAME_SUFFIX_EXPECTED, file_type)
-
- self._write_file(actual_filename, output)
- self._write_file(expected_filename, expected)
-
- def write_stderr(self, error):
- filename = self._output_abspath(self.FILENAME_SUFFIX_STDERR, ".txt")
- self._write_file(filename, error)
-
- def write_crash_log(self, crash_log):
- filename = self._output_abspath(self.FILENAME_SUFFIX_CRASH_LOG, ".txt")
- self._write_file(filename, crash_log.encode('utf8', 'replace'))
-
- def write_leak_log(self, leak_log):
- filename = self._output_abspath(self.FILENAME_SUFFIX_LEAK_LOG, ".txt")
- self._write_file(filename, leak_log)
-
- def copy_sample_file(self, sample_file):
- filename = self._output_abspath(self.FILENAME_SUFFIX_SAMPLE, ".txt")
- self._filesystem.copyfile(sample_file, filename)
-
- def write_text_files(self, actual_text, expected_text):
- self.write_output_files(".txt", actual_text, expected_text)
-
- def create_text_diff_and_write_result(self, actual_text, expected_text):
- # FIXME: This function is actually doing the diffs as well as writing results.
- # It might be better to extract code which does 'diff' and make it a separate function.
- actual_text = actual_text or ''
- expected_text = expected_text or ''
-
- # Output a plain-text diff file.
- file_type = '.txt'
- actual_filename = self._output_abspath(self.FILENAME_SUFFIX_ACTUAL, file_type)
- expected_filename = self._output_abspath(self.FILENAME_SUFFIX_EXPECTED, file_type)
- diff = unified_diff(expected_text, actual_text, expected_filename, actual_filename)
- diff_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFF, file_type)
- self._write_file(diff_filename, diff)
-
- # Output a HTML diff file.
- html_diff_filename = self._output_abspath(self.FILENAME_SUFFIX_HTML_DIFF, '.html')
- html_diff_contents = html_diff(expected_text, actual_text)
- self._write_file(html_diff_filename, html_diff_contents)
-
- def create_repaint_overlay_result(self, actual_text, expected_text):
- html = repaint_overlay.generate_repaint_overlay_html(self._test_name, actual_text, expected_text)
- if html:
- overlay_filename = self._output_abspath(self.FILENAME_SUFFIX_OVERLAY, '.html')
- self._write_file(overlay_filename, html)
-
- def write_audio_files(self, actual_audio, expected_audio):
- self.write_output_files('.wav', actual_audio, expected_audio)
-
- def write_image_files(self, actual_image, expected_image):
- self.write_output_files('.png', actual_image, expected_image)
-
- def write_image_diff_files(self, image_diff):
- diff_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFF, '.png')
- self._write_file(diff_filename, image_diff)
-
- diffs_html_filename = self._output_abspath(self.FILENAME_SUFFIX_DIFFS, '.html')
- # FIXME: old-run-webkit-tests shows the diff percentage as the text contents of the "diff" link.
- # FIXME: old-run-webkit-tests include a link to the test file.
- html = ("""<!DOCTYPE HTML>
-<html>
-<head>
-<title>%(title)s</title>
-<style>.label{font-weight:bold}</style>
-</head>
-<body>
-Difference between images: <a href="%(diff_filename)s">diff</a><br>
-<div class=imageText></div>
-<div class=imageContainer data-prefix="%(prefix)s">Loading...</div>
-<script>
-(function() {
- var preloadedImageCount = 0;
- function preloadComplete() {
- ++preloadedImageCount;
- if (preloadedImageCount < 2)
- return;
- toggleImages();
- setInterval(toggleImages, 2000)
- }
-
- function preloadImage(url) {
- image = new Image();
- image.addEventListener('load', preloadComplete);
- image.src = url;
- return image;
- }
-
- function toggleImages() {
- if (text.textContent == 'Expected Image') {
- text.textContent = 'Actual Image';
- container.replaceChild(actualImage, container.firstChild);
- } else {
- text.textContent = 'Expected Image';
- container.replaceChild(expectedImage, container.firstChild);
- }
- }
-
- var text = document.querySelector('.imageText');
- var container = document.querySelector('.imageContainer');
- var actualImage = preloadImage(container.getAttribute('data-prefix') + '-actual.png');
- var expectedImage = preloadImage(container.getAttribute('data-prefix') + '-expected.png');
-})();
-</script>
-</body>
-</html>"""
- % {
- 'title': self._test_name,
- 'diff_filename': self._output_filename(self.FILENAME_SUFFIX_DIFF, '.png'),
- 'prefix': self._output_filename('', ''),
- })
- self._write_file(diffs_html_filename, html)
-
- def write_reftest(self, src_filepath):
- fs = self._filesystem
- dst_dir = fs.dirname(fs.join(self._root_output_dir, self._test_name))
- dst_filepath = fs.join(dst_dir, fs.basename(src_filepath))
- self._write_file(dst_filepath, fs.read_binary_file(src_filepath))
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py
deleted file mode 100644
index ac75cf9942a..00000000000
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_writer_unittest.py
+++ /dev/null
@@ -1,105 +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.
-
-import optparse
-import unittest
-
-from blinkpy.common.system.filesystem_mock import MockFileSystem
-from blinkpy.common.system.system_host_mock import MockSystemHost
-from blinkpy.web_tests.controllers.test_result_writer import write_test_result
-from blinkpy.web_tests.port.driver import DriverOutput
-from blinkpy.web_tests.port.test import TestPort
-from blinkpy.web_tests.models import test_failures
-
-
-class TestResultWriterTests(unittest.TestCase):
-
- def run_test(self, failures=None, files=None, filename='foo.html'):
- failures = failures or []
- host = MockSystemHost()
- host.filesystem.files = files or {}
- port = TestPort(host=host, port_name='test-mac-mac10.11', options=optparse.Values())
- actual_output = DriverOutput(text='', image=None, image_hash=None, audio=None)
- expected_output = DriverOutput(text='', image=None, image_hash=None, audio=None)
- write_test_result(host.filesystem, port, '/tmp', filename, actual_output, expected_output, failures)
- return host.filesystem
-
- def test_success(self):
- # Nothing is written when the test passes.
- fs = self.run_test(failures=[])
- self.assertEqual(fs.written_files, {})
-
- def test_reference_exists(self):
- failure = test_failures.FailureReftestMismatch()
- failure.reference_filename = '/src/exists-expected.html'
- files = {'/src/exists-expected.html': 'yup'}
- fs = self.run_test(failures=[failure], files=files)
- self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
- failure = test_failures.FailureReftestMismatchDidNotOccur()
- failure.reference_filename = '/src/exists-expected-mismatch.html'
- files = {'/src/exists-expected-mismatch.html': 'yup'}
- fs = self.run_test(failures=[failure], files=files)
- self.assertEqual(fs.written_files, {'/tmp/exists-expected-mismatch.html': 'yup'})
-
- def test_reference_is_missing(self):
- failure = test_failures.FailureReftestMismatch()
- failure.reference_filename = 'notfound.html'
- fs = self.run_test(failures=[failure], files={})
- self.assertEqual(fs.written_files, {})
-
- failure = test_failures.FailureReftestMismatchDidNotOccur()
- failure.reference_filename = 'notfound.html'
- fs = self.run_test(failures=[failure], files={})
- self.assertEqual(fs.written_files, {})
-
- def test_reftest_image_missing(self):
- failure = test_failures.FailureReftestNoImageGenerated()
- failure.reference_filename = '/src/exists-expected.html'
- files = {'/src/exists-expected.html': 'yup'}
- fs = self.run_test(failures=[failure], files=files)
- self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
- failure = test_failures.FailureReftestNoReferenceImageGenerated()
- failure.reference_filename = '/src/exists-expected.html'
- files = {'/src/exists-expected.html': 'yup'}
- fs = self.run_test(failures=[failure], files=files)
- self.assertEqual(fs.written_files, {'/tmp/exists-expected.html': 'yup'})
-
- def test_slash_in_test_name(self):
- failure = test_failures.FailureTestHarnessAssertion()
- fs = self.run_test(failures=[failure], filename='foo.html?a/b')
- self.assertTrue('/tmp/foo_a_b-actual.txt' in fs.written_files)
- self.assertEqual(set(fs.written_files.keys()), {
- '/tmp/foo_a_b-actual.txt',
- '/tmp/foo_a_b-diff.txt',
- '/tmp/foo_a_b-expected.txt',
- '/tmp/foo_a_b-pretty-diff.html',
- })
- # Should not mkdir '/tmp/foo.html?a'
- self.assertEqual(fs.dirs, {'/', '/tmp'})
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 3a2cdbc1e05..7d807763c32 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
@@ -27,6 +27,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import errno
+import fnmatch
import json
import logging
import math
@@ -47,7 +48,8 @@ class WebTestFinder(object):
self._filesystem = self._port.host.filesystem
self.WEB_TESTS_DIRECTORIES = ('src', 'third_party', 'blink', 'web_tests')
- def find_tests(self, args, test_list=None, fastest_percentile=None):
+ def find_tests(self, args, test_list=None, fastest_percentile=None, filters=None):
+ filters = filters or []
paths = self._strip_test_dir_prefixes(args)
if test_list:
paths += self._strip_test_dir_prefixes(self._read_test_names_from_file(test_list, self._port.TEST_PATH_SEPARATOR))
@@ -77,6 +79,7 @@ class WebTestFinder(object):
test_files = all_tests
running_all_tests = True
+ test_files = filter_tests(test_files, [f.split('::') for f in filters])
return (paths, test_files, running_all_tests)
def _times_trie(self):
@@ -213,3 +216,57 @@ class WebTestFinder(object):
index, count, len(tests_to_run), len(test_names))
return tests_to_run, other_tests
+
+
+def filter_tests(tests, filters):
+ """Returns a filtered list of tests to run.
+
+ The test-filtering semantics are documented in
+ https://bit.ly/chromium-test-runner-api and
+ https://bit.ly/chromium-test-list-format, but are as follows:
+
+ Each filter is a list of glob expressions, with each expression optionally
+ prefixed by a "-". If the glob starts with a "-", it is a negative glob,
+ otherwise it is a positive glob.
+
+ A test passes the filter if and only if it is explicitly matched by at
+ least one positive glob and no negative globs, or if there are no
+ positive globs and it is not matched by any negative globs.
+
+ Globbing is fairly limited; "?" is not allowed, and "*" must only appear
+ at the end of the glob. If multiple globs match a test, the longest match
+ wins. If both globs are the same length, an error is raised.
+
+ A test will be run only if it passes every filter.
+ """
+
+ def glob_sort_key(k):
+ if k and k[0] == '-':
+ return (len(k[1:]), k[1:])
+ else:
+ return (len(k), k)
+
+ for globs in filters:
+ include_by_default = all(glob.startswith('-') for glob in globs)
+ filtered_tests = []
+ for test in tests:
+ include = include_by_default
+ for glob in sorted(globs, key=glob_sort_key):
+ if (glob.startswith('-') and not glob[1:]) or not glob:
+ raise ValueError('Empty glob filter "%s"' % (filter,))
+ if '*' in glob[:-1]:
+ raise ValueError('Bad test filter "%s" specified; '
+ 'wildcards are only allowed at the end'
+ % (glob,))
+ if glob.startswith('-') and glob[1:] in globs:
+ raise ValueError('Both "%s" and "%s" specified in test '
+ 'filter' % (glob, glob[1:]))
+ if glob.startswith('-'):
+ include = include and not fnmatch.fnmatch(test, glob[1:])
+ else:
+ include = include or fnmatch.fnmatch(test, glob)
+ if include:
+ filtered_tests.append(test)
+ tests = filtered_tests
+
+ return tests
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 cb4de53b9f8..af793230aa5 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
@@ -128,3 +128,79 @@ class WebTestFinderTests(unittest.TestCase):
self.assertEqual(([3, 6], [1, 2, 4, 5]), split(tests, 0, 3))
self.assertEqual(([1, 4], [2, 3, 5, 6]), split(tests, 1, 3))
self.assertEqual(([2, 5], [1, 3, 4, 6]), split(tests, 2, 3))
+
+
+class FilterTestsTests(unittest.TestCase):
+ simple_test_list = ['a/a1.html', 'a/a2.html', 'b/b1.html']
+
+ def check(self, tests, filters, expected_tests):
+ self.assertEqual(expected_tests,
+ web_test_finder.filter_tests(tests, filters))
+
+ def test_no_filters(self):
+ self.check(self.simple_test_list, [],
+ self.simple_test_list)
+
+ def test_empty_glob_is_rejected(self):
+ self.assertRaises(ValueError, self.check,
+ self.simple_test_list, [['']], [])
+ self.assertRaises(ValueError, self.check,
+ self.simple_test_list, [['-']], [])
+
+ def test_one_all_positive_filter(self):
+ self.check(self.simple_test_list, [['a*']],
+ ['a/a1.html', 'a/a2.html'])
+
+ self.check(self.simple_test_list, [['a*', 'b*']],
+ self.simple_test_list)
+
+ def test_one_all_negative_filter(self):
+ self.check(self.simple_test_list, [['-c*']],
+ self.simple_test_list)
+
+ def test_one_mixed_filter(self):
+ self.check(self.simple_test_list, [['a*', '-c*']],
+ ['a/a1.html', 'a/a2.html'])
+
+ def test_two_all_positive_filters(self):
+ self.check(self.simple_test_list, [['a*'], ['b*']],
+ [])
+
+ def test_two_all_negative_filters(self):
+ self.check(self.simple_test_list, [['-a*'], ['-b*']],
+ [])
+
+ self.check(self.simple_test_list, [['-a*'], ['-c*']],
+ ['b/b1.html'])
+
+ def test_two_mixed_filters(self):
+ self.check(self.simple_test_list, [['a*'], ['-b*']],
+ ['a/a1.html', 'a/a2.html'])
+
+ def test_longest_glob_wins(self):
+ # These test that if two matching globs are specified as
+ # part of the same filter expression, the longest matching
+ # glob wins (takes precedence). The order of the two globs
+ # must not matter.
+ self.check(self.simple_test_list, [['a/a*', '-a/a2*']],
+ ['a/a1.html'])
+ self.check(self.simple_test_list, [['-a/a*', 'a/a2*']],
+ ['a/a2.html'])
+
+ # In this test, the positive and negative globs are in
+ # separate filter expressions, so a2 should be filtered out
+ # and nothing should run (tests should only be run if they
+ # would be run by every filter individually).
+ self.check(self.simple_test_list, [['-a/a*'], ['a/a2*']],
+ [])
+
+ def test_only_trailing_globs_work(self):
+ self.check(self.simple_test_list, [['a*']],
+ ['a/a1.html', 'a/a2.html'])
+
+ # These test that if you have a glob that contains a "*" that isn't
+ # at the end, it is rejected; only globs at the end should work.
+ self.assertRaises(ValueError, self.check,
+ self.simple_test_list, [['*1.html']], [])
+ self.assertRaises(ValueError, self.check,
+ self.simple_test_list, [['a*.html']], [])
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
index 4980b260135..16b16780b4c 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
@@ -69,7 +69,6 @@ class WebTestRunner(object):
self._expectations = None
self._test_inputs = []
- self._retry_attempt = 0
self._shards_to_redo = []
self._current_run_results = None
@@ -84,10 +83,8 @@ class WebTestRunner(object):
# prevents content shell reuse.
if not self._options.must_use_derived_batch_size and retry_attempt >= 1:
batch_size = 1
-
self._expectations = expectations
self._test_inputs = test_inputs
- self._retry_attempt = retry_attempt
test_run_results = TestRunResults(self._expectations, len(test_inputs) + len(tests_to_skip))
self._current_run_results = test_run_results
@@ -162,17 +159,12 @@ class WebTestRunner(object):
shard.test_inputs = list(itertools.chain(*tests_by_args.values()))
def _worker_factory(self, worker_connection):
- results_directory = self._results_directory
- if self._retry_attempt > 0:
- results_directory = self._filesystem.join(self._results_directory,
- 'retry_%d' % self._retry_attempt)
- self._filesystem.maybe_make_directory(results_directory)
- return Worker(worker_connection, results_directory, self._options)
+ return Worker(worker_connection, self._results_directory, self._options)
def _mark_interrupted_tests_as_skipped(self, test_run_results):
for test_input in self._test_inputs:
if test_input.test_name not in test_run_results.results_by_name:
- result = test_results.TestResult(test_input.test_name, [test_failures.FailureEarlyExit()])
+ result = test_results.TestResult(test_input.test_name, failures=[test_failures.FailureEarlyExit()])
# FIXME: We probably need to loop here if there are multiple iterations.
# FIXME: Also, these results are really neither expected nor unexpected. We probably
# need a third type of result.
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 38bd0aff693..e83e182d034 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
@@ -40,6 +40,7 @@ from blinkpy.web_tests.models.test_run_results import TestRunResults
from blinkpy.web_tests.models.test_input import TestInput
from blinkpy.web_tests.models.test_results import TestResult
from blinkpy.web_tests.port.test import TestPort
+from blinkpy.web_tests.port.driver import DriverOutput
TestExpectations = test_expectations.TestExpectations
@@ -85,8 +86,13 @@ class LockCheckingRunner(WebTestRunner):
@unittest.skipIf(sys.platform == 'win32', 'may not clean up child processes')
class WebTestRunnerTests(unittest.TestCase):
- # pylint: disable=protected-access
+ def setUp(self):
+ self._actual_output = DriverOutput(
+ text='', image=None, image_hash=None, audio=None)
+ self._expected_output = DriverOutput(
+ text='', image=None, image_hash=None, audio=None)
+ # pylint: disable=protected-access
def _runner(self, port=None):
# FIXME: we shouldn't have to use run_web_tests.py to get the options we need.
options = run_web_tests.parse_args(['--platform', 'test-mac-mac10.11'])[0]
@@ -139,7 +145,11 @@ class WebTestRunnerTests(unittest.TestCase):
runner._expectations = expectations
run_results = TestRunResults(expectations, 1)
- result = TestResult(test_name=test, failures=[test_failures.FailureReftestMismatchDidNotOccur()], reftest_type=['!='])
+ result = TestResult(
+ test_name=test, failures=[
+ test_failures.FailureReftestMismatchDidNotOccur(
+ self._actual_output, self._expected_output)],
+ reftest_type=['!='])
runner._update_summary_with_result(run_results, result)
self.assertEqual(1, run_results.expected)
self.assertEqual(0, run_results.unexpected)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
index ade2f8ec5d2..855674c6f06 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_failures.py
@@ -29,7 +29,78 @@
import cPickle
from blinkpy.web_tests.models import test_expectations
-
+from blinkpy.web_tests.controllers import repaint_overlay
+from blinkpy.common.html_diff import html_diff
+from blinkpy.common.unified_diff import unified_diff
+
+# TODO(rmhasan) Create a unit test for each Failure type and make
+# sure each artifact is written to the correct path
+
+# FIXME: old-run-webkit-tests shows the diff percentage as the text
+# contents of the "diff" link.
+# FIXME: old-run-webkit-tests include a link to the test file.
+_image_diff_html_template = """<!DOCTYPE HTML>
+<html>
+<head>
+<title>%(title)s</title>
+<style>.label{font-weight:bold}</style>
+</head>
+<body>
+Difference between images: <a href="%(diff_filename)s">diff</a><br>
+<div class=imageText></div>
+<div class=imageContainer data-prefix="%(prefix)s">Loading...</div>
+<script>
+(function() {
+var preloadedImageCount = 0;
+function preloadComplete() {
+++preloadedImageCount;
+if (preloadedImageCount < 2)
+ return;
+toggleImages();
+setInterval(toggleImages, 2000)
+}
+
+function preloadImage(url) {
+image = new Image();
+image.addEventListener('load', preloadComplete);
+image.src = url;
+return image;
+}
+
+function toggleImages() {
+if (text.textContent == 'Expected Image') {
+ text.textContent = 'Actual Image';
+ container.replaceChild(actualImage, container.firstChild);
+} else {
+ text.textContent = 'Expected Image';
+ container.replaceChild(expectedImage, container.firstChild);
+}
+}
+
+var text = document.querySelector('.imageText');
+var container = document.querySelector('.imageContainer');
+var actualImage = preloadImage(container.getAttribute('data-prefix') + '-actual.png');
+var expectedImage = preloadImage(container.getAttribute('data-prefix') + '-expected.png');
+})();
+</script>
+</body>
+</html>"""
+
+# Filename pieces when writing failures to the test results directory.
+FILENAME_SUFFIX_ACTUAL = "-actual"
+FILENAME_SUFFIX_EXPECTED = "-expected"
+FILENAME_SUFFIX_DIFF = "-diff"
+FILENAME_SUFFIX_DIFFS = "-diffs"
+FILENAME_SUFFIX_STDERR = "-stderr"
+FILENAME_SUFFIX_CRASH_LOG = "-crash-log"
+FILENAME_SUFFIX_SAMPLE = "-sample"
+FILENAME_SUFFIX_LEAK_LOG = "-leak-log"
+FILENAME_SUFFIX_HTML_DIFF = "-pretty-diff"
+FILENAME_SUFFIX_OVERLAY = "-overlay"
+
+
+_ext_to_file_type = {
+ '.txt': 'text', '.png': 'image', '.wav': 'audio'}
def is_reftest_failure(failure_list):
input_failure_types = {type(f) for f in failure_list}
@@ -58,10 +129,12 @@ def determine_result_type(failure_list):
Returns:
one of the test_expectations result types - PASS, FAIL, CRASH, etc.
"""
-
if not failure_list or len(failure_list) == 0:
return test_expectations.PASS
+ if has_failure_type(PassWithStderr, failure_list):
+ assert len(failure_list) == 1
+ return test_expectations.PASS
if has_failure_type(FailureCrash, failure_list):
return test_expectations.CRASH
elif has_failure_type(FailureLeak, failure_list):
@@ -77,11 +150,13 @@ def determine_result_type(failure_list):
return test_expectations.MISSING
else:
is_text_failure = (has_failure_type(FailureTextMismatch, failure_list) or
- has_failure_type(FailureTestHarnessAssertion, failure_list))
- is_image_failure = (has_failure_type(FailureImageHashIncorrect, failure_list) or
- has_failure_type(FailureImageHashMismatch, failure_list) or
+ has_failure_type(FailureTestHarnessAssertion, failure_list) or
+ has_failure_type(FailureTextNotGenerated, failure_list))
+ is_image_failure = (has_failure_type(FailureImageHashMismatch, failure_list) or
+ has_failure_type(FailureImageHashNotGenerated, failure_list) or
is_reftest_failure(failure_list))
- is_audio_failure = has_failure_type(FailureAudioMismatch, failure_list)
+ is_audio_failure = (has_failure_type(FailureAudioMismatch, failure_list) or
+ has_failure_type(FailureAudioNotGenerated, failure_list))
if is_text_failure and is_image_failure:
return test_expectations.IMAGE_PLUS_TEXT
elif is_text_failure:
@@ -97,7 +172,44 @@ def determine_result_type(failure_list):
class TestFailure(object):
- """Abstract base class that defines the failure interface."""
+
+ port = None
+ test_name = None
+ filesystem = None
+ result_directory = None
+
+ def __init__(self, actual_driver_output, expected_driver_output):
+ self.actual_driver_output = actual_driver_output
+ self.expected_driver_output = expected_driver_output
+ self.has_stderr = False
+ self.has_repaint_overlay = False
+ self.is_reftest = False
+ if actual_driver_output:
+ self.has_stderr = actual_driver_output.has_stderr()
+ if expected_driver_output:
+ self.has_stderr |= expected_driver_output.has_stderr()
+
+ def _write_to_artifacts(
+ self, typ_artifacts, artifact_name, path, content, force_overwrite):
+ typ_artifacts.CreateArtifact(
+ artifact_name, path, content, force_overwrite=force_overwrite)
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ if self.actual_driver_output.error:
+ artifact_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_STDERR, '.txt')
+
+ # some ref tests don't produce any text output and also
+ # have a text baseline. They also produce an image mismatch
+ # error. If the test driver produces stderr then an exception
+ # will be raised because we will be writing that stderr twice
+ artifacts_abspath = self.filesystem.join(
+ self.result_directory, typ_artifacts.ArtifactsSubDirectory(),
+ artifact_filename)
+ if not self.filesystem.exists(artifacts_abspath):
+ self._write_to_artifacts(
+ typ_artifacts, 'stderr', artifact_filename,
+ self.actual_driver_output.error, force_overwrite=True)
@staticmethod
def loads(s):
@@ -125,13 +237,34 @@ class TestFailure(object):
"""Returns True if we should kill the driver before the next test."""
return False
+ def message(self):
+ raise NotImplementedError
+
+ def text_mismatch_category(self):
+ raise NotImplementedError
+
+
+class PassWithStderr(TestFailure):
+
+ def __init__(self, driver_output):
+ # TODO (rmhasan): Should we write out the reference driver standard
+ # error
+ super(PassWithStderr, self).__init__(driver_output, None)
+
+ def message(self):
+ return 'test passed but has standard error output'
+
class FailureTimeout(TestFailure):
- def __init__(self, is_reftest=False):
- super(FailureTimeout, self).__init__()
+ def __init__(self, actual_driver_output, is_reftest=False):
+ super(FailureTimeout, self).__init__(
+ actual_driver_output, None)
self.is_reftest = is_reftest
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ pass
+
def message(self):
return 'test timed out'
@@ -141,12 +274,24 @@ class FailureTimeout(TestFailure):
class FailureCrash(TestFailure):
- def __init__(self, is_reftest=False, process_name='content_shell', pid=None, has_log=False):
- super(FailureCrash, self).__init__()
+ def __init__(self, actual_driver_output, is_reftest=False,
+ process_name='content_shell', pid=None, has_log=False):
+ super(FailureCrash, self).__init__(
+ actual_driver_output, None)
self.process_name = process_name
self.pid = pid
self.is_reftest = is_reftest
self.has_log = has_log
+ self.crash_log = self.actual_driver_output.crash_log
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ super(FailureCrash, self).create_artifacts(typ_artifacts, force_overwrite)
+ if self.crash_log:
+ artifact_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_CRASH_LOG, '.txt')
+ self._write_to_artifacts(
+ typ_artifacts, 'crash_log', artifact_filename,
+ self.crash_log.encode('utf8', 'replace'), force_overwrite)
def message(self):
if self.pid:
@@ -159,28 +304,114 @@ class FailureCrash(TestFailure):
class FailureLeak(TestFailure):
- def __init__(self, is_reftest=False, log=''):
- super(FailureLeak, self).__init__()
+ def __init__(self, actual_driver_output, is_reftest=False):
+ super(FailureLeak, self).__init__(
+ actual_driver_output, None)
self.is_reftest = is_reftest
- self.log = log
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ super(FailureLeak, self).create_artifacts(typ_artifacts, force_overwrite)
+ artifact_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_LEAK_LOG, '.txt')
+ self.log = self.actual_driver_output.leak_log
+ self._write_to_artifacts(
+ typ_artifacts, 'leak_log', artifact_filename, self.log, force_overwrite)
def message(self):
return 'leak detected: %s' % (self.log)
-class FailureMissingResult(TestFailure):
+class ActualAndBaselineArtifacts(TestFailure):
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ super(ActualAndBaselineArtifacts, self).create_artifacts(
+ typ_artifacts, force_overwrite)
+ self.actual_artifact_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_ACTUAL, self.file_ext)
+ self.expected_artifact_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_EXPECTED, self.file_ext)
+ attr = _ext_to_file_type[self.file_ext]
+ if getattr(self.actual_driver_output, attr):
+ self._write_to_artifacts(
+ typ_artifacts, 'actual_%s' % attr, self.actual_artifact_filename,
+ getattr(self.actual_driver_output, attr), force_overwrite)
+ if getattr(self.expected_driver_output, attr):
+ self._write_to_artifacts(
+ typ_artifacts, 'expected_%s' % attr, self.expected_artifact_filename,
+ getattr(self.expected_driver_output, attr), force_overwrite)
+
+ def message(self):
+ raise NotImplementedError
+
+
+class FailureText(ActualAndBaselineArtifacts):
+
+ def __init__(self, actual_driver_output, expected_driver_output):
+ super(FailureText, self).__init__(
+ actual_driver_output, expected_driver_output)
+ self.has_repaint_overlay = (
+ repaint_overlay.result_contains_repaint_rects(
+ actual_driver_output.text) or
+ repaint_overlay.result_contains_repaint_rects(
+ expected_driver_output.text))
+ self.file_ext = '.txt'
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ # TODO (rmhasan): See if you can can only output diff files for
+ # non empty text.
+ super(FailureText, self).create_artifacts(
+ typ_artifacts, force_overwrite)
+ expected_text = self.expected_driver_output.text or ''
+ actual_text = self.actual_driver_output.text or ''
+ artifacts_abs_path = self.filesystem.join(
+ self.result_directory, typ_artifacts.ArtifactsSubDirectory())
+ diff_content = unified_diff(
+ expected_text, actual_text,
+ self.filesystem.join(artifacts_abs_path, self.expected_artifact_filename),
+ self.filesystem.join(artifacts_abs_path, self.actual_artifact_filename))
+ diff_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_DIFF, '.txt')
+ html_diff_content = html_diff(expected_text, actual_text)
+ html_diff_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')
+ self._write_to_artifacts(
+ typ_artifacts, 'text_diff', diff_filename, diff_content, force_overwrite)
+ self._write_to_artifacts(
+ typ_artifacts, 'pretty_text_diff', html_diff_filename,
+ html_diff_content, force_overwrite)
+
+ def message(self):
+ raise NotImplementedError
+
+ def text_mismatch_category(self):
+ raise NotImplementedError
+
+
+class FailureMissingResult(FailureText):
def message(self):
return '-expected.txt was missing'
-class FailureTestHarnessAssertion(TestFailure):
+class FailureTextNotGenerated(FailureText):
def message(self):
- return 'asserts failed'
+ return 'test did not generate text results'
+
+class FailureTextMismatch(FailureText):
-class FailureTextMismatch(TestFailure):
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ super(FailureTextMismatch, self).create_artifacts(
+ typ_artifacts, force_overwrite)
+ html = repaint_overlay.generate_repaint_overlay_html(
+ self.test_name, self.actual_driver_output.text,
+ self.expected_driver_output.text)
+ if html:
+ overlay_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_OVERLAY, '.html')
+ self._write_to_artifacts(
+ typ_artifacts, 'overlay', overlay_filename, html, force_overwrite)
def message(self):
return 'text diff'
@@ -189,6 +420,12 @@ class FailureTextMismatch(TestFailure):
return 'general text mismatch'
+class FailureTestHarnessAssertion(FailureText):
+
+ def message(self):
+ return 'asserts failed'
+
+
class FailureSpacesAndTabsTextMismatch(FailureTextMismatch):
def message(self):
@@ -216,83 +453,169 @@ class FailureSpaceTabLineBreakTextMismatch(FailureTextMismatch):
return 'spaces, tabs and newlines only'
-class FailureMissingImageHash(TestFailure):
+class FailureImage(ActualAndBaselineArtifacts):
+
+ def __init__(self, actual_driver_output, expected_driver_output):
+ super(FailureImage, self).__init__(
+ actual_driver_output, expected_driver_output)
+ self.file_ext = '.png'
def message(self):
- return '-expected.png was missing an embedded checksum'
+ raise NotImplementedError
-class FailureMissingImage(TestFailure):
+class FailureImageHashNotGenerated(FailureImage):
def message(self):
- return '-expected.png was missing'
+ return 'test did not generate image results'
-class FailureImageHashMismatch(TestFailure):
+class FailureMissingImageHash(FailureImage):
def message(self):
- return 'image diff'
+ return '-expected.png was missing an embedded checksum'
-class FailureImageHashIncorrect(TestFailure):
+class FailureMissingImage(FailureImage):
def message(self):
- return '-expected.png embedded checksum is incorrect'
+ return '-expected.png was missing'
+
+class FailureImageHashMismatch(FailureImage):
-class FailureReftestMismatch(TestFailure):
+ def message(self):
+ return 'image diff'
- def __init__(self, reference_filename=None):
- super(FailureReftestMismatch, self).__init__()
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ # Need this if statement in case the image diff process fails
+ if self.actual_driver_output.image_diff:
+ diff_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_DIFF, '.png')
+ diff = self.actual_driver_output.image_diff
+ self._write_to_artifacts(
+ typ_artifacts, 'image_diff', diff_filename, diff, force_overwrite)
+ diffs_html_filename = self.port.output_filename(
+ self.test_name, FILENAME_SUFFIX_DIFFS, '.html')
+ diffs_html = _image_diff_html_template % {
+ 'title': self.test_name, 'diff_filename': diff_filename,
+ 'prefix': self.port.output_filename(self.test_name, '', '')}
+ self._write_to_artifacts(
+ typ_artifacts, 'pretty_image_diff', diffs_html_filename,
+ diffs_html, force_overwrite)
+
+ super(FailureImageHashMismatch, self).create_artifacts(
+ typ_artifacts, force_overwrite)
+
+
+class FailureReftestMixin(object):
+ # This mixin will be used by reftest failure types to create a reference
+ # file artifact along with image mismatch artifacts, actual image output,
+ # reference driver output, and standard error output. The actual reftest
+ # failure types used in single_test_runner.py each have an inheritance list.
+ # The order of this list decides the call order of overridden methods like the
+ # constructor and create_artifacts. For example, FailureReftestMismatch
+ # has FailureReftestMixin followed by FailureImageHashMismatch. So when
+ # create_artifacts is called on that class, FailureReftestMixin's create_artifacts
+ # will be called first and then when that method calls the super class's
+ # create_artifacts, it will call FailureImageHashMismatch's create_artifacts.
+
+ def __init__(self, actual_driver_output, expected_driver_output,
+ reference_filename=None):
+ super(FailureReftestMixin, self).__init__(
+ actual_driver_output, expected_driver_output)
self.reference_filename = reference_filename
+ self.reference_file_type = 'reference_file_mismatch'
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ super(FailureReftestMixin, self).create_artifacts(
+ typ_artifacts, force_overwrite)
+ sub_dir = typ_artifacts.ArtifactsSubDirectory()
+ artifact_filename = self.filesystem.join(
+ sub_dir, self.filesystem.dirname(self.test_name),
+ self.filesystem.basename(self.reference_filename))
+ artifact_abspath = self.filesystem.join(
+ self.result_directory, artifact_filename)
+ # a reference test may include a page that does not exist in the
+ # web test directory, like about:blank pages
+ if (not self.filesystem.exists(artifact_abspath) and
+ self.filesystem.exists(self.reference_filename)):
+ self.filesystem.maybe_make_directory(
+ self.filesystem.dirname(artifact_abspath))
+ self.filesystem.copyfile(self.reference_filename, artifact_abspath)
+ typ_artifacts.AddArtifact(self.reference_file_type, artifact_filename,
+ raise_exception_for_duplicates=False)
+
+ def message(self):
+ raise NotImplementedError
+
+
+class FailureReftestMismatch(FailureReftestMixin, FailureImageHashMismatch):
def message(self):
return 'reference mismatch'
-class FailureReftestMismatchDidNotOccur(TestFailure):
+class FailureReftestMismatchDidNotOccur(FailureReftestMixin, FailureImage):
- def __init__(self, reference_filename=None):
- super(FailureReftestMismatchDidNotOccur, self).__init__()
- self.reference_filename = reference_filename
+ def __init__(self, actual_driver_output, expected_driver_output,
+ reference_filename=None):
+ super(FailureReftestMismatchDidNotOccur, self).__init__(
+ actual_driver_output, expected_driver_output, reference_filename)
+ self.reference_file_type = 'reference_file_match'
def message(self):
return "reference mismatch didn't happen"
-class FailureReftestNoImageGenerated(TestFailure):
-
- def __init__(self, reference_filename=None):
- super(FailureReftestNoImageGenerated, self).__init__()
- self.reference_filename = reference_filename
+class FailureReftestNoImageGenerated(FailureReftestMixin, FailureImage):
def message(self):
return "reference test didn't generate pixel results"
-class FailureReftestNoReferenceImageGenerated(TestFailure):
-
- def __init__(self, reference_filename=None):
- super(FailureReftestNoReferenceImageGenerated, self).__init__()
- self.reference_filename = reference_filename
+class FailureReftestNoReferenceImageGenerated(FailureReftestMixin, FailureImage):
def message(self):
return "-expected.html didn't generate pixel results"
-class FailureMissingAudio(TestFailure):
+class FailureAudio(ActualAndBaselineArtifacts):
+
+ def __init__(self, actual_driver_output, expected_driver_output):
+ super(FailureAudio, self).__init__(
+ actual_driver_output, expected_driver_output)
+ self.file_ext = '.wav'
+
+ def message(self):
+ raise NotImplementedError
+
+
+class FailureMissingAudio(FailureAudio):
def message(self):
return 'expected audio result was missing'
-class FailureAudioMismatch(TestFailure):
+class FailureAudioMismatch(FailureAudio):
def message(self):
return 'audio mismatch'
+class FailureAudioNotGenerated(FailureAudio):
+
+ def message(self):
+ return 'audio result not generated'
+
+
class FailureEarlyExit(TestFailure):
+ def __init__(self, actual_driver_output=None, expected_driver_output=None):
+ super(FailureEarlyExit, self).__init__(
+ actual_driver_output, expected_driver_output)
+
+ def create_artifacts(self, typ_artifacts, force_overwrite=False):
+ pass
def message(self):
return 'skipped due to early exit'
@@ -306,9 +629,10 @@ ALL_FAILURE_CLASSES = (FailureTimeout, FailureCrash, FailureMissingResult,
FailureLineBreaksTextMismatch, FailureSpaceTabLineBreakTextMismatch,
FailureMissingImageHash,
FailureMissingImage, FailureImageHashMismatch,
- FailureImageHashIncorrect, FailureReftestMismatch,
+ FailureReftestMismatch,
FailureReftestMismatchDidNotOccur,
FailureReftestNoImageGenerated,
FailureReftestNoReferenceImageGenerated,
FailureMissingAudio, FailureAudioMismatch,
- FailureEarlyExit)
+ FailureEarlyExit, FailureImageHashNotGenerated,
+ FailureTextNotGenerated, FailureAudioNotGenerated)
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 01a0a28f0b4..34b40e31b18 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
@@ -27,6 +27,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import unittest
+from blinkpy.web_tests.port.driver import DriverOutput
from blinkpy.web_tests.models.test_failures import (
ALL_FAILURE_CLASSES, determine_result_type,
@@ -36,8 +37,12 @@ from blinkpy.web_tests.models.test_failures import (
class TestFailuresTest(unittest.TestCase):
+ def setUp(self):
+ self._actual_output = DriverOutput(text=None, image=None, image_hash=None, audio=None)
+ self._expected_output = DriverOutput(text=None, image=None, image_hash=None, audio=None)
+
def assert_loads(self, cls):
- failure_obj = cls()
+ failure_obj = cls(self._actual_output, self._expected_output)
s = failure_obj.dumps()
new_failure_obj = TestFailure.loads(s)
self.assertIsInstance(new_failure_obj, cls)
@@ -53,12 +58,12 @@ class TestFailuresTest(unittest.TestCase):
def message(self):
return ''
- failure_obj = UnknownFailure()
+ failure_obj = UnknownFailure(self._actual_output, self._expected_output)
with self.assertRaises(ValueError):
determine_result_type([failure_obj])
def test_message_is_virtual(self):
- failure_obj = TestFailure()
+ failure_obj = TestFailure(self._actual_output, self._expected_output)
with self.assertRaises(NotImplementedError):
failure_obj.message()
@@ -67,14 +72,23 @@ class TestFailuresTest(unittest.TestCase):
self.assert_loads(c)
def test_equals(self):
- self.assertEqual(FailureCrash(), FailureCrash())
- self.assertNotEqual(FailureCrash(), FailureTimeout())
- crash_set = set([FailureCrash(), FailureCrash()])
+ self.assertEqual(FailureCrash(self._actual_output, self._expected_output),
+ FailureCrash(self._actual_output, self._expected_output))
+ self.assertNotEqual(FailureCrash(self._actual_output, self._expected_output),
+ FailureTimeout(self._actual_output, self._expected_output))
+ crash_set = set([FailureCrash(self._actual_output, self._expected_output),
+ FailureCrash(self._actual_output, self._expected_output)])
self.assertEqual(len(crash_set), 1)
# The hash happens to be the name of the class, but sets still work:
- crash_set = set([FailureCrash(), 'FailureCrash'])
+ crash_set = set([FailureCrash(self._actual_output, self._expected_output),
+ 'FailureCrash'])
self.assertEqual(len(crash_set), 2)
def test_crashes(self):
- self.assertEqual(FailureCrash().message(), 'content_shell crashed')
- self.assertEqual(FailureCrash(process_name='foo', pid=1234).message(), 'foo crashed [pid=1234]')
+ self.assertEqual(
+ FailureCrash(self._actual_output, self._expected_output).message(),
+ 'content_shell crashed')
+ self.assertEqual(
+ FailureCrash(self._actual_output, self._expected_output,
+ process_name='foo', pid=1234).message(),
+ 'foo crashed [pid=1234]')
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_input.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
index bf8af1918ee..cfec6f88efa 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_input.py
@@ -31,7 +31,8 @@
class TestInput(object):
"""Groups information about a test for easy passing of data."""
- def __init__(self, test_name, timeout_ms=None, requires_lock=None, reference_files=None):
+ def __init__(self, test_name, timeout_ms=None, requires_lock=None,
+ reference_files=None, retry_attempt=0, requires_force_overwrite=False):
# TestInput objects are normally constructed by the manager and passed
# to the workers, but these some fields are set lazily in the workers
# where possible, because they require us to look at the filesystem,
@@ -40,11 +41,15 @@ class TestInput(object):
self.timeout_ms = timeout_ms
self.requires_lock = requires_lock
self.reference_files = reference_files
+ self.retry_attempt = retry_attempt
+ self.requires_force_overwrite = requires_force_overwrite
def __repr__(self):
return (
- "TestInput('%s', timeout_ms=%s, requires_lock=%s, reference_files=%s)" % (
+ "TestInput('%s', timeout_ms=%s, requires_lock=%s, reference_files=%s, retry_attempt=%d, requires_force_overwrite=%s)" % (
self.test_name,
self.timeout_ms,
self.requires_lock,
- self.reference_files))
+ self.reference_files,
+ self.retry_attempt,
+ self.requires_force_overwrite))
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
index 8c83576888e..9eb88954ac0 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results.py
@@ -30,27 +30,51 @@ import cPickle
from blinkpy.web_tests.models import test_failures
+from blinkpy.common import path_finder
+
+path_finder.add_typ_dir_to_sys_path()
+
+from typ.artifacts import Artifacts
+
+def build_test_result(
+ driver_output, test_name, retry_attempt=0,
+ failures=None, test_run_time=None, reftest_type=None,
+ pid=None, references=None, device_failed=False, crash_site=None):
+ failures = failures or []
+ if not failures and driver_output.error:
+ failures.append(test_failures.PassWithStderr(driver_output))
+ return TestResult(
+ test_name, retry_attempt=retry_attempt,
+ failures=failures, test_run_time=test_run_time,
+ reftest_type=reftest_type, pid=pid, references=references,
+ device_failed=device_failed, crash_site=crash_site)
+
class TestResult(object):
"""Data object containing the results of a single test."""
+ repeat_tests = True
+ results_directory = ''
+ filesystem = None
@staticmethod
def loads(string):
return cPickle.loads(string)
- def __init__(self, test_name, failures=None, test_run_time=None, has_stderr=False, reftest_type=None,
- pid=None, references=None, device_failed=False, has_repaint_overlay=False, crash_site=None):
+ def __init__(self, test_name, retry_attempt=0, failures=None,
+ test_run_time=None, reftest_type=None,
+ pid=None, references=None, device_failed=False, crash_site=None):
self.test_name = test_name
self.failures = failures or []
self.test_run_time = test_run_time or 0 # The time taken to execute the test itself.
- self.has_stderr = has_stderr
+ self.has_stderr = any(failure.has_stderr for failure in self.failures)
self.reftest_type = reftest_type or []
self.pid = pid
self.references = references or []
self.device_failed = device_failed
- self.has_repaint_overlay = has_repaint_overlay
+ self.has_repaint_overlay = any(
+ failure.has_repaint_overlay for failure in self.failures)
self.crash_site = crash_site
-
+ self.retry_attempt = retry_attempt
# FIXME: Setting this in the constructor makes this class hard to mutate.
self.type = test_failures.determine_result_type(failures)
@@ -59,11 +83,20 @@ class TestResult(object):
self.shard_name = ''
self.total_run_time = 0 # The time taken to run the test plus any references, compute diffs, etc.
self.test_number = None
+ self.artifacts = Artifacts(
+ self.results_directory, self.filesystem, retry_attempt,
+ repeat_tests=self.repeat_tests)
+
+ def create_artifacts(self):
+ for failure in self.failures:
+ failure.create_artifacts(self.artifacts)
def __eq__(self, other):
return (self.test_name == other.test_name and
self.failures == other.failures and
- self.test_run_time == other.test_run_time)
+ self.test_run_time == other.test_run_time and
+ self.retry_attempt == other.retry_attempt and
+ self.results_directory == other.results_directory)
def __ne__(self, other):
return not (self == other)
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results_unittest.py b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results_unittest.py
index 7d90a66135d..72bab66d9ee 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results_unittest.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/models/test_results_unittest.py
@@ -29,6 +29,8 @@
import unittest
from blinkpy.web_tests.models.test_results import TestResult
+from blinkpy.web_tests.port.driver import DriverOutput
+from blinkpy.web_tests.models import test_failures
class TestResultsTest(unittest.TestCase):
@@ -51,3 +53,16 @@ class TestResultsTest(unittest.TestCase):
# Also check that != is implemented.
self.assertFalse(new_result != result)
+
+ def test_results_has_stderr(self):
+ driver_output = DriverOutput(None, None, None, None, error='error')
+ failures = [test_failures.FailureCrash(driver_output, None)]
+ result = TestResult('foo', failures=failures)
+ self.assertTrue(result.has_stderr)
+
+ def test_results_has_repaint_overlay(self):
+ driver_output = DriverOutput(
+ '"paintInvalidations": [', None, None, None)
+ failures = [test_failures.FailureTextMismatch(driver_output, None)]
+ result = TestResult('foo', failures=failures)
+ self.assertTrue(result.has_repaint_overlay)
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 9ad7bcc2f4b..1bec908e787 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
@@ -337,6 +337,11 @@ def summarize_results(port_obj, expectations, initial_results,
if is_unexpected:
test_dict.update(_interpret_test_failures(retry_result.failures))
+ for test_result, _ in merged_results:
+ for artifact_name, artifacts in test_result.artifacts.artifacts.items():
+ artifact_dict = test_dict.setdefault('artifacts', {})
+ artifact_dict.setdefault(artifact_name, []).extend(artifacts)
+
# Store test hierarchically by directory. e.g.
# foo/bar/baz.html: test_dict
# foo/bar/baz1.html: test_dict
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 b021a3f4102..c7b4805dec1 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
@@ -33,22 +33,23 @@ from blinkpy.web_tests.models import test_expectations
from blinkpy.web_tests.models import test_failures
from blinkpy.web_tests.models import test_results
from blinkpy.web_tests.models import test_run_results
-
+from blinkpy.web_tests.port.driver import DriverOutput
def get_result(test_name, result_type=test_expectations.PASS, run_time=0):
failures = []
+ dummy_1, dummy_2 = DriverOutput(None, None, None, None), DriverOutput(None, None, None, None)
if result_type == test_expectations.TIMEOUT:
- failures = [test_failures.FailureTimeout()]
+ failures = [test_failures.FailureTimeout(dummy_1)]
elif result_type == test_expectations.AUDIO:
- failures = [test_failures.FailureAudioMismatch()]
+ failures = [test_failures.FailureAudioMismatch(dummy_1, dummy_2)]
elif result_type == test_expectations.TEXT:
- failures = [test_failures.FailureTextMismatch()]
+ failures = [test_failures.FailureTextMismatch(dummy_1, dummy_2)]
elif result_type == test_expectations.IMAGE:
- failures = [test_failures.FailureImageHashMismatch()]
+ failures = [test_failures.FailureImageHashMismatch(dummy_1, dummy_2)]
elif result_type == test_expectations.CRASH:
- failures = [test_failures.FailureCrash()]
+ failures = [test_failures.FailureCrash(dummy_1)]
elif result_type == test_expectations.LEAK:
- failures = [test_failures.FailureLeak()]
+ failures = [test_failures.FailureLeak(dummy_1)]
return test_results.TestResult(test_name, failures=failures, test_run_time=run_time)
@@ -165,22 +166,34 @@ class InterpretTestFailuresTest(unittest.TestCase):
def setUp(self):
host = MockHost()
self.port = host.port_factory.get(port_name='test')
+ self._actual_output = DriverOutput(None, None, None, None)
+ self._expected_output = DriverOutput(None, None, None, None)
def test_interpret_test_failures(self):
test_dict = test_run_results._interpret_test_failures(
- [test_failures.FailureReftestMismatchDidNotOccur(self.port.abspath_for_test('foo/reftest-expected-mismatch.html'))])
+ [test_failures.FailureReftestMismatchDidNotOccur(
+ self._actual_output, self._expected_output,
+ self.port.abspath_for_test('foo/reftest-expected-mismatch.html'))])
self.assertEqual(len(test_dict), 0)
- test_dict = test_run_results._interpret_test_failures([test_failures.FailureMissingAudio()])
+ test_dict = test_run_results._interpret_test_failures(
+ [test_failures.FailureMissingAudio(
+ self._actual_output, self._expected_output)])
self.assertIn('is_missing_audio', test_dict)
- test_dict = test_run_results._interpret_test_failures([test_failures.FailureMissingResult()])
+ test_dict = test_run_results._interpret_test_failures(
+ [test_failures.FailureMissingResult(
+ self._actual_output, self._expected_output)])
self.assertIn('is_missing_text', test_dict)
- test_dict = test_run_results._interpret_test_failures([test_failures.FailureMissingImage()])
+ test_dict = test_run_results._interpret_test_failures(
+ [test_failures.FailureMissingImage(
+ self._actual_output, self._expected_output)])
self.assertIn('is_missing_image', test_dict)
- test_dict = test_run_results._interpret_test_failures([test_failures.FailureMissingImageHash()])
+ test_dict = test_run_results._interpret_test_failures(
+ [test_failures.FailureMissingImageHash(
+ self._actual_output, self._expected_output)])
self.assertIn('is_missing_image', test_dict)
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 07f0dc837c9..3f28ee31c45 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
@@ -129,6 +129,9 @@ class Port(object):
('mac10.11', 'x86'),
('mac10.12', 'x86'),
('mac10.13', 'x86'),
+ ('mac10.14', 'x86'),
+ ('mac10.15', 'x86'),
+
('win7', 'x86'),
('win10', 'x86'),
('trusty', 'x86_64'),
@@ -140,6 +143,10 @@ class Port(object):
)
CONFIGURATION_SPECIFIER_MACROS = {
+ # NOTE: We don't support specifiers for mac10.14 or mac10.15 because
+ # we don't have separate baselines for them (they share the mac10.13
+ # results in the platform/mac directory). This list will need to be
+ # updated if/when we actually have separate baselines.
'mac': ['retina', 'mac10.10', 'mac10.11', 'mac10.12', 'mac10.13'],
'win': ['win7', 'win10'],
'linux': ['trusty'],
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py b/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
index 4cdaa786864..505af530cdb 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/port/browser_test_driver.py
@@ -79,7 +79,7 @@ class BrowserTestDriver(Driver):
cmd.append(self._port._path_to_driver())
cmd.append('--gtest_filter=PrintPreviewPdfGeneratedBrowserTest.MANUAL_LayoutTestDriver')
cmd.append('--run-manual')
- cmd.append('--single_process')
+ cmd.append('--single-process-tests')
cmd.extend(per_test_args)
cmd.extend(self._port.get_option('additional_driver_flag', []))
return cmd
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 2ee5bfbbb31..d1b67bdd2f6 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
@@ -60,6 +60,8 @@ def _import_fuchsia_runner():
# pylint: disable=import-error
# pylint: disable=invalid-name
# pylint: disable=redefined-outer-name
+ global aemu_target
+ import aemu_target
global fuchsia_target
import target as fuchsia_target
global qemu_target
@@ -123,12 +125,20 @@ class SubprocessOutputLogger(object):
self._process.kill()
class _TargetHost(object):
- def __init__(self, build_path, ports_to_forward):
+ def __init__(self, build_path, ports_to_forward, target_device):
try:
self._target = None
- self._target = qemu_target.QemuTarget(
- build_path, 'x64', cpu_cores=CPU_CORES, system_log_file=None,
- require_kvm=True, ram_size_mb=8192)
+ target_args = { 'output_dir':build_path,
+ 'target_cpu':'x64',
+ 'system_log_file':None,
+ 'cpu_cores':CPU_CORES,
+ 'require_kvm':True,
+ 'emu_type':target_device,
+ 'ram_size_mb':8192}
+ if target_device == 'qemu':
+ self._target = qemu_target.QemuTarget(**target_args)
+ else:
+ self._target = aemu_target.AemuTarget(**target_args)
self._target.Start()
self._setup_target(build_path, ports_to_forward)
except:
@@ -150,8 +160,7 @@ class _TargetHost(object):
stderr=subprocess.PIPE)
package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH)
- self._target.InstallPackage(package_path, "content_shell",
- package_deps=[])
+ self._target.InstallPackage([package_path])
# Process will be forked for each worker, which may make QemuTarget
# unusable (e.g. waitpid() for qemu process returns ECHILD after
@@ -185,6 +194,7 @@ class FuchsiaPort(base.Port):
self._operating_system = 'fuchsia'
self._version = 'fuchsia'
+ self._target_device = self.get_option('device')
# TODO(sergeyu): Add support for arm64.
self._architecture = 'x86_64'
@@ -212,7 +222,7 @@ class FuchsiaPort(base.Port):
super(FuchsiaPort, self).setup_test_run()
try:
self._target_host = _TargetHost(
- self._build_path(), self.SERVER_PORTS)
+ self._build_path(), self.SERVER_PORTS, self._target_device)
if self.get_option('zircon_logging'):
self._zircon_logger = SubprocessOutputLogger(
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 2fa55f6cdc9..fdcc94ffe7c 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
@@ -95,10 +95,10 @@ class TestList(object):
actual_text=None, expected_text=None, expected_image=None)
def add_reftest(self, name, reference_name, same_image=True,
- actual_text=None, expected_text=None, crash=False):
+ actual_text=None, expected_text=None, crash=False, error=''):
self.add(name, actual_checksum='checksum', actual_image='IMAGE', expected_image=None,
actual_text=actual_text, expected_text=expected_text,
- crash=crash)
+ crash=crash, error=error)
if same_image:
self.add_reference(reference_name)
else:
@@ -116,14 +116,14 @@ class TestList(object):
#
# These numbers may need to be updated whenever we add or delete tests. This includes virtual tests.
#
-TOTAL_TESTS = 127
+TOTAL_TESTS = 151
TOTAL_WONTFIX = 3
TOTAL_SKIPS = 20 + TOTAL_WONTFIX
-TOTAL_CRASHES = 76
+TOTAL_CRASHES = 78
UNEXPECTED_PASSES = 1
-UNEXPECTED_NON_VIRTUAL_FAILURES = 21
-UNEXPECTED_FAILURES = 44
+UNEXPECTED_NON_VIRTUAL_FAILURES = 33
+UNEXPECTED_FAILURES = 65
def unit_test_list():
@@ -144,6 +144,37 @@ def unit_test_list():
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/unexpected/text-mismatch-overlay.html',
+ actual_text='"paintInvalidations": [\nfail',
+ expected_text='"paintInvalidations": [\npass')
+ tests.add('failures/unexpected/no-text-baseline.html',
+ actual_text='"paintInvalidations": [\nfail', expected_text=None)
+ tests.add('failures/unexpected/no-text-generated.html',
+ actual_text=None, expected_text='"paintInvalidations": [\npass')
tests.add('failures/expected/keyboard.html', keyboard=True)
tests.add('failures/expected/newlines_leading.html',
expected_text='\nfoo\n', actual_text='foo\n')
@@ -167,6 +198,8 @@ layer at (0,0) size 800x34
text run at (0,0) width 133: "This is an image test!"
""", expected_text=None)
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,
@@ -238,6 +271,9 @@ layer at (0,0) size 800x34
tests.add_reftest('failures/expected/mismatch.html', 'failures/expected/mismatch-expected-mismatch.html')
tests.add_reftest('failures/unexpected/crash-reftest.html', 'failures/unexpected/crash-reftest-expected.html', crash=True)
tests.add_reftest('failures/unexpected/reftest.html', 'failures/unexpected/reftest-expected.html', same_image=False)
+ tests.add_reftest('failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr.html',
+ 'failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr-expected.html',
+ same_image=False, actual_text='actual', expected_text='expected', error='oops')
tests.add_reftest('failures/unexpected/mismatch.html', 'failures/unexpected/mismatch-expected-mismatch.html')
tests.add('failures/unexpected/reftest-nopixel.html', actual_checksum=None, actual_image=None, expected_image=None)
tests.add('failures/unexpected/reftest-nopixel-expected.html', actual_checksum=None, actual_image=None)
@@ -419,6 +455,26 @@ class TestPort(Port):
'linux': ['precise', 'trusty']
}
+ def look_for_new_samples(self, crashed_processes, start_time):
+ del start_time
+ sample_files = {}
+ for cp in crashed_processes:
+ if cp[0].endswith('crash-with-sample.html'):
+ sample_file = cp[0].replace('.html', '_sample.txt')
+ self._filesystem.maybe_make_directory(
+ self._filesystem.dirname(sample_file))
+ self._filesystem.write_binary_file(sample_file, 'crash sample file')
+ sample_files[cp[0]] = sample_file
+ return sample_files
+
+ def look_for_new_crash_logs(self, crashed_processes, start_time):
+ del start_time
+ crash_logs = {}
+ for cp in crashed_processes:
+ if cp[0].endswith('-with-delayed-log.html'):
+ crash_logs[cp[0]] = ('delayed crash log', '/tmp')
+ return crash_logs
+
def _path_to_driver(self, target=None):
# This routine shouldn't normally be called, but it is called by
# the mock_drt Driver. We return something, but make sure it's useless.
@@ -560,6 +616,7 @@ class TestDriver(Driver):
actual_text = test.actual_text
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)
@@ -590,24 +647,30 @@ class TestDriver(Driver):
audio = base64.b64decode(test.actual_audio)
crashed_process_name = None
crashed_pid = None
+
+ leak_log = ''
+ if leak:
+ leak_log = 'leak detected'
+
+ crash_log = ''
if crash:
crashed_process_name = self._port.driver_name()
crashed_pid = 1
+ crash_log = 'crash log'
elif web_process_crash:
crashed_process_name = 'WebProcess'
crashed_pid = 2
+ crash_log = 'web process crash log'
- crash_log = ''
if crashed_process_name:
crash_logs = CrashLogs(self._port.host)
- crash_log = crash_logs.find_newest_log(crashed_process_name, None) or ''
+ crash_log = crash_logs.find_newest_log(crashed_process_name, None) or crash_log
if 'crash-reftest.html' in test_name:
crashed_process_name = self._port.driver_name()
crashed_pid = 3
crash = True
crash_log = 'reftest crash log'
-
if test.actual_checksum == driver_input.image_hash:
image = None
else:
@@ -616,7 +679,7 @@ class TestDriver(Driver):
crash=(crash or web_process_crash), crashed_process_name=crashed_process_name,
crashed_pid=crashed_pid, crash_log=crash_log,
test_time=time.time() - start_time, timeout=test.timeout, error=test.error, pid=self.pid,
- leak=test.leak)
+ leak=test.leak, leak_log=leak_log)
def stop(self, timeout_secs=0.0):
self.started = False
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 b2215640b9c..e8e21735868 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
@@ -143,6 +143,11 @@ def parse_args(args):
action='store_false',
default=True,
help=('Do not log Zircon debug messages.')),
+ optparse.make_option(
+ '--device',
+ choices=['aemu','qemu'],
+ default='qemu',
+ help=('Choose device to launch Fuchsia with.')),
]))
option_group_definitions.append(
@@ -438,9 +443,10 @@ def parse_args(args):
help='read list of tests to run from file'),
optparse.make_option(
'--isolated-script-test-filter',
+ action='append',
type='string',
- help='A list of tests to run separated by TWO colons, e.g. fast::css/test.html, '
- 'same as listing them as positional arguments'),
+ help='A list of test globs to run or skip, separated by TWO colons, e.g. fast::css/test.html; '
+ 'prefix the glob with "-" to skip it'),
# TODO(crbug.com/893235): Remove gtest_filter when FindIt no longer uses it.
optparse.make_option(
'--gtest_filter',
@@ -594,9 +600,6 @@ def _set_up_derived_options(port, options, args):
if not options.skipped:
options.skipped = 'default'
- if options.isolated_script_test_filter:
- args.extend(options.isolated_script_test_filter.split('::'))
-
if options.gtest_filter:
args.extend(options.gtest_filter.split(':'))
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 5e779d16be8..90df72d6a86 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
@@ -485,15 +485,127 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
def test_stderr_is_saved(self):
host = MockHost()
self.assertTrue(passing_run(host=host))
- self.assertEqual(host.filesystem.read_text_file('/tmp/layout-test-results/passes/error-stderr.txt'),
- 'stuff going to stderr')
+ self.assertEqual(
+ host.filesystem.read_text_file('/tmp/layout-test-results/passes/error-stderr.txt'),
+ 'stuff going to stderr')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['passes']['error.html']
+ self.assertEqual(test_results['artifacts']['stderr'], ['passes/error-stderr.txt'])
+
+ def test_crash_log_is_saved(self):
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash.html', '--num-retries', '1'],
+ tests_included=True, host=host))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ self.assertEqual(
+ host.filesystem.read_text_file(
+ '/tmp/layout-test-results/failures/unexpected/crash-crash-log.txt'),
+ 'crash log')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash.html']
+ self.assertEqual(test_results['artifacts']['crash_log'], [
+ 'failures/unexpected/crash-crash-log.txt',
+ 'retry_1/failures/unexpected/crash-crash-log.txt'])
+
+ def test_crash_log_is_saved_after_delay(self):
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash-with-delayed-log.html',
+ '--num-retries', '1'],
+ tests_included=True, host=host))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ self.assertEqual(
+ host.filesystem.read_text_file(
+ '/tmp/layout-test-results/failures/unexpected/crash-with-delayed-log-crash-log.txt'),
+ 'delayed crash log')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash-with-delayed-log.html']
+ self.assertEqual(test_results['artifacts']['crash_log'], [
+ 'failures/unexpected/crash-with-delayed-log-crash-log.txt',
+ 'retry_1/failures/unexpected/crash-with-delayed-log-crash-log.txt'])
+
+ def test_reftest_mismatch_with_text_mismatch_only_writes_stderr_once(self):
+ # test that there is no exception when two failure types, FailureTextMismatch and
+ # FailureReftestMismatch both have the same stderr to print out.
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/reftest-mismatch-with-text-mismatch-with-stderr.html',],
+ tests_included=True, host=host))
+
+ def test_crash_log_is_saved_after_delay_using_multiple_jobs(self):
+ # TODO(rmhasan): When web_test_runner.run() spawns multiple jobs it uses
+ # the non mock file system. We should figure out how to make all subprocesses
+ # use the mock file system.
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash-with-delayed-log.html',
+ 'passes/args.html', '-j', '2'],
+ tests_included=True, host=host))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash-with-delayed-log.html']
+ self.assertEqual(test_results['artifacts']['crash_log'], [
+ 'failures/unexpected/crash-with-delayed-log-crash-log.txt'])
+
+ def test_crash_sample_file_is_saved(self):
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash-with-sample.html',
+ '--num-retries', '1'],
+ tests_included=True, host=host))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ self.assertEqual(
+ host.filesystem.read_text_file(
+ '/tmp/layout-test-results/failures/unexpected/crash-with-sample-sample.txt'),
+ 'crash sample file')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash-with-sample.html']
+ self.assertEqual(test_results['artifacts']['sample_file'], [
+ 'failures/unexpected/crash-with-sample-sample.txt',
+ 'retry_1/failures/unexpected/crash-with-sample-sample.txt'])
+
+ def test_crash_sample_file_is_saved_multiple_jobs(self):
+ host = MockHost()
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash-with-sample.html',
+ 'passes/image.html', '--num-retries', '1', '-j', '2'],
+ tests_included=True, host=host))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash-with-sample.html']
+ self.assertEqual(test_results['artifacts']['sample_file'], [
+ 'failures/unexpected/crash-with-sample-sample.txt',
+ 'retry_1/failures/unexpected/crash-with-sample-sample.txt'])
def test_reftest_crash_log_is_saved(self):
host = MockHost()
- self.assertTrue(logging_run(['--order', 'natural', 'failures/unexpected/crash-reftest.html'],
- tests_included=True, host=host))
- self.assertEqual(host.filesystem.read_text_file('/tmp/layout-test-results/failures/unexpected/crash-reftest-crash-log.txt'),
- 'reftest crash log')
+ self.assertTrue(logging_run(
+ ['--order', 'natural', 'failures/unexpected/crash-reftest.html', '--num-retries', '1'],
+ tests_included=True, host=host))
+ self.assertEqual(
+ host.filesystem.read_text_file(
+ '/tmp/layout-test-results/failures/unexpected/crash-reftest-crash-log.txt'),
+ 'reftest crash log')
+ self.assertEqual(
+ host.filesystem.read_text_file(
+ '/tmp/layout-test-results/retry_1/failures/unexpected/crash-reftest-crash-log.txt'),
+ 'reftest crash log')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['crash-reftest.html']
+ self.assertEqual(test_results['artifacts']['crash_log'], [
+ 'failures/unexpected/crash-reftest-crash-log.txt',
+ 'retry_1/failures/unexpected/crash-reftest-crash-log.txt'])
def test_test_list(self):
host = MockHost()
@@ -519,7 +631,26 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
['--isolated-script-test-filter=passes/text.html::passes/image.html', 'passes/error.html'],
host=host
)
- self.assertEqual(sorted(tests_run), ['passes/error.html', 'passes/image.html', 'passes/text.html'])
+ self.assertEqual(sorted(tests_run), [])
+
+ tests_run = get_tests_run(
+ ['--isolated-script-test-filter=passes/error.html::passes/image.html', 'passes/error.html'],
+ host=host
+ )
+ self.assertEqual(sorted(tests_run), ['passes/error.html'])
+
+ tests_run = get_tests_run(
+ ['--isolated-script-test-filter=-passes/error.html::passes/image.html'],
+ host=host
+ )
+ self.assertEqual(sorted(tests_run), ['passes/image.html'])
+
+ tests_run = get_tests_run(
+ ['--isolated-script-test-filter=passes/error.html::passes/image.html',
+ '--isolated-script-test-filter=-passes/error.html'],
+ host=host
+ )
+ self.assertEqual(sorted(tests_run), ['passes/image.html'])
def test_gtest_filter(self):
host = MockHost()
@@ -604,8 +735,9 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
self.assertEqual(['passes/text.html'], tests_run)
# Verify that --no-smoke continues to work on a smoke-by-default port.
- tests_run = get_tests_run(['--no-smoke', '--order', 'natural'], host=host, port_obj=port_obj)
- self.assertNotEqual(['passes/text.html'], tests_run)
+ tests_run = get_tests_run(['--no-smoke', 'passes/image.html', '--order', 'natural'],
+ host=host, port_obj=port_obj)
+ self.assertNotIn('passes/text.html', tests_run)
def test_smoke_test_default_retry(self):
host = MockHost()
@@ -613,10 +745,6 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
host.filesystem.write_text_file(
smoke_test_filename, 'failures/unexpected/text-image-checksum.html\n')
- # Retry smoke tests by default.
- _, err, __ = logging_run(['--smoke'], host=host, tests_included=True)
- self.assertIn('Retrying', err.getvalue())
-
# Retry if additional tests are given.
_, err, __ = logging_run(['--smoke', 'passes/image.html'], host=host, tests_included=True)
self.assertIn('Retrying', err.getvalue())
@@ -631,6 +759,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
tests_included=True, host=host)
self.assertEqual(details.exit_code, 2)
results = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ results['tests']['failures']['unexpected']['text-image-checksum.html'].pop('artifacts')
self.assertEqual(
results['tests']['failures']['unexpected']['text-image-checksum.html'],
{
@@ -640,6 +769,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
'is_regression': True,
'text_mismatch': 'general text mismatch',
})
+ results['tests']['failures']['unexpected']['missing_text.html'].pop('artifacts')
self.assertEqual(
results['tests']['failures']['unexpected']['missing_text.html'],
{
@@ -826,9 +956,221 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
def test_retrying_leak_tests(self):
host = MockHost()
- details, err, _ = logging_run(['--num-retries=3', 'failures/unexpected/leak.html'], tests_included=True, host=host)
+ details, err, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/leak.html'],
+ tests_included=True, host=host)
self.assertEqual(details.exit_code, 1)
self.assertIn('Retrying', err.getvalue())
+ self.assertEqual(host.filesystem.read_text_file(
+ '/tmp/layout-test-results/failures/unexpected/leak-leak-log.txt'),
+ 'leak detected')
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['leak.html']
+ self.assertEqual(test_results['artifacts']['leak_log'], [
+ 'failures/unexpected/leak-leak-log.txt',
+ 'retry_1/failures/unexpected/leak-leak-log.txt'])
+
+ def test_unexpected_text_mismatch(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/text-mismatch-overlay.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['text-mismatch-overlay.html']
+ self.assertEqual(test_results['artifacts']['actual_text'], [
+ 'failures/unexpected/text-mismatch-overlay-actual.txt',
+ 'retry_1/failures/unexpected/text-mismatch-overlay-actual.txt'])
+ self.assertEqual(test_results['artifacts']['expected_text'], [
+ 'failures/unexpected/text-mismatch-overlay-expected.txt',
+ 'retry_1/failures/unexpected/text-mismatch-overlay-expected.txt'])
+ self.assertEqual(test_results['artifacts']['text_diff'], [
+ 'failures/unexpected/text-mismatch-overlay-diff.txt',
+ 'retry_1/failures/unexpected/text-mismatch-overlay-diff.txt'])
+ self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+ 'failures/unexpected/text-mismatch-overlay-pretty-diff.html',
+ 'retry_1/failures/unexpected/text-mismatch-overlay-pretty-diff.html'])
+ self.assertEqual(test_results['artifacts']['overlay'], [
+ 'failures/unexpected/text-mismatch-overlay-overlay.html',
+ 'retry_1/failures/unexpected/text-mismatch-overlay-overlay.html'])
+
+ def test_unexpected_no_text_baseline(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-text-baseline.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-text-baseline.html']
+ self.assertEqual(test_results['artifacts']['actual_text'], [
+ 'failures/unexpected/no-text-baseline-actual.txt',
+ 'retry_1/failures/unexpected/no-text-baseline-actual.txt'])
+ self.assertNotIn('expected_text', test_results['artifacts'])
+ self.assertEqual(test_results['artifacts']['text_diff'], [
+ 'failures/unexpected/no-text-baseline-diff.txt',
+ 'retry_1/failures/unexpected/no-text-baseline-diff.txt'])
+ self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+ 'failures/unexpected/no-text-baseline-pretty-diff.html',
+ 'retry_1/failures/unexpected/no-text-baseline-pretty-diff.html'])
+ self.assertNotIn('overlay', test_results['artifacts'])
+
+ def test_unexpected_no_text_generated(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-text-generated.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-text-generated.html']
+ self.assertEqual(test_results['artifacts']['expected_text'], [
+ 'failures/unexpected/no-text-generated-expected.txt',
+ 'retry_1/failures/unexpected/no-text-generated-expected.txt'])
+ self.assertNotIn('actual_text', test_results['artifacts'])
+ self.assertEqual(test_results['artifacts']['text_diff'], [
+ 'failures/unexpected/no-text-generated-diff.txt',
+ 'retry_1/failures/unexpected/no-text-generated-diff.txt'])
+ self.assertEqual(test_results['artifacts']['pretty_text_diff'], [
+ 'failures/unexpected/no-text-generated-pretty-diff.html',
+ 'retry_1/failures/unexpected/no-text-generated-pretty-diff.html'])
+ self.assertNotIn('overlay', test_results['artifacts'])
+
+ def test_reftest_mismatching_image(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/reftest.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['reftest.html']
+ self.assertEqual(test_results['artifacts']['actual_image'], [
+ 'failures/unexpected/reftest-actual.png',
+ 'retry_1/failures/unexpected/reftest-actual.png'])
+ self.assertEqual(test_results['artifacts']['expected_image'], [
+ 'failures/unexpected/reftest-expected.png',
+ 'retry_1/failures/unexpected/reftest-expected.png'])
+ self.assertEqual(test_results['artifacts']['image_diff'], [
+ 'failures/unexpected/reftest-diff.png',
+ 'retry_1/failures/unexpected/reftest-diff.png'])
+ self.assertEqual(test_results['artifacts']['pretty_image_diff'], [
+ 'failures/unexpected/reftest-diffs.html',
+ 'retry_1/failures/unexpected/reftest-diffs.html'])
+ self.assertEqual(test_results['artifacts']['reference_file_mismatch'], [
+ 'failures/unexpected/reftest-expected.html',
+ 'retry_1/failures/unexpected/reftest-expected.html'])
+
+ def test_reftest_failure_matching_image(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['failures/unexpected/mismatch.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['mismatch.html']
+ self.assertIn('reference_file_match', test_results['artifacts'])
+ self.assertEqual(test_results['artifacts']['reference_file_match'],
+ ['failures/unexpected/mismatch-expected-mismatch.html'])
+
+ def test_unexpected_image_mismatch(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/image-mismatch.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['image-mismatch.html']
+ self.assertEqual(test_results['artifacts']['actual_image'], [
+ 'failures/unexpected/image-mismatch-actual.png',
+ 'retry_1/failures/unexpected/image-mismatch-actual.png'])
+ self.assertEqual(test_results['artifacts']['expected_image'], [
+ 'failures/unexpected/image-mismatch-expected.png',
+ 'retry_1/failures/unexpected/image-mismatch-expected.png'])
+ self.assertEqual(test_results['artifacts']['image_diff'], [
+ 'failures/unexpected/image-mismatch-diff.png',
+ 'retry_1/failures/unexpected/image-mismatch-diff.png'])
+ self.assertEqual(test_results['artifacts']['pretty_image_diff'], [
+ 'failures/unexpected/image-mismatch-diffs.html',
+ 'retry_1/failures/unexpected/image-mismatch-diffs.html'])
+
+ def test_unexpected_no_image_generated(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-image-generated.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-image-generated.html']
+ self.assertNotIn('actual_image', test_results['artifacts'])
+ self.assertEqual(test_results['artifacts']['expected_image'], [
+ 'failures/unexpected/no-image-generated-expected.png',
+ 'retry_1/failures/unexpected/no-image-generated-expected.png'])
+ self.assertNotIn('image_diff', test_results['artifacts'])
+ self.assertNotIn('pretty_image_diff', test_results['artifacts'])
+
+ def test_unexpected_no_image_baseline(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-image-baseline.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-image-baseline.html']
+ self.assertNotIn('expected_image', test_results['artifacts'])
+ self.assertEqual(test_results['artifacts']['actual_image'], [
+ 'failures/unexpected/no-image-baseline-actual.png',
+ 'retry_1/failures/unexpected/no-image-baseline-actual.png'])
+ self.assertNotIn('image_diff', test_results['artifacts'])
+ self.assertNotIn('pretty_image_diff', test_results['artifacts'])
+
+ def test_unexpected_audio_mismatch(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/audio-mismatch.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['audio-mismatch.html']
+ self.assertEqual(test_results['artifacts']['actual_audio'], [
+ 'failures/unexpected/audio-mismatch-actual.wav',
+ 'retry_1/failures/unexpected/audio-mismatch-actual.wav'])
+ self.assertEqual(test_results['artifacts']['expected_audio'], [
+ 'failures/unexpected/audio-mismatch-expected.wav',
+ 'retry_1/failures/unexpected/audio-mismatch-expected.wav'])
+
+ def test_unexpected_audio_missing_baseline(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-audio-baseline.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-audio-baseline.html']
+ self.assertEqual(test_results['artifacts']['actual_audio'], [
+ 'failures/unexpected/no-audio-baseline-actual.wav',
+ 'retry_1/failures/unexpected/no-audio-baseline-actual.wav'])
+
+ def test_unexpected_no_audio_generated(self):
+ host = MockHost()
+ details, _, _ = logging_run(
+ ['--num-retries=1', 'failures/unexpected/no-audio-generated.html'],
+ tests_included=True, host=host)
+ self.assertEqual(details.exit_code, 1)
+ results = json.loads(
+ host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+ test_results = results['tests']['failures']['unexpected']['no-audio-generated.html']
+ self.assertEqual(test_results['artifacts']['expected_audio'], [
+ 'failures/unexpected/no-audio-generated-expected.wav',
+ 'retry_1/failures/unexpected/no-audio-generated-expected.wav'])
def test_retrying_uses_retry_directories(self):
host = MockHost()
@@ -990,8 +1332,8 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
test_result = run_details.initial_results.all_results[0]
self.assertEqual(test_result.test_name, test_name)
self.assertEqual(len(test_result.failures), 2)
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureTextMismatch, test_result.failures))
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureTextNotGenerated, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
self.assert_contains(log_stream, 'Please remove %s' % extra_txt)
self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
@@ -1023,7 +1365,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
test_result = run_details.initial_results.all_results[0]
self.assertEqual(test_result.test_name, test_name)
self.assertEqual(len(test_result.failures), 1)
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
# For now extra png baseline is only reported in an error message.
self.assert_contains(log_stream, 'Please remove %s' % extra_png)
self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
@@ -1041,7 +1383,7 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
test_result = run_details.initial_results.all_results[0]
self.assertEqual(test_result.test_name, test_name)
self.assertEqual(len(test_result.failures), 1)
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
# For now extra png baseline is only reported in an error message.
self.assert_contains(log_stream, 'Please remove %s' % extra_png)
self.assert_contains(log_stream, 'Please remove %s' % extra_wav)
@@ -1073,8 +1415,8 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
test_result = run_details.initial_results.all_results[0]
self.assertEqual(test_result.test_name, test_name)
self.assertEqual(len(test_result.failures), 2)
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureImageHashMismatch, test_result.failures))
- self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioMismatch, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureImageHashNotGenerated, test_result.failures))
+ self.assertTrue(test_failures.has_failure_type(test_failures.FailureAudioNotGenerated, test_result.failures))
# For now extra txt baseline for all-pass testharness test is only reported in an error message.
self.assert_contains(log_stream, 'Please remove %s' % extra_png)
self.assert_contains(log_stream, 'Please remove %s' % extra_txt)
@@ -1219,7 +1561,6 @@ class RunTest(unittest.TestCase, StreamTestingMixin):
self.assertEqual(json.loads(json_failing_test_results), details.summarized_failing_results)
def test_no_default_expectations(self):
- self.assertTrue(passing_run(['failures/expected/text.html']))
self.assertFalse(passing_run(['--ignore-default-expectations', 'failures/expected/text.html']))
diff --git a/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py b/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
index 9910eec2f31..0060996bcf5 100644
--- a/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
+++ b/chromium/third_party/blink/tools/blinkpy/web_tests/try_flag.py
@@ -117,7 +117,7 @@ class TryFlag(object):
def update(self):
self._host.print_('Fetching results...')
# TODO: Get jobs from the _tryflag branch. Current branch for now.
- jobs = self._git_cl.latest_try_jobs(BUILDER_CONFIGS.keys())
+ jobs = self._git_cl.latest_try_jobs(builder_names=BUILDER_CONFIGS.keys())
buildbot = self._host.buildbot
for build in sorted(jobs):
self._host.print_('-- %s: %s/results.html' % (
diff --git a/chromium/third_party/blink/tools/lldb/lldb_blink.py b/chromium/third_party/blink/tools/lldb/lldb_blink.py
index 1c263f07bd1..121b1827bbc 100644
--- a/chromium/third_party/blink/tools/lldb/lldb_blink.py
+++ b/chromium/third_party/blink/tools/lldb/lldb_blink.py
@@ -142,22 +142,30 @@ class WTFStringImplProvider:
def get_length(self):
return self.valobj.GetChildMemberWithName('length_').GetValueAsUnsigned(0)
- def get_data8(self):
- # FIXME: This should be the equivalent of reinterpret_cast<LChar*>(self.valobj + 1)
- return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data8')
-
- def get_data16(self):
- # FIXME: This should be the equivalent of reinterpret_cast<UChar*>(self.valobj + 1)
- return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data16')
-
def to_string(self):
+ val_type = self.valobj.GetType()
+ process = self.valobj.GetProcess()
+ endianness = process.GetByteOrder()
+ pointer_size = process.GetAddressByteSize()
+ offset = val_type.GetPointeeType().GetByteSize()
+
+ char_start = self.valobj.GetValueAsUnsigned(0) + offset
+ pointer = lldb.SBData.CreateDataFromUInt64Array(endianness, pointer_size, [char_start])
error = lldb.SBError()
if self.is_8bit():
- return lstring_to_string(self.get_data8(), error, self.get_length())
- return ustring_to_string(self.get_data16(), error, self.get_length())
+ return lstring_to_string(
+ self.valobj.CreateValueFromData(
+ 'str_impl', pointer,
+ val_type.GetBasicType(lldb.eBasicTypeChar).GetPointerType()),
+ error, self.get_length())
+ return ustring_to_string(
+ self.valobj.CreateValueFromData(
+ 'str_impl', pointer,
+ val_type.GetBasicType(lldb.eBasicTypeUnsignedChar).GetPointerType()),
+ error, self.get_length())
def is_8bit(self):
- return self.valobj.GetChildMemberWithName('is_8bit_')
+ return self.valobj.GetChildMemberWithName('is_8bit_').GetValueAsUnsigned(0)
class WTFStringProvider: